summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 15:28:34 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 13:54:51 +0000
commit2a19c63448c84c1805fb1a585c3651318bb86ca7 (patch)
treeeb17888e8531aa6ee5e85721bd553b832a7e5156 /chromium/third_party/blink/renderer
parentb014812705fc80bff0a5c120dfcef88f349816dc (diff)
downloadqtwebengine-chromium-2a19c63448c84c1805fb1a585c3651318bb86ca7.tar.gz
BASELINE: Update Chromium to 69.0.3497.70
Change-Id: I2b7b56e4e7a8b26656930def0d4575dc32b900a0 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer')
-rw-r--r--chromium/third_party/blink/renderer/BUILD.gn12
-rw-r--r--chromium/third_party/blink/renderer/DEPS5
-rw-r--r--chromium/third_party/blink/renderer/README.md37
-rw-r--r--chromium/third_party/blink/renderer/bindings/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.md17
-rw-r--r--chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt1
-rw-r--r--chromium/third_party/blink/renderer/bindings/IDLUnionTypes.md2
-rw-r--r--chromium/third_party/blink/renderer/bindings/bindings.gni7
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h24
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/activity_logger_test.cc13
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/binding_security.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/binding_security_test.cc18
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_custom_xpath_ns_resolver.cc1
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_custom_xpath_ns_resolver.h2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_element_custom.cc5
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_message_event_custom.cc1
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_promise_rejection_event_custom.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_shadow_root_custom.cc4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_window_custom.cc67
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_xml_http_request_custom.cc3
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/dictionary.h2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/dictionary_helper_for_core.cc5
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/exception_messages.cc186
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/exception_messages.h184
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/exception_state.cc228
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/exception_state.h228
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/generated_code_helper.cc31
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/generated_code_helper.h12
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/iterable.h2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc26
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/local_window_proxy.h4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h1
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/referrer_script_info.cc14
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/referrer_script_info.h19
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/referrer_script_info_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/rejected_promises.cc41
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/rejected_promises.h5
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc22
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/scheduled_action.h6
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_controller.cc77
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_controller.h8
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc51
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.h4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition_builder.cc11
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition_builder.h2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_event_listener.h4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_function.cc4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_function.h6
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_iterator.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_module.cc6
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_module.h8
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_module_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_promise.cc15
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_promise.h8
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property.h2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_base.h10
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc9
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h11
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_test.cc23
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_promise_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_regexp.cc3
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_source_code.cc20
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_source_code.h12
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_streamer.cc31
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_streamer.h2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc30
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_streamer_thread.cc1
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_streamer_thread.h2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_value.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_value.h8
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_wrappable_marking_visitor_test.cc24
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/script_wrappable_visitor_test.cc115
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc104
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h18
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_threaded_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc30
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h10
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc41
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.h7
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/source_location.h1
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc3
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.cc6
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.h2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.cc23
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.h13
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.cc17
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h27
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.cc16
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h13
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc330
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_code_cache.h72
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_context_snapshot.cc5
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc27
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.h14
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_error_handler.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_event_listener.cc4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.cc33
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_gc_for_context_dispose.cc14
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_html_constructor.cc5
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_idle_task_runner.h9
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc74
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_delegate.cc6
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_delegate.h1
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_lazy_event_listener.cc4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder.h4
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_object_parser.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc343
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner.h69
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner_test.cc48
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_string_resource.h6
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.cc40
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h25
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.cc18
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.h3
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc26
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/v8_worker_or_worklet_event_listener.cc2
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/window_proxy.h3
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc34
-rw-r--r--chromium/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h6
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/BUILD.gn8
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/custom/v8_extendable_message_event_custom.cc1
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/generated.gni2
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h8
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc6
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.h2
-rw-r--r--chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc14
-rwxr-xr-xchromium/third_party/blink/renderer/bindings/scripts/generate_origin_trial_features.py5
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/utilities.py10
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_attributes.py11
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_callback_function.py4
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_callback_interface.py2
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_dictionary.py28
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_interface.py13
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_methods.py4
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_types.py10
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_union.py3
-rw-r--r--chromium/third_party/blink/renderer/bindings/scripts/v8_utilities.py2
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/attributes.cpp.tmpl19
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl22
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/callback_function.h.tmpl9
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/callback_interface.cpp.tmpl22
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/callback_interface.h.tmpl11
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/constants.cpp.tmpl2
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/dictionary_impl.cpp.tmpl4
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/dictionary_impl.h.tmpl2
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/dictionary_impl_common.cpp.tmpl6
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/dictionary_v8.cpp.tmpl6
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/interface.cpp.tmpl31
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/interface.h.tmpl2
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/interface_base.cpp.tmpl34
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/methods.cpp.tmpl9
-rw-r--r--chromium/third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl6
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/blinkbuild/PRESUBMIT.py26
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter.py74
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter_test.py34
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/core/css/css_properties.py57
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/core/css/make_css_value_keywords.py8
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/core/css/make_media_features.py5
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/core/css/make_style_shorthands.py2
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/core/css/parser/make_atrule_names.py8
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/core/css/parser/templates/at_rule_descriptors.cc.tmpl12
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/core/css/parser/templates/at_rule_descriptors.h.tmpl2
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_base.py5
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_subclasses.py30
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property.h.tmpl1
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_subclass.cc.tmpl144
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_subclass.h.tmpl7
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl539
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/core/css/templates/media_features.h.tmpl2
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.cc.tmpl16
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.h.tmpl2
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/core/style/computed_style_fields.py32
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/json5_generator.py7
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/keyword_utils.py2
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/make_computed_style_base.py36
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/make_css_primitive_value_unit_trie.py2
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/make_css_property_names.py4
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/make_css_value_id_mappings.py20
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/make_element_factory.py2
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/make_element_lookup_trie.py2
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/make_element_type_helpers.py2
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/make_event_factory.py4
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/make_instrumenting_probes.py3
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/make_internal_settings.py2
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/make_names.py5
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/make_origin_trials.py4
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/make_qualified_names.py3
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/make_runtime_features.py17
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/make_settings.py2
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/make_style_builder.py38
-rwxr-xr-xchromium/third_party/blink/renderer/build/scripts/make_web_origin_trials.py32
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/media_feature_symbol.py2
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/name_utilities.py105
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/internal_runtime_flags.h.tmpl2
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/internal_runtime_flags.idl.tmpl4
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/internal_settings_generated.cc.tmpl8
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/internal_settings_generated.h.tmpl2
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/internal_settings_generated.idl.tmpl2
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/make_qualified_names.cc.tmpl2
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/origin_trials.cc.tmpl2
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/origin_trials.h.tmpl2
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/runtime_enabled_features.cc.tmpl10
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/runtime_enabled_features.h.tmpl8
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/settings_macros.h.tmpl8
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/style_builder.cc.tmpl73
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/style_builder_functions.cc.tmpl176
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/style_builder_functions.h.tmpl35
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/templates/web_origin_trials.cc.tmpl27
-rw-r--r--chromium/third_party/blink/renderer/build/scripts/update_css_ranking.py8
-rw-r--r--chromium/third_party/blink/renderer/config.gni7
-rw-r--r--chromium/third_party/blink/renderer/controller/blink_initializer.cc11
-rw-r--r--chromium/third_party/blink/renderer/controller/blink_leak_detector.cc1
-rw-r--r--chromium/third_party/blink/renderer/controller/bloated_renderer_detector.cc12
-rw-r--r--chromium/third_party/blink/renderer/controller/bloated_renderer_detector_test.cc29
-rw-r--r--chromium/third_party/blink/renderer/controller/oom_intervention_impl.cc104
-rw-r--r--chromium/third_party/blink/renderer/controller/oom_intervention_impl.h17
-rw-r--r--chromium/third_party/blink/renderer/controller/oom_intervention_impl_test.cc181
-rw-r--r--chromium/third_party/blink/renderer/core/BUILD.gn85
-rw-r--r--chromium/third_party/blink/renderer/core/DEPS20
-rw-r--r--chromium/third_party/blink/renderer/core/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/BUILD.gn15
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/ax_object_cache.cc171
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/ax_object_cache.h165
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/ax_object_cache_base.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/ax_object_cache_base.h41
-rw-r--r--chromium/third_party/blink/renderer/core/accessibility/axid.h12
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation.h2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_effect.h2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_input_helpers.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_input_helpers_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_sim_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/animation_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/animation/compositor_animations.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/animation/compositor_animations.h21
-rw-r--r--chromium/third_party/blink/renderer/core/animation/compositor_animations_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_animations.cc130
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css/css_animations_test.cc139
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_interpolation_type.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/animation/document_timeline.cc50
-rw-r--r--chromium/third_party/blink/renderer/core/animation/document_timeline.h17
-rw-r--r--chromium/third_party/blink/renderer/core/animation/document_timeline_test.cc66
-rw-r--r--chromium/third_party/blink/renderer/core/animation/effect_input.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/animation/effect_input_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/animation/effect_model.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/effect_stack_test.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/animation/element_animation.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/element_animations.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/animation/element_animations.h2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe_effect.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe_effect.h8
-rw-r--r--chromium/third_party/blink/renderer/core/animation/keyframe_effect_model.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/animation/pending_animations.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline.h5
-rw-r--r--chromium/third_party/blink/renderer/core/animation/scroll_timeline_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/timing_input.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/worklet_animation_base.h2
-rw-r--r--chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.h6
-rw-r--r--chromium/third_party/blink/renderer/core/aom/BUILD.gn16
-rw-r--r--chromium/third_party/blink/renderer/core/aom/accessible_node.cc1196
-rw-r--r--chromium/third_party/blink/renderer/core/aom/accessible_node.h402
-rw-r--r--chromium/third_party/blink/renderer/core/aom/accessible_node.idl (renamed from chromium/third_party/blink/renderer/core/dom/accessible_node.idl)0
-rw-r--r--chromium/third_party/blink/renderer/core/aom/accessible_node_list.cc114
-rw-r--r--chromium/third_party/blink/renderer/core/aom/accessible_node_list.h51
-rw-r--r--chromium/third_party/blink/renderer/core/aom/accessible_node_list.idl (renamed from chromium/third_party/blink/renderer/core/dom/accessible_node_list.idl)0
-rw-r--r--chromium/third_party/blink/renderer/core/aom/computed_accessible_node.cc347
-rw-r--r--chromium/third_party/blink/renderer/core/aom/computed_accessible_node.h112
-rw-r--r--chromium/third_party/blink/renderer/core/aom/computed_accessible_node.idl (renamed from chromium/third_party/blink/renderer/core/dom/computed_accessible_node.idl)0
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/BUILD.gn12
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/clipboard_mime_types.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/clipboard_mime_types.h51
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities.cc88
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities.h50
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities_win.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/data_object.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/data_object_item.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/data_transfer.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/data_transfer_item_list.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/data_transfer_test.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/system_clipboard.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/clipboard/system_clipboard.h4
-rw-r--r--chromium/third_party/blink/renderer/core/core_export.h6
-rw-r--r--chromium/third_party/blink/renderer/core/core_idl_files.gni25
-rw-r--r--chromium/third_party/blink/renderer/core/core_initializer.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/core_initializer.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/BUILD.gn76
-rw-r--r--chromium/third_party/blink/renderer/core/css/CSSProperties.json5592
-rw-r--r--chromium/third_party/blink/renderer/core/css/CSSValueKeywords.json51
-rw-r--r--chromium/third_party/blink/renderer/core/css/OWNERS3
-rw-r--r--chromium/third_party/blink/renderer/core/css/README.md2
-rw-r--r--chromium/third_party/blink/renderer/core/css/computed_style_css_value_mapping.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/css/computed_style_css_value_mapping.h6
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_computed_style_declaration.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_computed_style_declaration.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_font_face_source_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_gradient_value.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_grouping_rule.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_keyframe_rule.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_primitive_value.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_primitive_value_mappings.h37
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_property_value_set.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_rule.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_rule.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_selector.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_selector.h5
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_style_declaration.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_style_declaration.h3
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_style_declaration.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_style_rule.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_style_sheet.cc67
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_style_sheet.h14
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_style_sheet.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_style_sheet_test.cc108
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_syntax_descriptor.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_syntax_descriptor.h23
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_test_helper.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_timing.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_timing.h51
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_value_list.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_variable_data.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/css/css_variable_data.h59
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/computed_style_property_map.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_image_value.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_keyword_value.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_keyword_value.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_invert.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_invert.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_max.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_max.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_min.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_min.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_negate.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_negate.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_product.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_product.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_sum.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_sum.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_math_value.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_matrix_component.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_numeric_array.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_numeric_type.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_perspective.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_perspective.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_position_value.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_position_value.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_rotate.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_rotate.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_scale.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_skew.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_skew.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_skew_x.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_skew_x.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_skew_y.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_skew_y.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_style_value.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_style_value.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_transform_component.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_transform_value.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_transform_value.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_translate.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_translate.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_unit_value.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_unit_value.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_unit_values.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_unparsed_value.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_url_image_value.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/css_variable_reference_value.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/declared_style_property_map.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/element_computed_style_map.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/inline_style_property_map.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map_test.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/style_property_map.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/style_property_map.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/css/cssom/style_value_factory.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/css/document_style_environment_variables.cc104
-rw-r--r--chromium/third_party/blink/renderer/core/css/document_style_environment_variables.h58
-rw-r--r--chromium/third_party/blink/renderer/core/css/document_style_sheet_collection.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face_set.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face_set_document.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/css/font_face_set_document.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/fullscreen.css78
-rw-r--r--chromium/third_party/blink/renderer/core/css/html.css9
-rw-r--r--chromium/third_party/blink/renderer/core/css/invalidation/invalidation_set.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/css/invalidation/invalidation_set.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/invalidation/style_invalidator.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_list.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_list.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/media_query_exp.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_lazy_parsing_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_context.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_fast_paths.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_impl.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_parser_selector.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_property_parser.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc78
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h6
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_proto_converter.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_selector_parser.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_selector_parser_test.cc64
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_tokenizer_test.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_variable_parser.cc80
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/css_variable_parser.h3
-rw-r--r--chromium/third_party/blink/renderer/core/css/parser/font_variant_east_asian_parser.h46
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/computed_style_utils.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc231
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils.h3
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/css_parsing_utils_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/baseline_shift_custom.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/block_size_custom.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/border_block_end_color_custom.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/border_block_end_width_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/border_block_start_color_custom.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/border_block_start_width_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/border_image_source_custom.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/border_inline_end_color_custom.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/border_inline_end_width_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/border_inline_start_color_custom.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/border_inline_start_width_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/caret_color_custom.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/clip_path_custom.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/color_custom.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/content_custom.cc90
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/cursor_custom.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/direction_custom.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/display_custom.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/grid_template_areas_custom.cc50
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/inline_size_custom.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/inset_block_end_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/inset_block_start_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/inset_inline_end_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/inset_inline_start_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/list_style_image_custom.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/margin_block_end_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/margin_block_start_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/margin_inline_end_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/margin_inline_start_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/outline_style_custom.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/padding_block_end_custom.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/padding_block_start_custom.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/padding_inline_end_custom.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/padding_inline_start_custom.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/position_custom.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/resize_custom.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/size_custom.cc94
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/text_align_custom.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/text_indent_custom.cc92
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/text_orientation_custom.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/text_underline_position_custom.cc51
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/variable.cc98
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/variable.h9
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/vertical_align_custom.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_app_region_custom.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_after_color_custom.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_after_width_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_before_color_custom.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_before_width_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_end_color_custom.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_end_width_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_image_custom.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_start_color_custom.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_start_width_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_locale_custom.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_logical_height_custom.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_logical_width_custom.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_margin_after_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_margin_before_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_margin_end_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_margin_start_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_mask_box_image_source_custom.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_max_logical_height_custom.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_max_logical_width_custom.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_min_logical_height_custom.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_min_logical_width_custom.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_padding_after_custom.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_padding_before_custom.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_padding_end_custom.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_padding_start_custom.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_text_emphasis_style_custom.cc59
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_text_orientation_custom.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_writing_mode_custom.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/will_change_custom.cc51
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/word_wrap_custom.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/writing_mode_custom.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/longhands/zoom_custom.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_color_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_custom.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_end_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_start_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_style_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_width_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/border_custom.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_color_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_custom.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_end_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_start_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_style_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_width_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/inset_block_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/inset_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/inset_inline_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/margin_block_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/margin_inline_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/padding_block_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/padding_inline_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/webkit_border_after_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/webkit_border_before_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/webkit_border_end_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/shorthands/webkit_border_start_custom.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/css/properties/style_building_utils.h20
-rw-r--r--chromium/third_party/blink/renderer/core/css/property_descriptor.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/css/property_registration.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/css_variable_data_test.cc45
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver.cc242
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver.h96
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver_test.cc119
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/element_style_resources.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/filter_operation_resolver.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/filter_operation_resolver.h3
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/matched_properties_cache.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_adjuster.cc45
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_builder.cc116
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_builder.h7
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_builder_converter.h8
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_builder_custom.cc1050
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_resolver.cc132
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/style_resolver.h7
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/rule_feature_set.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/css/rule_feature_set.h11
-rw-r--r--chromium/third_party/blink/renderer/core/css/rule_feature_set_test.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/css/selector_checker.cc60
-rw-r--r--chromium/third_party/blink/renderer/core/css/selector_filter.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/css/selector_query.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/css/style-invalidation.md168
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_change_reason.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_change_reason.h2
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_engine.cc93
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_engine.h18
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_engine_test.cc76
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_environment_variables.cc172
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_environment_variables.h92
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_environment_variables_test.cc445
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_property_serializer.cc67
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_property_serializer.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_rule_css_style_declaration.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_rule_css_style_declaration.h1
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_sheet_collection.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_sheet_collection.h5
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_sheet_contents.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_sheet_list.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_sheet_list.h4
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_sheet_list.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/css/style_sheet_list_test.cc66
-rw-r--r--chromium/third_party/blink/renderer/core/css/threaded/filter_operation_resolver_threaded_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/css/threaded/font_object_threaded_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/css/threaded/text_renderer_threaded_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/BUILD.gn40
-rw-r--r--chromium/third_party/blink/renderer/core/dom/README.md299
-rw-r--r--chromium/third_party/blink/renderer/core/dom/abort_signal.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/accessibility_role.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/accessible_node.cc1191
-rw-r--r--chromium/third_party/blink/renderer/core/dom/accessible_node.h402
-rw-r--r--chromium/third_party/blink/renderer/core/dom/accessible_node_list.cc114
-rw-r--r--chromium/third_party/blink/renderer/core/dom/accessible_node_list.h51
-rw-r--r--chromium/third_party/blink/renderer/core/dom/aria_attributes.idl5
-rw-r--r--chromium/third_party/blink/renderer/core/dom/attr.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/dom/attr.h1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/ax_object_cache.cc173
-rw-r--r--chromium/third_party/blink/renderer/core/dom/ax_object_cache.h158
-rw-r--r--chromium/third_party/blink/renderer/core/dom/ax_object_cache_base.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/dom/ax_object_cache_base.h41
-rw-r--r--chromium/third_party/blink/renderer/core/dom/character_data.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/dom/child_list_mutation_scope.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/child_node_list.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/dom/child_node_list.h4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/computed_accessible_node.cc346
-rw-r--r--chromium/third_party/blink/renderer/core/dom/computed_accessible_node.h112
-rw-r--r--chromium/third_party/blink/renderer/core/dom/container_node.cc109
-rw-r--r--chromium/third_party/blink/renderer/core/dom/container_node.h3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/context_lifecycle_notifier.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/dom/context_lifecycle_observer.h55
-rw-r--r--chromium/third_party/blink/renderer/core/dom/dataset_dom_string_map.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document.cc502
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document.h152
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document.idl8
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_encoding_data.h5
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_lifecycle.h5
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_or_shadow_root.h11
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_or_shadow_root.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_parser.h5
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_parser_timing.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_parser_timing.h32
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_shutdown_observer.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_shutdown_observer.h3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_statistics_collector.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/dom/document_test.cc95
-rw-r--r--chromium/third_party/blink/renderer/core/dom/dom_exception.cc275
-rw-r--r--chromium/third_party/blink/renderer/core/dom/dom_exception.h20
-rw-r--r--chromium/third_party/blink/renderer/core/dom/dom_implementation.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/dom_string_map.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/dom_token_list.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element.cc754
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element.h50
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element.idl7
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element_rare_data.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element_rare_data.h13
-rw-r--r--chromium/third_party/blink/renderer/core/dom/element_visibility_observer.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/custom_event.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/custom_event.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/dom_window_event_queue.cc155
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/dom_window_event_queue.h65
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h75
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_listener.h5
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_listener_map.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_listener_map.h5
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_queue.cc129
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_queue.h43
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_target.cc82
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/event_target.h15
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/media_element_event_queue.cc139
-rw-r--r--chromium/third_party/blink/renderer/core/dom/events/media_element_event_queue.h68
-rw-r--r--chromium/third_party/blink/renderer/core/dom/exception_code.h108
-rw-r--r--chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng.cc368
-rw-r--r--chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng.h331
-rw-r--r--chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng_test.cc772
-rw-r--r--chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/frame_request_callback_collection.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/dom/frame_request_callback_collection.h10
-rw-r--r--chromium/third_party/blink/renderer/core/dom/idle_deadline.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/dom/idle_deadline.h10
-rw-r--r--chromium/third_party/blink/renderer/core/dom/idle_deadline_test.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/dom/layout_tree_builder.cc152
-rw-r--r--chromium/third_party/blink/renderer/core/dom/layout_tree_builder.h57
-rw-r--r--chromium/third_party/blink/renderer/core/dom/live_node_list.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/dom/mutation_observer.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/dom/mutation_observer.h18
-rw-r--r--chromium/third_party/blink/renderer/core/dom/mutation_observer_interest_group.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/mutation_observer_interest_group.h14
-rw-r--r--chromium/third_party/blink/renderer/core/dom/mutation_observer_options.h26
-rw-r--r--chromium/third_party/blink/renderer/core/dom/mutation_observer_registration.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/dom/mutation_observer_registration.h11
-rw-r--r--chromium/third_party/blink/renderer/core/dom/mutation_observer_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/mutation_record.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/dom/named_node_map.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/dom/ng/OWNERS4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/ng/README.md10
-rw-r--r--chromium/third_party/blink/renderer/core/dom/ng/flat_tree_traversal_ng.cc368
-rw-r--r--chromium/third_party/blink/renderer/core/dom/ng/flat_tree_traversal_ng.h331
-rw-r--r--chromium/third_party/blink/renderer/core/dom/ng/flat_tree_traversal_ng_test.cc772
-rw-r--r--chromium/third_party/blink/renderer/core/dom/ng/slot_assignment_engine.cc58
-rw-r--r--chromium/third_party/blink/renderer/core/dom/ng/slot_assignment_engine.h37
-rw-r--r--chromium/third_party/blink/renderer/core/dom/ng/slot_assignment_test.cc168
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node.cc97
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node.h57
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_child_removal_tracker.h3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_iterator.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_iterator.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_iterator_base.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_iterator_base.h1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_lists_node_data.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_lists_node_data.h3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_rare_data.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_rare_data.h49
-rw-r--r--chromium/third_party/blink/renderer/core/dom/node_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/dom/pausable_object.h18
-rw-r--r--chromium/third_party/blink/renderer/core/dom/pseudo_element.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/dom/pseudo_element.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/qualified_name.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/range.cc93
-rw-r--r--chromium/third_party/blink/renderer/core/dom/range.h8
-rw-r--r--chromium/third_party/blink/renderer/core/dom/range.idl5
-rw-r--r--chromium/third_party/blink/renderer/core/dom/range_boundary_point.h1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/range_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.h4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller.h15
-rw-r--r--chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/dom/shadow_root.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/dom/shadow_root.h4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/shadow_root_v0.h4
-rw-r--r--chromium/third_party/blink/renderer/core/dom/slot_assignment.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/slot_assignment_engine.cc58
-rw-r--r--chromium/third_party/blink/renderer/core/dom/slot_assignment_engine.h41
-rw-r--r--chromium/third_party/blink/renderer/core/dom/slot_assignment_recalc_forbidden_scope.h43
-rw-r--r--chromium/third_party/blink/renderer/core/dom/slot_assignment_test.cc169
-rw-r--r--chromium/third_party/blink/renderer/core/dom/static_node_list.h16
-rw-r--r--chromium/third_party/blink/renderer/core/dom/static_range.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/static_range_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/sync_reattach_context.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/dom/sync_reattach_context.h43
-rw-r--r--chromium/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/dom/text.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/dom/tree_scope.cc51
-rw-r--r--chromium/third_party/blink/renderer/core/dom/tree_scope.h8
-rw-r--r--chromium/third_party/blink/renderer/core/dom/tree_walker.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/dom/tree_walker.h2
-rw-r--r--chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_html.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_html.h38
-rw-r--r--chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.h38
-rw-r--r--chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_url.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_url.h37
-rw-r--r--chromium/third_party/blink/renderer/core/dom/user_action_element_set.h7
-rw-r--r--chromium/third_party/blink/renderer/core/dom/user_gesture_indicator.h1
-rw-r--r--chromium/third_party/blink/renderer/core/dom/user_gesture_indicator_test.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/dom/viewport_description.cc308
-rw-r--r--chromium/third_party/blink/renderer/core/dom/viewport_description.h185
-rw-r--r--chromium/third_party/blink/renderer/core/editing/BUILD.gn11
-rw-r--r--chromium/third_party/blink/renderer/core/editing/caret_display_item_client.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/editing/caret_display_item_client_test.cc213
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/append_node_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/apply_block_element_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/apply_block_element_command_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/delete_from_text_node_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/document_exec_command.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/editor_command.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/format_block_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/insert_list_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/insert_node_before_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/merge_identical_elements_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/move_commands.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/remove_css_property_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/remove_node_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/replace_node_with_span_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/split_element_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/split_text_node_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/typing_command.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/typing_command_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/commands/wrap_contents_in_dummy_span_command.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/dom_selection.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/editing/dom_selection.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/editing_strategy.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/editing_style.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/editing_style_utilities.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/editing_utilities.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/editing_utilities_test.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/editing/editor.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/editing/editor_test.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ephemeral_range.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/find_in_page_coordinates.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/text_finder.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/text_finder.h4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/finder/text_finder_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/frame_selection.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/editing/frame_selection.h9
-rw-r--r--chromium/third_party/blink/renderer/core/editing/frame_selection_test.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/editing/granularity_strategy_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/ime/input_method_controller.h1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/inline_box_position.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/editing/inline_box_traversal.cc146
-rw-r--r--chromium/third_party/blink/renderer/core/editing/inline_box_traversal.h19
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/character_iterator.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/character_iterator.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/fully_clipped_state_stack.h3
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/simplified_backwards_text_iterator.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_test.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_node_handler.cc65
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/kill_ring.h51
-rw-r--r--chromium/third_party/blink/renderer/core/editing/kill_ring_mac.mm76
-rw-r--r--chromium/third_party/blink/renderer/core/editing/kill_ring_none.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/editing/layout_selection.cc155
-rw-r--r--chromium/third_party/blink/renderer/core/editing/layout_selection_test.cc474
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.cc89
-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/markers/document_marker_controller_test.cc45
-rw-r--r--chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/position.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/position_iterator.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/position_with_affinity.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/rendered_position.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/rendered_position_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_adjuster.cc290
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_adjuster_test.cc480
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_controller.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_controller.h1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_controller_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_modifier_character_test.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_modifier_word_test.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/editing/selection_template.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/serializers/serialization.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.cc80
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.h10
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_callback.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_callback.h1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_callback_test.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/spell_check_requester.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/editing/spellcheck/spell_check_requester.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/editing/suggestion/text_suggestion_controller.h1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/testing/selection_sample_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/editing/text_offset_mapping.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/editing/text_offset_mapping_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/editing/text_segments.cc59
-rw-r--r--chromium/third_party/blink/renderer/core/editing/text_segments.h65
-rw-r--r--chromium/third_party/blink/renderer/core/editing/visible_position.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/visible_position.h2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/visible_selection.cc108
-rw-r--r--chromium/third_party/blink/renderer/core/editing/visible_selection.h17
-rw-r--r--chromium/third_party/blink/renderer/core/editing/visible_selection_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/editing/visible_units.cc145
-rw-r--r--chromium/third_party/blink/renderer/core/editing/visible_units.h10
-rw-r--r--chromium/third_party/blink/renderer/core/editing/visible_units_line.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/editing/visible_units_sentence.cc152
-rw-r--r--chromium/third_party/blink/renderer/core/editing/visible_units_sentence_test.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/editing/visible_units_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/editing/visible_units_word.cc141
-rw-r--r--chromium/third_party/blink/renderer/core/editing/visible_units_word_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/editing/web_substring_util.mm3
-rw-r--r--chromium/third_party/blink/renderer/core/events/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/events/current_input_event.h8
-rw-r--r--chromium/third_party/blink/renderer/core/events/error_event.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/events/error_event.h1
-rw-r--r--chromium/third_party/blink/renderer/core/events/event_target_names.json52
-rw-r--r--chromium/third_party/blink/renderer/core/events/event_type_names.json51
-rw-r--r--chromium/third_party/blink/renderer/core/events/message_event.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/events/mouse_event.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/events/picture_in_picture_control_event.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/events/picture_in_picture_control_event.h40
-rw-r--r--chromium/third_party/blink/renderer/core/events/picture_in_picture_control_event.idl11
-rw-r--r--chromium/third_party/blink/renderer/core/events/picture_in_picture_control_event_init.idl7
-rw-r--r--chromium/third_party/blink/renderer/core/events/pointer_event_factory.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/events/pointer_event_factory_test.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/events/pop_state_event.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/events/pop_state_event.h7
-rw-r--r--chromium/third_party/blink/renderer/core/events/promise_rejection_event.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/events/promise_rejection_event.h2
-rw-r--r--chromium/third_party/blink/renderer/core/events/registered_event_listener.h3
-rw-r--r--chromium/third_party/blink/renderer/core/events/touch_event.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/events/touch_event_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/events/web_input_event_conversion.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/events/web_input_event_conversion_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/execution_context.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/execution_context.h16
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/security_context.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/execution_context/security_context.h24
-rw-r--r--chromium/third_party/blink/renderer/core/exported/BUILD.gn3
-rw-r--r--chromium/third_party/blink/renderer/core/exported/fake_web_plugin.h6
-rw-r--r--chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.cc189
-rw-r--r--chromium/third_party/blink/renderer/core/exported/local_frame_client_impl.h27
-rw-r--r--chromium/third_party/blink/renderer/core/exported/local_frame_client_impl_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.h1
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_associated_url_loader_impl.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_associated_url_loader_impl_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_document.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_document_loader_impl.cc49
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_document_loader_impl.h9
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_document_test.cc70
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_element.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_form_control_element.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_frame_client.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_frame_serializer.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_frame_serializer_sanitization_test.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_frame_test.cc777
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_heap.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_image_decoder.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_local_frame_client.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_node.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.cc63
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_page_popup_impl.h6
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_performance.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc73
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_plugin_container_impl.h5
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_plugin_container_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_plugin_document.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_remote_frame_impl.h4
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_security_policy.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_selection.cc49
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_serialized_script_value.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_settings_impl.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_settings_impl.h7
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_shared_worker_impl.h22
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_user_gesture_indicator.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_view_impl.cc440
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_view_impl.h54
-rw-r--r--chromium/third_party/blink/renderer/core/exported/web_view_test.cc408
-rw-r--r--chromium/third_party/blink/renderer/core/exported/worker_shadow_page.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/exported/worker_shadow_page.h38
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer.cc283
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer.h51
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer_test.cc435
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/body.cc151
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/body.h42
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/body.idl12
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/body_stream_buffer.cc339
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/body_stream_buffer.h65
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc179
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/data_consumer_handle_test_util.h4
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_data_loader.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_manager.cc49
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_manager.h6
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_request_data.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_request_data.h20
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_response_data.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/fetch_response_data.h11
-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/form_data_bytes_consumer.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/global_fetch.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/global_fetch.h8
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/headers.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.h2
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/request.cc343
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/request.h15
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/request.idl13
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/request_init.cc289
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/request_init.h80
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/request_init.idl28
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/request_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/response.cc75
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/response.h13
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/response_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/window_fetch.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/fetch/worker_fetch.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/blob.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_error.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_error.h5
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_reader.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.cc58
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.h22
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/file_reader_sync.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/public_url_manager.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/public_url_manager_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/fileapi/url_file_api.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/BUILD.gn19
-rw-r--r--chromium/third_party/blink/renderer/core/frame/ad_tracker.cc57
-rw-r--r--chromium/third_party/blink/renderer/core/frame/ad_tracker.h36
-rw-r--r--chromium/third_party/blink/renderer/core/frame/ad_tracker_test.cc230
-rw-r--r--chromium/third_party/blink/renderer/core/frame/browser_controls.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/frame/browser_controls.h10
-rw-r--r--chromium/third_party/blink/renderer/core/frame/browser_controls_test.cc350
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/content_security_policy.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/content_security_policy.h10
-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.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list.cc376
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list.h38
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/csp_directive_list_test.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/source_list_directive.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/source_list_directive.h6
-rw-r--r--chromium/third_party/blink/renderer/core/frame/csp/source_list_directive_test.cc52
-rw-r--r--chromium/third_party/blink/renderer/core/frame/deprecation.cc138
-rw-r--r--chromium/third_party/blink/renderer/core/frame/deprecation.h7
-rw-r--r--chromium/third_party/blink/renderer/core/frame/deprecation_report.h40
-rw-r--r--chromium/third_party/blink/renderer/core/frame/deprecation_report.idl17
-rw-r--r--chromium/third_party/blink/renderer/core/frame/deprecation_report_body.h40
-rw-r--r--chromium/third_party/blink/renderer/core/frame/deprecation_report_body.idl17
-rw-r--r--chromium/third_party/blink/renderer/core/frame/display_cutout_client_impl.cc53
-rw-r--r--chromium/third_party/blink/renderer/core/frame/display_cutout_client_impl.h45
-rw-r--r--chromium/third_party/blink/renderer/core/frame/dom_timer.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/frame/dom_visual_viewport.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/frame/dom_window.cc221
-rw-r--r--chromium/third_party/blink/renderer/core/frame/dom_window.h49
-rw-r--r--chromium/third_party/blink/renderer/core/frame/dom_window_base64.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/frame/event_handler_registry.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/frame/find_in_page.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/frame/find_in_page.h15
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame.cc52
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame.h46
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_serializer.cc16
-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.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_test_helpers.cc148
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_test_helpers.h80
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_view.h7
-rw-r--r--chromium/third_party/blink/renderer/core/frame/frame_view_auto_size_info.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/frame/fullscreen_controller.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/frame/history.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/frame/history.h5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/history_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/intervention.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/frame/intervention.h4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/intervention_report.h26
-rw-r--r--chromium/third_party/blink/renderer/core/frame/intervention_report.idl16
-rw-r--r--chromium/third_party/blink/renderer/core/frame/intervention_report_body.h32
-rw-r--r--chromium/third_party/blink/renderer/core/frame/intervention_report_body.idl16
-rw-r--r--chromium/third_party/blink/renderer/core/frame/intrinsic_sizing_info.h29
-rw-r--r--chromium/third_party/blink/renderer/core/frame/link_highlights.cc108
-rw-r--r--chromium/third_party/blink/renderer/core/frame/link_highlights.h66
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_dom_window.cc241
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_dom_window.h50
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame.cc146
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame.h74
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_client.h52
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_view.cc2375
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_view.h554
-rw-r--r--chromium/third_party/blink/renderer/core/frame/local_frame_view_test.cc109
-rw-r--r--chromium/third_party/blink/renderer/core/frame/location.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/frame/location.h4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/location.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/message_report.h34
-rw-r--r--chromium/third_party/blink/renderer/core/frame/message_report_body.h42
-rw-r--r--chromium/third_party/blink/renderer/core/frame/mhtml_archive_test.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/frame/mhtml_loading_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator.h1
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_user_activation.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_user_activation.h39
-rw-r--r--chromium/third_party/blink/renderer/core/frame/navigator_user_activation.idl12
-rw-r--r--chromium/third_party/blink/renderer/core/frame/page_scale_constraints_set.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/pausable_script_executor.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/frame/pausable_script_executor.h4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/pausable_timer.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/frame/pausable_timer.h4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/performance_monitor.cc67
-rw-r--r--chromium/third_party/blink/renderer/core/frame/performance_monitor.h27
-rw-r--r--chromium/third_party/blink/renderer/core/frame/performance_monitor_test.cc68
-rw-r--r--chromium/third_party/blink/renderer/core/frame/picture_in_picture_controller.h17
-rw-r--r--chromium/third_party/blink/renderer/core/frame/platform_event_controller.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/frame/platform_event_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/platform_event_dispatcher.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/frame/platform_event_dispatcher.h3
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame.h10
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame_client.h13
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame_client_impl.h8
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame_owner.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame_view.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/frame/remote_frame_view.h15
-rw-r--r--chromium/third_party/blink/renderer/core/frame/report.h1
-rw-r--r--chromium/third_party/blink/renderer/core/frame/reporting_context.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/frame/reporting_context.h10
-rw-r--r--chromium/third_party/blink/renderer/core/frame/reporting_observer.cc69
-rw-r--r--chromium/third_party/blink/renderer/core/frame/reporting_observer.h44
-rw-r--r--chromium/third_party/blink/renderer/core/frame/reporting_observer.idl8
-rw-r--r--chromium/third_party/blink/renderer/core/frame/reporting_observer_options.idl10
-rw-r--r--chromium/third_party/blink/renderer/core/frame/root_frame_viewport.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/frame/root_frame_viewport.h11
-rw-r--r--chromium/third_party/blink/renderer/core/frame/root_frame_viewport_test.cc64
-rw-r--r--chromium/third_party/blink/renderer/core/frame/rotation_viewport_anchor.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/frame/rotation_viewport_anchor_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/frame/settings.json543
-rw-r--r--chromium/third_party/blink/renderer/core/frame/smart_clip.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/frame/use_counter.cc430
-rw-r--r--chromium/third_party/blink/renderer/core/frame/use_counter.h24
-rw-r--r--chromium/third_party/blink/renderer/core/frame/use_counter_test.cc414
-rw-r--r--chromium/third_party/blink/renderer/core/frame/user_activation.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/frame/user_activation.h33
-rw-r--r--chromium/third_party/blink/renderer/core/frame/user_activation.idl10
-rw-r--r--chromium/third_party/blink/renderer/core/frame/user_activation_state.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/frame/user_activation_state.h47
-rw-r--r--chromium/third_party/blink/renderer/core/frame/viewport_data.cc120
-rw-r--r--chromium/third_party/blink/renderer/core/frame/viewport_data.h61
-rw-r--r--chromium/third_party/blink/renderer/core/frame/visual_viewport.cc232
-rw-r--r--chromium/third_party/blink/renderer/core/frame/visual_viewport.h82
-rw-r--r--chromium/third_party/blink/renderer/core/frame/visual_viewport_test.cc270
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.cc176
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_frame_widget_base.h30
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_frame_widget_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.cc229
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_local_frame_impl.h66
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/frame/web_view_frame_widget.h6
-rw-r--r--chromium/third_party/blink/renderer/core/frame/window.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/frame/window_post_message_options.idl9
-rw-r--r--chromium/third_party/blink/renderer/core/fullscreen/document_fullscreen.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/fullscreen/document_fullscreen.h5
-rw-r--r--chromium/third_party/blink/renderer/core/fullscreen/document_fullscreen.idl9
-rw-r--r--chromium/third_party/blink/renderer/core/fullscreen/element_fullscreen.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/fullscreen/element_fullscreen.h6
-rw-r--r--chromium/third_party/blink/renderer/core/fullscreen/element_fullscreen.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc594
-rw-r--r--chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h89
-rw-r--r--chromium/third_party/blink/renderer/core/geometry/dom_matrix.h2
-rw-r--r--chromium/third_party/blink/renderer/core/geometry/dom_matrix_read_only.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/geometry/dom_matrix_read_only.h2
-rw-r--r--chromium/third_party/blink/renderer/core/geometry/dom_matrix_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/geometry/dom_point_read_only.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/BUILD.gn6
-rw-r--r--chromium/third_party/blink/renderer/core/html/anchor_element_metrics.cc274
-rw-r--r--chromium/third_party/blink/renderer/core/html/anchor_element_metrics.h120
-rw-r--r--chromium/third_party/blink/renderer/core/html/anchor_element_metrics_sender.cc50
-rw-r--r--chromium/third_party/blink/renderer/core/html/anchor_element_metrics_sender.h50
-rw-r--r--chromium/third_party/blink/renderer/core/html/anchor_element_metrics_test.cc260
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc208
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h71
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator_test.cc119
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_context_creation_attributes_core.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc140
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h43
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc281
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.h53
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/image_data.cc50
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/image_data.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/image_data_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/image_element_base.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/image_encode_options.idl21
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/text_metrics.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/text_metrics.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/canvas/text_metrics.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/README.md10
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_definition.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_definition.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_registry.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_registry.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_registry_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_test_helpers.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/custom_element_upgrade_sorter_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_exception.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/base_checkable_input_type.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/base_temporal_input_type.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/base_temporal_input_type.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/color_input_type.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_edit_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_field_element.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_field_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_local_input_type.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_symbolic_field_element.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/date_time_symbolic_field_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/external_popup_menu.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/external_popup_menu.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/file_chooser.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/file_chooser.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/file_input_type.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/file_input_type.h7
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/file_input_type_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/form_data.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/form_data.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/form_data_test.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/hidden_input_type.cc4
-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_field_set_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_field_set_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.h15
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_form_element.cc52
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_form_element.h7
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_input_element.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_input_element.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_input_element.idl5
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_input_element_test.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_option_element.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_options_collection.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_output_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_select_element.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_select_element.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/image_input_type.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/image_input_type.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/input_type.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/input_type.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/internal_popup_menu.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/multiple_fields_temporal_input_type_view.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/number_input_type.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/picker_indicator_element.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/radio_button_group_scope.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/range_input_type.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/resources/listPicker.js8
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/search_input_type.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/slider_thumb_element.cc6
-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/step_range.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/submit_input_type.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/text_control_element.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/text_control_element.h4
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/text_control_element_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/text_control_inner_elements.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/text_field_input_type.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/html/forms/text_field_input_type.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_anchor_element.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_anchor_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_attribute_names.json51
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_base_element.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_base_element.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_base_element.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_collection.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_details_element.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_details_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_dialog_element.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_document.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_document.h8
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_element.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_embed_element.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_element.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_element_base.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_owner_element.cc120
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_owner_element.h16
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_frame_owner_element_test.cc308
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_hyperlink_element_utils.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_iframe_element.cc52
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_iframe_element.idl10
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_iframe_element_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_image_element.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_image_element.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_image_element.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_image_fallback_helper.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_li_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_link_element.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_link_element.h10
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_link_element.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_marquee_element.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_meta_element.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_meta_element.h7
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_meta_element_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_meter_element.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_object_element.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_object_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_object_element.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_plugin_element.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_plugin_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_progress_element.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_ruby_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_script_element.cc7
-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_slot_element.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_slot_element.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_slot_element_test.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_source_element.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_source_element.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_source_element.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_style_element.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_style_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_summary_element.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_summary_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_table_element.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_table_row_element.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_table_section_element.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_template_element.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_template_element.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/html_title_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/image_document.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/html/image_document.h3
-rw-r--r--chromium/third_party/blink/renderer/core/html/image_document_test.cc110
-rw-r--r--chromium/third_party/blink/renderer/core/html/imports/html_import_loader.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/imports/html_import_tree_root.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/imports/html_import_tree_root.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/imports/html_imports_controller.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/imports/html_imports_controller.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc360
-rw-r--r--chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer.h93
-rw-r--r--chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer_test.cc739
-rw-r--r--chromium/third_party/blink/renderer/core/html/link_style.cc57
-rw-r--r--chromium/third_party/blink/renderer/core/html/link_style.h8
-rw-r--r--chromium/third_party/blink/renderer/core/html/list_item_ordinal.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/html/list_item_ordinal.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/autoplay_policy.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/autoplay_policy.h11
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc96
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/autoplay_uma_helper.h7
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_audio_element.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_media_element.cc171
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_media_element.h38
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_media_element.idl5
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_media_element_event_listeners_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_media_element_test.cc133
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_video_element.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_video_element.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_video_element_persistent_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/html_video_element_test.cc94
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/media_controls.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/media_controls.h15
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/media_custom_controls_fullscreen_detector.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/media_document.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.cc16
-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.cc92
-rw-r--r--chromium/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.h20
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/css_preload_scanner.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_construction_site.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_document_parser.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_document_parser.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_parser_idioms.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_preload_scanner_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/html_tree_builder.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/preload_request.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/preload_request.h8
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/html/plugin_document.cc52
-rw-r--r--chromium/third_party/blink/renderer/core/html/plugin_document.h6
-rw-r--r--chromium/third_party/blink/renderer/core/html/time_ranges.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/html/time_ranges_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/cue_timeline.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/html_track_element.idl6
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/text_track.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/text_track.h2
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/text_track_container.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/text_track_cue.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/text_track_cue_list.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/text_track_cue_list.h1
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/text_track_list.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/text_track_list.h5
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/track_list_base.h7
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/vtt/buffered_line_reader_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/html/track/vtt/vtt_region.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc57
-rw-r--r--chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.h5
-rw-r--r--chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_factories.h4
-rw-r--r--chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap_source.cc5
-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.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/input/event_handler.cc272
-rw-r--r--chromium/third_party/blink/renderer/core/input/event_handler.h32
-rw-r--r--chromium/third_party/blink/renderer/core/input/event_handler_test.cc108
-rw-r--r--chromium/third_party/blink/renderer/core/input/event_handling_util.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/input/event_handling_util.h5
-rw-r--r--chromium/third_party/blink/renderer/core/input/gesture_manager.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/input/mouse_event_manager.cc63
-rw-r--r--chromium/third_party/blink/renderer/core/input/mouse_wheel_event_manager.cc105
-rw-r--r--chromium/third_party/blink/renderer/core/input/pointer_event_manager.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/input/scroll_manager.cc171
-rw-r--r--chromium/third_party/blink/renderer/core/input/scroll_manager.h21
-rw-r--r--chromium/third_party/blink/renderer/core/input/scroll_snap_test.cc47
-rw-r--r--chromium/third_party/blink/renderer/core/input/touch.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/input/touch_action_test.cc71
-rw-r--r--chromium/third_party/blink/renderer/core/input/touch_event_manager.cc86
-rw-r--r--chromium/third_party/blink/renderer/core/input/touch_event_manager.h24
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/README.md3
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/browser_protocol.pdl318
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.cc77
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.h15
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/dev_tools_host.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/dom_editor.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/dom_patch_support.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/identifiers_factory.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_animation_agent.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_audits_agent.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_css_agent.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_dom_agent.h8
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.h4
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc437
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.h51
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_emulation_agent.cc196
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_emulation_agent.h26
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_highlight.cc129
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_highlight.h14
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_history.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_log_agent.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_log_agent.h4
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.cc201
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_network_agent.h57
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h3
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_page_agent.cc245
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_page_agent.h19
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_performance_agent.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_performance_agent.h7
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_protocol_config.json3
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_session.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc61
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_task_runner.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_trace_events.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/inspector_trace_events.h5
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/main_thread_debugger.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/main_thread_debugger.h2
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/network_resources_data.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/protocol_parser_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/thread_debugger.h1
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/v8_inspector_string.h3
-rw-r--r--chromium/third_party/blink/renderer/core/inspector/worker_inspector_controller.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.h5
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer.h3
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h4
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_delegate.h5
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h2
-rw-r--r--chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_test.cc281
-rw-r--r--chromium/third_party/blink/renderer/core/layout/BUILD.gn12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/api/line_layout_box_model.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/api/line_layout_item.h10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/counter_node.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/css_layout_definition.cc70
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/css_layout_definition.h20
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/custom_layout_child.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/custom_layout_child.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/custom_layout_constraints.cc56
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/custom_layout_constraints.h20
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/custom_layout_constraints_options.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment.h10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment_request.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment_request.h10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/fragment_result_options.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/layout_child.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/layout_constraints.idl4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/layout_custom.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/layout_custom.h14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/layout_fragment.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/flexible_box_algorithm.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/grid.cc104
-rw-r--r--chromium/third_party/blink/renderer/core/layout/grid.h119
-rw-r--r--chromium/third_party/blink/renderer/core/layout/grid_baseline_alignment.cc55
-rw-r--r--chromium/third_party/blink/renderer/core/layout/grid_baseline_alignment.h25
-rw-r--r--chromium/third_party/blink/renderer/core/layout/grid_layout_utils.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/grid_layout_utils.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.cc299
-rw-r--r--chromium/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.h37
-rw-r--r--chromium/third_party/blink/renderer/core/layout/hit_test_cache.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/layout/hit_test_cache.h23
-rw-r--r--chromium/third_party/blink/renderer/core/layout/hit_test_location.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/layout/hit_test_location.h24
-rw-r--r--chromium/third_party/blink/renderer/core/layout/hit_test_result.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/layout/hit_test_result.h29
-rw-r--r--chromium/third_party/blink/renderer/core/layout/intersection_geometry.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/layout/intrinsic_sizing_info.h29
-rw-r--r--chromium/third_party/blink/renderer/core/layout/jank_tracker.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/layout/jank_tracker.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/jank_tracker_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_block.cc96
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_block.h17
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_block_flow.cc210
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_block_flow.h9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_block_flow_line.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_block_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_box.cc213
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_box.h69
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_box_model_object.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_button.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_button.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_counter.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_details_marker.cc5
-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_embedded_content.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_embedded_content.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_embedded_object.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_embedded_object.h10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_fieldset.h8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_file_upload_control.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_flexible_box.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_flexible_box.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_frame_set.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_frame_set.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_full_screen.cc238
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_full_screen.h80
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_geometry_map_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_grid.cc469
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_grid.h58
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_html_canvas.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_image.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_image.h11
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_image_resource.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_image_resource.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_image_resource_style_image.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_image_test.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_inline.cc94
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_inline.h17
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_inline_test.cc61
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_list_box.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_list_item.cc45
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_list_item.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_list_marker.cc68
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_list_marker.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_media.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_media.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_menu_list.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object.cc364
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object.h262
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object_child_list.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object_factory.cc95
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object_factory.h39
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_object_test.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_progress.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_progress.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_replaced.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_replaced.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_scrollbar.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_scrollbar.h15
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_scrollbar_part.cc99
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_scrollbar_part.h12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_scrollbar_theme.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_table.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_table.h13
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_table_box_component.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_table_cell.cc54
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_table_cell.h23
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_table_cell_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_table_col.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_table_col.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_table_col_test.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_table_row.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_table_row.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_table_section.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_table_section.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_table_section_test.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text.h11
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text_combine.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text_control.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text_control_single_line.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text_fragment.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text_fragment.h7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text_fragment_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_text_test.cc104
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme.h8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_default.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_default.h8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_mac.h9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_theme_mac.mm8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_tree_as_text.cc116
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_video.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_video.h8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_view.cc226
-rw-r--r--chromium/third_party/blink/renderer/core/layout/layout_view.h47
-rw-r--r--chromium/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.cc91
-rw-r--r--chromium/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.h80
-rw-r--r--chromium/third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/line/ellipsis_box.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/line/inline_box.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/layout/line/inline_box.h10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/line/inline_text_box.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/layout/line/inline_text_box.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/line/line_box_list.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/line/root_inline_box.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/layout/map_coordinates_flags.h11
-rw-r--r--chromium/third_party/blink/renderer/core/layout/map_coordinates_test.cc51
-rw-r--r--chromium/third_party/blink/renderer/core/layout/min_max_size.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/min_max_size.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion.h54
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.cc146
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h159
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_layout_opportunity.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_shape_exclusions.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h29
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_margin_strut.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_margin_strut.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.cc224
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.h68
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_baseline.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.h1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc157
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.cc318
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.cc124
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item.h41
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.cc31
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h42
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.h9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc230
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm_test.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc152
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_box_fragment_builder.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc845
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h210
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_height_metrics.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_height_metrics.h9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_truncator.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc75
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h26
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment_test.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc58
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h18
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment_test.cc61
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_flexible_box.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc131
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.h8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc53
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.h11
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc61
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc88
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc410
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h43
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.cc291
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_node.h26
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_block_node_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_exclusion.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_exclusion.h54
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc105
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_floats_utils.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_floats_utils.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.cc33
-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_layout_input_node.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_layout_test.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc95
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils.h60
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_length_utils_test.cc87
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc75
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h13
-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_physical_box_fragment.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h11
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h11
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_relative_utils.cc52
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_relative_utils.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_relative_utils_test.cc60
-rw-r--r--chromium/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/layout/paint_containment_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/scroll_anchor.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/layout/scroll_anchor_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/scrollbars_test.cc172
-rw-r--r--chromium/third_party/blink/renderer/core/layout/shapes/polygon_shape.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/shapes/shape.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_container.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc77
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc54
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.h6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h4
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_path.cc82
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_path.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_root.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_root.h10
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_shape.h5
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/layout_svg_text.h2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h3
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/svg_layout_support.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/svg_layout_tree_as_text.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/svg/svg_resources.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/layout/text_autosizer.cc63
-rw-r--r--chromium/third_party/blink/renderer/core/layout/text_autosizer.h14
-rw-r--r--chromium/third_party/blink/renderer/core/layout/visual_rect_mapping_test.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/layout/web_font_rendering_win.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/loader/BUILD.gn10
-rw-r--r--chromium/third_party/blink/renderer/core/loader/allowed_by_nosniff_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/appcache/application_cache.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/loader/base_fetch_context.cc83
-rw-r--r--chromium/third_party/blink/renderer/core/loader/base_fetch_context.h14
-rw-r--r--chromium/third_party/blink/renderer/core/loader/base_fetch_context_test.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/loader/document_load_timing.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/loader/document_load_timing.h7
-rw-r--r--chromium/third_party/blink/renderer/core/loader/document_load_timing_test.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/loader/document_loader.cc201
-rw-r--r--chromium/third_party/blink/renderer/core/loader/document_loader.h45
-rw-r--r--chromium/third_party/blink/renderer/core/loader/document_loader_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/loader/document_threadable_loader.cc349
-rw-r--r--chromium/third_party/blink/renderer/core/loader/document_threadable_loader.h21
-rw-r--r--chromium/third_party/blink/renderer/core/loader/empty_clients.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/loader/empty_clients.h37
-rw-r--r--chromium/third_party/blink/renderer/core/loader/form_submission.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/loader/form_submission.h6
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_fetch_context.cc337
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_fetch_context.h27
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc287
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_load_request.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_load_request.h19
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_loader.cc769
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_loader.h103
-rw-r--r--chromium/third_party/blink/renderer/core/loader/frame_loader_types.h32
-rw-r--r--chromium/third_party/blink/renderer/core/loader/history_item.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/history_item.h10
-rw-r--r--chromium/third_party/blink/renderer/core/loader/http_equiv.cc85
-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.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/loader/idleness_detector.h17
-rw-r--r--chromium/third_party/blink/renderer/core/loader/idleness_detector_test.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/loader/image_loader.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/loader/importance_attribute.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/loader/importance_attribute.h18
-rw-r--r--chromium/third_party/blink/renderer/core/loader/interactive_detector.cc99
-rw-r--r--chromium/third_party/blink/renderer/core/loader/interactive_detector.h37
-rw-r--r--chromium/third_party/blink/renderer/core/loader/interactive_detector_test.cc422
-rw-r--r--chromium/third_party/blink/renderer/core/loader/link_loader.cc109
-rw-r--r--chromium/third_party/blink/renderer/core/loader/link_loader.h10
-rw-r--r--chromium/third_party/blink/renderer/core/loader/link_loader_client.h1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/link_loader_test.cc78
-rw-r--r--chromium/third_party/blink/renderer/core/loader/mixed_content_checker.cc129
-rw-r--r--chromium/third_party/blink/renderer/core/loader/mixed_content_checker.h39
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc131
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.h42
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h51
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h17
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.cc68
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.h27
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.h24
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader_registry.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader_registry.h11
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader_test.cc148
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.cc77
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.h40
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.h24
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc81
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc96
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.h47
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/worker_or_worklet_module_script_fetcher.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/worker_or_worklet_module_script_fetcher.h46
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.cc63
-rw-r--r--chromium/third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.h59
-rw-r--r--chromium/third_party/blink/renderer/core/loader/navigation_policy.cc155
-rw-r--r--chromium/third_party/blink/renderer/core/loader/navigation_policy.h20
-rw-r--r--chromium/third_party/blink/renderer/core/loader/navigation_policy_test.cc329
-rw-r--r--chromium/third_party/blink/renderer/core/loader/navigation_scheduler.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/loader/navigation_scheduler.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/ping_loader_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_receiver_impl.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_receiver_impl.h35
-rw-r--r--chromium/third_party/blink/renderer/core/loader/programmatic_scroll_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/loader/progress_tracker.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/loader/progress_tracker.h2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/progress_tracker_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/document_resource.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/image_resource.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/image_resource.h3
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/image_resource_content.h4
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/image_resource_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/script_resource.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/script_resource.h5
-rw-r--r--chromium/third_party/blink/renderer/core/loader/resource/text_resource.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/loader/scheduled_navigation.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/loader/subresource_integrity_helper.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/text_track_loader.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/loader/threadable_loader.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/loader/threadable_loader_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/loader/worker_fetch_context.cc82
-rw-r--r--chromium/third_party/blink/renderer/core/loader/worker_fetch_context.h41
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_struct_traits.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_struct_traits_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/message_port.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/messaging/message_port.h2
-rw-r--r--chromium/third_party/blink/renderer/core/mojo/mojo_watcher.cc23
-rw-r--r--chromium/third_party/blink/renderer/core/mojo/mojo_watcher.h1
-rw-r--r--chromium/third_party/blink/renderer/core/mojo/test/mojo_interface_interceptor.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/offscreencanvas/image_encode_options.idl10
-rw-r--r--chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc247
-rw-r--r--chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h59
-rw-r--r--chromium/third_party/blink/renderer/core/page/BUILD.gn3
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client.h28
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client_impl.cc113
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client_impl.h13
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client_impl_test.cc100
-rw-r--r--chromium/third_party/blink/renderer/core/page/chrome_client_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/page/context_menu_controller.cc88
-rw-r--r--chromium/third_party/blink/renderer/core/page/context_menu_controller_test.cc69
-rw-r--r--chromium/third_party/blink/renderer/core/page/create_window.cc152
-rw-r--r--chromium/third_party/blink/renderer/core/page/create_window.h10
-rw-r--r--chromium/third_party/blink/renderer/core/page/drag_controller.cc53
-rw-r--r--chromium/third_party/blink/renderer/core/page/drag_controller_test.cc75
-rw-r--r--chromium/third_party/blink/renderer/core/page/drag_data.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/page/effective_navigation_policy_test.cc199
-rw-r--r--chromium/third_party/blink/renderer/core/page/event_with_hit_test_results.h13
-rw-r--r--chromium/third_party/blink/renderer/core/page/focus_controller.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/page/page.cc102
-rw-r--r--chromium/third_party/blink/renderer/core/page/page.h50
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_animator.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_animator.h2
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_lifecycle_state.h18
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_overlay.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_overlay_test.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_popup_client_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_visibility_notifier.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_widget_delegate.cc56
-rw-r--r--chromium/third_party/blink/renderer/core/page/page_widget_delegate.h19
-rw-r--r--chromium/third_party/blink/renderer/core/page/pointer_lock_controller.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/page/popup_opening_observer.h3
-rw-r--r--chromium/third_party/blink/renderer/core/page/print_context.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/page/print_context_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_controller.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc69
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_util.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scroll_state.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scroll_state.h2
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.cc186
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h8
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc701
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc239
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.h17
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc435
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/page/slot_scoped_traversal_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/page/spatial_navigation.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/page/touch_adjustment.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/page/touch_disambiguation.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/page/validation_message_client_impl.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/page/validation_message_client_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/core/page/viewport_description.cc307
-rw-r--r--chromium/third_party/blink/renderer/core/page/viewport_description.h176
-rw-r--r--chromium/third_party/blink/renderer/core/page/viewport_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/BUILD.gn24
-rw-r--r--chromium/third_party/blink/renderer/core/paint/README.md318
-rw-r--r--chromium/third_party/blink/renderer/core/paint/adjust_paint_offset_scope.cc88
-rw-r--r--chromium/third_party/blink/renderer/core/paint/adjust_paint_offset_scope.h89
-rw-r--r--chromium/third_party/blink/renderer/core/paint/background_image_geometry.cc994
-rw-r--r--chromium/third_party/blink/renderer/core/paint/background_image_geometry.h115
-rw-r--r--chromium/third_party/blink/renderer/core/paint/block_flow_painter.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/paint/block_flow_painter.h6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/block_painter.cc191
-rw-r--r--chromium/third_party/blink/renderer/core/paint/block_painter.h32
-rw-r--r--chromium/third_party/blink/renderer/core/paint/block_painter_test.cc197
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_border_painter.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_clipper.cc79
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_clipper.h9
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_clipper_base.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_decoration_data.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_decoration_data.h4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_model_object_painter.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_model_object_painter.h14
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.cc152
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.h6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_paint_invalidator_test.cc695
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_painter.cc58
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_painter.h18
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_painter_base.cc411
-rw-r--r--chromium/third_party/blink/renderer/core/paint/box_painter_base.h64
-rw-r--r--chromium/third_party/blink/renderer/core/paint/clip_path_clipper.cc50
-rw-r--r--chromium/third_party/blink/renderer/core/paint/clip_path_clipper.h11
-rw-r--r--chromium/third_party/blink/renderer/core/paint/clip_path_clipper_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/clip_rect.cc55
-rw-r--r--chromium/third_party/blink/renderer/core/paint/clip_rect.h47
-rw-r--r--chromium/third_party/blink/renderer/core/paint/clip_rect_test.cc87
-rw-r--r--chromium/third_party/blink/renderer/core/paint/collapsed_border_painter.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/collapsed_border_painter.h3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc309
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h33
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc63
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/composited_selection.h4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.cc71
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.cc133
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc90
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater_test.cc70
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h14
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.cc227
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc134
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc378
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.h32
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_builder.cc93
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_builder.h10
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_updater.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/paint/details_marker_painter.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/paint/details_marker_painter.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/document_marker_painter.cc247
-rw-r--r--chromium/third_party/blink/renderer/core/paint/document_marker_painter.h48
-rw-r--r--chromium/third_party/blink/renderer/core/paint/embedded_content_painter.cc87
-rw-r--r--chromium/third_party/blink/renderer/core/paint/embedded_content_painter.h4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/fieldset_painter.h5
-rw-r--r--chromium/third_party/blink/renderer/core/paint/file_upload_control_painter.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/paint/file_upload_control_painter.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/filter_painter.cc95
-rw-r--r--chromium/third_party/blink/renderer/core/paint/filter_painter.h45
-rw-r--r--chromium/third_party/blink/renderer/core/paint/find_paint_offset_and_visual_rect_needing_update.h43
-rw-r--r--chromium/third_party/blink/renderer/core/paint/find_properties_needing_update.h6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h23
-rw-r--r--chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector_test.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/paint/float_clip_recorder.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/paint/float_clip_recorder.h40
-rw-r--r--chromium/third_party/blink/renderer/core/paint/fragment_data.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/fragment_data.h58
-rw-r--r--chromium/third_party/blink/renderer/core/paint/fragment_data_test.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/paint/frame_painter.cc110
-rw-r--r--chromium/third_party/blink/renderer/core/paint/frame_painter.h5
-rw-r--r--chromium/third_party/blink/renderer/core/paint/frame_set_painter.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/paint/frame_set_painter.h9
-rw-r--r--chromium/third_party/blink/renderer/core/paint/grid_painter.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/grid_painter.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/html_canvas_painter.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/html_canvas_painter.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_painter.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/paint/image_painter.h7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/inline_flow_box_painter.cc97
-rw-r--r--chromium/third_party/blink/renderer/core/paint/inline_flow_box_painter.h7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/inline_painter.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/paint/inline_painter.h3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/inline_text_box_painter.cc427
-rw-r--r--chromium/third_party/blink/renderer/core/paint/inline_text_box_painter.h9
-rw-r--r--chromium/third_party/blink/renderer/core/paint/layer_clip_recorder.cc129
-rw-r--r--chromium/third_party/blink/renderer/core/paint/layer_clip_recorder.h82
-rw-r--r--chromium/third_party/blink/renderer/core/paint/layer_clip_recorder_test.cc90
-rw-r--r--chromium/third_party/blink/renderer/core/paint/layout_object_counter.h24
-rw-r--r--chromium/third_party/blink/renderer/core/paint/line_box_list_painter.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/link_highlight_impl.cc71
-rw-r--r--chromium/third_party/blink/renderer/core/paint/link_highlight_impl.h12
-rw-r--r--chromium/third_party/blink/renderer/core/paint/link_highlight_impl_test.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/paint/list_item_painter.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/paint/list_item_painter.h3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/list_marker_painter.cc74
-rw-r--r--chromium/third_party/blink/renderer/core/paint/list_marker_painter.h11
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_block_flow_painter.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_block_flow_painter.h11
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_box_clipper.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc530
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.h90
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc255
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h48
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.cc114
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h84
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal_test.cc141
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc230
-rw-r--r--chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/nine_piece_image_painter.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/object_paint_invalidator.cc355
-rw-r--r--chromium/third_party/blink/renderer/core/paint/object_paint_invalidator.h61
-rw-r--r--chromium/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/paint/object_paint_properties.h140
-rw-r--r--chromium/third_party/blink/renderer/core/paint/object_painter.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/paint/object_painter.h8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc390
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.h74
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.h8
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_info.h6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_invalidation_capable_scrollable_area.cc282
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_invalidation_capable_scrollable_area.h61
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_invalidation_test.cc345
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_invalidator.cc273
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_invalidator.h53
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer.cc617
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer.h176
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.cc53
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.h6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc88
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_painter.cc573
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_painter.h24
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_painter_test.cc21
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_painting_info.h1
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc514
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h151
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc65
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node.cc204
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node.h89
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_layer_test.cc314
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_phase.h7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc239
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.h10
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc361
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.h20
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc117
-rw-r--r--chromium/third_party/blink/renderer/core/paint/paint_timing.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc111
-rw-r--r--chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h26
-rw-r--r--chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk_test.cc125
-rw-r--r--chromium/third_party/blink/renderer/core/paint/raster_invalidation_test.cc90
-rw-r--r--chromium/third_party/blink/renderer/core/paint/replaced_painter.cc100
-rw-r--r--chromium/third_party/blink/renderer/core/paint/replaced_painter.h7
-rw-r--r--chromium/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.h17
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scroll_recorder.cc40
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scroll_recorder.h42
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scrollable_area_painter.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scrollbar_manager.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scrollbar_manager.h56
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scrollbar_painter.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/paint/scrollbar_painter.h3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/selection_painting_utils.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/paint/stub_chrome_client_for_spv2.h12
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_container_painter.cc62
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_filter_painter.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc72
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_image_painter.cc32
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_inline_flow_box_painter.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_mask_painter.cc51
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_mask_painter.h4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_model_object_painter.cc46
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_model_object_painter.h35
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_paint_context.cc63
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_paint_context.h65
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_root_inline_box_painter.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_root_painter.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_root_painter.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_shape_painter.cc28
-rw-r--r--chromium/third_party/blink/renderer/core/paint/svg_text_painter.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/paint/table_cell_paint_invalidator.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/paint/table_cell_painter.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/paint/table_cell_painter.h3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/table_painter.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/paint/table_painter.h9
-rw-r--r--chromium/third_party/blink/renderer/core/paint/table_painter_test.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/paint/table_row_painter.cc59
-rw-r--r--chromium/third_party/blink/renderer/core/paint/table_row_painter.h14
-rw-r--r--chromium/third_party/blink/renderer/core/paint/table_section_painter.cc357
-rw-r--r--chromium/third_party/blink/renderer/core/paint/table_section_painter.h29
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_control_single_line_painter.cc49
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_control_single_line_painter.h29
-rw-r--r--chromium/third_party/blink/renderer/core/paint/text_painter_base.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/paint/theme_painter_default.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/paint/theme_painter_mac.mm10
-rw-r--r--chromium/third_party/blink/renderer/core/paint/transform_3d_recorder.cc41
-rw-r--r--chromium/third_party/blink/renderer/core/paint/transform_3d_recorder.h37
-rw-r--r--chromium/third_party/blink/renderer/core/paint/transform_recorder.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/paint/transform_recorder.h34
-rw-r--r--chromium/third_party/blink/renderer/core/paint/video_painter.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/video_painter.h2
-rw-r--r--chromium/third_party/blink/renderer/core/paint/video_painter_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/view_painter.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/paint/view_painter.h3
-rw-r--r--chromium/third_party/blink/renderer/core/paint/view_painter_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/policy/policy.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/policy/policy.h2
-rw-r--r--chromium/third_party/blink/renderer/core/policy/policy.idl8
-rw-r--r--chromium/third_party/blink/renderer/core/policy/policy_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/probe/CoreProbes.json522
-rw-r--r--chromium/third_party/blink/renderer/core/probe/CoreProbes.pidl25
-rw-r--r--chromium/third_party/blink/renderer/core/probe/core_probes.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/probe/core_probes.h25
-rw-r--r--chromium/third_party/blink/renderer/core/resize_observer/resize_observer.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/resize_observer/resize_observer.h1
-rw-r--r--chromium/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc79
-rw-r--r--chromium/third_party/blink/renderer/core/scheduler/throttling_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/script/BUILD.gn5
-rw-r--r--chromium/third_party/blink/renderer/core/script/classic_pending_script.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/script/classic_pending_script.h4
-rw-r--r--chromium/third_party/blink/renderer/core/script/classic_script.h2
-rw-r--r--chromium/third_party/blink/renderer/core/script/document_modulator_impl.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/script/document_modulator_impl.h8
-rw-r--r--chromium/third_party/blink/renderer/core/script/document_modulator_impl_test.cc98
-rw-r--r--chromium/third_party/blink/renderer/core/script/document_write_intervention.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/script/dynamic_module_resolver.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/script/fetch_client_settings_object.h55
-rw-r--r--chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.cc42
-rw-r--r--chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h46
-rw-r--r--chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.cc35
-rw-r--r--chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h97
-rw-r--r--chromium/third_party/blink/renderer/core/script/html_parser_script_runner.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/script/html_parser_script_runner.h5
-rw-r--r--chromium/third_party/blink/renderer/core/script/layered_api.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/script/modulator.cc49
-rw-r--r--chromium/third_party/blink/renderer/core/script/modulator.h94
-rw-r--r--chromium/third_party/blink/renderer/core/script/modulator_impl_base.cc163
-rw-r--r--chromium/third_party/blink/renderer/core/script/modulator_impl_base.h47
-rw-r--r--chromium/third_party/blink/renderer/core/script/modulator_test.cc73
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_map.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_map.h18
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_map_test.cc120
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_pending_script.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_pending_script.h2
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_script.cc36
-rw-r--r--chromium/third_party/blink/renderer/core/script/module_script.h18
-rw-r--r--chromium/third_party/blink/renderer/core/script/pending_script.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/script/pending_script.h28
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/README.chromium12
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/index.js163
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/layouts/layout-1d-base.js264
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/layouts/layout-1d-grid.js66
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/layouts/layout-1d.js329
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/virtual-list.js255
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/virtual-repeater.js522
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/README.chromium12
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/index.js213
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/item-source.js47
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d-base.js320
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d-grid.js64
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d.js349
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/virtual-repeater.js531
-rw-r--r--chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/virtual-scroller.js444
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_loader.cc178
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_loader.h9
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_module_resolver.h2
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_module_resolver_impl_test.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_runner.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_runner.h5
-rw-r--r--chromium/third_party/blink/renderer/core/script/script_scheduling_type.h6
-rw-r--r--chromium/third_party/blink/renderer/core/script/worker_modulator_impl.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/script/worker_modulator_impl.h7
-rw-r--r--chromium/third_party/blink/renderer/core/script/worklet_modulator_impl.cc27
-rw-r--r--chromium/third_party/blink/renderer/core/script/worklet_modulator_impl.h8
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_wrapper.h12
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_operations.cc272
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_operations.h115
-rw-r--r--chromium/third_party/blink/renderer/core/streams/readable_stream_operations_test.cc173
-rw-r--r--chromium/third_party/blink/renderer/core/style/BUILD.gn6
-rw-r--r--chromium/third_party/blink/renderer/core/style/OWNERS3
-rw-r--r--chromium/third_party/blink/renderer/core/style/clip_path_operation.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/style/clip_path_operation.h80
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style.h30
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style_constants.h16
-rw-r--r--chromium/third_party/blink/renderer/core/style/computed_style_test.cc68
-rw-r--r--chromium/third_party/blink/renderer/core/style/counter_directives.h4
-rw-r--r--chromium/third_party/blink/renderer/core/style/cursor_data.h3
-rw-r--r--chromium/third_party/blink/renderer/core/style/fill_layer.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/style/fill_layer.h1
-rw-r--r--chromium/third_party/blink/renderer/core/style/filter_operations.h1
-rw-r--r--chromium/third_party/blink/renderer/core/style/reference_clip_path_operation.cc30
-rw-r--r--chromium/third_party/blink/renderer/core/style/reference_clip_path_operation.h75
-rw-r--r--chromium/third_party/blink/renderer/core/style/shadow_data.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/style/shadow_data.h10
-rw-r--r--chromium/third_party/blink/renderer/core/style/shape_clip_path_operation.h84
-rw-r--r--chromium/third_party/blink/renderer/core/style/shape_value.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/style/shape_value.h9
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_difference.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_difference.h10
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_difference_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_generated_image.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_image.h4
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_inherited_variables.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_inherited_variables.h11
-rw-r--r--chromium/third_party/blink/renderer/core/style/style_non_inherited_variables.cc8
-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/svg_computed_style.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/style/svg_computed_style.h20
-rw-r--r--chromium/third_party/blink/renderer/core/style/svg_computed_style_defs.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/style/svg_computed_style_defs.h14
-rw-r--r--chromium/third_party/blink/renderer/core/svg/animation/smil_time_container.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/filters/svg_fe_image.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image.cc53
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image.h22
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc14
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h6
-rw-r--r--chromium/third_party/blink/renderer/core/svg/graphics/svg_image_test.cc76
-rw-r--r--chromium/third_party/blink/renderer/core/svg/properties/svg_animated_property.h3
-rw-r--r--chromium/third_party/blink/renderer/core/svg/properties/svg_list_property_helper.h12
-rw-r--r--chromium/third_party/blink/renderer/core/svg/properties/svg_list_property_tear_off_helper.h4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/properties/svg_property_tear_off.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/svg/properties/svg_property_tear_off.h9
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_a_element.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_angle_tear_off.cc19
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_angle.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_angle.h2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_boolean.h5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_enumeration_base.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_enumeration_base.h5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_integer.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_integer.h2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_length.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_length.h1
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_length_list.h5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_number.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_number.h2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_number_list.h5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_preserve_aspect_ratio.h5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_rect.h5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_string.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_string.h1
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animated_transform_list.h5
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_animation_element.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_ellipse_element.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fit_to_view_box.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_fit_to_view_box.h2
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_foreign_object_element.h6
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_geometry_element.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_length_tear_off.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_matrix_tear_off.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_matrix_tear_off.h1
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_parser_utilities.cc18
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_path_element.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_path_parser.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_path_parser_test.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_preserve_aspect_ratio_tear_off.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_script_element.cc6
-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_string_list.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_style_element.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_style_element.h1
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_svg_element.cc71
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_svg_element.h9
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_text_content_element.cc34
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_view_spec.cc58
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_view_spec.h42
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_zoom_and_pan.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/svg/svg_zoom_and_pan.h25
-rw-r--r--chromium/third_party/blink/renderer/core/testing/DEPS6
-rw-r--r--chromium/third_party/blink/renderer/core/testing/core_unit_test_helper.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/testing/core_unit_test_helper.h3
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/95-vh.html3
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/frameserialization/beautifull.css3
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/frameserialization/integrityfail.css3
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/frameserialization/link_integrity.html10
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/link-manifest-change.html2
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/origin-trial-dummy.html12
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/touch-action-blocking-handler.html8
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/touch-action-on-inline.html5
-rw-r--r--chromium/third_party/blink/renderer/core/testing/data/touch-action-with-vertical-rl-writing-mode.html6
-rw-r--r--chromium/third_party/blink/renderer/core/testing/death_aware_script_wrappable.h55
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dictionary_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dictionary_test.h2
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dummy_modulator.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dummy_modulator.h40
-rw-r--r--chromium/third_party/blink/renderer/core/testing/dummy_page_holder.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/testing/internal_settings.cc111
-rw-r--r--chromium/third_party/blink/renderer/core/testing/internals.cc455
-rw-r--r--chromium/third_party/blink/renderer/core/testing/internals.h24
-rw-r--r--chromium/third_party/blink/renderer/core/testing/internals.idl11
-rw-r--r--chromium/third_party/blink/renderer/core/testing/null_execution_context.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/testing/null_execution_context.h4
-rw-r--r--chromium/third_party/blink/renderer/core/testing/origin_trials_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.cc62
-rw-r--r--chromium/third_party/blink/renderer/core/testing/sim/sim_compositor.h67
-rw-r--r--chromium/third_party/blink/renderer/core/testing/sim/sim_request.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/testing/sim/sim_test.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/testing/sim/sim_test.h3
-rw-r--r--chromium/third_party/blink/renderer/core/testing/sim/sim_web_frame_client.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/testing/sim/sim_web_frame_client.h8
-rw-r--r--chromium/third_party/blink/renderer/core/testing/sim/sim_web_view_client.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/testing/sim/sim_web_view_client.h18
-rw-r--r--chromium/third_party/blink/renderer/core/testing/use_mock_scrollbar_settings.h51
-rw-r--r--chromium/third_party/blink/renderer/core/testing/v8/web_core_test_support.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/testing/worker_internals.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/timing/dom_window_performance.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/timing/dom_window_performance.h1
-rw-r--r--chromium/third_party/blink/renderer/core/timing/memory_info.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/timing/memory_info.h11
-rw-r--r--chromium/third_party/blink/renderer/core/timing/memory_info_test.cc151
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance.h7
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance.idl3
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_entry.cc109
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_entry.h32
-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.h6
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_long_task_timing.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_long_task_timing.h3
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_mark.cc17
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_mark.h7
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_measure.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_measure.h3
-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_timing.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_navigation_timing.h5
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_navigation_timing_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_observer.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_observer.h1
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_observer_entry_list.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_observer_entry_list.h5
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_paint_timing.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_paint_timing.h3
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_resource_timing.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_resource_timing.h4
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_timing.cc80
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_timing.h16
-rw-r--r--chromium/third_party/blink/renderer/core/timing/performance_user_timing.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/timing/task_attribution_timing.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/timing/task_attribution_timing.h4
-rw-r--r--chromium/third_party/blink/renderer/core/timing/window_performance.cc39
-rw-r--r--chromium/third_party/blink/renderer/core/timing/window_performance.h8
-rw-r--r--chromium/third_party/blink/renderer/core/timing/window_performance_test.cc77
-rw-r--r--chromium/third_party/blink/renderer/core/timing/worker_global_scope_performance.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/timing/worker_global_scope_performance.h1
-rw-r--r--chromium/third_party/blink/renderer/core/timing/worker_performance.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/BUILD.gn16
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.cc37
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.h38
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.idl (renamed from chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_html.idl)0
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.cc24
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.h38
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.idl (renamed from chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.idl)0
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_url.cc33
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_url.h37
-rw-r--r--chromium/third_party/blink/renderer/core/trustedtypes/trusted_url.idl (renamed from chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_url.idl)0
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/dom_data_view.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/dom_typed_array.h3
-rw-r--r--chromium/third_party/blink/renderer/core/typed_arrays/typed_flexible_array_buffer_view.h3
-rw-r--r--chromium/third_party/blink/renderer/core/url/dom_url.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/url/dom_url.h2
-rw-r--r--chromium/third_party/blink/renderer/core/url/dom_url_utils.cc25
-rw-r--r--chromium/third_party/blink/renderer/core/url/dom_url_utils.h5
-rw-r--r--chromium/third_party/blink/renderer/core/url/dom_url_utils_read_only.cc8
-rw-r--r--chromium/third_party/blink/renderer/core/url/dom_url_utils_read_only.h8
-rw-r--r--chromium/third_party/blink/renderer/core/url/url_search_params.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/workers/BUILD.gn4
-rw-r--r--chromium/third_party/blink/renderer/core/workers/abstract_worker.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/workers/abstract_worker.h1
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker.cc48
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker.h1
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc12
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h8
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h13
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/workers/dedicated_worker_thread.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/workers/execution_context_worker_registry.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/workers/global_scope_creation_params.cc26
-rw-r--r--chromium/third_party/blink/renderer/core/workers/global_scope_creation_params.h11
-rw-r--r--chromium/third_party/blink/renderer/core/workers/main_thread_worklet_global_scope.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/workers/main_thread_worklet_test.cc38
-rw-r--r--chromium/third_party/blink/renderer/core/workers/parent_execution_context_task_runners.cc9
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker.cc13
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker_global_scope.h8
-rw-r--r--chromium/third_party/blink/renderer/core/workers/shared_worker_repository_client.h2
-rw-r--r--chromium/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.cc2
-rw-r--r--chromium/third_party/blink/renderer/core/workers/threaded_worklet_global_scope.cc4
-rw-r--r--chromium/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc15
-rw-r--r--chromium/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.h1
-rw-r--r--chromium/third_party/blink/renderer/core/workers/threaded_worklet_object_proxy.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/workers/threaded_worklet_object_proxy.h3
-rw-r--r--chromium/third_party/blink/renderer/core/workers/threaded_worklet_test.cc52
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_animation_frame_provider.cc50
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_animation_frame_provider.h26
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_backing_thread.cc49
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_backing_thread.h21
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_classic_script_loader.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_event_queue.cc105
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_event_queue.h64
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_fetch_test_helper.h21
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_global_scope.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_global_scope.h17
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_navigator.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_navigator.h1
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_options.idl2
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc43
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h25
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_or_worklet_module_fetch_coordinator_proxy.cc116
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_or_worklet_module_fetch_coordinator_proxy.h52
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_thread.cc85
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_thread.h21
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_thread_test.cc124
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worker_thread_test_helper.h19
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet.cc22
-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.cc44
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet_global_scope.h14
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet_global_scope.idl1
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet_global_scope_proxy.h2
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet_module_responses_map.cc193
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet_module_responses_map.h92
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet_module_responses_map_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet_pending_tasks.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/workers/worklet_thread_holder.h6
-rw-r--r--chromium/third_party/blink/renderer/core/xml/document_xml_tree_viewer.cc6
-rw-r--r--chromium/third_party/blink/renderer/core/xml/document_xpath_evaluator.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/xml/dom_parser.cc29
-rw-r--r--chromium/third_party/blink/renderer/core/xml/dom_parser.h9
-rw-r--r--chromium/third_party/blink/renderer/core/xml/dom_parser.idl5
-rw-r--r--chromium/third_party/blink/renderer/core/xml/parser/shared_buffer_reader.cc20
-rw-r--r--chromium/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xpath_evaluator.cc10
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xpath_expression.cc11
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xpath_parser.cc7
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xpath_result.cc5
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xslt_processor.cc1
-rw-r--r--chromium/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc16
-rw-r--r--chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc104
-rw-r--r--chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h10
-rw-r--r--chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.cc8
-rw-r--r--chromium/third_party/blink/renderer/devtools/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/Runtime.js29
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2Controller.js35
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2ReportSelector.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits2/audits2Panel.css35
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/category-renderer.js39
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/details-renderer.js120
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/performance-category-renderer.js42
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/report-renderer.js60
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/report-styles.css1
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/audits2_worker/lighthouse/lighthouse-background.js19722
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/bindings/NetworkProject.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/browser_console/BrowserConsole.js7
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/ResourceType.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/common/Settings.js14
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleContextSelector.js10
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePinPane.js114
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js87
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js113
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleViewMessage.js29
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/consolePinPane.css62
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/consoleView.css62
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console/module.json4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/console_test_runner/ConsoleTestRunner.js30
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/devtools_app.html2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js14
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsPanel.js50
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeElement.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeOutline.js19
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js33
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/computedStyleSidebarPane.css14
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/elementsPanel.css2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/module.json36
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/elements/stylesSidebarPane.css5
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeToolbar.js7
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/externs.js53
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/heap_profiler_test_runner/HeapProfilerTestRunner.js60
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHost.js14
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/inspector.html2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/inspector_main/InspectorMain.js7
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/integration_test_runner.html2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/js_app.html2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/js_main/JsMain.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/main/Main.js18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/ThrottlingManager.js8
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/module.json20
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ndb_app.html2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js38
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogViewColumns.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/NetworkPanel.js1
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/NetworkWaterfallColumn.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/SignedExchangeInfoView.js106
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network/signedExchangeInfoTree.css10
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/network_test_runner/NetworkTestRunner.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/node_app.html2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/node_main/NodeMain.js5
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptAutocomplete.js97
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPopoverHelper.js119
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js51
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/object_ui/objectPropertiesSection.css5
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/perf_ui/FlameChart.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/platform/utilities.js111
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfileView.js113
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfilerPanel.js7
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotDataGrids.js97
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotGridNodes.js136
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js35
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/IsolateSelector.js52
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileLauncherView.js4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileType.js8
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileTypeRegistry.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileView.js29
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfilesPanel.js9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/heapProfiler.css45
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/profiler/profilesPanel.css19
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkersView.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/screencast/ScreencastView.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/CPUProfileDataModel.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSStyleDeclaration.js85
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/ChildTargetManager.js11
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMDebuggerModel.js11
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMModel.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/DebuggerModel.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/HeapProfilerModel.js16
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkManager.js12
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkRequest.js82
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/ProfileTreeModel.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/RemoteObject.js3
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/ResourceTreeModel.js8
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/RuntimeModel.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/ScreenCaptureModel.js8
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/Target.js11
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/TargetManager.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sdk/TracingModel.js31
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourceFrame.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js47
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/callStackSidebarPane.css8
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/navigatorTree.css4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources/watchExpressionsSidebarPane.css6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/EditorTestRunner.js21
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js96
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/text_editor/TextEditorAutocompleteController.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineController.js72
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineHistoryManager.js1
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelinePanel.js12
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline/timelinePanel.css11
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js8
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineProfileTree.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/toolbox.html2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/FilterBar.js4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/Fragment.js41
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/Panel.js12
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutRegistry.js15
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutsScreen.js9
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/SuggestBox.js6
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/TextEditor.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js26
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/Tooltip.js4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js26
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/filter.css18
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css24
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/softContextMenu.css1
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/suggestBox.css4
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/toolbar.css12
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/tooltip.css1
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/ui/treeoutline.js34
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/worker_app.html2
-rw-r--r--chromium/third_party/blink/renderer/devtools/front_end/worker_main/WorkerMain.js2
-rw-r--r--chromium/third_party/blink/renderer/devtools/readme.md1
-rwxr-xr-xchromium/third_party/blink/renderer/devtools/scripts/build/generate_protocol_externs.py5
-rw-r--r--chromium/third_party/blink/renderer/devtools/scripts/hosted_mode/server.js2
-rw-r--r--chromium/third_party/blink/renderer/modules/BUILD.gn22
-rw-r--r--chromium/third_party/blink/renderer/modules/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/BUILD.gn16
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/accessibility_object_model_test.cc17
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid.cc121
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid.h72
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid_cell.cc168
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid_cell.h69
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid_row.cc116
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid_row.h80
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_enums.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_enums.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_image_map_link.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_inline_text_box.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc798
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_layout_object.h33
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_list_box_option.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc16
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.cc17
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list_popup.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_mock_object.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_node_object.cc138
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_node_object.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_object.cc437
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_object.h220
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc155
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h21
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_object_cache_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_object_test.cc66
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_position.cc400
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_position.h78
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_position_test.cc887
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_progress_indicator.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_radio_input.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_range.cc15
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc47
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_relation_cache.h32
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_selection.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_selection.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_table.cc599
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_table.h103
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_table_cell.cc264
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_table_cell.h85
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_table_column.cc153
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_table_column.h81
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_table_header_container.cc71
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_table_header_container.h62
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_table_row.cc150
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_table_row.h80
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_virtual_object.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/ax_virtual_object.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.cc264
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.h48
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/BUILD.gn6
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet.cc20
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.cc140
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc153
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_impl.cc29
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_impl.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_thread_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animator.cc12
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animator.h11
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animator_definition.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/animator_definition.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/css_animation_worklet.cc61
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/css_animation_worklet.h44
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/css_animation_worklet.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/window_animation_worklet.cc59
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/window_animation_worklet.h44
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/window_animation_worklet.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc91
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.h22
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_options.cc21
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_options.h30
-rw-r--r--chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_test.cc17
-rw-r--r--chromium/third_party/blink/renderer/modules/app_banner/app_banner_controller.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/app_banner/app_banner_controller.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.cc32
-rw-r--r--chromium/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.h14
-rw-r--r--chromium/third_party/blink/renderer/modules/audio_output_devices/audio_output_device_client_impl.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/audio_output_devices/html_media_element_audio_output_device.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/audio_output_devices/html_media_element_audio_output_device.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/audio_output_devices/set_sink_id_callbacks.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_event.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.cc11
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader_test.cc41
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc27
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_manager_test.cc46
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_options.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_settled_event.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_settled_fetches_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.cc54
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.h20
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetched_event.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/background_fetched_event.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/icon_definition.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/background_fetch/service_worker_registration_background_fetch.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/background_sync/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/background_sync/sync_event.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/background_sync/sync_manager.cc27
-rw-r--r--chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/battery/battery_manager.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/battery/navigator_battery.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/beacon/navigator_beacon.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_characteristic_properties.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_device.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_error.cc111
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.cc19
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_descriptor.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_descriptor.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.cc28
-rw-r--r--chromium/third_party/blink/renderer/modules/bluetooth/navigator_bluetooth.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.cc15
-rw-r--r--chromium/third_party/blink/renderer/modules/budget/budget_service.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/cache.cc103
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/cache.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/cache_storage.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/cache_storage_error.cc21
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/cache_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc120
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h24
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_gradient.cc12
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.cc112
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_pattern.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc39
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_api_test.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc56
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/clip_list.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/clip_list.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/hit_region.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/canvas2d/path_2d.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module_support_webgl2_compute.idl25
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module_support_webgl2_compute.idl17
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc48
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/clipboard/clipboard_promise.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/BUILD.gn7
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/cookie_change_event.cc71
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/cookie_change_event.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/cookie_change_event.idl7
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/cookie_list_item.idl7
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.cc380
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.h54
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.idl30
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/cookie_store_delete_options.idl13
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/cookie_store_get_options.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/cookie_store_set_extra_options.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/cookie_store_set_options.idl13
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.cc19
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.h13
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/global_cookie_store.cc114
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/global_cookie_store.h29
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/global_cookie_store_impl.h71
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.cc40
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.h28
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/window_cookie_store.cc34
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/window_cookie_store.h25
-rw-r--r--chromium/third_party/blink/renderer/modules/cookie_store/window_cookie_store.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/authentication_extensions_client_inputs.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/cable_authentication_data.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/cable_registration_data.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/credential.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.cc124
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.h84
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc163
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc36
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/federated_credential.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/password_credential.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/password_credential_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/public_key_credential.cc29
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/public_key_credential_creation_options.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/scoped_promise_resolver.cc31
-rw-r--r--chromium/third_party/blink/renderer/modules/credentialmanager/scoped_promise_resolver.h38
-rw-r--r--chromium/third_party/blink/renderer/modules/crypto/crypto.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/crypto/crypto_key.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/crypto/crypto_result_impl.cc30
-rw-r--r--chromium/third_party/blink/renderer/modules/crypto/crypto_result_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/crypto/normalize_algorithm.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.h11
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/css_paint_worklet.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.cc35
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h13
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_size.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc22
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/BUILD.gn5
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/DEPS10
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_motion_controller.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_motion_controller.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_motion_data.cc20
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_motion_data.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_motion_dispatcher.cc21
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_motion_dispatcher.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.cc140
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h48
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc425
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.cc16
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.cc213
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h61
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc1011
-rw-r--r--chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h344
-rw-r--r--chromium/third_party/blink/renderer/modules/document_metadata/copyless_paste_extractor.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/encoding/text_decoder.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/encoding/text_encoder.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/content_decryption_module_result_promise.cc42
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/content_decryption_module_result_promise.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/encrypted_media_utils.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.cc23
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc69
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_session.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access.cc24
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_system_media_capability.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc29
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys_controller.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys_get_status_for_policy.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.cc31
-rw-r--r--chromium/third_party/blink/renderer/modules/event_target_modules_names.json59
-rw-r--r--chromium/third_party/blink/renderer/modules/eventsource/event_source.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/eventsource/event_source.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/eventsource/event_source_parser.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/exported/BUILD.gn4
-rw-r--r--chromium/third_party/blink/renderer/modules/exported/web_ax_object.cc130
-rw-r--r--chromium/third_party/blink/renderer/modules/exported/web_crypto_normalize.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/exported/web_dom_file_system.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc37
-rw-r--r--chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/exported/web_speech_grammar.cc56
-rw-r--r--chromium/third_party/blink/renderer/modules/exported/web_speech_recognition_handle.cc59
-rw-r--r--chromium/third_party/blink/renderer/modules/exported/web_speech_recognition_result.cc63
-rw-r--r--chromium/third_party/blink/renderer/modules/exported/web_speech_recognizer_client.cc98
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/directory_entry_sync.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/directory_reader.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/directory_reader_sync.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/dom_file_system_sync.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/entry_sync.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/file_entry_sync.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/file_writer.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/file_writer_sync.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/local_file_system.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/local_file_system.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/filesystem/worker_global_scope_file_system.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/DEPS6
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/gamepad.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/gamepad.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/gamepad.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.cc20
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h17
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/gamepad_pose.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.cc140
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.h56
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc56
-rw-r--r--chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.cc15
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geolocation.cc40
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geolocation.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geolocation_watchers.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/geolocation_watchers.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/navigator_geolocation.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/geolocation/navigator_geolocation.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/imagecapture/image_capture.cc133
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/OWNERS3
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc73
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_database.cc94
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_database.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_factory.cc19
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_index.cc64
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_key_range.cc24
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_key_range.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc200
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_object_store.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_observation.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_observer.cc19
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_observer.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_observer_changes.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_request.cc50
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_request.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_request_loader.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.cc31
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction_test.cc20
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_client.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_client.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc68
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database_callbacks_impl.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/installedapp/navigator_installed_app.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/keyboard/keyboard.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.cc75
-rw-r--r--chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout_map.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.cc54
-rw-r--r--chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/keyboard/navigator_keyboard.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/locks/OWNERS3
-rw-r--r--chromium/third_party/blink/renderer/modules/locks/lock.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/locks/lock.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/locks/lock_manager.cc70
-rw-r--r--chromium/third_party/blink/renderer/modules/locks/lock_manager.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/locks/lock_manager.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/locks/lock_options.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/locks/navigator_locks.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/locks/navigator_locks.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/locks/worker_navigator_locks.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/BUILD.gn12
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/image_resource.idl14
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/image_resource_type_converters.cc107
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/image_resource_type_converters.h24
-rw-r--r--chromium/third_party/blink/renderer/modules/manifest/image_resource_type_converters_test.cc189
-rw-r--r--chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_download_button_element.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_element_type.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_fullscreen_button_element.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.cc38
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.cc30
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_scrubbing_message_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_slider_element.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_metrics.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.cc30
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_display_cutout_delegate.cc170
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_display_cutout_delegate.h76
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_display_cutout_delegate_test.cc315
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl.cc83
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl_test.cc40
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_media_event_listener.cc22
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/resources/ic_picture_in_picture_exit.svg6
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/resources/ic_subtitles.svg4
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/resources/mediaInterstitials.css45
-rw-r--r--chromium/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css34
-rw-r--r--chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_canvas_element_capture.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc29
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc25
-rw-r--r--chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasession/media_metadata.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasession/media_metadata.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasession/media_session.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasession/media_session.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/media_source.cc64
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/media_source.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/source_buffer.cc136
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/source_buffer.h11
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/source_buffer.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/source_buffer_list.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/source_buffer_list.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/track_default.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediasource/track_default_list.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_constraints_impl.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_devices.cc16
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_devices_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_error_state.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_error_state.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream.cc62
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream.h15
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_stream_track.cc21
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/media_track_settings.idl14
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/navigator_media_stream.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/user_media_client.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/mediastream/user_media_request.cc34
-rw-r--r--chromium/third_party/blink/renderer/modules/modules_export.h27
-rw-r--r--chromium/third_party/blink/renderer/modules/modules_idl_files.gni93
-rw-r--r--chromium/third_party/blink/renderer/modules/modules_initializer.cc24
-rw-r--r--chromium/third_party/blink/renderer/modules/modules_initializer.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/navigatorcontentutils/testing/navigator_content_utils_client_mock.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/netinfo/network_information.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/navigator_nfc.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/navigator_nfc.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/nfc.cc40
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/nfc.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/nfc/nfc_error.cc20
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/notification.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/notification.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/notification_data.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/notification_data_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/notification_event.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/notification_image_loader.cc36
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/notification_image_loader.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/notification_manager.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/notifications/service_worker_registration_notifications.cc29
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/abort_payment_event.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/abort_payment_event.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.cc17
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/address_errors.idl20
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/basic_card_helper.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/basic_card_helper.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/can_make_payment_event.cc16
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/can_make_payment_event.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.cc17
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/complete_test.cc31
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payer_error_fields.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_app_service_worker_registration.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_app_service_worker_registration.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_completer.h28
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_details_modifier.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion_test.cc33
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_handler_utils.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_instruments.cc54
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_manager.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_method_data.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request.cc244
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request_details_test.cc170
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request_event.cc23
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request_event.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.cc17
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request_update_event.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_response.cc29
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_response.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_response.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_response_test.cc40
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_state_resolver.h30
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_test_helper.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_test_helper.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/payments/payment_validation_errors.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_init.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.cc29
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_error_util.cc76
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_error_util.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_ice_candidate.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc874
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h132
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_test.cc69
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtcp_parameters.idl9
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_capabilities.idl9
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_codec_capability.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_codec_parameters.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_coding_parameters.idl8
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_encoding_parameters.idl7
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_header_extension_capability.idl8
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_header_extension_parameters.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_parameters.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc73
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_send_parameters.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc175
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h25
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.cc200
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.h78
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.idl22
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_init.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_session_description_request_impl.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_session_description_request_promise_impl.cc27
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_session_description_request_promise_impl.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event.cc15
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event_init.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_impl.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_impl.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_promise_impl.cc24
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_promise_impl.h11
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_script_promise_resolver_impl.cc24
-rw-r--r--chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_script_promise_resolver_impl.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/permissions/permissions.cc45
-rw-r--r--chromium/third_party/blink/renderer/modules/permissions/permissions.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/permissions/permissions.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/picture_in_picture/OWNERS5
-rw-r--r--chromium/third_party/blink/renderer/modules/picture_in_picture/document_picture_in_picture.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/picture_in_picture/document_picture_in_picture.idl6
-rw-r--r--chromium/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.cc30
-rw-r--r--chromium/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.idl8
-rw-r--r--chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc44
-rw-r--r--chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_window.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/picture_in_picture/shadow_root_picture_in_picture.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/plugins/dom_plugin_array.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_availability_callbacks.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_availability_state.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_connection.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_connection.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_error.cc11
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_receiver.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_request.cc37
-rw-r--r--chromium/third_party/blink/renderer/modules/presentation/presentation_request_test.cc62
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_error.cc24
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_event.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_manager.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_message_data.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_bridge.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_bridge.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_subscription.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_subscription_callbacks.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_subscription_options.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/push_subscription_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/service_worker_registration_push.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/push_messaging/service_worker_registration_push.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/quota/deprecated_storage_info.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/quota/deprecated_storage_quota.cc21
-rw-r--r--chromium/third_party/blink/renderer/modules/quota/deprecated_storage_quota.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/quota/dom_error.cc11
-rw-r--r--chromium/third_party/blink/renderer/modules/quota/dom_error.h13
-rw-r--r--chromium/third_party/blink/renderer/modules/quota/storage_manager.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/remoteplayback/availability_callback_wrapper.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/remoteplayback/availability_callback_wrapper.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc57
-rw-r--r--chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_orientation/lock_orientation_callback.cc19
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_dispatcher.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_dispatcher.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/README.md4
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/absolute_orientation_sensor.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/accelerometer.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/gyroscope.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/linear_acceleration_sensor.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/orientation_sensor.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/orientation_sensor.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/relative_orientation_sensor.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor_error_event.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor_inspector_agent.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.cc31
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.h9
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.cc22
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/BUILD.gn66
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/DEPS21
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/OWNERS5
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/README.md6
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/client.idl (renamed from chromium/third_party/blink/renderer/modules/serviceworkers/client.idl)0
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/client_query_options.idl (renamed from chromium/third_party/blink/renderer/modules/serviceworkers/client_query_options.idl)0
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/clients.idl (renamed from chromium/third_party/blink/renderer/modules/serviceworkers/clients.idl)0
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/extendable_event.cc84
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/extendable_event.h71
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/extendable_event.idl (renamed from chromium/third_party/blink/renderer/modules/serviceworkers/extendable_event.idl)0
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/extendable_event_init.idl (renamed from chromium/third_party/blink/renderer/modules/serviceworkers/extendable_event_init.idl)0
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/extendable_message_event.cc133
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/extendable_message_event.h81
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/extendable_message_event.idl (renamed from chromium/third_party/blink/renderer/modules/serviceworkers/extendable_message_event.idl)0
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/extendable_message_event_init.idl (renamed from chromium/third_party/blink/renderer/modules/serviceworkers/extendable_message_event_init.idl)0
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/fetch_event.cc195
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/fetch_event.h105
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/fetch_event.idl (renamed from chromium/third_party/blink/renderer/modules/serviceworkers/fetch_event.idl)0
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/fetch_event_init.idl (renamed from chromium/third_party/blink/renderer/modules/serviceworkers/fetch_event_init.idl)0
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc347
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.h67
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/install_event.cc42
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/install_event.h40
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/install_event.idl (renamed from chromium/third_party/blink/renderer/modules/serviceworkers/install_event.idl)0
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_callbacks.cc90
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_callbacks.h67
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_manager.cc70
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_manager.h42
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_manager.idl (renamed from chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_manager.idl)0
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_state.idl (renamed from chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_state.idl)0
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/navigator_service_worker.cc142
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/navigator_service_worker.h52
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/navigator_service_worker.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/registration_options.idl (renamed from chromium/third_party/blink/renderer/modules/serviceworkers/registration_options.idl)0
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.cc101
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.h87
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker.cc168
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker.h103
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker.idl54
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_client.cc105
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_client.h61
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_clients.cc193
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_clients.h36
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.cc474
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.h120
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.idl44
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_client.cc67
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_client.h62
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc404
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_content_settings_proxy.cc46
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_content_settings_proxy.h48
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_error.cc152
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_error.h64
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc414
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h181
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.idl49
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.cc305
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h172
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc703
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h218
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc71
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.h33
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_registration.cc184
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_registration.h129
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_registration.idl32
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.cc72
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.h53
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.cc80
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.h81
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client.cc94
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client.h52
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client_callback.cc43
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client_callback.h31
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/testing/internals_service_worker.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/testing/internals_service_worker.h28
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/testing/internals_service_worker.idl (renamed from chromium/third_party/blink/renderer/modules/serviceworkers/testing/internals_service_worker.idl)0
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.cc326
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.h119
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc366
-rw-r--r--chromium/third_party/blink/renderer/modules/service_worker/window_client.idl (renamed from chromium/third_party/blink/renderer/modules/serviceworkers/window_client.idl)0
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/BUILD.gn66
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/DEPS21
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/OWNERS4
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/extendable_event.cc83
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/extendable_event.h71
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/extendable_message_event.cc133
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/extendable_message_event.h81
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/fetch_event.cc216
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/fetch_event.h105
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/fetch_respond_with_observer.cc309
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/fetch_respond_with_observer.h63
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/install_event.cc43
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/install_event.h40
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_callbacks.cc90
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_callbacks.h67
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_manager.cc70
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_manager.h42
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/navigator_service_worker.cc127
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/navigator_service_worker.h52
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/navigator_service_worker.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/respond_with_observer.cc94
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/respond_with_observer.h81
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker.cc169
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker.h103
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker.idl53
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_client.cc105
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_client.h61
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_clients.cc194
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_clients.h36
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container.cc512
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container.h126
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container.idl42
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container_client.cc67
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container_client.h66
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container_test.cc422
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_content_settings_proxy.cc46
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_content_settings_proxy.h48
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_error.cc153
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_error.h64
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.cc399
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.h179
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.idl49
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.cc305
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.h172
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_proxy.cc694
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_proxy.h218
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_installed_scripts_manager.cc71
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_installed_scripts_manager.h33
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_registration.cc182
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h129
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_registration.idl31
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_script_cached_metadata_handler.cc72
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_script_cached_metadata_handler.h53
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_thread.cc80
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_thread.h81
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_window_client.cc95
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_window_client.h52
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_window_client_callback.cc43
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_window_client_callback.h30
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/testing/internals_service_worker.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/testing/internals_service_worker.h28
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/wait_until_observer.cc327
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/wait_until_observer.h118
-rw-r--r--chromium/third_party/blink/renderer/modules/serviceworkers/web_embedded_worker_impl_test.cc366
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.cc20
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/detected_face.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/detected_face.h16
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/detected_face.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/detected_text.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/detected_text.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/detected_text.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/face_detector.cc12
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/shape_detector.cc41
-rw-r--r--chromium/third_party/blink/renderer/modules/shapedetection/text_detector.cc12
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_grammar_list.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_recognition.cc157
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_recognition.h40
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_recognition_client.h61
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_recognition_client_proxy.cc168
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_recognition_client_proxy.h90
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.cc54
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.h33
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_recognition_error.cc48
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_recognition_error.h19
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_recognition_event.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_synthesis.cc66
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_synthesis.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/speech/speech_synthesis.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/BUILD.gn25
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/OWNERS4
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/README.md25
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/dom_window_storage.cc36
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/dom_window_storage.h18
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/inspector_dom_storage_agent.cc63
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/inspector_dom_storage_agent.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage.cc78
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage.h85
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage.idl1
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage_area.cc236
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage_area.h69
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage_area_map.cc118
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage_area_map.h60
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage_area_map_test.cc132
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage_event.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage_event.h14
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage_namespace.cc19
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage_namespace.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage_namespace_controller.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/storage/storage_namespace_controller.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/vibration/navigator_vibration.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/vibration/vibration_controller.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/OWNERS4
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/PRESUBMIT.py24
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/navigator_vr.cc34
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/navigator_vr.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_controller.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_controller.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_display.cc232
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_display.h28
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_display.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_display_capabilities.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_display_event.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_eye_parameters.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_frame_data.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_pose.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/vr/vr_stage_parameters.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/analyser_node.cc29
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/analyser_node.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/async_audio_decoder.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_basic_inspector_node.cc28
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_basic_inspector_node.h14
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_buffer.cc90
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_context.cc244
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_context.h72
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_context_autoplay_test.cc732
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_context_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_destination_node.cc78
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_destination_node.h110
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_node.cc111
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_node.h20
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_node_output.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_param_map.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc33
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.cc33
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor_definition.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor_definition.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.cc182
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.h119
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/base_audio_context_test.cc732
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/biquad_filter_node.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/channel_merger_node.cc23
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/channel_splitter_node.cc25
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/constant_source_node.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/convolver_node.cc34
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/convolver_node.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/convolver_node_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.cc184
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.h45
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/delay_node.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/dynamics_compressor_node.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/iir_filter_node.cc18
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/media_stream_audio_destination_node.cc17
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/media_stream_audio_source_node.cc12
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc77
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/offline_audio_context.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc16
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/oscillator_node.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/panner_node.cc31
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/periodic_wave.cc15
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/realtime_analyser.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/script_processor_node.cc61
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/script_processor_node.h6
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/stereo_panner_node.cc19
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_dsp_kernel.cc67
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_dsp_kernel.h18
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_node.cc12
-rw-r--r--chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_processor.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/database.cc215
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/database.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/database_manager.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/dom_window_web_database.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/inspector_database_agent.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/sql_result_set.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/sql_result_set_row_list.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/BUILD.gn9
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/oes_vertex_array_object.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.cc157
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.h88
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc63
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h61
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl65
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.cc7
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc112
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h13
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_active_info.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_buffer.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_context_attribute_helpers.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_context_attribute_helpers.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_context_group.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_context_group.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_context_object.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_context_object.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_debug_shaders.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_fence_sync.cc17
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_fence_sync.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_framebuffer.cc13
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_framebuffer.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_framebuffer.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_program.cc6
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_program.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_program.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_query.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_renderbuffer.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc284
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h45
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_sampler.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_shader.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_shader_precision_format.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_shared_object.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_shared_object.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_sync.cc19
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_sync.h8
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_sync.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_texture.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_uniform_location.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_vertex_array_object.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_vertex_array_object_base.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/webgl/webgl_vertex_array_object_base.h1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/BUILD.gn18
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/OWNERS5
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/README.md7
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/webgpu.cc23
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/webgpu.h30
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/webgpu.idl9
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/webgpu_adapter.cc26
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/webgpu_adapter.h34
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/webgpu_adapter.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/webgpu_adapter_descriptor.idl13
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/webgpu_device.cc27
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/webgpu_device.h33
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/webgpu_device.idl9
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/window_webgpu.cc45
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/window_webgpu.h37
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/window_webgpu.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/webmidi/midi_access_initializer.cc14
-rw-r--r--chromium/third_party/blink/renderer/modules/webmidi/midi_output.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/webmidi/midi_port.cc12
-rw-r--r--chromium/third_party/blink/renderer/modules/webmidi/midi_port.h4
-rw-r--r--chromium/third_party/blink/renderer/modules/webmidi/midi_port_map.h2
-rw-r--r--chromium/third_party/blink/renderer/modules/webmidi/navigator_web_midi.cc8
-rw-r--r--chromium/third_party/blink/renderer/modules/webshare/navigator_share.cc10
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/dom_websocket.cc47
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/dom_websocket_test.cc503
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc21
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/websocket_handle_client.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/websockets/websocket_handle_impl.cc38
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/navigator_usb.cc1
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb.cc80
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_alternate_interface.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_alternate_interface.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_configuration.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_configuration.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_connection_event.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_device.cc179
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_device.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_endpoint.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_endpoint.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_in_transfer_result.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_interface.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_interface.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_in_transfer_packet.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_in_transfer_result.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_out_transfer_packet.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_out_transfer_result.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/usb_out_transfer_result.idl5
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/worker_navigator_usb.cc33
-rw-r--r--chromium/third_party/blink/renderer/modules/webusb/worker_navigator_usb.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/BUILD.gn8
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/OWNERS3
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/PRESUBMIT.py24
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr.cc43
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_canvas_input_provider.cc11
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_canvas_input_provider.h5
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_device.cc162
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_device.h34
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_device.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame.cc129
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame.h47
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame.idl16
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame_of_reference.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame_of_reference.idl4
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame_provider.cc407
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame_provider.h63
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame_request_callback.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.cc17
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_hit_result.cc25
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_hit_result.h29
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_hit_result.idl7
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_input_pose.cc9
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_input_pose.h7
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_input_pose.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_input_source.cc44
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_input_source.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_input_source.idl8
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_input_source_event.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_input_source_event.h12
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_input_source_event.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_input_source_event_init.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_presentation_context.cc2
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_presentation_frame.cc131
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_presentation_frame.h47
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_presentation_frame.idl16
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_ray.cc39
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_ray.h37
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_ray.idl10
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_session.cc250
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_session.h67
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_session.idl11
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_session_creation_options.idl3
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_view.cc4
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer.cc67
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer.h3
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer.idl2
-rw-r--r--chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer_init.idl2
-rw-r--r--chromium/third_party/blink/renderer/platform/BUILD.gn156
-rw-r--r--chromium/third_party/blink/renderer/platform/DEPS8
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_animation.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_animation.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_animation_host_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline_test.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_destination.cc38
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_destination.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_dsp_kernel_processor.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/audio_io_callback.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/biquad.cc18
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_impl.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_x86.h413
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_x8_6.h413
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/down_sampler.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/down_sampler.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/equal_power_panner.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/fft_frame.cc49
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/iir_filter.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.cc61
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.h58
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/sinc_resampler.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/stereo_panner.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/up_sampler.cc49
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/up_sampler.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/audio/vector_math.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/README.md6
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/TraceWrapperReference.md176
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/callback_function_base.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/callback_function_base.h18
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.h18
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/dom_data_store.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_map.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/exception_code.h156
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/exception_messages.cc186
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/exception_messages.h185
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/exception_state.cc282
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/exception_state.h255
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/name_client.h29
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.cc19
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.h22
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/scoped_persistent.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_state.cc53
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_state.h95
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_wrappable.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_wrappable.h16
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.cc38
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.h77
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_wrappable_visitor.cc28
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_wrappable_visitor.h106
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/script_wrappable_visitor_verifier.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/string_resource.cc24
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/string_resource.h78
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/to_v8.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_base.h32
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_member.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_string.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_string.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_binding.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_dom_activity_logger.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_per_context_data.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_per_context_data.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_private_property.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_value_cache.cc83
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/v8_value_cache.h49
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/OWNERS2
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/blob_data.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/blob_data.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/blob_registry.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.cc52
-rw-r--r--chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/clipboard/DEPS12
-rw-r--r--chromium/third_party/blink/renderer/platform/clipboard/clipboard_mime_types.cc46
-rw-r--r--chromium/third_party/blink/renderer/platform/clipboard/clipboard_mime_types.h51
-rw-r--r--chromium/third_party/blink/renderer/platform/clipboard/clipboard_utilities.cc91
-rw-r--r--chromium/third_party/blink/renderer/platform/clipboard/clipboard_utilities.h50
-rw-r--r--chromium/third_party/blink/renderer/platform/clipboard/clipboard_utilities_win.cc48
-rw-r--r--chromium/third_party/blink/renderer/platform/cross_thread_copier.h21
-rw-r--r--chromium/third_party/blink/renderer/platform/decimal.cc1007
-rw-r--r--chromium/third_party/blink/renderer/platform/decimal.h194
-rw-r--r--chromium/third_party/blink/renderer/platform/decimal_test.cc1161
-rw-r--r--chromium/third_party/blink/renderer/platform/drag_image.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/drag_image_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/event_dispatch_forbidden_scope.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h74
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/DEPS7
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/platform.cc29
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_active_gesture_animation.cc63
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_active_gesture_animation.h71
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_canonical_cookie.cc161
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_canonical_cookie_test.cc114
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_cors.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_cursor_info.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_data.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_font.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_image.cc78
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_image_test.cc34
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_media_constraints.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_media_stream.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_prerendering_support.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_rtc_rtp_transceiver.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_runtime_features.cc76
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_security_origin.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_service_worker_installed_scripts_manager.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_service_worker_request.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_service_worker_response.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_service_worker_stream_handle.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_surface_layer_bridge.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_url_request.cc62
-rw-r--r--chromium/third_party/blink/renderer/platform/exported/web_url_response.cc32
-rw-r--r--chromium/third_party/blink/renderer/platform/feature_policy/feature_policy.cc184
-rw-r--r--chromium/third_party/blink/renderer/platform/feature_policy/feature_policy.h40
-rw-r--r--chromium/third_party/blink/renderer/platform/feature_policy/feature_policy_test.cc225
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/README.md4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/accept_languages_resolver.cc42
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/accept_languages_resolver.h27
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/accept_languages_resolver_test.cc65
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/cursor_position_test.cc457
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font.cc34
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font.h43
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_cache.cc18
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_cache.h21
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_cache_key.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_cache_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_custom_platform_data.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_description.cc23
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_description.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_global_context.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_global_context.h65
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_platform_data.cc20
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_platform_data.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_test.cc40
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/font_vertical_position_type.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm1
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support_mpl.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_types.h22
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.cc47
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/script_run_iterator_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harf_buzz_buffer_filler.cc94
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harf_buzz_buffer_filler.h42
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.cc94
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.h42
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_face.cc448
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_face.h87
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_font_cache.h151
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.cc974
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.h119
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper_fuzzer.cc52
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper_test.cc1371
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc448
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h87
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h151
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc1017
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h113
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_fuzzer.cc52
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc1514
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.cc28
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h16
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter_test.cc105
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc743
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.h123
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc45
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h162
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_test_info.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_test_info.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc243
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h70
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker_test.cc100
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/simple_font_data.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/simple_font_data.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/symbols_iterator_test.cc433
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/vdmx_parser.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/web_font_typeface_factory.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/double_size.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_point.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_point.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_polygon.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_polygon.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_polygon_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_quad.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_rect.cc28
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_rect.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_rect_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_rounded_rect.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/float_rounded_rect.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/int_point.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/int_point.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/int_rect.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/layout_rect_outsets.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/geometry/layout_rect_outsets.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/DEPS4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/bitmap_image.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/box_reflection.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/box_reflection.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc189
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h25
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc729
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.cc44
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc468
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource.h189
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc488
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h136
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.cc30
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.h24
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc323
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h44
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/canvas_resource_test.cc171
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/color.cc172
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc105
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/color_space_profile_data.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper_test.cc52
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/composited_layer_raster_invalidator.cc337
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/composited_layer_raster_invalidator.h144
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/composited_layer_raster_invalidator_test.cc681
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc60
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc1397
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc295
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc39
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_animator.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_animators_state.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_element_id_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.cc19
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_client.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_impl.cc79
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_impl.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_impl_test.cc290
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/contiguous_container.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/contiguous_container.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/decoding_image_generator.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.cc19
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test_wo_platform.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/draw_looper_builder.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/filter.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/light_source.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/filters/source_graphic.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/PRESUBMIT.py24
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc115
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h31
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.cc43
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc33
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/shared_context_rate_limiter.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc57
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc24
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc79
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gradient.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc101
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_context.h28
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_context_state.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_context_test.cc50
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc551
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h108
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_layer_client.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc97
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image.cc177
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image.h73
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_data_buffer.cc15
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_decoding_store.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_frame_generator.cc51
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_frame_generator.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_layer_chromium_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/image_pattern.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/intercepting_canvas.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/logging_canvas.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher.cc483
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher.h136
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher_test.cc36
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.cc15
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.cc91
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/clip_display_item.cc66
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/clip_display_item.h76
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h33
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/clip_path_display_item.cc54
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/clip_path_display_item.h60
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/clip_path_recorder.cc29
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/clip_path_recorder.h32
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/clip_recorder.cc31
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/clip_recorder.h35
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/compositing_display_item.cc77
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/compositing_display_item.h82
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/compositing_recorder.cc36
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/compositing_recorder.h41
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item.cc90
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item.h185
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_client.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_client.h146
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.h24
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.cc255
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.h70
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc639
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item_test.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder_test.cc24
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.cc32
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h30
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/filter_display_item.cc76
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/filter_display_item.h77
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_display_item.cc48
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_display_item.h64
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc235
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.cc32
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc62
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h105
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_canvas.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.cc38
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.h38
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc68
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc727
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.h227
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_debug_data.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc1063
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h22
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node.h34
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node_test.cc424
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h38
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder_test.cc21
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state_test.cc30
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc359
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h158
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator_test.cc691
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/ref_counted_property_tree_state.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scoped_display_item_fragment.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scroll_display_item.cc46
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scroll_display_item.h65
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc19
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.cc15
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.h28
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/subsequence_recorder.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.cc56
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.h75
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/transform_display_item.cc47
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/transform_display_item.h60
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h24
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h27
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/path.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/path.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/pattern.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/picture_snapshot.cc38
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/picture_snapshot.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/placeholder_image.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/profiling_canvas.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/profiling_canvas.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/skia/image_pixel_locker.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc144
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc140
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.h27
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.h18
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc218
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.h82
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc445
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/BUILD.gn2
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/blink_gc.h8
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/garbage_collected.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/gc_info.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap.cc248
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap.h75
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_allocator.h54
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_compact.cc55
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_compact.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_page.cc231
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_page.h176
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.cc129
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.h153
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_stats_collector_test.cc379
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_test.cc193
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/incremental_marking_test.cc15
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/marking_verifier.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/marking_visitor.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/marking_visitor.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/name_trait_test.cc44
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/name_traits.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/page_memory.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/page_memory.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/persistent.h48
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/persistent_node.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/persistent_node.h26
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/process_heap.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/process_heap.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/self_keep_alive.h36
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/stack_frame_depth.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/thread_state.cc794
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/thread_state.h81
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/thread_state_scheduling_test.cc236
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/trace_traits.h23
-rw-r--r--chromium/third_party/blink/renderer/platform/heap/visitor.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/histogram.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/histogram.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder_test.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/ico/ico_image_decoder.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/ico/ico_image_decoder_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/image_decoder.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/image_decoder.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/image_decoder_test.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/image_decoder_test_helpers.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/image_frame.cc69
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/image_frame.h45
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/image_frame_test.cc183
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.cc15
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/segment_reader.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/image-encoders/image_encoder.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/image-encoders/image_encoder.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/instance_counters.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump_test.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/json/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/platform/json/json_parser.cc691
-rw-r--r--chromium/third_party/blink/renderer/platform/json/json_parser.h33
-rw-r--r--chromium/third_party/blink/renderer/platform/json/json_parser_test.cc261
-rw-r--r--chromium/third_party/blink/renderer/platform/json/json_values.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/kill_ring.h51
-rw-r--r--chromium/third_party/blink/renderer/platform/kill_ring_none.cc42
-rw-r--r--chromium/third_party/blink/renderer/platform/layout_locale.cc226
-rw-r--r--chromium/third_party/blink/renderer/platform/layout_locale.h88
-rw-r--r--chromium/third_party/blink/renderer/platform/layout_locale_test.cc155
-rw-r--r--chromium/third_party/blink/renderer/platform/layout_unit.h35
-rw-r--r--chromium/third_party/blink/renderer/platform/layout_unit_test.cc25
-rw-r--r--chromium/third_party/blink/renderer/platform/lifecycle_context_test.cc55
-rw-r--r--chromium/third_party/blink/renderer/platform/lifecycle_notifier.h69
-rw-r--r--chromium/third_party/blink/renderer/platform/lifecycle_observer.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/BUILD.gn3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/cors/cors.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/cors/cors.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc165
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/cors/cors_error_string.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc51
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h26
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc159
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.h48
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.json56
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc48
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc38
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc15
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc136
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource.h21
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_client.cc50
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_client.h27
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc198
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h36
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc89
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc261
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h106
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc296
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc124
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.cc34
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h94
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_request_test.cc31
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.cc33
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h29
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/resource_test.cc66
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc41
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h41
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/fetch_testing_platform_support.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/long_task_detector.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/long_task_detector.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/long_task_detector_test.cc29
-rw-r--r--chromium/third_party/blink/renderer/platform/mac/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/platform/mac/graphics_context_canvas.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/mac/graphics_context_canvas.mm6
-rw-r--r--chromium/third_party/blink/renderer/platform/mac/graphics_context_canvas_test.mm3
-rw-r--r--chromium/third_party/blink/renderer/platform/mac/kill_ring_mac.mm76
-rw-r--r--chromium/third_party/blink/renderer/platform/mac/local_current_graphics_context.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/mac/local_current_graphics_context.mm4
-rw-r--r--chromium/third_party/blink/renderer/platform/mac/scroll_animator_mac.mm2
-rw-r--r--chromium/third_party/blink/renderer/platform/mac/theme_mac.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/mac/theme_mac.mm5
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_center.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_center.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.cc23
-rw-r--r--chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/blink_typemaps.gni1
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/canonical_cookie.typemap14
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/canonical_cookie_mojom_traits.cc142
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/canonical_cookie_mojom_traits.h39
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/fetch_api_request_struct_traits.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/fetch_api_request_struct_traits.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/kurl_security_origin_test.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/mojo/security_origin_struct_traits.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/network/BUILD.gn4
-rw-r--r--chromium/third_party/blink/renderer/platform/network/http_header_map.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/network/http_names.json51
-rw-r--r--chromium/third_party/blink/renderer/platform/network/http_parsers.cc15
-rw-r--r--chromium/third_party/blink/renderer/platform/network/http_parsers.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/network/http_parsers_test.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/network/network_state_notifier.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/network/network_utils.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/network/network_utils.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/network/web_socket_handshake_request.cc59
-rw-r--r--chromium/third_party/blink/renderer/platform/network/web_socket_handshake_request.h93
-rw-r--r--chromium/third_party/blink/renderer/platform/network/web_socket_handshake_response.cc70
-rw-r--r--chromium/third_party/blink/renderer/platform/network/web_socket_handshake_response.h63
-rw-r--r--chromium/third_party/blink/renderer/platform/partition_alloc_memory_dump_provider.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/platform_export.h54
-rw-r--r--chromium/third_party/blink/renderer/platform/plugins/DEPS6
-rw-r--r--chromium/third_party/blink/renderer/platform/plugins/plugin_data.cc42
-rw-r--r--chromium/third_party/blink/renderer/platform/plugins/plugin_data_test.cc65
-rw-r--r--chromium/third_party/blink/renderer/platform/plugins/plugin_list_builder.cc64
-rw-r--r--chromium/third_party/blink/renderer/platform/plugins/plugin_list_builder.h63
-rw-r--r--chromium/third_party/blink/renderer/platform/plugins/plugin_script_forbidden_scope.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/png_fuzzer.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5247
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn183
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/DEPS9
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/README.md2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/DEPS7
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/enqueue_order.cc25
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/enqueue_order.h52
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/graceful_queue_shutdown_helper.cc40
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/graceful_queue_shutdown_helper.h47
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/intrusive_heap.h227
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/intrusive_heap_unittest.cc374
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/moveable_auto_lock.h41
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/proto/sequence_manager_test_description.proto67
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/real_time_domain.cc68
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/real_time_domain.h44
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer.cc24
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer_processor.cc170
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer_processor.h102
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer_processor_unittest.cc347
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/task_queue.cc273
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/task_queue.h307
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_impl.cc1041
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h460
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h108
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_delegate_for_test.cc64
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_delegate_for_test.h59
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl.cc683
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl.h337
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl_unittest.cc3220
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_perftest.cc318
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector.cc407
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h227
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector_logic.h35
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector_unittest.cc878
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/task_time_observer.h36
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/thread_controller_impl.cc258
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/thread_controller_impl.h128
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/time_domain.cc119
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/time_domain.h139
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/time_domain_unittest.cc343
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/virtual_time_domain.cc67
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/virtual_time_domain.h54
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/work_queue.cc235
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/work_queue.h155
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/work_queue_sets.cc172
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h104
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/work_queue_sets_unittest.cc327
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/work_queue_unittest.cc472
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/DEPS6
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/cancelable_closure_holder.cc30
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/cancelable_closure_holder.h42
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/compositor_metrics_helper.cc29
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/compositor_metrics_helper.h32
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/default_params.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/features.h123
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper.cc40
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper.h38
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc133
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/idle_helper.cc502
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/idle_helper.h251
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/idle_helper_unittest.cc1193
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/metrics_helper.cc84
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/metrics_helper.h73
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/metrics_helper_unittest.cc80
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/page_visibility_state.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/page_visibility_state.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/webthread_base.cc19
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc25
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.h22
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc21
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/worker_metrics_helper.cc66
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/worker_metrics_helper.h48
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler.cc144
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler.h64
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy.cc51
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy.h74
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy_unittest.cc198
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler_unittest.cc241
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/worker_task_queue.cc43
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/child/worker_task_queue.h37
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/DEPS6
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/background_scheduler.cc19
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/background_scheduler_unittest.cc34
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.cc30
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h42
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/frame_or_worker_scheduler.cc52
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper.cc40
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper.h38
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper_unittest.cc132
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc505
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.h250
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc1185
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.cc97
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.h77
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper_unittest.cc118
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc96
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h24
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc37
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_lifecycle_state.cc29
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_unittest.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc20
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc1089
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.cc31
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/total_duration_metric_reporter.cc47
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/total_duration_metric_reporter.h43
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/total_duration_metric_reporter_unittest.cc45
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/unprioritized_resource_loading_task_runner_handle.cc30
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/unprioritized_resource_loading_task_runner_handle.h45
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/web_resource_loading_task_runner_handle.cc17
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/common/web_thread_scheduler.cc165
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/DEPS7
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.cc81
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h29
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain_unittest.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner_unittest.cc68
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc426
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h129
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc1107
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc169
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h144
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc235
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator_unittest.cc49
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.cc209
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.h52
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper_unittest.cc358
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc665
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h238
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc1432
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc25
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h147
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc269
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h100
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc751
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.h22
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.cc112
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.h53
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.cc253
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h18
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator_unittest.cc347
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/resource_loading_task_runner_handle_impl.cc57
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/resource_loading_task_runner_handle_impl.h48
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_main_thread_scheduler.cc55
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/background_scheduler.h28
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h66
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h67
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/non_main_thread_scheduler.h143
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/page_lifecycle_state.h33
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/page_scheduler.h13
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/scheduling_lifecycle_state.h32
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h78
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/renderer/DEPS7
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/renderer/frame_status.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter.cc19
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter.h54
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter_unittest.cc87
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/util/thread_cpu_throttler.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/utility/webthread_impl_for_utility_thread.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/utility/webthread_impl_for_utility_thread.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/DEPS4
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_metrics_helper.cc28
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_metrics_helper.h31
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc98
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h38
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler_unittest.cc119
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler.cc141
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.cc27
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.cc105
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h110
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.cc39
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h38
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_metrics_helper.cc65
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_metrics_helper.h48
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc185
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.cc55
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h80
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy_unittest.cc221
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc273
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc208
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h94
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc202
-rw-r--r--chromium/third_party/blink/renderer/platform/scoped_orientation_change_indicator.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scroll_animator.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scroll_animator_compositor_coordinator.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scroll_animator_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scroll_snap_data.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scroll_types.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scrollable_area.cc56
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scrollable_area.h101
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scrollable_area_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scrollbar.cc44
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scrollbar.h7
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scrollbar_layer_delegate.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scrollbar_layer_delegate.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scrollbar_test_suite.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme.cc34
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme.h16
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_aura.cc57
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_aura.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_mac.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_mac.mm20
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_overlay.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_overlay.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_overlay_mock.h15
-rw-r--r--chromium/third_party/blink/renderer/platform/scroll/web_scrollbar_theme.mm5
-rw-r--r--chromium/third_party/blink/renderer/platform/shared_buffer.cc238
-rw-r--r--chromium/third_party/blink/renderer/platform/shared_buffer.h153
-rw-r--r--chromium/third_party/blink/renderer/platform/shared_buffer_chunk_reader.cc23
-rw-r--r--chromium/third_party/blink/renderer/platform/shared_buffer_test.cc236
-rw-r--r--chromium/third_party/blink/renderer/platform/supplementable.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/DEPS6
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/blink_perf_test_suite.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/blink_perf_test_suite.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/compositor_test.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/data/third_party/Roboto/LICENSE.txt202
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/data/third_party/Roboto/README.chromium12
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/data/third_party/Roboto/roboto-regular.woff2bin0 -> 63416 bytes
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/fake_display_item_client.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/histogram_tester.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/image_decode_bench.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/layer_tree_host_embedder.cc39
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/layer_tree_host_embedder.h45
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h56
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/paint_test_configurations.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/run_all_tests.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/scoped_fake_plugin_registry.cc75
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/scoped_fake_plugin_registry.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/shape_result_perf_test.cc170
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/shaping_line_breaker_perf_test.cc20
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/stub_graphics_layer_client.h36
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.cc116
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.h117
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/testing_platform_support.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/testing_platform_support.h16
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.cc84
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h27
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_web_rtc.cc90
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_web_rtc.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/use_mock_scrollbar_settings.h51
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.cc195
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.h106
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/text/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/platform/text/character.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/text/character.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/text/character_emoji.cc111
-rw-r--r--chromium/third_party/blink/renderer/platform/text/character_property.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/text/character_property_data_generator.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/text/character_property_data_generator.h19
-rw-r--r--chromium/third_party/blink/renderer/platform/text/character_test.cc33
-rw-r--r--chromium/third_party/blink/renderer/platform/text/hyphenation.cc12
-rw-r--r--chromium/third_party/blink/renderer/platform/text/hyphenation.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/text/hyphenation_test.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/text/icu_error.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/text/layout_locale.cc276
-rw-r--r--chromium/third_party/blink/renderer/platform/text/layout_locale.h93
-rw-r--r--chromium/third_party/blink/renderer/platform/text/layout_locale_test.cc206
-rw-r--r--chromium/third_party/blink/renderer/platform/text/line_ending.cc72
-rw-r--r--chromium/third_party/blink/renderer/platform/text/line_ending.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/text/platform_locale_test.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/text/text_boundaries_test.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/text/text_break_iterator.cc90
-rw-r--r--chromium/third_party/blink/renderer/platform/text/text_break_iterator.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/text/text_break_iterator_icu.cc92
-rw-r--r--chromium/third_party/blink/renderer/platform/text/text_break_iterator_internal_icu.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/text/text_break_iterator_test.cc25
-rw-r--r--chromium/third_party/blink/renderer/platform/text/text_encoding_detector.cc13
-rw-r--r--chromium/third_party/blink/renderer/platform/text/text_run.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/text/text_run.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/text/writing_mode.h10
-rw-r--r--chromium/third_party/blink/renderer/platform/text_codec_fuzzer.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/threading/DEPS16
-rw-r--r--chromium/third_party/blink/renderer/platform/threading/background_task_runner.cc20
-rw-r--r--chromium/third_party/blink/renderer/platform/threading/background_task_runner.h23
-rw-r--r--chromium/third_party/blink/renderer/platform/threading/background_task_runner_test.cc34
-rw-r--r--chromium/third_party/blink/renderer/platform/timer.cc7
-rw-r--r--chromium/third_party/blink/renderer/platform/timer.h21
-rw-r--r--chromium/third_party/blink/renderer/platform/timer_test.cc265
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/transformation_matrix.cc14
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/transformation_matrix.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/transforms/transformation_matrix_test.cc45
-rw-r--r--chromium/third_party/blink/renderer/platform/ukm_time_aggregator.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/ukm_time_aggregator_test.cc35
-rw-r--r--chromium/third_party/blink/renderer/platform/web_gesture_event.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/web_task_runner.cc44
-rw-r--r--chromium/third_party/blink/renderer/platform/web_thread.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/kurl.cc26
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/kurl.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/kurl_test.cc120
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry_test.cc50
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/referrer_policy.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_origin.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_origin.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_policy.cc25
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_policy.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/weborigin/security_policy_test.cc20
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/BUILD.gn14
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/DEPS2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/OWNERS1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/README.md2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.cc29
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.h40
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/ascii_ctype.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/bit_vector.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/byte_order.h44
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/byte_swap.h77
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/checked_numeric.h55
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/compiler.h17
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/conditional_destructor.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/date_math.cc15
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/decimal.cc1007
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/decimal.h194
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/decimal_test.cc1162
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/deque.h21
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum-dtoa.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/double-conversion.h6
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/dtoa/fixed-dtoa.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/experimental/README.md2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/experimental/container_type_operations_test.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/hash_iterators.h36
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/hash_map_test.cc23
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/hash_set_test.cc40
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/hash_table.h86
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/list_hash_set.h23
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/math_extras.h138
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/math_extras_test.cc4
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/process_metrics.h20
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/ref_ptr_test.cc107
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/ref_vector.h1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/atomic_string.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/atomic_string.h9
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/collator.cc (renamed from chromium/third_party/blink/renderer/platform/wtf/text/icu/collator_icu.cc)0
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/cstring.cc16
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/cstring.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/icu/unicode_icu.h226
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/integer_to_string_conversion.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/movable_string.cc147
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/movable_string.h139
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/movable_string_test.cc185
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_builder.cc77
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_builder.h32
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_concatenate.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_concatenate.h4
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_hash.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_impl.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_impl_cf.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_statics.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_view.h5
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/string_view_test.cc38
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_codec.cc8
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_codec.h14
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_codec_icu.cc6
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_codec_replacement_test.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf16.cc3
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.cc11
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8_test.cc9
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_encoding.cc10
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_encoding.h3
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/text_encoding_registry.cc1
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/unicode.h198
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.cc5
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.h11
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/text/wtf_string_test.cc20
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/threading.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/threading_primitives.h12
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/threading_win.cc27
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer.h2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/vector.h29
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/wtf_thread_data.cc2
-rw-r--r--chromium/third_party/blink/renderer/platform/wtf/wtf_thread_data.h4
4687 files changed, 136499 insertions, 129545 deletions
diff --git a/chromium/third_party/blink/renderer/BUILD.gn b/chromium/third_party/blink/renderer/BUILD.gn
index f148252157e..48d3b41eae3 100644
--- a/chromium/third_party/blink/renderer/BUILD.gn
+++ b/chromium/third_party/blink/renderer/BUILD.gn
@@ -24,10 +24,6 @@ declare_args() {
# a class has an empty destructor which would be unnecessarily invoked
# when finalized.
blink_gc_plugin_option_warn_unneeded_finalizer = false
-
- # Set to true to have the clang Blink GC plugin additionally check if a
- # TraceWrappers method also dispatches to all its base classes.
- blink_gc_plugin_option_warn_trace_wrappers_missing_base_dispatch = false
}
# features ---------------------------------------------------------------------
@@ -137,14 +133,6 @@ config("config") {
"warn-unneeded-finalizer",
]
}
- if (blink_gc_plugin_option_warn_trace_wrappers_missing_base_dispatch) {
- cflags += [
- "-Xclang",
- "-plugin-arg-blink-gc-plugin",
- "-Xclang",
- "warn_trace_wrappers_missing_base_dispatch",
- ]
- }
}
}
diff --git a/chromium/third_party/blink/renderer/DEPS b/chromium/third_party/blink/renderer/DEPS
index 41b21b60e77..0659cd7c48a 100644
--- a/chromium/third_party/blink/renderer/DEPS
+++ b/chromium/third_party/blink/renderer/DEPS
@@ -5,19 +5,24 @@ include_rules = [
"+base/containers/span.h",
"+base/debug",
"+base/feature_list.h",
+ "+base/format_macros.h",
"+base/gtest_prod_util.h",
"+base/location.h",
"+base/macros.h",
"+base/memory/ptr_util.h",
"+base/memory/weak_ptr.h",
"+base/metrics/histogram_macros.h",
+ "+base/numerics/checked_math.h",
+ "+base/numerics/safe_conversions.h",
"+base/optional.h",
"+base/rand_util.h",
"+base/sequenced_task_runner.h",
"+base/single_thread_task_runner.h",
"+base/stl_util.h",
+ "+base/sys_byteorder.h",
"+base/sys_info.h",
"+base/task_scheduler/post_task.h",
+ "+base/test/scoped_feature_list.h",
"+base/thread_annotations.h",
"+base/threading/thread_checker.h",
"+base/time/time.h",
diff --git a/chromium/third_party/blink/renderer/README.md b/chromium/third_party/blink/renderer/README.md
index 07318e7900d..5f1eb64bb05 100644
--- a/chromium/third_party/blink/renderer/README.md
+++ b/chromium/third_party/blink/renderer/README.md
@@ -127,16 +127,33 @@ See [this diagram](https://docs.google.com/document/d/1yYei-V76q3Mb-5LeJfNUMitmj
### Type dependencies
-`core/`, `modules/`, `bindings/`, `platform/` and `controller/` can use `std::` types and
-types defined in Chromium. The philosophy is that we should
-share as much code between Chromium and Blink as possible.
-
-However, there are a couple of types that really need to be optimized
-for Blink's workload (e.g., `Vector`, `HashTable`, `Bind`, `AtomicString`).
-These types are defined in `platform/wtf`. If there is an equivalent in
-`platform/wtf`, Blink must use the type in `platform/wtf` instead of the type
-defined in Chromium. For example, Blink should not use `std::vector`
-(except places where a conversion between `std::vector` and `WTF::Vector` is needed).
+Member variables of the following types are strongly discouraged in Blink:
+ - STL strings and containers. Use `WTF::String` and WTF containers instead.
+ - `GURL` and `url::Origin`. Use `KURL` and `SecurityOrigin` respectively.
+ - Any `//base` type which has a matching type in `platform/wtf`. The number of
+ duplicated types between WTF and base is continuously shrinking,
+ but always look at WTF first.
+
+The types above could only be used at the boundary to interoperate
+with `//base`, `//services`, `//third_party/blink/common` and other
+Chromium-side or third-party code. It is also allowed to use local variables
+of these types when convenient, as long as the result is not stored
+in a member variable.
+For example, calling an utility function on an `std::string` which came
+from `//net` and then converting to `WTF::String` to store in a field
+is allowed.
+
+We try to share as much code between Chromium and Blink as possible,
+so the number of these types should go down. However, some types
+really need to be optimized for Blink's workload (e.g., `Vector`,
+`HashTable`, `AtomicString`).
+
+Exceptions to this rule:
+ - Code in `//third_party/blink/common` and `//third_party/blink/public/common`
+ also runs in the browser process, and should use STL and base instead of WTF.
+ - Selected types in `public/platform` and `public/web`,
+ whole purpose of which is conversion between WTF and STL,
+ for example `WebString` or `WebVector`.
To prevent use of random types, we control allowed types by whitelisting
them in DEPS and a [presubmit script](../tools/audit_non_blink_usage.py).
diff --git a/chromium/third_party/blink/renderer/bindings/DEPS b/chromium/third_party/blink/renderer/bindings/DEPS
index 15a49de6c42..8d675914fd6 100644
--- a/chromium/third_party/blink/renderer/bindings/DEPS
+++ b/chromium/third_party/blink/renderer/bindings/DEPS
@@ -1,5 +1,6 @@
include_rules = [
"+base/memory/scoped_refptr.h",
+ "+base/process/process_metrics.h",
"+gin/public",
"+services/network/public/mojom/fetch_api.mojom-blink.h",
"+third_party/blink/renderer/bindings",
diff --git a/chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.md b/chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.md
index 64a8aca3900..1370c710cb3 100644
--- a/chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.md
+++ b/chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.md
@@ -148,6 +148,11 @@ are triggered for this method or attribute.
Usage: `[CEReactions]` takes no arguments.
+`[CEReacionts]` doesn't work with `[Custom]`. Custom binding code should use
+`blink::CEReactionsScope` if the method or the attribute has `[CEReactions]`.
+
+Note that `blink::CEReactionsScope` must be constructed after `blink::ExceptionState`.
+
### [Clamp] _(a, p)_
Standard: [Clamp](https://heycam.github.io/webidl/#Clamp)
@@ -308,6 +313,14 @@ Summary: HTML Elements have special constructor behavior. Interface object of gi
Usage: Must take no arguments, and must not appear on anything other than an interface. It must appear once on an interface, and the interface cannot be annotated with `[Constructor]` or `[NoInterfaceObject]` extended attributes. It must not be used on a callback interface.
+### [LenientSetter] _(a)_
+
+Standard: [LenientSetter](https://heycam.github.io/webidl/#LenientSetter)
+
+Summary: `[LenientSetter]` indicates that a no-op setter will be generated for a readonly attribute’s accessor property. This results in erroneous assignments to the property in strict mode to be ignored rather than causing an exception to be thrown.
+
+`[LenientSetter]` must take no arguments, and must not appear on anything other than a readonly regular attribute.
+
### [LegacyUnenumerableNamedProperties] _(i)_
Standard: [LegacyUnenumerableNamedProperties](https://heycam.github.io/webidl/#LegacyUnenumerableNamedProperties)
@@ -610,7 +623,7 @@ String Example::func(ScriptState* state, bool a, bool b);
```
Be careful when you use `[CallWith=ScriptState]`.
-You should not store the passed-in ScriptState on a DOM object (using scoped_refptr<ScriptState>).
+You should not store the passed-in ScriptState on a DOM object.
This is because if the stored ScriptState is used by some method called by a different
world (note that the DOM object is shared among multiple worlds), it leaks the ScriptState
to the world. ScriptState must be carefully maintained in a way that doesn't leak
@@ -696,7 +709,7 @@ scoped_refptr<XXX> XXX::create(ExecutionContext* context, float x, float y, Stri
```
Be careful when you use `[ConstructorCallWith=ScriptState]`.
-You should not store the passed-in ScriptState on a DOM object (using scoped_refptr<ScriptState>).
+You should not store the passed-in ScriptState on a DOM object.
This is because if the stored ScriptState is used by some method called by a different
world (note that the DOM object is shared among multiple worlds), it leaks the ScriptState
to the world. ScriptState must be carefully maintained in a way that doesn't leak
diff --git a/chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt b/chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt
index d3cd5b733a6..ac0bab0228a 100644
--- a/chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt
+++ b/chromium/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt
@@ -64,6 +64,7 @@ ImplementedAs=*
LegacyInterfaceTypeChecking
LegacyTreatAsPartialInterface
LegacyUnenumerableNamedProperties
+LenientSetter
LenientThis
LogActivity=|GetterOnly|SetterOnly
LogAllWorlds
diff --git a/chromium/third_party/blink/renderer/bindings/IDLUnionTypes.md b/chromium/third_party/blink/renderer/bindings/IDLUnionTypes.md
index 050c2ca071c..b123c9406c2 100644
--- a/chromium/third_party/blink/renderer/bindings/IDLUnionTypes.md
+++ b/chromium/third_party/blink/renderer/bindings/IDLUnionTypes.md
@@ -25,7 +25,7 @@ name, but we use some aliases to avoid too-long file names
Currently we use following alias(es).
```
-CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContextOrXRPresentationContext -> RenderingContext
+CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContextOrImageBitmapRenderingContextOrXRPresentationContext -> RenderingContext
```
The paths for generated classes depend on the places union types are
diff --git a/chromium/third_party/blink/renderer/bindings/bindings.gni b/chromium/third_party/blink/renderer/bindings/bindings.gni
index 99fe62acc3a..f58f106e41a 100644
--- a/chromium/third_party/blink/renderer/bindings/bindings.gni
+++ b/chromium/third_party/blink/renderer/bindings/bindings.gni
@@ -33,10 +33,6 @@ bindings_core_v8_files =
"core/v8/dictionary.cc",
"core/v8/dictionary.h",
"core/v8/dictionary_helper_for_core.cc",
- "core/v8/exception_messages.cc",
- "core/v8/exception_messages.h",
- "core/v8/exception_state.cc",
- "core/v8/exception_state.h",
"core/v8/generated_code_helper.cc",
"core/v8/generated_code_helper.h",
"core/v8/initialize_v8_extras_binding.cc",
@@ -105,6 +101,8 @@ bindings_core_v8_files =
"core/v8/v8_binding_for_core.cc",
"core/v8/v8_binding_for_core.h",
"core/v8/v8_cache_options.h",
+ "core/v8/v8_code_cache.cc",
+ "core/v8/v8_code_cache.h",
"core/v8/v8_cross_origin_setter_info.h",
"core/v8/v8_dom_configuration.cc",
"core/v8/v8_dom_configuration.h",
@@ -198,6 +196,7 @@ bindings_unittest_files =
"core/v8/script_promise_test.cc",
"core/v8/script_streamer_test.cc",
"core/v8/script_wrappable_marking_visitor_test.cc",
+ "core/v8/script_wrappable_visitor_test.cc",
"core/v8/to_v8_test.cc",
"core/v8/trace_wrapper_member_test.cc",
"core/v8/v8_binding_for_testing.cc",
diff --git a/chromium/third_party/blink/renderer/bindings/core/DEPS b/chromium/third_party/blink/renderer/bindings/core/DEPS
index e4cb4754c9f..f83e6ef79ac 100644
--- a/chromium/third_party/blink/renderer/bindings/core/DEPS
+++ b/chromium/third_party/blink/renderer/bindings/core/DEPS
@@ -1,5 +1,6 @@
include_rules = [
"+gin/public",
+ "+services/metrics/public/cpp",
"+third_party/blink/public/platform",
"+third_party/blink/public/web/web_serialized_script_value_version.h",
"+third_party/blink/public/web/web_settings.h",
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/BUILD.gn b/chromium/third_party/blink/renderer/bindings/core/v8/BUILD.gn
index d70c1ed8b22..8648fa717cd 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/BUILD.gn
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/BUILD.gn
@@ -86,8 +86,6 @@ bindings_core_generated_union_type_files = [
"$bindings_core_v8_output_dir/string_or_double.h",
"$bindings_core_v8_output_dir/string_or_double_or_performance_measure_options.cc",
"$bindings_core_v8_output_dir/string_or_double_or_performance_measure_options.h",
- "$bindings_core_v8_output_dir/string_or_float.cc",
- "$bindings_core_v8_output_dir/string_or_float.h",
"$bindings_core_v8_output_dir/string_or_string_sequence.cc",
"$bindings_core_v8_output_dir/string_or_string_sequence.h",
"$bindings_core_v8_output_dir/string_or_trusted_html.cc",
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h b/chromium/third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h
index 8b310b8f7b3..fcd8b9f8456 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h
@@ -12,6 +12,30 @@ namespace blink {
class ScriptWrappable;
+// Derived by wrappable objects which need to remain alive due to ongoing
+// asynchronous activity, even if they are not referenced in the JavaScript or
+// Blink heap.
+//
+// A ScriptWrappable ordinarily is held alive only if it has some such
+// reference, usually via a wrapper object held by script. However, some
+// objects, such as XMLHttpRequest, have pending activity that may be visible
+// (e.g. firing event listeners or resolving promises), and so should not be
+// collected, even if no references remain.
+//
+// Such objects should derive from ActiveScriptWrappable<T>, and override
+// ScriptWrappable::HasPendingActivity:
+// bool HasPendingActivity() const final;
+// which returns true if there may be pending activity which requires the
+// wrappable remain alive.
+//
+// During wrapper tracing, ActiveScriptWrappables which belong to a
+// non-destroyed execution context and have pending activity are treated as
+// roots for the purposes of marking and so will keep themselves and objects
+// they reference alive.
+//
+// Since this pending activity will not keep the wrappable alive after the
+// context is destroyed, it is common for ActiveScriptWrappable objects to also
+// derive from ContextLifecycleObserver to abort the activity at that time.
template <typename T>
class ActiveScriptWrappable : public ActiveScriptWrappableBase {
WTF_MAKE_NONCOPYABLE(ActiveScriptWrappable);
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/activity_logger_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/activity_logger_test.cc
index dfbac6c3ffa..3b6fbe59502 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/activity_logger_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/activity_logger_test.cc
@@ -90,19 +90,14 @@ class ActivityLoggerTest : public testing::Test {
void ExecuteScriptInMainWorld(const String& script) const {
v8::HandleScope scope(v8::Isolate::GetCurrent());
script_controller_->ExecuteScriptInMainWorld(script);
- PumpPendingRequestsForFrameToLoad(
- web_view_helper_.GetWebView()->MainFrame());
+ PumpPendingRequestsForFrameToLoad();
}
void ExecuteScriptInIsolatedWorld(const String& script) const {
v8::HandleScope scope(v8::Isolate::GetCurrent());
- HeapVector<ScriptSourceCode> sources;
- sources.push_back(ScriptSourceCode(script));
- Vector<v8::Local<v8::Value>> results;
- script_controller_->ExecuteScriptInIsolatedWorld(kIsolatedWorldId, sources,
- nullptr);
- PumpPendingRequestsForFrameToLoad(
- web_view_helper_.GetWebView()->MainFrame());
+ script_controller_->ExecuteScriptInIsolatedWorld(kIsolatedWorldId,
+ ScriptSourceCode(script));
+ PumpPendingRequestsForFrameToLoad();
}
bool VerifyActivities(const String& activities) {
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/binding_security.cc b/chromium/third_party/blink/renderer/bindings/core/v8/binding_security.cc
index 2f1c6a25fa9..8acd39b218c 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/binding_security.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/binding_security.cc
@@ -30,7 +30,6 @@
#include "third_party/blink/renderer/bindings/core/v8/binding_security.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_location.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_window.h"
@@ -43,6 +42,7 @@
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/html/html_frame_element_base.h"
#include "third_party/blink/renderer/core/workers/main_thread_worklet_global_scope.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/wrapper_creation_security_check.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/binding_security_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/binding_security_test.cc
index 903db147c05..d1e2a81fe71 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/binding_security_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/binding_security_test.cc
@@ -7,7 +7,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
-#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/loader/document_loader.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"
@@ -106,33 +106,33 @@ INSTANTIATE_TEST_CASE_P(WindowProperties,
TEST_P(BindingSecurityCounterTest, CrossOriginWindow) {
LoadWindowAndAccessProperty(OriginDisposition::CrossOrigin, GetParam());
- EXPECT_TRUE(GetDocument().GetPage()->GetUseCounter().HasRecordedMeasurement(
+ EXPECT_TRUE(GetDocument().Loader()->GetUseCounter().HasRecordedMeasurement(
WebFeature::kCrossOriginPropertyAccess));
- EXPECT_TRUE(GetDocument().GetPage()->GetUseCounter().HasRecordedMeasurement(
+ EXPECT_TRUE(GetDocument().Loader()->GetUseCounter().HasRecordedMeasurement(
WebFeature::kCrossOriginPropertyAccessFromOpener));
}
TEST_P(BindingSecurityCounterTest, SameOriginWindow) {
LoadWindowAndAccessProperty(OriginDisposition::SameOrigin, GetParam());
- EXPECT_FALSE(GetDocument().GetPage()->GetUseCounter().HasRecordedMeasurement(
+ EXPECT_FALSE(GetDocument().Loader()->GetUseCounter().HasRecordedMeasurement(
WebFeature::kCrossOriginPropertyAccess));
- EXPECT_FALSE(GetDocument().GetPage()->GetUseCounter().HasRecordedMeasurement(
+ EXPECT_FALSE(GetDocument().Loader()->GetUseCounter().HasRecordedMeasurement(
WebFeature::kCrossOriginPropertyAccessFromOpener));
}
TEST_P(BindingSecurityCounterTest, CrossOriginFrame) {
LoadFrameAndAccessProperty(OriginDisposition::CrossOrigin, GetParam());
- EXPECT_TRUE(GetDocument().GetPage()->GetUseCounter().HasRecordedMeasurement(
+ EXPECT_TRUE(GetDocument().Loader()->GetUseCounter().HasRecordedMeasurement(
WebFeature::kCrossOriginPropertyAccess));
- EXPECT_FALSE(GetDocument().GetPage()->GetUseCounter().HasRecordedMeasurement(
+ EXPECT_FALSE(GetDocument().Loader()->GetUseCounter().HasRecordedMeasurement(
WebFeature::kCrossOriginPropertyAccessFromOpener));
}
TEST_P(BindingSecurityCounterTest, SameOriginFrame) {
LoadFrameAndAccessProperty(OriginDisposition::SameOrigin, GetParam());
- EXPECT_FALSE(GetDocument().GetPage()->GetUseCounter().HasRecordedMeasurement(
+ EXPECT_FALSE(GetDocument().Loader()->GetUseCounter().HasRecordedMeasurement(
WebFeature::kCrossOriginPropertyAccess));
- EXPECT_FALSE(GetDocument().GetPage()->GetUseCounter().HasRecordedMeasurement(
+ EXPECT_FALSE(GetDocument().Loader()->GetUseCounter().HasRecordedMeasurement(
WebFeature::kCrossOriginPropertyAccessFromOpener));
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_custom_xpath_ns_resolver.cc b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_custom_xpath_ns_resolver.cc
index e04c55ad13b..985c052bfa9 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_custom_xpath_ns_resolver.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_custom_xpath_ns_resolver.cc
@@ -99,6 +99,7 @@ AtomicString V8CustomXPathNSResolver::lookupNamespaceURI(const String& prefix) {
}
void V8CustomXPathNSResolver::Trace(blink::Visitor* visitor) {
+ visitor->Trace(script_state_);
XPathNSResolver::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_custom_xpath_ns_resolver.h b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_custom_xpath_ns_resolver.h
index 375deb249d0..c4a90e04c30 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_custom_xpath_ns_resolver.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_custom_xpath_ns_resolver.h
@@ -54,7 +54,7 @@ class V8CustomXPathNSResolver final : public XPathNSResolver {
private:
V8CustomXPathNSResolver(ScriptState*, v8::Local<v8::Object> resolver);
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
v8::Local<v8::Object> resolver_; // Handle to resolver object.
};
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_element_custom.cc b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_element_custom.cc
index cb5220af173..6184abd88f3 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_element_custom.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_element_custom.cc
@@ -4,10 +4,11 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_trusted_html.h"
+#include "third_party/blink/renderer/core/html/custom/ce_reactions_scope.h"
#include "third_party/blink/renderer/core/html/custom/v0_custom_element_processing_stack.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -26,6 +27,7 @@ void V8Element::innerHTMLAttributeSetterCustom(
ExceptionState exception_state(isolate, ExceptionState::kSetterContext,
"Element", "innerHTML");
+ CEReactionsScope ce_reactions_scope;
// Prepare the value to be set.
StringOrTrustedHTML cpp_value;
@@ -58,6 +60,7 @@ void V8Element::outerHTMLAttributeSetterCustom(
ExceptionState exception_state(isolate, ExceptionState::kSetterContext,
"Element", "outerHTML");
+ CEReactionsScope ce_reactions_scope;
// Prepare the value to be set.
StringOrTrustedHTML cpp_value;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_message_event_custom.cc b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_message_event_custom.cc
index 51bdca5602b..e5e6016f2f8 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_message_event_custom.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_message_event_custom.cc
@@ -38,6 +38,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_event_target.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_message_port.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_window.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_promise_rejection_event_custom.cc b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_promise_rejection_event_custom.cc
index 6b6a039ff60..c7900983580 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_promise_rejection_event_custom.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_promise_rejection_event_custom.cc
@@ -4,11 +4,11 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_promise_rejection_event.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/generated_code_helper.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.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_state.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_shadow_root_custom.cc b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_shadow_root_custom.cc
index 97836aaa042..45240052bbf 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_shadow_root_custom.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_shadow_root_custom.cc
@@ -4,10 +4,11 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_shadow_root.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_trusted_html.h"
+#include "third_party/blink/renderer/core/html/custom/ce_reactions_scope.h"
#include "third_party/blink/renderer/core/html/custom/v0_custom_element_processing_stack.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -26,6 +27,7 @@ void V8ShadowRoot::innerHTMLAttributeSetterCustom(
ExceptionState exception_state(isolate, ExceptionState::kSetterContext,
"ShadowRoot", "innerHTML");
+ CEReactionsScope ce_reactions_scope;
// Prepare the value to be set.
StringOrTrustedHTML cpp_value;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_window_custom.cc b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_window_custom.cc
index 4110b8303e7..5871aa0a384 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_window_custom.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_window_custom.cc
@@ -31,8 +31,6 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_window.h"
#include "third_party/blink/renderer/bindings/core/v8/binding_security.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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_core.h"
@@ -58,6 +56,8 @@
#include "third_party/blink/renderer/core/loader/frame_loader.h"
#include "third_party/blink/renderer/core/messaging/message_port.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
#include "third_party/blink/renderer/platform/layout_test_support.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
@@ -198,69 +198,6 @@ void V8Window::openerAttributeSetterCustom(
}
}
-void V8Window::postMessageMethodCustom(
- const v8::FunctionCallbackInfo<v8::Value>& info) {
- ExceptionState exception_state(info.GetIsolate(),
- ExceptionState::kExecutionContext, "Window",
- "postMessage");
- if (UNLIKELY(info.Length() < 2)) {
- exception_state.ThrowTypeError(
- ExceptionMessages::NotEnoughArguments(2, info.Length()));
- return;
- }
-
- // None of these need to be RefPtr because info and context are guaranteed
- // to hold on to them.
- DOMWindow* window = V8Window::ToImpl(info.Holder());
- // TODO(yukishiino): The HTML spec specifies that we should use the
- // Incumbent Realm instead of the Current Realm, but currently we don't have
- // a way to retrieve the Incumbent Realm. See also:
- // https://html.spec.whatwg.org/multipage/comms.html#dom-window-postmessage
- LocalDOMWindow* source = CurrentDOMWindow(info.GetIsolate());
-
- DCHECK(window);
- UseCounter::Count(source->GetFrame(), WebFeature::kWindowPostMessage);
-
- // If called directly by WebCore we don't have a calling context.
- if (!source) {
- exception_state.ThrowTypeError("No active calling context exists.");
- return;
- }
-
- // This function has variable arguments and can be:
- // postMessage(message, targetOrigin)
- // postMessage(message, targetOrigin, {sequence of transferrables})
- // TODO(foolip): Type checking of the arguments should happen in order, so
- // that e.g. postMessage({}, { toString: () => { throw Error(); } }, 0)
- // throws the Error from toString, not the TypeError for argument 3.
- Transferables transferables;
- const int kTargetOriginArgIndex = 1;
- if (info.Length() > 2) {
- const int kTransferablesArgIndex = 2;
- if (!SerializedScriptValue::ExtractTransferables(
- info.GetIsolate(), info[kTransferablesArgIndex],
- kTransferablesArgIndex, transferables, exception_state)) {
- return;
- }
- }
- // TODO(foolip): targetOrigin should be a USVString in IDL and treated as
- // such here, without TreatNullAndUndefinedAsNullString.
- TOSTRING_VOID(V8StringResource<kTreatNullAndUndefinedAsNullString>,
- target_origin, info[kTargetOriginArgIndex]);
-
- SerializedScriptValue::SerializeOptions options;
- options.transferables = &transferables;
- scoped_refptr<SerializedScriptValue> message =
- SerializedScriptValue::Serialize(info.GetIsolate(), info[0], options,
- exception_state);
- if (exception_state.HadException())
- return;
-
- message->UnregisterMemoryAllocatedWithCurrentScriptContext();
- window->postMessage(std::move(message), transferables.message_ports,
- target_origin, source, exception_state);
-}
-
void V8Window::namedPropertyGetterCustom(
const AtomicString& name,
const v8::PropertyCallbackInfo<v8::Value>& info) {
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_xml_http_request_custom.cc b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_xml_http_request_custom.cc
index e9f9aaae23f..76b159e2ca8 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_xml_http_request_custom.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/custom/v8_xml_http_request_custom.cc
@@ -30,8 +30,6 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_xml_http_request.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
@@ -43,6 +41,7 @@
#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/xmlhttprequest/xml_http_request.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "v8/include/v8.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/dictionary.h b/chromium/third_party/blink/renderer/bindings/core/v8/dictionary.h
index ed9ba409755..e9de11c8d69 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/dictionary.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/dictionary.h
@@ -26,9 +26,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_DICTIONARY_H_
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_DICTIONARY_H_
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/text/string_view.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/dictionary_helper_for_core.cc b/chromium/third_party/blink/renderer/bindings/core/v8/dictionary_helper_for_core.cc
index 46ceb88eabf..8924bb1485e 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/dictionary_helper_for_core.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/dictionary_helper_for_core.cc
@@ -24,8 +24,6 @@
*/
#include "third_party/blink/renderer/bindings/core/v8/array_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer_view.h"
@@ -36,6 +34,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_uint8_array.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_window.h"
#include "third_party/blink/renderer/core/html/track/track_base.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
namespace blink {
@@ -174,7 +173,7 @@ bool DictionaryHelper::Get(const Dictionary& dictionary,
double double_value;
if (!v8_value->NumberValue(dictionary.V8Context()).To(&double_value))
return false;
- doubleToInteger(double_value, value);
+ value = DoubleToInteger(double_value);
return true;
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/exception_messages.cc b/chromium/third_party/blink/renderer/bindings/core/v8/exception_messages.cc
deleted file mode 100644
index eb17c6c72d7..00000000000
--- a/chromium/third_party/blink/renderer/bindings/core/v8/exception_messages.cc
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * 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/bindings/core/v8/exception_messages.h"
-
-#include "third_party/blink/renderer/platform/decimal.h"
-#include "third_party/blink/renderer/platform/wtf/math_extras.h"
-
-namespace blink {
-
-String ExceptionMessages::FailedToConvertJSValue(const char* type) {
- return String::Format("Failed to convert value to '%s'.", type);
-}
-
-String ExceptionMessages::FailedToConstruct(const char* type,
- const String& detail) {
- return "Failed to construct '" + String(type) +
- (!detail.IsEmpty() ? String("': " + detail) : String("'"));
-}
-
-String ExceptionMessages::FailedToEnumerate(const char* type,
- const String& detail) {
- return "Failed to enumerate the properties of '" + String(type) +
- (!detail.IsEmpty() ? String("': " + detail) : String("'"));
-}
-
-String ExceptionMessages::FailedToExecute(const char* method,
- const char* type,
- const String& detail) {
- return "Failed to execute '" + String(method) + "' on '" + String(type) +
- (!detail.IsEmpty() ? String("': " + detail) : String("'"));
-}
-
-String ExceptionMessages::FailedToGet(const char* property,
- const char* type,
- const String& detail) {
- return "Failed to read the '" + String(property) + "' property from '" +
- String(type) + "': " + detail;
-}
-
-String ExceptionMessages::FailedToSet(const char* property,
- const char* type,
- const String& detail) {
- return "Failed to set the '" + String(property) + "' property on '" +
- String(type) + "': " + detail;
-}
-
-String ExceptionMessages::FailedToDelete(const char* property,
- const char* type,
- const String& detail) {
- return "Failed to delete the '" + String(property) + "' property from '" +
- String(type) + "': " + detail;
-}
-
-String ExceptionMessages::FailedToGetIndexed(const char* type,
- const String& detail) {
- return "Failed to read an indexed property from '" + String(type) + "': " +
- detail;
-}
-
-String ExceptionMessages::FailedToSetIndexed(const char* type,
- const String& detail) {
- return "Failed to set an indexed property on '" + String(type) + "': " +
- detail;
-}
-
-String ExceptionMessages::FailedToDeleteIndexed(const char* type,
- const String& detail) {
- return "Failed to delete an indexed property from '" + String(type) + "': " +
- detail;
-}
-
-String ExceptionMessages::ConstructorNotCallableAsFunction(const char* type) {
- return FailedToConstruct(type,
- "Please use the 'new' operator, this DOM object "
- "constructor cannot be called as a function.");
-}
-
-String ExceptionMessages::IncorrectPropertyType(const String& property,
- const String& detail) {
- return "The '" + property + "' property " + detail;
-}
-
-String ExceptionMessages::InvalidArity(const char* expected,
- unsigned provided) {
- return "Valid arities are: " + String(expected) + ", but " +
- String::Number(provided) + " arguments provided.";
-}
-
-String ExceptionMessages::ArgumentNullOrIncorrectType(
- int argument_index,
- const String& expected_type) {
- return "The " + OrdinalNumber(argument_index) +
- " argument provided is either null, or an invalid " + expected_type +
- " object.";
-}
-
-String ExceptionMessages::NotASequenceTypeProperty(
- const String& property_name) {
- return "'" + property_name +
- "' property is neither an array, nor does it have indexed properties.";
-}
-
-String ExceptionMessages::NotEnoughArguments(unsigned expected,
- unsigned provided) {
- return String::Number(expected) + " argument" + (expected > 1 ? "s" : "") +
- " required, but only " + String::Number(provided) + " present.";
-}
-
-String ExceptionMessages::NotAFiniteNumber(double value, const char* name) {
- DCHECK(!std::isfinite(value));
- return String::Format("The %s is %s.", name,
- std::isinf(value) ? "infinite" : "not a number");
-}
-
-String ExceptionMessages::NotAFiniteNumber(const Decimal& value,
- const char* name) {
- DCHECK(!value.IsFinite());
- return String::Format("The %s is %s.", name,
- value.IsInfinity() ? "infinite" : "not a number");
-}
-
-String ExceptionMessages::OrdinalNumber(int number) {
- String suffix("th");
- switch (number % 10) {
- case 1:
- if (number % 100 != 11)
- suffix = "st";
- break;
- case 2:
- if (number % 100 != 12)
- suffix = "nd";
- break;
- case 3:
- if (number % 100 != 13)
- suffix = "rd";
- break;
- }
- return String::Number(number) + suffix;
-}
-
-String ExceptionMessages::ReadOnly(const char* detail) {
- DEFINE_STATIC_LOCAL(String, read_only, ("This object is read-only."));
- return detail
- ? String::Format("This object is read-only, because %s.", detail)
- : read_only;
-}
-
-template <>
-CORE_EXPORT String ExceptionMessages::FormatNumber<float>(float number) {
- return FormatPotentiallyNonFiniteNumber(number);
-}
-
-template <>
-CORE_EXPORT String ExceptionMessages::FormatNumber<double>(double number) {
- return FormatPotentiallyNonFiniteNumber(number);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/exception_messages.h b/chromium/third_party/blink/renderer/bindings/core/v8/exception_messages.h
deleted file mode 100644
index e3c328642b4..00000000000
--- a/chromium/third_party/blink/renderer/bindings/core/v8/exception_messages.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * 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_BINDINGS_CORE_V8_EXCEPTION_MESSAGES_H_
-#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_EXCEPTION_MESSAGES_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/math_extras.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-class Decimal;
-
-class CORE_EXPORT ExceptionMessages {
- STATIC_ONLY(ExceptionMessages);
-
- public:
- enum BoundType {
- kInclusiveBound,
- kExclusiveBound,
- };
-
- static String ArgumentNullOrIncorrectType(int argument_index,
- const String& expected_type);
- static String ConstructorNotCallableAsFunction(const char* type);
-
- static String FailedToConvertJSValue(const char* type);
-
- static String FailedToConstruct(const char* type, const String& detail);
- static String FailedToEnumerate(const char* type, const String& detail);
- static String FailedToExecute(const char* method,
- const char* type,
- const String& detail);
- static String FailedToGet(const char* property,
- const char* type,
- const String& detail);
- static String FailedToSet(const char* property,
- const char* type,
- const String& detail);
- static String FailedToDelete(const char* property,
- const char* type,
- const String& detail);
- static String FailedToGetIndexed(const char* type, const String& detail);
- static String FailedToSetIndexed(const char* type, const String& detail);
- static String FailedToDeleteIndexed(const char* type, const String& detail);
-
- template <typename NumType>
- static String FormatNumber(NumType number) {
- return FormatFiniteNumber(number);
- }
-
- static String IncorrectPropertyType(const String& property,
- const String& detail);
-
- template <typename NumberType>
- static String IndexExceedsMaximumBound(const char* name,
- NumberType given,
- NumberType bound) {
- bool eq = given == bound;
- StringBuilder result;
- result.Append("The ");
- result.Append(name);
- result.Append(" provided (");
- result.Append(FormatNumber(given));
- result.Append(") is greater than ");
- result.Append(eq ? "or equal to " : "");
- result.Append("the maximum bound (");
- result.Append(FormatNumber(bound));
- result.Append(").");
- return result.ToString();
- }
-
- template <typename NumberType>
- static String IndexExceedsMinimumBound(const char* name,
- NumberType given,
- NumberType bound) {
- bool eq = given == bound;
- StringBuilder result;
- result.Append("The ");
- result.Append(name);
- result.Append(" provided (");
- result.Append(FormatNumber(given));
- result.Append(") is less than ");
- result.Append(eq ? "or equal to " : "");
- result.Append("the minimum bound (");
- result.Append(FormatNumber(bound));
- result.Append(").");
- return result.ToString();
- }
-
- template <typename NumberType>
- static String IndexOutsideRange(const char* name,
- NumberType given,
- NumberType lower_bound,
- BoundType lower_type,
- NumberType upper_bound,
- BoundType upper_type) {
- StringBuilder result;
- result.Append("The ");
- result.Append(name);
- result.Append(" provided (");
- result.Append(FormatNumber(given));
- result.Append(") is outside the range ");
- result.Append(lower_type == kExclusiveBound ? '(' : '[');
- result.Append(FormatNumber(lower_bound));
- result.Append(", ");
- result.Append(FormatNumber(upper_bound));
- result.Append(upper_type == kExclusiveBound ? ')' : ']');
- result.Append('.');
- return result.ToString();
- }
-
- static String InvalidArity(const char* expected, unsigned provided);
-
- static String NotASequenceTypeProperty(const String& property_name);
- static String NotAFiniteNumber(double value,
- const char* name = "value provided");
- static String NotAFiniteNumber(const Decimal& value,
- const char* name = "value provided");
-
- static String NotEnoughArguments(unsigned expected, unsigned provided);
-
- static String ReadOnly(const char* detail = nullptr);
-
- private:
- template <typename NumType>
- static String FormatFiniteNumber(NumType number) {
- if (number > 1e20 || number < -1e20)
- return String::Format("%e", 1.0 * number);
- return String::Number(number);
- }
-
- template <typename NumType>
- static String FormatPotentiallyNonFiniteNumber(NumType number) {
- if (std::isnan(number))
- return "NaN";
- if (std::isinf(number))
- return number > 0 ? "Infinity" : "-Infinity";
- if (number > 1e20 || number < -1e20)
- return String::Format("%e", number);
- return String::Number(number);
- }
-
- static String OrdinalNumber(int number);
-};
-
-template <>
-String ExceptionMessages::FormatNumber<float>(float number);
-template <>
-String ExceptionMessages::FormatNumber<double>(double number);
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_EXCEPTION_MESSAGES_H_
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/exception_state.cc b/chromium/third_party/blink/renderer/bindings/core/v8/exception_state.cc
deleted file mode 100644
index 4ec6e3c315a..00000000000
--- a/chromium/third_party/blink/renderer/bindings/core/v8/exception_state.cc
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * 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/bindings/core/v8/exception_state.h"
-
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
-
-namespace blink {
-
-void ExceptionState::ThrowDOMException(ExceptionCode ec, const char* message) {
- ThrowDOMException(ec, String(message));
-}
-
-void ExceptionState::ThrowRangeError(const char* message) {
- ThrowRangeError(String(message));
-}
-
-void ExceptionState::ThrowSecurityError(const char* sanitized_message,
- const char* unsanitized_message) {
- ThrowSecurityError(String(sanitized_message), String(unsanitized_message));
-}
-
-void ExceptionState::ThrowTypeError(const char* message) {
- ThrowTypeError(String(message));
-}
-
-void ExceptionState::ThrowDOMException(ExceptionCode ec,
- const String& message) {
- // SecurityError is thrown via ::throwSecurityError, and _careful_
- // consideration must be given to the data exposed to JavaScript via the
- // 'sanitizedMessage'.
- DCHECK(ec != kSecurityError);
-
- const String& processed_message = AddExceptionContext(message);
- SetException(
- ec, processed_message,
- V8ThrowDOMException::CreateDOMException(isolate_, ec, processed_message));
-}
-
-void ExceptionState::ThrowRangeError(const String& message) {
- SetException(kV8RangeError, message,
- V8ThrowException::CreateRangeError(
- isolate_, AddExceptionContext(message)));
-}
-
-void ExceptionState::ThrowSecurityError(const String& sanitized_message,
- const String& unsanitized_message) {
- const String& final_sanitized = AddExceptionContext(sanitized_message);
- const String& final_unsanitized = AddExceptionContext(unsanitized_message);
- SetException(
- kSecurityError, final_sanitized,
- V8ThrowDOMException::CreateDOMException(
- isolate_, kSecurityError, final_sanitized, final_unsanitized));
-}
-
-void ExceptionState::ThrowTypeError(const String& message) {
- SetException(kV8TypeError, message,
- V8ThrowException::CreateTypeError(isolate_,
- AddExceptionContext(message)));
-}
-
-void ExceptionState::RethrowV8Exception(v8::Local<v8::Value> value) {
- SetException(kRethrownException, String(), value);
-}
-
-void ExceptionState::ClearException() {
- code_ = 0;
- message_ = String();
- exception_.Clear();
-}
-
-ScriptPromise ExceptionState::Reject(ScriptState* script_state) {
- ScriptPromise promise = ScriptPromise::Reject(script_state, GetException());
- ClearException();
- return promise;
-}
-
-void ExceptionState::Reject(ScriptPromiseResolver* resolver) {
- resolver->Reject(GetException());
- ClearException();
-}
-
-void ExceptionState::SetException(ExceptionCode ec,
- const String& message,
- v8::Local<v8::Value> exception) {
- CHECK(ec);
-
- code_ = ec;
- message_ = message;
- if (exception.IsEmpty()) {
- exception_.Clear();
- } else {
- DCHECK(isolate_);
- exception_.Set(isolate_, exception);
- }
-}
-
-String ExceptionState::AddExceptionContext(const String& message) const {
- if (message.IsEmpty())
- return message;
-
- String processed_message = message;
- if (PropertyName() && InterfaceName() && context_ != kUnknownContext) {
- if (context_ == kDeletionContext)
- processed_message = ExceptionMessages::FailedToDelete(
- PropertyName(), InterfaceName(), message);
- else if (context_ == kExecutionContext)
- processed_message = ExceptionMessages::FailedToExecute(
- PropertyName(), InterfaceName(), message);
- else if (context_ == kGetterContext)
- processed_message = ExceptionMessages::FailedToGet(
- PropertyName(), InterfaceName(), message);
- else if (context_ == kSetterContext)
- processed_message = ExceptionMessages::FailedToSet(
- PropertyName(), InterfaceName(), message);
- } else if (!PropertyName() && InterfaceName()) {
- if (context_ == kConstructionContext)
- processed_message =
- ExceptionMessages::FailedToConstruct(InterfaceName(), message);
- else if (context_ == kEnumerationContext)
- processed_message =
- ExceptionMessages::FailedToEnumerate(InterfaceName(), message);
- else if (context_ == kIndexedDeletionContext)
- processed_message =
- ExceptionMessages::FailedToDeleteIndexed(InterfaceName(), message);
- else if (context_ == kIndexedGetterContext)
- processed_message =
- ExceptionMessages::FailedToGetIndexed(InterfaceName(), message);
- else if (context_ == kIndexedSetterContext)
- processed_message =
- ExceptionMessages::FailedToSetIndexed(InterfaceName(), message);
- }
- return processed_message;
-}
-
-NonThrowableExceptionState::NonThrowableExceptionState()
- : ExceptionState(nullptr,
- ExceptionState::kUnknownContext,
- nullptr,
- nullptr),
- file_(""),
- line_(0) {}
-
-NonThrowableExceptionState::NonThrowableExceptionState(const char* file,
- int line)
- : ExceptionState(nullptr,
- ExceptionState::kUnknownContext,
- nullptr,
- nullptr),
- file_(file),
- line_(line) {}
-
-void NonThrowableExceptionState::ThrowDOMException(ExceptionCode ec,
- const String& message) {
- DCHECK_AT(false, file_, line_) << "DOMExeption should not be thrown.";
-}
-
-void NonThrowableExceptionState::ThrowRangeError(const String& message) {
- DCHECK_AT(false, file_, line_) << "RangeError should not be thrown.";
-}
-
-void NonThrowableExceptionState::ThrowSecurityError(
- const String& sanitized_message,
- const String&) {
- DCHECK_AT(false, file_, line_) << "SecurityError should not be thrown.";
-}
-
-void NonThrowableExceptionState::ThrowTypeError(const String& message) {
- DCHECK_AT(false, file_, line_) << "TypeError should not be thrown.";
-}
-
-void NonThrowableExceptionState::RethrowV8Exception(v8::Local<v8::Value>) {
- DCHECK_AT(false, file_, line_) << "An exception should not be rethrown.";
-}
-
-void DummyExceptionStateForTesting::ThrowDOMException(ExceptionCode ec,
- const String& message) {
- SetException(ec, message, v8::Local<v8::Value>());
-}
-
-void DummyExceptionStateForTesting::ThrowRangeError(const String& message) {
- SetException(kV8RangeError, message, v8::Local<v8::Value>());
-}
-
-void DummyExceptionStateForTesting::ThrowSecurityError(
- const String& sanitized_message,
- const String&) {
- SetException(kSecurityError, sanitized_message, v8::Local<v8::Value>());
-}
-
-void DummyExceptionStateForTesting::ThrowTypeError(const String& message) {
- SetException(kV8TypeError, message, v8::Local<v8::Value>());
-}
-
-void DummyExceptionStateForTesting::RethrowV8Exception(v8::Local<v8::Value>) {
- SetException(kRethrownException, String(), v8::Local<v8::Value>());
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/exception_state.h b/chromium/third_party/blink/renderer/bindings/core/v8/exception_state.h
deleted file mode 100644
index bb0aa86ea8b..00000000000
--- a/chromium/third_party/blink/renderer/bindings/core/v8/exception_state.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * 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_BINDINGS_CORE_V8_EXCEPTION_STATE_H_
-#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_EXCEPTION_STATE_H_
-
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
-#include "third_party/blink/renderer/platform/bindings/scoped_persistent.h"
-#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-typedef int ExceptionCode;
-class ScriptPromiseResolver;
-class ScriptState;
-
-// ExceptionState is a scope-like class and provides a way to throw an exception
-// with an option to cancel it. An exception message may be auto-generated.
-// You can convert an exception to a reject promise.
-class CORE_EXPORT ExceptionState {
- STACK_ALLOCATED();
- WTF_MAKE_NONCOPYABLE(ExceptionState);
-
- public:
- enum ContextType {
- kConstructionContext,
- kExecutionContext,
- kDeletionContext,
- kGetterContext,
- kSetterContext,
- kEnumerationContext,
- kQueryContext,
- kIndexedGetterContext,
- kIndexedSetterContext,
- kIndexedDeletionContext,
- kUnknownContext, // FIXME: Remove this once we've flipped over to the new
- // API.
- };
-
- ExceptionState(v8::Isolate* isolate,
- ContextType context_type,
- const char* interface_name,
- const char* property_name)
- : code_(0),
- context_(context_type),
- property_name_(property_name),
- interface_name_(interface_name),
- isolate_(isolate) {}
-
- ExceptionState(v8::Isolate* isolate,
- ContextType context_type,
- const char* interface_name)
- : ExceptionState(isolate, context_type, interface_name, nullptr) {
-#if DCHECK_IS_ON()
- switch (context_) {
- case kConstructionContext:
- case kEnumerationContext:
- case kIndexedGetterContext:
- case kIndexedSetterContext:
- case kIndexedDeletionContext:
- break;
- default:
- NOTREACHED();
- }
-#endif // DCHECK_IS_ON()
- }
-
- ~ExceptionState() {
- if (!exception_.IsEmpty()) {
- V8ThrowException::ThrowException(isolate_, exception_.NewLocal(isolate_));
- }
- }
-
- void ThrowDOMException(ExceptionCode, const char* message);
- void ThrowRangeError(const char* message);
- void ThrowSecurityError(const char* sanitized_message,
- const char* unsanitized_message = nullptr);
- void ThrowTypeError(const char* message);
-
- virtual void ThrowDOMException(ExceptionCode, const String& message);
- virtual void ThrowRangeError(const String& message);
- virtual void ThrowSecurityError(const String& sanitized_message,
- const String& unsanitized_message = String());
- virtual void ThrowTypeError(const String& message);
- virtual void RethrowV8Exception(v8::Local<v8::Value>);
-
- bool HadException() const { return code_; }
- void ClearException();
-
- ExceptionCode Code() const { return code_; }
- const String& Message() const { return message_; }
- v8::Local<v8::Value> GetException() {
- DCHECK(!exception_.IsEmpty());
- return exception_.NewLocal(isolate_);
- }
-
- // This method clears out the exception which |this| has.
- ScriptPromise Reject(ScriptState*);
-
- // This method clears out the exception which |this| has.
- void Reject(ScriptPromiseResolver*);
-
- ContextType Context() const { return context_; }
- const char* PropertyName() const { return property_name_; }
- const char* InterfaceName() const { return interface_name_; }
-
- String AddExceptionContext(const String&) const;
-
- protected:
- // An ExceptionCode for the case that an exception is rethrown. In that
- // case, we cannot determine an exception code.
- static const int kRethrownException = kUnknownError;
-
- void SetException(ExceptionCode, const String&, v8::Local<v8::Value>);
-
- private:
- ExceptionCode code_;
- ContextType context_;
- String message_;
- const char* property_name_;
- const char* interface_name_;
- // The exception is empty when it was thrown through
- // DummyExceptionStateForTesting.
- ScopedPersistent<v8::Value> exception_;
- v8::Isolate* isolate_;
-};
-
-// NonThrowableExceptionState never allow call sites to throw an exception.
-// Should be used if an exception must not be thrown.
-class CORE_EXPORT NonThrowableExceptionState final : public ExceptionState {
- public:
- NonThrowableExceptionState();
- NonThrowableExceptionState(const char*, int);
-
- void ThrowDOMException(ExceptionCode, const String& message) override;
- void ThrowTypeError(const String& message) override;
- void ThrowSecurityError(const String& sanitized_message,
- const String& unsanitized_message) override;
- void ThrowRangeError(const String& message) override;
- void RethrowV8Exception(v8::Local<v8::Value>) override;
- ExceptionState& ReturnThis() { return *this; }
-
- private:
- const char* file_;
- const int line_;
-};
-
-// Syntax sugar for NonThrowableExceptionState.
-// This can be used as a default value of an ExceptionState parameter like this:
-//
-// Node* removeChild(Node*, ExceptionState& = ASSERT_NO_EXCEPTION);
-#if DCHECK_IS_ON()
-#define ASSERT_NO_EXCEPTION \
- (::blink::NonThrowableExceptionState(__FILE__, __LINE__).ReturnThis())
-#else
-#define ASSERT_NO_EXCEPTION \
- (::blink::DummyExceptionStateForTesting().ReturnThis())
-#endif
-
-// DummyExceptionStateForTesting ignores all thrown exceptions. You should not
-// use DummyExceptionStateForTesting in production code, where you need to
-// handle all exceptions properly. If you really need to ignore exceptions in
-// production code for some special reason, explicitly call clearException().
-class CORE_EXPORT DummyExceptionStateForTesting final : public ExceptionState {
- public:
- DummyExceptionStateForTesting()
- : ExceptionState(nullptr,
- ExceptionState::kUnknownContext,
- nullptr,
- nullptr) {}
- ~DummyExceptionStateForTesting() {
- // Prevent the base class throw an exception.
- if (HadException()) {
- ClearException();
- }
- }
- void ThrowDOMException(ExceptionCode, const String& message) override;
- void ThrowTypeError(const String& message) override;
- void ThrowSecurityError(const String& sanitized_message,
- const String& unsanitized_message) override;
- void ThrowRangeError(const String& message) override;
- void RethrowV8Exception(v8::Local<v8::Value>) override;
- ExceptionState& ReturnThis() { return *this; }
-};
-
-// Syntax sugar for DummyExceptionStateForTesting.
-// This can be used as a default value of an ExceptionState parameter like this:
-//
-// Node* removeChild(Node*, ExceptionState& = IGNORE_EXCEPTION_FOR_TESTING);
-#define IGNORE_EXCEPTION_FOR_TESTING \
- (::blink::DummyExceptionStateForTesting().ReturnThis())
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_EXCEPTION_STATE_H_
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/generated_code_helper.cc b/chromium/third_party/blink/renderer/bindings/core/v8/generated_code_helper.cc
index 7135792982e..55f985060e4 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/generated_code_helper.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/generated_code_helper.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h"
namespace blink {
@@ -32,13 +33,35 @@ v8::Local<v8::Value> V8Deserialize(v8::Isolate* isolate,
}
bool IsCallbackFunctionRunnable(
- const ScriptState* callback_relevant_script_state) {
+ const ScriptState* callback_relevant_script_state,
+ ScriptState* incumbent_script_state) {
if (!callback_relevant_script_state->ContextIsValid())
return false;
- const ExecutionContext* execution_context =
+ const ExecutionContext* relevant_execution_context =
ExecutionContext::From(callback_relevant_script_state);
- return execution_context && !execution_context->IsContextPaused() &&
- !execution_context->IsContextDestroyed();
+ if (!relevant_execution_context ||
+ relevant_execution_context->IsContextPaused() ||
+ relevant_execution_context->IsContextDestroyed()) {
+ return false;
+ }
+
+ // TODO(yukishiino): Callback function type value must make the incumbent
+ // environment alive, i.e. the reference to v8::Context must be strong.
+ v8::HandleScope handle_scope(incumbent_script_state->GetIsolate());
+ v8::Local<v8::Context> incumbent_context =
+ incumbent_script_state->GetContext();
+ ExecutionContext* incumbent_execution_context =
+ incumbent_context.IsEmpty() ? nullptr
+ : ToExecutionContext(incumbent_context);
+ // The incumbent realm schedules the currently-running callback although it
+ // may not correspond to the currently-running function object. So we check
+ // the incumbent context which originally schedules the currently-running
+ // callback to see whether the script setting is disabled before invoking
+ // the callback.
+ return incumbent_execution_context &&
+ !incumbent_execution_context->IsContextPaused() &&
+ !incumbent_execution_context->IsContextDestroyed() &&
+ incumbent_execution_context->CanExecuteScripts(kAboutToExecuteScript);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/generated_code_helper.h b/chromium/third_party/blink/renderer/bindings/core/v8/generated_code_helper.h
index 15442f0f4d1..806710d2932 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/generated_code_helper.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/generated_code_helper.h
@@ -11,10 +11,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_GENERATED_CODE_HELPER_H_
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_GENERATED_CODE_HELPER_H_
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "v8/include/v8.h"
namespace blink {
@@ -51,7 +51,8 @@ class CORE_EXPORT ExceptionToRejectPromiseScope {
// promises must also be created in the current realm while regular promises
// are created in the relevant realm of the context object.
ScriptState* script_state = ScriptState::ForCurrentRealm(info_);
- V8SetReturnValue(info_, exception_state_.Reject(script_state).V8Value());
+ V8SetReturnValue(
+ info_, ScriptPromise::Reject(script_state, exception_state_).V8Value());
}
private:
@@ -60,7 +61,8 @@ class CORE_EXPORT ExceptionToRejectPromiseScope {
};
CORE_EXPORT bool IsCallbackFunctionRunnable(
- const ScriptState* callback_relevant_script_state);
+ const ScriptState* callback_relevant_script_state,
+ ScriptState* incumbent_script_state);
using InstallTemplateFunction =
void (*)(v8::Isolate* isolate,
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding_test.cc
index 0c41e8d38e8..b26ab984bc6 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding_test.cc
@@ -5,11 +5,13 @@
#include "third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_extras_test_utils.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
+#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "v8/include/v8.h"
@@ -31,6 +33,7 @@ TEST(InitializeV8ExtrasBindingTest, SupportedId) {
V8TestingScope scope;
InitializeV8ExtrasBinding(scope.GetScriptState());
AddExtrasBindingToGlobal(&scope);
+ Page::InsertOrdinaryPageForTesting(&scope.GetPage());
ScriptValue rv = EvalWithPrintingError(
&scope, "binding.countUse('TransformStreamConstructor');");
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/iterable.h b/chromium/third_party/blink/renderer/bindings/core/v8/iterable.h
index 5bab57aebdd..374baf58e0f 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/iterable.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/iterable.h
@@ -5,11 +5,11 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_ITERABLE_H_
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_ITERABLE_H_
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
#include "third_party/blink/renderer/core/dom/iterator.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc b/chromium/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
index 5c00e3e935b..cbd9f811d97 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/local_window_proxy.cc
@@ -41,6 +41,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_page_popup_controller_binding.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_window.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/html/document_name_collection.h"
@@ -65,6 +66,11 @@
namespace blink {
+void LocalWindowProxy::Trace(blink::Visitor* visitor) {
+ visitor->Trace(script_state_);
+ WindowProxy::Trace(visitor);
+}
+
void LocalWindowProxy::DisposeContext(Lifecycle next_status,
FrameReuseStatus frame_reuse_status) {
DCHECK(next_status == Lifecycle::kGlobalObjectIsDetached ||
@@ -73,13 +79,13 @@ void LocalWindowProxy::DisposeContext(Lifecycle next_status,
if (lifecycle_ != Lifecycle::kContextIsInitialized)
return;
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
v8::Local<v8::Context> context = script_state_->GetContext();
// The embedder could run arbitrary code in response to the
// willReleaseScriptContext callback, so all disposing should happen after
// it returns.
GetFrame()->Client()->WillReleaseScriptContext(context, world_->GetWorldId());
- MainThreadDebugger::Instance()->ContextWillBeDestroyed(script_state_.get());
+ MainThreadDebugger::Instance()->ContextWillBeDestroyed(script_state_);
if (next_status == Lifecycle::kGlobalObjectIsDetached) {
// Clean up state on the global proxy, which will be reused.
@@ -138,7 +144,7 @@ void LocalWindowProxy::Initialize() {
CreateContext();
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
v8::Local<v8::Context> context = script_state_->GetContext();
if (global_proxy_.IsEmpty()) {
global_proxy_.Set(GetIsolate(), context->Global());
@@ -169,8 +175,8 @@ void LocalWindowProxy::Initialize() {
{
TRACE_EVENT1("v8", "ContextCreatedNotification", "IsMainFrame",
GetFrame()->IsMainFrame());
- MainThreadDebugger::Instance()->ContextCreated(script_state_.get(),
- GetFrame(), origin);
+ MainThreadDebugger::Instance()->ContextCreated(script_state_, GetFrame(),
+ origin);
GetFrame()->Client()->DidCreateScriptContext(context, world_->GetWorldId());
}
@@ -238,7 +244,7 @@ void LocalWindowProxy::CreateContext() {
script_state_ = ScriptState::Create(context, world_);
- InitializeV8ExtrasBinding(script_state_.get());
+ InitializeV8ExtrasBinding(script_state_);
DCHECK(lifecycle_ == Lifecycle::kContextIsUninitialized ||
lifecycle_ == Lifecycle::kGlobalObjectIsDetached);
@@ -276,7 +282,7 @@ void LocalWindowProxy::InstallConditionalFeatures() {
// for origin trials, which do not apply to extensions). Some conditional
// bindings cannot be enabled until the execution context is available
// (e.g. parsing the document, inspecting HTTP headers).
- InstallOriginTrialFeatures(wrapper_type_info, script_state_.get(),
+ InstallOriginTrialFeatures(wrapper_type_info, script_state_,
v8::Local<v8::Object>(),
v8::Local<v8::Function>());
}
@@ -333,7 +339,7 @@ void LocalWindowProxy::UpdateDocumentProperty() {
TRACE_EVENT1("v8", "LocalWindowProxy::UpdateDocumentProperty", "IsMainFrame",
GetFrame()->IsMainFrame());
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
v8::Local<v8::Context> context = script_state_->GetContext();
v8::Local<v8::Value> document_wrapper =
ToV8(GetFrame()->GetDocument(), context->Global(), GetIsolate());
@@ -513,7 +519,7 @@ void LocalWindowProxy::NamedItemAdded(HTMLDocument* document,
if (lifecycle_ != Lifecycle::kContextIsInitialized)
return;
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
v8::Local<v8::Object> document_wrapper =
world_->DomDataStore().Get(document, GetIsolate());
document_wrapper
@@ -537,7 +543,7 @@ void LocalWindowProxy::NamedItemRemoved(HTMLDocument* document,
if (document->HasNamedItem(name))
return;
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
v8::Local<v8::Object> document_wrapper =
world_->DomDataStore().Get(document, GetIsolate());
document_wrapper
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/local_window_proxy.h b/chromium/third_party/blink/renderer/bindings/core/v8/local_window_proxy.h
index 01545a488e9..90cd4564f9d 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/local_window_proxy.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/local_window_proxy.h
@@ -54,6 +54,8 @@ class LocalWindowProxy final : public WindowProxy {
return new LocalWindowProxy(isolate, frame, std::move(world));
}
+ void Trace(blink::Visitor*) override;
+
v8::Local<v8::Context> ContextIfInitialized() const {
return script_state_ ? script_state_->GetContext()
: v8::Local<v8::Context>();
@@ -107,7 +109,7 @@ class LocalWindowProxy final : public WindowProxy {
LocalFrame* GetFrame() const { return ToLocalFrame(WindowProxy::GetFrame()); }
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
};
DEFINE_TYPE_CASTS(LocalWindowProxy,
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h b/chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h
index f940ddd3c07..ac4a9d03dfd 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl_test.cc
index 27af0849e6c..6cf10aeb8ec 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/native_value_traits_impl_test.cc
@@ -8,12 +8,12 @@
#include "testing/gtest/include/gtest/gtest-death-test.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_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_internals.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_test_sequence_callback.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/referrer_script_info.cc b/chromium/third_party/blink/renderer/bindings/core/v8/referrer_script_info.cc
index f6d30c92d66..e1ec82bd2ca 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/referrer_script_info.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/referrer_script_info.cc
@@ -16,6 +16,7 @@ enum HostDefinedOptionsIndex : size_t {
kCredentialsMode,
kNonce,
kParserState,
+ kReferrerPolicy,
kLength
};
@@ -48,7 +49,13 @@ ReferrerScriptInfo ReferrerScriptInfo::FromV8HostDefinedOptions(
ParserDisposition parser_state = static_cast<ParserDisposition>(
parser_state_value->IntegerValue(context).ToChecked());
- return ReferrerScriptInfo(base_url, credentials_mode, nonce, parser_state);
+ v8::Local<v8::Primitive> referrer_policy_value =
+ host_defined_options->Get(kReferrerPolicy);
+ ReferrerPolicy referrer_policy = static_cast<ReferrerPolicy>(
+ referrer_policy_value->IntegerValue(context).ToChecked());
+
+ return ReferrerScriptInfo(base_url, credentials_mode, nonce, parser_state,
+ referrer_policy);
}
v8::Local<v8::PrimitiveArray> ReferrerScriptInfo::ToV8HostDefinedOptions(
@@ -77,6 +84,11 @@ v8::Local<v8::PrimitiveArray> ReferrerScriptInfo::ToV8HostDefinedOptions(
host_defined_options->Set(HostDefinedOptionsIndex::kParserState,
parser_state_value);
+ v8::Local<v8::Primitive> referrer_policy_value = v8::Integer::NewFromUnsigned(
+ isolate, static_cast<uint32_t>(referrer_policy_));
+ host_defined_options->Set(HostDefinedOptionsIndex::kReferrerPolicy,
+ referrer_policy_value);
+
return host_defined_options;
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/referrer_script_info.h b/chromium/third_party/blink/renderer/bindings/core/v8/referrer_script_info.h
index 69482f55939..ca9b68ed965 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/referrer_script_info.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/referrer_script_info.h
@@ -6,11 +6,9 @@
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_REFERRER_SCRIPT_INFO_H_
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
-#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/loader/fetch/access_control_status.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
#include "third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h"
+#include "third_party/blink/renderer/platform/weborigin/referrer_policy.h"
#include "third_party/blink/renderer/platform/wtf/text/text_position.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "v8/include/v8.h"
@@ -26,16 +24,19 @@ class CORE_EXPORT ReferrerScriptInfo {
ReferrerScriptInfo(const KURL& base_url,
network::mojom::FetchCredentialsMode credentials_mode,
const String& nonce,
- ParserDisposition parser_state)
+ ParserDisposition parser_state,
+ ReferrerPolicy referrer_policy)
: base_url_(base_url),
credentials_mode_(credentials_mode),
nonce_(nonce),
- parser_state_(parser_state) {}
+ parser_state_(parser_state),
+ referrer_policy_(referrer_policy) {}
ReferrerScriptInfo(const KURL& base_url, const ScriptFetchOptions& options)
: ReferrerScriptInfo(base_url,
options.CredentialsMode(),
options.Nonce(),
- options.ParserState()) {}
+ options.ParserState(),
+ options.GetReferrerPolicy()) {}
static ReferrerScriptInfo FromV8HostDefinedOptions(
v8::Local<v8::Context>,
@@ -48,6 +49,7 @@ class CORE_EXPORT ReferrerScriptInfo {
}
const String& Nonce() const { return nonce_; }
ParserDisposition ParserState() const { return parser_state_; }
+ ReferrerPolicy GetReferrerPolicy() const { return referrer_policy_; }
bool IsDefaultValue() const {
return base_url_.IsNull() &&
@@ -77,6 +79,11 @@ class CORE_EXPORT ReferrerScriptInfo {
// The default value is "not-parser-inserted" per:
// https://html.spec.whatwg.org/multipage/webappapis.html#default-classic-script-fetch-options
const ParserDisposition parser_state_ = kNotParserInserted;
+
+ // Spec: "referencing script's referrer policy"
+ // The default value is "the empty string" per:
+ // https://html.spec.whatwg.org/multipage/webappapis.html#default-classic-script-fetch-options
+ const ReferrerPolicy referrer_policy_ = kReferrerPolicyDefault;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/referrer_script_info_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/referrer_script_info_test.cc
index a0b1284d820..16efb5041e2 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/referrer_script_info_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/referrer_script_info_test.cc
@@ -15,7 +15,7 @@ TEST(ReferrerScriptInfo, IsDefaultValue) {
EXPECT_FALSE(
ReferrerScriptInfo(KURL("http://example.com"),
network::mojom::FetchCredentialsMode::kInclude, "",
- kNotParserInserted)
+ kNotParserInserted, kReferrerPolicyDefault)
.IsDefaultValue());
}
@@ -28,7 +28,7 @@ TEST(ReferrerScriptInfo, ToFromV8) {
.IsEmpty());
ReferrerScriptInfo info(url, network::mojom::FetchCredentialsMode::kInclude,
- "foobar", kNotParserInserted);
+ "foobar", kNotParserInserted, kReferrerPolicyOrigin);
v8::Local<v8::PrimitiveArray> v8_info =
info.ToV8HostDefinedOptions(scope.GetIsolate());
@@ -39,6 +39,7 @@ TEST(ReferrerScriptInfo, ToFromV8) {
decoded.CredentialsMode());
EXPECT_EQ("foobar", decoded.Nonce());
EXPECT_EQ(kNotParserInserted, decoded.ParserState());
+ EXPECT_EQ(kReferrerPolicyOrigin, decoded.GetReferrerPolicy());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/rejected_promises.cc b/chromium/third_party/blink/renderer/bindings/core/v8/rejected_promises.cc
index c49a04a751c..7294894f729 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/rejected_promises.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/rejected_promises.cc
@@ -178,7 +178,7 @@ class RejectedPromises::Message final {
data.GetParameter()->exception_.Clear();
}
- ScriptState* script_state_;
+ Persistent<ScriptState> script_state_;
ScopedPersistent<v8::Promise> promise_;
ScopedPersistent<v8::Value> exception_;
String error_message_;
@@ -208,7 +208,7 @@ void RejectedPromises::RejectedWithNoHandler(
void RejectedPromises::HandlerAdded(v8::PromiseRejectMessage data) {
// First look it up in the pending messages and fast return, it'll be covered
// by processQueue().
- for (auto it = queue_.begin(); it != queue_.end(); ++it) {
+ for (auto* it = queue_.begin(); it != queue_.end(); ++it) {
if (!(*it)->IsCollected() && (*it)->HasPromise(data.GetPromise())) {
queue_.erase(it);
return;
@@ -235,46 +235,35 @@ void RejectedPromises::Dispose() {
if (queue_.IsEmpty())
return;
- std::unique_ptr<MessageQueue> queue = std::make_unique<MessageQueue>();
- queue->Swap(queue_);
- ProcessQueueNow(std::move(queue));
+ ProcessQueueNow(std::move(queue_));
+ queue_.clear();
}
void RejectedPromises::ProcessQueue() {
if (queue_.IsEmpty())
return;
- std::map<ExecutionContext*, std::unique_ptr<MessageQueue>> queues;
- while (!queue_.IsEmpty()) {
- std::unique_ptr<Message> message = queue_.TakeFirst();
- ExecutionContext* context = message->GetContext();
- if (queues.find(context) == queues.end()) {
- queues.emplace(context, std::make_unique<MessageQueue>());
- }
- queues[context]->emplace_back(std::move(message));
- }
+ std::map<ExecutionContext*, MessageQueue> queues;
+ for (auto& message : queue_)
+ queues[message->GetContext()].push_back(std::move(message));
+ queue_.clear();
for (auto& kv : queues) {
- std::unique_ptr<MessageQueue> queue = std::make_unique<MessageQueue>();
- queue->Swap(*kv.second);
kv.first->GetTaskRunner(blink::TaskType::kDOMManipulation)
->PostTask(FROM_HERE, WTF::Bind(&RejectedPromises::ProcessQueueNow,
scoped_refptr<RejectedPromises>(this),
- WTF::Passed(std::move(queue))));
+ WTF::Passed(std::move(kv.second))));
}
}
-void RejectedPromises::ProcessQueueNow(std::unique_ptr<MessageQueue> queue) {
+void RejectedPromises::ProcessQueueNow(MessageQueue queue) {
// Remove collected handlers.
- for (size_t i = 0; i < reported_as_errors_.size();) {
- if (reported_as_errors_.at(i)->IsCollected())
- reported_as_errors_.EraseAt(i);
- else
- ++i;
- }
+ auto* new_end = std::remove_if(
+ reported_as_errors_.begin(), reported_as_errors_.end(),
+ [](const auto& message) { return message->IsCollected(); });
+ reported_as_errors_.Shrink(new_end - reported_as_errors_.begin());
- while (!queue->IsEmpty()) {
- std::unique_ptr<Message> message = queue->TakeFirst();
+ for (auto& message : queue) {
if (message->IsCollected())
continue;
if (!message->HasHandler()) {
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/rejected_promises.h b/chromium/third_party/blink/renderer/bindings/core/v8/rejected_promises.h
index 2ec8e8cad0e..71821c55040 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/rejected_promises.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/rejected_promises.h
@@ -8,7 +8,6 @@
#include <memory>
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/platform/loader/fetch/access_control_status.h"
-#include "third_party/blink/renderer/platform/wtf/deque.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -46,9 +45,9 @@ class RejectedPromises final : public RefCounted<RejectedPromises> {
RejectedPromises();
- using MessageQueue = Deque<std::unique_ptr<Message>>;
+ using MessageQueue = Vector<std::unique_ptr<Message>>;
- void ProcessQueueNow(std::unique_ptr<MessageQueue>);
+ void ProcessQueueNow(MessageQueue);
void RevokeNow(std::unique_ptr<Message>);
MessageQueue queue_;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc b/chromium/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc
index 55b132e8ce7..6b96f3d1277 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/scheduled_action.cc
@@ -33,6 +33,7 @@
#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_source_code.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#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/bindings/core/v8/v8_gc_controller.h"
@@ -44,6 +45,7 @@
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
namespace blink {
@@ -89,9 +91,14 @@ void ScheduledAction::Dispose() {
code_ = String();
info_.Clear();
function_.Clear();
+ script_state_->Reset();
script_state_.Clear();
}
+void ScheduledAction::Trace(blink::Visitor* visitor) {
+ visitor->Trace(script_state_);
+}
+
void ScheduledAction::Execute(ExecutionContext* context) {
if (!script_state_->ContextIsValid()) {
DVLOG(1) << "ScheduledAction::execute " << this << ": context is empty";
@@ -99,7 +106,7 @@ void ScheduledAction::Execute(ExecutionContext* context) {
}
// ExecutionContext::CanExecuteScripts() relies on the current context to
// determine if it is allowed. Enter the scope here.
- ScriptState::Scope scope(script_state_.Get());
+ ScriptState::Scope scope(script_state_->Get());
if (context->IsDocument()) {
LocalFrame* frame = ToDocument(context)->GetFrame();
@@ -122,7 +129,7 @@ void ScheduledAction::Execute(ExecutionContext* context) {
ScheduledAction::ScheduledAction(ScriptState* script_state,
const ScriptValue& function,
const Vector<ScriptValue>& arguments)
- : script_state_(script_state), info_(script_state->GetIsolate()) {
+ : ScheduledAction(script_state) {
DCHECK(function.IsFunction());
function_.Set(script_state->GetIsolate(),
v8::Local<v8::Function>::Cast(function.V8Value()));
@@ -132,12 +139,13 @@ ScheduledAction::ScheduledAction(ScriptState* script_state,
}
ScheduledAction::ScheduledAction(ScriptState* script_state, const String& code)
- : script_state_(script_state),
- info_(script_state->GetIsolate()),
- code_(code) {}
+ : ScheduledAction(script_state) {
+ code_ = code;
+}
ScheduledAction::ScheduledAction(ScriptState* script_state)
- : script_state_(script_state), info_(script_state->GetIsolate()) {}
+ : script_state_(ScriptStateProtectingContext::Create(script_state)),
+ info_(script_state->GetIsolate()) {}
void ScheduledAction::Execute(LocalFrame* frame) {
DCHECK(script_state_->ContextIsValid());
@@ -181,7 +189,7 @@ void ScheduledAction::Execute(WorkerGlobalScope* worker) {
}
if (!function_.IsEmpty()) {
- ScriptState::Scope scope(script_state_.Get());
+ ScriptState::Scope scope(script_state_->Get());
v8::Local<v8::Function> function =
function_.NewLocal(script_state_->GetIsolate());
ScriptState* script_state_for_func =
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/scheduled_action.h b/chromium/third_party/blink/renderer/bindings/core/v8/scheduled_action.h
index e042ebd7339..e115da2ef77 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/scheduled_action.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/scheduled_action.h
@@ -36,12 +36,14 @@
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "v8/include/v8.h"
namespace blink {
class LocalFrame;
class ExecutionContext;
+class ScriptValue;
class WorkerGlobalScope;
class ScheduledAction final
@@ -60,7 +62,7 @@ class ScheduledAction final
~ScheduledAction();
void Dispose();
- void Trace(blink::Visitor* visitor) {}
+ void Trace(blink::Visitor*);
void Execute(ExecutionContext*);
@@ -77,7 +79,7 @@ class ScheduledAction final
void Execute(WorkerGlobalScope*);
void CreateLocalHandlesForArgs(Vector<v8::Local<v8::Value>>* handles);
- ScriptStateProtectingContext script_state_;
+ Member<ScriptStateProtectingContext> script_state_;
ScopedPersistent<v8::Function> function_;
V8PersistentValueVector<v8::Value> info_;
String code_;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_controller.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_controller.cc
index d9b8da2d26a..a875e304b0d 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_controller.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_controller.cc
@@ -33,8 +33,10 @@
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/public/web/web_settings.h"
+#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.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/bindings/core/v8/v8_code_cache.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
#include "third_party/blink/renderer/bindings/core/v8/window_proxy.h"
@@ -82,25 +84,6 @@ void ScriptController::UpdateSecurityOrigin(
window_proxy_manager_->UpdateSecurityOrigin(security_origin);
}
-namespace {
-
-V8CacheOptions CacheOptions(const CachedMetadataHandler* cache_handler,
- const Settings* settings) {
- V8CacheOptions v8_cache_options(kV8CacheOptionsDefault);
- if (settings) {
- v8_cache_options = settings->GetV8CacheOptions();
- if (v8_cache_options == kV8CacheOptionsNone)
- return kV8CacheOptionsNone;
- }
- // If the resource is served from CacheStorage, generate the V8 code cache in
- // the first load.
- if (cache_handler && cache_handler->IsServedFromCacheStorage())
- return kV8CacheOptionsCodeWithoutHeatCheck;
- return v8_cache_options;
-}
-
-} // namespace
-
v8::Local<v8::Value> ScriptController::ExecuteScriptAndReturnValue(
v8::Local<v8::Context> context,
const ScriptSourceCode& source,
@@ -113,10 +96,9 @@ v8::Local<v8::Value> ScriptController::ExecuteScriptAndReturnValue(
source.StartPosition()));
v8::Local<v8::Value> result;
{
- CachedMetadataHandler* cache_handler = source.CacheHandler();
-
- V8CacheOptions v8_cache_options =
- CacheOptions(cache_handler, GetFrame()->GetSettings());
+ V8CacheOptions v8_cache_options = kV8CacheOptionsDefault;
+ if (const Settings* settings = GetFrame()->GetSettings())
+ v8_cache_options = settings->GetV8CacheOptions();
// Isolate exceptions that occur when compiling and executing
// the code. These exceptions should not interfere with
@@ -134,10 +116,10 @@ v8::Local<v8::Value> ScriptController::ExecuteScriptAndReturnValue(
v8::Local<v8::Script> script;
v8::ScriptCompiler::CompileOptions compile_options;
- V8ScriptRunner::ProduceCacheOptions produce_cache_options;
+ V8CodeCache::ProduceCacheOptions produce_cache_options;
v8::ScriptCompiler::NoCacheReason no_cache_reason;
std::tie(compile_options, produce_cache_options, no_cache_reason) =
- V8ScriptRunner::GetCompileOptions(v8_cache_options, source);
+ V8CodeCache::GetCompileOptions(v8_cache_options, source);
if (!V8ScriptRunner::CompileScript(ScriptState::From(context), source,
access_control_status, compile_options,
no_cache_reason, referrer_info)
@@ -147,8 +129,9 @@ v8::Local<v8::Value> ScriptController::ExecuteScriptAndReturnValue(
v8::MaybeLocal<v8::Value> maybe_result;
maybe_result = V8ScriptRunner::RunCompiledScript(GetIsolate(), script,
GetFrame()->GetDocument());
- V8ScriptRunner::ProduceCache(GetIsolate(), script, source,
- produce_cache_options, compile_options);
+ probe::produceCompilationCache(frame_, source, script);
+ V8CodeCache::ProduceCache(GetIsolate(), script, source,
+ produce_cache_options, compile_options);
if (!maybe_result.ToLocal(&result)) {
return result;
@@ -231,8 +214,7 @@ bool ScriptController::ExecuteScriptIfJavaScriptURL(const KURL& url,
return false;
const int kJavascriptSchemeLength = sizeof("javascript:") - 1;
- String script_source = DecodeURLEscapeSequences(url.GetString())
- .Substring(kJavascriptSchemeLength);
+ String script_source = DecodeURLEscapeSequences(url.GetString());
bool should_bypass_main_world_content_security_policy =
ContentSecurityPolicy::ShouldBypassMainWorld(GetFrame()->GetDocument());
@@ -247,11 +229,13 @@ bool ScriptController::ExecuteScriptIfJavaScriptURL(const KURL& url,
return true;
}
+ script_source = script_source.Substring(kJavascriptSchemeLength);
+
bool progress_notifications_needed =
GetFrame()->Loader().StateMachine()->IsDisplayingInitialEmptyDocument() &&
!GetFrame()->IsLoading();
if (progress_notifications_needed)
- GetFrame()->Loader().Progress().ProgressStarted(kFrameLoadTypeStandard);
+ GetFrame()->Loader().Progress().ProgressStarted();
Document* owner_document = GetFrame()->GetDocument();
@@ -356,10 +340,9 @@ v8::Local<v8::Value> ScriptController::EvaluateScriptInMainWorld(
return handle_scope.Escape(object);
}
-void ScriptController::ExecuteScriptInIsolatedWorld(
+v8::Local<v8::Value> ScriptController::ExecuteScriptInIsolatedWorld(
int world_id,
- const HeapVector<ScriptSourceCode>& sources,
- Vector<v8::Local<v8::Value>>* results) {
+ const ScriptSourceCode& source) {
DCHECK_GT(world_id, 0);
scoped_refptr<DOMWrapperWorld> world =
@@ -370,30 +353,12 @@ void ScriptController::ExecuteScriptInIsolatedWorld(
v8::Local<v8::Context> context =
isolated_world_window_proxy->ContextIfInitialized();
v8::Context::Scope scope(context);
- v8::Local<v8::Array> result_array =
- v8::Array::New(GetIsolate(), sources.size());
-
- for (size_t i = 0; i < sources.size(); ++i) {
- v8::Local<v8::Value> evaluation_result =
- ExecuteScriptAndReturnValue(context, sources[i]);
- if (evaluation_result.IsEmpty())
- evaluation_result =
- v8::Local<v8::Value>::New(GetIsolate(), v8::Undefined(GetIsolate()));
- bool did_create;
- if (!result_array->CreateDataProperty(context, i, evaluation_result)
- .To(&did_create) ||
- !did_create)
- return;
- }
- if (results) {
- for (size_t i = 0; i < result_array->Length(); ++i) {
- v8::Local<v8::Value> value;
- if (!result_array->Get(context, i).ToLocal(&value))
- return;
- results->push_back(value);
- }
- }
+ v8::Local<v8::Value> evaluation_result =
+ ExecuteScriptAndReturnValue(context, source);
+ if (!evaluation_result.IsEmpty())
+ return evaluation_result;
+ return v8::Local<v8::Value>::New(GetIsolate(), v8::Undefined(GetIsolate()));
}
scoped_refptr<DOMWrapperWorld>
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_controller.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_controller.h
index eed2637bbc4..024678dc8d1 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_controller.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_controller.h
@@ -39,7 +39,6 @@
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/access_control_status.h"
#include "third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h"
-#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/text/text_position.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -111,11 +110,8 @@ class CORE_EXPORT ScriptController final
//
// If an isolated world with the specified ID already exists, it is reused.
// Otherwise, a new world is created.
- //
- // FIXME: We don't want to support multiple scripts.
- void ExecuteScriptInIsolatedWorld(int world_id,
- const HeapVector<ScriptSourceCode>& sources,
- Vector<v8::Local<v8::Value>>* results);
+ v8::Local<v8::Value> ExecuteScriptInIsolatedWorld(int world_id,
+ const ScriptSourceCode&);
// Returns true if argument is a JavaScript URL.
bool ExecuteScriptIfJavaScriptURL(const KURL&, Element*);
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc
index b50601a2d33..68a09410524 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.cc
@@ -10,13 +10,14 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_error_handler.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/events/error_event.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/html/custom/custom_element.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding_macros.h"
+#include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h"
#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "v8/include/v8.h"
@@ -121,14 +122,14 @@ ScriptCustomElementDefinition::ScriptCustomElementDefinition(
attribute_changed_callback_.Set(isolate, attribute_changed_callback);
}
-void ScriptCustomElementDefinition::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(constructor_.Cast<v8::Value>());
- visitor->TraceWrappers(connected_callback_.Cast<v8::Value>());
- visitor->TraceWrappers(disconnected_callback_.Cast<v8::Value>());
- visitor->TraceWrappers(adopted_callback_.Cast<v8::Value>());
- visitor->TraceWrappers(attribute_changed_callback_.Cast<v8::Value>());
- CustomElementDefinition::TraceWrappers(visitor);
+void ScriptCustomElementDefinition::Trace(Visitor* visitor) {
+ visitor->Trace(constructor_.Cast<v8::Value>());
+ visitor->Trace(connected_callback_.Cast<v8::Value>());
+ visitor->Trace(disconnected_callback_.Cast<v8::Value>());
+ visitor->Trace(adopted_callback_.Cast<v8::Value>());
+ visitor->Trace(attribute_changed_callback_.Cast<v8::Value>());
+ visitor->Trace(script_state_);
+ CustomElementDefinition::Trace(visitor);
}
HTMLElement* ScriptCustomElementDefinition::HandleCreateElementSyncException(
@@ -150,7 +151,7 @@ HTMLElement* ScriptCustomElementDefinition::CreateAutonomousCustomElementSync(
const QualifiedName& tag_name) {
if (!script_state_->ContextIsValid())
return CustomElement::CreateFailedElement(document, tag_name);
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
v8::Isolate* isolate = script_state_->GetIsolate();
ExceptionState exception_state(isolate, ExceptionState::kConstructionContext,
@@ -205,7 +206,7 @@ HTMLElement* ScriptCustomElementDefinition::CreateAutonomousCustomElementSync(
bool ScriptCustomElementDefinition::RunConstructor(Element* element) {
if (!script_state_->ContextIsValid())
return false;
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
v8::Isolate* isolate = script_state_->GetIsolate();
// Step 5 says to rethrow the exception; but there is no one to
@@ -225,9 +226,11 @@ bool ScriptCustomElementDefinition::RunConstructor(Element* element) {
const String& message =
"custom element constructors must call super() first and must "
"not return a different object";
- v8::Local<v8::Value> exception = V8ThrowDOMException::CreateDOMException(
- script_state_->GetIsolate(), kInvalidStateError, message);
- V8ScriptRunner::ReportException(isolate, exception);
+ v8::Local<v8::Value> exception = V8ThrowDOMException::CreateOrEmpty(
+ script_state_->GetIsolate(), DOMExceptionCode::kInvalidStateError,
+ message);
+ if (!exception.IsEmpty())
+ V8ScriptRunner::ReportException(isolate, exception);
return false;
}
@@ -237,8 +240,7 @@ bool ScriptCustomElementDefinition::RunConstructor(Element* element) {
Element* ScriptCustomElementDefinition::CallConstructor() {
v8::Isolate* isolate = script_state_->GetIsolate();
DCHECK(ScriptState::Current(isolate) == script_state_);
- ExecutionContext* execution_context =
- ExecutionContext::From(script_state_.get());
+ ExecutionContext* execution_context = ExecutionContext::From(script_state_);
v8::Local<v8::Value> result;
if (!V8ScriptRunner::CallAsConstructor(isolate, Constructor(),
execution_context, 0, nullptr)
@@ -255,7 +257,7 @@ v8::Local<v8::Object> ScriptCustomElementDefinition::Constructor() const {
// CustomElementDefinition
ScriptValue ScriptCustomElementDefinition::GetConstructorForScript() {
- return ScriptValue(script_state_.get(), Constructor());
+ return ScriptValue(script_state_, Constructor());
}
bool ScriptCustomElementDefinition::HasConnectedCallback() const {
@@ -284,8 +286,7 @@ void ScriptCustomElementDefinition::RunCallback(
v8::TryCatch try_catch(isolate);
try_catch.SetVerbose(true);
- ExecutionContext* execution_context =
- ExecutionContext::From(script_state_.get());
+ ExecutionContext* execution_context = ExecutionContext::From(script_state_);
v8::Local<v8::Value> element_handle =
ToV8(element, script_state_->GetContext()->Global(), isolate);
V8ScriptRunner::CallFunction(callback, execution_context, element_handle,
@@ -295,7 +296,7 @@ void ScriptCustomElementDefinition::RunCallback(
void ScriptCustomElementDefinition::RunConnectedCallback(Element* element) {
if (!script_state_->ContextIsValid())
return;
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
v8::Isolate* isolate = script_state_->GetIsolate();
RunCallback(connected_callback_.NewLocal(isolate), element);
}
@@ -303,7 +304,7 @@ void ScriptCustomElementDefinition::RunConnectedCallback(Element* element) {
void ScriptCustomElementDefinition::RunDisconnectedCallback(Element* element) {
if (!script_state_->ContextIsValid())
return;
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
v8::Isolate* isolate = script_state_->GetIsolate();
RunCallback(disconnected_callback_.NewLocal(isolate), element);
}
@@ -313,12 +314,12 @@ void ScriptCustomElementDefinition::RunAdoptedCallback(Element* element,
Document* new_owner) {
if (!script_state_->ContextIsValid())
return;
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
v8::Isolate* isolate = script_state_->GetIsolate();
v8::Local<v8::Value> argv[] = {
ToV8(old_owner, script_state_->GetContext()->Global(), isolate),
ToV8(new_owner, script_state_->GetContext()->Global(), isolate)};
- RunCallback(adopted_callback_.NewLocal(isolate), element, arraysize(argv),
+ RunCallback(adopted_callback_.NewLocal(isolate), element, base::size(argv),
argv);
}
@@ -329,7 +330,7 @@ void ScriptCustomElementDefinition::RunAttributeChangedCallback(
const AtomicString& new_value) {
if (!script_state_->ContextIsValid())
return;
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
v8::Isolate* isolate = script_state_->GetIsolate();
v8::Local<v8::Value> argv[] = {
V8String(isolate, name.LocalName()), V8StringOrNull(isolate, old_value),
@@ -337,7 +338,7 @@ void ScriptCustomElementDefinition::RunAttributeChangedCallback(
V8StringOrNull(isolate, name.NamespaceURI()),
};
RunCallback(attribute_changed_callback_.NewLocal(isolate), element,
- arraysize(argv), argv);
+ base::size(argv), argv);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.h
index 73d8b5e19e7..611de74f9cd 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.h
@@ -43,7 +43,7 @@ class CORE_EXPORT ScriptCustomElementDefinition final
~ScriptCustomElementDefinition() override = default;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
+ void Trace(Visitor*) override;
v8::Local<v8::Object> Constructor() const;
@@ -93,7 +93,7 @@ class CORE_EXPORT ScriptCustomElementDefinition final
v8::Isolate*,
ExceptionState&);
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
TraceWrapperV8Reference<v8::Object> constructor_;
TraceWrapperV8Reference<v8::Function> connected_callback_;
TraceWrapperV8Reference<v8::Function> disconnected_callback_;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition_builder.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition_builder.cc
index 7aa3acc2172..9896762b866 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition_builder.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition_builder.cc
@@ -4,15 +4,14 @@
#include "third_party/blink/renderer/bindings/core/v8/script_custom_element_definition_builder.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
#include "third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.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/bindings/v8_binding_macros.h"
@@ -47,13 +46,13 @@ bool ScriptCustomElementDefinitionBuilder::CheckConstructorIntrinsics() {
}
bool ScriptCustomElementDefinitionBuilder::CheckConstructorNotRegistered() {
- if (!ScriptCustomElementDefinition::ForConstructor(script_state_.get(),
- registry_, constructor_))
+ if (!ScriptCustomElementDefinition::ForConstructor(script_state_, registry_,
+ constructor_))
return true;
// Constructor is already registered.
exception_state_.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"this constructor has already been used with this registry");
return false;
}
@@ -157,7 +156,7 @@ CustomElementDefinition* ScriptCustomElementDefinitionBuilder::Build(
const CustomElementDescriptor& descriptor,
CustomElementDefinition::Id id) {
return ScriptCustomElementDefinition::Create(
- script_state_.get(), registry_, descriptor, id, constructor_,
+ script_state_, registry_, descriptor, id, constructor_,
connected_callback_, disconnected_callback_, adopted_callback_,
attribute_changed_callback_, std::move(observed_attributes_),
default_style_sheet_);
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition_builder.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition_builder.h
index f0b2c4265eb..a6c6f9885d2 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition_builder.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_custom_element_definition_builder.h
@@ -49,7 +49,7 @@ class CORE_EXPORT ScriptCustomElementDefinitionBuilder
private:
static ScriptCustomElementDefinitionBuilder* stack_;
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
Member<CustomElementRegistry> registry_;
const Member<CSSStyleSheet> default_style_sheet_;
v8::Local<v8::Value> constructor_value_;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_event_listener.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_event_listener.h
index 85d134fb6ab..2ce7ca60a47 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_event_listener.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_event_listener.h
@@ -31,8 +31,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SCRIPT_EVENT_LISTENER_H_
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SCRIPT_EVENT_LISTENER_H_
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include <memory>
+
#include "third_party/blink/renderer/bindings/core/v8/v8_lazy_event_listener.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_function.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_function.cc
index 66fe48c8fa9..47dad5beec1 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_function.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_function.cc
@@ -8,6 +8,10 @@
namespace blink {
+void ScriptFunction::Trace(blink::Visitor* visitor) {
+ visitor->Trace(script_state_);
+}
+
v8::Local<v8::Function> ScriptFunction::BindToV8Function() {
#if DCHECK_IS_ON()
DCHECK(!bind_to_v8_function_already_called_);
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_function.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_function.h
index 1f49bb23cdd..54c3055c439 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_function.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_function.h
@@ -54,13 +54,13 @@ class CORE_EXPORT ScriptFunction
: public GarbageCollectedFinalized<ScriptFunction> {
public:
virtual ~ScriptFunction() = default;
- virtual void Trace(blink::Visitor* visitor) {}
+ virtual void Trace(blink::Visitor*);
protected:
explicit ScriptFunction(ScriptState* script_state)
: script_state_(script_state) {}
- ScriptState* GetScriptState() const { return script_state_.get(); }
+ ScriptState* GetScriptState() const { return script_state_; }
v8::Local<v8::Function> BindToV8Function();
@@ -68,7 +68,7 @@ class CORE_EXPORT ScriptFunction
virtual ScriptValue Call(ScriptValue) = 0;
static void CallCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
#if DCHECK_IS_ON()
// bindToV8Function must not be called twice.
bool bind_to_v8_function_already_called_ = false;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_iterator.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_iterator.cc
index 117035a337c..8457d7d8a7d 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_iterator.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_iterator.cc
@@ -4,10 +4,10 @@
#include "third_party/blink/renderer/bindings/core/v8/script_iterator.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_string_resource.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_module.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_module.cc
index e9e9d291722..3fdc21bd60b 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_module.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_module.cc
@@ -4,12 +4,16 @@
#include "third_party/blink/renderer/bindings/core/v8/script_module.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/script/script_module_resolver.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/loader/fetch/script_fetch_options.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_module.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_module.h
index e484a9b2ece..b9f3f2be8b0 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_module.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_module.h
@@ -5,13 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SCRIPT_MODULE_H_
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SCRIPT_MODULE_H_
-#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/shared_persistent.h"
#include "third_party/blink/renderer/platform/loader/fetch/access_control_status.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
-#include "third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/text_position.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -21,6 +17,10 @@
namespace blink {
class ExceptionState;
+class KURL;
+class ScriptFetchOptions;
+class ScriptState;
+class ScriptValue;
// ScriptModule wraps a handle to a v8::Module for use in core.
//
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_module_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_module_test.cc
index d32832aa053..5817c36f600 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_module_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_module_test.cc
@@ -8,6 +8,7 @@
#include "testing/gtest/include/gtest/gtest.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/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/script/script_module_resolver.h"
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise.cc
index 9da06cc6db1..15165c8c30e 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise.cc
@@ -28,11 +28,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+
+#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
#include "third_party/blink/renderer/platform/instance_counters.h"
#include "v8/include/v8.h"
@@ -258,7 +259,7 @@ ScriptPromise ScriptPromise::Then(v8::Local<v8::Function> on_fulfilled,
return ScriptPromise();
}
- return ScriptPromise(script_state_.get(), result_promise);
+ return ScriptPromise(script_state_, result_promise);
}
ScriptPromise ScriptPromise::CastUndefined(ScriptState* script_state) {
@@ -299,6 +300,14 @@ ScriptPromise ScriptPromise::Reject(ScriptState* script_state,
return promise;
}
+ScriptPromise ScriptPromise::Reject(ScriptState* script_state,
+ ExceptionState& exception_state) {
+ DCHECK(exception_state.HadException());
+ ScriptPromise promise = Reject(script_state, exception_state.GetException());
+ exception_state.ClearException();
+ return promise;
+}
+
ScriptPromise ScriptPromise::RejectWithDOMException(ScriptState* script_state,
DOMException* exception) {
DCHECK(script_state->GetIsolate()->InContext());
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise.h
index ec16ceaee7e..842ff45ebeb 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise.h
@@ -32,7 +32,6 @@
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SCRIPT_PROMISE_H_
#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -43,6 +42,7 @@
namespace blink {
class DOMException;
+class ExceptionState;
// ScriptPromise is the class for representing Promise values in C++ world.
// ScriptPromise holds a Promise.
@@ -106,6 +106,8 @@ class CORE_EXPORT ScriptPromise final {
static ScriptPromise Reject(ScriptState*, const ScriptValue&);
static ScriptPromise Reject(ScriptState*, v8::Local<v8::Value>);
+ // Rejects with a given exception. The ExceptionState gets cleared.
+ static ScriptPromise Reject(ScriptState*, ExceptionState&);
static ScriptPromise RejectWithDOMException(ScriptState*, DOMException*);
@@ -137,7 +139,9 @@ class CORE_EXPORT ScriptPromise final {
static void IncreaseInstanceCount();
static void DecreaseInstanceCount();
- scoped_refptr<ScriptState> script_state_;
+ // TODO(peria): Move ScriptPromise to Oilpan heap.
+ GC_PLUGIN_IGNORE("813731")
+ Persistent<ScriptState> script_state_;
ScriptValue promise_;
};
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property.h
index 5e7a25fb2f7..71594612ae6 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property.h
@@ -50,7 +50,7 @@ class ScriptPromiseProperty : public ScriptPromisePropertyBase {
// property holder).
//
// When implementing a ScriptPromiseProperty add the property name
- // to ScriptPromiseProperties.h and pass
+ // to script_promise_properties.h and pass
// ScriptPromiseProperty::Foo to create. The name must be unique
// per kind of holder.
template <typename PassHolderType>
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_base.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_base.h
index 37cfb8d4e34..7950b9f626e 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_base.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_base.h
@@ -24,7 +24,7 @@ class DOMWrapperWorld;
class ExecutionContext;
class ScriptState;
-// TODO(yhirano): Remove NEVER_INLINE once we find the cause of crashes.
+// TODO(yhirano): Remove NOINLINE once we find the cause of crashes.
class CORE_EXPORT ScriptPromisePropertyBase
: public GarbageCollectedFinalized<ScriptPromisePropertyBase>,
public ContextClient {
@@ -71,7 +71,7 @@ class CORE_EXPORT ScriptPromisePropertyBase
v8::Isolate*,
v8::Local<v8::Object> creation_context) = 0;
- NEVER_INLINE void ResetBase();
+ NOINLINE void ResetBase();
private:
typedef Vector<std::unique_ptr<ScopedPersistent<v8::Object>>>
@@ -79,10 +79,10 @@ class CORE_EXPORT ScriptPromisePropertyBase
void ResolveOrRejectInternal(v8::Local<v8::Promise::Resolver>);
v8::Local<v8::Object> EnsureHolderWrapper(ScriptState*);
- NEVER_INLINE void ClearWrappers();
+ NOINLINE void ClearWrappers();
// TODO(yhirano): Remove these functions once we find the cause of crashes.
- NEVER_INLINE void CheckThis();
- NEVER_INLINE void CheckWrappers();
+ NOINLINE void CheckThis();
+ NOINLINE void CheckWrappers();
V8PrivateProperty::Symbol PromiseSymbol();
V8PrivateProperty::Symbol ResolverSymbol();
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
index 01950edf93e..5bc3a1935bd 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_property_test.cc
@@ -71,7 +71,7 @@ class StubFunction : public ScriptFunction {
size_t& call_count_;
};
-class GarbageCollectedHolder : public GarbageCollectedScriptWrappable {
+class GarbageCollectedHolder final : public GarbageCollectedScriptWrappable {
public:
typedef ScriptPromiseProperty<Member<GarbageCollectedScriptWrappable>,
Member<GarbageCollectedScriptWrappable>,
@@ -89,8 +89,8 @@ class GarbageCollectedHolder : public GarbageCollectedScriptWrappable {
}
void Trace(blink::Visitor* visitor) override {
- GarbageCollectedScriptWrappable::Trace(visitor);
visitor->Trace(property_);
+ GarbageCollectedScriptWrappable::Trace(visitor);
}
private:
@@ -102,7 +102,7 @@ class ScriptPromisePropertyTestBase {
ScriptPromisePropertyTestBase()
: page_(DummyPageHolder::Create(IntSize(1, 1))) {
v8::HandleScope handle_scope(GetIsolate());
- other_script_state_ = ScriptStateForTesting::Create(
+ other_script_state_ = ScriptState::Create(
v8::Context::New(GetIsolate()),
DOMWrapperWorld::EnsureIsolatedWorld(GetIsolate(), 1));
}
@@ -115,7 +115,7 @@ class ScriptPromisePropertyTestBase {
return ToScriptStateForMainWorld(GetDocument().GetFrame());
}
DOMWrapperWorld& MainWorld() { return MainScriptState()->World(); }
- ScriptState* OtherScriptState() { return other_script_state_.get(); }
+ ScriptState* OtherScriptState() { return other_script_state_; }
DOMWrapperWorld& OtherWorld() { return other_script_state_->World(); }
ScriptState* CurrentScriptState() {
return ScriptState::Current(GetIsolate());
@@ -155,7 +155,7 @@ class ScriptPromisePropertyTestBase {
private:
std::unique_ptr<DummyPageHolder> page_;
- scoped_refptr<ScriptState> other_script_state_;
+ Persistent<ScriptState> other_script_state_;
};
// This is the main test class.
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc
index aa3d288b445..643a43dea71 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.cc
@@ -24,6 +24,12 @@ ScriptPromiseResolver::ScriptPromiseResolver(ScriptState* script_state)
}
}
+void ScriptPromiseResolver::Reject(ExceptionState& exception_state) {
+ DCHECK(exception_state.HadException());
+ Reject(exception_state.GetException());
+ exception_state.ClearException();
+}
+
void ScriptPromiseResolver::Pause() {
timer_.Stop();
}
@@ -62,7 +68,7 @@ void ScriptPromiseResolver::OnTimerFired(TimerBase*) {
return;
}
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
ResolveOrRejectImmediately();
}
@@ -81,6 +87,7 @@ void ScriptPromiseResolver::ResolveOrRejectImmediately() {
}
void ScriptPromiseResolver::Trace(blink::Visitor* visitor) {
+ visitor->Trace(script_state_);
PausableObject::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h
index cbbfe11d753..4eb63b82905 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h
@@ -73,7 +73,10 @@ class CORE_EXPORT ScriptPromiseResolver
void Resolve() { Resolve(ToV8UndefinedGenerator()); }
void Reject() { Reject(ToV8UndefinedGenerator()); }
- ScriptState* GetScriptState() { return script_state_.get(); }
+ // Reject with a given exception.
+ void Reject(ExceptionState&);
+
+ ScriptState* GetScriptState() const { return script_state_; }
// Note that an empty ScriptPromise will be returned after resolve or
// reject is called.
@@ -84,8 +87,6 @@ class CORE_EXPORT ScriptPromiseResolver
return resolver_.Promise();
}
- ScriptState* GetScriptState() const { return script_state_.get(); }
-
// PausableObject implementation.
void Pause() override;
void Unpause() override;
@@ -125,7 +126,7 @@ class CORE_EXPORT ScriptPromiseResolver
DCHECK(new_state == kResolving || new_state == kRejecting);
state_ = new_state;
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
// Calling ToV8 in a ScriptForbiddenScope will trigger a CHECK and
// cause a crash. ToV8 just invokes a constructor for wrapper creation,
@@ -164,7 +165,7 @@ class CORE_EXPORT ScriptPromiseResolver
void OnTimerFired(TimerBase*);
ResolutionState state_;
- const scoped_refptr<ScriptState> script_state_;
+ const Member<ScriptState> script_state_;
TaskRunnerTimer<ScriptPromiseResolver> timer_;
Resolver resolver_;
ScopedPersistent<v8::Value> value_;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_test.cc
index eba306ecc89..85f10c93503 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_test.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
@@ -230,13 +231,13 @@ TEST_F(ScriptPromiseResolverTest, keepAliveUntilResolved) {
resolver->KeepAliveWhilePending();
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
ASSERT_TRUE(ScriptPromiseResolverKeepAlive::IsAlive());
resolver->Resolve("hello");
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
EXPECT_FALSE(ScriptPromiseResolverKeepAlive::IsAlive());
}
@@ -250,13 +251,13 @@ TEST_F(ScriptPromiseResolverTest, keepAliveUntilRejected) {
resolver->KeepAliveWhilePending();
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
ASSERT_TRUE(ScriptPromiseResolverKeepAlive::IsAlive());
resolver->Reject("hello");
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
EXPECT_FALSE(ScriptPromiseResolverKeepAlive::IsAlive());
}
@@ -274,7 +275,7 @@ TEST_F(ScriptPromiseResolverTest, keepAliveWhileScriptForbidden) {
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
EXPECT_TRUE(ScriptPromiseResolverKeepAlive::IsAlive());
}
@@ -282,7 +283,7 @@ TEST_F(ScriptPromiseResolverTest, keepAliveWhileScriptForbidden) {
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
EXPECT_FALSE(ScriptPromiseResolverKeepAlive::IsAlive());
}
@@ -296,13 +297,13 @@ TEST_F(ScriptPromiseResolverTest, keepAliveUntilStopped) {
resolver->KeepAliveWhilePending();
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
EXPECT_TRUE(ScriptPromiseResolverKeepAlive::IsAlive());
GetExecutionContext()->NotifyContextDestroyed();
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
EXPECT_FALSE(ScriptPromiseResolverKeepAlive::IsAlive());
}
@@ -316,20 +317,20 @@ TEST_F(ScriptPromiseResolverTest, suspend) {
resolver->KeepAliveWhilePending();
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
ASSERT_TRUE(ScriptPromiseResolverKeepAlive::IsAlive());
GetExecutionContext()->PausePausableObjects();
resolver->Resolve("hello");
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
EXPECT_TRUE(ScriptPromiseResolverKeepAlive::IsAlive());
GetExecutionContext()->NotifyContextDestroyed();
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
EXPECT_FALSE(ScriptPromiseResolverKeepAlive::IsAlive());
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_test.cc
index 71c56a264a5..5192d0beb78 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_promise_test.cc
@@ -38,7 +38,6 @@
#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/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/testing/null_execution_context.h"
#include "v8/include/v8.h"
@@ -262,7 +261,8 @@ TEST(ScriptPromiseTest, rejectWithExceptionState) {
ScriptValue on_fulfilled, on_rejected;
ScriptPromise promise = ScriptPromise::RejectWithDOMException(
scope.GetScriptState(),
- DOMException::Create(kSyntaxError, "some syntax error"));
+ DOMException::Create(DOMExceptionCode::kSyntaxError,
+ "some syntax error"));
promise.Then(FunctionForScriptPromiseTest::CreateFunction(
scope.GetScriptState(), &on_fulfilled),
FunctionForScriptPromiseTest::CreateFunction(
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_regexp.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_regexp.cc
index 5b6e5f91869..cf5d8167a7c 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_regexp.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_regexp.cc
@@ -28,6 +28,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_regexp.h"
+#include "base/stl_util.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
@@ -94,7 +95,7 @@ int ScriptRegexp::Match(const String& string,
V8String(isolate, string.Substring(start_from))};
v8::Local<v8::Value> return_value;
if (!V8ScriptRunner::CallInternalFunction(isolate, exec.As<v8::Function>(),
- regex, arraysize(argv), argv)
+ regex, base::size(argv), argv)
.ToLocal(&return_value))
return -1;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_source_code.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_source_code.cc
index d89a6640300..7b5bd831926 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_source_code.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_source_code.cc
@@ -10,9 +10,9 @@ namespace blink {
namespace {
-String TreatNullSourceAsEmpty(const String& source) {
+MovableString TreatNullSourceAsEmpty(const MovableString& source) {
// ScriptSourceCode allows for the representation of the null/not-there-really
- // ScriptSourceCode value. Encoded by way of a m_source.isNull() being true,
+ // ScriptSourceCode value. Encoded by way of a source_.IsNull() being true,
// with the nullary constructor to be used to construct such a value.
//
// Should the other constructors be passed a null string, that is interpreted
@@ -20,7 +20,7 @@ String TreatNullSourceAsEmpty(const String& source) {
// between such null string occurrences. Do that by converting the latter
// case's null strings into empty ones.
if (source.IsNull())
- return "";
+ return MovableString();
return source;
}
@@ -49,7 +49,7 @@ String SourceMapUrlFromResponse(const ResourceResponse& response) {
} // namespace
ScriptSourceCode::ScriptSourceCode(
- const String& source,
+ const MovableString& source,
ScriptSourceLocationType source_location_type,
SingleCachedMetadataHandler* cache_handler,
const KURL& url,
@@ -63,6 +63,18 @@ ScriptSourceCode::ScriptSourceCode(
DCHECK(source_location_type != ScriptSourceLocationType::kExternalFile);
}
+ScriptSourceCode::ScriptSourceCode(
+ const String& source,
+ ScriptSourceLocationType source_location_type,
+ SingleCachedMetadataHandler* cache_handler,
+ const KURL& url,
+ const TextPosition& start_position)
+ : ScriptSourceCode(MovableString(source.Impl()),
+ source_location_type,
+ cache_handler,
+ url,
+ start_position) {}
+
ScriptSourceCode::ScriptSourceCode(ScriptStreamer* streamer,
ScriptResource* resource)
: source_(TreatNullSourceAsEmpty(resource->SourceText())),
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_source_code.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_source_code.h
index a48e301517d..0dde36ca293 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_source_code.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_source_code.h
@@ -36,6 +36,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/text/movable_string.h"
#include "third_party/blink/renderer/platform/wtf/text/text_position.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -52,6 +53,13 @@ class CORE_EXPORT ScriptSourceCode final {
ScriptSourceCode(
const String& source,
ScriptSourceLocationType = ScriptSourceLocationType::kUnknown,
+ SingleCachedMetadataHandler* = nullptr,
+ const KURL& = KURL(),
+ const TextPosition& = TextPosition::MinimumPosition());
+
+ ScriptSourceCode(
+ const MovableString& source,
+ ScriptSourceLocationType = ScriptSourceLocationType::kUnknown,
SingleCachedMetadataHandler* cache_handler = nullptr,
const KURL& = KURL(),
const TextPosition& start_position = TextPosition::MinimumPosition());
@@ -65,7 +73,7 @@ class CORE_EXPORT ScriptSourceCode final {
~ScriptSourceCode();
void Trace(blink::Visitor*);
- const String& Source() const { return source_; }
+ const MovableString& Source() const { return source_; }
SingleCachedMetadataHandler* CacheHandler() const { return cache_handler_; }
const KURL& Url() const { return url_; }
const TextPosition& StartPosition() const { return start_position_; }
@@ -77,7 +85,7 @@ class CORE_EXPORT ScriptSourceCode final {
ScriptStreamer* Streamer() const { return streamer_; }
private:
- const String source_;
+ const MovableString source_;
Member<SingleCachedMetadataHandler> cache_handler_;
Member<ScriptStreamer> streamer_;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
index 3b120f66806..70f3cbdd736 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
@@ -8,7 +8,7 @@
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/bindings/core/v8/script_streamer_thread.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_code_cache.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/settings.h"
@@ -258,7 +258,7 @@ class SourceStream : public v8::ScriptCompiler::ExternalSourceStream {
SingleCachedMetadataHandler* cache_handler = resource->CacheHandler();
scoped_refptr<CachedMetadata> code_cache(
cache_handler ? cache_handler->GetCachedMetadata(
- V8ScriptRunner::TagForCodeCache(cache_handler))
+ V8CodeCache::TagForCodeCache(cache_handler))
: nullptr);
if (code_cache.get()) {
// The resource has a code cache, so it's unnecessary to stream and
@@ -287,18 +287,20 @@ class SourceStream : public v8::ScriptCompiler::ExternalSourceStream {
return;
}
- // Get as much data from the ResourceBuffer as we can.
- const char* data = nullptr;
- while (size_t length =
- resource_buffer_->GetSomeData(data, queue_tail_position_)) {
- // Copy the data chunks into a new buffer, since we're going to
- // give the data to a background thread.
- uint8_t* copied_data = new uint8_t[length];
- memcpy(copied_data, data, length);
- data_queue_.Produce(copied_data, length);
-
- queue_tail_position_ += length;
+ // Get as much data from the ResourceBuffer as we can in one chunk.
+ const size_t length = resource_buffer_->size() - queue_tail_position_;
+
+ uint8_t* const copied_data = new uint8_t[length];
+ size_t pos = 0;
+
+ for (auto it = resource_buffer_->GetIteratorAt(queue_tail_position_);
+ it != resource_buffer_->end(); ++it) {
+ memcpy(copied_data + pos, it->data(), it->size());
+ pos += it->size();
}
+ DCHECK_EQ(pos, length);
+ queue_tail_position_ = resource_buffer_->size();
+ data_queue_.Produce(copied_data, length);
}
// For coordinating between the main thread and background thread tasks.
@@ -459,7 +461,7 @@ void ScriptStreamer::NotifyAppendData(ScriptResource* resource) {
source_ = std::make_unique<v8::ScriptCompiler::StreamedSource>(stream_,
encoding_);
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask>
script_streaming_task(
base::WrapUnique(v8::ScriptCompiler::StartStreamingScript(
@@ -529,6 +531,7 @@ ScriptStreamer::~ScriptStreamer() = default;
void ScriptStreamer::Trace(blink::Visitor* visitor) {
visitor->Trace(pending_script_);
+ visitor->Trace(script_state_);
}
void ScriptStreamer::StreamingComplete() {
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer.h
index d9488765935..b7399f5b3bb 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer.h
@@ -122,7 +122,7 @@ class CORE_EXPORT ScriptStreamer final
// What kind of cached data V8 produces during streaming.
v8::ScriptCompiler::CompileOptions compile_options_;
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
// For recording metrics for different types of scripts separately.
Type script_type_;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc
index 7e08b2010c2..0ea5e530206 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc
@@ -11,10 +11,12 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
+#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
#include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
#include "third_party/blink/renderer/bindings/core/v8/script_streamer_thread.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_code_cache.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/script/classic_pending_script.h"
@@ -167,10 +169,10 @@ TEST_F(ScriptStreamingTest, CompilingStreamedScript) {
v8::TryCatch try_catch(scope.GetIsolate());
v8::Local<v8::Script> script;
v8::ScriptCompiler::CompileOptions compile_options;
- V8ScriptRunner::ProduceCacheOptions produce_cache_options;
+ V8CodeCache::ProduceCacheOptions produce_cache_options;
v8::ScriptCompiler::NoCacheReason no_cache_reason;
std::tie(compile_options, produce_cache_options, no_cache_reason) =
- V8ScriptRunner::GetCompileOptions(kV8CacheOptionsDefault, source_code);
+ V8CodeCache::GetCompileOptions(kV8CacheOptionsDefault, source_code);
EXPECT_TRUE(V8ScriptRunner::CompileScript(
scope.GetScriptState(), source_code, kSharableCrossOrigin,
compile_options, no_cache_reason, ReferrerScriptInfo())
@@ -212,10 +214,10 @@ TEST_F(ScriptStreamingTest, CompilingStreamedScriptWithParseError) {
v8::TryCatch try_catch(scope.GetIsolate());
v8::Local<v8::Script> script;
v8::ScriptCompiler::CompileOptions compile_options;
- V8ScriptRunner::ProduceCacheOptions produce_cache_options;
+ V8CodeCache::ProduceCacheOptions produce_cache_options;
v8::ScriptCompiler::NoCacheReason no_cache_reason;
std::tie(compile_options, produce_cache_options, no_cache_reason) =
- V8ScriptRunner::GetCompileOptions(kV8CacheOptionsDefault, source_code);
+ V8CodeCache::GetCompileOptions(kV8CacheOptionsDefault, source_code);
EXPECT_FALSE(V8ScriptRunner::CompileScript(
scope.GetScriptState(), source_code, kSharableCrossOrigin,
compile_options, no_cache_reason, ReferrerScriptInfo())
@@ -266,9 +268,9 @@ TEST_F(ScriptStreamingTest, SuppressingStreaming) {
SingleCachedMetadataHandler* cache_handler = GetResource()->CacheHandler();
EXPECT_TRUE(cache_handler);
- cache_handler->SetCachedMetadata(
- V8ScriptRunner::TagForCodeCache(cache_handler), "X", 1,
- CachedMetadataHandler::kCacheLocally);
+ cache_handler->SetCachedMetadata(V8CodeCache::TagForCodeCache(cache_handler),
+ "X", 1,
+ CachedMetadataHandler::kCacheLocally);
AppendPadding();
Finish();
@@ -369,10 +371,10 @@ TEST_F(ScriptStreamingTest, ScriptsWithSmallFirstChunk) {
v8::TryCatch try_catch(scope.GetIsolate());
v8::Local<v8::Script> script;
v8::ScriptCompiler::CompileOptions compile_options;
- V8ScriptRunner::ProduceCacheOptions produce_cache_options;
+ V8CodeCache::ProduceCacheOptions produce_cache_options;
v8::ScriptCompiler::NoCacheReason no_cache_reason;
std::tie(compile_options, produce_cache_options, no_cache_reason) =
- V8ScriptRunner::GetCompileOptions(kV8CacheOptionsDefault, source_code);
+ V8CodeCache::GetCompileOptions(kV8CacheOptionsDefault, source_code);
EXPECT_TRUE(V8ScriptRunner::CompileScript(
scope.GetScriptState(), source_code, kSharableCrossOrigin,
compile_options, no_cache_reason, ReferrerScriptInfo())
@@ -411,10 +413,10 @@ TEST_F(ScriptStreamingTest, EncodingChanges) {
v8::TryCatch try_catch(scope.GetIsolate());
v8::Local<v8::Script> script;
v8::ScriptCompiler::CompileOptions compile_options;
- V8ScriptRunner::ProduceCacheOptions produce_cache_options;
+ V8CodeCache::ProduceCacheOptions produce_cache_options;
v8::ScriptCompiler::NoCacheReason no_cache_reason;
std::tie(compile_options, produce_cache_options, no_cache_reason) =
- V8ScriptRunner::GetCompileOptions(kV8CacheOptionsDefault, source_code);
+ V8CodeCache::GetCompileOptions(kV8CacheOptionsDefault, source_code);
EXPECT_TRUE(V8ScriptRunner::CompileScript(
scope.GetScriptState(), source_code, kSharableCrossOrigin,
compile_options, no_cache_reason, ReferrerScriptInfo())
@@ -454,10 +456,10 @@ TEST_F(ScriptStreamingTest, EncodingFromBOM) {
v8::TryCatch try_catch(scope.GetIsolate());
v8::Local<v8::Script> script;
v8::ScriptCompiler::CompileOptions compile_options;
- V8ScriptRunner::ProduceCacheOptions produce_cache_options;
+ V8CodeCache::ProduceCacheOptions produce_cache_options;
v8::ScriptCompiler::NoCacheReason no_cache_reason;
std::tie(compile_options, produce_cache_options, no_cache_reason) =
- V8ScriptRunner::GetCompileOptions(kV8CacheOptionsDefault, source_code);
+ V8CodeCache::GetCompileOptions(kV8CacheOptionsDefault, source_code);
EXPECT_TRUE(V8ScriptRunner::CompileScript(
scope.GetScriptState(), source_code, kSharableCrossOrigin,
compile_options, no_cache_reason, ReferrerScriptInfo())
@@ -479,7 +481,7 @@ TEST_F(ScriptStreamingTest, GarbageCollectDuringStreaming) {
pending_script_ = nullptr;
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer_thread.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer_thread.cc
index b8c04f1a136..a197c9de6b8 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer_thread.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer_thread.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "base/location.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/bindings/core/v8/script_streamer.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer_thread.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer_thread.h
index 48a8fa5347b..2af307dd638 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer_thread.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_streamer_thread.h
@@ -8,7 +8,6 @@
#include <memory>
#include "base/macros.h"
-#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
@@ -17,6 +16,7 @@
namespace blink {
class ScriptStreamer;
+class WebThread;
// A singleton thread for running background tasks for script streaming.
class CORE_EXPORT ScriptStreamerThread {
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_value.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_value.cc
index 41fdfb169ad..419134d6a24 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_value.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_value.cc
@@ -71,7 +71,7 @@ bool ScriptValue::ToString(String& result) const {
if (IsEmpty())
return false;
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
v8::Local<v8::Value> string = V8Value();
if (string.IsEmpty() || !string->IsString())
return false;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_value.h b/chromium/third_party/blink/renderer/bindings/core/v8/script_value.h
index f9efb381544..0af66de8880 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_value.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_value.h
@@ -93,7 +93,7 @@ class CORE_EXPORT ScriptValue final {
DCHECK(IsEmpty() || script_state_);
}
- ScriptState* GetScriptState() const { return script_state_.get(); }
+ ScriptState* GetScriptState() const { return script_state_; }
v8::Isolate* GetIsolate() const {
return script_state_ ? script_state_->GetIsolate()
@@ -101,7 +101,7 @@ class CORE_EXPORT ScriptValue final {
}
v8::Local<v8::Context> GetContext() const {
- DCHECK(script_state_.get());
+ DCHECK(script_state_);
return script_state_->GetContext();
}
@@ -170,7 +170,9 @@ class CORE_EXPORT ScriptValue final {
static ScriptValue CreateNull(ScriptState*);
private:
- scoped_refptr<ScriptState> script_state_;
+ // TODO(peria): Move ScriptValue to Oilpan heap.
+ GC_PLUGIN_IGNORE("813731")
+ Persistent<ScriptState> script_state_;
scoped_refptr<SharedPersistent<v8::Value>> value_;
};
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_wrappable_marking_visitor_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_wrappable_marking_visitor_test.cc
index 9fe00338dfe..f3702be4a01 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/script_wrappable_marking_visitor_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_wrappable_marking_visitor_test.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h"
#include "third_party/blink/renderer/core/testing/death_aware_script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
@@ -169,7 +170,7 @@ TEST(ScriptWrappableMarkingVisitorTest,
->GetScriptWrappableMarkingVisitor();
visitor->TracePrologue();
- visitor->TraceWrappersWithManualWriteBarrier(object);
+ visitor->TraceWithWrappers(object);
EXPECT_EQ(visitor->MarkingDeque()->front().RawObjectPointer(), object);
@@ -241,17 +242,14 @@ TEST(ScriptWrappableMarkingVisitorTest,
namespace {
class HandleContainer
- : public blink::GarbageCollectedFinalized<HandleContainer>,
- public blink::TraceWrapperBase {
+ : public blink::GarbageCollectedFinalized<HandleContainer> {
public:
static HandleContainer* Create() { return new HandleContainer(); }
virtual ~HandleContainer() = default;
- void Trace(blink::Visitor* visitor) {}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- visitor->TraceWrappers(handle_.Cast<v8::Value>());
+ void Trace(blink::Visitor* visitor) {
+ visitor->Trace(handle_.Cast<v8::Value>());
}
- const char* NameInHeapSnapshot() const override { return "HandleContainer"; }
void SetValue(v8::Isolate* isolate, v8::Local<v8::String> string) {
handle_.Set(isolate, string);
@@ -451,9 +449,7 @@ class Mixin : public GarbageCollectedMixin {
explicit Mixin(DeathAwareScriptWrappable* wrapper_in_mixin)
: wrapper_in_mixin_(wrapper_in_mixin) {}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(wrapper_in_mixin_);
- }
+ void Trace(Visitor* visitor) override { visitor->Trace(wrapper_in_mixin_); }
protected:
DeathAwareScriptWrappable::Wrapper wrapper_in_mixin_;
@@ -465,7 +461,7 @@ class ClassWithField {
};
class Base : public blink::GarbageCollected<Base>,
- public blink::TraceWrapperBase,
+ public NameClient, // Force vtable on Base.
public ClassWithField,
public Mixin {
USING_GARBAGE_COLLECTED_MIXIN(Base);
@@ -476,9 +472,9 @@ class Base : public blink::GarbageCollected<Base>,
return new Base(wrapper_in_base, wrapper_in_mixin);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- visitor->TraceWrappers(wrapper_in_base_);
- Mixin::TraceWrappers(visitor);
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(wrapper_in_base_);
+ Mixin::Trace(visitor);
}
const char* NameInHeapSnapshot() const override { return "HandleContainer"; }
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/script_wrappable_visitor_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/script_wrappable_visitor_test.cc
new file mode 100644
index 00000000000..415b8a43188
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/script_wrappable_visitor_test.cc
@@ -0,0 +1,115 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/bindings/script_wrappable_visitor.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/testing/death_aware_script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/trace_traits.h"
+
+namespace blink {
+
+namespace {
+
+class VerifyingScriptWrappableVisitor : public ScriptWrappableVisitor {
+ public:
+ // Visitor interface.
+ void Visit(const TraceWrapperV8Reference<v8::Value>&) override {}
+ void Visit(DOMWrapperMap<ScriptWrappable>*,
+ const ScriptWrappable* key) override {}
+
+ void VisitWithWrappers(void*, TraceDescriptor desc) override {
+ visited_objects_.push_back(desc.base_object_payload);
+ }
+
+ void VisitBackingStoreStrongly(void* object,
+ void** object_slot,
+ TraceDescriptor desc) override {
+ desc.callback(this, desc.base_object_payload);
+ }
+
+ bool DidVisitObject(const ScriptWrappable* script_wrappable) const {
+ return std::find(visited_objects_.begin(), visited_objects_.end(),
+ script_wrappable) != visited_objects_.end();
+ }
+
+ protected:
+ using Visitor::Visit;
+
+ private:
+ std::vector<void*> visited_objects_;
+};
+
+class ExpectObjectsVisited {
+ public:
+ ExpectObjectsVisited(VerifyingScriptWrappableVisitor* visitor,
+ std::initializer_list<ScriptWrappable*> objects)
+ : visitor_(visitor), expected_objects_(objects) {}
+
+ ~ExpectObjectsVisited() {
+ for (const ScriptWrappable* expected_object : expected_objects_) {
+ EXPECT_TRUE(visitor_->DidVisitObject(expected_object));
+ }
+ }
+
+ private:
+ VerifyingScriptWrappableVisitor* visitor_;
+ std::vector<ScriptWrappable*> expected_objects_;
+};
+
+} // namespace
+
+TEST(ScriptWrappableVisitorTest, TraceWrapperMember) {
+ VerifyingScriptWrappableVisitor verifying_visitor;
+ DeathAwareScriptWrappable* parent = DeathAwareScriptWrappable::Create();
+ DeathAwareScriptWrappable* child = DeathAwareScriptWrappable::Create();
+ parent->SetWrappedDependency(child);
+ {
+ ExpectObjectsVisited expected(&verifying_visitor, {child});
+ TraceDescriptor desc =
+ TraceTrait<DeathAwareScriptWrappable>::GetTraceDescriptor(parent);
+ desc.callback(&verifying_visitor, parent);
+ }
+}
+
+TEST(ScriptWrappableVisitorTest, HeapVectorOfTraceWrapperMember) {
+ VerifyingScriptWrappableVisitor verifying_visitor;
+ DeathAwareScriptWrappable* parent = DeathAwareScriptWrappable::Create();
+ DeathAwareScriptWrappable* child = DeathAwareScriptWrappable::Create();
+ parent->AddWrappedVectorDependency(child);
+ {
+ ExpectObjectsVisited expected(&verifying_visitor, {child});
+ TraceDescriptor desc =
+ TraceTrait<DeathAwareScriptWrappable>::GetTraceDescriptor(parent);
+ desc.callback(&verifying_visitor, parent);
+ }
+}
+
+TEST(ScriptWrappableVisitorTest, HeapHashMapOfTraceWrapperMember) {
+ VerifyingScriptWrappableVisitor verifying_visitor;
+ DeathAwareScriptWrappable* parent = DeathAwareScriptWrappable::Create();
+ DeathAwareScriptWrappable* key = DeathAwareScriptWrappable::Create();
+ DeathAwareScriptWrappable* value = DeathAwareScriptWrappable::Create();
+ parent->AddWrappedHashMapDependency(key, value);
+ {
+ ExpectObjectsVisited expected(&verifying_visitor, {key, value});
+ TraceDescriptor desc =
+ TraceTrait<DeathAwareScriptWrappable>::GetTraceDescriptor(parent);
+ desc.callback(&verifying_visitor, parent);
+ }
+}
+
+TEST(ScriptWrappableVisitorTest, InObjectUsingTraceWrapperMember) {
+ VerifyingScriptWrappableVisitor verifying_visitor;
+ DeathAwareScriptWrappable* parent = DeathAwareScriptWrappable::Create();
+ DeathAwareScriptWrappable* child = DeathAwareScriptWrappable::Create();
+ parent->AddInObjectDependency(child);
+ {
+ ExpectObjectsVisited expected(&verifying_visitor, {child});
+ TraceDescriptor desc =
+ TraceTrait<DeathAwareScriptWrappable>::GetTraceDescriptor(parent);
+ desc.callback(&verifying_visitor, parent);
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc
index 15c2d604323..21e799892c5 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.cc
@@ -32,8 +32,10 @@
#include <algorithm>
#include <memory>
+
+#include "base/numerics/checked_math.h"
+#include "base/sys_byteorder.h"
#include "third_party/blink/public/web/web_serialized_script_value_version.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h"
@@ -45,20 +47,18 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_message_port.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_offscreen_canvas.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_shared_array_buffer.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/blink/renderer/core/messaging/message_port.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_shared_array_buffer.h"
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/byte_order.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
#include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
@@ -93,7 +93,7 @@ scoped_refptr<SerializedScriptValue> SerializedScriptValue::Create() {
scoped_refptr<SerializedScriptValue> SerializedScriptValue::Create(
const String& data) {
- CheckedNumeric<size_t> data_buffer_size = data.length();
+ base::CheckedNumeric<size_t> data_buffer_size = data.length();
data_buffer_size *= 2;
if (!data_buffer_size.IsValid())
return Create();
@@ -213,7 +213,7 @@ static void SwapWiredDataIfNeeded(uint8_t* buffer, size_t buffer_size) {
size_t uchars_size = buffer_size / sizeof(UChar);
for (size_t i = 0; i < uchars_size; ++i)
- uchars[i] = ntohs(uchars[i]);
+ uchars[i] = base::NetToHost16(uchars[i]);
}
scoped_refptr<SerializedScriptValue> SerializedScriptValue::Create(
@@ -236,13 +236,12 @@ scoped_refptr<SerializedScriptValue> SerializedScriptValue::Create(
return Create();
DataBufferPtr data_buffer = AllocateBuffer(buffer->size());
- buffer->ForEachSegment([&data_buffer](const char* segment,
- size_t segment_size,
- size_t segment_offset) {
- std::copy(segment, segment + segment_size,
- data_buffer.get() + segment_offset);
- return true;
- });
+ size_t offset = 0;
+ for (const auto& span : *buffer) {
+ std::copy(span.data(), span.data() + span.size(),
+ data_buffer.get() + offset);
+ offset += span.size();
+ }
SwapWiredDataIfNeeded(data_buffer.get(), buffer->size());
return base::AdoptRef(
@@ -260,6 +259,11 @@ SerializedScriptValue::SerializedScriptValue(DataBufferPtr data,
has_registered_external_allocation_(false),
transferables_need_external_allocation_registration_(false) {}
+void SerializedScriptValue::SetImageBitmapContentsArray(
+ ImageBitmapContentsArray contents) {
+ image_bitmap_contents_array_ = std::move(contents);
+}
+
SerializedScriptValue::DataBufferPtr SerializedScriptValue::AllocateBuffer(
size_t buffer_size) {
return DataBufferPtr(static_cast<uint8_t*>(WTF::Partitions::BufferMalloc(
@@ -309,9 +313,10 @@ SerializedScriptValue::TransferImageBitmapContents(
for (size_t i = 0; i < image_bitmaps.size(); ++i) {
if (image_bitmaps[i]->IsNeutered()) {
- exception_state.ThrowDOMException(
- kDataCloneError, "ImageBitmap at index " + String::Number(i) +
- " is already detached.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataCloneError,
+ "ImageBitmap at index " +
+ String::Number(i) +
+ " is already detached.");
return contents;
}
}
@@ -346,15 +351,17 @@ void SerializedScriptValue::TransferOffscreenCanvas(
if (visited.Contains(offscreen_canvases[i].Get()))
continue;
if (offscreen_canvases[i]->IsNeutered()) {
- exception_state.ThrowDOMException(
- kDataCloneError, "OffscreenCanvas at index " + String::Number(i) +
- " is already detached.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataCloneError,
+ "OffscreenCanvas at index " +
+ String::Number(i) +
+ " is already detached.");
return;
}
if (offscreen_canvases[i]->RenderingContext()) {
- exception_state.ThrowDOMException(
- kDataCloneError, "OffscreenCanvas at index " + String::Number(i) +
- " has an associated context.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataCloneError,
+ "OffscreenCanvas at index " +
+ String::Number(i) +
+ " has an associated context.");
return;
}
visited.insert(offscreen_canvases[i].Get());
@@ -422,15 +429,24 @@ bool SerializedScriptValue::ExtractTransferables(
if (value.IsEmpty() || value->IsUndefined())
return true;
- Vector<ScriptValue> transferable_array =
+ const Vector<ScriptValue>& transferable_array =
NativeValueTraits<IDLSequence<ScriptValue>>::NativeValue(isolate, value,
exception_state);
if (exception_state.HadException())
return false;
+ return ExtractTransferables(isolate, transferable_array, transferables,
+ exception_state);
+}
+
+bool SerializedScriptValue::ExtractTransferables(
+ v8::Isolate* isolate,
+ const Vector<ScriptValue>& object_sequence,
+ Transferables& transferables,
+ ExceptionState& exception_state) {
// Validate the passed array of transferables.
uint32_t i = 0;
- for (const auto& script_value : transferable_array) {
+ for (const auto& script_value : object_sequence) {
v8::Local<v8::Value> transferable_object = script_value.V8Value();
// Validation of non-null objects, per HTML5 spec 10.3.3.
if (IsUndefinedOrNull(transferable_object)) {
@@ -447,8 +463,9 @@ bool SerializedScriptValue::ExtractTransferables(
// Check for duplicate MessagePorts.
if (transferables.message_ports.Contains(port)) {
exception_state.ThrowDOMException(
- kDataCloneError, "Message port at index " + String::Number(i) +
- " is a duplicate of an earlier port.");
+ DOMExceptionCode::kDataCloneError,
+ "Message port at index " + String::Number(i) +
+ " is a duplicate of an earlier port.");
return false;
}
transferables.message_ports.push_back(port);
@@ -457,8 +474,9 @@ bool SerializedScriptValue::ExtractTransferables(
v8::Local<v8::Object>::Cast(transferable_object));
if (transferables.array_buffers.Contains(array_buffer)) {
exception_state.ThrowDOMException(
- kDataCloneError, "ArrayBuffer at index " + String::Number(i) +
- " is a duplicate of an earlier ArrayBuffer.");
+ DOMExceptionCode::kDataCloneError,
+ "ArrayBuffer at index " + String::Number(i) +
+ " is a duplicate of an earlier ArrayBuffer.");
return false;
}
transferables.array_buffers.push_back(array_buffer);
@@ -467,7 +485,7 @@ bool SerializedScriptValue::ExtractTransferables(
v8::Local<v8::Object>::Cast(transferable_object));
if (transferables.array_buffers.Contains(shared_array_buffer)) {
exception_state.ThrowDOMException(
- kDataCloneError,
+ DOMExceptionCode::kDataCloneError,
"SharedArrayBuffer at index " + String::Number(i) +
" is a duplicate of an earlier SharedArrayBuffer.");
return false;
@@ -478,8 +496,9 @@ bool SerializedScriptValue::ExtractTransferables(
v8::Local<v8::Object>::Cast(transferable_object));
if (transferables.image_bitmaps.Contains(image_bitmap)) {
exception_state.ThrowDOMException(
- kDataCloneError, "ImageBitmap at index " + String::Number(i) +
- " is a duplicate of an earlier ImageBitmap.");
+ DOMExceptionCode::kDataCloneError,
+ "ImageBitmap at index " + String::Number(i) +
+ " is a duplicate of an earlier ImageBitmap.");
return false;
}
transferables.image_bitmaps.push_back(image_bitmap);
@@ -488,7 +507,7 @@ bool SerializedScriptValue::ExtractTransferables(
v8::Local<v8::Object>::Cast(transferable_object));
if (transferables.offscreen_canvases.Contains(offscreen_canvas)) {
exception_state.ThrowDOMException(
- kDataCloneError,
+ DOMExceptionCode::kDataCloneError,
"OffscreenCanvas at index " + String::Number(i) +
" is a duplicate of an earlier OffscreenCanvas.");
return false;
@@ -537,9 +556,10 @@ SerializedScriptValue::TransferArrayBufferContents(
DOMArrayBufferBase* array_buffer = *it;
if (array_buffer->IsNeutered()) {
size_t index = std::distance(array_buffers.begin(), it);
- exception_state.ThrowDOMException(
- kDataCloneError, "ArrayBuffer at index " + String::Number(index) +
- " is already neutered.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataCloneError,
+ "ArrayBuffer at index " +
+ String::Number(index) +
+ " is already neutered.");
return ArrayBufferContentsArray();
}
}
@@ -554,18 +574,20 @@ SerializedScriptValue::TransferArrayBufferContents(
size_t index = std::distance(array_buffers.begin(), it);
if (array_buffer_base->IsShared()) {
- exception_state.ThrowDOMException(
- kDataCloneError, "SharedArrayBuffer at index " +
- String::Number(index) + " is not transferable.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataCloneError,
+ "SharedArrayBuffer at index " +
+ String::Number(index) +
+ " is not transferable.");
return ArrayBufferContentsArray();
} else {
DOMArrayBuffer* array_buffer =
static_cast<DOMArrayBuffer*>(array_buffer_base);
if (!array_buffer->Transfer(isolate, contents.at(index))) {
- exception_state.ThrowDOMException(
- kDataCloneError, "ArrayBuffer at index " + String::Number(index) +
- " could not be transferred.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataCloneError,
+ "ArrayBuffer at index " +
+ String::Number(index) +
+ " could not be transferred.");
return ArrayBufferContentsArray();
}
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h
index 182664f90bd..e8218fb2cba 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h
@@ -36,14 +36,12 @@
#include "base/containers/span.h"
#include "base/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/transferables.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_view.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
#include "third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h"
#include "v8/include/v8.h"
@@ -51,12 +49,14 @@
namespace blink {
class BlobDataHandle;
-class Transferables;
+class DOMSharedArrayBuffer;
class ExceptionState;
+class ScriptValue;
class SharedBuffer;
+class StaticBitmapImage;
+class Transferables;
class UnpackedSerializedScriptValue;
class WebBlobInfo;
-class DOMSharedArrayBuffer;
typedef HashMap<String, scoped_refptr<BlobDataHandle>> BlobDataHandleMap;
typedef Vector<WebBlobInfo> WebBlobInfoArray;
@@ -192,6 +192,10 @@ class CORE_EXPORT SerializedScriptValue
int,
Transferables&,
ExceptionState&);
+ static bool ExtractTransferables(v8::Isolate*,
+ const Vector<ScriptValue>&,
+ Transferables&,
+ ExceptionState&);
static ArrayBufferArray ExtractNonSharedArrayBuffers(Transferables&);
@@ -240,9 +244,7 @@ class CORE_EXPORT SerializedScriptValue
ImageBitmapContentsArray& GetImageBitmapContentsArray() {
return image_bitmap_contents_array_;
}
- void SetImageBitmapContentsArray(ImageBitmapContentsArray contents) {
- image_bitmap_contents_array_ = std::move(contents);
- }
+ void SetImageBitmapContentsArray(ImageBitmapContentsArray contents);
private:
friend class ScriptValueSerializer;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_test.cc
index e78c50a85c2..2448105b4ac 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_test.cc
@@ -5,13 +5,13 @@
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_factory.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_file.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_image_data.h"
#include "third_party/blink/renderer/core/fileapi/file.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/text/string_view.h"
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_threaded_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_threaded_test.cc
index ec6d406f1a6..3f69e6542e1 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_threaded_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_threaded_test.cc
@@ -5,13 +5,13 @@
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "build/build_config.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/unpacked_serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/core/workers/worker_thread_test_helper.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/to_v8.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc
index 3a3ab8827ba..f5acf9a4523 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h"
+#include "base/numerics/checked_math.h"
#include "third_party/blink/public/platform/web_blob_info.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/unpacked_serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
@@ -25,7 +26,6 @@
#include "third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_shared_array_buffer.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
#include "third_party/blink/renderer/platform/wtf/date_math.h"
namespace blink {
@@ -85,19 +85,19 @@ size_t ReadVersionEnvelope(SerializedScriptValue* serialized_script_value,
} // namespace
V8ScriptValueDeserializer::V8ScriptValueDeserializer(
- scoped_refptr<ScriptState> script_state,
+ ScriptState* script_state,
UnpackedSerializedScriptValue* unpacked_value,
const Options& options)
- : V8ScriptValueDeserializer(std::move(script_state),
+ : V8ScriptValueDeserializer(script_state,
unpacked_value,
unpacked_value->Value(),
options) {}
V8ScriptValueDeserializer::V8ScriptValueDeserializer(
- scoped_refptr<ScriptState> script_state,
+ ScriptState* script_state,
scoped_refptr<SerializedScriptValue> value,
const Options& options)
- : V8ScriptValueDeserializer(std::move(script_state),
+ : V8ScriptValueDeserializer(script_state,
nullptr,
std::move(value),
options) {
@@ -108,11 +108,11 @@ V8ScriptValueDeserializer::V8ScriptValueDeserializer(
}
V8ScriptValueDeserializer::V8ScriptValueDeserializer(
- scoped_refptr<ScriptState> script_state,
+ ScriptState* script_state,
UnpackedSerializedScriptValue* unpacked_value,
scoped_refptr<SerializedScriptValue> value,
const Options& options)
- : script_state_(std::move(script_state)),
+ : script_state_(script_state),
unpacked_value_(unpacked_value),
serialized_script_value_(value),
deserializer_(script_state_->GetIsolate(),
@@ -325,7 +325,7 @@ ScriptWrappable* V8ScriptValueDeserializer::ReadDOMObject(
canvas_opacity_mode,
SerializedImageDataStorageFormat::kUint8Clamped)
.GetCanvasColorParams();
- CheckedNumeric<uint32_t> computed_byte_length = width;
+ base::CheckedNumeric<uint32_t> computed_byte_length = width;
computed_byte_length *= height;
computed_byte_length *= color_params.BytesPerPixel();
if (!computed_byte_length.IsValid() ||
@@ -380,7 +380,7 @@ ScriptWrappable* V8ScriptValueDeserializer::ReadDOMObject(
canvas_color_space, SerializedPixelFormat::kRGBA8,
SerializedOpacityMode::kNonOpaque, image_data_storage_format);
ImageDataStorageFormat storage_format = color_params.GetStorageFormat();
- CheckedNumeric<uint32_t> computed_byte_length = width;
+ base::CheckedNumeric<uint32_t> computed_byte_length = width;
computed_byte_length *= height;
computed_byte_length *= 4;
computed_byte_length *= ImageData::StorageFormatDataSize(storage_format);
@@ -445,7 +445,7 @@ ScriptWrappable* V8ScriptValueDeserializer::ReadDOMObject(
if (!ReadDouble(&d))
return nullptr;
}
- return DOMMatrix::CreateForSerialization(values, arraysize(values));
+ return DOMMatrix::CreateForSerialization(values, base::size(values));
}
case kDOMMatrix2DReadOnlyTag: {
double values[6];
@@ -454,7 +454,7 @@ ScriptWrappable* V8ScriptValueDeserializer::ReadDOMObject(
return nullptr;
}
return DOMMatrixReadOnly::CreateForSerialization(values,
- arraysize(values));
+ base::size(values));
}
case kDOMMatrixTag: {
double values[16];
@@ -462,7 +462,7 @@ ScriptWrappable* V8ScriptValueDeserializer::ReadDOMObject(
if (!ReadDouble(&d))
return nullptr;
}
- return DOMMatrix::CreateForSerialization(values, arraysize(values));
+ return DOMMatrix::CreateForSerialization(values, base::size(values));
}
case kDOMMatrixReadOnlyTag: {
double values[16];
@@ -471,7 +471,7 @@ ScriptWrappable* V8ScriptValueDeserializer::ReadDOMObject(
return nullptr;
}
return DOMMatrixReadOnly::CreateForSerialization(values,
- arraysize(values));
+ base::size(values));
}
case kMessagePortTag: {
uint32_t index = 0;
@@ -588,7 +588,7 @@ v8::MaybeLocal<v8::Object> V8ScriptValueDeserializer::ReadHostObject(
if (ReadTag(&tag))
wrappable = ReadDOMObject(tag);
if (!wrappable) {
- exception_state.ThrowDOMException(kDataCloneError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataCloneError,
"Unable to deserialize cloned data.");
return v8::MaybeLocal<v8::Object>();
}
@@ -628,7 +628,7 @@ V8ScriptValueDeserializer::GetSharedArrayBufferFromId(v8::Isolate* isolate,
}
ExceptionState exception_state(isolate, ExceptionState::kUnknownContext,
nullptr, nullptr);
- exception_state.ThrowDOMException(kDataCloneError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataCloneError,
"Unable to deserialize SharedArrayBuffer.");
// If the id does not map to a valid index, it is expected that the
// SerializedScriptValue emptied its shared ArrayBufferContents when crossing
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h
index 6ad9ca1ab0b..3582fcbce79 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h
@@ -35,10 +35,10 @@ class CORE_EXPORT V8ScriptValueDeserializer
public:
using Options = SerializedScriptValue::DeserializeOptions;
- V8ScriptValueDeserializer(scoped_refptr<ScriptState>,
+ V8ScriptValueDeserializer(ScriptState*,
UnpackedSerializedScriptValue*,
const Options& = Options());
- V8ScriptValueDeserializer(scoped_refptr<ScriptState>,
+ V8ScriptValueDeserializer(ScriptState*,
scoped_refptr<SerializedScriptValue>,
const Options& = Options());
@@ -47,7 +47,7 @@ class CORE_EXPORT V8ScriptValueDeserializer
protected:
virtual ScriptWrappable* ReadDOMObject(SerializationTag);
- ScriptState* GetScriptState() const { return script_state_.get(); }
+ ScriptState* GetScriptState() const { return script_state_; }
uint32_t Version() const { return version_; }
bool ReadTag(SerializationTag* tag) {
@@ -82,7 +82,7 @@ class CORE_EXPORT V8ScriptValueDeserializer
}
private:
- V8ScriptValueDeserializer(scoped_refptr<ScriptState>,
+ V8ScriptValueDeserializer(ScriptState*,
UnpackedSerializedScriptValue*,
scoped_refptr<SerializedScriptValue>,
const Options&);
@@ -103,7 +103,7 @@ class CORE_EXPORT V8ScriptValueDeserializer
v8::Isolate*,
uint32_t) override;
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
Member<UnpackedSerializedScriptValue> unpacked_value_;
scoped_refptr<SerializedScriptValue> serialized_script_value_;
v8::ValueDeserializer deserializer_;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc
index 0dc19987b1e..292660efd7d 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc
@@ -55,10 +55,9 @@ namespace blink {
// made to how Blink writes data. Purely V8-side changes do not require an
// adjustment to this value.
-V8ScriptValueSerializer::V8ScriptValueSerializer(
- scoped_refptr<ScriptState> script_state,
- const Options& options)
- : script_state_(std::move(script_state)),
+V8ScriptValueSerializer::V8ScriptValueSerializer(ScriptState* script_state,
+ const Options& options)
+ : script_state_(script_state),
serialized_script_value_(SerializedScriptValue::Create()),
serializer_(script_state_->GetIsolate(), this),
transferables_(options.transferables),
@@ -120,12 +119,13 @@ void V8ScriptValueSerializer::PrepareTransfer(ExceptionState& exception_state) {
for (uint32_t i = 0; i < transferables_->array_buffers.size(); i++) {
DOMArrayBufferBase* array_buffer = transferables_->array_buffers[i].Get();
if (!array_buffer->IsShared()) {
- v8::Local<v8::Value> wrapper = ToV8(array_buffer, script_state_.get());
+ v8::Local<v8::Value> wrapper = ToV8(array_buffer, script_state_);
serializer_.TransferArrayBuffer(
i, v8::Local<v8::ArrayBuffer>::Cast(wrapper));
} else {
exception_state.ThrowDOMException(
- kDataCloneError, "SharedArrayBuffer can not be in transfer list.");
+ DOMExceptionCode::kDataCloneError,
+ "SharedArrayBuffer can not be in transfer list.");
return;
}
}
@@ -215,7 +215,7 @@ bool V8ScriptValueSerializer::WriteDOMObject(ScriptWrappable* wrappable,
ImageBitmap* image_bitmap = wrappable->ToImpl<ImageBitmap>();
if (image_bitmap->IsNeutered()) {
exception_state.ThrowDOMException(
- kDataCloneError,
+ DOMExceptionCode::kDataCloneError,
"An ImageBitmap is detached and could not be cloned.");
return false;
}
@@ -386,7 +386,7 @@ bool V8ScriptValueSerializer::WriteDOMObject(ScriptWrappable* wrappable,
index = transferables_->message_ports.Find(message_port);
if (index == kNotFound) {
exception_state.ThrowDOMException(
- kDataCloneError,
+ DOMExceptionCode::kDataCloneError,
"A MessagePort could not be cloned because it was not transferred.");
return false;
}
@@ -402,20 +402,20 @@ bool V8ScriptValueSerializer::WriteDOMObject(ScriptWrappable* wrappable,
index = transferables_->offscreen_canvases.Find(canvas);
if (index == kNotFound) {
exception_state.ThrowDOMException(
- kDataCloneError,
+ DOMExceptionCode::kDataCloneError,
"An OffscreenCanvas could not be cloned "
"because it was not transferred.");
return false;
}
if (canvas->IsNeutered()) {
exception_state.ThrowDOMException(
- kDataCloneError,
+ DOMExceptionCode::kDataCloneError,
"An OffscreenCanvas could not be cloned because it was detached.");
return false;
}
if (canvas->RenderingContext()) {
exception_state.ThrowDOMException(
- kDataCloneError,
+ DOMExceptionCode::kDataCloneError,
"An OffscreenCanvas could not be cloned "
"because it had a rendering context.");
return false;
@@ -474,10 +474,12 @@ bool V8ScriptValueSerializer::WriteFile(File* file,
void V8ScriptValueSerializer::ThrowDataCloneError(
v8::Local<v8::String> v8_message) {
DCHECK(exception_state_);
- String message = exception_state_->AddExceptionContext(
- V8StringToWebCoreString<String>(v8_message, kDoNotExternalize));
- V8ThrowDOMException::ThrowDOMException(script_state_->GetIsolate(),
- kDataCloneError, message);
+ ExceptionState exception_state(
+ script_state_->GetIsolate(), exception_state_->Context(),
+ exception_state_->InterfaceName(), exception_state_->PropertyName());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kDataCloneError,
+ ToBlinkString<String>(v8_message, kDoNotExternalize));
}
v8::Maybe<bool> V8ScriptValueSerializer::WriteHostObject(
@@ -490,7 +492,7 @@ v8::Maybe<bool> V8ScriptValueSerializer::WriteHostObject(
exception_state_->PropertyName());
if (!V8DOMWrapper::IsWrapper(isolate, object)) {
- exception_state.ThrowDOMException(kDataCloneError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataCloneError,
"An object could not be cloned.");
return v8::Nothing<bool>();
}
@@ -503,7 +505,8 @@ v8::Maybe<bool> V8ScriptValueSerializer::WriteHostObject(
if (!exception_state.HadException()) {
StringView interface = wrappable->GetWrapperTypeInfo()->interface_name;
exception_state.ThrowDOMException(
- kDataCloneError, interface + " object could not be cloned.");
+ DOMExceptionCode::kDataCloneError,
+ interface + " object could not be cloned.");
}
return v8::Nothing<bool>();
}
@@ -518,7 +521,7 @@ v8::Maybe<uint32_t> V8ScriptValueSerializer::GetSharedArrayBufferId(
exception_state_->InterfaceName(),
exception_state_->PropertyName());
exception_state.ThrowDOMException(
- kDataCloneError,
+ DOMExceptionCode::kDataCloneError,
"A SharedArrayBuffer can not be serialized for storage.");
return v8::Nothing<uint32_t>();
}
@@ -550,7 +553,7 @@ v8::Maybe<uint32_t> V8ScriptValueSerializer::GetWasmModuleTransferId(
ExceptionState exception_state(isolate, exception_state_->Context(),
exception_state_->InterfaceName(),
exception_state_->PropertyName());
- exception_state.ThrowDOMException(kDataCloneError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataCloneError,
"Serializing WebAssembly modules in "
"non-secure contexts is not allowed.");
return v8::Nothing<uint32_t>();
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.h b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.h
index bb5ca3ca62a..7d74e07672e 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.h
@@ -6,11 +6,11 @@
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SERIALIZATION_V8_SCRIPT_VALUE_SERIALIZER_H_
#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_color_params.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/core/core_export.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/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
@@ -37,8 +37,7 @@ class CORE_EXPORT V8ScriptValueSerializer
public:
using Options = SerializedScriptValue::SerializeOptions;
- explicit V8ScriptValueSerializer(scoped_refptr<ScriptState>,
- const Options& = Options());
+ explicit V8ScriptValueSerializer(ScriptState*, const Options& = Options());
scoped_refptr<SerializedScriptValue> Serialize(v8::Local<v8::Value>,
ExceptionState&);
@@ -99,7 +98,7 @@ class CORE_EXPORT V8ScriptValueSerializer
size_t* actual_size) override;
void FreeBufferMemory(void* buffer) override;
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
scoped_refptr<SerializedScriptValue> serialized_script_value_;
v8::ValueSerializer serializer_;
const Transferables* transferables_ = nullptr;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc
index 4426e7d929e..a32e43c7948 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc
@@ -8,7 +8,6 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_blob_info.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/serialization/unpacked_serialized_script_value.h"
@@ -45,6 +44,7 @@
#include "third_party/blink/renderer/core/html/canvas/image_data.h"
#include "third_party/blink/renderer/core/messaging/message_port.h"
#include "third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/date_math.h"
@@ -62,7 +62,7 @@ v8::Local<v8::Value> RoundTrip(
ExceptionState* override_exception_state = nullptr,
Transferables* transferables = nullptr,
WebBlobInfoArray* blob_info = nullptr) {
- scoped_refptr<ScriptState> script_state = scope.GetScriptState();
+ ScriptState* script_state = scope.GetScriptState();
ExceptionState& exception_state = override_exception_state
? *override_exception_state
: scope.GetExceptionState();
@@ -107,7 +107,7 @@ v8::Local<v8::Value> Eval(const String& source, V8TestingScope& scope) {
}
String ToJSON(v8::Local<v8::Object> object, const V8TestingScope& scope) {
- return V8StringToWebCoreString<String>(
+ return ToBlinkString<String>(
v8::JSON::Stringify(scope.GetContext(), object).ToLocalChecked(),
kDoNotExternalize);
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/source_location.h b/chromium/third_party/blink/renderer/bindings/core/v8/source_location.h
index 7740e724f6e..2e324f2875d 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/source_location.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/source_location.h
@@ -8,7 +8,6 @@
#include <v8-inspector-protocol.h>
#include <memory>
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/cross_thread_copier.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc b/chromium/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc
index e5f7ab5616b..3daee534b8b 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/use_counter_callback.cc
@@ -148,6 +148,9 @@ void UseCounterCallback(v8::Isolate* isolate,
case v8::Isolate::kArrayPrototypeSortJSArrayModifiedPrototype:
blink_feature = WebFeature::kV8ArrayPrototypeSortJSArrayModifiedPrototype;
break;
+ case v8::Isolate::kFunctionTokenOffsetTooLongForToString:
+ blink_feature = WebFeature::kV8FunctionTokenOffsetTooLongForToString;
+ break;
default:
// This can happen if V8 has added counters that this version of Blink
// does not know about. It's harmless.
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.cc
index cef56c1295d..f61db2f9edf 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.cc
@@ -30,7 +30,6 @@
#include "third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_dictionary.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_document.h"
@@ -46,6 +45,7 @@
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/svg_names.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v0_custom_element_binding.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h"
#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
@@ -154,7 +154,7 @@ V0CustomElementConstructorBuilder::CreateCallbacks() {
RetrieveCallback("attributeChangedCallback");
callbacks_ = V8V0CustomElementLifecycleCallbacks::Create(
- script_state_.get(), prototype_, created, attached, detached,
+ script_state_, prototype_, created, attached, detached,
attribute_changed);
return callbacks_.Get();
}
@@ -289,7 +289,7 @@ bool V0CustomElementConstructorBuilder::DidRegisterDefinition() const {
}
ScriptValue V0CustomElementConstructorBuilder::BindingsReturnValue() const {
- return ScriptValue(script_state_.get(), constructor_);
+ return ScriptValue(script_state_, constructor_);
}
bool V0CustomElementConstructorBuilder::HasValidPrototypeChainFor(
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.h b/chromium/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.h
index 6bd9eeeb9a0..116661e2809 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.h
@@ -84,7 +84,7 @@ class V0CustomElementConstructorBuilder {
bool PrototypeIsValid(const AtomicString& type, ExceptionState&) const;
v8::MaybeLocal<v8::Function> RetrieveCallback(const char* name);
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
const ElementRegistrationOptions& options_;
v8::Local<v8::Object> prototype_;
v8::Local<v8::Function> constructor_;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.cc
index 0bbdb70f255..250fff39735 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.cc
@@ -38,6 +38,7 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_parser.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/events/before_unload_event.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
@@ -70,6 +71,21 @@ V8AbstractEventListener::~V8AbstractEventListener() {
InstanceCounters::kJSEventListenerCounter);
}
+// static
+v8::Local<v8::Value> V8AbstractEventListener::GetListenerOrNull(
+ v8::Isolate* isolate,
+ EventTarget* event_target,
+ EventListener* listener) {
+ if (listener && listener->GetType() == kJSEventListenerType) {
+ v8::Local<v8::Object> v8_listener =
+ static_cast<V8AbstractEventListener*>(listener)->GetListenerObject(
+ event_target->GetExecutionContext());
+ if (!v8_listener.IsEmpty())
+ return v8_listener;
+ }
+ return v8::Null(isolate);
+}
+
void V8AbstractEventListener::handleEvent(ExecutionContext* execution_context,
Event* event) {
if (!execution_context)
@@ -258,14 +274,9 @@ void V8AbstractEventListener::WrapperCleared(
}
void V8AbstractEventListener::Trace(blink::Visitor* visitor) {
+ visitor->Trace(listener_.Cast<v8::Value>());
visitor->Trace(worker_or_worklet_global_scope_);
EventListener::Trace(visitor);
}
-void V8AbstractEventListener::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(listener_.Cast<v8::Value>());
- EventListener::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.h
index 1674ddd03a9..cbd188ca77d 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.h
@@ -42,6 +42,7 @@
namespace blink {
class Event;
+class EventTarget;
class WorkerOrWorkletGlobalScope;
// There are two kinds of event listeners: HTML or non-HMTL. onload,
@@ -67,6 +68,10 @@ class CORE_EXPORT V8AbstractEventListener : public EventListener {
Cast(const_cast<const EventListener*>(listener)));
}
+ static v8::Local<v8::Value> GetListenerOrNull(v8::Isolate*,
+ EventTarget*,
+ EventListener*);
+
// Implementation of EventListener interface.
bool operator==(const EventListener& other) const override {
@@ -76,13 +81,6 @@ class CORE_EXPORT V8AbstractEventListener : public EventListener {
void handleEvent(ExecutionContext*, Event*) final;
virtual void HandleEvent(ScriptState*, Event*);
- v8::Local<v8::Value> GetListenerOrNull(v8::Isolate* isolate,
- ExecutionContext* execution_context) {
- v8::Local<v8::Object> listener = GetListenerObject(execution_context);
- return listener.IsEmpty() ? v8::Null(isolate).As<v8::Value>()
- : listener.As<v8::Value>();
- }
-
// Returns the listener object, either a function or an object, or the empty
// handle if the user script is not compilable. No exception will be thrown
// even if the user script is not compilable.
@@ -112,7 +110,6 @@ class CORE_EXPORT V8AbstractEventListener : public EventListener {
DOMWrapperWorld& World() const { return *world_; }
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
protected:
V8AbstractEventListener(v8::Isolate*, bool is_attribute, DOMWrapperWorld&);
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.cc
index 3ddf4400bad..71d591e7aef 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.cc
@@ -67,6 +67,7 @@
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
#include "third_party/blink/renderer/platform/wtf/text/cstring.h"
#include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -412,13 +413,7 @@ int64_t ToInt64Slow(v8::Isolate* isolate,
"long long", exception_state);
}
- if (std::isnan(number_value) || std::isinf(number_value))
- return 0;
-
- // NaNs and +/-Infinity should be 0, otherwise modulo 2^64.
- unsigned long long integer;
- doubleToInteger(number_value, integer);
- return integer;
+ return DoubleToInteger(number_value);
}
uint64_t ToUInt64Slow(v8::Isolate* isolate,
@@ -462,13 +457,7 @@ uint64_t ToUInt64Slow(v8::Isolate* isolate,
if (configuration == kClamp)
return clampTo<uint64_t>(number_value);
- if (std::isinf(number_value))
- return 0;
-
- // NaNs and +/-Infinity should be 0, otherwise modulo 2^64.
- unsigned long long integer;
- doubleToInteger(number_value, integer);
- return integer;
+ return DoubleToInteger(number_value);
}
float ToRestrictedFloat(v8::Isolate* isolate,
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h
index f7400321995..a3f90daa95c 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h
@@ -32,8 +32,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_BINDING_FOR_CORE_H_
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_BINDING_FOR_CORE_H_
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
@@ -44,6 +42,7 @@
#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
@@ -345,6 +344,30 @@ inline uint64_t ToUInt64(v8::Isolate* isolate,
return ToUInt64Slow(isolate, value, configuration, exception_state);
}
+// NaNs and +/-Infinity should be 0, otherwise modulo 2^64.
+// Step 8 - 12 of https://heycam.github.io/webidl/#abstract-opdef-converttoint
+inline unsigned long long DoubleToInteger(double d) {
+ if (std::isnan(d) || std::isinf(d))
+ return 0;
+ constexpr unsigned long long kMaxULL =
+ std::numeric_limits<unsigned long long>::max();
+
+ // -2^{64} < fmod_value < 2^{64}.
+ double fmod_value = fmod(trunc(d), kMaxULL + 1.0);
+ if (fmod_value >= 0) {
+ // 0 <= fmod_value < 2^{64}.
+ // 0 <= value < 2^{64}. This cast causes no loss.
+ return static_cast<unsigned long long>(fmod_value);
+ }
+ // -2^{64} < fmod_value < 0.
+ // 0 < fmod_value_in_unsigned_long_long < 2^{64}. This cast causes no loss.
+ unsigned long long fmod_value_in_unsigned_long_long =
+ static_cast<unsigned long long>(-fmod_value);
+ // -1 < (kMaxULL - fmod_value_in_unsigned_long_long) < 2^{64} - 1.
+ // 0 < value < 2^{64}.
+ return kMaxULL - fmod_value_in_unsigned_long_long + 1;
+}
+
// Convert a value to a double precision float, which might fail.
CORE_EXPORT double ToDoubleSlow(v8::Isolate*,
v8::Local<v8::Value>,
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.cc
index 543e90950d6..2b45567b046 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.cc
@@ -11,22 +11,6 @@
namespace blink {
-scoped_refptr<ScriptStateForTesting> ScriptStateForTesting::Create(
- v8::Local<v8::Context> context,
- scoped_refptr<DOMWrapperWorld> world) {
- scoped_refptr<ScriptStateForTesting> script_state =
- base::AdoptRef(new ScriptStateForTesting(context, std::move(world)));
- // This ref() is for keeping this ScriptState alive as long as the v8::Context
- // is alive. This is deref()ed in the weak callback of the v8::Context.
- script_state->AddRef();
- return script_state;
-}
-
-ScriptStateForTesting::ScriptStateForTesting(
- v8::Local<v8::Context> context,
- scoped_refptr<DOMWrapperWorld> world)
- : ScriptState(context, std::move(world)) {}
-
V8TestingScope::V8TestingScope()
: holder_(DummyPageHolder::Create()),
handle_scope_(GetIsolate()),
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h
index 3ce899c0edf..0349072a0f8 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_BINDING_FOR_TESTING_H_
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_BINDING_FOR_TESTING_H_
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -14,22 +14,11 @@
namespace blink {
class Document;
-class DOMWrapperWorld;
class DummyPageHolder;
class ExecutionContext;
class LocalFrame;
class Page;
-class ScriptStateForTesting : public ScriptState {
- public:
- static scoped_refptr<ScriptStateForTesting> Create(
- v8::Local<v8::Context>,
- scoped_refptr<DOMWrapperWorld>);
-
- private:
- ScriptStateForTesting(v8::Local<v8::Context>, scoped_refptr<DOMWrapperWorld>);
-};
-
class V8TestingScope {
STACK_ALLOCATED();
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc
new file mode 100644
index 00000000000..ad3eca49af9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_code_cache.cc
@@ -0,0 +1,330 @@
+// 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/bindings/core/v8/v8_code_cache.h"
+
+#include "base/optional.h"
+#include "build/build_config.h"
+#include "third_party/blink/public/web/web_settings.h"
+#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.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/bindings/core/v8/v8_initializer.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/histogram.h"
+#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
+#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
+#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
+#include "third_party/blink/renderer/platform/wtf/time.h"
+
+namespace blink {
+
+namespace {
+
+enum CacheTagKind { kCacheTagCode = 0, kCacheTagTimeStamp = 1, kCacheTagLast };
+
+static const int kCacheTagKindSize = 1;
+
+static_assert((1 << kCacheTagKindSize) >= kCacheTagLast,
+ "CacheTagLast must be large enough");
+
+uint32_t CacheTag(CacheTagKind kind, const String& encoding) {
+ static uint32_t v8_cache_data_version =
+ v8::ScriptCompiler::CachedDataVersionTag() << kCacheTagKindSize;
+
+ // A script can be (successfully) interpreted with different encodings,
+ // depending on the page it appears in. The cache doesn't know anything
+ // about encodings, but the cached data is specific to one encoding. If we
+ // later load the script from the cache and interpret it with a different
+ // encoding, the cached data is not valid for that encoding.
+ return (v8_cache_data_version | kind) +
+ (encoding.IsNull() ? 0 : StringHash::GetHash(encoding));
+}
+
+// Check previously stored timestamp.
+bool IsResourceHotForCaching(SingleCachedMetadataHandler* cache_handler,
+ int hot_hours) {
+ const double hot_seconds = hot_hours * 60 * 60;
+ scoped_refptr<CachedMetadata> cached_metadata =
+ cache_handler->GetCachedMetadata(
+ V8CodeCache::TagForTimeStamp(cache_handler));
+ if (!cached_metadata)
+ return false;
+ double time_stamp;
+ const int size = sizeof(time_stamp);
+ DCHECK_EQ(cached_metadata->size(), static_cast<unsigned long>(size));
+ memcpy(&time_stamp, cached_metadata->Data(), size);
+ return (WTF::CurrentTime() - time_stamp) < hot_seconds;
+}
+
+} // namespace
+
+v8::ScriptCompiler::CachedData* V8CodeCache::CreateCachedData(
+ SingleCachedMetadataHandler* cache_handler) {
+ DCHECK(cache_handler);
+ uint32_t code_cache_tag = V8CodeCache::TagForCodeCache(cache_handler);
+ scoped_refptr<CachedMetadata> cached_metadata =
+ cache_handler->GetCachedMetadata(code_cache_tag);
+ DCHECK(cached_metadata);
+ const char* data = cached_metadata->Data();
+ int length = cached_metadata->size();
+ return new v8::ScriptCompiler::CachedData(
+ reinterpret_cast<const uint8_t*>(data), length,
+ v8::ScriptCompiler::CachedData::BufferNotOwned);
+}
+
+std::tuple<v8::ScriptCompiler::CompileOptions,
+ V8CodeCache::ProduceCacheOptions,
+ v8::ScriptCompiler::NoCacheReason>
+V8CodeCache::GetCompileOptions(V8CacheOptions cache_options,
+ const ScriptSourceCode& source) {
+ static const int kMinimalCodeLength = 1024;
+ static const int kHotHours = 72;
+ v8::ScriptCompiler::NoCacheReason no_cache_reason;
+
+ switch (source.SourceLocationType()) {
+ case ScriptSourceLocationType::kInline:
+ no_cache_reason = v8::ScriptCompiler::kNoCacheBecauseInlineScript;
+ break;
+ case ScriptSourceLocationType::kInlineInsideDocumentWrite:
+ no_cache_reason = v8::ScriptCompiler::kNoCacheBecauseInDocumentWrite;
+ break;
+ case ScriptSourceLocationType::kExternalFile:
+ no_cache_reason =
+ v8::ScriptCompiler::kNoCacheBecauseResourceWithNoCacheHandler;
+ break;
+ // TODO(leszeks): Possibly differentiate between the other kinds of script
+ // origin also.
+ default:
+ no_cache_reason = v8::ScriptCompiler::kNoCacheBecauseNoResource;
+ break;
+ }
+
+ SingleCachedMetadataHandler* cache_handler = source.CacheHandler();
+ if (!cache_handler) {
+ return std::make_tuple(v8::ScriptCompiler::kNoCompileOptions,
+ ProduceCacheOptions::kNoProduceCache,
+ no_cache_reason);
+ }
+
+ if (cache_options == kV8CacheOptionsNone) {
+ no_cache_reason = v8::ScriptCompiler::kNoCacheBecauseCachingDisabled;
+ return std::make_tuple(v8::ScriptCompiler::kNoCompileOptions,
+ ProduceCacheOptions::kNoProduceCache,
+ no_cache_reason);
+ }
+
+ if (source.Source().length() < kMinimalCodeLength) {
+ no_cache_reason = v8::ScriptCompiler::kNoCacheBecauseScriptTooSmall;
+ return std::make_tuple(v8::ScriptCompiler::kNoCompileOptions,
+ ProduceCacheOptions::kNoProduceCache,
+ no_cache_reason);
+ }
+
+ uint32_t code_cache_tag = V8CodeCache::TagForCodeCache(cache_handler);
+ scoped_refptr<CachedMetadata> code_cache =
+ cache_handler->GetCachedMetadata(code_cache_tag);
+ if (code_cache) {
+ return std::make_tuple(v8::ScriptCompiler::kConsumeCodeCache,
+ ProduceCacheOptions::kNoProduceCache,
+ no_cache_reason);
+ }
+
+ // If the resource is served from CacheStorage, generate the V8 code cache in
+ // the first load.
+ if (cache_handler->IsServedFromCacheStorage())
+ cache_options = kV8CacheOptionsCodeWithoutHeatCheck;
+
+ switch (cache_options) {
+ case kV8CacheOptionsDefault:
+ case kV8CacheOptionsCode:
+ if (!IsResourceHotForCaching(cache_handler, kHotHours)) {
+ return std::make_tuple(v8::ScriptCompiler::kNoCompileOptions,
+ ProduceCacheOptions::kSetTimeStamp,
+ v8::ScriptCompiler::kNoCacheBecauseCacheTooCold);
+ }
+ return std::make_tuple(
+ v8::ScriptCompiler::kNoCompileOptions,
+ ProduceCacheOptions::kProduceCodeCache,
+ v8::ScriptCompiler::kNoCacheBecauseDeferredProduceCodeCache);
+ case kV8CacheOptionsCodeWithoutHeatCheck:
+ return std::make_tuple(
+ v8::ScriptCompiler::kNoCompileOptions,
+ ProduceCacheOptions::kProduceCodeCache,
+ v8::ScriptCompiler::kNoCacheBecauseDeferredProduceCodeCache);
+ case kV8CacheOptionsFullCodeWithoutHeatCheck:
+ return std::make_tuple(
+ v8::ScriptCompiler::kEagerCompile,
+ ProduceCacheOptions::kProduceCodeCache,
+ v8::ScriptCompiler::kNoCacheBecauseDeferredProduceCodeCache);
+ case kV8CacheOptionsNone:
+ // Shouldn't happen, as this is handled above.
+ // Case is here so that compiler can check all cases are handled.
+ NOTREACHED();
+ break;
+ }
+
+ // All switch branches should return and we should never get here.
+ // But some compilers aren't sure, hence this default.
+ NOTREACHED();
+ return std::make_tuple(v8::ScriptCompiler::kNoCompileOptions,
+ ProduceCacheOptions::kNoProduceCache,
+ v8::ScriptCompiler::kNoCacheNoReason);
+}
+
+void V8CodeCache::ProduceCache(
+ v8::Isolate* isolate,
+ v8::Local<v8::Script> script,
+ const ScriptSourceCode& source,
+ ProduceCacheOptions produce_cache_options,
+ v8::ScriptCompiler::CompileOptions compile_options) {
+ TRACE_EVENT0("v8", "v8.compile");
+ RuntimeCallStatsScopedTracer rcs_scoped_tracer(isolate);
+ RUNTIME_CALL_TIMER_SCOPE(isolate, RuntimeCallStats::CounterId::kV8);
+
+ switch (produce_cache_options) {
+ case ProduceCacheOptions::kSetTimeStamp:
+ V8CodeCache::SetCacheTimeStamp(source.CacheHandler());
+ break;
+ case ProduceCacheOptions::kProduceCodeCache: {
+ constexpr const char* kTraceEventCategoryGroup = "v8,devtools.timeline";
+ TRACE_EVENT_BEGIN1(kTraceEventCategoryGroup, "v8.compile", "fileName",
+ source.Url().GetString().Utf8());
+
+ std::unique_ptr<v8::ScriptCompiler::CachedData> cached_data(
+ v8::ScriptCompiler::CreateCodeCache(script->GetUnboundScript()));
+ if (cached_data) {
+ const char* data = reinterpret_cast<const char*>(cached_data->data);
+ int length = cached_data->length;
+ if (length > 1024) {
+ // Omit histogram samples for small cache data to avoid outliers.
+ int cache_size_ratio =
+ static_cast<int>(100.0 * length / source.Source().length());
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ CustomCountHistogram, code_cache_size_histogram,
+ ("V8.CodeCacheSizeRatio", 0, 10000, 50));
+ code_cache_size_histogram.Count(cache_size_ratio);
+ }
+ SingleCachedMetadataHandler* cache_handler = source.CacheHandler();
+ cache_handler->ClearCachedMetadata(
+ CachedMetadataHandler::kCacheLocally);
+ cache_handler->SetCachedMetadata(
+ V8CodeCache::TagForCodeCache(cache_handler), data, length,
+ CachedMetadataHandler::kSendToPlatform);
+ }
+
+ TRACE_EVENT_END1(
+ kTraceEventCategoryGroup, "v8.compile", "data",
+ InspectorCompileScriptEvent::Data(
+ source.Url().GetString(), source.StartPosition(),
+ InspectorCompileScriptEvent::V8CacheResult(
+ InspectorCompileScriptEvent::V8CacheResult::ProduceResult(
+ compile_options, cached_data ? cached_data->length : 0),
+ base::Optional<InspectorCompileScriptEvent::V8CacheResult::
+ ConsumeResult>()),
+ source.Streamer()));
+ break;
+ }
+ case ProduceCacheOptions::kNoProduceCache:
+ break;
+ }
+}
+
+uint32_t V8CodeCache::TagForCodeCache(
+ SingleCachedMetadataHandler* cache_handler) {
+ return CacheTag(kCacheTagCode, cache_handler->Encoding());
+}
+
+uint32_t V8CodeCache::TagForTimeStamp(
+ SingleCachedMetadataHandler* cache_handler) {
+ return CacheTag(kCacheTagTimeStamp, cache_handler->Encoding());
+}
+
+// Store a timestamp to the cache as hint.
+void V8CodeCache::SetCacheTimeStamp(
+ SingleCachedMetadataHandler* cache_handler) {
+ double now = WTF::CurrentTime();
+ cache_handler->ClearCachedMetadata(CachedMetadataHandler::kCacheLocally);
+ cache_handler->SetCachedMetadata(TagForTimeStamp(cache_handler),
+ reinterpret_cast<char*>(&now), sizeof(now),
+ CachedMetadataHandler::kSendToPlatform);
+}
+
+// static
+scoped_refptr<CachedMetadata> V8CodeCache::GenerateFullCodeCache(
+ ScriptState* script_state,
+ const String& script_string,
+ const String& file_name,
+ const WTF::TextEncoding& encoding,
+ OpaqueMode opaque_mode) {
+ constexpr const char* kTraceEventCategoryGroup = "v8,devtools.timeline";
+ TRACE_EVENT_BEGIN1(kTraceEventCategoryGroup, "v8.compile", "fileName",
+ file_name.Utf8());
+
+ ScriptState::Scope scope(script_state);
+ v8::Isolate* isolate = script_state->GetIsolate();
+ // v8::TryCatch is needed to suppress all exceptions thrown during the code
+ // cache generation.
+ v8::TryCatch block(isolate);
+ ReferrerScriptInfo referrer_info;
+ v8::ScriptOrigin origin(
+ V8String(isolate, file_name),
+ v8::Integer::New(isolate, 0), // line_offset
+ v8::Integer::New(isolate, 0), // column_offset
+ v8::Boolean::New(
+ isolate,
+ opaque_mode == OpaqueMode::kNotOpaque), // is_shared_cross_origin
+ v8::Local<v8::Integer>(), // script_id
+ V8String(isolate, String("")), // source_map_url
+ v8::Boolean::New(isolate,
+ opaque_mode == OpaqueMode::kOpaque), // is_opaque
+ v8::False(isolate), // is_wasm
+ v8::False(isolate), // is_module
+ referrer_info.ToV8HostDefinedOptions(isolate));
+ v8::Local<v8::String> code(V8String(isolate, script_string));
+ v8::ScriptCompiler::Source source(code, origin);
+ scoped_refptr<CachedMetadata> cached_metadata;
+ std::unique_ptr<v8::ScriptCompiler::CachedData> cached_data;
+
+ v8::Local<v8::UnboundScript> unbound_script;
+ // When failed to compile the script with syntax error, the exceptions is
+ // suppressed by the v8::TryCatch, and returns null.
+ if (v8::ScriptCompiler::CompileUnboundScript(
+ isolate, &source, v8::ScriptCompiler::kEagerCompile)
+ .ToLocal(&unbound_script)) {
+ cached_data.reset(v8::ScriptCompiler::CreateCodeCache(unbound_script));
+ if (cached_data && cached_data->length) {
+ cached_metadata = CachedMetadata::Create(
+ CacheTag(kCacheTagCode, encoding.GetName()),
+ reinterpret_cast<const char*>(cached_data->data),
+ cached_data->length);
+ }
+ }
+
+ TRACE_EVENT_END1(
+ kTraceEventCategoryGroup, "v8.compile", "data",
+ InspectorCompileScriptEvent::Data(
+ file_name, TextPosition(),
+ InspectorCompileScriptEvent::V8CacheResult(
+ InspectorCompileScriptEvent::V8CacheResult::ProduceResult(
+ v8::ScriptCompiler::kEagerCompile,
+ cached_data ? cached_data->length : 0),
+ base::Optional<
+ InspectorCompileScriptEvent::V8CacheResult::ConsumeResult>()),
+ false));
+
+ return cached_metadata;
+}
+
+STATIC_ASSERT_ENUM(WebSettings::kV8CacheOptionsDefault, kV8CacheOptionsDefault);
+STATIC_ASSERT_ENUM(WebSettings::kV8CacheOptionsNone, kV8CacheOptionsNone);
+STATIC_ASSERT_ENUM(WebSettings::kV8CacheOptionsCode, kV8CacheOptionsCode);
+STATIC_ASSERT_ENUM(WebSettings::kV8CacheOptionsCodeWithoutHeatCheck,
+ kV8CacheOptionsCodeWithoutHeatCheck);
+STATIC_ASSERT_ENUM(WebSettings::kV8CacheOptionsFullCodeWithoutHeatCheck,
+ kV8CacheOptionsFullCodeWithoutHeatCheck);
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_code_cache.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_code_cache.h
new file mode 100644
index 00000000000..8f85911f4b5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_code_cache.h
@@ -0,0 +1,72 @@
+// 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_BINDINGS_CORE_V8_V8_CODE_CACHE_H_
+#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_CODE_CACHE_H_
+
+#include <stdint.h>
+
+#include "third_party/blink/renderer/bindings/core/v8/v8_cache_options.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/bindings/v8_binding_macros.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "v8/include/v8.h"
+
+namespace WTF {
+class TextEncoding;
+} // namespace WTF
+
+namespace blink {
+
+class CachedMetadata;
+class SingleCachedMetadataHandler;
+class ScriptSourceCode;
+
+class CORE_EXPORT V8CodeCache final {
+ STATIC_ONLY(V8CodeCache);
+
+ public:
+ enum class OpaqueMode {
+ kOpaque,
+ kNotOpaque,
+ };
+
+ enum class ProduceCacheOptions {
+ kNoProduceCache,
+ kSetTimeStamp,
+ kProduceCodeCache,
+ };
+
+ static uint32_t TagForParserCache(SingleCachedMetadataHandler*);
+ static uint32_t TagForCodeCache(SingleCachedMetadataHandler*);
+ static uint32_t TagForTimeStamp(SingleCachedMetadataHandler*);
+ static void SetCacheTimeStamp(SingleCachedMetadataHandler*);
+
+ static std::tuple<v8::ScriptCompiler::CompileOptions,
+ ProduceCacheOptions,
+ v8::ScriptCompiler::NoCacheReason>
+ GetCompileOptions(V8CacheOptions, const ScriptSourceCode&);
+
+ static v8::ScriptCompiler::CachedData* CreateCachedData(
+ SingleCachedMetadataHandler*);
+
+ static void ProduceCache(v8::Isolate*,
+ v8::Local<v8::Script>,
+ const ScriptSourceCode&,
+ ProduceCacheOptions,
+ v8::ScriptCompiler::CompileOptions);
+
+ static scoped_refptr<CachedMetadata> GenerateFullCodeCache(
+ ScriptState*,
+ const String& script_string,
+ const String& file_name,
+ const WTF::TextEncoding&,
+ OpaqueMode);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_CODE_CACHE_H_
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_context_snapshot.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_context_snapshot.cc
index d2f2dc4a46f..41ef61f57bb 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_context_snapshot.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_context_snapshot.cc
@@ -17,6 +17,7 @@
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
#include "third_party/blink/renderer/platform/bindings/origin_trial_features.h"
#include "third_party/blink/renderer/platform/bindings/v8_object_constructor.h"
+#include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -83,7 +84,7 @@ SnapshotInterface g_snapshot_interfaces[] = {
{&V8Document::wrapperTypeInfo,
V8Document::InstallRuntimeEnabledFeaturesOnTemplate},
};
-constexpr size_t kSnapshotInterfaceSize = arraysize(g_snapshot_interfaces);
+constexpr size_t kSnapshotInterfaceSize = base::size(g_snapshot_interfaces);
enum class InternalFieldType : uint8_t {
kNone,
@@ -456,7 +457,7 @@ void V8ContextSnapshot::TakeSnapshotForWorld(v8::SnapshotCreator* creator,
int indices[] = {kV8DOMWrapperObjectIndex, kV8DOMWrapperTypeIndex};
void* values[] = {nullptr, const_cast<WrapperTypeInfo*>(
&V8HTMLDocument::wrapperTypeInfo)};
- document_wrapper->SetAlignedPointerInInternalFields(arraysize(indices),
+ document_wrapper->SetAlignedPointerInInternalFields(base::size(indices),
indices, values);
// Set the cached accessor for window.document.
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc
index 9e8e84ae6bf..016b2461d4a 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc
@@ -21,7 +21,8 @@ V8EmbedderGraphBuilder::V8EmbedderGraphBuilder(v8::Isolate* isolate,
void V8EmbedderGraphBuilder::BuildEmbedderGraphCallback(
v8::Isolate* isolate,
- v8::EmbedderGraph* graph) {
+ v8::EmbedderGraph* graph,
+ void* data) {
V8EmbedderGraphBuilder builder(isolate, graph);
builder.BuildEmbedderGraph();
}
@@ -109,9 +110,9 @@ void V8EmbedderGraphBuilder::VisitPersistentHandle(
DomTreeState dom_tree_state = DomTreeStateFromWrapper(class_id, v8_value);
EmbedderNode* graph_node = GraphNode(
traceable, traceable->NameInHeapSnapshot(), wrapper, dom_tree_state);
- const TraceWrapperDescriptor& wrapper_descriptor =
- TraceWrapperDescriptorFor<ScriptWrappable>(traceable);
- WorklistItem item = ToWorklistItem(graph_node, wrapper_descriptor);
+ const TraceDescriptor& descriptor =
+ TraceDescriptorFor<ScriptWrappable>(traceable);
+ WorklistItem item = ToWorklistItem(graph_node, descriptor);
switch (graph_node->GetDomTreeState()) {
case DomTreeState::kAttached:
PushToWorklist(item);
@@ -135,8 +136,9 @@ void V8EmbedderGraphBuilder::Visit(
}
}
-void V8EmbedderGraphBuilder::Visit(void* object,
- TraceWrapperDescriptor wrapper_descriptor) {
+void V8EmbedderGraphBuilder::VisitWithWrappers(
+ void* object,
+ TraceDescriptor wrapper_descriptor) {
// Add an edge from the current parent to this object.
// Also push the object to the worklist in order to process its members.
const void* traceable = wrapper_descriptor.base_object_payload;
@@ -151,6 +153,12 @@ void V8EmbedderGraphBuilder::Visit(void* object,
PushToWorklist(ToWorklistItem(graph_node, wrapper_descriptor));
}
+void V8EmbedderGraphBuilder::VisitBackingStoreStrongly(void* object,
+ void** object_slot,
+ TraceDescriptor desc) {
+ desc.callback(this, desc.base_object_payload);
+}
+
void V8EmbedderGraphBuilder::Visit(DOMWrapperMap<ScriptWrappable>* wrapper_map,
const ScriptWrappable* key) {
// Add an edge from the current parent to the V8 object.
@@ -195,9 +203,8 @@ void V8EmbedderGraphBuilder::VisitPendingActivities() {
V8EmbedderGraphBuilder::WorklistItem V8EmbedderGraphBuilder::ToWorklistItem(
EmbedderNode* node,
- const TraceWrapperDescriptor& wrapper_descriptor) const {
- return {node, wrapper_descriptor.base_object_payload,
- wrapper_descriptor.trace_wrappers_callback};
+ const TraceDescriptor& descriptor) const {
+ return {node, descriptor.base_object_payload, descriptor.callback};
}
void V8EmbedderGraphBuilder::PushToWorklist(WorklistItem item) const {
@@ -213,7 +220,7 @@ void V8EmbedderGraphBuilder::VisitTransitiveClosure() {
auto item = worklist_.back();
worklist_.pop_back();
ParentScope parent(this, item.node);
- item.trace_wrappers_callback(this, const_cast<void*>(item.traceable));
+ item.trace_callback(this, const_cast<void*>(item.traceable));
}
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.h
index b88b027fba8..9fb02a4597c 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.h
@@ -19,7 +19,9 @@ class V8EmbedderGraphBuilder : public ScriptWrappableVisitor,
V8EmbedderGraphBuilder(v8::Isolate*, Graph*);
- static void BuildEmbedderGraphCallback(v8::Isolate*, v8::EmbedderGraph*);
+ static void BuildEmbedderGraphCallback(v8::Isolate*,
+ v8::EmbedderGraph*,
+ void* data);
void BuildEmbedderGraph();
// v8::PersistentHandleVisitor override.
@@ -28,8 +30,11 @@ class V8EmbedderGraphBuilder : public ScriptWrappableVisitor,
// Visitor overrides.
void Visit(const TraceWrapperV8Reference<v8::Value>&) final;
- void Visit(void*, TraceWrapperDescriptor) final;
+ void VisitWithWrappers(void*, TraceDescriptor) final;
void Visit(DOMWrapperMap<ScriptWrappable>*, const ScriptWrappable*) final;
+ void VisitBackingStoreStrongly(void* object,
+ void** object_slot,
+ TraceDescriptor desc) final;
protected:
using Visitor::Visit;
@@ -111,11 +116,10 @@ class V8EmbedderGraphBuilder : public ScriptWrappableVisitor,
struct WorklistItem {
EmbedderNode* node;
Traceable traceable;
- TraceWrappersCallback trace_wrappers_callback;
+ TraceCallback trace_callback;
};
- WorklistItem ToWorklistItem(EmbedderNode*,
- const TraceWrapperDescriptor&) const;
+ WorklistItem ToWorklistItem(EmbedderNode*, const TraceDescriptor&) const;
Graph::Node* GraphNode(const v8::Local<v8::Value>&) const;
EmbedderNode* GraphNode(Traceable,
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_error_handler.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_error_handler.cc
index 2fff5dc35de..005c55c13e0 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_error_handler.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_error_handler.cc
@@ -82,7 +82,7 @@ v8::Local<v8::Value> V8ErrorHandler::CallListenerFunction(
try_catch.SetVerbose(true);
v8::MaybeLocal<v8::Value> result = V8ScriptRunner::CallFunction(
- call_function, execution_context, this_value, arraysize(parameters),
+ call_function, execution_context, this_value, base::size(parameters),
parameters, GetIsolate());
v8::Local<v8::Value> return_value;
if (!result.ToLocal(&return_value))
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_event_listener.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_event_listener.cc
index 7cf70d44aa7..9770f7f62e4 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_event_listener.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_event_listener.cc
@@ -113,8 +113,8 @@ v8::Local<v8::Value> V8EventListener::CallListenerFunction(
v8::Local<v8::Value> parameters[1] = {js_event};
v8::Local<v8::Value> result;
if (!V8ScriptRunner::CallFunction(handler_function, frame->GetDocument(),
- receiver, arraysize(parameters), parameters,
- script_state->GetIsolate())
+ receiver, base::size(parameters),
+ parameters, script_state->GetIsolate())
.ToLocal(&result))
return v8::Local<v8::Value>();
return result;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.cc
index 44f53ee8afd..ff242d1984c 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_gc_controller.cc
@@ -33,6 +33,7 @@
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
+
#include "third_party/blink/public/platform/blame_context.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
@@ -48,9 +49,11 @@
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.h"
#include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h"
+#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -191,10 +194,11 @@ void V8GCController::GcPrologue(v8::Isolate* isolate,
namespace {
void UpdateCollectedPhantomHandles(v8::Isolate* isolate) {
- ThreadHeapStats& heap_stats = ThreadState::Current()->Heap().HeapStats();
- size_t count = isolate->NumberOfPhantomHandleResetsSinceLastCall();
- heap_stats.DecreaseWrapperCount(count);
- heap_stats.IncreaseCollectedWrapperCount(count);
+ ThreadHeapStatsCollector* stats_collector =
+ ThreadState::Current()->Heap().stats_collector();
+ const size_t count = isolate->NumberOfPhantomHandleResetsSinceLastCall();
+ stats_collector->DecreaseWrapperCount(count);
+ stats_collector->IncreaseCollectedWrapperCount(count);
}
} // namespace
@@ -208,6 +212,11 @@ void V8GCController::GcEpilogue(v8::Isolate* isolate,
case v8::kGCTypeScavenge:
TRACE_EVENT_END1("devtools.timeline,v8", "MinorGC", "usedHeapSizeAfter",
UsedHeapSize(isolate));
+ // Scavenger might have dropped nodes.
+ if (ThreadState::Current()) {
+ ThreadState::Current()->ScheduleV8FollowupGCIfNeeded(
+ BlinkGC::kV8MinorGC);
+ }
break;
case v8::kGCTypeMarkSweepCompact:
TRACE_EVENT_END1("devtools.timeline,v8", "MajorGC", "usedHeapSizeAfter",
@@ -256,10 +265,10 @@ void V8GCController::GcEpilogue(v8::Isolate* isolate,
// multiple V8's GC.
current_thread_state->CollectGarbage(
BlinkGC::kHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
// Forces a precise GC at the end of the current event loop.
- current_thread_state->SetGCState(ThreadState::kFullGCScheduled);
+ current_thread_state->ScheduleFullGC();
}
// v8::kGCCallbackFlagCollectAllAvailableGarbage is used when V8 handles
@@ -269,7 +278,7 @@ void V8GCController::GcEpilogue(v8::Isolate* isolate,
// This single GC is not enough. See the above comment.
current_thread_state->CollectGarbage(
BlinkGC::kHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
// The conservative GC might have left floating garbage. Schedule
// precise GC to ensure that we collect all available garbage.
@@ -289,17 +298,17 @@ void V8GCController::GcEpilogue(v8::Isolate* isolate,
void V8GCController::CollectGarbage(v8::Isolate* isolate, bool only_minor_gc) {
v8::HandleScope handle_scope(isolate);
- scoped_refptr<ScriptState> script_state = ScriptState::Create(
+ ScriptState* script_state = ScriptState::Create(
v8::Context::New(isolate),
DOMWrapperWorld::Create(isolate,
DOMWrapperWorld::WorldType::kGarbageCollector));
- ScriptState::Scope scope(script_state.get());
+ ScriptState::Scope scope(script_state);
StringBuilder builder;
builder.Append("if (gc) gc(");
builder.Append(only_minor_gc ? "true" : "false");
- builder.Append(")");
+ builder.Append(");");
V8ScriptRunner::CompileAndRunInternalScript(
- isolate, script_state.get(),
+ isolate, script_state,
ScriptSourceCode(builder.ToString(), ScriptSourceLocationType::kInternal,
nullptr, KURL(), TextPosition()));
script_state->DisposePerContextData();
@@ -353,7 +362,7 @@ class DOMWrapperPurger final : public v8::PersistentHandleVisitor {
void* values[] = {nullptr, nullptr};
v8::Local<v8::Object> wrapper = v8::Local<v8::Object>::New(
isolate_, v8::Persistent<v8::Object>::Cast(*value));
- wrapper->SetAlignedPointerInInternalFields(arraysize(indices), indices,
+ wrapper->SetAlignedPointerInInternalFields(base::size(indices), indices,
values);
value->Reset();
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_gc_for_context_dispose.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_gc_for_context_dispose.cc
index 73fc3414eee..948e9827edd 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_gc_for_context_dispose.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_gc_for_context_dispose.cc
@@ -30,27 +30,31 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_gc_for_context_dispose.h"
+#include "base/process/process_metrics.h"
#include "build/build_config.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/memory_coordinator.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
-#include "third_party/blink/renderer/platform/wtf/process_metrics.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
#include "v8/include/v8.h"
-size_t GetMemoryUsage() {
- size_t usage = WTF::GetMallocUsage() + WTF::Partitions::TotalActiveBytes() +
- blink::ProcessHeap::TotalAllocatedObjectSize() +
- blink::ProcessHeap::TotalMarkedObjectSize();
+#if defined(OS_ANDROID)
+static size_t GetMemoryUsage() {
+ size_t usage =
+ base::ProcessMetrics::CreateCurrentProcessMetrics()->GetMallocUsage() +
+ WTF::Partitions::TotalActiveBytes() +
+ blink::ProcessHeap::TotalAllocatedObjectSize() +
+ blink::ProcessHeap::TotalMarkedObjectSize();
v8::HeapStatistics v8_heap_statistics;
blink::V8PerIsolateData::MainThreadIsolate()->GetHeapStatistics(
&v8_heap_statistics);
usage = v8_heap_statistics.total_heap_size();
return usage;
}
+#endif // defined(OS_ANDROID)
namespace blink {
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_html_constructor.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_html_constructor.cc
index 518409c9a2f..e9b01bed52b 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_html_constructor.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_html_constructor.cc
@@ -4,16 +4,15 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_html_constructor.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_custom_element_definition.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_html_element.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/exception_code.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/html/custom/custom_element_registry.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding_macros.h"
#include "third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h"
@@ -128,7 +127,7 @@ void V8HTMLConstructor::HtmlConstructor(
// During upgrade an element has invoked the same constructor
// before calling 'super' and that invocation has poached the
// element.
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"this instance is already constructed");
return;
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_idle_task_runner.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_idle_task_runner.h
index ac95f6d7ec1..05c4a5b045c 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_idle_task_runner.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_idle_task_runner.h
@@ -47,10 +47,15 @@ class V8IdleTaskRunner : public gin::V8IdleTaskRunner {
explicit V8IdleTaskRunner(ThreadScheduler* scheduler)
: scheduler_(scheduler) {}
~V8IdleTaskRunner() override = default;
- void PostIdleTask(v8::IdleTask* task) override {
+ void PostIdleTask(std::unique_ptr<v8::IdleTask> task) override {
DCHECK(RuntimeEnabledFeatures::V8IdleTasksEnabled());
scheduler_->PostIdleTask(
- FROM_HERE, WTF::Bind(&v8::IdleTask::Run, base::WrapUnique(task)));
+ FROM_HERE,
+ WTF::Bind(
+ [](std::unique_ptr<v8::IdleTask> task, TimeTicks deadline) {
+ task->Run(deadline.since_origin().InSecondsF());
+ },
+ std::move(task)));
}
private:
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
index c8c822632a6..83a6639306a 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
@@ -29,6 +29,8 @@
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_macros.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/bindings/core/v8/binding_security.h"
@@ -50,18 +52,19 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.h"
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.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/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_dom_window.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/inspector/main_thread_debugger.h"
+#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h"
#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
-#include "third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/loader/fetch/access_control_status.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -73,6 +76,7 @@
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h"
#include "v8/include/v8-profiler.h"
+#include "v8/include/v8.h"
namespace blink {
@@ -94,9 +98,25 @@ namespace {
static NearV8HeapLimitCallback g_near_heap_limit_on_main_thread_callback_ =
nullptr;
-void Record(NearV8HeapLimitHandling handling) {
+void Record(NearV8HeapLimitHandling handling,
+ v8::Isolate* isolate,
+ size_t heap_limit,
+ ukm::UkmRecorder* ukm_recorder,
+ int64_t ukm_source_id) {
UMA_HISTOGRAM_ENUMERATION("BloatedRenderer.V8.NearV8HeapLimitHandling",
handling);
+ if (ukm_recorder) {
+ // Record size metrics in MB similar to Memory.Experimental.Renderer2.V8.
+ const size_t kMB = 1024 * 1024;
+ v8::HeapStatistics heap_statistics;
+ isolate->GetHeapStatistics(&heap_statistics);
+ ukm::builders::BloatedRenderer(ukm_source_id)
+ .SetV8_NearV8HeapLimitHandling(static_cast<int64_t>(handling))
+ .SetV8_Heap(heap_statistics.total_physical_size() / kMB)
+ .SetV8_Heap_AllocatedObjects(heap_statistics.used_heap_size() / kMB)
+ .SetV8_Heap_Limit(heap_limit / kMB)
+ .Record(ukm_recorder);
+ }
}
size_t IncreaseV8HeapLimit(size_t v8_heap_limit) {
@@ -107,40 +127,62 @@ size_t IncreaseV8HeapLimit(size_t v8_heap_limit) {
return v8_heap_limit + v8_heap_limit / 4;
}
-size_t NearHeapLimitCallbackOnMainThread(void* isolate,
+size_t NearHeapLimitCallbackOnMainThread(void* data,
size_t current_heap_limit,
size_t initial_heap_limit) {
- V8PerIsolateData* per_isolate_data =
- V8PerIsolateData::From(reinterpret_cast<v8::Isolate*>(isolate));
+ v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(data);
+ V8PerIsolateData* per_isolate_data = V8PerIsolateData::From(isolate);
if (per_isolate_data->IsNearV8HeapLimitHandled()) {
// Ignore all calls after the first one.
return current_heap_limit;
}
per_isolate_data->HandledNearV8HeapLimit();
+
+ // Find the main document for UKM recording.
+ Document* document = nullptr;
+ int pages = 0;
+ for (Page* page : Page::OrdinaryPages()) {
+ if (page->MainFrame()->IsLocalFrame()) {
+ ++pages;
+ document = ToLocalFrame(page->MainFrame())->GetDocument();
+ }
+ }
+ ukm::UkmRecorder* ukm_recorder = nullptr;
+ int64_t ukm_source_id = 0;
+ // Do not record UKM if there are multiple pages as we cannot attribute
+ // the heap size to a specific page.
+ if (pages == 1 && document) {
+ ukm_recorder = document->UkmRecorder();
+ ukm_source_id = document->UkmSourceID();
+ }
+
if (current_heap_limit != initial_heap_limit) {
- Record(NearV8HeapLimitHandling::kIgnoredDueToChangedHeapLimit);
+ Record(NearV8HeapLimitHandling::kIgnoredDueToChangedHeapLimit, isolate,
+ current_heap_limit, ukm_recorder, ukm_source_id);
return current_heap_limit;
}
NearV8HeapLimitHandling handling =
g_near_heap_limit_on_main_thread_callback_();
- Record(handling);
+ Record(handling, isolate, current_heap_limit, ukm_recorder, ukm_source_id);
return (handling == NearV8HeapLimitHandling::kForwardedToBrowser)
? IncreaseV8HeapLimit(current_heap_limit)
: current_heap_limit;
}
-size_t NearHeapLimitCallbackOnWorkerThread(void* isolate,
+size_t NearHeapLimitCallbackOnWorkerThread(void* data,
size_t current_heap_limit,
size_t initial_heap_limit) {
- V8PerIsolateData* per_isolate_data =
- V8PerIsolateData::From(reinterpret_cast<v8::Isolate*>(isolate));
+ v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(data);
+ V8PerIsolateData* per_isolate_data = V8PerIsolateData::From(isolate);
if (per_isolate_data->IsNearV8HeapLimitHandled()) {
// Ignore all calls after the first one.
return current_heap_limit;
}
per_isolate_data->HandledNearV8HeapLimit();
- Record(NearV8HeapLimitHandling::kIgnoredDueToWorker);
+ // Do not record UKM on worker thread.
+ Record(NearV8HeapLimitHandling::kIgnoredDueToWorker, isolate,
+ current_heap_limit, nullptr, 0);
return current_heap_limit;
}
@@ -310,9 +352,13 @@ static void PromiseRejectHandler(v8::PromiseRejectMessage data,
if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) {
rejected_promises.HandlerAdded(data);
return;
+ } else if (data.GetEvent() == v8::kPromiseRejectAfterResolved ||
+ data.GetEvent() == v8::kPromiseResolveAfterResolved) {
+ // Ignore reject/resolve after resolved.
+ return;
}
- DCHECK_EQ(data.GetEvent(), v8::kPromiseRejectWithNoHandler);
+ DCHECK_EQ(v8::kPromiseRejectWithNoHandler, data.GetEvent());
v8::Isolate* isolate = script_state->GetIsolate();
ExecutionContext* context = ExecutionContext::From(script_state);
@@ -709,8 +755,8 @@ void V8Initializer::InitializeMainThread(const intptr_t* reference_table) {
isolate->SetPromiseRejectCallback(PromiseRejectHandlerInMainThread);
if (v8::HeapProfiler* profiler = isolate->GetHeapProfiler()) {
- profiler->SetBuildEmbedderGraphCallback(
- &V8EmbedderGraphBuilder::BuildEmbedderGraphCallback);
+ profiler->AddBuildEmbedderGraphCallback(
+ &V8EmbedderGraphBuilder::BuildEmbedderGraphCallback, nullptr);
}
DCHECK(ThreadState::MainThreadState());
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_delegate.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_delegate.cc
index 402752f36b2..acd50fa35ae 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_delegate.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_delegate.cc
@@ -38,10 +38,4 @@ void V8IntersectionObserverDelegate::Trace(blink::Visitor* visitor) {
ContextClient::Trace(visitor);
}
-void V8IntersectionObserverDelegate::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(callback_);
- IntersectionObserverDelegate::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_delegate.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_delegate.h
index 9fb8cdd6acd..3611a18e24f 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_delegate.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_delegate.h
@@ -30,7 +30,6 @@ class V8IntersectionObserverDelegate final
ExecutionContext* GetExecutionContext() const override;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
void Deliver(const HeapVector<Member<IntersectionObserverEntry>>&,
IntersectionObserver&) override;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_lazy_event_listener.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_lazy_event_listener.cc
index c6103129b7d..0313cfc9ed6 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_lazy_event_listener.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_lazy_event_listener.cc
@@ -112,8 +112,8 @@ v8::Local<v8::Value> V8LazyEventListener::CallListenerFunction(
v8::Local<v8::Value> parameters[1] = {js_event};
v8::Local<v8::Value> result;
if (!V8ScriptRunner::CallFunction(handler_function, frame->GetDocument(),
- receiver, arraysize(parameters), parameters,
- script_state->GetIsolate())
+ receiver, base::size(parameters),
+ parameters, script_state->GetIsolate())
.ToLocal(&result))
return v8::Local<v8::Value>();
return result;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder.cc
index 8a82ea3b6c0..c448406ca4b 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder.cc
@@ -53,7 +53,7 @@ V8ObjectBuilder& V8ObjectBuilder::AddStringOrNull(const StringView& name,
}
ScriptValue V8ObjectBuilder::GetScriptValue() const {
- return ScriptValue(script_state_.get(), object_);
+ return ScriptValue(script_state_, object_);
}
void V8ObjectBuilder::AddInternal(const StringView& name,
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder.h
index 769e071bbd5..6fd0c7498f7 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder.h
@@ -22,7 +22,7 @@ class CORE_EXPORT V8ObjectBuilder final {
public:
explicit V8ObjectBuilder(ScriptState*);
- ScriptState* GetScriptState() const { return script_state_.get(); }
+ ScriptState* GetScriptState() const { return script_state_; }
V8ObjectBuilder& Add(const StringView& name, const V8ObjectBuilder&);
@@ -47,7 +47,7 @@ class CORE_EXPORT V8ObjectBuilder final {
private:
void AddInternal(const StringView& name, v8::Local<v8::Value>);
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
v8::Local<v8::Object> object_;
};
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder_test.cc
index e4cd8cc2844..1e2f145b674 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_builder_test.cc
@@ -20,7 +20,7 @@ TEST(V8ObjectBuilderTest, addNull) {
ScriptValue json_object = builder.GetScriptValue();
EXPECT_TRUE(json_object.IsObject());
- String json_string = V8StringToWebCoreString<String>(
+ String json_string = ToBlinkString<String>(
v8::JSON::Stringify(scope.GetContext(),
json_object.V8Value().As<v8::Object>())
.ToLocalChecked(),
@@ -39,7 +39,7 @@ TEST(V8ObjectBuilderTest, addBoolean) {
ScriptValue json_object = builder.GetScriptValue();
EXPECT_TRUE(json_object.IsObject());
- String json_string = V8StringToWebCoreString<String>(
+ String json_string = ToBlinkString<String>(
v8::JSON::Stringify(scope.GetContext(),
json_object.V8Value().As<v8::Object>())
.ToLocalChecked(),
@@ -58,7 +58,7 @@ TEST(V8ObjectBuilderTest, addNumber) {
ScriptValue json_object = builder.GetScriptValue();
EXPECT_TRUE(json_object.IsObject());
- String json_string = V8StringToWebCoreString<String>(
+ String json_string = ToBlinkString<String>(
v8::JSON::Stringify(scope.GetContext(),
json_object.V8Value().As<v8::Object>())
.ToLocalChecked(),
@@ -85,7 +85,7 @@ TEST(V8ObjectBuilderTest, addString) {
ScriptValue json_object = builder.GetScriptValue();
EXPECT_TRUE(json_object.IsObject());
- String json_string = V8StringToWebCoreString<String>(
+ String json_string = ToBlinkString<String>(
v8::JSON::Stringify(scope.GetContext(),
json_object.V8Value().As<v8::Object>())
.ToLocalChecked(),
@@ -110,7 +110,7 @@ TEST(V8ObjectBuilderTest, add) {
EXPECT_TRUE(builder_json_object.IsObject());
EXPECT_TRUE(result_json_object.IsObject());
- String json_string = V8StringToWebCoreString<String>(
+ String json_string = ToBlinkString<String>(
v8::JSON::Stringify(scope.GetContext(),
result_json_object.V8Value().As<v8::Object>())
.ToLocalChecked(),
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_parser.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_parser.cc
index 4890e5c72b1..e16d33a10fa 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_parser.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_object_parser.cc
@@ -4,9 +4,9 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_object_parser.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc
index 71f4326b49b..75f4589d174 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc
@@ -25,23 +25,18 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
-#include "base/optional.h"
#include "build/build_config.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/renderer/bindings/core/v8/binding_security.h"
#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
#include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
#include "third_party/blink/renderer/bindings/core/v8/script_streamer.h"
#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/bindings/core/v8/v8_code_cache.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_initializer.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/inspector/inspector_trace_events.h"
-#include "third_party/blink/renderer/core/inspector/thread_debugger.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
@@ -52,12 +47,6 @@
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
-#if defined(OS_WIN)
-#include <malloc.h>
-#else
-#include <alloca.h>
-#endif
-
namespace blink {
namespace {
@@ -102,58 +91,9 @@ v8::Local<v8::Value> ThrowStackOverflowExceptionIfNeeded(v8::Isolate* isolate) {
return result;
}
-enum CacheTagKind { kCacheTagCode = 0, kCacheTagTimeStamp = 1, kCacheTagLast };
-
-static const int kCacheTagKindSize = 1;
-
-uint32_t CacheTag(CacheTagKind kind, const String& encoding) {
- static_assert((1 << kCacheTagKindSize) >= kCacheTagLast,
- "CacheTagLast must be large enough");
-
- static uint32_t v8_cache_data_version =
- v8::ScriptCompiler::CachedDataVersionTag() << kCacheTagKindSize;
-
- // A script can be (successfully) interpreted with different encodings,
- // depending on the page it appears in. The cache doesn't know anything
- // about encodings, but the cached data is specific to one encoding. If we
- // later load the script from the cache and interpret it with a different
- // encoding, the cached data is not valid for that encoding.
- return (v8_cache_data_version | kind) +
- (encoding.IsNull() ? 0 : StringHash::GetHash(encoding));
-}
-
-// Check previously stored timestamp.
-bool IsResourceHotForCaching(SingleCachedMetadataHandler* cache_handler,
- int hot_hours) {
- const double cache_within_seconds = hot_hours * 60 * 60;
- scoped_refptr<CachedMetadata> cached_metadata =
- cache_handler->GetCachedMetadata(
- V8ScriptRunner::TagForTimeStamp(cache_handler));
- if (!cached_metadata)
- return false;
- double time_stamp;
- const int size = sizeof(time_stamp);
- DCHECK_EQ(cached_metadata->size(), static_cast<unsigned long>(size));
- memcpy(&time_stamp, cached_metadata->Data(), size);
- return (WTF::CurrentTime() - time_stamp) < cache_within_seconds;
-}
-
-v8::ScriptCompiler::CachedData* CreateCachedData(
- SingleCachedMetadataHandler* cache_handler) {
- DCHECK(cache_handler);
- uint32_t code_cache_tag = V8ScriptRunner::TagForCodeCache(cache_handler);
- scoped_refptr<CachedMetadata> cached_metadata =
- cache_handler->GetCachedMetadata(code_cache_tag);
- DCHECK(cached_metadata);
- const char* data = cached_metadata->Data();
- int length = cached_metadata->size();
- return new v8::ScriptCompiler::CachedData(
- reinterpret_cast<const uint8_t*>(data), length,
- v8::ScriptCompiler::CachedData::BufferNotOwned);
-}
-
v8::MaybeLocal<v8::Script> CompileScriptInternal(
v8::Isolate* isolate,
+ ExecutionContext* execution_context,
const ScriptSourceCode& source_code,
v8::ScriptOrigin origin,
v8::ScriptCompiler::CompileOptions compile_options,
@@ -171,6 +111,18 @@ v8::MaybeLocal<v8::Script> CompileScriptInternal(
streamer->Source(), code, origin);
}
+ // Allow inspector to use its own compilation cache store.
+ v8::ScriptCompiler::CachedData* inspector_data = nullptr;
+ probe::consumeCompilationCache(execution_context, source_code,
+ &inspector_data);
+ if (inspector_data) {
+ v8::ScriptCompiler::Source source(code, origin, inspector_data);
+ v8::MaybeLocal<v8::Script> script =
+ v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source,
+ v8::ScriptCompiler::kConsumeCodeCache);
+ return script;
+ }
+
switch (compile_options) {
case v8::ScriptCompiler::kNoCompileOptions:
case v8::ScriptCompiler::kEagerCompile: {
@@ -183,7 +135,7 @@ v8::MaybeLocal<v8::Script> CompileScriptInternal(
// Compile a script, and consume a V8 cache that was generated previously.
SingleCachedMetadataHandler* cache_handler = source_code.CacheHandler();
v8::ScriptCompiler::CachedData* cached_data =
- CreateCachedData(cache_handler);
+ V8CodeCache::CreateCachedData(cache_handler);
v8::ScriptCompiler::Source source(code, origin, cached_data);
v8::MaybeLocal<v8::Script> script =
v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &source,
@@ -217,100 +169,6 @@ v8::MaybeLocal<v8::Script> CompileScriptInternal(
} // namespace
-std::tuple<v8::ScriptCompiler::CompileOptions,
- V8ScriptRunner::ProduceCacheOptions,
- v8::ScriptCompiler::NoCacheReason>
-V8ScriptRunner::GetCompileOptions(V8CacheOptions cache_options,
- const ScriptSourceCode& source) {
- static const int kMinimalCodeLength = 1024;
- static const int kHotHours = 72;
- v8::ScriptCompiler::NoCacheReason no_cache_reason;
-
- switch (source.SourceLocationType()) {
- case ScriptSourceLocationType::kInline:
- no_cache_reason = v8::ScriptCompiler::kNoCacheBecauseInlineScript;
- break;
- case ScriptSourceLocationType::kInlineInsideDocumentWrite:
- no_cache_reason = v8::ScriptCompiler::kNoCacheBecauseInDocumentWrite;
- break;
- case ScriptSourceLocationType::kExternalFile:
- no_cache_reason =
- v8::ScriptCompiler::kNoCacheBecauseResourceWithNoCacheHandler;
- break;
- // TODO(leszeks): Possibly differentiate between the other kinds of script
- // origin also.
- default:
- no_cache_reason = v8::ScriptCompiler::kNoCacheBecauseNoResource;
- break;
- }
-
- SingleCachedMetadataHandler* cache_handler = source.CacheHandler();
- if (!cache_handler) {
- return std::make_tuple(v8::ScriptCompiler::kNoCompileOptions,
- ProduceCacheOptions::kNoProduceCache,
- no_cache_reason);
- }
-
- if (cache_options == kV8CacheOptionsNone) {
- no_cache_reason = v8::ScriptCompiler::kNoCacheBecauseCachingDisabled;
- return std::make_tuple(v8::ScriptCompiler::kNoCompileOptions,
- ProduceCacheOptions::kNoProduceCache,
- no_cache_reason);
- }
-
- if (source.Source().length() < kMinimalCodeLength) {
- no_cache_reason = v8::ScriptCompiler::kNoCacheBecauseScriptTooSmall;
- return std::make_tuple(v8::ScriptCompiler::kNoCompileOptions,
- ProduceCacheOptions::kNoProduceCache,
- no_cache_reason);
- }
-
- uint32_t code_cache_tag = V8ScriptRunner::TagForCodeCache(cache_handler);
- scoped_refptr<CachedMetadata> code_cache =
- cache_handler->GetCachedMetadata(code_cache_tag);
- if (code_cache) {
- return std::make_tuple(v8::ScriptCompiler::kConsumeCodeCache,
- ProduceCacheOptions::kNoProduceCache,
- no_cache_reason);
- }
-
- switch (cache_options) {
- case kV8CacheOptionsDefault:
- case kV8CacheOptionsCode:
- if (!IsResourceHotForCaching(cache_handler, kHotHours)) {
- return std::make_tuple(v8::ScriptCompiler::kNoCompileOptions,
- ProduceCacheOptions::kSetTimeStamp,
- v8::ScriptCompiler::kNoCacheBecauseCacheTooCold);
- }
- return std::make_tuple(
- v8::ScriptCompiler::kNoCompileOptions,
- ProduceCacheOptions::kProduceCodeCache,
- v8::ScriptCompiler::kNoCacheBecauseDeferredProduceCodeCache);
- case kV8CacheOptionsCodeWithoutHeatCheck:
- return std::make_tuple(
- v8::ScriptCompiler::kNoCompileOptions,
- ProduceCacheOptions::kProduceCodeCache,
- v8::ScriptCompiler::kNoCacheBecauseDeferredProduceCodeCache);
- case kV8CacheOptionsFullCodeWithoutHeatCheck:
- return std::make_tuple(
- v8::ScriptCompiler::kEagerCompile,
- ProduceCacheOptions::kProduceCodeCache,
- v8::ScriptCompiler::kNoCacheBecauseDeferredProduceCodeCache);
- case kV8CacheOptionsNone:
- // Shouldn't happen, as this is handled above.
- // Case is here so that compiler can check all cases are handled.
- NOTREACHED();
- break;
- }
-
- // All switch branches should return and we should never get here.
- // But some compilers aren't sure, hence this default.
- NOTREACHED();
- return std::make_tuple(v8::ScriptCompiler::kNoCompileOptions,
- ProduceCacheOptions::kNoProduceCache,
- v8::ScriptCompiler::kNoCacheNoReason);
-}
-
v8::MaybeLocal<v8::Script> V8ScriptRunner::CompileScript(
ScriptState* script_state,
const ScriptSourceCode& source,
@@ -330,7 +188,8 @@ v8::MaybeLocal<v8::Script> V8ScriptRunner::CompileScript(
constexpr const char* kTraceEventCategoryGroup = "v8,devtools.timeline";
TRACE_EVENT_BEGIN1(kTraceEventCategoryGroup, "v8.compile", "fileName",
file_name.Utf8());
- probe::V8Compile probe(ExecutionContext::From(script_state), file_name,
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+ probe::V8Compile probe(execution_context, file_name,
script_start_position.line_.ZeroBasedInt(),
script_start_position.column_.ZeroBasedInt());
@@ -348,13 +207,14 @@ v8::MaybeLocal<v8::Script> V8ScriptRunner::CompileScript(
referrer_info.ToV8HostDefinedOptions(isolate));
if (!*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(kTraceEventCategoryGroup)) {
- return CompileScriptInternal(isolate, source, origin, compile_options,
- no_cache_reason, nullptr);
+ return CompileScriptInternal(isolate, execution_context, source, origin,
+ compile_options, no_cache_reason, nullptr);
}
InspectorCompileScriptEvent::V8CacheResult cache_result;
- v8::MaybeLocal<v8::Script> script = CompileScriptInternal(
- isolate, source, origin, compile_options, no_cache_reason, &cache_result);
+ v8::MaybeLocal<v8::Script> script =
+ CompileScriptInternal(isolate, execution_context, source, origin,
+ compile_options, no_cache_reason, &cache_result);
TRACE_EVENT_END1(
kTraceEventCategoryGroup, "v8.compile", "data",
InspectorCompileScriptEvent::Data(file_name, script_start_position,
@@ -429,64 +289,6 @@ v8::MaybeLocal<v8::Value> V8ScriptRunner::RunCompiledScript(
return result;
}
-void V8ScriptRunner::ProduceCache(
- v8::Isolate* isolate,
- v8::Local<v8::Script> script,
- const ScriptSourceCode& source,
- ProduceCacheOptions produce_cache_options,
- v8::ScriptCompiler::CompileOptions compile_options) {
- TRACE_EVENT0("v8", "v8.run");
- RuntimeCallStatsScopedTracer rcs_scoped_tracer(isolate);
- RUNTIME_CALL_TIMER_SCOPE(isolate, RuntimeCallStats::CounterId::kV8);
-
- switch (produce_cache_options) {
- case ProduceCacheOptions::kSetTimeStamp:
- V8ScriptRunner::SetCacheTimeStamp(source.CacheHandler());
- break;
- case ProduceCacheOptions::kProduceCodeCache: {
- constexpr const char* kTraceEventCategoryGroup = "v8,devtools.timeline";
- TRACE_EVENT_BEGIN1(kTraceEventCategoryGroup, "v8.compile", "fileName",
- source.Url().GetString().Utf8());
-
- std::unique_ptr<v8::ScriptCompiler::CachedData> cached_data(
- v8::ScriptCompiler::CreateCodeCache(script->GetUnboundScript()));
- if (cached_data) {
- const char* data = reinterpret_cast<const char*>(cached_data->data);
- int length = cached_data->length;
- if (length > 1024) {
- // Omit histogram samples for small cache data to avoid outliers.
- int cache_size_ratio =
- static_cast<int>(100.0 * length / source.Source().length());
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram, code_cache_size_histogram,
- ("V8.CodeCacheSizeRatio", 0, 10000, 50));
- code_cache_size_histogram.Count(cache_size_ratio);
- }
- SingleCachedMetadataHandler* cache_handler = source.CacheHandler();
- cache_handler->ClearCachedMetadata(
- CachedMetadataHandler::kCacheLocally);
- cache_handler->SetCachedMetadata(
- V8ScriptRunner::TagForCodeCache(cache_handler), data, length,
- CachedMetadataHandler::kSendToPlatform);
- }
-
- TRACE_EVENT_END1(
- kTraceEventCategoryGroup, "v8.compile", "data",
- InspectorCompileScriptEvent::Data(
- source.Url().GetString(), source.StartPosition(),
- InspectorCompileScriptEvent::V8CacheResult(
- InspectorCompileScriptEvent::V8CacheResult::ProduceResult(
- compile_options, cached_data ? cached_data->length : 0),
- base::Optional<InspectorCompileScriptEvent::V8CacheResult::
- ConsumeResult>()),
- source.Streamer()));
- break;
- }
- case ProduceCacheOptions::kNoProduceCache:
- break;
- }
-}
-
v8::MaybeLocal<v8::Value> V8ScriptRunner::CompileAndRunInternalScript(
v8::Isolate* isolate,
ScriptState* script_state,
@@ -494,13 +296,14 @@ v8::MaybeLocal<v8::Value> V8ScriptRunner::CompileAndRunInternalScript(
DCHECK_EQ(isolate, script_state->GetIsolate());
v8::ScriptCompiler::CompileOptions compile_options;
- V8ScriptRunner::ProduceCacheOptions produce_cache_options;
+ V8CodeCache::ProduceCacheOptions produce_cache_options;
v8::ScriptCompiler::NoCacheReason no_cache_reason;
std::tie(compile_options, produce_cache_options, no_cache_reason) =
- V8ScriptRunner::GetCompileOptions(kV8CacheOptionsDefault, source_code);
+ V8CodeCache::GetCompileOptions(kV8CacheOptionsDefault, source_code);
// Currently internal scripts don't have cache handlers. So we should not
// produce cache for them.
- DCHECK_EQ(produce_cache_options, ProduceCacheOptions::kNoProduceCache);
+ DCHECK_EQ(produce_cache_options,
+ V8CodeCache::ProduceCacheOptions::kNoProduceCache);
v8::Local<v8::Script> script;
// Use default ScriptReferrerInfo here:
// - nonce: empty for internal script, and
@@ -633,26 +436,6 @@ v8::MaybeLocal<v8::Value> V8ScriptRunner::EvaluateModule(
return module->Evaluate(context);
}
-uint32_t V8ScriptRunner::TagForCodeCache(
- SingleCachedMetadataHandler* cache_handler) {
- return CacheTag(kCacheTagCode, cache_handler->Encoding());
-}
-
-uint32_t V8ScriptRunner::TagForTimeStamp(
- SingleCachedMetadataHandler* cache_handler) {
- return CacheTag(kCacheTagTimeStamp, cache_handler->Encoding());
-}
-
-// Store a timestamp to the cache as hint.
-void V8ScriptRunner::SetCacheTimeStamp(
- SingleCachedMetadataHandler* cache_handler) {
- double now = WTF::CurrentTime();
- cache_handler->ClearCachedMetadata(CachedMetadataHandler::kCacheLocally);
- cache_handler->SetCachedMetadata(TagForTimeStamp(cache_handler),
- reinterpret_cast<char*>(&now), sizeof(now),
- CachedMetadataHandler::kSendToPlatform);
-}
-
void V8ScriptRunner::ReportException(v8::Isolate* isolate,
v8::Local<v8::Value> exception) {
DCHECK(!exception.IsEmpty());
@@ -683,78 +466,4 @@ v8::MaybeLocal<v8::Value> V8ScriptRunner::CallExtraHelper(
isolate, function, v8::Undefined(isolate), num_args, args);
}
-// static
-scoped_refptr<CachedMetadata> V8ScriptRunner::GenerateFullCodeCache(
- ScriptState* script_state,
- const String& script_string,
- const String& file_name,
- const WTF::TextEncoding& encoding,
- OpaqueMode opaque_mode) {
- constexpr const char* kTraceEventCategoryGroup = "v8,devtools.timeline";
- TRACE_EVENT_BEGIN1(kTraceEventCategoryGroup, "v8.compile", "fileName",
- file_name.Utf8());
-
- ScriptState::Scope scope(script_state);
- v8::Isolate* isolate = script_state->GetIsolate();
- // v8::TryCatch is needed to suppress all exceptions thrown during the code
- // cache generation.
- v8::TryCatch block(isolate);
- ReferrerScriptInfo referrer_info;
- v8::ScriptOrigin origin(
- V8String(isolate, file_name),
- v8::Integer::New(isolate, 0), // line_offset
- v8::Integer::New(isolate, 0), // column_offset
- v8::Boolean::New(
- isolate,
- opaque_mode == OpaqueMode::kNotOpaque), // is_shared_cross_origin
- v8::Local<v8::Integer>(), // script_id
- V8String(isolate, String("")), // source_map_url
- v8::Boolean::New(isolate,
- opaque_mode == OpaqueMode::kOpaque), // is_opaque
- v8::False(isolate), // is_wasm
- v8::False(isolate), // is_module
- referrer_info.ToV8HostDefinedOptions(isolate));
- v8::Local<v8::String> code(V8String(isolate, script_string));
- v8::ScriptCompiler::Source source(code, origin);
- scoped_refptr<CachedMetadata> cached_metadata;
- std::unique_ptr<v8::ScriptCompiler::CachedData> cached_data;
-
- v8::Local<v8::UnboundScript> unbound_script;
- // When failed to compile the script with syntax error, the exceptions is
- // suppressed by the v8::TryCatch, and returns null.
- if (v8::ScriptCompiler::CompileUnboundScript(
- isolate, &source, v8::ScriptCompiler::kEagerCompile)
- .ToLocal(&unbound_script)) {
- cached_data.reset(v8::ScriptCompiler::CreateCodeCache(unbound_script));
- if (cached_data && cached_data->length) {
- cached_metadata = CachedMetadata::Create(
- CacheTag(kCacheTagCode, encoding.GetName()),
- reinterpret_cast<const char*>(cached_data->data),
- cached_data->length);
- }
- }
-
- TRACE_EVENT_END1(
- kTraceEventCategoryGroup, "v8.compile", "data",
- InspectorCompileScriptEvent::Data(
- file_name, TextPosition(),
- InspectorCompileScriptEvent::V8CacheResult(
- InspectorCompileScriptEvent::V8CacheResult::ProduceResult(
- v8::ScriptCompiler::kEagerCompile,
- cached_data ? cached_data->length : 0),
- base::Optional<
- InspectorCompileScriptEvent::V8CacheResult::ConsumeResult>()),
- false));
-
- return cached_metadata;
-}
-
-STATIC_ASSERT_ENUM(WebSettings::kV8CacheOptionsDefault, kV8CacheOptionsDefault);
-STATIC_ASSERT_ENUM(WebSettings::kV8CacheOptionsNone, kV8CacheOptionsNone);
-STATIC_ASSERT_ENUM(WebSettings::kV8CacheOptionsCode, kV8CacheOptionsCode);
-STATIC_ASSERT_ENUM(WebSettings::kV8CacheOptionsCodeWithoutHeatCheck,
- kV8CacheOptionsCodeWithoutHeatCheck);
-STATIC_ASSERT_ENUM(WebSettings::kV8CacheOptionsFullCodeWithoutHeatCheck,
- kV8CacheOptionsFullCodeWithoutHeatCheck);
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner.h
index e89d6bc9940..a6e4920b3a9 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner.h
@@ -26,50 +26,29 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_SCRIPT_RUNNER_H_
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_SCRIPT_RUNNER_H_
-#include <stdint.h>
-
-#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_source_location_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_cache_options.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/bindings/v8_binding_macros.h"
#include "third_party/blink/renderer/platform/loader/fetch/access_control_status.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/text/text_position.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "v8/include/v8.h"
namespace WTF {
-class TextEncoding;
-} // namespace WTF
+class TextPosition;
+}
namespace blink {
-class CachedMetadata;
-class SingleCachedMetadataHandler;
class ExecutionContext;
+class ReferrerScriptInfo;
class ScriptSourceCode;
+class ScriptState;
class CORE_EXPORT V8ScriptRunner final {
STATIC_ONLY(V8ScriptRunner);
public:
- enum class OpaqueMode {
- kOpaque,
- kNotOpaque,
- };
-
- enum class ProduceCacheOptions {
- kNoProduceCache,
- kSetTimeStamp,
- kProduceCodeCache,
- };
-
// For the following methods, the caller sites have to hold
// a HandleScope and a ContextScope.
- // SingleCachedMetadataHandler is set when metadata caching is supported.
static v8::MaybeLocal<v8::Script> CompileScript(
ScriptState*,
const ScriptSourceCode&,
@@ -81,7 +60,7 @@ class CORE_EXPORT V8ScriptRunner final {
const String& source,
const String& file_name,
AccessControlStatus,
- const TextPosition&,
+ const WTF::TextPosition&,
const ReferrerScriptInfo&);
static v8::MaybeLocal<v8::Value> RunCompiledScript(v8::Isolate*,
v8::Local<v8::Script>,
@@ -112,30 +91,13 @@ class CORE_EXPORT V8ScriptRunner final {
v8::Local<v8::Module>,
v8::Local<v8::Context>);
- static std::tuple<v8::ScriptCompiler::CompileOptions,
- ProduceCacheOptions,
- v8::ScriptCompiler::NoCacheReason>
- GetCompileOptions(V8CacheOptions, const ScriptSourceCode&);
-
- static void ProduceCache(v8::Isolate*,
- v8::Local<v8::Script>,
- const ScriptSourceCode&,
- ProduceCacheOptions,
- v8::ScriptCompiler::CompileOptions);
-
// Only to be used from ScriptModule::ReportException().
static void ReportExceptionForModule(v8::Isolate*,
v8::Local<v8::Value> exception,
const String& file_name,
- const TextPosition&);
-
- static uint32_t TagForParserCache(SingleCachedMetadataHandler*);
- static uint32_t TagForCodeCache(SingleCachedMetadataHandler*);
- static uint32_t TagForTimeStamp(SingleCachedMetadataHandler*);
- static void SetCacheTimeStamp(SingleCachedMetadataHandler*);
-
- // Utilities for calling functions added to the V8 extras binding object.
+ const WTF::TextPosition&);
+ // Calls a function on the V8 extras binding object.
template <size_t N>
static v8::MaybeLocal<v8::Value> CallExtra(ScriptState* script_state,
const char* name,
@@ -143,14 +105,6 @@ class CORE_EXPORT V8ScriptRunner final {
return CallExtraHelper(script_state, name, N, args);
}
- template <size_t N>
- static v8::Local<v8::Value> CallExtraOrCrash(
- ScriptState* script_state,
- const char* name,
- v8::Local<v8::Value> (&args)[N]) {
- return CallExtraHelper(script_state, name, N, args).ToLocalChecked();
- }
-
// Reports an exception to the message handler, as if it were an uncaught
// exception. Can only be called on the main thread.
//
@@ -158,13 +112,6 @@ class CORE_EXPORT V8ScriptRunner final {
// V8Initializer and so can't trivially move to platform/bindings.
static void ReportException(v8::Isolate*, v8::Local<v8::Value> exception);
- static scoped_refptr<CachedMetadata> GenerateFullCodeCache(
- ScriptState*,
- const String& script_string,
- const String& file_name,
- const WTF::TextEncoding&,
- OpaqueMode);
-
private:
static v8::MaybeLocal<v8::Value> CallExtraHelper(ScriptState*,
const char* name,
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner_test.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner_test.cc
index b322be63f56..8e87ed69554 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_script_runner_test.cc
@@ -9,6 +9,7 @@
#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/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_code_cache.h"
#include "third_party/blink/renderer/core/loader/resource/script_resource.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
@@ -43,13 +44,13 @@ class V8ScriptRunnerTest : public testing::Test {
return KURL(WTF::String::Format("http://bla.com/bla%d", counter_));
}
unsigned TagForCodeCache(SingleCachedMetadataHandler* cache_handler) const {
- return V8ScriptRunner::TagForCodeCache(cache_handler);
+ return V8CodeCache::TagForCodeCache(cache_handler);
}
unsigned TagForTimeStamp(SingleCachedMetadataHandler* cache_handler) const {
- return V8ScriptRunner::TagForTimeStamp(cache_handler);
+ return V8CodeCache::TagForTimeStamp(cache_handler);
}
void SetCacheTimeStamp(SingleCachedMetadataHandler* cache_handler) {
- V8ScriptRunner::SetCacheTimeStamp(cache_handler);
+ V8CodeCache::SetCacheTimeStamp(cache_handler);
}
bool CompileScript(v8::Isolate* isolate,
@@ -57,38 +58,37 @@ class V8ScriptRunnerTest : public testing::Test {
const ScriptSourceCode& source_code,
V8CacheOptions cache_options) {
v8::ScriptCompiler::CompileOptions compile_options;
- V8ScriptRunner::ProduceCacheOptions produce_cache_options;
+ V8CodeCache::ProduceCacheOptions produce_cache_options;
v8::ScriptCompiler::NoCacheReason no_cache_reason;
std::tie(compile_options, produce_cache_options, no_cache_reason) =
- V8ScriptRunner::GetCompileOptions(cache_options, source_code);
+ V8CodeCache::GetCompileOptions(cache_options, source_code);
v8::MaybeLocal<v8::Script> compiled_script = V8ScriptRunner::CompileScript(
script_state, source_code, kNotSharableCrossOrigin, compile_options,
no_cache_reason, ReferrerScriptInfo());
if (compiled_script.IsEmpty()) {
return false;
}
- V8ScriptRunner::ProduceCache(isolate, compiled_script.ToLocalChecked(),
- source_code, produce_cache_options,
- compile_options);
+ V8CodeCache::ProduceCache(isolate, compiled_script.ToLocalChecked(),
+ source_code, produce_cache_options,
+ compile_options);
return true;
}
- bool CompileScript(
- v8::Isolate* isolate,
- ScriptState* script_state,
- const ScriptSourceCode& source_code,
- v8::ScriptCompiler::CompileOptions compile_options,
- v8::ScriptCompiler::NoCacheReason no_cache_reason,
- V8ScriptRunner::ProduceCacheOptions produce_cache_options) {
+ bool CompileScript(v8::Isolate* isolate,
+ ScriptState* script_state,
+ const ScriptSourceCode& source_code,
+ v8::ScriptCompiler::CompileOptions compile_options,
+ v8::ScriptCompiler::NoCacheReason no_cache_reason,
+ V8CodeCache::ProduceCacheOptions produce_cache_options) {
v8::MaybeLocal<v8::Script> compiled_script = V8ScriptRunner::CompileScript(
script_state, source_code, kNotSharableCrossOrigin, compile_options,
no_cache_reason, ReferrerScriptInfo());
if (compiled_script.IsEmpty()) {
return false;
}
- V8ScriptRunner::ProduceCache(isolate, compiled_script.ToLocalChecked(),
- source_code, produce_cache_options,
- compile_options);
+ V8CodeCache::ProduceCache(isolate, compiled_script.ToLocalChecked(),
+ source_code, produce_cache_options,
+ compile_options);
return true;
}
@@ -161,12 +161,12 @@ TEST_F(V8ScriptRunnerTest, consumeCodeOption) {
// Hot run - should consume code cache.
v8::ScriptCompiler::CompileOptions compile_options;
- V8ScriptRunner::ProduceCacheOptions produce_cache_options;
+ V8CodeCache::ProduceCacheOptions produce_cache_options;
v8::ScriptCompiler::NoCacheReason no_cache_reason;
std::tie(compile_options, produce_cache_options, no_cache_reason) =
- V8ScriptRunner::GetCompileOptions(kV8CacheOptionsDefault, source_code);
+ V8CodeCache::GetCompileOptions(kV8CacheOptionsDefault, source_code);
EXPECT_EQ(produce_cache_options,
- V8ScriptRunner::ProduceCacheOptions::kNoProduceCache);
+ V8CodeCache::ProduceCacheOptions::kNoProduceCache);
EXPECT_EQ(compile_options,
v8::ScriptCompiler::CompileOptions::kConsumeCodeCache);
EXPECT_TRUE(CompileScript(scope.GetIsolate(), scope.GetScriptState(),
@@ -194,12 +194,12 @@ TEST_F(V8ScriptRunnerTest, produceAndConsumeCodeOption) {
// Hot run - should consume code cache
v8::ScriptCompiler::CompileOptions compile_options;
- V8ScriptRunner::ProduceCacheOptions produce_cache_options;
+ V8CodeCache::ProduceCacheOptions produce_cache_options;
v8::ScriptCompiler::NoCacheReason no_cache_reason;
std::tie(compile_options, produce_cache_options, no_cache_reason) =
- V8ScriptRunner::GetCompileOptions(kV8CacheOptionsDefault, source_code);
+ V8CodeCache::GetCompileOptions(kV8CacheOptionsDefault, source_code);
EXPECT_EQ(produce_cache_options,
- V8ScriptRunner::ProduceCacheOptions::kNoProduceCache);
+ V8CodeCache::ProduceCacheOptions::kNoProduceCache);
EXPECT_EQ(compile_options,
v8::ScriptCompiler::CompileOptions::kConsumeCodeCache);
EXPECT_TRUE(CompileScript(scope.GetIsolate(), scope.GetScriptState(),
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_string_resource.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_string_resource.h
index 729474df91c..e1e56690a01 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_string_resource.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_string_resource.h
@@ -26,7 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_STRING_RESOURCE_H_
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_STRING_RESOURCE_H_
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/string_resource.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -97,7 +97,7 @@ class V8StringResource {
return true;
if (LIKELY(v8_object_->IsInt32())) {
- SetString(Int32ToWebCoreString(v8_object_.As<v8::Int32>()->Value()));
+ SetString(ToBlinkString(v8_object_.As<v8::Int32>()->Value()));
return true;
}
@@ -126,7 +126,7 @@ class V8StringResource {
template <class StringType>
StringType ToString() const {
if (LIKELY(!v8_object_.IsEmpty()))
- return V8StringToWebCoreString<StringType>(
+ return ToBlinkString<StringType>(
const_cast<v8::Local<v8::Value>*>(&v8_object_)->As<v8::String>(),
mode_);
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.cc
index bd83aa2f82e..96a5d4c1b0a 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.cc
@@ -6,11 +6,18 @@
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
namespace blink {
+// static
+void V8ThrowDOMException::Init() {
+ ExceptionState::SetCreateDOMExceptionFunction(
+ V8ThrowDOMException::CreateOrEmpty);
+}
+
namespace {
void DomExceptionStackGetter(v8::Local<v8::Name> name,
@@ -35,30 +42,18 @@ void DomExceptionStackSetter(v8::Local<v8::Name> name,
} // namespace
-v8::Local<v8::Value> V8ThrowDOMException::CreateDOMException(
+v8::Local<v8::Value> V8ThrowDOMException::CreateOrEmpty(
v8::Isolate* isolate,
- ExceptionCode exception_code,
+ DOMExceptionCode exception_code,
const String& sanitized_message,
const String& unsanitized_message) {
- DCHECK_GT(exception_code, 0);
- DCHECK(exception_code == kSecurityError || unsanitized_message.IsNull());
+ DCHECK(IsDOMExceptionCode(ToExceptionCode(exception_code)));
+ DCHECK(exception_code == DOMExceptionCode::kSecurityError ||
+ unsanitized_message.IsNull());
if (isolate->IsExecutionTerminating())
return v8::Local<v8::Value>();
- switch (exception_code) {
- case kV8Error:
- return V8ThrowException::CreateError(isolate, sanitized_message);
- case kV8TypeError:
- return V8ThrowException::CreateTypeError(isolate, sanitized_message);
- case kV8RangeError:
- return V8ThrowException::CreateRangeError(isolate, sanitized_message);
- case kV8SyntaxError:
- return V8ThrowException::CreateSyntaxError(isolate, sanitized_message);
- case kV8ReferenceError:
- return V8ThrowException::CreateReferenceError(isolate, sanitized_message);
- }
-
DOMException* dom_exception = DOMException::Create(
exception_code, sanitized_message, unsanitized_message);
v8::Local<v8::Object> exception_obj =
@@ -80,15 +75,4 @@ v8::Local<v8::Value> V8ThrowDOMException::CreateDOMException(
return exception_obj;
}
-void V8ThrowDOMException::ThrowDOMException(v8::Isolate* isolate,
- ExceptionCode exception_code,
- const String& sanitized_message,
- const String& unsanitized_message) {
- v8::Local<v8::Value> dom_exception = CreateDOMException(
- isolate, exception_code, sanitized_message, unsanitized_message);
- if (dom_exception.IsEmpty())
- return;
- V8ThrowException::ThrowException(isolate, dom_exception);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h
index 19590706a15..45694c47031 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_THROW_DOM_EXCEPTION_H_
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_code.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "v8/include/v8.h"
@@ -18,22 +18,19 @@ class CORE_EXPORT V8ThrowDOMException {
STATIC_ONLY(V8ThrowDOMException);
public:
- // Creates and returns an exception object, or returns an empty handle if
- // failed. |unsanitizedMessage| should not be specified unless it's
- // SecurityError.
- static v8::Local<v8::Value> CreateDOMException(
+ // Per-process initializer. Must be called in CoreInitializer.
+ static void Init();
+
+ // Creates and returns a DOMException object, or returns an empty handle if
+ // the isolate is being terminated. Unlike DOMException::Create, this function
+ // associates the stacktrace with the returned object.
+ //
+ // |unsanitized_message| should be specified iff SecurityError.
+ static v8::Local<v8::Value> CreateOrEmpty(
v8::Isolate*,
- ExceptionCode,
+ DOMExceptionCode,
const String& sanitized_message,
const String& unsanitized_message = String());
-
- // Creates and throws an exception object, or does nothing if creation of the
- // DOMException fails. |unsanitizedMessage| should not be specified unless
- // it's SecurityError.
- static void ThrowDOMException(v8::Isolate*,
- ExceptionCode,
- const String& sanitized_message,
- const String& unsanitized_message = String());
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.cc
index 19329b1f284..aaff56e8050 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.cc
@@ -157,7 +157,7 @@ void V8V0CustomElementLifecycleCallbacks::Created(Element* element) {
element->SetV0CustomElementState(Element::kV0Upgraded);
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
v8::Isolate* isolate = script_state_->GetIsolate();
v8::Local<v8::Context> context = script_state_->GetContext();
v8::Local<v8::Value> receiver_value =
@@ -179,8 +179,7 @@ void V8V0CustomElementLifecycleCallbacks::Created(Element* element) {
v8::TryCatch exception_catcher(isolate);
exception_catcher.SetVerbose(true);
- V8ScriptRunner::CallFunction(callback,
- ExecutionContext::From(script_state_.get()),
+ V8ScriptRunner::CallFunction(callback, ExecutionContext::From(script_state_),
receiver, 0, nullptr, isolate);
}
@@ -202,7 +201,7 @@ void V8V0CustomElementLifecycleCallbacks::AttributeChanged(
// Bug 329665 tracks similar behavior for other synchronous events.
if (!script_state_->ContextIsValid())
return;
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
v8::Isolate* isolate = script_state_->GetIsolate();
v8::Local<v8::Context> context = script_state_->GetContext();
v8::Local<v8::Value> receiver = ToV8(element, context->Global(), isolate);
@@ -222,9 +221,8 @@ void V8V0CustomElementLifecycleCallbacks::AttributeChanged(
v8::TryCatch exception_catcher(isolate);
exception_catcher.SetVerbose(true);
- V8ScriptRunner::CallFunction(callback,
- ExecutionContext::From(script_state_.get()),
- receiver, arraysize(argv), argv, isolate);
+ V8ScriptRunner::CallFunction(callback, ExecutionContext::From(script_state_),
+ receiver, base::size(argv), argv, isolate);
}
void V8V0CustomElementLifecycleCallbacks::Call(
@@ -235,7 +233,7 @@ void V8V0CustomElementLifecycleCallbacks::Call(
// Bug 329665 tracks similar behavior for other synchronous events.
if (!script_state_->ContextIsValid())
return;
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
v8::Isolate* isolate = script_state_->GetIsolate();
v8::Local<v8::Context> context = script_state_->GetContext();
v8::Local<v8::Function> callback = weak_callback.NewLocal(isolate);
@@ -248,12 +246,12 @@ void V8V0CustomElementLifecycleCallbacks::Call(
v8::TryCatch exception_catcher(isolate);
exception_catcher.SetVerbose(true);
- V8ScriptRunner::CallFunction(callback,
- ExecutionContext::From(script_state_.get()),
+ V8ScriptRunner::CallFunction(callback, ExecutionContext::From(script_state_),
receiver, 0, nullptr, isolate);
}
void V8V0CustomElementLifecycleCallbacks::Trace(blink::Visitor* visitor) {
+ visitor->Trace(script_state_);
V0CustomElementLifecycleCallbacks::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.h b/chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.h
index 3ffb391ec58..3abeeb37b6c 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_v0_custom_element_lifecycle_callbacks.h
@@ -41,6 +41,7 @@
namespace blink {
+class V0CustomElementBinding;
class V0CustomElementLifecycleCallbacks;
class Element;
class V8PerContextData;
@@ -83,7 +84,7 @@ class V8V0CustomElementLifecycleCallbacks final
V8PerContextData* CreationContextData();
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
ScopedPersistent<v8::Object> prototype_;
ScopedPersistent<v8::Function> created_;
ScopedPersistent<v8::Function> attached_;
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
index 454b5acf874..26154edc309 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.cc
@@ -5,13 +5,13 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_wasm_response_extensions.h"
#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_response.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
#include "third_party/blink/renderer/core/fetch/fetch_data_loader.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/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -25,7 +25,7 @@ class FetchDataLoaderAsWasmModule final : public FetchDataLoader,
USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsWasmModule);
public:
- FetchDataLoaderAsWasmModule(ScriptState* script_state)
+ explicit FetchDataLoaderAsWasmModule(ScriptState* script_state)
: builder_(script_state->GetIsolate()), script_state_(script_state) {}
void Start(BytesConsumer* consumer,
@@ -65,7 +65,7 @@ class FetchDataLoaderAsWasmModule final : public FetchDataLoader,
break;
}
case BytesConsumer::Result::kDone: {
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
builder_.Finish();
client_->DidFetchDataLoadedCustomFormat();
return;
@@ -87,6 +87,7 @@ class FetchDataLoaderAsWasmModule final : public FetchDataLoader,
void Trace(blink::Visitor* visitor) override {
visitor->Trace(consumer_);
visitor->Trace(client_);
+ visitor->Trace(script_state_);
FetchDataLoader::Trace(visitor);
BytesConsumer::Client::Trace(visitor);
}
@@ -95,8 +96,8 @@ class FetchDataLoaderAsWasmModule final : public FetchDataLoader,
// TODO(mtrofin): replace with spec-ed error types, once spec clarifies
// what they are.
void AbortCompilation() {
- ScriptState::Scope scope(script_state_.get());
- if (!ExecutionContext::From(script_state_.get())->IsContextDestroyed()) {
+ ScriptState::Scope scope(script_state_);
+ if (!ExecutionContext::From(script_state_)->IsContextDestroyed()) {
builder_.Abort(V8ThrowException::CreateTypeError(
script_state_->GetIsolate(), "Could not download wasm module"));
} else {
@@ -110,7 +111,7 @@ class FetchDataLoaderAsWasmModule final : public FetchDataLoader,
Member<BytesConsumer> consumer_;
Member<FetchDataLoader::Client> client_;
v8::WasmModuleObjectBuilderStreaming builder_;
- const scoped_refptr<ScriptState> script_state_;
+ const Member<ScriptState> script_state_;
};
// TODO(mtrofin): WasmDataLoaderClient is necessary so we may provide an
@@ -123,7 +124,7 @@ class WasmDataLoaderClient final
USING_GARBAGE_COLLECTED_MIXIN(WasmDataLoaderClient);
public:
- explicit WasmDataLoaderClient() = default;
+ WasmDataLoaderClient() = default;
void DidFetchDataLoadedCustomFormat() override {}
void DidFetchDataLoadFailed() override { NOTREACHED(); }
void Abort() override {
@@ -171,11 +172,15 @@ void CompileFromResponseCallback(
return;
}
- if (response->IsBodyLocked() || response->bodyUsed()) {
+ if (response->IsBodyLocked(exception_state) == Body::BodyLocked::kLocked ||
+ response->IsBodyUsed(exception_state) == Body::BodyUsed::kUsed) {
+ DCHECK(!exception_state.HadException());
exception_state.ThrowTypeError(
"Cannot compile WebAssembly.Module from an already read Response");
return;
}
+ if (exception_state.HadException())
+ return;
if (!response->BodyBuffer()) {
exception_state.ThrowTypeError("Response object has a null body.");
@@ -185,7 +190,10 @@ void CompileFromResponseCallback(
FetchDataLoaderAsWasmModule* loader =
new FetchDataLoaderAsWasmModule(script_state);
v8::Local<v8::Value> promise = loader->GetPromise();
- response->BodyBuffer()->StartLoading(loader, new WasmDataLoaderClient());
+ response->BodyBuffer()->StartLoading(loader, new WasmDataLoaderClient(),
+ exception_state);
+ if (exception_state.HadException())
+ return;
V8SetReturnValue(args, promise);
}
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/v8_worker_or_worklet_event_listener.cc b/chromium/third_party/blink/renderer/bindings/core/v8/v8_worker_or_worklet_event_listener.cc
index 049ce295e36..73bf9c6ddbe 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/v8_worker_or_worklet_event_listener.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/v8_worker_or_worklet_event_listener.cc
@@ -82,7 +82,7 @@ v8::Local<v8::Value> V8WorkerOrWorkletEventListener::CallListenerFunction(
v8::Local<v8::Value> parameters[1] = {js_event};
v8::MaybeLocal<v8::Value> maybe_result = V8ScriptRunner::CallFunction(
handler_function, ToExecutionContext(script_state->GetContext()),
- receiver, arraysize(parameters), parameters, GetIsolate());
+ receiver, base::size(parameters), parameters, GetIsolate());
v8::Local<v8::Value> result;
if (!maybe_result.ToLocal(&result))
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/window_proxy.h b/chromium/third_party/blink/renderer/bindings/core/v8/window_proxy.h
index 04403ed3abc..c2f135f7fad 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/window_proxy.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/window_proxy.h
@@ -43,6 +43,7 @@ namespace blink {
class DOMWindow;
class Frame;
+struct WrapperTypeInfo;
// WindowProxy implements the split window model of a window for a frame. In the
// HTML standard, the split window model is composed of the Window interface
@@ -145,7 +146,7 @@ class WindowProxy : public GarbageCollectedFinalized<WindowProxy> {
public:
virtual ~WindowProxy();
- void Trace(blink::Visitor*);
+ virtual void Trace(blink::Visitor*);
void InitializeIfNeeded();
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc b/chromium/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc
index 5c24d6acd74..6a5c351eaf0 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc
@@ -34,10 +34,12 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/initialize_v8_extras_binding.h"
+#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.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/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_code_cache.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_error_handler.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_initializer.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
@@ -129,12 +131,14 @@ void WorkerOrWorkletScriptController::DisposeContextIfNeeded() {
if (global_scope_->IsWorkerGlobalScope() ||
global_scope_->IsThreadedWorkletGlobalScope()) {
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
WorkerThreadDebugger* debugger = WorkerThreadDebugger::From(isolate_);
debugger->ContextWillBeDestroyed(global_scope_->GetThread(),
script_state_->GetContext());
}
+
script_state_->DisposePerContextData();
+ script_state_->DissociateContext();
}
bool WorkerOrWorkletScriptController::InitializeContextIfNeeded(
@@ -180,9 +184,9 @@ bool WorkerOrWorkletScriptController::InitializeContextIfNeeded(
script_state_ = ScriptState::Create(context, world_);
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
- InitializeV8ExtrasBinding(script_state_.get());
+ InitializeV8ExtrasBinding(script_state_);
// Associate the global proxy object, the global object and the worker
// instance (C++ object) as follows.
@@ -264,7 +268,7 @@ ScriptValue WorkerOrWorkletScriptController::EvaluateInternal(
if (!InitializeContextIfNeeded(String()))
return ScriptValue();
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
v8::TryCatch block(isolate_);
@@ -275,18 +279,18 @@ ScriptValue WorkerOrWorkletScriptController::EvaluateInternal(
// - a work{er,let} script is always "not parser inserted".
ReferrerScriptInfo referrer_info;
v8::ScriptCompiler::CompileOptions compile_options;
- V8ScriptRunner::ProduceCacheOptions produce_cache_options;
+ V8CodeCache::ProduceCacheOptions produce_cache_options;
v8::ScriptCompiler::NoCacheReason no_cache_reason;
std::tie(compile_options, produce_cache_options, no_cache_reason) =
- V8ScriptRunner::GetCompileOptions(v8_cache_options, source_code);
- if (V8ScriptRunner::CompileScript(script_state_.get(), source_code,
+ V8CodeCache::GetCompileOptions(v8_cache_options, source_code);
+ if (V8ScriptRunner::CompileScript(script_state_, source_code,
kSharableCrossOrigin, compile_options,
no_cache_reason, referrer_info)
.ToLocal(&compiled_script)) {
maybe_result = V8ScriptRunner::RunCompiledScript(isolate_, compiled_script,
global_scope_);
- V8ScriptRunner::ProduceCache(isolate_, compiled_script, source_code,
- produce_cache_options, compile_options);
+ V8CodeCache::ProduceCache(isolate_, compiled_script, source_code,
+ produce_cache_options, compile_options);
}
if (!block.CanContinue()) {
@@ -299,9 +303,8 @@ ScriptValue WorkerOrWorkletScriptController::EvaluateInternal(
execution_state_->had_exception = true;
execution_state_->error_message = ToCoreString(message->Get());
execution_state_->location_ = SourceLocation::FromMessage(
- isolate_, message, ExecutionContext::From(script_state_.get()));
- execution_state_->exception =
- ScriptValue(script_state_.get(), block.Exception());
+ isolate_, message, ExecutionContext::From(script_state_));
+ execution_state_->exception = ScriptValue(script_state_, block.Exception());
block.Reset();
} else {
execution_state_->had_exception = false;
@@ -311,7 +314,7 @@ ScriptValue WorkerOrWorkletScriptController::EvaluateInternal(
if (!maybe_result.ToLocal(&result) || result->IsUndefined())
return ScriptValue();
- return ScriptValue(script_state_.get(), result);
+ return ScriptValue(script_state_, result);
}
bool WorkerOrWorkletScriptController::Evaluate(
@@ -326,7 +329,7 @@ bool WorkerOrWorkletScriptController::Evaluate(
if (IsExecutionForbidden())
return false;
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
if (state.had_exception) {
if (error_event) {
if (state.error_event_from_imported_script_) {
@@ -343,7 +346,7 @@ bool WorkerOrWorkletScriptController::Evaluate(
state.exception, world_.get());
}
V8ErrorHandler::StoreExceptionOnErrorEventWrapper(
- script_state_.get(), *error_event, state.exception.V8Value(),
+ script_state_, *error_event, state.exception.V8Value(),
script_state_->GetContext()->Global());
} else {
DCHECK(!global_scope_->ShouldSanitizeScriptError(
@@ -395,6 +398,7 @@ void WorkerOrWorkletScriptController::RethrowExceptionFromImportedScript(
void WorkerOrWorkletScriptController::Trace(blink::Visitor* visitor) {
visitor->Trace(global_scope_);
+ visitor->Trace(script_state_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h b/chromium/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h
index b53f97927ae..354f96a80a7 100644
--- a/chromium/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h
+++ b/chromium/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h
@@ -47,7 +47,7 @@ class ExceptionState;
class ScriptSourceCode;
class WorkerOrWorkletGlobalScope;
-class CORE_EXPORT WorkerOrWorkletScriptController
+class CORE_EXPORT WorkerOrWorkletScriptController final
: public GarbageCollectedFinalized<WorkerOrWorkletScriptController> {
WTF_MAKE_NONCOPYABLE(WorkerOrWorkletScriptController);
@@ -76,7 +76,7 @@ class CORE_EXPORT WorkerOrWorkletScriptController
void DisableEval(const String&);
// Used by Inspector agents:
- ScriptState* GetScriptState() { return script_state_.get(); }
+ ScriptState* GetScriptState() { return script_state_; }
// Used by V8 bindings:
v8::Local<v8::Context> GetContext() {
@@ -112,7 +112,7 @@ class CORE_EXPORT WorkerOrWorkletScriptController
// usually the main thread's isolate is used.
v8::Isolate* isolate_;
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
scoped_refptr<DOMWrapperWorld> world_;
String disable_eval_pending_;
bool execution_forbidden_;
diff --git a/chromium/third_party/blink/renderer/bindings/modules/BUILD.gn b/chromium/third_party/blink/renderer/bindings/modules/BUILD.gn
index d851317044d..1fe835bcdd0 100644
--- a/chromium/third_party/blink/renderer/bindings/modules/BUILD.gn
+++ b/chromium/third_party/blink/renderer/bindings/modules/BUILD.gn
@@ -47,10 +47,10 @@ generate_event_interfaces("modules_bindings_generated_event_interfaces") {
"//third_party/blink/renderer/modules/presentation/presentation_connection_close_event.idl",
"//third_party/blink/renderer/modules/push_messaging/push_event.idl",
"//third_party/blink/renderer/modules/sensor/sensor_error_event.idl",
- "//third_party/blink/renderer/modules/serviceworkers/extendable_event.idl",
- "//third_party/blink/renderer/modules/serviceworkers/extendable_message_event.idl",
- "//third_party/blink/renderer/modules/serviceworkers/fetch_event.idl",
- "//third_party/blink/renderer/modules/serviceworkers/install_event.idl",
+ "//third_party/blink/renderer/modules/service_worker/extendable_event.idl",
+ "//third_party/blink/renderer/modules/service_worker/extendable_message_event.idl",
+ "//third_party/blink/renderer/modules/service_worker/fetch_event.idl",
+ "//third_party/blink/renderer/modules/service_worker/install_event.idl",
"//third_party/blink/renderer/modules/speech/speech_recognition_error.idl",
"//third_party/blink/renderer/modules/speech/speech_recognition_event.idl",
"//third_party/blink/renderer/modules/speech/speech_synthesis_event.idl",
diff --git a/chromium/third_party/blink/renderer/bindings/modules/v8/custom/v8_extendable_message_event_custom.cc b/chromium/third_party/blink/renderer/bindings/modules/v8/custom/v8_extendable_message_event_custom.cc
index 27bc557bf2a..3f85f75499d 100644
--- a/chromium/third_party/blink/renderer/bindings/modules/v8/custom/v8_extendable_message_event_custom.cc
+++ b/chromium/third_party/blink/renderer/bindings/modules/v8/custom/v8_extendable_message_event_custom.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_extendable_message_event.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_extendable_message_event_init.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/bindings/modules/v8/generated.gni b/chromium/third_party/blink/renderer/bindings/modules/v8/generated.gni
index 271c55ae217..4f0ccb0740d 100644
--- a/chromium/third_party/blink/renderer/bindings/modules/v8/generated.gni
+++ b/chromium/third_party/blink/renderer/bindings/modules/v8/generated.gni
@@ -50,6 +50,8 @@ bindings_modules_generated_union_type_files = [
"$bindings_modules_v8_output_dir/idb_object_store_or_idb_index_or_idb_cursor.h",
"$bindings_modules_v8_output_dir/long_or_constrain_long_range.cc",
"$bindings_modules_v8_output_dir/long_or_constrain_long_range.h",
+ "$bindings_modules_v8_output_dir/media_stream_track_or_string.cc",
+ "$bindings_modules_v8_output_dir/media_stream_track_or_string.h",
"$bindings_modules_v8_output_dir/offscreen_rendering_context.cc",
"$bindings_modules_v8_output_dir/offscreen_rendering_context.h",
"$bindings_modules_v8_output_dir/password_credential_data_or_html_form_element.cc",
diff --git a/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h b/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h
index e6fa62bc37f..a120c0857a7 100644
--- a/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h
+++ b/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.h
@@ -20,17 +20,15 @@ class MODULES_EXPORT V8ScriptValueDeserializerForModules final
// using V8ScriptValueDeserializer::V8ScriptValueDeserializer;
// Unfortunately, MSVC 2015 emits C2248, claiming that it cannot access its
// own private members. Until it's gone, we write the constructors by hand.
- V8ScriptValueDeserializerForModules(scoped_refptr<ScriptState> script_state,
+ V8ScriptValueDeserializerForModules(ScriptState* script_state,
UnpackedSerializedScriptValue* unpacked,
const Options& options = Options())
: V8ScriptValueDeserializer(std::move(script_state), unpacked, options) {}
V8ScriptValueDeserializerForModules(
- scoped_refptr<ScriptState> script_state,
+ ScriptState* script_state,
scoped_refptr<SerializedScriptValue> value,
const Options& options = Options())
- : V8ScriptValueDeserializer(std::move(script_state),
- std::move(value),
- options) {}
+ : V8ScriptValueDeserializer(script_state, std::move(value), options) {}
protected:
ScriptWrappable* ReadDOMObject(SerializationTag) override;
diff --git a/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc b/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc
index 4808af66489..bb02b02bd42 100644
--- a/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc
+++ b/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.cc
@@ -36,7 +36,8 @@ bool V8ScriptValueSerializerForModules::WriteDOMObject(
DOMFileSystem* fs = wrappable->ToImpl<DOMFileSystem>();
if (!fs->Clonable()) {
exception_state.ThrowDOMException(
- kDataCloneError, "A FileSystem object could not be cloned.");
+ DOMExceptionCode::kDataCloneError,
+ "A FileSystem object could not be cloned.");
return false;
}
WriteTag(kDOMFileSystemTag);
@@ -212,7 +213,8 @@ bool V8ScriptValueSerializerForModules::WriteCryptoKey(
if (!Platform::Current()->Crypto()->SerializeKeyForClone(key, key_data) ||
key_data.size() > std::numeric_limits<uint32_t>::max()) {
exception_state.ThrowDOMException(
- kDataCloneError, "A CryptoKey object could not be cloned.");
+ DOMExceptionCode::kDataCloneError,
+ "A CryptoKey object could not be cloned.");
return false;
}
WriteUint32(key_data.size());
diff --git a/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.h b/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.h
index f8175736343..6f942e05a20 100644
--- a/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.h
+++ b/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules.h
@@ -18,7 +18,7 @@ class MODULES_EXPORT V8ScriptValueSerializerForModules final
: public V8ScriptValueSerializer {
public:
explicit V8ScriptValueSerializerForModules(
- scoped_refptr<ScriptState> script_state,
+ ScriptState* script_state,
const SerializedScriptValue::SerializeOptions& options)
: V8ScriptValueSerializer(script_state, options) {}
diff --git a/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc b/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc
index cb8bd3593ca..4b4948abbbf 100644
--- a/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc
+++ b/chromium/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc
@@ -11,7 +11,8 @@
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
#include "third_party/blink/public/platform/web_rtc_certificate_generator.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
@@ -24,6 +25,7 @@
#include "third_party/blink/renderer/modules/crypto/crypto_result_impl.h"
#include "third_party/blink/renderer/modules/filesystem/dom_file_system.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_certificate.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
using testing::ElementsAre;
@@ -35,7 +37,7 @@ namespace {
v8::Local<v8::Value> RoundTripForModules(v8::Local<v8::Value> value,
V8TestingScope& scope) {
- scoped_refptr<ScriptState> script_state = scope.GetScriptState();
+ ScriptState* script_state = scope.GetScriptState();
ExceptionState& exception_state = scope.GetExceptionState();
scoped_refptr<SerializedScriptValue> serialized_script_value =
V8ScriptValueSerializerForModules(
@@ -864,6 +866,14 @@ TEST(V8ScriptValueSerializerForModulesTest, DecodeCryptoKeyInvalid) {
0x0d, 0x01, 0x80, 0x08, 0x03, 0x01}))
.Deserialize()
->IsNull());
+
+ // ECDH key with invalid key data.
+ EXPECT_TRUE(
+ V8ScriptValueDeserializerForModules(
+ script_state, SerializedValue({0xff, 0x09, 0x3f, 0x00, 0x4b, 0x05,
+ 0x0e, 0x01, 0x01, 0x4b, 0x00, 0x00}))
+ .Deserialize()
+ ->IsNull());
}
TEST(V8ScriptValueSerializerForModulesTest, RoundTripDOMFileSystem) {
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/generate_origin_trial_features.py b/chromium/third_party/blink/renderer/bindings/scripts/generate_origin_trial_features.py
index 537112ebd25..16b0f8d58d9 100755
--- a/chromium/third_party/blink/renderer/bindings/scripts/generate_origin_trial_features.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/generate_origin_trial_features.py
@@ -20,7 +20,7 @@ from idl_reader import IdlReader
from utilities import (create_component_info_provider, write_file,
idl_filename_to_component)
from v8_utilities import (binding_header_filename, v8_class_name,
- v8_class_name_or_partial, uncapitalize)
+ v8_class_name_or_partial)
# Make sure extension is .py, not .pyc or .pyo, so doesn't depend on caching
MODULE_PYNAME = os.path.splitext(os.path.basename(__file__))[0] + '.py'
@@ -39,7 +39,7 @@ def get_install_functions(interfaces, feature_names):
be installed on those interfaces.
"""
return [
- {'condition': 'OriginTrials::%sEnabled' % uncapitalize(feature_name),
+ {'condition': 'OriginTrials::%sEnabled' % feature_name,
'name': feature_name,
'install_method': 'install%s' % feature_name,
'interface_is_global': interface_info.is_global,
@@ -162,6 +162,7 @@ def origin_trial_features_context(generator_name, feature_info):
'core/origin_trials/origin_trials.h',
'platform/bindings/origin_trial_features.h',
'platform/bindings/script_state.h',
+ 'platform/bindings/v8_per_context_data.h',
# TODO(iclelland): Remove the need to explicitly include this; it is
# here because the ContextFeatureSettings code needs it.
'bindings/core/v8/v8_window.h',
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/utilities.py b/chromium/third_party/blink/renderer/bindings/scripts/utilities.py
index 97d3dba7467..127acfeaf0e 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/utilities.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/utilities.py
@@ -432,13 +432,19 @@ def shorten_union_name(union_type):
aliases = {
# modules/canvas2d/CanvasRenderingContext2D.idl
'CSSImageValueOrHTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrImageBitmapOrOffscreenCanvas': 'CanvasImageSource',
- # modules/canvas/HTMLCanvasElementModule.idl
+ # modules/canvas/htmlcanvas/html_canvas_element_module_support_webgl2_compute.idl
+ # Due to html_canvas_element_module_support_webgl2_compute.idl and html_canvas_element_module.idl are exclusive in modules_idl_files.gni, they have same shorten name.
+ 'CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContextOrImageBitmapRenderingContextOrXRPresentationContext': 'RenderingContext',
+ # modules/canvas/htmlcanvas/html_canvas_element_module.idl
'CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContextOrXRPresentationContext': 'RenderingContext',
# core/imagebitmap/ImageBitmapFactories.idl
'HTMLImageElementOrSVGImageElementOrHTMLVideoElementOrHTMLCanvasElementOrBlobOrImageDataOrImageBitmapOrOffscreenCanvas': 'ImageBitmapSource',
# bindings/tests/idls/core/TestTypedefs.idl
'NodeOrLongSequenceOrEventOrXMLHttpRequestOrStringOrStringByteStringOrNodeListRecord': 'NestedUnionType',
- # modules/offscreencanvas/OffscreenCanvasModules.idl
+ # modules/canvas/offscreencanvas/offscreen_canvas_module_support_webgl2_compute.idl.
+ # Due to offscreen_canvas_module_support_webgl2_compute.idl and offscreen_canvas_module.idl are exclusive in modules_idl_files.gni, they have same shorten name.
+ 'OffscreenCanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContext': 'OffscreenRenderingContext',
+ # modules/canvas/offscreencanvas/offscreen_canvas_module.idl
'OffscreenCanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContext': 'OffscreenRenderingContext',
}
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_attributes.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_attributes.py
index 0adfd61b2ce..082c09b1f2f 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_attributes.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_attributes.py
@@ -120,6 +120,10 @@ def attribute_context(interface, attribute, interfaces):
if is_cached_accessor:
includes.add('platform/bindings/v8_private_property.h')
+ # [LogActivity]
+ if 'LogActivity' in extended_attributes:
+ includes.add('platform/bindings/v8_per_context_data.h')
+
context = {
'activity_logging_world_list_for_getter': v8_utilities.activity_logging_world_list(attribute, 'Getter'), # [ActivityLogging]
'activity_logging_world_list_for_setter': v8_utilities.activity_logging_world_list(attribute, 'Setter'), # [ActivityLogging]
@@ -157,6 +161,7 @@ def attribute_context(interface, attribute, interfaces):
'RaisesException' in extended_attributes and
extended_attributes['RaisesException'] in (None, 'Getter'),
'is_keep_alive_for_gc': keep_alive_for_gc,
+ 'is_lenient_setter': 'LenientSetter' in extended_attributes,
'is_lenient_this': 'LenientThis' in extended_attributes,
'is_nullable': idl_type.is_nullable,
'is_explicit_nullable': idl_type.is_explicit_nullable,
@@ -549,8 +554,8 @@ def scoped_content_attribute_name(interface, attribute):
# Property descriptor's {writable: boolean}
def is_writable(attribute):
return (not attribute.is_read_only or
- 'PutForwards' in attribute.extended_attributes or
- 'Replaceable' in attribute.extended_attributes)
+ any(keyword in attribute.extended_attributes for keyword in [
+ 'PutForwards', 'Replaceable', 'LenientSetter']))
def is_data_type_property(interface, attribute):
@@ -560,7 +565,7 @@ def is_data_type_property(interface, attribute):
'CrossOrigin' in attribute.extended_attributes)
-# [PutForwards], [Replaceable]
+# [PutForwards], [Replaceable], [LenientSetter]
def has_setter(interface, attribute):
if (is_data_type_property(interface, attribute) and
(is_constructor_attribute(attribute) or
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_function.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_function.py
index 53b556f1281..8b9288b82b8 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_function.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_function.py
@@ -13,12 +13,14 @@ CALLBACK_FUNCTION_H_INCLUDES = frozenset([
'platform/bindings/callback_function_base.h',
])
CALLBACK_FUNCTION_CPP_INCLUDES = frozenset([
- 'bindings/core/v8/exception_state.h',
+ 'base/stl_util.h',
'bindings/core/v8/generated_code_helper.h',
'bindings/core/v8/native_value_traits_impl.h',
'bindings/core/v8/to_v8_for_core.h',
'bindings/core/v8/v8_binding_for_core.h',
'core/execution_context/execution_context.h',
+ 'platform/bindings/exception_messages.h',
+ 'platform/bindings/exception_state.h',
])
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_interface.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_interface.py
index 30c030dc500..d3d8728ce67 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_interface.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_callback_interface.py
@@ -46,9 +46,11 @@ CALLBACK_INTERFACE_CPP_INCLUDES = frozenset([
'bindings/core/v8/generated_code_helper.h',
'bindings/core/v8/v8_binding_for_core.h',
'core/execution_context/execution_context.h',
+ 'platform/bindings/exception_messages.h',
])
LEGACY_CALLBACK_INTERFACE_H_INCLUDES = frozenset([
'platform/bindings/dom_wrapper_world.h',
+ 'platform/bindings/wrapper_type_info.h',
])
LEGACY_CALLBACK_INTERFACE_CPP_INCLUDES = frozenset([
'bindings/core/v8/v8_dom_configuration.h',
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_dictionary.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_dictionary.py
index 3f3f67fadf0..88c4d22d1b5 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_dictionary.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_dictionary.py
@@ -23,7 +23,8 @@ DICTIONARY_H_INCLUDES = frozenset([
])
DICTIONARY_CPP_INCLUDES = frozenset([
- 'bindings/core/v8/exception_state.h',
+ 'base/stl_util.h',
+ 'platform/bindings/exception_state.h',
])
@@ -115,6 +116,14 @@ def member_context(dictionary, member):
raise Exception(
'Required member %s must not have a default value.' % member.name)
+ # In most cases, we don't have to distinguish `null` and `not present`,
+ # and use null-states (e.g. nullptr, foo.IsUndefinedOrNull()) to show such
+ # states for some types for memory usage and performance.
+ # For types whose |has_explicit_presence| is True, we provide explicit
+ # states of presence.
+ has_explicit_presence = (
+ idl_type.is_nullable and idl_type.inner_type.is_interface_type)
+
def default_values():
if not member.default_value:
return None, None
@@ -144,6 +153,7 @@ def member_context(dictionary, member):
'enum_type': idl_type.enum_type,
'enum_values': idl_type.enum_values,
'getter_name': getter_name,
+ 'has_explicit_presence': has_explicit_presence,
'has_method_name': has_method_name_for_dictionary_member(member),
'idl_type': idl_type.base_type,
'is_interface_type': idl_type.is_interface_type and not is_deprecated_dictionary,
@@ -211,8 +221,16 @@ def member_impl_context(member, interfaces_info, header_includes,
idl_type = unwrap_nullable_if_needed(member.idl_type)
cpp_name = to_snake_case(v8_utilities.cpp_name(member))
+ # In most cases, we don't have to distinguish `null` and `not present`,
+ # and use null-states (e.g. nullptr, foo.IsUndefinedOrNull()) to show such
+ # states for some types for memory usage and performance.
+ # For types whose |has_explicit_presence| is True, we provide explicit
+ # states of presence.
+ has_explicit_presence = (
+ member.idl_type.is_nullable and member.idl_type.inner_type.is_interface_type)
+
nullable_indicator_name = None
- if not idl_type.cpp_type_has_null_value:
+ if not idl_type.cpp_type_has_null_value or has_explicit_presence:
nullable_indicator_name = 'has_' + cpp_name + '_'
def has_method_expression():
@@ -229,8 +247,9 @@ def member_impl_context(member, interfaces_info, header_includes,
return '%s_' % cpp_name
cpp_default_value = None
- if member.default_value and not member.default_value.is_null:
- cpp_default_value = idl_type.literal_cpp_value(member.default_value)
+ if member.default_value:
+ if not member.default_value.is_null or has_explicit_presence:
+ cpp_default_value = idl_type.literal_cpp_value(member.default_value)
forward_decl_name = idl_type.impl_forward_declaration_name
if forward_decl_name:
@@ -252,6 +271,7 @@ def member_impl_context(member, interfaces_info, header_includes,
return {
'cpp_default_value': cpp_default_value,
'cpp_name': cpp_name,
+ 'has_explicit_presence': has_explicit_presence,
'getter_expression': cpp_name + '_',
'getter_name': getter_name_for_dictionary_member(member),
'has_method_expression': has_method_expression(),
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_interface.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_interface.py
index 45c610edc22..12b5fa32d9c 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_interface.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_interface.py
@@ -64,10 +64,11 @@ INTERFACE_H_INCLUDES = frozenset([
])
INTERFACE_CPP_INCLUDES = frozenset([
'base/memory/scoped_refptr.h',
- 'bindings/core/v8/exception_state.h',
'bindings/core/v8/v8_dom_configuration.h',
- 'platform/bindings/v8_object_constructor.h',
'core/execution_context/execution_context.h',
+ 'platform/bindings/exception_messages.h',
+ 'platform/bindings/exception_state.h',
+ 'platform/bindings/v8_object_constructor.h',
'platform/wtf/get_ptr.h',
])
@@ -341,6 +342,7 @@ def interface_context(interface, interfaces):
' specified on partial interface definitions: '
'%s' % interface.name)
if named_constructor:
+ includes.add('platform/bindings/v8_per_context_data.h')
includes.add('platform/bindings/v8_private_property.h')
includes.add('platform/bindings/v8_object_constructor.h')
@@ -475,6 +477,8 @@ def interface_context(interface, interfaces):
sorted(origin_trial_features(interface, context['constants'], context['attributes'], context['methods']) +
context_enabled_features(context['attributes'])),
})
+ if context['optional_features']:
+ includes.add('platform/bindings/v8_per_context_data.h')
# Cross-origin interceptors
has_cross_origin_named_getter = False
@@ -913,9 +917,8 @@ def overloads_context(interface, overloads):
for length, effective_overloads in effective_overloads_by_length:
runtime_enabled_feature_names = set(
method['runtime_enabled_feature_name']
- for method, _, _ in effective_overloads
- if method.get('runtime_enabled_feature_name'))
- if not runtime_enabled_feature_names:
+ for method, _, _ in effective_overloads)
+ if None in runtime_enabled_feature_names:
# This "length" is unconditionally enabled, so stop here.
runtime_determined_lengths.append((length, [None]))
break
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_methods.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_methods.py
index 37f20d13fad..4e5e7379e65 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_methods.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_methods.py
@@ -178,6 +178,10 @@ def method_context(interface, method, is_visible=True):
else:
side_effect_type = 'V8DOMConfiguration::kHasSideEffect'
+ # [LogActivity]
+ if 'LogActivity' in extended_attributes:
+ includes.add('platform/bindings/v8_per_context_data.h')
+
argument_contexts = [
argument_context(interface, method, argument, index, is_visible=is_visible)
for index, argument in enumerate(arguments)]
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_types.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_types.py
index bf74a91fa88..dd76e7091a5 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_types.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_types.py
@@ -1032,11 +1032,8 @@ CPP_VALUE_TO_V8_VALUE = {
'StringOrNull': '{cpp_value}.IsNull() ? v8::Local<v8::Value>(v8::Null({isolate})) : V8String({isolate}, {cpp_value})',
# Special cases
'Dictionary': '{cpp_value}.V8Value()',
- 'EventHandler': (
- '{cpp_value} ? ' +
- 'V8AbstractEventListener::Cast({cpp_value})->GetListenerOrNull(' +
- '{isolate}, impl->GetExecutionContext()) : ' +
- 'v8::Null({isolate}).As<v8::Value>()'),
+ 'EventHandler':
+ 'V8AbstractEventListener::GetListenerOrNull({isolate}, impl, {cpp_value})',
'NodeFilter': 'ToV8({cpp_value}, {creation_context}, {isolate})',
'Record': 'ToV8({cpp_value}, {creation_context}, {isolate})',
'ScriptValue': '{cpp_value}.V8Value()',
@@ -1121,8 +1118,7 @@ def cpp_type_has_null_value(idl_type):
# - String types (String/AtomicString) represent null as a null string,
# i.e. one for which String::IsNull() returns true.
# - Enum types, as they are implemented as Strings.
- # - Interface types (raw pointer or RefPtr) represent null as
- # a null pointer.
+ # - Interface types (raw pointer) represent null as a null pointer.
# - Union types, as thier container classes can represent null value.
# - 'Object' and 'any' type. We use ScriptValue for object type.
return (idl_type.is_string_type
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_union.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_union.py
index 978f697ffd7..686310b529f 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_union.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_union.py
@@ -8,15 +8,16 @@ import v8_utilities
UNION_CPP_INCLUDES = frozenset([
+ 'base/stl_util.h',
'bindings/core/v8/to_v8_for_core.h',
])
UNION_H_INCLUDES = frozenset([
'base/optional.h',
'bindings/core/v8/dictionary.h',
- 'bindings/core/v8/exception_state.h',
'bindings/core/v8/native_value_traits.h',
'bindings/core/v8/v8_binding_for_core.h',
+ 'platform/bindings/exception_state.h',
'platform/heap/handle.h',
])
diff --git a/chromium/third_party/blink/renderer/bindings/scripts/v8_utilities.py b/chromium/third_party/blink/renderer/bindings/scripts/v8_utilities.py
index 2e8e49c144a..665038882a4 100644
--- a/chromium/third_party/blink/renderer/bindings/scripts/v8_utilities.py
+++ b/chromium/third_party/blink/renderer/bindings/scripts/v8_utilities.py
@@ -420,7 +420,7 @@ def origin_trial_feature_name(definition_or_member):
def origin_trial_function_call(feature_name, execution_context=None):
"""Returns a function call to determine if an origin trial is enabled."""
return 'OriginTrials::{feature_name}Enabled({context})'.format(
- feature_name=uncapitalize(feature_name),
+ feature_name=feature_name,
context=execution_context if execution_context else "execution_context")
diff --git a/chromium/third_party/blink/renderer/bindings/templates/attributes.cpp.tmpl b/chromium/third_party/blink/renderer/bindings/templates/attributes.cpp.tmpl
index da92e56ca4e..050de28af93 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/attributes.cpp.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/attributes.cpp.tmpl
@@ -386,6 +386,9 @@ v8::Local<v8::Value> v8Value, const v8::FunctionCallbackInfo<v8::Value>& info
{% if attribute.has_setter_exception_state %}
{{define_exception_state}}
{% endif %}
+ {% if attribute.is_ce_reactions %}
+ CEReactionsScope ce_reactions_scope;
+ {% endif %}
// Prepare the value to be set.
{% if attribute.idl_type != 'EventHandler' %}
@@ -405,7 +408,7 @@ v8::Local<v8::Value> v8Value, const v8::FunctionCallbackInfo<v8::Value>& info
// Returns undefined without setting the value if the value is invalid.
DummyExceptionStateForTesting dummyExceptionState;
{{declare_enum_validation_variable(attribute.enum_values) | trim | indent(2)}}
- if (!IsValidEnum(cppValue, validValues, arraysize(validValues), "{{attribute.enum_type}}", dummyExceptionState)) {
+ if (!IsValidEnum(cppValue, validValues, base::size(validValues), "{{attribute.enum_type}}", dummyExceptionState)) {
ExecutionContext::ForCurrentRealm(info)->AddConsoleMessage(
ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel,
dummyExceptionState.Message()));
@@ -446,8 +449,8 @@ v8::Local<v8::Value> v8Value, const v8::FunctionCallbackInfo<v8::Value>& info
.DeleteProperty(holder, v8::Undefined(isolate));
{% endif %}
{% endif %}{# attribute.is_put_forwards #}
+ {% endfilter %}{# format_remove_duplicates #}
}
-{% endfilter %}{# format_remove_duplicates #}
{% endmacro %}
@@ -459,6 +462,9 @@ v8::Local<v8::Name>, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInf
{%- else %}
const v8::FunctionCallbackInfo<v8::Value>& info
{%- endif %}) {
+ {% if attribute.is_lenient_setter %}
+ // Setter for {{attribute.name}} is no-op because [LenientSetter] is specified.
+ {% else %}
{% if attribute.runtime_call_stats.extended_attribute_defined %}
{{ runtime_timer_scope(attribute.runtime_call_stats.setter_counter) | trim | indent(2) }}
{% else %}
@@ -493,10 +499,6 @@ const v8::FunctionCallbackInfo<v8::Value>& info
}
{% endif %}
- {% if attribute.is_ce_reactions %}
- CEReactionsScope ceReactionsScope;
- {% endif %}
-
{% if attribute.has_custom_setter %}
{{v8_class}}::{{attribute.name}}AttributeSetterCustom(v8Value, info);
{% elif attribute.has_cross_origin_setter %}
@@ -504,6 +506,7 @@ const v8::FunctionCallbackInfo<v8::Value>& info
{% else %}
{{cpp_class_or_partial}}V8Internal::{{attribute.name}}AttributeSetter{{world_suffix}}(v8Value, info);
{% endif %}
+ {% endif %}{# attribute.is_lenient_setter #}
}
{% endmacro %}
@@ -601,7 +604,7 @@ static const V8DOMConfiguration::AccessorConfiguration accessor_configurations[]
V8DOMConfiguration::InstallAccessors(
isolate, world, instanceObject, prototypeObject, interfaceObject,
signature, accessor_configurations,
- arraysize(accessor_configurations));
+ base::size(accessor_configurations));
{% endfilter %}{# runtime_enabled #}
{% endfor %}{# secure_context_attribute_list grouped by runtime_enabled #}
{% endfilter %}{# secure_context #}
@@ -626,7 +629,7 @@ static const V8DOMConfiguration::AttributeConfiguration attribute_configurations
};
V8DOMConfiguration::InstallAttributes(
isolate, world, instanceObject, prototypeObject,
- attribute_configurations, arraysize(attribute_configurations));
+ attribute_configurations, base::size(attribute_configurations));
{% endfilter %}{# runtime_enabled #}
{% endfor %}{# secure_context_attribute_list grouped by runtime_enabled #}
{% endfilter %}{# secure_context #}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl b/chromium/third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl
index aa00906f809..b4e90663660 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/callback_function.cpp.tmpl
@@ -11,6 +11,10 @@
namespace blink {
+const char* {{cpp_class}}::NameInHeapSnapshot() const {
+ return "{{cpp_class}}";
+}
+
v8::Maybe<{{return_cpp_type}}> {{cpp_class}}::Invoke({{argument_declarations | join(', ')}}) {
// This function implements "invoke" algorithm defined in
// "3.10. Invoking callback functions".
@@ -20,7 +24,8 @@ v8::Maybe<{{return_cpp_type}}> {{cpp_class}}::Invoke({{argument_declarations | j
promise type, in which case this function needs to convert any exception
into a rejected promise. See also step 14.4. to 14.6. #}
- if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState())) {
+ if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(),
+ IncumbentScriptState())) {
// Wrapper-tracing for the callback function makes the function object and
// its creation context alive. Thus it's safe to use the creation context
// of the callback function here.
@@ -51,17 +56,6 @@ v8::Maybe<{{return_cpp_type}}> {{cpp_class}}::Invoke({{argument_declarations | j
ScriptState::Scope callback_relevant_context_scope(
CallbackRelevantScriptState());
// step 9. Prepare to run a callback with stored settings.
- {# TODO(yukishiino): Callback function type value must make the incumbent
- environment alive, i.e. the reference to v8::Context must be strong. #}
- if (IncumbentScriptState()->GetContext().IsEmpty()) {
- V8ThrowException::ThrowError(
- GetIsolate(),
- ExceptionMessages::FailedToExecute(
- "invoke",
- "{{callback_function_name}}",
- "The provided callback is no longer runnable."));
- return v8::Nothing<{{return_cpp_type}}>();
- }
v8::Context::BackupIncumbentScope backup_incumbent_scope(
IncumbentScriptState()->GetContext());
@@ -78,7 +72,7 @@ v8::Maybe<{{return_cpp_type}}> {{cpp_class}}::Invoke({{argument_declarations | j
ExceptionState::kExecutionContext,
"{{callback_function_name}}",
"invoke");
- if (!IsValidEnum({{argument.name}}, {{valid_enum_variables}}, arraysize({{valid_enum_variables}}), "{{argument.enum_type}}", exception_state)) {
+ if (!IsValidEnum({{argument.name}}, {{valid_enum_variables}}, base::size({{valid_enum_variables}}), "{{argument.enum_type}}", exception_state)) {
NOTREACHED();
return v8::Nothing<{{return_cpp_type}}>();
}
@@ -150,7 +144,6 @@ void {{cpp_class}}::InvokeAndReportException({{argument_declarations | join(', '
}
{% endif %}
-{{exported|replace('_EXPORT', '_TEMPLATE_EXPORT')|trim}}
v8::Maybe<{{return_cpp_type}}> V8PersistentCallbackFunction<{{cpp_class}}>::Invoke({{argument_declarations | join(', ')}}) {
return Proxy()->Invoke(
{{
@@ -161,7 +154,6 @@ v8::Maybe<{{return_cpp_type}}> V8PersistentCallbackFunction<{{cpp_class}}>::Invo
}
{% if idl_type == 'void' %}
-{{exported|replace('_EXPORT', '_TEMPLATE_EXPORT')|trim}}
void V8PersistentCallbackFunction<{{cpp_class}}>::InvokeAndReportException({{argument_declarations | join(', ')}}) {
Proxy()->InvokeAndReportException(
{{
diff --git a/chromium/third_party/blink/renderer/bindings/templates/callback_function.h.tmpl b/chromium/third_party/blink/renderer/bindings/templates/callback_function.h.tmpl
index e43b7d5cf1a..44b5414376d 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/callback_function.h.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/callback_function.h.tmpl
@@ -23,6 +23,9 @@ class {{exported}}{{cpp_class}} final : public CallbackFunctionBase {
~{{cpp_class}}() override = default;
+ // NameClient overrides:
+ const char* NameInHeapSnapshot() const override;
+
// Performs "invoke".
// https://heycam.github.io/webidl/#es-invoking-callback-functions
v8::Maybe<{{return_cpp_type}}> Invoke({{argument_declarations | join(', ')}}) WARN_UNUSED_RESULT;
@@ -39,7 +42,7 @@ class {{exported}}{{cpp_class}} final : public CallbackFunctionBase {
};
template <>
-class {{exported|replace('_EXPORT', '_TEMPLATE_CLASS_EXPORT')}}V8PersistentCallbackFunction<{{cpp_class}}> final : public V8PersistentCallbackFunctionBase {
+class V8PersistentCallbackFunction<{{cpp_class}}> final : public V8PersistentCallbackFunctionBase {
using V8CallbackFunction = {{cpp_class}};
public:
@@ -48,11 +51,9 @@ class {{exported|replace('_EXPORT', '_TEMPLATE_CLASS_EXPORT')}}V8PersistentCallb
// Returns a wrapper-tracing version of this callback function.
V8CallbackFunction* ToNonV8Persistent() { return Proxy(); }
- {{exported|replace('_EXPORT', '_EXTERN_TEMPLATE_EXPORT')|trim}}
v8::Maybe<{{return_cpp_type}}> Invoke({{argument_declarations | join(', ')}}) WARN_UNUSED_RESULT;
{% if idl_type == 'void' %}
- {{exported|replace('_EXPORT', '_EXTERN_TEMPLATE_EXPORT')|trim}}
- void InvokeAndReportException({{argument_declarations | join(', ')}});
+ {{exported}}void InvokeAndReportException({{argument_declarations | join(', ')}});
{% endif %}
private:
diff --git a/chromium/third_party/blink/renderer/bindings/templates/callback_interface.cpp.tmpl b/chromium/third_party/blink/renderer/bindings/templates/callback_interface.cpp.tmpl
index 5d6861ecf64..bd507150c47 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/callback_interface.cpp.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/callback_interface.cpp.tmpl
@@ -63,13 +63,18 @@ v8::Local<v8::FunctionTemplate> {{v8_class}}::DomTemplate(v8::Isolate* isolate,
}
{% endif %}{# is_legacy_callback_interface #}
+const char* {{v8_class}}::NameInHeapSnapshot() const {
+ return "{{v8_class}}";
+}
+
{% for method in methods %}
v8::Maybe<{{method.cpp_type}}> {{v8_class}}::{{method.name}}({{method.argument_declarations | join(', ')}}) {
// This function implements "call a user object's operation".
// https://heycam.github.io/webidl/#call-a-user-objects-operation
- if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState())) {
+ if (!IsCallbackFunctionRunnable(CallbackRelevantScriptState(),
+ IncumbentScriptState())) {
// Wrapper-tracing for the callback function makes the function object and
// its creation context alive. Thus it's safe to use the creation context
// of the callback function here.
@@ -89,17 +94,6 @@ v8::Maybe<{{method.cpp_type}}> {{v8_class}}::{{method.name}}({{method.argument_d
ScriptState::Scope callback_relevant_context_scope(
CallbackRelevantScriptState());
// step 8. Prepare to run a callback with stored settings.
- {# TODO(yukishiino): Callback interface type value must make the incumbent
- environment alive, i.e. the reference to v8::Context must be strong. #}
- if (IncumbentScriptState()->GetContext().IsEmpty()) {
- V8ThrowException::ThrowError(
- GetIsolate(),
- ExceptionMessages::FailedToExecute(
- "{{method.name}}",
- "{{cpp_class}}",
- "The provided callback is no longer runnable."));
- return v8::Nothing<{{method.cpp_type}}>();
- }
v8::Context::BackupIncumbentScope backup_incumbent_scope(
IncumbentScriptState()->GetContext());
@@ -156,7 +150,7 @@ v8::Maybe<{{method.cpp_type}}> {{v8_class}}::{{method.name}}({{method.argument_d
ExceptionState::kExecutionContext,
"{{cpp_class}}",
"{{method.name}}");
- if (!IsValidEnum({{argument.name}}, {{valid_enum_variables}}, arraysize({{valid_enum_variables}}), "{{argument.enum_type}}", exception_state)) {
+ if (!IsValidEnum({{argument.name}}, {{valid_enum_variables}}, base::size({{valid_enum_variables}}), "{{argument.enum_type}}", exception_state)) { //
NOTREACHED();
return v8::Nothing<{{method.cpp_type}}>();
}
@@ -236,7 +230,6 @@ void {{v8_class}}::InvokeAndReportException({{methods[0].argument_declarations |
{% endif %}
{% for method in methods %}
-{{exported|replace('_EXPORT', '_EXTERN_TEMPLATE_EXPORT')|trim}}
v8::Maybe<{{method.cpp_type}}> V8PersistentCallbackInterface<{{v8_class}}>::{{method.name}}({{method.argument_declarations | join(', ')}}) {
return Proxy()->{{method.name}}(
{{
@@ -249,7 +242,6 @@ v8::Maybe<{{method.cpp_type}}> V8PersistentCallbackInterface<{{v8_class}}>::{{me
{% endfor %}
{% if methods|length == 1 and methods[0].idl_type == 'void' %}
-{{exported|replace('_EXPORT', '_EXTERN_TEMPLATE_EXPORT')|trim}}
void V8PersistentCallbackInterface<{{v8_class}}>::InvokeAndReportException({{methods[0].argument_declarations | join(', ')}}) {
Proxy()->InvokeAndReportException(
{{
diff --git a/chromium/third_party/blink/renderer/bindings/templates/callback_interface.h.tmpl b/chromium/third_party/blink/renderer/bindings/templates/callback_interface.h.tmpl
index 4682e10ac93..8db43d46ff3 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/callback_interface.h.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/callback_interface.h.tmpl
@@ -33,6 +33,9 @@ class {{exported}}{{v8_class}} final : public CallbackInterfaceBase {
~{{v8_class}}() override = default;
+ // NameClient overrides:
+ const char* NameInHeapSnapshot() const override;
+
{% for method in methods %}
// Performs "call a user object's operation".
// https://heycam.github.io/webidl/#call-a-user-objects-operation
@@ -55,19 +58,17 @@ class {{exported}}{{v8_class}} final : public CallbackInterfaceBase {
};
template <>
-class {{exported|replace('_EXPORT', '_TEMPLATE_CLASS_EXPORT')}}V8PersistentCallbackInterface<{{v8_class}}> final : public V8PersistentCallbackInterfaceBase {
+class V8PersistentCallbackInterface<{{v8_class}}> final : public V8PersistentCallbackInterfaceBase {
using V8CallbackInterface = {{v8_class}};
public:
~V8PersistentCallbackInterface() override = default;
{% for method in methods %}
- {{exported|replace('_EXPORT', '_EXTERN_TEMPLATE_EXPORT')|trim}}
- v8::Maybe<{{method.cpp_type}}> {{method.name}}({{method.argument_declarations | join(', ')}}) WARN_UNUSED_RESULT;
+ {{exported}}v8::Maybe<{{method.cpp_type}}> {{method.name}}({{method.argument_declarations | join(', ')}}) WARN_UNUSED_RESULT;
{% endfor %}
{% if methods|length == 1 and methods[0].idl_type == 'void' %}
- {{exported|replace('_EXPORT', '_EXTERN_TEMPLATE_EXPORT')|trim}}
- void InvokeAndReportException({{methods[0].argument_declarations | join(', ')}});
+ {{exported}}void InvokeAndReportException({{methods[0].argument_declarations | join(', ')}});
{% endif %}
private:
diff --git a/chromium/third_party/blink/renderer/bindings/templates/constants.cpp.tmpl b/chromium/third_party/blink/renderer/bindings/templates/constants.cpp.tmpl
index 8f77b548725..1b8d27c0335 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/constants.cpp.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/constants.cpp.tmpl
@@ -32,7 +32,7 @@ static constexpr V8DOMConfiguration::ConstantConfiguration {{v8_class}}Constants
};
V8DOMConfiguration::InstallConstants(
isolate, interfaceTemplate, prototypeTemplate,
- {{v8_class}}Constants, arraysize({{v8_class}}Constants));
+ {{v8_class}}Constants, base::size({{v8_class}}Constants));
{% endif %}
{# Constants with [DeprecateAs] or [MeasureAs] #}
{% for constant in constants | has_special_getter %}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/dictionary_impl.cpp.tmpl b/chromium/third_party/blink/renderer/bindings/templates/dictionary_impl.cpp.tmpl
index d1be4bd542c..a08c3adb996 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/dictionary_impl.cpp.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/dictionary_impl.cpp.tmpl
@@ -13,7 +13,11 @@ namespace blink {
{# Constructor #}
{{cpp_class}}::{{cpp_class}}() {
{% for member in members if member.cpp_default_value %}
+ {% if member.is_default_value_null and member.null_setter_name %}
+ {{member.null_setter_name}}();
+ {% else %}
{{member.setter_name}}({{member.cpp_default_value}});
+ {% endif %}
{% endfor %}
}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/dictionary_impl.h.tmpl b/chromium/third_party/blink/renderer/bindings/templates/dictionary_impl.h.tmpl
index 48fd95efbbb..8c034f93ea4 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/dictionary_impl.h.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/dictionary_impl.h.tmpl
@@ -27,7 +27,7 @@ class {{exported}}{{cpp_class}}{% if parent_cpp_class %} : public {{parent_cpp_c
{% for member in members %}
bool {{member.has_method_name}}() const { return {{member.has_method_expression}}; }
{{member.rvalue_cpp_type}} {{member.getter_name}}() const {
- {% if member.nullable_indicator_name %}
+ {% if member.nullable_indicator_name and not member.has_explicit_presence %}
DCHECK({{member.nullable_indicator_name}});
{% endif %}
return {{member.getter_expression}};
diff --git a/chromium/third_party/blink/renderer/bindings/templates/dictionary_impl_common.cpp.tmpl b/chromium/third_party/blink/renderer/bindings/templates/dictionary_impl_common.cpp.tmpl
index ecdd7b04e66..d4cf49b6baf 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/dictionary_impl_common.cpp.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/dictionary_impl_common.cpp.tmpl
@@ -5,9 +5,13 @@ void {{cpp_class}}::{{member.setter_name}}({{member.rvalue_cpp_type}} value) {
{{member.nullable_indicator_name}} = true;
{% endif %}
}
+
{% if member.null_setter_name %}
void {{cpp_class}}::{{member.null_setter_name}}() {
- {% if member.nullable_indicator_name %}
+ {% if member.has_explicit_presence %}
+ {{member.cpp_name}}_ = {{member.member_cpp_type}}();
+ {{member.nullable_indicator_name}} = true;
+ {% elif member.nullable_indicator_name %}
{{member.nullable_indicator_name}} = false;
{% else %}
{{member.cpp_name}}_ = {{member.member_cpp_type}}();
diff --git a/chromium/third_party/blink/renderer/bindings/templates/dictionary_v8.cpp.tmpl b/chromium/third_party/blink/renderer/bindings/templates/dictionary_v8.cpp.tmpl
index 02cf3c0c248..20df71dae0d 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/dictionary_v8.cpp.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/dictionary_v8.cpp.tmpl
@@ -18,7 +18,7 @@ static const v8::Eternal<v8::Name>* eternal{{v8_class}}Keys(v8::Isolate* isolate
{% endfor %}
};
return V8PerIsolateData::From(isolate)->FindOrCreateEternalNameCache(
- kKeys, kKeys, arraysize(kKeys));
+ kKeys, kKeys, base::size(kKeys));
}
{% endif %}
@@ -92,7 +92,7 @@ void {{v8_class}}::ToImpl(v8::Isolate* isolate, v8::Local<v8::Value> v8Value, {{
{% endif %}
{% if member.enum_values %}
{{declare_enum_validation_variable(member.enum_values) | trim | indent}}
- if (!IsValidEnum({{member.name}}CppValue, validValues, arraysize(validValues), "{{member.enum_type}}", exceptionState))
+ if (!IsValidEnum({{member.name}}CppValue, validValues, base::size(validValues), "{{member.enum_type}}", exceptionState))
return;
{% elif member.is_object %}
if (!{{member.name}}CppValue.IsObject()) {
@@ -150,7 +150,7 @@ bool toV8{{cpp_class}}(const {{cpp_class}}& impl, v8::Local<v8::Object> dictiona
} else {
{{member.name}}Value = {{member.v8_default_value}};
{{member.name}}HasValueOrDefault = true;
- {% elif member.is_nullable %}
+ {% elif member.is_nullable and not member.has_explicit_presence %}
} else {
{{member.name}}Value = v8::Null(isolate);
{{member.name}}HasValueOrDefault = true;
diff --git a/chromium/third_party/blink/renderer/bindings/templates/interface.cpp.tmpl b/chromium/third_party/blink/renderer/bindings/templates/interface.cpp.tmpl
index 2222a65e744..9bd26814261 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/interface.cpp.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/interface.cpp.tmpl
@@ -77,6 +77,9 @@ static void indexedPropertySetter(uint32_t index, v8::Local<v8::Value> v8Value,
{% if setter.has_exception_state %}
ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kIndexedSetterContext, "{{interface_name}}");
{% endif %}
+ {% if setter.is_ce_reactions %}
+ CEReactionsScope ce_reactions_scope;
+ {% endif %}
{{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
{{v8_value_to_local_cpp_value(setter) | trim | indent(2)}}
@@ -117,10 +120,6 @@ static void indexedPropertySetter(uint32_t index, v8::Local<v8::Value> v8Value,
{% if indexed_property_getter or named_property_setter %}
{% set setter = indexed_property_setter or named_property_setter %}
void {{v8_class_or_partial}}::indexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<v8::Value>& info) {
- {% if setter.is_ce_reactions %}
- CEReactionsScope ceReactionsScope;
- {% endif %}
-
{% if indexed_property_setter %}
{% if setter.is_custom %}
@@ -148,6 +147,9 @@ void {{v8_class_or_partial}}::indexedPropertySetterCallback(uint32_t index, v8::
ExceptionState exceptionState(info.GetIsolate(),
ExceptionState::kIndexedSetterContext,
"{{interface_name}}");
+ {% if setter.is_ce_reactions %}
+ CEReactionsScope ce_reactions_scope;
+ {% endif %}
exceptionState.ThrowTypeError("Index property setter is not supported.");
}
@@ -267,6 +269,9 @@ static void indexedPropertyDeleter(uint32_t index, const v8::PropertyCallbackInf
{% if deleter.is_raises_exception %}
ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kIndexedDeletionContext, "{{interface_name}}");
{% endif %}
+ {% if deleter.is_ce_reactions %}
+ CEReactionsScope ce_reactions_scope;
+ {% endif %}
{{cpp_class}}* impl = {{v8_class}}::ToImpl(info.Holder());
@@ -298,10 +303,6 @@ static void indexedPropertyDeleter(uint32_t index, const v8::PropertyCallbackInf
{% if indexed_property_deleter or named_property_deleter %}
{% set deleter = indexed_property_deleter or named_property_deleter %}
void {{v8_class_or_partial}}::indexedPropertyDeleterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info) {
- {% if deleter.is_ce_reactions %}
- CEReactionsScope ceReactionsScope;
- {% endif %}
-
{% if indexed_property_deleter %}
{% if deleter.is_custom %}
@@ -434,6 +435,9 @@ static void namedPropertySetter(const AtomicString& name, v8::Local<v8::Value> v
const CString& nameInUtf8 = name.Utf8();
ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kSetterContext, "{{interface_name}}", nameInUtf8.data());
{% endif %}
+ {% if setter.is_ce_reactions %}
+ CEReactionsScope ce_reactions_scope;
+ {% endif %}
{% if setter.is_call_with_script_state %}
ScriptState* scriptState = ScriptState::ForRelevantRealm(info);
{% endif %}
@@ -481,10 +485,6 @@ void {{v8_class_or_partial}}::namedPropertySetterCallback(v8::Local<v8::Name> na
return;
const AtomicString& propertyName = ToCoreAtomicString(name.As<v8::String>());
- {% if setter.is_ce_reactions %}
- CEReactionsScope ceReactionsScope;
- {% endif %}
-
{% if setter.is_custom %}
{{v8_class}}::namedPropertySetterCustom(propertyName, v8Value, info);
{% else %}
@@ -505,6 +505,9 @@ static void namedPropertyDeleter(const AtomicString& name, const v8::PropertyCal
const CString& nameInUtf8 = name.Utf8();
ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kDeletionContext, "{{interface_name}}", nameInUtf8.data());
{% endif %}
+ {% if deleter.is_ce_reactions %}
+ CEReactionsScope ce_reactions_scope;
+ {% endif %}
{% if deleter.is_call_with_script_state %}
ScriptState* scriptState = ScriptState::ForRelevantRealm(info);
{% endif %}
@@ -542,10 +545,6 @@ void {{v8_class_or_partial}}::namedPropertyDeleterCallback(v8::Local<v8::Name> n
return;
const AtomicString& propertyName = ToCoreAtomicString(name.As<v8::String>());
- {% if deleter.is_ce_reactions %}
- CEReactionsScope ceReactionsScope;
- {% endif %}
-
{% if deleter.is_custom %}
{{v8_class}}::namedPropertyDeleterCustom(propertyName, info);
{% else %}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/interface.h.tmpl b/chromium/third_party/blink/renderer/bindings/templates/interface.h.tmpl
index 21ba3ec11f2..ddac35416b1 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/interface.h.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/interface.h.tmpl
@@ -199,10 +199,10 @@ class {{v8_class}} {
{# with considering partial overloads #}
{{exported}}static void {{method.name}}MethodCallback{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>&);
{% endif %}
- {% endif %}
{% if method.is_cross_origin and method.visible %}
{{exported}}static void {{method.name}}OriginSafeMethodGetterCallback{{world_suffix}}(v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>&);
{% endif %}
+ {% endif %}
{% endfor %}
{% endfor %}
{% if iterator_method %}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/interface_base.cpp.tmpl b/chromium/third_party/blink/renderer/bindings/templates/interface_base.cpp.tmpl
index 99690e67734..afa46eb913e 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/interface_base.cpp.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/interface_base.cpp.tmpl
@@ -92,7 +92,7 @@ static void (*{{method.name}}MethodForPartialInterface)(const v8::FunctionCallba
{% if not attribute.has_custom_getter and not attribute.constructor_type %}
{{attribute_getter(attribute, world_suffix)}}
{% endif %}
-{% if attribute.has_setter and not attribute.has_custom_setter %}
+{% if attribute.has_setter and not (attribute.has_custom_setter or attribute.is_lenient_setter) %}
{{attribute_setter(attribute, world_suffix)}}
{% endif %}
{% endfor %}
@@ -121,7 +121,8 @@ static void (*{{method.name}}MethodForPartialInterface)(const v8::FunctionCallba
{% endif %}
{{overload_resolution_method(method.overloads, world_suffix)}}
{% endif %}
-{% if method.is_cross_origin and method.visible %}
+{% if method.is_cross_origin and method.visible and
+ (not method.overload_index or method.overloads) %}
{{origin_safe_method_getter(method, world_suffix)}}
{% endif %}
{% endfor %}
@@ -173,7 +174,8 @@ static const struct {
},
{% endfor %}
{##### Cross-origin methods #####}
- {% for method in methods if method.is_cross_origin %}
+ {% for method in methods if method.is_cross_origin and
+ (not method.overload_index or method.overloads) %}
{"{{method.name}}", &{{cpp_class}}V8Internal::{{method.name}}OriginSafeMethodGetter, nullptr},
{% endfor %}
};
@@ -219,7 +221,8 @@ static const struct {
{{method_callback(method, world_suffix)}}
{% endif %}
{% endif %}
-{% if method.is_cross_origin and method.visible %}
+{% if method.is_cross_origin and method.visible and
+ (not method.overload_index or method.overloads) %}
{{origin_safe_method_getter_callback(method, world_suffix)}}
{% endif %}
{% endfor %}
@@ -491,22 +494,22 @@ static void install{{v8_class}}Template(
{% if data_attributes %}
V8DOMConfiguration::InstallAttributes(
isolate, world, instanceTemplate, prototypeTemplate,
- {{'%sAttributes' % v8_class}}, {{'arraysize(%sAttributes)' % v8_class}});
+ {{'%sAttributes' % v8_class}}, {{'base::size(%sAttributes)' % v8_class}});
{% endif %}
{% if lazy_data_attributes %}
V8DOMConfiguration::InstallLazyDataAttributes(
isolate, world, instanceTemplate, prototypeTemplate,
- {{'%sLazyDataAttributes' % v8_class}}, {{'arraysize(%sLazyDataAttributes)' % v8_class}});
+ {{'%sLazyDataAttributes' % v8_class}}, {{'base::size(%sLazyDataAttributes)' % v8_class}});
{% endif %}
{% if accessors %}
V8DOMConfiguration::InstallAccessors(
isolate, world, instanceTemplate, prototypeTemplate, interfaceTemplate,
- signature, {{'%sAccessors' % v8_class}}, {{'arraysize(%sAccessors)' % v8_class}});
+ signature, {{'%sAccessors' % v8_class}}, {{'base::size(%sAccessors)' % v8_class}});
{% endif %}
{% if methods | has_method_configuration(is_partial) %}
V8DOMConfiguration::InstallMethods(
isolate, world, instanceTemplate, prototypeTemplate, interfaceTemplate,
- signature, {{'%sMethods' % v8_class}}, {{'arraysize(%sMethods)' % v8_class}});
+ signature, {{'%sMethods' % v8_class}}, {{'base::size(%sMethods)' % v8_class}});
{% endif %}
{% if has_access_check_callbacks and not is_partial %}
@@ -707,7 +710,7 @@ void {{v8_class_or_partial}}::InstallRuntimeEnabledFeaturesOnTemplate(
};
V8DOMConfiguration::InstallConstants(
isolate, interface_template, prototype_template,
- constant_configurations, arraysize(constant_configurations));
+ constant_configurations, base::size(constant_configurations));
{% endfilter %}
{% endfor %}
@@ -720,7 +723,7 @@ void {{v8_class_or_partial}}::InstallRuntimeEnabledFeaturesOnTemplate(
};
V8DOMConfiguration::InstallAttributes(
isolate, world, instance_template, prototype_template,
- attribute_configurations, arraysize(attribute_configurations));
+ attribute_configurations, base::size(attribute_configurations));
{% endfilter %}
{% endfor %}
@@ -734,7 +737,7 @@ void {{v8_class_or_partial}}::InstallRuntimeEnabledFeaturesOnTemplate(
V8DOMConfiguration::InstallAccessors(
isolate, world, instance_template, prototype_template, interface_template,
signature, accessor_configurations,
- arraysize(accessor_configurations));
+ base::size(accessor_configurations));
{% endfilter %}
{% endfor %}
@@ -833,7 +836,7 @@ void {{v8_class_or_partial}}::InstallRuntimeEnabledFeaturesImpl(
{% endfor %}
};
V8DOMConfiguration::InstallAttributes(isolate, world, instance, prototype,
- attribute_configurations, arraysize(attribute_configurations));
+ attribute_configurations, base::size(attribute_configurations));
{% endfilter %}
{% endfor %}
@@ -846,7 +849,7 @@ void {{v8_class_or_partial}}::InstallRuntimeEnabledFeaturesImpl(
};
V8DOMConfiguration::InstallAccessors(isolate, world, instance, prototype,
interface, signature, accessor_configurations,
- arraysize(accessor_configurations));
+ base::size(accessor_configurations));
{% endfilter %}
{% endfor %}
@@ -985,7 +988,12 @@ void {{v8_class_or_partial}}::InstallConditionalFeatures(
if (prototypeObject->HasOwnProperty(context, unscopablesSymbol).To(&has_unscopables) && has_unscopables) {
unscopables = prototypeObject->Get(context, unscopablesSymbol).ToLocalChecked().As<v8::Object>();
} else {
+ // Web IDL 3.6.3. Interface prototype object
+ // https://heycam.github.io/webidl/#create-an-interface-prototype-object
+ // step 8.1. Let unscopableObject be the result of performing
+ // ! ObjectCreate(null).
unscopables = v8::Object::New(isolate);
+ unscopables->SetPrototype(context, v8::Null(isolate)).ToChecked();
}
{% for name, runtime_enabled_feature_name in unscopables %}
{% filter runtime_enabled(runtime_enabled_feature_name) %}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/methods.cpp.tmpl b/chromium/third_party/blink/renderer/bindings/templates/methods.cpp.tmpl
index 76e58c56364..1c81b4fc347 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/methods.cpp.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/methods.cpp.tmpl
@@ -18,10 +18,6 @@ static void {{method.name}}{{method.overload_index}}Method{{world_suffix}}(const
ExceptionState exceptionState(info.GetIsolate(), ExceptionState::kExecutionContext, "{{interface_name}}", "{{method.name}}");
{%- endset %}
- {% if method.is_ce_reactions %}
- CEReactionsScope ceReactionsScope;
- {% endif %}
-
{% set function_call = func_call_with_prep_of_args(method, world_suffix) %}
{% if 'exceptionState' in function_call or
@@ -31,6 +27,9 @@ static void {{method.name}}{{method.overload_index}}Method{{world_suffix}}(const
ExceptionToRejectPromiseScope rejectPromiseScope(info, exceptionState);
{% endif %}
{% endif %}
+ {% if method.is_ce_reactions %}
+ CEReactionsScope ce_reactions_scope;
+ {% endif %}
{% if not method.is_static %}
{% if method.returns_promise %}
@@ -231,7 +230,7 @@ if (!{{argument.name}}{% if argument.is_nullable %} && !IsUndefinedOrNull(info[{
{# Invalid enum values: http://www.w3.org/TR/WebIDL/#idl-enums #}
{% set enum_variable = 'valid' + argument.name[0].upper() + argument.name[1:] + 'Values' %}
{{declare_enum_validation_variable(argument.enum_values, enum_variable)}}
-if (!IsValidEnum({{argument.name}}, {{enum_variable}}, arraysize({{enum_variable}}), "{{argument.enum_type}}", exceptionState)) {
+if (!IsValidEnum({{argument.name}}, {{enum_variable}}, base::size({{enum_variable}}), "{{argument.enum_type}}", exceptionState)) {
return;
}
{% elif argument.idl_type == 'Promise' %}
diff --git a/chromium/third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl b/chromium/third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl
index 59e5c582aeb..f01f7b1ec8d 100644
--- a/chromium/third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl
+++ b/chromium/third_party/blink/renderer/bindings/templates/union_container.cpp.tmpl
@@ -42,7 +42,7 @@ void {{cpp_class}}::Set{{member.type_name}}({{member.rvalue_cpp_type}} value) {
{% if member.enum_values %}
NonThrowableExceptionState exceptionState;
{{declare_enum_validation_variable(member.enum_values) | trim | indent(2)}}
- if (!IsValidEnum(value, validValues, arraysize(validValues), "{{member.enum_type}}", exceptionState)) {
+ if (!IsValidEnum(value, validValues, base::size(validValues), "{{member.enum_type}}", exceptionState)) {
NOTREACHED();
return;
}
@@ -113,7 +113,7 @@ void {{v8_class}}::ToImpl(v8::Isolate* isolate, v8::Local<v8::Value> v8Value, {{
{{v8_value_to_local_cpp_value(array_or_sequence_type) | trim | indent}}
{% if array_or_sequence_type.enum_values %}
{{declare_enum_validation_variable(array_or_sequence_type.enum_values) | trim | indent(4)}}
- if (!IsValidEnum(cppValue, validValues, arraysize(validValues), "{{array_or_sequence_type.enum_type}}", exceptionState))
+ if (!IsValidEnum(cppValue, validValues, base::size(validValues), "{{array_or_sequence_type.enum_type}}", exceptionState))
return;
{% endif %}
impl.Set{{array_or_sequence_type.type_name}}(cppValue);
@@ -174,7 +174,7 @@ void {{v8_class}}::ToImpl(v8::Isolate* isolate, v8::Local<v8::Value> v8Value, {{
{{v8_value_to_local_cpp_value(string_type) | trim | indent}}
{% if string_type.enum_values %}
{{declare_enum_validation_variable(string_type.enum_values) | trim | indent}}
- if (!IsValidEnum(cppValue, validValues, arraysize(validValues), "{{string_type.enum_type}}", exceptionState))
+ if (!IsValidEnum(cppValue, validValues, base::size(validValues), "{{string_type.enum_type}}", exceptionState))
return;
{% endif %}
impl.Set{{string_type.type_name}}(cppValue);
diff --git a/chromium/third_party/blink/renderer/build/scripts/blinkbuild/PRESUBMIT.py b/chromium/third_party/blink/renderer/build/scripts/blinkbuild/PRESUBMIT.py
new file mode 100644
index 00000000000..393539ef97e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/build/scripts/blinkbuild/PRESUBMIT.py
@@ -0,0 +1,26 @@
+# 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.
+
+
+def _RunBindingsTests(input_api, output_api):
+ pardir = input_api.os_path.pardir
+ cmd_name = 'run_bindings_tests.py'
+ run_bindings_tests_path = input_api.os_path.join(
+ input_api.PresubmitLocalPath(), *([pardir] * 4 + ['tools', cmd_name]))
+ cmd = [input_api.python_executable, run_bindings_tests_path]
+ if input_api.verbose:
+ print('Running ' + cmd_name)
+ else:
+ cmd.append('--suppress-diff')
+ test_cmd = input_api.Command(name=cmd_name, cmd=cmd,
+ kwargs={}, message=output_api.PresubmitError)
+ return input_api.RunTests([test_cmd])
+
+
+def CheckChangeOnUpload(input_api, output_api):
+ return _RunBindingsTests(input_api, output_api)
+
+
+def CheckChangeOnCommit(input_api, output_api):
+ return _RunBindingsTests(input_api, output_api)
diff --git a/chromium/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter.py b/chromium/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter.py
index 1b6c7dab31b..9f28d3ad545 100644
--- a/chromium/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter.py
+++ b/chromium/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter.py
@@ -22,6 +22,7 @@ SPECIAL_TOKENS = [
'Uint16',
'Uint32',
'WebGL2',
+ 'WebGPU',
'ASCII',
'CSSOM',
'CType',
@@ -58,6 +59,8 @@ SPECIAL_TOKENS = [
'V8',
]
+_SPECIAL_TOKENS_WITH_NUMBERS = [token for token in SPECIAL_TOKENS if re.search(r'[0-9]', token)]
+
# Applying _TOKEN_PATTERNS repeatedly should capture any sequence of a-z, A-Z,
# 0-9.
_TOKEN_PATTERNS = [
@@ -89,7 +92,16 @@ def tokenize_name(name):
A list of token strings.
"""
- return _TOKEN_RE.findall(name)
+
+ # In case |name| is written in lowerCamelCase, we try to match special
+ # tokens that contains numbers ignoring cases only at the first step.
+ tokens = []
+ match = re.search(r'^(' + '|'.join(_SPECIAL_TOKENS_WITH_NUMBERS) + r')', name, re.IGNORECASE)
+ if match:
+ tokens.append(match.group(0))
+ name = name[match.end(0):]
+
+ return tokens + _TOKEN_RE.findall(name)
class NameStyleConverter(object):
@@ -98,6 +110,22 @@ class NameStyleConverter(object):
def __init__(self, name):
self.tokens = tokenize_name(name)
+ self._original = name
+
+ @property
+ def original(self):
+ return self._original
+
+ def __str__(self):
+ return self._original
+
+ # Make this class workable with sort().
+ def __lt__(self, other):
+ return self.original < other.original
+
+ # Make this class workable with groupby().
+ def __eq__(self, other):
+ return self.original == other.original
def to_snake_case(self):
"""Snake case is the file and variable name style per Google C++ Style
@@ -151,3 +179,47 @@ class NameStyleConverter(object):
'upper_camel_case': self.to_upper_camel_case(),
'macro_case': self.to_macro_case(),
}
+
+ # Use the following high level naming functions which describe the semantics
+ # of the name, rather than a particular style.
+
+ def to_class_name(self, prefix=None, suffix=None):
+ """Represents this name as a class name in Chromium C++ style.
+
+ i.e. UpperCamelCase.
+ """
+ camel_prefix = prefix[0].upper() + prefix[1:].lower() if prefix else ''
+ camel_suffix = suffix[0].upper() + suffix[1:].lower() if suffix else ''
+ return camel_prefix + self.to_upper_camel_case() + camel_suffix
+
+ def to_class_data_member(self, prefix=None, suffix=None):
+ """Represents this name as a data member name in Chromium C++ style.
+
+ i.e. snake_case_with_trailing_underscore_.
+ """
+ lower_prefix = prefix.lower() + '_' if prefix else ''
+ lower_suffix = suffix.lower() + '_' if suffix else ''
+ return lower_prefix + self.to_snake_case() + '_' + lower_suffix
+
+ def to_function_name(self, prefix=None, suffix=None):
+ """Represents this name as a function name in Blink C++ style.
+
+ i.e. UpperCamelCase
+ Note that this function should not be used for IDL operation names and
+ C++ functions implementing IDL operations and attributes.
+ """
+ camel_prefix = prefix[0].upper() + prefix[1:].lower() if prefix else ''
+ camel_suffix = ''
+ if type(suffix) is list:
+ for item in suffix:
+ camel_suffix += item[0].upper() + item[1:].lower()
+ elif suffix:
+ camel_suffix = suffix[0].upper() + suffix[1:].lower()
+ return camel_prefix + self.to_upper_camel_case() + camel_suffix
+
+ def to_enum_value(self):
+ """Represents this name as an enum value in Blink C++ style.
+
+ i.e. kUpperCamelCase
+ """
+ return 'k' + self.to_upper_camel_case()
diff --git a/chromium/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter_test.py b/chromium/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter_test.py
index 1b343b7086a..d3d5944b674 100644
--- a/chromium/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter_test.py
+++ b/chromium/third_party/blink/renderer/build/scripts/blinkbuild/name_style_converter_test.py
@@ -111,6 +111,11 @@ class SmartTokenizerTest(unittest.TestCase):
self.assertEqual(tokenize_name('matrix3d'), ['matrix', '3d'])
+ self.assertEqual(tokenize_name('uint8ArrayMember'), ['uint8', 'Array', 'Member'])
+ self.assertEqual(tokenize_name('webgl2Element'), ['webgl2', 'Element'])
+ self.assertEqual(tokenize_name('webGL2Element'), ['webGL2', 'Element'])
+ self.assertEqual(tokenize_name('xssError'), ['xss', 'Error'])
+
def test_ignoring_characters(self):
self.assertEqual(tokenize_name('Animation.idl'), ['Animation', 'idl'])
self.assertEqual(tokenize_name('-webkit-appearance'), ['webkit', 'appearance'])
@@ -118,10 +123,21 @@ class SmartTokenizerTest(unittest.TestCase):
class NameStyleConverterTest(unittest.TestCase):
+ def test_original(self):
+ self.assertEqual(NameStyleConverter('-webkit-appearance').original, '-webkit-appearance')
+
def test_snake_case(self):
converter = NameStyleConverter('HTMLElement')
self.assertEqual(converter.to_snake_case(), 'html_element')
+ def test_to_class_data_member(self):
+ converter = NameStyleConverter('HTMLElement')
+ self.assertEqual(converter.to_class_data_member(), 'html_element_')
+ self.assertEqual(converter.to_class_data_member(prefix='is'), 'is_html_element_')
+ self.assertEqual(converter.to_class_data_member(suffix='enabled'), 'html_element_enabled_')
+ self.assertEqual(converter.to_class_data_member(prefix='is', suffix='enabled'), 'is_html_element_enabled_')
+ self.assertEqual(converter.to_class_data_member(prefix='fooBar', suffix='V0V8'), 'foobar_html_element_v0v8_')
+
def test_upper_camel_case(self):
converter = NameStyleConverter('someSuperThing')
self.assertEqual(converter.to_upper_camel_case(), 'SomeSuperThing')
@@ -134,6 +150,24 @@ class NameStyleConverterTest(unittest.TestCase):
converter = NameStyleConverter('feDropShadow')
self.assertEqual(converter.to_upper_camel_case(), 'FEDropShadow')
+ def test_to_class_name(self):
+ self.assertEqual(NameStyleConverter('').to_class_name(), '')
+ self.assertEqual(NameStyleConverter('').to_class_name(prefix='s', suffix='d'), 'SD')
+ self.assertEqual(NameStyleConverter('').to_class_name(prefix='style', suffix='data'), 'StyleData')
+ self.assertEqual(NameStyleConverter('foo').to_class_name(prefix='style', suffix='data'), 'StyleFooData')
+ self.assertEqual(NameStyleConverter('xpath').to_class_name(), 'XPath')
+
+ def test_to_function_name(self):
+ converter = NameStyleConverter('fooBar')
+ self.assertEqual(converter.to_function_name(), 'FooBar')
+ self.assertEqual(converter.to_function_name(prefix='is'), 'IsFooBar')
+ self.assertEqual(converter.to_function_name(suffix='BAZ'), 'FooBarBaz')
+ self.assertEqual(converter.to_function_name(prefix='IS', suffix='baz'), 'IsFooBarBaz')
+ self.assertEqual(converter.to_function_name(prefix='prefixPrefix', suffix=['a', 'b']), 'PrefixprefixFooBarAB')
+
+ def test_to_enum_value(self):
+ self.assertEqual(NameStyleConverter('fooBar').to_enum_value(), 'kFooBar')
+
def test_lower_camel_case(self):
converter = NameStyleConverter('someSuperThing')
self.assertEqual(converter.to_lower_camel_case(), 'someSuperThing')
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/css_properties.py b/chromium/third_party/blink/renderer/build/scripts/core/css/css_properties.py
index fb0fa4673d8..9f807287a88 100755
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/css_properties.py
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/css_properties.py
@@ -3,15 +3,10 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import json5_generator
-from name_utilities import (
- upper_camel_case,
- lower_camel_case,
- enum_value_name,
- enum_for_css_property,
- enum_for_css_property_alias
-)
+from blinkbuild.name_style_converter import NameStyleConverter
from core.css.field_alias_expander import FieldAliasExpander
+import json5_generator
+from name_utilities import enum_for_css_property, enum_for_css_property_alias
# These values are converted using CSSPrimitiveValue in the setter function,
@@ -122,9 +117,9 @@ class CSSProperties(object):
# This order must match the order in CSSPropertyPriority.h.
priority_numbers = {'Animation': 0, 'High': 1, 'Low': 2}
priority = priority_numbers[property_['priority']]
- name_without_leading_dash = property_['name']
- if property_['name'].startswith('-'):
- name_without_leading_dash = property_['name'][1:]
+ name_without_leading_dash = property_['name'].original
+ if name_without_leading_dash.startswith('-'):
+ name_without_leading_dash = name_without_leading_dash[1:]
property_['sorting_key'] = (priority, name_without_leading_dash)
sorting_keys = {}
@@ -134,8 +129,8 @@ class CSSProperties(object):
('Collision detected - two properties have the same name and '
'priority, a potentially non-deterministic ordering can '
'occur: {}, {} and {}'.format(
- key, property_['name'], sorting_keys[key]))
- sorting_keys[key] = property_['name']
+ key, property_['name'].original, sorting_keys[key]))
+ sorting_keys[key] = property_['name'].original
self._longhands.sort(key=lambda p: p['sorting_key'])
self._shorthands.sort(key=lambda p: p['sorting_key'])
@@ -164,13 +159,11 @@ class CSSProperties(object):
updated_alias = aliased_property.copy()
updated_alias['name'] = alias['name']
updated_alias['alias_for'] = alias['alias_for']
- updated_alias['aliased_property'] = aliased_property['upper_camel_name']
+ updated_alias['aliased_property'] = aliased_property['name'].to_upper_camel_case()
updated_alias['property_id'] = enum_for_css_property_alias(
alias['name'])
updated_alias['enum_value'] = aliased_property['enum_value'] + \
self._alias_offset
- updated_alias['upper_camel_name'] = upper_camel_case(alias['name'])
- updated_alias['lower_camel_name'] = lower_camel_case(alias['name'])
self._aliases[i] = updated_alias
def expand_parameters(self, property_):
@@ -179,27 +172,26 @@ class CSSProperties(object):
property_[key] = value
# Basic info.
- property_['property_id'] = enum_for_css_property(property_['name'])
- property_['upper_camel_name'] = upper_camel_case(property_['name'])
- property_['lower_camel_name'] = lower_camel_case(property_['name'])
- property_['is_internal'] = property_['name'].startswith('-internal-')
- name = property_['name_for_methods']
- if not name:
- name = upper_camel_case(property_['name']).replace('Webkit', '')
+ name = property_['name']
+ property_['property_id'] = enum_for_css_property(name)
+ property_['is_internal'] = name.original.startswith('-internal-')
+ method_name = property_['name_for_methods']
+ if not method_name:
+ method_name = name.to_upper_camel_case().replace('Webkit', '')
set_if_none(property_, 'inherited', False)
# Initial function, Getters and Setters for ComputedStyle.
- property_['initial'] = 'Initial' + name
+ property_['initial'] = 'Initial' + method_name
simple_type_name = str(property_['type_name']).split('::')[-1]
- set_if_none(property_, 'name_for_methods', name)
- set_if_none(property_, 'type_name', 'E' + name)
+ set_if_none(property_, 'name_for_methods', method_name)
+ set_if_none(property_, 'type_name', 'E' + method_name)
set_if_none(
property_,
'getter',
- name if simple_type_name != name else 'Get' + name)
- set_if_none(property_, 'setter', 'Set' + name)
+ method_name if simple_type_name != method_name else 'Get' + method_name)
+ set_if_none(property_, 'setter', 'Set' + method_name)
if property_['inherited']:
- property_['is_inherited_setter'] = 'Set' + name + 'IsInherited'
+ property_['is_inherited_setter'] = 'Set' + method_name + 'IsInherited'
# Figure out whether we should generate style builder implementations.
for x in ['initial', 'inherit', 'value']:
@@ -219,8 +211,8 @@ class CSSProperties(object):
type_name = property_['type_name']
if (property_['field_template'] == 'keyword' or
property_['field_template'] == 'multi_keyword'):
- default_value = type_name + '::' + \
- enum_value_name(property_['default_value'])
+ default_value = (type_name + '::' + NameStyleConverter(
+ property_['default_value']).to_enum_value())
elif (property_['field_template'] == 'external' or
property_['field_template'] == 'primitive' or
property_['field_template'] == 'pointer'):
@@ -245,6 +237,9 @@ class CSSProperties(object):
set_if_none(property_, 'custom_compare', False)
set_if_none(property_, 'mutable', False)
+ if property_['direction_aware_options'] and not property_['style_builder_template']:
+ property_['style_builder_template'] = 'direction_aware'
+
@property
def default_parameters(self):
return self._default_parameters
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/make_css_value_keywords.py b/chromium/third_party/blink/renderer/build/scripts/core/css/make_css_value_keywords.py
index 199fc96d68b..c9ea5d05b8f 100755
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/make_css_value_keywords.py
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/make_css_value_keywords.py
@@ -24,10 +24,10 @@ class CSSValueKeywordsWriter(json5_generator.Writer):
self._value_keywords = self.json5_file.name_dictionaries
first_keyword_id = 1
for offset, keyword in enumerate(self._value_keywords):
- keyword['lower_name'] = keyword['name'].lower()
+ keyword['lower_name'] = keyword['name'].original.lower()
keyword['enum_name'] = enum_for_css_keyword(keyword['name'])
keyword['enum_value'] = first_keyword_id + offset
- if keyword['name'].startswith('-internal-'):
+ if keyword['name'].original.startswith('-internal-'):
assert keyword['mode'] is None, 'Can\'t specify mode for ' \
'value keywords with the prefix "-internal-".'
keyword['mode'] = 'UASheet'
@@ -42,7 +42,7 @@ class CSSValueKeywordsWriter(json5_generator.Writer):
'value_keywords': self._value_keywords,
'value_keywords_count': self._keyword_count,
'max_value_keyword_length':
- max(len(keyword['name']) for keyword in self._value_keywords),
+ max(len(keyword['name'].original) for keyword in self._value_keywords),
}
def _value_keywords_with_mode(self, mode):
@@ -59,7 +59,7 @@ class CSSValueKeywordsWriter(json5_generator.Writer):
current_offset = 0
for keyword in self._value_keywords:
keyword_offsets.append(current_offset)
- current_offset += len(keyword["name"]) + 1
+ current_offset += len(keyword["name"].original) + 1
return {
'value_keywords': self._value_keywords,
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/make_media_features.py b/chromium/third_party/blink/renderer/build/scripts/core/css/make_media_features.py
index 969641970d9..487e6b3f732 100755
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/make_media_features.py
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/make_media_features.py
@@ -8,10 +8,10 @@ import os
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
+from blinkbuild.name_style_converter import NameStyleConverter
import media_feature_symbol
import json5_generator
import template_expander
-import name_utilities
class MakeMediaFeaturesWriter(json5_generator.Writer):
@@ -21,8 +21,7 @@ class MakeMediaFeaturesWriter(json5_generator.Writer):
}
filters = {
'symbol': media_feature_symbol.getMediaFeatureSymbolWithSuffix(''),
- 'to_macro_style': name_utilities.to_macro_style,
- 'upper_first_letter': name_utilities.upper_first_letter,
+ 'to_function_name': lambda symbol: NameStyleConverter(symbol).to_function_name(),
}
def __init__(self, json5_file_path, output_dir):
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/make_style_shorthands.py b/chromium/third_party/blink/renderer/build/scripts/core/css/make_style_shorthands.py
index 5015606ecbf..11e80e2c5c9 100755
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/make_style_shorthands.py
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/make_style_shorthands.py
@@ -65,7 +65,7 @@ class StylePropertyShorthandWriter(json5_generator.Writer):
# alphabetically
longhands.sort(
key=lambda property_: (
- -len(property_['longhand_property_ids']), property_['name'])
+ -len(property_['longhand_property_ids']), property_['name'].original)
)
@template_expander.use_jinja(
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/parser/make_atrule_names.py b/chromium/third_party/blink/renderer/build/scripts/core/css/parser/make_atrule_names.py
index a083c4d095f..2715f4dcf18 100755
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/parser/make_atrule_names.py
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/parser/make_atrule_names.py
@@ -11,8 +11,6 @@ import gperf
import json5_generator
import template_expander
-from name_utilities import upper_camel_case
-
class AtRuleNamesWriter(json5_generator.Writer):
"""
@@ -38,13 +36,11 @@ class AtRuleNamesWriter(json5_generator.Writer):
chars_used = 0
self._longest_name_length = 0
for offset, descriptor in enumerate(self._descriptors):
- descriptor['upper_camel_name'] = upper_camel_case(
- descriptor['name'])
descriptor['enum_value'] = first_descriptor_id + offset
self._character_offsets.append(chars_used)
- chars_used += len(descriptor['name'])
+ chars_used += len(descriptor['name'].original)
self._longest_name_length = max(
- len(descriptor['name']),
+ len(descriptor['name'].original),
len(descriptor['alias']),
self._longest_name_length)
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/parser/templates/at_rule_descriptors.cc.tmpl b/chromium/third_party/blink/renderer/build/scripts/core/css/parser/templates/at_rule_descriptors.cc.tmpl
index 14db20859de..225ca7969a7 100644
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/parser/templates/at_rule_descriptors.cc.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/parser/templates/at_rule_descriptors.cc.tmpl
@@ -35,9 +35,9 @@ struct Property;
%enum
%%
{% for descriptor in descriptors %}
-{{descriptor.name}}, static_cast<int>(AtRuleDescriptorID::{{descriptor.upper_camel_name}})
+{{descriptor.name}}, static_cast<int>(AtRuleDescriptorID::{{descriptor.name.to_upper_camel_case()}})
{% if descriptor.alias %}
-{{descriptor.alias}}, static_cast<int>(AtRuleDescriptorID::{{descriptor.upper_camel_name}})
+{{descriptor.alias}}, static_cast<int>(AtRuleDescriptorID::{{descriptor.name.to_upper_camel_case()}})
{% endif %}
{% endfor %}
%%
@@ -84,8 +84,8 @@ AtRuleDescriptorID AsAtRuleDescriptorID(StringView string) {
CSSPropertyID AtRuleDescriptorIDAsCSSPropertyID(AtRuleDescriptorID id) {
switch (id) {
{% for descriptor in descriptors %}
- case AtRuleDescriptorID::{{descriptor.upper_camel_name}}:
- return CSSProperty{{descriptor.upper_camel_name}};
+ case AtRuleDescriptorID::{{descriptor.name.to_upper_camel_case()}}:
+ return CSSProperty{{descriptor.name.to_upper_camel_case()}};
{% endfor %}
default:
NOTREACHED();
@@ -96,8 +96,8 @@ CSSPropertyID AtRuleDescriptorIDAsCSSPropertyID(AtRuleDescriptorID id) {
AtRuleDescriptorID CSSPropertyIDAsAtRuleDescriptor(CSSPropertyID id) {
switch (id) {
{% for descriptor in descriptors %}
- case CSSProperty{{descriptor.upper_camel_name}}:
- return AtRuleDescriptorID::{{descriptor.upper_camel_name}};
+ case CSSProperty{{descriptor.name.to_upper_camel_case()}}:
+ return AtRuleDescriptorID::{{descriptor.name.to_upper_camel_case()}};
{% endfor %}
default:
NOTREACHED();
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/parser/templates/at_rule_descriptors.h.tmpl b/chromium/third_party/blink/renderer/build/scripts/core/css/parser/templates/at_rule_descriptors.h.tmpl
index a8ad2854415..0e41a3e1031 100644
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/parser/templates/at_rule_descriptors.h.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/parser/templates/at_rule_descriptors.h.tmpl
@@ -14,7 +14,7 @@ namespace blink {
enum class AtRuleDescriptorID {
Invalid = 0,
{% for descriptor in descriptors %}
- {{descriptor.upper_camel_name}} = {{descriptor.enum_value}},
+ {{descriptor.name.to_upper_camel_case()}} = {{descriptor.enum_value}},
{% endfor %}
};
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_base.py b/chromium/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_base.py
index 9f7309f112e..8399000b7f2 100755
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_base.py
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_base.py
@@ -12,7 +12,6 @@ import template_expander
from collections import namedtuple
from core.css import css_properties
-from name_utilities import snake_case
class PropertyClassData(
@@ -73,9 +72,9 @@ class CSSPropertyBaseWriter(json5_generator.Writer):
return PropertyClassData(
enum_value=property_['enum_value'],
property_id=property_['property_id'],
- classname=property_['upper_camel_name'],
+ classname=property_['name'].to_upper_camel_case(),
namespace_group=namespace_group,
- filename=snake_case(property_['upper_camel_name']))
+ filename=property_['name'].to_snake_case())
@property
def css_properties(self):
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_subclasses.py b/chromium/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_subclasses.py
index b9a8c3ce0e8..6f8788f3404 100755
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_subclasses.py
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/properties/make_css_property_subclasses.py
@@ -32,8 +32,8 @@ class CSSPropertiesWriter(CSSPropertyBaseWriter):
property_methods = json5_generator.Json5File.load_from_files(
[json5_file_paths[2]])
for property_method in property_methods.name_dictionaries:
- self._property_methods[property_method['name']] = PropertyMethod(
- name=property_method['name'],
+ self._property_methods[property_method['name'].original] = PropertyMethod(
+ name=property_method['name'].original,
return_type=property_method['return_type'],
parameters=property_method['parameters'],
)
@@ -56,7 +56,7 @@ class CSSPropertiesWriter(CSSPropertyBaseWriter):
self._outputs[class_data.filename + '.h'] = (
self.generate_property_h_builder(
class_data.classname, class_data.filename, property_))
- if 'should_implement_apply_functions_in_cpp' in property_:
+ if not property_['style_builder_inline']:
self._outputs[class_data.filename + '.cc'] = (
self.generate_property_cpp_builder(
class_data.filename, property_))
@@ -97,15 +97,17 @@ class CSSPropertiesWriter(CSSPropertyBaseWriter):
return generate_property_cpp
def calculate_apply_functions_to_declare(self, property_):
- if property_['style_builder_template'] in ['background_layer', 'color', 'counter', 'mask_layer']:
- property_['should_implement_apply_functions_in_cpp'] = True
+ cc_templates = ['background_layer', 'color', 'counter', 'grid', 'mask_layer']
+ property_['style_builder_inline'] = property_['style_builder_template'] not in cc_templates
- property_['should_implement_apply_functions'] = (
+ property_['style_builder_declare'] = (
property_['is_property'] and
- not property_['longhands'] and
- not property_['direction_aware_options'] and
- not property_['builder_skip'] and
- not property_['style_builder_legacy'])
+ not property_['longhands'])
+
+ if not property_['style_builder_declare']:
+ for x in ['initial', 'inherit', 'value']:
+ property_['style_builder_generate_%s' % x] = False
+
def h_includes(self, property_):
if property_['alias_for']:
@@ -120,7 +122,7 @@ class CSSPropertiesWriter(CSSPropertyBaseWriter):
yield "third_party/blink/renderer/platform/runtime_enabled_features.h"
def cpp_includes(self, property_):
- if 'should_implement_apply_functions_in_cpp' in property_:
+ if not property_['style_builder_inline']:
for include in self.apply_includes(property_):
yield 'third_party/blink/renderer/' + include
@@ -132,6 +134,9 @@ class CSSPropertiesWriter(CSSPropertyBaseWriter):
yield "core/css/css_primitive_value_mappings.h"
elif property_['converter'] == "CSSIdentifierValue":
yield "core/css/css_identifier_value.h"
+ elif property_['converter'] == "ConvertElementReference":
+ yield "core/css/resolver/style_builder_converter.h"
+ yield "core/style/style_svg_resource.h"
else:
yield "core/css/css_primitive_value_mappings.h"
yield "core/css/resolver/style_builder_converter.h"
@@ -153,7 +158,8 @@ class CSSPropertiesWriter(CSSPropertyBaseWriter):
if property_.get('style_builder_template') in ['counter']:
yield "core/css/css_value_pair.h"
yield "core/css/css_custom_ident_value.h"
-
+ if property_.get('style_builder_template') in ['grid']:
+ yield "core/css/resolver/style_builder_converter.h"
if __name__ == '__main__':
json5_generator.Maker(CSSPropertiesWriter).main()
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property.h.tmpl b/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property.h.tmpl
index 0465168f963..1947b2ffc35 100644
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property.h.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property.h.tmpl
@@ -58,6 +58,7 @@ class CSSProperty : public CSSUnresolvedProperty {
virtual bool IsAffectedByAll() const { return IsEnabled() && IsProperty(); }
virtual bool IsLayoutDependentProperty() const { return false; }
virtual bool IsLayoutDependent(const ComputedStyle* style, LayoutObject* layout_object) const { return false; }
+ virtual bool IsValidForVisitedLink() const { return false; }
// Properties that do not override this method:
// CSSPropertyWebkitFontSizeDelta
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_subclass.cc.tmpl b/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_subclass.cc.tmpl
index af83d306752..3647ca60c02 100644
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_subclass.cc.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_subclass.cc.tmpl
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-{% from 'core/css/properties/templates/style_builder_functions.tmpl' import declare_initial, declare_inherit, declare_value, set_value %}
+{% from 'core/css/properties/templates/style_builder_functions.tmpl' import style_builder_functions %}
{% from 'templates/macros.tmpl' import source_files_for_generated_file %}
{{source_files_for_generated_file(template_file, input_files)}}
@@ -15,147 +15,7 @@
namespace blink {
namespace CSSLonghand {
-{% if property.style_builder_template in ['background_layer', 'mask_layer'] %}
-{% set layer_type = 'Background' if property.style_builder_template == 'background_layer' else 'Mask' %}
-{% set fill_type = property.style_builder_template_args['fill_type'] %}
-{% set fill_type_getter = property.style_builder_template_args['fill_type_getter'] or fill_type %}
-{{declare_initial(property.upper_camel_name)}} {
- FillLayer* currChild = &state.Style()->Access{{layer_type}}Layers();
- currChild->Set{{fill_type}}(FillLayer::InitialFill{{fill_type}}(EFillLayerType::k{{layer_type}}));
- for (currChild = currChild->Next(); currChild; currChild = currChild->Next())
- currChild->Clear{{fill_type}}();
-}
-
-{{declare_inherit(property.upper_camel_name)}} {
- FillLayer* currChild = &state.Style()->Access{{layer_type}}Layers();
- FillLayer* prevChild = 0;
- const FillLayer* currParent = &state.ParentStyle()->{{layer_type}}Layers();
- while (currParent && currParent->Is{{fill_type}}Set()) {
- if (!currChild)
- currChild = prevChild->EnsureNext();
- currChild->Set{{fill_type}}(currParent->{{fill_type_getter}}());
- {% if fill_type == "PositionX" %}
- if (currParent->IsBackgroundXOriginSet())
- currChild->SetBackgroundXOrigin(currParent->BackgroundXOrigin());
- {% endif %}
- {% if fill_type == "PositionY" %}
- if (currParent->IsBackgroundYOriginSet())
- currChild->SetBackgroundYOrigin(currParent->BackgroundYOrigin());
- {% endif %}
- prevChild = currChild;
- currChild = prevChild->Next();
- currParent = currParent->Next();
- }
-
- while (currChild) {
- // Reset any remaining layers to not have the property set.
- currChild->Clear{{fill_type}}();
- currChild = currChild->Next();
- }
-}
-
-{{declare_value(property.upper_camel_name)}} {
- FillLayer* currChild = &state.Style()->Access{{layer_type}}Layers();
- FillLayer* prevChild = 0;
- if (value.IsValueList() && !value.IsImageSetValue()) {
- // Walk each value and put it into a layer, creating new layers as needed.
- const CSSValueList& valueList = ToCSSValueList(value);
- for (unsigned int i = 0; i < valueList.length(); i++) {
- if (!currChild)
- currChild = prevChild->EnsureNext();
- CSSToStyleMap::MapFill{{fill_type}}(state, currChild, valueList.Item(i));
- prevChild = currChild;
- currChild = currChild->Next();
- }
- } else {
- CSSToStyleMap::MapFill{{fill_type}}(state, currChild, value);
- currChild = currChild->Next();
- }
- while (currChild) {
- // Reset all remaining layers to not have the property set.
- currChild->Clear{{fill_type}}();
- currChild = currChild->Next();
- }
-}
-{% elif property.style_builder_template == 'color' %}
-{% set initial_color = property.style_builder_template_args['initial_color'] or 'StyleColor::CurrentColor' %}
-{% set visited_link_setter = 'SetVisitedLink' + property.name_for_methods %}
-{{declare_initial(property.upper_camel_name)}} {
- StyleColor color = {{initial_color}}();
- if (state.ApplyPropertyToRegularStyle())
- {{set_value(property)}}(color);
- if (state.ApplyPropertyToVisitedLinkStyle())
- state.Style()->{{visited_link_setter}}(color);
-}
-
-{{declare_inherit(property.upper_camel_name)}} {
- // Visited link style can never explicitly inherit from parent visited link
- // style so no separate getters are needed.
- StyleColor color = state.ParentStyle()->{{property.getter}}();
- if (state.ApplyPropertyToRegularStyle())
- {{set_value(property)}}(color);
- if (state.ApplyPropertyToVisitedLinkStyle())
- state.Style()->{{visited_link_setter}}(color);
-}
-
-{{declare_value(property.upper_camel_name)}} {
- if (state.ApplyPropertyToRegularStyle())
- {{set_value(property)}}(StyleBuilderConverter::{{property.converter}}(state, value));
- if (state.ApplyPropertyToVisitedLinkStyle()) {
- state.Style()->{{visited_link_setter}}(
- StyleBuilderConverter::{{property.converter}}(state, value, true));
- }
-}
-{% elif property.style_builder_template == 'counter' %}
-{% set action = property.style_builder_template_args['action'] %}
-{{declare_initial(property.upper_camel_name)}} {
- state.Style()->Clear{{action}}Directives();
-}
-
-{{declare_inherit(property.upper_camel_name)}} {
- const CounterDirectiveMap* parentMap = state.ParentStyle()->GetCounterDirectives();
- if (!parentMap)
- return;
-
- CounterDirectiveMap& map = state.Style()->AccessCounterDirectives();
- DCHECK(!parentMap->IsEmpty());
-
- typedef CounterDirectiveMap::const_iterator Iterator;
- Iterator end = parentMap->end();
- for (Iterator it = parentMap->begin(); it != end; ++it) {
- CounterDirectives& directives = map.insert(it->key, CounterDirectives()).stored_value->value;
- directives.Inherit{{action}}(it->value);
- }
-}
-
-{{declare_value(property.upper_camel_name)}} {
- state.Style()->Clear{{action}}Directives();
-
- if (!value.IsValueList()) {
- DCHECK(value.IsIdentifierValue());
- DCHECK_EQ(ToCSSIdentifierValue(value).GetValueID(), CSSValueNone);
- return;
- }
-
- CounterDirectiveMap& map = state.Style()->AccessCounterDirectives();
-
- const CSSValueList& list = ToCSSValueList(value);
-
- for (size_t i = 0; i < list.length(); ++i) {
- const CSSValuePair& pair = ToCSSValuePair(list.Item(i));
- AtomicString identifier(ToCSSCustomIdentValue(pair.First()).Value());
- int counter_value = ToCSSPrimitiveValue(pair.Second()).GetIntValue();
- CounterDirectives& directives =
- map.insert(identifier, CounterDirectives()).stored_value->value;
- {% if action == 'Reset' %}
- directives.SetResetValue(counter_value);
- {% else %}
- directives.AddIncrementValue(counter_value);
- {% endif %}
- }
- DCHECK(!map.IsEmpty());
-}
-{% endif %}
+{{style_builder_functions(property, false)}}
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_subclass.h.tmpl b/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_subclass.h.tmpl
index ae5c2740e5a..fd32fbc302c 100644
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_subclass.h.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/css_property_subclass.h.tmpl
@@ -80,6 +80,9 @@ class {{property_classname}} final : public {{property.namespace_group}} {
{% if not property.affected_by_all %}
bool IsAffectedByAll() const override { return false; }
{% endif %}
+ {% if property.valid_for_visited_link %}
+ bool IsValidForVisitedLink() const override { return true; }
+ {% endif %}
{% if property.direction_aware_options %}
const CSSValue* CSSValueFromComputedStyleInternal(
const ComputedStyle& ,
@@ -119,10 +122,10 @@ class {{property_classname}} final : public {{property.namespace_group}} {
}
{% endif %}
{% endif %}
- {% if property.should_implement_apply_functions %}
+ {% if property.style_builder_declare %}
// Style builder functions
-{{style_builder_functions(property)}}
+{{style_builder_functions(property, true)}}
{%- endif %}
{% endif %}
};
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl b/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl
index 832acd8bd9f..e10f98b0b49 100644
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl
@@ -12,6 +12,45 @@ void {{prefix ~ '::' if prefix}}ApplyInherit(StyleResolverState& state) const{{'
void {{prefix ~ '::' if prefix}}ApplyValue(StyleResolverState& state, const CSSValue& value) const{{' override' if not prefix}}
{%- endmacro %}
+{% macro apply_initial(property, header) %}
+ {% set spaces = 2 if header else 0 %}
+ {% if property.style_builder_declare %}
+ {% if property.style_builder_inline == header and property.style_builder_generate_initial %}
+{{declare_initial(property.name.to_upper_camel_case() if not header)|indent(spaces, true)}} {
+{{caller(property)|indent(spaces, true)-}}
+{{'}'|indent(spaces, true)}}
+ {% else %}
+{{declare_initial()|indent(spaces, true)-}};
+ {% endif %}
+ {% endif %}
+{% endmacro %}
+
+{% macro apply_inherit(property, header) %}
+ {% set spaces = 2 if header else 0 %}
+ {% if property.style_builder_declare %}
+ {% if property.style_builder_inline == header and property.style_builder_generate_inherit %}
+{{declare_inherit(property.name.to_upper_camel_case() if not header)|indent(spaces, true)}} {
+{{caller(property)|indent(spaces, true)-}}
+{{'}'|indent(spaces, true)}}
+ {% else %}
+{{declare_inherit()|indent(spaces, true)-}};
+ {% endif %}
+ {% endif %}
+{% endmacro %}
+
+{% macro apply_value(property, header) %}
+ {% set spaces = 2 if header else 0 %}
+ {% if property.style_builder_declare %}
+ {% if property.style_builder_inline == header and property.style_builder_generate_value %}
+{{declare_value(property.name.to_upper_camel_case() if not header)|indent(spaces, true)}} {
+{{caller(property)|indent(spaces, true)-}}
+{{'}'|indent(spaces, true)}}
+ {% else %}
+{{declare_value()|indent(spaces, true)-}};
+ {% endif %}
+ {% endif %}
+{% endmacro %}
+
{% macro set_value(property) %}
{% if property.svg %}
state.Style()->AccessSVGStyle().{{property.setter}}
@@ -32,176 +71,410 @@ state.Style()->{{property.setter}}
{%- endif %}
{% endmacro %}
-{% macro style_builder_functions(property) %}
- {% if property.should_implement_apply_functions_in_cpp %}
- {# declaration only #}
- {{declare_initial()}};
- {{declare_inherit()}};
- {{declare_value()}};
- {% else %}
- {# full implementation #}
- {% if not property.style_builder_template %}
- {% if property.style_builder_generate_initial %}
- {{declare_initial()}} {
- {% if property.svg %}
- {{set_value(property)}}(SVGComputedStyle::{{property.initial}}());
- {% elif property.font %}
- {{set_value(property)}}(FontBuilder::{{property.initial}}());
- {% else %}
- {{set_value(property)}}(ComputedStyleInitialValues::{{property.initial}}());
- {% endif %}
- {% if property.independent %}
- state.Style()->{{property.is_inherited_setter}}(false);
- {% endif %}
- }
+{% macro resolve_directional_property(apply_call) %}
+const CSSProperty& resolved_property =
+ ResolveDirectionAwareProperty(state.Style()->Direction(),
+ state.Style()->GetWritingMode());
+DCHECK(!resolved_property.IDEquals(PropertyID()));
+ToLonghand(resolved_property).{{apply_call}};
+{% endmacro %}
+
+{% macro style_builder_functions(property, header) %}
+ {% if not property.style_builder_template %}
+ {% call(property) apply_initial(property, header) %}
+ {% if property.svg %}
+ {{set_value(property)}}(SVGComputedStyle::{{property.initial}}());
+ {% elif property.font %}
+ {{set_value(property)}}(FontBuilder::{{property.initial}}());
+ {% else %}
+ {{set_value(property)}}(ComputedStyleInitialValues::{{property.initial}}());
{% endif %}
- {% if property.style_builder_generate_inherit %}
- {{declare_inherit()}} {
- {% if property.svg %}
- {{set_value(property)}}(state.ParentStyle()->SvgStyle().{{property.getter}}());
- {% elif property.font %}
- {{set_value(property)}}(state.ParentFontDescription().{{property.getter}}());
- {% else %}
- {{set_value(property)}}(state.ParentStyle()->{{property.getter}}());
- {% endif %}
- {% if property.independent %}
- state.Style()->{{property.is_inherited_setter}}(true);
- {% endif %}
- }
+ {% if property.independent %}
+ state.Style()->{{property.is_inherited_setter}}(false);
{% endif %}
- {% if property.style_builder_generate_value %}
- {{declare_value()}} {
- {{convert_and_set_value(property)}}
- {% if property.independent %}
- state.Style()->{{property.is_inherited_setter}}(false);
- {% endif %}
- }
+ {% endcall %}
+ {% call(property) apply_inherit(property, header) %}
+ {% if property.svg %}
+ {{set_value(property)}}(state.ParentStyle()->SvgStyle().{{property.getter}}());
+ {% elif property.font %}
+ {{set_value(property)}}(state.ParentFontDescription().{{property.getter}}());
+ {% else %}
+ {{set_value(property)}}(state.ParentStyle()->{{property.getter}}());
+ {% endif %}
+ {% if property.independent %}
+ state.Style()->{{property.is_inherited_setter}}(true);
{% endif %}
- {% elif property.style_builder_template == "auto" %}
- {% set auto_getter = property.style_builder_template_args['auto_getter'] or
- 'HasAuto' + property.name_for_methods %}
- {% set auto_setter = property.style_builder_template_args['auto_setter'] or
- 'SetHasAuto' + property.name_for_methods %}
- {{declare_initial()}} {
+ {% endcall %}
+ {% call(property) apply_value(property, header) %}
+ {{convert_and_set_value(property)}}
+ {% if property.independent %}
+ state.Style()->{{property.is_inherited_setter}}(false);
+ {% endif %}
+ {% endcall %}
+ {% elif property.style_builder_template == 'empty' %}
+ {% call(property) apply_initial(property, header) %}
+ // Intentionally empty.
+ {% endcall %}
+ {% call(property) apply_inherit(property, header) %}
+ // Intentionally empty.
+ {% endcall %}
+ {% call(property) apply_value(property, header) %}
+ // Intentionally empty.
+ {% endcall %}
+ {% elif property.style_builder_template == 'direction_aware' %}
+ {% call(property) apply_initial(property, header) %}
+{{resolve_directional_property('ApplyInitial(state)')|indent(2, true) -}}
+ {% endcall %}
+ {% call(property) apply_inherit(property, header) %}
+{{resolve_directional_property('ApplyInherit(state)')|indent(2, true) -}}
+ {% endcall %}
+ {% call(property) apply_value(property, header) %}
+{{resolve_directional_property('ApplyValue(state, value)')|indent(2, true) -}}
+ {% endcall %}
+ {% elif property.style_builder_template == "auto" %}
+ {% set auto_getter = property.style_builder_template_args['auto_getter'] or
+ 'HasAuto' + property.name_for_methods %}
+ {% set auto_setter = property.style_builder_template_args['auto_setter'] or
+ 'SetHasAuto' + property.name_for_methods %}
+ {% call(property) apply_initial(property, header) %}
+ state.Style()->{{auto_setter}}();
+ {% endcall %}
+ {% call(property) apply_inherit(property, header) %}
+ if (state.ParentStyle()->{{auto_getter}}())
state.Style()->{{auto_setter}}();
- }
- {{declare_inherit()}} {
- if (state.ParentStyle()->{{auto_getter}}())
- state.Style()->{{auto_setter}}();
- else
- {{set_value(property)}}(state.ParentStyle()->{{property.getter}}());
- }
- {{declare_value()}} {
- if (value.IsIdentifierValue() &&
- ToCSSIdentifierValue(value).GetValueID() == CSSValueAuto)
- state.Style()->{{auto_setter}}();
- else
- {{convert_and_set_value(property)}}
- }
- {% elif property.style_builder_template in ['border_image', 'mask_box'] %}
+ else
+ {{set_value(property)}}(state.ParentStyle()->{{property.getter}}());
+ {% endcall %}
+ {% call(property) apply_value(property, header) %}
+ if (value.IsIdentifierValue() &&
+ ToCSSIdentifierValue(value).GetValueID() == CSSValueAuto)
+ state.Style()->{{auto_setter}}();
+ else
+ {{convert_and_set_value(property)}}
+ {% endcall %}
+ {% elif property.style_builder_template in ['border_image', 'mask_box'] %}
{% set is_mask_box = property.style_builder_template == 'mask_box' %}
{% set modifier_type = property.style_builder_template_args['modifier_type'] %}
{% set getter = 'MaskBoxImage' if is_mask_box else 'BorderImage' %}
{% set setter = 'Set' + getter %}
- {{declare_initial()}} {
- const NinePieceImage& currentImage = state.Style()->{{getter}}();
- {# Check for equality in case we can bail out before creating a new NinePieceImage. #}
+ {% call(property) apply_initial(property, header) %}
+ const NinePieceImage& current_image = state.Style()->{{getter}}();
+ {# Check for equality in case we can bail out before creating a new NinePieceImage. #}
{% if modifier_type == 'Outset' %}
- if (StyleBuildingUtils::borderImageLengthMatchesAllSides(currentImage.Outset(),
- BorderImageLength(Length(0, kFixed))))
- return;
+ if (StyleBuildingUtils::BorderImageLengthMatchesAllSides(current_image.Outset(),
+ BorderImageLength(Length(0, kFixed))))
+ return;
{% elif modifier_type == 'Repeat' %}
- if (currentImage.HorizontalRule() == kStretchImageRule &&
- currentImage.VerticalRule() == kStretchImageRule)
- return;
+ if (current_image.HorizontalRule() == kStretchImageRule &&
+ current_image.VerticalRule() == kStretchImageRule)
+ return;
{% elif modifier_type == 'Slice' and is_mask_box %}
- // Masks have a different initial value for slices. Preserve the value of 0
- // for backwards compatibility.
- if (currentImage.Fill() == true &&
- StyleBuildingUtils::lengthMatchesAllSides(currentImage.ImageSlices(), Length(0, kFixed)))
- return;
+ // Masks have a different initial value for slices. Preserve the value of 0
+ // for backwards compatibility.
+ if (current_image.Fill() == true &&
+ StyleBuildingUtils::LengthMatchesAllSides(current_image.ImageSlices(), Length(0, kFixed)))
+ return;
{% elif modifier_type == 'Slice' and not is_mask_box %}
- if (currentImage.Fill() == false &&
- StyleBuildingUtils::lengthMatchesAllSides(currentImage.ImageSlices(), Length(100, kPercent)))
- return;
+ if (current_image.Fill() == false &&
+ StyleBuildingUtils::LengthMatchesAllSides(current_image.ImageSlices(), Length(100, kPercent)))
+ return;
{% elif modifier_type == 'Width' and is_mask_box %}
- // Masks have a different initial value for widths. Preserve the value of
- // 'auto' for backwards compatibility.
- if (StyleBuildingUtils::borderImageLengthMatchesAllSides(currentImage.BorderSlices(),
- BorderImageLength(Length(kAuto))))
- return;
+ // Masks have a different initial value for widths. Preserve the value of
+ // 'auto' for backwards compatibility.
+ if (StyleBuildingUtils::BorderImageLengthMatchesAllSides(current_image.BorderSlices(),
+ BorderImageLength(Length(kAuto))))
+ return;
{% elif modifier_type == 'Width' and not is_mask_box %}
- if (StyleBuildingUtils::borderImageLengthMatchesAllSides(currentImage.BorderSlices(),
- BorderImageLength(1.0)))
- return;
+ if (StyleBuildingUtils::BorderImageLengthMatchesAllSides(current_image.BorderSlices(),
+ BorderImageLength(1.0)))
+ return;
{% endif %}
- NinePieceImage image(currentImage);
+ NinePieceImage image(current_image);
{% if modifier_type == 'Outset' %}
- image.SetOutset(Length(0, kFixed));
+ image.SetOutset(Length(0, kFixed));
{% elif modifier_type == 'Repeat' %}
- image.SetHorizontalRule(kStretchImageRule);
- image.SetVerticalRule(kStretchImageRule);
+ image.SetHorizontalRule(kStretchImageRule);
+ image.SetVerticalRule(kStretchImageRule);
{% elif modifier_type == 'Slice' and is_mask_box %}
- image.SetImageSlices(LengthBox({{ (['Length(0, kFixed)']*4) | join(', ') }}));
- image.SetFill(true);
+ image.SetImageSlices(LengthBox({{ (['Length(0, kFixed)']*4) | join(', ') }}));
+ image.SetFill(true);
{% elif modifier_type == 'Slice' and not is_mask_box %}
- image.SetImageSlices(LengthBox({{ (['Length(100, kPercent)']*4) | join(', ') }}));
- image.SetFill(false);
+ image.SetImageSlices(LengthBox({{ (['Length(100, kPercent)']*4) | join(', ') }}));
+ image.SetFill(false);
{% elif modifier_type == 'Width' %}
- image.SetBorderSlices({{ 'Length(kAuto)' if is_mask_box else '1.0' }});
+ image.SetBorderSlices({{ 'Length(kAuto)' if is_mask_box else '1.0' }});
{% endif %}
- state.Style()->{{setter}}(image);
- }
- {{declare_inherit()}} {
- NinePieceImage image(state.Style()->{{getter}}());
+ state.Style()->{{setter}}(image);
+ {% endcall %}
+ {% call(property) apply_inherit(property, header) %}
+ NinePieceImage image(state.Style()->{{getter}}());
{% if modifier_type == 'Outset' %}
- image.CopyOutsetFrom(state.ParentStyle()->{{getter}}());
+ image.CopyOutsetFrom(state.ParentStyle()->{{getter}}());
{% elif modifier_type == 'Repeat' %}
- image.CopyRepeatFrom(state.ParentStyle()->{{getter}}());
+ image.CopyRepeatFrom(state.ParentStyle()->{{getter}}());
{% elif modifier_type == 'Slice' %}
- image.CopyImageSlicesFrom(state.ParentStyle()->{{getter}}());
+ image.CopyImageSlicesFrom(state.ParentStyle()->{{getter}}());
{% elif modifier_type == 'Width' %}
- image.CopyBorderSlicesFrom(state.ParentStyle()->{{getter}}());
+ image.CopyBorderSlicesFrom(state.ParentStyle()->{{getter}}());
{% endif %}
- state.Style()->{{setter}}(image);
- }
- {{declare_value()}} {
- NinePieceImage image(state.Style()->{{getter}}());
+ state.Style()->{{setter}}(image);
+ {% endcall %}
+ {% call(property) apply_value(property, header) %}
+ NinePieceImage image(state.Style()->{{getter}}());
{% if modifier_type == 'Outset' %}
- image.SetOutset(CSSToStyleMap::MapNinePieceImageQuad(state, value));
+ image.SetOutset(CSSToStyleMap::MapNinePieceImageQuad(state, value));
{% elif modifier_type == 'Repeat' %}
- CSSToStyleMap::MapNinePieceImageRepeat(state, value, image);
+ CSSToStyleMap::MapNinePieceImageRepeat(state, value, image);
{% elif modifier_type == 'Slice' %}
- CSSToStyleMap::MapNinePieceImageSlice(state, value, image);
+ CSSToStyleMap::MapNinePieceImageSlice(state, value, image);
{% elif modifier_type == 'Width' %}
- image.SetBorderSlices(CSSToStyleMap::MapNinePieceImageQuad(state, value));
+ image.SetBorderSlices(CSSToStyleMap::MapNinePieceImageQuad(state, value));
{% endif %}
- state.Style()->{{setter}}(image);
- }
- {% elif property.style_builder_template in ['animation', 'transition'] %}
+ state.Style()->{{setter}}(image);
+ {% endcall %}
+ {% elif property.style_builder_template in ['animation', 'transition'] %}
{% set attribute = property.style_builder_template_args['attribute'] %}
{% set animation = 'Animation' if property.style_builder_template == 'animation' else 'Transition' %}
{% set vector = attribute + "List()" %}
- {{declare_initial()}} {
- CSS{{animation}}Data& data = state.Style()->Access{{animation}}s();
- data.{{vector}}.clear();
- data.{{vector}}.push_back(CSS{{animation}}Data::Initial{{attribute}}());
+ {% call(property) apply_initial(property, header) %}
+ CSS{{animation}}Data& data = state.Style()->Access{{animation}}s();
+ data.{{vector}}.clear();
+ data.{{vector}}.push_back(CSS{{animation}}Data::Initial{{attribute}}());
+ {% endcall %}
+
+ {% call(property) apply_inherit(property, header) %}
+ const CSS{{animation}}Data* parent_data = state.ParentStyle()->{{animation}}s();
+ if (!parent_data)
+ ApplyInitial{{property_id}}(state);
+ else
+ state.Style()->Access{{animation}}s().{{vector}} = parent_data->{{vector}};
+ {% endcall %}
+
+ {% call(property) apply_value(property, header) %}
+ CSS{{animation}}Data& data = state.Style()->Access{{animation}}s();
+ data.{{vector}}.clear();
+ for (auto& listValue : ToCSSValueList(value))
+ data.{{vector}}.push_back(CSSToStyleMap::MapAnimation{{attribute}}(*listValue));
+ {% endcall %}
+ {% elif property.style_builder_template == 'svg_paint' %}
+ {% set paint_type = property.style_builder_template_args['paint_type'] %}
+ {% set visited_link_setter = 'SetVisitedLink' + paint_type %}
+ {% call(property) apply_initial(property, header) %}
+ if (state.ApplyPropertyToRegularStyle())
+ {{set_value(property)}}(SVGComputedStyle::Initial{{paint_type}}());
+ if (state.ApplyPropertyToVisitedLinkStyle())
+ state.Style()->AccessSVGStyle().{{visited_link_setter}}(SVGComputedStyle::Initial{{paint_type}}());
+ {% endcall %}
+
+ {% call(property) apply_inherit(property, header) %}
+ const SVGComputedStyle& parent_svg_style = state.ParentStyle()->SvgStyle();
+ if (state.ApplyPropertyToRegularStyle())
+ {{set_value(property)}}(parent_svg_style.{{paint_type}}());
+ if (state.ApplyPropertyToVisitedLinkStyle())
+ state.Style()->AccessSVGStyle().{{visited_link_setter}}(parent_svg_style.{{paint_type}}());
+ {% endcall %}
+
+ {% call(property) apply_value(property, header) %}
+ SVGPaint paint = StyleBuilderConverter::{{property.converter}}(state, value);
+ if (state.ApplyPropertyToRegularStyle())
+ {{set_value(property)}}(paint);
+ if (state.ApplyPropertyToVisitedLinkStyle())
+ state.Style()->AccessSVGStyle().{{visited_link_setter}}(paint);
+ {% endcall %}
+ {% elif property.style_builder_template in ['background_layer', 'mask_layer'] %}
+ {% set layer_type = 'Background' if property.style_builder_template == 'background_layer' else 'Mask' %}
+ {% set fill_type = property.style_builder_template_args['fill_type'] %}
+ {% set fill_type_getter = property.style_builder_template_args['fill_type_getter'] or fill_type %}
+ {% call(property) apply_initial(property, header) %}
+ FillLayer* curr_child = &state.Style()->Access{{layer_type}}Layers();
+ curr_child->Set{{fill_type}}(FillLayer::InitialFill{{fill_type}}(EFillLayerType::k{{layer_type}}));
+ for (curr_child = curr_child->Next(); curr_child; curr_child = curr_child->Next())
+ curr_child->Clear{{fill_type}}();
+ {% endcall %}
+
+ {% call(property) apply_inherit(property, header) %}
+ FillLayer* curr_child = &state.Style()->Access{{layer_type}}Layers();
+ FillLayer* prev_child = 0;
+ const FillLayer* curr_parent = &state.ParentStyle()->{{layer_type}}Layers();
+ while (curr_parent && curr_parent->Is{{fill_type}}Set()) {
+ if (!curr_child)
+ curr_child = prev_child->EnsureNext();
+ curr_child->Set{{fill_type}}(curr_parent->{{fill_type_getter}}());
+ {% if fill_type == "PositionX" %}
+ if (curr_parent->IsBackgroundXOriginSet())
+ curr_child->SetBackgroundXOrigin(curr_parent->BackgroundXOrigin());
+ {% endif %}
+ {% if fill_type == "PositionY" %}
+ if (curr_parent->IsBackgroundYOriginSet())
+ curr_child->SetBackgroundYOrigin(curr_parent->BackgroundYOrigin());
+ {% endif %}
+ prev_child = curr_child;
+ curr_child = prev_child->Next();
+ curr_parent = curr_parent->Next();
}
- {{declare_inherit()}} {
- const CSS{{animation}}Data* parentData = state.ParentStyle()->{{animation}}s();
- if (!parentData)
- ApplyInitial{{property_id}}(state);
- else
- state.Style()->Access{{animation}}s().{{vector}} = parentData->{{vector}};
+ while (curr_child) {
+ // Reset any remaining layers to not have the property set.
+ curr_child->Clear{{fill_type}}();
+ curr_child = curr_child->Next();
}
+ {% endcall %}
- {{declare_value()}} {
- CSS{{animation}}Data& data = state.Style()->Access{{animation}}s();
- data.{{vector}}.clear();
- for (auto& listValue : ToCSSValueList(value))
- data.{{vector}}.push_back(CSSToStyleMap::MapAnimation{{attribute}}(*listValue));
+ {% call(property) apply_value(property, header) %}
+ FillLayer* curr_child = &state.Style()->Access{{layer_type}}Layers();
+ FillLayer* prev_child = 0;
+ if (value.IsValueList() && !value.IsImageSetValue()) {
+ // Walk each value and put it into a layer, creating new layers as needed.
+ const CSSValueList& valueList = ToCSSValueList(value);
+ for (unsigned int i = 0; i < valueList.length(); i++) {
+ if (!curr_child)
+ curr_child = prev_child->EnsureNext();
+ CSSToStyleMap::MapFill{{fill_type}}(state, curr_child, valueList.Item(i));
+ prev_child = curr_child;
+ curr_child = curr_child->Next();
+ }
+ } else {
+ CSSToStyleMap::MapFill{{fill_type}}(state, curr_child, value);
+ curr_child = curr_child->Next();
}
- {% endif %}
- {%- endif %}
+ while (curr_child) {
+ // Reset all remaining layers to not have the property set.
+ curr_child->Clear{{fill_type}}();
+ curr_child = curr_child->Next();
+ }
+ {% endcall %}
+ {% elif property.style_builder_template == 'color' %}
+ {% set initial_color = property.style_builder_template_args['initial_color'] or 'StyleColor::CurrentColor' %}
+ {% set visited_link_setter = 'SetVisitedLink' + property.name_for_methods %}
+ {% call(property) apply_initial(property, header) %}
+ StyleColor color = {{initial_color}}();
+ if (state.ApplyPropertyToRegularStyle())
+ {{set_value(property)}}(color);
+ if (state.ApplyPropertyToVisitedLinkStyle())
+ state.Style()->{{visited_link_setter}}(color);
+ {% endcall %}
+
+ {% call(property) apply_inherit(property, header) %}
+ // Visited link style can never explicitly inherit from parent visited link
+ // style so no separate getters are needed.
+ StyleColor color = state.ParentStyle()->{{property.getter}}();
+ if (state.ApplyPropertyToRegularStyle())
+ {{set_value(property)}}(color);
+ if (state.ApplyPropertyToVisitedLinkStyle())
+ state.Style()->{{visited_link_setter}}(color);
+ {% endcall %}
+
+ {% call(property) apply_value(property, header) %}
+ if (state.ApplyPropertyToRegularStyle())
+ {{set_value(property)}}(StyleBuilderConverter::{{property.converter}}(state, value));
+ if (state.ApplyPropertyToVisitedLinkStyle()) {
+ state.Style()->{{visited_link_setter}}(
+ StyleBuilderConverter::{{property.converter}}(state, value, true));
+ }
+ {% endcall %}
+ {% elif property.style_builder_template == 'counter' %}
+ {% set action = property.style_builder_template_args['action'] %}
+ {% call(property) apply_initial(property, header) %}
+ state.Style()->Clear{{action}}Directives();
+ {% endcall %}
+
+ {% call(property) apply_inherit(property, header) %}
+ const CounterDirectiveMap* parent_map = state.ParentStyle()->GetCounterDirectives();
+ if (!parent_map)
+ return;
+
+ CounterDirectiveMap& map = state.Style()->AccessCounterDirectives();
+ DCHECK(!parent_map->IsEmpty());
+
+ typedef CounterDirectiveMap::const_iterator Iterator;
+ Iterator end = parent_map->end();
+ for (Iterator it = parent_map->begin(); it != end; ++it) {
+ CounterDirectives& directives = map.insert(it->key, CounterDirectives()).stored_value->value;
+ directives.Inherit{{action}}(it->value);
+ }
+ {% endcall %}
+
+ {% call(property) apply_value(property, header) %}
+ state.Style()->Clear{{action}}Directives();
+
+ if (!value.IsValueList()) {
+ DCHECK(value.IsIdentifierValue());
+ DCHECK_EQ(ToCSSIdentifierValue(value).GetValueID(), CSSValueNone);
+ return;
+ }
+
+ CounterDirectiveMap& map = state.Style()->AccessCounterDirectives();
+
+ const CSSValueList& list = ToCSSValueList(value);
+
+ for (size_t i = 0; i < list.length(); ++i) {
+ const CSSValuePair& pair = ToCSSValuePair(list.Item(i));
+ AtomicString identifier(ToCSSCustomIdentValue(pair.First()).Value());
+ int counter_value = ToCSSPrimitiveValue(pair.Second()).GetIntValue();
+ CounterDirectives& directives =
+ map.insert(identifier, CounterDirectives()).stored_value->value;
+ {% if action == 'Reset' %}
+ directives.SetResetValue(counter_value);
+ {% else %}
+ directives.AddIncrementValue(counter_value);
+ {% endif %}
+ }
+ DCHECK(!map.IsEmpty());
+ {% endcall %}
+ {% elif property.style_builder_template == 'grid' %}
+ {% set type = property.style_builder_template_args['type'] %}
+ {% call(property) apply_initial(property, header) %}
+ state.Style()->SetGridTemplate{{type}}s(ComputedStyleInitialValues::InitialGridTemplate{{type}}s());
+ state.Style()->SetNamedGrid{{type}}Lines(ComputedStyleInitialValues::InitialNamedGrid{{type}}Lines());
+ state.Style()->SetOrderedNamedGrid{{type}}Lines(ComputedStyleInitialValues::InitialOrderedNamedGrid{{type}}Lines());
+ state.Style()->SetGridAutoRepeat{{type}}s(ComputedStyleInitialValues::InitialGridAutoRepeat{{type}}s());
+ state.Style()->SetGridAutoRepeat{{type}}sInsertionPoint(ComputedStyleInitialValues::InitialGridAutoRepeat{{type}}sInsertionPoint());
+ state.Style()->SetAutoRepeatNamedGrid{{type}}Lines(ComputedStyleInitialValues::InitialNamedGrid{{type}}Lines());
+ state.Style()->SetAutoRepeatOrderedNamedGrid{{type}}Lines(ComputedStyleInitialValues::InitialOrderedNamedGrid{{type}}Lines());
+ state.Style()->SetGridAutoRepeat{{type}}sType(ComputedStyleInitialValues::InitialGridAutoRepeat{{type}}sType());
+ {% endcall %}
+
+ {% call(property) apply_inherit(property, header) %}
+ state.Style()->SetGridTemplate{{type}}s(state.ParentStyle()->GridTemplate{{type}}s());
+ state.Style()->SetNamedGrid{{type}}Lines(state.ParentStyle()->NamedGrid{{type}}Lines());
+ state.Style()->SetOrderedNamedGrid{{type}}Lines(state.ParentStyle()->OrderedNamedGrid{{type}}Lines());
+ state.Style()->SetGridAutoRepeat{{type}}s(state.ParentStyle()->GridAutoRepeat{{type}}s());
+ state.Style()->SetGridAutoRepeat{{type}}sInsertionPoint(state.ParentStyle()->GridAutoRepeat{{type}}sInsertionPoint());
+ state.Style()->SetAutoRepeatNamedGrid{{type}}Lines(state.ParentStyle()->AutoRepeatNamedGrid{{type}}Lines());
+ state.Style()->SetAutoRepeatOrderedNamedGrid{{type}}Lines(state.ParentStyle()->AutoRepeatOrderedNamedGrid{{type}}Lines());
+ state.Style()->SetGridAutoRepeat{{type}}sType(state.ParentStyle()->GridAutoRepeat{{type}}sType());
+ {% endcall %}
+
+ {% call(property) apply_value(property, header) %}
+ Vector<GridTrackSize> track_sizes;
+ Vector<GridTrackSize> auto_repeat_track_sizes;
+ NamedGridLinesMap named_grid_lines;
+ OrderedNamedGridLines ordered_named_grid_lines;
+ NamedGridLinesMap auto_repeat_named_grid_lines;
+ OrderedNamedGridLines auto_repeat_ordered_named_grid_lines;
+ AutoRepeatType autoRepeatType = ComputedStyleInitialValues::InitialGridAutoRepeatType();
+ size_t auto_repeat_insertion_point =
+ ComputedStyleInitialValues::InitialGridAutoRepeatInsertionPoint();
+ StyleBuilderConverter::ConvertGridTrackList(
+ value, track_sizes, named_grid_lines, ordered_named_grid_lines,
+ auto_repeat_track_sizes, auto_repeat_named_grid_lines,
+ auto_repeat_ordered_named_grid_lines, auto_repeat_insertion_point,
+ autoRepeatType, state);
+ const NamedGridAreaMap& named_grid_areas = state.Style()->NamedGridArea();
+ if (!named_grid_areas.IsEmpty()) {
+ StyleBuilderConverter::CreateImplicitNamedGridLinesFromGridArea(
+ named_grid_areas, named_grid_lines, kFor{{type}}s);
+ }
+ state.Style()->SetGridTemplate{{type}}s(track_sizes);
+ state.Style()->SetNamedGrid{{type}}Lines(named_grid_lines);
+ state.Style()->SetOrderedNamedGrid{{type}}Lines(ordered_named_grid_lines);
+ state.Style()->SetGridAutoRepeat{{type}}s(auto_repeat_track_sizes);
+ state.Style()->SetGridAutoRepeat{{type}}sInsertionPoint(
+ auto_repeat_insertion_point);
+ state.Style()->SetAutoRepeatNamedGrid{{type}}Lines(auto_repeat_named_grid_lines);
+ state.Style()->SetAutoRepeatOrderedNamedGrid{{type}}Lines(
+ auto_repeat_ordered_named_grid_lines);
+ state.Style()->SetGridAutoRepeat{{type}}sType(autoRepeatType);
+ {% endcall %}
+ {% endif %}
{%- endmacro %}
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/templates/media_features.h.tmpl b/chromium/third_party/blink/renderer/build/scripts/core/css/templates/media_features.h.tmpl
index ad7696f2b9b..4f7fe5d43f3 100644
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/templates/media_features.h.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/templates/media_features.h.tmpl
@@ -9,7 +9,7 @@
#define CSS_MEDIAQUERY_NAMES_FOR_EACH_MEDIAFEATURE(macro) \
{% for entry in entries %}
{% set constant_prefix = entry | symbol %}
- {% set method_prefix = constant_prefix | upper_first_letter %}
+ {% set method_prefix = constant_prefix | to_function_name %}
macro({{constant_prefix}}, {{method_prefix}}){% if not loop.last %} \
{% endif %}
{% endfor %}
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.cc.tmpl b/chromium/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.cc.tmpl
index 3b7324062b7..aef5305626d 100644
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.cc.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.cc.tmpl
@@ -31,18 +31,18 @@
namespace blink {
{% for property in properties %}
-const StylePropertyShorthand& {{property.lower_camel_name}}Shorthand() {
- static const CSSProperty* {{property.lower_camel_name}}Properties[] = {
+const StylePropertyShorthand& {{property.name.to_lower_camel_case()}}Shorthand() {
+ static const CSSProperty* {{property.name.to_lower_camel_case()}}Properties[] = {
{% for longhand_id in property.longhand_property_ids %}
&Get{{longhand_id}}(),
{% endfor %}
};
- static StylePropertyShorthand {{property.lower_camel_name}}Longhands(
+ static StylePropertyShorthand {{property.name.to_lower_camel_case()}}Longhands(
{{property.property_id}},
- {{property.lower_camel_name}}Properties,
- arraysize({{property.lower_camel_name}}Properties));
- return {{property.lower_camel_name}}Longhands;
+ {{property.name.to_lower_camel_case()}}Properties,
+ arraysize({{property.name.to_lower_camel_case()}}Properties));
+ return {{property.name.to_lower_camel_case()}}Longhands;
}
{% endfor %}
@@ -68,7 +68,7 @@ const StylePropertyShorthand& shorthandForProperty(CSSPropertyID propertyID) {
switch (propertyID) {
{% for property in properties %}
case {{property.property_id}}:
- return {{property.lower_camel_name}}Shorthand();
+ return {{property.name.to_lower_camel_case()}}Shorthand();
{% endfor %}
default: {
return emptyShorthand;
@@ -83,7 +83,7 @@ void getMatchingShorthandsForLonghand(
{% for longhand_id, shorthands in longhands_dictionary.items() %}
case {{longhand_id}}: {
{% for shorthand in shorthands %}
- result->UncheckedAppend({{shorthand.lower_camel_name}}Shorthand());
+ result->UncheckedAppend({{shorthand.name.to_lower_camel_case()}}Shorthand());
{% endfor %}
break;
}
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.h.tmpl b/chromium/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.h.tmpl
index 715ce15bbc8..20ae092e477 100644
--- a/chromium/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.h.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/core/css/templates/style_property_shorthand.h.tmpl
@@ -57,7 +57,7 @@ class StylePropertyShorthand {
};
{% for property in properties %}
-const StylePropertyShorthand& {{property.lower_camel_name}}Shorthand();
+const StylePropertyShorthand& {{property.name.to_lower_camel_case()}}Shorthand();
{% endfor %}
const StylePropertyShorthand& animationShorthandForParsing();
diff --git a/chromium/third_party/blink/renderer/build/scripts/core/style/computed_style_fields.py b/chromium/third_party/blink/renderer/build/scripts/core/style/computed_style_fields.py
index 9e4795169ba..9f539ca67bf 100644
--- a/chromium/third_party/blink/renderer/build/scripts/core/style/computed_style_fields.py
+++ b/chromium/third_party/blink/renderer/build/scripts/core/style/computed_style_fields.py
@@ -2,12 +2,10 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-from name_utilities import (
- enum_value_name, class_member_name, method_name, class_name
-)
-
from itertools import chain
+from blinkbuild.name_style_converter import NameStyleConverter
+
def _flatten_list(x):
"""Flattens a list of lists into a single list."""
@@ -31,7 +29,7 @@ class Group(object):
"""Represents a group of fields stored together in a class.
Attributes:
- name: The name of the group as a string.
+ name: The name of the group as a string, or None.
subgroups: List of Group instances that are stored as subgroups under
this group.
fields: List of Field instances stored directly under this group.
@@ -43,8 +41,9 @@ class Group(object):
self.fields = fields
self.parent = None
- self.type_name = class_name(['style', name, 'data'])
- self.member_name = class_member_name([name, 'data'])
+ converter = NameStyleConverter(name or '')
+ self.type_name = converter.to_class_name(prefix='style', suffix='data')
+ self.member_name = converter.to_class_data_member(suffix='data')
self.num_32_bit_words_for_bit_fields = _num_32_bit_words_for_bit_fields(
field for field in fields if field.is_bit_field
)
@@ -78,7 +77,8 @@ class Enum(object):
"""Represents a generated enum in ComputedStyleBaseConstants."""
def __init__(self, type_name, keywords, is_set):
self.type_name = type_name
- self.values = [enum_value_name(keyword) for keyword in keywords]
+ self.values = [NameStyleConverter(keyword).to_enum_value()
+ for keyword in keywords]
self.is_set = is_set
@@ -138,7 +138,8 @@ class Field(object):
custom_copy, custom_compare, mutable, getter_method_name,
setter_method_name, initial_method_name,
computed_style_custom_functions, **kwargs):
- self.name = class_member_name(name_for_methods)
+ name_source = NameStyleConverter(name_for_methods)
+ self.name = name_source.to_class_data_member()
self.property_name = property_name
self.type_name = type_name
self.wrapper_pointer_name = wrapper_pointer_name
@@ -154,13 +155,11 @@ class Field(object):
# Method names
self.getter_method_name = getter_method_name
self.setter_method_name = setter_method_name
- self.internal_getter_method_name = method_name([self.name, 'internal'])
- self.internal_mutable_method_name = method_name(
- ['mutable', name_for_methods, 'internal'])
- self.internal_setter_method_name = method_name(
- [setter_method_name, 'internal'])
+ self.internal_getter_method_name = name_source.to_function_name(suffix='internal')
+ self.internal_mutable_method_name = name_source.to_function_name(prefix='mutable', suffix='internal')
+ self.internal_setter_method_name = NameStyleConverter(setter_method_name).to_function_name(suffix='internal')
self.initial_method_name = initial_method_name
- self.resetter_method_name = method_name(['reset', name_for_methods])
+ self.resetter_method_name = name_source.to_function_name(prefix='reset')
self.computed_style_custom_functions = computed_style_custom_functions
# Only bitfields have sizes.
self.is_bit_field = self.size is not None
@@ -177,7 +176,6 @@ class Field(object):
assert self.is_inherited or not self.is_independent, \
'Only inherited fields can be independent'
- self.is_inherited_method_name = method_name(
- [name_for_methods, 'is inherited'])
+ self.is_inherited_method_name = name_source.to_function_name(suffix=['is', 'inherited'])
assert len(kwargs) == 0, \
'Unexpected arguments provided to Field: ' + str(kwargs)
diff --git a/chromium/third_party/blink/renderer/build/scripts/json5_generator.py b/chromium/third_party/blink/renderer/build/scripts/json5_generator.py
index 159936e246d..2a4ed7db2a5 100644
--- a/chromium/third_party/blink/renderer/build/scripts/json5_generator.py
+++ b/chromium/third_party/blink/renderer/build/scripts/json5_generator.py
@@ -159,8 +159,7 @@ class Json5File(object):
def _get_entry(self, item):
entry = copy.deepcopy(self._defaults)
if type(item) is not dict:
- entry["name"] = item
- entry["tokenized_name"] = NameStyleConverter(entry["name"])
+ entry["name"] = NameStyleConverter(item)
return entry
if "name" not in item:
raise Exception("Missing name in item: %s" % item)
@@ -168,8 +167,7 @@ class Json5File(object):
entry.update(item)
return entry
assert "name" not in self.parameters, "The parameter 'name' is reserved, use a different name."
- entry["name"] = item.pop("name")
- entry["tokenized_name"] = NameStyleConverter(entry["name"])
+ entry["name"] = NameStyleConverter(item.pop("name"))
# Validate parameters if it's specified.
for key, value in item.items():
if key not in self.parameters:
@@ -251,7 +249,6 @@ class Writer(object):
self.gperf_path = gperf_path
def get_file_basename(self, name):
- # Use NameStyleConverter instead of name_utilities for consistency.
return NameStyleConverter(name).to_snake_case()
def make_header_guard(self, path):
diff --git a/chromium/third_party/blink/renderer/build/scripts/keyword_utils.py b/chromium/third_party/blink/renderer/build/scripts/keyword_utils.py
index ca5eda9e76d..faab8b5eeaf 100644
--- a/chromium/third_party/blink/renderer/build/scripts/keyword_utils.py
+++ b/chromium/third_party/blink/renderer/build/scripts/keyword_utils.py
@@ -20,7 +20,7 @@ def sort_keyword_properties_by_canonical_order(css_properties, css_value_keyword
[css_value_keywords_file],
default_parameters=json5_file_parameters
).name_dictionaries
- css_values_dictionary = [x['name'] for x in css_values_dictionary]
+ css_values_dictionary = [x['name'].original for x in css_values_dictionary]
name_to_position_dictionary = dict(zip(css_values_dictionary, range(len(css_values_dictionary))))
for css_property in css_properties:
if css_property['field_template'] == 'keyword' and len(css_property['include_paths']) == 0:
diff --git a/chromium/third_party/blink/renderer/build/scripts/make_computed_style_base.py b/chromium/third_party/blink/renderer/build/scripts/make_computed_style_base.py
index fb38a038878..b6e8a5b552b 100755
--- a/chromium/third_party/blink/renderer/build/scripts/make_computed_style_base.py
+++ b/chromium/third_party/blink/renderer/build/scripts/make_computed_style_base.py
@@ -7,14 +7,10 @@ import math
import json5_generator
import template_expander
-import make_style_builder
import keyword_utils
import bisect
-from name_utilities import (
- enum_value_name, class_member_name, method_name, class_name, join_names
-)
-
+from blinkbuild.name_style_converter import NameStyleConverter
from core.css import css_properties
from core.style.computed_style_fields import DiffGroup, Enum, Group, Field
@@ -160,7 +156,7 @@ def _create_diff_groups_map(diff_function_inputs, root_group):
"Please check that there's an entry for '{}' in" \
"CSSProperties.json5 or " \
"ComputedStyleExtraFields.json5".format(name, name)
- diff_functions_map[entry['name']] = _create_diff_groups(
+ diff_functions_map[entry['name'].original] = _create_diff_groups(
entry['fields_to_diff'], entry['methods_to_diff'],
entry['predicates_to_test'], root_group)
return diff_functions_map
@@ -268,7 +264,7 @@ def _create_property_field(property_):
return Field(
'property',
name_for_methods,
- property_name=property_['name'],
+ property_name=property_['name'].original,
inherited=property_['inherited'],
independent=property_['independent'],
type_name=property_['type_name'],
@@ -292,12 +288,12 @@ def _create_inherited_flag_field(property_):
Create the field used for an inheritance fast path from an independent CSS
property, and return the Field object.
"""
- name_for_methods = join_names(
- property_['name_for_methods'], 'is', 'inherited')
+ name_for_methods = NameStyleConverter(property_['name_for_methods']).to_function_name(suffix=['is', 'inherited'])
+ name_source = NameStyleConverter(name_for_methods)
return Field(
'inherited_flag',
name_for_methods,
- property_name=property_['name'],
+ property_name=property_['name'].original,
type_name='bool',
wrapper_pointer_name=None,
field_template='primitive',
@@ -306,9 +302,9 @@ def _create_inherited_flag_field(property_):
custom_copy=False,
custom_compare=False,
mutable=False,
- getter_method_name=method_name(name_for_methods),
- setter_method_name=method_name(['set', name_for_methods]),
- initial_method_name=method_name(['initial', name_for_methods]),
+ getter_method_name=name_source.to_function_name(),
+ setter_method_name=name_source.to_function_name(prefix='set'),
+ initial_method_name=name_source.to_function_name(prefix='initial'),
computed_style_custom_functions=property_[
"computed_style_custom_functions"],
)
@@ -436,18 +432,18 @@ def _evaluate_rare_non_inherited_group(properties, properties_ranking,
if (property_["field_group"] is not None and
"*" in property_["field_group"]
and not property_["inherited"] and
- property_["name"] in properties_ranking):
+ property_["name"].original in properties_ranking):
assert property_["field_group"] == "*", \
"The property {} will be automatically assigned a group, " \
"please put '*' as the field_group".format(property_['name'])
property_["field_group"] = "->".join(
- layers_name[0:properties_ranking[property_["name"]]])
+ layers_name[0:properties_ranking[property_["name"].original]])
elif property_["field_group"] is not None and \
"*" in property_["field_group"] and \
not property_["inherited"] and \
- property_["name"] not in properties_ranking:
+ property_["name"].original not in properties_ranking:
group_tree = property_["field_group"].split("->")[1:]
group_tree = [layers_name[0], layers_name[0] + "-sub"] + group_tree
property_["field_group"] = "->".join(group_tree)
@@ -486,13 +482,13 @@ def _evaluate_rare_inherit_group(properties, properties_ranking,
if property_["field_group"] is not None and \
"*" in property_["field_group"] \
and property_["inherited"] and \
- property_["name"] in properties_ranking:
+ property_["name"].original in properties_ranking:
property_["field_group"] = "->".join(
- layers_name[0:properties_ranking[property_["name"]]])
+ layers_name[0:properties_ranking[property_["name"].original]])
elif property_["field_group"] is not None and \
"*" in property_["field_group"] \
and property_["inherited"] and \
- property_["name"] not in properties_ranking:
+ property_["name"].original not in properties_ranking:
group_tree = property_["field_group"].split("->")[1:]
group_tree = [layers_name[0], layers_name[0] + "-sub"] + group_tree
property_["field_group"] = "->".join(group_tree)
@@ -532,7 +528,7 @@ class ComputedStyleBaseWriter(json5_generator.Writer):
[json5_file_paths[6]]).name_dictionaries])
properties_ranking = [
- x["name"] for x in json5_generator.Json5File.load_from_files(
+ x["name"].original for x in json5_generator.Json5File.load_from_files(
[json5_file_paths[5]]).name_dictionaries
]
_evaluate_rare_non_inherited_group(
diff --git a/chromium/third_party/blink/renderer/build/scripts/make_css_primitive_value_unit_trie.py b/chromium/third_party/blink/renderer/build/scripts/make_css_primitive_value_unit_trie.py
index 695ddb1b72e..b6c0cfb6164 100755
--- a/chromium/third_party/blink/renderer/build/scripts/make_css_primitive_value_unit_trie.py
+++ b/chromium/third_party/blink/renderer/build/scripts/make_css_primitive_value_unit_trie.py
@@ -14,7 +14,7 @@ class UnitTrieWriter(json5_generator.Writer):
def __init__(self, json5_file_paths, output_dir):
super(UnitTrieWriter, self).__init__(json5_file_paths, output_dir)
- self._units = {entry['name']: entry['unit_type'] for entry in self.json5_file.name_dictionaries}
+ self._units = {entry['name'].original: entry['unit_type'] for entry in self.json5_file.name_dictionaries}
self._outputs = {
'css_primitive_value_unit_trie.cc': self.generate_implementation
diff --git a/chromium/third_party/blink/renderer/build/scripts/make_css_property_names.py b/chromium/third_party/blink/renderer/build/scripts/make_css_property_names.py
index 4be0dd384ba..4a9c81cff33 100755
--- a/chromium/third_party/blink/renderer/build/scripts/make_css_property_names.py
+++ b/chromium/third_party/blink/renderer/build/scripts/make_css_property_names.py
@@ -50,7 +50,7 @@ class CSSPropertyNamesWriter(json5_generator.Writer):
def generate_implementation(self):
enum_value_to_name = {}
for property_ in self._css_properties.properties_including_aliases:
- enum_value_to_name[property_['enum_value']] = property_['name']
+ enum_value_to_name[property_['enum_value']] = property_['name'].original
property_offsets = []
property_names = []
current_offset = 0
@@ -63,7 +63,7 @@ class CSSPropertyNamesWriter(json5_generator.Writer):
current_offset += len(name) + 1
css_name_and_enum_pairs = [
- (property_['name'], property_['property_id'])
+ (property_['name'].original, property_['property_id'])
for property_ in self._css_properties.properties_including_aliases]
return {
diff --git a/chromium/third_party/blink/renderer/build/scripts/make_css_value_id_mappings.py b/chromium/third_party/blink/renderer/build/scripts/make_css_value_id_mappings.py
index a5f95f554e4..9a3548f19bd 100755
--- a/chromium/third_party/blink/renderer/build/scripts/make_css_value_id_mappings.py
+++ b/chromium/third_party/blink/renderer/build/scripts/make_css_value_id_mappings.py
@@ -3,11 +3,12 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+from blinkbuild.name_style_converter import NameStyleConverter
import json5_generator
import template_expander
import make_style_builder
import keyword_utils
-from name_utilities import enum_for_css_keyword, enum_value_name
+from name_utilities import enum_for_css_keyword
def _find_continuous_segment(numbers):
@@ -89,11 +90,12 @@ def _find_enum_longest_continuous_segment(property_, name_to_position_dictionary
enum_segment, enum_pair_list = _find_continuous_segment(enum_pair_list)
longest_segment = _find_largest_segment(enum_segment)
- enum_pair_list = [
- (enum_value_name(property_['keywords'][x[1]]), x[1],
- enum_for_css_keyword(property_['keywords'][x[1]]), x[0]) for x in enum_pair_list
- ]
- return enum_pair_list, enum_segment, longest_segment
+ enum_tuple_list = []
+ for x in enum_pair_list:
+ keyword = NameStyleConverter(property_['keywords'][x[1]])
+ enum_tuple_list.append((keyword.to_enum_value(), x[1],
+ enum_for_css_keyword(keyword), x[0]))
+ return enum_tuple_list, enum_segment, longest_segment
class CSSValueIDMappingsWriter(make_style_builder.StyleBuilderWriter):
@@ -121,14 +123,16 @@ class CSSValueIDMappingsWriter(make_style_builder.StyleBuilderWriter):
[self.css_values_dictionary_file],
default_parameters=self.default_parameters
).name_dictionaries
- name_to_position_dictionary = dict(zip([x['name'] for x in css_values_dictionary], range(len(css_values_dictionary))))
+ name_to_position_dictionary = dict(zip([x['name'].original for x in css_values_dictionary],
+ range(len(css_values_dictionary))))
for property_ in self.css_properties.properties_including_aliases:
include_paths.update(property_['include_paths'])
if property_['field_template'] == 'multi_keyword':
mappings[property_['type_name']] = {
'default_value': property_['default_value'],
- 'mapping': [(enum_value_name(k), enum_for_css_keyword(k)) for k in property_['keywords']],
+ 'mapping': [(k.to_enum_value(), enum_for_css_keyword(k))
+ for k in map(NameStyleConverter, property_['keywords'])],
}
elif property_['field_template'] == 'keyword':
enum_pair_list, enum_segment, p_segment = _find_enum_longest_continuous_segment(
diff --git a/chromium/third_party/blink/renderer/build/scripts/make_element_factory.py b/chromium/third_party/blink/renderer/build/scripts/make_element_factory.py
index f4ce8d42286..6158af32dab 100755
--- a/chromium/third_party/blink/renderer/build/scripts/make_element_factory.py
+++ b/chromium/third_party/blink/renderer/build/scripts/make_element_factory.py
@@ -99,7 +99,7 @@ class MakeElementFactoryWriter(MakeQualifiedNamesWriter):
def _interface(self, tag):
if tag['interfaceName']:
return tag['interfaceName']
- name = tag['tokenized_name'].to_upper_camel_case()
+ name = tag['name'].to_upper_camel_case()
# FIXME: We shouldn't hard-code HTML here.
if name == 'HTML':
name = 'Html'
diff --git a/chromium/third_party/blink/renderer/build/scripts/make_element_lookup_trie.py b/chromium/third_party/blink/renderer/build/scripts/make_element_lookup_trie.py
index 24e96e73eb8..d0fce32f3c1 100755
--- a/chromium/third_party/blink/renderer/build/scripts/make_element_lookup_trie.py
+++ b/chromium/third_party/blink/renderer/build/scripts/make_element_lookup_trie.py
@@ -58,7 +58,7 @@ class ElementLookupTrieWriter(json5_generator.Writer):
super(ElementLookupTrieWriter, self).__init__(json5_file_paths, output_dir)
self._tags = {}
for entry in self.json5_file.name_dictionaries:
- self._tags[entry['name']] = entry['name']
+ self._tags[entry['name'].original] = entry['name'].original
self._namespace = self.json5_file.metadata['namespace'].strip('"')
basename = self._namespace.lower() + '_element_lookup_trie'
self._outputs = {
diff --git a/chromium/third_party/blink/renderer/build/scripts/make_element_type_helpers.py b/chromium/third_party/blink/renderer/build/scripts/make_element_type_helpers.py
index dd44d9d56dd..0c8561e0d5f 100755
--- a/chromium/third_party/blink/renderer/build/scripts/make_element_type_helpers.py
+++ b/chromium/third_party/blink/renderer/build/scripts/make_element_type_helpers.py
@@ -91,7 +91,7 @@ class MakeElementTypeHelpersWriter(json5_generator.Writer):
def _interface(self, tag):
if tag['interfaceName']:
return tag['interfaceName']
- name = tag['tokenized_name'].to_upper_camel_case()
+ name = tag['name'].to_upper_camel_case()
# FIXME: We shouldn't hard-code HTML here.
if name == 'HTML':
name = 'Html'
diff --git a/chromium/third_party/blink/renderer/build/scripts/make_event_factory.py b/chromium/third_party/blink/renderer/build/scripts/make_event_factory.py
index 67e56f22e7e..d509a3e8d42 100755
--- a/chromium/third_party/blink/renderer/build/scripts/make_event_factory.py
+++ b/chromium/third_party/blink/renderer/build/scripts/make_event_factory.py
@@ -121,13 +121,13 @@ class EventFactoryWriter(json5_generator.Writer):
exit(1)
def _headers_header_include_path(self, entry):
- path = os.path.dirname(entry['name'])
+ path = os.path.dirname(entry['name'].original)
if len(path):
path += '/'
if entry['ImplementedAs']:
path += self.get_file_basename(entry['ImplementedAs'])
else:
- path += self.get_file_basename(os.path.basename(entry['name']))
+ path += self.get_file_basename(os.path.basename(entry['name'].original))
return path + '.h'
def _headers_header_includes(self, entries):
diff --git a/chromium/third_party/blink/renderer/build/scripts/make_instrumenting_probes.py b/chromium/third_party/blink/renderer/build/scripts/make_instrumenting_probes.py
index e89f3b33860..e0b2be7087d 100644
--- a/chromium/third_party/blink/renderer/build/scripts/make_instrumenting_probes.py
+++ b/chromium/third_party/blink/renderer/build/scripts/make_instrumenting_probes.py
@@ -26,7 +26,6 @@ sys.path.insert(1, _THIRD_PARTY_DIR)
import jinja2
from blinkbuild.name_style_converter import NameStyleConverter
-from name_utilities import method_name
def _json5_loads(lines):
@@ -249,7 +248,7 @@ def main():
"files": files,
"agents": build_observers(config, files),
"config": config,
- "method_name": method_name,
+ "method_name": lambda name: NameStyleConverter(name).to_function_name(),
"name": base_name,
"input_files": [os.path.basename(input_path)],
"output_path_in_gen_dir": output_path_in_gen_dir
diff --git a/chromium/third_party/blink/renderer/build/scripts/make_internal_settings.py b/chromium/third_party/blink/renderer/build/scripts/make_internal_settings.py
index e1e59b87677..8827eea5e63 100755
--- a/chromium/third_party/blink/renderer/build/scripts/make_internal_settings.py
+++ b/chromium/third_party/blink/renderer/build/scripts/make_internal_settings.py
@@ -44,7 +44,7 @@ class MakeInternalSettingsWriter(json5_generator.Writer):
def __init__(self, json5_file_path, output_dir):
super(MakeInternalSettingsWriter, self).__init__(json5_file_path, output_dir)
- self.json5_file.name_dictionaries.sort(key=lambda entry: entry['name'])
+ self.json5_file.name_dictionaries.sort(key=lambda entry: entry['name'].original)
self._outputs = {
'internal_settings_generated.h': self.generate_header,
diff --git a/chromium/third_party/blink/renderer/build/scripts/make_names.py b/chromium/third_party/blink/renderer/build/scripts/make_names.py
index 305fb77b990..99f8a8f2586 100755
--- a/chromium/third_party/blink/renderer/build/scripts/make_names.py
+++ b/chromium/third_party/blink/renderer/build/scripts/make_names.py
@@ -39,8 +39,8 @@ def _symbol(entry):
if entry['Symbol'] is not None:
return entry['Symbol']
# FIXME: Remove this special case for the ugly x-webkit-foo attributes.
- if entry['name'].startswith('-webkit-'):
- return entry['name'].replace('-', '_')[1:]
+ if entry['name'].original.startswith('-webkit-'):
+ return entry['name'].original.replace('-', '_')[1:]
return name_utilities.cpp_name(entry).replace('-', '_').replace(' ', '_')
@@ -61,7 +61,6 @@ class MakeNamesWriter(json5_generator.Writer):
'hash': hasher.hash,
'script_name': name_utilities.script_name,
'symbol': _symbol,
- 'to_macro_style': name_utilities.to_macro_style,
}
def __init__(self, json5_file_path, output_dir):
diff --git a/chromium/third_party/blink/renderer/build/scripts/make_origin_trials.py b/chromium/third_party/blink/renderer/build/scripts/make_origin_trials.py
index 06c6e0ccc69..5a72aa3169c 100755
--- a/chromium/third_party/blink/renderer/build/scripts/make_origin_trials.py
+++ b/chromium/third_party/blink/renderer/build/scripts/make_origin_trials.py
@@ -55,7 +55,7 @@ class OriginTrialsWriter(make_runtime_features.RuntimeFeatureWriter):
# have a trial defined.
implied_by_trials = []
for implied_by_name in implied_feature['implied_by']:
- if any(implied_by_name == feature['name']
+ if any(implied_by_name == feature['name'].original
for feature in self._origin_trial_features):
implied_by_trials.append(implied_by_name)
@@ -67,7 +67,7 @@ class OriginTrialsWriter(make_runtime_features.RuntimeFeatureWriter):
if implied_list is None:
implied_list = set()
implied_mappings[implied_by_name] = implied_list
- implied_list.add(implied_feature['name'])
+ implied_list.add(implied_feature['name'].original)
implied_feature['implied_by_origin_trials'] = implied_by_trials
diff --git a/chromium/third_party/blink/renderer/build/scripts/make_qualified_names.py b/chromium/third_party/blink/renderer/build/scripts/make_qualified_names.py
index 1bb9d4eaf14..9957831019f 100755
--- a/chromium/third_party/blink/renderer/build/scripts/make_qualified_names.py
+++ b/chromium/third_party/blink/renderer/build/scripts/make_qualified_names.py
@@ -40,7 +40,7 @@ from json5_generator import Json5File
def _symbol(entry):
- return entry['name'].replace('-', '_')
+ return entry['name'].original.replace('-', '_')
class MakeQualifiedNamesWriter(json5_generator.Writer):
@@ -55,7 +55,6 @@ class MakeQualifiedNamesWriter(json5_generator.Writer):
filters = {
'hash': hasher.hash,
'symbol': _symbol,
- 'to_macro_style': name_utilities.to_macro_style,
}
def __init__(self, json5_file_paths, output_dir):
diff --git a/chromium/third_party/blink/renderer/build/scripts/make_runtime_features.py b/chromium/third_party/blink/renderer/build/scripts/make_runtime_features.py
index 9627fde37eb..f9efefe7a5c 100755
--- a/chromium/third_party/blink/renderer/build/scripts/make_runtime_features.py
+++ b/chromium/third_party/blink/renderer/build/scripts/make_runtime_features.py
@@ -31,8 +31,6 @@ import sys
from blinkbuild.name_style_converter import NameStyleConverter
import json5_generator
-import name_utilities
-from name_utilities import class_member_name
import template_expander
@@ -49,19 +47,24 @@ class RuntimeFeatureWriter(json5_generator.Writer):
self._features = self.json5_file.name_dictionaries
# Make sure the resulting dictionaries have all the keys we expect.
for feature in self._features:
- feature['class_member_name'] = class_member_name(feature['name'])
- # Most features just check their isFooEnabled bool
+ feature['data_member_name'] = self._data_member_name(feature['name'])
+ # Most features just check their is_foo_enabled_ bool
# but some depend on or are implied by other bools.
- enabled_condition = 'is_%senabled_' % feature['class_member_name']
+ enabled_condition = feature['data_member_name']
assert not feature['implied_by'] or not feature['depends_on'], 'Only one of implied_by and depends_on is allowed'
for implied_by_name in feature['implied_by']:
- enabled_condition += ' || is_%senabled_' % class_member_name(implied_by_name)
+ enabled_condition += ' || ' + self._data_member_name(implied_by_name)
for dependant_name in feature['depends_on']:
- enabled_condition += ' && is_%senabled_' % class_member_name(dependant_name)
+ enabled_condition += ' && ' + self._data_member_name(dependant_name)
feature['enabled_condition'] = enabled_condition
self._standard_features = [feature for feature in self._features if not feature['custom']]
self._origin_trial_features = [feature for feature in self._features if feature['origin_trial_feature_name']]
+ @staticmethod
+ def _data_member_name(str_or_converter):
+ converter = NameStyleConverter(str_or_converter) if type(str_or_converter) is str else str_or_converter
+ return converter.to_class_data_member(prefix='is', suffix='enabled')
+
def _feature_sets(self):
# Another way to think of the status levels is as "sets of features"
# which is how we're referring to them in this generator.
diff --git a/chromium/third_party/blink/renderer/build/scripts/make_settings.py b/chromium/third_party/blink/renderer/build/scripts/make_settings.py
index 269d105edf8..4f2752ad33f 100755
--- a/chromium/third_party/blink/renderer/build/scripts/make_settings.py
+++ b/chromium/third_party/blink/renderer/build/scripts/make_settings.py
@@ -65,7 +65,7 @@ class MakeSettingsWriter(json5_generator.Writer):
def __init__(self, json5_file_path, output_dir):
super(MakeSettingsWriter, self).__init__(json5_file_path, output_dir)
- self.json5_file.name_dictionaries.sort(key=lambda entry: entry['name'])
+ self.json5_file.name_dictionaries.sort(key=lambda entry: entry['name'].original)
self._outputs = {
('settings_macros.h'): self.generate_macros,
diff --git a/chromium/third_party/blink/renderer/build/scripts/make_style_builder.py b/chromium/third_party/blink/renderer/build/scripts/make_style_builder.py
index 6be87079705..fe097454f5b 100755
--- a/chromium/third_party/blink/renderer/build/scripts/make_style_builder.py
+++ b/chromium/third_party/blink/renderer/build/scripts/make_style_builder.py
@@ -32,30 +32,18 @@ import types
from core.css import css_properties
import json5_generator
-import template_expander
-
def calculate_apply_functions_to_declare(property_):
property_['should_declare_functions'] = \
not property_['longhands'] \
- and not property_['direction_aware_options'] \
- and not property_['builder_skip'] \
and property_['is_property']
property_['use_property_class_in_stylebuilder'] = \
- property_['should_declare_functions'] \
- and not property_['style_builder_legacy']
-
+ property_['should_declare_functions']
class StyleBuilderWriter(json5_generator.Writer):
def __init__(self, json5_file_paths, output_dir):
super(StyleBuilderWriter, self).__init__([], output_dir)
- self._outputs = {
- 'style_builder_functions.h': self.generate_style_builder_functions_h,
- 'style_builder_functions.cc':
- self.generate_style_builder_functions_cpp,
- 'style_builder.cc': self.generate_style_builder,
- }
self._json5_properties = css_properties.CSSProperties(json5_file_paths)
self._input_files = json5_file_paths
@@ -68,29 +56,5 @@ class StyleBuilderWriter(json5_generator.Writer):
def css_properties(self):
return self._json5_properties
- @template_expander.use_jinja('templates/style_builder_functions.h.tmpl')
- def generate_style_builder_functions_h(self):
- return {
- 'input_files': self._input_files,
- 'properties': self._properties,
- }
-
- @template_expander.use_jinja('templates/style_builder_functions.cc.tmpl')
- def generate_style_builder_functions_cpp(self):
- return {
- 'input_files': self._input_files,
- 'properties': self._properties,
- 'properties_by_id': self._json5_properties.properties_by_id,
- }
-
- @template_expander.use_jinja('templates/style_builder.cc.tmpl')
- def generate_style_builder(self):
- return {
- 'input_files': self._input_files,
- 'properties': self._properties,
- 'properties_by_id': self._json5_properties.properties_by_id,
- }
-
-
if __name__ == '__main__':
json5_generator.Maker(StyleBuilderWriter).main()
diff --git a/chromium/third_party/blink/renderer/build/scripts/make_web_origin_trials.py b/chromium/third_party/blink/renderer/build/scripts/make_web_origin_trials.py
new file mode 100755
index 00000000000..6ba2b2e8ba9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/build/scripts/make_web_origin_trials.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+# 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 json5_generator
+import make_runtime_features
+import template_expander
+
+
+# We want exactly the same parsing as RuntimeFeatureWriter but generate
+# different files.
+class OriginTrialsWriter(make_runtime_features.RuntimeFeatureWriter):
+ file_basename = 'web_origin_trials'
+
+ def __init__(self, json5_file_path, output_dir):
+ super(OriginTrialsWriter, self).__init__(json5_file_path, output_dir)
+ self._outputs = {
+ (self.file_basename + '.cc'): self.generate_implementation,
+ }
+
+ @template_expander.use_jinja('templates/' + file_basename + '.cc.tmpl')
+ def generate_implementation(self):
+ return {
+ 'features': self._features,
+ 'origin_trial_features': self._origin_trial_features,
+ 'input_files': self._input_files,
+ }
+
+
+if __name__ == '__main__':
+ json5_generator.Maker(OriginTrialsWriter).main()
diff --git a/chromium/third_party/blink/renderer/build/scripts/media_feature_symbol.py b/chromium/third_party/blink/renderer/build/scripts/media_feature_symbol.py
index 0077ccbf900..f9d51e96a7a 100644
--- a/chromium/third_party/blink/renderer/build/scripts/media_feature_symbol.py
+++ b/chromium/third_party/blink/renderer/build/scripts/media_feature_symbol.py
@@ -4,7 +4,7 @@
def mediaFeatureSymbol(entry, suffix):
- name = entry['name']
+ name = entry['name'].original
if name.startswith('-webkit-'):
name = name[8:]
diff --git a/chromium/third_party/blink/renderer/build/scripts/name_utilities.py b/chromium/third_party/blink/renderer/build/scripts/name_utilities.py
index 637ba53ed59..d6afcc029e7 100644
--- a/chromium/third_party/blink/renderer/build/scripts/name_utilities.py
+++ b/chromium/third_party/blink/renderer/build/scripts/name_utilities.py
@@ -27,32 +27,12 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import os.path
-import re
-from blinkbuild.name_style_converter import tokenize_name
-
-
-def lower_first_letter(name):
- """Return name with first letter lowercased."""
- if not name:
- return ''
- return name[0].lower() + name[1:]
-
-
-def upper_first_letter(name):
- """Return name with first letter uppercased."""
- if not name:
- return ''
- return name[0].upper() + name[1:]
-
-
-def to_macro_style(name):
- s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
- return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).upper()
+from blinkbuild.name_style_converter import NameStyleConverter
def script_name(entry):
- return os.path.basename(entry['name'])
+ return os.path.basename(entry['name'].original)
def cpp_bool(value):
@@ -70,85 +50,14 @@ def cpp_name(entry):
def enum_for_css_keyword(keyword):
- return 'CSSValue' + upper_camel_case(keyword)
+ converter = NameStyleConverter(keyword) if type(keyword) is str else keyword
+ return 'CSSValue' + converter.to_upper_camel_case()
def enum_for_css_property(property_name):
- return 'CSSProperty' + upper_camel_case(property_name)
+ converter = NameStyleConverter(property_name) if type(property_name) is str else property_name
+ return 'CSSProperty' + converter.to_upper_camel_case()
def enum_for_css_property_alias(property_name):
- return 'CSSPropertyAlias' + upper_camel_case(property_name)
-
-# FIXME: Merge these with the above methods.
-# and update all the generators to use these ones.
-# FIXME: Switch external callers of these methods to use the high level
-# API below instead.
-
-
-def join_names(*names):
- """Given a list of names, join them into a single space-separated name."""
- result = []
- for name in names:
- result.extend(tokenize_name(name))
- return ' '.join(result)
-
-
-def naming_style(f):
- """Decorator for name utility functions.
-
- Wraps a name utility function in a function that takes one or more names,
- splits them into a list of words, and passes the list to the utility function.
- """
- def inner(name_or_names):
- names = name_or_names if isinstance(name_or_names, list) else [name_or_names]
- words = []
- for name in names:
- if name:
- words.extend(tokenize_name(name))
- return f(words)
- return inner
-
-
-@naming_style
-def upper_camel_case(words):
- return ''.join(upper_first_letter(word) for word in words)
-
-
-@naming_style
-def lower_camel_case(words):
- return lower_first_letter(upper_camel_case(words))
-
-
-@naming_style
-def snake_case(words):
- return '_'.join(word.lower() for word in words)
-
-
-# Use these high level naming functions which describe the semantics of the name,
-# rather than a particular style.
-
-
-@naming_style
-def enum_type_name(words):
- return upper_camel_case(words)
-
-
-@naming_style
-def enum_value_name(words):
- return 'k' + upper_camel_case(words)
-
-
-@naming_style
-def class_name(words):
- return upper_camel_case(words)
-
-
-@naming_style
-def class_member_name(words):
- return snake_case(words) + "_"
-
-
-@naming_style
-def method_name(words):
- return upper_camel_case(words)
+ return 'CSSPropertyAlias' + property_name.to_upper_camel_case()
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/internal_runtime_flags.h.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/internal_runtime_flags.h.tmpl
index a28c58cc617..8f4a96e3fb5 100644
--- a/chromium/third_party/blink/renderer/build/scripts/templates/internal_runtime_flags.h.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/templates/internal_runtime_flags.h.tmpl
@@ -30,7 +30,7 @@ class InternalRuntimeFlags : public ScriptWrappable {
{% endfor %}
{% for feature in standard_features %}
- bool {{feature.tokenized_name.to_lower_camel_case()}}Enabled() {
+ bool {{feature.name.to_lower_camel_case()}}Enabled() {
{% if feature.origin_trial_feature_name %}
return RuntimeEnabledFeatures::{{feature.name}}EnabledByRuntimeFlag();
{% else %}
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/internal_runtime_flags.idl.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/internal_runtime_flags.idl.tmpl
index 5006b34050a..5728a76e968 100644
--- a/chromium/third_party/blink/renderer/build/scripts/templates/internal_runtime_flags.idl.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/templates/internal_runtime_flags.idl.tmpl
@@ -7,9 +7,9 @@ interface InternalRuntimeFlags {
{% for feature in standard_features %}
{%+ if feature.condition %}[Conditional={{feature.condition}}] {% endif -%}
{% if feature.settable_from_internals %}
- attribute boolean {{feature.tokenized_name.to_lower_camel_case()}}Enabled;
+ attribute boolean {{feature.name.to_lower_camel_case()}}Enabled;
{% else %}
- readonly attribute boolean {{feature.tokenized_name.to_lower_camel_case()}}Enabled;
+ readonly attribute boolean {{feature.name.to_lower_camel_case()}}Enabled;
{% endif %}
{% endfor %}
};
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/internal_settings_generated.cc.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/internal_settings_generated.cc.tmpl
index 5633a721614..b54ce95ade1 100644
--- a/chromium/third_party/blink/renderer/build/scripts/templates/internal_settings_generated.cc.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/templates/internal_settings_generated.cc.tmpl
@@ -13,7 +13,7 @@ namespace blink {
InternalSettingsGenerated::InternalSettingsGenerated(Page* page)
: m_page(page)
{% for setting in settings if setting.type|to_idl_type %}
- , m_{{setting.name}}(page->GetSettings().Get{{setting.tokenized_name.to_upper_camel_case()}}())
+ , m_{{setting.name}}(page->GetSettings().Get{{setting.name.to_upper_camel_case()}}())
{% endfor %}
{
}
@@ -22,13 +22,13 @@ InternalSettingsGenerated::~InternalSettingsGenerated() {}
void InternalSettingsGenerated::resetToConsistentState() {
{% for setting in settings if setting.type|to_idl_type %}
- m_page->GetSettings().Set{{setting.tokenized_name.to_upper_camel_case()}}(m_{{setting.name}});
+ m_page->GetSettings().Set{{setting.name.to_upper_camel_case()}}(m_{{setting.name}});
{% endfor %}
}
{% for setting in settings if setting.type|to_idl_type %}
-void InternalSettingsGenerated::set{{setting.tokenized_name.to_upper_camel_case()}}({{setting.type|to_passing_type}} {{setting.name}}) {
- m_page->GetSettings().Set{{setting.tokenized_name.to_upper_camel_case()}}({{setting.name}});
+void InternalSettingsGenerated::set{{setting.name.to_upper_camel_case()}}({{setting.type|to_passing_type}} {{setting.name}}) {
+ m_page->GetSettings().Set{{setting.name.to_upper_camel_case()}}({{setting.name}});
}
{% endfor %}
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/internal_settings_generated.h.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/internal_settings_generated.h.tmpl
index 2fcb1195601..50a86395612 100644
--- a/chromium/third_party/blink/renderer/build/scripts/templates/internal_settings_generated.h.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/templates/internal_settings_generated.h.tmpl
@@ -24,7 +24,7 @@ class InternalSettingsGenerated : public ScriptWrappable {
virtual ~InternalSettingsGenerated();
void resetToConsistentState();
{% for setting in settings if setting.type|to_idl_type %}
- void set{{setting.tokenized_name.to_upper_camel_case()}}({{setting.type|to_passing_type}} {{setting.name}});
+ void set{{setting.name.to_upper_camel_case()}}({{setting.type|to_passing_type}} {{setting.name}});
{% endfor %}
void Trace(Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/internal_settings_generated.idl.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/internal_settings_generated.idl.tmpl
index 9d7be66b932..5aa387ec67c 100644
--- a/chromium/third_party/blink/renderer/build/scripts/templates/internal_settings_generated.idl.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/templates/internal_settings_generated.idl.tmpl
@@ -5,6 +5,6 @@
interface InternalSettingsGenerated {
{% for setting in settings if setting.type|to_idl_type %}
- void set{{setting.tokenized_name.to_upper_camel_case()}}({{setting.type|to_idl_type}} {{setting.name}});
+ void set{{setting.name.to_upper_camel_case()}}({{setting.type|to_idl_type}} {{setting.name}});
{% endfor %}
};
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/make_qualified_names.cc.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/make_qualified_names.cc.tmpl
index 9a602d58b2e..7bf6eeb8d7c 100644
--- a/chromium/third_party/blink/renderer/build/scripts/templates/make_qualified_names.cc.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/templates/make_qualified_names.cc.tmpl
@@ -70,7 +70,7 @@ void init() {
{% set attrnames = attrs|map(attribute='name')|list() %}
static const NameEntry kNames[] = {
{% for name, tag_list in (tags + attrs)|groupby('name')|sort(attribute=0, case_sensitive=True) %}
- { "{{name}}", {{name|hash}}, {{name|length}}, {{ (name in tagnames)|int }}, {{ (name in attrnames)|int }} },
+ { "{{name}}", {{name.original|hash}}, {{name.original|length}}, {{ (name in tagnames)|int }}, {{ (name in attrnames)|int }} },
{% endfor %}
};
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/origin_trials.cc.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/origin_trials.cc.tmpl
index dcac3707d68..7c2e355dd9b 100644
--- a/chromium/third_party/blink/renderer/build/scripts/templates/origin_trials.cc.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/templates/origin_trials.cc.tmpl
@@ -19,7 +19,7 @@ const char OriginTrials::k{{feature.name}}TrialName[] = "{{feature.origin_trial_
{% for feature in features %}
{% if feature.origin_trial_feature_name %}
-bool OriginTrials::{{feature.tokenized_name.to_lower_camel_case()}}Enabled(const ExecutionContext* executionContext) {
+bool OriginTrials::{{feature.name}}Enabled(const ExecutionContext* executionContext) {
if (RuntimeEnabledFeatures::{{feature.name}}EnabledByRuntimeFlag())
return true;
{% if feature.origin_trial_os %}
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/origin_trials.h.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/origin_trials.h.tmpl
index 0034cbd7b75..ed530591361 100644
--- a/chromium/third_party/blink/renderer/build/scripts/templates/origin_trials.h.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/templates/origin_trials.h.tmpl
@@ -27,7 +27,7 @@ CORE_EXPORT extern const char k{{feature.name}}TrialName[];
{% for feature in features %}
{% if feature.origin_trial_feature_name %}
-CORE_EXPORT bool {{feature.tokenized_name.to_lower_camel_case()}}Enabled(const ExecutionContext*);
+CORE_EXPORT bool {{feature.name}}Enabled(const ExecutionContext*);
{% endif %}
{% endfor %}
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/runtime_enabled_features.cc.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/runtime_enabled_features.cc.tmpl
index 2cb327f14e8..a425ca6b9f1 100644
--- a/chromium/third_party/blink/renderer/build/scripts/templates/runtime_enabled_features.cc.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/templates/runtime_enabled_features.cc.tmpl
@@ -13,9 +13,9 @@ namespace blink {
RuntimeEnabledFeatures::Backup::Backup()
: {% for feature in standard_features -%}
{% if feature.origin_trial_feature_name %}
- {{feature.class_member_name}}(RuntimeEnabledFeatures::{{feature.name}}EnabledByRuntimeFlag())
+ {{feature.name.to_class_data_member()}}(RuntimeEnabledFeatures::{{feature.name}}EnabledByRuntimeFlag())
{% else %}
- {{feature.class_member_name}}(RuntimeEnabledFeatures::{{feature.name}}Enabled())
+ {{feature.name.to_class_data_member()}}(RuntimeEnabledFeatures::{{feature.name}}Enabled())
{% endif %}
{%- if not loop.last %},
{%+ endif -%}
@@ -23,7 +23,7 @@ RuntimeEnabledFeatures::Backup::Backup()
void RuntimeEnabledFeatures::Backup::Restore() {
{% for feature in standard_features %}
- RuntimeEnabledFeatures::Set{{feature.name}}Enabled({{feature.class_member_name}});
+ RuntimeEnabledFeatures::Set{{feature.name}}Enabled({{feature.name.to_class_data_member()}});
{% endfor %}
}
@@ -49,7 +49,7 @@ void RuntimeEnabledFeatures::SetFeatureEnabledFromString(
bool* setting;
} kFeatures[] = {
{% for feature in standard_features %}
- {"{{feature.name}}", &is_{{feature.class_member_name}}enabled_},
+ {"{{feature.name}}", &{{feature.data_member_name}}},
{% endfor %}
};
for (const auto& feature : kFeatures) {
@@ -62,7 +62,7 @@ void RuntimeEnabledFeatures::SetFeatureEnabledFromString(
}
{% for feature in standard_features %}
-bool RuntimeEnabledFeatures::is_{{feature.class_member_name}}enabled_ = {{'true' if feature.status == 'stable' else 'false'}};
+bool RuntimeEnabledFeatures::{{feature.data_member_name}} = {{'true' if feature.status == 'stable' else 'false'}};
{% endfor %}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/runtime_enabled_features.h.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/runtime_enabled_features.h.tmpl
index 80ee34d45a1..77be3bb3cda 100644
--- a/chromium/third_party/blink/renderer/build/scripts/templates/runtime_enabled_features.h.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/templates/runtime_enabled_features.h.tmpl
@@ -26,7 +26,7 @@ class PLATFORM_EXPORT RuntimeEnabledFeatures {
private:
{% for feature in standard_features %}
- bool {{feature.class_member_name}};
+ bool {{feature.name.to_class_data_member()}};
{% endfor %}
};
@@ -42,7 +42,7 @@ class PLATFORM_EXPORT RuntimeEnabledFeatures {
{% if feature.custom %}
static bool {{feature.name}}Enabled();
{% else %}
- static void Set{{feature.name}}Enabled(bool enabled) { is_{{feature.class_member_name}}enabled_ = enabled; }
+ static void Set{{feature.name}}Enabled(bool enabled) { {{feature.data_member_name}} = enabled; }
static bool {{feature.name}}Enabled() { return {{feature.enabled_condition}}; }
{% endif %}
@@ -64,7 +64,7 @@ class PLATFORM_EXPORT RuntimeEnabledFeatures {
{% if feature.custom %}
static bool {{feature.name}}EnabledByRuntimeFlag();
{% else %}
- static void Set{{feature.name}}Enabled(bool enabled) { is_{{feature.class_member_name}}enabled_ = enabled; }
+ static void Set{{feature.name}}Enabled(bool enabled) { {{feature.data_member_name}} = enabled; }
static bool {{feature.name}}EnabledByRuntimeFlag() { return {{feature.enabled_condition}}; }
{% endif %}
@@ -73,7 +73,7 @@ class PLATFORM_EXPORT RuntimeEnabledFeatures {
private:
{% for feature in standard_features %}
- static bool is_{{feature.class_member_name}}enabled_;
+ static bool {{feature.data_member_name}};
{% endfor %}
};
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/settings_macros.h.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/settings_macros.h.tmpl
index 0171eedeefb..33c2220baa9 100644
--- a/chromium/third_party/blink/renderer/build/scripts/templates/settings_macros.h.tmpl
+++ b/chromium/third_party/blink/renderer/build/scripts/templates/settings_macros.h.tmpl
@@ -8,8 +8,8 @@
#define SETTINGS_GETTERS_AND_SETTERS \
{% for setting in settings %}
- {{setting.type|to_passing_type}} Get{{setting.tokenized_name.to_upper_camel_case()}}() const { return {{setting.name}}_; } \
- void Set{{setting.tokenized_name.to_upper_camel_case()}}({{setting.type|to_passing_type}} {{setting.name}}); \
+ {{setting.type|to_passing_type}} Get{{setting.name.to_upper_camel_case()}}() const { return {{setting.name}}_; } \
+ void Set{{setting.name.to_upper_camel_case()}}({{setting.type|to_passing_type}} {{setting.name}}); \
{% endfor %}
void SetFromStrings(const String& name, const String& value);
// End of SETTINGS_GETTERS_AND_SETTERS.
@@ -34,7 +34,7 @@
#define SETTINGS_SETTER_BODIES \
{% for setting in settings %}
-void Settings::Set{{setting.tokenized_name.to_upper_camel_case()}}({{setting.type|to_passing_type}} {{setting.name}}) { \
+void Settings::Set{{setting.name.to_upper_camel_case()}}({{setting.type|to_passing_type}} {{setting.name}}) { \
if ({{setting.name}}_ == {{setting.name}}) \
return; \
{{setting.name}}_ = {{setting.name}}; \
@@ -46,7 +46,7 @@ void Settings::Set{{setting.tokenized_name.to_upper_camel_case()}}({{setting.typ
void Settings::SetFromStrings(const String& name, const String& value) { \
{% for setting in settings %}
if (name == "{{setting.name}}") { \
- Set{{setting.tokenized_name.to_upper_camel_case()}}( \
+ Set{{setting.name.to_upper_camel_case()}}( \
{% if setting.type == 'String' %}
value \
{% elif setting.type == 'bool' %}
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/style_builder.cc.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/style_builder.cc.tmpl
deleted file mode 100644
index 9d5c0417d2a..00000000000
--- a/chromium/third_party/blink/renderer/build/scripts/templates/style_builder.cc.tmpl
+++ /dev/null
@@ -1,73 +0,0 @@
-{% from 'templates/macros.tmpl' import license, source_files_for_generated_file %}
-{{license()}}
-
-{{source_files_for_generated_file(template_file, input_files)}}
-
-#include "third_party/blink/renderer/core/css/resolver/style_builder.h"
-
-#include "third_party/blink/renderer/core/css/css_property_value.h"
-#include "third_party/blink/renderer/core/css/properties/longhand.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/core/style_builder_functions.h"
-
-namespace blink {
-
-// TODO(crbug.com/751354): Delete this method and call property class methods
-// directly using CSSProperty::Get() once all StyleBuilderFunctions have been
-// moved to property classes.
-void StyleBuilder::ApplyProperty(const CSSProperty& property,
- StyleResolverState& state,
- const CSSValue& value,
- bool isInitial,
- bool isInherit) {
- switch (property.PropertyID()) {
- {% for input_property in properties if input_property.should_declare_functions %}
- {% set property_id = input_property.property_id %}
- {% if input_property.use_property_class_in_stylebuilder %}
- case {{input_property.property_id}}:
- if (isInitial)
- ToLonghand(Get{{property_id}}()).ApplyInitial(state);
- else if (isInherit)
- ToLonghand(Get{{property_id}}()).ApplyInherit(state);
- else
- ToLonghand(Get{{property_id}}()).ApplyValue(state, value);
- return;
- {% else %}
- case {{input_property.property_id}}:
- if (isInitial)
- StyleBuilderFunctions::applyInitial{{property_id}}(state);
- else if (isInherit)
- StyleBuilderFunctions::applyInherit{{property_id}}(state);
- else
- StyleBuilderFunctions::applyValue{{property_id}}(state, value);
- return;
- {% endif %}
-
- {% endfor %}
- case CSSPropertyVariable:
- DCHECK(!isInitial);
- DCHECK(!isInherit);
- StyleBuilderFunctions::applyValueCSSPropertyVariable(state, value);
- return;
- {% for input_property in properties if input_property.direction_aware_options %}
- case {{input_property.property_id}}:
- {% endfor %}
- {
- const CSSProperty& resolved_property =
- property.ResolveDirectionAwareProperty(state.Style()->Direction(),
- state.Style()->GetWritingMode());
- DCHECK(!resolved_property.IDEquals(property.PropertyID()));
- ApplyProperty(resolved_property, state, value);
- return;
- }
- {% for input_property in properties if input_property.builder_skip %}
- case {{input_property.property_id}}:
- {% endfor %}
- return;
- default:
- NOTREACHED();
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/style_builder_functions.cc.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/style_builder_functions.cc.tmpl
deleted file mode 100644
index 1907e3eb9e4..00000000000
--- a/chromium/third_party/blink/renderer/build/scripts/templates/style_builder_functions.cc.tmpl
+++ /dev/null
@@ -1,176 +0,0 @@
-{% from 'templates/macros.tmpl' import license, source_files_for_generated_file %}
-{% from 'core/css/properties/templates/style_builder_functions.tmpl' import set_value, convert_and_set_value %}
-
-{#
- This file is for property handlers which use the templating engine to
- reduce (handwritten) code duplication.
-
- The `properties' dict can be used to access a property's parameters in
- jinja2 templates (i.e. setter, getter, initial, type_name)
-
- TODO(meade): Delete this file once all StyleBuilderFunction generation
- is moved to the CSSProperty.
-#}
-
-{{source_files_for_generated_file(template_file, input_files)}}
-
-#include "third_party/blink/renderer/core/style_builder_functions.h"
-
-#include "third_party/blink/renderer/core/animation/css/css_animation_data.h"
-#include "third_party/blink/renderer/core/css/basic_shape_functions.h"
-#include "third_party/blink/renderer/core/css/css_content_distribution_value.h"
-#include "third_party/blink/renderer/core/css/css_custom_ident_value.h"
-#include "third_party/blink/renderer/core/css/css_primitive_value_mappings.h"
-#include "third_party/blink/renderer/core/css/css_uri_value.h"
-#include "third_party/blink/renderer/core/css/css_value_pair.h"
-#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h"
-#include "third_party/blink/renderer/core/css_value_keywords.h"
-#include "third_party/blink/renderer/core/style/computed_style.h"
-
-{% macro declare_initial_function(property_id) %}
-void StyleBuilderFunctions::applyInitial{{property_id}}(StyleResolverState& state)
-{%- endmacro %}
-{% macro declare_inherit_function(property_id) %}
-void StyleBuilderFunctions::applyInherit{{property_id}}(StyleResolverState& state)
-{%- endmacro %}
-{% macro declare_value_function(property_id) %}
-void StyleBuilderFunctions::applyValue{{property_id}}(StyleResolverState& state, const CSSValue& value)
-{%- endmacro %}
-{% macro set_is_inherited(property) %}
-state.Style()->{{property.is_inherited_setter}}
-{%- endmacro %}
-
-namespace blink {
-
-{% for property in properties if property.should_declare_functions
- and not property.use_property_class_in_stylebuilder
- and not property.style_builder_template %}
-{% if property.style_builder_generate_initial %}
-{{declare_initial_function(property.property_id)}} {
- {% if property.svg %}
- {{set_value(property)}}(SVGComputedStyle::{{property.initial}}());
- {% elif property.font %}
- {{set_value(property)}}(FontBuilder::{{property.initial}}());
- {% else %}
- {{set_value(property)}}(ComputedStyleInitialValues::{{property.initial}}());
- {% endif %}
- {% if property.independent %}
- {{set_is_inherited(property)}}(false);
- {% endif %}
-}
-
-{% endif %}
-{% if property.style_builder_generate_inherit %}
-{{declare_inherit_function(property.property_id)}} {
- {% if property.svg %}
- {{set_value(property)}}(state.ParentStyle()->SvgStyle().{{property.getter}}());
- {% elif property.font %}
- {{set_value(property)}}(state.ParentFontDescription().{{property.getter}}());
- {% else %}
- {{set_value(property)}}(state.ParentStyle()->{{property.getter}}());
- {% endif %}
- {% if property.independent %}
- {{set_is_inherited(property)}}(true);
- {% endif %}
-}
-
-{% endif %}
-{% if property.style_builder_generate_value %}
-{{declare_value_function(property.property_id)}} {
- {{convert_and_set_value(property)}}
- {% if property.independent %}
- {{set_is_inherited(property)}}(false);
- {% endif %}
-}
-
-{% endif %}
-{% endfor %}
-
-{% macro apply_grid_template(property_id, type) %}
-{{declare_initial_function(property_id)}} {
- state.Style()->SetGridTemplate{{type}}s(ComputedStyleInitialValues::InitialGridTemplate{{type}}s());
- state.Style()->SetNamedGrid{{type}}Lines(ComputedStyleInitialValues::InitialNamedGrid{{type}}Lines());
- state.Style()->SetOrderedNamedGrid{{type}}Lines(ComputedStyleInitialValues::InitialOrderedNamedGrid{{type}}Lines());
- state.Style()->SetGridAutoRepeat{{type}}s(ComputedStyleInitialValues::InitialGridAutoRepeat{{type}}s());
- state.Style()->SetGridAutoRepeat{{type}}sInsertionPoint(ComputedStyleInitialValues::InitialGridAutoRepeat{{type}}sInsertionPoint());
- state.Style()->SetAutoRepeatNamedGrid{{type}}Lines(ComputedStyleInitialValues::InitialNamedGrid{{type}}Lines());
- state.Style()->SetAutoRepeatOrderedNamedGrid{{type}}Lines(ComputedStyleInitialValues::InitialOrderedNamedGrid{{type}}Lines());
- state.Style()->SetGridAutoRepeat{{type}}sType(ComputedStyleInitialValues::InitialGridAutoRepeat{{type}}sType());
-
-}
-
-{{declare_inherit_function(property_id)}} {
- state.Style()->SetGridTemplate{{type}}s(state.ParentStyle()->GridTemplate{{type}}s());
- state.Style()->SetNamedGrid{{type}}Lines(state.ParentStyle()->NamedGrid{{type}}Lines());
- state.Style()->SetOrderedNamedGrid{{type}}Lines(state.ParentStyle()->OrderedNamedGrid{{type}}Lines());
- state.Style()->SetGridAutoRepeat{{type}}s(state.ParentStyle()->GridAutoRepeat{{type}}s());
- state.Style()->SetGridAutoRepeat{{type}}sInsertionPoint(state.ParentStyle()->GridAutoRepeat{{type}}sInsertionPoint());
- state.Style()->SetAutoRepeatNamedGrid{{type}}Lines(state.ParentStyle()->AutoRepeatNamedGrid{{type}}Lines());
- state.Style()->SetAutoRepeatOrderedNamedGrid{{type}}Lines(state.ParentStyle()->AutoRepeatOrderedNamedGrid{{type}}Lines());
- state.Style()->SetGridAutoRepeat{{type}}sType(state.ParentStyle()->GridAutoRepeat{{type}}sType());
-}
-
-{{declare_value_function(property_id)}} {
- Vector<GridTrackSize> trackSizes;
- Vector<GridTrackSize> autoRepeatTrackSizes;
- NamedGridLinesMap namedGridLines;
- OrderedNamedGridLines orderedNamedGridLines;
- NamedGridLinesMap autoRepeatNamedGridLines;
- OrderedNamedGridLines autoRepeatOrderedNamedGridLines;
- AutoRepeatType autoRepeatType = ComputedStyleInitialValues::InitialGridAutoRepeatType();
- size_t autoRepeatInsertionPoint =
- ComputedStyleInitialValues::InitialGridAutoRepeatInsertionPoint();
- StyleBuilderConverter::ConvertGridTrackList(
- value, trackSizes, namedGridLines, orderedNamedGridLines,
- autoRepeatTrackSizes, autoRepeatNamedGridLines,
- autoRepeatOrderedNamedGridLines, autoRepeatInsertionPoint,
- autoRepeatType, state);
- const NamedGridAreaMap& namedGridAreas = state.Style()->NamedGridArea();
- if (!namedGridAreas.IsEmpty()) {
- StyleBuilderConverter::CreateImplicitNamedGridLinesFromGridArea(
- namedGridAreas, namedGridLines, kFor{{type}}s);
- }
- state.Style()->SetGridTemplate{{type}}s(trackSizes);
- state.Style()->SetNamedGrid{{type}}Lines(namedGridLines);
- state.Style()->SetOrderedNamedGrid{{type}}Lines(orderedNamedGridLines);
- state.Style()->SetGridAutoRepeat{{type}}s(autoRepeatTrackSizes);
- state.Style()->SetGridAutoRepeat{{type}}sInsertionPoint(
- autoRepeatInsertionPoint);
- state.Style()->SetAutoRepeatNamedGrid{{type}}Lines(autoRepeatNamedGridLines);
- state.Style()->SetAutoRepeatOrderedNamedGrid{{type}}Lines(
- autoRepeatOrderedNamedGridLines);
- state.Style()->SetGridAutoRepeat{{type}}sType(autoRepeatType);
-}
-{% endmacro %}
-{{apply_grid_template('CSSPropertyGridTemplateColumns', 'Column')}}
-{{apply_grid_template('CSSPropertyGridTemplateRows', 'Row')}}
-
-{% macro apply_svg_paint(property_id, paint_type) %}
-{% set property = properties_by_id[property_id] %}
-{% set visited_link_setter = 'SetVisitedLink' + paint_type %}
-{{declare_initial_function(property_id)}} {
- if (state.ApplyPropertyToRegularStyle())
- {{set_value(property)}}(SVGComputedStyle::Initial{{paint_type}}());
- if (state.ApplyPropertyToVisitedLinkStyle())
- state.Style()->AccessSVGStyle().{{visited_link_setter}}(SVGComputedStyle::Initial{{paint_type}}());
-}
-
-{{declare_inherit_function(property_id)}} {
- const SVGComputedStyle& parent_svg_style = state.ParentStyle()->SvgStyle();
- if (state.ApplyPropertyToRegularStyle())
- {{set_value(property)}}(parent_svg_style.{{paint_type}}());
- if (state.ApplyPropertyToVisitedLinkStyle())
- state.Style()->AccessSVGStyle().{{visited_link_setter}}(parent_svg_style.{{paint_type}}());
-}
-
-{{declare_value_function(property_id)}} {
- SVGPaint paint = StyleBuilderConverter::ConvertSVGPaint(state, value);
- if (state.ApplyPropertyToRegularStyle())
- {{set_value(property)}}(paint);
- if (state.ApplyPropertyToVisitedLinkStyle())
- state.Style()->AccessSVGStyle().{{visited_link_setter}}(paint);
-}
-{% endmacro %}
-{{apply_svg_paint('CSSPropertyFill', 'FillPaint')}}
-{{apply_svg_paint('CSSPropertyStroke', 'StrokePaint')}}
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/style_builder_functions.h.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/style_builder_functions.h.tmpl
deleted file mode 100644
index f5c84f5d3e4..00000000000
--- a/chromium/third_party/blink/renderer/build/scripts/templates/style_builder_functions.h.tmpl
+++ /dev/null
@@ -1,35 +0,0 @@
-{% from 'templates/macros.tmpl' import license, source_files_for_generated_file %}
-{{license()}}
-
-{{source_files_for_generated_file(template_file, input_files)}}
-
-#ifndef BLINK_CORE_STYLE_BUILDER_FUNCTIONS_H_
-#define BLINK_CORE_STYLE_BUILDER_FUNCTIONS_H_
-
-#include "third_party/blink/renderer/core/css/resolver/style_builder_converter.h"
-
-namespace blink {
-
-class CSSValue;
-class StyleResolverState;
-
-// TODO(crbug.com/751354): Delete this class once all StyleBuilderFunctions
-// have been moved to property classes.
-class StyleBuilderFunctions {
- public:
-
- {% for property in properties if property.should_declare_functions
- and not property.use_property_class_in_stylebuilder %}
- static void applyInitial{{property.property_id}}(StyleResolverState&);
- static void applyInherit{{property.property_id}}(StyleResolverState&);
- static void applyValue{{property.property_id}}(StyleResolverState&, const CSSValue&);
-
- {% endfor %}
-
- static void applyValueCSSPropertyVariable(StyleResolverState&,
- const CSSValue&);
-};
-
-} // namespace blink
-
-#endif // BLINK_CORE_STYLE_BUILDER_FUNCTIONS_H_
diff --git a/chromium/third_party/blink/renderer/build/scripts/templates/web_origin_trials.cc.tmpl b/chromium/third_party/blink/renderer/build/scripts/templates/web_origin_trials.cc.tmpl
new file mode 100644
index 00000000000..657c373b880
--- /dev/null
+++ b/chromium/third_party/blink/renderer/build/scripts/templates/web_origin_trials.cc.tmpl
@@ -0,0 +1,27 @@
+{% from 'templates/macros.tmpl' import license, source_files_for_generated_file %}
+{{license()}}
+
+{{source_files_for_generated_file(template_file, input_files)}}
+
+#include "third_party/blink/public/web/web_origin_trials.h"
+
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/web/web_document.h"
+
+namespace blink {
+
+bool WebOriginTrials::isTrialEnabled(const WebDocument* web_document, const WebString& trial) {
+ if (!web_document) return false;
+{% for feature in features %}
+{% if feature.origin_trial_feature_name %}
+ if (trial == OriginTrials::k{{feature.name}}TrialName)
+ return OriginTrials::{{feature.name}}Enabled(*web_document);
+{% endif %}
+{% endfor %}
+ return false;
+}
+
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/build/scripts/update_css_ranking.py b/chromium/third_party/blink/renderer/build/scripts/update_css_ranking.py
index e2b3689059c..96b0e5decb4 100644
--- a/chromium/third_party/blink/renderer/build/scripts/update_css_ranking.py
+++ b/chromium/third_party/blink/renderer/build/scripts/update_css_ranking.py
@@ -85,17 +85,17 @@ def produce_partition_rule(config_file, css_ranking_api):
[float(i) / total_css_properties for i in range(total_css_properties)]))
css_properties = json5_generator.Json5File.load_from_files([CSS_PROPERTIES]).name_dictionaries
- rare_non_inherited_properties = sorted([(x["name"], css_ranking_dictionary[x["name"]])
+ rare_non_inherited_properties = sorted([(x["name"].original, css_ranking_dictionary[x["name"].original])
for x in css_properties if not x["inherited"]
and x["field_group"] is not None
and "*" in x["field_group"]
- and x["name"] in css_ranking_dictionary],
+ and x["name"].original in css_ranking_dictionary],
key=lambda x: -x[1])
- rare_inherited_properties = sorted([(x["name"], css_ranking_dictionary[x["name"]])
+ rare_inherited_properties = sorted([(x["name"].original, css_ranking_dictionary[x["name"].original])
for x in css_properties if x["inherited"]
and x["field_group"] is not None
and "*" in x["field_group"]
- and x["name"] in css_ranking_dictionary],
+ and x["name"].original in css_ranking_dictionary],
key=lambda x: -x[1])
rni_properties_rule = find_partition_rule(rare_non_inherited_properties,
diff --git a/chromium/third_party/blink/renderer/config.gni b/chromium/third_party/blink/renderer/config.gni
index 42903e7b2f6..601971c6c7c 100644
--- a/chromium/third_party/blink/renderer/config.gni
+++ b/chromium/third_party/blink/renderer/config.gni
@@ -36,6 +36,9 @@ declare_args() {
# If true, ffmpeg will be used for decoding audio.
use_webaudio_ffmpeg = !is_mac && !is_android
+
+ # If true, webgl2-compute context will be supported.
+ support_webgl2_compute_context = !is_android
}
# Whether Android build uses OpenMAX DL FFT. Currently supported only on
@@ -62,6 +65,10 @@ if (use_webaudio_ffmpeg) {
feature_defines_list += [ "WTF_USE_WEBAUDIO_FFMPEG=1" ]
}
+if (support_webgl2_compute_context) {
+ feature_defines_list += [ "SUPPORT_WEBGL2_COMPUTE_CONTEXT=1" ]
+}
+
if (use_openmax_dl_fft) {
feature_defines_list += [ "WTF_USE_WEBAUDIO_OPENMAX_DL_FFT=1" ]
}
diff --git a/chromium/third_party/blink/renderer/controller/blink_initializer.cc b/chromium/third_party/blink/renderer/controller/blink_initializer.cc
index 16731148c94..3c95d67dff2 100644
--- a/chromium/third_party/blink/renderer/controller/blink_initializer.cc
+++ b/chromium/third_party/blink/renderer/controller/blink_initializer.cc
@@ -44,6 +44,8 @@
#include "third_party/blink/renderer/controller/bloated_renderer_detector.h"
#include "third_party/blink/renderer/controller/dev_tools_frontend_impl.h"
#include "third_party/blink/renderer/core/animation/animation_clock.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/display_cutout_client_impl.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/platform/bindings/microtask.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
@@ -158,8 +160,17 @@ void BlinkInitializer::RegisterInterfaces(
}
void BlinkInitializer::InitLocalFrame(LocalFrame& frame) const {
+ if (RuntimeEnabledFeatures::DisplayCutoutAPIEnabled()) {
+ frame.GetInterfaceRegistry()->AddAssociatedInterface(WTF::BindRepeating(
+ &DisplayCutoutClientImpl::BindMojoRequest, WrapWeakPersistent(&frame)));
+ }
frame.GetInterfaceRegistry()->AddAssociatedInterface(WTF::BindRepeating(
&DevToolsFrontendImpl::BindMojoRequest, WrapWeakPersistent(&frame)));
+ frame.GetInterfaceRegistry()->AddInterface(WTF::BindRepeating(
+ &LocalFrame::PauseSubresourceLoading, WrapWeakPersistent(&frame)));
+ frame.GetInterfaceRegistry()->AddInterface(
+ WTF::BindRepeating(&LocalFrame::BindPreviewsResourceLoadingHintsRequest,
+ WrapWeakPersistent(&frame)));
ModulesInitializer::InitLocalFrame(frame);
}
diff --git a/chromium/third_party/blink/renderer/controller/blink_leak_detector.cc b/chromium/third_party/blink/renderer/controller/blink_leak_detector.cc
index 0d87117ff23..9982d2c52fd 100644
--- a/chromium/third_party/blink/renderer/controller/blink_leak_detector.cc
+++ b/chromium/third_party/blink/renderer/controller/blink_leak_detector.cc
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h"
#include "third_party/blink/renderer/core/core_initializer.h"
#include "third_party/blink/renderer/core/css/css_default_style_sheets.h"
+#include "third_party/blink/renderer/core/dom/document.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/web_local_frame_impl.h"
diff --git a/chromium/third_party/blink/renderer/controller/bloated_renderer_detector.cc b/chromium/third_party/blink/renderer/controller/bloated_renderer_detector.cc
index 459e076aa80..c17f99b6e56 100644
--- a/chromium/third_party/blink/renderer/controller/bloated_renderer_detector.cc
+++ b/chromium/third_party/blink/renderer/controller/bloated_renderer_detector.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/controller/bloated_renderer_detector.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
+#include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h"
namespace blink {
@@ -22,11 +23,14 @@ BloatedRendererDetector::OnNearV8HeapLimitOnMainThread() {
NearV8HeapLimitHandling
BloatedRendererDetector::OnNearV8HeapLimitOnMainThreadImpl() {
- WTF::TimeDelta uptime = (WTF::CurrentTimeTicks() - startup_time_);
- if (uptime.InMinutes() < kMinimumUptimeInMinutes) {
- return NearV8HeapLimitHandling::kIgnoredDueToSmallUptime;
+ if (!RuntimeEnabledFeatures::
+ BloatedRendererDetectionSkipUptimeCheckEnabled()) {
+ WTF::TimeDelta uptime = (WTF::CurrentTimeTicks() - startup_time_);
+ if (uptime.InMinutes() < kMinimumUptimeInMinutes) {
+ return NearV8HeapLimitHandling::kIgnoredDueToSmallUptime;
+ }
}
- // TODO(ulan): Send message to the browser.
+ RendererResourceCoordinator::Get().OnRendererIsBloated();
return NearV8HeapLimitHandling::kForwardedToBrowser;
}
diff --git a/chromium/third_party/blink/renderer/controller/bloated_renderer_detector_test.cc b/chromium/third_party/blink/renderer/controller/bloated_renderer_detector_test.cc
index e5577c32888..7172996d91a 100644
--- a/chromium/third_party/blink/renderer/controller/bloated_renderer_detector_test.cc
+++ b/chromium/third_party/blink/renderer/controller/bloated_renderer_detector_test.cc
@@ -4,41 +4,38 @@
#include "third_party/blink/renderer/controller/bloated_renderer_detector.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/testing/wtf/scoped_mock_clock.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink {
class BloatedRendererDetectorTest : public testing::Test {
public:
- static double GetMockLargeUptime() {
- int large_uptime = BloatedRendererDetector::kMinimumUptimeInMinutes + 1;
- return WTF::TimeTicksInSeconds(
- WTF::TimeTicksFromSeconds(large_uptime * 60));
+ static TimeDelta GetMockLargeUptime() {
+ return TimeDelta::FromMinutes(
+ BloatedRendererDetector::kMinimumUptimeInMinutes + 1);
}
- static double GetMockSmallUptime() {
- int small_uptime = BloatedRendererDetector::kMinimumUptimeInMinutes - 1;
- return WTF::TimeTicksInSeconds(
- WTF::TimeTicksFromSeconds(small_uptime * 60));
+ static TimeDelta GetMockSmallUptime() {
+ return TimeDelta::FromMinutes(
+ BloatedRendererDetector::kMinimumUptimeInMinutes - 1);
}
};
TEST_F(BloatedRendererDetectorTest, ForwardToBrowser) {
- BloatedRendererDetector detector(WTF::TimeTicksFromSeconds(0));
- WTF::TimeFunction original_time_function =
- WTF::SetTimeFunctionsForTesting(GetMockLargeUptime);
+ WTF::ScopedMockClock clock;
+ clock.Advance(GetMockLargeUptime());
+ BloatedRendererDetector detector(TimeTicks{});
EXPECT_EQ(NearV8HeapLimitHandling::kForwardedToBrowser,
detector.OnNearV8HeapLimitOnMainThreadImpl());
- WTF::SetTimeFunctionsForTesting(original_time_function);
}
TEST_F(BloatedRendererDetectorTest, SmallUptime) {
- BloatedRendererDetector detector(WTF::TimeTicksFromSeconds(0));
- WTF::TimeFunction original_time_function =
- SetTimeFunctionsForTesting(GetMockSmallUptime);
+ WTF::ScopedMockClock clock;
+ clock.Advance(GetMockSmallUptime());
+ BloatedRendererDetector detector(TimeTicks{});
EXPECT_EQ(NearV8HeapLimitHandling::kIgnoredDueToSmallUptime,
detector.OnNearV8HeapLimitOnMainThreadImpl());
- WTF::SetTimeFunctionsForTesting(original_time_function);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/controller/oom_intervention_impl.cc b/chromium/third_party/blink/renderer/controller/oom_intervention_impl.cc
index 92aa06edd17..4d9b60c78b1 100644
--- a/chromium/third_party/blink/renderer/controller/oom_intervention_impl.cc
+++ b/chromium/third_party/blink/renderer/controller/oom_intervention_impl.cc
@@ -8,8 +8,8 @@
#include <fcntl.h>
#include <unistd.h>
+#include "base/metrics/histogram_macros.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
-#include "third_party/blink/common/oom_intervention/oom_intervention_types.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -36,17 +36,19 @@ bool ReadFileContents(int fd, char contents[kMaxLineSize]) {
bool CalculateProcessMemoryFootprint(int statm_fd,
int status_fd,
uint64_t* private_footprint,
- uint64_t* swap_footprint) {
+ uint64_t* swap_footprint,
+ uint64_t* vm_size) {
// Get total resident and shared sizes from statm file.
static size_t page_size = getpagesize();
uint64_t resident_pages;
uint64_t shared_pages;
+ uint64_t vm_size_pages;
char line[kMaxLineSize];
if (!ReadFileContents(statm_fd, line))
return false;
- int num_scanned =
- sscanf(line, "%*s %" SCNu64 " %" SCNu64, &resident_pages, &shared_pages);
- if (num_scanned != 2)
+ int num_scanned = sscanf(line, "%" SCNu64 " %" SCNu64 " %" SCNu64,
+ &vm_size_pages, &resident_pages, &shared_pages);
+ if (num_scanned != 3)
return false;
// Get swap size from status file. The format is: VmSwap : 10 kB.
@@ -62,6 +64,7 @@ bool CalculateProcessMemoryFootprint(int statm_fd,
*swap_footprint *= 1024;
*private_footprint =
(resident_pages - shared_pages) * page_size + *swap_footprint;
+ *vm_size = vm_size_pages * page_size;
return true;
}
@@ -80,31 +83,39 @@ uint64_t BlinkMemoryWorkloadCaculator() {
return v8_size + blink_gc_size + partition_alloc_size;
}
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class RendererInterventionEnabledStatus {
+ kDetectionOnlyEnabled = 0,
+ kTriggerEnabled = 1,
+ kDisabledFailedMemoryMetricsFetch = 2,
+ kMaxValue = kDisabledFailedMemoryMetricsFetch
+};
+
+void RecordEnabledStatus(RendererInterventionEnabledStatus status) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Memory.Experimental.OomIntervention.RendererEnabledStatus", status);
+}
+
} // namespace
// static
void OomInterventionImpl::Create(mojom::blink::OomInterventionRequest request) {
- mojo::MakeStrongBinding(
- std::make_unique<OomInterventionImpl>(
- WTF::BindRepeating(&BlinkMemoryWorkloadCaculator)),
- std::move(request));
+ mojo::MakeStrongBinding(std::make_unique<OomInterventionImpl>(),
+ std::move(request));
}
-OomInterventionImpl::OomInterventionImpl(
- MemoryWorkloadCaculator workload_calculator)
- : workload_calculator_(std::move(workload_calculator)),
- timer_(Platform::Current()->MainThread()->GetTaskRunner(),
+OomInterventionImpl::OomInterventionImpl()
+ : timer_(Platform::Current()->MainThread()->GetTaskRunner(),
this,
- &OomInterventionImpl::Check) {
- DCHECK(workload_calculator_);
-}
+ &OomInterventionImpl::Check) {}
OomInterventionImpl::~OomInterventionImpl() {}
void OomInterventionImpl::StartDetection(
mojom::blink::OomInterventionHostPtr host,
base::UnsafeSharedMemoryRegion shared_metrics_buffer,
- uint64_t memory_workload_threshold,
+ mojom::blink::DetectionArgsPtr detection_args,
bool trigger_intervention) {
host_ = std::move(host);
shared_metrics_buffer_ = shared_metrics_buffer.Map();
@@ -116,23 +127,57 @@ void OomInterventionImpl::StartDetection(
if (!status_fd_.is_valid())
status_fd_.reset(open("/proc/self/status", O_RDONLY));
// Disable intervention if we cannot get memory details of current process.
- // TODO(ssid): Add UMA here to make sure we don't stop disable intervention
- // more often than expected.
- if (!statm_fd_.is_valid() || !status_fd_.is_valid())
+ if (!statm_fd_.is_valid() || !status_fd_.is_valid()) {
+ RecordEnabledStatus(
+ RendererInterventionEnabledStatus::kDisabledFailedMemoryMetricsFetch);
return;
+ }
+ RecordEnabledStatus(
+ trigger_intervention
+ ? RendererInterventionEnabledStatus::kTriggerEnabled
+ : RendererInterventionEnabledStatus::kDetectionOnlyEnabled);
- memory_workload_threshold_ = memory_workload_threshold;
+ detection_args_ = std::move(detection_args);
trigger_intervention_ = trigger_intervention;
timer_.Start(TimeDelta(), TimeDelta::FromSeconds(1), FROM_HERE);
}
+OomInterventionMetrics OomInterventionImpl::GetCurrentMemoryMetrics() {
+ OomInterventionMetrics metrics = {};
+ metrics.current_blink_usage_kb = BlinkMemoryWorkloadCaculator() / 1024;
+ uint64_t private_footprint, swap, vm_size;
+ if (CalculateProcessMemoryFootprint(statm_fd_.get(), status_fd_.get(),
+ &private_footprint, &swap, &vm_size)) {
+ metrics.current_private_footprint_kb = private_footprint / 1024;
+ metrics.current_swap_kb = swap / 1024;
+ metrics.current_vm_size_kb = vm_size / 1024;
+ }
+ return metrics;
+}
+
void OomInterventionImpl::Check(TimerBase*) {
DCHECK(host_);
- DCHECK_GT(memory_workload_threshold_, 0UL);
+ DCHECK(statm_fd_.is_valid());
+ DCHECK(status_fd_.is_valid());
- uint64_t workload = workload_calculator_.Run();
- if (workload > memory_workload_threshold_) {
+ OomInterventionMetrics current_memory = GetCurrentMemoryMetrics();
+ bool oom_detected = false;
+
+ oom_detected |= detection_args_->blink_workload_threshold > 0 &&
+ current_memory.current_blink_usage_kb * 1024 >
+ detection_args_->blink_workload_threshold;
+ oom_detected |= detection_args_->private_footprint_threshold > 0 &&
+ current_memory.current_private_footprint_kb * 1024 >
+ detection_args_->private_footprint_threshold;
+ oom_detected |=
+ detection_args_->swap_threshold > 0 &&
+ current_memory.current_swap_kb * 1024 > detection_args_->swap_threshold;
+ oom_detected |= detection_args_->virtual_memory_thresold > 0 &&
+ current_memory.current_vm_size_kb * 1024 >
+ detection_args_->virtual_memory_thresold;
+
+ if (oom_detected) {
host_->OnHighMemoryUsage(trigger_intervention_);
if (trigger_intervention_) {
@@ -142,18 +187,9 @@ void OomInterventionImpl::Check(TimerBase*) {
}
}
- // Write memory metrics to shared buffer accesible by browser.
OomInterventionMetrics* metrics_shared =
static_cast<OomInterventionMetrics*>(shared_metrics_buffer_.memory());
- metrics_shared->current_blink_usage_kb = workload / 1024;
- DCHECK(statm_fd_.is_valid());
- DCHECK(status_fd_.is_valid());
- uint64_t private_footprint, swap;
- if (CalculateProcessMemoryFootprint(statm_fd_.get(), status_fd_.get(),
- &private_footprint, &swap)) {
- metrics_shared->current_private_footprint_kb = private_footprint / 1024;
- metrics_shared->current_swap_kb = swap / 1024;
- }
+ memcpy(metrics_shared, &current_memory, sizeof(OomInterventionMetrics));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/controller/oom_intervention_impl.h b/chromium/third_party/blink/renderer/controller/oom_intervention_impl.h
index 791721cdc34..4d548e15c90 100644
--- a/chromium/third_party/blink/renderer/controller/oom_intervention_impl.h
+++ b/chromium/third_party/blink/renderer/controller/oom_intervention_impl.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CONTROLLER_OOM_INTERVENTION_IMPL_H_
#include "base/files/scoped_file.h"
+#include "third_party/blink/common/oom_intervention/oom_intervention_types.h"
#include "third_party/blink/public/platform/oom_intervention.mojom-blink.h"
#include "third_party/blink/renderer/controller/controller_export.h"
#include "third_party/blink/renderer/core/page/scoped_page_pauser.h"
@@ -22,33 +23,33 @@ class CONTROLLER_EXPORT OomInterventionImpl
public:
static void Create(mojom::blink::OomInterventionRequest);
- using MemoryWorkloadCaculator = base::RepeatingCallback<uint64_t()>;
-
- explicit OomInterventionImpl(MemoryWorkloadCaculator);
+ OomInterventionImpl();
~OomInterventionImpl() override;
// mojom::blink::OomIntervention:
void StartDetection(mojom::blink::OomInterventionHostPtr,
base::UnsafeSharedMemoryRegion shared_metrics_buffer,
- uint64_t memory_workload_threshold,
+ mojom::blink::DetectionArgsPtr detection_args,
bool trigger_intervention) override;
+ protected:
+ // Overridden by test.
+ virtual OomInterventionMetrics GetCurrentMemoryMetrics();
+
private:
FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest, DetectedAndDeclined);
- FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest, CalculatePMFAndSwap);
+ FRIEND_TEST_ALL_PREFIXES(OomInterventionImplTest, CalculateProcessFootprint);
void Check(TimerBase*);
- uint64_t memory_workload_threshold_ = 0;
-
// The file descriptor to current process proc files. The files are kept open
// when detection is on to reduce measurement overhead.
base::ScopedFD statm_fd_;
base::ScopedFD status_fd_;
+ mojom::blink::DetectionArgsPtr detection_args_;
base::WritableSharedMemoryMapping shared_metrics_buffer_;
- MemoryWorkloadCaculator workload_calculator_;
mojom::blink::OomInterventionHostPtr host_;
bool trigger_intervention_ = false;
TaskRunnerTimer<OomInterventionImpl> timer_;
diff --git a/chromium/third_party/blink/renderer/controller/oom_intervention_impl_test.cc b/chromium/third_party/blink/renderer/controller/oom_intervention_impl_test.cc
index 6b6655d4d93..b49e173ea24 100644
--- a/chromium/third_party/blink/renderer/controller/oom_intervention_impl_test.cc
+++ b/chromium/third_party/blink/renderer/controller/oom_intervention_impl_test.cc
@@ -23,6 +23,11 @@ namespace blink {
namespace {
+const uint64_t kTestBlinkThreshold = 80 * 1024;
+const uint64_t kTestPMFThreshold = 160 * 1024;
+const uint64_t kTestSwapThreshold = 500 * 1024;
+const uint64_t kTestVmSizeThreshold = 1024 * 1024;
+
class MockOomInterventionHost : public mojom::blink::OomInterventionHost {
public:
MockOomInterventionHost(mojom::blink::OomInterventionHostRequest request)
@@ -35,50 +40,152 @@ class MockOomInterventionHost : public mojom::blink::OomInterventionHost {
mojo::Binding<mojom::blink::OomInterventionHost> binding_;
};
+// Mock intervention class that has custom method for fetching metrics.
+class MockOomInterventionImpl : public OomInterventionImpl {
+ public:
+ MockOomInterventionImpl() {}
+ ~MockOomInterventionImpl() override {}
+
+ // If metrics are set by calling this method, then GetCurrentMemoryMetrics()
+ // will return the given metrics, else it will calculate metrics from
+ // providers.
+ void SetMetrics(OomInterventionMetrics metrics) {
+ metrics_ = std::make_unique<OomInterventionMetrics>();
+ *metrics_ = metrics;
+ }
+
+ private:
+ OomInterventionMetrics GetCurrentMemoryMetrics() override {
+ if (metrics_)
+ return *metrics_;
+ return OomInterventionImpl::GetCurrentMemoryMetrics();
+ }
+
+ std::unique_ptr<OomInterventionMetrics> metrics_;
+};
+
} // namespace
class OomInterventionImplTest : public testing::Test {
public:
- uint64_t MockMemoryWorkloadCalculator() { return memory_workload_; }
+ void SetUp() override {
+ intervention_ = std::make_unique<MockOomInterventionImpl>();
+ }
+
+ Page* DetectOnceOnBlankPage() {
+ WebViewImpl* web_view = web_view_helper_.InitializeAndLoad("about::blank");
+ Page* page = web_view->MainFrameImpl()->GetFrame()->GetPage();
+ EXPECT_FALSE(page->Paused());
+ mojom::blink::OomInterventionHostPtr host_ptr;
+ MockOomInterventionHost mock_host(mojo::MakeRequest(&host_ptr));
+ base::UnsafeSharedMemoryRegion shm =
+ base::UnsafeSharedMemoryRegion::Create(sizeof(OomInterventionMetrics));
+
+ mojom::blink::DetectionArgsPtr args(mojom::blink::DetectionArgs::New());
+ args->blink_workload_threshold = kTestBlinkThreshold;
+ args->private_footprint_threshold = kTestPMFThreshold;
+ args->swap_threshold = kTestSwapThreshold;
+ args->virtual_memory_thresold = kTestVmSizeThreshold;
+
+ intervention_->StartDetection(std::move(host_ptr), std::move(shm),
+ std::move(args),
+ true /*trigger_intervention*/);
+ test::RunDelayedTasks(TimeDelta::FromSeconds(1));
+ return page;
+ }
protected:
- uint64_t memory_workload_ = 0;
+ std::unique_ptr<MockOomInterventionImpl> intervention_;
FrameTestHelpers::WebViewHelper web_view_helper_;
};
-TEST_F(OomInterventionImplTest, DetectedAndDeclined) {
- WebViewImpl* web_view = web_view_helper_.InitializeAndLoad("about::blank");
- Page* page = web_view->MainFrameImpl()->GetFrame()->GetPage();
+TEST_F(OomInterventionImplTest, NoDetectionOnBelowThreshold) {
+ OomInterventionMetrics mock_metrics = {};
+ // Set value less than the threshold to not trigger intervention.
+ mock_metrics.current_blink_usage_kb = (kTestBlinkThreshold / 1024) - 1;
+ mock_metrics.current_private_footprint_kb = (kTestPMFThreshold / 1024) - 1;
+ mock_metrics.current_swap_kb = (kTestSwapThreshold / 1024) - 1;
+ mock_metrics.current_vm_size_kb = (kTestVmSizeThreshold / 1024) - 1;
+ intervention_->SetMetrics(mock_metrics);
+
+ Page* page = DetectOnceOnBlankPage();
+
EXPECT_FALSE(page->Paused());
+}
+
+TEST_F(OomInterventionImplTest, BlinkThresholdDetection) {
+ OomInterventionMetrics mock_metrics = {};
+ // Set value more than the threshold to not trigger intervention.
+ mock_metrics.current_blink_usage_kb = (kTestBlinkThreshold / 1024) + 1;
+ mock_metrics.current_private_footprint_kb = (kTestPMFThreshold / 1024) - 1;
+ mock_metrics.current_swap_kb = (kTestSwapThreshold / 1024) - 1;
+ mock_metrics.current_vm_size_kb = (kTestVmSizeThreshold / 1024) - 1;
+ intervention_->SetMetrics(mock_metrics);
+
+ Page* page = DetectOnceOnBlankPage();
- auto intervention = std::make_unique<OomInterventionImpl>(
- WTF::BindRepeating(&OomInterventionImplTest::MockMemoryWorkloadCalculator,
- WTF::Unretained(this)));
+ EXPECT_TRUE(page->Paused());
+ intervention_.reset();
EXPECT_FALSE(page->Paused());
+}
- // Assign an arbitrary threshold and report workload bigger than the
- // threshold.
- uint64_t threshold = 80;
- intervention->memory_workload_threshold_ = threshold;
- memory_workload_ = threshold + 1;
+TEST_F(OomInterventionImplTest, PmfThresholdDetection) {
+ OomInterventionMetrics mock_metrics = {};
+ mock_metrics.current_blink_usage_kb = (kTestBlinkThreshold / 1024) - 1;
+ // Set value more than the threshold to trigger intervention.
+ mock_metrics.current_private_footprint_kb = (kTestPMFThreshold / 1024) + 1;
+ mock_metrics.current_swap_kb = (kTestSwapThreshold / 1024) - 1;
+ mock_metrics.current_vm_size_kb = (kTestVmSizeThreshold / 1024) - 1;
+ intervention_->SetMetrics(mock_metrics);
+
+ Page* page = DetectOnceOnBlankPage();
- mojom::blink::OomInterventionHostPtr host_ptr;
- MockOomInterventionHost mock_host(mojo::MakeRequest(&host_ptr));
- base::UnsafeSharedMemoryRegion shm =
- base::UnsafeSharedMemoryRegion::Create(sizeof(OomInterventionMetrics));
- intervention->StartDetection(std::move(host_ptr), std::move(shm), threshold,
- true /*trigger_intervention*/);
- test::RunDelayedTasks(TimeDelta::FromSeconds(1));
EXPECT_TRUE(page->Paused());
+ intervention_.reset();
+ EXPECT_FALSE(page->Paused());
+}
- intervention.reset();
+TEST_F(OomInterventionImplTest, SwapThresholdDetection) {
+ OomInterventionMetrics mock_metrics = {};
+ mock_metrics.current_blink_usage_kb = (kTestBlinkThreshold / 1024) - 1;
+ mock_metrics.current_private_footprint_kb = (kTestPMFThreshold / 1024) - 1;
+ // Set value more than the threshold to trigger intervention.
+ mock_metrics.current_swap_kb = (kTestSwapThreshold / 1024) + 1;
+ mock_metrics.current_vm_size_kb = (kTestVmSizeThreshold / 1024) - 1;
+ intervention_->SetMetrics(mock_metrics);
+
+ Page* page = DetectOnceOnBlankPage();
+
+ EXPECT_TRUE(page->Paused());
+ intervention_.reset();
EXPECT_FALSE(page->Paused());
}
-TEST_F(OomInterventionImplTest, CalculatePMFAndSwap) {
- const char kStatmFile[] = "100 40 25 0 0";
+TEST_F(OomInterventionImplTest, VmSizeThresholdDetection) {
+ OomInterventionMetrics mock_metrics = {};
+ mock_metrics.current_blink_usage_kb = (kTestBlinkThreshold / 1024) - 1;
+ mock_metrics.current_private_footprint_kb = (kTestPMFThreshold / 1024) - 1;
+ mock_metrics.current_swap_kb = (kTestSwapThreshold / 1024) - 1;
+ // Set value more than the threshold to trigger intervention.
+ mock_metrics.current_vm_size_kb = (kTestVmSizeThreshold / 1024) + 1;
+ intervention_->SetMetrics(mock_metrics);
+
+ Page* page = DetectOnceOnBlankPage();
+
+ EXPECT_TRUE(page->Paused());
+ intervention_.reset();
+ EXPECT_FALSE(page->Paused());
+}
+
+TEST_F(OomInterventionImplTest, CalculateProcessFootprint) {
const char kStatusFile[] =
"First: 1\n Second: 2 kB\nVmSwap: 10 kB \n Third: 10 kB\n Last: 8";
+ const char kStatmFile[] = "100 40 25 0 0";
+ uint64_t expected_swap_kb = 10;
+ uint64_t expected_private_footprint_kb =
+ (40 - 25) * getpagesize() / 1024 + expected_swap_kb;
+ uint64_t expected_vm_size_kb = 100 * getpagesize() / 1024;
+
base::FilePath statm_path;
EXPECT_TRUE(base::CreateTemporaryFile(&statm_path));
EXPECT_EQ(static_cast<int>(sizeof(kStatmFile)),
@@ -92,29 +199,25 @@ TEST_F(OomInterventionImplTest, CalculatePMFAndSwap) {
base::File status_file(status_path,
base::File::FLAG_OPEN | base::File::FLAG_READ);
- auto intervention = std::make_unique<OomInterventionImpl>(
- WTF::BindRepeating(&OomInterventionImplTest::MockMemoryWorkloadCalculator,
- WTF::Unretained(this)));
- intervention->statm_fd_.reset(statm_file.TakePlatformFile());
- intervention->status_fd_.reset(status_file.TakePlatformFile());
+ intervention_->statm_fd_.reset(statm_file.TakePlatformFile());
+ intervention_->status_fd_.reset(status_file.TakePlatformFile());
mojom::blink::OomInterventionHostPtr host_ptr;
MockOomInterventionHost mock_host(mojo::MakeRequest(&host_ptr));
base::UnsafeSharedMemoryRegion shm =
base::UnsafeSharedMemoryRegion::Create(sizeof(OomInterventionMetrics));
- uint64_t threshold = 80;
- intervention->memory_workload_threshold_ = threshold;
- memory_workload_ = threshold - 1;
- intervention->StartDetection(std::move(host_ptr), std::move(shm), threshold,
- false /*trigger_intervention*/);
+ mojom::blink::DetectionArgsPtr args(mojom::blink::DetectionArgs::New());
+ intervention_->StartDetection(std::move(host_ptr), std::move(shm),
+ std::move(args),
+ false /*trigger_intervention*/);
- intervention->Check(nullptr);
+ intervention_->Check(nullptr);
OomInterventionMetrics* metrics = static_cast<OomInterventionMetrics*>(
- intervention->shared_metrics_buffer_.memory());
- uint64_t swap_kb = 10;
- uint64_t pmf_kb = (40 - 25) * getpagesize() / 1024 + swap_kb;
- EXPECT_EQ(pmf_kb, metrics->current_private_footprint_kb);
- EXPECT_EQ(swap_kb, metrics->current_swap_kb);
+ intervention_->shared_metrics_buffer_.memory());
+ EXPECT_EQ(expected_private_footprint_kb,
+ metrics->current_private_footprint_kb);
+ EXPECT_EQ(expected_swap_kb, metrics->current_swap_kb);
+ EXPECT_EQ(expected_vm_size_kb, metrics->current_vm_size_kb);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/BUILD.gn b/chromium/third_party/blink/renderer/core/BUILD.gn
index 5dd25558226..fa4dccf5768 100644
--- a/chromium/third_party/blink/renderer/core/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/BUILD.gn
@@ -28,13 +28,6 @@ rel_blink_core_gen_dir = rebase_path(blink_core_output_dir, root_build_dir)
# Config for code that builds as part of core.
config("config") {
defines = [ "BLINK_CORE_IMPLEMENTATION=1" ]
-
- cflags = []
- if (is_win) {
- # Suppress __declspec(dllexport)/extern conflict (C4910).
- cflags += [ "/wd4910" ]
- }
-
if (is_chromecast) {
defines += [ "BLINK_MEDIA_LOG=LOG(INFO)" ]
}
@@ -52,12 +45,7 @@ import("//build/config/pch.gni")
config("blink_core_pch") {
# Add precompiled header (pch) support when enabled, possible and
# making sense.
-
- # Precompiled headers are disabled for jumbo builds because they
- # slow down the build since each pch file is only used 1-3
- # times. Not nearly enough to make up for the long time spent
- # creating them.
- if (enable_precompiled_headers && !use_jumbo_build) {
+ if (enable_precompiled_headers) {
if (is_win) {
# This is a string rather than a file GN knows about. It has to match
# exactly what's in the /FI flag below, and what might appear in the
@@ -184,7 +172,9 @@ component("core") {
]
deps = [
"//third_party/blink/public/common",
+ "//third_party/blink/renderer/core/accessibility",
"//third_party/blink/renderer/core/animation",
+ "//third_party/blink/renderer/core/aom",
"//third_party/blink/renderer/core/clipboard",
"//third_party/blink/renderer/core/context_features",
"//third_party/blink/renderer/core/css",
@@ -221,6 +211,7 @@ component("core") {
"//third_party/blink/renderer/core/style:svg_style",
"//third_party/blink/renderer/core/svg",
"//third_party/blink/renderer/core/timing",
+ "//third_party/blink/renderer/core/trustedtypes",
"//third_party/blink/renderer/core/typed_arrays",
"//third_party/blink/renderer/core/url",
"//third_party/blink/renderer/core/workers",
@@ -307,6 +298,7 @@ jumbo_source_set("testing") {
"testing/type_conversions.h",
"testing/union_types_test.cc",
"testing/union_types_test.h",
+ "testing/use_mock_scrollbar_settings.h",
"testing/v8/web_core_test_support.cc",
"testing/v8/web_core_test_support.h",
"testing/worker_internals.cc",
@@ -351,6 +343,7 @@ generate_event_interfaces("core_event_interfaces") {
"events/mouse_event.idl",
"events/mutation_event.idl",
"events/page_transition_event.idl",
+ "events/picture_in_picture_control_event.idl",
"events/pointer_event.idl",
"events/pop_state_event.idl",
"events/progress_event.idl",
@@ -669,7 +662,9 @@ css_properties("make_core_generated_css_longhand_property_classes") {
"$blink_core_output_dir/css/properties/longhands/grid_row_start.h",
"$blink_core_output_dir/css/properties/longhands/grid_template_areas.h",
"$blink_core_output_dir/css/properties/longhands/grid_template_columns.h",
+ "$blink_core_output_dir/css/properties/longhands/grid_template_columns.cc",
"$blink_core_output_dir/css/properties/longhands/grid_template_rows.h",
+ "$blink_core_output_dir/css/properties/longhands/grid_template_rows.cc",
"$blink_core_output_dir/css/properties/longhands/height.h",
"$blink_core_output_dir/css/properties/longhands/hyphens.h",
"$blink_core_output_dir/css/properties/longhands/image_orientation.h",
@@ -1128,20 +1123,6 @@ css_properties("make_core_generated_style_property_shorthand") {
]
}
-css_properties("make_core_generated_style_builder") {
- script = "../build/scripts/make_style_builder.py"
- other_inputs = [
- "../build/scripts/templates/style_builder.cc.tmpl",
- "../build/scripts/templates/style_builder_functions.cc.tmpl",
- "../build/scripts/templates/style_builder_functions.h.tmpl",
- ]
- outputs = [
- "$blink_core_output_dir/style_builder.cc",
- "$blink_core_output_dir/style_builder_functions.h",
- "$blink_core_output_dir/style_builder_functions.cc",
- ]
-}
-
css_properties("make_core_generated_cssom_types") {
script = "../build/scripts/core/css/make_cssom_types.py"
other_inputs = [
@@ -1477,6 +1458,30 @@ action("make_core_generated_origin_trials") {
]
}
}
+action("make_core_generated_web_origin_trials") {
+ script = "../build/scripts/make_web_origin_trials.py"
+
+ inputs = scripts_for_json5_files + [
+ "../build/scripts/make_web_origin_trials.py",
+ "../platform/runtime_enabled_features.json5",
+ "../build/scripts/templates/web_origin_trials.cc.tmpl",
+ ]
+ outputs = [
+ "$blink_core_output_dir/exported/web_origin_trials.cc",
+ ]
+
+ args = [
+ rebase_path("../platform/runtime_enabled_features.json5", root_build_dir),
+ "--output_dir",
+ "$rel_blink_core_gen_dir/exported",
+ ]
+ if (is_mac && !use_system_xcode) {
+ args += [
+ "--developer_dir",
+ hermetic_xcode_path,
+ ]
+ }
+}
action_foreach("make_core_generated_bison") {
script = "../build/scripts/rule_bison.py"
@@ -1529,9 +1534,9 @@ targets_generating_sources = [
":make_core_generated_media_feature_names",
":make_core_generated_media_type_names",
":make_core_generated_origin_trials",
- ":make_core_generated_style_builder",
":make_core_generated_style_property_shorthand",
":make_core_generated_svg_names",
+ ":make_core_generated_web_origin_trials",
":make_core_generated_xlink_names",
":make_core_generated_xml_names",
":make_core_generated_xml_ns_names",
@@ -1635,6 +1640,7 @@ jumbo_source_set("unit_tests") {
"animation/animation_test_helper.cc",
"animation/animation_test_helper.h",
"animation/compositor_animations_test.cc",
+ "animation/css/css_animations_test.cc",
"animation/css/css_transition_data_test.cc",
"animation/document_timeline_test.cc",
"animation/effect_input_test.cc",
@@ -1693,6 +1699,8 @@ jumbo_source_set("unit_tests") {
"css/parser/sizes_attribute_parser_test.cc",
"css/parser/sizes_calc_parser_test.cc",
"css/properties/css_parsing_utils_test.cc",
+ "css/resolver/css_variable_data_test.cc",
+ "css/resolver/css_variable_resolver_test.cc",
"css/resolver/font_builder_test.cc",
"css/resolver/font_style_resolver_test.cc",
"css/resolver/match_result_test.cc",
@@ -1703,8 +1711,8 @@ jumbo_source_set("unit_tests") {
"css/selector_query_test.cc",
"css/style_element_test.cc",
"css/style_engine_test.cc",
+ "css/style_environment_variables_test.cc",
"css/style_sheet_contents_test.cc",
- "css/style_sheet_list_test.cc",
"css/threaded/css_parser_threaded_test.cc",
"css/threaded/css_to_length_conversion_data_threaded_test.cc",
"css/threaded/filter_operation_resolver_threaded_test.cc",
@@ -1720,14 +1728,13 @@ jumbo_source_set("unit_tests") {
"dom/events/event_target_test.cc",
"dom/events/listener_leak_test.cc",
"dom/first_letter_pseudo_element_test.cc",
+ "dom/flat_tree_traversal_ng_test.cc",
"dom/flat_tree_traversal_test.cc",
"dom/idle_deadline_test.cc",
"dom/layout_tree_builder_traversal_test.cc",
"dom/live_node_list_registry_test.cc",
"dom/mutation_observer_test.cc",
"dom/names_map_test.cc",
- "dom/ng/flat_tree_traversal_ng_test.cc",
- "dom/ng/slot_assignment_test.cc",
"dom/node_test.cc",
"dom/nth_index_cache_test.cc",
"dom/pausable_object_test.cc",
@@ -1735,6 +1742,7 @@ jumbo_source_set("unit_tests") {
"dom/scripted_animation_controller_test.cc",
"dom/scripted_idle_task_controller_test.cc",
"dom/shadow_dom_v0_test.cc",
+ "dom/slot_assignment_test.cc",
"dom/space_split_string_test.cc",
"dom/static_range_test.cc",
"dom/text_test.cc",
@@ -1814,6 +1822,7 @@ jumbo_source_set("unit_tests") {
"frame/use_counter_test.cc",
"frame/visual_viewport_test.cc",
"geometry/dom_matrix_test.cc",
+ "html/anchor_element_metrics_test.cc",
"html/canvas/canvas_async_blob_creator_test.cc",
"html/canvas/canvas_font_cache_test.cc",
"html/canvas/image_data_test.cc",
@@ -1846,7 +1855,6 @@ jumbo_source_set("unit_tests") {
"html/html_dimension_test.cc",
"html/html_embed_element_test.cc",
"html/html_frame_element_test.cc",
- "html/html_frame_owner_element_test.cc",
"html/html_iframe_element_test.cc",
"html/html_image_element_test.cc",
"html/html_link_element_sizes_attribute_test.cc",
@@ -1857,6 +1865,7 @@ jumbo_source_set("unit_tests") {
"html/html_table_row_element_test.cc",
"html/image_document_test.cc",
"html/imports/html_import_sheets_test.cc",
+ "html/lazy_load_frame_observer_test.cc",
"html/link_element_loading_test.cc",
"html/link_rel_attribute_test.cc",
"html/list_item_ordinal_test.cc",
@@ -1864,6 +1873,7 @@ jumbo_source_set("unit_tests") {
"html/media/html_media_element_event_listeners_test.cc",
"html/media/html_media_element_test.cc",
"html/media/html_video_element_persistent_test.cc",
+ "html/media/html_video_element_test.cc",
"html/media/media_custom_controls_fullscreen_detector_test.cc",
"html/media_element_filling_viewport_test.cc",
"html/parser/atomic_html_token_test.cc",
@@ -1906,6 +1916,7 @@ jumbo_source_set("unit_tests") {
"layout/layout_count_test.cc",
"layout/layout_embedded_content_test.cc",
"layout/layout_geometry_map_test.cc",
+ "layout/layout_image_test.cc",
"layout/layout_inline_test.cc",
"layout/layout_media_test.cc",
"layout/layout_multi_column_flow_thread_test.cc",
@@ -1979,6 +1990,7 @@ jumbo_source_set("unit_tests") {
"loader/mixed_content_checker_test.cc",
"loader/modulescript/module_script_loader_test.cc",
"loader/modulescript/module_tree_linker_test.cc",
+ "loader/navigation_policy_test.cc",
"loader/ping_loader_test.cc",
"loader/programmatic_scroll_test.cc",
"loader/progress_tracker_test.cc",
@@ -1999,7 +2011,6 @@ jumbo_source_set("unit_tests") {
"page/chrome_client_test.cc",
"page/context_menu_controller_test.cc",
"page/drag_controller_test.cc",
- "page/effective_navigation_policy_test.cc",
"page/focus_controller_test.cc",
"page/page_overlay_test.cc",
"page/page_popup_client_test.cc",
@@ -2017,6 +2028,7 @@ jumbo_source_set("unit_tests") {
"paint/block_painter_test.cc",
"paint/box_paint_invalidator_test.cc",
"paint/clip_path_clipper_test.cc",
+ "paint/clip_rect_test.cc",
"paint/compositing/composited_layer_mapping_test.cc",
"paint/compositing/compositing_inputs_updater_test.cc",
"paint/compositing/compositing_layer_assigner_test.cc",
@@ -2028,16 +2040,16 @@ jumbo_source_set("unit_tests") {
"paint/first_meaningful_paint_detector_test.cc",
"paint/fragment_data_test.cc",
"paint/html_canvas_painter_test.cc",
- "paint/layer_clip_recorder_test.cc",
"paint/link_highlight_impl_test.cc",
"paint/ng/ng_paint_fragment_test.cc",
"paint/ng/ng_paint_fragment_traversal_test.cc",
"paint/ng/ng_text_fragment_painter_test.cc",
"paint/nine_piece_image_grid_test.cc",
"paint/object_paint_invalidator_test.cc",
+ "paint/paint_and_raster_invalidation_test.cc",
+ "paint/paint_and_raster_invalidation_test.h",
"paint/paint_controller_paint_test.cc",
"paint/paint_controller_paint_test.h",
- "paint/paint_invalidation_test.cc",
"paint/paint_layer_clipper_test.cc",
"paint/paint_layer_painter_test.cc",
"paint/paint_layer_scrollable_area_test.cc",
@@ -2047,7 +2059,6 @@ jumbo_source_set("unit_tests") {
"paint/paint_property_tree_printer_test.cc",
"paint/paint_property_tree_update_tests.cc",
"paint/pre_paint_tree_walk_test.cc",
- "paint/raster_invalidation_test.cc",
"paint/stub_chrome_client_for_spv2.h",
"paint/table_painter_test.cc",
"paint/text_painter_test.cc",
@@ -2061,10 +2072,10 @@ jumbo_source_set("unit_tests") {
"scheduler/frame_throttling_test.cc",
"scheduler/throttling_test.cc",
"scheduler/virtual_time_test.cc",
+ "script/document_modulator_impl_test.cc",
"script/dynamic_module_resolver_test.cc",
"script/layered_api_test.cc",
"script/mock_script_element_base.h",
- "script/modulator_test.cc",
"script/module_map_test.cc",
"script/script_module_resolver_impl_test.cc",
"script/script_runner_test.cc",
diff --git a/chromium/third_party/blink/renderer/core/DEPS b/chromium/third_party/blink/renderer/core/DEPS
index f5cc566e2a9..0b8a51e8598 100644
--- a/chromium/third_party/blink/renderer/core/DEPS
+++ b/chromium/third_party/blink/renderer/core/DEPS
@@ -2,17 +2,23 @@ include_rules = [
"+base/atomic_sequence_num.h",
"+base/memory/scoped_refptr.h",
"+base/synchronization/waitable_event.h",
+ "+base/task/sequence_manager/task_time_observer.h",
"+base/unguessable_token.h",
"+build/mac",
"+build/win",
"+cc/base/region.h",
+ "+cc/input/browser_controls_state.h",
+ "+cc/input/event_listener_properties.h",
"+cc/input/overscroll_behavior.h",
"+cc/layers/content_layer_client.h",
"+cc/layers/layer.h",
"+cc/layers/layer_position_constraint.h",
"+cc/layers/layer_sticky_position_constraint.h",
+ "+cc/layers/picture_layer.h",
"+cc/layers/scrollbar_layer_interface.h",
"+cc/paint/display_item_list.h",
+ "+cc/paint/paint_canvas.h",
+ "+cc/paint/paint_flags.h",
"+gpu/config/gpu_feature_info.h",
"-inspector/v8",
"+inspector/v8/public",
@@ -20,7 +26,9 @@ include_rules = [
"+mojo/public/cpp/bindings",
"+mojo/public/cpp/system",
"+services/metrics/public",
+ "+services/network/public/cpp/cors/cors_error_status.h",
"+services/network/public/cpp/features.h",
+ "+services/network/public/cpp/shared_url_loader_factory.h",
"+services/network/public/mojom",
"+services/resource_coordinator/public/cpp/resource_coordinator_features.h",
"+services/service_manager/public",
@@ -48,12 +56,20 @@ include_rules = [
specific_include_rules = {
# Additional allowed includes for tests.
- ".*_test\.cc" : [
+ ".*_test(_.*)?\.(cc|h)" : [
+ # Test harness may use cc directly instead of going through WebViewImpl etc.
+ "+cc",
+ # TODO(crbug.com/838693): Test harnesses use LayerTreeView
+ # from content instead of a fake WebLayerTreeView implementation, so
+ # that the Web abstraction can go away.
+ "+content/renderer/gpu",
+ "+content/test",
"+third_party/blink/renderer/core/frame/web_local_frame_impl.h",
"+third_party/blink/renderer/core/frame/web_remote_frame_impl.h",
"+gin"
],
-
+ "data_object_item.cc" : [ "+ui/gfx/codec" ],
+ "clipboard_utilities.cc" : [ "+net/base/escape.h" ],
"find_in_page.cc" : [
"+third_party/blink/renderer/core/frame/web_local_frame_impl.h",
],
diff --git a/chromium/third_party/blink/renderer/core/OWNERS b/chromium/third_party/blink/renderer/core/OWNERS
index a53ea765783..cad509d87b5 100644
--- a/chromium/third_party/blink/renderer/core/OWNERS
+++ b/chromium/third_party/blink/renderer/core/OWNERS
@@ -2,7 +2,6 @@
# For example, core/rendering/OWNERS for rendering changes.
# Reviewers (comments indicate areas of expertise):
-ager@chromium.org
# alancutter reviews changes in core/animation, core/css and core/style.
alancutter@chromium.org
alexis.menard@intel.com
diff --git a/chromium/third_party/blink/renderer/core/accessibility/BUILD.gn b/chromium/third_party/blink/renderer/core/accessibility/BUILD.gn
new file mode 100644
index 00000000000..285ef59c189
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/accessibility/BUILD.gn
@@ -0,0 +1,15 @@
+# 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("accessibility") {
+ sources = [
+ "ax_object_cache.cc",
+ "ax_object_cache.h",
+ "ax_object_cache_base.cc",
+ "ax_object_cache_base.h",
+ "axid.h",
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/core/accessibility/ax_object_cache.cc b/chromium/third_party/blink/renderer/core/accessibility/ax_object_cache.cc
new file mode 100644
index 00000000000..210f4af6a8d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/accessibility/ax_object_cache.cc
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
+
+#include <memory>
+
+#include "base/memory/ptr_util.h"
+#include "third_party/blink/public/web/web_ax_enums.h"
+#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/dom/node.h"
+#include "third_party/blink/renderer/core/html_element_type_helpers.h"
+#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "third_party/blink/renderer/platform/wtf/hash_set.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+AXObjectCache::AXObjectCacheCreateFunction AXObjectCache::create_function_ =
+ nullptr;
+
+void AXObjectCache::Init(AXObjectCacheCreateFunction function) {
+ DCHECK(!create_function_);
+ create_function_ = function;
+}
+
+AXObjectCache* AXObjectCache::Create(Document& document) {
+ DCHECK(create_function_);
+ return create_function_(document);
+}
+
+AXObjectCache::AXObjectCache(Document& document)
+ : ContextLifecycleObserver(document.GetExecutionContext()) {}
+
+AXObjectCache::~AXObjectCache() = default;
+
+std::unique_ptr<ScopedAXObjectCache> ScopedAXObjectCache::Create(
+ Document& document) {
+ return base::WrapUnique(new ScopedAXObjectCache(document));
+}
+
+ScopedAXObjectCache::ScopedAXObjectCache(Document& document)
+ : document_(&document) {
+ if (!document_->GetOrCreateAXObjectCache())
+ cache_ = AXObjectCache::Create(*document_);
+}
+
+ScopedAXObjectCache::~ScopedAXObjectCache() {
+ if (cache_)
+ cache_->Dispose();
+}
+
+AXObjectCache* ScopedAXObjectCache::Get() {
+ if (cache_)
+ return cache_.Get();
+ AXObjectCache* cache = document_->GetOrCreateAXObjectCache();
+ DCHECK(cache);
+ return cache;
+}
+
+namespace {
+
+typedef HashSet<String, CaseFoldingHash> ARIAWidgetSet;
+
+const char* g_aria_widgets[] = {
+ // From http://www.w3.org/TR/wai-aria/roles#widget_roles
+ "alert", "alertdialog", "button", "checkbox", "dialog", "gridcell", "link",
+ "log", "marquee", "menuitem", "menuitemcheckbox", "menuitemradio", "option",
+ "progressbar", "radio", "scrollbar", "slider", "spinbutton", "status",
+ "tab", "tabpanel", "textbox", "timer", "tooltip", "treeitem",
+ // Composite user interface widgets.
+ // This list is also from the w3.org site referenced above.
+ "combobox", "grid", "listbox", "menu", "menubar", "radiogroup", "tablist",
+ "tree", "treegrid"};
+
+static ARIAWidgetSet* CreateARIARoleWidgetSet() {
+ ARIAWidgetSet* widget_set = new HashSet<String, CaseFoldingHash>();
+ for (size_t i = 0; i < arraysize(g_aria_widgets); ++i)
+ widget_set->insert(String(g_aria_widgets[i]));
+ return widget_set;
+}
+
+bool IncludesARIAWidgetRole(const String& role) {
+ static const HashSet<String, CaseFoldingHash>* role_set =
+ CreateARIARoleWidgetSet();
+
+ Vector<String> role_vector;
+ role.Split(' ', role_vector);
+ for (const auto& child : role_vector) {
+ if (role_set->Contains(child))
+ return true;
+ }
+ return false;
+}
+
+const char* g_aria_interactive_widget_attributes[] = {
+ // These attributes implicitly indicate the given widget is interactive.
+ // From http://www.w3.org/TR/wai-aria/states_and_properties#attrs_widgets
+ // clang-format off
+ "aria-activedescendant",
+ "aria-checked",
+ "aria-controls",
+ "aria-disabled", // If it's disabled, it can be made interactive.
+ "aria-haspopup",
+ "aria-multiselectable",
+ "aria-required",
+ "aria-selected"
+ // clang-format on
+};
+
+bool HasInteractiveARIAAttribute(const Element& element) {
+ for (size_t i = 0; i < arraysize(g_aria_interactive_widget_attributes); ++i) {
+ const char* attribute = g_aria_interactive_widget_attributes[i];
+ if (element.hasAttribute(attribute)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace
+
+bool AXObjectCache::IsInsideFocusableElementOrARIAWidget(const Node& node) {
+ const Node* cur_node = &node;
+ do {
+ if (cur_node->IsElementNode()) {
+ const Element* element = ToElement(cur_node);
+ if (element->IsFocusable())
+ return true;
+ String role = element->getAttribute("role");
+ if (!role.IsEmpty() && IncludesARIAWidgetRole(role))
+ return true;
+ if (HasInteractiveARIAAttribute(*element))
+ return true;
+ }
+ cur_node = cur_node->parentNode();
+ } while (cur_node && !IsHTMLBodyElement(node));
+ return false;
+}
+
+void AXObjectCache::Trace(blink::Visitor* visitor) {
+ ContextLifecycleObserver::Trace(visitor);
+}
+
+} // namespace blink
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
new file mode 100644
index 00000000000..b651d3867d1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/accessibility/ax_object_cache.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ACCESSIBILITY_AX_OBJECT_CACHE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_ACCESSIBILITY_AX_OBJECT_CACHE_H_
+
+#include <memory>
+
+#include "base/macros.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/dom/document.h"
+
+namespace blink {
+
+class AbstractInlineTextBox;
+class AccessibleNode;
+class HTMLCanvasElement;
+class HTMLOptionElement;
+class HTMLSelectElement;
+class LayoutMenuList;
+class LineLayoutItem;
+class LocalFrameView;
+
+class CORE_EXPORT AXObjectCache
+ : public GarbageCollectedFinalized<AXObjectCache>,
+ public ContextLifecycleObserver {
+ USING_GARBAGE_COLLECTED_MIXIN(AXObjectCache);
+
+ public:
+ static AXObjectCache* Create(Document&);
+
+ virtual ~AXObjectCache();
+ void Trace(blink::Visitor*) override;
+
+ virtual void Dispose() = 0;
+
+ virtual void SelectionChanged(Node*) = 0;
+ virtual void ChildrenChanged(Node*) = 0;
+ virtual void ChildrenChanged(LayoutObject*) = 0;
+ virtual void ChildrenChanged(AccessibleNode*) = 0;
+ virtual void CheckedStateChanged(Node*) = 0;
+ virtual void ListboxOptionStateChanged(HTMLOptionElement*) = 0;
+ virtual void ListboxSelectedChildrenChanged(HTMLSelectElement*) = 0;
+ virtual void ListboxActiveIndexChanged(HTMLSelectElement*) = 0;
+ virtual void LocationChanged(LayoutObject*) = 0;
+ virtual void RadiobuttonRemovedFromGroup(HTMLInputElement*) = 0;
+
+ virtual void Remove(AccessibleNode*) = 0;
+ virtual void Remove(LayoutObject*) = 0;
+ virtual void Remove(Node*) = 0;
+ virtual void Remove(AbstractInlineTextBox*) = 0;
+
+ virtual const Element* RootAXEditableElement(const Node*) = 0;
+
+ // Called by a node when text or a text equivalent (e.g. alt) attribute is
+ // changed.
+ virtual void TextChanged(LayoutObject*) = 0;
+ virtual void DocumentTitleChanged() = 0;
+ // Called when a node has just been attached, so we can make sure we have the
+ // right subclass of AXObject.
+ virtual void UpdateCacheAfterNodeIsAttached(Node*) = 0;
+ virtual void DidInsertChildrenOfNode(Node*) = 0;
+
+ virtual void HandleAttributeChanged(const QualifiedName& attr_name,
+ Element*) = 0;
+ virtual void HandleFocusedUIElementChanged(Node* old_focused_node,
+ Node* new_focused_node) = 0;
+ virtual void HandleInitialFocus() = 0;
+ virtual void HandleEditableTextContentChanged(Node*) = 0;
+ virtual void HandleScaleAndLocationChanged(Document*) = 0;
+ virtual void HandleTextMarkerDataAdded(Node* start, Node* end) = 0;
+ virtual void HandleTextFormControlChanged(Node*) = 0;
+ virtual void HandleValueChanged(Node*) = 0;
+ virtual void HandleUpdateActiveMenuOption(LayoutMenuList*,
+ int option_index) = 0;
+ virtual void DidShowMenuListPopup(LayoutMenuList*) = 0;
+ virtual void DidHideMenuListPopup(LayoutMenuList*) = 0;
+ virtual void HandleLoadComplete(Document*) = 0;
+ virtual void HandleLayoutComplete(Document*) = 0;
+ virtual void HandleClicked(Node*) = 0;
+
+ // Changes to virtual Accessibility Object Model nodes.
+ virtual void HandleAttributeChanged(const QualifiedName& attr_name,
+ AccessibleNode*) = 0;
+
+ virtual void SetCanvasObjectBounds(HTMLCanvasElement*,
+ Element*,
+ const LayoutRect&) = 0;
+
+ virtual void InlineTextBoxesUpdated(LineLayoutItem) = 0;
+
+ // Called when the scroll offset changes.
+ virtual void HandleScrollPositionChanged(LocalFrameView*) = 0;
+ virtual void HandleScrollPositionChanged(LayoutObject*) = 0;
+
+ // Called when scroll bars are added / removed (as the view resizes).
+ virtual void HandleLayoutComplete(LayoutObject*) = 0;
+ virtual void HandleScrolledToAnchor(const Node* anchor_node) = 0;
+
+ virtual const AtomicString& ComputedRoleForNode(Node*) = 0;
+ virtual String ComputedNameForNode(Node*) = 0;
+
+ virtual void OnTouchAccessibilityHover(const IntPoint&) = 0;
+
+ virtual AXID GetAXID(Node*) = 0;
+ virtual Element* GetElementFromAXID(AXID) = 0;
+
+ typedef AXObjectCache* (*AXObjectCacheCreateFunction)(Document&);
+ static void Init(AXObjectCacheCreateFunction);
+
+ // Static helper functions.
+ static bool IsInsideFocusableElementOrARIAWidget(const Node&);
+
+ protected:
+ AXObjectCache(Document&);
+
+ private:
+ static AXObjectCacheCreateFunction create_function_;
+ DISALLOW_COPY_AND_ASSIGN(AXObjectCache);
+};
+
+class CORE_EXPORT ScopedAXObjectCache {
+ USING_FAST_MALLOC(ScopedAXObjectCache);
+
+ public:
+ static std::unique_ptr<ScopedAXObjectCache> Create(Document&);
+ ~ScopedAXObjectCache();
+
+ AXObjectCache* Get();
+
+ private:
+ explicit ScopedAXObjectCache(Document&);
+
+ Persistent<Document> document_;
+ Persistent<AXObjectCache> cache_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedAXObjectCache);
+};
+
+} // namespace blink
+
+#endif
diff --git a/chromium/third_party/blink/renderer/core/accessibility/ax_object_cache_base.cc b/chromium/third_party/blink/renderer/core/accessibility/ax_object_cache_base.cc
new file mode 100644
index 00000000000..6aad63fec25
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/accessibility/ax_object_cache_base.cc
@@ -0,0 +1,17 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache_base.h"
+
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
+#include "third_party/blink/renderer/core/core_export.h"
+
+namespace blink {
+
+AXObjectCacheBase::~AXObjectCacheBase() = default;
+
+AXObjectCacheBase::AXObjectCacheBase(Document& document)
+ : AXObjectCache(document) {}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/accessibility/ax_object_cache_base.h b/chromium/third_party/blink/renderer/core/accessibility/ax_object_cache_base.h
new file mode 100644
index 00000000000..253a14bb550
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/accessibility/ax_object_cache_base.h
@@ -0,0 +1,41 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ACCESSIBILITY_AX_OBJECT_CACHE_BASE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_ACCESSIBILITY_AX_OBJECT_CACHE_BASE_H_
+
+#include "base/macros.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
+#include "third_party/blink/renderer/core/core_export.h"
+
+namespace blink {
+
+class LayoutObject;
+class Node;
+class AXObject;
+
+// AXObjectCacheBase is a temporary class that sits between AXObjectCache and
+// AXObject and contains methods required by web/ that we don't want to be
+// available in the public API (AXObjectCache).
+// TODO(dmazzoni): Once all dependencies in web/ use this class instead of
+// AXObjectCacheImpl, refactor usages to use AXObjectCache instead (introducing
+// new public API methods or similar) and remove this class.
+class CORE_EXPORT AXObjectCacheBase : public AXObjectCache {
+ public:
+ ~AXObjectCacheBase() override;
+
+ virtual AXObject* Get(const Node*) = 0;
+ virtual AXObject* GetOrCreate(LayoutObject*) = 0;
+
+ protected:
+ AXObjectCacheBase(Document&);
+ DISALLOW_COPY_AND_ASSIGN(AXObjectCacheBase);
+};
+
+// This is the only subclass of AXObjectCache.
+DEFINE_TYPE_CASTS(AXObjectCacheBase, AXObjectCache, cache, true, true);
+
+} // namespace blink
+
+#endif
diff --git a/chromium/third_party/blink/renderer/core/accessibility/axid.h b/chromium/third_party/blink/renderer/core/accessibility/axid.h
new file mode 100644
index 00000000000..812109a3f44
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/accessibility/axid.h
@@ -0,0 +1,12 @@
+// 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_ACCESSIBILITY_AXID_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_ACCESSIBILITY_AXID_H_
+
+namespace blink {
+using AXID = unsigned;
+}
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ACCESSIBILITY_AXID_H_
diff --git a/chromium/third_party/blink/renderer/core/animation/animation.cc b/chromium/third_party/blink/renderer/core/animation/animation.cc
index 77c6a5e8ca7..9dcdf4402b8 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animation.cc
@@ -43,7 +43,6 @@
#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/dom_node_ids.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/events/animation_playback_event.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
@@ -72,7 +71,7 @@ Animation* Animation::Create(AnimationEffect* effect,
ExceptionState& exception_state) {
if (!timeline || !timeline->IsDocumentTimeline()) {
// FIXME: Support creating animations without a timeline.
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"Animations can currently only be "
"created with a non-null "
"DocumentTimeline");
@@ -581,7 +580,7 @@ void Animation::pause(ExceptionState& exception_state) {
if (playback_rate_ < 0 &&
EffectEnd() == std::numeric_limits<double>::infinity()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Cannot pause, Animation has infinite target effect end.");
return;
}
@@ -618,7 +617,7 @@ void Animation::play(ExceptionState& exception_state) {
if (playback_rate_ < 0 && current_time <= 0 &&
EffectEnd() == std::numeric_limits<double>::infinity()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Cannot play reversed Animation with infinite target effect end.");
return;
}
@@ -659,14 +658,14 @@ void Animation::finish(ExceptionState& exception_state) {
if (!playback_rate_) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Cannot finish Animation with a playbackRate of 0.");
return;
}
if (playback_rate_ > 0 &&
EffectEnd() == std::numeric_limits<double>::infinity()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Cannot finish Animation with an infinite target effect end.");
return;
}
@@ -896,7 +895,8 @@ void Animation::StartAnimationOnCompositor(
base::Optional<double> start_time = base::nullopt;
double time_offset = 0;
if (start_time_) {
- start_time = TimelineInternal()->ZeroTime() + start_time_.value();
+ start_time = TimeTicksInSeconds(TimelineInternal()->ZeroTime()) +
+ start_time_.value();
if (reversed)
start_time = start_time.value() - (EffectEnd() / fabs(playback_rate_));
} else {
@@ -1307,7 +1307,7 @@ void Animation::ResolvePromiseMaybeAsync(AnimationPromise* promise) {
}
void Animation::RejectAndResetPromise(AnimationPromise* promise) {
- promise->Reject(DOMException::Create(kAbortError));
+ promise->Reject(DOMException::Create(DOMExceptionCode::kAbortError));
promise->Reset();
}
diff --git a/chromium/third_party/blink/renderer/core/animation/animation.h b/chromium/third_party/blink/renderer/core/animation/animation.h
index a12e603e291..1bbb016bcb8 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation.h
+++ b/chromium/third_party/blink/renderer/core/animation/animation.h
@@ -37,7 +37,6 @@
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_property.h"
#include "third_party/blink/renderer/core/animation/animation_effect.h"
@@ -51,6 +50,7 @@
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_client.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_delegate.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_effect.h b/chromium/third_party/blink/renderer/core/animation/animation_effect.h
index 65a88084a4a..c2c2842f9e2 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_effect.h
+++ b/chromium/third_party/blink/renderer/core/animation/animation_effect.h
@@ -32,9 +32,9 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_ANIMATION_EFFECT_H_
#include "base/optional.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/animation/timing.h"
#include "third_party/blink/renderer/core/core_export.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/heap/handle.h"
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_input_helpers.cc b/chromium/third_party/blink/renderer/core/animation/animation_input_helpers.cc
index 7ccdbc8cc2f..41c79d2cfa2 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_input_helpers.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animation_input_helpers.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/animation/animation_input_helpers.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/animation/property_handle.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
@@ -15,6 +14,7 @@
#include "third_party/blink/renderer/core/svg/animation/svg_smil_element.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/core/svg_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/animation/animation_input_helpers_test.cc b/chromium/third_party/blink/renderer/core/animation/animation_input_helpers_test.cc
index 22dc3043a9a..77fd3ef5044 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_input_helpers_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animation_input_helpers_test.cc
@@ -8,7 +8,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/animation/property_handle.h"
#include "third_party/blink/renderer/core/dom/element.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/animation/timing_function.h"
@@ -62,7 +61,7 @@ class AnimationAnimationInputHelpersTest : public PageTestBase {
scoped_refptr<TimingFunction> timing_function =
ParseTimingFunction(string, exception_state);
EXPECT_TRUE(exception_state.HadException());
- EXPECT_EQ(kV8TypeError, exception_state.Code());
+ EXPECT_EQ(ESErrorType::kTypeError, exception_state.CodeAs<ESErrorType>());
exception_state.ClearException();
}
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 fd01d827daa..345f1d40be8 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
@@ -48,12 +48,14 @@ TEST_F(AnimationSimTest, CustomPropertyBaseComputedStyle) {
// name: '--x',
// syntax: '<percentage>',
// initialValue: '0%',
+ // inherits: false
// })
DummyExceptionStateForTesting exception_state;
PropertyDescriptor property_descriptor;
property_descriptor.setName("--x");
property_descriptor.setSyntax("<percentage>");
property_descriptor.setInitialValue("0%");
+ property_descriptor.setInherits(false);
PropertyRegistration::registerProperty(&GetDocument(), property_descriptor,
exception_state);
EXPECT_FALSE(exception_state.HadException());
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 b5afc684e7a..b36783cd172 100644
--- a/chromium/third_party/blink/renderer/core/animation/animation_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/animation_test.cc
@@ -501,7 +501,8 @@ TEST_F(AnimationAnimationTest, FinishRaisesException) {
animation->finish(exception_state);
EXPECT_EQ(10, animation->CurrentTimeInternal());
EXPECT_TRUE(exception_state.HadException());
- EXPECT_EQ(kInvalidStateError, exception_state.Code());
+ EXPECT_EQ(DOMExceptionCode::kInvalidStateError,
+ exception_state.CodeAs<DOMExceptionCode>());
}
TEST_F(AnimationAnimationTest, LimitingAtEffectEnd) {
diff --git a/chromium/third_party/blink/renderer/core/animation/compositor_animations.cc b/chromium/third_party/blink/renderer/core/animation/compositor_animations.cc
index 72950a94c82..c9013c9c8fa 100644
--- a/chromium/third_party/blink/renderer/core/animation/compositor_animations.cc
+++ b/chromium/third_party/blink/renderer/core/animation/compositor_animations.cc
@@ -367,9 +367,9 @@ void CompositorAnimations::StartAnimationOnCompositor(
const Animation* animation,
CompositorAnimation& compositor_animation,
const EffectModel& effect,
- Vector<int>& started_animation_ids,
+ Vector<int>& started_keyframe_model_ids,
double animation_playback_rate) {
- DCHECK(started_animation_ids.IsEmpty());
+ DCHECK(started_keyframe_model_ids.IsEmpty());
DCHECK(CheckCanStartAnimationOnCompositor(timing, element, animation, effect,
animation_playback_rate)
.Ok());
@@ -385,9 +385,9 @@ void CompositorAnimations::StartAnimationOnCompositor(
for (auto& compositor_keyframe_model : keyframe_models) {
int id = compositor_keyframe_model->Id();
compositor_animation.AddKeyframeModel(std::move(compositor_keyframe_model));
- started_animation_ids.push_back(id);
+ started_keyframe_model_ids.push_back(id);
}
- DCHECK(!started_animation_ids.IsEmpty());
+ DCHECK(!started_keyframe_model_ids.IsEmpty());
}
void CompositorAnimations::CancelAnimationOnCompositor(
diff --git a/chromium/third_party/blink/renderer/core/animation/compositor_animations.h b/chromium/third_party/blink/renderer/core/animation/compositor_animations.h
index bcaa1d40547..1739effe9d1 100644
--- a/chromium/third_party/blink/renderer/core/animation/compositor_animations.h
+++ b/chromium/third_party/blink/renderer/core/animation/compositor_animations.h
@@ -89,16 +89,17 @@ class CORE_EXPORT CompositorAnimations {
static void CancelIncompatibleAnimationsOnCompositor(const Element&,
const Animation&,
const EffectModel&);
- static void StartAnimationOnCompositor(const Element&,
- int group,
- base::Optional<double> start_time,
- double time_offset,
- const Timing&,
- const Animation*,
- CompositorAnimation&,
- const EffectModel&,
- Vector<int>& started_animation_ids,
- double animation_playback_rate);
+ static void StartAnimationOnCompositor(
+ const Element&,
+ int group,
+ base::Optional<double> start_time,
+ double time_offset,
+ const Timing&,
+ const Animation*,
+ CompositorAnimation&,
+ const EffectModel&,
+ Vector<int>& started_keyframe_model_ids,
+ double animation_playback_rate);
static void CancelAnimationOnCompositor(const Element&,
CompositorAnimation*,
int id);
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 486502d5821..d1fcc00f2ea 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
@@ -1210,10 +1210,10 @@ TEST_F(AnimationCompositorAnimationsTest,
.Ok());
// simulate KeyframeEffect::maybeStartAnimationOnCompositor
- Vector<int> compositor_animation_ids;
- compositor_animation_ids.push_back(1);
- keyframe_effect1->SetCompositorAnimationIdsForTesting(
- compositor_animation_ids);
+ Vector<int> compositor_keyframe_model_ids;
+ compositor_keyframe_model_ids.push_back(1);
+ keyframe_effect1->SetCompositorKeyframeModelIdsForTesting(
+ compositor_keyframe_model_ids);
EXPECT_TRUE(animation1->HasActiveAnimationsOnCompositor());
// The second animation for opacity is not ok to run on compositor.
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 2fff93314da..b78f42e859a 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
@@ -199,6 +199,24 @@ StringKeyframeEffectModel* CreateKeyframeEffectModel(
return model;
}
+// Sample the given |animation| at the given |inherited_time|. Returns nullptr
+// if the |inherited_time| falls outside of the animation.
+std::unique_ptr<TypedInterpolationValue> SampleAnimation(
+ Animation* animation,
+ double inherited_time) {
+ KeyframeEffect* effect = ToKeyframeEffect(animation->effect());
+ InertEffect* inert_animation_for_sampling = InertEffect::Create(
+ effect->Model(), effect->SpecifiedTiming(), false, inherited_time);
+ Vector<scoped_refptr<Interpolation>> sample;
+ inert_animation_for_sampling->Sample(sample);
+ // Transition animation has only animated a single property or is not in
+ // effect.
+ DCHECK_LE(sample.size(), 1u);
+ if (sample.IsEmpty())
+ return nullptr;
+ return ToTransitionInterpolation(*sample.at(0)).GetInterpolatedValue();
+}
+
} // namespace
CSSAnimations::CSSAnimations() = default;
@@ -525,8 +543,7 @@ void CSSAnimations::MaybeApplyPendingUpdate(Element* element) {
// be when transitions are retargeted. Instead of triggering complete style
// recalculation, we find these cases by searching for new transitions that
// have matching cancelled animation property IDs on the compositor.
- HeapHashMap<PropertyHandle, std::pair<Member<KeyframeEffect>, double>>
- retargeted_compositor_transitions;
+ HashSet<PropertyHandle> retargeted_compositor_transitions;
for (const PropertyHandle& property :
pending_update_.CancelledTransitions()) {
DCHECK(transitions_.Contains(property));
@@ -537,10 +554,7 @@ void CSSAnimations::MaybeApplyPendingUpdate(Element* element) {
pending_update_.NewTransitions().find(property) !=
pending_update_.NewTransitions().end() &&
!animation->Limited()) {
- retargeted_compositor_transitions.insert(
- property,
- std::pair<KeyframeEffect*, double>(
- effect, animation->StartTimeInternal().value_or(NullValue())));
+ retargeted_compositor_transitions.insert(property);
}
animation->cancel();
// after cancelation, transitions must be downgraded or they'll fail
@@ -579,44 +593,6 @@ void CSSAnimations::MaybeApplyPendingUpdate(Element* element) {
KeyframeEffectModelBase* model = inert_animation->Model();
- if (retargeted_compositor_transitions.Contains(property)) {
- const std::pair<Member<KeyframeEffect>, double>& old_transition =
- retargeted_compositor_transitions.at(property);
- KeyframeEffect* old_animation = old_transition.first;
- double old_start_time = old_transition.second;
- double inherited_time =
- IsNull(old_start_time)
- ? 0
- : element->GetDocument().Timeline().CurrentTimeInternal() -
- old_start_time;
-
- TransitionKeyframeEffectModel* old_effect =
- ToTransitionKeyframeEffectModel(inert_animation->Model());
- const KeyframeVector& frames = old_effect->GetFrames();
-
- TransitionKeyframeVector new_frames;
- new_frames.push_back(ToTransitionKeyframe(frames[0]->Clone().get()));
- new_frames.push_back(ToTransitionKeyframe(frames[1]->Clone().get()));
- new_frames.push_back(ToTransitionKeyframe(frames[2]->Clone().get()));
-
- InertEffect* inert_animation_for_sampling = InertEffect::Create(
- old_animation->Model(), old_animation->SpecifiedTiming(), false,
- inherited_time);
- Vector<scoped_refptr<Interpolation>> sample;
- inert_animation_for_sampling->Sample(sample);
- if (sample.size() == 1) {
- const TransitionInterpolation& interpolation =
- ToTransitionInterpolation(*sample.at(0));
- new_frames[0]->SetValue(interpolation.GetInterpolatedValue());
- new_frames[0]->SetCompositorValue(
- interpolation.GetInterpolatedCompositorValue());
- new_frames[1]->SetValue(interpolation.GetInterpolatedValue());
- new_frames[1]->SetCompositorValue(
- interpolation.GetInterpolatedCompositorValue());
- model = TransitionKeyframeEffectModel::Create(new_frames);
- }
- }
-
KeyframeEffect* transition = KeyframeEffect::Create(
element, model, inert_animation->SpecifiedTiming(),
KeyframeEffect::kTransitionPriority, event_delegate);
@@ -678,6 +654,7 @@ void CSSAnimations::CalculateTransitionUpdateForProperty(
}
const RunningTransition* interrupted_transition = nullptr;
+ const RunningTransition* retargeted_compositor_transition = nullptr;
if (state.active_transitions) {
TransitionMap::const_iterator active_transition_iter =
state.active_transitions->find(property);
@@ -689,6 +666,10 @@ void CSSAnimations::CalculateTransitionUpdateForProperty(
return;
}
state.update.CancelTransition(property);
+ KeyframeEffect* effect =
+ ToKeyframeEffect(running_transition->animation->effect());
+ if (effect->HasActiveAnimationsOnCompositor())
+ retargeted_compositor_transition = running_transition;
DCHECK(!state.animating_element->GetElementAnimations() ||
!state.animating_element->GetElementAnimations()
->IsAnimationStyleChange());
@@ -718,22 +699,51 @@ void CSSAnimations::CalculateTransitionUpdateForProperty(
state.animating_element->GetDocument());
CSSInterpolationEnvironment old_environment(map, state.old_style);
CSSInterpolationEnvironment new_environment(map, state.style);
+ const InterpolationType* transition_type = nullptr;
InterpolationValue start = nullptr;
InterpolationValue end = nullptr;
- const InterpolationType* transition_type = nullptr;
- for (const auto& interpolation_type : map.Get(property)) {
- start = interpolation_type->MaybeConvertUnderlyingValue(old_environment);
- if (!start) {
- continue;
- }
- end = interpolation_type->MaybeConvertUnderlyingValue(new_environment);
- if (!end) {
- continue;
+ if (retargeted_compositor_transition) {
+ base::Optional<double> old_start_time =
+ retargeted_compositor_transition->animation->StartTimeInternal();
+ // TODO(flackr): This should be able to just use
+ // animation->currentTime() / 1000 rather than trying to calculate current
+ // time.
+ double inherited_time = old_start_time.has_value()
+ ? state.animating_element->GetDocument()
+ .Timeline()
+ .CurrentTimeInternal() -
+ old_start_time.value()
+ : 0;
+ std::unique_ptr<TypedInterpolationValue> retargeted_start = SampleAnimation(
+ retargeted_compositor_transition->animation, inherited_time);
+ if (retargeted_start) {
+ const InterpolationType& interpolation_type = retargeted_start->GetType();
+ start = retargeted_start->Value().Clone();
+ end = interpolation_type.MaybeConvertUnderlyingValue(new_environment);
+ if (end &&
+ interpolation_type.MaybeMergeSingles(start.Clone(), end.Clone()))
+ transition_type = &interpolation_type;
+ } else {
+ // If the previous transition was not in effect it is not used for
+ // retargeting.
+ retargeted_compositor_transition = nullptr;
}
- // Merge will only succeed if the two values are considered interpolable.
- if (interpolation_type->MaybeMergeSingles(start.Clone(), end.Clone())) {
- transition_type = interpolation_type.get();
- break;
+ }
+ if (!retargeted_compositor_transition) {
+ for (const auto& interpolation_type : map.Get(property)) {
+ start = interpolation_type->MaybeConvertUnderlyingValue(old_environment);
+ if (!start) {
+ continue;
+ }
+ end = interpolation_type->MaybeConvertUnderlyingValue(new_environment);
+ if (!end) {
+ continue;
+ }
+ // Merge will only succeed if the two values are considered interpolable.
+ if (interpolation_type->MaybeMergeSingles(start.Clone(), end.Clone())) {
+ transition_type = interpolation_type.get();
+ break;
+ }
}
}
@@ -1245,12 +1255,18 @@ bool CSSAnimations::IsAnimationAffectingProperty(const CSSProperty& property) {
case CSSPropertyAnimationName:
case CSSPropertyAnimationPlayState:
case CSSPropertyAnimationTimingFunction:
+ case CSSPropertyContain:
+ case CSSPropertyDirection:
case CSSPropertyDisplay:
+ case CSSPropertyTextOrientation:
case CSSPropertyTransition:
case CSSPropertyTransitionDelay:
case CSSPropertyTransitionDuration:
case CSSPropertyTransitionProperty:
case CSSPropertyTransitionTimingFunction:
+ case CSSPropertyUnicodeBidi:
+ case CSSPropertyWillChange:
+ case CSSPropertyWritingMode:
return true;
default:
return false;
diff --git a/chromium/third_party/blink/renderer/core/animation/css/css_animations_test.cc b/chromium/third_party/blink/renderer/core/animation/css/css_animations_test.cc
new file mode 100644
index 00000000000..3183baad2fa
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/animation/css/css_animations_test.cc
@@ -0,0 +1,139 @@
+// 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/animation/css/css_animations.h"
+#include "third_party/blink/renderer/core/animation/animation.h"
+#include "third_party/blink/renderer/core/animation/element_animations.h"
+#include "third_party/blink/renderer/core/dom/node_computed_style.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
+#include "third_party/blink/renderer/platform/animation/compositor_animation_delegate.h"
+#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h"
+
+namespace blink {
+
+namespace {
+
+class TestingPlatformSupportWithMockSchedulerAndThreadedAnimations
+ : public TestingPlatformSupportWithMockScheduler {
+ public:
+ bool IsThreadedAnimationEnabled() override { return true; }
+};
+
+} // namespace
+
+class CSSAnimationsTest : public RenderingTest {
+ public:
+ void SetUp() override {
+ platform_->SetAutoAdvanceNowToPendingTasks(false);
+ // Advance timer manually as RenderingTest expects the time to be non-zero.
+ platform_->AdvanceClockSeconds(1.);
+ RenderingTest::SetUp();
+ EnableCompositing();
+ }
+
+ void TearDown() override {
+ platform_->SetAutoAdvanceNowToPendingTasks(true);
+ platform_->RunUntilIdle();
+ }
+
+ void StartAnimationOnCompositor(Animation* animation) {
+ static_cast<CompositorAnimationDelegate*>(animation)
+ ->NotifyAnimationStarted(
+ (CurrentTimeTicks() - base::TimeTicks()).InSecondsF(),
+ animation->CompositorGroup());
+ }
+
+ void AdvanceClockSeconds(double seconds) {
+ platform_->AdvanceClockSeconds(seconds);
+ platform_->RunUntilIdle();
+ }
+
+ double GetContrastFilterAmount(Element* element) {
+ EXPECT_EQ(1u, element->GetComputedStyle()->Filter().size());
+ const FilterOperation* filter =
+ element->GetComputedStyle()->Filter().Operations()[0];
+ EXPECT_EQ(FilterOperation::OperationType::CONTRAST, filter->GetType());
+ return static_cast<const BasicComponentTransferFilterOperation*>(filter)
+ ->Amount();
+ }
+
+ private:
+ ScopedTestingPlatformSupport<
+ TestingPlatformSupportWithMockSchedulerAndThreadedAnimations>
+ platform_;
+};
+
+// Verify that a composited animation is retargeted according to its composited
+// time.
+TEST_F(CSSAnimationsTest, RetargetedTransition) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #test { transition: filter linear 1s; }
+ .contrast1 { filter: contrast(50%); }
+ .contrast2 { filter: contrast(0%); }
+ </style>
+ <div id='test'></div>
+ )HTML");
+ Element* element = GetDocument().getElementById("test");
+ element->setAttribute(HTMLNames::classAttr, "contrast1");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ ElementAnimations* animations = element->GetElementAnimations();
+ EXPECT_EQ(1u, animations->Animations().size());
+ Animation* animation = (*animations->Animations().begin()).key;
+ // Start animation on compositor and advance .8 seconds.
+ StartAnimationOnCompositor(animation);
+ EXPECT_TRUE(animation->HasActiveAnimationsOnCompositor());
+ AdvanceClockSeconds(0.8);
+
+ // Starting the second transition should retarget the active transition.
+ element->setAttribute(HTMLNames::classAttr, "contrast2");
+ GetPage().Animator().ServiceScriptedAnimations(CurrentTimeTicks());
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ EXPECT_DOUBLE_EQ(0.6, GetContrastFilterAmount(element));
+
+ // As it has been retargeted, advancing halfway should go to 0.3.
+ AdvanceClockSeconds(0.5);
+ GetPage().Animator().ServiceScriptedAnimations(CurrentTimeTicks());
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ EXPECT_DOUBLE_EQ(0.3, GetContrastFilterAmount(element));
+}
+
+// Test that when an incompatible in progress compositor transition
+// would be retargeted it does not incorrectly combine with a new
+// transition target.
+TEST_F(CSSAnimationsTest, IncompatibleRetargetedTransition) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #test { transition: filter 1s; }
+ .saturate { filter: saturate(20%); }
+ .contrast { filter: contrast(20%); }
+ </style>
+ <div id='test'></div>
+ )HTML");
+ Element* element = GetDocument().getElementById("test");
+ element->setAttribute(HTMLNames::classAttr, "saturate");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ ElementAnimations* animations = element->GetElementAnimations();
+ EXPECT_EQ(1u, animations->Animations().size());
+ Animation* animation = (*animations->Animations().begin()).key;
+
+ // Start animation on compositor and advance partially.
+ StartAnimationOnCompositor(animation);
+ EXPECT_TRUE(animation->HasActiveAnimationsOnCompositor());
+ AdvanceClockSeconds(0.003);
+
+ // The computed style still contains no filter until the next frame.
+ EXPECT_TRUE(element->GetComputedStyle()->Filter().IsEmpty());
+
+ // Now we start a contrast filter. Since it will try to combine with
+ // the in progress saturate filter, and be incompatible, there should
+ // be no transition and it should immediately apply on the next frame.
+ element->setAttribute(HTMLNames::classAttr, "contrast");
+ EXPECT_TRUE(element->GetComputedStyle()->Filter().IsEmpty());
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ EXPECT_EQ(0.2, GetContrastFilterAmount(element));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.cc b/chromium/third_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.cc
index da222c22476..5848ec5c177 100644
--- a/chromium/third_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.cc
+++ b/chromium/third_party/blink/renderer/core/animation/css_basic_shape_interpolation_type.cc
@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/core/style/basic_shapes.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/style/shape_clip_path_operation.h"
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 6d5b0974807..027da6d2f4d 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
@@ -308,9 +308,9 @@ void CSSInterpolationType::ApplyCustomPropertyValue(
const auto tokens = tokenizer.TokenizeToEOF();
bool is_animation_tainted = true;
bool needs_variable_resolution = false;
- scoped_refptr<CSSVariableData> variable_data =
- CSSVariableData::Create(CSSParserTokenRange(tokens), is_animation_tainted,
- needs_variable_resolution);
+ scoped_refptr<CSSVariableData> variable_data = CSSVariableData::Create(
+ CSSParserTokenRange(tokens), is_animation_tainted,
+ needs_variable_resolution, KURL(), WTF::TextEncoding());
ComputedStyle& style = *state.Style();
const PropertyHandle property = GetProperty();
const AtomicString& property_name = property.CustomPropertyName();
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 9927d4fb14a..5d76ade2851 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
@@ -387,7 +387,7 @@ CSSInterpolationTypesMap::CreateInterpolationTypesForCSSSyntax(
std::make_unique<CSSVarCycleInterpolationType>(property, registration));
for (const CSSSyntaxComponent& component : descriptor.Components()) {
- if (component.repeatable_) {
+ if (component.IsRepeatable()) {
// TODO(alancutter): Support animation of repeatable types.
continue;
}
@@ -427,6 +427,7 @@ CSSInterpolationTypesMap::CreateInterpolationTypesForCSSSyntax(
result.push_back(std::make_unique<CSSNumberInterpolationType>(
property, &registration, true));
break;
+ case CSSSyntaxType::kTransformFunction:
case CSSSyntaxType::kTransformList:
// TODO(alancutter): Support smooth interpolation of these types.
break;
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 5fa2510929b..f907702ba1d 100644
--- a/chromium/third_party/blink/renderer/core/animation/document_timeline.cc
+++ b/chromium/third_party/blink/renderer/core/animation/document_timeline.cc
@@ -43,6 +43,7 @@
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_timeline.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
+#include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink {
@@ -59,24 +60,25 @@ bool CompareAnimations(const Member<Animation>& left,
const double DocumentTimeline::kMinimumDelay = 0.04;
DocumentTimeline* DocumentTimeline::Create(Document* document,
- double origin_time_in_milliseconds,
+ TimeDelta origin_time,
PlatformTiming* timing) {
- return new DocumentTimeline(document, origin_time_in_milliseconds, timing);
+ return new DocumentTimeline(document, origin_time, timing);
}
DocumentTimeline* DocumentTimeline::Create(
ExecutionContext* execution_context,
const DocumentTimelineOptions& options) {
Document* document = ToDocument(execution_context);
- return new DocumentTimeline(document, options.originTime(), nullptr);
+ return new DocumentTimeline(
+ document, TimeDelta::FromMillisecondsD(options.originTime()), nullptr);
}
DocumentTimeline::DocumentTimeline(Document* document,
- double origin_time_in_milliseconds,
+ TimeDelta origin_time,
PlatformTiming* timing)
: document_(document),
- origin_time_(origin_time_in_milliseconds / 1000),
- zero_time_(origin_time_),
+ origin_time_(origin_time),
+ zero_time_(TimeTicks() + origin_time_),
zero_time_initialized_(false),
outdated_animation_count_(0),
playback_rate_(1),
@@ -188,9 +190,10 @@ void DocumentTimeline::ScheduleNextService() {
}
void DocumentTimeline::DocumentTimelineTiming::WakeAfter(double duration) {
- if (timer_.IsActive() && timer_.NextFireInterval() < duration)
+ TimeDelta duration_delta = TimeDelta::FromSecondsD(duration);
+ if (timer_.IsActive() && timer_.NextFireInterval() < duration_delta)
return;
- timer_.StartOneShot(duration, FROM_HERE);
+ timer_.StartOneShot(duration_delta, FROM_HERE);
}
void DocumentTimeline::DocumentTimelineTiming::ServiceOnNextFrame() {
@@ -203,19 +206,17 @@ void DocumentTimeline::DocumentTimelineTiming::Trace(blink::Visitor* visitor) {
DocumentTimeline::PlatformTiming::Trace(visitor);
}
-double DocumentTimeline::ZeroTime() {
+TimeTicks DocumentTimeline::ZeroTime() {
if (!zero_time_initialized_ && document_ && document_->Loader()) {
- zero_time_ =
- TimeTicksInSeconds(
- document_->Loader()->GetTiming().ReferenceMonotonicTime()) +
- origin_time_;
+ zero_time_ = document_->Loader()->GetTiming().ReferenceMonotonicTime() +
+ origin_time_;
zero_time_initialized_ = true;
}
return zero_time_;
}
void DocumentTimeline::ResetForTesting() {
- zero_time_ = origin_time_;
+ zero_time_ = TimeTicks() + origin_time_;
zero_time_initialized_ = true;
playback_rate_ = 1;
last_current_time_internal_ = 0;
@@ -225,17 +226,20 @@ double DocumentTimeline::currentTime(bool& is_null) {
return CurrentTimeInternal(is_null) * 1000;
}
+// TODO(npm): change the return type to base::Optional<TimeTicks>.
double DocumentTimeline::CurrentTimeInternal(bool& is_null) {
if (!IsActive()) {
is_null = true;
return std::numeric_limits<double>::quiet_NaN();
}
- double result =
- playback_rate_ == 0
- ? ZeroTime()
- : (GetDocument()->GetAnimationClock().CurrentTime() - ZeroTime()) *
- playback_rate_;
+ double result = playback_rate_ == 0
+ ? TimeTicksInSeconds(ZeroTime())
+ : (GetDocument()->GetAnimationClock().CurrentTime() -
+ TimeTicksInSeconds(ZeroTime())) *
+ playback_rate_;
is_null = std::isnan(result);
+ // This looks like it could never be NaN here.
+ DCHECK(!is_null);
return result;
}
@@ -294,10 +298,10 @@ void DocumentTimeline::SetPlaybackRate(double playback_rate) {
return;
double current_time = CurrentTimeInternal();
playback_rate_ = playback_rate;
- zero_time_ = playback_rate == 0
- ? current_time
- : GetDocument()->GetAnimationClock().CurrentTime() -
- current_time / playback_rate;
+ zero_time_ = TimeTicksFromSeconds(
+ playback_rate == 0 ? current_time
+ : GetDocument()->GetAnimationClock().CurrentTime() -
+ current_time / playback_rate);
zero_time_initialized_ = true;
// Corresponding compositor animation may need to be restarted to pick up
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 788fdc44412..ebcff58bcd2 100644
--- a/chromium/third_party/blink/renderer/core/animation/document_timeline.h
+++ b/chromium/third_party/blink/renderer/core/animation/document_timeline.h
@@ -69,7 +69,7 @@ class CORE_EXPORT DocumentTimeline : public AnimationTimeline {
};
static DocumentTimeline* Create(Document*,
- double origin_time_in_milliseconds = 0.0,
+ TimeDelta origin_time = TimeDelta(),
PlatformTiming* = nullptr);
// Web Animations API IDL constructor
@@ -95,7 +95,7 @@ class CORE_EXPORT DocumentTimeline : public AnimationTimeline {
size_t PendingAnimationsCount() const {
return animations_needing_update_.size();
}
- double ZeroTime();
+ TimeTicks ZeroTime();
double currentTime(bool& is_null) override;
double currentTime();
double CurrentTimeInternal(bool& is_null);
@@ -125,13 +125,16 @@ class CORE_EXPORT DocumentTimeline : public AnimationTimeline {
void Trace(blink::Visitor*) override;
private:
- DocumentTimeline(Document*,
- double origin_time_in_milliseconds,
- PlatformTiming*);
+ DocumentTimeline(Document*, TimeDelta origin_time, PlatformTiming*);
Member<Document> document_;
- double origin_time_;
- double zero_time_;
+ // Origin time for the timeline relative to the time origin of the document.
+ // Provided when the timeline is constructed. See
+ // https://drafts.csswg.org/web-animations/#dom-documenttimelineoptions-origintime.
+ TimeDelta origin_time_;
+ // The origin time. This is computed by adding |origin_time_| to the time
+ // origin of the document.
+ TimeTicks zero_time_;
bool zero_time_initialized_;
unsigned outdated_animation_count_;
// Animations which will be updated on the next frame
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 ec61b4345f5..8efe98ee197 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
@@ -64,7 +64,8 @@ class AnimationDocumentTimelineTest : public PageTestBase {
GetAnimationClock().ResetTimeForTesting();
element = Element::Create(QualifiedName::Null(), document.Get());
platform_timing = new MockPlatformTiming;
- timeline = DocumentTimeline::Create(document.Get(), 0.0, platform_timing);
+ timeline =
+ DocumentTimeline::Create(document.Get(), TimeDelta(), platform_timing);
timeline->ResetForTesting();
ASSERT_EQ(0, timeline->CurrentTimeInternal());
}
@@ -150,7 +151,7 @@ TEST_F(AnimationDocumentTimelineTest, ZeroTime) {
}
TEST_F(AnimationDocumentTimelineTest, PlaybackRateNormal) {
- double zero_time = timeline->ZeroTime();
+ TimeTicks zero_time = timeline->ZeroTime();
bool is_null;
timeline->SetPlaybackRate(1.0);
@@ -171,29 +172,29 @@ TEST_F(AnimationDocumentTimelineTest, PlaybackRateNormal) {
}
TEST_F(AnimationDocumentTimelineTest, PlaybackRateNormalWithOriginTime) {
- double origin_time_in_ms = -1000000.0;
- timeline = DocumentTimeline::Create(document.Get(), origin_time_in_ms,
- platform_timing);
+ TimeDelta origin_time = TimeDelta::FromSeconds(-1000);
+ timeline =
+ DocumentTimeline::Create(document.Get(), origin_time, platform_timing);
timeline->ResetForTesting();
bool is_null;
EXPECT_EQ(1.0, timeline->PlaybackRate());
- EXPECT_EQ(-1000, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicks() + origin_time, timeline->ZeroTime());
EXPECT_EQ(1000, timeline->CurrentTimeInternal());
EXPECT_EQ(1000, timeline->CurrentTimeInternal(is_null));
EXPECT_FALSE(is_null);
GetAnimationClock().UpdateTime(base::TimeTicks() +
base::TimeDelta::FromSecondsD(100));
- EXPECT_EQ(-1000, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicks() + origin_time, timeline->ZeroTime());
EXPECT_EQ(1100, timeline->CurrentTimeInternal());
EXPECT_EQ(1100, timeline->CurrentTimeInternal(is_null));
EXPECT_FALSE(is_null);
GetAnimationClock().UpdateTime(base::TimeTicks() +
base::TimeDelta::FromSecondsD(200));
- EXPECT_EQ(-1000, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicks() + origin_time, timeline->ZeroTime());
EXPECT_EQ(1200, timeline->CurrentTimeInternal());
EXPECT_EQ(1200, timeline->CurrentTimeInternal(is_null));
EXPECT_FALSE(is_null);
@@ -204,7 +205,7 @@ TEST_F(AnimationDocumentTimelineTest, PlaybackRatePause) {
GetAnimationClock().UpdateTime(base::TimeTicks() +
base::TimeDelta::FromSecondsD(100));
- EXPECT_EQ(0, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicks(), timeline->ZeroTime());
EXPECT_EQ(100, timeline->CurrentTimeInternal());
EXPECT_EQ(100, timeline->CurrentTimeInternal(is_null));
EXPECT_FALSE(is_null);
@@ -213,7 +214,7 @@ TEST_F(AnimationDocumentTimelineTest, PlaybackRatePause) {
EXPECT_EQ(0.0, timeline->PlaybackRate());
GetAnimationClock().UpdateTime(base::TimeTicks() +
base::TimeDelta::FromSecondsD(200));
- EXPECT_EQ(100, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicksFromSeconds(100), timeline->ZeroTime());
EXPECT_EQ(100, timeline->CurrentTimeInternal());
EXPECT_EQ(100, timeline->CurrentTimeInternal(is_null));
@@ -221,7 +222,7 @@ TEST_F(AnimationDocumentTimelineTest, PlaybackRatePause) {
EXPECT_EQ(1.0, timeline->PlaybackRate());
GetAnimationClock().UpdateTime(base::TimeTicks() +
base::TimeDelta::FromSecondsD(400));
- EXPECT_EQ(100, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicksFromSeconds(100), timeline->ZeroTime());
EXPECT_EQ(300, timeline->CurrentTimeInternal());
EXPECT_EQ(300, timeline->CurrentTimeInternal(is_null));
@@ -231,19 +232,19 @@ TEST_F(AnimationDocumentTimelineTest, PlaybackRatePause) {
TEST_F(AnimationDocumentTimelineTest, PlaybackRatePauseWithOriginTime) {
bool is_null;
- double origin_time_in_ms = -1000000.0;
- timeline = DocumentTimeline::Create(document.Get(), origin_time_in_ms,
- platform_timing);
+ TimeDelta origin_time = TimeDelta::FromSeconds(-1000);
+ timeline =
+ DocumentTimeline::Create(document.Get(), origin_time, platform_timing);
timeline->ResetForTesting();
- EXPECT_EQ(-1000, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicks() + origin_time, timeline->ZeroTime());
EXPECT_EQ(1000, timeline->CurrentTimeInternal());
EXPECT_EQ(1000, timeline->CurrentTimeInternal(is_null));
EXPECT_FALSE(is_null);
GetAnimationClock().UpdateTime(base::TimeTicks() +
base::TimeDelta::FromSecondsD(100));
- EXPECT_EQ(-1000, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicks() + origin_time, timeline->ZeroTime());
EXPECT_EQ(1100, timeline->CurrentTimeInternal());
EXPECT_EQ(1100, timeline->CurrentTimeInternal(is_null));
EXPECT_FALSE(is_null);
@@ -252,19 +253,19 @@ TEST_F(AnimationDocumentTimelineTest, PlaybackRatePauseWithOriginTime) {
EXPECT_EQ(0.0, timeline->PlaybackRate());
GetAnimationClock().UpdateTime(base::TimeTicks() +
base::TimeDelta::FromSecondsD(200));
- EXPECT_EQ(1100, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicksFromSeconds(1100), timeline->ZeroTime());
EXPECT_EQ(1100, timeline->CurrentTimeInternal());
EXPECT_EQ(1100, timeline->CurrentTimeInternal(is_null));
timeline->SetPlaybackRate(1.0);
EXPECT_EQ(1.0, timeline->PlaybackRate());
- EXPECT_EQ(-900, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicksFromSeconds(-900), timeline->ZeroTime());
EXPECT_EQ(1100, timeline->CurrentTimeInternal());
EXPECT_EQ(1100, timeline->CurrentTimeInternal(is_null));
GetAnimationClock().UpdateTime(base::TimeTicks() +
base::TimeDelta::FromSecondsD(400));
- EXPECT_EQ(-900, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicksFromSeconds(-900), timeline->ZeroTime());
EXPECT_EQ(1300, timeline->CurrentTimeInternal());
EXPECT_EQ(1300, timeline->CurrentTimeInternal(is_null));
@@ -276,7 +277,7 @@ TEST_F(AnimationDocumentTimelineTest, PlaybackRateSlow) {
GetAnimationClock().UpdateTime(base::TimeTicks() +
base::TimeDelta::FromSecondsD(100));
- EXPECT_EQ(0, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicks(), timeline->ZeroTime());
EXPECT_EQ(100, timeline->CurrentTimeInternal());
EXPECT_EQ(100, timeline->CurrentTimeInternal(is_null));
EXPECT_FALSE(is_null);
@@ -285,7 +286,7 @@ TEST_F(AnimationDocumentTimelineTest, PlaybackRateSlow) {
EXPECT_EQ(0.5, timeline->PlaybackRate());
GetAnimationClock().UpdateTime(base::TimeTicks() +
base::TimeDelta::FromSecondsD(300));
- EXPECT_EQ(-100, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicksFromSeconds(-100), timeline->ZeroTime());
EXPECT_EQ(200, timeline->CurrentTimeInternal());
EXPECT_EQ(200, timeline->CurrentTimeInternal(is_null));
@@ -293,7 +294,7 @@ TEST_F(AnimationDocumentTimelineTest, PlaybackRateSlow) {
EXPECT_EQ(1.0, timeline->PlaybackRate());
GetAnimationClock().UpdateTime(base::TimeTicks() +
base::TimeDelta::FromSecondsD(400));
- EXPECT_EQ(100, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicksFromSeconds(100), timeline->ZeroTime());
EXPECT_EQ(300, timeline->CurrentTimeInternal());
EXPECT_EQ(300, timeline->CurrentTimeInternal(is_null));
@@ -305,7 +306,7 @@ TEST_F(AnimationDocumentTimelineTest, PlaybackRateFast) {
GetAnimationClock().UpdateTime(base::TimeTicks() +
base::TimeDelta::FromSecondsD(100));
- EXPECT_EQ(0, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicks(), timeline->ZeroTime());
EXPECT_EQ(100, timeline->CurrentTimeInternal());
EXPECT_EQ(100, timeline->CurrentTimeInternal(is_null));
EXPECT_FALSE(is_null);
@@ -314,7 +315,7 @@ TEST_F(AnimationDocumentTimelineTest, PlaybackRateFast) {
EXPECT_EQ(2.0, timeline->PlaybackRate());
GetAnimationClock().UpdateTime(base::TimeTicks() +
base::TimeDelta::FromSecondsD(300));
- EXPECT_EQ(50, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicksFromSeconds(50), timeline->ZeroTime());
EXPECT_EQ(500, timeline->CurrentTimeInternal());
EXPECT_EQ(500, timeline->CurrentTimeInternal(is_null));
@@ -322,7 +323,7 @@ TEST_F(AnimationDocumentTimelineTest, PlaybackRateFast) {
EXPECT_EQ(1.0, timeline->PlaybackRate());
GetAnimationClock().UpdateTime(base::TimeTicks() +
base::TimeDelta::FromSecondsD(400));
- EXPECT_EQ(-200, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicksFromSeconds(-200), timeline->ZeroTime());
EXPECT_EQ(600, timeline->CurrentTimeInternal());
EXPECT_EQ(600, timeline->CurrentTimeInternal(is_null));
@@ -332,39 +333,38 @@ TEST_F(AnimationDocumentTimelineTest, PlaybackRateFast) {
TEST_F(AnimationDocumentTimelineTest, PlaybackRateFastWithOriginTime) {
bool is_null;
- double origin_time_in_ms = -1000000.0;
- timeline = DocumentTimeline::Create(document.Get(), origin_time_in_ms,
- platform_timing);
+ timeline = DocumentTimeline::Create(
+ document.Get(), TimeDelta::FromSeconds(-1000), platform_timing);
timeline->ResetForTesting();
GetAnimationClock().UpdateTime(base::TimeTicks() +
base::TimeDelta::FromSecondsD(100));
- EXPECT_EQ(-1000, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicksFromSeconds(-1000), timeline->ZeroTime());
EXPECT_EQ(1100, timeline->CurrentTimeInternal());
EXPECT_EQ(1100, timeline->CurrentTimeInternal(is_null));
EXPECT_FALSE(is_null);
timeline->SetPlaybackRate(2.0);
EXPECT_EQ(2.0, timeline->PlaybackRate());
- EXPECT_EQ(-450, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicksFromSeconds(-450), timeline->ZeroTime());
EXPECT_EQ(1100, timeline->CurrentTimeInternal());
EXPECT_EQ(1100, timeline->CurrentTimeInternal(is_null));
GetAnimationClock().UpdateTime(base::TimeTicks() +
base::TimeDelta::FromSecondsD(300));
- EXPECT_EQ(-450, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicksFromSeconds(-450), timeline->ZeroTime());
EXPECT_EQ(1500, timeline->CurrentTimeInternal());
EXPECT_EQ(1500, timeline->CurrentTimeInternal(is_null));
timeline->SetPlaybackRate(1.0);
EXPECT_EQ(1.0, timeline->PlaybackRate());
- EXPECT_EQ(-1200, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicksFromSeconds(-1200), timeline->ZeroTime());
EXPECT_EQ(1500, timeline->CurrentTimeInternal());
EXPECT_EQ(1500, timeline->CurrentTimeInternal(is_null));
GetAnimationClock().UpdateTime(base::TimeTicks() +
base::TimeDelta::FromSecondsD(400));
- EXPECT_EQ(-1200, timeline->ZeroTime());
+ EXPECT_EQ(TimeTicksFromSeconds(-1200), timeline->ZeroTime());
EXPECT_EQ(1600, timeline->CurrentTimeInternal());
EXPECT_EQ(1600, timeline->CurrentTimeInternal(is_null));
diff --git a/chromium/third_party/blink/renderer/core/animation/effect_input.cc b/chromium/third_party/blink/renderer/core/animation/effect_input.cc
index 87e818e25f5..8601e570b95 100644
--- a/chromium/third_party/blink/renderer/core/animation/effect_input.cc
+++ b/chromium/third_party/blink/renderer/core/animation/effect_input.cc
@@ -48,7 +48,6 @@
#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/dom/element.h"
-#include "third_party/blink/renderer/core/dom/exception_code.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"
@@ -724,7 +723,7 @@ StringKeyframeVector EffectInput::ParseKeyframesArgument(
}
if (!ValidatePartialKeyframes(parsed_keyframes)) {
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"Partial keyframes are not supported.");
return {};
}
diff --git a/chromium/third_party/blink/renderer/core/animation/effect_input_test.cc b/chromium/third_party/blink/renderer/core/animation/effect_input_test.cc
index 55e38a230e4..3ca4bd2fc3b 100644
--- a/chromium/third_party/blink/renderer/core/animation/effect_input_test.cc
+++ b/chromium/third_party/blink/renderer/core/animation/effect_input_test.cc
@@ -13,7 +13,6 @@
#include "third_party/blink/renderer/core/animation/keyframe_effect_model.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/exception_code.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
#include "v8/include/v8.h"
@@ -71,7 +70,8 @@ TEST(AnimationEffectInputTest, UnsortedOffsets) {
EffectInput::Convert(element, js_keyframes, EffectModel::kCompositeReplace,
scope.GetScriptState(), scope.GetExceptionState());
EXPECT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(kV8TypeError, scope.GetExceptionState().Code());
+ EXPECT_EQ(ESErrorType::kTypeError,
+ scope.GetExceptionState().CodeAs<ESErrorType>());
}
TEST(AnimationEffectInputTest, LooslySorted) {
@@ -157,7 +157,8 @@ TEST(AnimationEffectInputTest, Invalid) {
EffectInput::Convert(element, js_keyframes, EffectModel::kCompositeReplace,
scope.GetScriptState(), scope.GetExceptionState());
EXPECT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(kV8TypeError, scope.GetExceptionState().Code());
+ EXPECT_EQ(ESErrorType::kTypeError,
+ scope.GetExceptionState().CodeAs<ESErrorType>());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/effect_model.cc b/chromium/third_party/blink/renderer/core/animation/effect_model.cc
index f102ced1a3f..216d5dcdd70 100644
--- a/chromium/third_party/blink/renderer/core/animation/effect_model.cc
+++ b/chromium/third_party/blink/renderer/core/animation/effect_model.cc
@@ -4,8 +4,8 @@
#include "third_party/blink/renderer/core/animation/effect_model.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect_options.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
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 4623bc2587d..aa65718560f 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
@@ -35,10 +35,9 @@ class AnimationEffectStackTest : public PageTestBase {
return animation;
}
- void UpdateTimeline(double time) {
+ void UpdateTimeline(TimeDelta time) {
GetDocument().GetAnimationClock().UpdateTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(
- GetDocument().Timeline().ZeroTime() + time));
+ GetDocument().Timeline().ZeroTime() + time);
timeline->ServiceAnimations(kTimingUpdateForAnimationFrame);
}
@@ -175,7 +174,7 @@ TEST_F(AnimationEffectStackTest, ForwardsFillDiscarding) {
base::Optional<CompositorElementIdSet>());
ActiveInterpolationsMap interpolations;
- UpdateTimeline(11);
+ UpdateTimeline(TimeDelta::FromSeconds(11));
ThreadState::Current()->CollectAllGarbage();
interpolations = EffectStack::ActiveInterpolations(
&element->GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
@@ -184,7 +183,7 @@ TEST_F(AnimationEffectStackTest, ForwardsFillDiscarding) {
EXPECT_EQ(GetFontSizeValue(interpolations), 3);
EXPECT_EQ(3u, SampledEffectCount());
- UpdateTimeline(13);
+ UpdateTimeline(TimeDelta::FromSeconds(13));
ThreadState::Current()->CollectAllGarbage();
interpolations = EffectStack::ActiveInterpolations(
&element->GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
@@ -193,7 +192,7 @@ TEST_F(AnimationEffectStackTest, ForwardsFillDiscarding) {
EXPECT_EQ(GetFontSizeValue(interpolations), 3);
EXPECT_EQ(3u, SampledEffectCount());
- UpdateTimeline(15);
+ UpdateTimeline(TimeDelta::FromSeconds(15));
ThreadState::Current()->CollectAllGarbage();
interpolations = EffectStack::ActiveInterpolations(
&element->GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
@@ -202,7 +201,7 @@ TEST_F(AnimationEffectStackTest, ForwardsFillDiscarding) {
EXPECT_EQ(GetFontSizeValue(interpolations), 3);
EXPECT_EQ(2u, SampledEffectCount());
- UpdateTimeline(17);
+ UpdateTimeline(TimeDelta::FromSeconds(17));
ThreadState::Current()->CollectAllGarbage();
interpolations = EffectStack::ActiveInterpolations(
&element->GetElementAnimations()->GetEffectStack(), nullptr, nullptr,
diff --git a/chromium/third_party/blink/renderer/core/animation/element_animation.cc b/chromium/third_party/blink/renderer/core/animation/element_animation.cc
index 87129347162..4369fa97758 100644
--- a/chromium/third_party/blink/renderer/core/animation/element_animation.cc
+++ b/chromium/third_party/blink/renderer/core/animation/element_animation.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/animation/element_animation.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/animation/animation.h"
#include "third_party/blink/renderer/core/animation/document_timeline.h"
#include "third_party/blink/renderer/core/animation/effect_input.h"
@@ -15,6 +14,7 @@
#include "third_party/blink/renderer/core/animation/timing_input.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/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
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 b3eb02cb14c..9c202260257 100644
--- a/chromium/third_party/blink/renderer/core/animation/element_animations.cc
+++ b/chromium/third_party/blink/renderer/core/animation/element_animations.cc
@@ -30,6 +30,8 @@
#include "third_party/blink/renderer/core/animation/element_animations.h"
+#include "third_party/blink/renderer/core/css/css_property_equality.h"
+#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
@@ -51,6 +53,29 @@ void UpdateAnimationFlagsForEffect(const KeyframeEffect& effect,
style.SetHasCurrentBackdropFilterAnimation(true);
}
+#if DCHECK_IS_ON()
+// Under certain conditions ComputedStyle::operator==() may return false for
+// differences that are permitted during an animation.
+bool ShouldCheckComputedStyles(const ComputedStyle& base_computed_style,
+ const ComputedStyle& computed_style) {
+ // The FontFaceCache version number may be increased without forcing a style
+ // recalc (see crbug.com/471079).
+ if (!base_computed_style.GetFont().IsFallbackValid())
+ return false;
+ // Images use instance equality rather than value equality (see
+ // crbug.com/781461).
+ for (CSSPropertyID id :
+ {CSSPropertyBackgroundImage, CSSPropertyWebkitMaskImage}) {
+ if (!CSSPropertyEquality::PropertiesEqual(
+ PropertyHandle(CSSProperty::Get(id)), base_computed_style,
+ computed_style)) {
+ return false;
+ }
+ }
+ return true;
+}
+#endif // DCHECK_IS_ON()
+
} // namespace
ElementAnimations::ElementAnimations() : animation_style_change_(false) {}
@@ -136,8 +161,10 @@ void ElementAnimations::UpdateBaseComputedStyle(
// internally. To ensure this we disable the optimization when DCHECKs are
// enabled, but keep the internal base computed style and make sure the
// equivalency holds here.
- if (base_computed_style_ && computed_style)
+ if (base_computed_style_ && computed_style &&
+ ShouldCheckComputedStyles(*base_computed_style_, *computed_style)) {
DCHECK(*base_computed_style_ == *computed_style);
+ }
#endif
base_computed_style_ = ComputedStyle::Clone(*computed_style);
}
@@ -146,17 +173,4 @@ void ElementAnimations::ClearBaseComputedStyle() {
base_computed_style_ = nullptr;
}
-bool ElementAnimations::IsAnimationStyleChange() const {
- // TODO(futhark@chromium.org): The FontFaceCache version number may be
- // increased without forcing a style recalc (see crbug.com/471079).
- // ComputedStyle objects created with different cache versions will not be
- // considered equal as Font::operator== will compare versions, hence
- // ComputedStyle::operator== will return false. We avoid using
- // base_computed_style (the check for IsFallbackValid()) in that case to avoid
- // triggering the ComputedStyle comparison DCHECK in UpdateBaseComputedStyle.
- return animation_style_change_ &&
- (!base_computed_style_ ||
- base_computed_style_->GetFont().IsFallbackValid());
-}
-
} // namespace blink
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 5eb5348241c..63743d1c174 100644
--- a/chromium/third_party/blink/renderer/core/animation/element_animations.h
+++ b/chromium/third_party/blink/renderer/core/animation/element_animations.h
@@ -87,7 +87,7 @@ class CORE_EXPORT ElementAnimations
void Trace(blink::Visitor*);
private:
- bool IsAnimationStyleChange() const;
+ bool IsAnimationStyleChange() const { return animation_style_change_; }
EffectStack effect_stack_;
CSSAnimations css_animations_;
diff --git a/chromium/third_party/blink/renderer/core/animation/keyframe.cc b/chromium/third_party/blink/renderer/core/animation/keyframe.cc
index 31c8f2ec297..c841d809d76 100644
--- a/chromium/third_party/blink/renderer/core/animation/keyframe.cc
+++ b/chromium/third_party/blink/renderer/core/animation/keyframe.cc
@@ -10,6 +10,16 @@
namespace blink {
+Keyframe::PropertySpecificKeyframe::PropertySpecificKeyframe(
+ double offset,
+ scoped_refptr<TimingFunction> easing,
+ EffectModel::CompositeOperation composite)
+ : offset_(offset), easing_(std::move(easing)), composite_(composite) {
+ DCHECK(!IsNull(offset));
+ if (!easing_)
+ easing_ = LinearTimingFunction::Shared();
+}
+
scoped_refptr<Interpolation>
Keyframe::PropertySpecificKeyframe::CreateInterpolation(
const PropertyHandle& property_handle,
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 144e9f387c6..7c6607bcfd8 100644
--- a/chromium/third_party/blink/renderer/core/animation/keyframe_effect.cc
+++ b/chromium/third_party/blink/renderer/core/animation/keyframe_effect.cc
@@ -30,7 +30,6 @@
#include "third_party/blink/renderer/core/animation/keyframe_effect.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#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/effect_input.h"
@@ -44,6 +43,7 @@
#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/svg/svg_element.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
@@ -170,7 +170,7 @@ void KeyframeEffect::setKeyframes(ScriptState* script_state,
// Animation into a 'normal' one with multiple properties.
if (!Model()->IsStringKeyframeEffectModel()) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"Calling setKeyframes on CSS Transitions is not yet supported");
return;
}
@@ -251,12 +251,12 @@ void KeyframeEffect::StartAnimationOnCompositor(
CompositorAnimations::StartAnimationOnCompositor(
*target_, group, start_time, current_time, SpecifiedTiming(),
GetAnimation(), *compositor_animation, *Model(),
- compositor_animation_ids_, animation_playback_rate);
- DCHECK(!compositor_animation_ids_.IsEmpty());
+ compositor_keyframe_model_ids_, animation_playback_rate);
+ DCHECK(!compositor_keyframe_model_ids_.IsEmpty());
}
bool KeyframeEffect::HasActiveAnimationsOnCompositor() const {
- return !compositor_animation_ids_.IsEmpty();
+ return !compositor_keyframe_model_ids_.IsEmpty();
}
bool KeyframeEffect::HasActiveAnimationsOnCompositor(
@@ -274,11 +274,12 @@ bool KeyframeEffect::CancelAnimationOnCompositor(
return false;
if (!target_ || !target_->GetLayoutObject())
return false;
- for (const auto& compositor_animation_id : compositor_animation_ids_) {
+ for (const auto& compositor_keyframe_model_id :
+ compositor_keyframe_model_ids_) {
CompositorAnimations::CancelAnimationOnCompositor(
- *target_, compositor_animation, compositor_animation_id);
+ *target_, compositor_animation, compositor_keyframe_model_id);
}
- compositor_animation_ids_.clear();
+ compositor_keyframe_model_ids_.clear();
return true;
}
@@ -294,9 +295,10 @@ void KeyframeEffect::PauseAnimationForTestingOnCompositor(double pause_time) {
if (!target_ || !target_->GetLayoutObject())
return;
DCHECK(GetAnimation());
- for (const auto& compositor_animation_id : compositor_animation_ids_) {
+ for (const auto& compositor_keyframe_model_id :
+ compositor_keyframe_model_ids_) {
CompositorAnimations::PauseAnimationForTestingOnCompositor(
- *target_, *GetAnimation(), compositor_animation_id, pause_time);
+ *target_, *GetAnimation(), compositor_keyframe_model_id, pause_time);
}
}
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 b504e814065..e0689019c56 100644
--- a/chromium/third_party/blink/renderer/core/animation/keyframe_effect.h
+++ b/chromium/third_party/blink/renderer/core/animation/keyframe_effect.h
@@ -113,9 +113,9 @@ class CORE_EXPORT KeyframeEffect final : public AnimationEffect {
void AttachCompositedLayers();
- void SetCompositorAnimationIdsForTesting(
- const Vector<int>& compositor_animation_ids) {
- compositor_animation_ids_ = compositor_animation_ids;
+ void SetCompositorKeyframeModelIdsForTesting(
+ const Vector<int>& compositor_keyframe_model_ids) {
+ compositor_keyframe_model_ids_ = compositor_keyframe_model_ids;
}
void DowngradeToNormal() { priority_ = kDefaultPriority; }
@@ -152,7 +152,7 @@ class CORE_EXPORT KeyframeEffect final : public AnimationEffect {
Priority priority_;
- Vector<int> compositor_animation_ids_;
+ Vector<int> compositor_keyframe_model_ids_;
};
DEFINE_TYPE_CASTS(KeyframeEffect,
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 03808c5a40f..e2c6e39248e 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
@@ -319,16 +319,6 @@ bool KeyframeEffectModelBase::IsReplaceOnly() const {
return true;
}
-Keyframe::PropertySpecificKeyframe::PropertySpecificKeyframe(
- double offset,
- scoped_refptr<TimingFunction> easing,
- EffectModel::CompositeOperation composite)
- : offset_(offset), easing_(std::move(easing)), composite_(composite) {
- DCHECK(!IsNull(offset));
- if (!easing_)
- easing_ = LinearTimingFunction::Shared();
-}
-
void KeyframeEffectModelBase::PropertySpecificKeyframeGroup::AppendKeyframe(
scoped_refptr<Keyframe::PropertySpecificKeyframe> keyframe) {
DCHECK(keyframes_.IsEmpty() ||
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 22843283b98..b0df78b9a50 100644
--- a/chromium/third_party/blink/renderer/core/animation/pending_animations.cc
+++ b/chromium/third_party/blink/renderer/core/animation/pending_animations.cc
@@ -162,7 +162,7 @@ void PendingAnimations::NotifyCompositorAnimationStarted(
}
animation->NotifyCompositorStartTime(
monotonic_animation_start_time -
- animation->TimelineInternal()->ZeroTime());
+ TimeTicksInSeconds(animation->TimelineInternal()->ZeroTime()));
}
}
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 ef69fd29ee1..8103b2b4d64 100644
--- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline.cc
@@ -4,9 +4,10 @@
#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
-#include "third_party/blink/renderer/core/dom/exception_code.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/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"
namespace blink {
@@ -41,7 +42,7 @@ ScrollTimeline* ScrollTimeline::Create(Document& document,
ScrollDirection orientation;
if (!StringToScrollDirection(options.orientation(), orientation)) {
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"Invalid orientation");
return nullptr;
}
@@ -49,7 +50,8 @@ ScrollTimeline* ScrollTimeline::Create(Document& document,
// TODO(smcgruer): Support 'auto' value.
if (options.timeRange().IsScrollTimelineAutoKeyword()) {
exception_state.ThrowDOMException(
- kNotSupportedError, "'auto' value for timeRange not yet supported");
+ DOMExceptionCode::kNotSupportedError,
+ "'auto' value for timeRange not yet supported");
return nullptr;
}
@@ -69,7 +71,7 @@ ScrollTimeline::ScrollTimeline(Element* scroll_source,
double ScrollTimeline::currentTime(bool& is_null) {
// 1. If scrollSource does not currently have a CSS layout box, or if its
// layout box is not a scroll container, return an unresolved time value.
- LayoutBox* layout_box = scroll_source_->GetLayoutBox();
+ LayoutBox* layout_box = ResolvedScrollSource()->GetLayoutBox();
if (!layout_box || !layout_box->HasOverflowClip()) {
is_null = false;
return std::numeric_limits<double>::quiet_NaN();
@@ -147,20 +149,45 @@ void ScrollTimeline::timeRange(DoubleOrScrollTimelineAutoKeyword& result) {
result.SetDouble(time_range_);
}
+Node* ScrollTimeline::ResolvedScrollSource() const {
+ // When in quirks mode we need the style to be clean, so we don't use
+ // |ScrollingElementNoLayout|.
+ if (scroll_source_ == scroll_source_->GetDocument().scrollingElement())
+ return &scroll_source_->GetDocument();
+ return scroll_source_;
+}
+
void ScrollTimeline::AttachAnimation() {
- GetActiveScrollTimelineSet().insert(scroll_source_);
- scroll_source_->GetDocument()
+ Node* resolved_scroll_source = ResolvedScrollSource();
+ GetActiveScrollTimelineSet().insert(resolved_scroll_source);
+ if (resolved_scroll_source->IsElementNode())
+ ToElement(resolved_scroll_source)->SetNeedsCompositingUpdate();
+ resolved_scroll_source->GetDocument()
.GetLayoutView()
->Compositor()
->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
+ LayoutBoxModelObject* object = scroll_source_->GetLayoutBoxModelObject();
+ if (object && object->HasLayer())
+ object->Layer()->SetNeedsCompositingInputsUpdate();
+ if (object)
+ object->SetNeedsPaintPropertyUpdate();
}
void ScrollTimeline::DetachAnimation() {
- GetActiveScrollTimelineSet().erase(scroll_source_);
- auto* layout_view = scroll_source_->GetDocument().GetLayoutView();
+ Node* resolved_scroll_source = ResolvedScrollSource();
+ GetActiveScrollTimelineSet().erase(resolved_scroll_source);
+ if (resolved_scroll_source->IsElementNode())
+ ToElement(resolved_scroll_source)->SetNeedsCompositingUpdate();
+ auto* layout_view = resolved_scroll_source->GetDocument().GetLayoutView();
if (layout_view && layout_view->Compositor()) {
layout_view->Compositor()->SetNeedsCompositingUpdate(
kCompositingUpdateRebuildTree);
+
+ LayoutBoxModelObject* object = scroll_source_->GetLayoutBoxModelObject();
+ if (object && object->HasLayer())
+ object->Layer()->SetNeedsCompositingInputsUpdate();
+ if (object)
+ object->SetNeedsPaintPropertyUpdate();
}
}
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 0f417c282b0..ea60fd85332 100644
--- a/chromium/third_party/blink/renderer/core/animation/scroll_timeline.h
+++ b/chromium/third_party/blink/renderer/core/animation/scroll_timeline.h
@@ -45,6 +45,11 @@ class CORE_EXPORT ScrollTimeline final : public AnimationTimeline {
String orientation();
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.
+ Node* ResolvedScrollSource() const;
+
ScrollDirection GetOrientation() const { return orientation_; }
// Must be called when this ScrollTimeline is attached/detached from an
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 195c6d5de95..802289072db 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
@@ -5,10 +5,10 @@
#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/animation/timing_input.cc b/chromium/third_party/blink/renderer/core/animation/timing_input.cc
index 18bedcf0e3b..6276d951196 100644
--- a/chromium/third_party/blink/renderer/core/animation/timing_input.cc
+++ b/chromium/third_party/blink/renderer/core/animation/timing_input.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/animation/timing_input.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/unrestricted_double_or_keyframe_animation_options.h"
#include "third_party/blink/renderer/bindings/core/v8/unrestricted_double_or_keyframe_effect_options.h"
#include "third_party/blink/renderer/core/animation/animation_effect.h"
@@ -12,6 +11,7 @@
#include "third_party/blink/renderer/core/animation/effect_timing.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect_options.h"
#include "third_party/blink/renderer/core/animation/optional_effect_timing.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
namespace {
diff --git a/chromium/third_party/blink/renderer/core/animation/worklet_animation_base.h b/chromium/third_party/blink/renderer/core/animation/worklet_animation_base.h
index 5b1c504b277..dd5ddf5400d 100644
--- a/chromium/third_party/blink/renderer/core/animation/worklet_animation_base.h
+++ b/chromium/third_party/blink/renderer/core/animation/worklet_animation_base.h
@@ -11,6 +11,7 @@
namespace blink {
+class AnimationTimeline;
class Document;
class KeyframeEffect;
@@ -30,6 +31,7 @@ class CORE_EXPORT WorkletAnimationBase : public ScriptWrappable {
virtual Document* GetDocument() const = 0;
virtual KeyframeEffect* GetEffect() const = 0;
+ virtual AnimationTimeline* GetTimeline() const = 0;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.cc b/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.cc
index 39553dd726c..15e94efa40c 100644
--- a/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.cc
+++ b/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/animation/worklet_animation_controller.h"
+#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
#include "third_party/blink/renderer/core/animation/worklet_animation_base.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
@@ -68,6 +69,17 @@ void WorkletAnimationController::UpdateAnimationTimings(
}
}
+void WorkletAnimationController::ScrollSourceCompositingStateChanged(
+ Node* node) {
+ DCHECK(ScrollTimeline::HasActiveScrollTimeline(node));
+ for (const auto& animation : compositor_animations_) {
+ if (animation->GetTimeline()->IsScrollTimeline() &&
+ ToScrollTimeline(animation->GetTimeline())->scrollSource() == node) {
+ InvalidateAnimation(*animation);
+ }
+ }
+}
+
void WorkletAnimationController::Trace(blink::Visitor* visitor) {
visitor->Trace(pending_animations_);
visitor->Trace(compositor_animations_);
diff --git a/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.h b/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.h
index 2aff8291dc5..307aa40373c 100644
--- a/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.h
+++ b/chromium/third_party/blink/renderer/core/animation/worklet_animation_controller.h
@@ -39,6 +39,12 @@ class CORE_EXPORT WorkletAnimationController
void UpdateAnimationCompositingStates();
void UpdateAnimationTimings(TimingUpdateReason);
+ // Should be called whenever the compositing state changes for a Node which is
+ // the scroll source of an active ScrollTimeline. When the compositing state
+ // changes we have to schedule an update to make sure the compositor has the
+ // correct ElementId for the scroll source.
+ void ScrollSourceCompositingStateChanged(Node*);
+
void Trace(blink::Visitor*);
private:
diff --git a/chromium/third_party/blink/renderer/core/aom/BUILD.gn b/chromium/third_party/blink/renderer/core/aom/BUILD.gn
new file mode 100644
index 00000000000..051f452ae05
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/aom/BUILD.gn
@@ -0,0 +1,16 @@
+# 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("aom") {
+ sources = [
+ "accessible_node.cc",
+ "accessible_node.h",
+ "accessible_node_list.cc",
+ "accessible_node_list.h",
+ "computed_accessible_node.cc",
+ "computed_accessible_node.h",
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/core/aom/accessible_node.cc b/chromium/third_party/blink/renderer/core/aom/accessible_node.cc
new file mode 100644
index 00000000000..b9f51375cc3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/aom/accessible_node.cc
@@ -0,0 +1,1196 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/aom/accessible_node.h"
+
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
+#include "third_party/blink/renderer/core/aom/accessible_node_list.h"
+#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/dom/qualified_name.h"
+#include "third_party/blink/renderer/core/frame/settings.h"
+#include "third_party/blink/renderer/platform//weborigin/security_origin.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+
+namespace blink {
+
+using namespace HTMLNames;
+
+namespace {
+
+QualifiedName GetCorrespondingARIAAttribute(AOMStringProperty property) {
+ switch (property) {
+ case AOMStringProperty::kAutocomplete:
+ return aria_autocompleteAttr;
+ case AOMStringProperty::kChecked:
+ return aria_checkedAttr;
+ case AOMStringProperty::kCurrent:
+ return aria_currentAttr;
+ case AOMStringProperty::kHasPopUp:
+ return aria_haspopupAttr;
+ case AOMStringProperty::kInvalid:
+ return aria_invalidAttr;
+ case AOMStringProperty::kKeyShortcuts:
+ return aria_keyshortcutsAttr;
+ case AOMStringProperty::kLabel:
+ return aria_labelAttr;
+ case AOMStringProperty::kLive:
+ return aria_liveAttr;
+ case AOMStringProperty::kOrientation:
+ return aria_orientationAttr;
+ case AOMStringProperty::kPlaceholder:
+ return aria_placeholderAttr;
+ case AOMStringProperty::kPressed:
+ return aria_pressedAttr;
+ case AOMStringProperty::kRelevant:
+ return aria_relevantAttr;
+ case AOMStringProperty::kRole:
+ return roleAttr;
+ case AOMStringProperty::kRoleDescription:
+ return aria_roledescriptionAttr;
+ case AOMStringProperty::kSort:
+ return aria_sortAttr;
+ case AOMStringProperty::kValueText:
+ return aria_valuetextAttr;
+ }
+
+ NOTREACHED();
+ return g_null_name;
+}
+
+QualifiedName GetCorrespondingARIAAttribute(AOMRelationProperty property) {
+ switch (property) {
+ case AOMRelationProperty::kActiveDescendant:
+ return aria_activedescendantAttr;
+ break;
+ case AOMRelationProperty::kDetails:
+ return aria_detailsAttr;
+ break;
+ case AOMRelationProperty::kErrorMessage:
+ return aria_errormessageAttr;
+ break;
+ }
+
+ NOTREACHED();
+ return g_null_name;
+}
+
+QualifiedName GetCorrespondingARIAAttribute(AOMRelationListProperty property) {
+ switch (property) {
+ case AOMRelationListProperty::kDescribedBy:
+ return aria_describedbyAttr;
+ break;
+ case AOMRelationListProperty::kControls:
+ return aria_controlsAttr;
+ break;
+ case AOMRelationListProperty::kFlowTo:
+ return aria_flowtoAttr;
+ break;
+ case AOMRelationListProperty::kLabeledBy:
+ // Note that there are two allowed spellings of this attribute.
+ // Callers should check both.
+ return aria_labelledbyAttr;
+ break;
+ case AOMRelationListProperty::kOwns:
+ return aria_ownsAttr;
+ break;
+ }
+
+ NOTREACHED();
+ return g_null_name;
+}
+
+QualifiedName GetCorrespondingARIAAttribute(AOMBooleanProperty property) {
+ switch (property) {
+ case AOMBooleanProperty::kAtomic:
+ return aria_atomicAttr;
+ break;
+ case AOMBooleanProperty::kBusy:
+ return aria_busyAttr;
+ break;
+ case AOMBooleanProperty::kDisabled:
+ return aria_disabledAttr;
+ break;
+ case AOMBooleanProperty::kExpanded:
+ return aria_expandedAttr;
+ break;
+ case AOMBooleanProperty::kHidden:
+ return aria_hiddenAttr;
+ break;
+ case AOMBooleanProperty::kModal:
+ return aria_modalAttr;
+ break;
+ case AOMBooleanProperty::kMultiline:
+ return aria_multilineAttr;
+ break;
+ case AOMBooleanProperty::kMultiselectable:
+ return aria_multiselectableAttr;
+ break;
+ case AOMBooleanProperty::kReadOnly:
+ return aria_readonlyAttr;
+ break;
+ case AOMBooleanProperty::kRequired:
+ return aria_requiredAttr;
+ break;
+ case AOMBooleanProperty::kSelected:
+ return aria_selectedAttr;
+ break;
+ }
+
+ NOTREACHED();
+ return g_null_name;
+}
+
+QualifiedName GetCorrespondingARIAAttribute(AOMFloatProperty property) {
+ AtomicString attr_value;
+ switch (property) {
+ case AOMFloatProperty::kValueMax:
+ return aria_valuemaxAttr;
+ break;
+ case AOMFloatProperty::kValueMin:
+ return aria_valueminAttr;
+ break;
+ case AOMFloatProperty::kValueNow:
+ return aria_valuenowAttr;
+ break;
+ }
+
+ NOTREACHED();
+ return g_null_name;
+}
+
+QualifiedName GetCorrespondingARIAAttribute(AOMUIntProperty property) {
+ switch (property) {
+ case AOMUIntProperty::kColIndex:
+ return aria_colindexAttr;
+ break;
+ case AOMUIntProperty::kColSpan:
+ return aria_colspanAttr;
+ break;
+ case AOMUIntProperty::kLevel:
+ return aria_levelAttr;
+ break;
+ case AOMUIntProperty::kPosInSet:
+ return aria_posinsetAttr;
+ break;
+ case AOMUIntProperty::kRowIndex:
+ return aria_rowindexAttr;
+ break;
+ case AOMUIntProperty::kRowSpan:
+ return aria_rowspanAttr;
+ break;
+ }
+
+ NOTREACHED();
+ return g_null_name;
+}
+
+QualifiedName GetCorrespondingARIAAttribute(AOMIntProperty property) {
+ switch (property) {
+ case AOMIntProperty::kColCount:
+ return aria_colcountAttr;
+ break;
+ case AOMIntProperty::kRowCount:
+ return aria_rowcountAttr;
+ break;
+ case AOMIntProperty::kSetSize:
+ return aria_setsizeAttr;
+ break;
+ }
+
+ NOTREACHED();
+ return g_null_name;
+}
+
+} // namespace
+
+AccessibleNode::AccessibleNode(Element* element)
+ : element_(element), document_(nullptr) {
+ DCHECK(RuntimeEnabledFeatures::AccessibilityObjectModelEnabled());
+}
+
+AccessibleNode::AccessibleNode(Document& document)
+ : element_(nullptr), document_(document) {
+ DCHECK(RuntimeEnabledFeatures::AccessibilityObjectModelEnabled());
+}
+
+AccessibleNode::~AccessibleNode() = default;
+
+// static
+AccessibleNode* AccessibleNode::Create(Document& document) {
+ return new AccessibleNode(document);
+}
+
+Document* AccessibleNode::GetDocument() const {
+ if (document_)
+ return document_;
+ if (element_)
+ return &element_->GetDocument();
+
+ NOTREACHED();
+ return nullptr;
+}
+
+const AtomicString& AccessibleNode::GetProperty(
+ AOMStringProperty property) const {
+ for (const auto& item : string_properties_) {
+ if (item.first == property && !item.second.IsNull())
+ return item.second;
+ }
+
+ return g_null_atom;
+}
+
+// static
+AccessibleNode* AccessibleNode::GetProperty(Element* element,
+ AOMRelationProperty property) {
+ if (!element)
+ return nullptr;
+
+ if (AccessibleNode* accessible_node = element->ExistingAccessibleNode()) {
+ for (const auto& item : accessible_node->relation_properties_) {
+ if (item.first == property && item.second)
+ return item.second;
+ }
+ }
+
+ return nullptr;
+}
+
+// static
+AccessibleNodeList* AccessibleNode::GetProperty(
+ Element* element,
+ AOMRelationListProperty property) {
+ if (!element)
+ return nullptr;
+
+ if (AccessibleNode* accessible_node = element->ExistingAccessibleNode()) {
+ for (const auto& item : accessible_node->relation_list_properties_) {
+ if (item.first == property && item.second)
+ return item.second;
+ }
+ }
+
+ return nullptr;
+}
+
+// static
+bool AccessibleNode::GetProperty(Element* element,
+ AOMRelationListProperty property,
+ HeapVector<Member<Element>>& targets) {
+ AccessibleNodeList* node_list = GetProperty(element, property);
+ if (!node_list)
+ return false;
+
+ for (size_t i = 0; i < node_list->length(); ++i) {
+ AccessibleNode* accessible_node = node_list->item(i);
+ if (accessible_node) {
+ Element* element = accessible_node->element();
+ if (element)
+ targets.push_back(element);
+ }
+ }
+
+ return true;
+}
+
+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;
+}
+
+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");
+}
+
+// static
+const AtomicString& AccessibleNode::GetPropertyOrARIAAttribute(
+ Element* element,
+ AOMStringProperty property) {
+ if (!element)
+ return g_null_atom;
+
+ const bool is_token_attr = IsStringTokenProperty(property);
+ AccessibleNode* accessible_node = element->ExistingAccessibleNode();
+ if (accessible_node) {
+ const AtomicString& result = accessible_node->GetProperty(property);
+ if (!result.IsNull()) {
+ if (is_token_attr && IsUndefinedAttrValue(result))
+ return g_null_atom; // Property specifically set to undefined value.
+ return result;
+ }
+ }
+
+ // Fall back on the equivalent ARIA attribute.
+ QualifiedName attribute = GetCorrespondingARIAAttribute(property);
+ const AtomicString& attr_value = element->FastGetAttribute(attribute);
+ if (is_token_attr && IsUndefinedAttrValue(attr_value))
+ return g_null_atom; // Attribute not set or explicitly undefined.
+
+ return attr_value;
+}
+
+// static
+Element* AccessibleNode::GetPropertyOrARIAAttribute(
+ Element* element,
+ AOMRelationProperty property) {
+ if (!element)
+ return nullptr;
+
+ if (AccessibleNode* result = GetProperty(element, property))
+ return result->element();
+
+ // Fall back on the equivalent ARIA attribute.
+ QualifiedName attribute = GetCorrespondingARIAAttribute(property);
+ AtomicString value = element->FastGetAttribute(attribute);
+ return element->GetTreeScope().getElementById(value);
+}
+
+// static
+bool AccessibleNode::GetPropertyOrARIAAttribute(
+ Element* element,
+ AOMRelationListProperty property,
+ HeapVector<Member<Element>>& targets) {
+ if (!element)
+ return false;
+
+ if (GetProperty(element, property, targets))
+ return true;
+
+ // Fall back on the equivalent ARIA attribute.
+ QualifiedName attribute = GetCorrespondingARIAAttribute(property);
+ String value = element->FastGetAttribute(attribute).GetString();
+ if (value.IsEmpty() && property == AOMRelationListProperty::kLabeledBy)
+ value = element->FastGetAttribute(aria_labeledbyAttr).GetString();
+ if (value.IsEmpty())
+ return false;
+
+ value.SimplifyWhiteSpace();
+ Vector<String> ids;
+ value.Split(' ', ids);
+ if (ids.IsEmpty())
+ return false;
+
+ TreeScope& scope = element->GetTreeScope();
+ for (const auto& id : ids) {
+ if (Element* id_element = scope.getElementById(AtomicString(id)))
+ targets.push_back(id_element);
+ }
+ return true;
+}
+
+// static
+bool AccessibleNode::GetPropertyOrARIAAttribute(Element* element,
+ AOMBooleanProperty property,
+ bool& is_null) {
+ is_null = true;
+ if (!element)
+ return false;
+
+ AccessibleNode* accessible_node = element->ExistingAccessibleNode();
+ if (accessible_node) {
+ bool result = accessible_node->GetProperty(property, is_null);
+ if (!is_null)
+ return result;
+ }
+
+ // Fall back on the equivalent ARIA attribute.
+ QualifiedName attribute = GetCorrespondingARIAAttribute(property);
+ AtomicString attr_value = element->FastGetAttribute(attribute);
+ is_null = IsUndefinedAttrValue(attr_value);
+ return !is_null && !EqualIgnoringASCIICase(attr_value, "false");
+}
+
+// static
+float AccessibleNode::GetPropertyOrARIAAttribute(Element* element,
+ AOMFloatProperty property,
+ bool& is_null) {
+ is_null = true;
+ if (!element)
+ return 0.0;
+
+ float result = GetProperty(element, property, is_null);
+ if (!is_null)
+ return result;
+
+ // Fall back on the equivalent ARIA attribute.
+ QualifiedName attribute = GetCorrespondingARIAAttribute(property);
+ AtomicString attr_value = element->FastGetAttribute(attribute);
+ is_null = attr_value.IsNull();
+ return attr_value.ToFloat();
+}
+
+// static
+uint32_t AccessibleNode::GetPropertyOrARIAAttribute(Element* element,
+ AOMUIntProperty property,
+ bool& is_null) {
+ is_null = true;
+ if (!element)
+ return 0;
+
+ int32_t result = GetProperty(element, property, is_null);
+ if (!is_null)
+ return result;
+
+ // Fall back on the equivalent ARIA attribute.
+ QualifiedName attribute = GetCorrespondingARIAAttribute(property);
+ AtomicString attr_value = element->FastGetAttribute(attribute);
+ is_null = attr_value.IsNull();
+ return attr_value.GetString().ToUInt();
+}
+
+// static
+int32_t AccessibleNode::GetPropertyOrARIAAttribute(Element* element,
+ AOMIntProperty property,
+ bool& is_null) {
+ is_null = true;
+ if (!element)
+ return 0;
+
+ int32_t result = GetProperty(element, property, is_null);
+ if (!is_null)
+ return result;
+
+ // Fall back on the equivalent ARIA attribute.
+ QualifiedName attribute = GetCorrespondingARIAAttribute(property);
+ AtomicString attr_value = element->FastGetAttribute(attribute);
+ is_null = attr_value.IsNull();
+ return attr_value.ToInt();
+}
+
+void AccessibleNode::GetAllAOMProperties(
+ AOMPropertyClient* client,
+ HashSet<QualifiedName>& shadowed_aria_attributes) {
+ for (auto& item : string_properties_) {
+ client->AddStringProperty(item.first, item.second);
+ shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first));
+ }
+ for (auto& item : boolean_properties_) {
+ client->AddBooleanProperty(item.first, item.second);
+ shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first));
+ }
+ for (auto& item : float_properties_) {
+ client->AddFloatProperty(item.first, item.second);
+ shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first));
+ }
+ for (auto& item : int_properties_) {
+ client->AddIntProperty(item.first, item.second);
+ shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first));
+ }
+ for (auto& item : uint_properties_) {
+ client->AddUIntProperty(item.first, item.second);
+ shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first));
+ }
+ for (auto& item : relation_properties_) {
+ if (!item.second)
+ continue;
+ client->AddRelationProperty(item.first, *item.second);
+ shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first));
+ }
+ for (auto& item : relation_list_properties_) {
+ if (!item.second)
+ continue;
+ client->AddRelationListProperty(item.first, *item.second);
+ shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first));
+ }
+}
+
+AccessibleNode* AccessibleNode::activeDescendant() const {
+ return GetProperty(element_, AOMRelationProperty::kActiveDescendant);
+}
+
+void AccessibleNode::setActiveDescendant(AccessibleNode* active_descendant) {
+ SetRelationProperty(AOMRelationProperty::kActiveDescendant,
+ active_descendant);
+ NotifyAttributeChanged(aria_activedescendantAttr);
+}
+
+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(aria_atomicAttr);
+}
+
+AtomicString AccessibleNode::autocomplete() const {
+ return GetProperty(AOMStringProperty::kAutocomplete);
+}
+
+void AccessibleNode::setAutocomplete(const AtomicString& autocomplete) {
+ SetStringProperty(AOMStringProperty::kAutocomplete, autocomplete);
+ NotifyAttributeChanged(aria_autocompleteAttr);
+}
+
+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(aria_busyAttr);
+}
+
+AtomicString AccessibleNode::checked() const {
+ return GetProperty(AOMStringProperty::kChecked);
+}
+
+void AccessibleNode::setChecked(const AtomicString& checked) {
+ SetStringProperty(AOMStringProperty::kChecked, checked);
+ NotifyAttributeChanged(aria_checkedAttr);
+}
+
+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(aria_colcountAttr);
+}
+
+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(aria_colindexAttr);
+}
+
+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(aria_colspanAttr);
+}
+
+AccessibleNodeList* AccessibleNode::controls() const {
+ return GetProperty(element_, AOMRelationListProperty::kControls);
+}
+
+void AccessibleNode::setControls(AccessibleNodeList* controls) {
+ SetRelationListProperty(AOMRelationListProperty::kControls, controls);
+ NotifyAttributeChanged(aria_controlsAttr);
+}
+
+AtomicString AccessibleNode::current() const {
+ return GetProperty(AOMStringProperty::kCurrent);
+}
+
+void AccessibleNode::setCurrent(const AtomicString& current) {
+ SetStringProperty(AOMStringProperty::kCurrent, current);
+ NotifyAttributeChanged(aria_currentAttr);
+}
+
+AccessibleNodeList* AccessibleNode::describedBy() {
+ return GetProperty(element_, AOMRelationListProperty::kDescribedBy);
+}
+
+void AccessibleNode::setDescribedBy(AccessibleNodeList* described_by) {
+ SetRelationListProperty(AOMRelationListProperty::kDescribedBy, described_by);
+ NotifyAttributeChanged(aria_describedbyAttr);
+}
+
+AccessibleNode* AccessibleNode::details() const {
+ return GetProperty(element_, AOMRelationProperty::kDetails);
+}
+
+void AccessibleNode::setDetails(AccessibleNode* details) {
+ SetRelationProperty(AOMRelationProperty::kDetails, details);
+ NotifyAttributeChanged(aria_detailsAttr);
+}
+
+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(aria_disabledAttr);
+}
+
+AccessibleNode* AccessibleNode::errorMessage() const {
+ return GetProperty(element_, AOMRelationProperty::kErrorMessage);
+}
+
+void AccessibleNode::setErrorMessage(AccessibleNode* error_message) {
+ SetRelationProperty(AOMRelationProperty::kErrorMessage, error_message);
+ NotifyAttributeChanged(aria_errormessageAttr);
+}
+
+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(aria_expandedAttr);
+}
+
+AccessibleNodeList* AccessibleNode::flowTo() const {
+ return GetProperty(element_, AOMRelationListProperty::kFlowTo);
+}
+
+void AccessibleNode::setFlowTo(AccessibleNodeList* flow_to) {
+ SetRelationListProperty(AOMRelationListProperty::kFlowTo, flow_to);
+ NotifyAttributeChanged(aria_flowtoAttr);
+}
+
+AtomicString AccessibleNode::hasPopUp() const {
+ return GetProperty(AOMStringProperty::kHasPopUp);
+}
+
+void AccessibleNode::setHasPopUp(const AtomicString& has_popup) {
+ SetStringProperty(AOMStringProperty::kHasPopUp, has_popup);
+ NotifyAttributeChanged(aria_haspopupAttr);
+}
+
+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(aria_hiddenAttr);
+}
+
+AtomicString AccessibleNode::invalid() const {
+ return GetProperty(AOMStringProperty::kInvalid);
+}
+
+void AccessibleNode::setInvalid(const AtomicString& invalid) {
+ SetStringProperty(AOMStringProperty::kInvalid, invalid);
+ NotifyAttributeChanged(aria_invalidAttr);
+}
+
+AtomicString AccessibleNode::keyShortcuts() const {
+ return GetProperty(AOMStringProperty::kKeyShortcuts);
+}
+
+void AccessibleNode::setKeyShortcuts(const AtomicString& key_shortcuts) {
+ SetStringProperty(AOMStringProperty::kKeyShortcuts, key_shortcuts);
+ NotifyAttributeChanged(aria_keyshortcutsAttr);
+}
+
+AtomicString AccessibleNode::label() const {
+ return GetProperty(AOMStringProperty::kLabel);
+}
+
+void AccessibleNode::setLabel(const AtomicString& label) {
+ SetStringProperty(AOMStringProperty::kLabel, label);
+ NotifyAttributeChanged(aria_labelAttr);
+}
+
+AccessibleNodeList* AccessibleNode::labeledBy() {
+ return GetProperty(element_, AOMRelationListProperty::kLabeledBy);
+}
+
+void AccessibleNode::setLabeledBy(AccessibleNodeList* labeled_by) {
+ SetRelationListProperty(AOMRelationListProperty::kLabeledBy, labeled_by);
+ NotifyAttributeChanged(aria_labelledbyAttr);
+}
+
+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(aria_levelAttr);
+}
+
+AtomicString AccessibleNode::live() const {
+ return GetProperty(AOMStringProperty::kLive);
+}
+
+void AccessibleNode::setLive(const AtomicString& live) {
+ SetStringProperty(AOMStringProperty::kLive, live);
+ NotifyAttributeChanged(aria_liveAttr);
+}
+
+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(aria_modalAttr);
+}
+
+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(aria_multilineAttr);
+}
+
+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(aria_multiselectableAttr);
+}
+
+AtomicString AccessibleNode::orientation() const {
+ return GetProperty(AOMStringProperty::kOrientation);
+}
+
+void AccessibleNode::setOrientation(const AtomicString& orientation) {
+ SetStringProperty(AOMStringProperty::kOrientation, orientation);
+ NotifyAttributeChanged(aria_orientationAttr);
+}
+
+AccessibleNodeList* AccessibleNode::owns() const {
+ return GetProperty(element_, AOMRelationListProperty::kOwns);
+}
+
+void AccessibleNode::setOwns(AccessibleNodeList* owns) {
+ SetRelationListProperty(AOMRelationListProperty::kOwns, owns);
+ NotifyAttributeChanged(aria_ownsAttr);
+}
+
+AtomicString AccessibleNode::placeholder() const {
+ return GetProperty(AOMStringProperty::kPlaceholder);
+}
+
+void AccessibleNode::setPlaceholder(const AtomicString& placeholder) {
+ SetStringProperty(AOMStringProperty::kPlaceholder, placeholder);
+ NotifyAttributeChanged(aria_placeholderAttr);
+}
+
+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(aria_posinsetAttr);
+}
+
+AtomicString AccessibleNode::pressed() const {
+ return GetProperty(AOMStringProperty::kPressed);
+}
+
+void AccessibleNode::setPressed(const AtomicString& pressed) {
+ SetStringProperty(AOMStringProperty::kPressed, pressed);
+ NotifyAttributeChanged(aria_pressedAttr);
+}
+
+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(aria_readonlyAttr);
+}
+
+AtomicString AccessibleNode::relevant() const {
+ return GetProperty(AOMStringProperty::kRelevant);
+}
+
+void AccessibleNode::setRelevant(const AtomicString& relevant) {
+ SetStringProperty(AOMStringProperty::kRelevant, relevant);
+ NotifyAttributeChanged(aria_relevantAttr);
+}
+
+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(aria_requiredAttr);
+}
+
+AtomicString AccessibleNode::role() const {
+ return GetProperty(AOMStringProperty::kRole);
+}
+
+void AccessibleNode::setRole(const AtomicString& role) {
+ SetStringProperty(AOMStringProperty::kRole, role);
+ NotifyAttributeChanged(roleAttr);
+}
+
+AtomicString AccessibleNode::roleDescription() const {
+ return GetProperty(AOMStringProperty::kRoleDescription);
+}
+
+void AccessibleNode::setRoleDescription(const AtomicString& role_description) {
+ SetStringProperty(AOMStringProperty::kRoleDescription, role_description);
+ NotifyAttributeChanged(aria_roledescriptionAttr);
+}
+
+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(aria_rowcountAttr);
+}
+
+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(aria_rowindexAttr);
+}
+
+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(aria_rowspanAttr);
+}
+
+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(aria_selectedAttr);
+}
+
+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(aria_setsizeAttr);
+}
+
+AtomicString AccessibleNode::sort() const {
+ return GetProperty(AOMStringProperty::kSort);
+}
+
+void AccessibleNode::setSort(const AtomicString& sort) {
+ SetStringProperty(AOMStringProperty::kSort, sort);
+ NotifyAttributeChanged(aria_sortAttr);
+}
+
+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(aria_valuemaxAttr);
+}
+
+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(aria_valueminAttr);
+}
+
+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(aria_valuenowAttr);
+}
+
+AtomicString AccessibleNode::valueText() const {
+ return GetProperty(AOMStringProperty::kValueText);
+}
+
+void AccessibleNode::setValueText(const AtomicString& value_text) {
+ SetStringProperty(AOMStringProperty::kValueText, value_text);
+ NotifyAttributeChanged(aria_valuetextAttr);
+}
+
+AccessibleNodeList* AccessibleNode::childNodes() {
+ return AccessibleNodeList::Create(children_);
+}
+
+void AccessibleNode::appendChild(AccessibleNode* child,
+ ExceptionState& exception_state) {
+ if (child->element()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidAccessError,
+ "An AccessibleNode associated with an Element cannot be a child.");
+ return;
+ }
+
+ if (child->parent_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ "Reparenting is not supported yet.");
+ return;
+ }
+ child->parent_ = this;
+
+ if (!GetDocument()->GetSecurityOrigin()->CanAccess(
+ child->GetDocument()->GetSecurityOrigin())) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidAccessError,
+ "Trying to access an AccessibleNode from a different origin.");
+ return;
+ }
+
+ children_.push_back(child);
+ if (AXObjectCache* cache = GetAXObjectCache())
+ cache->ChildrenChanged(this);
+}
+
+void AccessibleNode::removeChild(AccessibleNode* old_child,
+ ExceptionState& exception_state) {
+ if (old_child->parent_ != this) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidAccessError,
+ "Node to remove is not a child of this node.");
+ return;
+ }
+ auto* ix = std::find_if(children_.begin(), children_.end(),
+ [old_child](const Member<AccessibleNode> child) {
+ return child.Get() == old_child;
+ });
+ if (ix == children_.end()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidAccessError,
+ "Node to remove is not a child of this node.");
+ return;
+ }
+ old_child->parent_ = nullptr;
+ children_.erase(ix);
+
+ if (AXObjectCache* cache = GetAXObjectCache())
+ cache->ChildrenChanged(this);
+}
+
+// These properties support a list of tokens, and "undefined"/"" is
+// equivalent to not setting the attribute.
+bool AccessibleNode::IsStringTokenProperty(AOMStringProperty property) {
+ switch (property) {
+ case AOMStringProperty::kAutocomplete:
+ case AOMStringProperty::kChecked:
+ case AOMStringProperty::kCurrent:
+ case AOMStringProperty::kHasPopUp:
+ case AOMStringProperty::kInvalid:
+ case AOMStringProperty::kLive:
+ case AOMStringProperty::kOrientation:
+ case AOMStringProperty::kPressed:
+ case AOMStringProperty::kRelevant:
+ case AOMStringProperty::kSort:
+ return true;
+ case AOMStringProperty::kKeyShortcuts:
+ case AOMStringProperty::kLabel:
+ case AOMStringProperty::kPlaceholder:
+ case AOMStringProperty::kRole: // Is token, but ""/"undefined" not
+ // supported.
+ case AOMStringProperty::kRoleDescription:
+ case AOMStringProperty::kValueText:
+ break;
+ }
+ return false;
+}
+
+const AtomicString& AccessibleNode::InterfaceName() const {
+ return EventTargetNames::AccessibleNode;
+}
+
+ExecutionContext* AccessibleNode::GetExecutionContext() const {
+ if (element_)
+ return element_->GetExecutionContext();
+
+ if (parent_)
+ return parent_->GetExecutionContext();
+
+ return nullptr;
+}
+
+void AccessibleNode::SetStringProperty(AOMStringProperty property,
+ const AtomicString& value) {
+ for (auto& item : string_properties_) {
+ if (item.first == property) {
+ item.second = value;
+ return;
+ }
+ }
+
+ string_properties_.push_back(std::make_pair(property, value));
+}
+
+void AccessibleNode::SetRelationProperty(AOMRelationProperty property,
+ AccessibleNode* value) {
+ for (auto& item : relation_properties_) {
+ if (item.first == property) {
+ item.second = value;
+ return;
+ }
+ }
+
+ relation_properties_.push_back(std::make_pair(property, value));
+}
+
+void AccessibleNode::SetRelationListProperty(AOMRelationListProperty property,
+ AccessibleNodeList* value) {
+ for (auto& item : relation_list_properties_) {
+ if (item.first == property) {
+ if (item.second)
+ item.second->RemoveOwner(property, this);
+ if (value)
+ value->AddOwner(property, this);
+ item.second = value;
+ return;
+ }
+ }
+
+ relation_list_properties_.push_back(std::make_pair(property, value));
+}
+
+template <typename P, typename T>
+static void SetProperty(P property,
+ T value,
+ bool is_null,
+ Vector<std::pair<P, T>>& properties) {
+ for (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));
+}
+
+void AccessibleNode::NotifyAttributeChanged(
+ const blink::QualifiedName& attribute) {
+ // TODO(dmazzoni): Make a cleaner API for this rather than pretending
+ // the DOM attribute changed.
+ if (AXObjectCache* cache = GetAXObjectCache()) {
+ if (element_)
+ cache->HandleAttributeChanged(attribute, element_);
+ else
+ cache->HandleAttributeChanged(attribute, this);
+ }
+}
+
+AXObjectCache* AccessibleNode::GetAXObjectCache() {
+ return GetDocument()->ExistingAXObjectCache();
+}
+
+void AccessibleNode::Trace(blink::Visitor* visitor) {
+ visitor->Trace(element_);
+ visitor->Trace(document_);
+ visitor->Trace(relation_properties_);
+ visitor->Trace(relation_list_properties_);
+ visitor->Trace(children_);
+ visitor->Trace(parent_);
+ EventTargetWithInlineData::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/aom/accessible_node.h b/chromium/third_party/blink/renderer/core/aom/accessible_node.h
new file mode 100644
index 00000000000..d6161002118
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/aom/accessible_node.h
@@ -0,0 +1,402 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_AOM_ACCESSIBLE_NODE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_AOM_ACCESSIBLE_NODE_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/dom/events/event_target.h"
+#include "third_party/blink/renderer/core/dom/qualified_name.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.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/atomic_string.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
+
+namespace blink {
+
+class AccessibleNodeList;
+class AXObjectCache;
+class Document;
+class Element;
+class QualifiedName;
+
+// All of the properties of AccessibleNode that have type "string".
+enum class AOMStringProperty {
+ kAutocomplete,
+ kChecked,
+ kCurrent,
+ kHasPopUp,
+ kInvalid,
+ kKeyShortcuts,
+ kLabel,
+ kLive,
+ kOrientation,
+ kPlaceholder,
+ kPressed,
+ kRelevant,
+ kRole,
+ kRoleDescription,
+ kSort,
+ kValueText
+};
+
+// All of the properties of AccessibleNode that have type "boolean".
+enum class AOMBooleanProperty {
+ kAtomic,
+ kBusy,
+ kDisabled,
+ kExpanded,
+ kHidden,
+ kModal,
+ kMultiline,
+ kMultiselectable,
+ kReadOnly,
+ kRequired,
+ kSelected
+};
+
+// All of the properties of AccessibleNode that have an unsigned integer type.
+enum class AOMUIntProperty {
+ kColIndex,
+ kColSpan,
+ kLevel,
+ kPosInSet,
+ kRowIndex,
+ kRowSpan,
+};
+
+enum class AOMRelationProperty {
+ kActiveDescendant,
+ kDetails,
+ kErrorMessage,
+};
+
+enum class AOMRelationListProperty {
+ kDescribedBy,
+ kControls,
+ kFlowTo,
+ kLabeledBy,
+ kOwns,
+};
+
+// All of the properties of AccessibleNode that have a signed integer type.
+// (These all allow the value -1.)
+enum class AOMIntProperty { kColCount, kRowCount, kSetSize };
+
+// All of the properties of AccessibleNode that have a floating-point type.
+enum class AOMFloatProperty { kValueMax, kValueMin, kValueNow };
+
+class AccessibleNode;
+
+class CORE_EXPORT AOMPropertyClient {
+ public:
+ virtual void AddStringProperty(AOMStringProperty, const String&) = 0;
+ virtual void AddBooleanProperty(AOMBooleanProperty, bool) = 0;
+ virtual void AddIntProperty(AOMIntProperty, int32_t) = 0;
+ virtual void AddUIntProperty(AOMUIntProperty, uint32_t) = 0;
+ virtual void AddFloatProperty(AOMFloatProperty, float) = 0;
+ virtual void AddRelationProperty(AOMRelationProperty,
+ const AccessibleNode&) = 0;
+ virtual void AddRelationListProperty(AOMRelationListProperty,
+ const AccessibleNodeList&) = 0;
+};
+
+// Accessibility Object Model node
+// Explainer: https://github.com/WICG/aom/blob/master/explainer.md
+// Spec: https://wicg.github.io/aom/spec/
+class CORE_EXPORT AccessibleNode : public EventTargetWithInlineData {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ explicit AccessibleNode(Document&);
+ explicit AccessibleNode(Element*);
+ ~AccessibleNode() override;
+
+ static AccessibleNode* Create(Document&);
+
+ // Gets the associated element, if any.
+ Element* element() const { return element_; }
+
+ // Gets the associated document.
+ Document* GetDocument() const;
+
+ // Children. These are only virtual AccessibleNodes that were added
+ // explicitly, never AccessibleNodes from DOM Elements.
+ HeapVector<Member<AccessibleNode>> GetChildren() { return children_; }
+
+ // Returns the given string property.
+ const AtomicString& GetProperty(AOMStringProperty) const;
+
+ // Returns the given relation property if the Element has an AccessibleNode.
+ static AccessibleNode* GetProperty(Element*, AOMRelationProperty);
+
+ // Returns the given relation list property if the Element has an
+ // AccessibleNode.
+ static AccessibleNodeList* GetProperty(Element*, AOMRelationListProperty);
+ static bool GetProperty(Element*,
+ AOMRelationListProperty,
+ HeapVector<Member<Element>>&);
+
+ // Returns the given boolean property.
+ bool GetProperty(AOMBooleanProperty, bool& is_null) const;
+
+ // Returns the value of the given property if the
+ // Element has an AccessibleNode. Sets |isNull| if the property and
+ // attribute are not present.
+ 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?
+ // These include the empty string ("") or "undefined" as a literal.
+ // See ARIA 1.1 Sections 6.2 and 6.3, as well as properties that specifically
+ // indicate a supported value of "undefined".
+ static bool IsUndefinedAttrValue(const AtomicString&);
+
+ // Returns the value of the given string property if the
+ // Element has an AccessibleNode, otherwise returns the equivalent
+ // ARIA attribute.
+ static const AtomicString& GetPropertyOrARIAAttribute(Element*,
+ AOMStringProperty);
+
+ // Returns the given relation property if the Element has an AccessibleNode,
+ // otherwise returns the equivalent ARIA attribute.
+ static Element* GetPropertyOrARIAAttribute(Element*, AOMRelationProperty);
+
+ // Returns true and provides the the value of the given relation
+ // list property if the Element has an AccessibleNode, or if it has
+ // the equivalent ARIA attribute. Otherwise returns false.
+ static bool GetPropertyOrARIAAttribute(Element*,
+ AOMRelationListProperty,
+ HeapVector<Member<Element>>&);
+
+ // Returns the value of the given property if the
+ // Element has an AccessibleNode, otherwise returns the equivalent
+ // ARIA attribute. Sets |isNull| if the property and attribute are not
+ // present.
+ static bool GetPropertyOrARIAAttribute(Element*,
+ AOMBooleanProperty,
+ bool& is_null);
+ static float GetPropertyOrARIAAttribute(Element*,
+ AOMFloatProperty,
+ bool& is_null);
+ static int32_t GetPropertyOrARIAAttribute(Element*,
+ AOMIntProperty,
+ bool& is_null);
+ static uint32_t GetPropertyOrARIAAttribute(Element*,
+ AOMUIntProperty,
+ bool& is_null);
+
+ // Iterates over all AOM properties. For each one, calls AOMPropertyClient
+ // with the value of the AOM property if set. Updates
+ // |shadowed_aria_attributes| to contain a list of the ARIA attributes that
+ // would be shadowed by these AOM properties.
+ void GetAllAOMProperties(AOMPropertyClient*,
+ HashSet<QualifiedName>& shadowed_aria_attributes);
+
+ AccessibleNode* activeDescendant() const;
+ void setActiveDescendant(AccessibleNode*);
+
+ bool atomic(bool& is_null) const;
+ void setAtomic(bool, bool is_null);
+
+ AtomicString autocomplete() const;
+ void setAutocomplete(const AtomicString&);
+
+ bool busy(bool& is_null) const;
+ void setBusy(bool, bool is_null);
+
+ AtomicString checked() const;
+ void setChecked(const AtomicString&);
+
+ int32_t colCount(bool& is_null) const;
+ void setColCount(int32_t, bool is_null);
+
+ uint32_t colIndex(bool& is_null) const;
+ void setColIndex(uint32_t, bool is_null);
+
+ uint32_t colSpan(bool& is_null) const;
+ void setColSpan(uint32_t, bool is_null);
+
+ AccessibleNodeList* controls() const;
+ void setControls(AccessibleNodeList*);
+
+ AtomicString current() const;
+ void setCurrent(const AtomicString&);
+
+ AccessibleNodeList* describedBy();
+ void setDescribedBy(AccessibleNodeList*);
+
+ AccessibleNode* details() const;
+ void setDetails(AccessibleNode*);
+
+ bool disabled(bool& is_null) const;
+ void setDisabled(bool, bool is_null);
+
+ AccessibleNode* errorMessage() const;
+ void setErrorMessage(AccessibleNode*);
+
+ bool expanded(bool& is_null) const;
+ void setExpanded(bool, bool is_null);
+
+ AccessibleNodeList* flowTo() const;
+ void setFlowTo(AccessibleNodeList*);
+
+ AtomicString hasPopUp() const;
+ void setHasPopUp(const AtomicString&);
+
+ bool hidden(bool& is_null) const;
+ void setHidden(bool, bool is_null);
+
+ AtomicString invalid() const;
+ void setInvalid(const AtomicString&);
+
+ AtomicString keyShortcuts() const;
+ void setKeyShortcuts(const AtomicString&);
+
+ AtomicString label() const;
+ void setLabel(const AtomicString&);
+
+ AccessibleNodeList* labeledBy();
+ void setLabeledBy(AccessibleNodeList*);
+
+ uint32_t level(bool& is_null) const;
+ void setLevel(uint32_t, bool is_null);
+
+ AtomicString live() const;
+ void setLive(const AtomicString&);
+
+ bool modal(bool& is_null) const;
+ void setModal(bool, bool is_null);
+
+ bool multiline(bool& is_null) const;
+ void setMultiline(bool, bool is_null);
+
+ bool multiselectable(bool& is_null) const;
+ void setMultiselectable(bool, bool is_null);
+
+ AtomicString orientation() const;
+ void setOrientation(const AtomicString&);
+
+ AccessibleNodeList* owns() const;
+ void setOwns(AccessibleNodeList*);
+
+ AtomicString placeholder() const;
+ void setPlaceholder(const AtomicString&);
+
+ uint32_t posInSet(bool& is_null) const;
+ void setPosInSet(uint32_t, bool is_null);
+
+ AtomicString pressed() const;
+ void setPressed(const AtomicString&);
+
+ bool readOnly(bool& is_null) const;
+ void setReadOnly(bool, bool is_null);
+
+ AtomicString relevant() const;
+ void setRelevant(const AtomicString&);
+
+ bool required(bool& is_null) const;
+ void setRequired(bool, bool is_null);
+
+ AtomicString role() const;
+ void setRole(const AtomicString&);
+
+ AtomicString roleDescription() const;
+ void setRoleDescription(const AtomicString&);
+
+ int32_t rowCount(bool& is_null) const;
+ void setRowCount(int32_t, bool is_null);
+
+ uint32_t rowIndex(bool& is_null) const;
+ void setRowIndex(uint32_t, bool is_null);
+
+ uint32_t rowSpan(bool& is_null) const;
+ void setRowSpan(uint32_t, bool is_null);
+
+ bool selected(bool& is_null) const;
+ void setSelected(bool, bool is_null);
+
+ int32_t setSize(bool& is_null) const;
+ void setSetSize(int32_t, bool is_null);
+
+ AtomicString sort() const;
+ void setSort(const AtomicString&);
+
+ float valueMax(bool& is_null) const;
+ void setValueMax(float, bool is_null);
+
+ float valueMin(bool& is_null) const;
+ void setValueMin(float, bool is_null);
+
+ float valueNow(bool& is_null) const;
+ void setValueNow(float, bool is_null);
+
+ AtomicString valueText() const;
+ void setValueText(const AtomicString&);
+
+ AccessibleNodeList* childNodes();
+
+ void appendChild(AccessibleNode*, ExceptionState&);
+ void removeChild(AccessibleNode*, ExceptionState&);
+
+ // EventTarget
+ const AtomicString& InterfaceName() const override;
+ ExecutionContext* GetExecutionContext() const override;
+
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(accessibleclick);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(accessiblecontextmenu);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(accessibledecrement);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(accessiblefocus);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(accessibleincrement);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(accessiblescrollintoview);
+
+ void Trace(blink::Visitor*) override;
+
+ protected:
+ friend class AccessibleNodeList;
+ void OnRelationListChanged(AOMRelationListProperty);
+
+ private:
+ static bool IsStringTokenProperty(AOMStringProperty);
+ void SetStringProperty(AOMStringProperty, const AtomicString&);
+ void SetRelationProperty(AOMRelationProperty, AccessibleNode*);
+ void SetRelationListProperty(AOMRelationListProperty, AccessibleNodeList*);
+ void SetBooleanProperty(AOMBooleanProperty, bool value, bool is_null);
+ void SetFloatProperty(AOMFloatProperty, float value, bool is_null);
+ void SetUIntProperty(AOMUIntProperty, uint32_t value, bool is_null);
+ void SetIntProperty(AOMIntProperty, int32_t value, bool is_null);
+ void NotifyAttributeChanged(const blink::QualifiedName&);
+ AXObjectCache* GetAXObjectCache();
+
+ Vector<std::pair<AOMStringProperty, AtomicString>> string_properties_;
+ Vector<std::pair<AOMBooleanProperty, bool>> boolean_properties_;
+ Vector<std::pair<AOMFloatProperty, float>> float_properties_;
+ Vector<std::pair<AOMIntProperty, int32_t>> int_properties_;
+ Vector<std::pair<AOMUIntProperty, uint32_t>> uint_properties_;
+ HeapVector<std::pair<AOMRelationProperty, Member<AccessibleNode>>>
+ relation_properties_;
+ HeapVector<std::pair<AOMRelationListProperty, Member<AccessibleNodeList>>>
+ relation_list_properties_;
+
+ // This object's owner Element, if it corresponds to an Element.
+ Member<Element> element_;
+
+ // The object's owner Document. Only set if |element_| is nullptr.
+ Member<Document> document_;
+
+ // This object's AccessibleNode children, which must be only virtual
+ // AccessibleNodes (with no associated Element).
+ HeapVector<Member<AccessibleNode>> children_;
+
+ // This object's AccessibleNode parent. Only set if this is a
+ // virtual AccessibleNode that's in the tree.
+ Member<AccessibleNode> parent_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_AOM_ACCESSIBLE_NODE_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/accessible_node.idl b/chromium/third_party/blink/renderer/core/aom/accessible_node.idl
index e74c43d78c3..e74c43d78c3 100644
--- a/chromium/third_party/blink/renderer/core/dom/accessible_node.idl
+++ b/chromium/third_party/blink/renderer/core/aom/accessible_node.idl
diff --git a/chromium/third_party/blink/renderer/core/aom/accessible_node_list.cc b/chromium/third_party/blink/renderer/core/aom/accessible_node_list.cc
new file mode 100644
index 00000000000..fc45a611553
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/aom/accessible_node_list.cc
@@ -0,0 +1,114 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/aom/accessible_node_list.h"
+
+#include "third_party/blink/renderer/core/aom/accessible_node.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+
+namespace blink {
+
+// The spec doesn't give a limit, but there's no reason to allow relations
+// between an arbitrarily large number of other accessible nodes.
+static const unsigned kMaxItems = 65536;
+
+// static
+AccessibleNodeList* AccessibleNodeList::Create(
+ const HeapVector<Member<AccessibleNode>>& nodes) {
+ AccessibleNodeList* result = new AccessibleNodeList();
+ result->nodes_ = nodes;
+ return result;
+}
+
+AccessibleNodeList::AccessibleNodeList() {
+ DCHECK(RuntimeEnabledFeatures::AccessibilityObjectModelEnabled());
+}
+
+AccessibleNodeList::~AccessibleNodeList() = default;
+
+void AccessibleNodeList::AddOwner(AOMRelationListProperty property,
+ AccessibleNode* node) {
+ owners_.push_back(std::make_pair(property, node));
+}
+
+void AccessibleNodeList::RemoveOwner(AOMRelationListProperty property,
+ AccessibleNode* node) {
+ for (size_t i = 0; i < owners_.size(); ++i) {
+ auto& item = owners_[i];
+ if (item.first == property && item.second == node) {
+ owners_.EraseAt(i);
+ return;
+ }
+ }
+}
+
+AccessibleNode* AccessibleNodeList::item(unsigned offset) const {
+ if (offset < nodes_.size())
+ return nodes_[offset];
+ return nullptr;
+}
+
+void AccessibleNodeList::add(AccessibleNode* node, AccessibleNode* before) {
+ if (nodes_.size() == kMaxItems)
+ return;
+
+ unsigned index = nodes_.size();
+ if (before) {
+ for (index = 0; index < nodes_.size(); ++index) {
+ if (nodes_[index] == before)
+ break;
+ }
+ if (index == nodes_.size())
+ return;
+ }
+
+ nodes_.insert(index, node);
+}
+
+void AccessibleNodeList::remove(int index) {
+ if (index >= 0 && index < static_cast<int>(nodes_.size()))
+ nodes_.EraseAt(index);
+}
+
+bool AccessibleNodeList::AnonymousIndexedSetter(unsigned index,
+ AccessibleNode* node,
+ ExceptionState& state) {
+ if (!node) {
+ remove(index);
+ return true;
+ }
+ if (index >= kMaxItems)
+ return false;
+ if (index >= nodes_.size()) {
+ unsigned old_size = nodes_.size();
+ nodes_.resize(index + 1);
+ for (unsigned i = old_size; i < nodes_.size(); ++i)
+ nodes_[i] = nullptr;
+ }
+ nodes_[index] = node;
+ return true;
+}
+
+unsigned AccessibleNodeList::length() const {
+ return nodes_.size();
+}
+
+void AccessibleNodeList::setLength(unsigned new_length) {
+ if (new_length >= kMaxItems)
+ return;
+ nodes_.resize(new_length);
+}
+
+void AccessibleNodeList::NotifyChanged() {
+ for (auto& owner : owners_)
+ owner.second->OnRelationListChanged(owner.first);
+}
+
+void AccessibleNodeList::Trace(blink::Visitor* visitor) {
+ visitor->Trace(nodes_);
+ visitor->Trace(owners_);
+ ScriptWrappable::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/aom/accessible_node_list.h b/chromium/third_party/blink/renderer/core/aom/accessible_node_list.h
new file mode 100644
index 00000000000..af44c5d68c2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/aom/accessible_node_list.h
@@ -0,0 +1,51 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_AOM_ACCESSIBLE_NODE_LIST_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_AOM_ACCESSIBLE_NODE_LIST_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+
+namespace blink {
+
+class AccessibleNode;
+enum class AOMRelationListProperty;
+class ExceptionState;
+
+// Accessibility Object Model node list
+// Explainer: https://github.com/WICG/aom/blob/master/explainer.md
+// Spec: https://wicg.github.io/aom/spec/
+class CORE_EXPORT AccessibleNodeList : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static AccessibleNodeList* Create(const HeapVector<Member<AccessibleNode>>&);
+
+ AccessibleNodeList();
+ ~AccessibleNodeList() override;
+
+ void AddOwner(AOMRelationListProperty, AccessibleNode*);
+ void RemoveOwner(AOMRelationListProperty, AccessibleNode*);
+
+ AccessibleNode* item(unsigned offset) const;
+ void add(AccessibleNode*, AccessibleNode* = nullptr);
+ void remove(int index);
+ bool AnonymousIndexedSetter(unsigned, AccessibleNode*, ExceptionState&);
+ unsigned length() const;
+ void setLength(unsigned);
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ void NotifyChanged();
+
+ HeapVector<std::pair<AOMRelationListProperty, Member<AccessibleNode>>>
+ owners_;
+ HeapVector<Member<AccessibleNode>> nodes_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_AOM_ACCESSIBLE_NODE_LIST_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/accessible_node_list.idl b/chromium/third_party/blink/renderer/core/aom/accessible_node_list.idl
index ec9a2b107ae..ec9a2b107ae 100644
--- a/chromium/third_party/blink/renderer/core/dom/accessible_node_list.idl
+++ b/chromium/third_party/blink/renderer/core/aom/accessible_node_list.idl
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
new file mode 100644
index 00000000000..279ec28f042
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.cc
@@ -0,0 +1,347 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/aom/computed_accessible_node.h"
+
+#include <stdint.h>
+#include <utility>
+
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/dom/frame_request_callback_collection.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
+
+namespace blink {
+
+class ComputedAccessibleNodePromiseResolver::RequestAnimationFrameCallback final
+ : public FrameRequestCallbackCollection::FrameCallback {
+ public:
+ explicit RequestAnimationFrameCallback(
+ ComputedAccessibleNodePromiseResolver* resolver)
+ : resolver_(resolver) {}
+
+ void Invoke(double) override {
+ resolver_->continue_callback_request_id_ = 0;
+ resolver_->UpdateTreeAndResolve();
+ }
+
+ void Trace(blink::Visitor* visitor) override {
+ visitor->Trace(resolver_);
+ FrameRequestCallbackCollection::FrameCallback::Trace(visitor);
+ }
+
+ private:
+ Member<ComputedAccessibleNodePromiseResolver> resolver_;
+
+ DISALLOW_COPY_AND_ASSIGN(RequestAnimationFrameCallback);
+};
+
+ComputedAccessibleNodePromiseResolver*
+ComputedAccessibleNodePromiseResolver::Create(ScriptState* script_state,
+ Element& element) {
+ return new ComputedAccessibleNodePromiseResolver(script_state, element);
+}
+
+ComputedAccessibleNodePromiseResolver::ComputedAccessibleNodePromiseResolver(
+ ScriptState* script_state,
+ Element& element)
+ : element_(element),
+ resolver_(ScriptPromiseResolver::Create(script_state)),
+ resolve_with_node_(false) {}
+
+ScriptPromise ComputedAccessibleNodePromiseResolver::Promise() {
+ return resolver_->Promise();
+}
+
+void ComputedAccessibleNodePromiseResolver::Trace(blink::Visitor* visitor) {
+ visitor->Trace(element_);
+ visitor->Trace(resolver_);
+}
+
+void ComputedAccessibleNodePromiseResolver::ComputeAccessibleNode() {
+ resolve_with_node_ = true;
+ EnsureUpToDate();
+}
+
+void ComputedAccessibleNodePromiseResolver::EnsureUpToDate() {
+ DCHECK(RuntimeEnabledFeatures::AccessibilityObjectModelEnabled());
+ if (continue_callback_request_id_)
+ return;
+ // TODO(aboxhall): Trigger a call when lifecycle is next at kPrePaintClean.
+ RequestAnimationFrameCallback* callback =
+ new RequestAnimationFrameCallback(this);
+ continue_callback_request_id_ =
+ element_->GetDocument().RequestAnimationFrame(callback);
+}
+
+void ComputedAccessibleNodePromiseResolver::UpdateTreeAndResolve() {
+ LocalFrame* local_frame = element_->ownerDocument()->GetFrame();
+ WebLocalFrameClient* client =
+ WebLocalFrameImpl::FromFrame(local_frame)->Client();
+ WebComputedAXTree* tree = client->GetOrCreateWebComputedAXTree();
+ tree->ComputeAccessibilityTree();
+
+ if (!resolve_with_node_) {
+ resolver_->Resolve();
+ return;
+ }
+
+ Document& document = element_->GetDocument();
+ document.View()->UpdateLifecycleToCompositingCleanPlusScrolling();
+ AXObjectCache* cache = element_->GetDocument().GetOrCreateAXObjectCache();
+ DCHECK(cache);
+ AXID ax_id = cache->GetAXID(element_);
+
+ ComputedAccessibleNode* accessible_node =
+ local_frame->GetOrCreateComputedAccessibleNode(ax_id, tree);
+ resolver_->Resolve(accessible_node);
+}
+
+// ComputedAccessibleNode ------------------------------------------------------
+
+ComputedAccessibleNode* ComputedAccessibleNode::Create(AXID ax_id,
+ WebComputedAXTree* tree,
+ LocalFrame* frame) {
+ return new ComputedAccessibleNode(ax_id, tree, frame);
+}
+
+ComputedAccessibleNode::ComputedAccessibleNode(AXID ax_id,
+ WebComputedAXTree* tree,
+ LocalFrame* frame)
+ : ax_id_(ax_id), tree_(tree), frame_(frame) {}
+
+ComputedAccessibleNode::~ComputedAccessibleNode() {}
+
+bool ComputedAccessibleNode::atomic(bool& is_null) const {
+ return GetBoolAttribute(WebAOMBoolAttribute::AOM_ATTR_ATOMIC, is_null);
+}
+
+ScriptPromise ComputedAccessibleNode::ensureUpToDate(
+ ScriptState* script_state) {
+ AXObjectCache* cache = frame_->GetDocument()->GetOrCreateAXObjectCache();
+ Element* element = cache->GetElementFromAXID(ax_id_);
+ ComputedAccessibleNodePromiseResolver* resolver =
+ ComputedAccessibleNodePromiseResolver::Create(script_state, *element);
+ ScriptPromise promise = resolver->Promise();
+ resolver->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);
+}
+
+const String ComputedAccessibleNode::checked() const {
+ WebString out;
+ if (tree_->GetCheckedStateForAXNode(ax_id_, &out)) {
+ return out;
+ }
+ return String();
+}
+
+const String ComputedAccessibleNode::keyShortcuts() const {
+ return GetStringAttribute(WebAOMStringAttribute::AOM_ATTR_KEY_SHORTCUTS);
+}
+const String ComputedAccessibleNode::name() const {
+ return GetStringAttribute(WebAOMStringAttribute::AOM_ATTR_NAME);
+}
+const String ComputedAccessibleNode::placeholder() const {
+ return GetStringAttribute(WebAOMStringAttribute::AOM_ATTR_PLACEHOLDER);
+}
+
+const String ComputedAccessibleNode::role() const {
+ WebString out;
+ if (tree_->GetRoleForAXNode(ax_id_, &out)) {
+ return out;
+ }
+ return String();
+}
+
+const String ComputedAccessibleNode::roleDescription() const {
+ return GetStringAttribute(WebAOMStringAttribute::AOM_ATTR_ROLE_DESCRIPTION);
+}
+
+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)) {
+ return nullptr;
+ }
+ return frame_->GetOrCreateComputedAccessibleNode(parent_ax_id, tree_);
+}
+
+ComputedAccessibleNode* ComputedAccessibleNode::firstChild() const {
+ int32_t child_ax_id;
+ if (!tree_->GetFirstChildIdForAXNode(ax_id_, &child_ax_id)) {
+ return nullptr;
+ }
+ return frame_->GetOrCreateComputedAccessibleNode(child_ax_id, tree_);
+}
+
+ComputedAccessibleNode* ComputedAccessibleNode::lastChild() const {
+ int32_t child_ax_id;
+ if (!tree_->GetLastChildIdForAXNode(ax_id_, &child_ax_id)) {
+ return nullptr;
+ }
+ return frame_->GetOrCreateComputedAccessibleNode(child_ax_id, tree_);
+}
+
+ComputedAccessibleNode* ComputedAccessibleNode::previousSibling() const {
+ int32_t sibling_ax_id;
+ if (!tree_->GetPreviousSiblingIdForAXNode(ax_id_, &sibling_ax_id)) {
+ return nullptr;
+ }
+ return frame_->GetOrCreateComputedAccessibleNode(sibling_ax_id, tree_);
+}
+
+ComputedAccessibleNode* ComputedAccessibleNode::nextSibling() const {
+ int32_t sibling_ax_id;
+ if (!tree_->GetNextSiblingIdForAXNode(ax_id_, &sibling_ax_id)) {
+ return nullptr;
+ }
+ return frame_->GetOrCreateComputedAccessibleNode(sibling_ax_id, tree_);
+}
+
+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;
+ if (tree_->GetStringAttributeForAXNode(ax_id_, attr, &out)) {
+ return out;
+ }
+ return String();
+}
+
+void ComputedAccessibleNode::Trace(Visitor* visitor) {
+ visitor->Trace(frame_);
+ ScriptWrappable::Trace(visitor);
+}
+
+} // namespace blink
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
new file mode 100644
index 00000000000..616fb5caea3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.h
@@ -0,0 +1,112 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_AOM_COMPUTED_ACCESSIBLE_NODE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_AOM_COMPUTED_ACCESSIBLE_NODE_H_
+
+#include "third_party/blink/public/platform/web_computed_ax_tree.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
+#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/dom/events/event_target.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class ScriptState;
+
+class ComputedAccessibleNodePromiseResolver final
+ : public GarbageCollectedFinalized<ComputedAccessibleNodePromiseResolver> {
+ public:
+ static ComputedAccessibleNodePromiseResolver* Create(ScriptState*, Element&);
+ ~ComputedAccessibleNodePromiseResolver() {}
+
+ ScriptPromise Promise();
+ void ComputeAccessibleNode();
+ void EnsureUpToDate();
+ void Trace(blink::Visitor*);
+
+ private:
+ ComputedAccessibleNodePromiseResolver(ScriptState*, Element&);
+ void UpdateTreeAndResolve();
+ class RequestAnimationFrameCallback;
+
+ int continue_callback_request_id_ = 0;
+ Member<Element> element_;
+ Member<ScriptPromiseResolver> resolver_;
+ bool resolve_with_node_;
+};
+
+class ComputedAccessibleNode : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static ComputedAccessibleNode* Create(AXID, WebComputedAXTree*, LocalFrame*);
+ ~ComputedAccessibleNode() override;
+
+ void Trace(Visitor*) override;
+
+ // TODO(meredithl): add accessors for state properties.
+ bool atomic(bool& is_null) const;
+ bool busy(bool& is_null) const;
+ bool disabled(bool& is_null) const;
+ bool readOnly(bool& is_null) const;
+ bool expanded(bool& is_null) const;
+ bool modal(bool& is_null) const;
+ bool multiline(bool& is_null) const;
+ bool multiselectable(bool& is_null) const;
+ bool required(bool& is_null) const;
+ bool selected(bool& is_null) const;
+
+ int32_t colCount(bool& is_null) const;
+ int32_t colIndex(bool& is_null) const;
+ int32_t colSpan(bool& is_null) const;
+ int32_t level(bool& is_null) const;
+ int32_t posInSet(bool& is_null) const;
+ int32_t rowCount(bool& is_null) const;
+ int32_t rowIndex(bool& is_null) const;
+ int32_t rowSpan(bool& is_null) const;
+ int32_t setSize(bool& is_null) const;
+
+ float valueMax(bool& is_null) const;
+ float valueMin(bool& is_null) const;
+ float valueNow(bool& is_null) const;
+
+ const String autocomplete() const;
+ const String checked() const;
+ const String keyShortcuts() const;
+ const String name() const;
+ const String placeholder() const;
+ const String role() const;
+ const String roleDescription() const;
+ const String valueText() const;
+
+ ComputedAccessibleNode* parent() const;
+ ComputedAccessibleNode* firstChild() const;
+ ComputedAccessibleNode* lastChild() const;
+ ComputedAccessibleNode* previousSibling() const;
+ ComputedAccessibleNode* nextSibling() const;
+
+ ScriptPromise ensureUpToDate(ScriptState*);
+
+ private:
+ ComputedAccessibleNode(AXID, WebComputedAXTree*, LocalFrame*);
+ 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_;
+
+ // This tree is owned by the RenderFrame.
+ blink::WebComputedAXTree* tree_;
+ Member<LocalFrame> frame_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_AOM_COMPUTED_ACCESSIBLE_NODE_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/computed_accessible_node.idl b/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.idl
index e8b62928fed..e8b62928fed 100644
--- a/chromium/third_party/blink/renderer/core/dom/computed_accessible_node.idl
+++ b/chromium/third_party/blink/renderer/core/aom/computed_accessible_node.idl
diff --git a/chromium/third_party/blink/renderer/core/clipboard/BUILD.gn b/chromium/third_party/blink/renderer/core/clipboard/BUILD.gn
index e1fc73f6920..65c6f844073 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/clipboard/BUILD.gn
@@ -6,6 +6,10 @@ import("//third_party/blink/renderer/core/core.gni")
blink_core_sources("clipboard") {
sources = [
+ "clipboard_mime_types.cc",
+ "clipboard_mime_types.h",
+ "clipboard_utilities.cc",
+ "clipboard_utilities.h",
"data_object.cc",
"data_object.h",
"data_object_item.cc",
@@ -22,4 +26,12 @@ blink_core_sources("clipboard") {
"system_clipboard.cc",
"system_clipboard.h",
]
+
+ if (is_win) {
+ sources += [ "clipboard_utilities_win.cc" ]
+ }
+
+ deps = [
+ "//ui/gfx/codec",
+ ]
}
diff --git a/chromium/third_party/blink/renderer/core/clipboard/clipboard_mime_types.cc b/chromium/third_party/blink/renderer/core/clipboard/clipboard_mime_types.cc
new file mode 100644
index 00000000000..fc09b0c24dd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/clipboard/clipboard_mime_types.cc
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "third_party/blink/renderer/core/clipboard/clipboard_mime_types.h"
+
+namespace blink {
+
+const char kMimeTypeText[] = "text";
+const char kMimeTypeTextPlain[] = "text/plain";
+const char kMimeTypeTextPlainEtc[] = "text/plain;";
+const char kMimeTypeTextHTML[] = "text/html";
+const char kMimeTypeTextRTF[] = "text/rtf";
+const char kMimeTypeURL[] = "url";
+const char kMimeTypeTextURIList[] = "text/uri-list";
+const char kMimeTypeDownloadURL[] = "downloadurl";
+const char kMimeTypeFiles[] = "Files";
+const char kMimeTypeImagePng[] = "image/png";
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/clipboard/clipboard_mime_types.h b/chromium/third_party/blink/renderer/core/clipboard/clipboard_mime_types.h
new file mode 100644
index 00000000000..6047989a7bd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/clipboard/clipboard_mime_types.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_CLIPBOARD_MIME_TYPES_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_CLIPBOARD_MIME_TYPES_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+
+namespace blink {
+
+CORE_EXPORT extern const char kMimeTypeText[];
+CORE_EXPORT extern const char kMimeTypeTextPlain[];
+CORE_EXPORT extern const char kMimeTypeTextPlainEtc[];
+CORE_EXPORT extern const char kMimeTypeTextHTML[];
+CORE_EXPORT extern const char kMimeTypeTextRTF[];
+CORE_EXPORT extern const char kMimeTypeURL[];
+CORE_EXPORT extern const char kMimeTypeTextURIList[];
+CORE_EXPORT extern const char kMimeTypeDownloadURL[];
+CORE_EXPORT extern const char kMimeTypeFiles[];
+CORE_EXPORT extern const char kMimeTypeImagePng[];
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_CLIPBOARD_MIME_TYPES_H_
diff --git a/chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities.cc b/chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities.cc
new file mode 100644
index 00000000000..75b347c4e44
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities.cc
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "third_party/blink/renderer/core/clipboard/clipboard_utilities.h"
+
+#include "net/base/escape.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+void ReplaceNBSPWithSpace(String& str) {
+ static const UChar kNonBreakingSpaceCharacter = 0xA0;
+ static const UChar kSpaceCharacter = ' ';
+ str.Replace(kNonBreakingSpaceCharacter, kSpaceCharacter);
+}
+
+String ConvertURIListToURL(const String& uri_list) {
+ Vector<String> items;
+ // Line separator is \r\n per RFC 2483 - however, for compatibility
+ // reasons we allow just \n here.
+ uri_list.Split('\n', items);
+ // Process the input and return the first valid URL. In case no URLs can
+ // be found, return an empty string. This is in line with the HTML5 spec.
+ for (size_t i = 0; i < items.size(); ++i) {
+ String& line = items[i];
+ line = line.StripWhiteSpace();
+ if (line.IsEmpty())
+ continue;
+ if (line[0] == '#')
+ continue;
+ KURL url = KURL(line);
+ if (url.IsValid())
+ return url;
+ }
+ return String();
+}
+
+static String EscapeForHTML(const String& str) {
+ std::string output =
+ net::EscapeForHTML(StringUTF8Adaptor(str).AsStringPiece());
+ return String(output.c_str());
+}
+
+String URLToImageMarkup(const KURL& url, const String& title) {
+ StringBuilder builder;
+ builder.Append("<img src=\"");
+ builder.Append(EscapeForHTML(url.GetString()));
+ builder.Append("\"");
+ if (!title.IsEmpty()) {
+ builder.Append(" alt=\"");
+ builder.Append(EscapeForHTML(title));
+ builder.Append("\"");
+ }
+ builder.Append("/>");
+ return builder.ToString();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities.h b/chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities.h
new file mode 100644
index 00000000000..623c77322ac
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_CLIPBOARD_UTILITIES_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_CLIPBOARD_UTILITIES_H_
+
+#include "build/build_config.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace blink {
+
+#if defined(OS_WIN)
+CORE_EXPORT void ReplaceNewlinesWithWindowsStyleNewlines(String&);
+#endif
+CORE_EXPORT void ReplaceNBSPWithSpace(String&);
+CORE_EXPORT String ConvertURIListToURL(const String& uri_list);
+CORE_EXPORT String URLToImageMarkup(const KURL&, const String& title);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_CLIPBOARD_UTILITIES_H_
diff --git a/chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities_win.cc b/chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities_win.cc
new file mode 100644
index 00000000000..9136bbfe129
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/clipboard/clipboard_utilities_win.cc
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "third_party/blink/renderer/core/clipboard/clipboard_utilities.h"
+
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+#include <shlwapi.h>
+
+namespace blink {
+
+void ReplaceNewlinesWithWindowsStyleNewlines(String& str) {
+ DEFINE_STATIC_LOCAL(String, windows_newline, ("\r\n"));
+ StringBuilder result;
+ for (unsigned index = 0; index < str.length(); ++index) {
+ if (str[index] != '\n' || (index > 0 && str[index - 1] == '\r'))
+ result.Append(str[index]);
+ else
+ result.Append(windows_newline);
+ }
+ str = result.ToString();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/clipboard/data_object.cc b/chromium/third_party/blink/renderer/core/clipboard/data_object.cc
index 812a3e05bca..b81a304f550 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/data_object.cc
+++ b/chromium/third_party/blink/renderer/core/clipboard/data_object.cc
@@ -32,10 +32,10 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_drag_data.h"
+#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/dragged_isolated_file_system.h"
#include "third_party/blink/renderer/core/clipboard/system_clipboard.h"
-#include "third_party/blink/renderer/platform/clipboard/clipboard_mime_types.h"
-#include "third_party/blink/renderer/platform/clipboard/clipboard_utilities.h"
#include "third_party/blink/renderer/platform/paste_mode.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
diff --git a/chromium/third_party/blink/renderer/core/clipboard/data_object_item.cc b/chromium/third_party/blink/renderer/core/clipboard/data_object_item.cc
index e5bfdfe21ae..aa2ab78e254 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/data_object_item.cc
+++ b/chromium/third_party/blink/renderer/core/clipboard/data_object_item.cc
@@ -31,10 +31,11 @@
#include "third_party/blink/renderer/core/clipboard/data_object_item.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/core/clipboard/clipboard_mime_types.h"
#include "third_party/blink/renderer/core/clipboard/system_clipboard.h"
#include "third_party/blink/renderer/core/fileapi/blob.h"
-#include "third_party/blink/renderer/platform/clipboard/clipboard_mime_types.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
+#include "ui/gfx/codec/png_codec.h"
namespace blink {
@@ -126,12 +127,17 @@ File* DataObjectItem::GetAsFile() const {
DCHECK_EQ(source_, kClipboardSource);
if (GetType() == kMimeTypeImagePng) {
- scoped_refptr<BlobDataHandle> blob =
- SystemClipboard::GetInstance().ReadImage(
- mojom::ClipboardBuffer::kStandard);
- if (!blob)
- return nullptr;
- return File::Create("image.png", CurrentTimeMS(), std::move(blob));
+ SkBitmap image = SystemClipboard::GetInstance().ReadImage(
+ mojom::ClipboardBuffer::kStandard);
+ std::vector<unsigned char> png_data;
+ if (gfx::PNGCodec::FastEncodeBGRASkBitmap(image, false, &png_data)) {
+ std::unique_ptr<BlobData> data = BlobData::Create();
+ data->SetContentType(kMimeTypeImagePng);
+ data->AppendBytes(png_data.data(), png_data.size());
+ const uint64_t length = data->length();
+ auto blob = BlobDataHandle::Create(std::move(data), length);
+ return File::Create("image.png", CurrentTimeMS(), std::move(blob));
+ }
}
return nullptr;
diff --git a/chromium/third_party/blink/renderer/core/clipboard/data_transfer.cc b/chromium/third_party/blink/renderer/core/clipboard/data_transfer.cc
index 0a5768cee52..43f6f8bdc1c 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/data_transfer.cc
+++ b/chromium/third_party/blink/renderer/core/clipboard/data_transfer.cc
@@ -29,6 +29,8 @@
#include "build/build_config.h"
#include "third_party/blink/public/platform/web_screen_info.h"
+#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/clipboard/data_transfer_access_policy.h"
#include "third_party/blink/renderer/core/clipboard/data_transfer_item.h"
@@ -50,9 +52,8 @@
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_painter.h"
-#include "third_party/blink/renderer/platform/clipboard/clipboard_mime_types.h"
-#include "third_party/blink/renderer/platform/clipboard/clipboard_utilities.h"
#include "third_party/blink/renderer/platform/drag_image.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
@@ -100,18 +101,20 @@ class DraggedNodeImageBuilder {
// object contains transparency and there are other elements in the same
// stacking context which stacked below.
PaintLayer* layer = dragged_layout_object->EnclosingLayer();
- if (!layer->StackingNode()->IsStackingContext())
- layer = layer->StackingNode()->AncestorStackingContextNode()->Layer();
+ if (!layer->GetLayoutObject().StyleRef().IsStackingContext()) {
+ layer =
+ PaintLayerStackingNode::AncestorStackingContextNode(layer)->Layer();
+ }
IntRect absolute_bounding_box =
dragged_layout_object->AbsoluteBoundingBoxRectIncludingDescendants();
// TODO(chrishtr): consider using the root frame's visible rect instead
// of the local frame, to avoid over-clipping.
- FloatRect visible_rect =
- layer->GetLayoutObject().GetFrameView()->VisibleContentRect();
+ IntRect visible_rect(IntPoint(),
+ layer->GetLayoutObject().GetFrameView()->Size());
// If the absolute bounding box is large enough to be possibly a memory
// or IPC payload issue, clip it to the visible content rect.
if (absolute_bounding_box.Size().Area() > visible_rect.Size().Area()) {
- absolute_bounding_box.Intersect(EnclosingIntRect(visible_rect));
+ absolute_bounding_box.Intersect(visible_rect);
}
FloatRect bounding_box =
@@ -134,15 +137,13 @@ class DraggedNodeImageBuilder {
DocumentLifecycle::kPaintClean);
FloatPoint paint_offset = bounding_box.Location();
- PropertyTreeState border_box_properties = PropertyTreeState::Root();
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- border_box_properties =
- layer->GetLayoutObject().FirstFragment().LocalBorderBoxProperties();
- // In SPv175+ we paint in the containing transform node's space. Add the
- // offset from the layer to this transform space.
- paint_offset +=
- FloatPoint(layer->GetLayoutObject().FirstFragment().PaintOffset());
- }
+ PropertyTreeState border_box_properties =
+ layer->GetLayoutObject().FirstFragment().LocalBorderBoxProperties();
+ // We paint in the containing transform node's space. Add the offset from
+ // the layer to this transform space.
+ paint_offset +=
+ FloatPoint(layer->GetLayoutObject().FirstFragment().PaintOffset());
+
return DataTransfer::CreateDragImageForFrame(
*local_frame_, 1.0f,
LayoutObject::ShouldRespectImageOrientation(dragged_layout_object),
@@ -371,7 +372,7 @@ FloatRect DataTransfer::ClipByVisualViewport(const FloatRect& absolute_rect,
IntRect viewport_in_root_frame =
EnclosingIntRect(frame.GetPage()->GetVisualViewport().VisibleRect());
FloatRect absolute_viewport =
- frame.View()->RootFrameToAbsolute(viewport_in_root_frame);
+ FloatRect(frame.View()->ConvertFromRootFrame(viewport_in_root_frame));
return Intersection(absolute_viewport, absolute_rect);
}
diff --git a/chromium/third_party/blink/renderer/core/clipboard/data_transfer_item_list.cc b/chromium/third_party/blink/renderer/core/clipboard/data_transfer_item_list.cc
index f0f209122a4..1dac9f36f16 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/data_transfer_item_list.cc
+++ b/chromium/third_party/blink/renderer/core/clipboard/data_transfer_item_list.cc
@@ -26,11 +26,10 @@
#include "third_party/blink/renderer/core/clipboard/data_transfer_item_list.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/clipboard/data_object.h"
#include "third_party/blink/renderer/core/clipboard/data_transfer.h"
#include "third_party/blink/renderer/core/clipboard/data_transfer_item.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -58,7 +57,7 @@ DataTransferItem* DataTransferItemList::item(unsigned long index) {
void DataTransferItemList::deleteItem(unsigned long index,
ExceptionState& exception_state) {
if (!data_transfer_->CanWriteData()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The list is not writable.");
return;
}
@@ -79,7 +78,8 @@ DataTransferItem* DataTransferItemList::add(const String& data,
DataObjectItem* item = data_object_->Add(data, type);
if (!item) {
exception_state.ThrowDOMException(
- kNotSupportedError, "An item already exists for type '" + type + "'.");
+ DOMExceptionCode::kNotSupportedError,
+ "An item already exists for type '" + type + "'.");
return nullptr;
}
return DataTransferItem::Create(data_transfer_, item);
diff --git a/chromium/third_party/blink/renderer/core/clipboard/data_transfer_test.cc b/chromium/third_party/blink/renderer/core/clipboard/data_transfer_test.cc
index 64db28f3c37..d4680cd67d3 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/data_transfer_test.cc
+++ b/chromium/third_party/blink/renderer/core/clipboard/data_transfer_test.cc
@@ -10,6 +10,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/layout/layout_object.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/drag_image.h"
@@ -137,8 +138,8 @@ TEST_F(DataTransferTest, NodeImageUnderScrollOffset) {
const int scroll_amount = 10;
LocalFrameView* frame_view = GetDocument().View();
- frame_view->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, scroll_amount), kProgrammaticScroll);
+ frame_view->LayoutViewport()->SetScrollOffset(ScrollOffset(0, scroll_amount),
+ kProgrammaticScroll);
// The first div should be offset by the scroll offset.
Element& first = *GetDocument().getElementById("first");
@@ -178,8 +179,8 @@ TEST_F(DataTransferTest, NodeImageSizeWithPageScaleFactor) {
// page scale factor.
const int scroll_amount = 10;
LocalFrameView* frame_view = GetDocument().View();
- frame_view->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, scroll_amount), kProgrammaticScroll);
+ frame_view->LayoutViewport()->SetScrollOffset(ScrollOffset(0, scroll_amount),
+ kProgrammaticScroll);
const auto image_with_offset = DataTransfer::NodeImage(GetFrame(), node);
EXPECT_EQ(
IntSize(node_width * page_scale_factor, node_height * page_scale_factor),
@@ -209,8 +210,8 @@ TEST_F(DataTransferTest, NodeImageSizeWithPageScaleFactorTooLarge) {
// page scale factor.
const int scroll_amount = 10;
LocalFrameView* frame_view = GetDocument().View();
- frame_view->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, scroll_amount), kProgrammaticScroll);
+ frame_view->LayoutViewport()->SetScrollOffset(ScrollOffset(0, scroll_amount),
+ kProgrammaticScroll);
const auto image_with_offset = DataTransfer::NodeImage(GetFrame(), node);
EXPECT_EQ(IntSize(node_width * page_scale_factor,
(node_height - scroll_amount) * page_scale_factor),
@@ -274,8 +275,8 @@ TEST_F(DataTransferTest, NodeImageFullyOffscreen) {
const int scroll_amount = 800;
LocalFrameView* frame_view = GetDocument().View();
- frame_view->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, scroll_amount), kProgrammaticScroll);
+ frame_view->LayoutViewport()->SetScrollOffset(ScrollOffset(0, scroll_amount),
+ kProgrammaticScroll);
Element& target = *GetDocument().getElementById("target");
const auto image = DataTransfer::NodeImage(GetFrame(), target);
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 e42539a0a75..ac7e91263d3 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/system_clipboard.cc
+++ b/chromium/third_party/blink/renderer/core/clipboard/system_clipboard.cc
@@ -12,13 +12,12 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_drag_data.h"
#include "third_party/blink/public/platform/web_string.h"
+#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/platform/blob/blob_data.h"
-#include "third_party/blink/renderer/platform/clipboard/clipboard_mime_types.h"
-#include "third_party/blink/renderer/platform/clipboard/clipboard_utilities.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -154,13 +153,11 @@ String SystemClipboard::ReadRTF() {
return rtf;
}
-scoped_refptr<BlobDataHandle> SystemClipboard::ReadImage(
- mojom::ClipboardBuffer buffer) {
- if (!IsValidBufferType(buffer))
- return nullptr;
- scoped_refptr<BlobDataHandle> blob;
- clipboard_->ReadImage(buffer, &blob);
- return blob;
+SkBitmap SystemClipboard::ReadImage(mojom::ClipboardBuffer buffer) {
+ SkBitmap image;
+ if (IsValidBufferType(buffer))
+ clipboard_->ReadImage(buffer, &image);
+ return image;
}
void SystemClipboard::WriteImage(Image* image,
@@ -177,26 +174,12 @@ void SystemClipboard::WriteImage(Image* image,
// Only 32-bit bitmaps are supported.
DCHECK_EQ(bitmap.colorType(), kN32_SkColorType);
- const WebSize size(bitmap.width(), bitmap.height());
void* pixels = bitmap.getPixels();
// TODO(piman): this should not be NULL, but it is. crbug.com/369621
if (!pixels)
return;
- CheckedNumeric<uint32_t> checked_buf_size = 4;
- checked_buf_size *= size.width;
- checked_buf_size *= size.height;
- if (!checked_buf_size.IsValid())
- return;
-
- // Allocate a shared memory buffer to hold the bitmap bits.
- uint32_t buf_size = checked_buf_size.ValueOrDie();
- auto shared_buffer = mojo::SharedBufferHandle::Create(buf_size);
- auto mapping = shared_buffer->Map(buf_size);
- memcpy(mapping.get(), pixels, buf_size);
-
- clipboard_->WriteImage(mojom::ClipboardBuffer::kStandard, size,
- std::move(shared_buffer));
+ clipboard_->WriteImage(mojom::ClipboardBuffer::kStandard, bitmap);
if (url.IsValid() && !url.IsEmpty()) {
clipboard_->WriteBookmark(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 fa645c3141b..e63b7646f01 100644
--- a/chromium/third_party/blink/renderer/core/clipboard/system_clipboard.h
+++ b/chromium/third_party/blink/renderer/core/clipboard/system_clipboard.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_SYSTEM_CLIPBOARD_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CLIPBOARD_SYSTEM_CLIPBOARD_H_
-#include "base/memory/scoped_refptr.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/wtf/forward.h"
@@ -13,7 +12,6 @@
namespace blink {
-class BlobDataHandle;
class DataObject;
class Image;
class KURL;
@@ -51,7 +49,7 @@ class CORE_EXPORT SystemClipboard {
String ReadRTF();
- scoped_refptr<BlobDataHandle> ReadImage(mojom::ClipboardBuffer);
+ SkBitmap ReadImage(mojom::ClipboardBuffer);
void WriteImage(Image*, const KURL&, const String& title);
String ReadCustomData(const String& type);
diff --git a/chromium/third_party/blink/renderer/core/core_export.h b/chromium/third_party/blink/renderer/core/core_export.h
index c71a87814c2..24af246f54d 100644
--- a/chromium/third_party/blink/renderer/core/core_export.h
+++ b/chromium/third_party/blink/renderer/core/core_export.h
@@ -43,27 +43,23 @@
#endif // !defined(COMPONENT_BUILD)
//
-// CORE_TEMPLATE_CLASS_EXPORT
// CORE_EXTERN_TEMPLATE_EXPORT
// CORE_TEMPLATE_EXPORT
//
#if BLINK_CORE_IMPLEMENTATION
#if defined(COMPILER_MSVC)
-#define CORE_TEMPLATE_CLASS_EXPORT
-#define CORE_EXTERN_TEMPLATE_EXPORT CORE_EXPORT
+#define CORE_EXTERN_TEMPLATE_EXPORT
#define CORE_TEMPLATE_EXPORT CORE_EXPORT
#endif
#if defined(COMPILER_GCC)
-#define CORE_TEMPLATE_CLASS_EXPORT CORE_EXPORT
#define CORE_EXTERN_TEMPLATE_EXPORT CORE_EXPORT
#define CORE_TEMPLATE_EXPORT
#endif
#else // BLINK_CORE_IMPLEMENTATION
-#define CORE_TEMPLATE_CLASS_EXPORT
#define CORE_EXTERN_TEMPLATE_EXPORT CORE_EXPORT
#define CORE_TEMPLATE_EXPORT
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 a94060a67d0..34474a9663b 100644
--- a/chromium/third_party/blink/renderer/core/core_idl_files.gni
+++ b/chromium/third_party/blink/renderer/core/core_idl_files.gni
@@ -36,6 +36,9 @@ core_global_constructors_generated_idl_files =
core_idl_files =
get_path_info([
+ "aom/accessible_node.idl",
+ "aom/accessible_node_list.idl",
+ "aom/computed_accessible_node.idl",
"animation/animation.idl",
"animation/animation_effect.idl",
"animation/animation_timeline.idl",
@@ -99,13 +102,10 @@ core_idl_files =
"css/cssom/style_property_map_read_only.idl",
"dom/abort_controller.idl",
"dom/abort_signal.idl",
- "dom/accessible_node.idl",
- "dom/accessible_node_list.idl",
"dom/attr.idl",
"dom/cdata_section.idl",
"dom/character_data.idl",
"dom/comment.idl",
- "dom/computed_accessible_node.idl",
"dom/dom_exception.idl",
"dom/dom_implementation.idl",
"dom/dom_string_list.idl",
@@ -133,9 +133,9 @@ core_idl_files =
"dom/events/custom_event.idl",
"dom/events/event.idl",
"dom/events/event_target.idl",
- "dom/trustedtypes/trusted_html.idl",
- "dom/trustedtypes/trusted_script_url.idl",
- "dom/trustedtypes/trusted_url.idl",
+ "trustedtypes/trusted_html.idl",
+ "trustedtypes/trusted_script_url.idl",
+ "trustedtypes/trusted_url.idl",
"editing/selection.idl",
"events/animation_event.idl",
"events/animation_playback_event.idl",
@@ -153,6 +153,7 @@ core_idl_files =
"events/mouse_event.idl",
"events/mutation_event.idl",
"events/page_transition_event.idl",
+ "events/picture_in_picture_control_event.idl",
"events/pointer_event.idl",
"events/pop_state_event.idl",
"events/progress_event.idl",
@@ -174,14 +175,15 @@ core_idl_files =
"fileapi/file_reader.idl",
"fileapi/file_reader_sync.idl",
"frame/bar_prop.idl",
- "frame/deprecation_report.idl",
+ "frame/deprecation_report_body.idl",
"frame/external.idl",
"frame/history.idl",
- "frame/intervention_report.idl",
+ "frame/intervention_report_body.idl",
"frame/location.idl",
"frame/report.idl",
"frame/report_body.idl",
"frame/reporting_observer.idl",
+ "frame/user_activation.idl",
"frame/visual_viewport.idl",
"geometry/dom_matrix.idl",
"geometry/dom_matrix_read_only.idl",
@@ -514,6 +516,7 @@ core_dependency_idl_files =
"frame/navigator_id.idl",
"frame/navigator_language.idl",
"frame/navigator_on_line.idl",
+ "frame/navigator_user_activation.idl",
"frame/window_base64.idl",
"frame/window_event_handlers.idl",
"frame/window_timers.idl",
@@ -599,6 +602,7 @@ core_dictionary_idl_files =
"events/message_event_init.idl",
"events/mouse_event_init.idl",
"events/page_transition_event_init.idl",
+ "events/picture_in_picture_control_event_init.idl",
"events/pointer_event_init.idl",
"events/pop_state_event_init.idl",
"events/progress_event_init.idl",
@@ -608,12 +612,15 @@ core_dictionary_idl_files =
"events/transition_event_init.idl",
"events/ui_event_init.idl",
"events/wheel_event_init.idl",
+ "fetch/request_init.idl",
"fetch/response_init.idl",
"fileapi/blob_property_bag.idl",
"fileapi/file_property_bag.idl",
+ "frame/reporting_observer_options.idl",
"frame/scroll_into_view_options.idl",
"frame/scroll_options.idl",
"frame/scroll_to_options.idl",
+ "frame/window_post_message_options.idl",
"fullscreen/fullscreen_options.idl",
"geometry/dom_matrix_2d_init.idl",
"geometry/dom_matrix_init.idl",
@@ -623,6 +630,7 @@ core_dictionary_idl_files =
"html/focus_options.idl",
"html/assigned_nodes_options.idl",
"html/canvas/image_data_color_settings.idl",
+ "html/canvas/image_encode_options.idl",
"html/track/track_event_init.idl",
"imagebitmap/image_bitmap_options.idl",
"input/input_device_capabilities_init.idl",
@@ -645,7 +653,6 @@ core_dictionary_idl_files =
"mojo/mojo_write_data_options.idl",
"mojo/mojo_write_data_result.idl",
"mojo/test/mojo_interface_request_event_init.idl",
- "offscreencanvas/image_encode_options.idl",
"page/scrolling/scroll_state_init.idl",
"timing/performance_mark_options.idl",
"timing/performance_measure_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 ca0a69e7878..2737c9b2b68 100644
--- a/chromium/third_party/blink/renderer/core/core_initializer.cc
+++ b/chromium/third_party/blink/renderer/core/core_initializer.cc
@@ -32,6 +32,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/script_streamer_thread.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"
#include "third_party/blink/renderer/core/css/media_query_evaluator.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
@@ -143,6 +144,8 @@ void CoreInitializer::Initialize() {
StringImpl::FreezeStaticStrings();
+ V8ThrowDOMException::Init();
+
ScriptStreamerThread::Init();
}
diff --git a/chromium/third_party/blink/renderer/core/core_initializer.h b/chromium/third_party/blink/renderer/core/core_initializer.h
index 1de64c989b2..2737b6bd957 100644
--- a/chromium/third_party/blink/renderer/core/core_initializer.h
+++ b/chromium/third_party/blink/renderer/core/core_initializer.h
@@ -49,7 +49,7 @@ class Page;
class PictureInPictureController;
class Settings;
class ShadowRoot;
-class WebFrameClient;
+class WebLocalFrameClient;
class WebLayerTreeView;
class WebMediaPlayer;
class WebMediaPlayerClient;
@@ -103,7 +103,7 @@ class CORE_EXPORT CoreInitializer {
const Settings&) const = 0;
virtual std::unique_ptr<WebMediaPlayer> CreateWebMediaPlayer(
- WebFrameClient*,
+ WebLocalFrameClient*,
HTMLMediaElement&,
const WebMediaPlayerSource&,
WebMediaPlayerClient*,
diff --git a/chromium/third_party/blink/renderer/core/css/BUILD.gn b/chromium/third_party/blink/renderer/core/css/BUILD.gn
index 8db0b38c35c..8a3c38f8846 100644
--- a/chromium/third_party/blink/renderer/core/css/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/css/BUILD.gn
@@ -160,8 +160,6 @@ blink_core_sources("css") {
"css_supports_rule.h",
"css_syntax_descriptor.cc",
"css_syntax_descriptor.h",
- "css_timing.cc",
- "css_timing.h",
"css_timing_function_value.cc",
"css_timing_function_value.h",
"css_to_length_conversion_data.cc",
@@ -262,6 +260,8 @@ blink_core_sources("css") {
"cssom/style_property_map_read_only.h",
"cssom/style_value_factory.cc",
"cssom/style_value_factory.h",
+ "document_style_environment_variables.cc",
+ "document_style_environment_variables.h",
"document_style_sheet_collection.cc",
"document_style_sheet_collection.h",
"document_style_sheet_collector.cc",
@@ -416,6 +416,10 @@ blink_core_sources("css") {
"properties/longhands/background_size_custom.cc",
"properties/longhands/baseline_shift_custom.cc",
"properties/longhands/block_size_custom.cc",
+ "properties/longhands/border_block_end_color_custom.cc",
+ "properties/longhands/border_block_end_width_custom.cc",
+ "properties/longhands/border_block_start_color_custom.cc",
+ "properties/longhands/border_block_start_width_custom.cc",
"properties/longhands/border_bottom_color_custom.cc",
"properties/longhands/border_bottom_left_radius_custom.cc",
"properties/longhands/border_bottom_right_radius_custom.cc",
@@ -427,6 +431,10 @@ blink_core_sources("css") {
"properties/longhands/border_image_slice_custom.cc",
"properties/longhands/border_image_source_custom.cc",
"properties/longhands/border_image_width_custom.cc",
+ "properties/longhands/border_inline_end_color_custom.cc",
+ "properties/longhands/border_inline_end_width_custom.cc",
+ "properties/longhands/border_inline_start_color_custom.cc",
+ "properties/longhands/border_inline_start_width_custom.cc",
"properties/longhands/border_left_color_custom.cc",
"properties/longhands/border_left_style_custom.cc",
"properties/longhands/border_left_width_custom.cc",
@@ -515,6 +523,10 @@ blink_core_sources("css") {
"properties/longhands/image_orientation_custom.cc",
"properties/longhands/image_rendering_custom.cc",
"properties/longhands/inline_size_custom.cc",
+ "properties/longhands/inset_block_end_custom.cc",
+ "properties/longhands/inset_block_start_custom.cc",
+ "properties/longhands/inset_inline_end_custom.cc",
+ "properties/longhands/inset_inline_start_custom.cc",
"properties/longhands/isolation_custom.cc",
"properties/longhands/justify_content_custom.cc",
"properties/longhands/justify_items_custom.cc",
@@ -528,7 +540,11 @@ blink_core_sources("css") {
"properties/longhands/list_style_image_custom.cc",
"properties/longhands/list_style_position_custom.cc",
"properties/longhands/list_style_type_custom.cc",
+ "properties/longhands/margin_block_end_custom.cc",
+ "properties/longhands/margin_block_start_custom.cc",
"properties/longhands/margin_bottom_custom.cc",
+ "properties/longhands/margin_inline_end_custom.cc",
+ "properties/longhands/margin_inline_start_custom.cc",
"properties/longhands/margin_left_custom.cc",
"properties/longhands/margin_right_custom.cc",
"properties/longhands/margin_top_custom.cc",
@@ -567,7 +583,11 @@ blink_core_sources("css") {
"properties/longhands/overflow_y_custom.cc",
"properties/longhands/overscroll_behavior_x_custom.cc",
"properties/longhands/overscroll_behavior_y_custom.cc",
+ "properties/longhands/padding_block_end_custom.cc",
+ "properties/longhands/padding_block_start_custom.cc",
"properties/longhands/padding_bottom_custom.cc",
+ "properties/longhands/padding_inline_end_custom.cc",
+ "properties/longhands/padding_inline_start_custom.cc",
"properties/longhands/padding_left_custom.cc",
"properties/longhands/padding_right_custom.cc",
"properties/longhands/padding_top_custom.cc",
@@ -655,22 +675,15 @@ blink_core_sources("css") {
"properties/longhands/translate_custom.cc",
"properties/longhands/unicode_bidi_custom.cc",
"properties/longhands/user_select_custom.cc",
+ "properties/longhands/variable.cc",
"properties/longhands/variable.h",
"properties/longhands/vector_effect_custom.cc",
"properties/longhands/vertical_align_custom.cc",
"properties/longhands/visibility_custom.cc",
"properties/longhands/webkit_app_region_custom.cc",
"properties/longhands/webkit_appearance_custom.cc",
- "properties/longhands/webkit_border_after_color_custom.cc",
- "properties/longhands/webkit_border_after_width_custom.cc",
- "properties/longhands/webkit_border_before_color_custom.cc",
- "properties/longhands/webkit_border_before_width_custom.cc",
- "properties/longhands/webkit_border_end_color_custom.cc",
- "properties/longhands/webkit_border_end_width_custom.cc",
"properties/longhands/webkit_border_horizontal_spacing_custom.cc",
"properties/longhands/webkit_border_image_custom.cc",
- "properties/longhands/webkit_border_start_color_custom.cc",
- "properties/longhands/webkit_border_start_width_custom.cc",
"properties/longhands/webkit_border_vertical_spacing_custom.cc",
"properties/longhands/webkit_box_align_custom.cc",
"properties/longhands/webkit_box_decoration_break_custom.cc",
@@ -687,15 +700,9 @@ blink_core_sources("css") {
"properties/longhands/webkit_line_break_custom.cc",
"properties/longhands/webkit_line_clamp_custom.cc",
"properties/longhands/webkit_locale_custom.cc",
- "properties/longhands/webkit_logical_height_custom.cc",
- "properties/longhands/webkit_logical_width_custom.cc",
"properties/longhands/webkit_margin_after_collapse_custom.cc",
- "properties/longhands/webkit_margin_after_custom.cc",
"properties/longhands/webkit_margin_before_collapse_custom.cc",
- "properties/longhands/webkit_margin_before_custom.cc",
"properties/longhands/webkit_margin_bottom_collapse_custom.cc",
- "properties/longhands/webkit_margin_end_custom.cc",
- "properties/longhands/webkit_margin_start_custom.cc",
"properties/longhands/webkit_margin_top_collapse_custom.cc",
"properties/longhands/webkit_mask_box_image_outset_custom.cc",
"properties/longhands/webkit_mask_box_image_repeat_custom.cc",
@@ -709,14 +716,6 @@ blink_core_sources("css") {
"properties/longhands/webkit_mask_position_x_custom.cc",
"properties/longhands/webkit_mask_position_y_custom.cc",
"properties/longhands/webkit_mask_size_custom.cc",
- "properties/longhands/webkit_max_logical_height_custom.cc",
- "properties/longhands/webkit_max_logical_width_custom.cc",
- "properties/longhands/webkit_min_logical_height_custom.cc",
- "properties/longhands/webkit_min_logical_width_custom.cc",
- "properties/longhands/webkit_padding_after_custom.cc",
- "properties/longhands/webkit_padding_before_custom.cc",
- "properties/longhands/webkit_padding_end_custom.cc",
- "properties/longhands/webkit_padding_start_custom.cc",
"properties/longhands/webkit_perspective_origin_x_custom.cc",
"properties/longhands/webkit_perspective_origin_y_custom.cc",
"properties/longhands/webkit_print_color_adjust_custom.cc",
@@ -745,7 +744,6 @@ blink_core_sources("css") {
"properties/longhands/will_change_custom.cc",
"properties/longhands/word_break_custom.cc",
"properties/longhands/word_spacing_custom.cc",
- "properties/longhands/word_wrap_custom.cc",
"properties/longhands/writing_mode_custom.cc",
"properties/longhands/x_custom.cc",
"properties/longhands/y_custom.cc",
@@ -756,10 +754,22 @@ blink_core_sources("css") {
"properties/shorthands/background_custom.cc",
"properties/shorthands/background_position_custom.cc",
"properties/shorthands/background_repeat_custom.cc",
+ "properties/shorthands/border_block_color_custom.cc",
+ "properties/shorthands/border_block_custom.cc",
+ "properties/shorthands/border_block_end_custom.cc",
+ "properties/shorthands/border_block_start_custom.cc",
+ "properties/shorthands/border_block_style_custom.cc",
+ "properties/shorthands/border_block_width_custom.cc",
"properties/shorthands/border_bottom_custom.cc",
"properties/shorthands/border_color_custom.cc",
"properties/shorthands/border_custom.cc",
"properties/shorthands/border_image_custom.cc",
+ "properties/shorthands/border_inline_color_custom.cc",
+ "properties/shorthands/border_inline_custom.cc",
+ "properties/shorthands/border_inline_end_custom.cc",
+ "properties/shorthands/border_inline_start_custom.cc",
+ "properties/shorthands/border_inline_style_custom.cc",
+ "properties/shorthands/border_inline_width_custom.cc",
"properties/shorthands/border_left_custom.cc",
"properties/shorthands/border_radius_custom.cc",
"properties/shorthands/border_right_custom.cc",
@@ -782,14 +792,21 @@ blink_core_sources("css") {
"properties/shorthands/grid_row_custom.cc",
"properties/shorthands/grid_row_gap_custom.cc",
"properties/shorthands/grid_template_custom.cc",
+ "properties/shorthands/inset_block_custom.cc",
+ "properties/shorthands/inset_custom.cc",
+ "properties/shorthands/inset_inline_custom.cc",
"properties/shorthands/list_style_custom.cc",
+ "properties/shorthands/margin_block_custom.cc",
"properties/shorthands/margin_custom.cc",
+ "properties/shorthands/margin_inline_custom.cc",
"properties/shorthands/marker_custom.cc",
"properties/shorthands/offset_custom.cc",
"properties/shorthands/outline_custom.cc",
"properties/shorthands/overflow_custom.cc",
"properties/shorthands/overscroll_behavior_custom.cc",
+ "properties/shorthands/padding_block_custom.cc",
"properties/shorthands/padding_custom.cc",
+ "properties/shorthands/padding_inline_custom.cc",
"properties/shorthands/page_break_after_custom.cc",
"properties/shorthands/page_break_before_custom.cc",
"properties/shorthands/page_break_inside_custom.cc",
@@ -804,10 +821,6 @@ blink_core_sources("css") {
"properties/shorthands/scroll_padding_inline_custom.cc",
"properties/shorthands/text_decoration_custom.cc",
"properties/shorthands/transition_custom.cc",
- "properties/shorthands/webkit_border_after_custom.cc",
- "properties/shorthands/webkit_border_before_custom.cc",
- "properties/shorthands/webkit_border_end_custom.cc",
- "properties/shorthands/webkit_border_start_custom.cc",
"properties/shorthands/webkit_column_break_after_custom.cc",
"properties/shorthands/webkit_column_break_before_custom.cc",
"properties/shorthands/webkit_column_break_inside_custom.cc",
@@ -857,9 +870,10 @@ blink_core_sources("css") {
"resolver/selector_filter_parent_scope.h",
"resolver/style_adjuster.cc",
"resolver/style_adjuster.h",
+ "resolver/style_builder.cc",
+ "resolver/style_builder.h",
"resolver/style_builder_converter.cc",
"resolver/style_builder_converter.h",
- "resolver/style_builder_custom.cc",
"resolver/style_resolver.cc",
"resolver/style_resolver.h",
"resolver/style_resolver_state.cc",
@@ -899,6 +913,8 @@ blink_core_sources("css") {
"style_engine.h",
"style_engine_context.cc",
"style_engine_context.h",
+ "style_environment_variables.cc",
+ "style_environment_variables.h",
"style_media.cc",
"style_media.h",
"style_property_serializer.cc",
diff --git a/chromium/third_party/blink/renderer/core/css/CSSProperties.json5 b/chromium/third_party/blink/renderer/core/css/CSSProperties.json5
index e8480c4f756..c4478b93cf9 100644
--- a/chromium/third_party/blink/renderer/core/css/CSSProperties.json5
+++ b/chromium/third_party/blink/renderer/core/css/CSSProperties.json5
@@ -62,12 +62,15 @@
"border_image",
"color",
"counter",
+ "empty",
+ "grid",
// The legacy template means that regular code generation should not be
// be performed, and that the property is hard-coded in
// style_builder_functions.cc.tmpl.
"legacy",
"mask_box",
"mask_layer",
+ "svg_paint",
"transition",
],
},
@@ -78,13 +81,6 @@
valid_type: "dict"
},
- // Set this to true if we do not support generation of style builder
- // functions in the CSSProperty subclasses (yet).
- style_builder_legacy: {
- default: false,
- value_type: "bool"
- },
-
// - 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
@@ -273,8 +269,8 @@
// The remaining arguments are used for the StyleBuilder and allow us to
// succinctly describe how to apply properties. When default handlers are
// not sufficient, we should prefer to use converter, and failing that
- // define custom property handlers in StyleBuilderCustom.cpp. We only should
- // use style_builder_functions.cc.tmpl to define handlers when there are
+ // define custom property handlers in CSSProperty subclasses. We should only
+ // use style_builder_functions.tmpl to define handlers when there are
// multiple properties requiring the same handling, but converter doesn't
// suffice.
@@ -328,13 +324,6 @@
converter: {
},
- // - builder_skip
- // Ignore this property in the StyleBuilder
- builder_skip: {
- default: false,
- valid_type: "bool",
- },
-
// - logical_side
// The logical side represented by a direction-dependent property
// - shorthand_for_physical_side
@@ -371,6 +360,15 @@
default: false,
valid_type: "bool",
},
+
+ // - valid_for_visited_link
+ // Most CSS properties do not apply to :visited and :link for privacy
+ // reasons. Mark properties which apply to :visited and :link by setting
+ // this flag to true.
+ valid_for_visited_link: {
+ default: false,
+ valid_type: "bool",
+ },
},
// Members in the data objects should appear in the same order as in the
@@ -537,11 +535,11 @@
default_value: "Color::kBlack",
type_name: "Color",
computed_style_custom_functions: ["getter", "setter"],
- style_builder_legacy: true,
style_builder_custom_functions: ["initial", "inherit", "value"],
priority: "High",
keywords: ["currentcolor"],
typedom_types: ["Keyword"],
+ valid_for_visited_link: true,
},
{
name: "direction",
@@ -554,7 +552,6 @@
typedom_types: ["Keyword"],
default_value: "ltr",
type_name: "TextDirection",
- style_builder_legacy: true,
style_builder_custom_functions: ["value"],
priority: "High",
},
@@ -743,7 +740,6 @@
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
inherited: true,
font: true,
- style_builder_legacy: true,
style_builder_custom_functions: ["value"],
priority: "High",
},
@@ -757,7 +753,6 @@
typedom_types: ["Keyword"],
default_value: "mixed",
getter: "GetTextOrientation",
- style_builder_legacy: true,
style_builder_custom_functions: ["value"],
priority: "High",
},
@@ -766,7 +761,6 @@
property_methods: ["CSSValueFromComputedStyleInternal"],
inherited: true,
type_name: "TextOrientation",
- style_builder_legacy: true,
style_builder_custom_functions: ["value"],
priority: "High",
},
@@ -780,7 +774,6 @@
typedom_types: ["Keyword"],
default_value: "horizontal-tb",
type_name: "WritingMode",
- style_builder_legacy: true,
style_builder_custom_functions: ["value"],
priority: "High",
},
@@ -789,7 +782,6 @@
property_methods: ["CSSValueFromComputedStyleInternal"],
inherited: true,
type_name: "WritingMode",
- style_builder_legacy: true,
style_builder_custom_functions: ["value"],
priority: "High",
},
@@ -811,7 +803,6 @@
field_template: "primitive",
default_value: "1.0",
type_name: "float",
- style_builder_legacy: true,
style_builder_custom_functions: ["initial", "inherit", "value"],
priority: "High",
},
@@ -933,6 +924,7 @@
style_builder_template_args: {
initial_color: "ComputedStyleInitialValues::InitialBackgroundColor",
},
+ valid_for_visited_link: true,
},
{
name: "background-image",
@@ -1007,7 +999,6 @@
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
interpolable: true,
svg: true,
- style_builder_legacy: true,
style_builder_custom_functions: ["inherit", "value"],
keywords: ["sub", "super"],
typedom_types: ["Keyword", "Percentage", "Length"]
@@ -1026,6 +1017,7 @@
typedom_types: ["Keyword"],
converter: "ConvertStyleColor",
style_builder_template: "color",
+ valid_for_visited_link: true,
},
{
name: "border-bottom-left-radius",
@@ -1124,7 +1116,6 @@
interpolable: true,
keywords: ["none"],
typedom_types: ["Keyword", "Image"],
- style_builder_legacy: true,
style_builder_custom_functions: ["value"],
},
{
@@ -1152,6 +1143,7 @@
typedom_types: ["Keyword"],
converter: "ConvertStyleColor",
style_builder_template: "color",
+ valid_for_visited_link: true,
},
{
name: "border-left-style",
@@ -1194,6 +1186,7 @@
typedom_types: ["Keyword"],
converter: "ConvertStyleColor",
style_builder_template: "color",
+ valid_for_visited_link: true,
},
{
name: "border-right-style",
@@ -1236,6 +1229,7 @@
typedom_types: ["Keyword"],
converter: "ConvertStyleColor",
style_builder_template: "color",
+ valid_for_visited_link: true,
},
{
name: "border-top-left-radius",
@@ -1387,10 +1381,10 @@
default_value: "Color()",
type_name: "Color",
computed_style_custom_functions: ["getter", "setter"],
- style_builder_legacy: true,
style_builder_custom_functions: ["initial", "inherit", "value"],
keywords: ["auto", "currentcolor"],
typedom_types: ["Keyword"],
+ valid_for_visited_link: true,
},
{
name: "clear",
@@ -1495,7 +1489,6 @@
separator: ",",
type_name: "ContentData",
computed_style_custom_functions: ["getter", "setter"],
- style_builder_legacy: true,
style_builder_custom_functions: ["initial", "inherit", "value"],
},
{
@@ -1533,7 +1526,6 @@
"zoom-out", "grab", "grabbing"
],
default_value: "auto",
- style_builder_legacy: true,
style_builder_custom_functions: ["initial", "inherit", "value"],
typedom_types: ["Keyword"]
},
@@ -1573,7 +1565,6 @@
"inline-flex", "grid", "inline-grid", "contents", "flow-root", "none"
],
typedom_types: ["Keyword"],
- style_builder_legacy: true,
style_builder_custom_functions: ["initial", "inherit", "value"],
},
{
@@ -1601,8 +1592,12 @@
inherited: true,
svg: true,
setter: "SetFillPaint",
- style_builder_legacy: true,
- style_builder_template: "legacy",
+ converter: "ConvertSVGPaint",
+ style_builder_template: "svg_paint",
+ style_builder_template_args: {
+ paint_type: "FillPaint",
+ },
+ valid_for_visited_link: true,
},
{
name: "fill-opacity",
@@ -1806,7 +1801,6 @@
{
name: "grid-template-areas",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
- style_builder_legacy: true,
style_builder_custom_functions: ["initial", "inherit", "value"],
keywords: ["none"],
typedom_types: ["Keyword"]
@@ -1821,8 +1815,10 @@
"third_party/blink/renderer/core/style/grid_track_size.h"],
default_value: "Vector<GridTrackSize>()",
type_name: "Vector<GridTrackSize>",
- style_builder_legacy: true,
- style_builder_template: "legacy",
+ style_builder_template: "grid",
+ style_builder_template_args: {
+ type: "Column",
+ },
keywords: ["none"],
typedom_types: ["Keyword"]
},
@@ -1836,8 +1832,10 @@
"third_party/blink/renderer/core/style/grid_track_size.h"],
default_value: "Vector<GridTrackSize>()",
type_name: "Vector<GridTrackSize>",
- style_builder_legacy: true,
- style_builder_template: "legacy",
+ style_builder_template: "grid",
+ style_builder_template_args: {
+ type: "Row",
+ },
keywords: ["none"],
typedom_types: ["Keyword"]
},
@@ -1998,7 +1996,6 @@
typedom_types: ["Keyword", "Image"],
type_name: "StyleImage",
computed_style_custom_functions: ["getter", "setter"],
- style_builder_legacy: true,
style_builder_custom_functions: ["value"],
keywords: ["none"]
},
@@ -2333,6 +2330,7 @@
typedom_types: ["Keyword"],
converter: "ConvertStyleColor",
style_builder_template: "color",
+ valid_for_visited_link: true,
},
{
name: "outline-offset",
@@ -2358,7 +2356,6 @@
typedom_types: ["Keyword"],
default_value: "none",
type_name: "EBorderStyle",
- style_builder_legacy: true,
style_builder_custom_functions: ["initial", "inherit", "value"],
},
{
@@ -2541,7 +2538,6 @@
typedom_types: ["Keyword"],
default_value: "static",
getter: "GetPosition",
- style_builder_legacy: true,
style_builder_custom_functions: ["inherit"],
},
{
@@ -2566,7 +2562,6 @@
keywords: ["none", "both", "horizontal", "vertical"],
typedom_types: ["Keyword"],
default_value: "none",
- style_builder_legacy: true,
style_builder_custom_functions: ["value"],
},
{
@@ -2892,7 +2887,6 @@
{
name: "size",
property_methods: ["ParseSingleValue"],
- style_builder_legacy: true,
style_builder_custom_functions: ["initial", "inherit", "value"],
},
{
@@ -2931,8 +2925,12 @@
inherited: true,
svg: true,
setter: "SetStrokePaint",
- style_builder_legacy: true,
- style_builder_template: "legacy",
+ converter: "ConvertSVGPaint",
+ style_builder_template: "svg_paint",
+ style_builder_template_args: {
+ paint_type: "StrokePaint",
+ },
+ valid_for_visited_link: true,
},
{
name: "stroke-dasharray",
@@ -3040,7 +3038,6 @@
typedom_types: ["Keyword"],
default_value: "start",
getter: "GetTextAlign",
- style_builder_legacy: true,
style_builder_custom_functions: ["value"],
},
{
@@ -3085,6 +3082,7 @@
typedom_types: ["Keyword"],
converter: "ConvertStyleColor",
style_builder_template: "color",
+ valid_for_visited_link: true,
},
{
name: "text-decoration-line",
@@ -3125,7 +3123,6 @@
field_group: "*",
field_template: "<length>",
default_value: "Length(kFixed)",
- style_builder_legacy: true,
style_builder_custom_functions: ["initial", "inherit", "value"],
typedom_types: ["Length", "Percentage"]
},
@@ -3192,17 +3189,19 @@
typedom_types: ["Keyword"],
default_value: "none",
},
- // FIXME: Implement support for 'under left' and 'under right' values.
{
name: "text-underline-position",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
inherited: true,
field_group: "*",
- field_template: "keyword",
- keywords: ["auto", "under"],
- default_value: "auto",
- type_name: "TextUnderlinePosition",
- typedom_types: ["Keyword"]
+ field_size: 3,
+ field_template: "primitive",
+ default_value: "kTextUnderlinePositionAuto",
+ name_for_methods: "TextUnderlinePosition",
+ type_name: "unsigned",
+ converter: "ConvertTextUnderlinePosition",
+ keywords: ["auto", "under", "left", "right"],
+ typedom_types: ["Keyword"],
},
{
name: "top",
@@ -3344,7 +3343,6 @@
name: "vertical-align",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
interpolable: true,
- style_builder_legacy: true,
style_builder_custom_functions: ["inherit", "value"],
typedom_types: ["Keyword", "Length", "Percentage"],
keywords: ["baseline", "sub", "super", "text-top", "text-bottom", "middle"],
@@ -3393,7 +3391,6 @@
keywords: ["none", "drag", "no-drag"],
default_value: "none",
name_for_methods: "DraggableRegionMode",
- style_builder_legacy: true,
style_builder_custom_functions: ["initial", "inherit", "value"],
},
{
@@ -3411,7 +3408,6 @@
{
name: "-webkit-border-image",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
- style_builder_legacy: true,
style_builder_custom_functions: ["value"],
},
{
@@ -3551,6 +3547,7 @@
typedom_types: ["Keyword"],
converter: "ConvertStyleColor",
style_builder_template: "color",
+ valid_for_visited_link: true,
},
{
name: "column-rule-style",
@@ -3713,7 +3710,6 @@
name: "-webkit-mask-box-image-source",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
interpolable: true,
- style_builder_legacy: true,
style_builder_custom_functions: ["value"],
},
{
@@ -3870,6 +3866,7 @@
computed_style_custom_functions: ["getter", "setter"],
converter: "ConvertStyleColor",
style_builder_template: "color",
+ valid_for_visited_link: true,
},
{
name: "-webkit-text-emphasis-position",
@@ -3886,7 +3883,6 @@
name: "-webkit-text-emphasis-style",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
inherited: true,
- style_builder_legacy: true,
style_builder_custom_functions: ["initial", "inherit", "value"],
},
{
@@ -3901,6 +3897,7 @@
computed_style_custom_functions: ["getter", "setter"],
converter: "ConvertStyleColor",
style_builder_template: "color",
+ valid_for_visited_link: true,
},
{
name: "-webkit-text-security",
@@ -3910,6 +3907,7 @@
field_template: "keyword",
keywords: ["none", "disc", "circle", "square"],
default_value: "none",
+ valid_for_visited_link: true,
},
{
name: "-webkit-text-stroke-color",
@@ -3924,6 +3922,7 @@
computed_style_custom_functions: ["getter", "setter"],
converter: "ConvertStyleColor",
style_builder_template: "color",
+ valid_for_visited_link: true,
},
{
name: "-webkit-text-stroke-width",
@@ -4020,7 +4019,6 @@
{
name: "will-change",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
- style_builder_legacy: true,
style_builder_custom_functions: ["initial", "inherit", "value"],
keywords: ["auto"],
typedom_types: ["Keyword"]
@@ -4046,16 +4044,6 @@
typedom_types: ["normal"],
typedom_types: ["Keyword", "Length"]
},
- // UAs must treat 'word-wrap' as an alternate name for the 'overflow-wrap'
- // property. So using the same handlers.
- {
- name: "word-wrap",
- property_methods: ["CSSValueFromComputedStyleInternal"],
- inherited: true,
- name_for_methods: "OverflowWrap",
- keywords: ["normal", "break-word"],
- typedom_types: ["Keyword"]
- },
{
name: "z-index",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
@@ -4074,6 +4062,7 @@
{
name: "inline-size",
property_methods: ["ParseSingleValue"],
+ layout_dependent: true,
direction_aware_options: {
logical_side: "width",
shorthand_for_physical_side: "CSSProperty",
@@ -4084,6 +4073,7 @@
{
name: "block-size",
property_methods: ["ParseSingleValue"],
+ layout_dependent: true,
direction_aware_options: {
logical_side: "height",
shorthand_for_physical_side: "CSSProperty",
@@ -4129,212 +4119,308 @@
keywords: ["none"],
typedom_types: ["Keyword", "Length", "Percentage"],
},
-
- // Non-standard direction aware properties
-
{
- name: "-webkit-border-end-color",
+ name: "margin-inline-start",
property_methods: ["ParseSingleValue"],
direction_aware_options: {
- logical_side: "end",
- shorthand_for_physical_side: "borderColorShorthand",
+ logical_side: "start",
+ shorthand_for_physical_side: "marginShorthand",
},
+ keywords: ["auto"]
},
{
- name: "-webkit-border-end-style",
+ name: "margin-inline-end",
+ property_methods: ["ParseSingleValue"],
direction_aware_options: {
logical_side: "end",
- shorthand_for_physical_side: "borderStyleShorthand",
+ shorthand_for_physical_side: "marginShorthand",
},
+ keywords: ["auto"]
},
{
- name: "-webkit-border-end-width",
+ name: "margin-block-start",
property_methods: ["ParseSingleValue"],
direction_aware_options: {
- logical_side: "end",
- shorthand_for_physical_side: "borderWidthShorthand",
+ logical_side: "before",
+ shorthand_for_physical_side: "marginShorthand",
},
+ keywords: ["auto"]
},
{
- name: "-webkit-border-start-color",
+ name: "margin-block-end",
property_methods: ["ParseSingleValue"],
direction_aware_options: {
- logical_side: "start",
- shorthand_for_physical_side: "borderColorShorthand",
+ logical_side: "after",
+ shorthand_for_physical_side: "marginShorthand",
},
+ keywords: ["auto"]
},
{
- name: "-webkit-border-start-style",
+ name: "padding-inline-start",
+ property_methods: ["ParseSingleValue"],
direction_aware_options: {
logical_side: "start",
- shorthand_for_physical_side: "borderStyleShorthand",
- },
+ shorthand_for_physical_side: "paddingShorthand",
+ }
},
{
- name: "-webkit-border-start-width",
+ name: "padding-inline-end",
property_methods: ["ParseSingleValue"],
direction_aware_options: {
- logical_side: "start",
- shorthand_for_physical_side: "borderWidthShorthand",
- },
+ logical_side: "end",
+ shorthand_for_physical_side: "paddingShorthand",
+ }
},
{
- name: "-webkit-border-before-color",
+ name: "padding-block-start",
property_methods: ["ParseSingleValue"],
direction_aware_options: {
logical_side: "before",
- shorthand_for_physical_side: "borderColorShorthand",
- },
+ shorthand_for_physical_side: "paddingShorthand",
+ }
},
{
- name: "-webkit-border-before-style",
+ name: "padding-block-end",
+ property_methods: ["ParseSingleValue"],
direction_aware_options: {
- logical_side: "before",
- shorthand_for_physical_side: "borderStyleShorthand",
- },
+ logical_side: "after",
+ shorthand_for_physical_side: "paddingShorthand",
+ }
},
{
- name: "-webkit-border-before-width",
+ name: "border-inline-start-width",
property_methods: ["ParseSingleValue"],
direction_aware_options: {
- logical_side: "before",
+ logical_side: "start",
shorthand_for_physical_side: "borderWidthShorthand",
},
},
{
- name: "-webkit-border-after-color",
- property_methods: ["ParseSingleValue"],
+ name: "border-inline-start-style",
direction_aware_options: {
- logical_side: "after",
- shorthand_for_physical_side: "borderColorShorthand",
+ logical_side: "start",
+ shorthand_for_physical_side: "borderStyleShorthand",
},
},
{
- name: "-webkit-border-after-style",
+ name: "border-inline-start-color",
+ property_methods: ["ParseSingleValue"],
direction_aware_options: {
- logical_side: "after",
- shorthand_for_physical_side: "borderStyleShorthand",
+ logical_side: "start",
+ shorthand_for_physical_side: "borderColorShorthand",
},
},
{
- name: "-webkit-border-after-width",
+ name: "border-inline-end-width",
property_methods: ["ParseSingleValue"],
direction_aware_options: {
- logical_side: "after",
+ logical_side: "end",
shorthand_for_physical_side: "borderWidthShorthand",
},
},
{
- name: "-webkit-margin-end",
- property_methods: ["ParseSingleValue"],
+ name: "border-inline-end-style",
direction_aware_options: {
logical_side: "end",
- shorthand_for_physical_side: "marginShorthand",
+ shorthand_for_physical_side: "borderStyleShorthand",
},
},
{
- name: "-webkit-margin-start",
+ name: "border-inline-end-color",
property_methods: ["ParseSingleValue"],
direction_aware_options: {
- logical_side: "start",
- shorthand_for_physical_side: "marginShorthand",
+ logical_side: "end",
+ shorthand_for_physical_side: "borderColorShorthand",
},
},
{
- name: "-webkit-margin-before",
+ name: "border-block-start-width",
property_methods: ["ParseSingleValue"],
direction_aware_options: {
logical_side: "before",
- shorthand_for_physical_side: "marginShorthand",
+ shorthand_for_physical_side: "borderWidthShorthand",
},
},
{
- name: "-webkit-margin-after",
- property_methods: ["ParseSingleValue"],
+ name: "border-block-start-style",
direction_aware_options: {
- logical_side: "after",
- shorthand_for_physical_side: "marginShorthand",
+ logical_side: "before",
+ shorthand_for_physical_side: "borderStyleShorthand",
},
},
{
- name: "-webkit-padding-end",
+ name: "border-block-start-color",
property_methods: ["ParseSingleValue"],
direction_aware_options: {
- logical_side: "end",
- shorthand_for_physical_side: "paddingShorthand",
+ logical_side: "before",
+ shorthand_for_physical_side: "borderColorShorthand",
},
},
{
- name: "-webkit-padding-start",
+ name: "border-block-end-width",
property_methods: ["ParseSingleValue"],
direction_aware_options: {
- logical_side: "start",
- shorthand_for_physical_side: "paddingShorthand",
+ logical_side: "after",
+ shorthand_for_physical_side: "borderWidthShorthand",
},
},
{
- name: "-webkit-padding-before",
- property_methods: ["ParseSingleValue"],
+ name: "border-block-end-style",
direction_aware_options: {
- logical_side: "before",
- shorthand_for_physical_side: "paddingShorthand",
+ logical_side: "after",
+ shorthand_for_physical_side: "borderStyleShorthand",
},
},
{
- name: "-webkit-padding-after",
+ name: "border-block-end-color",
property_methods: ["ParseSingleValue"],
direction_aware_options: {
logical_side: "after",
- shorthand_for_physical_side: "paddingShorthand",
+ shorthand_for_physical_side: "borderColorShorthand",
},
},
{
- name: "-webkit-logical-width",
+ name: "inset-inline-start",
property_methods: ["ParseSingleValue"],
+ runtime_flag: "CSSLogical",
direction_aware_options: {
- logical_side: "width",
- shorthand_for_physical_side: "CSSProperty",
- },
+ logical_side: "start",
+ shorthand_for_physical_side: "insetShorthand",
+ }
},
{
- name: "-webkit-logical-height",
+ name: "inset-inline-end",
property_methods: ["ParseSingleValue"],
+ runtime_flag: "CSSLogical",
direction_aware_options: {
- logical_side: "height",
- shorthand_for_physical_side: "CSSProperty",
- },
+ logical_side: "end",
+ shorthand_for_physical_side: "insetShorthand",
+ }
},
{
- name: "-webkit-min-logical-width",
+ name: "inset-block-start",
property_methods: ["ParseSingleValue"],
+ runtime_flag: "CSSLogical",
direction_aware_options: {
- logical_side: "width",
- shorthand_for_physical_side: "CSSPropertyMin",
- },
+ logical_side: "before",
+ shorthand_for_physical_side: "insetShorthand",
+ }
},
{
- name: "-webkit-min-logical-height",
+ name: "inset-block-end",
property_methods: ["ParseSingleValue"],
+ runtime_flag: "CSSLogical",
direction_aware_options: {
- logical_side: "height",
- shorthand_for_physical_side: "CSSPropertyMin",
- },
+ logical_side: "after",
+ shorthand_for_physical_side: "insetShorthand",
+ }
+ },
+
+ // Non-standard direction aware properties
+
+ {
+ name: "-webkit-border-end-color",
+ alias_for: "border-inline-end-color",
+ },
+ {
+ name: "-webkit-border-end-style",
+ alias_for: "border-inline-end-style",
+ },
+ {
+ name: "-webkit-border-end-width",
+ alias_for: "border-inline-end-width",
+ },
+ {
+ name: "-webkit-border-start-color",
+ alias_for: "border-inline-start-color",
+ },
+ {
+ name: "-webkit-border-start-style",
+ alias_for: "border-inline-start-style",
+ },
+ {
+ name: "-webkit-border-start-width",
+ alias_for: "border-inline-start-width",
+ },
+ {
+ name: "-webkit-border-before-color",
+ alias_for: "border-block-start-color",
+ },
+ {
+ name: "-webkit-border-before-style",
+ alias_for: "border-block-start-style",
+ },
+ {
+ name: "-webkit-border-before-width",
+ alias_for: "border-block-start-width",
+ },
+ {
+ name: "-webkit-border-after-color",
+ alias_for: "border-block-end-color",
+ },
+ {
+ name: "-webkit-border-after-style",
+ alias_for: "border-block-end-style",
+ },
+ {
+ name: "-webkit-border-after-width",
+ alias_for: "border-block-end-width",
+ },
+ {
+ name: "-webkit-margin-end",
+ alias_for: "margin-inline-end",
+ },
+ {
+ name: "-webkit-margin-start",
+ alias_for: "margin-inline-start",
+ },
+ {
+ name: "-webkit-margin-before",
+ alias_for: "margin-block-start",
+ },
+ {
+ name: "-webkit-margin-after",
+ alias_for: "margin-block-end",
+ },
+ {
+ name: "-webkit-padding-end",
+ alias_for: "padding-inline-end",
+ },
+ {
+ name: "-webkit-padding-start",
+ alias_for: "padding-inline-start",
+ },
+ {
+ name: "-webkit-padding-before",
+ alias_for: "padding-block-start",
+ },
+ {
+ name: "-webkit-padding-after",
+ alias_for: "padding-block-end",
+ },
+ {
+ name: "-webkit-logical-width",
+ alias_for: "inline-size",
+ },
+ {
+ name: "-webkit-logical-height",
+ alias_for: "block-size",
+ },
+ {
+ name: "-webkit-min-logical-width",
+ alias_for: "min-inline-size",
+ },
+ {
+ name: "-webkit-min-logical-height",
+ alias_for: "min-block-size",
},
{
name: "-webkit-max-logical-width",
- property_methods: ["ParseSingleValue"],
- direction_aware_options: {
- logical_side: "width",
- shorthand_for_physical_side: "CSSPropertyMax",
- },
+ alias_for: "max-inline-size",
},
{
name: "-webkit-max-logical-height",
- property_methods: ["ParseSingleValue"],
- direction_aware_options: {
- logical_side: "height",
- shorthand_for_physical_side: "CSSPropertyMax",
- },
+ alias_for: "max-block-size",
},
// Properties that we ignore in the StyleBuilder.
@@ -4343,23 +4429,23 @@
{
name: "all",
affected_by_all: false,
- builder_skip: true,
+ style_builder_template: "empty",
},
{
name: "page",
property_methods: ["ParseSingleValue"],
- builder_skip: true,
+ style_builder_template: "empty",
},
{
name: "-webkit-font-size-delta",
property_methods: ["ParseSingleValue"],
- builder_skip: true,
+ style_builder_template: "empty",
},
{
name: "-webkit-text-decorations-in-effect",
property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
inherited: true,
- builder_skip: true,
+ style_builder_template: "empty",
},
// Descriptor only names
@@ -4402,7 +4488,7 @@
name: "viewport-fit",
is_descriptor: true,
is_property: false,
- runtime_flag: "DisplayCutoutViewportFit",
+ runtime_flag: "DisplayCutoutAPI",
},
// Shorthands
@@ -4448,6 +4534,54 @@
property_methods: ["ParseShorthand", "CSSValueFromComputedStyleInternal"],
},
{
+ name: "border-block",
+ longhands: ["border-block-start", "border-block-end"],
+ property_methods: ["ParseShorthand"],
+ runtime_flag: "CSSLogical",
+ },
+ {
+ name: "border-block-color",
+ longhands: ["border-block-start-color", "border-block-end-color"],
+ property_methods: ["ParseShorthand"],
+ runtime_flag: "CSSLogical",
+ },
+ {
+ name: "border-block-end",
+ longhands: [
+ "border-block-end-width", "border-block-end-style",
+ "border-block-end-color"
+ ],
+ property_methods: ["ParseShorthand"],
+ direction_aware_options: {
+ logical_side: "after",
+ shorthand_for_physical_side: "BorderDirections",
+ },
+ },
+ {
+ name: "border-block-start",
+ longhands: [
+ "border-block-start-width", "border-block-start-style",
+ "border-block-start-color"
+ ],
+ property_methods: ["ParseShorthand"],
+ direction_aware_options: {
+ logical_side: "before",
+ shorthand_for_physical_side: "BorderDirections",
+ },
+ },
+ {
+ name: "border-block-style",
+ longhands: ["border-block-start-style", "border-block-end-style"],
+ property_methods: ["ParseShorthand"],
+ runtime_flag: "CSSLogical",
+ },
+ {
+ name: "border-block-width",
+ longhands: ["border-block-start-width", "border-block-end-width"],
+ property_methods: ["ParseShorthand"],
+ runtime_flag: "CSSLogical",
+ },
+ {
name: "border-bottom",
longhands: [
"border-bottom-width", "border-bottom-style", "border-bottom-color"
@@ -4471,6 +4605,54 @@
property_methods: ["ParseShorthand", "CSSValueFromComputedStyleInternal"],
},
{
+ name: "border-inline",
+ longhands: ["border-inline-start", "border-inline-end"],
+ property_methods: ["ParseShorthand"],
+ runtime_flag: "CSSLogical",
+ },
+ {
+ name: "border-inline-color",
+ longhands: ["border-inline-start-color", "border-inline-end-color"],
+ property_methods: ["ParseShorthand"],
+ runtime_flag: "CSSLogical",
+ },
+ {
+ name: "border-inline-end",
+ longhands: [
+ "border-inline-end-width", "border-inline-end-style",
+ "border-inline-end-color"
+ ],
+ property_methods: ["ParseShorthand"],
+ direction_aware_options: {
+ logical_side: "end",
+ shorthand_for_physical_side: "BorderDirections",
+ },
+ },
+ {
+ name: "border-inline-start",
+ longhands: [
+ "border-inline-start-width", "border-inline-start-style",
+ "border-inline-start-color"
+ ],
+ property_methods: ["ParseShorthand"],
+ direction_aware_options: {
+ logical_side: "start",
+ shorthand_for_physical_side: "BorderDirections",
+ },
+ },
+ {
+ name: "border-inline-style",
+ longhands: ["border-inline-start-style", "border-inline-end-style"],
+ property_methods: ["ParseShorthand"],
+ runtime_flag: "CSSLogical",
+ },
+ {
+ name: "border-inline-width",
+ longhands: ["border-inline-start-width", "border-inline-end-width"],
+ property_methods: ["ParseShorthand"],
+ runtime_flag: "CSSLogical",
+ },
+ {
name: "border-left",
longhands: [
"border-left-width", "border-left-style", "border-left-color"
@@ -4620,6 +4802,24 @@
layout_dependent: true,
},
{
+ name: "inset-block",
+ longhands: ["inset-block-start", "inset-block-end"],
+ property_methods: ["ParseShorthand"],
+ runtime_flag: "CSSLogical",
+ },
+ {
+ name: "inset-inline",
+ longhands: ["inset-inline-start", "inset-inline-end"],
+ property_methods: ["ParseShorthand"],
+ runtime_flag: "CSSLogical",
+ },
+ {
+ name: "inset",
+ longhands: ["top", "right", "bottom", "left"],
+ property_methods: ["ParseShorthand"],
+ runtime_flag: "CSSLogical",
+ },
+ {
name: "list-style",
longhands: ["list-style-type", "list-style-position", "list-style-image"],
property_methods: ["ParseShorthand", "CSSValueFromComputedStyleInternal"],
@@ -4631,6 +4831,18 @@
layout_dependent: true,
},
{
+ name: "margin-block",
+ longhands: ["margin-block-start", "margin-block-end"],
+ property_methods: ["ParseShorthand"],
+ runtime_flag: "CSSLogical",
+ },
+ {
+ name: "margin-inline",
+ longhands: ["margin-inline-start", "margin-inline-end"],
+ property_methods: ["ParseShorthand"],
+ runtime_flag: "CSSLogical",
+ },
+ {
name: "marker",
longhands: ["marker-start", "marker-mid", "marker-end"],
property_methods: ["ParseShorthand"],
@@ -4668,6 +4880,18 @@
layout_dependent: true,
},
{
+ name: "padding-block",
+ longhands: ["padding-block-start", "padding-block-end"],
+ property_methods: ["ParseShorthand"],
+ runtime_flag: "CSSLogical",
+ },
+ {
+ name: "padding-inline",
+ longhands: ["padding-inline-start", "padding-inline-end"],
+ property_methods: ["ParseShorthand"],
+ runtime_flag: "CSSLogical",
+ },
+ {
name: "page-break-after",
longhands: ["break-after"],
property_methods: ["ParseShorthand", "CSSValueFromComputedStyleInternal"],
@@ -4736,51 +4960,19 @@
},
{
name: "-webkit-border-after",
- longhands: [
- "-webkit-border-after-width", "-webkit-border-after-style",
- "-webkit-border-after-color"
- ],
- property_methods: ["ParseShorthand"],
- direction_aware_options: {
- logical_side: "after",
- shorthand_for_physical_side: "BorderDirections",
- },
+ alias_for: "border-block-end",
},
{
name: "-webkit-border-before",
- longhands: [
- "-webkit-border-before-width", "-webkit-border-before-style",
- "-webkit-border-before-color"
- ],
- property_methods: ["ParseShorthand"],
- direction_aware_options: {
- logical_side: "before",
- shorthand_for_physical_side: "BorderDirections",
- },
+ alias_for: "border-block-start",
},
{
name: "-webkit-border-end",
- longhands: [
- "-webkit-border-end-width", "-webkit-border-end-style",
- "-webkit-border-end-color"
- ],
- property_methods: ["ParseShorthand"],
- direction_aware_options: {
- logical_side: "end",
- shorthand_for_physical_side: "BorderDirections",
- },
+ alias_for: "border-inline-end",
},
{
name: "-webkit-border-start",
- longhands: [
- "-webkit-border-start-width", "-webkit-border-start-style",
- "-webkit-border-start-color"
- ],
- property_methods: ["ParseShorthand"],
- direction_aware_options: {
- logical_side: "start",
- shorthand_for_physical_side: "BorderDirections",
- },
+ alias_for: "border-inline-start",
},
{
name: "-webkit-column-break-after",
@@ -5138,5 +5330,9 @@
name: "-webkit-user-select",
alias_for: "user-select",
},
+ {
+ name: "word-wrap",
+ alias_for: "overflow-wrap",
+ },
],
}
diff --git a/chromium/third_party/blink/renderer/core/css/CSSValueKeywords.json5 b/chromium/third_party/blink/renderer/core/css/CSSValueKeywords.json5
index 970373af52c..45113bac35b 100644
--- a/chromium/third_party/blink/renderer/core/css/CSSValueKeywords.json5
+++ b/chromium/third_party/blink/renderer/core/css/CSSValueKeywords.json5
@@ -1156,6 +1156,7 @@
"var",
"-internal-variable-value",
+ "env",
// break-before, break-after, break-inside
"avoid-page",
diff --git a/chromium/third_party/blink/renderer/core/css/OWNERS b/chromium/third_party/blink/renderer/core/css/OWNERS
index ebb863967ba..7d528afeb3b 100644
--- a/chromium/third_party/blink/renderer/core/css/OWNERS
+++ b/chromium/third_party/blink/renderer/core/css/OWNERS
@@ -1,8 +1,9 @@
+andruud@chromium.org
ericwilligers@chromium.org
shend@chromium.org
# Also core owners
alancutter@chromium.org
-nainar@chromium.org
+futhark@chromium.org
# COMPONENT: Blink>CSS
diff --git a/chromium/third_party/blink/renderer/core/css/README.md b/chromium/third_party/blink/renderer/core/css/README.md
index 3d264a4e954..c7d5356fc27 100644
--- a/chromium/third_party/blink/renderer/core/css/README.md
+++ b/chromium/third_party/blink/renderer/core/css/README.md
@@ -12,4 +12,4 @@ Overview is [here](style-calculation.md).
## <a name="style-invalidation"></a> Style Invalidation
-Style invalidation docs <https://goo.gl/3ane6s> and <https://goo.gl/z0Z9gn>.
+Overview and further links are [here](style-invalidation.md).
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 5f3bae95de0..a4908281581 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
@@ -57,13 +57,34 @@ const CSSValue* ComputedStyleCSSValueMapping::Get(
return CSSCustomPropertyDeclaration::Create(custom_property_name, data);
}
-std::unique_ptr<HashMap<AtomicString, scoped_refptr<CSSVariableData>>>
-ComputedStyleCSSValueMapping::GetVariables(const ComputedStyle& style) {
- // TODO(timloh): Also return non-inherited variables
- StyleInheritedVariables* variables = style.InheritedVariables();
- if (variables)
- return variables->GetVariables();
- return nullptr;
+HeapHashMap<AtomicString, Member<const CSSValue>>
+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);
+ }
+ }
+
+ return variables;
}
} // namespace blink
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 89ab2caa880..5d3d03bcbd6 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
@@ -10,7 +10,6 @@
namespace blink {
-class CSSVariableData;
class ComputedStyle;
class PropertyRegistry;
@@ -21,8 +20,9 @@ class ComputedStyleCSSValueMapping {
static const CSSValue* Get(const AtomicString custom_property_name,
const ComputedStyle&,
const PropertyRegistry*);
- static std::unique_ptr<HashMap<AtomicString, scoped_refptr<CSSVariableData>>>
- GetVariables(const ComputedStyle&);
+ static HeapHashMap<AtomicString, Member<const CSSValue>> GetVariables(
+ const ComputedStyle& style,
+ const PropertyRegistry*);
};
} // namespace blink
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 73a3dddb54a..dac867d5620 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
@@ -24,7 +24,6 @@
#include "third_party/blink/renderer/core/css/css_computed_style_declaration.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/computed_style_css_value_mapping.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
@@ -37,12 +36,12 @@
#include "third_party/blink/renderer/core/css/zoom_adjusted_pixel_value.h"
#include "third_party/blink/renderer/core/css_property_names.h"
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/pseudo_element.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_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/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -113,7 +112,7 @@ const CSSPropertyID kComputedPropertyArray[] = {
CSSPropertyUnicodeBidi, CSSPropertyVerticalAlign, CSSPropertyVisibility,
CSSPropertyWhiteSpace, CSSPropertyWidows, CSSPropertyWidth,
CSSPropertyWillChange, CSSPropertyWordBreak, CSSPropertyWordSpacing,
- CSSPropertyWordWrap, CSSPropertyZIndex, CSSPropertyZoom,
+ CSSPropertyZIndex, CSSPropertyZoom,
CSSPropertyWebkitAppearance, CSSPropertyBackfaceVisibility,
CSSPropertyWebkitBorderHorizontalSpacing, CSSPropertyWebkitBorderImage,
@@ -233,7 +232,7 @@ void CSSComputedStyleDeclaration::setCSSText(const ExecutionContext*,
const String&,
ExceptionState& exception_state) {
exception_state.ThrowDOMException(
- kNoModificationAllowedError,
+ DOMExceptionCode::kNoModificationAllowedError,
"These styles are computed, and therefore read-only.");
}
@@ -317,12 +316,14 @@ const CSSValue* CSSComputedStyleDeclaration::GetPropertyCSSValue(
StyledNode()->GetDocument().GetPropertyRegistry());
}
-std::unique_ptr<HashMap<AtomicString, scoped_refptr<CSSVariableData>>>
+HeapHashMap<AtomicString, Member<const CSSValue>>
CSSComputedStyleDeclaration::GetVariables() const {
const ComputedStyle* style = ComputeComputedStyle();
if (!style)
- return nullptr;
- return ComputedStyleCSSValueMapping::GetVariables(*style);
+ return {};
+ DCHECK(StyledNode());
+ return ComputedStyleCSSValueMapping::GetVariables(
+ *style, StyledNode()->GetDocument().GetPropertyRegistry());
}
const CSSValue* CSSComputedStyleDeclaration::GetPropertyCSSValue(
@@ -479,7 +480,7 @@ void CSSComputedStyleDeclaration::setProperty(const ExecutionContext*,
const String&,
ExceptionState& exception_state) {
exception_state.ThrowDOMException(
- kNoModificationAllowedError,
+ DOMExceptionCode::kNoModificationAllowedError,
"These styles are computed, and therefore the '" + name +
"' property is read-only.");
}
@@ -488,7 +489,7 @@ String CSSComputedStyleDeclaration::removeProperty(
const String& name,
ExceptionState& exception_state) {
exception_state.ThrowDOMException(
- kNoModificationAllowedError,
+ DOMExceptionCode::kNoModificationAllowedError,
"These styles are computed, and therefore the '" + name +
"' property is read-only.");
return String();
@@ -521,7 +522,7 @@ void CSSComputedStyleDeclaration::SetPropertyInternal(
SecureContextMode,
ExceptionState& exception_state) {
exception_state.ThrowDOMException(
- kNoModificationAllowedError,
+ DOMExceptionCode::kNoModificationAllowedError,
"These styles are computed, and therefore the '" +
CSSUnresolvedProperty::Get(id).GetPropertyNameString() +
"' property is read-only.");
diff --git a/chromium/third_party/blink/renderer/core/css/css_computed_style_declaration.h b/chromium/third_party/blink/renderer/core/css/css_computed_style_declaration.h
index 24c796b0f4e..9e9a46a9611 100644
--- a/chromium/third_party/blink/renderer/core/css/css_computed_style_declaration.h
+++ b/chromium/third_party/blink/renderer/core/css/css_computed_style_declaration.h
@@ -33,7 +33,6 @@
namespace blink {
-class CSSVariableData;
class ExceptionState;
class LayoutObject;
class MutableCSSPropertyValueSet;
@@ -61,8 +60,7 @@ class CORE_EXPORT CSSComputedStyleDeclaration final
const CSSValue* GetPropertyCSSValue(const CSSProperty&) const;
const CSSValue* GetPropertyCSSValue(AtomicString custom_property_name) const;
- std::unique_ptr<HashMap<AtomicString, scoped_refptr<CSSVariableData>>>
- GetVariables() const;
+ HeapHashMap<AtomicString, Member<const CSSValue>> GetVariables() const;
const CSSValue* GetFontSizeCSSValuePreferringKeyword() const;
bool IsMonospaceFont() const;
diff --git a/chromium/third_party/blink/renderer/core/css/css_font_face_source_test.cc b/chromium/third_party/blink/renderer/core/css/css_font_face_source_test.cc
index 4a6da176d42..8f34fcd168d 100644
--- a/chromium/third_party/blink/renderer/core/css/css_font_face_source_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_font_face_source_test.cc
@@ -51,9 +51,9 @@ TEST(CSSFontFaceSourceTest, HashCollision) {
DummyFontFaceSource font_face_source;
// Even if the hash value collide, fontface cache should return different
// value for different fonts.
- EXPECT_EQ(SimulateHashCalculation(2), SimulateHashCalculation(4925));
- EXPECT_NE(font_face_source.GetFontDataForSize(2),
- font_face_source.GetFontDataForSize(4925));
+ EXPECT_EQ(SimulateHashCalculation(527), SimulateHashCalculation(3099));
+ EXPECT_NE(font_face_source.GetFontDataForSize(527),
+ font_face_source.GetFontDataForSize(3099));
}
// Exercises the size font_data_table_ assertions in CSSFontFaceSource.
diff --git a/chromium/third_party/blink/renderer/core/css/css_gradient_value.cc b/chromium/third_party/blink/renderer/core/css/css_gradient_value.cc
index 9c0dd4cecd7..c3c219f7126 100644
--- a/chromium/third_party/blink/renderer/core/css/css_gradient_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_gradient_value.cc
@@ -995,31 +995,19 @@ void CSSLinearGradientValue::TraceAfterDispatch(blink::Visitor* visitor) {
void CSSGradientValue::AppendCSSTextForColorStops(
StringBuilder& result,
bool requires_separator) const {
- const CSSValue* prev_color = nullptr;
-
for (const auto& stop : stops_) {
- bool is_color_repeat = false;
- if (RuntimeEnabledFeatures::MultipleColorStopPositionsEnabled()) {
- is_color_repeat = stop.color_ && stop.offset_ &&
- DataEquivalent(stop.color_.Get(), prev_color);
- }
-
if (requires_separator) {
- if (!is_color_repeat)
- result.Append(", ");
+ result.Append(", ");
} else {
requires_separator = true;
}
- if (stop.color_ && !is_color_repeat)
+ if (stop.color_)
result.Append(stop.color_->CssText());
if (stop.color_ && stop.offset_)
result.Append(' ');
if (stop.offset_)
result.Append(stop.offset_->CssText());
-
- // Reset prevColor if we've emitted a color repeat.
- prev_color = is_color_repeat ? nullptr : stop.color_.Get();
}
}
diff --git a/chromium/third_party/blink/renderer/core/css/css_grouping_rule.cc b/chromium/third_party/blink/renderer/core/css/css_grouping_rule.cc
index 7d8c4528f0f..85913b0c4cd 100644
--- a/chromium/third_party/blink/renderer/core/css/css_grouping_rule.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_grouping_rule.cc
@@ -30,13 +30,12 @@
#include "third_party/blink/renderer/core/css/css_grouping_rule.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/parser/css_parser.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -58,7 +57,7 @@ unsigned CSSGroupingRule::insertRule(const ExecutionContext* execution_context,
if (index > group_rule_->ChildRules().size()) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
"the index " + String::Number(index) +
" must be less than or equal to the length of the rule list.");
return 0;
@@ -71,14 +70,14 @@ unsigned CSSGroupingRule::insertRule(const ExecutionContext* execution_context,
context, style_sheet ? style_sheet->Contents() : nullptr, rule_string);
if (!new_rule) {
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"the rule '" + rule_string + "' is invalid and cannot be parsed.");
return 0;
}
if (new_rule->IsNamespaceRule()) {
exception_state.ThrowDOMException(
- kHierarchyRequestError,
+ DOMExceptionCode::kHierarchyRequestError,
"'@namespace' rules cannot be inserted inside a group rule.");
return 0;
}
@@ -88,7 +87,7 @@ unsigned CSSGroupingRule::insertRule(const ExecutionContext* execution_context,
// rule. They are currently not getting parsed, resulting in a SyntaxError
// to get raised above.
exception_state.ThrowDOMException(
- kHierarchyRequestError,
+ DOMExceptionCode::kHierarchyRequestError,
"'@import' rules cannot be inserted inside a group rule.");
return 0;
}
@@ -107,8 +106,9 @@ void CSSGroupingRule::deleteRule(unsigned index,
if (index >= group_rule_->ChildRules().size()) {
exception_state.ThrowDOMException(
- kIndexSizeError, "the index " + String::Number(index) +
- " is greated than the length of the rule list.");
+ DOMExceptionCode::kIndexSizeError,
+ "the index " + String::Number(index) +
+ " is greated than the length of the rule list.");
return;
}
diff --git a/chromium/third_party/blink/renderer/core/css/css_keyframe_rule.cc b/chromium/third_party/blink/renderer/core/css/css_keyframe_rule.cc
index f05e9d789a1..077ddf6e773 100644
--- a/chromium/third_party/blink/renderer/core/css/css_keyframe_rule.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_keyframe_rule.cc
@@ -25,11 +25,10 @@
#include "third_party/blink/renderer/core/css/css_keyframe_rule.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_keyframes_rule.h"
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
#include "third_party/blink/renderer/core/css/keyframe_style_rule_css_style_declaration.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -47,7 +46,7 @@ void CSSKeyframeRule::setKeyText(const String& key_text,
if (!keyframe_->SetKeyText(key_text))
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"The key '" + key_text + "' is invalid and cannot be parsed");
ToCSSKeyframesRule(parentRule())->StyleChanged();
diff --git a/chromium/third_party/blink/renderer/core/css/css_primitive_value.cc b/chromium/third_party/blink/renderer/core/css/css_primitive_value.cc
index 9f75a4db6f1..f0357072aa5 100644
--- a/chromium/third_party/blink/renderer/core/css/css_primitive_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_primitive_value.cc
@@ -380,7 +380,7 @@ double CSSPrimitiveValue::ConversionToCanonicalUnitsScaleFactor(
factor = kCssPixelsPerPica;
break;
case UnitType::kRadians:
- factor = 180 / piDouble;
+ factor = 180 / kPiDouble;
break;
case UnitType::kGradians:
factor = 0.9;
diff --git a/chromium/third_party/blink/renderer/core/css/css_primitive_value_mappings.h b/chromium/third_party/blink/renderer/core/css/css_primitive_value_mappings.h
index 144da32cf35..cc46ccb8dee 100644
--- a/chromium/third_party/blink/renderer/core/css/css_primitive_value_mappings.h
+++ b/chromium/third_party/blink/renderer/core/css/css_primitive_value_mappings.h
@@ -1982,6 +1982,43 @@ inline Containment CSSIdentifierValue::ConvertTo() const {
return kContainsNone;
}
+template <>
+inline CSSIdentifierValue::CSSIdentifierValue(TextUnderlinePosition position)
+ : CSSValue(kIdentifierClass) {
+ switch (position) {
+ case kTextUnderlinePositionAuto:
+ value_id_ = CSSValueAuto;
+ break;
+ case kTextUnderlinePositionUnder:
+ value_id_ = CSSValueUnder;
+ break;
+ case kTextUnderlinePositionLeft:
+ value_id_ = CSSValueLeft;
+ break;
+ case kTextUnderlinePositionRight:
+ value_id_ = CSSValueRight;
+ break;
+ }
+}
+
+template <>
+inline TextUnderlinePosition CSSIdentifierValue::ConvertTo() const {
+ switch (GetValueID()) {
+ case CSSValueAuto:
+ return kTextUnderlinePositionAuto;
+ case CSSValueUnder:
+ return kTextUnderlinePositionUnder;
+ case CSSValueLeft:
+ return kTextUnderlinePositionLeft;
+ case CSSValueRight:
+ return kTextUnderlinePositionRight;
+ default:
+ break;
+ }
+ NOTREACHED();
+ return kTextUnderlinePositionAuto;
+}
+
} // namespace blink
#endif
diff --git a/chromium/third_party/blink/renderer/core/css/css_property_value_set.cc b/chromium/third_party/blink/renderer/core/css/css_property_value_set.cc
index 5c314af429d..1af565c7dc4 100644
--- a/chromium/third_party/blink/renderer/core/css/css_property_value_set.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_property_value_set.cc
@@ -190,28 +190,34 @@ MutableCSSPropertyValueSet::MutableCSSPropertyValueSet(
static String SerializeShorthand(const CSSPropertyValueSet& property_set,
CSSPropertyID property_id) {
- return StylePropertySerializer(property_set).GetPropertyValue(property_id);
+ StylePropertyShorthand shorthand = shorthandForProperty(property_id);
+ if (!shorthand.length())
+ return String();
+
+ return StylePropertySerializer(property_set).SerializeShorthand(property_id);
}
static String SerializeShorthand(const CSSPropertyValueSet&,
const AtomicString& custom_property_name) {
// Custom properties are never shorthands.
- return "";
+ return String();
}
static String SerializeShorthand(const CSSPropertyValueSet& property_set,
AtRuleDescriptorID atrule_id) {
- return StylePropertySerializer(property_set)
- .GetPropertyValue(AtRuleDescriptorIDAsCSSPropertyID(atrule_id));
- ;
+ // Descriptor shorthands aren't handled yet.
+ return String();
}
template <typename T>
String CSSPropertyValueSet::GetPropertyValue(T property) const {
+ String shorthand_serialization = SerializeShorthand(*this, property);
+ if (!shorthand_serialization.IsNull())
+ return shorthand_serialization;
const CSSValue* value = GetPropertyCSSValue(property);
if (value)
return value->CssText();
- return SerializeShorthand(*this, property);
+ return g_empty_string;
}
template CORE_EXPORT String
CSSPropertyValueSet::GetPropertyValue<CSSPropertyID>(CSSPropertyID) const;
diff --git a/chromium/third_party/blink/renderer/core/css/css_rule.cc b/chromium/third_party/blink/renderer/core/css/css_rule.cc
index 3073ab9d627..f0faba51c9b 100644
--- a/chromium/third_party/blink/renderer/core/css/css_rule.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_rule.cc
@@ -64,18 +64,10 @@ void CSSRule::Trace(blink::Visitor* visitor) {
// pre-oilpan world, where the parent link is mysteriously zeroed under
// some circumstances.
if (parent_is_rule_)
- visitor->Trace(parent_rule_);
+ visitor->TraceWithWrappers(parent_rule_);
else
- visitor->Trace(parent_style_sheet_);
+ visitor->TraceWithWrappers(parent_style_sheet_);
ScriptWrappable::Trace(visitor);
}
-void CSSRule::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- if (parent_is_rule_)
- visitor->TraceWrappersWithManualWriteBarrier(parent_rule_);
- else
- visitor->TraceWrappersWithManualWriteBarrier(parent_style_sheet_);
- ScriptWrappable::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css_rule.h b/chromium/third_party/blink/renderer/core/css/css_rule.h
index 24b7c940bf0..5e733cbffe7 100644
--- a/chromium/third_party/blink/renderer/core/css/css_rule.h
+++ b/chromium/third_party/blink/renderer/core/css/css_rule.h
@@ -67,7 +67,6 @@ class CORE_EXPORT CSSRule : public ScriptWrappable {
void SetParentRule(CSSRule*);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
CSSStyleSheet* parentStyleSheet() const {
if (parent_is_rule_)
diff --git a/chromium/third_party/blink/renderer/core/css/css_selector.cc b/chromium/third_party/blink/renderer/core/css/css_selector.cc
index 5bcbcbd6304..d56a6d222d1 100644
--- a/chromium/third_party/blink/renderer/core/css/css_selector.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_selector.cc
@@ -279,6 +279,7 @@ PseudoId CSSSelector::GetPseudoId(PseudoType type) {
case kPseudoFullScreenAncestor:
case kPseudoFullscreen:
case kPseudoSpatialNavigationFocus:
+ case kPseudoIsHtml:
case kPseudoListBox:
case kPseudoHostHasAppearance:
case kPseudoSlotted:
@@ -301,6 +302,7 @@ struct NameToPseudoStruct {
// These tables should be kept sorted.
const static NameToPseudoStruct kPseudoTypeWithoutArgumentsMap[] = {
+ {"-internal-is-html", CSSSelector::kPseudoIsHtml},
{"-internal-list-box", CSSSelector::kPseudoListBox},
{"-internal-media-controls-overlay-cast-button",
CSSSelector::kPseudoWebKitCustomElement},
@@ -567,6 +569,7 @@ void CSSSelector::UpdatePseudoType(const AtomicString& value,
pseudo_type_ = kPseudoUnknown;
break;
case kPseudoHostHasAppearance:
+ case kPseudoIsHtml:
case kPseudoListBox:
case kPseudoSpatialNavigationFocus:
case kPseudoVideoPersistent:
@@ -859,9 +862,6 @@ String CSSSelector::SelectorText() const {
case kShadowDeepAsDescendant:
result = " /deep/ " + builder.ToString() + result;
break;
- case kShadowPiercingDescendant:
- result = " >>> " + builder.ToString() + result;
- break;
case kDirectAdjacent:
result = " + " + builder.ToString() + result;
break;
@@ -943,6 +943,7 @@ static bool ValidateSubSelector(const CSSSelector* selector) {
case CSSSelector::kPseudoHostContext:
case CSSSelector::kPseudoNot:
case CSSSelector::kPseudoSpatialNavigationFocus:
+ case CSSSelector::kPseudoIsHtml:
case CSSSelector::kPseudoListBox:
case CSSSelector::kPseudoHostHasAppearance:
return true;
@@ -1081,7 +1082,6 @@ bool CSSSelector::HasDeepCombinatorOrShadowPseudo() const {
return ForAnyInTagHistory(
[](const CSSSelector& selector) -> bool {
return selector.Relation() == CSSSelector::kShadowDeep ||
- selector.Relation() == CSSSelector::kShadowPiercingDescendant ||
selector.GetPseudoType() == CSSSelector::kPseudoShadow;
},
*this);
diff --git a/chromium/third_party/blink/renderer/core/css/css_selector.h b/chromium/third_party/blink/renderer/core/css/css_selector.h
index b709e69feac..61b36db28d4 100644
--- a/chromium/third_party/blink/renderer/core/css/css_selector.h
+++ b/chromium/third_party/blink/renderer/core/css/css_selector.h
@@ -25,13 +25,14 @@
#include <memory>
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_mode.h"
#include "third_party/blink/renderer/core/dom/qualified_name.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
namespace blink {
+
+class CSSParserContext;
class CSSSelectorList;
// This class represents a simple selector for a StyleRule.
@@ -132,7 +133,6 @@ class CORE_EXPORT CSSSelector {
kDirectAdjacent, // + combinator
kIndirectAdjacent, // ~ combinator
// Special cases for shadow DOM related selectors.
- kShadowPiercingDescendant, // >>> combinator
kShadowDeep, // /deep/ combinator
kShadowDeepAsDescendant, // /deep/ as an alias for descendant
kShadowPseudo, // ::shadow pseudo element
@@ -236,6 +236,7 @@ class CORE_EXPORT CSSSelector {
kPseudoHostContext,
kPseudoShadow,
kPseudoSpatialNavigationFocus,
+ kPseudoIsHtml,
kPseudoListBox,
kPseudoHostHasAppearance,
kPseudoSlotted,
diff --git a/chromium/third_party/blink/renderer/core/css/css_style_declaration.cc b/chromium/third_party/blink/renderer/core/css/css_style_declaration.cc
index b049f0cbeea..4032f2f8586 100644
--- a/chromium/third_party/blink/renderer/core/css/css_style_declaration.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_style_declaration.cc
@@ -32,8 +32,6 @@
#include <algorithm>
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/bindings/core/v8/string_or_float.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/css_property_id_templates.h"
#include "third_party/blink/renderer/core/css/css_style_declaration.h"
@@ -41,6 +39,8 @@
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/css_property_names.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/wtf/ascii_ctype.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -148,26 +148,15 @@ CSSPropertyID CssPropertyInfo(const AtomicString& name) {
} // namespace
-void CSSStyleDeclaration::AnonymousNamedGetter(const AtomicString& name,
- StringOrFloat& result) {
+String CSSStyleDeclaration::AnonymousNamedGetter(const AtomicString& name) {
// Search the style declaration.
CSSPropertyID unresolved_property = CssPropertyInfo(name);
// Do not handle non-property names.
if (!unresolved_property)
- return;
- CSSPropertyID resolved_property = resolveCSSPropertyID(unresolved_property);
-
- const CSSValue* css_value = GetPropertyCSSValueInternal(resolved_property);
- if (css_value) {
- const String css_text = css_value->CssText();
- if (!css_text.IsNull()) {
- result.SetString(css_text);
- return;
- }
- }
+ return String();
- result.SetString(GetPropertyValueInternal(resolved_property));
+ return GetPropertyValueInternal(resolveCSSPropertyID(unresolved_property));
}
bool CSSStyleDeclaration::AnonymousNamedSetter(ScriptState* script_state,
diff --git a/chromium/third_party/blink/renderer/core/css/css_style_declaration.h b/chromium/third_party/blink/renderer/core/css/css_style_declaration.h
index 5a0249612b1..e2ce951b3fd 100644
--- a/chromium/third_party/blink/renderer/core/css/css_style_declaration.h
+++ b/chromium/third_party/blink/renderer/core/css/css_style_declaration.h
@@ -36,7 +36,6 @@ class CSSRule;
class CSSStyleSheet;
class CSSValue;
class ExceptionState;
-class StringOrFloat;
enum class SecureContextMode;
class CORE_EXPORT CSSStyleDeclaration : public ScriptWrappable {
@@ -91,7 +90,7 @@ class CORE_EXPORT CSSStyleDeclaration : public ScriptWrappable {
virtual bool CssPropertyMatches(CSSPropertyID, const CSSValue&) const = 0;
virtual CSSStyleSheet* ParentStyleSheet() const { return nullptr; }
- void AnonymousNamedGetter(const AtomicString& name, StringOrFloat&);
+ String AnonymousNamedGetter(const AtomicString& name);
// Note: AnonymousNamedSetter() can end up throwing an exception via
// SetPropertyInternal() even though it does not take an |ExceptionState| as
// an argument (see bug 829408).
diff --git a/chromium/third_party/blink/renderer/core/css/css_style_declaration.idl b/chromium/third_party/blink/renderer/core/css/css_style_declaration.idl
index ec574ba3e84..7f5b13d6884 100644
--- a/chromium/third_party/blink/renderer/core/css/css_style_declaration.idl
+++ b/chromium/third_party/blink/renderer/core/css/css_style_declaration.idl
@@ -38,7 +38,7 @@
// The camel-cased and dashed attribute getters have custom bindings.
// https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-camel-cased-attribute
// https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-dashed-attribute
- [Affects=Nothing] getter (DOMString or float) (DOMString name);
+ [Affects=Nothing] getter DOMString (DOMString name);
// TODO(crbug.com/831544): [TreatNullAs=EmptyString] should be used instead
// of [TreatNullAs=NullString].
[CEReactions, CallWith=ScriptState] setter void (DOMString property, [TreatNullAs=NullString] DOMString propertyValue);
diff --git a/chromium/third_party/blink/renderer/core/css/css_style_rule.idl b/chromium/third_party/blink/renderer/core/css/css_style_rule.idl
index 2bfabec8211..44a3755ae52 100644
--- a/chromium/third_party/blink/renderer/core/css/css_style_rule.idl
+++ b/chromium/third_party/blink/renderer/core/css/css_style_rule.idl
@@ -25,5 +25,5 @@
] interface CSSStyleRule : CSSRule {
[SetterCallWith=ExecutionContext] attribute DOMString selectorText;
[SameObject, PutForwards=cssText] readonly attribute CSSStyleDeclaration style;
- [SameObject, RuntimeEnabled=CSSTypedOM, MeasureAs=CSSTypedOMStylePropertyMap] readonly attribute StylePropertyMap styleMap;
+ [SameObject, MeasureAs=CSSTypedOMStylePropertyMap] readonly attribute StylePropertyMap styleMap;
};
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 2dc2393fc0a..7af9a184053 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
@@ -20,7 +20,6 @@
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/media_list_or_string.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/css/css_import_rule.h"
@@ -33,7 +32,6 @@
#include "third_party/blink/renderer/core/css/style_rule.h"
#include "third_party/blink/renderer/core/css/style_sheet_contents.h"
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/core/html/html_link_element.h"
@@ -41,6 +39,7 @@
#include "third_party/blink/renderer/core/html_names.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"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -60,11 +59,6 @@ class StyleSheetCSSRuleList final : public CSSRuleList {
CSSRuleList::Trace(visitor);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- visitor->TraceWrappers(style_sheet_);
- CSSRuleList::TraceWrappers(visitor);
- }
-
private:
StyleSheetCSSRuleList(CSSStyleSheet* sheet) : style_sheet_(sheet) {}
@@ -98,14 +92,11 @@ const Document* CSSStyleSheet::SingleOwnerDocument(
}
CSSStyleSheet* CSSStyleSheet::Create(Document& document,
- const String& text,
ExceptionState& exception_state) {
- return CSSStyleSheet::Create(document, text, CSSStyleSheetInit(),
- exception_state);
+ return CSSStyleSheet::Create(document, CSSStyleSheetInit(), exception_state);
}
CSSStyleSheet* CSSStyleSheet::Create(Document& document,
- const String& text,
const CSSStyleSheetInit& options,
ExceptionState& exception_state) {
if (!RuntimeEnabledFeatures::ConstructableStylesheetsEnabled()) {
@@ -120,19 +111,18 @@ CSSStyleSheet* CSSStyleSheet::Create(Document& document,
sheet->SetTitle(options.title());
sheet->ClearOwnerNode();
sheet->ClearOwnerRule();
- if (options.media().IsString()) {
- MediaList* media_list = MediaList::Create(
- MediaQuerySet::Create(), const_cast<CSSStyleSheet*>(sheet));
- media_list->setMediaText(options.media().GetAsString());
- sheet->SetMedia(media_list);
- } else {
- sheet->SetMedia(options.media().GetAsMediaList());
- }
+ scoped_refptr<MediaQuerySet> media_query_set;
+ if (options.media().IsString())
+ media_query_set = MediaQuerySet::Create(options.media().GetAsString());
+ else
+ media_query_set = options.media().GetAsMediaList()->Queries()->Copy();
+ MediaList* media_list =
+ MediaList::Create(media_query_set, const_cast<CSSStyleSheet*>(sheet));
+ sheet->SetMedia(media_list);
if (options.alternate())
sheet->SetAlternateFromConstructor(true);
if (options.disabled())
sheet->setDisabled(true);
- sheet->SetText(text);
return sheet;
}
@@ -308,7 +298,7 @@ CSSRule* CSSStyleSheet::item(unsigned index) {
child_rule_cssom_wrappers_.Grow(rule_count);
DCHECK_EQ(child_rule_cssom_wrappers_.size(), rule_count);
- Member<CSSRule>& css_rule = child_rule_cssom_wrappers_[index];
+ TraceWrapperMember<CSSRule>& css_rule = child_rule_cssom_wrappers_[index];
if (!css_rule)
css_rule = contents_->RuleAt(index)->CreateCSSOMWrapper(this);
return css_rule.Get();
@@ -366,9 +356,10 @@ unsigned CSSStyleSheet::insertRule(const String& rule_string,
if (index > length()) {
exception_state.ThrowDOMException(
- kIndexSizeError, "The index provided (" + String::Number(index) +
- ") is larger than the maximum index (" +
- String::Number(length()) + ").");
+ DOMExceptionCode::kIndexSizeError,
+ "The index provided (" + String::Number(index) +
+ ") is larger than the maximum index (" + String::Number(length()) +
+ ").");
return 0;
}
const CSSParserContext* context =
@@ -378,18 +369,20 @@ unsigned CSSStyleSheet::insertRule(const String& rule_string,
if (!rule) {
exception_state.ThrowDOMException(
- kSyntaxError, "Failed to parse the rule '" + rule_string + "'.");
+ DOMExceptionCode::kSyntaxError,
+ "Failed to parse the rule '" + rule_string + "'.");
return 0;
}
RuleMutationScope mutation_scope(this);
bool success = contents_->WrapperInsertRule(rule, index);
if (!success) {
if (rule->IsNamespaceRule())
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Failed to insert the rule");
else
- exception_state.ThrowDOMException(kHierarchyRequestError,
- "Failed to insert the rule.");
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kHierarchyRequestError,
+ "Failed to insert the rule.");
return 0;
}
if (!child_rule_cssom_wrappers_.IsEmpty())
@@ -411,16 +404,17 @@ void CSSStyleSheet::deleteRule(unsigned index,
if (index >= length()) {
exception_state.ThrowDOMException(
- kIndexSizeError, "The index provided (" + String::Number(index) +
- ") is larger than the maximum index (" +
- String::Number(length() - 1) + ").");
+ DOMExceptionCode::kIndexSizeError,
+ "The index provided (" + String::Number(index) +
+ ") is larger than the maximum index (" +
+ String::Number(length() - 1) + ").");
return;
}
RuleMutationScope mutation_scope(this);
bool success = contents_->WrapperDeleteRule(index);
if (!success) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Failed to delete rule");
return;
}
@@ -589,13 +583,4 @@ void CSSStyleSheet::Trace(blink::Visitor* visitor) {
StyleSheet::Trace(visitor);
}
-void CSSStyleSheet::TraceWrappers(
- blink::ScriptWrappableVisitor* visitor) const {
- for (auto& rule : child_rule_cssom_wrappers_) {
- visitor->TraceWrappers(rule);
- }
- visitor->TraceWrappers(rule_list_cssom_wrapper_);
- StyleSheet::TraceWrappers(visitor);
-}
-
} // namespace blink
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 a9cb7a694d8..2a3fd74c6f8 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
@@ -53,9 +53,8 @@ class CORE_EXPORT CSSStyleSheet final : public StyleSheet {
public:
static const Document* SingleOwnerDocument(const CSSStyleSheet*);
- static CSSStyleSheet* Create(Document&, const String&, ExceptionState&);
+ static CSSStyleSheet* Create(Document&, ExceptionState&);
static CSSStyleSheet* Create(Document&,
- const String&,
const CSSStyleSheetInit&,
ExceptionState&);
@@ -183,7 +182,6 @@ class CORE_EXPORT CSSStyleSheet final : public StyleSheet {
bool CanBeActivated(const String& current_preferrable_name) const;
void Trace(blink::Visitor*) override;
- void TraceWrappers(blink::ScriptWrappableVisitor*) const override;
private:
CSSStyleSheet(StyleSheetContents*, CSSImportRule* owner_rule);
@@ -201,12 +199,18 @@ class CORE_EXPORT CSSStyleSheet final : public StyleSheet {
void SetLoadCompleted(bool);
+ FRIEND_TEST_ALL_PREFIXES(CSSStyleSheetTest,
+ CSSStyleSheetConstructionWithEmptyCSSStyleSheetInit);
FRIEND_TEST_ALL_PREFIXES(
CSSStyleSheetTest,
- CSSStyleSheetConstructionWithEmptyCSSStyleSheetInitAndText);
+ CSSStyleSheetConstructionWithNonEmptyCSSStyleSheetInit);
FRIEND_TEST_ALL_PREFIXES(
CSSStyleSheetTest,
- CSSStyleSheetConstructionWithoutEmptyCSSStyleSheetInitAndText);
+ CreateCSSStyleSheetWithEmptyCSSStyleSheetInitAndText);
+ FRIEND_TEST_ALL_PREFIXES(
+ CSSStyleSheetTest,
+ CreateCSSStyleSheetWithNonEmptyCSSStyleSheetInitAndText);
+
bool AlternateFromConstructor() const { return alternate_from_constructor_; }
Member<StyleSheetContents> contents_;
diff --git a/chromium/third_party/blink/renderer/core/css/css_style_sheet.idl b/chromium/third_party/blink/renderer/core/css/css_style_sheet.idl
index b76761ac24c..b70b9fe6a46 100644
--- a/chromium/third_party/blink/renderer/core/css/css_style_sheet.idl
+++ b/chromium/third_party/blink/renderer/core/css/css_style_sheet.idl
@@ -23,7 +23,7 @@
[
ConstructorCallWith=Document,
RaisesException=Constructor,
- Constructor(DOMString text, optional CSSStyleSheetInit options),
+ Constructor(optional CSSStyleSheetInit options),
Exposed=Window
] interface CSSStyleSheet : StyleSheet {
readonly attribute CSSRule? ownerRule;
diff --git a/chromium/third_party/blink/renderer/core/css/css_style_sheet_test.cc b/chromium/third_party/blink/renderer/core/css/css_style_sheet_test.cc
index e213a2be55d..d4b1bf77a1a 100644
--- a/chromium/third_party/blink/renderer/core/css/css_style_sheet_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_style_sheet_test.cc
@@ -2,10 +2,15 @@
// 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_style_sheet.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/bindings/core/v8/media_list_or_string.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_css_style_sheet.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_style_sheet_init.h"
#include "third_party/blink/renderer/core/css/media_list.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
@@ -18,22 +23,39 @@ class CSSStyleSheetTest : public PageTestBase {
PageTestBase::SetUp();
RuntimeEnabledFeatures::SetConstructableStylesheetsEnabled(true);
}
+
+ class FunctionForTest : public ScriptFunction {
+ public:
+ static v8::Local<v8::Function> CreateFunction(ScriptState* script_state,
+ ScriptValue* output) {
+ FunctionForTest* self = new FunctionForTest(script_state, output);
+ return self->BindToV8Function();
+ }
+
+ private:
+ FunctionForTest(ScriptState* script_state, ScriptValue* output)
+ : ScriptFunction(script_state), output_(output) {}
+
+ ScriptValue Call(ScriptValue value) override {
+ DCHECK(!value.IsEmpty());
+ *output_ = value;
+ return value;
+ }
+
+ ScriptValue* output_;
+ };
};
TEST_F(CSSStyleSheetTest, ConstructorWithoutRuntimeFlagThrowsException) {
DummyExceptionStateForTesting exception_state;
RuntimeEnabledFeatures::SetConstructableStylesheetsEnabled(false);
- EXPECT_EQ(CSSStyleSheet::Create(GetDocument(), "", CSSStyleSheetInit(),
- exception_state),
- nullptr);
+ EXPECT_EQ(CSSStyleSheet::Create(GetDocument(), exception_state), nullptr);
ASSERT_TRUE(exception_state.HadException());
}
-TEST_F(CSSStyleSheetTest,
- CSSStyleSheetConstructionWithEmptyCSSStyleSheetInitAndText) {
+TEST_F(CSSStyleSheetTest, CSSStyleSheetConstructionWithEmptyCSSStyleSheetInit) {
DummyExceptionStateForTesting exception_state;
- CSSStyleSheet* sheet = CSSStyleSheet::Create(
- GetDocument(), "", CSSStyleSheetInit(), exception_state);
+ CSSStyleSheet* sheet = CSSStyleSheet::Create(GetDocument(), exception_state);
ASSERT_FALSE(exception_state.HadException());
EXPECT_TRUE(sheet->href().IsNull());
EXPECT_EQ(sheet->parentStyleSheet(), nullptr);
@@ -48,8 +70,59 @@ TEST_F(CSSStyleSheetTest,
}
TEST_F(CSSStyleSheetTest,
- CSSStyleSheetConstructionWithoutEmptyCSSStyleSheetInitAndText) {
+ CSSStyleSheetConstructionWithNonEmptyCSSStyleSheetInit) {
+ DummyExceptionStateForTesting exception_state;
+ CSSStyleSheetInit init;
+ init.setMedia(MediaListOrString::FromString("screen, print"));
+ init.setTitle("test");
+ init.setAlternate(true);
+ init.setDisabled(true);
+ CSSStyleSheet* sheet =
+ CSSStyleSheet::Create(GetDocument(), init, exception_state);
+ ASSERT_FALSE(exception_state.HadException());
+ EXPECT_TRUE(sheet->href().IsNull());
+ EXPECT_EQ(sheet->parentStyleSheet(), nullptr);
+ EXPECT_EQ(sheet->ownerNode(), nullptr);
+ EXPECT_EQ(sheet->ownerRule(), nullptr);
+ EXPECT_EQ(sheet->media()->length(), 2U);
+ EXPECT_EQ(sheet->media()->mediaText(), init.media().GetAsString());
+ EXPECT_EQ(sheet->title(), init.title());
+ EXPECT_TRUE(sheet->AlternateFromConstructor());
+ EXPECT_TRUE(sheet->disabled());
+ EXPECT_EQ(sheet->cssRules(exception_state)->length(), 0U);
+ ASSERT_FALSE(exception_state.HadException());
+}
+
+TEST_F(CSSStyleSheetTest,
+ CreateCSSStyleSheetWithEmptyCSSStyleSheetInitAndText) {
+ V8TestingScope scope;
DummyExceptionStateForTesting exception_state;
+ ScriptPromise promise = GetDocument().createCSSStyleSheet(
+ scope.GetScriptState(), "", CSSStyleSheetInit(), exception_state);
+ EXPECT_FALSE(promise.IsEmpty());
+ ASSERT_FALSE(exception_state.HadException());
+ ScriptValue on_fulfilled, on_rejected;
+ promise.Then(
+ FunctionForTest::CreateFunction(scope.GetScriptState(), &on_fulfilled),
+ FunctionForTest::CreateFunction(scope.GetScriptState(), &on_rejected));
+
+ v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
+ CSSStyleSheet* sheet = V8CSSStyleSheet::ToImplWithTypeCheck(
+ scope.GetIsolate(), on_fulfilled.V8Value());
+ EXPECT_TRUE(sheet->href().IsNull());
+ EXPECT_EQ(sheet->parentStyleSheet(), nullptr);
+ EXPECT_EQ(sheet->ownerNode(), nullptr);
+ EXPECT_EQ(sheet->ownerRule(), nullptr);
+ EXPECT_EQ(sheet->media()->length(), 0U);
+ EXPECT_EQ(sheet->title(), StringImpl::empty_);
+ EXPECT_FALSE(sheet->AlternateFromConstructor());
+ EXPECT_FALSE(sheet->disabled());
+ EXPECT_EQ(sheet->cssRules(exception_state)->length(), 0U);
+ ASSERT_FALSE(exception_state.HadException());
+}
+
+TEST_F(CSSStyleSheetTest,
+ CreateCSSStyleSheetWithNonEmptyCSSStyleSheetInitAndText) {
String styleText[2] = {".red { color: red; }",
".red + span + span { color: red; }"};
CSSStyleSheetInit init;
@@ -57,9 +130,22 @@ TEST_F(CSSStyleSheetTest,
init.setTitle("test");
init.setAlternate(true);
init.setDisabled(true);
- CSSStyleSheet* sheet = CSSStyleSheet::Create(
- GetDocument(), styleText[0] + styleText[1], init, exception_state);
+ V8TestingScope scope;
+ DummyExceptionStateForTesting exception_state;
+ ScriptPromise promise = GetDocument().createCSSStyleSheet(
+ scope.GetScriptState(), styleText[0] + styleText[1], init,
+ exception_state);
+ EXPECT_FALSE(promise.IsEmpty());
ASSERT_FALSE(exception_state.HadException());
+ ScriptValue on_fulfilled, on_rejected;
+ promise.Then(
+ FunctionForTest::CreateFunction(scope.GetScriptState(), &on_fulfilled),
+ FunctionForTest::CreateFunction(scope.GetScriptState(), &on_rejected));
+
+ v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
+ CSSStyleSheet* sheet = V8CSSStyleSheet::ToImplWithTypeCheck(
+ scope.GetIsolate(), on_fulfilled.V8Value());
+
EXPECT_TRUE(sheet->href().IsNull());
EXPECT_EQ(sheet->parentStyleSheet(), nullptr);
EXPECT_EQ(sheet->ownerNode(), nullptr);
diff --git a/chromium/third_party/blink/renderer/core/css/css_syntax_descriptor.cc b/chromium/third_party/blink/renderer/core/css/css_syntax_descriptor.cc
index 0ab312f3a2a..ddbbb08ac54 100644
--- a/chromium/third_party/blink/renderer/core/css/css_syntax_descriptor.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_syntax_descriptor.cc
@@ -54,6 +54,8 @@ CSSSyntaxType ParseSyntaxType(String type) {
return CSSSyntaxType::kTime;
if (type == "resolution")
return CSSSyntaxType::kResolution;
+ if (type == "transform-function")
+ return CSSSyntaxType::kTransformFunction;
if (type == "transform-list")
return CSSSyntaxType::kTransformList;
if (type == "custom-ident")
@@ -96,8 +98,8 @@ CSSSyntaxDescriptor::CSSSyntaxDescriptor(const String& input) {
if (ConsumeCharacterAndWhitespace(input, '*', offset)) {
if (offset != input.length())
return;
- syntax_components_.push_back(
- CSSSyntaxComponent(CSSSyntaxType::kTokenStream, g_empty_string, false));
+ syntax_components_.push_back(CSSSyntaxComponent(
+ CSSSyntaxType::kTokenStream, g_empty_string, CSSSyntaxRepeat::kNone));
return;
}
@@ -118,15 +120,23 @@ CSSSyntaxDescriptor::CSSSyntaxDescriptor(const String& input) {
return;
}
- bool repeatable = ConsumeCharacterAndWhitespace(input, '+', offset);
+ CSSSyntaxRepeat repeat = CSSSyntaxRepeat::kNone;
+
+ if (ConsumeCharacterAndWhitespace(input, '+', offset))
+ repeat = CSSSyntaxRepeat::kSpaceSeparated;
+ else if (ConsumeCharacterAndWhitespace(input, '#', offset))
+ repeat = CSSSyntaxRepeat::kCommaSeparated;
+
// <transform-list> is already a space separated list,
// <transform-list>+ is invalid.
- if (type == CSSSyntaxType::kTransformList && repeatable) {
+ // TODO(andruud): Is <transform-list># invalid?
+ if (type == CSSSyntaxType::kTransformList &&
+ repeat != CSSSyntaxRepeat::kNone) {
syntax_components_.clear();
return;
}
ConsumeWhitespace(input, offset);
- syntax_components_.push_back(CSSSyntaxComponent(type, ident, repeatable));
+ syntax_components_.push_back(CSSSyntaxComponent(type, ident, repeat));
} while (ConsumeCharacterAndWhitespace(input, '|', offset));
@@ -171,6 +181,8 @@ const CSSValue* ConsumeSingleType(const CSSSyntaxComponent& syntax,
return ConsumeTime(range, ValueRange::kValueRangeAll);
case CSSSyntaxType::kResolution:
return ConsumeResolution(range);
+ case CSSSyntaxType::kTransformFunction:
+ return ConsumeTransformValue(range, *context);
case CSSSyntaxType::kTransformList:
return ConsumeTransformList(range, *context);
case CSSSyntaxType::kCustomIdent:
@@ -185,7 +197,7 @@ const CSSValue* ConsumeSyntaxComponent(const CSSSyntaxComponent& syntax,
CSSParserTokenRange range,
const CSSParserContext* context) {
// CSS-wide keywords are already handled by the CSSPropertyParser
- if (syntax.repeatable_) {
+ if (syntax.repeat_ == CSSSyntaxRepeat::kSpaceSeparated) {
CSSValueList* list = CSSValueList::CreateSpaceSeparated();
while (!range.AtEnd()) {
const CSSValue* value = ConsumeSingleType(syntax, range, context);
@@ -195,6 +207,16 @@ const CSSValue* ConsumeSyntaxComponent(const CSSSyntaxComponent& syntax,
}
return list;
}
+ if (syntax.repeat_ == CSSSyntaxRepeat::kCommaSeparated) {
+ CSSValueList* list = CSSValueList::CreateCommaSeparated();
+ do {
+ const CSSValue* value = ConsumeSingleType(syntax, range, context);
+ if (!value)
+ return nullptr;
+ list->Append(*value);
+ } while (CSSPropertyParserHelpers::ConsumeCommaIncludingWhitespace(range));
+ return list;
+ }
const CSSValue* result = ConsumeSingleType(syntax, range, context);
if (!range.AtEnd())
return nullptr;
diff --git a/chromium/third_party/blink/renderer/core/css/css_syntax_descriptor.h b/chromium/third_party/blink/renderer/core/css/css_syntax_descriptor.h
index 1049822332a..4e5c42491ce 100644
--- a/chromium/third_party/blink/renderer/core/css/css_syntax_descriptor.h
+++ b/chromium/third_party/blink/renderer/core/css/css_syntax_descriptor.h
@@ -26,22 +26,28 @@ enum class CSSSyntaxType {
kAngle,
kTime,
kResolution,
+ kTransformFunction,
kTransformList,
kCustomIdent,
};
+enum class CSSSyntaxRepeat { kNone, kSpaceSeparated, kCommaSeparated };
+
struct CSSSyntaxComponent {
- CSSSyntaxComponent(CSSSyntaxType type, const String& string, bool repeatable)
- : type_(type), string_(string), repeatable_(repeatable) {}
+ CSSSyntaxComponent(CSSSyntaxType type,
+ const String& string,
+ CSSSyntaxRepeat repeat)
+ : type_(type), string_(string), repeat_(repeat) {}
bool operator==(const CSSSyntaxComponent& a) const {
- return type_ == a.type_ && string_ == a.string_ &&
- repeatable_ == a.repeatable_;
+ return type_ == a.type_ && string_ == a.string_ && repeat_ == a.repeat_;
}
+ bool IsRepeatable() const { return repeat_ != CSSSyntaxRepeat::kNone; }
+
CSSSyntaxType type_;
String string_; // Only used when type_ is CSSSyntaxType::kIdent
- bool repeatable_;
+ CSSSyntaxRepeat repeat_;
};
class CORE_EXPORT CSSSyntaxDescriptor {
@@ -56,6 +62,13 @@ class CORE_EXPORT CSSSyntaxDescriptor {
return syntax_components_.size() == 1 &&
syntax_components_[0].type_ == CSSSyntaxType::kTokenStream;
}
+ bool HasUrlSyntax() const {
+ for (const CSSSyntaxComponent& component : syntax_components_) {
+ if (component.type_ == CSSSyntaxType::kUrl)
+ return true;
+ }
+ return false;
+ }
const Vector<CSSSyntaxComponent>& Components() const {
return syntax_components_;
}
diff --git a/chromium/third_party/blink/renderer/core/css/css_test_helper.cc b/chromium/third_party/blink/renderer/core/css/css_test_helper.cc
index 3962c9e89d3..7a5acf84252 100644
--- a/chromium/third_party/blink/renderer/core/css/css_test_helper.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_test_helper.cc
@@ -30,12 +30,12 @@
#include "third_party/blink/renderer/core/css/css_test_helper.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/rule_set.h"
#include "third_party/blink/renderer/core/css/style_sheet_contents.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/css/css_timing.cc b/chromium/third_party/blink/renderer/core/css/css_timing.cc
deleted file mode 100644
index 8c00e451b1d..00000000000
--- a/chromium/third_party/blink/renderer/core/css/css_timing.cc
+++ /dev/null
@@ -1,42 +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/css/css_timing.h"
-
-#include "third_party/blink/renderer/core/paint/paint_timing.h"
-
-namespace blink {
-
-// static
-const char CSSTiming::kSupplementName[] = "CSSTiming";
-
-CSSTiming& CSSTiming::From(Document& document) {
- CSSTiming* timing = Supplement<Document>::From<CSSTiming>(document);
- if (!timing) {
- timing = new CSSTiming(document);
- ProvideTo(document, timing);
- }
- return *timing;
-}
-
-void CSSTiming::RecordAuthorStyleSheetParseTime(double seconds) {
- if (paint_timing_->FirstContentfulPaint().is_null())
- parse_time_before_fcp_ += seconds;
-}
-
-void CSSTiming::RecordUpdateDuration(double seconds) {
- if (paint_timing_->FirstContentfulPaint().is_null())
- update_time_before_fcp_ += seconds;
-}
-
-void CSSTiming::Trace(blink::Visitor* visitor) {
- visitor->Trace(paint_timing_);
- Supplement<Document>::Trace(visitor);
-}
-
-CSSTiming::CSSTiming(Document& document)
- : Supplement<Document>(document),
- paint_timing_(PaintTiming::From(document)) {}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/css_timing.h b/chromium/third_party/blink/renderer/core/css/css_timing.h
deleted file mode 100644
index 2bdbd6a57ca..00000000000
--- a/chromium/third_party/blink/renderer/core/css/css_timing.h
+++ /dev/null
@@ -1,51 +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_CSS_CSS_TIMING_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_TIMING_H_
-
-#include "base/macros.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/supplementable.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
-
-namespace blink {
-
-class PaintTiming;
-
-class CSSTiming : public GarbageCollectedFinalized<CSSTiming>,
- public Supplement<Document> {
- USING_GARBAGE_COLLECTED_MIXIN(CSSTiming);
-
- public:
- static const char kSupplementName[];
-
- virtual ~CSSTiming() = default;
-
- void RecordAuthorStyleSheetParseTime(double seconds);
- void RecordUpdateDuration(double seconds);
-
- double AuthorStyleSheetParseDurationBeforeFCP() const {
- return parse_time_before_fcp_;
- }
-
- double UpdateDurationBeforeFCP() const { return update_time_before_fcp_; }
-
- static CSSTiming& From(Document&);
- void Trace(blink::Visitor*) override;
-
- private:
- explicit CSSTiming(Document&);
-
- double parse_time_before_fcp_ = 0;
- double update_time_before_fcp_ = 0;
-
- Member<PaintTiming> paint_timing_;
- DISALLOW_COPY_AND_ASSIGN(CSSTiming);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_TIMING_H_
diff --git a/chromium/third_party/blink/renderer/core/css/css_value_list.h b/chromium/third_party/blink/renderer/core/css/css_value_list.h
index 0dbc40ad7fe..d1c0b3d8aff 100644
--- a/chromium/third_party/blink/renderer/core/css/css_value_list.h
+++ b/chromium/third_party/blink/renderer/core/css/css_value_list.h
@@ -44,6 +44,10 @@ class CORE_EXPORT CSSValueList : public CSSValue {
static CSSValueList* CreateSlashSeparated() {
return new CSSValueList(kSlashSeparator);
}
+ static CSSValueList* CreateWithSeparatorFrom(const CSSValueList& list) {
+ return new CSSValueList(
+ static_cast<ValueListSeparator>(list.value_list_separator_));
+ }
iterator begin() { return values_.begin(); }
iterator end() { return values_.end(); }
diff --git a/chromium/third_party/blink/renderer/core/css/css_variable_data.cc b/chromium/third_party/blink/renderer/core/css/css_variable_data.cc
index 5fef3698efd..1c334cd6580 100644
--- a/chromium/third_party/blink/renderer/core/css/css_variable_data.cc
+++ b/chromium/third_party/blink/renderer/core/css/css_variable_data.cc
@@ -31,6 +31,24 @@ static void UpdateTokens(const CSSParserTokenRange& range,
backing_string.length());
}
+static bool IsFontUnitToken(CSSParserToken token) {
+ if (token.GetType() != kDimensionToken)
+ return false;
+ switch (token.GetUnitType()) {
+ case CSSPrimitiveValue::UnitType::kEms:
+ case CSSPrimitiveValue::UnitType::kChs:
+ case CSSPrimitiveValue::UnitType::kExs:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool IsRootFontUnitToken(CSSParserToken token) {
+ return token.GetType() == kDimensionToken &&
+ token.GetUnitType() == CSSPrimitiveValue::UnitType::kRems;
+}
+
bool CSSVariableData::operator==(const CSSVariableData& other) const {
return Tokens() == other.Tokens();
}
@@ -45,6 +63,10 @@ void CSSVariableData::ConsumeAndUpdateTokens(const CSSParserTokenRange& range) {
CSSParserToken token = local_range.Consume();
if (token.HasStringBacking())
string_builder.Append(token.Value());
+ needs_url_resolution_ |=
+ (token.GetType() == kUrlToken || token.FunctionId() == CSSValueUrl);
+ has_font_units_ |= IsFontUnitToken(token);
+ has_root_font_units_ |= IsRootFontUnitToken(token);
}
String backing_string = string_builder.ToString();
backing_strings_.push_back(backing_string);
@@ -56,9 +78,16 @@ void CSSVariableData::ConsumeAndUpdateTokens(const CSSParserTokenRange& range) {
CSSVariableData::CSSVariableData(const CSSParserTokenRange& range,
bool is_animation_tainted,
- bool needs_variable_resolution)
+ bool needs_variable_resolution,
+ const KURL& base_url,
+ const WTF::TextEncoding& charset)
: is_animation_tainted_(is_animation_tainted),
- needs_variable_resolution_(needs_variable_resolution) {
+ needs_variable_resolution_(needs_variable_resolution),
+ needs_url_resolution_(needs_variable_resolution_),
+ has_font_units_(false),
+ has_root_font_units_(false),
+ base_url_(base_url),
+ charset_(charset) {
DCHECK(!range.AtEnd());
ConsumeAndUpdateTokens(range);
}
diff --git a/chromium/third_party/blink/renderer/core/css/css_variable_data.h b/chromium/third_party/blink/renderer/core/css/css_variable_data.h
index 2246ef09a70..e8e4f18bdef 100644
--- a/chromium/third_party/blink/renderer/core/css/css_variable_data.h
+++ b/chromium/third_party/blink/renderer/core/css/css_variable_data.h
@@ -8,7 +8,9 @@
#include "base/macros.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/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -24,19 +26,26 @@ class CORE_EXPORT CSSVariableData : public RefCounted<CSSVariableData> {
static scoped_refptr<CSSVariableData> Create() {
return base::AdoptRef(new CSSVariableData());
}
- static scoped_refptr<CSSVariableData> Create(const CSSParserTokenRange& range,
- bool is_animation_tainted,
- bool needs_variable_resolution) {
+ static scoped_refptr<CSSVariableData> Create(
+ const CSSParserTokenRange& range,
+ bool is_animation_tainted,
+ bool needs_variable_resolution,
+ const KURL& base_url,
+ const WTF::TextEncoding& charset) {
return base::AdoptRef(new CSSVariableData(range, is_animation_tainted,
- needs_variable_resolution));
+ needs_variable_resolution,
+ base_url, charset));
}
static scoped_refptr<CSSVariableData> CreateResolved(
const Vector<CSSParserToken>& resolved_tokens,
Vector<String> backing_strings,
- bool is_animation_tainted) {
+ bool is_animation_tainted,
+ bool has_font_units,
+ bool has_root_font_units) {
return base::AdoptRef(new CSSVariableData(
- resolved_tokens, std::move(backing_strings), is_animation_tainted));
+ resolved_tokens, std::move(backing_strings), is_animation_tainted,
+ has_font_units, has_root_font_units));
}
CSSParserTokenRange TokenRange() const { return tokens_; }
@@ -50,24 +59,49 @@ class CORE_EXPORT CSSVariableData : public RefCounted<CSSVariableData> {
bool NeedsVariableResolution() const { return needs_variable_resolution_; }
+ bool NeedsUrlResolution() const { return needs_url_resolution_; }
+
+ // True if the CSSVariableData has tokens with units that are relative to the
+ // font-size of the current element, e.g. 'em'.
+ bool HasFontUnits() const { return has_font_units_; }
+
+ // True if the CSSVariableData has tokens with units that are relative to the
+ // font-size of the root element, e.g. 'rem'.
+ bool HasRootFontUnits() const { return has_root_font_units_; }
+
+ const KURL& BaseURL() const { return base_url_; }
+
+ const WTF::TextEncoding& Charset() const { return charset_; }
+
const CSSValue* ParseForSyntax(const CSSSyntaxDescriptor&,
SecureContextMode) const;
private:
CSSVariableData()
- : is_animation_tainted_(false), needs_variable_resolution_(false){};
+ : is_animation_tainted_(false),
+ needs_variable_resolution_(false),
+ needs_url_resolution_(false),
+ has_font_units_(false),
+ has_root_font_units_(false){};
CSSVariableData(const CSSParserTokenRange&,
bool is_animation_tainted,
- bool needs_variable_resolution);
+ bool needs_variable_resolution,
+ const KURL& base_url,
+ const WTF::TextEncoding& charset);
CSSVariableData(const Vector<CSSParserToken>& resolved_tokens,
Vector<String> backing_strings,
- bool is_animation_tainted)
+ bool is_animation_tainted,
+ bool has_font_units,
+ bool has_root_font_units)
: backing_strings_(std::move(backing_strings)),
tokens_(resolved_tokens),
is_animation_tainted_(is_animation_tainted),
- needs_variable_resolution_(false) {}
+ needs_variable_resolution_(false),
+ needs_url_resolution_(false),
+ has_font_units_(false),
+ has_root_font_units_(false) {}
void ConsumeAndUpdateTokens(const CSSParserTokenRange&);
@@ -78,6 +112,11 @@ class CORE_EXPORT CSSVariableData : public RefCounted<CSSVariableData> {
Vector<CSSParserToken> tokens_;
const bool is_animation_tainted_;
const bool needs_variable_resolution_;
+ bool needs_url_resolution_;
+ bool has_font_units_;
+ bool has_root_font_units_;
+ KURL base_url_;
+ WTF::TextEncoding charset_;
DISALLOW_COPY_AND_ASSIGN(CSSVariableData);
};
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 b92cf86d07b..16d58911f2d 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
@@ -167,9 +167,11 @@ unsigned int ComputedStylePropertyMap::size() {
if (!style)
return 0;
- const auto& variables = ComputedStyleCSSValueMapping::GetVariables(*style);
+ DCHECK(StyledNode());
return CSSComputedStyleDeclaration::ComputableProperties().size() +
- (variables ? variables->size() : 0);
+ ComputedStyleCSSValueMapping::GetVariables(
+ *style, StyledNode()->GetDocument().GetPropertyRegistry())
+ .size();
}
bool ComputedStylePropertyMap::ComparePropertyNames(const String& a,
@@ -264,15 +266,12 @@ void ComputedStylePropertyMap::ForEachProperty(
values.emplace_back(property->GetPropertyNameAtomicString(), value);
}
- const auto& variables = ComputedStyleCSSValueMapping::GetVariables(*style);
- if (variables) {
- for (const auto& name_value : *variables) {
- if (name_value.value) {
- values.emplace_back(name_value.key,
- CSSCustomPropertyDeclaration::Create(
- name_value.key, name_value.value));
- }
- }
+ PropertyRegistry* registry =
+ StyledNode()->GetDocument().GetPropertyRegistry();
+
+ for (const auto& name_value :
+ ComputedStyleCSSValueMapping::GetVariables(*style, registry)) {
+ values.emplace_back(name_value.key, name_value.value);
}
std::sort(values.begin(), values.end(), [](const auto& a, const auto& b) {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_image_value.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_image_value.idl
index 683bc070e76..272f96b1e98 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_image_value.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_image_value.idl
@@ -6,7 +6,6 @@
// image types.
// https://drafts.css-houdini.org/css-typed-om/#imagevalue-objects
[
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet),
ImplementedAs=CSSStyleImageValue
] interface CSSImageValue : CSSStyleValue {
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 f298aff0324..b23b9d6e813 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
@@ -4,13 +4,13 @@
#include "third_party/blink/renderer/core/css/cssom/css_keyword_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_custom_ident_value.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/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"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_keyword_value.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_keyword_value.idl
index 22c70605022..31f6b51730d 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_keyword_value.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_keyword_value.idl
@@ -7,7 +7,6 @@
// https://drafts.css-houdini.org/css-typed-om/#keywordvalue-objects
[
Constructor(CSSOMString keyword),
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet),
RaisesException=Constructor
] interface CSSKeywordValue : CSSStyleValue {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_math_invert.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_math_invert.cc
index cf4b1612b5e..b3ef32adfc6 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_math_invert.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_math_invert.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/css/cssom/css_math_invert.h"
#include "third_party/blink/renderer/core/css/cssom/css_numeric_sum_value.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_math_invert.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_math_invert.idl
index b580f529f51..c165677b6c5 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_math_invert.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_math_invert.idl
@@ -6,7 +6,6 @@
// https://drafts.css-houdini.org/css-typed-om/#cssmathinvert
[
Constructor(CSSNumberish arg),
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet)
] interface CSSMathInvert : CSSMathValue {
readonly attribute CSSNumberish value;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_math_max.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_math_max.cc
index ea119e46b2c..afad8017ee3 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_math_max.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_math_max.cc
@@ -5,13 +5,15 @@
#include "third_party/blink/renderer/core/css/cssom/css_math_max.h"
#include "third_party/blink/renderer/core/css/cssom/css_numeric_sum_value.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
CSSMathMax* CSSMathMax::Create(const HeapVector<CSSNumberish>& args,
ExceptionState& exception_state) {
if (args.IsEmpty()) {
- exception_state.ThrowDOMException(kSyntaxError, "Arguments can't be empty");
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
+ "Arguments can't be empty");
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_math_max.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_math_max.idl
index 590b3b7eada..4a29b526ffd 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_math_max.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_math_max.idl
@@ -6,7 +6,6 @@
// https://drafts.css-houdini.org/css-typed-om/#cssmathsum
[
Constructor(CSSNumberish... args),
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet),
RaisesException=Constructor
] interface CSSMathMax : CSSMathValue {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_math_min.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_math_min.cc
index ecf7293b86a..49afba461d3 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_math_min.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_math_min.cc
@@ -5,13 +5,15 @@
#include "third_party/blink/renderer/core/css/cssom/css_math_min.h"
#include "third_party/blink/renderer/core/css/cssom/css_numeric_sum_value.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
CSSMathMin* CSSMathMin::Create(const HeapVector<CSSNumberish>& args,
ExceptionState& exception_state) {
if (args.IsEmpty()) {
- exception_state.ThrowDOMException(kSyntaxError, "Arguments can't be empty");
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
+ "Arguments can't be empty");
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_math_min.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_math_min.idl
index a028f4ac449..fd8fbb1d2f8 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_math_min.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_math_min.idl
@@ -6,7 +6,6 @@
// https://drafts.css-houdini.org/css-typed-om/#cssmathsum
[
Constructor(CSSNumberish... args),
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet),
RaisesException=Constructor
] interface CSSMathMin : CSSMathValue {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_math_negate.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_math_negate.cc
index 1cc2296ac1b..a7e04624aac 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_math_negate.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_math_negate.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/css/cssom/css_math_negate.h"
#include "third_party/blink/renderer/core/css/cssom/css_numeric_sum_value.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_math_negate.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_math_negate.idl
index faf4b4194ba..69095537e37 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_math_negate.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_math_negate.idl
@@ -6,7 +6,6 @@
// https://drafts.css-houdini.org/css-typed-om/#cssmathnegate
[
Constructor(CSSNumberish arg),
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet)
] interface CSSMathNegate : CSSMathValue {
readonly attribute CSSNumberish value;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_math_product.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_math_product.cc
index 37b20a9001c..80a528e8b0b 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_math_product.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_math_product.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/core/css/css_calculation_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_math_invert.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -33,7 +34,8 @@ CSSNumericSumValue::UnitMap MultiplyUnitMaps(
CSSMathProduct* CSSMathProduct::Create(const HeapVector<CSSNumberish>& args,
ExceptionState& exception_state) {
if (args.IsEmpty()) {
- exception_state.ThrowDOMException(kSyntaxError, "Arguments can't be empty");
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
+ "Arguments can't be empty");
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_math_product.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_math_product.idl
index 19680ca468e..f4c4471331d 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_math_product.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_math_product.idl
@@ -6,7 +6,6 @@
// https://drafts.css-houdini.org/css-typed-om/#cssmathsub
[
Constructor(CSSNumberish... args),
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet),
RaisesException=Constructor
] interface CSSMathProduct : CSSMathValue {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_math_sum.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_math_sum.cc
index d7116e51ff7..615a96f6bc9 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_math_sum.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_math_sum.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/core/css/css_calculation_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_math_negate.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -51,7 +52,8 @@ bool operator==(const CSSNumericSumValue::Term& a, const UnitMapComparator& b) {
CSSMathSum* CSSMathSum::Create(const HeapVector<CSSNumberish>& args,
ExceptionState& exception_state) {
if (args.IsEmpty()) {
- exception_state.ThrowDOMException(kSyntaxError, "Arguments can't be empty");
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
+ "Arguments can't be empty");
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_math_sum.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_math_sum.idl
index 5b8e0372379..72b8cb82e9f 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_math_sum.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_math_sum.idl
@@ -6,7 +6,6 @@
// https://drafts.css-houdini.org/css-typed-om/#cssmathsum
[
Constructor(CSSNumberish... args),
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet),
RaisesException=Constructor
] interface CSSMathSum : CSSMathValue {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_math_value.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_math_value.idl
index 18eb71ee19e..f4d6a81f638 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_math_value.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_math_value.idl
@@ -14,7 +14,6 @@ enum CSSMathOperator {
};
[
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet)
] interface CSSMathValue : CSSNumericValue {
[ImplementedAs=getOperator] readonly attribute CSSMathOperator operator;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_matrix_component.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_matrix_component.idl
index 5db9a74e3ff..530e42f1402 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_matrix_component.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_matrix_component.idl
@@ -8,7 +8,6 @@
[
Constructor(DOMMatrixReadOnly matrix,
optional CSSMatrixComponentOptions options),
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet)
] interface CSSMatrixComponent : CSSTransformComponent {
attribute DOMMatrix matrix;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_array.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_array.idl
index c5dc75dfee9..402d98c6720 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_array.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_array.idl
@@ -5,7 +5,6 @@
// Represents the sum of one or more CSSNumericValues.
// https://drafts.css-houdini.org/css-typed-om/#cssmathsum
[
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet),
RaisesException=Constructor
] interface CSSNumericArray {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_type.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_type.idl
index 5584af49721..e539ea80e9a 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_type.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_type.idl
@@ -3,7 +3,6 @@
// found in the LICENSE file.
[
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet)
] enum CSSNumericBaseType {
"length",
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value.cc
index b2f12340763..ca43018cd54 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value.cc
@@ -4,7 +4,8 @@
#include "third_party/blink/renderer/core/css/cssom/css_numeric_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include <numeric>
+
#include "third_party/blink/renderer/core/css/css_calculation_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_math_invert.h"
@@ -16,8 +17,7 @@
#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token_stream.h"
#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
-
-#include <numeric>
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -128,16 +128,16 @@ CSSNumericValue* CalcToNumericValue(const CSSCalcExpressionNode& root) {
CSSNumericValueVector values;
// For cases like calc(1 + 2 + 3), the calc expression tree looks like:
- // +
- // / \
- // + 3
- // / \
- // 1 2
+ // + //
+ // / \ //
+ // + 3 //
+ // / \ //
+ // 1 2 //
//
// But we want to produce a CSSMathValue tree that looks like:
- // +
- // /|\
- // 1 2 3
+ // + //
+ // /|\ //
+ // 1 2 3 //
//
// So when the left child has the same operator as its parent, we can combine
// the two nodes. We keep moving down the left side of the tree as long as the
@@ -209,7 +209,8 @@ CSSNumericValue* CSSNumericValue::parse(const String& css_text,
auto range = stream.ConsumeUntilPeekedTypeIs<>();
stream.ConsumeWhitespace();
if (!stream.AtEnd()) {
- exception_state.ThrowDOMException(kSyntaxError, "Invalid math expression");
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
+ "Invalid math expression");
return nullptr;
}
@@ -237,7 +238,8 @@ CSSNumericValue* CSSNumericValue::parse(const String& css_text,
break;
}
- exception_state.ThrowDOMException(kSyntaxError, "Invalid math expression");
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
+ "Invalid math expression");
return nullptr;
}
@@ -260,7 +262,7 @@ CSSUnitValue* CSSNumericValue::to(const String& unit_string,
ExceptionState& exception_state) {
CSSPrimitiveValue::UnitType target_unit = UnitFromName(unit_string);
if (!IsValidUnit(target_unit)) {
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"Invalid unit for conversion");
return nullptr;
}
@@ -289,7 +291,7 @@ CSSMathSum* CSSNumericValue::toSum(const Vector<String>& unit_strings,
ExceptionState& exception_state) {
for (const auto& unit_string : unit_strings) {
if (!IsValidUnit(UnitFromName(unit_string))) {
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"Invalid unit for conversion");
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value.idl
index eb633b6d1a3..ae86a128983 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_numeric_value.idl
@@ -7,7 +7,6 @@
typedef (double or CSSNumericValue) CSSNumberish;
[
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet)
] interface CSSNumericValue : CSSStyleValue {
[RaisesException, NewObject] CSSNumericValue add(CSSNumberish... values);
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_perspective.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_perspective.cc
index e283ab2eb2f..e6969ce5359 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_perspective.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_perspective.cc
@@ -4,10 +4,10 @@
#include "third_party/blink/renderer/core/css/cssom/css_perspective.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_calculation_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
#include "third_party/blink/renderer/core/geometry/dom_matrix.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_perspective.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_perspective.idl
index 2fbea491324..9cba1d1f123 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_perspective.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_perspective.idl
@@ -7,7 +7,6 @@
// Spec: https://drafts.css-houdini.org/css-typed-om/#cssperspective
[
Constructor(CSSNumericValue length),
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet),
RaisesException=Constructor
] interface CSSPerspective : CSSTransformComponent {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_position_value.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_position_value.cc
index 31fc48c34f8..81c2b3cc8ca 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_position_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_position_value.cc
@@ -4,12 +4,12 @@
#include "third_party/blink/renderer/core/css/cssom/css_position_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_value_pair.h"
#include "third_party/blink/renderer/core/css/cssom/css_math_sum.h"
#include "third_party/blink/renderer/core/css/cssom/css_numeric_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_position_value.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_position_value.idl
index 0edf3262f86..3954abba2d5 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_position_value.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_position_value.idl
@@ -7,7 +7,6 @@
// Spec: https://drafts.css-houdini.org/css-typed-om/#positionvalue-objects
[
Constructor(CSSNumericValue x, CSSNumericValue y),
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet),
RaisesException=Constructor
] interface CSSPositionValue : CSSStyleValue {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_rotate.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_rotate.cc
index 8f912beb2e0..51bd5f8503d 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_rotate.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_rotate.cc
@@ -4,11 +4,11 @@
#include "third_party/blink/renderer/core/css/cssom/css_rotate.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_function_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
#include "third_party/blink/renderer/core/geometry/dom_matrix.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_rotate.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_rotate.idl
index f2fe3a950e8..1b19a86e0e0 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_rotate.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_rotate.idl
@@ -8,7 +8,6 @@
[
Constructor(CSSNumericValue angleValue),
Constructor(CSSNumberish x, CSSNumberish y, CSSNumberish z, CSSNumericValue angle),
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet),
RaisesException=Constructor
] interface CSSRotate : CSSTransformComponent {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_scale.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_scale.idl
index cd5d3c2a3f1..2644e70bb61 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_scale.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_scale.idl
@@ -7,7 +7,6 @@
// Spec: https://drafts.css-houdini.org/css-typed-om/#cssscale
[
Constructor(CSSNumberish x, CSSNumberish y, optional CSSNumberish z),
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet),
RaisesException=Constructor
] interface CSSScale : CSSTransformComponent {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_skew.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_skew.cc
index 7f02a422354..9bf1634eff4 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_skew.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_skew.cc
@@ -4,13 +4,13 @@
#include "third_party/blink/renderer/core/css/cssom/css_skew.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_function_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_numeric_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_style_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
#include "third_party/blink/renderer/core/geometry/dom_matrix.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_skew.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_skew.idl
index d600a548721..8aed33f0326 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_skew.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_skew.idl
@@ -7,7 +7,6 @@
// Spec: https://drafts.css-houdini.org/css-typed-om/#cssskew
[
Constructor(CSSNumericValue ax, CSSNumericValue ay),
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet),
RaisesException=Constructor
] interface CSSSkew : CSSTransformComponent {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_skew_x.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_skew_x.cc
index 14e29737988..424665d8524 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_skew_x.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_skew_x.cc
@@ -4,13 +4,13 @@
#include "third_party/blink/renderer/core/css/cssom/css_skew_x.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_function_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_numeric_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_style_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
#include "third_party/blink/renderer/core/geometry/dom_matrix.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_skew_x.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_skew_x.idl
index 56c29e62067..fc08ea50bf3 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_skew_x.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_skew_x.idl
@@ -7,7 +7,6 @@
// Spec: https://drafts.css-houdini.org/css-typed-om/#cssskewx
[
Constructor(CSSNumericValue ax),
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window, Worker, PaintWorklet, LayoutWorklet),
RaisesException=Constructor]
interface CSSSkewX : CSSTransformComponent {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_skew_y.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_skew_y.cc
index 8ea69f6509a..f064f891e0e 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_skew_y.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_skew_y.cc
@@ -4,13 +4,13 @@
#include "third_party/blink/renderer/core/css/cssom/css_skew_y.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_function_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_numeric_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_style_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
#include "third_party/blink/renderer/core/geometry/dom_matrix.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_skew_y.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_skew_y.idl
index 692e00c4670..eea0517cc41 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_skew_y.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_skew_y.idl
@@ -7,7 +7,6 @@
// Spec: https://drafts.css-houdini.org/css-typed-om/#cssskewy
[
Constructor(CSSNumericValue ay),
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window, Worker, PaintWorklet, LayoutWorklet),
RaisesException=Constructor]
interface CSSSkewY : CSSTransformComponent {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_style_value.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_style_value.cc
index c6451322901..4c4706cfe0b 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_style_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_style_value.cc
@@ -4,13 +4,13 @@
#include "third_party/blink/renderer/core/css/cssom/css_style_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/core/css/cssom/style_value_factory.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/style_property_shorthand.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_style_value.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_style_value.idl
index 88ae318d0c7..d63a4b1ae7b 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_style_value.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_style_value.idl
@@ -7,7 +7,7 @@
// base CSSStyleValues.
// Spec: https://drafts.css-houdini.org/css-typed-om/#stylevalue-objects
[
- Exposed(Window CSSTypedOM,LayoutWorklet CSSTypedOM,PaintWorklet CSSPaintAPI)
+ Exposed=(Window,LayoutWorklet,PaintWorklet)
] interface CSSStyleValue {
stringifier;
// Putting Exposed=Window in the next line makes |parse| not exposed to Worklets.
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_transform_component.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_transform_component.idl
index ab1d67b7128..cfb178357c0 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_transform_component.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_transform_component.idl
@@ -7,7 +7,6 @@
// before they can be used as a value for properties like "transform".
// Spec: https://drafts.css-houdini.org/css-typed-om/#csstransformcomponent
[
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet)
] interface CSSTransformComponent {
stringifier;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_transform_value.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_transform_value.cc
index a8846750b1e..9939dd3ee21 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_transform_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_transform_value.cc
@@ -7,6 +7,8 @@
#include "third_party/blink/renderer/core/css/css_value_list.h"
#include "third_party/blink/renderer/core/css/cssom/css_transform_component.h"
#include "third_party/blink/renderer/core/geometry/dom_matrix.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_transform_value.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_transform_value.idl
index d6b71ee6609..7c654d1180a 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_transform_value.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_transform_value.idl
@@ -5,7 +5,6 @@
[
Constructor(sequence<CSSTransformComponent> transforms),
RaisesException=Constructor,
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet)
] interface CSSTransformValue : CSSStyleValue {
iterable<CSSTransformComponent>;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_translate.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_translate.cc
index b978112e8df..f571a1e4758 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_translate.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_translate.cc
@@ -4,11 +4,11 @@
#include "third_party/blink/renderer/core/css/cssom/css_translate.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_numeric_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_style_value.h"
#include "third_party/blink/renderer/core/geometry/dom_matrix.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_translate.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_translate.idl
index ca272a6734f..51f2ce9e6de 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_translate.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_translate.idl
@@ -8,7 +8,6 @@
[
Constructor(CSSNumericValue x, CSSNumericValue y,
optional CSSNumericValue z),
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet),
RaisesException=Constructor
] interface CSSTranslate : CSSTransformComponent {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_unit_value.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_unit_value.cc
index ec8561fb28b..22b3c060978 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_unit_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_unit_value.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/css/cssom/css_unit_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/animation/length_property_functions.h"
#include "third_party/blink/renderer/core/css/css_calculation_value.h"
#include "third_party/blink/renderer/core/css/css_resolution_units.h"
@@ -15,7 +14,9 @@
#include "third_party/blink/renderer/core/css/cssom/css_math_sum.h"
#include "third_party/blink/renderer/core/css/cssom/css_numeric_sum_value.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_unit_value.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_unit_value.idl
index fe651c98c0b..b0be5d7bdfd 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_unit_value.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_unit_value.idl
@@ -8,7 +8,6 @@
[
Constructor(double value, CSSOMString unit),
RaisesException=Constructor,
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet)
] interface CSSUnitValue : CSSNumericValue {
attribute double value;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_unit_values.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_unit_values.idl
index 5f1eeb3a11e..36a25b5148c 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_unit_values.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_unit_values.idl
@@ -5,8 +5,7 @@
// https://drafts.css-houdini.org/css-typed-om/#numeric-factory
[
- ImplementedAs=CSSUnitValues,
- RuntimeEnabled=CSSTypedOM
+ ImplementedAs=CSSUnitValues
] partial interface CSS {
[NewObject] static CSSUnitValue number(double value);
[NewObject] static CSSUnitValue percent(double value);
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
index c0115351288..d599148a2f2 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_unparsed_value.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/css/css_variable_reference_value.h"
#include "third_party/blink/renderer/core/css/cssom/css_style_variable_reference_value.h"
#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -40,7 +41,8 @@ HeapVector<CSSUnparsedSegment> ParserTokenRangeToTokens(
HeapVector<CSSUnparsedSegment> tokens;
StringBuilder builder;
while (!range.AtEnd()) {
- if (range.Peek().FunctionId() == CSSValueVar) {
+ if (range.Peek().FunctionId() == CSSValueVar ||
+ range.Peek().FunctionId() == CSSValueEnv) {
if (!builder.IsEmpty()) {
tokens.push_back(CSSUnparsedSegment::FromString(builder.ToString()));
builder.Clear();
@@ -120,8 +122,8 @@ const CSSValue* CSSUnparsedValue::ToCSSValue() const {
CSSTokenizer tokenizer(ToString());
const auto tokens = tokenizer.TokenizeToEOF();
return CSSVariableReferenceValue::Create(CSSVariableData::Create(
- CSSParserTokenRange(tokens), false /* isAnimationTainted */,
- false /* needsVariableResolution */));
+ CSSParserTokenRange(tokens), false /* is_animation_tainted */,
+ false /* needs_variable_resolution */, KURL(), WTF::TextEncoding()));
}
String CSSUnparsedValue::ToString() const {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_unparsed_value.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_unparsed_value.idl
index 236fcd1cbc0..685c20f086c 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_unparsed_value.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_unparsed_value.idl
@@ -7,7 +7,6 @@
// Spec: https://drafts.css-houdini.org/css-typed-om/#unparsedvalue-objects
[
Constructor(sequence<CSSUnparsedSegment> members),
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet)
] interface CSSUnparsedValue : CSSStyleValue {
iterable<CSSUnparsedSegment>;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_url_image_value.cc b/chromium/third_party/blink/renderer/core/css/cssom/css_url_image_value.cc
index 3ec4f06dc5a..d0bb96c66fe 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_url_image_value.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_url_image_value.cc
@@ -4,11 +4,11 @@
#include "third_party/blink/renderer/core/css/cssom/css_url_image_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_image_value.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
#include "third_party/blink/renderer/core/style/style_image.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/css_variable_reference_value.idl b/chromium/third_party/blink/renderer/core/css/cssom/css_variable_reference_value.idl
index 8da21e8191f..ca4677386dd 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/css_variable_reference_value.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/css_variable_reference_value.idl
@@ -6,7 +6,6 @@
// Spec: https://drafts.css-houdini.org/css-typed-om/#cssvariablereferencevalue
[
Constructor(CSSOMString variable, optional CSSUnparsedValue? fallback = null),
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window,LayoutWorklet,PaintWorklet),
RaisesException=Constructor,
ImplementedAs=CSSStyleVariableReferenceValue
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/declared_style_property_map.cc b/chromium/third_party/blink/renderer/core/css/cssom/declared_style_property_map.cc
index 0b00dd6d22b..1856f7f80ee 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/declared_style_property_map.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/declared_style_property_map.cc
@@ -123,7 +123,7 @@ String DeclaredStylePropertyMap::SerializationForShorthand(
DCHECK(property.IsShorthand());
if (StyleRule* style_rule = GetStyleRule()) {
return StylePropertySerializer(style_rule->Properties())
- .GetPropertyValue(property.PropertyID());
+ .SerializeShorthand(property.PropertyID());
}
return "";
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/element_computed_style_map.idl b/chromium/third_party/blink/renderer/core/css/cssom/element_computed_style_map.idl
index b212058e2f9..38f0117151c 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/element_computed_style_map.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/element_computed_style_map.idl
@@ -5,8 +5,7 @@
// https://drafts.css-houdini.org/css-typed-om/#computed-stylepropertymapreadonly-objects
[
- ImplementedAs=ElementComputedStyleMap,
- RuntimeEnabled=CSSTypedOM
+ ImplementedAs=ElementComputedStyleMap
] partial interface Element {
[MeasureAs=CSSTypedOMStylePropertyMap] StylePropertyMapReadOnly computedStyleMap();
};
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/inline_style_property_map.cc b/chromium/third_party/blink/renderer/core/css/cssom/inline_style_property_map.cc
index 555b687f9f3..65e9ed9260c 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/inline_style_property_map.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/inline_style_property_map.cc
@@ -90,7 +90,7 @@ String InlineStylePropertyMap::SerializationForShorthand(
DCHECK(property.IsShorthand());
if (const CSSPropertyValueSet* inline_style = owner_element_->InlineStyle()) {
return StylePropertySerializer(*inline_style)
- .GetPropertyValue(property.PropertyID());
+ .SerializeShorthand(property.PropertyID());
}
NOTREACHED();
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h b/chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h
index f081f788336..f691eafe73f 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h
+++ b/chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h
@@ -11,6 +11,8 @@
namespace blink {
+class ComputedStyle;
+
// This class has the same behaviour as the ComputedStylePropertyMap, except it
// only contains the properties given to the constructor.
//
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map_test.cc b/chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map_test.cc
index 9ae84f12315..e0cc71c85c6 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map_test.cc
@@ -8,6 +8,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/css/css_computed_style_declaration.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/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -38,13 +39,13 @@ TEST_F(PrepopulatedComputedStylePropertyMapTest, NativePropertyAccessors) {
{CSSPropertyColor, CSSPropertyAlignItems});
Vector<AtomicString> empty_custom_properties;
+ GetDocument().View()->UpdateAllLifecyclePhases();
Node* node = PageNode();
- const ComputedStyle& style = *node->EnsureComputedStyle();
PrepopulatedComputedStylePropertyMap* map =
- new PrepopulatedComputedStylePropertyMap(GetDocument(), style, node,
- native_properties,
- empty_custom_properties);
+ new PrepopulatedComputedStylePropertyMap(
+ GetDocument(), node->ComputedStyleRef(), node, native_properties,
+ empty_custom_properties);
DummyExceptionStateForTesting exception_state;
@@ -74,13 +75,13 @@ TEST_F(PrepopulatedComputedStylePropertyMapTest, CustomPropertyAccessors) {
Vector<CSSPropertyID> empty_native_properties;
Vector<AtomicString> custom_properties({"--foo", "--bar"});
+ GetDocument().View()->UpdateAllLifecyclePhases();
Node* node = PageNode();
- const ComputedStyle& style = *node->EnsureComputedStyle();
PrepopulatedComputedStylePropertyMap* map =
- new PrepopulatedComputedStylePropertyMap(GetDocument(), style, node,
- empty_native_properties,
- custom_properties);
+ new PrepopulatedComputedStylePropertyMap(
+ GetDocument(), node->ComputedStyleRef(), node,
+ empty_native_properties, custom_properties);
DummyExceptionStateForTesting exception_state;
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/style_property_map.cc b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map.cc
index db8d0348983..0ec4c0624a5 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/style_property_map.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/css/cssom/style_property_map.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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"
@@ -15,6 +14,7 @@
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/style_property_shorthand.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/style_property_map.idl b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map.idl
index c8d3b1ccabc..775ab0b0cb0 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/style_property_map.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map.idl
@@ -5,7 +5,6 @@
// https://drafts.css-houdini.org/css-typed-om/#the-stylepropertymap
[
- RuntimeEnabled=CSSTypedOM,
Exposed=(Window)
] interface StylePropertyMap : StylePropertyMapReadOnly {
// TODO(https://crbug.com/838890): DOMString should be CSSOMString
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.cc b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.cc
index 1359ab6ada1..bd91dd14b39 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_custom_property_declaration.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
#include "third_party/blink/renderer/core/css/css_variable_reference_value.h"
@@ -15,6 +14,7 @@
#include "third_party/blink/renderer/core/css/properties/css_property.h"
#include "third_party/blink/renderer/core/css_property_names.h"
#include "third_party/blink/renderer/core/style_property_shorthand.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -72,7 +72,9 @@ CSSStyleValue* StylePropertyMapReadOnly::get(const String& property_name,
if (!value)
return nullptr;
- if (property.IsRepeated()) {
+ // Custom properties count as repeated whenever we have a CSSValueList.
+ if (property.IsRepeated() ||
+ (property_id == CSSPropertyVariable && value->IsValueList())) {
CSSStyleValueVector values =
StyleValueFactory::CssValueToStyleValueVector(property_id, *value);
return values.IsEmpty() ? nullptr : values[0];
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.idl b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.idl
index 8a73e33c07c..5fab519e625 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.idl
+++ b/chromium/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.idl
@@ -4,7 +4,7 @@
// Spec: https://drafts.css-houdini.org/css-typed-om/#the-stylepropertymap
[
- Exposed(Window CSSTypedOM,LayoutWorklet CSSTypedOM,PaintWorklet CSSPaintAPI)
+ Exposed=(Window,LayoutWorklet,PaintWorklet)
] interface StylePropertyMapReadOnly {
iterable<CSSOMString, sequence<CSSStyleValue>>;
/* TODO: This should return (undefined or CSSStyleValue),
diff --git a/chromium/third_party/blink/renderer/core/css/cssom/style_value_factory.cc b/chromium/third_party/blink/renderer/core/css/cssom/style_value_factory.cc
index 13038719e36..52601ae6f96 100644
--- a/chromium/third_party/blink/renderer/core/css/cssom/style_value_factory.cc
+++ b/chromium/third_party/blink/renderer/core/css/cssom/style_value_factory.cc
@@ -255,9 +255,10 @@ CSSStyleValueVector StyleValueFactory::FromString(
if ((property_id == CSSPropertyVariable && !tokens.IsEmpty()) ||
CSSVariableParser::ContainsValidVariableReferences(range)) {
- const auto variable_data =
- CSSVariableData::Create(range, false /* is_animation_tainted */,
- false /* needs variable resolution */);
+ const auto variable_data = CSSVariableData::Create(
+ range, false /* is_animation_tainted */,
+ false /* needs variable resolution */, parser_context->BaseURL(),
+ parser_context->Charset());
CSSStyleValueVector values;
values.push_back(CSSUnparsedValue::FromCSSVariableData(*variable_data));
return values;
@@ -289,7 +290,10 @@ CSSStyleValueVector StyleValueFactory::CssValueToStyleValueVector(
return style_value_vector;
}
- if (!css_value.IsValueList() || !CSSProperty::Get(property_id).IsRepeated()) {
+ // Custom properties count as repeated whenever we have a CSSValueList.
+ if (!css_value.IsValueList() ||
+ (!CSSProperty::Get(property_id).IsRepeated() &&
+ property_id != CSSPropertyVariable)) {
return UnsupportedCSSValue(property_id, css_value);
}
diff --git a/chromium/third_party/blink/renderer/core/css/document_style_environment_variables.cc b/chromium/third_party/blink/renderer/core/css/document_style_environment_variables.cc
new file mode 100644
index 00000000000..dbb6dfaee51
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/document_style_environment_variables.cc
@@ -0,0 +1,104 @@
+// 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/css/document_style_environment_variables.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/frame/use_counter.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
+#include "third_party/blink/renderer/platform/wtf/string_hasher.h"
+
+namespace blink {
+
+// static
+unsigned DocumentStyleEnvironmentVariables::GenerateHashFromName(
+ const AtomicString& name) {
+ StringHasher hasher;
+
+ if (name.Is8Bit()) {
+ String name_str = String(name);
+ name_str.Ensure16Bit();
+ hasher.AddCharacters(name_str.Characters16(), name_str.length());
+ } else {
+ hasher.AddCharacters(name.Characters16(), name.length());
+ }
+
+ return hasher.GetHash();
+}
+
+// static
+scoped_refptr<DocumentStyleEnvironmentVariables>
+DocumentStyleEnvironmentVariables::Create(StyleEnvironmentVariables& parent,
+ Document& document) {
+ scoped_refptr<DocumentStyleEnvironmentVariables> obj =
+ base::AdoptRef(new DocumentStyleEnvironmentVariables(document));
+
+ // Add a reference to this instance from the root.
+ obj->BindToParent(parent);
+
+ return obj;
+}
+
+CSSVariableData* DocumentStyleEnvironmentVariables::ResolveVariable(
+ const AtomicString& name,
+ bool record_metrics) {
+ unsigned id = GenerateHashFromName(name);
+ if (record_metrics)
+ RecordVariableUsage(id);
+
+ // Mark the variable as seen so we will invalidate the style if we change it.
+ seen_variables_.insert(id);
+ return StyleEnvironmentVariables::ResolveVariable(name);
+}
+
+CSSVariableData* DocumentStyleEnvironmentVariables::ResolveVariable(
+ const AtomicString& name) {
+ return ResolveVariable(name, true /* record_metrics */);
+}
+
+void DocumentStyleEnvironmentVariables::InvalidateVariable(
+ const AtomicString& name) {
+ DCHECK(document_);
+
+ // Invalidate the document if we have seen this variable on this document.
+ if (seen_variables_.Contains(GenerateHashFromName(name)))
+ document_->GetStyleEngine().EnvironmentVariableChanged();
+
+ StyleEnvironmentVariables::InvalidateVariable(name);
+}
+
+DocumentStyleEnvironmentVariables::DocumentStyleEnvironmentVariables(
+ Document& document)
+ : document_(&document) {}
+
+void DocumentStyleEnvironmentVariables::RecordVariableUsage(unsigned id) {
+ UseCounter::Count(document_, WebFeature::kCSSEnvironmentVariable);
+
+ // See the unittest DISABLED_PrintExpectedVariableNameHashes() for how these
+ // values are computed.
+ switch (id) {
+ case 0x3eb492df:
+ UseCounter::Count(document_,
+ WebFeature::kCSSEnvironmentVariable_SafeAreaInsetTop);
+ break;
+ case 0xe0994c83:
+ UseCounter::Count(document_,
+ WebFeature::kCSSEnvironmentVariable_SafeAreaInsetLeft);
+ break;
+ case 0x898873a2:
+ UseCounter::Count(
+ document_, WebFeature::kCSSEnvironmentVariable_SafeAreaInsetBottom);
+ break;
+ case 0xd99fe75b:
+ UseCounter::Count(document_,
+ WebFeature::kCSSEnvironmentVariable_SafeAreaInsetRight);
+ break;
+ default:
+ // Do nothing if this is an unknown variable.
+ break;
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/document_style_environment_variables.h b/chromium/third_party/blink/renderer/core/css/document_style_environment_variables.h
new file mode 100644
index 00000000000..032f5f14fca
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/document_style_environment_variables.h
@@ -0,0 +1,58 @@
+// 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_CSS_DOCUMENT_STYLE_ENVIRONMENT_VARIABLES_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_DOCUMENT_STYLE_ENVIRONMENT_VARIABLES_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/css/style_environment_variables.h"
+
+namespace blink {
+
+class Document;
+
+// DocumentStyleEnvironmentVariables is bound 1:1 to a document and provides
+// document level invalidation logic.
+class CORE_EXPORT DocumentStyleEnvironmentVariables
+ : public StyleEnvironmentVariables {
+ public:
+ // Generate a hash from the provided name.
+ static unsigned GenerateHashFromName(const AtomicString&);
+
+ // Create an instance bound to |parent| that will invalidate |document|'s
+ // style when a variable is changed.
+ static scoped_refptr<DocumentStyleEnvironmentVariables> Create(
+ StyleEnvironmentVariables& parent,
+ Document& document);
+
+ // Resolve the variable |name| and return the data. This will also cause
+ // future changes to this variable to invalidate the associated document's
+ // style. If |record_metrics| is true we will record UseCounter metrics when
+ // this function is called.
+ CSSVariableData* ResolveVariable(const AtomicString& name,
+ bool record_metrics);
+
+ // Resolve the variable |name| and return the data. This will also cause
+ // future changes to this variable to invalidate the associated document's
+ // style. UseCounter metrics will be recorded when this function is used.
+ CSSVariableData* ResolveVariable(const AtomicString& name) override;
+
+ protected:
+ // Called when variable |name| is changed. This will notify any children that
+ // this variable has changed.
+ void InvalidateVariable(const AtomicString& name) override;
+
+ private:
+ DocumentStyleEnvironmentVariables(Document& document);
+
+ // Record variable usage using |UseCounter|.
+ void RecordVariableUsage(unsigned id);
+
+ HashSet<unsigned> seen_variables_;
+ Persistent<Document> document_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_DOCUMENT_STYLE_ENVIRONMENT_VARIABLES_H_
diff --git a/chromium/third_party/blink/renderer/core/css/document_style_sheet_collection.cc b/chromium/third_party/blink/renderer/core/css/document_style_sheet_collection.cc
index d12fffceb64..f50558cfbcc 100644
--- a/chromium/third_party/blink/renderer/core/css/document_style_sheet_collection.cc
+++ b/chromium/third_party/blink/renderer/core/css/document_style_sheet_collection.cc
@@ -34,7 +34,6 @@
#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/css/style_sheet_candidate.h"
-#include "third_party/blink/renderer/core/css/style_sheet_list.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/processing_instruction.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
@@ -88,25 +87,6 @@ void DocumentStyleSheetCollection::CollectStyleSheetsFromCandidates(
collector.AppendActiveStyleSheet(
std::make_pair(css_sheet, master_engine.RuleSetForSheet(*css_sheet)));
}
-
- if (!GetTreeScope().HasMoreStyleSheets())
- return;
-
- StyleSheetList& more_style_sheets = GetTreeScope().MoreStyleSheets();
- unsigned length = more_style_sheets.length();
- for (unsigned index = 0; index < length; ++index) {
- StyleSheet* sheet = more_style_sheets.item(index);
- if (!sheet)
- continue;
- CSSStyleSheet* css_sheet = ToCSSStyleSheet(sheet);
- if (!css_sheet ||
- !css_sheet->CanBeActivated(
- GetDocument().GetStyleEngine().PreferredStylesheetSetName()))
- continue;
- collector.AppendSheetForList(sheet);
- collector.AppendActiveStyleSheet(
- std::make_pair(css_sheet, master_engine.RuleSetForSheet(*css_sheet)));
- }
}
void DocumentStyleSheetCollection::CollectStyleSheets(
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 06968d21934..5d8343bed85 100644
--- a/chromium/third_party/blink/renderer/core/css/font_face.cc
+++ b/chromium/third_party/blink/renderer/core/css/font_face.cc
@@ -31,7 +31,6 @@
#include "third_party/blink/renderer/core/css/font_face.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_array_buffer_or_array_buffer_view.h"
#include "third_party/blink/renderer/core/css/binary_data_font_face_source.h"
#include "third_party/blink/renderer/core/css/css_font_face.h"
@@ -54,7 +53,6 @@
#include "third_party/blink/renderer/core/css_value_keywords.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/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h"
@@ -62,6 +60,7 @@
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.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/font_family_names.h"
#include "third_party/blink/renderer/platform/histogram.h"
@@ -142,10 +141,12 @@ FontFace* FontFace::Create(ExecutionContext* context,
FontFace* font_face = new FontFace(context, family, descriptors);
const CSSValue* src = ParseCSSValue(context, source, AtRuleDescriptorID::Src);
- if (!src || !src->IsValueList())
- font_face->SetError(DOMException::Create(
- kSyntaxError, "The source provided ('" + source +
- "') could not be parsed as a value list."));
+ if (!src || !src->IsValueList()) {
+ font_face->SetError(
+ DOMException::Create(DOMExceptionCode::kSyntaxError,
+ "The source provided ('" + source +
+ "') could not be parsed as a value list."));
+ }
font_face->InitCSSFontFace(context, *src);
return font_face;
@@ -322,9 +323,9 @@ void FontFace::SetPropertyFromString(const ExecutionContext* context,
String message = "Failed to set '" + s + "' as a property value.";
if (exception_state)
- exception_state->ThrowDOMException(kSyntaxError, message);
+ exception_state->ThrowDOMException(DOMExceptionCode::kSyntaxError, message);
else
- SetError(DOMException::Create(kSyntaxError, message));
+ SetError(DOMException::Create(DOMExceptionCode::kSyntaxError, message));
}
bool FontFace::SetPropertyFromStyle(const CSSPropertyValueSet& properties,
@@ -463,8 +464,10 @@ void FontFace::RunCallbacks() {
}
void FontFace::SetError(DOMException* error) {
- if (!error_)
- error_ = error ? error : DOMException::Create(kNetworkError);
+ if (!error_) {
+ error_ =
+ error ? error : DOMException::Create(DOMExceptionCode::kNetworkError);
+ }
SetLoadStatus(kError);
}
@@ -759,7 +762,7 @@ void FontFace::InitCSSFontFace(const unsigned char* data, size_t size) {
if (source->IsValid())
SetLoadStatus(kLoaded);
else
- SetError(DOMException::Create(kSyntaxError,
+ SetError(DOMException::Create(DOMExceptionCode::kSyntaxError,
"Invalid font data in ArrayBuffer."));
css_font_face_->AddSource(source);
}
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 07005dc6197..3dcf1156d14 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
@@ -169,7 +169,8 @@ ScriptPromise FontFaceSet::load(ScriptState* script_state,
ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
resolver->Reject(DOMException::Create(
- kSyntaxError, "Could not resolve '" + font_string + "' as a font."));
+ DOMExceptionCode::kSyntaxError,
+ "Could not resolve '" + font_string + "' as a font."));
return promise;
}
@@ -200,7 +201,8 @@ bool FontFaceSet::check(const String& font_string,
Font font;
if (!ResolveFontStyle(font_string, font)) {
exception_state.ThrowDOMException(
- kSyntaxError, "Could not resolve '" + font_string + "' as a font.");
+ DOMExceptionCode::kSyntaxError,
+ "Could not resolve '" + font_string + "' as a font.");
return false;
}
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 ea410a8dac0..7b6e0a55578 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
@@ -207,11 +207,6 @@ void FontFaceSetDocument::Trace(blink::Visitor* visitor) {
FontFaceSet::Trace(visitor);
}
-void FontFaceSetDocument::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- FontFaceSet::TraceWrappers(visitor);
- Supplement<Document>::TraceWrappers(visitor);
-}
-
void FontFaceSetDocument::FontLoadHistogram::UpdateStatus(FontFace* font_face) {
if (status_ == kReported)
return;
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 f324f861020..b1ff2d832bd 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
@@ -74,7 +74,6 @@ class CORE_EXPORT FontFaceSetDocument final : public FontFaceSet,
static size_t ApproximateBlankCharacterCount(Document&);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
protected:
bool InActiveContext() const override;
diff --git a/chromium/third_party/blink/renderer/core/css/fullscreen.css b/chromium/third_party/blink/renderer/core/css/fullscreen.css
index fa0079ab04a..8023bdb8e26 100644
--- a/chromium/third_party/blink/renderer/core/css/fullscreen.css
+++ b/chromium/third_party/blink/renderer/core/css/fullscreen.css
@@ -1,64 +1,48 @@
-:-webkit-full-screen {
- background-color: white;
- z-index: 2147483647 !important;
-}
-
-:root:-webkit-full-screen-ancestor {
- overflow: hidden !important;
-}
-
-:-webkit-full-screen-ancestor:not(iframe) {
- z-index: auto !important;
- position: static !important;
- opacity: 1 !important;
- transform: none !important;
- -webkit-mask: none !important;
- clip: none !important;
- -webkit-filter: none !important;
- transition: none !important;
- -webkit-box-reflect: none !important;
- -webkit-perspective: none !important;
- -webkit-transform-style: flat !important;
- will-change: auto !important;
-}
-
-video:-webkit-full-screen, audio:-webkit-full-screen {
- background-color: transparent !important;
- position: relative !important;
+:not(:root):-webkit-full-screen {
+ position: fixed !important;
+ top: 0 !important;
+ right: 0 !important;
+ bottom: 0 !important;
left: 0 !important;
- top: 0 ! important;
margin: 0 !important;
+ box-sizing: border-box !important;
min-width: 0 !important;
max-width: none !important;
min-height: 0 !important;
max-height: none !important;
width: 100% !important;
height: 100% !important;
- flex: 1 !important;
- display: block !important;
transform: none !important;
-}
-img:-webkit-full-screen {
- width: auto;
- height: 100%;
- max-width: 100%;
+ /* intentionally not !important */
+ object-fit: contain;
}
iframe:-webkit-full-screen {
- margin: 0 !important;
+ border: none !important;
padding: 0 !important;
- border: 0 !important;
- position: fixed !important;
- min-width: 0 !important;
- max-width: none !important;
- min-height: 0 !important;
- max-height: none !important;
- width: 100% !important;
- height: 100% !important;
- left: 0 !important;
- top: 0 !important;
- transform: none !important;
+}
+
+/* TODO(foolip): In the spec, there's a ::backdrop block with the properties
+ shared with dialog::backdrop (see html.css). */
+:not(:root):-webkit-full-screen::backdrop {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background: black;
+}
+
+/* Anything below are extensions over what the Fullscreen API (29 May 2018) mandates. */
+
+/* This prevents video from overflowing the viewport in
+ virtual/android/fullscreen/video-scrolled-iframe.html (crbug.com/441890) and
+ removes scrollbars caused by html { overflow: scroll } (crbug.com/543946).
+ TODO(foolip): This is done differently in Gecko, find a fix not involving the
+ ancestor selector in https://github.com/whatwg/fullscreen/issues/19. */
+:root:-webkit-full-screen-ancestor {
+ overflow: hidden !important;
}
:-webkit-full-screen:-internal-video-persistent-ancestor :not(:-internal-video-persistent-ancestor) {
diff --git a/chromium/third_party/blink/renderer/core/css/html.css b/chromium/third_party/blink/renderer/core/css/html.css
index 0322f502f78..d5305dee6da 100644
--- a/chromium/third_party/blink/renderer/core/css/html.css
+++ b/chromium/third_party/blink/renderer/core/css/html.css
@@ -366,6 +366,10 @@ form {
margin-top: 0__qem;
}
+:-webkit-any(table, thead, tbody, tfoot, tr) > form:-internal-is-html {
+ display: none !important;
+}
+
label {
cursor: default;
}
@@ -463,6 +467,7 @@ input[type="search" i]::-webkit-search-cancel-button {
-webkit-margin-start: 1px;
opacity: 0;
pointer-events: none;
+ user-select: none !important;
}
input[type="search" i]:enabled:read-write:-webkit-any(:focus,:hover)::-webkit-search-cancel-button {
@@ -1049,7 +1054,7 @@ ruby > rt {
text-align: start;
}
-ruby > rp {
+rp {
display: none;
}
@@ -1120,6 +1125,8 @@ dialog {
color: black
}
+/* TODO(foolip): In the Fullscreen spec, there's a ::backdrop block with the
+ properties shared with :fullscreen::backdrop (see fullscreen.css). */
dialog::backdrop {
position: fixed;
top: 0;
diff --git a/chromium/third_party/blink/renderer/core/css/invalidation/invalidation_set.cc b/chromium/third_party/blink/renderer/core/css/invalidation/invalidation_set.cc
index 8608530b935..64f8eb80514 100644
--- a/chromium/third_party/blink/renderer/core/css/invalidation/invalidation_set.cc
+++ b/chromium/third_party/blink/renderer/core/css/invalidation/invalidation_set.cc
@@ -291,6 +291,13 @@ scoped_refptr<DescendantInvalidationSet> CreateSelfInvalidationSet() {
return new_set;
}
+scoped_refptr<DescendantInvalidationSet> CreatePartInvalidationSet() {
+ auto new_set = DescendantInvalidationSet::Create();
+ new_set->SetInvalidatesParts();
+ new_set->SetTreeBoundaryCrossing();
+ return new_set;
+}
+
} // namespace
InvalidationSet* InvalidationSet::SelfInvalidationSet() {
@@ -298,6 +305,11 @@ InvalidationSet* InvalidationSet::SelfInvalidationSet() {
return singleton_;
}
+InvalidationSet* InvalidationSet::PartInvalidationSet() {
+ DEFINE_STATIC_REF(InvalidationSet, singleton_, CreatePartInvalidationSet());
+ return singleton_;
+}
+
void InvalidationSet::ToTracedValue(TracedValue* value) const {
value->BeginDictionary();
diff --git a/chromium/third_party/blink/renderer/core/css/invalidation/invalidation_set.h b/chromium/third_party/blink/renderer/core/css/invalidation/invalidation_set.h
index cb68913d571..46e5e578466 100644
--- a/chromium/third_party/blink/renderer/core/css/invalidation/invalidation_set.h
+++ b/chromium/third_party/blink/renderer/core/css/invalidation/invalidation_set.h
@@ -207,6 +207,10 @@ class CORE_EXPORT InvalidationSet
static InvalidationSet* SelfInvalidationSet();
bool IsSelfInvalidationSet() const { return this == SelfInvalidationSet(); }
+ // Returns a singleton DescendantInvalidationSet which invalidates all
+ // shadow-including descendants with part attributes.
+ static InvalidationSet* PartInvalidationSet();
+
protected:
explicit InvalidationSet(InvalidationType);
diff --git a/chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations.h b/chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations.h
index 0ddaa75b741..1f98d90e9f6 100644
--- a/chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations.h
+++ b/chromium/third_party/blink/renderer/core/css/invalidation/pending_invalidations.h
@@ -68,6 +68,8 @@ class CORE_EXPORT PendingInvalidations {
PendingInvalidations();
~PendingInvalidations(){};
void Invalidate(Document&);
+ // May immediately invalidate the node and/or add pending invalidation sets to
+ // this node.
void ScheduleInvalidationSetsForNode(const InvalidationLists&,
ContainerNode&);
void ScheduleSiblingInvalidationsAsDescendants(
diff --git a/chromium/third_party/blink/renderer/core/css/invalidation/style_invalidator.cc b/chromium/third_party/blink/renderer/core/css/invalidation/style_invalidator.cc
index c17d16594e3..35e6c9137f4 100644
--- a/chromium/third_party/blink/renderer/core/css/invalidation/style_invalidator.cc
+++ b/chromium/third_party/blink/renderer/core/css/invalidation/style_invalidator.cc
@@ -246,8 +246,14 @@ void StyleInvalidator::InvalidateChildren(Element& element) {
void StyleInvalidator::Invalidate(Element& element, SiblingData& sibling_data) {
sibling_data.Advance();
+ // Preserves the current stack of pending invalidations and other state and
+ // restores it when this method returns.
RecursionCheckpoint checkpoint(this);
+ // If we have already entered a subtree that is going to be entirely
+ // recalculated then there is no need to test against current invalidation
+ // sets or to continue to accumulate new invalidation sets as we descend the
+ // tree.
if (!WholeSubtreeInvalid()) {
if (element.GetStyleChangeType() >= kSubtreeStyleChange) {
SetWholeSubtreeInvalid();
@@ -258,17 +264,34 @@ void StyleInvalidator::Invalidate(Element& element, SiblingData& sibling_data) {
}
if (UNLIKELY(element.NeedsStyleInvalidation()))
PushInvalidationSetsForContainerNode(element, sibling_data);
+
+ // When a slot element is invalidated, the slotted elements are also
+ // invalidated by HTMLSlotElement::DidRecalcStyle. So if WholeSubtreeInvalid
+ // is true, they will be included even though they are not part of the
+ // subtree. It's not necessary to fully recalc style for the slotted
+ // elements in that case as they just need to pick up changed inherited
+ // styles but we do it. If we ever stop doing that then this code and the
+ // PushInvalidationSetsForContainerNode above need to move out of the
+ // if-block.
+ if (InvalidatesSlotted() && IsHTMLSlotElement(element))
+ InvalidateSlotDistributedElements(ToHTMLSlotElement(element));
+
+ if (InsertionPointCrossing() && element.IsV0InsertionPoint()) {
+ element.SetNeedsStyleRecalc(kSubtreeStyleChange,
+ StyleChangeReasonForTracing::Create(
+ StyleChangeReason::kStyleInvalidator));
+ }
}
- if (HasInvalidationSets() || element.ChildNeedsStyleInvalidation())
+ // We need to recurse into children if:
+ // * the whole subtree is not invalid and we have invalidation sets that
+ // could apply to the descendants.
+ // * there are invalidation sets attached to descendants then we need to
+ // clear the flags on the nodes, whether we use the sets or not.
+ if ((!WholeSubtreeInvalid() && HasInvalidationSets()) ||
+ element.ChildNeedsStyleInvalidation()) {
InvalidateChildren(element);
-
- if (InsertionPointCrossing() && element.IsV0InsertionPoint())
- element.SetNeedsStyleRecalc(kSubtreeStyleChange,
- StyleChangeReasonForTracing::Create(
- StyleChangeReason::kStyleInvalidator));
- if (InvalidatesSlotted() && IsHTMLSlotElement(element))
- InvalidateSlotDistributedElements(ToHTMLSlotElement(element));
+ }
element.ClearChildNeedsStyleInvalidation();
element.ClearNeedsStyleInvalidation();
diff --git a/chromium/third_party/blink/renderer/core/css/media_list.cc b/chromium/third_party/blink/renderer/core/css/media_list.cc
index b05549a4820..89289698bfe 100644
--- a/chromium/third_party/blink/renderer/core/css/media_list.cc
+++ b/chromium/third_party/blink/renderer/core/css/media_list.cc
@@ -20,10 +20,10 @@
#include "third_party/blink/renderer/core/css/media_list.h"
#include <memory>
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
#include "third_party/blink/renderer/core/css/media_query_exp.h"
#include "third_party/blink/renderer/core/css/parser/media_query_parser.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -184,7 +184,7 @@ void MediaList::deleteMedium(const String& medium,
bool success = media_queries_->Remove(medium);
if (!success) {
- exception_state.ThrowDOMException(kNotFoundError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotFoundError,
"Failed to delete '" + medium + "'.");
return;
}
diff --git a/chromium/third_party/blink/renderer/core/css/media_list.h b/chromium/third_party/blink/renderer/core/css/media_list.h
index 2f148a5dda6..5018623ccb4 100644
--- a/chromium/third_party/blink/renderer/core/css/media_list.h
+++ b/chromium/third_party/blink/renderer/core/css/media_list.h
@@ -24,7 +24,6 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/media_query.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#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/wtf/forward.h"
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 ec8b97517f4..b61a883d3cc 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
@@ -32,8 +32,8 @@
#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
-#include "third_party/blink/renderer/platform/decimal.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/wtf/decimal.h"
#include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_lazy_parsing_test.cc b/chromium/third_party/blink/renderer/core/css/parser/css_lazy_parsing_test.cc
index eba7b8e2f54..c5415024fad 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_lazy_parsing_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_lazy_parsing_test.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
#include "third_party/blink/renderer/core/css/style_rule.h"
#include "third_party/blink/renderer/core/css/style_sheet_contents.h"
+#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -112,6 +113,8 @@ TEST_F(CSSLazyParsingTest, ShouldConsiderForMatchingRulesSimple) {
TEST_F(CSSLazyParsingTest, ChangeDocuments) {
std::unique_ptr<DummyPageHolder> dummy_holder =
DummyPageHolder::Create(IntSize(500, 500));
+ Page::InsertOrdinaryPageForTesting(&dummy_holder->GetPage());
+
CSSParserContext* context = CSSParserContext::Create(
kHTMLStandardMode, SecureContextMode::kInsecureContext,
CSSParserContext::kLiveProfile, &dummy_holder->GetDocument());
@@ -134,7 +137,7 @@ TEST_F(CSSLazyParsingTest, ChangeDocuments) {
EXPECT_EQ(&dummy_holder->GetDocument(),
cached_contents_->SingleOwnerDocument());
UseCounter& use_counter1 =
- dummy_holder->GetDocument().GetPage()->GetUseCounter();
+ dummy_holder->GetDocument().Loader()->GetUseCounter();
EXPECT_TRUE(use_counter1.IsCounted(CSSPropertyBackgroundColor));
EXPECT_FALSE(use_counter1.IsCounted(CSSPropertyColor));
@@ -147,6 +150,7 @@ TEST_F(CSSLazyParsingTest, ChangeDocuments) {
std::unique_ptr<DummyPageHolder> dummy_holder2 =
DummyPageHolder::Create(IntSize(500, 500));
+ Page::InsertOrdinaryPageForTesting(&dummy_holder2->GetPage());
CSSStyleSheet* sheet2 =
CSSStyleSheet::Create(cached_contents_, dummy_holder2->GetDocument());
@@ -160,7 +164,7 @@ TEST_F(CSSLazyParsingTest, ChangeDocuments) {
EXPECT_TRUE(HasParsedProperties(rule2));
UseCounter& use_counter2 =
- dummy_holder2->GetDocument().GetPage()->GetUseCounter();
+ dummy_holder2->GetDocument().Loader()->GetUseCounter();
EXPECT_TRUE(sheet2);
EXPECT_TRUE(use_counter2.IsCounted(CSSPropertyColor));
EXPECT_FALSE(use_counter2.IsCounted(CSSPropertyBackgroundColor));
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 4c6645acbd2..757d4dea80f 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
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/frame/deprecation.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/loader/document_loader.h"
#include "third_party/blink/renderer/core/page/page.h"
namespace blink {
@@ -227,8 +228,8 @@ void CSSParserContext::CountDeprecation(WebFeature feature) const {
}
void CSSParserContext::Count(CSSParserMode mode, CSSPropertyID property) const {
- if (IsUseCounterRecordingEnabled() && document_->GetPage()) {
- UseCounter* use_counter = &document_->GetPage()->GetUseCounter();
+ if (IsUseCounterRecordingEnabled() && document_->Loader()) {
+ UseCounter* use_counter = &document_->Loader()->GetUseCounter();
if (use_counter)
use_counter->Count(mode, property, document_->GetFrame());
}
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 d20b0668f7e..3fa20d6a895 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
@@ -57,14 +57,10 @@ static inline bool IsSimpleLengthPropertyID(CSSPropertyID property_id,
case CSSPropertyScrollPaddingLeft:
case CSSPropertyScrollPaddingRight:
case CSSPropertyScrollPaddingTop:
- case CSSPropertyWebkitLogicalWidth:
- case CSSPropertyWebkitLogicalHeight:
- case CSSPropertyWebkitMinLogicalWidth:
- case CSSPropertyWebkitMinLogicalHeight:
- case CSSPropertyWebkitPaddingAfter:
- case CSSPropertyWebkitPaddingBefore:
- case CSSPropertyWebkitPaddingEnd:
- case CSSPropertyWebkitPaddingStart:
+ case CSSPropertyPaddingBlockEnd:
+ case CSSPropertyPaddingBlockStart:
+ case CSSPropertyPaddingInlineEnd:
+ case CSSPropertyPaddingInlineStart:
case CSSPropertyShapeMargin:
case CSSPropertyR:
case CSSPropertyRx:
@@ -82,10 +78,10 @@ static inline bool IsSimpleLengthPropertyID(CSSPropertyID property_id,
case CSSPropertyOffsetDistance:
case CSSPropertyRight:
case CSSPropertyTop:
- case CSSPropertyWebkitMarginAfter:
- case CSSPropertyWebkitMarginBefore:
- case CSSPropertyWebkitMarginEnd:
- case CSSPropertyWebkitMarginStart:
+ case CSSPropertyMarginBlockEnd:
+ case CSSPropertyMarginBlockStart:
+ case CSSPropertyMarginInlineEnd:
+ case CSSPropertyMarginInlineStart:
case CSSPropertyX:
case CSSPropertyY:
accepts_negative_numbers = true;
@@ -174,10 +170,10 @@ static inline bool IsColorPropertyID(CSSPropertyID property_id) {
case CSSPropertyOutlineColor:
case CSSPropertyStopColor:
case CSSPropertyStroke:
- case CSSPropertyWebkitBorderAfterColor:
- case CSSPropertyWebkitBorderBeforeColor:
- case CSSPropertyWebkitBorderEndColor:
- case CSSPropertyWebkitBorderStartColor:
+ case CSSPropertyBorderBlockEndColor:
+ case CSSPropertyBorderBlockStartColor:
+ case CSSPropertyBorderInlineEndColor:
+ case CSSPropertyBorderInlineStartColor:
case CSSPropertyColumnRuleColor:
case CSSPropertyWebkitTextEmphasisColor:
case CSSPropertyWebkitTextFillColor:
@@ -572,10 +568,10 @@ bool CSSParserFastPaths::IsValidKeywordPropertyAndValue(
case CSSPropertyBorderRightStyle:
case CSSPropertyBorderBottomStyle:
case CSSPropertyBorderLeftStyle:
- case CSSPropertyWebkitBorderAfterStyle:
- case CSSPropertyWebkitBorderBeforeStyle:
- case CSSPropertyWebkitBorderEndStyle:
- case CSSPropertyWebkitBorderStartStyle:
+ case CSSPropertyBorderBlockEndStyle:
+ case CSSPropertyBorderBlockStartStyle:
+ case CSSPropertyBorderInlineEndStyle:
+ case CSSPropertyBorderInlineStartStyle:
case CSSPropertyColumnRuleStyle:
return value_id >= CSSValueNone && value_id <= CSSValueDouble;
case CSSPropertyBoxSizing:
@@ -641,7 +637,6 @@ bool CSSParserFastPaths::IsValidKeywordPropertyAndValue(
return value_id == CSSValueVisible || value_id == CSSValueNone ||
value_id == CSSValueAuto;
case CSSPropertyOverflowWrap:
- case CSSPropertyWordWrap:
return value_id == CSSValueNormal || value_id == CSSValueBreakWord;
case CSSPropertyOverflowX:
return value_id == CSSValueVisible || value_id == CSSValueHidden ||
@@ -965,10 +960,10 @@ bool CSSParserFastPaths::IsKeywordPropertyID(CSSPropertyID property_id) {
case CSSPropertyWebkitAppRegion:
case CSSPropertyWebkitAppearance:
case CSSPropertyBackfaceVisibility:
- case CSSPropertyWebkitBorderAfterStyle:
- case CSSPropertyWebkitBorderBeforeStyle:
- case CSSPropertyWebkitBorderEndStyle:
- case CSSPropertyWebkitBorderStartStyle:
+ case CSSPropertyBorderBlockEndStyle:
+ case CSSPropertyBorderBlockStartStyle:
+ case CSSPropertyBorderInlineEndStyle:
+ case CSSPropertyBorderInlineStartStyle:
case CSSPropertyWebkitBoxAlign:
case CSSPropertyWebkitBoxDecorationBreak:
case CSSPropertyWebkitBoxDirection:
@@ -999,7 +994,6 @@ bool CSSParserFastPaths::IsKeywordPropertyID(CSSPropertyID property_id) {
case CSSPropertyWebkitWritingMode:
case CSSPropertyWhiteSpace:
case CSSPropertyWordBreak:
- case CSSPropertyWordWrap:
case CSSPropertyWritingMode:
case CSSPropertyScrollSnapStop:
return true;
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 092c01bd0af..22c6edb189e 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
@@ -967,8 +967,8 @@ void CSSParserImpl::ConsumeVariableValue(CSSParserTokenRange range,
bool important,
bool is_animation_tainted) {
if (CSSCustomPropertyDeclaration* value =
- CSSVariableParser::ParseDeclarationValue(variable_name, range,
- is_animation_tainted)) {
+ CSSVariableParser::ParseDeclarationValue(
+ variable_name, range, is_animation_tainted, *context_)) {
parsed_properties_.push_back(
CSSPropertyValue(GetCSSPropertyVariable(), *value, important));
context_->Count(context_->Mode(), CSSPropertyVariable);
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_parser_selector.cc b/chromium/third_party/blink/renderer/core/css/parser/css_parser_selector.cc
index 5895646878a..de16b87d282 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_parser_selector.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_parser_selector.cc
@@ -39,16 +39,10 @@ CSSParserSelector::CSSParserSelector(const QualifiedName& tag_q_name,
: selector_(std::make_unique<CSSSelector>(tag_q_name, is_implicit)) {}
CSSParserSelector::~CSSParserSelector() {
- if (!tag_history_)
- return;
- Vector<std::unique_ptr<CSSParserSelector>, 16> to_delete;
- std::unique_ptr<CSSParserSelector> selector = std::move(tag_history_);
- while (true) {
- std::unique_ptr<CSSParserSelector> next = std::move(selector->tag_history_);
- to_delete.push_back(std::move(selector));
- if (!next)
- break;
- selector = std::move(next);
+ while (tag_history_) {
+ std::unique_ptr<CSSParserSelector> next =
+ std::move(tag_history_->tag_history_);
+ tag_history_ = std::move(next);
}
}
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 8a78b16b4bc..1f44e2df51b 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
@@ -118,7 +118,8 @@ bool CSSPropertyParser::ParseValueStart(CSSPropertyID unresolved_property,
if (CSSVariableParser::ContainsValidVariableReferences(original_range)) {
bool is_animation_tainted = false;
CSSVariableReferenceValue* variable = CSSVariableReferenceValue::Create(
- CSSVariableData::Create(original_range, is_animation_tainted, true),
+ CSSVariableData::Create(original_range, is_animation_tainted, true,
+ context_->BaseURL(), context_->Charset()),
*context_);
if (is_shorthand) {
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 f95cdc1335c..ba42b92428d 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
@@ -40,11 +40,13 @@ namespace {
// Add CSSVariableData to variableData vector.
bool AddCSSPaintArgument(
const Vector<CSSParserToken>& tokens,
- Vector<scoped_refptr<CSSVariableData>>* const variable_data) {
+ Vector<scoped_refptr<CSSVariableData>>* const variable_data,
+ const CSSParserContext* context) {
CSSParserTokenRange token_range(tokens);
if (!token_range.AtEnd()) {
scoped_refptr<CSSVariableData> unparsed_css_variable_data =
- CSSVariableData::Create(token_range, false, false);
+ CSSVariableData::Create(token_range, false, false, context->BaseURL(),
+ context->Charset());
if (unparsed_css_variable_data.get()) {
variable_data->push_back(std::move(unparsed_css_variable_data));
return true;
@@ -938,10 +940,13 @@ bool ConsumeOneOrTwoValuedPosition(CSSParserTokenRange& range,
if (!value1->IsIdentifierValue())
horizontal_edge = true;
- CSSValue* value2 = nullptr;
- if (!vertical_edge || range.Peek().GetType() == kIdentToken)
- value2 = ConsumePositionComponent(range, css_parser_mode, unitless,
- horizontal_edge, vertical_edge);
+ if (vertical_edge && ConsumeLengthOrPercent(range, css_parser_mode,
+ kValueRangeAll, unitless)) {
+ // <length-percentage> is not permitted after top | bottom.
+ return false;
+ }
+ CSSValue* value2 = ConsumePositionComponent(range, css_parser_mode, unitless,
+ horizontal_edge, vertical_edge);
if (!value2) {
PositionFromOneValue(value1, result_x, result_y);
return true;
@@ -950,6 +955,46 @@ bool ConsumeOneOrTwoValuedPosition(CSSParserTokenRange& range,
return true;
}
+bool ConsumeBorderShorthand(CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSValue*& result_width,
+ const CSSValue*& result_style,
+ const CSSValue*& result_color) {
+ while (!result_width || !result_style || !result_color) {
+ if (!result_width) {
+ result_width = CSSPropertyParserHelpers::ConsumeLineWidth(
+ range, context.Mode(),
+ CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
+ if (result_width)
+ continue;
+ }
+ if (!result_style) {
+ result_style = CSSPropertyParserHelpers::ParseLonghand(
+ CSSPropertyBorderLeftStyle, CSSPropertyBorder, context, range);
+ if (result_style)
+ continue;
+ }
+ if (!result_color) {
+ result_color =
+ CSSPropertyParserHelpers::ConsumeColor(range, context.Mode());
+ if (result_color)
+ continue;
+ }
+ break;
+ }
+
+ if (!result_width && !result_style && !result_color)
+ return false;
+
+ if (!result_width)
+ result_width = CSSInitialValue::Create();
+ if (!result_style)
+ result_style = CSSInitialValue::Create();
+ if (!result_color)
+ result_color = CSSInitialValue::Create();
+ return true;
+}
+
// This should go away once we drop support for -webkit-gradient
static CSSPrimitiveValue* ConsumeDeprecatedGradientPoint(
CSSParserTokenRange& args,
@@ -1320,9 +1365,6 @@ static CSSValue* ConsumeLinearGradient(CSSParserTokenRange& args,
static CSSValue* ConsumeConicGradient(CSSParserTokenRange& args,
const CSSParserContext& context,
CSSGradientRepeat repeating) {
- if (!RuntimeEnabledFeatures::ConicGradientEnabled())
- return nullptr;
-
const CSSPrimitiveValue* from_angle = nullptr;
if (ConsumeIdent<CSSValueFrom>(args)) {
if (!(from_angle = ConsumeAngle(args, &context,
@@ -1387,8 +1429,6 @@ static CSSValue* ConsumeCrossFade(CSSParserTokenRange& args,
static CSSValue* ConsumePaint(CSSParserTokenRange& args,
const CSSParserContext* context) {
- DCHECK(RuntimeEnabledFeatures::CSSPaintAPIEnabled());
-
const CSSParserToken& name_token = args.ConsumeIncludingWhitespace();
CSSCustomIdentValue* name = ConsumeCustomIdentWithToken(name_token);
if (!name)
@@ -1415,14 +1455,14 @@ static CSSValue* ConsumePaint(CSSParserTokenRange& args,
if (args.Peek().GetType() != kCommaToken) {
argument_tokens.AppendVector(ConsumeFunctionArgsOrNot(args));
} else {
- if (!AddCSSPaintArgument(argument_tokens, &variable_data))
+ if (!AddCSSPaintArgument(argument_tokens, &variable_data, context))
return nullptr;
argument_tokens.clear();
if (!ConsumeCommaIncludingWhitespace(args))
return nullptr;
}
}
- if (!AddCSSPaintArgument(argument_tokens, &variable_data))
+ if (!AddCSSPaintArgument(argument_tokens, &variable_data, context))
return nullptr;
return CSSPaintValue::Create(name, variable_data);
@@ -1468,10 +1508,7 @@ static CSSValue* ConsumeGeneratedImage(CSSParserTokenRange& range,
} else if (id == CSSValueWebkitCrossFade) {
result = ConsumeCrossFade(args, context);
} else if (id == CSSValuePaint) {
- result = context->IsSecureContext() &&
- RuntimeEnabledFeatures::CSSPaintAPIEnabled()
- ? ConsumePaint(args, context)
- : nullptr;
+ result = context->IsSecureContext() ? ConsumePaint(args, context) : nullptr;
}
if (!result || !args.AtEnd())
return nullptr;
@@ -1600,6 +1637,13 @@ void AddProperty(CSSPropertyID resolved_property,
shorthand_index, implicit == IsImplicitProperty::kImplicit));
}
+CSSValue* ConsumeTransformValue(CSSParserTokenRange& range,
+ const CSSParserContext& context) {
+ bool use_legacy_parsing = false;
+ return CSSParsingUtils::ConsumeTransformValue(range, context,
+ use_legacy_parsing);
+}
+
CSSValue* ConsumeTransformList(CSSParserTokenRange& range,
const CSSParserContext& context) {
return CSSParsingUtils::ConsumeTransformList(range, context,
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 f1870b17d8e..c8cc6856851 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
@@ -101,6 +101,11 @@ bool ConsumeOneOrTwoValuedPosition(CSSParserTokenRange&,
UnitlessQuirk,
CSSValue*& result_x,
CSSValue*& result_y);
+bool ConsumeBorderShorthand(CSSParserTokenRange&,
+ const CSSParserContext&,
+ const CSSValue*& result_width,
+ const CSSValue*& result_style,
+ const CSSValue*& result_color);
enum class ConsumeGeneratedImagePolicy { kAllow, kForbid };
@@ -195,6 +200,7 @@ CSSValueList* ConsumeCommaSeparatedList(Func callback,
return list;
}
+CSSValue* ConsumeTransformValue(CSSParserTokenRange&, const CSSParserContext&);
CSSValue* ConsumeTransformList(CSSParserTokenRange&, const CSSParserContext&);
CSSValue* ConsumeFilterFunctionList(CSSParserTokenRange&,
const CSSParserContext&);
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 5b58d515734..89b0b1bdea6 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
@@ -333,6 +333,7 @@ TEST(CSSPropertyParserTest, ClipPathEllipse) {
std::unique_ptr<DummyPageHolder> dummy_holder =
DummyPageHolder::Create(IntSize(500, 500));
Document* doc = &dummy_holder->GetDocument();
+ Page::InsertOrdinaryPageForTesting(&dummy_holder->GetPage());
CSSParserContext* context = CSSParserContext::Create(
kHTMLStandardMode, SecureContextMode::kSecureContext,
CSSParserContext::kLiveProfile, doc);
@@ -406,6 +407,7 @@ TEST(CSSPropertyParserTest, GradientUseCount) {
std::unique_ptr<DummyPageHolder> dummy_page_holder =
DummyPageHolder::Create(IntSize(800, 600));
Document& document = dummy_page_holder->GetDocument();
+ Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
WebFeature feature = WebFeature::kCSSGradient;
EXPECT_FALSE(UseCounter::IsCounted(document, feature));
document.documentElement()->SetInnerHTMLFromString(
@@ -417,6 +419,7 @@ TEST(CSSPropertyParserTest, PaintUseCount) {
std::unique_ptr<DummyPageHolder> dummy_page_holder =
DummyPageHolder::Create(IntSize(800, 600));
Document& document = dummy_page_holder->GetDocument();
+ Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
document.SetSecureContextStateForTesting(SecureContextState::kSecure);
WebFeature feature = WebFeature::kCSSPaintFunction;
EXPECT_FALSE(UseCounter::IsCounted(document, feature));
@@ -429,6 +432,7 @@ TEST(CSSPropertyParserTest, CrossFadeUseCount) {
std::unique_ptr<DummyPageHolder> dummy_page_holder =
DummyPageHolder::Create(IntSize(800, 600));
Document& document = dummy_page_holder->GetDocument();
+ Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
WebFeature feature = WebFeature::kWebkitCrossFade;
EXPECT_FALSE(UseCounter::IsCounted(document, feature));
document.documentElement()->SetInnerHTMLFromString(
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_proto_converter.cc b/chromium/third_party/blink/renderer/core/css/parser/css_proto_converter.cc
index c267e101b62..9f911947e18 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_proto_converter.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_proto_converter.cc
@@ -28,6 +28,7 @@ const std::string Converter::kViewportValueLookupTable[] = {
const std::string Converter::kPseudoLookupTable[] = {
"", // This is just to fill the zeroth spot. It should not be used.
+ "-internal-is-html",
"-internal-list-box",
"-internal-media-controls-overlay-cast-button",
"-internal-shadow-host-has-appearance",
@@ -1433,6 +1434,49 @@ const std::string Converter::kPropertyLookupTable[] = {
"stop-color",
"stroke-dasharray",
"-webkit-line-clamp",
+ "margin-block-start",
+ "margin-block-end",
+ "margin-inline-start",
+ "margin-inline-end",
+ "padding-block-start",
+ "padding-block-end",
+ "padding-inline-start",
+ "padding-inline-end",
+ "border-block-start-width",
+ "border-block-start-style",
+ "border-block-start-color",
+ "border-block-end-width",
+ "border-block-end-style",
+ "border-block-end-color",
+ "border-inline-start-width",
+ "border-inline-start-style",
+ "border-inline-start-color",
+ "border-inline-end-width",
+ "border-inline-end-style",
+ "border-inline-end-color",
+ "border-block-start",
+ "border-block-end",
+ "border-inline-start",
+ "border-inline-end",
+ "margin-block",
+ "margin-inline",
+ "padding-block",
+ "padding-inline",
+ "border-block-width",
+ "border-block-style",
+ "border-block-color",
+ "border-inline-width",
+ "border-inline-style",
+ "border-inline-color",
+ "border-block",
+ "border-inline",
+ "inset-block-start",
+ "inset-block-end",
+ "inset-block",
+ "inset-inline-start",
+ "inset-inline-end",
+ "inset-inline",
+ "inset",
"INVALID_PROPERTY",
};
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_selector_parser.cc b/chromium/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
index bd4f0d88251..0715324a4ba 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
@@ -662,25 +662,8 @@ CSSSelector::RelationType CSSSelectorParser::ConsumeCombinator(
return CSSSelector::kIndirectAdjacent;
case '>':
- if (!RuntimeEnabledFeatures::
- ShadowPiercingDescendantCombinatorEnabled() ||
- context_->IsLiveProfile() ||
- range.Peek(1).GetType() != kDelimiterToken ||
- range.Peek(1).Delimiter() != '>') {
- range.ConsumeIncludingWhitespace();
- return CSSSelector::kChild;
- }
- range.Consume();
-
- // Check the 3rd '>'.
- if (range.Peek(1).GetType() != kDelimiterToken ||
- range.Peek(1).Delimiter() != '>') {
- // TODO: Treat '>>' as a CSSSelector::kDescendant here.
- return CSSSelector::kChild;
- }
- range.Consume();
range.ConsumeIncludingWhitespace();
- return CSSSelector::kShadowPiercingDescendant;
+ return CSSSelector::kChild;
case '/': {
// Match /deep/
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_selector_parser_test.cc b/chromium/third_party/blink/renderer/core/css/parser/css_selector_parser_test.cc
index 68540910b48..c67ee0f9a91 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_selector_parser_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_selector_parser_test.cc
@@ -315,68 +315,6 @@ TEST(CSSSelectorParserTest, SerializedUniversal) {
}
}
-TEST(CSSSelectorParserTest, InvalidDescendantCombinatorInLiveProfile) {
- const char* test_cases[] = {"div >>>> span", "div >>> span", "div >> span"};
-
- CSSParserContext* context = CSSParserContext::Create(
- kHTMLStandardMode, SecureContextMode::kInsecureContext,
- CSSParserContext::kLiveProfile);
- StyleSheetContents* sheet = StyleSheetContents::Create(context);
-
- for (auto* test_case : test_cases) {
- SCOPED_TRACE(test_case);
- CSSTokenizer tokenizer(test_case);
- const auto tokens = tokenizer.TokenizeToEOF();
- CSSParserTokenRange range(tokens);
- CSSSelectorList list =
- CSSSelectorParser::ParseSelector(range, context, sheet);
- EXPECT_FALSE(list.IsValid());
- }
-}
-
-TEST(CSSSelectorParserTest, InvalidDescendantCombinatorInSnapshotProfile) {
- const char* test_cases[] = {"div >>>> span", "div >> span", "div >> > span",
- "div > >> span", "div > > > span"};
-
- CSSParserContext* context = CSSParserContext::Create(
- kHTMLStandardMode, SecureContextMode::kInsecureContext,
- CSSParserContext::kSnapshotProfile);
- StyleSheetContents* sheet = StyleSheetContents::Create(context);
-
- for (auto* test_case : test_cases) {
- SCOPED_TRACE(test_case);
- CSSTokenizer tokenizer(test_case);
- const auto tokens = tokenizer.TokenizeToEOF();
- CSSParserTokenRange range(tokens);
- CSSSelectorList list =
- CSSSelectorParser::ParseSelector(range, context, sheet);
- EXPECT_FALSE(list.IsValid());
- }
-}
-
-TEST(CSSSelectorParserTest, ShadowPiercingCombinatorInSnapshotProfile) {
- const char* test_cases[][2] = {{"div >>> span", "div >>> span"},
- {"div >>/**/> span", "div >>> span"},
- {"div >/**/>> span", "div >>> span"},
- {"div >/**/>/**/> span", "div >>> span"}};
-
- CSSParserContext* context = CSSParserContext::Create(
- kHTMLStandardMode, SecureContextMode::kInsecureContext,
- CSSParserContext::kSnapshotProfile);
- StyleSheetContents* sheet = StyleSheetContents::Create(context);
-
- for (auto** test_case : test_cases) {
- SCOPED_TRACE(test_case[0]);
- CSSTokenizer tokenizer(test_case[0]);
- const auto tokens = tokenizer.TokenizeToEOF();
- CSSParserTokenRange range(tokens);
- CSSSelectorList list =
- CSSSelectorParser::ParseSelector(range, context, sheet);
- EXPECT_TRUE(list.IsValid());
- EXPECT_STREQ(test_case[1], list.SelectorsText().Ascii().data());
- }
-}
-
TEST(CSSSelectorParserTest, AttributeSelectorUniversalInvalid) {
const char* test_cases[] = {"[*]", "[*|*]"};
@@ -398,6 +336,7 @@ TEST(CSSSelectorParserTest, AttributeSelectorUniversalInvalid) {
TEST(CSSSelectorParserTest, InternalPseudo) {
const char* test_cases[] = {"::-internal-whatever",
"::-internal-media-controls-text-track-list",
+ ":-internal-is-html",
":-internal-list-box",
":-internal-shadow-host-has-appearance",
":-internal-spatial-navigation-focus",
@@ -628,6 +567,7 @@ TEST(CSSSelectorParserTest, UseCountShadowPseudo) {
std::unique_ptr<DummyPageHolder> dummy_holder =
DummyPageHolder::Create(IntSize(500, 500));
Document* doc = &dummy_holder->GetDocument();
+ Page::InsertOrdinaryPageForTesting(&dummy_holder->GetPage());
CSSParserContext* context = CSSParserContext::Create(
kHTMLStandardMode, SecureContextMode::kSecureContext,
CSSParserContext::kLiveProfile, doc);
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_tokenizer_test.cc b/chromium/third_party/blink/renderer/core/css/parser/css_tokenizer_test.cc
index 3cd72175bcc..01e317334bf 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_tokenizer_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_tokenizer_test.cc
@@ -233,8 +233,8 @@ TEST(CSSTokenizerTest, Escapes) {
TEST_TOKENS("\\\f", Delim('\\'), Whitespace());
TEST_TOKENS("\\\r\n", Delim('\\'), Whitespace());
String replacement = FromUChar32(0xFFFD);
- TEST_TOKENS(String("null\\\0", 6), Ident("null" + replacement));
- TEST_TOKENS(String("null\\\0\0", 7),
+ TEST_TOKENS(String("null\\\0", 6u), Ident("null" + replacement));
+ TEST_TOKENS(String("null\\\0\0", 7u),
Ident("null" + replacement + replacement));
TEST_TOKENS("null\\0", Ident("null" + replacement));
TEST_TOKENS("null\\0000", Ident("null" + replacement));
@@ -267,9 +267,9 @@ TEST(CSSTokenizerTest, IdentToken) {
Ident(FromUChar32(0xA0))); // non-breaking space
TEST_TOKENS(FromUChar32(0x1234), Ident(FromUChar32(0x1234)));
TEST_TOKENS(FromUChar32(0x12345), Ident(FromUChar32(0x12345)));
- TEST_TOKENS(String("\0", 1), Ident(FromUChar32(0xFFFD)));
- TEST_TOKENS(String("ab\0c", 4), Ident("ab" + FromUChar32(0xFFFD) + "c"));
- TEST_TOKENS(String("ab\0c", 4), Ident("ab" + FromUChar32(0xFFFD) + "c"));
+ TEST_TOKENS(String("\0", 1u), Ident(FromUChar32(0xFFFD)));
+ TEST_TOKENS(String("ab\0c", 4u), Ident("ab" + FromUChar32(0xFFFD) + "c"));
+ TEST_TOKENS(String("ab\0c", 4u), Ident("ab" + FromUChar32(0xFFFD) + "c"));
}
TEST(CSSTokenizerTest, FunctionToken) {
@@ -344,10 +344,10 @@ TEST(CSSTokenizerTest, StringToken) {
TEST_TOKENS("'bad\rstring", BadString(), Whitespace(), Ident("string"));
TEST_TOKENS("'bad\r\nstring", BadString(), Whitespace(), Ident("string"));
TEST_TOKENS("'bad\fstring", BadString(), Whitespace(), Ident("string"));
- TEST_TOKENS(String("'\0'", 3), GetString(FromUChar32(0xFFFD)));
- TEST_TOKENS(String("'hel\0lo'", 8),
+ TEST_TOKENS(String("'\0'", 3u), GetString(FromUChar32(0xFFFD)));
+ TEST_TOKENS(String("'hel\0lo'", 8u),
GetString("hel" + FromUChar32(0xFFFD) + "lo"));
- TEST_TOKENS(String("'h\\65l\0lo'", 10),
+ TEST_TOKENS(String("'h\\65l\0lo'", 10u),
GetString("hel" + FromUChar32(0xFFFD) + "lo"));
}
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 271b1028f61..3c931168a48 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,30 +7,55 @@
#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/platform/runtime_enabled_features.h"
namespace blink {
namespace {
-bool IsValidVariableReference(CSSParserTokenRange);
+bool IsValidVariableReference(CSSParserTokenRange, bool);
+bool IsValidEnvVariableReference(CSSParserTokenRange, bool);
-bool ClassifyBlock(CSSParserTokenRange range, bool& has_references) {
+bool ClassifyBlock(CSSParserTokenRange range,
+ bool& has_references,
+ bool skip_variables) {
size_t block_stack_size = 0;
while (!range.AtEnd()) {
// First check if this is a valid variable reference, then handle the next
// token accordingly.
- if (range.Peek().GetBlockType() == CSSParserToken::kBlockStart &&
- range.Peek().FunctionId() == CSSValueVar) {
- CSSParserTokenRange block = range.ConsumeBlock();
- if (!IsValidVariableReference(block))
- return false; // Bail if any references are invalid
- has_references = true;
- continue;
+ if (range.Peek().GetBlockType() == CSSParserToken::kBlockStart) {
+ const CSSParserToken& token = range.Peek();
+
+ // A block may have both var and env references. They can also be nested
+ // and used as fallbacks.
+ switch (token.FunctionId()) {
+ case CSSValueVar:
+ if (!IsValidVariableReference(range.ConsumeBlock(), skip_variables))
+ return false; // Invalid reference.
+ has_references = true;
+ continue;
+ case CSSValueEnv:
+ if (!RuntimeEnabledFeatures::CSSEnvironmentVariablesEnabled())
+ return false;
+ if (!IsValidEnvVariableReference(range.ConsumeBlock(),
+ skip_variables))
+ return false; // Invalid reference.
+ has_references = true;
+ continue;
+ default:
+ break;
+ }
}
const CSSParserToken& token = range.Consume();
if (token.GetBlockType() == CSSParserToken::kBlockStart) {
+ // If we are an invalid function then we should skip over any variables
+ // this function contains.
+ if (token.GetType() == CSSParserTokenType::kFunctionToken &&
+ token.FunctionId() == CSSValueInvalid) {
+ skip_variables = true;
+ }
++block_stack_size;
} else if (token.GetBlockType() == CSSParserToken::kBlockEnd) {
--block_stack_size;
@@ -59,8 +84,10 @@ bool ClassifyBlock(CSSParserTokenRange range, bool& has_references) {
return true;
}
-bool IsValidVariableReference(CSSParserTokenRange range) {
+bool IsValidVariableReference(CSSParserTokenRange range, bool skip_variables) {
range.ConsumeWhitespace();
+ if (skip_variables)
+ return false;
if (!CSSVariableParser::IsValidVariableName(
range.ConsumeIncludingWhitespace()))
return false;
@@ -73,7 +100,27 @@ bool IsValidVariableReference(CSSParserTokenRange range) {
return false;
bool has_references = false;
- return ClassifyBlock(range, has_references);
+ return ClassifyBlock(range, has_references, skip_variables);
+}
+
+bool IsValidEnvVariableReference(CSSParserTokenRange range,
+ bool skip_variables) {
+ range.ConsumeWhitespace();
+ if (skip_variables)
+ return false;
+ if (range.ConsumeIncludingWhitespace().GetType() !=
+ CSSParserTokenType::kIdentToken)
+ return false;
+ if (range.AtEnd())
+ return true;
+
+ if (range.Consume().GetType() != kCommaToken)
+ return false;
+ if (range.AtEnd())
+ return false;
+
+ bool has_references = false;
+ return ClassifyBlock(range, has_references, skip_variables);
}
CSSValueID ClassifyVariableRange(CSSParserTokenRange range,
@@ -88,7 +135,7 @@ CSSValueID ClassifyVariableRange(CSSParserTokenRange range,
return id;
}
- if (ClassifyBlock(range, has_references))
+ if (ClassifyBlock(range, has_references, false /* skip_variables */))
return CSSValueInternalVariableValue;
return CSSValueInvalid;
}
@@ -117,7 +164,8 @@ bool CSSVariableParser::ContainsValidVariableReferences(
CSSCustomPropertyDeclaration* CSSVariableParser::ParseDeclarationValue(
const AtomicString& variable_name,
CSSParserTokenRange range,
- bool is_animation_tainted) {
+ bool is_animation_tainted,
+ const CSSParserContext& context) {
if (range.AtEnd())
return nullptr;
@@ -129,7 +177,8 @@ CSSCustomPropertyDeclaration* CSSVariableParser::ParseDeclarationValue(
if (type == CSSValueInternalVariableValue) {
return CSSCustomPropertyDeclaration::Create(
variable_name,
- CSSVariableData::Create(range, is_animation_tainted, has_references));
+ CSSVariableData::Create(range, is_animation_tainted, has_references,
+ context.BaseURL(), context.Charset()));
}
return CSSCustomPropertyDeclaration::Create(variable_name, type);
}
@@ -150,7 +199,8 @@ CSSVariableReferenceValue* CSSVariableParser::ParseRegisteredPropertyValue(
if (require_var_reference && !has_references)
return nullptr;
return CSSVariableReferenceValue::Create(
- CSSVariableData::Create(range, is_animation_tainted, has_references),
+ CSSVariableData::Create(range, is_animation_tainted, has_references,
+ context.BaseURL(), context.Charset()),
context);
}
diff --git a/chromium/third_party/blink/renderer/core/css/parser/css_variable_parser.h b/chromium/third_party/blink/renderer/core/css/parser/css_variable_parser.h
index 8bc2f7d5c1a..15cc9243e0d 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/css_variable_parser.h
+++ b/chromium/third_party/blink/renderer/core/css/parser/css_variable_parser.h
@@ -24,7 +24,8 @@ class CORE_EXPORT CSSVariableParser {
static CSSCustomPropertyDeclaration* ParseDeclarationValue(
const AtomicString&,
CSSParserTokenRange,
- bool is_animation_tainted);
+ bool is_animation_tainted,
+ const CSSParserContext&);
static CSSVariableReferenceValue* ParseRegisteredPropertyValue(
CSSParserTokenRange,
const CSSParserContext&,
diff --git a/chromium/third_party/blink/renderer/core/css/parser/font_variant_east_asian_parser.h b/chromium/third_party/blink/renderer/core/css/parser/font_variant_east_asian_parser.h
index 7394f5a58a1..4877ca89196 100644
--- a/chromium/third_party/blink/renderer/core/css/parser/font_variant_east_asian_parser.h
+++ b/chromium/third_party/blink/renderer/core/css/parser/font_variant_east_asian_parser.h
@@ -16,10 +16,9 @@ class FontVariantEastAsianParser {
public:
FontVariantEastAsianParser()
- : saw_east_asian_form_value_(false),
- saw_east_asian_width_value_(false),
- saw_ruby_value_(false),
- result_(CSSValueList::CreateSpaceSeparated()) {}
+ : east_asian_form_value_(nullptr),
+ east_asian_width_value_(nullptr),
+ ruby_value_(nullptr) {}
enum class ParseResult { kConsumedValue, kDisallowedValue, kUnknownValue };
@@ -32,39 +31,44 @@ class FontVariantEastAsianParser {
case CSSValueJis04:
case CSSValueSimplified:
case CSSValueTraditional:
- if (saw_east_asian_form_value_)
+ if (east_asian_form_value_)
return ParseResult::kDisallowedValue;
- saw_east_asian_form_value_ = true;
- break;
+ east_asian_form_value_ = CSSPropertyParserHelpers::ConsumeIdent(range);
+ return ParseResult::kConsumedValue;
case CSSValueFullWidth:
case CSSValueProportionalWidth:
- if (saw_east_asian_width_value_)
+ if (east_asian_width_value_)
return ParseResult::kDisallowedValue;
- saw_east_asian_width_value_ = true;
- break;
+ east_asian_width_value_ = CSSPropertyParserHelpers::ConsumeIdent(range);
+ return ParseResult::kConsumedValue;
case CSSValueRuby:
- if (saw_ruby_value_)
+ if (ruby_value_)
return ParseResult::kDisallowedValue;
- saw_ruby_value_ = true;
- break;
+ ruby_value_ = CSSPropertyParserHelpers::ConsumeIdent(range);
+ return ParseResult::kConsumedValue;
default:
return ParseResult::kUnknownValue;
}
- result_->Append(*CSSPropertyParserHelpers::ConsumeIdent(range));
- return ParseResult::kConsumedValue;
}
CSSValue* FinalizeValue() {
- if (!result_->length())
+ CSSValueList* result = CSSValueList::CreateSpaceSeparated();
+ if (east_asian_form_value_)
+ result->Append(*east_asian_form_value_.Release());
+ if (east_asian_width_value_)
+ result->Append(*east_asian_width_value_.Release());
+ if (ruby_value_)
+ result->Append(*ruby_value_.Release());
+
+ if (!result->length())
return CSSIdentifierValue::Create(CSSValueNormal);
- return result_.Release();
+ return result;
}
private:
- bool saw_east_asian_form_value_;
- bool saw_east_asian_width_value_;
- bool saw_ruby_value_;
- Member<CSSValueList> result_;
+ Member<CSSIdentifierValue> east_asian_form_value_;
+ Member<CSSIdentifierValue> east_asian_width_value_;
+ Member<CSSIdentifierValue> ruby_value_;
};
} // namespace blink
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 c9bedf95a82..a651b7ff521 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
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_grid.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
+#include "third_party/blink/renderer/core/style/style_svg_resource.h"
#include "third_party/blink/renderer/core/style_property_shorthand.h"
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 f9b66b3c5e0..218c46468cc 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
@@ -416,116 +416,6 @@ bool ConsumeTranslate3d(CSSParserTokenRange& args,
return true;
}
-CSSValue* ConsumeTransformValue(CSSParserTokenRange& range,
- const CSSParserContext& context,
- bool use_legacy_parsing) {
- CSSValueID function_id = range.Peek().FunctionId();
- if (function_id == CSSValueInvalid)
- return nullptr;
- CSSParserTokenRange args = CSSPropertyParserHelpers::ConsumeFunction(range);
- if (args.AtEnd())
- return nullptr;
- CSSFunctionValue* transform_value = CSSFunctionValue::Create(function_id);
- CSSValue* parsed_value = nullptr;
- switch (function_id) {
- case CSSValueRotate:
- case CSSValueRotateX:
- case CSSValueRotateY:
- case CSSValueRotateZ:
- case CSSValueSkewX:
- case CSSValueSkewY:
- case CSSValueSkew:
- parsed_value = CSSPropertyParserHelpers::ConsumeAngle(
- args, &context, WebFeature::kUnitlessZeroAngleTransform);
- if (!parsed_value)
- return nullptr;
- if (function_id == CSSValueSkew &&
- CSSPropertyParserHelpers::ConsumeCommaIncludingWhitespace(args)) {
- transform_value->Append(*parsed_value);
- parsed_value = CSSPropertyParserHelpers::ConsumeAngle(
- args, &context, WebFeature::kUnitlessZeroAngleTransform);
- if (!parsed_value)
- return nullptr;
- }
- break;
- case CSSValueScaleX:
- case CSSValueScaleY:
- case CSSValueScaleZ:
- case CSSValueScale:
- parsed_value =
- CSSPropertyParserHelpers::ConsumeNumber(args, kValueRangeAll);
- if (!parsed_value)
- return nullptr;
- if (function_id == CSSValueScale &&
- CSSPropertyParserHelpers::ConsumeCommaIncludingWhitespace(args)) {
- transform_value->Append(*parsed_value);
- parsed_value =
- CSSPropertyParserHelpers::ConsumeNumber(args, kValueRangeAll);
- if (!parsed_value)
- return nullptr;
- }
- break;
- case CSSValuePerspective:
- if (!ConsumePerspective(args, context, transform_value,
- use_legacy_parsing)) {
- return nullptr;
- }
- break;
- case CSSValueTranslateX:
- case CSSValueTranslateY:
- case CSSValueTranslate:
- parsed_value = CSSPropertyParserHelpers::ConsumeLengthOrPercent(
- args, context.Mode(), kValueRangeAll);
- if (!parsed_value)
- return nullptr;
- if (function_id == CSSValueTranslate &&
- CSSPropertyParserHelpers::ConsumeCommaIncludingWhitespace(args)) {
- transform_value->Append(*parsed_value);
- parsed_value = CSSPropertyParserHelpers::ConsumeLengthOrPercent(
- args, context.Mode(), kValueRangeAll);
- if (!parsed_value)
- return nullptr;
- }
- break;
- case CSSValueTranslateZ:
- parsed_value = CSSPropertyParserHelpers::ConsumeLength(
- args, context.Mode(), kValueRangeAll);
- break;
- case CSSValueMatrix:
- case CSSValueMatrix3d:
- if (!ConsumeNumbers(args, transform_value,
- (function_id == CSSValueMatrix3d) ? 16 : 6)) {
- return nullptr;
- }
- break;
- case CSSValueScale3d:
- if (!ConsumeNumbers(args, transform_value, 3))
- return nullptr;
- break;
- case CSSValueRotate3d:
- if (!ConsumeNumbers(args, transform_value, 3) ||
- !CSSPropertyParserHelpers::ConsumeCommaIncludingWhitespace(args)) {
- return nullptr;
- }
- parsed_value = CSSPropertyParserHelpers::ConsumeAngle(
- args, &context, WebFeature::kUnitlessZeroAngleTransform);
- if (!parsed_value)
- return nullptr;
- break;
- case CSSValueTranslate3d:
- if (!ConsumeTranslate3d(args, context.Mode(), transform_value))
- return nullptr;
- break;
- default:
- return nullptr;
- }
- if (parsed_value)
- transform_value->Append(*parsed_value);
- if (!args.AtEnd())
- return nullptr;
- return transform_value;
-}
-
} // namespace
bool IsSelfPositionKeyword(CSSValueID id) {
@@ -750,14 +640,7 @@ CSSPrimitiveValue* ConsumeLengthOrPercentCountNegative(
CSSPrimitiveValue* result =
ConsumeLengthOrPercent(range, context.Mode(), kValueRangeNonNegative,
CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
- if (result || !negative_size)
- return result;
-
- result =
- ConsumeLengthOrPercent(range, context.Mode(), kValueRangeAll,
- CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
-
- if (result)
+ if (!result && negative_size)
context.Count(*negative_size);
return result;
}
@@ -777,6 +660,8 @@ CSSValue* ConsumeBackgroundSize(CSSParserTokenRange& range,
horizontal =
ConsumeLengthOrPercentCountNegative(range, context, negative_size);
}
+ if (!horizontal)
+ return nullptr;
CSSValue* vertical = nullptr;
if (!range.AtEnd()) {
@@ -2463,6 +2348,116 @@ CSSValue* ConsumeTextDecorationLine(CSSParserTokenRange& range) {
return list;
}
+CSSValue* ConsumeTransformValue(CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ bool use_legacy_parsing) {
+ CSSValueID function_id = range.Peek().FunctionId();
+ if (function_id == CSSValueInvalid)
+ return nullptr;
+ CSSParserTokenRange args = CSSPropertyParserHelpers::ConsumeFunction(range);
+ if (args.AtEnd())
+ return nullptr;
+ CSSFunctionValue* transform_value = CSSFunctionValue::Create(function_id);
+ CSSValue* parsed_value = nullptr;
+ switch (function_id) {
+ case CSSValueRotate:
+ case CSSValueRotateX:
+ case CSSValueRotateY:
+ case CSSValueRotateZ:
+ case CSSValueSkewX:
+ case CSSValueSkewY:
+ case CSSValueSkew:
+ parsed_value = CSSPropertyParserHelpers::ConsumeAngle(
+ args, &context, WebFeature::kUnitlessZeroAngleTransform);
+ if (!parsed_value)
+ return nullptr;
+ if (function_id == CSSValueSkew &&
+ CSSPropertyParserHelpers::ConsumeCommaIncludingWhitespace(args)) {
+ transform_value->Append(*parsed_value);
+ parsed_value = CSSPropertyParserHelpers::ConsumeAngle(
+ args, &context, WebFeature::kUnitlessZeroAngleTransform);
+ if (!parsed_value)
+ return nullptr;
+ }
+ break;
+ case CSSValueScaleX:
+ case CSSValueScaleY:
+ case CSSValueScaleZ:
+ case CSSValueScale:
+ parsed_value =
+ CSSPropertyParserHelpers::ConsumeNumber(args, kValueRangeAll);
+ if (!parsed_value)
+ return nullptr;
+ if (function_id == CSSValueScale &&
+ CSSPropertyParserHelpers::ConsumeCommaIncludingWhitespace(args)) {
+ transform_value->Append(*parsed_value);
+ parsed_value =
+ CSSPropertyParserHelpers::ConsumeNumber(args, kValueRangeAll);
+ if (!parsed_value)
+ return nullptr;
+ }
+ break;
+ case CSSValuePerspective:
+ if (!ConsumePerspective(args, context, transform_value,
+ use_legacy_parsing)) {
+ return nullptr;
+ }
+ break;
+ case CSSValueTranslateX:
+ case CSSValueTranslateY:
+ case CSSValueTranslate:
+ parsed_value = CSSPropertyParserHelpers::ConsumeLengthOrPercent(
+ args, context.Mode(), kValueRangeAll);
+ if (!parsed_value)
+ return nullptr;
+ if (function_id == CSSValueTranslate &&
+ CSSPropertyParserHelpers::ConsumeCommaIncludingWhitespace(args)) {
+ transform_value->Append(*parsed_value);
+ parsed_value = CSSPropertyParserHelpers::ConsumeLengthOrPercent(
+ args, context.Mode(), kValueRangeAll);
+ if (!parsed_value)
+ return nullptr;
+ }
+ break;
+ case CSSValueTranslateZ:
+ parsed_value = CSSPropertyParserHelpers::ConsumeLength(
+ args, context.Mode(), kValueRangeAll);
+ break;
+ case CSSValueMatrix:
+ case CSSValueMatrix3d:
+ if (!ConsumeNumbers(args, transform_value,
+ (function_id == CSSValueMatrix3d) ? 16 : 6)) {
+ return nullptr;
+ }
+ break;
+ case CSSValueScale3d:
+ if (!ConsumeNumbers(args, transform_value, 3))
+ return nullptr;
+ break;
+ case CSSValueRotate3d:
+ if (!ConsumeNumbers(args, transform_value, 3) ||
+ !CSSPropertyParserHelpers::ConsumeCommaIncludingWhitespace(args)) {
+ return nullptr;
+ }
+ parsed_value = CSSPropertyParserHelpers::ConsumeAngle(
+ args, &context, WebFeature::kUnitlessZeroAngleTransform);
+ if (!parsed_value)
+ return nullptr;
+ break;
+ case CSSValueTranslate3d:
+ if (!ConsumeTranslate3d(args, context.Mode(), transform_value))
+ return nullptr;
+ break;
+ default:
+ return nullptr;
+ }
+ if (parsed_value)
+ transform_value->Append(*parsed_value);
+ if (!args.AtEnd())
+ return nullptr;
+ return transform_value;
+}
+
CSSValue* ConsumeTransformList(CSSParserTokenRange& range,
const CSSParserContext& context,
const CSSParserLocalContext& local_context) {
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 a68f3b6652f..130ab18ecc0 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
@@ -213,6 +213,9 @@ bool ConsumeRadii(CSSValue* horizontal_radii[4],
CSSValue* ConsumeTextDecorationLine(CSSParserTokenRange&);
+CSSValue* ConsumeTransformValue(CSSParserTokenRange&,
+ const CSSParserContext&,
+ bool use_legacy_parsing);
CSSValue* ConsumeTransformList(CSSParserTokenRange&,
const CSSParserContext&,
const CSSParserLocalContext&);
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 2292232de94..b93ab5a6a82 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
@@ -13,6 +13,7 @@ namespace blink {
TEST(CSSParsingUtilsTest, BasicShapeUseCount) {
std::unique_ptr<DummyPageHolder> dummy_page_holder =
DummyPageHolder::Create(IntSize(800, 600));
+ Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
Document& document = dummy_page_holder->GetDocument();
WebFeature feature = WebFeature::kCSSBasicShape;
EXPECT_FALSE(UseCounter::IsCounted(document, feature));
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/baseline_shift_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/baseline_shift_custom.cc
index 242da103d23..26734d4bc0d 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/baseline_shift_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/baseline_shift_custom.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/css/css_value_list.h"
#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
#include "third_party/blink/renderer/core/css/properties/computed_style_utils.h"
+#include "third_party/blink/renderer/core/css/resolver/style_builder_converter.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
@@ -42,5 +43,39 @@ const CSSValue* BaselineShift::CSSValueFromComputedStyleInternal(
return nullptr;
}
+void BaselineShift::ApplyInherit(StyleResolverState& state) const {
+ const SVGComputedStyle& parent_svg_style = state.ParentStyle()->SvgStyle();
+ EBaselineShift baseline_shift = parent_svg_style.BaselineShift();
+ SVGComputedStyle& svg_style = state.Style()->AccessSVGStyle();
+ svg_style.SetBaselineShift(baseline_shift);
+ if (baseline_shift == BS_LENGTH)
+ svg_style.SetBaselineShiftValue(parent_svg_style.BaselineShiftValue());
+}
+
+void BaselineShift::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ SVGComputedStyle& svg_style = state.Style()->AccessSVGStyle();
+ if (!value.IsIdentifierValue()) {
+ svg_style.SetBaselineShift(BS_LENGTH);
+ svg_style.SetBaselineShiftValue(StyleBuilderConverter::ConvertLength(
+ state, ToCSSPrimitiveValue(value)));
+ return;
+ }
+ switch (ToCSSIdentifierValue(value).GetValueID()) {
+ case CSSValueBaseline:
+ svg_style.SetBaselineShift(BS_LENGTH);
+ svg_style.SetBaselineShiftValue(Length(kFixed));
+ return;
+ case CSSValueSub:
+ svg_style.SetBaselineShift(BS_SUB);
+ return;
+ case CSSValueSuper:
+ svg_style.SetBaselineShift(BS_SUPER);
+ return;
+ default:
+ NOTREACHED();
+ }
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/block_size_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/block_size_custom.cc
index ae88c121e49..0bf6c111c7a 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/block_size_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/block_size_custom.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
namespace blink {
namespace CSSLonghand {
@@ -17,5 +18,10 @@ const CSSValue* BlockSize::ParseSingleValue(
return CSSParsingUtils::ConsumeWidthOrHeight(range, context);
}
+bool BlockSize::IsLayoutDependent(const ComputedStyle* style,
+ LayoutObject* layout_object) const {
+ return layout_object && layout_object->IsBox();
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/border_block_end_color_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/border_block_end_color_custom.cc
new file mode 100644
index 00000000000..584cd2e7b9b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/border_block_end_color_custom.cc
@@ -0,0 +1,25 @@
+// 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/css/properties/longhands/border_block_end_color.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+
+class CSSParserLocalContext;
+
+namespace CSSLonghand {
+
+const CSSValue* BorderBlockEndColor::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return CSSPropertyParserHelpers::ConsumeColor(range, context.Mode());
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/border_block_end_width_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/border_block_end_width_custom.cc
new file mode 100644
index 00000000000..b51c04782ef
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/border_block_end_width_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/longhands/border_block_end_width.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSLonghand {
+
+const CSSValue* BorderBlockEndWidth::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return CSSParsingUtils::ConsumeBorderWidth(
+ range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/border_block_start_color_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/border_block_start_color_custom.cc
new file mode 100644
index 00000000000..30d384981f3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/border_block_start_color_custom.cc
@@ -0,0 +1,25 @@
+// 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/css/properties/longhands/border_block_start_color.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+
+class CSSParserLocalContext;
+
+namespace CSSLonghand {
+
+const CSSValue* BorderBlockStartColor::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return CSSPropertyParserHelpers::ConsumeColor(range, context.Mode());
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/border_block_start_width_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/border_block_start_width_custom.cc
new file mode 100644
index 00000000000..a4bc114343b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/border_block_start_width_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/longhands/border_block_start_width.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSLonghand {
+
+const CSSValue* BorderBlockStartWidth::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return CSSParsingUtils::ConsumeBorderWidth(
+ range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/border_image_source_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/border_image_source_custom.cc
index 98c7f78a7a9..89c113006e0 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/border_image_source_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/border_image_source_custom.cc
@@ -38,5 +38,11 @@ const CSSValue* BorderImageSource::InitialValue() const {
return &value;
}
+void BorderImageSource::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ state.Style()->SetBorderImageSource(
+ state.GetStyleImage(CSSPropertyBorderImageSource, value));
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/border_inline_end_color_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/border_inline_end_color_custom.cc
new file mode 100644
index 00000000000..250d1d60b90
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/border_inline_end_color_custom.cc
@@ -0,0 +1,25 @@
+// 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/css/properties/longhands/border_inline_end_color.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+
+class CSSParserLocalContext;
+
+namespace CSSLonghand {
+
+const CSSValue* BorderInlineEndColor::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return CSSPropertyParserHelpers::ConsumeColor(range, context.Mode());
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/border_inline_end_width_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/border_inline_end_width_custom.cc
new file mode 100644
index 00000000000..9b239eac685
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/border_inline_end_width_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/longhands/border_inline_end_width.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSLonghand {
+
+const CSSValue* BorderInlineEndWidth::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return CSSParsingUtils::ConsumeBorderWidth(
+ range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/border_inline_start_color_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/border_inline_start_color_custom.cc
new file mode 100644
index 00000000000..927a86240e3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/border_inline_start_color_custom.cc
@@ -0,0 +1,25 @@
+// 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/css/properties/longhands/border_inline_start_color.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+
+class CSSParserLocalContext;
+
+namespace CSSLonghand {
+
+const CSSValue* BorderInlineStartColor::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return CSSPropertyParserHelpers::ConsumeColor(range, context.Mode());
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/border_inline_start_width_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/border_inline_start_width_custom.cc
new file mode 100644
index 00000000000..803070f0843
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/border_inline_start_width_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/longhands/border_inline_start_width.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSLonghand {
+
+const CSSValue* BorderInlineStartWidth::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return CSSParsingUtils::ConsumeBorderWidth(
+ range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/caret_color_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/caret_color_custom.cc
index db87c7fe11c..bd1010e20f8 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/caret_color_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/caret_color_custom.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/css/css_color_value.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/css/resolver/style_builder_converter.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
@@ -51,5 +52,33 @@ const CSSValue* CaretColor::CSSValueFromComputedStyleInternal(
return cssvalue::CSSColorValue::Create(color.Rgb());
}
+void CaretColor::ApplyInitial(StyleResolverState& state) const {
+ StyleAutoColor color = StyleAutoColor::AutoColor();
+ if (state.ApplyPropertyToRegularStyle())
+ state.Style()->SetCaretColor(color);
+ if (state.ApplyPropertyToVisitedLinkStyle())
+ state.Style()->SetVisitedLinkCaretColor(color);
+}
+
+void CaretColor::ApplyInherit(StyleResolverState& state) const {
+ StyleAutoColor color = state.ParentStyle()->CaretColor();
+ if (state.ApplyPropertyToRegularStyle())
+ state.Style()->SetCaretColor(color);
+ if (state.ApplyPropertyToVisitedLinkStyle())
+ state.Style()->SetVisitedLinkCaretColor(color);
+}
+
+void CaretColor::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ if (state.ApplyPropertyToRegularStyle()) {
+ state.Style()->SetCaretColor(
+ StyleBuilderConverter::ConvertStyleAutoColor(state, value));
+ }
+ if (state.ApplyPropertyToVisitedLinkStyle()) {
+ state.Style()->SetVisitedLinkCaretColor(
+ StyleBuilderConverter::ConvertStyleAutoColor(state, value, true));
+ }
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/clip_path_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/clip_path_custom.cc
index 353f51daffa..cde4e5ba9bc 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/clip_path_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/clip_path_custom.cc
@@ -9,6 +9,8 @@
#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.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/shape_clip_path_operation.h"
namespace blink {
namespace CSSLonghand {
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/color_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/color_custom.cc
index 4bd493eaf14..8061da94d70 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/color_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/color_custom.cc
@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_mode.h"
#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/css/resolver/style_builder_converter.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
@@ -40,5 +41,37 @@ const CSSValue* Color::CSSValueFromComputedStyleInternal(
: style.GetColor().Rgb());
}
+void Color::ApplyInitial(StyleResolverState& state) const {
+ blink::Color color = ComputedStyleInitialValues::InitialColor();
+ if (state.ApplyPropertyToRegularStyle())
+ state.Style()->SetColor(color);
+ if (state.ApplyPropertyToVisitedLinkStyle())
+ state.Style()->SetVisitedLinkColor(color);
+}
+
+void Color::ApplyInherit(StyleResolverState& state) const {
+ blink::Color color = state.ParentStyle()->GetColor();
+ if (state.ApplyPropertyToRegularStyle())
+ state.Style()->SetColor(color);
+ if (state.ApplyPropertyToVisitedLinkStyle())
+ state.Style()->SetVisitedLinkColor(color);
+}
+
+void Color::ApplyValue(StyleResolverState& state, const CSSValue& value) const {
+ // As per the spec, 'color: currentColor' is treated as 'color: inherit'
+ if (value.IsIdentifierValue() &&
+ ToCSSIdentifierValue(value).GetValueID() == CSSValueCurrentcolor) {
+ ApplyInherit(state);
+ return;
+ }
+
+ if (state.ApplyPropertyToRegularStyle())
+ state.Style()->SetColor(StyleBuilderConverter::ConvertColor(state, value));
+ if (state.ApplyPropertyToVisitedLinkStyle()) {
+ state.Style()->SetVisitedLinkColor(
+ StyleBuilderConverter::ConvertColor(state, value, true));
+ }
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/content_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/content_custom.cc
index af51dda04f9..a9efadf71c6 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/content_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/content_custom.cc
@@ -119,5 +119,95 @@ const CSSValue* Content::CSSValueFromComputedStyleInternal(
return ComputedStyleUtils::ValueForContentData(style);
}
+void Content::ApplyInitial(StyleResolverState& state) const {
+ state.Style()->SetContent(nullptr);
+}
+
+void Content::ApplyInherit(StyleResolverState& state) const {
+ // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not.
+ // This note is a reminder that eventually "inherit" needs to be supported.
+}
+
+void Content::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ if (value.IsIdentifierValue()) {
+ DCHECK(ToCSSIdentifierValue(value).GetValueID() == CSSValueNormal ||
+ ToCSSIdentifierValue(value).GetValueID() == CSSValueNone);
+ state.Style()->SetContent(nullptr);
+ return;
+ }
+
+ ContentData* first_content = nullptr;
+ ContentData* prev_content = nullptr;
+ for (auto& item : ToCSSValueList(value)) {
+ ContentData* next_content = nullptr;
+ if (item->IsImageGeneratorValue() || item->IsImageSetValue() ||
+ item->IsImageValue()) {
+ next_content =
+ ContentData::Create(state.GetStyleImage(CSSPropertyContent, *item));
+ } else if (item->IsCounterValue()) {
+ const cssvalue::CSSCounterValue* counter_value =
+ cssvalue::ToCSSCounterValue(item.Get());
+ const auto list_style_type =
+ CssValueIDToPlatformEnum<EListStyleType>(counter_value->ListStyle());
+ std::unique_ptr<CounterContent> counter =
+ std::make_unique<CounterContent>(
+ AtomicString(counter_value->Identifier()), list_style_type,
+ AtomicString(counter_value->Separator()));
+ next_content = ContentData::Create(std::move(counter));
+ } else if (item->IsIdentifierValue()) {
+ QuoteType quote_type;
+ switch (ToCSSIdentifierValue(*item).GetValueID()) {
+ default:
+ NOTREACHED();
+ FALLTHROUGH;
+ case CSSValueOpenQuote:
+ quote_type = QuoteType::kOpen;
+ break;
+ case CSSValueCloseQuote:
+ quote_type = QuoteType::kClose;
+ break;
+ case CSSValueNoOpenQuote:
+ quote_type = QuoteType::kNoOpen;
+ break;
+ case CSSValueNoCloseQuote:
+ quote_type = QuoteType::kNoClose;
+ break;
+ }
+ next_content = ContentData::Create(quote_type);
+ } else {
+ String string;
+ if (item->IsFunctionValue()) {
+ const CSSFunctionValue* function_value = ToCSSFunctionValue(item.Get());
+ DCHECK_EQ(function_value->FunctionType(), CSSValueAttr);
+ state.Style()->SetUnique();
+ // TODO: Can a namespace be specified for an attr(foo)?
+ QualifiedName attr(
+ g_null_atom, ToCSSCustomIdentValue(function_value->Item(0)).Value(),
+ g_null_atom);
+ const AtomicString& value = state.GetElement()->getAttribute(attr);
+ string = value.IsNull() ? g_empty_string : value.GetString();
+ } else {
+ string = ToCSSStringValue(*item).Value();
+ }
+ if (prev_content && prev_content->IsText()) {
+ TextContentData* text_content = ToTextContentData(prev_content);
+ text_content->SetText(text_content->GetText() + string);
+ continue;
+ }
+ next_content = ContentData::Create(string);
+ }
+
+ if (!first_content)
+ first_content = next_content;
+ else
+ prev_content->SetNext(next_content);
+
+ prev_content = next_content;
+ }
+ DCHECK(first_content);
+ state.Style()->SetContent(first_content);
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/cursor_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/cursor_custom.cc
index 4b2b8d648b4..ae8607ec0ff 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/cursor_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/cursor_custom.cc
@@ -27,10 +27,10 @@ const CSSValue* Cursor::ParseSingleValue(CSSParserTokenRange& range,
IntPoint hot_spot(-1, -1);
bool hot_spot_specified = false;
if (CSSPropertyParserHelpers::ConsumeNumberRaw(range, num)) {
- hot_spot.SetX(int(num));
+ hot_spot.SetX(clampTo<int>(num));
if (!CSSPropertyParserHelpers::ConsumeNumberRaw(range, num))
return nullptr;
- hot_spot.SetY(int(num));
+ hot_spot.SetY(clampTo<int>(num));
hot_spot_specified = true;
}
@@ -99,5 +99,37 @@ const CSSValue* Cursor::CSSValueFromComputedStyleInternal(
return value;
}
+void Cursor::ApplyInitial(StyleResolverState& state) const {
+ state.Style()->ClearCursorList();
+ state.Style()->SetCursor(ComputedStyleInitialValues::InitialCursor());
+}
+
+void Cursor::ApplyInherit(StyleResolverState& state) const {
+ state.Style()->SetCursor(state.ParentStyle()->Cursor());
+ state.Style()->SetCursorList(state.ParentStyle()->Cursors());
+}
+
+void Cursor::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ state.Style()->ClearCursorList();
+ if (value.IsValueList()) {
+ state.Style()->SetCursor(ECursor::kAuto);
+ for (const auto& item : ToCSSValueList(value)) {
+ if (item->IsCursorImageValue()) {
+ const cssvalue::CSSCursorImageValue& cursor =
+ cssvalue::ToCSSCursorImageValue(*item);
+ const CSSValue& image = cursor.ImageValue();
+ state.Style()->AddCursor(state.GetStyleImage(CSSPropertyCursor, image),
+ cursor.HotSpotSpecified(), cursor.HotSpot());
+ } else {
+ state.Style()->SetCursor(
+ ToCSSIdentifierValue(*item).ConvertTo<ECursor>());
+ }
+ }
+ } else {
+ state.Style()->SetCursor(ToCSSIdentifierValue(value).ConvertTo<ECursor>());
+ }
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/direction_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/direction_custom.cc
index ed8e51db52d..7cd95e7323f 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/direction_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/direction_custom.cc
@@ -16,5 +16,11 @@ const CSSValue* Direction::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.Direction());
}
+void Direction::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ state.Style()->SetDirection(
+ ToCSSIdentifierValue(value).ConvertTo<TextDirection>());
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/display_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/display_custom.cc
index 5ce16e23876..4d8e2fc6825 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/display_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/display_custom.cc
@@ -59,5 +59,38 @@ const CSSValue* Display::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.Display());
}
+void Display::ApplyInitial(StyleResolverState& state) const {
+ state.Style()->SetDisplay(ComputedStyleInitialValues::InitialDisplay());
+ state.Style()->SetDisplayLayoutCustomName(
+ ComputedStyleInitialValues::InitialDisplayLayoutCustomName());
+}
+
+void Display::ApplyInherit(StyleResolverState& state) const {
+ state.Style()->SetDisplay(state.ParentStyle()->Display());
+ state.Style()->SetDisplayLayoutCustomName(
+ state.ParentStyle()->DisplayLayoutCustomName());
+}
+
+void Display::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ if (value.IsIdentifierValue()) {
+ state.Style()->SetDisplay(
+ ToCSSIdentifierValue(value).ConvertTo<EDisplay>());
+ state.Style()->SetDisplayLayoutCustomName(
+ ComputedStyleInitialValues::InitialDisplayLayoutCustomName());
+ return;
+ }
+
+ DCHECK(value.IsLayoutFunctionValue());
+ const cssvalue::CSSLayoutFunctionValue& layout_function_value =
+ cssvalue::ToCSSLayoutFunctionValue(value);
+
+ EDisplay display = layout_function_value.IsInline()
+ ? EDisplay::kInlineLayoutCustom
+ : EDisplay::kLayoutCustom;
+ state.Style()->SetDisplay(display);
+ state.Style()->SetDisplayLayoutCustomName(layout_function_value.GetName());
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/grid_template_areas_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/grid_template_areas_custom.cc
index fb868d561aa..67153f84505 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/grid_template_areas_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/grid_template_areas_custom.cc
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
#include "third_party/blink/renderer/core/css/properties/computed_style_utils.h"
#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
+#include "third_party/blink/renderer/core/css/resolver/style_builder_converter.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/style/grid_area.h"
@@ -59,5 +60,54 @@ const CSSValue* GridTemplateAreas::CSSValueFromComputedStyleInternal(
style.NamedGridAreaColumnCount());
}
+void GridTemplateAreas::ApplyInitial(StyleResolverState& state) const {
+ state.Style()->SetNamedGridArea(
+ ComputedStyleInitialValues::InitialNamedGridArea());
+ state.Style()->SetNamedGridAreaRowCount(
+ ComputedStyleInitialValues::InitialNamedGridAreaRowCount());
+ state.Style()->SetNamedGridAreaColumnCount(
+ ComputedStyleInitialValues::InitialNamedGridAreaColumnCount());
+}
+
+void GridTemplateAreas::ApplyInherit(StyleResolverState& state) const {
+ state.Style()->SetNamedGridArea(state.ParentStyle()->NamedGridArea());
+ state.Style()->SetNamedGridAreaRowCount(
+ state.ParentStyle()->NamedGridAreaRowCount());
+ state.Style()->SetNamedGridAreaColumnCount(
+ state.ParentStyle()->NamedGridAreaColumnCount());
+}
+
+void GridTemplateAreas::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ if (value.IsIdentifierValue()) {
+ // FIXME: Shouldn't we clear the grid-area values
+ DCHECK_EQ(ToCSSIdentifierValue(value).GetValueID(), CSSValueNone);
+ return;
+ }
+
+ const CSSGridTemplateAreasValue& grid_template_areas_value =
+ ToCSSGridTemplateAreasValue(value);
+ const NamedGridAreaMap& new_named_grid_areas =
+ grid_template_areas_value.GridAreaMap();
+
+ NamedGridLinesMap named_grid_column_lines;
+ NamedGridLinesMap named_grid_row_lines;
+ StyleBuilderConverter::ConvertOrderedNamedGridLinesMapToNamedGridLinesMap(
+ state.Style()->OrderedNamedGridColumnLines(), named_grid_column_lines);
+ StyleBuilderConverter::ConvertOrderedNamedGridLinesMapToNamedGridLinesMap(
+ state.Style()->OrderedNamedGridRowLines(), named_grid_row_lines);
+ StyleBuilderConverter::CreateImplicitNamedGridLinesFromGridArea(
+ new_named_grid_areas, named_grid_column_lines, kForColumns);
+ StyleBuilderConverter::CreateImplicitNamedGridLinesFromGridArea(
+ new_named_grid_areas, named_grid_row_lines, kForRows);
+ state.Style()->SetNamedGridColumnLines(named_grid_column_lines);
+ state.Style()->SetNamedGridRowLines(named_grid_row_lines);
+
+ state.Style()->SetNamedGridArea(new_named_grid_areas);
+ state.Style()->SetNamedGridAreaRowCount(grid_template_areas_value.RowCount());
+ state.Style()->SetNamedGridAreaColumnCount(
+ grid_template_areas_value.ColumnCount());
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/inline_size_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/inline_size_custom.cc
index 5d0386051f2..5b7d8f892d8 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/inline_size_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/inline_size_custom.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
namespace blink {
namespace CSSLonghand {
@@ -17,5 +18,10 @@ const CSSValue* InlineSize::ParseSingleValue(
return CSSParsingUtils::ConsumeWidthOrHeight(range, context);
}
+bool InlineSize::IsLayoutDependent(const ComputedStyle* style,
+ LayoutObject* layout_object) const {
+ return layout_object && layout_object->IsBox();
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/inset_block_end_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/inset_block_end_custom.cc
new file mode 100644
index 00000000000..631aa57ae9e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/inset_block_end_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/longhands/inset_block_end.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSLonghand {
+
+const CSSValue* InsetBlockEnd::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return CSSParsingUtils::ConsumeMarginOrOffset(
+ range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/inset_block_start_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/inset_block_start_custom.cc
new file mode 100644
index 00000000000..27cbd329d83
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/inset_block_start_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/longhands/inset_block_start.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSLonghand {
+
+const CSSValue* InsetBlockStart::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return CSSParsingUtils::ConsumeMarginOrOffset(
+ range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/inset_inline_end_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/inset_inline_end_custom.cc
new file mode 100644
index 00000000000..6b1113d3795
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/inset_inline_end_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/longhands/inset_inline_end.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSLonghand {
+
+const CSSValue* InsetInlineEnd::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return CSSParsingUtils::ConsumeMarginOrOffset(
+ range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/inset_inline_start_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/inset_inline_start_custom.cc
new file mode 100644
index 00000000000..2a394eba3d0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/inset_inline_start_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/longhands/inset_inline_start.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSLonghand {
+
+const CSSValue* InsetInlineStart::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return CSSParsingUtils::ConsumeMarginOrOffset(
+ range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/list_style_image_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/list_style_image_custom.cc
index 1af5930c6d8..8563f505af3 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/list_style_image_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/list_style_image_custom.cc
@@ -31,5 +31,11 @@ const CSSValue* ListStyleImage::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(CSSValueNone);
}
+void ListStyleImage::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ state.Style()->SetListStyleImage(
+ state.GetStyleImage(CSSPropertyListStyleImage, value));
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/margin_block_end_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/margin_block_end_custom.cc
new file mode 100644
index 00000000000..1472ef90e71
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/margin_block_end_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/longhands/margin_block_end.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSLonghand {
+
+const CSSValue* MarginBlockEnd::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return CSSParsingUtils::ConsumeMarginOrOffset(
+ range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/margin_block_start_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/margin_block_start_custom.cc
new file mode 100644
index 00000000000..1cea46eee03
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/margin_block_start_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/longhands/margin_block_start.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSLonghand {
+
+const CSSValue* MarginBlockStart::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return CSSParsingUtils::ConsumeMarginOrOffset(
+ range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/margin_inline_end_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/margin_inline_end_custom.cc
new file mode 100644
index 00000000000..5dd6bdcbf1a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/margin_inline_end_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/longhands/margin_inline_end.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSLonghand {
+
+const CSSValue* MarginInlineEnd::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return CSSParsingUtils::ConsumeMarginOrOffset(
+ range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/margin_inline_start_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/margin_inline_start_custom.cc
new file mode 100644
index 00000000000..c4134551d94
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/margin_inline_start_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/longhands/margin_inline_start.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSLonghand {
+
+const CSSValue* MarginInlineStart::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return CSSParsingUtils::ConsumeMarginOrOffset(
+ range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/outline_style_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/outline_style_custom.cc
index 8bd75d73eec..85ebb2889bf 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/outline_style_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/outline_style_custom.cc
@@ -21,5 +21,25 @@ const CSSValue* OutlineStyle::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.OutlineStyle());
}
+void OutlineStyle::ApplyInitial(StyleResolverState& state) const {
+ state.Style()->SetOutlineStyleIsAuto(
+ ComputedStyleInitialValues::InitialOutlineStyleIsAuto());
+ state.Style()->SetOutlineStyle(EBorderStyle::kNone);
+}
+
+void OutlineStyle::ApplyInherit(StyleResolverState& state) const {
+ state.Style()->SetOutlineStyleIsAuto(
+ state.ParentStyle()->OutlineStyleIsAuto());
+ state.Style()->SetOutlineStyle(state.ParentStyle()->OutlineStyle());
+}
+
+void OutlineStyle::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
+ state.Style()->SetOutlineStyleIsAuto(
+ static_cast<bool>(identifier_value.ConvertTo<OutlineIsAuto>()));
+ state.Style()->SetOutlineStyle(identifier_value.ConvertTo<EBorderStyle>());
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/padding_block_end_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/padding_block_end_custom.cc
new file mode 100644
index 00000000000..d0764c3e0bb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/padding_block_end_custom.cc
@@ -0,0 +1,25 @@
+// 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/css/properties/longhands/padding_block_end.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSLonghand {
+
+const CSSValue* PaddingBlockEnd::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return ConsumeLengthOrPercent(
+ range, context.Mode(), kValueRangeNonNegative,
+ CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/padding_block_start_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/padding_block_start_custom.cc
new file mode 100644
index 00000000000..b431bcda79e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/padding_block_start_custom.cc
@@ -0,0 +1,25 @@
+// 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/css/properties/longhands/padding_block_start.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSLonghand {
+
+const CSSValue* PaddingBlockStart::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return ConsumeLengthOrPercent(
+ range, context.Mode(), kValueRangeNonNegative,
+ CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/padding_inline_end_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/padding_inline_end_custom.cc
new file mode 100644
index 00000000000..371658bd81d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/padding_inline_end_custom.cc
@@ -0,0 +1,25 @@
+// 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/css/properties/longhands/padding_inline_end.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSLonghand {
+
+const CSSValue* PaddingInlineEnd::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return ConsumeLengthOrPercent(
+ range, context.Mode(), kValueRangeNonNegative,
+ CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/padding_inline_start_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/padding_inline_start_custom.cc
new file mode 100644
index 00000000000..f5224eeb1d5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/padding_inline_start_custom.cc
@@ -0,0 +1,25 @@
+// 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/css/properties/longhands/padding_inline_start.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
+#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSLonghand {
+
+const CSSValue* PaddingInlineStart::ParseSingleValue(
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&) const {
+ return ConsumeLengthOrPercent(
+ range, context.Mode(), kValueRangeNonNegative,
+ CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
+}
+
+} // namespace CSSLonghand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/position_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/position_custom.cc
index 436e3152e98..1b4c438e4dd 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/position_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/position_custom.cc
@@ -16,5 +16,10 @@ const CSSValue* Position::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.GetPosition());
}
+void Position::ApplyInherit(StyleResolverState& state) const {
+ if (!state.ParentNode()->IsDocumentNode())
+ state.Style()->SetPosition(state.ParentStyle()->GetPosition());
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/resize_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/resize_custom.cc
index 2b257b0d310..646a4d6da2e 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/resize_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/resize_custom.cc
@@ -4,6 +4,10 @@
#include "third_party/blink/renderer/core/css/properties/longhands/resize.h"
+#include "third_party/blink/renderer/core/frame/settings.h"
+#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
+
namespace blink {
namespace CSSLonghand {
@@ -16,5 +20,22 @@ const CSSValue* Resize::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.Resize());
}
+void Resize::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
+
+ EResize r = EResize::kNone;
+ if (identifier_value.GetValueID() == CSSValueAuto) {
+ if (Settings* settings = state.GetDocument().GetSettings()) {
+ r = settings->GetTextAreasAreResizable() ? EResize::kBoth
+ : EResize::kNone;
+ }
+ UseCounter::Count(state.GetDocument(), WebFeature::kCSSResizeAuto);
+ } else {
+ r = identifier_value.ConvertTo<EResize>();
+ }
+ state.Style()->SetResize(r);
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/size_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/size_custom.cc
index 5c4b0a7fd57..5ed6ab5d3c8 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/size_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/size_custom.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/css/properties/longhands/size.h"
+#include "third_party/blink/renderer/core/css/css_resolution_units.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
@@ -17,6 +18,36 @@ static CSSValue* ConsumePageSize(CSSParserTokenRange& range) {
CSSValueLedger, CSSValueLegal, CSSValueLetter>(range);
}
+static float MmToPx(float mm) {
+ return mm * kCssPixelsPerMillimeter;
+}
+static float InchToPx(float inch) {
+ return inch * kCssPixelsPerInch;
+}
+static FloatSize GetPageSizeFromName(const CSSIdentifierValue& page_size_name) {
+ switch (page_size_name.GetValueID()) {
+ case CSSValueA5:
+ return FloatSize(MmToPx(148), MmToPx(210));
+ case CSSValueA4:
+ return FloatSize(MmToPx(210), MmToPx(297));
+ case CSSValueA3:
+ return FloatSize(MmToPx(297), MmToPx(420));
+ case CSSValueB5:
+ return FloatSize(MmToPx(176), MmToPx(250));
+ case CSSValueB4:
+ return FloatSize(MmToPx(250), MmToPx(353));
+ case CSSValueLetter:
+ return FloatSize(InchToPx(8.5), InchToPx(11));
+ case CSSValueLegal:
+ return FloatSize(InchToPx(8.5), InchToPx(14));
+ case CSSValueLedger:
+ return FloatSize(InchToPx(11), InchToPx(17));
+ default:
+ NOTREACHED();
+ return FloatSize(0, 0);
+ }
+}
+
const CSSValue* Size::ParseSingleValue(CSSParserTokenRange& range,
const CSSParserContext& context,
const CSSParserLocalContext&) const {
@@ -53,5 +84,68 @@ const CSSValue* Size::ParseSingleValue(CSSParserTokenRange& range,
return result;
}
+void Size::ApplyInitial(StyleResolverState& state) const {}
+
+void Size::ApplyInherit(StyleResolverState& state) const {}
+
+void Size::ApplyValue(StyleResolverState& state, const CSSValue& value) const {
+ state.Style()->ResetPageSizeType();
+ FloatSize size;
+ EPageSizeType page_size_type = EPageSizeType::kAuto;
+ const CSSValueList& list = ToCSSValueList(value);
+ if (list.length() == 2) {
+ // <length>{2} | <page-size> <orientation>
+ const CSSValue& first = list.Item(0);
+ const CSSValue& second = list.Item(1);
+ if (first.IsPrimitiveValue() && ToCSSPrimitiveValue(first).IsLength()) {
+ // <length>{2}
+ size = FloatSize(
+ ToCSSPrimitiveValue(first).ComputeLength<float>(
+ state.CssToLengthConversionData().CopyWithAdjustedZoom(1.0)),
+ ToCSSPrimitiveValue(second).ComputeLength<float>(
+ state.CssToLengthConversionData().CopyWithAdjustedZoom(1.0)));
+ } else {
+ // <page-size> <orientation>
+ size = GetPageSizeFromName(ToCSSIdentifierValue(first));
+
+ DCHECK(ToCSSIdentifierValue(second).GetValueID() == CSSValueLandscape ||
+ ToCSSIdentifierValue(second).GetValueID() == CSSValuePortrait);
+ if (ToCSSIdentifierValue(second).GetValueID() == CSSValueLandscape)
+ size = size.TransposedSize();
+ }
+ page_size_type = EPageSizeType::kResolved;
+ } else {
+ DCHECK_EQ(list.length(), 1U);
+ // <length> | auto | <page-size> | [ portrait | landscape]
+ const CSSValue& first = list.Item(0);
+ if (first.IsPrimitiveValue() && ToCSSPrimitiveValue(first).IsLength()) {
+ // <length>
+ page_size_type = EPageSizeType::kResolved;
+ float width = ToCSSPrimitiveValue(first).ComputeLength<float>(
+ state.CssToLengthConversionData().CopyWithAdjustedZoom(1.0));
+ size = FloatSize(width, width);
+ } else {
+ const CSSIdentifierValue& ident = ToCSSIdentifierValue(first);
+ switch (ident.GetValueID()) {
+ case CSSValueAuto:
+ page_size_type = EPageSizeType::kAuto;
+ break;
+ case CSSValuePortrait:
+ page_size_type = EPageSizeType::kPortrait;
+ break;
+ case CSSValueLandscape:
+ page_size_type = EPageSizeType::kLandscape;
+ break;
+ default:
+ // <page-size>
+ page_size_type = EPageSizeType::kResolved;
+ size = GetPageSizeFromName(ident);
+ }
+ }
+ }
+ state.Style()->SetPageSizeType(page_size_type);
+ state.Style()->SetPageSize(size);
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/text_align_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/text_align_custom.cc
index 20e54c75905..4b614bd4faf 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/text_align_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/text_align_custom.cc
@@ -16,5 +16,32 @@ const CSSValue* TextAlign::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.GetTextAlign());
}
+void TextAlign::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ if (value.IsIdentifierValue() &&
+ ToCSSIdentifierValue(value).GetValueID() != CSSValueWebkitMatchParent) {
+ // Special case for th elements - UA stylesheet text-align does not apply if
+ // parent's computed value for text-align is not its initial value
+ // https://html.spec.whatwg.org/multipage/rendering.html#tables-2
+ const CSSIdentifierValue& ident_value = ToCSSIdentifierValue(value);
+ if (ident_value.GetValueID() == CSSValueInternalCenter &&
+ state.ParentStyle()->GetTextAlign() !=
+ ComputedStyleInitialValues::InitialTextAlign())
+ state.Style()->SetTextAlign(state.ParentStyle()->GetTextAlign());
+ else
+ state.Style()->SetTextAlign(ident_value.ConvertTo<ETextAlign>());
+ } else if (state.ParentStyle()->GetTextAlign() == ETextAlign::kStart) {
+ state.Style()->SetTextAlign(state.ParentStyle()->IsLeftToRightDirection()
+ ? ETextAlign::kLeft
+ : ETextAlign::kRight);
+ } else if (state.ParentStyle()->GetTextAlign() == ETextAlign::kEnd) {
+ state.Style()->SetTextAlign(state.ParentStyle()->IsLeftToRightDirection()
+ ? ETextAlign::kRight
+ : ETextAlign::kLeft);
+ } else {
+ state.Style()->SetTextAlign(state.ParentStyle()->GetTextAlign());
+ }
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/text_indent_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/text_indent_custom.cc
index 2b1cd444411..2b3e126b407 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/text_indent_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/text_indent_custom.cc
@@ -20,42 +20,43 @@ const CSSValue* TextIndent::ParseSingleValue(
const CSSParserLocalContext&) const {
// [ <length> | <percentage> ] && hanging? && each-line?
// Keywords only allowed when css3Text is enabled.
- CSSValueList* list = CSSValueList::CreateSpaceSeparated();
-
- bool has_length_or_percentage = false;
- bool has_each_line = false;
- bool has_hanging = false;
-
+ CSSValue* length_percentage = nullptr;
+ CSSValue* hanging = nullptr;
+ CSSValue* each_line = nullptr;
do {
- if (!has_length_or_percentage) {
- if (CSSValue* text_indent =
- CSSPropertyParserHelpers::ConsumeLengthOrPercent(
- range, context.Mode(), kValueRangeAll,
- CSSPropertyParserHelpers::UnitlessQuirk::kAllow)) {
- list->Append(*text_indent);
- has_length_or_percentage = true;
+ if (!length_percentage) {
+ length_percentage = CSSPropertyParserHelpers::ConsumeLengthOrPercent(
+ range, context.Mode(), kValueRangeAll,
+ CSSPropertyParserHelpers::UnitlessQuirk::kAllow);
+ if (length_percentage) {
continue;
}
}
if (RuntimeEnabledFeatures::CSS3TextEnabled()) {
CSSValueID id = range.Peek().Id();
- if (!has_each_line && id == CSSValueEachLine) {
- list->Append(*CSSPropertyParserHelpers::ConsumeIdent(range));
- has_each_line = true;
+ if (!hanging && id == CSSValueHanging) {
+ hanging = CSSPropertyParserHelpers::ConsumeIdent(range);
continue;
}
- if (!has_hanging && id == CSSValueHanging) {
- list->Append(*CSSPropertyParserHelpers::ConsumeIdent(range));
- has_hanging = true;
+ if (!each_line && id == CSSValueEachLine) {
+ each_line = CSSPropertyParserHelpers::ConsumeIdent(range);
continue;
}
}
return nullptr;
} while (!range.AtEnd());
- if (!has_length_or_percentage)
+ if (!length_percentage)
return nullptr;
+ CSSValueList* list = CSSValueList::CreateSpaceSeparated();
+ list->Append(*length_percentage);
+
+ if (hanging)
+ list->Append(*hanging);
+
+ if (each_line)
+ list->Append(*each_line);
return list;
}
@@ -69,16 +70,57 @@ const CSSValue* TextIndent::CSSValueFromComputedStyleInternal(
CSSValueList* list = CSSValueList::CreateSpaceSeparated();
list->Append(*ComputedStyleUtils::ZoomAdjustedPixelValueForLength(
style.TextIndent(), style));
- if (RuntimeEnabledFeatures::CSS3TextEnabled() &&
- (style.GetTextIndentLine() == TextIndentLine::kEachLine ||
- style.GetTextIndentType() == TextIndentType::kHanging)) {
- if (style.GetTextIndentLine() == TextIndentLine::kEachLine)
- list->Append(*CSSIdentifierValue::Create(CSSValueEachLine));
+ if (RuntimeEnabledFeatures::CSS3TextEnabled()) {
if (style.GetTextIndentType() == TextIndentType::kHanging)
list->Append(*CSSIdentifierValue::Create(CSSValueHanging));
+ if (style.GetTextIndentLine() == TextIndentLine::kEachLine)
+ list->Append(*CSSIdentifierValue::Create(CSSValueEachLine));
}
return list;
}
+void TextIndent::ApplyInitial(StyleResolverState& state) const {
+ state.Style()->SetTextIndent(ComputedStyleInitialValues::InitialTextIndent());
+ state.Style()->SetTextIndentLine(
+ ComputedStyleInitialValues::InitialTextIndentLine());
+ state.Style()->SetTextIndentType(
+ ComputedStyleInitialValues::InitialTextIndentType());
+}
+
+void TextIndent::ApplyInherit(StyleResolverState& state) const {
+ state.Style()->SetTextIndent(state.ParentStyle()->TextIndent());
+ state.Style()->SetTextIndentLine(state.ParentStyle()->GetTextIndentLine());
+ state.Style()->SetTextIndentType(state.ParentStyle()->GetTextIndentType());
+}
+
+void TextIndent::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ Length length_or_percentage_value;
+ TextIndentLine text_indent_line_value =
+ ComputedStyleInitialValues::InitialTextIndentLine();
+ TextIndentType text_indent_type_value =
+ ComputedStyleInitialValues::InitialTextIndentType();
+
+ for (auto& list_value : ToCSSValueList(value)) {
+ if (list_value->IsPrimitiveValue()) {
+ length_or_percentage_value =
+ ToCSSPrimitiveValue(*list_value)
+ .ConvertToLength(state.CssToLengthConversionData());
+ } else if (ToCSSIdentifierValue(*list_value).GetValueID() ==
+ CSSValueEachLine) {
+ text_indent_line_value = TextIndentLine::kEachLine;
+ } else if (ToCSSIdentifierValue(*list_value).GetValueID() ==
+ CSSValueHanging) {
+ text_indent_type_value = TextIndentType::kHanging;
+ } else {
+ NOTREACHED();
+ }
+ }
+
+ state.Style()->SetTextIndent(length_or_percentage_value);
+ state.Style()->SetTextIndentLine(text_indent_line_value);
+ state.Style()->SetTextIndentType(text_indent_type_value);
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/text_orientation_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/text_orientation_custom.cc
index 6ececb1a4e7..80680e04cf4 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/text_orientation_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/text_orientation_custom.cc
@@ -16,5 +16,11 @@ const CSSValue* TextOrientation::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.GetTextOrientation());
}
+void TextOrientation::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ state.SetTextOrientation(
+ ToCSSIdentifierValue(value).ConvertTo<ETextOrientation>());
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/text_underline_position_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/text_underline_position_custom.cc
index 45c9d23c0a0..882eb40ca80 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/text_underline_position_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/text_underline_position_custom.cc
@@ -4,20 +4,43 @@
#include "third_party/blink/renderer/core/css/properties/longhands/text_underline_position.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/parser/css_property_parser_helpers.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
namespace CSSLonghand {
+// auto | [ under || [ left | right ] ]
const CSSValue* TextUnderlinePosition::ParseSingleValue(
CSSParserTokenRange& range,
const CSSParserContext& context,
const CSSParserLocalContext&) const {
- // auto | [ under || [ left | right ] ], but we only support auto | under
- // for now
- return CSSPropertyParserHelpers::ConsumeIdent<CSSValueAuto, CSSValueUnder>(
- range);
+ if (range.Peek().Id() == CSSValueAuto)
+ return CSSPropertyParserHelpers::ConsumeIdent(range);
+
+ CSSIdentifierValue* under_value =
+ CSSPropertyParserHelpers::ConsumeIdent<CSSValueUnder>(range);
+ CSSIdentifierValue* left_or_right_value = nullptr;
+ if (RuntimeEnabledFeatures::TextUnderlinePositionLeftRightEnabled()) {
+ left_or_right_value =
+ CSSPropertyParserHelpers::ConsumeIdent<CSSValueLeft, CSSValueRight>(
+ range);
+ if (left_or_right_value && !under_value) {
+ under_value =
+ CSSPropertyParserHelpers::ConsumeIdent<CSSValueUnder>(range);
+ }
+ }
+ if (!under_value && !left_or_right_value) {
+ return nullptr;
+ }
+ CSSValueList* list = CSSValueList::CreateSpaceSeparated();
+ if (under_value)
+ list->Append(*under_value);
+ if (left_or_right_value)
+ list->Append(*left_or_right_value);
+ return list;
}
const CSSValue* TextUnderlinePosition::CSSValueFromComputedStyleInternal(
@@ -26,7 +49,25 @@ const CSSValue* TextUnderlinePosition::CSSValueFromComputedStyleInternal(
const LayoutObject*,
Node*,
bool allow_visited_style) const {
- return CSSIdentifierValue::Create(style.GetTextUnderlinePosition());
+ auto text_underline_position = style.TextUnderlinePosition();
+ if (text_underline_position == kTextUnderlinePositionAuto)
+ return CSSIdentifierValue::Create(CSSValueAuto);
+ if (text_underline_position == kTextUnderlinePositionUnder)
+ return CSSIdentifierValue::Create(CSSValueUnder);
+ if (text_underline_position == kTextUnderlinePositionLeft)
+ return CSSIdentifierValue::Create(CSSValueLeft);
+ if (text_underline_position == kTextUnderlinePositionRight)
+ return CSSIdentifierValue::Create(CSSValueRight);
+
+ CSSValueList* list = CSSValueList::CreateSpaceSeparated();
+ DCHECK(text_underline_position & kTextUnderlinePositionUnder);
+ list->Append(*CSSIdentifierValue::Create(CSSValueUnder));
+ if (text_underline_position & kTextUnderlinePositionLeft)
+ list->Append(*CSSIdentifierValue::Create(CSSValueLeft));
+ if (text_underline_position & kTextUnderlinePositionRight)
+ list->Append(*CSSIdentifierValue::Create(CSSValueRight));
+ DCHECK_EQ(list->length(), 2U);
+ return list;
}
} // namespace CSSLonghand
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/variable.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/variable.cc
new file mode 100644
index 00000000000..2e4064b3561
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/variable.cc
@@ -0,0 +1,98 @@
+// 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/css/properties/longhands/variable.h"
+
+#include "third_party/blink/renderer/core/css/css_custom_property_declaration.h"
+#include "third_party/blink/renderer/core/css/property_registration.h"
+#include "third_party/blink/renderer/core/css/property_registry.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
+
+namespace blink {
+
+void Variable::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ const CSSCustomPropertyDeclaration& declaration =
+ ToCSSCustomPropertyDeclaration(value);
+ const AtomicString& name = declaration.GetName();
+ const PropertyRegistration* registration = nullptr;
+ const PropertyRegistry* registry = state.GetDocument().GetPropertyRegistry();
+ if (registry)
+ registration = registry->Registration(name);
+
+ bool is_inherited_property = !registration || registration->Inherits();
+ bool initial = declaration.IsInitial(is_inherited_property);
+ bool inherit = declaration.IsInherit(is_inherited_property);
+ DCHECK(!(initial && inherit));
+
+ if (!initial && !inherit) {
+ if (declaration.Value()->NeedsVariableResolution()) {
+ if (is_inherited_property) {
+ state.Style()->SetUnresolvedInheritedVariable(name,
+ declaration.Value());
+ } else {
+ state.Style()->SetUnresolvedNonInheritedVariable(name,
+ declaration.Value());
+ }
+ return;
+ }
+
+ if (!registration) {
+ state.Style()->SetResolvedUnregisteredVariable(name, declaration.Value());
+ return;
+ }
+
+ const CSSValue* parsed_value = declaration.Value()->ParseForSyntax(
+ registration->Syntax(), state.GetDocument().GetSecureContextMode());
+ if (parsed_value) {
+ DCHECK(parsed_value);
+ if (is_inherited_property) {
+ state.Style()->SetResolvedInheritedVariable(name, declaration.Value(),
+ parsed_value);
+ } else {
+ state.Style()->SetResolvedNonInheritedVariable(
+ name, declaration.Value(), parsed_value);
+ }
+ return;
+ }
+ if (is_inherited_property)
+ inherit = true;
+ else
+ initial = true;
+ }
+ DCHECK(initial ^ inherit);
+
+ state.Style()->RemoveVariable(name, is_inherited_property);
+ if (initial) {
+ return;
+ }
+
+ DCHECK(inherit);
+ CSSVariableData* parent_value =
+ state.ParentStyle()->GetVariable(name, is_inherited_property);
+ const CSSValue* parent_css_value =
+ registration && parent_value ? state.ParentStyle()->GetRegisteredVariable(
+ name, is_inherited_property)
+ : nullptr;
+
+ if (!is_inherited_property) {
+ DCHECK(registration);
+ if (parent_value) {
+ state.Style()->SetResolvedNonInheritedVariable(name, parent_value,
+ parent_css_value);
+ }
+ return;
+ }
+
+ if (parent_value) {
+ if (!registration) {
+ state.Style()->SetResolvedUnregisteredVariable(name, parent_value);
+ } else {
+ state.Style()->SetResolvedInheritedVariable(name, parent_value,
+ parent_css_value);
+ }
+ }
+}
+
+} // namespace blink
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 34dbd49c5c3..e10d8238cd0 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
@@ -9,13 +9,13 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTIES_LONGHANDS_VARIABLE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_PROPERTIES_LONGHANDS_VARIABLE_H_
-#include "third_party/blink/renderer/core/css/properties/css_property.h"
+#include "third_party/blink/renderer/core/css/properties/longhand.h"
namespace blink {
-class Variable final : public CSSProperty {
+class Variable final : public Longhand {
public:
- constexpr Variable() : CSSProperty() {}
+ constexpr Variable() : Longhand() {}
bool IsInherited() const override { return true; }
bool IsAffectedByAll() const override { return false; }
@@ -34,6 +34,9 @@ class Variable final : public CSSProperty {
NOTREACHED();
return nullptr;
}
+
+ void ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const override;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/vertical_align_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/vertical_align_custom.cc
index 564fc7c3a74..faebb54554b 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/vertical_align_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/vertical_align_custom.cc
@@ -59,5 +59,26 @@ const CSSValue* VerticalAlign::CSSValueFromComputedStyleInternal(
return nullptr;
}
+void VerticalAlign::ApplyInherit(StyleResolverState& state) const {
+ EVerticalAlign vertical_align = state.ParentStyle()->VerticalAlign();
+ state.Style()->SetVerticalAlign(vertical_align);
+ if (vertical_align == EVerticalAlign::kLength) {
+ state.Style()->SetVerticalAlignLength(
+ state.ParentStyle()->GetVerticalAlignLength());
+ }
+}
+
+void VerticalAlign::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ if (value.IsIdentifierValue()) {
+ state.Style()->SetVerticalAlign(
+ ToCSSIdentifierValue(value).ConvertTo<EVerticalAlign>());
+ } else {
+ state.Style()->SetVerticalAlignLength(
+ ToCSSPrimitiveValue(value).ConvertToLength(
+ state.CssToLengthConversionData()));
+ }
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_app_region_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_app_region_custom.cc
index 9bd8df3eab6..acf27dac60f 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_app_region_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_app_region_custom.cc
@@ -24,5 +24,19 @@ const CSSValue* WebkitAppRegion::CSSValueFromComputedStyleInternal(
: CSSValueNoDrag);
}
+void WebkitAppRegion::ApplyInitial(StyleResolverState& state) const {}
+
+void WebkitAppRegion::ApplyInherit(StyleResolverState& state) const {}
+
+void WebkitAppRegion::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
+ state.Style()->SetDraggableRegionMode(identifier_value.GetValueID() ==
+ CSSValueDrag
+ ? EDraggableRegionMode::kDrag
+ : EDraggableRegionMode::kNoDrag);
+ state.GetDocument().SetHasAnnotatedRegions(true);
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_after_color_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_after_color_custom.cc
deleted file mode 100644
index b0dbe9fa17d..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_after_color_custom.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_border_after_color.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-
-class CSSParserLocalContext;
-
-namespace CSSLonghand {
-
-const CSSValue* WebkitBorderAfterColor::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return CSSPropertyParserHelpers::ConsumeColor(range, context.Mode());
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_after_width_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_after_width_custom.cc
deleted file mode 100644
index ae13e62f563..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_after_width_custom.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_border_after_width.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-namespace CSSLonghand {
-
-const CSSValue* WebkitBorderAfterWidth::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return CSSParsingUtils::ConsumeBorderWidth(
- range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_before_color_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_before_color_custom.cc
deleted file mode 100644
index 790ccb483de..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_before_color_custom.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_border_before_color.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-
-class CSSParserLocalContext;
-
-namespace CSSLonghand {
-
-const CSSValue* WebkitBorderBeforeColor::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return CSSPropertyParserHelpers::ConsumeColor(range, context.Mode());
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_before_width_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_before_width_custom.cc
deleted file mode 100644
index 51321dd4fbb..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_before_width_custom.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_border_before_width.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-namespace CSSLonghand {
-
-const CSSValue* WebkitBorderBeforeWidth::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return CSSParsingUtils::ConsumeBorderWidth(
- range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_end_color_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_end_color_custom.cc
deleted file mode 100644
index 1ddbbeeab24..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_end_color_custom.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_border_end_color.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-
-class CSSParserLocalContext;
-
-namespace CSSLonghand {
-
-const CSSValue* WebkitBorderEndColor::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return CSSPropertyParserHelpers::ConsumeColor(range, context.Mode());
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_end_width_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_end_width_custom.cc
deleted file mode 100644
index 9cf3f207430..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_end_width_custom.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_border_end_width.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-namespace CSSLonghand {
-
-const CSSValue* WebkitBorderEndWidth::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return CSSParsingUtils::ConsumeBorderWidth(
- range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_image_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_image_custom.cc
index fb50a817491..700e42d5a6c 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_image_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_image_custom.cc
@@ -27,5 +27,13 @@ const CSSValue* WebkitBorderImage::CSSValueFromComputedStyleInternal(
return ComputedStyleUtils::ValueForNinePieceImage(style.BorderImage(), style);
}
+void WebkitBorderImage::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ NinePieceImage image;
+ CSSToStyleMap::MapNinePieceImage(state, CSSPropertyWebkitBorderImage, value,
+ image);
+ state.Style()->SetBorderImage(image);
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_start_color_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_start_color_custom.cc
deleted file mode 100644
index 65aeb3e50cd..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_start_color_custom.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_border_start_color.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-
-class CSSParserLocalContext;
-
-namespace CSSLonghand {
-
-const CSSValue* WebkitBorderStartColor::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return CSSPropertyParserHelpers::ConsumeColor(range, context.Mode());
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_start_width_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_start_width_custom.cc
deleted file mode 100644
index 6074d69f766..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_border_start_width_custom.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_border_start_width.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-namespace CSSLonghand {
-
-const CSSValue* WebkitBorderStartWidth::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return CSSParsingUtils::ConsumeBorderWidth(
- range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_locale_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_locale_custom.cc
index 9de939565ed..96b3e203bb8 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_locale_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_locale_custom.cc
@@ -31,5 +31,16 @@ const CSSValue* WebkitLocale::CSSValueFromComputedStyleInternal(
return CSSStringValue::Create(style.Locale());
}
+void WebkitLocale::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ if (value.IsIdentifierValue()) {
+ DCHECK_EQ(ToCSSIdentifierValue(value).GetValueID(), CSSValueAuto);
+ state.GetFontBuilder().SetLocale(nullptr);
+ } else {
+ state.GetFontBuilder().SetLocale(
+ LayoutLocale::Get(AtomicString(ToCSSStringValue(value).Value())));
+ }
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_logical_height_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_logical_height_custom.cc
deleted file mode 100644
index 51ab4e86c0e..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_logical_height_custom.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_logical_height.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
-
-namespace blink {
-namespace CSSLonghand {
-
-const CSSValue* WebkitLogicalHeight::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return CSSParsingUtils::ConsumeWidthOrHeight(range, context);
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_logical_width_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_logical_width_custom.cc
deleted file mode 100644
index 181dd754ad6..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_logical_width_custom.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_logical_width.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
-
-namespace blink {
-namespace CSSLonghand {
-
-const CSSValue* WebkitLogicalWidth::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return CSSParsingUtils::ConsumeWidthOrHeight(range, context);
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_margin_after_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_margin_after_custom.cc
deleted file mode 100644
index 97fb130868a..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_margin_after_custom.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_margin_after.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-namespace CSSLonghand {
-
-const CSSValue* WebkitMarginAfter::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return CSSParsingUtils::ConsumeMarginOrOffset(
- range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_margin_before_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_margin_before_custom.cc
deleted file mode 100644
index d90cc0249a2..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_margin_before_custom.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_margin_before.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-namespace CSSLonghand {
-
-const CSSValue* WebkitMarginBefore::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return CSSParsingUtils::ConsumeMarginOrOffset(
- range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_margin_end_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_margin_end_custom.cc
deleted file mode 100644
index 8e07cd5ceaa..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_margin_end_custom.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_margin_end.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-namespace CSSLonghand {
-
-const CSSValue* WebkitMarginEnd::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return CSSParsingUtils::ConsumeMarginOrOffset(
- range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_margin_start_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_margin_start_custom.cc
deleted file mode 100644
index a466a01907e..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_margin_start_custom.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_margin_start.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-namespace CSSLonghand {
-
-const CSSValue* WebkitMarginStart::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return CSSParsingUtils::ConsumeMarginOrOffset(
- range, context.Mode(), CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_mask_box_image_source_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_mask_box_image_source_custom.cc
index 39721e3c258..7390074dd9a 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_mask_box_image_source_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_mask_box_image_source_custom.cc
@@ -31,5 +31,11 @@ const CSSValue* WebkitMaskBoxImageSource::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(CSSValueNone);
}
+void WebkitMaskBoxImageSource::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ state.Style()->SetMaskBoxImageSource(
+ state.GetStyleImage(CSSPropertyWebkitMaskBoxImageSource, value));
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_max_logical_height_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_max_logical_height_custom.cc
deleted file mode 100644
index b7c5833c9cd..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_max_logical_height_custom.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_max_logical_height.h"
-
-#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
-
-namespace blink {
-namespace CSSLonghand {
-
-const CSSValue* WebkitMaxLogicalHeight::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return CSSParsingUtils::ConsumeMaxWidthOrHeight(range, context);
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_max_logical_width_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_max_logical_width_custom.cc
deleted file mode 100644
index 150ad71b164..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_max_logical_width_custom.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_max_logical_width.h"
-
-#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
-
-namespace blink {
-namespace CSSLonghand {
-
-const CSSValue* WebkitMaxLogicalWidth::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return CSSParsingUtils::ConsumeMaxWidthOrHeight(range, context);
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_min_logical_height_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_min_logical_height_custom.cc
deleted file mode 100644
index 8f001e7e73e..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_min_logical_height_custom.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_min_logical_height.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
-
-namespace blink {
-namespace CSSLonghand {
-
-const CSSValue* WebkitMinLogicalHeight::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return CSSParsingUtils::ConsumeWidthOrHeight(range, context);
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_min_logical_width_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_min_logical_width_custom.cc
deleted file mode 100644
index 440f38802dc..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_min_logical_width_custom.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_min_logical_width.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/css/properties/css_parsing_utils.h"
-
-namespace blink {
-namespace CSSLonghand {
-
-const CSSValue* WebkitMinLogicalWidth::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return CSSParsingUtils::ConsumeWidthOrHeight(range, context);
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_padding_after_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_padding_after_custom.cc
deleted file mode 100644
index 129b8b0218c..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_padding_after_custom.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_padding_after.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
-#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-namespace CSSLonghand {
-
-const CSSValue* WebkitPaddingAfter::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return ConsumeLengthOrPercent(
- range, context.Mode(), kValueRangeNonNegative,
- CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_padding_before_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_padding_before_custom.cc
deleted file mode 100644
index 771e728e381..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_padding_before_custom.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_padding_before.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
-#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-namespace CSSLonghand {
-
-const CSSValue* WebkitPaddingBefore::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return ConsumeLengthOrPercent(
- range, context.Mode(), kValueRangeNonNegative,
- CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_padding_end_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_padding_end_custom.cc
deleted file mode 100644
index 04b3897e9e8..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_padding_end_custom.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_padding_end.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
-#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-namespace CSSLonghand {
-
-const CSSValue* WebkitPaddingEnd::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return ConsumeLengthOrPercent(
- range, context.Mode(), kValueRangeNonNegative,
- CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_padding_start_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_padding_start_custom.cc
deleted file mode 100644
index 0383dd562f5..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_padding_start_custom.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/webkit_padding_start.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
-#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-namespace CSSLonghand {
-
-const CSSValue* WebkitPaddingStart::ParseSingleValue(
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&) const {
- return ConsumeLengthOrPercent(
- range, context.Mode(), kValueRangeNonNegative,
- CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_text_emphasis_style_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_text_emphasis_style_custom.cc
index 1bb819692e4..cbc33535993 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_text_emphasis_style_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_text_emphasis_style_custom.cc
@@ -79,5 +79,64 @@ const CSSValue* WebkitTextEmphasisStyle::CSSValueFromComputedStyleInternal(
return nullptr;
}
+void WebkitTextEmphasisStyle::ApplyInitial(StyleResolverState& state) const {
+ state.Style()->SetTextEmphasisFill(
+ ComputedStyleInitialValues::InitialTextEmphasisFill());
+ state.Style()->SetTextEmphasisMark(
+ ComputedStyleInitialValues::InitialTextEmphasisMark());
+ state.Style()->SetTextEmphasisCustomMark(
+ ComputedStyleInitialValues::InitialTextEmphasisCustomMark());
+}
+
+void WebkitTextEmphasisStyle::ApplyInherit(StyleResolverState& state) const {
+ state.Style()->SetTextEmphasisFill(
+ state.ParentStyle()->GetTextEmphasisFill());
+ state.Style()->SetTextEmphasisMark(
+ state.ParentStyle()->GetTextEmphasisMark());
+ state.Style()->SetTextEmphasisCustomMark(
+ state.ParentStyle()->TextEmphasisCustomMark());
+}
+
+void WebkitTextEmphasisStyle::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ if (value.IsValueList()) {
+ const CSSValueList& list = ToCSSValueList(value);
+ DCHECK_EQ(list.length(), 2U);
+ for (unsigned i = 0; i < 2; ++i) {
+ const CSSIdentifierValue& value = ToCSSIdentifierValue(list.Item(i));
+ if (value.GetValueID() == CSSValueFilled ||
+ value.GetValueID() == CSSValueOpen)
+ state.Style()->SetTextEmphasisFill(value.ConvertTo<TextEmphasisFill>());
+ else
+ state.Style()->SetTextEmphasisMark(value.ConvertTo<TextEmphasisMark>());
+ }
+ state.Style()->SetTextEmphasisCustomMark(g_null_atom);
+ return;
+ }
+
+ if (value.IsStringValue()) {
+ state.Style()->SetTextEmphasisFill(TextEmphasisFill::kFilled);
+ state.Style()->SetTextEmphasisMark(TextEmphasisMark::kCustom);
+ state.Style()->SetTextEmphasisCustomMark(
+ AtomicString(ToCSSStringValue(value).Value()));
+ return;
+ }
+
+ const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
+
+ state.Style()->SetTextEmphasisCustomMark(g_null_atom);
+
+ if (identifier_value.GetValueID() == CSSValueFilled ||
+ identifier_value.GetValueID() == CSSValueOpen) {
+ state.Style()->SetTextEmphasisFill(
+ identifier_value.ConvertTo<TextEmphasisFill>());
+ state.Style()->SetTextEmphasisMark(TextEmphasisMark::kAuto);
+ } else {
+ state.Style()->SetTextEmphasisFill(TextEmphasisFill::kFilled);
+ state.Style()->SetTextEmphasisMark(
+ identifier_value.ConvertTo<TextEmphasisMark>());
+ }
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_text_orientation_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_text_orientation_custom.cc
index 3662d685dba..fa32fe3a0e2 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_text_orientation_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_text_orientation_custom.cc
@@ -20,5 +20,11 @@ const CSSValue* WebkitTextOrientation::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.GetTextOrientation());
}
+void WebkitTextOrientation::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ state.SetTextOrientation(
+ ToCSSIdentifierValue(value).ConvertTo<ETextOrientation>());
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_writing_mode_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_writing_mode_custom.cc
index dbece1cf8ee..1aa5e106d86 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_writing_mode_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/webkit_writing_mode_custom.cc
@@ -16,5 +16,11 @@ const CSSValue* WebkitWritingMode::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.GetWritingMode());
}
+void WebkitWritingMode::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ state.SetWritingMode(
+ ToCSSIdentifierValue(value).ConvertTo<blink::WritingMode>());
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/will_change_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/will_change_custom.cc
index 8a362a70969..8caadeae027 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/will_change_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/will_change_custom.cc
@@ -81,5 +81,56 @@ const CSSValue* WillChange::CSSValueFromComputedStyleInternal(
style.WillChangeScrollPosition());
}
+void WillChange::ApplyInitial(StyleResolverState& state) const {
+ state.Style()->SetWillChangeContents(false);
+ state.Style()->SetWillChangeScrollPosition(false);
+ state.Style()->SetWillChangeProperties(Vector<CSSPropertyID>());
+ state.Style()->SetSubtreeWillChangeContents(
+ state.ParentStyle()->SubtreeWillChangeContents());
+}
+
+void WillChange::ApplyInherit(StyleResolverState& state) const {
+ state.Style()->SetWillChangeContents(
+ state.ParentStyle()->WillChangeContents());
+ state.Style()->SetWillChangeScrollPosition(
+ state.ParentStyle()->WillChangeScrollPosition());
+ state.Style()->SetWillChangeProperties(
+ state.ParentStyle()->WillChangeProperties());
+ state.Style()->SetSubtreeWillChangeContents(
+ state.ParentStyle()->SubtreeWillChangeContents());
+}
+
+void WillChange::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ bool will_change_contents = false;
+ bool will_change_scroll_position = false;
+ Vector<CSSPropertyID> will_change_properties;
+
+ if (value.IsIdentifierValue()) {
+ DCHECK_EQ(ToCSSIdentifierValue(value).GetValueID(), CSSValueAuto);
+ } else {
+ DCHECK(value.IsValueList());
+ for (auto& will_change_value : ToCSSValueList(value)) {
+ if (will_change_value->IsCustomIdentValue()) {
+ will_change_properties.push_back(
+ ToCSSCustomIdentValue(*will_change_value).ValueAsPropertyID());
+ } else if (ToCSSIdentifierValue(*will_change_value).GetValueID() ==
+ CSSValueContents) {
+ will_change_contents = true;
+ } else if (ToCSSIdentifierValue(*will_change_value).GetValueID() ==
+ CSSValueScrollPosition) {
+ will_change_scroll_position = true;
+ } else {
+ NOTREACHED();
+ }
+ }
+ }
+ state.Style()->SetWillChangeContents(will_change_contents);
+ state.Style()->SetWillChangeScrollPosition(will_change_scroll_position);
+ state.Style()->SetWillChangeProperties(will_change_properties);
+ state.Style()->SetSubtreeWillChangeContents(
+ will_change_contents || state.ParentStyle()->SubtreeWillChangeContents());
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/word_wrap_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/word_wrap_custom.cc
deleted file mode 100644
index 76a1d958961..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/word_wrap_custom.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/longhands/word_wrap.h"
-
-namespace blink {
-namespace CSSLonghand {
-
-const CSSValue* WordWrap::CSSValueFromComputedStyleInternal(
- const ComputedStyle& style,
- const SVGComputedStyle&,
- const LayoutObject*,
- Node*,
- bool allow_visited_style) const {
- return CSSIdentifierValue::Create(style.OverflowWrap());
-}
-
-} // namespace CSSLonghand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/writing_mode_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/writing_mode_custom.cc
index 9d510d0c545..36b2dd68322 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/writing_mode_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/writing_mode_custom.cc
@@ -16,5 +16,11 @@ const CSSValue* WritingMode::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.GetWritingMode());
}
+void WritingMode::ApplyValue(StyleResolverState& state,
+ const CSSValue& value) const {
+ state.SetWritingMode(
+ ToCSSIdentifierValue(value).ConvertTo<blink::WritingMode>());
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/longhands/zoom_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/longhands/zoom_custom.cc
index 99e37a1dc6b..150dc75aefa 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/longhands/zoom_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/longhands/zoom_custom.cc
@@ -48,5 +48,37 @@ const CSSValue* Zoom::CSSValueFromComputedStyleInternal(
CSSPrimitiveValue::UnitType::kNumber);
}
+void Zoom::ApplyInitial(StyleResolverState& state) const {
+ state.SetZoom(ComputedStyleInitialValues::InitialZoom());
+}
+
+void Zoom::ApplyInherit(StyleResolverState& state) const {
+ state.SetZoom(state.ParentStyle()->Zoom());
+}
+
+void Zoom::ApplyValue(StyleResolverState& state, const CSSValue& value) const {
+ SECURITY_DCHECK(value.IsPrimitiveValue() || value.IsIdentifierValue());
+
+ if (value.IsIdentifierValue()) {
+ const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
+ if (identifier_value.GetValueID() == CSSValueNormal) {
+ state.SetZoom(ComputedStyleInitialValues::InitialZoom());
+ }
+ } else if (value.IsPrimitiveValue()) {
+ const CSSPrimitiveValue& primitive_value = ToCSSPrimitiveValue(value);
+ if (primitive_value.IsPercentage()) {
+ if (float percent = primitive_value.GetFloatValue())
+ state.SetZoom(percent / 100.0f);
+ else
+ state.SetZoom(1.0f);
+ } else if (primitive_value.IsNumber()) {
+ if (float number = primitive_value.GetFloatValue())
+ state.SetZoom(number);
+ else
+ state.SetZoom(1.0f);
+ }
+ }
+}
+
} // namespace CSSLonghand
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_color_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_color_custom.cc
new file mode 100644
index 00000000000..a067b26f7a8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_color_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/shorthands/border_block_color.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSShorthand {
+
+bool BorderBlockColor::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ return CSSPropertyParserHelpers::ConsumeShorthandVia2Longhands(
+ borderBlockColorShorthand(), important, context, range, properties);
+}
+
+} // namespace CSSShorthand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_custom.cc
new file mode 100644
index 00000000000..111168bdb9b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_custom.cc
@@ -0,0 +1,39 @@
+// 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/css/properties/shorthands/border_block.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSShorthand {
+
+bool BorderBlock::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ const CSSValue* width = nullptr;
+ const CSSValue* style = nullptr;
+ const CSSValue* color = nullptr;
+
+ if (!CSSPropertyParserHelpers::ConsumeBorderShorthand(range, context, width,
+ style, color)) {
+ return false;
+ };
+
+ CSSPropertyParserHelpers::AddExpandedPropertyForValue(
+ CSSPropertyBorderBlockWidth, *width, important, properties);
+ CSSPropertyParserHelpers::AddExpandedPropertyForValue(
+ CSSPropertyBorderBlockStyle, *style, important, properties);
+ CSSPropertyParserHelpers::AddExpandedPropertyForValue(
+ CSSPropertyBorderBlockColor, *color, important, properties);
+
+ return range.AtEnd();
+}
+
+} // namespace CSSShorthand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_end_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_end_custom.cc
new file mode 100644
index 00000000000..8e9665afe4e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_end_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/shorthands/border_block_end.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSShorthand {
+
+bool BorderBlockEnd::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ return CSSPropertyParserHelpers::ConsumeShorthandGreedilyViaLonghands(
+ borderBlockEndShorthand(), important, context, range, properties);
+}
+
+} // namespace CSSShorthand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_start_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_start_custom.cc
new file mode 100644
index 00000000000..22f27305992
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_start_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/shorthands/border_block_start.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSShorthand {
+
+bool BorderBlockStart::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ return CSSPropertyParserHelpers::ConsumeShorthandGreedilyViaLonghands(
+ borderBlockStartShorthand(), important, context, range, properties);
+}
+
+} // namespace CSSShorthand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_style_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_style_custom.cc
new file mode 100644
index 00000000000..9258ef733cb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_style_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/shorthands/border_block_style.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSShorthand {
+
+bool BorderBlockStyle::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ return CSSPropertyParserHelpers::ConsumeShorthandVia2Longhands(
+ borderBlockStyleShorthand(), important, context, range, properties);
+}
+
+} // namespace CSSShorthand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_width_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_width_custom.cc
new file mode 100644
index 00000000000..da619397494
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_block_width_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/shorthands/border_block_width.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSShorthand {
+
+bool BorderBlockWidth::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ return CSSPropertyParserHelpers::ConsumeShorthandVia2Longhands(
+ borderBlockWidthShorthand(), important, context, range, properties);
+}
+
+} // namespace CSSShorthand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_custom.cc
index ba242f99ed6..7dff25ea3ef 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_custom.cc
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_custom.cc
@@ -19,43 +19,14 @@ bool Border::ParseShorthand(
const CSSParserContext& context,
const CSSParserLocalContext&,
HeapVector<CSSPropertyValue, 256>& properties) const {
- CSSValue* width = nullptr;
+ const CSSValue* width = nullptr;
const CSSValue* style = nullptr;
- CSSValue* color = nullptr;
+ const CSSValue* color = nullptr;
- while (!width || !style || !color) {
- if (!width) {
- width = CSSPropertyParserHelpers::ConsumeLineWidth(
- range, context.Mode(),
- CSSPropertyParserHelpers::UnitlessQuirk::kForbid);
- if (width)
- continue;
- }
- if (!style) {
- bool needs_legacy_parsing = false;
- style = CSSPropertyParserHelpers::ParseLonghand(
- CSSPropertyBorderLeftStyle, CSSPropertyBorder, context, range);
- DCHECK(!needs_legacy_parsing);
- if (style)
- continue;
- }
- if (!color) {
- color = CSSPropertyParserHelpers::ConsumeColor(range, context.Mode());
- if (color)
- continue;
- }
- break;
- }
-
- if (!width && !style && !color)
+ if (!CSSPropertyParserHelpers::ConsumeBorderShorthand(range, context, width,
+ style, color)) {
return false;
-
- if (!width)
- width = CSSInitialValue::Create();
- if (!style)
- style = CSSInitialValue::Create();
- if (!color)
- color = CSSInitialValue::Create();
+ };
CSSPropertyParserHelpers::AddExpandedPropertyForValue(
CSSPropertyBorderWidth, *width, important, properties);
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_color_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_color_custom.cc
new file mode 100644
index 00000000000..315135b5f34
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_color_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/shorthands/border_inline_color.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSShorthand {
+
+bool BorderInlineColor::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ return CSSPropertyParserHelpers::ConsumeShorthandVia2Longhands(
+ borderInlineColorShorthand(), important, context, range, properties);
+}
+
+} // namespace CSSShorthand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_custom.cc
new file mode 100644
index 00000000000..67d5695906d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_custom.cc
@@ -0,0 +1,39 @@
+// 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/css/properties/shorthands/border_inline.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSShorthand {
+
+bool BorderInline::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ const CSSValue* width = nullptr;
+ const CSSValue* style = nullptr;
+ const CSSValue* color = nullptr;
+
+ if (!CSSPropertyParserHelpers::ConsumeBorderShorthand(range, context, width,
+ style, color)) {
+ return false;
+ };
+
+ CSSPropertyParserHelpers::AddExpandedPropertyForValue(
+ CSSPropertyBorderInlineWidth, *width, important, properties);
+ CSSPropertyParserHelpers::AddExpandedPropertyForValue(
+ CSSPropertyBorderInlineStyle, *style, important, properties);
+ CSSPropertyParserHelpers::AddExpandedPropertyForValue(
+ CSSPropertyBorderInlineColor, *color, important, properties);
+
+ return range.AtEnd();
+}
+
+} // namespace CSSShorthand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_end_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_end_custom.cc
new file mode 100644
index 00000000000..53c9c7d72d8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_end_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/shorthands/border_inline_end.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSShorthand {
+
+bool BorderInlineEnd::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ return CSSPropertyParserHelpers::ConsumeShorthandGreedilyViaLonghands(
+ borderInlineEndShorthand(), important, context, range, properties);
+}
+
+} // namespace CSSShorthand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_start_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_start_custom.cc
new file mode 100644
index 00000000000..7440a220bc1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_start_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/shorthands/border_inline_start.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSShorthand {
+
+bool BorderInlineStart::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ return CSSPropertyParserHelpers::ConsumeShorthandGreedilyViaLonghands(
+ borderInlineStartShorthand(), important, context, range, properties);
+}
+
+} // namespace CSSShorthand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_style_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_style_custom.cc
new file mode 100644
index 00000000000..83859ed8424
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_style_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/shorthands/border_inline_style.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSShorthand {
+
+bool BorderInlineStyle::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ return CSSPropertyParserHelpers::ConsumeShorthandVia2Longhands(
+ borderInlineStyleShorthand(), important, context, range, properties);
+}
+
+} // namespace CSSShorthand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_width_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_width_custom.cc
new file mode 100644
index 00000000000..1fdacb111d4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/border_inline_width_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/shorthands/border_inline_width.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSShorthand {
+
+bool BorderInlineWidth::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ return CSSPropertyParserHelpers::ConsumeShorthandVia2Longhands(
+ borderInlineWidthShorthand(), important, context, range, properties);
+}
+
+} // namespace CSSShorthand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/inset_block_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/inset_block_custom.cc
new file mode 100644
index 00000000000..d9616b4405f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/inset_block_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/shorthands/inset_block.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSShorthand {
+
+bool InsetBlock::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ return CSSPropertyParserHelpers::ConsumeShorthandVia2Longhands(
+ insetBlockShorthand(), important, context, range, properties);
+}
+
+} // namespace CSSShorthand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/inset_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/inset_custom.cc
new file mode 100644
index 00000000000..06744cb17c8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/inset_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/shorthands/inset.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSShorthand {
+
+bool Inset::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ return CSSPropertyParserHelpers::ConsumeShorthandVia4Longhands(
+ insetShorthand(), important, context, range, properties);
+}
+
+} // namespace CSSShorthand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/inset_inline_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/inset_inline_custom.cc
new file mode 100644
index 00000000000..2ae7dce5d07
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/inset_inline_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/shorthands/inset_inline.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSShorthand {
+
+bool InsetInline::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ return CSSPropertyParserHelpers::ConsumeShorthandVia2Longhands(
+ insetInlineShorthand(), important, context, range, properties);
+}
+
+} // namespace CSSShorthand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/margin_block_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/margin_block_custom.cc
new file mode 100644
index 00000000000..3d91f6d7c46
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/margin_block_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/shorthands/margin_block.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSShorthand {
+
+bool MarginBlock::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ return CSSPropertyParserHelpers::ConsumeShorthandVia2Longhands(
+ marginBlockShorthand(), important, context, range, properties);
+}
+
+} // namespace CSSShorthand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/margin_inline_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/margin_inline_custom.cc
new file mode 100644
index 00000000000..3dabd4b34d5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/margin_inline_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/shorthands/margin_inline.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSShorthand {
+
+bool MarginInline::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ return CSSPropertyParserHelpers::ConsumeShorthandVia2Longhands(
+ marginInlineShorthand(), important, context, range, properties);
+}
+
+} // namespace CSSShorthand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/padding_block_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/padding_block_custom.cc
new file mode 100644
index 00000000000..959c9ed651e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/padding_block_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/shorthands/padding_block.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSShorthand {
+
+bool PaddingBlock::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ return CSSPropertyParserHelpers::ConsumeShorthandVia2Longhands(
+ paddingBlockShorthand(), important, context, range, properties);
+}
+
+} // namespace CSSShorthand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/padding_inline_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/padding_inline_custom.cc
new file mode 100644
index 00000000000..79c0a3b0ef1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/properties/shorthands/padding_inline_custom.cc
@@ -0,0 +1,24 @@
+// 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/css/properties/shorthands/padding_inline.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
+#include "third_party/blink/renderer/core/style_property_shorthand.h"
+
+namespace blink {
+namespace CSSShorthand {
+
+bool PaddingInline::ParseShorthand(
+ bool important,
+ CSSParserTokenRange& range,
+ const CSSParserContext& context,
+ const CSSParserLocalContext&,
+ HeapVector<CSSPropertyValue, 256>& properties) const {
+ return CSSPropertyParserHelpers::ConsumeShorthandVia2Longhands(
+ paddingInlineShorthand(), important, context, range, properties);
+}
+
+} // namespace CSSShorthand
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/webkit_border_after_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/webkit_border_after_custom.cc
deleted file mode 100644
index f9667447cf0..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/shorthands/webkit_border_after_custom.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/shorthands/webkit_border_after.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-namespace CSSShorthand {
-
-bool WebkitBorderAfter::ParseShorthand(
- bool important,
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&,
- HeapVector<CSSPropertyValue, 256>& properties) const {
- return CSSPropertyParserHelpers::ConsumeShorthandGreedilyViaLonghands(
- webkitBorderAfterShorthand(), important, context, range, properties);
-}
-
-} // namespace CSSShorthand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/webkit_border_before_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/webkit_border_before_custom.cc
deleted file mode 100644
index 2c6c48c5bac..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/shorthands/webkit_border_before_custom.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/shorthands/webkit_border_before.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-namespace CSSShorthand {
-
-bool WebkitBorderBefore::ParseShorthand(
- bool important,
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&,
- HeapVector<CSSPropertyValue, 256>& properties) const {
- return CSSPropertyParserHelpers::ConsumeShorthandGreedilyViaLonghands(
- webkitBorderBeforeShorthand(), important, context, range, properties);
-}
-
-} // namespace CSSShorthand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/webkit_border_end_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/webkit_border_end_custom.cc
deleted file mode 100644
index 23630c205be..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/shorthands/webkit_border_end_custom.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/shorthands/webkit_border_end.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-namespace CSSShorthand {
-
-bool WebkitBorderEnd::ParseShorthand(
- bool important,
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&,
- HeapVector<CSSPropertyValue, 256>& properties) const {
- return CSSPropertyParserHelpers::ConsumeShorthandGreedilyViaLonghands(
- webkitBorderEndShorthand(), important, context, range, properties);
-}
-
-} // namespace CSSShorthand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/shorthands/webkit_border_start_custom.cc b/chromium/third_party/blink/renderer/core/css/properties/shorthands/webkit_border_start_custom.cc
deleted file mode 100644
index bb8814c0927..00000000000
--- a/chromium/third_party/blink/renderer/core/css/properties/shorthands/webkit_border_start_custom.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/css/properties/shorthands/webkit_border_start.h"
-
-#include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-
-namespace blink {
-namespace CSSShorthand {
-
-bool WebkitBorderStart::ParseShorthand(
- bool important,
- CSSParserTokenRange& range,
- const CSSParserContext& context,
- const CSSParserLocalContext&,
- HeapVector<CSSPropertyValue, 256>& properties) const {
- return CSSPropertyParserHelpers::ConsumeShorthandGreedilyViaLonghands(
- webkitBorderStartShorthand(), important, context, range, properties);
-}
-
-} // namespace CSSShorthand
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/properties/style_building_utils.h b/chromium/third_party/blink/renderer/core/css/properties/style_building_utils.h
index b679a39cafc..1fba8a59397 100644
--- a/chromium/third_party/blink/renderer/core/css/properties/style_building_utils.h
+++ b/chromium/third_party/blink/renderer/core/css/properties/style_building_utils.h
@@ -13,18 +13,18 @@
namespace blink {
namespace StyleBuildingUtils {
-inline bool borderImageLengthMatchesAllSides(
- const BorderImageLengthBox& borderImageLengthBox,
- const BorderImageLength& borderImageLength) {
- return (borderImageLengthBox.Left() == borderImageLength &&
- borderImageLengthBox.Right() == borderImageLength &&
- borderImageLengthBox.Top() == borderImageLength &&
- borderImageLengthBox.Bottom() == borderImageLength);
+inline bool BorderImageLengthMatchesAllSides(
+ const BorderImageLengthBox& border_image_length_box,
+ const BorderImageLength& border_image_length) {
+ return (border_image_length_box.Left() == border_image_length &&
+ border_image_length_box.Right() == border_image_length &&
+ border_image_length_box.Top() == border_image_length &&
+ border_image_length_box.Bottom() == border_image_length);
}
-inline bool lengthMatchesAllSides(const LengthBox& lengthBox,
+inline bool LengthMatchesAllSides(const LengthBox& length_box,
const Length& length) {
- return (lengthBox.Left() == length && lengthBox.Right() == length &&
- lengthBox.Top() == length && lengthBox.Bottom() == length);
+ return (length_box.Left() == length && length_box.Right() == length &&
+ length_box.Top() == length && length_box.Bottom() == length);
}
} // namespace StyleBuildingUtils
diff --git a/chromium/third_party/blink/renderer/core/css/property_descriptor.idl b/chromium/third_party/blink/renderer/core/css/property_descriptor.idl
index 18b455b4608..a64010d8a5e 100644
--- a/chromium/third_party/blink/renderer/core/css/property_descriptor.idl
+++ b/chromium/third_party/blink/renderer/core/css/property_descriptor.idl
@@ -5,6 +5,6 @@
dictionary PropertyDescriptor {
required DOMString name;
DOMString syntax = "*";
- boolean inherits = false;
+ required boolean inherits;
DOMString initialValue;
};
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 f50c1692552..9e7fe70b1a6 100644
--- a/chromium/third_party/blink/renderer/core/css/property_registration.cc
+++ b/chromium/third_party/blink/renderer/core/css/property_registration.cc
@@ -19,7 +19,6 @@
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/css/style_sheet_contents.h"
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
namespace blink {
@@ -89,7 +88,8 @@ void PropertyRegistration::registerProperty(
String name = descriptor.name();
if (!CSSVariableParser::IsValidVariableName(name)) {
exception_state.ThrowDOMException(
- kSyntaxError, "Custom property names must start with '--'.");
+ DOMExceptionCode::kSyntaxError,
+ "Custom property names must start with '--'.");
return;
}
AtomicString atomic_name(name);
@@ -97,7 +97,7 @@ void PropertyRegistration::registerProperty(
PropertyRegistry& registry = *document->GetPropertyRegistry();
if (registry.Registration(atomic_name)) {
exception_state.ThrowDOMException(
- kInvalidModificationError,
+ DOMExceptionCode::kInvalidModificationError,
"The name provided has already been registered.");
return;
}
@@ -105,41 +105,43 @@ void PropertyRegistration::registerProperty(
CSSSyntaxDescriptor syntax_descriptor(descriptor.syntax());
if (!syntax_descriptor.IsValid()) {
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"The syntax provided is not a valid custom property syntax.");
return;
}
+ const CSSParserContext* parser_context =
+ document->ElementSheet().Contents()->ParserContext();
+
const CSSValue* initial = nullptr;
scoped_refptr<CSSVariableData> initial_variable_data;
if (descriptor.hasInitialValue()) {
CSSTokenizer tokenizer(descriptor.initialValue());
const auto tokens = tokenizer.TokenizeToEOF();
bool is_animation_tainted = false;
- initial = syntax_descriptor.Parse(
- CSSParserTokenRange(tokens),
- document->ElementSheet().Contents()->ParserContext(),
- is_animation_tainted);
+ initial = syntax_descriptor.Parse(CSSParserTokenRange(tokens),
+ parser_context, is_animation_tainted);
if (!initial) {
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"The initial value provided does not parse for the given syntax.");
return;
}
if (!ComputationallyIndependent(*initial)) {
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"The initial value provided is not computationally independent.");
return;
}
initial =
&StyleBuilderConverter::ConvertRegisteredPropertyInitialValue(*initial);
initial_variable_data = CSSVariableData::Create(
- CSSParserTokenRange(tokens), is_animation_tainted, false);
+ CSSParserTokenRange(tokens), is_animation_tainted, false,
+ parser_context->BaseURL(), parser_context->Charset());
} else {
if (!syntax_descriptor.IsTokenStream()) {
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"An initial value must be provided if the syntax is not '*'");
return;
}
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/css_variable_data_test.cc b/chromium/third_party/blink/renderer/core/css/resolver/css_variable_data_test.cc
new file mode 100644
index 00000000000..f437d9cd072
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/resolver/css_variable_data_test.cc
@@ -0,0 +1,45 @@
+// 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/css/css_variable_data.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
+
+namespace blink {
+
+namespace {
+
+scoped_refptr<CSSVariableData> CreateVariableData(const String& string) {
+ auto tokens = CSSTokenizer(string).TokenizeToEOF();
+ return CSSVariableData::Create(tokens, false, false, KURL(),
+ WTF::TextEncoding());
+}
+
+} // namespace
+
+TEST(CSSVariableDataTest, FontUnitsDetected) {
+ EXPECT_FALSE(CreateVariableData("100px")->HasFontUnits());
+ EXPECT_FALSE(CreateVariableData("10%")->HasFontUnits());
+ EXPECT_FALSE(CreateVariableData("10vw")->HasFontUnits());
+ EXPECT_FALSE(CreateVariableData("10rem")->HasFontUnits());
+
+ EXPECT_TRUE(CreateVariableData("10em")->HasFontUnits());
+ EXPECT_TRUE(CreateVariableData("10ch")->HasFontUnits());
+ EXPECT_TRUE(CreateVariableData("10ex")->HasFontUnits());
+ EXPECT_TRUE(CreateVariableData("calc(10em + 10%)")->HasFontUnits());
+}
+
+TEST(CSSVariableDataTest, RootFontUnitsDetected) {
+ EXPECT_FALSE(CreateVariableData("100px")->HasRootFontUnits());
+ EXPECT_FALSE(CreateVariableData("10%")->HasRootFontUnits());
+ EXPECT_FALSE(CreateVariableData("10vw")->HasRootFontUnits());
+ EXPECT_FALSE(CreateVariableData("10em")->HasRootFontUnits());
+ EXPECT_FALSE(CreateVariableData("10ch")->HasRootFontUnits());
+ EXPECT_FALSE(CreateVariableData("10ex")->HasRootFontUnits());
+
+ EXPECT_TRUE(CreateVariableData("10rem")->HasRootFontUnits());
+ EXPECT_TRUE(CreateVariableData("calc(10rem + 10%)")->HasRootFontUnits());
+}
+
+} // namespace blink
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 b54e0eb3267..b9cb5ae8a62 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
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/css/css_unset_value.h"
#include "third_party/blink/renderer/core/css/css_variable_data.h"
#include "third_party/blink/renderer/core/css/css_variable_reference_value.h"
+#include "third_party/blink/renderer/core/css/document_style_environment_variables.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/parser/css_property_parser.h"
@@ -20,27 +21,49 @@
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/css_property_names.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
+#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/style/style_inherited_variables.h"
#include "third_party/blink/renderer/core/style/style_non_inherited_variables.h"
-#include "third_party/blink/renderer/core/style_builder_functions.h"
#include "third_party/blink/renderer/core/style_property_shorthand.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
-bool CSSVariableResolver::ResolveFallback(
- CSSParserTokenRange range,
- bool disallow_animation_tainted,
- Vector<CSSParserToken>& result,
- Vector<String>& result_backing_strings,
- bool& result_is_animation_tainted) {
+namespace {
+
+CSSParserToken ResolveUrl(const CSSParserToken& token,
+ Vector<String>& backing_strings,
+ const KURL& base_url,
+ WTF::TextEncoding charset) {
+ DCHECK(token.GetType() == kUrlToken || token.GetType() == kStringToken);
+
+ StringView string_view = token.Value();
+
+ if (string_view.IsNull())
+ return token;
+
+ String relative_url = string_view.ToString();
+ KURL absolute_url = charset.IsValid() ? KURL(base_url, relative_url, charset)
+ : KURL(base_url, relative_url);
+
+ backing_strings.push_back(absolute_url.GetString());
+
+ return token.CopyWithUpdatedString(StringView(backing_strings.back()));
+}
+
+} // namespace
+
+bool CSSVariableResolver::ResolveFallback(CSSParserTokenRange range,
+ const Options& options,
+ Result& result) {
if (range.AtEnd())
return false;
DCHECK_EQ(range.Peek().GetType(), kCommaToken);
range.Consume();
- return ResolveTokenRange(range, disallow_animation_tainted, result,
- result_backing_strings, result_is_animation_tainted);
+ return ResolveTokenRange(range, options, result);
}
CSSVariableData* CSSVariableResolver::ValueForCustomProperty(
@@ -64,12 +87,15 @@ CSSVariableData* CSSVariableResolver::ValueForCustomProperty(
}
if (!variable_data)
return registration ? registration->InitialVariableData() : nullptr;
- if (!variable_data->NeedsVariableResolution())
+
+ bool resolve_urls = ShouldResolveRelativeUrls(name, *variable_data);
+
+ if (!variable_data->NeedsVariableResolution() && !resolve_urls)
return variable_data;
bool unused_cycle_detected;
- scoped_refptr<CSSVariableData> new_variable_data =
- ResolveCustomProperty(name, *variable_data, unused_cycle_detected);
+ scoped_refptr<CSSVariableData> new_variable_data = ResolveCustomProperty(
+ name, *variable_data, resolve_urls, unused_cycle_detected);
if (!registration) {
inherited_variables_->SetVariable(name, new_variable_data);
return new_variable_data.get();
@@ -97,19 +123,18 @@ CSSVariableData* CSSVariableResolver::ValueForCustomProperty(
scoped_refptr<CSSVariableData> CSSVariableResolver::ResolveCustomProperty(
AtomicString name,
const CSSVariableData& variable_data,
+ bool resolve_urls,
bool& cycle_detected) {
- DCHECK(variable_data.NeedsVariableResolution());
+ DCHECK(variable_data.NeedsVariableResolution() || resolve_urls);
- bool disallow_animation_tainted = false;
- bool is_animation_tainted = variable_data.IsAnimationTainted();
- Vector<CSSParserToken> tokens;
- Vector<String> backing_strings;
- backing_strings.AppendVector(variable_data.BackingStrings());
+ Result result;
+ result.is_animation_tainted = variable_data.IsAnimationTainted();
+ result.has_font_units = variable_data.HasFontUnits();
+ result.has_root_font_units = variable_data.HasRootFontUnits();
+ result.backing_strings.AppendVector(variable_data.BackingStrings());
DCHECK(!variables_seen_.Contains(name));
variables_seen_.insert(name);
- bool success =
- ResolveTokenRange(variable_data.Tokens(), disallow_animation_tainted,
- tokens, backing_strings, is_animation_tainted);
+ bool success = ResolveTokenRange(variable_data.Tokens(), Options(), result);
variables_seen_.erase(name);
if (!success || !cycle_start_points_.IsEmpty()) {
@@ -118,16 +143,63 @@ scoped_refptr<CSSVariableData> CSSVariableResolver::ResolveCustomProperty(
return nullptr;
}
cycle_detected = false;
- return CSSVariableData::CreateResolved(tokens, std::move(backing_strings),
- is_animation_tainted);
+
+ if (resolve_urls) {
+ ResolveRelativeUrls(result.tokens, result.backing_strings,
+ variable_data.BaseURL(), variable_data.Charset());
+ }
+
+ return CSSVariableData::CreateResolved(
+ result.tokens, std::move(result.backing_strings),
+ result.is_animation_tainted, result.has_font_units,
+ result.has_root_font_units);
+}
+
+void CSSVariableResolver::ResolveRelativeUrls(
+ Vector<CSSParserToken>& tokens,
+ Vector<String>& backing_strings,
+ const KURL& base_url,
+ const WTF::TextEncoding& charset) {
+ CSSParserToken* token = tokens.begin();
+ CSSParserToken* end = tokens.end();
+
+ while (token < end) {
+ if (token->GetType() == kUrlToken) {
+ *token = ResolveUrl(*token, backing_strings, base_url, charset);
+ } else if (token->FunctionId() == CSSValueUrl) {
+ if (token + 1 < end && token[1].GetType() == kStringToken)
+ token[1] = ResolveUrl(token[1], backing_strings, base_url, charset);
+ }
+ ++token;
+ }
+}
+
+bool CSSVariableResolver::ShouldResolveRelativeUrls(
+ const AtomicString& name,
+ const CSSVariableData& variable_data) {
+ if (!variable_data.NeedsUrlResolution())
+ return false;
+ const PropertyRegistration* registration =
+ registry_ ? registry_->Registration(name) : nullptr;
+ return registration ? registration->Syntax().HasUrlSyntax() : false;
+}
+
+bool CSSVariableResolver::IsVariableDisallowed(
+ const CSSVariableData& variable_data,
+ const Options& options,
+ const PropertyRegistration* registration) {
+ return (options.disallow_animation_tainted &&
+ variable_data.IsAnimationTainted()) ||
+ (registration && options.disallow_registered_font_units &&
+ variable_data.HasFontUnits()) ||
+ (registration && options.disallow_registered_root_font_units &&
+ variable_data.HasRootFontUnits());
}
-bool CSSVariableResolver::ResolveVariableReference(
- CSSParserTokenRange range,
- bool disallow_animation_tainted,
- Vector<CSSParserToken>& result,
- Vector<String>& result_backing_strings,
- bool& result_is_animation_tainted) {
+bool CSSVariableResolver::ResolveVariableReference(CSSParserTokenRange range,
+ const Options& options,
+ bool is_env_variable,
+ Result& result) {
range.ConsumeWhitespace();
DCHECK_EQ(range.Peek().GetType(), kIdentToken);
AtomicString variable_name =
@@ -148,42 +220,56 @@ bool CSSVariableResolver::ResolveVariableReference(
inherited_variables_ = state_.Style()->InheritedVariables();
non_inherited_variables_ = state_.Style()->NonInheritedVariables();
}
- CSSVariableData* variable_data = ValueForCustomProperty(variable_name);
+ CSSVariableData* variable_data =
+ is_env_variable ? ValueForEnvironmentVariable(variable_name)
+ : ValueForCustomProperty(variable_name);
+
+ const PropertyRegistration* registration =
+ registry_ ? registry_->Registration(variable_name) : nullptr;
+
if (!variable_data ||
- (disallow_animation_tainted && variable_data->IsAnimationTainted())) {
+ IsVariableDisallowed(*variable_data, options, registration)) {
// TODO(alancutter): Append the registered initial custom property value if
// we are disallowing an animation tainted value.
- return ResolveFallback(range, disallow_animation_tainted, result,
- result_backing_strings, result_is_animation_tainted);
+ return ResolveFallback(range, options, result);
}
- result.AppendVector(variable_data->Tokens());
+ result.tokens.AppendVector(variable_data->Tokens());
// TODO(alancutter): Avoid adding backing strings multiple times in a row.
- result_backing_strings.AppendVector(variable_data->BackingStrings());
- result_is_animation_tainted |= variable_data->IsAnimationTainted();
-
- Vector<CSSParserToken> trash;
- Vector<String> trash_backing_strings;
- bool trash_is_animation_tainted;
- ResolveFallback(range, disallow_animation_tainted, trash,
- trash_backing_strings, trash_is_animation_tainted);
+ result.backing_strings.AppendVector(variable_data->BackingStrings());
+ result.is_animation_tainted |= variable_data->IsAnimationTainted();
+
+ Result trash;
+ ResolveFallback(range, options, trash);
return true;
}
-bool CSSVariableResolver::ResolveTokenRange(
- CSSParserTokenRange range,
- bool disallow_animation_tainted,
- Vector<CSSParserToken>& result,
- Vector<String>& result_backing_strings,
- bool& result_is_animation_tainted) {
+CSSVariableData* CSSVariableResolver::ValueForEnvironmentVariable(
+ const AtomicString& name) {
+ // If we are in a User Agent Shadow DOM then we should not record metrics.
+ ContainerNode& scope_root = state_.GetTreeScope().RootNode();
+ bool is_ua_scope =
+ scope_root.IsShadowRoot() && ToShadowRoot(scope_root).IsUserAgent();
+
+ return state_.GetDocument()
+ .GetStyleEngine()
+ .EnsureEnvironmentVariables()
+ .ResolveVariable(name, !is_ua_scope);
+}
+
+bool CSSVariableResolver::ResolveTokenRange(CSSParserTokenRange range,
+ const Options& options,
+ Result& result) {
bool success = true;
while (!range.AtEnd()) {
- if (range.Peek().FunctionId() == CSSValueVar) {
- success &= ResolveVariableReference(
- range.ConsumeBlock(), disallow_animation_tainted, result,
- result_backing_strings, result_is_animation_tainted);
+ const CSSParserToken& token = range.Peek();
+ if (token.FunctionId() == CSSValueVar ||
+ token.FunctionId() == CSSValueEnv) {
+ success &=
+ ResolveVariableReference(range.ConsumeBlock(), options,
+ token.FunctionId() == CSSValueEnv, result);
} else {
- result.push_back(range.Consume());
+ result.tokens.push_back(range.Consume());
}
}
return success;
@@ -195,14 +281,25 @@ const CSSValue* CSSVariableResolver::ResolveVariableReferences(
bool disallow_animation_tainted) {
DCHECK(!CSSProperty::Get(id).IsShorthand());
+ Options options;
+ options.disallow_animation_tainted = disallow_animation_tainted;
+
+ if (id == CSSPropertyFontSize) {
+ bool is_root =
+ state_.GetElement() &&
+ state_.GetElement() == state_.GetDocument().documentElement();
+ options.disallow_registered_font_units = true;
+ options.disallow_registered_root_font_units = is_root;
+ }
+
if (value.IsPendingSubstitutionValue()) {
return ResolvePendingSubstitutions(id, ToCSSPendingSubstitutionValue(value),
- disallow_animation_tainted);
+ options);
}
if (value.IsVariableReferenceValue()) {
return ResolveVariableReferences(id, ToCSSVariableReferenceValue(value),
- disallow_animation_tainted);
+ options);
}
NOTREACHED();
@@ -212,26 +309,24 @@ const CSSValue* CSSVariableResolver::ResolveVariableReferences(
const CSSValue* CSSVariableResolver::ResolveVariableReferences(
CSSPropertyID id,
const CSSVariableReferenceValue& value,
- bool disallow_animation_tainted) {
- Vector<CSSParserToken> tokens;
- Vector<String> backing_strings;
- bool is_animation_tainted = false;
- if (!ResolveTokenRange(value.VariableDataValue()->Tokens(),
- disallow_animation_tainted, tokens, backing_strings,
- is_animation_tainted)) {
+ const Options& options) {
+ Result result;
+
+ if (!ResolveTokenRange(value.VariableDataValue()->Tokens(), options,
+ result)) {
return cssvalue::CSSUnsetValue::Create();
}
- const CSSValue* result =
- CSSPropertyParser::ParseSingleValue(id, tokens, value.ParserContext());
- if (!result)
+ const CSSValue* resolved_value = CSSPropertyParser::ParseSingleValue(
+ id, result.tokens, value.ParserContext());
+ if (!resolved_value)
return cssvalue::CSSUnsetValue::Create();
- return result;
+ return resolved_value;
}
const CSSValue* CSSVariableResolver::ResolvePendingSubstitutions(
CSSPropertyID id,
const CSSPendingSubstitutionValue& pending_value,
- bool disallow_animation_tainted) {
+ const Options& options) {
// Longhands from shorthand references follow this path.
HeapHashMap<CSSPropertyID, Member<const CSSValue>>& property_cache =
state_.ParsedPropertiesForPendingSubstitutionCache(pending_value);
@@ -243,16 +338,13 @@ const CSSValue* CSSVariableResolver::ResolvePendingSubstitutions(
CSSVariableReferenceValue* shorthand_value = pending_value.ShorthandValue();
CSSPropertyID shorthand_property_id = pending_value.ShorthandPropertyId();
- Vector<CSSParserToken> tokens;
- Vector<String> backing_strings;
- bool is_animation_tainted = false;
+ Result result;
if (ResolveTokenRange(shorthand_value->VariableDataValue()->Tokens(),
- disallow_animation_tainted, tokens, backing_strings,
- is_animation_tainted)) {
+ options, result)) {
HeapVector<CSSPropertyValue, 256> parsed_properties;
if (CSSPropertyParser::ParseValue(
- shorthand_property_id, false, CSSParserTokenRange(tokens),
+ shorthand_property_id, false, CSSParserTokenRange(result.tokens),
shorthand_value->ParserContext(), parsed_properties,
StyleRule::RuleType::kStyle)) {
unsigned parsed_properties_count = parsed_properties.size();
@@ -285,7 +377,9 @@ CSSVariableResolver::ResolveCustomPropertyAnimationKeyframe(
return nullptr;
}
- return ResolveCustomProperty(name, *keyframe.Value(), cycle_detected);
+ bool resolve_urls = false;
+ return ResolveCustomProperty(name, *keyframe.Value(), resolve_urls,
+ cycle_detected);
}
void CSSVariableResolver::ResolveVariableDefinitions() {
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver.h b/chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver.h
index c0501082c91..e5a574cc59c 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver.h
@@ -11,6 +11,10 @@
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
+namespace WTF {
+class TextEncoding;
+} // namespace WTF
+
namespace blink {
class CSSCustomPropertyDeclaration;
@@ -18,10 +22,12 @@ class CSSParserTokenRange;
class CSSPendingSubstitutionValue;
class CSSVariableData;
class CSSVariableReferenceValue;
+class KURL;
+class PropertyRegistration;
class PropertyRegistry;
-class StyleResolverState;
class StyleInheritedVariables;
class StyleNonInheritedVariables;
+class StyleResolverState;
class CSSVariableResolver {
STACK_ALLOCATED();
@@ -43,46 +49,94 @@ class CSSVariableResolver {
void ComputeRegisteredVariables();
private:
+ struct Options {
+ STACK_ALLOCATED();
+
+ // Treat any references to animation-tainted custom properties as invalid.
+ //
+ // Custom properties used in @keyframe rules become 'animation-tainted'
+ // (see https://drafts.csswg.org/css-variables/#syntax). References to
+ // animation-tainted custom properties are not allowed for properties
+ // that affect animations.
+ bool disallow_animation_tainted = false;
+
+ // Treat any references to registered custom properties with font-relative
+ // units as invalid.
+ //
+ // This is used when resolving variable references for 'font-size', where
+ // registered custom properties with font-relative units may not be used.
+ //
+ // https://drafts.css-houdini.org/css-properties-values-api-1/#dependency-cycles-via-relative-units
+ bool disallow_registered_font_units = false;
+
+ // Treat any references to registered custom properties with
+ // root-font-relative units as invalid.
+ //
+ // This is used when resolving variable references for 'font-size' on the
+ // root element, where registered custom properties with root-font-relative
+ // units may not be used.
+ //
+ // https://drafts.css-houdini.org/css-properties-values-api-1/#dependency-cycles-via-relative-units
+ bool disallow_registered_root_font_units = false;
+ };
+
+ struct Result {
+ STACK_ALLOCATED();
+
+ Vector<CSSParserToken> tokens;
+ Vector<String> backing_strings;
+ bool is_animation_tainted = false;
+ bool has_font_units = false;
+ bool has_root_font_units = false;
+ };
+
const CSSValue* ResolvePendingSubstitutions(
CSSPropertyID,
const CSSPendingSubstitutionValue&,
- bool disallow_animation_tainted);
+ const Options&);
const CSSValue* ResolveVariableReferences(CSSPropertyID,
const CSSVariableReferenceValue&,
- bool disallow_animation_tainted);
+ const Options&);
// These return false if we encounter a reference to an invalid variable with
// no fallback.
- // Resolves a range which may contain var() references.
- bool ResolveTokenRange(CSSParserTokenRange,
- bool disallow_animation_tainted,
- Vector<CSSParserToken>& result,
- Vector<String>& result_backing_strings,
- bool& result_is_animation_tainted);
- // Resolves the fallback (if present) of a var() reference, starting from the
- // comma.
- bool ResolveFallback(CSSParserTokenRange,
- bool disallow_animation_tainted,
- Vector<CSSParserToken>& result,
- Vector<String>& result_backing_strings,
- bool& result_is_animation_tainted);
- // Resolves the contents of a var() reference.
+ // Resolves a range which may contain var() or env() references.
+ bool ResolveTokenRange(CSSParserTokenRange, const Options&, Result&);
+ // Resolves the fallback (if present) of a var() or env() reference, starting
+ // from the comma.
+ bool ResolveFallback(CSSParserTokenRange, const Options&, Result&);
+ // Resolves the contents of a var() or env() reference.
bool ResolveVariableReference(CSSParserTokenRange,
- bool disallow_animation_tainted,
- Vector<CSSParserToken>& result,
- Vector<String>& result_backing_strings,
- bool& result_is_animation_tainted);
+ const Options&,
+ bool is_env_variable,
+ Result&);
// These return null if the custom property is invalid.
+ // Returns the CSSVariableData for an environment variable.
+ CSSVariableData* ValueForEnvironmentVariable(const AtomicString& name);
// Returns the CSSVariableData for a custom property, resolving and storing it
// if necessary.
CSSVariableData* ValueForCustomProperty(AtomicString name);
// Resolves the CSSVariableData from a custom property declaration.
scoped_refptr<CSSVariableData> ResolveCustomProperty(AtomicString name,
const CSSVariableData&,
+ bool resolve_urls,
bool& cycle_detected);
+ // Rewrites (in-place) kUrlTokens and kFunctionToken/CSSValueUrls to contain
+ // absolute URLs.
+ void ResolveRelativeUrls(Vector<CSSParserToken>& tokens,
+ Vector<String>& backing_strings,
+ const KURL& base_url,
+ const WTF::TextEncoding& charset);
+
+ bool ShouldResolveRelativeUrls(const AtomicString& name,
+ const CSSVariableData&);
+
+ bool IsVariableDisallowed(const CSSVariableData&,
+ const Options&,
+ const PropertyRegistration*);
const StyleResolverState& state_;
StyleInheritedVariables* inherited_variables_;
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
new file mode 100644
index 00000000000..6179efcdc16
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/resolver/css_variable_resolver_test.cc
@@ -0,0 +1,119 @@
+// 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/css/document_style_environment_variables.h"
+#include "third_party/blink/renderer/core/css/style_engine.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/style/computed_style.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+
+namespace blink {
+
+namespace {
+
+// blue
+static const Color kFallbackTestColor = Color(0, 0, 255);
+
+// black
+static const Color kMainBgTestColor = Color(0, 0, 0);
+
+// red
+static const Color kTestColor = Color(255, 0, 0);
+
+} // namespace
+
+class CSSVariableResolverTest : public PageTestBase {
+ public:
+ void SetUp() override {
+ PageTestBase::SetUp();
+
+ RuntimeEnabledFeatures::SetCSSEnvironmentVariablesEnabled(true);
+ GetStyleEngine().EnsureEnvironmentVariables().SetVariable("test", "red");
+ }
+
+ void SetTestHTML(const String& value) {
+ GetDocument().body()->SetInnerHTMLFromString(
+ "<style>"
+ " #target {"
+ " --main-bg-color: black;"
+ " --test: red;"
+ " background-color: " +
+ value +
+ " }"
+ "</style>"
+ "<div>"
+ " <div id=target></div>"
+ "</div>");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ }
+};
+
+TEST_F(CSSVariableResolverTest, ParseEnvVariable_Missing_NestedVar) {
+ SetTestHTML("env(missing, var(--main-bg-color))");
+
+ // Check that the element has the background color provided by the
+ // nested variable.
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(kMainBgTestColor, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+}
+
+TEST_F(CSSVariableResolverTest, ParseEnvVariable_Missing_NestedVar_Fallback) {
+ SetTestHTML("env(missing, var(--missing, blue))");
+
+ // Check that the element has the fallback background color.
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(kFallbackTestColor,
+ target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+}
+
+TEST_F(CSSVariableResolverTest, ParseEnvVariable_Missing_WithFallback) {
+ SetTestHTML("env(missing, blue)");
+
+ // Check that the element has the fallback background color.
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(kFallbackTestColor,
+ target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+}
+
+TEST_F(CSSVariableResolverTest, ParseEnvVariable_Valid) {
+ SetTestHTML("env(test)");
+
+ // Check that the element has the background color provided by the variable.
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(kTestColor, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+}
+
+TEST_F(CSSVariableResolverTest, ParseEnvVariable_Valid_WithFallback) {
+ SetTestHTML("env(test, blue)");
+
+ // Check that the element has the background color provided by the variable.
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(kTestColor, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+}
+
+TEST_F(CSSVariableResolverTest, ParseEnvVariable_WhenNested) {
+ SetTestHTML("var(--main-bg-color, env(missing))");
+
+ // Check that the element has the background color provided by var().
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(kMainBgTestColor, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+}
+
+TEST_F(CSSVariableResolverTest, ParseEnvVariable_WhenNested_WillFallback) {
+ SetTestHTML("var(--missing, env(test))");
+
+ // Check that the element has the background color provided by the variable.
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(kTestColor, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+}
+
+} // namespace blink
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 ddb97feae14..cadb825a69c 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
@@ -39,6 +39,7 @@
#include "third_party/blink/renderer/core/style/style_generated_image.h"
#include "third_party/blink/renderer/core/style/style_image.h"
#include "third_party/blink/renderer/core/style/style_pending_image.h"
+#include "third_party/blink/renderer/core/svg/svg_resource.h"
#include "third_party/blink/renderer/core/svg/svg_tree_scope_resources.h"
#include "third_party/blink/renderer/platform/length.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/filter_operation_resolver.cc b/chromium/third_party/blink/renderer/core/css/resolver/filter_operation_resolver.cc
index 1ab4e54fd10..88bd4a8bd56 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/filter_operation_resolver.cc
+++ b/chromium/third_party/blink/renderer/core/css/resolver/filter_operation_resolver.cc
@@ -209,7 +209,8 @@ FilterOperations FilterOperationResolver::CreateFilterOperations(
}
FilterOperations FilterOperationResolver::CreateOffscreenFilterOperations(
- const CSSValue& in_value) {
+ const CSSValue& in_value,
+ const Font& font) {
FilterOperations operations;
if (in_value.IsIdentifierValue()) {
@@ -217,8 +218,6 @@ FilterOperations FilterOperationResolver::CreateOffscreenFilterOperations(
return operations;
}
- FontDescription font_description;
- Font font(font_description);
CSSToLengthConversionData::FontSizes font_sizes(
kOffScreenCanvasEmFontSize, kOffScreenCanvasRemFontSize, &font);
CSSToLengthConversionData::ViewportSize viewport_size(0, 0);
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/filter_operation_resolver.h b/chromium/third_party/blink/renderer/core/css/resolver/filter_operation_resolver.h
index 363f859fcb8..39920cbb894 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/filter_operation_resolver.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/filter_operation_resolver.h
@@ -40,7 +40,8 @@ class CORE_EXPORT FilterOperationResolver {
static FilterOperation::OperationType FilterOperationForType(CSSValueID);
static FilterOperations CreateFilterOperations(StyleResolverState&,
const CSSValue&);
- static FilterOperations CreateOffscreenFilterOperations(const CSSValue&);
+ static FilterOperations CreateOffscreenFilterOperations(const CSSValue&,
+ const Font&);
};
} // namespace blink
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 428765528d2..d7771ea2e89 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
@@ -99,7 +99,7 @@ struct CachedMatchedPropertiesHashTraits
}
};
-class MatchedPropertiesCache {
+class CORE_EXPORT MatchedPropertiesCache {
DISALLOW_NEW();
public:
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 cc40137b685..21d9eeac7e9 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
@@ -56,7 +56,6 @@
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
#include "third_party/blink/renderer/core/svg/svg_svg_element.h"
#include "third_party/blink/renderer/core/svg_names.h"
-#include "third_party/blink/renderer/platform/feature_policy/feature_policy.h"
#include "third_party/blink/renderer/platform/length.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/transforms/transform_operations.h"
@@ -482,14 +481,8 @@ static void AdjustEffectiveTouchAction(ComputedStyle& style,
AdjustTouchActionForElement(inherited_action, style, element);
TouchAction enforced_by_policy = TouchAction::kTouchActionNone;
- if (element &&
- IsSupportedInFeaturePolicy(
- mojom::FeaturePolicyFeature::kVerticalScroll) &&
- element->GetDocument().GetFrame() &&
- !element->GetDocument().GetFrame()->IsFeatureEnabled(
- mojom::FeaturePolicyFeature::kVerticalScroll)) {
+ if (element->GetDocument().IsVerticalScrollEnforced())
enforced_by_policy = TouchAction::kTouchActionPanY;
- }
// Apply the adjusted parent effective touch actions.
style.SetEffectiveTouchAction((element_touch_action & inherited_action) |
@@ -520,9 +513,13 @@ void StyleAdjuster::AdjustComputedStyle(StyleResolverState& state,
AdjustStyleForHTMLElement(style, ToHTMLElement(*element));
}
if (style.Display() != EDisplay::kNone) {
+ bool is_document_element =
+ element && element->GetDocument().documentElement() == element;
// Per the spec, position 'static' and 'relative' in the top layer compute
- // to 'absolute'.
- if (IsInTopLayer(element, style) &&
+ // to 'absolute'. Root elements that are in the top layer should just
+ // be left alone because the fullscreen.css doesn't apply any style to
+ // them.
+ if (IsInTopLayer(element, style) && !is_document_element &&
(style.GetPosition() == EPosition::kStatic ||
style.GetPosition() == EPosition::kRelative))
style.SetPosition(EPosition::kAbsolute);
@@ -533,7 +530,7 @@ void StyleAdjuster::AdjustComputedStyle(StyleResolverState& state,
(style.HasOutOfFlowPosition() || style.IsFloating()))
style.SetDisplay(EquivalentBlockDisplay(style.Display()));
- if (element && element->GetDocument().documentElement() == element)
+ if (is_document_element)
style.SetDisplay(EquivalentBlockDisplay(style.Display()));
// We don't adjust the first letter style earlier because we may change the
@@ -543,11 +540,6 @@ void StyleAdjuster::AdjustComputedStyle(StyleResolverState& state,
AdjustStyleForDisplay(style, layout_parent_style,
element ? &element->GetDocument() : nullptr);
- // Paint containment forces a block formatting context, so we must coerce
- // from inline. https://drafts.csswg.org/css-containment/#containment-paint
- if (style.ContainsPaint() && style.Display() == EDisplay::kInline)
- style.SetDisplay(EDisplay::kBlock);
-
// If this is a child of a LayoutCustom, we need the name of the parent
// layout function for invalidation purposes.
if (layout_parent_style.IsDisplayLayoutCustomBox()) {
@@ -686,15 +678,13 @@ void StyleAdjuster::AdjustComputedStyle(StyleResolverState& state,
// Form controls are not supported yet.
style.SetForceLegacyLayout(true);
} else if (style.UserModify() != EUserModify::kReadOnly ||
- document.InDesignMode()) {
+ document.InDesignMode() ||
+ style.Display() == EDisplay::kWebkitBox ||
+ style.Display() == EDisplay::kWebkitInlineBox) {
// TODO(layout-dev): Once LayoutNG handles inline content editable, we
// should get rid of following code fragment.
style.SetForceLegacyLayout(true);
- if (style.Display() == EDisplay::kInline &&
- parent_style.UserModify() == EUserModify::kReadOnly) {
- style.SetDisplay(EDisplay::kInlineBlock);
- }
} else if (!RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled()) {
// Disable NG for the entire subtree if we're establishing a block
// fragmentation context.
@@ -702,19 +692,26 @@ void StyleAdjuster::AdjustComputedStyle(StyleResolverState& state,
(style.IsOverflowPaged() &&
element != document.ViewportDefiningElement())) {
style.SetForceLegacyLayout(true);
- } else if (document.Paginated()) {
+ } else if (document.Printing()) {
// This needs to be discovered on the root element.
DCHECK_EQ(element, document.documentElement());
style.SetForceLegacyLayout(true);
}
}
+ if (!style.ForceLegacyLayout()) {
+ // The custom container is laid out by the legacy engine. Its children may
+ // not establish new formatting contexts, so we need to protect against
+ // re-entering LayoutNG there.
+ if (style.Display() == EDisplay::kLayoutCustom ||
+ style.Display() == EDisplay::kInlineLayoutCustom)
+ style.SetForceLegacyLayout(true);
+ }
}
// If intrinsically sized images or videos are disallowed by feature policy,
// use default size (300 x 150) instead.
if (IsImageOrVideoElement(element)) {
- if (IsSupportedInFeaturePolicy(
- mojom::FeaturePolicyFeature::kUnsizedMedia) &&
+ if (RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled() &&
element->GetDocument().GetFrame() &&
!element->GetDocument().GetFrame()->IsFeatureEnabled(
mojom::FeaturePolicyFeature::kUnsizedMedia)) {
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_builder.cc b/chromium/third_party/blink/renderer/core/css/resolver/style_builder.cc
new file mode 100644
index 00000000000..056f19c56af
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_builder.cc
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc.
+ * All rights reserved.
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
+ * (http://www.torchmobile.com/)
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011. 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 <memory>
+#include <utility>
+
+#include "third_party/blink/renderer/core/animation/css/css_animations.h"
+#include "third_party/blink/renderer/core/css/properties/longhand.h"
+#include "third_party/blink/renderer/core/css/resolver/css_variable_resolver.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/style/computed_style.h"
+
+namespace blink {
+
+void StyleBuilder::ApplyProperty(const CSSProperty& property,
+ StyleResolverState& state,
+ const CSSValue& value) {
+ CSSPropertyID id = property.PropertyID();
+ bool is_inherited = property.IsInherited();
+ if (id != CSSPropertyVariable && (value.IsVariableReferenceValue() ||
+ value.IsPendingSubstitutionValue())) {
+ bool omit_animation_tainted =
+ CSSAnimations::IsAnimationAffectingProperty(property);
+ const CSSValue* resolved_value =
+ CSSVariableResolver(state).ResolveVariableReferences(
+ id, value, omit_animation_tainted);
+ ApplyProperty(property, state, *resolved_value);
+
+ if (!state.Style()->HasVariableReferenceFromNonInheritedProperty() &&
+ !is_inherited)
+ state.Style()->SetHasVariableReferenceFromNonInheritedProperty();
+ return;
+ }
+
+ DCHECK(!property.IsShorthand())
+ << "Shorthand property id = " << id << " wasn't expanded at parsing time";
+
+ bool is_inherit = state.ParentNode() && value.IsInheritedValue();
+ bool is_initial = value.IsInitialValue() ||
+ (!state.ParentNode() && value.IsInheritedValue());
+
+ // isInherit => !isInitial && isInitial => !isInherit
+ DCHECK(!is_inherit || !is_initial);
+ // isInherit => (state.parentNode() && state.parentStyle())
+ DCHECK(!is_inherit || (state.ParentNode() && state.ParentStyle()));
+
+ if (!state.ApplyPropertyToRegularStyle() &&
+ (!state.ApplyPropertyToVisitedLinkStyle() ||
+ !property.IsValidForVisitedLink())) {
+ // Limit the properties that can be applied to only the ones honored by
+ // :visited.
+ return;
+ }
+
+ if (is_inherit && !state.ParentStyle()->HasExplicitlyInheritedProperties() &&
+ !is_inherited) {
+ state.ParentStyle()->SetHasExplicitlyInheritedProperties();
+ } else if (value.IsUnsetValue()) {
+ DCHECK(!is_inherit && !is_initial);
+ if (is_inherited)
+ is_inherit = true;
+ else
+ is_initial = true;
+ }
+
+ // CSSPropertyVariable currently handles initial/inherit inside ApplyValue.
+ DCHECK(id != CSSPropertyVariable || !is_initial);
+ DCHECK(id != CSSPropertyVariable || !is_inherit);
+
+ if (is_initial)
+ ToLonghand(property).ApplyInitial(state);
+ else if (is_inherit)
+ ToLonghand(property).ApplyInherit(state);
+ else
+ ToLonghand(property).ApplyValue(state, value);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_builder.h b/chromium/third_party/blink/renderer/core/css/resolver/style_builder.h
index 5974c1be32e..1693a7498db 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_builder.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/style_builder.h
@@ -48,13 +48,6 @@ class CORE_EXPORT StyleBuilder {
static void ApplyProperty(const CSSProperty&,
StyleResolverState&,
const CSSValue&);
-
- private:
- static void ApplyProperty(const CSSProperty&,
- StyleResolverState&,
- const CSSValue&,
- bool is_initial,
- bool is_inherit);
};
} // namespace blink
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 b658ce99e58..6d2e327f43a 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
@@ -50,6 +50,8 @@
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/use_counter.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/shape_clip_path_operation.h"
#include "third_party/blink/renderer/core/style/style_svg_resource.h"
namespace blink {
@@ -156,8 +158,9 @@ FilterOperations StyleBuilderConverter::ConvertFilterOperations(
}
FilterOperations StyleBuilderConverter::ConvertOffscreenFilterOperations(
- const CSSValue& value) {
- return FilterOperationResolver::CreateOffscreenFilterOperations(value);
+ const CSSValue& value,
+ const Font& font) {
+ return FilterOperationResolver::CreateOffscreenFilterOperations(value, font);
}
static FontDescription::GenericFamilyType ConvertGenericFamily(
@@ -1475,6 +1478,26 @@ TextSizeAdjust StyleBuilderConverter::ConvertTextSizeAdjust(
return TextSizeAdjust(primitive_value.GetFloatValue() / 100.0f);
}
+TextUnderlinePosition StyleBuilderConverter::ConvertTextUnderlinePosition(
+ StyleResolverState& state,
+ const CSSValue& value) {
+ TextUnderlinePosition flags = kTextUnderlinePositionAuto;
+
+ auto process = [&flags](const CSSValue& identifier) {
+ flags |=
+ ToCSSIdentifierValue(identifier).ConvertTo<TextUnderlinePosition>();
+ };
+
+ if (value.IsValueList()) {
+ for (auto& entry : ToCSSValueList(value)) {
+ process(*entry);
+ }
+ } else {
+ process(value);
+ }
+ return flags;
+}
+
TransformOperations StyleBuilderConverter::ConvertTransformOperations(
StyleResolverState& state,
const CSSValue& value) {
@@ -1525,14 +1548,14 @@ ScrollSnapAlign StyleBuilderConverter::ConvertSnapAlign(StyleResolverState&,
ComputedStyleInitialValues::InitialScrollSnapAlign();
if (value.IsValuePair()) {
const CSSValuePair& pair = ToCSSValuePair(value);
- snapAlign.alignment_inline =
- ToCSSIdentifierValue(pair.First()).ConvertTo<SnapAlignment>();
snapAlign.alignment_block =
+ ToCSSIdentifierValue(pair.First()).ConvertTo<SnapAlignment>();
+ snapAlign.alignment_inline =
ToCSSIdentifierValue(pair.Second()).ConvertTo<SnapAlignment>();
} else {
- snapAlign.alignment_inline =
+ snapAlign.alignment_block =
ToCSSIdentifierValue(value).ConvertTo<SnapAlignment>();
- snapAlign.alignment_block = snapAlign.alignment_inline;
+ snapAlign.alignment_inline = snapAlign.alignment_block;
}
return snapAlign;
}
@@ -1656,8 +1679,9 @@ static const CSSValue& ComputeRegisteredPropertyValue(
}
if (value.IsValueList()) {
- CSSValueList* new_list = CSSValueList::CreateSpaceSeparated();
- for (const CSSValue* inner_value : ToCSSValueList(value)) {
+ const CSSValueList& old_list = ToCSSValueList(value);
+ CSSValueList* new_list = CSSValueList::CreateWithSeparatorFrom(old_list);
+ for (const CSSValue* inner_value : old_list) {
new_list->Append(ComputeRegisteredPropertyValue(
css_to_length_conversion_data, *inner_value));
}
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 16ad90e58f7..90e63408249 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
@@ -45,6 +45,7 @@
#include "third_party/blink/renderer/core/style/svg_computed_style_defs.h"
#include "third_party/blink/renderer/core/style/transform_origin.h"
#include "third_party/blink/renderer/platform/fonts/font_description.h"
+#include "third_party/blink/renderer/platform/graphics/image_orientation.h"
#include "third_party/blink/renderer/platform/length_size.h"
#include "third_party/blink/renderer/platform/text/tab_size.h"
#include "third_party/blink/renderer/platform/transforms/rotation.h"
@@ -54,6 +55,7 @@ namespace blink {
class ClipPathOperation;
class CSSToLengthConversionData;
+class Font;
class FontBuilder;
class RotateTransformOperation;
class ScaleTransformOperation;
@@ -105,7 +107,8 @@ class StyleBuilderConverter {
const CSSValue&);
static FilterOperations ConvertFilterOperations(StyleResolverState&,
const CSSValue&);
- static FilterOperations ConvertOffscreenFilterOperations(const CSSValue&);
+ static FilterOperations ConvertOffscreenFilterOperations(const CSSValue&,
+ const Font&);
template <typename T>
static T ConvertFlags(StyleResolverState&, const CSSValue&);
static FontDescription::FamilyDescription ConvertFontFamily(
@@ -201,6 +204,9 @@ class StyleBuilderConverter {
static float ConvertTextStrokeWidth(StyleResolverState&, const CSSValue&);
static TextSizeAdjust ConvertTextSizeAdjust(StyleResolverState&,
const CSSValue&);
+ static TextUnderlinePosition ConvertTextUnderlinePosition(
+ StyleResolverState& state,
+ const CSSValue& value);
static TransformOperations ConvertTransformOperations(StyleResolverState&,
const CSSValue&);
static TransformOrigin ConvertTransformOrigin(StyleResolverState&,
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/style_builder_custom.cc b/chromium/third_party/blink/renderer/core/css/resolver/style_builder_custom.cc
deleted file mode 100644
index 96039eb4c3b..00000000000
--- a/chromium/third_party/blink/renderer/core/css/resolver/style_builder_custom.cc
+++ /dev/null
@@ -1,1050 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
- * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
- * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc.
- * All rights reserved.
- * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
- * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
- * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
- * (http://www.torchmobile.com/)
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- * Copyright (C) Research In Motion Limited 2011. 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 <memory>
-#include <utility>
-
-#include "third_party/blink/renderer/core/animation/css/css_animations.h"
-#include "third_party/blink/renderer/core/css/css_counter_value.h"
-#include "third_party/blink/renderer/core/css/css_cursor_image_value.h"
-#include "third_party/blink/renderer/core/css/css_custom_property_declaration.h"
-#include "third_party/blink/renderer/core/css/css_function_value.h"
-#include "third_party/blink/renderer/core/css/css_grid_template_areas_value.h"
-#include "third_party/blink/renderer/core/css/css_image_set_value.h"
-#include "third_party/blink/renderer/core/css/css_layout_function_value.h"
-#include "third_party/blink/renderer/core/css/css_pending_substitution_value.h"
-#include "third_party/blink/renderer/core/css/css_primitive_value_mappings.h"
-#include "third_party/blink/renderer/core/css/css_property_value_set.h"
-#include "third_party/blink/renderer/core/css/css_resolution_units.h"
-#include "third_party/blink/renderer/core/css/css_value_id_mappings.h"
-#include "third_party/blink/renderer/core/css/css_variable_reference_value.h"
-#include "third_party/blink/renderer/core/css/properties/css_property.h"
-#include "third_party/blink/renderer/core/css/property_registration.h"
-#include "third_party/blink/renderer/core/css/property_registry.h"
-#include "third_party/blink/renderer/core/css/resolver/css_variable_resolver.h"
-#include "third_party/blink/renderer/core/css/resolver/element_style_resources.h"
-#include "third_party/blink/renderer/core/css/resolver/filter_operation_resolver.h"
-#include "third_party/blink/renderer/core/css/resolver/font_builder.h"
-#include "third_party/blink/renderer/core/css/resolver/style_builder.h"
-#include "third_party/blink/renderer/core/css/style_rule.h"
-#include "third_party/blink/renderer/core/css_property_names.h"
-#include "third_party/blink/renderer/core/css_value_keywords.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/use_counter.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/computed_style_constants.h"
-#include "third_party/blink/renderer/core/style/content_data.h"
-#include "third_party/blink/renderer/core/style/counter_content.h"
-#include "third_party/blink/renderer/core/style/quotes_data.h"
-#include "third_party/blink/renderer/core/style/style_generated_image.h"
-#include "third_party/blink/renderer/core/style/style_inherited_variables.h"
-#include "third_party/blink/renderer/core/style/style_non_inherited_variables.h"
-#include "third_party/blink/renderer/core/style/svg_computed_style.h"
-#include "third_party/blink/renderer/core/style_builder_functions.h"
-#include "third_party/blink/renderer/core/style_property_shorthand.h"
-#include "third_party/blink/renderer/platform/fonts/font_description.h"
-#include "third_party/blink/renderer/platform/wtf/math_extras.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-namespace {
-
-static inline bool IsValidVisitedLinkProperty(CSSPropertyID id) {
- switch (id) {
- case CSSPropertyBackgroundColor:
- case CSSPropertyBorderLeftColor:
- case CSSPropertyBorderRightColor:
- case CSSPropertyBorderTopColor:
- case CSSPropertyBorderBottomColor:
- case CSSPropertyCaretColor:
- case CSSPropertyColor:
- case CSSPropertyFill:
- case CSSPropertyOutlineColor:
- case CSSPropertyStroke:
- case CSSPropertyTextDecorationColor:
- case CSSPropertyColumnRuleColor:
- case CSSPropertyWebkitTextEmphasisColor:
- case CSSPropertyWebkitTextFillColor:
- case CSSPropertyWebkitTextStrokeColor:
- return true;
- default:
- return false;
- }
-}
-
-} // namespace
-
-void StyleBuilder::ApplyProperty(const CSSProperty& property,
- StyleResolverState& state,
- const CSSValue& value) {
- CSSPropertyID id = property.PropertyID();
- bool is_inherited = property.IsInherited();
- if (id != CSSPropertyVariable && (value.IsVariableReferenceValue() ||
- value.IsPendingSubstitutionValue())) {
- bool omit_animation_tainted =
- CSSAnimations::IsAnimationAffectingProperty(property);
- const CSSValue* resolved_value =
- CSSVariableResolver(state).ResolveVariableReferences(
- id, value, omit_animation_tainted);
- ApplyProperty(property, state, *resolved_value);
-
- if (!state.Style()->HasVariableReferenceFromNonInheritedProperty() &&
- !is_inherited)
- state.Style()->SetHasVariableReferenceFromNonInheritedProperty();
- return;
- }
-
- DCHECK(!property.IsShorthand())
- << "Shorthand property id = " << id << " wasn't expanded at parsing time";
-
- bool is_inherit = state.ParentNode() && value.IsInheritedValue();
- bool is_initial = value.IsInitialValue() ||
- (!state.ParentNode() && value.IsInheritedValue());
-
- // isInherit => !isInitial && isInitial => !isInherit
- DCHECK(!is_inherit || !is_initial);
- // isInherit => (state.parentNode() && state.parentStyle())
- DCHECK(!is_inherit || (state.ParentNode() && state.ParentStyle()));
-
- if (!state.ApplyPropertyToRegularStyle() &&
- (!state.ApplyPropertyToVisitedLinkStyle() ||
- !IsValidVisitedLinkProperty(id))) {
- // Limit the properties that can be applied to only the ones honored by
- // :visited.
- return;
- }
-
- if (is_inherit && !state.ParentStyle()->HasExplicitlyInheritedProperties() &&
- !is_inherited) {
- state.ParentStyle()->SetHasExplicitlyInheritedProperties();
- } else if (value.IsUnsetValue()) {
- DCHECK(!is_inherit && !is_initial);
- if (is_inherited)
- is_inherit = true;
- else
- is_initial = true;
- }
-
- StyleBuilder::ApplyProperty(property, state, value, is_initial, is_inherit);
-}
-
-void StyleBuilderFunctions::applyInitialCSSPropertyColor(
- StyleResolverState& state) {
- Color color = ComputedStyleInitialValues::InitialColor();
- if (state.ApplyPropertyToRegularStyle())
- state.Style()->SetColor(color);
- if (state.ApplyPropertyToVisitedLinkStyle())
- state.Style()->SetVisitedLinkColor(color);
-}
-
-void StyleBuilderFunctions::applyInheritCSSPropertyColor(
- StyleResolverState& state) {
- Color color = state.ParentStyle()->GetColor();
- if (state.ApplyPropertyToRegularStyle())
- state.Style()->SetColor(color);
- if (state.ApplyPropertyToVisitedLinkStyle())
- state.Style()->SetVisitedLinkColor(color);
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyColor(
- StyleResolverState& state,
- const CSSValue& value) {
- // As per the spec, 'color: currentColor' is treated as 'color: inherit'
- if (value.IsIdentifierValue() &&
- ToCSSIdentifierValue(value).GetValueID() == CSSValueCurrentcolor) {
- applyInheritCSSPropertyColor(state);
- return;
- }
-
- if (state.ApplyPropertyToRegularStyle())
- state.Style()->SetColor(StyleBuilderConverter::ConvertColor(state, value));
- if (state.ApplyPropertyToVisitedLinkStyle())
- state.Style()->SetVisitedLinkColor(
- StyleBuilderConverter::ConvertColor(state, value, true));
-}
-
-void StyleBuilderFunctions::applyInitialCSSPropertyCursor(
- StyleResolverState& state) {
- state.Style()->ClearCursorList();
- state.Style()->SetCursor(ComputedStyleInitialValues::InitialCursor());
-}
-
-void StyleBuilderFunctions::applyInheritCSSPropertyCursor(
- StyleResolverState& state) {
- state.Style()->SetCursor(state.ParentStyle()->Cursor());
- state.Style()->SetCursorList(state.ParentStyle()->Cursors());
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyCursor(
- StyleResolverState& state,
- const CSSValue& value) {
- state.Style()->ClearCursorList();
- if (value.IsValueList()) {
- state.Style()->SetCursor(ECursor::kAuto);
- for (const auto& item : ToCSSValueList(value)) {
- if (item->IsCursorImageValue()) {
- const cssvalue::CSSCursorImageValue& cursor =
- cssvalue::ToCSSCursorImageValue(*item);
- const CSSValue& image = cursor.ImageValue();
- state.Style()->AddCursor(state.GetStyleImage(CSSPropertyCursor, image),
- cursor.HotSpotSpecified(), cursor.HotSpot());
- } else {
- state.Style()->SetCursor(
- ToCSSIdentifierValue(*item).ConvertTo<ECursor>());
- }
- }
- } else {
- state.Style()->SetCursor(ToCSSIdentifierValue(value).ConvertTo<ECursor>());
- }
-}
-
-void StyleBuilderFunctions::applyInitialCSSPropertyDisplay(
- StyleResolverState& state) {
- state.Style()->SetDisplay(ComputedStyleInitialValues::InitialDisplay());
- state.Style()->SetDisplayLayoutCustomName(
- ComputedStyleInitialValues::InitialDisplayLayoutCustomName());
-}
-
-void StyleBuilderFunctions::applyInheritCSSPropertyDisplay(
- StyleResolverState& state) {
- state.Style()->SetDisplay(state.ParentStyle()->Display());
- state.Style()->SetDisplayLayoutCustomName(
- state.ParentStyle()->DisplayLayoutCustomName());
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyDisplay(
- StyleResolverState& state,
- const CSSValue& value) {
- if (value.IsIdentifierValue()) {
- state.Style()->SetDisplay(
- ToCSSIdentifierValue(value).ConvertTo<EDisplay>());
- state.Style()->SetDisplayLayoutCustomName(
- ComputedStyleInitialValues::InitialDisplayLayoutCustomName());
- return;
- }
-
- DCHECK(value.IsLayoutFunctionValue());
- const cssvalue::CSSLayoutFunctionValue& layout_function_value =
- cssvalue::ToCSSLayoutFunctionValue(value);
-
- EDisplay display = layout_function_value.IsInline()
- ? EDisplay::kInlineLayoutCustom
- : EDisplay::kLayoutCustom;
- state.Style()->SetDisplay(display);
- state.Style()->SetDisplayLayoutCustomName(layout_function_value.GetName());
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyDirection(
- StyleResolverState& state,
- const CSSValue& value) {
- state.Style()->SetDirection(
- ToCSSIdentifierValue(value).ConvertTo<TextDirection>());
-}
-
-void StyleBuilderFunctions::applyInitialCSSPropertyGridTemplateAreas(
- StyleResolverState& state) {
- state.Style()->SetNamedGridArea(
- ComputedStyleInitialValues::InitialNamedGridArea());
- state.Style()->SetNamedGridAreaRowCount(
- ComputedStyleInitialValues::InitialNamedGridAreaRowCount());
- state.Style()->SetNamedGridAreaColumnCount(
- ComputedStyleInitialValues::InitialNamedGridAreaColumnCount());
-}
-
-void StyleBuilderFunctions::applyInheritCSSPropertyGridTemplateAreas(
- StyleResolverState& state) {
- state.Style()->SetNamedGridArea(state.ParentStyle()->NamedGridArea());
- state.Style()->SetNamedGridAreaRowCount(
- state.ParentStyle()->NamedGridAreaRowCount());
- state.Style()->SetNamedGridAreaColumnCount(
- state.ParentStyle()->NamedGridAreaColumnCount());
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyGridTemplateAreas(
- StyleResolverState& state,
- const CSSValue& value) {
- if (value.IsIdentifierValue()) {
- // FIXME: Shouldn't we clear the grid-area values
- DCHECK_EQ(ToCSSIdentifierValue(value).GetValueID(), CSSValueNone);
- return;
- }
-
- const CSSGridTemplateAreasValue& grid_template_areas_value =
- ToCSSGridTemplateAreasValue(value);
- const NamedGridAreaMap& new_named_grid_areas =
- grid_template_areas_value.GridAreaMap();
-
- NamedGridLinesMap named_grid_column_lines;
- NamedGridLinesMap named_grid_row_lines;
- StyleBuilderConverter::ConvertOrderedNamedGridLinesMapToNamedGridLinesMap(
- state.Style()->OrderedNamedGridColumnLines(), named_grid_column_lines);
- StyleBuilderConverter::ConvertOrderedNamedGridLinesMapToNamedGridLinesMap(
- state.Style()->OrderedNamedGridRowLines(), named_grid_row_lines);
- StyleBuilderConverter::CreateImplicitNamedGridLinesFromGridArea(
- new_named_grid_areas, named_grid_column_lines, kForColumns);
- StyleBuilderConverter::CreateImplicitNamedGridLinesFromGridArea(
- new_named_grid_areas, named_grid_row_lines, kForRows);
- state.Style()->SetNamedGridColumnLines(named_grid_column_lines);
- state.Style()->SetNamedGridRowLines(named_grid_row_lines);
-
- state.Style()->SetNamedGridArea(new_named_grid_areas);
- state.Style()->SetNamedGridAreaRowCount(grid_template_areas_value.RowCount());
- state.Style()->SetNamedGridAreaColumnCount(
- grid_template_areas_value.ColumnCount());
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyListStyleImage(
- StyleResolverState& state,
- const CSSValue& value) {
- state.Style()->SetListStyleImage(
- state.GetStyleImage(CSSPropertyListStyleImage, value));
-}
-
-void StyleBuilderFunctions::applyInitialCSSPropertyOutlineStyle(
- StyleResolverState& state) {
- state.Style()->SetOutlineStyleIsAuto(
- ComputedStyleInitialValues::InitialOutlineStyleIsAuto());
- state.Style()->SetOutlineStyle(EBorderStyle::kNone);
-}
-
-void StyleBuilderFunctions::applyInheritCSSPropertyOutlineStyle(
- StyleResolverState& state) {
- state.Style()->SetOutlineStyleIsAuto(
- state.ParentStyle()->OutlineStyleIsAuto());
- state.Style()->SetOutlineStyle(state.ParentStyle()->OutlineStyle());
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyOutlineStyle(
- StyleResolverState& state,
- const CSSValue& value) {
- const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
- state.Style()->SetOutlineStyleIsAuto(
- static_cast<bool>(identifier_value.ConvertTo<OutlineIsAuto>()));
- state.Style()->SetOutlineStyle(identifier_value.ConvertTo<EBorderStyle>());
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyResize(
- StyleResolverState& state,
- const CSSValue& value) {
- const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
-
- EResize r = EResize::kNone;
- if (identifier_value.GetValueID() == CSSValueAuto) {
- if (Settings* settings = state.GetDocument().GetSettings()) {
- r = settings->GetTextAreasAreResizable() ? EResize::kBoth
- : EResize::kNone;
- }
- UseCounter::Count(state.GetDocument(), WebFeature::kCSSResizeAuto);
- } else {
- r = identifier_value.ConvertTo<EResize>();
- }
- state.Style()->SetResize(r);
-}
-
-static float MmToPx(float mm) {
- return mm * kCssPixelsPerMillimeter;
-}
-static float InchToPx(float inch) {
- return inch * kCssPixelsPerInch;
-}
-static FloatSize GetPageSizeFromName(const CSSIdentifierValue& page_size_name) {
- switch (page_size_name.GetValueID()) {
- case CSSValueA5:
- return FloatSize(MmToPx(148), MmToPx(210));
- case CSSValueA4:
- return FloatSize(MmToPx(210), MmToPx(297));
- case CSSValueA3:
- return FloatSize(MmToPx(297), MmToPx(420));
- case CSSValueB5:
- return FloatSize(MmToPx(176), MmToPx(250));
- case CSSValueB4:
- return FloatSize(MmToPx(250), MmToPx(353));
- case CSSValueLetter:
- return FloatSize(InchToPx(8.5), InchToPx(11));
- case CSSValueLegal:
- return FloatSize(InchToPx(8.5), InchToPx(14));
- case CSSValueLedger:
- return FloatSize(InchToPx(11), InchToPx(17));
- default:
- NOTREACHED();
- return FloatSize(0, 0);
- }
-}
-
-void StyleBuilderFunctions::applyInitialCSSPropertySize(StyleResolverState&) {}
-void StyleBuilderFunctions::applyInheritCSSPropertySize(StyleResolverState&) {}
-void StyleBuilderFunctions::applyValueCSSPropertySize(StyleResolverState& state,
- const CSSValue& value) {
- state.Style()->ResetPageSizeType();
- FloatSize size;
- EPageSizeType page_size_type = EPageSizeType::kAuto;
- const CSSValueList& list = ToCSSValueList(value);
- if (list.length() == 2) {
- // <length>{2} | <page-size> <orientation>
- const CSSValue& first = list.Item(0);
- const CSSValue& second = list.Item(1);
- if (first.IsPrimitiveValue() && ToCSSPrimitiveValue(first).IsLength()) {
- // <length>{2}
- size = FloatSize(
- ToCSSPrimitiveValue(first).ComputeLength<float>(
- state.CssToLengthConversionData().CopyWithAdjustedZoom(1.0)),
- ToCSSPrimitiveValue(second).ComputeLength<float>(
- state.CssToLengthConversionData().CopyWithAdjustedZoom(1.0)));
- } else {
- // <page-size> <orientation>
- size = GetPageSizeFromName(ToCSSIdentifierValue(first));
-
- DCHECK(ToCSSIdentifierValue(second).GetValueID() == CSSValueLandscape ||
- ToCSSIdentifierValue(second).GetValueID() == CSSValuePortrait);
- if (ToCSSIdentifierValue(second).GetValueID() == CSSValueLandscape)
- size = size.TransposedSize();
- }
- page_size_type = EPageSizeType::kResolved;
- } else {
- DCHECK_EQ(list.length(), 1U);
- // <length> | auto | <page-size> | [ portrait | landscape]
- const CSSValue& first = list.Item(0);
- if (first.IsPrimitiveValue() && ToCSSPrimitiveValue(first).IsLength()) {
- // <length>
- page_size_type = EPageSizeType::kResolved;
- float width = ToCSSPrimitiveValue(first).ComputeLength<float>(
- state.CssToLengthConversionData().CopyWithAdjustedZoom(1.0));
- size = FloatSize(width, width);
- } else {
- const CSSIdentifierValue& ident = ToCSSIdentifierValue(first);
- switch (ident.GetValueID()) {
- case CSSValueAuto:
- page_size_type = EPageSizeType::kAuto;
- break;
- case CSSValuePortrait:
- page_size_type = EPageSizeType::kPortrait;
- break;
- case CSSValueLandscape:
- page_size_type = EPageSizeType::kLandscape;
- break;
- default:
- // <page-size>
- page_size_type = EPageSizeType::kResolved;
- size = GetPageSizeFromName(ident);
- }
- }
- }
- state.Style()->SetPageSizeType(page_size_type);
- state.Style()->SetPageSize(size);
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyTextAlign(
- StyleResolverState& state,
- const CSSValue& value) {
- if (value.IsIdentifierValue() &&
- ToCSSIdentifierValue(value).GetValueID() != CSSValueWebkitMatchParent) {
- // Special case for th elements - UA stylesheet text-align does not apply if
- // parent's computed value for text-align is not its initial value
- // https://html.spec.whatwg.org/multipage/rendering.html#tables-2
- const CSSIdentifierValue& ident_value = ToCSSIdentifierValue(value);
- if (ident_value.GetValueID() == CSSValueInternalCenter &&
- state.ParentStyle()->GetTextAlign() !=
- ComputedStyleInitialValues::InitialTextAlign())
- state.Style()->SetTextAlign(state.ParentStyle()->GetTextAlign());
- else
- state.Style()->SetTextAlign(ident_value.ConvertTo<ETextAlign>());
- } else if (state.ParentStyle()->GetTextAlign() == ETextAlign::kStart) {
- state.Style()->SetTextAlign(state.ParentStyle()->IsLeftToRightDirection()
- ? ETextAlign::kLeft
- : ETextAlign::kRight);
- } else if (state.ParentStyle()->GetTextAlign() == ETextAlign::kEnd) {
- state.Style()->SetTextAlign(state.ParentStyle()->IsLeftToRightDirection()
- ? ETextAlign::kRight
- : ETextAlign::kLeft);
- } else {
- state.Style()->SetTextAlign(state.ParentStyle()->GetTextAlign());
- }
-}
-
-void StyleBuilderFunctions::applyInheritCSSPropertyTextIndent(
- StyleResolverState& state) {
- state.Style()->SetTextIndent(state.ParentStyle()->TextIndent());
- state.Style()->SetTextIndentLine(state.ParentStyle()->GetTextIndentLine());
- state.Style()->SetTextIndentType(state.ParentStyle()->GetTextIndentType());
-}
-
-void StyleBuilderFunctions::applyInitialCSSPropertyTextIndent(
- StyleResolverState& state) {
- state.Style()->SetTextIndent(ComputedStyleInitialValues::InitialTextIndent());
- state.Style()->SetTextIndentLine(
- ComputedStyleInitialValues::InitialTextIndentLine());
- state.Style()->SetTextIndentType(
- ComputedStyleInitialValues::InitialTextIndentType());
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyTextIndent(
- StyleResolverState& state,
- const CSSValue& value) {
- Length length_or_percentage_value;
- TextIndentLine text_indent_line_value =
- ComputedStyleInitialValues::InitialTextIndentLine();
- TextIndentType text_indent_type_value =
- ComputedStyleInitialValues::InitialTextIndentType();
-
- for (auto& list_value : ToCSSValueList(value)) {
- if (list_value->IsPrimitiveValue()) {
- length_or_percentage_value =
- ToCSSPrimitiveValue(*list_value)
- .ConvertToLength(state.CssToLengthConversionData());
- } else if (ToCSSIdentifierValue(*list_value).GetValueID() ==
- CSSValueEachLine) {
- text_indent_line_value = TextIndentLine::kEachLine;
- } else if (ToCSSIdentifierValue(*list_value).GetValueID() ==
- CSSValueHanging) {
- text_indent_type_value = TextIndentType::kHanging;
- } else {
- NOTREACHED();
- }
- }
-
- state.Style()->SetTextIndent(length_or_percentage_value);
- state.Style()->SetTextIndentLine(text_indent_line_value);
- state.Style()->SetTextIndentType(text_indent_type_value);
-}
-
-void StyleBuilderFunctions::applyInheritCSSPropertyVerticalAlign(
- StyleResolverState& state) {
- EVerticalAlign vertical_align = state.ParentStyle()->VerticalAlign();
- state.Style()->SetVerticalAlign(vertical_align);
- if (vertical_align == EVerticalAlign::kLength)
- state.Style()->SetVerticalAlignLength(
- state.ParentStyle()->GetVerticalAlignLength());
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyVerticalAlign(
- StyleResolverState& state,
- const CSSValue& value) {
- if (value.IsIdentifierValue()) {
- state.Style()->SetVerticalAlign(
- ToCSSIdentifierValue(value).ConvertTo<EVerticalAlign>());
- } else {
- state.Style()->SetVerticalAlignLength(
- ToCSSPrimitiveValue(value).ConvertToLength(
- state.CssToLengthConversionData()));
- }
-}
-
-void StyleBuilderFunctions::applyInitialCSSPropertyZoom(
- StyleResolverState& state) {
- state.SetZoom(ComputedStyleInitialValues::InitialZoom());
-}
-
-void StyleBuilderFunctions::applyInheritCSSPropertyZoom(
- StyleResolverState& state) {
- state.SetZoom(state.ParentStyle()->Zoom());
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyZoom(StyleResolverState& state,
- const CSSValue& value) {
- SECURITY_DCHECK(value.IsPrimitiveValue() || value.IsIdentifierValue());
-
- if (value.IsIdentifierValue()) {
- const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
- if (identifier_value.GetValueID() == CSSValueNormal) {
- state.SetZoom(ComputedStyleInitialValues::InitialZoom());
- }
- } else if (value.IsPrimitiveValue()) {
- const CSSPrimitiveValue& primitive_value = ToCSSPrimitiveValue(value);
- if (primitive_value.IsPercentage()) {
- if (float percent = primitive_value.GetFloatValue())
- state.SetZoom(percent / 100.0f);
- else
- state.SetZoom(1.0f);
- } else if (primitive_value.IsNumber()) {
- if (float number = primitive_value.GetFloatValue())
- state.SetZoom(number);
- else
- state.SetZoom(1.0f);
- }
- }
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyWebkitBorderImage(
- StyleResolverState& state,
- const CSSValue& value) {
- NinePieceImage image;
- CSSToStyleMap::MapNinePieceImage(state, CSSPropertyWebkitBorderImage, value,
- image);
- state.Style()->SetBorderImage(image);
-}
-
-void StyleBuilderFunctions::applyInitialCSSPropertyWebkitTextEmphasisStyle(
- StyleResolverState& state) {
- state.Style()->SetTextEmphasisFill(
- ComputedStyleInitialValues::InitialTextEmphasisFill());
- state.Style()->SetTextEmphasisMark(
- ComputedStyleInitialValues::InitialTextEmphasisMark());
- state.Style()->SetTextEmphasisCustomMark(
- ComputedStyleInitialValues::InitialTextEmphasisCustomMark());
-}
-
-void StyleBuilderFunctions::applyInheritCSSPropertyWebkitTextEmphasisStyle(
- StyleResolverState& state) {
- state.Style()->SetTextEmphasisFill(
- state.ParentStyle()->GetTextEmphasisFill());
- state.Style()->SetTextEmphasisMark(
- state.ParentStyle()->GetTextEmphasisMark());
- state.Style()->SetTextEmphasisCustomMark(
- state.ParentStyle()->TextEmphasisCustomMark());
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyWebkitTextEmphasisStyle(
- StyleResolverState& state,
- const CSSValue& value) {
- if (value.IsValueList()) {
- const CSSValueList& list = ToCSSValueList(value);
- DCHECK_EQ(list.length(), 2U);
- for (unsigned i = 0; i < 2; ++i) {
- const CSSIdentifierValue& value = ToCSSIdentifierValue(list.Item(i));
- if (value.GetValueID() == CSSValueFilled ||
- value.GetValueID() == CSSValueOpen)
- state.Style()->SetTextEmphasisFill(value.ConvertTo<TextEmphasisFill>());
- else
- state.Style()->SetTextEmphasisMark(value.ConvertTo<TextEmphasisMark>());
- }
- state.Style()->SetTextEmphasisCustomMark(g_null_atom);
- return;
- }
-
- if (value.IsStringValue()) {
- state.Style()->SetTextEmphasisFill(TextEmphasisFill::kFilled);
- state.Style()->SetTextEmphasisMark(TextEmphasisMark::kCustom);
- state.Style()->SetTextEmphasisCustomMark(
- AtomicString(ToCSSStringValue(value).Value()));
- return;
- }
-
- const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
-
- state.Style()->SetTextEmphasisCustomMark(g_null_atom);
-
- if (identifier_value.GetValueID() == CSSValueFilled ||
- identifier_value.GetValueID() == CSSValueOpen) {
- state.Style()->SetTextEmphasisFill(
- identifier_value.ConvertTo<TextEmphasisFill>());
- state.Style()->SetTextEmphasisMark(TextEmphasisMark::kAuto);
- } else {
- state.Style()->SetTextEmphasisFill(TextEmphasisFill::kFilled);
- state.Style()->SetTextEmphasisMark(
- identifier_value.ConvertTo<TextEmphasisMark>());
- }
-}
-
-void StyleBuilderFunctions::applyInitialCSSPropertyWillChange(
- StyleResolverState& state) {
- state.Style()->SetWillChangeContents(false);
- state.Style()->SetWillChangeScrollPosition(false);
- state.Style()->SetWillChangeProperties(Vector<CSSPropertyID>());
- state.Style()->SetSubtreeWillChangeContents(
- state.ParentStyle()->SubtreeWillChangeContents());
-}
-
-void StyleBuilderFunctions::applyInheritCSSPropertyWillChange(
- StyleResolverState& state) {
- state.Style()->SetWillChangeContents(
- state.ParentStyle()->WillChangeContents());
- state.Style()->SetWillChangeScrollPosition(
- state.ParentStyle()->WillChangeScrollPosition());
- state.Style()->SetWillChangeProperties(
- state.ParentStyle()->WillChangeProperties());
- state.Style()->SetSubtreeWillChangeContents(
- state.ParentStyle()->SubtreeWillChangeContents());
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyWillChange(
- StyleResolverState& state,
- const CSSValue& value) {
- bool will_change_contents = false;
- bool will_change_scroll_position = false;
- Vector<CSSPropertyID> will_change_properties;
-
- if (value.IsIdentifierValue()) {
- DCHECK_EQ(ToCSSIdentifierValue(value).GetValueID(), CSSValueAuto);
- } else {
- DCHECK(value.IsValueList());
- for (auto& will_change_value : ToCSSValueList(value)) {
- if (will_change_value->IsCustomIdentValue())
- will_change_properties.push_back(
- ToCSSCustomIdentValue(*will_change_value).ValueAsPropertyID());
- else if (ToCSSIdentifierValue(*will_change_value).GetValueID() ==
- CSSValueContents)
- will_change_contents = true;
- else if (ToCSSIdentifierValue(*will_change_value).GetValueID() ==
- CSSValueScrollPosition)
- will_change_scroll_position = true;
- else
- NOTREACHED();
- }
- }
- state.Style()->SetWillChangeContents(will_change_contents);
- state.Style()->SetWillChangeScrollPosition(will_change_scroll_position);
- state.Style()->SetWillChangeProperties(will_change_properties);
- state.Style()->SetSubtreeWillChangeContents(
- will_change_contents || state.ParentStyle()->SubtreeWillChangeContents());
-}
-
-void StyleBuilderFunctions::applyInitialCSSPropertyContent(
- StyleResolverState& state) {
- state.Style()->SetContent(nullptr);
-}
-
-void StyleBuilderFunctions::applyInheritCSSPropertyContent(
- StyleResolverState&) {
- // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not.
- // This note is a reminder that eventually "inherit" needs to be supported.
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyContent(
- StyleResolverState& state,
- const CSSValue& value) {
- if (value.IsIdentifierValue()) {
- DCHECK(ToCSSIdentifierValue(value).GetValueID() == CSSValueNormal ||
- ToCSSIdentifierValue(value).GetValueID() == CSSValueNone);
- state.Style()->SetContent(nullptr);
- return;
- }
-
- ContentData* first_content = nullptr;
- ContentData* prev_content = nullptr;
- for (auto& item : ToCSSValueList(value)) {
- ContentData* next_content = nullptr;
- if (item->IsImageGeneratorValue() || item->IsImageSetValue() ||
- item->IsImageValue()) {
- next_content =
- ContentData::Create(state.GetStyleImage(CSSPropertyContent, *item));
- } else if (item->IsCounterValue()) {
- const cssvalue::CSSCounterValue* counter_value =
- cssvalue::ToCSSCounterValue(item.Get());
- const auto list_style_type =
- CssValueIDToPlatformEnum<EListStyleType>(counter_value->ListStyle());
- std::unique_ptr<CounterContent> counter =
- std::make_unique<CounterContent>(
- AtomicString(counter_value->Identifier()), list_style_type,
- AtomicString(counter_value->Separator()));
- next_content = ContentData::Create(std::move(counter));
- } else if (item->IsIdentifierValue()) {
- QuoteType quote_type;
- switch (ToCSSIdentifierValue(*item).GetValueID()) {
- default:
- NOTREACHED();
- FALLTHROUGH;
- case CSSValueOpenQuote:
- quote_type = QuoteType::kOpen;
- break;
- case CSSValueCloseQuote:
- quote_type = QuoteType::kClose;
- break;
- case CSSValueNoOpenQuote:
- quote_type = QuoteType::kNoOpen;
- break;
- case CSSValueNoCloseQuote:
- quote_type = QuoteType::kNoClose;
- break;
- }
- next_content = ContentData::Create(quote_type);
- } else {
- String string;
- if (item->IsFunctionValue()) {
- const CSSFunctionValue* function_value = ToCSSFunctionValue(item.Get());
- DCHECK_EQ(function_value->FunctionType(), CSSValueAttr);
- state.Style()->SetUnique();
- // TODO: Can a namespace be specified for an attr(foo)?
- QualifiedName attr(
- g_null_atom, ToCSSCustomIdentValue(function_value->Item(0)).Value(),
- g_null_atom);
- const AtomicString& value = state.GetElement()->getAttribute(attr);
- string = value.IsNull() ? g_empty_string : value.GetString();
- } else {
- string = ToCSSStringValue(*item).Value();
- }
- if (prev_content && prev_content->IsText()) {
- TextContentData* text_content = ToTextContentData(prev_content);
- text_content->SetText(text_content->GetText() + string);
- continue;
- }
- next_content = ContentData::Create(string);
- }
-
- if (!first_content)
- first_content = next_content;
- else
- prev_content->SetNext(next_content);
-
- prev_content = next_content;
- }
- DCHECK(first_content);
- state.Style()->SetContent(first_content);
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyWebkitLocale(
- StyleResolverState& state,
- const CSSValue& value) {
- if (value.IsIdentifierValue()) {
- DCHECK_EQ(ToCSSIdentifierValue(value).GetValueID(), CSSValueAuto);
- state.GetFontBuilder().SetLocale(nullptr);
- } else {
- state.GetFontBuilder().SetLocale(
- LayoutLocale::Get(AtomicString(ToCSSStringValue(value).Value())));
- }
-}
-
-void StyleBuilderFunctions::applyInitialCSSPropertyWebkitAppRegion(
- StyleResolverState&) {}
-
-void StyleBuilderFunctions::applyInheritCSSPropertyWebkitAppRegion(
- StyleResolverState&) {}
-
-void StyleBuilderFunctions::applyValueCSSPropertyWebkitAppRegion(
- StyleResolverState& state,
- const CSSValue& value) {
- const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
- state.Style()->SetDraggableRegionMode(identifier_value.GetValueID() ==
- CSSValueDrag
- ? EDraggableRegionMode::kDrag
- : EDraggableRegionMode::kNoDrag);
- state.GetDocument().SetHasAnnotatedRegions(true);
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyWritingMode(
- StyleResolverState& state,
- const CSSValue& value) {
- state.SetWritingMode(ToCSSIdentifierValue(value).ConvertTo<WritingMode>());
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyWebkitWritingMode(
- StyleResolverState& state,
- const CSSValue& value) {
- state.SetWritingMode(ToCSSIdentifierValue(value).ConvertTo<WritingMode>());
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyTextOrientation(
- StyleResolverState& state,
- const CSSValue& value) {
- state.SetTextOrientation(
- ToCSSIdentifierValue(value).ConvertTo<ETextOrientation>());
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyWebkitTextOrientation(
- StyleResolverState& state,
- const CSSValue& value) {
- state.SetTextOrientation(
- ToCSSIdentifierValue(value).ConvertTo<ETextOrientation>());
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyVariable(
- StyleResolverState& state,
- const CSSValue& value) {
- const CSSCustomPropertyDeclaration& declaration =
- ToCSSCustomPropertyDeclaration(value);
- const AtomicString& name = declaration.GetName();
- const PropertyRegistration* registration = nullptr;
- const PropertyRegistry* registry = state.GetDocument().GetPropertyRegistry();
- if (registry)
- registration = registry->Registration(name);
-
- bool is_inherited_property = !registration || registration->Inherits();
- bool initial = declaration.IsInitial(is_inherited_property);
- bool inherit = declaration.IsInherit(is_inherited_property);
- DCHECK(!(initial && inherit));
-
- if (!initial && !inherit) {
- if (declaration.Value()->NeedsVariableResolution()) {
- if (is_inherited_property)
- state.Style()->SetUnresolvedInheritedVariable(name,
- declaration.Value());
- else
- state.Style()->SetUnresolvedNonInheritedVariable(name,
- declaration.Value());
- return;
- }
-
- if (!registration) {
- state.Style()->SetResolvedUnregisteredVariable(name, declaration.Value());
- return;
- }
-
- const CSSValue* parsed_value = declaration.Value()->ParseForSyntax(
- registration->Syntax(), state.GetDocument().GetSecureContextMode());
- if (parsed_value) {
- DCHECK(parsed_value);
- if (is_inherited_property)
- state.Style()->SetResolvedInheritedVariable(name, declaration.Value(),
- parsed_value);
- else
- state.Style()->SetResolvedNonInheritedVariable(
- name, declaration.Value(), parsed_value);
- return;
- }
- if (is_inherited_property)
- inherit = true;
- else
- initial = true;
- }
- DCHECK(initial ^ inherit);
-
- state.Style()->RemoveVariable(name, is_inherited_property);
- if (initial) {
- return;
- }
-
- DCHECK(inherit);
- CSSVariableData* parent_value =
- state.ParentStyle()->GetVariable(name, is_inherited_property);
- const CSSValue* parent_css_value =
- registration && parent_value ? state.ParentStyle()->GetRegisteredVariable(
- name, is_inherited_property)
- : nullptr;
-
- if (!is_inherited_property) {
- DCHECK(registration);
- if (parent_value) {
- state.Style()->SetResolvedNonInheritedVariable(name, parent_value,
- parent_css_value);
- }
- return;
- }
-
- if (parent_value) {
- if (!registration) {
- state.Style()->SetResolvedUnregisteredVariable(name, parent_value);
- } else {
- state.Style()->SetResolvedInheritedVariable(name, parent_value,
- parent_css_value);
- }
- }
-}
-
-void StyleBuilderFunctions::applyInheritCSSPropertyBaselineShift(
- StyleResolverState& state) {
- const SVGComputedStyle& parent_svg_style = state.ParentStyle()->SvgStyle();
- EBaselineShift baseline_shift = parent_svg_style.BaselineShift();
- SVGComputedStyle& svg_style = state.Style()->AccessSVGStyle();
- svg_style.SetBaselineShift(baseline_shift);
- if (baseline_shift == BS_LENGTH)
- svg_style.SetBaselineShiftValue(parent_svg_style.BaselineShiftValue());
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyBaselineShift(
- StyleResolverState& state,
- const CSSValue& value) {
- SVGComputedStyle& svg_style = state.Style()->AccessSVGStyle();
- if (!value.IsIdentifierValue()) {
- svg_style.SetBaselineShift(BS_LENGTH);
- svg_style.SetBaselineShiftValue(StyleBuilderConverter::ConvertLength(
- state, ToCSSPrimitiveValue(value)));
- return;
- }
- switch (ToCSSIdentifierValue(value).GetValueID()) {
- case CSSValueBaseline:
- svg_style.SetBaselineShift(BS_LENGTH);
- svg_style.SetBaselineShiftValue(Length(kFixed));
- return;
- case CSSValueSub:
- svg_style.SetBaselineShift(BS_SUB);
- return;
- case CSSValueSuper:
- svg_style.SetBaselineShift(BS_SUPER);
- return;
- default:
- NOTREACHED();
- }
-}
-
-void StyleBuilderFunctions::applyInheritCSSPropertyPosition(
- StyleResolverState& state) {
- if (!state.ParentNode()->IsDocumentNode())
- state.Style()->SetPosition(state.ParentStyle()->GetPosition());
-}
-
-void StyleBuilderFunctions::applyInitialCSSPropertyCaretColor(
- StyleResolverState& state) {
- StyleAutoColor color = StyleAutoColor::AutoColor();
- if (state.ApplyPropertyToRegularStyle())
- state.Style()->SetCaretColor(color);
- if (state.ApplyPropertyToVisitedLinkStyle())
- state.Style()->SetVisitedLinkCaretColor(color);
-}
-
-void StyleBuilderFunctions::applyInheritCSSPropertyCaretColor(
- StyleResolverState& state) {
- StyleAutoColor color = state.ParentStyle()->CaretColor();
- if (state.ApplyPropertyToRegularStyle())
- state.Style()->SetCaretColor(color);
- if (state.ApplyPropertyToVisitedLinkStyle())
- state.Style()->SetVisitedLinkCaretColor(color);
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyCaretColor(
- StyleResolverState& state,
- const CSSValue& value) {
- if (state.ApplyPropertyToRegularStyle()) {
- state.Style()->SetCaretColor(
- StyleBuilderConverter::ConvertStyleAutoColor(state, value));
- }
- if (state.ApplyPropertyToVisitedLinkStyle()) {
- state.Style()->SetVisitedLinkCaretColor(
- StyleBuilderConverter::ConvertStyleAutoColor(state, value, true));
- }
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyBorderImageSource(
- StyleResolverState& state,
- const CSSValue& value) {
- state.Style()->SetBorderImageSource(
- state.GetStyleImage(CSSPropertyBorderImageSource, value));
-}
-
-void StyleBuilderFunctions::applyValueCSSPropertyWebkitMaskBoxImageSource(
- StyleResolverState& state,
- const CSSValue& value) {
- state.Style()->SetMaskBoxImageSource(
- state.GetStyleImage(CSSPropertyWebkitMaskBoxImageSource, value));
-}
-
-} // 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 d170555230d..2721c53f4eb 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
@@ -86,7 +86,6 @@
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
#include "third_party/blink/renderer/core/html/html_slot_element.h"
#include "third_party/blink/renderer/core/html_names.h"
-#include "third_party/blink/renderer/core/layout/generated_children.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"
@@ -281,17 +280,16 @@ void StyleResolver::MatchPseudoPartRules(const Element& element,
collector.FinishAddingAuthorRulesForTreeScope();
}
- // We have reached the top-level document.
- if (!(host = host->OwnerShadowHost()))
- return;
-
- // After the direct host of the element, if the host doesn't forward any
- // parts using partmap= then the element is unreachable from any scope above
- // and we can stop.
+ // If the host doesn't forward any parts using partmap= then the element is
+ // unreachable from any scope further above and we can stop.
const NamesMap* part_map = host->PartNamesMap();
if (!part_map)
return;
+ // We have reached the top-level document.
+ if (!(host = host->OwnerShadowHost()))
+ return;
+
current_names.PushMap(*part_map);
}
}
@@ -805,79 +803,9 @@ scoped_refptr<AnimatableValue> StyleResolver::CreateAnimatableValueSnapshot(
return CSSAnimatableValueFactory::Create(property, *state.Style());
}
-PseudoElement* StyleResolver::CreatePseudoElement(Element* parent,
- PseudoId pseudo_id) {
- if (pseudo_id == kPseudoIdFirstLetter)
- return FirstLetterPseudoElement::Create(parent);
- return PseudoElement::Create(parent, pseudo_id);
-}
-
-PseudoElement* StyleResolver::CreatePseudoElementIfNeeded(Element& parent,
- PseudoId pseudo_id) {
- if (!parent.CanGeneratePseudoElement(pseudo_id))
- return nullptr;
-
- LayoutObject* parent_layout_object = parent.GetLayoutObject();
- if (!parent_layout_object) {
- DCHECK(parent.HasDisplayContentsStyle());
- parent_layout_object =
- LayoutTreeBuilderTraversal::ParentLayoutObject(parent);
- }
-
- if (!parent_layout_object)
- return nullptr;
-
- ComputedStyle* parent_style = parent.MutableComputedStyle();
- DCHECK(parent_style);
-
- // The first letter pseudo element has to look up the tree and see if any
- // of the ancestors are first letter.
- if (pseudo_id < kFirstInternalPseudoId && pseudo_id != kPseudoIdFirstLetter &&
- !parent_style->HasPseudoStyle(pseudo_id)) {
- return nullptr;
- }
-
- if (pseudo_id == kPseudoIdBackdrop && !parent.IsInTopLayer())
- return nullptr;
-
- if (pseudo_id == kPseudoIdFirstLetter &&
- (parent.IsSVGElement() ||
- !FirstLetterPseudoElement::FirstLetterTextLayoutObject(parent)))
- return nullptr;
-
- if (!CanHaveGeneratedChildren(*parent_layout_object))
- return nullptr;
-
- if (ComputedStyle* cached_style =
- parent_style->GetCachedPseudoStyle(pseudo_id)) {
- if (!PseudoElementLayoutObjectIsNeeded(cached_style))
- return nullptr;
- return CreatePseudoElement(&parent, pseudo_id);
- }
-
- StyleResolverState state(GetDocument(), &parent, parent_style,
- parent_layout_object->Style());
- if (!PseudoStyleForElementInternal(parent, pseudo_id, parent_style, state))
- return nullptr;
- scoped_refptr<ComputedStyle> style = state.TakeStyle();
- DCHECK(style);
- parent_style->AddCachedPseudoStyle(style);
-
- if (!PseudoElementLayoutObjectIsNeeded(style.get()))
- return nullptr;
-
- PseudoElement* pseudo = CreatePseudoElement(&parent, pseudo_id);
-
- SetAnimationUpdateIfNeeded(state, *pseudo);
- if (ElementAnimations* element_animations = pseudo->GetElementAnimations())
- element_animations->CssAnimations().MaybeApplyPendingUpdate(pseudo);
- return pseudo;
-}
-
bool StyleResolver::PseudoStyleForElementInternal(
Element& element,
const PseudoStyleRequest& pseudo_style_request,
- const ComputedStyle* parent_style,
StyleResolverState& state) {
DCHECK(GetDocument().GetFrame());
DCHECK(GetDocument().GetSettings());
@@ -967,8 +895,7 @@ scoped_refptr<ComputedStyle> StyleResolver::PseudoStyleForElement(
StyleResolverState state(GetDocument(), element, parent_style,
parent_layout_object_style);
- if (!PseudoStyleForElementInternal(*element, pseudo_style_request,
- parent_style, state)) {
+ if (!PseudoStyleForElementInternal(*element, pseudo_style_request, state)) {
if (pseudo_style_request.type == PseudoStyleRequest::kForRenderer)
return nullptr;
return state.TakeStyle();
@@ -1373,6 +1300,14 @@ static inline bool IsValidFirstLetterStyleProperty(CSSPropertyID id) {
case CSSPropertyBackgroundRepeatX:
case CSSPropertyBackgroundRepeatY:
case CSSPropertyBackgroundSize:
+ case CSSPropertyBorderBlockEnd:
+ case CSSPropertyBorderBlockEndColor:
+ case CSSPropertyBorderBlockEndStyle:
+ case CSSPropertyBorderBlockEndWidth:
+ case CSSPropertyBorderBlockStart:
+ case CSSPropertyBorderBlockStartColor:
+ case CSSPropertyBorderBlockStartStyle:
+ case CSSPropertyBorderBlockStartWidth:
case CSSPropertyBorderBottomColor:
case CSSPropertyBorderBottomLeftRadius:
case CSSPropertyBorderBottomRightRadius:
@@ -1383,6 +1318,14 @@ static inline bool IsValidFirstLetterStyleProperty(CSSPropertyID id) {
case CSSPropertyBorderImageSlice:
case CSSPropertyBorderImageSource:
case CSSPropertyBorderImageWidth:
+ case CSSPropertyBorderInlineEnd:
+ case CSSPropertyBorderInlineEndColor:
+ case CSSPropertyBorderInlineEndStyle:
+ case CSSPropertyBorderInlineEndWidth:
+ case CSSPropertyBorderInlineStart:
+ case CSSPropertyBorderInlineStartColor:
+ case CSSPropertyBorderInlineStartStyle:
+ case CSSPropertyBorderInlineStartWidth:
case CSSPropertyBorderLeftColor:
case CSSPropertyBorderLeftStyle:
case CSSPropertyBorderLeftWidth:
@@ -1413,7 +1356,11 @@ static inline bool IsValidFirstLetterStyleProperty(CSSPropertyID id) {
case CSSPropertyFontWeight:
case CSSPropertyLetterSpacing:
case CSSPropertyLineHeight:
+ case CSSPropertyMarginBlockEnd:
+ case CSSPropertyMarginBlockStart:
case CSSPropertyMarginBottom:
+ case CSSPropertyMarginInlineEnd:
+ case CSSPropertyMarginInlineStart:
case CSSPropertyMarginLeft:
case CSSPropertyMarginRight:
case CSSPropertyMarginTop:
@@ -1431,34 +1378,14 @@ static inline bool IsValidFirstLetterStyleProperty(CSSPropertyID id) {
case CSSPropertyTextTransform:
case CSSPropertyTextUnderlinePosition:
case CSSPropertyVerticalAlign:
- case CSSPropertyWebkitBorderAfter:
- case CSSPropertyWebkitBorderAfterColor:
- case CSSPropertyWebkitBorderAfterStyle:
- case CSSPropertyWebkitBorderAfterWidth:
- case CSSPropertyWebkitBorderBefore:
- case CSSPropertyWebkitBorderBeforeColor:
- case CSSPropertyWebkitBorderBeforeStyle:
- case CSSPropertyWebkitBorderBeforeWidth:
- case CSSPropertyWebkitBorderEnd:
- case CSSPropertyWebkitBorderEndColor:
- case CSSPropertyWebkitBorderEndStyle:
- case CSSPropertyWebkitBorderEndWidth:
case CSSPropertyWebkitBorderHorizontalSpacing:
case CSSPropertyWebkitBorderImage:
- case CSSPropertyWebkitBorderStart:
- case CSSPropertyWebkitBorderStartColor:
- case CSSPropertyWebkitBorderStartStyle:
- case CSSPropertyWebkitBorderStartWidth:
case CSSPropertyWebkitBorderVerticalSpacing:
case CSSPropertyWebkitFontSmoothing:
- case CSSPropertyWebkitMarginAfter:
case CSSPropertyWebkitMarginAfterCollapse:
- case CSSPropertyWebkitMarginBefore:
case CSSPropertyWebkitMarginBeforeCollapse:
case CSSPropertyWebkitMarginBottomCollapse:
case CSSPropertyWebkitMarginCollapse:
- case CSSPropertyWebkitMarginEnd:
- case CSSPropertyWebkitMarginStart:
case CSSPropertyWebkitMarginTopCollapse:
case CSSPropertyWordSpacing:
return true;
@@ -1599,7 +1526,10 @@ void StyleResolver::ApplyProperties(
// non-inherited properties as they might override the value inherited
// here. For this reason we don't allow declarations with explicitly
// inherited properties to be cached.
- DCHECK(!current.Value().IsInheritedValue());
+ DCHECK(!current.Value().IsInheritedValue() ||
+ (!state.ApplyPropertyToRegularStyle() &&
+ (!state.ApplyPropertyToVisitedLinkStyle() ||
+ !current.Property().IsValidForVisitedLink())));
continue;
}
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 3a3a49c24ee..2d63cf39116 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
@@ -133,8 +133,6 @@ class CORE_EXPORT StyleResolver final
return style_not_yet_available_;
}
- PseudoElement* CreatePseudoElementIfNeeded(Element& parent, PseudoId);
-
void SetRuleUsageTracker(StyleRuleUsageTracker*);
void UpdateMediaType();
@@ -280,15 +278,10 @@ class CORE_EXPORT StyleResolver final
bool PseudoStyleForElementInternal(Element&,
const PseudoStyleRequest&,
- const ComputedStyle* parent_style,
StyleResolverState&);
bool HasAuthorBorder(const StyleResolverState&);
-
- PseudoElement* CreatePseudoElement(Element* parent, PseudoId);
-
Document& GetDocument() const { return *document_; }
-
bool WasViewportResized() const { return was_viewport_resized_; }
static ComputedStyle* style_not_yet_available_;
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 202cf64b1ef..2957bc5bd55 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
@@ -43,12 +43,13 @@
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
-#include "third_party/blink/renderer/core/dom/viewport_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/frame/settings.h"
+#include "third_party/blink/renderer/core/frame/viewport_data.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/viewport_description.h"
namespace blink {
@@ -56,7 +57,7 @@ namespace {
bool HasViewportFitProperty(const CSSPropertyValueSet* property_set) {
DCHECK(property_set);
- return RuntimeEnabledFeatures::DisplayCutoutViewportFitEnabled() &&
+ return RuntimeEnabledFeatures::DisplayCutoutAPIEnabled() &&
property_set->HasProperty(CSSPropertyViewportFit);
}
@@ -197,7 +198,7 @@ void ViewportStyleResolver::AddViewportRule(StyleRuleViewport& viewport_rule,
void ViewportStyleResolver::Resolve() {
if (!property_set_) {
- document_->SetViewportDescription(
+ document_->GetViewportData().SetViewportDescription(
ViewportDescription(ViewportDescription::kUserAgentStyleSheet));
return;
}
@@ -218,7 +219,7 @@ void ViewportStyleResolver::Resolve() {
if (HasViewportFitProperty(property_set_))
description.SetViewportFit(ViewportFitValue());
- document_->SetViewportDescription(description);
+ document_->GetViewportData().SetViewportDescription(description);
DCHECK(initial_style_);
if (initial_style_->HasViewportUnits())
@@ -322,24 +323,23 @@ Length ViewportStyleResolver::ViewportLengthValue(CSSPropertyID id) {
return result;
}
-ViewportDescription::ViewportFit ViewportStyleResolver::ViewportFitValue()
- const {
+mojom::ViewportFit ViewportStyleResolver::ViewportFitValue() const {
const CSSValue* value =
property_set_->GetPropertyCSSValue(CSSPropertyViewportFit);
if (value->IsIdentifierValue()) {
switch (ToCSSIdentifierValue(value)->GetValueID()) {
case CSSValueCover:
- return ViewportDescription::ViewportFit::kCover;
+ return mojom::ViewportFit::kCover;
case CSSValueContain:
- return ViewportDescription::ViewportFit::kContain;
+ return mojom::ViewportFit::kContain;
case CSSValueAuto:
default:
- return ViewportDescription::ViewportFit::kAuto;
+ return mojom::ViewportFit::kAuto;
}
}
NOTREACHED();
- return ViewportDescription::ViewportFit::kAuto;
+ return mojom::ViewportFit::kAuto;
}
void ViewportStyleResolver::InitialStyleChanged() {
diff --git a/chromium/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h b/chromium/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h
index 45a122db35f..541f3b6a2fc 100644
--- a/chromium/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h
+++ b/chromium/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h
@@ -33,7 +33,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/rule_set.h"
#include "third_party/blink/renderer/core/css_property_names.h"
-#include "third_party/blink/renderer/core/dom/viewport_description.h"
+#include "third_party/blink/renderer/core/page/viewport_description.h"
#include "third_party/blink/renderer/platform/length.h"
namespace blink {
@@ -79,7 +79,7 @@ class CORE_EXPORT ViewportStyleResolver
float ViewportArgumentValue(CSSPropertyID) const;
Length ViewportLengthValue(CSSPropertyID);
- ViewportDescription::ViewportFit ViewportFitValue() const;
+ mojom::ViewportFit ViewportFitValue() const;
Member<Document> document_;
Member<MutableCSSPropertyValueSet> property_set_;
diff --git a/chromium/third_party/blink/renderer/core/css/rule_feature_set.cc b/chromium/third_party/blink/renderer/core/css/rule_feature_set.cc
index 74a63d88de3..e709eafa7af 100644
--- a/chromium/third_party/blink/renderer/core/css/rule_feature_set.cc
+++ b/chromium/third_party/blink/renderer/core/css/rule_feature_set.cc
@@ -158,6 +158,7 @@ bool SupportsInvalidation(CSSSelector::PseudoType type) {
case CSSSelector::kPseudoHost:
case CSSSelector::kPseudoShadow:
case CSSSelector::kPseudoSpatialNavigationFocus:
+ case CSSSelector::kPseudoIsHtml:
case CSSSelector::kPseudoListBox:
case CSSSelector::kPseudoHostHasAppearance:
case CSSSelector::kPseudoSlotted:
@@ -480,7 +481,6 @@ InvalidationSet* RuleFeatureSet::InvalidationSetForSimpleSelector(
case CSSSelector::kPseudoDefined:
case CSSSelector::kPseudoVideoPersistent:
case CSSSelector::kPseudoVideoPersistentAncestor:
- case CSSSelector::kPseudoPart:
return &EnsurePseudoInvalidationSet(selector.GetPseudoType(), type,
position);
case CSSSelector::kPseudoFirstOfType:
@@ -491,6 +491,7 @@ InvalidationSet* RuleFeatureSet::InvalidationSetForSimpleSelector(
case CSSSelector::kPseudoNthLastChild:
case CSSSelector::kPseudoNthLastOfType:
return &EnsureNthInvalidationSet();
+ case CSSSelector::kPseudoPart:
default:
break;
}
@@ -602,7 +603,6 @@ RuleFeatureSet::ExtractInvalidationSetFeaturesFromSelectorList(
const CSSSelectorList* selector_list = simple_selector.SelectorList();
if (!selector_list)
return kNormalInvalidation;
-
DCHECK(SupportsInvalidationWithSelectorList(simple_selector.GetPseudoType()));
const CSSSelector* sub_selector = selector_list->First();
@@ -686,6 +686,9 @@ const CSSSelector* RuleFeatureSet::ExtractInvalidationSetFeaturesFromCompound(
return nullptr;
}
+ if (features.invalidation_flags.InvalidatesParts())
+ metadata_.invalidates_parts = true;
+
if (!simple_selector->TagHistory() ||
simple_selector->Relation() != CSSSelector::kSubSelector) {
features.has_features_for_rule_set_invalidation =
@@ -940,6 +943,7 @@ void RuleFeatureSet::FeatureMetadata::Clear() {
uses_window_inactive_selector = false;
needs_full_recalc_for_rule_set_invalidation = false;
max_direct_adjacent_selectors = 0;
+ invalidates_parts = false;
}
void RuleFeatureSet::Add(const RuleFeatureSet& other) {
@@ -977,6 +981,8 @@ void RuleFeatureSet::Add(const RuleFeatureSet& other) {
}
if (other.nth_invalidation_set_)
EnsureNthInvalidationSet().Combine(*other.nth_invalidation_set_);
+ if (other.metadata_.invalidates_parts)
+ metadata_.invalidates_parts = true;
metadata_.Add(other.metadata_);
@@ -1199,6 +1205,14 @@ DescendantInvalidationSet& RuleFeatureSet::EnsureNthInvalidationSet() {
return *nth_invalidation_set_;
}
+void RuleFeatureSet::CollectPartInvalidationSet(
+ InvalidationLists& invalidation_lists) const {
+ if (metadata_.invalidates_parts) {
+ invalidation_lists.descendants.push_back(
+ InvalidationSet::PartInvalidationSet());
+ }
+}
+
void RuleFeatureSet::CollectTypeRuleInvalidationSet(
InvalidationLists& invalidation_lists,
ContainerNode& root_node) const {
diff --git a/chromium/third_party/blink/renderer/core/css/rule_feature_set.h b/chromium/third_party/blink/renderer/core/css/rule_feature_set.h
index 83bb2a96f58..e8e30a85f1e 100644
--- a/chromium/third_party/blink/renderer/core/css/rule_feature_set.h
+++ b/chromium/third_party/blink/renderer/core/css/rule_feature_set.h
@@ -41,6 +41,10 @@ struct InvalidationLists;
class QualifiedName;
class RuleData;
+// Summarizes and indexes the contents of RuleData objects. It creates
+// invalidation sets from rule data and makes them available via several
+// CollectInvalidationSetForFoo methods which use the indices to quickly gather
+// the relevant InvalidationSets for a particular DOM mutation.
class CORE_EXPORT RuleFeatureSet {
DISALLOW_NEW();
@@ -48,6 +52,7 @@ class CORE_EXPORT RuleFeatureSet {
RuleFeatureSet();
~RuleFeatureSet();
+ // Methods for updating the data in this object.
void Add(const RuleFeatureSet&);
void Clear();
@@ -55,6 +60,7 @@ class CORE_EXPORT RuleFeatureSet {
SelectorPreMatch CollectFeaturesFromRuleData(const RuleData&);
+ // Methods for accessing the data in this object.
bool UsesFirstLineRules() const { return metadata_.uses_first_line_rules; }
bool UsesWindowInactiveSelector() const {
return metadata_.uses_window_inactive_selector;
@@ -127,9 +133,11 @@ class CORE_EXPORT RuleFeatureSet {
InvalidationLists&,
unsigned min_direct_adjacent) const;
void CollectNthInvalidationSet(InvalidationLists&) const;
+ void CollectPartInvalidationSet(InvalidationLists&) const;
void CollectTypeRuleInvalidationSet(InvalidationLists&, ContainerNode&) const;
bool HasIdsInSelectors() const { return id_invalidation_sets_.size() > 0; }
+ bool InvalidatesParts() const { return metadata_.invalidates_parts; }
bool IsAlive() const { return is_alive_; }
@@ -161,6 +169,7 @@ class CORE_EXPORT RuleFeatureSet {
bool uses_window_inactive_selector = false;
bool needs_full_recalc_for_rule_set_invalidation = false;
unsigned max_direct_adjacent_selectors = 0;
+ bool invalidates_parts = false;
};
SelectorPreMatch CollectFeaturesFromSelector(const CSSSelector&,
@@ -182,6 +191,7 @@ class CORE_EXPORT RuleFeatureSet {
SiblingInvalidationSet& EnsureUniversalSiblingInvalidationSet();
DescendantInvalidationSet& EnsureNthInvalidationSet();
DescendantInvalidationSet& EnsureTypeRuleInvalidationSet();
+ DescendantInvalidationSet& EnsurePartInvalidationSet();
void UpdateInvalidationSets(const RuleData&);
void UpdateInvalidationSetsForContentAttribute(const RuleData&);
@@ -203,7 +213,6 @@ class CORE_EXPORT RuleFeatureSet {
bool content_pseudo_crossing = false;
bool has_nth_pseudo = false;
bool has_features_for_rule_set_invalidation = false;
- bool invalidates_parts = false; // ::part() selector
};
static void ExtractInvalidationSetFeature(const CSSSelector&,
diff --git a/chromium/third_party/blink/renderer/core/css/rule_feature_set_test.cc b/chromium/third_party/blink/renderer/core/css/rule_feature_set_test.cc
index 4acfb92dcfe..e618a35b850 100644
--- a/chromium/third_party/blink/renderer/core/css/rule_feature_set_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/rule_feature_set_test.cc
@@ -94,6 +94,10 @@ class RuleFeatureSetTest : public testing::Test {
*element, pseudo);
}
+ void CollectPartInvalidationSet(InvalidationLists& invalidation_lists) const {
+ rule_feature_set_.CollectPartInvalidationSet(invalidation_lists);
+ }
+
void CollectUniversalSiblingInvalidationSet(
InvalidationLists& invalidation_lists) {
rule_feature_set_.CollectUniversalSiblingInvalidationSet(invalidation_lists,
@@ -1217,6 +1221,8 @@ TEST_F(RuleFeatureSetTest, invalidatesParts) {
CollectInvalidationSetsForClass(invalidation_lists, "a");
EXPECT_EQ(1u, invalidation_lists.descendants.size());
ExpectNoSelfInvalidation(invalidation_lists.descendants);
+ EXPECT_TRUE(invalidation_lists.descendants[0]->TreeBoundaryCrossing());
+ EXPECT_TRUE(invalidation_lists.descendants[0]->InvalidatesParts());
}
{
@@ -1225,6 +1231,17 @@ TEST_F(RuleFeatureSetTest, invalidatesParts) {
EXPECT_EQ(1u, invalidation_lists.descendants.size());
ExpectPartsInvalidation(invalidation_lists.descendants);
EXPECT_FALSE(invalidation_lists.descendants[0]->WholeSubtreeInvalid());
+ EXPECT_TRUE(invalidation_lists.descendants[0]->TreeBoundaryCrossing());
+ EXPECT_TRUE(invalidation_lists.descendants[0]->InvalidatesParts());
+ }
+
+ {
+ InvalidationLists invalidation_lists;
+ CollectPartInvalidationSet(invalidation_lists);
+ EXPECT_EQ(1u, invalidation_lists.descendants.size());
+ ExpectPartsInvalidation(invalidation_lists.descendants);
+ EXPECT_TRUE(invalidation_lists.descendants[0]->TreeBoundaryCrossing());
+ EXPECT_TRUE(invalidation_lists.descendants[0]->InvalidatesParts());
}
}
} // namespace blink
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 a1116d85105..ea861fe1579 100644
--- a/chromium/third_party/blink/renderer/core/css/selector_checker.cc
+++ b/chromium/third_party/blink/renderer/core/css/selector_checker.cc
@@ -306,14 +306,6 @@ static inline Element* ParentOrV0ShadowHostElement(const Element& element) {
return element.ParentOrShadowHostElement();
}
-static inline Element* ParentOrOpenShadowHostElement(const Element& element) {
- if (element.parentNode() && element.parentNode()->IsShadowRoot()) {
- if (ToShadowRoot(element.parentNode())->GetType() != ShadowRootType::kOpen)
- return nullptr;
- }
- return element.ParentOrShadowHostElement();
-}
-
SelectorChecker::MatchStatus SelectorChecker::MatchForRelation(
const SelectorCheckingContext& context,
MatchResult& result) const {
@@ -483,28 +475,6 @@ SelectorChecker::MatchStatus SelectorChecker::MatchForRelation(
return kSelectorFailsCompletely;
}
- case CSSSelector::kShadowPiercingDescendant: {
- DCHECK_EQ(mode_, kQueryingRules);
- UseCounter::Count(context.element->GetDocument(),
- WebFeature::kCSSShadowPiercingDescendantCombinator);
- // TODO(kochi): parentOrOpenShadowHostElement() is necessary because
- // SelectorQuery can pass V0 shadow roots. All closed shadow roots are
- // already filtered out, thus once V0 is removed this logic can use
- // parentOrShadowHostElement() instead.
- for (next_context.element =
- ParentOrOpenShadowHostElement(*context.element);
- next_context.element;
- next_context.element =
- ParentOrOpenShadowHostElement(*next_context.element)) {
- MatchStatus match = MatchSelector(next_context, result);
- if (match == kSelectorMatches || match == kSelectorFailsCompletely)
- return match;
- if (NextSelectorExceedsScope(next_context))
- break;
- }
- return kSelectorFailsCompletely;
- }
-
case CSSSelector::kShadowSlot: {
if (ToHTMLSlotElementIfSupportsAssignmentOrNull(*context.element))
return kSelectorFailsCompletely;
@@ -1046,14 +1016,6 @@ bool SelectorChecker::CheckPseudoClass(const SelectorCheckingContext& context,
case CSSSelector::kPseudoFullscreen:
// fall through
case CSSSelector::kPseudoFullScreen:
- // While a Document is in the fullscreen state, and the document's current
- // fullscreen element is an element in the document, the 'full-screen'
- // pseudoclass applies to that element. Also, an <iframe>, <object> or
- // <embed> element whose child browsing context's Document is in the
- // fullscreen state has the 'full-screen' pseudoclass applied.
- if (IsHTMLFrameElementBase(element) &&
- element.ContainsFullScreenElement())
- return true;
return Fullscreen::IsFullscreenElement(element);
case CSSSelector::kPseudoFullScreenAncestor:
return element.ContainsFullScreenElement();
@@ -1090,6 +1052,9 @@ bool SelectorChecker::CheckPseudoClass(const SelectorCheckingContext& context,
case CSSSelector::kPseudoSpatialNavigationFocus:
DCHECK(is_ua_rule_);
return MatchesSpatialNavigationFocusPseudoClass(element);
+ case CSSSelector::kPseudoIsHtml:
+ DCHECK(is_ua_rule_);
+ return element.GetDocument().IsHTMLDocument();
case CSSSelector::kPseudoListBox:
DCHECK(is_ua_rule_);
return MatchesListBoxPseudoClass(element);
@@ -1383,14 +1348,17 @@ bool SelectorChecker::MatchesFocusVisiblePseudoClass(const Element& element) {
&force_pseudo_state);
if (force_pseudo_state)
return true;
- bool always_show_focus_ring =
- IsHTMLFormControlElement(element) &&
- ToHTMLFormControlElement(element).ShouldShowFocusRingOnMouseFocus();
- // Avoid probing for force_pseudo_state. Otherwise, as currently implemented,
- // :focus-visible will always match if :focus is forced, since no focus
- // source flags will be set.
- return element.IsFocused() && IsFrameFocused(element) &&
- (!element.WasFocusedByMouse() || always_show_focus_ring);
+
+ const Document& document = element.GetDocument();
+ bool always_show_focus_ring = element.MayTriggerVirtualKeyboard();
+ bool last_focus_from_mouse =
+ document.GetFrame() &&
+ document.GetFrame()->Selection().FrameIsFocusedAndActive() &&
+ document.LastFocusType() == kWebFocusTypeMouse;
+ bool had_keyboard_event = document.HadKeyboardEvent();
+
+ return element.IsFocused() && (!last_focus_from_mouse || had_keyboard_event ||
+ always_show_focus_ring);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/selector_filter.cc b/chromium/third_party/blink/renderer/core/css/selector_filter.cc
index f7e93c731e2..92450b3cf9f 100644
--- a/chromium/third_party/blink/renderer/core/css/selector_filter.cc
+++ b/chromium/third_party/blink/renderer/core/css/selector_filter.cc
@@ -182,7 +182,6 @@ void SelectorFilter::CollectIdentifierHashes(
case CSSSelector::kShadowPseudo:
case CSSSelector::kShadowPart:
case CSSSelector::kShadowDeep:
- case CSSSelector::kShadowPiercingDescendant:
skip_over_subselectors = false;
CollectDescendantSelectorIdentifierHashes(*current, hash);
break;
diff --git a/chromium/third_party/blink/renderer/core/css/selector_query.cc b/chromium/third_party/blink/renderer/core/css/selector_query.cc
index cb8f6848841..fa10f0df333 100644
--- a/chromium/third_party/blink/renderer/core/css/selector_query.cc
+++ b/chromium/third_party/blink/renderer/core/css/selector_query.cc
@@ -30,17 +30,16 @@
#include <utility>
#include "base/memory/ptr_util.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
#include "third_party/blink/renderer/core/css/selector_checker.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/nth_index_cache.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/dom/static_node_list.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
// Uncomment to run the SelectorQueryTests for stats in a release build.
// #define RELEASE_QUERY_STATS
@@ -523,7 +522,7 @@ SelectorQuery* SelectorQueryCache::Add(const AtomicString& selectors,
const Document& document,
ExceptionState& exception_state) {
if (selectors.IsEmpty()) {
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"The provided selector is empty.");
return nullptr;
}
@@ -543,7 +542,8 @@ SelectorQuery* SelectorQueryCache::Add(const AtomicString& selectors,
if (!selector_list.First()) {
exception_state.ThrowDOMException(
- kSyntaxError, "'" + selectors + "' is not a valid selector.");
+ DOMExceptionCode::kSyntaxError,
+ "'" + selectors + "' is not a valid selector.");
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.cc b/chromium/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.cc
index e8c5b15fec7..10eca79f90f 100644
--- a/chromium/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.cc
+++ b/chromium/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.cc
@@ -64,22 +64,6 @@ void ShadowTreeStyleSheetCollection::CollectStyleSheets(
std::make_pair(css_sheet, master_engine.RuleSetForSheet(*css_sheet)));
}
}
-
- if (!GetTreeScope().HasMoreStyleSheets())
- return;
-
- StyleSheetList& more_style_sheets = GetTreeScope().MoreStyleSheets();
- unsigned length = more_style_sheets.length();
- for (unsigned index = 0; index < length; ++index) {
- StyleSheet* sheet = more_style_sheets.item(index);
- if (!sheet)
- continue;
- CSSStyleSheet* css_sheet = ToCSSStyleSheet(sheet);
- if (!css_sheet || !css_sheet->CanBeActivated(g_null_atom))
- continue;
- collection.AppendActiveStyleSheet(
- std::make_pair(css_sheet, master_engine.RuleSetForSheet(*css_sheet)));
- }
}
void ShadowTreeStyleSheetCollection::UpdateActiveStyleSheets(
diff --git a/chromium/third_party/blink/renderer/core/css/style-invalidation.md b/chromium/third_party/blink/renderer/core/css/style-invalidation.md
new file mode 100644
index 00000000000..aaa1498a80c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/style-invalidation.md
@@ -0,0 +1,168 @@
+# CSS Style Invalidation in Blink
+
+[Rendered](https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/core/css/style-invalidation.md)
+
+# About this document
+
+The doc gives a high-level overview of the style invalidation process.
+It does not cover [sibling invalidation](https://goo.gl/z0Z9gn).
+
+# Overview of invalidation
+
+Invalidation is the process
+of marking which elements need their style recalculated
+in response to a change in the DOM.
+The simplest possible approach
+is to invalidate everything in response to every change.
+
+Invalidation sets give us a way
+to find a smaller set of elements which need recalculation
+They are not perfect,
+they err on the side of correctness,
+so we invalidate elements that do not need recalculation
+but this are significantly better than recalculating everything.
+An invalidation set represents
+
+* criteria for matching against a node
+* instructions for whether/how to descend the tree into the node's children
+
+If we have a style rule `".c1 .c2 { ... }"`
+then style recalculation is needed
+when a `c1`-class is added or removed
+as an ancestor of a `c2`-class
+or when a `c2`-class is added or removed
+as a descendant of a `c1`-class element
+(here adding/removing can be adding/removing an element
+or just adding/removing these classes on existing elements).
+We don't want to do full style recalc
+at the time of adding/removing
+because there may be more mutations coming.
+If we can tell immediately that a change forces style recalc
+then we mark the node as that,
+otherwise we collect everything as pending invalidation sets.
+
+In the example,
+if a `c1`-class is added to an element in the tree,
+we need to invalidate all of its descendants which have class c2.
+Rather than perform a search right now,
+we just mark the element with a pending invalidation set
+that matches against `c2`
+and descends into all light-descendants.
+
+If a `c2`-class element is added to the tree,
+then it needs recalculation
+if it has a `c1`-class ancestor.
+We never search _up_ the tree at this point
+or during style invalidation,
+we only do that during recalculation,
+so this becomes an immediate invalidation,
+even though it may be unnecessary.
+
+Eventually all DOM changes have been turned into immediate invalidations
+or pending invalidation sets.
+At this point,
+we apply all the pending invalidations
+and then recalculate style for all of the invalidated elements.
+
+For more details see the original [invalidation sets design doc](https://goo.gl/3ane6s)
+and the [sibling invalidation design doc](https://goo.gl/z0Z9gn).
+
+# State involved
+
+## RuleFeatureSet
+
+The data in RuleFeatureSet is built from the style rules
+and does not change unless the style rules change.
+
+## DOM Node's style states
+
+DOM nodes have several bits of style-related state
+that control style invalidation and recalculation.
+These are accessed through:
+
+* [`Node::NeedsStyleInvalidation`](https://cs.chromium.org/?q=symbol:%5Eblink::Node::NeedsStyleInvalidation$)
+* [`Node::ChildNeedsStyleInvalidation`](https://cs.chromium.org/?q=symbol:%5Eblink::Node::ChildNeedsStyleInvalidation$)
+* [`Node::NeedsStyleRecalc`](https://cs.chromium.org/?q=symbol:%5Eblink::Node::NeedsStyleRecalc$)
+* [`Node::ChildNeedsStyleRecalc`](https://cs.chromium.org/?q=symbol:%5Eblink::Node::ChildNeedsStyleRecalc$)
+
+
+
+## PendingInvalidationsMap
+
+This is a map from
+DOM Node to
+invalidation sets that should be applied due to updates to that node.
+
+
+# Processes
+
+
+## Overview
+
+The overview of style invalidation and recalculation is that
+
+* Style rules are compiled down to a collection of InvalidationSets
+ and other data
+ in [`RuleFeatureSet`](https://cs.chromium.org/?q=symbol:%5Eblink::RuleFeatureSet$)
+* The following process is then applied continuously
+ * Changes to the DOM cause nodes or subtrees to be immediately invalidated
+ or to accumulate pending invalidations.
+ * A point is reached where style is being read
+ (e.g. in order to render a new frame)
+ * Style invalidation process finds all pending invalidations
+ and decides on what will actually be recalculated
+ * Style recalculation process recalculates style
+ for all nodes that need it
+
+
+## Building the RuleFeatureSet
+
+Each [`RuleSet`](https://cs.chromium.org/?q=symbol:%5Eblink::RuleSet$)
+produces its own
+[`RuleFeatureSet`](https://cs.chromium.org/?q=symbol:%5Eblink::RuleFeatureSet$)
+by calling [`CollectFeaturesFromRuleData`](https://cs.chromium.org/?q=symbol:%5Eblink::RuleFeatureSet::CollectFeaturesFromRuleData$)
+for each [`RuleData`](https://cs.chromium.org/?q=symbol:%5Eblink::RuleData$).
+These contain several indexed collections of [`InvalidationSet`](https://cs.chromium.org/?q=symbol:%5Eblink::InvalidationSet$)s
+and some miscellaneous properties.
+
+All of these are merged together to form a final [`RuleFeatureSet`](https://cs.chromium.org/?q=symbol:%5Eblink::RuleFeatureSet$)
+which used for style purposes.
+
+
+## Turning DOM changes into pending/immediate invalidations
+
+Changes in the DOM that require updates to styles
+may get turned into either immediate invalidations or pending invalidations.
+When a DOM change that could impact style occurs inside a [`Node`](https://cs.chromium.org/?q=symbol:%5Eblink::Node$)
+(e.g. a change in class name)
+this leads to a call into [`StyleEngine`](https://cs.chromium.org/?q=symbol:%5Eblink::StyleEngine$)
+to record this style-impacting change via one of several [`FooChangedForElement`](https://cs.chromium.org/?q=symbol:%5Eblink::StyleEngine::.*ChangedForElement$) methods.
+
+Depending on the type of change,
+[`StyleEngine`](https://cs.chromium.org/?q=symbol:%5Eblink::StyleEngine$) gathers the relevant [`InvalidationSet`](https://cs.chromium.org/?q=symbol:%5Eblink::InvalidationSet$)s
+and calls [`PendingInvalidations::ScheduleInvalidationSetsForNode`](https://cs.chromium.org/?q=symbol:%5Eblink::PendingInvalidations::ScheduleInvalidationSetsForNode$)
+which will do one or both of
+
+* call [`Node::SetNeedsStyleInvalidation`](https://cs.chromium.org/?q=symbol:%5Eblink::Node::SetNeedsStyleInvalidation$)
+ which ensures that the invalidation process will consider this node
+ and add InvalidationSets for this node to the pending invalidation set map.
+* call [`Node::SetNeedsStyleRecalc`](https://cs.chromium.org/?q=symbol:%5Eblink::Node::SetNeedsStyleRecalc$)
+ with either [`kLocalStyleChange`](https://cs.chromium.org/?q=symbol:%5Eblink::StyleChangeType::kLocalStyleChange$) or [`kSubtreeStyleChange`](https://cs.chromium.org/?q=symbol:%5Eblink::StyleChangeType::kSubtreeStyleChange$)
+
+
+## Pushing the pending invalidations
+
+When style is about to be read,
+the map of pending invalidations which has been built up
+needs to be pushed.
+For each [`ContainerNode`](https://cs.chromium.org/?q=symbol:%5Eblink::ContainerNode$) in the DOM tree
+we have 0 or more descendant [`InvalidationSet`](https://cs.chromium.org/?q=symbol:%5Eblink::InvalidationSet$) waiting to be applied.
+The invalidation process starts with a call to [`StyleInvalidator::Invalidate`](https://cs.chromium.org/?q=symbol:%5Eblink::StyleInvalidator::Invalidate$)
+which recurses down the tree, depth first.
+Read the method's inline documentation to understand more about the process.
+
+# See Also
+
+[Invalidation sets design doc](https://goo.gl/3ane6s)
+
+[Sibling invalidation design doc](https://goo.gl/z0Z9gn)
diff --git a/chromium/third_party/blink/renderer/core/css/style_change_reason.cc b/chromium/third_party/blink/renderer/core/css/style_change_reason.cc
index feeef7c4295..a457e9fb3ea 100644
--- a/chromium/third_party/blink/renderer/core/css/style_change_reason.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_change_reason.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/wtf/static_constructors.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace blink {
@@ -21,7 +22,7 @@ const char kDesignMode[] = "DesignMode";
const char kFontSizeChange[] = "FontSizeChange";
const char kFonts[] = "Fonts";
const char kFrame[] = "Frame";
-const char kFullScreen[] = "FullScreen";
+const char kFullscreen[] = "Fullscreen";
const char kInheritedStyleChangeFromParentFrame[] =
"InheritedStyleChangeFromParentFrame";
const char kInline[] = "Inline";
diff --git a/chromium/third_party/blink/renderer/core/css/style_change_reason.h b/chromium/third_party/blink/renderer/core/css/style_change_reason.h
index 21ba7568615..3288796db13 100644
--- a/chromium/third_party/blink/renderer/core/css/style_change_reason.h
+++ b/chromium/third_party/blink/renderer/core/css/style_change_reason.h
@@ -25,7 +25,7 @@ extern const char kDesignMode[];
extern const char kFrame[];
extern const char kFontSizeChange[];
extern const char kFonts[];
-extern const char kFullScreen[];
+extern const char kFullscreen[];
extern const char kInheritedStyleChangeFromParentFrame[];
extern const char kInline[];
extern const char kInlineCSSStyleMutated[];
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 7931dbe560f..42c6d158a04 100644
--- a/chromium/third_party/blink/renderer/core/css/style_engine.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_engine.cc
@@ -32,6 +32,7 @@
#include "third_party/blink/renderer/core/css/css_default_style_sheets.h"
#include "third_party/blink/renderer/core/css/css_font_selector.h"
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
+#include "third_party/blink/renderer/core/css/document_style_environment_variables.h"
#include "third_party/blink/renderer/core/css/document_style_sheet_collector.h"
#include "third_party/blink/renderer/core/css/font_face_cache.h"
#include "third_party/blink/renderer/core/css/invalidation/invalidation_set.h"
@@ -40,6 +41,7 @@
#include "third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h"
#include "third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
+#include "third_party/blink/renderer/core/css/style_environment_variables.h"
#include "third_party/blink/renderer/core/css/style_sheet_contents.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
@@ -276,42 +278,6 @@ void StyleEngine::ModifiedStyleSheetCandidateNode(Node& node) {
SetNeedsActiveStyleUpdate(node.GetTreeScope());
}
-void StyleEngine::MoreStyleSheetsWillChange(TreeScope& tree_scope,
- StyleSheetList* old_sheets,
- StyleSheetList* new_sheets) {
- if (GetDocument().IsDetached())
- return;
-
- unsigned old_sheets_count = old_sheets ? old_sheets->length() : 0;
- unsigned new_sheets_count = new_sheets ? new_sheets->length() : 0;
-
- unsigned min_count = std::min(old_sheets_count, new_sheets_count);
- unsigned index = 0;
- while (index < min_count &&
- old_sheets->item(index) == new_sheets->item(index)) {
- index++;
- }
-
- if (old_sheets_count == new_sheets_count && index == old_sheets_count)
- return;
-
- for (unsigned i = index; i < old_sheets_count; ++i) {
- ToCSSStyleSheet(old_sheets->item(i))
- ->RemovedConstructedFromTreeScope(&tree_scope);
- }
- for (unsigned i = index; i < new_sheets_count; ++i) {
- ToCSSStyleSheet(new_sheets->item(i))
- ->AddedConstructedToTreeScope(&tree_scope);
- }
-
- if (new_sheets_count) {
- EnsureStyleSheetCollectionFor(tree_scope);
- if (tree_scope != document_)
- active_tree_scopes_.insert(&tree_scope);
- }
- SetNeedsActiveStyleUpdate(tree_scope);
-}
-
void StyleEngine::MediaQueriesChangedInScope(TreeScope& tree_scope) {
if (ScopedStyleResolver* resolver = tree_scope.GetScopedStyleResolver())
resolver->SetNeedsAppendAllSheets();
@@ -387,8 +353,7 @@ void StyleEngine::UpdateActiveStyleSheetsInShadow(
ToShadowTreeStyleSheetCollection(StyleSheetCollectionFor(*tree_scope));
DCHECK(collection);
collection->UpdateActiveStyleSheets(*this);
- if (!collection->HasStyleSheetCandidateNodes() &&
- !tree_scope->HasMoreStyleSheets()) {
+ if (!collection->HasStyleSheetCandidateNodes()) {
tree_scopes_removed.insert(tree_scope);
// When removing TreeScope from ActiveTreeScopes,
// its resolver should be destroyed by invoking resetAuthorStyle.
@@ -571,6 +536,9 @@ void StyleEngine::DidDetach() {
if (font_selector_)
font_selector_->GetFontFaceCache()->ClearAll();
font_selector_ = nullptr;
+ if (environment_variables_)
+ environment_variables_->DetachFromParent();
+ environment_variables_ = nullptr;
}
void StyleEngine::ClearFontCache() {
@@ -872,6 +840,30 @@ void StyleEngine::PseudoStateChangedForElement(
element);
}
+void StyleEngine::PartChangedForElement(Element& element) {
+ if (ShouldSkipInvalidationFor(element))
+ return;
+ if (element.GetTreeScope() == document_)
+ return;
+ if (!GetRuleFeatureSet().InvalidatesParts())
+ return;
+ element.SetNeedsStyleRecalc(
+ kLocalStyleChange,
+ StyleChangeReasonForTracing::FromAttribute(HTMLNames::partAttr));
+}
+
+void StyleEngine::PartmapChangedForElement(Element& element) {
+ if (ShouldSkipInvalidationFor(element))
+ return;
+ if (!element.GetShadowRoot())
+ return;
+
+ InvalidationLists invalidation_lists;
+ GetRuleFeatureSet().CollectPartInvalidationSet(invalidation_lists);
+ pending_invalidations_.ScheduleInvalidationSetsForNode(invalidation_lists,
+ element);
+}
+
void StyleEngine::ScheduleSiblingInvalidationsForElement(
Element& element,
ContainerNode& scheduling_parent,
@@ -1404,6 +1396,14 @@ void StyleEngine::CustomPropertyRegistered() {
resolver_->InvalidateMatchedPropertiesCache();
}
+void StyleEngine::EnvironmentVariableChanged() {
+ GetDocument().SetNeedsStyleRecalc(
+ kSubtreeStyleChange, StyleChangeReasonForTracing::Create(
+ StyleChangeReason::kPropertyRegistration));
+ if (resolver_)
+ resolver_->InvalidateMatchedPropertiesCache();
+}
+
void StyleEngine::MarkForWhitespaceReattachment() {
for (auto element : whitespace_reattach_set_) {
if (!element->GetLayoutObject())
@@ -1498,6 +1498,14 @@ StyleRuleKeyframes* StyleEngine::KeyframeStylesForAnimation(
return it->value.Get();
}
+DocumentStyleEnvironmentVariables& StyleEngine::EnsureEnvironmentVariables() {
+ if (!environment_variables_) {
+ environment_variables_ = DocumentStyleEnvironmentVariables::Create(
+ StyleEnvironmentVariables::GetRootInstance(), *document_);
+ }
+ return *environment_variables_.get();
+}
+
void StyleEngine::Trace(blink::Visitor* visitor) {
visitor->Trace(document_);
visitor->Trace(injected_user_style_sheets_);
@@ -1523,13 +1531,4 @@ void StyleEngine::Trace(blink::Visitor* visitor) {
FontSelectorClient::Trace(visitor);
}
-void StyleEngine::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- for (const auto& sheet : injected_user_style_sheets_) {
- visitor->TraceWrappers(sheet.second);
- }
- for (const auto& sheet : injected_author_style_sheets_) {
- visitor->TraceWrappers(sheet.second);
- }
- visitor->TraceWrappers(document_style_sheet_collection_);
-}
} // namespace blink
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 695e6bf481c..aa62593e488 100644
--- a/chromium/third_party/blink/renderer/core/css/style_engine.h
+++ b/chromium/third_party/blink/renderer/core/css/style_engine.h
@@ -45,7 +45,7 @@
#include "third_party/blink/renderer/core/css/style_engine_context.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/tree_ordered_list.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/fonts/font_selector_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -62,6 +62,7 @@ class MediaQueryEvaluator;
class Node;
class RuleFeatureSet;
class ShadowTreeStyleSheetCollection;
+class DocumentStyleEnvironmentVariables;
class StyleRuleFontFace;
class StyleRuleUsageTracker;
class StyleSheetContents;
@@ -77,7 +78,7 @@ using StyleSheetKey = AtomicString;
class CORE_EXPORT StyleEngine final
: public GarbageCollectedFinalized<StyleEngine>,
public FontSelectorClient,
- public TraceWrapperBase {
+ public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(StyleEngine);
public:
@@ -118,9 +119,6 @@ class CORE_EXPORT StyleEngine final
void AddStyleSheetCandidateNode(Node&);
void RemoveStyleSheetCandidateNode(Node&, ContainerNode& insertion_point);
void ModifiedStyleSheetCandidateNode(Node&);
- void MoreStyleSheetsWillChange(TreeScope&,
- StyleSheetList* old_sheets,
- StyleSheetList* new_sheets);
void MediaQueriesChangedInScope(TreeScope&);
void WatchedSelectorsChanged();
void InitialStyleChanged();
@@ -268,6 +266,9 @@ class CORE_EXPORT StyleEngine final
const AtomicString& new_id,
Element&);
void PseudoStateChangedForElement(CSSSelector::PseudoType, Element&);
+ void PartChangedForElement(Element&);
+ void PartmapChangedForElement(Element&);
+
void ScheduleSiblingInvalidationsForElement(Element&,
ContainerNode& scheduling_parent,
unsigned min_direct_adjacent);
@@ -299,6 +300,8 @@ class CORE_EXPORT StyleEngine final
void CustomPropertyRegistered();
+ void EnvironmentVariableChanged();
+
bool NeedsWhitespaceReattachment() const {
return !whitespace_reattach_set_.IsEmpty();
}
@@ -311,8 +314,9 @@ class CORE_EXPORT StyleEngine final
StyleRuleKeyframes* KeyframeStylesForAnimation(
const AtomicString& animation_name);
+ DocumentStyleEnvironmentVariables& EnsureEnvironmentVariables();
+
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override { return "StyleEngine"; }
private:
@@ -473,6 +477,8 @@ class CORE_EXPORT StyleEngine final
HeapHashMap<AtomicString, Member<StyleRuleKeyframes>>;
KeyframesRuleMap keyframes_rule_map_;
+ scoped_refptr<DocumentStyleEnvironmentVariables> environment_variables_;
+
friend class StyleEngineTest;
};
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 3e5f1fe112b..53346fb3edf 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
@@ -18,12 +18,14 @@
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/dom/shadow_root_init.h"
-#include "third_party/blink/renderer/core/dom/viewport_description.h"
+#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
+#include "third_party/blink/renderer/core/frame/viewport_data.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/html/html_span_element.h"
#include "third_party/blink/renderer/core/html/html_style_element.h"
+#include "third_party/blink/renderer/core/page/viewport_description.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
#include "third_party/blink/renderer/platform/geometry/float_size.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
@@ -955,6 +957,28 @@ TEST_F(StyleEngineTest, ModifyStyleRuleMatchedPropertiesCache) {
GetCSSPropertyColor()));
}
+TEST_F(StyleEngineTest, VisitedExplicitInheritanceMatchedPropertiesCache) {
+ GetDocument().body()->SetInnerHTMLFromString(R"HTML(
+ <style>
+ :visited { overflow: inherit }
+ </style>
+ <span id="span"><a href></a></span>
+ )HTML");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ Element* span = GetDocument().getElementById("span");
+ const ComputedStyle* style = span->GetComputedStyle();
+ EXPECT_FALSE(style->HasExplicitlyInheritedProperties());
+
+ style = span->firstChild()->GetComputedStyle();
+ EXPECT_TRUE(MatchedPropertiesCache::IsStyleCacheable(*style));
+
+ span->SetInlineStyleProperty(CSSPropertyColor, "blue");
+
+ // Should not DCHECK on applying overflow:inherit on cached matched properties
+ GetDocument().View()->UpdateAllLifecyclePhases();
+}
+
TEST_F(StyleEngineTest, ScheduleInvalidationAfterSubtreeRecalc) {
GetDocument().body()->SetInnerHTMLFromString(R"HTML(
<style id='s1'>
@@ -1153,29 +1177,21 @@ TEST_F(StyleEngineTest, ViewportDescriptionForZoomDSF) {
Document* document =
ToLocalFrame(web_view_impl->GetPage()->MainFrame())->GetDocument();
- float min_width =
- document->GetViewportDescription().min_width.GetFloatValue();
- float max_width =
- document->GetViewportDescription().max_width.GetFloatValue();
- float min_height =
- document->GetViewportDescription().min_height.GetFloatValue();
- float max_height =
- document->GetViewportDescription().max_height.GetFloatValue();
+ auto desc = document->GetViewportData().GetViewportDescription();
+ float min_width = desc.min_width.GetFloatValue();
+ float max_width = desc.max_width.GetFloatValue();
+ float min_height = desc.min_height.GetFloatValue();
+ float max_height = desc.max_height.GetFloatValue();
const float device_scale = 3.5f;
client.set_device_scale_factor(device_scale);
web_view_impl->UpdateAllLifecyclePhases();
- EXPECT_FLOAT_EQ(device_scale * min_width,
- document->GetViewportDescription().min_width.GetFloatValue());
- EXPECT_FLOAT_EQ(device_scale * max_width,
- document->GetViewportDescription().max_width.GetFloatValue());
- EXPECT_FLOAT_EQ(
- device_scale * min_height,
- document->GetViewportDescription().min_height.GetFloatValue());
- EXPECT_FLOAT_EQ(
- device_scale * max_height,
- document->GetViewportDescription().max_height.GetFloatValue());
+ desc = document->GetViewportData().GetViewportDescription();
+ EXPECT_FLOAT_EQ(device_scale * min_width, desc.min_width.GetFloatValue());
+ EXPECT_FLOAT_EQ(device_scale * max_width, desc.max_width.GetFloatValue());
+ EXPECT_FLOAT_EQ(device_scale * min_height, desc.min_height.GetFloatValue());
+ EXPECT_FLOAT_EQ(device_scale * max_height, desc.max_height.GetFloatValue());
}
TEST_F(StyleEngineTest, MediaQueryAffectingValueChanged_StyleElementNoMedia) {
@@ -1417,4 +1433,26 @@ TEST_F(StyleEngineTest, MediaQueriesChangeDefaultFontSize) {
GetCSSPropertyColor()));
}
+TEST_F(StyleEngineTest, ShadowRootStyleRecalcCrash) {
+ GetDocument().body()->SetInnerHTMLFromString("<div id=host></div>");
+ HTMLElement* host = ToHTMLElement(GetDocument().getElementById("host"));
+ ASSERT_TRUE(host);
+
+ ShadowRoot& shadow_root =
+ host->AttachShadowRootInternal(ShadowRootType::kOpen);
+
+ shadow_root.SetInnerHTMLFromString(R"HTML(
+ <span id=span></span>
+ <style>
+ :nth-child(odd) { color: green }
+ </style>
+ )HTML");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ // This should not cause DCHECK errors on style recalc flags.
+ shadow_root.getElementById("span")->remove();
+ host->SetInlineStyleProperty(CSSPropertyDisplay, "inline");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/style_environment_variables.cc b/chromium/third_party/blink/renderer/core/css/style_environment_variables.cc
new file mode 100644
index 00000000000..f9b69d4b010
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/style_environment_variables.cc
@@ -0,0 +1,172 @@
+// 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/css/style_environment_variables.h"
+
+#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
+
+namespace blink {
+
+namespace {
+
+// This is the default value for all safe-area-inset-* variables.
+static const char kSafeAreaInsetDefault[] = "0px";
+
+// Use this to set default values for environment variables when the root
+// instance is created.
+void SetDefaultEnvironmentVariables(StyleEnvironmentVariables* instance) {
+ instance->SetVariable(UADefinedVariable::kSafeAreaInsetTop,
+ kSafeAreaInsetDefault);
+ instance->SetVariable(UADefinedVariable::kSafeAreaInsetLeft,
+ kSafeAreaInsetDefault);
+ instance->SetVariable(UADefinedVariable::kSafeAreaInsetBottom,
+ kSafeAreaInsetDefault);
+ instance->SetVariable(UADefinedVariable::kSafeAreaInsetRight,
+ kSafeAreaInsetDefault);
+}
+
+} // namespace.
+
+// This owns the static root instance.
+class StyleEnvironmentVariables::RootOwner {
+ public:
+ StyleEnvironmentVariables& GetRoot() {
+ if (!instance_) {
+ instance_ = base::AdoptRef(new StyleEnvironmentVariables());
+ SetDefaultEnvironmentVariables(instance_.get());
+ }
+
+ return *instance_.get();
+ };
+
+ private:
+ scoped_refptr<StyleEnvironmentVariables> instance_;
+};
+
+// static
+StyleEnvironmentVariables& StyleEnvironmentVariables::GetRootInstance() {
+ static auto* instance = new StyleEnvironmentVariables::RootOwner();
+ return instance->GetRoot();
+}
+
+// static
+const AtomicString StyleEnvironmentVariables::GetVariableName(
+ UADefinedVariable variable) {
+ switch (variable) {
+ case UADefinedVariable::kSafeAreaInsetTop:
+ return "safe-area-inset-top";
+ case UADefinedVariable::kSafeAreaInsetLeft:
+ return "safe-area-inset-left";
+ case UADefinedVariable::kSafeAreaInsetBottom:
+ return "safe-area-inset-bottom";
+ case UADefinedVariable::kSafeAreaInsetRight:
+ return "safe-area-inset-right";
+ default:
+ break;
+ }
+
+ NOTREACHED();
+}
+
+// static
+scoped_refptr<StyleEnvironmentVariables> StyleEnvironmentVariables::Create(
+ StyleEnvironmentVariables& parent) {
+ scoped_refptr<StyleEnvironmentVariables> obj =
+ base::AdoptRef(new StyleEnvironmentVariables());
+
+ // Add a reference to this instance from the parent.
+ obj->BindToParent(parent);
+
+ return obj;
+}
+
+StyleEnvironmentVariables::~StyleEnvironmentVariables() {
+ // Remove a reference to this instance from the parent.
+ if (parent_) {
+ auto it = parent_->children_.Find(this);
+ DCHECK(it != kNotFound);
+ parent_->children_.EraseAt(it);
+ }
+}
+
+void StyleEnvironmentVariables::SetVariable(
+ const AtomicString& name,
+ scoped_refptr<CSSVariableData> value) {
+ data_.Set(name, std::move(value));
+ InvalidateVariable(name);
+}
+
+void StyleEnvironmentVariables::SetVariable(const AtomicString& name,
+ const String& value) {
+ CSSTokenizer tokenizer(value);
+ Vector<CSSParserToken> tokens;
+ tokens.AppendVector(tokenizer.TokenizeToEOF());
+
+ Vector<String> backing_strings;
+ backing_strings.push_back(value);
+
+ SetVariable(name, CSSVariableData::CreateResolved(tokens, backing_strings,
+ false, false, false));
+}
+
+void StyleEnvironmentVariables::SetVariable(const UADefinedVariable name,
+ const String& value) {
+ SetVariable(GetVariableName(name), value);
+}
+
+void StyleEnvironmentVariables::RemoveVariable(const AtomicString& name) {
+ data_.erase(name);
+ InvalidateVariable(name);
+}
+
+CSSVariableData* StyleEnvironmentVariables::ResolveVariable(
+ const AtomicString& name) {
+ auto result = data_.find(name);
+ if (result == data_.end() && parent_)
+ return parent_->ResolveVariable(name);
+ if (result == data_.end())
+ return nullptr;
+ return result->value.get();
+}
+
+void StyleEnvironmentVariables::DetachFromParent() {
+ DCHECK(parent_);
+
+ // Remove any reference the |parent| has to |this|.
+ auto it = parent_->children_.Find(this);
+ if (it != kNotFound)
+ parent_->children_.EraseAt(it);
+
+ parent_ = nullptr;
+}
+
+void StyleEnvironmentVariables::ClearForTesting() {
+ data_.clear();
+
+ // If we are the root then we should re-apply the default variables.
+ if (!parent_)
+ SetDefaultEnvironmentVariables(this);
+}
+
+void StyleEnvironmentVariables::BindToParent(
+ StyleEnvironmentVariables& parent) {
+ DCHECK_EQ(nullptr, parent_);
+ parent_ = &parent;
+ parent.children_.push_back(this);
+}
+
+void StyleEnvironmentVariables::ParentInvalidatedVariable(
+ const AtomicString& name) {
+ // If we have not overridden the variable then we should invalidate it
+ // locally.
+ if (data_.find(name) == data_.end())
+ InvalidateVariable(name);
+}
+
+void StyleEnvironmentVariables::InvalidateVariable(const AtomicString& name) {
+ for (auto& it : children_)
+ it->ParentInvalidatedVariable(name);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/style_environment_variables.h b/chromium/third_party/blink/renderer/core/css/style_environment_variables.h
new file mode 100644
index 00000000000..c5452476f6f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/style_environment_variables.h
@@ -0,0 +1,92 @@
+// 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_CSS_STYLE_ENVIRONMENT_VARIABLES_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_STYLE_ENVIRONMENT_VARIABLES_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/css/css_variable_data.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
+
+namespace blink {
+
+// UADefinedVariable contains all the user agent defined environment variables.
+// When adding a new variable the string equivalent needs to be added to
+// |GetVariableName|.
+enum class UADefinedVariable {
+ // The safe area insets are four environment variables that define a
+ // rectangle by its top, right, bottom, and left insets from the edge of
+ // the viewport.
+ kSafeAreaInsetTop,
+ kSafeAreaInsetLeft,
+ kSafeAreaInsetBottom,
+ kSafeAreaInsetRight,
+};
+
+// StyleEnvironmentVariables stores user agent and user defined CSS environment
+// variables. It has a static root instance that stores global values and
+// each document has a child that stores document level values.
+class CORE_EXPORT StyleEnvironmentVariables
+ : public RefCounted<StyleEnvironmentVariables> {
+ public:
+ static StyleEnvironmentVariables& GetRootInstance();
+
+ // Gets the name of a |UADefinedVariable| as a string.
+ static const AtomicString GetVariableName(UADefinedVariable);
+
+ // Create a new instance bound to |parent|.
+ static scoped_refptr<StyleEnvironmentVariables> Create(
+ StyleEnvironmentVariables& parent);
+
+ virtual ~StyleEnvironmentVariables();
+
+ // Set the value of the variable |name| and invalidate any dependents.
+ void SetVariable(const AtomicString& name,
+ scoped_refptr<CSSVariableData> value);
+
+ // Tokenize |value| and set it.
+ void SetVariable(const AtomicString& name, const String& value);
+ void SetVariable(const UADefinedVariable name, const String& value);
+
+ // Remove the variable |name| and invalidate any dependents.
+ void RemoveVariable(const AtomicString& name);
+
+ // Resolve the variable |name| by traversing the tree of
+ // |StyleEnvironmentVariables|.
+ virtual CSSVariableData* ResolveVariable(const AtomicString& name);
+
+ // Detach |this| from |parent|.
+ void DetachFromParent();
+
+ protected:
+ friend class StyleEnvironmentVariablesTest;
+
+ void ClearForTesting();
+
+ // Bind this instance to a |parent|. This should only be called once.
+ void BindToParent(StyleEnvironmentVariables& parent);
+
+ // Called by the parent to tell the child that variable |name| has changed.
+ void ParentInvalidatedVariable(const AtomicString& name);
+
+ StyleEnvironmentVariables() : parent_(nullptr) {}
+
+ // Called when variable |name| is changed. This will notify any children that
+ // this variable has changed.
+ virtual void InvalidateVariable(const AtomicString& name);
+
+ private:
+ class RootOwner;
+
+ Vector<scoped_refptr<StyleEnvironmentVariables>> children_;
+ HashMap<AtomicString, scoped_refptr<CSSVariableData>> data_;
+ scoped_refptr<StyleEnvironmentVariables> parent_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_STYLE_ENVIRONMENT_VARIABLES_H_
diff --git a/chromium/third_party/blink/renderer/core/css/style_environment_variables_test.cc b/chromium/third_party/blink/renderer/core/css/style_environment_variables_test.cc
new file mode 100644
index 00000000000..a36a902b0b5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/css/style_environment_variables_test.cc
@@ -0,0 +1,445 @@
+// 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/css/style_environment_variables.h"
+
+#include "third_party/blink/renderer/core/css/document_style_environment_variables.h"
+#include "third_party/blink/renderer/core/css/style_engine.h"
+#include "third_party/blink/renderer/core/dom/node_computed_style.h"
+#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/core/frame/web_feature.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/unit_test_helpers.h"
+
+namespace blink {
+
+namespace {
+
+static const char kVariableName[] = "test";
+
+// red
+static const Color kTestColorRed = Color(255, 0, 0);
+static const char kVariableTestColor[] = "red";
+
+// blue
+static const Color kAltTestColor = Color(0, 0, 255);
+static const char kVariableAltTestColor[] = "blue";
+
+// no set
+static const Color kNoColor = Color(0, 0, 0, 0);
+
+static const char kSafeAreaInsetExpectedDefault[] = "0px";
+
+} // namespace
+
+class StyleEnvironmentVariablesTest : public PageTestBase {
+ public:
+ void SetUp() override {
+ PageTestBase::SetUp();
+
+ RuntimeEnabledFeatures::SetCSSEnvironmentVariablesEnabled(true);
+
+ // Needed for RecordUseCounter_IgnoreMediaControls.
+ RuntimeEnabledFeatures::SetModernMediaControlsEnabled(true);
+ }
+
+ void TearDown() override {
+ StyleEnvironmentVariables::GetRootInstance().ClearForTesting();
+ }
+
+ DocumentStyleEnvironmentVariables& GetDocumentVariables() {
+ return GetStyleEngine().EnsureEnvironmentVariables();
+ }
+
+ void InitializeWithHTML(LocalFrame& frame, const String& html_content) {
+ // Sets the inner html and runs the document lifecycle.
+ frame.GetDocument()->body()->SetInnerHTMLFromString(html_content);
+ frame.GetDocument()->View()->UpdateAllLifecyclePhases();
+ }
+
+ void InitializeTestPageWithVariableNamed(LocalFrame& frame,
+ const String& name) {
+ InitializeWithHTML(frame,
+ "<style>"
+ " #target { background-color: env(" +
+ name +
+ "); }"
+ "</style>"
+ "<div>"
+ " <div id=target></div>"
+ "</div>");
+ }
+
+ void InitializeTestPageWithVariableNamed(LocalFrame& frame,
+ const UADefinedVariable name) {
+ InitializeTestPageWithVariableNamed(
+ frame, StyleEnvironmentVariables::GetVariableName(name));
+ }
+
+ void SimulateNavigation() {
+ const KURL& url = KURL(NullURL(), "https://www.example.com");
+ FrameLoadRequest request(nullptr, ResourceRequest(url),
+ SubstituteData(SharedBuffer::Create()));
+ GetDocument().GetFrame()->Loader().CommitNavigation(request);
+ blink::test::RunPendingTasks();
+ ASSERT_EQ(url.GetString(), GetDocument().Url().GetString());
+ }
+
+ const String& GetRootVariableValue(UADefinedVariable name) {
+ CSSVariableData* data =
+ StyleEnvironmentVariables::GetRootInstance().ResolveVariable(
+ StyleEnvironmentVariables::GetVariableName(name));
+ EXPECT_NE(nullptr, data);
+ return data->BackingStrings()[0];
+ }
+};
+
+TEST_F(StyleEnvironmentVariablesTest, DocumentVariable_AfterLoad) {
+ InitializeTestPageWithVariableNamed(GetFrame(), kVariableName);
+ GetDocumentVariables().SetVariable(kVariableName, kVariableTestColor);
+
+ // Ensure that the document has been invalidated.
+ EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate());
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ // Check that the element has the background color provided by the variable.
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(kTestColorRed, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+}
+
+TEST_F(StyleEnvironmentVariablesTest, DocumentVariable_Change) {
+ GetDocumentVariables().SetVariable(kVariableName, kVariableAltTestColor);
+ InitializeTestPageWithVariableNamed(GetFrame(), kVariableName);
+
+ // Change the variable value after we have loaded the page.
+ GetDocumentVariables().SetVariable(kVariableName, kVariableTestColor);
+
+ // Ensure that the document has been invalidated.
+ EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate());
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ // Check that the element has the background color provided by the variable.
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(kTestColorRed, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+}
+
+TEST_F(StyleEnvironmentVariablesTest,
+ DocumentVariable_Override_RemoveDocument) {
+ // Set the variable globally.
+ StyleEnvironmentVariables::GetRootInstance().SetVariable(
+ kVariableName, kVariableAltTestColor);
+ InitializeTestPageWithVariableNamed(GetFrame(), kVariableName);
+
+ // Check that the element has the background color provided by the global
+ // variable.
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(kAltTestColor, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+
+ // Change the variable value on the document after we have loaded the page.
+ GetDocumentVariables().SetVariable(kVariableName, kVariableTestColor);
+
+ // Ensure that the document has been invalidated.
+ EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate());
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ // Check that the element has the background color provided by the document
+ // variable.
+ EXPECT_EQ(kTestColorRed, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+
+ // Remove the document variable.
+ GetDocumentVariables().RemoveVariable(kVariableName);
+
+ // Ensure that the document has been invalidated.
+ EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate());
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ // Check that the element has the background color provided by the global
+ // variable.
+ EXPECT_EQ(kAltTestColor, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+}
+
+TEST_F(StyleEnvironmentVariablesTest, DocumentVariable_Override_RemoveGlobal) {
+ // Set the variable globally.
+ StyleEnvironmentVariables::GetRootInstance().SetVariable(
+ kVariableName, kVariableAltTestColor);
+ InitializeTestPageWithVariableNamed(GetFrame(), kVariableName);
+
+ // Check that the element has the background color provided by the global
+ // variable.
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(kAltTestColor, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+
+ // Change the variable value on the document after we have loaded the page.
+ GetDocumentVariables().SetVariable(kVariableName, kVariableTestColor);
+
+ // Ensure that the document has been invalidated.
+ EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate());
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ // Check that the element has the background color provided by the document
+ // variable.
+ EXPECT_EQ(kTestColorRed, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+
+ // Remove the global variable.
+ StyleEnvironmentVariables::GetRootInstance().RemoveVariable(kVariableName);
+
+ // Ensure that the document has not been invalidated.
+ EXPECT_FALSE(GetDocument().NeedsLayoutTreeUpdate());
+}
+
+TEST_F(StyleEnvironmentVariablesTest, DocumentVariable_Preset) {
+ GetDocumentVariables().SetVariable(kVariableName, kVariableTestColor);
+ InitializeTestPageWithVariableNamed(GetFrame(), kVariableName);
+
+ // Check that the element has the background color provided by the variable.
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(kTestColorRed, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+}
+
+TEST_F(StyleEnvironmentVariablesTest, DocumentVariable_Remove) {
+ GetDocumentVariables().SetVariable(kVariableName, kVariableTestColor);
+ InitializeTestPageWithVariableNamed(GetFrame(), kVariableName);
+
+ // Check that the element has the background color provided by the variable.
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(kTestColorRed, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+
+ // Change the variable value after we have loaded the page.
+ GetDocumentVariables().RemoveVariable(kVariableName);
+
+ // Ensure that the document has been invalidated.
+ EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate());
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ // Check that the element does not have the background color any more.
+ EXPECT_NE(kTestColorRed, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+}
+
+TEST_F(StyleEnvironmentVariablesTest, MultiDocumentInvalidation_FromRoot) {
+ InitializeTestPageWithVariableNamed(GetFrame(), kVariableName);
+
+ // Create a second page that uses the variable.
+ std::unique_ptr<DummyPageHolder> new_page =
+ DummyPageHolder::Create(IntSize(800, 600));
+ InitializeTestPageWithVariableNamed(new_page->GetFrame(), kVariableName);
+
+ // Create an empty page that does not use the variable.
+ std::unique_ptr<DummyPageHolder> empty_page =
+ DummyPageHolder::Create(IntSize(800, 600));
+ empty_page->GetDocument().View()->UpdateAllLifecyclePhases();
+
+ StyleEnvironmentVariables::GetRootInstance().SetVariable(kVariableName,
+ kVariableTestColor);
+
+ // The first two pages should be invalidated and the empty one should not.
+ EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate());
+ EXPECT_TRUE(new_page->GetDocument().NeedsLayoutTreeUpdate());
+ EXPECT_FALSE(empty_page->GetDocument().NeedsLayoutTreeUpdate());
+}
+
+TEST_F(StyleEnvironmentVariablesTest, MultiDocumentInvalidation_FromDocument) {
+ InitializeTestPageWithVariableNamed(GetFrame(), kVariableName);
+
+ // Create a second page that uses the variable.
+ std::unique_ptr<DummyPageHolder> new_page =
+ DummyPageHolder::Create(IntSize(800, 600));
+ InitializeTestPageWithVariableNamed(new_page->GetFrame(), kVariableName);
+
+ GetDocumentVariables().SetVariable(kVariableName, kVariableTestColor);
+
+ // Only the first document should be invalidated.
+ EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate());
+ EXPECT_FALSE(new_page->GetDocument().NeedsLayoutTreeUpdate());
+}
+
+TEST_F(StyleEnvironmentVariablesTest, NavigateToClear) {
+ GetDocumentVariables().SetVariable(kVariableName, kVariableTestColor);
+
+ // Simulate a navigation to clear the variables.
+ SimulateNavigation();
+ InitializeTestPageWithVariableNamed(GetFrame(), kVariableName);
+
+ // Check that the element has no background color.
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(kNoColor, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+}
+
+TEST_F(StyleEnvironmentVariablesTest, GlobalVariable_AfterLoad) {
+ InitializeTestPageWithVariableNamed(GetFrame(), kVariableName);
+ StyleEnvironmentVariables::GetRootInstance().SetVariable(kVariableName,
+ kVariableTestColor);
+
+ // Ensure that the document has been invalidated.
+ EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate());
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ // Check that the element has the background color provided by the variable.
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(kTestColorRed, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+}
+
+TEST_F(StyleEnvironmentVariablesTest, GlobalVariable_Change) {
+ StyleEnvironmentVariables::GetRootInstance().SetVariable(
+ kVariableName, kVariableAltTestColor);
+ InitializeTestPageWithVariableNamed(GetFrame(), kVariableName);
+
+ // Change the variable value after we have loaded the page.
+ StyleEnvironmentVariables::GetRootInstance().SetVariable(kVariableName,
+ kVariableTestColor);
+
+ // Ensure that the document has been invalidated.
+ EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate());
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ // Check that the element has the background color provided by the variable.
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(kTestColorRed, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+}
+
+TEST_F(StyleEnvironmentVariablesTest, GlobalVariable_DefaultsPresent) {
+ EXPECT_EQ(kSafeAreaInsetExpectedDefault,
+ GetRootVariableValue(UADefinedVariable::kSafeAreaInsetTop));
+ EXPECT_EQ(kSafeAreaInsetExpectedDefault,
+ GetRootVariableValue(UADefinedVariable::kSafeAreaInsetLeft));
+ EXPECT_EQ(kSafeAreaInsetExpectedDefault,
+ GetRootVariableValue(UADefinedVariable::kSafeAreaInsetBottom));
+ EXPECT_EQ(kSafeAreaInsetExpectedDefault,
+ GetRootVariableValue(UADefinedVariable::kSafeAreaInsetRight));
+
+ EXPECT_EQ(
+ nullptr,
+ StyleEnvironmentVariables::GetRootInstance().ResolveVariable("test"));
+}
+
+TEST_F(StyleEnvironmentVariablesTest, GlobalVariable_Preset) {
+ StyleEnvironmentVariables::GetRootInstance().SetVariable(kVariableName,
+ kVariableTestColor);
+ InitializeTestPageWithVariableNamed(GetFrame(), kVariableName);
+
+ // Check that the element has the background color provided by the variable.
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(kTestColorRed, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+}
+
+TEST_F(StyleEnvironmentVariablesTest, GlobalVariable_Remove) {
+ StyleEnvironmentVariables::GetRootInstance().SetVariable(kVariableName,
+ kVariableTestColor);
+ InitializeTestPageWithVariableNamed(GetFrame(), kVariableName);
+
+ // Check that the element has the background color provided by the variable.
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(kTestColorRed, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+
+ // Change the variable value after we have loaded the page.
+ StyleEnvironmentVariables::GetRootInstance().RemoveVariable(kVariableName);
+
+ // Ensure that the document has been invalidated.
+ EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate());
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ // Check that the element does not have the background color any more.
+ EXPECT_NE(kTestColorRed, target->ComputedStyleRef().VisitedDependentColor(
+ GetCSSPropertyBackgroundColor()));
+}
+
+TEST_F(StyleEnvironmentVariablesTest,
+ DISABLED_PrintExpectedVariableNameHashes) {
+ const UADefinedVariable variables[] = {
+ UADefinedVariable::kSafeAreaInsetTop,
+ UADefinedVariable::kSafeAreaInsetLeft,
+ UADefinedVariable::kSafeAreaInsetRight,
+ UADefinedVariable::kSafeAreaInsetBottom};
+ for (const auto& variable : variables) {
+ const AtomicString name =
+ StyleEnvironmentVariables::GetVariableName(variable);
+ printf("0x%x\n",
+ DocumentStyleEnvironmentVariables::GenerateHashFromName(name));
+ }
+}
+
+TEST_F(StyleEnvironmentVariablesTest, RecordUseCounter_IgnoreMediaControls) {
+ InitializeWithHTML(GetFrame(), "<video controls />");
+
+ EXPECT_FALSE(UseCounter::IsCounted(GetDocument(),
+ WebFeature::kCSSEnvironmentVariable));
+ EXPECT_FALSE(UseCounter::IsCounted(
+ GetDocument(), WebFeature::kCSSEnvironmentVariable_SafeAreaInsetTop));
+ EXPECT_FALSE(UseCounter::IsCounted(
+ GetDocument(), WebFeature::kCSSEnvironmentVariable_SafeAreaInsetLeft));
+ EXPECT_FALSE(UseCounter::IsCounted(
+ GetDocument(), WebFeature::kCSSEnvironmentVariable_SafeAreaInsetBottom));
+ EXPECT_FALSE(UseCounter::IsCounted(
+ GetDocument(), WebFeature::kCSSEnvironmentVariable_SafeAreaInsetRight));
+}
+
+TEST_F(StyleEnvironmentVariablesTest, RecordUseCounter_InvalidProperty) {
+ InitializeTestPageWithVariableNamed(GetFrame(), kVariableName);
+ EXPECT_TRUE(UseCounter::IsCounted(GetDocument(),
+ WebFeature::kCSSEnvironmentVariable));
+}
+
+TEST_F(StyleEnvironmentVariablesTest, RecordUseCounter_NoVariable) {
+ InitializeWithHTML(GetFrame(), "");
+ EXPECT_FALSE(UseCounter::IsCounted(GetDocument(),
+ WebFeature::kCSSEnvironmentVariable));
+}
+
+TEST_F(StyleEnvironmentVariablesTest, RecordUseCounter_SafeAreaInsetBottom) {
+ InitializeTestPageWithVariableNamed(GetFrame(),
+ UADefinedVariable::kSafeAreaInsetBottom);
+
+ EXPECT_TRUE(UseCounter::IsCounted(GetDocument(),
+ WebFeature::kCSSEnvironmentVariable));
+ EXPECT_TRUE(UseCounter::IsCounted(
+ GetDocument(), WebFeature::kCSSEnvironmentVariable_SafeAreaInsetBottom));
+}
+
+TEST_F(StyleEnvironmentVariablesTest, RecordUseCounter_SafeAreaInsetLeft) {
+ InitializeTestPageWithVariableNamed(GetFrame(),
+ UADefinedVariable::kSafeAreaInsetLeft);
+
+ EXPECT_TRUE(UseCounter::IsCounted(GetDocument(),
+ WebFeature::kCSSEnvironmentVariable));
+ EXPECT_TRUE(UseCounter::IsCounted(
+ GetDocument(), WebFeature::kCSSEnvironmentVariable_SafeAreaInsetLeft));
+}
+
+TEST_F(StyleEnvironmentVariablesTest, RecordUseCounter_SafeAreaInsetRight) {
+ InitializeTestPageWithVariableNamed(GetFrame(),
+ UADefinedVariable::kSafeAreaInsetRight);
+
+ EXPECT_TRUE(UseCounter::IsCounted(GetDocument(),
+ WebFeature::kCSSEnvironmentVariable));
+ EXPECT_TRUE(UseCounter::IsCounted(
+ GetDocument(), WebFeature::kCSSEnvironmentVariable_SafeAreaInsetRight));
+}
+
+TEST_F(StyleEnvironmentVariablesTest, RecordUseCounter_SafeAreaInsetTop) {
+ InitializeTestPageWithVariableNamed(GetFrame(),
+ UADefinedVariable::kSafeAreaInsetTop);
+
+ EXPECT_TRUE(UseCounter::IsCounted(GetDocument(),
+ WebFeature::kCSSEnvironmentVariable));
+ EXPECT_TRUE(UseCounter::IsCounted(
+ GetDocument(), WebFeature::kCSSEnvironmentVariable_SafeAreaInsetTop));
+}
+
+} // namespace blink
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 18e48dc16dd..17cefa36905 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
@@ -274,8 +274,7 @@ String StylePropertySerializer::AsText() const {
if (serialized_other_longhand)
continue;
- String shorthand_result =
- StylePropertySerializer::GetPropertyValue(shorthand_property);
+ String shorthand_result = SerializeShorthand(shorthand_property);
if (shorthand_result.IsEmpty())
continue;
@@ -402,13 +401,10 @@ String StylePropertySerializer::CommonShorthandChecks(
return String();
}
-String StylePropertySerializer::GetPropertyValue(
+String StylePropertySerializer::SerializeShorthand(
CSSPropertyID property_id) const {
const StylePropertyShorthand& shorthand = shorthandForProperty(property_id);
- // TODO(timloh): This is weird, why do we call this with non-shorthands at
- // all?
- if (!shorthand.length())
- return String();
+ DCHECK(shorthand.length());
String result = CommonShorthandChecks(shorthand);
if (!result.IsNull())
@@ -437,6 +433,14 @@ String StylePropertySerializer::GetPropertyValue(
return GetShorthandValue(borderBottomShorthand());
case CSSPropertyBorderLeft:
return GetShorthandValue(borderLeftShorthand());
+ case CSSPropertyBorderBlockStart:
+ return GetShorthandValue(borderBlockStartShorthand());
+ case CSSPropertyBorderBlockEnd:
+ return GetShorthandValue(borderBlockEndShorthand());
+ case CSSPropertyBorderInlineStart:
+ return GetShorthandValue(borderInlineStartShorthand());
+ case CSSPropertyBorderInlineEnd:
+ return GetShorthandValue(borderInlineEndShorthand());
case CSSPropertyOutline:
return GetShorthandValue(outlineShorthand());
case CSSPropertyBorderColor:
@@ -530,16 +534,53 @@ String StylePropertySerializer::GetPropertyValue(
}
}
-void StylePropertySerializer::AppendFontLonghandValueIfNotNormal(
+// The font shorthand only allows keyword font-stretch values. Thus, we check if
+// a percentage value can be parsed as a keyword, and if so, serialize it as
+// that keyword.
+const CSSValue* GetFontStretchKeyword(const CSSValue* font_stretch_value) {
+ if (font_stretch_value->IsIdentifierValue())
+ return font_stretch_value;
+ if (font_stretch_value->IsPrimitiveValue()) {
+ double value = ToCSSPrimitiveValue(font_stretch_value)->GetDoubleValue();
+ if (value == 50)
+ return CSSIdentifierValue::Create(CSSValueUltraCondensed);
+ if (value == 62.5)
+ return CSSIdentifierValue::Create(CSSValueExtraCondensed);
+ if (value == 75)
+ return CSSIdentifierValue::Create(CSSValueCondensed);
+ if (value == 87.5)
+ return CSSIdentifierValue::Create(CSSValueSemiCondensed);
+ if (value == 100)
+ return CSSIdentifierValue::Create(CSSValueNormal);
+ if (value == 112.5)
+ return CSSIdentifierValue::Create(CSSValueSemiExpanded);
+ if (value == 125)
+ return CSSIdentifierValue::Create(CSSValueExpanded);
+ if (value == 150)
+ return CSSIdentifierValue::Create(CSSValueExtraExpanded);
+ if (value == 200)
+ return CSSIdentifierValue::Create(CSSValueUltraExpanded);
+ }
+ return nullptr;
+}
+
+// Returns false if the value cannot be represented in the font shorthand
+bool StylePropertySerializer::AppendFontLonghandValueIfNotNormal(
const CSSProperty& property,
StringBuilder& result) const {
int found_property_index = property_set_.FindPropertyIndex(property);
DCHECK_NE(found_property_index, -1);
const CSSValue* val = property_set_.PropertyAt(found_property_index).Value();
+ if (property.IDEquals(CSSPropertyFontStretch)) {
+ const CSSValue* keyword = GetFontStretchKeyword(val);
+ if (!keyword)
+ return false;
+ val = keyword;
+ }
if (val->IsIdentifierValue() &&
ToCSSIdentifierValue(val)->GetValueID() == CSSValueNormal)
- return;
+ return true;
char prefix = '\0';
switch (property.PropertyID()) {
@@ -574,10 +615,11 @@ void StylePropertySerializer::AppendFontLonghandValueIfNotNormal(
"no-common-ligatures no-discretionary-ligatures "
"no-historical-ligatures no-contextual";
} else {
- value = property_set_.PropertyAt(found_property_index).Value()->CssText();
+ value = val->CssText();
}
result.Append(value);
+ return true;
}
String StylePropertySerializer::FontValue() const {
@@ -641,7 +683,10 @@ String StylePropertySerializer::FontValue() const {
AppendFontLonghandValueIfNotNormal(GetCSSPropertyFontVariantCaps(), result);
AppendFontLonghandValueIfNotNormal(GetCSSPropertyFontWeight(), result);
- AppendFontLonghandValueIfNotNormal(GetCSSPropertyFontStretch(), result);
+ bool font_stretch_valid =
+ AppendFontLonghandValueIfNotNormal(GetCSSPropertyFontStretch(), result);
+ if (!font_stretch_valid)
+ return String();
if (!result.IsEmpty())
result.Append(' ');
result.Append(font_size_property.Value()->CssText());
diff --git a/chromium/third_party/blink/renderer/core/css/style_property_serializer.h b/chromium/third_party/blink/renderer/core/css/style_property_serializer.h
index f558b99bc42..addd6aa900b 100644
--- a/chromium/third_party/blink/renderer/core/css/style_property_serializer.h
+++ b/chromium/third_party/blink/renderer/core/css/style_property_serializer.h
@@ -40,7 +40,7 @@ class StylePropertySerializer {
explicit StylePropertySerializer(const CSSPropertyValueSet&);
String AsText() const;
- String GetPropertyValue(CSSPropertyID) const;
+ String SerializeShorthand(CSSPropertyID) const;
private:
String GetCommonValue(const StylePropertyShorthand&) const;
@@ -54,7 +54,7 @@ class StylePropertySerializer {
String separator = " ") const;
String FontValue() const;
String FontVariantValue() const;
- void AppendFontLonghandValueIfNotNormal(const CSSProperty&,
+ bool AppendFontLonghandValueIfNotNormal(const CSSProperty&,
StringBuilder& result) const;
String OffsetValue() const;
String BackgroundRepeatPropertyValue() const;
diff --git a/chromium/third_party/blink/renderer/core/css/style_rule_css_style_declaration.cc b/chromium/third_party/blink/renderer/core/css/style_rule_css_style_declaration.cc
index ebfb9dcd767..0b02d74c462 100644
--- a/chromium/third_party/blink/renderer/core/css/style_rule_css_style_declaration.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_rule_css_style_declaration.cc
@@ -72,10 +72,4 @@ void StyleRuleCSSStyleDeclaration::Trace(blink::Visitor* visitor) {
PropertySetCSSStyleDeclaration::Trace(visitor);
}
-void StyleRuleCSSStyleDeclaration::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(parent_rule_);
- PropertySetCSSStyleDeclaration::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/style_rule_css_style_declaration.h b/chromium/third_party/blink/renderer/core/css/style_rule_css_style_declaration.h
index c30121e8d6d..618b296f702 100644
--- a/chromium/third_party/blink/renderer/core/css/style_rule_css_style_declaration.h
+++ b/chromium/third_party/blink/renderer/core/css/style_rule_css_style_declaration.h
@@ -45,7 +45,6 @@ class StyleRuleCSSStyleDeclaration : public PropertySetCSSStyleDeclaration {
void Reattach(MutableCSSPropertyValueSet&);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
protected:
StyleRuleCSSStyleDeclaration(MutableCSSPropertyValueSet&, CSSRule*);
diff --git a/chromium/third_party/blink/renderer/core/css/style_sheet_collection.cc b/chromium/third_party/blink/renderer/core/css/style_sheet_collection.cc
index 04e29ef8f0a..e171adc065c 100644
--- a/chromium/third_party/blink/renderer/core/css/style_sheet_collection.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_sheet_collection.cc
@@ -67,11 +67,4 @@ void StyleSheetCollection::Trace(blink::Visitor* visitor) {
visitor->Trace(style_sheets_for_style_sheet_list_);
}
-void StyleSheetCollection::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- for (auto sheet : style_sheets_for_style_sheet_list_) {
- visitor->TraceWrappers(sheet);
- }
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/style_sheet_collection.h b/chromium/third_party/blink/renderer/core/css/style_sheet_collection.h
index d87a54a6158..b8fd00326a9 100644
--- a/chromium/third_party/blink/renderer/core/css/style_sheet_collection.h
+++ b/chromium/third_party/blink/renderer/core/css/style_sheet_collection.h
@@ -33,7 +33,7 @@
#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/active_style_sheets.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
@@ -45,7 +45,7 @@ class StyleSheet;
class CORE_EXPORT StyleSheetCollection
: public GarbageCollected<StyleSheetCollection>,
- public TraceWrapperBase {
+ public NameClient {
public:
friend class ActiveDocumentStyleSheetCollector;
friend class ImportedDocumentStyleSheetCollector;
@@ -67,7 +67,6 @@ class CORE_EXPORT StyleSheetCollection
void MarkSheetListDirty() { sheet_list_dirty_ = true; }
virtual void Trace(blink::Visitor*);
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "StyleSheetCollection";
}
diff --git a/chromium/third_party/blink/renderer/core/css/style_sheet_contents.cc b/chromium/third_party/blink/renderer/core/css/style_sheet_contents.cc
index 4287e4e5ab3..9c7769fc584 100644
--- a/chromium/third_party/blink/renderer/core/css/style_sheet_contents.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_sheet_contents.cc
@@ -22,7 +22,6 @@
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
-#include "third_party/blink/renderer/core/css/css_timing.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/css/style_rule.h"
@@ -335,7 +334,7 @@ void StyleSheetContents::ParseAuthorStyleSheet(
const SecurityOrigin* security_origin) {
TRACE_EVENT1("blink,devtools.timeline", "ParseAuthorStyleSheet", "data",
InspectorParseAuthorStyleSheetEvent::Data(cached_style_sheet));
- double start_time = CurrentTimeTicksInSeconds();
+ TimeTicks start_time = CurrentTimeTicks();
bool is_same_origin_request =
security_origin && security_origin->CanRequest(BaseURL());
@@ -374,12 +373,8 @@ void StyleSheetContents::ParseAuthorStyleSheet(
DEFINE_STATIC_LOCAL(CustomCountHistogram, parse_histogram,
("Style.AuthorStyleSheet.ParseTime", 0, 10000000, 50));
- double parse_duration_seconds = (CurrentTimeTicksInSeconds() - start_time);
- parse_histogram.Count(parse_duration_seconds * 1000 * 1000);
- if (Document* document = SingleOwnerDocument()) {
- CSSTiming::From(*document).RecordAuthorStyleSheetParseTime(
- parse_duration_seconds);
- }
+ TimeDelta parse_duration = (CurrentTimeTicks() - start_time);
+ parse_histogram.CountMicroseconds(parse_duration);
}
void StyleSheetContents::ParseString(const String& sheet_text) {
diff --git a/chromium/third_party/blink/renderer/core/css/style_sheet_list.cc b/chromium/third_party/blink/renderer/core/css/style_sheet_list.cc
index 3045da40df5..181fa1391ca 100644
--- a/chromium/third_party/blink/renderer/core/css/style_sheet_list.cc
+++ b/chromium/third_party/blink/renderer/core/css/style_sheet_list.cc
@@ -36,24 +36,8 @@ StyleSheetList* StyleSheetList::Create() {
return new StyleSheetList();
}
-StyleSheetList* StyleSheetList::Create(
- const HeapVector<Member<CSSStyleSheet>>& style_sheet_vector,
- ExceptionState& exception_state) {
- if (!RuntimeEnabledFeatures::ConstructableStylesheetsEnabled()) {
- exception_state.ThrowTypeError("Illegal constructor");
- return nullptr;
- }
- return new StyleSheetList(style_sheet_vector);
-}
-
-StyleSheetList::StyleSheetList(
- const HeapVector<Member<CSSStyleSheet>>& style_sheet_vector)
- : style_sheet_vector_(style_sheet_vector) {}
-
StyleSheetList::StyleSheetList(TreeScope* tree_scope)
- : tree_scope_(tree_scope) {
- CHECK(tree_scope);
-}
+ : tree_scope_(tree_scope) {}
inline const HeapVector<TraceWrapperMember<StyleSheet>>&
StyleSheetList::StyleSheets() const {
@@ -62,16 +46,10 @@ StyleSheetList::StyleSheets() const {
}
unsigned StyleSheetList::length() {
- if (!tree_scope_)
- return style_sheet_vector_.size();
return StyleSheets().size();
}
StyleSheet* StyleSheetList::item(unsigned index) {
- if (!tree_scope_) {
- return index < style_sheet_vector_.size() ? style_sheet_vector_[index].Get()
- : nullptr;
- }
const HeapVector<TraceWrapperMember<StyleSheet>>& sheets = StyleSheets();
return index < sheets.size() ? sheets[index].Get() : nullptr;
}
@@ -108,7 +86,6 @@ CSSStyleSheet* StyleSheetList::AnonymousNamedGetter(const AtomicString& name) {
void StyleSheetList::Trace(blink::Visitor* visitor) {
visitor->Trace(tree_scope_);
- visitor->Trace(style_sheet_vector_);
ScriptWrappable::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/css/style_sheet_list.h b/chromium/third_party/blink/renderer/core/css/style_sheet_list.h
index 3ec4f37a496..794c91f3bfc 100644
--- a/chromium/third_party/blink/renderer/core/css/style_sheet_list.h
+++ b/chromium/third_party/blink/renderer/core/css/style_sheet_list.h
@@ -38,8 +38,6 @@ class CORE_EXPORT StyleSheetList final : public ScriptWrappable {
public:
static StyleSheetList* Create();
- static StyleSheetList* Create(const HeapVector<Member<CSSStyleSheet>>&,
- ExceptionState&);
static StyleSheetList* Create(TreeScope* tree_scope) {
return new StyleSheetList(tree_scope);
@@ -59,13 +57,11 @@ class CORE_EXPORT StyleSheetList final : public ScriptWrappable {
void Trace(blink::Visitor*) override;
private:
- explicit StyleSheetList(const HeapVector<Member<CSSStyleSheet>>&);
explicit StyleSheetList(TreeScope*);
StyleSheetList() {}
const HeapVector<TraceWrapperMember<StyleSheet>>& StyleSheets() const;
Member<TreeScope> tree_scope_;
- HeapVector<Member<CSSStyleSheet>> style_sheet_vector_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/style_sheet_list.idl b/chromium/third_party/blink/renderer/core/css/style_sheet_list.idl
index 163c8f1d373..2a7d00e5d94 100644
--- a/chromium/third_party/blink/renderer/core/css/style_sheet_list.idl
+++ b/chromium/third_party/blink/renderer/core/css/style_sheet_list.idl
@@ -21,8 +21,6 @@
// https://drafts.csswg.org/cssom/#the-stylesheetlist-interface
[
- RaisesException=Constructor,
- Constructor(sequence<CSSStyleSheet> sheets),
Exposed=Window
] interface StyleSheetList {
[Measure] getter StyleSheet? item(unsigned long index);
diff --git a/chromium/third_party/blink/renderer/core/css/style_sheet_list_test.cc b/chromium/third_party/blink/renderer/core/css/style_sheet_list_test.cc
deleted file mode 100644
index 7e9e143d82b..00000000000
--- a/chromium/third_party/blink/renderer/core/css/style_sheet_list_test.cc
+++ /dev/null
@@ -1,66 +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 "testing/gtest/include/gtest/gtest.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_style_sheet_init.h"
-#include "third_party/blink/renderer/core/css/style_sheet_list.h"
-#include "third_party/blink/renderer/core/testing/page_test_base.h"
-
-namespace blink {
-
-class StyleSheetListTest : public PageTestBase {
- protected:
- void SetUp() override {
- PageTestBase::SetUp();
- RuntimeEnabledFeatures::SetConstructableStylesheetsEnabled(true);
- }
-};
-
-TEST_F(StyleSheetListTest, ConstructorWithoutRuntimeFlagThrowsException) {
- DummyExceptionStateForTesting exception_state;
- RuntimeEnabledFeatures::SetConstructableStylesheetsEnabled(false);
- HeapVector<Member<CSSStyleSheet>> style_sheet_vector;
- EXPECT_EQ(StyleSheetList::Create(style_sheet_vector, exception_state),
- nullptr);
- ASSERT_TRUE(exception_state.HadException());
-}
-
-TEST_F(StyleSheetListTest, StyleSheetListConstructionWithEmptyList) {
- DummyExceptionStateForTesting exception_state;
- HeapVector<Member<CSSStyleSheet>> style_sheet_vector;
- StyleSheetList* sheet_list =
- StyleSheetList::Create(style_sheet_vector, exception_state);
- ASSERT_FALSE(exception_state.HadException());
- EXPECT_EQ(sheet_list->length(), 0U);
-}
-
-TEST_F(StyleSheetListTest, StyleSheetListConstructionWithNonEmptyList) {
- DummyExceptionStateForTesting exception_state;
- HeapVector<Member<CSSStyleSheet>> style_sheet_vector;
- CSSStyleSheetInit init;
- init.setTitle("Red Sheet");
- CSSStyleSheet* red_style_sheet = CSSStyleSheet::Create(
- GetDocument(), ".red { color: red; }", init, exception_state);
- init.setTitle("Blue Sheet");
- CSSStyleSheet* blue_style_sheet = CSSStyleSheet::Create(
- GetDocument(), ".blue { color: blue; }", init, exception_state);
- style_sheet_vector.push_back(red_style_sheet);
- style_sheet_vector.push_back(blue_style_sheet);
-
- StyleSheetList* sheet_list =
- StyleSheetList::Create(style_sheet_vector, exception_state);
- ASSERT_FALSE(exception_state.HadException());
- EXPECT_EQ(sheet_list->length(), 2U);
- EXPECT_EQ(sheet_list->item(0), red_style_sheet);
- EXPECT_EQ(sheet_list->item(1), blue_style_sheet);
-}
-
-TEST_F(StyleSheetListTest, GetNamedItemNoTreeScope) {
- StyleSheetList* list = StyleSheetList::Create();
- EXPECT_FALSE(list->GetNamedItem("id"));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/css/threaded/filter_operation_resolver_threaded_test.cc b/chromium/third_party/blink/renderer/core/css/threaded/filter_operation_resolver_threaded_test.cc
index 0085165fc5e..fbe080b96bd 100644
--- a/chromium/third_party/blink/renderer/core/css/threaded/filter_operation_resolver_threaded_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/threaded/filter_operation_resolver_threaded_test.cc
@@ -9,6 +9,8 @@
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
#include "third_party/blink/renderer/core/css/threaded/multi_threaded_test_util.h"
#include "third_party/blink/renderer/core/style/filter_operation.h"
+#include "third_party/blink/renderer/platform/fonts/font.h"
+#include "third_party/blink/renderer/platform/fonts/font_description.h"
namespace blink {
@@ -19,8 +21,10 @@ TSAN_TEST(FilterOperationResolverThreadedTest, SimpleMatrixFilter) {
StrictCSSParserContext(SecureContextMode::kInsecureContext));
ASSERT_TRUE(value);
+ FontDescription font_description;
+ Font font(font_description);
FilterOperations fo =
- FilterOperationResolver::CreateOffscreenFilterOperations(*value);
+ FilterOperationResolver::CreateOffscreenFilterOperations(*value, font);
ASSERT_EQ(fo.size(), 1ul);
EXPECT_EQ(*fo.at(0), *BasicColorMatrixFilterOperation::Create(
0.5, FilterOperation::SEPIA));
@@ -34,8 +38,10 @@ TSAN_TEST(FilterOperationResolverThreadedTest, SimpleTransferFilter) {
StrictCSSParserContext(SecureContextMode::kInsecureContext));
ASSERT_TRUE(value);
+ FontDescription font_description;
+ Font font(font_description);
FilterOperations fo =
- FilterOperationResolver::CreateOffscreenFilterOperations(*value);
+ FilterOperationResolver::CreateOffscreenFilterOperations(*value, font);
ASSERT_EQ(fo.size(), 1ul);
EXPECT_EQ(*fo.at(0), *BasicComponentTransferFilterOperation::Create(
0.5, FilterOperation::BRIGHTNESS));
@@ -49,8 +55,10 @@ TSAN_TEST(FilterOperationResolverThreadedTest, SimpleBlurFilter) {
StrictCSSParserContext(SecureContextMode::kInsecureContext));
ASSERT_TRUE(value);
+ FontDescription font_description;
+ Font font(font_description);
FilterOperations fo =
- FilterOperationResolver::CreateOffscreenFilterOperations(*value);
+ FilterOperationResolver::CreateOffscreenFilterOperations(*value, font);
ASSERT_EQ(fo.size(), 1ul);
EXPECT_EQ(*fo.at(0),
*BlurFilterOperation::Create(Length(10, LengthType::kFixed)));
@@ -64,8 +72,10 @@ TSAN_TEST(FilterOperationResolverThreadedTest, SimpleDropShadow) {
StrictCSSParserContext(SecureContextMode::kInsecureContext));
ASSERT_TRUE(value);
+ FontDescription font_description;
+ Font font(font_description);
FilterOperations fo =
- FilterOperationResolver::CreateOffscreenFilterOperations(*value);
+ FilterOperationResolver::CreateOffscreenFilterOperations(*value, font);
ASSERT_EQ(fo.size(), 1ul);
EXPECT_EQ(*fo.at(0), *DropShadowFilterOperation::Create(ShadowData(
FloatPoint(10, 5), 1, 0, ShadowStyle::kNormal,
@@ -80,8 +90,10 @@ TSAN_TEST(FilterOperationResolverThreadedTest, CompoundFilter) {
StrictCSSParserContext(SecureContextMode::kInsecureContext));
ASSERT_TRUE(value);
+ FontDescription font_description;
+ Font font(font_description);
FilterOperations fo =
- FilterOperationResolver::CreateOffscreenFilterOperations(*value);
+ FilterOperationResolver::CreateOffscreenFilterOperations(*value, font);
EXPECT_FALSE(fo.IsEmpty());
ASSERT_EQ(fo.size(), 2ul);
EXPECT_EQ(*fo.at(0), *BasicColorMatrixFilterOperation::Create(
diff --git a/chromium/third_party/blink/renderer/core/css/threaded/font_object_threaded_test.cc b/chromium/third_party/blink/renderer/core/css/threaded/font_object_threaded_test.cc
index 1f7630a725d..c3351970cce 100644
--- a/chromium/third_party/blink/renderer/core/css/threaded/font_object_threaded_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/threaded/font_object_threaded_test.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/css/resolver/filter_operation_resolver.h"
+#include "cc/paint/paint_flags.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
@@ -14,7 +15,7 @@
#include "third_party/blink/renderer/platform/fonts/font_description.h"
#include "third_party/blink/renderer/platform/fonts/font_selector.h"
#include "third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h"
#include "third_party/blink/renderer/platform/fonts/text_run_paint_info.h"
#include "third_party/blink/renderer/platform/language.h"
#include "third_party/blink/renderer/platform/testing/font_test_helpers.h"
@@ -84,7 +85,7 @@ TSAN_TEST(FontObjectThreadedTest, TextIntercepts) {
0x70, 0xc9, 0x70, 0xc9};
TextRun ahem_above_below_baseline(ahem_above_below_baseline_string, 9);
TextRunPaintInfo text_run_paint_info(ahem_above_below_baseline);
- PaintFlags default_paint;
+ cc::PaintFlags default_paint;
float device_scale_factor = 1;
std::tuple<float, float> below_baseline_bounds = std::make_tuple(2, 4);
Vector<Font::TextIntercept> text_intercepts;
diff --git a/chromium/third_party/blink/renderer/core/css/threaded/text_renderer_threaded_test.cc b/chromium/third_party/blink/renderer/core/css/threaded/text_renderer_threaded_test.cc
index d911f47d728..93c3382848d 100644
--- a/chromium/third_party/blink/renderer/core/css/threaded/text_renderer_threaded_test.cc
+++ b/chromium/third_party/blink/renderer/core/css/threaded/text_renderer_threaded_test.cc
@@ -11,7 +11,7 @@
#include "third_party/blink/renderer/platform/fonts/font_description.h"
#include "third_party/blink/renderer/platform/fonts/font_selector.h"
#include "third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h"
#include "third_party/blink/renderer/platform/fonts/text_run_paint_info.h"
#include "third_party/blink/renderer/platform/graphics/test/mock_paint_canvas.h"
#include "third_party/blink/renderer/platform/language.h"
diff --git a/chromium/third_party/blink/renderer/core/dom/BUILD.gn b/chromium/third_party/blink/renderer/core/dom/BUILD.gn
index f7e061d3624..740a785228d 100644
--- a/chromium/third_party/blink/renderer/core/dom/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/dom/BUILD.gn
@@ -12,20 +12,12 @@ blink_core_sources("dom") {
"abort_controller.h",
"abort_signal.cc",
"abort_signal.h",
- "accessible_node.cc",
- "accessible_node.h",
- "accessible_node_list.cc",
- "accessible_node_list.h",
"animation_worklet_proxy_client.cc",
"animation_worklet_proxy_client.h",
"attr.cc",
"attr.h",
"attribute.h",
"attribute_collection.h",
- "ax_object_cache.cc",
- "ax_object_cache.h",
- "ax_object_cache_base.cc",
- "ax_object_cache_base.h",
"cdata_section.cc",
"cdata_section.h",
"character_data.cc",
@@ -42,8 +34,6 @@ blink_core_sources("dom") {
"collection_index_cache.h",
"comment.cc",
"comment.h",
- "computed_accessible_node.cc",
- "computed_accessible_node.h",
"container_node.cc",
"container_node.h",
"context_features.cc",
@@ -119,10 +109,10 @@ blink_core_sources("dom") {
"events/add_event_listener_options_resolved.h",
"events/custom_event.cc",
"events/custom_event.h",
- "events/dom_window_event_queue.cc",
- "events/dom_window_event_queue.h",
"events/event.cc",
"events/event.h",
+ "events/event_dispatch_forbidden_scope.cc",
+ "events/event_dispatch_forbidden_scope.h",
"events/event_dispatch_result.h",
"events/event_dispatcher.cc",
"events/event_dispatcher.h",
@@ -131,13 +121,12 @@ blink_core_sources("dom") {
"events/event_listener_map.h",
"events/event_path.cc",
"events/event_path.h",
+ "events/event_queue.cc",
"events/event_queue.h",
"events/event_target.cc",
"events/event_target.h",
"events/event_target_impl.cc",
"events/event_target_impl.h",
- "events/media_element_event_queue.cc",
- "events/media_element_event_queue.h",
"events/node_event_context.cc",
"events/node_event_context.h",
"events/scoped_event_queue.cc",
@@ -147,11 +136,12 @@ blink_core_sources("dom") {
"events/tree_scope_event_context.h",
"events/window_event_context.cc",
"events/window_event_context.h",
- "exception_code.h",
"first_letter_pseudo_element.cc",
"first_letter_pseudo_element.h",
"flat_tree_traversal.cc",
"flat_tree_traversal.h",
+ "flat_tree_traversal_ng.cc",
+ "flat_tree_traversal_ng.h",
"frame_request_callback_collection.cc",
"frame_request_callback_collection.h",
"global_event_handlers.h",
@@ -190,10 +180,6 @@ blink_core_sources("dom") {
"named_node_map.h",
"names_map.cc",
"names_map.h",
- "ng/flat_tree_traversal_ng.cc",
- "ng/flat_tree_traversal_ng.h",
- "ng/slot_assignment_engine.cc",
- "ng/slot_assignment_engine.h",
"node.cc",
"node.h",
"node_child_removal_tracker.cc",
@@ -248,13 +234,14 @@ blink_core_sources("dom") {
"sink_document.h",
"slot_assignment.cc",
"slot_assignment.h",
+ "slot_assignment_engine.cc",
+ "slot_assignment_engine.h",
+ "slot_assignment_recalc_forbidden_scope.h",
"space_split_string.cc",
"space_split_string.h",
"static_node_list.h",
"static_range.cc",
"static_range.h",
- "sync_reattach_context.cc",
- "sync_reattach_context.h",
"synchronous_mutation_notifier.cc",
"synchronous_mutation_notifier.h",
"synchronous_mutation_observer.cc",
@@ -280,20 +267,12 @@ blink_core_sources("dom") {
"tree_scope_adopter.h",
"tree_walker.cc",
"tree_walker.h",
- "trustedtypes/trusted_html.cc",
- "trustedtypes/trusted_html.h",
- "trustedtypes/trusted_script_url.cc",
- "trustedtypes/trusted_script_url.h",
- "trustedtypes/trusted_url.cc",
- "trustedtypes/trusted_url.h",
"user_action_element_set.cc",
"user_action_element_set.h",
"user_gesture_indicator.cc",
"user_gesture_indicator.h",
"v0_insertion_point.cc",
"v0_insertion_point.h",
- "viewport_description.cc",
- "viewport_description.h",
"visited_link_state.cc",
"visited_link_state.h",
"weak_identifier_map.h",
@@ -305,6 +284,9 @@ blink_core_sources("dom") {
public_deps = [
"//third_party/blink/public/mojom:mojom_core_blink",
+
+ # Needed to generate included files, e.g. add_event_listener_options.h
+ "//third_party/blink/renderer/bindings/core/v8:bindings_core_v8_generated",
]
deps = [
diff --git a/chromium/third_party/blink/renderer/core/dom/README.md b/chromium/third_party/blink/renderer/core/dom/README.md
index 1beaa9238db..6a315e94658 100644
--- a/chromium/third_party/blink/renderer/core/dom/README.md
+++ b/chromium/third_party/blink/renderer/core/dom/README.md
@@ -6,32 +6,34 @@ Author: hayato@chromium.org
The `Source/core/dom` directory contains the implementation of [DOM].
-[DOM]: https://dom.spec.whatwg.org/
-[DOM Standard]: https://dom.spec.whatwg.org/
+[dom]: https://dom.spec.whatwg.org/
+[dom standard]: https://dom.spec.whatwg.org/
-Basically, this directory should contain only a file which is related to [DOM Standard].
-However, for historical reasons, `Source/core/dom` directory has been used
-as if it were *misc* directory. As a result, unfortunately, this directory
+Basically, this directory should contain only a file which is related to [DOM
+Standard]. However, for historical reasons, `Source/core/dom` directory has been
+used as if it were _misc_ directory. As a result, unfortunately, this directory
contains a lot of files which are not directly related to DOM.
-Please don't add unrelated files to this directory any more. We are trying to
+Please don't add unrelated files to this directory any more. We are trying to
organize the files so that developers wouldn't get confused at seeing this
directory.
-- See the [spreadsheet](https://docs.google.com/spreadsheets/d/1OydPU6r8CTj8HC4D9_gVkriJETu1Egcw2RlajYcw3FM/edit?usp=sharing), as a rough plan to organize Source/core/dom files.
+- See the
+ [spreadsheet](https://docs.google.com/spreadsheets/d/1OydPU6r8CTj8HC4D9_gVkriJETu1Egcw2RlajYcw3FM/edit?usp=sharing),
+ as a rough plan to organize Source/core/dom files.
- The classification in the spreadsheet might be wrong. Please update the spreadsheet, and move files if you can,
- if you know more appropriate places for each file.
-
-- See [crbug.com/738794](http://crbug.com/738794) for tracking our efforts.
+ The classification in the spreadsheet might be wrong. Please update the
+ spreadsheet, and move files if you can, if you know more appropriate places
+ for each file.
+- See [crbug.com/738794](http://crbug.com/738794) for tracking our efforts.
# Node and Node Tree
-In this README, we draw a tree in left-to-right direction. `A` is the root of the tree.
-
+In this README, we draw a tree in left-to-right direction. `A` is the root of
+the tree.
-``` text
+```text
A
├───B
├───C
@@ -40,30 +42,35 @@ A
└───F
```
+`Node` is a base class of all kinds of nodes in a node tree. Each `Node` has
+following 3 pointers (but not limited to):
-`Node` is a base class of all kinds of nodes in a node tree. Each `Node` has following 3 pointers (but not limited to):
+- `parent_or_shadow_host_node_`: Points to the parent (or the shadow host if it
+ is a shadow root; explained later)
+- `previous_`: Points to the previous sibling
+- `next_`: Points to the next sibling
-- `parent_or_shadow_host_node_`: Points to the parent (or the shadow host if it is a shadow root; explained later)
-- `previous_`: Points to the previous sibling
-- `next_`: Points to the next sibling
+`ContainerNode`, from which `Element` extends, has additional pointers for its
+child:
-`ContainerNode`, from which `Element` extends, has additional pointers for its child:
-
-- `first_child_`: The meaning is obvious.
-- `last_child_`: Nit.
+- `first_child_`: The meaning is obvious.
+- `last_child_`: Nit.
That means:
-- Siblings are stored as a linked list. It takes O(N) to access a parent's n-th child.
+
+- Siblings are stored as a linked list. It takes O(N) to access a parent's n-th
+ child.
- Parent can't tell how many children it has in O(1).
Further info:
+
- `Node`, `ContainerNode`
# C++11 range-based for loops for traversing a tree
You can traverse a tree manually:
-``` c++
+```c++
// In C++
// Traverse a children.
@@ -82,48 +89,53 @@ void foo(const Node& node) {
}
```
-However, traversing a tree in this way might be error-prone.
-Instead, you can use `NodeTraversal` and `ElementTraversal`. They provides a C++11's range-based for loops, such as:
+However, traversing a tree in this way might be error-prone. Instead, you can
+use `NodeTraversal` and `ElementTraversal`. They provides a C++11's range-based
+for loops, such as:
-``` c++
+```c++
// In C++
for (Node& child : NodeTraversal::childrenOf(parent) {
...
}
```
-e.g. Given a parent *A*, this traverses *B*, *C*, and *F* in this order.
-
+e.g. Given a parent _A_, this traverses _B_, _C_, and _F_ in this order.
-``` c++
+```c++
// In C++
for (Node& node : NodeTraversal::startsAt(root)) {
...
}
```
-e.g. Given the root *A*, this traverses *A*, *B*, *C*, *D*, *E*, and *F* in this order.
+e.g. Given the root _A_, this traverses _A_, _B_, _C_, _D_, _E_, and _F_ in this
+order.
-There are several other useful range-based for loops for each purpose.
-The cost of using range-based for loops is zero because everything can be inlined.
+There are several other useful range-based for loops for each purpose. The cost
+of using range-based for loops is zero because everything can be inlined.
Further info:
- `NodeTraversal` and `ElementTraversal` (more type-safe version)
-- The [CL](https://codereview.chromium.org/642973003), which introduced these range-based for loops.
+- The [CL](https://codereview.chromium.org/642973003), which introduced these
+ range-based for loops.
# Shadow Tree
-A **shadow tree** is a node tree whose root is a `ShadowRoot`.
-From web developer's perspective, a shadow root can be created by calling `element.attachShadow{ ... }` API.
-The *element* here is called a **shadow host**, or just a **host** if the context is clear.
+A **shadow tree** is a node tree whose root is a `ShadowRoot`. From web
+developer's perspective, a shadow root can be created by calling
+`element.attachShadow{ ... }` API. The _element_ here is called a **shadow
+host**, or just a **host** if the context is clear.
-- A shadow root is always attached to another node tree through its host. A shadow tree is therefore never alone.
-- The node tree of a shadow root’s host is sometimes referred to as the **light tree**.
+- A shadow root is always attached to another node tree through its host. A
+ shadow tree is therefore never alone.
+- The node tree of a shadow root’s host is sometimes referred to as the **light
+ tree**.
For example, given the example node tree:
-``` text
+```text
A
├───B
├───C
@@ -132,26 +144,27 @@ A
└───F
```
-Web developers can create a shadow root, and manipulate the shadow tree in the following way:
+Web developers can create a shadow root, and manipulate the shadow tree in the
+following way:
-``` javascript
+```javascript
// In JavaScript
const b = document.querySelector('#B');
-const shadowRoot = b.attachShadow({ mode: 'open'} )
+const shadowRoot = b.attachShadow({ mode: 'open' });
const sb = document.createElement('div');
shadowRoot.appendChild(sb);
```
The resulting shadow tree would be:
-``` text
+```text
shadowRoot
└── sb
```
-The *shadowRoot* has one child, *sb*. This shadow tree is being *attached* to B:
+The _shadowRoot_ has one child, _sb_. This shadow tree is being _attached_ to B:
-``` text
+```text
A
└── B
├──/shadowRoot
@@ -162,24 +175,26 @@ A
└── F
```
-In this README, a notation (`──/`) is used to represent a *shadowhost-shadowroot* relationship, in a **composed tree**.
-A composed tree will be explained later. A *shadowhost-shadowroot* is 1:1 relationship.
-
-Though a shadow root has always a corresponding shadow host element, a light tree and a shadow tree should be considered separately, from a node tree's perspective. (`──/`) is *NOT* a parent-child relationship in a node tree.
+In this README, a notation (`──/`) is used to represent a
+_shadowhost-shadowroot_ relationship, in a **composed tree**. A composed tree
+will be explained later. A _shadowhost-shadowroot_ is 1:1 relationship.
-For example, even though *B* *hosts* the shadow tree, *shadowRoot* is not considered as a *child* of *B*.
-The means the following traversal:
+Though a shadow root has always a corresponding shadow host element, a light
+tree and a shadow tree should be considered separately, from a node tree's
+perspective. (`──/`) is _NOT_ a parent-child relationship in a node tree.
+For example, even though _B_ _hosts_ the shadow tree, _shadowRoot_ is not
+considered as a _child_ of _B_. The means the following traversal:
-``` c++
+```c++
// In C++
for (Node& node : NodeTraversal::startsAt(A)) {
...
}
```
-traverses only *A*, *B*, *C*, *D*, *E* and *F* nodes. It never visits *shadowRoot* nor *sb*.
-NodeTraversal never cross a shadow boundary, `──/`.
+traverses only _A_, _B_, _C_, _D_, _E_ and _F_ nodes. It never visits
+_shadowRoot_ nor _sb_. NodeTraversal never cross a shadow boundary, `──/`.
Further info:
@@ -188,35 +203,41 @@ Further info:
# TreeScope
-`Document` and `ShadowRoot` are always the root of a node tree.
-Both`Document` and `ShadowRoot` implements `TreeScope`.
+`Document` and `ShadowRoot` are always the root of a node tree. Both`Document`
+and `ShadowRoot` implements `TreeScope`.
-`TreeScope` maintains a lot of information about the underlying tree for efficiency.
-For example, TreeScope has a *id-to-element* mapping, as [`TreeOrderedMap`](./TreeOrderedMap.h), so that `querySelector('#foo')` can find an element whose id attribute is "foo" in O(1).
-In other words, `root.querySelector('#foo')` can be slow if that is used in a node tree whose root is not `TreeScope`.
+`TreeScope` maintains a lot of information about the underlying tree for
+efficiency. For example, TreeScope has a _id-to-element_ mapping, as
+[`TreeOrderedMap`](./TreeOrderedMap.h), so that `querySelector('#foo')` can find
+an element whose id attribute is "foo" in O(1). In other words,
+`root.querySelector('#foo')` can be slow if that is used in a node tree whose
+root is not `TreeScope`.
Each `Node` has `tree_scope_` pointer, which points to:
- The root node: if the node's root is either Document or ShadowRoot.
-- [owner document](https://dom.spec.whatwg.org/#concept-node-documentOwnerDocument), otherwise.
+- [owner document](https://dom.spec.whatwg.org/#concept-node-documentOwnerDocument),
+ otherwise.
-The means `tree_scope_` pointer is always non-null (except for while in a DOM mutation),
-but it doesn't always point to the node's root.
+The means `tree_scope_` pointer is always non-null (except for while in a DOM
+mutation), but it doesn't always point to the node's root.
-Since each node doesn't have a pointer which *always* points to the root,
-`Node::getRootNode(...)` may take O(N) if the node is neither in a document tree nor in a shadow tree.
-If the node is in TreeScope (`Node#IsInTreeScope()` can tell it), we can get the root in O(1).
+Since each node doesn't have a pointer which _always_ points to the root,
+`Node::getRootNode(...)` may take O(N) if the node is neither in a document tree
+nor in a shadow tree. If the node is in TreeScope (`Node#IsInTreeScope()` can
+tell it), we can get the root in O(1).
-Each node has flags, which is updated in DOM mutation, so that we can tell whether the node is in a
-document tree, in a shadow tree, or in none of them, by using
-`Node::IsInDocumentTree()` and/or `Node::IsInShadowTree()`.
+Each node has flags, which is updated in DOM mutation, so that we can tell
+whether the node is in a document tree, in a shadow tree, or in none of them, by
+using `Node::IsInDocumentTree()` and/or `Node::IsInShadowTree()`.
-If you want to add new features to `Document`, `Document` might be a wrong place to add.
-Instead, please consider to add functionality to `TreeScope`. We want to treat a document tree and a shadow tree equally as much as possible.
+If you want to add new features to `Document`, `Document` might be a wrong place
+to add. Instead, please consider to add functionality to `TreeScope`. We want to
+treat a document tree and a shadow tree equally as much as possible.
## Example
-``` text
+```text
document
└── a1
├──/shadowRoot1
@@ -232,12 +253,14 @@ document-fragment
└── b3
```
-- Here, there are 4 node trees; The root node of each tree is *document*, *shadowRoot1*, *document-fragment*, and *shadowRoot2*.
-- Suppose that each node is created by `document.createElement(...)` (except for Document and ShadowRoot).
- That means each node's **owner document** is *document*.
+- Here, there are 4 node trees; The root node of each tree is _document_,
+ _shadowRoot1_, _document-fragment_, and _shadowRoot2_.
+- Suppose that each node is created by `document.createElement(...)` (except for
+ Document and ShadowRoot). That means each node's **owner document** is
+ _document_.
| node | node's root | node's `_tree_scope` points to: |
-|-------------------|--------------------------|---------------------------------|
+| ----------------- | ------------------------ | ------------------------------- |
| document | document (self) | document (self) |
| a1 | document | document |
| a2 | document | document |
@@ -258,11 +281,11 @@ Further Info:
# Composed Tree (a tree of node trees)
-In the previous picture, you might think that more than one node trees, a document tree and a shadow tree, were *connected* to each other. That is *true* in some sense.
-The following is a more complex example:
+In the previous picture, you might think that more than one node trees, a
+document tree and a shadow tree, were _connected_ to each other. That is _true_
+in some sense. The following is a more complex example:
-
-``` text
+```text
document
├── a1 (host)
│ ├──/shadowRoot1
@@ -290,12 +313,12 @@ document
└── f2
```
-If you see this carefully, you can notice that this *composed tree* is composed of 6 node trees; 1 document tree and 5 shadow trees:
-
+If you see this carefully, you can notice that this _composed tree_ is composed
+of 6 node trees; 1 document tree and 5 shadow trees:
- document tree
- ``` text
+ ```text
document
├── a1 (host)
│ └── a2 (host)
@@ -307,14 +330,14 @@ If you see this carefully, you can notice that this *composed tree* is composed
- shadow tree 1
- ``` text
+ ```text
shadowRoot1
└── b1
```
- shadow tree 2
- ``` text
+ ```text
shadowRoot2
├── c1
│ ├── c2
@@ -324,7 +347,7 @@ If you see this carefully, you can notice that this *composed tree* is composed
- shadow tree 3
- ``` text
+ ```text
shadowRoot3
└── d1
├── d2
@@ -334,7 +357,7 @@ If you see this carefully, you can notice that this *composed tree* is composed
- shadow tree 4
- ``` text
+ ```text
shadowRoot4
├── e1
└── e2
@@ -342,15 +365,16 @@ If you see this carefully, you can notice that this *composed tree* is composed
- shadow tree 5
- ``` text
+ ```text
shadowRoot5
├── f1
└── f2
```
-If we consider each *node tree* as *node* of a *super-tree*, we can draw a super-tree as such:
+If we consider each _node tree_ as _node_ of a _super-tree_, we can draw a
+super-tree as such:
-``` text
+```text
document
├── shadowRoot1
├── shadowRoot2
@@ -359,10 +383,12 @@ document
└── shadowRoot5
```
-Here, a root node is used as a representative of each node tree; A root node and a node tree itself can be sometimes exchangeable in explanations.
+Here, a root node is used as a representative of each node tree; A root node and
+a node tree itself can be sometimes exchangeable in explanations.
-We call this kind of a *super-tree* (*a tree of node trees*) a **composed tree**.
-The concept of a *composed tree* is very useful to understand how Shadow DOM's encapsulation works.
+We call this kind of a _super-tree_ (_a tree of node trees_) a **composed
+tree**. The concept of a _composed tree_ is very useful to understand how Shadow
+DOM's encapsulation works.
[DOM Standard] defines the following terminologies:
@@ -376,17 +402,18 @@ The concept of a *composed tree* is very useful to understand how Shadow DOM's e
For example,
-- *d1*'s *shadow-including ancestor nodes* are *shadowRoot3*, *a6*, *a5*, and *document*
-- *d1*'s *shadow-including descendant nodes* are *d2*, *d3*, *shadowRoot4*, *e1*, *e2*, *d4*, *shadowRoot5*, *f1*, and *f2*.
-
+- _d1_'s _shadow-including ancestor nodes_ are _shadowRoot3_, _a6_, _a5_, and
+ _document_
+- _d1_'s _shadow-including descendant nodes_ are _d2_, _d3_, _shadowRoot4_,
+ _e1_, _e2_, _d4_, _shadowRoot5_, _f1_, and _f2_.
-To honor Shadow DOM's encapsulation, we have a concept of *visibility relationship* between two nodes.
+To honor Shadow DOM's encapsulation, we have a concept of _visibility
+relationship_ between two nodes.
-In the following table, "`-`" means that "node *A* is *visible* from node *B*".
+In the following table, "`-`" means that "node _A_ is _visible_ from node _B_".
-
-| *A* \ *B* | document | a1 | a2 | b1 | c1 | d1 | d2 | e1 | f1 |
-|-----------|----------|--------|--------|--------|--------|--------|--------|--------|--------|
+| _A_ \ _B_ | document | a1 | a2 | b1 | c1 | d1 | d2 | e1 | f1 |
+| --------- | -------- | ------ | ------ | ------ | ------ | ------ | ------ | ------ | ------ |
| document | - | - | - | - | - | - | - | - | - |
| a1 | - | - | - | - | - | - | - | - | - |
| a2 | - | - | - | - | - | - | - | - | - |
@@ -397,22 +424,27 @@ In the following table, "`-`" means that "node *A* is *visible* from node *B*".
| e1 | hidden | hidden | hidden | hidden | hidden | hidden | hidden | - | hidden |
| f1 | hidden | hidden | hidden | hidden | hidden | hidden | hidden | hidden | - |
-For example, *document* is *visible* from any nodes.
+For example, _document_ is _visible_ from any nodes.
-To understand *visibility relationship* easily, here is a rule of thumb:
+To understand _visibility relationship_ easily, here is a rule of thumb:
-- If node *B* can reach node *A* by traversing an *edge* (in the first picture of this section), recursively, *A* is visible from *B*.
-- However, an *edge* of (`──/`) ( *shadowhost-shadowroot* relationship) is one-directional:
+- If node _B_ can reach node _A_ by traversing an _edge_ (in the first picture
+ of this section), recursively, _A_ is visible from _B_.
+- However, an _edge_ of (`──/`) ( _shadowhost-shadowroot_ relationship) is
+ one-directional:
- From a shadow root to the shadow host -> Okay
- From a shadow host to the shadow root -> Forbidden
-In other words, a node in an *inner tree* can see a node in an *outer tree* in a composed tree, but the opposite is not true.
+In other words, a node in an _inner tree_ can see a node in an _outer tree_ in a
+composed tree, but the opposite is not true.
-We have designed (or re-designed) a bunch of Web-facing APIs to honor this basic principle.
-If you add a new API to the web platform and Blink, please consider this rule and don't *leak* a node which should be hidden to web developers.
+We have designed (or re-designed) a bunch of Web-facing APIs to honor this basic
+principle. If you add a new API to the web platform and Blink, please consider
+this rule and don't _leak_ a node which should be hidden to web developers.
-Warning: Unfortunately, a *composed tree* had a different meaning in the past; it was used to specify a *flat tree* (which will be explained later).
-If you find a wrong usage of a composed tree in Blink, please fix it.
+Warning: Unfortunately, a _composed tree_ had a different meaning in the past;
+it was used to specify a _flat tree_ (which will be explained later). If you
+find a wrong usage of a composed tree in Blink, please fix it.
Further Info:
@@ -423,22 +455,24 @@ Further Info:
# Flat tree
-A composed tree itself can't be rendered *as is*. From the rendering's
-perspective, Blink has to construct a *layout tree*, which would be used as an input to
-the *paint phase*. A layout tree is a tree whose node is `LayoutObject`, which
-points to `Node` in a node tree, plus additional calculated layout information.
+A composed tree itself can't be rendered _as is_. From the rendering's
+perspective, Blink has to construct a _layout tree_, which would be used as an
+input to the _paint phase_. A layout tree is a tree whose node is
+`LayoutObject`, which points to `Node` in a node tree, plus additional
+calculated layout information.
Before the Web Platform got Shadow DOM, the structure of a layout tree is almost
-*similar* to the structure of a document tree; where only one node tree,
-*document tree*, is being involved there.
+_similar_ to the structure of a document tree; where only one node tree,
+_document tree_, is being involved there.
-Since the Web Platform got Shadow DOM, we now have a composed tree which is composed of multiple node
-trees, instead of a single node tree. That means We have to *flatten* the composed tree to the one node tree, called
-a *flat tree*, from which a layout tree is constructed.
+Since the Web Platform got Shadow DOM, we now have a composed tree which is
+composed of multiple node trees, instead of a single node tree. That means We
+have to _flatten_ the composed tree to the one node tree, called a _flat tree_,
+from which a layout tree is constructed.
For example, given the following composed tree,
-``` text
+```text
document
├── a1 (host)
│ ├──/shadowRoot1
@@ -464,13 +498,12 @@ document
└──/shadowRoot5
├── f1
└── f2
-
```
-This composed tree would be flattened into the following *flat tree* (assuming there are not `<slot>` elements there):
-
+This composed tree would be flattened into the following _flat tree_ (assuming
+there are not `<slot>` elements there):
-``` text
+```text
document
├── a1 (host)
│ └── b1
@@ -486,19 +519,23 @@ document
└── f2
```
-We can't explain the exact algorithm how to flatten a composed tree into a flat tree until I explain the concept of *slots* and *node distribution*
-If we are ignoring the effect of `<slot>`, we can have the following simple definition. A flat tree can be defined as:
+We can't explain the exact algorithm how to flatten a composed tree into a flat
+tree until I explain the concept of _slots_ and _node distribution_ If we are
+ignoring the effect of `<slot>`, we can have the following simple definition. A
+flat tree can be defined as:
-- A root of a flat tree: *document*
-- Given node *A* which is in a flat tree, its children are defined, recursively, as follows:
- - If *A* is a shadow host, its shadow root's children
- - Otherwise, *A*'s children
+- A root of a flat tree: _document_
+- Given node _A_ which is in a flat tree, its children are defined, recursively,
+ as follows:
+ - If _A_ is a shadow host, its shadow root's children
+ - Otherwise, _A_'s children
# Distribution and slots
TODO(hayato): Explain.
-In the meantime, please see [Incremental Shadow DOM](https://docs.google.com/document/d/1R9J8CVaSub_nbaVQwwm3NjCoZye4feJ7ft7tVe5QerM/edit?usp=sharing).
+In the meantime, please see
+[Incremental Shadow DOM](https://docs.google.com/document/d/1R9J8CVaSub_nbaVQwwm3NjCoZye4feJ7ft7tVe5QerM/edit?usp=sharing).
# FlatTreeTraversal
diff --git a/chromium/third_party/blink/renderer/core/dom/abort_signal.cc b/chromium/third_party/blink/renderer/core/dom/abort_signal.cc
index 66efd63020d..e0283241bd6 100644
--- a/chromium/third_party/blink/renderer/core/dom/abort_signal.cc
+++ b/chromium/third_party/blink/renderer/core/dom/abort_signal.cc
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/event_target_names.h"
#include "third_party/blink/renderer/core/event_type_names.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/platform/heap/visitor.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
diff --git a/chromium/third_party/blink/renderer/core/dom/accessibility_role.idl b/chromium/third_party/blink/renderer/core/dom/accessibility_role.idl
index 057c4f1f43e..cda5216ed76 100644
--- a/chromium/third_party/blink/renderer/core/dom/accessibility_role.idl
+++ b/chromium/third_party/blink/renderer/core/dom/accessibility_role.idl
@@ -3,7 +3,7 @@
// found in the LICENSE file.
// ARIA reflection
-// https://github.com/w3c/aria/pull/708/files
+// https://w3c.github.io/aria/#idl-interface
[
NoInterfaceObject,
RuntimeEnabled=AccessibilityObjectModel
diff --git a/chromium/third_party/blink/renderer/core/dom/accessible_node.cc b/chromium/third_party/blink/renderer/core/dom/accessible_node.cc
deleted file mode 100644
index 02f32e7db0c..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/accessible_node.cc
+++ /dev/null
@@ -1,1191 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/dom/accessible_node.h"
-
-#include "third_party/blink/renderer/core/dom/accessible_node_list.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
-#include "third_party/blink/renderer/core/dom/element.h"
-#include "third_party/blink/renderer/core/dom/qualified_name.h"
-#include "third_party/blink/renderer/core/frame/settings.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-
-namespace blink {
-
-using namespace HTMLNames;
-
-namespace {
-
-QualifiedName GetCorrespondingARIAAttribute(AOMStringProperty property) {
- switch (property) {
- case AOMStringProperty::kAutocomplete:
- return aria_autocompleteAttr;
- case AOMStringProperty::kChecked:
- return aria_checkedAttr;
- case AOMStringProperty::kCurrent:
- return aria_currentAttr;
- case AOMStringProperty::kHasPopUp:
- return aria_haspopupAttr;
- case AOMStringProperty::kInvalid:
- return aria_invalidAttr;
- case AOMStringProperty::kKeyShortcuts:
- return aria_keyshortcutsAttr;
- case AOMStringProperty::kLabel:
- return aria_labelAttr;
- case AOMStringProperty::kLive:
- return aria_liveAttr;
- case AOMStringProperty::kOrientation:
- return aria_orientationAttr;
- case AOMStringProperty::kPlaceholder:
- return aria_placeholderAttr;
- case AOMStringProperty::kPressed:
- return aria_pressedAttr;
- case AOMStringProperty::kRelevant:
- return aria_relevantAttr;
- case AOMStringProperty::kRole:
- return roleAttr;
- case AOMStringProperty::kRoleDescription:
- return aria_roledescriptionAttr;
- case AOMStringProperty::kSort:
- return aria_sortAttr;
- case AOMStringProperty::kValueText:
- return aria_valuetextAttr;
- }
-
- NOTREACHED();
- return g_null_name;
-}
-
-QualifiedName GetCorrespondingARIAAttribute(AOMRelationProperty property) {
- switch (property) {
- case AOMRelationProperty::kActiveDescendant:
- return aria_activedescendantAttr;
- break;
- case AOMRelationProperty::kDetails:
- return aria_detailsAttr;
- break;
- case AOMRelationProperty::kErrorMessage:
- return aria_errormessageAttr;
- break;
- }
-
- NOTREACHED();
- return g_null_name;
-}
-
-QualifiedName GetCorrespondingARIAAttribute(AOMRelationListProperty property) {
- switch (property) {
- case AOMRelationListProperty::kDescribedBy:
- return aria_describedbyAttr;
- break;
- case AOMRelationListProperty::kControls:
- return aria_controlsAttr;
- break;
- case AOMRelationListProperty::kFlowTo:
- return aria_flowtoAttr;
- break;
- case AOMRelationListProperty::kLabeledBy:
- // Note that there are two allowed spellings of this attribute.
- // Callers should check both.
- return aria_labelledbyAttr;
- break;
- case AOMRelationListProperty::kOwns:
- return aria_ownsAttr;
- break;
- }
-
- NOTREACHED();
- return g_null_name;
-}
-
-QualifiedName GetCorrespondingARIAAttribute(AOMBooleanProperty property) {
- switch (property) {
- case AOMBooleanProperty::kAtomic:
- return aria_atomicAttr;
- break;
- case AOMBooleanProperty::kBusy:
- return aria_busyAttr;
- break;
- case AOMBooleanProperty::kDisabled:
- return aria_disabledAttr;
- break;
- case AOMBooleanProperty::kExpanded:
- return aria_expandedAttr;
- break;
- case AOMBooleanProperty::kHidden:
- return aria_hiddenAttr;
- break;
- case AOMBooleanProperty::kModal:
- return aria_modalAttr;
- break;
- case AOMBooleanProperty::kMultiline:
- return aria_multilineAttr;
- break;
- case AOMBooleanProperty::kMultiselectable:
- return aria_multiselectableAttr;
- break;
- case AOMBooleanProperty::kReadOnly:
- return aria_readonlyAttr;
- break;
- case AOMBooleanProperty::kRequired:
- return aria_requiredAttr;
- break;
- case AOMBooleanProperty::kSelected:
- return aria_selectedAttr;
- break;
- }
-
- NOTREACHED();
- return g_null_name;
-}
-
-QualifiedName GetCorrespondingARIAAttribute(AOMFloatProperty property) {
- AtomicString attr_value;
- switch (property) {
- case AOMFloatProperty::kValueMax:
- return aria_valuemaxAttr;
- break;
- case AOMFloatProperty::kValueMin:
- return aria_valueminAttr;
- break;
- case AOMFloatProperty::kValueNow:
- return aria_valuenowAttr;
- break;
- }
-
- NOTREACHED();
- return g_null_name;
-}
-
-QualifiedName GetCorrespondingARIAAttribute(AOMUIntProperty property) {
- switch (property) {
- case AOMUIntProperty::kColIndex:
- return aria_colindexAttr;
- break;
- case AOMUIntProperty::kColSpan:
- return aria_colspanAttr;
- break;
- case AOMUIntProperty::kLevel:
- return aria_levelAttr;
- break;
- case AOMUIntProperty::kPosInSet:
- return aria_posinsetAttr;
- break;
- case AOMUIntProperty::kRowIndex:
- return aria_rowindexAttr;
- break;
- case AOMUIntProperty::kRowSpan:
- return aria_rowspanAttr;
- break;
- }
-
- NOTREACHED();
- return g_null_name;
-}
-
-QualifiedName GetCorrespondingARIAAttribute(AOMIntProperty property) {
- switch (property) {
- case AOMIntProperty::kColCount:
- return aria_colcountAttr;
- break;
- case AOMIntProperty::kRowCount:
- return aria_rowcountAttr;
- break;
- case AOMIntProperty::kSetSize:
- return aria_setsizeAttr;
- break;
- }
-
- NOTREACHED();
- return g_null_name;
-}
-
-} // namespace
-
-AccessibleNode::AccessibleNode(Element* element)
- : element_(element), document_(nullptr) {
- DCHECK(RuntimeEnabledFeatures::AccessibilityObjectModelEnabled());
-}
-
-AccessibleNode::AccessibleNode(Document& document)
- : element_(nullptr), document_(document) {
- DCHECK(RuntimeEnabledFeatures::AccessibilityObjectModelEnabled());
-}
-
-AccessibleNode::~AccessibleNode() = default;
-
-// static
-AccessibleNode* AccessibleNode::Create(Document& document) {
- return new AccessibleNode(document);
-}
-
-Document* AccessibleNode::GetDocument() const {
- if (document_)
- return document_;
- if (element_)
- return &element_->GetDocument();
-
- NOTREACHED();
- return nullptr;
-}
-
-const AtomicString& AccessibleNode::GetProperty(
- AOMStringProperty property) const {
- for (const auto& item : string_properties_) {
- if (item.first == property && !item.second.IsNull())
- return item.second;
- }
-
- return g_null_atom;
-}
-
-// static
-AccessibleNode* AccessibleNode::GetProperty(Element* element,
- AOMRelationProperty property) {
- if (!element)
- return nullptr;
-
- if (AccessibleNode* accessible_node = element->ExistingAccessibleNode()) {
- for (const auto& item : accessible_node->relation_properties_) {
- if (item.first == property && item.second)
- return item.second;
- }
- }
-
- return nullptr;
-}
-
-// static
-AccessibleNodeList* AccessibleNode::GetProperty(
- Element* element,
- AOMRelationListProperty property) {
- if (!element)
- return nullptr;
-
- if (AccessibleNode* accessible_node = element->ExistingAccessibleNode()) {
- for (const auto& item : accessible_node->relation_list_properties_) {
- if (item.first == property && item.second)
- return item.second;
- }
- }
-
- return nullptr;
-}
-
-// static
-bool AccessibleNode::GetProperty(Element* element,
- AOMRelationListProperty property,
- HeapVector<Member<Element>>& targets) {
- AccessibleNodeList* node_list = GetProperty(element, property);
- if (!node_list)
- return false;
-
- for (size_t i = 0; i < node_list->length(); ++i) {
- AccessibleNode* accessible_node = node_list->item(i);
- if (accessible_node) {
- Element* element = accessible_node->element();
- if (element)
- targets.push_back(element);
- }
- }
-
- return true;
-}
-
-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;
-}
-
-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");
-}
-
-// static
-const AtomicString& AccessibleNode::GetPropertyOrARIAAttribute(
- Element* element,
- AOMStringProperty property) {
- if (!element)
- return g_null_atom;
-
- const bool is_token_attr = IsStringTokenProperty(property);
- AccessibleNode* accessible_node = element->ExistingAccessibleNode();
- if (accessible_node) {
- const AtomicString& result = accessible_node->GetProperty(property);
- if (!result.IsNull()) {
- if (is_token_attr && IsUndefinedAttrValue(result))
- return g_null_atom; // Property specifically set to undefined value.
- return result;
- }
- }
-
- // Fall back on the equivalent ARIA attribute.
- QualifiedName attribute = GetCorrespondingARIAAttribute(property);
- const AtomicString& attr_value = element->FastGetAttribute(attribute);
- if (is_token_attr && IsUndefinedAttrValue(attr_value))
- return g_null_atom; // Attribute not set or explicitly undefined.
-
- return attr_value;
-}
-
-// static
-Element* AccessibleNode::GetPropertyOrARIAAttribute(
- Element* element,
- AOMRelationProperty property) {
- if (!element)
- return nullptr;
-
- if (AccessibleNode* result = GetProperty(element, property))
- return result->element();
-
- // Fall back on the equivalent ARIA attribute.
- QualifiedName attribute = GetCorrespondingARIAAttribute(property);
- AtomicString value = element->FastGetAttribute(attribute);
- return element->GetTreeScope().getElementById(value);
-}
-
-// static
-bool AccessibleNode::GetPropertyOrARIAAttribute(
- Element* element,
- AOMRelationListProperty property,
- HeapVector<Member<Element>>& targets) {
- if (!element)
- return false;
-
- if (GetProperty(element, property, targets))
- return true;
-
- // Fall back on the equivalent ARIA attribute.
- QualifiedName attribute = GetCorrespondingARIAAttribute(property);
- String value = element->FastGetAttribute(attribute).GetString();
- if (value.IsEmpty() && property == AOMRelationListProperty::kLabeledBy)
- value = element->FastGetAttribute(aria_labeledbyAttr).GetString();
- if (value.IsEmpty())
- return false;
-
- value.SimplifyWhiteSpace();
- Vector<String> ids;
- value.Split(' ', ids);
- if (ids.IsEmpty())
- return false;
-
- TreeScope& scope = element->GetTreeScope();
- for (const auto& id : ids) {
- if (Element* id_element = scope.getElementById(AtomicString(id)))
- targets.push_back(id_element);
- }
- return true;
-}
-
-// static
-bool AccessibleNode::GetPropertyOrARIAAttribute(Element* element,
- AOMBooleanProperty property,
- bool& is_null) {
- is_null = true;
- if (!element)
- return false;
-
- AccessibleNode* accessible_node = element->ExistingAccessibleNode();
- if (accessible_node) {
- bool result = accessible_node->GetProperty(property, is_null);
- if (!is_null)
- return result;
- }
-
- // Fall back on the equivalent ARIA attribute.
- QualifiedName attribute = GetCorrespondingARIAAttribute(property);
- AtomicString attr_value = element->FastGetAttribute(attribute);
- is_null = IsUndefinedAttrValue(attr_value);
- return !is_null && !EqualIgnoringASCIICase(attr_value, "false");
-}
-
-// static
-float AccessibleNode::GetPropertyOrARIAAttribute(Element* element,
- AOMFloatProperty property,
- bool& is_null) {
- is_null = true;
- if (!element)
- return 0.0;
-
- float result = GetProperty(element, property, is_null);
- if (!is_null)
- return result;
-
- // Fall back on the equivalent ARIA attribute.
- QualifiedName attribute = GetCorrespondingARIAAttribute(property);
- AtomicString attr_value = element->FastGetAttribute(attribute);
- is_null = attr_value.IsNull();
- return attr_value.ToFloat();
-}
-
-// static
-uint32_t AccessibleNode::GetPropertyOrARIAAttribute(Element* element,
- AOMUIntProperty property,
- bool& is_null) {
- is_null = true;
- if (!element)
- return 0;
-
- int32_t result = GetProperty(element, property, is_null);
- if (!is_null)
- return result;
-
- // Fall back on the equivalent ARIA attribute.
- QualifiedName attribute = GetCorrespondingARIAAttribute(property);
- AtomicString attr_value = element->FastGetAttribute(attribute);
- is_null = attr_value.IsNull();
- return attr_value.GetString().ToUInt();
-}
-
-// static
-int32_t AccessibleNode::GetPropertyOrARIAAttribute(Element* element,
- AOMIntProperty property,
- bool& is_null) {
- is_null = true;
- if (!element)
- return 0;
-
- int32_t result = GetProperty(element, property, is_null);
- if (!is_null)
- return result;
-
- // Fall back on the equivalent ARIA attribute.
- QualifiedName attribute = GetCorrespondingARIAAttribute(property);
- AtomicString attr_value = element->FastGetAttribute(attribute);
- is_null = attr_value.IsNull();
- return attr_value.ToInt();
-}
-
-void AccessibleNode::GetAllAOMProperties(
- AOMPropertyClient* client,
- HashSet<QualifiedName>& shadowed_aria_attributes) {
- for (auto& item : string_properties_) {
- client->AddStringProperty(item.first, item.second);
- shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first));
- }
- for (auto& item : boolean_properties_) {
- client->AddBooleanProperty(item.first, item.second);
- shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first));
- }
- for (auto& item : float_properties_) {
- client->AddFloatProperty(item.first, item.second);
- shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first));
- }
- for (auto& item : int_properties_) {
- client->AddIntProperty(item.first, item.second);
- shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first));
- }
- for (auto& item : uint_properties_) {
- client->AddUIntProperty(item.first, item.second);
- shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first));
- }
- for (auto& item : relation_properties_) {
- if (!item.second)
- continue;
- client->AddRelationProperty(item.first, *item.second);
- shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first));
- }
- for (auto& item : relation_list_properties_) {
- if (!item.second)
- continue;
- client->AddRelationListProperty(item.first, *item.second);
- shadowed_aria_attributes.insert(GetCorrespondingARIAAttribute(item.first));
- }
-}
-
-AccessibleNode* AccessibleNode::activeDescendant() const {
- return GetProperty(element_, AOMRelationProperty::kActiveDescendant);
-}
-
-void AccessibleNode::setActiveDescendant(AccessibleNode* active_descendant) {
- SetRelationProperty(AOMRelationProperty::kActiveDescendant,
- active_descendant);
- NotifyAttributeChanged(aria_activedescendantAttr);
-}
-
-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(aria_atomicAttr);
-}
-
-AtomicString AccessibleNode::autocomplete() const {
- return GetProperty(AOMStringProperty::kAutocomplete);
-}
-
-void AccessibleNode::setAutocomplete(const AtomicString& autocomplete) {
- SetStringProperty(AOMStringProperty::kAutocomplete, autocomplete);
- NotifyAttributeChanged(aria_autocompleteAttr);
-}
-
-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(aria_busyAttr);
-}
-
-AtomicString AccessibleNode::checked() const {
- return GetProperty(AOMStringProperty::kChecked);
-}
-
-void AccessibleNode::setChecked(const AtomicString& checked) {
- SetStringProperty(AOMStringProperty::kChecked, checked);
- NotifyAttributeChanged(aria_checkedAttr);
-}
-
-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(aria_colcountAttr);
-}
-
-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(aria_colindexAttr);
-}
-
-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(aria_colspanAttr);
-}
-
-AccessibleNodeList* AccessibleNode::controls() const {
- return GetProperty(element_, AOMRelationListProperty::kControls);
-}
-
-void AccessibleNode::setControls(AccessibleNodeList* controls) {
- SetRelationListProperty(AOMRelationListProperty::kControls, controls);
- NotifyAttributeChanged(aria_controlsAttr);
-}
-
-AtomicString AccessibleNode::current() const {
- return GetProperty(AOMStringProperty::kCurrent);
-}
-
-void AccessibleNode::setCurrent(const AtomicString& current) {
- SetStringProperty(AOMStringProperty::kCurrent, current);
-
- if (AXObjectCache* cache = GetAXObjectCache())
- cache->HandleAttributeChanged(aria_currentAttr, element_);
-}
-
-AccessibleNodeList* AccessibleNode::describedBy() {
- return GetProperty(element_, AOMRelationListProperty::kDescribedBy);
-}
-
-void AccessibleNode::setDescribedBy(AccessibleNodeList* described_by) {
- SetRelationListProperty(AOMRelationListProperty::kDescribedBy, described_by);
- NotifyAttributeChanged(aria_describedbyAttr);
-}
-
-AccessibleNode* AccessibleNode::details() const {
- return GetProperty(element_, AOMRelationProperty::kDetails);
-}
-
-void AccessibleNode::setDetails(AccessibleNode* details) {
- SetRelationProperty(AOMRelationProperty::kDetails, details);
- NotifyAttributeChanged(aria_detailsAttr);
-}
-
-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(aria_disabledAttr);
-}
-
-AccessibleNode* AccessibleNode::errorMessage() const {
- return GetProperty(element_, AOMRelationProperty::kErrorMessage);
-}
-
-void AccessibleNode::setErrorMessage(AccessibleNode* error_message) {
- SetRelationProperty(AOMRelationProperty::kErrorMessage, error_message);
- NotifyAttributeChanged(aria_errormessageAttr);
-}
-
-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(aria_expandedAttr);
-}
-
-AccessibleNodeList* AccessibleNode::flowTo() const {
- return GetProperty(element_, AOMRelationListProperty::kFlowTo);
-}
-
-void AccessibleNode::setFlowTo(AccessibleNodeList* flow_to) {
- SetRelationListProperty(AOMRelationListProperty::kFlowTo, flow_to);
- NotifyAttributeChanged(aria_flowtoAttr);
-}
-
-AtomicString AccessibleNode::hasPopUp() const {
- return GetProperty(AOMStringProperty::kHasPopUp);
-}
-
-void AccessibleNode::setHasPopUp(const AtomicString& has_popup) {
- SetStringProperty(AOMStringProperty::kHasPopUp, has_popup);
- NotifyAttributeChanged(aria_haspopupAttr);
-}
-
-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(aria_hiddenAttr);
-}
-
-AtomicString AccessibleNode::invalid() const {
- return GetProperty(AOMStringProperty::kInvalid);
-}
-
-void AccessibleNode::setInvalid(const AtomicString& invalid) {
- SetStringProperty(AOMStringProperty::kInvalid, invalid);
- NotifyAttributeChanged(aria_invalidAttr);
-}
-
-AtomicString AccessibleNode::keyShortcuts() const {
- return GetProperty(AOMStringProperty::kKeyShortcuts);
-}
-
-void AccessibleNode::setKeyShortcuts(const AtomicString& key_shortcuts) {
- SetStringProperty(AOMStringProperty::kKeyShortcuts, key_shortcuts);
- NotifyAttributeChanged(aria_keyshortcutsAttr);
-}
-
-AtomicString AccessibleNode::label() const {
- return GetProperty(AOMStringProperty::kLabel);
-}
-
-void AccessibleNode::setLabel(const AtomicString& label) {
- SetStringProperty(AOMStringProperty::kLabel, label);
- NotifyAttributeChanged(aria_labelAttr);
-}
-
-AccessibleNodeList* AccessibleNode::labeledBy() {
- return GetProperty(element_, AOMRelationListProperty::kLabeledBy);
-}
-
-void AccessibleNode::setLabeledBy(AccessibleNodeList* labeled_by) {
- SetRelationListProperty(AOMRelationListProperty::kLabeledBy, labeled_by);
- NotifyAttributeChanged(aria_labelledbyAttr);
-}
-
-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(aria_levelAttr);
-}
-
-AtomicString AccessibleNode::live() const {
- return GetProperty(AOMStringProperty::kLive);
-}
-
-void AccessibleNode::setLive(const AtomicString& live) {
- SetStringProperty(AOMStringProperty::kLive, live);
- NotifyAttributeChanged(aria_liveAttr);
-}
-
-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(aria_modalAttr);
-}
-
-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(aria_multilineAttr);
-}
-
-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(aria_multiselectableAttr);
-}
-
-AtomicString AccessibleNode::orientation() const {
- return GetProperty(AOMStringProperty::kOrientation);
-}
-
-void AccessibleNode::setOrientation(const AtomicString& orientation) {
- SetStringProperty(AOMStringProperty::kOrientation, orientation);
- NotifyAttributeChanged(aria_orientationAttr);
-}
-
-AccessibleNodeList* AccessibleNode::owns() const {
- return GetProperty(element_, AOMRelationListProperty::kOwns);
-}
-
-void AccessibleNode::setOwns(AccessibleNodeList* owns) {
- SetRelationListProperty(AOMRelationListProperty::kOwns, owns);
- NotifyAttributeChanged(aria_ownsAttr);
-}
-
-AtomicString AccessibleNode::placeholder() const {
- return GetProperty(AOMStringProperty::kPlaceholder);
-}
-
-void AccessibleNode::setPlaceholder(const AtomicString& placeholder) {
- SetStringProperty(AOMStringProperty::kPlaceholder, placeholder);
- NotifyAttributeChanged(aria_placeholderAttr);
-}
-
-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(aria_posinsetAttr);
-}
-
-AtomicString AccessibleNode::pressed() const {
- return GetProperty(AOMStringProperty::kPressed);
-}
-
-void AccessibleNode::setPressed(const AtomicString& pressed) {
- SetStringProperty(AOMStringProperty::kPressed, pressed);
- NotifyAttributeChanged(aria_pressedAttr);
-}
-
-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(aria_readonlyAttr);
-}
-
-AtomicString AccessibleNode::relevant() const {
- return GetProperty(AOMStringProperty::kRelevant);
-}
-
-void AccessibleNode::setRelevant(const AtomicString& relevant) {
- SetStringProperty(AOMStringProperty::kRelevant, relevant);
- NotifyAttributeChanged(aria_relevantAttr);
-}
-
-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(aria_requiredAttr);
-}
-
-AtomicString AccessibleNode::role() const {
- return GetProperty(AOMStringProperty::kRole);
-}
-
-void AccessibleNode::setRole(const AtomicString& role) {
- SetStringProperty(AOMStringProperty::kRole, role);
- NotifyAttributeChanged(roleAttr);
-}
-
-AtomicString AccessibleNode::roleDescription() const {
- return GetProperty(AOMStringProperty::kRoleDescription);
-}
-
-void AccessibleNode::setRoleDescription(const AtomicString& role_description) {
- SetStringProperty(AOMStringProperty::kRoleDescription, role_description);
- NotifyAttributeChanged(aria_roledescriptionAttr);
-}
-
-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(aria_rowcountAttr);
-}
-
-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(aria_rowindexAttr);
-}
-
-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(aria_rowspanAttr);
-}
-
-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(aria_selectedAttr);
-}
-
-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(aria_setsizeAttr);
-}
-
-AtomicString AccessibleNode::sort() const {
- return GetProperty(AOMStringProperty::kSort);
-}
-
-void AccessibleNode::setSort(const AtomicString& sort) {
- SetStringProperty(AOMStringProperty::kSort, sort);
- NotifyAttributeChanged(aria_sortAttr);
-}
-
-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(aria_valuemaxAttr);
-}
-
-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(aria_valueminAttr);
-}
-
-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(aria_valuenowAttr);
-}
-
-AtomicString AccessibleNode::valueText() const {
- return GetProperty(AOMStringProperty::kValueText);
-}
-
-void AccessibleNode::setValueText(const AtomicString& value_text) {
- SetStringProperty(AOMStringProperty::kValueText, value_text);
- NotifyAttributeChanged(aria_valuetextAttr);
-}
-
-AccessibleNodeList* AccessibleNode::childNodes() {
- return AccessibleNodeList::Create(children_);
-}
-
-void AccessibleNode::appendChild(AccessibleNode* child,
- ExceptionState& exception_state) {
- if (child->element()) {
- exception_state.ThrowDOMException(
- kInvalidAccessError,
- "An AccessibleNode associated with an Element cannot be a child.");
- return;
- }
-
- if (child->parent_) {
- exception_state.ThrowDOMException(kNotSupportedError,
- "Reparenting is not supported yet.");
- return;
- }
- child->parent_ = this;
-
- if (!GetDocument()->GetSecurityOrigin()->CanAccess(
- child->GetDocument()->GetSecurityOrigin())) {
- exception_state.ThrowDOMException(
- kInvalidAccessError,
- "Trying to access an AccessibleNode from a different origin.");
- return;
- }
-
- children_.push_back(child);
- if (AXObjectCache* cache = GetAXObjectCache())
- cache->ChildrenChanged(this);
-}
-
-void AccessibleNode::removeChild(AccessibleNode* old_child,
- ExceptionState& exception_state) {
- if (old_child->parent_ != this) {
- exception_state.ThrowDOMException(
- kInvalidAccessError, "Node to remove is not a child of this node.");
- return;
- }
- auto* ix = std::find_if(children_.begin(), children_.end(),
- [old_child](const Member<AccessibleNode> child) {
- return child.Get() == old_child;
- });
- if (ix == children_.end()) {
- exception_state.ThrowDOMException(
- kInvalidAccessError, "Node to remove is not a child of this node.");
- return;
- }
- old_child->parent_ = nullptr;
- children_.erase(ix);
-
- if (AXObjectCache* cache = GetAXObjectCache())
- cache->ChildrenChanged(this);
-}
-
-// These properties support a list of tokens, and "undefined"/"" is
-// equivalent to not setting the attribute.
-bool AccessibleNode::IsStringTokenProperty(AOMStringProperty property) {
- switch (property) {
- case AOMStringProperty::kAutocomplete:
- case AOMStringProperty::kChecked:
- case AOMStringProperty::kCurrent:
- case AOMStringProperty::kHasPopUp:
- case AOMStringProperty::kInvalid:
- case AOMStringProperty::kLive:
- case AOMStringProperty::kOrientation:
- case AOMStringProperty::kPressed:
- case AOMStringProperty::kRelevant:
- case AOMStringProperty::kSort:
- return true;
- case AOMStringProperty::kKeyShortcuts:
- case AOMStringProperty::kLabel:
- case AOMStringProperty::kPlaceholder:
- case AOMStringProperty::kRole: // Is token, but ""/"undefined" not
- // supported.
- case AOMStringProperty::kRoleDescription:
- case AOMStringProperty::kValueText:
- break;
- }
- return false;
-}
-
-const AtomicString& AccessibleNode::InterfaceName() const {
- return EventTargetNames::AccessibleNode;
-}
-
-ExecutionContext* AccessibleNode::GetExecutionContext() const {
- if (element_)
- return element_->GetExecutionContext();
-
- if (parent_)
- return parent_->GetExecutionContext();
-
- return nullptr;
-}
-
-void AccessibleNode::SetStringProperty(AOMStringProperty property,
- const AtomicString& value) {
- for (auto& item : string_properties_) {
- if (item.first == property) {
- item.second = value;
- return;
- }
- }
-
- string_properties_.push_back(std::make_pair(property, value));
-}
-
-void AccessibleNode::SetRelationProperty(AOMRelationProperty property,
- AccessibleNode* value) {
- for (auto& item : relation_properties_) {
- if (item.first == property) {
- item.second = value;
- return;
- }
- }
-
- relation_properties_.push_back(std::make_pair(property, value));
-}
-
-void AccessibleNode::SetRelationListProperty(AOMRelationListProperty property,
- AccessibleNodeList* value) {
- for (auto& item : relation_list_properties_) {
- if (item.first == property) {
- if (item.second)
- item.second->RemoveOwner(property, this);
- if (value)
- value->AddOwner(property, this);
- item.second = value;
- return;
- }
- }
-
- relation_list_properties_.push_back(std::make_pair(property, value));
-}
-
-template <typename P, typename T>
-static void SetProperty(P property,
- T value,
- bool is_null,
- Vector<std::pair<P, T>>& properties) {
- for (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));
-}
-
-void AccessibleNode::NotifyAttributeChanged(
- const blink::QualifiedName& attribute) {
- // TODO(dmazzoni): Make a cleaner API for this rather than pretending
- // the DOM attribute changed.
- if (AXObjectCache* cache = GetAXObjectCache())
- cache->HandleAttributeChanged(attribute, element_);
-}
-
-AXObjectCache* AccessibleNode::GetAXObjectCache() {
- return GetDocument()->ExistingAXObjectCache();
-}
-
-void AccessibleNode::Trace(blink::Visitor* visitor) {
- visitor->Trace(element_);
- visitor->Trace(document_);
- visitor->Trace(relation_properties_);
- visitor->Trace(relation_list_properties_);
- visitor->Trace(children_);
- visitor->Trace(parent_);
- EventTargetWithInlineData::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/accessible_node.h b/chromium/third_party/blink/renderer/core/dom/accessible_node.h
deleted file mode 100644
index 15ca54f950d..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/accessible_node.h
+++ /dev/null
@@ -1,402 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ACCESSIBLE_NODE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ACCESSIBLE_NODE_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/events/event_target.h"
-#include "third_party/blink/renderer/core/dom/qualified_name.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.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/atomic_string.h"
-#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
-
-namespace blink {
-
-class AccessibleNodeList;
-class AXObjectCache;
-class Document;
-class Element;
-class QualifiedName;
-
-// All of the properties of AccessibleNode that have type "string".
-enum class AOMStringProperty {
- kAutocomplete,
- kChecked,
- kCurrent,
- kHasPopUp,
- kInvalid,
- kKeyShortcuts,
- kLabel,
- kLive,
- kOrientation,
- kPlaceholder,
- kPressed,
- kRelevant,
- kRole,
- kRoleDescription,
- kSort,
- kValueText
-};
-
-// All of the properties of AccessibleNode that have type "boolean".
-enum class AOMBooleanProperty {
- kAtomic,
- kBusy,
- kDisabled,
- kExpanded,
- kHidden,
- kModal,
- kMultiline,
- kMultiselectable,
- kReadOnly,
- kRequired,
- kSelected
-};
-
-// All of the properties of AccessibleNode that have an unsigned integer type.
-enum class AOMUIntProperty {
- kColIndex,
- kColSpan,
- kLevel,
- kPosInSet,
- kRowIndex,
- kRowSpan,
-};
-
-enum class AOMRelationProperty {
- kActiveDescendant,
- kDetails,
- kErrorMessage,
-};
-
-enum class AOMRelationListProperty {
- kDescribedBy,
- kControls,
- kFlowTo,
- kLabeledBy,
- kOwns,
-};
-
-// All of the properties of AccessibleNode that have a signed integer type.
-// (These all allow the value -1.)
-enum class AOMIntProperty { kColCount, kRowCount, kSetSize };
-
-// All of the properties of AccessibleNode that have a floating-point type.
-enum class AOMFloatProperty { kValueMax, kValueMin, kValueNow };
-
-class AccessibleNode;
-
-class CORE_EXPORT AOMPropertyClient {
- public:
- virtual void AddStringProperty(AOMStringProperty, const String&) = 0;
- virtual void AddBooleanProperty(AOMBooleanProperty, bool) = 0;
- virtual void AddIntProperty(AOMIntProperty, int32_t) = 0;
- virtual void AddUIntProperty(AOMUIntProperty, uint32_t) = 0;
- virtual void AddFloatProperty(AOMFloatProperty, float) = 0;
- virtual void AddRelationProperty(AOMRelationProperty,
- const AccessibleNode&) = 0;
- virtual void AddRelationListProperty(AOMRelationListProperty,
- const AccessibleNodeList&) = 0;
-};
-
-// Accessibility Object Model node
-// Explainer: https://github.com/WICG/aom/blob/master/explainer.md
-// Spec: https://wicg.github.io/aom/spec/
-class CORE_EXPORT AccessibleNode : public EventTargetWithInlineData {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- explicit AccessibleNode(Document&);
- explicit AccessibleNode(Element*);
- ~AccessibleNode() override;
-
- static AccessibleNode* Create(Document&);
-
- // Gets the associated element, if any.
- Element* element() const { return element_; }
-
- // Gets the associated document.
- Document* GetDocument() const;
-
- // Children. These are only virtual AccessibleNodes that were added
- // explicitly, never AccessibleNodes from DOM Elements.
- HeapVector<Member<AccessibleNode>> GetChildren() { return children_; }
-
- // Returns the given string property.
- const AtomicString& GetProperty(AOMStringProperty) const;
-
- // Returns the given relation property if the Element has an AccessibleNode.
- static AccessibleNode* GetProperty(Element*, AOMRelationProperty);
-
- // Returns the given relation list property if the Element has an
- // AccessibleNode.
- static AccessibleNodeList* GetProperty(Element*, AOMRelationListProperty);
- static bool GetProperty(Element*,
- AOMRelationListProperty,
- HeapVector<Member<Element>>&);
-
- // Returns the given boolean property.
- bool GetProperty(AOMBooleanProperty, bool& is_null) const;
-
- // Returns the value of the given property if the
- // Element has an AccessibleNode. Sets |isNull| if the property and
- // attribute are not present.
- 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?
- // These include the empty string ("") or "undefined" as a literal.
- // See ARIA 1.1 Sections 6.2 and 6.3, as well as properties that specifically
- // indicate a supported value of "undefined".
- static bool IsUndefinedAttrValue(const AtomicString&);
-
- // Returns the value of the given string property if the
- // Element has an AccessibleNode, otherwise returns the equivalent
- // ARIA attribute.
- static const AtomicString& GetPropertyOrARIAAttribute(Element*,
- AOMStringProperty);
-
- // Returns the given relation property if the Element has an AccessibleNode,
- // otherwise returns the equivalent ARIA attribute.
- static Element* GetPropertyOrARIAAttribute(Element*, AOMRelationProperty);
-
- // Returns true and provides the the value of the given relation
- // list property if the Element has an AccessibleNode, or if it has
- // the equivalent ARIA attribute. Otherwise returns false.
- static bool GetPropertyOrARIAAttribute(Element*,
- AOMRelationListProperty,
- HeapVector<Member<Element>>&);
-
- // Returns the value of the given property if the
- // Element has an AccessibleNode, otherwise returns the equivalent
- // ARIA attribute. Sets |isNull| if the property and attribute are not
- // present.
- static bool GetPropertyOrARIAAttribute(Element*,
- AOMBooleanProperty,
- bool& is_null);
- static float GetPropertyOrARIAAttribute(Element*,
- AOMFloatProperty,
- bool& is_null);
- static int32_t GetPropertyOrARIAAttribute(Element*,
- AOMIntProperty,
- bool& is_null);
- static uint32_t GetPropertyOrARIAAttribute(Element*,
- AOMUIntProperty,
- bool& is_null);
-
- // Iterates over all AOM properties. For each one, calls AOMPropertyClient
- // with the value of the AOM property if set. Updates
- // |shadowed_aria_attributes| to contain a list of the ARIA attributes that
- // would be shadowed by these AOM properties.
- void GetAllAOMProperties(AOMPropertyClient*,
- HashSet<QualifiedName>& shadowed_aria_attributes);
-
- AccessibleNode* activeDescendant() const;
- void setActiveDescendant(AccessibleNode*);
-
- bool atomic(bool& is_null) const;
- void setAtomic(bool, bool is_null);
-
- AtomicString autocomplete() const;
- void setAutocomplete(const AtomicString&);
-
- bool busy(bool& is_null) const;
- void setBusy(bool, bool is_null);
-
- AtomicString checked() const;
- void setChecked(const AtomicString&);
-
- int32_t colCount(bool& is_null) const;
- void setColCount(int32_t, bool is_null);
-
- uint32_t colIndex(bool& is_null) const;
- void setColIndex(uint32_t, bool is_null);
-
- uint32_t colSpan(bool& is_null) const;
- void setColSpan(uint32_t, bool is_null);
-
- AccessibleNodeList* controls() const;
- void setControls(AccessibleNodeList*);
-
- AtomicString current() const;
- void setCurrent(const AtomicString&);
-
- AccessibleNodeList* describedBy();
- void setDescribedBy(AccessibleNodeList*);
-
- AccessibleNode* details() const;
- void setDetails(AccessibleNode*);
-
- bool disabled(bool& is_null) const;
- void setDisabled(bool, bool is_null);
-
- AccessibleNode* errorMessage() const;
- void setErrorMessage(AccessibleNode*);
-
- bool expanded(bool& is_null) const;
- void setExpanded(bool, bool is_null);
-
- AccessibleNodeList* flowTo() const;
- void setFlowTo(AccessibleNodeList*);
-
- AtomicString hasPopUp() const;
- void setHasPopUp(const AtomicString&);
-
- bool hidden(bool& is_null) const;
- void setHidden(bool, bool is_null);
-
- AtomicString invalid() const;
- void setInvalid(const AtomicString&);
-
- AtomicString keyShortcuts() const;
- void setKeyShortcuts(const AtomicString&);
-
- AtomicString label() const;
- void setLabel(const AtomicString&);
-
- AccessibleNodeList* labeledBy();
- void setLabeledBy(AccessibleNodeList*);
-
- uint32_t level(bool& is_null) const;
- void setLevel(uint32_t, bool is_null);
-
- AtomicString live() const;
- void setLive(const AtomicString&);
-
- bool modal(bool& is_null) const;
- void setModal(bool, bool is_null);
-
- bool multiline(bool& is_null) const;
- void setMultiline(bool, bool is_null);
-
- bool multiselectable(bool& is_null) const;
- void setMultiselectable(bool, bool is_null);
-
- AtomicString orientation() const;
- void setOrientation(const AtomicString&);
-
- AccessibleNodeList* owns() const;
- void setOwns(AccessibleNodeList*);
-
- AtomicString placeholder() const;
- void setPlaceholder(const AtomicString&);
-
- uint32_t posInSet(bool& is_null) const;
- void setPosInSet(uint32_t, bool is_null);
-
- AtomicString pressed() const;
- void setPressed(const AtomicString&);
-
- bool readOnly(bool& is_null) const;
- void setReadOnly(bool, bool is_null);
-
- AtomicString relevant() const;
- void setRelevant(const AtomicString&);
-
- bool required(bool& is_null) const;
- void setRequired(bool, bool is_null);
-
- AtomicString role() const;
- void setRole(const AtomicString&);
-
- AtomicString roleDescription() const;
- void setRoleDescription(const AtomicString&);
-
- int32_t rowCount(bool& is_null) const;
- void setRowCount(int32_t, bool is_null);
-
- uint32_t rowIndex(bool& is_null) const;
- void setRowIndex(uint32_t, bool is_null);
-
- uint32_t rowSpan(bool& is_null) const;
- void setRowSpan(uint32_t, bool is_null);
-
- bool selected(bool& is_null) const;
- void setSelected(bool, bool is_null);
-
- int32_t setSize(bool& is_null) const;
- void setSetSize(int32_t, bool is_null);
-
- AtomicString sort() const;
- void setSort(const AtomicString&);
-
- float valueMax(bool& is_null) const;
- void setValueMax(float, bool is_null);
-
- float valueMin(bool& is_null) const;
- void setValueMin(float, bool is_null);
-
- float valueNow(bool& is_null) const;
- void setValueNow(float, bool is_null);
-
- AtomicString valueText() const;
- void setValueText(const AtomicString&);
-
- AccessibleNodeList* childNodes();
-
- void appendChild(AccessibleNode*, ExceptionState&);
- void removeChild(AccessibleNode*, ExceptionState&);
-
- // EventTarget
- const AtomicString& InterfaceName() const override;
- ExecutionContext* GetExecutionContext() const override;
-
- DEFINE_ATTRIBUTE_EVENT_LISTENER(accessibleclick);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(accessiblecontextmenu);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(accessibledecrement);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(accessiblefocus);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(accessibleincrement);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(accessiblescrollintoview);
-
- void Trace(blink::Visitor*) override;
-
- protected:
- friend class AccessibleNodeList;
- void OnRelationListChanged(AOMRelationListProperty);
-
- private:
- static bool IsStringTokenProperty(AOMStringProperty);
- void SetStringProperty(AOMStringProperty, const AtomicString&);
- void SetRelationProperty(AOMRelationProperty, AccessibleNode*);
- void SetRelationListProperty(AOMRelationListProperty, AccessibleNodeList*);
- void SetBooleanProperty(AOMBooleanProperty, bool value, bool is_null);
- void SetFloatProperty(AOMFloatProperty, float value, bool is_null);
- void SetUIntProperty(AOMUIntProperty, uint32_t value, bool is_null);
- void SetIntProperty(AOMIntProperty, int32_t value, bool is_null);
- void NotifyAttributeChanged(const blink::QualifiedName&);
- AXObjectCache* GetAXObjectCache();
-
- Vector<std::pair<AOMStringProperty, AtomicString>> string_properties_;
- Vector<std::pair<AOMBooleanProperty, bool>> boolean_properties_;
- Vector<std::pair<AOMFloatProperty, float>> float_properties_;
- Vector<std::pair<AOMIntProperty, int32_t>> int_properties_;
- Vector<std::pair<AOMUIntProperty, uint32_t>> uint_properties_;
- HeapVector<std::pair<AOMRelationProperty, Member<AccessibleNode>>>
- relation_properties_;
- HeapVector<std::pair<AOMRelationListProperty, Member<AccessibleNodeList>>>
- relation_list_properties_;
-
- // This object's owner Element, if it corresponds to an Element.
- Member<Element> element_;
-
- // The object's owner Document. Only set if |element_| is nullptr.
- Member<Document> document_;
-
- // This object's AccessibleNode children, which must be only virtual
- // AccessibleNodes (with no associated Element).
- HeapVector<Member<AccessibleNode>> children_;
-
- // This object's AccessibleNode parent. Only set if this is a
- // virtual AccessibleNode that's in the tree.
- Member<AccessibleNode> parent_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ACCESSIBLE_NODE_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/accessible_node_list.cc b/chromium/third_party/blink/renderer/core/dom/accessible_node_list.cc
deleted file mode 100644
index 15f116bb0a2..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/accessible_node_list.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/dom/accessible_node_list.h"
-
-#include "third_party/blink/renderer/core/dom/accessible_node.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-
-namespace blink {
-
-// The spec doesn't give a limit, but there's no reason to allow relations
-// between an arbitrarily large number of other accessible nodes.
-static const unsigned kMaxItems = 65536;
-
-// static
-AccessibleNodeList* AccessibleNodeList::Create(
- const HeapVector<Member<AccessibleNode>>& nodes) {
- AccessibleNodeList* result = new AccessibleNodeList();
- result->nodes_ = nodes;
- return result;
-}
-
-AccessibleNodeList::AccessibleNodeList() {
- DCHECK(RuntimeEnabledFeatures::AccessibilityObjectModelEnabled());
-}
-
-AccessibleNodeList::~AccessibleNodeList() = default;
-
-void AccessibleNodeList::AddOwner(AOMRelationListProperty property,
- AccessibleNode* node) {
- owners_.push_back(std::make_pair(property, node));
-}
-
-void AccessibleNodeList::RemoveOwner(AOMRelationListProperty property,
- AccessibleNode* node) {
- for (size_t i = 0; i < owners_.size(); ++i) {
- auto& item = owners_[i];
- if (item.first == property && item.second == node) {
- owners_.EraseAt(i);
- return;
- }
- }
-}
-
-AccessibleNode* AccessibleNodeList::item(unsigned offset) const {
- if (offset < nodes_.size())
- return nodes_[offset];
- return nullptr;
-}
-
-void AccessibleNodeList::add(AccessibleNode* node, AccessibleNode* before) {
- if (nodes_.size() == kMaxItems)
- return;
-
- unsigned index = nodes_.size();
- if (before) {
- for (index = 0; index < nodes_.size(); ++index) {
- if (nodes_[index] == before)
- break;
- }
- if (index == nodes_.size())
- return;
- }
-
- nodes_.insert(index, node);
-}
-
-void AccessibleNodeList::remove(int index) {
- if (index >= 0 && index < static_cast<int>(nodes_.size()))
- nodes_.EraseAt(index);
-}
-
-bool AccessibleNodeList::AnonymousIndexedSetter(unsigned index,
- AccessibleNode* node,
- ExceptionState& state) {
- if (!node) {
- remove(index);
- return true;
- }
- if (index >= kMaxItems)
- return false;
- if (index >= nodes_.size()) {
- unsigned old_size = nodes_.size();
- nodes_.resize(index + 1);
- for (unsigned i = old_size; i < nodes_.size(); ++i)
- nodes_[i] = nullptr;
- }
- nodes_[index] = node;
- return true;
-}
-
-unsigned AccessibleNodeList::length() const {
- return nodes_.size();
-}
-
-void AccessibleNodeList::setLength(unsigned new_length) {
- if (new_length >= kMaxItems)
- return;
- nodes_.resize(new_length);
-}
-
-void AccessibleNodeList::NotifyChanged() {
- for (auto& owner : owners_)
- owner.second->OnRelationListChanged(owner.first);
-}
-
-void AccessibleNodeList::Trace(blink::Visitor* visitor) {
- visitor->Trace(nodes_);
- visitor->Trace(owners_);
- ScriptWrappable::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/accessible_node_list.h b/chromium/third_party/blink/renderer/core/dom/accessible_node_list.h
deleted file mode 100644
index c3695900f1c..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/accessible_node_list.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ACCESSIBLE_NODE_LIST_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ACCESSIBLE_NODE_LIST_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-
-namespace blink {
-
-class AccessibleNode;
-enum class AOMRelationListProperty;
-class ExceptionState;
-
-// Accessibility Object Model node list
-// Explainer: https://github.com/WICG/aom/blob/master/explainer.md
-// Spec: https://wicg.github.io/aom/spec/
-class CORE_EXPORT AccessibleNodeList : public ScriptWrappable {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- static AccessibleNodeList* Create(const HeapVector<Member<AccessibleNode>>&);
-
- AccessibleNodeList();
- ~AccessibleNodeList() override;
-
- void AddOwner(AOMRelationListProperty, AccessibleNode*);
- void RemoveOwner(AOMRelationListProperty, AccessibleNode*);
-
- AccessibleNode* item(unsigned offset) const;
- void add(AccessibleNode*, AccessibleNode* = nullptr);
- void remove(int index);
- bool AnonymousIndexedSetter(unsigned, AccessibleNode*, ExceptionState&);
- unsigned length() const;
- void setLength(unsigned);
-
- void Trace(blink::Visitor*) override;
-
- private:
- void NotifyChanged();
-
- HeapVector<std::pair<AOMRelationListProperty, Member<AccessibleNode>>>
- owners_;
- HeapVector<Member<AccessibleNode>> nodes_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_ACCESSIBLE_NODE_LIST_H_
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 b8aee48dc7e..199a90acffa 100644
--- a/chromium/third_party/blink/renderer/core/dom/aria_attributes.idl
+++ b/chromium/third_party/blink/renderer/core/dom/aria_attributes.idl
@@ -3,7 +3,7 @@
// found in the LICENSE file.
// ARIA reflection
-// https://github.com/w3c/aria/pull/708/files
+// https://w3c.github.io/aria/#idl-interface
[
NoInterfaceObject,
RuntimeEnabled=AccessibilityObjectModel
@@ -35,7 +35,8 @@
[CEReactions, Reflect=aria_owns] attribute DOMString? ariaOwns;
[CEReactions, Reflect=aria_placeholder] attribute DOMString? ariaPlaceholder;
[CEReactions, Reflect=aria_posinset] attribute DOMString? ariaPosInSet;
- [CEReactions, Reflect=aria_readonly] attribute DOMString? ariaPressed;
+ [CEReactions, Reflect=aria_pressed] attribute DOMString? ariaPressed;
+ [CEReactions, Reflect=aria_readonly] attribute DOMString? ariaReadOnly;
[CEReactions, Reflect=aria_relevant] attribute DOMString? ariaRelevant;
[CEReactions, Reflect=aria_required] attribute DOMString? ariaRequired;
[CEReactions, Reflect=aria_roledescription] attribute DOMString? ariaRoleDescription;
diff --git a/chromium/third_party/blink/renderer/core/dom/attr.cc b/chromium/third_party/blink/renderer/core/dom/attr.cc
index dde97c1dfb5..25afd5d818b 100644
--- a/chromium/third_party/blink/renderer/core/dom/attr.cc
+++ b/chromium/third_party/blink/renderer/core/dom/attr.cc
@@ -24,11 +24,11 @@
#include "third_party/blink/renderer/core/dom/attr.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/scoped_event_queue.h"
#include "third_party/blink/renderer/core/dom/text.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -117,9 +117,4 @@ void Attr::Trace(blink::Visitor* visitor) {
Node::Trace(visitor);
}
-void Attr::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(element_);
- Node::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/attr.h b/chromium/third_party/blink/renderer/core/dom/attr.h
index 6bc6578fcd4..09bc949123a 100644
--- a/chromium/third_party/blink/renderer/core/dom/attr.h
+++ b/chromium/third_party/blink/renderer/core/dom/attr.h
@@ -60,7 +60,6 @@ class CORE_EXPORT Attr final : public Node {
const AtomicString& prefix() const { return name_.Prefix(); }
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
Attr(Element&, const QualifiedName&);
diff --git a/chromium/third_party/blink/renderer/core/dom/ax_object_cache.cc b/chromium/third_party/blink/renderer/core/dom/ax_object_cache.cc
deleted file mode 100644
index 7ea764db8b5..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/ax_object_cache.cc
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2008, 2009, 2010 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
-
-#include <memory>
-
-#include "base/memory/ptr_util.h"
-#include "third_party/blink/public/web/web_ax_enums.h"
-#include "third_party/blink/renderer/core/dom/element.h"
-#include "third_party/blink/renderer/core/dom/node.h"
-#include "third_party/blink/renderer/core/html_element_type_helpers.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/hash_set.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-AXObjectCache::AXObjectCacheCreateFunction AXObjectCache::create_function_ =
- nullptr;
-
-void AXObjectCache::Init(AXObjectCacheCreateFunction function) {
- DCHECK(!create_function_);
- create_function_ = function;
-}
-
-AXObjectCache* AXObjectCache::Create(Document& document) {
- DCHECK(create_function_);
- return create_function_(document);
-}
-
-AXObjectCache::AXObjectCache(Document& document)
- : ContextLifecycleObserver(document.GetExecutionContext()) {}
-
-AXObjectCache::~AXObjectCache() = default;
-
-std::unique_ptr<ScopedAXObjectCache> ScopedAXObjectCache::Create(
- Document& document) {
- return base::WrapUnique(new ScopedAXObjectCache(document));
-}
-
-ScopedAXObjectCache::ScopedAXObjectCache(Document& document)
- : document_(&document) {
- if (!document_->GetOrCreateAXObjectCache())
- cache_ = AXObjectCache::Create(*document_);
-}
-
-ScopedAXObjectCache::~ScopedAXObjectCache() {
- if (cache_)
- cache_->Dispose();
-}
-
-AXObjectCache* ScopedAXObjectCache::Get() {
- if (cache_)
- return cache_.Get();
- AXObjectCache* cache = document_->GetOrCreateAXObjectCache();
- DCHECK(cache);
- return cache;
-}
-
-namespace {
-
-typedef HashSet<String, CaseFoldingHash> ARIAWidgetSet;
-
-const char* g_aria_widgets[] = {
- // From http://www.w3.org/TR/wai-aria/roles#widget_roles
- "alert", "alertdialog", "button", "checkbox", "dialog", "gridcell", "link",
- "log", "marquee", "menuitem", "menuitemcheckbox", "menuitemradio", "option",
- "progressbar", "radio", "scrollbar", "slider", "spinbutton", "status",
- "tab", "tabpanel", "textbox", "timer", "tooltip", "treeitem",
- // Composite user interface widgets.
- // This list is also from the w3.org site referenced above.
- "combobox", "grid", "listbox", "menu", "menubar", "radiogroup", "tablist",
- "tree", "treegrid"};
-
-static ARIAWidgetSet* CreateARIARoleWidgetSet() {
- ARIAWidgetSet* widget_set = new HashSet<String, CaseFoldingHash>();
- for (size_t i = 0; i < arraysize(g_aria_widgets); ++i)
- widget_set->insert(String(g_aria_widgets[i]));
- return widget_set;
-}
-
-bool IncludesARIAWidgetRole(const String& role) {
- static const HashSet<String, CaseFoldingHash>* role_set =
- CreateARIARoleWidgetSet();
-
- Vector<String> role_vector;
- role.Split(' ', role_vector);
- for (const auto& child : role_vector) {
- if (role_set->Contains(child))
- return true;
- }
- return false;
-}
-
-const char* g_aria_interactive_widget_attributes[] = {
- // These attributes implicitly indicate the given widget is interactive.
- // From http://www.w3.org/TR/wai-aria/states_and_properties#attrs_widgets
- // clang-format off
- "aria-activedescendant",
- "aria-checked",
- "aria-controls",
- "aria-disabled", // If it's disabled, it can be made interactive.
- "aria-expanded",
- "aria-haspopup",
- "aria-multiselectable",
- "aria-pressed",
- "aria-required",
- "aria-selected"
- // clang-format on
-};
-
-bool HasInteractiveARIAAttribute(const Element& element) {
- for (size_t i = 0; i < arraysize(g_aria_interactive_widget_attributes); ++i) {
- const char* attribute = g_aria_interactive_widget_attributes[i];
- if (element.hasAttribute(attribute)) {
- return true;
- }
- }
- return false;
-}
-
-} // namespace
-
-bool AXObjectCache::IsInsideFocusableElementOrARIAWidget(const Node& node) {
- const Node* cur_node = &node;
- do {
- if (cur_node->IsElementNode()) {
- const Element* element = ToElement(cur_node);
- if (element->IsFocusable())
- return true;
- String role = element->getAttribute("role");
- if (!role.IsEmpty() && IncludesARIAWidgetRole(role))
- return true;
- if (HasInteractiveARIAAttribute(*element))
- return true;
- }
- cur_node = cur_node->parentNode();
- } while (cur_node && !IsHTMLBodyElement(node));
- return false;
-}
-
-void AXObjectCache::Trace(blink::Visitor* visitor) {
- ContextLifecycleObserver::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/ax_object_cache.h b/chromium/third_party/blink/renderer/core/dom/ax_object_cache.h
deleted file mode 100644
index 19abf8f76c1..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/ax_object_cache.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_AX_OBJECT_CACHE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_AX_OBJECT_CACHE_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/document.h"
-
-typedef unsigned AXID;
-
-namespace blink {
-
-class AbstractInlineTextBox;
-class AccessibleNode;
-class HTMLCanvasElement;
-class HTMLOptionElement;
-class HTMLSelectElement;
-class LayoutMenuList;
-class LineLayoutItem;
-class LocalFrameView;
-
-class CORE_EXPORT AXObjectCache
- : public GarbageCollectedFinalized<AXObjectCache>,
- public ContextLifecycleObserver {
- USING_GARBAGE_COLLECTED_MIXIN(AXObjectCache);
-
- public:
- static AXObjectCache* Create(Document&);
-
- virtual ~AXObjectCache();
- void Trace(blink::Visitor*) override;
-
- virtual void Dispose() = 0;
-
- virtual void SelectionChanged(Node*) = 0;
- virtual void ChildrenChanged(Node*) = 0;
- virtual void ChildrenChanged(LayoutObject*) = 0;
- virtual void ChildrenChanged(AccessibleNode*) = 0;
- virtual void CheckedStateChanged(Node*) = 0;
- virtual void ListboxOptionStateChanged(HTMLOptionElement*) = 0;
- virtual void ListboxSelectedChildrenChanged(HTMLSelectElement*) = 0;
- virtual void ListboxActiveIndexChanged(HTMLSelectElement*) = 0;
- virtual void RadiobuttonRemovedFromGroup(HTMLInputElement*) = 0;
-
- virtual void Remove(AccessibleNode*) = 0;
- virtual void Remove(LayoutObject*) = 0;
- virtual void Remove(Node*) = 0;
- virtual void Remove(AbstractInlineTextBox*) = 0;
-
- virtual const Element* RootAXEditableElement(const Node*) = 0;
-
- // Called by a node when text or a text equivalent (e.g. alt) attribute is
- // changed.
- virtual void TextChanged(LayoutObject*) = 0;
- // Called when a node has just been attached, so we can make sure we have the
- // right subclass of AXObject.
- virtual void UpdateCacheAfterNodeIsAttached(Node*) = 0;
-
- virtual void HandleAttributeChanged(const QualifiedName& attr_name,
- Element*) = 0;
- virtual void HandleFocusedUIElementChanged(Node* old_focused_node,
- Node* new_focused_node) = 0;
- virtual void HandleInitialFocus() = 0;
- virtual void HandleEditableTextContentChanged(Node*) = 0;
- virtual void HandleTextMarkerDataAdded(Node* start, Node* end) = 0;
- virtual void HandleTextFormControlChanged(Node*) = 0;
- virtual void HandleValueChanged(Node*) = 0;
- virtual void HandleUpdateActiveMenuOption(LayoutMenuList*,
- int option_index) = 0;
- virtual void DidShowMenuListPopup(LayoutMenuList*) = 0;
- virtual void DidHideMenuListPopup(LayoutMenuList*) = 0;
- virtual void HandleLoadComplete(Document*) = 0;
- virtual void HandleLayoutComplete(Document*) = 0;
- virtual void HandleClicked(Node*) = 0;
-
- virtual void SetCanvasObjectBounds(HTMLCanvasElement*,
- Element*,
- const LayoutRect&) = 0;
-
- virtual void InlineTextBoxesUpdated(LineLayoutItem) = 0;
-
- // Called when the scroll offset changes.
- virtual void HandleScrollPositionChanged(LocalFrameView*) = 0;
- virtual void HandleScrollPositionChanged(LayoutObject*) = 0;
-
- // Called when scroll bars are added / removed (as the view resizes).
- virtual void HandleLayoutComplete(LayoutObject*) = 0;
- virtual void HandleScrolledToAnchor(const Node* anchor_node) = 0;
-
- virtual const AtomicString& ComputedRoleForNode(Node*) = 0;
- virtual String ComputedNameForNode(Node*) = 0;
-
- virtual void OnTouchAccessibilityHover(const IntPoint&) = 0;
-
- virtual AXID GetAXID(Node*) = 0;
- virtual Element* GetElementFromAXID(AXID) = 0;
-
- typedef AXObjectCache* (*AXObjectCacheCreateFunction)(Document&);
- static void Init(AXObjectCacheCreateFunction);
-
- // Static helper functions.
- static bool IsInsideFocusableElementOrARIAWidget(const Node&);
-
- protected:
- AXObjectCache(Document&);
-
- private:
- static AXObjectCacheCreateFunction create_function_;
- DISALLOW_COPY_AND_ASSIGN(AXObjectCache);
-};
-
-class CORE_EXPORT ScopedAXObjectCache {
- USING_FAST_MALLOC(ScopedAXObjectCache);
-
- public:
- static std::unique_ptr<ScopedAXObjectCache> Create(Document&);
- ~ScopedAXObjectCache();
-
- AXObjectCache* Get();
-
- private:
- explicit ScopedAXObjectCache(Document&);
-
- Persistent<Document> document_;
- Persistent<AXObjectCache> cache_;
- DISALLOW_COPY_AND_ASSIGN(ScopedAXObjectCache);
-};
-
-} // namespace blink
-
-#endif
diff --git a/chromium/third_party/blink/renderer/core/dom/ax_object_cache_base.cc b/chromium/third_party/blink/renderer/core/dom/ax_object_cache_base.cc
deleted file mode 100644
index 824c654f78d..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/ax_object_cache_base.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/dom/ax_object_cache_base.h"
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
-
-namespace blink {
-
-AXObjectCacheBase::~AXObjectCacheBase() = default;
-
-AXObjectCacheBase::AXObjectCacheBase(Document& document)
- : AXObjectCache(document) {}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/ax_object_cache_base.h b/chromium/third_party/blink/renderer/core/dom/ax_object_cache_base.h
deleted file mode 100644
index 409ac728aad..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/ax_object_cache_base.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_AX_OBJECT_CACHE_BASE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_AX_OBJECT_CACHE_BASE_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
-
-namespace blink {
-
-class LayoutObject;
-class Node;
-class AXObject;
-
-// AXObjectCacheBase is a temporary class that sits between AXObjectCache and
-// AXObject and contains methods required by web/ that we don't want to be
-// available in the public API (AXObjectCache).
-// TODO(dmazzoni): Once all dependencies in web/ use this class instead of
-// AXObjectCacheImpl, refactor usages to use AXObjectCache instead (introducing
-// new public API methods or similar) and remove this class.
-class CORE_EXPORT AXObjectCacheBase : public AXObjectCache {
- public:
- ~AXObjectCacheBase() override;
-
- virtual AXObject* Get(const Node*) = 0;
- virtual AXObject* GetOrCreate(LayoutObject*) = 0;
-
- protected:
- AXObjectCacheBase(Document&);
- DISALLOW_COPY_AND_ASSIGN(AXObjectCacheBase);
-};
-
-// This is the only subclass of AXObjectCache.
-DEFINE_TYPE_CASTS(AXObjectCacheBase, AXObjectCache, cache, true, true);
-
-} // namespace blink
-
-#endif
diff --git a/chromium/third_party/blink/renderer/core/dom/character_data.cc b/chromium/third_party/blink/renderer/core/dom/character_data.cc
index 6ad44b8f23b..4fe5a46d7a7 100644
--- a/chromium/third_party/blink/renderer/core/dom/character_data.cc
+++ b/chromium/third_party/blink/renderer/core/dom/character_data.cc
@@ -22,10 +22,9 @@
#include "third_party/blink/renderer/core/dom/character_data.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "base/numerics/checked_math.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/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/mutation_observer_interest_group.h"
#include "third_party/blink/renderer/core/dom/mutation_record.h"
#include "third_party/blink/renderer/core/dom/processing_instruction.h"
@@ -33,7 +32,7 @@
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/events/mutation_event.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -55,9 +54,10 @@ String CharacterData::substringData(unsigned offset,
ExceptionState& exception_state) {
if (offset > length()) {
exception_state.ThrowDOMException(
- kIndexSizeError, "The offset " + String::Number(offset) +
- " is greater than the node's length (" +
- String::Number(length()) + ").");
+ DOMExceptionCode::kIndexSizeError,
+ "The offset " + String::Number(offset) +
+ " is greater than the node's length (" + String::Number(length()) +
+ ").");
return String();
}
@@ -85,9 +85,10 @@ void CharacterData::insertData(unsigned offset,
ExceptionState& exception_state) {
if (offset > length()) {
exception_state.ThrowDOMException(
- kIndexSizeError, "The offset " + String::Number(offset) +
- " is greater than the node's length (" +
- String::Number(length()) + ").");
+ DOMExceptionCode::kIndexSizeError,
+ "The offset " + String::Number(offset) +
+ " is greater than the node's length (" + String::Number(length()) +
+ ").");
return;
}
@@ -106,13 +107,14 @@ static bool ValidateOffsetCount(unsigned offset,
ExceptionState& exception_state) {
if (offset > length) {
exception_state.ThrowDOMException(
- kIndexSizeError, "The offset " + String::Number(offset) +
- " is greater than the node's length (" +
- String::Number(length) + ").");
+ DOMExceptionCode::kIndexSizeError,
+ "The offset " + String::Number(offset) +
+ " is greater than the node's length (" + String::Number(length) +
+ ").");
return false;
}
- CheckedNumeric<unsigned> offset_count = offset;
+ base::CheckedNumeric<unsigned> offset_count = offset;
offset_count += count;
if (!offset_count.IsValid() || offset + count > length)
diff --git a/chromium/third_party/blink/renderer/core/dom/child_list_mutation_scope.h b/chromium/third_party/blink/renderer/core/dom/child_list_mutation_scope.h
index 667eb579626..2cc10f33603 100644
--- a/chromium/third_party/blink/renderer/core/dom/child_list_mutation_scope.h
+++ b/chromium/third_party/blink/renderer/core/dom/child_list_mutation_scope.h
@@ -93,7 +93,7 @@ class ChildListMutationScope final {
public:
explicit ChildListMutationScope(Node& target) {
if (target.GetDocument().HasMutationObserversOfType(
- MutationObserver::kChildList)) {
+ kMutationTypeChildList)) {
accumulator_ = ChildListMutationAccumulator::GetOrCreate(target);
// Register another user of the accumulator.
accumulator_->EnterMutationScope();
diff --git a/chromium/third_party/blink/renderer/core/dom/child_node_list.cc b/chromium/third_party/blink/renderer/core/dom/child_node_list.cc
index dda1fa1eb70..e93469872fa 100644
--- a/chromium/third_party/blink/renderer/core/dom/child_node_list.cc
+++ b/chromium/third_party/blink/renderer/core/dom/child_node_list.cc
@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/core/dom/child_node_list.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_rare_data.h"
@@ -36,6 +37,13 @@ Node* ChildNodeList::VirtualOwnerNode() const {
ChildNodeList::~ChildNodeList() = default;
+Node* ChildNodeList::item(unsigned index) const {
+ Node* node = collection_index_cache_.NodeAt(*this, index);
+ if (node && node->GetDocument().InDOMNodeRemovedHandler())
+ node->GetDocument().CountDetachingNodeAccessInDOMNodeRemovedHandler();
+ return node;
+}
+
void ChildNodeList::ChildrenChanged(
const ContainerNode::ChildrenChange& change) {
if (change.IsChildInsertion()) {
diff --git a/chromium/third_party/blink/renderer/core/dom/child_node_list.h b/chromium/third_party/blink/renderer/core/dom/child_node_list.h
index 16d93e1f4c2..6c9ebb912cd 100644
--- a/chromium/third_party/blink/renderer/core/dom/child_node_list.h
+++ b/chromium/third_party/blink/renderer/core/dom/child_node_list.h
@@ -43,9 +43,7 @@ class ChildNodeList final : public NodeList {
unsigned length() const override {
return collection_index_cache_.NodeCount(*this);
}
- Node* item(unsigned index) const override {
- return collection_index_cache_.NodeAt(*this, index);
- }
+ Node* item(unsigned index) const override;
// Non-DOM API.
void ChildrenChanged(const ContainerNode::ChildrenChange&);
diff --git a/chromium/third_party/blink/renderer/core/dom/computed_accessible_node.cc b/chromium/third_party/blink/renderer/core/dom/computed_accessible_node.cc
deleted file mode 100644
index a90b034b803..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/computed_accessible_node.cc
+++ /dev/null
@@ -1,346 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/dom/computed_accessible_node.h"
-
-#include <stdint.h>
-#include <utility>
-
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/web/web_frame_client.h"
-#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/frame_request_callback_collection.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
-
-namespace blink {
-
-class ComputedAccessibleNodePromiseResolver::RequestAnimationFrameCallback final
- : public FrameRequestCallbackCollection::FrameCallback {
- public:
- explicit RequestAnimationFrameCallback(
- ComputedAccessibleNodePromiseResolver* resolver)
- : resolver_(resolver) {}
-
- void Invoke(double) override {
- resolver_->continue_callback_request_id_ = 0;
- resolver_->UpdateTreeAndResolve();
- }
-
- void Trace(blink::Visitor* visitor) override {
- visitor->Trace(resolver_);
- FrameRequestCallbackCollection::FrameCallback::Trace(visitor);
- }
-
- private:
- Member<ComputedAccessibleNodePromiseResolver> resolver_;
-
- DISALLOW_COPY_AND_ASSIGN(RequestAnimationFrameCallback);
-};
-
-ComputedAccessibleNodePromiseResolver*
-ComputedAccessibleNodePromiseResolver::Create(ScriptState* script_state,
- Element& element) {
- return new ComputedAccessibleNodePromiseResolver(script_state, element);
-}
-
-ComputedAccessibleNodePromiseResolver::ComputedAccessibleNodePromiseResolver(
- ScriptState* script_state,
- Element& element)
- : element_(element),
- resolver_(ScriptPromiseResolver::Create(script_state)),
- resolve_with_node_(false) {}
-
-ScriptPromise ComputedAccessibleNodePromiseResolver::Promise() {
- return resolver_->Promise();
-}
-
-void ComputedAccessibleNodePromiseResolver::Trace(blink::Visitor* visitor) {
- visitor->Trace(element_);
- visitor->Trace(resolver_);
-}
-
-void ComputedAccessibleNodePromiseResolver::ComputeAccessibleNode() {
- resolve_with_node_ = true;
- EnsureUpToDate();
-}
-
-void ComputedAccessibleNodePromiseResolver::EnsureUpToDate() {
- DCHECK(RuntimeEnabledFeatures::AccessibilityObjectModelEnabled());
- if (continue_callback_request_id_)
- return;
- // TODO(aboxhall): Trigger a call when lifecycle is next at kPrePaintClean.
- RequestAnimationFrameCallback* callback =
- new RequestAnimationFrameCallback(this);
- continue_callback_request_id_ =
- element_->GetDocument().RequestAnimationFrame(callback);
-}
-
-void ComputedAccessibleNodePromiseResolver::UpdateTreeAndResolve() {
- LocalFrame* local_frame = element_->ownerDocument()->GetFrame();
- WebFrameClient* client = WebLocalFrameImpl::FromFrame(local_frame)->Client();
- WebComputedAXTree* tree = client->GetOrCreateWebComputedAXTree();
- tree->ComputeAccessibilityTree();
-
- if (!resolve_with_node_) {
- resolver_->Resolve();
- return;
- }
-
- Document& document = element_->GetDocument();
- document.View()->UpdateLifecycleToCompositingCleanPlusScrolling();
- AXObjectCache* cache = element_->GetDocument().GetOrCreateAXObjectCache();
- DCHECK(cache);
- AXID ax_id = cache->GetAXID(element_);
-
- ComputedAccessibleNode* accessible_node =
- local_frame->GetOrCreateComputedAccessibleNode(ax_id, tree);
- resolver_->Resolve(accessible_node);
-}
-
-// ComputedAccessibleNode ------------------------------------------------------
-
-ComputedAccessibleNode* ComputedAccessibleNode::Create(AXID ax_id,
- WebComputedAXTree* tree,
- LocalFrame* frame) {
- return new ComputedAccessibleNode(ax_id, tree, frame);
-}
-
-ComputedAccessibleNode::ComputedAccessibleNode(AXID ax_id,
- WebComputedAXTree* tree,
- LocalFrame* frame)
- : ax_id_(ax_id), tree_(tree), frame_(frame) {}
-
-ComputedAccessibleNode::~ComputedAccessibleNode() {}
-
-bool ComputedAccessibleNode::atomic(bool& is_null) const {
- return GetBoolAttribute(WebAOMBoolAttribute::AOM_ATTR_ATOMIC, is_null);
-}
-
-ScriptPromise ComputedAccessibleNode::ensureUpToDate(
- ScriptState* script_state) {
- AXObjectCache* cache = frame_->GetDocument()->GetOrCreateAXObjectCache();
- Element* element = cache->GetElementFromAXID(ax_id_);
- ComputedAccessibleNodePromiseResolver* resolver =
- ComputedAccessibleNodePromiseResolver::Create(script_state, *element);
- ScriptPromise promise = resolver->Promise();
- resolver->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);
-}
-
-const String ComputedAccessibleNode::checked() const {
- WebString out;
- if (tree_->GetCheckedStateForAXNode(ax_id_, &out)) {
- return out;
- }
- return String();
-}
-
-const String ComputedAccessibleNode::keyShortcuts() const {
- return GetStringAttribute(WebAOMStringAttribute::AOM_ATTR_KEY_SHORTCUTS);
-}
-const String ComputedAccessibleNode::name() const {
- return GetStringAttribute(WebAOMStringAttribute::AOM_ATTR_NAME);
-}
-const String ComputedAccessibleNode::placeholder() const {
- return GetStringAttribute(WebAOMStringAttribute::AOM_ATTR_PLACEHOLDER);
-}
-
-const String ComputedAccessibleNode::role() const {
- WebString out;
- if (tree_->GetRoleForAXNode(ax_id_, &out)) {
- return out;
- }
- return String();
-}
-
-const String ComputedAccessibleNode::roleDescription() const {
- return GetStringAttribute(WebAOMStringAttribute::AOM_ATTR_ROLE_DESCRIPTION);
-}
-
-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)) {
- return nullptr;
- }
- return frame_->GetOrCreateComputedAccessibleNode(parent_ax_id, tree_);
-}
-
-ComputedAccessibleNode* ComputedAccessibleNode::firstChild() const {
- int32_t child_ax_id;
- if (!tree_->GetFirstChildIdForAXNode(ax_id_, &child_ax_id)) {
- return nullptr;
- }
- return frame_->GetOrCreateComputedAccessibleNode(child_ax_id, tree_);
-}
-
-ComputedAccessibleNode* ComputedAccessibleNode::lastChild() const {
- int32_t child_ax_id;
- if (!tree_->GetLastChildIdForAXNode(ax_id_, &child_ax_id)) {
- return nullptr;
- }
- return frame_->GetOrCreateComputedAccessibleNode(child_ax_id, tree_);
-}
-
-ComputedAccessibleNode* ComputedAccessibleNode::previousSibling() const {
- int32_t sibling_ax_id;
- if (!tree_->GetPreviousSiblingIdForAXNode(ax_id_, &sibling_ax_id)) {
- return nullptr;
- }
- return frame_->GetOrCreateComputedAccessibleNode(sibling_ax_id, tree_);
-}
-
-ComputedAccessibleNode* ComputedAccessibleNode::nextSibling() const {
- int32_t sibling_ax_id;
- if (!tree_->GetNextSiblingIdForAXNode(ax_id_, &sibling_ax_id)) {
- return nullptr;
- }
- return frame_->GetOrCreateComputedAccessibleNode(sibling_ax_id, tree_);
-}
-
-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;
- if (tree_->GetStringAttributeForAXNode(ax_id_, attr, &out)) {
- return out;
- }
- return String();
-}
-
-void ComputedAccessibleNode::Trace(Visitor* visitor) {
- visitor->Trace(frame_);
- ScriptWrappable::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/computed_accessible_node.h b/chromium/third_party/blink/renderer/core/dom/computed_accessible_node.h
deleted file mode 100644
index 713e46e157a..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/computed_accessible_node.h
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_COMPUTED_ACCESSIBLE_NODE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_COMPUTED_ACCESSIBLE_NODE_H_
-
-#include "third_party/blink/public/platform/web_computed_ax_tree.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
-#include "third_party/blink/renderer/core/dom/element.h"
-#include "third_party/blink/renderer/core/dom/events/event_target.h"
-#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-class ScriptState;
-
-class ComputedAccessibleNodePromiseResolver final
- : public GarbageCollectedFinalized<ComputedAccessibleNodePromiseResolver> {
- public:
- static ComputedAccessibleNodePromiseResolver* Create(ScriptState*, Element&);
- ~ComputedAccessibleNodePromiseResolver() {}
-
- ScriptPromise Promise();
- void ComputeAccessibleNode();
- void EnsureUpToDate();
- void Trace(blink::Visitor*);
-
- private:
- ComputedAccessibleNodePromiseResolver(ScriptState*, Element&);
- void UpdateTreeAndResolve();
- class RequestAnimationFrameCallback;
-
- int continue_callback_request_id_ = 0;
- Member<Element> element_;
- Member<ScriptPromiseResolver> resolver_;
- bool resolve_with_node_;
-};
-
-class ComputedAccessibleNode : public ScriptWrappable {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- static ComputedAccessibleNode* Create(AXID, WebComputedAXTree*, LocalFrame*);
- ~ComputedAccessibleNode() override;
-
- void Trace(Visitor*) override;
-
- // TODO(meredithl): add accessors for state properties.
- bool atomic(bool& is_null) const;
- bool busy(bool& is_null) const;
- bool disabled(bool& is_null) const;
- bool readOnly(bool& is_null) const;
- bool expanded(bool& is_null) const;
- bool modal(bool& is_null) const;
- bool multiline(bool& is_null) const;
- bool multiselectable(bool& is_null) const;
- bool required(bool& is_null) const;
- bool selected(bool& is_null) const;
-
- int32_t colCount(bool& is_null) const;
- int32_t colIndex(bool& is_null) const;
- int32_t colSpan(bool& is_null) const;
- int32_t level(bool& is_null) const;
- int32_t posInSet(bool& is_null) const;
- int32_t rowCount(bool& is_null) const;
- int32_t rowIndex(bool& is_null) const;
- int32_t rowSpan(bool& is_null) const;
- int32_t setSize(bool& is_null) const;
-
- float valueMax(bool& is_null) const;
- float valueMin(bool& is_null) const;
- float valueNow(bool& is_null) const;
-
- const String autocomplete() const;
- const String checked() const;
- const String keyShortcuts() const;
- const String name() const;
- const String placeholder() const;
- const String role() const;
- const String roleDescription() const;
- const String valueText() const;
-
- ComputedAccessibleNode* parent() const;
- ComputedAccessibleNode* firstChild() const;
- ComputedAccessibleNode* lastChild() const;
- ComputedAccessibleNode* previousSibling() const;
- ComputedAccessibleNode* nextSibling() const;
-
- ScriptPromise ensureUpToDate(ScriptState*);
-
- private:
- ComputedAccessibleNode(AXID, WebComputedAXTree*, LocalFrame*);
- 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_;
-
- // This tree is owned by the RenderFrame.
- blink::WebComputedAXTree* tree_;
- Member<LocalFrame> frame_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_COMPUTED_ACCESSIBLE_NODE_H_
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 12d297632e5..31c96bdc0fb 100644
--- a/chromium/third_party/blink/renderer/core/dom/container_node.cc
+++ b/chromium/third_party/blink/renderer/core/dom/container_node.cc
@@ -23,7 +23,6 @@
#include "third_party/blink/renderer/core/dom/container_node.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/selector_query.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
@@ -31,7 +30,8 @@
#include "third_party/blink/renderer/core/dom/child_list_mutation_scope.h"
#include "third_party/blink/renderer/core/dom/class_collection.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
+#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
#include "third_party/blink/renderer/core/dom/name_node_list.h"
#include "third_party/blink/renderer/core/dom/node_child_removal_tracker.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
@@ -39,10 +39,12 @@
#include "third_party/blink/renderer/core/dom/node_rare_data.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
+#include "third_party/blink/renderer/core/dom/slot_assignment_recalc_forbidden_scope.h"
#include "third_party/blink/renderer/core/dom/static_node_list.h"
#include "third_party/blink/renderer/core/dom/whitespace_attacher.h"
#include "third_party/blink/renderer/core/events/mutation_event.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
+#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/html/forms/radio_node_list.h"
#include "third_party/blink/renderer/core/html/html_collection.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
@@ -53,10 +55,10 @@
#include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
#include "third_party/blink/renderer/core/layout/line/root_inline_box.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
-#include "third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
@@ -82,13 +84,17 @@ class DOMTreeMutationDetector {
public:
DOMTreeMutationDetector(const Node& node, const Node& parent)
- : node_document_(node.GetDocument()),
+ : node_(&node),
+ node_document_(node.GetDocument()),
parent_document_(parent.GetDocument()),
parent_(parent),
original_node_document_version_(node_document_->DomTreeVersion()),
original_parent_document_version_(parent_document_->DomTreeVersion()) {}
- bool HadAtMostOneDOMMutation() {
+ bool NeedsRecheck() {
+ if (node_document_ != node_->GetDocument()) {
+ return false;
+ }
if (node_document_->DomTreeVersion() > original_node_document_version_ + 1)
return false;
if (parent_document_ != parent_->GetDocument())
@@ -100,6 +106,7 @@ class DOMTreeMutationDetector {
}
private:
+ const Member<const Node> node_;
const Member<Document> node_document_;
const Member<Document> parent_document_;
const Member<const Node> parent_;
@@ -112,7 +119,7 @@ inline bool CheckReferenceChildParent(const Node& parent,
const Node* old_child,
ExceptionState& exception_state) {
if (next && next->parentNode() != &parent) {
- exception_state.ThrowDOMException(kNotFoundError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotFoundError,
"The node before which the new node is "
"to be inserted is not a child of this "
"node.");
@@ -120,7 +127,8 @@ inline bool CheckReferenceChildParent(const Node& parent,
}
if (old_child && old_child->parentNode() != &parent) {
exception_state.ThrowDOMException(
- kNotFoundError, "The node to be replaced is not a child of this node.");
+ DOMExceptionCode::kNotFoundError,
+ "The node to be replaced is not a child of this node.");
return false;
}
return true;
@@ -197,7 +205,8 @@ bool ContainerNode::IsHostIncludingInclusiveAncestorOfThis(
}
if (child_contains_parent) {
exception_state.ThrowDOMException(
- kHierarchyRequestError, "The new child element contains the parent.");
+ DOMExceptionCode::kHierarchyRequestError,
+ "The new child element contains the parent.");
}
return child_contains_parent;
}
@@ -231,7 +240,8 @@ bool ContainerNode::EnsurePreInsertionValidity(
DCHECK(!new_child.IsPseudoElement());
if (new_child.IsPseudoElement()) {
exception_state.ThrowDOMException(
- kHierarchyRequestError, "The new child element is a pseudo-element.");
+ DOMExceptionCode::kHierarchyRequestError,
+ "The new child element is a pseudo-element.");
return false;
}
@@ -261,7 +271,7 @@ bool ContainerNode::EnsurePreInsertionValidity(
// doctype and parent is not a document, throw a HierarchyRequestError.
if (!IsChildTypeAllowed(new_child)) {
exception_state.ThrowDOMException(
- kHierarchyRequestError,
+ DOMExceptionCode::kHierarchyRequestError,
"Nodes of type '" + new_child.nodeName() +
"' may not be inserted inside nodes of type '" + nodeName() + "'.");
return false;
@@ -343,6 +353,9 @@ void ContainerNode::DidInsertNodeVector(
DispatchChildInsertionEvents(*target_node);
}
DispatchSubtreeModifiedEvent();
+
+ if (AXObjectCache* cache = GetDocument().GetOrCreateAXObjectCache())
+ cache->DidInsertChildrenOfNode(this);
}
class ContainerNode::AdoptAndInsertBefore {
@@ -394,7 +407,7 @@ Node* ContainerNode::InsertBefore(Node* new_child,
if (!CollectChildrenAndRemoveFromOldParent(*new_child, targets,
exception_state))
return new_child;
- if (!detector.HadAtMostOneDOMMutation()) {
+ if (!detector.NeedsRecheck()) {
if (!RecheckNodeInsertionStructuralPrereq(targets, ref_child,
exception_state))
return new_child;
@@ -403,6 +416,7 @@ Node* ContainerNode::InsertBefore(Node* new_child,
// 5. Insert node into parent before reference child.
NodeVector post_insertion_notification_targets;
{
+ SlotAssignmentRecalcForbiddenScope forbid_slot_recalc(GetDocument());
ChildListMutationScope mutation(*this);
InsertNodeVector(targets, ref_child, AdoptAndInsertBefore(),
&post_insertion_notification_targets);
@@ -512,7 +526,7 @@ Node* ContainerNode::ReplaceChild(Node* new_child,
// https://dom.spec.whatwg.org/#concept-node-replace
if (!old_child) {
- exception_state.ThrowDOMException(kNotFoundError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotFoundError,
"The node to be replaced is null.");
return nullptr;
}
@@ -541,7 +555,7 @@ Node* ContainerNode::ReplaceChild(Node* new_child,
new_child_parent->RemoveChild(new_child, exception_state);
if (exception_state.HadException())
return nullptr;
- if (!detector.HadAtMostOneDOMMutation())
+ if (!detector.NeedsRecheck())
needs_recheck = true;
}
@@ -563,17 +577,19 @@ Node* ContainerNode::ReplaceChild(Node* new_child,
old_child_parent->RemoveChild(old_child, exception_state);
if (exception_state.HadException())
return nullptr;
- if (!detector.HadAtMostOneDOMMutation())
+ if (!detector.NeedsRecheck())
needs_recheck = true;
}
+ SlotAssignmentRecalcForbiddenScope forbid_slot_recalc(GetDocument());
+
// 13. Let nodes be node’s children if node is a DocumentFragment node, and
// a list containing solely node otherwise.
DOMTreeMutationDetector detector(*new_child, *this);
if (!CollectChildrenAndRemoveFromOldParent(*new_child, targets,
exception_state))
return old_child;
- if (!detector.HadAtMostOneDOMMutation() || needs_recheck) {
+ if (!detector.NeedsRecheck() || needs_recheck) {
if (!RecheckNodeInsertionStructuralPrereq(targets, next, exception_state))
return old_child;
}
@@ -642,12 +658,6 @@ void ContainerNode::Trace(blink::Visitor* visitor) {
Node::Trace(visitor);
}
-void ContainerNode::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(first_child_);
- visitor->TraceWrappers(last_child_);
- Node::TraceWrappers(visitor);
-}
-
Node* ContainerNode::RemoveChild(Node* old_child,
ExceptionState& exception_state) {
// NotFoundError: Raised if oldChild is not a child of this node.
@@ -657,7 +667,8 @@ Node* ContainerNode::RemoveChild(Node* old_child,
if (!old_child || old_child->parentNode() != this ||
old_child->IsPseudoElement()) {
exception_state.ThrowDOMException(
- kNotFoundError, "The node to be removed is not a child of this node.");
+ DOMExceptionCode::kNotFoundError,
+ "The node to be removed is not a child of this node.");
return nullptr;
}
@@ -669,7 +680,7 @@ Node* ContainerNode::RemoveChild(Node* old_child,
// child into a different parent.
if (child->parentNode() != this) {
exception_state.ThrowDOMException(
- kNotFoundError,
+ DOMExceptionCode::kNotFoundError,
"The node to be removed is no longer a "
"child of this node. Perhaps it was moved "
"in a 'blur' event handler?");
@@ -681,7 +692,7 @@ Node* ContainerNode::RemoveChild(Node* old_child,
// Mutation events might have moved this child into a different parent.
if (child->parentNode() != this) {
exception_state.ThrowDOMException(
- kNotFoundError,
+ DOMExceptionCode::kNotFoundError,
"The node to be removed is no longer a "
"child of this node. Perhaps it was moved "
"in response to a mutation?");
@@ -689,6 +700,7 @@ Node* ContainerNode::RemoveChild(Node* old_child,
}
{
+ SlotAssignmentRecalcForbiddenScope forbid_slot_recalc(GetDocument());
HTMLFrameOwnerElement::PluginDisposeSuspendScope suspend_plugin_dispose;
TreeOrderedMap::RemoveScope tree_remove_scope;
@@ -791,6 +803,7 @@ void ContainerNode::RemoveChildren(SubtreeModificationAction action) {
HTMLFrameOwnerElement::PluginDisposeSuspendScope suspend_plugin_dispose;
TreeOrderedMap::RemoveScope tree_remove_scope;
{
+ SlotAssignmentRecalcForbiddenScope forbid_slot_recalc(GetDocument());
EventDispatchForbiddenScope assert_no_event_dispatch;
ScriptForbiddenScope forbid_script;
@@ -822,7 +835,7 @@ Node* ContainerNode::AppendChild(Node* new_child,
if (!CollectChildrenAndRemoveFromOldParent(*new_child, targets,
exception_state))
return new_child;
- if (!detector.HadAtMostOneDOMMutation()) {
+ if (!detector.NeedsRecheck()) {
if (!RecheckNodeInsertionStructuralPrereq(targets, nullptr,
exception_state))
return new_child;
@@ -830,6 +843,7 @@ Node* ContainerNode::AppendChild(Node* new_child,
NodeVector post_insertion_notification_targets;
{
+ SlotAssignmentRecalcForbiddenScope forbid_slot_recalc(GetDocument());
ChildListMutationScope mutation(*this);
InsertNodeVector(targets, nullptr, AdoptAndAppendChild(),
&post_insertion_notification_targets);
@@ -1222,7 +1236,12 @@ Element* ContainerNode::QuerySelector(const AtomicString& selectors,
selectors, GetDocument(), exception_state);
if (!selector_query)
return nullptr;
- return selector_query->QueryFirst(*this);
+ Element* element = selector_query->QueryFirst(*this);
+ if (element && element->GetDocument().InDOMNodeRemovedHandler()) {
+ if (NodeChildRemovalTracker::IsBeingRemoved(element))
+ GetDocument().CountDetachingNodeAccessInDOMNodeRemovedHandler();
+ }
+ return element;
}
Element* ContainerNode::QuerySelector(const AtomicString& selectors) {
@@ -1285,24 +1304,47 @@ static void DispatchChildRemovalEvents(Node& child) {
probe::willRemoveDOMNode(&child);
Node* c = &child;
- Document* document = &child.GetDocument();
+ Document& document = child.GetDocument();
// Dispatch pre-removal mutation events.
if (c->parentNode() &&
- document->HasListenerType(Document::kDOMNodeRemovedListener)) {
+ document.HasListenerType(Document::kDOMNodeRemovedListener)) {
+ bool original_node_flag = c->InDOMNodeRemovedHandler();
+ auto original_document_state = document.GetInDOMNodeRemovedHandlerState();
+ if (ScopedEventQueue::Instance()->ShouldQueueEvents()) {
+ UseCounter::Count(document, WebFeature::kDOMNodeRemovedEventDelayed);
+ } else {
+ c->SetInDOMNodeRemovedHandler(true);
+ document.SetInDOMNodeRemovedHandlerState(
+ Document::InDOMNodeRemovedHandlerState::kDOMNodeRemoved);
+ }
NodeChildRemovalTracker scope(child);
c->DispatchScopedEvent(MutationEvent::Create(
EventTypeNames::DOMNodeRemoved, Event::Bubbles::kYes, c->parentNode()));
+ document.SetInDOMNodeRemovedHandlerState(original_document_state);
+ c->SetInDOMNodeRemovedHandler(original_node_flag);
}
// Dispatch the DOMNodeRemovedFromDocument event to all descendants.
- if (c->isConnected() && document->HasListenerType(
- Document::kDOMNodeRemovedFromDocumentListener)) {
+ if (c->isConnected() &&
+ document.HasListenerType(Document::kDOMNodeRemovedFromDocumentListener)) {
+ bool original_node_flag = c->InDOMNodeRemovedHandler();
+ auto original_document_state = document.GetInDOMNodeRemovedHandlerState();
+ if (ScopedEventQueue::Instance()->ShouldQueueEvents()) {
+ UseCounter::Count(document,
+ WebFeature::kDOMNodeRemovedFromDocumentEventDelayed);
+ } else {
+ c->SetInDOMNodeRemovedHandler(true);
+ document.SetInDOMNodeRemovedHandlerState(
+ Document::InDOMNodeRemovedHandlerState::kDOMNodeRemovedFromDocument);
+ }
NodeChildRemovalTracker scope(child);
for (; c; c = NodeTraversal::Next(*c, &child)) {
c->DispatchScopedEvent(MutationEvent::Create(
EventTypeNames::DOMNodeRemovedFromDocument, Event::Bubbles::kNo));
}
+ document.SetInDOMNodeRemovedHandlerState(original_document_state);
+ child.SetInDOMNodeRemovedHandler(original_node_flag);
}
}
@@ -1335,13 +1377,6 @@ void ContainerNode::RecalcDescendantStyles(StyleRecalcChange change) {
}
}
-void ContainerNode::RecalcDescendantStylesForReattach() {
- for (Node* child = lastChild(); child; child = child->previousSibling()) {
- if (child->IsElementNode())
- ToElement(child)->RecalcStyleForReattach();
- }
-}
-
void ContainerNode::RebuildLayoutTreeForChild(
Node* child,
WhitespaceAttacher& whitespace_attacher) {
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 7ecbdf45e52..dea345ca2d3 100644
--- a/chromium/third_party/blink/renderer/core/dom/container_node.h
+++ b/chromium/third_party/blink/renderer/core/dom/container_node.h
@@ -289,7 +289,6 @@ class CORE_EXPORT ContainerNode : public Node {
Node* node_before_change,
Node* node_after_change);
void RecalcDescendantStyles(StyleRecalcChange);
- void RecalcDescendantStylesForReattach();
void RebuildChildrenLayoutTrees(WhitespaceAttacher&);
void RebuildLayoutTreeForChild(Node* child, WhitespaceAttacher&);
void RebuildNonDistributedChildren();
@@ -367,8 +366,6 @@ class CORE_EXPORT ContainerNode : public Node {
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
protected:
ContainerNode(TreeScope*, ConstructionType = kCreateContainer);
diff --git a/chromium/third_party/blink/renderer/core/dom/context_lifecycle_notifier.cc b/chromium/third_party/blink/renderer/core/dom/context_lifecycle_notifier.cc
index 4fc1099cda6..1e755ea7e6f 100644
--- a/chromium/third_party/blink/renderer/core/dom/context_lifecycle_notifier.cc
+++ b/chromium/third_party/blink/renderer/core/dom/context_lifecycle_notifier.cc
@@ -33,59 +33,58 @@
namespace blink {
void ContextLifecycleNotifier::NotifyResumingPausableObjects() {
- base::AutoReset<IterationState> scope(&iteration_state_, kAllowingNone);
- for (ContextLifecycleObserver* observer : observers_) {
+ ForEachObserver([&](ContextLifecycleObserver* observer) {
if (observer->ObserverType() !=
ContextLifecycleObserver::kPausableObjectType)
- continue;
+ return;
PausableObject* pausable_object = static_cast<PausableObject*>(observer);
#if DCHECK_IS_ON()
DCHECK_EQ(pausable_object->GetExecutionContext(), Context());
DCHECK(pausable_object->PauseIfNeededCalled());
#endif
pausable_object->Unpause();
- }
+ });
}
void ContextLifecycleNotifier::NotifySuspendingPausableObjects() {
- base::AutoReset<IterationState> scope(&iteration_state_, kAllowingNone);
- for (ContextLifecycleObserver* observer : observers_) {
+ ForEachObserver([&](ContextLifecycleObserver* observer) {
if (observer->ObserverType() !=
ContextLifecycleObserver::kPausableObjectType)
- continue;
+ return;
PausableObject* pausable_object = static_cast<PausableObject*>(observer);
#if DCHECK_IS_ON()
DCHECK_EQ(pausable_object->GetExecutionContext(), Context());
DCHECK(pausable_object->PauseIfNeededCalled());
#endif
pausable_object->Pause();
- }
+ });
}
unsigned ContextLifecycleNotifier::PausableObjectCount() const {
DCHECK(!IsIteratingOverObservers());
unsigned pausable_objects = 0;
- for (ContextLifecycleObserver* observer : observers_) {
+ ForEachObserver([&](ContextLifecycleObserver* observer) {
if (observer->ObserverType() !=
ContextLifecycleObserver::kPausableObjectType)
- continue;
+ return;
pausable_objects++;
- }
+ });
return pausable_objects;
}
#if DCHECK_IS_ON()
bool ContextLifecycleNotifier::Contains(PausableObject* object) const {
DCHECK(!IsIteratingOverObservers());
- for (ContextLifecycleObserver* observer : observers_) {
+ bool found = false;
+ ForEachObserver([&](ContextLifecycleObserver* observer) {
if (observer->ObserverType() !=
ContextLifecycleObserver::kPausableObjectType)
- continue;
+ return;
PausableObject* pausable_object = static_cast<PausableObject*>(observer);
if (pausable_object == object)
- return true;
- }
- return false;
+ found = true;
+ });
+ return found;
}
#endif
diff --git a/chromium/third_party/blink/renderer/core/dom/context_lifecycle_observer.h b/chromium/third_party/blink/renderer/core/dom/context_lifecycle_observer.h
index c163095d109..bbba1d3aa9b 100644
--- a/chromium/third_party/blink/renderer/core/dom/context_lifecycle_observer.h
+++ b/chromium/third_party/blink/renderer/core/dom/context_lifecycle_observer.h
@@ -37,17 +37,38 @@ class LocalDOMWindow;
class LocalFrame;
// ContextClient and ContextLifecycleObserver are helpers to associate an
-// object with an ExecutionContext.
+// object with an ExecutionContext. It is unsafe to access an associated GC
+// object, *including via GetExecutionContext()*, in the destructor of a GC
+// object.
//
-// - getExecutionContext() returns null after the context is detached.
-// - frame() is a syntax sugar for getExecutionContext()->frame(). It returns
-// null after the context is detached or the context is not a Document.
+// 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
+// scope, this occurs when it shuts down.
//
-// Both can safely be used up until destruction; i.e., unsafe to
-// call upon in a destructor.
+// * If an object only needs to refer to a valid ExecutionContext but does not
+// need to stop or suspend any activity, it should be a ContextClient.
+// * If an object associated with an ExecutionContext has shutdown logic to
+// perform, such as halting activity or disconnecting from longer-lived
+// objects, it should be a ContextLifecycleObserver.
+// * If an object additionally must suspend its activity during pause (see
+// pausable_object.h), it should be a PausableObject (and thus, transitively,
+// also a ContextLifecycleObserver).
+//
+// If your object has activity which requires that it be kept alive, even if no
+// other object has a reference to it, consider whether your object should also
+// derive from ActiveScriptWrappable.
+
+// ContextClient provides access to the associated execution context until it is
+// shut down (e.g. for a document, at navigation or frame detach).
class CORE_EXPORT ContextClient : public GarbageCollectedMixin {
public:
+ // Returns the execution context until it is detached.
+ // From then on, returns null instead.
ExecutionContext* GetExecutionContext() const;
+
+ // If associated with a live document, returns the associated frame.
+ // Returns null otherwise.
LocalFrame* GetFrame() const;
void Trace(blink::Visitor*) override;
@@ -60,15 +81,31 @@ class CORE_EXPORT ContextClient : public GarbageCollectedMixin {
WeakMember<ExecutionContext> execution_context_;
};
-// ContextLifecycleObserver provides an additional contextDestroyed() hook
-// to execute cleanup code when a context is destroyed. Prefer the simpler
-// ContextClient when possible.
+// ContextLifecycleObserver provides an additional ContextDestroyed() hook
+// to execute cleanup code when a context is shut down (e.g. for a document,
+// at navigation or frame detach -- not when its destructor runs).
+//
+// Execution context associated objects which have ongoing activity,
+// registration with objects which outlive the context, or resources which
+// should be promptly released, should consider deriving from
+// ContextLifecycleObserver. As a rule of thumb: if the destructor contains
+// non-trivial logic, that logic may belong in ContextDestroyed() instead.
+//
+// If there is ongoing activity associated with the object, consider whether it
+// needs to be paused when execution is suspended (see PausableObject).
+//
+// If none of the above applies, prefer the simpler ContextClient.
class CORE_EXPORT ContextLifecycleObserver
: public LifecycleObserver<ExecutionContext, ContextLifecycleObserver> {
public:
virtual void ContextDestroyed(ExecutionContext*) {}
+ // Returns the execution context until it is detached.
+ // From then on, returns null instead.
ExecutionContext* GetExecutionContext() const { return LifecycleContext(); }
+
+ // If associated with a live document, returns the associated frame.
+ // Returns null otherwise.
LocalFrame* GetFrame() const;
enum Type {
diff --git a/chromium/third_party/blink/renderer/core/dom/dataset_dom_string_map.cc b/chromium/third_party/blink/renderer/core/dom/dataset_dom_string_map.cc
index 9468283744f..0a18a0a6e08 100644
--- a/chromium/third_party/blink/renderer/core/dom/dataset_dom_string_map.cc
+++ b/chromium/third_party/blink/renderer/core/dom/dataset_dom_string_map.cc
@@ -25,10 +25,9 @@
#include "third_party/blink/renderer/core/dom/dataset_dom_string_map.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/dom/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/ascii_ctype.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -181,7 +180,8 @@ void DatasetDOMStringMap::SetItem(const String& name,
ExceptionState& exception_state) {
if (!IsValidPropertyName(name)) {
exception_state.ThrowDOMException(
- kSyntaxError, "'" + name + "' is not a valid property name.");
+ DOMExceptionCode::kSyntaxError,
+ "'" + name + "' is not a valid property name.");
return;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/document.cc b/chromium/third_party/blink/renderer/core/dom/document.cc
index 9abb526ef01..5bfe30b8b88 100644
--- a/chromium/third_party/blink/renderer/core/dom/document.cc
+++ b/chromium/third_party/blink/renderer/core/dom/document.cc
@@ -47,23 +47,23 @@
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/ukm.mojom-blink.h"
#include "third_party/blink/public/platform/web_prerendering_support.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_dictionary.h"
+#include "third_party/blink/renderer/bindings/core/v8/usv_string_or_trusted_url.h"
#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/window_proxy.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.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/pending_animations.h"
+#include "third_party/blink/renderer/core/animation/worklet_animation_controller.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_style_declaration.h"
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
-#include "third_party/blink/renderer/core/css/css_timing.h"
#include "third_party/blink/renderer/core/css/cssom/computed_style_property_map.h"
#include "third_party/blink/renderer/core/css/font_face_set_document.h"
#include "third_party/blink/renderer/core/css/invalidation/style_invalidator.h"
@@ -80,11 +80,11 @@
#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/dom/attr.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/cdata_section.h"
#include "third_party/blink/renderer/core/dom/comment.h"
#include "third_party/blink/renderer/core/dom/context_features.h"
#include "third_party/blink/renderer/core/dom/document_fragment.h"
+#include "third_party/blink/renderer/core/dom/document_init.h"
#include "third_party/blink/renderer/core/dom/document_parser_timing.h"
#include "third_party/blink/renderer/core/dom/document_type.h"
#include "third_party/blink/renderer/core/dom/dom_implementation.h"
@@ -94,14 +94,14 @@
#include "third_party/blink/renderer/core/dom/element_registration_options.h"
#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/events/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
+#include "third_party/blink/renderer/core/dom/layout_tree_builder.h"
#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
#include "third_party/blink/renderer/core/dom/live_node_list.h"
#include "third_party/blink/renderer/core/dom/mutation_observer.h"
-#include "third_party/blink/renderer/core/dom/ng/slot_assignment_engine.h"
#include "third_party/blink/renderer/core/dom/node_child_removal_tracker.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/node_iterator.h"
@@ -114,10 +114,10 @@
#include "third_party/blink/renderer/core/dom/scripted_animation_controller.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/dom/slot_assignment.h"
+#include "third_party/blink/renderer/core/dom/slot_assignment_engine.h"
#include "third_party/blink/renderer/core/dom/static_node_list.h"
#include "third_party/blink/renderer/core/dom/transform_source.h"
#include "third_party/blink/renderer/core/dom/tree_walker.h"
-#include "third_party/blink/renderer/core/dom/trustedtypes/trusted_html.h"
#include "third_party/blink/renderer/core/dom/visited_link_state.h"
#include "third_party/blink/renderer/core/dom/whitespace_attacher.h"
#include "third_party/blink/renderer/core/dom/xml_document.h"
@@ -138,7 +138,6 @@
#include "third_party/blink/renderer/core/frame/event_handler_registry.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/hosts_using_features.h"
#include "third_party/blink/renderer/core/frame/intervention.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -147,6 +146,7 @@
#include "third_party/blink/renderer/core/frame/performance_monitor.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/core/frame/viewport_data.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_font_cache.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
@@ -206,6 +206,7 @@
#include "third_party/blink/renderer/core/loader/frame_fetch_context.h"
#include "third_party/blink/renderer/core/loader/frame_loader.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/navigation_scheduler.h"
#include "third_party/blink/renderer/core/loader/prerenderer_client.h"
#include "third_party/blink/renderer/core/loader/text_resource_decoder_builder.h"
@@ -224,6 +225,7 @@
#include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/core/paint/first_meaningful_paint_detector.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/policy/document_policy.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
@@ -238,18 +240,21 @@
#include "third_party/blink/renderer/core/svg_names.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/trustedtypes/trusted_html.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_url.h"
#include "third_party/blink/renderer/core/workers/shared_worker_repository_client.h"
#include "third_party/blink/renderer/core/xml/parser/xml_document_parser.h"
#include "third_party/blink/renderer/core/xml_names.h"
#include "third_party/blink/renderer/core/xmlns_names.h"
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.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_dom_wrapper.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/date_components.h"
-#include "third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/instance_counters.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -575,6 +580,10 @@ class Document::NetworkStateObserver final
online_observer_handle_;
};
+Document* Document::CreateForTest() {
+ return new Document(DocumentInit::Create());
+}
+
Document* Document::Create(Document& document) {
Document* new_document = new Document(
DocumentInit::Create().WithContextDocument(&document).WithURL(
@@ -600,10 +609,11 @@ Document::Document(const DocumentInit& initializer,
context_features_(ContextFeatures::DefaultSwitch()),
well_formed_(false),
printing_(kNotPrinting),
- paginated_for_screen_(false),
compatibility_mode_(kNoQuirksMode),
compatibility_mode_locked_(false),
has_autofocused_(false),
+ last_focus_type_(kWebFocusTypeNone),
+ had_keyboard_event_(false),
clear_focused_element_timer_(
GetTaskRunner(TaskType::kInternalUserInteraction),
this,
@@ -681,7 +691,8 @@ Document::Document(const DocumentInit& initializer,
#if DCHECK_IS_ON()
slot_assignment_recalc_forbidden_recursion_depth_(0),
#endif
- needs_to_record_ukm_outlive_time_(false) {
+ needs_to_record_ukm_outlive_time_(false),
+ viewport_data_(new ViewportData(*this)) {
if (frame_) {
DCHECK(frame_->GetPage());
ProvideContextFeaturesToDocumentFrom(*this, *frame_->GetPage());
@@ -904,7 +915,7 @@ Element* Document::CreateElementForBinding(const AtomicString& name,
ExceptionState& exception_state) {
if (!IsValidElementName(this, name)) {
exception_state.ThrowDOMException(
- kInvalidCharacterError,
+ DOMExceptionCode::kInvalidCharacterError,
"The tag name provided ('" + name + "') is not a valid name.");
return nullptr;
}
@@ -962,10 +973,14 @@ Element* Document::CreateElementForBinding(
const AtomicString& local_name,
const StringOrDictionary& string_or_options,
ExceptionState& exception_state) {
+ if (string_or_options.IsNull()) {
+ return CreateElementForBinding(local_name, exception_state);
+ }
+
// 1. If localName does not match Name production, throw InvalidCharacterError
if (!IsValidElementName(this, local_name)) {
exception_state.ThrowDOMException(
- kInvalidCharacterError,
+ DOMExceptionCode::kInvalidCharacterError,
"The tag name provided ('" + local_name + "') is not a valid name.");
return nullptr;
}
@@ -978,9 +993,7 @@ Element* Document::CreateElementForBinding(
: g_null_atom);
bool is_v1 = string_or_options.IsDictionary() || !RegistrationContext();
- bool create_v1_builtin =
- string_or_options.IsDictionary() &&
- RuntimeEnabledFeatures::CustomElementsBuiltinEnabled();
+ bool create_v1_builtin = string_or_options.IsDictionary();
bool should_create_builtin =
create_v1_builtin || string_or_options.IsString();
@@ -1014,7 +1027,7 @@ static inline QualifiedName CreateQualifiedName(
QualifiedName q_name(prefix, local_name, namespace_uri);
if (!Document::HasValidNamespaceForElements(q_name)) {
exception_state.ThrowDOMException(
- kNamespaceError,
+ DOMExceptionCode::kNamespaceError,
"The namespace URI provided ('" + namespace_uri +
"') is not valid for the qualified name provided ('" +
qualified_name + "').");
@@ -1045,6 +1058,9 @@ Element* Document::createElementNS(const AtomicString& namespace_uri,
const AtomicString& qualified_name,
const StringOrDictionary& string_or_options,
ExceptionState& exception_state) {
+ if (string_or_options.IsNull())
+ return createElementNS(namespace_uri, qualified_name, exception_state);
+
// 1. Validate and extract
QualifiedName q_name(
CreateQualifiedName(namespace_uri, qualified_name, exception_state));
@@ -1052,9 +1068,7 @@ Element* Document::createElementNS(const AtomicString& namespace_uri,
return nullptr;
bool is_v1 = string_or_options.IsDictionary() || !RegistrationContext();
- bool create_v1_builtin =
- string_or_options.IsDictionary() &&
- RuntimeEnabledFeatures::CustomElementsBuiltinEnabled();
+ bool create_v1_builtin = string_or_options.IsDictionary();
bool should_create_builtin =
create_v1_builtin || string_or_options.IsString();
@@ -1063,9 +1077,10 @@ Element* Document::createElementNS(const AtomicString& namespace_uri,
AtomicString(GetTypeExtension(this, string_or_options, exception_state));
if (!IsValidElementName(this, qualified_name)) {
- exception_state.ThrowDOMException(
- kInvalidCharacterError, "The tag name provided ('" + qualified_name +
- "') is not a valid name.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidCharacterError,
+ "The tag name provided ('" +
+ qualified_name +
+ "') is not a valid name.");
return nullptr;
}
@@ -1104,21 +1119,45 @@ Element* Document::CreateElement(const QualifiedName& q_name,
flags, is);
}
+ScriptPromise Document::createCSSStyleSheet(ScriptState* script_state,
+ const String& text,
+ ExceptionState& exception_state) {
+ return Document::createCSSStyleSheet(script_state, text, CSSStyleSheetInit(),
+ exception_state);
+}
+
+ScriptPromise Document::createCSSStyleSheet(ScriptState* script_state,
+ const String& text,
+ const CSSStyleSheetInit& options,
+ ExceptionState& exception_state) {
+ // Even though this function returns a Promise, it actually does all the work
+ // at once here because CSS parsing is done synchronously on the main thread.
+ // TODO(rakina): Find a way to improve this.
+ CSSStyleSheet* sheet = CSSStyleSheet::Create(*this, options, exception_state);
+ sheet->SetText(text);
+ return ScriptPromise::Cast(script_state,
+ ScriptValue::From(script_state, sheet));
+}
+
ScriptValue Document::registerElement(ScriptState* script_state,
const AtomicString& name,
const ElementRegistrationOptions& options,
ExceptionState& exception_state,
V0CustomElement::NameSet valid_names) {
- HostsUsingFeatures::CountMainWorldOnly(
- script_state, *this,
- HostsUsingFeatures::Feature::kDocumentRegisterElement);
-
if (!RegistrationContext()) {
exception_state.ThrowDOMException(
- kNotSupportedError, "No element registration context is available.");
+ DOMExceptionCode::kNotSupportedError,
+ "No element registration context is available.");
return ScriptValue();
}
+ // Polymer V1 uses Custom Elements V0. <dom-module> is defined in its base
+ // library and is a strong signal that this is a Polymer V1.
+ // This counter is used to research how much users are affected once Custom
+ // Element V0 is deprecated.
+ if (name == "dom-module")
+ UseCounter::Count(*this, WebFeature::kPolymerV1Detected);
+
V0CustomElementConstructorBuilder constructor_builder(script_state, options);
RegistrationContext()->RegisterElement(this, &constructor_builder, name,
valid_names, exception_state);
@@ -1203,12 +1242,12 @@ CDATASection* Document::createCDATASection(const String& data,
ExceptionState& exception_state) {
if (IsHTMLDocument()) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"This operation is not supported for HTML documents.");
return nullptr;
}
if (data.Contains("]]>")) {
- exception_state.ThrowDOMException(kInvalidCharacterError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidCharacterError,
"String cannot contain ']]>' since that "
"is the end delimiter of a CData "
"section.");
@@ -1223,13 +1262,13 @@ ProcessingInstruction* Document::createProcessingInstruction(
ExceptionState& exception_state) {
if (!IsValidName(target)) {
exception_state.ThrowDOMException(
- kInvalidCharacterError,
+ DOMExceptionCode::kInvalidCharacterError,
"The target provided ('" + target + "') is not a valid name.");
return nullptr;
}
if (data.Contains("?>")) {
exception_state.ThrowDOMException(
- kInvalidCharacterError,
+ DOMExceptionCode::kInvalidCharacterError,
"The data provided ('" + data + "') contains '?>'.");
return nullptr;
}
@@ -1253,7 +1292,7 @@ Node* Document::importNode(Node* imported_node,
// DOMException.
if (imported_node->IsDocumentNode()) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"The node provided is a document, which may not be imported.");
return nullptr;
}
@@ -1261,7 +1300,7 @@ Node* Document::importNode(Node* imported_node,
// ShadowRoot nodes should not be explicitly importable. Either they are
// imported along with their host node, or created implicitly.
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"The node provided is a shadow root, which may not be imported.");
return nullptr;
}
@@ -1277,7 +1316,7 @@ Node* Document::adoptNode(Node* source, ExceptionState& exception_state) {
switch (source->getNodeType()) {
case kDocumentNode:
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"The node provided is of type '" +
source->nodeName() +
"', which may not be adopted.");
@@ -1292,7 +1331,7 @@ Node* Document::adoptNode(Node* source, ExceptionState& exception_state) {
if (source->IsShadowRoot()) {
// ShadowRoot cannot disconnect itself from the host node.
exception_state.ThrowDOMException(
- kHierarchyRequestError,
+ DOMExceptionCode::kHierarchyRequestError,
"The node provided is a shadow root, which may not be adopted.");
return nullptr;
}
@@ -1303,7 +1342,7 @@ Node* Document::adoptNode(Node* source, ExceptionState& exception_state) {
if (GetFrame() && GetFrame()->Tree().IsDescendantOf(
frame_owner_element->ContentFrame())) {
exception_state.ThrowDOMException(
- kHierarchyRequestError,
+ DOMExceptionCode::kHierarchyRequestError,
"The node provided is a frame which contains this document.");
return nullptr;
}
@@ -1422,7 +1461,7 @@ void Document::setXMLVersion(const String& version,
ExceptionState& exception_state) {
if (!XMLDocumentParser::SupportsXMLVersion(version)) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"This document does not support the XML version '" + version + "'.");
return;
}
@@ -1583,6 +1622,9 @@ void Document::UpdateTitle(const String& title) {
if (!frame_ || old_title == title_)
return;
DispatchDidReceiveTitle();
+
+ if (AXObjectCache* cache = GetOrCreateAXObjectCache())
+ cache->DocumentTitleChanged();
}
void Document::DispatchDidReceiveTitle() {
@@ -1727,6 +1769,11 @@ void Document::DidChangeVisibilityState() {
if (hidden() && canvas_font_cache_)
canvas_font_cache_->PruneAll();
+
+ InteractiveDetector* interactive_detector = InteractiveDetector::From(*this);
+ if (interactive_detector) {
+ interactive_detector->OnPageVisibilityChanged(GetPageVisibilityState());
+ }
}
String Document::nodeName() const {
@@ -2030,9 +2077,6 @@ void Document::PropagateStyleToViewport() {
GetLayoutView()->SetStyle(new_style);
SetupFontBuilder(*new_style);
- View()->RecalculateScrollbarOverlayColorTheme(
- View()->DocumentBackgroundColor());
- View()->RecalculateCustomScrollbarStyle();
if (PaintLayerScrollableArea* scrollable_area =
GetLayoutView()->GetScrollableArea()) {
if (scrollable_area->HorizontalScrollbar() &&
@@ -2193,7 +2237,7 @@ void Document::UpdateStyle() {
TRACE_EVENT_BEGIN0("blink,blink_style", "Document::updateStyle");
RUNTIME_CALL_TIMER_SCOPE(V8PerIsolateData::MainThreadIsolate(),
RuntimeCallStats::CounterId::kUpdateStyle);
- double start_time = CurrentTimeTicksInSeconds();
+ TimeTicks start_time = CurrentTimeTicks();
unsigned initial_element_count = GetStyleEngine().StyleForElementCount();
@@ -2235,7 +2279,10 @@ void Document::UpdateStyle() {
if (document_element->ShouldCallRecalcStyle(change)) {
TRACE_EVENT0("blink,blink_style", "Document::recalcStyle");
Element* viewport_defining = ViewportDefiningElement();
+ ReattachLegacyLayoutObjectList legacy_layout_objects(*this);
+ legacy_layout_objects.WillRecalcStyle();
document_element->RecalcStyle(change);
+ legacy_layout_objects.DidRecalcStyle();
if (viewport_defining != ViewportDefiningElement())
ViewportDefiningElementDidChange();
}
@@ -2244,14 +2291,16 @@ void Document::UpdateStyle() {
if (document_element->NeedsReattachLayoutTree() ||
document_element->ChildNeedsReattachLayoutTree()) {
TRACE_EVENT0("blink,blink_style", "Document::rebuildLayoutTree");
+ ReattachLegacyLayoutObjectList legacy_layout_objects(*this);
WhitespaceAttacher whitespace_attacher;
document_element->RebuildLayoutTree(whitespace_attacher);
+ legacy_layout_objects.ForceLegacyLayoutIfNeeded();
}
}
GetStyleEngine().ClearWhitespaceReattachSet();
View()->UpdateCountersAfterStyleChange();
- View()->RecalcOverflowAfterStyleChange();
+ GetLayoutView()->RecalcOverflowAfterStyleChange();
ClearChildNeedsStyleRecalc();
ClearChildNeedsReattachLayoutTree();
@@ -2274,11 +2323,9 @@ void Document::UpdateStyle() {
GetStyleEngine().StyleForElementCount() - initial_element_count);
}
- double update_duration_seconds = CurrentTimeTicksInSeconds() - start_time;
DEFINE_STATIC_LOCAL(CustomCountHistogram, update_histogram,
("Style.UpdateTime", 0, 10000000, 50));
- update_histogram.Count(update_duration_seconds * 1000 * 1000);
- CSSTiming::From(*this).RecordUpdateDuration(update_duration_seconds);
+ update_histogram.CountMicroseconds(CurrentTimeTicks() - start_time);
}
void Document::ViewportDefiningElementDidChange() {
@@ -2295,6 +2342,15 @@ void Document::ViewportDefiningElementDidChange() {
// ViewportDefiningElement changes in order to trigger an update of
// HasOverflowClip() and the PaintLayer in StyleDidChange().
layout_object->SetStyle(ComputedStyle::Clone(*layout_object->Style()));
+ // CompositingReason::kClipsCompositingDescendants depends on the root
+ // element having a clip-related style. Since style update due to changes of
+ // viewport-defining element don't end up as a StyleDifference, we need a
+ // special dirty bit for this situation.
+ if (layout_object->HasLayer()) {
+ ToLayoutBoxModelObject(layout_object)
+ ->Layer()
+ ->SetNeeedsCompositingReasonsUpdate();
+ }
}
}
@@ -2635,8 +2691,12 @@ void Document::Initialize() {
layout_view_->Compositor()->SetNeedsCompositingUpdate(
kCompositingUpdateAfterCompositingInputChange);
- AttachContext context;
- ContainerNode::AttachLayoutTree(context);
+ {
+ ReattachLegacyLayoutObjectList legacy_layout_objects(*this);
+ AttachContext context;
+ ContainerNode::AttachLayoutTree(context);
+ legacy_layout_objects.ForceLegacyLayoutIfNeeded();
+ }
// The TextAutosizer can't update layout view info while the Document is
// detached, so update now in case anything changed.
@@ -2661,6 +2721,8 @@ void Document::Shutdown() {
if (!IsActive())
return;
+ GetViewportData().Shutdown();
+
// Frame navigation can cause a new Document to be attached. Don't allow that,
// since that will cause a situation where LocalFrame still has a Document
// attached after this finishes! Normally, it shouldn't actually be possible
@@ -2713,11 +2775,6 @@ void Document::Shutdown() {
if (SvgExtensions())
AccessSVGExtensions().PauseAnimations();
- // FIXME: This shouldn't be needed once LocalDOMWindow becomes
- // ExecutionContext.
- if (dom_window_)
- dom_window_->ClearEventQueue();
-
if (layout_view_)
layout_view_->SetIsInWindow(false);
@@ -2932,19 +2989,20 @@ void Document::open(Document* entered_document,
ExceptionState& exception_state) {
if (ImportLoader()) {
exception_state.ThrowDOMException(
- kInvalidStateError, "Imported document doesn't support open().");
+ DOMExceptionCode::kInvalidStateError,
+ "Imported document doesn't support open().");
return;
}
if (!IsHTMLDocument()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Only HTML documents support open().");
return;
}
if (throw_on_dynamic_markup_insertion_count_) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Custom Element constructor should not use open().");
return;
}
@@ -3099,19 +3157,19 @@ void Document::setBody(HTMLElement* prp_new_body,
if (!new_body) {
exception_state.ThrowDOMException(
- kHierarchyRequestError,
+ DOMExceptionCode::kHierarchyRequestError,
ExceptionMessages::ArgumentNullOrIncorrectType(1, "HTMLElement"));
return;
}
if (!documentElement()) {
- exception_state.ThrowDOMException(kHierarchyRequestError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kHierarchyRequestError,
"No document element exists.");
return;
}
if (!IsHTMLBodyElement(*new_body) && !IsHTMLFrameSetElement(*new_body)) {
exception_state.ThrowDOMException(
- kHierarchyRequestError,
+ DOMExceptionCode::kHierarchyRequestError,
"The new body element is of type '" + new_body->tagName() +
"'. It must be either a 'BODY' or 'FRAMESET' element.");
return;
@@ -3128,9 +3186,6 @@ void Document::setBody(HTMLElement* prp_new_body,
}
void Document::WillInsertBody() {
- if (GetFrame())
- GetFrame()->Client()->DispatchWillInsertBody();
-
if (auto* loader = Loader())
loader->Fetcher()->LoosenLoadThrottlingPolicy();
@@ -3179,8 +3234,7 @@ Document* Document::open(LocalDOMWindow* entered_window,
const AtomicString& replace,
ExceptionState& exception_state) {
if (replace == "replace") {
- UseCounter::Count(entered_window->document(),
- WebFeature::kDocumentOpenTwoArgsWithReplace);
+ UseCounter::Count(Loader(), WebFeature::kDocumentOpenTwoArgsWithReplace);
}
open(entered_window->document(), exception_state);
return this;
@@ -3188,17 +3242,18 @@ Document* Document::open(LocalDOMWindow* entered_window,
DOMWindow* Document::open(LocalDOMWindow* current_window,
LocalDOMWindow* entered_window,
- const AtomicString& url,
+ const USVStringOrTrustedURL& stringOrUrl,
const AtomicString& name,
const AtomicString& features,
ExceptionState& exception_state) {
if (!domWindow()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The document has no window associated.");
return nullptr;
}
AtomicString frame_name = name.IsEmpty() ? "_blank" : name;
- return domWindow()->open(url, frame_name, features, current_window,
+
+ return domWindow()->open(stringOrUrl, frame_name, features, current_window,
entered_window, exception_state);
}
@@ -3208,19 +3263,20 @@ void Document::close(ExceptionState& exception_state) {
if (ImportLoader()) {
exception_state.ThrowDOMException(
- kInvalidStateError, "Imported document doesn't support close().");
+ DOMExceptionCode::kInvalidStateError,
+ "Imported document doesn't support close().");
return;
}
if (!IsHTMLDocument()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Only HTML documents support close().");
return;
}
if (throw_on_dynamic_markup_insertion_count_) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Custom Element constructor should not use close().");
return;
}
@@ -3335,21 +3391,31 @@ bool Document::ShouldComplete() {
AllDescendantsAreComplete(frame_);
}
+void Document::Abort() {
+ CancelParsing();
+ CheckCompletedInternal();
+}
+
void Document::CheckCompleted() {
+ if (CheckCompletedInternal())
+ frame_->Loader().DidFinishNavigation();
+}
+
+bool Document::CheckCompletedInternal() {
if (!ShouldComplete())
- return;
+ return false;
if (frame_) {
frame_->Client()->RunScriptsAtDocumentIdle();
// Injected scripts may have disconnected this frame.
if (!frame_)
- return;
+ return false;
// Check again, because runScriptsAtDocumentIdle() may have delayed the load
// event.
if (!ShouldComplete())
- return;
+ return false;
}
// OK, completed. Fire load completion events as needed.
@@ -3359,7 +3425,7 @@ void Document::CheckCompleted() {
// The readystatechanged or load event may have disconnected this frame.
if (!frame_ || !frame_->IsAttached())
- return;
+ return false;
if (frame_->GetSettings()->GetSavePreviousDocumentResources() ==
SavePreviousDocumentResources::kUntilOnLoad) {
fetcher_->ClearResourcesFromPreviousFetcher();
@@ -3369,16 +3435,16 @@ void Document::CheckCompleted() {
// The document itself is complete, but if a child frame was restarted due to
// an event, this document is still considered to be in progress.
if (!AllDescendantsAreComplete(frame_))
- return;
+ return false;
// No need to repeat if we've already notified this load as finished.
if (!Loader()->SentDidFinishLoad()) {
if (frame_->IsMainFrame())
- GetViewportDescription().ReportMobilePageStats(frame_);
+ GetViewportData().GetViewportDescription().ReportMobilePageStats(frame_);
Loader()->SetSentDidFinishLoad();
frame_->Client()->DispatchDidFinishLoad();
if (!frame_)
- return;
+ return false;
// Send the source ID of the document to the browser.
if (frame_->Client()->GetRemoteNavigationAssociatedInterfaces()) {
@@ -3390,7 +3456,7 @@ void Document::CheckCompleted() {
}
}
- frame_->Loader().DidFinishNavigation();
+ return true;
}
bool Document::DispatchBeforeUnloadEvent(ChromeClient& chrome_client,
@@ -3408,15 +3474,15 @@ bool Document::DispatchBeforeUnloadEvent(ChromeClient& chrome_client,
BeforeUnloadEvent* before_unload_event = BeforeUnloadEvent::Create();
before_unload_event->initEvent(EventTypeNames::beforeunload, false, true);
load_event_progress_ = kBeforeUnloadEventInProgress;
- const double beforeunload_event_start = CurrentTimeTicksInSeconds();
+ const TimeTicks beforeunload_event_start = CurrentTimeTicks();
dom_window_->DispatchEvent(before_unload_event, this);
- const double beforeunload_event_end = CurrentTimeTicksInSeconds();
+ const TimeTicks beforeunload_event_end = CurrentTimeTicks();
load_event_progress_ = kBeforeUnloadEventCompleted;
DEFINE_STATIC_LOCAL(
CustomCountHistogram, beforeunload_histogram,
("DocumentEventTiming.BeforeUnloadDuration", 0, 10000000, 50));
- beforeunload_histogram.Count(
- (beforeunload_event_end - beforeunload_event_start) * 1000000.0);
+ beforeunload_histogram.CountMicroseconds(beforeunload_event_end -
+ beforeunload_event_start);
if (!before_unload_event->defaultPrevented())
DefaultEventHandler(before_unload_event);
@@ -3437,21 +3503,21 @@ bool Document::DispatchBeforeUnloadEvent(ChromeClient& chrome_client,
if (!GetFrame()->HasBeenActivated()) {
beforeunload_dialog_histogram.Count(kNoDialogNoUserGesture);
- AddConsoleMessage(ConsoleMessage::Create(
- kInterventionMessageSource, kErrorMessageLevel,
+ String message =
"Blocked attempt to show a 'beforeunload' confirmation panel for a "
"frame that never had a user gesture since its load. "
- "https://www.chromestatus.com/feature/5082396709879808"));
+ "https://www.chromestatus.com/feature/5082396709879808";
+ Intervention::GenerateReport(frame_, "BeforeUnloadNoGesture", message);
return true;
}
if (did_allow_navigation) {
beforeunload_dialog_histogram.Count(
kNoDialogMultipleConfirmationForNavigation);
- AddConsoleMessage(ConsoleMessage::Create(
- kInterventionMessageSource, kErrorMessageLevel,
+ String message =
"Blocked attempt to show multiple 'beforeunload' confirmation panels "
- "for a single navigation."));
+ "for a single navigation.";
+ Intervention::GenerateReport(frame_, "BeforeUnloadMultiple", message);
return true;
}
String text = before_unload_event->returnValue();
@@ -3480,15 +3546,15 @@ void Document::DispatchUnloadEvents() {
if (load_event_progress_ < kPageHideInProgress) {
load_event_progress_ = kPageHideInProgress;
if (LocalDOMWindow* window = domWindow()) {
- const double pagehide_event_start = CurrentTimeTicksInSeconds();
+ const TimeTicks pagehide_event_start = CurrentTimeTicks();
window->DispatchEvent(
PageTransitionEvent::Create(EventTypeNames::pagehide, false), this);
- const double pagehide_event_end = CurrentTimeTicksInSeconds();
+ const TimeTicks pagehide_event_end = CurrentTimeTicks();
DEFINE_STATIC_LOCAL(
CustomCountHistogram, pagehide_histogram,
("DocumentEventTiming.PageHideDuration", 0, 10000000, 50));
- pagehide_histogram.Count((pagehide_event_end - pagehide_event_start) *
- 1000000.0);
+ pagehide_histogram.CountMicroseconds(pagehide_event_end -
+ pagehide_event_start);
}
if (!frame_)
return;
@@ -3498,17 +3564,15 @@ void Document::DispatchUnloadEvents() {
if (visibility_state != mojom::PageVisibilityState::kHidden) {
// Dispatch visibilitychange event, but don't bother doing
// other notifications as we're about to be unloaded.
- const double pagevisibility_hidden_event_start =
- CurrentTimeTicksInSeconds();
+ const TimeTicks pagevisibility_hidden_event_start = CurrentTimeTicks();
DispatchEvent(Event::CreateBubble(EventTypeNames::visibilitychange));
- const double pagevisibility_hidden_event_end =
- CurrentTimeTicksInSeconds();
+ const TimeTicks pagevisibility_hidden_event_end = CurrentTimeTicks();
DEFINE_STATIC_LOCAL(CustomCountHistogram, pagevisibility_histogram,
("DocumentEventTiming.PageVibilityHiddenDuration",
0, 10000000, 50));
- pagevisibility_histogram.Count((pagevisibility_hidden_event_end -
- pagevisibility_hidden_event_start) *
- 1000000.0);
+ pagevisibility_histogram.CountMicroseconds(
+ pagevisibility_hidden_event_end -
+ pagevisibility_hidden_event_start);
DispatchEvent(
Event::CreateBubble(EventTypeNames::webkitvisibilitychange));
}
@@ -3533,8 +3597,8 @@ void Document::DispatchUnloadEvents() {
DEFINE_STATIC_LOCAL(
CustomCountHistogram, unload_histogram,
("DocumentEventTiming.UnloadDuration", 0, 10000000, 50));
- unload_histogram.Count(
- (unload_event_end - unload_event_start).InMicroseconds());
+ unload_histogram.CountMicroseconds(unload_event_end -
+ unload_event_start);
timing.MarkUnloadEventEnd(unload_event_end);
} else {
frame_->DomWindow()->DispatchEvent(unload_event, frame_->GetDocument());
@@ -3551,21 +3615,24 @@ void Document::DispatchUnloadEvents() {
bool keep_event_listeners =
frame_->Loader().GetProvisionalDocumentLoader() &&
frame_->ShouldReuseDefaultView(
- frame_->Loader().GetProvisionalDocumentLoader()->Url());
+ frame_->Loader().GetProvisionalDocumentLoader()->Url(),
+ frame_->Loader()
+ .GetProvisionalDocumentLoader()
+ ->GetContentSecurityPolicy());
if (!keep_event_listeners)
RemoveAllEventListenersRecursively();
}
void Document::DispatchFreezeEvent() {
DCHECK(RuntimeEnabledFeatures::PageLifecycleEnabled());
- const double freeze_event_start = CurrentTimeTicksInSeconds();
+ const TimeTicks freeze_event_start = CurrentTimeTicks();
SetFreezingInProgress(true);
DispatchEvent(Event::Create(EventTypeNames::freeze));
SetFreezingInProgress(false);
- const double freeze_event_end = CurrentTimeTicksInSeconds();
+ const TimeTicks freeze_event_end = CurrentTimeTicks();
DEFINE_STATIC_LOCAL(CustomCountHistogram, freeze_histogram,
("DocumentEventTiming.FreezeDuration", 0, 10000000, 50));
- freeze_histogram.Count((freeze_event_end - freeze_event_start) * 1000000.0);
+ freeze_histogram.CountMicroseconds(freeze_event_end - freeze_event_start);
}
Document::PageDismissalType Document::PageDismissalEventBeingDispatched()
@@ -3643,19 +3710,20 @@ void Document::write(const String& text,
ExceptionState& exception_state) {
if (ImportLoader()) {
exception_state.ThrowDOMException(
- kInvalidStateError, "Imported document doesn't support write().");
+ DOMExceptionCode::kInvalidStateError,
+ "Imported document doesn't support write().");
return;
}
if (!IsHTMLDocument()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Only HTML documents support write().");
return;
}
if (throw_on_dynamic_markup_insertion_count_) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Custom Element constructor should not use write().");
return;
}
@@ -3697,7 +3765,7 @@ void Document::write(const String& text,
DCHECK(parser_);
PerformanceMonitor::ReportGenericViolation(
this, PerformanceMonitor::kDiscouragedAPIUse,
- "Avoid using document.write().", 0, nullptr);
+ "Avoid using document.write().", base::TimeDelta(), nullptr);
probe::breakableLocation(this, "Document.write");
parser_->insert(text);
}
@@ -4050,63 +4118,20 @@ void Document::MaybeHandleHttpRefresh(const String& content,
http_refresh_type);
}
-bool Document::ShouldMergeWithLegacyDescription(
- ViewportDescription::Type origin) const {
- return GetSettings() && GetSettings()->GetViewportMetaMergeContentQuirk() &&
- legacy_viewport_description_.IsMetaViewportType() &&
- legacy_viewport_description_.type == origin;
-}
-
-void Document::SetViewportDescription(
- const ViewportDescription& viewport_description) {
- if (viewport_description.IsLegacyViewportType()) {
- if (viewport_description == legacy_viewport_description_)
- return;
- legacy_viewport_description_ = viewport_description;
- } else {
- if (viewport_description == viewport_description_)
- return;
- viewport_description_ = viewport_description;
-
- // The UA-defined min-width is considered specifically by Android WebView
- // quirks mode.
- if (!viewport_description.IsSpecifiedByAuthor())
- viewport_default_min_width_ = viewport_description.min_width;
- }
-
- UpdateViewportDescription();
-}
-
-ViewportDescription Document::GetViewportDescription() const {
- ViewportDescription applied_viewport_description = viewport_description_;
- bool viewport_meta_enabled =
- GetSettings() && GetSettings()->GetViewportMetaEnabled();
- if (legacy_viewport_description_.type !=
- ViewportDescription::kUserAgentStyleSheet &&
- viewport_meta_enabled)
- applied_viewport_description = legacy_viewport_description_;
- if (ShouldOverrideLegacyDescription(viewport_description_.type))
- applied_viewport_description = viewport_description_;
-
- return applied_viewport_description;
-}
+// https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer
+String Document::OutgoingReferrer() const {
+ // Step 3.1: "If environment's global object is a Window object, then"
-void Document::UpdateViewportDescription() {
- if (GetFrame() && GetFrame()->IsMainFrame()) {
- GetPage()->GetChromeClient().DispatchViewportPropertiesDidChange(
- GetViewportDescription());
- }
-}
+ // Step 3.1.1: "Let document be the associated Document of environment's
+ // global object."
+ const Document* referrer_document = this;
-String Document::OutgoingReferrer() const {
- if (GetSecurityOrigin()->IsUnique()) {
- // Return |no-referrer|.
+ // Step 3.1.2: "If document's origin is an opaque origin, return no referrer."
+ if (GetSecurityOrigin()->IsOpaque())
return String();
- }
- // See http://www.whatwg.org/specs/web-apps/current-work/#fetching-resources
- // for why we walk the parent chain for srcdoc documents.
- const Document* referrer_document = this;
+ // Step 3.1.3: "While document is an iframe srcdoc document, let document be
+ // document's browsing context's browsing context container's node document."
if (LocalFrame* frame = frame_) {
while (frame->GetDocument()->IsSrcdocDocument()) {
// Srcdoc documents must be local within the containing frame.
@@ -4117,6 +4142,8 @@ String Document::OutgoingReferrer() const {
}
referrer_document = frame->GetDocument();
}
+
+ // Step: 3.1.4: "Let referrerSource be document's URL."
return referrer_document->url_.StrippedForUseAsReferrer();
}
@@ -4146,12 +4173,15 @@ MouseEventWithHitTestResults Document::PerformMouseEventHitTest(
// page. Furthermore, mousemove events before the first layout should not
// lead to a premature layout() happening, which could show a flash of white.
// See also the similar code in EventHandler::hitTestResultAtPoint.
- if (!GetLayoutView() || !View() || !View()->DidFirstLayout())
- return MouseEventWithHitTestResults(event,
- HitTestResult(request, LayoutPoint()));
+ if (!GetLayoutView() || !View() || !View()->DidFirstLayout()) {
+ HitTestLocation location((LayoutPoint()));
+ return MouseEventWithHitTestResults(event, location,
+ HitTestResult(request, location));
+ }
- HitTestResult result(request, document_point);
- GetLayoutView()->HitTest(result);
+ HitTestLocation location(document_point);
+ HitTestResult result(request, location);
+ GetLayoutView()->HitTest(location, result);
if (!request.ReadOnly())
UpdateHoverActiveState(request, result.InnerElement());
@@ -4166,7 +4196,7 @@ MouseEventWithHitTestResults Document::PerformMouseEventHitTest(
result.SetCanvasRegionId(hit_test_canvas_result->GetId());
}
- return MouseEventWithHitTestResults(event, result);
+ return MouseEventWithHitTestResults(event, location, result);
}
// DOM Section 1.1.1
@@ -4273,7 +4303,7 @@ bool Document::CanAcceptChild(const Node& new_child,
case kDocumentNode:
case kTextNode:
exception_state.ThrowDOMException(
- kHierarchyRequestError,
+ DOMExceptionCode::kHierarchyRequestError,
"Nodes of type '" + new_child.nodeName() +
"' may not be inserted inside nodes of type '#document'.");
return false;
@@ -4287,7 +4317,7 @@ bool Document::CanAcceptChild(const Node& new_child,
num_elements++;
if (has_doctype_after_reference_node) {
exception_state.ThrowDOMException(
- kHierarchyRequestError,
+ DOMExceptionCode::kHierarchyRequestError,
"Can't insert an element before a doctype.");
return false;
}
@@ -4302,7 +4332,7 @@ bool Document::CanAcceptChild(const Node& new_child,
case kDocumentNode:
case kTextNode:
exception_state.ThrowDOMException(
- kHierarchyRequestError,
+ DOMExceptionCode::kHierarchyRequestError,
"Nodes of type '" + new_child.nodeName() +
"' may not be inserted inside nodes of type '#document'.");
return false;
@@ -4313,7 +4343,7 @@ bool Document::CanAcceptChild(const Node& new_child,
num_doctypes++;
if (num_elements > 0 && !has_element_after_reference_node) {
exception_state.ThrowDOMException(
- kHierarchyRequestError,
+ DOMExceptionCode::kHierarchyRequestError,
"Can't insert a doctype before the root element.");
return false;
}
@@ -4322,7 +4352,7 @@ bool Document::CanAcceptChild(const Node& new_child,
num_elements++;
if (has_doctype_after_reference_node) {
exception_state.ThrowDOMException(
- kHierarchyRequestError,
+ DOMExceptionCode::kHierarchyRequestError,
"Can't insert an element before a doctype.");
return false;
}
@@ -4332,7 +4362,7 @@ bool Document::CanAcceptChild(const Node& new_child,
if (num_elements > 1 || num_doctypes > 1) {
exception_state.ThrowDOMException(
- kHierarchyRequestError,
+ DOMExceptionCode::kHierarchyRequestError,
String::Format("Only one %s on document allowed.",
num_elements > 1 ? "element" : "doctype"));
return false;
@@ -4463,8 +4493,14 @@ void Document::HoveredElementDetached(Element& element) {
if (element != hover_element_)
return;
- hover_element_->UpdateDistributionForUnknownReasons();
- hover_element_ = SkipDisplayNoneAncestors(&element);
+ // While in detaching, we shouldn't use FlatTreeTraversal if slot assignemnt
+ // is dirty because it might triger assignement recalc. hover_element_ will be
+ // updated after recalc assignment is calculated (and re-layout is done).
+ if (IsSlotAssignmentOrLegacyDistributionDirty()) {
+ hover_element_ = nullptr;
+ } else {
+ hover_element_ = SkipDisplayNoneAncestors(&element);
+ }
// If the mouse cursor is not visible, do not clear existing
// hover effects on the ancestors of |element| and do not invoke
@@ -4491,6 +4527,10 @@ void Document::SetAnnotatedRegions(
SetAnnotatedRegionsDirty(false);
}
+void Document::SetLastFocusType(WebFocusType last_focus_type) {
+ last_focus_type_ = last_focus_type;
+}
+
bool Document::SetFocusedElement(Element* new_focused_element,
const FocusParams& params) {
DCHECK(!lifecycle_.InDetach());
@@ -4520,7 +4560,6 @@ bool Document::SetFocusedElement(Element* new_focused_element,
// Remove focus from the existing focus node (if any)
if (old_focused_element) {
- old_focused_element->SetWasFocusedByMouse(false);
old_focused_element->SetFocused(false, params.type);
old_focused_element->SetHasFocusWithinUpToAncestor(false, ancestor);
@@ -4569,7 +4608,10 @@ bool Document::SetFocusedElement(Element* new_focused_element,
focused_element_ = new_focused_element;
SetSequentialFocusNavigationStartingPoint(focused_element_.Get());
- focused_element_->SetWasFocusedByMouse(params.type == kWebFocusTypeMouse);
+ // Keep track of last focus from user interaction, ignoring focus from code.
+ if (params.type != kWebFocusTypeNone)
+ last_focus_type_ = params.type;
+
focused_element_->SetFocused(true, params.type);
focused_element_->SetHasFocusWithinUpToAncestor(true, ancestor);
@@ -4873,12 +4915,6 @@ EventListener* Document::GetWindowAttributeEventListener(
return dom_window->GetAttributeEventListener(event_type);
}
-EventQueue* Document::GetEventQueue() const {
- if (!dom_window_)
- return nullptr;
- return dom_window_->GetEventQueue();
-}
-
void Document::EnqueueAnimationFrameTask(base::OnceClosure task) {
EnsureScriptedAnimationController().EnqueueTask(std::move(task));
}
@@ -4997,13 +5033,13 @@ Event* Document::createEvent(ScriptState* script_state,
// createEvent for TouchEvent should throw DOM exception if touch event
// feature detection is not enabled. See crbug.com/392584#c22
if (DeprecatedEqualIgnoringCase(event_type, "TouchEvent") &&
- !OriginTrials::touchEventFeatureDetectionEnabled(execution_context))
+ !OriginTrials::TouchEventFeatureDetectionEnabled(execution_context))
break;
return event;
}
}
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"The provided event type ('" + event_type + "') is invalid.");
return nullptr;
}
@@ -5188,6 +5224,12 @@ void Document::setDomain(const String& raw_domain,
ExceptionState& exception_state) {
UseCounter::Count(*this, WebFeature::kDocumentSetDomain);
+ if (!frame_) {
+ exception_state.ThrowSecurityError(
+ "A browsing context is required to set a domain.");
+ return;
+ }
+
if (IsSandboxed(kSandboxDocumentDomain)) {
exception_state.ThrowSecurityError(
"Assignment is forbidden for sandboxed iframes.");
@@ -5437,7 +5479,7 @@ static ParseQualifiedNameResult ParseQualifiedNameInternal(
AtomicString& local_name) {
bool name_start = true;
bool saw_colon = false;
- int colon_pos = 0;
+ unsigned colon_pos = 0;
for (unsigned i = 0; i < length;) {
UChar32 c;
@@ -5482,7 +5524,7 @@ bool Document::ParseQualifiedName(const AtomicString& qualified_name,
unsigned length = qualified_name.length();
if (!length) {
- exception_state.ThrowDOMException(kInvalidCharacterError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidCharacterError,
"The qualified name provided is empty.");
return false;
}
@@ -5521,7 +5563,8 @@ bool Document::ParseQualifiedName(const AtomicString& qualified_name,
message.Append("has an empty local name.");
}
- exception_state.ThrowDOMException(kInvalidCharacterError, message.ToString());
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidCharacterError,
+ message.ToString());
return false;
}
@@ -5538,8 +5581,9 @@ void Document::SetEncodingData(const DocumentEncodingData& new_data) {
title_element_->textContent().ContainsOnlyLatin1()) {
CString original_bytes = title_element_->textContent().Latin1();
std::unique_ptr<TextCodec> codec = NewTextCodec(new_data.Encoding());
- String correctly_decoded_title = codec->Decode(
- original_bytes.data(), original_bytes.length(), WTF::kDataEOF);
+ String correctly_decoded_title =
+ codec->Decode(original_bytes.data(), original_bytes.length(),
+ WTF::FlushBehavior::kDataEOF);
title_element_->setTextContent(correctly_decoded_title);
}
@@ -5730,7 +5774,7 @@ Attr* Document::createAttributeNS(const AtomicString& namespace_uri,
if (!should_ignore_namespace_checks &&
!HasValidNamespaceForAttributes(q_name)) {
exception_state.ThrowDOMException(
- kNamespaceError,
+ DOMExceptionCode::kNamespaceError,
"The namespace URI provided ('" + namespace_uri +
"') is not valid for the qualified name provided ('" +
qualified_name + "').");
@@ -6039,17 +6083,21 @@ void Document::ApplyFeaturePolicy(const ParsedFeaturePolicy& declared_policy) {
InitializeFeaturePolicy(declared_policy, container_policy,
parent_feature_policy);
+
+ is_vertical_scroll_enforced_ =
+ RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled() &&
+ !GetFeaturePolicy()->IsFeatureEnabled(
+ mojom::FeaturePolicyFeature::kVerticalScroll);
}
bool Document::AllowedToUseDynamicMarkUpInsertion(
const char* api_name,
ExceptionState& exception_state) {
- if (!IsSupportedInFeaturePolicy(
- mojom::FeaturePolicyFeature::kDocumentStreamInsertion)) {
+ if (!RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled()) {
return true;
}
- if (!frame_ || frame_->IsFeatureEnabled(
- mojom::FeaturePolicyFeature::kDocumentStreamInsertion)) {
+ if (!frame_ ||
+ frame_->IsFeatureEnabled(mojom::FeaturePolicyFeature::kDocumentWrite)) {
return true;
}
@@ -6058,11 +6106,11 @@ bool Document::AllowedToUseDynamicMarkUpInsertion(
// origin as there are security risks involved. We should perhaps unload the
// whole frame instead of throwing.
exception_state.ThrowDOMException(
- kNotAllowedError,
+ DOMExceptionCode::kNotAllowedError,
String::Format(
"The use of method '%s' has been blocked by feature policy. The "
"feature "
- "'document-stream-insertion' is disabled in this document.",
+ "'document-write' is disabled in this document.",
api_name));
return false;
}
@@ -6092,7 +6140,7 @@ void Document::InitSecurityContext(const DocumentInit& initializer) {
// No source for a security context.
// This can occur via document.implementation.createDocument().
cookie_url_ = KURL(g_empty_string);
- SetSecurityOrigin(SecurityOrigin::CreateUnique());
+ SetSecurityOrigin(SecurityOrigin::CreateUniqueOpaque());
InitContentSecurityPolicy();
ApplyFeaturePolicy({});
return;
@@ -6123,7 +6171,7 @@ void Document::InitSecurityContext(const DocumentInit& initializer) {
if (IsSandboxed(kSandboxOrigin)) {
cookie_url_ = url_;
scoped_refptr<SecurityOrigin> security_origin =
- SecurityOrigin::CreateUnique();
+ SecurityOrigin::CreateUniqueOpaque();
// If we're supposed to inherit our security origin from our
// owner, but we're also sandboxed, the only things we inherit are
// the origin's potential trustworthiness and the ability to
@@ -6489,10 +6537,7 @@ void Document::AddConsoleMessage(ConsoleMessage* console_message) {
console_message->SetNodes(frame_, std::move(nodes));
}
- if (console_message->Source() == kInterventionMessageSource)
- Intervention::GenerateReport(frame_, console_message->Message());
- else
- frame_->Console().AddMessage(console_message);
+ frame_->Console().AddMessage(console_message);
}
void Document::TasksWerePaused() {
@@ -6679,10 +6724,6 @@ void Document::CancelIdleCallback(int id) {
scripted_idle_task_controller_->CancelCallback(id);
}
-TouchList* Document::createTouchList(HeapVector<Member<Touch>>& touches) const {
- return TouchList::Adopt(touches);
-}
-
DocumentLoader* Document::Loader() const {
if (!frame_)
return nullptr;
@@ -6714,10 +6755,7 @@ void Document::AdjustFloatQuadsForScrollAndAbsoluteZoom(
if (!View())
return;
- LayoutRect visible_content_rect(View()->VisibleContentRect());
for (size_t i = 0; i < quads.size(); ++i) {
- quads[i].Move(-FloatSize(visible_content_rect.X().ToFloat(),
- visible_content_rect.Y().ToFloat()));
AdjustForAbsoluteZoom::AdjustFloatQuad(quads[i], layout_object);
}
}
@@ -6728,9 +6766,6 @@ void Document::AdjustFloatRectForScrollAndAbsoluteZoom(
if (!View())
return;
- LayoutRect visible_content_rect(View()->VisibleContentRect());
- rect.Move(-FloatSize(visible_content_rect.X().ToFloat(),
- visible_content_rect.Y().ToFloat()));
AdjustForAbsoluteZoom::AdjustFloatRect(rect, layout_object);
}
@@ -7138,6 +7173,17 @@ void Document::DidEnforceInsecureNavigationsSet() {
*InsecureNavigationsToUpgrade()));
}
+void Document::CountDetachingNodeAccessInDOMNodeRemovedHandler() {
+ auto state = GetInDOMNodeRemovedHandlerState();
+ DCHECK_NE(state, InDOMNodeRemovedHandlerState::kNone);
+ UseCounter::Count(
+ *this,
+ state == InDOMNodeRemovedHandlerState::kDOMNodeRemoved
+ ? WebFeature::kDOMNodeRemovedEventHandlerAccessDetachingNode
+ : WebFeature::
+ kDOMNodeRemovedFromDocumentEventHandlerAccessDetachingNode);
+}
+
void Document::SetShadowCascadeOrder(ShadowCascadeOrder order) {
DCHECK_NE(order, ShadowCascadeOrder::kShadowCascadeNone);
if (order == shadow_cascade_order_)
@@ -7233,7 +7279,7 @@ service_manager::InterfaceProvider* Document::GetInterfaceProvider() {
return &GetFrame()->GetInterfaceProvider();
}
-FrameScheduler* Document::GetScheduler() {
+FrameOrWorkerScheduler* Document::GetScheduler() {
DCHECK(IsMainThread());
if (ContextDocument() && ContextDocument()->GetFrame())
@@ -7349,6 +7395,7 @@ void Document::Trace(blink::Visitor* visitor) {
visitor->Trace(network_state_observer_);
visitor->Trace(policy_);
visitor->Trace(slot_assignment_engine_);
+ visitor->Trace(viewport_data_);
Supplementable<Document>::Trace(visitor);
TreeScope::Trace(visitor);
ContainerNode::Trace(visitor);
@@ -7401,23 +7448,14 @@ SlotAssignmentEngine& Document::GetSlotAssignmentEngine() {
return *slot_assignment_engine_;
}
-void Document::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- // node_lists_ are traced in their corresponding NodeListsNodeData, keeping
- // them only alive for live nodes. Otherwise we would keep lists of dead
- // nodes alive that have not yet been invalidated.
- visitor->TraceWrappers(dom_window_);
- visitor->TraceWrappers(imports_controller_);
- visitor->TraceWrappers(parser_);
- visitor->TraceWrappers(implementation_);
- visitor->TraceWrappers(style_sheet_list_);
- visitor->TraceWrappers(style_engine_);
- visitor->TraceWrappers(script_runner_);
- visitor->TraceWrappers(scripted_animation_controller_);
- visitor->TraceWrappers(scripted_idle_task_controller_);
- visitor->TraceWrappers(intersection_observer_controller_);
- ContainerNode::TraceWrappers(visitor);
- ExecutionContext::TraceWrappers(visitor);
- Supplementable<Document>::TraceWrappers(visitor);
+bool Document::IsSlotAssignmentOrLegacyDistributionDirty() {
+ if (ChildNeedsDistributionRecalc())
+ return true;
+ if (RuntimeEnabledFeatures::IncrementalShadowDOMEnabled() &&
+ GetSlotAssignmentEngine().HasPendingSlotAssignmentRecalc()) {
+ return true;
+ }
+ return false;
}
template class CORE_TEMPLATE_EXPORT Supplement<Document>;
diff --git a/chromium/third_party/blink/renderer/core/dom/document.h b/chromium/third_party/blink/renderer/core/dom/document.h
index 13bc7ba2c49..9fdbca84a36 100644
--- a/chromium/third_party/blink/renderer/core/dom/document.h
+++ b/chromium/third_party/blink/renderer/core/dom/document.h
@@ -34,50 +34,46 @@
#include <utility>
#include "base/memory/scoped_refptr.h"
-#include "base/single_thread_task_runner.h"
#include "third_party/blink/public/platform/web_focus_type.h"
#include "third_party/blink/public/platform/web_insecure_request_policy.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/core/animation/worklet_animation_controller.h"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/css/css_style_sheet_init.h"
#include "third_party/blink/renderer/core/dom/container_node.h"
#include "third_party/blink/renderer/core/dom/create_element_flags.h"
#include "third_party/blink/renderer/core/dom/document_encoding_data.h"
-#include "third_party/blink/renderer/core/dom/document_init.h"
#include "third_party/blink/renderer/core/dom/document_lifecycle.h"
#include "third_party/blink/renderer/core/dom/document_shutdown_notifier.h"
#include "third_party/blink/renderer/core/dom/document_shutdown_observer.h"
#include "third_party/blink/renderer/core/dom/document_timing.h"
#include "third_party/blink/renderer/core/dom/frame_request_callback_collection.h"
#include "third_party/blink/renderer/core/dom/live_node_list_registry.h"
-#include "third_party/blink/renderer/core/dom/mutation_observer.h"
#include "third_party/blink/renderer/core/dom/scripted_idle_task_controller.h"
#include "third_party/blink/renderer/core/dom/synchronous_mutation_notifier.h"
#include "third_party/blink/renderer/core/dom/synchronous_mutation_observer.h"
-#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/dom/text_link_colors.h"
#include "third_party/blink/renderer/core/dom/tree_scope.h"
#include "third_party/blink/renderer/core/dom/user_action_element_set.h"
-#include "third_party/blink/renderer/core/dom/viewport_description.h"
#include "third_party/blink/renderer/core/editing/forward.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/execution_context/security_context.h"
#include "third_party/blink/renderer/core/frame/dom_timer_coordinator.h"
#include "third_party/blink/renderer/core/frame/hosts_using_features.h"
#include "third_party/blink/renderer/core/html/custom/v0_custom_element.h"
#include "third_party/blink/renderer/core/html/parser/parser_synchronization_policy.h"
-#include "third_party/blink/renderer/core/page/page_visibility_state.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
-#include "third_party/blink/renderer/platform/length.h"
-#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/scroll/scroll_types.h"
#include "third_party/blink/renderer/platform/timer.h"
#include "third_party/blink/renderer/platform/web_task_runner.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-#include "third_party/blink/renderer/platform/weborigin/referrer_policy.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
+namespace base {
+class SingleThreadTaskRunner;
+}
+
namespace ukm {
class UkmRecorder;
} // namespace ukm
@@ -86,6 +82,7 @@ namespace blink {
namespace mojom {
enum class EngagementLevel : int32_t;
+enum class PageVisibilityState : int32_t;
} // namespace mojom
class AnimationClock;
@@ -104,6 +101,7 @@ class V0CustomElementRegistrationContext;
class DOMImplementation;
class DOMWindow;
class DocumentFragment;
+class DocumentInit;
class DocumentLoader;
class DocumentMarkerController;
class DocumentNameCollection;
@@ -120,7 +118,6 @@ class EventFactoryBase;
class EventListener;
template <typename EventType>
class EventWithHitTestResults;
-class ExceptionState;
class FloatQuad;
class FloatRect;
class FormController;
@@ -139,6 +136,7 @@ class HitTestRequest;
class IdleRequestOptions;
class IntersectionObserverController;
class LayoutPoint;
+class ReattachLegacyLayoutObjectList;
class LayoutView;
class LiveNodeListBase;
class LocalDOMWindow;
@@ -163,6 +161,7 @@ class ResourceFetcher;
class RootScrollerController;
class SVGDocumentExtensions;
class SVGUseElement;
+class Text;
class TrustedHTML;
class ScriptElementBase;
class ScriptRunner;
@@ -180,19 +179,19 @@ class StyleResolver;
class StylePropertyMapReadOnly;
class StyleSheetList;
class TextAutosizer;
-class Touch;
-class TouchList;
class TransformSource;
class TreeWalker;
+class USVStringOrTrustedURL;
class V8NodeFilter;
+class ViewportData;
class VisitedLinkState;
class WebMouseEvent;
+class WorkletAnimationController;
struct AnnotatedRegionValue;
struct FocusParams;
struct IconURL;
using MouseEventWithHitTestResults = EventWithHitTestResults<WebMouseEvent>;
-using ExceptionCode = int;
enum NodeListInvalidationType : int {
kDoNotInvalidateOnAttributeChanges = 0,
@@ -265,9 +264,7 @@ class CORE_EXPORT Document : public ContainerNode,
static Document* Create(const DocumentInit& init) {
return new Document(init);
}
- static Document* CreateForTest() {
- return new Document(DocumentInit::Create());
- }
+ static Document* CreateForTest();
// Factory for web-exposed Document constructor. The argument document must be
// a document instance representing window.document, and it works as the
// source of ExecutionContext and security origin of the new document.
@@ -316,11 +313,7 @@ class CORE_EXPORT Document : public ContainerNode,
DEFINE_ATTRIBUTE_EVENT_LISTENER(selectstart);
DEFINE_ATTRIBUTE_EVENT_LISTENER(visibilitychange);
- bool ShouldMergeWithLegacyDescription(ViewportDescription::Type) const;
- bool ShouldOverrideLegacyDescription(ViewportDescription::Type) const;
- void SetViewportDescription(const ViewportDescription&);
- ViewportDescription GetViewportDescription() const;
- Length ViewportDefaultMinWidth() const { return viewport_default_min_width_; }
+ ViewportData& GetViewportData() const { return *viewport_data_; }
String OutgoingReferrer() const override;
ReferrerPolicy GetReferrerPolicy() const override;
@@ -369,6 +362,15 @@ class CORE_EXPORT Document : public ContainerNode,
Element* CreateRawElement(const QualifiedName&,
const CreateElementFlags = CreateElementFlags());
+ ScriptPromise createCSSStyleSheet(ScriptState*,
+ const String&,
+ ExceptionState&);
+
+ ScriptPromise createCSSStyleSheet(ScriptState*,
+ const String&,
+ const CSSStyleSheetInit&,
+ ExceptionState&);
+
Element* ElementFromPoint(double x, double y) const;
HeapVector<Member<Element>> ElementsFromPoint(double x, double y) const;
Range* caretRangeFromPoint(int x, int y);
@@ -612,7 +614,7 @@ class CORE_EXPORT Document : public ContainerNode,
ExceptionState&);
DOMWindow* open(LocalDOMWindow* current_window,
LocalDOMWindow* entered_window,
- const AtomicString& url,
+ const USVStringOrTrustedURL& stringOrUrl,
const AtomicString& name,
const AtomicString& features,
ExceptionState&);
@@ -621,6 +623,10 @@ class CORE_EXPORT Document : public ContainerNode,
// This is used internally and does not handle exceptions.
void close();
+ // Corresponds to "9. Abort the active document of browsingContext."
+ // https://html.spec.whatwg.org/#navigate
+ void Abort();
+
void CheckCompleted();
bool DispatchBeforeUnloadEvent(ChromeClient&,
@@ -711,11 +717,6 @@ class CORE_EXPORT Document : public ContainerNode,
}
void SetPrinting(PrintingState);
- bool PaginatedForScreen() const { return paginated_for_screen_; }
- void SetPaginatedForScreen(bool p) { paginated_for_screen_ = p; }
-
- bool Paginated() const { return Printing() || PaginatedForScreen(); }
-
enum CompatibilityMode { kQuirksMode, kLimitedQuirksMode, kNoQuirksMode };
void SetCompatibilityMode(CompatibilityMode);
@@ -756,6 +757,12 @@ class CORE_EXPORT Document : public ContainerNode,
const LayoutPoint&,
const WebMouseEvent&);
+ void SetHadKeyboardEvent(bool had_keyboard_event) {
+ had_keyboard_event_ = had_keyboard_event;
+ }
+ bool HadKeyboardEvent() const { return had_keyboard_event_; }
+ void SetLastFocusType(WebFocusType last_focus_type);
+ WebFocusType LastFocusType() const { return last_focus_type_; }
bool SetFocusedElement(Element*, const FocusParams&);
void ClearFocusedElement();
Element* FocusedElement() const { return focused_element_.Get(); }
@@ -856,11 +863,11 @@ class CORE_EXPORT Document : public ContainerNode,
}
void AddListenerTypeIfNeeded(const AtomicString& event_type, EventTarget&);
- bool HasMutationObserversOfType(MutationObserver::MutationType type) const {
+ bool HasMutationObserversOfType(MutationType type) const {
return mutation_observer_types_ & type;
}
bool HasMutationObservers() const { return mutation_observer_types_; }
- void AddMutationObserverTypes(MutationObserverOptions types) {
+ void AddMutationObserverTypes(MutationType types) {
mutation_observer_types_ |= types;
}
@@ -872,8 +879,6 @@ class CORE_EXPORT Document : public ContainerNode,
}
ResizeObserverController& EnsureResizeObserverController();
- void UpdateViewportDescription();
-
// 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;
@@ -1162,8 +1167,6 @@ class CORE_EXPORT Document : public ContainerNode,
// This calls checkCompleted() sync and thus can cause JavaScript execution.
void DecrementLoadEventDelayCountAndCheckLoadEvent();
- TouchList* createTouchList(HeapVector<Member<Touch>>&) const;
-
const DocumentTiming& GetTiming() const { return document_timing_; }
int RequestAnimationFrame(FrameRequestCallbackCollection::FrameCallback*);
@@ -1289,8 +1292,6 @@ class CORE_EXPORT Document : public ContainerNode,
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
AtomicString ConvertLocalName(const AtomicString&);
void PlatformColorsChanged();
@@ -1309,10 +1310,6 @@ class CORE_EXPORT Document : public ContainerNode,
secure_context_state_ = state;
}
- ClientHintsPreferences& GetClientHintsPreferences() {
- return client_hints_preferences_;
- }
-
CanvasFontCache* GetCanvasFontCache();
// Used by unit tests so that all parsing will be main thread for
@@ -1332,6 +1329,24 @@ class CORE_EXPORT Document : public ContainerNode,
void DidEnforceInsecureRequestPolicy();
void DidEnforceInsecureNavigationsSet();
+ // Temporary flag for some UseCounter items. crbug.com/859391.
+ enum class InDOMNodeRemovedHandlerState {
+ kNone,
+ kDOMNodeRemoved,
+ kDOMNodeRemovedFromDocument
+ };
+ void SetInDOMNodeRemovedHandlerState(InDOMNodeRemovedHandlerState state) {
+ in_dom_node_removed_handler_state_ = state;
+ }
+ InDOMNodeRemovedHandlerState GetInDOMNodeRemovedHandlerState() const {
+ return in_dom_node_removed_handler_state_;
+ }
+ bool InDOMNodeRemovedHandler() const {
+ return in_dom_node_removed_handler_state_ !=
+ InDOMNodeRemovedHandlerState::kNone;
+ }
+ void CountDetachingNodeAccessInDOMNodeRemovedHandler();
+
bool MayContainV0Shadow() const { return may_contain_v0_shadow_; }
ShadowCascadeOrder GetShadowCascadeOrder() const {
@@ -1395,7 +1410,7 @@ class CORE_EXPORT Document : public ContainerNode,
int64_t UkmSourceID() const;
// May return nullptr.
- FrameScheduler* GetScheduler() override;
+ FrameOrWorkerScheduler* GetScheduler() override;
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) override;
@@ -1406,18 +1421,30 @@ class CORE_EXPORT Document : public ContainerNode,
const AtomicString& RequiredCSP();
+ // TODO(layout-dev): Once everything are LayoutNG, we can get rid of this.
+ ReattachLegacyLayoutObjectList& GetReattachLegacyLayoutObjectList();
+
StylePropertyMapReadOnly* ComputedStyleMap(Element*);
void AddComputedStyleMapItem(Element*, StylePropertyMapReadOnly*);
StylePropertyMapReadOnly* RemoveComputedStyleMapItem(Element*);
SlotAssignmentEngine& GetSlotAssignmentEngine();
+ bool IsSlotAssignmentOrLegacyDistributionDirty();
+
#if DCHECK_IS_ON()
+ unsigned& SlotAssignmentRecalcForbiddenRecursionDepth() {
+ return slot_assignment_recalc_forbidden_recursion_depth_;
+ }
bool IsSlotAssignmentRecalcForbidden() {
return slot_assignment_recalc_forbidden_recursion_depth_ > 0;
}
+#else
+ bool IsSlotAssignmentRecalcForbidden() { return false; }
#endif
+ bool IsVerticalScrollEnforced() const { return is_vertical_scroll_enforced_; }
+
protected:
Document(const DocumentInit&, DocumentClassFlags = kDefaultDocumentClass);
@@ -1452,7 +1479,6 @@ class CORE_EXPORT Document : public ContainerNode,
void InitSecurityContext(const DocumentInit&);
void InitSecureContextState();
SecurityContext& GetSecurityContext() final { return *this; }
- EventQueue* GetEventQueue() const final;
bool HasPendingVisualUpdate() const {
return lifecycle_.GetState() == DocumentLifecycle::kVisualUpdatePending;
@@ -1476,6 +1502,11 @@ class CORE_EXPORT Document : public ContainerNode,
void ImplicitClose();
bool ShouldComplete();
+ // Returns |true| if both document and its owning frame are still attached.
+ // Any of them could be detached during the check, e.g. by calling
+ // iframe.remove() from an event handler.
+ bool CheckCompletedInternal();
+
void DetachParser();
void BeginLifecycleUpdatesIfRenderingReady();
@@ -1601,7 +1632,6 @@ class CORE_EXPORT Document : public ContainerNode,
Member<CSSStyleSheet> elem_sheet_;
PrintingState printing_;
- bool paginated_for_screen_;
CompatibilityMode compatibility_mode_;
// This is cheaper than making setCompatibilityMode virtual.
@@ -1610,6 +1640,8 @@ class CORE_EXPORT Document : public ContainerNode,
TaskHandle execute_scripts_waiting_for_resources_task_handle_;
bool has_autofocused_;
+ WebFocusType last_focus_type_;
+ bool had_keyboard_event_;
TaskRunnerTimer<Document> clear_focused_element_timer_;
Member<Element> autofocus_element_;
Member<Element> focused_element_;
@@ -1729,16 +1761,14 @@ class CORE_EXPORT Document : public ContainerNode,
// For early return in Fullscreen::fromIfExists()
bool has_fullscreen_supplement_;
+ // The last element in |m_topLayerElements| is topmost in the top layer
+ // stack and is thus the one that will be visually on top.
HeapVector<Member<Element>> top_layer_elements_;
int load_event_delay_count_;
TaskRunnerTimer<Document> load_event_delay_timer_;
TaskRunnerTimer<Document> plugin_loading_timer_;
- ViewportDescription viewport_description_;
- ViewportDescription legacy_viewport_description_;
- Length viewport_default_min_width_;
-
DocumentTiming document_timing_;
Member<MediaQueryMatcher> media_query_matcher_;
bool write_recursion_is_too_deep_;
@@ -1780,8 +1810,6 @@ class CORE_EXPORT Document : public ContainerNode,
HostsUsingFeatures::Value hosts_using_features_value_;
- ClientHintsPreferences client_hints_preferences_;
-
Member<CanvasFontCache> canvas_font_cache_;
TraceWrapperMember<IntersectionObserverController>
@@ -1790,6 +1818,9 @@ class CORE_EXPORT Document : public ContainerNode,
int node_count_;
+ // Temporary flag for some UseCounter items. crbug.com/859391.
+ InDOMNodeRemovedHandlerState in_dom_node_removed_handler_state_ =
+ InDOMNodeRemovedHandlerState::kNone;
bool may_contain_v0_shadow_ = false;
Member<SnapCoordinator> snap_coordinator_;
@@ -1829,18 +1860,21 @@ class CORE_EXPORT Document : public ContainerNode,
Member<Policy> policy_;
Member<SlotAssignmentEngine> slot_assignment_engine_;
+
+ friend class ReattachLegacyLayoutObjectList;
+ // TODO(layout-dev): Once everything are LayoutNG, we can get rid of this.
+ // Used for legacy layout tree fallback
+ ReattachLegacyLayoutObjectList* reattach_legacy_object_list_;
+
+ // TODO(tkent): Should it be moved to LocalFrame or LocalFrameView?
+ Member<ViewportData> viewport_data_;
+
+ // This is set through feature policy 'vertical-scroll'.
+ bool is_vertical_scroll_enforced_ = false;
};
extern template class CORE_EXTERN_TEMPLATE_EXPORT Supplement<Document>;
-inline bool Document::ShouldOverrideLegacyDescription(
- ViewportDescription::Type origin) const {
- // The different (legacy) meta tags have different priorities based on the
- // type regardless of which order they appear in the DOM. The priority is
- // given by the ViewportDescription::Type enum.
- return origin >= legacy_viewport_description_.type;
-}
-
inline void Document::ScheduleLayoutTreeUpdateIfNeeded() {
// Inline early out to avoid the function calls below.
if (HasPendingVisualUpdate())
diff --git a/chromium/third_party/blink/renderer/core/dom/document.idl b/chromium/third_party/blink/renderer/core/dom/document.idl
index 5d79c534974..7f86ca16454 100644
--- a/chromium/third_party/blink/renderer/core/dom/document.idl
+++ b/chromium/third_party/blink/renderer/core/dom/document.idl
@@ -75,6 +75,8 @@ typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement;
[NewObject] Range createRange();
+ [CallWith=ScriptState, NewObject, RaisesException, RuntimeEnabled=ConstructableStylesheets] Promise<CSSStyleSheet> createCSSStyleSheet(DOMString text, optional CSSStyleSheetInit options);
+
// NodeFilter.SHOW_ALL = 0xFFFFFFFF
[NewObject] NodeIterator createNodeIterator(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
[NewObject] TreeWalker createTreeWalker(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
@@ -118,7 +120,7 @@ typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement;
// dynamic markup insertion
[CallWith=EnteredWindow, CEReactions, CustomElementCallbacks, RaisesException, MeasureAs=DocumentOpenTwoArgs] Document open(optional DOMString type = "text/html", optional DOMString replace = "");
- [CallWith=(CurrentWindow,EnteredWindow), RaisesException, MeasureAs=DocumentOpenThreeArgs] Window open(USVString url, DOMString name, DOMString features);
+ [CallWith=(CurrentWindow,EnteredWindow), RaisesException, MeasureAs=DocumentOpenThreeArgs] Window open(URLString url, DOMString name, DOMString features);
[CEReactions, RaisesException] void close();
[CallWith=EnteredWindow, CEReactions, CustomElementCallbacks, RaisesException] void write(DOMString... text);
[CallWith=EnteredWindow, CEReactions, CustomElementCallbacks, RaisesException] void writeln(DOMString... text);
@@ -167,8 +169,6 @@ typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement;
attribute EventHandler onpointerlockerror;
[MeasureAs=DocumentExitPointerLock] void exitPointerLock();
- [OriginTrialEnabled=TouchEventFeatureDetection, DeprecateAs=V8Document_CreateTouchList_Method] TouchList createTouchList(Touch... touches);
-
// Custom Elements
// https://w3c.github.io/webcomponents/spec/custom/#extensions-to-document-interface-to-register
// FIXME: The registerElement return type should be Function.
@@ -196,7 +196,7 @@ typedef (HTMLScriptElement or SVGScriptElement) HTMLOrSVGScriptElement;
// TODO(iclelland): add spec for JS exposure in the spec for Feature Policy.
// Please refer to this doc for more details for now:
// https://docs.google.com/a/chromium.org/document/d/1wvk3cXkblNnbkMcsKayseK-k0SMGiP9b9fQFgfpqQpc/edit?usp=sharing
- [RuntimeEnabled=FeaturePolicyJavaScriptInterface] readonly attribute Policy policy;
+ [OriginTrialEnabled=FeaturePolicyJavaScriptInterface] readonly attribute Policy policy;
// Deprecated prefixed page visibility API.
// TODO(davidben): This is a property so attaching a deprecation warning results in false positives when outputting
diff --git a/chromium/third_party/blink/renderer/core/dom/document_encoding_data.h b/chromium/third_party/blink/renderer/core/dom/document_encoding_data.h
index b5131268aa9..bc9032d85de 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_encoding_data.h
+++ b/chromium/third_party/blink/renderer/core/dom/document_encoding_data.h
@@ -31,7 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_ENCODING_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_ENCODING_DATA_H_
-#include "third_party/blink/renderer/platform/cross_thread_copier.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
@@ -56,10 +55,6 @@ class DocumentEncodingData {
bool saw_decoding_error_;
};
-template <>
-struct CrossThreadCopier<DocumentEncodingData>
- : public CrossThreadCopierPassThrough<DocumentEncodingData> {};
-
inline bool operator!=(const DocumentEncodingData& a,
const DocumentEncodingData& b) {
return a.Encoding() != b.Encoding() ||
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 9b48c8e1ac7..2cb5634b39b 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_lifecycle.h
+++ b/chromium/third_party/blink/renderer/core/dom/document_lifecycle.h
@@ -72,12 +72,11 @@ class CORE_EXPORT DocumentLifecycle {
// In InPrePaint step, any data needed by painting are prepared.
// Paint property trees are built and paint invalidations are issued.
- // In SPv1, raster invalidations are also issued.
kInPrePaint,
kPrePaintClean,
- // In InPaint step, paint artifacts are generated.
- // In SPv1.75+, raster invalidations are issued.
+ // In InPaint step, paint artifacts are generated and raster invalidations
+ // are issued.
// In SPv2, composited layers are generated/updated.
kInPaint,
kPaintClean,
diff --git a/chromium/third_party/blink/renderer/core/dom/document_or_shadow_root.h b/chromium/third_party/blink/renderer/core/dom/document_or_shadow_root.h
index 6c3269ca092..27f00418fa1 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_or_shadow_root.h
+++ b/chromium/third_party/blink/renderer/core/dom/document_or_shadow_root.h
@@ -30,17 +30,6 @@ class DocumentOrShadowRoot {
return &shadow_root.StyleSheets();
}
- static StyleSheetList* moreStyleSheets(TreeScope& tree_scope) {
- CHECK(RuntimeEnabledFeatures::ConstructableStylesheetsEnabled());
- return &tree_scope.MoreStyleSheets();
- }
-
- static void setMoreStyleSheets(TreeScope& tree_scope,
- StyleSheetList* more_style_sheets) {
- CHECK(RuntimeEnabledFeatures::ConstructableStylesheetsEnabled());
- tree_scope.SetMoreStyleSheets(more_style_sheets);
- }
-
static DOMSelection* getSelection(TreeScope& tree_scope) {
return tree_scope.GetSelection();
}
diff --git a/chromium/third_party/blink/renderer/core/dom/document_or_shadow_root.idl b/chromium/third_party/blink/renderer/core/dom/document_or_shadow_root.idl
index 40db3630ffb..714c9381aac 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_or_shadow_root.idl
+++ b/chromium/third_party/blink/renderer/core/dom/document_or_shadow_root.idl
@@ -22,6 +22,5 @@
readonly attribute Element? pointerLockElement;
// Fullscreen API
// https://fullscreen.spec.whatwg.org/
- [RuntimeEnabled=FullscreenUnprefixed] readonly attribute Element? fullscreenElement;
- [RuntimeEnabled=ConstructableStylesheets] attribute StyleSheetList moreStyleSheets;
+ [LenientSetter, RuntimeEnabled=FullscreenUnprefixed] readonly attribute Element? fullscreenElement;
};
diff --git a/chromium/third_party/blink/renderer/core/dom/document_parser.h b/chromium/third_party/blink/renderer/core/dom/document_parser.h
index 7480b5a32a9..157f3b7e432 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_parser.h
+++ b/chromium/third_party/blink/renderer/core/dom/document_parser.h
@@ -26,7 +26,7 @@
#include <memory>
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -39,11 +39,10 @@ class TextResourceDecoder;
class CORE_EXPORT DocumentParser
: public GarbageCollectedFinalized<DocumentParser>,
- public TraceWrapperBase {
+ public NameClient {
public:
virtual ~DocumentParser();
virtual void Trace(blink::Visitor*);
- void TraceWrappers(ScriptWrappableVisitor*) const override {}
const char* NameInHeapSnapshot() const override { return "DocumentParser"; }
virtual ScriptableDocumentParser* AsScriptableDocumentParser() {
diff --git a/chromium/third_party/blink/renderer/core/dom/document_parser_timing.cc b/chromium/third_party/blink/renderer/core/dom/document_parser_timing.cc
index 435396df12a..a9c99cd4980 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_parser_timing.cc
+++ b/chromium/third_party/blink/renderer/core/dom/document_parser_timing.cc
@@ -44,7 +44,7 @@ void DocumentParserTiming::MarkParserDetached() {
}
void DocumentParserTiming::RecordParserBlockedOnScriptLoadDuration(
- double duration,
+ TimeDelta duration,
bool script_inserted_via_document_write) {
if (parser_detached_ || parser_start_.is_null() || !parser_stop_.is_null())
return;
@@ -55,7 +55,7 @@ void DocumentParserTiming::RecordParserBlockedOnScriptLoadDuration(
}
void DocumentParserTiming::RecordParserBlockedOnScriptExecutionDuration(
- double duration,
+ TimeDelta duration,
bool script_inserted_via_document_write) {
if (parser_detached_ || parser_start_.is_null() || !parser_stop_.is_null())
return;
diff --git a/chromium/third_party/blink/renderer/core/dom/document_parser_timing.h b/chromium/third_party/blink/renderer/core/dom/document_parser_timing.h
index 9e1f587f6dc..f0c93090c01 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_parser_timing.h
+++ b/chromium/third_party/blink/renderer/core/dom/document_parser_timing.h
@@ -45,23 +45,23 @@ class DocumentParserTiming final
void MarkParserDetached();
// Record a duration of time that the parser yielded due to loading a
- // script, in seconds. scriptInsertedViaDocumentWrite indicates whether the
+ // script. scriptInsertedViaDocumentWrite indicates whether the
// script causing blocking was inserted via document.write. This may be
// called multiple times, once for each time the parser yields on a script
// load.
void RecordParserBlockedOnScriptLoadDuration(
- double duration,
+ TimeDelta duration,
bool script_inserted_via_document_write);
- // Record a duration of time that the parser spent executing a script, in
- // seconds. scriptInsertedViaDocumentWrite indicates whether the script
- // being executed was inserted via document.write. This may be called
- // multiple times, once for each time the parser executes a script.
+ // Record a duration of time that the parser spent executing a script.
+ // scriptInsertedViaDocumentWrite indicates whether the script being executed
+ // was inserted via document.write. This may be called multiple times, once
+ // for each time the parser executes a script.
void RecordParserBlockedOnScriptExecutionDuration(
- double duration,
+ TimeDelta duration,
bool script_inserted_via_document_write);
- // The getters below return monotonically-increasing seconds, or zero if the
+ // The getters below return monotonically-increasing time, or zero if the
// given parser event has not yet occurred. See the comments for
// monotonicallyIncreasingTime in wtf/Time.h for additional details.
@@ -70,7 +70,7 @@ class DocumentParserTiming final
// Returns the sum of all blocking script load durations reported via
// recordParseBlockedOnScriptLoadDuration.
- double ParserBlockedOnScriptLoadDuration() const {
+ TimeDelta ParserBlockedOnScriptLoadDuration() const {
return parser_blocked_on_script_load_duration_;
}
@@ -78,13 +78,13 @@ class DocumentParserTiming final
// document.write reported via recordParseBlockedOnScriptLoadDuration. Note
// that some uncommon cases are not currently covered by this method. See
// crbug/600711 for details.
- double ParserBlockedOnScriptLoadFromDocumentWriteDuration() const {
+ TimeDelta ParserBlockedOnScriptLoadFromDocumentWriteDuration() const {
return parser_blocked_on_script_load_from_document_write_duration_;
}
// Returns the sum of all script execution durations reported via
// recordParseBlockedOnScriptExecutionDuration.
- double ParserBlockedOnScriptExecutionDuration() const {
+ TimeDelta ParserBlockedOnScriptExecutionDuration() const {
return parser_blocked_on_script_execution_duration_;
}
@@ -92,7 +92,7 @@ class DocumentParserTiming final
// document.write reported via recordParseBlockedOnScriptExecutionDuration.
// Note that some uncommon cases are not currently covered by this method. See
// crbug/600711 for details.
- double ParserBlockedOnScriptExecutionFromDocumentWriteDuration() const {
+ TimeDelta ParserBlockedOnScriptExecutionFromDocumentWriteDuration() const {
return parser_blocked_on_script_execution_from_document_write_duration_;
}
@@ -104,10 +104,10 @@ class DocumentParserTiming final
TimeTicks parser_start_;
TimeTicks parser_stop_;
- double parser_blocked_on_script_load_duration_ = 0.0;
- double parser_blocked_on_script_load_from_document_write_duration_ = 0.0;
- double parser_blocked_on_script_execution_duration_ = 0.0;
- double parser_blocked_on_script_execution_from_document_write_duration_ = 0.0;
+ TimeDelta parser_blocked_on_script_load_duration_;
+ TimeDelta parser_blocked_on_script_load_from_document_write_duration_;
+ TimeDelta parser_blocked_on_script_execution_duration_;
+ TimeDelta parser_blocked_on_script_execution_from_document_write_duration_;
bool parser_detached_ = false;
DISALLOW_COPY_AND_ASSIGN(DocumentParserTiming);
};
diff --git a/chromium/third_party/blink/renderer/core/dom/document_shutdown_observer.cc b/chromium/third_party/blink/renderer/core/dom/document_shutdown_observer.cc
index 321bbd8fe4e..76f3327775e 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_shutdown_observer.cc
+++ b/chromium/third_party/blink/renderer/core/dom/document_shutdown_observer.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/dom/document_shutdown_observer.h"
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_shutdown_notifier.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/dom/document_shutdown_observer.h b/chromium/third_party/blink/renderer/core/dom/document_shutdown_observer.h
index 3e0a78db5b2..e7321eca284 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_shutdown_observer.h
+++ b/chromium/third_party/blink/renderer/core/dom/document_shutdown_observer.h
@@ -6,11 +6,12 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOCUMENT_SHUTDOWN_OBSERVER_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/lifecycle_observer.h"
namespace blink {
+class Document;
+
// This class is a base class for classes which observe Document shutdown
// synchronously.
// Note: this functionality is also provided by SynchronousMutationObserver,
diff --git a/chromium/third_party/blink/renderer/core/dom/document_statistics_collector.cc b/chromium/third_party/blink/renderer/core/dom/document_statistics_collector.cc
index 3d09e837c25..de59cff236a 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_statistics_collector.cc
+++ b/chromium/third_party/blink/renderer/core/dom/document_statistics_collector.cc
@@ -209,7 +209,7 @@ WebDistillabilityFeatures DocumentStatisticsCollector::CollectStatistics(
features.is_mobile_friendly = IsMobileFriendly(document);
- double start_time = CurrentTimeTicksInSeconds();
+ TimeTicks start_time = CurrentTimeTicks();
// This should be cheap since collectStatistics is only called right after
// layout.
@@ -219,11 +219,11 @@ WebDistillabilityFeatures DocumentStatisticsCollector::CollectStatistics(
CollectFeatures(*body, features);
features.open_graph = HasOpenGraphArticle(*head);
- double elapsed_time = CurrentTimeTicksInSeconds() - start_time;
+ TimeDelta elapsed_time = CurrentTimeTicks() - start_time;
DEFINE_STATIC_LOCAL(CustomCountHistogram, distillability_histogram,
("WebCore.DistillabilityUs", 1, 1000000, 50));
- distillability_histogram.Count(static_cast<int>(1e6 * elapsed_time));
+ distillability_histogram.CountMicroseconds(elapsed_time);
return features;
}
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 995d3d7f202..723e114dc87 100644
--- a/chromium/third_party/blink/renderer/core/dom/document_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/document_test.cc
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include <memory>
+
#include "build/build_config.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -44,6 +45,7 @@
#include "third_party/blink/renderer/core/dom/text.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/viewport_data.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/html_head_element.h"
#include "third_party/blink/renderer/core/html/html_link_element.h"
@@ -57,6 +59,7 @@
#include "third_party/blink/renderer/platform/weborigin/referrer_policy.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -537,7 +540,7 @@ TEST_F(DocumentTest, OutgoingReferrer) {
TEST_F(DocumentTest, OutgoingReferrerWithUniqueOrigin) {
GetDocument().SetURL(KURL("https://www.example.com/hoge#fuga?piyo"));
- GetDocument().SetSecurityOrigin(SecurityOrigin::CreateUnique());
+ GetDocument().SetSecurityOrigin(SecurityOrigin::CreateUniqueOpaque());
EXPECT_EQ(String(), GetDocument().OutgoingReferrer());
}
@@ -581,7 +584,7 @@ TEST_F(DocumentTest, EnforceSandboxFlags) {
mask |= kSandboxOrigin;
GetDocument().EnforceSandboxFlags(mask);
- EXPECT_TRUE(GetDocument().GetSecurityOrigin()->IsUnique());
+ EXPECT_TRUE(GetDocument().GetSecurityOrigin()->IsOpaque());
EXPECT_FALSE(GetDocument().GetSecurityOrigin()->IsPotentiallyTrustworthy());
// A unique origin does not bypass secure context checks unless it
@@ -592,19 +595,19 @@ TEST_F(DocumentTest, EnforceSandboxFlags) {
SecurityOrigin::CreateFromString("very-special-scheme://example.test");
GetDocument().SetSecurityOrigin(origin);
GetDocument().EnforceSandboxFlags(mask);
- EXPECT_TRUE(GetDocument().GetSecurityOrigin()->IsUnique());
+ EXPECT_TRUE(GetDocument().GetSecurityOrigin()->IsOpaque());
EXPECT_FALSE(GetDocument().GetSecurityOrigin()->IsPotentiallyTrustworthy());
SchemeRegistry::RegisterURLSchemeAsSecure("very-special-scheme");
GetDocument().SetSecurityOrigin(origin);
GetDocument().EnforceSandboxFlags(mask);
- EXPECT_TRUE(GetDocument().GetSecurityOrigin()->IsUnique());
+ EXPECT_TRUE(GetDocument().GetSecurityOrigin()->IsOpaque());
EXPECT_TRUE(GetDocument().GetSecurityOrigin()->IsPotentiallyTrustworthy());
origin = SecurityOrigin::CreateFromString("https://example.test");
GetDocument().SetSecurityOrigin(origin);
GetDocument().EnforceSandboxFlags(mask);
- EXPECT_TRUE(GetDocument().GetSecurityOrigin()->IsUnique());
+ EXPECT_TRUE(GetDocument().GetSecurityOrigin()->IsOpaque());
EXPECT_TRUE(GetDocument().GetSecurityOrigin()->IsPotentiallyTrustworthy());
}
@@ -1059,9 +1062,13 @@ class ViewportFitDocumentTest : public DocumentTest {
void SetUp() override {
DocumentTest::SetUp();
- RuntimeEnabledFeatures::SetDisplayCutoutViewportFitEnabled(true);
+ RuntimeEnabledFeatures::SetDisplayCutoutAPIEnabled(true);
GetDocument().GetSettings()->SetViewportMetaEnabled(true);
}
+
+ mojom::ViewportFit GetViewportFit() const {
+ return GetDocument().GetViewportData().GetCurrentViewportFitForTests();
+ }
};
// Test both meta and @viewport present but no viewport-fit.
@@ -1070,30 +1077,45 @@ TEST_F(ViewportFitDocumentTest, MetaCSSViewportButNoFit) {
"<style>@viewport { min-width: 100px; }</style>"
"<meta name='viewport' content='initial-scale=1'>");
- EXPECT_EQ(ViewportDescription::ViewportFit::kAuto,
- GetDocument().GetViewportDescription().GetViewportFit());
+ 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(ViewportDescription::ViewportFit::kAuto,
- GetDocument().GetViewportDescription().GetViewportFit());
+ 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'>");
- EXPECT_EQ(ViewportDescription::ViewportFit::kAuto,
- GetDocument().GetViewportDescription().GetViewportFit());
+ EXPECT_EQ(mojom::ViewportFit::kAuto, GetViewportFit());
+}
+
+// Test overriding the viewport fit using SetExpandIntoDisplayCutout.
+TEST_F(ViewportFitDocumentTest, ForceExpandIntoCutout) {
+ SetHtmlInnerHTML("<meta name='viewport' content='viewport-fit=contain'>");
+ EXPECT_EQ(mojom::ViewportFit::kContain, GetViewportFit());
+
+ // Now override the viewport fit value and expect it to be kCover.
+ GetDocument().GetViewportData().SetExpandIntoDisplayCutout(true);
+ EXPECT_EQ(mojom::ViewportFit::kCoverForcedByUserAgent, GetViewportFit());
+
+ // Test that even if we change the value we ignore it.
+ SetHtmlInnerHTML("<meta name='viewport' content='viewport-fit=auto'>");
+ EXPECT_EQ(mojom::ViewportFit::kCoverForcedByUserAgent, GetViewportFit());
+
+ // Now remove the override and check that it went back to the previous value.
+ GetDocument().GetViewportData().SetExpandIntoDisplayCutout(false);
+ EXPECT_EQ(mojom::ViewportFit::kAuto, GetViewportFit());
}
// 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*, ViewportDescription::ViewportFit>;
+ std::tuple<const char*, const char*, mojom::ViewportFit>;
class ParameterizedViewportFitDocumentTest
: public ViewportFitDocumentTest,
@@ -1123,8 +1145,7 @@ class ParameterizedViewportFitDocumentTest
TEST_P(ParameterizedViewportFitDocumentTest, EffectiveViewportFit) {
LoadTestHTML();
- EXPECT_EQ(std::get<2>(GetParam()),
- GetDocument().GetViewportDescription().GetViewportFit());
+ EXPECT_EQ(std::get<2>(GetParam()), GetViewportFit());
}
INSTANTIATE_TEST_CASE_P(
@@ -1132,41 +1153,19 @@ INSTANTIATE_TEST_CASE_P(
ParameterizedViewportFitDocumentTest,
testing::Values(
// Test the default case.
- ViewportTestCase(nullptr,
- nullptr,
- ViewportDescription::ViewportFit::kAuto),
+ ViewportTestCase(nullptr, nullptr, mojom::ViewportFit::kAuto),
// Test the different values set through CSS.
- ViewportTestCase(nullptr,
- "auto",
- ViewportDescription::ViewportFit::kAuto),
- ViewportTestCase(nullptr,
- "contain",
- ViewportDescription::ViewportFit::kContain),
- ViewportTestCase(nullptr,
- "cover",
- ViewportDescription::ViewportFit::kCover),
- ViewportTestCase(nullptr,
- "invalid",
- ViewportDescription::ViewportFit::kAuto),
+ ViewportTestCase(nullptr, "auto", mojom::ViewportFit::kAuto),
+ ViewportTestCase(nullptr, "contain", mojom::ViewportFit::kContain),
+ ViewportTestCase(nullptr, "cover", mojom::ViewportFit::kCover),
+ ViewportTestCase(nullptr, "invalid", mojom::ViewportFit::kAuto),
// Test the different values set through the meta tag.
- ViewportTestCase("auto",
- nullptr,
- ViewportDescription::ViewportFit::kAuto),
- ViewportTestCase("contain",
- nullptr,
- ViewportDescription::ViewportFit::kContain),
- ViewportTestCase("cover",
- nullptr,
- ViewportDescription::ViewportFit::kCover),
- ViewportTestCase("invalid",
- nullptr,
- ViewportDescription::ViewportFit::kAuto),
+ 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",
- ViewportDescription::ViewportFit::kAuto),
- ViewportTestCase("cover",
- "contain",
- ViewportDescription::ViewportFit::kContain)));
+ ViewportTestCase("cover", "auto", mojom::ViewportFit::kAuto),
+ ViewportTestCase("cover", "contain", mojom::ViewportFit::kContain)));
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/dom_exception.cc b/chromium/third_party/blink/renderer/core/dom/dom_exception.cc
index be1a84cdbc9..672b6a99b5d 100644
--- a/chromium/third_party/blink/renderer/core/dom/dom_exception.cc
+++ b/chromium/third_party/blink/renderer/core/dom/dom_exception.cc
@@ -28,179 +28,173 @@
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
namespace blink {
-static const struct CoreException {
- const char* const name;
- const char* const message;
- const int code;
-} kCoreExceptions[] = {
- // This list must be kept in sync with the one in ExceptionCode.h
- {"IndexSizeError",
- "Index or size was negative, or greater than the allowed value.", 1},
- {"HierarchyRequestError",
- "A Node was inserted somewhere it doesn't belong.", 3},
- {"WrongDocumentError",
+namespace {
+
+// Name, decription, and legacy code name and value of DOMExceptions.
+// https://heycam.github.io/webidl/#idl-DOMException-error-names
+const struct DOMExceptionEntry {
+ DOMExceptionCode code;
+ const char* name;
+ const char* message;
+} kDOMExceptionEntryTable[] = {
+ // DOMException defined with legacy error code in Web IDL.
+ {DOMExceptionCode::kIndexSizeError, "IndexSizeError",
+ "Index or size was negative, or greater than the allowed value."},
+ {DOMExceptionCode::kHierarchyRequestError, "HierarchyRequestError",
+ "A Node was inserted somewhere it doesn't belong."},
+ {DOMExceptionCode::kWrongDocumentError, "WrongDocumentError",
"A Node was used in a different document than the one that created it "
- "(that doesn't support it).",
- 4},
- {"InvalidCharacterError", "The string contains invalid characters.", 5},
- {"NoModificationAllowedError",
+ "(that doesn't support it)."},
+ {DOMExceptionCode::kInvalidCharacterError, "InvalidCharacterError",
+ "The string contains invalid characters."},
+ {DOMExceptionCode::kNoModificationAllowedError,
+ "NoModificationAllowedError",
"An attempt was made to modify an object where modifications are not "
- "allowed.",
- 7},
- {"NotFoundError",
+ "allowed."},
+ {DOMExceptionCode::kNotFoundError, "NotFoundError",
"An attempt was made to reference a Node in a context where it does not "
- "exist.",
- 8},
- {"NotSupportedError",
+ "exist."},
+ {DOMExceptionCode::kNotSupportedError, "NotSupportedError",
"The implementation did not support the requested type of object or "
- "operation.",
- 9},
- {"InUseAttributeError",
+ "operation."},
+ {DOMExceptionCode::kInUseAttributeError, "InUseAttributeError",
"An attempt was made to add an attribute that is already in use "
- "elsewhere.",
- 10},
- {"InvalidStateError",
+ "elsewhere."},
+ {DOMExceptionCode::kInvalidStateError, "InvalidStateError",
"An attempt was made to use an object that is not, or is no longer, "
- "usable.",
- 11},
- {"SyntaxError", "An invalid or illegal string was specified.", 12},
- {"InvalidModificationError", "The object can not be modified in this way.",
- 13},
- {"NamespaceError",
+ "usable."},
+ {DOMExceptionCode::kSyntaxError, "SyntaxError",
+ "An invalid or illegal string was specified."},
+ {DOMExceptionCode::kInvalidModificationError, "InvalidModificationError",
+ "The object can not be modified in this way."},
+ {DOMExceptionCode::kNamespaceError, "NamespaceError",
"An attempt was made to create or change an object in a way which is "
- "incorrect with regard to namespaces.",
- 14},
- {"InvalidAccessError",
- "A parameter or an operation was not supported by the underlying object.",
- 15},
- {"TypeMismatchError",
+ "incorrect with regard to namespaces."},
+ {DOMExceptionCode::kInvalidAccessError, "InvalidAccessError",
+ "A parameter or an operation was not supported by the underlying object."},
+ {DOMExceptionCode::kTypeMismatchError, "TypeMismatchError",
"The type of an object was incompatible with the expected type of the "
- "parameter associated to the object.",
- 17},
- {"SecurityError",
+ "parameter associated to the object."},
+ {DOMExceptionCode::kSecurityError, "SecurityError",
"An attempt was made to break through the security policy of the user "
- "agent.",
- 18},
- {"NetworkError", "A network error occurred.", 19},
- {"AbortError", "The user aborted a request.", 20},
- {"URLMismatchError",
+ "agent."},
+ {DOMExceptionCode::kNetworkError, "NetworkError",
+ "A network error occurred."},
+ {DOMExceptionCode::kAbortError, "AbortError",
+ "The user aborted a request."},
+ {DOMExceptionCode::kURLMismatchError, "URLMismatchError",
"A worker global scope represented an absolute URL that is not equal to "
- "the resulting absolute URL.",
- 21},
- {"QuotaExceededError",
- "An attempt was made to add something to storage that exceeded the quota.",
- 22},
- {"TimeoutError", "A timeout occurred.", 23},
- {"InvalidNodeTypeError",
+ "the resulting absolute URL."},
+ {DOMExceptionCode::kQuotaExceededError, "QuotaExceededError",
+ "An attempt was made to add something to storage that exceeded the "
+ "quota."},
+ {DOMExceptionCode::kTimeoutError, "TimeoutError", "A timeout occurred."},
+ {DOMExceptionCode::kInvalidNodeTypeError, "InvalidNodeTypeError",
"The supplied node is invalid or has an invalid ancestor for this "
- "operation.",
- 24},
- {"DataCloneError", "An object could not be cloned.", 25},
+ "operation."},
+ {DOMExceptionCode::kDataCloneError, "DataCloneError",
+ "An object could not be cloned."},
- // Indexed DB
- {"UnknownError", "An unknown error occurred within Indexed Database.", 0},
- {"ConstraintError",
+ // DOMException defined without legacy error code in Web IDL.
+ {DOMExceptionCode::kEncodingError, "EncodingError",
+ "A URI supplied to the API was malformed, or the resulting Data URL has "
+ "exceeded the URL length limitations for Data URLs."},
+ {DOMExceptionCode::kNotReadableError, "NotReadableError",
+ "The requested file could not be read, typically due to permission "
+ "problems that have occurred after a reference to a file was acquired."},
+ {DOMExceptionCode::kUnknownError, "UnknownError",
+ "The operation failed for an unknown transient reason "
+ "(e.g. out of memory)."},
+ {DOMExceptionCode::kConstraintError, "ConstraintError",
"A mutation operation in the transaction failed because a constraint was "
- "not satisfied.",
- 0},
- {"DataError", "The data provided does not meet requirements.", 0},
- {"TransactionInactiveError",
+ "not satisfied."},
+ {DOMExceptionCode::kDataError, "DataError",
+ "The data provided does not meet requirements."},
+ {DOMExceptionCode::kTransactionInactiveError, "TransactionInactiveError",
"A request was placed against a transaction which is either currently not "
- "active, or which is finished.",
- 0},
- {"ReadOnlyError",
- "A write operation was attempted in a read-only transaction.", 0},
- {"VersionError",
+ "active, or which is finished."},
+ {DOMExceptionCode::kReadOnlyError, "ReadOnlyError",
+ "A write operation was attempted in a read-only transaction."},
+ {DOMExceptionCode::kVersionError, "VersionError",
"An attempt was made to open a database using a lower version than the "
- "existing version.",
- 0},
+ "existing version."},
+ {DOMExceptionCode::kOperationError, "OperationError",
+ "The operation failed for an operation-specific reason"},
+ {DOMExceptionCode::kNotAllowedError, "NotAllowedError",
+ "The request is not allowed by the user agent or the platform in the "
+ "current context."},
- // File system
- {"NotReadableError",
- "The requested file could not be read, typically due to permission "
- "problems that have occurred after a reference to a file was acquired.",
- 0},
- {"EncodingError",
- "A URI supplied to the API was malformed, or the resulting Data URL has "
- "exceeded the URL length limitations for Data URLs.",
- 0},
- {"PathExistsError",
+ // DOMError (obsolete, not DOMException) defined in File system (obsolete).
+ // https://www.w3.org/TR/2012/WD-file-system-api-20120417/
+ {DOMExceptionCode::kPathExistsError, "PathExistsError",
"An attempt was made to create a file or directory where an element "
- "already exists.",
- 0},
-
- // SQL
- {"DatabaseError",
- "The operation failed for some reason related to the database.", 0},
-
- // Web Crypto
- {"OperationError", "The operation failed for an operation-specific reason",
- 0},
+ "already exists."},
// Push API
- {"PermissionDeniedError", "User or security policy denied the request.", 0},
-
- // Used by HTML and Media Session API.
- {"NotAllowedError",
- "The request is not allowed by the user agent or the platform in the "
- "current context.",
- 0},
-
- // Pointer Event
- {"InvalidPointerId", "PointerId was invalid.", 0},
+ //
+ // PermissionDeniedError (obsolete) was replaced with NotAllowedError in the
+ // standard.
+ // https://github.com/WICG/BackgroundSync/issues/124
+ {DOMExceptionCode::kPermissionDeniedError, "PermissionDeniedError",
+ "User or security policy denied the request."},
+
+ // Pointer Events
+ // https://w3c.github.io/pointerevents/
+ // Pointer Events introduced a new DOMException outside Web IDL.
+ {DOMExceptionCode::kInvalidPointerId, "InvalidPointerId",
+ "PointerId was invalid."},
};
-static const CoreException* GetErrorEntry(ExceptionCode ec) {
- size_t table_size = arraysize(kCoreExceptions);
- size_t table_index = ec - kIndexSizeError;
+unsigned short ToLegacyErrorCode(DOMExceptionCode exception_code) {
+ if (DOMExceptionCode::kLegacyErrorCodeMin <= exception_code &&
+ exception_code <= DOMExceptionCode::kLegacyErrorCodeMax) {
+ return static_cast<unsigned short>(exception_code);
+ }
+ return 0;
+}
- return table_index < table_size ? &kCoreExceptions[table_index] : nullptr;
+const DOMExceptionEntry* FindErrorEntry(DOMExceptionCode exception_code) {
+ for (const auto& entry : kDOMExceptionEntryTable) {
+ if (exception_code == entry.code)
+ return &entry;
+ }
+ NOTREACHED();
+ return nullptr;
}
-static int GetErrorCode(const String& name) {
- for (const CoreException& entry : kCoreExceptions) {
- if (entry.name == name)
- return entry.code;
+unsigned short FindLegacyErrorCode(const String& name) {
+ for (const auto& entry : kDOMExceptionEntryTable) {
+ if (name == entry.name)
+ return ToLegacyErrorCode(entry.code);
}
return 0;
}
-DOMException::DOMException(unsigned short code,
- const String& name,
- const String& sanitized_message,
- const String& unsanitized_message) {
- DCHECK(name);
- code_ = code;
- name_ = name;
- sanitized_message_ = sanitized_message;
- unsanitized_message_ = unsanitized_message;
-}
+} // namespace
-DOMException* DOMException::Create(ExceptionCode ec,
+// static
+DOMException* DOMException::Create(DOMExceptionCode exception_code,
const String& sanitized_message,
const String& unsanitized_message) {
- const CoreException* entry = GetErrorEntry(ec);
- DCHECK(entry);
+ const DOMExceptionEntry* entry = FindErrorEntry(exception_code);
return new DOMException(
- entry->code, entry->name ? entry->name : "Error",
+ ToLegacyErrorCode(entry->code), entry->name ? entry->name : "Error",
sanitized_message.IsNull() ? String(entry->message) : sanitized_message,
unsanitized_message);
}
+// static
DOMException* DOMException::Create(const String& message, const String& name) {
- return new DOMException(GetErrorCode(name), name, message, message);
+ return new DOMException(FindLegacyErrorCode(name), name, message, String());
}
-String DOMException::ToStringForConsole() const {
- return name() + ": " + MessageForConsole();
-}
+// static
+String DOMException::GetErrorName(DOMExceptionCode exception_code) {
+ const DOMExceptionEntry* entry = FindErrorEntry(exception_code);
-String DOMException::GetErrorName(ExceptionCode ec) {
- const CoreException* entry = GetErrorEntry(ec);
DCHECK(entry);
if (!entry)
return "UnknownError";
@@ -208,8 +202,10 @@ String DOMException::GetErrorName(ExceptionCode ec) {
return entry->name;
}
-String DOMException::GetErrorMessage(ExceptionCode ec) {
- const CoreException* entry = GetErrorEntry(ec);
+// static
+String DOMException::GetErrorMessage(DOMExceptionCode exception_code) {
+ const DOMExceptionEntry* entry = FindErrorEntry(exception_code);
+
DCHECK(entry);
if (!entry)
return "Unknown error.";
@@ -217,4 +213,19 @@ String DOMException::GetErrorMessage(ExceptionCode ec) {
return entry->message;
}
+DOMException::DOMException(unsigned short legacy_code,
+ const String& name,
+ const String& sanitized_message,
+ const String& unsanitized_message)
+ : legacy_code_(legacy_code),
+ name_(name),
+ sanitized_message_(sanitized_message),
+ unsanitized_message_(unsanitized_message) {
+ DCHECK(name);
+}
+
+String DOMException::ToStringForConsole() const {
+ return name() + ": " + MessageForConsole();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/dom_exception.h b/chromium/third_party/blink/renderer/core/dom/dom_exception.h
index f3ce258b790..e96e5e8abbf 100644
--- a/chromium/third_party/blink/renderer/core/dom/dom_exception.h
+++ b/chromium/third_party/blink/renderer/core/dom/dom_exception.h
@@ -30,10 +30,8 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOM_EXCEPTION_H_
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_code.h"
#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/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -42,14 +40,19 @@ class CORE_EXPORT DOMException final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- static DOMException* Create(ExceptionCode,
+ // This function shouldn't be used except for V8ThrowDOMException. Note that
+ // this function does not associate the stacktrace with the created object.
+ static DOMException* Create(DOMExceptionCode,
const String& sanitized_message = String(),
const String& unsanitized_message = String());
// Constructor exposed to script.
static DOMException* Create(const String& message, const String& name);
- unsigned short code() const { return code_; }
+ static String GetErrorName(DOMExceptionCode);
+ static String GetErrorMessage(DOMExceptionCode);
+
+ unsigned short code() const { return legacy_code_; }
String name() const { return name_; }
// This is the message that's exposed to JavaScript: never return unsanitized
@@ -64,16 +67,13 @@ class CORE_EXPORT DOMException final : public ScriptWrappable {
}
String ToStringForConsole() const;
- static String GetErrorName(ExceptionCode);
- static String GetErrorMessage(ExceptionCode);
-
private:
- DOMException(unsigned short code,
+ DOMException(unsigned short legacy_code,
const String& name,
const String& sanitized_message,
const String& unsanitized_message);
- unsigned short code_;
+ unsigned short legacy_code_;
String name_;
String sanitized_message_;
String unsanitized_message_;
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 8c40eef254a..a2fbf84747a 100644
--- a/chromium/third_party/blink/renderer/core/dom/dom_implementation.cc
+++ b/chromium/third_party/blink/renderer/core/dom/dom_implementation.cc
@@ -25,7 +25,6 @@
#include "third_party/blink/renderer/core/dom/dom_implementation.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
#include "third_party/blink/renderer/core/css/media_list.h"
#include "third_party/blink/renderer/core/css/style_sheet_contents.h"
@@ -51,6 +50,7 @@
#include "third_party/blink/renderer/core/loader/frame_loader.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/svg_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/network/mime/content_type.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
diff --git a/chromium/third_party/blink/renderer/core/dom/dom_string_map.h b/chromium/third_party/blink/renderer/core/dom/dom_string_map.h
index 9c8cf447b14..04d281dfa45 100644
--- a/chromium/third_party/blink/renderer/core/dom/dom_string_map.h
+++ b/chromium/third_party/blink/renderer/core/dom/dom_string_map.h
@@ -27,8 +27,8 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_DOM_STRING_MAP_H_
#include "base/macros.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/core/dom/dom_token_list.cc b/chromium/third_party/blink/renderer/core/dom/dom_token_list.cc
index c1dfa3a95ff..02337667d58 100644
--- a/chromium/third_party/blink/renderer/core/dom/dom_token_list.cc
+++ b/chromium/third_party/blink/renderer/core/dom/dom_token_list.cc
@@ -25,10 +25,9 @@
#include "third_party/blink/renderer/core/dom/dom_token_list.h"
#include "base/auto_reset.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/element.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -37,7 +36,7 @@ namespace {
bool CheckEmptyToken(const String& token, ExceptionState& exception_state) {
if (!token.IsEmpty())
return true;
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"The token provided must not be empty.");
return false;
}
@@ -46,7 +45,7 @@ bool CheckTokenWithWhitespace(const String& token,
ExceptionState& exception_state) {
if (token.Find(IsHTMLSpace) == kNotFound)
return true;
- exception_state.ThrowDOMException(kInvalidCharacterError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidCharacterError,
"The token provided ('" + token +
"') contains HTML space characters, "
"which are not valid in tokens.");
diff --git a/chromium/third_party/blink/renderer/core/dom/element.cc b/chromium/third_party/blink/renderer/core/dom/element.cc
index dc3a45eb82b..54a70a4fd9d 100644
--- a/chromium/third_party/blink/renderer/core/dom/element.cc
+++ b/chromium/third_party/blink/renderer/core/dom/element.cc
@@ -30,12 +30,13 @@
#include "third_party/blink/public/platform/web_scroll_into_view_params.h"
#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_script_url.h"
+#include "third_party/blink/renderer/bindings/core/v8/usv_string_or_trusted_url.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/animation/css/css_animations.h"
+#include "third_party/blink/renderer/core/aom/computed_accessible_node.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_primitive_value.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
@@ -52,16 +53,14 @@
#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/dom/attr.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
-#include "third_party/blink/renderer/core/dom/computed_accessible_node.h"
#include "third_party/blink/renderer/core/dom/dataset_dom_string_map.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_token_list.h"
#include "third_party/blink/renderer/core/dom/element_data_cache.h"
#include "third_party/blink/renderer/core/dom/element_rare_data.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
+#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/dom/events/event_dispatcher.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/first_letter_pseudo_element.h"
#include "third_party/blink/renderer/core/dom/layout_tree_builder.h"
#include "third_party/blink/renderer/core/dom/mutation_observer_interest_group.h"
@@ -77,8 +76,6 @@
#include "third_party/blink/renderer/core/dom/slot_assignment.h"
#include "third_party/blink/renderer/core/dom/space_split_string.h"
#include "third_party/blink/renderer/core/dom/text.h"
-#include "third_party/blink/renderer/core/dom/trustedtypes/trusted_html.h"
-#include "third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.h"
#include "third_party/blink/renderer/core/dom/v0_insertion_point.h"
#include "third_party/blink/renderer/core/dom/whitespace_attacher.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
@@ -91,7 +88,6 @@
#include "third_party/blink/renderer/core/editing/visible_selection.h"
#include "third_party/blink/renderer/core/events/focus_event.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
-#include "third_party/blink/renderer/core/frame/hosts_using_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/frame/local_frame_view.h"
@@ -120,6 +116,7 @@
#include "third_party/blink/renderer/core/html/html_table_rows_collection.h"
#include "third_party/blink/renderer/core/html/html_template_element.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
+#include "third_party/blink/renderer/core/html/parser/nesting_level_incrementer.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
#include "third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.h"
#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
@@ -139,17 +136,21 @@
#include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.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/probe/core_probes.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observation.h"
#include "third_party/blink/renderer/core/svg/svg_a_element.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/core/svg_names.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_html.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_script_url.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_url.h"
#include "third_party/blink/renderer/core/xml_names.h"
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_dom_activity_logger.h"
#include "third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h"
-#include "third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scroll/scrollable_area.h"
@@ -497,7 +498,8 @@ void Element::scrollIntoView(bool align_to_top) {
static ScrollAlignment ToPhysicalAlignment(const ScrollIntoViewOptions& options,
ScrollOrientation axis,
- bool is_horizontal_writing_mode) {
+ bool is_horizontal_writing_mode,
+ bool is_flipped_blocks_mode) {
String alignment =
((axis == kHorizontalScroll && is_horizontal_writing_mode) ||
(axis == kVerticalScroll && !is_horizontal_writing_mode))
@@ -509,12 +511,16 @@ static ScrollAlignment ToPhysicalAlignment(const ScrollIntoViewOptions& options,
if (alignment == "nearest")
return ScrollAlignment::kAlignToEdgeIfNeeded;
if (alignment == "start") {
- return (axis == kHorizontalScroll) ? ScrollAlignment::kAlignLeftAlways
- : ScrollAlignment::kAlignTopAlways;
+ return (axis == kHorizontalScroll)
+ ? is_flipped_blocks_mode ? ScrollAlignment::kAlignRightAlways
+ : ScrollAlignment::kAlignLeftAlways
+ : ScrollAlignment::kAlignTopAlways;
}
if (alignment == "end") {
- return (axis == kHorizontalScroll) ? ScrollAlignment::kAlignRightAlways
- : ScrollAlignment::kAlignBottomAlways;
+ return (axis == kHorizontalScroll)
+ ? is_flipped_blocks_mode ? ScrollAlignment::kAlignLeftAlways
+ : ScrollAlignment::kAlignRightAlways
+ : ScrollAlignment::kAlignBottomAlways;
}
// Default values
@@ -528,7 +534,11 @@ static ScrollAlignment ToPhysicalAlignment(const ScrollIntoViewOptions& options,
void Element::scrollIntoViewWithOptions(const ScrollIntoViewOptions& options) {
GetDocument().EnsurePaintLocationDataValidForNode(this);
+ ScrollIntoViewNoVisualUpdate(options);
+}
+void Element::ScrollIntoViewNoVisualUpdate(
+ const ScrollIntoViewOptions& options) {
if (!GetLayoutObject() || !GetDocument().GetPage())
return;
@@ -544,10 +554,14 @@ void Element::scrollIntoViewWithOptions(const ScrollIntoViewOptions& options) {
bool is_horizontal_writing_mode =
GetComputedStyle()->IsHorizontalWritingMode();
- ScrollAlignment align_x = ToPhysicalAlignment(options, kHorizontalScroll,
- is_horizontal_writing_mode);
+ bool is_flipped_blocks_mode =
+ GetComputedStyle()->IsFlippedBlocksWritingMode();
+ ScrollAlignment align_x =
+ ToPhysicalAlignment(options, kHorizontalScroll,
+ is_horizontal_writing_mode, is_flipped_blocks_mode);
ScrollAlignment align_y =
- ToPhysicalAlignment(options, kVerticalScroll, is_horizontal_writing_mode);
+ ToPhysicalAlignment(options, kVerticalScroll, is_horizontal_writing_mode,
+ is_flipped_blocks_mode);
LayoutRect bounds = BoundingBoxForScrollIntoView();
GetLayoutObject()->ScrollRectToVisible(
@@ -958,9 +972,11 @@ void Element::setScrollLeft(double new_left) {
FloatPoint end_point(new_left * box->Style()->EffectiveZoom(),
box->ScrollTop().ToFloat());
- if (SnapCoordinator* coordinator = GetDocument().GetSnapCoordinator()) {
- end_point =
- coordinator->GetSnapPositionForPoint(*box, end_point, true, false);
+ if (RuntimeEnabledFeatures::CSSScrollSnapPointsEnabled()) {
+ end_point = GetDocument()
+ .GetSnapCoordinator()
+ ->GetSnapPositionForPoint(*box, end_point, true, false)
+ .value_or(end_point);
}
box->SetScrollLeft(LayoutUnit::FromFloatRound(end_point.X()));
}
@@ -987,9 +1003,11 @@ void Element::setScrollTop(double new_top) {
FloatPoint end_point(box->ScrollLeft().ToFloat(),
new_top * box->Style()->EffectiveZoom());
- if (SnapCoordinator* coordinator = GetDocument().GetSnapCoordinator()) {
- end_point =
- coordinator->GetSnapPositionForPoint(*box, end_point, false, true);
+ if (RuntimeEnabledFeatures::CSSScrollSnapPointsEnabled()) {
+ end_point = GetDocument()
+ .GetSnapCoordinator()
+ ->GetSnapPositionForPoint(*box, end_point, false, true)
+ .value_or(end_point);
}
box->SetScrollTop(LayoutUnit::FromFloatRound(end_point.Y()));
}
@@ -1004,11 +1022,7 @@ int Element::scrollWidth() {
if (GetDocument().ScrollingElementNoLayout() == this) {
if (GetDocument().View()) {
return AdjustForAbsoluteZoom::AdjustInt(
- GetDocument()
- .View()
- ->LayoutViewportScrollableArea()
- ->ContentsSize()
- .Width(),
+ GetDocument().View()->LayoutViewport()->ContentsSize().Width(),
GetDocument().GetFrame()->PageZoomFactor());
}
return 0;
@@ -1030,11 +1044,7 @@ int Element::scrollHeight() {
if (GetDocument().ScrollingElementNoLayout() == this) {
if (GetDocument().View()) {
return AdjustForAbsoluteZoom::AdjustInt(
- GetDocument()
- .View()
- ->LayoutViewportScrollableArea()
- ->ContentsSize()
- .Height(),
+ GetDocument().View()->LayoutViewport()->ContentsSize().Height(),
GetDocument().GetFrame()->PageZoomFactor());
}
return 0;
@@ -1114,10 +1124,14 @@ void Element::ScrollLayoutBoxBy(const ScrollToOptions& scroll_to_options) {
top * box->Style()->EffectiveZoom() + current_scaled_top;
FloatPoint new_scaled_position(new_scaled_left, new_scaled_top);
- if (SnapCoordinator* coordinator = GetDocument().GetSnapCoordinator()) {
- new_scaled_position = coordinator->GetSnapPositionForPoint(
- *box, new_scaled_position, scroll_to_options.hasLeft(),
- scroll_to_options.hasTop());
+ if (RuntimeEnabledFeatures::CSSScrollSnapPointsEnabled()) {
+ new_scaled_position =
+ GetDocument()
+ .GetSnapCoordinator()
+ ->GetSnapPositionForPoint(*box, new_scaled_position,
+ scroll_to_options.hasLeft(),
+ scroll_to_options.hasTop())
+ .value_or(new_scaled_position);
}
box->ScrollToPosition(new_scaled_position, scroll_behavior);
}
@@ -1142,10 +1156,14 @@ void Element::ScrollLayoutBoxTo(const ScrollToOptions& scroll_to_options) {
box->Style()->EffectiveZoom();
FloatPoint new_scaled_position(scaled_left, scaled_top);
- if (SnapCoordinator* coordinator = GetDocument().GetSnapCoordinator()) {
- new_scaled_position = coordinator->GetSnapPositionForPoint(
- *box, new_scaled_position, scroll_to_options.hasLeft(),
- scroll_to_options.hasTop());
+ if (RuntimeEnabledFeatures::CSSScrollSnapPointsEnabled()) {
+ new_scaled_position =
+ GetDocument()
+ .GetSnapCoordinator()
+ ->GetSnapPositionForPoint(*box, new_scaled_position,
+ scroll_to_options.hasLeft(),
+ scroll_to_options.hasTop())
+ .value_or(new_scaled_position);
}
box->ScrollToPosition(new_scaled_position, scroll_behavior);
}
@@ -1168,7 +1186,7 @@ void Element::ScrollFrameBy(const ScrollToOptions& scroll_to_options) {
if (!frame || !frame->View() || !GetDocument().GetPage())
return;
- ScrollableArea* viewport = frame->View()->LayoutViewportScrollableArea();
+ ScrollableArea* viewport = frame->View()->LayoutViewport();
if (!viewport)
return;
@@ -1182,15 +1200,19 @@ void Element::ScrollFrameBy(const ScrollToOptions& scroll_to_options) {
float new_scaled_top =
top * frame->PageZoomFactor() + viewport->GetScrollOffset().Height();
- FloatPoint new_scaled_position = ScrollOffsetToPosition(
- ScrollOffset(new_scaled_left, new_scaled_top), viewport->ScrollOrigin());
- if (SnapCoordinator* coordinator = GetDocument().GetSnapCoordinator()) {
- new_scaled_position = coordinator->GetSnapPositionForPoint(
- *GetDocument().GetLayoutView(), new_scaled_position,
- scroll_to_options.hasLeft(), scroll_to_options.hasTop());
+ FloatPoint new_scaled_position = viewport->ScrollOffsetToPosition(
+ ScrollOffset(new_scaled_left, new_scaled_top));
+ if (RuntimeEnabledFeatures::CSSScrollSnapPointsEnabled()) {
+ new_scaled_position =
+ GetDocument()
+ .GetSnapCoordinator()
+ ->GetSnapPositionForPoint(
+ *GetDocument().GetLayoutView(), new_scaled_position,
+ scroll_to_options.hasLeft(), scroll_to_options.hasTop())
+ .value_or(new_scaled_position);
}
viewport->SetScrollOffset(
- ScrollPositionToOffset(new_scaled_position, viewport->ScrollOrigin()),
+ viewport->ScrollPositionToOffset(new_scaled_position),
kProgrammaticScroll, scroll_behavior);
}
@@ -1202,7 +1224,7 @@ void Element::ScrollFrameTo(const ScrollToOptions& scroll_to_options) {
if (!frame || !frame->View() || !GetDocument().GetPage())
return;
- ScrollableArea* viewport = frame->View()->LayoutViewportScrollableArea();
+ ScrollableArea* viewport = frame->View()->LayoutViewport();
if (!viewport)
return;
@@ -1223,15 +1245,19 @@ void Element::ScrollFrameTo(const ScrollToOptions& scroll_to_options) {
ScrollableArea::NormalizeNonFiniteScroll(scroll_to_options.top()) *
frame->PageZoomFactor();
- FloatPoint new_scaled_position = ScrollOffsetToPosition(
- ScrollOffset(scaled_left, scaled_top), viewport->ScrollOrigin());
- if (SnapCoordinator* coordinator = GetDocument().GetSnapCoordinator()) {
- new_scaled_position = coordinator->GetSnapPositionForPoint(
- *GetDocument().GetLayoutView(), new_scaled_position,
- scroll_to_options.hasLeft(), scroll_to_options.hasTop());
+ FloatPoint new_scaled_position =
+ viewport->ScrollOffsetToPosition(ScrollOffset(scaled_left, scaled_top));
+ if (RuntimeEnabledFeatures::CSSScrollSnapPointsEnabled()) {
+ new_scaled_position =
+ GetDocument()
+ .GetSnapCoordinator()
+ ->GetSnapPositionForPoint(
+ *GetDocument().GetLayoutView(), new_scaled_position,
+ scroll_to_options.hasLeft(), scroll_to_options.hasTop())
+ .value_or(new_scaled_position);
}
viewport->SetScrollOffset(
- ScrollPositionToOffset(new_scaled_position, viewport->ScrollOrigin()),
+ viewport->ScrollPositionToOffset(new_scaled_position),
kProgrammaticScroll, scroll_behavior);
}
@@ -1278,7 +1304,7 @@ IntRect Element::BoundsInViewport() const {
for (size_t i = 1; i < quads.size(); ++i)
result.Unite(quads[i].EnclosingBoundingBox());
- return view->ContentsToViewport(result);
+ return view->FrameToViewport(result);
}
IntRect Element::VisibleBoundsInVisualViewport() const {
@@ -1291,7 +1317,7 @@ IntRect Element::VisibleBoundsInVisualViewport() const {
LayoutRect rect(
RoundedIntRect(GetLayoutObject()->AbsoluteBoundingBoxFloatRect()));
LayoutRect frame_clip_rect =
- GetDocument().View()->GetLayoutBox()->ClippingRect(LayoutPoint());
+ GetDocument().View()->GetLayoutView()->ClippingRect(LayoutPoint());
rect.Intersect(frame_clip_rect);
// MapToVisualRectInAncestorSpace, called with a null ancestor argument,
@@ -1408,6 +1434,79 @@ AccessibleNode* Element::accessibleNode() {
return rare_data.EnsureAccessibleNode(this);
}
+bool Element::toggleAttribute(const AtomicString& qualified_name,
+ ExceptionState& exception_state) {
+ // https://dom.spec.whatwg.org/#dom-element-toggleattribute
+ // 1. If qualifiedName does not match the Name production in XML, then throw
+ // an "InvalidCharacterError" DOMException.
+ if (!Document::IsValidName(qualified_name)) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidCharacterError,
+ "'" + qualified_name + "' is not a valid attribute name.");
+ return false;
+ }
+ // 2. If the context object is in the HTML namespace and its node document is
+ // an HTML document, then set qualifiedName to qualifiedName in ASCII
+ // lowercase.
+ AtomicString lower_case_name = LowercaseIfNecessary(qualified_name);
+ // 3. Let attribute be the first attribute in the context object’s attribute
+ // list whose qualified name is qualifiedName, and null otherwise.
+ // 4. If attribute is null, then
+ if (!getAttribute(lower_case_name)) {
+ // 4. 1. If force is not given or is true, create an attribute whose local
+ // name is qualifiedName, value is the empty string, and node document is
+ // the context object’s node document, then append this attribute to the
+ // context object, and then return true.
+ setAttribute(lower_case_name, g_empty_atom);
+ return true;
+ }
+ // 5. Otherwise, if force is not given or is false, remove an attribute given
+ // qualifiedName and the context object, and then return false.
+ removeAttribute(lower_case_name);
+ return false;
+}
+
+bool Element::toggleAttribute(const AtomicString& qualified_name,
+ bool force,
+ ExceptionState& exception_state) {
+ // https://dom.spec.whatwg.org/#dom-element-toggleattribute
+ // 1. If qualifiedName does not match the Name production in XML, then throw
+ // an "InvalidCharacterError" DOMException.
+ if (!Document::IsValidName(qualified_name)) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidCharacterError,
+ "'" + qualified_name + "' is not a valid attribute name.");
+ return false;
+ }
+ // 2. If the context object is in the HTML namespace and its node document is
+ // an HTML document, then set qualifiedName to qualifiedName in ASCII
+ // lowercase.
+ AtomicString lower_case_name = LowercaseIfNecessary(qualified_name);
+ // 3. Let attribute be the first attribute in the context object’s attribute
+ // list whose qualified name is qualifiedName, and null otherwise.
+ // 4. If attribute is null, then
+ if (!getAttribute(lower_case_name)) {
+ // 4. 1. If force is not given or is true, create an attribute whose local
+ // name is qualifiedName, value is the empty string, and node document is
+ // the context object’s node document, then append this attribute to the
+ // context object, and then return true.
+ if (force) {
+ setAttribute(lower_case_name, g_empty_atom);
+ return true;
+ }
+ // 4. 2. Return false.
+ return false;
+ }
+ // 5. Otherwise, if force is not given or is false, remove an attribute given
+ // qualifiedName and the context object, and then return false.
+ if (!force) {
+ removeAttribute(lower_case_name);
+ return false;
+ }
+ // 6. Return true.
+ return true;
+}
+
const AtomicString& Element::getAttribute(
const AtomicString& local_name) const {
if (!GetElementData())
@@ -1430,7 +1529,7 @@ void Element::setAttribute(const AtomicString& local_name,
ExceptionState& exception_state) {
if (!Document::IsValidName(local_name)) {
exception_state.ThrowDOMException(
- kInvalidCharacterError,
+ DOMExceptionCode::kInvalidCharacterError,
"'" + local_name + "' is not a valid attribute name.");
return;
}
@@ -1480,6 +1579,24 @@ void Element::SetSynchronizedLazyAttribute(const QualifiedName& name,
}
void Element::setAttribute(const QualifiedName& name,
+ const StringOrTrustedHTML& stringOrHTML,
+ ExceptionState& exception_state) {
+ DCHECK(stringOrHTML.IsString() ||
+ RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
+ if (stringOrHTML.IsString() && GetDocument().RequireTrustedTypes()) {
+ exception_state.ThrowTypeError(
+ "This document requires `TrustedHTML` assignment.");
+ return;
+ }
+
+ String valueString = stringOrHTML.IsString()
+ ? stringOrHTML.GetAsString()
+ : stringOrHTML.GetAsTrustedHTML()->toString();
+
+ setAttribute(name, AtomicString(valueString));
+}
+
+void Element::setAttribute(const QualifiedName& name,
const StringOrTrustedScriptURL& stringOrURL,
ExceptionState& exception_state) {
DCHECK(stringOrURL.IsString() ||
@@ -1497,6 +1614,24 @@ void Element::setAttribute(const QualifiedName& name,
setAttribute(name, AtomicString(valueString));
}
+void Element::setAttribute(const QualifiedName& name,
+ const USVStringOrTrustedURL& stringOrURL,
+ ExceptionState& exception_state) {
+ DCHECK(stringOrURL.IsUSVString() ||
+ RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
+ if (stringOrURL.IsUSVString() && GetDocument().RequireTrustedTypes()) {
+ exception_state.ThrowTypeError(
+ "This document requires `TrustedURL` assignment.");
+ return;
+ }
+
+ String valueString = stringOrURL.IsUSVString()
+ ? stringOrURL.GetAsUSVString()
+ : stringOrURL.GetAsTrustedURL()->toString();
+
+ setAttribute(name, AtomicString(valueString));
+}
+
ALWAYS_INLINE void Element::SetAttributeInternal(
size_t index,
const QualifiedName& name,
@@ -1571,11 +1706,15 @@ void Element::AttributeChanged(const AttributeModificationParams& params) {
} else if (name == HTMLNames::nameAttr) {
SetHasName(!params.new_value.IsNull());
} else if (name == HTMLNames::partAttr) {
- if (RuntimeEnabledFeatures::CSSPartPseudoElementEnabled())
+ if (RuntimeEnabledFeatures::CSSPartPseudoElementEnabled()) {
EnsureElementRareData().SetPart(params.new_value);
+ GetDocument().GetStyleEngine().PartChangedForElement(*this);
+ }
} else if (name == HTMLNames::partmapAttr) {
- if (RuntimeEnabledFeatures::CSSPartPseudoElementEnabled())
+ if (RuntimeEnabledFeatures::CSSPartPseudoElementEnabled()) {
EnsureElementRareData().SetPartNamesMap(params.new_value);
+ GetDocument().GetStyleEngine().PartmapChangedForElement(*this);
+ }
} else if (IsStyledElement()) {
if (name == styleAttr) {
StyleAttributeChanged(params.new_value, params.reason);
@@ -1876,8 +2015,14 @@ Node::InsertionNotificationRequest Element::InsertedInto(
void Element::RemovedFrom(ContainerNode* insertion_point) {
bool was_in_document = insertion_point->isConnected();
-
- DCHECK(!HasRareData() || !GetElementRareData()->HasPseudoElements());
+ if (HasRareData()) {
+ // If we detached the layout tree with LazyReattachIfAttached, we might not
+ // have cleared the pseudo elements if we remove the element before calling
+ // AttachLayoutTree again. We don't clear pseudo elements on
+ // DetachLayoutTree() if we intend to attach again to avoid recreating the
+ // pseudo elements.
+ GetElementRareData()->ClearPseudoElements();
+ }
if (Fullscreen::IsFullscreenElement(*this)) {
SetContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);
@@ -1889,9 +2034,6 @@ void Element::RemovedFrom(ContainerNode* insertion_point) {
}
}
- if (Fullscreen* fullscreen = Fullscreen::FromIfExists(GetDocument()))
- fullscreen->ElementRemoved(*this);
-
if (GetDocument().GetPage())
GetDocument().GetPage()->GetPointerLockController().ElementRemoved(this);
@@ -1927,7 +2069,10 @@ void Element::RemovedFrom(ContainerNode* insertion_point) {
GetDocument().GetRootScrollerController().ElementRemoved(*this);
- GetDocument().RemoveFromTopLayer(this);
+ if (IsInTopLayer()) {
+ Fullscreen::ElementRemoved(*this);
+ GetDocument().RemoveFromTopLayer(this);
+ }
ClearElementFlag(ElementFlags::kIsInCanvasSubtree);
@@ -1951,9 +2096,15 @@ void Element::RemovedFrom(ContainerNode* insertion_point) {
void Element::AttachLayoutTree(AttachContext& context) {
DCHECK(GetDocument().InStyleRecalc());
- // We've already been through detach when doing an attach, but we might
- // need to clear any state that's been added since then.
- if (HasRareData() && NeedsAttach()) {
+ if (HasRareData() && NeedsAttach() && !IsPseudoElement()) {
+ // We have already been through detach when doing an attach, but we may have
+ // done a getComputedStyle() in between storing the ComputedStyle on rare
+ // data if the detach was a LazyReattachIfAttached().
+ //
+ // We do not clear it for pseudo elements because we store the original
+ // style in rare data for display:contents when the ComputedStyle used for
+ // the LayoutObject is an inline only inheriting properties from the element
+ // parent.
ElementRareData* data = GetElementRareData();
data->ClearComputedStyle();
}
@@ -1970,11 +2121,13 @@ void Element::AttachLayoutTree(AttachContext& context) {
if (HasRareData() && !GetLayoutObject() &&
!GetElementRareData()->GetComputedStyle()) {
+ ElementRareData* rare_data = GetElementRareData();
if (ElementAnimations* element_animations =
- GetElementRareData()->GetElementAnimations()) {
+ rare_data->GetElementAnimations()) {
element_animations->CssAnimations().Cancel();
element_animations->SetAnimationStyleChange(false);
}
+ rare_data->ClearPseudoElements();
}
SelectorFilterParentScope filter_scope(*this);
@@ -1987,7 +2140,7 @@ void Element::AttachLayoutTree(AttachContext& context) {
children_context.use_previous_in_flow = true;
ClearNeedsReattachLayoutTree();
- CreateAndAttachPseudoElementIfNeeded(kPseudoIdBefore, children_context);
+ AttachPseudoElement(kPseudoIdBefore, children_context);
// When a shadow root exists, it does the work of attaching the children.
if (ShadowRoot* shadow_root = GetShadowRoot()) {
@@ -1999,13 +2152,19 @@ void Element::AttachLayoutTree(AttachContext& context) {
SetNonAttachedStyle(nullptr);
AddCallbackSelectors();
- CreateAndAttachPseudoElementIfNeeded(kPseudoIdAfter, children_context);
- CreateAndAttachPseudoElementIfNeeded(kPseudoIdBackdrop, children_context);
+ AttachPseudoElement(kPseudoIdAfter, children_context);
+ AttachPseudoElement(kPseudoIdBackdrop, children_context);
// We create the first-letter element after the :before, :after and
// children are attached because the first letter text could come
// from any of them.
- CreateAndAttachPseudoElementIfNeeded(kPseudoIdFirstLetter, children_context);
+ //
+ // TODO(futhark@chromium.org: Replace with AttachPseudoElement when we create
+ // ::first-letter elements during style recalc.
+ if (PseudoElement* first_letter =
+ CreatePseudoElementIfNeeded(kPseudoIdFirstLetter)) {
+ first_letter->AttachLayoutTree(children_context);
+ }
if (layout_object) {
if (!layout_object->IsFloatingOrOutOfFlowPositioned())
@@ -2021,7 +2180,10 @@ void Element::DetachLayoutTree(const AttachContext& context) {
RemoveCallbackSelectors();
if (HasRareData()) {
ElementRareData* data = GetElementRareData();
- data->ClearPseudoElements();
+ if (context.performing_reattach)
+ data->SetPseudoElement(kPseudoIdFirstLetter, nullptr);
+ else
+ data->ClearPseudoElements();
// attachLayoutTree() will clear the computed style for us when inside
// recalcStyle.
@@ -2045,12 +2207,17 @@ void Element::DetachLayoutTree(const AttachContext& context) {
element_animations->ClearBaseComputedStyle();
}
+ DetachPseudoElement(kPseudoIdBefore, context);
+
if (ShadowRoot* shadow_root = data->GetShadowRoot())
shadow_root->DetachLayoutTree(context);
}
ContainerNode::DetachLayoutTree(context);
+ DetachPseudoElement(kPseudoIdAfter, context);
+ DetachPseudoElement(kPseudoIdBackdrop, context);
+
if (!context.performing_reattach && IsUserActionElement()) {
if (IsHovered())
GetDocument().HoveredElementDetached(*this);
@@ -2084,7 +2251,8 @@ scoped_refptr<ComputedStyle> Element::StyleForLayoutObject() {
? CustomStyleForLayoutObject()
: OriginalStyleForLayoutObject();
if (!style) {
- DCHECK(IsBeforePseudoElement() || IsAfterPseudoElement());
+ DCHECK(IsBeforePseudoElement() || IsAfterPseudoElement() ||
+ GetPseudoId() == kPseudoIdBackdrop);
return nullptr;
}
@@ -2116,6 +2284,18 @@ scoped_refptr<ComputedStyle> Element::OriginalStyleForLayoutObject() {
return GetDocument().EnsureStyleResolver().StyleForElement(this);
}
+bool Element::ShouldCallRecalcStyleForChildren(StyleRecalcChange change) {
+ if (change != kReattach)
+ return change >= kUpdatePseudoElements || ChildNeedsStyleRecalc();
+ if (!ChildrenCanHaveStyle())
+ return false;
+ if (const ComputedStyle* new_style = GetNonAttachedStyle()) {
+ return LayoutObjectIsNeeded(*new_style) ||
+ ShouldStoreNonLayoutObjectComputedStyle(*new_style);
+ }
+ return !CanParticipateInFlatTree();
+}
+
void Element::RecalcStyle(StyleRecalcChange change) {
DCHECK(GetDocument().InStyleRecalc());
DCHECK(!GetDocument().Lifecycle().InDetach());
@@ -2157,29 +2337,37 @@ void Element::RecalcStyle(StyleRecalcChange change) {
element_animations->SetAnimationStyleChange(false);
}
}
+
if (ParentComputedStyle()) {
change = RecalcOwnStyle(change);
- } else if (NeedsAttach()) {
- if (!CanParticipateInFlatTree()) {
- // Recalculate style for reattachment of Shadow DOM v0 <content>
- // fallback.
- RecalcShadowIncludingDescendantStylesForReattach();
- }
- SetNeedsReattachLayoutTree();
- change = kReattach;
+ } else if (!CanParticipateInFlatTree()) {
+ // Recalculate style for Shadow DOM v0 <content> insertion point.
+ // It does not take style since it's not part of the flat tree, but we
+ // need to traverse into fallback children for reattach.
+ if (NeedsAttach())
+ change = kReattach;
+ if (change == kReattach)
+ SetNeedsReattachLayoutTree();
}
- // Needed because the rebuildLayoutTree code needs to see what the
- // styleChangeType() was on reattach roots. See Node::reattachLayoutTree()
+ // Needed because the RebuildLayoutTree code needs to see what the
+ // StyleChangeType() was on reattach roots. See Node::ReattachLayoutTree()
// for an example.
if (change != kReattach)
ClearNeedsStyleRecalc();
}
- // If we are going to reattach we don't need to recalc the style of
- // our descendants anymore.
- if (change < kReattach &&
- (change >= kUpdatePseudoElements || ChildNeedsStyleRecalc())) {
+ if (change >= kUpdatePseudoElements || ChildNeedsStyleRecalc()) {
+ // ChildrenCanHaveStyle(), hence ShouldCallRecalcStyleForChildren(),
+ // returns false for <object> elements below. Yet, they may have ::backdrop
+ // elements.
+ UpdatePseudoElement(kPseudoIdBackdrop, change);
+ }
+
+ if (ShouldCallRecalcStyleForChildren(change)) {
+ // TODO(futhark@chromium.org): Pseudo elements are feature-less and match
+ // the same features as their originating element. Move the filter scope
+ // inside the if-block for shadow-including descendants below.
SelectorFilterParentScope filter_scope(*this);
UpdatePseudoElement(kPseudoIdBefore, change);
@@ -2193,14 +2381,14 @@ void Element::RecalcStyle(StyleRecalcChange change) {
}
UpdatePseudoElement(kPseudoIdAfter, change);
- UpdatePseudoElement(kPseudoIdBackdrop, change);
// If our children have changed then we need to force the first-letter
// checks as we don't know if they effected the first letter or not.
// This can be seen when a child transitions from floating to
// non-floating we have to take it into account for the first letter.
- UpdatePseudoElement(kPseudoIdFirstLetter,
- ChildNeedsStyleRecalc() ? kForce : change);
+ UpdatePseudoElement(
+ kPseudoIdFirstLetter,
+ change < kForce && ChildNeedsStyleRecalc() ? kForce : change);
ClearChildNeedsStyleRecalc();
}
@@ -2236,6 +2424,7 @@ StyleRecalcChange Element::RecalcOwnStyle(StyleRecalcChange change) {
DCHECK(!ParentOrShadowHostNode()->NeedsStyleRecalc());
DCHECK(change >= kIndependentInherit || NeedsStyleRecalc());
DCHECK(ParentComputedStyle());
+ DCHECK(!GetNonAttachedStyle());
scoped_refptr<const ComputedStyle> old_style = GetComputedStyle();
@@ -2245,8 +2434,11 @@ StyleRecalcChange Element::RecalcOwnStyle(StyleRecalcChange change) {
scoped_refptr<ComputedStyle> new_style = PropagateInheritedProperties(change);
if (!new_style)
new_style = StyleForLayoutObject();
- if (!new_style)
+ if (!new_style) {
+ DCHECK(IsPseudoElement());
+ SetNeedsReattachLayoutTree();
return kReattach;
+ }
StyleRecalcChange local_change =
ComputedStyle::StylePropagationDiff(old_style.get(), new_style.get());
@@ -2269,13 +2461,9 @@ StyleRecalcChange Element::RecalcOwnStyle(StyleRecalcChange change) {
}
}
- if (local_change == kReattach) {
+ if (change == kReattach || local_change == kReattach) {
SetNonAttachedStyle(new_style);
SetNeedsReattachLayoutTree();
- if (LayoutObjectIsNeeded(*new_style) ||
- ShouldStoreNonLayoutObjectComputedStyle(*new_style)) {
- RecalcShadowIncludingDescendantStylesForReattach();
- }
return kReattach;
}
@@ -2321,45 +2509,6 @@ StyleRecalcChange Element::RecalcOwnStyle(StyleRecalcChange change) {
return local_change;
}
-void Element::RecalcStyleForReattach() {
- if (HasCustomStyleCallbacks())
- WillRecalcStyle(kReattach);
-
- bool recalc_descendants = false;
- if (ParentComputedStyle()) {
- scoped_refptr<ComputedStyle> non_attached_style = StyleForLayoutObject();
- SetNeedsReattachLayoutTree();
- SetNonAttachedStyle(non_attached_style);
- recalc_descendants =
- LayoutObjectIsNeeded(*non_attached_style) ||
- ShouldStoreNonLayoutObjectComputedStyle(*non_attached_style);
- } else {
- // Elements which cannot participate in the flat tree are <content> and
- // <slot> if SlotInFlatTree is not enabled. Even though we should not
- // compute their styles for re-attachment, we may need to compute their
- // children's style if fallback is rendered.
- recalc_descendants = !CanParticipateInFlatTree();
- }
- if (recalc_descendants)
- RecalcShadowIncludingDescendantStylesForReattach();
-
- if (HasCustomStyleCallbacks())
- DidRecalcStyle(kReattach);
-}
-
-void Element::RecalcShadowIncludingDescendantStylesForReattach() {
- if (!ChildrenCanHaveStyle())
- return;
- SelectorFilterParentScope filterScope(*this);
- RecalcShadowRootStylesForReattach();
- RecalcDescendantStylesForReattach();
-}
-
-void Element::RecalcShadowRootStylesForReattach() {
- if (ShadowRoot* root = GetShadowRoot())
- root->RecalcStylesForReattach();
-}
-
void Element::RebuildLayoutTree(WhitespaceAttacher& whitespace_attacher) {
DCHECK(InActiveDocument());
DCHECK(parentNode());
@@ -2381,7 +2530,7 @@ void Element::RebuildLayoutTree(WhitespaceAttacher& whitespace_attacher) {
// layout tree siblings.
WhitespaceAttacher local_attacher;
WhitespaceAttacher* child_attacher;
- if (GetLayoutObject()) {
+ if (GetLayoutObject() || !HasDisplayContentsStyle()) {
whitespace_attacher.DidVisitElement(this);
if (GetDocument().GetStyleEngine().NeedsWhitespaceReattachment(this))
local_attacher.SetReattachAllWhitespaceNodes();
@@ -2417,16 +2566,28 @@ void Element::RebuildPseudoElementLayoutTree(
PseudoId pseudo_id,
WhitespaceAttacher& whitespace_attacher) {
PseudoElement* element = GetPseudoElement(pseudo_id);
- if (element) {
- if (pseudo_id == kPseudoIdFirstLetter && UpdateFirstLetter(element))
- return;
- } else {
- element = CreatePseudoElementIfNeeded(pseudo_id);
+ if (pseudo_id == kPseudoIdFirstLetter) {
+ // Need to create a ::first-letter element here for the following case:
+ //
+ // <style>#outer::first-letter {...}</style>
+ // <div id=outer><div id=inner style="display:none">Text</div></div>
+ // <script> outer.offsetTop; inner.style.display = "block" </script>
+ //
+ // The creation of FirstLetterPseudoElement relies on the layout tree of the
+ // block contents. In this case, the ::first-letter element is not created
+ // initially since the #inner div is not displayed. On RecalcStyle it's not
+ // created since the layout tree is still not built, and AttachLayoutTree
+ // for #inner will not update the ::first-letter of outer. However, we end
+ // up here for #outer after AttachLayoutTree is called on #inner at which
+ // point the layout sub-tree is available for deciding on creating the
+ // ::first-letter.
if (!element)
+ element = CreatePseudoElementIfNeeded(pseudo_id);
+ else if (UpdateFirstLetter(element))
return;
}
- if (element->NeedsRebuildLayoutTree(whitespace_attacher))
+ if (element && element->NeedsRebuildLayoutTree(whitespace_attacher))
element->RebuildLayoutTree(whitespace_attacher);
}
@@ -2453,20 +2614,32 @@ void Element::RemoveCallbackSelectors() {
}
ShadowRoot& Element::CreateAndAttachShadowRoot(ShadowRootType type) {
+#if DCHECK_IS_ON()
+ NestingLevelIncrementer slot_assignment_recalc_forbidden_scope(
+ GetDocument().SlotAssignmentRecalcForbiddenRecursionDepth());
+#endif
EventDispatchForbiddenScope assert_no_event_dispatch;
ScriptForbiddenScope forbid_script;
DCHECK(!GetShadowRoot());
ShadowRoot* shadow_root = ShadowRoot::Create(GetDocument(), type);
+
+ if (type != ShadowRootType::V0) {
+ // Detach the host's children here for v1 (including UA shadow root),
+ // because we skip SetNeedsDistributionRecalc() in attaching v1 shadow root.
+ // See https://crrev.com/2822113002 for details.
+ // We need to call child.LazyReattachIfAttached() before setting a shadow
+ // root to the element because detach must use the original flat tree
+ // structure before attachShadow happens.
+ for (Node& child : NodeTraversal::ChildrenOf(*this))
+ child.LazyReattachIfAttached();
+ }
EnsureElementRareData().SetShadowRoot(*shadow_root);
shadow_root->SetParentOrShadowHostNode(this);
shadow_root->SetParentTreeScope(GetTreeScope());
if (type == ShadowRootType::V0) {
shadow_root->SetNeedsDistributionRecalc();
- } else {
- for (Node& child : NodeTraversal::ChildrenOf(*this))
- child.LazyReattachIfAttached();
}
shadow_root->InsertedInto(this);
@@ -2573,20 +2746,16 @@ const AtomicString& Element::IsValue() const {
return g_null_atom;
}
-ShadowRoot* Element::createShadowRoot(const ScriptState* script_state,
- ExceptionState& exception_state) {
- HostsUsingFeatures::CountMainWorldOnly(
- script_state, GetDocument(),
- HostsUsingFeatures::Feature::kElementCreateShadowRoot);
+ShadowRoot* Element::createShadowRoot(ExceptionState& exception_state) {
if (ShadowRoot* root = GetShadowRoot()) {
if (root->IsUserAgent()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Shadow root cannot be created on a host which already hosts a "
"user-agent shadow tree.");
} else {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Shadow root cannot be created on a host which already hosts a "
"shadow tree.");
}
@@ -2594,7 +2763,7 @@ ShadowRoot* Element::createShadowRoot(const ScriptState* script_state,
}
if (AlwaysCreateUserAgentShadowRoot()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Shadow root cannot be created on a host which already hosts a "
"user-agent shadow tree.");
return nullptr;
@@ -2603,7 +2772,7 @@ ShadowRoot* Element::createShadowRoot(const ScriptState* script_state,
// as children so we can't allow author shadows on them for now.
if (!AreAuthorShadowsAllowed()) {
exception_state.ThrowDOMException(
- kHierarchyRequestError,
+ DOMExceptionCode::kHierarchyRequestError,
"Author-created shadow roots are disabled for this element.");
return nullptr;
}
@@ -2629,22 +2798,18 @@ bool Element::CanAttachShadowRoot() const {
tag_name == HTMLNames::spanTag;
}
-ShadowRoot* Element::attachShadow(const ScriptState* script_state,
- const ShadowRootInit& shadow_root_init_dict,
+ShadowRoot* Element::attachShadow(const ShadowRootInit& shadow_root_init_dict,
ExceptionState& exception_state) {
DCHECK(shadow_root_init_dict.hasMode());
- HostsUsingFeatures::CountMainWorldOnly(
- script_state, GetDocument(),
- HostsUsingFeatures::Feature::kElementAttachShadow);
-
if (!CanAttachShadowRoot()) {
exception_state.ThrowDOMException(
- kNotSupportedError, "This element does not support attachShadow");
+ DOMExceptionCode::kNotSupportedError,
+ "This element does not support attachShadow");
return nullptr;
}
if (GetShadowRoot()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Shadow root cannot be created on a host "
"which already hosts a shadow tree.");
return nullptr;
@@ -2823,7 +2988,7 @@ Attr* Element::setAttributeNode(Attr* attr_node,
// to re-use them in other elements.
if (attr_node->ownerElement()) {
exception_state.ThrowDOMException(
- kInUseAttributeError,
+ DOMExceptionCode::kInUseAttributeError,
"The node provided is an attribute node that is already an attribute "
"of another Element; attribute nodes must be explicitly cloned.");
return nullptr;
@@ -2882,7 +3047,8 @@ Attr* Element::removeAttributeNode(Attr* attr,
ExceptionState& exception_state) {
if (attr->ownerElement() != this) {
exception_state.ThrowDOMException(
- kNotFoundError, "The node provided is owned by another element.");
+ DOMExceptionCode::kNotFoundError,
+ "The node provided is owned by another element.");
return nullptr;
}
@@ -2894,7 +3060,8 @@ Attr* Element::removeAttributeNode(Attr* attr,
GetElementData()->Attributes().FindIndex(attr->GetQualifiedName());
if (index == kNotFound) {
exception_state.ThrowDOMException(
- kNotFoundError, "The attribute was not found on this element.");
+ DOMExceptionCode::kNotFoundError,
+ "The attribute was not found on this element.");
return nullptr;
}
@@ -2931,7 +3098,7 @@ bool Element::ParseAttributeName(QualifiedName& out,
if (!Document::HasValidNamespaceForAttributes(q_name)) {
exception_state.ThrowDOMException(
- kNamespaceError,
+ DOMExceptionCode::kNamespaceError,
"'" + namespace_uri + "' is an invalid namespace for attributes.");
return false;
}
@@ -3337,15 +3504,16 @@ void Element::SetOuterHTMLFromString(const String& html,
ExceptionState& exception_state) {
Node* p = parentNode();
if (!p) {
- exception_state.ThrowDOMException(kNoModificationAllowedError,
- "This element has no parent node.");
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNoModificationAllowedError,
+ "This element has no parent node.");
return;
}
if (!p->IsElementNode()) {
- exception_state.ThrowDOMException(kNoModificationAllowedError,
- "This element's parent is of type '" +
- p->nodeName() +
- "', which is not an element node.");
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNoModificationAllowedError,
+ "This element's parent is of type '" + p->nodeName() +
+ "', which is not an element node.");
return;
}
@@ -3417,9 +3585,10 @@ Node* Element::InsertAdjacent(const String& where,
}
exception_state.ThrowDOMException(
- kSyntaxError, "The value provided ('" + where +
- "') is not one of 'beforeBegin', 'afterBegin', "
- "'beforeEnd', or 'afterEnd'.");
+ DOMExceptionCode::kSyntaxError,
+ "The value provided ('" + where +
+ "') is not one of 'beforeBegin', 'afterBegin', "
+ "'beforeEnd', or 'afterEnd'.");
return nullptr;
}
@@ -3478,8 +3647,9 @@ static Element* ContextElementForInsertion(const String& where,
DeprecatedEqualIgnoringCase(where, "afterEnd")) {
Element* parent = element->parentElement();
if (!parent) {
- exception_state.ThrowDOMException(kNoModificationAllowedError,
- "The element has no parent.");
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNoModificationAllowedError,
+ "The element has no parent.");
return nullptr;
}
return parent;
@@ -3488,9 +3658,10 @@ static Element* ContextElementForInsertion(const String& where,
DeprecatedEqualIgnoringCase(where, "beforeEnd"))
return element;
exception_state.ThrowDOMException(
- kSyntaxError, "The value provided ('" + where +
- "') is not one of 'beforeBegin', 'afterBegin', "
- "'beforeEnd', or 'afterEnd'.");
+ DOMExceptionCode::kSyntaxError,
+ "The value provided ('" + where +
+ "') is not one of 'beforeBegin', 'afterBegin', "
+ "'beforeEnd', or 'afterEnd'.");
return nullptr;
}
@@ -3547,13 +3718,14 @@ void Element::setPointerCapture(int pointer_id,
if (GetDocument().GetFrame()) {
if (!GetDocument().GetFrame()->GetEventHandler().IsPointerEventActive(
pointer_id)) {
- exception_state.ThrowDOMException(kInvalidPointerId, "InvalidPointerId");
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidPointerId,
+ "InvalidPointerId");
} else if (!isConnected() ||
(GetDocument().GetPage() && GetDocument()
.GetPage()
->GetPointerLockController()
.GetElement())) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"InvalidStateError");
} else {
GetDocument().GetFrame()->GetEventHandler().SetPointerCapture(pointer_id,
@@ -3566,11 +3738,13 @@ void Element::releasePointerCapture(int pointer_id,
ExceptionState& exception_state) {
if (GetDocument().GetFrame()) {
if (!GetDocument().GetFrame()->GetEventHandler().IsPointerEventActive(
- pointer_id))
- exception_state.ThrowDOMException(kInvalidPointerId, "InvalidPointerId");
- else
+ pointer_id)) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidPointerId,
+ "InvalidPointerId");
+ } else {
GetDocument().GetFrame()->GetEventHandler().ReleasePointerCapture(
pointer_id, this);
+ }
}
}
@@ -3591,7 +3765,7 @@ String Element::innerText() {
// tree.
GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheetsForNode(this);
- if (!GetLayoutObject())
+ if (!GetLayoutObject() && !HasDisplayContentsStyle())
return textContent(true);
return PlainText(
@@ -3807,43 +3981,49 @@ void Element::CancelFocusAppearanceUpdate() {
void Element::UpdatePseudoElement(PseudoId pseudo_id,
StyleRecalcChange change) {
- DCHECK(!NeedsStyleRecalc());
- PseudoElement* element = GetPseudoElement(pseudo_id);
+ // TODO(futhark@chromium.org): Update ::first-letter pseudo elements and style
+ // as part of style recalc also when re-attaching.
+ if (change == kReattach && pseudo_id == kPseudoIdFirstLetter)
+ return;
- if (element && (change == kUpdatePseudoElements ||
- element->ShouldCallRecalcStyle(change))) {
- if (pseudo_id == kPseudoIdFirstLetter && UpdateFirstLetter(element))
- return;
+ PseudoElement* element = GetPseudoElement(pseudo_id);
+ if (!element) {
+ if (change >= kUpdatePseudoElements)
+ element = CreatePseudoElementIfNeeded(pseudo_id);
+ // TODO(futhark@chromium.org): We cannot SetNeedsReattachLayoutTree() for
+ // ::first-letter inside CreatePseudoElementIfNeeded() because it may be
+ // called from layout tree attachment.
+ if (element && pseudo_id == kPseudoIdFirstLetter)
+ element->SetNeedsReattachLayoutTree();
+ return;
+ }
- // Need to clear the cached style if the PseudoElement wants a recalc so it
- // computes a new style.
- if (element->NeedsStyleRecalc())
- MutableComputedStyle()->RemoveCachedPseudoStyle(pseudo_id);
-
- // PseudoElement styles hang off their parent element's style so if we
- // needed a style recalc we should Force one on the pseudo.
- element->RecalcStyle(change == kUpdatePseudoElements ? kForce : change);
-
- // Wait until our parent is not displayed or
- // PseudoElementLayoutObjectIsNeeded is false, otherwise we could
- // continuously create and destroy PseudoElements when
- // LayoutObject::IsChildAllowed on our parent returns false for the
- // PseudoElement's GetLayoutObject for each style recalc.
- if (!CanGeneratePseudoElement(pseudo_id) ||
- !PseudoElementLayoutObjectIsNeeded(
- PseudoStyle(PseudoStyleRequest(pseudo_id))))
- GetElementRareData()->SetPseudoElement(pseudo_id, nullptr);
- } else if (pseudo_id == kPseudoIdFirstLetter && element &&
+ if (change == kUpdatePseudoElements ||
+ element->ShouldCallRecalcStyle(change)) {
+ if (pseudo_id == kPseudoIdFirstLetter) {
+ if (UpdateFirstLetter(element))
+ return;
+ // Need to clear the cached style if the PseudoElement wants a recalc so
+ // it computes a new style.
+ if (element->NeedsStyleRecalc())
+ MutableComputedStyle()->RemoveCachedPseudoStyle(kPseudoIdFirstLetter);
+ }
+ if (CanGeneratePseudoElement(pseudo_id)) {
+ element->RecalcStyle(change == kUpdatePseudoElements ? kForce : change);
+ if (!element->NeedsReattachLayoutTree())
+ return;
+ if (PseudoElementLayoutObjectIsNeeded(element->GetNonAttachedStyle()))
+ return;
+ }
+ GetElementRareData()->SetPseudoElement(pseudo_id, nullptr);
+ } else if (pseudo_id == kPseudoIdFirstLetter &&
change >= kUpdatePseudoElements &&
!FirstLetterPseudoElement::FirstLetterTextLayoutObject(*element)) {
- // This can happen if we change to a float, for example. We need to cleanup
- // the first-letter pseudoElement and then fix the text of the original
- // remaining text layoutObject. This can be seen in Test 7 of
+ // We can end up here if we change to a float, for example. We need to
+ // cleanup the first-letter PseudoElement and then fix the text of the
+ // original remaining text LayoutObject. This can be seen in Test 7 of
// fast/css/first-letter-removed-added.html
- GetElementRareData()->SetPseudoElement(pseudo_id, nullptr);
- } else if (change >= kUpdatePseudoElements) {
- if (PseudoElement* new_pseudo = CreatePseudoElementIfNeeded(pseudo_id))
- new_pseudo->SetNeedsReattachLayoutTree();
+ GetElementRareData()->SetPseudoElement(kPseudoIdFirstLetter, nullptr);
}
}
@@ -3872,32 +4052,53 @@ bool Element::UpdateFirstLetter(Element* element) {
PseudoElement* Element::CreatePseudoElementIfNeeded(PseudoId pseudo_id) {
if (IsPseudoElement())
return nullptr;
+ if (!CanGeneratePseudoElement(pseudo_id))
+ return nullptr;
+ if (pseudo_id == kPseudoIdFirstLetter) {
+ if (IsSVGElement())
+ return nullptr;
+ if (!FirstLetterPseudoElement::FirstLetterTextLayoutObject(*this))
+ return nullptr;
+ }
- // Document::ensureStyleResolver is not inlined and shows up on profiles,
- // avoid it here.
- PseudoElement* element = GetDocument()
- .GetStyleEngine()
- .EnsureResolver()
- .CreatePseudoElementIfNeeded(*this, pseudo_id);
- if (!element)
+ PseudoElement* pseudo_element = PseudoElement::Create(this, pseudo_id);
+ EnsureElementRareData().SetPseudoElement(pseudo_id, pseudo_element);
+ pseudo_element->InsertedInto(this);
+
+ scoped_refptr<ComputedStyle> pseudo_style =
+ pseudo_element->StyleForLayoutObject();
+ if (!PseudoElementLayoutObjectIsNeeded(pseudo_style.get())) {
+ GetElementRareData()->SetPseudoElement(pseudo_id, nullptr);
return nullptr;
+ }
if (pseudo_id == kPseudoIdBackdrop)
- GetDocument().AddToTopLayer(element, this);
- element->InsertedInto(this);
+ GetDocument().AddToTopLayer(pseudo_element, this);
+
+ pseudo_element->SetNonAttachedStyle(std::move(pseudo_style));
+
+ // TODO(futhark@chromium.org): We cannot SetNeedsReattachLayoutTree() for
+ // ::first-letter inside CreatePseudoElementIfNeeded() because it may be
+ // called from layout tree attachment.
+ if (pseudo_id != kPseudoIdFirstLetter)
+ pseudo_element->SetNeedsReattachLayoutTree();
- probe::pseudoElementCreated(element);
+ probe::pseudoElementCreated(pseudo_element);
- EnsureElementRareData().SetPseudoElement(pseudo_id, element);
- return element;
+ return pseudo_element;
}
-void Element::CreateAndAttachPseudoElementIfNeeded(PseudoId pseudo_id,
- AttachContext& context) {
- if (PseudoElement* pseudo_element = CreatePseudoElementIfNeeded(pseudo_id))
+void Element::AttachPseudoElement(PseudoId pseudo_id, AttachContext& context) {
+ if (PseudoElement* pseudo_element = GetPseudoElement(pseudo_id))
pseudo_element->AttachLayoutTree(context);
}
+void Element::DetachPseudoElement(PseudoId pseudo_id,
+ const AttachContext& context) {
+ if (PseudoElement* pseudo_element = GetPseudoElement(pseudo_id))
+ pseudo_element->DetachLayoutTree(context);
+}
+
PseudoElement* Element::GetPseudoElement(PseudoId pseudo_id) const {
return HasRareData() ? GetElementRareData()->GetPseudoElement(pseudo_id)
: nullptr;
@@ -3909,8 +4110,9 @@ LayoutObject* Element::PseudoElementLayoutObject(PseudoId pseudo_id) const {
return nullptr;
}
-ComputedStyle* Element::PseudoStyle(const PseudoStyleRequest& request,
- const ComputedStyle* parent_style) {
+ComputedStyle* Element::CachedStyleForPseudoElement(
+ const PseudoStyleRequest& request,
+ const ComputedStyle* parent_style) {
ComputedStyle* style = MutableComputedStyle();
if (!style || (request.pseudo_id < kFirstInternalPseudoId &&
@@ -3922,13 +4124,13 @@ ComputedStyle* Element::PseudoStyle(const PseudoStyleRequest& request,
return cached;
scoped_refptr<ComputedStyle> result =
- GetUncachedPseudoStyle(request, parent_style);
+ StyleForPseudoElement(request, parent_style);
if (result)
return style->AddCachedPseudoStyle(std::move(result));
return nullptr;
}
-scoped_refptr<ComputedStyle> Element::GetUncachedPseudoStyle(
+scoped_refptr<ComputedStyle> Element::StyleForPseudoElement(
const PseudoStyleRequest& request,
const ComputedStyle* parent_style) {
const ComputedStyle* style = GetComputedStyle();
@@ -3939,20 +4141,16 @@ scoped_refptr<ComputedStyle> Element::GetUncachedPseudoStyle(
DCHECK(!parent_style || !is_before_or_after);
if (is_before_or_after) {
- LayoutObject* parent_layout_object = GetLayoutObject();
- if (!parent_layout_object && HasDisplayContentsStyle()) {
- parent_layout_object =
- LayoutTreeBuilderTraversal::ParentLayoutObject(*this);
+ const ComputedStyle* layout_parent_style = style;
+ if (style->Display() == EDisplay::kContents) {
+ Node* layout_parent = LayoutTreeBuilderTraversal::LayoutParent(*this);
+ DCHECK(layout_parent);
+ layout_parent_style = layout_parent->GetComputedStyle();
}
- if (!parent_layout_object)
- return nullptr;
return GetDocument().EnsureStyleResolver().PseudoStyleForElement(
- this, request, style, parent_layout_object->Style());
+ this, request, style, layout_parent_style);
}
- if (!GetLayoutObject())
- return nullptr;
-
if (!parent_style)
parent_style = style;
@@ -3967,13 +4165,17 @@ scoped_refptr<ComputedStyle> Element::GetUncachedPseudoStyle(
return GetDocument().EnsureStyleResolver().PseudoStyleForElement(
this, request, parent_style, parent_style);
}
-// For display: contents elements, we still need to generate ::before and
-// ::after, but the rest of the pseudo-elements should only be used for elements
-// with an actual layout object.
+
bool Element::CanGeneratePseudoElement(PseudoId pseudo_id) const {
- if (HasDisplayContentsStyle())
- return pseudo_id == kPseudoIdBefore || pseudo_id == kPseudoIdAfter;
- return !!GetLayoutObject();
+ if (pseudo_id == kPseudoIdBackdrop && !IsInTopLayer())
+ return false;
+ if (const ComputedStyle* style = GetComputedStyle())
+ return style->CanGeneratePseudoElement(pseudo_id);
+ return false;
+}
+
+bool Element::MayTriggerVirtualKeyboard() const {
+ return HasEditableStyle(*this);
}
bool Element::matches(const AtomicString& selectors,
@@ -4047,6 +4249,24 @@ void Element::GetURLAttribute(const QualifiedName& name,
result.SetString(url.GetString());
}
+void Element::GetURLAttribute(const QualifiedName& name,
+ USVStringOrTrustedURL& result) const {
+ String url = GetURLAttribute(name);
+ result.SetUSVString(url);
+}
+
+void Element::FastGetAttribute(const QualifiedName& name,
+ USVStringOrTrustedURL& result) const {
+ String attr = FastGetAttribute(name);
+ result.SetUSVString(attr);
+}
+
+void Element::FastGetAttribute(const QualifiedName& name,
+ StringOrTrustedHTML& result) const {
+ String html = FastGetAttribute(name);
+ result.SetString(html);
+}
+
KURL Element::GetNonEmptyURLAttribute(const QualifiedName& name) const {
#if DCHECK_IS_ON()
if (GetElementData()) {
@@ -4483,6 +4703,8 @@ Node::InsertionNotificationRequest Node::InsertedInto(
if (ChildNeedsDistributionRecalc() &&
!insertion_point->ChildNeedsDistributionRecalc())
insertion_point->MarkAncestorsWithChildNeedsDistributionRecalc();
+ if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
+ cache->ChildrenChanged(insertion_point);
return kInsertionDone;
}
@@ -4495,8 +4717,10 @@ void Node::RemovedFrom(ContainerNode* insertion_point) {
}
if (IsInShadowTree() && !ContainingTreeScope().RootNode().IsShadowRoot())
ClearFlag(kIsInShadowTreeFlag);
- if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
+ if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache()) {
cache->Remove(this);
+ cache->ChildrenChanged(insertion_point);
+ }
}
void Element::WillRecalcStyle(StyleRecalcChange) {
@@ -4672,7 +4896,8 @@ void Element::StyleAttributeChanged(
ContainingShadowRoot()->IsUserAgent()) ||
GetDocument().GetContentSecurityPolicy()->AllowInlineStyle(
this, GetDocument().Url(), String(), start_line_number,
- new_style_string, ContentSecurityPolicy::InlineType::kBlock)) {
+ new_style_string,
+ ContentSecurityPolicy::InlineType::kAttribute)) {
SetInlineStyleFromString(new_style_string);
}
@@ -4889,18 +5114,11 @@ void Element::LogUpdateAttributeIfIsolatedWorldAndInDocument(
void Element::Trace(blink::Visitor* visitor) {
if (HasRareData())
- visitor->Trace(GetElementRareData());
+ visitor->TraceWithWrappers(GetElementRareData());
visitor->Trace(element_data_);
ContainerNode::Trace(visitor);
}
-void Element::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- if (HasRareData()) {
- visitor->TraceWrappersWithManualWriteBarrier(GetElementRareData());
- }
- ContainerNode::TraceWrappers(visitor);
-}
-
bool Element::HasPartName() const {
if (!RuntimeEnabledFeatures::CSSPartPseudoElementEnabled())
return false;
diff --git a/chromium/third_party/blink/renderer/core/dom/element.h b/chromium/third_party/blink/renderer/core/dom/element.h
index 753c4265734..f7d403771c1 100644
--- a/chromium/third_party/blink/renderer/core/dom/element.h
+++ b/chromium/third_party/blink/renderer/core/dom/element.h
@@ -40,6 +40,7 @@
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/scroll/scroll_customization.h"
#include "third_party/blink/renderer/platform/scroll/scroll_types.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
namespace blink {
@@ -80,6 +81,7 @@ class StringOrTrustedHTML;
class StringOrTrustedScriptURL;
class StylePropertyMap;
class StylePropertyMapReadOnly;
+class USVStringOrTrustedURL;
class V0CustomElementDefinition;
class V8ScrollStateCallback;
@@ -205,11 +207,21 @@ class CORE_EXPORT Element : public ContainerNode {
ExceptionState&);
void setAttribute(const AtomicString& name, const AtomicString& value);
- // Trusted Type variant of the above.
+ // Trusted Type ScriptURL variant of the above.
void setAttribute(const QualifiedName&,
const StringOrTrustedScriptURL&,
ExceptionState&);
+ // Trusted Type HTML variant
+ void setAttribute(const QualifiedName&,
+ const StringOrTrustedHTML&,
+ ExceptionState&);
+
+ // Trusted Type URL variant
+ void setAttribute(const QualifiedName&,
+ const USVStringOrTrustedURL&,
+ ExceptionState&);
+
static bool ParseAttributeName(QualifiedName&,
const AtomicString& namespace_uri,
const AtomicString& qualified_name,
@@ -219,6 +231,9 @@ class CORE_EXPORT Element : public ContainerNode {
const AtomicString& value,
ExceptionState&);
+ bool toggleAttribute(const AtomicString&, ExceptionState&);
+ bool toggleAttribute(const AtomicString&, bool force, ExceptionState&);
+
const AtomicString& GetIdAttribute() const;
void SetIdAttribute(const AtomicString&);
@@ -255,6 +270,7 @@ class CORE_EXPORT Element : public ContainerNode {
void scrollIntoView(ScrollIntoViewOptionsOrBoolean);
void scrollIntoView(bool align_to_top = true);
void scrollIntoViewWithOptions(const ScrollIntoViewOptions&);
+ void ScrollIntoViewNoVisualUpdate(const ScrollIntoViewOptions&);
void scrollIntoViewIfNeeded(bool center_if_needed = true);
int OffsetLeft();
@@ -464,7 +480,6 @@ class CORE_EXPORT Element : public ContainerNode {
virtual LayoutObject* CreateLayoutObject(const ComputedStyle&);
virtual bool LayoutObjectIsNeeded(const ComputedStyle&) const;
void RecalcStyle(StyleRecalcChange);
- void RecalcStyleForReattach();
bool NeedsRebuildLayoutTree(
const WhitespaceAttacher& whitespace_attacher) const {
// TODO(futhark@chromium.org): !CanParticipateInFlatTree() can be replaced
@@ -487,13 +502,8 @@ class CORE_EXPORT Element : public ContainerNode {
// creation of multiple shadow roots is prohibited in any combination and
// throws an exception. Multiple shadow roots are allowed only when
// createShadowRoot() is used without any parameters from JavaScript.
- //
- // TODO(esprehn): These take a ScriptState only for calling
- // HostsUsingFeatures::countMainWorldOnly, which should be handled in the
- // bindings instead so adding a ShadowRoot from C++ doesn't need one.
- ShadowRoot* createShadowRoot(const ScriptState*, ExceptionState&);
- ShadowRoot* attachShadow(const ScriptState*,
- const ShadowRootInit&,
+ ShadowRoot* createShadowRoot(ExceptionState&);
+ ShadowRoot* attachShadow(const ShadowRootInit&,
ExceptionState&);
ShadowRoot& CreateV0ShadowRootForTesting() {
@@ -579,6 +589,9 @@ class CORE_EXPORT Element : public ContainerNode {
KURL GetURLAttribute(const QualifiedName&) const;
void GetURLAttribute(const QualifiedName&, StringOrTrustedScriptURL&) const;
+ void GetURLAttribute(const QualifiedName&, USVStringOrTrustedURL&) const;
+ void FastGetAttribute(const QualifiedName&, USVStringOrTrustedURL&) const;
+ void FastGetAttribute(const QualifiedName&, StringOrTrustedHTML&) const;
KURL GetNonEmptyURLAttribute(const QualifiedName&) const;
@@ -709,9 +722,10 @@ class CORE_EXPORT Element : public ContainerNode {
PseudoElement* GetPseudoElement(PseudoId) const;
LayoutObject* PseudoElementLayoutObject(PseudoId) const;
- ComputedStyle* PseudoStyle(const PseudoStyleRequest&,
- const ComputedStyle* parent_style = nullptr);
- scoped_refptr<ComputedStyle> GetUncachedPseudoStyle(
+ ComputedStyle* CachedStyleForPseudoElement(
+ const PseudoStyleRequest&,
+ const ComputedStyle* parent_style = nullptr);
+ scoped_refptr<ComputedStyle> StyleForPseudoElement(
const PseudoStyleRequest&,
const ComputedStyle* parent_style = nullptr);
bool CanGeneratePseudoElement(PseudoId) const;
@@ -722,6 +736,8 @@ class CORE_EXPORT Element : public ContainerNode {
virtual bool MatchesReadWritePseudoClass() const { return false; }
virtual bool MatchesValidityPseudoClasses() const { return false; }
+ virtual bool MayTriggerVirtualKeyboard() const;
+
// https://dom.spec.whatwg.org/#dom-element-matches
bool matches(const AtomicString& selectors, ExceptionState&);
bool matches(const AtomicString& selectors);
@@ -843,7 +859,6 @@ class CORE_EXPORT Element : public ContainerNode {
const AttributeModificationParams&);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
SpellcheckAttributeState GetSpellcheckAttributeState() const;
@@ -956,8 +971,10 @@ class CORE_EXPORT Element : public ContainerNode {
scoped_refptr<ComputedStyle> PropagateInheritedProperties(StyleRecalcChange);
StyleRecalcChange RecalcOwnStyle(StyleRecalcChange);
- void RecalcShadowIncludingDescendantStylesForReattach();
- void RecalcShadowRootStylesForReattach();
+
+ // Returns true if we should traverse shadow including children and pseudo
+ // elements for RecalcStyle.
+ bool ShouldCallRecalcStyleForChildren(StyleRecalcChange);
void RebuildPseudoElementLayoutTree(PseudoId, WhitespaceAttacher&);
void RebuildShadowRootLayoutTree(WhitespaceAttacher&);
@@ -968,7 +985,8 @@ class CORE_EXPORT Element : public ContainerNode {
bool UpdateFirstLetter(Element*);
inline PseudoElement* CreatePseudoElementIfNeeded(PseudoId);
- void CreateAndAttachPseudoElementIfNeeded(PseudoId, AttachContext&);
+ void AttachPseudoElement(PseudoId, AttachContext&);
+ void DetachPseudoElement(PseudoId, const AttachContext&);
ShadowRoot& CreateAndAttachShadowRoot(ShadowRootType);
diff --git a/chromium/third_party/blink/renderer/core/dom/element.idl b/chromium/third_party/blink/renderer/core/dom/element.idl
index 0fbc8aa307f..534f5d1b009 100644
--- a/chromium/third_party/blink/renderer/core/dom/element.idl
+++ b/chromium/third_party/blink/renderer/core/dom/element.idl
@@ -54,6 +54,7 @@ interface Element : Node {
[CEReactions, CustomElementCallbacks] void removeAttributeNS(DOMString? namespaceURI, DOMString localName);
[Affects=Nothing] boolean hasAttribute(DOMString name);
[Affects=Nothing] boolean hasAttributeNS(DOMString? namespaceURI, DOMString localName);
+ [RaisesException] boolean toggleAttribute(DOMString qualifiedName, optional boolean force);
Attr? getAttributeNode(DOMString name);
Attr? getAttributeNodeNS(DOMString? namespaceURI, DOMString localName);
@@ -65,7 +66,7 @@ interface Element : Node {
[RaisesException] boolean matches(DOMString selectors);
[RaisesException, ImplementedAs=matches, MeasureAs=ElementPrefixedMatchesSelector] boolean webkitMatchesSelector(DOMString selectors); // historical alias of .matches
- [RaisesException, CallWith=ScriptState, MeasureAs=ElementAttachShadow] ShadowRoot attachShadow(ShadowRootInit shadowRootInitDict);
+ [RaisesException, MeasureAs=ElementAttachShadow] ShadowRoot attachShadow(ShadowRootInit shadowRootInitDict);
[Affects=Nothing, PerWorldBindings, ImplementedAs=OpenShadowRoot] readonly attribute ShadowRoot? shadowRoot;
[Affects=Nothing] HTMLCollection getElementsByTagName(DOMString localName);
@@ -120,11 +121,11 @@ interface Element : Node {
// Typed OM
// https://drafts.css-houdini.org/css-typed-om/#inline-stylepropertymap-objects
- [RuntimeEnabled=CSSTypedOM, SameObject, MeasureAs=CSSTypedOMStylePropertyMap] readonly attribute StylePropertyMap attributeStyleMap;
+ [SameObject, MeasureAs=CSSTypedOMStylePropertyMap] readonly attribute StylePropertyMap attributeStyleMap;
// Non-standard API
[MeasureAs=ElementScrollIntoViewIfNeeded] void scrollIntoViewIfNeeded(optional boolean centerIfNeeded);
- [RuntimeEnabled=ShadowDOMV0, RaisesException, CallWith=ScriptState, MeasureAs=ElementCreateShadowRoot] ShadowRoot createShadowRoot();
+ [RuntimeEnabled=ShadowDOMV0, RaisesException, MeasureAs=ElementCreateShadowRoot] ShadowRoot createShadowRoot();
[RuntimeEnabled=ShadowDOMV0] NodeList getDestinationInsertionPoints();
// Experimental accessibility API
diff --git a/chromium/third_party/blink/renderer/core/dom/element_rare_data.cc b/chromium/third_party/blink/renderer/core/dom/element_rare_data.cc
index 9bd1149b4fb..eb67c03c2db 100644
--- a/chromium/third_party/blink/renderer/core/dom/element_rare_data.cc
+++ b/chromium/third_party/blink/renderer/core/dom/element_rare_data.cc
@@ -30,8 +30,8 @@
#include "third_party/blink/renderer/core/dom/element_rare_data.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/css/cssom/inline_style_property_map.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observation.h"
#include "third_party/blink/renderer/core/resize_observer/resize_observer.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
@@ -109,27 +109,6 @@ void ElementRareData::TraceAfterDispatch(blink::Visitor* visitor) {
NodeRareData::TraceAfterDispatch(visitor);
}
-void ElementRareData::TraceWrappersAfterDispatch(
- ScriptWrappableVisitor* visitor) const {
- if (attr_node_list_.Get()) {
- for (auto& attr : *attr_node_list_) {
- visitor->TraceWrappers(attr);
- }
- }
- visitor->TraceWrappers(dataset_);
- visitor->TraceWrappers(shadow_root_);
- visitor->TraceWrappers(class_list_);
- visitor->TraceWrappers(attribute_map_);
- visitor->TraceWrappers(accessible_node_);
- visitor->TraceWrappers(intersection_observer_data_);
- if (resize_observer_data_) {
- for (auto& resize_observer : resize_observer_data_->Keys()) {
- visitor->TraceWrappers(resize_observer);
- }
- }
- NodeRareData::TraceWrappersAfterDispatch(visitor);
-}
-
static_assert(sizeof(ElementRareData) == sizeof(SameSizeAsElementRareData),
"ElementRareData should stay small");
diff --git a/chromium/third_party/blink/renderer/core/dom/element_rare_data.h b/chromium/third_party/blink/renderer/core/dom/element_rare_data.h
index 6b4896e7d5f..b73961b318c 100644
--- a/chromium/third_party/blink/renderer/core/dom/element_rare_data.h
+++ b/chromium/third_party/blink/renderer/core/dom/element_rare_data.h
@@ -24,9 +24,9 @@
#include <memory>
#include "third_party/blink/renderer/core/animation/element_animations.h"
+#include "third_party/blink/renderer/core/aom/accessible_node.h"
#include "third_party/blink/renderer/core/css/cssom/inline_style_property_map.h"
#include "third_party/blink/renderer/core/css/inline_css_style_declaration.h"
-#include "third_party/blink/renderer/core/dom/accessible_node.h"
#include "third_party/blink/renderer/core/dom/attr.h"
#include "third_party/blink/renderer/core/dom/dataset_dom_string_map.h"
#include "third_party/blink/renderer/core/dom/dom_token_list.h"
@@ -191,7 +191,6 @@ class ElementRareData : public NodeRareData {
void SetNonce(const AtomicString& nonce) { nonce_ = nonce; }
void TraceAfterDispatch(blink::Visitor*);
- void TraceWrappersAfterDispatch(ScriptWrappableVisitor*) const;
private:
ScrollOffset saved_layer_scroll_offset_;
@@ -203,14 +202,14 @@ class ElementRareData : public NodeRareData {
std::unique_ptr<SpaceSplitString> part_names_;
std::unique_ptr<NamesMap> part_names_map_;
TraceWrapperMember<NamedNodeMap> attribute_map_;
- Member<AttrNodeList> attr_node_list_;
+ TraceWrapperMember<AttrNodeList> attr_node_list_;
Member<InlineCSSStyleDeclaration> cssom_wrapper_;
Member<InlineStylePropertyMap> cssom_map_wrapper_;
Member<ElementAnimations> element_animations_;
TraceWrapperMember<ElementIntersectionObserverData>
intersection_observer_data_;
- Member<ResizeObserverDataMap> resize_observer_data_;
+ TraceWrapperMember<ResizeObserverDataMap> resize_observer_data_;
scoped_refptr<ComputedStyle> computed_style_;
// TODO(davaajav):remove this field when v0 custom elements are deprecated
@@ -224,7 +223,6 @@ class ElementRareData : public NodeRareData {
explicit ElementRareData(NodeRenderingData*);
};
-DEFINE_TRAIT_FOR_TRACE_WRAPPERS(ElementRareData);
inline LayoutSize DefaultMinimumSizeForResizing() {
return LayoutSize(LayoutUnit::Max(), LayoutUnit::Max());
@@ -243,8 +241,11 @@ inline void ElementRareData::ClearPseudoElements() {
inline void ElementRareData::SetPseudoElement(PseudoId pseudo_id,
PseudoElement* element) {
- if (!pseudo_element_data_)
+ if (!pseudo_element_data_) {
+ if (!element)
+ return;
pseudo_element_data_ = PseudoElementData::Create();
+ }
pseudo_element_data_->SetPseudoElement(pseudo_id, element);
}
diff --git a/chromium/third_party/blink/renderer/core/dom/element_visibility_observer.cc b/chromium/third_party/blink/renderer/core/dom/element_visibility_observer.cc
index caa4153e1f2..823ba2fa3ea 100644
--- a/chromium/third_party/blink/renderer/core/dom/element_visibility_observer.cc
+++ b/chromium/third_party/blink/renderer/core/dom/element_visibility_observer.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/dom/element_visibility_observer.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_frame.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h"
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 a7291f30445..14706ed5ef7 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
@@ -75,12 +75,8 @@ const AtomicString& CustomEvent::InterfaceName() const {
}
void CustomEvent::Trace(blink::Visitor* visitor) {
+ visitor->Trace(detail_);
Event::Trace(visitor);
}
-void CustomEvent::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(detail_);
- Event::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/events/custom_event.h b/chromium/third_party/blink/renderer/core/dom/events/custom_event.h
index dcd6bf55de0..72c81b2cbe2 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/custom_event.h
+++ b/chromium/third_party/blink/renderer/core/dom/events/custom_event.h
@@ -60,8 +60,6 @@ class CORE_EXPORT CustomEvent final : public Event {
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
private:
CustomEvent();
CustomEvent(ScriptState*,
diff --git a/chromium/third_party/blink/renderer/core/dom/events/dom_window_event_queue.cc b/chromium/third_party/blink/renderer/core/dom/events/dom_window_event_queue.cc
deleted file mode 100644
index a0374e483a3..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/events/dom_window_event_queue.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "third_party/blink/renderer/core/dom/events/dom_window_event_queue.h"
-
-#include "base/macros.h"
-#include "third_party/blink/public/platform/task_type.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/pausable_timer.h"
-#include "third_party/blink/renderer/core/probe/core_probes.h"
-
-namespace blink {
-
-class DOMWindowEventQueueTimer final
- : public GarbageCollectedFinalized<DOMWindowEventQueueTimer>,
- public PausableTimer {
- USING_GARBAGE_COLLECTED_MIXIN(DOMWindowEventQueueTimer);
-
- public:
- DOMWindowEventQueueTimer(DOMWindowEventQueue* event_queue,
- ExecutionContext* context)
- // This queue is unthrottled because throttling IndexedDB events may break
- // scenarios where several tabs, some of which are backgrounded, access
- // the same database concurrently.
- : PausableTimer(context, TaskType::kUnthrottled),
- event_queue_(event_queue) {}
-
- // Eager finalization is needed to promptly stop this timer object.
- // (see DOMTimer comment for more.)
- EAGERLY_FINALIZE();
- void Trace(blink::Visitor* visitor) override {
- visitor->Trace(event_queue_);
- PausableTimer::Trace(visitor);
- }
-
- private:
- void Fired() override { event_queue_->PendingEventTimerFired(); }
-
- Member<DOMWindowEventQueue> event_queue_;
- DISALLOW_COPY_AND_ASSIGN(DOMWindowEventQueueTimer);
-};
-
-DOMWindowEventQueue* DOMWindowEventQueue::Create(ExecutionContext* context) {
- return new DOMWindowEventQueue(context);
-}
-
-DOMWindowEventQueue::DOMWindowEventQueue(ExecutionContext* context)
- : pending_event_timer_(new DOMWindowEventQueueTimer(this, context)),
- is_closed_(false) {
- pending_event_timer_->PauseIfNeeded();
-}
-
-DOMWindowEventQueue::~DOMWindowEventQueue() = default;
-
-void DOMWindowEventQueue::Trace(blink::Visitor* visitor) {
- visitor->Trace(pending_event_timer_);
- visitor->Trace(queued_events_);
- EventQueue::Trace(visitor);
-}
-
-bool DOMWindowEventQueue::EnqueueEvent(const base::Location& from_here,
- Event* event) {
- if (is_closed_)
- return false;
-
- DCHECK(event->target());
- probe::AsyncTaskScheduled(event->target()->GetExecutionContext(),
- event->type(), event);
-
- bool was_added = queued_events_.insert(event).is_new_entry;
- DCHECK(was_added); // It should not have already been in the list.
-
- if (!pending_event_timer_->IsActive())
- pending_event_timer_->StartOneShot(TimeDelta(), from_here);
-
- return true;
-}
-
-bool DOMWindowEventQueue::CancelEvent(Event* event) {
- auto it = queued_events_.find(event);
- bool found = it != queued_events_.end();
- if (found) {
- probe::AsyncTaskCanceled(event->target()->GetExecutionContext(), event);
- queued_events_.erase(it);
- }
- if (queued_events_.IsEmpty())
- pending_event_timer_->Stop();
- return found;
-}
-
-void DOMWindowEventQueue::Close() {
- is_closed_ = true;
- pending_event_timer_->Stop();
- for (const auto& queued_event : queued_events_) {
- if (queued_event) {
- probe::AsyncTaskCanceled(queued_event->target()->GetExecutionContext(),
- queued_event);
- }
- }
- queued_events_.clear();
-}
-
-void DOMWindowEventQueue::PendingEventTimerFired() {
- DCHECK(!pending_event_timer_->IsActive());
- DCHECK(!queued_events_.IsEmpty());
-
- // Insert a marker for where we should stop.
- DCHECK(!queued_events_.Contains(nullptr));
- bool was_added = queued_events_.insert(nullptr).is_new_entry;
- DCHECK(was_added); // It should not have already been in the list.
-
- while (!queued_events_.IsEmpty()) {
- auto it = queued_events_.begin();
- Event* event = *it;
- queued_events_.erase(it);
- if (!event)
- break;
- DispatchEvent(event);
- }
-}
-
-void DOMWindowEventQueue::DispatchEvent(Event* event) {
- EventTarget* event_target = event->target();
- probe::AsyncTask async_task(event_target->GetExecutionContext(), event);
- if (LocalDOMWindow* window = event_target->ToLocalDOMWindow())
- window->DispatchEvent(event, nullptr);
- else
- event_target->DispatchEvent(event);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/events/dom_window_event_queue.h b/chromium/third_party/blink/renderer/core/dom/events/dom_window_event_queue.h
deleted file mode 100644
index 27ecbd5b120..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/events/dom_window_event_queue.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_DOM_WINDOW_EVENT_QUEUE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_DOM_WINDOW_EVENT_QUEUE_H_
-
-#include "third_party/blink/renderer/core/dom/events/event_queue.h"
-#include "third_party/blink/renderer/platform/wtf/linked_hash_set.h"
-
-namespace blink {
-
-class Event;
-class DOMWindowEventQueueTimer;
-class ExecutionContext;
-
-class DOMWindowEventQueue final : public EventQueue {
- public:
- static DOMWindowEventQueue* Create(ExecutionContext*);
- ~DOMWindowEventQueue() override;
-
- // EventQueue
- void Trace(blink::Visitor*) override;
- bool EnqueueEvent(const base::Location&, Event*) override;
- bool CancelEvent(Event*) override;
- void Close() override;
-
- private:
- explicit DOMWindowEventQueue(ExecutionContext*);
-
- void PendingEventTimerFired();
- void DispatchEvent(Event*);
-
- Member<DOMWindowEventQueueTimer> pending_event_timer_;
- HeapLinkedHashSet<Member<Event>> queued_events_;
- bool is_closed_;
-
- friend class DOMWindowEventQueueTimer;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_DOM_WINDOW_EVENT_QUEUE_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event.cc b/chromium/third_party/blink/renderer/core/dom/events/event.cc
index 09546e4d351..bd42170486b 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/event.cc
@@ -200,10 +200,6 @@ bool Event::IsWheelEvent() const {
return false;
}
-bool Event::IsRelatedEvent() const {
- return false;
-}
-
bool Event::IsPointerEvent() const {
return false;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event.h b/chromium/third_party/blink/renderer/core/dom/events/event.h
index 5b08c65c7d7..6c95dcf8773 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event.h
+++ b/chromium/third_party/blink/renderer/core/dom/events/event.h
@@ -41,6 +41,7 @@ namespace blink {
class DOMWrapperWorld;
class EventTarget;
class ScriptState;
+class ScriptValue;
class CORE_EXPORT Event : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
@@ -176,7 +177,6 @@ class CORE_EXPORT Event : public ScriptWrappable {
virtual bool IsTouchEvent() const;
virtual bool IsGestureEvent() const;
virtual bool IsWheelEvent() const;
- virtual bool IsRelatedEvent() const;
virtual bool IsPointerEvent() const;
virtual bool IsInputEvent() const;
virtual bool IsCompositionEvent() const;
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.cc b/chromium/third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.cc
new file mode 100644
index 00000000000..73ab12becac
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.cc
@@ -0,0 +1,13 @@
+// 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/dom/events/event_dispatch_forbidden_scope.h"
+
+namespace blink {
+
+#if DCHECK_IS_ON()
+unsigned EventDispatchForbiddenScope::count_ = 0;
+#endif // DECHECK_IS_ON()
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h b/chromium/third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h
new file mode 100644
index 00000000000..4a5462c6b3a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h
@@ -0,0 +1,75 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_DISPATCH_FORBIDDEN_SCOPE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_DISPATCH_FORBIDDEN_SCOPE_H_
+
+#include "base/auto_reset.h"
+#include "base/macros.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
+
+namespace blink {
+
+#if DCHECK_IS_ON()
+
+class EventDispatchForbiddenScope {
+ STACK_ALLOCATED();
+ DISALLOW_COPY_AND_ASSIGN(EventDispatchForbiddenScope);
+
+ public:
+ EventDispatchForbiddenScope() {
+ DCHECK(IsMainThread());
+ ++count_;
+ }
+
+ ~EventDispatchForbiddenScope() {
+ DCHECK(IsMainThread());
+ DCHECK(count_);
+ --count_;
+ }
+
+ static bool IsEventDispatchForbidden() {
+ if (!IsMainThread())
+ return false;
+ return count_;
+ }
+
+ class AllowUserAgentEvents {
+ STACK_ALLOCATED();
+
+ public:
+ AllowUserAgentEvents() : change_(&count_, 0) { DCHECK(IsMainThread()); }
+
+ ~AllowUserAgentEvents() { DCHECK(!count_); }
+
+ base::AutoReset<unsigned> change_;
+ };
+
+ private:
+ CORE_EXPORT static unsigned count_;
+};
+
+#else
+
+class EventDispatchForbiddenScope {
+ STACK_ALLOCATED();
+ DISALLOW_COPY_AND_ASSIGN(EventDispatchForbiddenScope);
+
+ public:
+ EventDispatchForbiddenScope() {}
+
+ class AllowUserAgentEvents {
+ public:
+ AllowUserAgentEvents() {}
+ };
+};
+
+#endif // DCHECK_IS_ON()
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_DISPATCH_FORBIDDEN_SCOPE_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc b/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
index 7672483e712..533a4ecef9b 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
@@ -28,10 +28,11 @@
#include "third_party/blink/renderer/core/dom/events/event_dispatcher.h"
#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/container_node.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_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
#include "third_party/blink/renderer/core/dom/events/window_event_context.h"
#include "third_party/blink/renderer/core/events/mouse_event.h"
@@ -44,7 +45,6 @@
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
#include "third_party/blink/renderer/core/timing/event_timing.h"
-#include "third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
namespace blink {
@@ -139,7 +139,7 @@ DispatchEventResult EventDispatcher::Dispatch() {
return DispatchEventResult::kNotCanceled;
}
std::unique_ptr<EventTiming> eventTiming;
- if (OriginTrials::eventTimingEnabled(&node_->GetDocument())) {
+ if (OriginTrials::EventTimingEnabled(&node_->GetDocument())) {
LocalFrame* frame = node_->GetDocument().GetFrame();
if (frame && frame->DomWindow()) {
UseCounter::Count(node_->GetDocument(),
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_listener.h b/chromium/third_party/blink/renderer/core/dom/events/event_listener.h
index 2dc6d11c0b3..018acd55347 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_listener.h
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_listener.h
@@ -22,7 +22,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_LISTENER_H_
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -33,7 +33,7 @@ class ExecutionContext;
class CORE_EXPORT EventListener
: public GarbageCollectedFinalized<EventListener>,
- public TraceWrapperBase {
+ public NameClient {
public:
enum ListenerType {
kJSEventListenerType,
@@ -55,7 +55,6 @@ class CORE_EXPORT EventListener
ListenerType GetType() const { return type_; }
virtual void Trace(blink::Visitor* visitor) {}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {}
const char* NameInHeapSnapshot() const override { return "EventListener"; }
protected:
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.cc b/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.cc
index 86d8b9cfb70..f7c8c459c89 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.cc
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.cc
@@ -209,13 +209,4 @@ void EventListenerMap::Trace(blink::Visitor* visitor) {
visitor->Trace(entries_);
}
-void EventListenerMap::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- // Trace wrappers in entries_.
- for (auto& entry : entries_) {
- for (auto& listener : *entry.second) {
- visitor->TraceWrappers(listener);
- }
- }
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.h b/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.h
index 3b743236364..fc603fddcb3 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.h
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_listener_map.h
@@ -73,7 +73,6 @@ class CORE_EXPORT EventListenerMap final {
void CopyEventListenersNotCreatedFromMarkupToTarget(EventTarget*);
void Trace(blink::Visitor*);
- void TraceWrappers(ScriptWrappableVisitor*) const;
private:
friend class EventListenerIterator;
@@ -84,7 +83,9 @@ class CORE_EXPORT EventListenerMap final {
// - HeapVector is much more space efficient than HeapHashMap.
// - An EventTarget rarely has event listeners for many event types, and
// HeapVector is faster in such cases.
- HeapVector<std::pair<AtomicString, Member<EventListenerVector>>, 2> entries_;
+ HeapVector<std::pair<AtomicString, TraceWrapperMember<EventListenerVector>>,
+ 2>
+ entries_;
#if DCHECK_IS_ON()
int active_iterator_count_ = 0;
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_queue.cc b/chromium/third_party/blink/renderer/core/dom/events/event_queue.cc
new file mode 100644
index 00000000000..53166a98285
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_queue.cc
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "third_party/blink/renderer/core/dom/events/event_queue.h"
+
+#include "base/macros.h"
+#include "third_party/blink/public/platform/task_type.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/probe/core_probes.h"
+
+namespace blink {
+
+EventQueue* EventQueue::Create(ExecutionContext* context, TaskType task_type) {
+ return new EventQueue(context, task_type);
+}
+
+EventQueue::EventQueue(ExecutionContext* context, TaskType task_type)
+ : ContextLifecycleObserver(context),
+ task_type_(task_type),
+ is_closed_(false) {
+ if (!GetExecutionContext() || GetExecutionContext()->IsContextDestroyed())
+ Close(nullptr);
+}
+
+EventQueue::~EventQueue() = default;
+
+void EventQueue::Trace(blink::Visitor* visitor) {
+ visitor->Trace(queued_events_);
+ ContextLifecycleObserver::Trace(visitor);
+}
+
+bool EventQueue::EnqueueEvent(const base::Location& from_here, Event* event) {
+ if (is_closed_)
+ return false;
+
+ DCHECK(event->target());
+ DCHECK(GetExecutionContext());
+
+ probe::AsyncTaskScheduled(GetExecutionContext(), event->type(), event);
+
+ bool was_added = queued_events_.insert(event).is_new_entry;
+ DCHECK(was_added); // It should not have already been in the list.
+
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+ GetExecutionContext()->GetTaskRunner(task_type_);
+
+ // Pass the event as a weak persistent so that GC can collect an event-related
+ // object like IDBTransaction as soon as possible.
+ task_runner->PostTask(
+ FROM_HERE, WTF::Bind(&EventQueue::DispatchEvent, WrapPersistent(this),
+ WrapWeakPersistent(event)));
+
+ return true;
+}
+
+void EventQueue::CancelAllEvents() {
+ if (!GetExecutionContext()) {
+ DCHECK(!queued_events_.size());
+ return;
+ }
+ DoCancelAllEvents(GetExecutionContext());
+}
+
+bool EventQueue::RemoveEvent(Event* event) {
+ auto found = queued_events_.find(event);
+ if (found == queued_events_.end())
+ return false;
+ queued_events_.erase(found);
+ return true;
+}
+
+void EventQueue::DispatchEvent(Event* event) {
+ if (!event || !RemoveEvent(event))
+ return;
+
+ DCHECK(GetExecutionContext());
+
+ probe::AsyncTask async_task(GetExecutionContext(), event);
+ EventTarget* target = event->target();
+ if (LocalDOMWindow* window = target->ToLocalDOMWindow())
+ window->DispatchEvent(event, nullptr);
+ else
+ target->DispatchEvent(event);
+}
+
+void EventQueue::ContextDestroyed(ExecutionContext* context) {
+ Close(context);
+}
+
+void EventQueue::Close(ExecutionContext* context) {
+ is_closed_ = true;
+ DoCancelAllEvents(context);
+}
+
+void EventQueue::DoCancelAllEvents(ExecutionContext* context) {
+ for (const auto& queued_event : queued_events_)
+ probe::AsyncTaskCanceled(context, queued_event);
+ queued_events_.clear();
+}
+
+bool EventQueue::HasPendingEvents() const {
+ return queued_events_.size() > 0;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_queue.h b/chromium/third_party/blink/renderer/core/dom/events/event_queue.h
index a095e485717..cc446451d61 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_queue.h
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_queue.h
@@ -27,25 +27,42 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_QUEUE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_EVENT_QUEUE_H_
-#include "base/location.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/hash_map.h"
-#include "third_party/blink/renderer/platform/wtf/hash_set.h"
+#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/platform/wtf/linked_hash_set.h"
namespace blink {
class Event;
+class ExecutionContext;
+
+class CORE_EXPORT EventQueue final
+ : public GarbageCollectedFinalized<EventQueue>,
+ public ContextLifecycleObserver {
+ USING_GARBAGE_COLLECTED_MIXIN(EventQueue);
-class CORE_EXPORT EventQueue : public GarbageCollectedFinalized<EventQueue> {
public:
- virtual ~EventQueue() = default;
- virtual void Trace(blink::Visitor* visitor) {}
- virtual bool EnqueueEvent(const base::Location&, Event*) = 0;
- virtual bool CancelEvent(Event*) = 0;
- // The accumulated and all the future events will be discarded, no events will
- // be dispatched anymore.
- virtual void Close() = 0;
+ static EventQueue* Create(ExecutionContext*, TaskType);
+ ~EventQueue();
+
+ void Trace(blink::Visitor*) override;
+ bool EnqueueEvent(const base::Location&, Event*);
+ void CancelAllEvents();
+ bool HasPendingEvents() const;
+
+ private:
+ EventQueue(ExecutionContext*, TaskType);
+
+ bool RemoveEvent(Event*);
+ void DispatchEvent(Event*);
+
+ void ContextDestroyed(ExecutionContext*) override;
+ void Close(ExecutionContext*);
+ void DoCancelAllEvents(ExecutionContext*);
+
+ const TaskType task_type_;
+ HeapLinkedHashSet<Member<Event>> queued_events_;
+ bool is_closed_;
};
} // namespace blink
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 6db9a46a8f1..e934b6afe4e 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
@@ -33,15 +33,15 @@
#include <memory>
+#include "base/format_macros.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/renderer/bindings/core/v8/add_event_listener_options_or_boolean.h"
#include "third_party/blink/renderer/bindings/core/v8/event_listener_options_or_boolean.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_event_listener.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/dom/events/event_target_impl.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/editing/editor.h"
#include "third_party/blink/renderer/core/events/event_util.h"
#include "third_party/blink/renderer/core/events/pointer_event.h"
@@ -52,8 +52,8 @@
#include "third_party/blink/renderer/core/frame/use_counter.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/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_dom_activity_logger.h"
-#include "third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
@@ -108,12 +108,12 @@ bool IsInstrumentedForAsyncStack(const AtomicString& event_type) {
event_type == EventTypeNames::error;
}
-double BlockedEventsWarningThreshold(ExecutionContext* context,
- const Event* event) {
+base::TimeDelta BlockedEventsWarningThreshold(ExecutionContext* context,
+ const Event* event) {
if (!event->cancelable())
- return 0.0;
+ return base::TimeDelta();
if (!IsScrollBlockingEvent(event->type()))
- return 0.0;
+ return base::TimeDelta();
return PerformanceMonitor::Threshold(context,
PerformanceMonitor::kBlockedEvent);
}
@@ -121,20 +121,20 @@ double BlockedEventsWarningThreshold(ExecutionContext* context,
void ReportBlockedEvent(ExecutionContext* context,
const Event* event,
RegisteredEventListener* registered_listener,
- double delayed_seconds) {
+ base::TimeDelta delayed) {
if (registered_listener->Callback()->GetType() !=
EventListener::kJSEventListenerType)
return;
String message_text = String::Format(
- "Handling of '%s' input event was delayed for %ld ms due to main thread "
- "being busy. "
+ "Handling of '%s' input event was delayed for %" PRId64
+ " ms due to main thread being busy. "
"Consider marking event handler as 'passive' to make the page more "
"responsive.",
- event->type().GetString().Utf8().data(), lround(delayed_seconds * 1000));
+ event->type().GetString().Utf8().data(), delayed.InMilliseconds());
PerformanceMonitor::ReportGenericViolation(
- context, PerformanceMonitor::kBlockedEvent, message_text, delayed_seconds,
+ context, PerformanceMonitor::kBlockedEvent, message_text, delayed,
GetFunctionLocation(context, registered_listener->Callback()));
registered_listener->SetBlockedEventWarningEmitted();
}
@@ -161,10 +161,6 @@ void EventTargetData::Trace(blink::Visitor* visitor) {
visitor->Trace(event_listener_map);
}
-void EventTargetData::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(event_listener_map);
-}
-
EventTarget::EventTarget() = default;
EventTarget::~EventTarget() = default;
@@ -316,7 +312,7 @@ void EventTarget::SetDefaultAddEventListenerOptions(
PerformanceMonitor::ReportGenericViolation(
GetExecutionContext(), PerformanceMonitor::kDiscouragedAPIUse,
- message_text, 0, nullptr);
+ message_text, base::TimeDelta(), nullptr);
}
}
@@ -402,8 +398,8 @@ void EventTarget::AddedEventListener(
"Consider using MutationObserver to make the page more responsive.",
event_type.GetString().Utf8().data());
PerformanceMonitor::ReportGenericViolation(
- context, PerformanceMonitor::kDiscouragedAPIUse, message_text, 0,
- nullptr);
+ context, PerformanceMonitor::kDiscouragedAPIUse, message_text,
+ base::TimeDelta(), nullptr);
}
}
}
@@ -530,12 +526,12 @@ EventListener* EventTarget::GetAttributeEventListener(
bool EventTarget::dispatchEventForBindings(Event* event,
ExceptionState& exception_state) {
if (!event->WasInitialized()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The event provided is uninitialized.");
return false;
}
if (event->IsBeingDispatched()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The event is already being dispatched.");
return false;
}
@@ -741,6 +737,18 @@ bool EventTarget::FireEventListeners(Event* event,
} else if (CheckTypeThenUseCount(event, EventTypeNames::pointerout,
WebFeature::kPointerOverOutFired,
document)) {
+ } else if (event->eventPhase() == Event::kCapturingPhase ||
+ event->eventPhase() == Event::kBubblingPhase) {
+ if (CheckTypeThenUseCount(
+ event, EventTypeNames::DOMNodeRemoved,
+ WebFeature::kDOMNodeRemovedEventListenedAtNonTarget,
+ document)) {
+ } else if (CheckTypeThenUseCount(
+ event, EventTypeNames::DOMNodeRemovedFromDocument,
+ WebFeature::
+ kDOMNodeRemovedFromDocumentEventListenedAtNonTarget,
+ document)) {
+ }
}
}
}
@@ -756,15 +764,14 @@ bool EventTarget::FireEventListeners(Event* event,
d->firing_event_iterators->push_back(
FiringEventIterator(event->type(), i, size));
- double blocked_event_threshold =
+ base::TimeDelta blocked_event_threshold =
BlockedEventsWarningThreshold(context, event);
- TimeTicks now;
+ base::TimeTicks now;
bool should_report_blocked_event = false;
- if (blocked_event_threshold) {
+ if (!blocked_event_threshold.is_zero()) {
now = CurrentTimeTicks();
should_report_blocked_event =
- (now - event->PlatformTimeStamp()).InSecondsF() >
- blocked_event_threshold;
+ now - event->PlatformTimeStamp() > blocked_event_threshold;
}
bool fired_listener = false;
@@ -816,7 +823,7 @@ bool EventTarget::FireEventListeners(Event* event,
!entry[i - 1].BlockedEventWarningEmitted() &&
!event->defaultPrevented()) {
ReportBlockedEvent(context, event, &entry[i - 1],
- (now - event->PlatformTimeStamp()).InSecondsF());
+ now - event->PlatformTimeStamp());
}
if (passive_forced) {
@@ -875,6 +882,27 @@ void EventTarget::RemoveAllEventListeners() {
}
}
+void EventTarget::EnqueueEvent(Event* event, TaskType task_type) {
+ ExecutionContext* context = GetExecutionContext();
+ if (!context)
+ return;
+ probe::AsyncTaskScheduled(context, event->type(), event);
+ context->GetTaskRunner(task_type)->PostTask(
+ FROM_HERE,
+ WTF::Bind(&EventTarget::DispatchEnqueuedEvent, WrapPersistent(this),
+ WrapPersistent(event), WrapPersistent(context)));
+}
+
+void EventTarget::DispatchEnqueuedEvent(Event* event,
+ ExecutionContext* context) {
+ if (!GetExecutionContext()) {
+ probe::AsyncTaskCanceled(context, event);
+ return;
+ }
+ probe::AsyncTask async_task(context, event);
+ DispatchEvent(event);
+}
+
STATIC_ASSERT_ENUM(WebSettings::PassiveEventListenerDefault::kFalse,
PassiveListenerDefault::kFalse);
STATIC_ASSERT_ENUM(WebSettings::PassiveEventListenerDefault::kTrue,
diff --git a/chromium/third_party/blink/renderer/core/dom/events/event_target.h b/chromium/third_party/blink/renderer/core/dom/events/event_target.h
index 6e83897333d..eb021cc39e2 100644
--- a/chromium/third_party/blink/renderer/core/dom/events/event_target.h
+++ b/chromium/third_party/blink/renderer/core/dom/events/event_target.h
@@ -35,6 +35,7 @@
#include <memory>
#include "base/macros.h"
+#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/events/add_event_listener_options_resolved.h"
#include "third_party/blink/renderer/core/dom/events/event_dispatch_result.h"
@@ -80,15 +81,12 @@ class CORE_EXPORT EventTargetData final
~EventTargetData();
void Trace(blink::Visitor*);
- void TraceWrappers(ScriptWrappableVisitor*) const;
EventListenerMap event_listener_map;
std::unique_ptr<FiringEventIteratorVector> firing_event_iterators;
DISALLOW_COPY_AND_ASSIGN(EventTargetData);
};
-DEFINE_TRAIT_FOR_TRACE_WRAPPERS(EventTargetData);
-
// All DOM event targets extend EventTarget. The spec is defined here:
// https://dom.spec.whatwg.org/#interface-eventtarget
// EventTarget objects allow us to add and remove an event
@@ -157,6 +155,8 @@ class CORE_EXPORT EventTarget : public ScriptWrappable {
DispatchEventResult DispatchEvent(Event*);
+ void EnqueueEvent(Event*, TaskType);
+
// dispatchEventForBindings is intended to only be called from
// javascript originated calls. This method will validate and may adjust
// the Event object before dispatching.
@@ -220,6 +220,8 @@ class CORE_EXPORT EventTarget : public ScriptWrappable {
EventListenerVector*,
EventListenerVector*);
+ void DispatchEnqueuedEvent(Event*, ExecutionContext*);
+
friend class EventListenerIterator;
};
@@ -232,11 +234,6 @@ class CORE_EXPORT EventTargetWithInlineData : public EventTarget {
EventTarget::Trace(visitor);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- visitor->TraceWrappers(event_target_data_);
- EventTarget::TraceWrappers(visitor);
- }
-
protected:
EventTargetData* GetEventTargetData() final { return &event_target_data_; }
EventTargetData& EnsureEventTargetData() final { return event_target_data_; }
@@ -245,7 +242,7 @@ class CORE_EXPORT EventTargetWithInlineData : public EventTarget {
// EventTargetData is a GCed object, so it should not be used as a part of
// object. However, we intentionally use it as a part of object for
// performance, assuming that no one extracts a pointer of
- // EventTargetWithInlineData::m_eventTargetData and store it to a Member etc.
+ // EventTargetWithInlineData::event_target_data_ and store it to a Member etc.
GC_PLUGIN_IGNORE("513199") EventTargetData event_target_data_;
};
diff --git a/chromium/third_party/blink/renderer/core/dom/events/media_element_event_queue.cc b/chromium/third_party/blink/renderer/core/dom/events/media_element_event_queue.cc
deleted file mode 100644
index c55cb3bd90e..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/events/media_element_event_queue.cc
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2012 Victor Carbune (victor@rosedu.org)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/core/dom/events/media_element_event_queue.h"
-
-#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/core/probe/core_probes.h"
-#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
-
-namespace blink {
-
-MediaElementEventQueue* MediaElementEventQueue::Create(
- EventTarget* owner,
- ExecutionContext* context) {
- return new MediaElementEventQueue(owner, context);
-}
-
-MediaElementEventQueue::MediaElementEventQueue(EventTarget* owner,
- ExecutionContext* context)
- : owner_(owner),
- timer_(context->GetTaskRunner(TaskType::kMediaElementEvent),
- this,
- &MediaElementEventQueue::TimerFired),
- is_closed_(false) {}
-
-MediaElementEventQueue::~MediaElementEventQueue() = default;
-
-void MediaElementEventQueue::Trace(blink::Visitor* visitor) {
- visitor->Trace(owner_);
- visitor->Trace(pending_events_);
- EventQueue::Trace(visitor);
-}
-
-bool MediaElementEventQueue::EnqueueEvent(const base::Location& from_here,
- Event* event) {
- if (is_closed_)
- return false;
-
- if (event->target() == owner_)
- event->SetTarget(nullptr);
-
- TRACE_EVENT_ASYNC_BEGIN1("event", "MediaElementEventQueue:enqueueEvent",
- event, "type", event->type().Ascii());
- EventTarget* target = event->target() ? event->target() : owner_.Get();
- probe::AsyncTaskScheduled(target->GetExecutionContext(), event->type(),
- event);
- pending_events_.push_back(event);
-
- if (!timer_.IsActive())
- timer_.StartOneShot(TimeDelta(), from_here);
-
- return true;
-}
-
-bool MediaElementEventQueue::CancelEvent(Event* event) {
- bool found = pending_events_.Contains(event);
-
- if (found) {
- EventTarget* target = event->target() ? event->target() : owner_.Get();
- probe::AsyncTaskCanceled(target->GetExecutionContext(), event);
- pending_events_.EraseAt(pending_events_.Find(event));
- TRACE_EVENT_ASYNC_END2("event", "MediaElementEventQueue:enqueueEvent",
- event, "type", event->type().Ascii(), "status",
- "cancelled");
- }
-
- if (pending_events_.IsEmpty())
- timer_.Stop();
-
- return found;
-}
-
-void MediaElementEventQueue::TimerFired(TimerBase*) {
- DCHECK(!timer_.IsActive());
- DCHECK(!pending_events_.IsEmpty());
-
- HeapVector<Member<Event>> pending_events;
- pending_events_.swap(pending_events);
-
- for (const auto& pending_event : pending_events) {
- Event* event = pending_event.Get();
- EventTarget* target = event->target() ? event->target() : owner_.Get();
- CString type(event->type().Ascii());
- probe::AsyncTask async_task(target->GetExecutionContext(), event);
- TRACE_EVENT_ASYNC_STEP_INTO1("event", "MediaElementEventQueue:enqueueEvent",
- event, "dispatch", "type", type);
- target->DispatchEvent(pending_event);
- TRACE_EVENT_ASYNC_END1("event", "MediaElementEventQueue:enqueueEvent",
- event, "type", type);
- }
-}
-
-void MediaElementEventQueue::Close() {
- is_closed_ = true;
- CancelAllEvents();
-}
-
-void MediaElementEventQueue::CancelAllEvents() {
- timer_.Stop();
-
- for (const auto& pending_event : pending_events_) {
- Event* event = pending_event.Get();
- TRACE_EVENT_ASYNC_END2("event", "MediaElementEventQueue:enqueueEvent",
- event, "type", event->type().Ascii(), "status",
- "cancelled");
- EventTarget* target = event->target() ? event->target() : owner_.Get();
- probe::AsyncTaskCanceled(target->GetExecutionContext(), event);
- }
- pending_events_.clear();
-}
-
-bool MediaElementEventQueue::HasPendingEvents() const {
- return pending_events_.size();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/events/media_element_event_queue.h b/chromium/third_party/blink/renderer/core/dom/events/media_element_event_queue.h
deleted file mode 100644
index 3e1792a8f4b..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/events/media_element_event_queue.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2012 Victor Carbune (victor@rosedu.org)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_MEDIA_ELEMENT_EVENT_QUEUE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EVENTS_MEDIA_ELEMENT_EVENT_QUEUE_H_
-
-#include "base/location.h"
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/events/event_queue.h"
-#include "third_party/blink/renderer/core/dom/events/event_target.h"
-#include "third_party/blink/renderer/platform/timer.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-// Queue for events originating in MediaElement and having
-// "media element event" task type according to the spec.
-class CORE_EXPORT MediaElementEventQueue final : public EventQueue {
- public:
- static MediaElementEventQueue* Create(EventTarget*, ExecutionContext*);
- ~MediaElementEventQueue() override;
-
- // EventQueue
- void Trace(blink::Visitor*) override;
- bool EnqueueEvent(const base::Location&, Event*) override;
- bool CancelEvent(Event*) override;
- void Close() override;
-
- void CancelAllEvents();
- bool HasPendingEvents() const;
-
- private:
- MediaElementEventQueue(EventTarget*, ExecutionContext*);
- void TimerFired(TimerBase*);
-
- Member<EventTarget> owner_;
- HeapVector<Member<Event>> pending_events_;
- TaskRunnerTimer<MediaElementEventQueue> timer_;
-
- bool is_closed_;
-};
-
-} // namespace blink
-
-#endif
diff --git a/chromium/third_party/blink/renderer/core/dom/exception_code.h b/chromium/third_party/blink/renderer/core/dom/exception_code.h
deleted file mode 100644
index 4de043ae128..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/exception_code.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; 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_DOM_EXCEPTION_CODE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EXCEPTION_CODE_H_
-
-namespace blink {
-
-// The DOM standards use unsigned short for exception codes.
-// In our DOM implementation we use int instead, and use different
-// numerical ranges for different types of DOM exception, so that
-// an exception of any type can be expressed with a single integer.
-typedef int ExceptionCode;
-
-// This list must be in sync with |coreExceptions| in DOMExceptions.cpp.
-// Some of these are considered historical since they have been
-// changed or removed from the specifications.
-enum {
- kIndexSizeError = 1,
- kHierarchyRequestError,
- kWrongDocumentError,
- kInvalidCharacterError,
- kNoModificationAllowedError,
- kNotFoundError,
- kNotSupportedError,
- kInUseAttributeError, // Historical. Only used in setAttributeNode etc which
- // have been removed from the DOM specs.
-
- // Introduced in DOM Level 2:
- kInvalidStateError,
- kSyntaxError,
- kInvalidModificationError,
- kNamespaceError,
- kInvalidAccessError,
-
- // Introduced in DOM Level 3:
- kTypeMismatchError, // Historical; use TypeError instead
-
- // XMLHttpRequest extension:
- kSecurityError,
-
- // Others introduced in HTML5:
- kNetworkError,
- kAbortError,
- kURLMismatchError,
- kQuotaExceededError,
- kTimeoutError,
- kInvalidNodeTypeError,
- kDataCloneError,
-
- // The operation failed for an unknown transient reason (e.g. out of memory).
- // Note: Rethrowed V8 exception will also have this code.
- kUnknownError,
-
- // These are IDB-specific.
- kConstraintError,
- kDataError,
- kTransactionInactiveError,
- kReadOnlyError,
- kVersionError,
-
- // File system
- kNotReadableError,
- kEncodingError,
- kPathExistsError,
-
- // SQL
- kSQLDatabaseError, // Naming conflict with DatabaseError class.
-
- // Web Crypto
- kOperationError,
-
- // Push API
- kPermissionDeniedError,
-
- kNotAllowedError,
-
- // Pointer Events
- kInvalidPointerId,
-};
-
-enum V8ErrorType {
- kV8Error = 1000,
- kV8TypeError,
- kV8RangeError,
- kV8SyntaxError,
- kV8ReferenceError,
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_EXCEPTION_CODE_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc b/chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc
index 87cbbd7dbf8..ca96e0d1f9a 100644
--- a/chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc
+++ b/chromium/third_party/blink/renderer/core/dom/first_letter_pseudo_element.cc
@@ -32,7 +32,7 @@
#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/platform/text/text_break_iterator.h"
-#include "third_party/blink/renderer/platform/wtf/text/icu/unicode_icu.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -277,7 +277,9 @@ ComputedStyle* FirstLetterPseudoElement::StyleForFirstLetter(
ComputedStyle* pseudo_style = style_container->GetCachedPseudoStyle(
kPseudoIdFirstLetter, layout_object_container->FirstLineStyle());
DCHECK(pseudo_style);
-
+ pseudo_style->UpdateIsStackingContext(false /* is_document_element */,
+ false /* is_in_top_layer */,
+ false /* is_svg_stacking */);
return pseudo_style;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.h b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.h
index 2ee19038386..829bde11117 100644
--- a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.h
+++ b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal.h
@@ -29,8 +29,8 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/flat_tree_traversal_ng.h"
#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
-#include "third_party/blink/renderer/core/dom/ng/flat_tree_traversal_ng.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/dom/v0_insertion_point.h"
diff --git a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng.cc b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng.cc
new file mode 100644
index 00000000000..c6500a0c739
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng.cc
@@ -0,0 +1,368 @@
+/*
+ * 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.
+ * * 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/dom/flat_tree_traversal_ng.h"
+
+#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/html/html_shadow_element.h"
+#include "third_party/blink/renderer/core/html/html_slot_element.h"
+
+namespace blink {
+
+bool CanBeDistributedToV0InsertionPoint(const Node& node) {
+ return node.IsInV0ShadowTree() || node.IsChildOfV0ShadowHost();
+}
+
+Node* FlatTreeTraversalNg::TraverseChild(const Node& node,
+ TraversalDirection direction) {
+ if (auto* slot = ToHTMLSlotElementIfSupportsAssignmentOrNull(node)) {
+ if (slot->AssignedNodes().IsEmpty()) {
+ return direction == kTraversalDirectionForward ? slot->firstChild()
+ : slot->lastChild();
+ }
+ return direction == kTraversalDirectionForward ? slot->FirstAssignedNode()
+ : slot->LastAssignedNode();
+ }
+
+ Node* child;
+ if (ShadowRoot* shadow_root = node.GetShadowRoot()) {
+ child = direction == kTraversalDirectionForward ? shadow_root->firstChild()
+ : shadow_root->lastChild();
+ } else {
+ child = direction == kTraversalDirectionForward ? node.firstChild()
+ : node.lastChild();
+ }
+
+ if (!child)
+ return nullptr;
+
+ if (child->IsInV0ShadowTree()) {
+ return V0ResolveDistributionStartingAt(*child, direction);
+ }
+ return child;
+}
+
+// This needs only for v0
+// Node* FlatTreeTraversalNg::ResolveDistributionStartingAt(
+// const Node* node,
+// TraversalDirection direction) {
+// if (!node)
+// return nullptr;
+// for (const Node* sibling = node; sibling;
+// sibling = (direction == kTraversalDirectionForward
+// ? sibling->nextSibling()
+// : sibling->previousSibling())) {
+// if (node->IsInV0ShadowTree())
+// return V0ResolveDistributionStartingAt(*sibling, direction);
+// return const_cast<Node*>(sibling);
+// }
+// return nullptr;
+// }
+
+Node* FlatTreeTraversalNg::V0ResolveDistributionStartingAt(
+ const Node& node,
+ TraversalDirection direction) {
+ DCHECK(!ToHTMLSlotElementIfSupportsAssignmentOrNull(node));
+ for (const Node* sibling = &node; sibling;
+ sibling = (direction == kTraversalDirectionForward
+ ? sibling->nextSibling()
+ : sibling->previousSibling())) {
+ if (!IsActiveV0InsertionPoint(*sibling))
+ return const_cast<Node*>(sibling);
+ const V0InsertionPoint& insertion_point = ToV0InsertionPoint(*sibling);
+ if (Node* found = (direction == kTraversalDirectionForward
+ ? insertion_point.FirstDistributedNode()
+ : insertion_point.LastDistributedNode()))
+ return found;
+ DCHECK(IsHTMLShadowElement(insertion_point) ||
+ (IsHTMLContentElement(insertion_point) &&
+ !insertion_point.HasChildren()));
+ }
+ return nullptr;
+}
+
+// TODO(hayato): This may return a wrong result for a node which is not in a
+// document flat tree. See FlatTreeTraversalNgTest's redistribution test for
+// details.
+Node* FlatTreeTraversalNg::TraverseSiblings(const Node& node,
+ TraversalDirection direction) {
+ if (node.IsChildOfV1ShadowHost())
+ return TraverseSiblingsForV1HostChild(node, direction);
+
+ if (ShadowRootWhereNodeCanBeDistributedForV0(node))
+ return TraverseSiblingsForV0Distribution(node, direction);
+
+ Node* sibling = direction == kTraversalDirectionForward
+ ? node.nextSibling()
+ : node.previousSibling();
+
+ if (!node.IsInV0ShadowTree())
+ return sibling;
+
+ if (sibling) {
+ if (Node* found = V0ResolveDistributionStartingAt(*sibling, direction))
+ return found;
+ }
+
+ // // Slotted nodes are already handled in traverseSiblingsForV1HostChild()
+ // // above, here is for fallback contents.
+ // if (auto* slot = ToHTMLSlotElementOrNull(node.parentElement())) {
+ // if (slot->SupportsAssignment() && slot->AssignedNodes().IsEmpty())
+ // return TraverseSiblings(*slot, direction);
+ // }
+ return nullptr;
+}
+
+Node* FlatTreeTraversalNg::TraverseSiblingsForV1HostChild(
+ const Node& node,
+ TraversalDirection direction) {
+ HTMLSlotElement* slot = node.AssignedSlot();
+ if (!slot)
+ return nullptr;
+ return direction == kTraversalDirectionForward
+ ? slot->AssignedNodeNextTo(node)
+ : slot->AssignedNodePreviousTo(node);
+}
+
+Node* FlatTreeTraversalNg::TraverseSiblingsForV0Distribution(
+ const Node& node,
+ TraversalDirection direction) {
+ const V0InsertionPoint* final_destination = ResolveReprojection(&node);
+ if (!final_destination)
+ return nullptr;
+ if (Node* found = (direction == kTraversalDirectionForward
+ ? final_destination->DistributedNodeNextTo(&node)
+ : final_destination->DistributedNodePreviousTo(&node)))
+ return found;
+ return TraverseSiblings(*final_destination, direction);
+}
+
+ContainerNode* FlatTreeTraversalNg::TraverseParent(
+ const Node& node,
+ ParentTraversalDetails* details) {
+ // TODO(hayato): Stop this hack for a pseudo element because a pseudo element
+ // is not a child of its parentOrShadowHostNode() in a flat tree.
+ if (node.IsPseudoElement())
+ return node.ParentOrShadowHostNode();
+
+ if (node.IsChildOfV1ShadowHost())
+ return node.AssignedSlot();
+
+ if (auto* parent_slot =
+ ToHTMLSlotElementIfSupportsAssignmentOrNull(node.parentElement())) {
+ if (!parent_slot->AssignedNodes().IsEmpty())
+ return nullptr;
+ return parent_slot;
+ }
+
+ if (CanBeDistributedToV0InsertionPoint(node))
+ return TraverseParentForV0(node, details);
+
+ DCHECK(!ShadowRootWhereNodeCanBeDistributedForV0(node));
+ return TraverseParentOrHost(node);
+}
+
+ContainerNode* FlatTreeTraversalNg::TraverseParentForV0(
+ const Node& node,
+ ParentTraversalDetails* details) {
+ if (ShadowRootWhereNodeCanBeDistributedForV0(node)) {
+ if (const V0InsertionPoint* insertion_point = ResolveReprojection(&node)) {
+ if (details)
+ details->DidTraverseInsertionPoint(insertion_point);
+ // The node is distributed. But the distribution was stopped at this
+ // insertion point.
+ if (ShadowRootWhereNodeCanBeDistributedForV0(*insertion_point))
+ return nullptr;
+ return TraverseParent(*insertion_point);
+ }
+ return nullptr;
+ }
+ ContainerNode* parent = TraverseParentOrHost(node);
+ if (IsActiveV0InsertionPoint(*parent))
+ return nullptr;
+ return parent;
+}
+
+ContainerNode* FlatTreeTraversalNg::TraverseParentOrHost(const Node& node) {
+ ContainerNode* parent = node.parentNode();
+ if (!parent)
+ return nullptr;
+ if (!parent->IsShadowRoot())
+ return parent;
+ ShadowRoot* shadow_root = ToShadowRoot(parent);
+ return &shadow_root->host();
+}
+
+Node* FlatTreeTraversalNg::ChildAt(const Node& node, unsigned index) {
+ AssertPrecondition(node);
+ Node* child = TraverseFirstChild(node);
+ while (child && index--)
+ child = NextSibling(*child);
+ AssertPostcondition(child);
+ return child;
+}
+
+Node* FlatTreeTraversalNg::NextSkippingChildren(const Node& node) {
+ if (Node* next_sibling = TraverseNextSibling(node))
+ return next_sibling;
+ return TraverseNextAncestorSibling(node);
+}
+
+bool FlatTreeTraversalNg::ContainsIncludingPseudoElement(
+ const ContainerNode& container,
+ const Node& node) {
+ AssertPrecondition(container);
+ AssertPrecondition(node);
+ // This can be slower than FlatTreeTraversalNg::contains() because we
+ // can't early exit even when container doesn't have children.
+ for (const Node* current = &node; current;
+ current = TraverseParent(*current)) {
+ if (current == &container)
+ return true;
+ }
+ return false;
+}
+
+Node* FlatTreeTraversalNg::PreviousSkippingChildren(const Node& node) {
+ if (Node* previous_sibling = TraversePreviousSibling(node))
+ return previous_sibling;
+ return TraversePreviousAncestorSibling(node);
+}
+
+Node* FlatTreeTraversalNg::PreviousAncestorSiblingPostOrder(
+ const Node& current,
+ const Node* stay_within) {
+ DCHECK(!FlatTreeTraversalNg::PreviousSibling(current));
+ for (Node* parent = FlatTreeTraversalNg::Parent(current); parent;
+ parent = FlatTreeTraversalNg::Parent(*parent)) {
+ if (parent == stay_within)
+ return nullptr;
+ if (Node* previous_sibling = FlatTreeTraversalNg::PreviousSibling(*parent))
+ return previous_sibling;
+ }
+ return nullptr;
+}
+
+// TODO(yosin) We should consider introducing template class to share code
+// between DOM tree traversal and flat tree tarversal.
+Node* FlatTreeTraversalNg::PreviousPostOrder(const Node& current,
+ const Node* stay_within) {
+ AssertPrecondition(current);
+ if (stay_within)
+ AssertPrecondition(*stay_within);
+ if (Node* last_child = TraverseLastChild(current)) {
+ AssertPostcondition(last_child);
+ return last_child;
+ }
+ if (current == stay_within)
+ return nullptr;
+ if (Node* previous_sibling = TraversePreviousSibling(current)) {
+ AssertPostcondition(previous_sibling);
+ return previous_sibling;
+ }
+ return PreviousAncestorSiblingPostOrder(current, stay_within);
+}
+
+bool FlatTreeTraversalNg::IsDescendantOf(const Node& node, const Node& other) {
+ AssertPrecondition(node);
+ AssertPrecondition(other);
+ if (!HasChildren(other) || node.isConnected() != other.isConnected())
+ return false;
+ for (const ContainerNode* n = TraverseParent(node); n;
+ n = TraverseParent(*n)) {
+ if (n == other)
+ return true;
+ }
+ return false;
+}
+
+Node* FlatTreeTraversalNg::CommonAncestor(const Node& node_a,
+ const Node& node_b) {
+ AssertPrecondition(node_a);
+ AssertPrecondition(node_b);
+ Node* result = node_a.CommonAncestor(node_b, [](const Node& node) {
+ return FlatTreeTraversalNg::Parent(node);
+ });
+ AssertPostcondition(result);
+ return result;
+}
+
+Node* FlatTreeTraversalNg::TraverseNextAncestorSibling(const Node& node) {
+ DCHECK(!TraverseNextSibling(node));
+ for (Node* parent = TraverseParent(node); parent;
+ parent = TraverseParent(*parent)) {
+ if (Node* next_sibling = TraverseNextSibling(*parent))
+ return next_sibling;
+ }
+ return nullptr;
+}
+
+Node* FlatTreeTraversalNg::TraversePreviousAncestorSibling(const Node& node) {
+ DCHECK(!TraversePreviousSibling(node));
+ for (Node* parent = TraverseParent(node); parent;
+ parent = TraverseParent(*parent)) {
+ if (Node* previous_sibling = TraversePreviousSibling(*parent))
+ return previous_sibling;
+ }
+ return nullptr;
+}
+
+unsigned FlatTreeTraversalNg::Index(const Node& node) {
+ AssertPrecondition(node);
+ unsigned count = 0;
+ for (Node* runner = TraversePreviousSibling(node); runner;
+ runner = PreviousSibling(*runner))
+ ++count;
+ return count;
+}
+
+unsigned FlatTreeTraversalNg::CountChildren(const Node& node) {
+ AssertPrecondition(node);
+ unsigned count = 0;
+ for (Node* runner = TraverseFirstChild(node); runner;
+ runner = TraverseNextSibling(*runner))
+ ++count;
+ return count;
+}
+
+Node* FlatTreeTraversalNg::LastWithin(const Node& node) {
+ AssertPrecondition(node);
+ Node* descendant = TraverseLastChild(node);
+ for (Node* child = descendant; child; child = LastChild(*child))
+ descendant = child;
+ AssertPostcondition(descendant);
+ return descendant;
+}
+
+Node& FlatTreeTraversalNg::LastWithinOrSelf(const Node& node) {
+ AssertPrecondition(node);
+ Node* last_descendant = LastWithin(node);
+ Node& result = last_descendant ? *last_descendant : const_cast<Node&>(node);
+ AssertPostcondition(&result);
+ return result;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng.h b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng.h
new file mode 100644
index 00000000000..bb93d2a749f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng.h
@@ -0,0 +1,331 @@
+/*
+ * 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.
+ * * 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_DOM_FLAT_TREE_TRAVERSAL_NG_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_FLAT_TREE_TRAVERSAL_NG_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/dom/layout_tree_builder_traversal.h"
+#include "third_party/blink/renderer/core/dom/node_traversal.h"
+#include "third_party/blink/renderer/core/dom/shadow_root.h"
+#include "third_party/blink/renderer/core/dom/v0_insertion_point.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+
+namespace blink {
+
+class ContainerNode;
+class Node;
+
+bool CanBeDistributedToV0InsertionPoint(const Node& node);
+
+// Flat tree version of |NodeTraversal|.
+//
+// None of member functions takes a |ShadowRoot| or an active insertion point,
+// e.g. roughly speaking <content> and <shadow> in the shadow tree, see
+// |InsertionPoint::isActive()| for details of active insertion points, since
+// they aren't appeared in the flat tree. |assertPrecondition()| and
+// |assertPostCondition()| check this condition.
+//
+// FIXME: Make some functions inline to optimise the performance.
+// https://bugs.webkit.org/show_bug.cgi?id=82702
+class CORE_EXPORT FlatTreeTraversalNg {
+ STATIC_ONLY(FlatTreeTraversalNg);
+
+ public:
+ typedef LayoutTreeBuilderTraversal::ParentDetails ParentTraversalDetails;
+ using TraversalNodeType = Node;
+
+ static Node* Next(const Node&);
+ static Node* Next(const Node&, const Node* stay_within);
+ static Node* Previous(const Node&);
+
+ static Node* FirstChild(const Node&);
+ static Node* LastChild(const Node&);
+ static bool HasChildren(const Node&);
+
+ static ContainerNode* Parent(const Node&, ParentTraversalDetails* = nullptr);
+ static Element* ParentElement(const Node&);
+
+ static Node* NextSibling(const Node&);
+ static Node* PreviousSibling(const Node&);
+
+ // Returns a child node at |index|. If |index| is greater than or equal to
+ // the children, this function returns |nullptr|.
+ static Node* ChildAt(const Node&, unsigned index);
+
+ // Flat tree version of |NodeTraversal::nextSkippingChildren()|. This
+ // function is similar to |next()| but skips child nodes of a specified
+ // node.
+ static Node* NextSkippingChildren(const Node&);
+ static Node* NextSkippingChildren(const Node&, const Node* stay_within);
+
+ static Node* FirstWithin(const Node& current) { return FirstChild(current); }
+
+ // Flat tree version of |NodeTraversal::previousSkippingChildren()|
+ // similar to |previous()| but skipping child nodes of the specified node.
+ static Node* PreviousSkippingChildren(const Node&);
+
+ // Like previous, but visits parents before their children.
+ static Node* PreviousPostOrder(const Node&,
+ const Node* stay_within = nullptr);
+
+ // Flat tree version of |Node::isDescendantOf(other)|. This function
+ // returns true if |other| contains |node|, otherwise returns
+ // false. If |other| is |node|, this function returns false.
+ static bool IsDescendantOf(const Node& /*node*/, const Node& other);
+
+ static bool Contains(const ContainerNode& container, const Node& node) {
+ AssertPrecondition(container);
+ AssertPrecondition(node);
+ return container == node || IsDescendantOf(node, container);
+ }
+
+ static bool ContainsIncludingPseudoElement(const ContainerNode&, const Node&);
+
+ // Returns a common ancestor of |nodeA| and |nodeB| if exists, otherwise
+ // returns |nullptr|.
+ static Node* CommonAncestor(const Node& node_a, const Node& node_b);
+
+ // Flat tree version of |Node::nodeIndex()|. This function returns a
+ // zero base position number of the specified node in child nodes list, or
+ // zero if the specified node has no parent.
+ static unsigned Index(const Node&);
+
+ // Flat tree version of |ContainerNode::countChildren()|. This function
+ // returns the number of the child nodes of the specified node in the
+ // flat tree.
+ static unsigned CountChildren(const Node&);
+
+ static Node* LastWithin(const Node&);
+ static Node& LastWithinOrSelf(const Node&);
+
+ // Flat tree range helper functions for range based for statement.
+ // TODO(dom-team): We should have following functions to match with
+ // |NodeTraversal|:
+ // - AncestorsOf()
+ // - DescendantsOf()
+ // - InclusiveAncestorsOf()
+ // - InclusiveDescendantsOf()
+ // - StartsAt()
+ // - StartsAfter()
+ static TraversalRange<TraversalChildrenIterator<FlatTreeTraversalNg>>
+ ChildrenOf(const Node&);
+
+ private:
+ enum TraversalDirection {
+ kTraversalDirectionForward,
+ kTraversalDirectionBackward
+ };
+
+ static void AssertPrecondition(const Node& node) {
+ DCHECK(!node.NeedsDistributionRecalc());
+ DCHECK(node.CanParticipateInFlatTree());
+ }
+
+ static void AssertPostcondition(const Node* node) {
+#if DCHECK_IS_ON()
+ if (node)
+ AssertPrecondition(*node);
+#endif
+ }
+
+ // static Node* ResolveDistributionStartingAt(const Node*,
+ // TraversalDirection);
+ static Node* V0ResolveDistributionStartingAt(const Node&, TraversalDirection);
+
+ static Node* TraverseNext(const Node&);
+ static Node* TraverseNext(const Node&, const Node* stay_within);
+ static Node* TraverseNextSkippingChildren(const Node&,
+ const Node* stay_within);
+ static Node* TraversePrevious(const Node&);
+
+ static Node* TraverseFirstChild(const Node&);
+ static Node* TraverseLastChild(const Node&);
+ static Node* TraverseChild(const Node&, TraversalDirection);
+
+ static ContainerNode* TraverseParent(const Node&,
+ ParentTraversalDetails* = nullptr);
+ // TODO(hayato): Make ParentTraversalDetails be aware of slot elements too.
+ static ContainerNode* TraverseParentForV0(const Node&,
+ ParentTraversalDetails* = nullptr);
+ static ContainerNode* TraverseParentOrHost(const Node&);
+
+ static Node* TraverseNextSibling(const Node&);
+ static Node* TraversePreviousSibling(const Node&);
+
+ static Node* TraverseSiblings(const Node&, TraversalDirection);
+ static Node* TraverseSiblingsForV1HostChild(const Node&, TraversalDirection);
+ static Node* TraverseSiblingsForV0Distribution(const Node&,
+ TraversalDirection);
+
+ static Node* TraverseNextAncestorSibling(const Node&);
+ static Node* TraversePreviousAncestorSibling(const Node&);
+ static Node* PreviousAncestorSiblingPostOrder(const Node& current,
+ const Node* stay_within);
+};
+
+inline ContainerNode* FlatTreeTraversalNg::Parent(
+ const Node& node,
+ ParentTraversalDetails* details) {
+ AssertPrecondition(node);
+ ContainerNode* result = TraverseParent(node, details);
+ AssertPostcondition(result);
+ return result;
+}
+
+inline Element* FlatTreeTraversalNg::ParentElement(const Node& node) {
+ ContainerNode* parent = FlatTreeTraversalNg::Parent(node);
+ return parent && parent->IsElementNode() ? ToElement(parent) : nullptr;
+}
+
+inline Node* FlatTreeTraversalNg::NextSibling(const Node& node) {
+ AssertPrecondition(node);
+ Node* result = TraverseSiblings(node, kTraversalDirectionForward);
+ AssertPostcondition(result);
+ return result;
+}
+
+inline Node* FlatTreeTraversalNg::PreviousSibling(const Node& node) {
+ AssertPrecondition(node);
+ Node* result = TraverseSiblings(node, kTraversalDirectionBackward);
+ AssertPostcondition(result);
+ return result;
+}
+
+inline Node* FlatTreeTraversalNg::Next(const Node& node) {
+ AssertPrecondition(node);
+ Node* result = TraverseNext(node);
+ AssertPostcondition(result);
+ return result;
+}
+
+inline Node* FlatTreeTraversalNg::Next(const Node& node,
+ const Node* stay_within) {
+ AssertPrecondition(node);
+ Node* result = TraverseNext(node, stay_within);
+ AssertPostcondition(result);
+ return result;
+}
+
+inline Node* FlatTreeTraversalNg::NextSkippingChildren(
+ const Node& node,
+ const Node* stay_within) {
+ AssertPrecondition(node);
+ Node* result = TraverseNextSkippingChildren(node, stay_within);
+ AssertPostcondition(result);
+ return result;
+}
+
+inline Node* FlatTreeTraversalNg::TraverseNext(const Node& node) {
+ if (Node* next = TraverseFirstChild(node))
+ return next;
+ for (const Node* next = &node; next; next = TraverseParent(*next)) {
+ if (Node* sibling = TraverseNextSibling(*next))
+ return sibling;
+ }
+ return nullptr;
+}
+
+inline Node* FlatTreeTraversalNg::TraverseNext(const Node& node,
+ const Node* stay_within) {
+ if (Node* next = TraverseFirstChild(node))
+ return next;
+ return TraverseNextSkippingChildren(node, stay_within);
+}
+
+inline Node* FlatTreeTraversalNg::TraverseNextSkippingChildren(
+ const Node& node,
+ const Node* stay_within) {
+ for (const Node* next = &node; next; next = TraverseParent(*next)) {
+ if (next == stay_within)
+ return nullptr;
+ if (Node* sibling = TraverseNextSibling(*next))
+ return sibling;
+ }
+ return nullptr;
+}
+
+inline Node* FlatTreeTraversalNg::Previous(const Node& node) {
+ AssertPrecondition(node);
+ Node* result = TraversePrevious(node);
+ AssertPostcondition(result);
+ return result;
+}
+
+inline Node* FlatTreeTraversalNg::TraversePrevious(const Node& node) {
+ if (Node* previous = TraversePreviousSibling(node)) {
+ while (Node* child = TraverseLastChild(*previous))
+ previous = child;
+ return previous;
+ }
+ return TraverseParent(node);
+}
+
+inline Node* FlatTreeTraversalNg::FirstChild(const Node& node) {
+ AssertPrecondition(node);
+ Node* result = TraverseChild(node, kTraversalDirectionForward);
+ AssertPostcondition(result);
+ return result;
+}
+
+inline Node* FlatTreeTraversalNg::LastChild(const Node& node) {
+ AssertPrecondition(node);
+ Node* result = TraverseLastChild(node);
+ AssertPostcondition(result);
+ return result;
+}
+
+inline bool FlatTreeTraversalNg::HasChildren(const Node& node) {
+ return FirstChild(node);
+}
+
+inline Node* FlatTreeTraversalNg::TraverseNextSibling(const Node& node) {
+ return TraverseSiblings(node, kTraversalDirectionForward);
+}
+
+inline Node* FlatTreeTraversalNg::TraversePreviousSibling(const Node& node) {
+ return TraverseSiblings(node, kTraversalDirectionBackward);
+}
+
+inline Node* FlatTreeTraversalNg::TraverseFirstChild(const Node& node) {
+ return TraverseChild(node, kTraversalDirectionForward);
+}
+
+inline Node* FlatTreeTraversalNg::TraverseLastChild(const Node& node) {
+ return TraverseChild(node, kTraversalDirectionBackward);
+}
+
+// TraverseRange<T> implementations
+inline TraversalRange<TraversalChildrenIterator<FlatTreeTraversalNg>>
+FlatTreeTraversalNg::ChildrenOf(const Node& parent) {
+ return TraversalRange<TraversalChildrenIterator<FlatTreeTraversalNg>>(
+ &parent);
+}
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_FLAT_TREE_TRAVERSAL_NG_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng_test.cc b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng_test.cc
new file mode 100644
index 00000000000..7f909cc882a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_ng_test.cc
@@ -0,0 +1,772 @@
+// 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/dom/flat_tree_traversal_ng.h"
+
+#include <memory>
+#include "testing/gtest/include/gtest/gtest.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.h"
+#include "third_party/blink/renderer/core/dom/node_traversal.h"
+#include "third_party/blink/renderer/core/dom/shadow_root.h"
+#include "third_party/blink/renderer/core/frame/local_frame_view.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/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/geometry/int_size.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+#include "third_party/blink/renderer/platform/wtf/compiler.h"
+#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+// To avoid symbol collisions in jumbo builds.
+namespace flat_tree_traversal_ng_test {
+
+class FlatTreeTraversalNgTest : public PageTestBase,
+ private ScopedSlotInFlatTreeForTest,
+ ScopedIncrementalShadowDOMForTest {
+ public:
+ FlatTreeTraversalNgTest()
+ : ScopedSlotInFlatTreeForTest(true),
+ ScopedIncrementalShadowDOMForTest(true) {}
+
+ protected:
+ // Sets |mainHTML| to BODY element with |innerHTML| property and attaches
+ // shadow root to child with |shadowHTML|, then update distribution for
+ // calling member functions in |FlatTreeTraversalNg|.
+ void SetupSampleHTML(const char* main_html,
+ const char* shadow_html,
+ unsigned);
+
+ void SetupDocumentTree(const char* main_html);
+
+ void AttachV0ShadowRoot(Element& shadow_host, const char* shadow_inner_html);
+ void AttachOpenShadowRoot(Element& shadow_host,
+ const char* shadow_inner_html);
+};
+
+void FlatTreeTraversalNgTest::SetupSampleHTML(const char* main_html,
+ const char* shadow_html,
+ unsigned index) {
+ Element* body = GetDocument().body();
+ body->SetInnerHTMLFromString(String::FromUTF8(main_html));
+ Element* shadow_host = ToElement(NodeTraversal::ChildAt(*body, index));
+ ShadowRoot& shadow_root = shadow_host->CreateV0ShadowRootForTesting();
+ shadow_root.SetInnerHTMLFromString(String::FromUTF8(shadow_html));
+ body->UpdateDistributionForFlatTreeTraversal();
+}
+
+void FlatTreeTraversalNgTest::SetupDocumentTree(const char* main_html) {
+ Element* body = GetDocument().body();
+ body->SetInnerHTMLFromString(String::FromUTF8(main_html));
+}
+
+void FlatTreeTraversalNgTest::AttachV0ShadowRoot(
+ Element& shadow_host,
+ const char* shadow_inner_html) {
+ ShadowRoot& shadow_root = shadow_host.CreateV0ShadowRootForTesting();
+ shadow_root.SetInnerHTMLFromString(String::FromUTF8(shadow_inner_html));
+ GetDocument().body()->UpdateDistributionForFlatTreeTraversal();
+}
+
+void FlatTreeTraversalNgTest::AttachOpenShadowRoot(
+ Element& shadow_host,
+ const char* shadow_inner_html) {
+ ShadowRoot& shadow_root =
+ shadow_host.AttachShadowRootInternal(ShadowRootType::kOpen);
+ shadow_root.SetInnerHTMLFromString(String::FromUTF8(shadow_inner_html));
+ GetDocument().body()->UpdateDistributionForFlatTreeTraversal();
+}
+
+namespace {
+
+void TestCommonAncestor(Node* expected_result,
+ const Node& node_a,
+ const Node& node_b) {
+ Node* result1 = FlatTreeTraversalNg::CommonAncestor(node_a, node_b);
+ EXPECT_EQ(expected_result, result1)
+ << "commonAncestor(" << node_a.textContent() << ","
+ << node_b.textContent() << ")";
+ Node* result2 = FlatTreeTraversalNg::CommonAncestor(node_b, node_a);
+ EXPECT_EQ(expected_result, result2)
+ << "commonAncestor(" << node_b.textContent() << ","
+ << node_a.textContent() << ")";
+}
+
+} // namespace
+
+// Test case for
+// - childAt
+// - countChildren
+// - hasChildren
+// - index
+// - isDescendantOf
+TEST_F(FlatTreeTraversalNgTest, childAt) {
+ const char* main_html =
+ "<div id='m0'>"
+ "<span id='m00'>m00</span>"
+ "<span id='m01'>m01</span>"
+ "</div>";
+ const char* shadow_html =
+ "<a id='s00'>s00</a>"
+ "<content select='#m01'></content>"
+ "<a id='s02'>s02</a>"
+ "<a id='s03'><content select='#m00'></content></a>"
+ "<a id='s04'>s04</a>";
+ SetupSampleHTML(main_html, shadow_html, 0);
+
+ Element* body = GetDocument().body();
+ Element* m0 = body->QuerySelector("#m0");
+ Element* m00 = m0->QuerySelector("#m00");
+ Element* m01 = m0->QuerySelector("#m01");
+
+ Element* shadow_host = m0;
+ ShadowRoot* shadow_root = shadow_host->OpenShadowRoot();
+ Element* s00 = shadow_root->QuerySelector("#s00");
+ Element* s02 = shadow_root->QuerySelector("#s02");
+ Element* s03 = shadow_root->QuerySelector("#s03");
+ Element* s04 = shadow_root->QuerySelector("#s04");
+
+ const unsigned kNumberOfChildNodes = 5;
+ Node* expected_child_nodes[5] = {s00, m01, s02, s03, s04};
+
+ ASSERT_EQ(kNumberOfChildNodes,
+ FlatTreeTraversalNg::CountChildren(*shadow_host));
+ EXPECT_TRUE(FlatTreeTraversalNg::HasChildren(*shadow_host));
+
+ for (unsigned index = 0; index < kNumberOfChildNodes; ++index) {
+ Node* child = FlatTreeTraversalNg::ChildAt(*shadow_host, index);
+ EXPECT_EQ(expected_child_nodes[index], child)
+ << "FlatTreeTraversalNg::childAt(*shadowHost, " << index << ")";
+ EXPECT_EQ(index, FlatTreeTraversalNg::Index(*child))
+ << "FlatTreeTraversalNg::index(FlatTreeTraversalNg(*shadowHost, "
+ << index << "))";
+ EXPECT_TRUE(FlatTreeTraversalNg::IsDescendantOf(*child, *shadow_host))
+ << "FlatTreeTraversalNg::isDescendantOf(*FlatTreeTraversalNg(*"
+ "shadowHost, "
+ << index << "), *shadowHost)";
+ }
+ EXPECT_EQ(nullptr,
+ FlatTreeTraversalNg::ChildAt(*shadow_host, kNumberOfChildNodes + 1))
+ << "Out of bounds childAt() returns nullptr.";
+
+ // Distribute node |m00| is child of node in shadow tree |s03|.
+ EXPECT_EQ(m00, FlatTreeTraversalNg::ChildAt(*s03, 0));
+}
+
+TEST_F(FlatTreeTraversalNgTest, ChildrenOf) {
+ SetupSampleHTML(
+ "<p id=sample>ZERO<span slot=three>three</b><span "
+ "slot=one>one</b>FOUR</p>",
+ "zero<slot name=one></slot>two<slot name=three></slot>four", 0);
+ Element* const sample = GetDocument().getElementById("sample");
+
+ HeapVector<Member<Node>> expected_nodes;
+ for (Node* runner = FlatTreeTraversalNg::FirstChild(*sample); runner;
+ runner = FlatTreeTraversalNg::NextSibling(*runner)) {
+ expected_nodes.push_back(runner);
+ }
+
+ HeapVector<Member<Node>> actual_nodes;
+ for (Node& child : FlatTreeTraversalNg::ChildrenOf(*sample))
+ actual_nodes.push_back(&child);
+
+ EXPECT_EQ(expected_nodes, actual_nodes);
+}
+
+// Test case for
+// - commonAncestor
+// - isDescendantOf
+TEST_F(FlatTreeTraversalNgTest, commonAncestor) {
+ // We build following flat tree:
+ // ____BODY___
+ // | | |
+ // m0 m1 m2 m1 is shadow host having m10, m11, m12.
+ // _|_ | __|__
+ // | | | | |
+ // m00 m01 | m20 m21
+ // _____|_____________
+ // | | | | |
+ // s10 s11 s12 s13 s14
+ // |
+ // __|__
+ // | | |
+ // m12 m10 m11 <-- distributed
+ // where: each symbol consists with prefix, child index, child-child index.
+ // prefix "m" means node in main tree,
+ // prefix "d" means node in main tree and distributed
+ // prefix "s" means node in shadow tree
+ const char* main_html =
+ "<a id='m0'><b id='m00'>m00</b><b id='m01'>m01</b></a>"
+ "<a id='m1'>"
+ "<b id='m10'>m10</b>"
+ "<b id='m11'>m11</b>"
+ "<b id='m12'>m12</b>"
+ "</a>"
+ "<a id='m2'><b id='m20'>m20</b><b id='m21'>m21</b></a>";
+ const char* shadow_html =
+ "<a id='s10'>s10</a>"
+ "<a id='s11'><content select='#m12'></content></a>"
+ "<a id='s12'>s12</a>"
+ "<a id='s13'>"
+ "<content select='#m10'></content>"
+ "<content select='#m11'></content>"
+ "</a>"
+ "<a id='s14'>s14</a>";
+ SetupSampleHTML(main_html, shadow_html, 1);
+ Element* body = GetDocument().body();
+ Element* m0 = body->QuerySelector("#m0");
+ Element* m1 = body->QuerySelector("#m1");
+ Element* m2 = body->QuerySelector("#m2");
+
+ Element* m00 = body->QuerySelector("#m00");
+ Element* m01 = body->QuerySelector("#m01");
+ Element* m10 = body->QuerySelector("#m10");
+ Element* m11 = body->QuerySelector("#m11");
+ Element* m12 = body->QuerySelector("#m12");
+ Element* m20 = body->QuerySelector("#m20");
+ Element* m21 = body->QuerySelector("#m21");
+
+ ShadowRoot* shadow_root = m1->OpenShadowRoot();
+ Element* s10 = shadow_root->QuerySelector("#s10");
+ Element* s11 = shadow_root->QuerySelector("#s11");
+ Element* s12 = shadow_root->QuerySelector("#s12");
+ Element* s13 = shadow_root->QuerySelector("#s13");
+ Element* s14 = shadow_root->QuerySelector("#s14");
+
+ TestCommonAncestor(body, *m0, *m1);
+ TestCommonAncestor(body, *m1, *m2);
+ TestCommonAncestor(body, *m1, *m20);
+ TestCommonAncestor(body, *s14, *m21);
+
+ TestCommonAncestor(m0, *m0, *m0);
+ TestCommonAncestor(m0, *m00, *m01);
+
+ TestCommonAncestor(m1, *m1, *m1);
+ TestCommonAncestor(m1, *s10, *s14);
+ TestCommonAncestor(m1, *s10, *m12);
+ TestCommonAncestor(m1, *s12, *m12);
+ TestCommonAncestor(m1, *m10, *m12);
+
+ TestCommonAncestor(m01, *m01, *m01);
+ TestCommonAncestor(s11, *s11, *m12);
+ TestCommonAncestor(s13, *m10, *m11);
+
+ s12->remove(ASSERT_NO_EXCEPTION);
+ TestCommonAncestor(s12, *s12, *s12);
+ TestCommonAncestor(nullptr, *s12, *s11);
+ TestCommonAncestor(nullptr, *s12, *m01);
+ TestCommonAncestor(nullptr, *s12, *m20);
+
+ m20->remove(ASSERT_NO_EXCEPTION);
+ TestCommonAncestor(m20, *m20, *m20);
+ TestCommonAncestor(nullptr, *m20, *s12);
+ TestCommonAncestor(nullptr, *m20, *m1);
+}
+
+// Test case for
+// - nextSkippingChildren
+// - previousSkippingChildren
+TEST_F(FlatTreeTraversalNgTest, nextSkippingChildren) {
+ const char* main_html =
+ "<div id='m0'>m0</div>"
+ "<div id='m1'>"
+ "<span id='m10'>m10</span>"
+ "<span id='m11'>m11</span>"
+ "</div>"
+ "<div id='m2'>m2</div>";
+ const char* shadow_html =
+ "<content select='#m11'></content>"
+ "<a id='s11'>s11</a>"
+ "<a id='s12'>"
+ "<b id='s120'>s120</b>"
+ "<content select='#m10'></content>"
+ "</a>";
+ SetupSampleHTML(main_html, shadow_html, 1);
+
+ Element* body = GetDocument().body();
+ Element* m0 = body->QuerySelector("#m0");
+ Element* m1 = body->QuerySelector("#m1");
+ Element* m2 = body->QuerySelector("#m2");
+
+ Element* m10 = body->QuerySelector("#m10");
+ Element* m11 = body->QuerySelector("#m11");
+
+ ShadowRoot* shadow_root = m1->OpenShadowRoot();
+ Element* s11 = shadow_root->QuerySelector("#s11");
+ Element* s12 = shadow_root->QuerySelector("#s12");
+ Element* s120 = shadow_root->QuerySelector("#s120");
+
+ // Main tree node to main tree node
+ EXPECT_EQ(*m1, FlatTreeTraversalNg::NextSkippingChildren(*m0));
+ EXPECT_EQ(*m0, FlatTreeTraversalNg::PreviousSkippingChildren(*m1));
+
+ // Distribute node to main tree node
+ EXPECT_EQ(*m2, FlatTreeTraversalNg::NextSkippingChildren(*m10));
+ EXPECT_EQ(*m1, FlatTreeTraversalNg::PreviousSkippingChildren(*m2));
+
+ // Distribute node to node in shadow tree
+ EXPECT_EQ(*s11, FlatTreeTraversalNg::NextSkippingChildren(*m11));
+ EXPECT_EQ(*m11, FlatTreeTraversalNg::PreviousSkippingChildren(*s11));
+
+ // Node in shadow tree to distributed node
+ EXPECT_EQ(*s11, FlatTreeTraversalNg::NextSkippingChildren(*m11));
+ EXPECT_EQ(*m11, FlatTreeTraversalNg::PreviousSkippingChildren(*s11));
+
+ EXPECT_EQ(*m10, FlatTreeTraversalNg::NextSkippingChildren(*s120));
+ EXPECT_EQ(*s120, FlatTreeTraversalNg::PreviousSkippingChildren(*m10));
+
+ // Node in shadow tree to main tree
+ EXPECT_EQ(*m2, FlatTreeTraversalNg::NextSkippingChildren(*s12));
+ EXPECT_EQ(*m1, FlatTreeTraversalNg::PreviousSkippingChildren(*m2));
+}
+
+// Test case for
+// - lastWithin
+// - lastWithinOrSelf
+TEST_F(FlatTreeTraversalNgTest, lastWithin) {
+ const char* main_html =
+ "<div id='m0'>m0</div>"
+ "<div id='m1'>"
+ "<span id='m10'>m10</span>"
+ "<span id='m11'>m11</span>"
+ "<span id='m12'>m12</span>" // #m12 is not distributed.
+ "</div>"
+ "<div id='m2'></div>";
+ const char* shadow_html =
+ "<content select='#m11'></content>"
+ "<a id='s11'>s11</a>"
+ "<a id='s12'>"
+ "<content select='#m10'></content>"
+ "</a>";
+ SetupSampleHTML(main_html, shadow_html, 1);
+
+ Element* body = GetDocument().body();
+ Element* m0 = body->QuerySelector("#m0");
+ Element* m1 = body->QuerySelector("#m1");
+ Element* m2 = body->QuerySelector("#m2");
+
+ Element* m10 = body->QuerySelector("#m10");
+
+ ShadowRoot* shadow_root = m1->OpenShadowRoot();
+ Element* s11 = shadow_root->QuerySelector("#s11");
+ Element* s12 = shadow_root->QuerySelector("#s12");
+
+ EXPECT_EQ(m0->firstChild(), FlatTreeTraversalNg::LastWithin(*m0));
+ EXPECT_EQ(*m0->firstChild(), FlatTreeTraversalNg::LastWithinOrSelf(*m0));
+
+ EXPECT_EQ(m10->firstChild(), FlatTreeTraversalNg::LastWithin(*m1));
+ EXPECT_EQ(*m10->firstChild(), FlatTreeTraversalNg::LastWithinOrSelf(*m1));
+
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::LastWithin(*m2));
+ EXPECT_EQ(*m2, FlatTreeTraversalNg::LastWithinOrSelf(*m2));
+
+ EXPECT_EQ(s11->firstChild(), FlatTreeTraversalNg::LastWithin(*s11));
+ EXPECT_EQ(*s11->firstChild(), FlatTreeTraversalNg::LastWithinOrSelf(*s11));
+
+ EXPECT_EQ(m10->firstChild(), FlatTreeTraversalNg::LastWithin(*s12));
+ EXPECT_EQ(*m10->firstChild(), FlatTreeTraversalNg::LastWithinOrSelf(*s12));
+}
+
+TEST_F(FlatTreeTraversalNgTest, previousPostOrder) {
+ const char* main_html =
+ "<div id='m0'>m0</div>"
+ "<div id='m1'>"
+ "<span id='m10'>m10</span>"
+ "<span id='m11'>m11</span>"
+ "</div>"
+ "<div id='m2'>m2</div>";
+ const char* shadow_html =
+ "<content select='#m11'></content>"
+ "<a id='s11'>s11</a>"
+ "<a id='s12'>"
+ "<b id='s120'>s120</b>"
+ "<content select='#m10'></content>"
+ "</a>";
+ SetupSampleHTML(main_html, shadow_html, 1);
+
+ Element* body = GetDocument().body();
+ Element* m0 = body->QuerySelector("#m0");
+ Element* m1 = body->QuerySelector("#m1");
+ Element* m2 = body->QuerySelector("#m2");
+
+ Element* m10 = body->QuerySelector("#m10");
+ Element* m11 = body->QuerySelector("#m11");
+
+ ShadowRoot* shadow_root = m1->OpenShadowRoot();
+ Element* s11 = shadow_root->QuerySelector("#s11");
+ Element* s12 = shadow_root->QuerySelector("#s12");
+ Element* s120 = shadow_root->QuerySelector("#s120");
+
+ EXPECT_EQ(*m0->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*m0));
+ EXPECT_EQ(*s12, FlatTreeTraversalNg::PreviousPostOrder(*m1));
+ EXPECT_EQ(*m10->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*m10));
+ EXPECT_EQ(*s120, FlatTreeTraversalNg::PreviousPostOrder(*m10->firstChild()));
+ EXPECT_EQ(*s120,
+ FlatTreeTraversalNg::PreviousPostOrder(*m10->firstChild(), s12));
+ EXPECT_EQ(*m11->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*m11));
+ EXPECT_EQ(*m0, FlatTreeTraversalNg::PreviousPostOrder(*m11->firstChild()));
+ EXPECT_EQ(nullptr,
+ FlatTreeTraversalNg::PreviousPostOrder(*m11->firstChild(), m11));
+ EXPECT_EQ(*m2->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*m2));
+
+ EXPECT_EQ(*s11->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*s11));
+ EXPECT_EQ(*m10, FlatTreeTraversalNg::PreviousPostOrder(*s12));
+ EXPECT_EQ(*s120->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*s120));
+ EXPECT_EQ(*s11, FlatTreeTraversalNg::PreviousPostOrder(*s120->firstChild()));
+ EXPECT_EQ(nullptr,
+ FlatTreeTraversalNg::PreviousPostOrder(*s120->firstChild(), s12));
+}
+
+TEST_F(FlatTreeTraversalNgTest, nextSiblingNotInDocumentFlatTree) {
+ const char* main_html =
+ "<div id='m0'>m0</div>"
+ "<div id='m1'>"
+ "<span id='m10'>m10</span>"
+ "<span id='m11'>m11</span>"
+ "</div>"
+ "<div id='m2'>m2</div>";
+ const char* shadow_html = "<content select='#m11'></content>";
+ SetupSampleHTML(main_html, shadow_html, 1);
+
+ Element* body = GetDocument().body();
+ Element* m10 = body->QuerySelector("#m10");
+
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*m10));
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*m10));
+}
+
+TEST_F(FlatTreeTraversalNgTest, redistribution) {
+ const char* main_html =
+ "<div id='m0'>m0</div>"
+ "<div id='m1'>"
+ "<span id='m10'>m10</span>"
+ "<span id='m11'>m11</span>"
+ "</div>"
+ "<div id='m2'>m2</div>";
+ const char* shadow_html1 =
+ "<div id='s1'>"
+ "<content></content>"
+ "</div>";
+
+ SetupSampleHTML(main_html, shadow_html1, 1);
+
+ const char* shadow_html2 =
+ "<div id='s2'>"
+ "<content select='#m10'></content>"
+ "<span id='s21'>s21</span>"
+ "</div>";
+
+ Element* body = GetDocument().body();
+ Element* m1 = body->QuerySelector("#m1");
+ Element* m10 = body->QuerySelector("#m10");
+
+ ShadowRoot* shadow_root1 = m1->OpenShadowRoot();
+ Element* s1 = shadow_root1->QuerySelector("#s1");
+
+ AttachV0ShadowRoot(*s1, shadow_html2);
+
+ ShadowRoot* shadow_root2 = s1->OpenShadowRoot();
+ Element* s21 = shadow_root2->QuerySelector("#s21");
+
+ EXPECT_EQ(s21, FlatTreeTraversalNg::NextSibling(*m10));
+ EXPECT_EQ(m10, FlatTreeTraversalNg::PreviousSibling(*s21));
+
+ // FlatTreeTraversalNg::traverseSiblings does not work for a node which is not
+ // in a document flat tree.
+ // e.g. The following test fails. The result of
+ // FlatTreeTraversalNg::previousSibling(*m11)) will be #m10, instead of
+ // nullptr. Element* m11 = body->querySelector("#m11"); EXPECT_EQ(nullptr,
+ // FlatTreeTraversalNg::previousSibling(*m11));
+}
+
+TEST_F(FlatTreeTraversalNgTest, v1Simple) {
+ const char* main_html =
+ "<div id='host'>"
+ "<div id='child1' slot='slot1'></div>"
+ "<div id='child2' slot='slot2'></div>"
+ "</div>";
+ const char* shadow_html =
+ "<div id='shadow-child1'></div>"
+ "<slot name='slot1'></slot>"
+ "<slot name='slot2'></slot>"
+ "<div id='shadow-child2'></div>";
+
+ SetupDocumentTree(main_html);
+ Element* body = GetDocument().body();
+ Element* host = body->QuerySelector("#host");
+ Element* child1 = body->QuerySelector("#child1");
+ Element* child2 = body->QuerySelector("#child2");
+
+ AttachOpenShadowRoot(*host, shadow_html);
+ ShadowRoot* shadow_root = host->OpenShadowRoot();
+ Element* slot1 = shadow_root->QuerySelector("[name=slot1]");
+ Element* slot2 = shadow_root->QuerySelector("[name=slot2]");
+ Element* shadow_child1 = shadow_root->QuerySelector("#shadow-child1");
+ Element* shadow_child2 = shadow_root->QuerySelector("#shadow-child2");
+
+ EXPECT_TRUE(slot1);
+ EXPECT_TRUE(slot2);
+ EXPECT_EQ(shadow_child1, FlatTreeTraversalNg::FirstChild(*host));
+ EXPECT_EQ(slot1, FlatTreeTraversalNg::NextSibling(*shadow_child1));
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*child1));
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*child2));
+ EXPECT_EQ(slot2, FlatTreeTraversalNg::NextSibling(*slot1));
+ EXPECT_EQ(shadow_child2, FlatTreeTraversalNg::NextSibling(*slot2));
+}
+
+TEST_F(FlatTreeTraversalNgTest, v1Redistribution) {
+ // composed tree:
+ // d1
+ // ├──/shadow-root
+ // │ └── d1-1
+ // │ ├──/shadow-root
+ // │ │ ├── d1-1-1
+ // │ │ ├── slot name=d1-1-s1
+ // │ │ ├── slot name=d1-1-s2
+ // │ │ └── d1-1-2
+ // │ ├── d1-2
+ // │ ├── slot id=d1-s0
+ // │ ├── slot name=d1-s1 slot=d1-1-s1
+ // │ ├── slot name=d1-s2
+ // │ ├── d1-3
+ // │ └── d1-4 slot=d1-1-s1
+ // ├── d2 slot=d1-s1
+ // ├── d3 slot=d1-s2
+ // ├── d4 slot=nonexistent
+ // └── d5
+
+ // flat tree:
+ // d1
+ // └── d1-1
+ // ├── d1-1-1
+ // ├── slot name=d1-1-s1
+ // │ ├── slot name=d1-s1 slot=d1-1-s1
+ // │ │ └── d2 slot=d1-s1
+ // │ └── d1-4 slot=d1-1-s1
+ // ├── slot name=d1-1-s2
+ // └── d1-1-2
+ const char* main_html =
+ "<div id='d1'>"
+ "<div id='d2' slot='d1-s1'></div>"
+ "<div id='d3' slot='d1-s2'></div>"
+ "<div id='d4' slot='nonexistent'></div>"
+ "<div id='d5'></div>"
+ "</div>"
+ "<div id='d6'></div>";
+ const char* shadow_html1 =
+ "<div id='d1-1'>"
+ "<div id='d1-2'></div>"
+ "<slot id='d1-s0'></slot>"
+ "<slot name='d1-s1' slot='d1-1-s1'></slot>"
+ "<slot name='d1-s2'></slot>"
+ "<div id='d1-3'></div>"
+ "<div id='d1-4' slot='d1-1-s1'></div>"
+ "</div>";
+ const char* shadow_html2 =
+ "<div id='d1-1-1'></div>"
+ "<slot name='d1-1-s1'></slot>"
+ "<slot name='d1-1-s2'></slot>"
+ "<div id='d1-1-2'></div>";
+
+ SetupDocumentTree(main_html);
+
+ Element* body = GetDocument().body();
+ Element* d1 = body->QuerySelector("#d1");
+ Element* d2 = body->QuerySelector("#d2");
+ Element* d3 = body->QuerySelector("#d3");
+ Element* d4 = body->QuerySelector("#d4");
+ Element* d5 = body->QuerySelector("#d5");
+ Element* d6 = body->QuerySelector("#d6");
+
+ AttachOpenShadowRoot(*d1, shadow_html1);
+ ShadowRoot* shadow_root1 = d1->OpenShadowRoot();
+ Element* d11 = shadow_root1->QuerySelector("#d1-1");
+ Element* d12 = shadow_root1->QuerySelector("#d1-2");
+ Element* d13 = shadow_root1->QuerySelector("#d1-3");
+ Element* d14 = shadow_root1->QuerySelector("#d1-4");
+ Element* d1s0 = shadow_root1->QuerySelector("#d1-s0");
+ Element* d1s1 = shadow_root1->QuerySelector("[name=d1-s1]");
+ Element* d1s2 = shadow_root1->QuerySelector("[name=d1-s2]");
+
+ AttachOpenShadowRoot(*d11, shadow_html2);
+ ShadowRoot* shadow_root2 = d11->OpenShadowRoot();
+ Element* d111 = shadow_root2->QuerySelector("#d1-1-1");
+ Element* d112 = shadow_root2->QuerySelector("#d1-1-2");
+ Element* d11s1 = shadow_root2->QuerySelector("[name=d1-1-s1]");
+ Element* d11s2 = shadow_root2->QuerySelector("[name=d1-1-s2]");
+
+ EXPECT_TRUE(d5);
+ EXPECT_TRUE(d12);
+ EXPECT_TRUE(d13);
+ EXPECT_TRUE(d1s0);
+ EXPECT_TRUE(d1s1);
+ EXPECT_TRUE(d1s2);
+ EXPECT_TRUE(d11s1);
+ EXPECT_TRUE(d11s2);
+
+ EXPECT_EQ(d11, FlatTreeTraversalNg::Next(*d1));
+ EXPECT_EQ(d111, FlatTreeTraversalNg::Next(*d11));
+ EXPECT_EQ(d11s1, FlatTreeTraversalNg::Next(*d111));
+ EXPECT_EQ(d1s1, FlatTreeTraversalNg::Next(*d11s1));
+ EXPECT_EQ(d2, FlatTreeTraversalNg::Next(*d1s1));
+ EXPECT_EQ(d14, FlatTreeTraversalNg::Next(*d2));
+ EXPECT_EQ(d11s2, FlatTreeTraversalNg::Next(*d14));
+ EXPECT_EQ(d112, FlatTreeTraversalNg::Next(*d11s2));
+ EXPECT_EQ(d6, FlatTreeTraversalNg::Next(*d112));
+
+ EXPECT_EQ(d112, FlatTreeTraversalNg::Previous(*d6));
+
+ EXPECT_EQ(d11, FlatTreeTraversalNg::Parent(*d111));
+ EXPECT_EQ(d11, FlatTreeTraversalNg::Parent(*d112));
+ EXPECT_EQ(d1s1, FlatTreeTraversalNg::Parent(*d2));
+ EXPECT_EQ(d11s1, FlatTreeTraversalNg::Parent(*d14));
+ EXPECT_EQ(d1s2, FlatTreeTraversalNg::Parent(*d3));
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::Parent(*d4));
+}
+
+TEST_F(FlatTreeTraversalNgTest, v1SlotInDocumentTree) {
+ const char* main_html =
+ "<div id='parent'>"
+ "<slot>"
+ "<div id='child1'></div>"
+ "<div id='child2'></div>"
+ "</slot>"
+ "</div>";
+
+ SetupDocumentTree(main_html);
+ Element* body = GetDocument().body();
+ Element* parent = body->QuerySelector("#parent");
+ Element* slot = body->QuerySelector("slot");
+ Element* child1 = body->QuerySelector("#child1");
+ Element* child2 = body->QuerySelector("#child2");
+
+ EXPECT_EQ(slot, FlatTreeTraversalNg::FirstChild(*parent));
+ EXPECT_EQ(child1, FlatTreeTraversalNg::FirstChild(*slot));
+ EXPECT_EQ(child2, FlatTreeTraversalNg::NextSibling(*child1));
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*child2));
+ EXPECT_EQ(slot, FlatTreeTraversalNg::Parent(*child1));
+ EXPECT_EQ(slot, FlatTreeTraversalNg::Parent(*child2));
+ EXPECT_EQ(parent, FlatTreeTraversalNg::Parent(*slot));
+}
+
+TEST_F(FlatTreeTraversalNgTest, v1FallbackContent) {
+ const char* main_html = "<div id='d1'></div>";
+ const char* shadow_html =
+ "<div id='before'></div>"
+ "<slot><p>fallback content</p></slot>"
+ "<div id='after'></div>";
+
+ SetupDocumentTree(main_html);
+
+ Element* body = GetDocument().body();
+ Element* d1 = body->QuerySelector("#d1");
+
+ AttachOpenShadowRoot(*d1, shadow_html);
+ ShadowRoot* shadow_root = d1->OpenShadowRoot();
+ Element* before = shadow_root->QuerySelector("#before");
+ Element* after = shadow_root->QuerySelector("#after");
+ Element* fallback_content = shadow_root->QuerySelector("p");
+ Element* slot = shadow_root->QuerySelector("slot");
+
+ EXPECT_EQ(before, FlatTreeTraversalNg::FirstChild(*d1));
+ EXPECT_EQ(after, FlatTreeTraversalNg::LastChild(*d1));
+ EXPECT_EQ(slot, FlatTreeTraversalNg::Parent(*fallback_content));
+
+ EXPECT_EQ(slot, FlatTreeTraversalNg::NextSibling(*before));
+ EXPECT_EQ(after, FlatTreeTraversalNg::NextSibling(*slot));
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_content));
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*after));
+
+ EXPECT_EQ(slot, FlatTreeTraversalNg::PreviousSibling(*after));
+ EXPECT_EQ(before, FlatTreeTraversalNg::PreviousSibling(*slot));
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_content));
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*before));
+}
+
+TEST_F(FlatTreeTraversalNgTest, v1FallbackContentSkippedInTraversal) {
+ const char* main_html = "<div id='d1'><span></span></div>";
+ const char* shadow_html =
+ "<div id='before'></div>"
+ "<slot><p>fallback content</p></slot>"
+ "<div id='after'></div>";
+
+ SetupDocumentTree(main_html);
+
+ Element* body = GetDocument().body();
+ Element* d1 = body->QuerySelector("#d1");
+ Element* span = body->QuerySelector("span");
+
+ AttachOpenShadowRoot(*d1, shadow_html);
+ ShadowRoot* shadow_root = d1->OpenShadowRoot();
+ Element* before = shadow_root->QuerySelector("#before");
+ Element* after = shadow_root->QuerySelector("#after");
+ Element* fallback_content = shadow_root->QuerySelector("p");
+ Element* slot = shadow_root->QuerySelector("slot");
+
+ EXPECT_EQ(before, FlatTreeTraversalNg::FirstChild(*d1));
+ EXPECT_EQ(after, FlatTreeTraversalNg::LastChild(*d1));
+ EXPECT_EQ(slot, FlatTreeTraversalNg::Parent(*span));
+ EXPECT_EQ(d1, FlatTreeTraversalNg::Parent(*slot));
+
+ EXPECT_EQ(slot, FlatTreeTraversalNg::NextSibling(*before));
+ EXPECT_EQ(after, FlatTreeTraversalNg::NextSibling(*slot));
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*after));
+
+ EXPECT_EQ(slot, FlatTreeTraversalNg::PreviousSibling(*after));
+ EXPECT_EQ(before, FlatTreeTraversalNg::PreviousSibling(*slot));
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*before));
+
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::Parent(*fallback_content));
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_content));
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_content));
+}
+
+TEST_F(FlatTreeTraversalNgTest, v1AllFallbackContent) {
+ const char* main_html = "<div id='d1'></div>";
+ const char* shadow_html =
+ "<slot name='a'><p id='x'>fallback content X</p></slot>"
+ "<slot name='b'><p id='y'>fallback content Y</p></slot>"
+ "<slot name='c'><p id='z'>fallback content Z</p></slot>";
+
+ SetupDocumentTree(main_html);
+
+ Element* body = GetDocument().body();
+ Element* d1 = body->QuerySelector("#d1");
+
+ AttachOpenShadowRoot(*d1, shadow_html);
+ ShadowRoot* shadow_root = d1->OpenShadowRoot();
+ Element* slot_a = shadow_root->QuerySelector("slot[name=a]");
+ Element* slot_b = shadow_root->QuerySelector("slot[name=b]");
+ Element* slot_c = shadow_root->QuerySelector("slot[name=c]");
+ Element* fallback_x = shadow_root->QuerySelector("#x");
+ Element* fallback_y = shadow_root->QuerySelector("#y");
+ Element* fallback_z = shadow_root->QuerySelector("#z");
+
+ EXPECT_EQ(slot_a, FlatTreeTraversalNg::FirstChild(*d1));
+ EXPECT_EQ(slot_c, FlatTreeTraversalNg::LastChild(*d1));
+
+ EXPECT_EQ(fallback_x, FlatTreeTraversalNg::FirstChild(*slot_a));
+ EXPECT_EQ(fallback_y, FlatTreeTraversalNg::FirstChild(*slot_b));
+ EXPECT_EQ(fallback_z, FlatTreeTraversalNg::FirstChild(*slot_c));
+
+ EXPECT_EQ(slot_a, FlatTreeTraversalNg::Parent(*fallback_x));
+ EXPECT_EQ(slot_b, FlatTreeTraversalNg::Parent(*fallback_y));
+ EXPECT_EQ(slot_c, FlatTreeTraversalNg::Parent(*fallback_z));
+ EXPECT_EQ(d1, FlatTreeTraversalNg::Parent(*slot_a));
+
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_x));
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_y));
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_z));
+
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_z));
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_y));
+ EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_x));
+}
+
+} // namespace flat_tree_traversal_ng_test
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_test.cc b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_test.cc
index 545b93b3f9d..517360e43db 100644
--- a/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/flat_tree_traversal_test.cc
@@ -6,7 +6,6 @@
#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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.h"
@@ -15,6 +14,7 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.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/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/compiler.h"
diff --git a/chromium/third_party/blink/renderer/core/dom/frame_request_callback_collection.cc b/chromium/third_party/blink/renderer/core/dom/frame_request_callback_collection.cc
index 7d515722c57..3923e0b289a 100644
--- a/chromium/third_party/blink/renderer/core/dom/frame_request_callback_collection.cc
+++ b/chromium/third_party/blink/renderer/core/dom/frame_request_callback_collection.cc
@@ -86,14 +86,6 @@ void FrameRequestCallbackCollection::Trace(blink::Visitor* visitor) {
visitor->Trace(context_);
}
-void FrameRequestCallbackCollection::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- for (const auto& callback : callbacks_)
- visitor->TraceWrappers(callback);
- for (const auto& callback_to_invoke : callbacks_to_invoke_)
- visitor->TraceWrappers(callback_to_invoke);
-}
-
FrameRequestCallbackCollection::V8FrameCallback::V8FrameCallback(
V8FrameRequestCallback* callback)
: callback_(callback) {}
@@ -104,12 +96,6 @@ void FrameRequestCallbackCollection::V8FrameCallback::Trace(
FrameRequestCallbackCollection::FrameCallback::Trace(visitor);
}
-void FrameRequestCallbackCollection::V8FrameCallback::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(callback_);
- FrameRequestCallbackCollection::FrameCallback::TraceWrappers(visitor);
-}
-
void FrameRequestCallbackCollection::V8FrameCallback::Invoke(
double highResTime) {
callback_->InvokeAndReportException(nullptr, highResTime);
diff --git a/chromium/third_party/blink/renderer/core/dom/frame_request_callback_collection.h b/chromium/third_party/blink/renderer/core/dom/frame_request_callback_collection.h
index 37c568b7982..0aca9b30f38 100644
--- a/chromium/third_party/blink/renderer/core/dom/frame_request_callback_collection.h
+++ b/chromium/third_party/blink/renderer/core/dom/frame_request_callback_collection.h
@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_frame_request_callback.h"
#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/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -15,8 +16,8 @@ namespace blink {
class ExecutionContext;
-class CORE_EXPORT FrameRequestCallbackCollection final
- : public TraceWrapperBase {
+class GC_PLUGIN_IGNORE("crbug.com/841830")
+ CORE_EXPORT FrameRequestCallbackCollection final : public NameClient {
DISALLOW_NEW();
public:
@@ -28,10 +29,9 @@ class CORE_EXPORT FrameRequestCallbackCollection final
// invoked when a script-based animation needs to be resampled.
class CORE_EXPORT FrameCallback
: public GarbageCollectedFinalized<FrameCallback>,
- public TraceWrapperBase {
+ public NameClient {
public:
virtual void Trace(blink::Visitor* visitor) {}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {}
const char* NameInHeapSnapshot() const override { return "FrameCallback"; }
virtual ~FrameCallback() = default;
virtual void Invoke(double) = 0;
@@ -62,7 +62,6 @@ class CORE_EXPORT FrameRequestCallbackCollection final
return new V8FrameCallback(callback);
}
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "V8FrameCallback";
}
@@ -81,7 +80,6 @@ class CORE_EXPORT FrameRequestCallbackCollection final
bool IsEmpty() const { return !callbacks_.size(); }
void Trace(blink::Visitor*);
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "FrameRequestCallbackCollection";
}
diff --git a/chromium/third_party/blink/renderer/core/dom/idle_deadline.cc b/chromium/third_party/blink/renderer/core/dom/idle_deadline.cc
index 371bd32be33..a30fe7c2767 100644
--- a/chromium/third_party/blink/renderer/core/dom/idle_deadline.cc
+++ b/chromium/third_party/blink/renderer/core/dom/idle_deadline.cc
@@ -11,21 +11,19 @@
namespace blink {
-IdleDeadline::IdleDeadline(double deadline_seconds, CallbackType callback_type)
- : deadline_seconds_(deadline_seconds), callback_type_(callback_type) {}
+IdleDeadline::IdleDeadline(TimeTicks deadline, CallbackType callback_type)
+ : deadline_(deadline), callback_type_(callback_type) {}
double IdleDeadline::timeRemaining() const {
- double time_remaining = deadline_seconds_ - CurrentTimeTicksInSeconds();
- if (time_remaining < 0) {
- return 0;
- } else if (Platform::Current()
- ->CurrentThread()
- ->Scheduler()
- ->ShouldYieldForHighPriorityWork()) {
+ TimeDelta time_remaining = deadline_ - CurrentTimeTicks();
+ if (time_remaining < TimeDelta() || Platform::Current()
+ ->CurrentThread()
+ ->Scheduler()
+ ->ShouldYieldForHighPriorityWork()) {
return 0;
}
- return 1000.0 * Performance::ClampTimeResolution(time_remaining);
+ return 1000.0 * Performance::ClampTimeResolution(time_remaining.InSecondsF());
}
} // namespace blink
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 a38c089d1fc..59c37cd7593 100644
--- a/chromium/third_party/blink/renderer/core/dom/idle_deadline.h
+++ b/chromium/third_party/blink/renderer/core/dom/idle_deadline.h
@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#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/wtf/time.h"
namespace blink {
@@ -17,9 +18,8 @@ class CORE_EXPORT IdleDeadline : public ScriptWrappable {
public:
enum class CallbackType { kCalledWhenIdle, kCalledByTimeout };
- static IdleDeadline* Create(double deadline_seconds,
- CallbackType callback_type) {
- return new IdleDeadline(deadline_seconds, callback_type);
+ static IdleDeadline* Create(TimeTicks deadline, CallbackType callback_type) {
+ return new IdleDeadline(deadline, callback_type);
}
double timeRemaining() const;
@@ -29,9 +29,9 @@ class CORE_EXPORT IdleDeadline : public ScriptWrappable {
}
private:
- IdleDeadline(double deadline_seconds, CallbackType);
+ IdleDeadline(TimeTicks deadline, CallbackType);
- double deadline_seconds_;
+ TimeTicks deadline_;
CallbackType callback_type_;
};
diff --git a/chromium/third_party/blink/renderer/core/dom/idle_deadline_test.cc b/chromium/third_party/blink/renderer/core/dom/idle_deadline_test.cc
index fbf1add7a9f..1759da148c5 100644
--- a/chromium/third_party/blink/renderer/core/dom/idle_deadline_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/idle_deadline_test.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h"
+#include "third_party/blink/renderer/platform/testing/wtf/scoped_mock_clock.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink {
@@ -50,7 +51,10 @@ class MockIdleDeadlineScheduler final : public ThreadScheduler {
void RemoveTaskObserver(
base::MessageLoop::TaskObserver* task_observer) override {}
- scheduler::NonMainThreadScheduler* AsNonMainThreadScheduler() override {
+ void AddRAILModeObserver(
+ scheduler::WebThreadScheduler::RAILModeObserver*) override {}
+
+ scheduler::NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() override {
return nullptr;
}
@@ -85,28 +89,24 @@ class MockIdleDeadlinePlatform : public TestingPlatformSupport {
class IdleDeadlineTest : public testing::Test {
public:
- void SetUp() override {
- original_time_function_ = SetTimeFunctionsForTesting([] { return 1.0; });
- }
-
- void TearDown() override {
- SetTimeFunctionsForTesting(original_time_function_);
- }
+ void SetUp() override { clock_.Advance(TimeDelta::FromSeconds(1)); }
private:
- TimeFunction original_time_function_;
+ WTF::ScopedMockClock clock_;
};
TEST_F(IdleDeadlineTest, deadlineInFuture) {
IdleDeadline* deadline =
- IdleDeadline::Create(1.25, IdleDeadline::CallbackType::kCalledWhenIdle);
+ IdleDeadline::Create(TimeTicks() + TimeDelta::FromSecondsD(1.25),
+ IdleDeadline::CallbackType::kCalledWhenIdle);
// Note: the deadline is computed with reduced resolution.
EXPECT_FLOAT_EQ(250.0, deadline->timeRemaining());
}
TEST_F(IdleDeadlineTest, deadlineInPast) {
IdleDeadline* deadline =
- IdleDeadline::Create(0.75, IdleDeadline::CallbackType::kCalledWhenIdle);
+ IdleDeadline::Create(TimeTicks() + TimeDelta::FromSecondsD(0.75),
+ IdleDeadline::CallbackType::kCalledWhenIdle);
EXPECT_FLOAT_EQ(0, deadline->timeRemaining());
}
@@ -114,7 +114,8 @@ TEST_F(IdleDeadlineTest, yieldForHighPriorityWork) {
ScopedTestingPlatformSupport<MockIdleDeadlinePlatform> platform;
IdleDeadline* deadline =
- IdleDeadline::Create(1.25, IdleDeadline::CallbackType::kCalledWhenIdle);
+ IdleDeadline::Create(TimeTicks() + TimeDelta::FromSecondsD(1.25),
+ IdleDeadline::CallbackType::kCalledWhenIdle);
EXPECT_FLOAT_EQ(0, deadline->timeRemaining());
}
diff --git a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.cc b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.cc
index 643edb380c7..e7ac71fa579 100644
--- a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.cc
+++ b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.cc
@@ -27,15 +27,17 @@
#include "third_party/blink/renderer/core/dom/layout_tree_builder.h"
+#include <algorithm>
#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/dom/first_letter_pseudo_element.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/pseudo_element.h"
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/dom/v0_insertion_point.h"
-#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
+#include "third_party/blink/renderer/core/dom/whitespace_attacher.h"
#include "third_party/blink/renderer/core/html_names.h"
-#include "third_party/blink/renderer/core/layout/layout_full_screen.h"
+#include "third_party/blink/renderer/core/layout/generated_children.h"
#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_text.h"
@@ -45,6 +47,31 @@
namespace blink {
+namespace {
+
+// Returns a layout object containing |start| establishes block formatting
+// context or a layout object associated to document element, or null if
+// no such layout object.
+const LayoutObject* FindBlockFormattingContext(const LayoutObject& start) {
+ const LayoutObject* candidate = nullptr;
+ for (const LayoutObject* runner = &start; runner; runner = runner->Parent()) {
+ if (!runner->GetNode() || !runner->GetNode()->IsElementNode())
+ continue;
+ candidate = runner;
+ if (!runner->IsLayoutBlock())
+ continue;
+ const LayoutBlock& block = ToLayoutBlock(*runner);
+ if (block.CreatesNewFormattingContext())
+ return &block;
+ }
+ // Note: Returns the highest layout object associated to element.
+ // For "append-node-under-document.html", |candidate| is |LayoutIFrame| and
+ // document element is IFRAME.
+ return candidate;
+}
+
+} // namespace
+
LayoutTreeBuilderForElement::LayoutTreeBuilderForElement(Element& element,
ComputedStyle* style)
: LayoutTreeBuilder(element, nullptr), style_(style) {
@@ -96,12 +123,17 @@ bool LayoutTreeBuilderForElement::ShouldCreateLayoutObject() const {
return false;
if (!parent_layout_object->CanHaveChildren())
return false;
+ if (node_->IsPseudoElement() &&
+ !CanHaveGeneratedChildren(*parent_layout_object)) {
+ return false;
+ }
return node_->LayoutObjectIsNeeded(Style());
}
ComputedStyle& LayoutTreeBuilderForElement::Style() const {
if (!style_) {
DCHECK(!node_->GetNonAttachedStyle());
+ DCHECK(node_->IsFirstLetterPseudoElement());
style_ = node_->StyleForLayoutObject();
}
return *style_;
@@ -110,7 +142,12 @@ ComputedStyle& LayoutTreeBuilderForElement::Style() const {
DISABLE_CFI_PERF
void LayoutTreeBuilderForElement::CreateLayoutObject() {
ComputedStyle& style = Style();
-
+ ReattachLegacyLayoutObjectList& legacy_layout_objects =
+ node_->GetDocument().GetReattachLegacyLayoutObjectList();
+ if (legacy_layout_objects.IsForcingLegacyLayout()) {
+ DCHECK(!node_->GetLayoutObject());
+ style.SetForceLegacyLayout(true);
+ }
LayoutObject* new_layout_object = node_->CreateLayoutObject(style);
if (!new_layout_object)
return;
@@ -134,18 +171,12 @@ void LayoutTreeBuilderForElement::CreateLayoutObject() {
new_layout_object->SetStyle(
&style); // SetStyle() can depend on LayoutObject() already being set.
- Document& document = node_->GetDocument();
- if (Fullscreen::IsFullscreenElement(*node_) &&
- node_.Get() != document.documentElement()) {
- new_layout_object = LayoutFullScreen::WrapLayoutObject(
- new_layout_object, parent_layout_object, &document);
- if (!new_layout_object)
- return;
- }
-
// Note: Adding new_layout_object instead of LayoutObject(). LayoutObject()
// may be a child of new_layout_object.
parent_layout_object->AddChild(new_layout_object, next_layout_object);
+ if (!legacy_layout_objects.IsCollecting())
+ return;
+ legacy_layout_objects.AddForceLegacyAtBFCAncestor(*new_layout_object);
}
LayoutObject*
@@ -204,4 +235,101 @@ void LayoutTreeBuilderForText::CreateLayoutObject() {
layout_object_parent_->AddChild(new_layout_object, next_layout_object);
}
+// ----
+ReattachLegacyLayoutObjectList::ReattachLegacyLayoutObjectList(
+ Document& document)
+ : document_(document),
+ state_(RuntimeEnabledFeatures::LayoutNGEnabled()
+ ? State::kCollecting
+ : State::kBuildingLegacyLayoutTree) {
+ DCHECK(!document_->reattach_legacy_object_list_);
+ document_->reattach_legacy_object_list_ = this;
+}
+
+ReattachLegacyLayoutObjectList::~ReattachLegacyLayoutObjectList() {
+ DCHECK_EQ(document_->reattach_legacy_object_list_, this);
+ DCHECK_EQ(state_, State::kClosed);
+ document_->reattach_legacy_object_list_ = nullptr;
+}
+
+void ReattachLegacyLayoutObjectList::AddForceLegacyAtBFCAncestor(
+ const LayoutObject& start) {
+ DCHECK(IsCollecting()) << static_cast<int>(state_);
+ if (!start.Style()->ForceLegacyLayout())
+ return;
+ if (start.Parent()->Style()->ForceLegacyLayout()) {
+ // BFC root of |start| is already in the list.
+ return;
+ }
+ const LayoutObject* const bfc = FindBlockFormattingContext(start);
+ if (start == bfc)
+ return;
+ DCHECK(bfc) << start;
+ if (std::any_of(blocks_.begin(), blocks_.end(),
+ [bfc](const LayoutObject* object) {
+ return bfc == object ||
+ bfc->GetNode()->IsDescendantOf(object->GetNode());
+ }))
+ return;
+ auto** itr = std::remove_if(
+ blocks_.begin(), blocks_.end(), [bfc](const LayoutObject* object) {
+ return object->GetNode()->IsDescendantOf(bfc->GetNode());
+ });
+ blocks_.resize(std::distance(blocks_.begin(), itr));
+ // Mark BFC root is added into the list.
+ bfc->MutableStyle()->SetForceLegacyLayout(true);
+ blocks_.push_back(bfc);
+}
+
+bool ReattachLegacyLayoutObjectList::IsCollecting() const {
+ return state_ == State::kCollecting || state_ == State::kRecalcStyle;
+}
+
+void ReattachLegacyLayoutObjectList::ForceLegacyLayoutIfNeeded() {
+ const State state = state_;
+ state_ = State::kClosed;
+ if (state == State::kBuildingLegacyLayoutTree)
+ return;
+ DCHECK_EQ(state, State::kCollecting);
+ if (blocks_.IsEmpty())
+ return;
+ for (const LayoutObject* block : blocks_)
+ ToElement(*block->GetNode()).LazyReattachIfAttached();
+ state_ = State::kForcingLegacyLayout;
+ Element& document_element = *document_->documentElement();
+ document_element.RecalcStyle(kNoChange);
+ WhitespaceAttacher whitespace_attacher;
+ document_element.RebuildLayoutTree(whitespace_attacher);
+ state_ = State::kClosed;
+}
+
+void ReattachLegacyLayoutObjectList::DidRecalcStyle() {
+ const State state = state_;
+ state_ = State::kClosed;
+ if (state == State::kBuildingLegacyLayoutTree)
+ return;
+ DCHECK_EQ(state, State::kRecalcStyle);
+ for (const LayoutObject* block : blocks_)
+ ToElement(*block->GetNode()).LazyReattachIfAttached();
+}
+
+void ReattachLegacyLayoutObjectList::WillRecalcStyle() {
+ // TODO(layout-dev): Once make |RecalcStyle()| not to create layout object,
+ // we don't need to have |WillRecalcStyle()| and |DidRecalcStyle()|.
+ // Note: "first-letter-removed-added.html" creates layout object during
+ // style recalc. See http://crbug.com/847218
+ if (state_ == State::kBuildingLegacyLayoutTree)
+ return;
+ state_ = State::kRecalcStyle;
+}
+
+void ReattachLegacyLayoutObjectList::Trace(blink::Visitor* visitor) {
+ visitor->Trace(document_);
+}
+
+ReattachLegacyLayoutObjectList& Document::GetReattachLegacyLayoutObjectList() {
+ DCHECK(reattach_legacy_object_list_);
+ return *reattach_legacy_object_list_;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.h b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.h
index 27eec47747b..a3e30b2cd03 100644
--- a/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.h
+++ b/chromium/third_party/blink/renderer/core/dom/layout_tree_builder.h
@@ -29,11 +29,13 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_LAYOUT_TREE_BUILDER_H_
#include "base/memory/scoped_refptr.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/dom/layout_tree_builder_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/layout/layout_object.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -130,6 +132,61 @@ class LayoutTreeBuilderForText : public LayoutTreeBuilder<Text> {
scoped_refptr<ComputedStyle> style_;
};
+// Replaces LayoutNG objects to legacy layout objects when corresponding element
+// returns true for |ShouldForceLegacyLayout()|.
+//
+// This replacement is done by three phases:
+// 1. Collects layout objects establish block formatting context(BFC) and
+// contain at least one layout object should be legacy layout.
+// 2. Marks descendant LayoutNG objects of collected layout objects to
+// |NeedsReattachLayoutTree|.
+// 3. Invokes |RebuildLayoutTree()| to replaces to legacy layout objects.
+//
+// See https://goo.gl/8s5h96 for more details.
+class CORE_EXPORT ReattachLegacyLayoutObjectList final {
+ // Note: Make GC-plugin happy, this object doesn't have |STACK_ALLOCATED()|.
+ DISALLOW_NEW();
+
+ public:
+ ReattachLegacyLayoutObjectList(Document&);
+ ~ReattachLegacyLayoutObjectList();
+
+ void AddForceLegacyAtBFCAncestor(const LayoutObject&);
+ bool IsCollecting() const;
+ bool IsForcingLegacyLayout() const {
+ return state_ == State::kForcingLegacyLayout;
+ }
+ void ForceLegacyLayoutIfNeeded();
+
+ void DidRecalcStyle();
+ void WillRecalcStyle();
+
+ void Trace(blink::Visitor*);
+
+ private:
+ Member<Document> document_;
+
+ // A list of block formatting context or layout object associated to
+ // document element.
+ Vector<const LayoutObject*> blocks_;
+
+ enum class State {
+ kInvalid,
+ // Building legacy layout tree
+ kBuildingLegacyLayoutTree,
+ // Usage of this list is finished.
+ kClosed,
+ // Collecting block formatting context should be legacy layout.
+ kCollecting,
+ // Replaces LayoutNG objects to legacy layout objects.
+ kForcingLegacyLayout,
+ // Doing style re-calculation.
+ kRecalcStyle,
+ } state_ = State::kInvalid;
+
+ DISALLOW_COPY_AND_ASSIGN(ReattachLegacyLayoutObjectList);
+};
+
} // namespace blink
#endif
diff --git a/chromium/third_party/blink/renderer/core/dom/live_node_list.cc b/chromium/third_party/blink/renderer/core/dom/live_node_list.cc
index 291b1a52b6d..4be5c8db964 100644
--- a/chromium/third_party/blink/renderer/core/dom/live_node_list.cc
+++ b/chromium/third_party/blink/renderer/core/dom/live_node_list.cc
@@ -22,6 +22,8 @@
#include "third_party/blink/renderer/core/dom/live_node_list.h"
+#include "third_party/blink/renderer/core/dom/node_child_removal_tracker.h"
+
namespace blink {
namespace {
@@ -55,7 +57,12 @@ unsigned LiveNodeList::length() const {
}
Element* LiveNodeList::item(unsigned offset) const {
- return collection_items_cache_.NodeAt(*this, offset);
+ Element* element = collection_items_cache_.NodeAt(*this, offset);
+ if (element && element->GetDocument().InDOMNodeRemovedHandler()) {
+ if (NodeChildRemovalTracker::IsBeingRemoved(element))
+ GetDocument().CountDetachingNodeAccessInDOMNodeRemovedHandler();
+ }
+ return element;
}
Element* LiveNodeList::TraverseToFirst() const {
diff --git a/chromium/third_party/blink/renderer/core/dom/mutation_observer.cc b/chromium/third_party/blink/renderer/core/dom/mutation_observer.cc
index 5cbcc65581f..a330c7b5bf2 100644
--- a/chromium/third_party/blink/renderer/core/dom/mutation_observer.cc
+++ b/chromium/third_party/blink/renderer/core/dom/mutation_observer.cc
@@ -32,9 +32,9 @@
#include <algorithm>
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_mutation_callback.h"
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/mutation_observer_init.h"
#include "third_party/blink/renderer/core/dom/mutation_observer_registration.h"
#include "third_party/blink/renderer/core/dom/mutation_record.h"
@@ -42,6 +42,7 @@
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/html/html_slot_element.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/microtask.h"
namespace blink {
@@ -74,11 +75,6 @@ class MutationObserver::V8DelegateImpl final
ContextClient::Trace(visitor);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- visitor->TraceWrappers(callback_);
- MutationObserver::Delegate::TraceWrappers(visitor);
- }
-
private:
V8DelegateImpl(V8MutationCallback* callback,
ExecutionContext* execution_context)
@@ -140,7 +136,7 @@ void MutationObserver::observe(Node* node,
if (attributes || (!observer_init.hasAttributes() &&
(observer_init.hasAttributeOldValue() ||
observer_init.hasAttributeFilter())))
- options |= kAttributes;
+ options |= kMutationTypeAttributes;
if (observer_init.hasCharacterDataOldValue() &&
observer_init.characterDataOldValue())
@@ -150,15 +146,15 @@ void MutationObserver::observe(Node* node,
observer_init.hasCharacterData() && observer_init.characterData();
if (character_data || (!observer_init.hasCharacterData() &&
observer_init.hasCharacterDataOldValue()))
- options |= kCharacterData;
+ options |= kMutationTypeCharacterData;
if (observer_init.childList())
- options |= kChildList;
+ options |= kMutationTypeChildList;
if (observer_init.subtree())
options |= kSubtree;
- if (!(options & kAttributes)) {
+ if (!(options & kMutationTypeAttributes)) {
if (options & kAttributeOldValue) {
exception_state.ThrowTypeError(
"The options object may only set 'attributeOldValue' to true when "
@@ -172,14 +168,15 @@ void MutationObserver::observe(Node* node,
return;
}
}
- if (!((options & kCharacterData) || !(options & kCharacterDataOldValue))) {
+ if (!((options & kMutationTypeCharacterData) ||
+ !(options & kCharacterDataOldValue))) {
exception_state.ThrowTypeError(
"The options object may only set 'characterDataOldValue' to true when "
"'characterData' is true or not present.");
return;
}
- if (!(options & (kAttributes | kCharacterData | kChildList))) {
+ if (!(options & kMutationTypeAll)) {
exception_state.ThrowTypeError(
"The options object must set at least one of 'attributes', "
"'characterData', or 'childList' to true.");
@@ -379,11 +376,4 @@ void MutationObserver::Trace(blink::Visitor* visitor) {
ContextClient::Trace(visitor);
}
-void MutationObserver::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(delegate_);
- for (auto record : records_)
- visitor->TraceWrappers(record);
- ScriptWrappable::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/mutation_observer.h b/chromium/third_party/blink/renderer/core/dom/mutation_observer.h
index a00e5a6ec1f..6b2c8ca210d 100644
--- a/chromium/third_party/blink/renderer/core/dom/mutation_observer.h
+++ b/chromium/third_party/blink/renderer/core/dom/mutation_observer.h
@@ -35,7 +35,9 @@
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/core/dom/mutation_observer_options.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -55,9 +57,6 @@ class Node;
class ScriptState;
class V8MutationCallback;
-typedef unsigned char MutationObserverOptions;
-typedef unsigned char MutationRecordDeliveryOptions;
-
using MutationObserverSet = HeapHashSet<Member<MutationObserver>>;
using MutationObserverRegistrationSet =
HeapHashSet<WeakMember<MutationObserverRegistration>>;
@@ -72,14 +71,6 @@ class CORE_EXPORT MutationObserver final
USING_GARBAGE_COLLECTED_MIXIN(MutationObserver);
public:
- enum MutationType {
- kChildList = 1 << 0,
- kAttributes = 1 << 1,
- kCharacterData = 1 << 2,
-
- kAllMutationTypes = kChildList | kAttributes | kCharacterData
- };
-
enum ObservationFlags { kSubtree = 1 << 3, kAttributeFilter = 1 << 4 };
enum DeliveryFlags {
@@ -88,14 +79,13 @@ class CORE_EXPORT MutationObserver final
};
class CORE_EXPORT Delegate : public GarbageCollectedFinalized<Delegate>,
- public TraceWrapperBase {
+ public NameClient {
public:
virtual ~Delegate() = default;
virtual ExecutionContext* GetExecutionContext() const = 0;
virtual void Deliver(const MutationRecordVector& records,
MutationObserver&) = 0;
virtual void Trace(blink::Visitor* visitor) {}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {}
const char* NameInHeapSnapshot() const override {
return "MutationObserver::Delegate";
}
@@ -128,8 +118,6 @@ class CORE_EXPORT MutationObserver final
EAGERLY_FINALIZE();
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
private:
struct ObserverLessThan;
diff --git a/chromium/third_party/blink/renderer/core/dom/mutation_observer_interest_group.cc b/chromium/third_party/blink/renderer/core/dom/mutation_observer_interest_group.cc
index 91496a065b0..49d85ba1c20 100644
--- a/chromium/third_party/blink/renderer/core/dom/mutation_observer_interest_group.cc
+++ b/chromium/third_party/blink/renderer/core/dom/mutation_observer_interest_group.cc
@@ -36,10 +36,10 @@ namespace blink {
MutationObserverInterestGroup* MutationObserverInterestGroup::CreateIfNeeded(
Node& target,
- MutationObserver::MutationType type,
+ MutationType type,
MutationRecordDeliveryOptions old_value_flag,
const QualifiedName* attribute_name) {
- DCHECK((type == MutationObserver::kAttributes && attribute_name) ||
+ DCHECK((type == kMutationTypeAttributes && attribute_name) ||
!attribute_name);
HeapHashMap<Member<MutationObserver>, MutationRecordDeliveryOptions>
observers;
diff --git a/chromium/third_party/blink/renderer/core/dom/mutation_observer_interest_group.h b/chromium/third_party/blink/renderer/core/dom/mutation_observer_interest_group.h
index 44807ac9d47..bdf9c03bf95 100644
--- a/chromium/third_party/blink/renderer/core/dom/mutation_observer_interest_group.h
+++ b/chromium/third_party/blink/renderer/core/dom/mutation_observer_interest_group.h
@@ -46,20 +46,20 @@ class MutationObserverInterestGroup final
static MutationObserverInterestGroup* CreateForChildListMutation(
Node& target) {
if (!target.GetDocument().HasMutationObserversOfType(
- MutationObserver::kChildList))
+ kMutationTypeChildList))
return nullptr;
MutationRecordDeliveryOptions old_value_flag = 0;
- return CreateIfNeeded(target, MutationObserver::kChildList, old_value_flag);
+ return CreateIfNeeded(target, kMutationTypeChildList, old_value_flag);
}
static MutationObserverInterestGroup* CreateForCharacterDataMutation(
Node& target) {
if (!target.GetDocument().HasMutationObserversOfType(
- MutationObserver::kCharacterData))
+ kMutationTypeCharacterData))
return nullptr;
- return CreateIfNeeded(target, MutationObserver::kCharacterData,
+ return CreateIfNeeded(target, kMutationTypeCharacterData,
MutationObserver::kCharacterDataOldValue);
}
@@ -67,10 +67,10 @@ class MutationObserverInterestGroup final
Node& target,
const QualifiedName& attribute_name) {
if (!target.GetDocument().HasMutationObserversOfType(
- MutationObserver::kAttributes))
+ kMutationTypeAttributes))
return nullptr;
- return CreateIfNeeded(target, MutationObserver::kAttributes,
+ return CreateIfNeeded(target, kMutationTypeAttributes,
MutationObserver::kAttributeOldValue,
&attribute_name);
}
@@ -83,7 +83,7 @@ class MutationObserverInterestGroup final
private:
static MutationObserverInterestGroup* CreateIfNeeded(
Node& target,
- MutationObserver::MutationType,
+ MutationType,
MutationRecordDeliveryOptions old_value_flag,
const QualifiedName* attribute_name = nullptr);
MutationObserverInterestGroup(
diff --git a/chromium/third_party/blink/renderer/core/dom/mutation_observer_options.h b/chromium/third_party/blink/renderer/core/dom/mutation_observer_options.h
new file mode 100644
index 00000000000..38503a52c81
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/dom/mutation_observer_options.h
@@ -0,0 +1,26 @@
+// 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_DOM_MUTATION_OBSERVER_OPTIONS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_MUTATION_OBSERVER_OPTIONS_H_
+
+namespace blink {
+
+using MutationObserverOptions = unsigned char;
+using MutationRecordDeliveryOptions = unsigned char;
+
+// MutationType represents lower three bits of MutationObserverOptions.
+// It doesn't use |enum class| because we'd like to do bitwise operations.
+enum MutationType {
+ kMutationTypeChildList = 1 << 0,
+ kMutationTypeAttributes = 1 << 1,
+ kMutationTypeCharacterData = 1 << 2,
+
+ kMutationTypeAll = kMutationTypeChildList | kMutationTypeAttributes |
+ kMutationTypeCharacterData
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_MUTATION_OBSERVER_OPTIONS_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/mutation_observer_registration.cc b/chromium/third_party/blink/renderer/core/dom/mutation_observer_registration.cc
index 2517cdd6516..836bb344704 100644
--- a/chromium/third_party/blink/renderer/core/dom/mutation_observer_registration.cc
+++ b/chromium/third_party/blink/renderer/core/dom/mutation_observer_registration.cc
@@ -116,9 +116,9 @@ void MutationObserverRegistration::Unregister() {
bool MutationObserverRegistration::ShouldReceiveMutationFrom(
Node& node,
- MutationObserver::MutationType type,
+ MutationType type,
const QualifiedName* attribute_name) const {
- DCHECK((type == MutationObserver::kAttributes && attribute_name) ||
+ DCHECK((type == kMutationTypeAttributes && attribute_name) ||
!attribute_name);
if (!(options_ & type))
return false;
@@ -126,7 +126,7 @@ bool MutationObserverRegistration::ShouldReceiveMutationFrom(
if (registration_node_ != &node && !IsSubtree())
return false;
- if (type != MutationObserver::kAttributes ||
+ if (type != kMutationTypeAttributes ||
!(options_ & MutationObserver::kAttributeFilter))
return true;
@@ -155,9 +155,4 @@ void MutationObserverRegistration::Trace(blink::Visitor* visitor) {
visitor->Trace(transient_registration_nodes_);
}
-void MutationObserverRegistration::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(observer_);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/mutation_observer_registration.h b/chromium/third_party/blink/renderer/core/dom/mutation_observer_registration.h
index d3e6c77d20f..ff5af8ec2f9 100644
--- a/chromium/third_party/blink/renderer/core/dom/mutation_observer_registration.h
+++ b/chromium/third_party/blink/renderer/core/dom/mutation_observer_registration.h
@@ -33,7 +33,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/mutation_observer.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
@@ -46,7 +46,7 @@ class QualifiedName;
class CORE_EXPORT MutationObserverRegistration final
: public GarbageCollectedFinalized<MutationObserverRegistration>,
- public TraceWrapperBase {
+ public NameClient {
public:
static MutationObserverRegistration* Create(
MutationObserver&,
@@ -66,7 +66,7 @@ class CORE_EXPORT MutationObserverRegistration final
void Unregister();
bool ShouldReceiveMutationFrom(Node&,
- MutationObserver::MutationType,
+ MutationType,
const QualifiedName* attribute_name) const;
bool IsSubtree() const { return options_ & MutationObserver::kSubtree; }
@@ -75,8 +75,8 @@ class CORE_EXPORT MutationObserverRegistration final
return options_ & (MutationObserver::kAttributeOldValue |
MutationObserver::kCharacterDataOldValue);
}
- MutationObserverOptions MutationTypes() const {
- return options_ & MutationObserver::kAllMutationTypes;
+ MutationType MutationTypes() const {
+ return static_cast<MutationType>(options_ & kMutationTypeAll);
}
void AddRegistrationNodesToSet(HeapHashSet<Member<Node>>&) const;
@@ -84,7 +84,6 @@ class CORE_EXPORT MutationObserverRegistration final
void Dispose();
void Trace(blink::Visitor*);
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "MutationObserverRegistration";
}
diff --git a/chromium/third_party/blink/renderer/core/dom/mutation_observer_test.cc b/chromium/third_party/blink/renderer/core/dom/mutation_observer_test.cc
index 31c23616905..b4f620ca95b 100644
--- a/chromium/third_party/blink/renderer/core/dom/mutation_observer_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/mutation_observer_test.cc
@@ -53,7 +53,7 @@ TEST(MutationObserverTest, DisconnectCrash) {
// MutationObserverRegistration for |head|.
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kLazySweeping, BlinkGC::kForcedGC);
+ BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGC);
observer->disconnect();
// The test passes if disconnect() didn't crash. crbug.com/657613.
}
diff --git a/chromium/third_party/blink/renderer/core/dom/mutation_record.cc b/chromium/third_party/blink/renderer/core/dom/mutation_record.cc
index 0e9f9c095c1..a8fe80cba29 100644
--- a/chromium/third_party/blink/renderer/core/dom/mutation_record.cc
+++ b/chromium/third_party/blink/renderer/core/dom/mutation_record.cc
@@ -62,13 +62,6 @@ class ChildListRecord : public MutationRecord {
MutationRecord::Trace(visitor);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- visitor->TraceWrappers(target_);
- visitor->TraceWrappers(added_nodes_);
- visitor->TraceWrappers(removed_nodes_);
- MutationRecord::TraceWrappers(visitor);
- }
-
private:
const AtomicString& type() override;
Node* target() override { return target_.Get(); }
@@ -96,13 +89,6 @@ class RecordWithEmptyNodeLists : public MutationRecord {
MutationRecord::Trace(visitor);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- visitor->TraceWrappers(target_);
- visitor->TraceWrappers(added_nodes_);
- visitor->TraceWrappers(removed_nodes_);
- MutationRecord::TraceWrappers(visitor);
- }
-
private:
Node* target() override { return target_.Get(); }
String oldValue() override { return old_value_; }
@@ -164,11 +150,6 @@ class MutationRecordWithNullOldValue : public MutationRecord {
MutationRecord::Trace(visitor);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- visitor->TraceWrappers(record_);
- MutationRecord::TraceWrappers(visitor);
- }
-
private:
const AtomicString& type() override { return record_->type(); }
Node* target() override { return record_->target(); }
diff --git a/chromium/third_party/blink/renderer/core/dom/named_node_map.cc b/chromium/third_party/blink/renderer/core/dom/named_node_map.cc
index c34ce7329a8..5ba3f05cdf9 100644
--- a/chromium/third_party/blink/renderer/core/dom/named_node_map.cc
+++ b/chromium/third_party/blink/renderer/core/dom/named_node_map.cc
@@ -25,11 +25,10 @@
#include "third_party/blink/renderer/core/dom/named_node_map.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/attr.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/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -51,7 +50,8 @@ Attr* NamedNodeMap::removeNamedItem(const AtomicString& name,
element_->Attributes().FindIndex(element_->LowercaseIfNecessary(name));
if (index == kNotFound) {
exception_state.ThrowDOMException(
- kNotFoundError, "No item with name '" + name + "' was found.");
+ DOMExceptionCode::kNotFoundError,
+ "No item with name '" + name + "' was found.");
return nullptr;
}
return element_->DetachAttribute(index);
@@ -63,7 +63,7 @@ Attr* NamedNodeMap::removeNamedItemNS(const AtomicString& namespace_uri,
size_t index = element_->Attributes().FindIndex(
QualifiedName(g_null_atom, local_name, namespace_uri));
if (index == kNotFound) {
- exception_state.ThrowDOMException(kNotFoundError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotFoundError,
"No item with name '" + namespace_uri +
"::" + local_name + "' was found.");
return nullptr;
diff --git a/chromium/third_party/blink/renderer/core/dom/ng/OWNERS b/chromium/third_party/blink/renderer/core/dom/ng/OWNERS
deleted file mode 100644
index 4961e2b782d..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/ng/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-hayato@chromium.org
-
-# TEAM: dom-dev@chromium.org
-# COMPONENT: Blink>DOM
diff --git a/chromium/third_party/blink/renderer/core/dom/ng/README.md b/chromium/third_party/blink/renderer/core/dom/ng/README.md
deleted file mode 100644
index 479a6b6c6fd..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/ng/README.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# DOM experimental
-
-[Rendered](https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/core/dom/ng/README.md)
-
-Author: hayato@chromium.org
-
-This directory contains the implementation of **Incremental Shadow DOM**, which is in development behind "IncrementalShadowDOM" runtime flag.
-
-- [Design doc](https://docs.google.com/document/d/1R9J8CVaSub_nbaVQwwm3NjCoZye4feJ7ft7tVe5QerM/edit?usp=sharing)
-- [Tracking bug](http://crbug.com/776656)
diff --git a/chromium/third_party/blink/renderer/core/dom/ng/flat_tree_traversal_ng.cc b/chromium/third_party/blink/renderer/core/dom/ng/flat_tree_traversal_ng.cc
deleted file mode 100644
index 7aee272ba99..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/ng/flat_tree_traversal_ng.cc
+++ /dev/null
@@ -1,368 +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.
- * * 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/dom/ng/flat_tree_traversal_ng.h"
-
-#include "third_party/blink/renderer/core/dom/element.h"
-#include "third_party/blink/renderer/core/html/html_shadow_element.h"
-#include "third_party/blink/renderer/core/html/html_slot_element.h"
-
-namespace blink {
-
-bool CanBeDistributedToV0InsertionPoint(const Node& node) {
- return node.IsInV0ShadowTree() || node.IsChildOfV0ShadowHost();
-}
-
-Node* FlatTreeTraversalNg::TraverseChild(const Node& node,
- TraversalDirection direction) {
- if (auto* slot = ToHTMLSlotElementIfSupportsAssignmentOrNull(node)) {
- if (slot->AssignedNodes().IsEmpty()) {
- return direction == kTraversalDirectionForward ? slot->firstChild()
- : slot->lastChild();
- }
- return direction == kTraversalDirectionForward ? slot->FirstAssignedNode()
- : slot->LastAssignedNode();
- }
-
- Node* child;
- if (ShadowRoot* shadow_root = node.GetShadowRoot()) {
- child = direction == kTraversalDirectionForward ? shadow_root->firstChild()
- : shadow_root->lastChild();
- } else {
- child = direction == kTraversalDirectionForward ? node.firstChild()
- : node.lastChild();
- }
-
- if (!child)
- return nullptr;
-
- if (child->IsInV0ShadowTree()) {
- return V0ResolveDistributionStartingAt(*child, direction);
- }
- return child;
-}
-
-// This needs only for v0
-// Node* FlatTreeTraversalNg::ResolveDistributionStartingAt(
-// const Node* node,
-// TraversalDirection direction) {
-// if (!node)
-// return nullptr;
-// for (const Node* sibling = node; sibling;
-// sibling = (direction == kTraversalDirectionForward
-// ? sibling->nextSibling()
-// : sibling->previousSibling())) {
-// if (node->IsInV0ShadowTree())
-// return V0ResolveDistributionStartingAt(*sibling, direction);
-// return const_cast<Node*>(sibling);
-// }
-// return nullptr;
-// }
-
-Node* FlatTreeTraversalNg::V0ResolveDistributionStartingAt(
- const Node& node,
- TraversalDirection direction) {
- DCHECK(!ToHTMLSlotElementIfSupportsAssignmentOrNull(node));
- for (const Node* sibling = &node; sibling;
- sibling = (direction == kTraversalDirectionForward
- ? sibling->nextSibling()
- : sibling->previousSibling())) {
- if (!IsActiveV0InsertionPoint(*sibling))
- return const_cast<Node*>(sibling);
- const V0InsertionPoint& insertion_point = ToV0InsertionPoint(*sibling);
- if (Node* found = (direction == kTraversalDirectionForward
- ? insertion_point.FirstDistributedNode()
- : insertion_point.LastDistributedNode()))
- return found;
- DCHECK(IsHTMLShadowElement(insertion_point) ||
- (IsHTMLContentElement(insertion_point) &&
- !insertion_point.HasChildren()));
- }
- return nullptr;
-}
-
-// TODO(hayato): This may return a wrong result for a node which is not in a
-// document flat tree. See FlatTreeTraversalNgTest's redistribution test for
-// details.
-Node* FlatTreeTraversalNg::TraverseSiblings(const Node& node,
- TraversalDirection direction) {
- if (node.IsChildOfV1ShadowHost())
- return TraverseSiblingsForV1HostChild(node, direction);
-
- if (ShadowRootWhereNodeCanBeDistributedForV0(node))
- return TraverseSiblingsForV0Distribution(node, direction);
-
- Node* sibling = direction == kTraversalDirectionForward
- ? node.nextSibling()
- : node.previousSibling();
-
- if (!node.IsInV0ShadowTree())
- return sibling;
-
- if (sibling) {
- if (Node* found = V0ResolveDistributionStartingAt(*sibling, direction))
- return found;
- }
-
- // // Slotted nodes are already handled in traverseSiblingsForV1HostChild()
- // // above, here is for fallback contents.
- // if (auto* slot = ToHTMLSlotElementOrNull(node.parentElement())) {
- // if (slot->SupportsAssignment() && slot->AssignedNodes().IsEmpty())
- // return TraverseSiblings(*slot, direction);
- // }
- return nullptr;
-}
-
-Node* FlatTreeTraversalNg::TraverseSiblingsForV1HostChild(
- const Node& node,
- TraversalDirection direction) {
- HTMLSlotElement* slot = node.AssignedSlot();
- if (!slot)
- return nullptr;
- return direction == kTraversalDirectionForward
- ? slot->AssignedNodeNextTo(node)
- : slot->AssignedNodePreviousTo(node);
-}
-
-Node* FlatTreeTraversalNg::TraverseSiblingsForV0Distribution(
- const Node& node,
- TraversalDirection direction) {
- const V0InsertionPoint* final_destination = ResolveReprojection(&node);
- if (!final_destination)
- return nullptr;
- if (Node* found = (direction == kTraversalDirectionForward
- ? final_destination->DistributedNodeNextTo(&node)
- : final_destination->DistributedNodePreviousTo(&node)))
- return found;
- return TraverseSiblings(*final_destination, direction);
-}
-
-ContainerNode* FlatTreeTraversalNg::TraverseParent(
- const Node& node,
- ParentTraversalDetails* details) {
- // TODO(hayato): Stop this hack for a pseudo element because a pseudo element
- // is not a child of its parentOrShadowHostNode() in a flat tree.
- if (node.IsPseudoElement())
- return node.ParentOrShadowHostNode();
-
- if (node.IsChildOfV1ShadowHost())
- return node.AssignedSlot();
-
- if (auto* parent_slot =
- ToHTMLSlotElementIfSupportsAssignmentOrNull(node.parentElement())) {
- if (!parent_slot->AssignedNodes().IsEmpty())
- return nullptr;
- return parent_slot;
- }
-
- if (CanBeDistributedToV0InsertionPoint(node))
- return TraverseParentForV0(node, details);
-
- DCHECK(!ShadowRootWhereNodeCanBeDistributedForV0(node));
- return TraverseParentOrHost(node);
-}
-
-ContainerNode* FlatTreeTraversalNg::TraverseParentForV0(
- const Node& node,
- ParentTraversalDetails* details) {
- if (ShadowRootWhereNodeCanBeDistributedForV0(node)) {
- if (const V0InsertionPoint* insertion_point = ResolveReprojection(&node)) {
- if (details)
- details->DidTraverseInsertionPoint(insertion_point);
- // The node is distributed. But the distribution was stopped at this
- // insertion point.
- if (ShadowRootWhereNodeCanBeDistributedForV0(*insertion_point))
- return nullptr;
- return TraverseParent(*insertion_point);
- }
- return nullptr;
- }
- ContainerNode* parent = TraverseParentOrHost(node);
- if (IsActiveV0InsertionPoint(*parent))
- return nullptr;
- return parent;
-}
-
-ContainerNode* FlatTreeTraversalNg::TraverseParentOrHost(const Node& node) {
- ContainerNode* parent = node.parentNode();
- if (!parent)
- return nullptr;
- if (!parent->IsShadowRoot())
- return parent;
- ShadowRoot* shadow_root = ToShadowRoot(parent);
- return &shadow_root->host();
-}
-
-Node* FlatTreeTraversalNg::ChildAt(const Node& node, unsigned index) {
- AssertPrecondition(node);
- Node* child = TraverseFirstChild(node);
- while (child && index--)
- child = NextSibling(*child);
- AssertPostcondition(child);
- return child;
-}
-
-Node* FlatTreeTraversalNg::NextSkippingChildren(const Node& node) {
- if (Node* next_sibling = TraverseNextSibling(node))
- return next_sibling;
- return TraverseNextAncestorSibling(node);
-}
-
-bool FlatTreeTraversalNg::ContainsIncludingPseudoElement(
- const ContainerNode& container,
- const Node& node) {
- AssertPrecondition(container);
- AssertPrecondition(node);
- // This can be slower than FlatTreeTraversalNg::contains() because we
- // can't early exit even when container doesn't have children.
- for (const Node* current = &node; current;
- current = TraverseParent(*current)) {
- if (current == &container)
- return true;
- }
- return false;
-}
-
-Node* FlatTreeTraversalNg::PreviousSkippingChildren(const Node& node) {
- if (Node* previous_sibling = TraversePreviousSibling(node))
- return previous_sibling;
- return TraversePreviousAncestorSibling(node);
-}
-
-Node* FlatTreeTraversalNg::PreviousAncestorSiblingPostOrder(
- const Node& current,
- const Node* stay_within) {
- DCHECK(!FlatTreeTraversalNg::PreviousSibling(current));
- for (Node* parent = FlatTreeTraversalNg::Parent(current); parent;
- parent = FlatTreeTraversalNg::Parent(*parent)) {
- if (parent == stay_within)
- return nullptr;
- if (Node* previous_sibling = FlatTreeTraversalNg::PreviousSibling(*parent))
- return previous_sibling;
- }
- return nullptr;
-}
-
-// TODO(yosin) We should consider introducing template class to share code
-// between DOM tree traversal and flat tree tarversal.
-Node* FlatTreeTraversalNg::PreviousPostOrder(const Node& current,
- const Node* stay_within) {
- AssertPrecondition(current);
- if (stay_within)
- AssertPrecondition(*stay_within);
- if (Node* last_child = TraverseLastChild(current)) {
- AssertPostcondition(last_child);
- return last_child;
- }
- if (current == stay_within)
- return nullptr;
- if (Node* previous_sibling = TraversePreviousSibling(current)) {
- AssertPostcondition(previous_sibling);
- return previous_sibling;
- }
- return PreviousAncestorSiblingPostOrder(current, stay_within);
-}
-
-bool FlatTreeTraversalNg::IsDescendantOf(const Node& node, const Node& other) {
- AssertPrecondition(node);
- AssertPrecondition(other);
- if (!HasChildren(other) || node.isConnected() != other.isConnected())
- return false;
- for (const ContainerNode* n = TraverseParent(node); n;
- n = TraverseParent(*n)) {
- if (n == other)
- return true;
- }
- return false;
-}
-
-Node* FlatTreeTraversalNg::CommonAncestor(const Node& node_a,
- const Node& node_b) {
- AssertPrecondition(node_a);
- AssertPrecondition(node_b);
- Node* result = node_a.CommonAncestor(node_b, [](const Node& node) {
- return FlatTreeTraversalNg::Parent(node);
- });
- AssertPostcondition(result);
- return result;
-}
-
-Node* FlatTreeTraversalNg::TraverseNextAncestorSibling(const Node& node) {
- DCHECK(!TraverseNextSibling(node));
- for (Node* parent = TraverseParent(node); parent;
- parent = TraverseParent(*parent)) {
- if (Node* next_sibling = TraverseNextSibling(*parent))
- return next_sibling;
- }
- return nullptr;
-}
-
-Node* FlatTreeTraversalNg::TraversePreviousAncestorSibling(const Node& node) {
- DCHECK(!TraversePreviousSibling(node));
- for (Node* parent = TraverseParent(node); parent;
- parent = TraverseParent(*parent)) {
- if (Node* previous_sibling = TraversePreviousSibling(*parent))
- return previous_sibling;
- }
- return nullptr;
-}
-
-unsigned FlatTreeTraversalNg::Index(const Node& node) {
- AssertPrecondition(node);
- unsigned count = 0;
- for (Node* runner = TraversePreviousSibling(node); runner;
- runner = PreviousSibling(*runner))
- ++count;
- return count;
-}
-
-unsigned FlatTreeTraversalNg::CountChildren(const Node& node) {
- AssertPrecondition(node);
- unsigned count = 0;
- for (Node* runner = TraverseFirstChild(node); runner;
- runner = TraverseNextSibling(*runner))
- ++count;
- return count;
-}
-
-Node* FlatTreeTraversalNg::LastWithin(const Node& node) {
- AssertPrecondition(node);
- Node* descendant = TraverseLastChild(node);
- for (Node* child = descendant; child; child = LastChild(*child))
- descendant = child;
- AssertPostcondition(descendant);
- return descendant;
-}
-
-Node& FlatTreeTraversalNg::LastWithinOrSelf(const Node& node) {
- AssertPrecondition(node);
- Node* last_descendant = LastWithin(node);
- Node& result = last_descendant ? *last_descendant : const_cast<Node&>(node);
- AssertPostcondition(&result);
- return result;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/ng/flat_tree_traversal_ng.h b/chromium/third_party/blink/renderer/core/dom/ng/flat_tree_traversal_ng.h
deleted file mode 100644
index fab7c008cb8..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/ng/flat_tree_traversal_ng.h
+++ /dev/null
@@ -1,331 +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.
- * * 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 FlatTreeTraversalNg_h
-#define FlatTreeTraversalNg_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/dom/layout_tree_builder_traversal.h"
-#include "third_party/blink/renderer/core/dom/node_traversal.h"
-#include "third_party/blink/renderer/core/dom/shadow_root.h"
-#include "third_party/blink/renderer/core/dom/v0_insertion_point.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class ContainerNode;
-class Node;
-
-bool CanBeDistributedToV0InsertionPoint(const Node& node);
-
-// Flat tree version of |NodeTraversal|.
-//
-// None of member functions takes a |ShadowRoot| or an active insertion point,
-// e.g. roughly speaking <content> and <shadow> in the shadow tree, see
-// |InsertionPoint::isActive()| for details of active insertion points, since
-// they aren't appeared in the flat tree. |assertPrecondition()| and
-// |assertPostCondition()| check this condition.
-//
-// FIXME: Make some functions inline to optimise the performance.
-// https://bugs.webkit.org/show_bug.cgi?id=82702
-class CORE_EXPORT FlatTreeTraversalNg {
- STATIC_ONLY(FlatTreeTraversalNg);
-
- public:
- typedef LayoutTreeBuilderTraversal::ParentDetails ParentTraversalDetails;
- using TraversalNodeType = Node;
-
- static Node* Next(const Node&);
- static Node* Next(const Node&, const Node* stay_within);
- static Node* Previous(const Node&);
-
- static Node* FirstChild(const Node&);
- static Node* LastChild(const Node&);
- static bool HasChildren(const Node&);
-
- static ContainerNode* Parent(const Node&, ParentTraversalDetails* = nullptr);
- static Element* ParentElement(const Node&);
-
- static Node* NextSibling(const Node&);
- static Node* PreviousSibling(const Node&);
-
- // Returns a child node at |index|. If |index| is greater than or equal to
- // the children, this function returns |nullptr|.
- static Node* ChildAt(const Node&, unsigned index);
-
- // Flat tree version of |NodeTraversal::nextSkippingChildren()|. This
- // function is similar to |next()| but skips child nodes of a specified
- // node.
- static Node* NextSkippingChildren(const Node&);
- static Node* NextSkippingChildren(const Node&, const Node* stay_within);
-
- static Node* FirstWithin(const Node& current) { return FirstChild(current); }
-
- // Flat tree version of |NodeTraversal::previousSkippingChildren()|
- // similar to |previous()| but skipping child nodes of the specified node.
- static Node* PreviousSkippingChildren(const Node&);
-
- // Like previous, but visits parents before their children.
- static Node* PreviousPostOrder(const Node&,
- const Node* stay_within = nullptr);
-
- // Flat tree version of |Node::isDescendantOf(other)|. This function
- // returns true if |other| contains |node|, otherwise returns
- // false. If |other| is |node|, this function returns false.
- static bool IsDescendantOf(const Node& /*node*/, const Node& other);
-
- static bool Contains(const ContainerNode& container, const Node& node) {
- AssertPrecondition(container);
- AssertPrecondition(node);
- return container == node || IsDescendantOf(node, container);
- }
-
- static bool ContainsIncludingPseudoElement(const ContainerNode&, const Node&);
-
- // Returns a common ancestor of |nodeA| and |nodeB| if exists, otherwise
- // returns |nullptr|.
- static Node* CommonAncestor(const Node& node_a, const Node& node_b);
-
- // Flat tree version of |Node::nodeIndex()|. This function returns a
- // zero base position number of the specified node in child nodes list, or
- // zero if the specified node has no parent.
- static unsigned Index(const Node&);
-
- // Flat tree version of |ContainerNode::countChildren()|. This function
- // returns the number of the child nodes of the specified node in the
- // flat tree.
- static unsigned CountChildren(const Node&);
-
- static Node* LastWithin(const Node&);
- static Node& LastWithinOrSelf(const Node&);
-
- // Flat tree range helper functions for range based for statement.
- // TODO(dom-team): We should have following functions to match with
- // |NodeTraversal|:
- // - AncestorsOf()
- // - DescendantsOf()
- // - InclusiveAncestorsOf()
- // - InclusiveDescendantsOf()
- // - StartsAt()
- // - StartsAfter()
- static TraversalRange<TraversalChildrenIterator<FlatTreeTraversalNg>>
- ChildrenOf(const Node&);
-
- private:
- enum TraversalDirection {
- kTraversalDirectionForward,
- kTraversalDirectionBackward
- };
-
- static void AssertPrecondition(const Node& node) {
- DCHECK(!node.NeedsDistributionRecalc());
- DCHECK(node.CanParticipateInFlatTree());
- }
-
- static void AssertPostcondition(const Node* node) {
-#if DCHECK_IS_ON()
- if (node)
- AssertPrecondition(*node);
-#endif
- }
-
- // static Node* ResolveDistributionStartingAt(const Node*,
- // TraversalDirection);
- static Node* V0ResolveDistributionStartingAt(const Node&, TraversalDirection);
-
- static Node* TraverseNext(const Node&);
- static Node* TraverseNext(const Node&, const Node* stay_within);
- static Node* TraverseNextSkippingChildren(const Node&,
- const Node* stay_within);
- static Node* TraversePrevious(const Node&);
-
- static Node* TraverseFirstChild(const Node&);
- static Node* TraverseLastChild(const Node&);
- static Node* TraverseChild(const Node&, TraversalDirection);
-
- static ContainerNode* TraverseParent(const Node&,
- ParentTraversalDetails* = nullptr);
- // TODO(hayato): Make ParentTraversalDetails be aware of slot elements too.
- static ContainerNode* TraverseParentForV0(const Node&,
- ParentTraversalDetails* = nullptr);
- static ContainerNode* TraverseParentOrHost(const Node&);
-
- static Node* TraverseNextSibling(const Node&);
- static Node* TraversePreviousSibling(const Node&);
-
- static Node* TraverseSiblings(const Node&, TraversalDirection);
- static Node* TraverseSiblingsForV1HostChild(const Node&, TraversalDirection);
- static Node* TraverseSiblingsForV0Distribution(const Node&,
- TraversalDirection);
-
- static Node* TraverseNextAncestorSibling(const Node&);
- static Node* TraversePreviousAncestorSibling(const Node&);
- static Node* PreviousAncestorSiblingPostOrder(const Node& current,
- const Node* stay_within);
-};
-
-inline ContainerNode* FlatTreeTraversalNg::Parent(
- const Node& node,
- ParentTraversalDetails* details) {
- AssertPrecondition(node);
- ContainerNode* result = TraverseParent(node, details);
- AssertPostcondition(result);
- return result;
-}
-
-inline Element* FlatTreeTraversalNg::ParentElement(const Node& node) {
- ContainerNode* parent = FlatTreeTraversalNg::Parent(node);
- return parent && parent->IsElementNode() ? ToElement(parent) : nullptr;
-}
-
-inline Node* FlatTreeTraversalNg::NextSibling(const Node& node) {
- AssertPrecondition(node);
- Node* result = TraverseSiblings(node, kTraversalDirectionForward);
- AssertPostcondition(result);
- return result;
-}
-
-inline Node* FlatTreeTraversalNg::PreviousSibling(const Node& node) {
- AssertPrecondition(node);
- Node* result = TraverseSiblings(node, kTraversalDirectionBackward);
- AssertPostcondition(result);
- return result;
-}
-
-inline Node* FlatTreeTraversalNg::Next(const Node& node) {
- AssertPrecondition(node);
- Node* result = TraverseNext(node);
- AssertPostcondition(result);
- return result;
-}
-
-inline Node* FlatTreeTraversalNg::Next(const Node& node,
- const Node* stay_within) {
- AssertPrecondition(node);
- Node* result = TraverseNext(node, stay_within);
- AssertPostcondition(result);
- return result;
-}
-
-inline Node* FlatTreeTraversalNg::NextSkippingChildren(
- const Node& node,
- const Node* stay_within) {
- AssertPrecondition(node);
- Node* result = TraverseNextSkippingChildren(node, stay_within);
- AssertPostcondition(result);
- return result;
-}
-
-inline Node* FlatTreeTraversalNg::TraverseNext(const Node& node) {
- if (Node* next = TraverseFirstChild(node))
- return next;
- for (const Node* next = &node; next; next = TraverseParent(*next)) {
- if (Node* sibling = TraverseNextSibling(*next))
- return sibling;
- }
- return nullptr;
-}
-
-inline Node* FlatTreeTraversalNg::TraverseNext(const Node& node,
- const Node* stay_within) {
- if (Node* next = TraverseFirstChild(node))
- return next;
- return TraverseNextSkippingChildren(node, stay_within);
-}
-
-inline Node* FlatTreeTraversalNg::TraverseNextSkippingChildren(
- const Node& node,
- const Node* stay_within) {
- for (const Node* next = &node; next; next = TraverseParent(*next)) {
- if (next == stay_within)
- return nullptr;
- if (Node* sibling = TraverseNextSibling(*next))
- return sibling;
- }
- return nullptr;
-}
-
-inline Node* FlatTreeTraversalNg::Previous(const Node& node) {
- AssertPrecondition(node);
- Node* result = TraversePrevious(node);
- AssertPostcondition(result);
- return result;
-}
-
-inline Node* FlatTreeTraversalNg::TraversePrevious(const Node& node) {
- if (Node* previous = TraversePreviousSibling(node)) {
- while (Node* child = TraverseLastChild(*previous))
- previous = child;
- return previous;
- }
- return TraverseParent(node);
-}
-
-inline Node* FlatTreeTraversalNg::FirstChild(const Node& node) {
- AssertPrecondition(node);
- Node* result = TraverseChild(node, kTraversalDirectionForward);
- AssertPostcondition(result);
- return result;
-}
-
-inline Node* FlatTreeTraversalNg::LastChild(const Node& node) {
- AssertPrecondition(node);
- Node* result = TraverseLastChild(node);
- AssertPostcondition(result);
- return result;
-}
-
-inline bool FlatTreeTraversalNg::HasChildren(const Node& node) {
- return FirstChild(node);
-}
-
-inline Node* FlatTreeTraversalNg::TraverseNextSibling(const Node& node) {
- return TraverseSiblings(node, kTraversalDirectionForward);
-}
-
-inline Node* FlatTreeTraversalNg::TraversePreviousSibling(const Node& node) {
- return TraverseSiblings(node, kTraversalDirectionBackward);
-}
-
-inline Node* FlatTreeTraversalNg::TraverseFirstChild(const Node& node) {
- return TraverseChild(node, kTraversalDirectionForward);
-}
-
-inline Node* FlatTreeTraversalNg::TraverseLastChild(const Node& node) {
- return TraverseChild(node, kTraversalDirectionBackward);
-}
-
-// TraverseRange<T> implementations
-inline TraversalRange<TraversalChildrenIterator<FlatTreeTraversalNg>>
-FlatTreeTraversalNg::ChildrenOf(const Node& parent) {
- return TraversalRange<TraversalChildrenIterator<FlatTreeTraversalNg>>(
- &parent);
-}
-
-} // namespace blink
-
-#endif
diff --git a/chromium/third_party/blink/renderer/core/dom/ng/flat_tree_traversal_ng_test.cc b/chromium/third_party/blink/renderer/core/dom/ng/flat_tree_traversal_ng_test.cc
deleted file mode 100644
index 7ffe9268281..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/ng/flat_tree_traversal_ng_test.cc
+++ /dev/null
@@ -1,772 +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/dom/ng/flat_tree_traversal_ng.h"
-
-#include <memory>
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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.h"
-#include "third_party/blink/renderer/core/dom/node_traversal.h"
-#include "third_party/blink/renderer/core/dom/shadow_root.h"
-#include "third_party/blink/renderer/core/frame/local_frame_view.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/geometry/int_size.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
-#include "third_party/blink/renderer/platform/wtf/compiler.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-// To avoid symbol collisions in jumbo builds.
-namespace flat_tree_traversal_ng_test {
-
-class FlatTreeTraversalNgTest : public PageTestBase,
- private ScopedSlotInFlatTreeForTest,
- ScopedIncrementalShadowDOMForTest {
- public:
- FlatTreeTraversalNgTest()
- : ScopedSlotInFlatTreeForTest(true),
- ScopedIncrementalShadowDOMForTest(true) {}
-
- protected:
- // Sets |mainHTML| to BODY element with |innerHTML| property and attaches
- // shadow root to child with |shadowHTML|, then update distribution for
- // calling member functions in |FlatTreeTraversalNg|.
- void SetupSampleHTML(const char* main_html,
- const char* shadow_html,
- unsigned);
-
- void SetupDocumentTree(const char* main_html);
-
- void AttachV0ShadowRoot(Element& shadow_host, const char* shadow_inner_html);
- void AttachOpenShadowRoot(Element& shadow_host,
- const char* shadow_inner_html);
-};
-
-void FlatTreeTraversalNgTest::SetupSampleHTML(const char* main_html,
- const char* shadow_html,
- unsigned index) {
- Element* body = GetDocument().body();
- body->SetInnerHTMLFromString(String::FromUTF8(main_html));
- Element* shadow_host = ToElement(NodeTraversal::ChildAt(*body, index));
- ShadowRoot& shadow_root = shadow_host->CreateV0ShadowRootForTesting();
- shadow_root.SetInnerHTMLFromString(String::FromUTF8(shadow_html));
- body->UpdateDistributionForFlatTreeTraversal();
-}
-
-void FlatTreeTraversalNgTest::SetupDocumentTree(const char* main_html) {
- Element* body = GetDocument().body();
- body->SetInnerHTMLFromString(String::FromUTF8(main_html));
-}
-
-void FlatTreeTraversalNgTest::AttachV0ShadowRoot(
- Element& shadow_host,
- const char* shadow_inner_html) {
- ShadowRoot& shadow_root = shadow_host.CreateV0ShadowRootForTesting();
- shadow_root.SetInnerHTMLFromString(String::FromUTF8(shadow_inner_html));
- GetDocument().body()->UpdateDistributionForFlatTreeTraversal();
-}
-
-void FlatTreeTraversalNgTest::AttachOpenShadowRoot(
- Element& shadow_host,
- const char* shadow_inner_html) {
- ShadowRoot& shadow_root =
- shadow_host.AttachShadowRootInternal(ShadowRootType::kOpen);
- shadow_root.SetInnerHTMLFromString(String::FromUTF8(shadow_inner_html));
- GetDocument().body()->UpdateDistributionForFlatTreeTraversal();
-}
-
-namespace {
-
-void TestCommonAncestor(Node* expected_result,
- const Node& node_a,
- const Node& node_b) {
- Node* result1 = FlatTreeTraversalNg::CommonAncestor(node_a, node_b);
- EXPECT_EQ(expected_result, result1)
- << "commonAncestor(" << node_a.textContent() << ","
- << node_b.textContent() << ")";
- Node* result2 = FlatTreeTraversalNg::CommonAncestor(node_b, node_a);
- EXPECT_EQ(expected_result, result2)
- << "commonAncestor(" << node_b.textContent() << ","
- << node_a.textContent() << ")";
-}
-
-} // namespace
-
-// Test case for
-// - childAt
-// - countChildren
-// - hasChildren
-// - index
-// - isDescendantOf
-TEST_F(FlatTreeTraversalNgTest, childAt) {
- const char* main_html =
- "<div id='m0'>"
- "<span id='m00'>m00</span>"
- "<span id='m01'>m01</span>"
- "</div>";
- const char* shadow_html =
- "<a id='s00'>s00</a>"
- "<content select='#m01'></content>"
- "<a id='s02'>s02</a>"
- "<a id='s03'><content select='#m00'></content></a>"
- "<a id='s04'>s04</a>";
- SetupSampleHTML(main_html, shadow_html, 0);
-
- Element* body = GetDocument().body();
- Element* m0 = body->QuerySelector("#m0");
- Element* m00 = m0->QuerySelector("#m00");
- Element* m01 = m0->QuerySelector("#m01");
-
- Element* shadow_host = m0;
- ShadowRoot* shadow_root = shadow_host->OpenShadowRoot();
- Element* s00 = shadow_root->QuerySelector("#s00");
- Element* s02 = shadow_root->QuerySelector("#s02");
- Element* s03 = shadow_root->QuerySelector("#s03");
- Element* s04 = shadow_root->QuerySelector("#s04");
-
- const unsigned kNumberOfChildNodes = 5;
- Node* expected_child_nodes[5] = {s00, m01, s02, s03, s04};
-
- ASSERT_EQ(kNumberOfChildNodes,
- FlatTreeTraversalNg::CountChildren(*shadow_host));
- EXPECT_TRUE(FlatTreeTraversalNg::HasChildren(*shadow_host));
-
- for (unsigned index = 0; index < kNumberOfChildNodes; ++index) {
- Node* child = FlatTreeTraversalNg::ChildAt(*shadow_host, index);
- EXPECT_EQ(expected_child_nodes[index], child)
- << "FlatTreeTraversalNg::childAt(*shadowHost, " << index << ")";
- EXPECT_EQ(index, FlatTreeTraversalNg::Index(*child))
- << "FlatTreeTraversalNg::index(FlatTreeTraversalNg(*shadowHost, "
- << index << "))";
- EXPECT_TRUE(FlatTreeTraversalNg::IsDescendantOf(*child, *shadow_host))
- << "FlatTreeTraversalNg::isDescendantOf(*FlatTreeTraversalNg(*"
- "shadowHost, "
- << index << "), *shadowHost)";
- }
- EXPECT_EQ(nullptr,
- FlatTreeTraversalNg::ChildAt(*shadow_host, kNumberOfChildNodes + 1))
- << "Out of bounds childAt() returns nullptr.";
-
- // Distribute node |m00| is child of node in shadow tree |s03|.
- EXPECT_EQ(m00, FlatTreeTraversalNg::ChildAt(*s03, 0));
-}
-
-TEST_F(FlatTreeTraversalNgTest, ChildrenOf) {
- SetupSampleHTML(
- "<p id=sample>ZERO<span slot=three>three</b><span "
- "slot=one>one</b>FOUR</p>",
- "zero<slot name=one></slot>two<slot name=three></slot>four", 0);
- Element* const sample = GetDocument().getElementById("sample");
-
- HeapVector<Member<Node>> expected_nodes;
- for (Node* runner = FlatTreeTraversalNg::FirstChild(*sample); runner;
- runner = FlatTreeTraversalNg::NextSibling(*runner)) {
- expected_nodes.push_back(runner);
- }
-
- HeapVector<Member<Node>> actual_nodes;
- for (Node& child : FlatTreeTraversalNg::ChildrenOf(*sample))
- actual_nodes.push_back(&child);
-
- EXPECT_EQ(expected_nodes, actual_nodes);
-}
-
-// Test case for
-// - commonAncestor
-// - isDescendantOf
-TEST_F(FlatTreeTraversalNgTest, commonAncestor) {
- // We build following flat tree:
- // ____BODY___
- // | | |
- // m0 m1 m2 m1 is shadow host having m10, m11, m12.
- // _|_ | __|__
- // | | | | |
- // m00 m01 | m20 m21
- // _____|_____________
- // | | | | |
- // s10 s11 s12 s13 s14
- // |
- // __|__
- // | | |
- // m12 m10 m11 <-- distributed
- // where: each symbol consists with prefix, child index, child-child index.
- // prefix "m" means node in main tree,
- // prefix "d" means node in main tree and distributed
- // prefix "s" means node in shadow tree
- const char* main_html =
- "<a id='m0'><b id='m00'>m00</b><b id='m01'>m01</b></a>"
- "<a id='m1'>"
- "<b id='m10'>m10</b>"
- "<b id='m11'>m11</b>"
- "<b id='m12'>m12</b>"
- "</a>"
- "<a id='m2'><b id='m20'>m20</b><b id='m21'>m21</b></a>";
- const char* shadow_html =
- "<a id='s10'>s10</a>"
- "<a id='s11'><content select='#m12'></content></a>"
- "<a id='s12'>s12</a>"
- "<a id='s13'>"
- "<content select='#m10'></content>"
- "<content select='#m11'></content>"
- "</a>"
- "<a id='s14'>s14</a>";
- SetupSampleHTML(main_html, shadow_html, 1);
- Element* body = GetDocument().body();
- Element* m0 = body->QuerySelector("#m0");
- Element* m1 = body->QuerySelector("#m1");
- Element* m2 = body->QuerySelector("#m2");
-
- Element* m00 = body->QuerySelector("#m00");
- Element* m01 = body->QuerySelector("#m01");
- Element* m10 = body->QuerySelector("#m10");
- Element* m11 = body->QuerySelector("#m11");
- Element* m12 = body->QuerySelector("#m12");
- Element* m20 = body->QuerySelector("#m20");
- Element* m21 = body->QuerySelector("#m21");
-
- ShadowRoot* shadow_root = m1->OpenShadowRoot();
- Element* s10 = shadow_root->QuerySelector("#s10");
- Element* s11 = shadow_root->QuerySelector("#s11");
- Element* s12 = shadow_root->QuerySelector("#s12");
- Element* s13 = shadow_root->QuerySelector("#s13");
- Element* s14 = shadow_root->QuerySelector("#s14");
-
- TestCommonAncestor(body, *m0, *m1);
- TestCommonAncestor(body, *m1, *m2);
- TestCommonAncestor(body, *m1, *m20);
- TestCommonAncestor(body, *s14, *m21);
-
- TestCommonAncestor(m0, *m0, *m0);
- TestCommonAncestor(m0, *m00, *m01);
-
- TestCommonAncestor(m1, *m1, *m1);
- TestCommonAncestor(m1, *s10, *s14);
- TestCommonAncestor(m1, *s10, *m12);
- TestCommonAncestor(m1, *s12, *m12);
- TestCommonAncestor(m1, *m10, *m12);
-
- TestCommonAncestor(m01, *m01, *m01);
- TestCommonAncestor(s11, *s11, *m12);
- TestCommonAncestor(s13, *m10, *m11);
-
- s12->remove(ASSERT_NO_EXCEPTION);
- TestCommonAncestor(s12, *s12, *s12);
- TestCommonAncestor(nullptr, *s12, *s11);
- TestCommonAncestor(nullptr, *s12, *m01);
- TestCommonAncestor(nullptr, *s12, *m20);
-
- m20->remove(ASSERT_NO_EXCEPTION);
- TestCommonAncestor(m20, *m20, *m20);
- TestCommonAncestor(nullptr, *m20, *s12);
- TestCommonAncestor(nullptr, *m20, *m1);
-}
-
-// Test case for
-// - nextSkippingChildren
-// - previousSkippingChildren
-TEST_F(FlatTreeTraversalNgTest, nextSkippingChildren) {
- const char* main_html =
- "<div id='m0'>m0</div>"
- "<div id='m1'>"
- "<span id='m10'>m10</span>"
- "<span id='m11'>m11</span>"
- "</div>"
- "<div id='m2'>m2</div>";
- const char* shadow_html =
- "<content select='#m11'></content>"
- "<a id='s11'>s11</a>"
- "<a id='s12'>"
- "<b id='s120'>s120</b>"
- "<content select='#m10'></content>"
- "</a>";
- SetupSampleHTML(main_html, shadow_html, 1);
-
- Element* body = GetDocument().body();
- Element* m0 = body->QuerySelector("#m0");
- Element* m1 = body->QuerySelector("#m1");
- Element* m2 = body->QuerySelector("#m2");
-
- Element* m10 = body->QuerySelector("#m10");
- Element* m11 = body->QuerySelector("#m11");
-
- ShadowRoot* shadow_root = m1->OpenShadowRoot();
- Element* s11 = shadow_root->QuerySelector("#s11");
- Element* s12 = shadow_root->QuerySelector("#s12");
- Element* s120 = shadow_root->QuerySelector("#s120");
-
- // Main tree node to main tree node
- EXPECT_EQ(*m1, FlatTreeTraversalNg::NextSkippingChildren(*m0));
- EXPECT_EQ(*m0, FlatTreeTraversalNg::PreviousSkippingChildren(*m1));
-
- // Distribute node to main tree node
- EXPECT_EQ(*m2, FlatTreeTraversalNg::NextSkippingChildren(*m10));
- EXPECT_EQ(*m1, FlatTreeTraversalNg::PreviousSkippingChildren(*m2));
-
- // Distribute node to node in shadow tree
- EXPECT_EQ(*s11, FlatTreeTraversalNg::NextSkippingChildren(*m11));
- EXPECT_EQ(*m11, FlatTreeTraversalNg::PreviousSkippingChildren(*s11));
-
- // Node in shadow tree to distributed node
- EXPECT_EQ(*s11, FlatTreeTraversalNg::NextSkippingChildren(*m11));
- EXPECT_EQ(*m11, FlatTreeTraversalNg::PreviousSkippingChildren(*s11));
-
- EXPECT_EQ(*m10, FlatTreeTraversalNg::NextSkippingChildren(*s120));
- EXPECT_EQ(*s120, FlatTreeTraversalNg::PreviousSkippingChildren(*m10));
-
- // Node in shadow tree to main tree
- EXPECT_EQ(*m2, FlatTreeTraversalNg::NextSkippingChildren(*s12));
- EXPECT_EQ(*m1, FlatTreeTraversalNg::PreviousSkippingChildren(*m2));
-}
-
-// Test case for
-// - lastWithin
-// - lastWithinOrSelf
-TEST_F(FlatTreeTraversalNgTest, lastWithin) {
- const char* main_html =
- "<div id='m0'>m0</div>"
- "<div id='m1'>"
- "<span id='m10'>m10</span>"
- "<span id='m11'>m11</span>"
- "<span id='m12'>m12</span>" // #m12 is not distributed.
- "</div>"
- "<div id='m2'></div>";
- const char* shadow_html =
- "<content select='#m11'></content>"
- "<a id='s11'>s11</a>"
- "<a id='s12'>"
- "<content select='#m10'></content>"
- "</a>";
- SetupSampleHTML(main_html, shadow_html, 1);
-
- Element* body = GetDocument().body();
- Element* m0 = body->QuerySelector("#m0");
- Element* m1 = body->QuerySelector("#m1");
- Element* m2 = body->QuerySelector("#m2");
-
- Element* m10 = body->QuerySelector("#m10");
-
- ShadowRoot* shadow_root = m1->OpenShadowRoot();
- Element* s11 = shadow_root->QuerySelector("#s11");
- Element* s12 = shadow_root->QuerySelector("#s12");
-
- EXPECT_EQ(m0->firstChild(), FlatTreeTraversalNg::LastWithin(*m0));
- EXPECT_EQ(*m0->firstChild(), FlatTreeTraversalNg::LastWithinOrSelf(*m0));
-
- EXPECT_EQ(m10->firstChild(), FlatTreeTraversalNg::LastWithin(*m1));
- EXPECT_EQ(*m10->firstChild(), FlatTreeTraversalNg::LastWithinOrSelf(*m1));
-
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::LastWithin(*m2));
- EXPECT_EQ(*m2, FlatTreeTraversalNg::LastWithinOrSelf(*m2));
-
- EXPECT_EQ(s11->firstChild(), FlatTreeTraversalNg::LastWithin(*s11));
- EXPECT_EQ(*s11->firstChild(), FlatTreeTraversalNg::LastWithinOrSelf(*s11));
-
- EXPECT_EQ(m10->firstChild(), FlatTreeTraversalNg::LastWithin(*s12));
- EXPECT_EQ(*m10->firstChild(), FlatTreeTraversalNg::LastWithinOrSelf(*s12));
-}
-
-TEST_F(FlatTreeTraversalNgTest, previousPostOrder) {
- const char* main_html =
- "<div id='m0'>m0</div>"
- "<div id='m1'>"
- "<span id='m10'>m10</span>"
- "<span id='m11'>m11</span>"
- "</div>"
- "<div id='m2'>m2</div>";
- const char* shadow_html =
- "<content select='#m11'></content>"
- "<a id='s11'>s11</a>"
- "<a id='s12'>"
- "<b id='s120'>s120</b>"
- "<content select='#m10'></content>"
- "</a>";
- SetupSampleHTML(main_html, shadow_html, 1);
-
- Element* body = GetDocument().body();
- Element* m0 = body->QuerySelector("#m0");
- Element* m1 = body->QuerySelector("#m1");
- Element* m2 = body->QuerySelector("#m2");
-
- Element* m10 = body->QuerySelector("#m10");
- Element* m11 = body->QuerySelector("#m11");
-
- ShadowRoot* shadow_root = m1->OpenShadowRoot();
- Element* s11 = shadow_root->QuerySelector("#s11");
- Element* s12 = shadow_root->QuerySelector("#s12");
- Element* s120 = shadow_root->QuerySelector("#s120");
-
- EXPECT_EQ(*m0->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*m0));
- EXPECT_EQ(*s12, FlatTreeTraversalNg::PreviousPostOrder(*m1));
- EXPECT_EQ(*m10->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*m10));
- EXPECT_EQ(*s120, FlatTreeTraversalNg::PreviousPostOrder(*m10->firstChild()));
- EXPECT_EQ(*s120,
- FlatTreeTraversalNg::PreviousPostOrder(*m10->firstChild(), s12));
- EXPECT_EQ(*m11->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*m11));
- EXPECT_EQ(*m0, FlatTreeTraversalNg::PreviousPostOrder(*m11->firstChild()));
- EXPECT_EQ(nullptr,
- FlatTreeTraversalNg::PreviousPostOrder(*m11->firstChild(), m11));
- EXPECT_EQ(*m2->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*m2));
-
- EXPECT_EQ(*s11->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*s11));
- EXPECT_EQ(*m10, FlatTreeTraversalNg::PreviousPostOrder(*s12));
- EXPECT_EQ(*s120->firstChild(), FlatTreeTraversalNg::PreviousPostOrder(*s120));
- EXPECT_EQ(*s11, FlatTreeTraversalNg::PreviousPostOrder(*s120->firstChild()));
- EXPECT_EQ(nullptr,
- FlatTreeTraversalNg::PreviousPostOrder(*s120->firstChild(), s12));
-}
-
-TEST_F(FlatTreeTraversalNgTest, nextSiblingNotInDocumentFlatTree) {
- const char* main_html =
- "<div id='m0'>m0</div>"
- "<div id='m1'>"
- "<span id='m10'>m10</span>"
- "<span id='m11'>m11</span>"
- "</div>"
- "<div id='m2'>m2</div>";
- const char* shadow_html = "<content select='#m11'></content>";
- SetupSampleHTML(main_html, shadow_html, 1);
-
- Element* body = GetDocument().body();
- Element* m10 = body->QuerySelector("#m10");
-
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*m10));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*m10));
-}
-
-TEST_F(FlatTreeTraversalNgTest, redistribution) {
- const char* main_html =
- "<div id='m0'>m0</div>"
- "<div id='m1'>"
- "<span id='m10'>m10</span>"
- "<span id='m11'>m11</span>"
- "</div>"
- "<div id='m2'>m2</div>";
- const char* shadow_html1 =
- "<div id='s1'>"
- "<content></content>"
- "</div>";
-
- SetupSampleHTML(main_html, shadow_html1, 1);
-
- const char* shadow_html2 =
- "<div id='s2'>"
- "<content select='#m10'></content>"
- "<span id='s21'>s21</span>"
- "</div>";
-
- Element* body = GetDocument().body();
- Element* m1 = body->QuerySelector("#m1");
- Element* m10 = body->QuerySelector("#m10");
-
- ShadowRoot* shadow_root1 = m1->OpenShadowRoot();
- Element* s1 = shadow_root1->QuerySelector("#s1");
-
- AttachV0ShadowRoot(*s1, shadow_html2);
-
- ShadowRoot* shadow_root2 = s1->OpenShadowRoot();
- Element* s21 = shadow_root2->QuerySelector("#s21");
-
- EXPECT_EQ(s21, FlatTreeTraversalNg::NextSibling(*m10));
- EXPECT_EQ(m10, FlatTreeTraversalNg::PreviousSibling(*s21));
-
- // FlatTreeTraversalNg::traverseSiblings does not work for a node which is not
- // in a document flat tree.
- // e.g. The following test fails. The result of
- // FlatTreeTraversalNg::previousSibling(*m11)) will be #m10, instead of
- // nullptr. Element* m11 = body->querySelector("#m11"); EXPECT_EQ(nullptr,
- // FlatTreeTraversalNg::previousSibling(*m11));
-}
-
-TEST_F(FlatTreeTraversalNgTest, v1Simple) {
- const char* main_html =
- "<div id='host'>"
- "<div id='child1' slot='slot1'></div>"
- "<div id='child2' slot='slot2'></div>"
- "</div>";
- const char* shadow_html =
- "<div id='shadow-child1'></div>"
- "<slot name='slot1'></slot>"
- "<slot name='slot2'></slot>"
- "<div id='shadow-child2'></div>";
-
- SetupDocumentTree(main_html);
- Element* body = GetDocument().body();
- Element* host = body->QuerySelector("#host");
- Element* child1 = body->QuerySelector("#child1");
- Element* child2 = body->QuerySelector("#child2");
-
- AttachOpenShadowRoot(*host, shadow_html);
- ShadowRoot* shadow_root = host->OpenShadowRoot();
- Element* slot1 = shadow_root->QuerySelector("[name=slot1]");
- Element* slot2 = shadow_root->QuerySelector("[name=slot2]");
- Element* shadow_child1 = shadow_root->QuerySelector("#shadow-child1");
- Element* shadow_child2 = shadow_root->QuerySelector("#shadow-child2");
-
- EXPECT_TRUE(slot1);
- EXPECT_TRUE(slot2);
- EXPECT_EQ(shadow_child1, FlatTreeTraversalNg::FirstChild(*host));
- EXPECT_EQ(slot1, FlatTreeTraversalNg::NextSibling(*shadow_child1));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*child1));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*child2));
- EXPECT_EQ(slot2, FlatTreeTraversalNg::NextSibling(*slot1));
- EXPECT_EQ(shadow_child2, FlatTreeTraversalNg::NextSibling(*slot2));
-}
-
-TEST_F(FlatTreeTraversalNgTest, v1Redistribution) {
- // composed tree:
- // d1
- // ├──/shadow-root
- // │ └── d1-1
- // │ ├──/shadow-root
- // │ │ ├── d1-1-1
- // │ │ ├── slot name=d1-1-s1
- // │ │ ├── slot name=d1-1-s2
- // │ │ └── d1-1-2
- // │ ├── d1-2
- // │ ├── slot id=d1-s0
- // │ ├── slot name=d1-s1 slot=d1-1-s1
- // │ ├── slot name=d1-s2
- // │ ├── d1-3
- // │ └── d1-4 slot=d1-1-s1
- // ├── d2 slot=d1-s1
- // ├── d3 slot=d1-s2
- // ├── d4 slot=nonexistent
- // └── d5
-
- // flat tree:
- // d1
- // └── d1-1
- // ├── d1-1-1
- // ├── slot name=d1-1-s1
- // │ ├── slot name=d1-s1 slot=d1-1-s1
- // │ │ └── d2 slot=d1-s1
- // │ └── d1-4 slot=d1-1-s1
- // ├── slot name=d1-1-s2
- // └── d1-1-2
- const char* main_html =
- "<div id='d1'>"
- "<div id='d2' slot='d1-s1'></div>"
- "<div id='d3' slot='d1-s2'></div>"
- "<div id='d4' slot='nonexistent'></div>"
- "<div id='d5'></div>"
- "</div>"
- "<div id='d6'></div>";
- const char* shadow_html1 =
- "<div id='d1-1'>"
- "<div id='d1-2'></div>"
- "<slot id='d1-s0'></slot>"
- "<slot name='d1-s1' slot='d1-1-s1'></slot>"
- "<slot name='d1-s2'></slot>"
- "<div id='d1-3'></div>"
- "<div id='d1-4' slot='d1-1-s1'></div>"
- "</div>";
- const char* shadow_html2 =
- "<div id='d1-1-1'></div>"
- "<slot name='d1-1-s1'></slot>"
- "<slot name='d1-1-s2'></slot>"
- "<div id='d1-1-2'></div>";
-
- SetupDocumentTree(main_html);
-
- Element* body = GetDocument().body();
- Element* d1 = body->QuerySelector("#d1");
- Element* d2 = body->QuerySelector("#d2");
- Element* d3 = body->QuerySelector("#d3");
- Element* d4 = body->QuerySelector("#d4");
- Element* d5 = body->QuerySelector("#d5");
- Element* d6 = body->QuerySelector("#d6");
-
- AttachOpenShadowRoot(*d1, shadow_html1);
- ShadowRoot* shadow_root1 = d1->OpenShadowRoot();
- Element* d11 = shadow_root1->QuerySelector("#d1-1");
- Element* d12 = shadow_root1->QuerySelector("#d1-2");
- Element* d13 = shadow_root1->QuerySelector("#d1-3");
- Element* d14 = shadow_root1->QuerySelector("#d1-4");
- Element* d1s0 = shadow_root1->QuerySelector("#d1-s0");
- Element* d1s1 = shadow_root1->QuerySelector("[name=d1-s1]");
- Element* d1s2 = shadow_root1->QuerySelector("[name=d1-s2]");
-
- AttachOpenShadowRoot(*d11, shadow_html2);
- ShadowRoot* shadow_root2 = d11->OpenShadowRoot();
- Element* d111 = shadow_root2->QuerySelector("#d1-1-1");
- Element* d112 = shadow_root2->QuerySelector("#d1-1-2");
- Element* d11s1 = shadow_root2->QuerySelector("[name=d1-1-s1]");
- Element* d11s2 = shadow_root2->QuerySelector("[name=d1-1-s2]");
-
- EXPECT_TRUE(d5);
- EXPECT_TRUE(d12);
- EXPECT_TRUE(d13);
- EXPECT_TRUE(d1s0);
- EXPECT_TRUE(d1s1);
- EXPECT_TRUE(d1s2);
- EXPECT_TRUE(d11s1);
- EXPECT_TRUE(d11s2);
-
- EXPECT_EQ(d11, FlatTreeTraversalNg::Next(*d1));
- EXPECT_EQ(d111, FlatTreeTraversalNg::Next(*d11));
- EXPECT_EQ(d11s1, FlatTreeTraversalNg::Next(*d111));
- EXPECT_EQ(d1s1, FlatTreeTraversalNg::Next(*d11s1));
- EXPECT_EQ(d2, FlatTreeTraversalNg::Next(*d1s1));
- EXPECT_EQ(d14, FlatTreeTraversalNg::Next(*d2));
- EXPECT_EQ(d11s2, FlatTreeTraversalNg::Next(*d14));
- EXPECT_EQ(d112, FlatTreeTraversalNg::Next(*d11s2));
- EXPECT_EQ(d6, FlatTreeTraversalNg::Next(*d112));
-
- EXPECT_EQ(d112, FlatTreeTraversalNg::Previous(*d6));
-
- EXPECT_EQ(d11, FlatTreeTraversalNg::Parent(*d111));
- EXPECT_EQ(d11, FlatTreeTraversalNg::Parent(*d112));
- EXPECT_EQ(d1s1, FlatTreeTraversalNg::Parent(*d2));
- EXPECT_EQ(d11s1, FlatTreeTraversalNg::Parent(*d14));
- EXPECT_EQ(d1s2, FlatTreeTraversalNg::Parent(*d3));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::Parent(*d4));
-}
-
-TEST_F(FlatTreeTraversalNgTest, v1SlotInDocumentTree) {
- const char* main_html =
- "<div id='parent'>"
- "<slot>"
- "<div id='child1'></div>"
- "<div id='child2'></div>"
- "</slot>"
- "</div>";
-
- SetupDocumentTree(main_html);
- Element* body = GetDocument().body();
- Element* parent = body->QuerySelector("#parent");
- Element* slot = body->QuerySelector("slot");
- Element* child1 = body->QuerySelector("#child1");
- Element* child2 = body->QuerySelector("#child2");
-
- EXPECT_EQ(slot, FlatTreeTraversalNg::FirstChild(*parent));
- EXPECT_EQ(child1, FlatTreeTraversalNg::FirstChild(*slot));
- EXPECT_EQ(child2, FlatTreeTraversalNg::NextSibling(*child1));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*child2));
- EXPECT_EQ(slot, FlatTreeTraversalNg::Parent(*child1));
- EXPECT_EQ(slot, FlatTreeTraversalNg::Parent(*child2));
- EXPECT_EQ(parent, FlatTreeTraversalNg::Parent(*slot));
-}
-
-TEST_F(FlatTreeTraversalNgTest, v1FallbackContent) {
- const char* main_html = "<div id='d1'></div>";
- const char* shadow_html =
- "<div id='before'></div>"
- "<slot><p>fallback content</p></slot>"
- "<div id='after'></div>";
-
- SetupDocumentTree(main_html);
-
- Element* body = GetDocument().body();
- Element* d1 = body->QuerySelector("#d1");
-
- AttachOpenShadowRoot(*d1, shadow_html);
- ShadowRoot* shadow_root = d1->OpenShadowRoot();
- Element* before = shadow_root->QuerySelector("#before");
- Element* after = shadow_root->QuerySelector("#after");
- Element* fallback_content = shadow_root->QuerySelector("p");
- Element* slot = shadow_root->QuerySelector("slot");
-
- EXPECT_EQ(before, FlatTreeTraversalNg::FirstChild(*d1));
- EXPECT_EQ(after, FlatTreeTraversalNg::LastChild(*d1));
- EXPECT_EQ(slot, FlatTreeTraversalNg::Parent(*fallback_content));
-
- EXPECT_EQ(slot, FlatTreeTraversalNg::NextSibling(*before));
- EXPECT_EQ(after, FlatTreeTraversalNg::NextSibling(*slot));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_content));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*after));
-
- EXPECT_EQ(slot, FlatTreeTraversalNg::PreviousSibling(*after));
- EXPECT_EQ(before, FlatTreeTraversalNg::PreviousSibling(*slot));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_content));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*before));
-}
-
-TEST_F(FlatTreeTraversalNgTest, v1FallbackContentSkippedInTraversal) {
- const char* main_html = "<div id='d1'><span></span></div>";
- const char* shadow_html =
- "<div id='before'></div>"
- "<slot><p>fallback content</p></slot>"
- "<div id='after'></div>";
-
- SetupDocumentTree(main_html);
-
- Element* body = GetDocument().body();
- Element* d1 = body->QuerySelector("#d1");
- Element* span = body->QuerySelector("span");
-
- AttachOpenShadowRoot(*d1, shadow_html);
- ShadowRoot* shadow_root = d1->OpenShadowRoot();
- Element* before = shadow_root->QuerySelector("#before");
- Element* after = shadow_root->QuerySelector("#after");
- Element* fallback_content = shadow_root->QuerySelector("p");
- Element* slot = shadow_root->QuerySelector("slot");
-
- EXPECT_EQ(before, FlatTreeTraversalNg::FirstChild(*d1));
- EXPECT_EQ(after, FlatTreeTraversalNg::LastChild(*d1));
- EXPECT_EQ(slot, FlatTreeTraversalNg::Parent(*span));
- EXPECT_EQ(d1, FlatTreeTraversalNg::Parent(*slot));
-
- EXPECT_EQ(slot, FlatTreeTraversalNg::NextSibling(*before));
- EXPECT_EQ(after, FlatTreeTraversalNg::NextSibling(*slot));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*after));
-
- EXPECT_EQ(slot, FlatTreeTraversalNg::PreviousSibling(*after));
- EXPECT_EQ(before, FlatTreeTraversalNg::PreviousSibling(*slot));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*before));
-
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::Parent(*fallback_content));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_content));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_content));
-}
-
-TEST_F(FlatTreeTraversalNgTest, v1AllFallbackContent) {
- const char* main_html = "<div id='d1'></div>";
- const char* shadow_html =
- "<slot name='a'><p id='x'>fallback content X</p></slot>"
- "<slot name='b'><p id='y'>fallback content Y</p></slot>"
- "<slot name='c'><p id='z'>fallback content Z</p></slot>";
-
- SetupDocumentTree(main_html);
-
- Element* body = GetDocument().body();
- Element* d1 = body->QuerySelector("#d1");
-
- AttachOpenShadowRoot(*d1, shadow_html);
- ShadowRoot* shadow_root = d1->OpenShadowRoot();
- Element* slot_a = shadow_root->QuerySelector("slot[name=a]");
- Element* slot_b = shadow_root->QuerySelector("slot[name=b]");
- Element* slot_c = shadow_root->QuerySelector("slot[name=c]");
- Element* fallback_x = shadow_root->QuerySelector("#x");
- Element* fallback_y = shadow_root->QuerySelector("#y");
- Element* fallback_z = shadow_root->QuerySelector("#z");
-
- EXPECT_EQ(slot_a, FlatTreeTraversalNg::FirstChild(*d1));
- EXPECT_EQ(slot_c, FlatTreeTraversalNg::LastChild(*d1));
-
- EXPECT_EQ(fallback_x, FlatTreeTraversalNg::FirstChild(*slot_a));
- EXPECT_EQ(fallback_y, FlatTreeTraversalNg::FirstChild(*slot_b));
- EXPECT_EQ(fallback_z, FlatTreeTraversalNg::FirstChild(*slot_c));
-
- EXPECT_EQ(slot_a, FlatTreeTraversalNg::Parent(*fallback_x));
- EXPECT_EQ(slot_b, FlatTreeTraversalNg::Parent(*fallback_y));
- EXPECT_EQ(slot_c, FlatTreeTraversalNg::Parent(*fallback_z));
- EXPECT_EQ(d1, FlatTreeTraversalNg::Parent(*slot_a));
-
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_x));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_y));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::NextSibling(*fallback_z));
-
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_z));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_y));
- EXPECT_EQ(nullptr, FlatTreeTraversalNg::PreviousSibling(*fallback_x));
-}
-
-} // namespace flat_tree_traversal_ng_test
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/ng/slot_assignment_engine.cc b/chromium/third_party/blink/renderer/core/dom/ng/slot_assignment_engine.cc
deleted file mode 100644
index ca067561cf2..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/ng/slot_assignment_engine.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/dom/ng/slot_assignment_engine.h"
-
-#include "third_party/blink/renderer/core/dom/shadow_root.h"
-#include "third_party/blink/renderer/core/dom/slot_assignment.h"
-
-namespace blink {
-
-SlotAssignmentEngine::SlotAssignmentEngine() {}
-
-void SlotAssignmentEngine::AddShadowRootNeedingRecalc(ShadowRoot& shadow_root) {
- DCHECK(shadow_root.isConnected());
- DCHECK(shadow_root.NeedsSlotAssignmentRecalc());
- shadow_roots_needing_recalc_.insert(&shadow_root);
-}
-
-void SlotAssignmentEngine::RemoveShadowRootNeedingRecalc(
- ShadowRoot& shadow_root) {
- DCHECK(shadow_root.isConnected());
- DCHECK(!shadow_root.NeedsSlotAssignmentRecalc());
- DCHECK(shadow_roots_needing_recalc_.Contains(&shadow_root));
- shadow_roots_needing_recalc_.erase(&shadow_root);
-}
-
-void SlotAssignmentEngine::Connected(ShadowRoot& shadow_root) {
- if (shadow_root.NeedsSlotAssignmentRecalc())
- AddShadowRootNeedingRecalc(shadow_root);
-}
-
-void SlotAssignmentEngine::Disconnected(ShadowRoot& shadow_root) {
- if (shadow_root.NeedsSlotAssignmentRecalc()) {
- DCHECK(shadow_roots_needing_recalc_.Contains(&shadow_root));
- shadow_roots_needing_recalc_.erase(&shadow_root);
- } else {
- DCHECK(!shadow_roots_needing_recalc_.Contains(&shadow_root));
- }
-}
-
-void SlotAssignmentEngine::RecalcSlotAssignments() {
- for (auto& shadow_root :
- HeapHashSet<WeakMember<ShadowRoot>>(shadow_roots_needing_recalc_)) {
- DCHECK(shadow_root->isConnected());
- DCHECK(shadow_root->NeedsSlotAssignmentRecalc());
- // SlotAssignment::RecalcAssignment() will remove its shadow root from
- // shadow_roots_needing_recalc_.
- shadow_root->GetSlotAssignment().RecalcAssignment();
- }
- DCHECK(shadow_roots_needing_recalc_.IsEmpty());
-}
-
-void SlotAssignmentEngine::Trace(blink::Visitor* visitor) {
- visitor->Trace(shadow_roots_needing_recalc_);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/ng/slot_assignment_engine.h b/chromium/third_party/blink/renderer/core/dom/ng/slot_assignment_engine.h
deleted file mode 100644
index baf12300833..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/ng/slot_assignment_engine.h
+++ /dev/null
@@ -1,37 +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_DOM_NG_SLOT_ASSIGNMENT_ENGINE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NG_SLOT_ASSIGNMENT_ENGINE_H_
-
-#include "third_party/blink/renderer/platform/heap/handle.h"
-
-namespace blink {
-
-class ShadowRoot;
-
-class SlotAssignmentEngine final
- : public GarbageCollected<SlotAssignmentEngine> {
- public:
- static SlotAssignmentEngine* Create() { return new SlotAssignmentEngine(); }
-
- void AddShadowRootNeedingRecalc(ShadowRoot&);
- void RemoveShadowRootNeedingRecalc(ShadowRoot&);
-
- void Connected(ShadowRoot&);
- void Disconnected(ShadowRoot&);
-
- void RecalcSlotAssignments();
-
- void Trace(blink::Visitor*);
-
- private:
- explicit SlotAssignmentEngine();
-
- HeapHashSet<WeakMember<ShadowRoot>> shadow_roots_needing_recalc_;
-};
-
-} // namespace blink
-
-#endif
diff --git a/chromium/third_party/blink/renderer/core/dom/ng/slot_assignment_test.cc b/chromium/third_party/blink/renderer/core/dom/ng/slot_assignment_test.cc
deleted file mode 100644
index e4b668c1820..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/ng/slot_assignment_test.cc
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
-
-#include "testing/gtest/include/gtest/gtest.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.h"
-#include "third_party/blink/renderer/core/dom/node_traversal.h"
-#include "third_party/blink/renderer/core/dom/shadow_root.h"
-#include "third_party/blink/renderer/core/html/html_collection.h"
-#include "third_party/blink/renderer/core/html/html_element.h"
-#include "third_party/blink/renderer/core/html/html_slot_element.h"
-#include "third_party/blink/renderer/core/testing/dummy_page_holder.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 {
-
-namespace {
-
-// Copy elements in HTMLCollection into a vector because HTMLCollection is a
-// live list and would be invalid if a mutation occurs.
-HeapVector<Member<Element>> CollectFromHTMLCollection(
- HTMLCollection& collection) {
- HeapVector<Member<Element>> elements;
- for (Element* element : collection)
- elements.push_back(element);
- return elements;
-}
-
-template <class T>
-HeapVector<Member<Node>> CollectFromIterable(T iterable) {
- HeapVector<Member<Node>> nodes;
- for (auto& node : iterable)
- nodes.push_back(&node);
- return nodes;
-}
-
-// Process Mini-DSL for Declarative Shadow DOM.
-
-// In Mini-DSL, <shadowroot> elements would behaves as if it were "Declarative
-// Shadow DOM". This is usuful for constructing a composed tree in testing.
-// Declarative Shadow DOM is under the dicussion. See
-// https://github.com/whatwg/dom/issues/510. Once Declarative Shadow DOM is
-// standardized and implemented, this DSL is no longer required.
-void ConvertDeclarativeShadowDOMToShadowRoot(Element& element) {
- HTMLCollection* shadow_root_collection =
- element.getElementsByTagName("shadowroot");
- if (!shadow_root_collection)
- return;
- for (Element* shadow_root :
- CollectFromHTMLCollection(*shadow_root_collection)) {
- Element* parent = shadow_root->parentElement();
- DCHECK(parent);
- parent->removeChild(shadow_root);
- ShadowRoot& attached_shadow_root =
- parent->AttachShadowRootInternal(ShadowRootType::kOpen);
- for (Node* child :
- CollectFromIterable(NodeTraversal::ChildrenOf(*shadow_root)))
- attached_shadow_root.AppendChild(child);
- }
-}
-
-void RemoveWhiteSpaceOnlyTextNode(ContainerNode& container) {
- for (Node* descendant :
- CollectFromIterable(NodeTraversal::InclusiveDescendantsOf(container))) {
- if (Text* text = ToTextOrNull(descendant)) {
- if (text->ContainsOnlyWhitespace())
- text->remove();
- } else if (Element* element = ToElementOrNull(descendant)) {
- if (ShadowRoot* shadow_root = element->OpenShadowRoot())
- RemoveWhiteSpaceOnlyTextNode(*shadow_root);
- }
- }
-}
-
-} // namespace
-
-class SlotAssignmentTest : public testing::Test,
- private ScopedIncrementalShadowDOMForTest {
- public:
- SlotAssignmentTest() : ScopedIncrementalShadowDOMForTest(true) {}
-
- protected:
- Document& GetDocument() const { return *document_; }
- void SetBody(const char* html);
-
- private:
- void SetUp() override;
-
- Persistent<Document> document_;
- std::unique_ptr<DummyPageHolder> dummy_page_holder_;
-};
-
-void SlotAssignmentTest::SetUp() {
- dummy_page_holder_ = DummyPageHolder::Create(IntSize(800, 600));
- document_ = &dummy_page_holder_->GetDocument();
- DCHECK(document_);
-}
-
-void SlotAssignmentTest::SetBody(const char* html) {
- Element* body = GetDocument().body();
- body->SetInnerHTMLFromString(String::FromUTF8(html));
- ConvertDeclarativeShadowDOMToShadowRoot(*body);
- RemoveWhiteSpaceOnlyTextNode(*body);
-}
-
-TEST_F(SlotAssignmentTest, DeclarativeShadowDOM) {
- SetBody(R"HTML(
- <div id=host>
- <shadowroot></shadowroot>
- </div>
- )HTML");
-
- Element* host = GetDocument().QuerySelector("#host");
- ASSERT_NE(nullptr, host);
- ASSERT_NE(nullptr, host->OpenShadowRoot());
-}
-
-TEST_F(SlotAssignmentTest, NestedDeclarativeShadowDOM) {
- SetBody(R"HTML(
- <div id=host1>
- <shadowroot>
- <div id=host2>
- <shadowroot></shadowroot>
- </div>
- </shadowroot>
- </div>
- )HTML");
-
- Element* host1 = GetDocument().QuerySelector("#host1");
- ASSERT_NE(nullptr, host1);
- ShadowRoot* shadow_root1 = host1->OpenShadowRoot();
- ASSERT_NE(nullptr, shadow_root1);
-
- Element* host2 = shadow_root1->QuerySelector("#host2");
- ASSERT_NE(nullptr, host2);
- ShadowRoot* shadow_root2 = host2->OpenShadowRoot();
- ASSERT_NE(nullptr, shadow_root2);
-}
-
-TEST_F(SlotAssignmentTest, AssignedNodesAreSet) {
- SetBody(R"HTML(
- <div id=host>
- <shadowroot>
- <slot></slot>
- </shadowroot>
- <div id='host-child'></div>
- </div>
- )HTML");
-
- Element* host = GetDocument().QuerySelector("#host");
- Element* host_child = GetDocument().QuerySelector("#host-child");
- ShadowRoot* shadow_root = host->OpenShadowRoot();
- HTMLSlotElement* slot =
- ToHTMLSlotElementOrNull(shadow_root->QuerySelector("slot"));
- ASSERT_NE(nullptr, slot);
-
- EXPECT_EQ(slot, host_child->AssignedSlot());
- HeapVector<Member<Node>> expected_nodes;
- expected_nodes.push_back(host_child);
- EXPECT_EQ(expected_nodes, slot->AssignedNodes());
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/node.cc b/chromium/third_party/blink/renderer/core/dom/node.cc
index ca47b2d0969..5629f817085 100644
--- a/chromium/third_party/blink/renderer/core/dom/node.cc
+++ b/chromium/third_party/blink/renderer/core/dom/node.cc
@@ -26,14 +26,14 @@
#include "third_party/blink/renderer/core/dom/node.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/node_or_string.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/css/css_selector.h"
#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/dom/attr.h"
#include "third_party/blink/renderer/core/dom/attribute.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/child_list_mutation_scope.h"
#include "third_party/blink/renderer/core/dom/child_node_list.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -44,13 +44,13 @@
#include "third_party/blink/renderer/core/dom/element_rare_data.h"
#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/events/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/dom/events/event_dispatcher.h"
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/dom/get_root_node_options.h"
#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
-#include "third_party/blink/renderer/core/dom/ng/slot_assignment_engine.h"
+#include "third_party/blink/renderer/core/dom/mutation_observer_registration.h"
#include "third_party/blink/renderer/core/dom/node_lists_node_data.h"
#include "third_party/blink/renderer/core/dom/node_rare_data.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
@@ -58,6 +58,7 @@
#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/dom/slot_assignment.h"
+#include "third_party/blink/renderer/core/dom/slot_assignment_engine.h"
#include "third_party/blink/renderer/core/dom/static_node_list.h"
#include "third_party/blink/renderer/core/dom/template_content_document_fragment.h"
#include "third_party/blink/renderer/core/dom/text.h"
@@ -100,10 +101,10 @@
#include "third_party/blink/renderer/core/svg/graphics/svg_image.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/microtask.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable_visitor.h"
#include "third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h"
-#include "third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/platform/instance_counters.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h"
@@ -154,6 +155,7 @@ NodeRenderingData::~NodeRenderingData() {
void NodeRenderingData::SetNonAttachedStyle(
scoped_refptr<ComputedStyle> non_attached_style) {
DCHECK_NE(&SharedEmptyData(), this);
+ DCHECK(!non_attached_style || !non_attached_style_);
non_attached_style_ = non_attached_style;
}
@@ -355,6 +357,16 @@ void Node::setNodeValue(const String&) {
// By default, setting nodeValue has no effect.
}
+ContainerNode* Node::parentNode() const {
+ return IsShadowRoot() ? nullptr : ParentOrShadowHostNode();
+}
+
+ContainerNode* Node::ParentNodeWithCounting() const {
+ if (GetFlag(kInDOMNodeRemovedHandler))
+ GetDocument().CountDetachingNodeAccessInDOMNodeRemovedHandler();
+ return IsShadowRoot() ? nullptr : ParentOrShadowHostNode();
+}
+
NodeList* Node::childNodes() {
ThreadState::MainThreadGCForbiddenScope gc_forbidden;
if (IsContainerNode())
@@ -437,7 +449,8 @@ Node* Node::insertBefore(Node* new_child,
exception_state);
exception_state.ThrowDOMException(
- kHierarchyRequestError, "This node type does not support this method.");
+ DOMExceptionCode::kHierarchyRequestError,
+ "This node type does not support this method.");
return nullptr;
}
@@ -453,7 +466,8 @@ Node* Node::replaceChild(Node* new_child,
exception_state);
exception_state.ThrowDOMException(
- kHierarchyRequestError, "This node type does not support this method.");
+ DOMExceptionCode::kHierarchyRequestError,
+ "This node type does not support this method.");
return nullptr;
}
@@ -466,7 +480,8 @@ Node* Node::removeChild(Node* old_child, ExceptionState& exception_state) {
return ToContainerNode(this)->RemoveChild(old_child, exception_state);
exception_state.ThrowDOMException(
- kNotFoundError, "This node type does not support this method.");
+ DOMExceptionCode::kNotFoundError,
+ "This node type does not support this method.");
return nullptr;
}
@@ -479,7 +494,8 @@ Node* Node::appendChild(Node* new_child, ExceptionState& exception_state) {
return ToContainerNode(this)->AppendChild(new_child, exception_state);
exception_state.ThrowDOMException(
- kHierarchyRequestError, "This node type does not support this method.");
+ DOMExceptionCode::kHierarchyRequestError,
+ "This node type does not support this method.");
return nullptr;
}
@@ -606,7 +622,7 @@ Node* Node::cloneNode(bool deep, ExceptionState& exception_state) const {
// 1. If context object is a shadow root, then throw a
// "NotSupportedError" DOMException.
if (IsShadowRoot()) {
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"ShadowRoot nodes are not clonable.");
return nullptr;
}
@@ -942,11 +958,6 @@ bool Node::IsInert() const {
DCHECK(!ChildNeedsDistributionRecalc());
if (this != GetDocument()) {
- // TODO(foolip): When fullscreen uses top layer, this can be simplified to
- // just look at the topmost element in top layer. https://crbug.com/240576.
- // Note: It's currently appropriate that a modal dialog element takes
- // precedence over a fullscreen element, because it will be rendered on top,
- // but with fullscreen merged into top layer that will no longer be true.
const Element* modal_element = GetDocument().ActiveModalDialog();
if (!modal_element)
modal_element = Fullscreen::FullscreenElementFrom(GetDocument());
@@ -2114,7 +2125,7 @@ static inline void CollectMatchingObserversForMutation(
observers,
Registry* registry,
Node& target,
- MutationObserver::MutationType type,
+ MutationType type,
const QualifiedName* attribute_name) {
if (!registry)
return;
@@ -2135,9 +2146,9 @@ static inline void CollectMatchingObserversForMutation(
void Node::GetRegisteredMutationObserversOfType(
HeapHashMap<Member<MutationObserver>, MutationRecordDeliveryOptions>&
observers,
- MutationObserver::MutationType type,
+ MutationType type,
const QualifiedName* attribute_name) {
- DCHECK((type == MutationObserver::kAttributes && attribute_name) ||
+ DCHECK((type == kMutationTypeAttributes && attribute_name) ||
!attribute_name);
CollectMatchingObserversForMutation(observers, MutationObserverRegistry(),
*this, type, attribute_name);
@@ -2472,7 +2483,29 @@ void Node::DefaultEventHandler(Event* event) {
}
}
-void Node::WillCallDefaultEventHandler(const Event&) {}
+void Node::WillCallDefaultEventHandler(const Event& event) {
+ if (!event.IsKeyboardEvent())
+ return;
+
+ if (!IsFocused() || GetDocument().LastFocusType() != kWebFocusTypeMouse)
+ return;
+
+ if (event.type() != EventTypeNames::keydown ||
+ GetDocument().HadKeyboardEvent())
+ return;
+
+ GetDocument().SetHadKeyboardEvent(true);
+
+ // Changes to HadKeyboardEvent may affect :focus-visible matching,
+ // ShouldHaveFocusAppearance and LayoutTheme::IsFocused().
+ // Inform LayoutTheme if HadKeyboardEvent changes.
+ if (GetLayoutObject()) {
+ GetLayoutObject()->InvalidateIfControlStateChanged(kFocusControlState);
+
+ if (RuntimeEnabledFeatures::CSSFocusVisibleEnabled() && IsContainerNode())
+ ToContainerNode(*this).FocusVisibleStateChanged();
+ }
+}
bool Node::HasActivationBehavior() const {
return false;
@@ -2562,6 +2595,8 @@ HTMLSlotElement* Node::assignedSlotForBinding() {
}
void Node::SetFocused(bool flag, WebFocusType focus_type) {
+ if (!flag || focus_type == kWebFocusTypeMouse)
+ GetDocument().SetHadKeyboardEvent(false);
GetDocument().UserActionElements().SetFocused(this, flag);
}
@@ -2569,10 +2604,6 @@ void Node::SetHasFocusWithin(bool flag) {
GetDocument().UserActionElements().SetHasFocusWithin(this, flag);
}
-void Node::SetWasFocusedByMouse(bool flag) {
- GetDocument().UserActionElements().SetWasFocusedByMouse(this, flag);
-}
-
void Node::SetActive(bool flag) {
GetDocument().UserActionElements().SetActive(this, flag);
}
@@ -2615,11 +2646,6 @@ bool Node::IsUserActionElementHasFocusWithin() const {
return GetDocument().UserActionElements().HasFocusWithin(this);
}
-bool Node::IsUserActionElementWasFocusedByMouse() const {
- DCHECK(IsUserActionElement());
- return GetDocument().UserActionElements().WasFocusedByMouse(this);
-}
-
void Node::SetCustomElementState(CustomElementState new_state) {
CustomElementState old_state = GetCustomElementState();
@@ -2754,23 +2780,12 @@ void Node::Trace(blink::Visitor* visitor) {
// rareData() and data_.node_layout_data_ share their storage. We have to
// trace only one of them.
if (HasRareData())
- visitor->Trace(RareData());
- visitor->Trace(GetEventTargetData());
+ visitor->TraceWithWrappers(RareData());
+ visitor->TraceWithWrappers(GetEventTargetData());
visitor->Trace(tree_scope_);
EventTarget::Trace(visitor);
}
-void Node::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(parent_or_shadow_host_node_);
- visitor->TraceWrappers(previous_);
- visitor->TraceWrappers(next_);
- if (HasRareData())
- visitor->TraceWrappersWithManualWriteBarrier(RareData());
- visitor->TraceWrappersWithManualWriteBarrier(
- const_cast<Node*>(this)->GetEventTargetData());
- EventTarget::TraceWrappers(visitor);
-}
-
} // namespace blink
#ifndef NDEBUG
diff --git a/chromium/third_party/blink/renderer/core/dom/node.h b/chromium/third_party/blink/renderer/core/dom/node.h
index 9b184a405ea..302eb60891c 100644
--- a/chromium/third_party/blink/renderer/core/dom/node.h
+++ b/chromium/third_party/blink/renderer/core/dom/node.h
@@ -31,7 +31,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/dom/events/simulated_click_options.h"
-#include "third_party/blink/renderer/core/dom/mutation_observer.h"
+#include "third_party/blink/renderer/core/dom/mutation_observer_options.h"
#include "third_party/blink/renderer/core/dom/node_rare_data.h"
#include "third_party/blink/renderer/core/dom/tree_scope.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
@@ -58,6 +58,8 @@ class KURL;
class LayoutBox;
class LayoutBoxModelObject;
class LayoutObject;
+class MutationObserver;
+class MutationObserverRegistration;
class NodeList;
class NodeListsNodeData;
class NodeOrString;
@@ -76,10 +78,17 @@ class WebPluginContainerImpl;
const int kNodeStyleChangeShift = 18;
const int kNodeCustomElementShift = 20;
+// Values for kChildNeedsStyleRecalcFlag, controlling whether a node gets its
+// style recalculated.
enum StyleChangeType {
+ // This node does not need style recalculation.
kNoStyleChange = 0,
+ // This node needs style recalculation.
kLocalStyleChange = 1 << kNodeStyleChangeShift,
+ // This node and all of its flat-tree descendeants need style recalculation.
kSubtreeStyleChange = 2 << kNodeStyleChangeShift,
+ // This node and all of its descendants are detached and need style
+ // recalculation.
kNeedsReattachStyleChange = 3 << kNodeStyleChangeShift,
};
@@ -172,6 +181,7 @@ class CORE_EXPORT Node : public EventTarget {
virtual void setNodeValue(const String&);
virtual NodeType getNodeType() const = 0;
ContainerNode* parentNode() const;
+ ContainerNode* ParentNodeWithCounting() const;
Element* parentElement() const;
ContainerNode* ParentElementOrShadowRoot() const;
ContainerNode* ParentElementOrDocumentFragment() const;
@@ -397,19 +407,24 @@ class CORE_EXPORT Node : public EventTarget {
bool HasFocusWithin() const {
return IsUserActionElement() && IsUserActionElementHasFocusWithin();
}
- bool WasFocusedByMouse() const {
- return IsUserActionElement() && IsUserActionElementWasFocusedByMouse();
- }
bool NeedsAttach() const {
return GetStyleChangeType() == kNeedsReattachStyleChange;
}
+ // True if the style recalc process should recalculate style for this node.
bool NeedsStyleRecalc() const {
- return GetStyleChangeType() != kNoStyleChange;
+ // We do not ClearNeedsStyleRecalc() if the recalc triggers a layout re-
+ // attachment (see Element::RecalcStyle()). In order to avoid doing an extra
+ // StyleForLayoutObject for slotted elements, also check if we have been
+ // marked for re-attachment (which mean we have already gone through
+ // RecalcStyleForReattachment as a slot-assigned element).
+ return GetStyleChangeType() != kNoStyleChange && !NeedsReattachLayoutTree();
}
StyleChangeType GetStyleChangeType() const {
return static_cast<StyleChangeType>(node_flags_ & kStyleChangeMask);
}
+ // True if the style recalculation process should traverse this node's
+ // children when looking for nodes that need recalculation.
bool ChildNeedsStyleRecalc() const {
return GetFlag(kChildNeedsStyleRecalcFlag);
}
@@ -426,6 +441,8 @@ class CORE_EXPORT Node : public EventTarget {
void SetChildNeedsStyleRecalc() { SetFlag(kChildNeedsStyleRecalcFlag); }
void ClearChildNeedsStyleRecalc() { ClearFlag(kChildNeedsStyleRecalcFlag); }
+ // Sets the flag for the current node and also calls
+ // MarkAncestorsWithChildNeedsStyleRecalc
void SetNeedsStyleRecalc(StyleChangeType, const StyleChangeReasonForTracing&);
void ClearNeedsStyleRecalc();
@@ -461,6 +478,8 @@ class CORE_EXPORT Node : public EventTarget {
}
void MarkAncestorsWithChildNeedsDistributionRecalc();
+ // True if the style invalidation process should traverse this node's children
+ // when looking for pending invalidations.
bool ChildNeedsStyleInvalidation() const {
return GetFlag(kChildNeedsStyleInvalidationFlag);
}
@@ -471,10 +490,14 @@ class CORE_EXPORT Node : public EventTarget {
ClearFlag(kChildNeedsStyleInvalidationFlag);
}
void MarkAncestorsWithChildNeedsStyleInvalidation();
+
+ // True if there are pending invalidations against this node.
bool NeedsStyleInvalidation() const {
return GetFlag(kNeedsStyleInvalidationFlag);
}
void ClearNeedsStyleInvalidation() { ClearFlag(kNeedsStyleInvalidationFlag); }
+ // Sets the flag for the current node and also calls
+ // MarkAncestorsWithChildNeedsStyleInvalidation
void SetNeedsStyleInvalidation();
// This needs to be called before using FlatTreeTraversal.
@@ -514,7 +537,6 @@ class CORE_EXPORT Node : public EventTarget {
virtual void SetActive(bool flag = true);
virtual void SetDragged(bool flag);
virtual void SetHovered(bool flag = true);
- void SetWasFocusedByMouse(bool flag);
virtual int tabIndex() const;
@@ -785,7 +807,7 @@ class CORE_EXPORT Node : public EventTarget {
void GetRegisteredMutationObserversOfType(
HeapHashMap<Member<MutationObserver>, MutationRecordDeliveryOptions>&,
- MutationObserver::MutationType,
+ MutationType,
const QualifiedName* attribute_name);
void RegisterMutationObserver(MutationObserver&,
MutationObserverOptions,
@@ -821,13 +843,18 @@ class CORE_EXPORT Node : public EventTarget {
return GetFlag(kHasDuplicateAttributes);
}
+ void SetInDOMNodeRemovedHandler(bool flag) {
+ SetFlag(flag, kInDOMNodeRemovedHandler);
+ }
+ bool InDOMNodeRemovedHandler() const {
+ return GetFlag(kInDOMNodeRemovedHandler);
+ }
+
// If the node is a plugin, then this returns its WebPluginContainer.
WebPluginContainerImpl* GetWebPluginContainer() const;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
private:
enum NodeFlags {
kHasRareDataFlag = 1,
@@ -878,11 +905,14 @@ class CORE_EXPORT Node : public EventTarget {
kHasDuplicateAttributes = 1 << 28,
+ // Temporary flag for some UseCounter items. crbug.com/859391.
+ kInDOMNodeRemovedHandler = 1 << 29,
+
kDefaultNodeFlags =
kIsFinishedParsingChildrenFlag | kNeedsReattachStyleChange
};
- // 4 bits remaining.
+ // 3 bits remaining.
bool GetFlag(NodeFlags mask) const { return node_flags_ & mask; }
void SetFlag(bool f, NodeFlags mask) {
@@ -968,7 +998,6 @@ class CORE_EXPORT Node : public EventTarget {
bool IsUserActionElementHovered() const;
bool IsUserActionElementFocused() const;
bool IsUserActionElementHasFocusWithin() const;
- bool IsUserActionElementWasFocusedByMouse() const;
void UpdateDistributionInternal();
void RecalcDistribution();
@@ -1012,10 +1041,6 @@ inline ContainerNode* Node::ParentOrShadowHostNode() const {
return reinterpret_cast<ContainerNode*>(parent_or_shadow_host_node_.Get());
}
-inline ContainerNode* Node::parentNode() const {
- return IsShadowRoot() ? nullptr : ParentOrShadowHostNode();
-}
-
inline void Node::LazyReattachIfAttached() {
if (NeedsAttach())
return;
@@ -1030,6 +1055,8 @@ inline void Node::LazyReattachIfAttached() {
}
inline bool Node::ShouldCallRecalcStyle(StyleRecalcChange change) {
+ if (NeedsReattachLayoutTree())
+ return false;
return change >= kIndependentInherit || NeedsStyleRecalc() ||
ChildNeedsStyleRecalc();
}
diff --git a/chromium/third_party/blink/renderer/core/dom/node.idl b/chromium/third_party/blink/renderer/core/dom/node.idl
index 8b772b98029..bc3277043de 100644
--- a/chromium/third_party/blink/renderer/core/dom/node.idl
+++ b/chromium/third_party/blink/renderer/core/dom/node.idl
@@ -40,7 +40,7 @@ interface Node : EventTarget {
[Affects=Nothing, Measure] readonly attribute boolean isConnected;
[Affects=Nothing, PerWorldBindings] readonly attribute Document? ownerDocument;
- [Affects=Nothing, PerWorldBindings] readonly attribute Node? parentNode;
+ [Affects=Nothing, PerWorldBindings, ImplementedAs=ParentNodeWithCounting] readonly attribute Node? parentNode;
[Affects=Nothing, PerWorldBindings] readonly attribute Element? parentElement;
[Affects=Nothing, ImplementedAs=hasChildren] boolean hasChildNodes();
[Affects=Nothing, SameObject, PerWorldBindings] readonly attribute NodeList childNodes;
diff --git a/chromium/third_party/blink/renderer/core/dom/node_child_removal_tracker.h b/chromium/third_party/blink/renderer/core/dom/node_child_removal_tracker.h
index 40e4a2fae9b..aa3456ec63f 100644
--- a/chromium/third_party/blink/renderer/core/dom/node_child_removal_tracker.h
+++ b/chromium/third_party/blink/renderer/core/dom/node_child_removal_tracker.h
@@ -27,6 +27,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NODE_CHILD_REMOVAL_TRACKER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NODE_CHILD_REMOVAL_TRACKER_H_
+#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -49,7 +50,7 @@ class NodeChildRemovalTracker {
// Using raw pointers are safe because these NodeChildRemovalTrackers are
// guaranteed to be on a stack.
NodeChildRemovalTracker* previous_;
- static NodeChildRemovalTracker* last_;
+ CORE_EXPORT static NodeChildRemovalTracker* last_;
};
inline NodeChildRemovalTracker::NodeChildRemovalTracker(Node& node)
diff --git a/chromium/third_party/blink/renderer/core/dom/node_iterator.cc b/chromium/third_party/blink/renderer/core/dom/node_iterator.cc
index 2bcd8a6fe6a..eae9578a213 100644
--- a/chromium/third_party/blink/renderer/core/dom/node_iterator.cc
+++ b/chromium/third_party/blink/renderer/core/dom/node_iterator.cc
@@ -24,11 +24,11 @@
#include "third_party/blink/renderer/core/dom/node_iterator.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_node_filter.h"
#include "third_party/blink/renderer/core/dom/attr.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -206,9 +206,4 @@ void NodeIterator::Trace(blink::Visitor* visitor) {
NodeIteratorBase::Trace(visitor);
}
-void NodeIterator::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- ScriptWrappable::TraceWrappers(visitor);
- NodeIteratorBase::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/node_iterator.h b/chromium/third_party/blink/renderer/core/dom/node_iterator.h
index be7d1ac8500..8fb47a744d7 100644
--- a/chromium/third_party/blink/renderer/core/dom/node_iterator.h
+++ b/chromium/third_party/blink/renderer/core/dom/node_iterator.h
@@ -58,8 +58,6 @@ class NodeIterator final : public ScriptWrappable, public NodeIteratorBase {
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
private:
NodeIterator(Node*, unsigned what_to_show, V8NodeFilter*);
diff --git a/chromium/third_party/blink/renderer/core/dom/node_iterator_base.cc b/chromium/third_party/blink/renderer/core/dom/node_iterator_base.cc
index 1f5d0f84031..6835dd716e4 100644
--- a/chromium/third_party/blink/renderer/core/dom/node_iterator_base.cc
+++ b/chromium/third_party/blink/renderer/core/dom/node_iterator_base.cc
@@ -24,10 +24,11 @@
#include "third_party/blink/renderer/core/dom/node_iterator_base.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_node_filter.h"
#include "third_party/blink/renderer/core/dom/node.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -45,7 +46,7 @@ unsigned NodeIteratorBase::AcceptNode(Node* node,
if (active_flag_) {
// 1. If the active flag is set, then throw an "InvalidStateError"
// DOMException.
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Filter function can't be recursive");
return V8NodeFilter::FILTER_REJECT;
}
@@ -92,8 +93,4 @@ void NodeIteratorBase::Trace(blink::Visitor* visitor) {
visitor->Trace(filter_);
}
-void NodeIteratorBase::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(filter_);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/node_iterator_base.h b/chromium/third_party/blink/renderer/core/dom/node_iterator_base.h
index d860ce06718..d58dcf604cc 100644
--- a/chromium/third_party/blink/renderer/core/dom/node_iterator_base.h
+++ b/chromium/third_party/blink/renderer/core/dom/node_iterator_base.h
@@ -43,7 +43,6 @@ class NodeIteratorBase : public GarbageCollectedMixin {
V8NodeFilter* filter() const { return filter_.Get(); }
void Trace(blink::Visitor*) override;
- virtual void TraceWrappers(ScriptWrappableVisitor*) const;
protected:
NodeIteratorBase(Node*, unsigned what_to_show, V8NodeFilter*);
diff --git a/chromium/third_party/blink/renderer/core/dom/node_lists_node_data.cc b/chromium/third_party/blink/renderer/core/dom/node_lists_node_data.cc
index 6e2dc541852..dfa31e4f94d 100644
--- a/chromium/third_party/blink/renderer/core/dom/node_lists_node_data.cc
+++ b/chromium/third_party/blink/renderer/core/dom/node_lists_node_data.cc
@@ -51,14 +51,4 @@ void NodeListsNodeData::Trace(blink::Visitor* visitor) {
visitor->Trace(tag_collection_ns_caches_);
}
-void NodeListsNodeData::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(child_node_list_);
- for (const auto list : atomic_name_caches_.Values()) {
- visitor->TraceWrappers(list);
- }
- for (const auto list : tag_collection_ns_caches_.Values()) {
- visitor->TraceWrappers(list);
- }
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/node_lists_node_data.h b/chromium/third_party/blink/renderer/core/dom/node_lists_node_data.h
index 1c73525009d..74ee59eb2e7 100644
--- a/chromium/third_party/blink/renderer/core/dom/node_lists_node_data.h
+++ b/chromium/third_party/blink/renderer/core/dom/node_lists_node_data.h
@@ -171,7 +171,6 @@ class NodeListsNodeData final : public GarbageCollected<NodeListsNodeData> {
}
void Trace(blink::Visitor*);
- void TraceWrappers(ScriptWrappableVisitor*) const;
private:
NodeListsNodeData() : child_node_list_(nullptr) {}
@@ -183,8 +182,6 @@ class NodeListsNodeData final : public GarbageCollected<NodeListsNodeData> {
DISALLOW_COPY_AND_ASSIGN(NodeListsNodeData);
};
-DEFINE_TRAIT_FOR_TRACE_WRAPPERS(NodeListsNodeData);
-
template <typename Collection>
inline Collection* ContainerNode::EnsureCachedCollection(CollectionType type) {
ThreadState::MainThreadGCForbiddenScope gc_forbidden;
diff --git a/chromium/third_party/blink/renderer/core/dom/node_rare_data.cc b/chromium/third_party/blink/renderer/core/dom/node_rare_data.cc
index 12d79e65269..db3b785ad31 100644
--- a/chromium/third_party/blink/renderer/core/dom/node_rare_data.cc
+++ b/chromium/third_party/blink/renderer/core/dom/node_rare_data.cc
@@ -33,6 +33,7 @@
#include "third_party/blink/renderer/core/dom/container_node.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/element_rare_data.h"
+#include "third_party/blink/renderer/core/dom/mutation_observer_registration.h"
#include "third_party/blink/renderer/core/dom/node_lists_node_data.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable_visitor.h"
@@ -46,9 +47,40 @@ struct SameSizeAsNodeRareData {
unsigned bitfields_;
};
+NodeMutationObserverData* NodeMutationObserverData::Create() {
+ return new NodeMutationObserverData;
+}
+
static_assert(sizeof(NodeRareData) == sizeof(SameSizeAsNodeRareData),
"NodeRareData should stay small");
+void NodeMutationObserverData::Trace(blink::Visitor* visitor) {
+ visitor->Trace(registry_);
+ visitor->Trace(transient_registry_);
+}
+
+void NodeMutationObserverData::AddTransientRegistration(
+ MutationObserverRegistration* registration) {
+ transient_registry_.insert(registration);
+}
+
+void NodeMutationObserverData::RemoveTransientRegistration(
+ MutationObserverRegistration* registration) {
+ DCHECK(transient_registry_.Contains(registration));
+ transient_registry_.erase(registration);
+}
+
+void NodeMutationObserverData::AddRegistration(
+ MutationObserverRegistration* registration) {
+ registry_.push_back(registration);
+}
+
+void NodeMutationObserverData::RemoveRegistration(
+ MutationObserverRegistration* registration) {
+ DCHECK(registry_.Contains(registration));
+ registry_.EraseAt(registry_.Find(registration));
+}
+
void NodeRareData::TraceAfterDispatch(blink::Visitor* visitor) {
visitor->Trace(mutation_observer_data_);
// Do not keep empty NodeListsNodeData objects around.
@@ -65,20 +97,6 @@ void NodeRareData::Trace(blink::Visitor* visitor) {
TraceAfterDispatch(visitor);
}
-void NodeRareData::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- if (is_element_rare_data_)
- static_cast<const ElementRareData*>(this)->TraceWrappersAfterDispatch(
- visitor);
- else
- TraceWrappersAfterDispatch(visitor);
-}
-
-void NodeRareData::TraceWrappersAfterDispatch(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(node_lists_);
- visitor->TraceWrappers(mutation_observer_data_);
-}
-
void NodeRareData::FinalizeGarbageCollectedObject() {
if (is_element_rare_data_)
static_cast<ElementRareData*>(this)->~ElementRareData();
diff --git a/chromium/third_party/blink/renderer/core/dom/node_rare_data.h b/chromium/third_party/blink/renderer/core/dom/node_rare_data.h
index 03589702a45..6e546271d69 100644
--- a/chromium/third_party/blink/renderer/core/dom/node_rare_data.h
+++ b/chromium/third_party/blink/renderer/core/dom/node_rare_data.h
@@ -23,7 +23,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NODE_RARE_DATA_H_
#include "base/macros.h"
-#include "third_party/blink/renderer/core/dom/mutation_observer_registration.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
@@ -34,14 +33,13 @@ class ComputedStyle;
enum class DynamicRestyleFlags;
enum class ElementFlags;
class LayoutObject;
+class MutationObserverRegistration;
class NodeListsNodeData;
class NodeMutationObserverData final
: public GarbageCollected<NodeMutationObserverData> {
public:
- static NodeMutationObserverData* Create() {
- return new NodeMutationObserverData;
- }
+ static NodeMutationObserverData* Create();
const HeapVector<TraceWrapperMember<MutationObserverRegistration>>&
Registry() {
@@ -53,37 +51,12 @@ class NodeMutationObserverData final
return transient_registry_;
}
- void AddTransientRegistration(MutationObserverRegistration* registration) {
- transient_registry_.insert(registration);
- }
+ void AddTransientRegistration(MutationObserverRegistration* registration);
+ void RemoveTransientRegistration(MutationObserverRegistration* registration);
+ void AddRegistration(MutationObserverRegistration* registration);
+ void RemoveRegistration(MutationObserverRegistration* registration);
- void RemoveTransientRegistration(MutationObserverRegistration* registration) {
- DCHECK(transient_registry_.Contains(registration));
- transient_registry_.erase(registration);
- }
-
- void AddRegistration(MutationObserverRegistration* registration) {
- registry_.push_back(registration);
- }
-
- void RemoveRegistration(MutationObserverRegistration* registration) {
- DCHECK(registry_.Contains(registration));
- registry_.EraseAt(registry_.Find(registration));
- }
-
- void Trace(blink::Visitor* visitor) {
- visitor->Trace(registry_);
- visitor->Trace(transient_registry_);
- }
-
- void TraceWrappers(ScriptWrappableVisitor* visitor) const {
- for (auto registration : registry_) {
- visitor->TraceWrappers(registration);
- }
- for (auto registration : transient_registry_) {
- visitor->TraceWrappers(registration);
- }
- }
+ void Trace(blink::Visitor* visitor);
private:
NodeMutationObserverData() = default;
@@ -94,8 +67,6 @@ class NodeMutationObserverData final
DISALLOW_COPY_AND_ASSIGN(NodeMutationObserverData);
};
-DEFINE_TRAIT_FOR_TRACE_WRAPPERS(NodeMutationObserverData);
-
class NodeRenderingData {
public:
explicit NodeRenderingData(LayoutObject*,
@@ -206,13 +177,9 @@ class NodeRareData : public GarbageCollectedFinalized<NodeRareData>,
};
void Trace(blink::Visitor*);
-
void TraceAfterDispatch(blink::Visitor*);
void FinalizeGarbageCollectedObject();
- void TraceWrappers(ScriptWrappableVisitor*) const;
- void TraceWrappersAfterDispatch(ScriptWrappableVisitor*) const;
-
protected:
explicit NodeRareData(NodeRenderingData* node_layout_data)
: NodeRareDataBase(node_layout_data),
@@ -238,8 +205,6 @@ class NodeRareData : public GarbageCollectedFinalized<NodeRareData>,
DISALLOW_COPY_AND_ASSIGN(NodeRareData);
};
-DEFINE_TRAIT_FOR_TRACE_WRAPPERS(NodeRareData);
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_NODE_RARE_DATA_H_
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 054d47998d9..4e2a57ef638 100644
--- a/chromium/third_party/blink/renderer/core/dom/node_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/node_test.cc
@@ -8,6 +8,7 @@
#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/flat_tree_traversal.h"
+#include "third_party/blink/renderer/core/dom/layout_tree_builder.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/dom/shadow_root_init.h"
#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
@@ -37,8 +38,10 @@ class NodeTest : public EditingTestBase {
GetDocument().documentElement()->RecalcStyle(kNoChange);
PushSelectorFilterAncestors(
GetDocument().EnsureStyleResolver().GetSelectorFilter(), node);
+ ReattachLegacyLayoutObjectList legacy_objects(GetDocument());
Node::AttachContext context;
node.ReattachLayoutTree(context);
+ legacy_objects.ForceLegacyLayoutIfNeeded();
return context.previous_in_flow;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/pausable_object.h b/chromium/third_party/blink/renderer/core/dom/pausable_object.h
index 50c2b62d81e..304f429f468 100644
--- a/chromium/third_party/blink/renderer/core/dom/pausable_object.h
+++ b/chromium/third_party/blink/renderer/core/dom/pausable_object.h
@@ -33,6 +33,24 @@
namespace blink {
+// A PausableObject responds to situations where Blink is running a nested event
+// loop. At such times, the page should be responsive, but only in a limited
+// sense: the browser should redraw the page as necessary, but should not run
+// timer callbacks, finish promise resolution, fire events, or perform other
+// activity, especially activity which may run script.
+//
+// Pausing can happen in cases such as:
+// - modal dialogs during script execution (e.g. window.alert, window.print)
+// - script execution stopped at a debugger breakpoint
+//
+// The scheduler will automatically suspend certain task queues for the duration
+// that the page is paused.
+//
+// Objects with asynchronous activity, especially activity that may have an
+// observable effect on web-visible state, on should suspend that activity while
+// the page is paused by overriding Pause() and Unpause().
+//
+// https://html.spec.whatwg.org/multipage/webappapis.html#pause
class CORE_EXPORT PausableObject : public ContextLifecycleObserver {
public:
explicit PausableObject(ExecutionContext*);
diff --git a/chromium/third_party/blink/renderer/core/dom/pseudo_element.cc b/chromium/third_party/blink/renderer/core/dom/pseudo_element.cc
index 3f08801d336..ac5aae97a88 100644
--- a/chromium/third_party/blink/renderer/core/dom/pseudo_element.cc
+++ b/chromium/third_party/blink/renderer/core/dom/pseudo_element.cc
@@ -29,6 +29,7 @@
#include "third_party/blink/renderer/core/dom/element_rare_data.h"
#include "third_party/blink/renderer/core/dom/first_letter_pseudo_element.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/core/layout/generated_children.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_quote.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
@@ -38,6 +39,8 @@
namespace blink {
PseudoElement* PseudoElement::Create(Element* parent, PseudoId pseudo_id) {
+ if (pseudo_id == kPseudoIdFirstLetter)
+ return FirstLetterPseudoElement::Create(parent);
return new PseudoElement(parent, pseudo_id);
}
@@ -102,10 +105,16 @@ PseudoElement::PseudoElement(Element* parent, PseudoId pseudo_id)
scoped_refptr<ComputedStyle> PseudoElement::CustomStyleForLayoutObject() {
scoped_refptr<ComputedStyle> original_style =
- ParentOrShadowHostElement()->PseudoStyle(PseudoStyleRequest(pseudo_id_));
+ ParentOrShadowHostElement()->StyleForPseudoElement(
+ PseudoStyleRequest(pseudo_id_));
if (!original_style || original_style->Display() != EDisplay::kContents)
return original_style;
+ return StoreOriginalAndReturnLayoutStyle(std::move(original_style));
+}
+
+scoped_refptr<ComputedStyle> PseudoElement::StoreOriginalAndReturnLayoutStyle(
+ scoped_refptr<ComputedStyle> original_style) {
// For display:contents we should not generate a box, but we generate a non-
// observable inline box for pseudo elements to be able to locate the
// anonymous layout objects for generated content during DetachLayoutTree().
@@ -117,7 +126,7 @@ scoped_refptr<ComputedStyle> PseudoElement::CustomStyleForLayoutObject() {
// Store the actual ComputedStyle to be able to return the correct values from
// getComputedStyle().
- StoreNonLayoutObjectComputedStyle(original_style);
+ StoreNonLayoutObjectComputedStyle(std::move(original_style));
return layout_style;
}
@@ -145,6 +154,13 @@ void PseudoElement::AttachLayoutTree(AttachContext& context) {
if (!layout_object)
return;
+ // This is to ensure that bypassing the CanHaveGeneratedChildren() check in
+ // LayoutTreeBuilderForElement::ShouldCreateLayoutObject() does not result in
+ // the backdrop pseudo element's layout object becoming the child of a layout
+ // object that doesn't allow children.
+ DCHECK(layout_object->Parent());
+ DCHECK(CanHaveGeneratedChildren(*layout_object->Parent()));
+
ComputedStyle& style = layout_object->MutableStyleRef();
if (style.StyleType() != kPseudoIdBefore &&
style.StyleType() != kPseudoIdAfter)
@@ -168,13 +184,18 @@ bool PseudoElement::LayoutObjectIsNeeded(const ComputedStyle& style) const {
return PseudoElementLayoutObjectIsNeeded(&style);
}
-void PseudoElement::DidRecalcStyle(StyleRecalcChange) {
+void PseudoElement::DidRecalcStyle(StyleRecalcChange change) {
+ // If the pseudo element is being re-attached, its anonymous LayoutObjects for
+ // generated content will be destroyed and possibly recreated during layout
+ // tree rebuild. Thus, propagating style to generated content now is futile.
+ if (change == kReattach)
+ return;
if (!GetLayoutObject())
return;
// The layoutObjects inside pseudo elements are anonymous so they don't get
// notified of recalcStyle and must have the style propagated downward
- // manually similar to LayoutObject::propagateStyleToAnonymousChildren.
+ // manually similar to LayoutObject::PropagateStyleToAnonymousChildren.
LayoutObject* layout_object = GetLayoutObject();
for (LayoutObject* child = layout_object->NextInPreOrder(layout_object);
child; child = child->NextInPreOrder(layout_object)) {
diff --git a/chromium/third_party/blink/renderer/core/dom/pseudo_element.h b/chromium/third_party/blink/renderer/core/dom/pseudo_element.h
index 67bdb1eb833..6cdcf693d36 100644
--- a/chromium/third_party/blink/renderer/core/dom/pseudo_element.h
+++ b/chromium/third_party/blink/renderer/core/dom/pseudo_element.h
@@ -47,6 +47,8 @@ class CORE_EXPORT PseudoElement : public Element {
PseudoId GetPseudoId() const override { return pseudo_id_; }
const ComputedStyle* VirtualEnsureComputedStyle(
PseudoId pseudo_element_specifier = kPseudoIdNone) final;
+ scoped_refptr<ComputedStyle> StoreOriginalAndReturnLayoutStyle(
+ scoped_refptr<ComputedStyle>);
static String PseudoElementNameForEvents(PseudoId);
diff --git a/chromium/third_party/blink/renderer/core/dom/qualified_name.cc b/chromium/third_party/blink/renderer/core/dom/qualified_name.cc
index 259d89d3c93..728acbbe889 100644
--- a/chromium/third_party/blink/renderer/core/dom/qualified_name.cc
+++ b/chromium/third_party/blink/renderer/core/dom/qualified_name.cc
@@ -28,6 +28,7 @@
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/static_constructors.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/dom/range.cc b/chromium/third_party/blink/renderer/core/dom/range.cc
index 4e534e0c98d..332ba077493 100644
--- a/chromium/third_party/blink/renderer/core/dom/range.cc
+++ b/chromium/third_party/blink/renderer/core/dom/range.cc
@@ -25,12 +25,12 @@
#include "third_party/blink/renderer/core/dom/range.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html.h"
#include "third_party/blink/renderer/core/dom/character_data.h"
#include "third_party/blink/renderer/core/dom/container_node.h"
#include "third_party/blink/renderer/core/dom/document_fragment.h"
+#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/dom/node_with_index.h"
@@ -54,8 +54,10 @@
#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/svg/svg_svg_element.h"
-#include "third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_html.h"
+#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/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/text/cstring.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#ifndef NDEBUG
@@ -327,7 +329,7 @@ short Range::comparePoint(Node* ref_node,
if (!HasSameRoot(*ref_node)) {
exception_state.ThrowDOMException(
- kWrongDocumentError,
+ DOMExceptionCode::kWrongDocumentError,
"The node provided and the Range are not in the same tree.");
return 0;
}
@@ -360,7 +362,7 @@ short Range::compareBoundaryPoints(unsigned how,
if (!(how == kStartToStart || how == kStartToEnd || how == kEndToEnd ||
how == kEndToStart)) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"The comparison method provided must be "
"one of 'START_TO_START', 'START_TO_END', "
"'END_TO_END', or 'END_TO_START'.");
@@ -371,7 +373,7 @@ short Range::compareBoundaryPoints(unsigned how,
Node* source_cont = source_range->commonAncestorContainer();
if (this_cont->GetDocument() != source_cont->GetDocument()) {
exception_state.ThrowDOMException(
- kWrongDocumentError,
+ DOMExceptionCode::kWrongDocumentError,
"The source range is in a different document than this range.");
return 0;
}
@@ -384,7 +386,7 @@ short Range::compareBoundaryPoints(unsigned how,
source_top = source_top->parentNode();
if (this_top != source_top) { // in different DocumentFragments
exception_state.ThrowDOMException(
- kWrongDocumentError,
+ DOMExceptionCode::kWrongDocumentError,
"The source range is in a different document than this range.");
return 0;
}
@@ -415,7 +417,8 @@ short Range::compareBoundaryPoints(Node* container_a,
offset_b, &disconnected);
if (disconnected) {
exception_state.ThrowDOMException(
- kWrongDocumentError, "The two ranges are in separate documents.");
+ DOMExceptionCode::kWrongDocumentError,
+ "The two ranges are in separate documents.");
return 0;
}
return result;
@@ -843,7 +846,7 @@ void Range::insertNode(Node* new_node, ExceptionState& exception_state) {
if (start_node.getNodeType() == Node::kProcessingInstructionNode ||
start_node.getNodeType() == Node::kCommentNode) {
exception_state.ThrowDOMException(
- kHierarchyRequestError,
+ DOMExceptionCode::kHierarchyRequestError,
"Nodes of type '" + new_node->nodeName() +
"' may not be inserted inside nodes of type '" +
start_node.nodeName() + "'.");
@@ -851,7 +854,7 @@ void Range::insertNode(Node* new_node, ExceptionState& exception_state) {
}
const bool start_is_text = start_node.IsTextNode();
if (start_is_text && !start_node.parentNode()) {
- exception_state.ThrowDOMException(kHierarchyRequestError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kHierarchyRequestError,
"This operation would split a text node, "
"but there's no parent into which to "
"insert.");
@@ -859,7 +862,7 @@ void Range::insertNode(Node* new_node, ExceptionState& exception_state) {
}
if (start_node == new_node) {
exception_state.ThrowDOMException(
- kHierarchyRequestError,
+ DOMExceptionCode::kHierarchyRequestError,
"Unable to insert a node into a Range starting from the node itself.");
return;
}
@@ -869,7 +872,7 @@ void Range::insertNode(Node* new_node, ExceptionState& exception_state) {
// ContainerNode parent.
if (start_node.IsAttributeNode()) {
exception_state.ThrowDOMException(
- kHierarchyRequestError,
+ DOMExceptionCode::kHierarchyRequestError,
"Nodes of type '" + new_node->nodeName() +
"' may not be inserted inside nodes of type 'Attr'.");
return;
@@ -967,6 +970,31 @@ String Range::GetText() const {
}
DocumentFragment* Range::createContextualFragment(
+ const StringOrTrustedHTML& string_or_html,
+ ExceptionState& exception_state) {
+ // Algorithm:
+ // http://domparsing.spec.whatwg.org/#extensions-to-the-range-interface
+
+ DCHECK(string_or_html.IsString() ||
+ RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
+ DCHECK(!string_or_html.IsNull());
+
+ Document& document = start_.Container().GetDocument();
+
+ if (string_or_html.IsString() && document.RequireTrustedTypes()) {
+ exception_state.ThrowTypeError(
+ "This document requires `TrustedHTML` assignment.");
+ return nullptr;
+ }
+
+ String markup = string_or_html.IsString()
+ ? string_or_html.GetAsString()
+ : string_or_html.GetAsTrustedHTML()->toString();
+
+ return createContextualFragmentFromString(markup, exception_state);
+}
+
+DocumentFragment* Range::createContextualFragmentFromString(
const String& markup,
ExceptionState& exception_state) {
// Algorithm:
@@ -1017,7 +1045,7 @@ Node* Range::CheckNodeWOffset(Node* n,
switch (n->getNodeType()) {
case Node::kDocumentTypeNode:
exception_state.ThrowDOMException(
- kInvalidNodeTypeError,
+ DOMExceptionCode::kInvalidNodeTypeError,
"The node provided is of type '" + n->nodeName() + "'.");
return nullptr;
case Node::kCdataSectionNode:
@@ -1025,21 +1053,21 @@ Node* Range::CheckNodeWOffset(Node* n,
case Node::kTextNode:
if (offset > ToCharacterData(n)->length()) {
exception_state.ThrowDOMException(
- kIndexSizeError, "The offset " + String::Number(offset) +
- " is larger than the node's length (" +
- String::Number(ToCharacterData(n)->length()) +
- ").");
+ DOMExceptionCode::kIndexSizeError,
+ "The offset " + String::Number(offset) +
+ " is larger than the node's length (" +
+ String::Number(ToCharacterData(n)->length()) + ").");
} else if (offset >
static_cast<unsigned>(std::numeric_limits<int>::max())) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
"The offset " + String::Number(offset) + " is invalid.");
}
return nullptr;
case Node::kProcessingInstructionNode:
if (offset > ToProcessingInstruction(n)->data().length()) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
"The offset " + String::Number(offset) +
" is larger than the node's length (" +
String::Number(ToProcessingInstruction(n)->data().length()) +
@@ -1047,7 +1075,7 @@ Node* Range::CheckNodeWOffset(Node* n,
} else if (offset >
static_cast<unsigned>(std::numeric_limits<int>::max())) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
"The offset " + String::Number(offset) + " is invalid.");
}
return nullptr;
@@ -1059,14 +1087,14 @@ Node* Range::CheckNodeWOffset(Node* n,
return nullptr;
if (offset > static_cast<unsigned>(std::numeric_limits<int>::max())) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
"The offset " + String::Number(offset) + " is invalid.");
return nullptr;
}
Node* child_before = NodeTraversal::ChildAt(*n, offset - 1);
if (!child_before) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
"There is no child at offset " + String::Number(offset) + ".");
}
return child_before;
@@ -1090,7 +1118,7 @@ void Range::CheckNodeBA(Node* n, ExceptionState& exception_state) const {
// Attr, Entity, or Notation node.
if (!n->parentNode()) {
- exception_state.ThrowDOMException(kInvalidNodeTypeError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidNodeTypeError,
"the given Node has no parent.");
return;
}
@@ -1100,7 +1128,7 @@ void Range::CheckNodeBA(Node* n, ExceptionState& exception_state) const {
case Node::kDocumentFragmentNode:
case Node::kDocumentNode:
exception_state.ThrowDOMException(
- kInvalidNodeTypeError,
+ DOMExceptionCode::kInvalidNodeTypeError,
"The node provided is of type '" + n->nodeName() + "'.");
return;
case Node::kCdataSectionNode:
@@ -1128,7 +1156,7 @@ void Range::CheckNodeBA(Node* n, ExceptionState& exception_state) const {
case Node::kProcessingInstructionNode:
case Node::kTextNode:
exception_state.ThrowDOMException(
- kInvalidNodeTypeError,
+ DOMExceptionCode::kInvalidNodeTypeError,
"The node provided is of type '" + n->nodeName() + "'.");
return;
}
@@ -1172,7 +1200,7 @@ void Range::selectNode(Node* ref_node, ExceptionState& exception_state) {
}
if (!ref_node->parentNode()) {
- exception_state.ThrowDOMException(kInvalidNodeTypeError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidNodeTypeError,
"the given Node has no parent.");
return;
}
@@ -1189,7 +1217,7 @@ void Range::selectNode(Node* ref_node, ExceptionState& exception_state) {
case Node::kDocumentFragmentNode:
case Node::kDocumentNode:
exception_state.ThrowDOMException(
- kInvalidNodeTypeError,
+ DOMExceptionCode::kInvalidNodeTypeError,
"The node provided is of type '" + ref_node->nodeName() + "'.");
return;
}
@@ -1224,7 +1252,7 @@ void Range::selectNodeContents(Node* ref_node,
break;
case Node::kDocumentTypeNode:
exception_state.ThrowDOMException(
- kInvalidNodeTypeError,
+ DOMExceptionCode::kInvalidNodeTypeError,
"The node provided is of type '" + ref_node->nodeName() + "'.");
return;
}
@@ -1288,7 +1316,7 @@ void Range::surroundContents(Node* new_parent,
end_non_text_container = end_non_text_container->parentNode();
if (start_non_text_container != end_non_text_container) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"The Range has partially selected a non-Text node.");
return;
}
@@ -1301,7 +1329,7 @@ void Range::surroundContents(Node* new_parent,
case Node::kDocumentNode:
case Node::kDocumentTypeNode:
exception_state.ThrowDOMException(
- kInvalidNodeTypeError,
+ DOMExceptionCode::kInvalidNodeTypeError,
"The node provided is of type '" + new_parent->nodeName() + "'.");
return;
case Node::kCdataSectionNode:
@@ -1357,8 +1385,9 @@ void Range::CheckExtractPrecondition(ExceptionState& exception_state) {
Node* past_last = PastLastNode();
for (Node* n = FirstNode(); n != past_last; n = NodeTraversal::Next(*n)) {
if (n->IsDocumentTypeNode()) {
- exception_state.ThrowDOMException(kHierarchyRequestError,
- "The Range contains a doctype node.");
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kHierarchyRequestError,
+ "The Range contains a doctype node.");
return;
}
}
diff --git a/chromium/third_party/blink/renderer/core/dom/range.h b/chromium/third_party/blink/renderer/core/dom/range.h
index bc8e40c9a2b..66f75b09717 100644
--- a/chromium/third_party/blink/renderer/core/dom/range.h
+++ b/chromium/third_party/blink/renderer/core/dom/range.h
@@ -26,9 +26,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_RANGE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_RANGE_H_
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/range_boundary_point.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/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
@@ -46,6 +46,7 @@ class ExceptionState;
class FloatQuad;
class Node;
class NodeWithIndex;
+class StringOrTrustedHTML;
class Text;
class CORE_EXPORT Range final : public ScriptWrappable {
@@ -114,7 +115,7 @@ class CORE_EXPORT Range final : public ScriptWrappable {
String GetText() const;
- DocumentFragment* createContextualFragment(const String& html,
+ DocumentFragment* createContextualFragment(const StringOrTrustedHTML& html,
ExceptionState&);
void detach();
@@ -205,6 +206,9 @@ class CORE_EXPORT Range final : public ScriptWrappable {
void UpdateSelectionIfAddedToSelection();
void RemoveFromSelectionIfInDifferentRoot(Document& old_document);
+ DocumentFragment* createContextualFragmentFromString(const String& html,
+ ExceptionState&);
+
Member<Document> owner_document_; // Cannot be null.
RangeBoundaryPoint start_;
RangeBoundaryPoint end_;
diff --git a/chromium/third_party/blink/renderer/core/dom/range.idl b/chromium/third_party/blink/renderer/core/dom/range.idl
index 51c59d08d97..86dc09b4a38 100644
--- a/chromium/third_party/blink/renderer/core/dom/range.idl
+++ b/chromium/third_party/blink/renderer/core/dom/range.idl
@@ -19,6 +19,9 @@
*/
// https://dom.spec.whatwg.org/#interface-range
+// The `HTMLString` reference below is from Trusted Types:
+// https://github.com/WICG/trusted-types/, which is still WIP.
+// https://crbug.com/739170.
[
Constructor,
ConstructorCallWith=Document
@@ -69,7 +72,7 @@
// DOM Parsing and Serialization
// https://w3c.github.io/DOM-Parsing/#extensions-to-the-range-interface
- [NewObject, RaisesException, CEReactions, CustomElementCallbacks] DocumentFragment createContextualFragment(DOMString fragment);
+ [NewObject, RaisesException, CEReactions, CustomElementCallbacks] DocumentFragment createContextualFragment(HTMLString fragment);
// Non-standard API
[RaisesException, DeprecateAs=RangeExpand] void expand([Default=Undefined] optional DOMString unit);
diff --git a/chromium/third_party/blink/renderer/core/dom/range_boundary_point.h b/chromium/third_party/blink/renderer/core/dom/range_boundary_point.h
index 3b92cd6a85e..8c3a071c5d0 100644
--- a/chromium/third_party/blink/renderer/core/dom/range_boundary_point.h
+++ b/chromium/third_party/blink/renderer/core/dom/range_boundary_point.h
@@ -26,6 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_RANGE_BOUNDARY_POINT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_RANGE_BOUNDARY_POINT_H_
+#include "third_party/blink/renderer/core/dom/character_data.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/editing/position.h"
diff --git a/chromium/third_party/blink/renderer/core/dom/range_test.cc b/chromium/third_party/blink/renderer/core/dom/range_test.cc
index bfd4e5878c5..3836b0c6fcb 100644
--- a/chromium/third_party/blink/renderer/core/dom/range_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/range_test.cc
@@ -6,7 +6,6 @@
#include "base/memory/scoped_refptr.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_array_buffer_or_array_buffer_view.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/core/css/font_face_descriptors.h"
@@ -26,6 +25,7 @@
#include "third_party/blink/renderer/core/html/html_document.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/html/html_html_element.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/compiler.h"
diff --git a/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.cc b/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.cc
index bc981852385..7921474ad0b 100644
--- a/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.cc
+++ b/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.cc
@@ -52,11 +52,6 @@ void ScriptedAnimationController::Trace(blink::Visitor* visitor) {
visitor->Trace(per_frame_events_);
}
-void ScriptedAnimationController::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(callback_collection_);
-}
-
void ScriptedAnimationController::Pause() {
++suspend_count_;
}
@@ -138,12 +133,15 @@ void ScriptedAnimationController::ExecuteCallbacks(
return;
double high_res_now_ms =
- 1000.0 *
- document_->Loader()->GetTiming().MonotonicTimeToZeroBasedDocumentTime(
- monotonic_time_now);
+ document_->Loader()
+ ->GetTiming()
+ .MonotonicTimeToZeroBasedDocumentTime(monotonic_time_now)
+ .InMillisecondsF();
double legacy_high_res_now_ms =
- 1000.0 * document_->Loader()->GetTiming().MonotonicTimeToPseudoWallTime(
- monotonic_time_now);
+ document_->Loader()
+ ->GetTiming()
+ .MonotonicTimeToPseudoWallTime(monotonic_time_now)
+ .InMillisecondsF();
callback_collection_.ExecuteCallbacks(high_res_now_ms,
legacy_high_res_now_ms);
}
diff --git a/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.h b/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.h
index 50bbd2a1553..6c8855f65b4 100644
--- a/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.h
+++ b/chromium/third_party/blink/renderer/core/dom/scripted_animation_controller.h
@@ -28,6 +28,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/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -43,7 +44,7 @@ class MediaQueryListListener;
class CORE_EXPORT ScriptedAnimationController
: public GarbageCollectedFinalized<ScriptedAnimationController>,
- public TraceWrapperBase {
+ public NameClient {
public:
static ScriptedAnimationController* Create(Document* document) {
return new ScriptedAnimationController(document);
@@ -51,7 +52,6 @@ class CORE_EXPORT ScriptedAnimationController
virtual ~ScriptedAnimationController() = default;
void Trace(blink::Visitor*);
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "ScriptedAnimationController";
}
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 f28a153fdc3..f38852efb04 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
@@ -33,7 +33,7 @@ class IdleRequestCallbackWrapper
static void IdleTaskFired(
scoped_refptr<IdleRequestCallbackWrapper> callback_wrapper,
- double deadline_seconds) {
+ TimeTicks deadline) {
if (ScriptedIdleTaskController* controller =
callback_wrapper->Controller()) {
// If we are going to yield immediately, reschedule the callback for
@@ -46,7 +46,7 @@ class IdleRequestCallbackWrapper
/* timeout_millis */ 0);
return;
}
- controller->CallbackFired(callback_wrapper->Id(), deadline_seconds,
+ controller->CallbackFired(callback_wrapper->Id(), deadline,
IdleDeadline::CallbackType::kCalledWhenIdle);
}
callback_wrapper->Cancel();
@@ -56,8 +56,7 @@ class IdleRequestCallbackWrapper
scoped_refptr<IdleRequestCallbackWrapper> callback_wrapper) {
if (ScriptedIdleTaskController* controller =
callback_wrapper->Controller()) {
- controller->CallbackFired(callback_wrapper->Id(),
- CurrentTimeTicksInSeconds(),
+ controller->CallbackFired(callback_wrapper->Id(), CurrentTimeTicks(),
IdleDeadline::CallbackType::kCalledByTimeout);
}
callback_wrapper->Cancel();
@@ -88,12 +87,6 @@ void ScriptedIdleTaskController::V8IdleTask::Trace(blink::Visitor* visitor) {
ScriptedIdleTaskController::IdleTask::Trace(visitor);
}
-void ScriptedIdleTaskController::V8IdleTask::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(callback_);
- ScriptedIdleTaskController::IdleTask::TraceWrappers(visitor);
-}
-
void ScriptedIdleTaskController::V8IdleTask::invoke(IdleDeadline* deadline) {
callback_->InvokeAndReportException(nullptr, deadline);
}
@@ -114,13 +107,6 @@ void ScriptedIdleTaskController::Trace(blink::Visitor* visitor) {
PausableObject::Trace(visitor);
}
-void ScriptedIdleTaskController::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- for (const auto& idle_task : idle_tasks_.Values()) {
- visitor->TraceWrappers(idle_task);
- }
-}
-
int ScriptedIdleTaskController::NextCallbackId() {
while (true) {
++next_callback_id_;
@@ -186,7 +172,7 @@ void ScriptedIdleTaskController::CancelCallback(CallbackId id) {
void ScriptedIdleTaskController::CallbackFired(
CallbackId id,
- double deadline_seconds,
+ TimeTicks deadline,
IdleDeadline::CallbackType callback_type) {
if (!idle_tasks_.Contains(id))
return;
@@ -201,12 +187,12 @@ void ScriptedIdleTaskController::CallbackFired(
return;
}
- RunCallback(id, deadline_seconds, callback_type);
+ RunCallback(id, deadline, callback_type);
}
void ScriptedIdleTaskController::RunCallback(
CallbackId id,
- double deadline_seconds,
+ TimeTicks deadline,
IdleDeadline::CallbackType callback_type) {
DCHECK(!paused_);
@@ -219,8 +205,8 @@ void ScriptedIdleTaskController::RunCallback(
IdleTask* idle_task = idle_task_iter->value;
DCHECK(idle_task);
- double allotted_time_millis =
- std::max((deadline_seconds - CurrentTimeTicksInSeconds()) * 1000, 0.0);
+ TimeDelta allotted_time =
+ std::max(deadline - CurrentTimeTicks(), TimeDelta());
probe::AsyncTask async_task(GetExecutionContext(), idle_task);
probe::UserCallback probe(GetExecutionContext(), "requestIdleCallback",
@@ -229,9 +215,9 @@ void ScriptedIdleTaskController::RunCallback(
TRACE_EVENT1(
"devtools.timeline", "FireIdleCallback", "data",
InspectorIdleCallbackFireEvent::Data(
- GetExecutionContext(), id, allotted_time_millis,
+ GetExecutionContext(), id, allotted_time.InMillisecondsF(),
callback_type == IdleDeadline::CallbackType::kCalledByTimeout));
- idle_task->invoke(IdleDeadline::Create(deadline_seconds, callback_type));
+ idle_task->invoke(IdleDeadline::Create(deadline, callback_type));
// Finally there is no need to keep the idle task alive.
//
@@ -255,7 +241,7 @@ void ScriptedIdleTaskController::Unpause() {
Vector<CallbackId> pending_timeouts;
pending_timeouts_.swap(pending_timeouts);
for (auto& id : pending_timeouts)
- RunCallback(id, CurrentTimeTicksInSeconds(),
+ RunCallback(id, CurrentTimeTicks(),
IdleDeadline::CallbackType::kCalledByTimeout);
// Repost idle tasks for any remaining callbacks.
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 29208f80a54..55adb1fe191 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
@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_idle_request_callback.h"
#include "third_party/blink/renderer/core/dom/idle_deadline.h"
#include "third_party/blink/renderer/core/dom/pausable_object.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/timer.h"
@@ -20,11 +21,12 @@ class IdleRequestCallbackWrapper;
class ExecutionContext;
class IdleRequestOptions;
+class ThreadScheduler;
class CORE_EXPORT ScriptedIdleTaskController
: public GarbageCollectedFinalized<ScriptedIdleTaskController>,
public PausableObject,
- public TraceWrapperBase {
+ public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(ScriptedIdleTaskController);
public:
@@ -34,7 +36,6 @@ class CORE_EXPORT ScriptedIdleTaskController
~ScriptedIdleTaskController() override;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "ScriptedIdleTaskController";
}
@@ -44,10 +45,9 @@ class CORE_EXPORT ScriptedIdleTaskController
// |IdleTask| is an interface type which generalizes tasks which are invoked
// on idle. The tasks need to define what to do on idle in |invoke|.
class IdleTask : public GarbageCollectedFinalized<IdleTask>,
- public TraceWrapperBase {
+ public NameClient {
public:
virtual void Trace(blink::Visitor* visitor) {}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {}
const char* NameInHeapSnapshot() const override { return "IdleTask"; }
virtual ~IdleTask() = default;
virtual void invoke(IdleDeadline*) = 0;
@@ -63,7 +63,6 @@ class CORE_EXPORT ScriptedIdleTaskController
~V8IdleTask() override = default;
void invoke(IdleDeadline*) override;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
explicit V8IdleTask(V8IdleRequestCallback*);
@@ -79,7 +78,7 @@ class CORE_EXPORT ScriptedIdleTaskController
void Unpause() override;
void CallbackFired(CallbackId,
- double deadline_seconds,
+ TimeTicks deadline,
IdleDeadline::CallbackType);
private:
@@ -97,9 +96,7 @@ class CORE_EXPORT ScriptedIdleTaskController
!WTF::IsHashTraitsEmptyValue<Traits, CallbackId>(id);
}
- void RunCallback(CallbackId,
- double deadline_seconds,
- IdleDeadline::CallbackType);
+ void RunCallback(CallbackId, TimeTicks deadline, IdleDeadline::CallbackType);
ThreadScheduler* scheduler_; // Not owned.
HeapHashMap<CallbackId, TraceWrapperMember<IdleTask>> idle_tasks_;
diff --git a/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc b/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc
index e2256b51b9d..4e1d93ca401 100644
--- a/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/scripted_idle_task_controller_test.cc
@@ -57,11 +57,14 @@ class MockScriptedIdleTaskControllerScheduler final : public ThreadScheduler {
void RemoveTaskObserver(
base::MessageLoop::TaskObserver* task_observer) override {}
- scheduler::NonMainThreadScheduler* AsNonMainThreadScheduler() override {
+ void AddRAILModeObserver(
+ scheduler::WebThreadScheduler::RAILModeObserver*) override {}
+
+ scheduler::NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() override {
return nullptr;
}
- void RunIdleTask() { std::move(idle_task_).Run(0); }
+ void RunIdleTask() { std::move(idle_task_).Run(TimeTicks()); }
bool HasIdleTask() const { return !!idle_task_; }
private:
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 4e3caef90ab..dfc0422362e 100644
--- a/chromium/third_party/blink/renderer/core/dom/shadow_root.cc
+++ b/chromium/third_party/blink/renderer/core/dom/shadow_root.cc
@@ -27,18 +27,17 @@
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html.h"
#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/css/style_sheet_list.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
-#include "third_party/blink/renderer/core/dom/ng/slot_assignment_engine.h"
+#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/dom/shadow_root_v0.h"
#include "third_party/blink/renderer/core/dom/slot_assignment.h"
+#include "third_party/blink/renderer/core/dom/slot_assignment_engine.h"
#include "third_party/blink/renderer/core/dom/text.h"
-#include "third_party/blink/renderer/core/dom/trustedtypes/trusted_html.h"
#include "third_party/blink/renderer/core/dom/v0_insertion_point.h"
#include "third_party/blink/renderer/core/dom/whitespace_attacher.h"
#include "third_party/blink/renderer/core/editing/serializers/serialization.h"
@@ -46,7 +45,8 @@
#include "third_party/blink/renderer/core/html/html_shadow_element.h"
#include "third_party/blink/renderer/core/html/html_slot_element.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
-#include "third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_html.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -150,25 +150,20 @@ void ShadowRoot::RecalcStyle(StyleRecalcChange change) {
DCHECK(!HasCustomStyleCallbacks());
if (GetStyleChangeType() >= kSubtreeStyleChange) {
- change = kForce;
- if (NeedsAttach())
+ if (change < kForce)
+ change = kForce;
+ if (NeedsAttach() || change == kReattach)
SetNeedsReattachLayoutTree();
}
-
- // There's no style to update so just calling recalcStyle means we're updated.
- ClearNeedsStyleRecalc();
+ // There's no style to update so just calling RecalcStyle means we're updated.
+ if (change != kReattach)
+ ClearNeedsStyleRecalc();
if (change >= kUpdatePseudoElements || ChildNeedsStyleRecalc())
RecalcDescendantStyles(change);
ClearChildNeedsStyleRecalc();
}
-void ShadowRoot::RecalcStylesForReattach() {
- // ShadowRoot doesn't support custom callbacks.
- DCHECK(!HasCustomStyleCallbacks());
- RecalcDescendantStylesForReattach();
-}
-
void ShadowRoot::RebuildLayoutTree(WhitespaceAttacher& whitespace_attacher) {
ClearNeedsReattachLayoutTree();
RebuildChildrenLayoutTrees(whitespace_attacher);
@@ -299,11 +294,6 @@ void ShadowRoot::Trace(blink::Visitor* visitor) {
DocumentFragment::Trace(visitor);
}
-void ShadowRoot::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(style_sheet_list_);
- DocumentFragment::TraceWrappers(visitor);
-}
-
std::ostream& operator<<(std::ostream& ostream, const ShadowRootType& type) {
switch (type) {
case ShadowRootType::kUserAgent:
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 fb23e8eddc8..fda132984ea 100644
--- a/chromium/third_party/blink/renderer/core/dom/shadow_root.h
+++ b/chromium/third_party/blink/renderer/core/dom/shadow_root.h
@@ -27,13 +27,13 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SHADOW_ROOT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SHADOW_ROOT_H_
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/style_sheet_list.h"
#include "third_party/blink/renderer/core/dom/container_node.h"
#include "third_party/blink/renderer/core/dom/document_fragment.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/tree_scope.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable_visitor.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
@@ -118,7 +118,6 @@ class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope {
unsigned ChildShadowRootCount() const { return child_shadow_root_count_; }
void RecalcStyle(StyleRecalcChange);
- void RecalcStylesForReattach();
void RebuildLayoutTree(WhitespaceAttacher&);
void RegisterScopedHTMLStyleChild();
@@ -165,7 +164,6 @@ class CORE_EXPORT ShadowRoot final : public DocumentFragment, public TreeScope {
}
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
ShadowRoot(Document&, ShadowRootType);
diff --git a/chromium/third_party/blink/renderer/core/dom/shadow_root_v0.h b/chromium/third_party/blink/renderer/core/dom/shadow_root_v0.h
index 362e7e6ac39..d836af74400 100644
--- a/chromium/third_party/blink/renderer/core/dom/shadow_root_v0.h
+++ b/chromium/third_party/blink/renderer/core/dom/shadow_root_v0.h
@@ -86,10 +86,6 @@ class CORE_EXPORT ShadowRootV0 final
visitor->Trace(node_to_insertion_points_);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(shadow_root_);
- }
-
private:
ShadowRoot& GetShadowRoot() const { return *shadow_root_; }
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 d44b41025d3..4049af22401 100644
--- a/chromium/third_party/blink/renderer/core/dom/slot_assignment.cc
+++ b/chromium/third_party/blink/renderer/core/dom/slot_assignment.cc
@@ -5,10 +5,10 @@
#include "third_party/blink/renderer/core/dom/slot_assignment.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
-#include "third_party/blink/renderer/core/dom/ng/slot_assignment_engine.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
+#include "third_party/blink/renderer/core/dom/slot_assignment_engine.h"
#include "third_party/blink/renderer/core/dom/v0_insertion_point.h"
#include "third_party/blink/renderer/core/html/forms/html_opt_group_element.h"
#include "third_party/blink/renderer/core/html/forms/html_select_element.h"
diff --git a/chromium/third_party/blink/renderer/core/dom/slot_assignment_engine.cc b/chromium/third_party/blink/renderer/core/dom/slot_assignment_engine.cc
new file mode 100644
index 00000000000..c4bb49abb68
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/dom/slot_assignment_engine.cc
@@ -0,0 +1,58 @@
+// 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/dom/slot_assignment_engine.h"
+
+#include "third_party/blink/renderer/core/dom/shadow_root.h"
+#include "third_party/blink/renderer/core/dom/slot_assignment.h"
+
+namespace blink {
+
+SlotAssignmentEngine::SlotAssignmentEngine() {}
+
+void SlotAssignmentEngine::AddShadowRootNeedingRecalc(ShadowRoot& shadow_root) {
+ DCHECK(shadow_root.isConnected());
+ DCHECK(shadow_root.NeedsSlotAssignmentRecalc());
+ shadow_roots_needing_recalc_.insert(&shadow_root);
+}
+
+void SlotAssignmentEngine::RemoveShadowRootNeedingRecalc(
+ ShadowRoot& shadow_root) {
+ DCHECK(shadow_root.isConnected());
+ DCHECK(!shadow_root.NeedsSlotAssignmentRecalc());
+ DCHECK(shadow_roots_needing_recalc_.Contains(&shadow_root));
+ shadow_roots_needing_recalc_.erase(&shadow_root);
+}
+
+void SlotAssignmentEngine::Connected(ShadowRoot& shadow_root) {
+ if (shadow_root.NeedsSlotAssignmentRecalc())
+ AddShadowRootNeedingRecalc(shadow_root);
+}
+
+void SlotAssignmentEngine::Disconnected(ShadowRoot& shadow_root) {
+ if (shadow_root.NeedsSlotAssignmentRecalc()) {
+ DCHECK(shadow_roots_needing_recalc_.Contains(&shadow_root));
+ shadow_roots_needing_recalc_.erase(&shadow_root);
+ } else {
+ DCHECK(!shadow_roots_needing_recalc_.Contains(&shadow_root));
+ }
+}
+
+void SlotAssignmentEngine::RecalcSlotAssignments() {
+ for (auto& shadow_root :
+ HeapHashSet<WeakMember<ShadowRoot>>(shadow_roots_needing_recalc_)) {
+ DCHECK(shadow_root->isConnected());
+ DCHECK(shadow_root->NeedsSlotAssignmentRecalc());
+ // SlotAssignment::RecalcAssignment() will remove its shadow root from
+ // shadow_roots_needing_recalc_.
+ shadow_root->GetSlotAssignment().RecalcAssignment();
+ }
+ DCHECK(shadow_roots_needing_recalc_.IsEmpty());
+}
+
+void SlotAssignmentEngine::Trace(blink::Visitor* visitor) {
+ visitor->Trace(shadow_roots_needing_recalc_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/slot_assignment_engine.h b/chromium/third_party/blink/renderer/core/dom/slot_assignment_engine.h
new file mode 100644
index 00000000000..a0c6bf2e5db
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/dom/slot_assignment_engine.h
@@ -0,0 +1,41 @@
+// 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_DOM_SLOT_ASSIGNMENT_ENGINE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SLOT_ASSIGNMENT_ENGINE_H_
+
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+class ShadowRoot;
+
+class SlotAssignmentEngine final
+ : public GarbageCollected<SlotAssignmentEngine> {
+ public:
+ static SlotAssignmentEngine* Create() { return new SlotAssignmentEngine(); }
+
+ void AddShadowRootNeedingRecalc(ShadowRoot&);
+ void RemoveShadowRootNeedingRecalc(ShadowRoot&);
+
+ void Connected(ShadowRoot&);
+ void Disconnected(ShadowRoot&);
+
+ bool HasPendingSlotAssignmentRecalc() const {
+ return !shadow_roots_needing_recalc_.IsEmpty();
+ }
+
+ void RecalcSlotAssignments();
+
+ void Trace(blink::Visitor*);
+
+ private:
+ explicit SlotAssignmentEngine();
+
+ HeapHashSet<WeakMember<ShadowRoot>> shadow_roots_needing_recalc_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SLOT_ASSIGNMENT_ENGINE_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/slot_assignment_recalc_forbidden_scope.h b/chromium/third_party/blink/renderer/core/dom/slot_assignment_recalc_forbidden_scope.h
new file mode 100644
index 00000000000..8e25b44ca1e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/dom/slot_assignment_recalc_forbidden_scope.h
@@ -0,0 +1,43 @@
+// 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_DOM_SLOT_ASSIGNMENT_RECALC_FORBIDDEN_SCOPE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SLOT_ASSIGNMENT_RECALC_FORBIDDEN_SCOPE_H_
+
+#include "base/macros.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+
+namespace blink {
+
+#if DCHECK_IS_ON()
+class SlotAssignmentRecalcForbiddenScope {
+ STACK_ALLOCATED();
+
+ public:
+ explicit SlotAssignmentRecalcForbiddenScope(Document& document)
+ : count_(document.SlotAssignmentRecalcForbiddenRecursionDepth()) {
+ ++count_;
+ }
+
+ ~SlotAssignmentRecalcForbiddenScope() { --count_; }
+
+ private:
+ unsigned& count_;
+ DISALLOW_COPY_AND_ASSIGN(SlotAssignmentRecalcForbiddenScope);
+};
+#else
+class SlotAssignmentRecalcForbiddenScope {
+ STACK_ALLOCATED();
+
+ public:
+ explicit SlotAssignmentRecalcForbiddenScope(Document&) {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SlotAssignmentRecalcForbiddenScope);
+};
+#endif
+
+} // namespace blink
+
+#endif
diff --git a/chromium/third_party/blink/renderer/core/dom/slot_assignment_test.cc b/chromium/third_party/blink/renderer/core/dom/slot_assignment_test.cc
new file mode 100644
index 00000000000..5ae7336dd72
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/dom/slot_assignment_test.cc
@@ -0,0 +1,169 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
+
+#include "testing/gtest/include/gtest/gtest.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.h"
+#include "third_party/blink/renderer/core/dom/node_traversal.h"
+#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/html/html_collection.h"
+#include "third_party/blink/renderer/core/html/html_element.h"
+#include "third_party/blink/renderer/core/html/html_slot_element.h"
+#include "third_party/blink/renderer/core/testing/dummy_page_holder.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 {
+
+namespace {
+
+// Copy elements in HTMLCollection into a vector because HTMLCollection is a
+// live list and would be invalid if a mutation occurs.
+HeapVector<Member<Element>> CollectFromHTMLCollection(
+ HTMLCollection& collection) {
+ HeapVector<Member<Element>> elements;
+ for (Element* element : collection)
+ elements.push_back(element);
+ return elements;
+}
+
+template <class T>
+HeapVector<Member<Node>> CollectFromIterable(T iterable) {
+ HeapVector<Member<Node>> nodes;
+ for (auto& node : iterable)
+ nodes.push_back(&node);
+ return nodes;
+}
+
+// Process Mini-DSL for Declarative Shadow DOM.
+
+// In Mini-DSL, <shadowroot> elements would behaves as if it were "Declarative
+// Shadow DOM". This is usuful for constructing a composed tree in testing.
+// Declarative Shadow DOM is under the dicussion. See
+// https://github.com/whatwg/dom/issues/510. Once Declarative Shadow DOM is
+// standardized and implemented, this DSL is no longer required.
+void ConvertDeclarativeShadowDOMToShadowRoot(Element& element) {
+ HTMLCollection* shadow_root_collection =
+ element.getElementsByTagName("shadowroot");
+ if (!shadow_root_collection)
+ return;
+ for (Element* shadow_root :
+ CollectFromHTMLCollection(*shadow_root_collection)) {
+ Element* parent = shadow_root->parentElement();
+ DCHECK(parent);
+ parent->removeChild(shadow_root);
+ ShadowRoot& attached_shadow_root =
+ parent->AttachShadowRootInternal(ShadowRootType::kOpen);
+ for (Node* child :
+ CollectFromIterable(NodeTraversal::ChildrenOf(*shadow_root)))
+ attached_shadow_root.AppendChild(child);
+ }
+}
+
+void RemoveWhiteSpaceOnlyTextNode(ContainerNode& container) {
+ for (Node* descendant :
+ CollectFromIterable(NodeTraversal::InclusiveDescendantsOf(container))) {
+ if (Text* text = ToTextOrNull(descendant)) {
+ if (text->ContainsOnlyWhitespace())
+ text->remove();
+ } else if (Element* element = ToElementOrNull(descendant)) {
+ if (ShadowRoot* shadow_root = element->OpenShadowRoot())
+ RemoveWhiteSpaceOnlyTextNode(*shadow_root);
+ }
+ }
+}
+
+} // namespace
+
+class SlotAssignmentTest : public testing::Test,
+ private ScopedIncrementalShadowDOMForTest {
+ public:
+ SlotAssignmentTest() : ScopedIncrementalShadowDOMForTest(true) {}
+
+ protected:
+ Document& GetDocument() const { return *document_; }
+ void SetBody(const char* html);
+
+ private:
+ void SetUp() override;
+
+ Persistent<Document> document_;
+ std::unique_ptr<DummyPageHolder> dummy_page_holder_;
+};
+
+void SlotAssignmentTest::SetUp() {
+ dummy_page_holder_ = DummyPageHolder::Create(IntSize(800, 600));
+ document_ = &dummy_page_holder_->GetDocument();
+ DCHECK(document_);
+}
+
+void SlotAssignmentTest::SetBody(const char* html) {
+ Element* body = GetDocument().body();
+ body->SetInnerHTMLFromString(String::FromUTF8(html));
+ ConvertDeclarativeShadowDOMToShadowRoot(*body);
+ RemoveWhiteSpaceOnlyTextNode(*body);
+}
+
+TEST_F(SlotAssignmentTest, DeclarativeShadowDOM) {
+ SetBody(R"HTML(
+ <div id=host>
+ <shadowroot></shadowroot>
+ </div>
+ )HTML");
+
+ Element* host = GetDocument().QuerySelector("#host");
+ ASSERT_NE(nullptr, host);
+ ASSERT_NE(nullptr, host->OpenShadowRoot());
+}
+
+TEST_F(SlotAssignmentTest, NestedDeclarativeShadowDOM) {
+ SetBody(R"HTML(
+ <div id=host1>
+ <shadowroot>
+ <div id=host2>
+ <shadowroot></shadowroot>
+ </div>
+ </shadowroot>
+ </div>
+ )HTML");
+
+ Element* host1 = GetDocument().QuerySelector("#host1");
+ ASSERT_NE(nullptr, host1);
+ ShadowRoot* shadow_root1 = host1->OpenShadowRoot();
+ ASSERT_NE(nullptr, shadow_root1);
+
+ Element* host2 = shadow_root1->QuerySelector("#host2");
+ ASSERT_NE(nullptr, host2);
+ ShadowRoot* shadow_root2 = host2->OpenShadowRoot();
+ ASSERT_NE(nullptr, shadow_root2);
+}
+
+TEST_F(SlotAssignmentTest, AssignedNodesAreSet) {
+ SetBody(R"HTML(
+ <div id=host>
+ <shadowroot>
+ <slot></slot>
+ </shadowroot>
+ <div id='host-child'></div>
+ </div>
+ )HTML");
+
+ Element* host = GetDocument().QuerySelector("#host");
+ Element* host_child = GetDocument().QuerySelector("#host-child");
+ ShadowRoot* shadow_root = host->OpenShadowRoot();
+ HTMLSlotElement* slot =
+ ToHTMLSlotElementOrNull(shadow_root->QuerySelector("slot"));
+ ASSERT_NE(nullptr, slot);
+
+ EXPECT_EQ(slot, host_child->AssignedSlot());
+ HeapVector<Member<Node>> expected_nodes;
+ expected_nodes.push_back(host_child);
+ EXPECT_EQ(expected_nodes, slot->AssignedNodes());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/static_node_list.h b/chromium/third_party/blink/renderer/core/dom/static_node_list.h
index adac7179383..884b32ad17d 100644
--- a/chromium/third_party/blink/renderer/core/dom/static_node_list.h
+++ b/chromium/third_party/blink/renderer/core/dom/static_node_list.h
@@ -29,6 +29,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_STATIC_NODE_LIST_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_STATIC_NODE_LIST_H_
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/node_child_removal_tracker.h"
#include "third_party/blink/renderer/core/dom/node_list.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -50,11 +52,6 @@ class StaticNodeTypeList final : public NodeList {
NodeType* item(unsigned index) const override;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- for (unsigned i = 0; i < length(); i++)
- visitor->TraceWrappers(nodes_[i]);
- NodeList::TraceWrappers(visitor);
- }
private:
HeapVector<TraceWrapperMember<NodeType>> nodes_;
@@ -80,8 +77,13 @@ unsigned StaticNodeTypeList<NodeType>::length() const {
template <typename NodeType>
NodeType* StaticNodeTypeList<NodeType>::item(unsigned index) const {
- if (index < nodes_.size())
- return nodes_[index].Get();
+ if (index < nodes_.size()) {
+ auto* node = nodes_[index].Get();
+ if (node->GetDocument().InDOMNodeRemovedHandler() &&
+ NodeChildRemovalTracker::IsBeingRemoved(node))
+ node->GetDocument().CountDetachingNodeAccessInDOMNodeRemovedHandler();
+ return node;
+ }
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/static_range.cc b/chromium/third_party/blink/renderer/core/dom/static_range.cc
index 76e51ce3e57..99fd39618a1 100644
--- a/chromium/third_party/blink/renderer/core/dom/static_range.cc
+++ b/chromium/third_party/blink/renderer/core/dom/static_range.cc
@@ -4,10 +4,10 @@
#include "third_party/blink/renderer/core/dom/static_range.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/range.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/dom/static_range_test.cc b/chromium/third_party/blink/renderer/core/dom/static_range_test.cc
index ec963322626..c12c6b5393c 100644
--- a/chromium/third_party/blink/renderer/core/dom/static_range_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/static_range_test.cc
@@ -6,7 +6,6 @@
#include "base/memory/scoped_refptr.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/node_list.h"
@@ -16,6 +15,7 @@
#include "third_party/blink/renderer/core/html/html_document.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/html/html_html_element.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/compiler.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
diff --git a/chromium/third_party/blink/renderer/core/dom/sync_reattach_context.cc b/chromium/third_party/blink/renderer/core/dom/sync_reattach_context.cc
deleted file mode 100644
index c81fc060c91..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/sync_reattach_context.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/dom/sync_reattach_context.h"
-
-namespace blink {
-
-SyncReattachContext* SyncReattachContext::current_context_ = nullptr;
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/sync_reattach_context.h b/chromium/third_party/blink/renderer/core/dom/sync_reattach_context.h
deleted file mode 100644
index a0efc2c8587..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/sync_reattach_context.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SYNC_REATTACH_CONTEXT_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SYNC_REATTACH_CONTEXT_H_
-
-#include "third_party/blink/renderer/core/dom/node.h"
-
-namespace blink {
-
-class SyncReattachContext {
- STACK_ALLOCATED();
-
- public:
- static Node::AttachContext& CurrentAttachContext() {
- DCHECK(current_context_);
- return current_context_->AttachContextForReattach();
- }
- SyncReattachContext(Node::AttachContext& attach_context)
- : parent_context_(current_context_),
- previous_in_flow_(attach_context.previous_in_flow),
- attach_context_(attach_context) {
- current_context_ = this;
- }
- ~SyncReattachContext() { current_context_ = parent_context_; }
-
- private:
- Node::AttachContext& AttachContextForReattach() {
- attach_context_.previous_in_flow = previous_in_flow_;
- return attach_context_;
- }
-
- static SyncReattachContext* current_context_;
-
- SyncReattachContext* parent_context_ = nullptr;
- LayoutObject* previous_in_flow_;
- Node::AttachContext& attach_context_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SYNC_REATTACH_CONTEXT_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.cc b/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.cc
index be9f8ac35a8..53e1eb052f3 100644
--- a/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.cc
+++ b/chromium/third_party/blink/renderer/core/dom/synchronous_mutation_notifier.cc
@@ -13,28 +13,32 @@ SynchronousMutationNotifier::SynchronousMutationNotifier() = default;
void SynchronousMutationNotifier::NotifyChangeChildren(
const ContainerNode& container) {
- for (SynchronousMutationObserver* observer : observers_)
+ ForEachObserver([&](SynchronousMutationObserver* observer) {
observer->DidChangeChildren(container);
+ });
}
void SynchronousMutationNotifier::NotifyMergeTextNodes(
const Text& node,
const NodeWithIndex& node_to_be_removed_with_index,
unsigned old_length) {
- for (SynchronousMutationObserver* observer : observers_)
+ ForEachObserver([&](SynchronousMutationObserver* observer) {
observer->DidMergeTextNodes(node, node_to_be_removed_with_index,
old_length);
+ });
}
void SynchronousMutationNotifier::NotifyMoveTreeToNewDocument(
const Node& root) {
- for (SynchronousMutationObserver* observer : observers_)
+ ForEachObserver([&](SynchronousMutationObserver* observer) {
observer->DidMoveTreeToNewDocument(root);
+ });
}
void SynchronousMutationNotifier::NotifySplitTextNode(const Text& node) {
- for (SynchronousMutationObserver* observer : observers_)
+ ForEachObserver([&](SynchronousMutationObserver* observer) {
observer->DidSplitTextNode(node);
+ });
}
void SynchronousMutationNotifier::NotifyUpdateCharacterData(
@@ -42,21 +46,30 @@ void SynchronousMutationNotifier::NotifyUpdateCharacterData(
unsigned offset,
unsigned old_length,
unsigned new_length) {
- for (SynchronousMutationObserver* observer : observers_) {
+ // Using ForEachObserverWithoutChecks() instead of ForEachObserver() is
+ // necessary because DocumentMarkerController::DidUpdateCharacterData ends up
+ // calling SynchronousMutationNotifier::RemoveObserver, which is unsafe and
+ // can result in memory corruption.
+ //
+ // TODO(crbug.com/862900): Fix DocumentMarkerController and switch to
+ // ForEachObsever() here.
+ ForEachObserverWithoutChecks([&](SynchronousMutationObserver* observer) {
observer->DidUpdateCharacterData(character_data, offset, old_length,
new_length);
- }
+ });
}
void SynchronousMutationNotifier::NotifyNodeChildrenWillBeRemoved(
ContainerNode& container) {
- for (SynchronousMutationObserver* observer : observers_)
+ ForEachObserver([&](SynchronousMutationObserver* observer) {
observer->NodeChildrenWillBeRemoved(container);
+ });
}
void SynchronousMutationNotifier::NotifyNodeWillBeRemoved(Node& node) {
- for (SynchronousMutationObserver* observer : observers_)
+ ForEachObserver([&](SynchronousMutationObserver* observer) {
observer->NodeWillBeRemoved(node);
+ });
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/text.cc b/chromium/third_party/blink/renderer/core/dom/text.cc
index 2c356a525cd..8ea980ab00e 100644
--- a/chromium/third_party/blink/renderer/core/dom/text.cc
+++ b/chromium/third_party/blink/renderer/core/dom/text.cc
@@ -22,10 +22,8 @@
#include "third_party/blink/renderer/core/dom/text.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/first_letter_pseudo_element.h"
#include "third_party/blink/renderer/core/dom/layout_tree_builder.h"
#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
@@ -41,6 +39,7 @@
#include "third_party/blink/renderer/core/svg/svg_foreign_object_element.h"
#include "third_party/blink/renderer/core/svg_names.h"
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/cstring.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -106,8 +105,9 @@ Text* Text::splitText(unsigned offset, ExceptionState& exception_state) {
// the number of 16-bit units in data.
if (offset > length()) {
exception_state.ThrowDOMException(
- kIndexSizeError, "The offset " + String::Number(offset) +
- " is larger than the Text node's length.");
+ DOMExceptionCode::kIndexSizeError,
+ "The offset " + String::Number(offset) +
+ " is larger than the Text node's length.");
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/dom/tree_scope.cc b/chromium/third_party/blink/renderer/core/dom/tree_scope.cc
index 777e61fd4ac..05b1cd910c2 100644
--- a/chromium/third_party/blink/renderer/core/dom/tree_scope.cc
+++ b/chromium/third_party/blink/renderer/core/dom/tree_scope.cc
@@ -34,6 +34,7 @@
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/events/event_path.h"
#include "third_party/blink/renderer/core/dom/id_target_observer_registry.h"
+#include "third_party/blink/renderer/core/dom/node_child_removal_tracker.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/dom/tree_scope_adopter.h"
@@ -48,6 +49,7 @@
#include "third_party/blink/renderer/core/layout/layout_view.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/core/svg/svg_text_content_element.h"
#include "third_party/blink/renderer/core/svg/svg_tree_scope_resources.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
@@ -114,7 +116,13 @@ Element* TreeScope::getElementById(const AtomicString& element_id) const {
return nullptr;
if (!elements_by_id_)
return nullptr;
- return elements_by_id_->GetElementById(element_id, *this);
+ Element* element = elements_by_id_->GetElementById(element_id, *this);
+ if (element && &RootNode() == &GetDocument() &&
+ GetDocument().InDOMNodeRemovedHandler()) {
+ if (NodeChildRemovalTracker::IsBeingRemoved(element))
+ GetDocument().CountDetachingNodeAccessInDOMNodeRemovedHandler();
+ }
+ return element;
}
const HeapVector<Member<Element>>& TreeScope::GetAllElementsById(
@@ -200,7 +208,7 @@ static bool PointInFrameContentIfVisible(Document& document,
// The VisibleContentRect check below requires that scrollbars are up-to-date.
document.UpdateStyleAndLayoutIgnorePendingStylesheets();
- auto* scrollable_area = frame_view->LayoutViewportScrollableArea();
+ auto* scrollable_area = frame_view->LayoutViewport();
IntRect visible_frame_rect(IntPoint(),
scrollable_area->VisibleContentRect().Size());
visible_frame_rect.Scale(1 / frame->PageZoomFactor());
@@ -222,8 +230,9 @@ HitTestResult HitTestInDocument(Document* document,
if (!PointInFrameContentIfVisible(*document, hit_point))
return HitTestResult();
- HitTestResult result(request, LayoutPoint(hit_point));
- document->GetLayoutView()->HitTest(result);
+ HitTestLocation location(hit_point);
+ HitTestResult result(request, location);
+ document->GetLayoutView()->HitTest(location, result);
return result;
}
@@ -277,8 +286,8 @@ static bool ShouldAcceptNonElementNode(const Node& node) {
HeapVector<Member<Element>> TreeScope::ElementsFromHitTestResult(
HitTestResult& result) const {
+ DCHECK(RootNode().isConnected());
HeapVector<Member<Element>> elements;
-
Node* last_node = nullptr;
for (const auto rect_based_node : result.ListBasedTestResult()) {
Node* node = rect_based_node.Get();
@@ -295,14 +304,10 @@ HeapVector<Member<Element>> TreeScope::ElementsFromHitTestResult(
last_node = node;
}
}
-
- if (RootNode().IsDocumentNode()) {
- if (Element* root_element = ToDocument(RootNode()).documentElement()) {
- if (elements.IsEmpty() || elements.back() != root_element)
- elements.push_back(root_element);
- }
+ if (Element* document_element = GetDocument().documentElement()) {
+ if (elements.IsEmpty() || elements.back() != document_element)
+ elements.push_back(document_element);
}
-
return elements;
}
@@ -313,11 +318,12 @@ HeapVector<Member<Element>> TreeScope::ElementsFromPoint(double x,
if (!PointInFrameContentIfVisible(document, hit_point))
return HeapVector<Member<Element>>();
+ HitTestLocation location(hit_point);
HitTestRequest request(HitTestRequest::kReadOnly | HitTestRequest::kActive |
HitTestRequest::kListBased |
HitTestRequest::kPenetratingList);
- HitTestResult result(request, LayoutPoint(hit_point));
- document.GetLayoutView()->HitTest(result);
+ HitTestResult result(request, location);
+ document.GetLayoutView()->HitTest(location, result);
return ElementsFromHitTestResult(result);
}
@@ -328,22 +334,6 @@ SVGTreeScopeResources& TreeScope::EnsureSVGTreeScopedResources() {
return *svg_tree_scoped_resources_;
}
-bool TreeScope::HasMoreStyleSheets() const {
- return more_style_sheets_ && more_style_sheets_->length() > 0;
-}
-
-StyleSheetList& TreeScope::MoreStyleSheets() {
- if (!more_style_sheets_)
- SetMoreStyleSheets(StyleSheetList::Create());
- return *more_style_sheets_;
-}
-
-void TreeScope::SetMoreStyleSheets(StyleSheetList* more_style_sheets) {
- GetDocument().GetStyleEngine().MoreStyleSheetsWillChange(
- *this, more_style_sheets_, more_style_sheets);
- more_style_sheets_ = more_style_sheets;
-}
-
DOMSelection* TreeScope::GetSelection() const {
if (!RootNode().GetDocument().GetFrame())
return nullptr;
@@ -599,7 +589,6 @@ void TreeScope::Trace(blink::Visitor* visitor) {
visitor->Trace(scoped_style_resolver_);
visitor->Trace(radio_button_group_scope_);
visitor->Trace(svg_tree_scoped_resources_);
- visitor->Trace(more_style_sheets_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/tree_scope.h b/chromium/third_party/blink/renderer/core/dom/tree_scope.h
index 0c4eeec22dc..63d0cb9206d 100644
--- a/chromium/third_party/blink/renderer/core/dom/tree_scope.h
+++ b/chromium/third_party/blink/renderer/core/dom/tree_scope.h
@@ -43,10 +43,8 @@ class Element;
class HTMLMapElement;
class HitTestResult;
class IdTargetObserverRegistry;
-class Node;
class SVGTreeScopeResources;
class ScopedStyleResolver;
-class StyleSheetList;
// The root node of a document tree (in which case this is a Document) or of a
// shadow tree (in which case this is a ShadowRoot). Various things, like
@@ -141,10 +139,6 @@ class CORE_EXPORT TreeScope : public GarbageCollectedMixin {
SVGTreeScopeResources& EnsureSVGTreeScopedResources();
- bool HasMoreStyleSheets() const;
- StyleSheetList& MoreStyleSheets();
- void SetMoreStyleSheets(StyleSheetList*);
-
protected:
TreeScope(ContainerNode&, Document&);
TreeScope(Document&);
@@ -174,8 +168,6 @@ class CORE_EXPORT TreeScope : public GarbageCollectedMixin {
RadioButtonGroupScope radio_button_group_scope_;
Member<SVGTreeScopeResources> svg_tree_scoped_resources_;
-
- Member<StyleSheetList> more_style_sheets_;
};
inline bool TreeScope::HasElementWithId(const AtomicString& id) const {
diff --git a/chromium/third_party/blink/renderer/core/dom/tree_walker.cc b/chromium/third_party/blink/renderer/core/dom/tree_walker.cc
index c016bff5bb9..19491db3a8a 100644
--- a/chromium/third_party/blink/renderer/core/dom/tree_walker.cc
+++ b/chromium/third_party/blink/renderer/core/dom/tree_walker.cc
@@ -24,12 +24,11 @@
#include "third_party/blink/renderer/core/dom/tree_walker.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_node_filter.h"
#include "third_party/blink/renderer/core/dom/container_node.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/dom/node_traversal_strategy.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -255,9 +254,4 @@ void TreeWalker::Trace(blink::Visitor* visitor) {
NodeIteratorBase::Trace(visitor);
}
-void TreeWalker::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- ScriptWrappable::TraceWrappers(visitor);
- NodeIteratorBase::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/tree_walker.h b/chromium/third_party/blink/renderer/core/dom/tree_walker.h
index b38454b151f..97d51f00efa 100644
--- a/chromium/third_party/blink/renderer/core/dom/tree_walker.h
+++ b/chromium/third_party/blink/renderer/core/dom/tree_walker.h
@@ -57,8 +57,6 @@ class TreeWalker final : public ScriptWrappable, public NodeIteratorBase {
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
private:
TreeWalker(Node*, unsigned what_to_show, V8NodeFilter*);
diff --git a/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_html.cc b/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_html.cc
deleted file mode 100644
index e1f872d9231..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_html.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/dom/trustedtypes/trusted_html.h"
-
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-
-namespace blink {
-
-TrustedHTML::TrustedHTML(const String& html) : html_(html) {}
-
-TrustedHTML* TrustedHTML::escape(ScriptState* script_state,
- const String& html) {
- // TODO(mkwst): This could be hugely optimized by scanning the string for any
- // of the interesting characters to see whether we need to do any replacement
- // at all, and by replacing all the characters in a single pass.
- String escapedHTML(html);
- escapedHTML.Replace("&", "&amp;")
- .Replace("<", "&lt;")
- .Replace(">", "&gt;")
- .Replace("\"", "&quot;")
- .Replace("'", "&#39;");
-
- return TrustedHTML::unsafelyCreate(script_state, escapedHTML);
-}
-
-TrustedHTML* TrustedHTML::unsafelyCreate(ScriptState* script_state,
- const String& html) {
- return TrustedHTML::Create(html);
-}
-
-String TrustedHTML::toString() const {
- return html_;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_html.h b/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_html.h
deleted file mode 100644
index a32710256f0..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_html.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TRUSTEDTYPES_TRUSTED_HTML_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TRUSTEDTYPES_TRUSTED_HTML_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#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/wtf/text/wtf_string.h"
-
-namespace blink {
-
-class ScriptState;
-
-class CORE_EXPORT TrustedHTML final : public ScriptWrappable {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- static TrustedHTML* Create(const String& html) {
- return new TrustedHTML(html);
- }
-
- // CredentialsContainer.idl
- String toString() const;
- static TrustedHTML* escape(ScriptState*, const String& html);
- static TrustedHTML* unsafelyCreate(ScriptState*, const String& html);
-
- private:
- TrustedHTML(const String& html);
-
- const String html_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TRUSTEDTYPES_TRUSTED_HTML_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.cc b/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.cc
deleted file mode 100644
index 3956b19f94b..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.cc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.h"
-
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-
-namespace blink {
-
-TrustedScriptURL::TrustedScriptURL(const KURL& url) : url_(url) {}
-
-TrustedScriptURL* TrustedScriptURL::unsafelyCreate(ScriptState* script_state,
- const String& url) {
- return TrustedScriptURL::Create(
- ExecutionContext::From(script_state)->CompleteURL(url));
-}
-
-String TrustedScriptURL::toString() const {
- return url_.GetString();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.h b/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.h
deleted file mode 100644
index 4f22b32d6de..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TRUSTEDTYPES_TRUSTED_SCRIPT_URL_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TRUSTEDTYPES_TRUSTED_SCRIPT_URL_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#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/weborigin/kurl.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-class ScriptState;
-
-class CORE_EXPORT TrustedScriptURL final : public ScriptWrappable {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- static TrustedScriptURL* Create(const KURL& url) {
- return new TrustedScriptURL(url);
- }
-
- // TrustedScriptURL.idl
- String toString() const;
- static TrustedScriptURL* unsafelyCreate(ScriptState*, const String& url);
-
- private:
- TrustedScriptURL(const KURL&);
-
- KURL url_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TRUSTEDTYPES_TRUSTED_SCRIPT_URL_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_url.cc b/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_url.cc
deleted file mode 100644
index ff620436ba0..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_url.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/dom/trustedtypes/trusted_url.h"
-
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-
-namespace blink {
-
-TrustedURL::TrustedURL(const KURL& url) : url_(url) {}
-
-TrustedURL* TrustedURL::create(ScriptState* script_state, const String& url) {
- KURL result(ExecutionContext::From(script_state)->CompleteURL(url));
-
- if (!result.IsValid() || !result.ProtocolIsInHTTPFamily())
- result = KURL("about:invalid");
-
- return TrustedURL::Create(result);
-}
-
-TrustedURL* TrustedURL::unsafelyCreate(ScriptState* script_state,
- const String& url) {
- return TrustedURL::Create(
- ExecutionContext::From(script_state)->CompleteURL(url));
-}
-
-String TrustedURL::toString() const {
- return url_.GetString();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_url.h b/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_url.h
deleted file mode 100644
index 2b2f99478f8..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_url.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TRUSTEDTYPES_TRUSTED_URL_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TRUSTEDTYPES_TRUSTED_URL_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#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/weborigin/kurl.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-class ScriptState;
-
-class CORE_EXPORT TrustedURL final : public ScriptWrappable {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- static TrustedURL* Create(const KURL& url) { return new TrustedURL(url); }
-
- // TrustedURL.idl
- String toString() const;
- static TrustedURL* create(ScriptState*, const String& url);
- static TrustedURL* unsafelyCreate(ScriptState*, const String& url);
-
- private:
- TrustedURL(const KURL&);
-
- KURL url_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_TRUSTEDTYPES_TRUSTED_URL_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/user_action_element_set.h b/chromium/third_party/blink/renderer/core/dom/user_action_element_set.h
index db820a6ebcb..9287449d807 100644
--- a/chromium/third_party/blink/renderer/core/dom/user_action_element_set.h
+++ b/chromium/third_party/blink/renderer/core/dom/user_action_element_set.h
@@ -43,9 +43,6 @@ class UserActionElementSet final {
bool HasFocusWithin(const Node* node) {
return HasFlags(node, kHasFocusWithinFlag);
}
- bool WasFocusedByMouse(const Node* node) {
- return HasFlags(node, kWasFocusedByMouseFlag);
- }
bool IsActive(const Node* node) { return HasFlags(node, kIsActiveFlag); }
bool IsInActiveChain(const Node* node) {
return HasFlags(node, kInActiveChainFlag);
@@ -58,9 +55,6 @@ class UserActionElementSet final {
void SetHasFocusWithin(Node* node, bool enable) {
SetFlags(node, enable, kHasFocusWithinFlag);
}
- void SetWasFocusedByMouse(Node* node, bool enable) {
- SetFlags(node, enable, kWasFocusedByMouseFlag);
- }
void SetActive(Node* node, bool enable) {
SetFlags(node, enable, kIsActiveFlag);
}
@@ -89,7 +83,6 @@ class UserActionElementSet final {
kIsFocusedFlag = 1 << 3,
kIsDraggedFlag = 1 << 4,
kHasFocusWithinFlag = 1 << 5,
- kWasFocusedByMouseFlag = 1 << 6,
};
void SetFlags(Node* node, bool enable, unsigned flags) {
diff --git a/chromium/third_party/blink/renderer/core/dom/user_gesture_indicator.h b/chromium/third_party/blink/renderer/core/dom/user_gesture_indicator.h
index 41113c3085a..e32295f4e0e 100644
--- a/chromium/third_party/blink/renderer/core/dom/user_gesture_indicator.h
+++ b/chromium/third_party/blink/renderer/core/dom/user_gesture_indicator.h
@@ -8,7 +8,6 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.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/ref_counted.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/dom/user_gesture_indicator_test.cc b/chromium/third_party/blink/renderer/core/dom/user_gesture_indicator_test.cc
index 0b946a49ace..df4f5ea6f82 100644
--- a/chromium/third_party/blink/renderer/core/dom/user_gesture_indicator_test.cc
+++ b/chromium/third_party/blink/renderer/core/dom/user_gesture_indicator_test.cc
@@ -6,20 +6,11 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/platform/testing/wtf/scoped_mock_clock.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink {
-static double g_current_time = 1000.0;
-
-static void AdvanceClock(double seconds) {
- g_current_time += seconds;
-}
-
-static double MockTimeFunction() {
- return g_current_time;
-}
-
// Checks for the initial state of UserGestureIndicator.
TEST(UserGestureIndicatorTest, InitialState) {
EXPECT_FALSE(UserGestureIndicator::ProcessingUserGesture());
@@ -120,7 +111,7 @@ TEST(UserGestureIndicatorTest, MultipleGesturesWithTheSameToken) {
}
TEST(UserGestureIndicatorTest, Timeouts) {
- TimeFunction previous = SetTimeFunctionsForTesting(MockTimeFunction);
+ WTF::ScopedMockClock clock;
{
// Token times out after 1 second.
@@ -128,9 +119,9 @@ TEST(UserGestureIndicatorTest, Timeouts) {
Frame::NotifyUserActivation(nullptr);
scoped_refptr<UserGestureToken> token = user_gesture_scope->CurrentToken();
EXPECT_TRUE(token->HasGestures());
- AdvanceClock(0.75);
+ clock.Advance(TimeDelta::FromSecondsD(0.75));
EXPECT_TRUE(token->HasGestures());
- AdvanceClock(0.75);
+ clock.Advance(TimeDelta::FromSecondsD(0.75));
EXPECT_FALSE(token->HasGestures());
}
@@ -143,20 +134,18 @@ TEST(UserGestureIndicatorTest, Timeouts) {
Frame::NotifyUserActivation(nullptr);
token = user_gesture_scope->CurrentToken();
EXPECT_TRUE(token->HasGestures());
- AdvanceClock(0.75);
+ clock.Advance(TimeDelta::FromSecondsD(0.75));
EXPECT_TRUE(token->HasGestures());
}
{
UserGestureIndicator user_gesture_scope(token.get());
- AdvanceClock(0.75);
+ clock.Advance(TimeDelta::FromSecondsD(0.75));
EXPECT_TRUE(token->HasGestures());
- AdvanceClock(0.75);
+ clock.Advance(TimeDelta::FromSecondsD(0.75));
EXPECT_FALSE(token->HasGestures());
}
}
-
- SetTimeFunctionsForTesting(previous);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/viewport_description.cc b/chromium/third_party/blink/renderer/core/dom/viewport_description.cc
deleted file mode 100644
index 200de1d3261..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/viewport_description.cc
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2001 Dirk Mueller (mueller@kde.org)
- * (C) 2006 Alexey Proskuryakov (ap@webkit.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights
- * reserved.
- * Copyright (C) 2008 Torch Mobile Inc. All rights reserved.
- * (http://www.torchmobile.com/)
- * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
- * Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
- *
- * 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/dom/viewport_description.h"
-
-#include "build/build_config.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"
-#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/page/page.h"
-#include "third_party/blink/renderer/platform/histogram.h"
-#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-
-namespace blink {
-
-static const float& CompareIgnoringAuto(const float& value1,
- const float& value2,
- const float& (*compare)(const float&,
- const float&)) {
- if (value1 == ViewportDescription::kValueAuto)
- return value2;
-
- if (value2 == ViewportDescription::kValueAuto)
- return value1;
-
- return compare(value1, value2);
-}
-
-float ViewportDescription::ResolveViewportLength(
- const Length& length,
- const FloatSize& initial_viewport_size,
- Direction direction) {
- if (length.IsAuto())
- return ViewportDescription::kValueAuto;
-
- if (length.IsFixed())
- return length.GetFloatValue();
-
- if (length.GetType() == kExtendToZoom)
- return ViewportDescription::kValueExtendToZoom;
-
- if (length.GetType() == kPercent && direction == kHorizontal)
- return initial_viewport_size.Width() * length.GetFloatValue() / 100.0f;
-
- if (length.GetType() == kPercent && direction == kVertical)
- return initial_viewport_size.Height() * length.GetFloatValue() / 100.0f;
-
- if (length.GetType() == kDeviceWidth)
- return initial_viewport_size.Width();
-
- if (length.GetType() == kDeviceHeight)
- return initial_viewport_size.Height();
-
- NOTREACHED();
- return ViewportDescription::kValueAuto;
-}
-
-PageScaleConstraints ViewportDescription::Resolve(
- const FloatSize& initial_viewport_size,
- Length legacy_fallback_width) const {
- float result_width = kValueAuto;
-
- Length copy_max_width = max_width;
- Length copy_min_width = min_width;
- // In case the width (used for min- and max-width) is undefined.
- if (IsLegacyViewportType() && max_width.IsAuto()) {
- // The width viewport META property is translated into 'width' descriptors,
- // setting the 'min' value to 'extend-to-zoom' and the 'max' value to the
- // intended length. In case the UA-defines a min-width, use that as length.
- if (zoom == ViewportDescription::kValueAuto) {
- copy_min_width = Length(kExtendToZoom);
- copy_max_width = legacy_fallback_width;
- } else if (max_height.IsAuto()) {
- copy_min_width = Length(kExtendToZoom);
- copy_max_width = Length(kExtendToZoom);
- }
- }
-
- float result_max_width =
- ResolveViewportLength(copy_max_width, initial_viewport_size, kHorizontal);
- float result_min_width =
- ResolveViewportLength(copy_min_width, initial_viewport_size, kHorizontal);
-
- float result_height = kValueAuto;
- float result_max_height =
- ResolveViewportLength(max_height, initial_viewport_size, kVertical);
- float result_min_height =
- ResolveViewportLength(min_height, initial_viewport_size, kVertical);
-
- float result_zoom = zoom;
- float result_min_zoom = min_zoom;
- float result_max_zoom = max_zoom;
- bool result_user_zoom = user_zoom;
-
- // Resolve min-zoom and max-zoom values.
- if (result_min_zoom != ViewportDescription::kValueAuto &&
- result_max_zoom != ViewportDescription::kValueAuto)
- result_max_zoom = std::max(result_min_zoom, result_max_zoom);
-
- // Constrain zoom value to the [min-zoom, max-zoom] range.
- if (result_zoom != ViewportDescription::kValueAuto)
- result_zoom = CompareIgnoringAuto(
- result_min_zoom,
- CompareIgnoringAuto(result_max_zoom, result_zoom, std::min), std::max);
-
- float extend_zoom =
- CompareIgnoringAuto(result_zoom, result_max_zoom, std::min);
-
- // Resolve non-"auto" lengths to pixel lengths.
- if (extend_zoom == ViewportDescription::kValueAuto) {
- if (result_max_width == ViewportDescription::kValueExtendToZoom)
- result_max_width = ViewportDescription::kValueAuto;
-
- if (result_max_height == ViewportDescription::kValueExtendToZoom)
- result_max_height = ViewportDescription::kValueAuto;
-
- if (result_min_width == ViewportDescription::kValueExtendToZoom)
- result_min_width = result_max_width;
-
- if (result_min_height == ViewportDescription::kValueExtendToZoom)
- result_min_height = result_max_height;
- } else {
- float extend_width = initial_viewport_size.Width() / extend_zoom;
- float extend_height = initial_viewport_size.Height() / extend_zoom;
-
- if (result_max_width == ViewportDescription::kValueExtendToZoom)
- result_max_width = extend_width;
-
- if (result_max_height == ViewportDescription::kValueExtendToZoom)
- result_max_height = extend_height;
-
- if (result_min_width == ViewportDescription::kValueExtendToZoom)
- result_min_width =
- CompareIgnoringAuto(extend_width, result_max_width, std::max);
-
- if (result_min_height == ViewportDescription::kValueExtendToZoom)
- result_min_height =
- CompareIgnoringAuto(extend_height, result_max_height, std::max);
- }
-
- // Resolve initial width from min/max descriptors.
- if (result_min_width != ViewportDescription::kValueAuto ||
- result_max_width != ViewportDescription::kValueAuto)
- result_width = CompareIgnoringAuto(
- result_min_width,
- CompareIgnoringAuto(result_max_width, initial_viewport_size.Width(),
- std::min),
- std::max);
-
- // Resolve initial height from min/max descriptors.
- if (result_min_height != ViewportDescription::kValueAuto ||
- result_max_height != ViewportDescription::kValueAuto)
- result_height = CompareIgnoringAuto(
- result_min_height,
- CompareIgnoringAuto(result_max_height, initial_viewport_size.Height(),
- std::min),
- std::max);
-
- // Resolve width value.
- if (result_width == ViewportDescription::kValueAuto) {
- if (result_height == ViewportDescription::kValueAuto ||
- !initial_viewport_size.Height())
- result_width = initial_viewport_size.Width();
- else
- result_width = result_height * (initial_viewport_size.Width() /
- initial_viewport_size.Height());
- }
-
- // Resolve height value.
- if (result_height == ViewportDescription::kValueAuto) {
- if (!initial_viewport_size.Width())
- result_height = initial_viewport_size.Height();
- else
- result_height = result_width * initial_viewport_size.Height() /
- initial_viewport_size.Width();
- }
-
- // Resolve initial-scale value.
- if (result_zoom == ViewportDescription::kValueAuto) {
- if (result_width != ViewportDescription::kValueAuto && result_width > 0)
- result_zoom = initial_viewport_size.Width() / result_width;
- if (result_height != ViewportDescription::kValueAuto && result_height > 0) {
- // if 'auto', the initial-scale will be negative here and thus ignored.
- result_zoom = std::max<float>(
- result_zoom, initial_viewport_size.Height() / result_height);
- }
-
- // Reconstrain zoom value to the [min-zoom, max-zoom] range.
- result_zoom = CompareIgnoringAuto(
- result_min_zoom,
- CompareIgnoringAuto(result_max_zoom, result_zoom, std::min), std::max);
- }
-
- // If user-scalable = no, lock the min/max scale to the computed initial
- // scale.
- if (!result_user_zoom)
- result_min_zoom = result_max_zoom = result_zoom;
-
- // Only set initialScale to a value if it was explicitly set.
- if (zoom == ViewportDescription::kValueAuto)
- result_zoom = ViewportDescription::kValueAuto;
-
- PageScaleConstraints result;
- result.minimum_scale = result_min_zoom;
- result.maximum_scale = result_max_zoom;
- result.initial_scale = result_zoom;
- result.layout_size.SetWidth(result_width);
- result.layout_size.SetHeight(result_height);
- return result;
-}
-
-void ViewportDescription::ReportMobilePageStats(
- const LocalFrame* main_frame) const {
-
- if (!main_frame || !main_frame->GetPage() || !main_frame->View() ||
- !main_frame->GetDocument())
- return;
-
- if (!main_frame->GetSettings() ||
- !main_frame->GetSettings()->GetViewportEnabled())
- return;
-
- // Avoid chrome:// pages like the new-tab page (on Android new tab is
- // non-http).
- if (!main_frame->GetDocument()->Url().ProtocolIsInHTTPFamily())
- return;
-
- DEFINE_STATIC_LOCAL(
- EnumerationHistogram, meta_tag_type_histogram,
- ("Viewport.MetaTagType", static_cast<int>(ViewportUMAType::kTypeCount)));
- if (!IsSpecifiedByAuthor()) {
- meta_tag_type_histogram.Count(
- main_frame->GetDocument()->IsMobileDocument()
- ? static_cast<int>(ViewportUMAType::kXhtmlMobileProfile)
- : static_cast<int>(ViewportUMAType::kNoViewportTag));
- return;
- }
-
- if (IsMetaViewportType()) {
- if (max_width.GetType() == blink::kFixed) {
- meta_tag_type_histogram.Count(
- static_cast<int>(ViewportUMAType::kConstantWidth));
-
- if (main_frame->View()) {
- // To get an idea of how "far" the viewport is from the device's ideal
- // width, we report the zoom level that we'd need to be at for the
- // entire page to be visible.
- int viewport_width = max_width.IntValue();
- int window_width =
- main_frame->GetPage()->GetVisualViewport().Size().Width();
- int overview_zoom_percent =
- 100 * window_width / static_cast<float>(viewport_width);
- DEFINE_STATIC_LOCAL(SparseHistogram, overview_zoom_histogram,
- ("Viewport.OverviewZoom"));
- overview_zoom_histogram.Sample(overview_zoom_percent);
- }
-
- } else if (max_width.GetType() == blink::kDeviceWidth ||
- max_width.GetType() == blink::kExtendToZoom) {
- meta_tag_type_histogram.Count(
- static_cast<int>(ViewportUMAType::kDeviceWidth));
- } else {
- // Overflow bucket for cases we may be unaware of.
- meta_tag_type_histogram.Count(
- static_cast<int>(ViewportUMAType::kMetaWidthOther));
- }
- } else if (type == ViewportDescription::kHandheldFriendlyMeta) {
- meta_tag_type_histogram.Count(
- static_cast<int>(ViewportUMAType::kMetaHandheldFriendly));
- } else if (type == ViewportDescription::kMobileOptimizedMeta) {
- meta_tag_type_histogram.Count(
- static_cast<int>(ViewportUMAType::kMetaMobileOptimized));
- }
-}
-
-bool ViewportDescription::MatchesHeuristicsForGpuRasterization() const {
- return IsSpecifiedByAuthor();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/dom/viewport_description.h b/chromium/third_party/blink/renderer/core/dom/viewport_description.h
deleted file mode 100644
index 5dacc0ff081..00000000000
--- a/chromium/third_party/blink/renderer/core/dom/viewport_description.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2001 Dirk Mueller (mueller@kde.org)
- * (C) 2006 Alexey Proskuryakov (ap@webkit.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Torch Mobile Inc. All rights reserved.
- * (http://www.torchmobile.com/)
- * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
- * Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
- *
- * 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_DOM_VIEWPORT_DESCRIPTION_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_VIEWPORT_DESCRIPTION_H_
-
-#include "base/optional.h"
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/frame/page_scale_constraints.h"
-#include "third_party/blink/renderer/platform/geometry/float_size.h"
-#include "third_party/blink/renderer/platform/length.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class LocalFrame;
-
-struct CORE_EXPORT ViewportDescription {
- DISALLOW_NEW();
-
- enum Type {
- // These are ordered in increasing importance.
- kUserAgentStyleSheet,
- kHandheldFriendlyMeta,
- kMobileOptimizedMeta,
- kViewportMeta,
- kAuthorStyleSheet
- } type;
-
- // Enums used to record the kind of viewport in the Viewport.MetaTagType
- // histogram. These must match the enums in histograms.xml and existing
- // entries must not be changed.
- enum class ViewportUMAType : int {
- kNoViewportTag = 0,
- kDeviceWidth = 1,
- kConstantWidth = 2,
- kMetaWidthOther = 3,
- kMetaHandheldFriendly = 4,
- kMetaMobileOptimized = 5,
- kXhtmlMobileProfile = 6,
-
- kTypeCount = 7
- };
-
- // Stores the different possible |viewport-fit| configurations.
- enum class ViewportFit {
- // No effect - the whole web page is viewable (default).
- kAuto = 0,
-
- // The initial layout viewport and the visual viewport are set to the
- // largest rectangle which is inscribed in the display of the device.
- kContain,
-
- // The initial layout viewport and the visual viewport are set to the
- // circumscribed rectangle of the physical screen of the device.
- kCover,
- };
-
- enum {
- kValueAuto = -1,
- kValueDeviceWidth = -2,
- kValueDeviceHeight = -3,
- kValuePortrait = -4,
- kValueLandscape = -5,
- kValueDeviceDPI = -6,
- kValueLowDPI = -7,
- kValueMediumDPI = -8,
- kValueHighDPI = -9,
- kValueExtendToZoom = -10
- };
-
- ViewportDescription(Type type = kUserAgentStyleSheet)
- : type(type),
- zoom(kValueAuto),
- min_zoom(kValueAuto),
- max_zoom(kValueAuto),
- user_zoom(true),
- orientation(kValueAuto),
- deprecated_target_density_dpi(kValueAuto),
- zoom_is_explicit(false),
- min_zoom_is_explicit(false),
- max_zoom_is_explicit(false),
- user_zoom_is_explicit(false) {}
-
- // All arguments are in CSS units.
- PageScaleConstraints Resolve(const FloatSize& initial_viewport_size,
- Length legacy_fallback_width) const;
-
- // When --use-zoom-for-dsf is enabled, if the type is kFixed, these Length
- // values (i.e., |min_width|, |max_width|, |min_height|, and |max_height|)
- // must be in physical pixel scale. When --use-zoom-for-dsf is disabled, if
- // the type is kFixed, these Length values must be in DIP scale.
- Length min_width;
- Length max_width;
- Length min_height;
- Length max_height;
- float zoom;
- float min_zoom;
- float max_zoom;
- bool user_zoom;
- float orientation;
- float deprecated_target_density_dpi; // Only used for Android WebView
-
- // Whether the computed value was explicitly specified rather than being
- // inferred.
- bool zoom_is_explicit;
- bool min_zoom_is_explicit;
- bool max_zoom_is_explicit;
- bool user_zoom_is_explicit;
-
- ViewportFit GetViewportFit() const {
- return viewport_fit_.value_or(ViewportFit::kAuto);
- }
- void SetViewportFit(ViewportFit value) { viewport_fit_ = value; }
-
- bool operator==(const ViewportDescription& other) const {
- // Used for figuring out whether to reset the viewport or not,
- // thus we are not taking type into account.
- return min_width == other.min_width && max_width == other.max_width &&
- min_height == other.min_height && max_height == other.max_height &&
- zoom == other.zoom && min_zoom == other.min_zoom &&
- max_zoom == other.max_zoom && user_zoom == other.user_zoom &&
- orientation == other.orientation &&
- deprecated_target_density_dpi ==
- other.deprecated_target_density_dpi &&
- zoom_is_explicit == other.zoom_is_explicit &&
- min_zoom_is_explicit == other.min_zoom_is_explicit &&
- max_zoom_is_explicit == other.max_zoom_is_explicit &&
- user_zoom_is_explicit == other.user_zoom_is_explicit &&
- viewport_fit_ == other.viewport_fit_;
- }
-
- bool operator!=(const ViewportDescription& other) const {
- return !(*this == other);
- }
-
- bool IsLegacyViewportType() const {
- return type >= kHandheldFriendlyMeta && type <= kViewportMeta;
- }
- bool IsMetaViewportType() const { return type == kViewportMeta; }
- bool IsSpecifiedByAuthor() const { return type != kUserAgentStyleSheet; }
- bool MatchesHeuristicsForGpuRasterization() const;
-
- // Reports UMA stat on whether the page is considered mobile or desktop and
- // what kind of mobile it is. Applies only to Android, must only be called
- // once per page load.
- void ReportMobilePageStats(const LocalFrame*) const;
-
- private:
- enum Direction { kHorizontal, kVertical };
- static float ResolveViewportLength(const Length&,
- const FloatSize& initial_viewport_size,
- Direction);
-
- base::Optional<ViewportFit> viewport_fit_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_VIEWPORT_DESCRIPTION_H_
diff --git a/chromium/third_party/blink/renderer/core/editing/BUILD.gn b/chromium/third_party/blink/renderer/core/editing/BUILD.gn
index 2db2e5ef066..ea78e473a3d 100644
--- a/chromium/third_party/blink/renderer/core/editing/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/editing/BUILD.gn
@@ -176,6 +176,7 @@ blink_core_sources("editing") {
"iterators/text_iterator_text_state.h",
"iterators/text_searcher_icu.cc",
"iterators/text_searcher_icu.h",
+ "kill_ring.h",
"layout_selection.cc",
"layout_selection.h",
"local_caret_rect.cc",
@@ -307,6 +308,8 @@ blink_core_sources("editing") {
"text_granularity.h",
"text_offset_mapping.cc",
"text_offset_mapping.h",
+ "text_segments.cc",
+ "text_segments.h",
"visible_position.cc",
"visible_position.h",
"visible_selection.cc",
@@ -322,7 +325,12 @@ blink_core_sources("editing") {
]
if (is_mac) {
- sources += [ "commands/smart_replace_cf.cc" ]
+ sources += [
+ "commands/smart_replace_cf.cc",
+ "kill_ring_mac.mm",
+ ]
+ } else {
+ sources += [ "kill_ring_none.cc" ]
}
}
@@ -391,6 +399,7 @@ jumbo_source_set("unit_tests") {
"selection_controller_test.cc",
"selection_modifier_character_test.cc",
"selection_modifier_test.cc",
+ "selection_modifier_word_test.cc",
"selection_template_test.cc",
"serializers/styled_markup_serializer_test.cc",
"set_selection_options_test.cc",
diff --git a/chromium/third_party/blink/renderer/core/editing/caret_display_item_client.cc b/chromium/third_party/blink/renderer/core/editing/caret_display_item_client.cc
index af432495ae1..02b2bb4b2bd 100644
--- a/chromium/third_party/blink/renderer/core/editing/caret_display_item_client.cc
+++ b/chromium/third_party/blink/renderer/core/editing/caret_display_item_client.cc
@@ -202,14 +202,6 @@ void CaretDisplayItemClient::InvalidatePaintInPreviousLayoutBlock(
ObjectPaintInvalidatorWithContext object_invalidator(*previous_layout_block_,
context);
- // For SPv175 raster invalidation will be done in PaintController.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- !IsImmediateFullPaintInvalidationReason(
- previous_layout_block_->FullPaintInvalidationReason())) {
- object_invalidator.InvalidatePaintRectangleWithContext(
- visual_rect_in_previous_layout_block_, PaintInvalidationReason::kCaret);
- }
-
context.painting_layer->SetNeedsRepaint();
object_invalidator.InvalidateDisplayItemClient(
*this, PaintInvalidationReason::kCaret);
@@ -228,8 +220,7 @@ void CaretDisplayItemClient::InvalidatePaintInCurrentLayoutBlock(
if (context.NeedsVisualRectUpdate(*layout_block_)) {
if (!local_rect_.IsEmpty()) {
new_visual_rect = local_rect_;
- context.MapLocalRectToVisualRectInBacking(*layout_block_,
- new_visual_rect);
+ context.MapLocalRectToVisualRect(*layout_block_, new_visual_rect);
if (layout_block_->UsesCompositedScrolling()) {
// The caret should use scrolling coordinate space.
@@ -251,13 +242,7 @@ void CaretDisplayItemClient::InvalidatePaintInCurrentLayoutBlock(
// need to invalidate the display item client if the block is doing full
// paint invalidation.
if (IsImmediateFullPaintInvalidationReason(
- layout_block_->FullPaintInvalidationReason()) ||
- // For SPv1, kSubtreeInvalidationChecking may hint change of
- // paint offset. See ObjectPaintInvalidatorWithContext::
- // invalidatePaintIfNeededWithComputedReason().
- (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- (context.subtree_flags &
- PaintInvalidatorContext::kSubtreeInvalidationChecking))) {
+ layout_block_->FullPaintInvalidationReason())) {
object_invalidator.InvalidateDisplayItemClient(
*this, PaintInvalidationReason::kCaret);
}
@@ -266,13 +251,6 @@ void CaretDisplayItemClient::InvalidatePaintInCurrentLayoutBlock(
needs_paint_invalidation_ = false;
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- !IsImmediateFullPaintInvalidationReason(
- layout_block_->FullPaintInvalidationReason())) {
- object_invalidator.FullyInvalidatePaint(PaintInvalidationReason::kCaret,
- visual_rect_, new_visual_rect);
- }
-
context.painting_layer->SetNeedsRepaint();
object_invalidator.InvalidateDisplayItemClient(
*this, PaintInvalidationReason::kCaret);
diff --git a/chromium/third_party/blink/renderer/core/editing/caret_display_item_client_test.cc b/chromium/third_party/blink/renderer/core/editing/caret_display_item_client_test.cc
index af6cd31f176..19cc6e4369b 100644
--- a/chromium/third_party/blink/renderer/core/editing/caret_display_item_client_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/caret_display_item_client_test.cc
@@ -4,38 +4,27 @@
#include "third_party/blink/renderer/core/editing/caret_display_item_client.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
+#include "third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h"
-#include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
namespace blink {
-class CaretDisplayItemClientTest : public PaintTestConfigurations,
- public RenderingTest {
+using ::testing::UnorderedElementsAre;
+
+class CaretDisplayItemClientTest : public PaintAndRasterInvalidationTest {
protected:
void SetUp() override {
- RenderingTest::SetUp();
- EnableCompositing();
+ PaintAndRasterInvalidationTest::SetUp();
Selection().SetCaretBlinkingSuspended(true);
}
- const RasterInvalidationTracking* GetRasterInvalidationTracking() const {
- // TODO(wangxianzhu): Test SPv2.
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
- return GetLayoutView()
- .Layer()
- ->GraphicsLayerBacking()
- ->GetRasterInvalidationTracking();
- }
-
FrameSelection& Selection() const {
return GetDocument().View()->GetFrame().Selection();
}
@@ -100,23 +89,11 @@ TEST_P(CaretDisplayItemClientTest, CaretPaintInvalidation) {
EXPECT_EQ(1, caret_visual_rect.Width());
EXPECT_EQ(block->Location(), caret_visual_rect.Location());
- const Vector<RasterInvalidationInfo>* raster_invalidations;
- if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- raster_invalidations = &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations->size());
- EXPECT_EQ(EnclosingIntRect(caret_visual_rect),
- (*raster_invalidations)[0].rect);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(&GetCaretDisplayItemClient(),
- (*raster_invalidations)[0].client);
- EXPECT_EQ(PaintInvalidationReason::kAppeared,
- (*raster_invalidations)[0].reason);
- } else {
- EXPECT_EQ(block, (*raster_invalidations)[0].client);
- EXPECT_EQ(PaintInvalidationReason::kCaret,
- (*raster_invalidations)[0].reason);
- }
- }
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{&GetCaretDisplayItemClient(), "Caret",
+ EnclosingIntRect(caret_visual_rect),
+ PaintInvalidationReason::kAppeared}));
std::unique_ptr<JSONArray> object_invalidations =
GetDocument().View()->TrackedObjectPaintInvalidationsAsJSON();
@@ -139,30 +116,15 @@ TEST_P(CaretDisplayItemClientTest, CaretPaintInvalidation) {
EXPECT_EQ(caret_visual_rect.Y(), new_caret_visual_rect.Y());
EXPECT_LT(caret_visual_rect.X(), new_caret_visual_rect.X());
- if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- raster_invalidations = &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations->size());
- EXPECT_EQ(EnclosingIntRect(caret_visual_rect),
- (*raster_invalidations)[0].rect);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(&GetCaretDisplayItemClient(),
- (*raster_invalidations)[0].client);
- } else {
- EXPECT_EQ(block, (*raster_invalidations)[0].client);
- }
- EXPECT_EQ(PaintInvalidationReason::kCaret,
- (*raster_invalidations)[0].reason);
- EXPECT_EQ(EnclosingIntRect(new_caret_visual_rect),
- (*raster_invalidations)[1].rect);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(&GetCaretDisplayItemClient(),
- (*raster_invalidations)[1].client);
- } else {
- EXPECT_EQ(block, (*raster_invalidations)[1].client);
- }
- EXPECT_EQ(PaintInvalidationReason::kCaret,
- (*raster_invalidations)[1].reason);
- }
+ EXPECT_THAT(
+ GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{&GetCaretDisplayItemClient(), "Caret",
+ EnclosingIntRect(caret_visual_rect),
+ PaintInvalidationReason::kCaret},
+ RasterInvalidationInfo{&GetCaretDisplayItemClient(), "Caret",
+ EnclosingIntRect(new_caret_visual_rect),
+ PaintInvalidationReason::kCaret}));
object_invalidations =
GetDocument().View()->TrackedObjectPaintInvalidationsAsJSON();
@@ -179,18 +141,11 @@ TEST_P(CaretDisplayItemClientTest, CaretPaintInvalidation) {
EXPECT_FALSE(block->ShouldPaintCursorCaret());
EXPECT_EQ(LayoutRect(), GetCaretDisplayItemClient().VisualRect());
- if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- raster_invalidations = &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations->size());
- EXPECT_EQ(EnclosingIntRect(old_caret_visual_rect),
- (*raster_invalidations)[0].rect);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(&GetCaretDisplayItemClient(),
- (*raster_invalidations)[0].client);
- } else {
- EXPECT_EQ(block, (*raster_invalidations)[0].client);
- }
- }
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ &GetCaretDisplayItemClient(), "Caret",
+ EnclosingIntRect(old_caret_visual_rect),
+ PaintInvalidationReason::kDisappeared}));
object_invalidations =
GetDocument().View()->TrackedObjectPaintInvalidationsAsJSON();
@@ -207,8 +162,8 @@ TEST_P(CaretDisplayItemClientTest, CaretMovesBetweenBlocks) {
auto* block_element1 = AppendBlock("Block1");
auto* block_element2 = AppendBlock("Block2");
UpdateAllLifecyclePhases();
- auto* block1 = ToLayoutBlock(block_element1->GetLayoutObject());
- auto* block2 = ToLayoutBlock(block_element2->GetLayoutObject());
+ auto* block1 = ToLayoutBlockFlow(block_element1->GetLayoutObject());
+ auto* block2 = ToLayoutBlockFlow(block_element2->GetLayoutObject());
// Focus the body.
GetDocument().body()->focus();
@@ -235,36 +190,14 @@ TEST_P(CaretDisplayItemClientTest, CaretMovesBetweenBlocks) {
EXPECT_FALSE(block1->ShouldPaintCursorCaret());
EXPECT_TRUE(block2->ShouldPaintCursorCaret());
- const Vector<RasterInvalidationInfo>* raster_invalidations;
- if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- raster_invalidations = &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations->size());
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(EnclosingIntRect(caret_visual_rect1),
- (*raster_invalidations)[0].rect);
- EXPECT_EQ(&GetCaretDisplayItemClient(),
- (*raster_invalidations)[0].client);
- EXPECT_EQ(PaintInvalidationReason::kCaret,
- (*raster_invalidations)[0].reason);
- EXPECT_EQ(EnclosingIntRect(caret_visual_rect2),
- (*raster_invalidations)[1].rect);
- EXPECT_EQ(&GetCaretDisplayItemClient(),
- (*raster_invalidations)[1].client);
- EXPECT_EQ(PaintInvalidationReason::kCaret,
- (*raster_invalidations)[1].reason);
- } else {
- EXPECT_EQ(EnclosingIntRect(caret_visual_rect1),
- (*raster_invalidations)[0].rect);
- EXPECT_EQ(block1, (*raster_invalidations)[0].client);
- EXPECT_EQ(PaintInvalidationReason::kCaret,
- (*raster_invalidations)[0].reason);
- EXPECT_EQ(EnclosingIntRect(caret_visual_rect2),
- (*raster_invalidations)[1].rect);
- EXPECT_EQ(block2, (*raster_invalidations)[1].client);
- EXPECT_EQ(PaintInvalidationReason::kCaret,
- (*raster_invalidations)[1].reason);
- }
- }
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{&GetCaretDisplayItemClient(), "Caret",
+ EnclosingIntRect(caret_visual_rect1),
+ PaintInvalidationReason::kCaret},
+ RasterInvalidationInfo{&GetCaretDisplayItemClient(), "Caret",
+ EnclosingIntRect(caret_visual_rect2),
+ PaintInvalidationReason::kCaret}));
std::unique_ptr<JSONArray> object_invalidations =
GetDocument().View()->TrackedObjectPaintInvalidationsAsJSON();
@@ -283,35 +216,14 @@ TEST_P(CaretDisplayItemClientTest, CaretMovesBetweenBlocks) {
EXPECT_TRUE(block1->ShouldPaintCursorCaret());
EXPECT_FALSE(block2->ShouldPaintCursorCaret());
- if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- raster_invalidations = &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations->size());
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(EnclosingIntRect(caret_visual_rect2),
- (*raster_invalidations)[0].rect);
- EXPECT_EQ(&GetCaretDisplayItemClient(),
- (*raster_invalidations)[0].client);
- EXPECT_EQ(PaintInvalidationReason::kCaret,
- (*raster_invalidations)[0].reason);
- EXPECT_EQ(EnclosingIntRect(caret_visual_rect1),
- (*raster_invalidations)[1].rect);
- EXPECT_EQ(&GetCaretDisplayItemClient(),
- (*raster_invalidations)[1].client);
- EXPECT_EQ(PaintInvalidationReason::kCaret,
- (*raster_invalidations)[1].reason);
- } else {
- EXPECT_EQ(EnclosingIntRect(caret_visual_rect1),
- (*raster_invalidations)[0].rect);
- EXPECT_EQ(block1, (*raster_invalidations)[0].client);
- EXPECT_EQ(PaintInvalidationReason::kCaret,
- (*raster_invalidations)[0].reason);
- EXPECT_EQ(EnclosingIntRect(caret_visual_rect2),
- (*raster_invalidations)[1].rect);
- EXPECT_EQ(block2, (*raster_invalidations)[1].client);
- EXPECT_EQ(PaintInvalidationReason::kCaret,
- (*raster_invalidations)[1].reason);
- }
- }
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{&GetCaretDisplayItemClient(), "Caret",
+ EnclosingIntRect(caret_visual_rect1),
+ PaintInvalidationReason::kCaret},
+ RasterInvalidationInfo{&GetCaretDisplayItemClient(), "Caret",
+ EnclosingIntRect(caret_visual_rect2),
+ PaintInvalidationReason::kCaret}));
object_invalidations =
GetDocument().View()->TrackedObjectPaintInvalidationsAsJSON();
@@ -410,25 +322,15 @@ TEST_P(CaretDisplayItemClientTest, CaretHideMoveAndShow) {
EXPECT_EQ(caret_visual_rect.Y(), new_caret_visual_rect.Y());
EXPECT_LT(caret_visual_rect.X(), new_caret_visual_rect.X());
- if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- const auto& raster_invalidations =
- GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations.size());
- EXPECT_EQ(EnclosingIntRect(caret_visual_rect),
- raster_invalidations[0].rect);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- EXPECT_EQ(&GetCaretDisplayItemClient(), raster_invalidations[0].client);
- else
- EXPECT_EQ(block, raster_invalidations[0].client);
- EXPECT_EQ(PaintInvalidationReason::kCaret, raster_invalidations[0].reason);
- EXPECT_EQ(EnclosingIntRect(new_caret_visual_rect),
- raster_invalidations[1].rect);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- EXPECT_EQ(&GetCaretDisplayItemClient(), raster_invalidations[1].client);
- else
- EXPECT_EQ(block, raster_invalidations[1].client);
- EXPECT_EQ(PaintInvalidationReason::kCaret, raster_invalidations[1].reason);
- }
+ EXPECT_THAT(
+ GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{&GetCaretDisplayItemClient(), "Caret",
+ EnclosingIntRect(caret_visual_rect),
+ PaintInvalidationReason::kCaret},
+ RasterInvalidationInfo{&GetCaretDisplayItemClient(), "Caret",
+ EnclosingIntRect(new_caret_visual_rect),
+ PaintInvalidationReason::kCaret}));
auto object_invalidations =
GetDocument().View()->TrackedObjectPaintInvalidationsAsJSON();
@@ -440,10 +342,6 @@ TEST_P(CaretDisplayItemClientTest, CaretHideMoveAndShow) {
}
TEST_P(CaretDisplayItemClientTest, CompositingChange) {
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- return;
-
- EnableCompositing();
SetBodyInnerHTML(
"<style>"
" body { margin: 0 }"
@@ -470,7 +368,12 @@ TEST_P(CaretDisplayItemClientTest, CompositingChange) {
// Composite container.
container->setAttribute(HTMLNames::styleAttr, "will-change: transform");
UpdateAllLifecyclePhases();
- EXPECT_EQ(LayoutRect(50, 50, 1, 1), GetCaretDisplayItemClient().VisualRect());
+ // TODO(wangxianzhu): Why will-change:transform doens't trigger compositing
+ // in SPv2?
+ if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ EXPECT_EQ(LayoutRect(50, 50, 1, 1),
+ GetCaretDisplayItemClient().VisualRect());
+ }
// Uncomposite container.
container->setAttribute(HTMLNames::styleAttr, "");
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/append_node_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/append_node_command.cc
index f4ba2617395..4978f7b4566 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/append_node_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/append_node_command.cc
@@ -25,8 +25,8 @@
#include "third_party/blink/renderer/core/editing/commands/append_node_command.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/apply_block_element_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/apply_block_element_command.cc
index 492ac08996a..66199c9a1a2 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/apply_block_element_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/apply_block_element_command.cc
@@ -26,7 +26,6 @@
#include "third_party/blink/renderer/core/editing/commands/apply_block_element_command.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/editing/commands/editing_commands_utilities.h"
@@ -39,6 +38,7 @@
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/apply_block_element_command_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/apply_block_element_command_test.cc
index 67482c7d9aa..0c31debf868 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/apply_block_element_command_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/apply_block_element_command_test.cc
@@ -2,7 +2,6 @@
// 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/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/qualified_name.h"
#include "third_party/blink/renderer/core/editing/commands/format_block_command.h"
@@ -14,6 +13,7 @@
#include "third_party/blink/renderer/core/editing/visible_selection.h"
#include "third_party/blink/renderer/core/html/html_head_element.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include <memory>
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 de16957d26d..8929fb2727c 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
@@ -26,7 +26,6 @@
#include "third_party/blink/renderer/core/editing/commands/composite_edit_command.h"
#include <algorithm>
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_fragment.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
@@ -81,6 +80,7 @@
#include "third_party/blink/renderer/core/layout/layout_list_item.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
#include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -304,6 +304,7 @@ void CompositeEditCommand::InsertNodeBefore(
void CompositeEditCommand::InsertNodeAfter(Node* insert_child,
Node* ref_child,
EditingState* editing_state) {
+ ABORT_EDITING_COMMAND_IF(!ref_child->parentNode());
DCHECK(insert_child);
DCHECK(ref_child);
DCHECK_NE(GetDocument().body(), ref_child);
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command_test.cc
index 5cf9da21411..00ce0d5b6ef 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command_test.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/core/css/css_property_value_set.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/testing/editing_test_base.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -23,6 +24,7 @@ class SampleCommand final : public CompositeEditCommand {
EditingState*,
ShouldAssumeContentIsAlwaysEditable =
kDoNotAssumeContentIsAlwaysEditable);
+ void InsertNodeAfter(Node*, Node*, EditingState*);
void MoveParagraphContentsToNewBlockIfNecessary(const Position&,
EditingState*);
@@ -48,6 +50,12 @@ void SampleCommand::InsertNodeBefore(
should_assume_content_is_always_editable);
}
+void SampleCommand::InsertNodeAfter(Node* insert_child,
+ Node* ref_child,
+ EditingState* editing_state) {
+ CompositeEditCommand::InsertNodeAfter(insert_child, ref_child, editing_state);
+}
+
void SampleCommand::MoveParagraphContentsToNewBlockIfNecessary(
const Position& position,
EditingState* editing_state) {
@@ -140,10 +148,15 @@ TEST_F(CompositeEditCommandTest, InsertNodeOnDisconnectedParent) {
Node* insert_child = GetDocument().QuerySelector("b");
Element* ref_child = GetDocument().QuerySelector("p");
ref_child->remove();
- EditingState editing_state;
+ EditingState editing_state_before;
// editing state should abort here.
- sample.InsertNodeBefore(insert_child, ref_child, &editing_state);
- EXPECT_TRUE(editing_state.IsAborted());
+ sample.InsertNodeBefore(insert_child, ref_child, &editing_state_before);
+ EXPECT_TRUE(editing_state_before.IsAborted());
+
+ EditingState editing_state_after;
+ // editing state should abort here.
+ sample.InsertNodeAfter(insert_child, ref_child, &editing_state_after);
+ EXPECT_TRUE(editing_state_after.IsAborted());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/delete_from_text_node_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/delete_from_text_node_command.cc
index 337d0910b8d..94d0b00d5f2 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/delete_from_text_node_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/delete_from_text_node_command.cc
@@ -25,9 +25,9 @@
#include "third_party/blink/renderer/core/editing/commands/delete_from_text_node_command.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command_test.cc
index 40ecab83091..77cb714ac9e 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_command_test.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/core/editing/commands/delete_selection_command.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/position.h"
@@ -15,6 +14,7 @@
#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/testing/dummy_page_holder.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include <memory>
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/document_exec_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/document_exec_command.cc
index e9df9c09a89..9cbe75b81b8 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/document_exec_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/document_exec_command.cc
@@ -63,7 +63,8 @@ bool Document::execCommand(const String& command_name,
ExceptionState& exception_state) {
if (!IsHTMLDocument() && !IsXHTMLDocument()) {
exception_state.ThrowDOMException(
- kInvalidStateError, "execCommand is only supported on HTML documents.");
+ DOMExceptionCode::kInvalidStateError,
+ "execCommand is only supported on HTML documents.");
return false;
}
if (FocusedElement() && IsTextControl(*FocusedElement()))
@@ -100,7 +101,7 @@ bool Document::queryCommandEnabled(const String& command_name,
ExceptionState& exception_state) {
if (!IsHTMLDocument() && !IsXHTMLDocument()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"queryCommandEnabled is only supported on HTML documents.");
return false;
}
@@ -112,7 +113,7 @@ bool Document::queryCommandIndeterm(const String& command_name,
ExceptionState& exception_state) {
if (!IsHTMLDocument() && !IsXHTMLDocument()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"queryCommandIndeterm is only supported on HTML documents.");
return false;
}
@@ -124,7 +125,7 @@ bool Document::queryCommandState(const String& command_name,
ExceptionState& exception_state) {
if (!IsHTMLDocument() && !IsXHTMLDocument()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"queryCommandState is only supported on HTML documents.");
return false;
}
@@ -136,7 +137,7 @@ bool Document::queryCommandSupported(const String& command_name,
ExceptionState& exception_state) {
if (!IsHTMLDocument() && !IsXHTMLDocument()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"queryCommandSupported is only supported on HTML documents.");
return false;
}
@@ -148,7 +149,7 @@ String Document::queryCommandValue(const String& command_name,
ExceptionState& exception_state) {
if (!IsHTMLDocument() && !IsXHTMLDocument()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"queryCommandValue is only supported on HTML documents.");
return "";
}
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc b/chromium/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc
index 942ba3c0ac3..fe65f08ccef 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/editing/commands/editing_commands_utilities.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
+#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/editing/commands/selection_for_undo_step.h"
#include "third_party/blink/renderer/core/editing/commands/typing_command.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/editor_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/editor_command.cc
index 9125c0ce988..51df2dab237 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/editor_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/editor_command.cc
@@ -29,7 +29,6 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_editing_command_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css_property_names.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
@@ -53,6 +52,7 @@
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/iterators/text_iterator.h"
+#include "third_party/blink/renderer/core/editing/kill_ring.h"
#include "third_party/blink/renderer/core/editing/selection_modifier.h"
#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/core/editing/set_selection_options.h"
@@ -64,8 +64,8 @@
#include "third_party/blink/renderer/core/input/event_handler.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/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/histogram.h"
-#include "third_party/blink/renderer/platform/kill_ring.h"
#include "third_party/blink/renderer/platform/scroll/scrollbar.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/format_block_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/format_block_command.cc
index 2642dd7f342..1e7a98ff4ab 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/format_block_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/format_block_command.cc
@@ -25,7 +25,6 @@
#include "third_party/blink/renderer/core/editing/commands/format_block_command.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/range.h"
#include "third_party/blink/renderer/core/editing/commands/editing_commands_utilities.h"
@@ -37,6 +36,7 @@
#include "third_party/blink/renderer/core/html/html_br_element.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.cc
index dfbc4660489..8f737b0b9f7 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.cc
@@ -25,12 +25,12 @@
#include "third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/editing_utilities.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command.cc
index 303cc9240c8..02132854330 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command.cc
@@ -25,7 +25,6 @@
#include "third_party/blink/renderer/core/editing/commands/insert_list_command.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/element_traversal.h"
@@ -42,6 +41,7 @@
#include "third_party/blink/renderer/core/html/html_li_element.h"
#include "third_party/blink/renderer/core/html/html_ulist_element.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/insert_node_before_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/insert_node_before_command.cc
index afff31a8389..cff87303f4b 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/insert_node_before_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/insert_node_before_command.cc
@@ -25,8 +25,8 @@
#include "third_party/blink/renderer/core/editing/commands/insert_node_before_command.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/merge_identical_elements_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/merge_identical_elements_command.cc
index af13bce1054..aae9886d9a0 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/merge_identical_elements_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/merge_identical_elements_command.cc
@@ -25,9 +25,9 @@
#include "third_party/blink/renderer/core/editing/commands/merge_identical_elements_command.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/move_commands.cc b/chromium/third_party/blink/renderer/core/editing/commands/move_commands.cc
index 282ebdfdbcd..01dbd04fe66 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/move_commands.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/move_commands.cc
@@ -37,6 +37,7 @@
#include "third_party/blink/renderer/core/editing/selection_modifier.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
namespace blink {
@@ -55,8 +56,7 @@ unsigned MoveCommands::VerticalScrollDistance(LocalFrame& frame) {
style->OverflowY() == EOverflow::kAuto ||
HasEditableStyle(*focused_element)))
return 0;
- const ScrollableArea& scrollable_area =
- *frame.View()->LayoutViewportScrollableArea();
+ const ScrollableArea& scrollable_area = *frame.View()->LayoutViewport();
const int height = std::min<int>(layout_box.ClientHeight().ToInt(),
scrollable_area.VisibleHeight());
return static_cast<unsigned>(
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/remove_css_property_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/remove_css_property_command.cc
index 672d976f89a..66bcc03c674 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/remove_css_property_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/remove_css_property_command.cc
@@ -25,10 +25,10 @@
#include "third_party/blink/renderer/core/editing/commands/remove_css_property_command.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css/css_style_declaration.h"
#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/remove_node_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/remove_node_command.cc
index e3428b9fd3d..804155bd44a 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/remove_node_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/remove_node_command.cc
@@ -25,10 +25,10 @@
#include "third_party/blink/renderer/core/editing/commands/remove_node_command.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/editing/commands/editing_state.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/replace_node_with_span_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/replace_node_with_span_command.cc
index 0d3f21eb136..99b746df851 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/replace_node_with_span_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/replace_node_with_span_command.cc
@@ -30,11 +30,11 @@
#include "third_party/blink/renderer/core/editing/commands/replace_node_with_span_command.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/html/html_span_element.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc
index 3be3469dcd6..2832a98013d 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc
@@ -27,7 +27,6 @@
#include "third_party/blink/renderer/core/editing/commands/replace_selection_command.h"
#include "base/macros.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css/css_style_declaration.h"
#include "third_party/blink/renderer/core/css_property_names.h"
@@ -65,6 +64,7 @@
#include "third_party/blink/renderer/core/input_type_names.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_text.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command_test.cc
index 3992c835b16..73bb44c8b50 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command_test.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/core/editing/commands/replace_selection_command.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_fragment.h"
#include "third_party/blink/renderer/core/dom/parser_content_policy.h"
@@ -20,6 +19,7 @@
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include <memory>
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/split_element_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/split_element_command.cc
index 3687b185a3f..4b239aa96b9 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/split_element_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/split_element_command.cc
@@ -25,10 +25,10 @@
#include "third_party/blink/renderer/core/editing/commands/split_element_command.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/html_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/split_text_node_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/split_text_node_command.cc
index 53c6ae850eb..a4c4c14bed2 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/split_text_node_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/split_text_node_command.cc
@@ -25,11 +25,11 @@
#include "third_party/blink/renderer/core/editing/commands/split_text_node_command.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/typing_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/typing_command.cc
index a1c0ba2e0ae..302caa960bd 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/typing_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/typing_command.cc
@@ -208,14 +208,19 @@ void TypingCommand::DeleteSelectionIfRange(const VisibleSelection& selection,
EditingState* editing_state) {
if (!selection.IsRange())
return;
- ApplyCommandToComposite(DeleteSelectionCommand::Create(
- selection, DeleteSelectionOptions::Builder()
- .SetSmartDelete(smart_delete_)
- .SetMergeBlocksAfterDelete(true)
- .SetExpandForSpecialElements(true)
- .SetSanitizeMarkup(true)
- .Build()),
- editing_state);
+ // Although the 'selection' to delete is indeed a Range, it may have been
+ // built from a Caret selection; in that case we don't want to expand so that
+ // the table structure is deleted as well.
+ bool expand_for_special = EndingSelection().IsRange();
+ ApplyCommandToComposite(
+ DeleteSelectionCommand::Create(
+ selection, DeleteSelectionOptions::Builder()
+ .SetSmartDelete(smart_delete_)
+ .SetMergeBlocksAfterDelete(true)
+ .SetExpandForSpecialElements(expand_for_special)
+ .SetSanitizeMarkup(true)
+ .Build()),
+ editing_state);
}
void TypingCommand::DeleteKeyPressed(Document& document,
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/typing_command_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/typing_command_test.cc
index fadcfa56225..a684a21d29b 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/typing_command_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/typing_command_test.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/core/editing/commands/typing_command.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/position.h"
@@ -15,6 +14,7 @@
#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/testing/dummy_page_holder.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include <memory>
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/wrap_contents_in_dummy_span_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/wrap_contents_in_dummy_span_command.cc
index 06f79557802..58db6e738dd 100644
--- a/chromium/third_party/blink/renderer/core/editing/commands/wrap_contents_in_dummy_span_command.cc
+++ b/chromium/third_party/blink/renderer/core/editing/commands/wrap_contents_in_dummy_span_command.cc
@@ -25,10 +25,10 @@
#include "third_party/blink/renderer/core/editing/commands/wrap_contents_in_dummy_span_command.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/editing/commands/apply_style_command.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/html/html_span_element.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
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 287857bba25..f79220c775f 100644
--- a/chromium/third_party/blink/renderer/core/editing/dom_selection.cc
+++ b/chromium/third_party/blink/renderer/core/editing/dom_selection.cc
@@ -29,10 +29,7 @@
#include "third_party/blink/renderer/core/editing/dom_selection.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/range.h"
#include "third_party/blink/renderer/core/dom/tree_scope.h"
@@ -49,6 +46,7 @@
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -283,7 +281,7 @@ void DOMSelection::collapseToEnd(ExceptionState& exception_state) {
// The method must throw InvalidStateError exception if the context object is
// empty.
if (rangeCount() == 0) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"there is no selection.");
return;
}
@@ -316,7 +314,7 @@ void DOMSelection::collapseToStart(ExceptionState& exception_state) {
// The method must throw InvalidStateError ([DOM4]) exception if the context
// object is empty.
if (rangeCount() == 0) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"there is no selection.");
return;
}
@@ -478,7 +476,8 @@ void DOMSelection::extend(Node* node,
// abort these steps.
if (rangeCount() == 0) {
exception_state.ThrowDOMException(
- kInvalidStateError, "This Selection object doesn't have any Ranges.");
+ DOMExceptionCode::kInvalidStateError,
+ "This Selection object doesn't have any Ranges.");
return;
}
@@ -537,7 +536,8 @@ Range* DOMSelection::getRangeAt(unsigned index,
if (index >= rangeCount()) {
exception_state.ThrowDOMException(
- kIndexSizeError, String::Number(index) + " is not a valid index.");
+ DOMExceptionCode::kIndexSizeError,
+ String::Number(index) + " is not a valid index.");
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/editing/dom_selection.h b/chromium/third_party/blink/renderer/core/editing/dom_selection.h
index ad38325f2b0..2b68830d95e 100644
--- a/chromium/third_party/blink/renderer/core/editing/dom_selection.h
+++ b/chromium/third_party/blink/renderer/core/editing/dom_selection.h
@@ -30,9 +30,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_DOM_SELECTION_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_DOM_SELECTION_H_
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/editing/forward.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/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/editing_strategy.h b/chromium/third_party/blink/renderer/core/editing/editing_strategy.h
index 6d016d9858b..d44796248ec 100644
--- a/chromium/third_party/blink/renderer/core/editing/editing_strategy.h
+++ b/chromium/third_party/blink/renderer/core/editing/editing_strategy.h
@@ -14,7 +14,7 @@ namespace blink {
// Editing algorithm defined on node traversal.
template <typename Traversal>
-class CORE_TEMPLATE_CLASS_EXPORT EditingAlgorithm : public Traversal {
+class EditingAlgorithm : public Traversal {
STATIC_ONLY(EditingAlgorithm);
public:
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 0140e00123d..7599ba00059 100644
--- a/chromium/third_party/blink/renderer/core/editing/editing_style.cc
+++ b/chromium/third_party/blink/renderer/core/editing/editing_style.cc
@@ -26,7 +26,6 @@
#include "third_party/blink/renderer/core/editing/editing_style.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_color_value.h"
#include "third_party/blink/renderer/core/css/css_computed_style_declaration.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
@@ -64,6 +63,7 @@
#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/style/computed_style.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/editing_style_utilities.cc b/chromium/third_party/blink/renderer/core/editing/editing_style_utilities.cc
index d5608a3e2ae..14692dc4624 100644
--- a/chromium/third_party/blink/renderer/core/editing/editing_style_utilities.cc
+++ b/chromium/third_party/blink/renderer/core/editing/editing_style_utilities.cc
@@ -32,6 +32,7 @@
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
#include "third_party/blink/renderer/core/css_property_names.h"
+#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/editing/editing_style.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/editing_utilities.cc b/chromium/third_party/blink/renderer/core/editing/editing_utilities.cc
index 99794ab7119..85114d29c1b 100644
--- a/chromium/third_party/blink/renderer/core/editing/editing_utilities.cc
+++ b/chromium/third_party/blink/renderer/core/editing/editing_utilities.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
+#include "third_party/blink/renderer/core/clipboard/clipboard_mime_types.h"
#include "third_party/blink/renderer/core/clipboard/data_object.h"
#include "third_party/blink/renderer/core/clipboard/system_clipboard.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -71,7 +72,6 @@
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
#include "third_party/blink/renderer/core/svg/svg_image_element.h"
-#include "third_party/blink/renderer/platform/clipboard/clipboard_mime_types.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/editing_utilities_test.cc b/chromium/third_party/blink/renderer/core/editing/editing_utilities_test.cc
index 017ce30913d..64c533dc13e 100644
--- a/chromium/third_party/blink/renderer/core/editing/editing_utilities_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/editing_utilities_test.cc
@@ -435,7 +435,7 @@ TEST_F(EditingUtilitiesTest, uncheckedPreviousNextOffset) {
// Break other Hangul syllable combination. See test of GB999.
- // GB8a: Don't break between regional indicator if there are even numbered
+ // GB12: Don't break between regional indicator if there are even numbered
// regional indicator symbols before.
// U+1F1FA is REGIONAL INDICATOR SYMBOL LETTER U.
// U+1F1F8 is REGIONAL INDICATOR SYMBOL LETTER S.
@@ -571,8 +571,12 @@ TEST_F(EditingUtilitiesTest, uncheckedPreviousNextOffset) {
EXPECT_EQ(5, NextGraphemeBoundaryOf(*node, 4));
// GB10: Do not break within emoji modifier.
- // U+1F385(FATHER CHRISTMAS) has E_Base property.
- // U+1F3FB(EMOJI MODIFIER FITZPATRICK TYPE-1-2) has E_Modifier property.
+ // GB10 is deleted in Unicode 11, but it's subsumed by GB9 by
+ // extending the definition of Extend to include E_Base, E_Modifier,
+ // etc. E_Base, E_Modifier and E_Base_GAZ are obsolete.
+ // U+1F385(FATHER CHRISTMAS) used to have E_Base property.
+ // U+1F3FB(EMOJI MODIFIER FITZPATRICK TYPE-1-2) used to have
+ // E_Modifier property.
SetBodyContent(
"<p id='target'>a&#x1F385;&#x1F3FB;b</p>"); // E_Base x E_Modifier
node = GetDocument().getElementById("target")->firstChild();
@@ -582,7 +586,7 @@ TEST_F(EditingUtilitiesTest, uncheckedPreviousNextOffset) {
EXPECT_EQ(1, NextGraphemeBoundaryOf(*node, 0));
EXPECT_EQ(5, NextGraphemeBoundaryOf(*node, 1));
EXPECT_EQ(6, NextGraphemeBoundaryOf(*node, 5));
- // U+1F466(BOY) has EBG property.
+ // U+1F466(BOY) used to have EBG property, but now has Extend property.
SetBodyContent(
"<p id='target'>a&#x1F466;&#x1F3FB;b</p>"); // EBG x E_Modifier
node = GetDocument().getElementById("target")->firstChild();
@@ -594,7 +598,8 @@ TEST_F(EditingUtilitiesTest, uncheckedPreviousNextOffset) {
EXPECT_EQ(6, NextGraphemeBoundaryOf(*node, 5));
// GB11: Do not break within ZWJ emoji sequence.
- // U+2764(HEAVY BLACK HEART) has Glue_After_Zwj property.
+ // U+2764(HEAVY BLACK HEART) has Extended_Pictographic=True.
+ // So does U+1F466.
SetBodyContent(
"<p id='target'>a&#x200D;&#x2764;b</p>"); // ZWJ x Glue_After_Zwj
node = GetDocument().getElementById("target")->firstChild();
@@ -609,10 +614,7 @@ TEST_F(EditingUtilitiesTest, uncheckedPreviousNextOffset) {
EXPECT_EQ(4, NextGraphemeBoundaryOf(*node, 0));
EXPECT_EQ(5, NextGraphemeBoundaryOf(*node, 4));
- // Not only Glue_After_ZWJ or EBG but also other emoji shouldn't break
- // before ZWJ.
- // U+1F5FA(WORLD MAP) doesn't have either Glue_After_Zwj or EBG but has
- // Emoji property.
+ // U+1F5FA(World Map) has Extended_Pictographic=True.
SetBodyContent("<p id='target'>&#x200D;&#x1F5FA;</p>");
node = GetDocument().getElementById("target")->firstChild();
EXPECT_EQ(0, PreviousGraphemeBoundaryOf(*node, 3));
@@ -681,17 +683,16 @@ TEST_F(EditingUtilitiesTest, uncheckedPreviousNextOffset) {
EXPECT_EQ(1, PreviousGraphemeBoundaryOf(*node, 2));
EXPECT_EQ(1, NextGraphemeBoundaryOf(*node, 0));
- // For GB10, if base emoji character is not E_Base or EBG, break happens
- // before E_Modifier.
+ // Per GB8, do not break before Extended|ZWJ. E_Modifier is obsolete
+ // in Unicode 11 and is now a part of Extended.
SetBodyContent("<p id='target'>a&#x1F3FB;</p>");
node = GetDocument().getElementById("target")->firstChild();
- EXPECT_EQ(1, PreviousGraphemeBoundaryOf(*node, 3));
- EXPECT_EQ(1, NextGraphemeBoundaryOf(*node, 0));
- // U+1F5FA(WORLD MAP) doesn't have either E_Base or EBG property.
+ EXPECT_EQ(0, PreviousGraphemeBoundaryOf(*node, 3));
+ EXPECT_EQ(3, NextGraphemeBoundaryOf(*node, 0));
SetBodyContent("<p id='target'>&#x1F5FA;&#x1F3FB;</p>");
node = GetDocument().getElementById("target")->firstChild();
- EXPECT_EQ(2, PreviousGraphemeBoundaryOf(*node, 4));
- EXPECT_EQ(2, NextGraphemeBoundaryOf(*node, 0));
+ EXPECT_EQ(0, PreviousGraphemeBoundaryOf(*node, 4));
+ EXPECT_EQ(4, NextGraphemeBoundaryOf(*node, 0));
// For GB11, if trailing character is not Glue_After_Zwj or EBG, break happens
// after ZWJ.
diff --git a/chromium/third_party/blink/renderer/core/editing/editor.cc b/chromium/third_party/blink/renderer/core/editing/editor.cc
index 92d1e084867..381ef1b2cab 100644
--- a/chromium/third_party/blink/renderer/core/editing/editor.cc
+++ b/chromium/third_party/blink/renderer/core/editing/editor.cc
@@ -27,7 +27,7 @@
#include "third_party/blink/renderer/core/editing/editor.h"
#include "third_party/blink/public/platform/web_scroll_into_view_params.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/clipboard/data_object.h"
#include "third_party/blink/renderer/core/clipboard/data_transfer.h"
#include "third_party/blink/renderer/core/clipboard/data_transfer_access_policy.h"
@@ -35,7 +35,6 @@
#include "third_party/blink/renderer/core/css/css_computed_style_declaration.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css_property_names.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/document_fragment.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
@@ -57,6 +56,7 @@
#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/iterators/search_buffer.h"
+#include "third_party/blink/renderer/core/editing/kill_ring.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
#include "third_party/blink/renderer/core/editing/selection_template.h"
@@ -86,7 +86,7 @@
#include "third_party/blink/renderer/core/page/drag_data.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/kill_ring.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/scroll/scroll_alignment.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/editor_test.cc b/chromium/third_party/blink/renderer/core/editing/editor_test.cc
index b9b015c3b23..42dc372e107 100644
--- a/chromium/third_party/blink/renderer/core/editing/editor_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/editor_test.cc
@@ -8,10 +8,22 @@
#include "third_party/blink/renderer/core/editing/commands/editor_command.h"
#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
namespace blink {
class EditorTest : public EditingTestBase {
+ public:
+ void TearDown() override {
+ SystemClipboard::GetInstance().WritePlainText(String(""));
+ EditingTestBase::TearDown();
+ }
+
+ void ExecuteCopy() {
+ Editor& editor = GetDocument().GetFrame()->GetEditor();
+ editor.CreateCommand("Copy").Execute();
+ test::RunPendingTasks();
+ }
};
TEST_F(EditorTest, copyGeneratedPassword) {
@@ -36,10 +48,24 @@ TEST_F(EditorTest, copyGeneratedPassword) {
EXPECT_TRUE(editor.CanCopy());
}
+TEST_F(EditorTest, CopyVisibleSelection) {
+ const char* body_content = "<input id=hiding value=HEY>";
+ SetBodyContent(body_content);
+
+ HTMLInputElement& text_control =
+ ToHTMLInputElement(*GetDocument().getElementById("hiding"));
+ text_control.select();
+
+ ExecuteCopy();
+
+ const String copied = SystemClipboard::GetInstance().ReadPlainText();
+ EXPECT_EQ("HEY", copied);
+}
+
TEST_F(EditorTest, DontCopyHiddenSelections) {
const char* body_content =
"<input type=checkbox id=checkbox>"
- "<input id=hiding value=HEY></input>";
+ "<input id=hiding value=HEY>";
SetBodyContent(body_content);
HTMLInputElement& text_control =
@@ -50,8 +76,7 @@ TEST_F(EditorTest, DontCopyHiddenSelections) {
ToHTMLInputElement(*GetDocument().getElementById("checkbox"));
checkbox.focus();
- Editor& editor = GetDocument().GetFrame()->GetEditor();
- editor.CreateCommand("Copy").Execute();
+ ExecuteCopy();
const String copied = SystemClipboard::GetInstance().ReadPlainText();
EXPECT_TRUE(copied.IsEmpty()) << copied << " was copied.";
diff --git a/chromium/third_party/blink/renderer/core/editing/ephemeral_range.h b/chromium/third_party/blink/renderer/core/editing/ephemeral_range.h
index c9bc293a7be..d51b650e4e1 100644
--- a/chromium/third_party/blink/renderer/core/editing/ephemeral_range.h
+++ b/chromium/third_party/blink/renderer/core/editing/ephemeral_range.h
@@ -77,7 +77,7 @@ class CheckedTraversalNextIterator
// if |Range| objects doesn't live after DOM mutation.
//
template <typename Strategy>
-class CORE_TEMPLATE_CLASS_EXPORT EphemeralRangeTemplate final {
+class EphemeralRangeTemplate final {
STACK_ALLOCATED();
public:
diff --git a/chromium/third_party/blink/renderer/core/editing/finder/find_in_page_coordinates.cc b/chromium/third_party/blink/renderer/core/editing/finder/find_in_page_coordinates.cc
index a3f06fe3c16..76ecb45df78 100644
--- a/chromium/third_party/blink/renderer/core/editing/finder/find_in_page_coordinates.cc
+++ b/chromium/third_party/blink/renderer/core/editing/finder/find_in_page_coordinates.cc
@@ -75,13 +75,13 @@ static FloatRect ToNormalizedRect(const FloatRect& absolute_rect,
// For overflow:scroll we need to get where the actual origin is independently
// of the scroll.
if (container->HasOverflowClip())
- scrolled_origin = -IntPoint(container->ScrolledContentOffset());
+ scrolled_origin = -FloatPoint(container->ScrolledContentOffset());
FloatRect overflow_rect(scrolled_origin,
FloatSize(container->MaxLayoutOverflow()));
FloatRect container_rect =
- container->LocalToAbsoluteQuad(FloatQuad(overflow_rect))
- .EnclosingBoundingBox();
+ FloatRect(container->LocalToAbsoluteQuad(FloatQuad(overflow_rect))
+ .EnclosingBoundingBox());
if (container_rect.IsEmpty())
return FloatRect();
@@ -92,15 +92,6 @@ static FloatRect ToNormalizedRect(const FloatRect& absolute_rect,
FloatRect normalized_rect = absolute_rect;
normalized_rect.MoveBy(-container_rect.Location());
- // Fixed positions do not make sense in this coordinate system, but need to
- // leave consistent tickmarks. So, use their position when the view is not
- // scrolled, like an absolute position.
- if (layout_object->Style()->GetPosition() == EPosition::kFixed &&
- container->IsLayoutView()) {
- normalized_rect.Move(
- -ToLayoutView(container)->GetFrameView()->GetScrollOffset());
- }
-
normalized_rect.Scale(1 / container_rect.Width(),
1 / container_rect.Height());
return normalized_rect;
@@ -126,8 +117,9 @@ FloatRect FindInPageRectFromAbsoluteRect(
const LayoutBlock* container = EnclosingScrollableAncestor(layout_object);
// Compose the normalized rects.
- FloatRect normalized_box_rect = ToNormalizedRect(
- layout_object->AbsoluteBoundingBoxRect(), layout_object, container);
+ FloatRect normalized_box_rect =
+ ToNormalizedRect(FloatRect(layout_object->AbsoluteBoundingBoxRect()),
+ layout_object, container);
normalized_rect.Scale(normalized_box_rect.Width(),
normalized_box_rect.Height());
normalized_rect.MoveBy(normalized_box_rect.Location());
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 5a1754d7185..3e1ccba1566 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
@@ -35,9 +35,9 @@
#include "third_party/blink/public/platform/web_scroll_into_view_params.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/public/web/web_find_options.h"
-#include "third_party/blink/public/web/web_frame_client.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_view_client.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache_base.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache_base.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/editor.h"
@@ -55,6 +55,7 @@
#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/layout/layout_object.h"
+#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/text_autosizer.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/timer.h"
@@ -121,9 +122,11 @@ static void ScrollToVisible(Range* match) {
smooth_find_enabled ? kScrollBehaviorSmooth : kScrollBehaviorAuto;
first_node.GetLayoutObject()->ScrollRectToVisible(
LayoutRect(match->BoundingBox()),
- WebScrollIntoViewParams(ScrollAlignment::kAlignCenterIfNeeded,
- ScrollAlignment::kAlignCenterIfNeeded,
- kUserScroll, false, scroll_behavior, true));
+ WebScrollIntoViewParams(
+ ScrollAlignment::kAlignCenterIfNeeded,
+ ScrollAlignment::kAlignCenterIfNeeded, kUserScroll,
+ true /* make_visible_in_visual_viewport */, scroll_behavior,
+ true /* is_for_scroll_sequence */));
first_node.GetDocument().SetSequentialFocusNavigationStartingPoint(
const_cast<Node*>(&first_node));
}
@@ -175,7 +178,7 @@ bool TextFinder::Find(int identifier,
if (!options.find_next)
ClearFindMatchesCache();
- OwnerFrame().GetFrameView()->InvalidatePaintForTickmarks();
+ InvalidatePaintForTickmarks();
return false;
}
ScrollToVisible(active_match_);
@@ -189,7 +192,7 @@ bool TextFinder::Find(int identifier,
->GetTextAutosizer()
->PageNeedsAutosizing()) {
OwnerFrame().ViewImpl()->ZoomToFindInPageRect(
- OwnerFrame().GetFrameView()->AbsoluteToRootFrame(
+ OwnerFrame().GetFrameView()->ConvertToRootFrame(
EnclosingIntRect(LayoutObject::AbsoluteBoundingBoxRectForRange(
EphemeralRange(active_match_.Get())))));
}
@@ -231,7 +234,7 @@ bool TextFinder::Find(int identifier,
else if (active_match_index_ < 0)
active_match_index_ = last_match_count_ - 1;
}
- WebRect selection_rect = OwnerFrame().GetFrameView()->AbsoluteToRootFrame(
+ WebRect selection_rect = OwnerFrame().GetFrameView()->ConvertToRootFrame(
active_match_->BoundingBox());
ReportFindInPageSelection(selection_rect, active_match_index_ + 1,
identifier);
@@ -347,7 +350,7 @@ void TextFinder::StopFindingAndClearSelection() {
ResetActiveMatch();
// Let the frame know that we don't want tickmarks anymore.
- OwnerFrame().GetFrameView()->InvalidatePaintForTickmarks();
+ InvalidatePaintForTickmarks();
}
void TextFinder::ReportFindInPageResultToAccessibility(int identifier) {
@@ -440,7 +443,7 @@ void TextFinder::ScopeStringMatches(int identifier,
const double kMaxScopingDuration = 0.1; // seconds
int match_count = 0;
- bool timed_out = false;
+ bool full_range_searched = false;
double start_time = CurrentTime();
PositionInFlatTree next_scoping_start;
do {
@@ -454,6 +457,7 @@ void TextFinder::ScopeStringMatches(int identifier,
search_text, options.match_case ? 0 : kCaseInsensitive);
if (result.IsCollapsed()) {
// Not found.
+ full_range_searched = true;
break;
}
Range* result_range = Range::Create(
@@ -494,7 +498,7 @@ void TextFinder::ScopeStringMatches(int identifier,
// Notify browser of new location for the selected rectangle.
ReportFindInPageSelection(
- OwnerFrame().GetFrameView()->AbsoluteToRootFrame(result_bounds),
+ OwnerFrame().GetFrameView()->ConvertToRootFrame(result_bounds),
active_match_index_ + 1, identifier);
}
@@ -513,8 +517,7 @@ void TextFinder::ScopeStringMatches(int identifier,
search_start = result.EndPosition();
next_scoping_start = search_start;
- timed_out = (CurrentTime() - start_time) >= kMaxScopingDuration;
- } while (!timed_out);
+ } while (CurrentTime() - start_time < kMaxScopingDuration);
if (next_scoping_start.IsNotNull()) {
resume_scoping_from_range_ =
@@ -537,7 +540,7 @@ void TextFinder::ScopeStringMatches(int identifier,
IncreaseMatchCount(identifier, match_count);
}
- if (timed_out) {
+ if (!full_range_searched) {
// If we found anything during this pass, we should redraw. However, we
// don't want to spam too much if the page is extremely long, so if we
// reach a certain point we start throttling the redraw requests.
@@ -570,7 +573,7 @@ void TextFinder::FinishCurrentScopingEffort(int identifier) {
last_find_request_completed_with_no_matches_ = !last_match_count_;
// This frame is done, so show any scrollbar tickmarks we haven't drawn yet.
- OwnerFrame().GetFrameView()->InvalidatePaintForTickmarks();
+ InvalidatePaintForTickmarks();
}
void TextFinder::CancelPendingScopingEffort() {
@@ -777,7 +780,7 @@ int TextFinder::SelectFindMatch(unsigned index, WebRect* selection_rect) {
}
// Zoom to the active match.
- active_match_rect = OwnerFrame().GetFrameView()->AbsoluteToRootFrame(
+ active_match_rect = OwnerFrame().GetFrameView()->ConvertToRootFrame(
active_match_bounding_box);
OwnerFrame().ViewImpl()->ZoomToFindInPageRect(active_match_rect);
}
@@ -894,13 +897,17 @@ void TextFinder::InvalidateIfNecessary() {
int i = last_match_count_ / kStartSlowingDownAfter;
next_invalidate_after_ += i * kSlowdown;
- OwnerFrame().GetFrameView()->InvalidatePaintForTickmarks();
+ InvalidatePaintForTickmarks();
}
void TextFinder::FlushCurrentScoping() {
FlushCurrentScopingEffort(find_request_identifier_);
}
+void TextFinder::InvalidatePaintForTickmarks() {
+ OwnerFrame().GetFrame()->ContentLayoutObject()->InvalidatePaintForTickmarks();
+}
+
void TextFinder::Trace(blink::Visitor* visitor) {
visitor->Trace(owner_frame_);
visitor->Trace(active_match_);
diff --git a/chromium/third_party/blink/renderer/core/editing/finder/text_finder.h b/chromium/third_party/blink/renderer/core/editing/finder/text_finder.h
index 27c1d947db9..1ae14d99cf9 100644
--- a/chromium/third_party/blink/renderer/core/editing/finder/text_finder.h
+++ b/chromium/third_party/blink/renderer/core/editing/finder/text_finder.h
@@ -202,6 +202,10 @@ class CORE_EXPORT TextFinder final
// Determines whether to invalidate the content area and scrollbar.
void InvalidateIfNecessary();
+ // Issues a paint invalidation on the layout viewport's vertical scrollbar,
+ // which is responsible for painting the tickmarks.
+ void InvalidatePaintForTickmarks();
+
LocalFrame* GetFrame() const;
WebLocalFrameImpl& OwnerFrame() const {
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 aa30dffcd82..289b62c4ba0 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,7 +9,6 @@
#include "third_party/blink/public/platform/web_float_rect.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_find_options.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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"
@@ -23,6 +22,7 @@
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/layout/text_autosizer.h"
#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
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 d80a08d6a5b..d88aac9ceac 100644
--- a/chromium/third_party/blink/renderer/core/editing/frame_selection.cc
+++ b/chromium/third_party/blink/renderer/core/editing/frame_selection.cc
@@ -27,9 +27,8 @@
#include <stdio.h>
#include "third_party/blink/public/platform/web_scroll_into_view_params.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/character_data.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
@@ -80,6 +79,7 @@
#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/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/unicode_utilities.h"
@@ -291,8 +291,11 @@ void FrameSelection::DidSetSelectionDeprecated(
NotifyAccessibilityForSelectionChange();
NotifyCompositorForSelectionChange();
NotifyEventHandlerForSelectionChange();
+ // The task source should be kDOMManipulation, but the spec doesn't say
+ // anything about this.
frame_->DomWindow()->EnqueueDocumentEvent(
- Event::Create(EventTypeNames::selectionchange));
+ Event::Create(EventTypeNames::selectionchange),
+ TaskType::kMiscPlatformAPI);
}
void FrameSelection::NodeChildrenWillBeRemoved(ContainerNode& container) {
@@ -569,8 +572,9 @@ bool FrameSelection::Contains(const LayoutPoint& point) {
return false;
HitTestRequest request(HitTestRequest::kReadOnly | HitTestRequest::kActive);
- HitTestResult result(request, point);
- GetDocument().GetLayoutView()->HitTest(result);
+ HitTestLocation location(point);
+ HitTestResult result(request, location);
+ GetDocument().GetLayoutView()->HitTest(location, result);
Node* inner_node = result.InnerNode();
if (!inner_node || !inner_node->GetLayoutObject())
return false;
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 301e07ed169..7b1ecd427d9 100644
--- a/chromium/third_party/blink/renderer/core/editing/frame_selection.h
+++ b/chromium/third_party/blink/renderer/core/editing/frame_selection.h
@@ -64,8 +64,7 @@ enum RevealExtentOption { kRevealExtent, kDoNotRevealExtent };
enum class CaretVisibility;
enum class HandleVisibility { kNotVisible, kVisible };
-
-enum class SelectLineBreak { kNotSelected, kSelected };
+enum class SelectSoftLineBreak { kNotSelected, kSelected };
// This is return type of ComputeLayoutSelectionStatus(paintfragment).
// This structure represents how the fragment is selected.
@@ -74,13 +73,13 @@ enum class SelectLineBreak { kNotSelected, kSelected };
// |fragemnt.StartOffset <= start <= end <= fragment.EndOffset|.
// |start| == |end| means this fragment is not selected.
// |line_break| : This value represents If this fragment is selected and
-// selection wraps line break.
+// selection wraps soft line break.
struct LayoutSelectionStatus {
STACK_ALLOCATED();
LayoutSelectionStatus(unsigned passed_start,
unsigned passed_end,
- SelectLineBreak passed_line_break)
+ SelectSoftLineBreak passed_line_break)
: start(passed_start), end(passed_end), line_break(passed_line_break) {
DCHECK_LE(start, end);
}
@@ -91,7 +90,7 @@ struct LayoutSelectionStatus {
unsigned start;
unsigned end;
- SelectLineBreak line_break;
+ SelectSoftLineBreak line_break;
};
class CORE_EXPORT FrameSelection final
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 3024c0f57d7..928567b6975 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
@@ -7,7 +7,6 @@
#include <memory>
#include "base/memory/scoped_refptr.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/text.h"
@@ -24,7 +23,9 @@
#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/paint/paint_info.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/dummy_page_holder.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.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/testing/fake_display_item_client.h"
@@ -144,12 +145,8 @@ TEST_F(FrameSelectionTest, PaintCaretShouldNotLayout) {
std::unique_ptr<PaintController> paint_controller = PaintController::Create();
{
GraphicsContext context(*paint_controller);
-
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- paint_controller->UpdateCurrentPaintChunkProperties(
- root_paint_chunk_id_, PropertyTreeState::Root());
- }
-
+ paint_controller->UpdateCurrentPaintChunkProperties(
+ root_paint_chunk_id_, PropertyTreeState::Root());
Selection().PaintCaret(context, LayoutPoint());
}
paint_controller->CommitNewDisplayItems();
@@ -1065,19 +1062,17 @@ TEST_F(FrameSelectionTest, SelectionBounds) {
// bottom is visible. The unclipped selection bounds should not be clipped.
const int scroll_offset = 500;
LocalFrameView* frame_view = GetDocument().View();
- frame_view->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, scroll_offset), kProgrammaticScroll);
- EXPECT_EQ(
- LayoutRect(0, node_margin_top, node_width, node_height),
- frame_view->AbsoluteToDocument(Selection().AbsoluteUnclippedBounds()));
+ frame_view->LayoutViewport()->SetScrollOffset(ScrollOffset(0, scroll_offset),
+ kProgrammaticScroll);
+ EXPECT_EQ(LayoutRect(0, node_margin_top, node_width, node_height),
+ frame_view->FrameToDocument(Selection().AbsoluteUnclippedBounds()));
// Adjust the page scale factor which changes the selection bounds as seen
// through the viewport. The unclipped selection bounds should not be clipped.
const int page_scale_factor = 2;
GetPage().SetPageScaleFactor(page_scale_factor);
- EXPECT_EQ(
- LayoutRect(0, node_margin_top, node_width, node_height),
- frame_view->AbsoluteToDocument(Selection().AbsoluteUnclippedBounds()));
+ EXPECT_EQ(LayoutRect(0, node_margin_top, node_width, node_height),
+ frame_view->FrameToDocument(Selection().AbsoluteUnclippedBounds()));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/granularity_strategy_test.cc b/chromium/third_party/blink/renderer/core/editing/granularity_strategy_test.cc
index d895767e2c3..c1f8fd068d1 100644
--- a/chromium/third_party/blink/renderer/core/editing/granularity_strategy_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/granularity_strategy_test.cc
@@ -5,7 +5,6 @@
#include <memory>
#include "base/memory/scoped_refptr.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/text.h"
@@ -19,6 +18,7 @@
#include "third_party/blink/renderer/core/html/html_body_element.h"
#include "third_party/blink/renderer/core/html/html_span_element.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
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 34f9ed99479..9f2ed35bdc2 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
@@ -31,6 +31,7 @@
#include "third_party/blink/public/platform/web_text_input_info.h"
#include "third_party/blink/public/platform/web_text_input_type.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/dom/document_shutdown_observer.h"
#include "third_party/blink/renderer/core/editing/forward.h"
#include "third_party/blink/renderer/core/editing/ime/ime_text_span.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/inline_box_position.cc b/chromium/third_party/blink/renderer/core/editing/inline_box_position.cc
index b837c24b6d8..18852bacfc0 100644
--- a/chromium/third_party/blink/renderer/core/editing/inline_box_position.cc
+++ b/chromium/third_party/blink/renderer/core/editing/inline_box_position.cc
@@ -227,18 +227,19 @@ PositionWithAffinityTemplate<Strategy> ComputeInlineAdjustedPositionAlgorithm(
if (layout_object.IsText())
return position;
- if (layout_object.IsAtomicInlineLevel()) {
- // TODO(crbug.com/567964): Change the following branch to DCHECK once fixed.
- if (!layout_object.IsInline())
- return PositionWithAffinityTemplate<Strategy>();
- return position;
+ // We perform block flow adjustment first, so that we can move into an inline
+ // block when needed instead of stopping at its boundary as if it is a
+ // replaced element.
+ if (layout_object.IsLayoutBlockFlow() &&
+ CanHaveChildrenForEditing(position.AnchorNode()) &&
+ HasRenderedNonAnonymousDescendantsWithHeight(&layout_object)) {
+ return AdjustBlockFlowPositionToInline(position.GetPosition());
}
- if (!layout_object.IsLayoutBlockFlow() ||
- !CanHaveChildrenForEditing(position.AnchorNode()) ||
- !HasRenderedNonAnonymousDescendantsWithHeight(&layout_object))
+ // TODO(crbug.com/567964): Change the second operand to DCHECK once fixed.
+ if (!layout_object.IsAtomicInlineLevel() || !layout_object.IsInline())
return PositionWithAffinityTemplate<Strategy>();
- return AdjustBlockFlowPositionToInline(position.GetPosition());
+ return position;
}
// Returns true if |layout_object| and |offset| points after line end.
diff --git a/chromium/third_party/blink/renderer/core/editing/inline_box_traversal.cc b/chromium/third_party/blink/renderer/core/editing/inline_box_traversal.cc
index 626100aedfd..ce39ab9164c 100644
--- a/chromium/third_party/blink/renderer/core/editing/inline_box_traversal.cc
+++ b/chromium/third_party/blink/renderer/core/editing/inline_box_traversal.cc
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/layout/line/inline_box.h"
#include "third_party/blink/renderer/core/layout/line/root_inline_box.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.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_physical_text_fragment.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h"
@@ -128,16 +129,18 @@ class AbstractInlineBox {
return result.IsNull() ? AbstractInlineBox() : AbstractInlineBox(result);
}
- // TODO(xiaochengh): Bidi adjustment should check base direction of containing
- // line instead of containing block, to handle unicode-bidi correctly.
TextDirection ParagraphDirection() const {
DCHECK(IsNotNull());
- if (IsOldLayout())
+ if (IsOldLayout()) {
+ // TODO(editing-dev): Bidi adjustment should check base direction of
+ // containing line instead of containing block, to handle unicode-bidi
+ // correctly.
return GetInlineBox().Root().Block().Style()->Direction();
- return NGPaintFragment::GetForInlineContainer(
- GetNGPaintFragment().GetLayoutObject())
- ->Style()
- .Direction();
+ }
+ const NGPhysicalLineBoxFragment& line_box =
+ ToNGPhysicalLineBoxFragmentOrDie(
+ GetNGPaintFragment().ContainerLineBox()->PhysicalFragment());
+ return line_box.BaseDirection();
}
private:
@@ -441,49 +444,6 @@ AbstractInlineBox FindBoundaryOfEntireBidiRunIgnoringLineBreak(
start, bidi_level, TraversalStrategy::ForwardIgnoringLineBreak);
}
-// Shorthands for InlineBoxTraversal
-
-template <typename TraversalStrategy>
-const InlineBox* FindBidiRun(const InlineBox& start, unsigned bidi_level) {
- const AbstractInlineBox& result =
- FindBidiRun<TraversalStrategy>(AbstractInlineBox(start), bidi_level);
- if (result.IsNull())
- return nullptr;
- DCHECK(result.IsOldLayout());
- return &result.GetInlineBox();
-}
-
-template <typename TraversalStrategy>
-const InlineBox& FindBoundaryOfBidiRunIgnoringLineBreak(const InlineBox& start,
- unsigned bidi_level) {
- const AbstractInlineBox& result =
- FindBoundaryOfBidiRunIgnoringLineBreak<TraversalStrategy>(
- AbstractInlineBox(start), bidi_level);
- DCHECK(result.IsOldLayout());
- return result.GetInlineBox();
-}
-
-template <typename TraversalStrategy>
-const InlineBox& FindBoundaryOfEntireBidiRun(const InlineBox& start,
- unsigned bidi_level) {
- const AbstractInlineBox& result =
- FindBoundaryOfEntireBidiRun<TraversalStrategy>(AbstractInlineBox(start),
- bidi_level);
- DCHECK(result.IsOldLayout());
- return result.GetInlineBox();
-}
-
-template <typename TraversalStrategy>
-const InlineBox& FindBoundaryOfEntireBidiRunIgnoringLineBreak(
- const InlineBox& start,
- unsigned bidi_level) {
- const AbstractInlineBox& result =
- FindBoundaryOfEntireBidiRunIgnoringLineBreak<TraversalStrategy>(
- AbstractInlineBox(start), bidi_level);
- DCHECK(result.IsOldLayout());
- return result.GetInlineBox();
-}
-
// Adjustment algorithm at the end of caret position resolution.
template <typename TraversalStrategy>
class CaretPositionResolutionAdjuster {
@@ -520,18 +480,33 @@ class CaretPositionResolutionAdjuster {
result_box);
}
+ static bool ShouldUseLegacyUnicodeBidiHack(const AbstractInlineBox& box,
+ UnicodeBidi unicode_bidi) {
+ if (!box.IsOldLayout())
+ return false;
+ if (unicode_bidi != UnicodeBidi::kPlaintext)
+ return false;
+ // Even in 'unicode-bidi: plaintext', we still need bidi adjustment at bidi
+ // boundaries.
+ // TODO(editing-dev): The code below may miss some cases of bidi boundaries.
+ const AbstractInlineBox backward_box =
+ TraversalStrategy::BackwardIgnoringLineBreak(box);
+ return backward_box.IsNull() || backward_box.BidiLevel() == box.BidiLevel();
+ }
+
static AbstractInlineBoxAndSideAffinity AdjustFor(
const AbstractInlineBox& box,
UnicodeBidi unicode_bidi) {
DCHECK(box.IsNotNull());
- // TODO(xiaochengh): We should check line direction instead, and get rid of
- // ad hoc handling of 'unicode-bidi'.
const TextDirection primary_direction = box.ParagraphDirection();
if (box.Direction() == primary_direction)
return AdjustForPrimaryDirectionAlgorithm(box);
- if (unicode_bidi == UnicodeBidi::kPlaintext)
+ // In legacy layout we don't have a reliable way to get the line direction,
+ // which is different from block direction with 'unicode-bidi: plaintext'.
+ // We do hacky things in this case.
+ if (ShouldUseLegacyUnicodeBidiHack(box, unicode_bidi))
return UnadjustedCaretPosition(box);
const unsigned char level = box.BidiLevel();
@@ -845,55 +820,40 @@ RangeSelectionAdjuster::RenderedPosition::Create(
const InlineBox* InlineBoxTraversal::FindLeftBidiRun(const InlineBox& box,
unsigned bidi_level) {
- return FindBidiRun<TraverseLeft>(box, bidi_level);
+ const AbstractInlineBox& result =
+ FindBidiRun<TraverseLeft>(AbstractInlineBox(box), bidi_level);
+ if (result.IsNull())
+ return nullptr;
+ DCHECK(result.IsOldLayout());
+ return &result.GetInlineBox();
}
const InlineBox* InlineBoxTraversal::FindRightBidiRun(const InlineBox& box,
unsigned bidi_level) {
- return FindBidiRun<TraverseRight>(box, bidi_level);
-}
-
-const InlineBox& InlineBoxTraversal::FindLeftBoundaryOfBidiRunIgnoringLineBreak(
- const InlineBox& inline_box,
- unsigned bidi_level) {
- return FindBoundaryOfBidiRunIgnoringLineBreak<TraverseLeft>(inline_box,
- bidi_level);
+ const AbstractInlineBox& result =
+ FindBidiRun<TraverseRight>(AbstractInlineBox(box), bidi_level);
+ if (result.IsNull())
+ return nullptr;
+ DCHECK(result.IsOldLayout());
+ return &result.GetInlineBox();
}
const InlineBox& InlineBoxTraversal::FindLeftBoundaryOfEntireBidiRun(
- const InlineBox& inline_box,
- unsigned bidi_level) {
- return FindBoundaryOfEntireBidiRun<TraverseLeft>(inline_box, bidi_level);
-}
-
-const InlineBox&
-InlineBoxTraversal::FindLeftBoundaryOfEntireBidiRunIgnoringLineBreak(
- const InlineBox& inline_box,
+ const InlineBox& box,
unsigned bidi_level) {
- return FindBoundaryOfEntireBidiRunIgnoringLineBreak<TraverseLeft>(inline_box,
- bidi_level);
-}
-
-const InlineBox&
-InlineBoxTraversal::FindRightBoundaryOfBidiRunIgnoringLineBreak(
- const InlineBox& inline_box,
- unsigned bidi_level) {
- return FindBoundaryOfBidiRunIgnoringLineBreak<TraverseRight>(inline_box,
- bidi_level);
+ const AbstractInlineBox& result = FindBoundaryOfEntireBidiRun<TraverseLeft>(
+ AbstractInlineBox(box), bidi_level);
+ DCHECK(result.IsOldLayout());
+ return result.GetInlineBox();
}
const InlineBox& InlineBoxTraversal::FindRightBoundaryOfEntireBidiRun(
- const InlineBox& inline_box,
- unsigned bidi_level) {
- return FindBoundaryOfEntireBidiRun<TraverseRight>(inline_box, bidi_level);
-}
-
-const InlineBox&
-InlineBoxTraversal::FindRightBoundaryOfEntireBidiRunIgnoringLineBreak(
- const InlineBox& inline_box,
+ const InlineBox& box,
unsigned bidi_level) {
- return FindBoundaryOfEntireBidiRunIgnoringLineBreak<TraverseRight>(
- inline_box, bidi_level);
+ const AbstractInlineBox& result = FindBoundaryOfEntireBidiRun<TraverseRight>(
+ AbstractInlineBox(box), bidi_level);
+ DCHECK(result.IsOldLayout());
+ return result.GetInlineBox();
}
InlineBoxPosition BidiAdjustment::AdjustForCaretPositionResolution(
@@ -912,14 +872,12 @@ InlineBoxPosition BidiAdjustment::AdjustForCaretPositionResolution(
NGCaretPosition BidiAdjustment::AdjustForCaretPositionResolution(
const NGCaretPosition& caret_position) {
const AbstractInlineBoxAndSideAffinity unadjusted(caret_position);
- const UnicodeBidi unicode_bidi =
- caret_position.fragment->Style().GetUnicodeBidi();
const AbstractInlineBoxAndSideAffinity adjusted =
unadjusted.AtLeftSide()
? CaretPositionResolutionAdjuster<TraverseRight>::AdjustFor(
- unadjusted.GetBox(), unicode_bidi)
+ unadjusted.GetBox(), UnicodeBidi())
: CaretPositionResolutionAdjuster<TraverseLeft>::AdjustFor(
- unadjusted.GetBox(), unicode_bidi);
+ unadjusted.GetBox(), UnicodeBidi());
return adjusted.ToNGCaretPosition();
}
diff --git a/chromium/third_party/blink/renderer/core/editing/inline_box_traversal.h b/chromium/third_party/blink/renderer/core/editing/inline_box_traversal.h
index ae2254462c7..8f8dc28f403 100644
--- a/chromium/third_party/blink/renderer/core/editing/inline_box_traversal.h
+++ b/chromium/third_party/blink/renderer/core/editing/inline_box_traversal.h
@@ -23,7 +23,7 @@ class BidiAdjustment final {
public:
// Function to be called at the end of caret position resolution, adjusting
// the result in bidi text runs.
- // TODO(xiaochengh): Eliminate |unicode_bidi| from parameters.
+ // TODO(editing-dev): Eliminate |unicode_bidi| from parameters.
static InlineBoxPosition AdjustForCaretPositionResolution(
const InlineBoxPosition&,
UnicodeBidi unicode_bidi);
@@ -62,29 +62,12 @@ class InlineBoxTraversal final {
static const InlineBox* FindRightBidiRun(const InlineBox& box,
unsigned bidi_level);
- // Traverses left/right from |box|, and returns the last non-linebreak box
- // with bidi level greater than |bidi_level| (including |box| itself).
- static const InlineBox& FindLeftBoundaryOfBidiRunIgnoringLineBreak(
- const InlineBox& box,
- unsigned bidi_level);
- static const InlineBox& FindRightBoundaryOfBidiRunIgnoringLineBreak(
- const InlineBox& box,
- unsigned bidi_level);
-
// Traverses left/right from |box|, and returns the last box with bidi level
// greater than or equal to |bidi_level| (including |box| itself).
static const InlineBox& FindLeftBoundaryOfEntireBidiRun(const InlineBox& box,
unsigned bidi_level);
static const InlineBox& FindRightBoundaryOfEntireBidiRun(const InlineBox& box,
unsigned bidi_level);
-
- // Variants of the above two where line break boxes are ignored.
- static const InlineBox& FindLeftBoundaryOfEntireBidiRunIgnoringLineBreak(
- const InlineBox&,
- unsigned bidi_level);
- static const InlineBox& FindRightBoundaryOfEntireBidiRunIgnoringLineBreak(
- const InlineBox&,
- unsigned bidi_level);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/character_iterator.cc b/chromium/third_party/blink/renderer/core/editing/iterators/character_iterator.cc
index 8ac17fd7384..4bccec30ced 100644
--- a/chromium/third_party/blink/renderer/core/editing/iterators/character_iterator.cc
+++ b/chromium/third_party/blink/renderer/core/editing/iterators/character_iterator.cc
@@ -134,6 +134,8 @@ void CharacterIteratorAlgorithm<Strategy>::Advance(int count) {
return;
}
+ DCHECK(!AtEnd());
+
at_break_ = false;
// easy if there is enough left in the current m_textIterator run
diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/character_iterator.h b/chromium/third_party/blink/renderer/core/editing/iterators/character_iterator.h
index 9f060a54f2b..ec82b4553e3 100644
--- a/chromium/third_party/blink/renderer/core/editing/iterators/character_iterator.h
+++ b/chromium/third_party/blink/renderer/core/editing/iterators/character_iterator.h
@@ -38,7 +38,7 @@ namespace blink {
// Builds on the text iterator, adding a character position so we can walk one
// character at a time, or faster, as needed. Useful for searching.
template <typename Strategy>
-class CORE_EXPORT CharacterIteratorAlgorithm {
+class CharacterIteratorAlgorithm {
STACK_ALLOCATED();
public:
diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/fully_clipped_state_stack.h b/chromium/third_party/blink/renderer/core/editing/iterators/fully_clipped_state_stack.h
index 3c8fa02e5b1..0e8ca69fa0e 100644
--- a/chromium/third_party/blink/renderer/core/editing/iterators/fully_clipped_state_stack.h
+++ b/chromium/third_party/blink/renderer/core/editing/iterators/fully_clipped_state_stack.h
@@ -12,8 +12,7 @@
namespace blink {
template <typename Strategy>
-class CORE_TEMPLATE_CLASS_EXPORT FullyClippedStateStackAlgorithm final
- : public BitStack {
+class FullyClippedStateStackAlgorithm final : public BitStack {
STACK_ALLOCATED();
public:
diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/simplified_backwards_text_iterator.h b/chromium/third_party/blink/renderer/core/editing/iterators/simplified_backwards_text_iterator.h
index ad1b8d6e57a..203fa7b4d0c 100644
--- a/chromium/third_party/blink/renderer/core/editing/iterators/simplified_backwards_text_iterator.h
+++ b/chromium/third_party/blink/renderer/core/editing/iterators/simplified_backwards_text_iterator.h
@@ -41,7 +41,7 @@ class LayoutText;
// boundaries at points where replaced elements break up the text flow. The text
// comes back in chunks so as to optimize for performance of the iteration.
template <typename Strategy>
-class CORE_TEMPLATE_CLASS_EXPORT SimplifiedBackwardsTextIteratorAlgorithm {
+class SimplifiedBackwardsTextIteratorAlgorithm {
STACK_ALLOCATED();
public:
diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.cc b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.cc
index 0e13f7ed2f1..04e4ee88a66 100644
--- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.cc
+++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.cc
@@ -709,9 +709,10 @@ bool TextIteratorAlgorithm<Strategy>::ShouldRepresentNodeOffsetZero() {
// The currPos.isNotNull() check is needed because positions in non-HTML
// content (like SVG) do not have visible positions, and we don't want to emit
// for them either.
- VisiblePosition start_pos =
- CreateVisiblePosition(Position(start_container_, start_offset_));
- VisiblePosition curr_pos = VisiblePosition::BeforeNode(*node_);
+ const VisiblePositionTemplate<Strategy> start_pos = CreateVisiblePosition(
+ PositionTemplate<Strategy>(start_container_, start_offset_));
+ const VisiblePositionTemplate<Strategy> curr_pos =
+ VisiblePositionTemplate<Strategy>::BeforeNode(*node_);
return start_pos.IsNotNull() && curr_pos.IsNotNull() &&
!InSameLine(start_pos, curr_pos);
}
diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.h b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.h
index 81af94169e6..51fd7612edb 100644
--- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.h
+++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator.h
@@ -50,7 +50,7 @@ String PlainText(const EphemeralRangeInFlatTree&,
// text comes back in chunks so as to optimize for performance of the iteration.
template <typename Strategy>
-class CORE_TEMPLATE_CLASS_EXPORT TextIteratorAlgorithm {
+class TextIteratorAlgorithm {
STACK_ALLOCATED();
public:
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 f7a30b82311..2221e11d9b3 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
@@ -123,8 +123,7 @@ std::string TextIteratorTest::IterateWithIterator(
String text_chunks;
for (; !iterator.AtEnd(); iterator.Advance()) {
text_chunks.append('[');
- text_chunks.append(
- iterator.GetText().Substring(0, iterator.GetText().length()));
+ text_chunks.append(iterator.GetText().GetTextForTesting());
text_chunks.append(']');
}
return std::string(text_chunks.Utf8().data());
@@ -527,6 +526,18 @@ TEST_P(ParameterizedTextIteratorTest, RangeLengthWithFirstLetter) {
EXPECT_EQ(11, TestRangeLength("<p>^ (1) abc def|</p>"));
}
+TEST_P(ParameterizedTextIteratorTest,
+ RangeLengthWithFirstLetterMultipleLeadingSpaces) {
+ InsertStyleElement("p::first-letter {font-size:200%;}");
+ EXPECT_EQ(0, TestRangeLength("<p>^| foo</p>"));
+ EXPECT_EQ(0, TestRangeLength("<p>^ | foo</p>"));
+ EXPECT_EQ(0, TestRangeLength("<p>^ | foo</p>"));
+ EXPECT_EQ(0, TestRangeLength("<p>^ |foo</p>"));
+ EXPECT_EQ(1, TestRangeLength("<p>^ f|oo</p>"));
+ EXPECT_EQ(2, TestRangeLength("<p>^ fo|o</p>"));
+ EXPECT_EQ(3, TestRangeLength("<p>^ foo|</p>"));
+}
+
TEST_F(TextIteratorTest, WhitespaceCollapseForReplacedElements) {
static const char* body_content =
"<span>Some text </span> <input type='button' value='Button "
@@ -1119,5 +1130,18 @@ TEST_P(ParameterizedTextIteratorTest, PositionInShadowTree) {
ASSERT_TRUE(it.AtEnd());
}
+TEST_P(ParameterizedTextIteratorTest, HiddenFirstLetter) {
+ InsertStyleElement("body::first-letter{visibility:hidden}");
+ SetBodyContent("foo");
+ EXPECT_EQ("[oo]", Iterate<DOMTree>());
+}
+
+TEST_P(ParameterizedTextIteratorTest, HiddenFirstLetterInPre) {
+ InsertStyleElement(
+ "body::first-letter{visibility:hidden} body{white-space:pre}");
+ SetBodyContent("foo");
+ EXPECT_EQ("[oo]", Iterate<DOMTree>());
+}
+
} // namespace text_iterator_test
} // namespace blink
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 99118c416ed..1513e70cc41 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
@@ -36,6 +36,14 @@ bool ShouldSkipInvisibleTextAt(const Text& text,
return layout_object->Style()->Visibility() != EVisibility::kVisible;
}
+EVisibility FirstLetterVisibilityOf(const LayoutObject* layout_object) {
+ const LayoutTextFragment* text_fragment = ToLayoutTextFragment(layout_object);
+ DCHECK(text_fragment->IsRemainingTextLayoutObject());
+ return text_fragment->GetFirstLetterPseudoElement()
+ ->ComputedStyleRef()
+ .Visibility();
+}
+
struct StringAndOffsetRange {
String string;
unsigned start;
@@ -90,12 +98,6 @@ void TextIteratorTextNodeHandler::HandleTextNodeWithLayoutNG() {
DCHECK_LE(offset_, end_offset_);
DCHECK_LE(end_offset_, text_node_->data().length());
- if (ShouldSkipInvisibleTextAt(*text_node_, offset_,
- IgnoresStyleVisibility())) {
- offset_ = end_offset_;
- return;
- }
-
while (offset_ < end_offset_ && !text_state_.PositionNode()) {
const EphemeralRange range_to_emit(Position(text_node_, offset_),
Position(text_node_, end_offset_));
@@ -115,7 +117,9 @@ void TextIteratorTextNodeHandler::HandleTextNodeWithLayoutNG() {
const unsigned run_end = std::min(end_offset_, unit.DOMEnd());
if (run_start >= run_end ||
unit.ConvertDOMOffsetToTextContent(run_start) ==
- unit.ConvertDOMOffsetToTextContent(run_end)) {
+ unit.ConvertDOMOffsetToTextContent(run_end) ||
+ ShouldSkipInvisibleTextAt(*text_node_, run_start,
+ IgnoresStyleVisibility())) {
offset_ = run_end;
continue;
}
@@ -187,11 +191,14 @@ void TextIteratorTextNodeHandler::HandlePreFormattedTextNode() {
}
}
if (ShouldHandleFirstLetter(*layout_object)) {
- HandleTextNodeFirstLetter(ToLayoutTextFragment(layout_object));
+ LayoutTextFragment* remaining_text = ToLayoutTextFragment(layout_object);
+ const bool stops_in_first_letter =
+ end_offset_ <= remaining_text->TextStartOffset();
+
+ HandleTextNodeFirstLetter(remaining_text);
if (first_letter_text_) {
const String first_letter = first_letter_text_->GetText();
const unsigned run_start = offset_;
- const bool stops_in_first_letter = end_offset_ <= first_letter.length();
const unsigned run_end =
stops_in_first_letter ? end_offset_ : first_letter.length();
EmitText(first_letter_text_, run_start, run_end);
@@ -202,10 +209,13 @@ void TextIteratorTextNodeHandler::HandlePreFormattedTextNode() {
needs_handle_pre_formatted_text_node_ = true;
return;
}
- // We are here only if the DOM and/or layout trees are broken.
- // For robustness, we should stop processing this node.
- NOTREACHED();
- return;
+ DCHECK_NE(EVisibility::kVisible, FirstLetterVisibilityOf(remaining_text));
+ if (stops_in_first_letter) {
+ offset_ = end_offset_;
+ return;
+ }
+ // Fall through to handle remaining text.
+ offset_ = remaining_text->TextStartOffset();
}
if (layout_object->Style()->Visibility() != EVisibility::kVisible &&
!IgnoresStyleVisibility())
@@ -277,8 +287,20 @@ void TextIteratorTextNodeHandler::HandleTextNodeInRange(const Text* node,
return;
}
- if (first_letter_text_)
- layout_object = first_letter_text_;
+ if (should_handle_first_letter) {
+ if (first_letter_text_) {
+ layout_object = first_letter_text_;
+ } else {
+ DCHECK_NE(EVisibility::kVisible, FirstLetterVisibilityOf(layout_object));
+ if (end_offset_ <= layout_object->TextStartOffset()) {
+ offset_ = end_offset_;
+ text_box_ = nullptr;
+ return;
+ }
+ // Fall through to handle remaining text.
+ offset_ = layout_object->TextStartOffset();
+ }
+ }
// Used when text boxes are out of order (Hebrew/Arabic w/ embeded LTR text)
if (layout_object->ContainsReversedText()) {
@@ -344,16 +366,18 @@ size_t TextIteratorTextNodeHandler::RestoreCollapsedTrailingSpace(
void TextIteratorTextNodeHandler::HandleTextBox() {
LayoutText* layout_object =
first_letter_text_ ? first_letter_text_ : text_node_->GetLayoutObject();
- const unsigned text_start_offset = layout_object->TextStartOffset();
if (layout_object->Style()->Visibility() != EVisibility::kVisible &&
!IgnoresStyleVisibility()) {
text_box_ = nullptr;
} else {
String str = layout_object->GetText();
+ const unsigned text_start_offset = layout_object->TextStartOffset();
// Start and end offsets in |str|, i.e., str[start..end - 1] should be
// emitted (after handling whitespace collapsing).
- const unsigned start = offset_ - layout_object->TextStartOffset();
+ DCHECK_GE(offset_, text_start_offset);
+ DCHECK_GE(end_offset_, text_start_offset);
+ const unsigned start = offset_ - text_start_offset;
const unsigned end = end_offset_ - text_start_offset;
while (text_box_) {
const unsigned text_box_start = text_box_->Start();
@@ -461,13 +485,12 @@ void TextIteratorTextNodeHandler::HandleTextBox() {
++sorted_text_boxes_position_;
return;
}
- // Advance and continue
- if (run_start == run_end && run_end == end) {
- // "<p>^ |(1) foo</p>" with ::first-letter reaches here.
- // Where "^" is start of range and "|" is end of range.
+ // All remaining text boxes are after range end. Nothing left to emit.
+ if (text_box_start >= end) {
offset_ = end_offset_;
return;
}
+ // Advance and continue
text_box_ = next_text_box;
if (layout_object->ContainsReversedText())
++sorted_text_boxes_position_;
diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.cc b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.cc
index 66c79b7e4d4..494c1418156 100644
--- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.cc
+++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.cc
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.h"
+#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/iterators/backwards_text_buffer.h"
#include "third_party/blink/renderer/core/html/html_element.h"
@@ -73,18 +74,10 @@ UChar TextIteratorTextState::CharacterAt(unsigned index) const {
return text_[text_start_offset_ + index];
}
-String TextIteratorTextState::Substring(unsigned position,
- unsigned length) const {
- SECURITY_DCHECK(position <= this->length());
- SECURITY_DCHECK(position + length <= this->length());
- if (!length)
- return g_empty_string;
- if (single_character_buffer_) {
- DCHECK_EQ(position, 0u);
- DCHECK_EQ(length, 1u);
+String TextIteratorTextState::GetTextForTesting() const {
+ if (single_character_buffer_)
return String(&single_character_buffer_, 1);
- }
- return text_.Substring(text_start_offset_ + position, length);
+ return text_.Substring(text_start_offset_, length());
}
void TextIteratorTextState::AppendTextToStringBuilder(
diff --git a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.h b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.h
index e185b2fee00..9b880d5b615 100644
--- a/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.h
+++ b/chromium/third_party/blink/renderer/core/editing/iterators/text_iterator_text_state.h
@@ -49,7 +49,7 @@ class CORE_EXPORT TextIteratorTextState {
// Return properties of the current text.
unsigned length() const { return text_length_; }
UChar CharacterAt(unsigned index) const;
- String Substring(unsigned position, unsigned length) const;
+ String GetTextForTesting() const;
void AppendTextToStringBuilder(StringBuilder&,
unsigned position = 0,
unsigned max_length = UINT_MAX) const;
diff --git a/chromium/third_party/blink/renderer/core/editing/kill_ring.h b/chromium/third_party/blink/renderer/core/editing/kill_ring.h
new file mode 100644
index 00000000000..5a7977c6161
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/editing/kill_ring.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_KILL_RING_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_KILL_RING_H_
+
+#include "base/macros.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class CORE_EXPORT KillRing {
+ USING_FAST_MALLOC(KillRing);
+
+ public:
+ KillRing() = default;
+ void Append(const String&);
+ void Prepend(const String&);
+ String Yank();
+ void StartNewSequence();
+ void SetToYankedState();
+
+ DISALLOW_COPY_AND_ASSIGN(KillRing);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_KILL_RING_H_
diff --git a/chromium/third_party/blink/renderer/core/editing/kill_ring_mac.mm b/chromium/third_party/blink/renderer/core/editing/kill_ring_mac.mm
new file mode 100644
index 00000000000..94afefcee81
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/editing/kill_ring_mac.mm
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 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 GOOGLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "third_party/blink/renderer/core/editing/kill_ring.h"
+
+namespace blink {
+
+extern "C" {
+
+// Kill ring calls. Would be better to use NSKillRing.h, but that's not
+// available as API or SPI.
+
+void _NSInitializeKillRing();
+void _NSAppendToKillRing(NSString*);
+void _NSPrependToKillRing(NSString*);
+NSString* _NSYankFromKillRing();
+void _NSNewKillRingSequence();
+void _NSSetKillRingToYankedState();
+}
+
+static void InitializeKillRingIfNeeded() {
+ static bool initialized_kill_ring = false;
+ if (!initialized_kill_ring) {
+ initialized_kill_ring = true;
+ _NSInitializeKillRing();
+ }
+}
+
+void KillRing::Append(const String& string) {
+ InitializeKillRingIfNeeded();
+ _NSAppendToKillRing(string);
+}
+
+void KillRing::Prepend(const String& string) {
+ InitializeKillRingIfNeeded();
+ _NSPrependToKillRing(string);
+}
+
+String KillRing::Yank() {
+ InitializeKillRingIfNeeded();
+ return _NSYankFromKillRing();
+}
+
+void KillRing::StartNewSequence() {
+ InitializeKillRingIfNeeded();
+ _NSNewKillRingSequence();
+}
+
+void KillRing::SetToYankedState() {
+ InitializeKillRingIfNeeded();
+ _NSSetKillRingToYankedState();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/kill_ring_none.cc b/chromium/third_party/blink/renderer/core/editing/kill_ring_none.cc
new file mode 100644
index 00000000000..7ef8da2be77
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/editing/kill_ring_none.cc
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "third_party/blink/renderer/core/editing/kill_ring.h"
+
+namespace blink {
+
+void KillRing::Append(const String&) {}
+
+void KillRing::Prepend(const String&) {}
+
+String KillRing::Yank() {
+ return String();
+}
+
+void KillRing::StartNewSequence() {}
+
+void KillRing::SetToYankedState() {}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/layout_selection.cc b/chromium/third_party/blink/renderer/core/editing/layout_selection.cc
index f6ce09af00f..2286b3e9869 100644
--- a/chromium/third_party/blink/renderer/core/editing/layout_selection.cc
+++ b/chromium/third_party/blink/renderer/core/editing/layout_selection.cc
@@ -604,28 +604,72 @@ static NewPaintRangeAndSelectedLayoutObjects MarkStartAndEndInTwoNodes(
std::move(selected_objects)};
}
-static base::Optional<unsigned> GetTextContentOffset(
- LayoutObject* layout_object,
- base::Optional<unsigned> node_offset) {
- DCHECK(layout_object->EnclosingNGBlockFlow());
- // |layout_object| is start or end of selection and offset is only valid
- // if it is LayoutText.
- if (!layout_object->IsText())
- return base::nullopt;
- // There are LayoutText that selection can't be inside it(BR, WBR,
- // LayoutCounter).
- if (!node_offset.has_value())
+#if DCHECK_IS_ON()
+// Position should be offset on text or before/after a break element.
+static bool IsPositionValidText(const Position& position) {
+ if (position.AnchorNode()->IsTextNode() && position.IsOffsetInAnchor())
+ return true;
+ if ((IsHTMLBRElement(position.AnchorNode()) ||
+ IsHTMLWBRElement(position.AnchorNode())) &&
+ (position.IsBeforeAnchor() || position.IsAfterAnchor()))
+ return true;
+ return false;
+}
+#endif
+
+static base::Optional<unsigned> GetTextContentOffset(const Position& position) {
+ if (position.IsNull())
return base::nullopt;
- const Position position_in_dom(*layout_object->GetNode(),
- node_offset.value());
+#if DCHECK_IS_ON()
+ DCHECK(IsPositionValidText(position));
+#endif
+ DCHECK(position.AnchorNode()->GetLayoutObject()->EnclosingNGBlockFlow());
const NGOffsetMapping* const offset_mapping =
- NGOffsetMapping::GetFor(position_in_dom);
+ NGOffsetMapping::GetFor(position);
DCHECK(offset_mapping);
const base::Optional<unsigned>& ng_offset =
- offset_mapping->GetTextContentOffset(position_in_dom);
+ offset_mapping->GetTextContentOffset(position);
return ng_offset;
}
+// Computes text content offset of selection start if |layout_object| is
+// LayoutText.
+static base::Optional<unsigned> GetTextContentOffsetStart(
+ LayoutObject* layout_object,
+ base::Optional<unsigned> node_offset) {
+ if (!layout_object->IsText())
+ return base::nullopt;
+ const Node* node = layout_object->GetNode();
+ DCHECK(node) << layout_object;
+ if (node->IsTextNode()) {
+ DCHECK(node_offset.has_value()) << node;
+ return GetTextContentOffset(Position(*node, node_offset.value()));
+ }
+
+ DCHECK(IsHTMLWBRElement(node) || IsHTMLBRElement(node)) << node;
+ DCHECK(!node_offset.has_value()) << node;
+ return GetTextContentOffset(Position::BeforeNode(*node));
+}
+
+// Computes text content offset of selection end if |layout_object| is
+// LayoutText.
+static base::Optional<unsigned> GetTextContentOffsetEnd(
+ LayoutObject* layout_object,
+ base::Optional<unsigned> node_offset) {
+ if (!layout_object->IsText())
+ return {};
+ const Node* node = layout_object->GetNode();
+ DCHECK(node) << layout_object;
+ if (node->IsTextNode()) {
+ DCHECK(node_offset.has_value()) << node;
+ return GetTextContentOffset(Position(*node, node_offset.value()));
+ }
+
+ DCHECK(IsHTMLWBRElement(node) || IsHTMLBRElement(node)) << node;
+ DCHECK(!node_offset.has_value()) << node;
+ return GetTextContentOffset(Position::AfterNode(*node));
+}
+
static NewPaintRangeAndSelectedLayoutObjects ComputeNewPaintRange(
const NewPaintRangeAndSelectedLayoutObjects& new_range,
LayoutObject* start_layout_object,
@@ -638,13 +682,13 @@ static NewPaintRangeAndSelectedLayoutObjects ComputeNewPaintRange(
// If LayoutObject is not in NG, use legacy offset.
const base::Optional<unsigned> start_offset =
start->EnclosingNGBlockFlow()
- ? GetTextContentOffset(start_layout_object, start_node_offset)
+ ? GetTextContentOffsetStart(start_layout_object, start_node_offset)
: new_range.PaintRange().StartOffset();
LayoutObject* const end = new_range.PaintRange().EndLayoutObject();
const base::Optional<unsigned> end_offset =
end->EnclosingNGBlockFlow()
- ? GetTextContentOffset(end_layout_object, end_node_offset)
+ ? GetTextContentOffsetEnd(end_layout_object, end_node_offset)
: new_range.PaintRange().EndOffset();
return {{start, start_offset, end, end_offset},
@@ -659,17 +703,35 @@ static unsigned ClampOffset(unsigned offset,
text_fragment.EndOffset());
}
-static bool IsBeforeLineBreak(const NGPaintFragment& fragment) {
+// We don't paint a line break the end of inline-block
+// because if an inline-block is at the middle of line, we should not paint
+// a line break.
+// Old layout paints line break if the inline-block is at the end of line, but
+// since its complex to determine if the inline-block is at the end of line on NG,
+// we just cancels block-end line break painting for any inline-block.
+static bool IsLastLineInInlineBlock(const NGPaintFragment& line) {
+ DCHECK(line.PhysicalFragment().IsLineBox());
+ NGPaintFragment* parent = line.Parent();
+ if (!parent->PhysicalFragment().IsAtomicInline())
+ return false;
+ return parent->Children().back().get() == &line;
+}
+
+static bool IsBeforeSoftLineBreak(const NGPaintFragment& fragment) {
+ if (ToNGPhysicalTextFragmentOrDie(fragment.PhysicalFragment()).IsLineBreak())
+ return false;
+
// TODO(yoichio): InlineBlock should not be container line box.
// See paint/selection/text-selection-inline-block.html.
const NGPaintFragment* container_line_box = fragment.ContainerLineBox();
DCHECK(container_line_box);
+ if (IsLastLineInInlineBlock(*container_line_box))
+ return false;
const NGPhysicalLineBoxFragment& physical_line_box =
ToNGPhysicalLineBoxFragment(container_line_box->PhysicalFragment());
- const NGPhysicalFragment* last_leaf_not_linebreak =
- physical_line_box.LastLogicalLeafIgnoringLineBreak();
- DCHECK(last_leaf_not_linebreak);
- if (&fragment.PhysicalFragment() != last_leaf_not_linebreak)
+ const NGPhysicalFragment* last_leaf = physical_line_box.LastLogicalLeaf();
+ DCHECK(last_leaf);
+ if (&fragment.PhysicalFragment() != last_leaf)
return false;
// Even If |fragment| is before linebreak, if its direction differs to line
// direction, we don't paint line break. See
@@ -688,12 +750,9 @@ LayoutSelectionStatus LayoutSelection::ComputeSelectionStatus(
const NGPaintFragment& fragment) const {
const NGPhysicalTextFragment& text_fragment =
ToNGPhysicalTextFragmentOrDie(fragment.PhysicalFragment());
- // For BR, WBR, no selection painting.
- if (fragment.GetNode() && !fragment.GetNode()->IsTextNode())
- return {0, 0, SelectLineBreak::kNotSelected};
- if (text_fragment.IsLineBreak())
- return {0, 0, SelectLineBreak::kNotSelected};
-
+ // We don't paint selection on ellipsis.
+ if (text_fragment.StyleVariant() == NGStyleVariant::kEllipsis)
+ return {0, 0, SelectSoftLineBreak::kNotSelected};
switch (text_fragment.GetLayoutObject()->GetSelectionState()) {
case SelectionState::kStart: {
DCHECK(SelectionStart().has_value());
@@ -701,9 +760,9 @@ LayoutSelectionStatus LayoutSelection::ComputeSelectionStatus(
const bool is_continuous = start_in_block <= text_fragment.EndOffset();
return {ClampOffset(start_in_block, text_fragment),
text_fragment.EndOffset(),
- (is_continuous && IsBeforeLineBreak(fragment))
- ? SelectLineBreak::kSelected
- : SelectLineBreak::kNotSelected};
+ (is_continuous && IsBeforeSoftLineBreak(fragment))
+ ? SelectSoftLineBreak::kSelected
+ : SelectSoftLineBreak::kNotSelected};
}
case SelectionState::kEnd: {
DCHECK(SelectionEnd().has_value());
@@ -712,9 +771,9 @@ LayoutSelectionStatus LayoutSelection::ComputeSelectionStatus(
const unsigned end_in_fragment = ClampOffset(end_in_block, text_fragment);
const bool is_continuous = text_fragment.EndOffset() < end_in_block;
return {text_fragment.StartOffset(), end_in_fragment,
- (is_continuous && IsBeforeLineBreak(fragment))
- ? SelectLineBreak::kSelected
- : SelectLineBreak::kNotSelected};
+ (is_continuous && IsBeforeSoftLineBreak(fragment))
+ ? SelectSoftLineBreak::kSelected
+ : SelectSoftLineBreak::kNotSelected};
}
case SelectionState::kStartAndEnd: {
DCHECK(SelectionStart().has_value());
@@ -726,18 +785,19 @@ LayoutSelectionStatus LayoutSelection::ComputeSelectionStatus(
const bool is_continuous = start_in_block <= text_fragment.EndOffset() &&
text_fragment.EndOffset() < end_in_block;
return {ClampOffset(start_in_block, text_fragment), end_in_fragment,
- (is_continuous && IsBeforeLineBreak(fragment))
- ? SelectLineBreak::kSelected
- : SelectLineBreak::kNotSelected};
+ (is_continuous && IsBeforeSoftLineBreak(fragment))
+ ? SelectSoftLineBreak::kSelected
+ : SelectSoftLineBreak::kNotSelected};
}
case SelectionState::kInside: {
return {text_fragment.StartOffset(), text_fragment.EndOffset(),
- IsBeforeLineBreak(fragment) ? SelectLineBreak::kSelected
- : SelectLineBreak::kNotSelected};
+ IsBeforeSoftLineBreak(fragment)
+ ? SelectSoftLineBreak::kSelected
+ : SelectSoftLineBreak::kNotSelected};
}
default:
// This block is not included in selection.
- return {0, 0, SelectLineBreak::kNotSelected};
+ return {0, 0, SelectSoftLineBreak::kNotSelected};
}
}
@@ -921,8 +981,19 @@ void PrintLayoutObjectForSelection(std::ostream& ostream,
ostream << "<null>";
return;
}
- ostream << (void*)layout_object << ' ' << layout_object->GetNode()
- << ", state:" << layout_object->GetSelectionState()
+ ostream << (void*)layout_object << ' ';
+ if (const LayoutTextFragment* fragment =
+ ToLayoutTextFragmentOrNull(*layout_object)) {
+ // TODO(yoichio): Treat LayoutQuote which may generate LayoutTextFragment
+ // that's neither first-letter nor remaining text.
+ if (fragment->IsRemainingTextLayoutObject())
+ ostream << "remaining part of " << fragment->AssociatedTextNode();
+ else
+ ostream << "first-letter of " << fragment->AssociatedTextNode();
+ } else {
+ ostream << layout_object->GetNode();
+ }
+ ostream << ", state:" << layout_object->GetSelectionState()
<< (layout_object->ShouldInvalidateSelection() ? ", ShouldInvalidate"
: ", NotInvalidate");
}
diff --git a/chromium/third_party/blink/renderer/core/editing/layout_selection_test.cc b/chromium/third_party/blink/renderer/core/editing/layout_selection_test.cc
index 3b9607505a0..abb63da7d1f 100644
--- a/chromium/third_party/blink/renderer/core/editing/layout_selection_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/layout_selection_test.cc
@@ -21,33 +21,197 @@
namespace blink {
+static const LayoutTextFragment* ToFirstLetterOrNull(
+ const LayoutObject& layout_object) {
+ if (const LayoutTextFragment* fragment =
+ ToLayoutTextFragmentOrNull(layout_object)) {
+ if (fragment->IsRemainingTextLayoutObject())
+ return nullptr;
+ return fragment;
+ }
+ return nullptr;
+}
+
+static const Node* FindNextNodeOnDOMIncludingShadow(const Node& node) {
+ if (const ShadowRoot* shadow_root = node.GetShadowRoot())
+ return shadow_root;
+ if (const Node* first_child = node.firstChild())
+ return first_child;
+ if (const Node* next_sibling = node.nextSibling())
+ return next_sibling;
+ for (const Node* parent = node.parentNode(); parent;) {
+ if (parent->IsShadowRoot()) {
+ Node* host = parent->ParentOrShadowHostNode();
+ DCHECK_EQ(host->GetShadowRoot(), parent);
+ if (const Node* first_child = host->firstChild())
+ return first_child;
+ parent = host;
+ continue;
+ }
+ if (const Node* next_sibling = parent->nextSibling())
+ return next_sibling;
+ parent = parent->parentNode();
+ }
+ return nullptr;
+}
+
+static LayoutTextFragment* FirstLetterPartFor(
+ const LayoutObject* layout_object) {
+ if (!layout_object->IsText())
+ return nullptr;
+ if (!ToLayoutText(layout_object)->IsTextFragment())
+ return nullptr;
+ return ToLayoutTextFragment(const_cast<LayoutObject*>(
+ AssociatedLayoutObjectOf(*layout_object->GetNode(), 0)));
+}
+
+static LayoutObject* NextLayoutObjectOnDOMTreeIncludeShadow(
+ const LayoutObject& layout_object) {
+ // If |layout_object| is a first letter part, return remaining part.
+ if (const LayoutTextFragment* fragment = ToFirstLetterOrNull(layout_object)) {
+ return fragment->AssociatedTextNode()->GetLayoutObject();
+ }
+ // Otherwise, find the first layouted object of following nodes.
+ const Node* node = layout_object.GetNode();
+ DCHECK(node);
+ for (const Node* next = FindNextNodeOnDOMIncludingShadow(*node); next;
+ next = FindNextNodeOnDOMIncludingShadow(*next)) {
+ LayoutObject* layout_object = next->GetLayoutObject();
+ if (!layout_object)
+ continue;
+ if (LayoutObject* first_letter = FirstLetterPartFor(layout_object))
+ return first_letter;
+ return layout_object;
+ }
+ return nullptr;
+}
+
class LayoutSelectionTest : public EditingTestBase {
- public:
+ protected:
LayoutObject* Current() const { return current_; }
+ void Reset() {
+ results.clear();
+ stream = std::stringstream();
+ current_ = GetDocument().body()->GetLayoutObject();
+ }
+
void Next() {
+ DCHECK(current_);
+ current_ = NextLayoutObjectOnDOMTreeIncludeShadow(*current_);
+ }
+ void TestNext(bool result) {
+ results.push_back(result);
+ if (!result) {
+ stream << "case " << results.size() - 1 << " failed.\n";
+ }
if (!current_) {
- current_ = GetDocument().body()->GetLayoutObject();
+ stream << "cases are more than layout objects.\n";
return;
}
- current_ = current_->NextInPreOrder();
+ Next();
}
-#ifndef NDEBUG
- void PrintLayoutTreeForDebug() {
- std::stringstream stream;
+ bool CheckResult() {
+ if (current_)
+ stream << "cases are fewer than layout objects.";
+
+ std::string errors = stream.str();
+ if (errors.size()) {
+ std::stringstream layout_tree;
+ PrintLayoutTree(layout_tree);
+ LOG(ERROR) << "\n" << errors << layout_tree.str();
+ }
+ return !errors.size();
+ }
+
+ WTF::Vector<bool> results;
+ std::stringstream stream;
+
+ void PrintLayoutTree(std::stringstream& stream) {
for (LayoutObject* runner = GetDocument().body()->GetLayoutObject(); runner;
- runner = runner->NextInPreOrder()) {
- PrintLayoutObjectForSelection(stream, runner);
+ runner = NextLayoutObjectOnDOMTreeIncludeShadow(*runner)) {
stream << '\n';
+ PrintLayoutObjectForSelection(stream, runner);
}
- LOG(INFO) << '\n' << stream.str();
+ }
+
+ void PrintText(std::ostream& ostream, const Text& text) {
+ ostream << "'" << text.data().Utf8().data() << "'";
+ }
+
+ void PrintSelectionInfo(std::ostream& ostream, LayoutObject* layout_object) {
+ if (!layout_object) {
+ ostream << "<null>";
+ return;
+ }
+ if (const LayoutTextFragment* fragment =
+ ToLayoutTextFragmentOrNull(*layout_object)) {
+ // TODO(yoichio): Treat LayoutQuote which may generate LayoutTextFragment
+ // that's neither first-letter nor remaining text.
+ if (fragment->IsRemainingTextLayoutObject())
+ ostream << "remaining part of ";
+ else
+ ostream << "first-letter of ";
+ PrintText(ostream, *fragment->AssociatedTextNode());
+ } else {
+ if (Text* text = ToTextOrNull(layout_object->GetNode()))
+ PrintText(ostream, *text);
+ else
+ ostream << layout_object->GetNode();
+ }
+ ostream << ", " << layout_object->GetSelectionState()
+ << (layout_object->ShouldInvalidateSelection()
+ ? ", ShouldInvalidate "
+ : ", NotInvalidate ");
+ }
+
+ void PrintDOMTreeInternal(std::ostream& ostream,
+ const Node& node,
+ size_t depth) {
+ ostream << RepeatString(" ", depth).Utf8().data();
+ PrintSelectionInfo(ostream, node.GetLayoutObject());
+ if (ShadowRoot* shadow_root = node.GetShadowRoot()) {
+ ostream << std::endl << RepeatString(" ", depth + 1).Utf8().data();
+ ostream << "#shadow-root";
+ for (Node* child = shadow_root->firstChild(); child;
+ child = child->nextSibling()) {
+ PrintDOMTreeInternal(ostream, *child, depth + 2);
+ }
+ }
+
+ for (Node* child = node.firstChild(); child; child = child->nextSibling()) {
+ ostream << std::endl;
+ PrintDOMTreeInternal(ostream, *child, depth + 1);
+ }
+ }
+
+#ifndef NDEBUG
+ void PrintDOMTreeForDebug() {
+ std::stringstream stream;
+ stream << "\nPrintDOMTreeForDebug";
+ PrintDOMTreeInternal(stream, *GetDocument().body(), 0u);
+ LOG(INFO) << stream.str();
}
#endif
+ std::string DumpSelectionInfo() {
+ std::stringstream stream;
+ PrintDOMTreeInternal(stream, *GetDocument().body(), 0u);
+ return stream.str();
+ }
+
private:
LayoutObject* current_ = nullptr;
};
+// You can test SeletionStatus of all LayoutObjects in the body with following
+// macros. See TraverseLayoutObject example below.
+#define TEST_RESET() Reset();
+#define TEST_NEXT(predicate, state, invalidate) \
+ TestNext(TestLayoutObject(Current(), predicate, SelectionState::state, \
+ InvalidateOption::invalidate));
+#define TEST_CHECK() EXPECT_TRUE(CheckResult())
+
std::ostream& operator<<(std::ostream& ostream, LayoutObject* layout_object) {
PrintLayoutObjectForSelection(ostream, layout_object);
return ostream;
@@ -82,9 +246,10 @@ USING_LAYOUTOBJECT_FUNC(IsLayoutNGBlockFlow);
USING_LAYOUTOBJECT_FUNC(IsLayoutInline);
USING_LAYOUTOBJECT_FUNC(IsBR);
USING_LAYOUTOBJECT_FUNC(IsListItem);
-USING_LAYOUTOBJECT_FUNC(IsListMarker);
USING_LAYOUTOBJECT_FUNC(IsLayoutImage);
USING_LAYOUTOBJECT_FUNC(IsLayoutButton);
+USING_LAYOUTOBJECT_FUNC(IsRuby);
+USING_LAYOUTOBJECT_FUNC(IsRubyText);
USING_LAYOUTOBJECT_FUNC(IsSVGRoot);
USING_LAYOUTOBJECT_FUNC(IsSVGText);
USING_LAYOUTOBJECT_FUNC(IsLayoutEmbeddedContent);
@@ -101,6 +266,14 @@ static IsTypeOf IsLayoutTextFragmentOf(const String& text) {
text);
}
+static IsTypeOf IsLayoutOf(const String& text) {
+ return WTF::BindRepeating(
+ [](const String& text, const LayoutObject& object) {
+ return ToElement(object.GetNode())->tagName() == text;
+ },
+ text);
+}
+
static bool IsSVGTSpan(const LayoutObject& layout_object) {
return layout_object.GetName() == String("LayoutSVGTSpan");
}
@@ -149,16 +322,6 @@ static bool TestLayoutObject(LayoutObject* object,
state, invalidate);
}
-#define TEST_NEXT(predicate, state, invalidate) \
- Next(); \
- EXPECT_TRUE(TestLayoutObject(Current(), predicate, SelectionState::state, \
- InvalidateOption::invalidate)) \
- << Current();
-
-#define TEST_NO_NEXT_LAYOUT_OBJECT() \
- Next(); \
- EXPECT_EQ(Current(), nullptr)
-
TEST_F(LayoutSelectionTest, TraverseLayoutObject) {
SetBodyContent("foo<br>bar");
Selection().SetSelectionAndEndTyping(
@@ -166,11 +329,12 @@ TEST_F(LayoutSelectionTest, TraverseLayoutObject) {
.SelectAllChildren(*GetDocument().body())
.Build());
Selection().CommitAppearanceIfNeeded();
- TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
- TEST_NEXT("foo", kStart, ShouldInvalidate);
- TEST_NEXT(IsBR, kInside, ShouldInvalidate);
- TEST_NEXT("bar", kEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ EXPECT_EQ(
+ "BODY, Contain, NotInvalidate \n"
+ " 'foo', Start, ShouldInvalidate \n"
+ " BR, Inside, ShouldInvalidate \n"
+ " 'bar', End, ShouldInvalidate ",
+ DumpSelectionInfo());
}
TEST_F(LayoutSelectionTest, TraverseLayoutObjectTruncateVisibilityHidden) {
@@ -183,13 +347,14 @@ TEST_F(LayoutSelectionTest, TraverseLayoutObjectTruncateVisibilityHidden) {
.SelectAllChildren(*GetDocument().body())
.Build());
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
TEST_NEXT("before", kNone, NotInvalidate);
TEST_NEXT("foo", kStartAndEnd, ShouldInvalidate);
TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
TEST_NEXT("after", kNone, NotInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
}
TEST_F(LayoutSelectionTest, TraverseLayoutObjectBRs) {
@@ -199,13 +364,14 @@ TEST_F(LayoutSelectionTest, TraverseLayoutObjectBRs) {
.SelectAllChildren(*GetDocument().body())
.Build());
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT(IsBR, kStart, ShouldInvalidate);
TEST_NEXT(IsBR, kInside, ShouldInvalidate);
TEST_NEXT("foo", kInside, ShouldInvalidate);
TEST_NEXT(IsBR, kInside, ShouldInvalidate);
TEST_NEXT(IsBR, kEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
EXPECT_FALSE(Selection().LayoutSelectionStart().has_value());
EXPECT_FALSE(Selection().LayoutSelectionEnd().has_value());
}
@@ -221,15 +387,14 @@ TEST_F(LayoutSelectionTest, TraverseLayoutObjectListStyleImage) {
.SelectAllChildren(*GetDocument().body())
.Build());
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT(IsLayoutBlockFlow, kContain, NotInvalidate);
TEST_NEXT(IsListItem, kContain, NotInvalidate);
- TEST_NEXT(IsListMarker, kNone, NotInvalidate);
TEST_NEXT("foo", kStart, ShouldInvalidate);
TEST_NEXT(IsListItem, kContain, NotInvalidate);
- TEST_NEXT(IsListMarker, kNone, NotInvalidate);
TEST_NEXT("bar", kEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
}
TEST_F(LayoutSelectionTest, TraverseLayoutObjectCrossingShadowBoundary) {
@@ -243,16 +408,16 @@ TEST_F(LayoutSelectionTest, TraverseLayoutObjectCrossingShadowBoundary) {
"<span slot=s1><!--|-->bar1</span><span slot=s2>bar2</span>"
"</div>"));
Selection().CommitAppearanceIfNeeded();
- TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
- TEST_NEXT(IsLayoutBlockFlow, kContain, NotInvalidate);
+ TEST_RESET();
+ TEST_NEXT(IsLayoutOf("BODY"), kContain, NotInvalidate);
TEST_NEXT("foo", kStart, ShouldInvalidate);
- TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
+ TEST_NEXT(IsLayoutOf("DIV"), kContain, NotInvalidate);
TEST_NEXT("Foo", kInside, ShouldInvalidate);
- TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
- TEST_NEXT("bar2", kEnd, ShouldInvalidate);
- TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
+ TEST_NEXT(IsLayoutOf("SPAN"), kNone, NotInvalidate);
TEST_NEXT("bar1", kNone, NotInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_NEXT(IsLayoutOf("SPAN"), kNone, NotInvalidate);
+ TEST_NEXT("bar2", kEnd, ShouldInvalidate);
+ TEST_CHECK();
}
// crbug.com/752715
@@ -267,6 +432,7 @@ TEST_F(LayoutSelectionTest,
Position(span->firstChild(), 3))
.Build());
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT(IsLayoutBlockFlow, kNone, NotInvalidate);
TEST_NEXT("div1", kNone, NotInvalidate);
@@ -275,7 +441,7 @@ TEST_F(LayoutSelectionTest,
TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
TEST_NEXT("bar", kStartAndEnd, ShouldInvalidate);
TEST_NEXT("baz", kNone, NotInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
Node* d1 = GetDocument().QuerySelector("#d1");
Node* d2 = GetDocument().QuerySelector("#d2");
@@ -285,6 +451,7 @@ TEST_F(LayoutSelectionTest,
.Build());
// This commit should not crash.
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT(IsLayoutBlockFlow, kContain, NotInvalidate);
TEST_NEXT("div1", kStartAndEnd, ShouldInvalidate);
@@ -293,7 +460,7 @@ TEST_F(LayoutSelectionTest,
TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
TEST_NEXT("bar", kNone, ShouldInvalidate);
TEST_NEXT("baz", kNone, NotInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
}
TEST_F(LayoutSelectionTest, TraverseLayoutObjectLineWrap) {
@@ -303,9 +470,10 @@ TEST_F(LayoutSelectionTest, TraverseLayoutObjectLineWrap) {
.SelectAllChildren(*GetDocument().body())
.Build());
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("bar\n", kStartAndEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
EXPECT_EQ(0u, Selection().LayoutSelectionStart());
EXPECT_EQ(4u, Selection().LayoutSelectionEnd());
}
@@ -319,12 +487,12 @@ TEST_F(LayoutSelectionTest, FirstLetter) {
.SelectAllChildren(*GetDocument().body())
.Build());
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
- TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
TEST_NEXT(IsLayoutTextFragmentOf("f"), kStart, ShouldInvalidate);
TEST_NEXT(IsLayoutTextFragmentOf("oo"), kEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
}
TEST_F(LayoutSelectionTest, FirstLetterClearSeletion) {
@@ -332,27 +500,24 @@ TEST_F(LayoutSelectionTest, FirstLetterClearSeletion) {
Selection().SetSelectionAndEndTyping(
SetSelectionTextToBody("fo^o<div>bar</div>b|az"));
Selection().CommitAppearanceIfNeeded();
- TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("foo", kStart, ShouldInvalidate);
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
- TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
TEST_NEXT(IsLayoutTextFragmentOf("b"), kInside, ShouldInvalidate);
TEST_NEXT(IsLayoutTextFragmentOf("ar"), kInside, ShouldInvalidate);
- TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("baz", kEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
+
Selection().ClearLayoutSelection();
- TEST_NEXT(IsLayoutBlock, kNone, NotInvalidate);
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kNone, NotInvalidate);
TEST_NEXT("foo", kNone, ShouldInvalidate);
TEST_NEXT(IsLayoutBlock, kNone, NotInvalidate);
- TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
TEST_NEXT(IsLayoutTextFragmentOf("b"), kNone, ShouldInvalidate);
TEST_NEXT(IsLayoutTextFragmentOf("ar"), kNone, ShouldInvalidate);
- TEST_NEXT(IsLayoutBlock, kNone, NotInvalidate);
TEST_NEXT("baz", kNone, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
}
TEST_F(LayoutSelectionTest, FirstLetterUpdateSeletion) {
@@ -371,35 +536,31 @@ TEST_F(LayoutSelectionTest, FirstLetterUpdateSeletion) {
.SetBaseAndExtent({foo, 2}, {baz, 1})
.Build());
Selection().CommitAppearanceIfNeeded();
- TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("foo", kStart, ShouldInvalidate);
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
- TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
TEST_NEXT(IsLayoutTextFragmentOf("b"), kInside, ShouldInvalidate);
TEST_NEXT(IsLayoutTextFragmentOf("ar"), kInside, ShouldInvalidate);
- TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("baz", kEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
// <div>foo</div><div>bar</div>ba^z|
Selection().SetSelectionAndEndTyping(SelectionInDOMTree::Builder()
.SetBaseAndExtent({baz, 2}, {baz, 3})
.Build());
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
- TEST_NEXT(IsLayoutBlock, kNone, NotInvalidate);
TEST_NEXT("foo", kNone, ShouldInvalidate);
// TODO(yoichio): Invalidating next LayoutBlock is flaky but it doesn't
// matter in wild because we don't paint selection gap. I will update
// invalidating propagation so this flakiness should be fixed as:
// TEST_NEXT(IsLayoutBlock, kNone, NotInvalidate);
Next();
- TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
TEST_NEXT(IsLayoutTextFragmentOf("b"), kNone, ShouldInvalidate);
TEST_NEXT(IsLayoutTextFragmentOf("ar"), kNone, ShouldInvalidate);
- TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("baz", kStartAndEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
}
TEST_F(LayoutSelectionTest, CommitAppearanceIfNeededNotCrash) {
@@ -417,9 +578,10 @@ TEST_F(LayoutSelectionTest, SelectImage) {
SetSelectionTextToBody("^<img style=\"width:100px; height:100px\"/>|");
Selection().SetSelectionAndEndTyping(selection);
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT(IsLayoutImage, kStartAndEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
EXPECT_FALSE(Selection().LayoutSelectionStart().has_value());
EXPECT_FALSE(Selection().LayoutSelectionEnd().has_value());
}
@@ -429,21 +591,23 @@ TEST_F(LayoutSelectionTest, MoveOnSameNode_Start) {
SetSelectionTextToBody("f^oo<span>b|ar</span>");
Selection().SetSelectionAndEndTyping(selection);
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("foo", kStart, ShouldInvalidate);
TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
TEST_NEXT("bar", kEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
EXPECT_EQ(1u, Selection().LayoutSelectionStart());
EXPECT_EQ(1u, Selection().LayoutSelectionEnd());
// Paint virtually and clear ShouldInvalidate flag.
UpdateAllLifecyclePhases();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("foo", kStart, NotInvalidate);
TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
TEST_NEXT("bar", kEnd, NotInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
// "fo^o<span>b|ar</span>"
Selection().SetSelectionAndEndTyping(
@@ -453,11 +617,12 @@ TEST_F(LayoutSelectionTest, MoveOnSameNode_Start) {
.Build());
Selection().CommitAppearanceIfNeeded();
// Only "foo" should be invalidated.
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("foo", kStart, ShouldInvalidate);
TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
TEST_NEXT("bar", kEnd, NotInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
EXPECT_EQ(2u, Selection().LayoutSelectionStart());
EXPECT_EQ(1u, Selection().LayoutSelectionEnd());
}
@@ -467,21 +632,23 @@ TEST_F(LayoutSelectionTest, MoveOnSameNode_End) {
SetSelectionTextToBody("f^oo<span>b|ar</span>");
Selection().SetSelectionAndEndTyping(selection);
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("foo", kStart, ShouldInvalidate);
TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
TEST_NEXT("bar", kEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
EXPECT_EQ(1u, Selection().LayoutSelectionStart());
EXPECT_EQ(1u, Selection().LayoutSelectionEnd());
// Paint virtually and clear ShouldInvalidate flag.
UpdateAllLifecyclePhases();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("foo", kStart, NotInvalidate);
TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
TEST_NEXT("bar", kEnd, NotInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
// "fo^o<span>ba|r</span>"
Selection().SetSelectionAndEndTyping(
@@ -491,11 +658,12 @@ TEST_F(LayoutSelectionTest, MoveOnSameNode_End) {
.Build());
Selection().CommitAppearanceIfNeeded();
// Only "bar" should be invalidated.
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("foo", kStart, NotInvalidate);
TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
TEST_NEXT("bar", kEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
EXPECT_EQ(1u, Selection().LayoutSelectionStart());
EXPECT_EQ(2u, Selection().LayoutSelectionEnd());
}
@@ -504,17 +672,19 @@ TEST_F(LayoutSelectionTest, MoveOnSameNode_StartAndEnd) {
const SelectionInDOMTree& selection = SetSelectionTextToBody("f^oob|ar");
Selection().SetSelectionAndEndTyping(selection);
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("foobar", kStartAndEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
EXPECT_EQ(1u, Selection().LayoutSelectionStart());
EXPECT_EQ(4u, Selection().LayoutSelectionEnd());
// Paint virtually and clear ShouldInvalidate flag.
UpdateAllLifecyclePhases();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("foobar", kStartAndEnd, NotInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
// "f^ooba|r"
Selection().SetSelectionAndEndTyping(
@@ -524,9 +694,10 @@ TEST_F(LayoutSelectionTest, MoveOnSameNode_StartAndEnd) {
.Build());
Selection().CommitAppearanceIfNeeded();
// "foobar" should be invalidated.
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("foobar", kStartAndEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
EXPECT_EQ(1u, Selection().LayoutSelectionStart());
EXPECT_EQ(5u, Selection().LayoutSelectionEnd());
}
@@ -535,17 +706,19 @@ TEST_F(LayoutSelectionTest, MoveOnSameNode_StartAndEnd_Collapse) {
const SelectionInDOMTree& selection = SetSelectionTextToBody("f^oob|ar");
Selection().SetSelectionAndEndTyping(selection);
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("foobar", kStartAndEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
EXPECT_EQ(1u, Selection().LayoutSelectionStart());
EXPECT_EQ(4u, Selection().LayoutSelectionEnd());
// Paint virtually and clear ShouldInvalidate flag.
UpdateAllLifecyclePhases();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("foobar", kStartAndEnd, NotInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
// "foo^|bar"
Selection().SetSelectionAndEndTyping(
@@ -554,9 +727,10 @@ TEST_F(LayoutSelectionTest, MoveOnSameNode_StartAndEnd_Collapse) {
.Build());
Selection().CommitAppearanceIfNeeded();
// "foobar" should be invalidated.
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kNone, NotInvalidate);
TEST_NEXT("foobar", kNone, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
EXPECT_FALSE(Selection().LayoutSelectionStart().has_value());
EXPECT_FALSE(Selection().LayoutSelectionEnd().has_value());
}
@@ -568,35 +742,38 @@ TEST_F(LayoutSelectionTest, ContentEditableButton) {
.SelectAllChildren(*GetDocument().body())
.Build());
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT(IsLayoutButton, kContain, NotInvalidate);
- TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("foo", kStartAndEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
}
TEST_F(LayoutSelectionTest, ClearSelection) {
Selection().SetSelectionAndEndTyping(
SetSelectionTextToBody("<div>f^o|o</div>"));
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("foo", kStartAndEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
EXPECT_EQ(1u, Selection().LayoutSelectionStart());
EXPECT_EQ(2u, Selection().LayoutSelectionEnd());
UpdateAllLifecyclePhases();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT("foo", kStartAndEnd, NotInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
Selection().ClearLayoutSelection();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kNone, NotInvalidate);
TEST_NEXT(IsLayoutBlock, kNone, NotInvalidate);
TEST_NEXT("foo", kNone, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
EXPECT_FALSE(Selection().LayoutSelectionStart().has_value());
EXPECT_FALSE(Selection().LayoutSelectionEnd().has_value());
}
@@ -606,21 +783,23 @@ TEST_F(LayoutSelectionTest, SVG) {
SetSelectionTextToBody("<svg><text x=10 y=10>fo^o|bar</text></svg>");
Selection().SetSelectionAndEndTyping(selection);
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT(IsSVGRoot, kNone, NotInvalidate);
// LayoutSVGText should be invalidate though it is kContain.
TEST_NEXT(IsSVGText, kContain, ShouldInvalidate);
TEST_NEXT("foobar", kStartAndEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
EXPECT_EQ(2u, Selection().LayoutSelectionStart());
EXPECT_EQ(3u, Selection().LayoutSelectionEnd());
UpdateAllLifecyclePhases();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT(IsSVGRoot, kNone, NotInvalidate);
TEST_NEXT(IsSVGText, kContain, NotInvalidate);
TEST_NEXT("foobar", kStartAndEnd, NotInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
Selection().SetSelectionAndEndTyping(
SelectionInDOMTree::Builder()
@@ -628,11 +807,12 @@ TEST_F(LayoutSelectionTest, SVG) {
{selection.Extent().AnchorNode(), 4})
.Build());
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT(IsSVGRoot, kNone, NotInvalidate);
TEST_NEXT(IsSVGText, kContain, ShouldInvalidate);
TEST_NEXT("foobar", kStartAndEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
EXPECT_EQ(2u, Selection().LayoutSelectionStart());
EXPECT_EQ(4u, Selection().LayoutSelectionEnd());
}
@@ -643,23 +823,25 @@ TEST_F(LayoutSelectionTest, SVGAncestor) {
"<svg><text x=10 y=10><tspan>fo^o|bar</tspan></text></svg>");
Selection().SetSelectionAndEndTyping(selection);
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT(IsSVGRoot, kNone, NotInvalidate);
// LayoutSVGText should be invalidated.
TEST_NEXT(IsSVGText, kContain, ShouldInvalidate);
TEST_NEXT(IsSVGTSpan, kNone, NotInvalidate);
TEST_NEXT("foobar", kStartAndEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
EXPECT_EQ(2u, Selection().LayoutSelectionStart());
EXPECT_EQ(3u, Selection().LayoutSelectionEnd());
UpdateAllLifecyclePhases();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT(IsSVGRoot, kNone, NotInvalidate);
TEST_NEXT(IsSVGText, kContain, NotInvalidate);
TEST_NEXT(IsSVGTSpan, kNone, NotInvalidate);
TEST_NEXT("foobar", kStartAndEnd, NotInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
Selection().SetSelectionAndEndTyping(
SelectionInDOMTree::Builder()
@@ -667,12 +849,13 @@ TEST_F(LayoutSelectionTest, SVGAncestor) {
{selection.Extent().AnchorNode(), 4})
.Build());
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT(IsSVGRoot, kNone, NotInvalidate);
TEST_NEXT(IsSVGText, kContain, ShouldInvalidate);
TEST_NEXT(IsSVGTSpan, kNone, NotInvalidate);
TEST_NEXT("foobar", kStartAndEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
EXPECT_EQ(2u, Selection().LayoutSelectionStart());
EXPECT_EQ(4u, Selection().LayoutSelectionEnd());
}
@@ -681,9 +864,45 @@ TEST_F(LayoutSelectionTest, Embed) {
Selection().SetSelectionAndEndTyping(
SetSelectionTextToBody("^<embed type=foobar></embed>|"));
Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
TEST_NEXT(IsLayoutBlock, kContain, NotInvalidate);
TEST_NEXT(IsLayoutEmbeddedContent, kStartAndEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
+}
+
+// http:/crbug.com/843144
+TEST_F(LayoutSelectionTest, Ruby) {
+ Selection().SetSelectionAndEndTyping(
+ SetSelectionTextToBody("^<ruby>foo<rt>bar</rt></ruby>|"));
+ Selection().CommitAppearanceIfNeeded();
+ TEST_RESET();
+ TEST_NEXT(IsLayoutOf("BODY"), kContain, NotInvalidate);
+ TEST_NEXT(IsRuby, kNone, NotInvalidate);
+ TEST_NEXT("foo", kStart, ShouldInvalidate);
+ TEST_NEXT(IsRubyText, kContain, NotInvalidate);
+ TEST_NEXT("bar", kEnd, ShouldInvalidate);
+ TEST_CHECK();
+
+ UpdateAllLifecyclePhases();
+ TEST_RESET();
+ TEST_NEXT(IsLayoutOf("BODY"), kContain, NotInvalidate);
+ TEST_NEXT(IsRuby, kNone, NotInvalidate);
+ TEST_NEXT("foo", kStart, NotInvalidate);
+ TEST_NEXT(IsRubyText, kContain, NotInvalidate);
+ TEST_NEXT("bar", kEnd, NotInvalidate);
+ TEST_CHECK();
+
+ Selection().ClearLayoutSelection();
+ TEST_RESET();
+ TEST_NEXT(IsLayoutOf("BODY"), kNone, NotInvalidate);
+ TEST_NEXT(IsRuby, kNone, NotInvalidate);
+ TEST_NEXT("foo", kNone, ShouldInvalidate);
+ // TODO(yoichio): These 2 should be kNone.
+ // TEST_NEXT(IsRubyText, kNone, NotInvalidate);
+ // TEST_NEXT("bar", kNone, ShouldInvalidate);
+ TEST_NEXT(IsRubyText, kContain, NotInvalidate);
+ TEST_NEXT("bar", kEnd, NotInvalidate);
+ TEST_CHECK();
}
static const NGPaintFragment* FindNGPaintFragmentInternal(
@@ -737,7 +956,7 @@ class NGLayoutSelectionTest
GetNGPaintFragment(first_text->GetLayoutObject());
const LayoutSelectionStatus& status =
Selection().ComputeLayoutSelectionStatus(fragment);
- return status.line_break == SelectLineBreak::kSelected;
+ return status.line_break == SelectSoftLineBreak::kSelected;
}
LayoutSelectionStatus ComputeLayoutSelectionStatus(const Node& node) {
@@ -755,28 +974,25 @@ class NGLayoutSelectionTest
std::ostream& operator<<(std::ostream& ostream,
const LayoutSelectionStatus& status) {
- const String line_break = (status.line_break == SelectLineBreak::kSelected)
- ? "kSelected"
- : "kNotSelected";
+ const String line_break =
+ (status.line_break == SelectSoftLineBreak::kSelected) ? "kSelected"
+ : "kNotSelected";
return ostream << status.start << ", " << status.end << ", " << std::boolalpha
<< line_break;
}
TEST_F(NGLayoutSelectionTest, SelectOnOneText) {
-#ifndef NDEBUG
- // This line prohibits compiler optimization removing the debug function.
- PrintLayoutTreeForDebug();
-#endif
SetSelectionAndUpdateLayoutSelection("foo<span>b^a|r</span>");
+ TEST_RESET();
TEST_NEXT(IsLayoutNGBlockFlow, kContain, NotInvalidate);
TEST_NEXT("foo", kNone, NotInvalidate);
TEST_NEXT(IsLayoutInline, kNone, NotInvalidate);
TEST_NEXT("bar", kStartAndEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
LayoutObject* const foo =
GetDocument().body()->firstChild()->GetLayoutObject();
- EXPECT_EQ(LayoutSelectionStatus(0u, 0u, SelectLineBreak::kNotSelected),
+ EXPECT_EQ(LayoutSelectionStatus(0u, 0u, SelectSoftLineBreak::kNotSelected),
Selection().ComputeLayoutSelectionStatus(GetNGPaintFragment(foo)));
LayoutObject* const bar = GetDocument()
.body()
@@ -784,42 +1000,43 @@ TEST_F(NGLayoutSelectionTest, SelectOnOneText) {
->nextSibling()
->firstChild()
->GetLayoutObject();
- EXPECT_EQ(LayoutSelectionStatus(4u, 5u, SelectLineBreak::kNotSelected),
+ EXPECT_EQ(LayoutSelectionStatus(4u, 5u, SelectSoftLineBreak::kNotSelected),
Selection().ComputeLayoutSelectionStatus(GetNGPaintFragment(bar)));
}
TEST_F(NGLayoutSelectionTest, FirstLetterInAnotherBlockFlow) {
SetSelectionAndUpdateLayoutSelection(
"<style>:first-letter { float: right}</style>^fo|o");
- TEST_NEXT(IsLayoutNGBlockFlow, kContain, NotInvalidate);
+ TEST_RESET();
TEST_NEXT(IsLayoutNGBlockFlow, kContain, NotInvalidate);
TEST_NEXT(IsLayoutTextFragmentOf("f"), kStart, ShouldInvalidate);
TEST_NEXT(IsLayoutTextFragmentOf("oo"), kEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
Node* const foo = GetDocument().body()->firstChild()->nextSibling();
const LayoutTextFragment* const foo_f =
ToLayoutTextFragment(AssociatedLayoutObjectOf(*foo, 0));
EXPECT_EQ(
- LayoutSelectionStatus(0u, 1u, SelectLineBreak::kSelected),
+ LayoutSelectionStatus(0u, 1u, SelectSoftLineBreak::kSelected),
Selection().ComputeLayoutSelectionStatus(GetNGPaintFragment(foo_f)));
const LayoutTextFragment* const foo_oo =
ToLayoutTextFragment(AssociatedLayoutObjectOf(*foo, 1));
EXPECT_EQ(
- LayoutSelectionStatus(1u, 2u, SelectLineBreak::kNotSelected),
+ LayoutSelectionStatus(1u, 2u, SelectSoftLineBreak::kNotSelected),
Selection().ComputeLayoutSelectionStatus(GetNGPaintFragment(foo_oo)));
}
TEST_F(NGLayoutSelectionTest, TwoNGBlockFlows) {
SetSelectionAndUpdateLayoutSelection("<div>f^oo</div><div>ba|r</div>");
+ TEST_RESET();
TEST_NEXT(IsLayoutNGBlockFlow, kContain, NotInvalidate);
TEST_NEXT(IsLayoutNGBlockFlow, kContain, NotInvalidate);
TEST_NEXT("foo", kStart, ShouldInvalidate);
TEST_NEXT(IsLayoutNGBlockFlow, kContain, NotInvalidate);
TEST_NEXT("bar", kEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
LayoutObject* const foo =
GetDocument().body()->firstChild()->firstChild()->GetLayoutObject();
- EXPECT_EQ(LayoutSelectionStatus(1u, 3u, SelectLineBreak::kSelected),
+ EXPECT_EQ(LayoutSelectionStatus(1u, 3u, SelectSoftLineBreak::kSelected),
Selection().ComputeLayoutSelectionStatus(GetNGPaintFragment(foo)));
LayoutObject* const bar = GetDocument()
.body()
@@ -827,64 +1044,65 @@ TEST_F(NGLayoutSelectionTest, TwoNGBlockFlows) {
->nextSibling()
->firstChild()
->GetLayoutObject();
- EXPECT_EQ(LayoutSelectionStatus(0u, 2u, SelectLineBreak::kNotSelected),
+ EXPECT_EQ(LayoutSelectionStatus(0u, 2u, SelectSoftLineBreak::kNotSelected),
Selection().ComputeLayoutSelectionStatus(GetNGPaintFragment(bar)));
}
+// TODO(editing-dev): Once LayoutNG supports editing, we should change this
+// test to use LayoutNG tree.
TEST_F(NGLayoutSelectionTest, MixedBlockFlowsAsSibling) {
SetSelectionAndUpdateLayoutSelection(
"<div>f^oo</div>"
"<div contenteditable>ba|r</div>");
- TEST_NEXT(IsLayoutNGBlockFlow, kContain, NotInvalidate);
- TEST_NEXT(IsLayoutNGBlockFlow, kContain, NotInvalidate);
+ TEST_RESET();
+ TEST_NEXT(IsLayoutBlockFlow, kContain, NotInvalidate);
+ TEST_NEXT(IsLayoutBlockFlow, kContain, NotInvalidate);
TEST_NEXT("foo", kStart, ShouldInvalidate);
- TEST_NEXT(IsLegacyBlockFlow, kContain, NotInvalidate);
+ TEST_NEXT(IsLayoutBlockFlow, kContain, NotInvalidate);
TEST_NEXT("bar", kEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
- LayoutObject* const foo =
- GetDocument().body()->firstChild()->firstChild()->GetLayoutObject();
- EXPECT_EQ(LayoutSelectionStatus(1u, 3u, SelectLineBreak::kSelected),
- Selection().ComputeLayoutSelectionStatus(GetNGPaintFragment(foo)));
+ TEST_CHECK();
+ EXPECT_EQ(1u, Selection().LayoutSelectionStart().value());
EXPECT_EQ(2u, Selection().LayoutSelectionEnd().value());
}
+// TODO(editing-dev): Once LayoutNG supports editing, we should change this
+// test to use LayoutNG tree.
TEST_F(NGLayoutSelectionTest, MixedBlockFlowsAnscestor) {
// Both "foo" and "bar" for DIV elements should be legacy LayoutBlock.
SetSelectionAndUpdateLayoutSelection(
"<div contenteditable>f^oo"
"<div contenteditable=false>ba|r</div></div>");
- TEST_NEXT(IsLayoutNGBlockFlow, kContain, NotInvalidate);
+ TEST_RESET();
+ TEST_NEXT(IsLayoutBlockFlow, kContain, NotInvalidate);
TEST_NEXT(IsLegacyBlockFlow, kContain, NotInvalidate);
- TEST_NEXT(IsLayoutNGBlockFlow, kContain, NotInvalidate);
TEST_NEXT("foo", kStart, ShouldInvalidate);
TEST_NEXT(IsLegacyBlockFlow, kContain, NotInvalidate);
TEST_NEXT("bar", kEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
+ TEST_CHECK();
EXPECT_EQ(1u, Selection().LayoutSelectionStart().value());
}
+// TODO(editing-dev): Once LayoutNG supports editing, we should change this
+// test to use LayoutNG tree.
TEST_F(NGLayoutSelectionTest, MixedBlockFlowsDecendant) {
SetSelectionAndUpdateLayoutSelection(
"<div contenteditable=false>f^oo"
"<div contenteditable>ba|r</div></div>");
- TEST_NEXT(IsLayoutNGBlockFlow, kContain, NotInvalidate);
- TEST_NEXT(IsLayoutNGBlockFlow, kContain, NotInvalidate);
- TEST_NEXT(IsLayoutNGBlockFlow, kContain, NotInvalidate);
+ TEST_RESET();
+ TEST_NEXT(IsLayoutBlockFlow, kContain, NotInvalidate);
+ TEST_NEXT(IsLayoutBlockFlow, kContain, NotInvalidate);
TEST_NEXT("foo", kStart, ShouldInvalidate);
TEST_NEXT(IsLegacyBlockFlow, kContain, NotInvalidate);
TEST_NEXT("bar", kEnd, ShouldInvalidate);
- TEST_NO_NEXT_LAYOUT_OBJECT();
- LayoutObject* const foo =
- GetDocument().body()->firstChild()->firstChild()->GetLayoutObject();
- EXPECT_EQ(LayoutSelectionStatus(1u, 3u, SelectLineBreak::kSelected),
- Selection().ComputeLayoutSelectionStatus(GetNGPaintFragment(foo)));
+ TEST_CHECK();
+ EXPECT_EQ(1u, Selection().LayoutSelectionStart().value());
EXPECT_EQ(2u, Selection().LayoutSelectionEnd().value());
}
TEST_F(NGLayoutSelectionTest, LineBreakBasic) {
LoadAhem();
- EXPECT_TRUE(IsFirstTextLineBreak("<div>f^oo<br>ba|r</div>"));
- EXPECT_TRUE(IsFirstTextLineBreak("<div>^foo<br><br>|</div>"));
+ EXPECT_FALSE(IsFirstTextLineBreak("<div>f^oo<br>ba|r</div>"));
+ EXPECT_FALSE(IsFirstTextLineBreak("<div>^foo<br><br>|</div>"));
EXPECT_TRUE(IsFirstTextLineBreak(
"<div style='font: Ahem; width: 2em'>f^oo ba|r</div>"));
EXPECT_TRUE(IsFirstTextLineBreak("<div>f^oo</div><div>b|ar</div>"));
@@ -899,16 +1117,22 @@ TEST_F(NGLayoutSelectionTest, LineBreakBasic) {
// "<div style='display:inline-block'>f^oo</div>bar|"));
}
+TEST_F(NGLayoutSelectionTest, LineBreakInlineBlock) {
+ LoadAhem();
+ EXPECT_FALSE(
+ IsFirstTextLineBreak("<div style='display:inline-block'>^x</div>y|"));
+}
+
TEST_F(NGLayoutSelectionTest, LineBreakImage) {
SetSelectionAndUpdateLayoutSelection(
"<div>^<img id=img1 width=10px height=10px>foo<br>"
"bar<img id=img2 width=10px height=10px>|</div>");
Node* const foo =
GetDocument().body()->firstChild()->firstChild()->nextSibling();
- EXPECT_EQ(SelectLineBreak::kSelected,
+ EXPECT_EQ(SelectSoftLineBreak::kNotSelected,
ComputeLayoutSelectionStatus(*foo).line_break);
Node* const bar = foo->nextSibling()->nextSibling();
- EXPECT_EQ(SelectLineBreak::kNotSelected,
+ EXPECT_EQ(SelectSoftLineBreak::kNotSelected,
ComputeLayoutSelectionStatus(*bar).line_break);
}
@@ -921,7 +1145,7 @@ TEST_F(NGLayoutSelectionTest, BRStatus) {
GetDocument().QuerySelector("br")->GetLayoutObject();
CHECK(layout_br->IsBR());
EXPECT_EQ(
- LayoutSelectionStatus(0u, 0u, SelectLineBreak::kNotSelected),
+ LayoutSelectionStatus(3u, 4u, SelectSoftLineBreak::kNotSelected),
Selection().ComputeLayoutSelectionStatus(GetNGPaintFragment(layout_br)));
}
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 b30fd729643..dc0257d76b7 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
@@ -29,7 +29,7 @@
#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
#include <algorithm>
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/dom/text.h"
@@ -51,6 +51,7 @@
#include "third_party/blink/renderer/core/editing/visible_units.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/layout/layout_view.h"
#ifndef NDEBUG
#include <stdio.h>
@@ -523,6 +524,82 @@ DocumentMarkerVector DocumentMarkerController::Markers() {
return result;
}
+DocumentMarkerVector DocumentMarkerController::ComputeMarkersToPaint(
+ const Node& node) {
+ // We don't render composition or spelling markers that overlap suggestion
+ // markers.
+ // Note: DocumentMarkerController::MarkersFor() returns markers sorted by
+ // start offset.
+ const DocumentMarkerVector& suggestion_markers =
+ MarkersFor(&node, DocumentMarker::kSuggestion);
+ if (suggestion_markers.IsEmpty()) {
+ // If there are no suggestion markers, we can return early as a minor
+ // performance optimization.
+ DocumentMarker::MarkerTypes remaining_types = DocumentMarker::AllMarkers();
+ remaining_types.Remove(DocumentMarker::kSuggestion);
+ return MarkersFor(&node, remaining_types);
+ }
+
+ const DocumentMarkerVector& markers_overridden_by_suggestion_markers =
+ MarkersFor(&node,
+ DocumentMarker::kComposition | DocumentMarker::kSpelling);
+
+ Vector<unsigned> suggestion_starts;
+ Vector<unsigned> suggestion_ends;
+ for (const DocumentMarker* suggestion_marker : suggestion_markers) {
+ suggestion_starts.push_back(suggestion_marker->StartOffset());
+ suggestion_ends.push_back(suggestion_marker->EndOffset());
+ }
+
+ std::sort(suggestion_starts.begin(), suggestion_starts.end());
+ std::sort(suggestion_ends.begin(), suggestion_ends.end());
+
+ unsigned suggestion_starts_index = 0;
+ unsigned suggestion_ends_index = 0;
+ unsigned number_suggestions_currently_inside = 0;
+
+ DocumentMarkerVector markers_to_paint;
+ for (DocumentMarker* marker : markers_overridden_by_suggestion_markers) {
+ while (suggestion_starts_index < suggestion_starts.size() &&
+ suggestion_starts[suggestion_starts_index] <=
+ marker->StartOffset()) {
+ ++suggestion_starts_index;
+ ++number_suggestions_currently_inside;
+ }
+ while (suggestion_ends_index < suggestion_ends.size() &&
+ suggestion_ends[suggestion_ends_index] <= marker->StartOffset()) {
+ ++suggestion_ends_index;
+ --number_suggestions_currently_inside;
+ }
+
+ // At this point, number_suggestions_currently_inside should be equal to the
+ // number of suggestion markers overlapping the point marker->StartOffset()
+ // (marker endpoints don't count as overlapping).
+
+ // Marker is overlapped by a suggestion marker, do not paint.
+ if (number_suggestions_currently_inside)
+ continue;
+
+ // Verify that no suggestion marker starts before the current marker ends.
+ if (suggestion_starts_index < suggestion_starts.size() &&
+ suggestion_starts[suggestion_starts_index] < marker->EndOffset())
+ continue;
+
+ markers_to_paint.push_back(marker);
+ }
+
+ markers_to_paint.AppendVector(suggestion_markers);
+
+ DocumentMarker::MarkerTypes remaining_types = DocumentMarker::AllMarkers();
+ remaining_types.Remove(DocumentMarker::kComposition |
+ DocumentMarker::kSpelling |
+ DocumentMarker::kSuggestion);
+
+ markers_to_paint.AppendVector(MarkersFor(&node, remaining_types));
+
+ return markers_to_paint;
+}
+
Vector<IntRect> DocumentMarkerController::LayoutRectsForTextMatchMarkers() {
DCHECK(!document_->View()->NeedsLayout());
DCHECK(!document_->NeedsLayoutTreeUpdate());
@@ -553,8 +630,8 @@ Vector<IntRect> DocumentMarkerController::LayoutRectsForTextMatchMarkers() {
}
static void InvalidatePaintForTickmarks(const Node& node) {
- if (LocalFrameView* frame_view = node.GetDocument().View())
- frame_view->InvalidatePaintForTickmarks();
+ if (LayoutView* layout_view = node.GetDocument().GetLayoutView())
+ layout_view->InvalidatePaintForTickmarks();
}
void DocumentMarkerController::InvalidateRectsForTextMatchMarkersInNode(
@@ -611,8 +688,10 @@ void DocumentMarkerController::RemoveSpellingMarkersUnderWords(
DocumentMarkerList* const list = ListForType(markers, type);
if (!list)
continue;
- ToSpellCheckMarkerListImpl(list)->RemoveMarkersUnderWords(
- ToText(node).data(), words);
+ if (ToSpellCheckMarkerListImpl(list)->RemoveMarkersUnderWords(
+ ToText(node).data(), words)) {
+ InvalidatePaintForNode(node);
+ }
}
}
}
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 c0d3de46e11..7f358621152 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
@@ -120,6 +120,8 @@ class CORE_EXPORT DocumentMarkerController final
const Node*,
DocumentMarker::MarkerTypes = DocumentMarker::AllMarkers());
DocumentMarkerVector Markers();
+ // TODO(yoichio): Make const by making PossiblyHasMarkers const.
+ DocumentMarkerVector ComputeMarkersToPaint(const Node&);
Vector<IntRect> LayoutRectsForTextMatchMarkers();
void InvalidateRectsForAllTextMatchMarkers();
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller_test.cc b/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller_test.cc
index f1bcea1c5a4..1fb2fcf60c8 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller_test.cc
@@ -33,7 +33,6 @@
#include <memory>
#include "base/memory/scoped_refptr.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_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/text.h"
@@ -42,7 +41,9 @@
#include "third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.h"
#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
#include "third_party/blink/renderer/core/html/html_element.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -188,6 +189,30 @@ TEST_F(DocumentMarkerControllerTest, NodeWillBeRemovedBySetInnerHTML) {
EXPECT_EQ(0u, MarkerController().Markers().size());
}
+// TODO(crbug.com/862900): Fix DocumentMarkerController::DidUpdateCharacterData
+// and enable this test.
+TEST_F(DocumentMarkerControllerTest,
+ DISABLED_SynchronousMutationNotificationAfterGC) {
+ SetBodyContent("<b><i>foo</i></b>");
+ Persistent<Text> sibling_text = CreateTextNode("bar");
+ {
+ Element* parent =
+ ToElement(GetDocument().body()->firstChild()->firstChild());
+ parent->parentNode()->AppendChild(sibling_text);
+ MarkNodeContents(parent);
+ EXPECT_EQ(1u, MarkerController().Markers().size());
+ parent->parentNode()->RemoveChild(parent);
+ }
+
+ // GC the marked node, so it disappears from WeakMember collections.
+ ThreadState::Current()->CollectAllGarbage();
+ EXPECT_EQ(0u, MarkerController().Markers().size());
+
+ // Trigger SynchronousMutationNotifier::NotifyUpdateCharacterData().
+ // This matches the conditions for the crashes in crbug.com/862960.
+ sibling_text->setData("baz");
+}
+
TEST_F(DocumentMarkerControllerTest, UpdateRenderedRects) {
SetBodyContent("<div style='margin: 100px'>foo</div>");
Element* div = ToElement(GetDocument().body()->firstChild());
@@ -313,6 +338,24 @@ TEST_F(DocumentMarkerControllerTest, RemoveSpellingMarkersUnderWords) {
EXPECT_EQ(DocumentMarker::kTextMatch, marker.GetType());
}
+TEST_F(DocumentMarkerControllerTest, RemoveSpellingMarkersUnderAllWords) {
+ SetBodyContent("<div contenteditable>foo</div>");
+ Element* div = GetDocument().QuerySelector("div");
+ Node* text = div->firstChild();
+ ASSERT_NE(text->GetLayoutObject(), nullptr);
+
+ const EphemeralRange marker_range(Position(text, 0), Position(text, 3));
+ text->GetLayoutObject()->ClearPaintInvalidationFlags();
+ MarkerController().AddSpellingMarker(marker_range);
+ EXPECT_TRUE(text->GetLayoutObject()->ShouldCheckForPaintInvalidation());
+ ASSERT_EQ(1u, MarkerController().Markers().size());
+
+ text->GetLayoutObject()->ClearPaintInvalidationFlags();
+ MarkerController().RemoveSpellingMarkersUnderWords({"foo"});
+ EXPECT_TRUE(text->GetLayoutObject()->ShouldCheckForPaintInvalidation());
+ ASSERT_EQ(0u, MarkerController().Markers().size());
+}
+
TEST_F(DocumentMarkerControllerTest, RemoveSuggestionMarkerByTag) {
SetBodyContent("<div contenteditable>foo</div>");
Element* div = GetDocument().QuerySelector("div");
diff --git a/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.cc b/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.cc
index a1bbb5638f8..bf232cc7b68 100644
--- a/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.cc
+++ b/chromium/third_party/blink/renderer/core/editing/markers/text_match_marker_list_impl.cc
@@ -86,7 +86,7 @@ static void UpdateMarkerLayoutRect(const Node& node, TextMatchMarker& marker) {
DCHECK(frame_view);
marker.SetLayoutRect(
- frame_view->AbsoluteToDocument(LayoutRect(ComputeTextRect(range))));
+ frame_view->FrameToDocument(LayoutRect(ComputeTextRect(range))));
}
Vector<IntRect> TextMatchMarkerListImpl::LayoutRects(const Node& node) const {
diff --git a/chromium/third_party/blink/renderer/core/editing/position.h b/chromium/third_party/blink/renderer/core/editing/position.h
index 5da5181e77e..f19cca9bb79 100644
--- a/chromium/third_party/blink/renderer/core/editing/position.h
+++ b/chromium/third_party/blink/renderer/core/editing/position.h
@@ -47,7 +47,7 @@ enum class PositionAnchorType : unsigned {
// Instances of |PositionTemplate<Strategy>| are immutable.
// TODO(editing-dev): Make constructor of |PositionTemplate| take |const Node*|.
template <typename Strategy>
-class CORE_TEMPLATE_CLASS_EXPORT PositionTemplate {
+class PositionTemplate {
DISALLOW_NEW();
public:
diff --git a/chromium/third_party/blink/renderer/core/editing/position_iterator.h b/chromium/third_party/blink/renderer/core/editing/position_iterator.h
index 820e4ad8e7e..c5239864926 100644
--- a/chromium/third_party/blink/renderer/core/editing/position_iterator.h
+++ b/chromium/third_party/blink/renderer/core/editing/position_iterator.h
@@ -39,7 +39,7 @@ namespace blink {
// Conversion to Position is O(1).
// PositionIteratorAlgorithm must be used without DOM tree change.
template <typename Strategy>
-class CORE_TEMPLATE_CLASS_EXPORT PositionIteratorAlgorithm {
+class PositionIteratorAlgorithm {
STACK_ALLOCATED();
public:
diff --git a/chromium/third_party/blink/renderer/core/editing/position_with_affinity.h b/chromium/third_party/blink/renderer/core/editing/position_with_affinity.h
index 1bf36b227c7..008ffbcf2e7 100644
--- a/chromium/third_party/blink/renderer/core/editing/position_with_affinity.h
+++ b/chromium/third_party/blink/renderer/core/editing/position_with_affinity.h
@@ -14,7 +14,7 @@ namespace blink {
enum class TextAffinity;
template <typename Strategy>
-class CORE_TEMPLATE_CLASS_EXPORT PositionWithAffinityTemplate {
+class PositionWithAffinityTemplate {
DISALLOW_NEW();
public:
diff --git a/chromium/third_party/blink/renderer/core/editing/rendered_position.cc b/chromium/third_party/blink/renderer/core/editing/rendered_position.cc
index dc4d4d71184..c31eb28a12b 100644
--- a/chromium/third_party/blink/renderer/core/editing/rendered_position.cc
+++ b/chromium/third_party/blink/renderer/core/editing/rendered_position.cc
@@ -41,6 +41,7 @@
#include "third_party/blink/renderer/core/html/forms/text_control_element.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_selection.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include <unicode/ubidi.h>
diff --git a/chromium/third_party/blink/renderer/core/editing/rendered_position_test.cc b/chromium/third_party/blink/renderer/core/editing/rendered_position_test.cc
index f2c8217eeed..f3c86170239 100644
--- a/chromium/third_party/blink/renderer/core/editing/rendered_position_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/rendered_position_test.cc
@@ -15,7 +15,7 @@
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_selection.h"
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
-#include "third_party/blink/renderer/platform/testing/use_mock_scrollbar_settings.h"
+#include "third_party/blink/renderer/core/testing/use_mock_scrollbar_settings.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/editing/selection_adjuster.cc b/chromium/third_party/blink/renderer/core/editing/selection_adjuster.cc
index c982005a60f..30f3881e094 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_adjuster.cc
+++ b/chromium/third_party/blink/renderer/core/editing/selection_adjuster.cc
@@ -299,8 +299,9 @@ class GranularityAdjuster final {
const PositionTemplate<Strategy> expanded_end =
new_end.IsNotNull() ? new_end : end;
- const EphemeralRangeTemplate<Strategy> expanded_range(expanded_start,
- expanded_end);
+ const EphemeralRangeTemplate<Strategy> expanded_range =
+ AdjustStartAndEnd(expanded_start, expanded_end);
+
return ComputeAdjustedSelection(canonicalized_selection, expanded_range);
}
@@ -314,6 +315,21 @@ class GranularityAdjuster final {
? kPreviousWordIfOnBoundary
: kNextWordIfOnBoundary;
}
+
+ // Because of expansion is done in flat tree, in case of |start| and |end| are
+ // distributed, |start| can be after |end|.
+ static EphemeralRange AdjustStartAndEnd(const Position& start,
+ const Position& end) {
+ if (start <= end)
+ return EphemeralRange(start, end);
+ return EphemeralRange(end, start);
+ }
+
+ static EphemeralRangeInFlatTree AdjustStartAndEnd(
+ const PositionInFlatTree& start,
+ const PositionInFlatTree& end) {
+ return EphemeralRangeInFlatTree(start, end);
+ }
};
PositionInFlatTree ComputeStartRespectingGranularity(
@@ -562,199 +578,125 @@ class EditingBoundaryAdjuster final {
public:
template <typename Strategy>
static SelectionTemplate<Strategy> AdjustSelection(
- const SelectionTemplate<Strategy>& shadow_adjusted_selection) {
- // TODO(editing-dev): Refactor w/o EphemeralRange.
- const EphemeralRangeTemplate<Strategy> shadow_adjusted_range =
- shadow_adjusted_selection.ComputeRange();
- const EphemeralRangeTemplate<Strategy> editing_adjusted_range =
- AdjustSelectionToAvoidCrossingEditingBoundaries(
- shadow_adjusted_range, shadow_adjusted_selection.Base());
- return ComputeAdjustedSelection(shadow_adjusted_selection,
- editing_adjusted_range);
+ const SelectionTemplate<Strategy>& selection) {
+ const auto adjusted = AdjustExtent(selection);
+ // TODO(editing-dev): This DCHECK now fails on crossing <body> selection.
+ // Test ApplyBlockElementCommandTest.selectionCrossingOverBody has base
+ // outside of <body> and extent inside of <body>, after adjustment, new
+ // extent is still inside of <body>, so RBE is not the same.
+ // DCHECK_EQ(
+ // &RootBoundaryElementOf<Strategy>(
+ // *selection.Base().ComputeContainerNode()),
+ // &RootBoundaryElementOf<Strategy>(*adjusted.ComputeContainerNode()))
+ // << std::endl
+ // << selection << std::endl
+ // << adjusted;
+ return typename SelectionTemplate<Strategy>::Builder(selection)
+ .Extend(adjusted)
+ .Build();
}
private:
- static Element* LowestEditableAncestor(Node* node) {
- while (node) {
- if (HasEditableStyle(*node))
- return RootEditableElement(*node);
- if (IsHTMLBodyElement(*node))
+ template <typename Strategy>
+ static bool IsEditingBoundary(const Node& node,
+ const Node& previous_node,
+ bool is_previous_node_editable) {
+ return HasEditableStyle(node) != is_previous_node_editable;
+ }
+
+ // Returns the highest ancestor of |start| along the parent chain, so that
+ // all node in between them including the ancestor have the same
+ // HasEditableStyle() bit with |start|. Note that it only consider the <body>
+ // subtree.
+ template <typename Strategy>
+ static const Node& RootBoundaryElementOf(const Node& start) {
+ if (IsHTMLBodyElement(start))
+ return start;
+
+ const bool is_editable = HasEditableStyle(start);
+ const Node* result = &start;
+ for (const Node& ancestor : Strategy::AncestorsOf(start)) {
+ if (IsEditingBoundary<Strategy>(ancestor, *result, is_editable))
+ break;
+ result = &ancestor;
+ if (IsHTMLBodyElement(*result))
break;
- node = node->parentNode();
}
- return nullptr;
+ return *result;
}
- // Returns true if |position| is editable or its lowest editable root is not
- // |base_editable_ancestor|.
+ // TODO(editing-dev): The input |selection| for this function might cross
+ // shadow boundary in DOM tree in flat tree selection case. We still want to
+ // adjust the selection on DOM tree since currently editibility is defined on
+ // DOM tree according to spec, so we need to deal with shadow boundary in this
+ // function for flat tree selection. We ended with no good way but just
+ // templated the DOM tree algorithm including |RootBoundaryElementOf()| for
+ // flat tree.
template <typename Strategy>
- static bool ShouldContinueSearchEditingBoundary(
- const PositionTemplate<Strategy>& position,
- Element* base_editable_ancestor) {
- if (position.IsNull())
- return false;
- if (IsEditablePosition(position))
- return true;
- return LowestEditableAncestor(position.ComputeContainerNode()) !=
- base_editable_ancestor;
- }
+ static PositionTemplate<Strategy> AdjustExtent(
+ const SelectionTemplate<Strategy>& selection) {
+ DCHECK(!selection.IsNone()) << selection;
- template <typename Strategy>
- static bool ShouldAdjustPositionToAvoidCrossingEditingBoundaries(
- const PositionTemplate<Strategy>& position,
- const ContainerNode* editable_root,
- const Element* base_editable_ancestor) {
- if (editable_root)
- return true;
- Element* const editable_ancestor =
- LowestEditableAncestor(position.ComputeContainerNode());
- return editable_ancestor != base_editable_ancestor;
- }
+ const Node* const base_node = selection.Base().ComputeContainerNode();
+ const Node* const extent_node = selection.Extent().ComputeContainerNode();
- // The selection ends in editable content or non-editable content inside a
- // different editable ancestor, move backward until non-editable content
- // inside the same lowest editable ancestor is reached.
- template <typename Strategy>
- static PositionTemplate<Strategy>
- AdjustSelectionEndToAvoidCrossingEditingBoundaries(
- const PositionTemplate<Strategy>& end,
- ContainerNode* end_root,
- Element* base_editable_ancestor) {
- if (ShouldAdjustPositionToAvoidCrossingEditingBoundaries(
- end, end_root, base_editable_ancestor)) {
- PositionTemplate<Strategy> position =
- PreviousVisuallyDistinctCandidate(end);
- Element* shadow_ancestor =
- end_root ? end_root->OwnerShadowHost() : nullptr;
- if (position.IsNull() && shadow_ancestor)
- position = PositionTemplate<Strategy>::AfterNode(*shadow_ancestor);
- while (ShouldContinueSearchEditingBoundary(position,
- base_editable_ancestor)) {
- Element* root = RootEditableElementOf(position);
- shadow_ancestor = root ? root->OwnerShadowHost() : nullptr;
- position = IsAtomicNode(position.ComputeContainerNode())
- ? PositionTemplate<Strategy>::InParentBeforeNode(
- *position.ComputeContainerNode())
- : PreviousVisuallyDistinctCandidate(position);
- if (position.IsNull() && shadow_ancestor)
- position = PositionTemplate<Strategy>::AfterNode(*shadow_ancestor);
- }
- return CreateVisiblePosition(position).DeepEquivalent();
- }
- return end;
- }
+ // In the same node, no need to adjust.
+ if (base_node == extent_node)
+ return selection.Extent();
- // The selection starts in editable content or non-editable content inside a
- // different editable ancestor, move forward until non-editable content inside
- // the same lowest editable ancestor is reached.
- template <typename Strategy>
- static PositionTemplate<Strategy>
- AdjustSelectionStartToAvoidCrossingEditingBoundaries(
- const PositionTemplate<Strategy>& start,
- ContainerNode* start_root,
- Element* base_editable_ancestor) {
- if (ShouldAdjustPositionToAvoidCrossingEditingBoundaries(
- start, start_root, base_editable_ancestor)) {
- PositionTemplate<Strategy> position =
- NextVisuallyDistinctCandidate(start);
- Element* shadow_ancestor =
- start_root ? start_root->OwnerShadowHost() : nullptr;
- if (position.IsNull() && shadow_ancestor)
- position = PositionTemplate<Strategy>::BeforeNode(*shadow_ancestor);
- while (ShouldContinueSearchEditingBoundary(position,
- base_editable_ancestor)) {
- Element* root = RootEditableElementOf(position);
- shadow_ancestor = root ? root->OwnerShadowHost() : nullptr;
- position = IsAtomicNode(position.ComputeContainerNode())
- ? PositionTemplate<Strategy>::InParentAfterNode(
- *position.ComputeContainerNode())
- : NextVisuallyDistinctCandidate(position);
- if (position.IsNull() && shadow_ancestor)
- position = PositionTemplate<Strategy>::BeforeNode(*shadow_ancestor);
- }
- return CreateVisiblePosition(position).DeepEquivalent();
- }
- return start;
- }
+ const Node& base_rbe = RootBoundaryElementOf<Strategy>(*base_node);
+ const Node& extent_rbe = RootBoundaryElementOf<Strategy>(*extent_node);
- template <typename Strategy>
- static EphemeralRangeTemplate<Strategy>
- AdjustSelectionToAvoidCrossingEditingBoundaries(
- const EphemeralRangeTemplate<Strategy>& range,
- const PositionTemplate<Strategy>& base) {
- DCHECK(base.IsNotNull());
- DCHECK(range.IsNotNull());
+ // In the same RBE, no need to adjust.
+ if (base_rbe == extent_rbe)
+ return selection.Extent();
- ContainerNode* base_root = HighestEditableRoot(base);
- ContainerNode* start_root = HighestEditableRoot(range.StartPosition());
- ContainerNode* end_root = HighestEditableRoot(range.EndPosition());
-
- Element* base_editable_ancestor =
- LowestEditableAncestor(base.ComputeContainerNode());
-
- // The base, start and end are all in the same region. No adjustment
- // necessary.
- if (base_root == start_root && base_root == end_root)
- return range;
-
- // The selection is based in editable content.
- if (base_root) {
- // If the start is outside the base's editable root, cap it at the start
- // of that root. If the start is in non-editable content that is inside
- // the base's editable root, put it at the first editable position after
- // start inside the base's editable root.
- PositionTemplate<Strategy> start = range.StartPosition();
- if (start_root != base_root) {
- const VisiblePositionTemplate<Strategy> first =
- FirstEditableVisiblePositionAfterPositionInRoot(start, *base_root);
- start = first.DeepEquivalent();
- if (start.IsNull()) {
- NOTREACHED();
- return {};
- }
- }
- // If the end is outside the base's editable root, cap it at the end of
- // that root. If the end is in non-editable content that is inside the
- // base's root, put it at the last editable position before the end inside
- // the base's root.
- PositionTemplate<Strategy> end = range.EndPosition();
- if (end_root != base_root) {
- const VisiblePositionTemplate<Strategy> last =
- LastEditableVisiblePositionBeforePositionInRoot(end, *base_root);
- end = last.DeepEquivalent();
- if (end.IsNull())
- end = start;
- }
- return {start, end};
+ // |extent_rbe| is not in |base_rbe| subtree, in this case, the result
+ // should be the first/last position in the |base_rbe| subtree.
+ if (!Strategy::IsDescendantOf(extent_rbe, base_rbe)) {
+ if (selection.IsBaseFirst())
+ return PositionTemplate<Strategy>::LastPositionInNode(base_rbe);
+ return PositionTemplate<Strategy>::FirstPositionInNode(base_rbe);
}
- // The selection is based in non-editable content.
- // FIXME: Non-editable pieces inside editable content should be atomic, in
- // the same way that editable pieces in non-editable content are atomic.
- const PositionTemplate<Strategy>& end =
- AdjustSelectionEndToAvoidCrossingEditingBoundaries(
- range.EndPosition(), end_root, base_editable_ancestor);
- if (end.IsNull()) {
- // The selection crosses an Editing boundary. This is a
- // programmer error in the editing code. Happy debugging!
- NOTREACHED();
- return {};
+ // |extent_rbe| is in |base_rbe| subtree. We want to find the last boundary
+ // the selection crossed from extent. Which is the highest ancestor node of
+ // extent in |base_rbe| subtree that RBE(ancestor) != |base_rbe|.
+ const Node* boundary = &extent_rbe;
+ const Node* previous_ancestor = &extent_rbe;
+ bool previous_editable = HasEditableStyle(extent_rbe);
+ for (const Node& ancestor : Strategy::AncestorsOf(extent_rbe)) {
+ if (IsEditingBoundary<Strategy>(ancestor, *previous_ancestor,
+ previous_editable))
+ boundary = previous_ancestor;
+
+ if (ancestor == base_rbe || IsHTMLBodyElement(ancestor))
+ break;
+ previous_editable = HasEditableStyle(ancestor);
+ previous_ancestor = &ancestor;
}
- const PositionTemplate<Strategy>& start =
- AdjustSelectionStartToAvoidCrossingEditingBoundaries(
- range.StartPosition(), start_root, base_editable_ancestor);
- if (start.IsNull()) {
- // The selection crosses an Editing boundary. This is a
- // programmer error in the editing code. Happy debugging!
- NOTREACHED();
- return {};
- }
- return {start, end};
+ if (selection.IsBaseFirst())
+ return PositionTemplate<Strategy>::BeforeNode(*boundary);
+ return PositionTemplate<Strategy>::AfterNode(*boundary);
}
};
+template <>
+inline bool
+EditingBoundaryAdjuster::IsEditingBoundary<EditingInFlatTreeStrategy>(
+ const Node& node,
+ const Node& previous_node,
+ bool is_previous_node_editable) {
+ // We want to treat shadow host as not editable element if |previous_node|
+ // is in the shadow tree attached to the shadow host.
+ if (IsShadowHost(&node) && is_previous_node_editable &&
+ previous_node.OwnerShadowHost() == &node)
+ return true;
+ return HasEditableStyle(node) != is_previous_node_editable;
+}
+
SelectionInDOMTree
SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
const SelectionInDOMTree& selection) {
diff --git a/chromium/third_party/blink/renderer/core/editing/selection_adjuster_test.cc b/chromium/third_party/blink/renderer/core/editing/selection_adjuster_test.cc
index 6fe4e71d222..34765590077 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_adjuster_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/selection_adjuster_test.cc
@@ -12,6 +12,7 @@ namespace blink {
class SelectionAdjusterTest : public EditingTestBase {};
+// ------------ Shadow boundary adjustment tests --------------
TEST_F(SelectionAdjusterTest, AdjustShadowToCollpasedInDOMTree) {
const SelectionInDOMTree& selection = SetSelectionTextToBody(
"<span><template data-mode=\"open\">a|bc</template></span>^");
@@ -37,4 +38,483 @@ TEST_F(SelectionAdjusterTest, AdjustShadowToCollpasedInFlatTree) {
GetSelectionTextInFlatTreeFromBody(result));
}
+// ------------ Editing boundary adjustment tests --------------
+// Extracted the related part from delete-non-editable-range-crash.html here,
+// because the final result in that test was not WAI.
+TEST_F(SelectionAdjusterTest, DeleteNonEditableRange) {
+ const SelectionInDOMTree& selection = SetSelectionTextToBody(R"HTML(
+ <div contenteditable>
+ <blockquote>
+ <span>^foo<br></span>
+ barbarbar
+ </blockquote>
+ <span contenteditable="false">
+ <span contenteditable>|</span>
+ <ol>bar</ol>
+ </span>
+ </div>)HTML");
+
+ const SelectionInDOMTree& result =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ selection);
+
+ EXPECT_EQ(R"HTML(
+ <div contenteditable>
+ <blockquote>
+ <span>^foo<br></span>
+ barbarbar
+ </blockquote>
+ |<span contenteditable="false">
+ <span contenteditable></span>
+ <ol>bar</ol>
+ </span>
+ </div>)HTML",
+ GetSelectionTextFromBody(result));
+}
+
+// Extracted the related part from format-block-contenteditable-false.html here,
+// because the final result in that test was not WAI.
+TEST_F(SelectionAdjusterTest, FormatBlockContentEditableFalse) {
+ const SelectionInDOMTree& selection = SetSelectionTextToBody(R"HTML(
+ <div contenteditable>
+ <h1><i>^foo</i><br><i>baz</i></h1>
+ <div contenteditable="false">|bar</div>
+ </div>)HTML");
+
+ const SelectionInDOMTree& result =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ selection);
+
+ EXPECT_EQ(R"HTML(
+ <div contenteditable>
+ <h1><i>^foo</i><br><i>baz</i></h1>
+ |<div contenteditable="false">bar</div>
+ </div>)HTML",
+ GetSelectionTextFromBody(result));
+}
+
+TEST_F(SelectionAdjusterTest, NestedContentEditableElements) {
+ // Select from bar to foo.
+ const SelectionInDOMTree& selection = SetSelectionTextToBody(R"HTML(
+ <div contenteditable>
+ <div contenteditable="false">
+ <div contenteditable>
+ |foo
+ </div>
+ </div>
+ <br>
+ bar^
+ </div>)HTML");
+
+ const SelectionInDOMTree& result =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ selection);
+
+ EXPECT_EQ(R"HTML(
+ <div contenteditable>
+ <div contenteditable="false">
+ <div contenteditable>
+ foo
+ </div>
+ </div>|
+ <br>
+ bar^
+ </div>)HTML",
+ GetSelectionTextFromBody(result));
+}
+
+TEST_F(SelectionAdjusterTest, ShadowRootAsRootBoundaryElement) {
+ const char* body_content = "<div id='host'></div>";
+ const char* shadow_content = "<div id='foo'>foo</div><div id='bar'>bar</div>";
+ SetBodyContent(body_content);
+ ShadowRoot* shadow_root = SetShadowContent(shadow_content, "host");
+
+ Element* foo = shadow_root->QuerySelector("#foo");
+ Element* bar = shadow_root->QuerySelector("#bar");
+
+ // DOM tree selection.
+ const SelectionInDOMTree& selection =
+ SelectionInDOMTree::Builder()
+ .Collapse(Position::FirstPositionInNode(*foo))
+ .Extend(Position::LastPositionInNode(*bar))
+ .Build();
+ const SelectionInDOMTree& result =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ selection);
+
+ EXPECT_EQ(Position::FirstPositionInNode(*foo), result.Base());
+ EXPECT_EQ(Position::LastPositionInNode(*bar), result.Extent());
+
+ // Flat tree selection.
+ const SelectionInFlatTree& selection_in_flat_tree =
+ SelectionInFlatTree::Builder()
+ .Collapse(PositionInFlatTree::FirstPositionInNode(*foo))
+ .Extend(PositionInFlatTree::LastPositionInNode(*bar))
+ .Build();
+ const SelectionInFlatTree& result_in_flat_tree =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ selection_in_flat_tree);
+
+ EXPECT_EQ(PositionInFlatTree::FirstPositionInNode(*foo),
+ result_in_flat_tree.Base());
+ EXPECT_EQ(PositionInFlatTree::LastPositionInNode(*bar),
+ result_in_flat_tree.Extent());
+}
+
+TEST_F(SelectionAdjusterTest, ShadowRootAsRootBoundaryElementEditable) {
+ const char* body_content = "<div id='host'></div>";
+ const char* shadow_content =
+ "foo"
+ "<div id='bar' contenteditable>bar</div>";
+ SetBodyContent(body_content);
+ ShadowRoot* shadow_root = SetShadowContent(shadow_content, "host");
+
+ const Node* foo = shadow_root->firstChild();
+ const Element* bar = shadow_root->QuerySelector("#bar");
+
+ // Select from foo to bar in DOM tree.
+ const SelectionInDOMTree& selection =
+ SelectionInDOMTree::Builder()
+ .Collapse(Position::FirstPositionInNode(*foo))
+ .Extend(Position::LastPositionInNode(*bar))
+ .Build();
+ const SelectionInDOMTree& result =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ selection);
+
+ EXPECT_EQ(Position::FirstPositionInNode(*foo), result.Base());
+ EXPECT_EQ(Position::BeforeNode(*bar), result.Extent());
+
+ // Select from foo to bar in flat tree.
+ const SelectionInFlatTree& selection_in_flat_tree =
+ SelectionInFlatTree::Builder()
+ .Collapse(PositionInFlatTree::FirstPositionInNode(*foo))
+ .Extend(PositionInFlatTree::LastPositionInNode(*bar))
+ .Build();
+ const SelectionInFlatTree& result_in_flat_tree =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ selection_in_flat_tree);
+
+ EXPECT_EQ(PositionInFlatTree::FirstPositionInNode(*foo),
+ result_in_flat_tree.Base());
+ EXPECT_EQ(PositionInFlatTree::BeforeNode(*bar), result_in_flat_tree.Extent());
+
+ // Select from bar to foo in DOM tree.
+ const SelectionInDOMTree& selection2 =
+ SelectionInDOMTree::Builder()
+ .Collapse(Position::LastPositionInNode(*bar))
+ .Extend(Position::FirstPositionInNode(*foo))
+ .Build();
+ const SelectionInDOMTree& result2 =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ selection2);
+
+ EXPECT_EQ(Position::LastPositionInNode(*bar), result2.Base());
+ EXPECT_EQ(Position::FirstPositionInNode(*bar), result2.Extent());
+
+ // Select from bar to foo in flat tree.
+ const SelectionInFlatTree& selection_in_flat_tree2 =
+ SelectionInFlatTree::Builder()
+ .Collapse(PositionInFlatTree::LastPositionInNode(*bar))
+ .Extend(PositionInFlatTree::FirstPositionInNode(*foo))
+ .Build();
+ const SelectionInFlatTree& result_in_flat_tree2 =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ selection_in_flat_tree2);
+
+ EXPECT_EQ(PositionInFlatTree::LastPositionInNode(*bar),
+ result_in_flat_tree2.Base());
+ EXPECT_EQ(PositionInFlatTree::FirstPositionInNode(*bar),
+ result_in_flat_tree2.Extent());
+}
+
+TEST_F(SelectionAdjusterTest, ShadowDistributedNodesWithoutEditingBoundary) {
+ const char* body_content = R"HTML(
+ <div id=host>
+ <div id=foo slot=foo>foo</div>
+ <div id=bar slot=bar>bar</div>
+ </div>)HTML";
+ const char* shadow_content = R"HTML(
+ <div>
+ <div id=s1>111</div>
+ <slot name=foo></slot>
+ <div id=s2>222</div>
+ <slot name=bar></slot>
+ <div id=s3>333</div>
+ </div>)HTML";
+ SetBodyContent(body_content);
+ Element* host = GetDocument().getElementById("host");
+ ShadowRoot& shadow_root =
+ host->AttachShadowRootInternal(ShadowRootType::kOpen);
+ shadow_root.SetInnerHTMLFromString(shadow_content);
+
+ Element* foo = GetDocument().getElementById("foo");
+ Element* s1 = shadow_root.QuerySelector("#s1");
+
+ // Select from 111 to foo.
+ const SelectionInFlatTree& selection =
+ SelectionInFlatTree::Builder()
+ .Collapse(PositionInFlatTree::FirstPositionInNode(*s1))
+ .Extend(PositionInFlatTree::LastPositionInNode(*foo))
+ .Build();
+ const SelectionInFlatTree& result =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ selection);
+ EXPECT_EQ(R"HTML(
+ <div id="host">
+ <div>
+ <div id="s1">^111</div>
+ <slot name="foo"><div id="foo" slot="foo">foo|</div></slot>
+ <div id="s2">222</div>
+ <slot name="bar"><div id="bar" slot="bar">bar</div></slot>
+ <div id="s3">333</div>
+ </div></div>)HTML",
+ GetSelectionTextInFlatTreeFromBody(result));
+
+ // Select from foo to 111.
+ const SelectionInFlatTree& selection2 =
+ SelectionInFlatTree::Builder()
+ .Collapse(PositionInFlatTree::LastPositionInNode(*foo))
+ .Extend(PositionInFlatTree::FirstPositionInNode(*s1))
+ .Build();
+ const SelectionInFlatTree& result2 =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ selection2);
+ EXPECT_EQ(R"HTML(
+ <div id="host">
+ <div>
+ <div id="s1">|111</div>
+ <slot name="foo"><div id="foo" slot="foo">foo^</div></slot>
+ <div id="s2">222</div>
+ <slot name="bar"><div id="bar" slot="bar">bar</div></slot>
+ <div id="s3">333</div>
+ </div></div>)HTML",
+ GetSelectionTextInFlatTreeFromBody(result2));
+}
+
+// This test is just recording the behavior of current implementation, can be
+// changed.
+TEST_F(SelectionAdjusterTest, ShadowDistributedNodesWithEditingBoundary) {
+ const char* body_content = R"HTML(
+ <div contenteditable id=host>
+ <div id=foo slot=foo>foo</div>
+ <div id=bar slot=bar>bar</div>
+ </div>)HTML";
+ const char* shadow_content = R"HTML(
+ <div>
+ <div id=s1>111</div>
+ <slot name=foo></slot>
+ <div id=s2>222</div>
+ <slot name=bar></slot>
+ <div id=s3>333</div>
+ </div>)HTML";
+ SetBodyContent(body_content);
+ Element* host = GetDocument().getElementById("host");
+ ShadowRoot& shadow_root =
+ host->AttachShadowRootInternal(ShadowRootType::kOpen);
+ shadow_root.SetInnerHTMLFromString(shadow_content);
+
+ Element* foo = GetDocument().getElementById("foo");
+ Element* bar = GetDocument().getElementById("bar");
+ Element* s1 = shadow_root.QuerySelector("#s1");
+ Element* s2 = shadow_root.QuerySelector("#s2");
+
+ // Select from 111 to foo.
+ const SelectionInFlatTree& selection =
+ SelectionInFlatTree::Builder()
+ .Collapse(PositionInFlatTree::FirstPositionInNode(*s1))
+ .Extend(PositionInFlatTree::LastPositionInNode(*foo))
+ .Build();
+ const SelectionInFlatTree& result =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ selection);
+ EXPECT_EQ(R"HTML(
+ <div contenteditable id="host">
+ <div>
+ <div id="s1">^111</div>
+ <slot name="foo">|<div id="foo" slot="foo">foo</div></slot>
+ <div id="s2">222</div>
+ <slot name="bar"><div id="bar" slot="bar">bar</div></slot>
+ <div id="s3">333</div>
+ </div></div>)HTML",
+ GetSelectionTextInFlatTreeFromBody(result));
+
+ // Select from foo to 111.
+ const SelectionInFlatTree& selection2 =
+ SelectionInFlatTree::Builder()
+ .Collapse(PositionInFlatTree::LastPositionInNode(*foo))
+ .Extend(PositionInFlatTree::FirstPositionInNode(*s1))
+ .Build();
+ const SelectionInFlatTree& result2 =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ selection2);
+ EXPECT_EQ(R"HTML(
+ <div contenteditable id="host">
+ <div>
+ <div id="s1">111</div>
+ <slot name="foo"><div id="foo" slot="foo">|foo^</div></slot>
+ <div id="s2">222</div>
+ <slot name="bar"><div id="bar" slot="bar">bar</div></slot>
+ <div id="s3">333</div>
+ </div></div>)HTML",
+ GetSelectionTextInFlatTreeFromBody(result2));
+
+ // Select from 111 to 222.
+ const SelectionInFlatTree& selection3 =
+ SelectionInFlatTree::Builder()
+ .Collapse(PositionInFlatTree::FirstPositionInNode(*s1))
+ .Extend(PositionInFlatTree::LastPositionInNode(*s2))
+ .Build();
+ const SelectionInFlatTree& result3 =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ selection3);
+ EXPECT_EQ(R"HTML(
+ <div contenteditable id="host">
+ <div>
+ <div id="s1">^111</div>
+ <slot name="foo"><div id="foo" slot="foo">foo</div></slot>
+ <div id="s2">222|</div>
+ <slot name="bar"><div id="bar" slot="bar">bar</div></slot>
+ <div id="s3">333</div>
+ </div></div>)HTML",
+ GetSelectionTextInFlatTreeFromBody(result3));
+
+ // Select from foo to bar.
+ const SelectionInFlatTree& selection4 =
+ SelectionInFlatTree::Builder()
+ .Collapse(PositionInFlatTree::FirstPositionInNode(*foo))
+ .Extend(PositionInFlatTree::LastPositionInNode(*bar))
+ .Build();
+ const SelectionInFlatTree& result4 =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ selection4);
+ EXPECT_EQ(R"HTML(
+ <div contenteditable id="host">
+ <div>
+ <div id="s1">111</div>
+ <slot name="foo"><div id="foo" slot="foo">^foo|</div></slot>
+ <div id="s2">222</div>
+ <slot name="bar"><div id="bar" slot="bar">bar</div></slot>
+ <div id="s3">333</div>
+ </div></div>)HTML",
+ GetSelectionTextInFlatTreeFromBody(result4));
+}
+
+TEST_F(SelectionAdjusterTest, EditingBoundaryOutsideOfShadowTree) {
+ SetBodyContent(R"HTML(
+ <div>
+ <div id=base>base</div>
+ <div id=div1 contenteditable>
+ 55
+ <div id=host></div>
+ </div>
+ </div>)HTML");
+ ShadowRoot* shadow_root =
+ SetShadowContent("<div id=extent>extent</div>", "host");
+ Element* base = GetDocument().getElementById("base");
+ Element* extent = shadow_root->QuerySelector("#extent");
+
+ const SelectionInFlatTree& selection =
+ SelectionInFlatTree::Builder()
+ .Collapse(PositionInFlatTree::FirstPositionInNode(*base))
+ .Extend(PositionInFlatTree::LastPositionInNode(*extent))
+ .Build();
+ const SelectionInFlatTree& result =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ selection);
+ EXPECT_EQ(R"HTML(
+ <div>
+ <div id="base">^base</div>
+ |<div contenteditable id="div1">
+ 55
+ <div id="host"><div id="extent">extent</div></div>
+ </div>
+ </div>)HTML",
+ GetSelectionTextInFlatTreeFromBody(result));
+}
+
+TEST_F(SelectionAdjusterTest, EditingBoundaryInsideOfShadowTree) {
+ SetBodyContent(R"HTML(
+ <div>
+ <div id=base>base</div>
+ <div id=host>foo</div>
+ </div>)HTML");
+ ShadowRoot* shadow_root = SetShadowContent(R"HTML(
+ <div>
+ <div>bar</div>
+ <div contenteditable id=extent>extent</div>
+ <div>baz</div>
+ </div>)HTML",
+ "host");
+
+ Element* base = GetDocument().getElementById("base");
+ Element* extent = shadow_root->QuerySelector("#extent");
+
+ const SelectionInFlatTree& selection =
+ SelectionInFlatTree::Builder()
+ .Collapse(PositionInFlatTree::FirstPositionInNode(*base))
+ .Extend(PositionInFlatTree::LastPositionInNode(*extent))
+ .Build();
+ const SelectionInFlatTree& result =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ selection);
+ EXPECT_EQ(R"HTML(
+ <div>
+ <div id="base">^base</div>
+ <div id="host">
+ <div>
+ <div>bar</div>
+ |<div contenteditable id="extent">extent</div>
+ <div>baz</div>
+ </div></div>
+ </div>)HTML",
+ GetSelectionTextInFlatTreeFromBody(result));
+}
+
+// The current behavior of shadow host and shadow tree are editable is we can't
+// cross the shadow boundary.
+TEST_F(SelectionAdjusterTest, ShadowHostAndShadowTreeAreEditable) {
+ SetBodyContent(R"HTML(
+ <div contenteditable>
+ <div id=foo>foo</div>
+ <div id=host></div>
+ </div>)HTML");
+ ShadowRoot* shadow_root =
+ SetShadowContent("<div contenteditable id=bar>bar</div>", "host");
+
+ Element* foo = GetDocument().getElementById("foo");
+ Element* bar = shadow_root->QuerySelector("#bar");
+
+ // Select from foo to bar.
+ const SelectionInFlatTree& selection =
+ SelectionInFlatTree::Builder()
+ .Collapse(PositionInFlatTree::FirstPositionInNode(*foo))
+ .Extend(PositionInFlatTree::LastPositionInNode(*bar))
+ .Build();
+ const SelectionInFlatTree& result =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ selection);
+ EXPECT_EQ(R"HTML(
+ <div contenteditable>
+ <div id="foo">^foo</div>
+ <div id="host">|<div contenteditable id="bar">bar</div></div>
+ </div>)HTML",
+ GetSelectionTextInFlatTreeFromBody(result));
+
+ // Select from bar to foo.
+ const SelectionInFlatTree& selection2 =
+ SelectionInFlatTree::Builder()
+ .Collapse(PositionInFlatTree::LastPositionInNode(*bar))
+ .Extend(PositionInFlatTree::FirstPositionInNode(*foo))
+ .Build();
+ const SelectionInFlatTree& result2 =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ selection2);
+ EXPECT_EQ(R"HTML(
+ <div contenteditable>
+ <div id="foo">foo</div>
+ <div id="host"><div contenteditable id="bar">|bar^</div></div>
+ </div>)HTML",
+ GetSelectionTextInFlatTreeFromBody(result2));
+}
} // namespace blink
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 644e69c72bb..11e667a0c21 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_controller.cc
+++ b/chromium/third_party/blink/renderer/core/editing/selection_controller.cc
@@ -31,7 +31,6 @@
#include "base/auto_reset.h"
#include "third_party/blink/public/platform/web_menu_source_type.h"
-#include "third_party/blink/public/web/web_selection.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/editing/editing_boundary.h"
@@ -323,7 +322,7 @@ bool SelectionController::HandleSingleClick(
// Don't restart the selection when the mouse is pressed on an
// existing selection so we can allow for text dragging.
if (LocalFrameView* view = frame_->View()) {
- const LayoutPoint v_point = view->RootFrameToContents(
+ const LayoutPoint v_point = view->ConvertFromRootFrame(
FlooredIntPoint(event.Event().PositionInRootFrame()));
if (!extend_selection && this->Selection().Contains(v_point)) {
mouse_down_was_single_click_in_selection_ = true;
@@ -993,8 +992,9 @@ void SelectionController::HandleMouseDraggedEvent(
return;
if (selection_state_ != SelectionState::kExtendedSelection) {
HitTestRequest request(HitTestRequest::kReadOnly | HitTestRequest::kActive);
- HitTestResult result(request, mouse_down_pos);
- frame_->GetDocument()->GetLayoutView()->HitTest(result);
+ HitTestLocation location(mouse_down_pos);
+ HitTestResult result(request, location);
+ frame_->GetDocument()->GetLayoutView()->HitTest(location, result);
UpdateSelectionForMouseDrag(result, drag_start_pos,
last_known_mouse_position);
@@ -1015,9 +1015,9 @@ void SelectionController::UpdateSelectionForMouseDrag(
HitTestRequest request(HitTestRequest::kReadOnly | HitTestRequest::kActive |
HitTestRequest::kMove);
- HitTestResult result(request,
- view->ViewportToContents(last_known_mouse_position));
- layout_view->HitTest(result);
+ HitTestLocation location(view->ViewportToFrame(last_known_mouse_position));
+ HitTestResult result(request, location);
+ layout_view->HitTest(location, result);
UpdateSelectionForMouseDrag(result, drag_start_pos,
last_known_mouse_position);
}
@@ -1207,7 +1207,7 @@ void SelectionController::PassMousePressEventToSubframe(
// greyed out even though we're clicking on the selection. This looks
// really strange (having the whole frame be greyed out), so we deselect the
// selection.
- IntPoint p = frame_->View()->RootFrameToContents(
+ IntPoint p = frame_->View()->ConvertFromRootFrame(
FlooredIntPoint(mev.Event().PositionInRootFrame()));
if (!Selection().Contains(p))
return;
@@ -1281,8 +1281,4 @@ bool IsExtendingSelection(const MouseEventWithHitTestResults& event) {
!is_mouse_down_on_link_or_image;
}
-STATIC_ASSERT_ENUM(WebSelection::kNoSelection, kNoSelection);
-STATIC_ASSERT_ENUM(WebSelection::kCaretSelection, kCaretSelection);
-STATIC_ASSERT_ENUM(WebSelection::kRangeSelection, kRangeSelection);
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/selection_controller.h b/chromium/third_party/blink/renderer/core/editing/selection_controller.h
index 4919e87f626..e16e00701ee 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_controller.h
+++ b/chromium/third_party/blink/renderer/core/editing/selection_controller.h
@@ -29,6 +29,7 @@
#include "base/macros.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/dom/document_shutdown_observer.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
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 f8d843f9030..f07c5c78899 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
@@ -117,8 +117,9 @@ TEST_F(SelectionControllerTest, setCaretAtHitTestResult) {
" event => elem.parentNode.removeChild(elem));");
GetDocument().body()->AppendChild(script);
GetDocument().View()->UpdateAllLifecyclePhases();
+ HitTestLocation location((IntPoint(8, 8)));
GetFrame().GetEventHandler().GetSelectionController().HandleGestureLongPress(
- GetFrame().GetEventHandler().HitTestResultAtPoint(IntPoint(8, 8)));
+ GetFrame().GetEventHandler().HitTestResultAtLocation(location));
}
// For http://crbug.com/704827
@@ -132,8 +133,9 @@ TEST_F(SelectionControllerTest, setCaretAtHitTestResultWithNullPosition) {
GetDocument().View()->UpdateAllLifecyclePhases();
// Hit "&nbsp;" in before pseudo element of "sample".
+ HitTestLocation location((IntPoint(10, 10)));
SetCaretAtHitTestResult(
- GetFrame().GetEventHandler().HitTestResultAtPoint(IntPoint(10, 10)));
+ GetFrame().GetEventHandler().HitTestResultAtLocation(location));
EXPECT_TRUE(Selection().GetSelectionInDOMTree().IsNone());
}
@@ -166,10 +168,11 @@ TEST_F(SelectionControllerTest,
blink::WebInputEvent::GetStaticTimeStampForTests());
// Frame scale defaults to 0, which would cause a divide-by-zero problem.
mouse_event.SetFrameScale(1);
+ HitTestLocation location((IntPoint(0, 0)));
GetFrame().GetEventHandler().GetSelectionController().HandleMousePressEvent(
MouseEventWithHitTestResults(
- mouse_event,
- GetFrame().GetEventHandler().HitTestResultAtPoint(IntPoint(0, 0))));
+ mouse_event, location,
+ GetFrame().GetEventHandler().HitTestResultAtLocation(location)));
// The original bug was that this test would cause
// TextSuggestionController::HandlePotentialMisspelledWordTap() to crash. So
diff --git a/chromium/third_party/blink/renderer/core/editing/selection_modifier_character_test.cc b/chromium/third_party/blink/renderer/core/editing/selection_modifier_character_test.cc
index bba82509b1f..935e31ea05d 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_modifier_character_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/selection_modifier_character_test.cc
@@ -22,4 +22,17 @@ TEST_F(SelectionModifierCharacterTest, MoveLeftTowardsListMarkerNoCrash) {
GetSelectionTextFromBody(modifier.Selection().AsSelection()));
}
+// Regression test for crbug.com/861559
+TEST_F(SelectionModifierCharacterTest, MoveRightInDirAutoBidiTextNoCrash) {
+ const SelectionInDOMTree selection = SetSelectionTextToBody(
+ u8"<pre contenteditable dir=\"auto\">\u05D0$|A$\u05D0</pre>");
+ SelectionModifier modifier(GetFrame(), selection);
+ modifier.Modify(SelectionModifyAlteration::kMove,
+ SelectionModifyDirection::kRight,
+ TextGranularity::kCharacter);
+ // Shouldn't crash here.
+ EXPECT_EQ(u8"<pre contenteditable dir=\"auto\">\u05D0|$A$\u05D0</pre>",
+ GetSelectionTextFromBody(modifier.Selection().AsSelection()));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/selection_modifier_word_test.cc b/chromium/third_party/blink/renderer/core/editing/selection_modifier_word_test.cc
new file mode 100644
index 00000000000..6f518116657
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/editing/selection_modifier_word_test.cc
@@ -0,0 +1,32 @@
+// 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/editing/selection_modifier.h"
+
+#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
+
+namespace blink {
+
+class SelectionModifierWordTest : public EditingTestBase {};
+
+// Regression test for crbug.com/856417
+TEST_F(SelectionModifierWordTest, MoveIntoInlineBlockWithBidiNoHang) {
+ const SelectionInDOMTree selection = SetSelectionTextToBody(
+ "<div contenteditable>"
+ "<span>&#x05D0;|&#x05D1;&#x05D2;</span>"
+ "<span style=\"display: inline-block\">foo</span>"
+ "</div>");
+ SelectionModifier modifier(GetFrame(), selection);
+ modifier.Modify(SelectionModifyAlteration::kMove,
+ SelectionModifyDirection::kRight, TextGranularity::kWord);
+ // Shouldn't hang here.
+ EXPECT_EQ(
+ "<div contenteditable>"
+ "<span>\xD7\x90\xD7\x91\xD7\x92</span>"
+ "<span style=\"display: inline-block\">foo|</span>"
+ "</div>",
+ GetSelectionTextFromBody(modifier.Selection().AsSelection()));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/selection_template.h b/chromium/third_party/blink/renderer/core/editing/selection_template.h
index 732728d4b2c..1c126e94b57 100644
--- a/chromium/third_party/blink/renderer/core/editing/selection_template.h
+++ b/chromium/third_party/blink/renderer/core/editing/selection_template.h
@@ -23,7 +23,7 @@ namespace blink {
//
// To construct |SelectionTemplate| object, please use |Builder| class.
template <typename Strategy>
-class CORE_EXPORT SelectionTemplate final {
+class SelectionTemplate final {
DISALLOW_NEW();
public:
diff --git a/chromium/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc b/chromium/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc
index b57be31f4ae..536ffd21a6b 100644
--- a/chromium/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc
+++ b/chromium/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc
@@ -390,7 +390,7 @@ void MarkupFormatter::AppendAttribute(StringBuilder& result,
// This behavior is in process of being standardized. See
// crbug.com/248044 and
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=24208
- String prefix_prefix("ns", 2);
+ String prefix_prefix("ns", 2u);
for (unsigned i = attribute.NamespaceURI().Impl()->ExistingHash();;
++i) {
AtomicString new_prefix(String(prefix_prefix + String::Number(i)));
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 c6d2d4d5251..4aacc70ee44 100644
--- a/chromium/third_party/blink/renderer/core/editing/serializers/serialization.cc
+++ b/chromium/third_party/blink/renderer/core/editing/serializers/serialization.cc
@@ -29,7 +29,6 @@
#include "third_party/blink/renderer/core/editing/serializers/serialization.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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_value.h"
@@ -39,8 +38,8 @@
#include "third_party/blink/renderer/core/dom/comment.h"
#include "third_party/blink/renderer/core/dom/context_features.h"
#include "third_party/blink/renderer/core/dom/document_fragment.h"
+#include "third_party/blink/renderer/core/dom/document_init.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/dom/range.h"
#include "third_party/blink/renderer/core/editing/editing_strategy.h"
@@ -63,6 +62,7 @@
#include "third_party/blink/renderer/core/html/html_table_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/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -616,7 +616,7 @@ DocumentFragment* CreateFragmentForInnerOuterHTML(
fragment->ParseXML(markup, context_element, parser_content_policy);
if (!was_valid) {
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"The provided markup is invalid XML, and "
"therefore cannot be inserted into an XML "
"document.");
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 f7c90688fd3..a3dc6a7562e 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
@@ -13,6 +13,7 @@
#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/core/editing/spellcheck/spell_check_requester.h"
#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_frame.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -35,7 +36,7 @@ ColdModeSpellCheckRequester* ColdModeSpellCheckRequester::Create(
void ColdModeSpellCheckRequester::Trace(blink::Visitor* visitor) {
visitor->Trace(frame_);
visitor->Trace(root_editable_);
- visitor->Trace(last_chunk_end_);
+ visitor->Trace(remaining_check_range_);
}
ColdModeSpellCheckRequester::ColdModeSpellCheckRequester(LocalFrame& frame)
@@ -48,8 +49,13 @@ bool ColdModeSpellCheckRequester::FullyChecked() const {
needs_more_invocation_for_testing_ = false;
return false;
}
- return !root_editable_ ||
- last_chunk_end_ == Position::LastPositionInNode(*root_editable_);
+ // Note that DOM mutations between cold mode invocations may corrupt the
+ // stored states, in which case we also consider checking as finished.
+ return !root_editable_ || !remaining_check_range_ ||
+ remaining_check_range_->collapsed() ||
+ !remaining_check_range_->IsConnected() ||
+ !root_editable_->contains(
+ remaining_check_range_->commonAncestorContainer());
}
SpellCheckRequester& ColdModeSpellCheckRequester::GetSpellCheckRequester()
@@ -88,43 +94,77 @@ void ColdModeSpellCheckRequester::Invoke(IdleDeadline* deadline) {
}
if (root_editable_ != current_focused) {
+ ClearProgress();
root_editable_ = current_focused;
last_chunk_index_ = 0;
- last_chunk_end_ = Position::FirstPositionInNode(*root_editable_);
+ remaining_check_range_ = Range::Create(root_editable_->GetDocument());
+ remaining_check_range_->selectNodeContents(
+ const_cast<Element*>(root_editable_.Get()), ASSERT_NO_EXCEPTION);
}
- while (!FullyChecked() && deadline->timeRemaining() > 0)
+ while (deadline->timeRemaining() > 0) {
+ if (FullyChecked()) {
+ SetHasFullyChecked();
+ return;
+ }
RequestCheckingForNextChunk();
+ }
}
void ColdModeSpellCheckRequester::ClearProgress() {
root_editable_ = nullptr;
last_chunk_index_ = kInvalidChunkIndex;
- last_chunk_end_ = Position();
+ if (!remaining_check_range_)
+ return;
+ remaining_check_range_->Dispose();
+ remaining_check_range_ = nullptr;
+}
+
+void ColdModeSpellCheckRequester::SetHasFullyChecked() {
+ DCHECK(root_editable_);
+ last_chunk_index_ = kInvalidChunkIndex;
+ if (!remaining_check_range_)
+ return;
+ remaining_check_range_->Dispose();
+ remaining_check_range_ = nullptr;
}
void ColdModeSpellCheckRequester::RequestCheckingForNextChunk() {
DCHECK(root_editable_);
+ DCHECK(!FullyChecked());
+
+ const EphemeralRange remaining_range(remaining_check_range_);
+ const int remaining_length = TextIterator::RangeLength(
+ remaining_range,
+ // Same behavior used in |CalculateCharacterSubrange()|
+ TextIteratorBehavior::EmitsObjectReplacementCharacterBehavior());
+ if (remaining_length == 0) {
+ SetHasFullyChecked();
+ return;
+ }
- const int chunk_index = last_chunk_index_;
- const Position chunk_start = last_chunk_end_;
+ const int chunk_index = last_chunk_index_ + 1;
+ const Position chunk_start = remaining_range.StartPosition();
const Position chunk_end =
- CalculateCharacterSubrange(
- EphemeralRange(chunk_start,
- Position::LastPositionInNode(*root_editable_)),
- 0, kColdModeChunkSize)
+ CalculateCharacterSubrange(remaining_range, 0,
+ std::min(remaining_length, kColdModeChunkSize))
.EndPosition();
- const EphemeralRange chunk_range(chunk_start, chunk_end);
- const EphemeralRange check_range = ExpandEndToSentenceBoundary(chunk_range);
- if (!GetSpellCheckRequester().RequestCheckingFor(check_range, chunk_index)) {
- // Fully checked.
- last_chunk_end_ = Position::LastPositionInNode(*root_editable_);
- return;
- }
+ // Chromium spellchecker requires complete sentences to be checked. However,
+ // EndOfSentence() sometimes returns null or out-of-editable positions, which
+ // are corrected here.
+ const Position extended_end =
+ EndOfSentence(CreateVisiblePosition(chunk_end)).DeepEquivalent();
+ const Position check_end =
+ extended_end.IsNull() || extended_end < chunk_end
+ ? chunk_end
+ : std::min(extended_end, remaining_range.EndPosition());
+ const EphemeralRange check_range(chunk_start, check_end);
+
+ GetSpellCheckRequester().RequestCheckingFor(check_range, chunk_index);
last_chunk_index_ = chunk_index;
- last_chunk_end_ = check_range.EndPosition();
+ remaining_check_range_->setStart(check_range.EndPosition());
}
} // namespace blink
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 ebcbefa9634..051d047b775 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
@@ -45,18 +45,20 @@ class ColdModeSpellCheckRequester
const Element* CurrentFocusedEditable() const;
void RequestCheckingForNextChunk();
+ void SetHasFullyChecked();
// The LocalFrame this cold mode checker belongs to.
const Member<LocalFrame> frame_;
// The root editable element checked in the last invocation. |nullptr| if not
- // invoked yet or nothing was checked in the last invocation.
+ // invoked yet or didn't find any root editable element to check.
Member<const Element> root_editable_;
- // If the last invocation checked a chunk of text, the id and ending position
- // of the chunk; Otherwise, |kInvalidChunkIndex| and null.
+ // If |root_editable_| is non-null and hasn't been fully checked, the id of
+ // the last checked chunk and the remaining range to check;
+ // Otherwise, |kInvalidChunkIndex| and null.
int last_chunk_index_;
- Position last_chunk_end_;
+ Member<Range> remaining_check_range_;
// A test-only flag for forcing lifecycle advancing.
mutable bool needs_more_invocation_for_testing_;
diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_callback.cc b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_callback.cc
index 84fdc046bcb..d76ebfa4daa 100644
--- a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_callback.cc
+++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_callback.cc
@@ -29,12 +29,13 @@ namespace blink {
namespace {
-const int kColdModeTimerIntervalMS = 1000;
-const int kConsecutiveColdModeTimerIntervalMS = 200;
+constexpr TimeDelta kColdModeTimerInterval = TimeDelta::FromMilliseconds(1000);
+constexpr TimeDelta kConsecutiveColdModeTimerInterval =
+ TimeDelta::FromMilliseconds(200);
const int kHotModeRequestTimeoutMS = 200;
const int kInvalidHandle = -1;
const int kDummyHandleForForcedInvocation = -2;
-const double kForcedInvocationDeadlineSeconds = 10;
+constexpr TimeDelta kForcedInvocationDeadline = TimeDelta::FromSeconds(10);
} // namespace
@@ -73,6 +74,7 @@ void IdleSpellCheckCallback::Deactivate() {
state_ = State::kInactive;
if (cold_mode_timer_.IsActive())
cold_mode_timer_.Stop();
+ cold_mode_requester_->ClearProgress();
if (idle_callback_handle_ != kInvalidHandle && IsAvailable())
GetDocument().CancelIdleCallback(idle_callback_handle_);
idle_callback_handle_ = kInvalidHandle;
@@ -117,10 +119,10 @@ void IdleSpellCheckCallback::SetNeedsColdModeInvocation() {
return;
DCHECK(!cold_mode_timer_.IsActive());
- int interval_ms = state_ == State::kInColdModeInvocation
- ? kConsecutiveColdModeTimerIntervalMS
- : kColdModeTimerIntervalMS;
- cold_mode_timer_.StartOneShot(interval_ms / 1000.0, FROM_HERE);
+ TimeDelta interval = state_ == State::kInColdModeInvocation
+ ? kConsecutiveColdModeTimerInterval
+ : kColdModeTimerInterval;
+ cold_mode_timer_.StartOneShot(interval, FROM_HERE);
state_ = State::kColdModeTimerStarted;
}
@@ -205,9 +207,9 @@ void IdleSpellCheckCallback::ForceInvocationForTesting() {
if (!IsSpellCheckingEnabled())
return;
- IdleDeadline* deadline = IdleDeadline::Create(
- kForcedInvocationDeadlineSeconds + CurrentTimeTicksInSeconds(),
- IdleDeadline::CallbackType::kCalledWhenIdle);
+ IdleDeadline* deadline =
+ IdleDeadline::Create(CurrentTimeTicks() + kForcedInvocationDeadline,
+ IdleDeadline::CallbackType::kCalledWhenIdle);
switch (state_) {
case State::kColdModeTimerStarted:
diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_callback.h b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_callback.h
index 96b6440d49f..31237edd418 100644
--- a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_callback.h
+++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_callback.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SPELLCHECK_IDLE_SPELL_CHECK_CALLBACK_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_SPELLCHECK_IDLE_SPELL_CHECK_CALLBACK_H_
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_shutdown_observer.h"
#include "third_party/blink/renderer/core/dom/scripted_idle_task_controller.h"
#include "third_party/blink/renderer/core/editing/forward.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_callback_test.cc b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_callback_test.cc
index 4f46e6432ea..74179ea4f8a 100644
--- a/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_callback_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_callback_test.cc
@@ -4,10 +4,13 @@
#include "third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_callback.h"
+#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/editing/spellcheck/spell_check_test_base.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/html/html_object_element.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
namespace blink {
@@ -181,4 +184,28 @@ TEST_F(IdleSpellCheckCallbackTest, DetachWhenColdModeRequested) {
EXPECT_EQ(State::kInactive, IdleChecker().GetState());
}
+// crbug.com/863784
+TEST_F(IdleSpellCheckCallbackTest, ColdModeRangeCrossesShadow) {
+ ScopedIdleTimeColdModeSpellCheckingForTest cold_mode_scope(true);
+ SetBodyContent(
+ "<div contenteditable style=\"width:800px\">"
+ "foo"
+ "<menu style=\"all: initial\">1127</menu>"
+ "<object><optgroup></optgroup></object>"
+ "</div>");
+ ToHTMLObjectElement(GetDocument().QuerySelector("object"))
+ ->RenderFallbackContent();
+ GetDocument().QuerySelector("div")->focus();
+ UpdateAllLifecyclePhases();
+
+ // Advance to cold mode invocation
+ IdleChecker().ForceInvocationForTesting();
+ IdleChecker().SkipColdModeTimerForTesting();
+ ASSERT_EQ(State::kColdModeRequested, IdleChecker().GetState());
+
+ // Shouldn't crash
+ IdleChecker().ForceInvocationForTesting();
+ EXPECT_EQ(State::kInactive, IdleChecker().GetState());
+}
+
} // namespace blink
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 9b184252859..706f274d258 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
@@ -88,7 +88,6 @@ SpellCheckRequest::SpellCheckRequest(Range* checking_range,
request_number_(request_number) {
DCHECK(checking_range_);
DCHECK(checking_range_->IsConnected());
- DCHECK(root_editable_element_);
}
SpellCheckRequest::~SpellCheckRequest() = default;
@@ -123,7 +122,15 @@ SpellCheckRequest* SpellCheckRequest::Create(
Range* checking_range_object = CreateRange(checking_range);
- return new SpellCheckRequest(checking_range_object, text, request_number);
+ SpellCheckRequest* request =
+ new SpellCheckRequest(checking_range_object, text, request_number);
+ if (request->RootEditableElement())
+ return request;
+
+ // We may reach here if |checking_range| crosses shadow boundary, in which
+ // case we don't want spellchecker to crash renderer.
+ request->Dispose();
+ return nullptr;
}
bool SpellCheckRequest::IsValid() const {
@@ -159,7 +166,6 @@ SpellCheckRequester::SpellCheckRequester(LocalFrame& frame)
: frame_(&frame),
last_request_sequence_(0),
last_processed_sequence_(0),
- last_request_time_(0.0),
timer_to_process_queued_request_(
frame.GetTaskRunner(TaskType::kInternalDefault),
this,
@@ -189,14 +195,10 @@ bool SpellCheckRequester::RequestCheckingFor(const EphemeralRange& range,
if (!request)
return false;
- DEFINE_STATIC_LOCAL(CustomCountHistogram,
- spell_checker_request_interval_histogram,
- ("WebCore.SpellChecker.RequestInterval", 0, 10000, 50));
- const double current_request_time = CurrentTimeTicksInSeconds();
- if (request_num == 0 && last_request_time_ > 0) {
- const double interval_ms =
- (current_request_time - last_request_time_) * 1000.0;
- spell_checker_request_interval_histogram.Count(interval_ms);
+ const TimeTicks current_request_time = CurrentTimeTicks();
+ if (request_num == 0 && last_request_time_ > TimeTicks()) {
+ UMA_HISTOGRAM_TIMES("WebCore.SpellChecker.RequestInterval",
+ current_request_time - last_request_time_);
}
last_request_time_ = current_request_time;
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 c5268df0892..2085f68910f 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
@@ -127,7 +127,7 @@ class CORE_EXPORT SpellCheckRequester final
int last_request_sequence_;
int last_processed_sequence_;
- double last_request_time_;
+ TimeTicks last_request_time_;
TaskRunnerTimer<SpellCheckRequester> timer_to_process_queued_request_;
diff --git a/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util.cc b/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util.cc
index 6a2830ceeb2..64fe6ae2a45 100644
--- a/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util.cc
+++ b/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util.cc
@@ -13,16 +13,6 @@ namespace blink {
namespace {
-// Returns true if the code point has E_Basae_GAZ grapheme break property.
-// See
-// http://www.unicode.org/Public/9.0.0/ucd/auxiliary/GraphemeBreakProperty-9.0.0d18.txt
-bool IsEBaseGAZ(uint32_t code_point) {
- return code_point == WTF::Unicode::kBoyCharacter ||
- code_point == WTF::Unicode::kGirlCharacter ||
- code_point == WTF::Unicode::kManCharacter ||
- code_point == WTF::Unicode::kWomanCharacter;
-}
-
// The list of code points which has Indic_Syllabic_Category=Virama property.
// Must be sorted.
// See http://www.unicode.org/Public/9.0.0/ucd/IndicSyllabicCategory-9.0.0d2.txt
@@ -48,8 +38,6 @@ bool IsIndicSyllabicCategoryVirama(uint32_t code_point) {
bool IsGraphemeBreak(UChar32 prev_code_point, UChar32 next_code_point) {
// The following breaking rules come from Unicode Standard Annex #29 on
// Unicode Text Segmaentation. See http://www.unicode.org/reports/tr29/
- // Note that some of rules are in proposal.
- // Also see http://www.unicode.org/reports/tr29/proposed.html
int prev_prop =
u_getIntPropertyValue(prev_code_point, UCHAR_GRAPHEME_CLUSTER_BREAK);
int next_prop =
@@ -113,17 +101,14 @@ bool IsGraphemeBreak(UChar32 prev_code_point, UChar32 next_code_point) {
U_OTHER_LETTER)
return false;
- // Proposed Rule GB10, (E_Base | EBG) x E_Modifier
- if ((Character::IsEmojiModifierBase(prev_code_point) ||
- IsEBaseGAZ(prev_code_point)) &&
- Character::IsModifier(next_code_point))
- return false;
-
- // Proposed Rule GB11, ZWJ x Emoji
+ // GB11, ZWJ x Emoji
if (prev_code_point == kZeroWidthJoinerCharacter &&
(Character::IsEmoji(next_code_point)))
return false;
+ // GB12 for RI(Regional Indicator) is handled elsewhere because it requires
+ // counting the number of consecutive RIs.
+
// Rule GB999 any ÷ any
return true;
}
diff --git a/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util_test.cc b/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util_test.cc
index 8d71c543fa6..047744ebc74 100644
--- a/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/state_machines/state_machine_util_test.cc
@@ -121,7 +121,9 @@ TEST(StateMachineUtilTest, IsGraphmeBreak_EmojiModifier) {
EXPECT_TRUE(IsGraphemeBreak(kEBaseGAZ, kEBase));
EXPECT_TRUE(IsGraphemeBreak(kEBase, kEBaseGAZ));
EXPECT_TRUE(IsGraphemeBreak(kEBaseGAZ, kEBaseGAZ));
- EXPECT_TRUE(IsGraphemeBreak(kEModifier, kEModifier));
+ // EModifier is absorbed into Extend and there is NO break
+ // before Extend per GB 9.
+ EXPECT_FALSE(IsGraphemeBreak(kEModifier, kEModifier));
}
TEST(StateMachineUtilTest, IsGraphmeBreak_ZWJSequecne) {
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 6b0d30d38b4..e66b7394c4c 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
@@ -432,7 +432,7 @@ void TextSuggestionController::ShowSpellCheckMenu(
const IntRect& absolute_bounds = GetFrame().Selection().AbsoluteCaretBounds();
const IntRect& viewport_bounds =
- GetFrame().View()->ContentsToViewport(absolute_bounds);
+ GetFrame().View()->FrameToViewport(absolute_bounds);
text_suggestion_host_->ShowSpellCheckSuggestionMenu(
viewport_bounds.X(), viewport_bounds.MaxY(), std::move(misspelled_word),
@@ -508,7 +508,7 @@ void TextSuggestionController::CallMojoShowTextSuggestionMenu(
const IntRect& absolute_bounds = GetFrame().Selection().AbsoluteCaretBounds();
const IntRect& viewport_bounds =
- GetFrame().View()->ContentsToViewport(absolute_bounds);
+ GetFrame().View()->FrameToViewport(absolute_bounds);
text_suggestion_host_->ShowTextSuggestionMenu(
viewport_bounds.X(), viewport_bounds.MaxY(), misspelled_word,
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 255153ea80c..43754fab928 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
@@ -7,6 +7,7 @@
#include "third_party/blink/public/platform/input_host.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/dom/document_shutdown_observer.h"
#include "third_party/blink/renderer/core/editing/forward.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/testing/selection_sample_test.cc b/chromium/third_party/blink/renderer/core/editing/testing/selection_sample_test.cc
index 05c851dcd30..dbbcd245576 100644
--- a/chromium/third_party/blink/renderer/core/editing/testing/selection_sample_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/testing/selection_sample_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/editing/testing/selection_sample.h"
#include "third_party/blink/renderer/core/dom/processing_instruction.h"
+#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/text_offset_mapping.cc b/chromium/third_party/blink/renderer/core/editing/text_offset_mapping.cc
index edddf122afd..b507f7be8cd 100644
--- a/chromium/third_party/blink/renderer/core/editing/text_offset_mapping.cc
+++ b/chromium/third_party/blink/renderer/core/editing/text_offset_mapping.cc
@@ -196,8 +196,7 @@ PositionInFlatTree TextOffsetMapping::GetPositionBefore(unsigned offset) const {
PositionInFlatTree TextOffsetMapping::GetPositionAfter(unsigned offset) const {
DCHECK_LE(offset, text16_.length());
CharacterIteratorInFlatTree iterator(range_, behavior_);
- if (offset > 0)
- iterator.Advance(offset - 1);
+ iterator.Advance(offset);
return iterator.GetPositionAfter();
}
diff --git a/chromium/third_party/blink/renderer/core/editing/text_offset_mapping_test.cc b/chromium/third_party/blink/renderer/core/editing/text_offset_mapping_test.cc
index 7976375d87c..c9c784b3e63 100644
--- a/chromium/third_party/blink/renderer/core/editing/text_offset_mapping_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/text_offset_mapping_test.cc
@@ -23,8 +23,6 @@ class ParameterizedTextOffsetMappingTest
protected:
ParameterizedTextOffsetMappingTest() : ScopedLayoutNGForTest(GetParam()) {}
- bool LayoutNGEnabled() const { return GetParam(); }
-
std::string ComputeTextOffset(const std::string& selection_text) {
const PositionInFlatTree position =
ToPositionInFlatTree(SetSelectionTextToBody(selection_text).Base());
@@ -248,8 +246,7 @@ TEST_P(ParameterizedTextOffsetMappingTest, RangeWithMulticol) {
TEST_P(ParameterizedTextOffsetMappingTest, RangeWithNestedFloat) {
InsertStyleElement("b, i { float: right; }");
// Note: Legacy: BODY is inline, NG: BODY is block.
- EXPECT_EQ(LayoutNGEnabled() ? "<b>^abc <i>def</i> ghi|</b>xyz"
- : "^<b>abc <i>def</i> ghi</b>xyz|",
+ EXPECT_EQ("^<b>abc <i>def</i> ghi</b>xyz|",
GetRange("<b>abc <i>d|ef</i> ghi</b>xyz"));
}
@@ -348,13 +345,13 @@ TEST_P(ParameterizedTextOffsetMappingTest, GetPositionBefore) {
TEST_P(ParameterizedTextOffsetMappingTest, GetPositionAfter) {
EXPECT_EQ(" 0|12 456 ", GetPositionAfter(" 012 456 ", 0));
- EXPECT_EQ(" 0|12 456 ", GetPositionAfter(" 012 456 ", 1));
- EXPECT_EQ(" 01|2 456 ", GetPositionAfter(" 012 456 ", 2));
- EXPECT_EQ(" 012| 456 ", GetPositionAfter(" 012 456 ", 3));
- EXPECT_EQ(" 012 | 456 ", GetPositionAfter(" 012 456 ", 4));
- EXPECT_EQ(" 012 4|56 ", GetPositionAfter(" 012 456 ", 5));
- EXPECT_EQ(" 012 45|6 ", GetPositionAfter(" 012 456 ", 6));
- EXPECT_EQ(" 012 456| ", GetPositionAfter(" 012 456 ", 7));
+ EXPECT_EQ(" 01|2 456 ", GetPositionAfter(" 012 456 ", 1));
+ EXPECT_EQ(" 012| 456 ", GetPositionAfter(" 012 456 ", 2));
+ EXPECT_EQ(" 012 | 456 ", GetPositionAfter(" 012 456 ", 3));
+ EXPECT_EQ(" 012 4|56 ", GetPositionAfter(" 012 456 ", 4));
+ EXPECT_EQ(" 012 45|6 ", GetPositionAfter(" 012 456 ", 5));
+ EXPECT_EQ(" 012 456| ", GetPositionAfter(" 012 456 ", 6));
+ EXPECT_EQ(" 012 456 |", GetPositionAfter(" 012 456 ", 7));
// We hit DCHECK for offset 8, because we walk on "012 456".
}
diff --git a/chromium/third_party/blink/renderer/core/editing/text_segments.cc b/chromium/third_party/blink/renderer/core/editing/text_segments.cc
new file mode 100644
index 00000000000..4f3e19f7cc3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/editing/text_segments.cc
@@ -0,0 +1,59 @@
+// 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/editing/text_segments.h"
+
+#include "third_party/blink/renderer/core/editing/position.h"
+#include "third_party/blink/renderer/core/editing/text_offset_mapping.h"
+
+namespace blink {
+
+TextSegments::Finder::Position::Position() = default;
+
+TextSegments::Finder::Position::Position(unsigned offset, Type type)
+ : offset_(offset), type_(type) {
+ DCHECK_NE(type, kNone);
+}
+
+// static
+TextSegments::Finder::Position TextSegments::Finder::Position::Before(
+ unsigned offset) {
+ return Position(offset, kBefore);
+}
+
+// static
+TextSegments::Finder::Position TextSegments::Finder::Position::After(
+ unsigned offset) {
+ return Position(offset, kAfter);
+}
+
+unsigned TextSegments::Finder::Position::Offset() const {
+ DCHECK(type_ == kBefore || type_ == kAfter) << type_;
+ return offset_;
+}
+
+// static
+PositionInFlatTree TextSegments::FindBoundaryForward(
+ const PositionInFlatTree& position,
+ Finder* finder) {
+ DCHECK(position.IsNotNull());
+ PositionInFlatTree last_position = position;
+ for (const auto& inline_contents :
+ TextOffsetMapping::ForwardRangeOf(position)) {
+ const TextOffsetMapping mapping(inline_contents);
+ const String text = mapping.GetText();
+ const unsigned offset =
+ last_position == position ? mapping.ComputeTextOffset(position) : 0;
+ const TextSegments::Finder::Position result = finder->Find(text, offset);
+ if (result.IsBefore())
+ return mapping.GetPositionBefore(result.Offset());
+ if (result.IsAfter())
+ return mapping.GetPositionAfter(result.Offset());
+ DCHECK(result.IsNone());
+ last_position = mapping.GetRange().EndPosition();
+ }
+ return last_position;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/editing/text_segments.h b/chromium/third_party/blink/renderer/core/editing/text_segments.h
new file mode 100644
index 00000000000..f8813fcb76c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/editing/text_segments.h
@@ -0,0 +1,65 @@
+// 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_EDITING_TEXT_SEGMENTS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_TEXT_SEGMENTS_H_
+
+#include "base/optional.h"
+#include "third_party/blink/renderer/core/editing/forward.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace blink {
+
+// Provides functions for finding boundary of text segments.
+class TextSegments final {
+ STATIC_ONLY(TextSegments);
+
+ public:
+ // The interface to find boundary of text segment.
+ class Finder {
+ public:
+ class Position final {
+ STACK_ALLOCATED();
+
+ public:
+ Position();
+
+ static Position Before(unsigned offset);
+ static Position After(unsigned offset);
+
+ bool IsAfter() const { return type_ == kAfter; }
+ bool IsBefore() const { return type_ == kBefore; }
+ bool IsNone() const { return type_ == kNone; }
+
+ unsigned Offset() const;
+
+ private:
+ enum Type { kNone, kBefore, kAfter };
+
+ Position(unsigned value, Type type);
+
+ const unsigned offset_ = 0;
+ const Type type_ = kNone;
+ };
+
+ // Returns a text segment boundary position in |text| from |offset|.
+ // Note: |text| must contains character 16.
+ // Note: Since implementations can have state, |Find()| function isn't
+ // marked |const| intentionally.
+ virtual Position Find(const String text, unsigned offset) = 0;
+ };
+
+ // TODO(editing-dev): We should have |FindBoundaryBackward()|.
+
+ // Returns a boundary position found by |finder| followed by |position|
+ // (inclusive). |finder| can be stateful or stateless.
+ static PositionInFlatTree FindBoundaryForward(
+ const PositionInFlatTree& position,
+ Finder* finder);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_TEXT_SEGMENTS_H_
diff --git a/chromium/third_party/blink/renderer/core/editing/visible_position.cc b/chromium/third_party/blink/renderer/core/editing/visible_position.cc
index f1e2380360a..4a013d1ef5e 100644
--- a/chromium/third_party/blink/renderer/core/editing/visible_position.cc
+++ b/chromium/third_party/blink/renderer/core/editing/visible_position.cc
@@ -28,7 +28,6 @@
#include "third_party/blink/renderer/core/editing/visible_position.h"
#include <ostream> // NOLINT
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/editing_utilities.h"
@@ -36,6 +35,7 @@
#include "third_party/blink/renderer/core/editing/visible_units.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/html_names.h"
+#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/wtf/text/cstring.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/visible_position.h b/chromium/third_party/blink/renderer/core/editing/visible_position.h
index 3cfa12a9a87..4ff562a1ce4 100644
--- a/chromium/third_party/blink/renderer/core/editing/visible_position.h
+++ b/chromium/third_party/blink/renderer/core/editing/visible_position.h
@@ -53,7 +53,7 @@ namespace blink {
// NOTE: UPSTREAM affinity will be used only if pos is at end of a wrapped line,
// otherwise it will be converted to DOWNSTREAM.
template <typename Strategy>
-class CORE_TEMPLATE_CLASS_EXPORT VisiblePositionTemplate final {
+class VisiblePositionTemplate final {
DISALLOW_NEW();
public:
diff --git a/chromium/third_party/blink/renderer/core/editing/visible_selection.cc b/chromium/third_party/blink/renderer/core/editing/visible_selection.cc
index a2aa495e2d4..377fc0aac29 100644
--- a/chromium/third_party/blink/renderer/core/editing/visible_selection.cc
+++ b/chromium/third_party/blink/renderer/core/editing/visible_selection.cc
@@ -25,7 +25,6 @@
#include "third_party/blink/renderer/core/editing/visible_selection.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/range.h"
@@ -35,6 +34,7 @@
#include "third_party/blink/renderer/core/editing/selection_adjuster.h"
#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/core/editing/visible_position.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/geometry/layout_point.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
@@ -56,47 +56,72 @@ VisibleSelectionTemplate<Strategy>::VisibleSelectionTemplate(
base_is_first_(selection.IsBaseFirst()) {}
template <typename Strategy>
-VisibleSelectionTemplate<Strategy> VisibleSelectionTemplate<Strategy>::Create(
- const SelectionTemplate<Strategy>& selection) {
- return CreateWithGranularity(selection, TextGranularity::kCharacter);
-}
+class VisibleSelectionTemplate<Strategy>::Creator {
+ STATIC_ONLY(Creator);
+
+ public:
+ static VisibleSelectionTemplate<Strategy> CreateWithGranularity(
+ const SelectionTemplate<Strategy>& selection,
+ TextGranularity granularity) {
+ return VisibleSelectionTemplate<Strategy>(
+ ComputeVisibleSelection(selection, granularity));
+ }
+
+ private:
+ static SelectionTemplate<Strategy> ComputeVisibleSelection(
+ const SelectionTemplate<Strategy>& passed_selection,
+ TextGranularity granularity) {
+ DCHECK(!NeedsLayoutTreeUpdate(passed_selection.Base()));
+ DCHECK(!NeedsLayoutTreeUpdate(passed_selection.Extent()));
+
+ const SelectionTemplate<Strategy>& canonicalized_selection =
+ CanonicalizeSelection(passed_selection);
+
+ if (canonicalized_selection.IsNone())
+ return SelectionTemplate<Strategy>();
+
+ const SelectionTemplate<Strategy>& granularity_adjusted_selection =
+ SelectionAdjuster::AdjustSelectionRespectingGranularity(
+ canonicalized_selection, granularity);
+ const SelectionTemplate<Strategy>& shadow_adjusted_selection =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingShadowBoundaries(
+ granularity_adjusted_selection);
+ const SelectionTemplate<Strategy>& editing_adjusted_selection =
+ SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
+ shadow_adjusted_selection);
+ const SelectionTemplate<Strategy>& type_adjusted_selection =
+ SelectionAdjuster::AdjustSelectionType(
+ typename SelectionTemplate<Strategy>::Builder(
+ editing_adjusted_selection)
+ .SetAffinity(passed_selection.Affinity())
+ .Build());
+ return type_adjusted_selection;
+ }
+};
VisibleSelection CreateVisibleSelection(const SelectionInDOMTree& selection) {
- return VisibleSelection::Create(selection);
+ return VisibleSelection::Creator::CreateWithGranularity(
+ selection, TextGranularity::kCharacter);
}
VisibleSelectionInFlatTree CreateVisibleSelection(
const SelectionInFlatTree& selection) {
- return VisibleSelectionInFlatTree::Create(selection);
-}
-
-// TODO(editing-dev): We should move |ComputeVisibleSelection()| to here to
-// avoid forward declaration.
-template <typename Strategy>
-static SelectionTemplate<Strategy> ComputeVisibleSelection(
- const SelectionTemplate<Strategy>&,
- TextGranularity);
-
-template <typename Strategy>
-VisibleSelectionTemplate<Strategy>
-VisibleSelectionTemplate<Strategy>::CreateWithGranularity(
- const SelectionTemplate<Strategy>& selection,
- TextGranularity granularity) {
- return VisibleSelectionTemplate(
- ComputeVisibleSelection(selection, granularity));
+ return VisibleSelectionInFlatTree::Creator::CreateWithGranularity(
+ selection, TextGranularity::kCharacter);
}
VisibleSelection CreateVisibleSelectionWithGranularity(
const SelectionInDOMTree& selection,
TextGranularity granularity) {
- return VisibleSelection::CreateWithGranularity(selection, granularity);
+ return VisibleSelection::Creator::CreateWithGranularity(selection,
+ granularity);
}
VisibleSelectionInFlatTree CreateVisibleSelectionWithGranularity(
const SelectionInFlatTree& selection,
TextGranularity granularity) {
- return VisibleSelectionInFlatTree::CreateWithGranularity(selection,
- granularity);
+ return VisibleSelectionInFlatTree::Creator::CreateWithGranularity(
+ selection, granularity);
}
template <typename Strategy>
@@ -233,37 +258,6 @@ static SelectionTemplate<Strategy> CanonicalizeSelection(
}
template <typename Strategy>
-static SelectionTemplate<Strategy> ComputeVisibleSelection(
- const SelectionTemplate<Strategy>& passed_selection,
- TextGranularity granularity) {
- DCHECK(!NeedsLayoutTreeUpdate(passed_selection.Base()));
- DCHECK(!NeedsLayoutTreeUpdate(passed_selection.Extent()));
-
- const SelectionTemplate<Strategy>& canonicalized_selection =
- CanonicalizeSelection(passed_selection);
-
- if (canonicalized_selection.IsNone())
- return SelectionTemplate<Strategy>();
-
- const SelectionTemplate<Strategy>& granularity_adjusted_selection =
- SelectionAdjuster::AdjustSelectionRespectingGranularity(
- canonicalized_selection, granularity);
- const SelectionTemplate<Strategy>& shadow_adjusted_selection =
- SelectionAdjuster::AdjustSelectionToAvoidCrossingShadowBoundaries(
- granularity_adjusted_selection);
- const SelectionTemplate<Strategy>& editing_adjusted_selection =
- SelectionAdjuster::AdjustSelectionToAvoidCrossingEditingBoundaries(
- shadow_adjusted_selection);
- const SelectionTemplate<Strategy>& type_adjusted_selection =
- SelectionAdjuster::AdjustSelectionType(
- typename SelectionTemplate<Strategy>::Builder(
- editing_adjusted_selection)
- .SetAffinity(passed_selection.Affinity())
- .Build());
- return type_adjusted_selection;
-}
-
-template <typename Strategy>
bool VisibleSelectionTemplate<Strategy>::IsValidFor(
const Document& document) const {
if (IsNone())
diff --git a/chromium/third_party/blink/renderer/core/editing/visible_selection.h b/chromium/third_party/blink/renderer/core/editing/visible_selection.h
index 3bab691384a..3466e8cc5ef 100644
--- a/chromium/third_party/blink/renderer/core/editing/visible_selection.h
+++ b/chromium/third_party/blink/renderer/core/editing/visible_selection.h
@@ -38,28 +38,19 @@
namespace blink {
-class SelectionAdjuster;
-
const TextAffinity kSelDefaultAffinity = TextAffinity::kDownstream;
template <typename Strategy>
-class CORE_TEMPLATE_CLASS_EXPORT VisibleSelectionTemplate {
+class VisibleSelectionTemplate {
DISALLOW_NEW();
public:
+ class Creator;
+
VisibleSelectionTemplate();
VisibleSelectionTemplate(const VisibleSelectionTemplate&);
VisibleSelectionTemplate& operator=(const VisibleSelectionTemplate&);
- // Note: |create()| should be used only by |createVisibleSelection|.
- static VisibleSelectionTemplate Create(const SelectionTemplate<Strategy>&);
-
- // Note: |CreateWithGranularity()| should be used only by
- // |CreateVisibleSelectionWithGranularity()|.
- static VisibleSelectionTemplate CreateWithGranularity(
- const SelectionTemplate<Strategy>&,
- TextGranularity);
-
TextAffinity Affinity() const { return affinity_; }
SelectionTemplate<Strategy> AsSelection() const;
@@ -112,8 +103,6 @@ class CORE_TEMPLATE_CLASS_EXPORT VisibleSelectionTemplate {
static void PrintTo(const VisibleSelectionTemplate&, std::ostream*);
private:
- friend class SelectionAdjuster;
-
explicit VisibleSelectionTemplate(const SelectionTemplate<Strategy>&);
// We need to store these as Positions because VisibleSelection is
diff --git a/chromium/third_party/blink/renderer/core/editing/visible_selection_test.cc b/chromium/third_party/blink/renderer/core/editing/visible_selection_test.cc
index 9709dac42bc..663977ea43e 100644
--- a/chromium/third_party/blink/renderer/core/editing/visible_selection_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/visible_selection_test.cc
@@ -101,6 +101,7 @@ TEST_F(VisibleSelectionTest, expandUsingGranularity) {
Node* three = shadow_root->getElementById("three")->firstChild();
Node* four = shadow_root->getElementById("four")->firstChild();
Node* five = shadow_root->getElementById("five")->firstChild();
+ Node* space = shadow_root->getElementById("space")->firstChild();
VisibleSelection selection;
VisibleSelectionInFlatTree selection_in_flat_tree;
@@ -118,8 +119,8 @@ TEST_F(VisibleSelectionTest, expandUsingGranularity) {
EXPECT_EQ(selection.Start(), selection.Base());
EXPECT_EQ(selection.End(), selection.Extent());
- EXPECT_EQ(Position(one, 0), selection.Start());
- EXPECT_EQ(Position(two, 2), selection.End());
+ EXPECT_EQ(Position(five, 5), selection.Start());
+ EXPECT_EQ(Position(five, 5), selection.End());
EXPECT_EQ(selection_in_flat_tree.Start(), selection_in_flat_tree.Base());
EXPECT_EQ(selection_in_flat_tree.End(), selection_in_flat_tree.Extent());
@@ -139,8 +140,8 @@ TEST_F(VisibleSelectionTest, expandUsingGranularity) {
EXPECT_EQ(selection.Start(), selection.Base());
EXPECT_EQ(selection.End(), selection.Extent());
- EXPECT_EQ(Position(one, 0), selection.Start());
- EXPECT_EQ(Position(two, 2), selection.End());
+ EXPECT_EQ(Position(space, 0), selection.Start());
+ EXPECT_EQ(Position(five, 5), selection.End());
EXPECT_EQ(selection_in_flat_tree.Start(), selection_in_flat_tree.Base());
EXPECT_EQ(selection_in_flat_tree.End(), selection_in_flat_tree.Extent());
diff --git a/chromium/third_party/blink/renderer/core/editing/visible_units.cc b/chromium/third_party/blink/renderer/core/editing/visible_units.cc
index 9d2d5ff2af2..efc60394e4c 100644
--- a/chromium/third_party/blink/renderer/core/editing/visible_units.cc
+++ b/chromium/third_party/blink/renderer/core/editing/visible_units.cc
@@ -425,127 +425,6 @@ static PositionTemplate<Strategy> PreviousBoundaryAlgorithm(
return char_it.EndPosition();
}
-template <typename Strategy>
-static PositionTemplate<Strategy> NextBoundaryAlgorithm(
- const VisiblePositionTemplate<Strategy>& c,
- BoundarySearchFunction search_function) {
- DCHECK(c.IsValid()) << c;
- PositionTemplate<Strategy> pos = c.DeepEquivalent();
- Node* boundary = ParentEditingBoundary(pos);
- if (!boundary)
- return PositionTemplate<Strategy>();
-
- Document& d = boundary->GetDocument();
- const PositionTemplate<Strategy> start(pos.ParentAnchoredEquivalent());
-
- BackwardsTextBuffer prefix_string;
- if (RequiresContextForWordBoundary(CharacterAfter(c))) {
- SimplifiedBackwardsTextIteratorAlgorithm<Strategy> backwards_iterator(
- EphemeralRangeTemplate<Strategy>(
- PositionTemplate<Strategy>::FirstPositionInNode(d), start));
- while (!backwards_iterator.AtEnd()) {
- backwards_iterator.CopyTextTo(&prefix_string);
- int context_start_index = StartOfLastWordBoundaryContext(
- prefix_string.Data(), backwards_iterator.length());
- if (context_start_index > 0) {
- prefix_string.Shrink(context_start_index);
- break;
- }
- backwards_iterator.Advance();
- }
- }
-
- unsigned prefix_length = prefix_string.Size();
- ForwardsTextBuffer string;
- string.PushRange(prefix_string.Data(), prefix_string.Size());
-
- const PositionTemplate<Strategy> search_start =
- PositionTemplate<Strategy>::EditingPositionOf(
- start.AnchorNode(), start.OffsetInContainerNode());
- const PositionTemplate<Strategy> search_end =
- PositionTemplate<Strategy>::LastPositionInNode(*boundary);
- // Treat bullets used in the text security mode as regular characters when
- // looking for boundaries
- TextIteratorAlgorithm<Strategy> it(
- search_start, search_end,
- TextIteratorBehavior::Builder()
- .SetEmitsCharactersBetweenAllVisiblePositions(true)
- .SetEmitsSmallXForTextSecurity(true)
- .Build());
- const unsigned kInvalidOffset = static_cast<unsigned>(-1);
- unsigned next = kInvalidOffset;
- unsigned offset = prefix_length;
- bool need_more_context = false;
- while (!it.AtEnd()) {
- // Keep asking the iterator for chunks until the search function
- // returns an end value not equal to the length of the string passed to
- // it.
- int run_offset = 0;
- do {
- run_offset += it.CopyTextTo(&string, run_offset, string.Capacity());
- next = search_function(string.Data(), string.Size(), offset,
- kMayHaveMoreContext, need_more_context);
- if (!need_more_context) {
- // When the search does not need more context, skip all examined
- // characters except the last one, in case it is a boundary.
- offset = string.Size();
- U16_BACK_1(string.Data(), 0, offset);
- }
- } while (next == string.Size() && run_offset < it.length());
- if (next != string.Size())
- break;
- it.Advance();
- }
- if (need_more_context) {
- // The last search returned the end of the buffer and asked for more
- // context, but there is no further text. Force a search with what's
- // available.
- next = search_function(string.Data(), string.Size(), prefix_length,
- kDontHaveMoreContext, need_more_context);
- DCHECK(!need_more_context);
- }
-
- if (it.AtEnd() && next == string.Size()) {
- pos = it.StartPositionInCurrentContainer();
- } else if (next != kInvalidOffset && next != prefix_length) {
- // Use the character iterator to translate the next value into a DOM
- // position.
- CharacterIteratorAlgorithm<Strategy> char_it(
- search_start, search_end,
- TextIteratorBehavior::Builder()
- .SetEmitsCharactersBetweenAllVisiblePositions(true)
- .Build());
- char_it.Advance(next - prefix_length - 1);
- pos = char_it.EndPosition();
-
- if (char_it.CharacterAt(0) == '\n') {
- // TODO(yosin) workaround for collapsed range (where only start
- // position is correct) emitted for some emitted newlines
- // (see rdar://5192593)
- const VisiblePositionTemplate<Strategy> vis_pos =
- CreateVisiblePosition(pos);
- if (vis_pos.DeepEquivalent() ==
- CreateVisiblePosition(char_it.StartPosition()).DeepEquivalent()) {
- char_it.Advance(1);
- pos = char_it.StartPosition();
- }
- }
- }
-
- return pos;
-}
-
-Position NextBoundary(const VisiblePosition& visible_position,
- BoundarySearchFunction search_function) {
- return NextBoundaryAlgorithm(visible_position, search_function);
-}
-
-PositionInFlatTree NextBoundary(
- const VisiblePositionInFlatTree& visible_position,
- BoundarySearchFunction search_function) {
- return NextBoundaryAlgorithm(visible_position, search_function);
-}
-
Position PreviousBoundary(const VisiblePosition& visible_position,
BoundarySearchFunction search_function) {
return PreviousBoundaryAlgorithm(visible_position, search_function);
@@ -690,8 +569,9 @@ VisiblePosition VisiblePositionForContentsPoint(const IntPoint& contents_point,
HitTestRequest request = HitTestRequest::kMove | HitTestRequest::kReadOnly |
HitTestRequest::kActive |
HitTestRequest::kIgnoreClipping;
- HitTestResult result(request, contents_point);
- frame->GetDocument()->GetLayoutView()->HitTest(result);
+ HitTestLocation location(contents_point);
+ HitTestResult result(request, location);
+ frame->GetDocument()->GetLayoutView()->HitTest(location, result);
if (Node* node = result.InnerNode()) {
return CreateVisiblePosition(PositionRespectingEditingBoundary(
@@ -931,6 +811,22 @@ PositionInFlatTree MostBackwardCaretPosition(const PositionInFlatTree& position,
return MostBackwardCaretPosition<EditingInFlatTreeStrategy>(position, rule);
}
+namespace {
+bool HasInvisibleFirstLetter(const Node* node) {
+ if (!node || !node->IsTextNode())
+ return false;
+ const LayoutTextFragment* remaining_text =
+ ToLayoutTextFragmentOrNull(node->GetLayoutObject());
+ if (!remaining_text || !remaining_text->IsRemainingTextLayoutObject())
+ return false;
+ const LayoutTextFragment* first_letter =
+ ToLayoutTextFragmentOrNull(AssociatedLayoutObjectOf(*node, 0));
+ if (!first_letter || first_letter == remaining_text)
+ return false;
+ return first_letter->StyleRef().Visibility() != EVisibility::kVisible;
+}
+} // namespace
+
template <typename Strategy>
PositionTemplate<Strategy> MostForwardCaretPosition(
const PositionTemplate<Strategy>& position,
@@ -1023,7 +919,8 @@ PositionTemplate<Strategy> MostForwardCaretPosition(
continue;
const unsigned text_start_offset = text_layout_object->TextStartOffset();
if (current_node != start_node) {
- DCHECK(current_pos.AtStartOfNode());
+ DCHECK(current_pos.AtStartOfNode() ||
+ HasInvisibleFirstLetter(current_node));
return PositionTemplate<Strategy>(
current_node, layout_object->CaretMinOffset() + text_start_offset);
}
diff --git a/chromium/third_party/blink/renderer/core/editing/visible_units.h b/chromium/third_party/blink/renderer/core/editing/visible_units.h
index 80e867db067..fb3495668a8 100644
--- a/chromium/third_party/blink/renderer/core/editing/visible_units.h
+++ b/chromium/third_party/blink/renderer/core/editing/visible_units.h
@@ -31,7 +31,7 @@
#include "third_party/blink/renderer/core/editing/forward.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/text/text_direction.h"
-#include "third_party/blink/renderer/platform/wtf/text/icu/unicode_icu.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
namespace blink {
@@ -126,10 +126,6 @@ StartOfWordPosition(const VisiblePositionInFlatTree&,
CORE_EXPORT VisiblePositionInFlatTree
StartOfWord(const VisiblePositionInFlatTree&,
EWordSide = kNextWordIfOnBoundary);
-// TODO(yoichio): Replace |endOfWord| to |endOfWordPosition| because returned
-// Position should be canonicalized with |nextBoundary()| by TextItetator.
-CORE_EXPORT Position EndOfWordPosition(const VisiblePosition&,
- EWordSide = kNextWordIfOnBoundary);
CORE_EXPORT VisiblePosition EndOfWord(const VisiblePosition&,
EWordSide = kNextWordIfOnBoundary);
CORE_EXPORT PositionInFlatTree
@@ -275,10 +271,6 @@ typedef unsigned (*BoundarySearchFunction)(const UChar*,
BoundarySearchContextAvailability,
bool& need_more_context);
-CORE_EXPORT Position NextBoundary(const VisiblePosition&,
- BoundarySearchFunction);
-PositionInFlatTree NextBoundary(const VisiblePositionInFlatTree&,
- BoundarySearchFunction);
Position PreviousBoundary(const VisiblePosition&, BoundarySearchFunction);
PositionInFlatTree PreviousBoundary(const VisiblePositionInFlatTree&,
BoundarySearchFunction);
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 3bbe1078b6d..90c566c30a0 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
@@ -30,7 +30,7 @@
#include "third_party/blink/renderer/core/editing/visible_units.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/inline_box_position.h"
#include "third_party/blink/renderer/core/editing/ng_flat_tree_shorthands.h"
diff --git a/chromium/third_party/blink/renderer/core/editing/visible_units_sentence.cc b/chromium/third_party/blink/renderer/core/editing/visible_units_sentence.cc
index 424949e0741..870e8c01aa0 100644
--- a/chromium/third_party/blink/renderer/core/editing/visible_units_sentence.cc
+++ b/chromium/third_party/blink/renderer/core/editing/visible_units_sentence.cc
@@ -30,7 +30,9 @@
#include "third_party/blink/renderer/core/editing/visible_units.h"
+#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
+#include "third_party/blink/renderer/core/editing/text_segments.h"
#include "third_party/blink/renderer/core/editing/visible_position.h"
#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
@@ -38,26 +40,6 @@ namespace blink {
namespace {
-unsigned EndSentenceBoundary(const UChar* characters,
- unsigned length,
- unsigned,
- BoundarySearchContextAvailability,
- bool&) {
- TextBreakIterator* iterator = SentenceBreakIterator(characters, length);
- return iterator->next();
-}
-
-unsigned NextSentencePositionBoundary(const UChar* characters,
- unsigned length,
- unsigned,
- BoundarySearchContextAvailability,
- bool&) {
- // FIXME: This is identical to endSentenceBoundary. This isn't right, it needs
- // to move to the equivlant position in the following sentence.
- TextBreakIterator* iterator = SentenceBreakIterator(characters, length);
- return iterator->following(0);
-}
-
unsigned PreviousSentencePositionBoundary(const UChar* characters,
unsigned length,
unsigned,
@@ -82,12 +64,81 @@ unsigned StartSentenceBoundary(const UChar* characters,
// TODO(yosin) This includes the space after the punctuation that marks the end
// of the sentence.
-template <typename Strategy>
-static VisiblePositionTemplate<Strategy> EndOfSentenceAlgorithm(
- const VisiblePositionTemplate<Strategy>& c) {
- DCHECK(c.IsValid()) << c;
- return CreateVisiblePosition(NextBoundary(c, EndSentenceBoundary),
- TextAffinity::kUpstreamIfPossible);
+PositionInFlatTree EndOfSentenceInternal(const PositionInFlatTree& position) {
+ class Finder final : public TextSegments::Finder {
+ STACK_ALLOCATED();
+
+ public:
+ Position Find(const String text, unsigned passed_offset) final {
+ DCHECK_LE(passed_offset, text.length());
+ TextBreakIterator* iterator =
+ SentenceBreakIterator(text.Characters16(), text.length());
+ // "move_by_sentence_boundary.html" requires to skip a space characters
+ // between sentences.
+ const unsigned offset = FindNonSpaceCharacter(text, passed_offset);
+ const int result = iterator->following(offset);
+ if (result == kTextBreakDone)
+ return Position();
+ return result == 0 ? Position::Before(0) : Position::After(result - 1);
+ }
+
+ private:
+ static unsigned FindNonSpaceCharacter(const String text,
+ unsigned passed_offset) {
+ for (unsigned offset = passed_offset; offset < text.length(); ++offset) {
+ if (text[offset] != ' ')
+ return offset;
+ }
+ return text.length();
+ }
+ } finder;
+ return TextSegments::FindBoundaryForward(position, &finder);
+}
+
+PositionInFlatTree NextSentencePositionInternal(
+ const PositionInFlatTree& position) {
+ class Finder final : public TextSegments::Finder {
+ STACK_ALLOCATED();
+
+ private:
+ Position Find(const String text, unsigned offset) final {
+ DCHECK_LE(offset, text.length());
+ if (should_stop_finding_) {
+ DCHECK_EQ(offset, 0u);
+ return Position::Before(0);
+ }
+ if (IsImplicitEndOfSentence(text, offset)) {
+ // Since each block is separated by newline == end of sentence code,
+ // |Find()| will stop at start of next block rater than between blocks.
+ should_stop_finding_ = true;
+ return Position();
+ }
+ TextBreakIterator* it =
+ SentenceBreakIterator(text.Characters16(), text.length());
+ const int result = it->following(offset);
+ if (result == kTextBreakDone)
+ return Position();
+ return result == 0 ? Position::Before(0) : Position::After(result - 1);
+ }
+
+ static bool IsImplicitEndOfSentence(const String text, unsigned offset) {
+ DCHECK_LE(offset, text.length());
+ if (offset == text.length()) {
+ // "extend-by-sentence-002.html" reaches here.
+ // Example: <p>abc|</p><p>def</p> => <p>abc</p><p>|def</p>
+ return true;
+ }
+ if (offset + 1 == text.length() && text[offset] == '\n') {
+ // "move_forward_sentence_empty_line_break.html" reaches here.
+ // foo<div>|<br></div>bar -> foo<div><br></div>|bar
+ return true;
+ }
+ return false;
+ }
+
+ bool should_stop_finding_ = false;
+ } finder;
+ return TextSegments::FindBoundaryForward(position, &finder);
}
template <typename Strategy>
@@ -99,12 +150,24 @@ VisiblePositionTemplate<Strategy> StartOfSentenceAlgorithm(
} // namespace
+PositionInFlatTreeWithAffinity EndOfSentence(const PositionInFlatTree& start) {
+ const PositionInFlatTree result = EndOfSentenceInternal(start);
+ return AdjustForwardPositionToAvoidCrossingEditingBoundaries(
+ PositionInFlatTreeWithAffinity(result), start);
+}
+
+PositionWithAffinity EndOfSentence(const Position& start) {
+ const PositionInFlatTreeWithAffinity result =
+ EndOfSentence(ToPositionInFlatTree(start));
+ return ToPositionInDOMTreeWithAffinity(result);
+}
+
VisiblePosition EndOfSentence(const VisiblePosition& c) {
- return EndOfSentenceAlgorithm<EditingStrategy>(c);
+ return CreateVisiblePosition(EndOfSentence(c.DeepEquivalent()));
}
VisiblePositionInFlatTree EndOfSentence(const VisiblePositionInFlatTree& c) {
- return EndOfSentenceAlgorithm<EditingInFlatTreeStrategy>(c);
+ return CreateVisiblePosition(EndOfSentence(c.DeepEquivalent()));
}
EphemeralRange ExpandEndToSentenceBoundary(const EphemeralRange& range) {
@@ -140,15 +203,36 @@ EphemeralRange ExpandRangeToSentenceBoundary(const EphemeralRange& range) {
range.EndPosition()));
}
-VisiblePosition NextSentencePosition(const VisiblePosition& c) {
- DCHECK(c.IsValid()) << c;
- VisiblePosition next =
- CreateVisiblePosition(NextBoundary(c, NextSentencePositionBoundary),
- TextAffinity::kUpstreamIfPossible);
+// ----
+
+PositionInFlatTreeWithAffinity NextSentencePosition(
+ const PositionInFlatTree& start) {
+ const PositionInFlatTree result = NextSentencePositionInternal(start);
return AdjustForwardPositionToAvoidCrossingEditingBoundaries(
- next, c.DeepEquivalent());
+ PositionInFlatTreeWithAffinity(result), start);
+}
+
+PositionWithAffinity NextSentencePosition(const Position& start) {
+ const PositionInFlatTreeWithAffinity result =
+ NextSentencePosition(ToPositionInFlatTree(start));
+ return ToPositionInDOMTreeWithAffinity(result);
}
+VisiblePosition NextSentencePosition(const VisiblePosition& c) {
+ return CreateVisiblePosition(
+ NextSentencePosition(c.DeepEquivalent()).GetPosition(),
+ TextAffinity::kUpstreamIfPossible);
+}
+
+VisiblePositionInFlatTree NextSentencePosition(
+ const VisiblePositionInFlatTree& c) {
+ return CreateVisiblePosition(
+ NextSentencePosition(c.DeepEquivalent()).GetPosition(),
+ TextAffinity::kUpstreamIfPossible);
+}
+
+// ----
+
VisiblePosition PreviousSentencePosition(const VisiblePosition& c) {
DCHECK(c.IsValid()) << c;
VisiblePosition prev = CreateVisiblePosition(
diff --git a/chromium/third_party/blink/renderer/core/editing/visible_units_sentence_test.cc b/chromium/third_party/blink/renderer/core/editing/visible_units_sentence_test.cc
index f2ed9b0f81b..fd08634cbce 100644
--- a/chromium/third_party/blink/renderer/core/editing/visible_units_sentence_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/visible_units_sentence_test.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/editing/visible_position.h"
#include "third_party/blink/renderer/core/html/forms/text_control_element.h"
#include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
namespace blink {
@@ -47,7 +48,21 @@ class VisibleUnitsSentenceTest : public EditingTestBase {
}
};
-TEST_F(VisibleUnitsSentenceTest, endOfSentence) {
+class ParameterizedVisibleUnitsSentenceTest
+ : public ::testing::WithParamInterface<bool>,
+ private ScopedLayoutNGForTest,
+ public VisibleUnitsSentenceTest {
+ protected:
+ ParameterizedVisibleUnitsSentenceTest() : ScopedLayoutNGForTest(GetParam()) {}
+
+ bool LayoutNGEnabled() const { return GetParam(); }
+};
+
+INSTANTIATE_TEST_CASE_P(All,
+ ParameterizedVisibleUnitsSentenceTest,
+ ::testing::Bool());
+
+TEST_P(ParameterizedVisibleUnitsSentenceTest, EndOfSentenceShadowDOMV0) {
const char* body_content = "<a id=host><b id=one>1</b><b id=two>22</b></a>";
const char* shadow_content =
"<p><i id=three>333</i> <content select=#two></content> <content "
@@ -61,28 +76,28 @@ TEST_F(VisibleUnitsSentenceTest, endOfSentence) {
Node* four = shadow_root->getElementById("four")->firstChild();
EXPECT_EQ(
- Position(two, 2),
+ Position(four, 4),
EndOfSentence(CreateVisiblePositionInDOMTree(*one, 0)).DeepEquivalent());
EXPECT_EQ(
PositionInFlatTree(four, 4),
EndOfSentence(CreateVisiblePositionInFlatTree(*one, 0)).DeepEquivalent());
EXPECT_EQ(
- Position(two, 2),
+ Position(four, 4),
EndOfSentence(CreateVisiblePositionInDOMTree(*one, 1)).DeepEquivalent());
EXPECT_EQ(
PositionInFlatTree(four, 4),
EndOfSentence(CreateVisiblePositionInFlatTree(*one, 1)).DeepEquivalent());
EXPECT_EQ(
- Position(two, 2),
+ Position(four, 4),
EndOfSentence(CreateVisiblePositionInDOMTree(*two, 0)).DeepEquivalent());
EXPECT_EQ(
PositionInFlatTree(four, 4),
EndOfSentence(CreateVisiblePositionInFlatTree(*two, 0)).DeepEquivalent());
EXPECT_EQ(
- Position(two, 2),
+ Position(four, 4),
EndOfSentence(CreateVisiblePositionInDOMTree(*two, 1)).DeepEquivalent());
EXPECT_EQ(
PositionInFlatTree(four, 4),
diff --git a/chromium/third_party/blink/renderer/core/editing/visible_units_test.cc b/chromium/third_party/blink/renderer/core/editing/visible_units_test.cc
index 719e0b0978d..cd11696bd1b 100644
--- a/chromium/third_party/blink/renderer/core/editing/visible_units_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/visible_units_test.cc
@@ -761,22 +761,12 @@ TEST_F(VisibleUnitsTest,
EXPECT_EQ(Position(text, 2), start);
}
-static unsigned MockBoundarySearch(const UChar*,
- unsigned,
- unsigned,
- BoundarySearchContextAvailability,
- bool&) {
- return true;
-}
-
-// Regression test for crbug.com/788661
-TEST_F(VisibleUnitsTest, NextBoundaryOfEditableTableWithLeadingSpaceInOutput) {
- VisiblePosition pos = CreateVisiblePosition(SetCaretTextToBody(
- // The leading whitespace is necessary for bug repro
- "<output> <table contenteditable><!--|--></table></output>"));
- Position result = NextBoundary(pos, MockBoundarySearch);
- EXPECT_EQ("<output> <table contenteditable>|</table></output>",
- GetCaretTextFromBody(result));
+TEST_F(VisibleUnitsTest, MostForwardCaretPositionWithInvisibleFirstLetter) {
+ InsertStyleElement("div::first-letter{visibility:hidden}");
+ // Use special syntax to set input position DIV@0
+ const Position position = SetCaretTextToBody("<div><!--|-->foo</div>");
+ const Node* foo = GetDocument().QuerySelector("div")->firstChild();
+ EXPECT_EQ(Position(foo, 1), MostForwardCaretPosition(position));
}
} // namespace visible_units_test
diff --git a/chromium/third_party/blink/renderer/core/editing/visible_units_word.cc b/chromium/third_party/blink/renderer/core/editing/visible_units_word.cc
index ca38b6d4e98..6bea8e9672f 100644
--- a/chromium/third_party/blink/renderer/core/editing/visible_units_word.cc
+++ b/chromium/third_party/blink/renderer/core/editing/visible_units_word.cc
@@ -32,70 +32,82 @@
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
-#include "third_party/blink/renderer/core/editing/text_offset_mapping.h"
+#include "third_party/blink/renderer/core/editing/text_segments.h"
#include "third_party/blink/renderer/core/editing/visible_position.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/text/text_boundaries.h"
+#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
namespace blink {
namespace {
-unsigned EndWordBoundary(
- const UChar* characters,
- unsigned length,
- unsigned offset,
- BoundarySearchContextAvailability may_have_more_context,
- bool& need_more_context) {
- DCHECK_LE(offset, length);
- if (may_have_more_context &&
- EndOfFirstWordBoundaryContext(characters + offset, length - offset) ==
- static_cast<int>(length - offset)) {
- need_more_context = true;
- return length;
- }
- need_more_context = false;
- return FindWordEndBoundary(characters, length, offset);
-}
-
-template <typename Strategy>
-PositionTemplate<Strategy> EndOfWordAlgorithm(
- const VisiblePositionTemplate<Strategy>& c,
- EWordSide side) {
- DCHECK(c.IsValid()) << c;
- VisiblePositionTemplate<Strategy> p = c;
- if (side == kPreviousWordIfOnBoundary) {
- if (IsStartOfParagraph(c))
- return c.DeepEquivalent();
-
- p = PreviousPositionOf(c);
- if (p.IsNull())
- return c.DeepEquivalent();
- } else if (IsEndOfParagraph(c)) {
- return c.DeepEquivalent();
- }
-
- return NextBoundary(p, EndWordBoundary);
+PositionInFlatTree EndOfWordPositionInternal(const PositionInFlatTree& position,
+ EWordSide side) {
+ class Finder final : public TextSegments::Finder {
+ STACK_ALLOCATED();
+
+ public:
+ Finder(EWordSide side) : side_(side) {}
+
+ private:
+ Position Find(const String text, unsigned offset) final {
+ DCHECK_LE(offset, text.length());
+ if (!is_first_time_)
+ return FindInternal(text, offset);
+ is_first_time_ = false;
+ if (side_ == kPreviousWordIfOnBoundary) {
+ if (offset == 0)
+ return Position::Before(0);
+ return FindInternal(text, offset - 1);
+ }
+ if (offset == text.length())
+ return Position::After(offset);
+ return FindInternal(text, offset);
+ }
+
+ static Position FindInternal(const String text, unsigned offset) {
+ DCHECK_LE(offset, text.length());
+ TextBreakIterator* it =
+ WordBreakIterator(text.Characters16(), text.length());
+ const int result = it->following(offset);
+ if (result == kTextBreakDone || result == 0)
+ return Position();
+ return Position::After(result - 1);
+ }
+
+ const EWordSide side_;
+ bool is_first_time_ = true;
+ } finder(side);
+ return TextSegments::FindBoundaryForward(position, &finder);
}
PositionInFlatTree NextWordPositionInternal(
const PositionInFlatTree& position) {
- DCHECK(position.IsNotNull());
- PositionInFlatTree last_position = position;
- for (const auto& inline_contents :
- TextOffsetMapping::ForwardRangeOf(position)) {
- const TextOffsetMapping mapping(inline_contents);
- const String text = mapping.GetText();
- const int offset =
- last_position == position ? mapping.ComputeTextOffset(position) : 0;
- const int word_end =
- FindNextWordForward(text.Characters16(), text.length(), offset);
- if (offset < word_end)
- return mapping.GetPositionAfter(word_end);
- last_position = mapping.GetRange().EndPosition();
- }
- return last_position;
+ class Finder final : public TextSegments::Finder {
+ STACK_ALLOCATED();
+
+ private:
+ Position Find(const String text, unsigned offset) final {
+ DCHECK_LE(offset, text.length());
+ if (offset == text.length() || text.length() == 0)
+ return Position();
+ TextBreakIterator* it =
+ WordBreakIterator(text.Characters16(), text.length());
+ for (int runner = it->following(offset); runner != kTextBreakDone;
+ runner = it->following(runner)) {
+ // We stop searching when the character preceding the break is
+ // alphanumeric or underscore.
+ if (static_cast<unsigned>(runner) < text.length() &&
+ (WTF::Unicode::IsAlphanumeric(text[runner - 1]) ||
+ text[runner - 1] == kLowLineCharacter))
+ return Position::After(runner - 1);
+ }
+ return Position::After(text.length() - 1);
+ }
+ } finder;
+ return TextSegments::FindBoundaryForward(position, &finder);
}
unsigned PreviousWordPositionBoundary(
@@ -153,24 +165,31 @@ PositionTemplate<Strategy> StartOfWordAlgorithm(
} // namespace
-Position EndOfWordPosition(const VisiblePosition& position, EWordSide side) {
- return EndOfWordAlgorithm<EditingStrategy>(position, side);
+PositionInFlatTree EndOfWordPosition(const PositionInFlatTree& start,
+ EWordSide side) {
+ return AdjustForwardPositionToAvoidCrossingEditingBoundaries(
+ PositionInFlatTreeWithAffinity(
+ EndOfWordPositionInternal(start, side)),
+ start)
+ .GetPosition();
}
-VisiblePosition EndOfWord(const VisiblePosition& position, EWordSide side) {
- return CreateVisiblePosition(EndOfWordPosition(position, side),
- TextAffinity::kUpstreamIfPossible);
+Position EndOfWordPosition(const Position& position, EWordSide side) {
+ return ToPositionInDOMTree(
+ EndOfWordPosition(ToPositionInFlatTree(position), side));
}
-PositionInFlatTree EndOfWordPosition(const VisiblePositionInFlatTree& position,
- EWordSide side) {
- return EndOfWordAlgorithm<EditingInFlatTreeStrategy>(position, side);
+VisiblePosition EndOfWord(const VisiblePosition& position, EWordSide side) {
+ return CreateVisiblePosition(
+ EndOfWordPosition(position.DeepEquivalent(), side),
+ TextAffinity::kUpstreamIfPossible);
}
VisiblePositionInFlatTree EndOfWord(const VisiblePositionInFlatTree& position,
EWordSide side) {
- return CreateVisiblePosition(EndOfWordPosition(position, side),
- TextAffinity::kUpstreamIfPossible);
+ return CreateVisiblePosition(
+ EndOfWordPosition(position.DeepEquivalent(), side),
+ TextAffinity::kUpstreamIfPossible);
}
// ----
diff --git a/chromium/third_party/blink/renderer/core/editing/visible_units_word_test.cc b/chromium/third_party/blink/renderer/core/editing/visible_units_word_test.cc
index cc32dc1e3c3..bf68bf269ed 100644
--- a/chromium/third_party/blink/renderer/core/editing/visible_units_word_test.cc
+++ b/chromium/third_party/blink/renderer/core/editing/visible_units_word_test.cc
@@ -241,7 +241,7 @@ TEST_F(VisibleUnitsWordTest, StartOfWordTextSecurity) {
EXPECT_EQ("|abc<s>foo bar</s>baz", DoStartOfWord("abc<s>foo bar</s>b|az"));
}
-TEST_F(VisibleUnitsWordTest, EndOfWordBasic) {
+TEST_P(ParameterizedVisibleUnitsWordTest, EndOfWordBasic) {
EXPECT_EQ("<p> (|1) abc def</p>", DoEndOfWord("<p>| (1) abc def</p>"));
EXPECT_EQ("<p> (|1) abc def</p>", DoEndOfWord("<p> |(1) abc def</p>"));
EXPECT_EQ("<p> (1|) abc def</p>", DoEndOfWord("<p> (|1) abc def</p>"));
@@ -258,7 +258,8 @@ TEST_F(VisibleUnitsWordTest, EndOfWordBasic) {
EXPECT_EQ("<p> (1) abc def|</p>", DoEndOfWord("<p> (1) abc def</p>|"));
}
-TEST_F(VisibleUnitsWordTest, EndOfWordPreviousWordIfOnBoundaryBasic) {
+TEST_P(ParameterizedVisibleUnitsWordTest,
+ EndOfWordPreviousWordIfOnBoundaryBasic) {
EXPECT_EQ("<p> |(1) abc def</p>",
DoEndOfWord("<p>| (1) abc def</p>",
EWordSide::kPreviousWordIfOnBoundary));
@@ -303,7 +304,7 @@ TEST_F(VisibleUnitsWordTest, EndOfWordPreviousWordIfOnBoundaryBasic) {
EWordSide::kPreviousWordIfOnBoundary));
}
-TEST_F(VisibleUnitsWordTest, EndOfWordShadowDOM) {
+TEST_P(ParameterizedVisibleUnitsWordTest, EndOfWordShadowDOM) {
const char* body_content =
"<a id=host><b id=one>1</b> <b id=two>22</b></a><i id=three>333</i>";
const char* shadow_content =
@@ -319,28 +320,28 @@ TEST_F(VisibleUnitsWordTest, EndOfWordShadowDOM) {
Node* five = shadow_root->getElementById("five")->firstChild();
EXPECT_EQ(
- Position(three, 3),
+ Position(five, 5),
EndOfWord(CreateVisiblePositionInDOMTree(*one, 0)).DeepEquivalent());
EXPECT_EQ(
PositionInFlatTree(five, 5),
EndOfWord(CreateVisiblePositionInFlatTree(*one, 0)).DeepEquivalent());
EXPECT_EQ(
- Position(three, 3),
+ Position(five, 5),
EndOfWord(CreateVisiblePositionInDOMTree(*one, 1)).DeepEquivalent());
EXPECT_EQ(
PositionInFlatTree(five, 5),
EndOfWord(CreateVisiblePositionInFlatTree(*one, 1)).DeepEquivalent());
EXPECT_EQ(
- Position(three, 3),
+ Position(five, 5),
EndOfWord(CreateVisiblePositionInDOMTree(*two, 0)).DeepEquivalent());
EXPECT_EQ(
PositionInFlatTree(two, 2),
EndOfWord(CreateVisiblePositionInFlatTree(*two, 0)).DeepEquivalent());
EXPECT_EQ(
- Position(three, 3),
+ Position(two, 2),
EndOfWord(CreateVisiblePositionInDOMTree(*two, 1)).DeepEquivalent());
EXPECT_EQ(
PositionInFlatTree(two, 2),
@@ -354,7 +355,7 @@ TEST_F(VisibleUnitsWordTest, EndOfWordShadowDOM) {
EndOfWord(CreateVisiblePositionInFlatTree(*three, 1)).DeepEquivalent());
EXPECT_EQ(
- Position(four, 5),
+ Position(two, 2),
EndOfWord(CreateVisiblePositionInDOMTree(*four, 1)).DeepEquivalent());
EXPECT_EQ(
PositionInFlatTree(two, 2),
@@ -368,7 +369,7 @@ TEST_F(VisibleUnitsWordTest, EndOfWordShadowDOM) {
EndOfWord(CreateVisiblePositionInFlatTree(*five, 1)).DeepEquivalent());
}
-TEST_F(VisibleUnitsWordTest, EndOfWordTextSecurity) {
+TEST_P(ParameterizedVisibleUnitsWordTest, EndOfWordTextSecurity) {
// Note: |EndOfWord()| considers security characters as a sequence "x".
InsertStyleElement("s {-webkit-text-security:disc;}");
EXPECT_EQ("abc<s>foo bar</s>baz|", DoEndOfWord("|abc<s>foo bar</s>baz"));
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 4c2f665f92e..0e95a9a6bc9 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
@@ -37,7 +37,6 @@
#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_local_frame.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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.h"
@@ -143,7 +142,7 @@ NSAttributedString* AttributedSubstringFromRange(const EphemeralRange& range,
WebPoint GetBaselinePoint(LocalFrameView* frame_view,
const EphemeralRange& range,
NSAttributedString* string) {
- IntRect string_rect = frame_view->ContentsToViewport(ComputeTextRect(range));
+ IntRect string_rect = frame_view->FrameToViewport(ComputeTextRect(range));
IntPoint string_point = string_rect.MinXMaxYCorner();
// Adjust for the font's descender. AppKit wants the baseline point.
diff --git a/chromium/third_party/blink/renderer/core/events/BUILD.gn b/chromium/third_party/blink/renderer/core/events/BUILD.gn
index f10dfae27e4..b1a771baa0a 100644
--- a/chromium/third_party/blink/renderer/core/events/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/events/BUILD.gn
@@ -48,6 +48,8 @@ blink_core_sources("events") {
"navigator_events.h",
"page_transition_event.cc",
"page_transition_event.h",
+ "picture_in_picture_control_event.cc",
+ "picture_in_picture_control_event.h",
"pointer_event.cc",
"pointer_event.h",
"pointer_event_factory.cc",
diff --git a/chromium/third_party/blink/renderer/core/events/current_input_event.h b/chromium/third_party/blink/renderer/core/events/current_input_event.h
index b8ad887a713..149b6a43931 100644
--- a/chromium/third_party/blink/renderer/core/events/current_input_event.h
+++ b/chromium/third_party/blink/renderer/core/events/current_input_event.h
@@ -5,13 +5,13 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_CURRENT_INPUT_EVENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_CURRENT_INPUT_EVENT_H_
+#include "third_party/blink/renderer/core/core_export.h"
+
namespace blink {
-class WebFrameWidgetImpl;
class WebInputEvent;
-class WebViewImpl;
-class CurrentInputEvent {
+class CORE_EXPORT CurrentInputEvent {
public:
// Gets the "current" input event - event that is currently being processed by
// either blink::WebViewImpl::HandleInputEventInternal or by
@@ -21,6 +21,8 @@ class CurrentInputEvent {
private:
friend class WebViewImpl;
friend class WebFrameWidgetImpl;
+ friend class NavigationPolicyTest;
+
static const WebInputEvent* current_input_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 77b983639e2..52507abfb98 100644
--- a/chromium/third_party/blink/renderer/core/events/error_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/error_event.cc
@@ -95,12 +95,8 @@ ScriptValue ErrorEvent::error(ScriptState* script_state) const {
}
void ErrorEvent::Trace(blink::Visitor* visitor) {
+ visitor->Trace(error_);
Event::Trace(visitor);
}
-void ErrorEvent::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(error_);
- Event::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/events/error_event.h b/chromium/third_party/blink/renderer/core/events/error_event.h
index 7e51be41829..a18243e50b6 100644
--- a/chromium/third_party/blink/renderer/core/events/error_event.h
+++ b/chromium/third_party/blink/renderer/core/events/error_event.h
@@ -94,7 +94,6 @@ class ErrorEvent final : public Event {
void SetUnsanitizedMessage(const String&);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
ErrorEvent();
diff --git a/chromium/third_party/blink/renderer/core/events/event_target_names.json5 b/chromium/third_party/blink/renderer/core/events/event_target_names.json5
index 8101a2eeced..6aab6842f93 100644
--- a/chromium/third_party/blink/renderer/core/events/event_target_names.json5
+++ b/chromium/third_party/blink/renderer/core/events/event_target_names.json5
@@ -5,11 +5,11 @@
},
data: [
+ "core/accessibility/AccessibleNode",
"core/animation/Animation",
"core/clipboard/Clipboard",
"core/css/FontFaceSet",
"core/css/MediaQueryList",
- "core/dom/AccessibleNode",
"core/dom/BroadcastChannel",
"core/dom/MessagePort",
"core/dom/Node",
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 50a3684f31f..959a71466f7 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
@@ -193,6 +193,7 @@
"pause",
"paymentrequest",
"periodicsync",
+ "pictureinpicturecontrolclick",
"play",
"playing",
"pointercancel",
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 ab0aee9e7ce..c098abda392 100644
--- a/chromium/third_party/blink/renderer/core/events/message_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/message_event.cc
@@ -28,9 +28,9 @@
#include "third_party/blink/renderer/core/events/message_event.h"
#include <memory>
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+
#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/events/mouse_event.cc b/chromium/third_party/blink/renderer/core/events/mouse_event.cc
index b2086af5326..a4ab1280f78 100644
--- a/chromium/third_party/blink/renderer/core/events/mouse_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/mouse_event.cc
@@ -33,6 +33,7 @@
#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/paint/paint_layer.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
@@ -47,8 +48,7 @@ DoubleSize ContentsScrollOffset(AbstractView* abstract_view) {
LocalFrame* frame = ToLocalDOMWindow(abstract_view)->GetFrame();
if (!frame)
return DoubleSize();
- ScrollableArea* scrollable_area =
- frame->View()->LayoutViewportScrollableArea();
+ ScrollableArea* scrollable_area = frame->View()->LayoutViewport();
if (!scrollable_area)
return DoubleSize();
float scale_factor = frame->PageZoomFactor();
@@ -223,12 +223,10 @@ void MouseEvent::SetCoordinatesFromWebPointerProperties(
float scale_factor = 1.0f;
if (dom_window && dom_window->GetFrame() && dom_window->GetFrame()->View()) {
LocalFrame* frame = dom_window->GetFrame();
- FloatPoint page_point = frame->View()->RootFrameToContents(
+ FloatPoint page_point = frame->View()->ConvertFromRootFrame(
web_pointer_properties.PositionInWidget());
scale_factor = 1.0f / frame->PageZoomFactor();
- FloatPoint scroll_position(frame->View()->GetScrollOffset());
client_point = page_point.ScaledBy(scale_factor);
- client_point.MoveBy(scroll_position.ScaledBy(-scale_factor));
}
initializer.setScreenX(web_pointer_properties.PositionInScreen().x);
@@ -454,8 +452,7 @@ void MouseEvent::ComputePageLocation() {
DoublePoint scaled_page_location =
page_location_.ScaledBy(PageZoomFactor(this));
if (frame && frame->View()) {
- absolute_location_ =
- frame->View()->DocumentToAbsolute(scaled_page_location);
+ absolute_location_ = frame->View()->DocumentToFrame(scaled_page_location);
} else {
absolute_location_ = scaled_page_location;
}
@@ -509,7 +506,7 @@ void MouseEvent::ComputeRelativePosition() {
DoublePoint scaled_page_location =
page_location_.ScaledBy(PageZoomFactor(this));
if (LocalFrameView* view = n->GetLayoutObject()->View()->GetFrameView())
- layer_location_ = view->DocumentToAbsolute(scaled_page_location);
+ layer_location_ = view->DocumentToFrame(scaled_page_location);
// FIXME: This logic is a wrong implementation of convertToLayerCoords.
for (PaintLayer* layer = n->GetLayoutObject()->EnclosingLayer(); layer;
diff --git a/chromium/third_party/blink/renderer/core/events/picture_in_picture_control_event.cc b/chromium/third_party/blink/renderer/core/events/picture_in_picture_control_event.cc
new file mode 100644
index 00000000000..6c37f141f1f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/events/picture_in_picture_control_event.cc
@@ -0,0 +1,38 @@
+// 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/events/picture_in_picture_control_event.h"
+
+namespace blink {
+
+PictureInPictureControlEvent* PictureInPictureControlEvent::Create(
+ const AtomicString& type,
+ String id) {
+ return new PictureInPictureControlEvent(type, id);
+}
+
+PictureInPictureControlEvent* PictureInPictureControlEvent::Create(
+ const AtomicString& type,
+ const PictureInPictureControlEventInit& initializer) {
+ return new PictureInPictureControlEvent(type, initializer);
+}
+
+String PictureInPictureControlEvent::id() const {
+ return id_;
+}
+void PictureInPictureControlEvent::setId(String id) {
+ id_ = id;
+}
+
+PictureInPictureControlEvent::PictureInPictureControlEvent(
+ AtomicString const& type,
+ String id)
+ : Event(type, Bubbles::kYes, Cancelable::kNo), id_(id) {}
+
+PictureInPictureControlEvent::PictureInPictureControlEvent(
+ AtomicString const& type,
+ const PictureInPictureControlEventInit& initializer)
+ : Event(type, initializer), id_(initializer.id()) {}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/events/picture_in_picture_control_event.h b/chromium/third_party/blink/renderer/core/events/picture_in_picture_control_event.h
new file mode 100644
index 00000000000..199c2bbfb39
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/events/picture_in_picture_control_event.h
@@ -0,0 +1,40 @@
+// 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_EVENTS_PICTURE_IN_PICTURE_CONTROL_EVENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_PICTURE_IN_PICTURE_CONTROL_EVENT_H_
+
+#include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/events/picture_in_picture_control_event_init.h"
+
+namespace blink {
+
+// A PictureInPictureControlEvent is a subclass of Event with an additional
+// string. This string is used to convey to the browser the name of a custom
+// control on a Picture in Picture window.
+class CORE_EXPORT PictureInPictureControlEvent final : public Event {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static PictureInPictureControlEvent* Create(const AtomicString&, String);
+ static PictureInPictureControlEvent* Create(
+ const AtomicString&,
+ const PictureInPictureControlEventInit&);
+
+ String id() const;
+ void setId(String id);
+
+ private:
+ PictureInPictureControlEvent(AtomicString const&, String);
+ PictureInPictureControlEvent(AtomicString const&,
+ const PictureInPictureControlEventInit&);
+
+ // id_ holds the id of a PictureIncPictureControlEvent, which is used to
+ // convey which custom control fired the event by being clicked.
+ String id_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_PICTURE_IN_PICTURE_CONTROL_EVENT_H_
diff --git a/chromium/third_party/blink/renderer/core/events/picture_in_picture_control_event.idl b/chromium/third_party/blink/renderer/core/events/picture_in_picture_control_event.idl
new file mode 100644
index 00000000000..550f1e697cc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/events/picture_in_picture_control_event.idl
@@ -0,0 +1,11 @@
+// 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.
+
+[
+ RuntimeEnabled=PictureInPictureControl,
+ Constructor(DOMString type, PictureInPictureControlEventInit eventInitDict)
+]
+interface PictureInPictureControlEvent : Event {
+ attribute DOMString id;
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/events/picture_in_picture_control_event_init.idl b/chromium/third_party/blink/renderer/core/events/picture_in_picture_control_event_init.idl
new file mode 100644
index 00000000000..a34e0a4c1d0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/events/picture_in_picture_control_event_init.idl
@@ -0,0 +1,7 @@
+// 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.
+
+dictionary PictureInPictureControlEventInit : EventInit {
+ required DOMString id;
+}; \ No newline at end of file
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 64bfd195d8c..f3e68551981 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
@@ -192,14 +192,6 @@ PointerEvent* PointerEventFactory::Create(
SetIdTypeButtons(pointer_event_init, web_pointer_event);
AtomicString type = PointerEventNameForEventType(event_type);
- // Make sure chorded buttons fire pointermove instead of pointerup/down.
- if ((event_type == WebInputEvent::kPointerDown &&
- (pointer_event_init.buttons() &
- ~ButtonToButtonsBitfield(web_pointer_event.button)) != 0) ||
- (event_type == WebInputEvent::kPointerUp &&
- pointer_event_init.buttons() != 0))
- type = EventTypeNames::pointermove;
-
if (event_type == WebInputEvent::kPointerDown ||
event_type == WebInputEvent::kPointerUp) {
WebPointerProperties::Button button = web_pointer_event.button;
@@ -209,6 +201,14 @@ PointerEvent* PointerEventFactory::Create(
button == WebPointerProperties::Button::kLeft)
button = WebPointerProperties::Button::kEraser;
pointer_event_init.setButton(static_cast<int>(button));
+
+ // Make sure chorded buttons fire pointermove instead of pointerup/down.
+ if ((event_type == WebInputEvent::kPointerDown &&
+ (pointer_event_init.buttons() & ~ButtonToButtonsBitfield(button)) !=
+ 0) ||
+ (event_type == WebInputEvent::kPointerUp &&
+ pointer_event_init.buttons() != 0))
+ type = EventTypeNames::pointermove;
} else {
pointer_event_init.setButton(
static_cast<int>(WebPointerProperties::Button::kNoButton));
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 0fceeb98cc5..0cea2c45d27 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
@@ -25,6 +25,7 @@ const char* PointerTypeNameForWebPointPointerType(
case WebPointerProperties::PointerType::kTouch:
return "touch";
case WebPointerProperties::PointerType::kPen:
+ case WebPointerProperties::PointerType::kEraser:
return "pen";
case WebPointerProperties::PointerType::kMouse:
return "mouse";
@@ -50,6 +51,8 @@ class PointerEventFactoryTest : public testing::Test {
bool hovering,
WebInputEvent::Modifiers modifiers = WebInputEvent::kNoModifiers,
WebInputEvent::Type type = WebInputEvent::kPointerDown,
+ WebPointerProperties::Button button =
+ WebPointerProperties::Button::kNoButton,
size_t coalesced_event_count = 0) {
WebPointerEvent web_pointer_event;
web_pointer_event.pointer_type = pointer_type;
@@ -59,6 +62,7 @@ class PointerEventFactoryTest : public testing::Test {
web_pointer_event.SetModifiers(modifiers);
web_pointer_event.force = 1.0;
web_pointer_event.hovering = hovering;
+ web_pointer_event.button = button;
Vector<WebPointerEvent> coalesced_events;
for (size_t i = 0; i < coalesced_event_count; i++) {
coalesced_events.push_back(web_pointer_event);
@@ -527,11 +531,47 @@ TEST_F(PointerEventFactoryTest, CoalescedEvents) {
CreateAndCheckWebPointerEvent(
WebPointerProperties::PointerType::kMouse, 0, expected_mouse_id_,
true /* isprimary */, true /* hovering */, WebInputEvent::kNoModifiers,
- WebInputEvent::kPointerMove, 4);
+ WebInputEvent::kPointerMove, WebPointerProperties::Button::kNoButton, 4);
CreateAndCheckWebPointerEvent(
WebPointerProperties::PointerType::kTouch, 0, mapped_id_start_,
true /* isprimary */, false /* hovering */, WebInputEvent::kNoModifiers,
- WebInputEvent::kPointerMove, 3);
+ WebInputEvent::kPointerMove, WebPointerProperties::Button::kNoButton, 3);
+}
+
+TEST_F(PointerEventFactoryTest, PenEraserButton) {
+ // Send the pointerdown event when pressing the eraser button on the tablet.
+ PointerEvent* first_pointerdown_event = CreateAndCheckWebPointerEvent(
+ WebPointerProperties::PointerType::kEraser, 0, mapped_id_start_,
+ true /* isprimary */, false /* hovering */,
+ WebInputEvent::kLeftButtonDown, WebInputEvent::kPointerDown,
+ WebPointerProperties::Button::kLeft);
+ EXPECT_EQ(EventTypeNames::pointerdown, first_pointerdown_event->type());
+
+ // Send the pointermove event when pressing any other button while the eraser
+ // button is still pressed on the tablet.
+ WebInputEvent::Modifiers modifiers = static_cast<WebInputEvent::Modifiers>(
+ WebInputEvent::kLeftButtonDown | WebInputEvent::kRightButtonDown);
+ PointerEvent* second_pointerdown_event = CreateAndCheckWebPointerEvent(
+ WebPointerProperties::PointerType::kEraser, 1, mapped_id_start_ + 1,
+ false /* isprimary */, false /* hovering */, modifiers,
+ WebInputEvent::kPointerDown, WebPointerProperties::Button::kRight);
+ EXPECT_EQ(EventTypeNames::pointermove, second_pointerdown_event->type());
+
+ // Send the pointermove event when releasing any other button while the
+ // eraser button is still pressed on the tablet.
+ PointerEvent* first_pointerup_event = CreateAndCheckWebPointerEvent(
+ WebPointerProperties::PointerType::kEraser, 1, mapped_id_start_ + 1,
+ false /* isprimary */, true /* hovering */,
+ WebInputEvent::kLeftButtonDown, WebInputEvent::kPointerUp,
+ WebPointerProperties::Button::kRight);
+ EXPECT_EQ(EventTypeNames::pointermove, first_pointerup_event->type());
+
+ // Send the pointerup event when releasing the eraser button from the tablet.
+ PointerEvent* last_pointerup_event = CreateAndCheckWebPointerEvent(
+ WebPointerProperties::PointerType::kEraser, 0, mapped_id_start_,
+ true /* isprimary */, true /* hovering */, WebInputEvent::kNoModifiers,
+ WebInputEvent::kPointerUp, WebPointerProperties::Button::kLeft);
+ EXPECT_EQ(EventTypeNames::pointerup, last_pointerup_event->type());
}
} // namespace blink
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 b03d50ce143..ceb416a9e57 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
@@ -47,7 +47,7 @@ PopStateEvent::PopStateEvent(ScriptState* script_state,
PopStateEvent::PopStateEvent(
scoped_refptr<SerializedScriptValue> serialized_state,
History* history)
- : Event(EventTypeNames::popstate, Bubbles::kNo, Cancelable::kYes),
+ : Event(EventTypeNames::popstate, Bubbles::kNo, Cancelable::kNo),
serialized_state_(std::move(serialized_state)),
history_(history) {}
@@ -83,18 +83,20 @@ PopStateEvent* PopStateEvent::Create(ScriptState* script_state,
return new PopStateEvent(script_state, type, initializer);
}
+void PopStateEvent::SetSerializedState(
+ scoped_refptr<SerializedScriptValue> state) {
+ DCHECK(!serialized_state_);
+ serialized_state_ = std::move(state);
+}
+
const AtomicString& PopStateEvent::InterfaceName() const {
return EventNames::PopStateEvent;
}
void PopStateEvent::Trace(blink::Visitor* visitor) {
+ visitor->Trace(state_);
visitor->Trace(history_);
Event::Trace(visitor);
}
-void PopStateEvent::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(state_);
- Event::TraceWrappers(visitor);
-}
-
} // namespace blink
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 3a1f2cbe695..67ed13212bb 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
@@ -53,18 +53,13 @@ class PopStateEvent final : public Event {
SerializedScriptValue* SerializedState() const {
return serialized_state_.get();
}
- void SetSerializedState(scoped_refptr<SerializedScriptValue> state) {
- DCHECK(!serialized_state_);
- serialized_state_ = std::move(state);
- }
+ void SetSerializedState(scoped_refptr<SerializedScriptValue> state);
History* GetHistory() const { return history_.Get(); }
const AtomicString& InterfaceName() const override;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
private:
PopStateEvent();
PopStateEvent(ScriptState*, const AtomicString&, const PopStateEventInit&);
diff --git a/chromium/third_party/blink/renderer/core/events/promise_rejection_event.cc b/chromium/third_party/blink/renderer/core/events/promise_rejection_event.cc
index a8456f79186..885728339a5 100644
--- a/chromium/third_party/blink/renderer/core/events/promise_rejection_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/promise_rejection_event.cc
@@ -60,14 +60,9 @@ bool PromiseRejectionEvent::CanBeDispatchedInWorld(
}
void PromiseRejectionEvent::Trace(blink::Visitor* visitor) {
+ visitor->Trace(promise_);
+ visitor->Trace(reason_);
Event::Trace(visitor);
}
-void PromiseRejectionEvent::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(promise_);
- visitor->TraceWrappers(reason_);
- Event::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/events/promise_rejection_event.h b/chromium/third_party/blink/renderer/core/events/promise_rejection_event.h
index 4f3dab9ea58..3a7997f222e 100644
--- a/chromium/third_party/blink/renderer/core/events/promise_rejection_event.h
+++ b/chromium/third_party/blink/renderer/core/events/promise_rejection_event.h
@@ -39,8 +39,6 @@ class CORE_EXPORT PromiseRejectionEvent final : public Event {
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
private:
PromiseRejectionEvent(ScriptState*,
const AtomicString&,
diff --git a/chromium/third_party/blink/renderer/core/events/registered_event_listener.h b/chromium/third_party/blink/renderer/core/events/registered_event_listener.h
index 40951d3575e..c2b0157bd17 100644
--- a/chromium/third_party/blink/renderer/core/events/registered_event_listener.h
+++ b/chromium/third_party/blink/renderer/core/events/registered_event_listener.h
@@ -56,9 +56,6 @@ class RegisteredEventListener final {
passive_specified_(options.PassiveSpecified()) {}
void Trace(blink::Visitor* visitor) { visitor->Trace(callback_); }
- void TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(callback_);
- }
AddEventListenerOptionsResolved Options() const {
AddEventListenerOptionsResolved result;
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 c4202fa9cb2..4cc304c7fa5 100644
--- a/chromium/third_party/blink/renderer/core/events/touch_event.cc
+++ b/chromium/third_party/blink/renderer/core/events/touch_event.cc
@@ -36,6 +36,7 @@
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/input/input_device_capabilities.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/histogram.h"
@@ -181,7 +182,7 @@ void LogTouchTargetHistogram(EventTarget* event_target,
if (document) {
LocalFrameView* view = document->View();
- if (view && view->IsScrollable())
+ if (view && view->LayoutViewport()->ScrollsOverflow())
result += kTouchTargetHistogramScrollableDocumentOffset;
}
@@ -263,11 +264,13 @@ void TouchEvent::preventDefault() {
// A common developer error is to wait too long before attempting to stop
// scrolling by consuming a touchmove event. Generate an error if this
// event is uncancelable.
+ String id;
String message;
switch (HandlingPassive()) {
case PassiveMode::kNotPassive:
case PassiveMode::kNotPassiveDefault:
if (!cancelable()) {
+ id = "IgnoredEventCancel";
message = "Ignored attempt to cancel a " + type() +
" event with cancelable=false, for example "
"because scrolling is in progress and "
@@ -279,6 +282,7 @@ void TouchEvent::preventDefault() {
// an author may use touch action but call preventDefault for interop with
// browsers that don't support touch-action.
if (current_touch_action_ == TouchAction::kTouchActionAuto) {
+ id = "PreventDefaultPassive";
message =
"Unable to preventDefault inside passive event listener due to "
"target being treated as passive. See "
@@ -291,7 +295,8 @@ void TouchEvent::preventDefault() {
if (!message.IsEmpty() && view() && view()->IsLocalDOMWindow() &&
view()->GetFrame()) {
- Intervention::GenerateReport(ToLocalDOMWindow(view())->GetFrame(), message);
+ Intervention::GenerateReport(ToLocalDOMWindow(view())->GetFrame(), id,
+ message);
}
if ((type() == EventTypeNames::touchstart ||
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 e4aec9f8ff2..c7e9b86989f 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
@@ -51,6 +51,7 @@ class TouchEventTest : public PageTestBase {
FillWithEmptyClients(clients);
clients.chrome_client = chrome_client_.Get();
SetupPageWithClients(&clients);
+ Page::InsertOrdinaryPageForTesting(&GetPage());
}
const std::vector<String>& Messages() { return chrome_client_->Messages(); }
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 4228d85ae1c..ad20d875ffe 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
@@ -96,7 +96,7 @@ void UpdateWebMouseEventFromCoreMouseEvent(const MouseEvent& event,
event.AbsoluteLocation().Y());
if (plugin_parent) {
point_in_root_frame =
- plugin_parent->ContentsToRootFrame(point_in_root_frame);
+ plugin_parent->ConvertToRootFrame(point_in_root_frame);
}
web_event.SetPositionInScreen(event.screenX(), event.screenY());
FloatPoint local_point = ConvertAbsoluteLocationForLayoutObjectFloat(
@@ -281,7 +281,7 @@ WebMouseEventBuilder::WebMouseEventBuilder(const LocalFrameView* plugin_parent,
IntPoint point_in_root_frame = RoundedIntPoint(touch->AbsoluteLocation());
if (plugin_parent) {
point_in_root_frame =
- plugin_parent->AbsoluteToRootFrame(point_in_root_frame);
+ plugin_parent->ConvertToRootFrame(point_in_root_frame);
}
FloatPoint screen_point = touch->ScreenLocation();
SetPositionInScreen(screen_point.X(), screen_point.Y());
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 cc4bc44e525..7e641e35681 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
@@ -642,7 +642,7 @@ TEST(WebInputEventConversionTest, VisualViewportOffset) {
web_view->SetPageScaleFactor(2);
- IntPoint visual_offset(35, 60);
+ FloatPoint visual_offset(35, 60);
web_view->GetPage()->GetVisualViewport().SetLocation(visual_offset);
LocalFrameView* view = ToLocalFrame(web_view->GetPage()->MainFrame())->View();
@@ -773,7 +773,7 @@ TEST(WebInputEventConversionTest, ElasticOverscroll) {
// pinch-zoom).
float page_scale = 2;
web_view->SetPageScaleFactor(page_scale);
- IntPoint visual_offset(35, 60);
+ FloatPoint visual_offset(35, 60);
web_view->GetPage()->GetVisualViewport().SetLocation(visual_offset);
{
WebMouseEvent web_mouse_event(WebInputEvent::kMouseMove,
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 5ebfbd8be84..34fda803b0c 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
@@ -202,7 +202,12 @@ bool ExecutionContext::IsSecureContext() const {
return IsSecureContext(unused_error_message);
}
+// https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer
String ExecutionContext::OutgoingReferrer() const {
+ // Step 3.1: "If environment's global object is a Window object, then"
+ // This case is implemented in Document::OutgoingReferrer().
+
+ // Step 3.2: "Otherwise, let referrerSource be environment's creation URL."
return Url().StrippedForUseAsReferrer();
}
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 dd52e3d3db6..8c0d54536d0 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
@@ -32,18 +32,19 @@
#include "base/location.h"
#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_notifier.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
-#include "third_party/blink/renderer/core/execution_context/security_context.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/access_control_status.h"
#include "third_party/blink/renderer/platform/supplementable.h"
-#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/referrer_policy.h"
#include "v8/include/v8.h"
+namespace base {
+class SingleThreadTaskRunner;
+}
+
namespace service_manager {
class InterfaceProvider;
}
@@ -51,17 +52,19 @@ class InterfaceProvider;
namespace blink {
class ConsoleMessage;
+class ContentSecurityPolicy;
class CoreProbeSink;
class DOMTimerCoordinator;
class ErrorEvent;
-class EventQueue;
class EventTarget;
class FrameOrWorkerScheduler;
class InterfaceInvalidator;
+class KURL;
class LocalDOMWindow;
class PausableObject;
class PublicURLManager;
class ResourceFetcher;
+class SecurityContext;
class SecurityOrigin;
class ScriptState;
@@ -190,7 +193,6 @@ class CORE_EXPORT ExecutionContext : public ContextLifecycleNotifier,
int CircularSequentialID();
virtual EventTarget* ErrorEventTarget() = 0;
- virtual EventQueue* GetEventQueue() const = 0;
// Methods related to window interaction. It should be used to manage window
// focusing and window creation permission for an ExecutionContext.
@@ -208,7 +210,11 @@ class CORE_EXPORT ExecutionContext : public ContextLifecycleNotifier,
: SecureContextMode::kInsecureContext;
}
+ // Returns a referrer to be used in the "Determine request's Referrer"
+ // algorithm defined in the Referrer Policy spec.
+ // https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer
virtual String OutgoingReferrer() const;
+
// Parses a comma-separated list of referrer policy tokens, and sets
// the context's referrer policy to the last one that is a valid
// policy. Logs a message to the console if none of the policy
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 42d96d15ede..1ec0c650c8b 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
@@ -104,6 +104,13 @@ String SecurityContext::addressSpaceForBindings() const {
return "public";
}
+void SecurityContext::SetFeaturePolicy(
+ std::unique_ptr<FeaturePolicy> feature_policy) {
+ // This method should be called before a FeaturePolicy has been created.
+ DCHECK(!feature_policy_);
+ feature_policy_ = std::move(feature_policy);
+}
+
void SecurityContext::InitializeFeaturePolicy(
const ParsedFeaturePolicy& parsed_header,
const ParsedFeaturePolicy& container_policy,
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 83a8a369a46..195a58dfdaf 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
@@ -29,23 +29,27 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/public/common/feature_policy/feature_policy.h"
-#include "third_party/blink/public/mojom/net/ip_address_space.mojom-blink.h"
#include "third_party/blink/public/platform/web_insecure_request_policy.h"
-#include "third_party/blink/public/platform/web_url_request.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/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include <memory>
namespace blink {
-class SecurityOrigin;
class ContentSecurityPolicy;
+class FeaturePolicy;
+class SecurityOrigin;
+struct ParsedFeaturePolicyDeclaration;
+
+using ParsedFeaturePolicy = std::vector<ParsedFeaturePolicyDeclaration>;
+
+namespace mojom {
+enum class IPAddressSpace : int32_t;
+}
// Defines the security properties (such as the security origin, content
// security policy, and other restrictions) of an environment in which
@@ -79,7 +83,12 @@ class CORE_EXPORT SecurityContext : public GarbageCollectedMixin {
virtual void DidUpdateSecurityOrigin() = 0;
SandboxFlags GetSandboxFlags() const { return sandbox_flags_; }
- bool IsSandboxed(SandboxFlags mask) const { return sandbox_flags_ & mask; }
+ bool IsSandboxed(SandboxFlags mask) const {
+ return IsSandboxed(mask, sandbox_flags_);
+ }
+ static bool IsSandboxed(SandboxFlags mask, SandboxFlags sandbox_flags) {
+ return sandbox_flags & mask;
+ }
virtual void EnforceSandboxFlags(SandboxFlags mask);
void SetAddressSpace(mojom::IPAddressSpace space) { address_space_ = space; }
@@ -109,6 +118,7 @@ class CORE_EXPORT SecurityContext : public GarbageCollectedMixin {
}
FeaturePolicy* GetFeaturePolicy() const { return feature_policy_.get(); }
+ void SetFeaturePolicy(std::unique_ptr<FeaturePolicy> feature_policy);
void InitializeFeaturePolicy(const ParsedFeaturePolicy& parsed_header,
const ParsedFeaturePolicy& container_policy,
const FeaturePolicy* parent_feature_policy);
diff --git a/chromium/third_party/blink/renderer/core/exported/BUILD.gn b/chromium/third_party/blink/renderer/core/exported/BUILD.gn
index 783e411ce34..2e6006a9738 100644
--- a/chromium/third_party/blink/renderer/core/exported/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/exported/BUILD.gn
@@ -35,7 +35,6 @@ blink_core_sources("exported") {
"web_form_element_observer_impl.cc",
"web_form_element_observer_impl.h",
"web_frame.cc",
- "web_frame_client.cc",
"web_frame_content_dumper.cc",
"web_frame_serializer.cc",
"web_heap.cc",
@@ -48,6 +47,7 @@ blink_core_sources("exported") {
"web_input_method_controller_impl.h",
"web_label_element.cc",
"web_language_detection_details.cc",
+ "web_local_frame_client.cc",
"web_memory_statistics.cc",
"web_meta_element.cc",
"web_node.cc",
@@ -71,7 +71,6 @@ blink_core_sources("exported") {
"web_searchable_form_data.cc",
"web_security_policy.cc",
"web_select_element.cc",
- "web_selection.cc",
"web_selector.cc",
"web_serialized_script_value.cc",
"web_settings_impl.cc",
diff --git a/chromium/third_party/blink/renderer/core/exported/fake_web_plugin.h b/chromium/third_party/blink/renderer/core/exported/fake_web_plugin.h
index 0a5d1596395..45ee9f92f22 100644
--- a/chromium/third_party/blink/renderer/core/exported/fake_web_plugin.h
+++ b/chromium/third_party/blink/renderer/core/exported/fake_web_plugin.h
@@ -33,6 +33,10 @@
#include "third_party/blink/public/web/web_plugin.h"
+namespace cc {
+class PaintCanvas;
+}
+
namespace blink {
class WebCoalescedInputEvent;
@@ -50,7 +54,7 @@ class FakeWebPlugin : public WebPlugin {
void Destroy() override;
bool CanProcessDrag() const override { return false; }
void UpdateAllLifecyclePhases() override {}
- void Paint(WebCanvas*, const WebRect&) override {}
+ void Paint(cc::PaintCanvas*, const WebRect&) override {}
void UpdateGeometry(const WebRect& client_rect,
const WebRect& clip_rect,
const WebRect& window_clip_rect,
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 9c999c43668..4cea1fbf477 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
@@ -34,8 +34,11 @@
#include <memory>
#include <utility>
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider_client.h"
+#include "base/time/time.h"
+#include "third_party/blink/public/common/blob/blob_utils.h"
+#include "third_party/blink/public/common/frame/user_activation_update_type.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider_client.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_application_cache_host.h"
#include "third_party/blink/public/platform/web_media_player_source.h"
@@ -49,7 +52,7 @@
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_dom_event.h"
#include "third_party/blink/public/web/web_form_element.h"
-#include "third_party/blink/public/web/web_frame_client.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_node.h"
#include "third_party/blink/public/web/web_plugin.h"
#include "third_party/blink/public/web/web_plugin_params.h"
@@ -61,7 +64,6 @@
#include "third_party/blink/renderer/core/events/current_input_event.h"
#include "third_party/blink/renderer/core/events/message_event.h"
#include "third_party/blink/renderer/core/events/mouse_event.h"
-#include "third_party/blink/renderer/core/events/ui_event_with_key_state.h"
#include "third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.h"
#include "third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h"
#include "third_party/blink/renderer/core/exported/web_document_loader_impl.h"
@@ -136,6 +138,25 @@ bool IsBackForwardNavigationInProgress(LocalFrame* local_frame) {
!local_frame->GetDocument()->LoadEventFinished();
}
+// Called after committing provisional load to reset the EventHandlerProperties.
+// Only called on local frame roots.
+void ResetWheelAndTouchEventHandlerProperties(LocalFrame& frame) {
+ // If we are loading a local root, it is important to explicitly set the event
+ // listener properties to Nothing as this triggers notifications to the
+ // client. Clients may assume the presence of handlers for touch and wheel
+ // events, so these notifications tell it there are (presently) no handlers.
+ auto& chrome_client = frame.GetPage()->GetChromeClient();
+ chrome_client.SetEventListenerProperties(
+ &frame, cc::EventListenerClass::kTouchStartOrMove,
+ cc::EventListenerProperties::kNone);
+ chrome_client.SetEventListenerProperties(&frame,
+ cc::EventListenerClass::kMouseWheel,
+ cc::EventListenerProperties::kNone);
+ chrome_client.SetEventListenerProperties(
+ &frame, cc::EventListenerClass::kTouchEndOrCancel,
+ cc::EventListenerProperties::kNone);
+}
+
} // namespace
LocalFrameClientImpl::LocalFrameClientImpl(WebLocalFrameImpl* frame)
@@ -317,17 +338,17 @@ void LocalFrameClientImpl::WillBeDetached() {
void LocalFrameClientImpl::Detached(FrameDetachType type) {
// Alert the client that the frame is being detached. This is the last
// chance we have to communicate with the client.
- WebFrameClient* client = web_frame_->Client();
+ WebLocalFrameClient* client = web_frame_->Client();
if (!client)
return;
web_frame_->WillDetachParent();
- // Signal that no further communication with WebFrameClient should take
+ // Signal that no further communication with WebLocalFrameClient should take
// place at this point since we are no longer associated with the Page.
web_frame_->SetClient(nullptr);
- client->FrameDetached(static_cast<WebFrameClient::DetachType>(type));
+ client->FrameDetached(static_cast<WebLocalFrameClient::DetachType>(type));
if (type == FrameDetachType::kRemove)
web_frame_->DetachFromParent();
@@ -338,7 +359,7 @@ void LocalFrameClientImpl::Detached(FrameDetachType type) {
}
void LocalFrameClientImpl::DispatchWillSendRequest(ResourceRequest& request) {
- // Give the WebFrameClient a crack at the request.
+ // Give the WebLocalFrameClient a crack at the request.
if (web_frame_->Client()) {
WrappedResourceRequest webreq(request);
web_frame_->Client()->WillSendRequest(webreq);
@@ -354,9 +375,9 @@ void LocalFrameClientImpl::DispatchDidReceiveResponse(
}
void LocalFrameClientImpl::DispatchDidFinishDocumentLoad() {
- // TODO(dglazkov): Sadly, workers are WebFrameClients, and they can totally
- // destroy themselves when didFinishDocumentLoad is invoked, and in turn
- // destroy the fake WebLocalFrame that they create, which means that you
+ // TODO(dglazkov): Sadly, workers are WebLocalFrameClients, and they can
+ // totally destroy themselves when didFinishDocumentLoad is invoked, and in
+ // turn destroy the fake WebLocalFrame that they create, which means that you
// should not put any code touching `this` after the two lines below.
if (web_frame_->Client())
web_frame_->Client()->DidFinishDocumentLoad();
@@ -376,24 +397,16 @@ void LocalFrameClientImpl::DispatchDidHandleOnloadEvents() {
web_frame_->Client()->DidHandleOnloadEvents();
}
-void LocalFrameClientImpl::
- DispatchDidReceiveServerRedirectForProvisionalLoad() {
- if (web_frame_->Client()) {
- web_frame_->Client()->DidReceiveServerRedirectForProvisionalLoad();
- }
-}
-
void LocalFrameClientImpl::DidFinishSameDocumentNavigation(
HistoryItem* item,
- HistoryCommitType commit_type,
+ WebHistoryCommitType commit_type,
bool content_initiated) {
- bool should_create_history_entry = commit_type == kStandardCommit;
+ bool should_create_history_entry = commit_type == kWebStandardCommit;
// TODO(dglazkov): Does this need to be called for subframes?
web_frame_->ViewImpl()->DidCommitLoad(should_create_history_entry, true);
if (web_frame_->Client()) {
web_frame_->Client()->DidFinishSameDocumentNavigation(
- WebHistoryItem(item), static_cast<WebHistoryCommitType>(commit_type),
- content_initiated);
+ WebHistoryItem(item), commit_type, content_initiated);
}
virtual_time_pauser_.UnpauseVirtualTime();
}
@@ -430,17 +443,23 @@ void LocalFrameClientImpl::DispatchDidChangeIcons(IconType type) {
void LocalFrameClientImpl::DispatchDidCommitLoad(
HistoryItem* item,
- HistoryCommitType commit_type,
+ WebHistoryCommitType commit_type,
WebGlobalObjectReusePolicy global_object_reuse_policy) {
if (!web_frame_->Parent()) {
- web_frame_->ViewImpl()->DidCommitLoad(commit_type == kStandardCommit,
+ web_frame_->ViewImpl()->DidCommitLoad(commit_type == kWebStandardCommit,
false);
}
if (web_frame_->Client()) {
web_frame_->Client()->DidCommitProvisionalLoad(
- WebHistoryItem(item), static_cast<WebHistoryCommitType>(commit_type),
- global_object_reuse_policy);
+ WebHistoryItem(item), commit_type, global_object_reuse_policy);
+ if (web_frame_->GetFrame()->IsLocalRoot()) {
+ // This update should be sent as soon as loading the new document begins
+ // so that the browser and compositor could reset their states. However,
+ // up to this point |web_frame_| is still provisional and the updates will
+ // not get sent. Revise this when https://crbug.com/578349 is fixed.
+ ResetWheelAndTouchEventHandlerProperties(*web_frame_->GetFrame());
+ }
}
if (WebDevToolsAgentImpl* dev_tools = DevToolsAgent())
dev_tools->DidCommitLoadForLocalFrame(web_frame_->GetFrame());
@@ -450,13 +469,14 @@ void LocalFrameClientImpl::DispatchDidCommitLoad(
void LocalFrameClientImpl::DispatchDidFailProvisionalLoad(
const ResourceError& error,
- HistoryCommitType commit_type) {
+ WebHistoryCommitType commit_type) {
web_frame_->DidFail(error, true, commit_type);
virtual_time_pauser_.UnpauseVirtualTime();
}
-void LocalFrameClientImpl::DispatchDidFailLoad(const ResourceError& error,
- HistoryCommitType commit_type) {
+void LocalFrameClientImpl::DispatchDidFailLoad(
+ const ResourceError& error,
+ WebHistoryCommitType commit_type) {
web_frame_->DidFail(error, false, commit_type);
}
@@ -469,53 +489,11 @@ void LocalFrameClientImpl::DispatchDidChangeThemeColor() {
web_frame_->Client()->DidChangeThemeColor();
}
-static bool AllowCreatingBackgroundTabs() {
- const WebInputEvent* input_event = CurrentInputEvent::Get();
- if (!input_event || (input_event->GetType() != WebInputEvent::kMouseUp &&
- (input_event->GetType() != WebInputEvent::kRawKeyDown &&
- input_event->GetType() != WebInputEvent::kKeyDown) &&
- input_event->GetType() != WebInputEvent::kGestureTap))
- return false;
-
- unsigned short button_number;
- if (WebInputEvent::IsMouseEventType(input_event->GetType())) {
- const WebMouseEvent* mouse_event =
- static_cast<const WebMouseEvent*>(input_event);
-
- switch (mouse_event->button) {
- case WebMouseEvent::Button::kLeft:
- button_number = 0;
- break;
- case WebMouseEvent::Button::kMiddle:
- button_number = 1;
- break;
- case WebMouseEvent::Button::kRight:
- button_number = 2;
- break;
- default:
- return false;
- }
- } else {
- // The click is simulated when triggering the keypress event.
- button_number = 0;
- }
- bool ctrl = input_event->GetModifiers() & WebMouseEvent::kControlKey;
- bool shift = input_event->GetModifiers() & WebMouseEvent::kShiftKey;
- bool alt = input_event->GetModifiers() & WebMouseEvent::kAltKey;
- bool meta = input_event->GetModifiers() & WebMouseEvent::kMetaKey;
-
- NavigationPolicy user_policy;
- if (!NavigationPolicyFromMouseEvent(button_number, ctrl, shift, alt, meta,
- &user_policy))
- return false;
- return user_policy == kNavigationPolicyNewBackgroundTab;
-}
-
NavigationPolicy LocalFrameClientImpl::DecidePolicyForNavigation(
const ResourceRequest& request,
Document* origin_document,
DocumentLoader* document_loader,
- NavigationType type,
+ WebNavigationType type,
NavigationPolicy policy,
bool replaces_current_history_item,
bool is_client_redirect,
@@ -527,18 +505,13 @@ NavigationPolicy LocalFrameClientImpl::DecidePolicyForNavigation(
if (!web_frame_->Client())
return kNavigationPolicyIgnore;
- if (policy == kNavigationPolicyNewBackgroundTab &&
- !AllowCreatingBackgroundTabs() &&
- !UIEventWithKeyState::NewTabModifierSetFromIsolatedWorld())
- policy = kNavigationPolicyNewForegroundTab;
-
WebDocumentLoaderImpl* web_document_loader =
WebDocumentLoaderImpl::FromDocumentLoader(document_loader);
WrappedResourceRequest wrapped_resource_request(request);
- WebFrameClient::NavigationPolicyInfo navigation_info(
+ WebLocalFrameClient::NavigationPolicyInfo navigation_info(
wrapped_resource_request);
- navigation_info.navigation_type = static_cast<WebNavigationType>(type);
+ navigation_info.navigation_type = type;
navigation_info.default_policy = static_cast<WebNavigationPolicy>(policy);
navigation_info.extra_data =
web_document_loader ? web_document_loader->GetExtraData() : nullptr;
@@ -569,8 +542,8 @@ NavigationPolicy LocalFrameClientImpl::DecidePolicyForNavigation(
// should the output be spread back across multiple processes?
navigation_info.archive_status =
IsLoadedAsMHTMLArchive(local_parent_frame)
- ? WebFrameClient::NavigationPolicyInfo::ArchiveStatus::Present
- : WebFrameClient::NavigationPolicyInfo::ArchiveStatus::Absent;
+ ? WebLocalFrameClient::NavigationPolicyInfo::ArchiveStatus::Present
+ : WebLocalFrameClient::NavigationPolicyInfo::ArchiveStatus::Absent;
if (form)
navigation_info.form = WebFormElement(form);
@@ -635,18 +608,21 @@ void LocalFrameClientImpl::ForwardResourceTimingToParent(
web_frame_->Client()->ForwardResourceTimingToParent(info);
}
-void LocalFrameClientImpl::DownloadURL(const ResourceRequest& request) {
+void LocalFrameClientImpl::DownloadURL(
+ const ResourceRequest& request,
+ DownloadCrossOriginRedirects cross_origin_redirect_behavior) {
if (!web_frame_->Client())
return;
DCHECK(web_frame_->GetFrame()->GetDocument());
mojom::blink::BlobURLTokenPtr blob_url_token;
- if (request.Url().ProtocolIs("blob") &&
- RuntimeEnabledFeatures::MojoBlobURLsEnabled()) {
+ if (request.Url().ProtocolIs("blob") && BlobUtils::MojoBlobURLsEnabled()) {
web_frame_->GetFrame()->GetDocument()->GetPublicURLManager().Resolve(
request.Url(), MakeRequest(&blob_url_token));
}
web_frame_->Client()->DownloadURL(
WrappedResourceRequest(request),
+ static_cast<WebLocalFrameClient::CrossOriginRedirects>(
+ cross_origin_redirect_behavior),
blob_url_token.PassInterface().PassHandle());
}
@@ -753,7 +729,7 @@ bool LocalFrameClientImpl::ShouldTrackUseCounter(const KURL& url) {
void LocalFrameClientImpl::SelectorMatchChanged(
const Vector<String>& added_selectors,
const Vector<String>& removed_selectors) {
- if (WebFrameClient* client = web_frame_->Client()) {
+ if (WebLocalFrameClient* client = web_frame_->Client()) {
client->DidMatchCSS(WebVector<WebString>(added_selectors),
WebVector<WebString>(removed_selectors));
}
@@ -764,11 +740,17 @@ DocumentLoader* LocalFrameClientImpl::CreateDocumentLoader(
const ResourceRequest& request,
const SubstituteData& data,
ClientRedirectPolicy client_redirect_policy,
- const base::UnguessableToken& devtools_navigation_token) {
+ const base::UnguessableToken& devtools_navigation_token,
+ std::unique_ptr<WebDocumentLoader::ExtraData> extra_data,
+ const WebNavigationTimings& navigation_timings) {
DCHECK(frame);
WebDocumentLoaderImpl* document_loader = WebDocumentLoaderImpl::Create(
frame, request, data, client_redirect_policy, devtools_navigation_token);
+ document_loader->SetExtraData(std::move(extra_data));
+ document_loader->UpdateNavigationTimings(
+ navigation_timings.navigation_start, navigation_timings.redirect_start,
+ navigation_timings.redirect_end, navigation_timings.fetch_start);
if (web_frame_->Client())
web_frame_->Client()->DidCreateDocumentLoader(document_loader);
return document_loader;
@@ -941,11 +923,6 @@ bool LocalFrameClientImpl::ShouldBlockWebGL() {
return web_frame_->Client()->ShouldBlockWebGL();
}
-void LocalFrameClientImpl::DispatchWillInsertBody() {
- if (web_frame_->Client())
- web_frame_->Client()->WillInsertBody();
-}
-
std::unique_ptr<WebServiceWorkerProvider>
LocalFrameClientImpl::CreateServiceWorkerProvider() {
if (!web_frame_->Client())
@@ -992,7 +969,7 @@ void LocalFrameClientImpl::SuddenTerminationDisablerChanged(
}
BlameContext* LocalFrameClientImpl::GetFrameBlameContext() {
- if (WebFrameClient* client = web_frame_->Client())
+ if (WebLocalFrameClient* client = web_frame_->Client())
return client->GetFrameBlameContext();
return nullptr;
}
@@ -1025,13 +1002,20 @@ KURL LocalFrameClientImpl::OverrideFlashEmbedWithHTML(const KURL& url) {
return web_frame_->Client()->OverrideFlashEmbedWithHTML(WebURL(url));
}
-void LocalFrameClientImpl::SetHasReceivedUserGesture() {
+void LocalFrameClientImpl::NotifyUserActivation() {
DCHECK(web_frame_->Client());
- web_frame_->Client()->SetHasReceivedUserGesture();
+ web_frame_->Client()->UpdateUserActivationState(
+ UserActivationUpdateType::kNotifyActivation);
if (WebAutofillClient* autofill_client = web_frame_->AutofillClient())
autofill_client->UserGestureObserved();
}
+void LocalFrameClientImpl::ConsumeUserActivation() {
+ DCHECK(web_frame_->Client());
+ web_frame_->Client()->UpdateUserActivationState(
+ UserActivationUpdateType::kConsumeTransientActivation);
+}
+
void LocalFrameClientImpl::SetHasReceivedUserGestureBeforeNavigation(
bool value) {
web_frame_->Client()->SetHasReceivedUserGestureBeforeNavigation(value);
@@ -1130,8 +1114,25 @@ void LocalFrameClientImpl::FrameRectsChanged(const IntRect& frame_rect) {
web_frame_->Client()->FrameRectsChanged(frame_rect);
}
+std::unique_ptr<WebWorkerFetchContext>
+LocalFrameClientImpl::CreateWorkerFetchContext() {
+ DCHECK(web_frame_->Client());
+ return web_frame_->Client()->CreateWorkerFetchContext();
+}
+
+std::unique_ptr<WebContentSettingsClient>
+LocalFrameClientImpl::CreateWorkerContentSettingsClient() {
+ DCHECK(web_frame_->Client());
+ return web_frame_->Client()->CreateWorkerContentSettingsClient();
+}
+
void LocalFrameClientImpl::SetMouseCapture(bool capture) {
web_frame_->Client()->SetMouseCapture(capture);
}
+STATIC_ASSERT_ENUM(DownloadCrossOriginRedirects::kFollow,
+ WebLocalFrameClient::CrossOriginRedirects::kFollow);
+STATIC_ASSERT_ENUM(DownloadCrossOriginRedirects::kNavigate,
+ WebLocalFrameClient::CrossOriginRedirects::kNavigate);
+
} // namespace blink
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 85b53ff243c..14a451e9e11 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
@@ -93,9 +93,8 @@ class LocalFrameClientImpl final : public LocalFrameClient {
void DispatchDidLoadResourceFromMemoryCache(const ResourceRequest&,
const ResourceResponse&) override;
void DispatchDidHandleOnloadEvents() override;
- void DispatchDidReceiveServerRedirectForProvisionalLoad() override;
void DidFinishSameDocumentNavigation(HistoryItem*,
- HistoryCommitType,
+ WebHistoryCommitType,
bool content_initiated) override;
void DispatchWillCommitProvisionalLoad() override;
void DispatchDidStartProvisionalLoad(DocumentLoader*,
@@ -103,11 +102,11 @@ class LocalFrameClientImpl final : public LocalFrameClient {
void DispatchDidReceiveTitle(const String&) override;
void DispatchDidChangeIcons(IconType) override;
void DispatchDidCommitLoad(HistoryItem*,
- HistoryCommitType,
+ WebHistoryCommitType,
WebGlobalObjectReusePolicy) override;
void DispatchDidFailProvisionalLoad(const ResourceError&,
- HistoryCommitType) override;
- void DispatchDidFailLoad(const ResourceError&, HistoryCommitType) override;
+ WebHistoryCommitType) override;
+ void DispatchDidFailLoad(const ResourceError&, WebHistoryCommitType) override;
void DispatchDidFinishDocumentLoad() override;
void DispatchDidFinishLoad() override;
@@ -116,7 +115,7 @@ class LocalFrameClientImpl final : public LocalFrameClient {
const ResourceRequest&,
Document* origin_document,
DocumentLoader*,
- NavigationType,
+ WebNavigationType,
NavigationPolicy,
bool should_replace_current_entry,
bool is_client_redirect,
@@ -130,7 +129,8 @@ class LocalFrameClientImpl final : public LocalFrameClient {
void DidStopLoading() override;
void ProgressEstimateChanged(double progress_estimate) override;
void ForwardResourceTimingToParent(const WebResourceTimingInfo&) override;
- void DownloadURL(const ResourceRequest&) override;
+ void DownloadURL(const ResourceRequest&,
+ DownloadCrossOriginRedirects) override;
void LoadErrorPage(int reason) override;
bool NavigateBackForward(int offset) const override;
void DidAccessInitialDocument() override;
@@ -160,7 +160,9 @@ class LocalFrameClientImpl final : public LocalFrameClient {
const ResourceRequest&,
const SubstituteData&,
ClientRedirectPolicy,
- const base::UnguessableToken& devtools_navigation_token) override;
+ const base::UnguessableToken& devtools_navigation_token,
+ std::unique_ptr<WebDocumentLoader::ExtraData> extra_data,
+ const WebNavigationTimings& navigation_timings) override;
WTF::String UserAgent() override;
WTF::String DoNotTrackValue() override;
void TransitionToCommittedForNewPage() override;
@@ -204,8 +206,6 @@ class LocalFrameClientImpl final : public LocalFrameClient {
bool ShouldBlockWebGL() override;
- void DispatchWillInsertBody() override;
-
std::unique_ptr<WebServiceWorkerProvider> CreateServiceWorkerProvider()
override;
ContentSettingsClient& GetContentSettingsClient() override;
@@ -233,7 +233,8 @@ class LocalFrameClientImpl final : public LocalFrameClient {
KURL OverrideFlashEmbedWithHTML(const KURL&) override;
- void SetHasReceivedUserGesture() override;
+ void NotifyUserActivation() override;
+ void ConsumeUserActivation() override;
void SetHasReceivedUserGestureBeforeNavigation(bool value) override;
@@ -276,6 +277,10 @@ class LocalFrameClientImpl final : public LocalFrameClient {
void FrameRectsChanged(const IntRect&) override;
+ std::unique_ptr<WebWorkerFetchContext> CreateWorkerFetchContext() override;
+ std::unique_ptr<WebContentSettingsClient> CreateWorkerContentSettingsClient()
+ override;
+
void SetMouseCapture(bool capture) override;
private:
diff --git a/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl_test.cc b/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl_test.cc
index 1b448bc7b5a..a7f5fdf318e 100644
--- a/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl_test.cc
+++ b/chromium/third_party/blink/renderer/core/exported/local_frame_client_impl_test.cc
@@ -32,7 +32,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/web/web_frame_client.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/public/web/web_view.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
@@ -73,7 +73,7 @@ class LocalFrameClientImplTest : public testing::Test {
// Tearing down the WebView by resetting the helper will call
// UserAgentOverride() in order to store the information for detached
// requests.
- EXPECT_CALL(WebFrameClient(), UserAgentOverride());
+ EXPECT_CALL(WebLocalFrameClient(), UserAgentOverride());
helper_.Reset();
}
@@ -85,7 +85,9 @@ class LocalFrameClientImplTest : public testing::Test {
WebLocalFrameImpl* MainFrame() { return helper_.LocalMainFrame(); }
Document& GetDocument() { return *MainFrame()->GetFrame()->GetDocument(); }
- LocalFrameMockWebFrameClient& WebFrameClient() { return web_frame_client_; }
+ LocalFrameMockWebFrameClient& WebLocalFrameClient() {
+ return web_frame_client_;
+ }
LocalFrameClient& GetLocalFrameClient() {
return *ToLocalFrameClientImpl(MainFrame()->GetFrame()->Client());
}
@@ -100,13 +102,13 @@ TEST_F(LocalFrameClientImplTest, UserAgentOverride) {
const WebString override_user_agent = WebString::FromUTF8("dummy override");
// Override the user agent and make sure we get it back.
- EXPECT_CALL(WebFrameClient(), UserAgentOverride())
+ EXPECT_CALL(WebLocalFrameClient(), UserAgentOverride())
.WillOnce(Return(override_user_agent));
EXPECT_TRUE(override_user_agent.Equals(UserAgent()));
- Mock::VerifyAndClearExpectations(&WebFrameClient());
+ Mock::VerifyAndClearExpectations(&WebLocalFrameClient());
// Remove the override and make sure we get the original back.
- EXPECT_CALL(WebFrameClient(), UserAgentOverride())
+ EXPECT_CALL(WebLocalFrameClient(), UserAgentOverride())
.WillOnce(Return(WebString()));
EXPECT_TRUE(default_user_agent.Equals(UserAgent()));
}
diff --git a/chromium/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.cc b/chromium/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.cc
index c9c405733ff..c72e0d15c99 100644
--- a/chromium/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.cc
+++ b/chromium/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.cc
@@ -106,10 +106,12 @@ static WebSharedWorkerRepositoryClient::DocumentID GetId(void* document) {
document);
}
-void SharedWorkerRepositoryClientImpl::Connect(SharedWorker* worker,
- MessagePortChannel port,
- const KURL& url,
- const String& name) {
+void SharedWorkerRepositoryClientImpl::Connect(
+ SharedWorker* worker,
+ MessagePortChannel port,
+ const KURL& url,
+ mojom::blink::BlobURLTokenPtr blob_url_token,
+ const String& name) {
DCHECK(client_);
// No nested workers (for now) - connect() should only be called from document
@@ -121,16 +123,15 @@ void SharedWorkerRepositoryClientImpl::Connect(SharedWorker* worker,
// when multiple might have been sent. Fix by making the
// SharedWorkerConnectListener interface take a map that can contain
// multiple headers.
- std::unique_ptr<Vector<CSPHeaderAndType>> headers =
+ Vector<CSPHeaderAndType> headers =
worker->GetExecutionContext()->GetContentSecurityPolicy()->Headers();
WebString header;
WebContentSecurityPolicyType header_type =
kWebContentSecurityPolicyTypeReport;
- if (headers->size() > 0) {
- header = (*headers)[0].first;
- header_type =
- static_cast<WebContentSecurityPolicyType>((*headers)[0].second);
+ if (headers.size() > 0) {
+ header = headers[0].first;
+ header_type = static_cast<WebContentSecurityPolicyType>(headers[0].second);
}
bool is_secure_context = worker->GetExecutionContext()->IsSecureContext();
@@ -139,8 +140,8 @@ void SharedWorkerRepositoryClientImpl::Connect(SharedWorker* worker,
client_->Connect(
url, name, GetId(document), header, header_type,
worker->GetExecutionContext()->GetSecurityContext().AddressSpace(),
- ToCreationContextType(is_secure_context),
- std::move(port), std::move(listener));
+ ToCreationContextType(is_secure_context), std::move(port),
+ blob_url_token.PassInterface().PassHandle(), std::move(listener));
}
void SharedWorkerRepositoryClientImpl::DocumentDetached(Document* document) {
diff --git a/chromium/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.h b/chromium/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.h
index 2cec65bd52b..3b0b0461192 100644
--- a/chromium/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.h
+++ b/chromium/third_party/blink/renderer/core/exported/shared_worker_repository_client_impl.h
@@ -58,6 +58,7 @@ class CORE_EXPORT SharedWorkerRepositoryClientImpl final
void Connect(SharedWorker*,
MessagePortChannel,
const KURL&,
+ mojom::blink::BlobURLTokenPtr,
const String& name) override;
void DocumentDetached(Document*) override;
diff --git a/chromium/third_party/blink/renderer/core/exported/web_associated_url_loader_impl.cc b/chromium/third_party/blink/renderer/core/exported/web_associated_url_loader_impl.cc
index b781941988c..c74a5977af6 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_associated_url_loader_impl.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_associated_url_loader_impl.cc
@@ -54,6 +54,7 @@
#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/loader/cors/cors.h"
+#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_utils.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
@@ -414,13 +415,19 @@ void WebAssociatedURLLoaderImpl::LoadAsynchronously(
resource_loader_options.data_buffering_policy = kDoNotBufferData;
const ResourceRequest& webcore_request = new_request.ToResourceRequest();
- if (webcore_request.GetRequestContext() ==
- WebURLRequest::kRequestContextUnspecified) {
- // FIXME: We load URLs without setting a TargetType (and therefore a
+ WebURLRequest::RequestContext context = webcore_request.GetRequestContext();
+ if (context == WebURLRequest::kRequestContextUnspecified) {
+ // TODO(yoav): We load URLs without setting a TargetType (and therefore a
// request context) in several places in content/
// (P2PPortAllocatorSession::AllocateLegacyRelaySession, for example).
// Remove this once those places are patched up.
new_request.SetRequestContext(WebURLRequest::kRequestContextInternal);
+ } else if (context == WebURLRequest::kRequestContextVideo) {
+ resource_loader_options.initiator_info.name =
+ FetchInitiatorTypeNames::video;
+ } else if (context == WebURLRequest::kRequestContextAudio) {
+ resource_loader_options.initiator_info.name =
+ FetchInitiatorTypeNames::audio;
}
Document* document = ToDocument(observer_->LifecycleContext());
diff --git a/chromium/third_party/blink/renderer/core/exported/web_associated_url_loader_impl_test.cc b/chromium/third_party/blink/renderer/core/exported/web_associated_url_loader_impl_test.cc
index 748af0843b4..d58fe497799 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_associated_url_loader_impl_test.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_associated_url_loader_impl_test.cc
@@ -628,9 +628,6 @@ TEST_F(WebAssociatedURLLoaderTest, MAYBE_UntrustedCheckHeaders) {
// Check that validation is case-insensitive.
CheckHeaderFails("AcCePt-ChArSeT");
CheckHeaderFails("ProXy-FoO");
-
- // Check invalid header values.
- CheckHeaderFails("foo", "bar\x0d\x0ax-csrf-token:\x20test1234");
}
// Test that the loader filters response headers according to the CORS standard.
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 f98ae01cd46..976bae9c792 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
@@ -168,18 +168,17 @@ class ClientMessageLoopAdapter : public MainThreadDebugger::ClientMessageLoop {
// 3. Process messages until quitNow is called.
message_loop_->Run();
-
- // 4. Resume active objects
- WebView::DidExitModalLoop();
-
- // 5. Enable input events.
- WebFrameWidgetBase::SetIgnoreInputEvents(false);
}
void QuitNow() override {
if (running_for_debug_break_) {
running_for_debug_break_ = false;
+ // Undo steps (3), (2) and (1) from above.
+ // NOTE: This code used to be above right after the |mesasge_loop_->Run()|
+ // code, but it is moved here to support browser-side navigation.
message_loop_->QuitNow();
+ WebView::DidExitModalLoop();
+ WebFrameWidgetBase::SetIgnoreInputEvents(false);
}
}
@@ -574,7 +573,8 @@ void WebDevToolsAgentImpl::InspectElement(const WebPoint& point_in_local_root) {
if (web_local_frame_impl_->ViewImpl() &&
web_local_frame_impl_->ViewImpl()->Client()) {
WebFloatRect rect(point.x, point.y, 0, 0);
- web_local_frame_impl_->ViewImpl()->Client()->ConvertWindowToViewport(&rect);
+ web_local_frame_impl_->ViewImpl()->WidgetClient()->ConvertWindowToViewport(
+ &rect);
point = WebPoint(rect.x, rect.y);
}
@@ -589,10 +589,12 @@ void WebDevToolsAgentImpl::InspectElement(const WebPoint& point_in_local_root) {
IntPoint transformed_point = FlooredIntPoint(
TransformWebMouseEvent(web_local_frame_impl_->GetFrameView(), dummy_event)
.PositionInRootFrame());
- HitTestResult result(
- request, web_local_frame_impl_->GetFrameView()->RootFrameToContents(
- transformed_point));
- web_local_frame_impl_->GetFrame()->ContentLayoutObject()->HitTest(result);
+ HitTestLocation location(
+ web_local_frame_impl_->GetFrameView()->ConvertFromRootFrame(
+ transformed_point));
+ HitTestResult result(request, location);
+ web_local_frame_impl_->GetFrame()->ContentLayoutObject()->HitTest(location,
+ result);
Node* node = result.InnerNode();
if (!node && web_local_frame_impl_->GetFrame()->GetDocument())
node = web_local_frame_impl_->GetFrame()->GetDocument()->documentElement();
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 94eff938f10..963fa6d2d44 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_document.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_document.cc
@@ -37,7 +37,6 @@
#include "third_party/blink/public/web/web_element.h"
#include "third_party/blink/public/web/web_element_collection.h"
#include "third_party/blink/public/web/web_form_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_element_registration_options.h"
#include "third_party/blink/renderer/core/css/css_selector_watch.h"
@@ -59,6 +58,7 @@
#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/loader/document_loader.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/weborigin/security_origin.h"
#include "v8/include/v8.h"
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 9767697061f..ddb7c6c8894 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
@@ -34,7 +34,7 @@
#include <utility>
#include "base/memory/ptr_util.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
#include "third_party/blink/public/platform/web_document_subresource_filter.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_url_error.h"
@@ -84,20 +84,6 @@ void WebDocumentLoaderImpl::AppendRedirect(const WebURL& url) {
DocumentLoader::AppendRedirect(url);
}
-void WebDocumentLoaderImpl::UpdateNavigation(
- base::TimeTicks redirect_start_time,
- base::TimeTicks redirect_end_time,
- base::TimeTicks fetch_start_time,
- bool has_redirect) {
- // Updates the redirection timing if there is at least one redirection
- // (between two URLs).
- if (has_redirect) {
- GetTiming().SetRedirectStart(redirect_start_time);
- GetTiming().SetRedirectEnd(redirect_end_time);
- }
- GetTiming().SetFetchStart(fetch_start_time);
-}
-
void WebDocumentLoaderImpl::RedirectChain(WebVector<WebURL>& result) const {
result.Assign(redirect_chain_);
}
@@ -111,41 +97,16 @@ bool WebDocumentLoaderImpl::ReplacesCurrentHistoryItem() const {
}
WebNavigationType WebDocumentLoaderImpl::GetNavigationType() const {
- return ToWebNavigationType(DocumentLoader::GetNavigationType());
+ return DocumentLoader::GetNavigationType();
}
WebDocumentLoader::ExtraData* WebDocumentLoaderImpl::GetExtraData() const {
return extra_data_.get();
}
-void WebDocumentLoaderImpl::SetExtraData(ExtraData* extra_data) {
- // extraData can't be a std::unique_ptr because setExtraData is a WebKit API
- // function.
- extra_data_ = base::WrapUnique(extra_data);
-}
-
-void WebDocumentLoaderImpl::SetNavigationStartTime(
- base::TimeTicks navigation_start) {
- GetTiming().SetNavigationStart(navigation_start);
-}
-
-WebNavigationType WebDocumentLoaderImpl::ToWebNavigationType(
- NavigationType type) {
- switch (type) {
- case kNavigationTypeLinkClicked:
- return kWebNavigationTypeLinkClicked;
- case kNavigationTypeFormSubmitted:
- return kWebNavigationTypeFormSubmitted;
- case kNavigationTypeBackForward:
- return kWebNavigationTypeBackForward;
- case kNavigationTypeReload:
- return kWebNavigationTypeReload;
- case kNavigationTypeFormResubmitted:
- return kWebNavigationTypeFormResubmitted;
- case kNavigationTypeOther:
- default:
- return kWebNavigationTypeOther;
- }
+void WebDocumentLoaderImpl::SetExtraData(
+ std::unique_ptr<ExtraData> extra_data) {
+ extra_data_ = std::move(extra_data);
}
WebDocumentLoaderImpl::WebDocumentLoaderImpl(
diff --git a/chromium/third_party/blink/renderer/core/exported/web_document_loader_impl.h b/chromium/third_party/blink/renderer/core/exported/web_document_loader_impl.h
index 3ff90414ae4..e222cbeb96d 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_document_loader_impl.h
+++ b/chromium/third_party/blink/renderer/core/exported/web_document_loader_impl.h
@@ -72,12 +72,7 @@ class CORE_EXPORT WebDocumentLoaderImpl final : public DocumentLoader,
bool ReplacesCurrentHistoryItem() const override;
WebNavigationType GetNavigationType() const override;
ExtraData* GetExtraData() const override;
- void SetExtraData(ExtraData*) override;
- void SetNavigationStartTime(base::TimeTicks) override;
- void UpdateNavigation(base::TimeTicks redirect_start_time,
- base::TimeTicks redirect_end_time,
- base::TimeTicks fetch_start_time,
- bool has_redirect) override;
+ void SetExtraData(std::unique_ptr<ExtraData>) override;
void SetSubresourceFilter(WebDocumentSubresourceFilter*) override;
void SetServiceWorkerNetworkProvider(
std::unique_ptr<WebServiceWorkerNetworkProvider>) override;
@@ -90,8 +85,6 @@ class CORE_EXPORT WebDocumentLoaderImpl final : public DocumentLoader,
bool IsArchive() const override;
WebArchiveInfo GetArchiveInfo() const override;
- static WebNavigationType ToWebNavigationType(NavigationType);
-
void Trace(blink::Visitor*) override;
private:
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 3e63182303d..59ab4aaee67 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
@@ -6,7 +6,11 @@
#include <string>
+#include "base/stl_util.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/origin_trials/origin_trial_policy.h"
+#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
+#include "third_party/blink/public/web/web_origin_trials.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/css_property_names.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
@@ -23,6 +27,7 @@
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
@@ -31,6 +36,8 @@ using blink::URLTestHelpers::ToKURL;
const char kDefaultOrigin[] = "https://example.test/";
const char kManifestDummyFilePath[] = "manifest-dummy.html";
+const char kOriginTrialDummyFilePath[] = "origin-trial-dummy.html";
+const char kNoOriginTrialDummyFilePath[] = "simple_div.html";
class WebDocumentTest : public testing::Test {
protected:
@@ -47,6 +54,12 @@ void WebDocumentTest::SetUpTestCase() {
URLTestHelpers::RegisterMockedURLLoad(
ToKURL(std::string(kDefaultOrigin) + kManifestDummyFilePath),
test::CoreTestDataPath(kManifestDummyFilePath));
+ URLTestHelpers::RegisterMockedURLLoad(
+ ToKURL(std::string(kDefaultOrigin) + kNoOriginTrialDummyFilePath),
+ test::CoreTestDataPath(kNoOriginTrialDummyFilePath));
+ URLTestHelpers::RegisterMockedURLLoad(
+ ToKURL(std::string(kDefaultOrigin) + kOriginTrialDummyFilePath),
+ test::CoreTestDataPath(kOriginTrialDummyFilePath));
}
void WebDocumentTest::LoadURL(const std::string& url) {
@@ -163,6 +176,63 @@ TEST_F(WebDocumentTest, ManifestUseCredentials) {
ASSERT_TRUE(web_doc.ManifestUseCredentials());
}
+// Origin Trial Policy which vends the test public key so that the token
+// can be validated.
+class TestOriginTrialPolicy : public blink::OriginTrialPolicy {
+ bool IsOriginTrialsSupported() const override { return true; }
+ base::StringPiece GetPublicKey() const override {
+ // This is the public key which the test below will use to enable origin
+ // trial features. Trial tokens for use in tests can be created with the
+ // tool in /tools/origin_trials/generate_token.py, using the private key
+ // contained in /tools/origin_trials/eftest.key.
+ static const uint8_t kOriginTrialPublicKey[] = {
+ 0x75, 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2,
+ 0x9a, 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f,
+ 0x64, 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0,
+ };
+ return base::StringPiece(
+ reinterpret_cast<const char*>(kOriginTrialPublicKey),
+ base::size(kOriginTrialPublicKey));
+ }
+ bool IsOriginSecure(const GURL& url) const override { return true; }
+};
+
+TEST_F(WebDocumentTest, OriginTrialDisabled) {
+ // Set an origin trial policy.
+ TestOriginTrialPolicy policy;
+ blink::TrialTokenValidator::SetOriginTrialPolicyGetter(WTF::BindRepeating(
+ [](TestOriginTrialPolicy* policy_ptr) -> blink::OriginTrialPolicy* {
+ return policy_ptr;
+ },
+ base::Unretained(&policy)));
+
+ // Load a document with no origin trial token.
+ LoadURL(std::string(kDefaultOrigin) + kNoOriginTrialDummyFilePath);
+ WebDocument web_doc = TopWebDocument();
+ EXPECT_FALSE(WebOriginTrials::isTrialEnabled(&web_doc, "Frobulate"));
+ // Reset the origin trial policy.
+ TrialTokenValidator::ResetOriginTrialPolicyGetter();
+}
+
+TEST_F(WebDocumentTest, OriginTrialEnabled) {
+ // Set an origin trial policy.
+ TestOriginTrialPolicy policy;
+ blink::TrialTokenValidator::SetOriginTrialPolicyGetter(WTF::BindRepeating(
+ [](TestOriginTrialPolicy* policy_ptr) -> blink::OriginTrialPolicy* {
+ return policy_ptr;
+ },
+ base::Unretained(&policy)));
+
+ // Load a document with a valid origin trial token for the test trial.
+ LoadURL(std::string(kDefaultOrigin) + kOriginTrialDummyFilePath);
+ WebDocument web_doc = TopWebDocument();
+ EXPECT_TRUE(WebOriginTrials::isTrialEnabled(&web_doc, "Frobulate"));
+ // Ensure that other trials are not also enabled
+ EXPECT_FALSE(WebOriginTrials::isTrialEnabled(&web_doc, "NotATrial"));
+ // Reset the origin trial policy.
+ TrialTokenValidator::ResetOriginTrialPolicyGetter();
+}
+
namespace {
const char* g_base_url_origin_a = "http://example.test:0/";
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 c24e9fe77bd..e9f1304a577 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_element.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_element.cc
@@ -31,7 +31,6 @@
#include "third_party/blink/public/web/web_element.h"
#include "third_party/blink/public/platform/web_rect.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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"
@@ -40,6 +39,7 @@
#include "third_party/blink/renderer/core/html/custom/v0_custom_element_processing_stack.h"
#include "third_party/blink/renderer/core/html/forms/text_control_element.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -152,11 +152,12 @@ WebRect WebElement::BoundsInViewport() const {
return ConstUnwrap<Element>()->BoundsInViewport();
}
-WebImage WebElement::ImageContents() {
+SkBitmap WebElement::ImageContents() {
if (IsNull())
- return WebImage();
+ return {};
- return WebImage(Unwrap<Element>()->ImageContents(), kRespectImageOrientation);
+ return Unwrap<Element>()->ImageContents()->AsSkBitmapForCurrentFrame(
+ kRespectImageOrientation);
}
void WebElement::RequestFullscreen() {
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 bfb08346890..192e2915af4 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
@@ -68,12 +68,27 @@ WebString WebFormControlElement::FormControlTypeForAutofill() const {
return ConstUnwrap<HTMLFormControlElement>()->type();
}
+WebAutofillState WebFormControlElement::GetAutofillState() const {
+ return ConstUnwrap<HTMLFormControlElement>()->GetAutofillState();
+}
+
bool WebFormControlElement::IsAutofilled() const {
return ConstUnwrap<HTMLFormControlElement>()->IsAutofilled();
}
-void WebFormControlElement::SetAutofilled(bool autofilled) {
- Unwrap<HTMLFormControlElement>()->SetAutofilled(autofilled);
+bool WebFormControlElement::UserHasEditedTheField() const {
+ if (auto* input = ToHTMLInputElementOrNull(*private_))
+ return input->UserHasEditedTheField();
+ return true;
+}
+
+void WebFormControlElement::SetUserHasEditedTheFieldForTest() {
+ if (auto* input = ToHTMLInputElementOrNull(*private_))
+ input->SetUserHasEditedTheFieldForTest();
+}
+
+void WebFormControlElement::SetAutofillState(WebAutofillState autofill_state) {
+ Unwrap<HTMLFormControlElement>()->SetAutofillState(autofill_state);
}
WebString WebFormControlElement::AutofillSection() const {
diff --git a/chromium/third_party/blink/renderer/core/exported/web_frame_client.cc b/chromium/third_party/blink/renderer/core/exported/web_frame_client.cc
deleted file mode 100644
index 958c7417509..00000000000
--- a/chromium/third_party/blink/renderer/core/exported/web_frame_client.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/web/web_frame_client.h"
-
-#include "services/service_manager/public/cpp/interface_provider.h"
-
-namespace blink {
-
-service_manager::InterfaceProvider* WebFrameClient::GetInterfaceProvider() {
- static service_manager::InterfaceProvider* interface_provider = []() {
- auto* interface_provider = new service_manager::InterfaceProvider();
- service_manager::mojom::InterfaceProviderPtr provider;
- mojo::MakeRequest(&provider);
- interface_provider->Bind(std::move(provider));
- return interface_provider;
- }();
-
- return interface_provider;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/exported/web_frame_serializer.cc b/chromium/third_party/blink/renderer/core/exported/web_frame_serializer.cc
index d33b994240e..e9e57f61987 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_frame_serializer.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_frame_serializer.cc
@@ -55,6 +55,7 @@
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/core/html/html_head_element.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
+#include "third_party/blink/renderer/core/html/html_link_element.h"
#include "third_party/blink/renderer/core/html/html_table_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/input_type_names.h"
@@ -152,6 +153,12 @@ bool MHTMLFrameSerializerDelegate::ShouldIgnoreElement(const Element& element) {
ShouldIgnorePopupOverlayElement(element)) {
return true;
}
+ // Remove <link> for stylesheets that do not load.
+ if (IsHTMLLinkElement(element) &&
+ ToHTMLLinkElement(element).RelAttribute().IsStyleSheet() &&
+ !ToHTMLLinkElement(element).sheet()) {
+ return true;
+ }
return false;
}
@@ -258,6 +265,12 @@ bool MHTMLFrameSerializerDelegate::ShouldIgnoreAttribute(
if (is_src_doc_attribute && RewriteLink(element, new_link_for_the_element))
return false;
+ // Drop integrity attribute for those links with subresource loaded.
+ if (attribute.LocalName() == HTMLNames::integrityAttr &&
+ IsHTMLLinkElement(element) && ToHTMLLinkElement(element).sheet()) {
+ return true;
+ }
+
// Do not include attributes that contain javascript. This is because the
// script will not be executed when a MHTML page is being loaded.
return element.IsScriptingAttribute(attribute);
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 9191df65431..dfe65ba5f09 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
@@ -347,6 +347,23 @@ TEST_F(WebFrameSerializerSanitizationTest, KeepPopupOverlayIfNotRequested) {
"PageSerialization.MhtmlGeneration.PopupOverlaySkipped", 0);
}
+TEST_F(WebFrameSerializerSanitizationTest, LinkIntegrity) {
+ RegisterMockedFileURLLoad(KURL("http://www.test.com/beautifull.css"),
+ "frameserialization/beautifull.css", "text/css");
+ RegisterMockedFileURLLoad(KURL("http://www.test.com/integrityfail.css"),
+ "frameserialization/integrityfail.css", "text/css");
+ String mhtml =
+ GenerateMHTMLFromHtml("http://www.test.com", "link_integrity.html");
+ SCOPED_TRACE(testing::Message() << "mhtml:\n" << mhtml);
+
+ // beautifull.css remains, without 'integrity'. integrityfail.css is removed.
+ EXPECT_TRUE(
+ mhtml.Contains("<link rel=3D\"stylesheet\" "
+ "href=3D\"http://www.test.com/beautifull.css\">"));
+ EXPECT_EQ(WTF::kNotFound,
+ mhtml.Find("http://www.test.com/integrityfail.css"));
+}
+
TEST_F(WebFrameSerializerSanitizationTest, RemoveElements) {
String mhtml =
GenerateMHTMLFromHtml("http://www.test.com", "remove_elements.html");
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 4a63518cc68..7a664c13f71 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
@@ -37,9 +37,9 @@
#include <memory>
#include <set>
-#include "SkBitmap.h"
-#include "SkCanvas.h"
#include "build/build_config.h"
+#include "cc/layers/picture_layer.h"
+#include "cc/trees/layer_tree_host.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/page/launching_process_state.h"
@@ -63,10 +63,11 @@
#include "third_party/blink/public/web/web_document_loader.h"
#include "third_party/blink/public/web/web_find_options.h"
#include "third_party/blink/public/web/web_form_element.h"
-#include "third_party/blink/public/web/web_frame_client.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_history_item.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
+#include "third_party/blink/public/web/web_navigation_timings.h"
#include "third_party/blink/public/web/web_print_params.h"
#include "third_party/blink/public/web/web_range.h"
#include "third_party/blink/public/web/web_remote_frame.h"
@@ -74,7 +75,6 @@
#include "third_party/blink/public/web/web_script_source.h"
#include "third_party/blink/public/web/web_searchable_form_data.h"
#include "third_party/blink/public/web/web_security_policy.h"
-#include "third_party/blink/public/web/web_selection.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/public/web/web_text_check_client.h"
#include "third_party/blink/public/web/web_text_checking_completion.h"
@@ -111,6 +111,7 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/remote_frame.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"
#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
@@ -124,7 +125,6 @@
#include "third_party/blink/renderer/core/input/event_handler.h"
#include "third_party/blink/renderer/core/inspector/dev_tools_emulator.h"
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
-#include "third_party/blink/renderer/core/layout/layout_full_screen.h"
#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/document_threadable_loader.h"
@@ -138,6 +138,7 @@
#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.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/testing/null_execution_context.h"
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
@@ -158,6 +159,7 @@
#include "third_party/blink/renderer/platform/scroll/scrollbar_test_suite.h"
#include "third_party/blink/renderer/platform/testing/histogram_tester.h"
#include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
+#include "third_party/blink/renderer/platform/testing/scoped_fake_plugin_registry.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/weborigin/kurl_hash.h"
@@ -165,6 +167,8 @@
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkCanvas.h"
#include "v8/include/v8.h"
using blink::URLTestHelpers::ToKURL;
@@ -344,7 +348,7 @@ class WebFrameTest : public testing::Test {
return node_count;
}
- static void GetElementAndCaretBonundsForFocusedEditableElement(
+ static void GetElementAndCaretBoundsForFocusedEditableElement(
FrameTestHelpers::WebViewHelper& helper,
IntRect& element_bounds,
IntRect& caret_bounds) {
@@ -354,7 +358,7 @@ class WebFrameTest : public testing::Test {
caret_bounds =
helper.GetWebView()->GetPage()->GetVisualViewport().ViewportToRootFrame(
caret_in_viewport);
- element_bounds = element->GetDocument().View()->AbsoluteToRootFrame(
+ element_bounds = element->GetDocument().View()->ConvertToRootFrame(
PixelSnappedIntRect(element->Node::BoundingBox()));
}
@@ -1224,8 +1228,8 @@ TEST_F(WebFrameTest, PostMessageThenDetach) {
scoped_refptr<SerializedScriptValue> message =
SerializeString("message", ToScriptStateForMainWorld(frame));
MessagePortArray message_ports;
- frame->DomWindow()->postMessage(message, message_ports, "*",
- frame->DomWindow(), exception_state);
+ frame->DomWindow()->PostMessageForTesting(
+ message, message_ports, "*", frame->DomWindow(), exception_state);
web_view_helper.Reset();
EXPECT_FALSE(exception_state.HadException());
@@ -1301,7 +1305,8 @@ TEST_F(WebFrameTest, ChangeInFixedLayoutResetsTextAutosizingMultipliers) {
EXPECT_TRUE(SetTextAutosizingMultiplier(document, 2));
- ViewportDescription description = document->GetViewportDescription();
+ ViewportDescription description =
+ document->GetViewportData().GetViewportDescription();
// Choose a width that's not going match the viewport width of the loaded
// document.
description.min_width = Length(100, blink::kFixed);
@@ -1534,12 +1539,13 @@ TEST_F(WebFrameTest, DelayedViewportInitialScale) {
EXPECT_EQ(0.25f, web_view_helper.GetWebView()->PageScaleFactor());
- Document* document =
+ ViewportData& viewport =
ToLocalFrame(web_view_helper.GetWebView()->GetPage()->MainFrame())
- ->GetDocument();
- ViewportDescription description = document->GetViewportDescription();
+ ->GetDocument()
+ ->GetViewportData();
+ ViewportDescription description = viewport.GetViewportDescription();
description.zoom = 2;
- document->SetViewportDescription(description);
+ viewport.SetViewportDescription(description);
web_view_helper.GetWebView()->UpdateAllLifecyclePhases();
EXPECT_EQ(2, web_view_helper.GetWebView()->PageScaleFactor());
}
@@ -1609,12 +1615,12 @@ TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidth) {
EXPECT_EQ(viewport_width, web_view_helper.GetWebView()
->MainFrameImpl()
->GetFrameView()
- ->ContentsSize()
+ ->Size()
.Width());
EXPECT_EQ(viewport_height, web_view_helper.GetWebView()
->MainFrameImpl()
->GetFrameView()
- ->ContentsSize()
+ ->Size()
.Height());
}
@@ -1641,12 +1647,12 @@ TEST_F(WebFrameTest, NoWideViewportIgnoresPageViewportWidthButAccountsScale) {
EXPECT_EQ(viewport_width / 2, web_view_helper.GetWebView()
->MainFrameImpl()
->GetFrameView()
- ->ContentsSize()
+ ->Size()
.Width());
EXPECT_EQ(viewport_height / 2, web_view_helper.GetWebView()
->MainFrameImpl()
->GetFrameView()
- ->ContentsSize()
+ ->Size()
.Height());
}
@@ -1669,14 +1675,14 @@ TEST_F(WebFrameTest, WideViewportSetsTo980WithoutViewportTag) {
EXPECT_EQ(980, web_view_helper.GetWebView()
->MainFrameImpl()
->GetFrameView()
- ->LayoutViewportScrollableArea()
+ ->LayoutViewport()
->ContentsSize()
.Width());
EXPECT_EQ(980.0 / viewport_width * viewport_height,
web_view_helper.GetWebView()
->MainFrameImpl()
->GetFrameView()
- ->LayoutViewportScrollableArea()
+ ->LayoutViewport()
->ContentsSize()
.Height());
}
@@ -1702,12 +1708,12 @@ TEST_F(WebFrameTest, WideViewportSetsTo980WithXhtmlMp) {
EXPECT_EQ(viewport_width, web_view_helper.GetWebView()
->MainFrameImpl()
->GetFrameView()
- ->ContentsSize()
+ ->Size()
.Width());
EXPECT_EQ(viewport_height, web_view_helper.GetWebView()
->MainFrameImpl()
->GetFrameView()
- ->ContentsSize()
+ ->Size()
.Height());
}
@@ -1731,7 +1737,7 @@ TEST_F(WebFrameTest, NoWideViewportAndHeightInMeta) {
EXPECT_EQ(viewport_width, web_view_helper.GetWebView()
->MainFrameImpl()
->GetFrameView()
- ->ContentsSize()
+ ->Size()
.Width());
}
@@ -1755,13 +1761,13 @@ TEST_F(WebFrameTest, WideViewportSetsTo980WithAutoWidth) {
EXPECT_EQ(980, web_view_helper.GetWebView()
->MainFrameImpl()
->GetFrameView()
- ->ContentsSize()
+ ->Size()
.Width());
EXPECT_EQ(980.0 / viewport_width * viewport_height,
web_view_helper.GetWebView()
->MainFrameImpl()
->GetFrameView()
- ->ContentsSize()
+ ->Size()
.Height());
}
@@ -1925,7 +1931,7 @@ TEST_F(WebFrameTest, PermanentInitialPageScaleFactorAffectsLayoutWidth) {
web_view_helper.GetWebView()
->MainFrameImpl()
->GetFrameView()
- ->ContentsSize()
+ ->Size()
.Width());
EXPECT_EQ(enforced_page_scale_factor,
web_view_helper.GetWebView()->PageScaleFactor());
@@ -2101,16 +2107,17 @@ TEST_F(WebFrameTest, ToggleViewportMetaOnOff) {
settings->SetShrinksViewportContentToFit(true);
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
- Document* document =
+ ViewportData& viewport =
ToLocalFrame(web_view_helper.GetWebView()->GetPage()->MainFrame())
- ->GetDocument();
- EXPECT_FALSE(document->GetViewportDescription().IsLegacyViewportType());
+ ->GetDocument()
+ ->GetViewportData();
+ EXPECT_FALSE(viewport.GetViewportDescription().IsLegacyViewportType());
settings->SetViewportMetaEnabled(true);
- EXPECT_TRUE(document->GetViewportDescription().IsLegacyViewportType());
+ EXPECT_TRUE(viewport.GetViewportDescription().IsLegacyViewportType());
settings->SetViewportMetaEnabled(false);
- EXPECT_FALSE(document->GetViewportDescription().IsLegacyViewportType());
+ EXPECT_FALSE(viewport.GetViewportDescription().IsLegacyViewportType());
}
TEST_F(WebFrameTest,
@@ -2192,10 +2199,8 @@ TEST_F(WebFrameTest, FrameOwnerPropertiesMargin) {
frame_view->SetNeedsLayout();
frame_view->UpdateAllLifecyclePhases();
// Expect scrollbars to be enabled by default.
- EXPECT_NE(nullptr,
- frame_view->LayoutViewportScrollableArea()->HorizontalScrollbar());
- EXPECT_NE(nullptr,
- frame_view->LayoutViewportScrollableArea()->VerticalScrollbar());
+ EXPECT_NE(nullptr, frame_view->LayoutViewport()->HorizontalScrollbar());
+ EXPECT_NE(nullptr, frame_view->LayoutViewport()->VerticalScrollbar());
}
TEST_F(WebFrameTest, FrameOwnerPropertiesScrolling) {
@@ -2221,8 +2226,8 @@ TEST_F(WebFrameTest, FrameOwnerPropertiesScrolling) {
LocalFrameView* frame_view =
static_cast<WebLocalFrameImpl*>(local_frame)->GetFrameView();
- EXPECT_EQ(nullptr, frame_view->HorizontalScrollbar());
- EXPECT_EQ(nullptr, frame_view->VerticalScrollbar());
+ EXPECT_EQ(nullptr, frame_view->LayoutViewport()->HorizontalScrollbar());
+ EXPECT_EQ(nullptr, frame_view->LayoutViewport()->VerticalScrollbar());
}
TEST_F(WebFrameTest, SetForceZeroLayoutHeightWorksAcrossNavigations) {
@@ -2374,13 +2379,14 @@ TEST_F(WebFrameTest, LayoutSize320Quirk) {
// The magic number to snap to device-width is 320, so test that 321 is
// respected.
- Document* document =
+ ViewportData& viewport =
ToLocalFrame(web_view_helper.GetWebView()->GetPage()->MainFrame())
- ->GetDocument();
- ViewportDescription description = document->GetViewportDescription();
+ ->GetDocument()
+ ->GetViewportData();
+ ViewportDescription description = viewport.GetViewportDescription();
description.min_width = Length(321, blink::kFixed);
description.max_width = Length(321, blink::kFixed);
- document->SetViewportDescription(description);
+ viewport.SetViewportDescription(description);
web_view_helper.GetWebView()->UpdateAllLifecyclePhases();
EXPECT_EQ(321, web_view_helper.GetWebView()
->MainFrameImpl()
@@ -2390,7 +2396,7 @@ TEST_F(WebFrameTest, LayoutSize320Quirk) {
description.min_width = Length(320, blink::kFixed);
description.max_width = Length(320, blink::kFixed);
- document->SetViewportDescription(description);
+ viewport.SetViewportDescription(description);
web_view_helper.GetWebView()->UpdateAllLifecyclePhases();
EXPECT_EQ(600, web_view_helper.GetWebView()
->MainFrameImpl()
@@ -2398,9 +2404,9 @@ TEST_F(WebFrameTest, LayoutSize320Quirk) {
->GetLayoutSize()
.Width());
- description = document->GetViewportDescription();
+ description = viewport.GetViewportDescription();
description.max_height = Length(1000, blink::kFixed);
- document->SetViewportDescription(description);
+ viewport.SetViewportDescription(description);
web_view_helper.GetWebView()->UpdateAllLifecyclePhases();
EXPECT_EQ(1000, web_view_helper.GetWebView()
->MainFrameImpl()
@@ -2409,7 +2415,7 @@ TEST_F(WebFrameTest, LayoutSize320Quirk) {
.Height());
description.max_height = Length(320, blink::kFixed);
- document->SetViewportDescription(description);
+ viewport.SetViewportDescription(description);
web_view_helper.GetWebView()->UpdateAllLifecyclePhases();
EXPECT_EQ(800, web_view_helper.GetWebView()
->MainFrameImpl()
@@ -2470,8 +2476,9 @@ TEST_F(WebFrameTest, OverflowHiddenDisablesScrolling) {
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
LocalFrameView* view = web_view_helper.LocalMainFrame()->GetFrameView();
- EXPECT_FALSE(view->UserInputScrollable(kVerticalScrollbar));
- EXPECT_FALSE(view->UserInputScrollable(kHorizontalScrollbar));
+ EXPECT_FALSE(view->LayoutViewport()->UserInputScrollable(kVerticalScrollbar));
+ EXPECT_FALSE(
+ view->LayoutViewport()->UserInputScrollable(kHorizontalScrollbar));
}
TEST_F(WebFrameTest, OverflowHiddenDisablesScrollingWithSetCanHaveScrollbars) {
@@ -2489,12 +2496,14 @@ TEST_F(WebFrameTest, OverflowHiddenDisablesScrollingWithSetCanHaveScrollbars) {
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
LocalFrameView* view = web_view_helper.LocalMainFrame()->GetFrameView();
- EXPECT_FALSE(view->UserInputScrollable(kVerticalScrollbar));
- EXPECT_FALSE(view->UserInputScrollable(kHorizontalScrollbar));
+ EXPECT_FALSE(view->LayoutViewport()->UserInputScrollable(kVerticalScrollbar));
+ EXPECT_FALSE(
+ view->LayoutViewport()->UserInputScrollable(kHorizontalScrollbar));
web_view_helper.LocalMainFrame()->SetCanHaveScrollbars(true);
- EXPECT_FALSE(view->UserInputScrollable(kVerticalScrollbar));
- EXPECT_FALSE(view->UserInputScrollable(kHorizontalScrollbar));
+ EXPECT_FALSE(view->LayoutViewport()->UserInputScrollable(kVerticalScrollbar));
+ EXPECT_FALSE(
+ view->LayoutViewport()->UserInputScrollable(kHorizontalScrollbar));
}
TEST_F(WebFrameTest, IgnoreOverflowHiddenQuirk) {
@@ -2515,8 +2524,7 @@ TEST_F(WebFrameTest, IgnoreOverflowHiddenQuirk) {
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
LocalFrameView* view = web_view_helper.LocalMainFrame()->GetFrameView();
- EXPECT_TRUE(view->LayoutViewportScrollableArea()->UserInputScrollable(
- kVerticalScrollbar));
+ EXPECT_TRUE(view->LayoutViewport()->UserInputScrollable(kVerticalScrollbar));
}
TEST_F(WebFrameTest, NonZeroValuesNoQuirk) {
@@ -2680,28 +2688,27 @@ TEST_F(WebFrameTest, pageScaleFactorDoesntShrinkFrameView) {
int viewport_width_minus_scrollbar = viewport_width;
int viewport_height_minus_scrollbar = viewport_height;
- if (view->VerticalScrollbar() &&
- !view->VerticalScrollbar()->IsOverlayScrollbar())
+ if (view->LayoutViewport()->VerticalScrollbar() &&
+ !view->LayoutViewport()->VerticalScrollbar()->IsOverlayScrollbar())
viewport_width_minus_scrollbar -= 15;
- if (view->HorizontalScrollbar() &&
- !view->HorizontalScrollbar()->IsOverlayScrollbar())
+ if (view->LayoutViewport()->HorizontalScrollbar() &&
+ !view->LayoutViewport()->HorizontalScrollbar()->IsOverlayScrollbar())
viewport_height_minus_scrollbar -= 15;
web_view_helper.GetWebView()->SetPageScaleFactor(2);
- IntSize unscaled_size = view->VisibleContentSize(kIncludeScrollbars);
+ IntSize unscaled_size = view->Size();
EXPECT_EQ(viewport_width, unscaled_size.Width());
EXPECT_EQ(viewport_height, unscaled_size.Height());
- IntSize unscaled_size_minus_scrollbar =
- view->VisibleContentSize(kExcludeScrollbars);
+ IntSize unscaled_size_minus_scrollbar = view->Size();
EXPECT_EQ(viewport_width_minus_scrollbar,
unscaled_size_minus_scrollbar.Width());
EXPECT_EQ(viewport_height_minus_scrollbar,
unscaled_size_minus_scrollbar.Height());
- IntSize frame_view_size = view->VisibleContentRect().Size();
+ IntSize frame_view_size = view->Size();
EXPECT_EQ(viewport_width_minus_scrollbar, frame_view_size.Width());
EXPECT_EQ(viewport_height_minus_scrollbar, frame_view_size.Height());
}
@@ -2729,7 +2736,7 @@ TEST_F(WebFrameTest, pageScaleFactorDoesNotApplyCssTransform) {
EXPECT_EQ(980, web_view_helper.GetWebView()
->MainFrameImpl()
->GetFrameView()
- ->LayoutViewportScrollableArea()
+ ->LayoutViewport()
->ContentsSize()
.Width());
}
@@ -3335,22 +3342,18 @@ TEST_F(WebFrameTest, pageScaleFactorUpdatesScrollbars) {
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
LocalFrameView* view = web_view_helper.LocalMainFrame()->GetFrameView();
- ScrollableArea* scrollable_area = view->LayoutViewportScrollableArea();
+ ScrollableArea* scrollable_area = view->LayoutViewport();
EXPECT_EQ(scrollable_area->ScrollSize(kHorizontalScrollbar),
- scrollable_area->ContentsSize().Width() -
- view->VisibleContentRect().Width());
+ scrollable_area->ContentsSize().Width() - view->Width());
EXPECT_EQ(scrollable_area->ScrollSize(kVerticalScrollbar),
- scrollable_area->ContentsSize().Height() -
- view->VisibleContentRect().Height());
+ scrollable_area->ContentsSize().Height() - view->Height());
web_view_helper.GetWebView()->SetPageScaleFactor(10);
EXPECT_EQ(scrollable_area->ScrollSize(kHorizontalScrollbar),
- scrollable_area->ContentsSize().Width() -
- view->VisibleContentRect().Width());
+ scrollable_area->ContentsSize().Width() - view->Width());
EXPECT_EQ(scrollable_area->ScrollSize(kVerticalScrollbar),
- scrollable_area->ContentsSize().Height() -
- view->VisibleContentRect().Height());
+ scrollable_area->ContentsSize().Height() - view->Height());
}
TEST_F(WebFrameTest, CanOverrideScaleLimits) {
@@ -3409,16 +3412,12 @@ TEST_F(WebFrameTest, updateOverlayScrollbarLayers)
web_view_helper.GetWebView()->UpdateAllLifecyclePhases();
LocalFrameView* view = web_view_helper.LocalMainFrame()->GetFrameView();
- EXPECT_TRUE(
- view->LayoutViewportScrollableArea()->LayerForHorizontalScrollbar());
- EXPECT_TRUE(
- view->LayoutViewportScrollableArea()->LayerForVerticalScrollbar());
+ EXPECT_TRUE(view->LayoutViewport()->LayerForHorizontalScrollbar());
+ EXPECT_TRUE(view->LayoutViewport()->LayerForVerticalScrollbar());
web_view_helper.Resize(WebSize(view_width * 10, view_height * 10));
- EXPECT_FALSE(
- view->LayoutViewportScrollableArea()->LayerForHorizontalScrollbar());
- EXPECT_FALSE(
- view->LayoutViewportScrollableArea()->LayerForVerticalScrollbar());
+ EXPECT_FALSE(view->LayoutViewport()->LayerForHorizontalScrollbar());
+ EXPECT_FALSE(view->LayoutViewport()->LayerForVerticalScrollbar());
}
void SetScaleAndScrollAndLayout(WebViewImpl* web_view,
@@ -3430,14 +3429,10 @@ void SetScaleAndScrollAndLayout(WebViewImpl* web_view,
}
void SimulatePageScale(WebViewImpl* web_view_impl, float& scale) {
- ScrollOffset scroll_delta =
- ToScrollOffset(
- web_view_impl->FakePageScaleAnimationTargetPositionForTesting()) -
- web_view_impl->MainFrameImpl()->GetFrameView()->GetScrollOffset();
float scale_delta =
web_view_impl->FakePageScaleAnimationPageScaleForTesting() /
web_view_impl->PageScaleFactor();
- web_view_impl->ApplyViewportDeltas(WebFloatSize(), FloatSize(scroll_delta),
+ web_view_impl->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(),
WebFloatSize(), scale_delta, 0);
scale = web_view_impl->PageScaleFactor();
}
@@ -4161,7 +4156,7 @@ TEST_F(WebFrameTest, DivScrollIntoEditableTest) {
IntPoint scroll;
bool need_animation;
IntRect element_bounds, caret_bounds;
- GetElementAndCaretBonundsForFocusedEditableElement(
+ GetElementAndCaretBoundsForFocusedEditableElement(
web_view_helper, element_bounds, caret_bounds);
web_view_helper.GetWebView()->ComputeScaleAndScrollForEditableElementRects(
element_bounds, caret_bounds, kAutoZoomToLegibleScale, scale, scroll,
@@ -4181,7 +4176,7 @@ TEST_F(WebFrameTest, DivScrollIntoEditableTest) {
web_view_helper.Resize(WebSize(viewport_width, viewport_height));
SetScaleAndScrollAndLayout(web_view_helper.GetWebView(), WebPoint(0, 0),
initial_scale);
- GetElementAndCaretBonundsForFocusedEditableElement(
+ GetElementAndCaretBoundsForFocusedEditableElement(
web_view_helper, element_bounds, caret_bounds);
web_view_helper.GetWebView()->ComputeScaleAndScrollForEditableElementRects(
element_bounds, caret_bounds, kAutoZoomToLegibleScale, scale, scroll,
@@ -4197,7 +4192,7 @@ TEST_F(WebFrameTest, DivScrollIntoEditableTest) {
initial_scale);
// Move focus to edit box with text.
web_view_helper.GetWebView()->AdvanceFocus(false);
- GetElementAndCaretBonundsForFocusedEditableElement(
+ GetElementAndCaretBoundsForFocusedEditableElement(
web_view_helper, element_bounds, caret_bounds);
web_view_helper.GetWebView()->ComputeScaleAndScrollForEditableElementRects(
element_bounds, caret_bounds, kAutoZoomToLegibleScale, scale, scroll,
@@ -4219,7 +4214,7 @@ TEST_F(WebFrameTest, DivScrollIntoEditableTest) {
within_tolerance_scale);
// Move focus back to the second edit box.
web_view_helper.GetWebView()->AdvanceFocus(false);
- GetElementAndCaretBonundsForFocusedEditableElement(
+ GetElementAndCaretBoundsForFocusedEditableElement(
web_view_helper, element_bounds, caret_bounds);
web_view_helper.GetWebView()->ComputeScaleAndScrollForEditableElementRects(
element_bounds, caret_bounds, kAutoZoomToLegibleScale, scale, scroll,
@@ -4269,7 +4264,7 @@ TEST_F(WebFrameTest, DivScrollIntoEditablePreservePageScaleTest) {
IntPoint scroll;
bool need_animation;
IntRect element_bounds, caret_bounds;
- GetElementAndCaretBonundsForFocusedEditableElement(
+ GetElementAndCaretBoundsForFocusedEditableElement(
web_view_helper, element_bounds, caret_bounds);
web_view_helper.GetWebView()->ComputeScaleAndScrollForEditableElementRects(
element_bounds, caret_bounds, kAutoZoomToLegibleScale, scale, scroll,
@@ -4289,7 +4284,7 @@ TEST_F(WebFrameTest, DivScrollIntoEditablePreservePageScaleTest) {
h_scroll = 200;
SetScaleAndScrollAndLayout(web_view_helper.GetWebView(),
WebPoint(h_scroll, 0), new_scale);
- GetElementAndCaretBonundsForFocusedEditableElement(
+ GetElementAndCaretBoundsForFocusedEditableElement(
web_view_helper, element_bounds, caret_bounds);
web_view_helper.GetWebView()->ComputeScaleAndScrollForEditableElementRects(
element_bounds, caret_bounds, kAutoZoomToLegibleScale, scale, scroll,
@@ -4347,7 +4342,7 @@ TEST_F(WebFrameTest, DivScrollIntoEditableTestZoomToLegibleScaleDisabled) {
IntPoint scroll;
bool need_animation;
IntRect element_bounds, caret_bounds;
- GetElementAndCaretBonundsForFocusedEditableElement(
+ GetElementAndCaretBoundsForFocusedEditableElement(
web_view_helper, element_bounds, caret_bounds);
web_view_helper.GetWebView()->ComputeScaleAndScrollForEditableElementRects(
element_bounds, caret_bounds, kAutoZoomToLegibleScale, scale, scroll,
@@ -4370,7 +4365,7 @@ TEST_F(WebFrameTest, DivScrollIntoEditableTestZoomToLegibleScaleDisabled) {
web_view_helper.GetWebView()->AdvanceFocus(true);
WebRect rect, caret;
web_view_helper.GetWebView()->SelectionBounds(caret, rect);
- GetElementAndCaretBonundsForFocusedEditableElement(
+ GetElementAndCaretBoundsForFocusedEditableElement(
web_view_helper, element_bounds, caret_bounds);
web_view_helper.GetWebView()->ComputeScaleAndScrollForEditableElementRects(
element_bounds, caret_bounds, kAutoZoomToLegibleScale, scale, scroll,
@@ -4382,6 +4377,60 @@ TEST_F(WebFrameTest, DivScrollIntoEditableTestZoomToLegibleScaleDisabled) {
EXPECT_FALSE(need_animation);
}
+// Tests zoom into editable zoom and scroll correctly when zoom-for-dsf enabled.
+TEST_F(WebFrameTest, DivScrollIntoEditableTestWithDeviceScaleFactor) {
+ RegisterMockedHttpURLLoad("get_scale_for_zoom_into_editable_test.html");
+
+ bool kAutoZoomToLegibleScale = true;
+ const float kDeviceScaleFactor = 2.f;
+ int viewport_width = 200 * kDeviceScaleFactor;
+ int viewport_height = 150 * kDeviceScaleFactor;
+ float min_readable_caret_height = 16.0f * kDeviceScaleFactor;
+
+ FrameTestHelpers::WebViewHelper web_view_helper;
+ web_view_helper.InitializeAndLoad(
+ base_url_ + "get_scale_for_zoom_into_editable_test.html", nullptr,
+ nullptr, nullptr, ConfigureAndroid);
+ web_view_helper.GetWebView()
+ ->GetPage()
+ ->GetSettings()
+ .SetTextAutosizingEnabled(false);
+ web_view_helper.Resize(WebSize(viewport_width, viewport_height));
+ web_view_helper.GetWebView()->SetZoomFactorForDeviceScaleFactor(
+ kDeviceScaleFactor);
+ web_view_helper.GetWebView()->SetDefaultPageScaleLimits(0.25f, 4);
+
+ web_view_helper.GetWebView()->EnableFakePageScaleAnimationForTesting(true);
+
+ WebRect edit_box_with_text(200 * kDeviceScaleFactor, 200 * kDeviceScaleFactor,
+ 250 * kDeviceScaleFactor, 20 * kDeviceScaleFactor);
+ web_view_helper.GetWebView()->AdvanceFocus(false);
+
+ // Set the page scale to be smaller than the minimal readable scale.
+ float initial_scale = 0.5f;
+ SetScaleAndScrollAndLayout(web_view_helper.GetWebView(), WebPoint(0, 0),
+ initial_scale);
+ ASSERT_EQ(web_view_helper.GetWebView()->PageScaleFactor(), initial_scale);
+
+ float scale;
+ IntPoint scroll;
+ bool need_animation;
+ IntRect element_bounds, caret_bounds;
+ GetElementAndCaretBoundsForFocusedEditableElement(
+ web_view_helper, element_bounds, caret_bounds);
+ web_view_helper.GetWebView()->ComputeScaleAndScrollForEditableElementRects(
+ element_bounds, caret_bounds, kAutoZoomToLegibleScale, scale, scroll,
+ need_animation);
+ EXPECT_TRUE(need_animation);
+ // The edit box wider than the viewport when legible should be left aligned.
+ int h_scroll = edit_box_with_text.x;
+ EXPECT_NEAR(h_scroll, scroll.X(), 2);
+ int v_scroll = edit_box_with_text.y -
+ (viewport_height / scale - edit_box_with_text.height) / 2;
+ EXPECT_NEAR(v_scroll, scroll.Y(), 2);
+ EXPECT_NEAR(min_readable_caret_height / caret_bounds.Height(), scale, 0.1);
+}
+
TEST_F(WebFrameTest, CharacterIndexAtPointWithPinchZoom) {
RegisterMockedHttpURLLoad("sometext.html");
@@ -4460,7 +4509,7 @@ TEST_F(WebFrameTest, ReloadDoesntSetRedirect) {
FrameTestHelpers::WebViewHelper web_view_helper;
web_view_helper.InitializeAndLoad(base_url_ + "form.html", &web_frame_client);
- web_view_helper.GetWebView()->MainFrameImpl()->Reload(
+ web_view_helper.GetWebView()->MainFrameImpl()->StartReload(
WebFrameLoadType::kReloadBypassingCache);
// start another reload before request is delivered.
FrameTestHelpers::ReloadFrameBypassingCache(
@@ -4498,10 +4547,9 @@ TEST_F(WebFrameTest, ReloadPreservesState) {
web_view_helper.GetWebView()->SetPageScaleFactor(kPageScaleFactor);
// Reload the page and end up at the same url. State should not be propagated.
- web_view_helper.GetWebView()->MainFrameImpl()->Reload(
+ web_view_helper.GetWebView()->MainFrameImpl()->StartReload(
WebFrameLoadType::kReload);
- FrameTestHelpers::PumpPendingRequestsForFrameToLoad(
- web_view_helper.GetWebView()->MainFrame());
+ FrameTestHelpers::PumpPendingRequestsForFrameToLoad();
EXPECT_EQ(0, web_view_helper.LocalMainFrame()->GetScrollOffset().width);
EXPECT_EQ(0, web_view_helper.LocalMainFrame()->GetScrollOffset().height);
EXPECT_EQ(1.0f, web_view_helper.GetWebView()->PageScaleFactor());
@@ -4515,7 +4563,7 @@ TEST_F(WebFrameTest, ReloadWhileProvisional) {
FrameTestHelpers::WebViewHelper web_view_helper;
web_view_helper.Initialize();
WebURLRequest request(ToKURL(base_url_ + "fixed_layout.html"));
- web_view_helper.GetWebView()->MainFrameImpl()->LoadRequest(request);
+ web_view_helper.GetWebView()->MainFrameImpl()->StartNavigation(request);
// start reload before first request is delivered.
FrameTestHelpers::ReloadFrameBypassingCache(
web_view_helper.GetWebView()->MainFrameImpl());
@@ -4554,8 +4602,7 @@ TEST_F(WebFrameTest, IframeRedirect) {
web_view_helper.InitializeAndLoad(base_url_ + "iframe_redirect.html");
// Pump pending requests one more time. The test page loads script that
// navigates.
- FrameTestHelpers::PumpPendingRequestsForFrameToLoad(
- web_view_helper.GetWebView()->MainFrame());
+ FrameTestHelpers::PumpPendingRequestsForFrameToLoad();
WebFrame* iframe = web_view_helper.LocalMainFrame()->FindFrameByName(
WebString::FromUTF8("ifr"));
@@ -4641,8 +4688,8 @@ TEST_F(WebFrameTest, TabKeyCursorMoveTriggersOneSelectionChange) {
EXPECT_EQ(4, counter.Count());
}
-// Implementation of WebFrameClient that tracks the v8 contexts that are created
-// and destroyed for verification.
+// Implementation of WebLocalFrameClient that tracks the v8 contexts that are
+// created and destroyed for verification.
class ContextLifetimeTestWebFrameClient
: public FrameTestHelpers::TestWebFrameClient {
public:
@@ -4679,7 +4726,7 @@ class ContextLifetimeTestWebFrameClient
release_notifications_.clear();
}
- // WebFrameClient:
+ // WebLocalFrameClient:
WebLocalFrame* CreateChildFrame(WebLocalFrame* parent,
WebTreeScopeType scope,
const WebString& name,
@@ -5376,9 +5423,9 @@ TEST_F(WebFrameTest, SetTickmarks) {
// Get the tickmarks for the original find request.
LocalFrameView* frame_view = web_view_helper.LocalMainFrame()->GetFrameView();
- Scrollbar* scrollbar = frame_view->CreateScrollbar(kHorizontalScrollbar);
+ ScrollableArea* layout_viewport = frame_view->LayoutViewport();
Vector<IntRect> original_tickmarks;
- scrollbar->GetTickmarks(original_tickmarks);
+ layout_viewport->GetTickmarks(original_tickmarks);
EXPECT_EQ(4u, original_tickmarks.size());
// Override the tickmarks.
@@ -5390,7 +5437,7 @@ TEST_F(WebFrameTest, SetTickmarks) {
// Check the tickmarks are overriden correctly.
Vector<IntRect> overriding_tickmarks_actual;
- scrollbar->GetTickmarks(overriding_tickmarks_actual);
+ layout_viewport->GetTickmarks(overriding_tickmarks_actual);
EXPECT_EQ(overriding_tickmarks_expected, overriding_tickmarks_actual);
// Reset the tickmark behavior.
@@ -5399,7 +5446,7 @@ TEST_F(WebFrameTest, SetTickmarks) {
// Check that the original tickmarks are returned
Vector<IntRect> original_tickmarks_after_reset;
- scrollbar->GetTickmarks(original_tickmarks_after_reset);
+ layout_viewport->GetTickmarks(original_tickmarks_after_reset);
EXPECT_EQ(original_tickmarks, original_tickmarks_after_reset);
}
@@ -5456,7 +5503,7 @@ TEST_F(WebFrameTest, FindInPageJavaScriptUpdatesDOM) {
struct FakeTimerSetter {
FakeTimerSetter() {
- time_elapsed_ = 0.0;
+ time_elapsed_ = 1.0;
original_time_function_ = SetTimeFunctionsForTesting(ReturnMockTime);
}
@@ -5848,9 +5895,7 @@ TEST_F(WebFrameTest, SelectRangeCanMoveSelectionStart) {
EXPECT_EQ("Editable 2.", SelectionAsString(frame));
frame->SelectRange(BottomRightMinusOne(ElementBounds(frame, "editable_2")),
TopLeft(ElementBounds(frame, "header_2")));
- // positionForPoint returns the wrong values for contenteditable spans. See
- // http://crbug.com/238334.
- // EXPECT_EQ("[ Editable 1. Editable 2.", selectionAsString(frame));
+ EXPECT_EQ("[ Editable 1. Editable 2.", SelectionAsString(frame));
}
TEST_F(WebFrameTest, SelectRangeCanMoveSelectionEnd) {
@@ -5904,9 +5949,7 @@ TEST_F(WebFrameTest, SelectRangeCanMoveSelectionEnd) {
EXPECT_EQ("Editable 1.", SelectionAsString(frame));
frame->SelectRange(TopLeft(ElementBounds(frame, "editable_1")),
BottomRightMinusOne(ElementBounds(frame, "footer_1")));
- // positionForPoint returns the wrong values for contenteditable spans. See
- // http://crbug.com/238334.
- // EXPECT_EQ("Editable 1. Editable 2. ]", selectionAsString(frame));
+ EXPECT_EQ("Editable 1. Editable 2. ]", SelectionAsString(frame));
}
TEST_F(WebFrameTest, MoveRangeSelectionExtent) {
@@ -6230,66 +6273,15 @@ TEST_F(WebFrameTest, MoveCaretStaysHorizontallyAlignedWhenMoved) {
}
#endif
-class CompositedSelectionBoundsTestLayerTreeView : public WebLayerTreeView {
- public:
- CompositedSelectionBoundsTestLayerTreeView() : selection_cleared_(false) {}
- ~CompositedSelectionBoundsTestLayerTreeView() override = default;
-
- // WebLayerTreeView:
- void RegisterSelection(const WebSelection& selection) override {
- selection_ = std::make_unique<WebSelection>(selection);
- }
- void ClearSelection() override {
- selection_cleared_ = true;
- selection_.reset();
- }
-
- bool GetAndResetSelectionCleared() {
- bool selection_cleared = selection_cleared_;
- selection_cleared_ = false;
- return selection_cleared;
- }
-
- const WebSelection* Selection() const { return selection_.get(); }
- const WebSelectionBound* Start() const {
- return selection_ ? &selection_->Start() : nullptr;
- }
- const WebSelectionBound* end() const {
- return selection_ ? &selection_->end() : nullptr;
- }
-
- private:
- bool selection_cleared_;
- std::unique_ptr<WebSelection> selection_;
-};
-
-class CompositedSelectionBoundsTestWebViewClient
- : public FrameTestHelpers::TestWebViewClient {
- public:
- ~CompositedSelectionBoundsTestWebViewClient() override = default;
- WebLayerTreeView* InitializeLayerTreeView() override {
- return &test_layer_tree_view_;
- }
-
- CompositedSelectionBoundsTestLayerTreeView& SelectionLayerTreeView() {
- return test_layer_tree_view_;
- }
-
- private:
- CompositedSelectionBoundsTestLayerTreeView test_layer_tree_view_;
-};
-
class CompositedSelectionBoundsTest
: public WebFrameTest,
private ScopedCompositedSelectionUpdateForTest {
protected:
CompositedSelectionBoundsTest()
- : ScopedCompositedSelectionUpdateForTest(true),
- fake_selection_layer_tree_view_(
- fake_selection_web_view_client_.SelectionLayerTreeView()) {
+ : ScopedCompositedSelectionUpdateForTest(true) {
RegisterMockedHttpURLLoad("Ahem.ttf");
- web_view_helper_.Initialize(nullptr, &fake_selection_web_view_client_);
+ web_view_helper_.Initialize(nullptr, &web_view_client_);
web_view_helper_.GetWebView()->GetSettings()->SetDefaultFontSize(12);
web_view_helper_.GetWebView()->SetDefaultPageScaleLimits(1, 1);
web_view_helper_.Resize(WebSize(640, 480));
@@ -6302,14 +6294,13 @@ class CompositedSelectionBoundsTest
base_url_ + test_file);
web_view_helper_.GetWebView()->UpdateAllLifecyclePhases();
- const WebSelection* selection = fake_selection_layer_tree_view_.Selection();
- const WebSelectionBound* select_start =
- fake_selection_layer_tree_view_.Start();
- const WebSelectionBound* select_end = fake_selection_layer_tree_view_.end();
+ cc::LayerTreeHost* layer_tree_host =
+ web_view_client_.layer_tree_view()->layer_tree_host();
+ const cc::LayerSelection& selection = layer_tree_host->selection();
- EXPECT_FALSE(selection);
- EXPECT_FALSE(select_start);
- EXPECT_FALSE(select_end);
+ ASSERT_EQ(selection, cc::LayerSelection());
+ ASSERT_EQ(selection.start, cc::LayerSelectionBound());
+ ASSERT_EQ(selection.end, cc::LayerSelectionBound());
}
void RunTest(const char* test_file) {
@@ -6403,16 +6394,13 @@ class CompositedSelectionBoundsTest
->GetEventHandler()
.HandleGestureEvent(gesture_event);
- const WebSelection* selection = fake_selection_layer_tree_view_.Selection();
- const WebSelectionBound* select_start =
- fake_selection_layer_tree_view_.Start();
- const WebSelectionBound* select_end = fake_selection_layer_tree_view_.end();
-
- ASSERT_TRUE(selection);
- ASSERT_TRUE(select_start);
- ASSERT_TRUE(select_end);
+ cc::LayerTreeHost* layer_tree_host =
+ web_view_client_.layer_tree_view()->layer_tree_host();
+ const cc::LayerSelection& selection = layer_tree_host->selection();
- EXPECT_FALSE(selection->IsNone());
+ ASSERT_NE(selection, cc::LayerSelection());
+ ASSERT_NE(selection.start, cc::LayerSelectionBound());
+ ASSERT_NE(selection.end, cc::LayerSelectionBound());
blink::Node* layer_owner_node_for_start = V8Node::ToImplWithTypeCheck(
v8::Isolate::GetCurrent(), expected_result.Get(0));
@@ -6420,12 +6408,11 @@ class CompositedSelectionBoundsTest
EXPECT_EQ(GetExpectedLayerForSelection(layer_owner_node_for_start)
->CcLayer()
->id(),
- select_start->layer_id);
+ selection.start.layer_id);
- EXPECT_EQ(start_edge_top_in_layer_x, select_start->edge_top_in_layer.x);
- EXPECT_EQ(start_edge_top_in_layer_y, select_start->edge_top_in_layer.y);
- EXPECT_EQ(start_edge_bottom_in_layer_x,
- select_start->edge_bottom_in_layer.x);
+ EXPECT_EQ(start_edge_top_in_layer_x, selection.start.edge_top.x());
+ EXPECT_EQ(start_edge_top_in_layer_y, selection.start.edge_top.y());
+ EXPECT_EQ(start_edge_bottom_in_layer_x, selection.start.edge_bottom.x());
blink::Node* layer_owner_node_for_end = V8Node::ToImplWithTypeCheck(
v8::Isolate::GetCurrent(),
@@ -6434,11 +6421,11 @@ class CompositedSelectionBoundsTest
ASSERT_TRUE(layer_owner_node_for_end);
EXPECT_EQ(
GetExpectedLayerForSelection(layer_owner_node_for_end)->CcLayer()->id(),
- select_end->layer_id);
+ selection.end.layer_id);
- EXPECT_EQ(end_edge_top_in_layer_x, select_end->edge_top_in_layer.x);
- EXPECT_EQ(end_edge_top_in_layer_y, select_end->edge_top_in_layer.y);
- EXPECT_EQ(end_edge_bottom_in_layer_x, select_end->edge_bottom_in_layer.x);
+ EXPECT_EQ(end_edge_top_in_layer_x, selection.end.edge_top.x());
+ EXPECT_EQ(end_edge_top_in_layer_y, selection.end.edge_top.y());
+ EXPECT_EQ(end_edge_bottom_in_layer_x, selection.end.edge_bottom.x());
// Platform differences can introduce small stylistic deviations in
// y-axis positioning, the details of which aren't relevant to
@@ -6453,10 +6440,10 @@ class CompositedSelectionBoundsTest
}
int y_bottom_deviation =
- start_edge_bottom_in_layer_y - select_start->edge_bottom_in_layer.y;
+ start_edge_bottom_in_layer_y - selection.start.edge_bottom.y();
EXPECT_GE(y_bottom_epsilon, std::abs(y_bottom_deviation));
EXPECT_EQ(y_bottom_deviation,
- end_edge_bottom_in_layer_y - select_end->edge_bottom_in_layer.y);
+ end_edge_bottom_in_layer_y - selection.end.edge_bottom.y());
if (expected_result.Length() >= 15) {
bool start_hidden = expected_result.Get(context, 13)
@@ -6468,8 +6455,8 @@ class CompositedSelectionBoundsTest
.As<v8::Boolean>()
->Value();
- EXPECT_EQ(start_hidden, select_start->hidden);
- EXPECT_EQ(end_hidden, select_end->hidden);
+ EXPECT_EQ(start_hidden, selection.start.hidden);
+ EXPECT_EQ(end_hidden, selection.end.hidden);
}
}
@@ -6495,8 +6482,7 @@ class CompositedSelectionBoundsTest
: clm->MainGraphicsLayer();
}
- CompositedSelectionBoundsTestWebViewClient fake_selection_web_view_client_;
- CompositedSelectionBoundsTestLayerTreeView& fake_selection_layer_tree_view_;
+ FrameTestHelpers::TestWebViewClient web_view_client_;
FrameTestHelpers::WebViewHelper web_view_helper_;
};
@@ -6752,7 +6738,7 @@ TEST_F(WebFrameTest, DisambiguationPopupVisualViewport) {
// Scroll main frame to the bottom of the document
web_view_impl->MainFrameImpl()->SetScrollOffset(WebSize(0, 400));
EXPECT_EQ(ScrollOffset(0, 400),
- frame->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ frame->View()->LayoutViewport()->GetScrollOffset());
web_view_impl->SetPageScaleFactor(2.0);
@@ -6911,7 +6897,6 @@ TEST_F(WebFrameTest, ReplaceNavigationAfterHistoryNavigation) {
Platform::Current()->GetURLLoaderMockFactory()->RegisterErrorURL(
URLTestHelpers::ToKURL(error_url), response, error);
FrameTestHelpers::LoadHistoryItem(frame, error_history_item,
- kWebHistoryDifferentDocumentLoad,
mojom::FetchCacheMode::kDefault);
WebString text = WebFrameContentDumper::DumpWebViewAsText(
web_view_helper.GetWebView(), std::numeric_limits<size_t>::max());
@@ -6922,20 +6907,16 @@ TEST_F(WebFrameTest, ReplaceNavigationAfterHistoryNavigation) {
class TestWillInsertBodyWebFrameClient
: public FrameTestHelpers::TestWebFrameClient {
public:
- TestWillInsertBodyWebFrameClient() : num_bodies_(0), did_load_(false) {}
+ TestWillInsertBodyWebFrameClient() : did_load_(false) {}
~TestWillInsertBodyWebFrameClient() override = default;
// FrameTestHelpers::TestWebFrameClient:
void DidCommitProvisionalLoad(const WebHistoryItem&,
WebHistoryCommitType,
WebGlobalObjectReusePolicy) override {
- num_bodies_ = 0;
did_load_ = true;
}
- void DidCreateDocumentElement() override { EXPECT_EQ(0, num_bodies_); }
- void WillInsertBody() override { num_bodies_++; }
- int num_bodies_;
bool did_load_;
};
@@ -6948,7 +6929,6 @@ TEST_F(WebFrameTest, HTMLDocument) {
&web_frame_client);
EXPECT_TRUE(web_frame_client.did_load_);
- EXPECT_EQ(1, web_frame_client.num_bodies_);
}
TEST_F(WebFrameTest, EmptyDocument) {
@@ -6959,8 +6939,6 @@ TEST_F(WebFrameTest, EmptyDocument) {
web_view_helper.Initialize(&web_frame_client);
EXPECT_FALSE(web_frame_client.did_load_);
- // The empty document that a new frame starts with triggers this.
- EXPECT_EQ(1, web_frame_client.num_bodies_);
}
TEST_F(WebFrameTest, MoveCaretSelectionTowardsWindowPointWithNoSelection) {
@@ -7469,7 +7447,7 @@ class TestScrolledFrameClient : public FrameTestHelpers::TestWebFrameClient {
void Reset() { did_scroll_frame_ = false; }
bool WasFrameScrolled() const { return did_scroll_frame_; }
- // WebFrameClient:
+ // WebLocalFrameClient:
void DidChangeScrollOffset() override {
if (Frame()->Parent())
return;
@@ -7507,11 +7485,10 @@ TEST_F(WebFrameTest, CompositorScrollIsUserScrollLongPage) {
EXPECT_FALSE(client.WasFrameScrolled());
EXPECT_FALSE(initial_scroll_state.was_scrolled_by_user);
- auto* scrollable_area =
- frame_impl->GetFrameView()->LayoutViewportScrollableArea();
+ auto* scrollable_area = frame_impl->GetFrameView()->LayoutViewport();
// Do a compositor scroll, verify that this is counted as a user scroll.
- scrollable_area->DidScroll(gfx::ScrollOffset(0, 1));
+ scrollable_area->DidScroll(FloatPoint(0, 1));
web_view_helper.GetWebView()->ApplyViewportDeltas(
WebFloatSize(), WebFloatSize(), WebFloatSize(), 1.7f, 0);
EXPECT_TRUE(client.WasFrameScrolled());
@@ -7521,7 +7498,7 @@ TEST_F(WebFrameTest, CompositorScrollIsUserScrollLongPage) {
initial_scroll_state.was_scrolled_by_user = false;
// The page scale 1.0f and scroll.
- scrollable_area->DidScroll(gfx::ScrollOffset(0, 2));
+ scrollable_area->DidScroll(FloatPoint(0, 2));
web_view_helper.GetWebView()->ApplyViewportDeltas(
WebFloatSize(), WebFloatSize(), WebFloatSize(), 1.0f, 0);
EXPECT_TRUE(client.WasFrameScrolled());
@@ -7530,7 +7507,7 @@ TEST_F(WebFrameTest, CompositorScrollIsUserScrollLongPage) {
initial_scroll_state.was_scrolled_by_user = false;
// No scroll event if there is no scroll delta.
- scrollable_area->DidScroll(gfx::ScrollOffset(0, 2));
+ scrollable_area->DidScroll(FloatPoint(0, 2));
web_view_helper.GetWebView()->ApplyViewportDeltas(
WebFloatSize(), WebFloatSize(), WebFloatSize(), 1.0f, 0);
EXPECT_FALSE(client.WasFrameScrolled());
@@ -7538,7 +7515,7 @@ TEST_F(WebFrameTest, CompositorScrollIsUserScrollLongPage) {
client.Reset();
// Non zero page scale and scroll.
- scrollable_area->DidScroll(gfx::ScrollOffset(9, 15));
+ scrollable_area->DidScroll(FloatPoint(9, 15));
web_view_helper.GetWebView()->ApplyViewportDeltas(
WebFloatSize(), WebFloatSize(), WebFloatSize(), 0.6f, 0);
EXPECT_TRUE(client.WasFrameScrolled());
@@ -7585,51 +7562,6 @@ TEST_F(WebFrameTest, SiteForCookiesForRedirect) {
.SiteForCookies() == redirect_url);
}
-class TestNavigationPolicyWebFrameClient
- : public FrameTestHelpers::TestWebFrameClient {
- public:
- TestNavigationPolicyWebFrameClient() = default;
- ~TestNavigationPolicyWebFrameClient() override = default;
-
- // FrameTestHelpers::TestWebFrameClient:
- void DidFinishSameDocumentNavigation(const WebHistoryItem&,
- WebHistoryCommitType,
- bool) override {
- EXPECT_TRUE(false);
- }
-
- WebNavigationPolicy DecidePolicyForNavigation(
- const NavigationPolicyInfo& info) override {
- return kWebNavigationPolicyIgnore;
- }
-};
-
-TEST_F(WebFrameTest, SimulateFragmentAnchorMiddleClick) {
- RegisterMockedHttpURLLoad("fragment_middle_click.html");
- TestNavigationPolicyWebFrameClient client;
- FrameTestHelpers::WebViewHelper web_view_helper;
- web_view_helper.InitializeAndLoad(base_url_ + "fragment_middle_click.html",
- &client);
-
- Document* document =
- ToLocalFrame(web_view_helper.GetWebView()->GetPage()->MainFrame())
- ->GetDocument();
- KURL destination = document->Url();
- destination.SetFragmentIdentifier("test");
-
- MouseEventInit mouse_initializer;
- mouse_initializer.setView(document->domWindow());
- mouse_initializer.setButton(1);
-
- Event* event =
- MouseEvent::Create(nullptr, EventTypeNames::click, mouse_initializer);
- FrameLoadRequest frame_request(document, ResourceRequest(destination));
- frame_request.SetTriggeringEvent(event);
- ToLocalFrame(web_view_helper.GetWebView()->GetPage()->MainFrame())
- ->Loader()
- .StartNavigation(frame_request);
-}
-
class TestNewWindowWebViewClient : public FrameTestHelpers::TestWebViewClient {
public:
TestNewWindowWebViewClient() = default;
@@ -7657,17 +7589,24 @@ class TestNewWindowWebFrameClient
// FrameTestHelpers::TestWebFrameClient:
WebNavigationPolicy DecidePolicyForNavigation(
const NavigationPolicyInfo& info) override {
- decide_policy_call_count_++;
- return kWebNavigationPolicyIgnore;
+ if (ignore_navigations_) {
+ decide_policy_call_count_++;
+ return kWebNavigationPolicyIgnore;
+ }
+ return info.default_policy;
}
int DecidePolicyCallCount() const { return decide_policy_call_count_; }
+ void IgnoreNavigations() { ignore_navigations_ = true; }
private:
+ bool ignore_navigations_ = false;
int decide_policy_call_count_;
};
TEST_F(WebFrameTest, ModifiedClickNewWindow) {
+ // This test checks that ctrl+click does not just open a new window,
+ // but instead goes to client to decide the navigation policy.
RegisterMockedHttpURLLoad("ctrl_click.html");
RegisterMockedHttpURLLoad("hello_world.html");
TestNewWindowWebViewClient web_view_client;
@@ -7690,18 +7629,19 @@ TEST_F(WebFrameTest, ModifiedClickNewWindow) {
Event* event =
MouseEvent::Create(nullptr, EventTypeNames::click, mouse_initializer);
FrameLoadRequest frame_request(document, ResourceRequest(destination));
- frame_request.SetTriggeringEvent(event);
+ frame_request.SetTriggeringEventInfo(
+ WebTriggeringEventInfo::kFromTrustedEvent);
std::unique_ptr<UserGestureIndicator> gesture =
Frame::NotifyUserActivation(frame);
+ web_frame_client.IgnoreNavigations();
ToLocalFrame(web_view_helper.GetWebView()->GetPage()->MainFrame())
->Loader()
- .StartNavigation(frame_request);
- FrameTestHelpers::PumpPendingRequestsForFrameToLoad(
- web_view_helper.GetWebView()->MainFrame());
+ .StartNavigation(frame_request, WebFrameLoadType::kStandard,
+ NavigationPolicyFromEvent(event));
+ FrameTestHelpers::PumpPendingRequestsForFrameToLoad();
- // decidePolicyForNavigation should be called both for the original request
- // and the ctrl+click.
- EXPECT_EQ(2, web_frame_client.DecidePolicyCallCount());
+ // decidePolicyForNavigation should be called for the ctrl+click.
+ EXPECT_EQ(1, web_frame_client.DecidePolicyCallCount());
}
TEST_F(WebFrameTest, BackToReload) {
@@ -7721,7 +7661,6 @@ TEST_F(WebFrameTest, BackToReload) {
main_frame_loader.GetDocumentLoader()->GetHistoryItem());
FrameTestHelpers::LoadHistoryItem(frame, WebHistoryItem(first_item.Get()),
- kWebHistoryDifferentDocumentLoad,
mojom::FetchCacheMode::kDefault);
EXPECT_EQ(first_item.Get(),
main_frame_loader.GetDocumentLoader()->GetHistoryItem());
@@ -7753,10 +7692,9 @@ TEST_F(WebFrameTest, BackDuringChildFrameReload) {
HistoryItem* history_item = item;
ResourceRequest request =
history_item->GenerateResourceRequest(mojom::FetchCacheMode::kDefault);
- main_frame->CommitNavigation(WrappedResourceRequest(request),
- WebFrameLoadType::kBackForward, item,
- kWebHistoryDifferentDocumentLoad, false,
- base::UnguessableToken::Create());
+ main_frame->CommitNavigation(
+ WrappedResourceRequest(request), WebFrameLoadType::kBackForward, item,
+ false, base::UnguessableToken::Create(), nullptr, WebNavigationTimings());
FrameTestHelpers::ReloadFrame(child_frame);
EXPECT_EQ(item.UrlString(), main_frame->GetDocument().Url().GetString());
@@ -7775,8 +7713,7 @@ TEST_F(WebFrameTest, ReloadPost) {
"javascript:document.forms[0].submit()");
// Pump requests one more time after the javascript URL has executed to
// trigger the actual POST load request.
- FrameTestHelpers::PumpPendingRequestsForFrameToLoad(
- web_view_helper.GetWebView()->MainFrame());
+ FrameTestHelpers::PumpPendingRequestsForFrameToLoad();
EXPECT_EQ(WebString::FromUTF8("POST"),
frame->GetDocumentLoader()->GetRequest().HttpMethod());
@@ -7805,7 +7742,6 @@ TEST_F(WebFrameTest, LoadHistoryItemReload) {
// Cache policy overrides should take.
FrameTestHelpers::LoadHistoryItem(frame, WebHistoryItem(first_item),
- kWebHistoryDifferentDocumentLoad,
mojom::FetchCacheMode::kValidateCache);
EXPECT_EQ(first_item.Get(),
main_frame_loader.GetDocumentLoader()->GetHistoryItem());
@@ -7905,7 +7841,7 @@ class TestSameDocumentWebFrameClient
FrameLoader& frame_loader =
ToWebLocalFrameImpl(Frame())->GetFrame()->Loader();
if (frame_loader.GetProvisionalDocumentLoader()->LoadType() ==
- kFrameLoadTypeReload)
+ WebFrameLoadType::kReload)
frame_load_type_reload_seen_ = true;
}
@@ -7932,8 +7868,7 @@ TEST_F(WebFrameTest, NavigateToSame) {
ToLocalFrame(web_view_helper.GetWebView()->GetPage()->MainFrame())
->Loader()
.StartNavigation(frame_request);
- FrameTestHelpers::PumpPendingRequestsForFrameToLoad(
- web_view_helper.GetWebView()->MainFrame());
+ FrameTestHelpers::PumpPendingRequestsForFrameToLoad();
EXPECT_TRUE(client.FrameLoadTypeReloadSeen());
}
@@ -7994,12 +7929,11 @@ TEST_F(WebFrameTest, WebNodeImageContents) {
WebNode node = frame->GetDocument().Body().FirstChild();
EXPECT_TRUE(node.IsElementNode());
WebElement element = node.To<WebElement>();
- WebImage image = element.ImageContents();
- ASSERT_FALSE(image.IsNull());
- EXPECT_EQ(image.Size().width, 10);
- EXPECT_EQ(image.Size().height, 10);
- SkBitmap bitmap = image.GetSkBitmap();
- EXPECT_EQ(bitmap.getColor(0, 0), SK_ColorBLUE);
+ SkBitmap image = element.ImageContents();
+ ASSERT_FALSE(image.isNull());
+ EXPECT_EQ(image.width(), 10);
+ EXPECT_EQ(image.height(), 10);
+ EXPECT_EQ(image.getColor(0, 0), SK_ColorBLUE);
}
TEST_F(WebFrameTest, WebNodeImageContentsWithOrientation) {
@@ -8045,13 +7979,12 @@ TEST_F(WebFrameTest, WebNodeImageContentsWithOrientation) {
EXPECT_TRUE(node.IsElementNode());
WebElement element = node.To<WebElement>();
- WebImage image_with_orientation = element.ImageContents();
- ASSERT_FALSE(image_with_orientation.IsNull());
- EXPECT_EQ(image_with_orientation.Size().width, 8);
- EXPECT_EQ(image_with_orientation.Size().height, 4);
- SkBitmap oriented_bitmap = image_with_orientation.GetSkBitmap();
+ SkBitmap image_with_orientation = element.ImageContents();
+ ASSERT_FALSE(image_with_orientation.isNull());
+ EXPECT_EQ(image_with_orientation.width(), 8);
+ EXPECT_EQ(image_with_orientation.height(), 4);
// Should be almost blue.
- SkColor oriented_color = oriented_bitmap.getColor(0, 0);
+ SkColor oriented_color = image_with_orientation.getColor(0, 0);
EXPECT_NEAR(SkColorGetR(oriented_color), SkColorGetR(SK_ColorBLUE), 5);
EXPECT_NEAR(SkColorGetG(oriented_color), SkColorGetG(SK_ColorBLUE), 5);
EXPECT_NEAR(SkColorGetB(oriented_color), SkColorGetB(SK_ColorBLUE), 5);
@@ -8137,10 +8070,9 @@ TEST_F(WebFrameTest, SameDocumentHistoryNavigationCommitType) {
ToLocalFrame(web_view_impl->GetPage()->MainFrame())
->Loader()
- .CommitNavigation(
- FrameLoadRequest(nullptr, item->GenerateResourceRequest(
- mojom::FetchCacheMode::kDefault)),
- kFrameLoadTypeBackForward, item.Get(), kHistorySameDocumentLoad);
+ .CommitSameDocumentNavigation(
+ item->Url(), WebFrameLoadType::kBackForward, item.Get(),
+ ClientRedirectPolicy::kNotClientRedirect, nullptr, false);
EXPECT_EQ(kWebBackForwardCommit, client.LastCommitType());
}
@@ -8289,12 +8221,12 @@ TEST_F(WebFrameTest, CurrentHistoryItem) {
const FrameLoader& main_frame_loader =
web_view_helper.LocalMainFrame()->GetFrame()->Loader();
WebURLRequest request(ToKURL(url));
- frame->LoadRequest(request);
+ frame->StartNavigation(request);
// Before commit, there is no history item.
EXPECT_FALSE(main_frame_loader.GetDocumentLoader()->GetHistoryItem());
- FrameTestHelpers::PumpPendingRequestsForFrameToLoad(frame);
+ FrameTestHelpers::PumpPendingRequestsForFrameToLoad();
// After commit, there is.
HistoryItem* item = main_frame_loader.GetDocumentLoader()->GetHistoryItem();
@@ -8326,7 +8258,7 @@ class FailCreateChildFrame : public FrameTestHelpers::TestWebFrameClient {
int call_count_;
};
-// Test that we don't crash if WebFrameClient::createChildFrame() fails.
+// Test that we don't crash if WebLocalFrameClient::createChildFrame() fails.
TEST_F(WebFrameTest, CreateChildFrameFailure) {
RegisterMockedHttpURLLoad("create_child_frame_fail.html");
FailCreateChildFrame client;
@@ -8396,27 +8328,27 @@ TEST_F(WebFrameTest, FrameViewScrollAccountsForBrowserControls) {
web_view->MainFrameImpl()->SetScrollOffset(WebSize(0, 2000));
EXPECT_EQ(ScrollOffset(0, 1900),
- frame_view->LayoutViewportScrollableArea()->GetScrollOffset());
+ frame_view->LayoutViewport()->GetScrollOffset());
// Simulate the browser controls showing by 20px, thus shrinking the viewport
// and allowing it to scroll an additional 20px.
web_view->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), WebFloatSize(),
1.0f, 20.0f / browser_controls_height);
EXPECT_EQ(ScrollOffset(0, 1920),
- frame_view->LayoutViewportScrollableArea()->MaximumScrollOffset());
+ frame_view->LayoutViewport()->MaximumScrollOffset());
// Show more, make sure the scroll actually gets clamped.
web_view->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), WebFloatSize(),
1.0f, 20.0f / browser_controls_height);
web_view->MainFrameImpl()->SetScrollOffset(WebSize(0, 2000));
EXPECT_EQ(ScrollOffset(0, 1940),
- frame_view->LayoutViewportScrollableArea()->GetScrollOffset());
+ frame_view->LayoutViewport()->GetScrollOffset());
// Hide until there's 10px showing.
web_view->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), WebFloatSize(),
1.0f, -30.0f / browser_controls_height);
EXPECT_EQ(ScrollOffset(0, 1910),
- frame_view->LayoutViewportScrollableArea()->MaximumScrollOffset());
+ frame_view->LayoutViewport()->MaximumScrollOffset());
// Simulate a LayoutEmbeddedContent::resize. The frame is resized to
// accomodate the browser controls and Blink's view of the browser controls
@@ -8426,13 +8358,13 @@ TEST_F(WebFrameTest, FrameViewScrollAccountsForBrowserControls) {
web_view->ResizeWithBrowserControls(WebSize(100, 60), 40.0f, 0, true);
web_view->UpdateAllLifecyclePhases();
EXPECT_EQ(ScrollOffset(0, 1940),
- frame_view->LayoutViewportScrollableArea()->MaximumScrollOffset());
+ frame_view->LayoutViewport()->MaximumScrollOffset());
// Now simulate hiding.
web_view->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), WebFloatSize(),
1.0f, -10.0f / browser_controls_height);
EXPECT_EQ(ScrollOffset(0, 1930),
- frame_view->LayoutViewportScrollableArea()->MaximumScrollOffset());
+ frame_view->LayoutViewport()->MaximumScrollOffset());
// Reset to original state: 100px widget height, browser controls fully
// hidden.
@@ -8442,7 +8374,7 @@ TEST_F(WebFrameTest, FrameViewScrollAccountsForBrowserControls) {
browser_controls_height, 0, false);
web_view->UpdateAllLifecyclePhases();
EXPECT_EQ(ScrollOffset(0, 1900),
- frame_view->LayoutViewportScrollableArea()->MaximumScrollOffset());
+ frame_view->LayoutViewport()->MaximumScrollOffset());
// Show the browser controls by just 1px, since we're zoomed in to 2X, that
// should allow an extra 0.5px of scrolling in the visual viewport. Make
@@ -8451,12 +8383,12 @@ TEST_F(WebFrameTest, FrameViewScrollAccountsForBrowserControls) {
web_view->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), WebFloatSize(),
1.0f, 1.0f / browser_controls_height);
EXPECT_EQ(ScrollOffset(0, 1901),
- frame_view->LayoutViewportScrollableArea()->MaximumScrollOffset());
+ frame_view->LayoutViewport()->MaximumScrollOffset());
web_view->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), WebFloatSize(),
1.0f, 2.0f / browser_controls_height);
EXPECT_EQ(ScrollOffset(0, 1903),
- frame_view->LayoutViewportScrollableArea()->MaximumScrollOffset());
+ frame_view->LayoutViewport()->MaximumScrollOffset());
}
TEST_F(WebFrameTest, MaximumScrollPositionCanBeNegative) {
@@ -8480,7 +8412,7 @@ TEST_F(WebFrameTest, MaximumScrollPositionCanBeNegative) {
web_view_helper.GetWebView()->UpdateAllLifecyclePhases();
LocalFrameView* frame_view = web_view_helper.LocalMainFrame()->GetFrameView();
- ScrollableArea* layout_viewport = frame_view->LayoutViewportScrollableArea();
+ ScrollableArea* layout_viewport = frame_view->LayoutViewport();
EXPECT_LT(layout_viewport->MaximumScrollOffset().Width(), 0);
}
@@ -8511,8 +8443,8 @@ TEST_F(WebFrameTest, FullscreenLayerSize) {
EXPECT_EQ(div_fullscreen, Fullscreen::FullscreenElementFrom(*document));
// Verify that the element is sized to the viewport.
- LayoutFullScreen* fullscreen_layout_object =
- Fullscreen::From(*document).FullScreenLayoutObject();
+ LayoutBox* fullscreen_layout_object =
+ ToLayoutBox(div_fullscreen->GetLayoutObject());
EXPECT_EQ(viewport_width, fullscreen_layout_object->LogicalWidth().ToInt());
EXPECT_EQ(viewport_height, fullscreen_layout_object->LogicalHeight().ToInt());
@@ -8599,7 +8531,7 @@ TEST_F(WebFrameTest, FullscreenMainFrame) {
cc::Layer* cc_scroll_layer = web_view_impl->MainFrameImpl()
->GetFrame()
->View()
- ->LayoutViewportScrollableArea()
+ ->LayoutViewport()
->LayerForScrolling()
->CcLayer();
ASSERT_TRUE(cc_scroll_layer->scrollable());
@@ -8624,7 +8556,7 @@ TEST_F(WebFrameTest, FullscreenMainFrame) {
cc_scroll_layer = web_view_impl->MainFrameImpl()
->GetFrame()
->View()
- ->LayoutViewportScrollableArea()
+ ->LayoutViewport()
->LayerForScrolling()
->CcLayer();
ASSERT_TRUE(cc_scroll_layer->scrollable());
@@ -8666,8 +8598,8 @@ TEST_F(WebFrameTest, FullscreenSubframe) {
web_view_impl->UpdateAllLifecyclePhases();
// Verify that the element is sized to the viewport.
- LayoutFullScreen* fullscreen_layout_object =
- Fullscreen::From(*document).FullScreenLayoutObject();
+ LayoutBox* fullscreen_layout_object =
+ ToLayoutBox(div_fullscreen->GetLayoutObject());
EXPECT_EQ(viewport_width, fullscreen_layout_object->LogicalWidth().ToInt());
EXPECT_EQ(viewport_height, fullscreen_layout_object->LogicalHeight().ToInt());
@@ -8954,44 +8886,16 @@ TEST_F(WebFrameTest, ClearFullscreenConstraintsOnNavigation) {
EXPECT_FLOAT_EQ(5.0, web_view_impl->MaximumPageScaleFactor());
}
-namespace {
-
-class TestFullscreenWebLayerTreeView : public WebLayerTreeView {
- public:
- TestFullscreenWebLayerTreeView() = default;
- ~TestFullscreenWebLayerTreeView() override = default;
-
- // WebLayerTreeView:
- void SetBackgroundColor(SkColor color) override {
- has_transparent_background = SkColorGetA(color) < SK_AlphaOPAQUE;
- }
- bool has_transparent_background = false;
-};
-
-class TestFullscreenWebViewClient : public FrameTestHelpers::TestWebViewClient {
- public:
- TestFullscreenWebViewClient() = default;
- ~TestFullscreenWebViewClient() override = default;
-
- // FrameTestHelpers::TestWebViewClient:
- WebLayerTreeView* InitializeLayerTreeView() override {
- return &test_fullscreen_layer_tree_view;
- }
- TestFullscreenWebLayerTreeView test_fullscreen_layer_tree_view;
-};
-
-} // namespace
-
TEST_F(WebFrameTest, OverlayFullscreenVideo) {
ScopedForceOverlayFullscreenVideoForTest force_overlay_fullscreen_video(true);
RegisterMockedHttpURLLoad("fullscreen_video.html");
- TestFullscreenWebViewClient web_view_client;
+ FrameTestHelpers::TestWebViewClient web_view_client;
FrameTestHelpers::WebViewHelper web_view_helper;
WebViewImpl* web_view_impl = web_view_helper.InitializeAndLoad(
base_url_ + "fullscreen_video.html", nullptr, &web_view_client);
- const TestFullscreenWebLayerTreeView& layer_tree_view =
- web_view_client.test_fullscreen_layer_tree_view;
+ const cc::LayerTreeHost* layer_tree_host =
+ web_view_client.layer_tree_view()->layer_tree_host();
LocalFrame* frame = web_view_impl->MainFrameImpl()->GetFrame();
std::unique_ptr<UserGestureIndicator> gesture =
@@ -9000,18 +8904,18 @@ TEST_F(WebFrameTest, OverlayFullscreenVideo) {
ToHTMLVideoElement(frame->GetDocument()->getElementById("video"));
EXPECT_TRUE(video->UsesOverlayFullscreenVideo());
EXPECT_FALSE(video->IsFullscreen());
- EXPECT_FALSE(layer_tree_view.has_transparent_background);
+ EXPECT_EQ(SkColorGetA(layer_tree_host->background_color()), SK_AlphaOPAQUE);
video->webkitEnterFullscreen();
web_view_impl->DidEnterFullscreen();
web_view_impl->UpdateAllLifecyclePhases();
EXPECT_TRUE(video->IsFullscreen());
- EXPECT_TRUE(layer_tree_view.has_transparent_background);
+ EXPECT_LT(SkColorGetA(layer_tree_host->background_color()), SK_AlphaOPAQUE);
web_view_impl->DidExitFullscreen();
web_view_impl->UpdateAllLifecyclePhases();
EXPECT_FALSE(video->IsFullscreen());
- EXPECT_FALSE(layer_tree_view.has_transparent_background);
+ EXPECT_EQ(SkColorGetA(layer_tree_host->background_color()), SK_AlphaOPAQUE);
}
TEST_F(WebFrameTest, LayoutBlockPercentHeightDescendants) {
@@ -9714,7 +9618,7 @@ TEST_F(WebFrameSwapTest, SetTimeoutAfterSwap) {
WebFrame* target_frame = MainFrame()->FirstChild();
target_frame->Swap(remote_frame);
remote_frame->SetReplicatedOrigin(
- WebSecurityOrigin(SecurityOrigin::CreateUnique()), false);
+ WebSecurityOrigin(SecurityOrigin::CreateUniqueOpaque()), false);
// Invoking setTimeout should throw a security error.
{
@@ -9796,7 +9700,7 @@ TEST_F(WebFrameSwapTest, RemoteWindowNamedAccess) {
WebRemoteFrame* remote_frame = FrameTestHelpers::CreateRemote();
LastChild(MainFrame())->Swap(remote_frame);
remote_frame->SetReplicatedOrigin(
- WebSecurityOrigin(SecurityOrigin::CreateUnique()), false);
+ WebSecurityOrigin(SecurityOrigin::CreateUniqueOpaque()), false);
v8::Local<v8::Value> remote_window_property =
MainFrame()->ExecuteScriptAndReturnValue(
WebScriptSource("window[2].foo"));
@@ -9826,7 +9730,7 @@ TEST_F(WebFrameSwapTest, FramesOfRemoteParentAreIndexable) {
WebRemoteFrame* remote_parent_frame = FrameTestHelpers::CreateRemote();
MainFrame()->Swap(remote_parent_frame);
remote_parent_frame->SetReplicatedOrigin(
- WebSecurityOrigin(SecurityOrigin::CreateUnique()), false);
+ WebSecurityOrigin(SecurityOrigin::CreateUniqueOpaque()), false);
WebLocalFrame* child_frame =
FrameTestHelpers::CreateLocalChild(*remote_parent_frame);
@@ -9854,7 +9758,7 @@ TEST_F(WebFrameSwapTest, FrameElementInFramesWithRemoteParent) {
WebRemoteFrame* remote_parent_frame = FrameTestHelpers::CreateRemote();
MainFrame()->Swap(remote_parent_frame);
remote_parent_frame->SetReplicatedOrigin(
- WebSecurityOrigin(SecurityOrigin::CreateUnique()), false);
+ WebSecurityOrigin(SecurityOrigin::CreateUniqueOpaque()), false);
WebLocalFrame* child_frame =
FrameTestHelpers::CreateLocalChild(*remote_parent_frame);
@@ -9907,7 +9811,7 @@ TEST_F(WebFrameSwapTest, HistoryCommitTypeAfterNewRemoteToLocalSwap) {
WebLocalFrame* local_frame =
FrameTestHelpers::CreateProvisional(*remote_frame, &client);
FrameTestHelpers::LoadFrame(local_frame, base_url_ + "subframe-hello.html");
- EXPECT_EQ(kWebInitialCommitInChildFrame, client.HistoryCommitType());
+ EXPECT_EQ(kWebHistoryInertCommit, client.HistoryCommitType());
// Manually reset to break WebViewHelper's dependency on the stack allocated
// TestWebFrameClient.
@@ -9983,7 +9887,7 @@ TEST_F(WebFrameSwapTest, WindowOpenOnRemoteFrame) {
WebRemoteFrame* remote_frame = FrameTestHelpers::CreateRemote(&remote_client);
MainFrame()->FirstChild()->Swap(remote_frame);
remote_frame->SetReplicatedOrigin(
- WebSecurityOrigin(SecurityOrigin::CreateUnique()), false);
+ WebSecurityOrigin(SecurityOrigin::CreateUniqueOpaque()), false);
ASSERT_TRUE(MainFrame()->FirstChild()->IsWebRemoteFrame());
LocalDOMWindow* main_window =
@@ -10111,15 +10015,14 @@ TEST_F(WebFrameTest, RemoteFrameInitialCommitType) {
WebString::FromUTF8(base_url_)));
// If an iframe has a remote main frame, ensure the inital commit is correctly
- // identified as WebInitialCommitInChildFrame.
+ // identified as kWebHistoryInertCommit.
CommitTypeWebFrameClient child_frame_client;
WebLocalFrame* child_frame = FrameTestHelpers::CreateLocalChild(
*helper.RemoteMainFrame(), "frameName", WebFrameOwnerProperties(),
nullptr, &child_frame_client);
RegisterMockedHttpURLLoad("foo.html");
FrameTestHelpers::LoadFrame(child_frame, base_url_ + "foo.html");
- EXPECT_EQ(kWebInitialCommitInChildFrame,
- child_frame_client.HistoryCommitType());
+ EXPECT_EQ(kWebHistoryInertCommit, child_frame_client.HistoryCommitType());
helper.Reset();
}
@@ -10282,7 +10185,7 @@ TEST_F(WebFrameTest, CrossDomainAccessErrorsUseCallingWindow) {
popup_web_frame_client.messages[1].text.Utf8().find("Blocked a frame"));
// Manually reset to break WebViewHelpers' dependencies on the stack
- // allocated WebFrameClients.
+ // allocated WebLocalFrameClients.
web_view_helper.Reset();
popup_web_view_helper.Reset();
}
@@ -11229,7 +11132,7 @@ class SaveImageFromDataURLWebFrameClient
SaveImageFromDataURLWebFrameClient() = default;
~SaveImageFromDataURLWebFrameClient() override = default;
- // WebFrameClient:
+ // WebLocalFrameClient:
void SaveImageFromDataURL(const WebString& data_url) override {
data_url_ = data_url;
}
@@ -11687,7 +11590,20 @@ TEST_F(WebFrameTest, MouseOverDifferntNodeClearsTooltip) {
document->GetFrame()->GetChromeClient().LastSetTooltipNodeForTesting());
}
-class WebFrameSimTest : public SimTest {};
+class WebFrameSimTest : public SimTest {
+ public:
+ void UseAndroidSettings() {
+ WebView().GetPage()->GetSettings().SetViewportMetaEnabled(true);
+ WebView().GetPage()->GetSettings().SetViewportEnabled(true);
+ WebView().GetPage()->GetSettings().SetMainFrameResizesAreOrientationChanges(
+ true);
+ WebView().GetPage()->GetSettings().SetViewportStyle(
+ WebViewportStyle::kMobile);
+ WebView().GetSettings()->SetAutoZoomFocusedNodeToLegibleScale(true);
+ WebView().GetSettings()->SetShrinksViewportContentToFit(true);
+ WebView().SetDefaultPageScaleLimits(0.25f, 5);
+ }
+};
TEST_F(WebFrameSimTest, HitTestWithIgnoreClippingAtNegativeOffset) {
WebView().Resize(WebSize(500, 300));
@@ -11733,9 +11649,10 @@ TEST_F(WebFrameSimTest, HitTestWithIgnoreClippingAtNegativeOffset) {
HitTestRequest request = HitTestRequest::kMove | HitTestRequest::kReadOnly |
HitTestRequest::kActive |
HitTestRequest::kIgnoreClipping;
- HitTestResult result(request,
- frame_view->RootFrameToAbsolute(LayoutPoint(100, -50)));
- frame_view->GetLayoutView()->HitTest(result);
+ HitTestLocation location(
+ frame_view->ConvertFromRootFrame(LayoutPoint(100, -50)));
+ HitTestResult result(request, location);
+ frame_view->GetLayoutView()->HitTest(location, result);
EXPECT_EQ(GetDocument().getElementById("top"), result.InnerNode());
}
@@ -11783,9 +11700,8 @@ TEST_F(WebFrameSimTest, TickmarksDocumentRelative) {
RunPendingTasks();
// Get the tickmarks for the original find request.
- Scrollbar* scrollbar = frame_view->CreateScrollbar(kVerticalScrollbar);
Vector<IntRect> original_tickmarks;
- scrollbar->GetTickmarks(original_tickmarks);
+ frame_view->LayoutViewport()->GetTickmarks(original_tickmarks);
EXPECT_EQ(1u, original_tickmarks.size());
EXPECT_EQ(IntPoint(800, 2000), original_tickmarks[0].Location());
@@ -11867,6 +11783,68 @@ TEST_F(WebFrameSimTest, FindInPageSelectNextMatch) {
<< visual_viewport.VisibleRectInDocument().ToString() << "]";
}
+// Basic smoke test of the paint path used by the Android disambiguation popup.
+TEST_F(WebFrameSimTest, DisambiguationPopupPixelTest) {
+ WebView().Resize(WebSize(400, 600));
+ WebView().GetPage()->GetSettings().SetTextAutosizingEnabled(false);
+ UseAndroidSettings();
+
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ body, html {
+ width: 4000px;
+ height: 4000px;
+ margin: 0;
+ }
+ #box {
+ position: absolute;
+ left: 200px;
+ top: 300px;
+ width: 100px;
+ height: 100px;
+ background-color: red;
+ }
+ </style>
+ <div id="box"></div>
+ )HTML");
+
+ Compositor().BeginFrame();
+
+ ASSERT_EQ(0.25f, WebView().PageScaleFactor());
+
+ // Pick exactly the rect covered by the red <div> on the page. Paint it at 4x
+ // magnification.
+ float scale = 4.f;
+ WebRect zoom_rect(200, 300, 100, 100);
+ gfx::Size canvas_size(zoom_rect.width * scale, zoom_rect.height * scale);
+
+ SkImageInfo info =
+ SkImageInfo::MakeN32Premul(canvas_size.width(), canvas_size.height());
+
+ size_t size = info.computeMinByteSize();
+ auto buffer = std::make_unique<uint8_t[]>(size);
+
+ SkBitmap bitmap;
+ bitmap.installPixels(info, buffer.get(), info.minRowBytes());
+ cc::SkiaPaintCanvas canvas(bitmap);
+ canvas.scale(scale, scale);
+ canvas.translate(-zoom_rect.x, -zoom_rect.y);
+
+ WebView().UpdateAllLifecyclePhases();
+ WebView().PaintContentIgnoringCompositing(&canvas, zoom_rect);
+
+ // All the pixels in the canvas should be the <div> color.
+ for (int x = 0; x < canvas_size.width(); ++x) {
+ for (int y = 0; y < canvas_size.height(); ++y) {
+ ASSERT_EQ(bitmap.getColor(x, y), SK_ColorRED)
+ << "Mismatching pixel at (" << x << ", " << y << ")";
+ }
+ }
+}
+
TEST_F(WebFrameSimTest, TestScrollFocusedEditableElementIntoView) {
WebView().Resize(WebSize(500, 300));
WebView().SetDefaultPageScaleLimits(1.f, 4);
@@ -11927,8 +11905,9 @@ TEST_F(WebFrameSimTest, TestScrollFocusedEditableElementIntoView) {
EXPECT_EQ(1, WebView().FakePageScaleAnimationPageScaleForTesting());
- frame_view->LayoutViewportScrollableArea()->SetScrollOffset(
- ToFloatSize(WebView().FakePageScaleAnimationTargetPositionForTesting()),
+ frame_view->LayoutViewport()->SetScrollOffset(
+ ToFloatSize(FloatPoint(
+ WebView().FakePageScaleAnimationTargetPositionForTesting())),
kProgrammaticScroll);
EXPECT_TRUE(visual_viewport.VisibleRectInDocument().Contains(inputRect));
@@ -11956,7 +11935,8 @@ TEST_F(WebFrameSimTest, TestScrollFocusedEditableElementIntoView) {
->FrameWidget()
->ScrollFocusedEditableElementIntoView();
frame_view->GetScrollableArea()->SetScrollOffset(
- ToFloatSize(WebView().FakePageScaleAnimationTargetPositionForTesting()),
+ ToFloatSize(FloatPoint(
+ WebView().FakePageScaleAnimationTargetPositionForTesting())),
kProgrammaticScroll);
EXPECT_TRUE(visual_viewport.VisibleRectInDocument().Contains(inputRect));
@@ -11973,16 +11953,10 @@ TEST_F(WebFrameSimTest, ScrollFocusedIntoViewClipped) {
// In these cases, there's no way to scroll just the viewport to make the
// input visible, we need to also scroll those clip/scroller elements This
// test ensures we do so. https://crbug.com/270018.
+ UseAndroidSettings();
WebView().Resize(WebSize(400, 600));
- WebView().SetDefaultPageScaleLimits(0.25f, 5);
WebView().EnableFakePageScaleAnimationForTesting(true);
WebView().GetPage()->GetSettings().SetTextAutosizingEnabled(false);
- WebView().GetSettings()->SetViewportMetaEnabled(true);
- WebView().GetSettings()->SetViewportEnabled(true);
- WebView().GetSettings()->SetMainFrameResizesAreOrientationChanges(true);
- WebView().GetSettings()->SetShrinksViewportContentToFit(true);
- WebView().GetSettings()->SetViewportStyle(WebViewportStyle::kMobile);
- WebView().GetSettings()->SetAutoZoomFocusedNodeToLegibleScale(true);
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -12047,8 +12021,9 @@ TEST_F(WebFrameSimTest, ScrollFocusedIntoViewClipped) {
input->getBoundingClientRect()->width(),
input->getBoundingClientRect()->height());
- EXPECT_TRUE(frame_view->VisibleContentRect().Contains(input_rect))
- << "Layout viewport [" << frame_view->VisibleContentRect().ToString()
+ IntRect visible_content_rect(IntPoint(), frame_view->Size());
+ EXPECT_TRUE(visible_content_rect.Contains(input_rect))
+ << "Layout viewport [" << visible_content_rect.ToString()
<< "] does not contain input rect [" << input_rect.ToString()
<< "] after scroll into view.";
@@ -12068,17 +12043,11 @@ TEST_F(WebFrameSimTest, ScrollFocusedIntoViewClipped) {
}
TEST_F(WebFrameSimTest, DoubleTapZoomWhileScrolled) {
+ UseAndroidSettings();
WebView().Resize(WebSize(490, 500));
- WebView().SetDefaultPageScaleLimits(0.5f, 4);
WebView().EnableFakePageScaleAnimationForTesting(true);
-
WebView().GetSettings()->SetTextAutosizingEnabled(false);
- WebView().GetSettings()->SetViewportMetaEnabled(true);
- WebView().GetSettings()->SetViewportEnabled(true);
- WebView().GetSettings()->SetMainFrameResizesAreOrientationChanges(true);
- WebView().GetSettings()->SetShrinksViewportContentToFit(true);
- WebView().GetSettings()->SetViewportStyle(WebViewportStyle::kMobile);
- WebView().GetSettings()->SetAutoZoomFocusedNodeToLegibleScale(true);
+ WebView().SetDefaultPageScaleLimits(0.5f, 4);
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
@@ -12129,7 +12098,7 @@ TEST_F(WebFrameSimTest, DoubleTapZoomWhileScrolled) {
WebView().AnimateDoubleTapZoom(WebPoint(445, 455));
EXPECT_TRUE(WebView().FakeDoubleTapAnimationPendingForTesting());
ScrollOffset new_offset = ToScrollOffset(
- WebView().FakePageScaleAnimationTargetPositionForTesting());
+ FloatPoint(WebView().FakePageScaleAnimationTargetPositionForTesting()));
float new_scale = WebView().FakePageScaleAnimationPageScaleForTesting();
visual_viewport.SetScale(new_scale);
frame_view->GetScrollableArea()->SetScrollOffset(new_offset,
@@ -12148,8 +12117,8 @@ TEST_F(WebFrameSimTest, DoubleTapZoomWhileScrolled) {
{
WebView().AnimateDoubleTapZoom(WebPoint(445, 455));
EXPECT_TRUE(WebView().FakeDoubleTapAnimationPendingForTesting());
- IntPoint target_offset =
- WebView().FakePageScaleAnimationTargetPositionForTesting();
+ FloatPoint target_offset(
+ WebView().FakePageScaleAnimationTargetPositionForTesting());
float new_scale = WebView().FakePageScaleAnimationPageScaleForTesting();
EXPECT_FLOAT_EQ(0.5f, new_scale);
@@ -12208,7 +12177,7 @@ TEST_F(WebFrameSimTest, ScrollFocusedEditableIntoViewNoLayoutObject) {
Element* input = GetDocument().getElementById("target");
input->focus();
- ScrollableArea* area = GetDocument().View()->LayoutViewportScrollableArea();
+ ScrollableArea* area = GetDocument().View()->LayoutViewport();
area->SetScrollOffset(ScrollOffset(0, 0), kProgrammaticScroll);
ASSERT_TRUE(input->GetLayoutObject());
@@ -12316,8 +12285,7 @@ TEST_F(WebFrameSimTest, NormalIFrameHasLayoutObjects) {
}
TEST_F(WebFrameSimTest, RtlInitialScrollOffsetWithViewport) {
- WebView().GetSettings()->SetViewportEnabled(true);
- WebView().GetSettings()->SetViewportMetaEnabled(true);
+ UseAndroidSettings();
WebView().Resize(WebSize(400, 400));
WebView().SetDefaultPageScaleLimits(0.25f, 2);
@@ -12331,13 +12299,12 @@ TEST_F(WebFrameSimTest, RtlInitialScrollOffsetWithViewport) {
)HTML");
Compositor().BeginFrame();
- ScrollableArea* area = GetDocument().View()->LayoutViewportScrollableArea();
+ ScrollableArea* area = GetDocument().View()->LayoutViewport();
ASSERT_EQ(ScrollOffset(0, 0), area->GetScrollOffset());
}
TEST_F(WebFrameSimTest, LayoutViewportExceedsLayoutOverflow) {
- WebView().GetSettings()->SetViewportEnabled(true);
- WebView().GetSettings()->SetViewportMetaEnabled(true);
+ UseAndroidSettings();
WebView().ResizeWithBrowserControls(WebSize(400, 540), 60, 0, true);
WebView().SetDefaultPageScaleLimits(0.25f, 2);
@@ -12350,7 +12317,7 @@ TEST_F(WebFrameSimTest, LayoutViewportExceedsLayoutOverflow) {
)HTML");
Compositor().BeginFrame();
- ScrollableArea* area = GetDocument().View()->LayoutViewportScrollableArea();
+ ScrollableArea* area = GetDocument().View()->LayoutViewport();
ASSERT_EQ(540, area->VisibleHeight());
ASSERT_EQ(IntSize(400, 570), area->ContentsSize());
@@ -12364,8 +12331,7 @@ TEST_F(WebFrameSimTest, LayoutViewportExceedsLayoutOverflow) {
}
TEST_F(WebFrameSimTest, LayoutViewLocalVisualRect) {
- WebView().GetSettings()->SetViewportEnabled(true);
- WebView().GetSettings()->SetViewportMetaEnabled(true);
+ UseAndroidSettings();
WebView().Resize(WebSize(600, 400));
WebView().SetDefaultPageScaleLimits(0.5f, 2);
@@ -12555,7 +12521,7 @@ class ContextMenuWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
ContextMenuWebFrameClient() = default;
~ContextMenuWebFrameClient() override = default;
- // WebFrameClient:
+ // WebLocalFrameClient:
void ShowContextMenu(const WebContextMenuData& data) override {
menu_data_ = data;
}
@@ -12749,7 +12715,7 @@ TEST_F(WebFrameTest, FallbackForNonexistentProvisionalNavigation) {
WebLocalFrameImpl* main_frame = web_view_helper_.LocalMainFrame();
WebURLRequest request(ToKURL(base_url_ + "fallback.html"));
- main_frame->LoadRequest(request);
+ main_frame->StartNavigation(request);
// Because the child frame will be HandledByClient, the main frame will not
// finish loading, so FrameTestHelpers::PumpPendingRequestsForFrameToLoad
@@ -12758,7 +12724,7 @@ TEST_F(WebFrameTest, FallbackForNonexistentProvisionalNavigation) {
// Overwrite the client-handled child frame navigation with about:blank.
WebLocalFrame* child = main_frame->FirstChild()->ToWebLocalFrame();
- child->LoadRequest(WebURLRequest(BlankURL()));
+ child->StartNavigation(WebURLRequest(BlankURL()));
// Failing the original child frame navigation and trying to render fallback
// content shouldn't crash. It should return NoLoadInProgress. This is so the
@@ -12799,6 +12765,7 @@ TEST_F(WebFrameTest, AltTextOnAboutBlankPage) {
}
TEST_F(WebFrameTest, NavigatorPluginsClearedWhenPluginsDisabled) {
+ ScopedFakePluginRegistry fake_plugins;
FrameTestHelpers::WebViewHelper web_view_helper;
web_view_helper.Initialize();
v8::HandleScope scope(v8::Isolate::GetCurrent());
@@ -12829,7 +12796,7 @@ TEST_F(WebFrameTest, RecordSameDocumentNavigationToHistogram) {
tester.ExpectTotalCount(histogramName, 0);
main_frame_loader.UpdateForSameDocumentNavigation(
ToKURL("about:blank"), kSameDocumentNavigationHistoryApi, message,
- kScrollRestorationAuto, kFrameLoadTypeInitialHistoryLoad,
+ kScrollRestorationAuto, WebFrameLoadType::kReplaceCurrentItem,
frame->GetDocument());
// The bucket index corresponds to the definition of
// |SinglePageAppNavigationType|.
@@ -12837,17 +12804,17 @@ TEST_F(WebFrameTest, RecordSameDocumentNavigationToHistogram) {
kSPANavTypeHistoryPushStateOrReplaceState, 1);
main_frame_loader.UpdateForSameDocumentNavigation(
ToKURL("about:blank"), kSameDocumentNavigationDefault, message,
- kScrollRestorationManual, kFrameLoadTypeBackForward,
+ kScrollRestorationManual, WebFrameLoadType::kBackForward,
frame->GetDocument());
tester.ExpectBucketCount(histogramName,
kSPANavTypeSameDocumentBackwardOrForward, 1);
main_frame_loader.UpdateForSameDocumentNavigation(
ToKURL("about:blank"), kSameDocumentNavigationDefault, message,
- kScrollRestorationManual, kFrameLoadTypeInitialHistoryLoad,
+ kScrollRestorationManual, WebFrameLoadType::kReplaceCurrentItem,
frame->GetDocument());
tester.ExpectBucketCount(histogramName, kSPANavTypeOtherFragmentNavigation,
1);
- // kSameDocumentNavigationHistoryApi and kFrameLoadTypeBackForward is an
+ // kSameDocumentNavigationHistoryApi and WebFrameLoadType::kBackForward is an
// illegal combination, which has been caught by DCHECK in
// UpdateForSameDocumentNavigation().
@@ -13033,7 +13000,7 @@ TEST_P(SlimmingPaintWebFrameTest, FrameViewScroll) {
WebView()->UpdateAllLifecyclePhases();
- auto* scrollable_area = GetLocalFrameView()->LayoutViewportScrollableArea();
+ auto* scrollable_area = GetLocalFrameView()->LayoutViewport();
EXPECT_NE(nullptr, scrollable_area);
EXPECT_EQ(ScrollHitTestLayerCount(), 1u);
diff --git a/chromium/third_party/blink/renderer/core/exported/web_heap.cc b/chromium/third_party/blink/renderer/core/exported/web_heap.cc
index 6949db816d6..9040bcb48c6 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_heap.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_heap.cc
@@ -38,7 +38,7 @@ namespace blink {
void WebHeap::CollectGarbageForTesting() {
ThreadState::Current()->CollectGarbage(
BlinkGC::kHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
}
void WebHeap::CollectAllGarbageForTesting() {
diff --git a/chromium/third_party/blink/renderer/core/exported/web_image_decoder.cc b/chromium/third_party/blink/renderer/core/exported/web_image_decoder.cc
index 9b5d6ecb3c2..84715b4d4f1 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_image_decoder.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_image_decoder.cc
@@ -33,11 +33,11 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_data.h"
-#include "third_party/blink/public/platform/web_image.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder.h"
#include "third_party/blink/renderer/platform/image-decoders/ico/ico_image_decoder.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
+#include "third_party/skia/include/core/SkBitmap.h"
namespace blink {
@@ -95,12 +95,12 @@ bool WebImageDecoder::IsFrameCompleteAtIndex(int index) const {
return frame_buffer->GetStatus() == ImageFrame::kFrameComplete;
}
-WebImage WebImageDecoder::GetFrameAtIndex(int index = 0) const {
+SkBitmap WebImageDecoder::GetFrameAtIndex(int index = 0) const {
DCHECK(private_);
ImageFrame* const frame_buffer = private_->DecodeFrameBufferAtIndex(index);
if (!frame_buffer)
- return WebImage();
- return WebImage(frame_buffer->Bitmap());
+ return {};
+ return frame_buffer->Bitmap();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/exported/web_local_frame_client.cc b/chromium/third_party/blink/renderer/core/exported/web_local_frame_client.cc
new file mode 100644
index 00000000000..fb8d07d3837
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/exported/web_local_frame_client.cc
@@ -0,0 +1,24 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/web/web_local_frame_client.h"
+
+#include "services/service_manager/public/cpp/interface_provider.h"
+
+namespace blink {
+
+service_manager::InterfaceProvider*
+WebLocalFrameClient::GetInterfaceProvider() {
+ static service_manager::InterfaceProvider* interface_provider = []() {
+ auto* interface_provider = new service_manager::InterfaceProvider();
+ service_manager::mojom::InterfaceProviderPtr provider;
+ mojo::MakeRequest(&provider);
+ interface_provider->Bind(std::move(provider));
+ return interface_provider;
+ }();
+
+ return interface_provider;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/exported/web_node.cc b/chromium/third_party/blink/renderer/core/exported/web_node.cc
index 08b61ae4cfa..06ba400d053 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_node.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_node.cc
@@ -36,8 +36,7 @@
#include "third_party/blink/public/web/web_dom_event.h"
#include "third_party/blink/public/web/web_element.h"
#include "third_party/blink/public/web/web_element_collection.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.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"
@@ -52,6 +51,7 @@
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
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 5d4fd3cf38e..b6a4b95e83e 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
@@ -31,13 +31,15 @@
#include <memory>
+#include "cc/layers/picture_layer.h"
#include "third_party/blink/public/platform/web_cursor_info.h"
#include "third_party/blink/public/platform/web_float_rect.h"
-#include "third_party/blink/public/web/web_frame_client.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_view_client.h"
#include "third_party/blink/public/web/web_widget_client.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache_base.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/events/event_dispatch_forbidden_scope.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"
@@ -59,7 +61,6 @@
#include "third_party/blink/renderer/core/page/page_popup_supplement.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_host.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
-#include "third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -152,7 +153,7 @@ class PagePopupChromeClient final : public EmptyChromeClient {
WebScreenInfo GetScreenInfo() const override {
return popup_->web_view_->Client()
- ? popup_->web_view_->Client()->GetScreenInfo()
+ ? popup_->web_view_->WidgetClient()->GetScreenInfo()
: WebScreenInfo();
}
@@ -166,36 +167,36 @@ class PagePopupChromeClient final : public EmptyChromeClient {
void SetEventListenerProperties(
LocalFrame* frame,
- WebEventListenerClass event_class,
- WebEventListenerProperties properties) override {
+ cc::EventListenerClass event_class,
+ cc::EventListenerProperties properties) override {
DCHECK(frame->IsMainFrame());
WebWidgetClient* client = popup_->WidgetClient();
if (WebLayerTreeView* layer_tree_view = popup_->layer_tree_view_) {
layer_tree_view->SetEventListenerProperties(event_class, properties);
- if (event_class == WebEventListenerClass::kTouchStartOrMove) {
+ if (event_class == cc::EventListenerClass::kTouchStartOrMove) {
client->HasTouchEventHandlers(
- properties != WebEventListenerProperties::kNothing ||
- EventListenerProperties(frame,
- WebEventListenerClass::kTouchEndOrCancel) !=
- WebEventListenerProperties::kNothing);
- } else if (event_class == WebEventListenerClass::kTouchEndOrCancel) {
+ properties != cc::EventListenerProperties::kNone ||
+ EventListenerProperties(
+ frame, cc::EventListenerClass::kTouchEndOrCancel) !=
+ cc::EventListenerProperties::kNone);
+ } else if (event_class == cc::EventListenerClass::kTouchEndOrCancel) {
client->HasTouchEventHandlers(
- properties != WebEventListenerProperties::kNothing ||
- EventListenerProperties(frame,
- WebEventListenerClass::kTouchStartOrMove) !=
- WebEventListenerProperties::kNothing);
+ properties != cc::EventListenerProperties::kNone ||
+ EventListenerProperties(
+ frame, cc::EventListenerClass::kTouchStartOrMove) !=
+ cc::EventListenerProperties::kNone);
}
} else {
client->HasTouchEventHandlers(true);
}
}
- WebEventListenerProperties EventListenerProperties(
+ cc::EventListenerProperties EventListenerProperties(
LocalFrame*,
- WebEventListenerClass event_class) const override {
+ cc::EventListenerClass event_class) const override {
if (popup_->layer_tree_view_) {
return popup_->layer_tree_view_->EventListenerProperties(event_class);
}
- return WebEventListenerProperties::kNothing;
+ return cc::EventListenerProperties::kNone;
}
void SetHasScrollEventHandlers(LocalFrame* frame,
@@ -208,17 +209,25 @@ class PagePopupChromeClient final : public EmptyChromeClient {
void SetTouchAction(LocalFrame* frame, TouchAction touch_action) override {
DCHECK(frame);
WebLocalFrameImpl* web_frame = WebLocalFrameImpl::FromFrame(frame);
+ // TODO(https://crbug.com/844547): check if we are setting touch action on
+ // pop up window or not.
+ if (!web_frame)
+ return;
WebFrameWidget* widget = web_frame->LocalRoot()->FrameWidget();
if (!widget)
return;
-
if (WebWidgetClient* client = ToWebFrameWidgetBase(widget)->Client())
client->SetTouchAction(static_cast<WebTouchAction>(touch_action));
}
void AttachRootGraphicsLayer(GraphicsLayer* graphics_layer,
LocalFrame* local_root) override {
- popup_->SetRootGraphicsLayer(graphics_layer);
+ popup_->SetRootLayer(graphics_layer ? graphics_layer->CcLayer() : nullptr);
+ }
+
+ void AttachRootLayer(scoped_refptr<cc::Layer> layer,
+ LocalFrame* local_root) override {
+ popup_->SetRootLayer(layer.get());
}
void SetToolTip(LocalFrame&,
@@ -355,9 +364,8 @@ void WebPagePopupImpl::SetWindowRect(const IntRect& rect_in_screen) {
WidgetClient()->SetWindowRect(rect_in_screen);
}
-void WebPagePopupImpl::SetRootGraphicsLayer(GraphicsLayer* layer) {
- root_graphics_layer_ = layer;
- root_layer_ = layer ? layer->CcLayer() : nullptr;
+void WebPagePopupImpl::SetRootLayer(cc::Layer* layer) {
+ root_layer_ = layer;
is_accelerated_compositing_active_ = !!layer;
if (layer_tree_view_) {
@@ -423,10 +431,11 @@ void WebPagePopupImpl::CompositeWithRasterForTesting() {
layer_tree_view_->CompositeWithRasterForTesting();
}
-void WebPagePopupImpl::Paint(WebCanvas* canvas, const WebRect& rect) {
+void WebPagePopupImpl::PaintContent(cc::PaintCanvas* canvas,
+ const WebRect& rect) {
if (!closing_) {
- PageWidgetDelegate::Paint(*page_, canvas, rect,
- *page_->DeprecatedLocalMainFrame());
+ PageWidgetDelegate::PaintContent(*page_, canvas, rect,
+ *page_->DeprecatedLocalMainFrame());
}
}
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 6b30992d98b..4e7fa457d01 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
@@ -45,7 +45,6 @@ class Layer;
namespace blink {
class CompositorAnimationHost;
-class GraphicsLayer;
class Page;
class PagePopupChromeClient;
class PagePopupClient;
@@ -88,7 +87,7 @@ class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup,
void UpdateAllLifecyclePhasesAndCompositeForTesting() override;
void CompositeWithRasterForTesting() override;
void WillCloseLayerTreeView() override;
- void Paint(WebCanvas*, const WebRect&) override;
+ void PaintContent(cc::PaintCanvas*, const WebRect&) override;
void Resize(const WebSize&) override;
void Close() override;
WebInputEventResult HandleInputEvent(const WebCoalescedInputEvent&) override;
@@ -115,7 +114,7 @@ class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup,
bool InitializePage();
void DestroyPage();
void InitializeLayerTreeView();
- void SetRootGraphicsLayer(GraphicsLayer*);
+ void SetRootLayer(cc::Layer*);
WebRect WindowRectInScreen() const;
@@ -128,7 +127,6 @@ class CORE_EXPORT WebPagePopupImpl final : public WebPagePopup,
WebLayerTreeView* layer_tree_view_ = nullptr;
scoped_refptr<cc::Layer> root_layer_;
- GraphicsLayer* root_graphics_layer_ = nullptr;
std::unique_ptr<CompositorAnimationHost> animation_host_;
bool is_accelerated_compositing_active_ = false;
diff --git a/chromium/third_party/blink/renderer/core/exported/web_performance.cc b/chromium/third_party/blink/renderer/core/exported/web_performance.cc
index 775ecbf7ecd..be907d1f091 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_performance.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_performance.cc
@@ -166,6 +166,11 @@ double WebPerformance::FirstMeaningfulPaint() const {
return MillisecondsToSeconds(private_->timing()->FirstMeaningfulPaint());
}
+double WebPerformance::FirstMeaningfulPaintCandidate() const {
+ return MillisecondsToSeconds(
+ private_->timing()->FirstMeaningfulPaintCandidate());
+}
+
double WebPerformance::PageInteractive() const {
return MillisecondsToSeconds(private_->timing()->PageInteractive());
}
@@ -187,6 +192,14 @@ double WebPerformance::FirstInputTimestamp() const {
return MillisecondsToSeconds(private_->timing()->FirstInputTimestamp());
}
+double WebPerformance::LongestInputDelay() const {
+ return MillisecondsToSeconds(private_->timing()->LongestInputDelay());
+}
+
+double WebPerformance::LongestInputTimestamp() const {
+ return MillisecondsToSeconds(private_->timing()->LongestInputTimestamp());
+}
+
double WebPerformance::ParseStart() const {
return MillisecondsToSeconds(private_->timing()->ParseStart());
}
@@ -218,16 +231,6 @@ double WebPerformance::ParseBlockedOnScriptExecutionFromDocumentWriteDuration()
->ParseBlockedOnScriptExecutionFromDocumentWriteDuration());
}
-double WebPerformance::AuthorStyleSheetParseDurationBeforeFCP() const {
- return MillisecondsToSeconds(
- private_->timing()->AuthorStyleSheetParseDurationBeforeFCP());
-}
-
-double WebPerformance::UpdateStyleDurationBeforeFCP() const {
- return MillisecondsToSeconds(
- private_->timing()->UpdateStyleDurationBeforeFCP());
-}
-
WebPerformance::WebPerformance(WindowPerformance* performance)
: private_(performance) {}
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 92ad2266191..57e1b53a801 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
@@ -45,8 +45,8 @@
#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_element.h"
-#include "third_party/blink/public/web/web_frame_client.h"
#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_plugin.h"
#include "third_party/blink/public/web/web_print_params.h"
#include "third_party/blink/public/web/web_print_preset_options.h"
@@ -58,7 +58,6 @@
#include "third_party/blink/renderer/core/clipboard/data_object.h"
#include "third_party/blink/renderer/core/clipboard/data_transfer.h"
#include "third_party/blink/renderer/core/clipboard/system_clipboard.h"
-#include "third_party/blink/renderer/core/dom/events/event_queue.h"
#include "third_party/blink/renderer/core/dom/user_gesture_indicator.h"
#include "third_party/blink/renderer/core/events/drag_event.h"
#include "third_party/blink/renderer/core/events/gesture_event.h"
@@ -154,8 +153,10 @@ IntRect WebPluginContainerImpl::FrameRect() const {
if (owner) {
LayoutView* owner_layout_view = owner->View();
DCHECK(owner_layout_view);
- if (owner_layout_view->HasOverflowClip())
- location.Move(-owner_layout_view->ScrolledContentOffset());
+ if (owner_layout_view->HasOverflowClip()) {
+ IntSize scroll_offset(owner_layout_view->ScrolledContentOffset());
+ location.SaturatedMove(-scroll_offset.Width(), -scroll_offset.Height());
+ }
}
return IntRect(location, frame_rect_.Size());
@@ -176,7 +177,7 @@ void WebPluginContainerImpl::Paint(GraphicsContext& context,
// inserted rather than invoking WebPlugin::paint.
RecordForeignLayer(context, *element_->GetLayoutObject(),
DisplayItem::kForeignLayerPlugin, layer_,
- FrameRect().Location(), frame_rect_.Size());
+ FloatPoint(FrameRect().Location()), frame_rect_.Size());
return;
}
@@ -190,13 +191,13 @@ void WebPluginContainerImpl::Paint(GraphicsContext& context,
// The plugin is positioned in the root frame's coordinates, so it needs to
// be painted in them too.
- FloatPoint origin(ParentFrameView().ContentsToRootFrame(IntPoint()));
+ FloatPoint origin(ParentFrameView().ConvertToRootFrame(IntPoint()));
origin.Move(-paint_offset);
context.Translate(-origin.X(), -origin.Y());
- WebCanvas* canvas = context.Canvas();
+ cc::PaintCanvas* canvas = context.Canvas();
- IntRect window_rect = ParentFrameView().ContentsToRootFrame(cull_rect.rect_);
+ IntRect window_rect = ParentFrameView().ConvertToRootFrame(cull_rect.Rect());
web_plugin_->Paint(canvas, window_rect);
context.Restore();
@@ -392,7 +393,7 @@ void WebPluginContainerImpl::PrintPage(int page_number, GraphicsContext& gc) {
DisplayItem::kWebPlugin);
gc.Save();
- WebCanvas* canvas = gc.Canvas();
+ cc::PaintCanvas* canvas = gc.Canvas();
web_plugin_->PrintPage(page_number, canvas);
gc.Restore();
}
@@ -457,9 +458,9 @@ void WebPluginContainerImpl::DispatchProgressEvent(const WebString& type,
void WebPluginContainerImpl::EnqueueMessageEvent(
const WebDOMMessageEvent& event) {
- static_cast<Event*>(event)->SetTarget(element_);
- element_->GetExecutionContext()->GetEventQueue()->EnqueueEvent(FROM_HERE,
- event);
+ if (!element_->GetExecutionContext())
+ return;
+ element_->EnqueueEvent(event, TaskType::kInternalDefault);
}
void WebPluginContainerImpl::Invalidate() {
@@ -522,13 +523,13 @@ WebString WebPluginContainerImpl::ExecuteScriptURL(const WebURL& url,
const KURL& kurl = url;
DCHECK(kurl.ProtocolIs("javascript"));
- String script = DecodeURLEscapeSequences(
- kurl.GetString().Substring(strlen("javascript:")));
+ String script = DecodeURLEscapeSequences(kurl.GetString());
if (!element_->GetDocument().GetContentSecurityPolicy()->AllowJavaScriptURLs(
element_, script, element_->GetDocument().Url(), OrdinalNumber())) {
return WebString();
}
+ script = script.Substring(strlen("javascript:"));
std::unique_ptr<UserGestureIndicator> gesture_indicator;
if (popups_allowed) {
@@ -571,26 +572,13 @@ bool WebPluginContainerImpl::IsRectTopmost(const WebRect& rect) {
if (!frame)
return false;
- IntPoint location = FrameRect().Location();
- LayoutRect document_rect(location.X() + rect.x, location.Y() + rect.y,
- rect.width, rect.height);
- // hitTestResultAtPoint() takes a padding rectangle.
- // FIXME: We'll be off by 1 when the width or height is even.
- LayoutPoint center = document_rect.Center();
- // Make the rect we're checking (the point surrounded by padding rects)
- // contained inside the requested rect.
- // TODO(pdr): This logic for calculating padding is only needed because the
- // hit test rect for a point has non-zero dimensions. This can be simplified
- // when the hit test rect is 0px x 0px, see: HitTestLocation::RectForPoint.
- LayoutRect hit_rect = HitTestLocation::RectForPoint(center);
- LayoutRectOutsets padding(
- hit_rect.Y() - document_rect.Y(), document_rect.MaxX() - hit_rect.MaxX(),
- document_rect.MaxY() - hit_rect.MaxY(), hit_rect.X() - document_rect.X());
- HitTestResult result = frame->GetEventHandler().HitTestResultAtPoint(
- center,
- HitTestRequest::kReadOnly | HitTestRequest::kActive |
- HitTestRequest::kListBased,
- padding);
+ IntPoint frame_location = FrameRect().Location();
+ HitTestLocation location(LayoutRect(frame_location.X() + rect.x,
+ frame_location.Y() + rect.y, rect.width,
+ rect.height));
+ HitTestResult result = frame->GetEventHandler().HitTestResultAtLocation(
+ location, HitTestRequest::kReadOnly | HitTestRequest::kActive |
+ HitTestRequest::kListBased);
const HitTestResult::NodeSet& nodes = result.ListBasedTestResult();
if (nodes.size() != 1)
return false;
@@ -666,7 +654,7 @@ void WebPluginContainerImpl::SetWantsWheelEvents(bool wants_wheel_events) {
WebPoint WebPluginContainerImpl::RootFrameToLocalPoint(
const WebPoint& point_in_root_frame) {
WebPoint point_in_content =
- ParentFrameView().RootFrameToContents(point_in_root_frame);
+ ParentFrameView().ConvertFromRootFrame(point_in_root_frame);
return RoundedIntPoint(element_->GetLayoutObject()->AbsoluteToLocal(
FloatPoint(point_in_content), kUseTransforms));
}
@@ -676,7 +664,7 @@ WebPoint WebPluginContainerImpl::LocalToRootFramePoint(
IntPoint absolute_point =
RoundedIntPoint(element_->GetLayoutObject()->LocalToAbsolute(
FloatPoint(point_in_local), kUseTransforms));
- return ParentFrameView().ContentsToRootFrame(absolute_point);
+ return ParentFrameView().ConvertToRootFrame(absolute_point);
}
void WebPluginContainerImpl::DidReceiveResponse(
@@ -863,7 +851,7 @@ void WebPluginContainerImpl::HandleWheelEvent(WheelEvent* event) {
WebFloatPoint absolute_location = event->NativeEvent().PositionInRootFrame();
// Translate the root frame position to content coordinates.
- absolute_location = ParentFrameView().RootFrameToContents(absolute_location);
+ absolute_location = ParentFrameView().ConvertFromRootFrame(absolute_location);
FloatPoint local_point = element_->GetLayoutObject()->AbsoluteToLocal(
absolute_location, kUseTransforms);
@@ -958,7 +946,7 @@ WebTouchEvent WebPluginContainerImpl::TransformTouchEvent(
transformed_event.touches[i].PositionInWidget();
// Translate the root frame position to content coordinates.
- absolute_location = parent.RootFrameToContents(absolute_location);
+ absolute_location = parent.ConvertFromRootFrame(absolute_location);
FloatPoint local_point = element_->GetLayoutObject()->AbsoluteToLocal(
absolute_location, kUseTransforms);
@@ -1079,7 +1067,7 @@ void WebPluginContainerImpl::ComputeClipRectsForPlugin(
LayoutRect unclipped_absolute_rect(box->ContentBoxRect());
box->MapToVisualRectInAncestorSpace(root_view, unclipped_absolute_rect);
unclipped_absolute_rect =
- box->View()->GetFrameView()->DocumentToAbsolute(unclipped_absolute_rect);
+ box->View()->GetFrameView()->DocumentToFrame(unclipped_absolute_rect);
// The frameRect is already in absolute space of the local frame to the
// plugin so map it up to the root frame.
@@ -1092,17 +1080,12 @@ void WebPluginContainerImpl::ComputeClipRectsForPlugin(
kTraverseDocumentBoundaries)
.BoundingBox());
- // Finally, adjust for scrolling of the root frame, which the above does not
- // take into account (until root-layer-scrolling ships at which point we can
- // remove the AbsoluteToRootFrame).
- layout_window_rect =
- root_view->GetFrameView()->AbsoluteToRootFrame(layout_window_rect);
window_rect = PixelSnappedIntRect(layout_window_rect);
LayoutRect layout_clipped_local_rect = unclipped_absolute_rect;
LayoutRect unclipped_layout_local_rect = layout_clipped_local_rect;
layout_clipped_local_rect.Intersect(
- LayoutRect(root_view->GetFrameView()->VisibleContentRect()));
+ LayoutRect(LayoutPoint(), LayoutSize(root_view->GetFrameView()->Size())));
unclipped_int_local_rect =
box->AbsoluteToLocalQuad(FloatRect(unclipped_layout_local_rect),
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 3e641281dbe..d6a40e48c2e 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
@@ -94,9 +94,8 @@ class CORE_EXPORT WebPluginContainerImpl final
void FrameRectsChanged() override;
void SetFrameRect(const IntRect&) override;
IntRect FrameRect() const override;
- // |paint_offset| is a workaround for SlimmingPaintV175 to paint the contents
- // at the correct location. It should be issued as a transform operation
- // before painting the contents.
+ // |paint_offset| is used to to paint the contents at the correct location.
+ // It should be issued as a transform operation before painting the contents.
void Paint(GraphicsContext&,
const GlobalPaintFlags,
const CullRect&,
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 23b2409415e..3a289592911 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
@@ -44,7 +44,7 @@
#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"
-#include "third_party/blink/public/web/web_frame_client.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_plugin_params.h"
#include "third_party/blink/public/web/web_print_params.h"
#include "third_party/blink/public/web/web_settings.h"
@@ -68,6 +68,7 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.h"
#include "third_party/blink/renderer/platform/keyboard_codes.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/scoped_fake_plugin_registry.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
@@ -102,6 +103,7 @@ class WebPluginContainerTest : public testing::Test {
}
protected:
+ ScopedFakePluginRegistry fake_plugins_;
std::string base_url_;
};
@@ -136,7 +138,7 @@ class TestPlugin : public FakeWebPlugin {
WebString SelectionAsMarkup() const override { return WebString("y"); }
bool SupportsPaginatedPrint() override { return true; }
int PrintBegin(const WebPrintParams& print_params) override { return 1; }
- void PrintPage(int page_number, WebCanvas*) override;
+ void PrintPage(int page_number, cc::PaintCanvas*) override;
private:
~TestPlugin() override = default;
@@ -209,7 +211,7 @@ class TestPluginWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
return new TestPlugin(params, this);
}
- return WebFrameClient::CreatePlugin(params);
+ return WebLocalFrameClient::CreatePlugin(params);
}
public:
@@ -224,7 +226,7 @@ class TestPluginWebFrameClient : public FrameTestHelpers::TestWebFrameClient {
bool has_editable_text_ = false;
};
-void TestPlugin::PrintPage(int page_number, WebCanvas* canvas) {
+void TestPlugin::PrintPage(int page_number, cc::PaintCanvas* canvas) {
DCHECK(test_client_);
test_client_->OnPrintPage();
}
diff --git a/chromium/third_party/blink/renderer/core/exported/web_plugin_document.cc b/chromium/third_party/blink/renderer/core/exported/web_plugin_document.cc
index 2589d0436ec..ed3cf77cef9 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_plugin_document.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_plugin_document.cc
@@ -61,4 +61,12 @@ WebPluginDocument::operator PluginDocument*() const {
return static_cast<PluginDocument*>(private_.Get());
}
+void WebPluginDocument::SetShowBeforeUnloadDialog(bool show_dialog) {
+ if (!IsPluginDocument())
+ return;
+
+ PluginDocument* doc = Unwrap<PluginDocument>();
+ doc->SetShowBeforeUnloadDialog(show_dialog);
+}
+
} // namespace blink
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 6228bf99286..b2add6c5df8 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
@@ -46,7 +46,7 @@ namespace {
FloatRect DeNormalizeRect(const WebFloatRect& normalized, const IntRect& base) {
FloatRect result = normalized;
result.Scale(base.Width(), base.Height());
- result.MoveBy(base.Location());
+ result.MoveBy(FloatPoint(base.Location()));
return result;
}
} // namespace
@@ -141,7 +141,7 @@ WebLocalFrame* WebRemoteFrameImpl::CreateLocalChild(
WebTreeScopeType scope,
const WebString& name,
WebSandboxFlags sandbox_flags,
- WebFrameClient* client,
+ WebLocalFrameClient* client,
blink::InterfaceRegistry* interface_registry,
WebFrame* previous_sibling,
const ParsedFeaturePolicy& container_policy,
@@ -342,10 +342,16 @@ void WebRemoteFrameImpl::WillEnterFullscreen() {
Fullscreen::RequestType::kPrefixedForCrossProcessDescendant);
}
-void WebRemoteFrameImpl::SetHasReceivedUserGesture() {
- RemoteFrame* frame = GetFrame();
- if (frame)
- frame->NotifyUserActivationInLocalTree();
+void WebRemoteFrameImpl::UpdateUserActivationState(
+ UserActivationUpdateType update_type) {
+ switch (update_type) {
+ case UserActivationUpdateType::kNotifyActivation:
+ GetFrame()->NotifyUserActivationInLocalTree();
+ break;
+ case UserActivationUpdateType::kConsumeTransientActivation:
+ GetFrame()->ConsumeTransientUserActivationInLocalTree();
+ break;
+ }
}
void WebRemoteFrameImpl::ScrollRectToVisible(
@@ -387,7 +393,7 @@ void WebRemoteFrameImpl::ScrollRectToVisible(
IntRect rect_in_document =
view_impl->MainFrameImpl()->GetFrame()->View()->RootFrameToDocument(
EnclosingIntRect(
- owner_element->GetDocument().View()->AbsoluteToRootFrame(
+ owner_element->GetDocument().View()->ConvertToRootFrame(
absolute_rect)));
IntRect element_bounds_in_document = EnclosingIntRect(
DeNormalizeRect(params.relative_element_bounds, rect_in_document));
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 65b45760af0..fac141df8b8 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
@@ -48,7 +48,7 @@ class CORE_EXPORT WebRemoteFrameImpl final
WebLocalFrame* CreateLocalChild(WebTreeScopeType,
const WebString& name,
WebSandboxFlags,
- WebFrameClient*,
+ WebLocalFrameClient*,
blink::InterfaceRegistry*,
WebFrame* previous_sibling,
const ParsedFeaturePolicy&,
@@ -82,7 +82,7 @@ class CORE_EXPORT WebRemoteFrameImpl final
void DidStopLoading() override;
bool IsIgnoredForHitTest() const override;
void WillEnterFullscreen() override;
- void SetHasReceivedUserGesture() override;
+ void UpdateUserActivationState(UserActivationUpdateType) override;
void ScrollRectToVisible(const WebRect&,
const WebScrollIntoViewParams&) override;
void BubbleLogicalScroll(WebScrollDirection direction,
diff --git a/chromium/third_party/blink/renderer/core/exported/web_security_policy.cc b/chromium/third_party/blink/renderer/core/exported/web_security_policy.cc
index 96e2593495c..b49ba1e5a5d 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_security_policy.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_security_policy.cc
@@ -85,6 +85,12 @@ void WebSecurityPolicy::RemoveOriginAccessWhitelistEntry(
destination_host, allow_destination_subdomains);
}
+void WebSecurityPolicy::RemoveAllOriginAccessWhitelistEntriesForOrigin(
+ const WebURL& source_origin) {
+ SecurityPolicy::RemoveAllOriginAccessWhitelistEntriesForOrigin(
+ *SecurityOrigin::Create(source_origin));
+}
+
void WebSecurityPolicy::ResetOriginAccessWhitelists() {
SecurityPolicy::ResetOriginAccessWhitelists();
}
diff --git a/chromium/third_party/blink/renderer/core/exported/web_selection.cc b/chromium/third_party/blink/renderer/core/exported/web_selection.cc
deleted file mode 100644
index 1b6d4d4c84b..00000000000
--- a/chromium/third_party/blink/renderer/core/exported/web_selection.cc
+++ /dev/null
@@ -1,49 +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/public/web/web_selection.h"
-
-#include "third_party/blink/renderer/core/editing/selection_type.h"
-#include "third_party/blink/renderer/core/paint/compositing/composited_selection.h"
-
-namespace blink {
-
-static WebSelectionBound GetWebSelectionBound(
- const CompositedSelection& selection,
- bool is_start) {
- DCHECK_NE(selection.type, kNoSelection);
- const CompositedSelectionBound& bound =
- is_start ? selection.start : selection.end;
- DCHECK(bound.layer);
-
- WebSelectionBound::Type type = WebSelectionBound::kCaret;
- if (selection.type == kRangeSelection) {
- if (is_start) {
- type = bound.is_text_direction_rtl ? WebSelectionBound::kSelectionRight
- : WebSelectionBound::kSelectionLeft;
- } else {
- type = bound.is_text_direction_rtl ? WebSelectionBound::kSelectionLeft
- : WebSelectionBound::kSelectionRight;
- }
- }
-
- WebSelectionBound result(type);
- result.layer_id = bound.layer->CcLayer()->id();
- result.edge_top_in_layer = RoundedIntPoint(bound.edge_top_in_layer);
- result.edge_bottom_in_layer = RoundedIntPoint(bound.edge_bottom_in_layer);
- result.is_text_direction_rtl = bound.is_text_direction_rtl;
- result.hidden = bound.hidden;
- return result;
-}
-
-// SelectionType enums have the same values; enforced in
-// AssertMatchingEnums.cpp.
-WebSelection::WebSelection(const CompositedSelection& selection)
- : selection_type_(static_cast<WebSelection::SelectionType>(selection.type)),
- start_(GetWebSelectionBound(selection, true)),
- end_(GetWebSelectionBound(selection, false)) {}
-
-WebSelection::WebSelection(const WebSelection& other) = default;
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/exported/web_serialized_script_value.cc b/chromium/third_party/blink/renderer/core/exported/web_serialized_script_value.cc
index cf505f67b2e..c296d56ac74 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_serialized_script_value.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_serialized_script_value.cc
@@ -31,9 +31,9 @@
#include "third_party/blink/public/web/web_serialized_script_value.h"
#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_factory.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
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 d9038b63b9f..4760b2c18b4 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
@@ -71,6 +71,10 @@ void WebSettingsImpl::SetFixedFontFamily(const WebString& font,
settings_->NotifyGenericFontFamilyChange();
}
+void WebSettingsImpl::SetFMPNetworkQuietTimeout(double timeout) {
+ settings_->SetFMPNetworkQuietTimeout(timeout);
+}
+
void WebSettingsImpl::SetForceMainWorldInitialization(bool enabled) {
settings_->SetForceMainWorldInitialization(enabled);
}
@@ -483,7 +487,7 @@ void WebSettingsImpl::SetMockScrollbarsEnabled(bool enabled) {
}
void WebSettingsImpl::SetHideScrollbars(bool enabled) {
- settings_->SetHideScrollbars(enabled);
+ dev_tools_emulator_->SetHideScrollbars(enabled);
}
void WebSettingsImpl::SetMockGestureTapHighlightsEnabled(bool enabled) {
@@ -663,7 +667,7 @@ void WebSettingsImpl::SetSyncXHRInDocumentsEnabled(bool enabled) {
}
void WebSettingsImpl::SetCookieEnabled(bool enabled) {
- settings_->SetCookieEnabled(enabled);
+ dev_tools_emulator_->SetCookieEnabled(enabled);
}
void WebSettingsImpl::SetNavigateOnDragDrop(bool enabled) {
@@ -724,4 +728,34 @@ void WebSettingsImpl::SetLowPriorityIframesThreshold(
settings_->SetLowPriorityIframesThreshold(effective_connection_type);
}
+void WebSettingsImpl::SetLazyFrameLoadingDistanceThresholdPxUnknown(
+ int distance_px) {
+ settings_->SetLazyFrameLoadingDistanceThresholdPxUnknown(distance_px);
+}
+
+void WebSettingsImpl::SetLazyFrameLoadingDistanceThresholdPxOffline(
+ int distance_px) {
+ settings_->SetLazyFrameLoadingDistanceThresholdPxOffline(distance_px);
+}
+
+void WebSettingsImpl::SetLazyFrameLoadingDistanceThresholdPxSlow2G(
+ int distance_px) {
+ settings_->SetLazyFrameLoadingDistanceThresholdPxSlow2G(distance_px);
+}
+
+void WebSettingsImpl::SetLazyFrameLoadingDistanceThresholdPx2G(
+ int distance_px) {
+ settings_->SetLazyFrameLoadingDistanceThresholdPx2G(distance_px);
+}
+
+void WebSettingsImpl::SetLazyFrameLoadingDistanceThresholdPx3G(
+ int distance_px) {
+ settings_->SetLazyFrameLoadingDistanceThresholdPx3G(distance_px);
+}
+
+void WebSettingsImpl::SetLazyFrameLoadingDistanceThresholdPx4G(
+ int distance_px) {
+ settings_->SetLazyFrameLoadingDistanceThresholdPx4G(distance_px);
+}
+
} // namespace blink
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 5a1ec0f177b..8dc554aa52b 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
@@ -93,6 +93,7 @@ class CORE_EXPORT WebSettingsImpl final : public WebSettings {
UScriptCode = USCRIPT_COMMON) override;
void SetFixedFontFamily(const WebString&,
UScriptCode = USCRIPT_COMMON) override;
+ void SetFMPNetworkQuietTimeout(double timeout) override;
void SetForceMainWorldInitialization(bool) override;
void SetForcePreloadNoneForMediaElements(bool) override;
void SetForceZeroLayoutHeight(bool) override;
@@ -206,6 +207,12 @@ class CORE_EXPORT WebSettingsImpl final : public WebSettings {
void SetDoNotUpdateSelectionOnMutatingSelectionRange(bool) override;
void SetMediaDownloadInProductHelpEnabled(bool) override;
void SetLowPriorityIframesThreshold(WebEffectiveConnectionType) override;
+ void SetLazyFrameLoadingDistanceThresholdPxUnknown(int) override;
+ void SetLazyFrameLoadingDistanceThresholdPxOffline(int) override;
+ void SetLazyFrameLoadingDistanceThresholdPxSlow2G(int) override;
+ void SetLazyFrameLoadingDistanceThresholdPx2G(int) override;
+ void SetLazyFrameLoadingDistanceThresholdPx3G(int) override;
+ void SetLazyFrameLoadingDistanceThresholdPx4G(int) override;
bool ShowFPSCounter() const { return show_fps_counter_; }
bool ShowPaintRects() const { return show_paint_rects_; }
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 6c2af8c8208..7ed15f2edac 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
@@ -31,8 +31,9 @@
#include "third_party/blink/renderer/core/exported/web_shared_worker_impl.h"
#include <memory>
+#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
#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_string.h"
@@ -78,6 +79,8 @@ WebSharedWorkerImpl::WebSharedWorkerImpl(WebSharedWorkerClient* client)
: worker_inspector_proxy_(WorkerInspectorProxy::Create()),
client_(client),
creation_address_space_(mojom::IPAddressSpace::kPublic),
+ parent_execution_context_task_runners_(
+ ParentExecutionContextTaskRunners::Create()),
weak_ptr_factory_(this) {
DCHECK(IsMainThread());
}
@@ -212,6 +215,8 @@ void WebSharedWorkerImpl::StartWorkerContext(
WebContentSecurityPolicyType policy_type,
mojom::IPAddressSpace creation_address_space,
const base::UnguessableToken& devtools_worker_token,
+ PrivacyPreferences privacy_preferences,
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory,
mojo::ScopedMessagePipeHandle content_settings_handle,
mojo::ScopedMessagePipeHandle interface_provider) {
DCHECK(IsMainThread());
@@ -224,7 +229,12 @@ void WebSharedWorkerImpl::StartWorkerContext(
pending_interface_provider_.set_handle(std::move(interface_provider));
devtools_worker_token_ = devtools_worker_token;
- shadow_page_ = std::make_unique<WorkerShadowPage>(this);
+ // |shadow_page_| must be created after |devtools_worker_token_| because it
+ // triggers creation of a InspectorNetworkAgent that tries to access the
+ // token.
+ shadow_page_ =
+ std::make_unique<WorkerShadowPage>(this, std::move(loader_factory),
+ std::move(privacy_preferences));
// If we were asked to pause worker context on start and wait for debugger
// then now is a good time to do that.
@@ -327,8 +337,8 @@ void WebSharedWorkerImpl::ContinueOnScriptLoaderFinished() {
auto global_scope_creation_params =
std::make_unique<GlobalScopeCreationParams>(
url_, script_type, document->UserAgent(),
- content_security_policy ? content_security_policy->Headers().get()
- : nullptr,
+ content_security_policy ? content_security_policy->Headers()
+ : Vector<CSPHeaderAndType>(),
referrer_policy, starter_origin, starter_secure_context,
worker_clients, main_script_loader_->ResponseAddressSpace(),
main_script_loader_->OriginTrialTokens(), devtools_worker_token_,
@@ -337,16 +347,8 @@ void WebSharedWorkerImpl::ContinueOnScriptLoaderFinished() {
std::move(pending_interface_provider_));
String source_code = main_script_loader_->SourceText();
- // SharedWorker can sometimes run tasks that are initiated by/associated with
- // a document's frame but these documents can be from a different process. So
- // we intentionally populate the task runners with default task runners of the
- // main thread. Note that |m_document| should not be used as it's a dummy
- // document for loading that doesn't represent the frame of any associated
- // document.
- ParentExecutionContextTaskRunners* task_runners =
- ParentExecutionContextTaskRunners::Create();
-
- reporting_proxy_ = new SharedWorkerReportingProxy(this, task_runners);
+ reporting_proxy_ = new SharedWorkerReportingProxy(
+ this, parent_execution_context_task_runners_);
worker_thread_ = std::make_unique<SharedWorkerThread>(
name_, ThreadableLoadingContext::Create(*document), *reporting_proxy_);
probe::scriptImported(document, main_script_loader_->Identifier(),
@@ -360,7 +362,7 @@ void WebSharedWorkerImpl::ContinueOnScriptLoaderFinished() {
GetWorkerThread()->Start(
std::move(global_scope_creation_params), thread_startup_data,
worker_inspector_proxy_->ShouldPauseOnWorkerStart(document),
- task_runners);
+ parent_execution_context_task_runners_);
worker_inspector_proxy_->WorkerThreadCreated(document, GetWorkerThread(),
url_);
// TODO(nhiroki): Support module workers (https://crbug.com/680046).
@@ -385,6 +387,11 @@ void WebSharedWorkerImpl::BindDevToolsAgent(
std::move(devtools_agent_request)));
}
+scoped_refptr<base::SingleThreadTaskRunner> WebSharedWorkerImpl::GetTaskRunner(
+ TaskType task_type) {
+ return parent_execution_context_task_runners_->Get(task_type);
+}
+
std::unique_ptr<WebSharedWorker> WebSharedWorker::Create(
WebSharedWorkerClient* client) {
return base::WrapUnique(new WebSharedWorkerImpl(client));
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 ee624837d99..c7ba68eade9 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
@@ -38,6 +38,7 @@
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "services/service_manager/public/mojom/interface_provider.mojom-blink.h"
+#include "third_party/blink/public/common/privacy_preferences.h"
#include "third_party/blink/public/mojom/net/ip_address_space.mojom-shared.h"
#include "third_party/blink/public/platform/web_content_security_policy.h"
#include "third_party/blink/public/web/web_shared_worker_client.h"
@@ -48,6 +49,14 @@
#include "third_party/blink/renderer/core/workers/worker_clients.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h"
+namespace base {
+class SingleThreadTaskRunner;
+};
+
+namespace network {
+class SharedURLLoaderFactory;
+};
+
namespace blink {
class WebApplicationCacheHost;
@@ -87,14 +96,16 @@ class CORE_EXPORT WebSharedWorkerImpl final : public WebSharedWorker,
WebContentSecurityPolicyType,
mojom::IPAddressSpace,
const base::UnguessableToken& devtools_worker_token,
+ PrivacyPreferences privacy_preferences,
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory,
mojo::ScopedMessagePipeHandle content_settings_handle,
mojo::ScopedMessagePipeHandle interface_provider) override;
void Connect(MessagePortChannel) override;
void TerminateWorkerContext() override;
-
void PauseWorkerContextOnStart() override;
void BindDevToolsAgent(
mojo::ScopedInterfaceEndpointHandle devtools_agent_request) override;
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) override;
// Callback methods for SharedWorkerReportingProxy.
void CountFeature(WebFeature);
@@ -142,6 +153,15 @@ class CORE_EXPORT WebSharedWorkerImpl final : public WebSharedWorker,
service_manager::mojom::blink::InterfaceProviderPtrInfo
pending_interface_provider_;
+ // SharedWorker can sometimes run tasks that are initiated by/associated with
+ // a document's frame but these documents can be from a different process. So
+ // we intentionally populate the task runners with default task runners of the
+ // main thread. Note that |shadow_page_| should not be used as it's a dummy
+ // document for loading that doesn't represent the frame of any associated
+ // document.
+ Persistent<ParentExecutionContextTaskRunners>
+ parent_execution_context_task_runners_;
+
base::WeakPtrFactory<WebSharedWorkerImpl> weak_ptr_factory_;
};
diff --git a/chromium/third_party/blink/renderer/core/exported/web_user_gesture_indicator.cc b/chromium/third_party/blink/renderer/core/exported/web_user_gesture_indicator.cc
index a1015d0a81c..02bf71a908f 100644
--- a/chromium/third_party/blink/renderer/core/exported/web_user_gesture_indicator.cc
+++ b/chromium/third_party/blink/renderer/core/exported/web_user_gesture_indicator.cc
@@ -51,9 +51,12 @@ bool WebUserGestureIndicator::IsProcessingUserGestureThreadSafe(
// TODO(csharrison): consumeUserGesture() and currentUserGestureToken() use
// the thread-safe API, which many callers probably do not need. Consider
// updating them if they are in any sort of critical path or called often.
-bool WebUserGestureIndicator::ConsumeUserGesture(WebLocalFrame* frame) {
+bool WebUserGestureIndicator::ConsumeUserGesture(
+ WebLocalFrame* frame,
+ UserActivationUpdateSource update_source) {
return Frame::ConsumeTransientUserActivation(
- frame ? ToWebLocalFrameImpl(frame)->GetFrame() : nullptr, true);
+ frame ? ToWebLocalFrameImpl(frame)->GetFrame() : nullptr, true,
+ update_source);
;
}
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 80ba4c18ebc..2acc5921abe 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
@@ -37,11 +37,9 @@
#include "base/memory/scoped_refptr.h"
#include "base/time/time.h"
#include "build/build_config.h"
-#include "cc/layers/layer.h"
+#include "cc/layers/picture_layer.h"
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom-blink.h"
-#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_float_point.h"
-#include "third_party/blink/public/platform/web_gesture_curve.h"
#include "third_party/blink/public/platform/web_image.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/public/platform/web_layer_tree_view.h"
@@ -54,9 +52,9 @@
#include "third_party/blink/public/web/web_console_message.h"
#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_client.h"
#include "third_party/blink/public/web/web_hit_test_result.h"
#include "third_party/blink/public/web/web_input_element.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_meaningful_layout.h"
#include "third_party/blink/public/web/web_media_player_action.h"
#include "third_party/blink/public/web/web_node.h"
@@ -64,8 +62,8 @@
#include "third_party/blink/public/web/web_plugin_action.h"
#include "third_party/blink/public/web/web_range.h"
#include "third_party/blink/public/web/web_scoped_user_gesture.h"
-#include "third_party/blink/public/web/web_selection.h"
#include "third_party/blink/public/web/web_view_client.h"
+#include "third_party/blink/public/web/web_widget_client.h"
#include "third_party/blink/public/web/web_window_features.h"
#include "third_party/blink/renderer/core/clipboard/data_object.h"
#include "third_party/blink/renderer/core/core_initializer.h"
@@ -96,6 +94,7 @@
#include "third_party/blink/renderer/core/frame/browser_controls.h"
#include "third_party/blink/renderer/core/frame/event_handler_registry.h"
#include "third_party/blink/renderer/core/frame/fullscreen_controller.h"
+#include "third_party/blink/renderer/core/frame/link_highlights.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"
@@ -105,13 +104,13 @@
#include "third_party/blink/renderer/core/frame/rotation_viewport_anchor.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/core/frame/viewport_data.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/html_text_area_element.h"
#include "third_party/blink/renderer/core/html/html_plugin_element.h"
-#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/html/plugin_document.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/input/context_menu_allowed_scope.h"
@@ -133,7 +132,6 @@
#include "third_party/blink/renderer/core/page/focus_controller.h"
#include "third_party/blink/renderer/core/page/frame_tree.h"
#include "third_party/blink/renderer/core/page/page.h"
-#include "third_party/blink/renderer/core/page/page_lifecycle_state.h"
#include "third_party/blink/renderer/core/page/page_overlay.h"
#include "third_party/blink/renderer/core/page/page_popup_client.h"
#include "third_party/blink/renderer/core/page/pointer_lock_controller.h"
@@ -142,16 +140,14 @@
#include "third_party/blink/renderer/core/page/validation_message_client_impl.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h"
-#include "third_party/blink/renderer/core/paint/link_highlight_impl.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/timing/dom_window_performance.h"
#include "third_party/blink/renderer/core/timing/window_performance.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_host.h"
#include "third_party/blink/renderer/platform/cursor.h"
-#include "third_party/blink/renderer/platform/exported/web_active_gesture_animation.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
-#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/graphics/compositor_mutator_client.h"
#include "third_party/blink/renderer/platform/graphics/compositor_mutator_impl.h"
#include "third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h"
@@ -164,6 +160,7 @@
#include "third_party/blink/renderer/platform/keyboard_codes.h"
#include "third_party/blink/renderer/platform/loader/fetch/unique_identifier.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#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/scroll/scrollbar_theme.h"
@@ -192,10 +189,6 @@ static const float doubleTapZoomAlreadyLegibleRatio = 1.2f;
static const double multipleTargetsZoomAnimationDurationInSeconds = 0.25;
static const double findInPageAnimationDurationInSeconds = 0;
-// Constants for snapping to minimum zoom.
-static const double maximumZoomForSnapToMinimum = 1.05;
-static const double snapToMiminimumZoomAnimationDurationInSeconds = 0.2;
-
// Constants for viewport anchoring on resize.
static const float viewportAnchorCoordX = 0.5f;
static const float viewportAnchorCoordY = 0;
@@ -293,18 +286,20 @@ class ColorOverlay final : public PageOverlay::Delegate {
// WebView ----------------------------------------------------------------
WebView* WebView::Create(WebViewClient* client,
+ WebWidgetClient* widget_client,
mojom::PageVisibilityState visibility_state,
WebView* opener) {
- return WebViewImpl::Create(client, visibility_state,
+ return WebViewImpl::Create(client, widget_client, visibility_state,
static_cast<WebViewImpl*>(opener));
}
WebViewImpl* WebViewImpl::Create(WebViewClient* client,
+ WebWidgetClient* widget_client,
mojom::PageVisibilityState visibility_state,
WebViewImpl* opener) {
// Pass the WebViewImpl's self-reference to the caller.
- auto web_view =
- base::AdoptRef(new WebViewImpl(client, visibility_state, opener));
+ auto web_view = base::AdoptRef(
+ new WebViewImpl(client, widget_client, visibility_state, opener));
web_view->AddRef();
return web_view.get();
}
@@ -325,9 +320,11 @@ void WebViewImpl::SetPrerendererClient(
}
WebViewImpl::WebViewImpl(WebViewClient* client,
+ WebWidgetClient* widget_client,
mojom::PageVisibilityState visibility_state,
WebViewImpl* opener)
: client_(client),
+ widget_client_(widget_client),
chrome_client_(ChromeClientImpl::Create(this)),
should_auto_resize_(false),
zoom_level_(0),
@@ -364,6 +361,7 @@ WebViewImpl::WebViewImpl(WebViewClient* client,
elastic_overscroll_(FloatSize()),
mutator_(nullptr),
override_compositor_visibility_(false) {
+ DCHECK_EQ(!!client_, !!widget_client_);
Page::PageClients page_clients;
page_clients.chrome_client = chrome_client_.Get();
@@ -385,11 +383,6 @@ WebViewImpl::WebViewImpl(WebViewClient* client,
WebViewImpl::~WebViewImpl() {
DCHECK(!page_);
-
- // Each highlight uses m_owningWebViewImpl->m_linkHighlightsTimeline
- // in destructor. m_linkHighlightsTimeline might be destroyed earlier
- // than m_linkHighlights.
- DCHECK(link_highlights_.IsEmpty());
}
ValidationMessageClient* WebViewImpl::GetValidationMessageClient() const {
@@ -438,14 +431,14 @@ void WebViewImpl::HandleMouseDown(LocalFrame& main_frame,
// Take capture on a mouse down on a plugin so we can send it mouse events.
// If the hit node is a plugin but a scrollbar is over it don't start mouse
// capture because it will interfere with the scrollbar receiving events.
- LayoutPoint point(event.PositionInWidget());
if (event.button == WebMouseEvent::Button::kLeft &&
page_->MainFrame()->IsLocalFrame()) {
- point =
- page_->DeprecatedLocalMainFrame()->View()->RootFrameToContents(point);
+ HitTestLocation location(
+ page_->DeprecatedLocalMainFrame()->View()->ConvertFromRootFrame(
+ event.PositionInWidget()));
HitTestResult result(page_->DeprecatedLocalMainFrame()
->GetEventHandler()
- .HitTestResultAtPoint(point));
+ .HitTestResultAtLocation(location));
result.SetToShadowHostIfInRestrictedShadowRoot();
Node* hit_node = result.InnerNodeOrImageMapImage();
@@ -539,37 +532,22 @@ void WebViewImpl::HandleMouseUp(LocalFrame& main_frame,
WebInputEventResult WebViewImpl::HandleMouseWheel(
LocalFrame& main_frame,
const WebMouseWheelEvent& event) {
- // Halt an in-progress fling on a wheel tick.
- if (!event.has_precise_scrolling_deltas) {
- if (WebFrameWidgetBase* widget = MainFrameImpl()->FrameWidgetImpl())
- widget->EndActiveFlingAnimation();
- }
HidePopups();
return PageWidgetEventHandler::HandleMouseWheel(main_frame, event);
}
WebInputEventResult WebViewImpl::HandleGestureEvent(
const WebGestureEvent& event) {
- if (!client_ || !client_->CanHandleGestureEvent()) {
+ if (!client_ || !WidgetClient() || !client_->CanHandleGestureEvent()) {
return WebInputEventResult::kNotHandled;
}
WebInputEventResult event_result = WebInputEventResult::kNotHandled;
bool event_cancelled = false; // for disambiguation
- // Special handling for slow-path fling gestures.
- switch (event.GetType()) {
- case WebInputEvent::kGestureFlingStart:
- case WebInputEvent::kGestureFlingCancel: {
- if (WebFrameWidgetBase* widget = MainFrameImpl()->FrameWidgetImpl())
- event_result = widget->HandleGestureFlingEvent(event);
-
- client_->DidHandleGestureEvent(event, event_cancelled);
- return event_result;
- }
- default:
- break;
- }
+ // Fling events are not sent to the renderer.
+ CHECK(event.GetType() != WebInputEvent::kGestureFlingStart);
+ CHECK(event.GetType() != WebInputEvent::kGestureFlingCancel);
WebGestureEvent scaled_event =
TransformWebGestureEvent(MainFrameImpl()->GetFrameView(), event);
@@ -587,12 +565,11 @@ WebInputEventResult WebViewImpl::HandleGestureEvent(
// WebCore, GestureTap with tap count = 2 is used instead. So we drop
// GestureDoubleTap here.
event_result = WebInputEventResult::kHandledSystem;
- client_->DidHandleGestureEvent(event, event_cancelled);
+ WidgetClient()->DidHandleGestureEvent(event, event_cancelled);
return event_result;
case WebInputEvent::kGestureScrollBegin:
case WebInputEvent::kGestureScrollEnd:
case WebInputEvent::kGestureScrollUpdate:
- case WebInputEvent::kGestureFlingStart:
// 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
@@ -602,12 +579,8 @@ WebInputEventResult WebViewImpl::HandleGestureEvent(
->GetFrame()
->GetEventHandler()
.HandleGestureScrollEvent(scaled_event);
- client_->DidHandleGestureEvent(event, event_cancelled);
+ WidgetClient()->DidHandleGestureEvent(event, event_cancelled);
return event_result;
- case WebInputEvent::kGesturePinchBegin:
- case WebInputEvent::kGesturePinchEnd:
- case WebInputEvent::kGesturePinchUpdate:
- return WebInputEventResult::kNotHandled;
default:
break;
}
@@ -628,8 +601,7 @@ WebInputEventResult WebViewImpl::HandleGestureEvent(
case WebInputEvent::kGestureTapCancel:
case WebInputEvent::kGestureTap:
case WebInputEvent::kGestureLongPress:
- for (size_t i = 0; i < link_highlights_.size(); ++i)
- link_highlights_[i]->StartHighlightAnimationIfNeeded();
+ GetPage()->GetLinkHighlights().StartHighlightAnimationIfNeeded();
break;
default:
break;
@@ -673,12 +645,11 @@ WebInputEventResult WebViewImpl::HandleGestureEvent(
// Stash the position of the node that would've been used absent
// disambiguation, for UMA purposes.
last_tap_disambiguation_best_candidate_position_ =
- targeted_event.GetHitTestResult().RoundedPointInMainFrame() -
+ RoundedIntPoint(targeted_event.GetHitTestLocation().Point()) -
RoundedIntSize(targeted_event.GetHitTestResult().LocalPoint());
EnableTapHighlights(highlight_nodes);
- for (size_t i = 0; i < link_highlights_.size(); ++i)
- link_highlights_[i]->StartHighlightAnimationIfNeeded();
+ GetPage()->GetLinkHighlights().StartHighlightAnimationIfNeeded();
event_result = WebInputEventResult::kHandledSystem;
event_cancelled = true;
break;
@@ -754,7 +725,7 @@ WebInputEventResult WebViewImpl::HandleGestureEvent(
}
default: { NOTREACHED(); }
}
- client_->DidHandleGestureEvent(event, event_cancelled);
+ WidgetClient()->DidHandleGestureEvent(event, event_cancelled);
return event_result;
}
@@ -798,7 +769,7 @@ void WebViewImpl::ResolveTapDisambiguation(base::TimeTicks timestamp,
page_->DeprecatedLocalMainFrame()->GetEventHandler().TargetGestureEvent(
scaled_event);
WebPoint node_position =
- targeted_event.GetHitTestResult().RoundedPointInMainFrame() -
+ RoundedIntPoint(targeted_event.GetHitTestLocation().Point()) -
RoundedIntSize(targeted_event.GetHitTestResult().LocalPoint());
TapDisambiguationResult result =
(node_position == last_tap_disambiguation_best_candidate_position_)
@@ -810,43 +781,6 @@ void WebViewImpl::ResolveTapDisambiguation(base::TimeTicks timestamp,
HandleGestureEvent(event);
}
-WebInputEventResult WebViewImpl::HandleSyntheticWheelFromTouchpadPinchEvent(
- const WebGestureEvent& pinch_event) {
- DCHECK_EQ(pinch_event.GetType(), WebInputEvent::kGesturePinchUpdate);
-
- // For pinch gesture events, match typical trackpad behavior on Windows by
- // sending fake wheel events with the ctrl modifier set when we see trackpad
- // pinch gestures. Ideally we'd someday get a platform 'pinch' event and
- // send that instead.
- WebMouseWheelEvent wheel_event(
- WebInputEvent::kMouseWheel,
- pinch_event.GetModifiers() | WebInputEvent::kControlKey,
- pinch_event.TimeStamp());
- wheel_event.SetPositionInWidget(pinch_event.PositionInWidget().x,
- pinch_event.PositionInWidget().y);
- wheel_event.SetPositionInScreen(pinch_event.PositionInScreen().x,
- pinch_event.PositionInScreen().y);
- wheel_event.delta_x = 0;
-
- // The function to convert scales to deltaY values is designed to be
- // compatible with websites existing use of wheel events, and with existing
- // Windows trackpad behavior. In particular, we want:
- // - deltas should accumulate via addition: f(s1*s2)==f(s1)+f(s2)
- // - deltas should invert via negation: f(1/s) == -f(s)
- // - zoom in should be positive: f(s) > 0 iff s > 1
- // - magnitude roughly matches wheels: f(2) > 25 && f(2) < 100
- // - a formula that's relatively easy to use from JavaScript
- // Note that 'wheel' event deltaY values have their sign inverted. So to
- // convert a wheel deltaY back to a scale use Math.exp(-deltaY/100).
- DCHECK_GT(pinch_event.data.pinch_update.scale, 0);
- wheel_event.delta_y = 100.0f * log(pinch_event.data.pinch_update.scale);
- wheel_event.has_precise_scrolling_deltas = true;
- wheel_event.wheel_ticks_x = 0;
- wheel_event.wheel_ticks_y = pinch_event.data.pinch_update.scale > 1 ? 1 : -1;
-
- return HandleInputEvent(blink::WebCoalescedInputEvent(wheel_event));
-}
-
bool WebViewImpl::StartPageScaleAnimation(const IntPoint& target_position,
bool use_anchor,
float new_scale,
@@ -879,8 +813,9 @@ bool WebViewImpl::StartPageScaleAnimation(const IntPoint& target_position,
} else {
if (!layer_tree_view_)
return false;
- layer_tree_view_->StartPageScaleAnimation(target_position, use_anchor,
- new_scale, duration_in_seconds);
+ layer_tree_view_->StartPageScaleAnimation(
+ static_cast<gfx::Vector2d>(target_position), use_anchor, new_scale,
+ duration_in_seconds);
}
return true;
}
@@ -938,10 +873,6 @@ WebInputEventResult WebViewImpl::HandleKeyEvent(const WebKeyboardEvent& event) {
WebInputEvent::GetName(event.GetType()), "text",
String(event.text).Utf8());
- // Halt an in-progress fling on a key event.
- if (WebFrameWidgetBase* widget = MainFrameImpl()->FrameWidgetImpl())
- widget->EndActiveFlingAnimation();
-
// Please refer to the comments explaining the m_suppressNextKeypressEvent
// member.
// The m_suppressNextKeypressEvent is set if the KeyDown is handled by
@@ -1075,14 +1006,15 @@ WebRect WebViewImpl::ComputeBlockBound(const WebPoint& point_in_root_frame,
return WebRect();
// Use the point-based hit test to find the node.
- LayoutPoint point = MainFrameImpl()->GetFrameView()->RootFrameToAbsolute(
- LayoutPoint(point_in_root_frame));
+ HitTestLocation location(
+ MainFrameImpl()->GetFrameView()->ConvertFromRootFrame(
+ LayoutPoint(point_in_root_frame)));
HitTestRequest::HitTestRequestType hit_type =
HitTestRequest::kReadOnly | HitTestRequest::kActive |
(ignore_clipping ? HitTestRequest::kIgnoreClipping : 0);
HitTestResult result =
- MainFrameImpl()->GetFrame()->GetEventHandler().HitTestResultAtPoint(
- point, hit_type);
+ MainFrameImpl()->GetFrame()->GetEventHandler().HitTestResultAtLocation(
+ location, hit_type);
result.SetToShadowHostIfInRestrictedShadowRoot();
Node* node = result.InnerNodeOrImageMapImage();
@@ -1100,7 +1032,7 @@ WebRect WebViewImpl::ComputeBlockBound(const WebPoint& point_in_root_frame,
if (node) {
IntRect absolute_rect = node->GetLayoutObject()->AbsoluteBoundingBoxRect();
LocalFrame* frame = node->GetDocument().GetFrame();
- return frame->View()->AbsoluteToRootFrame(absolute_rect);
+ return frame->View()->ConvertToRootFrame(absolute_rect);
}
return WebRect();
}
@@ -1310,30 +1242,7 @@ void WebViewImpl::EnableTapHighlightAtPoint(
void WebViewImpl::EnableTapHighlights(
HeapVector<Member<Node>>& highlight_nodes) {
- if (highlight_nodes.IsEmpty())
- return;
-
- // Always clear any existing highlight when this is invoked, even if we
- // don't get a new target to highlight.
- link_highlights_.clear();
-
- for (size_t i = 0; i < highlight_nodes.size(); ++i) {
- Node* node = highlight_nodes[i];
-
- if (!node || !node->GetLayoutObject())
- continue;
-
- Color highlight_color =
- node->GetLayoutObject()->Style()->TapHighlightColor();
- // Safari documentation for -webkit-tap-highlight-color says if the
- // specified color has 0 alpha, then tap highlighting is disabled.
- // http://developer.apple.com/library/safari/#documentation/appleapplications/reference/safaricssref/articles/standardcssproperties.html
- if (!highlight_color.Alpha())
- continue;
-
- link_highlights_.push_back(LinkHighlightImpl::Create(node, this));
- }
-
+ GetPage()->GetLinkHighlights().SetTapHighlights(highlight_nodes);
UpdateAllLifecyclePhases();
}
@@ -1588,15 +1497,19 @@ void WebViewImpl::UpdateICBAndResizeViewport() {
// controls hide so that the ICB will always be the same size as the
// viewport with the browser controls shown.
IntSize icb_size = size_;
- if (GetBrowserControls().PermittedState() == kWebBrowserControlsBoth &&
+ if (GetBrowserControls().PermittedState() ==
+ cc::BrowserControlsState::kBoth &&
!GetBrowserControls().ShrinkViewport()) {
icb_size.Expand(0, -GetBrowserControls().TotalHeight());
}
GetPageScaleConstraintsSet().DidChangeInitialContainingBlockSize(icb_size);
- UpdatePageDefinedViewportConstraints(
- MainFrameImpl()->GetFrame()->GetDocument()->GetViewportDescription());
+ UpdatePageDefinedViewportConstraints(MainFrameImpl()
+ ->GetFrame()
+ ->GetDocument()
+ ->GetViewportData()
+ .GetViewportDescription());
UpdateMainFrameLayoutSize();
GetPage()->GetVisualViewport().SetSize(size_);
@@ -1608,10 +1521,11 @@ void WebViewImpl::UpdateICBAndResizeViewport() {
}
}
-void WebViewImpl::UpdateBrowserControlsState(WebBrowserControlsState constraint,
- WebBrowserControlsState current,
- bool animate) {
- WebBrowserControlsState old_permitted_state =
+void WebViewImpl::UpdateBrowserControlsState(
+ cc::BrowserControlsState constraint,
+ cc::BrowserControlsState current,
+ bool animate) {
+ cc::BrowserControlsState old_permitted_state =
GetBrowserControls().PermittedState();
GetBrowserControls().UpdateConstraintsAndState(constraint, current, animate);
@@ -1620,10 +1534,10 @@ void WebViewImpl::UpdateBrowserControlsState(WebBrowserControlsState constraint,
// versa, the ICB size needs to change but we can't rely on getting a
// WebViewImpl::resize since the top controls shown state may not have
// changed.
- if ((old_permitted_state == kWebBrowserControlsHidden &&
- constraint == kWebBrowserControlsBoth) ||
- (old_permitted_state == kWebBrowserControlsBoth &&
- constraint == kWebBrowserControlsHidden)) {
+ if ((old_permitted_state == cc::BrowserControlsState::kHidden &&
+ constraint == cc::BrowserControlsState::kBoth) ||
+ (old_permitted_state == cc::BrowserControlsState::kBoth &&
+ constraint == cc::BrowserControlsState::kHidden)) {
UpdateICBAndResizeViewport();
}
@@ -1795,9 +1709,6 @@ void WebViewImpl::BeginFrame(base::TimeTicks last_frame_time) {
if (!MainFrameImpl())
return;
- if (WebFrameWidgetBase* widget = MainFrameImpl()->FrameWidgetImpl())
- widget->UpdateGestureAnimation(last_frame_time);
-
DocumentLifecycle::AllowThrottlingScope throttling_scope(
MainFrameImpl()->GetFrame()->GetDocument()->Lifecycle());
PageWidgetDelegate::Animate(*page_, last_frame_time);
@@ -1829,8 +1740,8 @@ void WebViewImpl::UpdateLifecycle(LifecycleUpdate requested_update) {
// TODO(chrishtr): link highlights don't currently paint themselves, it's
// still driven by cc. Fix this.
- for (size_t i = 0; i < link_highlights_.size(); ++i)
- link_highlights_[i]->UpdateGeometry();
+ // TODO(pdr): Move this to LocalFrameView::UpdateLifecyclePhasesInternal.
+ GetPage()->GetLinkHighlights().UpdateGeometry();
if (LocalFrameView* view = MainFrameImpl()->GetFrameView()) {
LocalFrame* frame = MainFrameImpl()->GetFrame();
@@ -1869,32 +1780,32 @@ void WebViewImpl::CompositeWithRasterForTesting() {
NOTREACHED();
}
-void WebViewImpl::Paint(WebCanvas* canvas, const WebRect& rect) {
+void WebViewImpl::PaintContent(cc::PaintCanvas* canvas, const WebRect& rect) {
// This should only be used when compositing is not being used for this
// WebView, and it is painting into the recording of its parent.
DCHECK(!IsAcceleratedCompositingActive());
- PageWidgetDelegate::Paint(*page_, canvas, rect,
- *page_->DeprecatedLocalMainFrame());
+ PageWidgetDelegate::PaintContent(*page_, canvas, rect,
+ *page_->DeprecatedLocalMainFrame());
}
-#if defined(OS_ANDROID)
-void WebViewImpl::PaintIgnoringCompositing(WebCanvas* canvas,
- const WebRect& rect) {
+void WebViewImpl::PaintContentIgnoringCompositing(cc::PaintCanvas* canvas,
+ const WebRect& rect) {
// This is called on a composited WebViewImpl, but we will ignore it,
- // producing all possible content of the WebViewImpl into the WebCanvas.
+ // producing all possible content of the WebViewImpl into the PaintCanvas.
DCHECK(IsAcceleratedCompositingActive());
- PageWidgetDelegate::PaintIgnoringCompositing(
+ PageWidgetDelegate::PaintContentIgnoringCompositing(
*page_, canvas, rect, *page_->DeprecatedLocalMainFrame());
}
-#endif
void WebViewImpl::LayoutAndPaintAsync(base::OnceClosure callback) {
- layer_tree_view_->LayoutAndPaintAsync(std::move(callback));
+ if (layer_tree_view_)
+ layer_tree_view_->LayoutAndPaintAsync(std::move(callback));
}
void WebViewImpl::CompositeAndReadbackAsync(
base::OnceCallback<void(const SkBitmap&)> callback) {
- layer_tree_view_->CompositeAndReadbackAsync(std::move(callback));
+ if (layer_tree_view_)
+ layer_tree_view_->CompositeAndReadbackAsync(std::move(callback));
}
void WebViewImpl::ThemeChanged() {
@@ -1925,15 +1836,12 @@ void WebViewImpl::FullscreenElementChanged(Element* old_element,
bool WebViewImpl::HasHorizontalScrollbar() {
return MainFrameImpl()
->GetFrameView()
- ->LayoutViewportScrollableArea()
+ ->LayoutViewport()
->HorizontalScrollbar();
}
bool WebViewImpl::HasVerticalScrollbar() {
- return MainFrameImpl()
- ->GetFrameView()
- ->LayoutViewportScrollableArea()
- ->VerticalScrollbar();
+ return MainFrameImpl()->GetFrameView()->LayoutViewport()->VerticalScrollbar();
}
WebInputEventResult WebViewImpl::DispatchBufferedTouchEvents() {
@@ -1955,7 +1863,6 @@ WebInputEventResult WebViewImpl::HandleInputEvent(
// routing code.
if (!MainFrameImpl())
return WebInputEventResult::kNotHandled;
-
DCHECK(!WebInputEvent::IsTouchEventType(input_event.GetType()));
GetPage()->GetVisualViewport().StartTrackingPinchStats();
@@ -1969,9 +1876,6 @@ WebInputEventResult WebViewImpl::HandleInputEvent(
input_event.GetType() != WebInputEvent::kPointerCancel)
return WebInputEventResult::kHandledSuppressed;
- if (dev_tools_emulator_->HandleInputEvent(input_event))
- return WebInputEventResult::kHandledSuppressed;
-
if (WebDevToolsAgentImpl* devtools = MainFrameDevToolsAgentImpl()) {
if (devtools->HandleInputEvent(input_event))
return WebInputEventResult::kHandledSuppressed;
@@ -2062,50 +1966,8 @@ WebInputEventResult WebViewImpl::HandleInputEvent(
}
// FIXME: This should take in the intended frame, not the local frame root.
- WebInputEventResult result = PageWidgetDelegate::HandleInputEvent(
- *this, coalesced_event, MainFrameImpl()->GetFrame());
- if (result != WebInputEventResult::kNotHandled)
- return result;
-
- // Unhandled pinch events should adjust the scale.
- if (input_event.GetType() == WebInputEvent::kGesturePinchUpdate) {
- const WebGestureEvent& pinch_event =
- static_cast<const WebGestureEvent&>(input_event);
-
- // For touchpad gestures synthesize a Windows-like wheel event
- // to send to any handlers that may exist. Not necessary for touchscreen
- // as touch events would have already been sent for the gesture.
- if (pinch_event.SourceDevice() == kWebGestureDeviceTouchpad) {
- result = HandleSyntheticWheelFromTouchpadPinchEvent(pinch_event);
- if (result != WebInputEventResult::kNotHandled)
- return result;
- }
-
- if (pinch_event.data.pinch_update.zoom_disabled)
- return WebInputEventResult::kNotHandled;
-
- if (GetPage()->GetVisualViewport().MagnifyScaleAroundAnchor(
- pinch_event.data.pinch_update.scale,
- pinch_event.PositionInWidget()))
- return WebInputEventResult::kHandledSystem;
- }
-
- // If the page is close to minimum scale at pinch end, snap to minimum.
- if (input_event.GetType() == WebInputEvent::kGesturePinchEnd) {
- const WebGestureEvent& pinch_event =
- static_cast<const WebGestureEvent&>(input_event);
- float min_scale = MinimumPageScaleFactor();
- if (pinch_event.SourceDevice() == kWebGestureDeviceTouchpad &&
- PageScaleFactor() <= min_scale * maximumZoomForSnapToMinimum) {
- IntPoint target_position =
- MainFrameImpl()->GetFrameView()->ViewportToContents(
- FlooredIntPoint(pinch_event.PositionInWidget()));
- StartPageScaleAnimation(target_position, true, min_scale,
- snapToMiminimumZoomAnimationDurationInSeconds);
- }
- }
-
- return WebInputEventResult::kNotHandled;
+ return PageWidgetDelegate::HandleInputEvent(*this, coalesced_event,
+ MainFrameImpl()->GetFrame());
}
void WebViewImpl::SetCursorVisibilityState(bool is_visible) {
@@ -2198,9 +2060,9 @@ bool WebViewImpl::SelectionBounds(WebRect& anchor_web,
VisualViewport& visual_viewport = GetPage()->GetVisualViewport();
anchor_web = visual_viewport.RootFrameToViewport(
- frame_view->AbsoluteToRootFrame(anchor));
+ frame_view->ConvertToRootFrame(anchor));
focus_web = visual_viewport.RootFrameToViewport(
- frame_view->AbsoluteToRootFrame(focus));
+ frame_view->ConvertToRootFrame(focus));
return true;
}
@@ -2228,12 +2090,6 @@ bool WebViewImpl::IsAcceleratedCompositingActive() const {
}
void WebViewImpl::WillCloseLayerTreeView() {
- if (link_highlights_timeline_) {
- link_highlights_.clear();
- DetachCompositorAnimationTimeline(link_highlights_timeline_.get());
- link_highlights_timeline_.reset();
- }
-
if (layer_tree_view_)
GetPage()->WillCloseLayerTreeView(*layer_tree_view_, nullptr);
@@ -2413,10 +2269,10 @@ bool WebViewImpl::ScrollFocusedEditableElementIntoView() {
ZoomAndScrollToFocusedEditableElementRect(
main_frame_view->RootFrameToDocument(
- element->GetDocument().View()->AbsoluteToRootFrame(
+ element->GetDocument().View()->ConvertToRootFrame(
layout_object->AbsoluteBoundingBoxRect())),
main_frame_view->RootFrameToDocument(
- element->GetDocument().View()->AbsoluteToRootFrame(
+ element->GetDocument().View()->ConvertToRootFrame(
element->GetDocument()
.GetFrame()
->Selection()
@@ -2482,10 +2338,11 @@ void WebViewImpl::ComputeScaleAndScrollForEditableElementRects(
// the caret height will become minReadableCaretHeightForNode (adjusted
// for dpi and font scale factor).
const int min_readable_caret_height_for_node =
- element_bounds_in_document.Height() >=
- 2 * caret_bounds_in_document.Height()
- ? minReadableCaretHeightForTextArea
- : minReadableCaretHeight;
+ (element_bounds_in_document.Height() >=
+ 2 * caret_bounds_in_document.Height()
+ ? minReadableCaretHeightForTextArea
+ : minReadableCaretHeight) *
+ MainFrameImpl()->GetFrame()->PageZoomFactor();
new_scale = ClampPageScaleFactorToLimits(
MaximumLegiblePageScale() * min_readable_caret_height_for_node /
caret_bounds_in_document.Height());
@@ -2678,30 +2535,6 @@ WebFloatSize WebViewImpl::VisualViewportSize() const {
return GetPage()->GetVisualViewport().VisibleRect().Size();
}
-void WebViewImpl::ScrollAndRescaleViewports(
- float scale_factor,
- const IntPoint& main_frame_origin,
- const FloatPoint& visual_viewport_origin) {
- if (!GetPage())
- return;
-
- if (!MainFrameImpl())
- return;
-
- LocalFrameView* view = MainFrameImpl()->GetFrameView();
- if (!view)
- return;
-
- // Order is important: visual viewport location is clamped based on
- // main frame scroll position and visual viewport scale.
-
- view->SetScrollOffset(ToScrollOffset(main_frame_origin), kProgrammaticScroll);
-
- SetPageScaleFactor(scale_factor);
-
- GetPage()->GetVisualViewport().SetLocation(visual_viewport_origin);
-}
-
void WebViewImpl::SetPageScaleFactorAndLocation(float scale_factor,
const FloatPoint& location) {
DCHECK(GetPage());
@@ -2732,10 +2565,8 @@ void WebViewImpl::SetDeviceScaleFactor(float scale_factor) {
void WebViewImpl::SetZoomFactorForDeviceScaleFactor(
float zoom_factor_for_device_scale_factor) {
- if (zoom_factor_for_device_scale_factor_ ==
- zoom_factor_for_device_scale_factor) {
- return;
- }
+ // We can't early-return here if these are already equal, because we may
+ // need to propagate the correct zoom factor to newly navigated frames.
zoom_factor_for_device_scale_factor_ = zoom_factor_for_device_scale_factor;
if (!layer_tree_view_)
return;
@@ -2810,14 +2641,19 @@ void WebViewImpl::RefreshPageScaleFactorAfterLayout() {
return;
LocalFrameView* view = GetPage()->DeprecatedLocalMainFrame()->View();
- UpdatePageDefinedViewportConstraints(
- MainFrameImpl()->GetFrame()->GetDocument()->GetViewportDescription());
+ UpdatePageDefinedViewportConstraints(MainFrameImpl()
+ ->GetFrame()
+ ->GetDocument()
+ ->GetViewportData()
+ .GetViewportDescription());
GetPageScaleConstraintsSet().ComputeFinalConstraints();
int vertical_scrollbar_width = 0;
- if (view->VerticalScrollbar() &&
- !view->VerticalScrollbar()->IsOverlayScrollbar())
- vertical_scrollbar_width = view->VerticalScrollbar()->Width();
+ if (view->LayoutViewport()->VerticalScrollbar() &&
+ !view->LayoutViewport()->VerticalScrollbar()->IsOverlayScrollbar()) {
+ vertical_scrollbar_width =
+ view->LayoutViewport()->VerticalScrollbar()->Width();
+ }
GetPageScaleConstraintsSet().AdjustFinalConstraintsToContentsSize(
ContentsSize(), vertical_scrollbar_width,
GetSettings()->ShrinksViewportContentToFit());
@@ -2862,7 +2698,8 @@ void WebViewImpl::UpdatePageDefinedViewportConstraints(
matches_heuristics_for_gpu_rasterization_);
}
- Length default_min_width = document->ViewportDefaultMinWidth();
+ Length default_min_width =
+ document->GetViewportData().ViewportDefaultMinWidth();
if (default_min_width.IsAuto())
default_min_width = Length(kExtendToZoom);
@@ -3005,8 +2842,7 @@ void WebViewImpl::ResetScrollAndScaleState() {
if (LocalFrameView* frame_view =
ToLocalFrame(GetPage()->MainFrame())->View()) {
- ScrollableArea* scrollable_area =
- frame_view->LayoutViewportScrollableArea();
+ ScrollableArea* scrollable_area = frame_view->LayoutViewport();
if (!scrollable_area->GetScrollOffset().IsZero())
scrollable_area->SetScrollOffset(ScrollOffset(), kProgrammaticScroll);
@@ -3023,38 +2859,6 @@ void WebViewImpl::ResetScrollAndScaleState() {
GetPageScaleConstraintsSet().SetNeedsReset(true);
}
-void WebViewImpl::PerformMediaPlayerAction(const WebMediaPlayerAction& action,
- const WebPoint& location) {
- HitTestResult result = HitTestResultForRootFramePos(
- page_->GetVisualViewport().ViewportToRootFrame(location));
-
- Node* node = result.InnerNode();
- if (!IsHTMLVideoElement(*node) && !IsHTMLAudioElement(*node))
- return;
-
- HTMLMediaElement* media_element = ToHTMLMediaElement(node);
- switch (action.type) {
- case WebMediaPlayerAction::kPlay:
- if (action.enable)
- media_element->Play();
- else
- media_element->pause();
- break;
- case WebMediaPlayerAction::kMute:
- media_element->setMuted(action.enable);
- break;
- case WebMediaPlayerAction::kLoop:
- media_element->SetLoop(action.enable);
- break;
- case WebMediaPlayerAction::kControls:
- media_element->SetBooleanAttribute(HTMLNames::controlsAttr,
- action.enable);
- break;
- default:
- NOTREACHED();
- }
-}
-
void WebViewImpl::PerformPluginAction(const WebPluginAction& action,
const WebPoint& location) {
// FIXME: Location is probably in viewport coordinates
@@ -3103,8 +2907,8 @@ HitTestResult WebViewImpl::CoreHitTestResultAt(
DocumentLifecycle::AllowThrottlingScope throttling_scope(
MainFrameImpl()->GetFrame()->GetDocument()->Lifecycle());
LocalFrameView* view = MainFrameImpl()->GetFrameView();
- LayoutPoint point_in_root_frame = view->ContentsToFrame(
- view->ViewportToContents(LayoutPoint(point_in_viewport)));
+ LayoutPoint point_in_root_frame =
+ view->ViewportToFrame(LayoutPoint(point_in_viewport));
return HitTestResultForRootFramePos(point_in_root_frame);
}
@@ -3319,12 +3123,10 @@ void WebViewImpl::DidCommitLoad(bool is_new_navigation,
GetPage()->GetVisualViewport().MainFrameDidChangeSize();
// Make sure link highlight from previous page is cleared.
- link_highlights_.clear();
+ // TODO(pdr): Move this to Page::DidCommitLoad.
+ GetPage()->GetLinkHighlights().ResetForPageNavigation();
if (!MainFrameImpl())
return;
-
- if (WebFrameWidgetBase* widget = MainFrameImpl()->FrameWidgetImpl())
- widget->EndActiveFlingAnimation();
}
void WebViewImpl::ResizeAfterLayout() {
@@ -3434,12 +3236,14 @@ HitTestResult WebViewImpl::HitTestResultForRootFramePos(
const LayoutPoint& pos_in_root_frame) {
if (!page_->MainFrame()->IsLocalFrame())
return HitTestResult();
- LayoutPoint doc_point(
- page_->DeprecatedLocalMainFrame()->View()->RootFrameToContents(
+ HitTestLocation location(
+ page_->DeprecatedLocalMainFrame()->View()->ConvertFromRootFrame(
pos_in_root_frame));
HitTestResult result =
- page_->DeprecatedLocalMainFrame()->GetEventHandler().HitTestResultAtPoint(
- doc_point, HitTestRequest::kReadOnly | HitTestRequest::kActive);
+ page_->DeprecatedLocalMainFrame()
+ ->GetEventHandler()
+ .HitTestResultAtLocation(
+ location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
result.SetToShadowHostIfInRestrictedShadowRoot();
return result;
}
@@ -3611,26 +3415,14 @@ void WebViewImpl::ScheduleAnimationForWidget() {
client_->WidgetClient()->ScheduleAnimation();
}
-void WebViewImpl::AttachCompositorAnimationTimeline(
- CompositorAnimationTimeline* timeline) {
- if (animation_host_)
- animation_host_->AddTimeline(*timeline);
-}
-
-void WebViewImpl::DetachCompositorAnimationTimeline(
- CompositorAnimationTimeline* timeline) {
- if (animation_host_)
- animation_host_->RemoveTimeline(*timeline);
-}
-
void WebViewImpl::InitializeLayerTreeView() {
- if (client_) {
- layer_tree_view_ = client_->InitializeLayerTreeView();
+ if (WidgetClient()) {
+ layer_tree_view_ = WidgetClient()->InitializeLayerTreeView();
// TODO(dcheng): All WebViewImpls should have an associated LayerTreeView,
// but for various reasons, that's not the case...
page_->GetSettings().SetAcceleratedCompositingEnabled(layer_tree_view_);
if (layer_tree_view_) {
- if (layer_tree_view_->CompositorAnimationHost()) {
+ if (Platform::Current()->IsThreadedAnimationEnabled()) {
animation_host_ = std::make_unique<CompositorAnimationHost>(
layer_tree_view_->CompositorAnimationHost());
}
@@ -3648,11 +3440,6 @@ void WebViewImpl::InitializeLayerTreeView() {
// hit this code and then delete allowsBrokenNullLayerTreeView.
DCHECK(layer_tree_view_ || !client_ ||
client_->WidgetClient()->AllowsBrokenNullLayerTreeView());
-
- if (Platform::Current()->IsThreadedAnimationEnabled() && layer_tree_view_) {
- link_highlights_timeline_ = CompositorAnimationTimeline::Create();
- AttachCompositorAnimationTimeline(link_highlights_timeline_.get());
- }
}
void WebViewImpl::ApplyViewportDeltas(
@@ -3685,9 +3472,6 @@ void WebViewImpl::ApplyViewportDeltas(
}
elastic_overscroll_ += elastic_overscroll_delta;
-
- if (MainFrameImpl() && MainFrameImpl()->GetFrameView())
- MainFrameImpl()->GetFrameView()->DidUpdateElasticOverscroll();
}
void WebViewImpl::RecordWheelAndTouchScrollingCount(
@@ -3806,8 +3590,8 @@ LocalFrame* WebViewImpl::FocusedLocalFrameAvailableForIme() const {
return ime_accept_events_ ? FocusedLocalFrameInWidget() : nullptr;
}
-void WebViewImpl::FreezePage() {
- Scheduler()->SetPageFrozen(true);
+void WebViewImpl::SetPageFrozen(bool frozen) {
+ Scheduler()->SetPageFrozen(frozen);
}
void WebViewImpl::AddAutoplayFlags(int32_t value) {
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 58f8ff5cc82..9055bbe708a 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
@@ -37,7 +37,6 @@
#include "build/build_config.h"
#include "third_party/blink/public/common/manifest/web_display_mode.h"
#include "third_party/blink/public/platform/web_float_size.h"
-#include "third_party/blink/public/platform/web_gesture_curve_target.h"
#include "third_party/blink/public/platform/web_gesture_event.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/public/platform/web_input_event_result.h"
@@ -57,7 +56,6 @@
#include "third_party/blink/renderer/core/page/event_with_hit_test_results.h"
#include "third_party/blink/renderer/core/page/page_widget_delegate.h"
#include "third_party/blink/renderer/core/page/scoped_page_pauser.h"
-#include "third_party/blink/renderer/platform/animation/compositor_animation_timeline.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/graphics_layer.h"
@@ -79,7 +77,6 @@ class CompositorAnimationHost;
class DevToolsEmulator;
class Frame;
class FullscreenController;
-class LinkHighlightImpl;
class PageOverlay;
class PageScaleConstraintsSet;
class PaintLayerCompositor;
@@ -94,12 +91,15 @@ class WebLocalFrameImpl;
class CompositorMutatorImpl;
class WebRemoteFrame;
class WebSettingsImpl;
+class WebViewClient;
+class WebWidgetClient;
class CORE_EXPORT WebViewImpl final : public WebView,
public RefCounted<WebViewImpl>,
public PageWidgetEventHandler {
public:
static WebViewImpl* Create(WebViewClient*,
+ WebWidgetClient*,
mojom::PageVisibilityState,
WebViewImpl* opener);
static HashSet<WebViewImpl*>& AllInstances();
@@ -121,10 +121,9 @@ class CORE_EXPORT WebViewImpl final : public WebView,
void UpdateLifecycle(LifecycleUpdate requested_update) override;
void UpdateAllLifecyclePhasesAndCompositeForTesting() override;
void CompositeWithRasterForTesting() override;
- void Paint(WebCanvas*, const WebRect&) override;
-#if defined(OS_ANDROID)
- void PaintIgnoringCompositing(WebCanvas*, const WebRect&) override;
-#endif
+ void PaintContent(cc::PaintCanvas*, const WebRect&) override;
+ void PaintContentIgnoringCompositing(cc::PaintCanvas*,
+ const WebRect&) override;
void LayoutAndPaintAsync(base::OnceClosure callback) override;
void CompositeAndReadbackAsync(
base::OnceCallback<void(const SkBitmap&)> callback) override;
@@ -211,8 +210,6 @@ class CORE_EXPORT WebViewImpl final : public WebView,
void EnableAutoResizeMode(const WebSize& min_size,
const WebSize& max_size) override;
void DisableAutoResizeMode() override;
- void PerformMediaPlayerAction(const WebMediaPlayerAction&,
- const WebPoint& location) override;
void PerformPluginAction(const WebPluginAction&, const WebPoint&) override;
void AudioStateChanged(bool is_audio_playing) override;
void PausePageScheduledTasks(bool paused) override;
@@ -236,7 +233,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
void SetShowFPSCounter(bool) override;
void SetShowScrollBottleneckRects(bool) override;
void AcceptLanguagesChanged() override;
- void FreezePage() override;
+ void SetPageFrozen(bool frozen) override;
void DidUpdateFullscreenSize();
@@ -272,6 +269,9 @@ class CORE_EXPORT WebViewImpl final : public WebView,
Element* FocusedElement() const;
WebViewClient* Client() { return client_; }
+ // TODO(dcheng): This client should be acquirable from the MainFrameImpl
+ // in some cases? We need to know how to get it in all cases.
+ WebWidgetClient* WidgetClient() { return widget_client_; }
// Returns the page object associated with this view. This may be null when
// the page is shutting down, but will be valid at all other times.
@@ -343,9 +343,6 @@ class CORE_EXPORT WebViewImpl final : public WebView,
GraphicsLayer* RootGraphicsLayer();
void RegisterViewportLayersWithCompositor();
PaintLayerCompositor* Compositor() const;
- CompositorAnimationTimeline* LinkHighlightsTimeline() const {
- return link_highlights_timeline_.get();
- }
PageScheduler* Scheduler() const override;
void SetVisibilityState(mojom::PageVisibilityState, bool) override;
@@ -400,12 +397,6 @@ class CORE_EXPORT WebViewImpl final : public WebView,
bool HasHorizontalScrollbar();
bool HasVerticalScrollbar();
- // Exposed for tests.
- unsigned NumLinkHighlights() { return link_highlights_.size(); }
- LinkHighlightImpl* GetLinkHighlight(int i) {
- return link_highlights_[i].get();
- }
-
WebSettingsImpl* SettingsImpl();
// Returns the bounding box of the block type node touched by the WebPoint.
@@ -420,8 +411,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
return matches_heuristics_for_gpu_rasterization_;
}
- void UpdateBrowserControlsState(WebBrowserControlsState constraint,
- WebBrowserControlsState current,
+ void UpdateBrowserControlsState(cc::BrowserControlsState constraint,
+ cc::BrowserControlsState current,
bool animate) override;
BrowserControls& GetBrowserControls();
@@ -471,14 +462,12 @@ class CORE_EXPORT WebViewImpl final : public WebView,
DivScrollIntoEditablePreservePageScaleTest);
FRIEND_TEST_ALL_PREFIXES(WebFrameTest,
DivScrollIntoEditableTestZoomToLegibleScaleDisabled);
+ FRIEND_TEST_ALL_PREFIXES(WebFrameTest,
+ DivScrollIntoEditableTestWithDeviceScaleFactor);
void SetPageScaleFactorAndLocation(float, const FloatPoint&);
void PropagateZoomFactorToLocalFrameRoots(Frame*, float);
- void ScrollAndRescaleViewports(float scale_factor,
- const IntPoint& main_frame_origin,
- const FloatPoint& visual_viewport_origin);
-
float MaximumLegiblePageScale() const;
void RefreshPageScaleFactorAfterLayout();
IntSize ContentsSize() const;
@@ -501,7 +490,10 @@ class CORE_EXPORT WebViewImpl final : public WebView,
friend class WebViewFrameWidget;
friend class WTF::RefCounted<WebViewImpl>;
- WebViewImpl(WebViewClient*, mojom::PageVisibilityState, WebViewImpl* opener);
+ WebViewImpl(WebViewClient*,
+ WebWidgetClient*,
+ mojom::PageVisibilityState,
+ WebViewImpl* opener);
~WebViewImpl() override;
void HideSelectPopup();
@@ -535,9 +527,6 @@ class CORE_EXPORT WebViewImpl final : public WebView,
WebInputEventResult HandleKeyEvent(const WebKeyboardEvent&) override;
WebInputEventResult HandleCharEvent(const WebKeyboardEvent&) override;
- WebInputEventResult HandleSyntheticWheelFromTouchpadPinchEvent(
- const WebGestureEvent&);
-
void EnablePopupMouseWheelEventListener(WebLocalFrameImpl* local_root);
void DisablePopupMouseWheelEventListener();
@@ -548,8 +537,6 @@ class CORE_EXPORT WebViewImpl final : public WebView,
void SetRootGraphicsLayer(GraphicsLayer*);
void SetRootLayer(scoped_refptr<cc::Layer>);
- void AttachCompositorAnimationTimeline(CompositorAnimationTimeline*);
- void DetachCompositorAnimationTimeline(CompositorAnimationTimeline*);
LocalFrame* FocusedLocalFrameInWidget() const;
LocalFrame* FocusedLocalFrameAvailableForIme() const;
@@ -575,7 +562,8 @@ class CORE_EXPORT WebViewImpl final : public WebView,
IntPoint& scroll,
bool& need_animation);
- WebViewClient* client_; // Can be 0 (e.g. unittests, shared workers, etc.)
+ WebViewClient* client_; // Can be null (e.g. unittests, shared workers, etc.)
+ WebWidgetClient* widget_client_; // Can also be null.
Persistent<ChromeClient> chrome_client_;
@@ -660,8 +648,6 @@ class CORE_EXPORT WebViewImpl final : public WebView,
GraphicsLayer* visual_viewport_container_layer_;
bool matches_heuristics_for_gpu_rasterization_;
- Vector<std::unique_ptr<LinkHighlightImpl>> link_highlights_;
- std::unique_ptr<CompositorAnimationTimeline> link_highlights_timeline_;
std::unique_ptr<FullscreenController> fullscreen_controller_;
WebPoint last_tap_disambiguation_best_candidate_position_;
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 4aa77f1c7b7..c92036ebe57 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
@@ -35,6 +35,7 @@
#include <string>
#include "build/build_config.h"
+#include "cc/trees/layer_tree_host.h"
#include "gin/handle.h"
#include "gin/object_template_builder.h"
#include "gin/wrappable.h"
@@ -61,11 +62,11 @@
#include "third_party/blink/public/web/web_document.h"
#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_client.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_client.h"
#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"
@@ -104,10 +105,12 @@
#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/page/page_visibility_state.h"
#include "third_party/blink/renderer/core/page/print_context.h"
#include "third_party/blink/renderer/core/page/scoped_page_pauser.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_painter.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.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/platform/geometry/int_rect.h"
@@ -118,6 +121,7 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
#include "third_party/blink/renderer/platform/keyboard_codes.h"
#include "third_party/blink/renderer/platform/scroll/scroll_types.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/testing/wtf/scoped_mock_clock.h"
@@ -254,7 +258,11 @@ class WebViewTest : public testing::Test {
protected:
void SetViewportSize(const WebSize& size) {
- web_view_helper_.SetViewportSize(size);
+ content::LayerTreeView* layer_tree_view =
+ web_view_helper_.GetLayerTreeView();
+ layer_tree_view->SetViewportSizeAndScale(
+ static_cast<gfx::Size>(size), /*device_scale_factor=*/1.f,
+ layer_tree_view->layer_tree_host()->local_surface_id_from_parent());
}
std::string RegisterMockedHttpURLLoad(const std::string& file_name) {
@@ -465,8 +473,9 @@ TEST_F(WebViewTest, SetBaseBackgroundColorBeforeMainFrame) {
// Note: this test doesn't use WebViewHelper since it intentionally runs
// initialization code between WebView and WebLocalFrame creation.
FrameTestHelpers::TestWebViewClient web_view_client;
- WebViewImpl* web_view = static_cast<WebViewImpl*>(WebView::Create(
- &web_view_client, mojom::PageVisibilityState::kVisible, nullptr));
+ WebViewImpl* web_view = static_cast<WebViewImpl*>(
+ WebView::Create(&web_view_client, &web_view_client,
+ mojom::PageVisibilityState::kVisible, nullptr));
EXPECT_NE(SK_ColorBLUE, web_view->BackgroundColor());
// webView does not have a frame yet, but we should still be able to set the
// background color.
@@ -2265,18 +2274,15 @@ TEST_F(WebViewTest, BackForwardRestoreScroll) {
main_frame_local->Loader().GetDocumentLoader()->GetHistoryItem();
// Go back, then forward, then back again.
- main_frame_local->Loader().CommitNavigation(
- FrameLoadRequest(nullptr, item1->GenerateResourceRequest(
- mojom::FetchCacheMode::kDefault)),
- kFrameLoadTypeBackForward, item1.Get(), kHistorySameDocumentLoad);
- main_frame_local->Loader().CommitNavigation(
- FrameLoadRequest(nullptr, item2->GenerateResourceRequest(
- mojom::FetchCacheMode::kDefault)),
- kFrameLoadTypeBackForward, item2.Get(), kHistorySameDocumentLoad);
- main_frame_local->Loader().CommitNavigation(
- FrameLoadRequest(nullptr, item1->GenerateResourceRequest(
- mojom::FetchCacheMode::kDefault)),
- kFrameLoadTypeBackForward, item1.Get(), kHistorySameDocumentLoad);
+ main_frame_local->Loader().CommitSameDocumentNavigation(
+ item1->Url(), WebFrameLoadType::kBackForward, item1.Get(),
+ ClientRedirectPolicy::kNotClientRedirect, nullptr, false);
+ main_frame_local->Loader().CommitSameDocumentNavigation(
+ item2->Url(), WebFrameLoadType::kBackForward, item2.Get(),
+ ClientRedirectPolicy::kNotClientRedirect, nullptr, false);
+ main_frame_local->Loader().CommitSameDocumentNavigation(
+ item1->Url(), WebFrameLoadType::kBackForward, item1.Get(),
+ ClientRedirectPolicy::kNotClientRedirect, nullptr, false);
// Click a different anchor
main_frame_local->Loader().StartNavigation(FrameLoadRequest(
@@ -2287,14 +2293,12 @@ TEST_F(WebViewTest, BackForwardRestoreScroll) {
// Go back, then forward. The scroll position should be properly set on the
// forward navigation.
- main_frame_local->Loader().CommitNavigation(
- FrameLoadRequest(nullptr, item1->GenerateResourceRequest(
- mojom::FetchCacheMode::kDefault)),
- kFrameLoadTypeBackForward, item1.Get(), kHistorySameDocumentLoad);
- main_frame_local->Loader().CommitNavigation(
- FrameLoadRequest(nullptr, item3->GenerateResourceRequest(
- mojom::FetchCacheMode::kDefault)),
- kFrameLoadTypeBackForward, item3.Get(), kHistorySameDocumentLoad);
+ main_frame_local->Loader().CommitSameDocumentNavigation(
+ item1->Url(), WebFrameLoadType::kBackForward, item1.Get(),
+ ClientRedirectPolicy::kNotClientRedirect, nullptr, false);
+ main_frame_local->Loader().CommitSameDocumentNavigation(
+ item3->Url(), WebFrameLoadType::kBackForward, item3.Get(),
+ ClientRedirectPolicy::kNotClientRedirect, nullptr, false);
EXPECT_EQ(0, web_view_impl->MainFrameImpl()->GetScrollOffset().width);
EXPECT_GT(web_view_impl->MainFrameImpl()->GetScrollOffset().height, 2000);
}
@@ -2325,6 +2329,7 @@ TEST_F(WebViewTest, FullscreenResetScrollAndScaleFullscreenStyles) {
ASSERT_EQ(0, web_view_impl->MainFrameImpl()->GetScrollOffset().height);
ASSERT_EQ(0, web_view_impl->MainFrameImpl()
->GetFrameView()
+ ->LayoutViewport()
->MaximumScrollOffset()
.Height());
@@ -2365,6 +2370,7 @@ TEST_F(WebViewTest, FullscreenResetScrollAndScaleExitAndReenter) {
ASSERT_EQ(0, web_view_impl->MainFrameImpl()->GetScrollOffset().height);
ASSERT_EQ(0, web_view_impl->MainFrameImpl()
->GetFrameView()
+ ->LayoutViewport()
->MaximumScrollOffset()
.Height());
@@ -2380,6 +2386,7 @@ TEST_F(WebViewTest, FullscreenResetScrollAndScaleExitAndReenter) {
ASSERT_EQ(0, web_view_impl->MainFrameImpl()->GetScrollOffset().height);
ASSERT_EQ(0, web_view_impl->MainFrameImpl()
->GetFrameView()
+ ->LayoutViewport()
->MaximumScrollOffset()
.Height());
@@ -2477,7 +2484,7 @@ static void DragAndDropURL(WebViewImpl* web_view, const std::string& url) {
widget->DragTargetDragEnter(drag_data, client_point, screen_point,
kWebDragOperationCopy, 0);
widget->DragTargetDrop(drag_data, client_point, screen_point, 0);
- FrameTestHelpers::PumpPendingRequestsForFrameToLoad(web_view->MainFrame());
+ FrameTestHelpers::PumpPendingRequestsForFrameToLoad();
}
TEST_F(WebViewTest, DragDropURL) {
@@ -2524,8 +2531,7 @@ bool WebViewTest::TapElement(WebInputEvent::Type type, Element* element) {
web_view_helper_.GetWebView()
->MainFrameImpl()
->GetFrameView()
- ->ContentsToScreen(
- element->GetLayoutObject()->AbsoluteBoundingBoxRect())
+ ->FrameToScreen(element->GetLayoutObject()->AbsoluteBoundingBoxRect())
.Center());
WebGestureEvent event(type, WebInputEvent::kNoModifiers,
@@ -2585,8 +2591,8 @@ 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, mojom::PageVisibilityState::kVisible, nullptr));
+ WebViewImpl* web_view = static_cast<WebViewImpl*>(WebView::Create(
+ nullptr, nullptr, mojom::PageVisibilityState::kVisible, nullptr));
FrameTestHelpers::TestWebFrameClient web_frame_client;
FrameTestHelpers::TestWebWidgetClient web_widget_client;
WebLocalFrame* local_frame = WebLocalFrame::CreateMainFrame(
@@ -3381,7 +3387,7 @@ TEST_F(WebViewTest, FinishComposingTextDoesntTriggerAutofillTextChange) {
EXPECT_EQ(0, info.composition_start);
EXPECT_EQ((int)composition_text.length(), info.composition_end);
- form->SetAutofilled(true);
+ form->SetAutofillState(blink::WebAutofillState::kAutofilled);
client.ClearChangeCounts();
active_input_method_controller->FinishComposingText(
@@ -4743,7 +4749,7 @@ TEST_F(WebViewTest, ViewportOverrideAdaptsToScaleAndScroll) {
// Initial transform takes current page scale and scroll position into
// account.
web_view_impl->SetPageScaleFactor(1.5f);
- frame_view->LayoutViewportScrollableArea()->SetScrollOffset(
+ frame_view->LayoutViewport()->SetScrollOffset(
ScrollOffset(100, 150), kProgrammaticScroll, kScrollBehaviorInstant);
dev_tools_emulator->ForceViewport(WebFloatPoint(50, 55), 2.f);
expected_matrix.MakeIdentity()
@@ -4758,7 +4764,7 @@ TEST_F(WebViewTest, ViewportOverrideAdaptsToScaleAndScroll) {
*dev_tools_emulator->VisibleContentRectForPainting());
// Transform adapts to scroll changes.
- frame_view->LayoutViewportScrollableArea()->SetScrollOffset(
+ frame_view->LayoutViewport()->SetScrollOffset(
ScrollOffset(50, 55), kProgrammaticScroll, kScrollBehaviorInstant);
expected_matrix.MakeIdentity()
.Scale(2.f)
@@ -4920,8 +4926,7 @@ TEST_F(WebViewTest, DeviceEmulationResetScrollbars) {
WebLocalFrameImpl* frame = web_view->MainFrameImpl();
auto* frame_view = frame->GetFrameView();
EXPECT_FALSE(frame_view->VisualViewportSuppliesScrollbars());
- EXPECT_NE(nullptr,
- frame_view->LayoutViewportScrollableArea()->VerticalScrollbar());
+ EXPECT_NE(nullptr, frame_view->LayoutViewport()->VerticalScrollbar());
WebDeviceEmulationParams params;
params.screen_position = WebDeviceEmulationParams::kMobile;
@@ -4932,21 +4937,20 @@ TEST_F(WebViewTest, DeviceEmulationResetScrollbars) {
// The visual viewport should now proivde the scrollbars instead of the view.
EXPECT_TRUE(frame_view->VisualViewportSuppliesScrollbars());
- EXPECT_EQ(nullptr, frame_view->VerticalScrollbar());
+ EXPECT_EQ(nullptr, frame_view->LayoutViewport()->VerticalScrollbar());
web_view->DisableDeviceEmulation();
// The view should once again provide the scrollbars.
EXPECT_FALSE(frame_view->VisualViewportSuppliesScrollbars());
- EXPECT_NE(nullptr,
- frame_view->LayoutViewportScrollableArea()->VerticalScrollbar());
+ EXPECT_NE(nullptr, frame_view->LayoutViewport()->VerticalScrollbar());
}
TEST_F(WebViewTest, SetZoomLevelWhilePluginFocused) {
class PluginCreatingWebFrameClient
: public FrameTestHelpers::TestWebFrameClient {
public:
- // WebFrameClient overrides:
+ // WebLocalFrameClient overrides:
WebPlugin* CreatePlugin(const WebPluginParams& params) override {
return new FakeWebPlugin(params);
}
@@ -4997,7 +5001,7 @@ TEST_F(WebViewTest, DetachPluginInLayout) {
class PluginCreatingWebFrameClient
: public FrameTestHelpers::TestWebFrameClient {
public:
- // WebFrameClient overrides:
+ // WebLocalFrameClient overrides:
WebPlugin* CreatePlugin(const WebPluginParams& params) override {
return new ScriptInDestroyPlugin(Frame(), params);
}
@@ -5093,6 +5097,245 @@ TEST_F(WebViewTest, FirstInputDelayReported) {
.InMillisecondsF());
}
+// Check that longest input delay is correctly reported to the document.
+TEST_F(WebViewTest, LongestInputDelayReported) {
+ WebViewImpl* web_view = web_view_helper_.Initialize();
+ WebURL base_url = URLTestHelpers::ToKURL("http://example.com/");
+ FrameTestHelpers::LoadHTMLString(web_view->MainFrameImpl(),
+ "<html><body></body></html>", base_url);
+
+ LocalFrame* main_frame = web_view->MainFrameImpl()->GetFrame();
+ ASSERT_NE(nullptr, main_frame);
+
+ Document* document = main_frame->GetDocument();
+ ASSERT_NE(nullptr, document);
+
+ WTF::ScopedMockClock clock;
+ clock.Advance(TimeDelta::FromMilliseconds(70));
+
+ InteractiveDetector* interactive_detector(
+ InteractiveDetector::From(*document));
+ ASSERT_NE(nullptr, interactive_detector);
+
+ EXPECT_TRUE(interactive_detector->GetLongestInputDelay().is_zero());
+
+ WebKeyboardEvent key_event1(WebInputEvent::kRawKeyDown,
+ WebInputEvent::kNoModifiers,
+ WebInputEvent::GetStaticTimeStampForTests());
+ key_event1.dom_key = Platform::Current()->DomKeyEnumFromString(" ");
+ key_event1.windows_key_code = VKEY_SPACE;
+ key_event1.SetTimeStamp(CurrentTimeTicks());
+ clock.Advance(TimeDelta::FromMilliseconds(50));
+ web_view->HandleInputEvent(WebCoalescedInputEvent(key_event1));
+
+ TimeTicks longest_input_timestamp = CurrentTimeTicks();
+
+ WebKeyboardEvent key_event2(WebInputEvent::kRawKeyDown,
+ WebInputEvent::kNoModifiers,
+ WebInputEvent::GetStaticTimeStampForTests());
+ key_event2.dom_key = Platform::Current()->DomKeyEnumFromString(" ");
+ key_event2.windows_key_code = VKEY_SPACE;
+ key_event2.SetTimeStamp(longest_input_timestamp);
+ clock.Advance(TimeDelta::FromMilliseconds(100));
+ web_view->HandleInputEvent(WebCoalescedInputEvent(key_event2));
+
+ WebKeyboardEvent key_event3(WebInputEvent::kRawKeyDown,
+ WebInputEvent::kNoModifiers,
+ WebInputEvent::GetStaticTimeStampForTests());
+ key_event3.dom_key = Platform::Current()->DomKeyEnumFromString(" ");
+ key_event3.windows_key_code = VKEY_SPACE;
+ key_event3.SetTimeStamp(CurrentTimeTicks());
+ clock.Advance(TimeDelta::FromMilliseconds(70));
+ web_view->HandleInputEvent(WebCoalescedInputEvent(key_event3));
+
+ EXPECT_NEAR(100,
+ interactive_detector->GetLongestInputDelay().InMillisecondsF(),
+ 0.01);
+ EXPECT_EQ(longest_input_timestamp,
+ interactive_detector->GetLongestInputTimestamp());
+}
+
+TEST_F(WebViewTest, InputDelayReported) {
+ WTF::ScopedMockClock clock;
+ clock.Advance(TimeDelta::FromMilliseconds(50));
+
+ WebViewImpl* web_view = web_view_helper_.Initialize();
+
+ WebURL base_url = URLTestHelpers::ToKURL("http://example.com/");
+ FrameTestHelpers::LoadHTMLString(web_view->MainFrameImpl(),
+ "<html><body></body></html>", base_url);
+
+ clock.Advance(TimeDelta::FromMilliseconds(70));
+
+ HistogramTester histogram_tester;
+ WebKeyboardEvent key_event1(WebInputEvent::kRawKeyDown,
+ WebInputEvent::kNoModifiers,
+ WebInputEvent::GetStaticTimeStampForTests());
+ key_event1.dom_key = Platform::Current()->DomKeyEnumFromString(" ");
+ key_event1.windows_key_code = VKEY_SPACE;
+ key_event1.SetTimeStamp(CurrentTimeTicks());
+ clock.Advance(TimeDelta::FromMilliseconds(50));
+ web_view->HandleInputEvent(WebCoalescedInputEvent(key_event1));
+
+ WebKeyboardEvent key_event2(WebInputEvent::kRawKeyDown,
+ WebInputEvent::kNoModifiers,
+ WebInputEvent::GetStaticTimeStampForTests());
+ key_event2.dom_key = Platform::Current()->DomKeyEnumFromString(" ");
+ key_event2.windows_key_code = VKEY_SPACE;
+ key_event2.SetTimeStamp(CurrentTimeTicks());
+ clock.Advance(TimeDelta::FromMilliseconds(50));
+ web_view->HandleInputEvent(WebCoalescedInputEvent(key_event2));
+
+ WebKeyboardEvent key_event3(WebInputEvent::kRawKeyDown,
+ WebInputEvent::kNoModifiers,
+ WebInputEvent::GetStaticTimeStampForTests());
+ key_event3.dom_key = Platform::Current()->DomKeyEnumFromString(" ");
+ key_event3.windows_key_code = VKEY_SPACE;
+ key_event3.SetTimeStamp(CurrentTimeTicks());
+ clock.Advance(TimeDelta::FromMilliseconds(70));
+ web_view->HandleInputEvent(WebCoalescedInputEvent(key_event3));
+
+ histogram_tester.ExpectTotalCount("PageLoad.InteractiveTiming.InputDelay", 3);
+ histogram_tester.ExpectBucketCount("PageLoad.InteractiveTiming.InputDelay", 50, 2);
+ histogram_tester.ExpectBucketCount("PageLoad.InteractiveTiming.InputDelay", 70, 1);
+
+ histogram_tester.ExpectTotalCount("PageLoad.InteractiveTiming.InputTimestamp", 3);
+ histogram_tester.ExpectBucketCount("PageLoad.InteractiveTiming.InputTimestamp", 70, 1);
+ histogram_tester.ExpectBucketCount("PageLoad.InteractiveTiming.InputTimestamp", 120, 1);
+ histogram_tester.ExpectBucketCount("PageLoad.InteractiveTiming.InputTimestamp", 170, 1);
+}
+
+// Tests that if the page was backgrounded while an input event was queued,
+// we do not count its delay to calculate longest input delay.
+TEST_F(WebViewTest, LongestInputDelayPageBackgroundedDuringQueuing) {
+ WebViewImpl* web_view = web_view_helper_.Initialize();
+ WebURL base_url = URLTestHelpers::ToKURL("http://example.com/");
+ FrameTestHelpers::LoadHTMLString(web_view->MainFrameImpl(),
+ "<html><body></body></html>", base_url);
+
+ LocalFrame* main_frame = web_view->MainFrameImpl()->GetFrame();
+ ASSERT_NE(nullptr, main_frame);
+
+ Document* document = main_frame->GetDocument();
+ ASSERT_NE(nullptr, document);
+
+ WTF::ScopedMockClock clock;
+ clock.Advance(TimeDelta::FromMilliseconds(70));
+
+ InteractiveDetector* interactive_detector(
+ InteractiveDetector::From(*document));
+ ASSERT_NE(nullptr, interactive_detector);
+
+ EXPECT_TRUE(interactive_detector->GetLongestInputDelay().is_zero());
+
+ WebKeyboardEvent key_event1(WebInputEvent::kRawKeyDown,
+ WebInputEvent::kNoModifiers,
+ WebInputEvent::GetStaticTimeStampForTests());
+ key_event1.dom_key = Platform::Current()->DomKeyEnumFromString(" ");
+ key_event1.windows_key_code = VKEY_SPACE;
+ TimeTicks key_event1_time = CurrentTimeTicks();
+ key_event1.SetTimeStamp(key_event1_time);
+ clock.Advance(TimeDelta::FromMilliseconds(50));
+ web_view->HandleInputEvent(WebCoalescedInputEvent(key_event1));
+
+ WebKeyboardEvent key_event2(WebInputEvent::kRawKeyDown,
+ WebInputEvent::kNoModifiers,
+ WebInputEvent::GetStaticTimeStampForTests());
+ key_event2.dom_key = Platform::Current()->DomKeyEnumFromString(" ");
+ key_event2.windows_key_code = VKEY_SPACE;
+ key_event2.SetTimeStamp(CurrentTimeTicks());
+ clock.Advance(TimeDelta::FromMilliseconds(100));
+ web_view->SetVisibilityState(mojom::PageVisibilityState::kHidden, false);
+ clock.Advance(TimeDelta::FromMilliseconds(100));
+ web_view->SetVisibilityState(mojom::PageVisibilityState::kVisible, false);
+ clock.Advance(TimeDelta::FromMilliseconds(100));
+ // Total input delay is >300ms.
+ web_view->HandleInputEvent(WebCoalescedInputEvent(key_event2));
+
+ EXPECT_NEAR(
+ 50, interactive_detector->GetLongestInputDelay().InMillisecondsF(), 0.01);
+ EXPECT_EQ(key_event1_time, interactive_detector->GetLongestInputTimestamp());
+}
+
+// Tests that if the page was backgrounded at navigation start and an input
+// event was queued before it was foregrounded, we do not count its delay to
+// calculate longest input delay.
+TEST_F(WebViewTest, LongestInputDelayPageBackgroundedAtNavStart) {
+ WebViewImpl* web_view = web_view_helper_.Initialize();
+ web_view->SetVisibilityState(mojom::PageVisibilityState::kHidden, false);
+ WebURL base_url = URLTestHelpers::ToKURL("http://example.com/");
+ FrameTestHelpers::LoadHTMLString(web_view->MainFrameImpl(),
+ "<html><body></body></html>", base_url);
+
+ LocalFrame* main_frame = web_view->MainFrameImpl()->GetFrame();
+ ASSERT_NE(nullptr, main_frame);
+
+ Document* document = main_frame->GetDocument();
+ ASSERT_NE(nullptr, document);
+
+ WTF::ScopedMockClock clock;
+ clock.Advance(TimeDelta::FromMilliseconds(70));
+
+ InteractiveDetector* interactive_detector(
+ InteractiveDetector::From(*document));
+ ASSERT_NE(nullptr, interactive_detector);
+
+ WebKeyboardEvent key_event(WebInputEvent::kRawKeyDown,
+ WebInputEvent::kNoModifiers,
+ WebInputEvent::GetStaticTimeStampForTests());
+ key_event.dom_key = Platform::Current()->DomKeyEnumFromString(" ");
+ key_event.windows_key_code = VKEY_SPACE;
+ key_event.SetTimeStamp(CurrentTimeTicks());
+ clock.Advance(TimeDelta::FromMilliseconds(100));
+ web_view->SetVisibilityState(mojom::PageVisibilityState::kVisible, false);
+ web_view->HandleInputEvent(WebCoalescedInputEvent(key_event));
+
+ EXPECT_TRUE(interactive_detector->GetLongestInputDelay().is_zero());
+}
+
+// Tests page backgrounding outside of input queuing time does not affect
+// longest input delay.
+TEST_F(WebViewTest, LongestInputDelayPageBackgroundedNotDuringQueuing) {
+ WebViewImpl* web_view = web_view_helper_.Initialize();
+ WebURL base_url = URLTestHelpers::ToKURL("http://example.com/");
+ FrameTestHelpers::LoadHTMLString(web_view->MainFrameImpl(),
+ "<html><body></body></html>", base_url);
+
+ LocalFrame* main_frame = web_view->MainFrameImpl()->GetFrame();
+ ASSERT_NE(nullptr, main_frame);
+
+ Document* document = main_frame->GetDocument();
+ ASSERT_NE(nullptr, document);
+
+ WTF::ScopedMockClock clock;
+ clock.Advance(TimeDelta::FromMilliseconds(70));
+
+ InteractiveDetector* interactive_detector(
+ InteractiveDetector::From(*document));
+ ASSERT_NE(nullptr, interactive_detector);
+
+ EXPECT_TRUE(interactive_detector->GetLongestInputDelay().is_zero());
+
+ web_view->SetVisibilityState(mojom::PageVisibilityState::kHidden, false);
+ clock.Advance(TimeDelta::FromMilliseconds(100));
+ web_view->SetVisibilityState(mojom::PageVisibilityState::kVisible, false);
+ clock.Advance(TimeDelta::FromMilliseconds(1));
+
+ WebKeyboardEvent key_event(WebInputEvent::kRawKeyDown,
+ WebInputEvent::kNoModifiers,
+ WebInputEvent::GetStaticTimeStampForTests());
+ key_event.dom_key = Platform::Current()->DomKeyEnumFromString(" ");
+ key_event.windows_key_code = VKEY_SPACE;
+ TimeTicks key_event_time = CurrentTimeTicks();
+ key_event.SetTimeStamp(key_event_time);
+ clock.Advance(TimeDelta::FromMilliseconds(50));
+ web_view->HandleInputEvent(WebCoalescedInputEvent(key_event));
+
+ EXPECT_NEAR(
+ 50, interactive_detector->GetLongestInputDelay().InMillisecondsF(), 0.01);
+ EXPECT_EQ(key_event_time, interactive_detector->GetLongestInputTimestamp());
+}
+
// Check that first input delay is correctly reported to the document when the
// first input is a pointer down event, and we receive a pointer up event.
TEST_F(WebViewTest, PointerDownUpFirstInputDelay) {
@@ -5185,31 +5428,34 @@ TEST_F(WebViewTest, PointerDownCancelFirstInputDelay) {
EXPECT_TRUE(interactive_detector->GetFirstInputTimestamp().is_null());
}
-// Check that the input delay is correctly reported to the document.
-TEST_F(WebViewTest, FirstInputDelayExcludesProcessingTime) {
- // We need a way for JS to advance the mock clock. Hook into console.log, so
- // that logging advances the clock by 6 seconds.
- class MockClockAdvancingWebFrameClient
- : public FrameTestHelpers::TestWebFrameClient {
- public:
- MockClockAdvancingWebFrameClient(WTF::ScopedMockClock* mock_clock)
- : mock_clock_(mock_clock) {}
- // WebFrameClient overrides:
- void DidAddMessageToConsole(const WebConsoleMessage& message,
- const WebString& source_name,
- unsigned source_line,
- const WebString& stack_trace) override {
- mock_clock_->Advance(TimeDelta::FromMilliseconds(6000));
- }
+// We need a way for JS to advance the mock clock. Hook into console.log, so
+// that logging advances the clock by |event_handling_delay| seconds.
+class MockClockAdvancingWebFrameClient
+ : public FrameTestHelpers::TestWebFrameClient {
+ public:
+ MockClockAdvancingWebFrameClient(WTF::ScopedMockClock* mock_clock,
+ TimeDelta event_handling_delay)
+ : mock_clock_(mock_clock), event_handling_delay_(event_handling_delay) {}
+ // WebLocalFrameClient overrides:
+ void DidAddMessageToConsole(const WebConsoleMessage& message,
+ const WebString& source_name,
+ unsigned source_line,
+ const WebString& stack_trace) override {
+ mock_clock_->Advance(event_handling_delay_);
+ }
- private:
- WTF::ScopedMockClock* mock_clock_;
- };
+ private:
+ WTF::ScopedMockClock* mock_clock_;
+ TimeDelta event_handling_delay_;
+};
+// Check that the input delay is correctly reported to the document.
+TEST_F(WebViewTest, FirstInputDelayExcludesProcessingTime) {
WTF::ScopedMockClock clock;
// Page load timing logic depends on the time not being zero.
clock.Advance(TimeDelta::FromMilliseconds(1));
- MockClockAdvancingWebFrameClient frame_client(&clock);
+ MockClockAdvancingWebFrameClient frame_client(
+ &clock, TimeDelta::FromMilliseconds(6000));
WebViewImpl* web_view = web_view_helper_.Initialize(&frame_client);
WebURL base_url = URLTestHelpers::ToKURL("http://example.com/");
FrameTestHelpers::LoadHTMLString(web_view->MainFrameImpl(),
@@ -5248,4 +5494,48 @@ TEST_F(WebViewTest, FirstInputDelayExcludesProcessingTime) {
web_view_helper_.Reset(); // Remove dependency on locally scoped client.
}
+// Check that the longest input delay is correctly reported to the document.
+TEST_F(WebViewTest, LongestInputDelayExcludesProcessingTime) {
+ WTF::ScopedMockClock clock;
+ // Page load timing logic depends on the time not being zero.
+ clock.Advance(TimeDelta::FromMilliseconds(1));
+ MockClockAdvancingWebFrameClient frame_client(
+ &clock, TimeDelta::FromMilliseconds(6000));
+ WebViewImpl* web_view = web_view_helper_.Initialize(&frame_client);
+ WebURL base_url = URLTestHelpers::ToKURL("http://example.com/");
+ FrameTestHelpers::LoadHTMLString(web_view->MainFrameImpl(),
+ "<html><body></body></html>", base_url);
+
+ LocalFrame* main_frame = web_view->MainFrameImpl()->GetFrame();
+ ASSERT_NE(nullptr, main_frame);
+
+ Document* document = main_frame->GetDocument();
+ ASSERT_NE(nullptr, document);
+
+ WebLocalFrame* frame = web_view_helper_.LocalMainFrame();
+ // console.log will advance the mock clock.
+ frame->ExecuteScript(
+ WebScriptSource("document.addEventListener('keydown', "
+ "() => {console.log('advancing timer');})"));
+
+ InteractiveDetector* interactive_detector(
+ InteractiveDetector::From(*document));
+ ASSERT_NE(nullptr, interactive_detector);
+
+ WebKeyboardEvent key_event(WebInputEvent::kRawKeyDown,
+ WebInputEvent::kNoModifiers,
+ WebInputEvent::GetStaticTimeStampForTests());
+ key_event.dom_key = Platform::Current()->DomKeyEnumFromString(" ");
+ key_event.windows_key_code = VKEY_SPACE;
+ key_event.SetTimeStamp(CurrentTimeTicks());
+
+ clock.Advance(TimeDelta::FromMilliseconds(5000));
+
+ web_view->HandleInputEvent(WebCoalescedInputEvent(key_event));
+
+ TimeDelta longest_input_delay = interactive_detector->GetLongestInputDelay();
+ EXPECT_EQ(5000, longest_input_delay.InMillisecondsF());
+
+ web_view_helper_.Reset(); // Remove dependency on locally scoped client.
+}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/exported/worker_shadow_page.cc b/chromium/third_party/blink/renderer/core/exported/worker_shadow_page.cc
index a630ff1210d..bee5e5d485d 100644
--- a/chromium/third_party/blink/renderer/core/exported/worker_shadow_page.cc
+++ b/chromium/third_party/blink/renderer/core/exported/worker_shadow_page.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_referrer_policy.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
@@ -15,17 +16,30 @@
namespace blink {
-WorkerShadowPage::WorkerShadowPage(Client* client)
+namespace {
+
+constexpr char kDoNotTrackHeader[] = "DNT";
+
+} // namespace
+
+WorkerShadowPage::WorkerShadowPage(
+ Client* client,
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory,
+ PrivacyPreferences preferences)
: client_(client),
web_view_(WebViewImpl::Create(nullptr,
+ nullptr,
mojom::PageVisibilityState::kVisible,
nullptr)),
- main_frame_(WebLocalFrameImpl::CreateMainFrame(web_view_,
- this,
- nullptr,
- nullptr,
- g_empty_atom,
- WebSandboxFlags::kNone)) {
+ main_frame_(
+ WebLocalFrameImpl::CreateMainFrame(web_view_,
+ this,
+ nullptr /* interface_registry */,
+ nullptr /* opener */,
+ g_empty_atom,
+ WebSandboxFlags::kNone)),
+ loader_factory_(std::move(loader_factory)),
+ preferences_(std::move(preferences)) {
DCHECK(IsMainThread());
// TODO(http://crbug.com/363843): This needs to find a better way to
@@ -87,6 +101,8 @@ WorkerShadowPage::CreateApplicationCacheHost(
std::unique_ptr<blink::WebURLLoaderFactory>
WorkerShadowPage::CreateURLLoaderFactory() {
DCHECK(IsMainThread());
+ if (loader_factory_)
+ return Platform::Current()->WrapSharedURLLoaderFactory(loader_factory_);
return Platform::Current()->CreateDefaultURLLoaderFactory();
}
@@ -102,6 +118,15 @@ WorkerShadowPage::CreateWebSocketHandshakeThrottle() {
return Platform::Current()->CreateWebSocketHandshakeThrottle();
}
+void WorkerShadowPage::WillSendRequest(WebURLRequest& request) {
+ if (preferences_.enable_do_not_track) {
+ request.SetHTTPHeaderField(WebString::FromUTF8(kDoNotTrackHeader), "1");
+ }
+ if (!preferences_.enable_referrers) {
+ request.SetHTTPReferrer(WebString(), kWebReferrerPolicyDefault);
+ }
+}
+
bool WorkerShadowPage::WasInitialized() const {
return state_ == State::kInitialized;
}
diff --git a/chromium/third_party/blink/renderer/core/exported/worker_shadow_page.h b/chromium/third_party/blink/renderer/core/exported/worker_shadow_page.h
index 4771b864fd0..cf252214cef 100644
--- a/chromium/third_party/blink/renderer/core/exported/worker_shadow_page.h
+++ b/chromium/third_party/blink/renderer/core/exported/worker_shadow_page.h
@@ -5,12 +5,18 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WORKER_SHADOW_PAGE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EXPORTED_WORKER_SHADOW_PAGE_H_
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "third_party/blink/public/common/privacy_preferences.h"
#include "third_party/blink/public/web/web_document_loader.h"
-#include "third_party/blink/public/web/web_frame_client.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_view.h"
#include "third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+namespace network {
+class SharedURLLoaderFactory;
+}
+
namespace blink {
class ContentSecurityPolicy;
@@ -31,7 +37,7 @@ class WebSettings;
// core/exported are gone (now depending on core/exported/WebViewImpl.h in
// *.cpp).
// TODO(kinuko): Make this go away (https://crbug.com/538751).
-class CORE_EXPORT WorkerShadowPage : public WebFrameClient {
+class CORE_EXPORT WorkerShadowPage : public WebLocalFrameClient {
public:
class CORE_EXPORT Client : public WebDevToolsAgentImpl::WorkerClient {
public:
@@ -48,26 +54,33 @@ class CORE_EXPORT WorkerShadowPage : public WebFrameClient {
virtual const base::UnguessableToken& GetDevToolsWorkerToken() = 0;
};
- explicit WorkerShadowPage(Client*);
+ // If |loader_factory| is non-null, the shadow page will use it when making
+ // requests.
+ WorkerShadowPage(
+ Client* client,
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory,
+ PrivacyPreferences preferences);
~WorkerShadowPage() override;
- // Calls Client::OnShadowPageInitialized() when complete.
+ // Initializes this instance and calls Client::OnShadowPageInitialized() when
+ // complete.
void Initialize(const KURL& script_url);
void SetContentSecurityPolicyAndReferrerPolicy(ContentSecurityPolicy*,
String referrer_policy);
- // WebFrameClient overrides.
+ // WebLocalFrameClient overrides.
std::unique_ptr<WebApplicationCacheHost> CreateApplicationCacheHost(
WebApplicationCacheHostClient*) override;
- // Note: usually WebFrameClient implementations override WebFrameClient to
- // call Close() on the corresponding WebLocalFrame. Shadow pages are set up a
- // bit differently and clear the WebFrameClient pointer before shutting down,
- // so the shadow page must also manually call Close() on the corresponding
- // frame and its widget.
+ // Note: usually WebLocalFrameClient implementations override
+ // WebLocalFrameClient to call Close() on the corresponding WebLocalFrame.
+ // Shadow pages are set up a bit differently and clear the WebLocalFrameClient
+ // pointer before shutting down, so the shadow page must also manually call
+ // Close() on the corresponding frame and its widget.
void DidFinishDocumentLoad() override;
std::unique_ptr<blink::WebURLLoaderFactory> CreateURLLoaderFactory() override;
base::UnguessableToken GetDevToolsFrameToken() override;
+ void WillSendRequest(WebURLRequest&) override;
// TODO(nhiroki): Remove this once the off-main-thread WebSocket is enabled by
// default (https://crbug.com/825740).
@@ -90,6 +103,11 @@ class CORE_EXPORT WorkerShadowPage : public WebFrameClient {
Client* client_;
WebView* web_view_;
Persistent<WebLocalFrameImpl> main_frame_;
+ scoped_refptr<network::SharedURLLoaderFactory> loader_factory_;
+
+ // TODO(crbug.com/862854): Update the values when the browser process changes
+ // the preferences.
+ const PrivacyPreferences preferences_;
State state_ = State::kUninitialized;
};
diff --git a/chromium/third_party/blink/renderer/core/fetch/BUILD.gn b/chromium/third_party/blink/renderer/core/fetch/BUILD.gn
index b698b777d73..cf99b45faaa 100644
--- a/chromium/third_party/blink/renderer/core/fetch/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/fetch/BUILD.gn
@@ -38,8 +38,6 @@ blink_core_sources("fetch") {
"readable_stream_bytes_consumer.h",
"request.cc",
"request.h",
- "request_init.cc",
- "request_init.h",
"response.cc",
"response.h",
]
diff --git a/chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer.cc b/chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer.cc
index bfa9f026de5..17a17f5b0a5 100644
--- a/chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer.cc
@@ -4,132 +4,52 @@
#include "third_party/blink/renderer/core/fetch/blob_bytes_consumer.h"
-#include "third_party/blink/renderer/core/fetch/bytes_consumer_for_data_consumer_handle.h"
-#include "third_party/blink/renderer/core/loader/threadable_loader.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/fetch/form_data_bytes_consumer.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
-#include "third_party/blink/renderer/platform/blob/blob_registry.h"
-#include "third_party/blink/renderer/platform/blob/blob_url.h"
-#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.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/weborigin/security_origin.h"
namespace blink {
BlobBytesConsumer::BlobBytesConsumer(
ExecutionContext* execution_context,
- scoped_refptr<BlobDataHandle> blob_data_handle,
- ThreadableLoader* loader)
- : ContextLifecycleObserver(execution_context),
- blob_data_handle_(std::move(blob_data_handle)),
- loader_(loader) {
- if (!blob_data_handle_) {
- // Note that |m_loader| is non-null only in tests.
- if (loader_) {
- loader_->Cancel();
- loader_ = nullptr;
- }
- state_ = PublicState::kClosed;
- }
-}
-
-BlobBytesConsumer::BlobBytesConsumer(
- ExecutionContext* execution_context,
scoped_refptr<BlobDataHandle> blob_data_handle)
- : BlobBytesConsumer(execution_context,
- std::move(blob_data_handle),
- nullptr) {}
+ : execution_context_(execution_context),
+ blob_data_handle_(std::move(blob_data_handle)) {}
BlobBytesConsumer::~BlobBytesConsumer() {
- if (!blob_url_.IsEmpty())
- BlobRegistry::RevokePublicBlobURL(blob_url_);
}
BytesConsumer::Result BlobBytesConsumer::BeginRead(const char** buffer,
size_t* available) {
- *buffer = nullptr;
- *available = 0;
-
- if (state_ == PublicState::kClosed) {
- // It's possible that |cancel| has been called before the first
- // |beginRead| call. That's why we need to check this condition
- // before checking |isClean()|.
- return Result::kDone;
- }
-
- if (IsClean()) {
- DCHECK(blob_url_.IsEmpty());
- blob_url_ =
- BlobURL::CreatePublicURL(GetExecutionContext()->GetSecurityOrigin());
- if (blob_url_.IsEmpty()) {
- GetError();
- } else {
- BlobRegistry::RegisterPublicBlobURL(
- GetExecutionContext()->GetMutableSecurityOrigin(), blob_url_,
- blob_data_handle_);
-
- // m_loader is non-null only in tests.
- if (!loader_)
- loader_ = CreateLoader();
-
- ResourceRequest request(blob_url_);
- request.SetRequestContext(WebURLRequest::kRequestContextInternal);
- request.SetFetchRequestMode(
- network::mojom::FetchRequestMode::kSameOrigin);
- request.SetFetchCredentialsMode(
- network::mojom::FetchCredentialsMode::kOmit);
- request.SetUseStreamOnResponse(true);
- // We intentionally skip
- // 'setExternalRequestStateFromRequestorAddressSpace', as 'blob:'
- // can never be external.
- loader_->Start(request);
- }
+ if (!nested_consumer_) {
+ if (!blob_data_handle_)
+ return Result::kDone;
+
+ scoped_refptr<EncodedFormData> form_data = EncodedFormData::Create();
+ form_data->AppendDataPipe(base::MakeRefCounted<WrappedDataPipeGetter>(
+ blob_data_handle_->AsDataPipeGetter()));
+ nested_consumer_ =
+ new FormDataBytesConsumer(execution_context_, std::move(form_data));
+ if (client_)
+ nested_consumer_->SetClient(client_);
blob_data_handle_ = nullptr;
+ client_ = nullptr;
}
- DCHECK_NE(state_, PublicState::kClosed);
-
- if (state_ == PublicState::kErrored)
- return Result::kError;
-
- if (!body_) {
- // The response has not arrived.
- return Result::kShouldWait;
- }
-
- auto result = body_->BeginRead(buffer, available);
- switch (result) {
- case Result::kOk:
- case Result::kShouldWait:
- break;
- case Result::kDone:
- has_seen_end_of_data_ = true;
- if (has_finished_loading_)
- Close();
- return state_ == PublicState::kClosed ? Result::kDone
- : Result::kShouldWait;
- case Result::kError:
- GetError();
- break;
- }
- return result;
+ return nested_consumer_->BeginRead(buffer, available);
}
BytesConsumer::Result BlobBytesConsumer::EndRead(size_t read) {
- DCHECK(body_);
- return body_->EndRead(read);
+ DCHECK(nested_consumer_);
+ return nested_consumer_->EndRead(read);
}
scoped_refptr<BlobDataHandle> BlobBytesConsumer::DrainAsBlobDataHandle(
BlobSizePolicy policy) {
- if (!IsClean())
+ if (!blob_data_handle_)
return nullptr;
- DCHECK(blob_data_handle_);
if (policy == BlobSizePolicy::kDisallowBlobWithInvalidSize &&
blob_data_handle_->size() == UINT64_MAX)
return nullptr;
- Close();
return std::move(blob_data_handle_);
}
@@ -146,172 +66,43 @@ scoped_refptr<EncodedFormData> BlobBytesConsumer::DrainAsFormData() {
void BlobBytesConsumer::SetClient(BytesConsumer::Client* client) {
DCHECK(!client_);
DCHECK(client);
- client_ = client;
+ if (nested_consumer_)
+ nested_consumer_->SetClient(client);
+ else
+ client_ = client;
}
void BlobBytesConsumer::ClearClient() {
client_ = nullptr;
+ if (nested_consumer_)
+ nested_consumer_->ClearClient();
}
void BlobBytesConsumer::Cancel() {
- if (state_ == PublicState::kClosed || state_ == PublicState::kErrored)
- return;
- Close();
- if (body_) {
- body_->Cancel();
- body_ = nullptr;
- }
- if (!blob_url_.IsEmpty()) {
- BlobRegistry::RevokePublicBlobURL(blob_url_);
- blob_url_ = KURL();
- }
+ if (nested_consumer_)
+ nested_consumer_->Cancel();
blob_data_handle_ = nullptr;
+ client_ = nullptr;
}
BytesConsumer::Error BlobBytesConsumer::GetError() const {
- DCHECK_EQ(PublicState::kErrored, state_);
- return Error("Failed to load a blob.");
+ DCHECK(nested_consumer_);
+ return nested_consumer_->GetError();
}
BytesConsumer::PublicState BlobBytesConsumer::GetPublicState() const {
- return state_;
-}
-
-void BlobBytesConsumer::ContextDestroyed(ExecutionContext*) {
- if (state_ != PublicState::kReadableOrWaiting)
- return;
-
- BytesConsumer::Client* client = client_;
- GetError();
- if (client)
- client->OnStateChange();
-}
-
-void BlobBytesConsumer::OnStateChange() {
- if (state_ != PublicState::kReadableOrWaiting)
- return;
- DCHECK(body_);
-
- BytesConsumer::Client* client = client_;
- switch (body_->GetPublicState()) {
- case PublicState::kReadableOrWaiting:
- break;
- case PublicState::kClosed:
- has_seen_end_of_data_ = true;
- if (has_finished_loading_)
- Close();
- break;
- case PublicState::kErrored:
- GetError();
- break;
+ if (!nested_consumer_) {
+ return blob_data_handle_ ? PublicState::kReadableOrWaiting
+ : PublicState::kClosed;
}
- if (client)
- client->OnStateChange();
-}
-
-void BlobBytesConsumer::DidReceiveResponse(
- unsigned long identifier,
- const ResourceResponse&,
- std::unique_ptr<WebDataConsumerHandle> handle) {
- DCHECK(handle);
- DCHECK(!body_);
- DCHECK_EQ(PublicState::kReadableOrWaiting, state_);
-
- body_ = new BytesConsumerForDataConsumerHandle(GetExecutionContext(),
- std::move(handle));
- body_->SetClient(this);
-
- if (IsClean()) {
- // This function is called synchronously in ThreadableLoader::start.
- return;
- }
- OnStateChange();
-}
-
-void BlobBytesConsumer::DidFinishLoading(unsigned long identifier) {
- DCHECK_EQ(PublicState::kReadableOrWaiting, state_);
- has_finished_loading_ = true;
- loader_ = nullptr;
- if (!has_seen_end_of_data_)
- return;
- DCHECK(!IsClean());
- BytesConsumer::Client* client = client_;
- Close();
- if (client)
- client->OnStateChange();
-}
-
-void BlobBytesConsumer::DidFail(const ResourceError& e) {
- if (e.IsCancellation()) {
- if (state_ != PublicState::kReadableOrWaiting)
- return;
- }
- DCHECK_EQ(PublicState::kReadableOrWaiting, state_);
- loader_ = nullptr;
- BytesConsumer::Client* client = client_;
- GetError();
- if (IsClean()) {
- // This function is called synchronously in ThreadableLoader::start.
- return;
- }
- if (client) {
- client->OnStateChange();
- client = nullptr;
- }
-}
-
-void BlobBytesConsumer::DidFailRedirectCheck() {
- NOTREACHED();
+ return nested_consumer_->GetPublicState();
}
void BlobBytesConsumer::Trace(blink::Visitor* visitor) {
- visitor->Trace(body_);
+ visitor->Trace(execution_context_);
+ visitor->Trace(nested_consumer_);
visitor->Trace(client_);
- visitor->Trace(loader_);
BytesConsumer::Trace(visitor);
- BytesConsumer::Client::Trace(visitor);
- ContextLifecycleObserver::Trace(visitor);
-}
-
-BlobBytesConsumer* BlobBytesConsumer::CreateForTesting(
- ExecutionContext* execution_context,
- scoped_refptr<BlobDataHandle> blob_data_handle,
- ThreadableLoader* loader) {
- return new BlobBytesConsumer(execution_context, std::move(blob_data_handle),
- loader);
-}
-
-ThreadableLoader* BlobBytesConsumer::CreateLoader() {
- ThreadableLoaderOptions options;
-
- ResourceLoaderOptions resource_loader_options;
- resource_loader_options.data_buffering_policy = kDoNotBufferData;
- resource_loader_options.initiator_info.name =
- FetchInitiatorTypeNames::internal;
-
- return ThreadableLoader::Create(*GetExecutionContext(), this, options,
- resource_loader_options);
-}
-
-void BlobBytesConsumer::Close() {
- DCHECK_EQ(state_, PublicState::kReadableOrWaiting);
- state_ = PublicState::kClosed;
- Clear();
-}
-
-void BlobBytesConsumer::GetError() {
- DCHECK_EQ(state_, PublicState::kReadableOrWaiting);
- state_ = PublicState::kErrored;
- Clear();
-}
-
-void BlobBytesConsumer::Clear() {
- DCHECK_NE(state_, PublicState::kReadableOrWaiting);
- if (loader_) {
- loader_->Cancel();
- loader_ = nullptr;
- }
- client_ = nullptr;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer.h b/chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer.h
index 674305347a3..579273980ce 100644
--- a/chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer.h
+++ b/chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer.h
@@ -8,28 +8,17 @@
#include <memory>
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/fetch/bytes_consumer.h"
-#include "third_party/blink/renderer/core/loader/threadable_loader_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
class BlobDataHandle;
-class EncodedFormData;
class ExecutionContext;
-class ThreadableLoader;
-class WebDataConsumerHandle;
// A BlobBytesConsumer is created from a blob handle and it will
// return a valid handle from drainAsBlobDataHandle as much as possible.
-class CORE_EXPORT BlobBytesConsumer final : public BytesConsumer,
- public ContextLifecycleObserver,
- public BytesConsumer::Client,
- public ThreadableLoaderClient {
- USING_GARBAGE_COLLECTED_MIXIN(BlobBytesConsumer);
- USING_PRE_FINALIZER(BlobBytesConsumer, Cancel);
-
+class CORE_EXPORT BlobBytesConsumer final : public BytesConsumer {
public:
// |handle| can be null. In that case this consumer gets closed.
BlobBytesConsumer(ExecutionContext*,
@@ -48,47 +37,13 @@ class CORE_EXPORT BlobBytesConsumer final : public BytesConsumer,
Error GetError() const override;
String DebugName() const override { return "BlobBytesConsumer"; }
- // ContextLifecycleObserver implementation
- void ContextDestroyed(ExecutionContext*) override;
-
- // BytesConsumer::Client implementation
- void OnStateChange() override;
-
- // ThreadableLoaderClient implementation
- void DidReceiveResponse(unsigned long identifier,
- const ResourceResponse&,
- std::unique_ptr<WebDataConsumerHandle>) override;
- void DidFinishLoading(unsigned long identifier) override;
- void DidFail(const ResourceError&) override;
- void DidFailRedirectCheck() override;
-
void Trace(blink::Visitor*) override;
- static BlobBytesConsumer* CreateForTesting(ExecutionContext*,
- scoped_refptr<BlobDataHandle>,
- ThreadableLoader*);
-
private:
- BlobBytesConsumer(ExecutionContext*,
- scoped_refptr<BlobDataHandle>,
- ThreadableLoader*);
- ThreadableLoader* CreateLoader();
- void DidFailInternal();
- bool IsClean() const { return blob_data_handle_.get(); }
- void Close();
- void GetError();
- void Clear();
-
- KURL blob_url_;
+ Member<ExecutionContext> execution_context_;
scoped_refptr<BlobDataHandle> blob_data_handle_;
- Member<BytesConsumer> body_;
+ Member<BytesConsumer> nested_consumer_;
Member<BytesConsumer::Client> client_;
- Member<ThreadableLoader> loader_;
-
- PublicState state_ = PublicState::kReadableOrWaiting;
- // These two booleans are meaningful only when m_state is ReadableOrWaiting.
- bool has_seen_end_of_data_ = false;
- bool has_finished_loading_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer_test.cc b/chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer_test.cc
index 877801119aa..8a2581ef3d1 100644
--- a/chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer_test.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/blob_bytes_consumer_test.cc
@@ -4,12 +4,14 @@
#include "third_party/blink/renderer/core/fetch/blob_bytes_consumer.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/fetch/bytes_consumer_test_util.h"
#include "third_party/blink/renderer/core/fetch/data_consumer_handle_test_util.h"
#include "third_party/blink/renderer/core/loader/threadable_loader.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
+#include "third_party/blink/renderer/platform/blob/testing/fake_blob.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
@@ -25,92 +27,6 @@ using PublicState = BytesConsumer::PublicState;
using ReplayingHandle = DataConsumerHandleTestUtil::ReplayingHandle;
using Result = BytesConsumer::Result;
-class TestThreadableLoader : public ThreadableLoader {
- public:
- ~TestThreadableLoader() override {
- EXPECT_FALSE(should_be_cancelled_ && !is_cancelled_)
- << "The loader should be cancelled but is not cancelled.";
- }
-
- void Start(const ResourceRequest& request) override { is_started_ = true; }
-
- void OverrideTimeout(unsigned long timeout_milliseconds) override {
- ADD_FAILURE() << "overrideTimeout should not be called.";
- }
-
- void Cancel() override { is_cancelled_ = true; }
- void Detach() override { NOTREACHED(); }
-
- bool IsStarted() const { return is_started_; }
- bool IsCancelled() const { return is_cancelled_; }
- void SetShouldBeCancelled() { should_be_cancelled_ = true; }
-
- private:
- bool is_started_ = false;
- bool is_cancelled_ = false;
- bool should_be_cancelled_ = false;
-};
-
-class SyncLoadingTestThreadableLoader : public ThreadableLoader {
- public:
- ~SyncLoadingTestThreadableLoader() override { DCHECK(!handle_); }
-
- void Start(const ResourceRequest& request) override {
- is_started_ = true;
- client_->DidReceiveResponse(0, ResourceResponse(), std::move(handle_));
- client_->DidFinishLoading(0);
- }
-
- void OverrideTimeout(unsigned long timeout_milliseconds) override {
- ADD_FAILURE() << "overrideTimeout should not be called.";
- }
-
- void Cancel() override { is_cancelled_ = true; }
- void Detach() override { NOTREACHED(); }
-
- bool IsStarted() const { return is_started_; }
- bool IsCancelled() const { return is_cancelled_; }
-
- void SetClient(ThreadableLoaderClient* client) { client_ = client; }
-
- void SetHandle(std::unique_ptr<WebDataConsumerHandle> handle) {
- handle_ = std::move(handle);
- }
-
- private:
- bool is_started_ = false;
- bool is_cancelled_ = false;
- ThreadableLoaderClient* client_ = nullptr;
- std::unique_ptr<WebDataConsumerHandle> handle_;
-};
-
-class SyncErrorTestThreadableLoader : public ThreadableLoader {
- public:
- ~SyncErrorTestThreadableLoader() override {}
-
- void Start(const ResourceRequest& request) override {
- is_started_ = true;
- client_->DidFail(ResourceError::Failure(NullURL()));
- }
-
- void OverrideTimeout(unsigned long timeout_milliseconds) override {
- ADD_FAILURE() << "overrideTimeout should not be called.";
- }
-
- void Cancel() override { is_cancelled_ = true; }
- void Detach() override { NOTREACHED(); }
-
- bool IsStarted() const { return is_started_; }
- bool IsCancelled() const { return is_cancelled_; }
-
- void SetClient(ThreadableLoaderClient* client) { client_ = client; }
-
- private:
- bool is_started_ = false;
- bool is_cancelled_ = false;
- ThreadableLoaderClient* client_ = nullptr;
-};
-
class BlobBytesConsumerTestClient final
: public GarbageCollectedFinalized<BlobBytesConsumerTestClient>,
public BytesConsumer::Client {
@@ -128,144 +44,71 @@ class BlobBytesConsumerTestClient final
class BlobBytesConsumerTest : public PageTestBase {
public:
void SetUp() override { PageTestBase::SetUp(IntSize(1, 1)); }
+ scoped_refptr<BlobDataHandle> CreateBlob(const String& body) {
+ mojom::blink::BlobPtrInfo mojo_blob;
+ mojo::MakeStrongBinding(
+ std::make_unique<FakeBlob>(kBlobUUID, body, &blob_state_),
+ MakeRequest(&mojo_blob));
+ return BlobDataHandle::Create(kBlobUUID, "", body.length(),
+ std::move(mojo_blob));
+ }
+
+ bool DidStartLoading() {
+ base::RunLoop().RunUntilIdle();
+ return blob_state_.did_initiate_read_operation;
+ }
+
+ private:
+ const String kBlobUUID = "blob-id";
+ FakeBlob::State blob_state_;
};
TEST_F(BlobBytesConsumerTest, TwoPhaseRead) {
- scoped_refptr<BlobDataHandle> blob_data_handle =
- BlobDataHandle::Create(BlobData::Create(), 12345);
- TestThreadableLoader* loader = new TestThreadableLoader();
- BlobBytesConsumer* consumer = BlobBytesConsumer::CreateForTesting(
- &GetDocument(), blob_data_handle, loader);
- std::unique_ptr<ReplayingHandle> src = ReplayingHandle::Create();
- src->Add(DataConsumerCommand(DataConsumerCommand::kData, "hello, "));
- src->Add(DataConsumerCommand(DataConsumerCommand::kWait));
- src->Add(DataConsumerCommand(DataConsumerCommand::kData, "world"));
- src->Add(DataConsumerCommand(DataConsumerCommand::kDone));
+ String body = "hello, world";
+ scoped_refptr<BlobDataHandle> blob_data_handle = CreateBlob(body);
+
+ BlobBytesConsumer* consumer =
+ new BlobBytesConsumer(&GetDocument(), blob_data_handle);
EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
- EXPECT_FALSE(loader->IsStarted());
+ EXPECT_FALSE(DidStartLoading());
const char* buffer = nullptr;
size_t available = 0;
EXPECT_EQ(Result::kShouldWait, consumer->BeginRead(&buffer, &available));
- EXPECT_TRUE(loader->IsStarted());
+ EXPECT_TRUE(DidStartLoading());
EXPECT_FALSE(consumer->DrainAsBlobDataHandle(
BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize));
EXPECT_FALSE(consumer->DrainAsFormData());
EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
- consumer->DidReceiveResponse(0, ResourceResponse(), std::move(src));
- consumer->DidFinishLoading(0);
-
auto result = (new BytesConsumerTestUtil::TwoPhaseReader(consumer))->Run();
EXPECT_EQ(Result::kDone, result.first);
EXPECT_EQ("hello, world",
BytesConsumerTestUtil::CharVectorToString(result.second));
}
-TEST_F(BlobBytesConsumerTest, FailLoading) {
- scoped_refptr<BlobDataHandle> blob_data_handle =
- BlobDataHandle::Create(BlobData::Create(), 12345);
- TestThreadableLoader* loader = new TestThreadableLoader();
- BlobBytesConsumer* consumer = BlobBytesConsumer::CreateForTesting(
- &GetDocument(), blob_data_handle, loader);
- BlobBytesConsumerTestClient* client = new BlobBytesConsumerTestClient();
- consumer->SetClient(client);
-
- const char* buffer = nullptr;
- size_t available = 0;
- EXPECT_EQ(Result::kShouldWait, consumer->BeginRead(&buffer, &available));
- EXPECT_TRUE(loader->IsStarted());
- EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
-
- int num_on_state_change_called = client->NumOnStateChangeCalled();
- consumer->DidFail(ResourceError::Failure(NullURL()));
-
- EXPECT_EQ(num_on_state_change_called + 1, client->NumOnStateChangeCalled());
- EXPECT_EQ(PublicState::kErrored, consumer->GetPublicState());
- EXPECT_EQ(Result::kError, consumer->BeginRead(&buffer, &available));
-}
-
-TEST_F(BlobBytesConsumerTest, FailLoadingAfterResponseReceived) {
- scoped_refptr<BlobDataHandle> blob_data_handle =
- BlobDataHandle::Create(BlobData::Create(), 12345);
- TestThreadableLoader* loader = new TestThreadableLoader();
- BlobBytesConsumer* consumer = BlobBytesConsumer::CreateForTesting(
- &GetDocument(), blob_data_handle, loader);
- BlobBytesConsumerTestClient* client = new BlobBytesConsumerTestClient();
- consumer->SetClient(client);
-
- const char* buffer = nullptr;
- size_t available;
- EXPECT_EQ(Result::kShouldWait, consumer->BeginRead(&buffer, &available));
- EXPECT_TRUE(loader->IsStarted());
- EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
-
- int num_on_state_change_called = client->NumOnStateChangeCalled();
- consumer->DidReceiveResponse(
- 0, ResourceResponse(),
- DataConsumerHandleTestUtil::CreateWaitingDataConsumerHandle());
- EXPECT_EQ(num_on_state_change_called + 1, client->NumOnStateChangeCalled());
- EXPECT_EQ(Result::kShouldWait, consumer->BeginRead(&buffer, &available));
- EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
-
- consumer->DidFail(ResourceError::Failure(NullURL()));
- EXPECT_EQ(num_on_state_change_called + 2, client->NumOnStateChangeCalled());
- EXPECT_EQ(PublicState::kErrored, consumer->GetPublicState());
- EXPECT_EQ(Result::kError, consumer->BeginRead(&buffer, &available));
-}
-
-TEST_F(BlobBytesConsumerTest, FailAccessControlCheck) {
- scoped_refptr<BlobDataHandle> blob_data_handle =
- BlobDataHandle::Create(BlobData::Create(), 12345);
- TestThreadableLoader* loader = new TestThreadableLoader();
- BlobBytesConsumer* consumer = BlobBytesConsumer::CreateForTesting(
- &GetDocument(), blob_data_handle, loader);
- BlobBytesConsumerTestClient* client = new BlobBytesConsumerTestClient();
- consumer->SetClient(client);
-
- const char* buffer = nullptr;
- size_t available;
- EXPECT_EQ(Result::kShouldWait, consumer->BeginRead(&buffer, &available));
- EXPECT_TRUE(loader->IsStarted());
- EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
-
- int num_on_state_change_called = client->NumOnStateChangeCalled();
- consumer->DidFail(ResourceError::Failure(NullURL()));
- EXPECT_EQ(num_on_state_change_called + 1, client->NumOnStateChangeCalled());
-
- EXPECT_EQ(PublicState::kErrored, consumer->GetPublicState());
- EXPECT_EQ(Result::kError, consumer->BeginRead(&buffer, &available));
-}
-
TEST_F(BlobBytesConsumerTest, CancelBeforeStarting) {
- scoped_refptr<BlobDataHandle> blob_data_handle =
- BlobDataHandle::Create(BlobData::Create(), 12345);
- TestThreadableLoader* loader = new TestThreadableLoader();
- BlobBytesConsumer* consumer = BlobBytesConsumer::CreateForTesting(
- &GetDocument(), blob_data_handle, loader);
+ scoped_refptr<BlobDataHandle> blob_data_handle = CreateBlob("foo bar");
+ BlobBytesConsumer* consumer =
+ new BlobBytesConsumer(&GetDocument(), blob_data_handle);
BlobBytesConsumerTestClient* client = new BlobBytesConsumerTestClient();
consumer->SetClient(client);
consumer->Cancel();
- // This should be FALSE in production, but TRUE here because we set the
- // loader before starting loading in tests.
- EXPECT_TRUE(loader->IsCancelled());
const char* buffer = nullptr;
size_t available;
EXPECT_EQ(Result::kDone, consumer->BeginRead(&buffer, &available));
EXPECT_EQ(PublicState::kClosed, consumer->GetPublicState());
- EXPECT_FALSE(loader->IsStarted());
+ EXPECT_FALSE(DidStartLoading());
EXPECT_EQ(0, client->NumOnStateChangeCalled());
}
TEST_F(BlobBytesConsumerTest, CancelAfterStarting) {
- scoped_refptr<BlobDataHandle> blob_data_handle =
- BlobDataHandle::Create(BlobData::Create(), 12345);
- TestThreadableLoader* loader = new TestThreadableLoader();
- BlobBytesConsumer* consumer = BlobBytesConsumer::CreateForTesting(
- &GetDocument(), blob_data_handle, loader);
+ scoped_refptr<BlobDataHandle> blob_data_handle = CreateBlob("foo bar");
+ BlobBytesConsumer* consumer =
+ new BlobBytesConsumer(&GetDocument(), blob_data_handle);
BlobBytesConsumerTestClient* client = new BlobBytesConsumerTestClient();
consumer->SetClient(client);
@@ -273,130 +116,43 @@ TEST_F(BlobBytesConsumerTest, CancelAfterStarting) {
size_t available;
EXPECT_EQ(Result::kShouldWait, consumer->BeginRead(&buffer, &available));
EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
- EXPECT_TRUE(loader->IsStarted());
EXPECT_EQ(0, client->NumOnStateChangeCalled());
consumer->Cancel();
- EXPECT_TRUE(loader->IsCancelled());
EXPECT_EQ(PublicState::kClosed, consumer->GetPublicState());
EXPECT_EQ(Result::kDone, consumer->BeginRead(&buffer, &available));
EXPECT_EQ(0, client->NumOnStateChangeCalled());
-}
-
-TEST_F(BlobBytesConsumerTest, ReadLastChunkBeforeDidFinishLoadingArrives) {
- scoped_refptr<BlobDataHandle> blob_data_handle =
- BlobDataHandle::Create(BlobData::Create(), 12345);
- TestThreadableLoader* loader = new TestThreadableLoader();
- BlobBytesConsumer* consumer = BlobBytesConsumer::CreateForTesting(
- &GetDocument(), blob_data_handle, loader);
- BlobBytesConsumerTestClient* client = new BlobBytesConsumerTestClient();
- consumer->SetClient(client);
- std::unique_ptr<ReplayingHandle> src = ReplayingHandle::Create();
- src->Add(DataConsumerCommand(DataConsumerCommand::kData, "hello"));
- src->Add(DataConsumerCommand(DataConsumerCommand::kDone));
-
- EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
- EXPECT_FALSE(loader->IsStarted());
-
- const char* buffer = nullptr;
- size_t available;
- EXPECT_EQ(Result::kShouldWait, consumer->BeginRead(&buffer, &available));
- EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
- EXPECT_TRUE(loader->IsStarted());
- EXPECT_EQ(0, client->NumOnStateChangeCalled());
-
- consumer->DidReceiveResponse(0, ResourceResponse(), std::move(src));
- EXPECT_EQ(1, client->NumOnStateChangeCalled());
- test::RunPendingTasks();
- EXPECT_EQ(2, client->NumOnStateChangeCalled());
-
- EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
- ASSERT_EQ(Result::kOk, consumer->BeginRead(&buffer, &available));
- ASSERT_EQ(5u, available);
- EXPECT_EQ("hello", String(buffer, available));
- ASSERT_EQ(Result::kOk, consumer->EndRead(available));
-
- EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
- ASSERT_EQ(Result::kShouldWait, consumer->BeginRead(&buffer, &available));
- EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
-
- consumer->DidFinishLoading(0);
- EXPECT_EQ(3, client->NumOnStateChangeCalled());
- EXPECT_EQ(PublicState::kClosed, consumer->GetPublicState());
- ASSERT_EQ(Result::kDone, consumer->BeginRead(&buffer, &available));
-}
-
-TEST_F(BlobBytesConsumerTest, ReadLastChunkAfterDidFinishLoadingArrives) {
- scoped_refptr<BlobDataHandle> blob_data_handle =
- BlobDataHandle::Create(BlobData::Create(), 12345);
- TestThreadableLoader* loader = new TestThreadableLoader();
- BlobBytesConsumer* consumer = BlobBytesConsumer::CreateForTesting(
- &GetDocument(), blob_data_handle, loader);
- BlobBytesConsumerTestClient* client = new BlobBytesConsumerTestClient();
- consumer->SetClient(client);
- std::unique_ptr<ReplayingHandle> src = ReplayingHandle::Create();
- src->Add(DataConsumerCommand(DataConsumerCommand::kData, "hello"));
- src->Add(DataConsumerCommand(DataConsumerCommand::kDone));
-
- EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
- EXPECT_FALSE(loader->IsStarted());
-
- const char* buffer = nullptr;
- size_t available;
- EXPECT_EQ(Result::kShouldWait, consumer->BeginRead(&buffer, &available));
- EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
- EXPECT_TRUE(loader->IsStarted());
- EXPECT_EQ(0, client->NumOnStateChangeCalled());
-
- consumer->DidReceiveResponse(0, ResourceResponse(), std::move(src));
- EXPECT_EQ(1, client->NumOnStateChangeCalled());
- test::RunPendingTasks();
- EXPECT_EQ(2, client->NumOnStateChangeCalled());
-
- consumer->DidFinishLoading(0);
- test::RunPendingTasks();
- EXPECT_EQ(2, client->NumOnStateChangeCalled());
-
- EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
- ASSERT_EQ(Result::kOk, consumer->BeginRead(&buffer, &available));
- ASSERT_EQ(5u, available);
- EXPECT_EQ("hello", String(buffer, available));
- ASSERT_EQ(Result::kOk, consumer->EndRead(available));
-
- EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
- EXPECT_EQ(Result::kDone, consumer->BeginRead(&buffer, &available));
- EXPECT_EQ(2, client->NumOnStateChangeCalled());
+ EXPECT_TRUE(DidStartLoading());
}
TEST_F(BlobBytesConsumerTest, DrainAsBlobDataHandle) {
- scoped_refptr<BlobDataHandle> blob_data_handle =
- BlobDataHandle::Create(BlobData::Create(), 12345);
- TestThreadableLoader* loader = new TestThreadableLoader();
- BlobBytesConsumer* consumer = BlobBytesConsumer::CreateForTesting(
- &GetDocument(), blob_data_handle, loader);
+ String body = "hello, world";
+ scoped_refptr<BlobDataHandle> blob_data_handle = CreateBlob(body);
+ BlobBytesConsumer* consumer =
+ new BlobBytesConsumer(&GetDocument(), blob_data_handle);
EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
- EXPECT_FALSE(loader->IsStarted());
+ EXPECT_FALSE(DidStartLoading());
scoped_refptr<BlobDataHandle> result = consumer->DrainAsBlobDataHandle(
BytesConsumer::BlobSizePolicy::kDisallowBlobWithInvalidSize);
ASSERT_TRUE(result);
EXPECT_FALSE(consumer->DrainAsBlobDataHandle(
BytesConsumer::BlobSizePolicy::kDisallowBlobWithInvalidSize));
- EXPECT_EQ(12345u, result->size());
+ EXPECT_EQ(body.length(), result->size());
EXPECT_EQ(PublicState::kClosed, consumer->GetPublicState());
- EXPECT_FALSE(loader->IsStarted());
+ EXPECT_FALSE(DidStartLoading());
}
TEST_F(BlobBytesConsumerTest, DrainAsBlobDataHandle_2) {
- scoped_refptr<BlobDataHandle> blob_data_handle =
- BlobDataHandle::Create(BlobData::Create(), -1);
- TestThreadableLoader* loader = new TestThreadableLoader();
- BlobBytesConsumer* consumer = BlobBytesConsumer::CreateForTesting(
- &GetDocument(), blob_data_handle, loader);
+ scoped_refptr<BlobDataHandle> blob_data_handle = BlobDataHandle::Create(
+ "uuid", "", -1, CreateBlob("foo bar")->CloneBlobPtr().PassInterface());
+ ;
+ BlobBytesConsumer* consumer =
+ new BlobBytesConsumer(&GetDocument(), blob_data_handle);
EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
- EXPECT_FALSE(loader->IsStarted());
+ EXPECT_FALSE(DidStartLoading());
scoped_refptr<BlobDataHandle> result = consumer->DrainAsBlobDataHandle(
BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize);
@@ -405,109 +161,44 @@ TEST_F(BlobBytesConsumerTest, DrainAsBlobDataHandle_2) {
BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize));
EXPECT_EQ(UINT64_MAX, result->size());
EXPECT_EQ(PublicState::kClosed, consumer->GetPublicState());
- EXPECT_FALSE(loader->IsStarted());
+ EXPECT_FALSE(DidStartLoading());
}
TEST_F(BlobBytesConsumerTest, DrainAsBlobDataHandle_3) {
- scoped_refptr<BlobDataHandle> blob_data_handle =
- BlobDataHandle::Create(BlobData::Create(), -1);
- TestThreadableLoader* loader = new TestThreadableLoader();
- BlobBytesConsumer* consumer = BlobBytesConsumer::CreateForTesting(
- &GetDocument(), blob_data_handle, loader);
+ scoped_refptr<BlobDataHandle> blob_data_handle = BlobDataHandle::Create(
+ "uuid", "", -1, CreateBlob("foo bar")->CloneBlobPtr().PassInterface());
+ ;
+ BlobBytesConsumer* consumer =
+ new BlobBytesConsumer(&GetDocument(), blob_data_handle);
EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
- EXPECT_FALSE(loader->IsStarted());
+ EXPECT_FALSE(DidStartLoading());
EXPECT_FALSE(consumer->DrainAsBlobDataHandle(
BytesConsumer::BlobSizePolicy::kDisallowBlobWithInvalidSize));
EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
- EXPECT_FALSE(loader->IsStarted());
+ EXPECT_FALSE(DidStartLoading());
}
TEST_F(BlobBytesConsumerTest, DrainAsFormData) {
- scoped_refptr<BlobDataHandle> blob_data_handle =
- BlobDataHandle::Create(BlobData::Create(), 12345);
- TestThreadableLoader* loader = new TestThreadableLoader();
- BlobBytesConsumer* consumer = BlobBytesConsumer::CreateForTesting(
- &GetDocument(), blob_data_handle, loader);
+ String body = "hello, world";
+ scoped_refptr<BlobDataHandle> blob_data_handle = CreateBlob(body);
+ BlobBytesConsumer* consumer =
+ new BlobBytesConsumer(&GetDocument(), blob_data_handle);
EXPECT_EQ(PublicState::kReadableOrWaiting, consumer->GetPublicState());
- EXPECT_FALSE(loader->IsStarted());
+ EXPECT_FALSE(DidStartLoading());
scoped_refptr<EncodedFormData> result = consumer->DrainAsFormData();
ASSERT_TRUE(result);
ASSERT_EQ(1u, result->Elements().size());
ASSERT_EQ(FormDataElement::kEncodedBlob, result->Elements()[0].type_);
ASSERT_TRUE(result->Elements()[0].optional_blob_data_handle_);
- EXPECT_EQ(12345u, result->Elements()[0].optional_blob_data_handle_->size());
+ EXPECT_EQ(body.length(),
+ result->Elements()[0].optional_blob_data_handle_->size());
EXPECT_EQ(blob_data_handle->Uuid(), result->Elements()[0].blob_uuid_);
EXPECT_EQ(PublicState::kClosed, consumer->GetPublicState());
- EXPECT_FALSE(loader->IsStarted());
-}
-
-TEST_F(BlobBytesConsumerTest, LoaderShouldBeCancelled) {
- {
- scoped_refptr<BlobDataHandle> blob_data_handle =
- BlobDataHandle::Create(BlobData::Create(), 12345);
- TestThreadableLoader* loader = new TestThreadableLoader();
- BlobBytesConsumer* consumer = BlobBytesConsumer::CreateForTesting(
- &GetDocument(), blob_data_handle, loader);
-
- const char* buffer = nullptr;
- size_t available;
- EXPECT_EQ(Result::kShouldWait, consumer->BeginRead(&buffer, &available));
- EXPECT_TRUE(loader->IsStarted());
- loader->SetShouldBeCancelled();
- }
- ThreadState::Current()->CollectAllGarbage();
-}
-
-TEST_F(BlobBytesConsumerTest, SyncErrorDispatch) {
- scoped_refptr<BlobDataHandle> blob_data_handle =
- BlobDataHandle::Create(BlobData::Create(), 12345);
- SyncErrorTestThreadableLoader* loader = new SyncErrorTestThreadableLoader();
- BlobBytesConsumer* consumer = BlobBytesConsumer::CreateForTesting(
- &GetDocument(), blob_data_handle, loader);
- loader->SetClient(consumer);
- BlobBytesConsumerTestClient* client = new BlobBytesConsumerTestClient();
- consumer->SetClient(client);
-
- const char* buffer = nullptr;
- size_t available;
- EXPECT_EQ(Result::kError, consumer->BeginRead(&buffer, &available));
- EXPECT_TRUE(loader->IsStarted());
-
- EXPECT_EQ(0, client->NumOnStateChangeCalled());
- EXPECT_EQ(BytesConsumer::PublicState::kErrored, consumer->GetPublicState());
-}
-
-TEST_F(BlobBytesConsumerTest, SyncLoading) {
- scoped_refptr<BlobDataHandle> blob_data_handle =
- BlobDataHandle::Create(BlobData::Create(), 12345);
- SyncLoadingTestThreadableLoader* loader =
- new SyncLoadingTestThreadableLoader();
- BlobBytesConsumer* consumer = BlobBytesConsumer::CreateForTesting(
- &GetDocument(), blob_data_handle, loader);
- std::unique_ptr<ReplayingHandle> src = ReplayingHandle::Create();
- src->Add(DataConsumerCommand(DataConsumerCommand::kData, "hello, "));
- src->Add(DataConsumerCommand(DataConsumerCommand::kWait));
- src->Add(DataConsumerCommand(DataConsumerCommand::kData, "world"));
- src->Add(DataConsumerCommand(DataConsumerCommand::kDone));
- loader->SetClient(consumer);
- loader->SetHandle(std::move(src));
- BlobBytesConsumerTestClient* client = new BlobBytesConsumerTestClient();
- consumer->SetClient(client);
-
- const char* buffer = nullptr;
- size_t available;
- ASSERT_EQ(Result::kOk, consumer->BeginRead(&buffer, &available));
- EXPECT_TRUE(loader->IsStarted());
- ASSERT_EQ(7u, available);
- EXPECT_EQ("hello, ", String(buffer, available));
-
- EXPECT_EQ(0, client->NumOnStateChangeCalled());
- EXPECT_EQ(BytesConsumer::PublicState::kReadableOrWaiting,
- consumer->GetPublicState());
+ EXPECT_FALSE(DidStartLoading());
}
TEST_F(BlobBytesConsumerTest, ConstructedFromNullHandle) {
diff --git a/chromium/third_party/blink/renderer/core/fetch/body.cc b/chromium/third_party/blink/renderer/core/fetch/body.cc
index 63f6dbcdaa6..b055be8ae42 100644
--- a/chromium/third_party/blink/renderer/core/fetch/body.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/body.cc
@@ -6,6 +6,7 @@
#include <memory>
#include "base/memory/scoped_refptr.h"
+#include "base/optional.h"
#include "third_party/blink/public/platform/web_data_consumer_handle.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
@@ -17,6 +18,7 @@
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
#include "third_party/blink/renderer/core/url/url_search_params.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/bindings/v8_throw_exception.h"
#include "third_party/blink/renderer/platform/network/parsed_content_type.h"
@@ -40,7 +42,7 @@ class BodyConsumerBase : public GarbageCollectedFinalized<BodyConsumerBase>,
}
void Abort() override {
- resolver_->Reject(DOMException::Create(kAbortError));
+ resolver_->Reject(DOMException::Create(DOMExceptionCode::kAbortError));
}
void Trace(blink::Visitor* visitor) override {
@@ -131,10 +133,11 @@ class BodyJsonConsumer final : public BodyConsumerBase {
} // namespace
-ScriptPromise Body::arrayBuffer(ScriptState* script_state) {
- ScriptPromise promise = RejectInvalidConsumption(script_state);
- if (!promise.IsEmpty())
- return promise;
+ScriptPromise Body::arrayBuffer(ScriptState* script_state,
+ ExceptionState& exception_state) {
+ RejectInvalidConsumption(script_state, exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
// When the main thread sends a V8::TerminateExecution() signal to a worker
// thread, any V8 API on the worker thread starts returning an empty
@@ -146,31 +149,37 @@ ScriptPromise Body::arrayBuffer(ScriptState* script_state) {
return ScriptPromise();
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- promise = resolver->Promise();
+ ScriptPromise promise = resolver->Promise();
if (BodyBuffer()) {
BodyBuffer()->StartLoading(FetchDataLoader::CreateLoaderAsArrayBuffer(),
- new BodyArrayBufferConsumer(resolver));
+ new BodyArrayBufferConsumer(resolver),
+ exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
} else {
resolver->Resolve(DOMArrayBuffer::Create(0u, 1));
}
return promise;
}
-ScriptPromise Body::blob(ScriptState* script_state) {
- ScriptPromise promise = RejectInvalidConsumption(script_state);
- if (!promise.IsEmpty())
- return promise;
+ScriptPromise Body::blob(ScriptState* script_state,
+ ExceptionState& exception_state) {
+ RejectInvalidConsumption(script_state, exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
// See above comment.
if (!ExecutionContext::From(script_state))
return ScriptPromise();
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- promise = resolver->Promise();
+ ScriptPromise promise = resolver->Promise();
if (BodyBuffer()) {
BodyBuffer()->StartLoading(
FetchDataLoader::CreateLoaderAsBlobHandle(MimeType()),
- new BodyBlobConsumer(resolver));
+ new BodyBlobConsumer(resolver), exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
} else {
std::unique_ptr<BlobData> blob_data = BlobData::Create();
blob_data->SetContentType(MimeType());
@@ -180,10 +189,11 @@ ScriptPromise Body::blob(ScriptState* script_state) {
return promise;
}
-ScriptPromise Body::formData(ScriptState* script_state) {
- ScriptPromise promise = RejectInvalidConsumption(script_state);
- if (!promise.IsEmpty())
- return promise;
+ScriptPromise Body::formData(ScriptState* script_state,
+ ExceptionState& exception_state) {
+ RejectInvalidConsumption(script_state, exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
// See above comment.
if (!ExecutionContext::From(script_state))
@@ -192,20 +202,26 @@ ScriptPromise Body::formData(ScriptState* script_state) {
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
const ParsedContentType parsedTypeWithParameters(ContentType());
const String parsedType = parsedTypeWithParameters.MimeType().LowerASCII();
- promise = resolver->Promise();
+ ScriptPromise promise = resolver->Promise();
if (parsedType == "multipart/form-data") {
const String boundary =
parsedTypeWithParameters.ParameterValueForName("boundary");
- if (BodyBuffer() && !boundary.IsEmpty()) {
- BodyBuffer()->StartLoading(
+ auto* body_buffer = BodyBuffer();
+ if (body_buffer && !boundary.IsEmpty()) {
+ body_buffer->StartLoading(
FetchDataLoader::CreateLoaderAsFormData(boundary),
- new BodyFormDataConsumer(resolver));
+ new BodyFormDataConsumer(resolver), exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
return promise;
}
} else if (parsedType == "application/x-www-form-urlencoded") {
if (BodyBuffer()) {
BodyBuffer()->StartLoading(FetchDataLoader::CreateLoaderAsString(),
- new BodyFormDataConsumer(resolver));
+ new BodyFormDataConsumer(resolver),
+ exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
} else {
resolver->Resolve(FormData::Create());
}
@@ -213,7 +229,10 @@ ScriptPromise Body::formData(ScriptState* script_state) {
} else {
if (BodyBuffer()) {
BodyBuffer()->StartLoading(FetchDataLoader::CreateLoaderAsFailure(),
- new BodyFormDataConsumer(resolver));
+ new BodyFormDataConsumer(resolver),
+ exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
return promise;
}
}
@@ -223,20 +242,23 @@ ScriptPromise Body::formData(ScriptState* script_state) {
return promise;
}
-ScriptPromise Body::json(ScriptState* script_state) {
- ScriptPromise promise = RejectInvalidConsumption(script_state);
- if (!promise.IsEmpty())
- return promise;
+ScriptPromise Body::json(ScriptState* script_state,
+ ExceptionState& exception_state) {
+ RejectInvalidConsumption(script_state, exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
// See above comment.
if (!ExecutionContext::From(script_state))
return ScriptPromise();
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- promise = resolver->Promise();
+ ScriptPromise promise = resolver->Promise();
if (BodyBuffer()) {
BodyBuffer()->StartLoading(FetchDataLoader::CreateLoaderAsString(),
- new BodyJsonConsumer(resolver));
+ new BodyJsonConsumer(resolver), exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
} else {
resolver->Reject(V8ThrowException::CreateSyntaxError(
script_state->GetIsolate(), "Unexpected end of input"));
@@ -244,20 +266,23 @@ ScriptPromise Body::json(ScriptState* script_state) {
return promise;
}
-ScriptPromise Body::text(ScriptState* script_state) {
- ScriptPromise promise = RejectInvalidConsumption(script_state);
- if (!promise.IsEmpty())
- return promise;
+ScriptPromise Body::text(ScriptState* script_state,
+ ExceptionState& exception_state) {
+ RejectInvalidConsumption(script_state, exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
// See above comment.
if (!ExecutionContext::From(script_state))
return ScriptPromise();
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- promise = resolver->Promise();
+ ScriptPromise promise = resolver->Promise();
if (BodyBuffer()) {
BodyBuffer()->StartLoading(FetchDataLoader::CreateLoaderAsString(),
- new BodyTextConsumer(resolver));
+ new BodyTextConsumer(resolver), exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
} else {
resolver->Resolve(String());
}
@@ -272,34 +297,60 @@ ScriptValue Body::body(ScriptState* script_state) {
return stream;
}
-bool Body::bodyUsed() {
- return BodyBuffer() && BodyBuffer()->IsStreamDisturbed();
+Body::BodyUsed Body::IsBodyUsed(ExceptionState& exception_state) {
+ auto* body_buffer = BodyBuffer();
+ if (!body_buffer)
+ return BodyUsed::kUnused;
+ base::Optional<bool> stream_disturbed =
+ body_buffer->IsStreamDisturbed(exception_state);
+ if (exception_state.HadException())
+ return BodyUsed::kBroken;
+ return stream_disturbed.value() ? BodyUsed::kUsed : BodyUsed::kUnused;
}
-bool Body::IsBodyLocked() {
- return BodyBuffer() && BodyBuffer()->IsStreamLocked();
+Body::BodyLocked Body::IsBodyLocked(ExceptionState& exception_state) {
+ auto* body_buffer = BodyBuffer();
+ if (!body_buffer)
+ return BodyLocked::kUnlocked;
+ base::Optional<bool> is_locked = body_buffer->IsStreamLocked(exception_state);
+ if (exception_state.HadException())
+ return BodyLocked::kBroken;
+ return is_locked.value() ? BodyLocked::kLocked : BodyLocked::kUnlocked;
}
bool Body::HasPendingActivity() const {
if (!GetExecutionContext() || GetExecutionContext()->IsContextDestroyed())
return false;
- if (!BodyBuffer())
+ auto* body_buffer = BodyBuffer();
+ if (!body_buffer)
return false;
- return BodyBuffer()->HasPendingActivity();
+ return body_buffer->HasPendingActivity();
+}
+
+bool Body::IsBodyUsedForDCheck() {
+ return BodyBuffer() && BodyBuffer()->IsStreamDisturbedForDCheck();
}
Body::Body(ExecutionContext* context) : ContextClient(context) {}
-ScriptPromise Body::RejectInvalidConsumption(ScriptState* script_state) {
- const bool used = bodyUsed();
- if (IsBodyLocked() || used) {
- return ScriptPromise::Reject(
- script_state,
- V8ThrowException::CreateTypeError(
- script_state->GetIsolate(),
- used ? "body stream already read" : "body stream is locked"));
+void Body::RejectInvalidConsumption(ScriptState* script_state,
+ ExceptionState& exception_state) {
+ const auto used = IsBodyUsed(exception_state);
+ if (exception_state.HadException()) {
+ DCHECK_EQ(used, BodyUsed::kBroken);
+ return;
+ }
+ DCHECK_NE(used, BodyUsed::kBroken);
+
+ if (IsBodyLocked(exception_state) == BodyLocked::kLocked) {
+ DCHECK(!exception_state.HadException());
+ exception_state.ThrowTypeError("body stream is locked");
}
- return ScriptPromise();
+ if (exception_state.HadException())
+ return;
+
+ if (used == BodyUsed::kUsed)
+ exception_state.ThrowTypeError("body stream already read");
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fetch/body.h b/chromium/third_party/blink/renderer/core/fetch/body.h
index b2df2bf89a5..7f8b16d9d32 100644
--- a/chromium/third_party/blink/renderer/core/fetch/body.h
+++ b/chromium/third_party/blink/renderer/core/fetch/body.h
@@ -17,6 +17,7 @@
namespace blink {
class BodyStreamBuffer;
+class ExceptionState;
class ExecutionContext;
class ScriptState;
@@ -34,19 +35,33 @@ class CORE_EXPORT Body : public ScriptWrappable,
USING_GARBAGE_COLLECTED_MIXIN(Body);
public:
+ enum class BodyUsed { kUsed, kUnused, kBroken };
+ enum class BodyLocked { kLocked, kUnlocked, kBroken };
+
explicit Body(ExecutionContext*);
- ScriptPromise arrayBuffer(ScriptState*);
- ScriptPromise blob(ScriptState*);
- ScriptPromise formData(ScriptState*);
- ScriptPromise json(ScriptState*);
- ScriptPromise text(ScriptState*);
+ ScriptPromise arrayBuffer(ScriptState*, ExceptionState&);
+ ScriptPromise blob(ScriptState*, ExceptionState&);
+ ScriptPromise formData(ScriptState*, ExceptionState&);
+ ScriptPromise json(ScriptState*, ExceptionState&);
+ ScriptPromise text(ScriptState*, ExceptionState&);
ScriptValue body(ScriptState*);
virtual BodyStreamBuffer* BodyBuffer() = 0;
virtual const BodyStreamBuffer* BodyBuffer() const = 0;
- virtual bool bodyUsed();
- bool IsBodyLocked();
+ // This should only be called from the generated bindings. All other code
+ // should use IsBodyUsed() instead.
+ bool bodyUsed(ExceptionState& exception_state) {
+ return IsBodyUsed(exception_state) == BodyUsed::kUsed;
+ }
+
+ // Returns kUsed, kUnused or kBroken. kBroken implies there is an exception
+ // pending and the caller should return to JavaScript immediately.
+ virtual BodyUsed IsBodyUsed(ExceptionState&);
+
+ // Returns kLocked, kUnlocked or kBroken. kBroken implies there is an
+ // exception pending and the caller should return to JavaScript immediately.
+ BodyLocked IsBodyLocked(ExceptionState&);
// ScriptWrappable override.
bool HasPendingActivity() const override;
@@ -56,6 +71,11 @@ class CORE_EXPORT Body : public ScriptWrappable,
ContextClient::Trace(visitor);
}
+ protected:
+ // A version of IsBodyUsed() which catches exceptions and returns
+ // false. Should never be used outside DCHECK().
+ virtual bool IsBodyUsedForDCheck();
+
private:
// TODO(e_hakkinen): Fix |MimeType()| to always contain parameters and
// remove |ContentType()|.
@@ -63,10 +83,10 @@ class CORE_EXPORT Body : public ScriptWrappable,
virtual String MimeType() const = 0;
// Body consumption algorithms will reject with a TypeError in a number of
- // error conditions. This method wraps those up into one call which returns
- // an empty ScriptPromise if the consumption may proceed, and a
- // ScriptPromise rejected with a TypeError if it ought to be blocked.
- ScriptPromise RejectInvalidConsumption(ScriptState*);
+ // error conditions. This method wraps those up into one call which throws
+ // an exception if consumption cannot proceed. The caller must check
+ // |exception_state| on return.
+ void RejectInvalidConsumption(ScriptState*, ExceptionState& exception_state);
DISALLOW_COPY_AND_ASSIGN(Body);
};
diff --git a/chromium/third_party/blink/renderer/core/fetch/body.idl b/chromium/third_party/blink/renderer/core/fetch/body.idl
index 7afe7d0f714..c9aa9461fe0 100644
--- a/chromium/third_party/blink/renderer/core/fetch/body.idl
+++ b/chromium/third_party/blink/renderer/core/fetch/body.idl
@@ -8,12 +8,12 @@
ActiveScriptWrappable,
NoInterfaceObject
] interface Body {
- readonly attribute boolean bodyUsed;
- [CallWith=ScriptState, NewObject] Promise<ArrayBuffer> arrayBuffer();
- [CallWith=ScriptState, NewObject] Promise<Blob> blob();
- [CallWith=ScriptState, NewObject] Promise<FormData> formData();
- [CallWith=ScriptState, NewObject] Promise<JSON> json();
- [CallWith=ScriptState, NewObject] Promise<USVString> text();
+ [RaisesException] readonly attribute boolean bodyUsed;
+ [CallWith=ScriptState, NewObject, RaisesException] Promise<ArrayBuffer> arrayBuffer();
+ [CallWith=ScriptState, NewObject, RaisesException] Promise<Blob> blob();
+ [CallWith=ScriptState, NewObject, RaisesException] Promise<FormData> formData();
+ [CallWith=ScriptState, NewObject, RaisesException] Promise<JSON> json();
+ [CallWith=ScriptState, NewObject, RaisesException] Promise<USVString> text();
// body attribute is defined in sub-interfaces, because the IDL processor
// cannot deal with attribute inheritance with runtime enabled flag.
diff --git a/chromium/third_party/blink/renderer/core/fetch/body_stream_buffer.cc b/chromium/third_party/blink/renderer/core/fetch/body_stream_buffer.cc
index aac4eddcf6b..063ffe6342f 100644
--- a/chromium/third_party/blink/renderer/core/fetch/body_stream_buffer.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/body_stream_buffer.cc
@@ -6,8 +6,6 @@
#include <memory>
#include "base/auto_reset.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fetch/body.h"
#include "third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.h"
@@ -15,12 +13,14 @@
#include "third_party/blink/renderer/core/streams/readable_stream_operations.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
+#include "third_party/blink/renderer/platform/bindings/exception_code.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/bindings/v8_private_property.h"
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
@@ -99,17 +99,29 @@ BodyStreamBuffer::BodyStreamBuffer(ScriptState* script_state,
consumer_(consumer),
signal_(signal),
made_from_readable_stream_(false) {
- v8::Local<v8::Value> body_value = ToV8(this, script_state);
- DCHECK(!body_value.IsEmpty());
- DCHECK(body_value->IsObject());
- v8::Local<v8::Object> body = body_value.As<v8::Object>();
-
- ScriptValue readable_stream = ReadableStreamOperations::CreateReadableStream(
- script_state, this,
- ReadableStreamOperations::CreateCountQueuingStrategy(script_state, 0));
- DCHECK(!readable_stream.IsEmpty());
- V8PrivateProperty::GetInternalBodyStream(script_state->GetIsolate())
- .Set(body, readable_stream.V8Value());
+ RetainWrapperUntilV8WrapperGetReturnedToV8(script_state);
+
+ {
+ // Leaving an exception pending will cause Blink to crash in the bindings
+ // code later, so catch instead.
+ v8::TryCatch try_catch(script_state->GetIsolate());
+ ScriptValue strategy =
+ ReadableStreamOperations::CreateCountQueuingStrategy(script_state, 0);
+ if (!strategy.IsEmpty()) {
+ ScriptValue readable_stream =
+ ReadableStreamOperations::CreateReadableStream(script_state, this,
+ strategy);
+ if (!readable_stream.IsEmpty()) {
+ stream_.Set(script_state->GetIsolate(),
+ readable_stream.V8Value().As<v8::Object>());
+ } else {
+ stream_broken_ = true;
+ }
+ } else {
+ stream_broken_ = true;
+ }
+ DCHECK_EQ(stream_broken_, try_catch.HasCaught());
+ }
consumer_->SetClient(this);
if (signal) {
if (signal->aborted()) {
@@ -123,38 +135,38 @@ BodyStreamBuffer::BodyStreamBuffer(ScriptState* script_state,
}
BodyStreamBuffer::BodyStreamBuffer(ScriptState* script_state,
- ScriptValue stream)
+ ScriptValue stream,
+ ExceptionState& exception_state)
: UnderlyingSourceBase(script_state),
script_state_(script_state),
signal_(nullptr),
made_from_readable_stream_(true) {
- DCHECK(ReadableStreamOperations::IsReadableStream(script_state, stream));
- v8::Local<v8::Value> body_value = ToV8(this, script_state);
- DCHECK(!body_value.IsEmpty());
- DCHECK(body_value->IsObject());
- v8::Local<v8::Object> body = body_value.As<v8::Object>();
+ RetainWrapperUntilV8WrapperGetReturnedToV8(script_state);
+ DCHECK(ReadableStreamOperations::IsReadableStreamForDCheck(script_state,
+ stream));
- V8PrivateProperty::GetInternalBodyStream(script_state->GetIsolate())
- .Set(body, stream.V8Value());
+ stream_.Set(script_state->GetIsolate(), stream.V8Value().As<v8::Object>());
}
ScriptValue BodyStreamBuffer::Stream() {
- ScriptState::Scope scope(script_state_.get());
- v8::Local<v8::Value> body_value = ToV8(this, script_state_.get());
- DCHECK(!body_value.IsEmpty());
- DCHECK(body_value->IsObject());
- v8::Local<v8::Object> body = body_value.As<v8::Object>();
- return ScriptValue(
- script_state_.get(),
- V8PrivateProperty::GetInternalBodyStream(script_state_->GetIsolate())
- .GetOrUndefined(body));
+ // Since this is the implementation of response.body, we return the stream
+ // even if |stream_broken_| is true, so that expected JavaScript attribute
+ // behaviour is not changed. User code is still permitted to access the
+ // stream even when it has thrown an exception.
+ return ScriptValue(script_state_,
+ stream_.NewLocal(script_state_->GetIsolate()));
}
scoped_refptr<BlobDataHandle> BodyStreamBuffer::DrainAsBlobDataHandle(
- BytesConsumer::BlobSizePolicy policy) {
- DCHECK(!IsStreamLocked());
- DCHECK(!IsStreamDisturbed());
- if (IsStreamClosed() || IsStreamErrored())
+ BytesConsumer::BlobSizePolicy policy,
+ ExceptionState& exception_state) {
+ DCHECK(!IsStreamLockedForDCheck());
+ DCHECK(!IsStreamDisturbedForDCheck());
+ const base::Optional<bool> is_closed = IsStreamClosed(exception_state);
+ if (exception_state.HadException() || is_closed.value())
+ return nullptr;
+ const base::Optional<bool> is_errored = IsStreamErrored(exception_state);
+ if (exception_state.HadException() || is_errored.value())
return nullptr;
if (made_from_readable_stream_)
@@ -163,16 +175,23 @@ scoped_refptr<BlobDataHandle> BodyStreamBuffer::DrainAsBlobDataHandle(
scoped_refptr<BlobDataHandle> blob_data_handle =
consumer_->DrainAsBlobDataHandle(policy);
if (blob_data_handle) {
- CloseAndLockAndDisturb();
+ CloseAndLockAndDisturb(exception_state);
+ if (exception_state.HadException())
+ return nullptr;
return blob_data_handle;
}
return nullptr;
}
-scoped_refptr<EncodedFormData> BodyStreamBuffer::DrainAsFormData() {
- DCHECK(!IsStreamLocked());
- DCHECK(!IsStreamDisturbed());
- if (IsStreamClosed() || IsStreamErrored())
+scoped_refptr<EncodedFormData> BodyStreamBuffer::DrainAsFormData(
+ ExceptionState& exception_state) {
+ DCHECK(!IsStreamLockedForDCheck());
+ DCHECK(!IsStreamDisturbedForDCheck());
+ const base::Optional<bool> is_closed = IsStreamClosed(exception_state);
+ if (exception_state.HadException() || is_closed.value())
+ return nullptr;
+ const base::Optional<bool> is_errored = IsStreamErrored(exception_state);
+ if (exception_state.HadException() || is_errored.value())
return nullptr;
if (made_from_readable_stream_)
@@ -180,14 +199,17 @@ scoped_refptr<EncodedFormData> BodyStreamBuffer::DrainAsFormData() {
scoped_refptr<EncodedFormData> form_data = consumer_->DrainAsFormData();
if (form_data) {
- CloseAndLockAndDisturb();
+ CloseAndLockAndDisturb(exception_state);
+ if (exception_state.HadException())
+ return nullptr;
return form_data;
}
return nullptr;
}
void BodyStreamBuffer::StartLoading(FetchDataLoader* loader,
- FetchDataLoader::Client* client) {
+ FetchDataLoader::Client* client,
+ ExceptionState& exception_state) {
DCHECK(!loader_);
DCHECK(script_state_->ContextIsValid());
loader_ = loader;
@@ -199,36 +221,65 @@ void BodyStreamBuffer::StartLoading(FetchDataLoader* loader,
signal_->AddAlgorithm(
WTF::Bind(&FetchDataLoader::Client::Abort, WrapWeakPersistent(client)));
}
- loader->Start(ReleaseHandle(),
- new LoaderClient(ExecutionContext::From(script_state_.get()),
- this, client));
+ auto* handle = ReleaseHandle(exception_state);
+ if (exception_state.HadException())
+ return;
+ loader->Start(handle, new LoaderClient(ExecutionContext::From(script_state_),
+ this, client));
}
void BodyStreamBuffer::Tee(BodyStreamBuffer** branch1,
- BodyStreamBuffer** branch2) {
- DCHECK(!IsStreamLocked());
- DCHECK(!IsStreamDisturbed());
+ BodyStreamBuffer** branch2,
+ ExceptionState& exception_state) {
+ DCHECK(!IsStreamLockedForDCheck());
+ DCHECK(!IsStreamDisturbedForDCheck());
*branch1 = nullptr;
*branch2 = nullptr;
if (made_from_readable_stream_) {
+ if (stream_broken_) {
+ // We don't really know what state the stream is in, so throw an exception
+ // rather than making things worse.
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ "Unsafe to tee stream in unknown state");
+ return;
+ }
ScriptValue stream1, stream2;
- ReadableStreamOperations::Tee(script_state_.get(), Stream(), &stream1,
- &stream2);
- *branch1 = new BodyStreamBuffer(script_state_.get(), stream1);
- *branch2 = new BodyStreamBuffer(script_state_.get(), stream2);
+ ReadableStreamOperations::Tee(script_state_, Stream(), &stream1, &stream2,
+ exception_state);
+ if (exception_state.HadException()) {
+ stream_broken_ = true;
+ return;
+ }
+
+ // Exceptions here imply that |stream1| and/or |stream2| are broken, not the
+ // stream owned by this object, so we shouldn't set |stream_broken_|.
+ auto* tmp1 = new BodyStreamBuffer(script_state_, stream1, exception_state);
+ if (exception_state.HadException())
+ return;
+ auto* tmp2 = new BodyStreamBuffer(script_state_, stream2, exception_state);
+ if (exception_state.HadException())
+ return;
+ *branch1 = tmp1;
+ *branch2 = tmp2;
return;
}
BytesConsumer* dest1 = nullptr;
BytesConsumer* dest2 = nullptr;
- BytesConsumer::Tee(ExecutionContext::From(script_state_.get()),
- ReleaseHandle(), &dest1, &dest2);
- *branch1 = new BodyStreamBuffer(script_state_.get(), dest1, signal_);
- *branch2 = new BodyStreamBuffer(script_state_.get(), dest2, signal_);
+ auto* handle = ReleaseHandle(exception_state);
+ if (exception_state.HadException()) {
+ stream_broken_ = true;
+ return;
+ }
+ BytesConsumer::Tee(ExecutionContext::From(script_state_), handle, &dest1,
+ &dest2);
+ *branch1 = new BodyStreamBuffer(script_state_, dest1, signal_);
+ *branch2 = new BodyStreamBuffer(script_state_, dest2, signal_);
}
ScriptPromise BodyStreamBuffer::pull(ScriptState* script_state) {
- DCHECK_EQ(script_state, script_state_.get());
+ DCHECK_EQ(script_state, script_state_);
if (!consumer_) {
// This is a speculative workaround for a crash. See
// https://crbug.com/773525.
@@ -246,7 +297,7 @@ ScriptPromise BodyStreamBuffer::pull(ScriptState* script_state) {
ScriptPromise BodyStreamBuffer::Cancel(ScriptState* script_state,
ScriptValue reason) {
- DCHECK_EQ(script_state, script_state_.get());
+ DCHECK_EQ(script_state, script_state_);
if (Controller())
Controller()->Close();
CancelConsumer();
@@ -282,43 +333,68 @@ void BodyStreamBuffer::ContextDestroyed(ExecutionContext* destroyed_context) {
UnderlyingSourceBase::ContextDestroyed(destroyed_context);
}
-bool BodyStreamBuffer::IsStreamReadable() {
- ScriptState::Scope scope(script_state_.get());
- return ReadableStreamOperations::IsReadable(script_state_.get(), Stream());
+base::Optional<bool> BodyStreamBuffer::IsStreamReadable(
+ ExceptionState& exception_state) {
+ return BooleanStreamOperation(ReadableStreamOperations::IsReadable,
+ exception_state);
}
-bool BodyStreamBuffer::IsStreamClosed() {
- ScriptState::Scope scope(script_state_.get());
- return ReadableStreamOperations::IsClosed(script_state_.get(), Stream());
+base::Optional<bool> BodyStreamBuffer::IsStreamClosed(
+ ExceptionState& exception_state) {
+ return BooleanStreamOperation(ReadableStreamOperations::IsClosed,
+ exception_state);
}
-bool BodyStreamBuffer::IsStreamErrored() {
- ScriptState::Scope scope(script_state_.get());
- return ReadableStreamOperations::IsErrored(script_state_.get(), Stream());
+base::Optional<bool> BodyStreamBuffer::IsStreamErrored(
+ ExceptionState& exception_state) {
+ return BooleanStreamOperation(ReadableStreamOperations::IsErrored,
+ exception_state);
}
-bool BodyStreamBuffer::IsStreamLocked() {
- ScriptState::Scope scope(script_state_.get());
- return ReadableStreamOperations::IsLocked(script_state_.get(), Stream());
+base::Optional<bool> BodyStreamBuffer::IsStreamLocked(
+ ExceptionState& exception_state) {
+ return BooleanStreamOperation(ReadableStreamOperations::IsLocked,
+ exception_state);
}
-bool BodyStreamBuffer::IsStreamDisturbed() {
- ScriptState::Scope scope(script_state_.get());
- return ReadableStreamOperations::IsDisturbed(script_state_.get(), Stream());
+bool BodyStreamBuffer::IsStreamLockedForDCheck() {
+ return ReadableStreamOperations::IsLockedForDCheck(script_state_, Stream());
}
-void BodyStreamBuffer::CloseAndLockAndDisturb() {
- if (IsStreamReadable()) {
+base::Optional<bool> BodyStreamBuffer::IsStreamDisturbed(
+ ExceptionState& exception_state) {
+ return BooleanStreamOperation(ReadableStreamOperations::IsDisturbed,
+ exception_state);
+}
+
+bool BodyStreamBuffer::IsStreamDisturbedForDCheck() {
+ return ReadableStreamOperations::IsDisturbedForDCheck(script_state_,
+ Stream());
+}
+
+void BodyStreamBuffer::CloseAndLockAndDisturb(ExceptionState& exception_state) {
+ base::Optional<bool> is_readable = IsStreamReadable(exception_state);
+ if (exception_state.HadException())
+ return;
+ DCHECK(is_readable.has_value());
+ if (is_readable.value()) {
// Note that the stream cannot be "draining", because it doesn't have
// the internal buffer.
Close();
}
+ DCHECK(!stream_broken_);
- ScriptState::Scope scope(script_state_.get());
- NonThrowableExceptionState exception_state;
+ ScriptState::Scope scope(script_state_);
+ const base::Optional<bool> is_locked = IsStreamLocked(exception_state);
+ if (exception_state.HadException() || is_locked.value())
+ return;
ScriptValue reader = ReadableStreamOperations::GetReader(
- script_state_.get(), Stream(), exception_state);
- ReadableStreamOperations::DefaultReaderRead(script_state_.get(), reader);
+ script_state_, Stream(), exception_state);
+ if (exception_state.HadException()) {
+ stream_broken_ = true;
+ return;
+ }
+ ReadableStreamOperations::DefaultReaderRead(script_state_, reader);
}
bool BodyStreamBuffer::IsAborted() {
@@ -327,8 +403,22 @@ bool BodyStreamBuffer::IsAborted() {
return signal_->aborted();
}
+void BodyStreamBuffer::Trace(blink::Visitor* visitor) {
+ visitor->Trace(script_state_);
+ visitor->Trace(stream_);
+ visitor->Trace(consumer_);
+ visitor->Trace(loader_);
+ visitor->Trace(signal_);
+ UnderlyingSourceBase::Trace(visitor);
+}
+
void BodyStreamBuffer::Abort() {
- Controller()->GetError(DOMException::Create(kAbortError));
+ if (!Controller()) {
+ DCHECK(!GetExecutionContext());
+ DCHECK(!consumer_);
+ return;
+ }
+ Controller()->GetError(DOMException::Create(DOMExceptionCode::kAbortError));
CancelConsumer();
}
@@ -339,7 +429,7 @@ void BodyStreamBuffer::Close() {
void BodyStreamBuffer::GetError() {
{
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
Controller()->GetError(V8ThrowException::CreateTypeError(
script_state_->GetIsolate(), "network error"));
}
@@ -410,36 +500,85 @@ void BodyStreamBuffer::StopLoading() {
loader_ = nullptr;
}
-BytesConsumer* BodyStreamBuffer::ReleaseHandle() {
- DCHECK(!IsStreamLocked());
- DCHECK(!IsStreamDisturbed());
+base::Optional<bool> BodyStreamBuffer::BooleanStreamOperation(
+ base::Optional<bool> (*predicate)(ScriptState*,
+ ScriptValue,
+ ExceptionState&),
+ ExceptionState& exception_state) {
+ if (stream_broken_) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ "Body stream has suffered a fatal error and cannot be inspected");
+ return base::nullopt;
+ }
+ ScriptState::Scope scope(script_state_);
+ base::Optional<bool> result =
+ predicate(script_state_, Stream(), exception_state);
+ if (exception_state.HadException()) {
+ stream_broken_ = true;
+ return base::nullopt;
+ }
+ return result;
+}
+
+void BodyStreamBuffer::RetainWrapperUntilV8WrapperGetReturnedToV8(
+ ScriptState* script_state) {
+ ExecutionContext::From(script_state)
+ ->GetTaskRunner(TaskType::kInternalDefault)
+ ->PostTask(
+ FROM_HERE,
+ WTF::Bind(Noop, ScriptValue(script_state, ToV8(this, script_state))));
+}
+
+BytesConsumer* BodyStreamBuffer::ReleaseHandle(
+ ExceptionState& exception_state) {
+ DCHECK(!IsStreamLockedForDCheck());
+ DCHECK(!IsStreamDisturbedForDCheck());
+
+ if (stream_broken_) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ "Body stream has suffered a fatal error and cannot be inspected");
+ return nullptr;
+ }
if (made_from_readable_stream_) {
- ScriptState::Scope scope(script_state_.get());
- // We need to have |reader| alive by some means (as written in
- // ReadableStreamDataConsumerHandle). Based on the following facts
- // - This function is used only from tee and startLoading.
- // - This branch cannot be taken when called from tee.
- // - startLoading makes hasPendingActivity return true while loading.
- // , we don't need to keep the reader explicitly.
- NonThrowableExceptionState exception_state;
+ ScriptState::Scope scope(script_state_);
+ // We need to have |reader| alive by some means (as noted in
+ // ReadableStreamDataConsumerHandle). Based on the following facts:
+ // - This function is used only from Tee and StartLoading.
+ // - This branch cannot be taken when called from Tee.
+ // - StartLoading makes HasPendingActivity return true while loading.
+ // - ReadableStream holds a reference to |reader| inside JS.
+ // we don't need to keep the reader explicitly.
ScriptValue reader = ReadableStreamOperations::GetReader(
- script_state_.get(), Stream(), exception_state);
- return new ReadableStreamBytesConsumer(script_state_.get(), reader);
+ script_state_, Stream(), exception_state);
+ if (exception_state.HadException()) {
+ stream_broken_ = true;
+ return nullptr;
+ }
+ return new ReadableStreamBytesConsumer(script_state_, reader);
}
- // We need to call these before calling closeAndLockAndDisturb.
- const bool is_closed = IsStreamClosed();
- const bool is_errored = IsStreamErrored();
+ // We need to call these before calling CloseAndLockAndDisturb.
+ const base::Optional<bool> is_closed = IsStreamClosed(exception_state);
+ if (exception_state.HadException())
+ return nullptr;
+ const base::Optional<bool> is_errored = IsStreamErrored(exception_state);
+ if (exception_state.HadException())
+ return nullptr;
+
BytesConsumer* consumer = consumer_.Release();
- CloseAndLockAndDisturb();
+ CloseAndLockAndDisturb(exception_state);
+ if (exception_state.HadException())
+ return nullptr;
- if (is_closed) {
+ if (is_closed.value()) {
// Note that the stream cannot be "draining", because it doesn't have
// the internal buffer.
return BytesConsumer::CreateClosed();
}
- if (is_errored)
+ if (is_errored.value())
return BytesConsumer::CreateErrored(BytesConsumer::Error("error"));
DCHECK(consumer);
diff --git a/chromium/third_party/blink/renderer/core/fetch/body_stream_buffer.h b/chromium/third_party/blink/renderer/core/fetch/body_stream_buffer.h
index 9bbcc178e34..4e5e782909d 100644
--- a/chromium/third_party/blink/renderer/core/fetch/body_stream_buffer.h
+++ b/chromium/third_party/blink/renderer/core/fetch/body_stream_buffer.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_BODY_STREAM_BUFFER_H_
#include <memory>
+#include "base/optional.h"
#include "third_party/blink/public/platform/web_data_consumer_handle.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
@@ -15,11 +16,13 @@
#include "third_party/blink/renderer/core/fetch/bytes_consumer.h"
#include "third_party/blink/renderer/core/fetch/fetch_data_loader.h"
#include "third_party/blink/renderer/core/streams/underlying_source_base.h"
+#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
class EncodedFormData;
+class ExceptionState;
class ScriptState;
class CORE_EXPORT BodyStreamBuffer final : public UnderlyingSourceBase,
@@ -36,16 +39,19 @@ class CORE_EXPORT BodyStreamBuffer final : public UnderlyingSourceBase,
AbortSignal* /* signal */);
// |ReadableStreamOperations::isReadableStream(stream)| must hold.
// This function must be called with entering an appropriate V8 context.
- BodyStreamBuffer(ScriptState*, ScriptValue stream);
+ BodyStreamBuffer(ScriptState*, ScriptValue stream, ExceptionState&);
ScriptValue Stream();
// Callable only when neither locked nor disturbed.
scoped_refptr<BlobDataHandle> DrainAsBlobDataHandle(
- BytesConsumer::BlobSizePolicy);
- scoped_refptr<EncodedFormData> DrainAsFormData();
- void StartLoading(FetchDataLoader*, FetchDataLoader::Client* /* client */);
- void Tee(BodyStreamBuffer**, BodyStreamBuffer**);
+ BytesConsumer::BlobSizePolicy,
+ ExceptionState&);
+ scoped_refptr<EncodedFormData> DrainAsFormData(ExceptionState&);
+ void StartLoading(FetchDataLoader*,
+ FetchDataLoader::Client* /* client */,
+ ExceptionState&);
+ void Tee(BodyStreamBuffer**, BodyStreamBuffer**, ExceptionState&);
// UnderlyingSourceBase
ScriptPromise pull(ScriptState*) override;
@@ -57,27 +63,32 @@ class CORE_EXPORT BodyStreamBuffer final : public UnderlyingSourceBase,
void OnStateChange() override;
String DebugName() const override { return "BodyStreamBuffer"; }
- bool IsStreamReadable();
- bool IsStreamClosed();
- bool IsStreamErrored();
- bool IsStreamLocked();
- bool IsStreamDisturbed();
- void CloseAndLockAndDisturb();
- ScriptState* GetScriptState() { return script_state_.get(); }
+ base::Optional<bool> IsStreamReadable(ExceptionState&);
+ base::Optional<bool> IsStreamClosed(ExceptionState&);
+ base::Optional<bool> IsStreamErrored(ExceptionState&);
+ base::Optional<bool> IsStreamLocked(ExceptionState&);
+ bool IsStreamLockedForDCheck();
+ base::Optional<bool> IsStreamDisturbed(ExceptionState&);
+ bool IsStreamDisturbedForDCheck();
+ void CloseAndLockAndDisturb(ExceptionState&);
+ ScriptState* GetScriptState() { return script_state_; }
bool IsAborted();
- void Trace(blink::Visitor* visitor) override {
- visitor->Trace(consumer_);
- visitor->Trace(loader_);
- visitor->Trace(signal_);
- UnderlyingSourceBase::Trace(visitor);
- }
+ void Trace(blink::Visitor*) override;
private:
class LoaderClient;
- BytesConsumer* ReleaseHandle();
+ // We need to keep the wrapper alive in order to make
+ // |Stream()| alive. We can create a wrapper in the constructor, but there is
+ // a chance that GC happens after construction happens before the wrapper is
+ // connected to the value returned to the user in the JS world. This function
+ // posts a task with a ScriptPromise containing the wrapper to avoid that.
+ // TODO(yhirano): Remove this once the unified GC is available.
+ void RetainWrapperUntilV8WrapperGetReturnedToV8(ScriptState*);
+
+ BytesConsumer* ReleaseHandle(ExceptionState&);
void Abort();
void Close();
void GetError();
@@ -86,7 +97,20 @@ class CORE_EXPORT BodyStreamBuffer final : public UnderlyingSourceBase,
void EndLoading();
void StopLoading();
- scoped_refptr<ScriptState> script_state_;
+ // Implementation of IsStream*() methods. Delegates to |predicate|, one of the
+ // methods defined in ReadableStreamOperations. Sets |stream_broken_| and
+ // throws if |predicate| throws. Throws an exception if called when
+ // |stream_broken_| is already true.
+ base::Optional<bool> BooleanStreamOperation(
+ base::Optional<bool> (*predicate)(ScriptState*,
+ ScriptValue,
+ ExceptionState&),
+ ExceptionState& exception_state);
+
+ static void Noop(ScriptValue) {}
+
+ Member<ScriptState> script_state_;
+ TraceWrapperV8Reference<v8::Object> stream_;
Member<BytesConsumer> consumer_;
// We need this member to keep it alive while loading.
Member<FetchDataLoader> loader_;
@@ -96,6 +120,7 @@ class CORE_EXPORT BodyStreamBuffer final : public UnderlyingSourceBase,
bool stream_needs_more_ = false;
bool made_from_readable_stream_;
bool in_process_data_ = false;
+ bool stream_broken_ = false;
DISALLOW_COPY_AND_ASSIGN(BodyStreamBuffer);
};
diff --git a/chromium/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc b/chromium/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc
index e65abd5da4e..69528dac237 100644
--- a/chromium/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc
@@ -14,6 +14,7 @@
#include "third_party/blink/renderer/core/fetch/bytes_consumer_test_util.h"
#include "third_party/blink/renderer/core/fetch/form_data_bytes_consumer.h"
#include "third_party/blink/renderer/core/html/forms/form_data.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
#include "third_party/blink/renderer/platform/blob/blob_url.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@@ -24,7 +25,6 @@ namespace blink {
namespace {
-using testing::ByMove;
using testing::InSequence;
using testing::Return;
using testing::_;
@@ -87,6 +87,7 @@ class MockFetchDataLoader : public FetchDataLoader {
TEST_F(BodyStreamBufferTest, Tee) {
V8TestingScope scope;
+ NonThrowableExceptionState exception_state;
Checkpoint checkpoint;
MockFetchDataLoaderClient* client1 = MockFetchDataLoaderClient::Create();
MockFetchDataLoaderClient* client2 = MockFetchDataLoaderClient::Create();
@@ -110,19 +111,21 @@ TEST_F(BodyStreamBufferTest, Tee) {
BodyStreamBuffer* new1;
BodyStreamBuffer* new2;
- buffer->Tee(&new1, &new2);
+ buffer->Tee(&new1, &new2, exception_state);
- EXPECT_TRUE(buffer->IsStreamLocked());
- EXPECT_TRUE(buffer->IsStreamDisturbed());
+ EXPECT_TRUE(buffer->IsStreamLocked(exception_state).value_or(false));
+ EXPECT_TRUE(buffer->IsStreamDisturbed(exception_state).value_or(false));
EXPECT_FALSE(buffer->HasPendingActivity());
checkpoint.Call(0);
- new1->StartLoading(FetchDataLoader::CreateLoaderAsString(), client1);
+ new1->StartLoading(FetchDataLoader::CreateLoaderAsString(), client1,
+ exception_state);
checkpoint.Call(1);
test::RunPendingTasks();
checkpoint.Call(2);
- new2->StartLoading(FetchDataLoader::CreateLoaderAsString(), client2);
+ new2->StartLoading(FetchDataLoader::CreateLoaderAsString(), client2,
+ exception_state);
checkpoint.Call(3);
test::RunPendingTasks();
checkpoint.Call(4);
@@ -130,6 +133,7 @@ TEST_F(BodyStreamBufferTest, Tee) {
TEST_F(BodyStreamBufferTest, TeeFromHandleMadeFromStream) {
V8TestingScope scope;
+ NonThrowableExceptionState exception_state;
ScriptValue stream = EvalWithPrintingError(
scope.GetScriptState(),
"stream = new ReadableStream({start: c => controller = c});"
@@ -150,32 +154,34 @@ TEST_F(BodyStreamBufferTest, TeeFromHandleMadeFromStream) {
EXPECT_CALL(checkpoint, Call(4));
BodyStreamBuffer* buffer =
- new BodyStreamBuffer(scope.GetScriptState(), stream);
+ new BodyStreamBuffer(scope.GetScriptState(), stream, exception_state);
BodyStreamBuffer* new1;
BodyStreamBuffer* new2;
- buffer->Tee(&new1, &new2);
+ buffer->Tee(&new1, &new2, exception_state);
- EXPECT_TRUE(buffer->IsStreamLocked());
+ EXPECT_TRUE(buffer->IsStreamLocked(exception_state).value_or(false));
// Note that this behavior is slightly different from for the behavior of
// a BodyStreamBuffer made from a BytesConsumer. See the above test. In this
// test, the stream will get disturbed when the microtask is performed.
// TODO(yhirano): A uniformed behavior is preferred.
- EXPECT_FALSE(buffer->IsStreamDisturbed());
+ EXPECT_FALSE(buffer->IsStreamDisturbed(exception_state).value_or(true));
EXPECT_FALSE(buffer->HasPendingActivity());
v8::MicrotasksScope::PerformCheckpoint(scope.GetScriptState()->GetIsolate());
- EXPECT_TRUE(buffer->IsStreamLocked());
- EXPECT_TRUE(buffer->IsStreamDisturbed());
+ EXPECT_TRUE(buffer->IsStreamLocked(exception_state).value_or(false));
+ EXPECT_TRUE(buffer->IsStreamDisturbed(exception_state).value_or(false));
EXPECT_FALSE(buffer->HasPendingActivity());
- new1->StartLoading(FetchDataLoader::CreateLoaderAsString(), client1);
+ new1->StartLoading(FetchDataLoader::CreateLoaderAsString(), client1,
+ exception_state);
checkpoint.Call(1);
test::RunPendingTasks();
checkpoint.Call(2);
- new2->StartLoading(FetchDataLoader::CreateLoaderAsString(), client2);
+ new2->StartLoading(FetchDataLoader::CreateLoaderAsString(), client2,
+ exception_state);
checkpoint.Call(3);
test::RunPendingTasks();
checkpoint.Call(4);
@@ -193,15 +199,16 @@ TEST_F(BodyStreamBufferTest, DrainAsBlobDataHandle) {
new BlobBytesConsumer(scope.GetExecutionContext(), blob_data_handle),
nullptr);
- EXPECT_FALSE(buffer->IsStreamLocked());
- EXPECT_FALSE(buffer->IsStreamDisturbed());
+ EXPECT_FALSE(buffer->IsStreamLocked(ASSERT_NO_EXCEPTION).value_or(true));
+ EXPECT_FALSE(buffer->IsStreamDisturbed(ASSERT_NO_EXCEPTION).value_or(true));
EXPECT_FALSE(buffer->HasPendingActivity());
scoped_refptr<BlobDataHandle> output_blob_data_handle =
buffer->DrainAsBlobDataHandle(
- BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize);
+ BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize,
+ ASSERT_NO_EXCEPTION);
- EXPECT_TRUE(buffer->IsStreamLocked());
- EXPECT_TRUE(buffer->IsStreamDisturbed());
+ EXPECT_TRUE(buffer->IsStreamLocked(ASSERT_NO_EXCEPTION).value_or(false));
+ EXPECT_TRUE(buffer->IsStreamDisturbed(ASSERT_NO_EXCEPTION).value_or(false));
EXPECT_FALSE(buffer->HasPendingActivity());
EXPECT_EQ(blob_data_handle, output_blob_data_handle);
}
@@ -213,38 +220,41 @@ TEST_F(BodyStreamBufferTest, DrainAsBlobDataHandleReturnsNull) {
BodyStreamBuffer* buffer =
new BodyStreamBuffer(scope.GetScriptState(), src, nullptr);
- EXPECT_FALSE(buffer->IsStreamLocked());
- EXPECT_FALSE(buffer->IsStreamDisturbed());
+ EXPECT_FALSE(buffer->IsStreamLocked(ASSERT_NO_EXCEPTION).value_or(true));
+ EXPECT_FALSE(buffer->IsStreamDisturbed(ASSERT_NO_EXCEPTION).value_or(true));
EXPECT_FALSE(buffer->HasPendingActivity());
EXPECT_FALSE(buffer->DrainAsBlobDataHandle(
- BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize));
+ BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize,
+ ASSERT_NO_EXCEPTION));
- EXPECT_FALSE(buffer->IsStreamLocked());
- EXPECT_FALSE(buffer->IsStreamDisturbed());
+ EXPECT_FALSE(buffer->IsStreamLocked(ASSERT_NO_EXCEPTION).value_or(true));
+ EXPECT_FALSE(buffer->IsStreamDisturbed(ASSERT_NO_EXCEPTION).value_or(true));
EXPECT_FALSE(buffer->HasPendingActivity());
}
TEST_F(BodyStreamBufferTest,
DrainAsBlobFromBufferMadeFromBufferMadeFromStream) {
V8TestingScope scope;
+ NonThrowableExceptionState exception_state;
ScriptValue stream =
EvalWithPrintingError(scope.GetScriptState(), "new ReadableStream()");
BodyStreamBuffer* buffer =
- new BodyStreamBuffer(scope.GetScriptState(), stream);
+ new BodyStreamBuffer(scope.GetScriptState(), stream, exception_state);
EXPECT_FALSE(buffer->HasPendingActivity());
- EXPECT_FALSE(buffer->IsStreamLocked());
- EXPECT_FALSE(buffer->IsStreamDisturbed());
- EXPECT_TRUE(buffer->IsStreamReadable());
+ EXPECT_FALSE(buffer->IsStreamLocked(exception_state).value_or(true));
+ EXPECT_FALSE(buffer->IsStreamDisturbed(exception_state).value_or(true));
+ EXPECT_TRUE(buffer->IsStreamReadable(exception_state).value_or(false));
EXPECT_FALSE(buffer->DrainAsBlobDataHandle(
- BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize));
+ BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize,
+ exception_state));
EXPECT_FALSE(buffer->HasPendingActivity());
- EXPECT_FALSE(buffer->IsStreamLocked());
- EXPECT_FALSE(buffer->IsStreamDisturbed());
- EXPECT_TRUE(buffer->IsStreamReadable());
+ EXPECT_FALSE(buffer->IsStreamLocked(exception_state).value_or(true));
+ EXPECT_FALSE(buffer->IsStreamDisturbed(exception_state).value_or(true));
+ EXPECT_TRUE(buffer->IsStreamReadable(exception_state).value_or(false));
}
TEST_F(BodyStreamBufferTest, DrainAsFormData) {
@@ -260,13 +270,14 @@ TEST_F(BodyStreamBufferTest, DrainAsFormData) {
new FormDataBytesConsumer(scope.GetExecutionContext(), input_form_data),
nullptr);
- EXPECT_FALSE(buffer->IsStreamLocked());
- EXPECT_FALSE(buffer->IsStreamDisturbed());
+ EXPECT_FALSE(buffer->IsStreamLocked(ASSERT_NO_EXCEPTION).value_or(true));
+ EXPECT_FALSE(buffer->IsStreamDisturbed(ASSERT_NO_EXCEPTION).value_or(true));
EXPECT_FALSE(buffer->HasPendingActivity());
- scoped_refptr<EncodedFormData> output_form_data = buffer->DrainAsFormData();
+ scoped_refptr<EncodedFormData> output_form_data =
+ buffer->DrainAsFormData(ASSERT_NO_EXCEPTION);
- EXPECT_TRUE(buffer->IsStreamLocked());
- EXPECT_TRUE(buffer->IsStreamDisturbed());
+ EXPECT_TRUE(buffer->IsStreamLocked(ASSERT_NO_EXCEPTION).value_or(false));
+ EXPECT_TRUE(buffer->IsStreamDisturbed(ASSERT_NO_EXCEPTION).value_or(false));
EXPECT_FALSE(buffer->HasPendingActivity());
EXPECT_EQ(output_form_data->FlattenToString(),
input_form_data->FlattenToString());
@@ -279,36 +290,37 @@ TEST_F(BodyStreamBufferTest, DrainAsFormDataReturnsNull) {
BodyStreamBuffer* buffer =
new BodyStreamBuffer(scope.GetScriptState(), src, nullptr);
- EXPECT_FALSE(buffer->IsStreamLocked());
- EXPECT_FALSE(buffer->IsStreamDisturbed());
+ EXPECT_FALSE(buffer->IsStreamLocked(ASSERT_NO_EXCEPTION).value_or(true));
+ EXPECT_FALSE(buffer->IsStreamDisturbed(ASSERT_NO_EXCEPTION).value_or(true));
EXPECT_FALSE(buffer->HasPendingActivity());
- EXPECT_FALSE(buffer->DrainAsFormData());
+ EXPECT_FALSE(buffer->DrainAsFormData(ASSERT_NO_EXCEPTION));
- EXPECT_FALSE(buffer->IsStreamLocked());
- EXPECT_FALSE(buffer->IsStreamDisturbed());
+ EXPECT_FALSE(buffer->IsStreamLocked(ASSERT_NO_EXCEPTION).value_or(true));
+ EXPECT_FALSE(buffer->IsStreamDisturbed(ASSERT_NO_EXCEPTION).value_or(true));
EXPECT_FALSE(buffer->HasPendingActivity());
}
TEST_F(BodyStreamBufferTest,
DrainAsFormDataFromBufferMadeFromBufferMadeFromStream) {
V8TestingScope scope;
+ NonThrowableExceptionState exception_state;
ScriptValue stream =
EvalWithPrintingError(scope.GetScriptState(), "new ReadableStream()");
BodyStreamBuffer* buffer =
- new BodyStreamBuffer(scope.GetScriptState(), stream);
+ new BodyStreamBuffer(scope.GetScriptState(), stream, exception_state);
EXPECT_FALSE(buffer->HasPendingActivity());
- EXPECT_FALSE(buffer->IsStreamLocked());
- EXPECT_FALSE(buffer->IsStreamDisturbed());
- EXPECT_TRUE(buffer->IsStreamReadable());
+ EXPECT_FALSE(buffer->IsStreamLocked(exception_state).value_or(true));
+ EXPECT_FALSE(buffer->IsStreamDisturbed(exception_state).value_or(true));
+ EXPECT_TRUE(buffer->IsStreamReadable(exception_state).value_or(false));
- EXPECT_FALSE(buffer->DrainAsFormData());
+ EXPECT_FALSE(buffer->DrainAsFormData(exception_state));
EXPECT_FALSE(buffer->HasPendingActivity());
- EXPECT_FALSE(buffer->IsStreamLocked());
- EXPECT_FALSE(buffer->IsStreamDisturbed());
- EXPECT_TRUE(buffer->IsStreamReadable());
+ EXPECT_FALSE(buffer->IsStreamLocked(exception_state).value_or(true));
+ EXPECT_FALSE(buffer->IsStreamDisturbed(exception_state).value_or(true));
+ EXPECT_TRUE(buffer->IsStreamReadable(exception_state).value_or(false));
}
TEST_F(BodyStreamBufferTest, LoadBodyStreamBufferAsArrayBuffer) {
@@ -330,18 +342,19 @@ TEST_F(BodyStreamBufferTest, LoadBodyStreamBufferAsArrayBuffer) {
src->Add(BytesConsumerCommand(BytesConsumerCommand::kDone));
BodyStreamBuffer* buffer =
new BodyStreamBuffer(scope.GetScriptState(), src, nullptr);
- buffer->StartLoading(FetchDataLoader::CreateLoaderAsArrayBuffer(), client);
+ buffer->StartLoading(FetchDataLoader::CreateLoaderAsArrayBuffer(), client,
+ ASSERT_NO_EXCEPTION);
- EXPECT_TRUE(buffer->IsStreamLocked());
- EXPECT_TRUE(buffer->IsStreamDisturbed());
+ EXPECT_TRUE(buffer->IsStreamLocked(ASSERT_NO_EXCEPTION).value_or(false));
+ EXPECT_TRUE(buffer->IsStreamDisturbed(ASSERT_NO_EXCEPTION).value_or(false));
EXPECT_TRUE(buffer->HasPendingActivity());
checkpoint.Call(1);
test::RunPendingTasks();
checkpoint.Call(2);
- EXPECT_TRUE(buffer->IsStreamLocked());
- EXPECT_TRUE(buffer->IsStreamDisturbed());
+ EXPECT_TRUE(buffer->IsStreamLocked(ASSERT_NO_EXCEPTION).value_or(false));
+ EXPECT_TRUE(buffer->IsStreamDisturbed(ASSERT_NO_EXCEPTION).value_or(true));
EXPECT_FALSE(buffer->HasPendingActivity());
ASSERT_TRUE(array_buffer);
EXPECT_EQ("hello", String(static_cast<const char*>(array_buffer->Data()),
@@ -368,18 +381,18 @@ TEST_F(BodyStreamBufferTest, LoadBodyStreamBufferAsBlob) {
BodyStreamBuffer* buffer =
new BodyStreamBuffer(scope.GetScriptState(), src, nullptr);
buffer->StartLoading(FetchDataLoader::CreateLoaderAsBlobHandle("text/plain"),
- client);
+ client, ASSERT_NO_EXCEPTION);
- EXPECT_TRUE(buffer->IsStreamLocked());
- EXPECT_TRUE(buffer->IsStreamDisturbed());
+ EXPECT_TRUE(buffer->IsStreamLocked(ASSERT_NO_EXCEPTION).value_or(false));
+ EXPECT_TRUE(buffer->IsStreamDisturbed(ASSERT_NO_EXCEPTION).value_or(false));
EXPECT_TRUE(buffer->HasPendingActivity());
checkpoint.Call(1);
test::RunPendingTasks();
checkpoint.Call(2);
- EXPECT_TRUE(buffer->IsStreamLocked());
- EXPECT_TRUE(buffer->IsStreamDisturbed());
+ EXPECT_TRUE(buffer->IsStreamLocked(ASSERT_NO_EXCEPTION).value_or(false));
+ EXPECT_TRUE(buffer->IsStreamDisturbed(ASSERT_NO_EXCEPTION).value_or(false));
EXPECT_FALSE(buffer->HasPendingActivity());
EXPECT_EQ(5u, blob_data_handle->size());
}
@@ -401,18 +414,19 @@ TEST_F(BodyStreamBufferTest, LoadBodyStreamBufferAsString) {
src->Add(BytesConsumerCommand(BytesConsumerCommand::kDone));
BodyStreamBuffer* buffer =
new BodyStreamBuffer(scope.GetScriptState(), src, nullptr);
- buffer->StartLoading(FetchDataLoader::CreateLoaderAsString(), client);
+ buffer->StartLoading(FetchDataLoader::CreateLoaderAsString(), client,
+ ASSERT_NO_EXCEPTION);
- EXPECT_TRUE(buffer->IsStreamLocked());
- EXPECT_TRUE(buffer->IsStreamDisturbed());
+ EXPECT_TRUE(buffer->IsStreamLocked(ASSERT_NO_EXCEPTION).value_or(false));
+ EXPECT_TRUE(buffer->IsStreamDisturbed(ASSERT_NO_EXCEPTION).value_or(false));
EXPECT_TRUE(buffer->HasPendingActivity());
checkpoint.Call(1);
test::RunPendingTasks();
checkpoint.Call(2);
- EXPECT_TRUE(buffer->IsStreamLocked());
- EXPECT_TRUE(buffer->IsStreamDisturbed());
+ EXPECT_TRUE(buffer->IsStreamLocked(ASSERT_NO_EXCEPTION).value_or(false));
+ EXPECT_TRUE(buffer->IsStreamDisturbed(ASSERT_NO_EXCEPTION).value_or(false));
EXPECT_FALSE(buffer->HasPendingActivity());
}
@@ -429,18 +443,19 @@ TEST_F(BodyStreamBufferTest, LoadClosedHandle) {
BodyStreamBuffer* buffer = new BodyStreamBuffer(
scope.GetScriptState(), BytesConsumer::CreateClosed(), nullptr);
- EXPECT_TRUE(buffer->IsStreamClosed());
+ EXPECT_TRUE(buffer->IsStreamClosed(ASSERT_NO_EXCEPTION).value_or(false));
- EXPECT_FALSE(buffer->IsStreamLocked());
- EXPECT_FALSE(buffer->IsStreamDisturbed());
+ EXPECT_FALSE(buffer->IsStreamLocked(ASSERT_NO_EXCEPTION).value_or(true));
+ EXPECT_FALSE(buffer->IsStreamDisturbed(ASSERT_NO_EXCEPTION).value_or(true));
EXPECT_FALSE(buffer->HasPendingActivity());
checkpoint.Call(1);
- buffer->StartLoading(FetchDataLoader::CreateLoaderAsString(), client);
+ buffer->StartLoading(FetchDataLoader::CreateLoaderAsString(), client,
+ ASSERT_NO_EXCEPTION);
checkpoint.Call(2);
- EXPECT_TRUE(buffer->IsStreamLocked());
- EXPECT_TRUE(buffer->IsStreamDisturbed());
+ EXPECT_TRUE(buffer->IsStreamLocked(ASSERT_NO_EXCEPTION).value_or(false));
+ EXPECT_TRUE(buffer->IsStreamDisturbed(ASSERT_NO_EXCEPTION).value_or(false));
EXPECT_FALSE(buffer->HasPendingActivity());
}
@@ -458,18 +473,19 @@ TEST_F(BodyStreamBufferTest, LoadErroredHandle) {
scope.GetScriptState(),
BytesConsumer::CreateErrored(BytesConsumer::Error()), nullptr);
- EXPECT_TRUE(buffer->IsStreamErrored());
+ EXPECT_TRUE(buffer->IsStreamErrored(ASSERT_NO_EXCEPTION).value_or(false));
- EXPECT_FALSE(buffer->IsStreamLocked());
- EXPECT_FALSE(buffer->IsStreamDisturbed());
+ EXPECT_FALSE(buffer->IsStreamLocked(ASSERT_NO_EXCEPTION).value_or(true));
+ EXPECT_FALSE(buffer->IsStreamDisturbed(ASSERT_NO_EXCEPTION).value_or(true));
EXPECT_FALSE(buffer->HasPendingActivity());
checkpoint.Call(1);
- buffer->StartLoading(FetchDataLoader::CreateLoaderAsString(), client);
+ buffer->StartLoading(FetchDataLoader::CreateLoaderAsString(), client,
+ ASSERT_NO_EXCEPTION);
checkpoint.Call(2);
- EXPECT_TRUE(buffer->IsStreamLocked());
- EXPECT_TRUE(buffer->IsStreamDisturbed());
+ EXPECT_TRUE(buffer->IsStreamLocked(ASSERT_NO_EXCEPTION).value_or(false));
+ EXPECT_TRUE(buffer->IsStreamDisturbed(ASSERT_NO_EXCEPTION).value_or(false));
EXPECT_FALSE(buffer->HasPendingActivity());
}
@@ -490,7 +506,8 @@ TEST_F(BodyStreamBufferTest, LoaderShouldBeKeptAliveByBodyStreamBuffer) {
src->Add(BytesConsumerCommand(BytesConsumerCommand::kDone));
Persistent<BodyStreamBuffer> buffer =
new BodyStreamBuffer(scope.GetScriptState(), src, nullptr);
- buffer->StartLoading(FetchDataLoader::CreateLoaderAsString(), client);
+ buffer->StartLoading(FetchDataLoader::CreateLoaderAsString(), client,
+ ASSERT_NO_EXCEPTION);
ThreadState::Current()->CollectAllGarbage();
checkpoint.Call(1);
@@ -596,7 +613,7 @@ TEST_F(BodyStreamBufferTest,
signal->SignalAbort();
checkpoint.Call(2);
- buffer->StartLoading(loader, client);
+ buffer->StartLoading(loader, client, ASSERT_NO_EXCEPTION);
checkpoint.Call(3);
}
@@ -627,7 +644,7 @@ TEST_F(BodyStreamBufferTest, AbortAfterStartLoadingCallsDataLoaderClientAbort) {
new BodyStreamBuffer(scope.GetScriptState(), src, signal);
checkpoint.Call(1);
- buffer->StartLoading(loader, client);
+ buffer->StartLoading(loader, client, ASSERT_NO_EXCEPTION);
checkpoint.Call(2);
signal->SignalAbort();
@@ -662,7 +679,7 @@ TEST_F(BodyStreamBufferTest,
new BodyStreamBuffer(scope.GetScriptState(), src, signal);
checkpoint.Call(1);
- buffer->StartLoading(loader, client);
+ buffer->StartLoading(loader, client, ASSERT_NO_EXCEPTION);
test::RunPendingTasks();
checkpoint.Call(2);
diff --git a/chromium/third_party/blink/renderer/core/fetch/data_consumer_handle_test_util.h b/chromium/third_party/blink/renderer/core/fetch/data_consumer_handle_test_util.h
index df71454b446..a7a310295e4 100644
--- a/chromium/third_party/blink/renderer/core/fetch/data_consumer_handle_test_util.h
+++ b/chromium/third_party/blink/renderer/core/fetch/data_consumer_handle_test_util.h
@@ -64,7 +64,7 @@ class DataConsumerHandleTestUtil {
WebThreadSupportingGC* GetThread() { return thread_.get(); }
ExecutionContext* GetExecutionContext() { return execution_context_.Get(); }
- ScriptState* GetScriptState() { return script_state_.get(); }
+ ScriptState* GetScriptState() { return script_state_; }
v8::Isolate* GetIsolate() { return isolate_holder_->isolate(); }
private:
@@ -76,7 +76,7 @@ class DataConsumerHandleTestUtil {
std::unique_ptr<WaitableEvent> waitable_event_;
Persistent<NullExecutionContext> execution_context_;
std::unique_ptr<gin::IsolateHolder> isolate_holder_;
- scoped_refptr<ScriptState> script_state_;
+ Persistent<ScriptState> script_state_;
};
class ThreadingTestBase : public ThreadSafeRefCounted<ThreadingTestBase> {
diff --git a/chromium/third_party/blink/renderer/core/fetch/fetch_data_loader.cc b/chromium/third_party/blink/renderer/core/fetch/fetch_data_loader.cc
index 66d289894e6..00c4d01d2f6 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_data_loader.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_data_loader.cc
@@ -519,21 +519,24 @@ class FetchDataLoaderAsDataPipe final : public FetchDataLoader,
if (result == BytesConsumer::Result::kShouldWait)
return;
if (result == BytesConsumer::Result::kOk) {
- DCHECK_GT(available, 0UL);
- uint32_t num_bytes = available;
- MojoResult mojo_result = out_data_pipe_->WriteData(
- buffer, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE);
- if (mojo_result == MOJO_RESULT_OK) {
- result = consumer_->EndRead(num_bytes);
- } else if (mojo_result == MOJO_RESULT_SHOULD_WAIT) {
+ if (available == 0) {
result = consumer_->EndRead(0);
- should_wait = true;
- data_pipe_watcher_.ArmOrNotify();
} else {
- result = consumer_->EndRead(0);
- StopInternal();
- client_->DidFetchDataLoadFailed();
- return;
+ uint32_t num_bytes = available;
+ MojoResult mojo_result = out_data_pipe_->WriteData(
+ buffer, &num_bytes, MOJO_WRITE_DATA_FLAG_NONE);
+ if (mojo_result == MOJO_RESULT_OK) {
+ result = consumer_->EndRead(num_bytes);
+ } else if (mojo_result == MOJO_RESULT_SHOULD_WAIT) {
+ result = consumer_->EndRead(0);
+ should_wait = true;
+ data_pipe_watcher_.ArmOrNotify();
+ } else {
+ result = consumer_->EndRead(0);
+ StopInternal();
+ client_->DidFetchDataLoadFailed();
+ return;
+ }
}
}
switch (result) {
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 ee6677cdbcf..442e88fc9e0 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_manager.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_manager.cc
@@ -9,11 +9,9 @@
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "third_party/blink/public/platform/web_cors.h"
#include "third_party/blink/public/platform/web_url_request.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fetch/body.h"
#include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
@@ -34,11 +32,13 @@
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.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/bindings/v8_throw_exception.h"
#include "third_party/blink/renderer/platform/exported/wrapped_resource_response.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/loader/cors/cors.h"
+#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_utils.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
@@ -187,7 +187,7 @@ class FetchManager::Loader final
void DidFail(const ResourceError&) override;
void DidFailRedirectCheck() override;
- void Start();
+ void Start(ExceptionState&);
void Dispose();
void Abort();
@@ -317,9 +317,9 @@ class FetchManager::Loader final
bool is_isolated_world,
AbortSignal*);
- void PerformSchemeFetch();
+ void PerformSchemeFetch(ExceptionState&);
void PerformNetworkError(const String& message);
- void PerformHTTPFetch();
+ void PerformHTTPFetch(ExceptionState&);
void PerformDataFetch();
void Failed(const String& message);
void NotifyFinished();
@@ -589,7 +589,7 @@ void FetchManager::Loader::LoadSucceeded() {
NotifyFinished();
}
-void FetchManager::Loader::Start() {
+void FetchManager::Loader::Start(ExceptionState& exception_state) {
// "1. If |request|'s url contains a Known HSTS Host, modify it per the
// requirements of the 'URI [sic] Loading and Port Mapping' chapter of HTTP
// Strict Transport Security."
@@ -635,7 +635,7 @@ void FetchManager::Loader::Start() {
fetch_request_data_->SameOriginDataURLFlag()) ||
(fetch_request_data_->Mode() == FetchRequestMode::kNavigate)) {
// "The result of performing a scheme fetch using request."
- PerformSchemeFetch();
+ PerformSchemeFetch(exception_state);
return;
}
@@ -665,7 +665,7 @@ void FetchManager::Loader::Start() {
// "Set |request|'s response tainting to |opaque|."
fetch_request_data_->SetResponseTainting(FetchRequestData::kOpaqueTainting);
// "The result of performing a scheme fetch using |request|."
- PerformSchemeFetch();
+ PerformSchemeFetch(exception_state);
return;
}
@@ -686,11 +686,10 @@ void FetchManager::Loader::Start() {
// "The result of performing an HTTP fetch using |request| with the
// |CORS flag| set."
- PerformHTTPFetch();
+ PerformHTTPFetch(exception_state);
}
void FetchManager::Loader::Dispose() {
- probe::detachClientRequest(execution_context_, this);
// Prevent notification
fetch_manager_ = nullptr;
if (threadable_loader_) {
@@ -707,7 +706,7 @@ void FetchManager::Loader::Dispose() {
void FetchManager::Loader::Abort() {
if (resolver_) {
- resolver_->Reject(DOMException::Create(kAbortError));
+ resolver_->Reject(DOMException::Create(DOMExceptionCode::kAbortError));
resolver_.Clear();
}
if (threadable_loader_) {
@@ -719,14 +718,16 @@ void FetchManager::Loader::Abort() {
NotifyFinished();
}
-void FetchManager::Loader::PerformSchemeFetch() {
+void FetchManager::Loader::PerformSchemeFetch(ExceptionState& exception_state) {
// "To perform a scheme fetch using |request|, switch on |request|'s url's
// scheme, and run the associated steps:"
if (SchemeRegistry::ShouldTreatURLSchemeAsSupportingFetchAPI(
fetch_request_data_->Url().Protocol()) ||
fetch_request_data_->Url().ProtocolIs("blob")) {
// "Return the result of performing an HTTP fetch using |request|."
- PerformHTTPFetch();
+ PerformHTTPFetch(exception_state);
+ if (exception_state.HadException())
+ return;
} else if (fetch_request_data_->Url().ProtocolIsData()) {
PerformDataFetch();
} else {
@@ -742,7 +743,7 @@ void FetchManager::Loader::PerformNetworkError(const String& message) {
Failed(message);
}
-void FetchManager::Loader::PerformHTTPFetch() {
+void FetchManager::Loader::PerformHTTPFetch(ExceptionState& exception_state) {
// CORS preflight fetch procedure is implemented inside
// DocumentThreadableLoader.
@@ -781,11 +782,16 @@ void FetchManager::Loader::PerformHTTPFetch() {
if (fetch_request_data_->Method() != HTTPNames::GET &&
fetch_request_data_->Method() != HTTPNames::HEAD) {
- if (fetch_request_data_->Buffer())
- request.SetHTTPBody(fetch_request_data_->Buffer()->DrainAsFormData());
+ if (fetch_request_data_->Buffer()) {
+ request.SetHTTPBody(
+ fetch_request_data_->Buffer()->DrainAsFormData(exception_state));
+ if (exception_state.HadException())
+ return;
+ }
}
request.SetCacheMode(fetch_request_data_->CacheMode());
request.SetFetchRedirectMode(fetch_request_data_->Redirect());
+ request.SetFetchImportanceMode(fetch_request_data_->Importance());
request.SetUseStreamOnResponse(true);
request.SetExternalRequestStateFromRequestorAddressSpace(
execution_context_->GetSecurityContext().AddressSpace());
@@ -837,6 +843,7 @@ void FetchManager::Loader::PerformHTTPFetch() {
// and the |CORS flag| is unset, and unset otherwise."
ResourceLoaderOptions resource_loader_options;
+ resource_loader_options.initiator_info.name = FetchInitiatorTypeNames::fetch;
resource_loader_options.data_buffering_policy = kDoNotBufferData;
resource_loader_options.security_origin = fetch_request_data_->Origin().get();
if (fetch_request_data_->URLLoaderFactory()) {
@@ -869,6 +876,7 @@ void FetchManager::Loader::PerformDataFetch() {
request.SetHTTPMethod(fetch_request_data_->Method());
request.SetFetchCredentialsMode(network::mojom::FetchCredentialsMode::kOmit);
request.SetFetchRedirectMode(FetchRedirectMode::kError);
+ request.SetFetchImportanceMode(fetch_request_data_->Importance());
// We intentionally skip 'setExternalRequestStateFromRequestorAddressSpace',
// as 'data:' can never be external.
@@ -918,13 +926,14 @@ FetchManager::FetchManager(ExecutionContext* execution_context)
ScriptPromise FetchManager::Fetch(ScriptState* script_state,
FetchRequestData* request,
- AbortSignal* signal) {
+ AbortSignal* signal,
+ ExceptionState& exception_state) {
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
DCHECK(signal);
if (signal->aborted()) {
- resolver->Reject(DOMException::Create(kAbortError));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kAbortError));
return promise;
}
@@ -936,7 +945,9 @@ ScriptPromise FetchManager::Fetch(ScriptState* script_state,
loaders_.insert(loader);
signal->AddAlgorithm(WTF::Bind(&Loader::Abort, WrapWeakPersistent(loader)));
// TODO(ricea): Reject the Response body with AbortError, not TypeError.
- loader->Start();
+ loader->Start(exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
return promise;
}
diff --git a/chromium/third_party/blink/renderer/core/fetch/fetch_manager.h b/chromium/third_party/blink/renderer/core/fetch/fetch_manager.h
index 9081a7a5316..f6e04ff36a4 100644
--- a/chromium/third_party/blink/renderer/core/fetch/fetch_manager.h
+++ b/chromium/third_party/blink/renderer/core/fetch/fetch_manager.h
@@ -13,6 +13,7 @@
namespace blink {
class AbortSignal;
+class ExceptionState;
class ExecutionContext;
class FetchRequestData;
class ScriptState;
@@ -23,7 +24,10 @@ class CORE_EXPORT FetchManager final : public GarbageCollected<FetchManager>,
public:
static FetchManager* Create(ExecutionContext*);
- ScriptPromise Fetch(ScriptState*, FetchRequestData*, AbortSignal*);
+ ScriptPromise Fetch(ScriptState*,
+ FetchRequestData*,
+ AbortSignal*,
+ ExceptionState&);
void ContextDestroyed(ExecutionContext*) override;
void Trace(blink::Visitor*) override;
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 05a28f16d5a..de775ac28cc 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
@@ -4,15 +4,16 @@
#include "third_party/blink/renderer/core/fetch/fetch_request_data.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_request.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h"
+#include "third_party/blink/public/platform/web_http_body.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fetch/blob_bytes_consumer.h"
-#include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
#include "third_party/blink/renderer/core/fetch/bytes_consumer.h"
#include "third_party/blink/renderer/core/fetch/fetch_header_list.h"
#include "third_party/blink/renderer/core/fetch/form_data_bytes_consumer.h"
#include "third_party/blink/renderer/core/loader/threadable_loader.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/loader/fetch/resource_loader_options.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
@@ -57,6 +58,7 @@ FetchRequestData* FetchRequestData::Create(
request->SetMIMEType(request->header_list_->ExtractMIMEType());
request->SetIntegrity(web_request.Integrity());
request->SetKeepalive(web_request.Keepalive());
+ request->SetIsHistoryNavigation(web_request.IsHistoryNavigation());
return request;
}
@@ -76,16 +78,21 @@ FetchRequestData* FetchRequestData::CloneExceptBody() {
request->response_tainting_ = response_tainting_;
request->mime_type_ = mime_type_;
request->integrity_ = integrity_;
+ request->importance_ = importance_;
request->keepalive_ = keepalive_;
+ request->is_history_navigation_ = is_history_navigation_;
return request;
}
-FetchRequestData* FetchRequestData::Clone(ScriptState* script_state) {
+FetchRequestData* FetchRequestData::Clone(ScriptState* script_state,
+ ExceptionState& exception_state) {
FetchRequestData* request = FetchRequestData::CloneExceptBody();
if (buffer_) {
BodyStreamBuffer* new1 = nullptr;
BodyStreamBuffer* new2 = nullptr;
- buffer_->Tee(&new1, &new2);
+ buffer_->Tee(&new1, &new2, exception_state);
+ if (exception_state.HadException())
+ return nullptr;
buffer_ = new1;
request->buffer_ = new2;
}
@@ -95,13 +102,16 @@ FetchRequestData* FetchRequestData::Clone(ScriptState* script_state) {
return request;
}
-FetchRequestData* FetchRequestData::Pass(ScriptState* script_state) {
+FetchRequestData* FetchRequestData::Pass(ScriptState* script_state,
+ ExceptionState& exception_state) {
FetchRequestData* request = FetchRequestData::CloneExceptBody();
if (buffer_) {
request->buffer_ = buffer_;
buffer_ = new BodyStreamBuffer(script_state, BytesConsumer::CreateClosed(),
nullptr /* AbortSignal */);
- buffer_->CloseAndLockAndDisturb();
+ buffer_->CloseAndLockAndDisturb(exception_state);
+ if (exception_state.HadException())
+ return nullptr;
}
request->url_loader_factory_ = std::move(url_loader_factory_);
return request;
@@ -119,6 +129,7 @@ FetchRequestData::FetchRequestData()
credentials_(network::mojom::FetchCredentialsMode::kOmit),
cache_mode_(mojom::FetchCacheMode::kDefault),
redirect_(network::mojom::FetchRedirectMode::kFollow),
+ importance_(mojom::FetchImportanceMode::kImportanceAuto),
response_tainting_(kBasicTainting),
keepalive_(false) {}
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 b46b9e05d88..9db2e759c0c 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
@@ -10,18 +10,20 @@
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "services/network/public/mojom/url_loader_factory.mojom-blink.h"
#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_request.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h"
#include "third_party/blink/public/platform/web_url_request.h"
+#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/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/referrer.h"
#include "third_party/blink/renderer/platform/weborigin/referrer_policy.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
-class BodyStreamBuffer;
+class ExceptionState;
class FetchHeaderList;
class SecurityOrigin;
class ScriptState;
@@ -35,8 +37,8 @@ class FetchRequestData final
static FetchRequestData* Create();
static FetchRequestData* Create(ScriptState*, const WebServiceWorkerRequest&);
// Call Request::refreshBody() after calling clone() or pass().
- FetchRequestData* Clone(ScriptState*);
- FetchRequestData* Pass(ScriptState*);
+ FetchRequestData* Clone(ScriptState*, ExceptionState&);
+ FetchRequestData* Pass(ScriptState*, ExceptionState&);
~FetchRequestData();
void SetMethod(AtomicString method) { method_ = method; }
@@ -75,6 +77,10 @@ class FetchRequestData final
redirect_ = redirect;
}
network::mojom::FetchRedirectMode Redirect() const { return redirect_; }
+ void SetImportance(mojom::FetchImportanceMode importance) {
+ importance_ = importance;
+ }
+ mojom::FetchImportanceMode Importance() const { return importance_; }
void SetResponseTainting(Tainting tainting) { response_tainting_ = tainting; }
Tainting ResponseTainting() const { return response_tainting_; }
FetchHeaderList* HeaderList() const { return header_list_.Get(); }
@@ -90,6 +96,8 @@ class FetchRequestData final
void SetIntegrity(const String& integrity) { integrity_ = integrity; }
bool Keepalive() const { return keepalive_; }
void SetKeepalive(bool b) { keepalive_ = b; }
+ bool IsHistoryNavigation() const { return is_history_navigation_; }
+ void SetIsHistoryNavigation(bool b) { is_history_navigation_ = b; }
network::mojom::blink::URLLoaderFactory* URLLoaderFactory() const {
return url_loader_factory_.get();
@@ -132,13 +140,15 @@ class FetchRequestData final
// worker.
mojom::FetchCacheMode cache_mode_;
network::mojom::FetchRedirectMode redirect_;
+ mojom::FetchImportanceMode importance_;
// FIXME: Support m_useURLCredentialsFlag;
// FIXME: Support m_redirectCount;
Tainting response_tainting_;
- Member<BodyStreamBuffer> buffer_;
+ TraceWrapperMember<BodyStreamBuffer> buffer_;
String mime_type_;
String integrity_;
bool keepalive_;
+ bool is_history_navigation_ = false;
// A specific factory that should be used for this request instead of whatever
// 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
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 be9274f6453..53ef2e15dd6 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,10 +4,10 @@
#include "third_party/blink/renderer/core/fetch/fetch_response_data.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_response.h"
-#include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_response.h"
#include "third_party/blink/renderer/core/fetch/fetch_header_list.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.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/loader/fetch/fetch_utils.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
@@ -171,7 +171,8 @@ const Vector<KURL>& FetchResponseData::InternalURLList() const {
return url_list_;
}
-FetchResponseData* FetchResponseData::Clone(ScriptState* script_state) {
+FetchResponseData* FetchResponseData::Clone(ScriptState* script_state,
+ ExceptionState& exception_state) {
FetchResponseData* new_response = Create();
new_response->type_ = type_;
if (termination_reason_) {
@@ -194,7 +195,9 @@ FetchResponseData* FetchResponseData::Clone(ScriptState* script_state) {
DCHECK_EQ(buffer_, internal_response_->buffer_);
DCHECK_EQ(internal_response_->type_, Type::kDefault);
new_response->internal_response_ =
- internal_response_->Clone(script_state);
+ internal_response_->Clone(script_state, exception_state);
+ if (exception_state.HadException())
+ return nullptr;
buffer_ = internal_response_->buffer_;
new_response->buffer_ = new_response->internal_response_->buffer_;
break;
@@ -203,7 +206,9 @@ FetchResponseData* FetchResponseData::Clone(ScriptState* script_state) {
if (buffer_) {
BodyStreamBuffer* new1 = nullptr;
BodyStreamBuffer* new2 = nullptr;
- buffer_->Tee(&new1, &new2);
+ buffer_->Tee(&new1, &new2, exception_state);
+ if (exception_state.HadException())
+ return nullptr;
buffer_ = new1;
new_response->buffer_ = new2;
}
@@ -219,7 +224,9 @@ FetchResponseData* FetchResponseData::Clone(ScriptState* script_state) {
DCHECK(!buffer_);
DCHECK_EQ(internal_response_->type_, Type::kDefault);
new_response->internal_response_ =
- internal_response_->Clone(script_state);
+ internal_response_->Clone(script_state, exception_state);
+ if (exception_state.HadException())
+ return nullptr;
break;
}
return new_response;
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 dec0cea6462..5810fcd80a3 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
@@ -12,9 +12,10 @@
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-blink.h"
#include "third_party/blink/public/platform/modules/fetch/fetch_api_response.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_request.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h"
#include "third_party/blink/public/platform/web_cors.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/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -23,7 +24,7 @@
namespace blink {
-class BodyStreamBuffer;
+class ExceptionState;
class FetchHeaderList;
class ScriptState;
class WebServiceWorkerResponse;
@@ -54,7 +55,7 @@ class CORE_EXPORT FetchResponseData final
return internal_response_;
}
- FetchResponseData* Clone(ScriptState*);
+ FetchResponseData* Clone(ScriptState*, ExceptionState& exception_state);
network::mojom::FetchResponseType GetType() const { return type_; }
const KURL* Url() const;
@@ -115,8 +116,8 @@ class CORE_EXPORT FetchResponseData final
unsigned short status_;
AtomicString status_message_;
Member<FetchHeaderList> header_list_;
- Member<FetchResponseData> internal_response_;
- Member<BodyStreamBuffer> buffer_;
+ TraceWrapperMember<FetchResponseData> internal_response_;
+ TraceWrapperMember<BodyStreamBuffer> buffer_;
String mime_type_;
Time response_time_;
String cache_storage_cache_name_;
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 1e9797fc2a6..32747bc40e9 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
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/core/fetch/fetch_response_data.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_response.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_response.h"
#include "third_party/blink/renderer/core/fetch/fetch_header_list.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
diff --git a/chromium/third_party/blink/renderer/core/fetch/form_data_bytes_consumer.cc b/chromium/third_party/blink/renderer/core/fetch/form_data_bytes_consumer.cc
index 5b457b59a8d..48bb0a57e4d 100644
--- a/chromium/third_party/blink/renderer/core/fetch/form_data_bytes_consumer.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/form_data_bytes_consumer.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/fetch/form_data_bytes_consumer.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/fetch/blob_bytes_consumer.h"
#include "third_party/blink/renderer/core/fetch/bytes_consumer_for_data_consumer_handle.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
@@ -12,6 +13,7 @@
#include "third_party/blink/renderer/platform/blob/blob_data.h"
#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
#include "third_party/blink/renderer/platform/network/form_data_encoder.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/text/text_codec.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -319,7 +321,6 @@ class DataPipeAndDataBytesConsumer final : public BytesConsumer {
case PublicState::kErrored:
return;
case PublicState::kClosed:
- NOTREACHED();
return;
case PublicState::kReadableOrWaiting:
break;
diff --git a/chromium/third_party/blink/renderer/core/fetch/global_fetch.cc b/chromium/third_party/blink/renderer/core/fetch/global_fetch.cc
index e136ae52b6d..a62d026e974 100644
--- a/chromium/third_party/blink/renderer/core/fetch/global_fetch.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/global_fetch.cc
@@ -6,10 +6,12 @@
#include "third_party/blink/renderer/core/fetch/fetch_manager.h"
#include "third_party/blink/renderer/core/fetch/request.h"
+#include "third_party/blink/renderer/core/fetch/request_init.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/use_counter.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/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/supplementable.h"
@@ -40,7 +42,7 @@ class GlobalFetchImpl final
ScriptPromise Fetch(ScriptState* script_state,
const RequestInfo& input,
- const Dictionary& init,
+ const RequestInit& init,
ExceptionState& exception_state) override {
ExecutionContext* execution_context = fetch_manager_->GetExecutionContext();
if (!script_state->ContextIsValid() || !execution_context) {
@@ -57,8 +59,13 @@ class GlobalFetchImpl final
return ScriptPromise();
probe::willSendXMLHttpOrFetchNetworkRequest(execution_context, r->url());
- return fetch_manager_->Fetch(script_state, r->PassRequestData(script_state),
- r->signal());
+ auto promise = fetch_manager_->Fetch(
+ script_state, r->PassRequestData(script_state, exception_state),
+ r->signal(), exception_state);
+ if (exception_state.HadException())
+ return ScriptPromise();
+
+ return promise;
}
void Trace(blink::Visitor* visitor) override {
@@ -99,7 +106,7 @@ void GlobalFetch::ScopedFetcher::Trace(blink::Visitor* visitor) {}
ScriptPromise GlobalFetch::fetch(ScriptState* script_state,
LocalDOMWindow& window,
const RequestInfo& input,
- const Dictionary& init,
+ const RequestInit& init,
ExceptionState& exception_state) {
UseCounter::Count(window.GetExecutionContext(), WebFeature::kFetch);
if (!window.GetFrame()) {
@@ -113,7 +120,7 @@ ScriptPromise GlobalFetch::fetch(ScriptState* script_state,
ScriptPromise GlobalFetch::fetch(ScriptState* script_state,
WorkerGlobalScope& worker,
const RequestInfo& input,
- const Dictionary& init,
+ const RequestInit& init,
ExceptionState& exception_state) {
UseCounter::Count(worker.GetExecutionContext(), WebFeature::kFetch);
return ScopedFetcher::From(worker)->Fetch(script_state, input, init,
diff --git a/chromium/third_party/blink/renderer/core/fetch/global_fetch.h b/chromium/third_party/blink/renderer/core/fetch/global_fetch.h
index c05ccd5a49b..e36b5d05315 100644
--- a/chromium/third_party/blink/renderer/core/fetch/global_fetch.h
+++ b/chromium/third_party/blink/renderer/core/fetch/global_fetch.h
@@ -11,9 +11,9 @@
namespace blink {
-class Dictionary;
class LocalDOMWindow;
class ExceptionState;
+class RequestInit;
class ScriptState;
class WorkerGlobalScope;
@@ -27,7 +27,7 @@ class CORE_EXPORT GlobalFetch {
virtual ScriptPromise Fetch(ScriptState*,
const RequestInfo&,
- const Dictionary&,
+ const RequestInit&,
ExceptionState&) = 0;
static ScopedFetcher* From(LocalDOMWindow&);
@@ -39,12 +39,12 @@ class CORE_EXPORT GlobalFetch {
static ScriptPromise fetch(ScriptState*,
LocalDOMWindow&,
const RequestInfo&,
- const Dictionary&,
+ const RequestInit&,
ExceptionState&);
static ScriptPromise fetch(ScriptState*,
WorkerGlobalScope&,
const RequestInfo&,
- const Dictionary&,
+ const RequestInit&,
ExceptionState&);
};
diff --git a/chromium/third_party/blink/renderer/core/fetch/headers.cc b/chromium/third_party/blink/renderer/core/fetch/headers.cc
index 3cd3032743a..fc60cc3c299 100644
--- a/chromium/third_party/blink/renderer/core/fetch/headers.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/headers.cc
@@ -5,9 +5,9 @@
#include "third_party/blink/renderer/core/fetch/headers.h"
#include "third_party/blink/renderer/bindings/core/v8/byte_string_sequence_sequence_or_byte_string_byte_string_record.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h"
#include "third_party/blink/renderer/core/dom/iterator.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#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/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.cc b/chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.cc
index 6b755eb52f9..edbc16664ee 100644
--- a/chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.cc
@@ -122,14 +122,14 @@ BytesConsumer::Result ReadableStreamBytesConsumer::BeginRead(
}
if (!is_reading_) {
is_reading_ = true;
- ScriptState::Scope scope(script_state_.get());
- ScriptValue reader(script_state_.get(),
+ ScriptState::Scope scope(script_state_);
+ ScriptValue reader(script_state_,
reader_.NewLocal(script_state_->GetIsolate()));
// The owner must retain the reader.
DCHECK(!reader.IsEmpty());
- ReadableStreamOperations::DefaultReaderRead(script_state_.get(), reader)
- .Then(OnFulfilled::CreateFunction(script_state_.get(), this),
- OnRejected::CreateFunction(script_state_.get(), this));
+ ReadableStreamOperations::DefaultReaderRead(script_state_, reader)
+ .Then(OnFulfilled::CreateFunction(script_state_, this),
+ OnRejected::CreateFunction(script_state_, this));
}
return Result::kShouldWait;
}
@@ -174,6 +174,7 @@ BytesConsumer::Error ReadableStreamBytesConsumer::GetError() const {
void ReadableStreamBytesConsumer::Trace(blink::Visitor* visitor) {
visitor->Trace(client_);
visitor->Trace(pending_buffer_);
+ visitor->Trace(script_state_);
BytesConsumer::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.h b/chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.h
index 4d0f481bf99..94ec6ea8aa9 100644
--- a/chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.h
+++ b/chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.h
@@ -60,7 +60,7 @@ class CORE_EXPORT ReadableStreamBytesConsumer final : public BytesConsumer {
// Holding a ScopedPersistent here is safe in terms of cross-world wrapper
// leakage because we read only Uint8Array chunks from the reader.
ScopedPersistent<v8::Value> reader_;
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
Member<BytesConsumer::Client> client_;
Member<DOMUint8Array> pending_buffer_;
size_t pending_offset_ = 0;
diff --git a/chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer_test.cc b/chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer_test.cc
index 42f7167f551..ae715b75b50 100644
--- a/chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer_test.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer_test.cc
@@ -83,9 +83,8 @@ class ReadableStreamBytesConsumerTest : public testing::Test {
}
ReadableStreamBytesConsumer* CreateConsumer(ScriptValue stream) {
- NonThrowableExceptionState es;
- ScriptValue reader =
- ReadableStreamOperations::GetReader(GetScriptState(), stream, es);
+ ScriptValue reader = ReadableStreamOperations::GetReader(
+ GetScriptState(), stream, ASSERT_NO_EXCEPTION);
DCHECK(!reader.IsEmpty());
DCHECK(reader.V8Value()->IsObject());
return new ReadableStreamBytesConsumer(GetScriptState(), reader);
diff --git a/chromium/third_party/blink/renderer/core/fetch/request.cc b/chromium/third_party/blink/renderer/core/fetch/request.cc
index a966276ec95..00d5b6a8867 100644
--- a/chromium/third_party/blink/renderer/core/fetch/request.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/request.cc
@@ -4,26 +4,43 @@
#include "third_party/blink/renderer/core/fetch/request.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_request.h"
+#include "third_party/blink/public/common/blob/blob_utils.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
+#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
+#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_abort_signal.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer_view.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_blob.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_form_data.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_url_search_params.h"
#include "third_party/blink/renderer/core/dom/abort_signal.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/fetch/blob_bytes_consumer.h"
#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/request_init.h"
+#include "third_party/blink/renderer/core/fileapi/blob.h"
#include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
+#include "third_party/blink/renderer/core/html/forms/form_data.h"
#include "third_party/blink/renderer/core/loader/threadable_loader.h"
-#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
+#include "third_party/blink/renderer/core/url/url_search_params.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/blob/blob_data.h"
#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/loader/fetch/resource_loader_options.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
+#include "third_party/blink/renderer/platform/network/encoded_form_data.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/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/origin_access_entry.h"
#include "third_party/blink/renderer/platform/weborigin/referrer.h"
+#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
namespace blink {
@@ -50,7 +67,9 @@ FetchRequestData* CreateCopyOfFetchRequestDataForFetch(
request->SetCacheMode(original->CacheMode());
request->SetRedirect(original->Redirect());
request->SetIntegrity(original->Integrity());
+ request->SetImportance(original->Importance());
request->SetKeepalive(original->Keepalive());
+ request->SetIsHistoryNavigation(original->IsHistoryNavigation());
if (original->URLLoaderFactory()) {
network::mojom::blink::URLLoaderFactoryPtr factory_clone;
original->URLLoaderFactory()->Clone(MakeRequest(&factory_clone));
@@ -59,20 +78,99 @@ FetchRequestData* CreateCopyOfFetchRequestDataForFetch(
return request;
}
+static bool AreAnyMembersPresent(const RequestInit& init) {
+ return init.hasMethod() || init.hasHeaders() || init.hasBody() ||
+ init.hasReferrer() || init.hasReferrerPolicy() || init.hasMode() ||
+ init.hasCredentials() || init.hasCache() || init.hasRedirect() ||
+ init.hasIntegrity() || init.hasKeepalive() || init.hasImportance() ||
+ init.hasSignal();
+}
+
+static BodyStreamBuffer* ExtractBody(ScriptState* script_state,
+ ExceptionState& exception_state,
+ v8::Local<v8::Value> body,
+ String& content_type) {
+ DCHECK(!body->IsNull());
+ BodyStreamBuffer* return_buffer = nullptr;
+
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+ v8::Isolate* isolate = script_state->GetIsolate();
+
+ if (V8Blob::hasInstance(body, isolate)) {
+ Blob* blob = V8Blob::ToImpl(body.As<v8::Object>());
+ return_buffer = new BodyStreamBuffer(
+ script_state,
+ new BlobBytesConsumer(execution_context, blob->GetBlobDataHandle()),
+ nullptr /* AbortSignal */);
+ content_type = blob->type();
+ } else if (body->IsArrayBuffer()) {
+ // Avoid calling into V8 from the following constructor parameters, which
+ // is potentially unsafe.
+ DOMArrayBuffer* array_buffer = V8ArrayBuffer::ToImpl(body.As<v8::Object>());
+ return_buffer = new BodyStreamBuffer(
+ script_state, new FormDataBytesConsumer(array_buffer),
+ nullptr /* AbortSignal */);
+ } else if (body->IsArrayBufferView()) {
+ // Avoid calling into V8 from the following constructor parameters, which
+ // is potentially unsafe.
+ DOMArrayBufferView* array_buffer_view =
+ V8ArrayBufferView::ToImpl(body.As<v8::Object>());
+ return_buffer = new BodyStreamBuffer(
+ script_state, new FormDataBytesConsumer(array_buffer_view),
+ nullptr /* AbortSignal */);
+ } else if (V8FormData::hasInstance(body, isolate)) {
+ scoped_refptr<EncodedFormData> form_data =
+ V8FormData::ToImpl(body.As<v8::Object>())->EncodeMultiPartFormData();
+ // Here we handle formData->boundary() as a C-style string. See
+ // FormDataEncoder::generateUniqueBoundaryString.
+ content_type = AtomicString("multipart/form-data; boundary=") +
+ form_data->Boundary().data();
+ return_buffer = new BodyStreamBuffer(
+ script_state,
+ new FormDataBytesConsumer(execution_context, std::move(form_data)),
+ nullptr /* AbortSignal */);
+ } else if (V8URLSearchParams::hasInstance(body, isolate)) {
+ scoped_refptr<EncodedFormData> form_data =
+ V8URLSearchParams::ToImpl(body.As<v8::Object>())->ToEncodedFormData();
+ return_buffer = new BodyStreamBuffer(
+ script_state,
+ new FormDataBytesConsumer(execution_context, std::move(form_data)),
+ nullptr /* AbortSignal */);
+ content_type = "application/x-www-form-urlencoded;charset=UTF-8";
+ } else {
+ String string = NativeValueTraits<IDLUSVString>::NativeValue(
+ isolate, body, exception_state);
+ if (exception_state.HadException())
+ return nullptr;
+
+ return_buffer =
+ new BodyStreamBuffer(script_state, new FormDataBytesConsumer(string),
+ nullptr /* AbortSignal */);
+ content_type = "text/plain;charset=UTF-8";
+ }
+
+ return return_buffer;
+}
+
Request* Request::CreateRequestWithRequestOrString(
ScriptState* script_state,
Request* input_request,
const String& input_string,
- RequestInit& init,
+ const RequestInit& init,
ExceptionState& exception_state) {
+ // Setup RequestInit's body first
// - "If |input| is a Request object and it is disturbed, throw a
// TypeError."
- if (input_request && input_request->bodyUsed()) {
+ if (input_request &&
+ input_request->IsBodyUsed(exception_state) == BodyUsed::kUsed) {
+ DCHECK(!exception_state.HadException());
exception_state.ThrowTypeError(
"Cannot construct a Request with a Request object that has already "
"been used.");
return nullptr;
}
+ if (exception_state.HadException())
+ return nullptr;
// - "Let |temporaryBody| be |input|'s request's body if |input| is a
// Request object, and null otherwise."
BodyStreamBuffer* temporary_body =
@@ -81,7 +179,7 @@ Request* Request::CreateRequestWithRequestOrString(
// "Let |request| be |input|'s request, if |input| is a Request object,
// and a new request otherwise."
- auto* execution_context = ExecutionContext::From(script_state);
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
scoped_refptr<const SecurityOrigin> origin =
execution_context->GetSecurityOrigin();
@@ -148,8 +246,7 @@ Request* Request::CreateRequestWithRequestOrString(
// Parsing URLs should also resolve blob URLs. This is important because
// fetching of a blob URL should work even after the URL is revoked as long
// as the request was created while the URL was still valid.
- if (parsed_url.ProtocolIs("blob") &&
- RuntimeEnabledFeatures::MojoBlobURLsEnabled()) {
+ if (parsed_url.ProtocolIs("blob") && BlobUtils::MojoBlobURLsEnabled()) {
network::mojom::blink::URLLoaderFactoryPtr url_loader_factory;
ExecutionContext::From(script_state)
->GetPublicURLManager()
@@ -162,56 +259,41 @@ Request* Request::CreateRequestWithRequestOrString(
// - "Set |fallbackCredentials| to "omit"."
}
- // "If any of |init|'s members are present, run these substeps:"
- if (init.AreAnyMembersSet()) {
- // "If |request|'s |mode| is "navigate", throw a TypeError."
- if (request->Mode() == network::mojom::FetchRequestMode::kNavigate) {
- exception_state.ThrowTypeError(
- "Cannot construct a Request with a Request whose mode is 'navigate' "
- "and a non-empty RequestInit.");
- return nullptr;
- }
+ // "If any of |init|'s members are present, then:"
+ if (AreAnyMembersPresent(init)) {
+ // "If |request|'s |mode| is "navigate", then set it to "same-origin".
+ if (request->Mode() == network::mojom::FetchRequestMode::kNavigate)
+ request->SetMode(network::mojom::FetchRequestMode::kSameOrigin);
// TODO(yhirano): Implement the following substep:
- // "Unset |request|'s omit-Origin-header flag."
+ // "Unset |request|'s reload-navigation flag."
- // The substep "Set |request|'s referrer to "client"." is performed by
- // the code below as follows:
- // - |init.referrer.referrer| gets initialized by the RequestInit
- // constructor to "about:client" when any of |options|'s members are
- // present.
- // - The code below does the equivalent as the step specified in the
- // spec by processing the "about:client".
+ // "Unset |request|'s history-navigation flag."
+ request->SetIsHistoryNavigation(false);
- // The substep "Set |request|'s referrer policy to the empty string."
- // is also performed by the code below similarly.
+ // "Set |request|’s referrer to "client"."
+ request->SetReferrerString(FetchRequestData::ClientReferrerString());
+
+ // "Set |request|’s referrer policy to the empty string."
+ request->SetReferrerPolicy(kReferrerPolicyDefault);
}
- // The following if-clause performs the following two steps:
- // - "If |init|'s referrer member is present, run these substeps:"
- // "If |init|'s referrerPolicy member is present, set |request|'s
- // referrer policy to it."
- //
- // The condition "if any of |init|'s members are present"
- // (areAnyMembersSet) is used for the if-clause instead of conditions
- // indicating presence of each member as specified in the spec. This is to
- // perform the substeps in the previous step together here.
- if (init.AreAnyMembersSet()) {
+ // "If init’s referrer member is present, then:"
+ if (init.hasReferrer()) {
// Nothing to do for the step "Let |referrer| be |init|'s referrer
// member."
- if (init.GetReferrer().referrer.IsEmpty()) {
+ if (init.referrer().IsEmpty()) {
// "If |referrer| is the empty string, set |request|'s referrer to
// "no-referrer" and terminate these substeps."
request->SetReferrerString(AtomicString(Referrer::NoReferrer()));
} else {
// "Let |parsedReferrer| be the result of parsing |referrer| with
// |baseURL|."
- KURL parsed_referrer(base_url, init.GetReferrer().referrer);
+ KURL parsed_referrer(base_url, init.referrer());
if (!parsed_referrer.IsValid()) {
// "If |parsedReferrer| is failure, throw a TypeError."
- exception_state.ThrowTypeError("Referrer '" +
- init.GetReferrer().referrer +
+ exception_state.ThrowTypeError("Referrer '" + init.referrer() +
"' is not a valid URL.");
return nullptr;
}
@@ -237,7 +319,23 @@ Request* Request::CreateRequestWithRequestOrString(
request->SetReferrerString(AtomicString(parsed_referrer.GetString()));
}
}
- request->SetReferrerPolicy(init.GetReferrer().referrer_policy);
+ }
+
+ // "If init's referrerPolicy member is present, set request's referrer
+ // policy to it."
+ if (init.hasReferrerPolicy()) {
+ // In case referrerPolicy = "", the SecurityPolicy method below will not
+ // actually set referrer_policy, so we'll default to
+ // kReferrerPolicyDefault.
+ ReferrerPolicy referrer_policy;
+ if (!SecurityPolicy::ReferrerPolicyFromString(
+ init.referrerPolicy(), kDoNotSupportReferrerPolicyLegacyKeywords,
+ &referrer_policy)) {
+ DCHECK(init.referrerPolicy().IsEmpty());
+ referrer_policy = kReferrerPolicyDefault;
+ }
+
+ request->SetReferrerPolicy(referrer_policy);
}
// The following code performs the following steps:
@@ -245,17 +343,17 @@ 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") {
+ 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") {
+ if (init.mode() == "same-origin") {
request->SetMode(network::mojom::FetchRequestMode::kSameOrigin);
- } else if (init.Mode() == "no-cors") {
+ } else if (init.mode() == "no-cors") {
request->SetMode(network::mojom::FetchRequestMode::kNoCORS);
- } else if (init.Mode() == "cors") {
+ } else if (init.mode() == "cors") {
request->SetMode(network::mojom::FetchRequestMode::kCORS);
} else {
// |inputRequest| is directly checked here instead of setting and
@@ -264,30 +362,42 @@ Request* Request::CreateRequestWithRequestOrString(
request->SetMode(network::mojom::FetchRequestMode::kCORS);
}
+ // This is not yet standardized, but we can assume the following:
+ // "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());
+ if (init.importance() == "low") {
+ request->SetImportance(mojom::FetchImportanceMode::kImportanceLow);
+ } else if (init.importance() == "high") {
+ request->SetImportance(mojom::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|."
network::mojom::FetchCredentialsMode credentials_mode;
- if (ParseCredentialsMode(init.Credentials(), &credentials_mode)) {
+ if (ParseCredentialsMode(init.credentials(), &credentials_mode)) {
request->SetCredentials(credentials_mode);
} else if (!input_request) {
request->SetCredentials(network::mojom::FetchCredentialsMode::kSameOrigin);
}
// "If |init|'s cache member is present, set |request|'s cache mode to it."
- if (init.CacheMode() == "default") {
+ if (init.cache() == "default") {
request->SetCacheMode(mojom::FetchCacheMode::kDefault);
- } else if (init.CacheMode() == "no-store") {
+ } else if (init.cache() == "no-store") {
request->SetCacheMode(mojom::FetchCacheMode::kNoStore);
- } else if (init.CacheMode() == "reload") {
+ } else if (init.cache() == "reload") {
request->SetCacheMode(mojom::FetchCacheMode::kBypassCache);
- } else if (init.CacheMode() == "no-cache") {
+ } else if (init.cache() == "no-cache") {
request->SetCacheMode(mojom::FetchCacheMode::kValidateCache);
- } else if (init.CacheMode() == "force-cache") {
+ } else if (init.cache() == "force-cache") {
request->SetCacheMode(mojom::FetchCacheMode::kForceCache);
- } else if (init.CacheMode() == "only-if-cached") {
+ } else if (init.cache() == "only-if-cached") {
request->SetCacheMode(mojom::FetchCacheMode::kOnlyIfCached);
}
@@ -302,47 +412,46 @@ Request* Request::CreateRequestWithRequestOrString(
// "If |init|'s redirect member is present, set |request|'s redirect mode
// to it."
- if (init.Redirect() == "follow") {
+ if (init.redirect() == "follow") {
request->SetRedirect(network::mojom::FetchRedirectMode::kFollow);
- } else if (init.Redirect() == "error") {
+ } else if (init.redirect() == "error") {
request->SetRedirect(network::mojom::FetchRedirectMode::kError);
- } else if (init.Redirect() == "manual") {
+ } else if (init.redirect() == "manual") {
request->SetRedirect(network::mojom::FetchRedirectMode::kManual);
}
// "If |init|'s integrity member is present, set |request|'s
// integrity metadata to it."
- if (!init.Integrity().IsNull())
- request->SetIntegrity(init.Integrity());
+ if (init.hasIntegrity())
+ request->SetIntegrity(init.integrity());
- if (init.Keepalive().has_value())
- request->SetKeepalive(*init.Keepalive());
+ if (init.hasKeepalive())
+ request->SetKeepalive(init.keepalive());
// "If |init|'s method member is present, let |method| be it and run these
// substeps:"
- if (!init.Method().IsNull()) {
+ if (init.hasMethod()) {
// "If |method| is not a method or method is a forbidden method, throw
// a TypeError."
- if (!IsValidHTTPToken(init.Method())) {
- exception_state.ThrowTypeError("'" + init.Method() +
+ if (!IsValidHTTPToken(init.method())) {
+ exception_state.ThrowTypeError("'" + init.method() +
"' is not a valid HTTP method.");
return nullptr;
}
- if (FetchUtils::IsForbiddenMethod(init.Method())) {
- exception_state.ThrowTypeError("'" + init.Method() +
+ if (FetchUtils::IsForbiddenMethod(init.method())) {
+ exception_state.ThrowTypeError("'" + init.method() +
"' HTTP method is unsupported.");
return nullptr;
}
// "Normalize |method|."
// "Set |request|'s method to |method|."
request->SetMethod(
- FetchUtils::NormalizeMethod(AtomicString(init.Method())));
+ FetchUtils::NormalizeMethod(AtomicString(init.method())));
}
// "If |init|'s signal member is present, then set |signal| to it."
- auto init_signal = init.Signal();
- if (init_signal.has_value()) {
- signal = init_signal.value();
+ if (init.hasSignal()) {
+ signal = init.signal();
}
// "Let |r| be a new Request object associated with |request| and a new
@@ -356,7 +465,7 @@ Request* Request::CreateRequestWithRequestOrString(
// We don't create a copy of r's Headers object when init's headers member
// is present.
Headers* headers = nullptr;
- if (init.GetHeaders().IsNull()) {
+ if (!init.hasHeaders()) {
headers = r->getHeaders()->Clone();
}
// "Empty |r|'s request's header list."
@@ -374,12 +483,12 @@ Request* Request::CreateRequestWithRequestOrString(
r->getHeaders()->SetGuard(Headers::kRequestNoCORSGuard);
}
// "If |signal| is not null, then make |r|’s signal follow |signal|."
- if (signal) {
+ if (signal)
r->signal_->Follow(signal);
- }
+
// "Fill |r|'s Headers object with |headers|. Rethrow any exceptions."
- if (!init.GetHeaders().IsNull()) {
- r->getHeaders()->FillWith(init.GetHeaders(), exception_state);
+ if (init.hasHeaders()) {
+ r->getHeaders()->FillWith(init.headers(), exception_state);
} else {
DCHECK(headers);
r->getHeaders()->FillWith(headers, exception_state);
@@ -389,7 +498,9 @@ Request* Request::CreateRequestWithRequestOrString(
// "If either |init|'s body member is present or |temporaryBody| is
// non-null, and |request|'s method is `GET` or `HEAD`, throw a TypeError.
- if (init.GetBody() || temporary_body) {
+ v8::Local<v8::Value> init_body =
+ init.hasBody() ? init.body().V8Value() : v8::Local<v8::Value>();
+ if ((!init_body.IsEmpty() && !init_body->IsNull()) || temporary_body) {
if (request->Method() == HTTPNames::GET ||
request->Method() == HTTPNames::HEAD) {
exception_state.ThrowTypeError(
@@ -398,8 +509,8 @@ Request* Request::CreateRequestWithRequestOrString(
}
}
- // "If |init|'s body member is present, run these substeps:"
- if (init.GetBody()) {
+ // "If |init|’s body member is present and is non-null, then:"
+ if (!init_body.IsEmpty() && !init_body->IsNull()) {
// TODO(yhirano): Throw if keepalive flag is set and body is a
// ReadableStream. We don't support body stream setting for Request yet.
@@ -411,11 +522,12 @@ Request* Request::CreateRequestWithRequestOrString(
// contains no header named `Content-Type`, append
// `Content-Type`/|Content-Type| to |r|'s Headers object. Rethrow any
// exception."
+ String content_type;
temporary_body =
- new BodyStreamBuffer(script_state, std::move(init.GetBody()), nullptr);
- if (!init.ContentType().IsEmpty() &&
+ ExtractBody(script_state, exception_state, init_body, content_type);
+ if (!content_type.IsEmpty() &&
!r->getHeaders()->has(HTTPNames::Content_Type, exception_state)) {
- r->getHeaders()->append(HTTPNames::Content_Type, init.ContentType(),
+ r->getHeaders()->append(HTTPNames::Content_Type, content_type,
exception_state);
}
if (exception_state.HadException())
@@ -423,10 +535,8 @@ Request* Request::CreateRequestWithRequestOrString(
}
// "Set |r|'s request's body to |temporaryBody|.
- if (temporary_body) {
+ if (temporary_body)
r->request_->SetBuffer(temporary_body);
- r->RefreshBody(script_state);
- }
// "Set |r|'s MIME type to the result of extracting a MIME type from |r|'s
// request's header list."
@@ -441,10 +551,11 @@ Request* Request::CreateRequestWithRequestOrString(
// "Set |input|'s request's body to a new body whose stream is
// |dummyStream|."
input_request->request_->SetBuffer(dummy_stream);
- input_request->RefreshBody(script_state);
// "Let |reader| be the result of getting reader from |dummyStream|."
// "Read all bytes from |dummyStream| with |reader|."
- input_request->BodyBuffer()->CloseAndLockAndDisturb();
+ input_request->BodyBuffer()->CloseAndLockAndDisturb(exception_state);
+ if (exception_state.HadException())
+ return nullptr;
}
// "Return |r|."
@@ -453,7 +564,7 @@ Request* Request::CreateRequestWithRequestOrString(
Request* Request::Create(ScriptState* script_state,
const RequestInfo& input,
- const Dictionary& init,
+ const RequestInit& init,
ExceptionState& exception_state) {
DCHECK(!input.IsNull());
if (input.IsUSVString())
@@ -464,33 +575,29 @@ Request* Request::Create(ScriptState* script_state,
Request* Request::Create(ScriptState* script_state,
const String& input,
ExceptionState& exception_state) {
- return Create(script_state, input, Dictionary(), exception_state);
+ return Create(script_state, input, RequestInit(), exception_state);
}
Request* Request::Create(ScriptState* script_state,
const String& input,
- const Dictionary& init,
+ const RequestInit& init,
ExceptionState& exception_state) {
- RequestInit request_init(ExecutionContext::From(script_state), init,
- exception_state);
- return CreateRequestWithRequestOrString(script_state, nullptr, input,
- request_init, exception_state);
+ return CreateRequestWithRequestOrString(script_state, nullptr, input, init,
+ exception_state);
}
Request* Request::Create(ScriptState* script_state,
Request* input,
ExceptionState& exception_state) {
- return Create(script_state, input, Dictionary(), exception_state);
+ return Create(script_state, input, RequestInit(), exception_state);
}
Request* Request::Create(ScriptState* script_state,
Request* input,
- const Dictionary& init,
+ const RequestInit& init,
ExceptionState& exception_state) {
- RequestInit request_init(ExecutionContext::From(script_state), init,
- exception_state);
- return CreateRequestWithRequestOrString(script_state, input, String(),
- request_init, exception_state);
+ return CreateRequestWithRequestOrString(script_state, input, String(), init,
+ exception_state);
}
Request* Request::Create(ScriptState* script_state, FetchRequestData* request) {
@@ -530,7 +637,6 @@ Request::Request(ScriptState* script_state,
request_(request),
headers_(headers),
signal_(signal) {
- RefreshBody(script_state);
}
Request::Request(ScriptState* script_state, FetchRequestData* request)
@@ -724,15 +830,24 @@ bool Request::keepalive() const {
return request_->Keepalive();
}
+bool Request::isHistoryNavigation() const {
+ return request_->IsHistoryNavigation();
+}
+
Request* Request::clone(ScriptState* script_state,
ExceptionState& exception_state) {
- if (IsBodyLocked() || bodyUsed()) {
+ if (IsBodyLocked(exception_state) == BodyLocked::kLocked ||
+ IsBodyUsed(exception_state) == BodyUsed::kUsed) {
+ DCHECK(!exception_state.HadException());
exception_state.ThrowTypeError("Request body is already used");
return nullptr;
}
+ if (exception_state.HadException())
+ return nullptr;
- FetchRequestData* request = request_->Clone(script_state);
- RefreshBody(script_state);
+ FetchRequestData* request = request_->Clone(script_state, exception_state);
+ if (exception_state.HadException())
+ return nullptr;
Headers* headers = Headers::Create(request->HeaderList());
headers->SetGuard(headers_->GetGuard());
auto* signal = new AbortSignal(ExecutionContext::From(script_state));
@@ -740,10 +855,12 @@ Request* Request::clone(ScriptState* script_state,
return new Request(script_state, request, headers, signal);
}
-FetchRequestData* Request::PassRequestData(ScriptState* script_state) {
- DCHECK(!bodyUsed());
- FetchRequestData* data = request_->Pass(script_state);
- RefreshBody(script_state);
+FetchRequestData* Request::PassRequestData(ScriptState* script_state,
+ ExceptionState& exception_state) {
+ DCHECK(!IsBodyUsedForDCheck());
+ FetchRequestData* data = request_->Pass(script_state, exception_state);
+ if (exception_state.HadException())
+ return nullptr;
// |data|'s buffer('s js wrapper) has no retainer, but it's OK because
// the only caller is the fetch function and it uses the body buffer
// immediately.
@@ -762,6 +879,7 @@ void Request::PopulateWebServiceWorkerRequest(
web_request.SetCacheMode(request_->CacheMode());
web_request.SetRedirectMode(request_->Redirect());
web_request.SetIntegrity(request_->Integrity());
+ web_request.SetIsHistoryNavigation(request_->IsHistoryNavigation());
web_request.SetRequestContext(request_->Context());
// Strip off the fragment part of URL. So far, all users of
@@ -794,21 +912,6 @@ String Request::ContentType() const {
return result;
}
-void Request::RefreshBody(ScriptState* script_state) {
- v8::Local<v8::Value> request = ToV8(this, script_state);
- if (request.IsEmpty()) {
- // |toV8| can return an empty handle when the worker is terminating.
- // We don't want the renderer to crash in such cases.
- // TODO(yhirano): Delete this block after the graceful shutdown
- // mechanism is introduced.
- return;
- }
- DCHECK(request->IsObject());
- v8::Local<v8::Value> body_buffer = ToV8(this->BodyBuffer(), script_state);
- V8PrivateProperty::GetInternalBodyBuffer(script_state->GetIsolate())
- .Set(request.As<v8::Object>(), body_buffer);
-}
-
void Request::Trace(blink::Visitor* visitor) {
Body::Trace(visitor);
visitor->Trace(request_);
diff --git a/chromium/third_party/blink/renderer/core/fetch/request.h b/chromium/third_party/blink/renderer/core/fetch/request.h
index d5176067674..a4a4471ba38 100644
--- a/chromium/third_party/blink/renderer/core/fetch/request.h
+++ b/chromium/third_party/blink/renderer/core/fetch/request.h
@@ -22,6 +22,7 @@ namespace blink {
class AbortSignal;
class BodyStreamBuffer;
+class ExceptionState;
class RequestInit;
class WebServiceWorkerRequest;
@@ -36,18 +37,18 @@ class CORE_EXPORT Request final : public Body {
// From Request.idl:
static Request* Create(ScriptState*,
const RequestInfo&,
- const Dictionary&,
+ const RequestInit&,
ExceptionState&);
static Request* Create(ScriptState*, const String&, ExceptionState&);
static Request* Create(ScriptState*,
const String&,
- const Dictionary&,
+ const RequestInit&,
ExceptionState&);
static Request* Create(ScriptState*, Request*, ExceptionState&);
static Request* Create(ScriptState*,
Request*,
- const Dictionary&,
+ const RequestInit&,
ExceptionState&);
static Request* Create(ScriptState*, FetchRequestData*);
static Request* Create(ScriptState*, const WebServiceWorkerRequest&);
@@ -70,13 +71,14 @@ class CORE_EXPORT Request final : public Body {
String redirect() const;
String integrity() const;
bool keepalive() const;
+ bool isHistoryNavigation() const;
AbortSignal* signal() const { return signal_; }
// From Request.idl:
// This function must be called with entering an appropriate V8 context.
Request* clone(ScriptState*, ExceptionState&);
- FetchRequestData* PassRequestData(ScriptState*);
+ FetchRequestData* PassRequestData(ScriptState*, ExceptionState&);
void PopulateWebServiceWorkerRequest(WebServiceWorkerRequest&) const;
bool HasBody() const;
BodyStreamBuffer* BodyBuffer() override { return request_->Buffer(); }
@@ -94,14 +96,13 @@ class CORE_EXPORT Request final : public Body {
static Request* CreateRequestWithRequestOrString(ScriptState*,
Request*,
const String&,
- RequestInit&,
+ const RequestInit&,
ExceptionState&);
String ContentType() const override;
String MimeType() const override;
- void RefreshBody(ScriptState*);
- const Member<FetchRequestData> request_;
+ const TraceWrapperMember<FetchRequestData> request_;
const Member<Headers> headers_;
const Member<AbortSignal> signal_;
DISALLOW_COPY_AND_ASSIGN(Request);
diff --git a/chromium/third_party/blink/renderer/core/fetch/request.idl b/chromium/third_party/blink/renderer/core/fetch/request.idl
index 6bd3fdc8b0f..19218756447 100644
--- a/chromium/third_party/blink/renderer/core/fetch/request.idl
+++ b/chromium/third_party/blink/renderer/core/fetch/request.idl
@@ -13,6 +13,7 @@ enum RequestCredentials { "omit", "same-origin", "include" };
enum RequestRedirect { "follow", "error", "manual" };
enum RequestCache { "default", "no-store", "reload", "no-cache", "force-cache",
"only-if-cached" };
+enum RequestImportance {"low", "auto", "high"};
// https://w3c.github.io/webappsec-referrer-policy/#referrer-policies
@@ -20,14 +21,17 @@ enum ReferrerPolicy {
"",
"no-referrer",
"no-referrer-when-downgrade",
+ "same-origin",
"origin",
+ "strict-origin",
"origin-when-cross-origin",
+ "strict-origin-when-cross-origin",
"unsafe-url"
};
[
ActiveScriptWrappable,
- Constructor(RequestInfo input, optional Dictionary requestInitDict),
+ Constructor(RequestInfo input, optional RequestInit requestInitDict),
ConstructorCallWith=ScriptState,
Exposed=(Window,Worker),
RaisesException=Constructor
@@ -40,12 +44,13 @@ enum ReferrerPolicy {
[ImplementedAs=getReferrerPolicy] readonly attribute ReferrerPolicy referrerPolicy;
readonly attribute RequestMode mode;
readonly attribute RequestCredentials credentials;
- [RuntimeEnabled=FetchRequestCache] readonly attribute RequestCache cache;
+ readonly attribute RequestCache cache;
readonly attribute RequestRedirect redirect;
readonly attribute DOMString integrity;
- [RuntimeEnabled=FetchRequestKeepalive] readonly attribute boolean keepalive;
- [RuntimeEnabled=FetchRequestSignal] readonly attribute AbortSignal signal;
+ readonly attribute boolean keepalive;
+ readonly attribute AbortSignal signal;
+ [RuntimeEnabled=RequestIsHistoryNavigation] readonly attribute boolean isHistoryNavigation;
[RaisesException, CallWith=ScriptState, DoNotTestNewObject, NewObject] Request clone();
};
diff --git a/chromium/third_party/blink/renderer/core/fetch/request_init.cc b/chromium/third_party/blink/renderer/core/fetch/request_init.cc
deleted file mode 100644
index d56ca734350..00000000000
--- a/chromium/third_party/blink/renderer/core/fetch/request_init.cc
+++ /dev/null
@@ -1,289 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/fetch/request_init.h"
-
-#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
-#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_abort_signal.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer_view.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_blob.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_form_data.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_url_search_params.h"
-#include "third_party/blink/renderer/core/fetch/blob_bytes_consumer.h"
-#include "third_party/blink/renderer/core/fetch/form_data_bytes_consumer.h"
-#include "third_party/blink/renderer/core/fetch/headers.h"
-#include "third_party/blink/renderer/core/fileapi/blob.h"
-#include "third_party/blink/renderer/core/frame/deprecation.h"
-#include "third_party/blink/renderer/core/frame/use_counter.h"
-#include "third_party/blink/renderer/core/html/forms/form_data.h"
-#include "third_party/blink/renderer/core/url/url_search_params.h"
-#include "third_party/blink/renderer/platform/blob/blob_data.h"
-#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/weborigin/referrer_policy.h"
-
-namespace blink {
-
-struct RequestInit::IDLPassThrough
- : public IDLBaseHelper<v8::Local<v8::Value>> {};
-
-template <>
-struct NativeValueTraits<RequestInit::IDLPassThrough>
- : public NativeValueTraitsBase<RequestInit::IDLPassThrough> {
- static v8::Local<v8::Value> NativeValue(v8::Isolate* isolate,
- v8::Local<v8::Value> value,
- ExceptionState& exception_state) {
- DCHECK(!value.IsEmpty());
- return value;
- }
-};
-
-class RequestInit::GetterHelper {
- STACK_ALLOCATED();
-
- public:
- // |this| object must not outlive |src| and |exception_state|.
- GetterHelper(const Dictionary& src, ExceptionState& exception_state)
- : src_(src), exception_state_(exception_state) {}
-
- template <typename IDLType>
- base::Optional<typename IDLType::ImplType> Get(const StringView& key) {
- auto r = src_.Get<IDLType>(key, exception_state_);
- are_any_members_set_ = are_any_members_set_ || r.has_value();
- return r;
- }
-
- bool AreAnyMembersSet() const { return are_any_members_set_; }
-
- private:
- const Dictionary& src_;
- ExceptionState& exception_state_;
- bool are_any_members_set_ = false;
- DISALLOW_COPY_AND_ASSIGN(GetterHelper);
-};
-
-RequestInit::RequestInit(ExecutionContext* context,
- const Dictionary& options,
- ExceptionState& exception_state) {
- GetterHelper h(options, exception_state);
-
- method_ = h.Get<IDLByteString>("method").value_or(String());
- if (exception_state.HadException())
- return;
-
- auto v8_headers = h.Get<IDLPassThrough>("headers");
- if (exception_state.HadException())
- return;
-
- mode_ = h.Get<IDLUSVString>("mode").value_or(String());
- if (exception_state.HadException())
- return;
-
- if (RuntimeEnabledFeatures::FetchRequestCacheEnabled()) {
- cache_ = h.Get<IDLUSVString>("cache").value_or(String());
- if (exception_state.HadException())
- return;
- }
-
- redirect_ = h.Get<IDLUSVString>("redirect").value_or(String());
- if (exception_state.HadException())
- return;
-
- auto referrer_string = h.Get<IDLUSVString>("referrer");
- if (exception_state.HadException())
- return;
-
- auto referrer_policy_string = h.Get<IDLUSVString>("referrerPolicy");
- if (exception_state.HadException())
- return;
-
- integrity_ = h.Get<IDLString>("integrity").value_or(String());
- if (exception_state.HadException())
- return;
-
- if (RuntimeEnabledFeatures::FetchRequestKeepaliveEnabled()) {
- keepalive_ = h.Get<IDLBoolean>("keepalive");
- if (exception_state.HadException())
- return;
- }
-
- base::Optional<v8::Local<v8::Value>> v8_signal;
- if (RuntimeEnabledFeatures::FetchRequestSignalEnabled()) {
- // In order to distinguish between undefined and null, split the steps of
- // looking it up in the dictionary and converting to the native type.
- v8_signal = h.Get<IDLPassThrough>("signal");
- if (exception_state.HadException())
- return;
- }
-
- auto v8_body = h.Get<IDLPassThrough>("body");
- if (exception_state.HadException())
- return;
-
- credentials_ = h.Get<IDLUSVString>("credentials").value_or(String());
-
- if (exception_state.HadException())
- return;
-
- are_any_members_set_ = h.AreAnyMembersSet();
-
- CheckEnumValues(referrer_string, referrer_policy_string, exception_state);
- if (exception_state.HadException())
- return;
-
- v8::Isolate* isolate = ToIsolate(context);
-
- if (v8_headers.has_value()) {
- V8ByteStringSequenceSequenceOrByteStringByteStringRecord::ToImpl(
- isolate, *v8_headers, headers_, UnionTypeConversionMode::kNotNullable,
- exception_state);
- if (exception_state.HadException())
- return;
- }
-
- if (v8_signal.has_value()) {
- if ((*v8_signal)->IsNull()) {
- // Override any existing value.
- signal_.emplace(nullptr);
- } else {
- signal_.emplace(NativeValueTraits<AbortSignal>::NativeValue(
- isolate, *v8_signal, exception_state));
- }
- if (exception_state.HadException())
- return;
- }
-
- if (v8_body.has_value()) {
- SetUpBody(context, isolate, *v8_body, exception_state);
- if (exception_state.HadException())
- return;
- }
-}
-
-base::Optional<AbortSignal*> RequestInit::Signal() const {
- return signal_.has_value() ? base::make_optional(signal_.value().Get())
- : base::nullopt;
-}
-
-void RequestInit::CheckEnumValues(
- const base::Optional<String>& referrer_string,
- const base::Optional<String>& referrer_policy_string,
- ExceptionState& exception_state) {
- TRACE_EVENT0("blink", "RequestInit::CheckEnumValues");
-
- // Validate cache_
- if (!cache_.IsNull() && cache_ != "default" && cache_ != "no-store" &&
- cache_ != "reload" && cache_ != "no-cache" && cache_ != "force-cache" &&
- cache_ != "only-if-cached") {
- exception_state.ThrowTypeError("Invalid cache mode");
- return;
- }
-
- // Validate credentials_
- if (!credentials_.IsNull() && credentials_ != "omit" &&
- credentials_ != "same-origin" && credentials_ != "include") {
- exception_state.ThrowTypeError("Invalid credentials mode");
- return;
- }
-
- // Validate mode_
- if (!mode_.IsNull() && mode_ != "navigate" && mode_ != "same-origin" &&
- mode_ != "no-cors" && mode_ != "cors") {
- exception_state.ThrowTypeError("Invalid mode");
- return;
- }
-
- // Validate redirect_
- if (!redirect_.IsNull() && redirect_ != "follow" && redirect_ != "error" &&
- redirect_ != "manual") {
- exception_state.ThrowTypeError("Invalid redirect mode");
- return;
- }
-
- // Validate referrer policy
-
- // A part of the Request constructor algorithm is performed here. See
- // the comments in the Request constructor code for the detail.
-
- // We need to use "about:client" instead of |clientReferrerString|,
- // because "about:client" => |clientReferrerString| conversion is done
- // in Request::createRequestWithRequestOrString.
- referrer_ = Referrer("about:client", kReferrerPolicyDefault);
- if (referrer_string.has_value())
- referrer_.referrer = AtomicString(*referrer_string);
-
- if (referrer_policy_string.has_value()) {
- if (*referrer_policy_string == "") {
- referrer_.referrer_policy = kReferrerPolicyDefault;
- } else if (*referrer_policy_string == "no-referrer") {
- referrer_.referrer_policy = kReferrerPolicyNever;
- } else if (*referrer_policy_string == "no-referrer-when-downgrade") {
- referrer_.referrer_policy = kReferrerPolicyNoReferrerWhenDowngrade;
- } else if (*referrer_policy_string == "origin") {
- referrer_.referrer_policy = kReferrerPolicyOrigin;
- } else if (*referrer_policy_string == "origin-when-cross-origin") {
- referrer_.referrer_policy = kReferrerPolicyOriginWhenCrossOrigin;
- } else if (*referrer_policy_string == "same-origin") {
- referrer_.referrer_policy = kReferrerPolicySameOrigin;
- } else if (*referrer_policy_string == "strict-origin") {
- referrer_.referrer_policy = kReferrerPolicyStrictOrigin;
- } else if (*referrer_policy_string == "unsafe-url") {
- referrer_.referrer_policy = kReferrerPolicyAlways;
- } else if (*referrer_policy_string == "strict-origin-when-cross-origin") {
- referrer_.referrer_policy = kReferrerPolicyStrictOriginWhenCrossOrigin;
- } else {
- exception_state.ThrowTypeError("Invalid referrer policy");
- return;
- }
- }
-}
-
-void RequestInit::SetUpBody(ExecutionContext* context,
- v8::Isolate* isolate,
- v8::Local<v8::Value> v8_body,
- ExceptionState& exception_state) {
- if (v8_body->IsNull())
- return;
-
- if (v8_body->IsArrayBuffer()) {
- body_ = new FormDataBytesConsumer(
- V8ArrayBuffer::ToImpl(v8_body.As<v8::Object>()));
- } else if (v8_body->IsArrayBufferView()) {
- body_ = new FormDataBytesConsumer(
- V8ArrayBufferView::ToImpl(v8_body.As<v8::Object>()));
- } else if (V8Blob::hasInstance(v8_body, isolate)) {
- scoped_refptr<BlobDataHandle> blob_data_handle =
- V8Blob::ToImpl(v8_body.As<v8::Object>())->GetBlobDataHandle();
- content_type_ = blob_data_handle->GetType();
- body_ = new BlobBytesConsumer(context, std::move(blob_data_handle));
- } else if (V8FormData::hasInstance(v8_body, isolate)) {
- scoped_refptr<EncodedFormData> form_data =
- V8FormData::ToImpl(v8_body.As<v8::Object>())->EncodeMultiPartFormData();
- // Here we handle formData->boundary() as a C-style string. See
- // FormDataEncoder::generateUniqueBoundaryString.
- content_type_ = AtomicString("multipart/form-data; boundary=") +
- form_data->Boundary().data();
- body_ = new FormDataBytesConsumer(context, std::move(form_data));
- } else if (V8URLSearchParams::hasInstance(v8_body, isolate)) {
- scoped_refptr<EncodedFormData> form_data =
- V8URLSearchParams::ToImpl(v8_body.As<v8::Object>())
- ->ToEncodedFormData();
- content_type_ =
- AtomicString("application/x-www-form-urlencoded;charset=UTF-8");
- body_ = new FormDataBytesConsumer(context, std::move(form_data));
- } else {
- String string = NativeValueTraits<IDLUSVString>::NativeValue(
- isolate, v8_body, exception_state);
- if (exception_state.HadException())
- return;
- content_type_ = "text/plain;charset=UTF-8";
- body_ = new FormDataBytesConsumer(string);
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fetch/request_init.h b/chromium/third_party/blink/renderer/core/fetch/request_init.h
deleted file mode 100644
index 50300c1e4ea..00000000000
--- a/chromium/third_party/blink/renderer/core/fetch/request_init.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_REQUEST_INIT_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_REQUEST_INIT_H_
-
-#include "base/memory/scoped_refptr.h"
-#include "base/optional.h"
-#include "third_party/blink/renderer/bindings/core/v8/byte_string_sequence_sequence_or_byte_string_byte_string_record.h"
-#include "third_party/blink/renderer/bindings/core/v8/native_value_traits.h"
-#include "third_party/blink/renderer/core/fetch/headers.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/weborigin/referrer.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-class AbortSignal;
-class BytesConsumer;
-class Dictionary;
-class ExecutionContext;
-class ExceptionState;
-
-// FIXME: Use IDL dictionary instead of this class.
-class RequestInit {
- STACK_ALLOCATED();
-
- public:
- RequestInit(ExecutionContext*, const Dictionary&, ExceptionState&);
-
- const String& Method() const { return method_; }
- const HeadersInit& GetHeaders() const { return headers_; }
- const String& ContentType() const { return content_type_; }
- BytesConsumer* GetBody() { return body_; }
- const Referrer& GetReferrer() const { return referrer_; }
- const String& Mode() const { return mode_; }
- const String& Credentials() const { return credentials_; }
- const String& CacheMode() const { return cache_; }
- const String& Redirect() const { return redirect_; }
- const String& Integrity() const { return integrity_; }
- const base::Optional<bool>& Keepalive() const { return keepalive_; }
- base::Optional<AbortSignal*> Signal() const;
- bool AreAnyMembersSet() const { return are_any_members_set_; }
-
- private:
- // These are defined here to avoid JUMBO ambiguity.
- class GetterHelper;
- struct IDLPassThrough;
- friend struct NativeValueTraits<IDLPassThrough>;
- friend struct NativeValueTraitsBase<IDLPassThrough>;
-
- void CheckEnumValues(const base::Optional<String>& referrer_string,
- const base::Optional<String>& referrer_policy_string,
- ExceptionState&);
- void SetUpBody(ExecutionContext*,
- v8::Isolate*,
- v8::Local<v8::Value> v8_body,
- ExceptionState&);
-
- String method_;
- HeadersInit headers_;
- String content_type_;
- Member<BytesConsumer> body_;
- Referrer referrer_;
- String mode_;
- String credentials_;
- String cache_;
- String redirect_;
- String integrity_;
- base::Optional<bool> keepalive_;
- base::Optional<Member<AbortSignal>> signal_;
- // True if any members in RequestInit are set and hence the referrer member
- // should be used in the Request constructor.
- bool are_any_members_set_ = false;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_REQUEST_INIT_H_
diff --git a/chromium/third_party/blink/renderer/core/fetch/request_init.idl b/chromium/third_party/blink/renderer/core/fetch/request_init.idl
new file mode 100644
index 00000000000..82e7336ae8e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/fetch/request_init.idl
@@ -0,0 +1,28 @@
+// 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.
+
+// https://fetch.spec.whatwg.org/#requestinit
+
+// NOTE: Upon adding or removing any dictionary members here you must update
+// the AreAnyMembersPresent function in request.cc.
+
+dictionary RequestInit {
+ ByteString method;
+ HeadersInit headers;
+ // TODO(domfarolino): this should be of type BodyInit? when the IDL
+ // compiler can handle it.
+ any body;
+ USVString referrer;
+ ReferrerPolicy referrerPolicy;
+ RequestMode mode;
+ RequestCredentials credentials;
+ RequestCache cache;
+ RequestRedirect redirect;
+ DOMString integrity;
+ boolean keepalive;
+ [RuntimeEnabled=PriorityHints] RequestImportance importance;
+ AbortSignal? signal;
+ // 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 505ceba49de..20c2a054138 100644
--- a/chromium/third_party/blink/renderer/core/fetch/request_test.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/request_test.cc
@@ -7,10 +7,10 @@
#include <memory>
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_request.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h"
#include "third_party/blink/public/platform/web_url_request.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.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/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/core/fetch/response.cc b/chromium/third_party/blink/renderer/core/fetch/response.cc
index 30bf01469af..61d0c955101 100644
--- a/chromium/third_party/blink/renderer/core/fetch/response.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/response.cc
@@ -5,11 +5,12 @@
#include "third_party/blink/renderer/core/fetch/response.h"
#include <memory>
+
#include "base/memory/scoped_refptr.h"
+#include "base/optional.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_response.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_response.h"
#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
@@ -29,8 +30,9 @@
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
#include "third_party/blink/renderer/core/url/url_search_params.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.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/bindings/v8_private_property.h"
#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/encoded_form_data.h"
@@ -234,11 +236,17 @@ Response* Response::Create(ScriptState* script_state,
new FormDataBytesConsumer(execution_context, std::move(form_data)),
nullptr /* AbortSignal */);
content_type = "application/x-www-form-urlencoded;charset=UTF-8";
- } else if (ReadableStreamOperations::IsReadableStream(script_state,
- body_value)) {
+ } else if (ReadableStreamOperations::IsReadableStream(
+ script_state, body_value, exception_state)
+ .value_or(true)) {
+ if (exception_state.HadException())
+ return nullptr;
UseCounter::Count(execution_context,
WebFeature::kFetchResponseConstructionWithStream);
- body_buffer = new BodyStreamBuffer(script_state, body_value);
+ body_buffer =
+ new BodyStreamBuffer(script_state, body_value, exception_state);
+ if (exception_state.HadException())
+ return nullptr;
} else {
String string = NativeValueTraits<IDLUSVString>::NativeValue(
isolate, body, exception_state);
@@ -316,7 +324,6 @@ Response* Response::Create(ScriptState* script_state,
return nullptr;
}
r->response_->ReplaceBodyStreamBuffer(body);
- r->RefreshBody(script_state);
if (!content_type.IsEmpty() &&
!r->response_->HeaderList()->Has("Content-Type"))
r->response_->HeaderList()->Append("Content-Type", content_type);
@@ -443,13 +450,19 @@ Headers* Response::headers() const {
Response* Response::clone(ScriptState* script_state,
ExceptionState& exception_state) {
- if (IsBodyLocked() || bodyUsed()) {
+ if (IsBodyLocked(exception_state) == BodyLocked::kLocked ||
+ IsBodyUsed(exception_state) == BodyUsed::kUsed) {
+ DCHECK(!exception_state.HadException());
exception_state.ThrowTypeError("Response body is already used");
return nullptr;
}
- FetchResponseData* response = response_->Clone(script_state);
- RefreshBody(script_state);
+ if (exception_state.HadException())
+ return nullptr;
+
+ FetchResponseData* response = response_->Clone(script_state, exception_state);
+ if (exception_state.HadException())
+ return nullptr;
Headers* headers = Headers::Create(response->HeaderList());
headers->SetGuard(headers_->GetGuard());
return new Response(GetExecutionContext(), response, headers);
@@ -485,16 +498,22 @@ Response::Response(ExecutionContext* context, FetchResponseData* response)
Response::Response(ExecutionContext* context,
FetchResponseData* response,
Headers* headers)
- : Body(context), response_(response), headers_(headers) {
- InstallBody();
-}
+ : Body(context), response_(response), headers_(headers) {}
bool Response::HasBody() const {
return response_->InternalBuffer();
}
-bool Response::bodyUsed() {
- return InternalBodyBuffer() && InternalBodyBuffer()->IsStreamDisturbed();
+Body::BodyUsed Response::IsBodyUsed(ExceptionState& exception_state) {
+ auto* body_buffer = InternalBodyBuffer();
+ if (!body_buffer)
+ return BodyUsed::kUnused;
+ base::Optional<bool> stream_disturbed =
+ body_buffer->IsStreamDisturbed(exception_state);
+ if (exception_state.HadException())
+ return BodyUsed::kBroken;
+ DCHECK(stream_disturbed.has_value());
+ return stream_disturbed.value() ? BodyUsed::kUsed : BodyUsed::kUnused;
}
String Response::MimeType() const {
@@ -515,31 +534,15 @@ const Vector<KURL>& Response::InternalURLList() const {
return response_->InternalURLList();
}
-void Response::InstallBody() {
- if (!InternalBodyBuffer())
- return;
- RefreshBody(InternalBodyBuffer()->GetScriptState());
-}
-
-void Response::RefreshBody(ScriptState* script_state) {
- v8::Local<v8::Value> body_buffer = ToV8(InternalBodyBuffer(), script_state);
- v8::Local<v8::Value> response = ToV8(this, script_state);
- if (response.IsEmpty()) {
- // |toV8| can return an empty handle when the worker is terminating.
- // We don't want the renderer to crash in such cases.
- // TODO(yhirano): Delete this block after the graceful shutdown
- // mechanism is introduced.
- return;
- }
- DCHECK(response->IsObject());
- V8PrivateProperty::GetInternalBodyBuffer(script_state->GetIsolate())
- .Set(response.As<v8::Object>(), body_buffer);
-}
-
void Response::Trace(blink::Visitor* visitor) {
Body::Trace(visitor);
visitor->Trace(response_);
visitor->Trace(headers_);
}
+bool Response::IsBodyUsedForDCheck() {
+ return InternalBodyBuffer() &&
+ InternalBodyBuffer()->IsStreamDisturbedForDCheck();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fetch/response.h b/chromium/third_party/blink/renderer/core/fetch/response.h
index 45b81d8c7f6..33463f83bed 100644
--- a/chromium/third_party/blink/renderer/core/fetch/response.h
+++ b/chromium/third_party/blink/renderer/core/fetch/response.h
@@ -92,7 +92,8 @@ class CORE_EXPORT Response final : public Body {
const BodyStreamBuffer* InternalBodyBuffer() const {
return response_->InternalBuffer();
}
- bool bodyUsed() override;
+
+ BodyUsed IsBodyUsed(ExceptionState&) override;
String ContentType() const override;
String MimeType() const override;
@@ -102,15 +103,17 @@ class CORE_EXPORT Response final : public Body {
void Trace(blink::Visitor*) override;
+ protected:
+ // A version of IsBodyUsed() which catches exceptions and returns
+ // false. Should never be used outside DCHECK().
+ bool IsBodyUsedForDCheck() override;
+
private:
explicit Response(ExecutionContext*);
Response(ExecutionContext*, FetchResponseData*);
Response(ExecutionContext*, FetchResponseData*, Headers*);
- void InstallBody();
- void RefreshBody(ScriptState*);
-
- const Member<FetchResponseData> response_;
+ const TraceWrapperMember<FetchResponseData> response_;
const Member<Headers> headers_;
DISALLOW_COPY_AND_ASSIGN(Response);
};
diff --git a/chromium/third_party/blink/renderer/core/fetch/response_test.cc b/chromium/third_party/blink/renderer/core/fetch/response_test.cc
index 3325cefcb60..3e8deb38433 100644
--- a/chromium/third_party/blink/renderer/core/fetch/response_test.cc
+++ b/chromium/third_party/blink/renderer/core/fetch/response_test.cc
@@ -7,8 +7,7 @@
#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_response.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_response.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
@@ -18,6 +17,7 @@
#include "third_party/blink/renderer/core/fetch/fetch_response_data.h"
#include "third_party/blink/renderer/core/frame/frame.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.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/blob/blob_data.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
@@ -209,9 +209,9 @@ void CheckResponseStream(ScriptState* script_state,
EXPECT_CALL(*client2, DidFetchDataLoadedString(String("Hello, world")));
response->InternalBodyBuffer()->StartLoading(
- FetchDataLoader::CreateLoaderAsString(), client1);
+ FetchDataLoader::CreateLoaderAsString(), client1, ASSERT_NO_EXCEPTION);
cloned_response->InternalBodyBuffer()->StartLoading(
- FetchDataLoader::CreateLoaderAsString(), client2);
+ FetchDataLoader::CreateLoaderAsString(), client2, ASSERT_NO_EXCEPTION);
blink::test::RunPendingTasks();
}
@@ -310,9 +310,9 @@ TEST(ServiceWorkerResponseTest, BodyStreamBufferCloneError) {
EXPECT_CALL(*client2, DidFetchDataLoadFailed());
response->InternalBodyBuffer()->StartLoading(
- FetchDataLoader::CreateLoaderAsString(), client1);
+ FetchDataLoader::CreateLoaderAsString(), client1, ASSERT_NO_EXCEPTION);
cloned_response->InternalBodyBuffer()->StartLoading(
- FetchDataLoader::CreateLoaderAsString(), client2);
+ FetchDataLoader::CreateLoaderAsString(), client2, ASSERT_NO_EXCEPTION);
blink::test::RunPendingTasks();
}
diff --git a/chromium/third_party/blink/renderer/core/fetch/window_fetch.idl b/chromium/third_party/blink/renderer/core/fetch/window_fetch.idl
index f2de064f0bc..a6170ea1a8e 100644
--- a/chromium/third_party/blink/renderer/core/fetch/window_fetch.idl
+++ b/chromium/third_party/blink/renderer/core/fetch/window_fetch.idl
@@ -5,5 +5,5 @@
[
ImplementedAs=GlobalFetch
] partial interface Window {
- [CallWith=ScriptState, NewObject, RaisesException] Promise<Response> fetch(RequestInfo input, optional Dictionary init);
+ [CallWith=ScriptState, NewObject, RaisesException] Promise<Response> fetch(RequestInfo input, optional RequestInit init);
};
diff --git a/chromium/third_party/blink/renderer/core/fetch/worker_fetch.idl b/chromium/third_party/blink/renderer/core/fetch/worker_fetch.idl
index 1954a75dc62..b210f6cfee6 100644
--- a/chromium/third_party/blink/renderer/core/fetch/worker_fetch.idl
+++ b/chromium/third_party/blink/renderer/core/fetch/worker_fetch.idl
@@ -5,5 +5,5 @@
[
ImplementedAs=GlobalFetch
] partial interface WorkerGlobalScope {
- [CallWith=ScriptState, NewObject, RaisesException] Promise<Response> fetch(RequestInfo input, optional Dictionary init);
+ [CallWith=ScriptState, NewObject, RaisesException] Promise<Response> fetch(RequestInfo input, optional RequestInit init);
};
diff --git a/chromium/third_party/blink/renderer/core/fileapi/OWNERS b/chromium/third_party/blink/renderer/core/fileapi/OWNERS
index 75048f422da..792720cc02c 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/OWNERS
+++ b/chromium/third_party/blink/renderer/core/fileapi/OWNERS
@@ -3,4 +3,4 @@ mek@chromium.org
pwnall@chromium.org
# TEAM: storage-dev@chromium.org
-# COMPONENT: Blink>FileAPI
+# COMPONENT: Blink>Storage>FileAPI
diff --git a/chromium/third_party/blink/renderer/core/fileapi/blob.cc b/chromium/third_party/blink/renderer/core/fileapi/blob.cc
index c82f88fbaa2..87c33867bc0 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/blob.cc
+++ b/chromium/third_party/blink/renderer/core/fileapi/blob.cc
@@ -31,12 +31,11 @@
#include "third_party/blink/renderer/core/fileapi/blob.h"
#include <memory>
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fileapi/blob_property_bag.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/url/dom_url.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/blob/blob_registry.h"
#include "third_party/blink/renderer/platform/blob/blob_url.h"
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file.cc b/chromium/third_party/blink/renderer/core/fileapi/file.cc
index 78b2299e35d..01df3889651 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/file.cc
+++ b/chromium/third_party/blink/renderer/core/fileapi/file.cc
@@ -26,12 +26,12 @@
#include "third_party/blink/renderer/core/fileapi/file.h"
#include <memory>
+
#include "third_party/blink/public/platform/file_path_conversion.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/fileapi/file_property_bag.h"
#include "third_party/blink/renderer/core/frame/use_counter.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/blob/blob_data.h"
#include "third_party/blink/renderer/platform/file_metadata.h"
@@ -70,6 +70,11 @@ static std::unique_ptr<BlobData> CreateBlobDataForFileWithType(
static std::unique_ptr<BlobData> CreateBlobDataForFile(
const String& path,
File::ContentTypeLookupPolicy policy) {
+ if (path.IsEmpty()) {
+ std::unique_ptr<BlobData> blob_data = BlobData::Create();
+ blob_data->SetContentType("application/octet-stream");
+ return blob_data;
+ }
return CreateBlobDataForFileWithType(
path, GetContentTypeFromFileName(path, policy));
}
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_error.cc b/chromium/third_party/blink/renderer/core/fileapi/file_error.cc
index 1dd5f239998..990ab274b2d 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/file_error.cc
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_error.cc
@@ -31,9 +31,8 @@
#include "third_party/blink/renderer/core/fileapi/file_error.h"
#include "third_party/blink/public/platform/web_file_error.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink {
@@ -74,37 +73,37 @@ const char kTypeMismatchErrorMessage[] =
namespace {
-ExceptionCode ErrorCodeToExceptionCode(ErrorCode code) {
+DOMExceptionCode ErrorCodeToExceptionCode(ErrorCode code) {
switch (code) {
case kOK:
- return 0;
+ return DOMExceptionCode::kNoError;
case kNotFoundErr:
- return kNotFoundError;
+ return DOMExceptionCode::kNotFoundError;
case kSecurityErr:
- return kSecurityError;
+ return DOMExceptionCode::kSecurityError;
case kAbortErr:
- return kAbortError;
+ return DOMExceptionCode::kAbortError;
case kNotReadableErr:
- return kNotReadableError;
+ return DOMExceptionCode::kNotReadableError;
case kEncodingErr:
- return kEncodingError;
+ return DOMExceptionCode::kEncodingError;
case kNoModificationAllowedErr:
- return kNoModificationAllowedError;
+ return DOMExceptionCode::kNoModificationAllowedError;
case kInvalidStateErr:
- return kInvalidStateError;
+ return DOMExceptionCode::kInvalidStateError;
case kSyntaxErr:
- return kSyntaxError;
+ return DOMExceptionCode::kSyntaxError;
case kInvalidModificationErr:
- return kInvalidModificationError;
+ return DOMExceptionCode::kInvalidModificationError;
case kQuotaExceededErr:
- return kQuotaExceededError;
+ return DOMExceptionCode::kQuotaExceededError;
case kTypeMismatchErr:
- return kTypeMismatchError;
+ return DOMExceptionCode::kTypeMismatchError;
case kPathExistsErr:
- return kPathExistsError;
+ return DOMExceptionCode::kPathExistsError;
default:
NOTREACHED();
- return code;
+ return DOMExceptionCode::kUnknownError;
}
}
@@ -146,19 +145,24 @@ const char* ErrorCodeToMessage(ErrorCode code) {
} // namespace
-void ThrowDOMException(ExceptionState& exception_state, ErrorCode code) {
+void ThrowDOMException(ExceptionState& exception_state,
+ ErrorCode code,
+ String message) {
if (code == kOK)
return;
// SecurityError is special-cased, as we want to route those exceptions
- // through ExceptionState::throwSecurityError.
+ // through ExceptionState::ThrowSecurityError.
if (code == kSecurityErr) {
exception_state.ThrowSecurityError(kSecurityErrorMessage);
return;
}
- exception_state.ThrowDOMException(ErrorCodeToExceptionCode(code),
- ErrorCodeToMessage(code));
+ if (message.IsNull()) {
+ message = ErrorCodeToMessage(code);
+ }
+
+ exception_state.ThrowDOMException(ErrorCodeToExceptionCode(code), message);
}
DOMException* CreateDOMException(ErrorCode code) {
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_error.h b/chromium/third_party/blink/renderer/core/fileapi/file_error.h
index 55f11174804..4b5408c1479 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/file_error.h
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_error.h
@@ -32,6 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_ERROR_H_
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -68,7 +69,9 @@ CORE_EXPORT extern const char kSecurityErrorMessage[];
CORE_EXPORT extern const char kSyntaxErrorMessage[];
CORE_EXPORT extern const char kTypeMismatchErrorMessage[];
-CORE_EXPORT void ThrowDOMException(ExceptionState&, ErrorCode);
+CORE_EXPORT void ThrowDOMException(ExceptionState&,
+ ErrorCode,
+ String message = String());
CORE_EXPORT DOMException* CreateDOMException(ErrorCode);
} // namespace FileError
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 ee0922f85bd..d2e87ac7ddf 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/file_reader.cc
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_reader.cc
@@ -32,16 +32,15 @@
#include "base/auto_reset.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/dom/exception_code.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/frame/use_counter.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/supplementable.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
@@ -277,14 +276,16 @@ void FileReader::ReadInternal(Blob* blob,
// InvalidStateError should be thrown when the state is kLoading.
if (state_ == kLoading) {
exception_state.ThrowDOMException(
- kInvalidStateError, "The object is already busy reading Blobs.");
+ DOMExceptionCode::kInvalidStateError,
+ "The object is already busy reading Blobs.");
return;
}
ExecutionContext* context = GetExecutionContext();
if (!context) {
exception_state.ThrowDOMException(
- kAbortError, "Reading from a detached FileReader is not supported.");
+ DOMExceptionCode::kAbortError,
+ "Reading from a detached FileReader is not supported.");
return;
}
@@ -292,7 +293,7 @@ void FileReader::ReadInternal(Blob* blob,
// detached from its frame.
if (context->IsDocument() && !ToDocument(context)->GetFrame()) {
exception_state.ThrowDOMException(
- kAbortError,
+ DOMExceptionCode::kAbortError,
"Reading from a Document-detached FileReader is not supported.");
return;
}
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.cc b/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.cc
index 5543f63bc48..88fa2d46436 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.cc
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.cc
@@ -93,7 +93,7 @@ void FileReaderLoader::Start(scoped_refptr<BlobDataHandle> blob_data) {
MojoResult result =
CreateDataPipe(nullptr, &producer_handle, &consumer_handle_);
if (result != MOJO_RESULT_OK) {
- Failed(FileError::kNotReadableErr);
+ Failed(FileError::kNotReadableErr, FailureType::kMojoPipeCreation);
return;
}
@@ -108,14 +108,16 @@ void FileReaderLoader::Start(scoped_refptr<BlobDataHandle> blob_data) {
if (received_on_complete_)
return;
if (!received_all_data_) {
- Failed(FileError::kNotReadableErr);
+ Failed(FileError::kNotReadableErr, FailureType::kSyncDataNotAllLoaded);
return;
}
// Wait for OnComplete
binding_.WaitForIncomingMethodCall();
- if (!received_on_complete_)
- Failed(FileError::kNotReadableErr);
+ if (!received_on_complete_) {
+ Failed(FileError::kNotReadableErr,
+ FailureType::kSyncOnCompleteNotReceived);
+ }
}
}
@@ -198,11 +200,16 @@ void FileReaderLoader::Cleanup() {
}
}
-void FileReaderLoader::Failed(FileError::ErrorCode error_code) {
+void FileReaderLoader::Failed(FileError::ErrorCode error_code,
+ FailureType type) {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(EnumerationHistogram, failure_histogram,
+ ("Storage.Blob.FileReaderLoader.FailureType",
+ static_cast<int>(FailureType::kCount)));
// If an error was already reported, don't report this error again.
if (error_code_ != FileError::kOK)
return;
error_code_ = error_code;
+ failure_histogram.Count(static_cast<int>(type));
Cleanup();
if (client_)
client_->DidFail(error_code_);
@@ -218,13 +225,14 @@ void FileReaderLoader::OnStartLoading(uint64_t total_bytes) {
// so to call ArrayBuffer's create function.
// FIXME: Support reading more than the current size limit of ArrayBuffer.
if (total_bytes > std::numeric_limits<unsigned>::max()) {
- Failed(FileError::kNotReadableErr);
+ Failed(FileError::kNotReadableErr, FailureType::kTotalBytesTooLarge);
return;
}
raw_data_ = std::make_unique<ArrayBufferBuilder>(total_bytes);
if (!raw_data_->IsValid()) {
- Failed(FileError::kNotReadableErr);
+ Failed(FileError::kNotReadableErr,
+ FailureType::kArrayBufferBuilderCreation);
return;
}
raw_data_->SetVariableCapacity(false);
@@ -253,7 +261,7 @@ void FileReaderLoader::OnReceivedData(const char* data, unsigned data_length) {
if (!bytes_appended) {
raw_data_.reset();
bytes_loaded_ = 0;
- Failed(FileError::kNotReadableErr);
+ Failed(FileError::kNotReadableErr, FailureType::kArrayBufferBuilderAppend);
return;
}
bytes_loaded_ += bytes_appended;
@@ -305,12 +313,16 @@ void FileReaderLoader::OnComplete(int32_t status, uint64_t data_length) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(SparseHistogram,
file_reader_loader_read_errors_histogram,
("Storage.Blob.FileReaderLoader.ReadError"));
- if (status != net::OK || data_length != total_bytes_) {
+ if (status != net::OK) {
net_error_ = status;
- if (net_error_ != net::OK)
- file_reader_loader_read_errors_histogram.Sample(std::max(0, -net_error_));
+ file_reader_loader_read_errors_histogram.Sample(std::max(0, -net_error_));
Failed(status == net::ERR_FILE_NOT_FOUND ? FileError::kNotFoundErr
- : FileError::kNotReadableErr);
+ : FileError::kNotReadableErr,
+ FailureType::kBackendReadError);
+ return;
+ }
+ if (data_length != total_bytes_) {
+ Failed(FileError::kNotReadableErr, FailureType::kReadSizesIncorrect);
return;
}
@@ -321,8 +333,10 @@ void FileReaderLoader::OnComplete(int32_t status, uint64_t data_length) {
void FileReaderLoader::OnDataPipeReadable(MojoResult result) {
if (result != MOJO_RESULT_OK) {
- if (!received_all_data_)
- Failed(FileError::kNotReadableErr);
+ if (!received_all_data_) {
+ Failed(FileError::kNotReadableErr,
+ FailureType::kDataPipeNotReadableWithBytesLeft);
+ }
return;
}
@@ -341,12 +355,14 @@ void FileReaderLoader::OnDataPipeReadable(MojoResult result) {
}
if (result == MOJO_RESULT_FAILED_PRECONDITION) {
// Pipe closed.
- if (!received_all_data_)
- Failed(FileError::kNotReadableErr);
+ if (!received_all_data_) {
+ Failed(FileError::kNotReadableErr, FailureType::kMojoPipeClosedEarly);
+ }
return;
}
if (result != MOJO_RESULT_OK) {
- Failed(FileError::kNotReadableErr);
+ Failed(FileError::kNotReadableErr,
+ FailureType::kMojoPipeUnexpectedReadError);
return;
}
OnReceivedData(static_cast<const char*>(buffer), num_bytes);
@@ -408,7 +424,13 @@ String FileReaderLoader::ConvertToDataURL() {
if (!bytes_loaded_)
return builder.ToString();
- builder.Append(data_type_);
+ if (data_type_.IsEmpty()) {
+ // Match Firefox in defaulting to application/octet-stream when the MIME
+ // type is unknown. See https://crbug.com/48368.
+ builder.Append("application/octet-stream");
+ } else {
+ builder.Append(data_type_);
+ }
builder.Append(";base64,");
Vector<char> out;
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.h b/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.h
index 0f1bfdbf047..6b5d8b3ec31 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.h
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_reader_loader.h
@@ -107,8 +107,28 @@ class CORE_EXPORT FileReaderLoader : public mojom::blink::BlobReaderClient {
bool HasFinishedLoading() const { return finished_loading_; }
private:
+ // These values are persisted to logs. Entries should not be renumbered and
+ // numeric values should never be reused.
+ enum class FailureType {
+ kMojoPipeCreation = 0,
+ kSyncDataNotAllLoaded = 1,
+ kSyncOnCompleteNotReceived = 2,
+ kTotalBytesTooLarge = 3,
+ kArrayBufferBuilderCreation = 4,
+ kArrayBufferBuilderAppend = 5,
+ kBackendReadError = 6,
+ kReadSizesIncorrect = 7,
+ kDataPipeNotReadableWithBytesLeft = 8,
+ kMojoPipeClosedEarly = 9,
+ // Any MojoResult error we aren't expecting during data pipe reading falls
+ // into this bucket. If there are a large number of errors reported here,
+ // then there can be a new enumeration reported for mojo pipe errors.
+ kMojoPipeUnexpectedReadError = 10,
+ kCount
+ };
+
void Cleanup();
- void Failed(FileError::ErrorCode);
+ void Failed(FileError::ErrorCode, FailureType type);
void OnStartLoading(uint64_t total_bytes);
void OnReceivedData(const char* data, unsigned data_length);
diff --git a/chromium/third_party/blink/renderer/core/fileapi/file_reader_sync.cc b/chromium/third_party/blink/renderer/core/fileapi/file_reader_sync.cc
index 94d3943339b..ebd429f6a8e 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/file_reader_sync.cc
+++ b/chromium/third_party/blink/renderer/core/fileapi/file_reader_sync.cc
@@ -30,12 +30,12 @@
#include "third_party/blink/renderer/core/fileapi/file_reader_sync.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/fileapi/file_error.h"
#include "third_party/blink/renderer/core/fileapi/file_reader_loader.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.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/histogram.h"
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 19faf5d2f96..d54672b81df 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
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
+#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink.h"
#include "third_party/blink/renderer/core/fileapi/url_registry.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
@@ -114,7 +115,7 @@ String PublicURLManager::RegisterURL(URLRegistrable* registrable) {
const String& url_string = url.GetString();
mojom::blink::BlobPtr blob;
- if (RuntimeEnabledFeatures::MojoBlobURLsEnabled())
+ if (BlobUtils::MojoBlobURLsEnabled())
blob = registrable->AsMojoBlob();
if (blob) {
if (!url_store_) {
@@ -144,7 +145,7 @@ void PublicURLManager::Revoke(const KURL& url) {
GetExecutionContext()->GetSecurityOrigin()))
return;
- if (RuntimeEnabledFeatures::MojoBlobURLsEnabled()) {
+ if (BlobUtils::MojoBlobURLsEnabled()) {
if (!url_store_) {
BlobDataHandle::GetBlobRegistry()->URLStoreForOrigin(
GetExecutionContext()->GetSecurityOrigin(), MakeRequest(&url_store_));
@@ -163,7 +164,7 @@ void PublicURLManager::Revoke(const KURL& url) {
void PublicURLManager::Resolve(
const KURL& url,
network::mojom::blink::URLLoaderFactoryRequest factory_request) {
- DCHECK(RuntimeEnabledFeatures::MojoBlobURLsEnabled());
+ DCHECK(BlobUtils::MojoBlobURLsEnabled());
DCHECK(url.ProtocolIs("blob"));
if (!url_store_) {
BlobDataHandle::GetBlobRegistry()->URLStoreForOrigin(
@@ -175,7 +176,7 @@ void PublicURLManager::Resolve(
void PublicURLManager::Resolve(
const KURL& url,
mojom::blink::BlobURLTokenRequest token_request) {
- DCHECK(RuntimeEnabledFeatures::MojoBlobURLsEnabled());
+ DCHECK(BlobUtils::MojoBlobURLsEnabled());
DCHECK(url.ProtocolIs("blob"));
if (!url_store_) {
BlobDataHandle::GetBlobRegistry()->URLStoreForOrigin(
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 7e2a27d1284..ff8c275f0de 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
@@ -4,9 +4,11 @@
#include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
+#include "base/test/scoped_feature_list.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/core/fileapi/url_registry.h"
#include "third_party/blink/renderer/core/testing/null_execution_context.h"
#include "third_party/blink/renderer/platform/blob/testing/fake_blob.h"
@@ -67,6 +69,8 @@ class PublicURLManagerTest : public testing::Test {
PublicURLManagerTest() : url_store_binding_(&url_store_) {}
void SetUp() override {
+ scoped_feature_list_.InitAndEnableFeature(features::kMojoBlobURLs);
+
execution_context_ = new NullExecutionContext;
// By default this creates a unique origin, which is exactly what this test
// wants.
@@ -90,7 +94,7 @@ class PublicURLManagerTest : public testing::Test {
}
protected:
- ScopedMojoBlobURLsForTest mojo_blob_urls_ = true;
+ base::test::ScopedFeatureList scoped_feature_list_;
Persistent<NullExecutionContext> execution_context_;
FakeBlobURLStore url_store_;
diff --git a/chromium/third_party/blink/renderer/core/fileapi/url_file_api.cc b/chromium/third_party/blink/renderer/core/fileapi/url_file_api.cc
index dc29bc939df..2a253e03531 100644
--- a/chromium/third_party/blink/renderer/core/fileapi/url_file_api.cc
+++ b/chromium/third_party/blink/renderer/core/fileapi/url_file_api.cc
@@ -4,12 +4,12 @@
#include "third_party/blink/renderer/core/fileapi/url_file_api.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/fileapi/public_url_manager.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/url/dom_url.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/frame/BUILD.gn b/chromium/third_party/blink/renderer/core/frame/BUILD.gn
index a902ed3885d..faf80c781f1 100644
--- a/chromium/third_party/blink/renderer/core/frame/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/frame/BUILD.gn
@@ -29,9 +29,11 @@ blink_core_sources("frame") {
"deprecated_schedule_style_recalc_during_layout.h",
"deprecation.cc",
"deprecation.h",
- "deprecation_report.h",
+ "deprecation_report_body.h",
"device_single_window_event_controller.cc",
"device_single_window_event_controller.h",
+ "display_cutout_client_impl.cc",
+ "display_cutout_client_impl.h",
"dom_timer.cc",
"dom_timer.h",
"dom_timer_coordinator.cc",
@@ -73,10 +75,11 @@ blink_core_sources("frame") {
"hosts_using_features.h",
"intervention.cc",
"intervention.h",
- "intervention_report.h",
- "intrinsic_sizing_info.h",
+ "intervention_report_body.h",
"layout_subtree_root_list.cc",
"layout_subtree_root_list.h",
+ "link_highlights.cc",
+ "link_highlights.h",
"local_dom_window.cc",
"local_dom_window.h",
"local_frame.cc",
@@ -86,7 +89,7 @@ blink_core_sources("frame") {
"local_frame_view.h",
"location.cc",
"location.h",
- "message_report.h",
+ "message_report_body.h",
"navigator.cc",
"navigator.h",
"navigator_concurrent_hardware.cc",
@@ -98,6 +101,8 @@ blink_core_sources("frame") {
"navigator_language.cc",
"navigator_language.h",
"navigator_on_line.h",
+ "navigator_user_activation.cc",
+ "navigator_user_activation.h",
"opened_frame_tracker.cc",
"opened_frame_tracker.h",
"page_scale_constraints.cc",
@@ -155,8 +160,10 @@ blink_core_sources("frame") {
"smart_clip.h",
"use_counter.cc",
"use_counter.h",
- "user_activation_state.cc",
- "user_activation_state.h",
+ "user_activation.cc",
+ "user_activation.h",
+ "viewport_data.cc",
+ "viewport_data.h",
"visual_viewport.cc",
"visual_viewport.h",
"web_feature.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 ea6da545068..7b142845ba1 100644
--- a/chromium/third_party/blink/renderer/core/frame/ad_tracker.cc
+++ b/chromium/third_party/blink/renderer/core/frame/ad_tracker.cc
@@ -4,7 +4,10 @@
#include "third_party/blink/renderer/core/frame/ad_tracker.h"
+#include <memory>
+
#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/CoreProbeSink.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
@@ -35,9 +38,18 @@ String AdTracker::ScriptAtTopOfStack(ExecutionContext* execution_context) {
return current_stack_trace ? current_stack_trace->Url() : "";
}
-void AdTracker::WillExecuteScript(const String& script_url) {
- bool is_ad =
- script_url.IsEmpty() ? false : known_ad_scripts_.Contains(script_url);
+ExecutionContext* AdTracker::GetCurrentExecutionContext() {
+ // Determine the current ExecutionContext.
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ v8::Local<v8::Context> context = isolate->GetCurrentContext();
+ return context.IsEmpty() ? nullptr : ToExecutionContext(context);
+}
+
+void AdTracker::WillExecuteScript(ExecutionContext* execution_context,
+ const String& script_url) {
+ bool is_ad = script_url.IsEmpty()
+ ? false
+ : IsKnownAdScript(execution_context, script_url);
ExecutingScript script(script_url, is_ad);
executing_scripts_.push_back(script);
}
@@ -47,7 +59,7 @@ void AdTracker::DidExecuteScript() {
}
void AdTracker::Will(const probe::ExecuteScript& probe) {
- WillExecuteScript(probe.script_url);
+ WillExecuteScript(probe.context, probe.script_url);
}
void AdTracker::Did(const probe::ExecuteScript& probe) {
@@ -65,7 +77,7 @@ void AdTracker::Will(const probe::CallFunction& probe) {
String script_url;
if (!resource_name.IsEmpty())
script_url = ToCoreString(resource_name->ToString());
- WillExecuteScript(script_url);
+ WillExecuteScript(probe.context, script_url);
}
void AdTracker::Did(const probe::CallFunction& probe) {
@@ -84,20 +96,26 @@ void AdTracker::WillSendRequest(ExecutionContext* execution_context,
Resource::Type resource_type) {
// If the resource is not already marked as an ad, check if any executing
// script is an ad. If yes, mark this as an ad.
- if (!request.IsAdResource() && IsAdScriptInStack(execution_context))
+ if (!request.IsAdResource() && IsAdScriptInStack())
request.SetIsAdResource();
// If it is a script marked as an ad, append it to the known ad scripts set.
- if (resource_type == Resource::kScript && request.IsAdResource())
- AppendToKnownAdScripts(request.Url());
+ if (resource_type == Resource::kScript && request.IsAdResource()) {
+ AppendToKnownAdScripts(*execution_context, request.Url().GetString());
+ }
}
-bool AdTracker::IsAdScriptInStack(ExecutionContext* execution_context) {
+bool AdTracker::IsAdScriptInStack() {
+ ExecutionContext* execution_context = GetCurrentExecutionContext();
+ if (!execution_context)
+ return false;
+
// The pseudo-stack contains entry points into the stack (e.g., when v8 is
// executed) but not the entire stack. It's cheap to retrieve the top of the
// stack so scan that as well.
String top_script = ScriptAtTopOfStack(execution_context);
- if (!top_script.IsEmpty() && known_ad_scripts_.Contains(top_script))
+
+ if (!top_script.IsEmpty() && IsKnownAdScript(execution_context, top_script))
return true;
// Scan the pseudo-stack for ad scripts.
@@ -108,13 +126,28 @@ bool AdTracker::IsAdScriptInStack(ExecutionContext* execution_context) {
return false;
}
+bool AdTracker::IsKnownAdScript(ExecutionContext* execution_context,
+ const String& url) {
+ if (!execution_context)
+ return false;
+
+ auto it = known_ad_scripts_.find(execution_context);
+ if (it == known_ad_scripts_.end())
+ return false;
+ return it->value.find(url) != it->value.end();
+}
+
// This is a separate function for testing purposes.
-void AdTracker::AppendToKnownAdScripts(const KURL& url) {
- known_ad_scripts_.insert(url.GetString());
+void AdTracker::AppendToKnownAdScripts(ExecutionContext& execution_context,
+ const String& url) {
+ auto add_result =
+ known_ad_scripts_.insert(&execution_context, HashSet<String>());
+ add_result.stored_value->value.insert(url);
}
void AdTracker::Trace(blink::Visitor* visitor) {
visitor->Trace(local_root_);
+ visitor->Trace(known_ad_scripts_);
}
} // namespace blink
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 e0421c77836..f9b36167ea9 100644
--- a/chromium/third_party/blink/renderer/core/frame/ad_tracker.h
+++ b/chromium/third_party/blink/renderer/core/frame/ad_tracker.h
@@ -7,8 +7,10 @@
#include "base/macros.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/platform/heap/member.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.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"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "v8/include/v8.h"
@@ -43,17 +45,18 @@ class CORE_EXPORT AdTracker : public GarbageCollectedFinalized<AdTracker> {
// - Mark a resource request as an ad if any executing scripts contain an ad.
// - If the marked resource is a script, also save it to keep track of all
// those script resources that have been identified as ads.
- void WillSendRequest(ExecutionContext*,
- unsigned long identifier,
- DocumentLoader*,
- ResourceRequest&,
- const ResourceResponse& redirect_response,
- const FetchInitiatorInfo&,
- Resource::Type);
-
- // Returns true if any script in the pseudo call stack have previously been
+ // Virtual for testing.
+ virtual void WillSendRequest(ExecutionContext*,
+ unsigned long identifier,
+ DocumentLoader*,
+ ResourceRequest&,
+ const ResourceResponse& redirect_response,
+ const FetchInitiatorInfo&,
+ Resource::Type);
+
+ // Returns true if any script in the pseudo call stack has previously been
// identified as an ad resource.
- bool IsAdScriptInStack(ExecutionContext*);
+ bool IsAdScriptInStack();
virtual void Trace(blink::Visitor*);
@@ -64,28 +67,33 @@ class CORE_EXPORT AdTracker : public GarbageCollectedFinalized<AdTracker> {
protected:
// Protected for testing.
virtual String ScriptAtTopOfStack(ExecutionContext*);
+ virtual ExecutionContext* GetCurrentExecutionContext();
private:
friend class FrameFetchContextSubresourceFilterTest;
+ friend class AdTrackerSimTest;
friend class AdTrackerTest;
- void WillExecuteScript(const String& script_name);
+ void WillExecuteScript(ExecutionContext*, const String& script_name);
void DidExecuteScript();
- void AppendToKnownAdScripts(const KURL&);
+ bool IsKnownAdScript(ExecutionContext* execution_context, const String& url);
+ void AppendToKnownAdScripts(ExecutionContext&, const String& url);
Member<LocalFrame> local_root_;
// Since the script URLs should be external strings in v8 (allocated in Blink)
// getting it as String should end up with the same StringImpl. Thus storing a
// vector of Strings here should not be expensive.
+ // TODO(jkarlin): We don't need this struct. A Vector<bool> would suffice.
struct ExecutingScript {
String url;
bool is_ad;
ExecutingScript(String script_url, bool is_ad_script)
- : url(script_url), is_ad(is_ad_script){};
+ : url(script_url), is_ad(is_ad_script) {}
};
+
Vector<ExecutingScript> executing_scripts_;
- HashSet<String> known_ad_scripts_;
+ HeapHashMap<WeakMember<ExecutionContext>, HashSet<String>> known_ad_scripts_;
DISALLOW_COPY_AND_ASSIGN(AdTracker);
};
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 d7de5d47bfc..68ca2035ba3 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
@@ -4,12 +4,15 @@
#include "third_party/blink/renderer/core/frame/ad_tracker.h"
+#include <memory>
+
#include "testing/gtest/include/gtest/gtest.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/core/testing/dummy_page_holder.h"
-
-#include <memory>
+#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 {
@@ -18,18 +21,54 @@ namespace {
class TestAdTracker : public AdTracker {
public:
explicit TestAdTracker(LocalFrame* frame) : AdTracker(frame) {}
- void SetScriptAtTopOfStack(String url) { script_at_top_ = url; }
+ void SetScriptAtTopOfStack(const String& url) { script_at_top_ = url; }
+ void SetExecutionContext(ExecutionContext* execution_context) {
+ execution_context_ = execution_context;
+ }
+
+ void SetAdSuffix(const String& ad_suffix) { ad_suffix_ = ad_suffix; }
~TestAdTracker() override {}
+ void Trace(Visitor* visitor) override {
+ visitor->Trace(execution_context_);
+ AdTracker::Trace(visitor);
+ }
+
protected:
- // Returns "" by default unless SetScriptAtTopOfStack is called with
- // something else.
String ScriptAtTopOfStack(ExecutionContext* execution_context) override {
+ if (script_at_top_.IsEmpty())
+ return AdTracker::ScriptAtTopOfStack(execution_context);
+
return script_at_top_;
}
+ ExecutionContext* GetCurrentExecutionContext() override {
+ if (!execution_context_)
+ return AdTracker::GetCurrentExecutionContext();
+
+ return execution_context_;
+ }
+
+ void WillSendRequest(ExecutionContext* execution_context,
+ unsigned long identifier,
+ DocumentLoader* document_loader,
+ ResourceRequest& resource_request,
+ const ResourceResponse& redirect_response,
+ const FetchInitiatorInfo& fetch_initiator_info,
+ Resource::Type resource_type) override {
+ if (!ad_suffix_.IsEmpty() &&
+ resource_request.Url().GetString().EndsWith(ad_suffix_)) {
+ resource_request.SetIsAdResource();
+ }
+ AdTracker::WillSendRequest(execution_context, identifier, document_loader,
+ resource_request, redirect_response,
+ fetch_initiator_info, resource_type);
+ }
+
private:
String script_at_top_;
+ Member<ExecutionContext> execution_context_;
+ String ad_suffix_;
};
} // namespace
@@ -43,15 +82,16 @@ class AdTrackerTest : public testing::Test {
}
void WillExecuteScript(const String& script_url) {
- ad_tracker_->WillExecuteScript(script_url);
+ ad_tracker_->WillExecuteScript(&page_holder_->GetDocument(),
+ String(script_url));
}
bool AnyExecutingScriptsTaggedAsAdResource() {
- return ad_tracker_->IsAdScriptInStack(&page_holder_->GetDocument());
+ return ad_tracker_->IsAdScriptInStack();
}
- void AppendToKnownAdScripts(const KURL& url) {
- ad_tracker_->AppendToKnownAdScripts(url);
+ void AppendToKnownAdScripts(const String& url) {
+ ad_tracker_->AppendToKnownAdScripts(page_holder_->GetDocument(), url);
}
Persistent<TestAdTracker> ad_tracker_;
@@ -62,6 +102,7 @@ void AdTrackerTest::SetUp() {
page_holder_ = DummyPageHolder::Create(IntSize(800, 600));
page_holder_->GetDocument().SetURL(KURL("https://example.com/foo"));
ad_tracker_ = new TestAdTracker(GetFrame());
+ ad_tracker_->SetExecutionContext(&page_holder_->GetDocument());
}
void AdTrackerTest::TearDown() {
@@ -69,7 +110,7 @@ void AdTrackerTest::TearDown() {
}
TEST_F(AdTrackerTest, AnyExecutingScriptsTaggedAsAdResource) {
- KURL ad_script_url("https://example.com/bar.js");
+ String ad_script_url("https://example.com/bar.js");
AppendToKnownAdScripts(ad_script_url);
WillExecuteScript("https://example.com/foo.js");
@@ -86,7 +127,7 @@ TEST_F(AdTrackerTest, AnyExecutingScriptsTaggedAsAdResource_False) {
}
TEST_F(AdTrackerTest, TopOfStackIncluded) {
- KURL ad_script_url("https://example.com/ad.js");
+ String ad_script_url("https://example.com/ad.js");
AppendToKnownAdScripts(ad_script_url);
WillExecuteScript("https://example.com/foo.js");
@@ -105,11 +146,176 @@ TEST_F(AdTrackerTest, TopOfStackIncluded) {
ad_tracker_->SetScriptAtTopOfStack("");
EXPECT_FALSE(AnyExecutingScriptsTaggedAsAdResource());
- ad_tracker_->SetScriptAtTopOfStack(WTF::String());
+ ad_tracker_->SetScriptAtTopOfStack(String());
EXPECT_FALSE(AnyExecutingScriptsTaggedAsAdResource());
WillExecuteScript(ad_script_url);
EXPECT_TRUE(AnyExecutingScriptsTaggedAsAdResource());
}
+class AdTrackerSimTest : public SimTest {
+ protected:
+ void SetUp() override {
+ SimTest::SetUp();
+ main_resource_ = std::make_unique<SimRequest>(
+ "https://example.com/test.html", "text/html");
+
+ LoadURL("https://example.com/test.html");
+ main_resource_->Start();
+ ad_tracker_ = new TestAdTracker(GetDocument().GetFrame());
+ GetDocument().GetFrame()->SetAdTrackerForTesting(ad_tracker_);
+ }
+
+ void TearDown() override {
+ ad_tracker_->Shutdown();
+ SimTest::TearDown();
+ }
+
+ bool IsKnownAdScript(ExecutionContext* execution_context, const String& url) {
+ return ad_tracker_->IsKnownAdScript(execution_context, url);
+ }
+
+ std::unique_ptr<SimRequest> main_resource_;
+ Persistent<TestAdTracker> ad_tracker_;
+};
+
+// Resources loaded by ad script are tagged as ads.
+TEST_F(AdTrackerSimTest, ResourceLoadedWhileExecutingAdScript) {
+ SimRequest ad_resource("https://example.com/ad_script.js", "text/javascript");
+ SimRequest vanilla_script("https://example.com/vanilla_script.js",
+ "text/javascript");
+
+ ad_tracker_->SetAdSuffix("ad_script.js");
+
+ main_resource_->Complete("<body></body><script src=ad_script.js></script>");
+
+ ad_resource.Complete(R"SCRIPT(
+ script = document.createElement("script");
+ script.src = "vanilla_script.js";
+ document.body.appendChild(script);
+ )SCRIPT");
+ vanilla_script.Complete("");
+
+ EXPECT_TRUE(IsKnownAdScript(&GetDocument(),
+ String("https://example.com/ad_script.js")));
+ EXPECT_TRUE(IsKnownAdScript(&GetDocument(),
+ String("https://example.com/vanilla_script.js")));
+}
+
+// A script tagged as an ad in one frame shouldn't cause it to be considered
+// an ad when executed in another frame.
+TEST_F(AdTrackerSimTest, Contexts) {
+ // Load a page that loads library.js. It also creates an iframe that also
+ // loads library.js (where it gets tagged as an ad). Even though library.js
+ // gets tagged as an ad script in the subframe, that shouldn't cause it to
+ // be treated as an ad in the main frame.
+ SimRequest iframe_resource("https://example.com/iframe.html", "text/html");
+ SimRequest library_resource("https://example.com/library.js",
+ "text/javascript");
+
+ main_resource_->Complete(R"HTML(
+ <script src=library.js></script>
+ <iframe src=iframe.html></iframe>
+ )HTML");
+
+ // Complete the main frame's library.js.
+ library_resource.Complete("");
+
+ // The library script is loaded for a second time, this time in the
+ // subframe. Mark it as an ad.
+ SimRequest library_resource_for_subframe("https://example.com/library.js",
+ "text/javascript");
+ ad_tracker_->SetAdSuffix("library.js");
+
+ iframe_resource.Complete(R"HTML(
+ <script src="library.js"></script>
+ )HTML");
+ library_resource_for_subframe.Complete("");
+
+ // Verify that library.js is an ad script in the subframe's context but not
+ // in the main frame's context.
+ Frame* subframe = GetDocument().GetFrame()->Tree().FirstChild();
+ ASSERT_TRUE(subframe->IsLocalFrame());
+ LocalFrame* local_subframe = ToLocalFrame(subframe);
+ EXPECT_TRUE(IsKnownAdScript(local_subframe->GetDocument(),
+ String("https://example.com/library.js")));
+
+ EXPECT_FALSE(IsKnownAdScript(&GetDocument(),
+ String("https://example.com/library.js")));
+}
+
+TEST_F(AdTrackerSimTest, SameOriginSubframeFromAdScript) {
+ SimRequest ad_resource("https://example.com/ad_script.js", "text/javascript");
+ SimRequest iframe_resource("https://example.com/iframe.html", "text/html");
+ ad_tracker_->SetAdSuffix("ad_script.js");
+
+ main_resource_->Complete(R"HTML(
+ <body></body><script src=ad_script.js></script>
+ )HTML");
+ ad_resource.Complete(R"SCRIPT(
+ var iframe = document.createElement("iframe");
+ iframe.src = "iframe.html";
+ document.body.appendChild(iframe);
+ )SCRIPT");
+
+ iframe_resource.Complete("iframe data");
+
+ Frame* subframe = GetDocument().GetFrame()->Tree().FirstChild();
+ ASSERT_TRUE(subframe->IsLocalFrame());
+ LocalFrame* local_subframe = ToLocalFrame(subframe);
+ EXPECT_TRUE(local_subframe->IsAdSubframe());
+}
+
+TEST_F(AdTrackerSimTest, SameOriginDocWrittenSubframeFromAdScript) {
+ SimRequest ad_resource("https://example.com/ad_script.js", "text/javascript");
+ ad_tracker_->SetAdSuffix("ad_script.js");
+
+ main_resource_->Complete(R"HTML(
+ <body></body><script src=ad_script.js></script>
+ )HTML");
+ ad_resource.Complete(R"SCRIPT(
+ var iframe = document.createElement("iframe");
+ document.body.appendChild(iframe);
+ var iframeDocument = iframe.contentWindow.document;
+ iframeDocument.open();
+ iframeDocument.write("iframe data");
+ iframeDocument.close();
+ )SCRIPT");
+
+ Frame* subframe = GetDocument().GetFrame()->Tree().FirstChild();
+ ASSERT_TRUE(subframe->IsLocalFrame());
+ LocalFrame* local_subframe = ToLocalFrame(subframe);
+ EXPECT_TRUE(local_subframe->IsAdSubframe());
+}
+
+class AdTrackerDisabledSimTest : public SimTest {
+ protected:
+ void SetUp() override {
+ RuntimeEnabledFeatures::SetAdTaggingEnabled(false);
+
+ SimTest::SetUp();
+ main_resource_ = std::make_unique<SimRequest>(
+ "https://example.com/test.html", "text/html");
+
+ LoadURL("https://example.com/test.html");
+ main_resource_->Start();
+ }
+
+ void TearDown() override { SimTest::TearDown(); }
+
+ std::unique_ptr<SimRequest> main_resource_;
+};
+
+TEST_F(AdTrackerDisabledSimTest, ResourceLoadedWhenAdTaggingDisabled) {
+ SimRequest iframe_resource("https://example.com/iframe.html", "text/html");
+
+ main_resource_->Complete(R"HTML(
+ <iframe src=https://example.com/iframe.html></iframe>
+ )HTML");
+
+ iframe_resource.Complete("<body></body>");
+
+ EXPECT_FALSE(GetDocument().GetFrame()->IsAdSubframe());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/browser_controls.cc b/chromium/third_party/blink/renderer/core/frame/browser_controls.cc
index 7128cf5120f..1a780d968ab 100644
--- a/chromium/third_party/blink/renderer/core/frame/browser_controls.cc
+++ b/chromium/third_party/blink/renderer/core/frame/browser_controls.cc
@@ -21,7 +21,7 @@ BrowserControls::BrowserControls(const Page& page)
baseline_content_offset_(0),
accumulated_scroll_delta_(0),
shrink_viewport_(false),
- permitted_state_(kWebBrowserControlsBoth) {}
+ permitted_state_(cc::BrowserControlsState::kBoth) {}
void BrowserControls::Trace(blink::Visitor* visitor) {
visitor->Trace(page_);
@@ -32,9 +32,9 @@ void BrowserControls::ScrollBegin() {
}
FloatSize BrowserControls::ScrollBy(FloatSize pending_delta) {
- if ((permitted_state_ == kWebBrowserControlsShown &&
+ if ((permitted_state_ == cc::BrowserControlsState::kShown &&
pending_delta.Height() > 0) ||
- (permitted_state_ == kWebBrowserControlsHidden &&
+ (permitted_state_ == cc::BrowserControlsState::kHidden &&
pending_delta.Height() < 0))
return pending_delta;
@@ -104,15 +104,15 @@ void BrowserControls::SetShownRatio(float shown_ratio) {
}
void BrowserControls::UpdateConstraintsAndState(
- WebBrowserControlsState constraints,
- WebBrowserControlsState current,
+ cc::BrowserControlsState constraints,
+ cc::BrowserControlsState current,
bool animate) {
permitted_state_ = constraints;
- DCHECK(!(constraints == kWebBrowserControlsShown &&
- current == kWebBrowserControlsHidden));
- DCHECK(!(constraints == kWebBrowserControlsHidden &&
- current == kWebBrowserControlsShown));
+ DCHECK(!(constraints == cc::BrowserControlsState::kShown &&
+ current == cc::BrowserControlsState::kHidden));
+ DCHECK(!(constraints == cc::BrowserControlsState::kHidden &&
+ current == cc::BrowserControlsState::kShown));
// If the change should be animated, let the impl thread drive the change.
// Otherwise, immediately set the shown ratio so we don't have to wait for
@@ -120,12 +120,12 @@ void BrowserControls::UpdateConstraintsAndState(
if (animate)
return;
- if (constraints == kWebBrowserControlsBoth &&
- current == kWebBrowserControlsBoth)
+ if (constraints == cc::BrowserControlsState::kBoth &&
+ current == cc::BrowserControlsState::kBoth)
return;
- if (constraints == kWebBrowserControlsHidden ||
- current == kWebBrowserControlsHidden)
+ if (constraints == cc::BrowserControlsState::kHidden ||
+ current == cc::BrowserControlsState::kHidden)
SetShownRatio(0.f);
else
SetShownRatio(1.f);
diff --git a/chromium/third_party/blink/renderer/core/frame/browser_controls.h b/chromium/third_party/blink/renderer/core/frame/browser_controls.h
index 8e27cd3eaaa..9391a89907d 100644
--- a/chromium/third_party/blink/renderer/core/frame/browser_controls.h
+++ b/chromium/third_party/blink/renderer/core/frame/browser_controls.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_BROWSER_CONTROLS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_BROWSER_CONTROLS_H_
-#include "third_party/blink/public/platform/web_browser_controls_state.h"
+#include "cc/input/browser_controls_state.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -45,8 +45,8 @@ class CORE_EXPORT BrowserControls final
float ShownRatio() const { return shown_ratio_; }
void SetShownRatio(float);
- void UpdateConstraintsAndState(WebBrowserControlsState constraints,
- WebBrowserControlsState current,
+ void UpdateConstraintsAndState(cc::BrowserControlsState constraints,
+ cc::BrowserControlsState current,
bool animate);
void ScrollBegin();
@@ -55,7 +55,7 @@ class CORE_EXPORT BrowserControls final
// scroll amount.
FloatSize ScrollBy(FloatSize scroll_delta);
- WebBrowserControlsState PermittedState() const { return permitted_state_; }
+ cc::BrowserControlsState PermittedState() const { return permitted_state_; }
private:
explicit BrowserControls(const Page&);
@@ -89,7 +89,7 @@ class CORE_EXPORT BrowserControls final
bool shrink_viewport_;
// Constraints on the browser controls state
- WebBrowserControlsState permitted_state_;
+ cc::BrowserControlsState permitted_state_;
};
} // namespace blink
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 ced0bbe0f0e..272f36c8a23 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
@@ -43,7 +43,11 @@
#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_view.h"
#include "third_party/blink/renderer/core/page/page.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"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
@@ -63,6 +67,7 @@ class BrowserControlsTest : public testing::Test {
RegisterMockedHttpURLLoad("percent-height.html");
RegisterMockedHttpURLLoad("vh-height.html");
RegisterMockedHttpURLLoad("vh-height-width-800.html");
+ RegisterMockedHttpURLLoad("95-vh.html");
RegisterMockedHttpURLLoad("vh-height-width-800-extra-wide.html");
}
@@ -163,9 +168,8 @@ TEST_F(BrowserControlsTest, MAYBE(HideOnScrollDown)) {
web_view->HandleInputEvent(
GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -25.f));
EXPECT_FLOAT_EQ(25.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 0),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 0),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Browser controls should consume 25px and become hidden. Excess scroll
// should be
@@ -173,17 +177,15 @@ TEST_F(BrowserControlsTest, MAYBE(HideOnScrollDown)) {
web_view->HandleInputEvent(
GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -40.f));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 15),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 15),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Only page should consume scroll
web_view->HandleInputEvent(
GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -20.f));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 35),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 35),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
}
// Scrolling down should hide bottom browser controls.
@@ -202,9 +204,8 @@ TEST_F(BrowserControlsTest, MAYBE(HideBottomControlsOnScrollDown)) {
GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -25.f));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_FLOAT_EQ(0.5f, web_view->GetBrowserControls().ShownRatio());
- EXPECT_EQ(
- ScrollOffset(0, 25.f),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 25.f),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Browser controls should become completely hidden.
web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollBegin));
@@ -213,9 +214,8 @@ TEST_F(BrowserControlsTest, MAYBE(HideBottomControlsOnScrollDown)) {
web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollEnd));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ShownRatio());
- EXPECT_EQ(
- ScrollOffset(0, 65.f),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 65.f),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
}
// Scrolling up should show browser controls.
@@ -231,16 +231,14 @@ TEST_F(BrowserControlsTest, MAYBE(ShowOnScrollUp)) {
web_view->HandleInputEvent(
GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 10.f));
EXPECT_FLOAT_EQ(10.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 0),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 0),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
web_view->HandleInputEvent(
GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 50.f));
EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 0),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 0),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
}
// Scrolling up should show the bottom browser controls.
@@ -265,9 +263,8 @@ TEST_F(BrowserControlsTest, MAYBE(ShowBottomControlsOnScrollUp)) {
web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollEnd));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_FLOAT_EQ(0.5f, web_view->GetBrowserControls().ShownRatio());
- EXPECT_EQ(
- ScrollOffset(0, 25),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 25),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
}
// Scrolling up after previous scroll downs should cause browser controls to be
@@ -288,42 +285,37 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollDownThenUp)) {
web_view->HandleInputEvent(
GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -150.f));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 200),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 200),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Scroll up and ensure the browser controls does not move until we recover
// 100px previously scrolled.
web_view->HandleInputEvent(
GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 40.f));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 160),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 160),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
web_view->HandleInputEvent(
GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 60.f));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 100),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 100),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Now we have hit the threshold so further scroll up should be consumed by
// browser controls.
web_view->HandleInputEvent(
GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 30.f));
EXPECT_FLOAT_EQ(30.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 100),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 100),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Once top control is fully shown then page should consume any excess scroll.
web_view->HandleInputEvent(
GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 70.f));
EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 50),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 50),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
}
// Scrolling down should always cause visible browser controls to start hiding
@@ -344,24 +336,21 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollUpThenDown)) {
web_view->HandleInputEvent(
GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 100.f));
EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 50),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 50),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Scroll down and ensure only browser controls is scrolled
web_view->HandleInputEvent(
GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -40.f));
EXPECT_FLOAT_EQ(10.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 50),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 50),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
web_view->HandleInputEvent(
GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, -60.f));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 100),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 100),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
}
// Browser controls should not consume horizontal scroll.
@@ -378,16 +367,14 @@ TEST_F(BrowserControlsTest, MAYBE(HorizontalScroll)) {
web_view->HandleInputEvent(
GenerateEvent(WebInputEvent::kGestureScrollUpdate, -110.f, -100.f));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(110, 50),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(110, 50),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
web_view->HandleInputEvent(
GenerateEvent(WebInputEvent::kGestureScrollUpdate, -40.f, 0));
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(150, 50),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(150, 50),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
}
// Page scale should not impact browser controls scrolling
@@ -479,47 +466,41 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollableSubregionScrollFirst)) {
// main frame should not scroll.
VerticalScroll(-800.f);
EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 50),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 50),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Continued scroll down should start hiding browser controls but main frame
// should not scroll.
VerticalScroll(-40.f);
EXPECT_FLOAT_EQ(10.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 50),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 50),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Continued scroll down should scroll down the main frame
VerticalScroll(-40.f);
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 80),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 80),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Test scroll up
// scroll up should scroll overflow div first
VerticalScroll(800.f);
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 80),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 80),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Continued scroll up should start showing browser controls but main frame
// should not scroll.
VerticalScroll(40.f);
EXPECT_FLOAT_EQ(40.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 80),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 80),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Continued scroll down up scroll up the main frame
VerticalScroll(40.f);
EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 50),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 50),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
}
// Scrollable iframes should scroll before browser controls
@@ -535,47 +516,41 @@ TEST_F(BrowserControlsTest, MAYBE(ScrollableIframeScrollFirst)) {
// frame should not scroll.
VerticalScroll(-800.f);
EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 50),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 50),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Continued scroll down should start hiding browser controls but main frame
// should not scroll.
VerticalScroll(-40.f);
EXPECT_FLOAT_EQ(10.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 50),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 50),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Continued scroll down should scroll down the main frame
VerticalScroll(-40.f);
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 80),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 80),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Test scroll up
// scroll up should scroll iframe first
VerticalScroll(800.f);
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 80),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 80),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Continued scroll up should start showing browser controls but main frame
// should not scroll.
VerticalScroll(40.f);
EXPECT_FLOAT_EQ(40.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 80),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 80),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Continued scroll down up scroll up the main frame
VerticalScroll(40.f);
EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 50),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 50),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
}
// Browser controls visibility should remain consistent when height is changed.
@@ -612,15 +587,13 @@ TEST_F(BrowserControlsTest, MAYBE(ZeroHeightMeansNoEffect)) {
VerticalScroll(20.f);
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 80),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 80),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
VerticalScroll(-30.f);
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 110),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 110),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
web_view->GetBrowserControls().SetShownRatio(1);
EXPECT_FLOAT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
@@ -668,72 +641,69 @@ TEST_F(BrowserControlsTest, MAYBE(StateConstraints)) {
// Setting permitted state should change the content offset to match the
// constraint.
- web_view->UpdateBrowserControlsState(kWebBrowserControlsShown,
- kWebBrowserControlsShown, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kShown,
+ cc::BrowserControlsState::kShown, false);
EXPECT_FLOAT_EQ(50.f, web_view->GetBrowserControls().ContentOffset());
// Only shown state is permitted so controls cannot hide
VerticalScroll(-20.f);
EXPECT_FLOAT_EQ(50, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 120),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 120),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Setting permitted state should change content offset to match the
// constraint.
- web_view->UpdateBrowserControlsState(kWebBrowserControlsHidden,
- kWebBrowserControlsHidden, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kHidden,
+ cc::BrowserControlsState::kHidden,
+ false);
EXPECT_FLOAT_EQ(0, web_view->GetBrowserControls().ContentOffset());
// Only hidden state is permitted so controls cannot show
VerticalScroll(30.f);
EXPECT_FLOAT_EQ(0, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 90),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 90),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Setting permitted state to "both" should not change content offset.
- web_view->UpdateBrowserControlsState(kWebBrowserControlsBoth,
- kWebBrowserControlsBoth, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kBoth,
+ cc::BrowserControlsState::kBoth, false);
EXPECT_FLOAT_EQ(0, web_view->GetBrowserControls().ContentOffset());
// Both states are permitted so controls can either show or hide
VerticalScroll(50.f);
EXPECT_FLOAT_EQ(50, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 90),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 90),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
VerticalScroll(-50.f);
EXPECT_FLOAT_EQ(0, web_view->GetBrowserControls().ContentOffset());
- EXPECT_EQ(
- ScrollOffset(0, 90),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 90),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
// Setting permitted state to "both" should not change an in-flight offset.
VerticalScroll(20.f);
EXPECT_FLOAT_EQ(20, web_view->GetBrowserControls().ContentOffset());
- web_view->UpdateBrowserControlsState(kWebBrowserControlsBoth,
- kWebBrowserControlsBoth, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kBoth,
+ cc::BrowserControlsState::kBoth, false);
EXPECT_FLOAT_EQ(20, web_view->GetBrowserControls().ContentOffset());
// An animated state change shouldn't cause a change to the content offset
// since it'll be driven from the compositor.
- web_view->UpdateBrowserControlsState(kWebBrowserControlsHidden,
- kWebBrowserControlsHidden, true);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kHidden,
+ cc::BrowserControlsState::kHidden, true);
EXPECT_FLOAT_EQ(20, web_view->GetBrowserControls().ContentOffset());
- web_view->UpdateBrowserControlsState(kWebBrowserControlsShown,
- kWebBrowserControlsShown, true);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kShown,
+ cc::BrowserControlsState::kShown, true);
EXPECT_FLOAT_EQ(20, web_view->GetBrowserControls().ContentOffset());
// Setting just the constraint should affect the content offset.
- web_view->UpdateBrowserControlsState(kWebBrowserControlsHidden,
- kWebBrowserControlsBoth, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kHidden,
+ cc::BrowserControlsState::kBoth, false);
EXPECT_FLOAT_EQ(0, web_view->GetBrowserControls().ContentOffset());
- web_view->UpdateBrowserControlsState(kWebBrowserControlsShown,
- kWebBrowserControlsBoth, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kShown,
+ cc::BrowserControlsState::kBoth, false);
EXPECT_FLOAT_EQ(50, web_view->GetBrowserControls().ContentOffset());
}
@@ -743,8 +713,8 @@ TEST_F(BrowserControlsTest, MAYBE(DontAffectLayoutHeight)) {
// Initialize with the browser controls showing.
WebViewImpl* web_view = Initialize("percent-height.html");
web_view->ResizeWithBrowserControls(WebSize(400, 300), 100.f, 0, true);
- web_view->UpdateBrowserControlsState(kWebBrowserControlsBoth,
- kWebBrowserControlsShown, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kBoth,
+ cc::BrowserControlsState::kShown, false);
web_view->GetBrowserControls().SetShownRatio(1);
web_view->UpdateAllLifecyclePhases();
@@ -761,8 +731,7 @@ TEST_F(BrowserControlsTest, MAYBE(DontAffectLayoutHeight)) {
// The layout size on the LocalFrameView should not include the browser
// controls.
- EXPECT_EQ(300,
- GetFrame()->View()->GetLayoutSize(kIncludeScrollbars).Height());
+ EXPECT_EQ(300, GetFrame()->View()->GetLayoutSize().Height());
// Hide the browser controls.
VerticalScroll(-100.f);
@@ -778,8 +747,7 @@ TEST_F(BrowserControlsTest, MAYBE(DontAffectLayoutHeight)) {
EXPECT_FLOAT_EQ(200.f, fixed_pos->getBoundingClientRect()->height());
// The layout size should not change as a result of browser controls hiding.
- EXPECT_EQ(300,
- GetFrame()->View()->GetLayoutSize(kIncludeScrollbars).Height());
+ EXPECT_EQ(300, GetFrame()->View()->GetLayoutSize().Height());
}
// Ensure that browser controls do not affect the layout by showing and hiding
@@ -788,8 +756,8 @@ TEST_F(BrowserControlsTest, MAYBE(AffectLayoutHeightWhenConstrained)) {
// Initialize with the browser controls showing.
WebViewImpl* web_view = Initialize("percent-height.html");
web_view->ResizeWithBrowserControls(WebSize(400, 300), 100.f, 0, true);
- web_view->UpdateBrowserControlsState(kWebBrowserControlsBoth,
- kWebBrowserControlsShown, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kBoth,
+ cc::BrowserControlsState::kShown, false);
web_view->GetBrowserControls().SetShownRatio(1);
web_view->UpdateAllLifecyclePhases();
@@ -802,71 +770,65 @@ TEST_F(BrowserControlsTest, MAYBE(AffectLayoutHeightWhenConstrained)) {
VerticalScroll(-100.f);
web_view->ResizeWithBrowserControls(WebSize(400, 400), 100.f, 0, false);
web_view->UpdateAllLifecyclePhases();
- ASSERT_EQ(300,
- GetFrame()->View()->GetLayoutSize(kIncludeScrollbars).Height());
+ ASSERT_EQ(300, GetFrame()->View()->GetLayoutSize().Height());
// Now lock the controls in a hidden state. The layout and elements should
// resize without a WebView::resize.
- web_view->UpdateBrowserControlsState(kWebBrowserControlsHidden,
- kWebBrowserControlsBoth, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kHidden,
+ cc::BrowserControlsState::kBoth, false);
EXPECT_FLOAT_EQ(200.f, abs_pos->getBoundingClientRect()->height());
EXPECT_FLOAT_EQ(200.f, fixed_pos->getBoundingClientRect()->height());
- EXPECT_EQ(400,
- GetFrame()->View()->GetLayoutSize(kIncludeScrollbars).Height());
+ EXPECT_EQ(400, GetFrame()->View()->GetLayoutSize().Height());
// Unlock the controls, the sizes should change even though the controls are
// still hidden.
- web_view->UpdateBrowserControlsState(kWebBrowserControlsBoth,
- kWebBrowserControlsBoth, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kBoth,
+ cc::BrowserControlsState::kBoth, false);
EXPECT_FLOAT_EQ(150.f, abs_pos->getBoundingClientRect()->height());
EXPECT_FLOAT_EQ(200.f, fixed_pos->getBoundingClientRect()->height());
- EXPECT_EQ(300,
- GetFrame()->View()->GetLayoutSize(kIncludeScrollbars).Height());
+ EXPECT_EQ(300, GetFrame()->View()->GetLayoutSize().Height());
// Now lock the controls in a shown state.
- web_view->UpdateBrowserControlsState(kWebBrowserControlsShown,
- kWebBrowserControlsBoth, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kShown,
+ cc::BrowserControlsState::kBoth, false);
web_view->ResizeWithBrowserControls(WebSize(400, 300), 100.f, 0, true);
EXPECT_FLOAT_EQ(150.f, abs_pos->getBoundingClientRect()->height());
EXPECT_FLOAT_EQ(150.f, fixed_pos->getBoundingClientRect()->height());
- EXPECT_EQ(300,
- GetFrame()->View()->GetLayoutSize(kIncludeScrollbars).Height());
+ EXPECT_EQ(300, GetFrame()->View()->GetLayoutSize().Height());
// Shown -> Hidden
web_view->ResizeWithBrowserControls(WebSize(400, 400), 100.f, 0, false);
- web_view->UpdateBrowserControlsState(kWebBrowserControlsHidden,
- kWebBrowserControlsBoth, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kHidden,
+ cc::BrowserControlsState::kBoth, false);
EXPECT_FLOAT_EQ(200.f, abs_pos->getBoundingClientRect()->height());
EXPECT_FLOAT_EQ(200.f, fixed_pos->getBoundingClientRect()->height());
- EXPECT_EQ(400,
- GetFrame()->View()->GetLayoutSize(kIncludeScrollbars).Height());
+ EXPECT_EQ(400, GetFrame()->View()->GetLayoutSize().Height());
// Go from Unlocked and showing, to locked and hidden but issue the resize
// before the constraint update to check for race issues.
- web_view->UpdateBrowserControlsState(kWebBrowserControlsBoth,
- kWebBrowserControlsShown, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kBoth,
+ cc::BrowserControlsState::kShown, false);
web_view->ResizeWithBrowserControls(WebSize(400, 300), 100.f, 0, true);
- ASSERT_EQ(300,
- GetFrame()->View()->GetLayoutSize(kIncludeScrollbars).Height());
+ ASSERT_EQ(300, GetFrame()->View()->GetLayoutSize().Height());
web_view->UpdateAllLifecyclePhases();
web_view->ResizeWithBrowserControls(WebSize(400, 400), 100.f, 0, false);
- web_view->UpdateBrowserControlsState(kWebBrowserControlsHidden,
- kWebBrowserControlsHidden, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kHidden,
+ cc::BrowserControlsState::kHidden,
+ false);
EXPECT_FLOAT_EQ(200.f, abs_pos->getBoundingClientRect()->height());
EXPECT_FLOAT_EQ(200.f, fixed_pos->getBoundingClientRect()->height());
- EXPECT_EQ(400,
- GetFrame()->View()->GetLayoutSize(kIncludeScrollbars).Height());
+ EXPECT_EQ(400, GetFrame()->View()->GetLayoutSize().Height());
}
// Ensure that browser controls do not affect vh units.
@@ -874,8 +836,8 @@ TEST_F(BrowserControlsTest, MAYBE(DontAffectVHUnits)) {
// Initialize with the browser controls showing.
WebViewImpl* web_view = Initialize("vh-height.html");
web_view->ResizeWithBrowserControls(WebSize(400, 300), 100.f, 0, true);
- web_view->UpdateBrowserControlsState(kWebBrowserControlsBoth,
- kWebBrowserControlsShown, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kBoth,
+ cc::BrowserControlsState::kShown, false);
web_view->GetBrowserControls().SetShownRatio(1);
web_view->UpdateAllLifecyclePhases();
@@ -916,8 +878,8 @@ TEST_F(BrowserControlsTest, MAYBE(DontAffectVHUnitsWithScale)) {
// Initialize with the browser controls showing.
WebViewImpl* web_view = Initialize("vh-height-width-800.html");
web_view->ResizeWithBrowserControls(WebSize(400, 300), 100.f, 0, true);
- web_view->UpdateBrowserControlsState(kWebBrowserControlsBoth,
- kWebBrowserControlsShown, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kBoth,
+ cc::BrowserControlsState::kShown, false);
web_view->GetBrowserControls().SetShownRatio(1);
web_view->UpdateAllLifecyclePhases();
@@ -966,8 +928,8 @@ TEST_F(BrowserControlsTest, MAYBE(DontAffectVHUnitsUseLayoutSize)) {
// Initialize with the browser controls showing.
WebViewImpl* web_view = Initialize("vh-height-width-800-extra-wide.html");
web_view->ResizeWithBrowserControls(WebSize(400, 300), 100.f, 0, true);
- web_view->UpdateBrowserControlsState(kWebBrowserControlsBoth,
- kWebBrowserControlsShown, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kBoth,
+ cc::BrowserControlsState::kShown, false);
web_view->GetBrowserControls().SetShownRatio(1);
web_view->UpdateAllLifecyclePhases();
@@ -1002,8 +964,8 @@ TEST_F(BrowserControlsTest,
GetWebView()->SetDefaultPageScaleLimits(min_scale, 5);
web_view->ResizeWithBrowserControls(WebSize(800, layout_viewport_height),
browser_controls_height, 0, true);
- web_view->UpdateBrowserControlsState(kWebBrowserControlsBoth,
- kWebBrowserControlsShown, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kBoth,
+ cc::BrowserControlsState::kShown, false);
web_view->GetBrowserControls().SetShownRatio(1);
web_view->UpdateAllLifecyclePhases();
@@ -1033,7 +995,7 @@ TEST_F(BrowserControlsTest,
EXPECT_EQ(expected_visual_offset,
GetVisualViewport().GetScrollOffset().Height());
EXPECT_EQ(expected_layout_offset,
- view->LayoutViewportScrollableArea()->GetScrollOffset().Height());
+ view->LayoutViewport()->GetScrollOffset().Height());
EXPECT_EQ(expected_root_offset, root_viewport->GetScrollOffset().Height());
web_view->HandleInputEvent(GenerateEvent(WebInputEvent::kGestureScrollEnd));
@@ -1048,7 +1010,7 @@ TEST_F(BrowserControlsTest,
ASSERT_EQ(expected_visual_offset,
GetVisualViewport().GetScrollOffset().Height());
ASSERT_EQ(expected_layout_offset,
- view->LayoutViewportScrollableArea()->GetScrollOffset().Height());
+ view->LayoutViewport()->GetScrollOffset().Height());
ASSERT_EQ(expected_root_offset, root_viewport->GetScrollOffset().Height());
// Now scroll back up just enough to show the browser controls. The browser
@@ -1064,7 +1026,8 @@ TEST_F(BrowserControlsTest,
GenerateEvent(WebInputEvent::kGestureScrollUpdate, 0, 80));
GetVisualViewport().ClampToBoundaries();
- view->SetScrollOffset(view->GetScrollOffset(), kProgrammaticScroll);
+ view->LayoutViewport()->SetScrollOffset(
+ view->LayoutViewport()->GetScrollOffset(), kProgrammaticScroll);
ASSERT_EQ(80.f, web_view->GetBrowserControls().ContentOffset());
EXPECT_EQ(expected_root_offset, root_viewport->GetScrollOffset().Height());
@@ -1083,8 +1046,8 @@ TEST_F(BrowserControlsTest, MAYBE(ViewportUnitsWhenControlsLocked)) {
// Initialize with the browser controls showing.
WebViewImpl* web_view = Initialize("vh-height.html");
web_view->ResizeWithBrowserControls(WebSize(400, 300), 100.f, 0, true);
- web_view->UpdateBrowserControlsState(kWebBrowserControlsBoth,
- kWebBrowserControlsShown, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kBoth,
+ cc::BrowserControlsState::kShown, false);
web_view->GetBrowserControls().SetShownRatio(1);
web_view->UpdateAllLifecyclePhases();
@@ -1096,8 +1059,9 @@ TEST_F(BrowserControlsTest, MAYBE(ViewportUnitsWhenControlsLocked)) {
// Lock the browser controls to hidden.
{
- web_view->UpdateBrowserControlsState(kWebBrowserControlsHidden,
- kWebBrowserControlsHidden, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kHidden,
+ cc::BrowserControlsState::kHidden,
+ false);
web_view->ResizeWithBrowserControls(WebSize(400, 400), 100.f, 0, false);
web_view->UpdateAllLifecyclePhases();
@@ -1115,8 +1079,9 @@ TEST_F(BrowserControlsTest, MAYBE(ViewportUnitsWhenControlsLocked)) {
// Lock the browser controls to shown. This should cause the vh units to
// behave as usual by including the browser controls region in 100vh.
{
- web_view->UpdateBrowserControlsState(kWebBrowserControlsShown,
- kWebBrowserControlsShown, false);
+ web_view->UpdateBrowserControlsState(cc::BrowserControlsState::kShown,
+ cc::BrowserControlsState::kShown,
+ false);
web_view->ResizeWithBrowserControls(WebSize(400, 300), 100.f, 0, true);
web_view->UpdateAllLifecyclePhases();
@@ -1174,7 +1139,8 @@ TEST_F(BrowserControlsTest, MAYBE(GrowingHeightKeepsTopControlsHidden)) {
false);
web_view->GetBrowserControls().UpdateConstraintsAndState(
- kWebBrowserControlsHidden, kWebBrowserControlsHidden, false);
+ cc::BrowserControlsState::kHidden, cc::BrowserControlsState::kHidden,
+ false);
// As we expand the top controls height while hidden, the content offset
// shouln't change.
@@ -1189,5 +1155,37 @@ TEST_F(BrowserControlsTest, MAYBE(GrowingHeightKeepsTopControlsHidden)) {
EXPECT_EQ(0.f, web_view->GetBrowserControls().ContentOffset());
}
+TEST_F(BrowserControlsTest,
+ MAYBE(HidingBrowserControlsInvalidatesGraphicsLayer)) {
+ // Initialize with the browser controls showing.
+ WebViewImpl* web_view = Initialize("95-vh.html");
+ web_view->ResizeWithBrowserControls(WebSize(412, 604), 56.f, 0, true);
+ web_view->GetBrowserControls().SetShownRatio(1);
+ web_view->UpdateAllLifecyclePhases();
+
+ GetFrame()->GetDocument()->View()->SetTracksPaintInvalidations(true);
+
+ // Hide the browser controls.
+ VerticalScroll(-100.f);
+ web_view->ResizeWithBrowserControls(WebSize(412, 660), 56.f, 0, false);
+ web_view->UpdateAllLifecyclePhases();
+
+ // Ensure there is a raster invalidation of the bottom of the layer.
+ const auto& raster_invalidations = GetFrame()
+ ->ContentLayoutObject()
+ ->Layer()
+ ->GetCompositedLayerMapping()
+ ->ScrollingContentsLayer()
+ ->GetRasterInvalidationTracking()
+ ->Invalidations();
+ EXPECT_EQ(1u, raster_invalidations.size());
+ EXPECT_EQ(IntRect(0, 643, 412, 17), raster_invalidations[0].rect);
+ EXPECT_EQ(PaintInvalidationReason::kIncremental,
+ raster_invalidations[0].reason);
+
+ GetFrame()->GetDocument()->View()->SetTracksPaintInvalidations(false);
+}
+
#undef MAYBE
+
} // namespace blink
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 8f9382c7f67..2401b6f7711 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
@@ -422,13 +422,12 @@ void ContentSecurityPolicy::SetOverrideURLForSelf(const KURL& url) {
String(), CSPSource::kNoWildcard, CSPSource::kNoWildcard);
}
-std::unique_ptr<Vector<CSPHeaderAndType>> ContentSecurityPolicy::Headers()
- const {
- std::unique_ptr<Vector<CSPHeaderAndType>> headers =
- std::make_unique<Vector<CSPHeaderAndType>>();
+Vector<CSPHeaderAndType> ContentSecurityPolicy::Headers() const {
+ Vector<CSPHeaderAndType> headers;
+ headers.ReserveInitialCapacity(policies_.size());
for (const auto& policy : policies_) {
- CSPHeaderAndType header_and_type(policy->Header(), policy->HeaderType());
- headers->push_back(header_and_type);
+ headers.UncheckedAppend(
+ CSPHeaderAndType(policy->Header(), policy->HeaderType()));
}
return headers;
}
@@ -502,9 +501,17 @@ bool ContentSecurityPolicy::AllowJavaScriptURLs(
const String& context_url,
const WTF::OrdinalNumber& context_line,
SecurityViolationReportingPolicy reporting_policy) const {
+ // Javascript URLs may be whitelisted by hash, if
+ // 'unsafe-hashes' is present in a policy. Check against the digest
+ // of the |source| and also check whether inline script is allowed.
+ Vector<CSPHashValue> csp_hash_values;
+ FillInCSPHashValues(source, script_hash_algorithms_used_, csp_hash_values);
+
bool is_allowed = true;
for (const auto& policy : policies_) {
- is_allowed &= policy->AllowJavaScriptURLs(element, source, context_url,
+ is_allowed &= CheckScriptHashAgainstPolicy(csp_hash_values, policy,
+ InlineType::kAttribute) ||
+ policy->AllowJavaScriptURLs(element, source, context_url,
context_line, reporting_policy);
}
return is_allowed;
@@ -517,7 +524,7 @@ bool ContentSecurityPolicy::AllowInlineEventHandler(
const WTF::OrdinalNumber& context_line,
SecurityViolationReportingPolicy reporting_policy) const {
// Inline event handlers may be whitelisted by hash, if
- // 'unsafe-hash-attributes' is present in a policy. Check against the digest
+ // 'unsafe-hashes' is present in a policy. Check against the digest
// of the |source| and also check whether inline script is allowed.
Vector<CSPHashValue> csp_hash_values;
FillInCSPHashValues(source, script_hash_algorithms_used_, csp_hash_values);
@@ -1409,12 +1416,6 @@ void ContentSecurityPolicy::PostViolationReport(
void ContentSecurityPolicy::DispatchViolationEvents(
const SecurityPolicyViolationEventInit& violation_data,
Element* element) {
- // If the context is detached or closed (thus clearing its event queue)
- // between the violation occuring and this event dispatch, exit early.
- EventQueue* queue = execution_context_->GetEventQueue();
- if (!queue)
- return;
-
// Worklets don't support Events in general.
if (execution_context_->IsWorkletGlobalScope())
return;
@@ -1426,17 +1427,18 @@ void ContentSecurityPolicy::DispatchViolationEvents(
if (execution_context_->IsDocument()) {
Document* document = ToDocument(execution_context_);
if (element && element->isConnected() && element->GetDocument() == document)
- event->SetTarget(element);
+ element->EnqueueEvent(event, TaskType::kInternalDefault);
else
- event->SetTarget(document);
+ document->EnqueueEvent(event, TaskType::kInternalDefault);
} else if (execution_context_->IsWorkerGlobalScope()) {
- event->SetTarget(ToWorkerGlobalScope(execution_context_));
+ ToWorkerGlobalScope(execution_context_)
+ ->EnqueueEvent(event, TaskType::kInternalDefault);
}
- queue->EnqueueEvent(FROM_HERE, event);
}
-void ContentSecurityPolicy::ReportMixedContent(const KURL& mixed_url,
- RedirectStatus redirect_status) {
+void ContentSecurityPolicy::ReportMixedContent(
+ const KURL& mixed_url,
+ RedirectStatus redirect_status) const {
for (const auto& policy : policies_)
policy->ReportMixedContent(mixed_url, redirect_status);
}
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 3fe223e7d8b..d97eb519aab 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
@@ -151,7 +151,7 @@ class CORE_EXPORT ContentSecurityPolicy
ContentSecurityPolicyHeaderSource);
void ReportAccumulatedHeaders(LocalFrameClient*) const;
- std::unique_ptr<Vector<CSPHeaderAndType>> Headers() const;
+ Vector<CSPHeaderAndType> Headers() const;
// |element| will not be present for navigations to javascript URLs,
// as those checks happen in the middle of the navigation algorithm,
@@ -387,7 +387,7 @@ class CORE_EXPORT ContentSecurityPolicy
// Called when mixed content is detected on a page; will trigger a violation
// report if the 'block-all-mixed-content' directive is specified for a
// policy.
- void ReportMixedContent(const KURL& mixed_url, RedirectStatus);
+ void ReportMixedContent(const KURL& mixed_url, RedirectStatus) const;
void ReportBlockedScriptExecutionToInspector(
const String& directive_text) const;
@@ -455,6 +455,12 @@ class CORE_EXPORT ContentSecurityPolicy
// perform these checks in NavigationRequest::CheckContentSecurityPolicy.
WebContentSecurityPolicyList ExposeForNavigationalChecks() const;
+ // Retrieves the parsed sandbox flags. A lot of the time the execution
+ // 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_; }
+
private:
FRIEND_TEST_ALL_PREFIXES(ContentSecurityPolicyTest, NonceInline);
FRIEND_TEST_ALL_PREFIXES(ContentSecurityPolicyTest, NonceSinglePolicy);
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 d94778fc1e3..ad5c35ac936 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
@@ -43,7 +43,7 @@ int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
// CoreServices.framework/Frameworks/CarbonCore.framework/Headers/Threads.h.
blink::ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
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 495b4e4ad50..5643996494d 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
@@ -239,10 +239,10 @@ TEST_F(ContentSecurityPolicyTest, SandboxInMeta) {
csp->BindToExecutionContext(execution_context.Get());
csp->DidReceiveHeader("sandbox;", kContentSecurityPolicyHeaderTypeEnforce,
kContentSecurityPolicyHeaderSourceMeta);
- EXPECT_FALSE(execution_context->GetSecurityOrigin()->IsUnique());
+ EXPECT_FALSE(execution_context->GetSecurityOrigin()->IsOpaque());
csp->DidReceiveHeader("sandbox;", kContentSecurityPolicyHeaderTypeEnforce,
kContentSecurityPolicyHeaderSourceHTTP);
- EXPECT_TRUE(execution_context->GetSecurityOrigin()->IsUnique());
+ EXPECT_TRUE(execution_context->GetSecurityOrigin()->IsOpaque());
}
// Tests that report-uri directives are discarded from policies
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 9a748e3e923..7ee2f0ba3a7 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
@@ -95,13 +95,15 @@ CSPDirectiveList* CSPDirectiveList::Create(
CSPDirectiveList* directives = new CSPDirectiveList(policy, type, source);
directives->Parse(begin, end, should_parse_wasm_eval);
- if (!directives->CheckEval(
- directives->OperativeDirective(directives->script_src_.Get()))) {
+ if (!directives->CheckEval(directives->OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kScriptSrc))) {
String message =
"Refused to evaluate a string as JavaScript because 'unsafe-eval' is "
"not an allowed source of script in the following Content Security "
"Policy directive: \"" +
- directives->OperativeDirective(directives->script_src_.Get())
+ directives
+ ->OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kScriptSrc)
->GetText() +
"\".\n";
directives->SetEvalDisabledErrorMessage(message);
@@ -117,7 +119,7 @@ CSPDirectiveList* CSPDirectiveList::Create(
void CSPDirectiveList::ReportViolation(
const String& directive_text,
- const ContentSecurityPolicy::DirectiveType& effective_type,
+ const ContentSecurityPolicy::DirectiveType effective_type,
const String& console_message,
const KURL& blocked_url,
ResourceRequest::RedirectStatus redirect_status) const {
@@ -135,7 +137,7 @@ void CSPDirectiveList::ReportViolation(
void CSPDirectiveList::ReportViolationWithFrame(
const String& directive_text,
- const ContentSecurityPolicy::DirectiveType& effective_type,
+ const ContentSecurityPolicy::DirectiveType effective_type,
const String& console_message,
const KURL& blocked_url,
LocalFrame* frame) const {
@@ -152,7 +154,7 @@ void CSPDirectiveList::ReportViolationWithFrame(
void CSPDirectiveList::ReportViolationWithLocation(
const String& directive_text,
- const ContentSecurityPolicy::DirectiveType& effective_type,
+ const ContentSecurityPolicy::DirectiveType effective_type,
const String& console_message,
const KURL& blocked_url,
const String& context_url,
@@ -176,7 +178,7 @@ void CSPDirectiveList::ReportViolationWithLocation(
void CSPDirectiveList::ReportEvalViolation(
const String& directive_text,
- const ContentSecurityPolicy::DirectiveType& effective_type,
+ const ContentSecurityPolicy::DirectiveType effective_type,
const String& message,
const KURL& blocked_url,
ScriptState* script_state,
@@ -236,9 +238,9 @@ bool CSPDirectiveList::CheckHash(SourceListDirective* directive,
return !directive || directive->AllowHash(hash_value);
}
-bool CSPDirectiveList::CheckHashedAttributes(
+bool CSPDirectiveList::CheckUnsafeHashesAllowed(
SourceListDirective* directive) const {
- return !directive || directive->AllowHashedAttributes();
+ return !directive || directive->AllowUnsafeHashes();
}
bool CSPDirectiveList::CheckDynamic(SourceListDirective* directive) const {
@@ -375,17 +377,6 @@ bool CSPDirectiveList::CheckMediaType(MediaListDirective* directive,
return directive->Allows(type);
}
-SourceListDirective* CSPDirectiveList::OperativeDirective(
- SourceListDirective* directive) const {
- return directive ? directive : default_src_.Get();
-}
-
-SourceListDirective* CSPDirectiveList::OperativeDirective(
- SourceListDirective* directive,
- SourceListDirective* override) const {
- return directive ? directive : override;
-}
-
bool CSPDirectiveList::CheckEvalAndReportViolation(
SourceListDirective* directive,
const String& console_message,
@@ -515,7 +506,7 @@ bool CSPDirectiveList::CheckInlineAndReportViolation(
bool CSPDirectiveList::CheckSourceAndReportViolation(
SourceListDirective* directive,
const KURL& url,
- const ContentSecurityPolicy::DirectiveType& effective_type,
+ const ContentSecurityPolicy::DirectiveType effective_type,
ResourceRequest::RedirectStatus redirect_status) const {
if (!directive)
return true;
@@ -608,11 +599,12 @@ bool CSPDirectiveList::AllowJavaScriptURLs(
const String& context_url,
const WTF::OrdinalNumber& context_line,
SecurityViolationReportingPolicy reporting_policy) const {
- SourceListDirective* directive = OperativeDirective(script_src_.Get());
+ SourceListDirective* directive =
+ OperativeDirective(ContentSecurityPolicy::DirectiveType::kScriptSrc);
if (reporting_policy == SecurityViolationReportingPolicy::kReport) {
return CheckInlineAndReportViolation(
directive,
- "Refused to execute JavaScript URL because it violates the following "
+ "Refused to run the JavaScript URL because it violates the following "
"Content Security Policy directive: ",
element, source, context_url, context_line, true, "sha256-...");
}
@@ -626,10 +618,11 @@ bool CSPDirectiveList::AllowInlineEventHandlers(
const String& context_url,
const WTF::OrdinalNumber& context_line,
SecurityViolationReportingPolicy reporting_policy) const {
- SourceListDirective* directive = OperativeDirective(script_src_.Get());
+ SourceListDirective* directive =
+ OperativeDirective(ContentSecurityPolicy::DirectiveType::kScriptSrc);
if (reporting_policy == SecurityViolationReportingPolicy::kReport) {
return CheckInlineAndReportViolation(
- OperativeDirective(script_src_.Get()),
+ OperativeDirective(ContentSecurityPolicy::DirectiveType::kScriptSrc),
"Refused to execute inline event handler because it violates the "
"following Content Security Policy directive: ",
element, source, context_url, context_line, true, "sha256-...");
@@ -645,7 +638,8 @@ bool CSPDirectiveList::AllowInlineScript(
const WTF::OrdinalNumber& context_line,
SecurityViolationReportingPolicy reporting_policy,
const String& content) const {
- SourceListDirective* directive = OperativeDirective(script_src_.Get());
+ SourceListDirective* directive =
+ OperativeDirective(ContentSecurityPolicy::DirectiveType::kScriptSrc);
if (IsMatchingNoncePresent(directive, nonce))
return true;
if (element && IsHTMLScriptElement(element) &&
@@ -672,7 +666,8 @@ bool CSPDirectiveList::AllowInlineStyle(
const WTF::OrdinalNumber& context_line,
SecurityViolationReportingPolicy reporting_policy,
const String& content) const {
- SourceListDirective* directive = OperativeDirective(style_src_.Get());
+ SourceListDirective* directive =
+ OperativeDirective(ContentSecurityPolicy::DirectiveType::kStyleSrc);
if (IsMatchingNoncePresent(directive, nonce))
return true;
if (reporting_policy == SecurityViolationReportingPolicy::kReport) {
@@ -694,13 +689,14 @@ bool CSPDirectiveList::AllowEval(
const String& content) const {
if (reporting_policy == SecurityViolationReportingPolicy::kReport) {
return CheckEvalAndReportViolation(
- OperativeDirective(script_src_.Get()),
+ OperativeDirective(ContentSecurityPolicy::DirectiveType::kScriptSrc),
"Refused to evaluate a string as JavaScript because 'unsafe-eval' is "
"not an allowed source of script in the following Content Security "
"Policy directive: ",
script_state, exception_status, content);
}
- return CheckEval(OperativeDirective(script_src_.Get()));
+ return CheckEval(
+ OperativeDirective(ContentSecurityPolicy::DirectiveType::kScriptSrc));
}
bool CSPDirectiveList::AllowWasmEval(
@@ -710,13 +706,14 @@ bool CSPDirectiveList::AllowWasmEval(
const String& content) const {
if (reporting_policy == SecurityViolationReportingPolicy::kReport) {
return CheckWasmEvalAndReportViolation(
- OperativeDirective(script_src_.Get()),
+ OperativeDirective(ContentSecurityPolicy::DirectiveType::kScriptSrc),
"Refused to compile or instantiate WebAssembly module because "
"'wasm-eval' is not an allowed source of script in the following "
"Content Security Policy directive: ",
script_state, exception_status, content);
}
- return CheckWasmEval(OperativeDirective(script_src_.Get()));
+ return CheckWasmEval(
+ OperativeDirective(ContentSecurityPolicy::DirectiveType::kScriptSrc));
}
bool CSPDirectiveList::AllowPluginType(
@@ -741,7 +738,8 @@ bool CSPDirectiveList::AllowScriptFromSource(
ParserDisposition parser_disposition,
ResourceRequest::RedirectStatus redirect_status,
SecurityViolationReportingPolicy reporting_policy) const {
- SourceListDirective* directive = OperativeDirective(script_src_.Get());
+ SourceListDirective* directive =
+ OperativeDirective(ContentSecurityPolicy::DirectiveType::kScriptSrc);
if (IsMatchingNoncePresent(directive, nonce))
return true;
if (parser_disposition == kNotParserInserted && AllowDynamic())
@@ -764,11 +762,14 @@ bool CSPDirectiveList::AllowObjectFromSource(
return true;
return reporting_policy == SecurityViolationReportingPolicy::kReport
? CheckSourceAndReportViolation(
- OperativeDirective(object_src_.Get()), url,
- ContentSecurityPolicy::DirectiveType::kObjectSrc,
+ OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kObjectSrc),
+ url, ContentSecurityPolicy::DirectiveType::kObjectSrc,
redirect_status)
- : CheckSource(OperativeDirective(object_src_.Get()), url,
- redirect_status);
+ : CheckSource(
+ OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kObjectSrc),
+ url, redirect_status);
}
bool CSPDirectiveList::AllowPrefetchFromSource(
@@ -777,11 +778,14 @@ bool CSPDirectiveList::AllowPrefetchFromSource(
SecurityViolationReportingPolicy reporting_policy) const {
return reporting_policy == SecurityViolationReportingPolicy::kReport
? CheckSourceAndReportViolation(
- OperativeDirective(prefetch_src_.Get()), url,
- ContentSecurityPolicy::DirectiveType::kPrefetchSrc,
+ OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kPrefetchSrc),
+ url, ContentSecurityPolicy::DirectiveType::kPrefetchSrc,
redirect_status)
- : CheckSource(OperativeDirective(prefetch_src_.Get()), url,
- redirect_status);
+ : CheckSource(
+ OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kPrefetchSrc),
+ url, redirect_status);
}
bool CSPDirectiveList::AllowFrameFromSource(
@@ -795,8 +799,8 @@ bool CSPDirectiveList::AllowFrameFromSource(
// sources. So, we do this nested set of calls to 'operativeDirective()' to
// grab 'frame-src' if it exists, 'child-src' if it doesn't, and 'defaut-src'
// if neither are available.
- SourceListDirective* which_directive = OperativeDirective(
- frame_src_.Get(), OperativeDirective(child_src_.Get()));
+ SourceListDirective* which_directive =
+ OperativeDirective(ContentSecurityPolicy::DirectiveType::kFrameSrc);
return reporting_policy == SecurityViolationReportingPolicy::kReport
? CheckSourceAndReportViolation(
@@ -812,11 +816,13 @@ bool CSPDirectiveList::AllowImageFromSource(
SecurityViolationReportingPolicy reporting_policy) const {
return reporting_policy == SecurityViolationReportingPolicy::kReport
? CheckSourceAndReportViolation(
- OperativeDirective(img_src_.Get()), url,
- ContentSecurityPolicy::DirectiveType::kImgSrc,
+ OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kImgSrc),
+ url, ContentSecurityPolicy::DirectiveType::kImgSrc,
redirect_status)
- : CheckSource(OperativeDirective(img_src_.Get()), url,
- redirect_status);
+ : CheckSource(OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kImgSrc),
+ url, redirect_status);
}
bool CSPDirectiveList::AllowStyleFromSource(
@@ -824,15 +830,19 @@ bool CSPDirectiveList::AllowStyleFromSource(
const String& nonce,
ResourceRequest::RedirectStatus redirect_status,
SecurityViolationReportingPolicy reporting_policy) const {
- if (IsMatchingNoncePresent(OperativeDirective(style_src_.Get()), nonce))
+ if (IsMatchingNoncePresent(
+ OperativeDirective(ContentSecurityPolicy::DirectiveType::kStyleSrc),
+ nonce))
return true;
return reporting_policy == SecurityViolationReportingPolicy::kReport
? CheckSourceAndReportViolation(
- OperativeDirective(style_src_.Get()), url,
- ContentSecurityPolicy::DirectiveType::kStyleSrc,
+ OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kStyleSrc),
+ url, ContentSecurityPolicy::DirectiveType::kStyleSrc,
redirect_status)
- : CheckSource(OperativeDirective(style_src_.Get()), url,
- redirect_status);
+ : CheckSource(OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kStyleSrc),
+ url, redirect_status);
}
bool CSPDirectiveList::AllowFontFromSource(
@@ -841,11 +851,13 @@ bool CSPDirectiveList::AllowFontFromSource(
SecurityViolationReportingPolicy reporting_policy) const {
return reporting_policy == SecurityViolationReportingPolicy::kReport
? CheckSourceAndReportViolation(
- OperativeDirective(font_src_.Get()), url,
- ContentSecurityPolicy::DirectiveType::kFontSrc,
+ OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kFontSrc),
+ url, ContentSecurityPolicy::DirectiveType::kFontSrc,
redirect_status)
- : CheckSource(OperativeDirective(font_src_.Get()), url,
- redirect_status);
+ : CheckSource(OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kFontSrc),
+ url, redirect_status);
}
bool CSPDirectiveList::AllowMediaFromSource(
@@ -854,11 +866,13 @@ bool CSPDirectiveList::AllowMediaFromSource(
SecurityViolationReportingPolicy reporting_policy) const {
return reporting_policy == SecurityViolationReportingPolicy::kReport
? CheckSourceAndReportViolation(
- OperativeDirective(media_src_.Get()), url,
- ContentSecurityPolicy::DirectiveType::kMediaSrc,
+ OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kMediaSrc),
+ url, ContentSecurityPolicy::DirectiveType::kMediaSrc,
redirect_status)
- : CheckSource(OperativeDirective(media_src_.Get()), url,
- redirect_status);
+ : CheckSource(OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kMediaSrc),
+ url, redirect_status);
}
bool CSPDirectiveList::AllowManifestFromSource(
@@ -867,11 +881,14 @@ bool CSPDirectiveList::AllowManifestFromSource(
SecurityViolationReportingPolicy reporting_policy) const {
return reporting_policy == SecurityViolationReportingPolicy::kReport
? CheckSourceAndReportViolation(
- OperativeDirective(manifest_src_.Get()), url,
- ContentSecurityPolicy::DirectiveType::kManifestSrc,
+ OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kManifestSrc),
+ url, ContentSecurityPolicy::DirectiveType::kManifestSrc,
redirect_status)
- : CheckSource(OperativeDirective(manifest_src_.Get()), url,
- redirect_status);
+ : CheckSource(
+ OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kManifestSrc),
+ url, redirect_status);
}
bool CSPDirectiveList::AllowConnectToSource(
@@ -880,11 +897,14 @@ bool CSPDirectiveList::AllowConnectToSource(
SecurityViolationReportingPolicy reporting_policy) const {
return reporting_policy == SecurityViolationReportingPolicy::kReport
? CheckSourceAndReportViolation(
- OperativeDirective(connect_src_.Get()), url,
- ContentSecurityPolicy::DirectiveType::kConnectSrc,
+ OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kConnectSrc),
+ url, ContentSecurityPolicy::DirectiveType::kConnectSrc,
redirect_status)
- : CheckSource(OperativeDirective(connect_src_.Get()), url,
- redirect_status);
+ : CheckSource(
+ OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kConnectSrc),
+ url, redirect_status);
}
bool CSPDirectiveList::AllowFormAction(
@@ -893,10 +913,14 @@ bool CSPDirectiveList::AllowFormAction(
SecurityViolationReportingPolicy reporting_policy) const {
return reporting_policy == SecurityViolationReportingPolicy::kReport
? CheckSourceAndReportViolation(
- form_action_.Get(), url,
- ContentSecurityPolicy::DirectiveType::kFormAction,
+ OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kFormAction),
+ url, ContentSecurityPolicy::DirectiveType::kFormAction,
redirect_status)
- : CheckSource(form_action_.Get(), url, redirect_status);
+ : CheckSource(
+ OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kFormAction),
+ url, redirect_status);
}
bool CSPDirectiveList::AllowBaseURI(
@@ -906,12 +930,18 @@ bool CSPDirectiveList::AllowBaseURI(
bool result =
reporting_policy == SecurityViolationReportingPolicy::kReport
? CheckSourceAndReportViolation(
- base_uri_.Get(), url,
- ContentSecurityPolicy::DirectiveType::kBaseURI, redirect_status)
- : CheckSource(base_uri_.Get(), url, redirect_status);
+ OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kBaseURI),
+ url, ContentSecurityPolicy::DirectiveType::kBaseURI,
+ redirect_status)
+ : CheckSource(OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kBaseURI),
+ url, redirect_status);
if (result &&
- !CheckSource(OperativeDirective(base_uri_.Get()), url, redirect_status)) {
+ !CheckSource(
+ OperativeDirective(ContentSecurityPolicy::DirectiveType::kBaseURI),
+ url, redirect_status)) {
UseCounter::Count(policy_->GetDocument(),
WebFeature::kBaseWouldBeBlockedByDefaultSrc);
}
@@ -923,43 +953,19 @@ bool CSPDirectiveList::AllowWorkerFromSource(
const KURL& url,
ResourceRequest::RedirectStatus redirect_status,
SecurityViolationReportingPolicy reporting_policy) const {
- SourceListDirective* worker_src = OperativeDirective(
- worker_src_.Get(), OperativeDirective(script_src_.Get()));
-
if (AllowDynamicWorker())
return true;
- // In CSP2, workers are controlled via 'child-src'. CSP3 moves them to
- // 'script-src'. In order to avoid breaking sites that allowed workers via
- // 'child-src' that would have been blocked via 'script-src', we'll
- // temporarily check whether a worker blocked via 'script-src' would have been
- // allowed under 'child-src'. If the new 'worker-src' directive is present,
- // however, we'll assume that the developer knows what they're asking for, and
- // skip the extra fallback.
- //
- // That is, we'll block 'https://example.com/worker' given the policy
- // "worker-src 'none'", "worker-src 'none'; child-src https://example.com",
- // but we'll allow it given the policy
- // "script-src https://not-example.com; child-src https://example.com"
- // (because 'child-src' allows it) or "child-src https://not-example.com"
- // (because the absent 'script-src' allows it).
- //
- // TODO(mkwst): Remove this once other vendors follow suit.
- // https://crbug.com/662930
- if (!CheckSource(worker_src, url, redirect_status) && !worker_src_ &&
- child_src_ && CheckSource(child_src_, url, redirect_status)) {
- Deprecation::CountDeprecation(
- policy_->GetDocument(),
- WebFeature::kChildSrcAllowedWorkerThatScriptSrcBlocked);
- return true;
- }
-
return reporting_policy == SecurityViolationReportingPolicy::kReport
? CheckSourceAndReportViolation(
- worker_src, url,
- ContentSecurityPolicy::DirectiveType::kWorkerSrc,
+ OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kWorkerSrc),
+ url, ContentSecurityPolicy::DirectiveType::kWorkerSrc,
redirect_status)
- : CheckSource(worker_src, url, redirect_status);
+ : CheckSource(
+ OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kWorkerSrc),
+ url, redirect_status);
}
bool CSPDirectiveList::AllowAncestors(
@@ -967,38 +973,51 @@ bool CSPDirectiveList::AllowAncestors(
const KURL& url,
SecurityViolationReportingPolicy reporting_policy) const {
return reporting_policy == SecurityViolationReportingPolicy::kReport
- ? CheckAncestorsAndReportViolation(frame_ancestors_.Get(), frame,
- url)
- : CheckAncestors(frame_ancestors_.Get(), frame);
+ ? CheckAncestorsAndReportViolation(
+ OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kFrameAncestors),
+ frame, url)
+ : CheckAncestors(
+ OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kFrameAncestors),
+ frame);
}
-bool CSPDirectiveList::AllowScriptHash(
+bool CSPDirectiveList::AllowHash(
const CSPHashValue& hash_value,
- ContentSecurityPolicy::InlineType type) const {
+ const ContentSecurityPolicy::InlineType type,
+ const ContentSecurityPolicy::DirectiveType directive_type) const {
if (type == ContentSecurityPolicy::InlineType::kAttribute) {
if (!policy_->ExperimentalFeaturesEnabled())
return false;
- if (!CheckHashedAttributes(OperativeDirective(script_src_.Get())))
+ if (!CheckUnsafeHashesAllowed(OperativeDirective(directive_type)))
return false;
}
- return CheckHash(OperativeDirective(script_src_.Get()), hash_value);
+ return CheckHash(OperativeDirective(directive_type), hash_value);
+}
+
+bool CSPDirectiveList::AllowScriptHash(
+ const CSPHashValue& hash_value,
+ ContentSecurityPolicy::InlineType type) const {
+ return AllowHash(hash_value, type,
+ ContentSecurityPolicy::DirectiveType::kScriptSrc);
}
bool CSPDirectiveList::AllowStyleHash(
const CSPHashValue& hash_value,
ContentSecurityPolicy::InlineType type) const {
- if (type != ContentSecurityPolicy::InlineType::kBlock)
- return false;
- return CheckHash(OperativeDirective(style_src_.Get()), hash_value);
+ return AllowHash(hash_value, type,
+ ContentSecurityPolicy::DirectiveType::kStyleSrc);
}
bool CSPDirectiveList::AllowDynamic() const {
- return CheckDynamic(OperativeDirective(script_src_.Get()));
+ return CheckDynamic(
+ OperativeDirective(ContentSecurityPolicy::DirectiveType::kScriptSrc));
}
bool CSPDirectiveList::AllowDynamicWorker() const {
- SourceListDirective* worker_src = OperativeDirective(
- worker_src_.Get(), OperativeDirective(script_src_.Get()));
+ SourceListDirective* worker_src =
+ OperativeDirective(ContentSecurityPolicy::DirectiveType::kWorkerSrc);
return CheckDynamic(worker_src);
}
@@ -1407,54 +1426,125 @@ void CSPDirectiveList::AddDirective(const String& name, const String& value) {
}
}
+ContentSecurityPolicy::DirectiveType CSPDirectiveList::FallbackDirective(
+ const ContentSecurityPolicy::DirectiveType current_directive,
+ const ContentSecurityPolicy::DirectiveType original_directive) const {
+ switch (current_directive) {
+ case ContentSecurityPolicy::DirectiveType::kConnectSrc:
+ case ContentSecurityPolicy::DirectiveType::kFontSrc:
+ case ContentSecurityPolicy::DirectiveType::kImgSrc:
+ case ContentSecurityPolicy::DirectiveType::kManifestSrc:
+ case ContentSecurityPolicy::DirectiveType::kMediaSrc:
+ case ContentSecurityPolicy::DirectiveType::kPrefetchSrc:
+ case ContentSecurityPolicy::DirectiveType::kObjectSrc:
+ case ContentSecurityPolicy::DirectiveType::kScriptSrc:
+ case ContentSecurityPolicy::DirectiveType::kStyleSrc:
+ return ContentSecurityPolicy::DirectiveType::kDefaultSrc;
+
+ case ContentSecurityPolicy::DirectiveType::kFrameSrc:
+ case ContentSecurityPolicy::DirectiveType::kWorkerSrc:
+ return ContentSecurityPolicy::DirectiveType::kChildSrc;
+
+ // Because the fallback chain of child-src can be different if we are
+ // checking a worker or a frame request, we need to know the original type
+ // of the request to decide. These are the fallback chains for worker-src
+ // and frame-src specifically.
+
+ // worker-src > child-src > script-src > default-src
+ // frame-src > child-src > default-src
+
+ // Since there are some situations and tests that will operate on the
+ // `child-src` directive directly (like for example the EE subsumption
+ // algorithm), we consider the child-src > default-src fallback path as the
+ // "default" and the worker-src fallback path as an exception.
+ case ContentSecurityPolicy::DirectiveType::kChildSrc:
+ if (original_directive ==
+ ContentSecurityPolicy::DirectiveType::kWorkerSrc)
+ return ContentSecurityPolicy::DirectiveType::kScriptSrc;
+
+ return ContentSecurityPolicy::DirectiveType::kDefaultSrc;
+
+ default:
+ return ContentSecurityPolicy::DirectiveType::kUndefined;
+ }
+}
+
SourceListDirective* CSPDirectiveList::OperativeDirective(
- const ContentSecurityPolicy::DirectiveType& type) const {
+ const ContentSecurityPolicy::DirectiveType type,
+ ContentSecurityPolicy::DirectiveType original_type) const {
+ if (type == ContentSecurityPolicy::DirectiveType::kUndefined) {
+ return nullptr;
+ }
+
+ SourceListDirective* directive;
+ if (original_type == ContentSecurityPolicy::DirectiveType::kUndefined) {
+ original_type = type;
+ }
+
switch (type) {
- // Directives that do not have a default directive.
case ContentSecurityPolicy::DirectiveType::kBaseURI:
- return base_uri_.Get();
+ directive = base_uri_;
+ break;
case ContentSecurityPolicy::DirectiveType::kDefaultSrc:
- return default_src_.Get();
+ directive = default_src_;
+ break;
case ContentSecurityPolicy::DirectiveType::kFrameAncestors:
- return frame_ancestors_.Get();
+ directive = frame_ancestors_;
+ break;
case ContentSecurityPolicy::DirectiveType::kFormAction:
- return form_action_.Get();
+ directive = form_action_;
+ break;
case ContentSecurityPolicy::DirectiveType::kNavigateTo:
- return navigate_to_.Get();
- // Directives that have one default directive.
+ directive = navigate_to_;
+ break;
case ContentSecurityPolicy::DirectiveType::kChildSrc:
- return OperativeDirective(child_src_.Get());
+ directive = child_src_;
+ break;
case ContentSecurityPolicy::DirectiveType::kConnectSrc:
- return OperativeDirective(connect_src_.Get());
+ directive = connect_src_;
+ break;
case ContentSecurityPolicy::DirectiveType::kFontSrc:
- return OperativeDirective(font_src_.Get());
+ directive = font_src_;
+ break;
case ContentSecurityPolicy::DirectiveType::kImgSrc:
- return OperativeDirective(img_src_.Get());
+ directive = img_src_;
+ break;
case ContentSecurityPolicy::DirectiveType::kManifestSrc:
- return OperativeDirective(manifest_src_.Get());
+ directive = manifest_src_;
+ break;
case ContentSecurityPolicy::DirectiveType::kMediaSrc:
- return OperativeDirective(media_src_.Get());
+ directive = media_src_;
+ break;
case ContentSecurityPolicy::DirectiveType::kObjectSrc:
- return OperativeDirective(object_src_.Get());
+ directive = object_src_;
+ break;
+ case ContentSecurityPolicy::DirectiveType::kPrefetchSrc:
+ directive = prefetch_src_;
+ break;
case ContentSecurityPolicy::DirectiveType::kScriptSrc:
- return OperativeDirective(script_src_.Get());
+ directive = script_src_;
+ break;
case ContentSecurityPolicy::DirectiveType::kStyleSrc:
- return OperativeDirective(style_src_.Get());
- // Directives that default to 'child-src' (which defaults to 'default-src')
+ directive = style_src_;
+ break;
case ContentSecurityPolicy::DirectiveType::kFrameSrc:
- return OperativeDirective(frame_src_.Get(),
- OperativeDirective(child_src_.Get()));
- // Directives that default to 'script-src' (which defaults to 'default-src')
+ directive = frame_src_;
+ break;
case ContentSecurityPolicy::DirectiveType::kWorkerSrc:
- return OperativeDirective(worker_src_.Get(),
- OperativeDirective(script_src_.Get()));
+ directive = worker_src_;
+ break;
default:
return nullptr;
}
+
+ // if the directive does not exist, rely on the fallback directive
+ return directive ? directive
+ : OperativeDirective(FallbackDirective(type, original_type),
+ original_type);
}
SourceListDirectiveVector CSPDirectiveList::GetSourceVector(
- const ContentSecurityPolicy::DirectiveType& type,
+ const ContentSecurityPolicy::DirectiveType type,
const CSPDirectiveListVector& policies) {
SourceListDirectiveVector source_list_directives;
for (const auto& policy : policies) {
@@ -1472,7 +1562,7 @@ bool CSPDirectiveList::Subsumes(const CSPDirectiveListVector& other) {
// A white-list of directives that we consider for subsumption.
// See more about source lists here:
// https://w3c.github.io/webappsec-csp/#framework-directive-source-list
- ContentSecurityPolicy::DirectiveType directives[] = {
+ static ContentSecurityPolicy::DirectiveType directives[] = {
ContentSecurityPolicy::DirectiveType::kChildSrc,
ContentSecurityPolicy::DirectiveType::kConnectSrc,
ContentSecurityPolicy::DirectiveType::kFontSrc,
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 75388843493..2d55db6ef9b 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
@@ -231,21 +231,21 @@ class CORE_EXPORT CSPDirectiveList
Member<CSPDirectiveType>&,
bool should_parse_wasm_eval = false);
- SourceListDirective* OperativeDirective(SourceListDirective*) const;
- SourceListDirective* OperativeDirective(SourceListDirective*,
- SourceListDirective* override) const;
+ ContentSecurityPolicy::DirectiveType FallbackDirective(
+ const ContentSecurityPolicy::DirectiveType current_directive,
+ const ContentSecurityPolicy::DirectiveType original_directive) const;
void ReportViolation(const String& directive_text,
- const ContentSecurityPolicy::DirectiveType&,
+ const ContentSecurityPolicy::DirectiveType,
const String& console_message,
const KURL& blocked_url,
ResourceRequest::RedirectStatus) const;
void ReportViolationWithFrame(const String& directive_text,
- const ContentSecurityPolicy::DirectiveType&,
+ const ContentSecurityPolicy::DirectiveType,
const String& console_message,
const KURL& blocked_url,
LocalFrame*) const;
void ReportViolationWithLocation(const String& directive_text,
- const ContentSecurityPolicy::DirectiveType&,
+ const ContentSecurityPolicy::DirectiveType,
const String& console_message,
const KURL& blocked_url,
const String& context_url,
@@ -253,7 +253,7 @@ class CORE_EXPORT CSPDirectiveList
Element*,
const String& source) const;
void ReportEvalViolation(const String& directive_text,
- const ContentSecurityPolicy::DirectiveType&,
+ const ContentSecurityPolicy::DirectiveType,
const String& message,
const KURL& blocked_url,
ScriptState*,
@@ -267,7 +267,7 @@ class CORE_EXPORT CSPDirectiveList
bool AreAllMatchingHashesPresent(SourceListDirective*,
const IntegrityMetadataSet&) const;
bool CheckHash(SourceListDirective*, const CSPHashValue&) const;
- bool CheckHashedAttributes(SourceListDirective*) const;
+ bool CheckUnsafeHashesAllowed(SourceListDirective*) const;
bool CheckSource(SourceListDirective*,
const KURL&,
ResourceRequest::RedirectStatus) const;
@@ -300,11 +300,10 @@ class CORE_EXPORT CSPDirectiveList
bool is_script,
const String& hash_value) const;
- bool CheckSourceAndReportViolation(
- SourceListDirective*,
- const KURL&,
- const ContentSecurityPolicy::DirectiveType&,
- ResourceRequest::RedirectStatus) const;
+ bool CheckSourceAndReportViolation(SourceListDirective*,
+ const KURL&,
+ const ContentSecurityPolicy::DirectiveType,
+ ResourceRequest::RedirectStatus) const;
bool CheckMediaTypeAndReportViolation(MediaListDirective*,
const String& type,
const String& type_attribute,
@@ -320,16 +319,23 @@ class CORE_EXPORT CSPDirectiveList
bool DenyIfEnforcingPolicy() const { return IsReportOnly(); }
// This function returns a SourceListDirective of a given type
- // or if it is not defined, the default SourceListDirective for that type.
+ // or if it is not defined, the fallback SourceListDirective for that type.
SourceListDirective* OperativeDirective(
- const ContentSecurityPolicy::DirectiveType&) const;
+ const ContentSecurityPolicy::DirectiveType type,
+ ContentSecurityPolicy::DirectiveType original_type =
+ ContentSecurityPolicy::DirectiveType::kUndefined) const;
// This function aggregates from a vector of policies all operative
// SourceListDirectives of a given type into a vector.
static SourceListDirectiveVector GetSourceVector(
- const ContentSecurityPolicy::DirectiveType&,
+ const ContentSecurityPolicy::DirectiveType,
const CSPDirectiveListVector& policies);
+ bool AllowHash(
+ const CSPHashValue& hash_value,
+ const ContentSecurityPolicy::InlineType type,
+ const ContentSecurityPolicy::DirectiveType directive_type) const;
+
Member<ContentSecurityPolicy> policy_;
String header_;
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 80939562aad..a7cbc6d25db 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
@@ -88,8 +88,8 @@ TEST_F(CSPDirectiveListTest, IsMatchingNoncePresent) {
// Report-only
Member<CSPDirectiveList> directive_list =
CreateList(test.list, kContentSecurityPolicyHeaderTypeReport);
- Member<SourceListDirective> script_src =
- directive_list->OperativeDirective(directive_list->script_src_.Get());
+ Member<SourceListDirective> script_src = directive_list->OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kScriptSrc);
EXPECT_EQ(test.expected,
directive_list->IsMatchingNoncePresent(script_src, test.nonce));
// Empty/null strings are always not present, regardless of the policy.
@@ -99,8 +99,8 @@ TEST_F(CSPDirectiveListTest, IsMatchingNoncePresent) {
// Enforce
directive_list =
CreateList(test.list, kContentSecurityPolicyHeaderTypeEnforce);
- script_src =
- directive_list->OperativeDirective(directive_list->script_src_.Get());
+ script_src = directive_list->OperativeDirective(
+ ContentSecurityPolicy::DirectiveType::kScriptSrc);
EXPECT_EQ(test.expected,
directive_list->IsMatchingNoncePresent(script_src, test.nonce));
// Empty/null strings are always not present, regardless of the policy.
@@ -564,14 +564,14 @@ TEST_F(CSPDirectiveListTest, WorkerSrcChildSrcFallback) {
// When 'worker-src' is not present, 'child-src' can allow a worker when
// present.
{"child-src https://example.test", true},
- {"child-src https://not-example.test", true},
+ {"child-src https://not-example.test", false},
{"script-src https://example.test", true},
{"script-src https://not-example.test", false},
{"child-src https://example.test; script-src https://example.test", true},
{"child-src https://example.test; script-src https://not-example.test",
true},
{"child-src https://not-example.test; script-src https://example.test",
- true},
+ false},
{"child-src https://not-example.test; script-src "
"https://not-example.test",
false},
@@ -869,7 +869,7 @@ TEST_F(CSPDirectiveListTest, OperativeDirectiveGivenType) {
kDefault,
kNoDefault,
kChildAndDefault,
- kScriptAndDefault
+ kChildAndScriptAndDefault
};
struct TestCase {
@@ -893,7 +893,8 @@ TEST_F(CSPDirectiveListTest, OperativeDirectiveGivenType) {
{ContentSecurityPolicy::DirectiveType::kFormAction, kNoDefault},
// Directive with multiple default directives.
{ContentSecurityPolicy::DirectiveType::kFrameSrc, kChildAndDefault},
- {ContentSecurityPolicy::DirectiveType::kWorkerSrc, kScriptAndDefault},
+ {ContentSecurityPolicy::DirectiveType::kWorkerSrc,
+ kChildAndScriptAndDefault},
};
// Initial set-up.
@@ -922,7 +923,7 @@ TEST_F(CSPDirectiveListTest, OperativeDirectiveGivenType) {
std::stringstream all_except_this;
std::stringstream all_except_child_src_and_this;
- std::stringstream all_except_script_src_and_this;
+ std::stringstream all_except_child_src_and_script_src_and_this;
for (const auto& subtest : cases) {
if (subtest.directive == test.directive)
continue;
@@ -936,9 +937,11 @@ TEST_F(CSPDirectiveListTest, OperativeDirectiveGivenType) {
<< directive_name << ".com; ";
}
if (subtest.directive !=
- ContentSecurityPolicy::DirectiveType::kScriptSrc) {
- all_except_script_src_and_this << directive_name << " http://"
- << directive_name << ".com; ";
+ ContentSecurityPolicy::DirectiveType::kChildSrc &&
+ subtest.directive !=
+ ContentSecurityPolicy::DirectiveType::kScriptSrc) {
+ all_except_child_src_and_script_src_and_this
+ << directive_name << " http://" << directive_name << ".com; ";
}
}
CSPDirectiveList* all_except_this_list = CreateList(
@@ -946,8 +949,8 @@ TEST_F(CSPDirectiveListTest, OperativeDirectiveGivenType) {
CSPDirectiveList* all_except_child_src_and_this_list =
CreateList(all_except_child_src_and_this.str().c_str(),
kContentSecurityPolicyHeaderTypeEnforce);
- CSPDirectiveList* all_except_script_src_and_this_list =
- CreateList(all_except_script_src_and_this.str().c_str(),
+ CSPDirectiveList* all_except_child_src_and_script_src_and_this_list =
+ CreateList(all_except_child_src_and_script_src_and_this.str().c_str(),
kContentSecurityPolicyHeaderTypeEnforce);
switch (test.type) {
@@ -971,12 +974,17 @@ TEST_F(CSPDirectiveListTest, OperativeDirectiveGivenType) {
EXPECT_EQ(sources.size(), 1u);
EXPECT_EQ(sources[0]->host_, "default-src.com");
break;
- case kScriptAndDefault:
+ case kChildAndScriptAndDefault:
sources =
all_except_this_list->OperativeDirective(test.directive)->list_;
EXPECT_EQ(sources.size(), 1u);
+ EXPECT_EQ(sources[0]->host_, "child-src.com");
+ sources = all_except_child_src_and_this_list
+ ->OperativeDirective(test.directive)
+ ->list_;
+ EXPECT_EQ(sources.size(), 1u);
EXPECT_EQ(sources[0]->host_, "script-src.com");
- sources = all_except_script_src_and_this_list
+ sources = all_except_child_src_and_script_src_and_this_list
->OperativeDirective(test.directive)
->list_;
EXPECT_EQ(sources.size(), 1u);
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/source_list_directive.cc b/chromium/third_party/blink/renderer/core/frame/csp/source_list_directive.cc
index d01d351d264..7ad92d95d89 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/source_list_directive.cc
+++ b/chromium/third_party/blink/renderer/core/frame/csp/source_list_directive.cc
@@ -37,7 +37,7 @@ SourceListDirective::SourceListDirective(const String& name,
allow_eval_(false),
allow_wasm_eval_(false),
allow_dynamic_(false),
- allow_hashed_attributes_(false),
+ allow_unsafe_hashes_(false),
report_sample_(false),
hash_algorithms_used_(0) {
Vector<UChar> characters;
@@ -108,8 +108,8 @@ bool SourceListDirective::AllowHash(const CSPHashValue& hash_value) const {
return hashes_.Contains(hash_value);
}
-bool SourceListDirective::AllowHashedAttributes() const {
- return allow_hashed_attributes_;
+bool SourceListDirective::AllowUnsafeHashes() const {
+ return allow_unsafe_hashes_;
}
bool SourceListDirective::AllowReportSample() const {
@@ -118,7 +118,7 @@ bool SourceListDirective::AllowReportSample() const {
bool SourceListDirective::IsNone() const {
return !list_.size() && !allow_self_ && !allow_star_ && !allow_inline_ &&
- !allow_hashed_attributes_ && !allow_eval_ && !allow_wasm_eval_ &&
+ !allow_unsafe_hashes_ && !allow_eval_ && !allow_wasm_eval_ &&
!allow_dynamic_ && !nonces_.size() && !hashes_.size();
}
@@ -234,8 +234,8 @@ bool SourceListDirective::ParseSource(
return true;
}
- if (EqualIgnoringASCIICase("'unsafe-hashed-attributes'", token)) {
- AddSourceUnsafeHashedAttributes();
+ if (EqualIgnoringASCIICase("'unsafe-hashes'", token)) {
+ AddSourceUnsafeHashes();
return true;
}
@@ -632,8 +632,8 @@ void SourceListDirective::AddSourceStrictDynamic() {
allow_dynamic_ = true;
}
-void SourceListDirective::AddSourceUnsafeHashedAttributes() {
- allow_hashed_attributes_ = true;
+void SourceListDirective::AddSourceUnsafeHashes() {
+ allow_unsafe_hashes_ = true;
}
void SourceListDirective::AddReportSample() {
@@ -719,7 +719,7 @@ bool SourceListDirective::Subsumes(
bool allow_eval_other = other[0]->allow_eval_;
bool allow_wasm_eval_other = other[0]->allow_wasm_eval_;
bool allow_dynamic_other = other[0]->allow_dynamic_;
- bool allow_hashed_attributes_other = other[0]->allow_hashed_attributes_;
+ bool allow_unsafe_hashes = other[0]->allow_unsafe_hashes_;
bool is_hash_or_nonce_present_other = other[0]->IsHashOrNoncePresent();
HashSet<String> nonces_b = other[0]->nonces_;
HashSet<CSPHashValue> hashes_b = other[0]->hashes_;
@@ -731,8 +731,7 @@ bool SourceListDirective::Subsumes(
allow_eval_other = allow_eval_other && other[i]->allow_eval_;
allow_wasm_eval_other = allow_wasm_eval_other && other[i]->allow_wasm_eval_;
allow_dynamic_other = allow_dynamic_other && other[i]->allow_dynamic_;
- allow_hashed_attributes_other =
- allow_hashed_attributes_other && other[i]->allow_hashed_attributes_;
+ allow_unsafe_hashes = allow_unsafe_hashes && other[i]->allow_unsafe_hashes_;
is_hash_or_nonce_present_other =
is_hash_or_nonce_present_other && other[i]->IsHashOrNoncePresent();
nonces_b = other[i]->GetIntersectNonces(nonces_b);
@@ -751,7 +750,7 @@ bool SourceListDirective::Subsumes(
return false;
if (!allow_wasm_eval_ && allow_wasm_eval_other)
return false;
- if (!allow_hashed_attributes_ && allow_hashed_attributes_other)
+ if (!allow_unsafe_hashes_ && allow_unsafe_hashes)
return false;
bool allow_all_inline_other =
allow_inline_other && !is_hash_or_nonce_present_other &&
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/source_list_directive.h b/chromium/third_party/blink/renderer/core/frame/csp/source_list_directive.h
index 87a85279074..195c0af78f2 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/source_list_directive.h
+++ b/chromium/third_party/blink/renderer/core/frame/csp/source_list_directive.h
@@ -43,7 +43,7 @@ class CORE_EXPORT SourceListDirective final : public CSPDirective {
bool AllowDynamic() const;
bool AllowNonce(const String& nonce) const;
bool AllowHash(const CSPHashValue&) const;
- bool AllowHashedAttributes() const;
+ bool AllowUnsafeHashes() const;
bool AllowReportSample() const;
bool IsNone() const;
bool IsHashOrNoncePresent() const;
@@ -102,7 +102,7 @@ class CORE_EXPORT SourceListDirective final : public CSPDirective {
void AddSourceUnsafeEval();
void AddSourceWasmEval();
void AddSourceStrictDynamic();
- void AddSourceUnsafeHashedAttributes();
+ void AddSourceUnsafeHashes();
void AddReportSample();
void AddSourceNonce(const String& nonce);
void AddSourceHash(const ContentSecurityPolicyHashAlgorithm&,
@@ -132,7 +132,7 @@ class CORE_EXPORT SourceListDirective final : public CSPDirective {
bool allow_eval_;
bool allow_wasm_eval_;
bool allow_dynamic_;
- bool allow_hashed_attributes_;
+ bool allow_unsafe_hashes_;
bool allow_redirects_;
bool report_sample_;
HashSet<String> nonces_;
diff --git a/chromium/third_party/blink/renderer/core/frame/csp/source_list_directive_test.cc b/chromium/third_party/blink/renderer/core/frame/csp/source_list_directive_test.cc
index 225007ae66e..97987c6ece8 100644
--- a/chromium/third_party/blink/renderer/core/frame/csp/source_list_directive_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/csp/source_list_directive_test.cc
@@ -74,11 +74,11 @@ TEST_F(SourceListDirectiveTest, BasicMatchingStrictDynamic) {
EXPECT_TRUE(source_list.AllowDynamic());
}
-TEST_F(SourceListDirectiveTest, BasicMatchingUnsafeHashedAttributes) {
- String sources = "'unsafe-hashed-attributes'";
+TEST_F(SourceListDirectiveTest, BasicMatchingUnsafeHashes) {
+ String sources = "'unsafe-hashes'";
SourceListDirective source_list("script-src", sources, csp.Get());
- EXPECT_TRUE(source_list.AllowHashedAttributes());
+ EXPECT_TRUE(source_list.AllowUnsafeHashes());
}
TEST_F(SourceListDirectiveTest, BasicMatchingStar) {
@@ -743,37 +743,37 @@ TEST_F(SourceListDirectiveTest, SubsumesUnsafeAttributes) {
"http://example1.com/foo/bar 'self' 'unsafe-eval'",
"http://non-example.com/foo/ 'unsafe-eval' 'self'"},
false},
- // A or policiesB contain `unsafe-hashed-attributes`.
+ // A or policiesB contain `unsafe-hashes`.
{false,
"http://example1.com/foo/ 'self' 'unsafe-inline' 'unsafe-eval' "
"'strict-dynamic' "
- "'unsafe-hashed-attributes'",
- {"http://example1.com/foo/bar.html 'unsafe-hashed-attributes'"},
+ "'unsafe-hashes'",
+ {"http://example1.com/foo/bar.html 'unsafe-hashes'"},
true},
{true,
- "http://example1.com/foo/ 'self' 'unsafe-hashed-attributes'",
+ "http://example1.com/foo/ 'self' 'unsafe-hashes'",
{"http://example1.com/foo/ 'unsafe-inline'"},
false},
{true,
- "http://example1.com/foo/ 'self' 'unsafe-hashed-attributes'",
- {"http://example1.com/foo/ 'unsafe-inline' 'unsafe-hashed-attributes'"},
+ "http://example1.com/foo/ 'self' 'unsafe-hashes'",
+ {"http://example1.com/foo/ 'unsafe-inline' 'unsafe-hashes'"},
false},
{true,
"http://example1.com/foo/ 'self' 'unsafe-eval' "
- "'unsafe-hashed-attributes'",
- {"http://example1.com/foo/ 'unsafe-eval' 'unsafe-hashed-attributes'",
- "http://example1.com/foo/bar 'self' 'unsafe-hashed-attributes'",
- "http://non-example.com/foo/ 'unsafe-hashed-attributes' 'self'"},
+ "'unsafe-hashes'",
+ {"http://example1.com/foo/ 'unsafe-eval' 'unsafe-hashes'",
+ "http://example1.com/foo/bar 'self' 'unsafe-hashes'",
+ "http://non-example.com/foo/ 'unsafe-hashes' 'self'"},
true},
{true,
"http://example1.com/foo/ 'self'",
- {"http://example1.com/foo/ 'unsafe-hashed-attributes'"},
+ {"http://example1.com/foo/ 'unsafe-hashes'"},
false},
{true,
"http://example1.com/foo/ 'self' 'unsafe-inline'",
- {"http://example1.com/foo/ 'unsafe-hashed-attributes'",
- "http://example1.com/foo/bar 'self' 'unsafe-hashed-attributes'",
- "https://example1.com/foo/bar 'unsafe-hashed-attributes' 'self'"},
+ {"http://example1.com/foo/ 'unsafe-hashes'",
+ "http://example1.com/foo/bar 'self' 'unsafe-hashes'",
+ "https://example1.com/foo/bar 'unsafe-hashes' 'self'"},
false},
};
@@ -1130,13 +1130,13 @@ TEST_F(SourceListDirectiveTest, SubsumesStrictDynamic) {
{"'strict-dynamic' 'nonce-yay'", "'nonce-yay'", "'sha512-321abc'"},
true},
{true,
- "http://example1.com/foo/ 'self' 'unsafe-hashed-attributes' "
+ "http://example1.com/foo/ 'self' 'unsafe-hashes' "
"'strict-dynamic'",
- {"'strict-dynamic' 'unsafe-hashed-attributes'"},
+ {"'strict-dynamic' 'unsafe-hashes'"},
true},
{true,
"http://example1.com/foo/ 'self' 'nonce-yay' 'strict-dynamic'",
- {"'strict-dynamic' 'nonce-yay' 'unsafe-hashed-attributes'"},
+ {"'strict-dynamic' 'nonce-yay' 'unsafe-hashes'"},
false},
{true,
"http://example1.com/foo/ 'self' 'unsafe-eval' 'strict-dynamic'",
@@ -1209,12 +1209,12 @@ TEST_F(SourceListDirectiveTest, SubsumesStrictDynamic) {
{"'unsafe-eval' 'strict-dynamic'"},
false},
{true,
- "'unsafe-hashed-attributes' 'self' 'sha512-321abc' 'strict-dynamic'",
- {"'unsafe-hashed-attributes' 'strict-dynamic'"},
+ "'unsafe-hashes' 'self' 'sha512-321abc' 'strict-dynamic'",
+ {"'unsafe-hashes' 'strict-dynamic'"},
true},
{true,
"http://example1.com/foo/ 'self' 'sha512-321abc' 'strict-dynamic'",
- {"'unsafe-hashed-attributes' 'strict-dynamic'"},
+ {"'unsafe-hashes' 'strict-dynamic'"},
false},
};
@@ -1256,7 +1256,7 @@ TEST_F(SourceListDirectiveTest, SubsumesListWildcard) {
{"http://another.test", {"https:", "'self'"}, true},
{"'self'", {"*", "'self'"}, true},
{"'unsafe-eval' * ", {"'unsafe-eval'"}, true},
- {"'unsafe-hashed-attributes' * ", {"'unsafe-hashed-attributes'"}, true},
+ {"'unsafe-hashes' * ", {"'unsafe-hashes'"}, true},
{"'unsafe-inline' * ", {"'unsafe-inline'"}, true},
{"*", {"*", "http://a.com ws://b.com ftp://c.com"}, true},
{"*", {"* data: blob:", "http://a.com ws://b.com ftp://c.com"}, true},
@@ -1279,10 +1279,10 @@ TEST_F(SourceListDirectiveTest, SubsumesListWildcard) {
false},
{"https://another.test", {"*"}, false},
{"*", {"* 'unsafe-eval'"}, false},
- {"*", {"* 'unsafe-hashed-attributes'"}, false},
+ {"*", {"* 'unsafe-hashes'"}, false},
{"*", {"* 'unsafe-inline'"}, false},
{"'unsafe-eval'", {"* 'unsafe-eval'"}, false},
- {"'unsafe-hashed-attributes'", {"* 'unsafe-hashed-attributes'"}, false},
+ {"'unsafe-hashes'", {"* 'unsafe-hashes'"}, false},
{"'unsafe-inline'", {"* 'unsafe-inline'"}, false},
{"*", {"data: blob:", "data://a.com ws://b.com ftp://c.com"}, false},
{"* data:",
diff --git a/chromium/third_party/blink/renderer/core/frame/deprecation.cc b/chromium/third_party/blink/renderer/core/frame/deprecation.cc
index 5c501037a85..fbe82e389d1 100644
--- a/chromium/third_party/blink/renderer/core/frame/deprecation.cc
+++ b/chromium/third_party/blink/renderer/core/frame/deprecation.cc
@@ -10,7 +10,7 @@
#include "third_party/blink/public/platform/reporting.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/core/frame/deprecation_report.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_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
@@ -182,10 +182,6 @@ DeprecationInfo GetDeprecationInfo(WebFeature feature) {
"'navigator.webkitTemporaryStorage' or "
"'navigator.webkitPersistentStorage'")};
- case WebFeature::kConsoleMarkTimeline:
- return {"ConsoleMarkTimeline", kUnknown,
- ReplacedBy("'console.markTimeline'", "'console.timeStamp'")};
-
case WebFeature::kPrefixedVideoSupportsFullscreen:
return {"PrefixedVideoSupportsFullscreen", kUnknown,
ReplacedBy("'HTMLVideoElement.webkitSupportsFullscreen'",
@@ -231,14 +227,6 @@ DeprecationInfo GetDeprecationInfo(WebFeature feature) {
"<source src> with a <picture> parent is invalid and therefore "
"ignored. Please use <source srcset> instead."};
- case WebFeature::kConsoleTimeline:
- return {"ConsoleTimeline", kUnknown,
- ReplacedBy("'console.timeline'", "'console.time'")};
-
- case WebFeature::kConsoleTimelineEnd:
- return {"ConsoleTimelineEnd", kUnknown,
- ReplacedBy("'console.timelineEnd'", "'console.timeEnd'")};
-
case WebFeature::kXMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload:
return {"XMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload",
kUnknown,
@@ -504,28 +492,22 @@ DeprecationInfo GetDeprecationInfo(WebFeature feature) {
case WebFeature::kPresentationRequestStartInsecureOrigin:
case WebFeature::kPresentationReceiverInsecureOrigin:
return {
- "PresentationInsecureOrigin", kM68,
+ "PresentationInsecureOrigin", kM71,
String("Using the Presentation API on insecure origins is "
- "deprecated and will be removed in M68. You should consider "
+ "deprecated and will be removed in M71. You should consider "
"switching your application to a secure origin, such as "
"HTTPS. See "
"https://goo.gl/rStTGz for more details.")};
- case WebFeature::kPaymentRequestSupportedMethodsArray:
- return {"PaymentRequestSupportedMethodsArray", kM64,
- ReplacedWillBeRemoved(
- "PaymentRequest's supportedMethods taking an array",
- "a single string", kM64, "5177301645918208")};
-
case WebFeature::kLocalCSSFileExtensionRejected:
return {"LocalCSSFileExtensionRejected", kM64,
String("CSS cannot be loaded from `file:` URLs unless they end "
"in a `.css` file extension.")};
case WebFeature::kCreateObjectURLMediaStream:
- return {"CreateObjectURLMediaStreamDeprecated", kM69,
+ return {"CreateObjectURLMediaStreamDeprecated", kM71,
ReplacedWillBeRemoved("URL.createObjectURL with media streams",
- "HTMLMediaElement.srcObject", kM69,
+ "HTMLMediaElement.srcObject", kM71,
"5618491470118912")};
case WebFeature::kChromeLoadTimesRequestTime:
@@ -556,20 +538,6 @@ DeprecationInfo GetDeprecationInfo(WebFeature feature) {
"Using unescaped '#' characters in a data URI body", "'%23'",
kM71, "5656049583390720")};
- case WebFeature::kImageInputTypeFormDataWithNonEmptyValue:
- return {"ImageInputTypeFormDataWithNonEmptyValue", kM68,
- WillBeRemoved("Extra form data if value attribute "
- "is present with non-empty "
- "value for <input type='image'>",
- kM68, "5672688152477696")};
-
-
- case WebFeature::kV8Document_CreateTouchList_Method:
- return {"V8Document_CreateTouchList_Method", kM69,
- ReplacedWillBeRemoved("document.createTouchList",
- "TouchEvent constructor", kM69,
- "5668612064935936")};
-
case WebFeature::kDocumentOrigin:
return {"DocumentOrigin", kM70,
ReplacedWillBeRemoved("document.origin",
@@ -581,6 +549,41 @@ DeprecationInfo GetDeprecationInfo(WebFeature feature) {
WillBeRemoved("Anonymous named getter of HTMLFrameSetElement",
kM70, "5235521668251648")};
+ case WebFeature::kMediaElementSourceOnOfflineContext:
+ return {"MediaElementAudioSourceNode", kM70,
+ WillBeRemoved("Creating a MediaElementAudioSourceNode on an "
+ "OfflineAudioContext",
+ kM70, "5258622686724096")};
+
+ case WebFeature::kMediaStreamDestinationOnOfflineContext:
+ return {"MediaStreamAudioDestinationNode", kM70,
+ WillBeRemoved("Creating a MediaStreamAudioDestinationNode on an "
+ "OfflineAudioContext",
+ kM70, "5258622686724096")};
+
+ case WebFeature::kMediaStreamSourceOnOfflineContext:
+ return {
+ "MediaStreamAudioSourceNode", kM70,
+ WillBeRemoved(
+ "Creating a MediaStreamAudioSourceNode on an OfflineAudioContext",
+ kM70, "5258622686724096")};
+
+ case WebFeature::kRTCDataChannelInitMaxRetransmitTime:
+ return {"RTCDataChannelInitMaxRetransmitTime", kM70,
+ ReplacedWillBeRemoved("maxRetransmitTime", "maxPacketLifeTime",
+ kM70, "5198350873788416")};
+
+ case WebFeature::kGridRowTrackPercentIndefiniteHeight:
+ return {"GridRowTrackPercentIndefiniteHeight", kM70,
+ String::Format("Percentages row tracks and gutters for "
+ "indefinite height grid containers will be "
+ "resolved against the intrinsic height instead of "
+ "being treated as auto and zero respectively. "
+ "This change will happen in %s. See "
+ "https://www.chromestatus.com/feature/"
+ "6708326821789696 for more details.",
+ MilestoneString(kM70))};
+
// Features that aren't deprecated don't have a deprecation message.
default:
return {"NotDeprecated", kUnknown, ""};
@@ -593,12 +596,15 @@ namespace blink {
Deprecation::Deprecation() : mute_count_(0) {
css_property_deprecation_bits_.EnsureSize(numCSSPropertyIDs);
+ features_deprecation_bits_.EnsureSize(
+ static_cast<int>(WebFeature::kNumberOfFeatures));
}
Deprecation::~Deprecation() = default;
void Deprecation::ClearSuppression() {
css_property_deprecation_bits_.ClearAll();
+ features_deprecation_bits_.ClearAll();
}
void Deprecation::MuteForInspector() {
@@ -619,6 +625,14 @@ bool Deprecation::IsSuppressed(CSSPropertyID unresolved_property) {
return css_property_deprecation_bits_.QuickGet(unresolved_property);
}
+void Deprecation::SetReported(WebFeature feature) {
+ features_deprecation_bits_.QuickSet(static_cast<int>(feature));
+}
+
+bool Deprecation::GetReported(WebFeature feature) const {
+ return features_deprecation_bits_.QuickGet(static_cast<int>(feature));
+}
+
void Deprecation::WarnOnDeprecatedProperties(
const LocalFrame* frame,
CSSPropertyID unresolved_property) {
@@ -643,18 +657,16 @@ String Deprecation::DeprecationMessage(CSSPropertyID unresolved_property) {
return g_empty_string;
}
+// TODO(loonybear): Replace CountDeprecation(LocalFrame*) by CountDeprecation(
+// DocumentLoader*) eventually.
void Deprecation::CountDeprecation(const LocalFrame* frame,
WebFeature feature) {
if (!frame)
return;
- Page* page = frame->GetPage();
- if (!page || page->GetDeprecation().mute_count_)
- return;
-
- if (!page->GetUseCounter().HasRecordedMeasurement(feature)) {
- page->GetUseCounter().RecordMeasurement(feature, *frame);
- GenerateReport(frame, feature);
- }
+ DocumentLoader* loader = frame->GetDocument()
+ ? frame->GetDocument()->Loader()
+ : frame->Loader().GetProvisionalDocumentLoader();
+ Deprecation::CountDeprecation(loader, feature);
}
void Deprecation::CountDeprecation(ExecutionContext* context,
@@ -671,7 +683,23 @@ void Deprecation::CountDeprecation(ExecutionContext* context,
void Deprecation::CountDeprecation(const Document& document,
WebFeature feature) {
- Deprecation::CountDeprecation(document.GetFrame(), feature);
+ Deprecation::CountDeprecation(document.Loader(), feature);
+}
+
+void Deprecation::CountDeprecation(DocumentLoader* loader, WebFeature feature) {
+ if (!loader)
+ return;
+ LocalFrame* frame = loader->GetFrame();
+ if (!frame)
+ return;
+ Page* page = frame->GetPage();
+ if (!loader || !page || page->GetDeprecation().mute_count_ ||
+ page->GetDeprecation().GetReported(feature))
+ return;
+
+ page->GetDeprecation().SetReported(feature);
+ UseCounter::Count(loader, feature);
+ GenerateReport(frame, feature);
}
void Deprecation::CountDeprecationCrossOriginIframe(const LocalFrame* frame,
@@ -761,24 +789,26 @@ void Deprecation::GenerateReport(const LocalFrame* frame, WebFeature feature) {
// Construct the deprecation report.
double removal_date = MilestoneDate(info.anticipated_removal);
- DeprecationReport* body = new DeprecationReport(
+ DeprecationReportBody* body = new DeprecationReportBody(
info.id, removal_date, info.message, SourceLocation::Capture());
Report* report = new Report("deprecation", document->Url().GetString(), body);
// Send the deprecation report to any ReportingObservers.
- ReportingContext* reporting_context = ReportingContext::From(document);
- if (reporting_context->ObserverExists())
- reporting_context->QueueReport(report);
+ ReportingContext::From(document)->QueueReport(report);
// Send the deprecation report to the Reporting API.
mojom::blink::ReportingServiceProxyPtr service;
Platform* platform = Platform::Current();
platform->GetConnector()->BindInterface(platform->GetBrowserServiceName(),
&service);
- service->QueueDeprecationReport(document->Url(), info.id,
- WTF::Time::FromDoubleT(removal_date),
- info.message, body->sourceFile(),
- body->lineNumber(), body->columnNumber());
+ bool is_null;
+ int line_number = body->lineNumber(is_null);
+ line_number = is_null ? 0 : line_number;
+ int column_number = body->columnNumber(is_null);
+ column_number = is_null ? 0 : column_number;
+ service->QueueDeprecationReport(
+ document->Url(), info.id, WTF::Time::FromDoubleT(removal_date),
+ info.message, body->sourceFile(), line_number, column_number);
}
// static
diff --git a/chromium/third_party/blink/renderer/core/frame/deprecation.h b/chromium/third_party/blink/renderer/core/frame/deprecation.h
index 093e6f4aaac..c85f2d15c31 100644
--- a/chromium/third_party/blink/renderer/core/frame/deprecation.h
+++ b/chromium/third_party/blink/renderer/core/frame/deprecation.h
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css_property_names.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/platform/wtf/bit_vector.h"
namespace blink {
@@ -44,6 +45,7 @@ class CORE_EXPORT Deprecation {
static void CountDeprecation(const LocalFrame*, WebFeature);
static void CountDeprecation(ExecutionContext*, WebFeature);
static void CountDeprecation(const Document&, WebFeature);
+ static void CountDeprecation(DocumentLoader*, WebFeature);
// Count only features if they're being used in an iframe which does not
// have script access into the top level document.
@@ -60,6 +62,8 @@ class CORE_EXPORT Deprecation {
protected:
void Suppress(CSSPropertyID unresolved_property);
+ void SetReported(WebFeature feature);
+ bool GetReported(WebFeature feature) const;
// CSSPropertyIDs that aren't deprecated return an empty string.
static String DeprecationMessage(CSSPropertyID unresolved_property);
@@ -67,6 +71,9 @@ class CORE_EXPORT Deprecation {
// ReportingObservers. Also sends the deprecation message to the console.
static void GenerateReport(const LocalFrame*, WebFeature);
+ // To minimize the report/console spam from frames coming and going, report
+ // each deprecation at most once per page load per renderer process.
+ BitVector features_deprecation_bits_;
BitVector css_property_deprecation_bits_;
unsigned mute_count_;
diff --git a/chromium/third_party/blink/renderer/core/frame/deprecation_report.h b/chromium/third_party/blink/renderer/core/frame/deprecation_report.h
deleted file mode 100644
index 989465da273..00000000000
--- a/chromium/third_party/blink/renderer/core/frame/deprecation_report.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DEPRECATION_REPORT_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DEPRECATION_REPORT_H_
-
-#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
-#include "third_party/blink/renderer/core/frame/message_report.h"
-
-namespace blink {
-
-class CORE_EXPORT DeprecationReport : public MessageReport {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- DeprecationReport(const String& id,
- double anticipatedRemoval,
- const String& message,
- std::unique_ptr<SourceLocation> location)
- : MessageReport(message, std::move(location)),
- id_(id),
- anticipatedRemoval_(anticipatedRemoval) {}
-
- ~DeprecationReport() override = default;
-
- String id() const { return id_; }
- double anticipatedRemoval(bool& is_null) const {
- is_null = !anticipatedRemoval_;
- return anticipatedRemoval_;
- }
-
- private:
- const String id_;
- const double anticipatedRemoval_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DEPRECATION_REPORT_H_
diff --git a/chromium/third_party/blink/renderer/core/frame/deprecation_report.idl b/chromium/third_party/blink/renderer/core/frame/deprecation_report.idl
deleted file mode 100644
index 3602ad74ee5..00000000000
--- a/chromium/third_party/blink/renderer/core/frame/deprecation_report.idl
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://github.com/WICG/reporting/blob/master/EXPLAINER.md#reportingobserver---observing-reports-from-javascript
-
-[
- NoInterfaceObject,
- RuntimeEnabled=ReportingObserver
-] interface DeprecationReport : ReportBody {
- readonly attribute DOMString id;
- readonly attribute Date? anticipatedRemoval;
- readonly attribute DOMString message;
- readonly attribute DOMString sourceFile;
- readonly attribute long lineNumber;
- readonly attribute long columnNumber;
-};
diff --git a/chromium/third_party/blink/renderer/core/frame/deprecation_report_body.h b/chromium/third_party/blink/renderer/core/frame/deprecation_report_body.h
new file mode 100644
index 00000000000..5b24d162ddc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/deprecation_report_body.h
@@ -0,0 +1,40 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DEPRECATION_REPORT_BODY_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DEPRECATION_REPORT_BODY_H_
+
+#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
+#include "third_party/blink/renderer/core/frame/message_report_body.h"
+
+namespace blink {
+
+class CORE_EXPORT DeprecationReportBody : public MessageReportBody {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ DeprecationReportBody(const String& id,
+ double anticipatedRemoval,
+ const String& message,
+ std::unique_ptr<SourceLocation> location)
+ : MessageReportBody(message, std::move(location)),
+ id_(id),
+ anticipatedRemoval_(anticipatedRemoval) {}
+
+ ~DeprecationReportBody() override = default;
+
+ String id() const { return id_; }
+ double anticipatedRemoval(bool& is_null) const {
+ is_null = !anticipatedRemoval_;
+ return anticipatedRemoval_;
+ }
+
+ private:
+ const String id_;
+ const double anticipatedRemoval_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DEPRECATION_REPORT_BODY_H_
diff --git a/chromium/third_party/blink/renderer/core/frame/deprecation_report_body.idl b/chromium/third_party/blink/renderer/core/frame/deprecation_report_body.idl
new file mode 100644
index 00000000000..8ac1919fdf8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/deprecation_report_body.idl
@@ -0,0 +1,17 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://wicg.github.io/reporting/#deprecation-report
+
+[
+ NoInterfaceObject,
+ RuntimeEnabled=DeprecationReporting
+] interface DeprecationReportBody : ReportBody {
+ readonly attribute DOMString id;
+ readonly attribute Date? anticipatedRemoval;
+ readonly attribute DOMString message;
+ readonly attribute DOMString? sourceFile;
+ readonly attribute unsigned long? lineNumber;
+ readonly attribute unsigned long? columnNumber;
+};
diff --git a/chromium/third_party/blink/renderer/core/frame/display_cutout_client_impl.cc b/chromium/third_party/blink/renderer/core/frame/display_cutout_client_impl.cc
new file mode 100644
index 00000000000..055f69cfb85
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/display_cutout_client_impl.cc
@@ -0,0 +1,53 @@
+// 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/frame/display_cutout_client_impl.h"
+
+#include "third_party/blink/renderer/core/css/document_style_environment_variables.h"
+#include "third_party/blink/renderer/core/css/style_engine.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+
+namespace blink {
+
+namespace {
+
+const char kSafeAreaInsetTopName[] = "safe-area-inset-top";
+const char kSafeAreaInsetLeftName[] = "safe-area-inset-left";
+const char kSafeAreaInsetBottomName[] = "safe-area-inset-bottom";
+const char kSafeAreaInsetRightName[] = "safe-area-inset-right";
+
+String GetPx(int value) {
+ return String::Format("%dpx", value);
+}
+
+} // namespace
+
+DisplayCutoutClientImpl::DisplayCutoutClientImpl(
+ LocalFrame* frame,
+ mojom::blink::DisplayCutoutClientAssociatedRequest request)
+ : frame_(frame), binding_(this, std::move(request)) {}
+
+void DisplayCutoutClientImpl::BindMojoRequest(
+ LocalFrame* frame,
+ mojom::blink::DisplayCutoutClientAssociatedRequest request) {
+ if (!frame)
+ return;
+ new DisplayCutoutClientImpl(frame, std::move(request));
+}
+
+void DisplayCutoutClientImpl::SetSafeArea(
+ mojom::blink::DisplayCutoutSafeAreaPtr safe_area) {
+ DocumentStyleEnvironmentVariables& vars =
+ frame_->GetDocument()->GetStyleEngine().EnsureEnvironmentVariables();
+ vars.SetVariable(kSafeAreaInsetTopName, GetPx(safe_area->top));
+ vars.SetVariable(kSafeAreaInsetLeftName, GetPx(safe_area->left));
+ vars.SetVariable(kSafeAreaInsetBottomName, GetPx(safe_area->bottom));
+ vars.SetVariable(kSafeAreaInsetRightName, GetPx(safe_area->right));
+}
+
+void DisplayCutoutClientImpl::Trace(Visitor* visitor) {
+ visitor->Trace(frame_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/display_cutout_client_impl.h b/chromium/third_party/blink/renderer/core/frame/display_cutout_client_impl.h
new file mode 100644
index 00000000000..56aade212f6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/display_cutout_client_impl.h
@@ -0,0 +1,45 @@
+// 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_FRAME_DISPLAY_CUTOUT_CLIENT_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DISPLAY_CUTOUT_CLIENT_IMPL_H_
+
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "third_party/blink/public/mojom/page/display_cutout.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/heap/member.h"
+
+namespace blink {
+
+class LocalFrame;
+
+// Mojo interface to set CSS environment variables for display cutout.
+class CORE_EXPORT DisplayCutoutClientImpl final
+ : public GarbageCollectedFinalized<DisplayCutoutClientImpl>,
+ public mojom::blink::DisplayCutoutClient {
+ public:
+ static void BindMojoRequest(
+ LocalFrame*,
+ mojom::blink::DisplayCutoutClientAssociatedRequest);
+
+ // Notify the renderer that the safe areas have changed.
+ void SetSafeArea(mojom::blink::DisplayCutoutSafeAreaPtr safe_area) override;
+
+ void Trace(Visitor*);
+
+ private:
+ DisplayCutoutClientImpl(LocalFrame*,
+ mojom::blink::DisplayCutoutClientAssociatedRequest);
+
+ Member<LocalFrame> frame_;
+
+ mojo::AssociatedBinding<mojom::blink::DisplayCutoutClient> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(DisplayCutoutClientImpl);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DISPLAY_CUTOUT_CLIENT_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/core/frame/dom_timer.cc b/chromium/third_party/blink/renderer/core/frame/dom_timer.cc
index 452bc15c511..11a6310355c 100644
--- a/chromium/third_party/blink/renderer/core/frame/dom_timer.cc
+++ b/chromium/third_party/blink/renderer/core/frame/dom_timer.cc
@@ -116,9 +116,10 @@ DOMTimer::~DOMTimer() {
}
void DOMTimer::Stop() {
+ const bool is_interval = !RepeatInterval().is_zero();
probe::AsyncTaskCanceledBreakable(
- GetExecutionContext(),
- RepeatInterval() ? "clearInterval" : "clearTimeout", this);
+ GetExecutionContext(), is_interval ? "clearInterval" : "clearTimeout",
+ this);
user_gesture_token_ = nullptr;
// Need to release JS objects potentially protected by ScheduledAction
@@ -145,19 +146,17 @@ void DOMTimer::Fired() {
TRACE_EVENT1("devtools.timeline", "TimerFire", "data",
InspectorTimerFireEvent::Data(context, timeout_id_));
- probe::UserCallback probe(context,
- RepeatInterval() ? "setInterval" : "setTimeout",
- AtomicString(), true);
- probe::AsyncTask async_task(context, this,
- RepeatInterval() ? "fired" : nullptr);
+ const bool is_interval = !RepeatInterval().is_zero();
+ probe::UserCallback probe(context, is_interval ? "setInterval" : "setTimeout",
+ g_null_atom, true);
+ probe::AsyncTask async_task(context, this, is_interval ? "fired" : nullptr);
// Simple case for non-one-shot timers.
if (IsActive()) {
- if (!RepeatIntervalDelta().is_zero() &&
- RepeatIntervalDelta() < kMinimumInterval) {
+ if (is_interval && RepeatInterval() < kMinimumInterval) {
nesting_level_++;
if (nesting_level_ >= kMaxTimerNestingLevel)
- AugmentRepeatInterval(kMinimumInterval - RepeatIntervalDelta());
+ AugmentRepeatInterval(kMinimumInterval - RepeatInterval());
}
// No access to member variables after this point, it can delete the timer.
diff --git a/chromium/third_party/blink/renderer/core/frame/dom_visual_viewport.cc b/chromium/third_party/blink/renderer/core/frame/dom_visual_viewport.cc
index 49e98b508ed..f3ef4890793 100644
--- a/chromium/third_party/blink/renderer/core/frame/dom_visual_viewport.cc
+++ b/chromium/third_party/blink/renderer/core/frame/dom_visual_viewport.cc
@@ -33,6 +33,7 @@
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.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/core/style/computed_style.h"
namespace blink {
@@ -87,13 +88,12 @@ float DOMVisualViewport::pageLeft() const {
return 0;
LocalFrameView* view = frame->View();
- if (!view || !view->LayoutViewportScrollableArea())
+ if (!view || !view->LayoutViewport())
return 0;
frame->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
- float viewport_x =
- page->GetVisualViewport().GetScrollOffset().Width() +
- view->LayoutViewportScrollableArea()->GetScrollOffset().Width();
+ float viewport_x = page->GetVisualViewport().GetScrollOffset().Width() +
+ view->LayoutViewport()->GetScrollOffset().Width();
return AdjustForAbsoluteZoom::AdjustScroll(viewport_x,
frame->PageZoomFactor());
}
@@ -108,13 +108,12 @@ float DOMVisualViewport::pageTop() const {
return 0;
LocalFrameView* view = frame->View();
- if (!view || !view->LayoutViewportScrollableArea())
+ if (!view || !view->LayoutViewport())
return 0;
frame->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
- float viewport_y =
- page->GetVisualViewport().GetScrollOffset().Height() +
- view->LayoutViewportScrollableArea()->GetScrollOffset().Height();
+ float viewport_y = page->GetVisualViewport().GetScrollOffset().Height() +
+ view->LayoutViewport()->GetScrollOffset().Height();
return AdjustForAbsoluteZoom::AdjustScroll(viewport_y,
frame->PageZoomFactor());
}
@@ -127,7 +126,7 @@ double DOMVisualViewport::width() const {
if (!frame->IsMainFrame()) {
// Update layout to ensure scrollbars are up-to-date.
frame->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
- auto* scrollable_area = frame->View()->LayoutViewportScrollableArea();
+ auto* scrollable_area = frame->View()->LayoutViewport();
float width =
scrollable_area->VisibleContentRect(kExcludeScrollbars).Width();
return AdjustForAbsoluteZoom::AdjustInt(clampTo<int>(ceilf(width)),
@@ -148,7 +147,7 @@ double DOMVisualViewport::height() const {
if (!frame->IsMainFrame()) {
// Update layout to ensure scrollbars are up-to-date.
frame->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
- auto* scrollable_area = frame->View()->LayoutViewportScrollableArea();
+ auto* scrollable_area = frame->View()->LayoutViewport();
float height =
scrollable_area->VisibleContentRect(kExcludeScrollbars).Height();
return AdjustForAbsoluteZoom::AdjustInt(clampTo<int>(ceilf(height)),
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 7cae0ec22c8..21c4cd01f89 100644
--- a/chromium/third_party/blink/renderer/core/frame/dom_window.cc
+++ b/chromium/third_party/blink/renderer/core/frame/dom_window.cc
@@ -19,6 +19,7 @@
#include "third_party/blink/renderer/core/frame/location.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/core/frame/window_post_message_options.h"
#include "third_party/blink/renderer/core/input/input_device_capabilities.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/loader/mixed_content_checker.h"
@@ -108,6 +109,50 @@ DOMWindow* DOMWindow::top() const {
return GetFrame()->Tree().Top().DomWindow();
}
+void DOMWindow::postMessage(LocalDOMWindow* incumbent_window,
+ const ScriptValue& message,
+ const String& target_origin,
+ Vector<ScriptValue>& transfer,
+ ExceptionState& exception_state) {
+ WindowPostMessageOptions options;
+ options.setTargetOrigin(target_origin);
+ postMessage(incumbent_window, message, transfer, options, exception_state);
+}
+
+void DOMWindow::postMessage(LocalDOMWindow* incumbent_window,
+ const ScriptValue& message,
+ Vector<ScriptValue>& transfer,
+ const WindowPostMessageOptions& options,
+ ExceptionState& exception_state) {
+ UseCounter::Count(incumbent_window->GetFrame(),
+ WebFeature::kWindowPostMessage);
+
+ // Since remote windows do not have a v8::Context, we cannot use
+ // [CallWith=ScriptState], and there is no good way to get the v8::Isolate.
+ // As a compromise, ask the isolate to the WindowProxyManager.
+ v8::Isolate* isolate = window_proxy_manager_->GetIsolate();
+
+ Transferables transferables;
+ if (!transfer.IsEmpty()) {
+ if (!SerializedScriptValue::ExtractTransferables(
+ isolate, transfer, transferables, exception_state)) {
+ return;
+ }
+ }
+
+ SerializedScriptValue::SerializeOptions serialize_options;
+ serialize_options.transferables = &transferables;
+ scoped_refptr<SerializedScriptValue> serialized_message =
+ SerializedScriptValue::Serialize(isolate, message.V8Value(),
+ serialize_options, exception_state);
+ if (exception_state.HadException())
+ return;
+
+ serialized_message->UnregisterMemoryAllocatedWithCurrentScriptContext();
+ DoPostMessage(std::move(serialized_message), transferables.message_ports,
+ options.targetOrigin(), incumbent_window, exception_state);
+}
+
DOMWindow* DOMWindow::AnonymousIndexedGetter(uint32_t index) const {
if (!GetFrame())
return nullptr;
@@ -149,86 +194,6 @@ bool DOMWindow::IsInsecureScriptAccess(LocalDOMWindow& calling_window,
return true;
}
-void DOMWindow::postMessage(scoped_refptr<SerializedScriptValue> message,
- const MessagePortArray& ports,
- const String& target_origin,
- LocalDOMWindow* source,
- ExceptionState& exception_state) {
- if (!IsCurrentlyDisplayedInFrame())
- return;
-
- Document* source_document = source->document();
-
- // Compute the target origin. We need to do this synchronously in order
- // to generate the SyntaxError exception correctly.
- scoped_refptr<const SecurityOrigin> target;
- if (target_origin == "/") {
- if (!source_document)
- return;
- target = source_document->GetSecurityOrigin();
- } else if (target_origin != "*") {
- target = SecurityOrigin::CreateFromString(target_origin);
- // It doesn't make sense target a postMessage at a unique origin
- // because there's no way to represent a unique origin in a string.
- if (target->IsUnique()) {
- exception_state.ThrowDOMException(
- kSyntaxError, "Invalid target origin '" + target_origin +
- "' in a call to 'postMessage'.");
- return;
- }
- }
-
- auto channels = MessagePort::DisentanglePorts(GetExecutionContext(), ports,
- exception_state);
- if (exception_state.HadException())
- return;
-
- // Capture the source of the message. We need to do this synchronously
- // in order to capture the source of the message correctly.
- if (!source_document)
- return;
-
- const SecurityOrigin* security_origin = source_document->GetSecurityOrigin();
-
- String source_origin = security_origin->ToString();
-
- KURL target_url = IsLocalDOMWindow()
- ? blink::ToLocalDOMWindow(this)->document()->Url()
- : KURL(NullURL(), GetFrame()
- ->GetSecurityContext()
- ->GetSecurityOrigin()
- ->ToString());
- if (MixedContentChecker::IsMixedContent(source_document->GetSecurityOrigin(),
- target_url)) {
- UseCounter::Count(source->GetFrame(),
- WebFeature::kPostMessageFromSecureToInsecure);
- } else if (MixedContentChecker::IsMixedContent(
- GetFrame()->GetSecurityContext()->GetSecurityOrigin(),
- source_document->Url())) {
- UseCounter::Count(source->GetFrame(),
- WebFeature::kPostMessageFromInsecureToSecure);
- if (MixedContentChecker::IsMixedContent(
- GetFrame()->Tree().Top().GetSecurityContext()->GetSecurityOrigin(),
- source_document->Url())) {
- UseCounter::Count(source->GetFrame(),
- WebFeature::kPostMessageFromInsecureToSecureToplevel);
- }
- }
-
- if (!source_document->GetContentSecurityPolicy()->AllowConnectToSource(
- target_url, RedirectStatus::kNoRedirect,
- SecurityViolationReportingPolicy::kSuppressReporting)) {
- UseCounter::Count(
- source->GetFrame(),
- WebFeature::kPostMessageOutgoingWouldBeBlockedByConnectSrc);
- }
-
- MessageEvent* event = MessageEvent::Create(
- std::move(channels), std::move(message), source_origin, String(), source);
-
- SchedulePostMessage(event, std::move(target), source_document);
-}
-
// FIXME: Once we're throwing exceptions for cross-origin access violations, we
// will always sanitize the target frame details, so we can safely combine
// 'crossDomainAccessErrorMessage' with this method after considering exactly
@@ -434,6 +399,97 @@ InputDeviceCapabilitiesConstants* DOMWindow::GetInputDeviceCapabilities() {
return input_capabilities_;
}
+void DOMWindow::PostMessageForTesting(
+ scoped_refptr<SerializedScriptValue> message,
+ const MessagePortArray& ports,
+ const String& target_origin,
+ LocalDOMWindow* source,
+ ExceptionState& exception_state) {
+ DoPostMessage(std::move(message), ports, target_origin, source,
+ exception_state);
+}
+
+void DOMWindow::DoPostMessage(scoped_refptr<SerializedScriptValue> message,
+ const MessagePortArray& ports,
+ const String& target_origin,
+ LocalDOMWindow* source,
+ ExceptionState& exception_state) {
+ if (!IsCurrentlyDisplayedInFrame())
+ return;
+
+ Document* source_document = source->document();
+
+ // Compute the target origin. We need to do this synchronously in order
+ // to generate the SyntaxError exception correctly.
+ scoped_refptr<const SecurityOrigin> target;
+ if (target_origin == "/") {
+ if (!source_document)
+ return;
+ target = source_document->GetSecurityOrigin();
+ } else if (target_origin != "*") {
+ target = SecurityOrigin::CreateFromString(target_origin);
+ // It doesn't make sense target a postMessage at a unique origin
+ // because there's no way to represent a unique origin in a string.
+ if (target->IsOpaque()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
+ "Invalid target origin '" +
+ target_origin +
+ "' in a call to 'postMessage'.");
+ return;
+ }
+ }
+
+ auto channels = MessagePort::DisentanglePorts(GetExecutionContext(), ports,
+ exception_state);
+ if (exception_state.HadException())
+ return;
+
+ // Capture the source of the message. We need to do this synchronously
+ // in order to capture the source of the message correctly.
+ if (!source_document)
+ return;
+
+ const SecurityOrigin* security_origin = source_document->GetSecurityOrigin();
+
+ String source_origin = security_origin->ToString();
+
+ KURL target_url = IsLocalDOMWindow()
+ ? blink::ToLocalDOMWindow(this)->document()->Url()
+ : KURL(NullURL(), GetFrame()
+ ->GetSecurityContext()
+ ->GetSecurityOrigin()
+ ->ToString());
+ if (MixedContentChecker::IsMixedContent(source_document->GetSecurityOrigin(),
+ target_url)) {
+ UseCounter::Count(source->GetFrame(),
+ WebFeature::kPostMessageFromSecureToInsecure);
+ } else if (MixedContentChecker::IsMixedContent(
+ GetFrame()->GetSecurityContext()->GetSecurityOrigin(),
+ source_document->Url())) {
+ UseCounter::Count(source->GetFrame(),
+ WebFeature::kPostMessageFromInsecureToSecure);
+ if (MixedContentChecker::IsMixedContent(
+ GetFrame()->Tree().Top().GetSecurityContext()->GetSecurityOrigin(),
+ source_document->Url())) {
+ UseCounter::Count(source->GetFrame(),
+ WebFeature::kPostMessageFromInsecureToSecureToplevel);
+ }
+ }
+
+ if (!source_document->GetContentSecurityPolicy()->AllowConnectToSource(
+ target_url, RedirectStatus::kNoRedirect,
+ SecurityViolationReportingPolicy::kSuppressReporting)) {
+ UseCounter::Count(
+ source->GetFrame(),
+ WebFeature::kPostMessageOutgoingWouldBeBlockedByConnectSrc);
+ }
+
+ MessageEvent* event = MessageEvent::Create(
+ std::move(channels), std::move(message), source_origin, String(), source);
+
+ SchedulePostMessage(event, std::move(target), source_document);
+}
+
void DOMWindow::Trace(blink::Visitor* visitor) {
visitor->Trace(frame_);
visitor->Trace(window_proxy_manager_);
@@ -442,9 +498,4 @@ void DOMWindow::Trace(blink::Visitor* visitor) {
EventTargetWithInlineData::Trace(visitor);
}
-void DOMWindow::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(location_);
- EventTargetWithInlineData::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/dom_window.h b/chromium/third_party/blink/renderer/core/frame/dom_window.h
index 73464d04e42..31905b58793 100644
--- a/chromium/third_party/blink/renderer/core/frame/dom_window.h
+++ b/chromium/third_party/blink/renderer/core/frame/dom_window.h
@@ -22,7 +22,10 @@ class InputDeviceCapabilitiesConstants;
class LocalDOMWindow;
class Location;
class MessageEvent;
+class ScriptValue;
+class SecurityOrigin;
class SerializedScriptValue;
+class WindowPostMessageOptions;
class WindowProxyManager;
class CORE_EXPORT DOMWindow : public EventTargetWithInlineData,
@@ -33,14 +36,14 @@ class CORE_EXPORT DOMWindow : public EventTargetWithInlineData,
~DOMWindow() override;
Frame* GetFrame() const {
- // A Frame is typically reused for navigations. If |m_frame| is not null,
+ // A Frame is typically reused for navigations. If |frame_| is not null,
// two conditions must always be true:
- // - |m_frame->domWindow()| must point back to this DOMWindow. If it does
+ // - |frame_->domWindow()| must point back to this DOMWindow. If it does
// not, it is easy to introduce a bug where script execution uses the
// wrong DOMWindow (which may be cross-origin).
- // - |m_frame| must be attached, i.e. |m_frame->page()| must not be null.
- // If |m_frame->page()| is null, this indicates a bug where the frame was
- // detached but |m_frame| was not set to null. This bug can lead to
+ // - |frame_| must be attached, i.e. |frame_->page()| must not be null.
+ // If |frame_->page()| is null, this indicates a bug where the frame was
+ // detached but |frame_| was not set to null. This bug can lead to
// issues where executing script incorrectly schedules work on a detached
// frame.
SECURITY_DCHECK(!frame_ ||
@@ -51,8 +54,6 @@ class CORE_EXPORT DOMWindow : public EventTargetWithInlineData,
// GarbageCollectedFinalized overrides:
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
virtual bool IsLocalDOMWindow() const = 0;
virtual bool IsRemoteDOMWindow() const = 0;
@@ -86,15 +87,21 @@ class CORE_EXPORT DOMWindow : public EventTargetWithInlineData,
virtual void blur() = 0;
void close(LocalDOMWindow* incumbent_window);
- // Indexed properties
- DOMWindow* AnonymousIndexedGetter(uint32_t index) const;
-
- void postMessage(scoped_refptr<SerializedScriptValue> message,
- const MessagePortArray&,
+ void postMessage(LocalDOMWindow* incumbent_window,
+ const ScriptValue& message,
const String& target_origin,
- LocalDOMWindow* source,
+ Vector<ScriptValue>& transfer,
+ ExceptionState&);
+
+ void postMessage(LocalDOMWindow* incumbent_window,
+ const ScriptValue& message,
+ Vector<ScriptValue>& transfer,
+ const WindowPostMessageOptions& options,
ExceptionState&);
+ // Indexed properties
+ DOMWindow* AnonymousIndexedGetter(uint32_t index) const;
+
String SanitizedCrossDomainAccessErrorMessage(
const LocalDOMWindow* calling_window) const;
String CrossDomainAccessErrorMessage(
@@ -103,8 +110,8 @@ class CORE_EXPORT DOMWindow : public EventTargetWithInlineData,
// FIXME: When this DOMWindow is no longer the active DOMWindow (i.e.,
// when its document is no longer the document that is displayed in its
- // frame), we would like to zero out m_frame to avoid being confused
- // by the document that is currently active in m_frame.
+ // frame), we would like to zero out |frame_| to avoid being confused
+ // by the document that is currently active in |frame_|.
// See https://bugs.webkit.org/show_bug.cgi?id=62054
bool IsCurrentlyDisplayedInFrame() const;
@@ -112,6 +119,12 @@ class CORE_EXPORT DOMWindow : public EventTargetWithInlineData,
InputDeviceCapabilitiesConstants* GetInputDeviceCapabilities();
+ void PostMessageForTesting(scoped_refptr<SerializedScriptValue> message,
+ const MessagePortArray&,
+ const String& target_origin,
+ LocalDOMWindow* source,
+ ExceptionState&);
+
protected:
explicit DOMWindow(Frame&);
@@ -122,6 +135,12 @@ class CORE_EXPORT DOMWindow : public EventTargetWithInlineData,
void DisconnectFromFrame() { frame_ = nullptr; }
private:
+ void DoPostMessage(scoped_refptr<SerializedScriptValue> message,
+ const MessagePortArray&,
+ const String& target_origin,
+ LocalDOMWindow* source,
+ ExceptionState&);
+
Member<Frame> frame_;
// Unlike |frame_|, |window_proxy_manager_| is available even after the
// window's frame gets detached from the DOM, until the end of the lifetime
diff --git a/chromium/third_party/blink/renderer/core/frame/dom_window_base64.cc b/chromium/third_party/blink/renderer/core/frame/dom_window_base64.cc
index ae5d9f483bb..67a51dded68 100644
--- a/chromium/third_party/blink/renderer/core/frame/dom_window_base64.cc
+++ b/chromium/third_party/blink/renderer/core/frame/dom_window_base64.cc
@@ -32,9 +32,8 @@
#include "third_party/blink/renderer/core/frame/dom_window_base64.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/base64.h"
namespace blink {
@@ -46,7 +45,7 @@ String DOMWindowBase64::btoa(const String& string_to_encode,
if (!string_to_encode.ContainsOnlyLatin1()) {
exception_state.ThrowDOMException(
- kInvalidCharacterError,
+ DOMExceptionCode::kInvalidCharacterError,
"The string to be encoded contains "
"characters outside of the Latin1 range.");
return String();
@@ -62,7 +61,7 @@ String DOMWindowBase64::atob(const String& encoded_string,
if (!encoded_string.ContainsOnlyLatin1()) {
exception_state.ThrowDOMException(
- kInvalidCharacterError,
+ DOMExceptionCode::kInvalidCharacterError,
"The string to be decoded contains "
"characters outside of the Latin1 range.");
return String();
@@ -71,7 +70,7 @@ String DOMWindowBase64::atob(const String& encoded_string,
if (!Base64Decode(encoded_string, out, IsHTMLSpace<UChar>,
kBase64ValidatePadding)) {
exception_state.ThrowDOMException(
- kInvalidCharacterError,
+ DOMExceptionCode::kInvalidCharacterError,
"The string to be decoded is not correctly encoded.");
return String();
}
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 b0b7ec27f38..fb49073f4cc 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
@@ -9,6 +9,8 @@
#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_frame_owner_element.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/scrolling/scrolling_coordinator.h"
@@ -16,15 +18,15 @@ namespace blink {
namespace {
-WebEventListenerProperties GetWebEventListenerProperties(bool has_blocking,
- bool has_passive) {
+cc::EventListenerProperties GetEventListenerProperties(bool has_blocking,
+ bool has_passive) {
if (has_blocking && has_passive)
- return WebEventListenerProperties::kBlockingAndPassive;
+ return cc::EventListenerProperties::kBlockingAndPassive;
if (has_blocking)
- return WebEventListenerProperties::kBlocking;
+ return cc::EventListenerProperties::kBlocking;
if (has_passive)
- return WebEventListenerProperties::kPassive;
- return WebEventListenerProperties::kNothing;
+ return cc::EventListenerProperties::kPassive;
+ return cc::EventListenerProperties::kNone;
}
LocalFrame* GetLocalFrameForTarget(EventTarget* target) {
@@ -248,9 +250,9 @@ void EventHandlerRegistry::NotifyHasHandlersChanged(
case kWheelEventBlocking:
case kWheelEventPassive:
GetPage()->GetChromeClient().SetEventListenerProperties(
- frame, WebEventListenerClass::kMouseWheel,
- GetWebEventListenerProperties(HasEventHandlers(kWheelEventBlocking),
- HasEventHandlers(kWheelEventPassive)));
+ frame, cc::EventListenerClass::kMouseWheel,
+ GetEventListenerProperties(HasEventHandlers(kWheelEventBlocking),
+ HasEventHandlers(kWheelEventPassive)));
break;
case kTouchStartOrMoveEventBlockingLowLatency:
GetPage()->GetChromeClient().SetNeedsLowLatencyInput(frame,
@@ -261,8 +263,8 @@ void EventHandlerRegistry::NotifyHasHandlersChanged(
case kTouchStartOrMoveEventPassive:
case kPointerEvent:
GetPage()->GetChromeClient().SetEventListenerProperties(
- frame, WebEventListenerClass::kTouchStartOrMove,
- GetWebEventListenerProperties(
+ frame, cc::EventListenerClass::kTouchStartOrMove,
+ GetEventListenerProperties(
HasEventHandlers(kTouchAction) ||
HasEventHandlers(kTouchStartOrMoveEventBlocking) ||
HasEventHandlers(kTouchStartOrMoveEventBlockingLowLatency),
@@ -272,8 +274,8 @@ void EventHandlerRegistry::NotifyHasHandlersChanged(
case kTouchEndOrCancelEventBlocking:
case kTouchEndOrCancelEventPassive:
GetPage()->GetChromeClient().SetEventListenerProperties(
- frame, WebEventListenerClass::kTouchEndOrCancel,
- GetWebEventListenerProperties(
+ frame, cc::EventListenerClass::kTouchEndOrCancel,
+ GetEventListenerProperties(
HasEventHandlers(kTouchEndOrCancelEventBlocking),
HasEventHandlers(kTouchEndOrCancelEventPassive)));
break;
@@ -285,6 +287,22 @@ void EventHandlerRegistry::NotifyHasHandlersChanged(
NOTREACHED();
break;
}
+
+ if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()) {
+ if (handler_class == kTouchStartOrMoveEventBlocking ||
+ handler_class == kTouchStartOrMoveEventBlockingLowLatency) {
+ if (auto* node = target->ToNode()) {
+ if (auto* layout_object = node->GetLayoutObject())
+ layout_object->MarkEffectiveWhitelistedTouchActionChanged();
+ } else if (auto* dom_window = target->ToLocalDOMWindow()) {
+ // This event handler is on a window. Ensure the layout view is
+ // invalidated because the layout view tracks the window's blocking
+ // touch event rects.
+ if (auto* layout_view = dom_window->GetFrame()->ContentLayoutObject())
+ layout_view->MarkEffectiveWhitelistedTouchActionChanged();
+ }
+ }
+ }
}
void EventHandlerRegistry::NotifyDidAddOrRemoveEventHandlerTarget(
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 36ff9390b46..c1a4a34c3a7 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
@@ -32,14 +32,31 @@
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_find_options.h"
-#include "third_party/blink/public/web/web_frame_client.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_plugin.h"
#include "third_party/blink/public/web/web_plugin_document.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"
namespace blink {
+FindInPage::FindInPage(WebLocalFrameImpl& frame,
+ InterfaceRegistry* interface_registry)
+ : ContextLifecycleObserver(
+ frame.GetFrame() ? frame.GetFrame()->GetDocument() : nullptr),
+ frame_(&frame),
+ binding_(this) {
+ // TODO(rakina): Use InterfaceRegistry of |frame| directly rather than passing
+ // both of them.
+ if (!interface_registry)
+ return;
+ // TODO(crbug.com/800641): Use InterfaceValidator when it works for associated
+ // interfaces.
+ interface_registry->AddAssociatedInterface(
+ WTF::BindRepeating(&FindInPage::BindToRequest, WrapWeakPersistent(this)));
+}
+
void WebLocalFrameImpl::RequestFind(int identifier,
const WebString& search_text,
const WebFindOptions& options) {
@@ -230,11 +247,11 @@ void WebLocalFrameImpl::SetTickmarks(const WebVector<WebRect>& tickmarks) {
}
void FindInPage::SetTickmarks(const WebVector<WebRect>& tickmarks) {
- if (frame_->GetFrameView()) {
+ if (LayoutView* layout_view = frame_->GetFrame()->ContentLayoutObject()) {
Vector<IntRect> tickmarks_converted(tickmarks.size());
for (size_t i = 0; i < tickmarks.size(); ++i)
tickmarks_converted[i] = tickmarks[i];
- frame_->GetFrameView()->SetTickmarks(tickmarks_converted);
+ layout_view->OverrideTickmarks(tickmarks_converted);
}
}
@@ -286,4 +303,8 @@ void FindInPage::Dispose() {
binding_.Close();
}
+void FindInPage::ContextDestroyed(ExecutionContext* context) {
+ binding_.Close();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/find_in_page.h b/chromium/third_party/blink/renderer/core/frame/find_in_page.h
index e897d38736a..cd5c66b285c 100644
--- a/chromium/third_party/blink/renderer/core/frame/find_in_page.h
+++ b/chromium/third_party/blink/renderer/core/frame/find_in_page.h
@@ -12,6 +12,7 @@
#include "third_party/blink/public/web/web_local_frame.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/dom/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/editing/finder/text_finder.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@@ -24,6 +25,7 @@ struct WebFloatRect;
class CORE_EXPORT FindInPage final
: public GarbageCollectedFinalized<FindInPage>,
+ public ContextLifecycleObserver,
public mojom::blink::FindInPage {
USING_PRE_FINALIZER(FindInPage, Dispose);
@@ -88,19 +90,16 @@ class CORE_EXPORT FindInPage final
void Dispose();
- void Trace(blink::Visitor* visitor) {
+ void ContextDestroyed(ExecutionContext*) override;
+
+ void Trace(blink::Visitor* visitor) override {
visitor->Trace(text_finder_);
visitor->Trace(frame_);
+ ContextLifecycleObserver::Trace(visitor);
}
private:
- FindInPage(WebLocalFrameImpl& frame, InterfaceRegistry* interface_registry)
- : frame_(&frame), binding_(this) {
- if (!interface_registry)
- return;
- interface_registry->AddAssociatedInterface(WTF::BindRepeating(
- &FindInPage::BindToRequest, WrapWeakPersistent(this)));
- }
+ FindInPage(WebLocalFrameImpl& frame, InterfaceRegistry* interface_registry);
// Will be initialized after first call to ensureTextFinder().
Member<TextFinder> text_finder_;
diff --git a/chromium/third_party/blink/renderer/core/frame/frame.cc b/chromium/third_party/blink/renderer/core/frame/frame.cc
index 8e810c34d0d..660c3ac07b3 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame.cc
@@ -32,7 +32,7 @@
#include <memory>
-#include "third_party/blink/public/web/web_frame_client.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_remote_frame_client.h"
#include "third_party/blink/renderer/bindings/core/v8/window_proxy_manager.h"
#include "third_party/blink/renderer/core/dom/document_type.h"
@@ -175,28 +175,33 @@ void Frame::DidChangeVisibilityState() {
}
void Frame::NotifyUserActivationInLocalTree() {
- user_activation_state_.Activate();
- for (Frame* parent = Tree().Parent(); parent;
- parent = parent->Tree().Parent()) {
- parent->user_activation_state_.Activate();
- }
+ for (Frame* node = this; node; node = node->Tree().Parent())
+ node->user_activation_state_.Activate();
}
void Frame::NotifyUserActivation() {
+ ToLocalFrame(this)->Client()->NotifyUserActivation();
NotifyUserActivationInLocalTree();
- ToLocalFrame(this)->Client()->SetHasReceivedUserGesture();
}
-bool Frame::ConsumeTransientUserActivation() {
- for (Frame* parent = Tree().Parent(); parent;
- parent = parent->Tree().Parent()) {
- parent->user_activation_state_.ConsumeIfActive();
- }
- for (Frame* child = Tree().FirstChild(); child;
- child = child->Tree().TraverseNext(this)) {
- child->user_activation_state_.ConsumeIfActive();
- }
- return user_activation_state_.ConsumeIfActive();
+bool Frame::ConsumeTransientUserActivationInLocalTree() {
+ bool was_active = user_activation_state_.IsActive();
+
+ // Note that consumption "touches" the whole frame tree, to guarantee that a
+ // malicious subframe can't embed sub-subframes in a way that could allow
+ // multiple consumptions per user activation.
+ Frame& root = Tree().Top();
+ for (Frame* node = &root; node; node = node->Tree().TraverseNext(&root))
+ node->user_activation_state_.ConsumeIfActive();
+
+ return was_active;
+}
+
+bool Frame::ConsumeTransientUserActivation(
+ UserActivationUpdateSource update_source) {
+ if (update_source == UserActivationUpdateSource::kRenderer)
+ ToLocalFrame(this)->Client()->ConsumeUserActivation();
+ return ConsumeTransientUserActivationInLocalTree();
}
// static
@@ -230,10 +235,12 @@ bool Frame::HasTransientUserActivation(LocalFrame* frame,
}
// static
-bool Frame::ConsumeTransientUserActivation(LocalFrame* frame,
- bool checkIfMainThread) {
+bool Frame::ConsumeTransientUserActivation(
+ LocalFrame* frame,
+ bool checkIfMainThread,
+ UserActivationUpdateSource update_source) {
if (RuntimeEnabledFeatures::UserActivationV2Enabled()) {
- return frame ? frame->ConsumeTransientUserActivation() : false;
+ return frame ? frame->ConsumeTransientUserActivation(update_source) : false;
}
return checkIfMainThread
@@ -303,8 +310,9 @@ Frame::Frame(FrameClient* client,
}
STATIC_ASSERT_ENUM(FrameDetachType::kRemove,
- WebFrameClient::DetachType::kRemove);
-STATIC_ASSERT_ENUM(FrameDetachType::kSwap, WebFrameClient::DetachType::kSwap);
+ WebLocalFrameClient::DetachType::kRemove);
+STATIC_ASSERT_ENUM(FrameDetachType::kSwap,
+ WebLocalFrameClient::DetachType::kSwap);
STATIC_ASSERT_ENUM(FrameDetachType::kRemove,
WebRemoteFrameClient::DetachType::kRemove);
STATIC_ASSERT_ENUM(FrameDetachType::kSwap,
diff --git a/chromium/third_party/blink/renderer/core/frame/frame.h b/chromium/third_party/blink/renderer/core/frame/frame.h
index 203bc4e0201..9dd4cf19433 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame.h
+++ b/chromium/third_party/blink/renderer/core/frame/frame.h
@@ -33,12 +33,14 @@
#include "base/optional.h"
#include "base/unguessable_token.h"
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
+#include "third_party/blink/public/common/frame/user_activation_state.h"
+#include "third_party/blink/public/common/frame/user_activation_update_source.h"
+#include "third_party/blink/public/web/web_frame_load_type.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/user_gesture_indicator.h"
#include "third_party/blink/renderer/core/frame/frame_lifecycle.h"
#include "third_party/blink/renderer/core/frame/frame_types.h"
#include "third_party/blink/renderer/core/frame/frame_view.h"
-#include "third_party/blink/renderer/core/frame/user_activation_state.h"
#include "third_party/blink/renderer/core/loader/frame_loader_types.h"
#include "third_party/blink/renderer/core/page/frame_tree.h"
#include "third_party/blink/renderer/platform/graphics/touch_action.h"
@@ -82,14 +84,25 @@ class CORE_EXPORT Frame : public GarbageCollectedFinalized<Frame> {
virtual bool IsLocalFrame() const = 0;
virtual bool IsRemoteFrame() const = 0;
- virtual void Navigate(Document& origin_document,
- const KURL&,
- bool replace_current_item,
- UserGestureStatus) = 0;
- // This version of Frame::navigate assumes the resulting navigation is not
- // to be started on a timer. Use the method above in such cases.
+ // Asynchronously schedules a task to begin a navigation: this roughly
+ // corresponds to "queue a task to navigate the target browsing context to
+ // resource" in https://whatwg.org/C/links.html#following-hyperlinks.
+ //
+ // Note that there's currently an exception for same-origin same-document
+ // navigations: these are never scheduled and are always synchronously
+ // processed.
+ //
+ // TODO(dcheng): Note that despite the comment, most navigations in the spec
+ // are *not* currently queued. See https://github.com/whatwg/html/issues/3730.
+ // How this discussion is resolved will affect how https://crbug.com/848171 is
+ // eventually fixed.
+ virtual void ScheduleNavigation(Document& origin_document,
+ const KURL&,
+ bool replace_current_item,
+ UserGestureStatus) = 0;
+ // Synchronously begins a navigation.
virtual void Navigate(const FrameLoadRequest&) = 0;
- virtual void Reload(FrameLoadType, ClientRedirectPolicy) = 0;
+ virtual void Reload(WebFrameLoadType, ClientRedirectPolicy) = 0;
// The base Detach() method must be the last line of overrides of Detach().
virtual void Detach(FrameDetachType);
@@ -156,6 +169,9 @@ class CORE_EXPORT Frame : public GarbageCollectedFinalized<Frame> {
// This should never be called from outside Frame or WebFrame.
void NotifyUserActivationInLocalTree();
+ // This should never be called from outside Frame or WebFrame.
+ bool ConsumeTransientUserActivationInLocalTree();
+
bool HasBeenActivated() const {
return user_activation_state_.HasBeenActive();
}
@@ -199,8 +215,11 @@ class CORE_EXPORT Frame : public GarbageCollectedFinalized<Frame> {
//
// The |checkIfMainThread| parameter determines if the token based gestures
// (legacy code) must be used in a thread-safe manner.
- static bool ConsumeTransientUserActivation(LocalFrame*,
- bool checkIfMainThread = false);
+ static bool ConsumeTransientUserActivation(
+ LocalFrame*,
+ bool checkIfMainThread = false,
+ UserActivationUpdateSource update_source =
+ UserActivationUpdateSource::kRenderer);
bool IsAttached() const {
return lifecycle_.GetState() == FrameLifecycle::kAttached;
@@ -250,9 +269,8 @@ class CORE_EXPORT Frame : public GarbageCollectedFinalized<Frame> {
Member<FrameOwner> owner_;
Member<DOMWindow> dom_window_;
- // A LocalFrame is the primary "owner" of the activation state. The state in
- // a RemoteFrame serves as a cache for the corresponding LocalFrame state (to
- // avoid double hops through the browser during reading).
+ // The user activation state of the current frame. See
+ // FrameTreeNode::user_activation_state_ for details.
UserActivationState user_activation_state_;
bool has_received_user_gesture_before_nav_ = false;
@@ -279,7 +297,7 @@ class CORE_EXPORT Frame : public GarbageCollectedFinalized<Frame> {
// Consumes and returns the transient user activation of current Frame, after
// updating all ancestor/descendant frames.
- bool ConsumeTransientUserActivation();
+ bool ConsumeTransientUserActivation(UserActivationUpdateSource update_source);
Member<FrameClient> client_;
const Member<WindowProxyManager> window_proxy_manager_;
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 075d42cc53a..70b73c85976 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_serializer.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame_serializer.cc
@@ -403,10 +403,10 @@ void FrameSerializer::SerializeCSSStyleSheet(CSSStyleSheet& style_sheet,
TRACE_EVENT2("page-serialization", "FrameSerializer::serializeCSSStyleSheet",
"type", "CSS", "url", url.ElidedString().Utf8().data());
// Only report UMA metric if this is not a reentrant CSS serialization call.
- double css_start_time = 0;
+ TimeTicks css_start_time;
if (!is_serializing_css_) {
is_serializing_css_ = true;
- css_start_time = CurrentTimeTicksInSeconds();
+ css_start_time = CurrentTimeTicks();
}
// If this CSS is inlined its definition was already serialized with the frame
@@ -443,14 +443,12 @@ void FrameSerializer::SerializeCSSStyleSheet(CSSStyleSheet& style_sheet,
for (unsigned i = 0; i < style_sheet.length(); ++i)
SerializeCSSRule(style_sheet.item(i));
- if (css_start_time != 0) {
+ if (css_start_time != TimeTicks()) {
is_serializing_css_ = false;
DEFINE_STATIC_LOCAL(CustomCountHistogram, css_histogram,
("PageSerialization.SerializationTime.CSSElement", 0,
maxSerializationTimeUmaMicroseconds, 50));
- css_histogram.Count(
- static_cast<int64_t>((CurrentTimeTicksInSeconds() - css_start_time) *
- secondsToMicroseconds));
+ css_histogram.CountMicroseconds(CurrentTimeTicks() - css_start_time);
}
}
@@ -534,7 +532,7 @@ void FrameSerializer::AddImageToResources(ImageResourceContent* image,
TRACE_EVENT2("page-serialization", "FrameSerializer::addImageToResources",
"type", "image", "url", url.ElidedString().Utf8().data());
- double image_start_time = CurrentTimeTicksInSeconds();
+ base::TimeTicks image_start_time = CurrentTimeTicks();
scoped_refptr<const SharedBuffer> data = image->GetImage()->Data();
AddToResources(image->GetResponse().MimeType(),
@@ -549,9 +547,7 @@ void FrameSerializer::AddImageToResources(ImageResourceContent* image,
DEFINE_STATIC_LOCAL(CustomCountHistogram, image_histogram,
("PageSerialization.SerializationTime.ImageElement", 0,
maxSerializationTimeUmaMicroseconds, 50));
- image_histogram.Count(
- static_cast<int64_t>((CurrentTimeTicksInSeconds() - image_start_time) *
- secondsToMicroseconds));
+ image_histogram.CountMicroseconds(CurrentTimeTicks() - image_start_time);
}
}
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 c221f4759cb..dd8242b69b2 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
@@ -149,7 +149,7 @@ class FrameSerializerTest : public testing::Test,
String GetSerializedData(const char* url, const char* mime_type = nullptr) {
const SerializedResource* resource = GetResource(url, mime_type);
if (resource) {
- const Vector<char> data = resource->data->Copy();
+ const Vector<char> data = resource->data->CopyAs<Vector<char>>();
return String(data.data(), data.size());
}
return String();
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_test.cc b/chromium/third_party/blink/renderer/core/frame/frame_test.cc
index 1506c94b307..5de0224f6cd 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame_test.cc
@@ -163,4 +163,24 @@ TEST_F(FrameTest, NavigateSameDomainNoGesture) {
GetDocument().GetFrame()->HasReceivedUserGestureBeforeNavigation());
}
+TEST_F(FrameTest, UserActivationInterfaceTest) {
+ RuntimeEnabledFeatures::SetUserActivationV2Enabled(true);
+
+ // Initially both sticky and transient bits are false.
+ EXPECT_FALSE(GetDocument().GetFrame()->HasBeenActivated());
+ EXPECT_FALSE(Frame::HasTransientUserActivation(GetDocument().GetFrame()));
+
+ Frame::NotifyUserActivation(GetDocument().GetFrame());
+
+ // Now both sticky and transient bits are true, hence consumable.
+ EXPECT_TRUE(GetDocument().GetFrame()->HasBeenActivated());
+ EXPECT_TRUE(Frame::HasTransientUserActivation(GetDocument().GetFrame()));
+ EXPECT_TRUE(Frame::ConsumeTransientUserActivation(GetDocument().GetFrame()));
+
+ // After consumption, only the transient bit resets to false.
+ EXPECT_TRUE(GetDocument().GetFrame()->HasBeenActivated());
+ EXPECT_FALSE(Frame::HasTransientUserActivation(GetDocument().GetFrame()));
+ EXPECT_FALSE(Frame::ConsumeTransientUserActivation(GetDocument().GetFrame()));
+}
+
} // namespace blink
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 fd05810fcf9..25b337f1269 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
@@ -32,6 +32,9 @@
#include <utility>
+#include "cc/test/test_ukm_recorder_factory.h"
+#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/layer_tree_settings.h"
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_data.h"
@@ -41,6 +44,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/web/web_frame_widget.h"
+#include "third_party/blink/public/web/web_navigation_timings.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"
@@ -66,11 +70,11 @@ namespace {
// 2. Enter the run loop.
// 3. Posted task triggers the load, and starts pumping pending resource
// requests using runServeAsyncRequestsTask().
-// 4. TestWebFrameClient watches for didStartLoading/didStopLoading calls,
+// 4. TestWebFrameClient watches for DidStartLoading/DidStopLoading calls,
// keeping track of how many loads it thinks are in flight.
-// 5. While runServeAsyncRequestsTask() observes TestWebFrameClient to still
+// 5. While RunServeAsyncRequestsTask() observes TestWebFrameClient to still
// have loads in progress, it posts itself back to the run loop.
-// 6. When runServeAsyncRequestsTask() notices there are no more loads in
+// 6. When RunServeAsyncRequestsTask() notices there are no more loads in
// progress, it exits the run loop.
// 7. At this point, all parsing, resource loads, and layout should be finished.
@@ -97,48 +101,58 @@ std::unique_ptr<T> CreateDefaultClientIfNeeded(T*& client) {
return owned_client;
}
+WebNavigationTimings BuildDummyWebNavigationTimings() {
+ WebNavigationTimings web_navigation_timings;
+ web_navigation_timings.navigation_start = base::TimeTicks::Now();
+ web_navigation_timings.fetch_start = base::TimeTicks::Now();
+ return web_navigation_timings;
+}
+
} // namespace
void LoadFrame(WebLocalFrame* frame, const std::string& url) {
- WebURLRequest url_request(URLTestHelpers::ToKURL(url));
- if (url_request.Url().ProtocolIs("javascript")) {
- frame->LoadJavaScriptURL(url_request.Url());
+ WebURL web_url(URLTestHelpers::ToKURL(url));
+ if (web_url.ProtocolIs("javascript")) {
+ frame->LoadJavaScriptURL(web_url);
} else {
- frame->LoadRequest(url_request);
+ frame->CommitNavigation(
+ WebURLRequest(web_url), blink::WebFrameLoadType::kStandard,
+ blink::WebHistoryItem(), false, base::UnguessableToken::Create(),
+ nullptr, BuildDummyWebNavigationTimings());
}
- PumpPendingRequestsForFrameToLoad(frame);
+ PumpPendingRequestsForFrameToLoad();
}
void LoadHTMLString(WebLocalFrame* frame,
const std::string& html,
const WebURL& base_url) {
frame->LoadHTMLString(WebData(html.data(), html.size()), base_url);
- PumpPendingRequestsForFrameToLoad(frame);
+ PumpPendingRequestsForFrameToLoad();
}
void LoadHistoryItem(WebLocalFrame* frame,
const WebHistoryItem& item,
- WebHistoryLoadType load_type,
mojom::FetchCacheMode cache_mode) {
HistoryItem* history_item = item;
frame->CommitNavigation(
WrappedResourceRequest(history_item->GenerateResourceRequest(cache_mode)),
- WebFrameLoadType::kBackForward, item, kWebHistoryDifferentDocumentLoad,
- /*is_client_redirect=*/false, base::UnguessableToken::Create());
- PumpPendingRequestsForFrameToLoad(frame);
+ WebFrameLoadType::kBackForward, item,
+ /*is_client_redirect=*/false, base::UnguessableToken::Create(), nullptr,
+ BuildDummyWebNavigationTimings());
+ PumpPendingRequestsForFrameToLoad();
}
void ReloadFrame(WebLocalFrame* frame) {
- frame->Reload(WebFrameLoadType::kReload);
- PumpPendingRequestsForFrameToLoad(frame);
+ frame->StartReload(WebFrameLoadType::kReload);
+ PumpPendingRequestsForFrameToLoad();
}
void ReloadFrameBypassingCache(WebLocalFrame* frame) {
- frame->Reload(WebFrameLoadType::kReloadBypassingCache);
- PumpPendingRequestsForFrameToLoad(frame);
+ frame->StartReload(WebFrameLoadType::kReloadBypassingCache);
+ PumpPendingRequestsForFrameToLoad();
}
-void PumpPendingRequestsForFrameToLoad(WebFrame* frame) {
+void PumpPendingRequestsForFrameToLoad() {
Platform::Current()->CurrentThread()->GetTaskRunner()->PostTask(
FROM_HERE, WTF::Bind(&RunServeAsyncRequestsTask));
test::EnterRunLoop();
@@ -189,22 +203,22 @@ WebLocalFrameImpl* CreateProvisional(WebRemoteFrame& old_frame,
ParsedFeaturePolicy()));
client->Bind(frame, std::move(owned_client));
// Create a local root, if necessary.
- std::unique_ptr<TestWebWidgetClient> owned_widget_client;
+ std::unique_ptr<WebWidgetClient> owned_widget_client;
+ WebWidgetClient* widget_client = nullptr;
if (!frame->Parent()) {
// TODO(dcheng): The main frame widget currently has a special case.
// Eliminate this once WebView is no longer a WebWidget.
- owned_widget_client = std::make_unique<TestWebViewWidgetClient>(
- *static_cast<TestWebViewClient*>(frame->ViewImpl()->Client()));
+ widget_client = frame->ViewImpl()->Client()->WidgetClient();
} else if (frame->Parent()->IsWebRemoteFrame()) {
owned_widget_client = std::make_unique<TestWebWidgetClient>();
+ widget_client = owned_widget_client.get();
}
- if (owned_widget_client) {
- WebFrameWidget::Create(owned_widget_client.get(), frame);
- // Set an initial size for subframes.
+ if (widget_client) {
+ WebFrameWidget::Create(widget_client, frame);
if (frame->Parent())
frame->FrameWidget()->Resize(WebSize());
- client->BindWidgetClient(std::move(owned_widget_client));
}
+ client->BindWidgetClient(std::move(owned_widget_client));
return frame;
}
@@ -247,7 +261,7 @@ WebRemoteFrameImpl* CreateRemoteChild(
ParsedFeaturePolicy(), client, nullptr));
client->Bind(frame, std::move(owned_client));
if (!security_origin)
- security_origin = SecurityOrigin::CreateUnique();
+ security_origin = SecurityOrigin::CreateUniqueOpaque();
frame->GetFrame()->GetSecurityContext()->SetReplicatedOrigin(
std::move(security_origin));
return frame;
@@ -263,7 +277,7 @@ WebViewImpl* WebViewHelper::InitializeWithOpener(
WebFrame* opener,
TestWebFrameClient* web_frame_client,
TestWebViewClient* web_view_client,
- TestWebWidgetClient* web_widget_client,
+ TestWebWidgetClient* test_web_widget_client,
void (*update_settings_func)(WebSettings*)) {
Reset();
@@ -278,17 +292,13 @@ WebViewImpl* WebViewHelper::InitializeWithOpener(
// TODO(dcheng): The main frame widget currently has a special case.
// Eliminate this once WebView is no longer a WebWidget.
- std::unique_ptr<TestWebWidgetClient> owned_web_widget_client;
- if (!web_widget_client) {
- owned_web_widget_client =
- std::make_unique<TestWebViewWidgetClient>(*test_web_view_client_);
- web_widget_client = owned_web_widget_client.get();
- }
+ WebWidgetClient* web_widget_client = test_web_widget_client;
+ if (!web_widget_client)
+ web_widget_client = test_web_view_client_->WidgetClient();
blink::WebFrameWidget::Create(web_widget_client, frame);
// Set an initial size for subframes.
if (frame->Parent())
frame->FrameWidget()->Resize(WebSize());
- web_frame_client->BindWidgetClient(std::move(owned_web_widget_client));
return web_view_;
}
@@ -331,7 +341,7 @@ WebViewImpl* WebViewHelper::InitializeRemote(
web_remote_frame_client->Bind(frame,
std::move(owned_web_remote_frame_client));
if (!security_origin)
- security_origin = SecurityOrigin::CreateUnique();
+ security_origin = SecurityOrigin::CreateUniqueOpaque();
frame->GetFrame()->GetSecurityContext()->SetReplicatedOrigin(
std::move(security_origin));
return web_view_;
@@ -360,11 +370,6 @@ WebRemoteFrameImpl* WebViewHelper::RemoteMainFrame() const {
return ToWebRemoteFrameImpl(web_view_->MainFrame());
}
-void WebViewHelper::SetViewportSize(const WebSize& viewport_size) {
- test_web_view_client_->GetLayerTreeViewForTesting()->SetViewportSize(
- viewport_size);
-}
-
void WebViewHelper::Resize(WebSize size) {
test_web_view_client_->ClearAnimationScheduled();
GetWebView()->Resize(size);
@@ -375,8 +380,9 @@ void WebViewHelper::Resize(WebSize size) {
void WebViewHelper::InitializeWebView(TestWebViewClient* web_view_client,
class WebView* opener) {
owned_test_web_view_client_ = CreateDefaultClientIfNeeded(web_view_client);
- web_view_ = static_cast<WebViewImpl*>(WebView::Create(
- web_view_client, mojom::PageVisibilityState::kVisible, opener));
+ web_view_ = static_cast<WebViewImpl*>(
+ WebView::Create(web_view_client, web_view_client,
+ mojom::PageVisibilityState::kVisible, opener));
web_view_->GetSettings()->SetJavaScriptEnabled(true);
web_view_->GetSettings()->SetPluginsEnabled(true);
// Enable (mocked) network loads of image URLs, as this simplifies
@@ -406,7 +412,7 @@ void TestWebFrameClient::Bind(WebLocalFrame* frame,
}
void TestWebFrameClient::BindWidgetClient(
- std::unique_ptr<TestWebWidgetClient> client) {
+ std::unique_ptr<WebWidgetClient> client) {
DCHECK(!owned_widget_client_);
owned_widget_client_ = std::move(client);
}
@@ -444,12 +450,6 @@ void TestWebFrameClient::DidStopLoading() {
void TestWebFrameClient::DidCreateDocumentLoader(
WebDocumentLoader* document_loader) {
- base::TimeTicks redirect_start;
- base::TimeTicks redirect_end;
- base::TimeTicks fetch_start = base::TimeTicks::Now();
- bool has_redirect = false;
- document_loader->UpdateNavigation(redirect_start, redirect_end, fetch_start,
- has_redirect);
}
TestWebRemoteFrameClient::TestWebRemoteFrameClient() = default;
@@ -468,32 +468,42 @@ void TestWebRemoteFrameClient::FrameDetached(DetachType type) {
self_owned_.reset();
}
-WebLayerTreeViewImplForTesting*
-TestWebViewClient::GetLayerTreeViewForTesting() {
+content::LayerTreeView* LayerTreeViewFactory::Initialize() {
+ return Initialize(/*delegate=*/nullptr);
+}
+
+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;
+ // For web contents, layer transforms should scale up the contents of layers
+ // to keep content always crisp when possible.
+ settings.layer_transforms_should_scale_layer_contents = true;
+ // BlinkGenPropertyTrees should imply layer lists in the compositor. Some
+ // code across the boundaries makes assumptions based on this so ensure tests
+ // run using this configuration as well.
+ if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled())
+ settings.use_layer_lists = true;
+
+ layer_tree_view_ = std::make_unique<content::LayerTreeView>(
+ specified_delegate ? specified_delegate : &delegate_,
+ Platform::Current()->CurrentThread()->GetTaskRunner(),
+ /*compositor_thread=*/nullptr, &test_task_graph_runner_,
+ &fake_renderer_scheduler_);
+ layer_tree_view_->Initialize(settings,
+ std::make_unique<cc::TestUkmRecorderFactory>());
return layer_tree_view_.get();
}
-WebLayerTreeView* TestWebViewClient::InitializeLayerTreeView() {
- layer_tree_view_ = std::make_unique<WebLayerTreeViewImplForTesting>();
- return layer_tree_view_.get();
-}
-
-WebLayerTreeView* TestWebViewWidgetClient::InitializeLayerTreeView() {
- return test_web_view_client_.InitializeLayerTreeView();
-}
-
WebLayerTreeView* TestWebWidgetClient::InitializeLayerTreeView() {
- layer_tree_view_ = std::make_unique<WebLayerTreeViewImplForTesting>();
- return layer_tree_view_.get();
-}
-
-void TestWebViewWidgetClient::ScheduleAnimation() {
- test_web_view_client_.ScheduleAnimation();
+ return layer_tree_view_factory_.Initialize();
}
-void TestWebViewWidgetClient::DidMeaningfulLayout(
- WebMeaningfulLayout layout_type) {
- test_web_view_client_.DidMeaningfulLayout(layout_type);
+WebLayerTreeView* TestWebViewClient::InitializeLayerTreeView() {
+ layer_tree_view_ = layer_tree_view_factory_.Initialize();
+ return layer_tree_view_;
}
} // namespace FrameTestHelpers
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 58bc5d1767c..644cec99b7b 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
@@ -37,24 +37,27 @@
#include <string>
#include "base/macros.h"
+#include "cc/test/test_task_graph_runner.h"
+#include "content/renderer/gpu/layer_tree_view.h"
+#include "content/test/stub_layer_tree_view_delegate.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/scheduler/test/fake_renderer_scheduler.h"
#include "third_party/blink/public/platform/web_mouse_event.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url_request.h"
-#include "third_party/blink/public/web/web_frame_client.h"
#include "third_party/blink/public/web/web_frame_owner_properties.h"
#include "third_party/blink/public/web/web_history_item.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_remote_frame_client.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/public/web/web_view_client.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/settings.h"
+#include "third_party/blink/renderer/core/testing/use_mock_scrollbar_settings.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scroll/scrollbar_theme.h"
-#include "third_party/blink/renderer/platform/testing/use_mock_scrollbar_settings.h"
-#include "third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.h"
#define EXPECT_FLOAT_POINT_EQ(expected, actual) \
do { \
@@ -101,7 +104,6 @@ void LoadHTMLString(WebLocalFrame*,
// Same as above, but for WebLocalFrame::RequestFromHistoryItem/Load.
void LoadHistoryItem(WebLocalFrame*,
const WebHistoryItem&,
- WebHistoryLoadType,
mojom::FetchCacheMode);
// Same as above, but for WebLocalFrame::Reload().
void ReloadFrame(WebLocalFrame*);
@@ -109,7 +111,7 @@ void ReloadFrameBypassingCache(WebLocalFrame*);
// Pumps pending resource requests while waiting for a frame to load. Consider
// using one of the above helper methods whenever possible.
-void PumpPendingRequestsForFrameToLoad(WebFrame*);
+void PumpPendingRequestsForFrameToLoad();
WebMouseEvent CreateMouseEvent(WebInputEvent::Type,
WebMouseEvent::Button,
@@ -160,51 +162,54 @@ WebRemoteFrameImpl* CreateRemoteChild(WebRemoteFrame& parent,
scoped_refptr<SecurityOrigin> = nullptr,
TestWebRemoteFrameClient* = nullptr);
-class TestWebWidgetClient : public WebWidgetClient {
+// A class that constructs and owns a LayerTreeView for blink
+// unit tests.
+class LayerTreeViewFactory {
public:
- ~TestWebWidgetClient() override = default;
-
- // WebWidgetClient:
- bool AllowsBrokenNullLayerTreeView() const override { return true; }
- WebLayerTreeView* InitializeLayerTreeView() override;
+ // Use this to make a LayerTreeView with a stub delegate.
+ content::LayerTreeView* Initialize();
+ // Use this to specify a delegate instead of using a stub.
+ content::LayerTreeView* Initialize(content::LayerTreeViewDelegate*);
private:
- std::unique_ptr<WebLayerTreeView> layer_tree_view_;
+ content::StubLayerTreeViewDelegate delegate_;
+ cc::TestTaskGraphRunner test_task_graph_runner_;
+ blink::scheduler::FakeRendererScheduler fake_renderer_scheduler_;
+ std::unique_ptr<content::LayerTreeView> layer_tree_view_;
};
-class TestWebViewWidgetClient : public TestWebWidgetClient {
+class TestWebWidgetClient : public WebWidgetClient {
public:
- explicit TestWebViewWidgetClient(TestWebViewClient& test_web_view_client)
- : test_web_view_client_(test_web_view_client) {}
- ~TestWebViewWidgetClient() override = default;
+ ~TestWebWidgetClient() override = default;
- // TestWebViewWidgetClient:
+ // WebWidgetClient:
WebLayerTreeView* InitializeLayerTreeView() override;
- void ScheduleAnimation() override;
- void DidMeaningfulLayout(WebMeaningfulLayout) override;
private:
- TestWebViewClient& test_web_view_client_;
+ LayerTreeViewFactory layer_tree_view_factory_;
};
-class TestWebViewClient : public WebViewClient {
+class TestWebViewClient : public WebViewClient, public WebWidgetClient {
public:
~TestWebViewClient() override = default;
- WebLayerTreeViewImplForTesting* GetLayerTreeViewForTesting();
+ content::LayerTreeView* layer_tree_view() { return layer_tree_view_; }
- // WebViewClient:
+ // WebWidgetClient:
WebLayerTreeView* InitializeLayerTreeView() override;
void ScheduleAnimation() override { animation_scheduled_ = true; }
- bool AnimationScheduled() { return animation_scheduled_; }
- void ClearAnimationScheduled() { animation_scheduled_ = false; }
+
+ // WebViewClient:
bool CanHandleGestureEvent() override { return true; }
bool CanUpdateLayout() override { return true; }
+ WebWidgetClient* WidgetClient() override { return this; }
- private:
- friend class TestWebViewWidgetClient;
+ bool AnimationScheduled() { return animation_scheduled_; }
+ void ClearAnimationScheduled() { animation_scheduled_ = false; }
- std::unique_ptr<WebLayerTreeViewImplForTesting> layer_tree_view_;
+ private:
+ content::LayerTreeView* layer_tree_view_ = nullptr;
+ LayerTreeViewFactory layer_tree_view_factory_;
bool animation_scheduled_ = false;
};
@@ -262,12 +267,13 @@ class WebViewHelper {
void Reset();
WebViewImpl* GetWebView() const { return web_view_; }
+ content::LayerTreeView* GetLayerTreeView() const {
+ return test_web_view_client_->layer_tree_view();
+ }
WebLocalFrameImpl* LocalMainFrame() const;
WebRemoteFrameImpl* RemoteMainFrame() const;
- void SetViewportSize(const WebSize&);
-
private:
void InitializeWebView(TestWebViewClient*, class WebView* opener);
@@ -280,10 +286,10 @@ class WebViewHelper {
DISALLOW_COPY_AND_ASSIGN(WebViewHelper);
};
-// Minimal implementation of WebFrameClient needed for unit tests that load
+// Minimal implementation of WebLocalFrameClient needed for unit tests that load
// frames. Tests that load frames and need further specialization of
-// WebFrameClient behavior should subclass this.
-class TestWebFrameClient : public WebFrameClient {
+// WebLocalFrameClient behavior should subclass this.
+class TestWebFrameClient : public WebLocalFrameClient {
public:
TestWebFrameClient();
~TestWebFrameClient() override = default;
@@ -296,9 +302,9 @@ class TestWebFrameClient : public WebFrameClient {
void Bind(WebLocalFrame*,
std::unique_ptr<TestWebFrameClient> self_owned = nullptr);
// Note: only needed for local roots.
- void BindWidgetClient(std::unique_ptr<TestWebWidgetClient>);
+ void BindWidgetClient(std::unique_ptr<WebWidgetClient>);
- // WebFrameClient:
+ // WebLocalFrameClient:
void FrameDetached(DetachType) override;
WebLocalFrame* CreateChildFrame(WebLocalFrame* parent,
WebTreeScopeType,
@@ -334,12 +340,12 @@ class TestWebFrameClient : public WebFrameClient {
// Bind().
WebLocalFrame* frame_ = nullptr;
- std::unique_ptr<TestWebWidgetClient> owned_widget_client_;
+ std::unique_ptr<WebWidgetClient> owned_widget_client_;
};
// Minimal implementation of WebRemoteFrameClient needed for unit tests that
// load remote frames. Tests that load frames and need further specialization
-// of WebFrameClient behavior should subclass this.
+// of WebLocalFrameClient behavior should subclass this.
class TestWebRemoteFrameClient : public WebRemoteFrameClient {
public:
TestWebRemoteFrameClient();
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_view.h b/chromium/third_party/blink/renderer/core/frame/frame_view.h
index d03702f5264..429a2e036c9 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_view.h
+++ b/chromium/third_party/blink/renderer/core/frame/frame_view.h
@@ -5,17 +5,16 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_VIEW_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FRAME_VIEW_H_
-#include "third_party/blink/renderer/core/dom/document_lifecycle.h"
#include "third_party/blink/renderer/core/frame/embedded_content_view.h"
-#include "third_party/blink/renderer/core/frame/intrinsic_sizing_info.h"
namespace blink {
+struct IntrinsicSizingInfo;
+
class CORE_EXPORT FrameView : public EmbeddedContentView {
public:
~FrameView() override = default;
- virtual void UpdateViewportIntersectionsForSubtree(
- DocumentLifecycle::LifecycleState) = 0;
+ virtual void UpdateViewportIntersectionsForSubtree() = 0;
virtual bool GetIntrinsicSizingInfo(IntrinsicSizingInfo&) const = 0;
virtual bool HasIntrinsicSizingInfo() const = 0;
diff --git a/chromium/third_party/blink/renderer/core/frame/frame_view_auto_size_info.cc b/chromium/third_party/blink/renderer/core/frame/frame_view_auto_size_info.cc
index a4a779479e1..cac4c748fcf 100644
--- a/chromium/third_party/blink/renderer/core/frame/frame_view_auto_size_info.cc
+++ b/chromium/third_party/blink/renderer/core/frame/frame_view_auto_size_info.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.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/paint_layer_scrollable_area.h"
namespace blink {
@@ -55,7 +56,7 @@ void FrameViewAutoSizeInfo::AutoSizeIfNeeded() {
frame_view_->Resize(frame_view_->Width(), min_auto_size_.Height());
IntSize size = frame_view_->Size();
- ScrollableArea* layout_viewport = frame_view_->LayoutViewportScrollableArea();
+ PaintLayerScrollableArea* layout_viewport = frame_view_->LayoutViewport();
// Do the resizing twice. The first time is basically a rough calculation
// using the preferred width which may result in a height change during the
@@ -85,29 +86,14 @@ void FrameViewAutoSizeInfo::AutoSizeIfNeeded() {
// Since the dimensions are only for the view rectangle, once a
// dimension exceeds the maximum, there is no need to increase it further.
if (new_size.Width() > max_auto_size_.Width()) {
- Scrollbar* local_horizontal_scrollbar =
- layout_viewport->HorizontalScrollbar();
- if (!local_horizontal_scrollbar) {
- local_horizontal_scrollbar =
- layout_viewport->CreateScrollbar(kHorizontalScrollbar);
- }
- if (!local_horizontal_scrollbar->IsOverlayScrollbar()) {
- new_size.SetHeight(new_size.Height() +
- local_horizontal_scrollbar->Height());
- }
-
+ new_size.Expand(0, layout_viewport->HypotheticalScrollbarThickness(
+ kHorizontalScrollbar));
// Don't bother checking for a vertical scrollbar because the width is at
// already greater the maximum.
} else if (new_size.Height() > max_auto_size_.Height()) {
- Scrollbar* local_vertical_scrollbar =
- layout_viewport->VerticalScrollbar();
- if (!local_vertical_scrollbar) {
- local_vertical_scrollbar =
- layout_viewport->CreateScrollbar(kVerticalScrollbar);
- }
- if (!local_vertical_scrollbar->IsOverlayScrollbar())
- new_size.SetWidth(new_size.Width() + local_vertical_scrollbar->Width());
-
+ new_size.Expand(
+ layout_viewport->HypotheticalScrollbarThickness(kVerticalScrollbar),
+ 0);
// Don't bother checking for a horizontal scrollbar because the height is
// already greater the maximum.
}
@@ -145,8 +131,8 @@ void FrameViewAutoSizeInfo::AutoSizeIfNeeded() {
// causing them to be needed. For example, a vertical scrollbar may cause
// text to wrap and thus increase the height (which is the only reason the
// scollbar is needed).
- layout_viewport->SetAutosizeScrollbarModes(vertical_scrollbar_mode,
- horizontal_scrollbar_mode);
+ frame_view_->GetLayoutView()->SetAutosizeScrollbarModes(
+ horizontal_scrollbar_mode, vertical_scrollbar_mode);
}
did_run_autosize_ = true;
}
diff --git a/chromium/third_party/blink/renderer/core/frame/fullscreen_controller.cc b/chromium/third_party/blink/renderer/core/frame/fullscreen_controller.cc
index b1546cfecd8..cbd15aa4a83 100644
--- a/chromium/third_party/blink/renderer/core/frame/fullscreen_controller.cc
+++ b/chromium/third_party/blink/renderer/core/frame/fullscreen_controller.cc
@@ -32,8 +32,8 @@
#include "base/memory/ptr_util.h"
#include "third_party/blink/public/platform/web_layer_tree_view.h"
-#include "third_party/blink/public/web/web_frame_client.h"
#include "third_party/blink/public/web/web_fullscreen_options.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -43,14 +43,13 @@
#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
#include "third_party/blink/renderer/core/fullscreen/fullscreen_options.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
-#include "third_party/blink/renderer/core/layout/layout_full_screen.h"
#include "third_party/blink/renderer/core/page/page.h"
namespace blink {
namespace {
-WebFrameClient& GetWebFrameClient(LocalFrame& frame) {
+WebLocalFrameClient& GetWebFrameClient(LocalFrame& frame) {
WebLocalFrameImpl* web_frame = WebLocalFrameImpl::FromFrame(frame);
DCHECK(web_frame);
DCHECK(web_frame->Client());
@@ -87,10 +86,8 @@ void FullscreenController::DidEnterFullscreen() {
frame = frame->Tree().TraverseNext()) {
if (!frame->IsLocalFrame())
continue;
- if (Document* document = ToLocalFrame(frame)->GetDocument()) {
- if (Fullscreen* fullscreen = Fullscreen::FromIfExists(*document))
- fullscreen->DidEnterFullscreen();
- }
+ if (Document* document = ToLocalFrame(frame)->GetDocument())
+ Fullscreen::DidEnterFullscreen(*document);
}
// TODO(foolip): If the top level browsing context (main frame) ends up with
@@ -123,10 +120,8 @@ void FullscreenController::DidExitFullscreen() {
}
DCHECK(frame->IsLocalFrame() && ToLocalFrame(frame)->IsLocalRoot());
- if (Document* document = ToLocalFrame(frame)->GetDocument()) {
- if (Fullscreen* fullscreen = Fullscreen::FromIfExists(*document))
- fullscreen->DidExitFullscreen();
- }
+ if (Document* document = ToLocalFrame(frame)->GetDocument())
+ Fullscreen::DidExitFullscreen(*document);
// Skip over all descendant frames.
while (next_frame && next_frame->Tree().IsDescendantOf(frame))
@@ -224,6 +219,12 @@ void FullscreenController::FullscreenElementChanged(Element* old_element,
if (auto* video_element = ToHTMLVideoElementOrNull(*old_element))
video_element->DidExitFullscreen();
}
+
+ // Tell the browser the fullscreen state has changed.
+ if (Element* owner = new_element ? new_element : old_element) {
+ if (LocalFrame* frame = owner->GetDocument().GetFrame())
+ GetWebFrameClient(*frame).FullscreenStateChanged(!!new_element);
+ }
}
void FullscreenController::RestoreBackgroundColorOverride() {
@@ -247,20 +248,6 @@ void FullscreenController::UpdateSize() {
return;
UpdatePageScaleConstraints(false);
-
- // Traverse all local frames and notify the LayoutFullScreen object, if any.
- for (Frame* frame = web_view_base_->GetPage()->MainFrame(); frame;
- frame = frame->Tree().TraverseNext()) {
- if (!frame->IsLocalFrame())
- continue;
- if (Document* document = ToLocalFrame(frame)->GetDocument()) {
- if (Fullscreen* fullscreen = Fullscreen::FromIfExists(*document)) {
- if (LayoutFullScreen* layout_object =
- fullscreen->FullScreenLayoutObject())
- layout_object->UpdateStyle();
- }
- }
- }
}
void FullscreenController::DidUpdateLayout() {
diff --git a/chromium/third_party/blink/renderer/core/frame/history.cc b/chromium/third_party/blink/renderer/core/frame/history.cc
index 82ba2201ab8..1b4b8aef02c 100644
--- a/chromium/third_party/blink/renderer/core/frame/history.cc
+++ b/chromium/third_party/blink/renderer/core/frame/history.cc
@@ -25,7 +25,6 @@
#include "third_party/blink/renderer/core/frame/history.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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"
@@ -38,6 +37,7 @@
#include "third_party/blink/renderer/core/loader/history_item.h"
#include "third_party/blink/renderer/core/loader/navigation_scheduler.h"
#include "third_party/blink/renderer/core/page/page.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/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -134,11 +134,21 @@ String History::scrollRestoration(ExceptionState& exception_state) {
}
HistoryScrollRestorationType History::ScrollRestorationInternal() const {
- HistoryItem* history_item =
- GetFrame() ? GetFrame()->Loader().GetDocumentLoader()->GetHistoryItem()
- : nullptr;
- return history_item ? history_item->ScrollRestorationType()
- : kScrollRestorationAuto;
+ constexpr HistoryScrollRestorationType default_type = kScrollRestorationAuto;
+
+ LocalFrame* frame = GetFrame();
+ if (!frame)
+ return default_type;
+
+ DocumentLoader* document_loader = frame->Loader().GetDocumentLoader();
+ if (!document_loader)
+ return default_type;
+
+ HistoryItem* history_item = document_loader->GetHistoryItem();
+ if (!history_item)
+ return default_type;
+
+ return history_item->ScrollRestorationType();
}
// TODO(crbug.com/394296): This is not the long-term fix to IPC flooding that we
@@ -212,7 +222,7 @@ void History::go(ScriptState* script_state,
// Otherwise, navigation happens on the root frame.
// This behavior is designed in the following spec.
// https://html.spec.whatwg.org/multipage/browsers.html#dom-history-go
- GetFrame()->Reload(kFrameLoadTypeReload,
+ GetFrame()->Reload(WebFrameLoadType::kReload,
ClientRedirectPolicy::kClientRedirect);
}
}
@@ -222,7 +232,7 @@ void History::pushState(scoped_refptr<SerializedScriptValue> data,
const String& url,
ExceptionState& exception_state) {
StateObjectAdded(std::move(data), title, url, ScrollRestorationInternal(),
- kFrameLoadTypeStandard, exception_state);
+ WebFrameLoadType::kStandard, exception_state);
}
KURL History::UrlForState(const String& url_string) {
@@ -248,7 +258,7 @@ bool History::CanChangeToUrl(const KURL& url,
// We allow sandboxed documents, `data:`/`file:` URLs, etc. to use
// 'pushState'/'replaceState' to modify the URL fragment: see
// https://crbug.com/528681 for the compatibility concerns.
- if (document_origin->IsUnique() || document_origin->IsLocal())
+ if (document_origin->IsOpaque() || document_origin->IsLocal())
return EqualIgnoringQueryAndFragment(url, document_url);
if (!EqualIgnoringPathQueryAndFragment(url, document_url))
@@ -256,7 +266,7 @@ bool History::CanChangeToUrl(const KURL& url,
scoped_refptr<const SecurityOrigin> requested_origin =
SecurityOrigin::Create(url);
- if (requested_origin->IsUnique() ||
+ if (requested_origin->IsOpaque() ||
!requested_origin->IsSameSchemeHostPort(document_origin)) {
return false;
}
@@ -268,7 +278,7 @@ void History::StateObjectAdded(scoped_refptr<SerializedScriptValue> data,
const String& /* title */,
const String& url_string,
HistoryScrollRestorationType restoration_type,
- FrameLoadType type,
+ WebFrameLoadType type,
ExceptionState& exception_state) {
if (!GetFrame() || !GetFrame()->GetPage() ||
!GetFrame()->Loader().GetDocumentLoader()) {
@@ -295,7 +305,7 @@ void History::StateObjectAdded(scoped_refptr<SerializedScriptValue> data,
if (ShouldThrottleStateObjectChanges()) {
// TODO(769592): Get an API spec change so that we can throw an exception:
//
- // exception_state.ThrowDOMException(kQuotaExceededError,
+ // exception_state.ThrowDOMException(DOMExceptionCode::kQuotaExceededError,
// "Throttling history state changes to "
// "prevent the browser from hanging.");
//
diff --git a/chromium/third_party/blink/renderer/core/frame/history.h b/chromium/third_party/blink/renderer/core/frame/history.h
index 9cc6e862aac..95e5a6382da 100644
--- a/chromium/third_party/blink/renderer/core/frame/history.h
+++ b/chromium/third_party/blink/renderer/core/frame/history.h
@@ -27,6 +27,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_HISTORY_H_
#include "base/gtest_prod_util.h"
+#include "third_party/blink/public/web/web_frame_load_type.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/loader/frame_loader_types.h"
@@ -69,7 +70,7 @@ class CORE_EXPORT History final : public ScriptWrappable,
const String& url,
ExceptionState& exception_state) {
StateObjectAdded(std::move(data), title, url, ScrollRestorationInternal(),
- kFrameLoadTypeReplaceCurrentItem, exception_state);
+ WebFrameLoadType::kReplaceCurrentItem, exception_state);
}
void setScrollRestoration(const String& value, ExceptionState&);
@@ -97,7 +98,7 @@ class CORE_EXPORT History final : public ScriptWrappable,
const String& title,
const String& url,
HistoryScrollRestorationType,
- FrameLoadType,
+ WebFrameLoadType,
ExceptionState&);
SerializedScriptValue* StateInternal() const;
HistoryScrollRestorationType ScrollRestorationInternal() const;
diff --git a/chromium/third_party/blink/renderer/core/frame/history_test.cc b/chromium/third_party/blink/renderer/core/frame/history_test.cc
index d56b90db01b..0dfee5184e9 100644
--- a/chromium/third_party/blink/renderer/core/frame/history_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/history_test.cc
@@ -109,7 +109,7 @@ TEST_F(HistoryTest, CanChangeToURLInUniqueOrigin) {
KURL url(test.url);
KURL document_url(test.document_url);
scoped_refptr<const SecurityOrigin> document_origin =
- SecurityOrigin::CreateUnique();
+ SecurityOrigin::CreateUniqueOpaque();
EXPECT_EQ(test.expected, History::CanChangeToUrl(url, document_origin.get(),
document_url));
}
diff --git a/chromium/third_party/blink/renderer/core/frame/intervention.cc b/chromium/third_party/blink/renderer/core/frame/intervention.cc
index f0d9b1a2b91..f65037b839a 100644
--- a/chromium/third_party/blink/renderer/core/frame/intervention.cc
+++ b/chromium/third_party/blink/renderer/core/frame/intervention.cc
@@ -8,7 +8,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/reporting.mojom-blink.h"
#include "third_party/blink/renderer/core/frame/frame_console.h"
-#include "third_party/blink/renderer/core/frame/intervention_report.h"
+#include "third_party/blink/renderer/core/frame/intervention_report_body.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"
@@ -19,37 +19,40 @@ namespace blink {
// static
void Intervention::GenerateReport(const LocalFrame* frame,
+ const String& id,
const String& message) {
if (!frame)
return;
// Send the message to the console.
- frame->Console().AddMessage(ConsoleMessage::Create(
+ Document* document = frame->GetDocument();
+ document->AddConsoleMessage(ConsoleMessage::Create(
kInterventionMessageSource, kErrorMessageLevel, message));
if (!frame->Client())
return;
- Document* document = frame->GetDocument();
-
// Construct the intervention report.
- InterventionReport* body =
- new InterventionReport(message, SourceLocation::Capture());
+ InterventionReportBody* body =
+ new InterventionReportBody(id, message, SourceLocation::Capture());
Report* report =
new Report("intervention", document->Url().GetString(), body);
// Send the intervention report to any ReportingObservers.
- ReportingContext* reporting_context = ReportingContext::From(document);
- if (reporting_context->ObserverExists())
- reporting_context->QueueReport(report);
+ ReportingContext::From(document)->QueueReport(report);
// Send the intervention report to the Reporting API.
mojom::blink::ReportingServiceProxyPtr service;
Platform* platform = Platform::Current();
platform->GetConnector()->BindInterface(platform->GetBrowserServiceName(),
&service);
+ bool is_null;
+ int line_number = body->lineNumber(is_null);
+ line_number = is_null ? 0 : line_number;
+ int column_number = body->columnNumber(is_null);
+ column_number = is_null ? 0 : column_number;
service->QueueInterventionReport(document->Url(), message, body->sourceFile(),
- body->lineNumber(), body->columnNumber());
+ line_number, column_number);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/intervention.h b/chromium/third_party/blink/renderer/core/frame/intervention.h
index 1f7b1d56608..b9016f124cf 100644
--- a/chromium/third_party/blink/renderer/core/frame/intervention.h
+++ b/chromium/third_party/blink/renderer/core/frame/intervention.h
@@ -23,7 +23,9 @@ class CORE_EXPORT Intervention {
// Generates a intervention report, to be routed to the Reporting API and any
// ReportingObservers. Also sends the intervention message to the console.
- static void GenerateReport(const LocalFrame*, const String& message);
+ static void GenerateReport(const LocalFrame*,
+ const String& id,
+ const String& message);
DISALLOW_COPY_AND_ASSIGN(Intervention);
};
diff --git a/chromium/third_party/blink/renderer/core/frame/intervention_report.h b/chromium/third_party/blink/renderer/core/frame/intervention_report.h
deleted file mode 100644
index 4c5da128fcc..00000000000
--- a/chromium/third_party/blink/renderer/core/frame/intervention_report.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_INTERVENTION_REPORT_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_INTERVENTION_REPORT_H_
-
-#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
-#include "third_party/blink/renderer/core/frame/message_report.h"
-
-namespace blink {
-
-class CORE_EXPORT InterventionReport : public MessageReport {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- InterventionReport(const String& message,
- std::unique_ptr<SourceLocation> location)
- : MessageReport(message, std::move(location)) {}
-
- ~InterventionReport() override = default;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_INTERVENTION_REPORT_H_
diff --git a/chromium/third_party/blink/renderer/core/frame/intervention_report.idl b/chromium/third_party/blink/renderer/core/frame/intervention_report.idl
deleted file mode 100644
index 158541e20cb..00000000000
--- a/chromium/third_party/blink/renderer/core/frame/intervention_report.idl
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://github.com/WICG/reporting/blob/master/EXPLAINER.md#reportingobserver---observing-reports-from-javascript
-
-[
- NoInterfaceObject,
- RuntimeEnabled=ReportingObserver
-] interface InterventionReport : ReportBody {
- // TODO(paulmeyer): Add additional data, such as id.
- readonly attribute DOMString message;
- readonly attribute DOMString sourceFile;
- readonly attribute long lineNumber;
- readonly attribute long columnNumber;
-};
diff --git a/chromium/third_party/blink/renderer/core/frame/intervention_report_body.h b/chromium/third_party/blink/renderer/core/frame/intervention_report_body.h
new file mode 100644
index 00000000000..058f948b588
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/intervention_report_body.h
@@ -0,0 +1,32 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_INTERVENTION_REPORT_BODY_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_INTERVENTION_REPORT_BODY_H_
+
+#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
+#include "third_party/blink/renderer/core/frame/message_report_body.h"
+
+namespace blink {
+
+class CORE_EXPORT InterventionReportBody : public MessageReportBody {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ InterventionReportBody(const String& id,
+ const String& message,
+ std::unique_ptr<SourceLocation> location)
+ : MessageReportBody(message, std::move(location)), id_(id) {}
+
+ ~InterventionReportBody() override = default;
+
+ String id() const { return id_; }
+
+ private:
+ const String id_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_INTERVENTION_REPORT_BODY_H_
diff --git a/chromium/third_party/blink/renderer/core/frame/intervention_report_body.idl b/chromium/third_party/blink/renderer/core/frame/intervention_report_body.idl
new file mode 100644
index 00000000000..303945bddb4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/intervention_report_body.idl
@@ -0,0 +1,16 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://wicg.github.io/reporting/#intervention-report
+
+[
+ NoInterfaceObject,
+ RuntimeEnabled=InterventionReporting
+] interface InterventionReportBody : ReportBody {
+ readonly attribute DOMString id;
+ readonly attribute DOMString message;
+ readonly attribute DOMString? sourceFile;
+ readonly attribute unsigned long? lineNumber;
+ readonly attribute unsigned long? columnNumber;
+};
diff --git a/chromium/third_party/blink/renderer/core/frame/intrinsic_sizing_info.h b/chromium/third_party/blink/renderer/core/frame/intrinsic_sizing_info.h
deleted file mode 100644
index d884ddb02fb..00000000000
--- a/chromium/third_party/blink/renderer/core/frame/intrinsic_sizing_info.h
+++ /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.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_INTRINSIC_SIZING_INFO_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_INTRINSIC_SIZING_INFO_H_
-
-#include "third_party/blink/renderer/platform/geometry/float_size.h"
-
-namespace blink {
-
-struct IntrinsicSizingInfo {
- IntrinsicSizingInfo() : has_width(true), has_height(true) {}
-
- FloatSize size;
- FloatSize aspect_ratio;
- bool has_width;
- bool has_height;
-
- void Transpose() {
- size = size.TransposedSize();
- aspect_ratio = aspect_ratio.TransposedSize();
- std::swap(has_width, has_height);
- }
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_INTRINSIC_SIZING_INFO_H_
diff --git a/chromium/third_party/blink/renderer/core/frame/link_highlights.cc b/chromium/third_party/blink/renderer/core/frame/link_highlights.cc
new file mode 100644
index 00000000000..34f1ffce410
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/link_highlights.cc
@@ -0,0 +1,108 @@
+// 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/frame/link_highlights.h"
+
+#include <memory>
+
+#include "cc/layers/picture_layer.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_layer_tree_view.h"
+#include "third_party/blink/renderer/core/dom/node.h"
+#include "third_party/blink/renderer/core/layout/layout_object.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/paint/link_highlight_impl.h"
+#include "third_party/blink/renderer/platform/animation/compositor_animation_host.h"
+#include "third_party/blink/renderer/platform/animation/compositor_animation_timeline.h"
+
+namespace blink {
+
+LinkHighlights::LinkHighlights(Page& owner) : page_(&owner) {}
+
+LinkHighlights::~LinkHighlights() {
+ RemoveAllHighlights();
+}
+
+void LinkHighlights::Trace(blink::Visitor* visitor) {
+ visitor->Trace(page_);
+}
+
+void LinkHighlights::RemoveAllHighlights() {
+ if (timeline_) {
+ for (auto& highlight : link_highlights_)
+ timeline_->AnimationDestroyed(*highlight);
+ }
+ link_highlights_.clear();
+}
+
+void LinkHighlights::ResetForPageNavigation() {
+ RemoveAllHighlights();
+}
+
+void LinkHighlights::SetTapHighlights(
+ HeapVector<Member<Node>>& highlight_nodes) {
+ // Always clear any existing highlight when this is invoked, even if we
+ // don't get a new target to highlight.
+ RemoveAllHighlights();
+
+ for (size_t i = 0; i < highlight_nodes.size(); ++i) {
+ Node* node = highlight_nodes[i];
+
+ if (!node || !node->GetLayoutObject())
+ continue;
+
+ Color highlight_color =
+ node->GetLayoutObject()->Style()->TapHighlightColor();
+ // Safari documentation for -webkit-tap-highlight-color says if the
+ // specified color has 0 alpha, then tap highlighting is disabled.
+ // http://developer.apple.com/library/safari/#documentation/appleapplications/reference/safaricssref/articles/standardcssproperties.html
+ if (!highlight_color.Alpha())
+ continue;
+
+ link_highlights_.push_back(LinkHighlightImpl::Create(node));
+ if (timeline_)
+ timeline_->AnimationAttached(*link_highlights_.back());
+ }
+}
+
+void LinkHighlights::UpdateGeometry() {
+ for (auto& highlight : link_highlights_)
+ highlight->UpdateGeometry();
+}
+
+LocalFrame* LinkHighlights::MainFrame() const {
+ return GetPage().MainFrame() && GetPage().MainFrame()->IsLocalFrame()
+ ? GetPage().DeprecatedLocalMainFrame()
+ : nullptr;
+}
+
+void LinkHighlights::StartHighlightAnimationIfNeeded() {
+ for (auto& highlight : link_highlights_)
+ highlight->StartHighlightAnimationIfNeeded();
+
+ if (auto* local_frame = MainFrame())
+ GetPage().GetChromeClient().ScheduleAnimation(local_frame->View());
+}
+
+void LinkHighlights::LayerTreeViewInitialized(
+ WebLayerTreeView& layer_tree_view) {
+ if (Platform::Current()->IsThreadedAnimationEnabled()) {
+ timeline_ = CompositorAnimationTimeline::Create();
+ animation_host_ = std::make_unique<CompositorAnimationHost>(
+ layer_tree_view.CompositorAnimationHost());
+ animation_host_->AddTimeline(*timeline_);
+ }
+}
+
+void LinkHighlights::WillCloseLayerTreeView(WebLayerTreeView& layer_tree_view) {
+ RemoveAllHighlights();
+ if (timeline_) {
+ animation_host_->RemoveTimeline(*timeline_);
+ timeline_.reset();
+ }
+ animation_host_ = nullptr;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/link_highlights.h b/chromium/third_party/blink/renderer/core/frame/link_highlights.h
new file mode 100644
index 00000000000..2eb1e31bc48
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/link_highlights.h
@@ -0,0 +1,66 @@
+// 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_FRAME_LINK_HIGHLIGHTS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LINK_HIGHLIGHTS_H_
+
+#include <memory>
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+class Page;
+class LinkHighlightImpl;
+class CompositorAnimationHost;
+class CompositorAnimationTimeline;
+class WebLayerTreeView;
+class LocalFrame;
+
+class CORE_EXPORT LinkHighlights final
+ : public GarbageCollectedFinalized<LinkHighlights> {
+ public:
+ static LinkHighlights* Create(Page& page) { return new LinkHighlights(page); }
+ virtual ~LinkHighlights();
+
+ virtual void Trace(blink::Visitor*);
+
+ void ResetForPageNavigation();
+
+ void SetTapHighlights(HeapVector<Member<Node>>&);
+
+ void UpdateGeometry();
+
+ void StartHighlightAnimationIfNeeded();
+
+ void LayerTreeViewInitialized(WebLayerTreeView&);
+ void WillCloseLayerTreeView(WebLayerTreeView&);
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, verifyWebViewImplIntegration);
+ FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, resetDuringNodeRemoval);
+ FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, resetLayerTreeView);
+ FRIEND_TEST_ALL_PREFIXES(LinkHighlightImplTest, multipleHighlights);
+
+ explicit LinkHighlights(Page&);
+
+ void RemoveAllHighlights();
+
+ LocalFrame* MainFrame() const;
+
+ Page& GetPage() const {
+ DCHECK(page_);
+ return *page_;
+ }
+
+ Member<Page> page_;
+ Vector<std::unique_ptr<LinkHighlightImpl>> link_highlights_;
+ std::unique_ptr<CompositorAnimationHost> animation_host_;
+ std::unique_ptr<CompositorAnimationTimeline> timeline_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_LINK_HIGHLIGHTS_H_
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 c8babd054cb..4b1dd4d6f67 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
@@ -37,7 +37,9 @@
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
+#include "third_party/blink/renderer/bindings/core/v8/usv_string_or_trusted_url.h"
#include "third_party/blink/renderer/bindings/core/v8/window_proxy.h"
+#include "third_party/blink/renderer/core/aom/computed_accessible_node.h"
#include "third_party/blink/renderer/core/css/css_computed_style_declaration.h"
#include "third_party/blink/renderer/core/css/css_rule_list.h"
#include "third_party/blink/renderer/core/css/dom_window_css.h"
@@ -45,9 +47,9 @@
#include "third_party/blink/renderer/core/css/media_query_matcher.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/css/style_media.h"
-#include "third_party/blink/renderer/core/dom/computed_accessible_node.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/dom/events/dom_window_event_queue.h"
+#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
#include "third_party/blink/renderer/core/dom/frame_request_callback_collection.h"
#include "third_party/blink/renderer/core/dom/scripted_idle_task_controller.h"
@@ -75,6 +77,7 @@
#include "third_party/blink/renderer/core/frame/screen.h"
#include "third_party/blink/renderer/core/frame/scroll_to_options.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"
#include "third_party/blink/renderer/core/html/custom/custom_element_registry.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
@@ -90,11 +93,13 @@
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
#include "third_party/blink/renderer/core/page/scrolling/snap_coordinator.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/script/modulator.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/platform/event_dispatch_forbidden_scope.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_url.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/scroll/scroll_types.h"
#include "third_party/blink/renderer/platform/scroll/scrollbar_theme.h"
@@ -103,7 +108,7 @@
namespace blink {
// Timeout for link preloads to be used after window.onload
-static const int kUnusedPreloadTimeoutInSeconds = 3;
+static constexpr TimeDelta kUnusedPreloadTimeout = TimeDelta::FromSeconds(3);
class PostMessageTimer final
: public GarbageCollectedFinalized<PostMessageTimer>,
@@ -122,8 +127,7 @@ class PostMessageTimer final
target_origin_(std::move(target_origin)),
location_(std::move(location)),
user_gesture_token_(user_gesture_token),
- disposal_allowed_(true) {
- }
+ disposal_allowed_(true) {}
MessageEvent* Event() const { return event_; }
const SecurityOrigin* TargetOrigin() const { return target_origin_.get(); }
@@ -265,21 +269,11 @@ void LocalDOMWindow::ClearDocument() {
DCHECK(!document_->IsActive());
- // FIXME: This should be part of PausableObject shutdown
- ClearEventQueue();
-
unused_preloads_timer_.Stop();
document_->ClearDOMWindow();
document_ = nullptr;
}
-void LocalDOMWindow::ClearEventQueue() {
- if (!event_queue_)
- return;
- event_queue_->Close();
- event_queue_.Clear();
-}
-
void LocalDOMWindow::AcceptLanguagesChanged() {
if (navigator_)
navigator_->SetLanguagesChanged();
@@ -319,27 +313,16 @@ Document* LocalDOMWindow::InstallNewDocument(const String& mime_type,
ClearDocument();
document_ = CreateDocument(mime_type, init, force_xhtml);
- event_queue_ = DOMWindowEventQueue::Create(document_.Get());
document_->Initialize();
if (!GetFrame())
return document_;
GetFrame()->GetScriptController().UpdateDocument();
- document_->UpdateViewportDescription();
+ document_->GetViewportData().UpdateViewportDescription();
if (GetFrame()->GetPage() && GetFrame()->View()) {
GetFrame()->GetPage()->GetChromeClient().InstallSupplements(*GetFrame());
-
- if (ScrollingCoordinator* scrolling_coordinator =
- GetFrame()->GetPage()->GetScrollingCoordinator()) {
- scrolling_coordinator->ScrollableAreaScrollbarLayerDidChange(
- GetFrame()->View(), kHorizontalScrollbar);
- scrolling_coordinator->ScrollableAreaScrollbarLayerDidChange(
- GetFrame()->View(), kVerticalScrollbar);
- scrolling_coordinator->ScrollableAreaScrollLayerDidChange(
- GetFrame()->View());
- }
}
if (GetFrame()->IsCrossOriginSubframe())
@@ -348,22 +331,13 @@ Document* LocalDOMWindow::InstallNewDocument(const String& mime_type,
return document_;
}
-EventQueue* LocalDOMWindow::GetEventQueue() const {
- return event_queue_.Get();
+void LocalDOMWindow::EnqueueWindowEvent(Event* event, TaskType task_type) {
+ EnqueueEvent(event, task_type);
}
-void LocalDOMWindow::EnqueueWindowEvent(Event* event) {
- if (!event_queue_)
- return;
- event->SetTarget(this);
- event_queue_->EnqueueEvent(FROM_HERE, event);
-}
-
-void LocalDOMWindow::EnqueueDocumentEvent(Event* event) {
- if (!event_queue_)
- return;
- event->SetTarget(document_.Get());
- event_queue_->EnqueueEvent(FROM_HERE, event);
+void LocalDOMWindow::EnqueueDocumentEvent(Event* event, TaskType task_type) {
+ if (document_)
+ document_->EnqueueEvent(event, task_type);
}
void LocalDOMWindow::DispatchWindowLoadEvent() {
@@ -395,8 +369,11 @@ void LocalDOMWindow::EnqueuePageshowEvent(PageshowEventPersistence persisted) {
// asynchronously. However to be compatible with other browsers blink fires
// pageshow synchronously unless we are in EventQueueScope.
if (ScopedEventQueue::Instance()->ShouldQueueEvents() && document_) {
- EnqueueWindowEvent(
- PageTransitionEvent::Create(EventTypeNames::pageshow, persisted));
+ // The task source should be kDOMManipulation, but the spec doesn't say
+ // anything about this.
+ EnqueueWindowEvent(
+ PageTransitionEvent::Create(EventTypeNames::pageshow, persisted),
+ TaskType::kMiscPlatformAPI);
return;
}
DispatchEvent(
@@ -406,7 +383,9 @@ void LocalDOMWindow::EnqueuePageshowEvent(PageshowEventPersistence persisted) {
void LocalDOMWindow::EnqueueHashchangeEvent(const String& old_url,
const String& new_url) {
- EnqueueWindowEvent(HashChangeEvent::Create(old_url, new_url));
+ // https://html.spec.whatwg.org/#history-traversal
+ EnqueueWindowEvent(HashChangeEvent::Create(old_url, new_url),
+ TaskType::kDOMManipulation);
}
void LocalDOMWindow::EnqueuePopstateEvent(
@@ -429,10 +408,7 @@ void LocalDOMWindow::StatePopped(
pending_state_object_ = std::move(state_object);
}
-LocalDOMWindow::~LocalDOMWindow() {
- // Cleared when detaching document.
- DCHECK(!event_queue_);
-}
+LocalDOMWindow::~LocalDOMWindow() = default;
void LocalDOMWindow::Dispose() {
// Oilpan: should the LocalDOMWindow be GCed along with its LocalFrame without
@@ -1032,8 +1008,7 @@ double LocalDOMWindow::scrollX() const {
// TODO(bokan): This is wrong when the document.rootScroller is non-default.
// crbug.com/505516.
- double viewport_x =
- view->LayoutViewportScrollableArea()->GetScrollOffset().Width();
+ double viewport_x = view->LayoutViewport()->GetScrollOffset().Width();
return AdjustForAbsoluteZoom::AdjustScroll(viewport_x,
GetFrame()->PageZoomFactor());
}
@@ -1050,8 +1025,7 @@ double LocalDOMWindow::scrollY() const {
// TODO(bokan): This is wrong when the document.rootScroller is non-default.
// crbug.com/505516.
- double viewport_y =
- view->LayoutViewportScrollableArea()->GetScrollOffset().Height();
+ double viewport_y = view->LayoutViewport()->GetScrollOffset().Height();
return AdjustForAbsoluteZoom::AdjustScroll(viewport_y,
GetFrame()->PageZoomFactor());
}
@@ -1162,23 +1136,27 @@ void LocalDOMWindow::scrollBy(const ScrollToOptions& scroll_to_options) const {
if (scroll_to_options.hasTop())
y = ScrollableArea::NormalizeNonFiniteScroll(scroll_to_options.top());
- ScrollableArea* viewport = view->LayoutViewportScrollableArea();
+ PaintLayerScrollableArea* viewport = view->LayoutViewport();
ScrollOffset current_offset = viewport->GetScrollOffset();
ScrollOffset scaled_delta(x * GetFrame()->PageZoomFactor(),
y * GetFrame()->PageZoomFactor());
- FloatPoint new_scaled_position = ScrollOffsetToPosition(
- scaled_delta + current_offset, viewport->ScrollOrigin());
- if (SnapCoordinator* coordinator = document()->GetSnapCoordinator()) {
- new_scaled_position = coordinator->GetSnapPositionForPoint(
- *document()->GetLayoutView(), new_scaled_position,
- scroll_to_options.hasLeft(), scroll_to_options.hasTop());
+ FloatPoint new_scaled_position =
+ viewport->ScrollOffsetToPosition(scaled_delta + current_offset);
+ if (RuntimeEnabledFeatures::CSSScrollSnapPointsEnabled()) {
+ new_scaled_position =
+ document()
+ ->GetSnapCoordinator()
+ ->GetSnapPositionForPoint(
+ *document()->GetLayoutView(), new_scaled_position,
+ scroll_to_options.hasLeft(), scroll_to_options.hasTop())
+ .value_or(new_scaled_position);
}
ScrollBehavior scroll_behavior = kScrollBehaviorAuto;
ScrollableArea::ScrollBehaviorFromString(scroll_to_options.behavior(),
scroll_behavior);
viewport->SetScrollOffset(
- ScrollPositionToOffset(new_scaled_position, viewport->ScrollOrigin()),
+ viewport->ScrollPositionToOffset(new_scaled_position),
kProgrammaticScroll, scroll_behavior);
}
@@ -1222,7 +1200,7 @@ void LocalDOMWindow::scrollTo(const ScrollToOptions& scroll_to_options) const {
double scaled_x = 0.0;
double scaled_y = 0.0;
- ScrollableArea* viewport = view->LayoutViewportScrollableArea();
+ PaintLayerScrollableArea* viewport = view->LayoutViewport();
ScrollOffset current_offset = viewport->GetScrollOffset();
scaled_x = current_offset.Width();
scaled_y = current_offset.Height();
@@ -1237,12 +1215,16 @@ void LocalDOMWindow::scrollTo(const ScrollToOptions& scroll_to_options) const {
ScrollableArea::NormalizeNonFiniteScroll(scroll_to_options.top()) *
GetFrame()->PageZoomFactor();
- FloatPoint new_scaled_position = ScrollOffsetToPosition(
- ScrollOffset(scaled_x, scaled_y), viewport->ScrollOrigin());
- if (SnapCoordinator* coordinator = document()->GetSnapCoordinator()) {
- new_scaled_position = coordinator->GetSnapPositionForPoint(
- *document()->GetLayoutView(), new_scaled_position,
- scroll_to_options.hasLeft(), scroll_to_options.hasTop());
+ FloatPoint new_scaled_position =
+ viewport->ScrollOffsetToPosition(ScrollOffset(scaled_x, scaled_y));
+ if (RuntimeEnabledFeatures::CSSScrollSnapPointsEnabled()) {
+ new_scaled_position =
+ document()
+ ->GetSnapCoordinator()
+ ->GetSnapPositionForPoint(
+ *document()->GetLayoutView(), new_scaled_position,
+ scroll_to_options.hasLeft(), scroll_to_options.hasTop())
+ .value_or(new_scaled_position);
}
ScrollBehavior scroll_behavior = kScrollBehaviorAuto;
@@ -1250,7 +1232,7 @@ void LocalDOMWindow::scrollTo(const ScrollToOptions& scroll_to_options) const {
scroll_behavior);
viewport->SetScrollOffset(
- ScrollPositionToOffset(new_scaled_position, viewport->ScrollOrigin()),
+ viewport->ScrollPositionToOffset(new_scaled_position),
kProgrammaticScroll, scroll_behavior);
}
@@ -1439,12 +1421,20 @@ void LocalDOMWindow::RemovedEventListener(
}
void LocalDOMWindow::WarnUnusedPreloads(TimerBase* base) {
- if (GetFrame() && GetFrame()->Loader().GetDocumentLoader()) {
- ResourceFetcher* fetcher =
- GetFrame()->Loader().GetDocumentLoader()->Fetcher();
- DCHECK(fetcher);
- if (fetcher->CountPreloads())
- fetcher->WarnUnusedPreloads();
+ if (!GetFrame() || !GetFrame()->Loader().GetDocumentLoader())
+ return;
+ ResourceFetcher* fetcher =
+ GetFrame()->Loader().GetDocumentLoader()->Fetcher();
+ DCHECK(fetcher);
+ Vector<KURL> urls = fetcher->GetUrlsOfUnusedPreloads();
+ for (const KURL& url : urls) {
+ String message =
+ "The resource " + url.GetString() + " was preloaded using link " +
+ "preload but not used within a few seconds from the window's load " +
+ "event. Please make sure it has an appropriate `as` value and it is " +
+ "preloaded intentionally.";
+ GetFrameConsole()->AddMessage(ConsoleMessage::Create(
+ kJSMessageSource, kWarningMessageLevel, message));
}
}
@@ -1464,8 +1454,7 @@ void LocalDOMWindow::DispatchLoadEvent() {
if (GetFrame() &&
document_loader == GetFrame()->Loader().GetDocumentLoader() &&
document_loader->Fetcher()->CountPreloads()) {
- unused_preloads_timer_.StartOneShot(kUnusedPreloadTimeoutInSeconds,
- FROM_HERE);
+ unused_preloads_timer_.StartOneShot(kUnusedPreloadTimeout, FROM_HERE);
}
} else {
DispatchEvent(load_event, document());
@@ -1545,6 +1534,46 @@ DOMWindow* LocalDOMWindow::open(ExecutionContext* executionContext,
const AtomicString& target,
const String& features,
ExceptionState& exception_state) {
+ if (document_->RequireTrustedTypes()) {
+ exception_state.ThrowTypeError(
+ "This document requires `TrustedURL` assignment.");
+ return nullptr;
+ }
+ return openFromString(executionContext, current_window, entered_window, url,
+ target, features, exception_state);
+}
+
+DOMWindow* LocalDOMWindow::open(ExecutionContext* executionContext,
+ LocalDOMWindow* current_window,
+ LocalDOMWindow* entered_window,
+ const USVStringOrTrustedURL& stringOrUrl,
+ const AtomicString& target,
+ const String& features,
+ ExceptionState& exception_state) {
+ DCHECK(stringOrUrl.IsUSVString() ||
+ RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
+
+ if (!stringOrUrl.IsTrustedURL() && document_->RequireTrustedTypes()) {
+ exception_state.ThrowTypeError(
+ "This document requires `TrustedURL` assignment.");
+ return nullptr;
+ }
+
+ String url = stringOrUrl.IsUSVString()
+ ? stringOrUrl.GetAsUSVString()
+ : stringOrUrl.GetAsTrustedURL()->toString();
+
+ return openFromString(executionContext, current_window, entered_window, url,
+ target, features, exception_state);
+}
+
+DOMWindow* LocalDOMWindow::openFromString(ExecutionContext* executionContext,
+ LocalDOMWindow* current_window,
+ LocalDOMWindow* entered_window,
+ const String& url,
+ const AtomicString& target,
+ const String& features,
+ ExceptionState& exception_state) {
// If the bindings implementation is 100% correct, the current realm and the
// entered realm should be same origin-domain. However, to be on the safe
// side and add some defense in depth, we'll check against the entered realm
@@ -1555,16 +1584,54 @@ DOMWindow* LocalDOMWindow::open(ExecutionContext* executionContext,
return nullptr;
}
DCHECK(!target.IsNull());
- return open(url, target, features, current_window, entered_window,
- exception_state);
+ return openFromString(url, target, features, current_window, entered_window,
+ exception_state);
+}
+
+DOMWindow* LocalDOMWindow::open(const String& url,
+ const AtomicString& frame_name,
+ const String& window_features_string,
+ LocalDOMWindow* calling_window,
+ LocalDOMWindow* entered_window,
+ ExceptionState& exception_state) {
+ if (document_->RequireTrustedTypes()) {
+ exception_state.ThrowTypeError(
+ "This document requires `TrustedURL` assignment.");
+ return nullptr;
+ }
+ return openFromString(url, frame_name, window_features_string, calling_window,
+ entered_window, exception_state);
}
-DOMWindow* LocalDOMWindow::open(const String& url_string,
+DOMWindow* LocalDOMWindow::open(const USVStringOrTrustedURL& stringOrUrl,
const AtomicString& frame_name,
const String& window_features_string,
LocalDOMWindow* calling_window,
LocalDOMWindow* entered_window,
ExceptionState& exception_state) {
+ DCHECK(stringOrUrl.IsUSVString() ||
+ RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
+
+ if (!stringOrUrl.IsTrustedURL() && document_->RequireTrustedTypes()) {
+ exception_state.ThrowTypeError(
+ "This document requires `TrustedURL` assignment.");
+ return nullptr;
+ }
+
+ String url = stringOrUrl.IsUSVString()
+ ? stringOrUrl.GetAsUSVString()
+ : stringOrUrl.GetAsTrustedURL()->toString();
+
+ return openFromString(url, frame_name, window_features_string, calling_window,
+ entered_window, exception_state);
+}
+
+DOMWindow* LocalDOMWindow::openFromString(const String& url_string,
+ const AtomicString& frame_name,
+ const String& window_features_string,
+ LocalDOMWindow* calling_window,
+ LocalDOMWindow* entered_window,
+ ExceptionState& exception_state) {
if (!IsCurrentlyDisplayedInFrame())
return nullptr;
if (!calling_window->GetFrame())
@@ -1607,8 +1674,8 @@ DOMWindow* LocalDOMWindow::open(const String& url_string,
if (url_string.IsEmpty())
return target_frame->DomWindow();
- target_frame->Navigate(*active_document, completed_url, false,
- UserGestureStatus::kNone);
+ target_frame->ScheduleNavigation(*active_document, completed_url, false,
+ UserGestureStatus::kNone);
return target_frame->DomWindow();
}
@@ -1634,7 +1701,6 @@ void LocalDOMWindow::Trace(blink::Visitor* visitor) {
visitor->Trace(modulator_);
visitor->Trace(external_);
visitor->Trace(application_cache_);
- visitor->Trace(event_queue_);
visitor->Trace(post_message_timers_);
visitor->Trace(visualViewport_);
visitor->Trace(event_listener_observers_);
@@ -1642,13 +1708,4 @@ void LocalDOMWindow::Trace(blink::Visitor* visitor) {
Supplementable<LocalDOMWindow>::Trace(visitor);
}
-void LocalDOMWindow::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(custom_elements_);
- visitor->TraceWrappers(document_);
- visitor->TraceWrappers(modulator_);
- visitor->TraceWrappers(navigator_);
- DOMWindow::TraceWrappers(visitor);
- Supplementable<LocalDOMWindow>::TraceWrappers(visitor);
-}
-
} // namespace blink
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 b0a66c4ff81..f64aaa45cde 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
@@ -50,9 +50,7 @@ class Document;
class DocumentInit;
class DOMSelection;
class DOMVisualViewport;
-class DOMWindowEventQueue;
class Element;
-class EventQueue;
class ExceptionState;
class External;
class FrameConsole;
@@ -71,6 +69,7 @@ class SecurityOrigin;
class SerializedScriptValue;
class SourceLocation;
class StyleMedia;
+class USVStringOrTrustedURL;
class V8FrameRequestCallback;
class V8IdleRequestCallback;
@@ -109,7 +108,6 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
LocalFrame* GetFrame() const { return ToLocalFrame(DOMWindow::GetFrame()); }
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
Document* InstallNewDocument(const String& mime_type,
const DocumentInit&,
@@ -270,12 +268,27 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
DOMWindow* open(ExecutionContext*,
LocalDOMWindow* current_window,
LocalDOMWindow* entered_window,
- const String& url,
+ const USVStringOrTrustedURL& stringOrUrl,
const AtomicString& target,
const String& features,
ExceptionState&);
- DOMWindow* open(const String& url_string,
+ DOMWindow* open(const USVStringOrTrustedURL& stringOrUrl,
+ const AtomicString& frame_name,
+ const String& window_features_string,
+ LocalDOMWindow* calling_window,
+ LocalDOMWindow* entered_window,
+ ExceptionState&);
+
+ DOMWindow* open(ExecutionContext*,
+ LocalDOMWindow* current_window,
+ LocalDOMWindow* entered_window,
+ const String& str_url,
+ const AtomicString& target,
+ const String& features,
+ ExceptionState&);
+
+ DOMWindow* open(const String& str_url,
const AtomicString& frame_name,
const String& window_features_string,
LocalDOMWindow* calling_window,
@@ -306,9 +319,8 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
// recurse on its child frames.
void SendOrientationChangeEvent();
- EventQueue* GetEventQueue() const;
- void EnqueueWindowEvent(Event*);
- void EnqueueDocumentEvent(Event*);
+ void EnqueueWindowEvent(Event*, TaskType);
+ void EnqueueDocumentEvent(Event*, TaskType);
void EnqueuePageshowEvent(PageshowEventPersistence);
void EnqueueHashchangeEvent(const String& old_url, const String& new_url);
void EnqueuePopstateEvent(scoped_refptr<SerializedScriptValue>);
@@ -316,10 +328,6 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
void DocumentWasClosed();
void StatePopped(scoped_refptr<SerializedScriptValue>);
- // FIXME: This shouldn't be public once LocalDOMWindow becomes
- // ExecutionContext.
- void ClearEventQueue();
-
void AcceptLanguagesChanged();
protected:
@@ -347,6 +355,21 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
void DispatchLoadEvent();
void ClearDocument();
+ DOMWindow* openFromString(ExecutionContext*,
+ LocalDOMWindow* current_window,
+ LocalDOMWindow* entered_window,
+ const String& url,
+ const AtomicString& target,
+ const String& features,
+ ExceptionState&);
+
+ DOMWindow* openFromString(const String& url_string,
+ const AtomicString& frame_name,
+ const String& window_features_string,
+ LocalDOMWindow* calling_window,
+ LocalDOMWindow* entered_window,
+ ExceptionState&);
+
// Return the viewport size including scrollbars.
IntSize GetViewportSize() const;
@@ -372,8 +395,6 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
// This is wrong, as Modulator is per-context, where as LocalDOMWindow is
// shared among context. However, this *works* as Modulator is currently only
// enabled in the main world,
- // TODO(kouhei): Remove this workaround once V8PerContextData::Data is
- // TraceWrapperBase.
TraceWrapperMember<Modulator> modulator_;
Member<External> external_;
@@ -382,7 +403,6 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
mutable Member<ApplicationCache> application_cache_;
- Member<DOMWindowEventQueue> event_queue_;
scoped_refptr<SerializedScriptValue> pending_state_object_;
HeapHashSet<Member<PostMessageTimer>> post_message_timers_;
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 5686e6a06d6..464a41e6f27 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame.cc
@@ -36,12 +36,15 @@
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/interface_registry.h"
+#include "third_party/blink/public/platform/scheduler/web_resource_loading_task_runner_handle.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/core/CoreProbeSink.h"
+#include "third_party/blink/renderer/core/aom/computed_accessible_node.h"
#include "third_party/blink/renderer/core/core_initializer.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/dom/child_frame_disconnector.h"
+#include "third_party/blink/renderer/core/dom/document_init.h"
#include "third_party/blink/renderer/core/dom/document_parser.h"
#include "third_party/blink/renderer/core/dom/document_type.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
@@ -77,20 +80,19 @@
#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/loader/navigation_scheduler.h"
+#include "third_party/blink/renderer/core/loader/previews_resource_loading_hints_receiver_impl.h"
#include "third_party/blink/renderer/core/page/drag_controller.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
+#include "third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/svg/svg_document_extensions.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-#include "third_party/blink/renderer/platform/graphics/paint/transform_display_item.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/blink_resource_coordinator_base.h"
#include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.h"
@@ -151,17 +153,20 @@ class EmptyFrameScheduler final : public FrameScheduler {
return Platform::Current()->MainThread()->GetTaskRunner();
}
- std::unique_ptr<ThrottlingObserverHandle> AddThrottlingObserver(
- ObserverType,
- Observer*) override {
- return nullptr;
+ std::unique_ptr<scheduler::WebResourceLoadingTaskRunnerHandle>
+ CreateResourceLoadingTaskRunnerHandle() override {
+ return scheduler::WebResourceLoadingTaskRunnerHandle::CreateUnprioritized(
+ GetTaskRunner(TaskType::kNetworkingWithURLLoaderAnnotation));
}
+
void SetFrameVisible(bool) override {}
bool IsFrameVisible() const override { return false; }
bool IsPageVisible() const override { return false; }
void SetPaused(bool) override {}
void SetCrossOrigin(bool) override {}
bool IsCrossOrigin() const override { return false; }
+ void SetIsAdFrame() override {}
+ bool IsAdFrame() const override { return false; }
void TraceUrlChange(const String& override) override {}
FrameScheduler::FrameType GetFrameType() const override {
return FrameScheduler::FrameType::kSubframe;
@@ -181,6 +186,10 @@ class EmptyFrameScheduler final : public FrameScheduler {
return nullptr;
}
bool IsExemptFromBudgetBasedThrottling() const override { return false; }
+ std::unique_ptr<blink::mojom::blink::PauseSubresourceLoadingHandle>
+ GetPauseSubresourceLoadingHandle() override {
+ return nullptr;
+ }
};
} // namespace
@@ -302,10 +311,10 @@ bool LocalFrame::IsLocalRoot() const {
return Tree().Parent()->IsRemoteFrame();
}
-void LocalFrame::Navigate(Document& origin_document,
- const KURL& url,
- bool replace_current_item,
- UserGestureStatus user_gesture_status) {
+void LocalFrame::ScheduleNavigation(Document& origin_document,
+ const KURL& url,
+ bool replace_current_item,
+ UserGestureStatus user_gesture_status) {
navigation_scheduler_->ScheduleFrameNavigation(&origin_document, url,
replace_current_item);
}
@@ -314,7 +323,7 @@ void LocalFrame::Navigate(const FrameLoadRequest& request) {
loader_.StartNavigation(request);
}
-void LocalFrame::Reload(FrameLoadType load_type,
+void LocalFrame::Reload(WebFrameLoadType load_type,
ClientRedirectPolicy client_redirect_policy) {
DCHECK(IsReloadLoadType(load_type));
if (client_redirect_policy == ClientRedirectPolicy::kNotClientRedirect) {
@@ -326,7 +335,7 @@ void LocalFrame::Reload(FrameLoadType load_type,
request.SetClientRedirect(client_redirect_policy);
loader_.StartNavigation(request, load_type);
} else {
- DCHECK_EQ(kFrameLoadTypeReload, load_type);
+ DCHECK_EQ(WebFrameLoadType::kReload, load_type);
navigation_scheduler_->ScheduleReload();
}
}
@@ -344,7 +353,8 @@ void LocalFrame::Detach(FrameDetachType type) {
if (IsLocalRoot()) {
performance_monitor_->Shutdown();
- ad_tracker_->Shutdown();
+ if (ad_tracker_)
+ ad_tracker_->Shutdown();
}
idleness_detector_->Shutdown();
if (inspector_trace_events_)
@@ -484,6 +494,7 @@ void LocalFrame::DocumentAttached() {
GetInputMethodController().DocumentAttached(GetDocument());
GetSpellChecker().DocumentAttached(GetDocument());
GetTextSuggestionController().DocumentAttached(GetDocument());
+ previews_resource_loading_hints_receiver_.reset();
}
Frame* LocalFrame::FindFrameForNavigation(const AtomicString& name,
@@ -547,13 +558,13 @@ void LocalFrame::DidFreeze() {
void LocalFrame::DidResume() {
DCHECK(RuntimeEnabledFeatures::PageLifecycleEnabled());
if (GetDocument()) {
- const double resume_event_start = CurrentTimeTicksInSeconds();
+ const TimeTicks resume_event_start = CurrentTimeTicks();
GetDocument()->DispatchEvent(Event::Create(EventTypeNames::resume));
- const double resume_event_end = CurrentTimeTicksInSeconds();
+ const TimeTicks resume_event_end = CurrentTimeTicks();
DEFINE_STATIC_LOCAL(
CustomCountHistogram, resume_histogram,
("DocumentEventTiming.ResumeDuration", 0, 10000000, 50));
- resume_histogram.Count((resume_event_end - resume_event_start) * 1000000.0);
+ resume_histogram.CountMicroseconds(resume_event_end - resume_event_start);
// TODO(fmeawad): Move the following logic to the page once we have a
// PageResourceCoordinator in Blink
if (auto* frame_resource_coordinator = GetFrameResourceCoordinator()) {
@@ -808,7 +819,8 @@ String LocalFrame::SelectedTextForClipboard() const {
PositionWithAffinity LocalFrame::PositionForPoint(
const LayoutPoint& frame_point) {
- HitTestResult result = GetEventHandler().HitTestResultAtPoint(frame_point);
+ HitTestLocation location(frame_point);
+ HitTestResult result = GetEventHandler().HitTestResultAtLocation(location);
Node* node = result.InnerNodeOrImageMapImage();
if (!node)
return PositionWithAffinity();
@@ -826,21 +838,33 @@ Document* LocalFrame::DocumentAtPoint(const LayoutPoint& point_in_root_frame) {
if (!View())
return nullptr;
- LayoutPoint pt = View()->RootFrameToContents(point_in_root_frame);
+ HitTestLocation location(View()->ConvertFromRootFrame(point_in_root_frame));
if (!ContentLayoutObject())
return nullptr;
- HitTestResult result = GetEventHandler().HitTestResultAtPoint(
- pt, HitTestRequest::kReadOnly | HitTestRequest::kActive);
+ HitTestResult result = GetEventHandler().HitTestResultAtLocation(
+ location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
return result.InnerNode() ? &result.InnerNode()->GetDocument() : nullptr;
}
-bool LocalFrame::ShouldReuseDefaultView(const KURL& url) const {
+bool LocalFrame::ShouldReuseDefaultView(
+ const KURL& url,
+ const ContentSecurityPolicy* csp) const {
// Secure transitions can only happen when navigating from the initial empty
// document.
if (!Loader().StateMachine()->IsDisplayingInitialEmptyDocument())
return false;
+ // The Window object should only be re-used if it is same-origin.
+ // Since sandboxing turns the origin into an opaque origin it needs to also
+ // be considered when deciding whether to reuse it.
+ // Spec:
+ // https://html.spec.whatwg.org/multipage/browsing-the-web.html#initialise-the-document-object
+ if (csp &&
+ SecurityContext::IsSandboxed(kSandboxOrigin, csp->GetSandboxMask())) {
+ return false;
+ }
+
return GetDocument()->IsSecureTransitionTo(url);
}
@@ -862,7 +886,8 @@ String LocalFrame::GetLayerTreeAsTextForTesting(unsigned flags) const {
while (root_layer->Parent())
root_layer = root_layer->Parent();
}
- layers = root_layer->LayerTreeAsJSON(static_cast<LayerTreeFlags>(flags));
+ layers = GraphicsLayerTreeAsJSON(root_layer,
+ static_cast<LayerTreeFlags>(flags));
}
}
@@ -917,10 +942,12 @@ inline LocalFrame::LocalFrame(LocalFrameClient* client,
interface_registry_(interface_registry) {
if (IsLocalRoot()) {
probe_sink_ = new CoreProbeSink();
- ad_tracker_ = new AdTracker(this);
performance_monitor_ = new PerformanceMonitor(this);
inspector_trace_events_ = new InspectorTraceEvents();
probe_sink_->addInspectorTraceEvents(inspector_trace_events_);
+ if (RuntimeEnabledFeatures::AdTaggingEnabled()) {
+ ad_tracker_ = new AdTracker(this);
+ }
} else {
// Inertness only needs to be updated if this frame might inherit the
// inert state from a higher-level frame. If this is an OOPIF local root,
@@ -934,8 +961,11 @@ inline LocalFrame::LocalFrame(LocalFrameClient* client,
idleness_detector_ = new IdlenessDetector(this);
inspector_task_runner_->InitIsolate(V8PerIsolateData::MainThreadIsolate());
- if (ComputeIsAdSubFrame())
- SetIsAdSubframe();
+ if (ad_tracker_) {
+ SetIsAdSubframeIfNecessary();
+ }
+ DCHECK(ad_tracker_ ? RuntimeEnabledFeatures::AdTaggingEnabled()
+ : !RuntimeEnabledFeatures::AdTaggingEnabled());
}
FrameScheduler* LocalFrame::GetFrameScheduler() {
@@ -1088,16 +1118,6 @@ static bool CanAccessAncestor(const SecurityOrigin& active_security_origin,
return false;
}
-blink::mojom::blink::PrefetchURLLoaderService*
-LocalFrame::PrefetchURLLoaderService() {
- if (!prefetch_loader_service_ &&
- base::FeatureList::IsEnabled(network::features::kNetworkService)) {
- GetInterfaceProvider().GetInterface(
- mojo::MakeRequest(&prefetch_loader_service_));
- }
- return prefetch_loader_service_.get();
-}
-
bool LocalFrame::CanNavigateWithoutFramebusting(const Frame& target_frame,
String& reason) {
if (&target_frame == this)
@@ -1193,17 +1213,20 @@ bool LocalFrame::CanNavigateWithoutFramebusting(const Frame& target_frame,
return false;
}
-bool LocalFrame::ComputeIsAdSubFrame() const {
+void LocalFrame::SetIsAdSubframeIfNecessary() {
DCHECK(ad_tracker_);
Frame* parent = Tree().Parent();
if (!parent)
- return false;
+ return;
- // If the parent frame is local, directly determine if it's an ad. If
- // it's remote, then blink relies on the embedder to call SetIsAdFrame.
+ // If the parent frame is local, directly determine if it's an ad. If it's
+ // remote, then it is up to the embedder that moved this frame out-of-
+ // process to set this frame as an ad via SetIsAdSubframe before commit.
bool parent_is_ad =
parent->IsLocalFrame() && ToLocalFrame(parent)->IsAdSubframe();
- return parent_is_ad || ad_tracker_->IsAdScriptInStack(GetDocument());
+
+ if (parent_is_ad || ad_tracker_->IsAdScriptInStack())
+ SetIsAdSubframe();
}
service_manager::InterfaceProvider& LocalFrame::GetInterfaceProvider() {
@@ -1245,6 +1268,12 @@ PluginData* LocalFrame::GetPluginData() const {
Tree().Top().GetSecurityContext()->GetSecurityOrigin());
}
+void LocalFrame::SetAdTrackerForTesting(AdTracker* ad_tracker) {
+ if (ad_tracker_)
+ ad_tracker_->Shutdown();
+ ad_tracker_ = ad_tracker;
+}
+
DEFINE_WEAK_IDENTIFIER_MAP(LocalFrame);
FrameNavigationDisabler::FrameNavigationDisabler(LocalFrame& frame)
@@ -1349,18 +1378,15 @@ void LocalFrame::ForceSynchronousDocumentInstall(
GetDocument()->OpenForNavigation(kForceSynchronousParsing, mime_type,
AtomicString("UTF-8"));
- data->ForEachSegment(
- [this](const char* segment, size_t segment_size, size_t segment_offset) {
- GetDocument()->Parser()->AppendBytes(segment, segment_size);
- return true;
- });
+ for (const auto& segment : *data)
+ GetDocument()->Parser()->AppendBytes(segment.data(), segment.size());
GetDocument()->Parser()->Finish();
// Upon loading of SVGIamges, log PageVisits in UseCounter.
// Do not track PageVisits for inspector, web page popups, and validation
// message overlays (the other callers of this method).
- if (GetPage() && GetDocument()->IsSVGDocument())
- GetPage()->GetUseCounter().DidCommitLoad(this);
+ if (GetDocument()->IsSVGDocument())
+ loader_.GetDocumentLoader()->GetUseCounter().DidCommitLoad(this);
}
bool LocalFrame::IsProvisional() const {
@@ -1399,4 +1425,28 @@ ComputedAccessibleNode* LocalFrame::GetOrCreateComputedAccessibleNode(
return computed_node_mapping_.at(ax_id);
}
+void LocalFrame::PauseSubresourceLoading(
+ blink::mojom::blink::PauseSubresourceLoadingHandleRequest request) {
+ auto handle = GetFrameScheduler()->GetPauseSubresourceLoadingHandle();
+ if (!handle)
+ return;
+ pause_handle_bindings_.AddBinding(std::move(handle), std::move(request));
+}
+
+void LocalFrame::ResumeSubresourceLoading() {
+ pause_handle_bindings_.CloseAllBindings();
+}
+
+void LocalFrame::AnimateSnapFling(base::TimeTicks monotonic_time) {
+ GetEventHandler().AnimateSnapFling(monotonic_time);
+}
+
+void LocalFrame::BindPreviewsResourceLoadingHintsRequest(
+ blink::mojom::blink::PreviewsResourceLoadingHintsReceiverRequest request) {
+ DCHECK(!previews_resource_loading_hints_receiver_);
+ previews_resource_loading_hints_receiver_ =
+ std::make_unique<PreviewsResourceLoadingHintsReceiverImpl>(
+ std::move(request));
+}
+
} // 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 60c8c7288d9..79dec449f7e 100644
--- a/chromium/third_party/blink/renderer/core/frame/local_frame.h
+++ b/chromium/third_party/blink/renderer/core/frame/local_frame.h
@@ -32,25 +32,29 @@
#include <memory>
#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
-#include "third_party/blink/public/mojom/loader/prefetch_url_loader_service.mojom-blink.h"
+#include "mojo/public/cpp/bindings/strong_binding_set.h"
+#include "third_party/blink/public/mojom/loader/pause_subresource_loading_handle.mojom-blink.h"
+#include "third_party/blink/public/mojom/loader/previews_resource_loading_hints.mojom-blink.h"
+#include "third_party/blink/public/platform/task_type.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/dom/ax_object_cache.h"
-#include "third_party/blink/renderer/core/dom/computed_accessible_node.h"
#include "third_party/blink/renderer/core/dom/user_gesture_indicator.h"
#include "third_party/blink/renderer/core/dom/weak_identifier_map.h"
#include "third_party/blink/renderer/core/editing/forward.h"
#include "third_party/blink/renderer/core/frame/frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/loader/frame_loader.h"
-#include "third_party/blink/renderer/core/loader/interactive_detector.h"
-#include "third_party/blink/renderer/core/page/frame_tree.h"
#include "third_party/blink/renderer/platform/graphics/touch_action.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/instance_counters.h"
-#include "third_party/blink/renderer/platform/scroll/scroll_types.h"
+#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"
+namespace base {
+class SingleThreadTaskRunner;
+}
+
namespace service_manager {
class InterfaceProvider;
}
@@ -71,7 +75,7 @@ class FetchParameters;
class FloatSize;
class FrameConsole;
class FrameResourceCoordinator;
-class FrameScheduler;
+// class FrameScheduler;
class FrameSelection;
class InputMethodController;
class InspectorTraceEvents;
@@ -90,6 +94,7 @@ class NodeTraversal;
class PerformanceMonitor;
class PluginData;
class ScriptController;
+class SharedBuffer;
class SpellChecker;
class TextSuggestionController;
class WebComputedAXTree;
@@ -115,12 +120,12 @@ class CORE_EXPORT LocalFrame final : public Frame,
// Frame overrides:
~LocalFrame() override;
void Trace(blink::Visitor*) override;
- void Navigate(Document& origin_document,
- const KURL&,
- bool replace_current_item,
- UserGestureStatus) override;
+ void ScheduleNavigation(Document& origin_document,
+ const KURL&,
+ bool replace_current_item,
+ UserGestureStatus) override;
void Navigate(const FrameLoadRequest&) override;
- void Reload(FrameLoadType, ClientRedirectPolicy) override;
+ void Reload(WebFrameLoadType, ClientRedirectPolicy) override;
void Detach(FrameDetachType) override;
bool ShouldClose() override;
SecurityContext* GetSecurityContext() const override;
@@ -231,7 +236,7 @@ class CORE_EXPORT LocalFrame final : public Frame,
PositionForPoint(const LayoutPoint& frame_point);
Document* DocumentAtPoint(const LayoutPoint&);
- bool ShouldReuseDefaultView(const KURL&) const;
+ bool ShouldReuseDefaultView(const KURL&, const ContentSecurityPolicy*) const;
void RemoveSpellingMarkersUnderWords(const Vector<String>& words);
bool ShouldThrottleRendering() const;
@@ -279,6 +284,7 @@ class CORE_EXPORT LocalFrame final : public Frame,
PerformanceMonitor* GetPerformanceMonitor() { return performance_monitor_; }
IdlenessDetector* GetIdlenessDetector() { return idleness_detector_; }
AdTracker* GetAdTracker() { return ad_tracker_; }
+ void SetAdTrackerForTesting(AdTracker* ad_tracker);
// Convenience function to allow loading image placeholders for the request if
// either the flag in Settings() for using image placeholders is set, or if
@@ -325,29 +331,43 @@ class CORE_EXPORT LocalFrame final : public Frame,
// preview.
bool IsUsingDataSavingPreview() const;
- // Prefetch URLLoader service. May return nullptr.
- blink::mojom::blink::PrefetchURLLoaderService* PrefetchURLLoaderService();
-
ComputedAccessibleNode* GetOrCreateComputedAccessibleNode(AXID,
WebComputedAXTree*);
// True if AdTracker heuristics have determined that this frame is an ad.
+ // Calculated in the constructor but LocalFrames created on behalf of OOPIF
+ // aren't set until just before commit (ReadyToCommitNavigation time) by the
+ // embedder.
bool IsAdSubframe() const { return is_ad_subframe_; }
void SetIsAdSubframe() {
DCHECK(!IsMainFrame());
if (is_ad_subframe_)
return;
is_ad_subframe_ = true;
+ frame_scheduler_->SetIsAdFrame();
InstanceCounters::IncrementCounter(InstanceCounters::kAdSubframeCounter);
}
+ // Binds |request| and prevents resource loading until either the frame is
+ // navigated or the request pipe is closed.
+ void PauseSubresourceLoading(
+ blink::mojom::blink::PauseSubresourceLoadingHandleRequest request);
+
+ void ResumeSubresourceLoading();
+
+ void AnimateSnapFling(base::TimeTicks monotonic_time);
+
+ ClientHintsPreferences& GetClientHintsPreferences() {
+ return client_hints_preferences_;
+ }
+
+ void BindPreviewsResourceLoadingHintsRequest(
+ blink::mojom::blink::PreviewsResourceLoadingHintsReceiverRequest request);
+
private:
friend class FrameNavigationDisabler;
- LocalFrame(LocalFrameClient*,
- Page&,
- FrameOwner*,
- InterfaceRegistry*);
+ LocalFrame(LocalFrameClient*, Page&, FrameOwner*, InterfaceRegistry*);
// Intentionally private to prevent redundant checks when the type is
// already LocalFrame.
@@ -359,7 +379,7 @@ class CORE_EXPORT LocalFrame final : public Frame,
bool CanNavigateWithoutFramebusting(const Frame&, String& error_reason);
- bool ComputeIsAdSubFrame() const;
+ void SetIsAdSubframeIfNecessary();
void PropagateInertToChildFrames();
@@ -376,6 +396,11 @@ class CORE_EXPORT LocalFrame final : public Frame,
std::unique_ptr<FrameScheduler> frame_scheduler_;
+ // Holds all PauseSubresourceLoadingHandles allowing either |this| to delete
+ // them explicitly or the pipe closing to delete them.
+ mojo::StrongBindingSet<blink::mojom::blink::PauseSubresourceLoadingHandle>
+ pause_handle_bindings_;
+
mutable FrameLoader loader_;
Member<NavigationScheduler> navigation_scheduler_;
@@ -431,7 +456,10 @@ class CORE_EXPORT LocalFrame final : public Frame,
// Per-frame URLLoader factory.
std::unique_ptr<WebURLLoaderFactory> url_loader_factory_;
- blink::mojom::blink::PrefetchURLLoaderServicePtr prefetch_loader_service_;
+ std::unique_ptr<mojom::blink::PreviewsResourceLoadingHintsReceiver>
+ previews_resource_loading_hints_receiver_;
+
+ ClientHintsPreferences client_hints_preferences_;
};
inline FrameLoader& LocalFrame::Loader() const {
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 53d77b624e4..7360a10773e 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
@@ -35,19 +35,24 @@
#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/platform/web_content_security_policy_struct.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_insecure_request_policy.h"
#include "third_party/blink/public/platform/web_loading_behavior_flag.h"
#include "third_party/blink/public/platform/web_scoped_virtual_time_pauser.h"
#include "third_party/blink/public/platform/web_sudden_termination_disabler_type.h"
#include "third_party/blink/public/platform/web_url_request.h"
+#include "third_party/blink/public/platform/web_worker_fetch_context.h"
#include "third_party/blink/public/web/web_global_object_reuse_policy.h"
+#include "third_party/blink/public/web/web_history_commit_type.h"
+#include "third_party/blink/public/web/web_navigation_timings.h"
#include "third_party/blink/public/web/web_triggering_event_info.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/dom/icon_url.h"
#include "third_party/blink/renderer/core/frame/frame_client.h"
#include "third_party/blink/renderer/core/frame/frame_types.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/link_resource.h"
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
#include "third_party/blink/renderer/core/loader/frame_loader_types.h"
@@ -79,7 +84,6 @@ class HTMLMediaElement;
class HTMLPlugInElement;
class HistoryItem;
class KURL;
-class LocalFrame;
class WebPluginContainerImpl;
class ResourceError;
class ResourceRequest;
@@ -103,6 +107,10 @@ class WebSpellCheckPanelHostClient;
struct WebScrollIntoViewParams;
class WebTextCheckClient;
+// Whether to follow cross origin redirects when downloading, or treating
+// the download as a navigation instead.
+enum class DownloadCrossOriginRedirects { kFollow, kNavigate };
+
class CORE_EXPORT LocalFrameClient : public FrameClient {
public:
~LocalFrameClient() override = default;
@@ -119,9 +127,8 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
const ResourceResponse&) = 0;
virtual void DispatchDidHandleOnloadEvents() = 0;
- virtual void DispatchDidReceiveServerRedirectForProvisionalLoad() = 0;
virtual void DidFinishSameDocumentNavigation(HistoryItem*,
- HistoryCommitType,
+ WebHistoryCommitType,
bool content_initiated) {}
virtual void DispatchWillCommitProvisionalLoad() = 0;
virtual void DispatchDidStartProvisionalLoad(DocumentLoader*,
@@ -129,11 +136,12 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
virtual void DispatchDidReceiveTitle(const String&) = 0;
virtual void DispatchDidChangeIcons(IconType) = 0;
virtual void DispatchDidCommitLoad(HistoryItem*,
- HistoryCommitType,
+ WebHistoryCommitType,
WebGlobalObjectReusePolicy) = 0;
virtual void DispatchDidFailProvisionalLoad(const ResourceError&,
- HistoryCommitType) = 0;
- virtual void DispatchDidFailLoad(const ResourceError&, HistoryCommitType) = 0;
+ WebHistoryCommitType) = 0;
+ virtual void DispatchDidFailLoad(const ResourceError&,
+ WebHistoryCommitType) = 0;
virtual void DispatchDidFinishDocumentLoad() = 0;
virtual void DispatchDidFinishLoad() = 0;
virtual void DispatchDidChangeThemeColor() = 0;
@@ -142,7 +150,7 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
const ResourceRequest&,
Document* origin_document,
DocumentLoader*,
- NavigationType,
+ WebNavigationType,
NavigationPolicy,
bool should_replace_current_entry,
bool is_client_redirect,
@@ -161,7 +169,8 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
virtual void ForwardResourceTimingToParent(const WebResourceTimingInfo&) = 0;
- virtual void DownloadURL(const ResourceRequest&) = 0;
+ virtual void DownloadURL(const ResourceRequest&,
+ DownloadCrossOriginRedirects) = 0;
virtual void LoadErrorPage(int reason) = 0;
virtual bool NavigateBackForward(int offset) const = 0;
@@ -227,7 +236,9 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
const ResourceRequest&,
const SubstituteData&,
ClientRedirectPolicy,
- const base::UnguessableToken& devtools_navigation_token) = 0;
+ const base::UnguessableToken& devtools_navigation_token,
+ std::unique_ptr<WebDocumentLoader::ExtraData> extra_data,
+ const WebNavigationTimings& navigation_timings) = 0;
virtual String UserAgent() = 0;
@@ -309,10 +320,6 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
virtual bool ShouldBlockWebGL() { return false; }
- // If an HTML document is being loaded, informs the embedder that the document
- // will have its <body> attached soon.
- virtual void DispatchWillInsertBody() {}
-
virtual std::unique_ptr<WebServiceWorkerProvider>
CreateServiceWorkerProvider() = 0;
@@ -363,7 +370,14 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
return nullptr;
}
- virtual void SetHasReceivedUserGesture() {}
+ // Notify the embedder that the associated frame has user activation so that
+ // the replicated states in the browser and other renderers can be updated.
+ virtual void NotifyUserActivation() {}
+
+ // Tell the embedder that the associated frame has consumed user activation so
+ // that the replicated states in the browser and other renderers can be
+ // updated.
+ virtual void ConsumeUserActivation() {}
virtual void SetHasReceivedUserGestureBeforeNavigation(bool value) {}
@@ -404,6 +418,16 @@ class CORE_EXPORT LocalFrameClient : public FrameClient {
virtual void FrameRectsChanged(const IntRect&) {}
+ // Returns a new WebWorkerFetchContext for a dedicated worker or worklet.
+ virtual std::unique_ptr<WebWorkerFetchContext> CreateWorkerFetchContext() {
+ return nullptr;
+ }
+
+ virtual std::unique_ptr<WebContentSettingsClient>
+ CreateWorkerContentSettingsClient() {
+ return nullptr;
+ }
+
virtual void SetMouseCapture(bool) {}
};
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 351ac278246..1a661a7f0bd 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
@@ -31,15 +31,17 @@
#include <utility>
#include "base/memory/ptr_util.h"
+#include "cc/layers/picture_layer.h"
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_rect.h"
#include "third_party/blink/public/platform/web_scroll_into_view_params.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#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/dom/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/element_visibility_observer.h"
+#include "third_party/blink/renderer/core/dom/static_node_list.h"
#include "third_party/blink/renderer/core/editing/drag_caret.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
@@ -48,12 +50,15 @@
#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
#include "third_party/blink/renderer/core/frame/browser_controls.h"
#include "third_party/blink/renderer/core/frame/event_handler_registry.h"
+#include "third_party/blink/renderer/core/frame/frame_view_auto_size_info.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/location.h"
#include "third_party/blink/renderer/core/frame/page_scale_constraints_set.h"
#include "third_party/blink/renderer/core/frame/remote_frame.h"
#include "third_party/blink/renderer/core/frame/remote_frame_view.h"
+#include "third_party/blink/renderer/core/frame/root_frame_viewport.h"
+#include "third_party/blink/renderer/core/frame/scroll_into_view_options.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/fullscreen/fullscreen.h"
@@ -71,9 +76,8 @@
#include "third_party/blink/renderer/core/layout/layout_counter.h"
#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_scrollbar.h"
-#include "third_party/blink/renderer/core/layout/layout_scrollbar_part.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
#include "third_party/blink/renderer/core/layout/text_autosizer.h"
#include "third_party/blink/renderer/core/layout/traced_layout_object.h"
@@ -95,9 +99,11 @@
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_selection.h"
#include "third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h"
+#include "third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/core/paint/frame_painter.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/paint/paint_timing.h"
#include "third_party/blink/renderer/core/paint/pre_paint_tree_walk.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
@@ -107,6 +113,7 @@
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#include "third_party/blink/renderer/platform/geometry/double_rect.h"
+#include "third_party/blink/renderer/platform/geometry/float_quad.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h"
@@ -126,8 +133,9 @@
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
#include "third_party/blink/renderer/platform/scroll/scroll_alignment.h"
#include "third_party/blink/renderer/platform/scroll/scroll_animator_base.h"
-#include "third_party/blink/renderer/platform/scroll/scrollbar_theme.h"
+#include "third_party/blink/renderer/platform/scroll/smooth_scroll_sequencer.h"
#include "third_party/blink/renderer/platform/transforms/transform_state.h"
+#include "third_party/blink/renderer/platform/ukm_time_aggregator.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
@@ -152,6 +160,10 @@ constexpr int kA4PortraitPageHeight = 842;
constexpr int kLetterPortraitPageWidth = 612;
constexpr int kLetterPortraitPageHeight = 792;
+constexpr char kCssFragmentIdentifierPrefix[] = "targetElement=";
+constexpr size_t kCssFragmentIdentifierPrefixLength =
+ base::size(kCssFragmentIdentifierPrefix);
+
// Changing these values requires changing the names generated in
// EnsureUkmTimeAggregator().
enum class UkmMetricNames {
@@ -188,7 +200,6 @@ using namespace HTMLNames;
// The maximum number of updatePlugins iterations that should be done before
// returning.
static const unsigned kMaxUpdatePluginsIterations = 2;
-static const double kResourcePriorityUpdateDelayAfterScroll = 0.250;
static bool g_initial_track_all_paint_invalidations = false;
@@ -209,33 +220,21 @@ LocalFrameView::LocalFrameView(LocalFrame& frame, IntRect frame_rect)
base_background_color_(Color::kWhite),
media_type_(MediaTypeNames::screen),
safe_to_propagate_scroll_to_parent_(true),
- scroll_corner_(nullptr),
sticky_position_object_count_(0),
input_events_scale_factor_for_emulation_(1),
layout_size_fixed_to_frame_size_(true),
- did_scroll_timer_(frame.GetTaskRunner(TaskType::kInternalDefault),
- this,
- &LocalFrameView::DidScrollTimerFired),
needs_update_geometries_(false),
- horizontal_scrollbar_mode_(kScrollbarAuto),
- vertical_scrollbar_mode_(kScrollbarAuto),
- scrollbars_suppressed_(false),
root_layer_did_scroll_(false),
- in_update_scrollbars_(false),
frame_timing_requests_dirty_(true),
hidden_for_throttling_(false),
subtree_throttled_(false),
lifecycle_updates_throttled_(false),
- needs_paint_property_update_(true),
current_update_lifecycle_phases_target_state_(
DocumentLifecycle::kUninitialized),
past_layout_lifecycle_update_(false),
- scroll_anchor_(this),
- scrollbar_manager_(*this),
- needs_scrollbars_update_(false),
suppress_adjust_view_size_(false),
allows_layout_invalidation_after_layout_clean_(true),
- needs_intersection_observation_(false),
+ intersection_observation_state_(kNotNeeded),
needs_forced_compositing_update_(false),
needs_focus_on_fragment_(false),
main_thread_scrolling_reasons_(0),
@@ -278,11 +277,8 @@ void LocalFrameView::Trace(blink::Visitor* visitor) {
visitor->Trace(scrollbars_);
visitor->Trace(viewport_scrollable_area_);
visitor->Trace(visibility_observer_);
- visitor->Trace(scroll_anchor_);
visitor->Trace(anchoring_adjustment_queue_);
- visitor->Trace(scrollbar_manager_);
visitor->Trace(print_context_);
- ScrollableArea::Trace(visitor);
}
void LocalFrameView::Reset() {
@@ -399,22 +395,9 @@ void LocalFrameView::SetupRenderThrottling() {
void LocalFrameView::Dispose() {
CHECK(!IsInPerformLayout());
- if (ScrollAnimatorBase* scroll_animator = ExistingScrollAnimator())
- scroll_animator->CancelAnimation();
- CancelProgrammaticScrollAnimation();
-
- DetachScrollbars();
-
- if (ScrollingCoordinator* scrolling_coordinator =
- this->GetScrollingCoordinator())
- scrolling_coordinator->WillDestroyScrollableArea(this);
-
- Page* page = frame_->GetPage();
// TODO(dcheng): It's wrong that the frame can be detached before the
// LocalFrameView. Figure out what's going on and fix LocalFrameView to be
// disposed with the correct timing.
- if (page)
- page->GlobalRootScrollerController().DidDisposeScrollableArea(*this);
// We need to clear the RootFrameViewport's animator since it gets called
// from non-GC'd objects and RootFrameViewport will still have a pointer to
@@ -422,14 +405,11 @@ void LocalFrameView::Dispose() {
if (viewport_scrollable_area_)
viewport_scrollable_area_->ClearScrollableArea();
- ClearScrollableArea();
-
// Destroy |m_autoSizeInfo| as early as possible, to avoid dereferencing
// partially destroyed |this| via |m_autoSizeInfo->m_frameView|.
auto_size_info_.Clear();
post_layout_tasks_timer_.Stop();
- did_scroll_timer_.Stop();
// FIXME: Do we need to do something here for OOPI?
HTMLFrameOwnerElement* owner_element = frame_->DeprecatedLocalOwner();
@@ -445,123 +425,13 @@ void LocalFrameView::Dispose() {
ClearPrintContext();
ukm_time_aggregator_.reset();
+ jank_tracker_.Dispose();
#if DCHECK_IS_ON()
has_been_disposed_ = true;
#endif
}
-void LocalFrameView::DetachScrollbars() {
- // Previously, we detached custom scrollbars as early as possible to prevent
- // Document::detachLayoutTree() from messing with the view such that its
- // scroll bars won't be torn down. However, scripting in
- // Document::detachLayoutTree() is forbidden
- // now, so it's not clear if these edge cases can still happen.
- // However, for Oilpan, we still need to remove the native scrollbars before
- // we lose the connection to the ChromeClient, so we just unconditionally
- // detach any scrollbars now.
- scrollbar_manager_.Dispose();
-
- if (scroll_corner_) {
- scroll_corner_->Destroy();
- scroll_corner_ = nullptr;
- }
-}
-
-void LocalFrameView::ScrollbarManager::SetHasHorizontalScrollbar(
- bool has_scrollbar) {
- if (has_scrollbar == HasHorizontalScrollbar())
- return;
-
- if (has_scrollbar) {
- h_bar_ = CreateScrollbar(kHorizontalScrollbar);
- h_bar_is_attached_ = 1;
- scrollable_area_->DidAddScrollbar(*h_bar_, kHorizontalScrollbar);
- h_bar_->StyleChanged();
- } else {
- h_bar_is_attached_ = 0;
- DestroyScrollbar(kHorizontalScrollbar);
- }
-
- scrollable_area_->SetScrollCornerNeedsPaintInvalidation();
-}
-
-void LocalFrameView::ScrollbarManager::SetHasVerticalScrollbar(
- bool has_scrollbar) {
- if (has_scrollbar == HasVerticalScrollbar())
- return;
-
- if (has_scrollbar) {
- v_bar_ = CreateScrollbar(kVerticalScrollbar);
- v_bar_is_attached_ = 1;
- scrollable_area_->DidAddScrollbar(*v_bar_, kVerticalScrollbar);
- v_bar_->StyleChanged();
- } else {
- v_bar_is_attached_ = 0;
- DestroyScrollbar(kVerticalScrollbar);
- }
-
- scrollable_area_->SetScrollCornerNeedsPaintInvalidation();
-}
-
-Scrollbar* LocalFrameView::ScrollbarManager::CreateScrollbar(
- ScrollbarOrientation orientation) {
- Element* custom_scrollbar_element = nullptr;
- LayoutBox* box = scrollable_area_->GetLayoutBox();
- if (box->GetDocument().View()->ShouldUseCustomScrollbars(
- custom_scrollbar_element)) {
- return LayoutScrollbar::CreateCustomScrollbar(
- scrollable_area_.Get(), orientation, custom_scrollbar_element);
- }
-
- // Nobody set a custom style, so we just use a native scrollbar.
- return Scrollbar::Create(scrollable_area_.Get(), orientation,
- kRegularScrollbar,
- &box->GetFrame()->GetPage()->GetChromeClient());
-}
-
-void LocalFrameView::SnapAfterScrollbarDragging(
- ScrollbarOrientation orientation) {
- SnapCoordinator* snap_coordinator =
- frame_->GetDocument()->GetSnapCoordinator();
- if (!snap_coordinator)
- return;
- snap_coordinator->PerformSnapping(*GetLayoutBox(),
- orientation == kHorizontalScrollbar,
- orientation == kVerticalScrollbar);
-}
-
-void LocalFrameView::ScrollbarManager::DestroyScrollbar(
- ScrollbarOrientation orientation) {
- Member<Scrollbar>& scrollbar =
- orientation == kHorizontalScrollbar ? h_bar_ : v_bar_;
- DCHECK(orientation == kHorizontalScrollbar ? !h_bar_is_attached_
- : !v_bar_is_attached_);
- if (!scrollbar)
- return;
-
- scrollable_area_->WillRemoveScrollbar(*scrollbar, orientation);
- scrollbar->DisconnectFromScrollableArea();
- scrollbar = nullptr;
-}
-
-void LocalFrameView::RecalculateCustomScrollbarStyle() {
- bool did_style_change = false;
- if (HorizontalScrollbar() && HorizontalScrollbar()->IsCustomScrollbar()) {
- HorizontalScrollbar()->StyleChanged();
- did_style_change = true;
- }
- if (VerticalScrollbar() && VerticalScrollbar()->IsCustomScrollbar()) {
- VerticalScrollbar()->StyleChanged();
- did_style_change = true;
- }
- if (did_style_change) {
- UpdateScrollbarGeometry();
- UpdateScrollCorner();
- PositionScrollbarLayers();
- }
-}
-
void LocalFrameView::InvalidateAllCustomScrollbarsOnActiveChanged() {
bool uses_window_inactive_selector =
frame_->GetDocument()->GetStyleEngine().UsesWindowInactiveSelector();
@@ -574,9 +444,6 @@ void LocalFrameView::InvalidateAllCustomScrollbarsOnActiveChanged() {
if (uses_window_inactive_selector && scrollbar->IsCustomScrollbar())
scrollbar->StyleChanged();
}
-
- if (uses_window_inactive_selector)
- RecalculateCustomScrollbarStyle();
}
bool LocalFrameView::DidFirstLayout() const {
@@ -587,6 +454,10 @@ bool LocalFrameView::LifecycleUpdatesActive() const {
return !lifecycle_updates_throttled_;
}
+void LocalFrameView::SetLifecycleUpdatesThrottledForTesting() {
+ lifecycle_updates_throttled_ = true;
+}
+
void LocalFrameView::InvalidateRect(const IntRect& rect) {
auto* layout_object = frame_->OwnerLayoutObject();
if (!layout_object)
@@ -607,12 +478,8 @@ void LocalFrameView::SetFrameRect(const IntRect& unclamped_frame_rect) {
const bool height_changed = frame_rect_.Height() != frame_rect.Height();
frame_rect_ = frame_rect;
- needs_scrollbars_update_ |= width_changed || height_changed;
-
FrameRectsChanged();
- UpdateParentScrollableAreaSet();
-
if (auto* layout_view = GetLayoutView())
layout_view->SetMayNeedPaintInvalidation();
@@ -694,93 +561,15 @@ CompositorAnimationTimeline* LocalFrameView::GetCompositorAnimationTimeline()
return c ? c->GetCompositorAnimationTimeline() : nullptr;
}
-LayoutBox* LocalFrameView::GetLayoutBox() const {
- return GetLayoutView();
-}
-
-FloatQuad LocalFrameView::LocalToVisibleContentQuad(
- const FloatQuad& quad,
- const LayoutObject* local_object,
- MapCoordinatesFlags flags) const {
- LayoutBox* box = GetLayoutBox();
- if (!box)
- return quad;
- DCHECK(local_object);
- FloatQuad result = local_object->LocalToAncestorQuad(quad, box, flags);
- result.Move(-GetScrollOffset());
- return result;
-}
-
-scoped_refptr<base::SingleThreadTaskRunner> LocalFrameView::GetTimerTaskRunner()
- const {
- return frame_->GetTaskRunner(TaskType::kInternalDefault);
-}
-
-void LocalFrameView::SetCanHaveScrollbars(bool can_have_scrollbars) {
- can_have_scrollbars_ = can_have_scrollbars;
-
- ScrollbarMode new_vertical_mode = EffectiveVerticalScrollbarMode();
- if (can_have_scrollbars && new_vertical_mode == kScrollbarAlwaysOff)
- new_vertical_mode = kScrollbarAuto;
- else if (!can_have_scrollbars)
- new_vertical_mode = kScrollbarAlwaysOff;
-
- ScrollbarMode new_horizontal_mode = EffectiveHorizontalScrollbarMode();
- if (can_have_scrollbars && new_horizontal_mode == kScrollbarAlwaysOff)
- new_horizontal_mode = kScrollbarAuto;
- else if (!can_have_scrollbars)
- new_horizontal_mode = kScrollbarAlwaysOff;
-
- SetScrollbarModes(new_horizontal_mode, new_vertical_mode);
-}
-
-bool LocalFrameView::ShouldUseCustomScrollbars(
- Element*& custom_scrollbar_element) const {
- custom_scrollbar_element = nullptr;
-
- if (Settings* settings = frame_->GetSettings()) {
- if (!settings->GetAllowCustomScrollbarInMainFrame() &&
- frame_->IsMainFrame())
- return false;
- }
- Document* doc = frame_->GetDocument();
-
- // Try the <body> element first as a scrollbar source.
- Element* body = doc ? doc->body() : nullptr;
- if (body && body->GetLayoutObject() &&
- body->GetLayoutObject()->Style()->HasPseudoStyle(kPseudoIdScrollbar)) {
- custom_scrollbar_element = body;
- return true;
- }
-
- // If the <body> didn't have a custom style, then the root element might.
- Element* doc_element = doc ? doc->documentElement() : nullptr;
- if (doc_element && doc_element->GetLayoutObject() &&
- doc_element->GetLayoutObject()->Style()->HasPseudoStyle(
- kPseudoIdScrollbar)) {
- custom_scrollbar_element = doc_element;
- return true;
- }
-
- return false;
-}
-
-Scrollbar* LocalFrameView::CreateScrollbar(ScrollbarOrientation orientation) {
- return scrollbar_manager_.CreateScrollbar(orientation);
-}
-
void LocalFrameView::SetLayoutOverflowSize(const IntSize& size) {
if (size == layout_overflow_size_)
return;
layout_overflow_size_ = size;
- needs_scrollbars_update_ = true;
- ScrollableArea::ContentsResized();
Page* page = GetFrame().GetPage();
if (!page)
return;
-
page->GetChromeClient().ContentsSizeChanged(frame_.Get(), size);
}
@@ -793,17 +582,7 @@ void LocalFrameView::AdjustViewSize() {
return;
DCHECK_EQ(frame_->View(), this);
-
- const IntRect rect = layout_view->DocumentRect();
- const IntSize& size = rect.Size();
-
- if (!RuntimeEnabledFeatures::RootLayerScrollingEnabled()) {
- const IntPoint origin(-rect.X(), -rect.Y());
- if (ScrollOrigin() != origin)
- SetScrollOrigin(origin);
- }
-
- SetLayoutOverflowSize(size);
+ SetLayoutOverflowSize(layout_view->DocumentRect().Size());
}
void LocalFrameView::AdjustViewSizeAndLayout() {
@@ -820,85 +599,12 @@ void LocalFrameView::UpdateAcceleratedCompositingSettings() {
layout_view->Compositor()->UpdateAcceleratedCompositingSettings();
}
-void LocalFrameView::RecalcOverflowAfterStyleChange() {
- auto* layout_view = this->GetLayoutView();
- CHECK(layout_view);
- if (!layout_view->NeedsOverflowRecalcAfterStyleChange())
- return;
-
- layout_view->RecalcOverflowAfterStyleChange();
-
- // Changing overflow should notify scrolling coordinator to ensures that it
- // updates non-fast scroll rects even if there is no layout.
- if (ScrollingCoordinator* scrolling_coordinator =
- this->GetScrollingCoordinator()) {
- GetScrollingContext()->SetScrollGestureRegionIsDirty(true);
- }
-
- IntRect document_rect = layout_view->DocumentRect();
- if (ScrollOrigin() == -document_rect.Location() &&
- ContentsSize() == document_rect.Size())
- return;
-
- if (NeedsLayout())
- return;
-
- // If the visualViewport supplies scrollbars, we won't get a paint
- // invalidation from computeScrollbarExistence so we need to force one.
- if (VisualViewportSuppliesScrollbars())
- layout_view->SetMayNeedPaintInvalidation();
-
- // TODO(pdr): This should be refactored to just block scrollbar updates as
- // we are not in a scrollbar update here and m_inUpdateScrollbars has other
- // side effects. This scope is only for preventing a synchronous layout from
- // scroll origin changes which would not be allowed during style recalc.
- InUpdateScrollbarsScope in_update_scrollbars_scope(this);
-
- bool should_have_horizontal_scrollbar = false;
- bool should_have_vertical_scrollbar = false;
- ComputeScrollbarExistence(should_have_horizontal_scrollbar,
- should_have_vertical_scrollbar,
- document_rect.Size());
-
- bool has_horizontal_scrollbar = HorizontalScrollbar();
- bool has_vertical_scrollbar = VerticalScrollbar();
- if (has_horizontal_scrollbar != should_have_horizontal_scrollbar ||
- has_vertical_scrollbar != should_have_vertical_scrollbar) {
- SetNeedsLayout();
- return;
- }
-
- AdjustViewSize();
- UpdateScrollbarGeometry();
- SetNeedsPaintPropertyUpdate();
-
- if (ScrollOriginChanged())
- SetNeedsLayout();
-}
-
void LocalFrameView::UpdateCountersAfterStyleChange() {
auto* layout_view = GetLayoutView();
DCHECK(layout_view);
layout_view->UpdateCounters();
}
-bool LocalFrameView::ShouldScrollOnMainThread() const {
- if (GetMainThreadScrollingReasons())
- return true;
- return ScrollableArea::ShouldScrollOnMainThread();
-}
-
-bool LocalFrameView::IsEnclosedInCompositingLayer() const {
- // FIXME: It's a bug that compositing state isn't always up to date when this
- // is called. crbug.com/366314
- DisableCompositingQueryAsserts disabler;
-
- auto* frame_owner_layout_object = frame_->OwnerLayoutObject();
- return frame_owner_layout_object &&
- frame_owner_layout_object->EnclosingLayer()
- ->EnclosingLayerForPaintInvalidationCrossingFrameBoundaries();
-}
-
void LocalFrameView::CountObjectsNeedingLayout(unsigned& needs_layout_objects,
unsigned& total_objects,
bool& is_subtree) {
@@ -955,16 +661,6 @@ void LocalFrameView::PerformPreLayoutTasks() {
if (was_resized)
document->ClearResizedForViewportUnits();
-
- if (ShouldPerformScrollAnchoring())
- scroll_anchor_.NotifyBeforeLayout();
-}
-
-bool LocalFrameView::ShouldPerformScrollAnchoring() const {
- return !RuntimeEnabledFeatures::RootLayerScrollingEnabled() &&
- scroll_anchor_.HasScroller() && GetLayoutBox() &&
- GetLayoutBox()->Style()->OverflowAnchor() != EOverflowAnchor::kNone &&
- !frame_->GetDocument()->FinishingOrIsPrinting();
}
void LocalFrameView::LayoutFromRootObject(LayoutObject& root) {
@@ -979,7 +675,7 @@ void LocalFrameView::LayoutFromRootObject(LayoutObject& root) {
box_object.UpdateLayout();
if (box_object.VisualOverflowRect() != previous_visual_overflow_rect) {
box_object.SetNeedsOverflowRecalcAfterStyleChange();
- RecalcOverflowAfterStyleChange();
+ GetLayoutView()->RecalcOverflowAfterStyleChange();
}
}
}
@@ -1007,7 +703,7 @@ std::unique_ptr<TracedValue> LocalFrameView::AnalyzerCounters() {
String::Format("0x%" PRIxPTR, reinterpret_cast<uintptr_t>(frame_.Get())));
value->SetInteger("contentsHeightAfterLayout",
GetLayoutView()->DocumentRect().Height());
- value->SetInteger("visibleHeight", VisibleHeight());
+ value->SetInteger("visibleHeight", Height());
value->SetInteger("approximateBlankCharacterCount",
FontFaceSetDocument::ApproximateBlankCharacterCount(
*frame_->GetDocument()));
@@ -1067,8 +763,7 @@ void LocalFrameView::PerformLayout(bool in_subtree_layout) {
}
layout_subtree_root_list_.Clear();
} else {
- if (HasOrthogonalWritingModeRoots() &&
- !RuntimeEnabledFeatures::LayoutNGEnabled())
+ if (HasOrthogonalWritingModeRoots())
LayoutOrthogonalWritingModeRoots();
GetLayoutView()->UpdateLayout();
}
@@ -1084,7 +779,7 @@ void LocalFrameView::PerformLayout(bool in_subtree_layout) {
FirstMeaningfulPaintDetector::From(*frame_->GetDocument())
.MarkNextPaintAsMeaningfulIfNeeded(
layout_object_counter_, contents_height_before_layout,
- GetLayoutView()->DocumentRect().Height(), VisibleHeight());
+ GetLayoutView()->DocumentRect().Height(), Height());
}
void LocalFrameView::ScheduleOrPerformPostLayoutTasks() {
@@ -1191,45 +886,21 @@ void LocalFrameView::UpdateLayout() {
}
}
- ScrollbarMode h_mode;
- ScrollbarMode v_mode;
- GetLayoutView()->CalculateScrollbarModes(h_mode, v_mode);
-
- // Now set our scrollbar state for the layout.
- ScrollbarMode current_h_mode = EffectiveHorizontalScrollbarMode();
- ScrollbarMode current_v_mode = EffectiveVerticalScrollbarMode();
-
if (first_layout_) {
- SetScrollbarsSuppressed(true);
-
first_layout_ = false;
- last_viewport_size_ = GetLayoutSize(kIncludeScrollbars);
+ last_viewport_size_ = GetLayoutSize();
last_zoom_factor_ = GetLayoutView()->Style()->Zoom();
- // Set the initial vMode to AlwaysOn if we're auto.
+ ScrollbarMode h_mode;
+ ScrollbarMode v_mode;
+ GetLayoutView()->CalculateScrollbarModes(h_mode, v_mode);
if (v_mode == kScrollbarAuto) {
- // This causes a vertical scrollbar to appear.
- SetVerticalScrollbarMode(kScrollbarAlwaysOn);
- if (RuntimeEnabledFeatures::RootLayerScrollingEnabled()) {
- GetLayoutView()
- ->GetScrollableArea()
- ->ForceVerticalScrollbarForFirstLayout();
- }
+ GetLayoutView()
+ ->GetScrollableArea()
+ ->ForceVerticalScrollbarForFirstLayout();
}
- // Set the initial hMode to AlwaysOff if we're auto.
- if (h_mode == kScrollbarAuto) {
- // This causes a horizontal scrollbar to disappear.
- SetHorizontalScrollbarMode(kScrollbarAlwaysOff);
- }
-
- SetScrollbarModes(h_mode, v_mode);
- SetScrollbarsSuppressed(false);
- } else if (h_mode != current_h_mode || v_mode != current_v_mode) {
- SetScrollbarModes(h_mode, v_mode);
}
- UpdateScrollbarsIfNeeded();
-
LayoutSize old_size = size_;
size_ = LayoutSize(GetLayoutSize());
@@ -1258,12 +929,8 @@ void LocalFrameView::UpdateLayout() {
PerformLayout(in_subtree_layout);
- UpdateScrollbars();
- UpdateParentScrollableAreaSet();
-
IntSize new_size(Size());
if (old_size != new_size) {
- needs_scrollbars_update_ = true;
SetNeedsLayout();
MarkViewportConstrainedObjectsForLayout(
old_size.Width() != new_size.Width(),
@@ -1338,17 +1005,11 @@ void LocalFrameView::UpdateLayout() {
}
void LocalFrameView::SetNeedsPaintPropertyUpdate() {
- needs_paint_property_update_ = true;
- if (auto* layout_view = this->GetLayoutView()) {
+ if (auto* layout_view = GetLayoutView())
layout_view->SetNeedsPaintPropertyUpdate();
- return;
- }
- if (LayoutObject* owner = GetFrame().OwnerLayoutObject())
- owner->SetNeedsPaintPropertyUpdate();
}
void LocalFrameView::SetSubtreeNeedsPaintPropertyUpdate() {
- SetNeedsPaintPropertyUpdate();
if (auto* layout_view = GetLayoutView())
layout_view->SetSubtreeNeedsPaintPropertyUpdate();
}
@@ -1367,7 +1028,7 @@ FloatSize LocalFrameView::ViewportSizeForViewportUnits() const {
layout_size.SetHeight(layout_view->ViewHeight(kIncludeScrollbars) / zoom);
BrowserControls& browser_controls = frame_->GetPage()->GetBrowserControls();
- if (browser_controls.PermittedState() != kWebBrowserControlsHidden) {
+ if (browser_controls.PermittedState() != cc::BrowserControlsState::kHidden) {
// We use the layoutSize rather than frameRect to calculate viewport units
// so that we get correct results on mobile where the page is laid out into
// a rect that may be larger than the viewport (e.g. the 980px fallback
@@ -1390,7 +1051,7 @@ FloatSize LocalFrameView::ViewportSizeForViewportUnits() const {
}
FloatSize LocalFrameView::ViewportSizeForMediaQueries() const {
- FloatSize viewport_size(GetLayoutSize(kIncludeScrollbars));
+ FloatSize viewport_size(GetLayoutSize());
if (!frame_->GetDocument() || !frame_->GetDocument()->Printing())
viewport_size.Scale(1 / GetFrame().PageZoomFactor());
return viewport_size;
@@ -1444,7 +1105,7 @@ void LocalFrameView::UpdateGeometry() {
// frame's page to make sure that the frame isn't in the process of being
// destroyed. If iframe scrollbars needs reconstruction from native to custom
// scrollbar, then also we need to layout the frameview.
- if (bounds_will_change || NeedsScrollbarReconstruction())
+ if (bounds_will_change)
SetNeedsLayout();
layout->UpdateGeometry(*this);
@@ -1519,12 +1180,6 @@ void LocalFrameView::AdjustMediaTypeForPrinting(bool printing) {
StyleChangeReason::kStyleSheetChange));
}
-bool LocalFrameView::ContentsInCompositedLayer() const {
- auto* layout_view = this->GetLayoutView();
- return layout_view &&
- layout_view->GetCompositingState() == kPaintsIntoOwnBacking;
-}
-
void LocalFrameView::AddBackgroundAttachmentFixedObject(LayoutObject* object) {
DCHECK(!background_attachment_fixed_objects_.Contains(object));
@@ -1592,36 +1247,24 @@ void LocalFrameView::ViewportSizeChanged(bool width_changed,
frame_->GetDocument()->Lifecycle().LifecyclePostponed())
return;
- bool root_layer_scrolling_enabled =
- RuntimeEnabledFeatures::RootLayerScrollingEnabled();
-
if (LayoutView* layout_view = this->GetLayoutView()) {
// If this is the main frame, we might have got here by hiding/showing the
// top controls. In that case, layout won't be triggered, so we need to
// clamp the scroll offset here.
if (GetFrame().IsMainFrame()) {
- if (root_layer_scrolling_enabled) {
- layout_view->Layer()->UpdateSize();
- layout_view->GetScrollableArea()
- ->ClampScrollOffsetAfterOverflowChange();
- } else {
- AdjustScrollOffsetFromUpdateScrollbars();
- }
+ layout_view->Layer()->UpdateSize();
+ layout_view->GetScrollableArea()->ClampScrollOffsetAfterOverflowChange();
}
if (layout_view->UsesCompositing()) {
- if (root_layer_scrolling_enabled) {
- layout_view->Layer()->SetNeedsCompositingInputsUpdate();
- SetNeedsPaintPropertyUpdate();
- }
+ layout_view->Layer()->SetNeedsCompositingInputsUpdate();
+ SetNeedsPaintPropertyUpdate();
}
}
if (GetFrame().GetDocument())
GetFrame().GetDocument()->GetRootScrollerController().DidResizeFrameView();
- ShowOverlayScrollbars();
-
if (GetLayoutView() && frame_->IsMainFrame() &&
frame_->GetPage()->GetBrowserControls().TotalHeight()) {
if (GetLayoutView()->Style()->HasFixedBackgroundImage()) {
@@ -1678,10 +1321,6 @@ void LocalFrameView::MarkViewportConstrainedObjectsForLayout(
}
}
-IntPoint LocalFrameView::LastKnownMousePosition() const {
- return frame_->GetEventHandler().LastKnownMousePositionInRootFrame();
-}
-
bool LocalFrameView::ShouldSetCursor() const {
Page* page = GetFrame().GetPage();
return page &&
@@ -1696,11 +1335,6 @@ void LocalFrameView::NotifyFrameRectsChangedIfNeededRecursive() {
});
}
-void LocalFrameView::ScrollContentsIfNeededRecursive() {
- ForAllNonThrottledLocalFrameViews(
- [](LocalFrameView& frame_view) { frame_view.ScrollContentsIfNeeded(); });
-}
-
void LocalFrameView::InvalidateBackgroundAttachmentFixedDescendants(
const LayoutObject& object) {
for (auto* const layout_object : background_attachment_fixed_objects_) {
@@ -1762,7 +1396,6 @@ bool LocalFrameView::InvalidateViewportConstrainedObjects() {
// layer->SubtreeIsInvisible() here.
layout_object->SetMayNeedPaintInvalidationSubtree();
if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled() &&
- RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
!layer->NeedsRepaint()) {
// Paint properties of the layer relative to its containing graphics
// layer may change if the paint properties escape the graphics layer's
@@ -1792,56 +1425,6 @@ bool LocalFrameView::InvalidateViewportConstrainedObjects() {
return fast_path_allowed;
}
-bool LocalFrameView::ScrollContentsFastPath(const IntSize& scroll_delta) {
- if (!ContentsInCompositedLayer())
- return false;
-
- InvalidateBackgroundAttachmentFixedDescendants(*GetLayoutView());
-
- if (!viewport_constrained_objects_ ||
- viewport_constrained_objects_->IsEmpty()) {
- probe::didChangeViewport(frame_.Get());
- return true;
- }
-
- if (!InvalidateViewportConstrainedObjects())
- return false;
-
- probe::didChangeViewport(frame_.Get());
- return true;
-}
-
-void LocalFrameView::ScrollContentsSlowPath() {
- TRACE_EVENT0("blink", "LocalFrameView::scrollContentsSlowPath");
- // We need full invalidation during slow scrolling. For slimming paint, full
- // invalidation of the LayoutView is not enough. We also need to invalidate
- // all of the objects.
- // FIXME: Find out what are enough to invalidate in slow path scrolling.
- // crbug.com/451090#9.
- auto* layout_view = GetLayoutView();
- DCHECK(layout_view);
- if (ContentsInCompositedLayer()) {
- layout_view->Layer()->GetCompositedLayerMapping()->SetContentsNeedDisplay();
- } else {
- layout_view
- ->SetShouldDoFullPaintInvalidationIncludingNonCompositingDescendants();
- }
-
- if (ContentsInCompositedLayer()) {
- IntRect update_rect = VisibleContentRect();
- layout_view->InvalidatePaintRectangle(LayoutRect(update_rect));
- }
-}
-
-void LocalFrameView::RestoreScrollbar() {
- SetScrollbarsSuppressed(false);
-}
-
-bool LocalFrameView::RestoreScrollAnchor(
- const SerializedAnchor& serialized_anchor) {
- return false;
-}
-
void LocalFrameView::ProcessUrlFragment(const KURL& url,
UrlFragmentBehavior behavior) {
// If our URL has no ref, then we have no place we need to jump to.
@@ -1917,7 +1500,15 @@ bool LocalFrameView::ProcessUrlFragmentHelper(const String& name,
UrlFragmentBehavior behavior) {
DCHECK(frame_->GetDocument());
- Element* anchor_node = frame_->GetDocument()->FindAnchor(name);
+ Element* anchor_node;
+ String selector;
+ if (RuntimeEnabledFeatures::CSSFragmentIdentifiersEnabled() &&
+ ParseCSSFragmentIdentifier(name, &selector)) {
+ anchor_node =
+ FindCSSFragmentAnchor(AtomicString(selector), frame_->GetDocument());
+ } else {
+ anchor_node = frame_->GetDocument()->FindAnchor(name);
+ }
// Setting to null will clear the current target.
frame_->GetDocument()->SetCSSTarget(anchor_node);
@@ -1968,42 +1559,25 @@ bool LocalFrameView::ProcessUrlFragmentHelper(const String& name,
return true;
}
-void LocalFrameView::ClearFragmentAnchor() {
- fragment_anchor_ = nullptr;
+Element* LocalFrameView::FindCSSFragmentAnchor(const AtomicString& selector,
+ Document* document) {
+ DummyExceptionStateForTesting exception_state;
+ return document->QuerySelector(selector, exception_state);
}
-void LocalFrameView::DidUpdateElasticOverscroll() {
- Page* page = GetFrame().GetPage();
- if (!page)
- return;
- FloatSize elastic_overscroll = page->GetChromeClient().ElasticOverscroll();
- if (HorizontalScrollbar()) {
- float delta =
- elastic_overscroll.Width() - HorizontalScrollbar()->ElasticOverscroll();
- if (delta != 0) {
- HorizontalScrollbar()->SetElasticOverscroll(elastic_overscroll.Width());
- GetScrollAnimator().NotifyContentAreaScrolled(FloatSize(delta, 0),
- kCompositorScroll);
- SetScrollbarNeedsPaintInvalidation(kHorizontalScrollbar);
- }
- }
- if (VerticalScrollbar()) {
- float delta =
- elastic_overscroll.Height() - VerticalScrollbar()->ElasticOverscroll();
- if (delta != 0) {
- VerticalScrollbar()->SetElasticOverscroll(elastic_overscroll.Height());
- GetScrollAnimator().NotifyContentAreaScrolled(FloatSize(0, delta),
- kCompositorScroll);
- SetScrollbarNeedsPaintInvalidation(kVerticalScrollbar);
- }
+bool LocalFrameView::ParseCSSFragmentIdentifier(const String& fragment,
+ String* selector) {
+ size_t pos = fragment.Find(kCssFragmentIdentifierPrefix);
+ if (pos == 0) {
+ *selector = fragment.Substring(kCssFragmentIdentifierPrefixLength - 1);
+ return true;
}
+
+ return false;
}
-IntSize LocalFrameView::GetLayoutSize(
- IncludeScrollbarsInRect scrollbar_inclusion) const {
- return scrollbar_inclusion == kExcludeScrollbars
- ? ExcludeScrollbars(layout_size_)
- : layout_size_;
+void LocalFrameView::ClearFragmentAnchor() {
+ fragment_anchor_ = nullptr;
}
void LocalFrameView::SetLayoutSize(const IntSize& size) {
@@ -2024,60 +1598,6 @@ void LocalFrameView::SetLayoutSizeFixedToFrameSize(bool is_fixed) {
SetLayoutSizeInternal(Size());
}
-void LocalFrameView::DidScrollTimerFired(TimerBase*) {
- if (frame_->GetDocument() && frame_->GetDocument()->GetLayoutView())
- frame_->GetDocument()->Fetcher()->UpdateAllImageResourcePriorities();
-
- GetFrame().Loader().SaveScrollAnchor();
-}
-
-void LocalFrameView::UpdateLayersAndCompositingAfterScrollIfNeeded() {
- // Nothing to do after scrolling if there are no fixed position elements.
- if (!HasViewportConstrainedObjects())
- return;
-
- // Update sticky position objects which are stuck to the viewport. In order to
- // correctly compute the sticky position offsets the layers must be visited
- // top-down, so start at the 'root' sticky elements and recurse downwards.
- for (auto* const viewport_constrained_object :
- *viewport_constrained_objects_) {
- LayoutObject* layout_object = viewport_constrained_object;
- if (layout_object->Style()->GetPosition() != EPosition::kSticky)
- continue;
-
- PaintLayer* layer = ToLayoutBoxModelObject(layout_object)->Layer();
-
- // This method can be called during layout at which point the ancestor
- // overflow layer may not be set yet. We can safely skip such cases as we
- // will revisit this method during compositing inputs update.
- if (!layer->AncestorOverflowLayer())
- continue;
-
- const StickyConstraintsMap& constraints_map =
- layer->AncestorOverflowLayer()
- ->GetScrollableArea()
- ->GetStickyConstraintsMap();
- if (constraints_map.Contains(layer) &&
- !constraints_map.at(layer).HasAncestorStickyElement()) {
- // TODO(skobes): Resolve circular dependency between scroll offset and
- // compositing state, and remove this disabler. https://crbug.com/420741
- DisableCompositingQueryAsserts disabler;
- layer->UpdateLayerPositionsAfterOverflowScroll();
- layout_object->SetMayNeedPaintInvalidationSubtree();
- SetNeedsUpdateGeometries();
- }
- }
-
- // If there fixed position elements, scrolling may cause compositing layers to
- // change. Update LocalFrameView and layer positions after scrolling, but
- // only if we're not inside of layout.
- if (!nested_layout_count_) {
- UpdateGeometriesIfNeeded();
- if (auto* layout_view = this->GetLayoutView())
- layout_view->Layer()->SetNeedsCompositingInputsUpdate();
- }
-}
-
static CompositedSelection ComputeCompositedSelection(LocalFrame& frame) {
if (!frame.View() || frame.View()->ShouldThrottleRendering())
return {};
@@ -2131,50 +1651,13 @@ void LocalFrameView::SetNeedsCompositingUpdate(
}
}
-ChromeClient* LocalFrameView::GetChromeClient() const {
+PlatformChromeClient* LocalFrameView::GetChromeClient() const {
Page* page = GetFrame().GetPage();
if (!page)
return nullptr;
return &page->GetChromeClient();
}
-SmoothScrollSequencer* LocalFrameView::GetSmoothScrollSequencer() const {
- Page* page = GetFrame().GetPage();
- if (!page)
- return nullptr;
- return page->GetSmoothScrollSequencer();
-}
-
-void LocalFrameView::ContentsResized() {
- if (frame_->IsMainFrame() && frame_->GetDocument()) {
- if (TextAutosizer* text_autosizer =
- frame_->GetDocument()->GetTextAutosizer())
- text_autosizer->UpdatePageInfoInAllFrames();
- }
-
- ScrollableArea::ContentsResized();
- SetNeedsLayout();
-}
-
-void LocalFrameView::ScrollbarExistenceMaybeChanged() {
- // We check to make sure the view is attached to a frame() as this method can
- // be triggered before the view is attached by LocalFrame::createView(...)
- // setting various values such as setScrollBarModes(...) for example. An
- // ASSERT is triggered when a view is layout before being attached to a
- // frame().
- if (!GetFrame().View())
- return;
-
- Element* custom_scrollbar_element = nullptr;
-
- bool uses_overlay_scrollbars =
- GetPageScrollbarTheme().UsesOverlayScrollbars() &&
- !ShouldUseCustomScrollbars(custom_scrollbar_element);
-
- if (!uses_overlay_scrollbars && NeedsLayout())
- UpdateLayout();
-}
-
void LocalFrameView::HandleLoadCompleted() {
// Once loading has completed, allow autoSize one last opportunity to
// reduce the size of the frame.
@@ -2235,6 +1718,11 @@ static bool PrepareOrthogonalWritingModeRootForLayout(LayoutObject& root) {
ToLayoutBox(root).IsGridItem() || root.IsTablePart())
return false;
+ // Do not lay out objects managed by LayoutNG.
+ if (RuntimeEnabledFeatures::LayoutNGEnabled() &&
+ (root.IsLayoutBlock() && IsLayoutNGContainingBlock(ToLayoutBlock(&root))))
+ return false;
+
RemoveFloatingObjectsForSubtreeRoot(root);
return true;
}
@@ -2391,7 +1879,6 @@ void LocalFrameView::SetBaseBackgroundColor(const Color& background_color) {
composited_layer_mapping->ScrollingContentsLayer()->SetNeedsDisplay();
}
}
- RecalculateScrollbarOverlayColorTheme(DocumentBackgroundColor());
if (!ShouldThrottleRendering())
GetPage()->Animator().ScheduleVisualUpdate(frame_.Get());
@@ -2410,17 +1897,11 @@ void LocalFrameView::ScrollAndFocusFragmentAnchor() {
if (!anchor_node)
return;
- // Scrolling is disabled during updateScrollbars (see
- // isProgrammaticallyScrollable). Bail now to avoid clearing m_fragmentAnchor
- // before we actually have a chance to scroll.
- if (in_update_scrollbars_)
- return;
-
if (anchor_node->GetLayoutObject()) {
LayoutRect rect;
if (anchor_node != frame_->GetDocument()) {
rect = anchor_node->BoundingBoxForScrollIntoView();
- } else if (RuntimeEnabledFeatures::RootLayerScrollingEnabled()) {
+ } else {
if (Element* document_element = frame_->GetDocument()->documentElement())
rect = document_element->BoundingBoxForScrollIntoView();
}
@@ -2434,11 +1915,15 @@ void LocalFrameView::ScrollAndFocusFragmentAnchor() {
->SetSafeToPropagateScrollToParent(false);
}
- // Scroll nested layers and frames to reveal the anchor.
- // Align to the top and to the closest side (this matches other browsers).
- anchor_node->GetLayoutObject()->ScrollRectToVisible(
- rect, WebScrollIntoViewParams(ScrollAlignment::kAlignToEdgeIfNeeded,
- ScrollAlignment::kAlignTopAlways));
+ Element* anchor_element = anchor_node->IsElementNode()
+ ? ToElement(anchor_node)
+ : frame_->GetDocument()->documentElement();
+ if (anchor_element) {
+ ScrollIntoViewOptions options;
+ options.setBlock("start");
+ options.setInlinePosition("nearest");
+ anchor_element->ScrollIntoViewNoVisualUpdate(options);
+ }
if (boundary_frame && boundary_frame->IsLocalFrame()) {
ToLocalFrame(boundary_frame)
@@ -2587,7 +2072,7 @@ bool LocalFrameView::WasViewportResized() {
auto* layout_view = GetLayoutView();
if (!layout_view)
return false;
- return (GetLayoutSize(kIncludeScrollbars) != last_viewport_size_ ||
+ return (GetLayoutSize() != last_viewport_size_ ||
layout_view->StyleRef().Zoom() != last_zoom_factor_);
}
@@ -2601,7 +2086,7 @@ void LocalFrameView::SendResizeEventIfNeeded() {
if (!WasViewportResized())
return;
- last_viewport_size_ = GetLayoutSize(kIncludeScrollbars);
+ last_viewport_size_ = GetLayoutSize();
last_zoom_factor_ = layout_view->StyleRef().Zoom();
if (RuntimeEnabledFeatures::VisualViewportAPIEnabled())
@@ -2617,38 +2102,6 @@ void LocalFrameView::PostLayoutTimerFired(TimerBase*) {
PerformPostLayoutTasks();
}
-bool LocalFrameView::ShouldUseIntegerScrollOffset() const {
- if (frame_->GetSettings() &&
- !frame_->GetSettings()->GetPreferCompositingToLCDTextEnabled())
- return true;
-
- return ScrollableArea::ShouldUseIntegerScrollOffset();
-}
-
-bool LocalFrameView::IsActive() const {
- Page* page = GetFrame().GetPage();
- return page && page->GetFocusController().IsActive();
-}
-
-void LocalFrameView::InvalidatePaintForTickmarks() {
- ScrollableArea* scrollable_area = LayoutViewportScrollableArea();
- if (!scrollable_area)
- return;
- if (Scrollbar* scrollbar = scrollable_area->VerticalScrollbar()) {
- scrollbar->SetNeedsPaintInvalidation(
- static_cast<ScrollbarPart>(~kThumbPart));
- }
-}
-
-void LocalFrameView::GetTickmarks(Vector<IntRect>& tickmarks) const {
- if (!tickmarks_.IsEmpty()) {
- tickmarks = tickmarks_;
- return;
- }
- tickmarks =
- GetFrame().GetDocument()->Markers().LayoutRectsForTextMatchMarkers();
-}
-
void LocalFrameView::SetInputEventsScaleForEmulation(
float content_scale_factor) {
input_events_scale_factor_for_emulation_ = content_scale_factor;
@@ -2659,125 +2112,11 @@ float LocalFrameView::InputEventsScaleFactor() const {
return page_scale * input_events_scale_factor_for_emulation_;
}
-bool LocalFrameView::ScrollbarsCanBeActive() const {
- if (frame_->View() != this)
- return false;
-
- return !!frame_->GetDocument();
-}
-
-void LocalFrameView::ScrollbarVisibilityChanged() {
- UpdateScrollbarEnabledState();
- if (auto* layout_view = GetLayoutView())
- layout_view->ClearHitTestCache();
-}
-
-void LocalFrameView::ScrollbarFrameRectChanged() {
- SetNeedsPaintPropertyUpdate();
-}
-
-IntRect LocalFrameView::ScrollableAreaBoundingBox() const {
- auto* owner_layout_object = GetFrame().OwnerLayoutObject();
- if (!owner_layout_object)
- return FrameRect();
-
- LocalFrameView* local_root = GetFrame().LocalFrameRoot().View();
- return local_root->RootFrameToDocument(local_root->AbsoluteToRootFrame(
- owner_layout_object->AbsoluteContentQuad(kTraverseDocumentBoundaries)
- .EnclosingBoundingBox()));
-}
-
-bool LocalFrameView::IsScrollable() const {
- return GetScrollingReasons() == kScrollable;
-}
-
-bool LocalFrameView::IsProgrammaticallyScrollable() {
- return !in_update_scrollbars_;
-}
-
-LocalFrameView::ScrollingReasons LocalFrameView::GetScrollingReasons() const {
- // Check for:
- // 1) If there an actual overflow.
- // 2) display:none or visibility:hidden set to self or inherited.
- // 3) overflow{-x,-y}: hidden;
- // 4) scrolling: no;
-
- // Covers #1
- IntSize contents_size;
- if (GetLayoutView())
- contents_size = GetLayoutView()->DocumentRect().Size();
- else
- contents_size = ContentsSize();
-
- IntSize visible_content_size = VisibleContentSize();
- if (contents_size.Height() <= visible_content_size.Height() &&
- contents_size.Width() <= visible_content_size.Width())
- return kNotScrollableNoOverflow;
-
- // Covers #2.
- // FIXME: Do we need to fix this for OOPI?
- HTMLFrameOwnerElement* owner = frame_->DeprecatedLocalOwner();
- if (owner && (!owner->GetLayoutObject() ||
- !owner->GetLayoutObject()->VisibleToHitTesting()))
- return kNotScrollableNotVisible;
-
- // Cover #3 and #4.
- ScrollbarMode horizontal_mode;
- ScrollbarMode vertical_mode;
- GetLayoutView()->CalculateScrollbarModes(horizontal_mode, vertical_mode);
- if (horizontal_mode == kScrollbarAlwaysOff &&
- vertical_mode == kScrollbarAlwaysOff)
- return kNotScrollableExplicitlyDisabled;
-
- return kScrollable;
-}
-
-void LocalFrameView::UpdateParentScrollableAreaSet() {
- if (RuntimeEnabledFeatures::RootLayerScrollingEnabled())
- return;
-
- // That ensures that only inner frames are cached.
- LocalFrameView* parent_frame_view = ParentFrameView();
- if (!parent_frame_view)
- return;
-
- if (!IsScrollable()) {
- parent_frame_view->RemoveScrollableArea(this);
- return;
- }
-
- parent_frame_view->AddScrollableArea(this);
-}
-
-bool LocalFrameView::ShouldSuspendScrollAnimations() const {
- return !frame_->GetDocument()->LoadEventFinished();
-}
-
-void LocalFrameView::ScrollbarStyleChanged() {
- // FIXME: Why does this only apply to the main frame?
- if (!frame_->IsMainFrame())
- return;
- AdjustScrollbarOpacity();
- ContentsResized();
- UpdateScrollbars();
- PositionScrollbarLayers();
-}
-
-bool LocalFrameView::ScheduleAnimation() {
- if (ChromeClient* client = GetChromeClient()) {
- client->ScheduleAnimation(this);
- return true;
- }
- return false;
-}
-
void LocalFrameView::NotifyPageThatContentAreaWillPaint() const {
Page* page = frame_->GetPage();
if (!page)
return;
- ContentAreaWillPaint();
-
if (!scrollable_areas_)
return;
@@ -2789,20 +2128,6 @@ void LocalFrameView::NotifyPageThatContentAreaWillPaint() const {
}
}
-CompositorElementId LocalFrameView::GetCompositorElementId() const {
- if (!RuntimeEnabledFeatures::RootLayerScrollingEnabled()) {
- return CompositorElementIdFromUniqueObjectId(
- unique_id_, CompositorElementIdNamespace::kScroll);
- } else {
- return PaintInvalidationCapableScrollableArea::GetCompositorElementId();
- }
-}
-
-bool LocalFrameView::ScrollAnimatorEnabled() const {
- return frame_->GetSettings() &&
- frame_->GetSettings()->GetScrollAnimatorEnabled();
-}
-
void LocalFrameView::UpdateDocumentAnnotatedRegions() const {
Document* document = frame_->GetDocument();
if (!document->HasAnnotatedRegions())
@@ -2825,7 +2150,7 @@ void LocalFrameView::DidAttachDocument() {
if (frame_->IsMainFrame()) {
ScrollableArea& visual_viewport = frame_->GetPage()->GetVisualViewport();
- ScrollableArea* layout_viewport = LayoutViewportScrollableArea();
+ ScrollableArea* layout_viewport = LayoutViewport();
DCHECK(layout_viewport);
RootFrameViewport* root_frame_viewport =
@@ -2837,55 +2162,6 @@ void LocalFrameView::DidAttachDocument() {
}
}
-void LocalFrameView::UpdateScrollCorner() {
- scoped_refptr<ComputedStyle> corner_style;
- IntRect corner_rect = ScrollCornerRect();
- Document* doc = frame_->GetDocument();
-
- if (doc && !corner_rect.IsEmpty()) {
- // Try the <body> element first as a scroll corner source.
- if (Element* body = doc->body()) {
- if (LayoutObject* layout_object = body->GetLayoutObject()) {
- corner_style = layout_object->GetUncachedPseudoStyle(
- PseudoStyleRequest(kPseudoIdScrollbarCorner),
- layout_object->Style());
- }
- }
-
- if (!corner_style) {
- // If the <body> didn't have a custom style, then the root element might.
- if (Element* doc_element = doc->documentElement()) {
- if (LayoutObject* layout_object = doc_element->GetLayoutObject()) {
- corner_style = layout_object->GetUncachedPseudoStyle(
- PseudoStyleRequest(kPseudoIdScrollbarCorner),
- layout_object->Style());
- }
- }
- }
-
- if (!corner_style) {
- // If we have an owning ipage/LocalFrame element, then it can set the
- // custom scrollbar also.
- auto* layout_object = frame_->OwnerLayoutObject();
- if (layout_object) {
- corner_style = layout_object->GetUncachedPseudoStyle(
- PseudoStyleRequest(kPseudoIdScrollbarCorner),
- layout_object->Style());
- }
- }
- }
-
- if (corner_style) {
- if (!scroll_corner_)
- scroll_corner_ = LayoutScrollbarPart::CreateAnonymous(doc, this);
- scroll_corner_->SetStyleWithWritingModeOfParent(std::move(corner_style));
- SetScrollCornerNeedsPaintInvalidation();
- } else if (scroll_corner_) {
- scroll_corner_->Destroy();
- scroll_corner_ = nullptr;
- }
-}
-
Color LocalFrameView::DocumentBackgroundColor() const {
// The LayoutView's background color is set in
// Document::inheritHtmlAndBodyElementStyles. Blend this with the base
@@ -2916,44 +2192,9 @@ LocalFrameView* LocalFrameView::ParentFrameView() const {
return nullptr;
}
-void LocalFrameView::DidChangeGlobalRootScroller() {
- // Being the global root scroller will affect clipping size due to browser
- // controls behavior so we need to update compositing based on updated clip
- // geometry.
- SetNeedsCompositingUpdate(kCompositingUpdateAfterGeometryChange);
- SetNeedsPaintPropertyUpdate();
-
- // Avoid drawing two sets of scrollbars when visual viewport provides
- // scrollbars.
- if (frame_->GetSettings() && frame_->GetSettings()->GetViewportEnabled())
- VisualViewportScrollbarsChanged();
-}
-
-// TODO(pdr): This logic is similar to adjustScrollbarExistence and the common
-// logic should be factored into a helper.
void LocalFrameView::VisualViewportScrollbarsChanged() {
- bool has_horizontal_scrollbar = HorizontalScrollbar();
- bool has_vertical_scrollbar = VerticalScrollbar();
- bool should_have_horizontal_scrollbar = false;
- bool should_have_vertical_scrollbar = false;
- ComputeScrollbarExistence(should_have_horizontal_scrollbar,
- should_have_vertical_scrollbar, ContentsSize());
- scrollbar_manager_.SetHasHorizontalScrollbar(
- should_have_horizontal_scrollbar);
- scrollbar_manager_.SetHasVerticalScrollbar(should_have_vertical_scrollbar);
-
- if (has_horizontal_scrollbar != should_have_horizontal_scrollbar ||
- has_vertical_scrollbar != should_have_vertical_scrollbar) {
- ScrollbarExistenceMaybeChanged();
-
- if (!VisualViewportSuppliesScrollbars())
- UpdateScrollbarGeometry();
- }
-
- if (RuntimeEnabledFeatures::RootLayerScrollingEnabled()) {
- if (LayoutView* layout_view = GetLayoutView())
- layout_view->Layer()->ClearClipRects();
- }
+ if (LayoutView* layout_view = GetLayoutView())
+ layout_view->Layer()->ClearClipRects();
}
void LocalFrameView::UpdateGeometriesIfNeeded() {
@@ -2979,15 +2220,6 @@ void LocalFrameView::UpdateAllLifecyclePhases() {
DocumentLifecycle::kPaintClean);
}
-bool LocalFrameView::UpdateLifecycleToPrePaintClean() {
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- return UpdateAllLifecyclePhasesExceptPaint();
- } else {
- return GetFrame().LocalFrameRoot().View()->UpdateLifecyclePhasesInternal(
- DocumentLifecycle::kPrePaintClean);
- }
-}
-
// TODO(chrishtr): add a scrolling update lifecycle phase.
bool LocalFrameView::UpdateLifecycleToCompositingCleanPlusScrolling() {
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
@@ -3076,8 +2308,7 @@ void LocalFrameView::NotifyResizeObservers() {
SourceLocation::Capture(frame_->GetDocument()), nullptr);
frame_->GetDocument()->DispatchErrorEvent(error, kNotSharableCrossOrigin);
// Ensure notifications will get delivered in next cycle.
- if (LocalFrameView* frame_view = frame_->View())
- frame_view->ScheduleAnimation();
+ ScheduleAnimation();
}
DCHECK(!GetLayoutView()->NeedsLayout());
@@ -3148,8 +2379,7 @@ bool LocalFrameView::UpdateLifecyclePhasesInternal(
&current_update_lifecycle_phases_target_state_, target_state);
if (ShouldThrottleRendering()) {
- UpdateViewportIntersectionsForSubtree(
- std::min(target_state, DocumentLifecycle::kCompositingClean));
+ UpdateThrottlingStatusForSubtree();
return Lifecycle().GetState() == target_state;
}
@@ -3179,7 +2409,7 @@ bool LocalFrameView::UpdateLifecyclePhasesInternal(
}
if (target_state == DocumentLifecycle::kLayoutClean) {
- UpdateViewportIntersectionsForSubtree(target_state);
+ UpdateThrottlingStatusForSubtree();
return Lifecycle().GetState() == target_state;
}
@@ -3189,7 +2419,9 @@ bool LocalFrameView::UpdateLifecyclePhasesInternal(
// OOPIF local frame roots that are throttled can return now that layout
// is clean and intersection observations can be calculated.
if (ShouldThrottleRendering()) {
- UpdateViewportIntersectionsForSubtree(target_state);
+ if (target_state == DocumentLifecycle::kPaintClean)
+ UpdateViewportIntersectionsForSubtree();
+ UpdateThrottlingStatusForSubtree();
return Lifecycle().GetState() == target_state;
}
@@ -3201,13 +2433,14 @@ bool LocalFrameView::UpdateLifecyclePhasesInternal(
ForAllNonThrottledLocalFrameViews(
[](LocalFrameView& frame_view) { frame_view.NotifyResizeObservers(); });
- if (RuntimeEnabledFeatures::RootLayerScrollingEnabled())
- NotifyFrameRectsChangedIfNeededRecursive();
+ NotifyFrameRectsChangedIfNeededRecursive();
}
if (auto* layout_view = GetLayoutView()) {
- ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
- frame_view.CheckDoesNotNeedLayout();
+ allows_layout_invalidation_after_layout_clean_ = false;
+ ForAllChildLocalFrameViews([](LocalFrameView& frame_view) {
+ if (!frame_view.ShouldThrottleRendering())
+ frame_view.CheckDoesNotNeedLayout();
frame_view.allows_layout_invalidation_after_layout_clean_ = false;
});
@@ -3230,21 +2463,11 @@ bool LocalFrameView::UpdateLifecyclePhasesInternal(
}
if (target_state >= DocumentLifecycle::kCompositingClean) {
- if (!RuntimeEnabledFeatures::RootLayerScrollingEnabled())
- ScrollContentsIfNeededRecursive();
-
frame_->GetPage()->GlobalRootScrollerController().DidUpdateCompositing(
*this);
}
if (target_state >= DocumentLifecycle::kPrePaintClean) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- if (layout_view->Compositor()->InCompositingMode()) {
- GetScrollingCoordinator()->UpdateAfterCompositingChangeIfNeeded(
- this);
- }
- }
-
UpdateCompositedSelectionIfNeeded();
// TODO(pdr): prePaint should be under the "Paint" devtools timeline
@@ -3267,6 +2490,12 @@ bool LocalFrameView::UpdateLifecyclePhasesInternal(
if (!print_mode_enabled)
PaintTree();
+ if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ if (layout_view->Compositor()->InCompositingMode()) {
+ GetScrollingCoordinator()->UpdateAfterPaint(this);
+ }
+ }
+
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled() ||
RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
if (!print_mode_enabled) {
@@ -3277,10 +2506,22 @@ bool LocalFrameView::UpdateLifecyclePhasesInternal(
DocumentAnimations::UpdateAnimations(GetLayoutView()->GetDocument(),
DocumentLifecycle::kPaintClean,
composited_element_ids);
+
+ // Notify the controller that the artifact has been pushed and some
+ // lifecycle state can be freed (such as raster invalidations).
+ paint_controller_->FinishCycle();
+ // PaintController for BlinkGenPropertyTrees is transient.
+ if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled())
+ paint_controller_ = nullptr;
}
- // Notify the controller that the artifact has been pushed and some
- // lifecycle state can be freed (such as raster invalidations).
- paint_controller_->FinishCycle();
+ }
+
+ if (intersection_observation_state_ != kNotNeeded) {
+ TRACE_EVENT0("blink,benchmark",
+ "LocalFrameView::UpdateViewportIntersectionsForSubtree");
+ SCOPED_UMA_AND_UKM_TIMER("Blink.IntersectionObservation.UpdateTime",
+ UkmMetricNames::kIntersectionObservation);
+ UpdateViewportIntersectionsForSubtree();
}
DCHECK(!frame_->Selection().NeedsLayoutSelectionUpdate());
@@ -3290,19 +2531,15 @@ bool LocalFrameView::UpdateLifecyclePhasesInternal(
Lifecycle().GetState() == DocumentLifecycle::kPaintClean);
}
- ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
- frame_view.CheckDoesNotNeedLayout();
+ allows_layout_invalidation_after_layout_clean_ = true;
+ ForAllChildLocalFrameViews([](LocalFrameView& frame_view) {
+ if (!frame_view.ShouldThrottleRendering())
+ frame_view.CheckDoesNotNeedLayout();
frame_view.allows_layout_invalidation_after_layout_clean_ = true;
});
}
- {
- TRACE_EVENT0("blink,benchmark",
- "LocalFrameView::UpdateViewportIntersectionsForSubtree");
- SCOPED_UMA_AND_UKM_TIMER("Blink.IntersectionObservation.UpdateTime",
- UkmMetricNames::kIntersectionObservation);
- UpdateViewportIntersectionsForSubtree(target_state);
- }
+ UpdateThrottlingStatusForSubtree();
return Lifecycle().GetState() == target_state;
}
@@ -3335,9 +2572,6 @@ void LocalFrameView::PerformScrollAnchoringAdjustments() {
void LocalFrameView::PrePaint() {
TRACE_EVENT0("blink,benchmark", "LocalFrameView::prePaint");
- if (!paint_controller_)
- paint_controller_ = PaintController::Create();
-
ForAllNonThrottledLocalFrameViews([](LocalFrameView& frame_view) {
frame_view.Lifecycle().AdvanceTo(DocumentLifecycle::kInPrePaint);
if (frame_view.CanThrottleRendering()) {
@@ -3362,6 +2596,55 @@ void LocalFrameView::PrePaint() {
});
}
+static void CollectViewportLayersForLayerList(GraphicsContext& context,
+ VisualViewport& visual_viewport) {
+ DCHECK(RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled());
+
+ // Collect the visual viewport container layer.
+ {
+ GraphicsLayer* container_layer = visual_viewport.ContainerLayer();
+ ScopedPaintChunkProperties container_scope(
+ context.GetPaintController(), container_layer->GetPropertyTreeState(),
+ *container_layer, DisplayItem::kForeignLayerWrapper);
+
+ // TODO(trchen): Currently the GraphicsLayer hierarchy is still built during
+ // CompositingUpdate, and we have to clear them here to ensure no extraneous
+ // layers are still attached. In future we will disable all those layer
+ // hierarchy code so we won't need this line.
+ container_layer->CcLayer()->RemoveAllChildren();
+ RecordForeignLayer(context, *container_layer,
+ DisplayItem::kForeignLayerWrapper,
+ container_layer->CcLayer(), FloatPoint(),
+ IntSize(container_layer->CcLayer()->bounds()));
+ }
+
+ // Collect the page scale layer.
+ {
+ GraphicsLayer* scale_layer = visual_viewport.PageScaleLayer();
+ ScopedPaintChunkProperties scale_scope(
+ context.GetPaintController(), scale_layer->GetPropertyTreeState(),
+ *scale_layer, DisplayItem::kForeignLayerWrapper);
+
+ scale_layer->CcLayer()->RemoveAllChildren();
+ RecordForeignLayer(context, *scale_layer, DisplayItem::kForeignLayerWrapper,
+ scale_layer->CcLayer(), FloatPoint(), IntSize());
+ }
+
+ // Collect the visual viewport scroll layer.
+ {
+ GraphicsLayer* scroll_layer = visual_viewport.ScrollLayer();
+ ScopedPaintChunkProperties scroll_scope(
+ context.GetPaintController(), scroll_layer->GetPropertyTreeState(),
+ *scroll_layer, DisplayItem::kForeignLayerWrapper);
+
+ scroll_layer->CcLayer()->RemoveAllChildren();
+ RecordForeignLayer(context, *scroll_layer,
+ DisplayItem::kForeignLayerWrapper,
+ scroll_layer->CcLayer(), FloatPoint(),
+ IntSize(scroll_layer->CcLayer()->bounds()));
+ }
+}
+
static void CollectDrawableLayersForLayerListRecursively(
GraphicsContext& context,
const GraphicsLayer* layer) {
@@ -3370,32 +2653,30 @@ static void CollectDrawableLayersForLayerListRecursively(
if (!layer || layer->Client().ShouldThrottleRendering())
return;
- scoped_refptr<cc::Layer> contents_layer = layer->ContentsLayer();
- if (layer->DrawsContent() || contents_layer) {
+ if (layer->DrawsContent()) {
ScopedPaintChunkProperties scope(context.GetPaintController(),
layer->GetPropertyTreeState(), *layer,
DisplayItem::kForeignLayerWrapper);
-
- if (layer->DrawsContent()) {
- // TODO(trchen): Currently the GraphicsLayer hierarchy is still built
- // during CompositingUpdate, and we have to clear them here to ensure no
- // extraneous layers are still attached. In future we will disable all
- // those layer hierarchy code so we won't need this line.
- layer->CcLayer()->RemoveAllChildren();
- RecordForeignLayer(context, *layer, DisplayItem::kForeignLayerWrapper,
- layer->CcLayer(), layer->GetOffsetFromTransformNode(),
- RoundedIntSize(layer->Size()));
- }
- if (contents_layer) {
- auto position = contents_layer->position();
- auto size = contents_layer->bounds();
- RecordForeignLayer(context, *layer,
- DisplayItem::kForeignLayerContentsWrapper,
- std::move(contents_layer),
- layer->GetOffsetFromTransformNode() +
- FloatSize(position.x(), position.y()),
- IntSize(size.width(), size.height()));
- }
+ // TODO(trchen): Currently the GraphicsLayer hierarchy is still built
+ // during CompositingUpdate, and we have to clear them here to ensure no
+ // extraneous layers are still attached. In future we will disable all
+ // those layer hierarchy code so we won't need this line.
+ layer->CcLayer()->RemoveAllChildren();
+ RecordForeignLayer(
+ context, *layer, DisplayItem::kForeignLayerWrapper, layer->CcLayer(),
+ FloatPoint(layer->GetOffsetFromTransformNode()), layer->Size());
+ }
+
+ if (scoped_refptr<cc::Layer> contents_layer = layer->ContentsLayer()) {
+ ScopedPaintChunkProperties scope(
+ context.GetPaintController(), layer->GetContentsPropertyTreeState(),
+ *layer, DisplayItem::kForeignLayerContentsWrapper);
+ auto size = contents_layer->bounds();
+ RecordForeignLayer(context, *layer,
+ DisplayItem::kForeignLayerContentsWrapper,
+ std::move(contents_layer),
+ FloatPoint(layer->GetContentsOffsetFromTransformNode()),
+ IntSize(size.width(), size.height()));
}
DCHECK(!layer->ContentsClippingMaskLayer());
@@ -3404,6 +2685,24 @@ static void CollectDrawableLayersForLayerListRecursively(
CollectDrawableLayersForLayerListRecursively(context, layer->MaskLayer());
}
+static void PaintGraphicsLayerRecursively(GraphicsLayer* layer) {
+ layer->PaintRecursively();
+
+#if DCHECK_IS_ON()
+ if (VLOG_IS_ON(2)) {
+ DEFINE_STATIC_LOCAL(String, s_previous_tree, ());
+ LayerTreeFlags flags = VLOG_IS_ON(3) ? 0xffffffff : kOutputAsLayerTree;
+ String new_tree = GraphicsLayerTreeAsTextForTesting(layer, flags);
+ if (new_tree != s_previous_tree) {
+ VLOG(2) << "After GraphicsLayer::PaintRecursively()\n"
+ << "GraphicsLayer tree:\n"
+ << new_tree.Utf8().data();
+ s_previous_tree = new_tree;
+ }
+ }
+#endif
+}
+
void LocalFrameView::PaintTree() {
TRACE_EVENT0("blink,benchmark", "LocalFrameView::paintTree");
SCOPED_UMA_AND_UKM_TIMER("Blink.Paint.UpdateTime", UkmMetricNames::kPaint);
@@ -3419,6 +2718,9 @@ void LocalFrameView::PaintTree() {
});
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ if (!paint_controller_)
+ paint_controller_ = PaintController::Create();
+
if (GetLayoutView()->Layer()->NeedsRepaint()) {
GraphicsContext graphics_context(*paint_controller_);
if (RuntimeEnabledFeatures::PrintBrowserEnabled())
@@ -3444,26 +2746,47 @@ void LocalFrameView::PaintTree() {
// frame view of a page overlay. The page overlay is in the layer tree of
// the host page and will be painted during painting of the host page.
if (GraphicsLayer* root_graphics_layer =
- layout_view->Compositor()->PaintRootGraphicsLayer())
- root_graphics_layer->PaintRecursively();
+ layout_view->Compositor()->PaintRootGraphicsLayer()) {
+ PaintGraphicsLayerRecursively(root_graphics_layer);
+ }
// TODO(sataya.m):Main frame doesn't create RootFrameViewport in some
// webkit_unit_tests (http://crbug.com/644788).
if (viewport_scrollable_area_) {
if (GraphicsLayer* layer_for_horizontal_scrollbar =
- viewport_scrollable_area_->LayerForHorizontalScrollbar())
- layer_for_horizontal_scrollbar->PaintRecursively();
+ viewport_scrollable_area_->LayerForHorizontalScrollbar()) {
+ PaintGraphicsLayerRecursively(layer_for_horizontal_scrollbar);
+ }
if (GraphicsLayer* layer_for_vertical_scrollbar =
- viewport_scrollable_area_->LayerForVerticalScrollbar())
- layer_for_vertical_scrollbar->PaintRecursively();
+ viewport_scrollable_area_->LayerForVerticalScrollbar()) {
+ PaintGraphicsLayerRecursively(layer_for_vertical_scrollbar);
+ }
if (GraphicsLayer* layer_for_scroll_corner =
- viewport_scrollable_area_->LayerForScrollCorner())
- layer_for_scroll_corner->PaintRecursively();
+ viewport_scrollable_area_->LayerForScrollCorner()) {
+ PaintGraphicsLayerRecursively(layer_for_scroll_corner);
+ }
}
}
if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
+ // BlinkGenPropertyTrees just needs a transient PaintController to
+ // collect the foreign layers which doesn't need caching. It also
+ // shouldn't affect caching status of DisplayItemClients because it's
+ // FinishCycle() is not synchronized with other PaintControllers.
+ paint_controller_ = PaintController::Create(PaintController::kTransient);
+
GraphicsContext context(*paint_controller_);
+ // Note: Some blink unit tests run without turning on compositing which
+ // means we don't create viewport layers. OOPIFs also don't have their own
+ // viewport layers.
+ if (GetLayoutView()->Compositor()->InCompositingMode() &&
+ GetFrame() == GetPage()->MainFrame()) {
+ // TODO(bokan): We should eventually stop creating layers for the visual
+ // viewport. At that point, we can remove this. However, for now, CC
+ // still has some dependencies on the viewport scale and scroll layers.
+ CollectViewportLayersForLayerList(context,
+ frame_->GetPage()->GetVisualViewport());
+ }
// With BlinkGenPropertyTrees, |PaintRootGraphicsLayer| is the ancestor of
// all drawable layers (see: PaintLayerCompositor::PaintRootGraphicsLayer)
// so we do not need to collect scrollbars separately.
@@ -3501,14 +2824,15 @@ void LocalFrameView::PushPaintArtifactToCompositor(
// ScrollingCoordinator.
WrapWeakPersistent(page->GetScrollingCoordinator())));
page->GetChromeClient().AttachRootLayer(
- paint_artifact_compositor_->GetCcLayer(), &GetFrame());
+ paint_artifact_compositor_->RootLayer(), &GetFrame());
}
SCOPED_UMA_AND_UKM_TIMER("Blink.Compositing.UpdateTime",
UkmMetricNames::kCompositing);
- paint_artifact_compositor_->Update(paint_controller_->GetPaintArtifact(),
- composited_element_ids);
+ paint_artifact_compositor_->Update(
+ paint_controller_->GetPaintArtifactShared(), composited_element_ids,
+ frame_->GetPage()->GetVisualViewport().GetPageScaleNode());
}
std::unique_ptr<JSONObject> LocalFrameView::CompositedLayersAsJSON(
@@ -3629,8 +2953,7 @@ void LocalFrameView::DisableAutoSizeMode() {
ScheduleRelayout();
// Since autosize mode forces the scrollbar mode, change them to being auto.
- SetAutosizeScrollbarModes(kScrollbarAuto, kScrollbarAuto);
- SetScrollbarModes(kScrollbarAuto, kScrollbarAuto);
+ GetLayoutView()->SetAutosizeScrollbarModes(kScrollbarAuto, kScrollbarAuto);
auto_size_info_.Clear();
}
@@ -3733,22 +3056,14 @@ IntRect LocalFrameView::ConvertFromLayoutObject(
LayoutRect rect = EnclosingLayoutRect(
layout_object.LocalToAbsoluteQuad(FloatRect(layout_object_rect))
.BoundingBox());
- rect.Move(LayoutSize(-GetScrollOffset()));
return PixelSnappedIntRect(rect);
}
IntRect LocalFrameView::ConvertToLayoutObject(const LayoutObject& layout_object,
const IntRect& frame_rect) const {
- IntRect rect_in_content = FrameToContents(frame_rect);
-
- // Convert from LocalFrameView coords into page ("absolute") coordinates.
- rect_in_content.Move(ScrollOffsetInt());
-
- // FIXME: we don't have a way to map an absolute rect down to a local quad, so
- // just move the rect for now.
- rect_in_content.SetLocation(RoundedIntPoint(layout_object.AbsoluteToLocal(
- rect_in_content.Location(), kUseTransforms)));
- return rect_in_content;
+ FloatQuad quad((FloatRect(frame_rect)));
+ quad = layout_object.AbsoluteToLocalQuad(quad, kUseTransforms);
+ return RoundedIntRect(quad.BoundingBox());
}
IntPoint LocalFrameView::ConvertFromLayoutObject(
@@ -3768,12 +3083,8 @@ IntPoint LocalFrameView::ConvertToLayoutObject(
LayoutPoint LocalFrameView::ConvertFromLayoutObject(
const LayoutObject& layout_object,
const LayoutPoint& layout_object_point) const {
- LayoutPoint point(layout_object.LocalToAbsolute(
+ return LayoutPoint(layout_object.LocalToAbsolute(
FloatPoint(layout_object_point), kUseTransforms));
-
- // Convert from page ("absolute") to LocalFrameView coordinates.
- point.Move(-LayoutSize(GetScrollOffset()));
- return point;
}
LayoutPoint LocalFrameView::ConvertToLayoutObject(
@@ -3786,45 +3097,16 @@ LayoutPoint LocalFrameView::ConvertToLayoutObject(
FloatPoint LocalFrameView::ConvertToLayoutObject(
const LayoutObject& layout_object,
const FloatPoint& frame_point) const {
- FloatPoint point = frame_point;
-
- // Convert from LocalFrameView coords into page ("absolute") coordinates.
- point += FloatSize(ScrollX(), ScrollY());
-
- return layout_object.AbsoluteToLocal(point, kUseTransforms);
+ return layout_object.AbsoluteToLocal(frame_point, kUseTransforms);
}
IntPoint LocalFrameView::ConvertSelfToChild(const EmbeddedContentView& child,
const IntPoint& point) const {
- IntPoint new_point = point;
- new_point = FrameToContents(point);
+ IntPoint new_point(point);
new_point.MoveBy(-child.FrameRect().Location());
return new_point;
}
-IntRect LocalFrameView::AbsoluteToRootFrame(
- const IntRect& absolute_rect) const {
- IntRect root_frame_rect(absolute_rect);
- root_frame_rect.Move(-ScrollOffsetInt());
- return ConvertToRootFrame(root_frame_rect);
-}
-
-IntPoint LocalFrameView::AbsoluteToRootFrame(
- const IntPoint& absolute_point) const {
- IntPoint point_in_frame(absolute_point);
- // With RLS turned on, this will be a no-op.
- point_in_frame -= ScrollOffsetInt();
- return ConvertToRootFrame(point_in_frame);
-}
-
-LayoutRect LocalFrameView::AbsoluteToRootFrame(
- const LayoutRect& layout_rect) const {
- LayoutPoint point_in_frame(layout_rect.Location());
- // With RLS turned on, this will be a no-op.
- point_in_frame -= LayoutSize(ScrollOffsetInt());
- return LayoutRect(ConvertToRootFrame(point_in_frame), layout_rect.Size());
-}
-
IntRect LocalFrameView::RootFrameToDocument(const IntRect& rect_in_root_frame) {
IntPoint offset = RootFrameToDocument(rect_in_root_frame.Location());
IntRect local_rect = rect_in_root_frame;
@@ -3840,63 +3122,42 @@ IntPoint LocalFrameView::RootFrameToDocument(
FloatPoint LocalFrameView::RootFrameToDocument(
const FloatPoint& point_in_root_frame) {
FloatPoint local_frame = ConvertFromRootFrame(point_in_root_frame);
- return local_frame + LayoutViewportScrollableArea()->GetScrollOffset();
-}
-
-LayoutPoint LocalFrameView::RootFrameToAbsolute(
- const LayoutPoint& point_in_root_frame) const {
- LayoutPoint local_frame = ConvertFromRootFrame(point_in_root_frame);
- // With RLS turned on, this will be a no-op.
- return local_frame + LayoutSize(GetScrollOffset());
+ return local_frame + LayoutViewport()->GetScrollOffset();
}
-IntPoint LocalFrameView::RootFrameToAbsolute(
- const IntPoint& point_in_root_frame) const {
- IntPoint local_frame = ConvertFromRootFrame(point_in_root_frame);
- // With RLS turned on, this will be a no-op.
- return local_frame + FlooredIntSize(GetScrollOffset());
-}
-
-IntRect LocalFrameView::RootFrameToAbsolute(
- const IntRect& rect_in_root_frame) const {
- IntRect absolute_rect = ConvertFromRootFrame(rect_in_root_frame);
- absolute_rect.Move(FlooredIntSize(GetScrollOffset()));
- return absolute_rect;
-}
-
-DoublePoint LocalFrameView::DocumentToAbsolute(
+DoublePoint LocalFrameView::DocumentToFrame(
const DoublePoint& point_in_document) const {
return point_in_document -
GetLayoutView()->GetScrollableArea()->GetScrollOffset();
}
-FloatPoint LocalFrameView::DocumentToAbsolute(
+FloatPoint LocalFrameView::DocumentToFrame(
const FloatPoint& point_in_document) const {
- return FloatPoint(DocumentToAbsolute(DoublePoint(point_in_document)));
+ return FloatPoint(DocumentToFrame(DoublePoint(point_in_document)));
}
-LayoutPoint LocalFrameView::DocumentToAbsolute(
+LayoutPoint LocalFrameView::DocumentToFrame(
const LayoutPoint& point_in_document) const {
return point_in_document -
LayoutSize(GetLayoutView()->GetScrollableArea()->GetScrollOffset());
}
-LayoutRect LocalFrameView::DocumentToAbsolute(
+LayoutRect LocalFrameView::DocumentToFrame(
const LayoutRect& rect_in_document) const {
// With RLS turned off, this will be a no-op.
- return LayoutRect(DocumentToAbsolute(rect_in_document.Location()),
+ return LayoutRect(DocumentToFrame(rect_in_document.Location()),
rect_in_document.Size());
}
-LayoutPoint LocalFrameView::AbsoluteToDocument(
+LayoutPoint LocalFrameView::FrameToDocument(
const LayoutPoint& point_in_absolute) const {
return point_in_absolute +
LayoutSize(GetLayoutView()->GetScrollableArea()->GetScrollOffset());
}
-LayoutRect LocalFrameView::AbsoluteToDocument(
+LayoutRect LocalFrameView::FrameToDocument(
const LayoutRect& rect_in_absolute) const {
- return LayoutRect(AbsoluteToDocument(rect_in_absolute.Location()),
+ return LayoutRect(FrameToDocument(rect_in_absolute.Location()),
rect_in_absolute.Size());
}
@@ -3948,6 +3209,25 @@ LayoutPoint LocalFrameView::ConvertToContainingEmbeddedContentView(
return local_point;
}
+FloatPoint LocalFrameView::ConvertToContainingEmbeddedContentView(
+ const FloatPoint& local_point) const {
+ if (LocalFrameView* parent = ParentFrameView()) {
+ auto* layout_object = frame_->OwnerLayoutObject();
+ if (!layout_object)
+ return local_point;
+
+ FloatPoint point(local_point);
+
+ // Add borders and padding
+ point.Move(
+ (layout_object->BorderLeft() + layout_object->PaddingLeft()).ToFloat(),
+ (layout_object->BorderTop() + layout_object->PaddingTop()).ToFloat());
+ return layout_object->LocalToAbsolute(point, kUseTransforms);
+ }
+
+ return local_point;
+}
+
LayoutPoint LocalFrameView::ConvertFromContainingEmbeddedContentView(
const LayoutPoint& parent_point) const {
return LayoutPoint(
@@ -3987,12 +3267,6 @@ IntPoint LocalFrameView::ConvertToContainingEmbeddedContentView(
ConvertToContainingEmbeddedContentView(LayoutPoint(local_point)));
}
-IntPoint LocalFrameView::ConvertFromContainingEmbeddedContentView(
- const IntPoint& parent_point) const {
- return RoundedIntPoint(
- ConvertFromContainingEmbeddedContentView(DoublePoint(parent_point)));
-}
-
void LocalFrameView::SetInitialTracksPaintInvalidationsForTesting(
bool track_paint_invalidations) {
g_initial_track_all_paint_invalidations = track_paint_invalidations;
@@ -4016,10 +3290,6 @@ void LocalFrameView::SetTracksPaintInvalidations(
? new Vector<ObjectPaintInvalidation>
: nullptr);
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- if (!paint_controller_)
- paint_controller_ = PaintController::Create();
- paint_controller_->SetTracksRasterInvalidations(
- track_paint_invalidations);
if (paint_artifact_compositor_) {
paint_artifact_compositor_->SetTracksRasterInvalidations(
track_paint_invalidations);
@@ -4087,18 +3357,20 @@ void LocalFrameView::RemoveResizerArea(LayoutBox& resizer_box) {
resizer_areas_->erase(it);
}
+void LocalFrameView::ScheduleAnimation() {
+ if (auto* client = ToChromeClient(GetChromeClient()))
+ client->ScheduleAnimation(this);
+}
+
bool LocalFrameView::FrameIsScrollableDidChange() {
DCHECK(GetFrame().IsLocalRoot());
return GetScrollingContext()->WasScrollable() !=
- LayoutViewportScrollableArea()->IsScrollable();
+ LayoutViewport()->ScrollsOverflow();
}
void LocalFrameView::ClearFrameIsScrollableDidChange() {
- GetScrollingContext()->SetWasScrollable(GetFrame()
- .LocalFrameRoot()
- .View()
- ->LayoutViewportScrollableArea()
- ->IsScrollable());
+ GetScrollingContext()->SetWasScrollable(
+ GetFrame().LocalFrameRoot().View()->LayoutViewport()->ScrollsOverflow());
}
void LocalFrameView::ScrollableAreasDidChange() {
@@ -4116,7 +3388,8 @@ void LocalFrameView::ScrollableAreasDidChange() {
GetScrollingContext()->SetScrollGestureRegionIsDirty(true);
}
-void LocalFrameView::AddScrollableArea(ScrollableArea* scrollable_area) {
+void LocalFrameView::AddScrollableArea(
+ PaintLayerScrollableArea* scrollable_area) {
DCHECK(scrollable_area);
if (!scrollable_areas_)
scrollable_areas_ = new ScrollableAreaSet;
@@ -4128,7 +3401,8 @@ void LocalFrameView::AddScrollableArea(ScrollableArea* scrollable_area) {
}
}
-void LocalFrameView::RemoveScrollableArea(ScrollableArea* scrollable_area) {
+void LocalFrameView::RemoveScrollableArea(
+ PaintLayerScrollableArea* scrollable_area) {
if (!scrollable_areas_)
return;
scrollable_areas_->erase(scrollable_area);
@@ -4140,7 +3414,7 @@ void LocalFrameView::RemoveScrollableArea(ScrollableArea* scrollable_area) {
}
void LocalFrameView::AddAnimatingScrollableArea(
- ScrollableArea* scrollable_area) {
+ PaintLayerScrollableArea* scrollable_area) {
DCHECK(scrollable_area);
if (!animating_scrollable_areas_)
animating_scrollable_areas_ = new ScrollableAreaSet;
@@ -4148,7 +3422,7 @@ void LocalFrameView::AddAnimatingScrollableArea(
}
void LocalFrameView::RemoveAnimatingScrollableArea(
- ScrollableArea* scrollable_area) {
+ PaintLayerScrollableArea* scrollable_area) {
if (!animating_scrollable_areas_)
return;
animating_scrollable_areas_->erase(scrollable_area);
@@ -4170,7 +3444,6 @@ void LocalFrameView::AttachToLayout() {
CHECK(parent_);
if (parent_->IsVisible())
SetParentVisible(true);
- UpdateParentScrollableAreaSet();
SetupRenderThrottling();
subtree_throttled_ = ParentFrameView()->CanThrottleRendering();
@@ -4191,8 +3464,6 @@ void LocalFrameView::DetachFromLayout() {
CHECK(parent_frame->View());
}
CHECK(parent == parent_);
- if (!RuntimeEnabledFeatures::RootLayerScrollingEnabled())
- parent->RemoveScrollableArea(this);
SetParentVisible(false);
is_attached_ = false;
@@ -4225,11 +3496,11 @@ bool LocalFrameView::VisualViewportSuppliesScrollbars() {
const TopDocumentRootScrollerController& controller =
frame_->GetPage()->GlobalRootScrollerController();
- if (!LayoutViewportScrollableArea())
+ if (!LayoutViewport())
return false;
return RootScrollerUtil::ScrollableAreaForRootScroller(
- controller.GlobalRootScroller()) == LayoutViewportScrollableArea();
+ controller.GlobalRootScroller()) == LayoutViewport();
}
AXObjectCache* LocalFrameView::ExistingAXObjectCache() const {
@@ -4251,7 +3522,9 @@ void LocalFrameView::FrameRectsChanged() {
SetLayoutSizeInternal(Size());
ForAllChildViewsAndPlugins([](EmbeddedContentView& embedded_content_view) {
- embedded_content_view.FrameRectsChanged();
+ if (!embedded_content_view.IsLocalFrameView() ||
+ !ToLocalFrameView(embedded_content_view).ShouldThrottleRendering())
+ embedded_content_view.FrameRectsChanged();
});
GetFrame().Client()->FrameRectsChanged(FrameRect());
@@ -4260,134 +3533,15 @@ void LocalFrameView::FrameRectsChanged() {
void LocalFrameView::SetLayoutSizeInternal(const IntSize& size) {
if (layout_size_ == size)
return;
-
layout_size_ = size;
- ContentsResized();
-}
-
-void LocalFrameView::DidAddScrollbar(Scrollbar& scrollbar,
- ScrollbarOrientation orientation) {
- ScrollableArea::DidAddScrollbar(scrollbar, orientation);
-}
-
-PaintLayer* LocalFrameView::Layer() const {
- auto* layout_view = GetLayoutView();
- if (!layout_view || !layout_view->Compositor())
- return nullptr;
- return layout_view->Compositor()->RootLayer();
-}
-
-IntSize LocalFrameView::MaximumScrollOffsetInt() const {
- // Make the same calculation as in CC's LayerImpl::MaxScrollOffset()
- // FIXME: We probably shouldn't be storing the bounds in a float.
- // crbug.com/422331.
- IntSize visible_size = VisibleContentSize(kExcludeScrollbars);
- IntSize content_bounds = ContentsSize();
-
- Page* page = frame_->GetPage();
- DCHECK(page);
-
- // We need to perform this const_cast since maximumScrollOffsetInt is a const
- // method but we can't make layoutViewportScrollableArea const since it can
- // return |this|. Once root-layer-scrolls ships layoutViewportScrollableArea
- // can be made const.
- const ScrollableArea* layout_viewport =
- const_cast<LocalFrameView*>(this)->LayoutViewportScrollableArea();
- TopDocumentRootScrollerController& controller =
- page->GlobalRootScrollerController();
- if (layout_viewport == controller.RootScrollerArea())
- visible_size = controller.RootScrollerVisibleArea();
-
- IntSize maximum_offset =
- ToIntSize(-ScrollOrigin() + (content_bounds - visible_size));
- return maximum_offset.ExpandedTo(MinimumScrollOffsetInt());
-}
-
-void LocalFrameView::SetScrollbarModes(ScrollbarMode horizontal_mode,
- ScrollbarMode vertical_mode) {
- bool needs_update = false;
-
- // If the page's overflow setting has disabled scrolling, do not allow
- // anything to override that setting, http://crbug.com/426447
- LayoutObject* viewport = ViewportLayoutObject();
- if (viewport && !ShouldIgnoreOverflowHidden()) {
- if (viewport->Style()->OverflowX() == EOverflow::kHidden)
- horizontal_mode = kScrollbarAlwaysOff;
- if (viewport->Style()->OverflowY() == EOverflow::kHidden)
- vertical_mode = kScrollbarAlwaysOff;
- }
-
- if (horizontal_mode != horizontal_scrollbar_mode_) {
- horizontal_scrollbar_mode_ = horizontal_mode;
- needs_update = true;
- }
-
- if (vertical_mode != vertical_scrollbar_mode_) {
- vertical_scrollbar_mode_ = vertical_mode;
- needs_update = true;
+ if (frame_->IsMainFrame() && frame_->GetDocument()) {
+ if (TextAutosizer* text_autosizer =
+ frame_->GetDocument()->GetTextAutosizer())
+ text_autosizer->UpdatePageInfoInAllFrames();
}
- if (!needs_update)
- return;
-
- UpdateScrollbars();
-
- if (GetScrollingCoordinator())
- GetScrollingCoordinator()->UpdateUserInputScrollable(this);
-}
-
-ScrollbarMode LocalFrameView::EffectiveHorizontalScrollbarMode() const {
- // If we're autosizing, override the current scrollbar mode to whatever the
- // frame autosizer specifies.
- if (AutosizeHorizontalScrollbarMode() != kScrollbarAuto)
- return AutosizeHorizontalScrollbarMode();
-
- return horizontal_scrollbar_mode_;
-}
-
-ScrollbarMode LocalFrameView::EffectiveVerticalScrollbarMode() const {
- // If we're autosizing, override the current scrollbar mode to whatever the
- // frame autosizer specifies.
- if (AutosizeVerticalScrollbarMode() != kScrollbarAuto)
- return AutosizeVerticalScrollbarMode();
-
- return vertical_scrollbar_mode_;
-}
-
-IntSize LocalFrameView::VisibleContentSize(
- IncludeScrollbarsInRect scrollbar_inclusion) const {
- return scrollbar_inclusion == kExcludeScrollbars ? ExcludeScrollbars(Size())
- : Size();
-}
-
-IntRect LocalFrameView::VisibleContentRect(
- IncludeScrollbarsInRect scrollbar_inclusion) const {
- return IntRect(IntPoint(FlooredIntSize(scroll_offset_)),
- VisibleContentSize(scrollbar_inclusion));
-}
-
-LayoutRect LocalFrameView::VisibleScrollSnapportRect() const {
- const ComputedStyle* style = GetLayoutBox()->Style();
- LayoutRect visible_content_rect = LayoutRect(
- FloatPoint(scroll_offset_), VisibleContentSize(kExcludeScrollbars));
- LayoutRectOutsets padding(
- MinimumValueForLength(style->ScrollPaddingTop(),
- visible_content_rect.Height()),
- MinimumValueForLength(style->ScrollPaddingRight(),
- visible_content_rect.Width()),
- MinimumValueForLength(style->ScrollPaddingBottom(),
- visible_content_rect.Height()),
- MinimumValueForLength(style->ScrollPaddingLeft(),
- visible_content_rect.Width()));
- visible_content_rect.Contract(padding);
- return visible_content_rect;
-}
-
-IntSize LocalFrameView::ContentsSize() const {
- if (RuntimeEnabledFeatures::RootLayerScrollingEnabled())
- return Size();
- return layout_overflow_size_;
+ SetNeedsLayout();
}
void LocalFrameView::ClipPaintRect(FloatRect* paint_rect) const {
@@ -4398,93 +3552,7 @@ void LocalFrameView::ClipPaintRect(FloatRect* paint_rect) const {
paint_rect->Intersect(
GetPage()->GetChromeClient().VisibleContentRectForPainting().value_or(
- VisibleContentRect()));
-}
-
-IntSize LocalFrameView::MinimumScrollOffsetInt() const {
- return ToIntSize(-ScrollOrigin());
-}
-
-void LocalFrameView::AdjustScrollbarOpacity() {
- if (HorizontalScrollbar() && LayerForHorizontalScrollbar()) {
- bool is_opaque_scrollbar = !HorizontalScrollbar()->IsOverlayScrollbar();
- LayerForHorizontalScrollbar()->SetContentsOpaque(is_opaque_scrollbar);
- }
- if (VerticalScrollbar() && LayerForVerticalScrollbar()) {
- bool is_opaque_scrollbar = !VerticalScrollbar()->IsOverlayScrollbar();
- LayerForVerticalScrollbar()->SetContentsOpaque(is_opaque_scrollbar);
- }
-}
-
-int LocalFrameView::ScrollSize(ScrollbarOrientation orientation) const {
- Scrollbar* scrollbar =
- ((orientation == kHorizontalScrollbar) ? HorizontalScrollbar()
- : VerticalScrollbar());
-
- // If no scrollbars are present, the content may still be scrollable.
- if (!scrollbar) {
- IntSize scroll_size = ContentsSize() - VisibleContentSize();
- scroll_size.ClampNegativeToZero();
- return orientation == kHorizontalScrollbar ? scroll_size.Width()
- : scroll_size.Height();
- }
-
- return scrollbar->TotalSize() - scrollbar->VisibleSize();
-}
-
-void LocalFrameView::UpdateScrollOffset(const ScrollOffset& offset,
- ScrollType scroll_type) {
- ScrollOffset scroll_delta = offset - scroll_offset_;
- if (scroll_delta.IsZero())
- return;
-
- if (RuntimeEnabledFeatures::RootLayerScrollingEnabled()) {
- // Don't scroll the LocalFrameView!
- NOTREACHED();
- }
-
- scroll_offset_ = offset;
-
- if (!ScrollbarsSuppressed())
- pending_scroll_delta_ += scroll_delta;
-
- UpdateLayersAndCompositingAfterScrollIfNeeded();
-
- Document* document = frame_->GetDocument();
- document->EnqueueScrollEventForNode(document);
-
- GetLayoutView()->DispatchFakeMouseMoveEventSoon(GetFrame().GetEventHandler());
-
- if (scroll_type == kUserScroll || scroll_type == kCompositorScroll) {
- Page* page = GetFrame().GetPage();
- if (page)
- page->GetChromeClient().ClearToolTip(*frame_);
- }
-
- auto* layout_view = GetLayoutView();
- if (layout_view)
- layout_view->ClearHitTestCache();
-
- did_scroll_timer_.StartOneShot(kResourcePriorityUpdateDelayAfterScroll,
- FROM_HERE);
-
- if (AXObjectCache* cache = frame_->GetDocument()->ExistingAXObjectCache())
- cache->HandleScrollPositionChanged(this);
-
- GetFrame().Loader().SaveScrollState();
- DidChangeScrollOffset();
-
- if (scroll_type == kCompositorScroll || scroll_type == kUserScroll) {
- if (DocumentLoader* document_loader = frame_->Loader().GetDocumentLoader())
- document_loader->GetInitialScrollState().was_scrolled_by_user = true;
- }
-
- if (IsExplicitScrollType(scroll_type)) {
- if (scroll_type != kCompositorScroll)
- ShowOverlayScrollbars();
- ClearFragmentAnchor();
- ClearScrollAnchor();
- }
+ IntRect(IntPoint(), Size())));
}
void LocalFrameView::DidChangeScrollOffset() {
@@ -4493,285 +3561,13 @@ void LocalFrameView::DidChangeScrollOffset() {
GetFrame().GetPage()->GetChromeClient().MainFrameScrollOffsetChanged();
}
-void LocalFrameView::ClearScrollAnchor() {
- scroll_anchor_.Clear();
-}
-
-bool LocalFrameView::HasOverlayScrollbars() const {
- return (HorizontalScrollbar() &&
- HorizontalScrollbar()->IsOverlayScrollbar()) ||
- (VerticalScrollbar() && VerticalScrollbar()->IsOverlayScrollbar());
-}
-
-void LocalFrameView::ComputeScrollbarExistence(
- bool& new_has_horizontal_scrollbar,
- bool& new_has_vertical_scrollbar,
- const IntSize& doc_size,
- ComputeScrollbarExistenceOption option) {
- if ((frame_->GetSettings() && frame_->GetSettings()->GetHideScrollbars()) ||
- VisualViewportSuppliesScrollbars()) {
- new_has_horizontal_scrollbar = false;
- new_has_vertical_scrollbar = false;
- return;
- }
-
- bool has_horizontal_scrollbar = HorizontalScrollbar();
- bool has_vertical_scrollbar = VerticalScrollbar();
-
- new_has_horizontal_scrollbar = has_horizontal_scrollbar;
- new_has_vertical_scrollbar = has_vertical_scrollbar;
-
- if (RuntimeEnabledFeatures::RootLayerScrollingEnabled())
- return;
-
- ScrollbarMode h_scroll = EffectiveHorizontalScrollbarMode();
- ScrollbarMode v_scroll = EffectiveVerticalScrollbarMode();
-
- if (h_scroll != kScrollbarAuto)
- new_has_horizontal_scrollbar = (h_scroll == kScrollbarAlwaysOn);
- if (v_scroll != kScrollbarAuto)
- new_has_vertical_scrollbar = (v_scroll == kScrollbarAlwaysOn);
-
- if (scrollbars_suppressed_ ||
- (h_scroll != kScrollbarAuto && v_scroll != kScrollbarAuto))
- return;
-
- if (h_scroll == kScrollbarAuto)
- new_has_horizontal_scrollbar = doc_size.Width() > VisibleWidth();
- if (v_scroll == kScrollbarAuto)
- new_has_vertical_scrollbar = doc_size.Height() > VisibleHeight();
-
- if (HasOverlayScrollbars())
- return;
-
- IntSize full_visible_size = VisibleContentSize(kIncludeScrollbars);
-
- bool attempt_to_remove_scrollbars =
- (option == kFirstPass && doc_size.Width() <= full_visible_size.Width() &&
- doc_size.Height() <= full_visible_size.Height());
- if (attempt_to_remove_scrollbars) {
- if (h_scroll == kScrollbarAuto)
- new_has_horizontal_scrollbar = false;
- if (v_scroll == kScrollbarAuto)
- new_has_vertical_scrollbar = false;
- }
-}
-
-void LocalFrameView::UpdateScrollbarEnabledState() {
- bool force_disabled =
- GetPageScrollbarTheme().ShouldDisableInvisibleScrollbars() &&
- ScrollbarsHiddenIfOverlay();
-
- if (HorizontalScrollbar()) {
- HorizontalScrollbar()->SetEnabled(ContentsWidth() > VisibleWidth() &&
- !force_disabled);
- }
- if (VerticalScrollbar()) {
- VerticalScrollbar()->SetEnabled(ContentsHeight() > VisibleHeight() &&
- !force_disabled);
- }
-}
-
-void LocalFrameView::UpdateScrollbarGeometry() {
- UpdateScrollbarEnabledState();
- if (HorizontalScrollbar()) {
- int thickness = HorizontalScrollbar()->ScrollbarThickness();
- IntRect old_rect(HorizontalScrollbar()->FrameRect());
- IntRect h_bar_rect(
- (ShouldPlaceVerticalScrollbarOnLeft() && VerticalScrollbar())
- ? VerticalScrollbar()->Width()
- : 0,
- Height() - thickness,
- Width() - (VerticalScrollbar() ? VerticalScrollbar()->Width() : 0),
- thickness);
- HorizontalScrollbar()->SetFrameRect(h_bar_rect);
- if (old_rect != HorizontalScrollbar()->FrameRect())
- SetScrollbarNeedsPaintInvalidation(kHorizontalScrollbar);
-
- HorizontalScrollbar()->SetProportion(VisibleWidth(), ContentsWidth());
- HorizontalScrollbar()->OffsetDidChange();
- }
-
- if (VerticalScrollbar()) {
- int thickness = VerticalScrollbar()->ScrollbarThickness();
- IntRect old_rect(VerticalScrollbar()->FrameRect());
- IntRect v_bar_rect(
- ShouldPlaceVerticalScrollbarOnLeft() ? 0 : (Width() - thickness), 0,
- thickness,
- Height() -
- (HorizontalScrollbar() ? HorizontalScrollbar()->Height() : 0));
- VerticalScrollbar()->SetFrameRect(v_bar_rect);
- if (old_rect != VerticalScrollbar()->FrameRect())
- SetScrollbarNeedsPaintInvalidation(kVerticalScrollbar);
-
- VerticalScrollbar()->SetProportion(VisibleHeight(), ContentsHeight());
- VerticalScrollbar()->OffsetDidChange();
- }
-}
-
-bool LocalFrameView::AdjustScrollbarExistence(
- ComputeScrollbarExistenceOption option) {
- DCHECK(in_update_scrollbars_);
-
- // If we came in here with the view already needing a layout, then go ahead
- // and do that first. (This will be the common case, e.g., when the page
- // changes due to window resizing for example). This layout will not re-enter
- // updateScrollbars and does not count towards our max layout pass total.
- if (!scrollbars_suppressed_)
- ScrollbarExistenceMaybeChanged();
-
- bool has_horizontal_scrollbar = HorizontalScrollbar();
- bool has_vertical_scrollbar = VerticalScrollbar();
-
- bool new_has_horizontal_scrollbar = false;
- bool new_has_vertical_scrollbar = false;
- ComputeScrollbarExistence(new_has_horizontal_scrollbar,
- new_has_vertical_scrollbar, ContentsSize(), option);
-
- bool scrollbar_existence_changed =
- has_horizontal_scrollbar != new_has_horizontal_scrollbar ||
- has_vertical_scrollbar != new_has_vertical_scrollbar;
- if (!scrollbar_existence_changed)
- return false;
-
- scrollbar_manager_.SetHasHorizontalScrollbar(new_has_horizontal_scrollbar);
- scrollbar_manager_.SetHasVerticalScrollbar(new_has_vertical_scrollbar);
-
- if (scrollbars_suppressed_)
- return true;
-
- Element* custom_scrollbar_element = nullptr;
- bool uses_overlay_scrollbars =
- GetPageScrollbarTheme().UsesOverlayScrollbars() &&
- !ShouldUseCustomScrollbars(custom_scrollbar_element);
-
- if (!uses_overlay_scrollbars)
- SetNeedsLayout();
-
- ScrollbarExistenceMaybeChanged();
- return true;
-}
-
-bool LocalFrameView::NeedsScrollbarReconstruction() const {
- // We have no scrollbar to reconstruct.
- if (!HorizontalScrollbar() && !VerticalScrollbar())
- return false;
-
- Element* style_source = nullptr;
- bool needs_custom = ShouldUseCustomScrollbars(style_source);
-
- Scrollbar* scrollbars[] = {HorizontalScrollbar(), VerticalScrollbar()};
-
- for (Scrollbar* scrollbar : scrollbars) {
- if (!scrollbar)
- continue;
-
- // We have a native scrollbar that should be custom, or vice versa.
- if (scrollbar->IsCustomScrollbar() != needs_custom)
- return true;
-
- if (needs_custom) {
- DCHECK(scrollbar->IsCustomScrollbar());
- // We have a custom scrollbar with a stale m_owner.
- if (ToLayoutScrollbar(scrollbar)->StyleSource() !=
- style_source->GetLayoutObject())
- return true;
-
- // Should use custom scrollbar and nothing should change.
- continue;
- }
-
- // Check if native scrollbar should change.
- Page* page = frame_->GetPage();
- DCHECK(page);
- ScrollbarTheme* current_theme = &page->GetScrollbarTheme();
-
- if (current_theme != &scrollbar->GetTheme())
- return true;
- }
- return false;
-}
-
-bool LocalFrameView::ShouldIgnoreOverflowHidden() const {
- return frame_->GetSettings()->GetIgnoreMainFrameOverflowHiddenQuirk() &&
- frame_->IsMainFrame();
-}
-
-void LocalFrameView::UpdateScrollbarsIfNeeded() {
- if (needs_scrollbars_update_ || NeedsScrollbarReconstruction() ||
- ScrollOriginChanged())
- UpdateScrollbars();
-}
-
-void LocalFrameView::UpdateScrollbars() {
- needs_scrollbars_update_ = false;
-
- if (RuntimeEnabledFeatures::RootLayerScrollingEnabled())
- return;
-
- SetNeedsPaintPropertyUpdate();
-
- // Avoid drawing two sets of scrollbars when visual viewport is enabled.
- if (VisualViewportSuppliesScrollbars()) {
- if (scrollbar_manager_.HasHorizontalScrollbar() ||
- scrollbar_manager_.HasVerticalScrollbar()) {
- scrollbar_manager_.SetHasHorizontalScrollbar(false);
- scrollbar_manager_.SetHasVerticalScrollbar(false);
- ScrollbarExistenceMaybeChanged();
- }
- AdjustScrollOffsetFromUpdateScrollbars();
- return;
- }
-
- if (in_update_scrollbars_)
- return;
- InUpdateScrollbarsScope in_update_scrollbars_scope(this);
-
- bool scrollbar_existence_changed = false;
-
- if (NeedsScrollbarReconstruction()) {
- scrollbar_manager_.SetHasHorizontalScrollbar(false);
- scrollbar_manager_.SetHasVerticalScrollbar(false);
- scrollbar_existence_changed = true;
- }
-
- int max_update_scrollbars_pass =
- HasOverlayScrollbars() || scrollbars_suppressed_ ? 1 : 3;
- for (int update_scrollbars_pass = 0;
- update_scrollbars_pass < max_update_scrollbars_pass;
- update_scrollbars_pass++) {
- if (!AdjustScrollbarExistence(update_scrollbars_pass ? kIncremental
- : kFirstPass))
- break;
- scrollbar_existence_changed = true;
- }
-
- UpdateScrollbarGeometry();
-
- if (scrollbar_existence_changed) {
- // FIXME: Is frameRectsChanged really necessary here? Have any frame rects
- // changed?
- FrameRectsChanged();
- PositionScrollbarLayers();
- UpdateScrollCorner();
- }
-
- AdjustScrollOffsetFromUpdateScrollbars();
-}
-
-void LocalFrameView::AdjustScrollOffsetFromUpdateScrollbars() {
- ScrollOffset clamped = ClampScrollOffset(GetScrollOffset());
- if (clamped != GetScrollOffset() || ScrollOriginChanged())
- SetScrollOffset(clamped, kClampingScroll);
-}
-
ScrollableArea* LocalFrameView::ScrollableAreaWithElementId(
const CompositorElementId& id) {
// Check for the layout viewport, which may not be in scrollable_areas_ if it
// is styled overflow: hidden. (Other overflow: hidden elements won't have
// composited scrolling layers per crbug.com/784053, so we don't have to worry
// about them.)
- ScrollableArea* viewport = LayoutViewportScrollableArea();
+ ScrollableArea* viewport = LayoutViewport();
if (id == viewport->GetCompositorElementId())
return viewport;
@@ -4791,7 +3587,7 @@ void LocalFrameView::ScrollRectToVisibleInRemoteParent(
const WebScrollIntoViewParams& params) {
DCHECK(GetFrame().IsLocalRoot() && !GetFrame().IsMainFrame() &&
safe_to_propagate_scroll_to_parent_);
- LayoutRect new_rect = AbsoluteToRootFrame(rect_to_scroll);
+ LayoutRect new_rect = ConvertToRootFrame(rect_to_scroll);
GetFrame().Client()->ScrollRectToVisibleInParentFrame(
WebRect(new_rect.X().ToInt(), new_rect.Y().ToInt(),
new_rect.Width().ToInt(), new_rect.Height().ToInt()),
@@ -4805,347 +3601,58 @@ void LocalFrameView::NotifyFrameRectsChangedIfNeeded() {
}
}
-void LocalFrameView::ScrollContentsIfNeeded() {
- if (pending_scroll_delta_.IsZero())
- return;
- ScrollOffset scroll_delta = pending_scroll_delta_;
- pending_scroll_delta_ = ScrollOffset();
- // FIXME: Change scrollContents() to take DoubleSize. crbug.com/414283.
- ScrollContents(FlooredIntSize(scroll_delta));
-}
-
-void LocalFrameView::ScrollContents(const IntSize& scroll_delta) {
- ChromeClient* client = GetChromeClient();
- if (!client)
- return;
-
- TRACE_EVENT0("blink", "LocalFrameView::scrollContents");
-
- if (!ScrollContentsFastPath(-scroll_delta))
- ScrollContentsSlowPath();
-
- // This call will move children with native FrameViews (plugins) and
- // invalidate them as well.
- FrameRectsChanged();
-}
-
-FloatPoint LocalFrameView::ContentsToFrame(
- const FloatPoint& point_in_content_space) const {
- return point_in_content_space - GetScrollOffset();
-}
-
-LayoutPoint LocalFrameView::ContentsToFrame(
- const LayoutPoint& point_in_content_space) const {
- return point_in_content_space - LayoutSize(GetScrollOffset());
-}
-
-IntPoint LocalFrameView::ContentsToFrame(
- const IntPoint& point_in_content_space) const {
- return point_in_content_space - ScrollOffsetInt();
-}
-
-IntRect LocalFrameView::ContentsToFrame(
- const IntRect& rect_in_content_space) const {
- return IntRect(ContentsToFrame(rect_in_content_space.Location()),
- rect_in_content_space.Size());
-}
-
-FloatPoint LocalFrameView::FrameToContents(
- const FloatPoint& point_in_frame) const {
- return point_in_frame + GetScrollOffset();
-}
-
-LayoutPoint LocalFrameView::FrameToContents(
- const LayoutPoint& point_in_frame) const {
- return point_in_frame + LayoutSize(GetScrollOffset());
-}
-
-IntPoint LocalFrameView::FrameToContents(const IntPoint& point_in_frame) const {
- return point_in_frame + ScrollOffsetInt();
-}
-
-IntRect LocalFrameView::FrameToContents(const IntRect& rect_in_frame) const {
- return IntRect(FrameToContents(rect_in_frame.Location()),
- rect_in_frame.Size());
-}
-
-LayoutPoint LocalFrameView::RootFrameToContents(
- const LayoutPoint& point_in_root_frame) const {
- LayoutPoint frame_point = ConvertFromRootFrame(point_in_root_frame);
- return FrameToContents(frame_point);
-}
-
-FloatPoint LocalFrameView::RootFrameToContents(
- const FloatPoint& point_in_root_frame) const {
- FloatPoint frame_point = ConvertFromRootFrame(point_in_root_frame);
- return FrameToContents(frame_point);
-}
-
-IntPoint LocalFrameView::RootFrameToContents(
- const IntPoint& root_frame_point) const {
- IntPoint frame_point = ConvertFromRootFrame(root_frame_point);
- return FrameToContents(frame_point);
-}
-
-IntRect LocalFrameView::RootFrameToContents(
- const IntRect& root_frame_rect) const {
- return IntRect(RootFrameToContents(root_frame_rect.Location()),
- root_frame_rect.Size());
-}
-
-LayoutPoint LocalFrameView::ContentsToRootFrame(
- const LayoutPoint& contents_point) const {
- LayoutPoint frame_point = ContentsToFrame(contents_point);
- return ConvertToRootFrame(frame_point);
-}
-
-IntPoint LocalFrameView::ContentsToRootFrame(
- const IntPoint& contents_point) const {
- IntPoint frame_point = ContentsToFrame(contents_point);
- return ConvertToRootFrame(frame_point);
-}
-
-IntRect LocalFrameView::ContentsToRootFrame(
- const IntRect& contents_rect) const {
- IntRect rect_in_frame = ContentsToFrame(contents_rect);
- return ConvertToRootFrame(rect_in_frame);
-}
-
-LayoutPoint LocalFrameView::ViewportToContents(
+LayoutPoint LocalFrameView::ViewportToFrame(
const LayoutPoint& point_in_viewport) const {
LayoutPoint point_in_root_frame(
frame_->GetPage()->GetVisualViewport().ViewportToRootFrame(
FloatPoint(point_in_viewport)));
- LayoutPoint point_in_frame = ConvertFromRootFrame(point_in_root_frame);
- return FrameToContents(point_in_frame);
+ return ConvertFromRootFrame(point_in_root_frame);
}
-FloatPoint LocalFrameView::ViewportToContents(
+FloatPoint LocalFrameView::ViewportToFrame(
const FloatPoint& point_in_viewport) const {
FloatPoint point_in_root_frame(
frame_->GetPage()->GetVisualViewport().ViewportToRootFrame(
point_in_viewport));
- FloatPoint point_in_frame = ConvertFromRootFrame(point_in_root_frame);
- return FrameToContents(point_in_frame);
+ return ConvertFromRootFrame(point_in_root_frame);
}
-IntRect LocalFrameView::ViewportToContents(
- const IntRect& rect_in_viewport) const {
+IntRect LocalFrameView::ViewportToFrame(const IntRect& rect_in_viewport) const {
IntRect rect_in_root_frame =
frame_->GetPage()->GetVisualViewport().ViewportToRootFrame(
rect_in_viewport);
- IntRect frame_rect = ConvertFromRootFrame(rect_in_root_frame);
- return FrameToContents(frame_rect);
+ return ConvertFromRootFrame(rect_in_root_frame);
}
-IntPoint LocalFrameView::ViewportToContents(
+IntPoint LocalFrameView::ViewportToFrame(
const IntPoint& point_in_viewport) const {
- return RoundedIntPoint(ViewportToContents(LayoutPoint(point_in_viewport)));
+ return RoundedIntPoint(ViewportToFrame(LayoutPoint(point_in_viewport)));
}
-IntRect LocalFrameView::ContentsToViewport(
- const IntRect& rect_in_contents) const {
- IntRect rect_in_frame = ContentsToFrame(rect_in_contents);
+IntRect LocalFrameView::FrameToViewport(const IntRect& rect_in_frame) const {
IntRect rect_in_root_frame = ConvertToRootFrame(rect_in_frame);
return frame_->GetPage()->GetVisualViewport().RootFrameToViewport(
rect_in_root_frame);
}
-IntPoint LocalFrameView::ContentsToViewport(
- const IntPoint& point_in_contents) const {
- IntPoint point_in_frame = ContentsToFrame(point_in_contents);
+IntPoint LocalFrameView::FrameToViewport(const IntPoint& point_in_frame) const {
IntPoint point_in_root_frame = ConvertToRootFrame(point_in_frame);
return frame_->GetPage()->GetVisualViewport().RootFrameToViewport(
point_in_root_frame);
}
-IntRect LocalFrameView::ContentsToScreen(const IntRect& rect) const {
- ChromeClient* client = GetChromeClient();
- if (!client)
- return IntRect();
- return client->ViewportToScreen(ContentsToViewport(rect), this);
+IntRect LocalFrameView::FrameToScreen(const IntRect& rect) const {
+ if (auto* client = ToChromeClient(GetChromeClient()))
+ return client->ViewportToScreen(FrameToViewport(rect), this);
+ return IntRect();
}
IntPoint LocalFrameView::SoonToBeRemovedUnscaledViewportToContents(
const IntPoint& point_in_viewport) const {
IntPoint point_in_root_frame = FlooredIntPoint(
frame_->GetPage()->GetVisualViewport().ViewportCSSPixelsToRootFrame(
- point_in_viewport));
- IntPoint point_in_this_frame = ConvertFromRootFrame(point_in_root_frame);
- return FrameToContents(point_in_this_frame);
-}
-
-Scrollbar* LocalFrameView::ScrollbarAtFramePoint(
- const IntPoint& point_in_frame) {
- if (HorizontalScrollbar() &&
- HorizontalScrollbar()->ShouldParticipateInHitTesting() &&
- HorizontalScrollbar()->FrameRect().Contains(point_in_frame))
- return HorizontalScrollbar();
- if (VerticalScrollbar() &&
- VerticalScrollbar()->ShouldParticipateInHitTesting() &&
- VerticalScrollbar()->FrameRect().Contains(point_in_frame))
- return VerticalScrollbar();
- return nullptr;
-}
-
-static void PositionScrollbarLayer(GraphicsLayer* graphics_layer,
- Scrollbar* scrollbar) {
- if (!graphics_layer || !scrollbar)
- return;
-
- IntRect scrollbar_rect = scrollbar->FrameRect();
- graphics_layer->SetPosition(scrollbar_rect.Location());
- graphics_layer->SetOffsetFromLayoutObject(
- ToIntSize(scrollbar_rect.Location()));
-
- if (scrollbar_rect.Size() == graphics_layer->Size())
- return;
-
- graphics_layer->SetSize(scrollbar_rect.Size());
-
- if (graphics_layer->HasContentsLayer()) {
- graphics_layer->SetContentsRect(
- IntRect(0, 0, scrollbar_rect.Width(), scrollbar_rect.Height()));
- return;
- }
-
- graphics_layer->SetDrawsContent(true);
- graphics_layer->SetNeedsDisplay();
-}
-
-static void PositionScrollCornerLayer(GraphicsLayer* graphics_layer,
- const IntRect& corner_rect) {
- if (!graphics_layer)
- return;
- graphics_layer->SetDrawsContent(!corner_rect.IsEmpty());
- graphics_layer->SetPosition(corner_rect.Location());
- graphics_layer->SetOffsetFromLayoutObject(ToIntSize(corner_rect.Location()));
- if (corner_rect.Size() != graphics_layer->Size())
- graphics_layer->SetNeedsDisplay();
- graphics_layer->SetSize(corner_rect.Size());
-}
-
-void LocalFrameView::PositionScrollbarLayers() {
- PositionScrollbarLayer(LayerForHorizontalScrollbar(), HorizontalScrollbar());
- PositionScrollbarLayer(LayerForVerticalScrollbar(), VerticalScrollbar());
- PositionScrollCornerLayer(LayerForScrollCorner(), ScrollCornerRect());
-}
-
-bool LocalFrameView::UpdateAfterCompositingChange() {
- if (ScrollOriginChanged())
- ResetScrollOriginChanged();
-
- return false;
-}
-
-bool LocalFrameView::UserInputScrollable(
- ScrollbarOrientation orientation) const {
- Document* document = GetFrame().GetDocument();
- Element* fullscreen_element = Fullscreen::FullscreenElementFrom(*document);
- if (fullscreen_element && fullscreen_element != document->documentElement())
- return false;
-
- if (RuntimeEnabledFeatures::RootLayerScrollingEnabled())
- return false;
-
- ScrollbarMode mode = (orientation == kHorizontalScrollbar)
- ? EffectiveHorizontalScrollbarMode()
- : EffectiveVerticalScrollbarMode();
-
- return mode == kScrollbarAuto || mode == kScrollbarAlwaysOn;
-}
-
-bool LocalFrameView::ShouldPlaceVerticalScrollbarOnLeft() const {
- return false;
-}
-
-LayoutRect LocalFrameView::ScrollIntoView(
- const LayoutRect& rect_in_absolute,
- const WebScrollIntoViewParams& params) {
- GetLayoutBox()->SetPendingOffsetToScroll(LayoutSize());
-
- LayoutRect scroll_snapport_rect(VisibleScrollSnapportRect());
-
- ScrollOffset new_scroll_offset =
- ClampScrollOffset(ScrollAlignment::GetScrollOffsetToExpose(
- scroll_snapport_rect, rect_in_absolute, params.GetScrollAlignmentX(),
- params.GetScrollAlignmentY(), GetScrollOffset()));
- ScrollOffset old_scroll_offset = GetScrollOffset();
- if (params.GetScrollType() == kUserScroll) {
- if (!UserInputScrollable(kHorizontalScrollbar))
- new_scroll_offset.SetWidth(old_scroll_offset.Width());
- if (!UserInputScrollable(kVerticalScrollbar))
- new_scroll_offset.SetHeight(old_scroll_offset.Height());
- }
-
- if (new_scroll_offset != old_scroll_offset) {
- new_scroll_offset = ShouldUseIntegerScrollOffset()
- ? ScrollOffset(FlooredIntSize(new_scroll_offset))
- : new_scroll_offset;
- if (params.is_for_scroll_sequence) {
- DCHECK(params.GetScrollType() == kProgrammaticScroll ||
- params.GetScrollType() == kUserScroll);
- ScrollBehavior behavior =
- DetermineScrollBehavior(params.GetScrollBehavior(),
- GetLayoutBox()->Style()->GetScrollBehavior());
- GetSmoothScrollSequencer()->QueueAnimation(this, new_scroll_offset,
- behavior);
- ScrollOffset scroll_offset_difference =
- new_scroll_offset - old_scroll_offset;
- GetLayoutBox()->SetPendingOffsetToScroll(
- -LayoutSize(scroll_offset_difference));
- } else {
- SetScrollOffset(new_scroll_offset, params.GetScrollType());
- }
- }
-
- // Scrolling the LocalFrameView cannot change the input rect's location
- // relative to the document.
- // TODO(szager): PaintLayerScrollableArea::ScrollIntoView clips the return
- // value to the visible content rect, but this does not.
- return rect_in_absolute;
-}
-
-IntRect LocalFrameView::ScrollCornerRect() const {
- IntRect corner_rect;
-
- if (HasOverlayScrollbars())
- return corner_rect;
-
- if (HorizontalScrollbar() && Width() - HorizontalScrollbar()->Width() > 0) {
- corner_rect.Unite(IntRect(ShouldPlaceVerticalScrollbarOnLeft()
- ? 0
- : HorizontalScrollbar()->Width(),
- Height() - HorizontalScrollbar()->Height(),
- Width() - HorizontalScrollbar()->Width(),
- HorizontalScrollbar()->Height()));
- }
-
- if (VerticalScrollbar() && Height() - VerticalScrollbar()->Height() > 0) {
- corner_rect.Unite(IntRect(ShouldPlaceVerticalScrollbarOnLeft()
- ? 0
- : (Width() - VerticalScrollbar()->Width()),
- VerticalScrollbar()->Height(),
- VerticalScrollbar()->Width(),
- Height() - VerticalScrollbar()->Height()));
- }
-
- return corner_rect;
-}
-
-bool LocalFrameView::IsScrollCornerVisible() const {
- return !ScrollCornerRect().IsEmpty();
-}
-
-ScrollBehavior LocalFrameView::ScrollBehaviorStyle() const {
- Element* scroll_element = frame_->GetDocument()->scrollingElement();
- LayoutObject* layout_object =
- scroll_element ? scroll_element->GetLayoutObject() : nullptr;
- if (layout_object &&
- layout_object->Style()->GetScrollBehavior() == kScrollBehaviorSmooth)
- return kScrollBehaviorSmooth;
-
- return kScrollBehaviorInstant;
+ FloatPoint(point_in_viewport)));
+ return ConvertFromRootFrame(point_in_root_frame);
}
void LocalFrameView::Paint(GraphicsContext& context,
@@ -5192,43 +3699,6 @@ void LocalFrameView::PaintContents(GraphicsContext& context,
});
}
-bool LocalFrameView::IsPointInScrollbarCorner(
- const IntPoint& point_in_root_frame) {
- if (!ScrollbarCornerPresent())
- return false;
-
- IntPoint frame_point = ConvertFromRootFrame(point_in_root_frame);
-
- if (HorizontalScrollbar()) {
- int horizontal_scrollbar_y_min = HorizontalScrollbar()->FrameRect().Y();
- int horizontal_scrollbar_y_max =
- HorizontalScrollbar()->FrameRect().Y() +
- HorizontalScrollbar()->FrameRect().Height();
- int horizontal_scrollbar_x_min = HorizontalScrollbar()->FrameRect().X() +
- HorizontalScrollbar()->FrameRect().Width();
-
- return frame_point.Y() > horizontal_scrollbar_y_min &&
- frame_point.Y() < horizontal_scrollbar_y_max &&
- frame_point.X() > horizontal_scrollbar_x_min;
- }
-
- int vertical_scrollbar_x_min = VerticalScrollbar()->FrameRect().X();
- int vertical_scrollbar_x_max = VerticalScrollbar()->FrameRect().X() +
- VerticalScrollbar()->FrameRect().Width();
- int vertical_scrollbar_y_min = VerticalScrollbar()->FrameRect().Y() +
- VerticalScrollbar()->FrameRect().Height();
-
- return frame_point.X() > vertical_scrollbar_x_min &&
- frame_point.X() < vertical_scrollbar_x_max &&
- frame_point.Y() > vertical_scrollbar_y_min;
-}
-
-bool LocalFrameView::ScrollbarCornerPresent() const {
- return (HorizontalScrollbar() &&
- Width() - HorizontalScrollbar()->Width() > 0) ||
- (VerticalScrollbar() && Height() - VerticalScrollbar()->Height() > 0);
-}
-
IntRect LocalFrameView::ConvertToRootFrame(const IntRect& local_rect) const {
if (LocalFrameView* parent = ParentFrameView()) {
IntRect parent_rect = ConvertToContainingEmbeddedContentView(local_rect);
@@ -5251,6 +3721,27 @@ LayoutPoint LocalFrameView::ConvertToRootFrame(
return local_point;
}
+FloatPoint LocalFrameView::ConvertToRootFrame(
+ const FloatPoint& local_point) const {
+ if (LocalFrameView* parent = ParentFrameView()) {
+ FloatPoint parent_point =
+ ConvertToContainingEmbeddedContentView(local_point);
+ return parent->ConvertToRootFrame(parent_point);
+ }
+ return local_point;
+}
+
+LayoutRect LocalFrameView::ConvertToRootFrame(
+ const LayoutRect& local_rect) const {
+ if (LocalFrameView* parent = ParentFrameView()) {
+ LayoutPoint parent_point =
+ ConvertToContainingEmbeddedContentView(local_rect.Location());
+ LayoutRect parent_rect(parent_point, local_rect.Size());
+ return parent->ConvertToRootFrame(parent_rect);
+ }
+ return local_rect;
+}
+
IntRect LocalFrameView::ConvertFromRootFrame(
const IntRect& rect_in_root_frame) const {
if (LocalFrameView* parent = ParentFrameView()) {
@@ -5285,15 +3776,6 @@ FloatPoint LocalFrameView::ConvertFromRootFrame(
return point_in_root_frame;
}
-IntPoint LocalFrameView::ConvertFromContainingEmbeddedContentViewToScrollbar(
- const Scrollbar& scrollbar,
- const IntPoint& parent_point) const {
- IntPoint new_point = parent_point;
- // Scrollbars won't be transformed within us
- new_point.MoveBy(-scrollbar.Location());
- return new_point;
-}
-
void LocalFrameView::SetParentVisible(bool visible) {
if (IsParentVisible() == visible)
return;
@@ -5313,6 +3795,16 @@ void LocalFrameView::SetParentVisible(bool visible) {
});
}
+void LocalFrameView::SetSelfVisible(bool visible) {
+ if (visible != self_visible_) {
+ // Frame view visibility affects PLC::CanBeComposited, which in turn
+ // affects compositing inputs.
+ if (LayoutView* view = GetLayoutView())
+ view->Layer()->SetNeedsCompositingInputsUpdate();
+ }
+ self_visible_ = visible;
+}
+
void LocalFrameView::Show() {
if (!IsSelfVisible()) {
SetSelfVisible(true);
@@ -5321,7 +3813,6 @@ void LocalFrameView::Show() {
GetScrollingContext()->SetScrollGestureRegionIsDirty(true);
}
SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
- UpdateParentScrollableAreaSet();
if (IsParentVisible()) {
ForAllChildViewsAndPlugins(
[](EmbeddedContentView& embedded_content_view) {
@@ -5345,12 +3836,11 @@ void LocalFrameView::Hide() {
GetScrollingContext()->SetScrollGestureRegionIsDirty(true);
}
SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
- UpdateParentScrollableAreaSet();
}
}
int LocalFrameView::ViewportWidth() const {
- int viewport_width = GetLayoutSize(kIncludeScrollbars).Width();
+ int viewport_width = GetLayoutSize().Width();
return AdjustForAbsoluteZoom::AdjustInt(viewport_width, GetLayoutView());
}
@@ -5358,14 +3848,11 @@ ScrollableArea* LocalFrameView::GetScrollableArea() {
if (viewport_scrollable_area_)
return viewport_scrollable_area_.Get();
- return LayoutViewportScrollableArea();
+ return LayoutViewport();
}
-ScrollableArea* LocalFrameView::LayoutViewportScrollableArea() {
- if (!RuntimeEnabledFeatures::RootLayerScrollingEnabled())
- return this;
-
- auto* layout_view = this->GetLayoutView();
+PaintLayerScrollableArea* LocalFrameView::LayoutViewport() const {
+ auto* layout_view = GetLayoutView();
return layout_view ? layout_view->GetScrollableArea() : nullptr;
}
@@ -5373,14 +3860,6 @@ RootFrameViewport* LocalFrameView::GetRootFrameViewport() {
return viewport_scrollable_area_.Get();
}
-LayoutObject* LocalFrameView::ViewportLayoutObject() const {
- if (Document* document = GetFrame().GetDocument()) {
- if (Element* element = document->ViewportDefiningElement())
- return element->GetLayoutObject();
- }
- return nullptr;
-}
-
void LocalFrameView::CollectAnnotatedRegions(
LayoutObject& layout_object,
Vector<AnnotatedRegionValue>& regions) const {
@@ -5395,8 +3874,7 @@ void LocalFrameView::CollectAnnotatedRegions(
CollectAnnotatedRegions(*curr, regions);
}
-void LocalFrameView::UpdateViewportIntersectionsForSubtree(
- DocumentLifecycle::LifecycleState target_state) {
+void LocalFrameView::UpdateViewportIntersectionsForSubtree() {
// TODO(dcheng): Since LocalFrameView tree updates are deferred, FrameViews
// might still be in the LocalFrameView hierarchy even though the associated
// Document is already detached. Investigate if this check and a similar check
@@ -5405,19 +3883,29 @@ void LocalFrameView::UpdateViewportIntersectionsForSubtree(
if (!GetFrame().GetDocument()->IsActive())
return;
- if (target_state == DocumentLifecycle::kPaintClean) {
- RecordDeferredLoadingStats();
- if (!NeedsLayout()) {
- // Notify javascript IntersectionObservers
- if (GetFrame().GetDocument()->GetIntersectionObserverController()) {
- GetFrame()
- .GetDocument()
- ->GetIntersectionObserverController()
- ->ComputeTrackedIntersectionObservations();
- }
+ RecordDeferredLoadingStats();
+ if (!NeedsLayout()) {
+ // Notify javascript IntersectionObservers
+ if (GetFrame().GetDocument()->GetIntersectionObserverController()) {
+ GetFrame()
+ .GetDocument()
+ ->GetIntersectionObserverController()
+ ->ComputeTrackedIntersectionObservations();
}
}
+ for (Frame* child = frame_->Tree().FirstChild(); child;
+ child = child->Tree().NextSibling()) {
+ child->View()->UpdateViewportIntersectionsForSubtree();
+ }
+
+ intersection_observation_state_ = kNotNeeded;
+}
+
+void LocalFrameView::UpdateThrottlingStatusForSubtree() {
+ if (!GetFrame().GetDocument()->IsActive())
+ return;
+
// Don't throttle display:none frames (see updateRenderThrottlingStatus).
HTMLFrameOwnerElement* owner_element = frame_->DeprecatedLocalOwner();
if (hidden_for_throttling_ && owner_element &&
@@ -5429,11 +3917,9 @@ void LocalFrameView::UpdateViewportIntersectionsForSubtree(
kDontNotifyChildren);
}
- for (Frame* child = frame_->Tree().FirstChild(); child;
- child = child->Tree().NextSibling()) {
- child->View()->UpdateViewportIntersectionsForSubtree(target_state);
- }
- needs_intersection_observation_ = false;
+ ForAllChildLocalFrameViews([](LocalFrameView& child_view) {
+ child_view.UpdateThrottlingStatusForSubtree();
+ });
}
void LocalFrameView::UpdateRenderThrottlingStatusForTesting() {
@@ -5566,20 +4052,17 @@ void LocalFrameView::RecordDeferredLoadingStats() {
return;
}
- IntRect parent_rect = parent->FrameRect();
+ IntSize parent_size(parent->Size());
// First clause: for this rough data collection we assume the user never
// scrolls right.
- if (frame_rect.X() >= parent_rect.Width() || parent_rect.Height() <= 0)
+ if (frame_rect.X() >= parent_size.Width() || parent_size.Height() <= 0)
return;
int this_frame_screens_away = 0;
// If an frame is created above the current scoll position, this logic counts
// it as visible.
- if (frame_rect.Y() > parent->GetScrollOffset().Height()) {
- this_frame_screens_away =
- (frame_rect.Y() - parent->GetScrollOffset().Height()) /
- parent_rect.Height();
- }
+ if (frame_rect.Y() > 0)
+ this_frame_screens_away = frame_rect.Y() / parent_size.Height();
DCHECK_GE(this_frame_screens_away, 0);
int parent_screens_away = 0;
@@ -5605,10 +4088,13 @@ void LocalFrameView::SetNeedsForcedCompositingUpdate() {
parent->SetNeedsForcedCompositingUpdate();
}
-void LocalFrameView::SetNeedsIntersectionObservation() {
- needs_intersection_observation_ = true;
+void LocalFrameView::SetNeedsIntersectionObservation(
+ IntersectionObservationState state) {
+ if (intersection_observation_state_ >= state)
+ return;
+ intersection_observation_state_ = state;
if (LocalFrameView* parent = ParentFrameView())
- parent->SetNeedsIntersectionObservation();
+ parent->SetNeedsIntersectionObservation(state);
}
bool LocalFrameView::ShouldThrottleRendering() const {
@@ -5620,7 +4106,7 @@ bool LocalFrameView::ShouldThrottleRendering() const {
// Only lifecycle phases up to layout are needed to generate an
// intersection observation.
- return !needs_intersection_observation_ ||
+ return intersection_observation_state_ != kRequired ||
GetFrame().LocalFrameRoot().View()->past_layout_lifecycle_update_;
}
@@ -5711,14 +4197,12 @@ void LocalFrameView::UpdateSubFrameScrollOnMainReason(
if (frame_view.ShouldThrottleRendering())
return;
- if (!frame_view.LayoutViewportScrollableArea())
+ if (!frame_view.LayoutViewport())
return;
reasons |= frame_view.MainThreadScrollingReasonsPerFrame();
- if (GraphicsLayer* layer_for_scrolling = ToLocalFrame(frame)
- .View()
- ->LayoutViewportScrollableArea()
- ->LayerForScrolling()) {
+ if (GraphicsLayer* layer_for_scrolling =
+ ToLocalFrame(frame).View()->LayoutViewport()->LayerForScrolling()) {
if (cc::Layer* platform_layer_for_scrolling =
layer_for_scrolling->CcLayer()) {
if (reasons) {
@@ -5755,17 +4239,13 @@ MainThreadScrollingReasons LocalFrameView::MainThreadScrollingReasonsPerFrame()
if (HasBackgroundAttachmentFixedObjects())
reasons |= MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects;
- ScrollingReasons scrolling_reasons = GetScrollingReasons();
- const bool may_be_scrolled_by_input = (scrolling_reasons == kScrollable);
- const bool may_be_scrolled_by_script =
- may_be_scrolled_by_input ||
- (scrolling_reasons == kNotScrollableExplicitlyDisabled);
-
- // TODO(awoloszyn) Currently crbug.com/304810 will let certain
- // overflow:hidden elements scroll on the compositor thread, so we should
- // not let this move there path as an optimization, when we have
- // slow-repaint elements.
- if (may_be_scrolled_by_script &&
+ // Force main-thread scrolling if the frame has uncomposited position: fixed
+ // elements. Note: we care about this not only for input-scrollable frames
+ // but also for overflow: hidden frames, because script can run composited
+ // smooth-scroll animations. For this reason, we use HasOverflow instead of
+ // ScrollsOverflow (which is false for overflow: hidden).
+ if (LayoutViewport()->HasOverflow() &&
+ GetLayoutView()->Style()->VisibleToHitTesting() &&
HasVisibleSlowRepaintViewportConstrainedObjects()) {
reasons |=
MainThreadScrollingReason::kHasNonLayerViewportConstrainedObjects;
@@ -5821,7 +4301,7 @@ String LocalFrameView::MainThreadScrollingReasonsAsText() {
} else {
DCHECK(Lifecycle().GetState() >= DocumentLifecycle::kCompositingClean);
if (GraphicsLayer* layer_for_scrolling =
- LayoutViewportScrollableArea()->LayerForScrolling()) {
+ LayoutViewport()->LayerForScrolling()) {
if (cc::Layer* cc_layer = layer_for_scrolling->CcLayer())
reasons = cc_layer->main_thread_scrolling_reasons();
}
@@ -5830,40 +4310,13 @@ String LocalFrameView::MainThreadScrollingReasonsAsText() {
return String(MainThreadScrollingReason::AsText(reasons).c_str());
}
-IntRect LocalFrameView::RemoteViewportIntersection() {
- IntRect intersection(GetFrame().RemoteViewportIntersection());
- intersection.Move(ScrollOffsetInt());
- return intersection;
-}
-
-void LocalFrameView::MapQuadToAncestorFrameIncludingScrollOffset(
- LayoutRect& rect,
- const LayoutObject* descendant,
- const LayoutView* ancestor,
- MapCoordinatesFlags mode) {
- FloatQuad mapped_quad = descendant->LocalToAncestorQuad(
- FloatQuad(FloatRect(rect)), ancestor, mode);
- rect = LayoutRect(mapped_quad.BoundingBox());
-
- // localToAncestorQuad accounts for scroll offset if it encounters a remote
- // frame in the ancestor chain, otherwise it needs to be added explicitly.
- if (GetFrame().LocalFrameRoot() == GetFrame().Tree().Top() ||
- (ancestor &&
- ancestor->GetFrame()->LocalFrameRoot() == GetFrame().LocalFrameRoot())) {
- LocalFrameView* ancestor_view =
- (ancestor ? ancestor->GetFrameView()
- : ToLocalFrame(GetFrame().Tree().Top()).View());
- LayoutSize scroll_position = LayoutSize(ancestor_view->GetScrollOffset());
- rect.Move(-scroll_position);
- }
-}
-
bool LocalFrameView::MapToVisualRectInTopFrameSpace(LayoutRect& rect) {
// This is the top-level frame, so no mapping necessary.
if (frame_->IsMainFrame())
return true;
- LayoutRect viewport_intersection_rect(RemoteViewportIntersection());
+ LayoutRect viewport_intersection_rect(
+ GetFrame().RemoteViewportIntersection());
rect.Intersect(viewport_intersection_rect);
if (rect.IsEmpty())
return false;
@@ -5876,7 +4329,8 @@ void LocalFrameView::ApplyTransformForTopFrameSpace(
if (frame_->IsMainFrame())
return;
- LayoutRect viewport_intersection_rect(RemoteViewportIntersection());
+ LayoutRect viewport_intersection_rect(
+ GetFrame().RemoteViewportIntersection());
transform_state.Move(LayoutSize(-viewport_intersection_rect.X(),
-viewport_intersection_rect.Y()));
}
@@ -5886,13 +4340,6 @@ LayoutUnit LocalFrameView::CaretWidth() const {
std::max<float>(1.0, GetChromeClient()->WindowToViewportScalar(1)));
}
-ScrollbarTheme& LocalFrameView::GetPageScrollbarTheme() const {
- Page* page = frame_->GetPage();
- DCHECK(page);
-
- return page->GetScrollbarTheme();
-}
-
UkmTimeAggregator& LocalFrameView::EnsureUkmTimeAggregator() {
if (!ukm_time_aggregator_) {
ukm_time_aggregator_.reset(new UkmTimeAggregator(
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 056fc3022d6..9e546708d7c 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
@@ -29,51 +29,32 @@
#include <memory>
#include <utility>
-#include "base/auto_reset.h"
-#include "base/single_thread_task_runner.h"
#include "third_party/blink/public/common/manifest/web_display_mode.h"
#include "third_party/blink/public/platform/shape_properties.h"
-#include "third_party/blink/public/platform/web_rect.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/document_lifecycle.h"
#include "third_party/blink/renderer/core/frame/frame_view.h"
-#include "third_party/blink/renderer/core/frame/frame_view_auto_size_info.h"
#include "third_party/blink/renderer/core/frame/layout_subtree_root_list.h"
-#include "third_party/blink/renderer/core/frame/root_frame_viewport.h"
+#include "third_party/blink/renderer/core/layout/depth_ordered_layout_object_list.h"
#include "third_party/blink/renderer/core/layout/jank_tracker.h"
#include "third_party/blink/renderer/core/layout/map_coordinates_flags.h"
#include "third_party/blink/renderer/core/layout/scroll_anchor.h"
-#include "third_party/blink/renderer/core/page/chrome_client.h"
+#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
-#include "third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h"
-#include "third_party/blink/renderer/core/paint/object_paint_properties.h"
-#include "third_party/blink/renderer/core/paint/paint_invalidation_capable_scrollable_area.h"
-#include "third_party/blink/renderer/core/paint/paint_phase.h"
-#include "third_party/blink/renderer/core/paint/scrollbar_manager.h"
-#include "third_party/blink/renderer/platform/geometry/int_rect.h"
-#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
-#include "third_party/blink/renderer/platform/graphics/color.h"
-#include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
+#include "third_party/blink/renderer/core/paint/layout_object_counter.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer_client.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/scroll/scroll_types.h"
-#include "third_party/blink/renderer/platform/scroll/scrollbar.h"
-#include "third_party/blink/renderer/platform/scroll/smooth_scroll_sequencer.h"
-#include "third_party/blink/renderer/platform/ukm_time_aggregator.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/blink/renderer/platform/wtf/hash_set.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/scroll/scrollable_area.h"
namespace blink {
class AXObjectCache;
class Cursor;
+class Document;
class DocumentLifecycle;
class Element;
class ElementVisibilityObserver;
class Frame;
class FloatSize;
+class FrameViewAutoSizeInfo;
class IntRect;
class JSONArray;
class JSONObject;
@@ -86,16 +67,18 @@ class LayoutBox;
class LayoutEmbeddedObject;
class LayoutObject;
class LayoutSVGRoot;
-class LayoutScrollbarPart;
class LayoutView;
class PaintArtifactCompositor;
class PaintController;
+class PaintLayerScrollableArea;
class Page;
class PrintContext;
+class RootFrameViewport;
class ScrollingCoordinator;
class ScrollingCoordinatorContext;
class TracedValue;
class TransformState;
+class UkmTimeAggregator;
class WebPluginContainerImpl;
struct AnnotatedRegionValue;
struct IntrinsicSizingInfo;
@@ -105,8 +88,7 @@ typedef unsigned long long DOMTimeStamp;
class CORE_EXPORT LocalFrameView final
: public GarbageCollectedFinalized<LocalFrameView>,
- public FrameView,
- public PaintInvalidationCapableScrollableArea {
+ public FrameView {
USING_GARBAGE_COLLECTED_MIXIN(LocalFrameView);
friend class PaintControllerPaintTestBase;
@@ -147,22 +129,18 @@ class CORE_EXPORT LocalFrameView final
LayoutView* GetLayoutView() const;
- // If false, prevents scrollbars on the viewport even if web content would
- // make them appear. Also prevents user-input scrolls (but not programmatic
- // scrolls).
- // This API is root-layer-scrolling-aware (affects root PLSA in RLS mode).
- void SetCanHaveScrollbars(bool);
+ void SetCanHaveScrollbars(bool can_have_scrollbars) {
+ can_have_scrollbars_ = can_have_scrollbars;
+ }
bool CanHaveScrollbars() const { return can_have_scrollbars_; }
-
- Scrollbar* CreateScrollbar(ScrollbarOrientation) override;
-
- void SnapAfterScrollbarDragging(ScrollbarOrientation) override;
+ bool VisualViewportSuppliesScrollbars();
void SetLayoutOverflowSize(const IntSize&);
void UpdateLayout();
bool DidFirstLayout() const;
bool LifecycleUpdatesActive() const;
+ void SetLifecycleUpdatesThrottledForTesting();
void ScheduleRelayout();
void ScheduleRelayoutOfSubtree(LayoutObject*);
bool LayoutPending() const;
@@ -189,8 +167,22 @@ class CORE_EXPORT LocalFrameView final
// Marks this frame, and ancestor frames, as needing one intersection
// observervation. This overrides throttling for one frame, up to
- // kLayoutClean.
- void SetNeedsIntersectionObservation();
+ // kLayoutClean. The order of these enums is important - they must proceed
+ // from "least required to most required".
+ enum IntersectionObservationState {
+ // The next painting frame does not need an intersection observation.
+ kNotNeeded = 0,
+ // The next painting frame needs an intersection observation.
+ kDesired = 1,
+ // The next painting frame must be generated up to intersection observation
+ // (even if frame is throttled).
+ kRequired = 2
+ };
+
+ // Sets the internal IntersectionObservationState to the max of the
+ // current value and the provided one.
+ void SetNeedsIntersectionObservation(IntersectionObservationState);
+
// Marks this frame, and ancestor frames, as needing a mandatory compositing
// update. This overrides throttling for one frame, up to kCompositingClean.
void SetNeedsForcedCompositingUpdate();
@@ -200,9 +192,7 @@ class CORE_EXPORT LocalFrameView final
// Methods for getting/setting the size Blink should use to layout the
// contents.
- // NOTE: Scrollbar exclusion is based on the LocalFrameView's scrollbars. To
- // exclude scrollbars on the root PaintLayer, use LayoutView::layoutSize.
- IntSize GetLayoutSize(IncludeScrollbarsInRect = kExcludeScrollbars) const;
+ IntSize GetLayoutSize() const { return layout_size_; }
void SetLayoutSize(const IntSize&);
// If this is set to false, the layout size will need to be explicitly set by
@@ -219,14 +209,9 @@ class CORE_EXPORT LocalFrameView final
void UpdateAcceleratedCompositingSettings();
- void RecalcOverflowAfterStyleChange();
void UpdateCountersAfterStyleChange();
- bool IsEnclosedInCompositingLayer() const;
-
void Dispose() override;
- void DetachScrollbars();
- void RecalculateCustomScrollbarStyle();
void InvalidateAllCustomScrollbarsOnActiveChanged();
// True if the LocalFrameView's base background color is completely opaque.
@@ -246,7 +231,6 @@ class CORE_EXPORT LocalFrameView final
void SetInputEventsScaleForEmulation(float);
void DidChangeScrollOffset();
- void DidUpdateElasticOverscroll();
void ViewportSizeChanged(bool width_changed, bool height_changed);
void MarkViewportConstrainedObjectsForLayout(bool width_changed,
@@ -289,8 +273,6 @@ class CORE_EXPORT LocalFrameView final
void DidAttachDocument();
- void RestoreScrollbar();
-
void PostLayoutTimerFired(TimerBase*);
bool SafeToPropagateScrollToParent() const {
@@ -315,21 +297,18 @@ class CORE_EXPORT LocalFrameView final
// PaintClean.
void UpdateAllLifecyclePhases();
- // Everything except paint (the last phase).
- bool UpdateAllLifecyclePhasesExceptPaint();
-
- // Printing needs everything up-to-date except paint (which will be done
- // specially). We may also print a detached frame or a descendant of a
- // detached frame and need special handling of the frame.
- void UpdateLifecyclePhasesForPrinting();
-
// Computes the style, layout, compositing and pre-paint lifecycle stages
// if needed.
// After calling this method, all frames will be in a lifecycle
// state >= PrePaintClean, unless the frame was throttled or inactive.
// Returns whether the lifecycle was successfully updated to the
// desired state.
- bool UpdateLifecycleToPrePaintClean();
+ bool UpdateAllLifecyclePhasesExceptPaint();
+
+ // Printing needs everything up-to-date except paint (which will be done
+ // specially). We may also print a detached frame or a descendant of a
+ // detached frame and need special handling of the frame.
+ void UpdateLifecyclePhasesForPrinting();
// After calling this method, all frames will be in a lifecycle
// state >= CompositingClean, and scrolling has been updated (unless
@@ -391,36 +370,13 @@ class CORE_EXPORT LocalFrameView final
FloatPoint ConvertToLayoutObject(const LayoutObject&,
const FloatPoint&) const;
- bool IsFrameViewScrollCorner(LayoutScrollbarPart* scroll_corner) const {
- return scroll_corner_ == scroll_corner;
- }
-
- enum ScrollingReasons {
- kScrollable,
- kNotScrollableNoOverflow,
- kNotScrollableNotVisible,
- kNotScrollableExplicitlyDisabled
- };
-
- ScrollingReasons GetScrollingReasons() const;
- bool IsScrollable() const override;
- bool IsProgrammaticallyScrollable() override;
-
- IntPoint LastKnownMousePosition() const override;
bool ShouldSetCursor() const;
void SetCursor(const Cursor&);
- bool ScrollbarsCanBeActive() const override;
- void ScrollbarVisibilityChanged() override;
- void ScrollbarFrameRectChanged() override;
-
// FIXME: Remove this method once plugin loading is decoupled from layout.
void FlushAnyPendingPostLayoutTasks();
- bool ShouldSuspendScrollAnimations() const override;
- void ScrollbarStyleChanged() override;
-
static void SetInitialTracksPaintInvalidationsForTesting(bool);
// These methods are for testing.
@@ -432,15 +388,15 @@ class CORE_EXPORT LocalFrameView final
PaintInvalidationReason);
std::unique_ptr<JSONArray> TrackedObjectPaintInvalidationsAsJSON() const;
- using ScrollableAreaSet = HeapHashSet<Member<ScrollableArea>>;
- void AddScrollableArea(ScrollableArea*);
- void RemoveScrollableArea(ScrollableArea*);
+ using ScrollableAreaSet = HeapHashSet<Member<PaintLayerScrollableArea>>;
+ void AddScrollableArea(PaintLayerScrollableArea*);
+ void RemoveScrollableArea(PaintLayerScrollableArea*);
const ScrollableAreaSet* ScrollableAreas() const {
return scrollable_areas_.Get();
}
- void AddAnimatingScrollableArea(ScrollableArea*);
- void RemoveAnimatingScrollableArea(ScrollableArea*);
+ void AddAnimatingScrollableArea(PaintLayerScrollableArea*);
+ void RemoveAnimatingScrollableArea(PaintLayerScrollableArea*);
const ScrollableAreaSet* AnimatingScrollableAreas() const {
return animating_scrollable_areas_.Get();
}
@@ -454,60 +410,17 @@ class CORE_EXPORT LocalFrameView final
void RemoveResizerArea(LayoutBox&);
const ResizerAreaSet* ResizerAreas() const { return resizer_areas_.get(); }
- bool ShouldUseIntegerScrollOffset() const override;
-
- bool IsActive() const override;
-
- // Override scrollbar notifications to update the AXObject cache.
- void DidAddScrollbar(Scrollbar&, ScrollbarOrientation) override;
+ void ScheduleAnimation();
// FIXME: This should probably be renamed as the 'inSubtreeLayout' parameter
// passed around the LocalFrameView layout methods can be true while this
// returns false.
bool IsSubtreeLayout() const { return !layout_subtree_root_list_.IsEmpty(); }
- // Sets the tickmarks for the LocalFrameView, overriding the default behavior
- // which is to display the tickmarks corresponding to find results.
- // If |m_tickmarks| is empty, the default behavior is restored.
- void SetTickmarks(const Vector<IntRect>& tickmarks) {
- tickmarks_ = tickmarks;
- InvalidatePaintForTickmarks();
- }
-
- void InvalidatePaintForTickmarks();
-
- IntSize MaximumScrollOffsetInt() const override;
-
- // ScrollableArea interface
- void GetTickmarks(Vector<IntRect>&) const override;
- IntRect ScrollableAreaBoundingBox() const override;
- CompositorElementId GetCompositorElementId() const override;
- bool ScrollAnimatorEnabled() const override;
- bool ShouldScrollOnMainThread() const override;
- PaintLayer* Layer() const override;
- int ScrollSize(ScrollbarOrientation) const override;
- bool IsScrollCornerVisible() const override;
- bool UpdateAfterCompositingChange() override;
- bool UserInputScrollable(ScrollbarOrientation) const override;
- bool ShouldPlaceVerticalScrollbarOnLeft() const override;
- bool ScheduleAnimation() override;
- CompositorAnimationHost* GetCompositorAnimationHost() const override;
- CompositorAnimationTimeline* GetCompositorAnimationTimeline() const override;
- LayoutBox* GetLayoutBox() const override;
- FloatQuad LocalToVisibleContentQuad(const FloatQuad&,
- const LayoutObject*,
- unsigned = 0) const final;
- scoped_refptr<base::SingleThreadTaskRunner> GetTimerTaskRunner() const final;
-
- LayoutRect ScrollIntoView(const LayoutRect& rect_in_absolute,
- const WebScrollIntoViewParams& params) override;
-
// The window that hosts the LocalFrameView. The LocalFrameView will
// communicate scrolls and repaints to the host window in the window's
// coordinate space.
- ChromeClient* GetChromeClient() const override;
-
- SmoothScrollSequencer* GetSmoothScrollSequencer() const override;
+ PlatformChromeClient* GetChromeClient() const;
// Functions for child manipulation and inspection.
bool IsSelfVisible() const {
@@ -520,7 +433,7 @@ class CORE_EXPORT LocalFrameView final
return self_visible_ && parent_visible_;
} // Whether or not we are actually visible.
void SetParentVisible(bool) override;
- void SetSelfVisible(bool v) { self_visible_ = v; }
+ void SetSelfVisible(bool);
void AttachToLayout() override;
void DetachFromLayout() override;
bool IsAttached() const override { return is_attached_; }
@@ -532,112 +445,23 @@ class CORE_EXPORT LocalFrameView final
void RemoveScrollbar(Scrollbar*);
void AddScrollbar(Scrollbar*);
- // If the scroll view does not use a native widget, then it will have
- // cross-platform Scrollbars. These functions can be used to obtain those
- // scrollbars.
- Scrollbar* HorizontalScrollbar() const override {
- return scrollbar_manager_.HorizontalScrollbar();
- }
- Scrollbar* VerticalScrollbar() const override {
- return scrollbar_manager_.VerticalScrollbar();
- }
- LayoutScrollbarPart* ScrollCorner() const override { return scroll_corner_; }
-
- void PositionScrollbarLayers();
-
- // Functions for setting and retrieving the scrolling mode in each axis
- // (horizontal/vertical). The mode has values of AlwaysOff, AlwaysOn, and
- // Auto. AlwaysOff means never show a scrollbar, AlwaysOn means always show a
- // scrollbar. Auto means show a scrollbar only when one is needed.
- // Note that for platforms with native widgets, these modes are considered
- // advisory. In other words the underlying native widget may choose not to
- // honor the requested modes.
- void SetScrollbarModes(ScrollbarMode horizontal_mode,
- ScrollbarMode vertical_mode);
- void SetHorizontalScrollbarMode(ScrollbarMode mode) {
- SetScrollbarModes(mode, vertical_scrollbar_mode_);
- }
- void SetVerticalScrollbarMode(ScrollbarMode mode) {
- SetScrollbarModes(horizontal_scrollbar_mode_, mode);
- }
- ScrollbarMode EffectiveHorizontalScrollbarMode() const;
- ScrollbarMode EffectiveVerticalScrollbarMode() const;
-
- // The visible content rect has a location that is the scrolled offset of
- // the document. The width and height are the layout viewport width and
- // height. By default the scrollbars themselves are excluded from this
- // rectangle, but an optional boolean argument allows them to be included.
- IntRect VisibleContentRect(
- IncludeScrollbarsInRect = kExcludeScrollbars) const override;
- IntSize VisibleContentSize(
- IncludeScrollbarsInRect = kExcludeScrollbars) const;
-
- // The visible scroll snapport rect is contracted from the visible content
- // rect, by the amount of the document's scroll-padding.
- LayoutRect VisibleScrollSnapportRect() const override;
-
// Clips the provided rect to the visible content area. For this purpose, we
// also query the chrome client for any active overrides to the visible area
// (e.g. DevTool's viewport override).
void ClipPaintRect(FloatRect*) const;
- // Functions for getting/setting the size of the document contained inside the
- // LocalFrameView (as an IntSize or as individual width and height values).
- // Always at least as big as the visibleWidth()/visibleHeight().
- IntSize ContentsSize() const override;
- int ContentsWidth() const { return ContentsSize().Width(); }
- int ContentsHeight() const { return ContentsSize().Height(); }
-
- // Functions for querying the current scrolled offset (both as a point, a
- // size, or as individual X and Y values). Be careful in using the Float
- // version getScrollOffset() and getScrollOffset(). They are meant to be used
- // to communicate the fractional scroll offset with chromium compositor which
- // can do sub-pixel positioning. Do not call these if the scroll offset is
- // used in Blink for positioning. Use the Int version instead.
- IntSize ScrollOffsetInt() const override {
- return ToIntSize(VisibleContentRect().Location());
- }
- ScrollOffset GetScrollOffset() const override { return scroll_offset_; }
- ScrollOffset PendingScrollDelta() const { return pending_scroll_delta_; }
- IntSize MinimumScrollOffsetInt()
- const override; // The minimum offset we can be scrolled to.
- int ScrollX() const { return ScrollOffsetInt().Width(); }
- int ScrollY() const { return ScrollOffsetInt().Height(); }
-
- // Scroll the actual contents of the view (either blitting or invalidating as
- // needed).
- void ScrollContents(const IntSize& scroll_delta);
-
- // This gives us a means of blocking updating our scrollbars until the first
- // layout has occurred.
- void SetScrollbarsSuppressed(bool suppressed) {
- scrollbars_suppressed_ = suppressed;
- }
- bool ScrollbarsSuppressed() const { return scrollbars_suppressed_; }
-
// Indicates the root layer's scroll offset changed since the last frame
void SetRootLayerDidScroll() { root_layer_did_scroll_ = true; }
// Methods for converting between this frame and other coordinate spaces.
// For definitions and an explanation of the varous spaces, please see:
// http://www.chromium.org/developers/design-documents/blink-coordinate-spaces
- // WARNING: With --root-layer-scrolling, these become ambiguous since content
- // coordinates mean something different. These will eventually be replaced,
- // see comments below about writing RLS agnostic conversions.
- IntPoint RootFrameToContents(const IntPoint&) const;
- FloatPoint RootFrameToContents(const FloatPoint&) const;
- LayoutPoint RootFrameToContents(const LayoutPoint&) const;
- IntRect RootFrameToContents(const IntRect&) const;
- IntPoint ContentsToRootFrame(const IntPoint&) const;
- LayoutPoint ContentsToRootFrame(const LayoutPoint&) const;
- IntRect ContentsToRootFrame(const IntRect&) const;
-
- IntRect ViewportToContents(const IntRect&) const;
- IntRect ContentsToViewport(const IntRect&) const;
- IntPoint ContentsToViewport(const IntPoint&) const;
- IntPoint ViewportToContents(const IntPoint&) const;
- FloatPoint ViewportToContents(const FloatPoint&) const;
- LayoutPoint ViewportToContents(const LayoutPoint&) const;
+ IntRect ViewportToFrame(const IntRect&) const;
+ IntRect FrameToViewport(const IntRect&) const;
+ IntPoint FrameToViewport(const IntPoint&) const;
+ IntPoint ViewportToFrame(const IntPoint&) const;
+ FloatPoint ViewportToFrame(const FloatPoint&) const;
+ LayoutPoint ViewportToFrame(const LayoutPoint&) const;
// FIXME: Some external callers expect to get back a rect that's positioned
// in viewport space, but sized in CSS pixels. This is an artifact of the
@@ -645,71 +469,31 @@ class CORE_EXPORT LocalFrameView final
// fully in viewport space. crbug.com/459591.
IntPoint SoonToBeRemovedUnscaledViewportToContents(const IntPoint&) const;
- // Methods for converting between Frame and Content (i.e. Document)
- // coordinates. Frame coordinates are relative to the top left corner of the
- // frame and so they are affected by scroll offset. Content coordinates are
- // relative to the document's top left corner and thus are not affected by
- // scroll offset.
- // WARNING: With --root-layer-scrolling, these become ambiguous since content
- // coordinates mean something different. These will eventually be replaced,
- // see comments below about writing RLS agnostic conversions.
- IntPoint ContentsToFrame(const IntPoint&) const;
- LayoutPoint ContentsToFrame(const LayoutPoint&) const;
- FloatPoint ContentsToFrame(const FloatPoint&) const;
- IntRect ContentsToFrame(const IntRect&) const;
- IntPoint FrameToContents(const IntPoint&) const;
- FloatPoint FrameToContents(const FloatPoint&) const;
- LayoutPoint FrameToContents(const LayoutPoint&) const;
- IntRect FrameToContents(const IntRect&) const;
-
// Functions for converting to screen coordinates.
- IntRect ContentsToScreen(const IntRect&) const;
-
- // For platforms that need to hit test scrollbars from within the engine's
- // event handlers (like Win32).
- Scrollbar* ScrollbarAtFramePoint(const IntPoint&);
-
- // Converts from/to local "frame" coordinates to the root "frame"
- // coordinates. Note: with root-layer-scrolls, "frame" coordinates become
- // equivalent to "absoltue" coordinates since the LayoutView (same size and
- // origin as the frame) clips and scrolls content below it. Without RLS, the
- // LayoutView is the size of the entire document and doesn't scroll itself so
- // "absolute" means "document". To write RLS agnostic-code, use (or add) the
- // methods below these ones. For details, see:
- // http://www.chromium.org/developers/design-documents/blink-coordinate-spaces
+ IntRect FrameToScreen(const IntRect&) const;
+
+ // Converts from/to local frame coordinates to the root frame coordinates.
IntRect ConvertToRootFrame(const IntRect&) const;
IntPoint ConvertToRootFrame(const IntPoint&) const;
LayoutPoint ConvertToRootFrame(const LayoutPoint&) const;
+ FloatPoint ConvertToRootFrame(const FloatPoint&) const;
+ LayoutRect ConvertToRootFrame(const LayoutRect&) const;
IntRect ConvertFromRootFrame(const IntRect&) const;
- IntPoint ConvertFromRootFrame(const IntPoint&) const override;
+ IntPoint ConvertFromRootFrame(const IntPoint&) const;
FloatPoint ConvertFromRootFrame(const FloatPoint&) const;
LayoutPoint ConvertFromRootFrame(const LayoutPoint&) const;
IntPoint ConvertSelfToChild(const EmbeddedContentView&,
const IntPoint&) const;
- // root-layer-scrolls agnostic conversion functions:
- // Maps from "absolute" coordinates to root frame coordinates. TODO(bokan)
- // This is a temporary shim to hide the difference between root-layer-scrolls
- // being on and off. Once RLS is turned on, this becomes (and can be replaced
- // with) ConvertToRootFrame since "frame coordinates" == "absolute
- // coordinates" in RLS. Without RLS, "absolute coordinates" == "document
- // coordinates". https://crbug.com/417782.
- IntRect AbsoluteToRootFrame(const IntRect&) const;
- IntPoint AbsoluteToRootFrame(const IntPoint&) const;
- LayoutRect AbsoluteToRootFrame(const LayoutRect&) const;
IntRect RootFrameToDocument(const IntRect&);
IntPoint RootFrameToDocument(const IntPoint&);
FloatPoint RootFrameToDocument(const FloatPoint&);
- LayoutPoint RootFrameToAbsolute(const LayoutPoint&) const;
- IntPoint RootFrameToAbsolute(const IntPoint&) const;
- IntRect RootFrameToAbsolute(const IntRect&) const;
- DoublePoint DocumentToAbsolute(const DoublePoint&) const;
- FloatPoint DocumentToAbsolute(const FloatPoint&) const;
- LayoutPoint DocumentToAbsolute(const LayoutPoint&) const;
- LayoutRect DocumentToAbsolute(const LayoutRect&) const;
-
- LayoutPoint AbsoluteToDocument(const LayoutPoint&) const;
- LayoutRect AbsoluteToDocument(const LayoutRect&) const;
+ DoublePoint DocumentToFrame(const DoublePoint&) const;
+ FloatPoint DocumentToFrame(const FloatPoint&) const;
+ LayoutPoint DocumentToFrame(const LayoutPoint&) const;
+ LayoutRect DocumentToFrame(const LayoutRect&) const;
+ LayoutPoint FrameToDocument(const LayoutPoint&) const;
+ LayoutRect FrameToDocument(const LayoutRect&) const;
// Handles painting of the contents of the view as well as the scrollbars.
void Paint(GraphicsContext&,
@@ -728,14 +512,6 @@ class CORE_EXPORT LocalFrameView final
void Show() override;
void Hide() override;
- bool IsPointInScrollbarCorner(const IntPoint&);
- bool ScrollbarCornerPresent() const;
- IntRect ScrollCornerRect() const override;
-
- IntPoint ConvertFromContainingEmbeddedContentViewToScrollbar(
- const Scrollbar&,
- const IntPoint&) const override;
-
bool IsLocalFrameView() const override { return true; }
void Trace(blink::Visitor*) override;
@@ -743,14 +519,14 @@ class CORE_EXPORT LocalFrameView final
// Returns the scrollable area for the frame. For the root frame, this will
// be the RootFrameViewport, which adds pinch-zoom semantics to scrolling.
- // For non-root frames, this will be the the ScrollableArea used by the
- // LocalFrameView, depending on whether root-layer-scrolls is enabled.
+ // For non-root frames, this will be the ScrollableArea of the LayoutView.
ScrollableArea* GetScrollableArea();
- // Used to get at the underlying layoutViewport in the rare instances where
- // we actually want to scroll *just* the layout viewport (e.g. when sending
- // deltas from CC). For typical scrolling cases, use getScrollableArea().
- ScrollableArea* LayoutViewportScrollableArea();
+ // Returns the ScrollableArea of the LayoutView, a.k.a. the layout viewport.
+ // In the root frame, this is the "outer" viewport in the pinch-zoom dual
+ // viewport model. Callers that need awareness of both inner and outer
+ // viewports should use GetScrollableArea() instead.
+ PaintLayerScrollableArea* LayoutViewport() const;
// If this is the main frame, this will return the RootFrameViewport used
// to scroll the main frame. Otherwise returns nullptr. Unless you need a
@@ -777,30 +553,8 @@ class CORE_EXPORT LocalFrameView final
void BeginLifecycleUpdates();
- // TODO(pdr): Remove the paint property update bits from LocalFrameView in
- // favor of using LayoutView.
- // Paint properties (e.g., m_preTranslation, etc.) are built from the
- // LocalFrameView's state (e.g., x(), y(), etc.) as well as inherited context.
- // When these inputs change, setNeedsPaintPropertyUpdate will cause a paint
- // property tree update during the next document lifecycle update.
- // setNeedsPaintPropertyUpdate also sets the owning layout tree as needing a
- // paint property update.
+ // Shorthands of LayoutView's corresponding methods.
void SetNeedsPaintPropertyUpdate();
-#if DCHECK_IS_ON()
- // Similar to setNeedsPaintPropertyUpdate() but does not set the owning layout
- // tree as needing a paint property update.
- void SetOnlyThisNeedsPaintPropertyUpdateForTesting() {
- needs_paint_property_update_ = true;
- }
-#endif
- void ClearNeedsPaintPropertyUpdate() {
- DCHECK_EQ(Lifecycle().GetState(), DocumentLifecycle::kInPrePaint);
- needs_paint_property_update_ = false;
- }
- bool NeedsPaintPropertyUpdate() const { return needs_paint_property_update_; }
-
- // Set when the whole frame subtree needs full paint property update,
- // e.g. when beginning or finishing printing.
void SetSubtreeNeedsPaintPropertyUpdate();
// Viewport size that should be used for viewport units (i.e. 'vh'/'vw').
@@ -812,10 +566,6 @@ class CORE_EXPORT LocalFrameView final
// queries.
FloatSize ViewportSizeForMediaQueries() const;
- bool RestoreScrollAnchor(const SerializedAnchor&) override;
- ScrollAnchor* GetScrollAnchor() override { return &scroll_anchor_; }
- void ClearScrollAnchor();
- bool ShouldPerformScrollAnchoring() const override;
void EnqueueScrollAnchoringAdjustment(ScrollableArea*);
void DequeueScrollAnchoringAdjustment(ScrollableArea*);
void PerformScrollAnchoringAdjustments();
@@ -844,32 +594,13 @@ class CORE_EXPORT LocalFrameView final
bool HasVisibleSlowRepaintViewportConstrainedObjects() const;
- // Called on a view for a LocalFrame with a RemoteFrame parent. This makes
- // viewport intersection available that accounts for remote ancestor frames
- // and their respective scroll positions, clips, etc.
- void SetViewportIntersectionFromParent(const IntRect&);
- IntRect RemoteViewportIntersection();
-
- // This method uses localToAncestorQuad to map a rect into an ancestor's
- // coordinate space, while guaranteeing that the top-level scroll offset
- // is accounted for. This is needed because LayoutView::mapLocalToAncestor()
- // implicitly includes the ancestor frame's scroll offset when there is
- // a remote frame in the ancestor chain, but does not include it when
- // there are only local frames in the frame tree.
- void MapQuadToAncestorFrameIncludingScrollOffset(
- LayoutRect&,
- const LayoutObject* descendant,
- const LayoutView* ancestor,
- MapCoordinatesFlags mode);
-
bool MapToVisualRectInTopFrameSpace(LayoutRect&);
void ApplyTransformForTopFrameSpace(TransformState&);
void CrossOriginStatusChanged();
- // The visual viewport can supply scrollbars which affect the existence of
- // our scrollbars (see: computeScrollbarExistence).
+ // The visual viewport can supply scrollbars.
void VisualViewportScrollbarsChanged();
LayoutUnit CaretWidth() const;
@@ -891,8 +622,6 @@ class CORE_EXPORT LocalFrameView final
return paint_artifact_compositor_.get();
}
- ScrollbarTheme& GetPageScrollbarTheme() const override;
-
enum ForceThrottlingInvalidationBehavior {
kDontForceThrottlingInvalidation,
kForceThrottlingInvalidation
@@ -915,65 +644,17 @@ class CORE_EXPORT LocalFrameView final
void ScrollableAreasDidChange();
ScrollingCoordinatorContext* GetScrollingContext() const;
+ CompositorAnimationHost* GetCompositorAnimationHost() const;
+ CompositorAnimationTimeline* GetCompositorAnimationTimeline() const;
void ScrollAndFocusFragmentAnchor();
JankTracker& GetJankTracker() { return jank_tracker_; }
protected:
- // Scroll the content via the compositor.
- bool ScrollContentsFastPath(const IntSize& scroll_delta);
-
- // Scroll the content by invalidating everything.
- void ScrollContentsSlowPath();
-
- ScrollBehavior ScrollBehaviorStyle() const override;
-
- void ScrollContentsIfNeeded();
void NotifyFrameRectsChangedIfNeeded();
- enum ComputeScrollbarExistenceOption { kFirstPass, kIncremental };
- void ComputeScrollbarExistence(bool& new_has_horizontal_scrollbar,
- bool& new_has_vertical_scrollbar,
- const IntSize& doc_size,
- ComputeScrollbarExistenceOption = kFirstPass);
- void UpdateScrollbarGeometry();
-
- // Called to update the scrollbars to accurately reflect the state of the
- // view.
- void UpdateScrollbars();
- void UpdateScrollbarsIfNeeded();
-
- class InUpdateScrollbarsScope {
- STACK_ALLOCATED();
-
- public:
- explicit InUpdateScrollbarsScope(LocalFrameView* view)
- : scope_(&view->in_update_scrollbars_, true) {}
-
- private:
- base::AutoReset<bool> scope_;
- };
-
private:
explicit LocalFrameView(LocalFrame&, IntRect);
- class ScrollbarManager : public blink::ScrollbarManager {
- DISALLOW_NEW();
-
- // Helper class to manage the life cycle of Scrollbar objects.
- public:
- ScrollbarManager(LocalFrameView& scroller)
- : blink::ScrollbarManager(scroller) {}
-
- void SetHasHorizontalScrollbar(bool has_scrollbar) override;
- void SetHasVerticalScrollbar(bool has_scrollbar) override;
-
- // TODO(ymalik): This should be hidden and all calls should go through
- // setHas*Scrollbar functions above.
- Scrollbar* CreateScrollbar(ScrollbarOrientation) override;
-
- protected:
- void DestroyScrollbar(ScrollbarOrientation) override;
- };
void PaintInternal(GraphicsContext&,
const GlobalPaintFlags,
@@ -982,10 +663,6 @@ class CORE_EXPORT LocalFrameView final
LocalFrameView* ParentFrameView() const;
LayoutSVGRoot* EmbeddedReplacedContent() const;
- void UpdateScrollOffset(const ScrollOffset&, ScrollType) override;
-
- void UpdateScrollbarEnabledState();
-
void DispatchEventsForPrintingOnAllFrames();
void SetupPrintContext();
@@ -996,7 +673,6 @@ class CORE_EXPORT LocalFrameView final
bool UpdateLifecyclePhasesInternal(
DocumentLifecycle::LifecycleState target_state);
- void ScrollContentsIfNeededRecursive();
void NotifyFrameRectsChangedIfNeededRecursive();
void UpdateStyleAndLayoutIfNeededRecursive();
void PrePaint();
@@ -1012,8 +688,6 @@ class CORE_EXPORT LocalFrameView final
void ClearLayoutSubtreeRootsAndMarkContainingBlocks();
- bool ContentsInCompositedLayer() const;
-
void PerformPreLayoutTasks();
void PerformLayout(bool in_subtree_layout);
void ScheduleOrPerformPostLayoutTasks();
@@ -1023,14 +697,12 @@ class CORE_EXPORT LocalFrameView final
DocumentLifecycle& Lifecycle() const;
- void ContentsResized() override;
- void ScrollbarExistenceMaybeChanged();
-
// Methods to do point conversion via layoutObjects, in order to take
// transforms into account.
IntRect ConvertToContainingEmbeddedContentView(const IntRect&) const;
IntPoint ConvertToContainingEmbeddedContentView(const IntPoint&) const;
LayoutPoint ConvertToContainingEmbeddedContentView(const LayoutPoint&) const;
+ FloatPoint ConvertToContainingEmbeddedContentView(const FloatPoint&) const;
IntRect ConvertFromContainingEmbeddedContentView(const IntRect&) const;
IntPoint ConvertFromContainingEmbeddedContentView(const IntPoint&) const;
LayoutPoint ConvertFromContainingEmbeddedContentView(
@@ -1039,62 +711,31 @@ class CORE_EXPORT LocalFrameView final
DoublePoint ConvertFromContainingEmbeddedContentView(
const DoublePoint&) const;
- void DidChangeGlobalRootScroller() override;
-
void UpdateGeometriesIfNeeded();
bool WasViewportResized();
void SendResizeEventIfNeeded();
- void UpdateParentScrollableAreaSet();
-
void ScheduleUpdatePluginsIfNecessary();
void UpdatePluginsTimerFired(TimerBase*);
bool UpdatePlugins();
bool ProcessUrlFragmentHelper(const String&, UrlFragmentBehavior);
- void DidScrollTimerFired(TimerBase*);
-
- void UpdateLayersAndCompositingAfterScrollIfNeeded();
+ bool ParseCSSFragmentIdentifier(const String&, String*);
+ Element* FindCSSFragmentAnchor(const AtomicString&, Document*);
void UpdateCompositedSelectionIfNeeded();
void SetNeedsCompositingUpdate(CompositingUpdateType);
- // Returns true if the LocalFrameView's own scrollbars overlay its content
- // when visible.
- bool HasOverlayScrollbars() const;
-
- // Returns true if the frame should use custom scrollbars. If true, sets
- // customScrollbarElement to the element that supplies the scrollbar's style
- // information.
- bool ShouldUseCustomScrollbars(Element*& custom_scrollbar_element) const;
-
- // Returns true if a scrollbar needs to go from native -> custom or vice
- // versa, or if a custom scrollbar has a stale owner.
- bool NeedsScrollbarReconstruction() const;
-
- bool ShouldIgnoreOverflowHidden() const;
-
- void UpdateScrollCorner();
-
AXObjectCache* ExistingAXObjectCache() const;
void SetLayoutSizeInternal(const IntSize&);
- bool AdjustScrollbarExistence(ComputeScrollbarExistenceOption = kFirstPass);
- void AdjustScrollbarOpacity();
- void AdjustScrollOffsetFromUpdateScrollbars();
- bool VisualViewportSuppliesScrollbars();
-
ScrollingCoordinator* GetScrollingCoordinator() const;
void PrepareLayoutAnalyzer();
std::unique_ptr<TracedValue> AnalyzerCounters();
- // LayoutObject for the viewport-defining element (see
- // Document::viewportDefiningElement).
- LayoutObject* ViewportLayoutObject() const;
-
void CollectAnnotatedRegions(LayoutObject&,
Vector<AnnotatedRegionValue>&) const;
@@ -1107,14 +748,11 @@ class CORE_EXPORT LocalFrameView final
template <typename Function>
void ForAllNonThrottledLocalFrameViews(const Function&);
- void UpdateViewportIntersectionsForSubtree(
- DocumentLifecycle::LifecycleState) override;
+ void UpdateViewportIntersectionsForSubtree() override;
+ void UpdateThrottlingStatusForSubtree();
void NotifyResizeObservers();
- // PaintInvalidationCapableScrollableArea
- LayoutScrollbarPart* Resizer() const override { return nullptr; }
-
bool CheckLayoutInvalidationIsAllowed() const;
PaintController* GetPaintController() { return paint_controller_.get(); }
@@ -1166,13 +804,10 @@ class CORE_EXPORT LocalFrameView final
unsigned visually_non_empty_character_count_;
uint64_t visually_non_empty_pixel_count_;
bool is_visually_non_empty_;
- FirstMeaningfulPaintDetector::LayoutObjectCounter layout_object_counter_;
+ LayoutObjectCounter layout_object_counter_;
Member<Node> fragment_anchor_;
- // layoutObject to hold our custom scroll corner.
- LayoutScrollbarPart* scroll_corner_;
-
Member<ScrollableAreaSet> scrollable_areas_;
Member<ScrollableAreaSet> animating_scrollable_areas_;
std::unique_ptr<ResizerAreaSet> resizer_areas_;
@@ -1187,10 +822,6 @@ class CORE_EXPORT LocalFrameView final
IntSize initial_viewport_size_;
bool layout_size_fixed_to_frame_size_;
- TaskRunnerTimer<LocalFrameView> did_scroll_timer_;
-
- Vector<IntRect> tickmarks_;
-
bool needs_update_geometries_;
#if DCHECK_IS_ON()
@@ -1198,22 +829,14 @@ class CORE_EXPORT LocalFrameView final
bool has_been_disposed_ = false;
#endif
- ScrollbarMode horizontal_scrollbar_mode_;
- ScrollbarMode vertical_scrollbar_mode_;
-
PluginSet plugins_;
HeapHashSet<Member<Scrollbar>> scrollbars_;
- ScrollOffset pending_scroll_delta_;
- ScrollOffset scroll_offset_;
-
// TODO(bokan): This is unneeded when root-layer-scrolls is turned on.
// crbug.com/417782.
IntSize layout_overflow_size_;
- bool scrollbars_suppressed_;
bool root_layer_did_scroll_;
- bool in_update_scrollbars_;
std::unique_ptr<LayoutAnalyzer> analyzer_;
@@ -1233,27 +856,19 @@ class CORE_EXPORT LocalFrameView final
bool subtree_throttled_;
bool lifecycle_updates_throttled_;
- // Whether the paint properties need to be updated. For more details, see
- // LocalFrameView::needsPaintPropertyUpdate().
- bool needs_paint_property_update_;
-
// This is set on the local root frame view only.
DocumentLifecycle::LifecycleState
current_update_lifecycle_phases_target_state_;
bool past_layout_lifecycle_update_;
- ScrollAnchor scroll_anchor_;
using AnchoringAdjustmentQueue =
HeapLinkedHashSet<WeakMember<ScrollableArea>>;
AnchoringAdjustmentQueue anchoring_adjustment_queue_;
- // ScrollbarManager holds the Scrollbar instances.
- ScrollbarManager scrollbar_manager_;
-
- bool needs_scrollbars_update_;
bool suppress_adjust_view_size_;
bool allows_layout_invalidation_after_layout_clean_;
- bool needs_intersection_observation_;
+
+ IntersectionObservationState intersection_observation_state_;
bool needs_forced_compositing_update_;
bool needs_focus_on_fragment_;
@@ -1322,11 +937,6 @@ DEFINE_TYPE_CASTS(LocalFrameView,
embedded_content_view,
embedded_content_view->IsLocalFrameView(),
embedded_content_view.IsLocalFrameView());
-DEFINE_TYPE_CASTS(LocalFrameView,
- ScrollableArea,
- scrollableArea,
- scrollableArea->IsLocalFrameView(),
- scrollableArea.IsLocalFrameView());
} // namespace blink
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 6ab2e3b47f2..5bda833fcbc 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
@@ -10,8 +10,11 @@
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/layout/layout_view.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/paint/paint_property_tree_printer.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.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_size.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -105,16 +108,16 @@ TEST_F(LocalFrameViewTest, HideTooltipWhenScrollPositionChanges) {
EXPECT_CALL(GetAnimationMockChromeClient(),
MockSetToolTip(GetDocument().GetFrame(), String(), _));
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(1, 1), kUserScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(1, 1),
+ kUserScroll);
// Programmatic scrolling should not dismiss the tooltip, so setToolTip
// should not be called for this invocation.
EXPECT_CALL(GetAnimationMockChromeClient(),
MockSetToolTip(GetDocument().GetFrame(), String(), _))
.Times(0);
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(2, 2), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(2, 2),
+ kProgrammaticScroll);
}
// NoOverflowInIncrementVisuallyNonEmptyPixelCount tests fail if the number of
@@ -148,8 +151,8 @@ TEST_F(LocalFrameViewTest,
sticky->Layer()->UpdateAncestorOverflowLayer(nullptr);
// This call should not crash.
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 100), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 100),
+ kProgrammaticScroll);
}
TEST_F(LocalFrameViewTest, UpdateLifecyclePhasesForPrintingDetachedFrame) {
@@ -168,5 +171,99 @@ TEST_F(LocalFrameViewTest, UpdateLifecyclePhasesForPrintingDetachedFrame) {
EXPECT_TRUE(child_layout_view->FirstFragment().PaintProperties());
}
+class LocalFrameViewSimTest : public SimTest {
+ void SetUp() override {
+ SimTest::SetUp();
+ RuntimeEnabledFeatures::SetCSSFragmentIdentifiersEnabled(true);
+ }
+};
+
+TEST_F(LocalFrameViewSimTest, CSSFragmentIdentifierIsParsed) {
+ SimRequest main_resource("https://example.com/#targetElement=.foobar",
+ "text/html");
+ LoadURL("https://example.com/#targetElement=.foobar");
+ main_resource.Complete("<div class='foobar' id='target'></div>");
+
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(target, GetDocument().CssTarget());
+}
+
+TEST_F(LocalFrameViewSimTest, CSSFragmentIdentifierComplexSelector) {
+ SimRequest main_resource(
+ "https://example.com/#targetElement=.outer%3Ediv%3Ep%3Anth-child%282%29",
+ "text/html");
+ LoadURL(
+ "https://example.com/#targetElement=.outer%3Ediv%3Ep%3Anth-child%282%29");
+ main_resource.Complete(R"HTML(
+ <!DOCTYPE html>
+ <html>
+ <head></head>
+ <body>
+ <div class='outer'>
+ <div>
+ <p></p>
+ <p id='target'></p>
+ </div>
+ </div>
+ </body>
+ </html>
+ )HTML");
+
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(target, GetDocument().CssTarget());
+}
+
+TEST_F(LocalFrameViewSimTest, CSSFragmentIdentifierUsesFirstElementFound) {
+ SimRequest main_resource("https://example.com/#targetElement=.foobar",
+ "text/html");
+ LoadURL("https://example.com/#targetElement=.foobar");
+ main_resource.Complete(
+ "<div class='foobar' id='target'></div><div class='foobar'></div>");
+
+ Element* target = GetDocument().getElementById("target");
+ EXPECT_EQ(target, GetDocument().CssTarget());
+}
+
+TEST_F(LocalFrameViewSimTest, CSSFragmentIdentifierIneligibleFragments) {
+ SimRequest main_resource("https://example.com/#targetEl=.foobar",
+ "text/html");
+ LoadURL("https://example.com/#targetEl=.foobar");
+ main_resource.Complete("<div class='foobar' id='target'></div>");
+
+ EXPECT_EQ(nullptr, GetDocument().CssTarget());
+
+ SimRequest main_resource2("https://example.com/#path/fragment", "text/html");
+ LoadURL("https://example.com/#path/fragment");
+ main_resource2.Complete("<div class='foobar' id='target'></div>");
+
+ EXPECT_EQ(nullptr, GetDocument().CssTarget());
+}
+
+TEST_F(LocalFrameViewSimTest, CSSFragmentIdentifierNoMatches) {
+ SimRequest main_resource("https://example.com/#targetElement=.foobar",
+ "text/html");
+ LoadURL("https://example.com/#targetElement=.foobar");
+ main_resource.Complete("<div class='barbaz' id='target'></div>");
+
+ EXPECT_EQ(nullptr, GetDocument().CssTarget());
+}
+
+TEST_F(LocalFrameViewSimTest, CSSFragmentIdentifierInvalidSelector) {
+ SimRequest main_resource("https://example.com/#targetElement=..foobar",
+ "text/html");
+ LoadURL("https://example.com/#targetElement=..foobar");
+ main_resource.Complete("<div class='foobar' id='target'></div>");
+
+ EXPECT_EQ(nullptr, GetDocument().CssTarget());
+}
+
+TEST_F(LocalFrameViewSimTest, CSSFragmentIdentifierEmptySelector) {
+ SimRequest main_resource("https://example.com/#targetElement=", "text/html");
+ LoadURL("https://example.com/#targetElement=");
+ main_resource.Complete("<div class='foobar' id='target'></div>");
+
+ EXPECT_EQ(nullptr, GetDocument().CssTarget());
+}
+
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/location.cc b/chromium/third_party/blink/renderer/core/frame/location.cc
index 4b4a006ba08..588a7d65dbf 100644
--- a/chromium/third_party/blink/renderer/core/frame/location.cc
+++ b/chromium/third_party/blink/renderer/core/frame/location.cc
@@ -29,16 +29,15 @@
#include "third_party/blink/renderer/core/frame/location.h"
#include "third_party/blink/renderer/bindings/core/v8/binding_security.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/usv_string_or_trusted_url.h"
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
-#include "third_party/blink/renderer/core/dom/trustedtypes/trusted_url.h"
#include "third_party/blink/renderer/core/frame/dom_window.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/trustedtypes/trusted_url.h"
#include "third_party/blink/renderer/core/url/dom_url_utils_read_only.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_dom_activity_logger.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -145,7 +144,8 @@ void Location::setProtocol(LocalDOMWindow* current_window,
KURL url = GetDocument()->Url();
if (!url.SetProtocol(protocol)) {
exception_state.ThrowDOMException(
- kSyntaxError, "'" + protocol + "' is an invalid protocol.");
+ DOMExceptionCode::kSyntaxError,
+ "'" + protocol + "' is an invalid protocol.");
return;
}
SetLocation(url.GetString(), current_window, entered_window,
@@ -223,7 +223,7 @@ void Location::setHash(LocalDOMWindow* current_window,
void Location::assign(LocalDOMWindow* current_window,
LocalDOMWindow* entered_window,
- const String& url,
+ const USVStringOrTrustedURL& stringOrUrl,
ExceptionState& exception_state) {
// TODO(yukishiino): Remove this check once we remove [CrossOrigin] from
// the |assign| DOM operation's definition in Location.idl. See the comment
@@ -233,13 +233,43 @@ void Location::assign(LocalDOMWindow* current_window,
return;
}
+ DCHECK(stringOrUrl.IsUSVString() ||
+ RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
+ DCHECK(!stringOrUrl.IsNull());
+
+ if (stringOrUrl.IsUSVString() &&
+ current_window->document()->RequireTrustedTypes()) {
+ exception_state.ThrowTypeError(
+ "This document requires `TrustedURL` assignment.");
+ return;
+ }
+
+ String url = stringOrUrl.IsUSVString()
+ ? stringOrUrl.GetAsUSVString()
+ : stringOrUrl.GetAsTrustedURL()->toString();
+
SetLocation(url, current_window, entered_window, &exception_state);
}
void Location::replace(LocalDOMWindow* current_window,
LocalDOMWindow* entered_window,
- const String& url,
+ const USVStringOrTrustedURL& stringOrUrl,
ExceptionState& exception_state) {
+ DCHECK(stringOrUrl.IsUSVString() ||
+ RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
+ DCHECK(!stringOrUrl.IsNull());
+
+ if (stringOrUrl.IsUSVString() &&
+ current_window->document()->RequireTrustedTypes()) {
+ exception_state.ThrowTypeError(
+ "This document requires `TrustedURL` assignment.");
+ return;
+ }
+
+ String url = stringOrUrl.IsUSVString()
+ ? stringOrUrl.GetAsUSVString()
+ : stringOrUrl.GetAsTrustedURL()->toString();
+
SetLocation(url, current_window, entered_window, &exception_state,
SetLocationPolicy::kReplaceThisFrame);
}
@@ -249,7 +279,7 @@ void Location::reload(LocalDOMWindow* current_window) {
return;
if (GetDocument()->Url().ProtocolIsJavaScript())
return;
- dom_window_->GetFrame()->Reload(kFrameLoadTypeReload,
+ dom_window_->GetFrame()->Reload(WebFrameLoadType::kReload,
ClientRedirectPolicy::kClientRedirect);
}
@@ -283,7 +313,7 @@ void Location::SetLocation(const String& url,
return;
}
if (exception_state && !completed_url.IsValid()) {
- exception_state->ThrowDOMException(kSyntaxError,
+ exception_state->ThrowDOMException(DOMExceptionCode::kSyntaxError,
"'" + url + "' is not a valid URL.");
return;
}
@@ -301,7 +331,7 @@ void Location::SetLocation(const String& url,
argv.push_back(completed_url);
activity_logger->LogEvent("blinkSetAttribute", argv.size(), argv.data());
}
- dom_window_->GetFrame()->Navigate(
+ dom_window_->GetFrame()->ScheduleNavigation(
*current_window->document(), completed_url,
set_location_policy == SetLocationPolicy::kReplaceThisFrame,
UserGestureStatus::kNone);
diff --git a/chromium/third_party/blink/renderer/core/frame/location.h b/chromium/third_party/blink/renderer/core/frame/location.h
index 162ce39ac4d..0b83297023e 100644
--- a/chromium/third_party/blink/renderer/core/frame/location.h
+++ b/chromium/third_party/blink/renderer/core/frame/location.h
@@ -67,11 +67,11 @@ class CORE_EXPORT Location final : public ScriptWrappable {
void assign(LocalDOMWindow* current_window,
LocalDOMWindow* entered_window,
- const String&,
+ const USVStringOrTrustedURL&,
ExceptionState&);
void replace(LocalDOMWindow* current_window,
LocalDOMWindow* entered_window,
- const String&,
+ const USVStringOrTrustedURL&,
ExceptionState&);
void reload(LocalDOMWindow* current_window);
diff --git a/chromium/third_party/blink/renderer/core/frame/location.idl b/chromium/third_party/blink/renderer/core/frame/location.idl
index b8d42c386f6..575131be33d 100644
--- a/chromium/third_party/blink/renderer/core/frame/location.idl
+++ b/chromium/third_party/blink/renderer/core/frame/location.idl
@@ -41,7 +41,7 @@
// |assign| itself is not cross-origin accessible.
// TODO(yukishiino): Remove [CrossOrigin] once we support the Incumbent
// realm correctly.
- [CallWith=(CurrentWindow,EnteredWindow), CrossOrigin, RaisesException] void assign(USVString url);
+ [CallWith=(CurrentWindow,EnteredWindow), CrossOrigin, RaisesException] void assign(URLString url);
// |replace|, and *writing* |href| do not require a security check, as they
// *change* the page, and thus these do not change any property of an
@@ -49,7 +49,7 @@
// However, *reading* |href|, or accessing any component, is a security
// problem, since that allows tracking navigation.
// https://html.spec.whatwg.org/multipage/browsers.html#crossoriginproperties-(-o-)
- [CallWith=(CurrentWindow,EnteredWindow), CrossOrigin, RaisesException] void replace(USVString url);
+ [CallWith=(CurrentWindow,EnteredWindow), CrossOrigin, RaisesException] void replace(URLString url);
[CallWith=CurrentWindow] void reload();
// TODO(foolip): |ancestorOrigins| should have [Unforgeable, SameObject].
diff --git a/chromium/third_party/blink/renderer/core/frame/message_report.h b/chromium/third_party/blink/renderer/core/frame/message_report.h
deleted file mode 100644
index 75e191a67df..00000000000
--- a/chromium/third_party/blink/renderer/core/frame/message_report.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_MESSAGE_REPORT_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_MESSAGE_REPORT_H_
-
-#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
-#include "third_party/blink/renderer/core/frame/report_body.h"
-
-namespace blink {
-
-class MessageReport : public ReportBody {
- public:
- MessageReport(const String& message, std::unique_ptr<SourceLocation> location)
- : message_(message), location_(std::move(location)) {}
-
- ~MessageReport() override = default;
-
- String message() const { return message_; }
- long lineNumber() const { return location_->LineNumber(); }
- long columnNumber() const { return location_->ColumnNumber(); }
- String sourceFile() const {
- return location_->Url().IsNull() ? "" : location_->Url();
- }
-
- protected:
- const String message_;
- std::unique_ptr<SourceLocation> location_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_MESSAGE_REPORT_H_
diff --git a/chromium/third_party/blink/renderer/core/frame/message_report_body.h b/chromium/third_party/blink/renderer/core/frame/message_report_body.h
new file mode 100644
index 00000000000..54b40611adf
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/message_report_body.h
@@ -0,0 +1,42 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_MESSAGE_REPORT_BODY_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_MESSAGE_REPORT_BODY_H_
+
+#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
+#include "third_party/blink/renderer/core/frame/report_body.h"
+
+namespace blink {
+
+class MessageReportBody : public ReportBody {
+ public:
+ MessageReportBody(const String& message,
+ std::unique_ptr<SourceLocation> location)
+ : message_(message), location_(std::move(location)) {}
+
+ ~MessageReportBody() override = default;
+
+ String message() const { return message_; }
+
+ String sourceFile() const { return location_->Url(); }
+
+ long lineNumber(bool& is_null) const {
+ is_null = location_->IsUnknown();
+ return location_->LineNumber();
+ }
+
+ long columnNumber(bool& is_null) const {
+ is_null = location_->IsUnknown();
+ return location_->ColumnNumber();
+ }
+
+ protected:
+ const String message_;
+ std::unique_ptr<SourceLocation> location_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_MESSAGE_REPORT_BODY_H_
diff --git a/chromium/third_party/blink/renderer/core/frame/mhtml_archive_test.cc b/chromium/third_party/blink/renderer/core/frame/mhtml_archive_test.cc
index ae3e9bf4d9b..b29a8d5dc9b 100644
--- a/chromium/third_party/blink/renderer/core/frame/mhtml_archive_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/mhtml_archive_test.cc
@@ -381,6 +381,23 @@ TEST_F(MHTMLArchiveTest, EmptyArchive) {
EXPECT_EQ(nullptr, archive);
}
+TEST_F(MHTMLArchiveTest, NoMainResource) {
+ const char kURL[] = "http://www.example.com";
+ // Only add a resource to a CSS file, so no main resource is valid for
+ // rendering.
+ AddResource("http://www.example.com/link_styles.css", "text/css",
+ "link_styles.css");
+ Serialize(ToKURL(kURL), "Test Serialization", "text/html",
+ MHTMLArchive::kUseDefaultEncoding);
+
+ scoped_refptr<SharedBuffer> data =
+ SharedBuffer::Create(mhtml_data().data(), mhtml_data().size());
+ KURL http_url = ToKURL("http://www.example.com");
+ MHTMLArchive* archive = MHTMLArchive::Create(http_url, data.get());
+
+ EXPECT_EQ(nullptr, archive);
+}
+
} // namespace test
} // namespace blink
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 e97bdeb6969..7601d88283c 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
@@ -128,7 +128,7 @@ TEST_F(MHTMLLoadingTest, EnforceSandboxFlags) {
document->GetSandboxFlags());
// MHTML document should be loaded into unique origin.
- EXPECT_TRUE(document->GetSecurityOrigin()->IsUnique());
+ EXPECT_TRUE(document->GetSecurityOrigin()->IsOpaque());
// Script execution should be disabled.
EXPECT_FALSE(document->CanExecuteScripts(kNotAboutToExecuteScript));
@@ -147,7 +147,7 @@ TEST_F(MHTMLLoadingTest, EnforceSandboxFlags) {
child_document->GetSandboxFlags());
// MHTML document should be loaded into unique origin.
- EXPECT_TRUE(child_document->GetSecurityOrigin()->IsUnique());
+ EXPECT_TRUE(child_document->GetSecurityOrigin()->IsOpaque());
// Script execution should be disabled.
EXPECT_FALSE(child_document->CanExecuteScripts(kNotAboutToExecuteScript));
@@ -174,7 +174,7 @@ TEST_F(MHTMLLoadingTest, EnforceSandboxFlagsInXSLT) {
document->GetSandboxFlags());
// MHTML document should be loaded into unique origin.
- EXPECT_TRUE(document->GetSecurityOrigin()->IsUnique());
+ EXPECT_TRUE(document->GetSecurityOrigin()->IsOpaque());
// Script execution should be disabled.
EXPECT_FALSE(document->CanExecuteScripts(kNotAboutToExecuteScript));
}
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator.cc b/chromium/third_party/blink/renderer/core/frame/navigator.cc
index a63307ea60f..dbccaebbdd5 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator.cc
+++ b/chromium/third_party/blink/renderer/core/frame/navigator.cc
@@ -32,6 +32,7 @@
#include "third_party/blink/renderer/core/loader/frame_loader.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/probe/core_probes.h"
#include "third_party/blink/renderer/platform/language.h"
#include "third_party/blink/renderer/platform/memory_coordinator.h"
@@ -91,6 +92,8 @@ Vector<String> Navigator::languages() {
GetFrame()->GetPage()->GetChromeClient().AcceptLanguages();
}
+ probe::applyAcceptLanguageOverride(GetFrame(), &accept_languages);
+
Vector<String> languages;
accept_languages.Split(',', languages);
@@ -116,9 +119,4 @@ void Navigator::Trace(blink::Visitor* visitor) {
Supplementable<Navigator>::Trace(visitor);
}
-void Navigator::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- ScriptWrappable::TraceWrappers(visitor);
- Supplementable<Navigator>::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator.h b/chromium/third_party/blink/renderer/core/frame/navigator.h
index 6e46f31333f..333194a0514 100644
--- a/chromium/third_party/blink/renderer/core/frame/navigator.h
+++ b/chromium/third_party/blink/renderer/core/frame/navigator.h
@@ -66,7 +66,6 @@ class CORE_EXPORT Navigator final : public ScriptWrappable,
Vector<String> languages() override;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
explicit Navigator(LocalFrame*);
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_user_activation.cc b/chromium/third_party/blink/renderer/core/frame/navigator_user_activation.cc
new file mode 100644
index 00000000000..8d23e6cbf86
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_user_activation.cc
@@ -0,0 +1,42 @@
+// 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/frame/navigator_user_activation.h"
+
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/user_activation.h"
+
+namespace blink {
+
+const char NavigatorUserActivation::kSupplementName[] =
+ "NavigatorUserActivation";
+
+NavigatorUserActivation& NavigatorUserActivation::From(Navigator& navigator) {
+ NavigatorUserActivation* supplement =
+ Supplement<Navigator>::From<NavigatorUserActivation>(navigator);
+ if (!supplement) {
+ supplement = new NavigatorUserActivation(navigator);
+ ProvideTo(navigator, supplement);
+ }
+ return *supplement;
+}
+
+UserActivation* NavigatorUserActivation::userActivation(Navigator& navigator) {
+ return From(navigator).userActivation();
+}
+
+UserActivation* NavigatorUserActivation::userActivation() {
+ return user_activation_;
+}
+
+void NavigatorUserActivation::Trace(blink::Visitor* visitor) {
+ visitor->Trace(user_activation_);
+ Supplement<Navigator>::Trace(visitor);
+}
+
+NavigatorUserActivation::NavigatorUserActivation(Navigator& navigator) {
+ user_activation_ = new UserActivation(navigator.DomWindow());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_user_activation.h b/chromium/third_party/blink/renderer/core/frame/navigator_user_activation.h
new file mode 100644
index 00000000000..a99263535f2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_user_activation.h
@@ -0,0 +1,39 @@
+// 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_FRAME_NAVIGATOR_USER_ACTIVATION_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_NAVIGATOR_USER_ACTIVATION_H_
+
+#include "third_party/blink/renderer/core/frame/navigator.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+
+namespace blink {
+
+class UserActivation;
+
+class CORE_EXPORT NavigatorUserActivation final
+ : public GarbageCollected<NavigatorUserActivation>,
+ public Supplement<Navigator> {
+ USING_GARBAGE_COLLECTED_MIXIN(NavigatorUserActivation);
+
+ public:
+ static const char kSupplementName[];
+
+ static UserActivation* userActivation(Navigator& navigator);
+ UserActivation* userActivation();
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ explicit NavigatorUserActivation(Navigator&);
+
+ static NavigatorUserActivation& From(Navigator&);
+
+ Member<UserActivation> user_activation_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_NAVIGATOR_USER_ACTIVATION_H_
diff --git a/chromium/third_party/blink/renderer/core/frame/navigator_user_activation.idl b/chromium/third_party/blink/renderer/core/frame/navigator_user_activation.idl
new file mode 100644
index 00000000000..92a7bc2f0e6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/navigator_user_activation.idl
@@ -0,0 +1,12 @@
+// 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.
+
+// https://github.com/dtapuska/useractivation
+[
+ ImplementedAs=NavigatorUserActivation,
+ RuntimeEnabled=UserActivationAPI
+] partial interface Navigator {
+ // User activation
+ readonly attribute UserActivation userActivation;
+};
diff --git a/chromium/third_party/blink/renderer/core/frame/page_scale_constraints_set.h b/chromium/third_party/blink/renderer/core/frame/page_scale_constraints_set.h
index cb83e67881a..18a97c96b27 100644
--- a/chromium/third_party/blink/renderer/core/frame/page_scale_constraints_set.h
+++ b/chromium/third_party/blink/renderer/core/frame/page_scale_constraints_set.h
@@ -35,8 +35,8 @@
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/viewport_description.h"
#include "third_party/blink/renderer/core/frame/page_scale_constraints.h"
+#include "third_party/blink/renderer/core/page/viewport_description.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/length.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
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 5e6db52f9cb..90c7fd725fe 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
@@ -57,13 +57,12 @@ Vector<v8::Local<v8::Value>> WebScriptExecutor::Execute(LocalFrame* frame) {
}
Vector<v8::Local<v8::Value>> results;
- if (world_id_) {
- frame->GetScriptController().ExecuteScriptInIsolatedWorld(
- world_id_, sources_, &results);
- } else {
+ for (const auto& source : sources_) {
v8::Local<v8::Value> script_value =
- frame->GetScriptController().ExecuteScriptInMainWorldAndReturnValue(
- sources_.front());
+ world_id_ ? frame->GetScriptController().ExecuteScriptInIsolatedWorld(
+ world_id_, source)
+ : frame->GetScriptController()
+ .ExecuteScriptInMainWorldAndReturnValue(source);
results.push_back(script_value);
}
@@ -169,7 +168,7 @@ void PausableScriptExecutor::ContextDestroyed(
// with a vector of v8::Local<>s, which implies that creating v8::Locals
// is permitted. Ensure a valid scope is present for the callback.
// See https://crbug.com/840719.
- ScriptState::Scope script_scope(script_state_.get());
+ ScriptState::Scope script_scope(script_state_);
callback_->Completed(Vector<v8::Local<v8::Value>>());
}
Dispose();
@@ -225,7 +224,7 @@ void PausableScriptExecutor::ExecuteAndDestroySelf() {
if (callback_)
callback_->WillExecute();
- ScriptState::Scope script_scope(script_state_.get());
+ ScriptState::Scope script_scope(script_state_);
Vector<v8::Local<v8::Value>> results =
executor_->Execute(ToDocument(GetExecutionContext())->GetFrame());
@@ -251,6 +250,7 @@ void PausableScriptExecutor::Dispose() {
}
void PausableScriptExecutor::Trace(blink::Visitor* visitor) {
+ visitor->Trace(script_state_);
visitor->Trace(executor_);
PausableTimer::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/frame/pausable_script_executor.h b/chromium/third_party/blink/renderer/core/frame/pausable_script_executor.h
index 91f28e82f4b..bc32d083aeb 100644
--- a/chromium/third_party/blink/renderer/core/frame/pausable_script_executor.h
+++ b/chromium/third_party/blink/renderer/core/frame/pausable_script_executor.h
@@ -57,7 +57,7 @@ class CORE_EXPORT PausableScriptExecutor final
virtual Vector<v8::Local<v8::Value>> Execute(LocalFrame*) = 0;
- virtual void Trace(blink::Visitor* visitor){};
+ virtual void Trace(blink::Visitor* visitor) {}
};
private:
@@ -71,7 +71,7 @@ class CORE_EXPORT PausableScriptExecutor final
void ExecuteAndDestroySelf();
void Dispose();
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
WebScriptExecutionCallback* callback_;
BlockingOption blocking_option_;
diff --git a/chromium/third_party/blink/renderer/core/frame/pausable_timer.cc b/chromium/third_party/blink/renderer/core/frame/pausable_timer.cc
index 55f66ce41ab..ec5bd0fdb07 100644
--- a/chromium/third_party/blink/renderer/core/frame/pausable_timer.cc
+++ b/chromium/third_party/blink/renderer/core/frame/pausable_timer.cc
@@ -31,15 +31,14 @@
namespace blink {
namespace {
-// The lowest value returned by TimerBase::nextUnalignedFireInterval is 0.0
-const double kNextFireIntervalInvalid = -1.0;
+// TimerBase::NextFireIntervalDelta returns a delta >= 0.
+constexpr TimeDelta kNextFireIntervalInvalid = TimeDelta::Min();
} // namespace
PausableTimer::PausableTimer(ExecutionContext* context, TaskType task_type)
: TimerBase(context->GetTaskRunner(task_type)),
PausableObject(context),
- next_fire_interval_(kNextFireIntervalInvalid),
- repeat_interval_(0) {
+ next_fire_interval_(kNextFireIntervalInvalid) {
DCHECK(context);
}
@@ -61,7 +60,7 @@ void PausableTimer::Pause() {
#endif
if (IsActive()) {
next_fire_interval_ = NextFireInterval();
- DCHECK_GE(next_fire_interval_, 0.0);
+ DCHECK_GE(next_fire_interval_, TimeDelta());
repeat_interval_ = RepeatInterval();
TimerBase::Stop();
}
@@ -72,7 +71,7 @@ void PausableTimer::Unpause() {
DCHECK(paused_);
paused_ = false;
#endif
- if (next_fire_interval_ >= 0.0) {
+ if (next_fire_interval_ >= TimeDelta()) {
// start() was called before, therefore location() is already set.
// m_nextFireInterval is only set in suspend() if the Timer was active.
Start(next_fire_interval_, repeat_interval_, GetLocation());
diff --git a/chromium/third_party/blink/renderer/core/frame/pausable_timer.h b/chromium/third_party/blink/renderer/core/frame/pausable_timer.h
index 1f73e437ac9..40cf8b05c56 100644
--- a/chromium/third_party/blink/renderer/core/frame/pausable_timer.h
+++ b/chromium/third_party/blink/renderer/core/frame/pausable_timer.h
@@ -48,8 +48,8 @@ class CORE_EXPORT PausableTimer : public TimerBase, public PausableObject {
private:
void Fired() override = 0;
- double next_fire_interval_;
- double repeat_interval_;
+ TimeDelta next_fire_interval_;
+ TimeDelta repeat_interval_;
#if DCHECK_IS_ON()
bool paused_ = false;
#endif
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 c68f6775967..62e763460ee 100644
--- a/chromium/third_party/blink/renderer/core/frame/performance_monitor.cc
+++ b/chromium/third_party/blink/renderer/core/frame/performance_monitor.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/frame/performance_monitor.h"
+#include "base/format_macros.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/scheduled_action.h"
#include "third_party/blink/renderer/bindings/core/v8/script_event_listener.h"
@@ -30,11 +31,11 @@ void PerformanceMonitor::BypassLongCompileThresholdOnceForTesting() {
};
// static
-double PerformanceMonitor::Threshold(ExecutionContext* context,
- Violation violation) {
+base::TimeDelta PerformanceMonitor::Threshold(ExecutionContext* context,
+ Violation violation) {
PerformanceMonitor* monitor =
PerformanceMonitor::InstrumentingMonitor(context);
- return monitor ? monitor->thresholds_[violation] : 0;
+ return monitor ? monitor->thresholds_[violation] : base::TimeDelta();
}
// static
@@ -42,7 +43,7 @@ void PerformanceMonitor::ReportGenericViolation(
ExecutionContext* context,
Violation violation,
const String& text,
- double time,
+ base::TimeDelta time,
std::unique_ptr<SourceLocation> location) {
PerformanceMonitor* monitor =
PerformanceMonitor::InstrumentingMonitor(context);
@@ -72,7 +73,7 @@ PerformanceMonitor* PerformanceMonitor::InstrumentingMonitor(
PerformanceMonitor::PerformanceMonitor(LocalFrame* local_root)
: local_root_(local_root) {
- std::fill(std::begin(thresholds_), std::end(thresholds_), 0);
+ std::fill(std::begin(thresholds_), std::end(thresholds_), base::TimeDelta());
Platform::Current()->CurrentThread()->AddTaskTimeObserver(this);
local_root_->GetProbeSink()->addPerformanceMonitor(this);
}
@@ -82,7 +83,7 @@ PerformanceMonitor::~PerformanceMonitor() {
}
void PerformanceMonitor::Subscribe(Violation violation,
- double threshold,
+ base::TimeDelta threshold,
Client* client) {
DCHECK(violation < kAfterLast);
ClientThresholds* client_thresholds = subscriptions_.at(violation);
@@ -111,20 +112,20 @@ void PerformanceMonitor::Shutdown() {
}
void PerformanceMonitor::UpdateInstrumentation() {
- std::fill(std::begin(thresholds_), std::end(thresholds_), 0);
+ std::fill(std::begin(thresholds_), std::end(thresholds_), base::TimeDelta());
for (const auto& it : subscriptions_) {
Violation violation = static_cast<Violation>(it.key);
ClientThresholds* client_thresholds = it.value;
for (const auto& client_threshold : *client_thresholds) {
- if (!thresholds_[violation] ||
+ if (thresholds_[violation].is_zero() ||
thresholds_[violation] > client_threshold.value)
thresholds_[violation] = client_threshold.value;
}
}
- enabled_ = std::count(std::begin(thresholds_), std::end(thresholds_), 0) <
- static_cast<int>(kAfterLast);
+ enabled_ = std::count(std::begin(thresholds_), std::end(thresholds_),
+ base::TimeDelta()) < static_cast<int>(kAfterLast);
}
void PerformanceMonitor::WillExecuteScript(ExecutionContext* context) {
@@ -163,12 +164,12 @@ void PerformanceMonitor::UpdateTaskShouldBeReported(LocalFrame* frame) {
void PerformanceMonitor::Will(const probe::RecalculateStyle& probe) {
UpdateTaskShouldBeReported(probe.document ? probe.document->GetFrame()
: nullptr);
- if (enabled_ && thresholds_[kLongLayout] && script_depth_)
+ if (enabled_ && !thresholds_[kLongLayout].is_zero() && script_depth_)
probe.CaptureStartTime();
}
void PerformanceMonitor::Did(const probe::RecalculateStyle& probe) {
- if (enabled_ && script_depth_ && thresholds_[kLongLayout])
+ if (enabled_ && script_depth_ && !thresholds_[kLongLayout].is_zero())
per_task_style_and_layout_time_ += probe.Duration();
}
@@ -178,7 +179,7 @@ void PerformanceMonitor::Will(const probe::UpdateLayout& probe) {
++layout_depth_;
if (!enabled_)
return;
- if (layout_depth_ > 1 || !script_depth_ || !thresholds_[kLongLayout])
+ if (layout_depth_ > 1 || !script_depth_ || thresholds_[kLongLayout].is_zero())
return;
probe.CaptureStartTime();
@@ -188,7 +189,7 @@ void PerformanceMonitor::Did(const probe::UpdateLayout& probe) {
--layout_depth_;
if (!enabled_)
return;
- if (thresholds_[kLongLayout] && script_depth_ && !layout_depth_)
+ if (!thresholds_[kLongLayout].is_zero() && script_depth_ && !layout_depth_)
per_task_style_and_layout_time_ += probe.Duration();
}
@@ -201,7 +202,7 @@ void PerformanceMonitor::Will(const probe::ExecuteScript& probe) {
void PerformanceMonitor::Did(const probe::ExecuteScript& probe) {
DidExecuteScript();
- if (!enabled_ || !thresholds_[kLongTask])
+ if (!enabled_ || thresholds_[kLongTask].is_zero())
return;
if (probe.Duration() <= kLongTaskSubTaskThreshold)
@@ -229,29 +230,29 @@ void PerformanceMonitor::Did(const probe::CallFunction& probe) {
static_cast<const probe::UserCallback*>(user_callback_);
Violation handler_type =
user_callback->recurring ? kRecurringHandler : kHandler;
- double threshold = thresholds_[handler_type];
- double duration = probe.Duration().InSecondsF();
- if (!threshold || duration < threshold)
+ base::TimeDelta threshold = thresholds_[handler_type];
+ base::TimeDelta duration = probe.Duration();
+ if (threshold.is_zero() || duration < threshold)
return;
String name = user_callback->name ? String(user_callback->name)
: String(user_callback->atomicName);
- String text = String::Format("'%s' handler took %ldms", name.Utf8().data(),
- lround(duration * 1000));
+ String text = String::Format("'%s' handler took %" PRId64 "ms",
+ name.Utf8().data(), duration.InMilliseconds());
InnerReportGenericViolation(probe.context, handler_type, text, duration,
SourceLocation::FromFunction(probe.function));
}
void PerformanceMonitor::Will(const probe::V8Compile& probe) {
UpdateTaskAttribution(probe.context);
- if (!enabled_ || !thresholds_[kLongTask])
+ if (!enabled_ || thresholds_[kLongTask].is_zero())
return;
v8_compile_start_time_ = probe.CaptureStartTime();
}
void PerformanceMonitor::Did(const probe::V8Compile& probe) {
- if (!enabled_ || !thresholds_[kLongTask])
+ if (!enabled_ || thresholds_[kLongTask].is_zero())
return;
TimeDelta v8_compile_duration = probe.Duration();
@@ -276,7 +277,7 @@ void PerformanceMonitor::Will(const probe::UserCallback& probe) {
++user_callback_depth_;
UpdateTaskAttribution(probe.context);
if (!enabled_ || user_callback_depth_ != 1 ||
- !thresholds_[probe.recurring ? kRecurringHandler : kHandler])
+ thresholds_[probe.recurring ? kRecurringHandler : kHandler].is_zero())
return;
DCHECK(!user_callback_);
@@ -294,10 +295,11 @@ void PerformanceMonitor::DocumentWriteFetchScript(Document* document) {
if (!enabled_)
return;
String text = "Parser was blocked due to document.write(<script>)";
- InnerReportGenericViolation(document, kBlockedParser, text, 0, nullptr);
+ InnerReportGenericViolation(document, kBlockedParser, text, base::TimeDelta(),
+ nullptr);
}
-void PerformanceMonitor::WillProcessTask(double start_time) {
+void PerformanceMonitor::WillProcessTask(base::TimeTicks start_time) {
// Reset m_taskExecutionContext. We don't clear this in didProcessTask
// as it is needed in ReportTaskTime which occurs after didProcessTask.
task_execution_context_ = nullptr;
@@ -316,12 +318,13 @@ void PerformanceMonitor::WillProcessTask(double start_time) {
sub_task_attributions_.clear();
}
-void PerformanceMonitor::DidProcessTask(double start_time, double end_time) {
+void PerformanceMonitor::DidProcessTask(base::TimeTicks start_time,
+ base::TimeTicks end_time) {
if (!enabled_ || !task_should_be_reported_)
return;
- double layout_threshold = thresholds_[kLongLayout];
- double layout_time = per_task_style_and_layout_time_.InSecondsF();
- if (layout_threshold && layout_time > layout_threshold) {
+ base::TimeDelta layout_threshold = thresholds_[kLongLayout];
+ base::TimeDelta layout_time = per_task_style_and_layout_time_;
+ if (!layout_threshold.is_zero() && layout_time > layout_threshold) {
ClientThresholds* client_thresholds = subscriptions_.at(kLongLayout);
DCHECK(client_thresholds);
for (const auto& it : *client_thresholds) {
@@ -330,8 +333,8 @@ void PerformanceMonitor::DidProcessTask(double start_time, double end_time) {
}
}
- double task_time = end_time - start_time;
- if (thresholds_[kLongTask] && task_time > thresholds_[kLongTask]) {
+ base::TimeDelta task_time = end_time - start_time;
+ if (!thresholds_[kLongTask].is_zero() && task_time > thresholds_[kLongTask]) {
ClientThresholds* client_thresholds = subscriptions_.at(kLongTask);
for (const auto& it : *client_thresholds) {
if (it.value < task_time) {
@@ -348,7 +351,7 @@ void PerformanceMonitor::InnerReportGenericViolation(
ExecutionContext* context,
Violation violation,
const String& text,
- double time,
+ base::TimeDelta time,
std::unique_ptr<SourceLocation> location) {
ClientThresholds* client_thresholds = subscriptions_.at(violation);
if (!client_thresholds)
diff --git a/chromium/third_party/blink/renderer/core/frame/performance_monitor.h b/chromium/third_party/blink/renderer/core/frame/performance_monitor.h
index ddde02312c3..b214148bf86 100644
--- a/chromium/third_party/blink/renderer/core/frame/performance_monitor.h
+++ b/chromium/third_party/blink/renderer/core/frame/performance_monitor.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_PERFORMANCE_MONITOR_H_
#include "base/macros.h"
+#include "base/task/sequence_manager/task_time_observer.h"
#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -13,7 +14,6 @@
#include "third_party/blink/renderer/core/timing/sub_task_attribution.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/scheduler/base/task_time_observer.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "v8/include/v8.h"
@@ -56,15 +56,15 @@ class CORE_EXPORT PerformanceMonitor final
class CORE_EXPORT Client : public GarbageCollectedMixin {
public:
virtual void ReportLongTask(
- double start_time,
- double end_time,
+ base::TimeTicks start_time,
+ base::TimeTicks end_time,
ExecutionContext* task_context,
bool has_multiple_contexts,
const SubTaskAttribution::EntriesVector& sub_task_attributions) {}
- virtual void ReportLongLayout(double duration) {}
+ virtual void ReportLongLayout(base::TimeDelta duration) {}
virtual void ReportGenericViolation(Violation,
const String& text,
- double time,
+ base::TimeDelta time,
SourceLocation*) {}
void Trace(blink::Visitor* visitor) override {}
};
@@ -72,9 +72,9 @@ class CORE_EXPORT PerformanceMonitor final
static void ReportGenericViolation(ExecutionContext*,
Violation,
const String& text,
- double time,
+ base::TimeDelta time,
std::unique_ptr<SourceLocation>);
- static double Threshold(ExecutionContext*, Violation);
+ static base::TimeDelta Threshold(ExecutionContext*, Violation);
void BypassLongCompileThresholdOnceForTesting();
@@ -102,7 +102,7 @@ class CORE_EXPORT PerformanceMonitor final
void DocumentWriteFetchScript(Document*);
// Direct API for core.
- void Subscribe(Violation, double threshold, Client*);
+ void Subscribe(Violation, base::TimeDelta threshold, Client*);
void UnsubscribeAll(Client*);
void Shutdown();
@@ -123,12 +123,13 @@ class CORE_EXPORT PerformanceMonitor final
void InnerReportGenericViolation(ExecutionContext*,
Violation,
const String& text,
- double time,
+ base::TimeDelta time,
std::unique_ptr<SourceLocation>);
// TaskTimeObserver implementation
- void WillProcessTask(double start_time) override;
- void DidProcessTask(double start_time, double end_time) override;
+ void WillProcessTask(base::TimeTicks start_time) override;
+ void DidProcessTask(base::TimeTicks start_time,
+ base::TimeTicks end_time) override;
void WillExecuteScript(ExecutionContext*);
void DidExecuteScript();
@@ -150,13 +151,13 @@ class CORE_EXPORT PerformanceMonitor final
SubTaskAttribution::EntriesVector sub_task_attributions_;
- double thresholds_[kAfterLast];
+ base::TimeDelta thresholds_[kAfterLast];
Member<LocalFrame> local_root_;
Member<ExecutionContext> task_execution_context_;
bool task_has_multiple_contexts_ = false;
bool task_should_be_reported_ = false;
- using ClientThresholds = HeapHashMap<WeakMember<Client>, double>;
+ using ClientThresholds = HeapHashMap<WeakMember<Client>, base::TimeDelta>;
HeapHashMap<Violation,
Member<ClientThresholds>,
typename DefaultHash<size_t>::Hash,
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 d420d05f86e..3df0b743db4 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
@@ -13,6 +13,9 @@
#include <memory>
namespace blink {
+namespace {
+
+} // namespace
class PerformanceMonitorTest : public testing::Test {
protected:
@@ -36,11 +39,11 @@ class PerformanceMonitorTest : public testing::Test {
}
// scheduler::TaskTimeObserver implementation
- void WillProcessTask(double start_time) {
+ void WillProcessTask(base::TimeTicks start_time) {
monitor_->WillProcessTask(start_time);
}
- void DidProcessTask(double start_time, double end_time) {
+ void DidProcessTask(base::TimeTicks start_time, base::TimeTicks end_time) {
monitor_->DidProcessTask(start_time, end_time);
}
void UpdateTaskAttribution(ExecutionContext* execution_context) {
@@ -61,6 +64,10 @@ class PerformanceMonitorTest : public testing::Test {
String FrameContextURL();
int NumUniqueFrameContextsSeen();
+ static base::TimeTicks SecondsToTimeTicks(double seconds) {
+ return base::TimeTicks() + base::TimeDelta::FromSecondsD(seconds);
+ }
+
Persistent<PerformanceMonitor> monitor_;
std::unique_ptr<DummyPageHolder> page_holder_;
std::unique_ptr<DummyPageHolder> another_page_holder_;
@@ -97,17 +104,18 @@ int PerformanceMonitorTest::NumUniqueFrameContextsSeen() {
}
TEST_F(PerformanceMonitorTest, SingleScriptInTask) {
- WillProcessTask(3719349.445172);
+ WillProcessTask(SecondsToTimeTicks(3719349.445172));
EXPECT_EQ(0, NumUniqueFrameContextsSeen());
WillExecuteScript(GetExecutionContext());
EXPECT_EQ(1, NumUniqueFrameContextsSeen());
- DidProcessTask(3719349.445172, 3719349.5561923); // Long task
+ DidProcessTask(SecondsToTimeTicks(3719349.445172),
+ SecondsToTimeTicks(3719349.5561923)); // Long task
EXPECT_EQ(1, NumUniqueFrameContextsSeen());
EXPECT_EQ("https://example.com/foo", FrameContextURL());
}
TEST_F(PerformanceMonitorTest, MultipleScriptsInTask_SingleContext) {
- WillProcessTask(3719349.445172);
+ WillProcessTask(SecondsToTimeTicks(3719349.445172));
EXPECT_EQ(0, NumUniqueFrameContextsSeen());
WillExecuteScript(GetExecutionContext());
EXPECT_EQ(1, NumUniqueFrameContextsSeen());
@@ -115,13 +123,14 @@ TEST_F(PerformanceMonitorTest, MultipleScriptsInTask_SingleContext) {
WillExecuteScript(GetExecutionContext());
EXPECT_EQ(1, NumUniqueFrameContextsSeen());
- DidProcessTask(3719349.445172, 3719349.5561923); // Long task
+ DidProcessTask(SecondsToTimeTicks(3719349.445172),
+ SecondsToTimeTicks(3719349.5561923)); // Long task
EXPECT_EQ(1, NumUniqueFrameContextsSeen());
EXPECT_EQ("https://example.com/foo", FrameContextURL());
}
TEST_F(PerformanceMonitorTest, MultipleScriptsInTask_MultipleContexts) {
- WillProcessTask(3719349.445172);
+ WillProcessTask(SecondsToTimeTicks(3719349.445172));
EXPECT_EQ(0, NumUniqueFrameContextsSeen());
WillExecuteScript(GetExecutionContext());
EXPECT_EQ(1, NumUniqueFrameContextsSeen());
@@ -129,77 +138,80 @@ TEST_F(PerformanceMonitorTest, MultipleScriptsInTask_MultipleContexts) {
WillExecuteScript(AnotherExecutionContext());
EXPECT_EQ(2, NumUniqueFrameContextsSeen());
- DidProcessTask(3719349.445172, 3719349.5561923); // Long task
+ DidProcessTask(SecondsToTimeTicks(3719349.445172),
+ SecondsToTimeTicks(3719349.5561923)); // Long task
EXPECT_EQ(2, NumUniqueFrameContextsSeen());
EXPECT_EQ("", FrameContextURL());
}
TEST_F(PerformanceMonitorTest, NoScriptInLongTask) {
- WillProcessTask(3719349.445172);
+ WillProcessTask(SecondsToTimeTicks(3719349.445172));
WillExecuteScript(GetExecutionContext());
- DidProcessTask(3719349.445172, 3719349.445182);
+ DidProcessTask(SecondsToTimeTicks(3719349.445172),
+ SecondsToTimeTicks(3719349.445182));
- WillProcessTask(3719349.445172);
- DidProcessTask(3719349.445172, 3719349.5561923); // Long task
+ WillProcessTask(SecondsToTimeTicks(3719349.445172));
+ DidProcessTask(SecondsToTimeTicks(3719349.445172),
+ SecondsToTimeTicks(3719349.5561923)); // Long task
// Without presence of Script, FrameContext URL is not available
EXPECT_EQ(0, NumUniqueFrameContextsSeen());
}
TEST_F(PerformanceMonitorTest, TaskWithoutLocalRoot) {
- WillProcessTask(1234.5678);
+ WillProcessTask(SecondsToTimeTicks(1234.5678));
UpdateTaskAttribution(AnotherExecutionContext());
- DidProcessTask(1234.5678, 2345.6789);
+ DidProcessTask(SecondsToTimeTicks(1234.5678), SecondsToTimeTicks(2345.6789));
EXPECT_FALSE(TaskShouldBeReported());
EXPECT_EQ(1, NumUniqueFrameContextsSeen());
}
TEST_F(PerformanceMonitorTest, TaskWithLocalRoot) {
- WillProcessTask(1234.5678);
+ WillProcessTask(SecondsToTimeTicks(1234.5678));
UpdateTaskAttribution(GetExecutionContext());
EXPECT_TRUE(TaskShouldBeReported());
EXPECT_EQ(1, NumUniqueFrameContextsSeen());
UpdateTaskAttribution(AnotherExecutionContext());
- DidProcessTask(1234.5678, 2345.6789);
+ DidProcessTask(SecondsToTimeTicks(1234.5678), SecondsToTimeTicks(2345.6789));
EXPECT_TRUE(TaskShouldBeReported());
EXPECT_EQ(2, NumUniqueFrameContextsSeen());
}
TEST_F(PerformanceMonitorTest, RecalculateStyleWithDocument) {
- WillProcessTask(1234.5678);
+ WillProcessTask(SecondsToTimeTicks(1234.5678));
RecalculateStyle(&another_page_holder_->GetDocument());
- DidProcessTask(1234.5678, 2345.6789);
+ DidProcessTask(SecondsToTimeTicks(1234.5678), SecondsToTimeTicks(2345.6789));
// Task from unrelated context should not be reported.
EXPECT_FALSE(TaskShouldBeReported());
- WillProcessTask(3234.5678);
+ WillProcessTask(SecondsToTimeTicks(3234.5678));
RecalculateStyle(&page_holder_->GetDocument());
- DidProcessTask(3234.5678, 4345.6789);
+ DidProcessTask(SecondsToTimeTicks(3234.5678), SecondsToTimeTicks(4345.6789));
EXPECT_TRUE(TaskShouldBeReported());
- WillProcessTask(3234.5678);
+ WillProcessTask(SecondsToTimeTicks(3234.5678));
RecalculateStyle(&another_page_holder_->GetDocument());
RecalculateStyle(&page_holder_->GetDocument());
- DidProcessTask(3234.5678, 4345.6789);
+ DidProcessTask(SecondsToTimeTicks(3234.5678), SecondsToTimeTicks(4345.6789));
// This task involves the current context, so it should be reported.
EXPECT_TRUE(TaskShouldBeReported());
}
TEST_F(PerformanceMonitorTest, UpdateLayoutWithDocument) {
- WillProcessTask(1234.5678);
+ WillProcessTask(SecondsToTimeTicks(1234.5678));
UpdateLayout(&another_page_holder_->GetDocument());
- DidProcessTask(1234.5678, 2345.6789);
+ DidProcessTask(SecondsToTimeTicks(1234.5678), SecondsToTimeTicks(2345.6789));
// Task from unrelated context should not be reported.
EXPECT_FALSE(TaskShouldBeReported());
- WillProcessTask(3234.5678);
+ WillProcessTask(SecondsToTimeTicks(3234.5678));
UpdateLayout(&page_holder_->GetDocument());
- DidProcessTask(3234.5678, 4345.6789);
+ DidProcessTask(SecondsToTimeTicks(3234.5678), SecondsToTimeTicks(4345.6789));
EXPECT_TRUE(TaskShouldBeReported());
- WillProcessTask(3234.5678);
+ WillProcessTask(SecondsToTimeTicks(3234.5678));
UpdateLayout(&another_page_holder_->GetDocument());
UpdateLayout(&page_holder_->GetDocument());
- DidProcessTask(3234.5678, 4345.6789);
+ DidProcessTask(SecondsToTimeTicks(3234.5678), SecondsToTimeTicks(4345.6789));
// This task involves the current context, so it should be reported.
EXPECT_TRUE(TaskShouldBeReported());
}
diff --git a/chromium/third_party/blink/renderer/core/frame/picture_in_picture_controller.h b/chromium/third_party/blink/renderer/core/frame/picture_in_picture_controller.h
index 0112287e1f4..92dfb88ac49 100644
--- a/chromium/third_party/blink/renderer/core/frame/picture_in_picture_controller.h
+++ b/chromium/third_party/blink/renderer/core/frame/picture_in_picture_controller.h
@@ -11,6 +11,9 @@
namespace blink {
+class HTMLVideoElement;
+class ScriptPromiseResolver;
+
// PictureInPictureController allows to know if Picture-in-Picture is allowed
// for a video element in Blink outside of modules/ module. It
// is an interface that the module will implement and add a provider for.
@@ -40,6 +43,14 @@ class CORE_EXPORT PictureInPictureController
kDisabledByAttribute,
};
+ // Enter Picture-in-Picture for a video element and resolve promise if any.
+ virtual void EnterPictureInPicture(HTMLVideoElement*,
+ ScriptPromiseResolver*) = 0;
+
+ // Exit Picture-in-Picture for a video element and resolve promise if any.
+ virtual void ExitPictureInPicture(HTMLVideoElement*,
+ ScriptPromiseResolver*) = 0;
+
// Returns whether a given video element in a document associated with the
// controller is allowed to request Picture-in-Picture.
virtual Status IsElementAllowed(const HTMLVideoElement&) const = 0;
@@ -47,6 +58,12 @@ class CORE_EXPORT PictureInPictureController
// Should be called when an element has exited Picture-in-Picture.
virtual void OnExitedPictureInPicture(ScriptPromiseResolver*) = 0;
+ // Should be called when a custom control on a video element in
+ // Picture-in-Picture is clicked. |control_id| is the identifier for its
+ // custom control. This is defined by the site that calls the web API.
+ virtual void OnPictureInPictureControlClicked(
+ const WebString& control_id) = 0;
+
// Returns whether the given element is currently in Picture-in-Picture.
virtual bool IsPictureInPictureElement(const Element*) const = 0;
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 1118d5e2692..3c8fa1d73bf 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,6 +4,7 @@
#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/page/page.h"
namespace blink {
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 0139d8f8687..e24c4661b2a 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
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/page/page_visibility_observer.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/timer.h"
+#include "third_party/blink/renderer/platform/web_task_runner.h"
namespace blink {
@@ -26,6 +27,7 @@ class CORE_EXPORT PlatformEventController : public PageVisibilityObserver {
virtual void DidUpdateData() = 0;
void Trace(blink::Visitor*) override;
+ Document* GetDocument() const { return document_; }
protected:
explicit PlatformEventController(Document*);
diff --git a/chromium/third_party/blink/renderer/core/frame/platform_event_dispatcher.cc b/chromium/third_party/blink/renderer/core/frame/platform_event_dispatcher.cc
index 648d32e8513..b889d90510a 100644
--- a/chromium/third_party/blink/renderer/core/frame/platform_event_dispatcher.cc
+++ b/chromium/third_party/blink/renderer/core/frame/platform_event_dispatcher.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/frame/platform_event_dispatcher.h"
#include "base/auto_reset.h"
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/platform_event_controller.h"
namespace blink {
@@ -23,7 +24,9 @@ void PlatformEventDispatcher::AddController(
controllers_.insert(controller);
if (!is_listening_) {
- StartListening();
+ StartListening(controller->GetDocument()
+ ? controller->GetDocument()->GetFrame()
+ : nullptr);
is_listening_ = true;
}
}
diff --git a/chromium/third_party/blink/renderer/core/frame/platform_event_dispatcher.h b/chromium/third_party/blink/renderer/core/frame/platform_event_dispatcher.h
index 95a5507187a..52c90ba3941 100644
--- a/chromium/third_party/blink/renderer/core/frame/platform_event_dispatcher.h
+++ b/chromium/third_party/blink/renderer/core/frame/platform_event_dispatcher.h
@@ -10,6 +10,7 @@
namespace blink {
class PlatformEventController;
+class LocalFrame;
class CORE_EXPORT PlatformEventDispatcher : public GarbageCollectedMixin {
public:
@@ -23,7 +24,7 @@ class CORE_EXPORT PlatformEventDispatcher : public GarbageCollectedMixin {
void NotifyControllers();
- virtual void StartListening() = 0;
+ virtual void StartListening(LocalFrame* frame) = 0;
virtual void StopListening() = 0;
private:
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 894f2d0b7b7..2e0021740a8 100644
--- a/chromium/third_party/blink/renderer/core/frame/remote_frame.cc
+++ b/chromium/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -55,10 +55,10 @@ void RemoteFrame::Trace(blink::Visitor* visitor) {
Frame::Trace(visitor);
}
-void RemoteFrame::Navigate(Document& origin_document,
- const KURL& url,
- bool replace_current_item,
- UserGestureStatus user_gesture_status) {
+void RemoteFrame::ScheduleNavigation(Document& origin_document,
+ const KURL& url,
+ bool replace_current_item,
+ UserGestureStatus user_gesture_status) {
FrameLoadRequest frame_request(&origin_document, ResourceRequest(url));
frame_request.SetReplacesCurrentItem(replace_current_item);
frame_request.GetResourceRequest().SetHasUserGesture(
@@ -84,7 +84,7 @@ void RemoteFrame::Navigate(const FrameLoadRequest& passed_request) {
frame_request.GetBlobURLToken());
}
-void RemoteFrame::Reload(FrameLoadType frame_load_type,
+void RemoteFrame::Reload(WebFrameLoadType frame_load_type,
ClientRedirectPolicy client_redirect_policy) {
Client()->Reload(frame_load_type, client_redirect_policy);
}
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 bd6ec85b1d1..76238a41200 100644
--- a/chromium/third_party/blink/renderer/core/frame/remote_frame.h
+++ b/chromium/third_party/blink/renderer/core/frame/remote_frame.h
@@ -29,12 +29,12 @@ class CORE_EXPORT RemoteFrame final : public Frame {
// Frame overrides:
void Trace(blink::Visitor*) override;
- void Navigate(Document& origin_document,
- const KURL&,
- bool replace_current_item,
- UserGestureStatus) override;
+ void ScheduleNavigation(Document& origin_document,
+ const KURL&,
+ bool replace_current_item,
+ UserGestureStatus) override;
void Navigate(const FrameLoadRequest& passed_request) override;
- void Reload(FrameLoadType, ClientRedirectPolicy) override;
+ void Reload(WebFrameLoadType, ClientRedirectPolicy) override;
void Detach(FrameDetachType) override;
RemoteSecurityContext* GetSecurityContext() const override;
bool PrepareForCommit() override;
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 7cefecebb0d..f578bbfdd7d 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,16 +5,19 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_REMOTE_FRAME_CLIENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_REMOTE_FRAME_CLIENT_H_
+#include "cc/paint/paint_canvas.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink.h"
-#include "third_party/blink/public/platform/web_canvas.h"
#include "third_party/blink/public/platform/web_focus_type.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"
-#include "third_party/blink/renderer/core/loader/frame_loader_types.h"
#include "third_party/blink/renderer/platform/graphics/touch_action.h"
-namespace blink {
+namespace cc {
+class PaintCanvas;
+}
+namespace blink {
class IntRect;
class LocalFrame;
class MessageEvent;
@@ -28,7 +31,7 @@ class RemoteFrameClient : public FrameClient {
virtual void Navigate(const ResourceRequest&,
bool should_replace_current_entry,
mojom::blink::BlobURLTokenPtr) = 0;
- virtual void Reload(FrameLoadType, ClientRedirectPolicy) = 0;
+ virtual void Reload(WebFrameLoadType, ClientRedirectPolicy) = 0;
unsigned BackForwardLength() override = 0;
// Notifies the remote frame to check whether it is done loading, after one
@@ -62,7 +65,7 @@ class RemoteFrameClient : public FrameClient {
virtual void UpdateRenderThrottlingStatus(bool isThrottled,
bool subtreeThrottled) = 0;
- virtual uint32_t Print(const IntRect&, WebCanvas*) const = 0;
+ virtual uint32_t Print(const IntRect&, cc::PaintCanvas*) const = 0;
};
} // namespace blink
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 0d1f04079ed..25d988f493e 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
@@ -120,12 +120,11 @@ void RemoteFrameClientImpl::Navigate(
}
void RemoteFrameClientImpl::Reload(
- FrameLoadType load_type,
+ WebFrameLoadType load_type,
ClientRedirectPolicy client_redirect_policy) {
DCHECK(IsReloadLoadType(load_type));
if (web_frame_->Client()) {
- web_frame_->Client()->Reload(static_cast<WebFrameLoadType>(load_type),
- client_redirect_policy);
+ web_frame_->Client()->Reload(load_type, client_redirect_policy);
}
}
@@ -192,7 +191,7 @@ void RemoteFrameClientImpl::UpdateRenderThrottlingStatus(
}
uint32_t RemoteFrameClientImpl::Print(const IntRect& rect,
- WebCanvas* canvas) const {
+ cc::PaintCanvas* canvas) const {
return web_frame_->Client()->Print(rect, canvas);
}
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 7c3337bd2f0..0e9871705b3 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
@@ -7,6 +7,10 @@
#include "third_party/blink/renderer/core/frame/remote_frame_client.h"
+namespace cc {
+class PaintCanvas;
+}
+
namespace blink {
class WebRemoteFrameImpl;
@@ -32,7 +36,7 @@ class RemoteFrameClientImpl final : public RemoteFrameClient {
void Navigate(const ResourceRequest&,
bool should_replace_current_entry,
mojom::blink::BlobURLTokenPtr) override;
- void Reload(FrameLoadType, ClientRedirectPolicy) override;
+ void Reload(WebFrameLoadType, ClientRedirectPolicy) override;
unsigned BackForwardLength() override;
void CheckCompleted() override;
void ForwardPostMessage(MessageEvent*,
@@ -48,7 +52,7 @@ class RemoteFrameClientImpl final : public RemoteFrameClient {
void SetInheritedEffectiveTouchAction(TouchAction) override;
void UpdateRenderThrottlingStatus(bool is_throttled,
bool subtree_throttled) override;
- uint32_t Print(const IntRect&, WebCanvas*) const override;
+ uint32_t Print(const IntRect&, cc::PaintCanvas*) const override;
WebRemoteFrameImpl* GetWebFrame() const { return web_frame_; }
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 ae9c65e6627..fcbc661ab85 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
@@ -5,11 +5,12 @@
#include "third_party/blink/renderer/core/frame/remote_frame_owner.h"
#include "third_party/blink/public/platform/web_resource_timing_info.h"
-#include "third_party/blink/public/web/web_frame_client.h"
+#include "third_party/blink/public/web/web_local_frame_client.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"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+#include "third_party/blink/renderer/core/layout/intrinsic_sizing_info.h"
#include "third_party/blink/renderer/core/timing/performance.h"
namespace blink {
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 3b6d2625944..47f1be02f65 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
@@ -63,12 +63,9 @@ RemoteFrameView* RemoteFrameView::Create(RemoteFrame* remote_frame) {
return view;
}
-void RemoteFrameView::UpdateViewportIntersectionsForSubtree(
- DocumentLifecycle::LifecycleState target_state) {
+void RemoteFrameView::UpdateViewportIntersectionsForSubtree() {
if (!remote_frame_->OwnerLayoutObject())
return;
- if (target_state < DocumentLifecycle::kPaintClean)
- return;
LocalFrameView* local_root_view =
ToLocalFrame(remote_frame_->Tree().Parent())->LocalFrameRoot().View();
@@ -84,16 +81,11 @@ void RemoteFrameView::UpdateViewportIntersectionsForSubtree(
LayoutRect rect(0, 0, frame_rect_.Width(), frame_rect_.Height());
rect.Move(remote_frame_->OwnerLayoutObject()->ContentBoxOffset());
IntRect viewport_intersection;
- VisualRectFlags flags =
- RuntimeEnabledFeatures::IntersectionObserverGeometryMapperEnabled()
- ? kUseGeometryMapper
- : kDefaultVisualRectFlags;
if (remote_frame_->OwnerLayoutObject()->MapToVisualRectInAncestorSpace(
- nullptr, rect, flags)) {
- IntRect root_visible_rect = local_root_view->VisibleContentRect();
+ nullptr, rect, kUseGeometryMapper)) {
+ IntRect root_visible_rect(IntPoint(), local_root_view->Size());
IntRect intersected_rect = EnclosingIntRect(rect);
intersected_rect.Intersect(root_visible_rect);
- intersected_rect.Move(-local_root_view->ScrollOffsetInt());
// Translate the intersection rect from the root frame's coordinate space
// to the remote frame's coordinate space.
@@ -111,6 +103,7 @@ void RemoteFrameView::UpdateViewportIntersectionsForSubtree(
if (viewport_intersection == last_viewport_intersection_)
return;
+ // TODO(szager): Propagate occlusion information.
last_viewport_intersection_ = viewport_intersection;
remote_frame_->Client()->UpdateRemoteViewportIntersection(
viewport_intersection);
@@ -128,7 +121,8 @@ IntRect RemoteFrameView::GetCompositingRect() {
// that needs to be rastered by the OOPIF compositor.
IntSize viewport_size = local_root_view->FrameRect().Size();
if (local_root_view->GetPage()->MainFrame() != local_root_view->GetFrame()) {
- viewport_size = local_root_view->RemoteViewportIntersection().Size();
+ viewport_size =
+ local_root_view->GetFrame().RemoteViewportIntersection().Size();
}
// The viewport size needs to account for intermediate CSS transforms before
@@ -205,8 +199,10 @@ IntRect RemoteFrameView::FrameRect() const {
if (owner) {
LayoutView* owner_layout_view = owner->View();
DCHECK(owner_layout_view);
- if (owner_layout_view->HasOverflowClip())
- location.Move(-owner_layout_view->ScrolledContentOffset());
+ if (owner_layout_view->HasOverflowClip()) {
+ IntSize scroll_offset(owner_layout_view->ScrolledContentOffset());
+ location.SaturatedMove(-scroll_offset.Width(), -scroll_offset.Height());
+ }
}
return IntRect(location, frame_rect_.Size());
@@ -220,8 +216,7 @@ void RemoteFrameView::FrameRectsChanged() {
IntRect screen_space_rect = frame_rect;
if (LocalFrameView* parent = ParentFrameView()) {
- screen_space_rect =
- parent->ConvertToRootFrame(parent->ContentsToFrame(screen_space_rect));
+ screen_space_rect = parent->ConvertToRootFrame(screen_space_rect);
}
remote_frame_->Client()->FrameRectsChanged(frame_rect, screen_space_rect);
}
@@ -344,7 +339,8 @@ bool RemoteFrameView::HasIntrinsicSizingInfo() const {
return has_intrinsic_sizing_info_;
}
-uint32_t RemoteFrameView::Print(const IntRect& rect, WebCanvas* canvas) const {
+uint32_t RemoteFrameView::Print(const IntRect& rect,
+ cc::PaintCanvas* canvas) const {
return remote_frame_->Client()->Print(rect, canvas);
}
diff --git a/chromium/third_party/blink/renderer/core/frame/remote_frame_view.h b/chromium/third_party/blink/renderer/core/frame/remote_frame_view.h
index a57f63bb3fb..25b94e7eaf5 100644
--- a/chromium/third_party/blink/renderer/core/frame/remote_frame_view.h
+++ b/chromium/third_party/blink/renderer/core/frame/remote_frame_view.h
@@ -5,18 +5,22 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_REMOTE_FRAME_VIEW_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_REMOTE_FRAME_VIEW_H_
-#include "third_party/blink/public/platform/web_canvas.h"
+#include "cc/paint/paint_canvas.h"
#include "third_party/blink/renderer/core/dom/document_lifecycle.h"
#include "third_party/blink/renderer/core/frame/frame_view.h"
-#include "third_party/blink/renderer/core/frame/local_frame_view.h"
+#include "third_party/blink/renderer/core/layout/intrinsic_sizing_info.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
-namespace blink {
+namespace cc {
+class PaintCanvas;
+}
+namespace blink {
class CullRect;
class ElementVisibilityObserver;
class GraphicsContext;
+class LocalFrameView;
class RemoteFrame;
class RemoteFrameView final : public GarbageCollectedFinalized<RemoteFrameView>,
@@ -52,8 +56,7 @@ class RemoteFrameView final : public GarbageCollectedFinalized<RemoteFrameView>,
void Show() override;
void SetParentVisible(bool) override;
- void UpdateViewportIntersectionsForSubtree(
- DocumentLifecycle::LifecycleState) override;
+ void UpdateViewportIntersectionsForSubtree() override;
bool GetIntrinsicSizingInfo(IntrinsicSizingInfo&) const override;
@@ -65,7 +68,7 @@ class RemoteFrameView final : public GarbageCollectedFinalized<RemoteFrameView>,
// and reduce the number of paint-ops generated.
IntRect GetCompositingRect();
- uint32_t Print(const IntRect&, WebCanvas*) const;
+ uint32_t Print(const IntRect&, cc::PaintCanvas*) const;
void Trace(blink::Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/core/frame/report.h b/chromium/third_party/blink/renderer/core/frame/report.h
index 7391a8ee717..5163422a1c4 100644
--- a/chromium/third_party/blink/renderer/core/frame/report.h
+++ b/chromium/third_party/blink/renderer/core/frame/report.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_REPORT_H_
#include "third_party/blink/renderer/core/frame/report_body.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
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 d41250e7f83..b8c6458145d 100644
--- a/chromium/third_party/blink/renderer/core/frame/reporting_context.cc
+++ b/chromium/third_party/blink/renderer/core/frame/reporting_context.cc
@@ -4,8 +4,9 @@
#include "third_party/blink/renderer/core/frame/reporting_context.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/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/report.h"
#include "third_party/blink/renderer/core/frame/reporting_observer.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
@@ -30,45 +31,34 @@ ReportingContext* ReportingContext::From(ExecutionContext* context) {
}
void ReportingContext::QueueReport(Report* report) {
- if (!ObserverExists())
- return;
-
- reports_.push_back(report);
+ report_buffer_.insert(report);
- // When the first report of a batch is queued, make a task to report the whole
- // batch (in the queue) to all ReportingObservers.
- if (reports_.size() == 1) {
- execution_context_->GetTaskRunner(TaskType::kMiscPlatformAPI)
- ->PostTask(FROM_HERE, WTF::Bind(&ReportingContext::SendReports,
- WrapWeakPersistent(this)));
- }
-}
+ // Only the most recent 100 reports will remain buffered.
+ // https://wicg.github.io/reporting/#notify-observers
+ if (report_buffer_.size() > 100)
+ report_buffer_.RemoveFirst();
-void ReportingContext::SendReports() {
- // The reports queued to be sent to callbacks are copied (and cleared) before
- // being sent to observers, since additional reports may be queued as a result
- // of the callbacks.
- auto reports_to_send = reports_;
- reports_.clear();
for (auto observer : observers_)
- observer->ReportToCallback(reports_to_send);
+ observer->QueueReport(report);
}
void ReportingContext::RegisterObserver(ReportingObserver* observer) {
observers_.insert(observer);
+ if (!observer->Buffered())
+ return;
+
+ observer->ClearBuffered();
+ for (auto report : report_buffer_)
+ observer->QueueReport(report);
}
void ReportingContext::UnregisterObserver(ReportingObserver* observer) {
observers_.erase(observer);
}
-bool ReportingContext::ObserverExists() {
- return observers_.size();
-}
-
void ReportingContext::Trace(blink::Visitor* visitor) {
visitor->Trace(observers_);
- visitor->Trace(reports_);
+ visitor->Trace(report_buffer_);
visitor->Trace(execution_context_);
Supplement<ExecutionContext>::Trace(visitor);
}
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 ed322d78972..f75fbdef812 100644
--- a/chromium/third_party/blink/renderer/core/frame/reporting_context.h
+++ b/chromium/third_party/blink/renderer/core/frame/reporting_context.h
@@ -30,23 +30,17 @@ class CORE_EXPORT ReportingContext final
// already exist for the given context, one is created.
static ReportingContext* From(ExecutionContext*);
- // Queues a report to be reported to all observers.
+ // Queues a report in all registered observers.
void QueueReport(Report*);
- // Sends all queued reports to all observers.
- void SendReports();
-
void RegisterObserver(ReportingObserver*);
void UnregisterObserver(ReportingObserver*);
- // Returns whether there is at least one active ReportingObserver.
- bool ObserverExists();
-
void Trace(blink::Visitor*) override;
private:
HeapListHashSet<Member<ReportingObserver>> observers_;
- HeapVector<Member<Report>> reports_;
+ HeapListHashSet<Member<Report>> report_buffer_;
Member<ExecutionContext> execution_context_;
};
diff --git a/chromium/third_party/blink/renderer/core/frame/reporting_observer.cc b/chromium/third_party/blink/renderer/core/frame/reporting_observer.cc
index 9db714b9310..9147f97f682 100644
--- a/chromium/third_party/blink/renderer/core/frame/reporting_observer.cc
+++ b/chromium/third_party/blink/renderer/core/frame/reporting_observer.cc
@@ -4,40 +4,95 @@
#include "third_party/blink/renderer/core/frame/reporting_observer.h"
+#include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.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/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/web_task_runner.h"
namespace blink {
ReportingObserver* ReportingObserver::Create(
ExecutionContext* execution_context,
- V8ReportingObserverCallback* callback) {
- return new ReportingObserver(execution_context, callback);
+ V8ReportingObserverCallback* callback,
+ ReportingObserverOptions options) {
+ return new ReportingObserver(execution_context, callback, options);
}
ReportingObserver::ReportingObserver(ExecutionContext* execution_context,
- V8ReportingObserverCallback* callback)
- : execution_context_(execution_context), callback_(callback) {}
+ V8ReportingObserverCallback* callback,
+ ReportingObserverOptions options)
+ : ContextClient(execution_context),
+ execution_context_(execution_context),
+ callback_(callback),
+ options_(options),
+ registered_(false) {}
-void ReportingObserver::ReportToCallback(
- const HeapVector<Member<Report>>& reports) {
- callback_->InvokeAndReportException(this, reports, this);
+bool ReportingObserver::HasPendingActivity() const {
+ return registered_;
+}
+
+void ReportingObserver::ReportToCallback() {
+ // The reports queued to be sent to callbacks are copied (and cleared) before
+ // being sent, since additional reports may be queued as a result of the
+ // callbacks.
+ auto reports_to_send = report_queue_;
+ report_queue_.clear();
+ callback_->InvokeAndReportException(this, reports_to_send, this);
+}
+
+void ReportingObserver::QueueReport(Report* report) {
+ if (!ObservedType(report->type()))
+ return;
+
+ report_queue_.push_back(report);
+
+ // When the first report of a batch is queued, make a task to report the whole
+ // batch.
+ if (report_queue_.size() == 1) {
+ execution_context_->GetTaskRunner(TaskType::kMiscPlatformAPI)
+ ->PostTask(FROM_HERE, WTF::Bind(&ReportingObserver::ReportToCallback,
+ WrapWeakPersistent(this)));
+ }
+}
+
+bool ReportingObserver::ObservedType(const String& type) {
+ return !options_.hasTypes() || options_.types().IsEmpty() ||
+ options_.types().Find(type) != kNotFound;
+}
+
+bool ReportingObserver::Buffered() {
+ return options_.hasBuffered() && options_.buffered();
+}
+
+void ReportingObserver::ClearBuffered() {
+ return options_.setBuffered(false);
}
void ReportingObserver::observe() {
+ registered_ = true;
ReportingContext::From(execution_context_)->RegisterObserver(this);
}
void ReportingObserver::disconnect() {
+ registered_ = false;
ReportingContext::From(execution_context_)->UnregisterObserver(this);
}
+HeapVector<Member<Report>> ReportingObserver::takeRecords() {
+ auto reports = report_queue_;
+ report_queue_.clear();
+ return reports;
+}
+
void ReportingObserver::Trace(blink::Visitor* visitor) {
visitor->Trace(execution_context_);
visitor->Trace(callback_);
+ visitor->Trace(report_queue_);
ScriptWrappable::Trace(visitor);
+ ContextClient::Trace(visitor);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/reporting_observer.h b/chromium/third_party/blink/renderer/core/frame/reporting_observer.h
index 5c7350e4b32..4f358dc8c03 100644
--- a/chromium/third_party/blink/renderer/core/frame/reporting_observer.h
+++ b/chromium/third_party/blink/renderer/core/frame/reporting_observer.h
@@ -5,9 +5,11 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_REPORTING_OBSERVER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_REPORTING_OBSERVER_H_
+#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_reporting_observer_callback.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/core/frame/report.h"
+#include "third_party/blink/renderer/core/frame/reporting_observer_options.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -15,26 +17,54 @@ namespace blink {
class ExecutionContext;
class Report;
-class CORE_EXPORT ReportingObserver final : public ScriptWrappable {
+class CORE_EXPORT ReportingObserver final
+ : public ScriptWrappable,
+ public ActiveScriptWrappable<ReportingObserver>,
+ public ContextClient {
+ USING_GARBAGE_COLLECTED_MIXIN(ReportingObserver);
DEFINE_WRAPPERTYPEINFO();
public:
static ReportingObserver* Create(ExecutionContext*,
- V8ReportingObserverCallback*);
+ V8ReportingObserverCallback*,
+ ReportingObserverOptions);
- // Call the callback with reports.
- void ReportToCallback(const HeapVector<Member<Report>>& reports);
+ // ActiveScriptWrappable
+ bool HasPendingActivity() const final;
+
+ // Call the callback with all reports in |report_queue_|.
+ void ReportToCallback();
+
+ // Queues a report to be reported via callback soon (possibly in a batch).
+ void QueueReport(Report* report);
+
+ // Returns whether this ReportingObserver observes reports of the type |type|,
+ // based on the |types| option.
+ bool ObservedType(const String& type);
+
+ // Returns the state of the |buffered| option.
+ bool Buffered();
+
+ // Sets the |buffered| option to false. This should be called after queueing
+ // all buffered reports, so that they are not reported multiple times.
+ void ClearBuffered();
void observe();
void disconnect();
+ HeapVector<Member<Report>> takeRecords();
void Trace(blink::Visitor*) override;
private:
- explicit ReportingObserver(ExecutionContext*, V8ReportingObserverCallback*);
+ explicit ReportingObserver(ExecutionContext*,
+ V8ReportingObserverCallback*,
+ ReportingObserverOptions);
Member<ExecutionContext> execution_context_;
- Member<V8ReportingObserverCallback> callback_;
+ TraceWrapperMember<V8ReportingObserverCallback> callback_;
+ ReportingObserverOptions options_;
+ HeapVector<Member<Report>> report_queue_;
+ bool registered_;
};
} // namespace blink
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 f3cbb92519a..0d273aebc30 100644
--- a/chromium/third_party/blink/renderer/core/frame/reporting_observer.idl
+++ b/chromium/third_party/blink/renderer/core/frame/reporting_observer.idl
@@ -2,15 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// https://github.com/WICG/reporting/blob/master/EXPLAINER.md#reportingobserver---observing-reports-from-javascript
+// https://w3c.github.io/reporting/#interface-reporting-observer
callback ReportingObserverCallback = void (sequence<Report> reports, ReportingObserver observer);
[
- Constructor(ReportingObserverCallback callback),
+ Constructor(ReportingObserverCallback callback, optional ReportingObserverOptions options),
ConstructorCallWith=ExecutionContext,
+ ActiveScriptWrappable,
RuntimeEnabled=ReportingObserver
] interface ReportingObserver {
void observe();
void disconnect();
+ ReportList takeRecords();
};
+
+typedef sequence<Report> ReportList;
diff --git a/chromium/third_party/blink/renderer/core/frame/reporting_observer_options.idl b/chromium/third_party/blink/renderer/core/frame/reporting_observer_options.idl
new file mode 100644
index 00000000000..8a1ada9189a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/reporting_observer_options.idl
@@ -0,0 +1,10 @@
+// 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.
+
+// https://wicg.github.io/reporting/#dictdef-reportingobserveroptions
+
+dictionary ReportingObserverOptions {
+ sequence<DOMString>? types;
+ boolean buffered = false;
+};
diff --git a/chromium/third_party/blink/renderer/core/frame/root_frame_viewport.cc b/chromium/third_party/blink/renderer/core/frame/root_frame_viewport.cc
index d88e0409929..3dc134c59cc 100644
--- a/chromium/third_party/blink/renderer/core/frame/root_frame_viewport.cc
+++ b/chromium/third_party/blink/renderer/core/frame/root_frame_viewport.cc
@@ -8,10 +8,13 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/scroll_anchor.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/geometry/double_rect.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/scroll/scroll_alignment.h"
+#include "third_party/blink/renderer/platform/scroll/scroll_animator_base.h"
+#include "third_party/blink/renderer/platform/scroll/smooth_scroll_sequencer.h"
namespace blink {
namespace {
@@ -72,7 +75,7 @@ LayoutRect RootFrameViewport::RootContentsToLayoutViewportContents(
// If the root LocalFrameView is the layout viewport then coordinates in the
// root LocalFrameView's content space are already in the layout viewport's
// content space.
- if (root_frame_view.LayoutViewportScrollableArea() == &LayoutViewport())
+ if (root_frame_view.LayoutViewport() == &LayoutViewport())
return ret;
// Make the given rect relative to the top of the layout viewport's content
@@ -173,21 +176,21 @@ IntRect RootFrameViewport::VisibleContentRect(
VisualViewport().VisibleContentRect(scrollbar_inclusion).Size());
}
-LayoutRect RootFrameViewport::VisibleScrollSnapportRect() const {
- // The current viewport is the one that excludes the scrollbars so
- // we intersect the visual viewport with the scrollbar-excluded frameView
- // content rect. However, we don't use visibleContentRect directly since it
+LayoutRect RootFrameViewport::VisibleScrollSnapportRect(
+ IncludeScrollbarsInRect scrollbar_inclusion) const {
+ // The effective viewport is the intersection of the visual viewport with the
+ // layout viewport. However, we don't use visibleContentRect directly since it
// floors the scroll offset. Instead, we use ScrollAnimatorBase::currentOffset
// and construct a LayoutRect from that.
LayoutRect frame_rect_in_content = LayoutRect(
FloatPoint(LayoutViewport().GetScrollAnimator().CurrentOffset()),
- FloatSize(LayoutViewport().VisibleContentRect().Size()));
- LayoutRect visual_rect_in_content =
- LayoutRect(FloatPoint(ScrollOffsetFromScrollAnimators()),
- FloatSize(VisualViewport().VisibleContentRect().Size()));
+ FloatSize(
+ LayoutViewport().VisibleContentRect(scrollbar_inclusion).Size()));
+ LayoutRect visual_rect_in_content = LayoutRect(
+ FloatPoint(ScrollOffsetFromScrollAnimators()),
+ FloatSize(
+ VisualViewport().VisibleContentRect(scrollbar_inclusion).Size()));
- // Intersect layout and visual rects to exclude the scrollbar from the view
- // rect.
LayoutRect visible_scroll_snapport =
Intersection(visual_rect_in_content, frame_rect_in_content);
if (!LayoutViewport().GetLayoutBox())
@@ -243,10 +246,6 @@ void RootFrameViewport::SetScrollOffset(const ScrollOffset& offset,
if (scroll_behavior == kScrollBehaviorAuto)
scroll_behavior = ScrollBehaviorStyle();
- if (scroll_type == kProgrammaticScroll &&
- !LayoutViewport().IsProgrammaticallyScrollable())
- return;
-
if (scroll_type == kAnchoringScroll) {
DistributeScrollBetweenViewports(offset, scroll_type, scroll_behavior,
kLayoutViewport);
@@ -371,10 +370,6 @@ IntSize RootFrameViewport::ScrollOffsetInt() const {
return FlooredIntSize(GetScrollOffset());
}
-IntPoint RootFrameViewport::ScrollOrigin() const {
- return LayoutViewport().ScrollOrigin() + VisualViewport().ScrollOrigin();
-}
-
ScrollOffset RootFrameViewport::GetScrollOffset() const {
return LayoutViewport().GetScrollOffset() +
VisualViewport().GetScrollOffset();
@@ -530,6 +525,13 @@ CompositorElementId RootFrameViewport::GetCompositorElementId() const {
return LayoutViewport().GetCompositorElementId();
}
+CompositorElementId RootFrameViewport::GetScrollbarElementId(
+ ScrollbarOrientation orientation) {
+ return VisualViewport().VisualViewportSuppliesScrollbars()
+ ? VisualViewport().GetScrollbarElementId(orientation)
+ : LayoutViewport().GetScrollbarElementId(orientation);
+}
+
PlatformChromeClient* RootFrameViewport::GetChromeClient() const {
return LayoutViewport().GetChromeClient();
}
diff --git a/chromium/third_party/blink/renderer/core/frame/root_frame_viewport.h b/chromium/third_party/blink/renderer/core/frame/root_frame_viewport.h
index f6b00c099ee..6dd97704a05 100644
--- a/chromium/third_party/blink/renderer/core/frame/root_frame_viewport.h
+++ b/chromium/third_party/blink/renderer/core/frame/root_frame_viewport.h
@@ -64,15 +64,20 @@ class CORE_EXPORT RootFrameViewport final
const WebScrollIntoViewParams&) override;
IntRect VisibleContentRect(
IncludeScrollbarsInRect = kExcludeScrollbars) const override;
- LayoutRect VisibleScrollSnapportRect() const override;
+ LayoutRect VisibleScrollSnapportRect(
+ IncludeScrollbarsInRect = kExcludeScrollbars) const override;
bool ShouldUseIntegerScrollOffset() const override;
+ bool IsThrottled() const override {
+ // RootFrameViewport is always in the main frame, so the frame does not get
+ // throttled.
+ return false;
+ }
bool IsActive() const override;
int ScrollSize(ScrollbarOrientation) const override;
bool IsScrollCornerVisible() const override;
IntRect ScrollCornerRect() const override;
void UpdateScrollOffset(const ScrollOffset&, ScrollType) override;
IntSize ScrollOffsetInt() const override;
- IntPoint ScrollOrigin() const override;
ScrollOffset GetScrollOffset() const override;
IntSize MinimumScrollOffsetInt() const override;
IntSize MaximumScrollOffsetInt() const override;
@@ -98,6 +103,8 @@ class CORE_EXPORT RootFrameViewport final
kIgnorePlatformOverlayScrollbarSize) const override;
ScrollResult UserScroll(ScrollGranularity, const FloatSize&) override;
CompositorElementId GetCompositorElementId() const override;
+ CompositorElementId GetScrollbarElementId(
+ ScrollbarOrientation orientation) override;
bool ScrollAnimatorEnabled() const override;
PlatformChromeClient* GetChromeClient() const override;
SmoothScrollSequencer* GetSmoothScrollSequencer() const override;
diff --git a/chromium/third_party/blink/renderer/core/frame/root_frame_viewport_test.cc b/chromium/third_party/blink/renderer/core/frame/root_frame_viewport_test.cc
index f179a0741d1..03c375761a1 100644
--- a/chromium/third_party/blink/renderer/core/frame/root_frame_viewport_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/root_frame_viewport_test.cc
@@ -102,6 +102,7 @@ class ScrollableAreaStub : public GarbageCollectedFinalized<ScrollableAreaStub>,
scroll_offset_ = offset;
}
bool ShouldUseIntegerScrollOffset() const override { return true; }
+ bool IsThrottled() const override { return false; }
bool IsActive() const override { return true; }
bool IsScrollCornerVisible() const override { return true; }
IntRect ScrollCornerRect() const override { return IntRect(); }
@@ -138,25 +139,26 @@ class ScrollableAreaStub : public GarbageCollectedFinalized<ScrollableAreaStub>,
scoped_refptr<base::SingleThreadTaskRunner> timer_task_runner_;
};
-class RootFrameViewStub : public ScrollableAreaStub {
+class RootLayoutViewportStub : public ScrollableAreaStub {
public:
- static RootFrameViewStub* Create(const IntSize& viewport_size,
- const IntSize& contents_size) {
- return new RootFrameViewStub(viewport_size, contents_size);
+ static RootLayoutViewportStub* Create(const IntSize& viewport_size,
+ const IntSize& contents_size) {
+ return new RootLayoutViewportStub(viewport_size, contents_size);
}
ScrollOffset MaximumScrollOffset() const override {
return ScrollOffset(ContentsSize() - ViewportSize());
}
- LayoutRect DocumentToAbsolute(const LayoutRect& rect) const {
+ LayoutRect DocumentToFrame(const LayoutRect& rect) const {
LayoutRect ret = rect;
ret.Move(LayoutSize(-GetScrollOffset()));
return ret;
}
private:
- RootFrameViewStub(const IntSize& viewport_size, const IntSize& contents_size)
+ RootLayoutViewportStub(const IntSize& viewport_size,
+ const IntSize& contents_size)
: ScrollableAreaStub(viewport_size, contents_size) {}
int VisibleWidth() const override { return viewport_size_.Width(); }
@@ -211,8 +213,8 @@ class RootFrameViewportTest : public testing::Test {
// correctly, that is, the visual viewport can scroll, but not the layout.
TEST_F(RootFrameViewportTest, UserInputScrollable) {
IntSize viewport_size(100, 150);
- RootFrameViewStub* layout_viewport =
- RootFrameViewStub::Create(viewport_size, IntSize(200, 300));
+ RootLayoutViewportStub* layout_viewport =
+ RootLayoutViewportStub::Create(viewport_size, IntSize(200, 300));
VisualViewportStub* visual_viewport =
VisualViewportStub::Create(viewport_size, viewport_size);
@@ -274,8 +276,8 @@ TEST_F(RootFrameViewportTest, UserInputScrollable) {
// using the // RootFrameViewport interface.
TEST_F(RootFrameViewportTest, TestScrollAnimatorUpdatedBeforeScroll) {
IntSize viewport_size(100, 150);
- RootFrameViewStub* layout_viewport =
- RootFrameViewStub::Create(viewport_size, IntSize(200, 300));
+ RootLayoutViewportStub* layout_viewport =
+ RootLayoutViewportStub::Create(viewport_size, IntSize(200, 300));
VisualViewportStub* visual_viewport =
VisualViewportStub::Create(viewport_size, viewport_size);
@@ -315,8 +317,8 @@ TEST_F(RootFrameViewportTest, TestScrollAnimatorUpdatedBeforeScroll) {
// and visual viewport such that the given rect is centered in the viewport.
TEST_F(RootFrameViewportTest, ScrollIntoView) {
IntSize viewport_size(100, 150);
- RootFrameViewStub* layout_viewport =
- RootFrameViewStub::Create(viewport_size, IntSize(200, 300));
+ RootLayoutViewportStub* layout_viewport =
+ RootLayoutViewportStub::Create(viewport_size, IntSize(200, 300));
VisualViewportStub* visual_viewport =
VisualViewportStub::Create(viewport_size, viewport_size);
@@ -328,7 +330,7 @@ TEST_F(RootFrameViewportTest, ScrollIntoView) {
// scaled.
visual_viewport->SetViewportSize(IntSize(100, 100));
root_frame_viewport->ScrollIntoView(
- layout_viewport->DocumentToAbsolute(LayoutRect(100, 250, 50, 50)),
+ layout_viewport->DocumentToFrame(LayoutRect(100, 250, 50, 50)),
WebScrollIntoViewParams(ScrollAlignment::kAlignToEdgeIfNeeded,
ScrollAlignment::kAlignToEdgeIfNeeded,
kProgrammaticScroll, true,
@@ -337,7 +339,7 @@ TEST_F(RootFrameViewportTest, ScrollIntoView) {
EXPECT_EQ(ScrollOffset(0, 50), visual_viewport->GetScrollOffset());
root_frame_viewport->ScrollIntoView(
- layout_viewport->DocumentToAbsolute(LayoutRect(25, 75, 50, 50)),
+ layout_viewport->DocumentToFrame(LayoutRect(25, 75, 50, 50)),
WebScrollIntoViewParams(ScrollAlignment::kAlignToEdgeIfNeeded,
ScrollAlignment::kAlignToEdgeIfNeeded,
kProgrammaticScroll, true,
@@ -351,7 +353,7 @@ TEST_F(RootFrameViewportTest, ScrollIntoView) {
root_frame_viewport->SetScrollOffset(ScrollOffset(), kProgrammaticScroll);
root_frame_viewport->ScrollIntoView(
- layout_viewport->DocumentToAbsolute(LayoutRect(50, 75, 50, 75)),
+ layout_viewport->DocumentToFrame(LayoutRect(50, 75, 50, 75)),
WebScrollIntoViewParams(ScrollAlignment::kAlignToEdgeIfNeeded,
ScrollAlignment::kAlignToEdgeIfNeeded,
kProgrammaticScroll, true,
@@ -360,7 +362,7 @@ TEST_F(RootFrameViewportTest, ScrollIntoView) {
EXPECT_EQ(ScrollOffset(50, 75), visual_viewport->GetScrollOffset());
root_frame_viewport->ScrollIntoView(
- layout_viewport->DocumentToAbsolute(LayoutRect(190, 290, 10, 10)),
+ layout_viewport->DocumentToFrame(LayoutRect(190, 290, 10, 10)),
WebScrollIntoViewParams(ScrollAlignment::kAlignToEdgeIfNeeded,
ScrollAlignment::kAlignToEdgeIfNeeded,
kProgrammaticScroll, true,
@@ -377,7 +379,7 @@ TEST_F(RootFrameViewportTest, ScrollIntoView) {
kProgrammaticScroll);
root_frame_viewport->ScrollIntoView(
- layout_viewport->DocumentToAbsolute(LayoutRect(
+ layout_viewport->DocumentToFrame(LayoutRect(
root_frame_viewport->VisibleContentRect(kExcludeScrollbars))),
WebScrollIntoViewParams(ScrollAlignment::kAlignToEdgeIfNeeded,
ScrollAlignment::kAlignToEdgeIfNeeded,
@@ -387,7 +389,7 @@ TEST_F(RootFrameViewportTest, ScrollIntoView) {
EXPECT_EQ(ScrollOffset(0, 10), visual_viewport->GetScrollOffset());
root_frame_viewport->ScrollIntoView(
- layout_viewport->DocumentToAbsolute(LayoutRect(
+ layout_viewport->DocumentToFrame(LayoutRect(
root_frame_viewport->VisibleContentRect(kExcludeScrollbars))),
WebScrollIntoViewParams(ScrollAlignment::kAlignCenterAlways,
ScrollAlignment::kAlignCenterAlways,
@@ -397,7 +399,7 @@ TEST_F(RootFrameViewportTest, ScrollIntoView) {
EXPECT_EQ(ScrollOffset(0, 10), visual_viewport->GetScrollOffset());
root_frame_viewport->ScrollIntoView(
- layout_viewport->DocumentToAbsolute(LayoutRect(
+ layout_viewport->DocumentToFrame(LayoutRect(
root_frame_viewport->VisibleContentRect(kExcludeScrollbars))),
WebScrollIntoViewParams(
ScrollAlignment::kAlignTopAlways, ScrollAlignment::kAlignTopAlways,
@@ -409,8 +411,8 @@ TEST_F(RootFrameViewportTest, ScrollIntoView) {
// Tests that the setScrollOffset method works correctly with both viewports.
TEST_F(RootFrameViewportTest, SetScrollOffset) {
IntSize viewport_size(500, 500);
- RootFrameViewStub* layout_viewport =
- RootFrameViewStub::Create(viewport_size, IntSize(1000, 2000));
+ RootLayoutViewportStub* layout_viewport =
+ RootLayoutViewportStub::Create(viewport_size, IntSize(1000, 2000));
VisualViewportStub* visual_viewport =
VisualViewportStub::Create(viewport_size, viewport_size);
@@ -449,8 +451,8 @@ TEST_F(RootFrameViewportTest, SetScrollOffset) {
// calculated, taking into account both viewports and page scale.
TEST_F(RootFrameViewportTest, VisibleContentRect) {
IntSize viewport_size(500, 401);
- RootFrameViewStub* layout_viewport =
- RootFrameViewStub::Create(viewport_size, IntSize(1000, 2000));
+ RootLayoutViewportStub* layout_viewport =
+ RootLayoutViewportStub::Create(viewport_size, IntSize(1000, 2000));
VisualViewportStub* visual_viewport =
VisualViewportStub::Create(viewport_size, viewport_size);
@@ -463,22 +465,22 @@ TEST_F(RootFrameViewportTest, VisibleContentRect) {
EXPECT_EQ(IntPoint(100, 75),
root_frame_viewport->VisibleContentRect().Location());
EXPECT_EQ(ScrollOffset(500, 401),
- root_frame_viewport->VisibleContentRect().Size());
+ DoubleSize(root_frame_viewport->VisibleContentRect().Size()));
visual_viewport->SetScale(2);
EXPECT_EQ(IntPoint(100, 75),
root_frame_viewport->VisibleContentRect().Location());
EXPECT_EQ(ScrollOffset(250, 201),
- root_frame_viewport->VisibleContentRect().Size());
+ DoubleSize(root_frame_viewport->VisibleContentRect().Size()));
}
// Tests that scrolls on the root frame scroll the visual viewport before
// trying to scroll the layout viewport.
TEST_F(RootFrameViewportTest, ViewportScrollOrder) {
IntSize viewport_size(100, 100);
- RootFrameViewStub* layout_viewport =
- RootFrameViewStub::Create(viewport_size, IntSize(200, 300));
+ RootLayoutViewportStub* layout_viewport =
+ RootLayoutViewportStub::Create(viewport_size, IntSize(200, 300));
VisualViewportStub* visual_viewport =
VisualViewportStub::Create(viewport_size, viewport_size);
@@ -501,13 +503,13 @@ TEST_F(RootFrameViewportTest, ViewportScrollOrder) {
// instead of the original.
TEST_F(RootFrameViewportTest, SetAlternateLayoutViewport) {
IntSize viewport_size(100, 100);
- RootFrameViewStub* layout_viewport =
- RootFrameViewStub::Create(viewport_size, IntSize(200, 300));
+ RootLayoutViewportStub* layout_viewport =
+ RootLayoutViewportStub::Create(viewport_size, IntSize(200, 300));
VisualViewportStub* visual_viewport =
VisualViewportStub::Create(viewport_size, viewport_size);
- RootFrameViewStub* alternate_scroller =
- RootFrameViewStub::Create(viewport_size, IntSize(600, 500));
+ RootLayoutViewportStub* alternate_scroller =
+ RootLayoutViewportStub::Create(viewport_size, IntSize(600, 500));
RootFrameViewport* root_frame_viewport =
RootFrameViewport::Create(*visual_viewport, *layout_viewport);
diff --git a/chromium/third_party/blink/renderer/core/frame/rotation_viewport_anchor.cc b/chromium/third_party/blink/renderer/core/frame/rotation_viewport_anchor.cc
index befe380e83e..85925c61167 100644
--- a/chromium/third_party/blink/renderer/core/frame/rotation_viewport_anchor.cc
+++ b/chromium/third_party/blink/renderer/core/frame/rotation_viewport_anchor.cc
@@ -27,10 +27,12 @@ Node* FindNonEmptyAnchorNode(const FloatPoint& absolute_point,
const IntRect& view_rect,
EventHandler& event_handler) {
IntPoint point = FlooredIntPoint(absolute_point);
- Node* node = event_handler
- .HitTestResultAtPoint(point, HitTestRequest::kReadOnly |
- HitTestRequest::kActive)
- .InnerNode();
+ HitTestLocation location(point);
+ Node* node =
+ event_handler
+ .HitTestResultAtLocation(
+ location, HitTestRequest::kReadOnly | HitTestRequest::kActive)
+ .InnerNode();
if (!node)
return nullptr;
@@ -47,10 +49,10 @@ Node* FindNonEmptyAnchorNode(const FloatPoint& absolute_point,
if (node_size.Width() * node_size.Height() > max_node_area) {
IntSize point_offset = view_rect.Size();
point_offset.Scale(kViewportAnchorRelativeEpsilon);
+ HitTestLocation location(point + point_offset);
node = event_handler
- .HitTestResultAtPoint(
- point + point_offset,
- HitTestRequest::kReadOnly | HitTestRequest::kActive)
+ .HitTestResultAtLocation(location, HitTestRequest::kReadOnly |
+ HitTestRequest::kActive)
.InnerNode();
}
@@ -83,7 +85,7 @@ void MoveIntoRect(FloatRect& inner, const IntRect& outer) {
// VisualViewport::maximumScrollPosition() does the same.
// The value of minumumPosition is already adjusted since it is
// constructed from an integer point.
- maximum_position = FlooredIntPoint(maximum_position);
+ maximum_position = FloatPoint(FlooredIntPoint(maximum_position));
FloatPoint inner_origin = inner.Location();
inner_origin = inner_origin.ExpandedTo(minimum_position);
@@ -159,13 +161,13 @@ void RotationViewportAnchor::SetAnchor() {
visual_viewport_->ViewportToRootFrame(anchor_offset));
Node* node = FindNonEmptyAnchorNode(
- root_frame_view_->DocumentToAbsolute(anchor_point_in_document),
+ root_frame_view_->DocumentToFrame(anchor_point_in_document),
inner_view_rect, root_frame_view_->GetFrame().GetEventHandler());
if (!node || !node->GetLayoutObject())
return;
anchor_node_ = node;
- anchor_node_bounds_ = root_frame_view_->AbsoluteToDocument(
+ anchor_node_bounds_ = root_frame_view_->FrameToDocument(
LayoutRect(node->GetLayoutObject()->AbsoluteBoundingBoxRect()));
anchor_in_node_coords_ =
anchor_point_in_document - FloatPoint(anchor_node_bounds_.Location());
@@ -190,8 +192,8 @@ void RotationViewportAnchor::RestoreToAnchor() {
ComputeOrigins(visual_viewport_size, main_frame_origin,
visual_viewport_origin);
- LayoutViewport().SetScrollOffset(ToScrollOffset(main_frame_origin),
- kProgrammaticScroll);
+ LayoutViewport().SetScrollOffset(
+ ToScrollOffset(FloatPoint(main_frame_origin)), kProgrammaticScroll);
// Set scale before location, since location can be clamped on setting scale.
visual_viewport_->SetScale(new_page_scale_factor);
@@ -239,7 +241,7 @@ FloatPoint RotationViewportAnchor::GetInnerOrigin(
!anchor_node_->GetLayoutObject())
return visual_viewport_in_document_;
- const LayoutRect current_node_bounds = root_frame_view_->AbsoluteToDocument(
+ const LayoutRect current_node_bounds = root_frame_view_->FrameToDocument(
LayoutRect(anchor_node_->GetLayoutObject()->AbsoluteBoundingBoxRect()));
if (anchor_node_bounds_ == current_node_bounds)
return visual_viewport_in_document_;
diff --git a/chromium/third_party/blink/renderer/core/frame/rotation_viewport_anchor_test.cc b/chromium/third_party/blink/renderer/core/frame/rotation_viewport_anchor_test.cc
index bbce5d9a4cc..391187aa637 100644
--- a/chromium/third_party/blink/renderer/core/frame/rotation_viewport_anchor_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/rotation_viewport_anchor_test.cc
@@ -4,6 +4,7 @@
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.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/testing/testing_platform_support.h"
@@ -49,8 +50,7 @@ TEST_F(RotationViewportAnchorTest, SimpleAbsolutePosition) {
Compositor().BeginFrame();
Document& document = GetDocument();
- ScrollableArea* layout_viewport =
- document.View()->LayoutViewportScrollableArea();
+ ScrollableArea* layout_viewport = document.View()->LayoutViewport();
// Place the target at the top-center of the viewport. This is where the
// rotation anchor finds the node to anchor to.
@@ -90,8 +90,7 @@ TEST_F(RotationViewportAnchorTest, PositionRelativeToViewportSize) {
Compositor().BeginFrame();
Document& document = GetDocument();
- ScrollableArea* layout_viewport =
- document.View()->LayoutViewportScrollableArea();
+ ScrollableArea* layout_viewport = document.View()->LayoutViewport();
IntPoint target_position(5 * WebView().Size().width,
5 * WebView().Size().height);
diff --git a/chromium/third_party/blink/renderer/core/frame/settings.json5 b/chromium/third_party/blink/renderer/core/frame/settings.json5
index ad56eeaab26..24f03d2a651 100644
--- a/chromium/third_party/blink/renderer/core/frame/settings.json5
+++ b/chromium/third_party/blink/renderer/core/frame/settings.json5
@@ -575,6 +575,15 @@
initial: false,
},
+ // Set the timeout seconds of NetworkQuietTimers in FirstMeaningfulPainterDetector.
+ // Used by embedders who want to change the timeout time in order to run web contents
+ // on various embedded devices and changeable network bandwidths in different regions.
+ {
+ name: "FMPNetworkQuietTimeout",
+ initial: "0.5",
+ type: "double",
+ },
+
// Forces initialization of main world, even if no scripts will be executed.
// Used by inspector to report all contexts.
{
@@ -957,5 +966,39 @@
name: "shouldThrottlePushState",
initial: true,
},
+
+ //
+ // Lazy frame loading distance-from-viewport thresholds for different effective connection types.
+ //
+ {
+ name: "lazyFrameLoadingDistanceThresholdPxUnknown",
+ initial: 800,
+ type: "int",
+ },
+ {
+ name: "lazyFrameLoadingDistanceThresholdPxOffline",
+ initial: 800,
+ type: "int",
+ },
+ {
+ name: "lazyFrameLoadingDistanceThresholdPxSlow2G",
+ initial: 800,
+ type: "int",
+ },
+ {
+ name: "lazyFrameLoadingDistanceThresholdPx2G",
+ initial: 800,
+ type: "int",
+ },
+ {
+ name: "lazyFrameLoadingDistanceThresholdPx3G",
+ initial: 800,
+ type: "int",
+ },
+ {
+ name: "lazyFrameLoadingDistanceThresholdPx4G",
+ initial: 800,
+ type: "int",
+ },
],
}
diff --git a/chromium/third_party/blink/renderer/core/frame/smart_clip.cc b/chromium/third_party/blink/renderer/core/frame/smart_clip.cc
index 0293c36a570..b0887aaf9be 100644
--- a/chromium/third_party/blink/renderer/core/frame/smart_clip.cc
+++ b/chromium/third_party/blink/renderer/core/frame/smart_clip.cc
@@ -45,7 +45,7 @@ namespace blink {
static IntRect ConvertToContentCoordinatesWithoutCollapsingToZero(
const IntRect& rect_in_viewport,
const LocalFrameView* view) {
- IntRect rect_in_contents = view->ViewportToContents(rect_in_viewport);
+ IntRect rect_in_contents = view->ViewportToFrame(rect_in_viewport);
if (rect_in_viewport.Width() > 0 && !rect_in_contents.Width())
rect_in_contents.SetWidth(1);
if (rect_in_viewport.Height() > 0 && !rect_in_contents.Height())
@@ -92,7 +92,7 @@ SmartClipData SmartClip::DataForRect(const IntRect& crop_rect_in_viewport) {
}
return SmartClipData(
- frame_->GetDocument()->View()->ContentsToViewport(united_rects),
+ frame_->GetDocument()->View()->FrameToViewport(united_rects),
collected_text.ToString());
}
diff --git a/chromium/third_party/blink/renderer/core/frame/use_counter.cc b/chromium/third_party/blink/renderer/core/frame/use_counter.cc
index 9b98fc845b5..50cf45bc1bf 100644
--- a/chromium/third_party/blink/renderer/core/frame/use_counter.cc
+++ b/chromium/third_party/blink/renderer/core/frame/use_counter.cc
@@ -37,7 +37,7 @@
#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"
-#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -349,7 +349,7 @@ int UseCounter::MapCSSPropertyIdToCSSSampleIdForHistogram(
return 162;
case CSSPropertyWordSpacing:
return 163;
- case CSSPropertyWordWrap:
+ case CSSPropertyAliasWordWrap:
return 164;
case CSSPropertyZIndex:
return 165;
@@ -383,29 +383,29 @@ int UseCounter::MapCSSPropertyIdToCSSSampleIdForHistogram(
return 180;
case CSSPropertyAliasWebkitBackgroundSize:
return 181;
- case CSSPropertyWebkitBorderAfter:
+ case CSSPropertyAliasWebkitBorderAfter:
return 182;
- case CSSPropertyWebkitBorderAfterColor:
+ case CSSPropertyAliasWebkitBorderAfterColor:
return 183;
- case CSSPropertyWebkitBorderAfterStyle:
+ case CSSPropertyAliasWebkitBorderAfterStyle:
return 184;
- case CSSPropertyWebkitBorderAfterWidth:
+ case CSSPropertyAliasWebkitBorderAfterWidth:
return 185;
- case CSSPropertyWebkitBorderBefore:
+ case CSSPropertyAliasWebkitBorderBefore:
return 186;
- case CSSPropertyWebkitBorderBeforeColor:
+ case CSSPropertyAliasWebkitBorderBeforeColor:
return 187;
- case CSSPropertyWebkitBorderBeforeStyle:
+ case CSSPropertyAliasWebkitBorderBeforeStyle:
return 188;
- case CSSPropertyWebkitBorderBeforeWidth:
+ case CSSPropertyAliasWebkitBorderBeforeWidth:
return 189;
- case CSSPropertyWebkitBorderEnd:
+ case CSSPropertyAliasWebkitBorderEnd:
return 190;
- case CSSPropertyWebkitBorderEndColor:
+ case CSSPropertyAliasWebkitBorderEndColor:
return 191;
- case CSSPropertyWebkitBorderEndStyle:
+ case CSSPropertyAliasWebkitBorderEndStyle:
return 192;
- case CSSPropertyWebkitBorderEndWidth:
+ case CSSPropertyAliasWebkitBorderEndWidth:
return 193;
// CSSPropertyWebkitBorderFit was 194
case CSSPropertyWebkitBorderHorizontalSpacing:
@@ -414,13 +414,13 @@ int UseCounter::MapCSSPropertyIdToCSSSampleIdForHistogram(
return 196;
case CSSPropertyAliasWebkitBorderRadius:
return 197;
- case CSSPropertyWebkitBorderStart:
+ case CSSPropertyAliasWebkitBorderStart:
return 198;
- case CSSPropertyWebkitBorderStartColor:
+ case CSSPropertyAliasWebkitBorderStartColor:
return 199;
- case CSSPropertyWebkitBorderStartStyle:
+ case CSSPropertyAliasWebkitBorderStartStyle:
return 200;
- case CSSPropertyWebkitBorderStartWidth:
+ case CSSPropertyAliasWebkitBorderStartWidth:
return 201;
case CSSPropertyWebkitBorderVerticalSpacing:
return 202;
@@ -524,9 +524,9 @@ int UseCounter::MapCSSPropertyIdToCSSSampleIdForHistogram(
return 260;
// case CSSPropertyWebkitLineGrid: return 261;
// case CSSPropertyWebkitLineSnap: return 262;
- case CSSPropertyWebkitLogicalWidth:
+ case CSSPropertyAliasWebkitLogicalWidth:
return 263;
- case CSSPropertyWebkitLogicalHeight:
+ case CSSPropertyAliasWebkitLogicalHeight:
return 264;
case CSSPropertyWebkitMarginAfterCollapse:
return 265;
@@ -538,13 +538,13 @@ int UseCounter::MapCSSPropertyIdToCSSSampleIdForHistogram(
return 268;
case CSSPropertyWebkitMarginCollapse:
return 269;
- case CSSPropertyWebkitMarginAfter:
+ case CSSPropertyAliasWebkitMarginAfter:
return 270;
- case CSSPropertyWebkitMarginBefore:
+ case CSSPropertyAliasWebkitMarginBefore:
return 271;
- case CSSPropertyWebkitMarginEnd:
+ case CSSPropertyAliasWebkitMarginEnd:
return 272;
- case CSSPropertyWebkitMarginStart:
+ case CSSPropertyAliasWebkitMarginStart:
return 273;
// CSSPropertyWebkitMarquee was 274.
// CSSPropertyInternalMarquee* were 275-279.
@@ -584,24 +584,24 @@ int UseCounter::MapCSSPropertyIdToCSSSampleIdForHistogram(
return 296;
case CSSPropertyWebkitMaskSize:
return 297;
- case CSSPropertyWebkitMaxLogicalWidth:
+ case CSSPropertyAliasWebkitMaxLogicalWidth:
return 298;
- case CSSPropertyWebkitMaxLogicalHeight:
+ case CSSPropertyAliasWebkitMaxLogicalHeight:
return 299;
- case CSSPropertyWebkitMinLogicalWidth:
+ case CSSPropertyAliasWebkitMinLogicalWidth:
return 300;
- case CSSPropertyWebkitMinLogicalHeight:
+ case CSSPropertyAliasWebkitMinLogicalHeight:
return 301;
// WebkitNbspMode has been deleted, was return 302;
case CSSPropertyOrder:
return 303;
- case CSSPropertyWebkitPaddingAfter:
+ case CSSPropertyAliasWebkitPaddingAfter:
return 304;
- case CSSPropertyWebkitPaddingBefore:
+ case CSSPropertyAliasWebkitPaddingBefore:
return 305;
- case CSSPropertyWebkitPaddingEnd:
+ case CSSPropertyAliasWebkitPaddingEnd:
return 306;
- case CSSPropertyWebkitPaddingStart:
+ case CSSPropertyAliasWebkitPaddingStart:
return 307;
case CSSPropertyAliasWebkitPerspective:
return 308;
@@ -1138,6 +1138,92 @@ int UseCounter::MapCSSPropertyIdToCSSSampleIdForHistogram(
return 592;
case CSSPropertyViewportFit:
return 593;
+ case CSSPropertyMarginBlockStart:
+ return 594;
+ case CSSPropertyMarginBlockEnd:
+ return 595;
+ case CSSPropertyMarginInlineStart:
+ return 596;
+ case CSSPropertyMarginInlineEnd:
+ return 597;
+ case CSSPropertyPaddingBlockStart:
+ return 598;
+ case CSSPropertyPaddingBlockEnd:
+ return 599;
+ case CSSPropertyPaddingInlineStart:
+ return 600;
+ case CSSPropertyPaddingInlineEnd:
+ return 601;
+ case CSSPropertyBorderBlockEndColor:
+ return 602;
+ case CSSPropertyBorderBlockEndStyle:
+ return 603;
+ case CSSPropertyBorderBlockEndWidth:
+ return 604;
+ case CSSPropertyBorderBlockStartColor:
+ return 605;
+ case CSSPropertyBorderBlockStartStyle:
+ return 606;
+ case CSSPropertyBorderBlockStartWidth:
+ return 607;
+ case CSSPropertyBorderInlineEndColor:
+ return 608;
+ case CSSPropertyBorderInlineEndStyle:
+ return 609;
+ case CSSPropertyBorderInlineEndWidth:
+ return 610;
+ case CSSPropertyBorderInlineStartColor:
+ return 611;
+ case CSSPropertyBorderInlineStartStyle:
+ return 612;
+ case CSSPropertyBorderInlineStartWidth:
+ return 613;
+ case CSSPropertyBorderBlockStart:
+ return 614;
+ case CSSPropertyBorderBlockEnd:
+ return 615;
+ case CSSPropertyBorderInlineStart:
+ return 616;
+ case CSSPropertyBorderInlineEnd:
+ return 617;
+ case CSSPropertyMarginBlock:
+ return 618;
+ case CSSPropertyMarginInline:
+ return 619;
+ case CSSPropertyPaddingBlock:
+ return 620;
+ case CSSPropertyPaddingInline:
+ return 621;
+ case CSSPropertyBorderBlockColor:
+ return 622;
+ case CSSPropertyBorderBlockStyle:
+ return 623;
+ case CSSPropertyBorderBlockWidth:
+ return 624;
+ case CSSPropertyBorderInlineColor:
+ return 625;
+ case CSSPropertyBorderInlineStyle:
+ return 626;
+ case CSSPropertyBorderInlineWidth:
+ return 627;
+ case CSSPropertyBorderBlock:
+ return 628;
+ case CSSPropertyBorderInline:
+ return 629;
+ case CSSPropertyInsetBlockStart:
+ return 630;
+ case CSSPropertyInsetBlockEnd:
+ return 631;
+ case CSSPropertyInsetBlock:
+ return 632;
+ case CSSPropertyInsetInlineStart:
+ return 633;
+ case CSSPropertyInsetInlineEnd:
+ return 634;
+ case CSSPropertyInsetInline:
+ return 635;
+ case CSSPropertyInset:
+ return 636;
// 1. Add new features above this line (don't change the assigned numbers of
// the existing items).
// 2. Update kMaximumCSSSampleId (defined in
@@ -1154,9 +1240,10 @@ int UseCounter::MapCSSPropertyIdToCSSSampleIdForHistogram(
return 0;
}
-UseCounter::UseCounter(Context context)
+UseCounter::UseCounter(Context context, CommitState commit_state)
: mute_count_(0),
context_(context),
+ commit_state_(commit_state),
features_recorded_(static_cast<int>(WebFeature::kNumberOfFeatures)),
css_recorded_(numCSSPropertyIDs),
animated_css_recorded_(numCSSPropertyIDs) {}
@@ -1174,28 +1261,33 @@ void UseCounter::RecordMeasurement(WebFeature feature,
if (mute_count_)
return;
- if (context_ == kDefaultContext &&
- !Page::OrdinaryPages().Contains(source_frame.GetPage()))
- return;
-
// PageDestruction is reserved as a scaling factor.
DCHECK_NE(WebFeature::kOBSOLETE_PageDestruction, feature);
DCHECK_NE(WebFeature::kPageVisits, feature);
DCHECK_GE(WebFeature::kNumberOfFeatures, feature);
int feature_id = static_cast<int>(feature);
- if (!features_recorded_.QuickGet(feature_id)) {
- if (context_ != kDisabledContext) {
- // Note that HTTPArchive tooling looks specifically for this event - see
- // https://github.com/HTTPArchive/httparchive/issues/59
- TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.feature_usage"),
- "FeatureFirstUsed", "feature", feature_id);
+ if (features_recorded_.QuickGet(feature_id))
+ return;
+ if (commit_state_ >= kCommited)
+ ReportAndTraceMeasurementByFeatureId(feature_id, source_frame);
+
+ features_recorded_.QuickSet(feature_id);
+}
+
+void UseCounter::ReportAndTraceMeasurementByFeatureId(
+ int feature_id,
+ const LocalFrame& source_frame) {
+ if (context_ != kDisabledContext) {
+ // Note that HTTPArchive tooling looks specifically for this event -
+ // see https://github.com/HTTPArchive/httparchive/issues/59
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.feature_usage"),
+ "FeatureFirstUsed", "feature", feature_id);
+ if (context_ != kDefaultContext)
FeaturesHistogram().Count(feature_id);
- if (LocalFrameClient* client = source_frame.Client())
- client->DidObserveNewFeatureUsage(feature);
- NotifyFeatureCounted(feature);
- }
- features_recorded_.QuickSet(feature_id);
+ if (LocalFrameClient* client = source_frame.Client())
+ client->DidObserveNewFeatureUsage(static_cast<WebFeature>(feature_id));
+ NotifyFeatureCounted(static_cast<WebFeature>(feature_id));
}
}
@@ -1211,6 +1303,10 @@ bool UseCounter::HasRecordedMeasurement(WebFeature feature) const {
return features_recorded_.QuickGet(static_cast<int>(feature));
}
+void UseCounter::ClearMeasurementForTesting(WebFeature feature) {
+ features_recorded_.QuickClear(static_cast<int>(feature));
+}
+
// Static
void UseCounter::CountIfFeatureWouldBeBlockedByFeaturePolicy(
const LocalFrame& frame,
@@ -1246,75 +1342,81 @@ void UseCounter::Trace(blink::Visitor* visitor) {
}
void UseCounter::DidCommitLoad(const LocalFrame* frame) {
- // Reset state from previous load.
- // Use the protocol of the document being loaded into the main frame to
- // decide whether this page is interesting from a metrics perspective.
- // Drop usage tracking on view source and new-tab pages. This matches the
- // policy of page_load_metrics.
- // Note that SVGImage cases always have an about:blank URL
- if (context_ != kSVGImageContext) {
- if (!frame->GetDocument() ||
- !Page::OrdinaryPages().Contains(frame->GetPage())) {
- context_ = kDisabledContext;
- return;
- }
- const KURL url = frame->GetDocument()->Url();
- if (url.ProtocolIs("chrome-extension"))
- context_ = kExtensionContext;
- else if (frame->GetDocument()->IsViewSource())
- context_ = kDisabledContext;
- else if (!frame->Client() || !frame->Client()->ShouldTrackUseCounter(url))
- context_ = kDisabledContext;
- else if (frame->GetDocument()->IsPrefetchOnly())
- context_ = kDisabledContext;
- // TODO(loonybear): Service worker and shared worker count feature usage on
- // the blink side use counter. Once the blink side use counter is removed
- // (crbug.com/811948), the checker for shadow pages should be removed.
- else if (frame->GetSettings()->IsShadowPage())
- context_ = kDisabledContext;
- else if (SchemeRegistry::ShouldTrackUsageMetricsForScheme(url.Protocol()))
- context_ = kDefaultContext;
- else
- context_ = kDisabledContext;
- }
+ const KURL url = frame->GetDocument()->Url();
+ if (url.ProtocolIs("chrome-extension"))
+ context_ = kExtensionContext;
- features_recorded_.ClearAll();
- css_recorded_.ClearAll();
- animated_css_recorded_.ClearAll();
-
- if (context_ != kDisabledContext && !mute_count_) {
- FeaturesHistogram().Count(static_cast<int>(WebFeature::kPageVisits));
- if (context_ != kExtensionContext) {
- CssHistogram().Count(mojom::blink::kTotalPagesMeasuredCSSSampleId);
- AnimatedCSSHistogram().Count(
- mojom::blink::kTotalPagesMeasuredCSSSampleId);
+ DCHECK_EQ(kPreCommit, commit_state_);
+ commit_state_ = kCommited;
+ if (!mute_count_) {
+ // If any feature was recorded prior to navigation commits, flush to the
+ // browser side.
+ for (size_t feature_id = 0; feature_id < features_recorded_.size();
+ ++feature_id) {
+ if (features_recorded_.QuickGet(feature_id))
+ ReportAndTraceMeasurementByFeatureId(feature_id, *frame);
+ }
+ for (size_t sample_id = 0; sample_id < css_recorded_.size(); ++sample_id) {
+ if (css_recorded_.QuickGet(sample_id))
+ ReportAndTraceMeasurementByCSSSampleId(sample_id, frame, false);
+ if (animated_css_recorded_.QuickGet(sample_id))
+ ReportAndTraceMeasurementByCSSSampleId(sample_id, frame, true);
}
+
+ // TODO(loonybear): remove or move SVG histogram and extension histogram
+ // to the browser side.
+ if ((context_ == kSVGImageContext || context_ == kExtensionContext))
+ FeaturesHistogram().Count(static_cast<int>(WebFeature::kPageVisits));
}
}
+// TODO(loonybear): Replace Count(LocalFrame*) by Count(DocumentLoader*).
void UseCounter::Count(const LocalFrame* frame, WebFeature feature) {
if (!frame)
return;
- Page* page = frame->GetPage();
- if (!page)
- return;
+ DocumentLoader* loader = frame->GetDocument()
+ ? frame->GetDocument()->Loader()
+ : frame->Loader().GetProvisionalDocumentLoader();
+ UseCounter::Count(loader, feature);
+}
- page->GetUseCounter().Count(feature, frame);
+void UseCounter::Count(DocumentLoader* loader, WebFeature feature) {
+ if (!loader)
+ return;
+ loader->GetUseCounter().Count(feature, loader->GetFrame());
}
void UseCounter::Count(const Document& document, WebFeature feature) {
- Count(document.GetFrame(), feature);
+ if (DocumentLoader* loader = document.Loader())
+ loader->GetUseCounter().Count(feature, document.GetFrame());
+}
+
+void UseCounter::Count(ExecutionContext* context, WebFeature feature) {
+ if (!context)
+ return;
+ if (context->IsDocument()) {
+ Count(*ToDocument(context), feature);
+ return;
+ }
+ if (context->IsWorkerOrWorkletGlobalScope()) {
+ ToWorkerOrWorkletGlobalScope(context)->CountFeature(feature);
+ }
}
bool UseCounter::IsCounted(Document& document, WebFeature feature) {
- Page* page = document.GetPage();
- if (!page)
- return false;
- return page->GetUseCounter().HasRecordedMeasurement(feature);
+ DocumentLoader* loader = document.Loader();
+ return loader ? loader->GetUseCounter().HasRecordedMeasurement(feature)
+ : false;
}
bool UseCounter::IsCounted(CSSPropertyID unresolved_property) {
- return css_recorded_.QuickGet(unresolved_property);
+ return css_recorded_.QuickGet(
+ MapCSSPropertyIdToCSSSampleIdForHistogram(unresolved_property));
+}
+
+void UseCounter::ClearCountForTesting(Document& document, WebFeature feature) {
+ if (DocumentLoader* loader = document.Loader())
+ loader->GetUseCounter().ClearMeasurementForTesting(feature);
}
void UseCounter::AddObserver(Observer* observer) {
@@ -1323,26 +1425,12 @@ void UseCounter::AddObserver(Observer* observer) {
}
bool UseCounter::IsCounted(Document& document, const String& string) {
- Page* page = document.GetPage();
- if (!page)
- return false;
-
CSSPropertyID unresolved_property = unresolvedCSSPropertyID(string);
if (unresolved_property == CSSPropertyInvalid)
return false;
- return page->GetUseCounter().IsCounted(unresolved_property);
-}
-
-void UseCounter::Count(ExecutionContext* context, WebFeature feature) {
- if (!context)
- return;
- if (context->IsDocument()) {
- Count(*ToDocument(context), feature);
- return;
- }
- if (context->IsWorkerOrWorkletGlobalScope()) {
- ToWorkerOrWorkletGlobalScope(context)->CountFeature(feature);
- }
+ DocumentLoader* loader = document.Loader();
+ return loader ? loader->GetUseCounter().IsCounted(unresolved_property)
+ : false;
}
void UseCounter::CountCrossOriginIframe(const Document& document,
@@ -1352,6 +1440,20 @@ void UseCounter::CountCrossOriginIframe(const Document& document,
Count(frame, feature);
}
+void UseCounter::ReportAndTraceMeasurementByCSSSampleId(int sample_id,
+ const LocalFrame* frame,
+ bool is_animated) {
+ // Note that HTTPArchive tooling looks specifically for this event - see
+ // https://github.com/HTTPArchive/httparchive/issues/59
+ if (context_ != kDisabledContext && context_ != kExtensionContext) {
+ const char* name = is_animated ? "AnimatedCSSFirstUsed" : "CSSFirstUsed";
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.feature_usage"), name,
+ "feature", sample_id);
+ if (frame && frame->Client())
+ frame->Client()->DidObserveNewCssPropertyUsage(sample_id, is_animated);
+ }
+}
+
void UseCounter::Count(CSSParserMode css_parser_mode,
CSSPropertyID property,
const LocalFrame* source_frame) {
@@ -1360,55 +1462,42 @@ void UseCounter::Count(CSSParserMode css_parser_mode,
if (!IsUseCounterEnabledForMode(css_parser_mode) || mute_count_)
return;
- // TODO(loonybear): Remove this check once UseCounter is moved from Page to
- // DocumentLoader. No features would be counted before
- // UseCounter::DidCommitLoad (crbug.com/828416).
- if (context_ == kDefaultContext &&
- !Page::OrdinaryPages().Contains(source_frame->GetPage()))
+ int sample_id = MapCSSPropertyIdToCSSSampleIdForHistogram(property);
+ if (css_recorded_.QuickGet(sample_id))
return;
+ if (commit_state_ >= kCommited)
+ ReportAndTraceMeasurementByCSSSampleId(sample_id, source_frame, false);
- if (!css_recorded_.QuickGet(property)) {
- // Note that HTTPArchive tooling looks specifically for this event - see
- // https://github.com/HTTPArchive/httparchive/issues/59
- int sample_id = MapCSSPropertyIdToCSSSampleIdForHistogram(property);
- if (context_ != kDisabledContext && context_ != kExtensionContext) {
- TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.feature_usage"),
- "CSSFirstUsed", "feature", sample_id);
- CssHistogram().Count(sample_id);
- if (source_frame && source_frame->Client())
- source_frame->Client()->DidObserveNewCssPropertyUsage(sample_id, false);
- }
- css_recorded_.QuickSet(property);
- }
+ css_recorded_.QuickSet(sample_id);
}
void UseCounter::Count(WebFeature feature, const LocalFrame* source_frame) {
+ if (!source_frame)
+ return;
RecordMeasurement(feature, *source_frame);
}
bool UseCounter::IsCountedAnimatedCSS(CSSPropertyID unresolved_property) {
- return animated_css_recorded_.QuickGet(unresolved_property);
+ return animated_css_recorded_.QuickGet(
+ MapCSSPropertyIdToCSSSampleIdForHistogram(unresolved_property));
}
bool UseCounter::IsCountedAnimatedCSS(Document& document,
const String& string) {
- Page* page = document.GetPage();
- if (!page)
- return false;
-
CSSPropertyID unresolved_property = unresolvedCSSPropertyID(string);
if (unresolved_property == CSSPropertyInvalid)
return false;
- return page->GetUseCounter().IsCountedAnimatedCSS(unresolved_property);
+ DocumentLoader* loader = document.Loader();
+ return loader
+ ? loader->GetUseCounter().IsCountedAnimatedCSS(unresolved_property)
+ : false;
}
void UseCounter::CountAnimatedCSS(const Document& document,
CSSPropertyID property) {
- Page* page = document.GetPage();
- if (!page)
- return;
-
- page->GetUseCounter().CountAnimatedCSS(property, document.GetFrame());
+ DocumentLoader* loader = document.Loader();
+ if (loader)
+ loader->GetUseCounter().CountAnimatedCSS(property, document.GetFrame());
}
void UseCounter::CountAnimatedCSS(CSSPropertyID property,
@@ -1418,24 +1507,13 @@ void UseCounter::CountAnimatedCSS(CSSPropertyID property,
if (mute_count_)
return;
- // TODO(loonybear): Remove this check once UseCounter is moved from Page to
- // DocumentLoader. No features would be counted before
- // UseCounter::DidCommitLoad (crbug.com/828416).
- if (context_ == kDefaultContext &&
- !Page::OrdinaryPages().Contains(source_frame->GetPage()))
+ int sample_id = MapCSSPropertyIdToCSSSampleIdForHistogram(property);
+ if (animated_css_recorded_.QuickGet(sample_id))
return;
+ if (commit_state_ >= kCommited)
+ ReportAndTraceMeasurementByCSSSampleId(sample_id, source_frame, true);
- if (!animated_css_recorded_.QuickGet(property)) {
- int sample_id = MapCSSPropertyIdToCSSSampleIdForHistogram(property);
- if (context_ != kDisabledContext && context_ != kExtensionContext) {
- TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("blink.feature_usage"),
- "AnimatedCSSFirstUsed", "feature", sample_id);
- AnimatedCSSHistogram().Count(sample_id);
- if (source_frame && source_frame->Client())
- source_frame->Client()->DidObserveNewCssPropertyUsage(sample_id, true);
- }
- animated_css_recorded_.QuickSet(property);
- }
+ animated_css_recorded_.QuickSet(sample_id);
}
void UseCounter::NotifyFeatureCounted(WebFeature feature) {
@@ -1451,6 +1529,8 @@ void UseCounter::NotifyFeatureCounted(WebFeature feature) {
EnumerationHistogram& UseCounter::FeaturesHistogram() const {
DCHECK_NE(kDisabledContext, context_);
+ // The default features histogram is being recorded on the browser side.
+ DCHECK_NE(kDefaultContext, context_);
// Every SVGImage has it's own Page instance, and multiple web pages can
// share the usage of a single SVGImage. Ideally perhaps we'd delegate
// metrics from an SVGImage to one of the Page's it's displayed in, but
@@ -1465,43 +1545,25 @@ EnumerationHistogram& UseCounter::FeaturesHistogram() const {
static_cast<int32_t>(WebFeature::kNumberOfFeatures)));
// Track what features/properties have been reported to the browser side
// histogram.
- DEFINE_STATIC_LOCAL(blink::EnumerationHistogram, histogram,
- ("Blink.UseCounter.Features_Legacy",
- static_cast<int32_t>(WebFeature::kNumberOfFeatures)));
- switch (context_) {
- case kSVGImageContext:
- return svg_histogram;
- case kExtensionContext:
- return extension_histogram;
- case kDefaultContext:
- case kDisabledContext:
- break;
- }
- return histogram;
+ return context_ == kSVGImageContext ? svg_histogram : extension_histogram;
}
EnumerationHistogram& UseCounter::CssHistogram() const {
- DCHECK_NE(kExtensionContext, context_);
- DCHECK_NE(kDisabledContext, context_);
- DEFINE_STATIC_LOCAL(
- blink::EnumerationHistogram, histogram,
- ("Blink.UseCounter.CSSProperties", mojom::blink::kMaximumCSSSampleId));
+ DCHECK_EQ(kSVGImageContext, context_);
DEFINE_STATIC_LOCAL(blink::EnumerationHistogram, svg_histogram,
("Blink.UseCounter.SVGImage.CSSProperties",
mojom::blink::kMaximumCSSSampleId));
- return context_ == kSVGImageContext ? svg_histogram : histogram;
+ return svg_histogram;
}
EnumerationHistogram& UseCounter::AnimatedCSSHistogram() const {
- DEFINE_STATIC_LOCAL(blink::EnumerationHistogram, histogram,
- ("Blink.UseCounter.AnimatedCSSProperties",
- mojom::blink::kMaximumCSSSampleId));
+ DCHECK_EQ(kSVGImageContext, context_);
DEFINE_STATIC_LOCAL(blink::EnumerationHistogram, svg_histogram,
("Blink.UseCounter.SVGImage.AnimatedCSSProperties",
mojom::blink::kMaximumCSSSampleId));
- return context_ == kSVGImageContext ? svg_histogram : histogram;
+ return svg_histogram;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/use_counter.h b/chromium/third_party/blink/renderer/core/frame/use_counter.h
index 49d51481d7d..d120eaaadc3 100644
--- a/chromium/third_party/blink/renderer/core/frame/use_counter.h
+++ b/chromium/third_party/blink/renderer/core/frame/use_counter.h
@@ -40,6 +40,7 @@ namespace blink {
class CSSStyleSheet;
class Document;
+class DocumentLoader;
class EnumerationHistogram;
class ExecutionContext;
class LocalFrame;
@@ -79,7 +80,9 @@ class CORE_EXPORT UseCounter {
kDisabledContext
};
- UseCounter(Context = kDefaultContext);
+ enum CommitState { kPreCommit, kCommited };
+
+ UseCounter(Context = kDefaultContext, CommitState = kPreCommit);
// An interface to observe UseCounter changes. Note that this is never
// notified when the counter is disabled by |m_muteCount| or when |m_context|
@@ -95,7 +98,11 @@ class CORE_EXPORT UseCounter {
};
// "count" sets the bit for this feature to 1. Repeated calls are ignored.
+ // Count(const LocalFrame*) is being deprecated since during a navigation it
+ // may pick the wrong DocumentLoader (will guess and avoid using the
+ // provisional document loader when both loaders are present).
static void Count(const LocalFrame*, WebFeature);
+ static void Count(DocumentLoader*, WebFeature);
static void Count(const Document&, WebFeature);
static void Count(ExecutionContext*, WebFeature);
@@ -117,6 +124,8 @@ class CORE_EXPORT UseCounter {
static bool IsCounted(Document&, const String&);
bool IsCounted(CSSPropertyID unresolved_property);
+ static void ClearCountForTesting(Document& document, WebFeature feature);
+
// Return whether the CSSPropertyID was previously counted for this document.
// NOTE: only for use in testing.
static bool IsCountedAnimatedCSS(Document&, const String&);
@@ -135,12 +144,18 @@ class CORE_EXPORT UseCounter {
void UnmuteForInspector();
void RecordMeasurement(WebFeature, const LocalFrame&);
+ void ReportAndTraceMeasurementByFeatureId(int, const LocalFrame&);
+ void ReportAndTraceMeasurementByCSSSampleId(int,
+ const LocalFrame*,
+ bool /*is_animated*/);
// Return whether the feature has been seen since the last page load
// (except when muted). Does include features seen in documents which have
// reporting disabled.
bool HasRecordedMeasurement(WebFeature) const;
+ void ClearMeasurementForTesting(WebFeature);
+
// Triggers a use counter if a feature, which is currently available in all
// frames, would be blocked by the introduction of feature policy. This takes
// two counters (which may be the same). It triggers |blockedCrossOrigin| if
@@ -170,8 +185,13 @@ class CORE_EXPORT UseCounter {
// The scope represented by this UseCounter instance, which must be fixed for
// the duration of a page but can change when a new page is loaded.
Context context_;
+ // CommitState tracks whether navigation has commited. Prior to commit,
+ // UseCounters are logged locally and delivered to the browser only once the
+ // document has been commited (eg. to ensure never logging a feature that has
+ // no corresponding PageVisits).
+ CommitState commit_state_;
- // Track what features/properties have been reported to the histograms.
+ // Track what features/properties have been recorded.
BitVector features_recorded_;
BitVector css_recorded_;
BitVector animated_css_recorded_;
diff --git a/chromium/third_party/blink/renderer/core/frame/use_counter_test.cc b/chromium/third_party/blink/renderer/core/frame/use_counter_test.cc
index 33a3685de1d..7670a6c4bf2 100644
--- a/chromium/third_party/blink/renderer/core/frame/use_counter_test.cc
+++ b/chromium/third_party/blink/renderer/core/frame/use_counter_test.cc
@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/use_counter/css_property_id.mojom-blink.h"
#include "third_party/blink/renderer/core/css/css_test_helper.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
-#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/html/html_html_element.h"
+#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
#include "third_party/blink/renderer/platform/testing/histogram_tester.h"
@@ -16,31 +17,13 @@
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
namespace {
-// The legacy features histogram will be removed in crbug.com/811948.
-// The browser side use counter (renamed to "Blink.UseCounter.Features") is
-// responsinle for recording the metrics instead.
-const char kLegacyFeaturesHistogramName[] = "Blink.UseCounter.Features_Legacy";
-const char kCSSHistogramName[] = "Blink.UseCounter.CSSProperties";
-const char kAnimatedCSSHistogramName[] =
- "Blink.UseCounter.AnimatedCSSProperties";
const char kExtensionFeaturesHistogramName[] =
"Blink.UseCounter.Extensions.Features";
const char kSVGFeaturesHistogramName[] = "Blink.UseCounter.SVGImage.Features";
-const char kSVGCSSHistogramName[] = "Blink.UseCounter.SVGImage.CSSProperties";
-const char kSVGAnimatedCSSHistogramName[] =
- "Blink.UseCounter.SVGImage.AnimatedCSSProperties";
-
-const char* kHistogramList[] = {
- kLegacyFeaturesHistogramName, kCSSHistogramName,
- kAnimatedCSSHistogramName, kExtensionFeaturesHistogramName,
- kSVGCSSHistogramName, kSVGCSSHistogramName,
- kSVGAnimatedCSSHistogramName};
// In practice, SVGs always appear to be loaded with an about:blank URL
const char kSvgUrl[] = "about:blank";
-const char* const kInternalUrl = kSvgUrl;
-const char kHttpsUrl[] = "https://dummysite.com/";
const char kExtensionUrl[] = "chrome-extension://dummysite/";
int GetPageVisitsBucketforHistogram(const std::string& histogram_name) {
@@ -57,7 +40,9 @@ using WebFeature = mojom::WebFeature;
class UseCounterTest : public testing::Test {
public:
- UseCounterTest() : dummy_(DummyPageHolder::Create()) {}
+ UseCounterTest() : dummy_(DummyPageHolder::Create()) {
+ Page::InsertOrdinaryPageForTesting(&dummy_->GetPage());
+ }
protected:
LocalFrame* GetFrame() { return &dummy_->GetFrame(); }
@@ -66,14 +51,16 @@ class UseCounterTest : public testing::Test {
Document& GetDocument() { return dummy_->GetDocument(); }
template <typename T>
- void HistogramBasicTest(const std::string& histogram,
- T item,
- T second_item,
- std::function<bool(T)> counted,
- std::function<void(T)> count,
- std::function<int(T)> histogram_map,
- std::function<void(LocalFrame*)> did_commit_load,
- const std::string& url);
+ void HistogramBasicTest(
+ const std::string& histogram,
+ T item,
+ T second_item,
+ std::function<bool(T, UseCounter&)> counted,
+ std::function<void(T, UseCounter&)> count,
+ std::function<int(T)> histogram_map,
+ std::function<void(LocalFrame*, UseCounter&)> did_commit_load,
+ const std::string& url,
+ UseCounter::Context context = UseCounter::kDefaultContext);
std::unique_ptr<DummyPageHolder> dummy_;
HistogramTester histogram_tester_;
};
@@ -83,184 +70,90 @@ void UseCounterTest::HistogramBasicTest(
const std::string& histogram,
T item,
T second_item,
- std::function<bool(T)> counted,
- std::function<void(T)> count,
+ std::function<bool(T, UseCounter&)> counted,
+ std::function<void(T, UseCounter&)> count,
std::function<int(T)> histogram_map,
- std::function<void(LocalFrame*)> did_commit_load,
- const std::string& url) {
+ std::function<void(LocalFrame*, UseCounter&)> did_commit_load,
+ const std::string& url,
+ UseCounter::Context context) {
int page_visits_bucket = GetPageVisitsBucketforHistogram(histogram);
+ UseCounter use_counter0(context, UseCounter::kCommited);
+
// Test recording a single (arbitrary) counter
- EXPECT_FALSE(counted(item));
- count(item);
- EXPECT_TRUE(counted(item));
+ EXPECT_FALSE(counted(item, use_counter0));
+ count(item, use_counter0);
+ EXPECT_TRUE(counted(item, use_counter0));
histogram_tester_.ExpectUniqueSample(histogram, histogram_map(item), 1);
// Test that repeated measurements have no effect
- count(item);
+ count(item, use_counter0);
histogram_tester_.ExpectUniqueSample(histogram, histogram_map(item), 1);
// Test recording a different sample
- EXPECT_FALSE(counted(second_item));
- count(second_item);
- EXPECT_TRUE(counted(second_item));
+ EXPECT_FALSE(counted(second_item, use_counter0));
+ count(second_item, use_counter0);
+ EXPECT_TRUE(counted(second_item, use_counter0));
histogram_tester_.ExpectBucketCount(histogram, histogram_map(item), 1);
histogram_tester_.ExpectBucketCount(histogram, histogram_map(second_item), 1);
histogram_tester_.ExpectTotalCount(histogram, 2);
// After a page load, the histograms will be updated, even when the URL
// scheme is internal
+ UseCounter use_counter1(context);
SetURL(URLTestHelpers::ToKURL(url));
- did_commit_load(GetFrame());
+ did_commit_load(GetFrame(), use_counter1);
histogram_tester_.ExpectBucketCount(histogram, histogram_map(item), 1);
histogram_tester_.ExpectBucketCount(histogram, histogram_map(second_item), 1);
histogram_tester_.ExpectBucketCount(histogram, page_visits_bucket, 1);
histogram_tester_.ExpectTotalCount(histogram, 3);
// Now a repeat measurement should get recorded again, exactly once
- EXPECT_FALSE(counted(item));
- count(item);
- count(item);
- EXPECT_TRUE(counted(item));
+ EXPECT_FALSE(counted(item, use_counter1));
+ count(item, use_counter1);
+ count(item, use_counter1);
+ EXPECT_TRUE(counted(item, use_counter1));
histogram_tester_.ExpectBucketCount(histogram, histogram_map(item), 2);
histogram_tester_.ExpectTotalCount(histogram, 4);
-
- // For all histograms, no other histograms besides |histogram| should
- // be affected.
- for (const std::string& unaffected_histogram : kHistogramList) {
- if (unaffected_histogram == histogram)
- continue;
- // CSS histograms are never created in didCommitLoad when the context is
- // extension.
- if (histogram == kExtensionFeaturesHistogramName &&
- unaffected_histogram.find("CSS") != std::string::npos)
- continue;
-
- // The expected total count for "Features" of unaffected histograms should
- // be either:
- // a. pageVisits, for "CSSFeatures"; or
- // b. 0 (pageVisits is 0), for others, including "SVGImage.CSSFeatures"
- // since no SVG images are loaded at all.
- histogram_tester_.ExpectTotalCount(
- unaffected_histogram,
- 0 + histogram_tester_.GetBucketCount(
- unaffected_histogram,
- GetPageVisitsBucketforHistogram(unaffected_histogram)));
- }
-}
-
-TEST_F(UseCounterTest, RecordingFeatures) {
- UseCounter use_counter;
- HistogramBasicTest<WebFeature>(
- kLegacyFeaturesHistogramName, WebFeature::kFetch,
- WebFeature::kFetchBodyStream,
- [&](WebFeature feature) -> bool {
- return use_counter.HasRecordedMeasurement(feature);
- },
- [&](WebFeature feature) {
- use_counter.RecordMeasurement(feature, *GetFrame());
- },
- [](WebFeature feature) -> int { return static_cast<int>(feature); },
- [&](LocalFrame* frame) { use_counter.DidCommitLoad(frame); }, kHttpsUrl);
-}
-
-TEST_F(UseCounterTest, RecordingCSSProperties) {
- UseCounter use_counter;
- HistogramBasicTest<CSSPropertyID>(
- kCSSHistogramName, CSSPropertyFont, CSSPropertyZoom,
- [&](CSSPropertyID property) -> bool {
- return use_counter.IsCounted(property);
- },
- [&](CSSPropertyID property) {
- use_counter.Count(kHTMLStandardMode, property, GetFrame());
- },
- [](CSSPropertyID property) -> int {
- return UseCounter::MapCSSPropertyIdToCSSSampleIdForHistogram(property);
- },
- [&](LocalFrame* frame) { use_counter.DidCommitLoad(frame); }, kHttpsUrl);
-}
-
-TEST_F(UseCounterTest, RecordingAnimatedCSSProperties) {
- UseCounter use_counter;
- HistogramBasicTest<CSSPropertyID>(
- kAnimatedCSSHistogramName, CSSPropertyOpacity, CSSPropertyVariable,
- [&](CSSPropertyID property) -> bool {
- return use_counter.IsCountedAnimatedCSS(property);
- },
- [&](CSSPropertyID property) {
- use_counter.CountAnimatedCSS(property, GetFrame());
- },
- [](CSSPropertyID property) -> int {
- return UseCounter::MapCSSPropertyIdToCSSSampleIdForHistogram(property);
- },
- [&](LocalFrame* frame) { use_counter.DidCommitLoad(frame); }, kHttpsUrl);
}
TEST_F(UseCounterTest, RecordingExtensions) {
- UseCounter use_counter(UseCounter::kExtensionContext);
HistogramBasicTest<WebFeature>(
kExtensionFeaturesHistogramName, WebFeature::kFetch,
WebFeature::kFetchBodyStream,
- [&](WebFeature feature) -> bool {
+ [&](WebFeature feature, UseCounter& use_counter) -> bool {
return use_counter.HasRecordedMeasurement(feature);
},
- [&](WebFeature feature) {
+ [&](WebFeature feature, UseCounter& use_counter) {
use_counter.RecordMeasurement(feature, *GetFrame());
},
[](WebFeature feature) -> int { return static_cast<int>(feature); },
- [&](LocalFrame* frame) { use_counter.DidCommitLoad(frame); },
- kExtensionUrl);
+ [&](LocalFrame* frame, UseCounter& use_counter) {
+ use_counter.DidCommitLoad(frame);
+ },
+ kExtensionUrl, UseCounter::kExtensionContext);
}
TEST_F(UseCounterTest, SVGImageContextFeatures) {
- UseCounter use_counter(UseCounter::kSVGImageContext);
HistogramBasicTest<WebFeature>(
kSVGFeaturesHistogramName, WebFeature::kSVGSMILAdditiveAnimation,
WebFeature::kSVGSMILAnimationElementTiming,
- [&](WebFeature feature) -> bool {
+ [&](WebFeature feature, UseCounter& use_counter) -> bool {
return use_counter.HasRecordedMeasurement(feature);
},
- [&](WebFeature feature) {
+ [&](WebFeature feature, UseCounter& use_counter) {
use_counter.RecordMeasurement(feature, *GetFrame());
},
[](WebFeature feature) -> int { return static_cast<int>(feature); },
- [&](LocalFrame* frame) { use_counter.DidCommitLoad(frame); }, kSvgUrl);
-}
-
-TEST_F(UseCounterTest, SVGImageContextCSSProperties) {
- UseCounter use_counter(UseCounter::kSVGImageContext);
- HistogramBasicTest<CSSPropertyID>(
- kSVGCSSHistogramName, CSSPropertyFont, CSSPropertyZoom,
- [&](CSSPropertyID property) -> bool {
- return use_counter.IsCounted(property);
- },
- [&](CSSPropertyID property) {
- use_counter.Count(kHTMLStandardMode, property, GetFrame());
- },
- [](CSSPropertyID property) -> int {
- return UseCounter::MapCSSPropertyIdToCSSSampleIdForHistogram(property);
- },
- [&](LocalFrame* frame) { use_counter.DidCommitLoad(frame); }, kSvgUrl);
-}
-
-TEST_F(UseCounterTest, SVGImageContextAnimatedCSSProperties) {
- UseCounter use_counter(UseCounter::kSVGImageContext);
- HistogramBasicTest<CSSPropertyID>(
- kSVGAnimatedCSSHistogramName, CSSPropertyOpacity, CSSPropertyVariable,
- [&](CSSPropertyID property) -> bool {
- return use_counter.IsCountedAnimatedCSS(property);
+ [&](LocalFrame* frame, UseCounter& use_counter) {
+ use_counter.DidCommitLoad(frame);
},
- [&](CSSPropertyID property) {
- use_counter.CountAnimatedCSS(property, GetFrame());
- },
- [](CSSPropertyID property) -> int {
- return UseCounter::MapCSSPropertyIdToCSSSampleIdForHistogram(property);
- },
- [&](LocalFrame* frame) { use_counter.DidCommitLoad(frame); }, kSvgUrl);
+ kSvgUrl, UseCounter::kSVGImageContext);
}
TEST_F(UseCounterTest, CSSSelectorPseudoIS) {
std::unique_ptr<DummyPageHolder> dummy_page_holder =
DummyPageHolder::Create(IntSize(800, 600));
+ Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
Document& document = dummy_page_holder->GetDocument();
WebFeature feature = WebFeature::kCSSSelectorPseudoIS;
EXPECT_FALSE(UseCounter::IsCounted(document, feature));
@@ -269,54 +162,6 @@ TEST_F(UseCounterTest, CSSSelectorPseudoIS) {
EXPECT_TRUE(UseCounter::IsCounted(document, feature));
}
-// TODO(lunalu): When removing the legacy use counter and its tests, find
-// another way to test muting behavior.
-TEST_F(UseCounterTest, InspectorDisablesMeasurement) {
- UseCounter use_counter;
-
- // The specific feature we use here isn't important.
- WebFeature feature = WebFeature::kSVGSMILElementInDocument;
- CSSPropertyID property = CSSPropertyFontWeight;
- CSSParserMode parser_mode = kHTMLStandardMode;
-
- EXPECT_FALSE(use_counter.HasRecordedMeasurement(feature));
-
- use_counter.MuteForInspector();
- use_counter.RecordMeasurement(feature, *GetFrame());
- EXPECT_FALSE(use_counter.HasRecordedMeasurement(feature));
- use_counter.Count(parser_mode, property, GetFrame());
- EXPECT_FALSE(use_counter.IsCounted(property));
- histogram_tester_.ExpectTotalCount(kLegacyFeaturesHistogramName, 0);
- histogram_tester_.ExpectTotalCount(kCSSHistogramName, 0);
-
- use_counter.MuteForInspector();
- use_counter.RecordMeasurement(feature, *GetFrame());
- EXPECT_FALSE(use_counter.HasRecordedMeasurement(feature));
- use_counter.Count(parser_mode, property, GetFrame());
- EXPECT_FALSE(use_counter.IsCounted(property));
- histogram_tester_.ExpectTotalCount(kLegacyFeaturesHistogramName, 0);
- histogram_tester_.ExpectTotalCount(kCSSHistogramName, 0);
-
- use_counter.UnmuteForInspector();
- use_counter.RecordMeasurement(feature, *GetFrame());
- EXPECT_FALSE(use_counter.HasRecordedMeasurement(feature));
- use_counter.Count(parser_mode, property, GetFrame());
- EXPECT_FALSE(use_counter.IsCounted(property));
- histogram_tester_.ExpectTotalCount(kLegacyFeaturesHistogramName, 0);
- histogram_tester_.ExpectTotalCount(kCSSHistogramName, 0);
-
- use_counter.UnmuteForInspector();
- use_counter.RecordMeasurement(feature, *GetFrame());
- EXPECT_TRUE(use_counter.HasRecordedMeasurement(feature));
- use_counter.Count(parser_mode, property, GetFrame());
- EXPECT_TRUE(use_counter.IsCounted(property));
- histogram_tester_.ExpectUniqueSample(kLegacyFeaturesHistogramName,
- static_cast<int>(feature), 1);
- histogram_tester_.ExpectUniqueSample(
- kCSSHistogramName,
- UseCounter::MapCSSPropertyIdToCSSSampleIdForHistogram(property), 1);
-}
-
/*
* Counter-specific tests
*
@@ -331,6 +176,7 @@ TEST_F(UseCounterTest, InspectorDisablesMeasurement) {
TEST_F(UseCounterTest, CSSSelectorPseudoAnyLink) {
std::unique_ptr<DummyPageHolder> dummy_page_holder =
DummyPageHolder::Create(IntSize(800, 600));
+ Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
Document& document = dummy_page_holder->GetDocument();
WebFeature feature = WebFeature::kCSSSelectorPseudoAnyLink;
EXPECT_FALSE(UseCounter::IsCounted(document, feature));
@@ -342,6 +188,7 @@ TEST_F(UseCounterTest, CSSSelectorPseudoAnyLink) {
TEST_F(UseCounterTest, CSSSelectorPseudoWebkitAnyLink) {
std::unique_ptr<DummyPageHolder> dummy_page_holder =
DummyPageHolder::Create(IntSize(800, 600));
+ Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
Document& document = dummy_page_holder->GetDocument();
WebFeature feature = WebFeature::kCSSSelectorPseudoWebkitAnyLink;
EXPECT_FALSE(UseCounter::IsCounted(document, feature));
@@ -361,6 +208,7 @@ TEST_F(UseCounterTest, CSSTypedOMStylePropertyMap) {
TEST_F(UseCounterTest, CSSSelectorPseudoMatches) {
std::unique_ptr<DummyPageHolder> dummy_page_holder =
DummyPageHolder::Create(IntSize(800, 600));
+ Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
Document& document = dummy_page_holder->GetDocument();
WebFeature feature = WebFeature::kCSSSelectorPseudoMatches;
EXPECT_FALSE(UseCounter::IsCounted(document, feature));
@@ -369,134 +217,10 @@ TEST_F(UseCounterTest, CSSSelectorPseudoMatches) {
EXPECT_TRUE(UseCounter::IsCounted(document, feature));
}
-TEST_F(UseCounterTest, DropMeasurementOnViewSourcePages) {
- UseCounter use_counter;
- SetIsViewSource();
- SetURL(URLTestHelpers::ToKURL(kHttpsUrl));
- use_counter.DidCommitLoad(GetFrame());
-
- WebFeature feature = WebFeature::kFetch;
- EXPECT_FALSE(use_counter.HasRecordedMeasurement(feature));
- histogram_tester_.ExpectTotalCount(kLegacyFeaturesHistogramName, 0);
- use_counter.RecordMeasurement(feature, *GetFrame());
- // The feature will be marked as seen.
- EXPECT_TRUE(use_counter.HasRecordedMeasurement(feature));
- // But the feature is not recorded to UMA.
- histogram_tester_.ExpectTotalCount(kLegacyFeaturesHistogramName, 0);
-}
-
-void ExpectHistograms(const HistogramTester& histogram_tester,
- int visits_count,
- WebFeature feature,
- int feature_count,
- CSSPropertyID property,
- int property_count) {
- histogram_tester.ExpectBucketCount(kLegacyFeaturesHistogramName,
- static_cast<int>(WebFeature::kPageVisits),
- visits_count);
- histogram_tester.ExpectBucketCount(kLegacyFeaturesHistogramName,
- static_cast<int>(feature), feature_count);
- histogram_tester.ExpectTotalCount(kLegacyFeaturesHistogramName,
- visits_count + feature_count);
- histogram_tester.ExpectBucketCount(kCSSHistogramName, 1, visits_count);
- histogram_tester.ExpectBucketCount(
- kCSSHistogramName,
- UseCounter::MapCSSPropertyIdToCSSSampleIdForHistogram(property),
- property_count);
- histogram_tester.ExpectTotalCount(kCSSHistogramName,
- visits_count + property_count);
-}
-
-TEST_F(UseCounterTest, MutedDocuments) {
- UseCounter use_counter;
- // Counters triggered before any load are always reported.
- use_counter.RecordMeasurement(WebFeature::kFetch, *GetFrame());
- use_counter.Count(kHTMLStandardMode, CSSPropertyFontWeight, GetFrame());
- ExpectHistograms(histogram_tester_, 0, WebFeature::kFetch, 1,
- CSSPropertyFontWeight, 1);
-
- // Loading an internal page doesn't bump PageVisits and metrics not reported.
- SetURL(URLTestHelpers::ToKURL(kInternalUrl));
- use_counter.DidCommitLoad(GetFrame());
- EXPECT_FALSE(use_counter.HasRecordedMeasurement(WebFeature::kFetch));
- EXPECT_FALSE(use_counter.IsCounted(CSSPropertyFontWeight));
- use_counter.RecordMeasurement(WebFeature::kFetch, *GetFrame());
- use_counter.Count(kHTMLStandardMode, CSSPropertyFontWeight, GetFrame());
- ExpectHistograms(histogram_tester_, 0, WebFeature::kFetch, 1,
- CSSPropertyFontWeight, 1);
-
- // But the fact that the features were seen is still known.
- EXPECT_TRUE(use_counter.HasRecordedMeasurement(WebFeature::kFetch));
- EXPECT_TRUE(use_counter.IsCounted(CSSPropertyFontWeight));
-
- // Inspector muting then unmuting doesn't change the behavior.
- use_counter.MuteForInspector();
- use_counter.UnmuteForInspector();
- use_counter.RecordMeasurement(WebFeature::kFetch, *GetFrame());
- use_counter.Count(kHTMLStandardMode, CSSPropertyFontWeight, GetFrame());
- ExpectHistograms(histogram_tester_, 0, WebFeature::kFetch, 1,
- CSSPropertyFontWeight, 1);
-
- // If we now load a real web page, metrics are reported again.
- SetURL(URLTestHelpers::ToKURL("http://foo.com/"));
- use_counter.DidCommitLoad(GetFrame());
- use_counter.RecordMeasurement(WebFeature::kFetch, *GetFrame());
- use_counter.Count(kHTMLStandardMode, CSSPropertyFontWeight, GetFrame());
- ExpectHistograms(histogram_tester_, 1, WebFeature::kFetch, 2,
- CSSPropertyFontWeight, 2);
-
- // HTTPs URLs are the same.
- SetURL(URLTestHelpers::ToKURL(kHttpsUrl));
- use_counter.DidCommitLoad(GetFrame());
- use_counter.RecordMeasurement(WebFeature::kFetch, *GetFrame());
- use_counter.Count(kHTMLStandardMode, CSSPropertyFontWeight, GetFrame());
- ExpectHistograms(histogram_tester_, 2, WebFeature::kFetch, 3,
- CSSPropertyFontWeight, 3);
-
- // Extensions aren't counted.
- SetURL(URLTestHelpers::ToKURL(kExtensionUrl));
- use_counter.DidCommitLoad(GetFrame());
- use_counter.RecordMeasurement(WebFeature::kFetch, *GetFrame());
- use_counter.Count(kHTMLStandardMode, CSSPropertyFontWeight, GetFrame());
- ExpectHistograms(histogram_tester_, 2, WebFeature::kFetch, 3,
- CSSPropertyFontWeight, 3);
-
- // Nor is devtools
- SetURL(URLTestHelpers::ToKURL("chrome-devtools://1238ba908adf/"));
- use_counter.DidCommitLoad(GetFrame());
- use_counter.RecordMeasurement(WebFeature::kFetch, *GetFrame());
- use_counter.Count(kHTMLStandardMode, CSSPropertyFontWeight, GetFrame());
- ExpectHistograms(histogram_tester_, 2, WebFeature::kFetch, 3,
- CSSPropertyFontWeight, 3);
-
- // Nor are data URLs
- SetURL(URLTestHelpers::ToKURL("data:text/plain,thisisaurl"));
- use_counter.DidCommitLoad(GetFrame());
- use_counter.RecordMeasurement(WebFeature::kFetch, *GetFrame());
- use_counter.Count(kHTMLStandardMode, CSSPropertyFontWeight, GetFrame());
- ExpectHistograms(histogram_tester_, 2, WebFeature::kFetch, 3,
- CSSPropertyFontWeight, 3);
-
- // Nor are empty URLs (a main frame with no Document)
- SetURL(NullURL());
- use_counter.DidCommitLoad(GetFrame());
- use_counter.RecordMeasurement(WebFeature::kFetch, *GetFrame());
- use_counter.Count(kHTMLStandardMode, CSSPropertyFontWeight, GetFrame());
- ExpectHistograms(histogram_tester_, 2, WebFeature::kFetch, 3,
- CSSPropertyFontWeight, 3);
-
- // Or file URLs
- SetURL(URLTestHelpers::ToKURL("file:///c/autoexec.bat"));
- use_counter.DidCommitLoad(GetFrame());
- use_counter.RecordMeasurement(WebFeature::kFetch, *GetFrame());
- use_counter.Count(kHTMLStandardMode, CSSPropertyFontWeight, GetFrame());
- ExpectHistograms(histogram_tester_, 2, WebFeature::kFetch, 3,
- CSSPropertyFontWeight, 3);
-}
-
TEST_F(UseCounterTest, CSSContainLayoutNonPositionedDescendants) {
std::unique_ptr<DummyPageHolder> dummy_page_holder =
DummyPageHolder::Create(IntSize(800, 600));
+ Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
Document& document = dummy_page_holder->GetDocument();
WebFeature feature = WebFeature::kCSSContainLayoutPositionedDescendants;
EXPECT_FALSE(UseCounter::IsCounted(document, feature));
@@ -510,6 +234,7 @@ TEST_F(UseCounterTest, CSSContainLayoutNonPositionedDescendants) {
TEST_F(UseCounterTest, CSSContainLayoutAbsolutelyPositionedDescendants) {
std::unique_ptr<DummyPageHolder> dummy_page_holder =
DummyPageHolder::Create(IntSize(800, 600));
+ Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
Document& document = dummy_page_holder->GetDocument();
WebFeature feature = WebFeature::kCSSContainLayoutPositionedDescendants;
EXPECT_FALSE(UseCounter::IsCounted(document, feature));
@@ -525,6 +250,7 @@ TEST_F(UseCounterTest,
CSSContainLayoutAbsolutelyPositionedDescendantsAlreadyContainingBlock) {
std::unique_ptr<DummyPageHolder> dummy_page_holder =
DummyPageHolder::Create(IntSize(800, 600));
+ Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
Document& document = dummy_page_holder->GetDocument();
WebFeature feature = WebFeature::kCSSContainLayoutPositionedDescendants;
EXPECT_FALSE(UseCounter::IsCounted(document, feature));
@@ -539,6 +265,7 @@ TEST_F(UseCounterTest,
TEST_F(UseCounterTest, CSSContainLayoutFixedPositionedDescendants) {
std::unique_ptr<DummyPageHolder> dummy_page_holder =
DummyPageHolder::Create(IntSize(800, 600));
+ Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
Document& document = dummy_page_holder->GetDocument();
WebFeature feature = WebFeature::kCSSContainLayoutPositionedDescendants;
EXPECT_FALSE(UseCounter::IsCounted(document, feature));
@@ -554,6 +281,7 @@ TEST_F(UseCounterTest,
CSSContainLayoutFixedPositionedDescendantsAlreadyContainingBlock) {
std::unique_ptr<DummyPageHolder> dummy_page_holder =
DummyPageHolder::Create(IntSize(800, 600));
+ Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
Document& document = dummy_page_holder->GetDocument();
WebFeature feature = WebFeature::kCSSContainLayoutPositionedDescendants;
EXPECT_FALSE(UseCounter::IsCounted(document, feature));
@@ -565,12 +293,42 @@ TEST_F(UseCounterTest,
EXPECT_FALSE(UseCounter::IsCounted(document, feature));
}
+TEST_F(UseCounterTest, CSSGridLayoutPercentageColumnIndefiniteWidth) {
+ std::unique_ptr<DummyPageHolder> dummy_page_holder =
+ DummyPageHolder::Create(IntSize(800, 600));
+ Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
+ Document& document = dummy_page_holder->GetDocument();
+ WebFeature feature = WebFeature::kGridRowTrackPercentIndefiniteHeight;
+ EXPECT_FALSE(UseCounter::IsCounted(document, feature));
+ document.documentElement()->SetInnerHTMLFromString(
+ "<div style='display: inline-grid; grid-template-columns: 50%;'>"
+ "</div>");
+ document.View()->UpdateAllLifecyclePhases();
+ EXPECT_FALSE(UseCounter::IsCounted(document, feature));
+}
+
+TEST_F(UseCounterTest, CSSGridLayoutPercentageRowIndefiniteHeight) {
+ std::unique_ptr<DummyPageHolder> dummy_page_holder =
+ DummyPageHolder::Create(IntSize(800, 600));
+ Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
+ Document& document = dummy_page_holder->GetDocument();
+ WebFeature feature = WebFeature::kGridRowTrackPercentIndefiniteHeight;
+ EXPECT_FALSE(UseCounter::IsCounted(document, feature));
+ document.documentElement()->SetInnerHTMLFromString(
+ "<div style='display: inline-grid; grid-template-rows: 50%;'>"
+ "</div>");
+ document.View()->UpdateAllLifecyclePhases();
+ EXPECT_TRUE(UseCounter::IsCounted(document, feature));
+}
+
class DeprecationTest : public testing::Test {
public:
DeprecationTest()
: dummy_(DummyPageHolder::Create()),
deprecation_(dummy_->GetPage().GetDeprecation()),
- use_counter_(dummy_->GetPage().GetUseCounter()) {}
+ use_counter_(dummy_->GetDocument().Loader()->GetUseCounter()) {
+ Page::InsertOrdinaryPageForTesting(&dummy_->GetPage());
+ }
protected:
LocalFrame* GetFrame() { return &dummy_->GetFrame(); }
diff --git a/chromium/third_party/blink/renderer/core/frame/user_activation.cc b/chromium/third_party/blink/renderer/core/frame/user_activation.cc
new file mode 100644
index 00000000000..0f07a645ebc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/user_activation.cc
@@ -0,0 +1,34 @@
+// 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/frame/user_activation.h"
+
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+
+namespace blink {
+
+UserActivation::UserActivation(LocalDOMWindow* window) : window_(window) {}
+
+UserActivation::~UserActivation() = default;
+
+void UserActivation::Trace(blink::Visitor* visitor) {
+ visitor->Trace(window_);
+ ScriptWrappable::Trace(visitor);
+}
+
+bool UserActivation::hasBeenActive() const {
+ LocalFrame* frame = window_ ? window_->GetFrame() : nullptr;
+ if (!frame)
+ return false;
+ return frame->HasBeenActivated();
+}
+
+bool UserActivation::isActive() const {
+ LocalFrame* frame = window_ ? window_->GetFrame() : nullptr;
+ if (!frame)
+ return false;
+ return Frame::HasTransientUserActivation(frame);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/user_activation.h b/chromium/third_party/blink/renderer/core/frame/user_activation.h
new file mode 100644
index 00000000000..9658ea291f2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/user_activation.h
@@ -0,0 +1,33 @@
+// 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_FRAME_USER_ACTIVATION_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_USER_ACTIVATION_H_
+
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+
+namespace blink {
+
+class LocalDOMWindow;
+
+class UserActivation final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ explicit UserActivation(LocalDOMWindow* window);
+
+ ~UserActivation() override;
+
+ void Trace(blink::Visitor*) override;
+
+ bool hasBeenActive() const;
+ bool isActive() const;
+
+ private:
+ Member<LocalDOMWindow> window_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_USER_ACTIVATION_H_
diff --git a/chromium/third_party/blink/renderer/core/frame/user_activation.idl b/chromium/third_party/blink/renderer/core/frame/user_activation.idl
new file mode 100644
index 00000000000..24b22ec20ed
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/user_activation.idl
@@ -0,0 +1,10 @@
+// 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.
+
+// https://github.com/dtapuska/useractivation
+[RuntimeEnabled=UserActivationAPI]
+interface UserActivation {
+ readonly attribute boolean hasBeenActive;
+ readonly attribute boolean isActive;
+};
diff --git a/chromium/third_party/blink/renderer/core/frame/user_activation_state.cc b/chromium/third_party/blink/renderer/core/frame/user_activation_state.cc
deleted file mode 100644
index 16290e27983..00000000000
--- a/chromium/third_party/blink/renderer/core/frame/user_activation_state.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/frame/user_activation_state.h"
-
-#include "third_party/blink/renderer/platform/wtf/time.h"
-
-namespace blink {
-
-// This is a tentative timespan, which should be more than the current limit of
-// 1 sec (in UGI) because we want a reasonable value that works even for a slow
-// network. Currently we are experimenting with a vary large value (eqvt to no
-// expiry): crbug.com/776404.
-constexpr TimeDelta kActivationLifespan = TimeDelta::FromSeconds(3600);
-
-void UserActivationState::Activate() {
- has_been_active_ = true;
- is_active_ = true;
- activation_timestamp_ = CurrentTimeTicks();
-}
-
-void UserActivationState::Clear() {
- has_been_active_ = false;
- is_active_ = false;
-}
-
-bool UserActivationState::IsActive() {
- if (is_active_ &&
- (CurrentTimeTicks() - activation_timestamp_ > kActivationLifespan)) {
- is_active_ = false;
- }
- return is_active_;
-}
-
-bool UserActivationState::ConsumeIfActive() {
- if (!IsActive())
- return false;
- is_active_ = false;
- return true;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/user_activation_state.h b/chromium/third_party/blink/renderer/core/frame/user_activation_state.h
deleted file mode 100644
index a7fd965d847..00000000000
--- a/chromium/third_party/blink/renderer/core/frame/user_activation_state.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_USER_ACTIVATION_STATE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_USER_ACTIVATION_STATE_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/wtf/time.h"
-
-namespace blink {
-
-// This class represents the user activation state of a frame. It maintains two
-// bits of information: whether this frame has ever seen an activation in its
-// lifetime, and whether this frame has a current activation that was neither
-// expired nor consumed. The "owner" frame propagates both bits to ancestor
-// frames.
-//
-// This provides a simple alternative to current user gesture tracking code
-// based on UserGestureIndicator and UserGestureToken.
-class CORE_EXPORT UserActivationState {
- public:
- void Activate();
- void Clear();
-
- // Returns the sticky activation state, which is |true| if
- // |UserActivationState| has ever seen an activation.
- bool HasBeenActive() const { return has_been_active_; }
-
- // Returns the transient activation state, which is |true| if
- // |UserActivationState| has recently been activated and the transient state
- // hasn't been consumed yet.
- bool IsActive();
-
- // Consumes the transient activation state if available, and returns |true| if
- // successfully consumed.
- bool ConsumeIfActive();
-
- private:
- bool has_been_active_ = false;
- bool is_active_ = false;
- TimeTicks activation_timestamp_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_USER_ACTIVATION_STATE_H_
diff --git a/chromium/third_party/blink/renderer/core/frame/viewport_data.cc b/chromium/third_party/blink/renderer/core/frame/viewport_data.cc
new file mode 100644
index 00000000000..edec6c1fd77
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/viewport_data.cc
@@ -0,0 +1,120 @@
+// 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/frame/viewport_data.h"
+
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.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_client.h"
+#include "third_party/blink/renderer/core/frame/settings.h"
+#include "third_party/blink/renderer/core/page/chrome_client.h"
+#include "third_party/blink/renderer/core/page/page.h"
+
+namespace blink {
+
+ViewportData::ViewportData(Document& document) : document_(document) {}
+
+void ViewportData::Trace(Visitor* visitor) {
+ visitor->Trace(document_);
+}
+
+void ViewportData::Shutdown() {
+ // TODO(https://crbug.com/800641): Use InterfaceInvalidator once it works with
+ // associated interfaces.
+ display_cutout_host_.reset();
+}
+
+bool ViewportData::ShouldMergeWithLegacyDescription(
+ ViewportDescription::Type origin) const {
+ return document_->GetSettings() &&
+ document_->GetSettings()->GetViewportMetaMergeContentQuirk() &&
+ legacy_viewport_description_.IsMetaViewportType() &&
+ legacy_viewport_description_.type == origin;
+}
+
+void ViewportData::SetViewportDescription(
+ const ViewportDescription& viewport_description) {
+ if (viewport_description.IsLegacyViewportType()) {
+ if (viewport_description == legacy_viewport_description_)
+ return;
+ legacy_viewport_description_ = viewport_description;
+ } else {
+ if (viewport_description == viewport_description_)
+ return;
+ viewport_description_ = viewport_description;
+
+ // The UA-defined min-width is considered specifically by Android WebView
+ // quirks mode.
+ if (!viewport_description.IsSpecifiedByAuthor())
+ viewport_default_min_width_ = viewport_description.min_width;
+ }
+
+ UpdateViewportDescription();
+}
+
+ViewportDescription ViewportData::GetViewportDescription() const {
+ ViewportDescription applied_viewport_description = viewport_description_;
+ bool viewport_meta_enabled =
+ document_->GetSettings() &&
+ document_->GetSettings()->GetViewportMetaEnabled();
+ if (legacy_viewport_description_.type !=
+ ViewportDescription::kUserAgentStyleSheet &&
+ viewport_meta_enabled)
+ applied_viewport_description = legacy_viewport_description_;
+ if (ShouldOverrideLegacyDescription(viewport_description_.type))
+ applied_viewport_description = viewport_description_;
+
+ return applied_viewport_description;
+}
+
+void ViewportData::UpdateViewportDescription() {
+ if (!document_->GetFrame())
+ return;
+
+ // If the viewport_fit has changed we should send this to the browser. We
+ // use the legacy viewport description which contains the viewport_fit
+ // defined from the layout meta tag.
+ mojom::ViewportFit current_viewport_fit =
+ GetViewportDescription().GetViewportFit();
+
+ // If we are forcing to expand into the display cutout then we should override
+ // the viewport fit value.
+ if (force_expand_display_cutout_)
+ current_viewport_fit = mojom::ViewportFit::kCoverForcedByUserAgent;
+
+ if (viewport_fit_ != current_viewport_fit) {
+ if (AssociatedInterfaceProvider* provider =
+ document_->GetFrame()
+ ->Client()
+ ->GetRemoteNavigationAssociatedInterfaces()) {
+ // Bind the mojo interface.
+ if (!display_cutout_host_.is_bound()) {
+ provider->GetInterface(&display_cutout_host_);
+ DCHECK(display_cutout_host_.is_bound());
+ }
+
+ // Even though we bind the mojo interface above there still may be cases
+ // where this will fail (e.g. unit tests).
+ display_cutout_host_->NotifyViewportFitChanged(current_viewport_fit);
+ }
+
+ viewport_fit_ = current_viewport_fit;
+ }
+
+ if (document_->GetFrame()->IsMainFrame()) {
+ document_->GetPage()->GetChromeClient().DispatchViewportPropertiesDidChange(
+ GetViewportDescription());
+ }
+}
+
+void ViewportData::SetExpandIntoDisplayCutout(bool expand) {
+ if (force_expand_display_cutout_ == expand)
+ return;
+
+ force_expand_display_cutout_ = expand;
+ UpdateViewportDescription();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/viewport_data.h b/chromium/third_party/blink/renderer/core/frame/viewport_data.h
new file mode 100644
index 00000000000..e3f539089ea
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/viewport_data.h
@@ -0,0 +1,61 @@
+// 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_FRAME_VIEWPORT_DATA_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_VIEWPORT_DATA_H_
+
+#include "third_party/blink/public/mojom/page/display_cutout.mojom-blink.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/page/viewport_description.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+class Document;
+
+class ViewportData : public GarbageCollectedFinalized<ViewportData> {
+ public:
+ ViewportData(Document& document);
+ void Trace(Visitor* visitor);
+ void Shutdown();
+
+ bool ShouldMergeWithLegacyDescription(ViewportDescription::Type) const;
+ bool ShouldOverrideLegacyDescription(ViewportDescription::Type) const;
+ CORE_EXPORT void SetViewportDescription(const ViewportDescription&);
+ CORE_EXPORT ViewportDescription GetViewportDescription() const;
+ Length ViewportDefaultMinWidth() const { return viewport_default_min_width_; }
+
+ void UpdateViewportDescription();
+
+ // When true this will force a kCover viewport fit value which will result in
+ // the document expanding into the display cutout area.
+ CORE_EXPORT void SetExpandIntoDisplayCutout(bool expand);
+ mojom::ViewportFit GetCurrentViewportFitForTests() const {
+ return viewport_fit_;
+ }
+
+ private:
+ Member<Document> document_;
+
+ ViewportDescription viewport_description_;
+ ViewportDescription legacy_viewport_description_;
+ Length viewport_default_min_width_;
+
+ // Stores the current value viewport-fit value.
+ mojom::ViewportFit viewport_fit_ = blink::mojom::ViewportFit::kAuto;
+ bool force_expand_display_cutout_ = false;
+
+ mojom::blink::DisplayCutoutHostAssociatedPtr display_cutout_host_;
+};
+
+inline bool ViewportData::ShouldOverrideLegacyDescription(
+ ViewportDescription::Type origin) const {
+ // The different (legacy) meta tags have different priorities based on the
+ // type regardless of which order they appear in the DOM. The priority is
+ // given by the ViewportDescription::Type enum.
+ return origin >= legacy_viewport_description_.type;
+}
+
+} // namespace blink
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_VIEWPORT_DATA_H_
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 b159fa9f5f9..512a32095b1 100644
--- a/chromium/third_party/blink/renderer/core/frame/visual_viewport.cc
+++ b/chromium/third_party/blink/renderer/core/frame/visual_viewport.cc
@@ -32,7 +32,7 @@
#include <memory>
-#include "cc/layers/layer.h"
+#include "cc/layers/picture_layer.h"
#include "cc/layers/scrollbar_layer_interface.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -44,17 +44,18 @@
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
-#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
#include "third_party/blink/renderer/core/layout/text_autosizer.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/paint/compositing/paint_layer_compositor.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/platform/geometry/double_rect.h"
#include "third_party/blink/renderer/platform/geometry/float_size.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
+#include "third_party/blink/renderer/platform/scroll/scroll_animator_base.h"
#include "third_party/blink/renderer/platform/scroll/scrollbar.h"
#include "third_party/blink/renderer/platform/scroll/scrollbar_theme_overlay.h"
@@ -70,6 +71,100 @@ VisualViewport::VisualViewport(Page& owner)
Reset();
}
+TransformPaintPropertyNode* VisualViewport::GetPageScaleNode() const {
+ return scale_transform_node_.get();
+}
+
+TransformPaintPropertyNode* VisualViewport::GetScrollTranslationNode() const {
+ return translation_transform_node_.get();
+}
+
+ScrollPaintPropertyNode* VisualViewport::GetScrollNode() const {
+ return scroll_node_.get();
+}
+
+void VisualViewport::UpdatePaintPropertyNodes(
+ scoped_refptr<const TransformPaintPropertyNode> transform_parent,
+ scoped_refptr<const ScrollPaintPropertyNode> scroll_parent) {
+ DCHECK(transform_parent);
+ DCHECK(scroll_parent);
+
+ if (inner_viewport_container_layer_) {
+ inner_viewport_container_layer_->SetLayerState(
+ PropertyTreeState(&TransformPaintPropertyNode::Root(),
+ &ClipPaintPropertyNode::Root(),
+ &EffectPaintPropertyNode::Root()),
+ IntPoint());
+ }
+
+ {
+ TransformationMatrix scale_transform;
+ scale_transform.Scale(Scale());
+ TransformPaintPropertyNode::State state{scale_transform, FloatPoint3D()};
+ state.compositor_element_id = GetCompositorElementId();
+
+ if (!scale_transform_node_) {
+ scale_transform_node_ = TransformPaintPropertyNode::Create(
+ *transform_parent, std::move(state));
+ } else {
+ scale_transform_node_->Update(*transform_parent, std::move(state));
+ }
+ }
+
+ if (page_scale_layer_) {
+ page_scale_layer_->SetLayerState(
+ PropertyTreeState(scale_transform_node_.get(),
+ &ClipPaintPropertyNode::Root(),
+ &EffectPaintPropertyNode::Root()),
+ IntPoint());
+ }
+
+ {
+ ScrollPaintPropertyNode::State state;
+ state.container_rect = IntRect(IntPoint(), ExcludeScrollbars(size_));
+ state.contents_rect = IntRect(IntPoint(), ContentsSize());
+
+ state.user_scrollable_horizontal =
+ UserInputScrollable(kHorizontalScrollbar);
+ state.user_scrollable_vertical = UserInputScrollable(kVerticalScrollbar);
+ state.scrolls_inner_viewport = true;
+ state.max_scroll_offset_affected_by_page_scale = true;
+ state.compositor_element_id = GetCompositorScrollElementId();
+
+ if (!scroll_node_) {
+ scroll_node_ =
+ ScrollPaintPropertyNode::Create(*scroll_parent, std::move(state));
+ } else {
+ scroll_node_->Update(*scroll_parent, std::move(state));
+ }
+ }
+
+ {
+ TransformationMatrix translate_transform;
+ ScrollOffset scroll_position = GetScrollOffset();
+ translate_transform.Translate(-scroll_position.Width(),
+ -scroll_position.Height());
+ TransformPaintPropertyNode::State state{translate_transform,
+ FloatPoint3D()};
+ state.scroll = scroll_node_;
+ if (!translation_transform_node_) {
+ translation_transform_node_ = TransformPaintPropertyNode::Create(
+ *scale_transform_node_, std::move(state));
+ } else {
+ translation_transform_node_->Update(*scale_transform_node_,
+ std::move(state));
+ }
+ }
+
+ if (inner_viewport_scroll_layer_) {
+ inner_viewport_scroll_layer_->SetLayerState(
+ PropertyTreeState(translation_transform_node_.get(),
+ &ClipPaintPropertyNode::Root(),
+ &EffectPaintPropertyNode::Root()),
+ IntPoint());
+ }
+}
+
VisualViewport::~VisualViewport() {
SendUMAMetrics();
}
@@ -153,24 +248,27 @@ void VisualViewport::MainFrameDidChangeSize() {
ClampToBoundaries();
}
-FloatSize VisualViewport::VisibleSize() const {
- FloatSize scaled_size(size_);
- scaled_size.Expand(0, browser_controls_adjustment_);
- scaled_size.Scale(1 / scale_);
- return scaled_size;
-}
+FloatRect VisualViewport::VisibleRect(
+ IncludeScrollbarsInRect scrollbar_inclusion) const {
+ FloatSize visible_size(size_);
-FloatRect VisualViewport::VisibleRect() const {
- return FloatRect(FloatPoint(GetScrollOffset()), VisibleSize());
+ if (scrollbar_inclusion == kExcludeScrollbars)
+ visible_size = FloatSize(ExcludeScrollbars(size_));
+
+ visible_size.Expand(0, browser_controls_adjustment_);
+ visible_size.Scale(1 / scale_);
+
+ return FloatRect(FloatPoint(GetScrollOffset()), visible_size);
}
-FloatRect VisualViewport::VisibleRectInDocument() const {
+FloatRect VisualViewport::VisibleRectInDocument(
+ IncludeScrollbarsInRect scrollbar_inclusion) const {
if (!MainFrame() || !MainFrame()->View())
return FloatRect();
FloatPoint view_location =
FloatPoint(MainFrame()->View()->GetScrollableArea()->GetScrollOffset());
- return FloatRect(view_location, VisibleSize());
+ return FloatRect(view_location, VisibleRect(scrollbar_inclusion).Size());
}
FloatPoint VisualViewport::ViewportCSSPixelsToRootFrame(
@@ -199,8 +297,7 @@ double VisualViewport::OffsetLeft() const {
UpdateStyleAndLayoutIgnorePendingStylesheets();
- return AdjustForAbsoluteZoom::AdjustScroll(VisibleRect().X(),
- MainFrame()->PageZoomFactor());
+ return VisibleRect().X() / MainFrame()->PageZoomFactor();
}
double VisualViewport::OffsetTop() const {
@@ -209,8 +306,7 @@ double VisualViewport::OffsetTop() const {
UpdateStyleAndLayoutIgnorePendingStylesheets();
- return AdjustForAbsoluteZoom::AdjustScroll(VisibleRect().Y(),
- MainFrame()->PageZoomFactor());
+ return VisibleRect().Y() / MainFrame()->PageZoomFactor();
}
double VisualViewport::Width() const {
@@ -229,8 +325,13 @@ double VisualViewport::ScaleForVisualViewport() const {
void VisualViewport::SetScaleAndLocation(float scale,
const FloatPoint& location) {
- if (DidSetScaleOrLocation(scale, location))
+ if (DidSetScaleOrLocation(scale, location)) {
NotifyRootFrameViewport();
+ Document* document = MainFrame()->GetDocument();
+ if (AXObjectCache* cache = document->ExistingAXObjectCache()) {
+ cache->HandleScaleAndLocationChanged(document);
+ }
+ }
}
double VisualViewport::VisibleWidthCSSPx() const {
@@ -238,12 +339,8 @@ double VisualViewport::VisibleWidthCSSPx() const {
return 0;
float zoom = MainFrame()->PageZoomFactor();
- float width_css_px =
- AdjustForAbsoluteZoom::AdjustScroll(VisibleSize().Width(), zoom);
- auto* scrollable_area = MainFrame()->View()->LayoutViewportScrollableArea();
- float scrollbar_thickness_css_px =
- scrollable_area->VerticalScrollbarWidth() / (zoom * scale_);
- return width_css_px - scrollbar_thickness_css_px;
+ float width_css_px = VisibleRect().Width() / zoom;
+ return width_css_px;
}
double VisualViewport::VisibleHeightCSSPx() const {
@@ -251,12 +348,8 @@ double VisualViewport::VisibleHeightCSSPx() const {
return 0;
float zoom = MainFrame()->PageZoomFactor();
- float height_css_px =
- AdjustForAbsoluteZoom::AdjustScroll(VisibleSize().Height(), zoom);
- auto* scrollable_area = MainFrame()->View()->LayoutViewportScrollableArea();
- float scrollbar_thickness_css_px =
- scrollable_area->HorizontalScrollbarHeight() / (zoom * scale_);
- return height_css_px - scrollbar_thickness_css_px;
+ float height_css_px = VisibleRect().Height() / zoom;
+ return height_css_px;
}
bool VisualViewport::DidSetScaleOrLocation(float scale,
@@ -381,8 +474,8 @@ void VisualViewport::CreateLayerTree() {
static_cast<gfx::Size>(size_));
DCHECK(MainFrame());
DCHECK(MainFrame()->GetDocument());
- inner_viewport_scroll_layer_->SetElementId(
- CompositorElementIdFromUniqueObjectId(unique_id_));
+ inner_viewport_scroll_layer_->SetElementId(GetCompositorScrollElementId());
+ page_scale_layer_->SetElementId(GetCompositorElementId());
root_transform_layer_->AddChild(inner_viewport_container_layer_.get());
inner_viewport_container_layer_->AddChild(overscroll_elasticity_layer_.get());
@@ -479,8 +572,10 @@ void VisualViewport::SetupScrollbar(ScrollbarOrientation orientation) {
if (!scrollbar_layer_group) {
ScrollingCoordinator* coordinator = GetPage().GetScrollingCoordinator();
DCHECK(coordinator);
+
scrollbar_layer_group = coordinator->CreateSolidColorScrollbarLayer(
- orientation, thumb_thickness, scrollbar_margin, false);
+ orientation, thumb_thickness, scrollbar_margin, false,
+ GetScrollbarElementId(orientation));
// The compositor will control the scrollbar's visibility. Set to invisible
// by default so scrollbars don't show up in layout tests.
@@ -510,7 +605,7 @@ void VisualViewport::SetupScrollbar(ScrollbarOrientation orientation) {
scrollbar_thickness;
// Use the GraphicsLayer to position the scrollbars.
- scrollbar_graphics_layer->SetPosition(IntPoint(x_position, y_position));
+ scrollbar_graphics_layer->SetPosition(FloatPoint(x_position, y_position));
scrollbar_graphics_layer->SetSize(IntSize(width, height));
scrollbar_graphics_layer->SetContentsRect(IntRect(0, 0, width, height));
}
@@ -520,8 +615,13 @@ bool VisualViewport::VisualViewportSuppliesScrollbars() const {
}
CompositorElementId VisualViewport::GetCompositorElementId() const {
- // TODO(chrishtr): Implement http://crbug.com/638473.
- return CompositorElementId();
+ return CompositorElementIdFromUniqueObjectId(
+ unique_id_, CompositorElementIdNamespace::kPrimary);
+}
+
+CompositorElementId VisualViewport::GetCompositorScrollElementId() const {
+ return CompositorElementIdFromUniqueObjectId(
+ unique_id_, CompositorElementIdNamespace::kScroll);
}
bool VisualViewport::ScrollAnimatorEnabled() const {
@@ -604,15 +704,15 @@ IntPoint VisualViewport::ClampDocumentOffsetAtScale(const IntPoint& offset,
LocalFrameView* view = MainFrame()->View();
- FloatSize scaled_size(size_);
+ FloatSize scaled_size(ExcludeScrollbars(size_));
scaled_size.Scale(1 / scale);
IntSize visual_viewport_max =
FlooredIntSize(FloatSize(ContentsSize()) - scaled_size);
- IntSize max = view->LayoutViewportScrollableArea()->MaximumScrollOffsetInt() +
- visual_viewport_max;
+ IntSize max =
+ view->LayoutViewport()->MaximumScrollOffsetInt() + visual_viewport_max;
IntSize min =
- view->LayoutViewportScrollableArea()
+ view->LayoutViewport()
->MinimumScrollOffsetInt(); // VisualViewportMin should be (0, 0)
IntSize clamped = ToIntSize(offset);
@@ -661,28 +761,15 @@ bool VisualViewport::UserInputScrollable(ScrollbarOrientation) const {
IntSize VisualViewport::ContentsSize() const {
LocalFrame* frame = MainFrame();
-
if (!frame || !frame->View())
return IntSize();
- // TODO(bokan): This should be the layout viewport rather than main
- // LocalFrameView.
- return frame->View()->VisibleContentRect(kIncludeScrollbars).Size();
+ return frame->View()->Size();
}
IntRect VisualViewport::VisibleContentRect(
IncludeScrollbarsInRect scrollbar_inclusion) const {
- // TODO(ymalik): We're losing precision here and below. visibleRect should
- // be replaced with visibleContentRect.
- IntRect rect = EnclosingIntRect(VisibleRect());
- if (scrollbar_inclusion == kExcludeScrollbars) {
- RootFrameViewport* root_frame_viewport =
- MainFrame()->View()->GetRootFrameViewport();
- DCHECK(root_frame_viewport);
- rect.Contract(root_frame_viewport->VerticalScrollbarWidth() / scale_,
- root_frame_viewport->HorizontalScrollbarHeight() / scale_);
- }
- return rect;
+ return EnclosingIntRect(VisibleRect(scrollbar_inclusion));
}
scoped_refptr<base::SingleThreadTaskRunner> VisualViewport::GetTimerTaskRunner()
@@ -727,12 +814,28 @@ void VisualViewport::PaintContents(const GraphicsLayer*,
GraphicsLayerPaintingPhase,
const IntRect&) const {}
+RootFrameViewport* VisualViewport::GetRootFrameViewport() const {
+ if (!MainFrame() || !MainFrame()->View())
+ return nullptr;
+
+ return MainFrame()->View()->GetRootFrameViewport();
+}
+
LocalFrame* VisualViewport::MainFrame() const {
return GetPage().MainFrame() && GetPage().MainFrame()->IsLocalFrame()
? GetPage().DeprecatedLocalMainFrame()
: nullptr;
}
+IntSize VisualViewport::ExcludeScrollbars(const IntSize& size) const {
+ IntSize excluded_size = size;
+ if (RootFrameViewport* root_frame_viewport = GetRootFrameViewport()) {
+ excluded_size.Expand(-root_frame_viewport->VerticalScrollbarWidth(),
+ -root_frame_viewport->HorizontalScrollbarHeight());
+ }
+ return excluded_size;
+}
+
bool VisualViewport::ScheduleAnimation() {
GetPage().GetChromeClient().ScheduleAnimation(MainFrame()->View());
return true;
@@ -879,22 +982,20 @@ CompositorAnimationTimeline* VisualViewport::GetCompositorAnimationTimeline()
}
void VisualViewport::NotifyRootFrameViewport() const {
- if (!MainFrame() || !MainFrame()->View())
- return;
-
- RootFrameViewport* root_frame_viewport =
- MainFrame()->View()->GetRootFrameViewport();
-
- if (!root_frame_viewport)
+ if (!GetRootFrameViewport())
return;
- root_frame_viewport->DidUpdateVisualViewport();
+ GetRootFrameViewport()->DidUpdateVisualViewport();
}
ScrollbarTheme& VisualViewport::GetPageScrollbarTheme() const {
return GetPage().GetScrollbarTheme();
}
+void VisualViewport::SetOverlayScrollbarsHidden(bool hidden) {
+ ScrollableArea::SetScrollbarsHiddenIfOverlay(hidden);
+}
+
String VisualViewport::DebugName(const GraphicsLayer* graphics_layer) const {
String name;
if (graphics_layer == inner_viewport_container_layer_.get()) {
@@ -918,4 +1019,11 @@ String VisualViewport::DebugName(const GraphicsLayer* graphics_layer) const {
return name;
}
+const ScrollableArea* VisualViewport::GetScrollableAreaForTesting(
+ const GraphicsLayer* layer) const {
+ if (layer == inner_viewport_scroll_layer_.get())
+ return this;
+ return nullptr;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/frame/visual_viewport.h b/chromium/third_party/blink/renderer/core/frame/visual_viewport.h
index 01e6b9d60c6..6f10824b473 100644
--- a/chromium/third_party/blink/renderer/core/frame/visual_viewport.h
+++ b/chromium/third_party/blink/renderer/core/frame/visual_viewport.h
@@ -54,6 +54,8 @@ class IntRect;
class IntSize;
class LocalFrame;
class Page;
+class ScrollPaintPropertyNode;
+class TransformPaintPropertyNode;
// Represents the visual viewport the user is currently seeing the page through.
// This class corresponds to the InnerViewport on the compositor. It is a
@@ -113,12 +115,21 @@ class CORE_EXPORT VisualViewport final
// FIXME: This should be called moveBy
void Move(const ScrollOffset&);
- // Sets the size of the inner viewport when unscaled in CSS pixels.
+ // The size of the Blink viewport area. See size_ for precise
+ // definition.
void SetSize(const IntSize&);
IntSize Size() const { return size_; }
- // Gets the scaled size, i.e. the viewport in root view space.
- FloatSize VisibleSize() const;
+ // The area of the layout viewport rect visible in the visual viewport,
+ // relative to the layout viewport's top-left corner. i.e. As the page scale
+ // is increased, this rect shrinks. Does not account for browser-zoom (ctrl
+ // +/- zooming).
+ FloatRect VisibleRect(IncludeScrollbarsInRect = kExcludeScrollbars) const;
+
+ // Similar to VisibleRect but this returns the rect relative to the main
+ // document's top-left corner.
+ FloatRect VisibleRectInDocument(
+ IncludeScrollbarsInRect = kExcludeScrollbars) const;
// Resets the viewport to initial state.
void Reset();
@@ -137,13 +148,6 @@ class CORE_EXPORT VisualViewport final
// if page scale factor is left unchanged.
bool MagnifyScaleAroundAnchor(float magnify_delta, const FloatPoint& anchor);
- // The portion of the unzoomed frame visible in the visual viewport,
- // in partial CSS pixels. Relative to the main frame.
- FloatRect VisibleRect() const;
-
- // The viewport rect relative to the document origin, in partial CSS pixels.
- FloatRect VisibleRectInDocument() const;
-
// Convert the given rect in the main LocalFrameView's coordinates into a rect
// in the viewport. The given and returned rects are in CSS pixels, meaning
// scale isn't applied.
@@ -183,6 +187,11 @@ class CORE_EXPORT VisualViewport final
void SetScrollOffset(const ScrollOffset&,
ScrollType,
ScrollBehavior = kScrollBehaviorInstant) override;
+ bool IsThrottled() const override {
+ // VisualViewport is always in the main frame, so the frame does not get
+ // throttled.
+ return false;
+ }
bool IsActive() const override { return false; }
int ScrollSize(ScrollbarOrientation) const override;
bool IsScrollCornerVisible() const override { return false; }
@@ -192,8 +201,9 @@ class CORE_EXPORT VisualViewport final
IntSize MinimumScrollOffsetInt() const override;
IntSize MaximumScrollOffsetInt() const override;
ScrollOffset MaximumScrollOffset() const override;
- int VisibleHeight() const override { return VisibleRect().Height(); }
- int VisibleWidth() const override { return VisibleRect().Width(); }
+ // Note: Because scrollbars are conceptually owned by the LayoutView,
+ // ContentsSize includes the main frame's scrollbars. This is necessary for
+ // correct cc Layer sizing.
IntSize ContentsSize() const override;
bool ScrollbarsCanBeActive() const override { return false; }
IntRect ScrollableAreaBoundingBox() const override;
@@ -217,7 +227,7 @@ class CORE_EXPORT VisualViewport final
// VisualViewport scrolling may involve pinch zoom and gets routed through
// WebViewImpl explicitly rather than via ScrollingCoordinator::DidScroll
// since it needs to be set in tandem with the page scale delta.
- void DidScroll(const gfx::ScrollOffset&) final { NOTREACHED(); }
+ void DidScroll(const FloatPoint&) final { NOTREACHED(); }
// Visual Viewport API implementation.
double OffsetLeft() const;
@@ -240,13 +250,25 @@ class CORE_EXPORT VisualViewport final
bool ShouldDisableDesktopWorkarounds() const;
ScrollbarTheme& GetPageScrollbarTheme() const override;
+ bool VisualViewportSuppliesScrollbars() const override;
+
+ TransformPaintPropertyNode* GetPageScaleNode() const;
+ TransformPaintPropertyNode* GetScrollTranslationNode() const;
+ ScrollPaintPropertyNode* GetScrollNode() const;
+
+ // Create/update the page scale translation, viewport scroll, and viewport
+ // translation property nodes. Also set the layer states (inner viewport
+ // container, page scale layer, inner viewport scroll layer) to reference
+ // these nodes.
+ void UpdatePaintPropertyNodes(
+ scoped_refptr<const TransformPaintPropertyNode> transform_parent,
+ scoped_refptr<const ScrollPaintPropertyNode> scroll_parent);
private:
explicit VisualViewport(Page&);
bool DidSetScaleOrLocation(float scale, const FloatPoint& location);
- bool VisualViewportSuppliesScrollbars() const;
void UpdateStyleAndLayoutIgnorePendingStylesheets() const;
@@ -264,12 +286,18 @@ class CORE_EXPORT VisualViewport final
GraphicsContext&,
GraphicsLayerPaintingPhase,
const IntRect&) const override;
+ void SetOverlayScrollbarsHidden(bool) override;
String DebugName(const GraphicsLayer*) const override;
+ const ScrollableArea* GetScrollableAreaForTesting(
+ const GraphicsLayer*) const override;
+
void SetupScrollbar(ScrollbarOrientation);
void NotifyRootFrameViewport() const;
+ RootFrameViewport* GetRootFrameViewport() const;
+
LocalFrame* MainFrame() const;
Page& GetPage() const {
@@ -277,6 +305,12 @@ class CORE_EXPORT VisualViewport final
return *page_;
}
+ CompositorElementId GetCompositorScrollElementId() const;
+
+ // Contracts the given size by the thickness of any visible scrollbars. Does
+ // not contract the size if the scrollbar is overlay.
+ IntSize ExcludeScrollbars(const IntSize&) const;
+
Member<Page> page_;
std::unique_ptr<GraphicsLayer> root_transform_layer_;
std::unique_ptr<GraphicsLayer> inner_viewport_container_layer_;
@@ -294,11 +328,31 @@ class CORE_EXPORT VisualViewport final
std::unique_ptr<GraphicsLayer> overlay_scrollbar_horizontal_;
std::unique_ptr<GraphicsLayer> overlay_scrollbar_vertical_;
+ scoped_refptr<TransformPaintPropertyNode> scale_transform_node_;
+ scoped_refptr<TransformPaintPropertyNode> translation_transform_node_;
+ scoped_refptr<ScrollPaintPropertyNode> scroll_node_;
+
// Offset of the visual viewport from the main frame's origin, in CSS pixels.
ScrollOffset offset_;
float scale_;
+
+ // The Blink viewport size. This is effectively the size of the rect Blink is
+ // rendering into and includes space consumed by scrollbars. While it will
+ // not include the URL bar height, Blink is only informed of changes to the
+ // URL bar once they're fully committed (all the way hidden or shown). While
+ // they're animating or being dragged, size_ will not reflect the changed
+ // visible content area. The transient URL bar-caused change to the visible
+ // content area is tracked in browser_controls_adjustment.
IntSize size_;
+
+ // Blink is only resized as a result of showing/hiding the URL bar once
+ // they're fully committed (all the way hidden or shown). While they're
+ // animating or being dragged, browser_controls_adjustment_ tracks the amount
+ // they expand or shrink the visible content height.
float browser_controls_adjustment_;
+
+ // The maximum page scale the user has zoomed to on the current page. Used
+ // only to report statistics about pinch-zoom usage.
float max_page_scale_;
bool track_pinch_zoom_stats_for_page_;
UniqueObjectId unique_id_;
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 bd86a9cede3..24acefd9154 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
@@ -6,6 +6,7 @@
#include <memory>
+#include "cc/layers/picture_layer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
@@ -16,7 +17,7 @@
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/public/web/web_context_menu_data.h"
#include "third_party/blink/public/web/web_document.h"
-#include "third_party/blink/public/web/web_frame_client.h"
+#include "third_party/blink/public/web/web_local_frame_client.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_view_client.h"
@@ -38,6 +39,9 @@
#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.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/double_point.h"
#include "third_party/blink/renderer/platform/geometry/double_rect.h"
#include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
@@ -228,14 +232,14 @@ TEST_P(VisualViewportTest, TestResizeAtFullyScrolledPreservesViewportLocation) {
visual_viewport.SetScale(2);
// Fully scroll both viewports.
- frame_view.LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(10000, 10000), kProgrammaticScroll);
+ frame_view.LayoutViewport()->SetScrollOffset(ScrollOffset(10000, 10000),
+ kProgrammaticScroll);
visual_viewport.Move(FloatSize(10000, 10000));
// Sanity check.
ASSERT_EQ(FloatSize(400, 300), visual_viewport.GetScrollOffset());
ASSERT_EQ(ScrollOffset(200, 1400),
- frame_view.LayoutViewportScrollableArea()->GetScrollOffset());
+ frame_view.LayoutViewport()->GetScrollOffset());
IntPoint expected_location =
frame_view.GetScrollableArea()->VisibleContentRect().Location();
@@ -290,9 +294,8 @@ TEST_P(VisualViewportTest, TestResizeAfterVerticalScroll) {
// Scroll main frame to the bottom of the document
WebView()->MainFrameImpl()->SetScrollOffset(WebSize(0, 400));
- EXPECT_EQ(
- ScrollOffset(0, 400),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 400),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
WebView()->SetPageScaleFactor(2.0);
@@ -311,9 +314,8 @@ TEST_P(VisualViewportTest, TestResizeAfterVerticalScroll) {
// After resizing the scale changes 2.0 -> 4.0
EXPECT_FLOAT_SIZE_EQ(FloatSize(50, 25), visual_viewport.VisibleRect().Size());
- EXPECT_EQ(
- ScrollOffset(0, 625),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 625),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
EXPECT_FLOAT_SIZE_EQ(FloatSize(0, 75), visual_viewport.GetScrollOffset());
}
@@ -371,7 +373,8 @@ TEST_P(VisualViewportTest, TestResizeAfterHorizontalScroll) {
// After resizing the scale changes 2.0 -> 4.0
EXPECT_FLOAT_SIZE_EQ(FloatSize(50, 25), visual_viewport.VisibleRect().Size());
- EXPECT_EQ(ScrollOffset(0, 0), GetFrame()->View()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(0, 0),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
EXPECT_FLOAT_SIZE_EQ(FloatSize(150, 0), visual_viewport.GetScrollOffset());
}
@@ -471,8 +474,8 @@ TEST_P(VisualViewportTest, TestVisibleRectInDocument) {
// Scroll the layout viewport. Ensure its offset is reflected in
// visibleRectInDocument().
LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView();
- frame_view.LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(40, 100), kProgrammaticScroll);
+ frame_view.LayoutViewport()->SetScrollOffset(ScrollOffset(40, 100),
+ kProgrammaticScroll);
EXPECT_FLOAT_RECT_EQ(FloatRect(50, 115, 50, 200),
visual_viewport.VisibleRectInDocument());
}
@@ -486,14 +489,12 @@ TEST_P(VisualViewportTest, TestFractionalScrollOffsetIsNotOverwritten) {
NavigateTo(base_url_ + "200-by-800-viewport.html");
LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView();
- frame_view.LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 10.5), kProgrammaticScroll);
- frame_view.LayoutViewportScrollableArea()->ScrollableArea::SetScrollOffset(
+ frame_view.LayoutViewport()->SetScrollOffset(ScrollOffset(0, 10.5),
+ kProgrammaticScroll);
+ frame_view.LayoutViewport()->ScrollableArea::SetScrollOffset(
ScrollOffset(10, 30.5), kCompositorScroll);
- EXPECT_EQ(
- 30.5,
- frame_view.LayoutViewportScrollableArea()->GetScrollOffset().Height());
+ EXPECT_EQ(30.5, frame_view.LayoutViewport()->GetScrollOffset().Height());
}
// Test that the viewport's scroll offset is always appropriately bounded such
@@ -738,7 +739,7 @@ TEST_P(VisualViewportTest, TestAttachingNewFrameSetsInnerScrollLayerSize) {
NavigateTo(base_url_ + "viewport-device-width.html");
// Ensure the scroll layer matches the frame view's size.
- EXPECT_EQ(FloatSize(320, 240), visual_viewport.ScrollLayer()->Size());
+ EXPECT_EQ(IntSize(320, 240), visual_viewport.ScrollLayer()->Size());
// Ensure the location and scale were reset.
EXPECT_EQ(FloatSize(), visual_viewport.GetScrollOffset());
@@ -864,7 +865,6 @@ TEST_P(VisualViewportTest, TestRestoredFromHistoryItem) {
item.SetPageScaleFactor(2);
FrameTestHelpers::LoadHistoryItem(WebView()->MainFrameImpl(), item,
- kWebHistoryDifferentDocumentLoad,
mojom::FetchCacheMode::kDefault);
VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport();
@@ -895,14 +895,12 @@ TEST_P(VisualViewportTest, TestRestoredFromLegacyHistoryItem) {
item.SetPageScaleFactor(2);
FrameTestHelpers::LoadHistoryItem(WebView()->MainFrameImpl(), item,
- kWebHistoryDifferentDocumentLoad,
mojom::FetchCacheMode::kDefault);
VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport();
EXPECT_EQ(2, visual_viewport.Scale());
- EXPECT_EQ(
- ScrollOffset(100, 150),
- GetFrame()->View()->LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(100, 150),
+ GetFrame()->View()->LayoutViewport()->GetScrollOffset());
EXPECT_FLOAT_POINT_EQ(FloatPoint(20, 30),
visual_viewport.VisibleRect().Location());
}
@@ -919,8 +917,8 @@ TEST_P(VisualViewportTest,
NavigateTo(base_url_ + "content-width-1000.html");
LocalFrameView* frame_view = WebView()->MainFrameImpl()->GetFrameView();
- frame_view->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 1000), kProgrammaticScroll);
+ frame_view->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 1000),
+ kProgrammaticScroll);
EXPECT_EQ(IntSize(1000, 1000), frame_view->FrameRect().Size());
@@ -1042,7 +1040,7 @@ TEST_P(VisualViewportTest, TestContextMenuShownInCorrectLocation) {
WebMouseEvent mouse_up_event(mouse_down_event);
mouse_up_event.SetType(WebInputEvent::kMouseUp);
- WebFrameClient* old_client = WebView()->MainFrameImpl()->Client();
+ WebLocalFrameClient* old_client = WebView()->MainFrameImpl()->Client();
VisualViewportMockWebFrameClient mock_web_frame_client;
EXPECT_CALL(mock_web_frame_client,
ShowContextMenu(ContextMenuAtLocation(
@@ -1085,7 +1083,7 @@ TEST_P(VisualViewportTest, TestClientNotifiedOfScrollEvents) {
RegisterMockedHttpURLLoad("200-by-300.html");
NavigateTo(base_url_ + "200-by-300.html");
- WebFrameClient* old_client = WebView()->MainFrameImpl()->Client();
+ WebLocalFrameClient* old_client = WebView()->MainFrameImpl()->Client();
VisualViewportMockWebFrameClient mock_web_frame_client;
WebView()->MainFrameImpl()->SetClient(&mock_web_frame_client);
@@ -1120,8 +1118,7 @@ TEST_P(VisualViewportTest, ScrollIntoViewFractionalOffset) {
NavigateTo(base_url_ + "scroll-into-view.html");
LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView();
- ScrollableArea* layout_viewport_scrollable_area =
- frame_view.LayoutViewportScrollableArea();
+ ScrollableArea* layout_viewport_scrollable_area = frame_view.LayoutViewport();
VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport();
Element* inputBox = GetFrame()->GetDocument()->getElementById("box");
@@ -1183,8 +1180,7 @@ static ScrollOffset expectedMaxLayoutViewportScrollOffset(
float aspect_ratio = visual_viewport.VisibleRect().Width() /
visual_viewport.VisibleRect().Height();
float new_height = frame_view.FrameRect().Width() / aspect_ratio;
- IntSize contents_size =
- frame_view.LayoutViewportScrollableArea()->ContentsSize();
+ IntSize contents_size = frame_view.LayoutViewport()->ContentsSize();
return ScrollOffset(contents_size.Width() - frame_view.FrameRect().Width(),
contents_size.Height() - new_height);
}
@@ -1201,13 +1197,13 @@ TEST_P(VisualViewportTest, TestBrowserControlsAdjustment) {
LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView();
visual_viewport.SetScale(1);
- EXPECT_EQ(IntSize(500, 450), visual_viewport.VisibleRect().Size());
+ EXPECT_EQ(FloatSize(500, 450), visual_viewport.VisibleRect().Size());
EXPECT_EQ(IntSize(1000, 900), frame_view.FrameRect().Size());
// Simulate bringing down the browser controls by 20px.
WebView()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), WebFloatSize(),
1, 1);
- EXPECT_EQ(IntSize(500, 430), visual_viewport.VisibleRect().Size());
+ EXPECT_EQ(FloatSize(500, 430), visual_viewport.VisibleRect().Size());
// Test that the scroll bounds are adjusted appropriately: the visual viewport
// should be shrunk by 20px to 430px. The outer viewport was shrunk to
@@ -1217,10 +1213,10 @@ TEST_P(VisualViewportTest, TestBrowserControlsAdjustment) {
EXPECT_EQ(FloatSize(500, 860 - 430), visual_viewport.GetScrollOffset());
// The outer viewport (LocalFrameView) should be affected as well.
- frame_view.LayoutViewportScrollableArea()->ScrollBy(
- ScrollOffset(10000, 10000), kUserScroll);
+ frame_view.LayoutViewport()->ScrollBy(ScrollOffset(10000, 10000),
+ kUserScroll);
EXPECT_EQ(expectedMaxLayoutViewportScrollOffset(visual_viewport, frame_view),
- frame_view.LayoutViewportScrollableArea()->GetScrollOffset());
+ frame_view.LayoutViewport()->GetScrollOffset());
// Simulate bringing up the browser controls by 10.5px.
WebView()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), WebFloatSize(),
@@ -1234,10 +1230,10 @@ TEST_P(VisualViewportTest, TestBrowserControlsAdjustment) {
visual_viewport.GetScrollOffset());
// The outer viewport (LocalFrameView) should be affected as well.
- frame_view.LayoutViewportScrollableArea()->ScrollBy(
- ScrollOffset(10000, 10000), kUserScroll);
+ frame_view.LayoutViewport()->ScrollBy(ScrollOffset(10000, 10000),
+ kUserScroll);
EXPECT_EQ(expectedMaxLayoutViewportScrollOffset(visual_viewport, frame_view),
- frame_view.LayoutViewportScrollableArea()->GetScrollOffset());
+ frame_view.LayoutViewport()->GetScrollOffset());
}
TEST_P(VisualViewportTest, TestBrowserControlsAdjustmentWithScale) {
@@ -1252,7 +1248,7 @@ TEST_P(VisualViewportTest, TestBrowserControlsAdjustmentWithScale) {
LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView();
visual_viewport.SetScale(2);
- EXPECT_EQ(IntSize(250, 225), visual_viewport.VisibleRect().Size());
+ EXPECT_EQ(FloatSize(250, 225), visual_viewport.VisibleRect().Size());
EXPECT_EQ(IntSize(1000, 900), frame_view.FrameRect().Size());
// Simulate bringing down the browser controls by 20px. Since we're zoomed in,
@@ -1260,31 +1256,28 @@ TEST_P(VisualViewportTest, TestBrowserControlsAdjustmentWithScale) {
// they do at an unzoomed level.
WebView()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), WebFloatSize(),
1, 1);
- EXPECT_EQ(IntSize(250, 215), visual_viewport.VisibleRect().Size());
+ EXPECT_EQ(FloatSize(250, 215), visual_viewport.VisibleRect().Size());
// Test that the scroll bounds are adjusted appropriately.
visual_viewport.Move(ScrollOffset(10000, 10000));
EXPECT_EQ(FloatSize(750, 860 - 215), visual_viewport.GetScrollOffset());
// The outer viewport (LocalFrameView) should be affected as well.
- frame_view.LayoutViewportScrollableArea()->ScrollBy(
- ScrollOffset(10000, 10000), kUserScroll);
+ frame_view.LayoutViewport()->ScrollBy(ScrollOffset(10000, 10000),
+ kUserScroll);
ScrollOffset expected =
expectedMaxLayoutViewportScrollOffset(visual_viewport, frame_view);
- EXPECT_EQ(expected,
- frame_view.LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(expected, frame_view.LayoutViewport()->GetScrollOffset());
// Scale back out, LocalFrameView max scroll shouldn't have changed. Visual
// viewport should be moved up to accomodate larger view.
WebView()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), WebFloatSize(),
0.5f, 0);
EXPECT_EQ(1, visual_viewport.Scale());
- EXPECT_EQ(expected,
- frame_view.LayoutViewportScrollableArea()->GetScrollOffset());
- frame_view.LayoutViewportScrollableArea()->ScrollBy(
- ScrollOffset(10000, 10000), kUserScroll);
- EXPECT_EQ(expected,
- frame_view.LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(expected, frame_view.LayoutViewport()->GetScrollOffset());
+ frame_view.LayoutViewport()->ScrollBy(ScrollOffset(10000, 10000),
+ kUserScroll);
+ EXPECT_EQ(expected, frame_view.LayoutViewport()->GetScrollOffset());
EXPECT_EQ(FloatSize(500, 860 - 430), visual_viewport.GetScrollOffset());
visual_viewport.Move(ScrollOffset(10000, 10000));
@@ -1305,10 +1298,10 @@ TEST_P(VisualViewportTest, TestBrowserControlsAdjustmentWithScale) {
EXPECT_FLOAT_SIZE_EQ(FloatSize(375, 877.5 - 548.75),
visual_viewport.GetScrollOffset());
- frame_view.LayoutViewportScrollableArea()->ScrollBy(
- ScrollOffset(10000, 10000), kUserScroll);
+ frame_view.LayoutViewport()->ScrollBy(ScrollOffset(10000, 10000),
+ kUserScroll);
EXPECT_EQ(expectedMaxLayoutViewportScrollOffset(visual_viewport, frame_view),
- frame_view.LayoutViewportScrollableArea()->GetScrollOffset());
+ frame_view.LayoutViewport()->GetScrollOffset());
}
// Tests that a scroll all the way to the bottom of the page, while hiding the
@@ -1337,8 +1330,8 @@ TEST_P(VisualViewportTest, TestBrowserControlsAdjustmentAndResize) {
LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView();
visual_viewport.SetScale(page_scale);
- EXPECT_EQ(IntSize(250, (visual_viewport_height - browser_controls_height) /
- page_scale),
+ EXPECT_EQ(FloatSize(250, (visual_viewport_height - browser_controls_height) /
+ page_scale),
visual_viewport.VisibleRect().Size());
EXPECT_EQ(IntSize(1000, layout_viewport_height -
browser_controls_height / min_page_scale),
@@ -1349,11 +1342,11 @@ TEST_P(VisualViewportTest, TestBrowserControlsAdjustmentAndResize) {
// Scroll all the way to the bottom, hiding the browser controls in the
// process.
visual_viewport.Move(ScrollOffset(10000, 10000));
- frame_view.LayoutViewportScrollableArea()->ScrollBy(
- ScrollOffset(10000, 10000), kUserScroll);
+ frame_view.LayoutViewport()->ScrollBy(ScrollOffset(10000, 10000),
+ kUserScroll);
WebView()->GetBrowserControls().SetShownRatio(0);
- EXPECT_EQ(IntSize(250, visual_viewport_height / page_scale),
+ EXPECT_EQ(FloatSize(250, visual_viewport_height / page_scale),
visual_viewport.VisibleRect().Size());
ScrollOffset frame_view_expected =
@@ -1363,7 +1356,7 @@ TEST_P(VisualViewportTest, TestBrowserControlsAdjustmentAndResize) {
EXPECT_EQ(visual_viewport_expected, visual_viewport.GetScrollOffset());
EXPECT_EQ(frame_view_expected,
- frame_view.LayoutViewportScrollableArea()->GetScrollOffset());
+ frame_view.LayoutViewport()->GetScrollOffset());
ScrollOffset total_expected = visual_viewport_expected + frame_view_expected;
@@ -1374,13 +1367,12 @@ TEST_P(VisualViewportTest, TestBrowserControlsAdjustmentAndResize) {
0, false);
EXPECT_EQ(IntSize(500, visual_viewport_height), visual_viewport.Size());
- EXPECT_EQ(IntSize(250, visual_viewport_height / page_scale),
+ EXPECT_EQ(FloatSize(250, visual_viewport_height / page_scale),
visual_viewport.VisibleRect().Size());
EXPECT_EQ(IntSize(1000, layout_viewport_height),
frame_view.FrameRect().Size());
- EXPECT_EQ(total_expected,
- visual_viewport.GetScrollOffset() +
- frame_view.LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(total_expected, visual_viewport.GetScrollOffset() +
+ frame_view.LayoutViewport()->GetScrollOffset());
}
// Tests that a scroll all the way to the bottom while showing the browser
@@ -1409,7 +1401,7 @@ TEST_P(VisualViewportTest, TestBrowserControlsShrinkAdjustmentAndResize) {
LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView();
visual_viewport.SetScale(page_scale);
- EXPECT_EQ(IntSize(250, visual_viewport_height / page_scale),
+ EXPECT_EQ(FloatSize(250, visual_viewport_height / page_scale),
visual_viewport.VisibleRect().Size());
EXPECT_EQ(IntSize(1000, layout_viewport_height),
frame_view.FrameRect().Size());
@@ -1420,11 +1412,11 @@ TEST_P(VisualViewportTest, TestBrowserControlsShrinkAdjustmentAndResize) {
// example).
WebView()->GetBrowserControls().SetShownRatio(1);
visual_viewport.Move(ScrollOffset(10000, 10000));
- frame_view.LayoutViewportScrollableArea()->ScrollBy(
- ScrollOffset(10000, 10000), kUserScroll);
+ frame_view.LayoutViewport()->ScrollBy(ScrollOffset(10000, 10000),
+ kUserScroll);
- EXPECT_EQ(IntSize(250, (visual_viewport_height - browser_controls_height) /
- page_scale),
+ EXPECT_EQ(FloatSize(250, (visual_viewport_height - browser_controls_height) /
+ page_scale),
visual_viewport.VisibleRect().Size());
ScrollOffset frame_view_expected(
@@ -1436,7 +1428,7 @@ TEST_P(VisualViewportTest, TestBrowserControlsShrinkAdjustmentAndResize) {
EXPECT_EQ(visual_viewport_expected, visual_viewport.GetScrollOffset());
EXPECT_EQ(frame_view_expected,
- frame_view.LayoutViewportScrollableArea()->GetScrollOffset());
+ frame_view.LayoutViewport()->GetScrollOffset());
ScrollOffset total_expected = visual_viewport_expected + frame_view_expected;
@@ -1449,15 +1441,14 @@ TEST_P(VisualViewportTest, TestBrowserControlsShrinkAdjustmentAndResize) {
EXPECT_EQ(IntSize(500, visual_viewport_height - browser_controls_height),
visual_viewport.Size());
- EXPECT_EQ(IntSize(250, (visual_viewport_height - browser_controls_height) /
- page_scale),
+ EXPECT_EQ(FloatSize(250, (visual_viewport_height - browser_controls_height) /
+ page_scale),
visual_viewport.VisibleRect().Size());
EXPECT_EQ(IntSize(1000, layout_viewport_height -
browser_controls_height / min_page_scale),
frame_view.FrameRect().Size());
- EXPECT_EQ(total_expected,
- visual_viewport.GetScrollOffset() +
- frame_view.LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(total_expected, visual_viewport.GetScrollOffset() +
+ frame_view.LayoutViewport()->GetScrollOffset());
}
// Tests that a resize due to browser controls hiding doesn't incorrectly clamp
@@ -1479,17 +1470,13 @@ TEST_P(VisualViewportTest, TestTopControlHidingResizeDoesntClampMainFrame) {
WebView()->ApplyViewportDeltas(WebFloatSize(), WebFloatSize(), WebFloatSize(),
1, -1);
LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView();
- frame_view.LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 10000), kProgrammaticScroll);
- EXPECT_EQ(
- 500,
- frame_view.LayoutViewportScrollableArea()->GetScrollOffset().Height());
+ frame_view.LayoutViewport()->SetScrollOffset(ScrollOffset(0, 10000),
+ kProgrammaticScroll);
+ EXPECT_EQ(500, frame_view.LayoutViewport()->GetScrollOffset().Height());
// Now send the resize, make sure the scroll offset doesn't change.
WebView()->ResizeWithBrowserControls(WebSize(1000, 1500), 500, 0, false);
- EXPECT_EQ(
- 500,
- frame_view.LayoutViewportScrollableArea()->GetScrollOffset().Height());
+ EXPECT_EQ(500, frame_view.LayoutViewport()->GetScrollOffset().Height());
}
static void configureHiddenScrollbarsSettings(WebSettings* settings) {
@@ -1543,7 +1530,7 @@ TEST_P(VisualViewportTest, TestChangingContentSizeAffectsScrollBounds) {
"content.style.height = \"2400px\";"));
frame_view.UpdateAllLifecyclePhases();
cc::Layer* scroll_layer =
- frame_view.LayoutViewportScrollableArea()->LayerForScrolling()->CcLayer();
+ frame_view.LayoutViewport()->LayerForScrolling()->CcLayer();
EXPECT_EQ(gfx::Size(1500, 2400), scroll_layer->bounds());
}
@@ -1583,17 +1570,18 @@ TEST_P(VisualViewportTest, ElementBoundsInViewportSpaceAccountsForViewport) {
IntRect bounds = input_element->GetLayoutObject()->AbsoluteBoundingBoxRect();
VisualViewport& visual_viewport = GetFrame()->GetPage()->GetVisualViewport();
- IntPoint scrollDelta(250, 400);
+ FloatPoint scrollDelta(250, 400);
visual_viewport.SetScale(2);
visual_viewport.SetLocation(scrollDelta);
const IntRect bounds_in_viewport = input_element->BoundsInViewport();
IntRect expectedBounds = bounds;
expectedBounds.Scale(2.f);
- IntPoint expectedScrollDelta = scrollDelta;
+ FloatPoint expectedScrollDelta = scrollDelta;
expectedScrollDelta.Scale(2.f, 2.f);
- EXPECT_EQ(IntPoint(expectedBounds.Location() - expectedScrollDelta),
+ EXPECT_EQ(RoundedIntPoint(FloatPoint(FloatPoint(expectedBounds.Location()) -
+ expectedScrollDelta)),
bounds_in_viewport.Location());
EXPECT_EQ(expectedBounds.Size(), bounds_in_viewport.Size());
}
@@ -1652,8 +1640,8 @@ TEST_P(VisualViewportTest, visualViewportIsInert) {
->GetVisualViewport();
visual_viewport.SetScale(2);
- ASSERT_EQ(100, visual_viewport.VisibleSize().Width());
- ASSERT_EQ(150, visual_viewport.VisibleSize().Height());
+ ASSERT_EQ(100, visual_viewport.VisibleRect().Width());
+ ASSERT_EQ(150, visual_viewport.VisibleRect().Height());
EXPECT_EQ(200, window->innerWidth());
EXPECT_EQ(300, window->innerHeight());
@@ -1794,8 +1782,8 @@ TEST_P(VisualViewportTest, AccessibilityHitTestWhileZoomedIn) {
WebView()->SetPageScaleFactor(2);
WebView()->SetVisualViewportOffset(WebFloatPoint(200, 230));
- frame_view.LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(400, 1100), kProgrammaticScroll);
+ frame_view.LayoutViewport()->SetScrollOffset(ScrollOffset(400, 1100),
+ kProgrammaticScroll);
// FIXME(504057): PaintLayerScrollableArea dirties the compositing state.
ForceFullCompositingUpdate();
@@ -1854,8 +1842,8 @@ TEST_P(VisualViewportTest, TestCoordinateTransforms) {
visual_viewport.RootFrameToViewport(FloatPoint(50.5, 62.4)));
// Scrolling the main frame should have no effect.
- frame_view.LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(100, 120), kProgrammaticScroll);
+ frame_view.LayoutViewport()->SetScrollOffset(ScrollOffset(100, 120),
+ kProgrammaticScroll);
EXPECT_FLOAT_POINT_EQ(FloatPoint(50, 62), visual_viewport.ViewportToRootFrame(
FloatPoint(80, 100)));
EXPECT_FLOAT_POINT_EQ(
@@ -1895,30 +1883,6 @@ TEST_P(VisualViewportTest, WindowDimensionsOnLoadWideContent) {
std::string(output->InnerHTMLAsString().Ascii().data()));
}
-TEST_P(VisualViewportTest, PinchZoomGestureScrollsVisualViewportOnly) {
- InitializeWithDesktopSettings();
- WebView()->Resize(IntSize(100, 100));
-
- RegisterMockedHttpURLLoad("200-by-800-viewport.html");
- NavigateTo(base_url_ + "200-by-800-viewport.html");
-
- WebGestureEvent pinch_update(
- WebInputEvent::kGesturePinchUpdate, WebInputEvent::kNoModifiers,
- WebInputEvent::GetStaticTimeStampForTests(), kWebGestureDeviceTouchpad);
- pinch_update.SetPositionInWidget(FloatPoint(100, 100));
- pinch_update.data.pinch_update.scale = 2;
- pinch_update.data.pinch_update.zoom_disabled = false;
-
- WebView()->HandleInputEvent(WebCoalescedInputEvent(pinch_update));
-
- VisualViewport& visual_viewport = WebView()->GetPage()->GetVisualViewport();
- LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView();
-
- EXPECT_FLOAT_SIZE_EQ(FloatSize(50, 50), visual_viewport.GetScrollOffset());
- EXPECT_EQ(ScrollOffset(0, 0),
- frame_view.LayoutViewportScrollableArea()->GetScrollOffset());
-}
-
TEST_P(VisualViewportTest, ResizeWithScrollAnchoring) {
InitializeWithDesktopSettings();
WebView()->Resize(IntSize(800, 600));
@@ -1927,13 +1891,13 @@ TEST_P(VisualViewportTest, ResizeWithScrollAnchoring) {
NavigateTo(base_url_ + "icb-relative-content.html");
LocalFrameView& frame_view = *WebView()->MainFrameImpl()->GetFrameView();
- frame_view.LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(700, 500), kProgrammaticScroll);
+ frame_view.LayoutViewport()->SetScrollOffset(ScrollOffset(700, 500),
+ kProgrammaticScroll);
WebView()->UpdateAllLifecyclePhases();
WebView()->Resize(IntSize(800, 300));
EXPECT_EQ(ScrollOffset(700, 200),
- frame_view.LayoutViewportScrollableArea()->GetScrollOffset());
+ frame_view.LayoutViewport()->GetScrollOffset());
}
// Ensure that resize anchoring as happens when browser controls hide/show
@@ -1962,8 +1926,7 @@ TEST_P(VisualViewportTest, ResizeAnchoringWithRootScroller) {
WebView()->Resize(IntSize(800, 500));
- EXPECT_EQ(ScrollOffset(),
- frame_view.LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(), frame_view.LayoutViewport()->GetScrollOffset());
}
// Ensure that resize anchoring as happens when the device is rotated affects
@@ -1988,8 +1951,7 @@ TEST_P(VisualViewportTest, RotationAnchoringWithRootScroller) {
WebView()->Resize(IntSize(600, 800));
- EXPECT_EQ(ScrollOffset(),
- frame_view.LayoutViewportScrollableArea()->GetScrollOffset());
+ EXPECT_EQ(ScrollOffset(), frame_view.LayoutViewport()->GetScrollOffset());
EXPECT_EQ(600, scroller->scrollTop());
}
@@ -2290,5 +2252,61 @@ TEST_P(VisualViewportTest, AutoResizeNoHeightUsesMinimumHeight) {
base_url);
}
+class VisualViewportSimTest : public SimTest {
+ public:
+ VisualViewportSimTest() {}
+
+ void SetUp() override {
+ SimTest::SetUp();
+
+ // Use settings that resemble the Android configuration.
+ WebView().GetSettings()->SetViewportEnabled(true);
+ WebView().GetSettings()->SetAcceleratedCompositingEnabled(true);
+ WebView().GetSettings()->SetPreferCompositingToLCDTextEnabled(true);
+ WebView().GetSettings()->SetViewportMetaEnabled(true);
+ WebView().GetSettings()->SetViewportEnabled(true);
+ WebView().GetSettings()->SetMainFrameResizesAreOrientationChanges(true);
+ WebView().GetSettings()->SetShrinksViewportContentToFit(true);
+ WebView().SetDefaultPageScaleLimits(0.25f, 5);
+ }
+};
+
+// Test that we correcty size the visual viewport's scrolling contents layer
+// when the layout viewport is smaller.
+TEST_F(VisualViewportSimTest, ScrollingContentsSmallerThanContainer) {
+ WebView().Resize(WebSize(400, 600));
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <meta name="viewport" content="width=320">
+ <style>
+ body {
+ height: 2000px;
+ }
+ </style>
+ )HTML");
+ Compositor().BeginFrame();
+
+ ASSERT_EQ(1.25f, WebView().MinimumPageScaleFactor());
+
+ VisualViewport& visual_viewport = WebView().GetPage()->GetVisualViewport();
+ EXPECT_EQ(IntSize(400, 600), visual_viewport.ContainerLayer()->Size());
+ EXPECT_EQ(gfx::Size(400, 600),
+ visual_viewport.ContainerLayer()->CcLayer()->bounds());
+ EXPECT_EQ(IntSize(320, 480), visual_viewport.ScrollLayer()->Size());
+ EXPECT_EQ(gfx::Size(320, 480),
+ visual_viewport.ScrollLayer()->CcLayer()->bounds());
+
+ WebView().ApplyViewportDeltas(WebFloatSize(1, 1), WebFloatSize(),
+ WebFloatSize(), 2, 1);
+ EXPECT_EQ(IntSize(400, 600), visual_viewport.ContainerLayer()->Size());
+ EXPECT_EQ(gfx::Size(400, 600),
+ visual_viewport.ContainerLayer()->CcLayer()->bounds());
+ EXPECT_EQ(IntSize(320, 480), visual_viewport.ScrollLayer()->Size());
+ EXPECT_EQ(gfx::Size(320, 480),
+ visual_viewport.ScrollLayer()->CcLayer()->bounds());
+}
+
} // namespace
} // namespace blink
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 b4b93ca50aa..bfa6a1fcae6 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
@@ -9,7 +9,6 @@
#include "base/time/time.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/web_gesture_curve.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"
@@ -29,7 +28,6 @@
#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/pointer_lock_controller.h"
-#include "third_party/blink/renderer/platform/exported/web_active_gesture_animation.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink {
@@ -48,9 +46,7 @@ STATIC_ASSERT_ENUM(kDragOperationEvery, kWebDragOperationEvery);
bool WebFrameWidgetBase::ignore_input_events_ = false;
WebFrameWidgetBase::WebFrameWidgetBase(WebWidgetClient& client)
- : client_(&client),
- fling_modifier_(0),
- fling_source_device_(kWebGestureDeviceUninitialized) {}
+ : client_(&client) {}
WebFrameWidgetBase::~WebFrameWidgetBase() = default;
@@ -208,7 +204,7 @@ void WebFrameWidgetBase::CancelDrag() {
void WebFrameWidgetBase::StartDragging(WebReferrerPolicy policy,
const WebDragData& data,
WebDragOperationsMask mask,
- const WebImage& drag_image,
+ const SkBitmap& drag_image,
const WebPoint& drag_image_offset) {
doing_drag_and_drop_ = true;
Client()->StartDragging(policy, data, mask, drag_image, drag_image_offset);
@@ -379,176 +375,8 @@ LocalFrame* WebFrameWidgetBase::FocusedLocalFrameInWidget() const {
: nullptr;
}
-bool WebFrameWidgetBase::EndActiveFlingAnimation() {
- if (gesture_animation_) {
- gesture_animation_.reset();
- fling_source_device_ = kWebGestureDeviceUninitialized;
- if (WebLayerTreeView* layer_tree_view = GetLayerTreeView())
- layer_tree_view->DidStopFlinging();
- return true;
- }
- return false;
-}
-
-bool WebFrameWidgetBase::ScrollBy(const WebFloatSize& delta,
- const WebFloatSize& velocity) {
- DCHECK_NE(fling_source_device_, kWebGestureDeviceUninitialized);
-
- if (fling_source_device_ == kWebGestureDeviceTouchpad) {
- bool enable_touchpad_scroll_latching =
- RuntimeEnabledFeatures::TouchpadAndWheelScrollLatchingEnabled();
- WebMouseWheelEvent synthetic_wheel(
- WebInputEvent::kMouseWheel, fling_modifier_, WTF::CurrentTimeTicks());
- const float kTickDivisor = WheelEvent::kTickMultiplier;
-
- synthetic_wheel.delta_x = delta.width;
- synthetic_wheel.delta_y = delta.height;
- synthetic_wheel.wheel_ticks_x = delta.width / kTickDivisor;
- synthetic_wheel.wheel_ticks_y = delta.height / kTickDivisor;
- synthetic_wheel.has_precise_scrolling_deltas = true;
- synthetic_wheel.phase = WebMouseWheelEvent::kPhaseChanged;
- synthetic_wheel.SetPositionInWidget(position_on_fling_start_.x,
- position_on_fling_start_.y);
- synthetic_wheel.SetPositionInScreen(global_position_on_fling_start_.x,
- global_position_on_fling_start_.y);
-
- // TODO(wjmaclean): Is local_root_ the right frame to use here?
- if (GetPageWidgetEventHandler()->HandleMouseWheel(*local_root_->GetFrame(),
- synthetic_wheel) !=
- WebInputEventResult::kNotHandled) {
- return true;
- }
-
- if (!enable_touchpad_scroll_latching) {
- WebGestureEvent synthetic_scroll_begin =
- CreateGestureScrollEventFromFling(WebInputEvent::kGestureScrollBegin,
- kWebGestureDeviceTouchpad);
- synthetic_scroll_begin.data.scroll_begin.delta_x_hint = delta.width;
- synthetic_scroll_begin.data.scroll_begin.delta_y_hint = delta.height;
- synthetic_scroll_begin.data.scroll_begin.inertial_phase =
- WebGestureEvent::kMomentumPhase;
- GetPageWidgetEventHandler()->HandleGestureEvent(synthetic_scroll_begin);
- }
-
- WebGestureEvent synthetic_scroll_update = CreateGestureScrollEventFromFling(
- WebInputEvent::kGestureScrollUpdate, kWebGestureDeviceTouchpad);
- synthetic_scroll_update.data.scroll_update.delta_x = delta.width;
- synthetic_scroll_update.data.scroll_update.delta_y = delta.height;
- synthetic_scroll_update.data.scroll_update.velocity_x = velocity.width;
- synthetic_scroll_update.data.scroll_update.velocity_y = velocity.height;
- synthetic_scroll_update.data.scroll_update.inertial_phase =
- WebGestureEvent::kMomentumPhase;
- bool scroll_update_handled =
- GetPageWidgetEventHandler()->HandleGestureEvent(
- synthetic_scroll_update) != WebInputEventResult::kNotHandled;
-
- if (!enable_touchpad_scroll_latching) {
- WebGestureEvent synthetic_scroll_end = CreateGestureScrollEventFromFling(
- WebInputEvent::kGestureScrollEnd, kWebGestureDeviceTouchpad);
- synthetic_scroll_end.data.scroll_end.inertial_phase =
- WebGestureEvent::kMomentumPhase;
- GetPageWidgetEventHandler()->HandleGestureEvent(synthetic_scroll_end);
- }
-
- return scroll_update_handled;
- }
-
- WebGestureEvent synthetic_gesture_event = CreateGestureScrollEventFromFling(
- WebInputEvent::kGestureScrollUpdate, fling_source_device_);
- synthetic_gesture_event.data.scroll_update.delta_x = delta.width;
- synthetic_gesture_event.data.scroll_update.delta_y = delta.height;
- synthetic_gesture_event.data.scroll_update.velocity_x = velocity.width;
- synthetic_gesture_event.data.scroll_update.velocity_y = velocity.height;
- synthetic_gesture_event.data.scroll_update.inertial_phase =
- WebGestureEvent::kMomentumPhase;
-
- return GetPageWidgetEventHandler()->HandleGestureEvent(
- synthetic_gesture_event) != WebInputEventResult::kNotHandled;
-}
-
-WebInputEventResult WebFrameWidgetBase::HandleGestureFlingEvent(
- const WebGestureEvent& event) {
- WebInputEventResult event_result = WebInputEventResult::kNotHandled;
- switch (event.GetType()) {
- case WebInputEvent::kGestureFlingStart: {
- if (event.SourceDevice() != kWebGestureDeviceSyntheticAutoscroll)
- EndActiveFlingAnimation();
- position_on_fling_start_ = event.PositionInWidget();
- global_position_on_fling_start_ = event.PositionInScreen();
- fling_modifier_ = event.GetModifiers();
- fling_source_device_ = event.SourceDevice();
- DCHECK_NE(fling_source_device_, kWebGestureDeviceUninitialized);
- std::unique_ptr<WebGestureCurve> fling_curve =
- Platform::Current()->CreateFlingAnimationCurve(
- event.SourceDevice(),
- WebFloatPoint(event.data.fling_start.velocity_x,
- event.data.fling_start.velocity_y),
- WebSize());
- DCHECK(fling_curve);
- gesture_animation_ = WebActiveGestureAnimation::CreateWithTimeOffset(
- std::move(fling_curve), this, event.TimeStamp());
- ScheduleAnimation();
-
- WebGestureEvent scaled_event =
- TransformWebGestureEvent(local_root_->GetFrameView(), event);
- // Plugins may need to see GestureFlingStart to balance
- // GestureScrollBegin (since the former replaces GestureScrollEnd when
- // transitioning to a fling).
- // TODO(dtapuska): Why isn't the response used?
- local_root_->GetFrame()->GetEventHandler().HandleGestureScrollEvent(
- scaled_event);
-
- event_result = WebInputEventResult::kHandledSystem;
- break;
- }
- case WebInputEvent::kGestureFlingCancel:
- if (EndActiveFlingAnimation())
- event_result = WebInputEventResult::kHandledSuppressed;
-
- break;
- default:
- NOTREACHED();
- }
- return event_result;
-}
-
WebLocalFrame* WebFrameWidgetBase::FocusedWebLocalFrameInWidget() const {
return WebLocalFrameImpl::FromFrame(FocusedLocalFrameInWidget());
}
-WebGestureEvent WebFrameWidgetBase::CreateGestureScrollEventFromFling(
- WebInputEvent::Type type,
- WebGestureDevice source_device) const {
- WebGestureEvent gesture_event(type, fling_modifier_, WTF::CurrentTimeTicks(),
- source_device);
- gesture_event.SetPositionInWidget(position_on_fling_start_);
- gesture_event.SetPositionInScreen(global_position_on_fling_start_);
- return gesture_event;
-}
-
-bool WebFrameWidgetBase::IsFlinging() const {
- return !!gesture_animation_;
-}
-
-void WebFrameWidgetBase::UpdateGestureAnimation(
- base::TimeTicks last_frame_time) {
- if (!gesture_animation_)
- return;
-
- if (gesture_animation_->Animate(last_frame_time)) {
- ScheduleAnimation();
- } else {
- DCHECK_NE(fling_source_device_, kWebGestureDeviceUninitialized);
- WebGestureDevice last_fling_source_device = fling_source_device_;
- EndActiveFlingAnimation();
-
- if (last_fling_source_device != kWebGestureDeviceSyntheticAutoscroll) {
- WebGestureEvent end_scroll_event = CreateGestureScrollEventFromFling(
- WebInputEvent::kGestureScrollEnd, last_fling_source_device);
- local_root_->GetFrame()->GetEventHandler().HandleGestureScrollEnd(
- end_scroll_event);
- }
- }
-}
-
} // 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 c1dee023f79..8459ad786b9 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
@@ -8,8 +8,8 @@
#include "base/single_thread_task_runner.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_gesture_curve_target.h"
#include "third_party/blink/public/platform/web_gesture_device.h"
+#include "third_party/blink/public/platform/web_referrer_policy.h"
#include "third_party/blink/public/web/web_frame_widget.h"
#include "third_party/blink/renderer/core/clipboard/data_object.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -28,8 +28,6 @@ class CompositorMutatorImpl;
class GraphicsLayer;
struct IntrinsicSizingInfo;
class PageWidgetEventHandler;
-class WebActiveGestureAnimation;
-class WebImage;
class WebLayerTreeView;
class WebLocalFrameImpl;
class WebViewImpl;
@@ -38,11 +36,10 @@ struct WebFloatPoint;
class CORE_EXPORT WebFrameWidgetBase
: public GarbageCollectedFinalized<WebFrameWidgetBase>,
- public WebFrameWidget,
- public WebGestureCurveTarget {
+ public WebFrameWidget {
public:
explicit WebFrameWidgetBase(WebWidgetClient&);
- ~WebFrameWidgetBase() override;
+ virtual ~WebFrameWidgetBase();
WebWidgetClient* Client() const { return client_; }
WebLocalFrameImpl* LocalRootImpl() const { return local_root_; }
@@ -70,15 +67,6 @@ class CORE_EXPORT WebFrameWidgetBase
virtual HitTestResult CoreHitTestResultAt(const WebPoint&) = 0;
- // Fling operations.
- bool EndActiveFlingAnimation();
- WebInputEventResult HandleGestureFlingEvent(const WebGestureEvent&);
- void UpdateGestureAnimation(base::TimeTicks last_frame_time);
-
- // WebGestureCurveTarget implementation.
- bool ScrollBy(const WebFloatSize& delta,
- const WebFloatSize& velocity) override;
-
// WebFrameWidget implementation.
void Close() override;
WebLocalFrame* LocalRoot() const override;
@@ -109,7 +97,7 @@ class CORE_EXPORT WebFrameWidgetBase
void StartDragging(WebReferrerPolicy,
const WebDragData&,
WebDragOperationsMask,
- const WebImage& drag_image,
+ const SkBitmap& drag_image,
const WebPoint& drag_image_offset);
bool DoingDragAndDrop() { return doing_drag_and_drop_; }
@@ -121,7 +109,6 @@ class CORE_EXPORT WebFrameWidgetBase
void DidNotAcquirePointerLock() override;
void DidLosePointerLock() override;
void ShowContextMenu(WebMenuSourceType) override;
- bool IsFlinging() const override;
// Image decode functionality.
void RequestDecode(const PaintImage&, base::OnceCallback<void(bool)>);
@@ -178,9 +165,6 @@ class CORE_EXPORT WebFrameWidgetBase
WebDragOperation drag_operation_ = kWebDragOperationNone;
private:
- // Fling local.
- WebGestureEvent CreateGestureScrollEventFromFling(WebInputEvent::Type,
- WebGestureDevice) const;
void CancelDrag();
WebWidgetClient* client_;
@@ -190,12 +174,6 @@ class CORE_EXPORT WebFrameWidgetBase
// points to the root of that subtree.
Member<WebLocalFrameImpl> local_root_;
- std::unique_ptr<WebActiveGestureAnimation> gesture_animation_;
- WebFloatPoint position_on_fling_start_;
- WebFloatPoint global_position_on_fling_start_;
- int fling_modifier_;
- WebGestureDevice fling_source_device_;
-
static bool ignore_input_events_;
scoped_refptr<UserGestureToken> pointer_lock_gesture_token_;
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 4a40389b746..d2026b66ee0 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
@@ -36,7 +36,9 @@
#include "base/auto_reset.h"
#include "base/optional.h"
#include "build/build_config.h"
+#include "cc/layers/picture_layer.h"
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom-blink.h"
+#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_scroll_into_view_params.h"
#include "third_party/blink/public/web/web_autofill_client.h"
#include "third_party/blink/public/web/web_element.h"
@@ -90,10 +92,10 @@ const float kIdealPaddingRatio = 0.3f;
// Returns a rect which is offset and scaled accordingly to |base_rect|'s
// location and size.
-FloatRect NormalizeRect(const FloatRect& to_normalize,
- const FloatRect& base_rect) {
+FloatRect NormalizeRect(const IntRect& to_normalize, const IntRect& base_rect) {
FloatRect result(to_normalize);
- result.SetLocation(to_normalize.Location() + (-base_rect.Location()));
+ result.SetLocation(
+ FloatPoint(to_normalize.Location() + (-base_rect.Location())));
result.Scale(1.0 / base_rect.Width(), 1.0 / base_rect.Height());
return result;
}
@@ -278,8 +280,6 @@ void WebFrameWidgetImpl::BeginFrame(base::TimeTicks last_frame_time) {
if (!LocalRootImpl())
return;
- UpdateGestureAnimation(last_frame_time);
-
DocumentLifecycle::AllowThrottlingScope throttling_scope(
LocalRootImpl()->GetFrame()->GetDocument()->Lifecycle());
PageWidgetDelegate::Animate(*GetPage(), last_frame_time);
@@ -311,7 +311,8 @@ void WebFrameWidgetImpl::UpdateAllLifecyclePhasesAndCompositeForTesting() {
layer_tree_view_->SynchronouslyCompositeNoRasterForTesting();
}
-void WebFrameWidgetImpl::Paint(WebCanvas* canvas, const WebRect& rect) {
+void WebFrameWidgetImpl::PaintContent(cc::PaintCanvas* canvas,
+ const WebRect& rect) {
// Out-of-process iframes require compositing.
NOTREACHED();
}
@@ -672,8 +673,8 @@ bool WebFrameWidgetImpl::SelectionBounds(WebRect& anchor_web,
// FIXME: This doesn't apply page scale. This should probably be contents to
// viewport. crbug.com/459293.
- anchor_web = local_frame->View()->ContentsToRootFrame(anchor);
- focus_web = local_frame->View()->ContentsToRootFrame(focus);
+ anchor_web = local_frame->View()->ConvertToRootFrame(anchor);
+ focus_web = local_frame->View()->ConvertToRootFrame(focus);
return true;
}
@@ -750,10 +751,11 @@ void WebFrameWidgetImpl::HandleMouseDown(LocalFrame& main_frame,
// capture because it will interfere with the scrollbar receiving events.
LayoutPoint point(event.PositionInWidget().x, event.PositionInWidget().y);
if (event.button == WebMouseEvent::Button::kLeft) {
- point = LocalRootImpl()->GetFrameView()->RootFrameToContents(point);
+ HitTestLocation location(
+ LocalRootImpl()->GetFrameView()->ConvertFromRootFrame(point));
HitTestResult result(
- LocalRootImpl()->GetFrame()->GetEventHandler().HitTestResultAtPoint(
- point));
+ LocalRootImpl()->GetFrame()->GetEventHandler().HitTestResultAtLocation(
+ location));
result.SetToShadowHostIfInRestrictedShadowRoot();
Node* hit_node = result.InnerNode();
@@ -842,9 +844,6 @@ void WebFrameWidgetImpl::HandleMouseUp(LocalFrame& main_frame,
WebInputEventResult WebFrameWidgetImpl::HandleMouseWheel(
LocalFrame& frame,
const WebMouseWheelEvent& event) {
- // Halt an in-progress fling on a wheel tick.
- if (!event.has_precise_scrolling_deltas)
- EndActiveFlingAnimation();
View()->HidePopups();
return PageWidgetEventHandler::HandleMouseWheel(frame, event);
@@ -886,11 +885,6 @@ WebInputEventResult WebFrameWidgetImpl::HandleGestureEvent(
GetPage()->GetContextMenuController().ClearContextMenu();
maybe_context_menu_scope.emplace();
break;
- case WebInputEvent::kGestureFlingStart:
- case WebInputEvent::kGestureFlingCancel:
- event_result = HandleGestureFlingEvent(event);
- Client()->DidHandleGestureEvent(event, event_cancelled);
- return event_result;
default:
NOTREACHED();
}
@@ -1033,7 +1027,7 @@ void WebFrameWidgetImpl::InitializeLayerTreeView() {
DCHECK(!mutator_);
layer_tree_view_ = Client()->InitializeLayerTreeView();
DCHECK(layer_tree_view_);
- if (layer_tree_view_->CompositorAnimationHost()) {
+ if (Platform::Current()->IsThreadedAnimationEnabled()) {
animation_host_ = std::make_unique<CompositorAnimationHost>(
layer_tree_view_->CompositorAnimationHost());
}
@@ -1124,8 +1118,7 @@ HitTestResult WebFrameWidgetImpl::CoreHitTestResultAt(
DocumentLifecycle::AllowThrottlingScope throttling_scope(
LocalRootImpl()->GetFrame()->GetDocument()->Lifecycle());
LocalFrameView* view = LocalRootImpl()->GetFrameView();
- IntPoint point_in_root_frame =
- view->ContentsToFrame(view->ViewportToContents(point_in_viewport));
+ IntPoint point_in_root_frame = view->ViewportToFrame(point_in_viewport);
return HitTestResultForRootFramePos(point_in_root_frame);
}
@@ -1140,11 +1133,12 @@ void WebFrameWidgetImpl::SetVisibilityState(
HitTestResult WebFrameWidgetImpl::HitTestResultForRootFramePos(
const LayoutPoint& pos_in_root_frame) {
LayoutPoint doc_point(
- LocalRootImpl()->GetFrame()->View()->RootFrameToContents(
+ LocalRootImpl()->GetFrame()->View()->ConvertFromRootFrame(
pos_in_root_frame));
+ HitTestLocation location(doc_point);
HitTestResult result =
- LocalRootImpl()->GetFrame()->GetEventHandler().HitTestResultAtPoint(
- doc_point, HitTestRequest::kReadOnly | HitTestRequest::kActive);
+ LocalRootImpl()->GetFrame()->GetEventHandler().HitTestResultAtLocation(
+ location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
result.SetToShadowHostIfInRestrictedShadowRoot();
return result;
}
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 d0055431ec1..aed5ed2ed2a 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
@@ -88,7 +88,7 @@ class WebFrameWidgetImpl final : public WebFrameWidgetBase,
void BeginFrame(base::TimeTicks last_frame_time) override;
void UpdateLifecycle(LifecycleUpdate requested_update) override;
void UpdateAllLifecyclePhasesAndCompositeForTesting() override;
- void Paint(WebCanvas*, const WebRect&) override;
+ void PaintContent(cc::PaintCanvas*, const WebRect&) override;
void LayoutAndPaintAsync(base::OnceClosure callback) override;
void CompositeAndReadbackAsync(
base::OnceCallback<void(const SkBitmap&)> callback) override;
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 db86ae3c5eb..082b055a570 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
@@ -78,7 +78,7 @@
// detachChildren() (virtually) calls Frame::detach(), which again calls
// LocalFrameClient::detached(). This triggers WebFrame to clear its reference
// to LocalFrame. LocalFrameClient::detached() also notifies the embedder via
-// WebFrameClient that the frame is detached. Most embedders will invoke
+// WebLocalFrameClient that the frame is detached. Most embedders will invoke
// close() on the WebFrame at this point, triggering its deletion unless
// something else is still retaining a reference.
//
@@ -113,11 +113,12 @@
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_dom_event.h"
#include "third_party/blink/public/web/web_form_element.h"
-#include "third_party/blink/public/web/web_frame_client.h"
#include "third_party/blink/public/web/web_frame_owner_properties.h"
#include "third_party/blink/public/web/web_history_item.h"
#include "third_party/blink/public/web/web_icon_url.h"
#include "third_party/blink/public/web/web_input_element.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
+#include "third_party/blink/public/web/web_media_player_action.h"
#include "third_party/blink/public/web/web_node.h"
#include "third_party/blink/public/web/web_performance.h"
#include "third_party/blink/public/web/web_plugin.h"
@@ -129,13 +130,13 @@
#include "third_party/blink/public/web/web_text_direction.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/exception_state.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/script_value.h"
#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/bindings/core/v8/v8_gc_controller.h"
+#include "third_party/blink/renderer/core/clipboard/clipboard_utilities.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"
@@ -176,6 +177,7 @@
#include "third_party/blink/renderer/core/frame/page_scale_constraints_set.h"
#include "third_party/blink/renderer/core/frame/pausable_script_executor.h"
#include "third_party/blink/renderer/core/frame/pausable_task.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/screen_orientation_controller.h"
@@ -193,6 +195,8 @@
#include "third_party/blink/renderer/core/html/html_head_element.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
#include "third_party/blink/renderer/core/html/html_link_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/plugin_document.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/input/context_menu_allowed_scope.h"
@@ -215,18 +219,17 @@
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/print_context.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.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/platform/bindings/dom_wrapper_world.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
-#include "third_party/blink/renderer/platform/clipboard/clipboard_utilities.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.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_client.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
#include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
@@ -283,7 +286,7 @@ class ChromePrintContext : public PrintContext {
return printed_page_width_ / page_rect.Width();
}
- float SpoolSinglePage(WebCanvas* canvas, int page_number) {
+ float SpoolSinglePage(cc::PaintCanvas* canvas, int page_number) {
DispatchEventsForPrintingOnAllFrames();
if (!GetFrame()->GetDocument() ||
!GetFrame()->GetDocument()->GetLayoutView())
@@ -296,7 +299,7 @@ class ChromePrintContext : public PrintContext {
// The page rect gets scaled and translated, so specify the entire
// print content area here as the recording rect.
- IntRect bounds(0, 0, printed_page_height_, printed_page_width_);
+ FloatRect bounds(0, 0, printed_page_height_, printed_page_width_);
PaintRecordBuilder builder(&canvas->getMetaData());
builder.Context().SetPrinting(true);
builder.Context().BeginRecording(bounds);
@@ -306,7 +309,7 @@ class ChromePrintContext : public PrintContext {
}
void SpoolAllPagesWithBoundariesForTesting(
- WebCanvas* canvas,
+ cc::PaintCanvas* canvas,
const FloatSize& page_size_in_pixels) {
DispatchEventsForPrintingOnAllFrames();
if (!GetFrame()->GetDocument() ||
@@ -323,7 +326,7 @@ class ChromePrintContext : public PrintContext {
const float page_width = page_size_in_pixels.Width();
size_t num_pages = PageRects().size();
int total_height = num_pages * (page_size_in_pixels.Height() + 1) - 1;
- IntRect all_pages_rect(0, 0, page_width, total_height);
+ FloatRect all_pages_rect(0, 0, page_width, total_height);
PaintRecordBuilder builder(&canvas->getMetaData());
GraphicsContext& context = builder.Context();
@@ -388,25 +391,17 @@ class ChromePrintContext : public PrintContext {
auto* frame_view = GetFrame()->View();
DCHECK(frame_view);
- PropertyTreeState property_tree_state = PropertyTreeState::Root();
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- property_tree_state = frame_view->GetLayoutView()
- ->FirstFragment()
- .LocalBorderBoxProperties();
- }
+ PropertyTreeState property_tree_state =
+ frame_view->GetLayoutView()->FirstFragment().LocalBorderBoxProperties();
PaintRecordBuilder builder(&context.Canvas()->getMetaData(), &context);
frame_view->PaintContents(builder.Context(), kGlobalPaintNormalPhase,
page_rect);
{
- base::Optional<ScopedPaintChunkProperties> scoped_paint_chunk_properties;
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- scoped_paint_chunk_properties.emplace(
- builder.Context().GetPaintController(), property_tree_state,
- builder, DisplayItem::kPrintedContentDestinationLocations);
- }
-
+ ScopedPaintChunkProperties scoped_paint_chunk_properties(
+ builder.Context().GetPaintController(), property_tree_state, builder,
+ DisplayItem::kPrintedContentDestinationLocations);
DrawingRecorder line_boundary_recorder(
builder.Context(), builder,
DisplayItem::kPrintedContentDestinationLocations);
@@ -414,7 +409,6 @@ class ChromePrintContext : public PrintContext {
}
context.DrawRecord(builder.EndRecording(property_tree_state));
-
context.Restore();
return scale;
@@ -584,9 +578,9 @@ void WebLocalFrameImpl::SetSharedWorkerRepositoryClient(
SharedWorkerRepositoryClientImpl::Create(client);
}
-ScrollableArea* WebLocalFrameImpl::LayoutViewportScrollableArea() const {
+ScrollableArea* WebLocalFrameImpl::LayoutViewport() const {
if (LocalFrameView* view = GetFrameView())
- return view->LayoutViewportScrollableArea();
+ return view->LayoutViewport();
return nullptr;
}
@@ -600,13 +594,13 @@ bool WebLocalFrameImpl::IsFocused() const {
}
WebSize WebLocalFrameImpl::GetScrollOffset() const {
- if (ScrollableArea* scrollable_area = LayoutViewportScrollableArea())
+ if (ScrollableArea* scrollable_area = LayoutViewport())
return scrollable_area->ScrollOffsetInt();
return WebSize();
}
void WebLocalFrameImpl::SetScrollOffset(const WebSize& offset) {
- if (ScrollableArea* scrollable_area = LayoutViewportScrollableArea()) {
+ if (ScrollableArea* scrollable_area = LayoutViewport()) {
scrollable_area->SetScrollOffset(ScrollOffset(offset.width, offset.height),
kProgrammaticScroll);
}
@@ -627,13 +621,13 @@ bool WebLocalFrameImpl::HasVisibleContent() const {
}
if (LocalFrameView* view = GetFrameView())
- return view->VisibleWidth() > 0 && view->VisibleHeight() > 0;
+ return view->Width() > 0 && view->Height() > 0;
return false;
}
WebRect WebLocalFrameImpl::VisibleContentRect() const {
if (LocalFrameView* view = GetFrameView())
- return view->LayoutViewportScrollableArea()->VisibleContentRect();
+ return view->LayoutViewport()->VisibleContentRect();
return WebRect();
}
@@ -684,12 +678,9 @@ void WebLocalFrameImpl::ExecuteScriptInIsolatedWorld(
CHECK_GT(world_id, 0);
CHECK_LT(world_id, DOMWrapperWorld::kEmbedderWorldIdLimit);
- HeapVector<ScriptSourceCode> sources;
- sources.push_back(source_in);
-
v8::HandleScope handle_scope(ToIsolate(GetFrame()));
- GetFrame()->GetScriptController().ExecuteScriptInIsolatedWorld(
- world_id, sources, nullptr);
+ GetFrame()->GetScriptController().ExecuteScriptInIsolatedWorld(world_id,
+ source_in);
}
v8::Local<v8::Value>
@@ -700,17 +691,8 @@ WebLocalFrameImpl::ExecuteScriptInIsolatedWorldAndReturnValue(
CHECK_GT(world_id, 0);
CHECK_LT(world_id, DOMWrapperWorld::kEmbedderWorldIdLimit);
- HeapVector<ScriptSourceCode> sources;
- sources.push_back(source_in);
-
- Vector<v8::Local<v8::Value>> script_results;
- GetFrame()->GetScriptController().ExecuteScriptInIsolatedWorld(
- world_id, sources, &script_results);
-
- if (script_results.size() != 1)
- return v8::Local<v8::Value>();
-
- return v8::Local<v8::Value>::New(ToIsolate(GetFrame()), script_results[0]);
+ return GetFrame()->GetScriptController().ExecuteScriptInIsolatedWorld(
+ world_id, source_in);
}
void WebLocalFrameImpl::SetIsolatedWorldSecurityOrigin(
@@ -898,11 +880,10 @@ bool WebFrame::ScriptCanAccess(WebFrame* target) {
ToCoreFrame(*target), BindingSecurity::ErrorReportOption::kDoNotReport);
}
-void WebLocalFrameImpl::Reload(WebFrameLoadType load_type) {
- // TODO(clamy): Remove this function once RenderFrame calls load for all
- // requests.
+void WebLocalFrameImpl::StartReload(WebFrameLoadType frame_load_type) {
+ // TODO(clamy): Remove this function once RenderFrame calls StartNavigation
+ // for all requests.
DCHECK(GetFrame());
- FrameLoadType frame_load_type = static_cast<FrameLoadType>(load_type);
DCHECK(IsReloadLoadType(frame_load_type));
ResourceRequest request =
GetFrame()->Loader().ResourceRequestForReload(frame_load_type);
@@ -929,7 +910,7 @@ void WebLocalFrameImpl::ReloadLoFiImages() {
GetFrame()->GetDocument()->Fetcher()->ReloadLoFiImages();
}
-void WebLocalFrameImpl::LoadRequest(const WebURLRequest& request) {
+void WebLocalFrameImpl::StartNavigation(const WebURLRequest& request) {
// TODO(clamy): Remove this function once RenderFrame calls CommitNavigation
// for all requests.
DCHECK(GetFrame());
@@ -942,7 +923,7 @@ void WebLocalFrameImpl::LoadRequest(const WebURLRequest& request) {
FrameLoadRequest(
nullptr, request.ToResourceRequest(), /*frame_name=*/AtomicString(),
kCheckContentSecurityPolicy, base::UnguessableToken::Create()),
- kFrameLoadTypeStandard);
+ WebFrameLoadType::kStandard);
}
void WebLocalFrameImpl::CheckCompleted() {
@@ -954,9 +935,10 @@ void WebLocalFrameImpl::LoadHTMLString(const WebData& data,
const WebURL& unreachable_url,
bool replace) {
DCHECK(GetFrame());
- LoadData(data, WebString::FromUTF8("text/html"), WebString::FromUTF8("UTF-8"),
- base_url, unreachable_url, replace, WebFrameLoadType::kStandard,
- WebHistoryItem(), kWebHistoryDifferentDocumentLoad, false);
+ CommitDataNavigation(data, WebString::FromUTF8("text/html"),
+ WebString::FromUTF8("UTF-8"), base_url, unreachable_url,
+ replace, WebFrameLoadType::kStandard, WebHistoryItem(),
+ false, nullptr, WebNavigationTimings());
}
void WebLocalFrameImpl::StopLoading() {
@@ -1055,7 +1037,7 @@ bool WebLocalFrameImpl::FirstRectForCharacterRange(
return false;
IntRect int_rect = FirstRectForRange(range);
rect_in_viewport = WebRect(int_rect);
- rect_in_viewport = GetFrame()->View()->ContentsToViewport(rect_in_viewport);
+ rect_in_viewport = GetFrame()->View()->FrameToViewport(rect_in_viewport);
return true;
}
@@ -1064,9 +1046,10 @@ size_t WebLocalFrameImpl::CharacterIndexForPoint(
if (!GetFrame())
return kNotFound;
- LayoutPoint point = GetFrame()->View()->ViewportToContents(point_in_viewport);
- HitTestResult result = GetFrame()->GetEventHandler().HitTestResultAtPoint(
- point, HitTestRequest::kReadOnly | HitTestRequest::kActive);
+ HitTestLocation location(
+ GetFrame()->View()->ViewportToFrame(point_in_viewport));
+ HitTestResult result = GetFrame()->GetEventHandler().HitTestResultAtLocation(
+ location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
return GetFrame()->Selection().CharacterIndexForPoint(
result.RoundedPointInInnerNodeFrame());
}
@@ -1344,7 +1327,7 @@ void WebLocalFrameImpl::MoveRangeSelectionExtent(const WebPoint& point) {
GetFrame()->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
GetFrame()->Selection().MoveRangeSelectionExtent(
- GetFrame()->View()->ViewportToContents(point));
+ GetFrame()->View()->ViewportToFrame(point));
}
void WebLocalFrameImpl::MoveRangeSelection(
@@ -1361,8 +1344,8 @@ void WebLocalFrameImpl::MoveRangeSelection(
if (granularity == WebFrame::kWordGranularity)
blink_granularity = blink::TextGranularity::kWord;
GetFrame()->Selection().MoveRangeSelection(
- GetFrame()->View()->ViewportToContents(base_in_viewport),
- GetFrame()->View()->ViewportToContents(extent_in_viewport),
+ GetFrame()->View()->ViewportToFrame(base_in_viewport),
+ GetFrame()->View()->ViewportToFrame(extent_in_viewport),
blink_granularity);
}
@@ -1373,7 +1356,7 @@ void WebLocalFrameImpl::MoveCaretSelection(const WebPoint& point_in_viewport) {
// needs to be audited. see http://crbug.com/590369 for more details.
GetFrame()->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
const IntPoint point_in_contents =
- GetFrame()->View()->ViewportToContents(point_in_viewport);
+ GetFrame()->View()->ViewportToFrame(point_in_viewport);
GetFrame()->Selection().MoveCaretSelection(point_in_contents);
}
@@ -1462,7 +1445,7 @@ void WebLocalFrameImpl::SetCaretVisible(bool visible) {
VisiblePosition WebLocalFrameImpl::VisiblePositionForViewportPoint(
const WebPoint& point_in_viewport) {
return VisiblePositionForContentsPoint(
- GetFrame()->View()->ViewportToContents(point_in_viewport), GetFrame());
+ GetFrame()->View()->ViewportToFrame(point_in_viewport), GetFrame());
}
WebPlugin* WebLocalFrameImpl::FocusedPluginIfInputMethodSupported() {
@@ -1547,7 +1530,7 @@ float WebLocalFrameImpl::GetPrintPageShrink(int page) {
return print_context_->GetPageShrink(page);
}
-float WebLocalFrameImpl::PrintPage(int page, WebCanvas* canvas) {
+float WebLocalFrameImpl::PrintPage(int page, cc::PaintCanvas* canvas) {
DCHECK(print_context_);
DCHECK_GE(page, 0);
DCHECK(GetFrame());
@@ -1616,7 +1599,7 @@ WebString WebLocalFrameImpl::PageProperty(const WebString& property_name,
}
void WebLocalFrameImpl::PrintPagesForTesting(
- WebCanvas* canvas,
+ cc::PaintCanvas* canvas,
const WebSize& page_size_in_pixels) {
DCHECK(print_context_);
@@ -1644,7 +1627,7 @@ WebString WebLocalFrameImpl::GetLayerTreeAsTextForTesting(
WebLocalFrame* WebLocalFrame::CreateMainFrame(
WebView* web_view,
- WebFrameClient* client,
+ WebLocalFrameClient* client,
InterfaceRegistry* interface_registry,
WebFrame* opener,
const WebString& name,
@@ -1654,7 +1637,7 @@ WebLocalFrame* WebLocalFrame::CreateMainFrame(
}
WebLocalFrame* WebLocalFrame::CreateProvisional(
- WebFrameClient* client,
+ WebLocalFrameClient* client,
InterfaceRegistry* interface_registry,
WebRemoteFrame* old_web_frame,
WebSandboxFlags flags,
@@ -1665,7 +1648,7 @@ WebLocalFrame* WebLocalFrame::CreateProvisional(
WebLocalFrameImpl* WebLocalFrameImpl::Create(
WebTreeScopeType scope,
- WebFrameClient* client,
+ WebLocalFrameClient* client,
blink::InterfaceRegistry* interface_registry,
WebFrame* opener) {
WebLocalFrameImpl* frame =
@@ -1676,7 +1659,7 @@ WebLocalFrameImpl* WebLocalFrameImpl::Create(
WebLocalFrameImpl* WebLocalFrameImpl::CreateMainFrame(
WebView* web_view,
- WebFrameClient* client,
+ WebLocalFrameClient* client,
InterfaceRegistry* interface_registry,
WebFrame* opener,
const WebString& name,
@@ -1694,7 +1677,7 @@ WebLocalFrameImpl* WebLocalFrameImpl::CreateMainFrame(
}
WebLocalFrameImpl* WebLocalFrameImpl::CreateProvisional(
- WebFrameClient* client,
+ WebLocalFrameClient* client,
blink::InterfaceRegistry* interface_registry,
WebRemoteFrame* old_web_frame,
WebSandboxFlags flags,
@@ -1739,7 +1722,7 @@ WebLocalFrameImpl* WebLocalFrameImpl::CreateProvisional(
WebLocalFrameImpl* WebLocalFrameImpl::CreateLocalChild(
WebTreeScopeType scope,
- WebFrameClient* client,
+ WebLocalFrameClient* client,
blink::InterfaceRegistry* interface_registry) {
WebLocalFrameImpl* frame =
new WebLocalFrameImpl(scope, client, interface_registry);
@@ -1749,7 +1732,7 @@ WebLocalFrameImpl* WebLocalFrameImpl::CreateLocalChild(
WebLocalFrameImpl::WebLocalFrameImpl(
WebTreeScopeType scope,
- WebFrameClient* client,
+ WebLocalFrameClient* client,
blink::InterfaceRegistry* interface_registry)
: WebLocalFrame(scope),
client_(client),
@@ -1768,7 +1751,7 @@ WebLocalFrameImpl::WebLocalFrameImpl(
WebLocalFrameImpl::WebLocalFrameImpl(
WebRemoteFrame* old_web_frame,
- WebFrameClient* client,
+ WebLocalFrameClient* client,
blink::InterfaceRegistry* interface_registry)
: WebLocalFrameImpl(old_web_frame->InShadowTree()
? WebTreeScopeType::kShadow
@@ -1941,12 +1924,10 @@ WebViewImpl* WebLocalFrameImpl::ViewImpl() const {
void WebLocalFrameImpl::DidFail(const ResourceError& error,
bool was_provisional,
- HistoryCommitType commit_type) {
+ WebHistoryCommitType web_commit_type) {
if (!Client())
return;
WebURLError web_error = error;
- WebHistoryCommitType web_commit_type =
- static_cast<WebHistoryCommitType>(commit_type);
if (WebPluginContainerImpl* plugin = GetFrame()->GetWebPluginContainer())
plugin->DidFailLoading(error);
@@ -1986,9 +1967,10 @@ HitTestResult WebLocalFrameImpl::HitTestResultForVisualViewportPos(
IntPoint root_frame_point(
GetFrame()->GetPage()->GetVisualViewport().ViewportToRootFrame(
pos_in_viewport));
- IntPoint doc_point(GetFrame()->View()->RootFrameToContents(root_frame_point));
- HitTestResult result = GetFrame()->GetEventHandler().HitTestResultAtPoint(
- doc_point, HitTestRequest::kReadOnly | HitTestRequest::kActive);
+ HitTestLocation location(
+ GetFrame()->View()->ConvertFromRootFrame(root_frame_point));
+ HitTestResult result = GetFrame()->GetEventHandler().HitTestResultAtLocation(
+ location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
result.SetToShadowHostIfInRestrictedShadowRoot();
return result;
}
@@ -2042,9 +2024,10 @@ void WebLocalFrameImpl::CommitNavigation(
const WebURLRequest& request,
WebFrameLoadType web_frame_load_type,
const WebHistoryItem& item,
- WebHistoryLoadType web_history_load_type,
bool is_client_redirect,
- const base::UnguessableToken& devtools_navigation_token) {
+ const base::UnguessableToken& devtools_navigation_token,
+ std::unique_ptr<WebDocumentLoader::ExtraData> extra_data,
+ const WebNavigationTimings& navigation_timings) {
DCHECK(GetFrame());
DCHECK(!request.IsNull());
DCHECK(!request.Url().ProtocolIs("javascript"));
@@ -2059,9 +2042,9 @@ void WebLocalFrameImpl::CommitNavigation(
if (is_client_redirect)
frame_request.SetClientRedirect(ClientRedirectPolicy::kClientRedirect);
HistoryItem* history_item = item;
- GetFrame()->Loader().CommitNavigation(
- frame_request, static_cast<FrameLoadType>(web_frame_load_type),
- history_item, static_cast<HistoryLoadType>(web_history_load_type));
+ GetFrame()->Loader().CommitNavigation(frame_request, web_frame_load_type,
+ history_item, std::move(extra_data),
+ navigation_timings);
}
blink::mojom::CommitResult WebLocalFrameImpl::CommitSameDocumentNavigation(
@@ -2074,7 +2057,7 @@ blink::mojom::CommitResult WebLocalFrameImpl::CommitSameDocumentNavigation(
HistoryItem* history_item = item;
return GetFrame()->Loader().CommitSameDocumentNavigation(
- url, static_cast<FrameLoadType>(web_frame_load_type), history_item,
+ url, web_frame_load_type, history_item,
is_client_redirect ? ClientRedirectPolicy::kClientRedirect
: ClientRedirectPolicy::kNotClientRedirect);
}
@@ -2118,16 +2101,18 @@ void WebLocalFrameImpl::LoadJavaScriptURL(const WebURL& url) {
}
}
-void WebLocalFrameImpl::LoadData(const WebData& data,
- const WebString& mime_type,
- const WebString& text_encoding,
- const WebURL& base_url,
- const WebURL& unreachable_url,
- bool replace,
- WebFrameLoadType web_frame_load_type,
- const WebHistoryItem& item,
- WebHistoryLoadType web_history_load_type,
- bool is_client_redirect) {
+void WebLocalFrameImpl::CommitDataNavigation(
+ const WebData& data,
+ const WebString& mime_type,
+ const WebString& text_encoding,
+ const WebURL& base_url,
+ const WebURL& unreachable_url,
+ bool replace,
+ WebFrameLoadType web_frame_load_type,
+ const WebHistoryItem& item,
+ bool is_client_redirect,
+ std::unique_ptr<WebDocumentLoader::ExtraData> navigation_data,
+ const WebNavigationTimings& navigation_timings) {
DCHECK(GetFrame());
// If we are loading substitute data to replace an existing load, then
@@ -2145,7 +2130,8 @@ void WebLocalFrameImpl::LoadData(const WebData& data,
// When replacing a failed back/forward provisional navigation with an error
// page, retain the HistoryItem for the failed provisional navigation
// and reuse it for the error page navigation.
- if (provisional_document_loader->LoadType() == kFrameLoadTypeBackForward &&
+ if (provisional_document_loader->LoadType() ==
+ WebFrameLoadType::kBackForward &&
provisional_document_loader->GetHistoryItem()) {
history_item = provisional_document_loader->GetHistoryItem();
web_frame_load_type = WebFrameLoadType::kBackForward;
@@ -2163,8 +2149,8 @@ void WebLocalFrameImpl::LoadData(const WebData& data,
frame_request.SetClientRedirect(ClientRedirectPolicy::kClientRedirect);
GetFrame()->Loader().CommitNavigation(
- frame_request, static_cast<FrameLoadType>(web_frame_load_type),
- history_item, static_cast<HistoryLoadType>(web_history_load_type));
+ frame_request, web_frame_load_type, history_item,
+ std::move(navigation_data), navigation_timings);
}
WebLocalFrame::FallbackContentResult
@@ -2455,8 +2441,8 @@ void WebLocalFrameImpl::ExtractSmartClipData(WebRect rect_in_viewport,
WebPoint end_point(rect_in_viewport.x + rect_in_viewport.width,
rect_in_viewport.y + rect_in_viewport.height);
clip_html = CreateMarkupInRect(
- GetFrame(), GetFrame()->View()->ViewportToContents(start_point),
- GetFrame()->View()->ViewportToContents(end_point));
+ GetFrame(), GetFrame()->View()->ViewportToFrame(start_point),
+ GetFrame()->View()->ViewportToFrame(end_point));
}
// TODO(editing-dev): We should move |CreateMarkupInRect()| to
@@ -2502,6 +2488,47 @@ void WebLocalFrameImpl::AdvanceFocusInForm(WebFocusType focus_type) {
next_element->focus();
}
+void WebLocalFrameImpl::PerformMediaPlayerAction(
+ const WebPoint& location,
+ const WebMediaPlayerAction& action) {
+ HitTestResult result = HitTestResultForVisualViewportPos(location);
+ Node* node = result.InnerNode();
+ if (!IsHTMLVideoElement(*node) && !IsHTMLAudioElement(*node))
+ return;
+
+ HTMLMediaElement* media_element = ToHTMLMediaElement(node);
+ switch (action.type) {
+ case WebMediaPlayerAction::kPlay:
+ if (action.enable)
+ media_element->Play();
+ else
+ media_element->pause();
+ break;
+ case WebMediaPlayerAction::kMute:
+ media_element->setMuted(action.enable);
+ break;
+ case WebMediaPlayerAction::kLoop:
+ media_element->SetLoop(action.enable);
+ break;
+ case WebMediaPlayerAction::kControls:
+ media_element->SetBooleanAttribute(HTMLNames::controlsAttr,
+ action.enable);
+ break;
+ case WebMediaPlayerAction::kPictureInPicture:
+ DCHECK(media_element->IsHTMLVideoElement());
+ if (action.enable) {
+ PictureInPictureController::From(node->GetDocument())
+ .EnterPictureInPicture(ToHTMLVideoElement(media_element), nullptr);
+ } else {
+ PictureInPictureController::From(node->GetDocument())
+ .ExitPictureInPicture(ToHTMLVideoElement(media_element), nullptr);
+ }
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
void WebLocalFrameImpl::SetTextCheckClient(
WebTextCheckClient* text_check_client) {
text_check_client_ = text_check_client;
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 0adc92eb48f..feb4b14bc8e 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
@@ -34,6 +34,7 @@
#include "base/single_thread_task_runner.h"
#include "third_party/blink/public/platform/web_file_system_type.h"
#include "third_party/blink/public/web/devtools_agent.mojom-blink.h"
+#include "third_party/blink/public/web/web_history_commit_type.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/editing/forward.h"
@@ -60,7 +61,7 @@ class WebAssociatedURLLoader;
struct WebAssociatedURLLoaderOptions;
class WebAutofillClient;
class WebDevToolsAgentImpl;
-class WebFrameClient;
+class WebLocalFrameClient;
class WebFrameWidgetBase;
class WebNode;
class WebPerformance;
@@ -145,10 +146,10 @@ class CORE_EXPORT WebLocalFrameImpl final
v8::Local<v8::Value> argv[]) override;
v8::Local<v8::Context> MainWorldScriptContext() const override;
v8::Local<v8::Object> GlobalProxy() const override;
- void Reload(WebFrameLoadType) override;
+ void StartReload(WebFrameLoadType) override;
void ReloadImage(const WebNode&) override;
void ReloadLoFiImages() override;
- void LoadRequest(const WebURLRequest&) override;
+ void StartNavigation(const WebURLRequest&) override;
void CheckCompleted() override;
void LoadHTMLString(const WebData& html,
const WebURL& base_url,
@@ -214,7 +215,7 @@ class CORE_EXPORT WebLocalFrameImpl final
void DispatchBeforePrintEvent() override;
int PrintBegin(const WebPrintParams&,
const WebNode& constrain_to_node) override;
- float PrintPage(int page_to_print, WebCanvas*) override;
+ float PrintPage(int page_to_print, cc::PaintCanvas*) override;
float GetPrintPageShrink(int page) override;
void PrintEnd() override;
void DispatchAfterPrintEvent() override;
@@ -231,7 +232,7 @@ class CORE_EXPORT WebLocalFrameImpl final
int& margin_left) override;
WebString PageProperty(const WebString& property_name,
int page_index) override;
- void PrintPagesForTesting(WebCanvas*, const WebSize&) override;
+ void PrintPagesForTesting(cc::PaintCanvas*, const WebSize&) override;
void DispatchMessageEventWithOriginCheck(
const WebSecurityOrigin& intended_target_origin,
@@ -243,11 +244,11 @@ class CORE_EXPORT WebLocalFrameImpl final
WebString GetLayerTreeAsTextForTesting(
bool show_debug_info = false) const override;
- WebFrameClient* Client() const override { return client_; }
+ WebLocalFrameClient* Client() const override { return client_; }
// WebLocalFrame methods:
WebLocalFrameImpl* CreateLocalChild(WebTreeScopeType,
- WebFrameClient*,
+ WebLocalFrameClient*,
blink::InterfaceRegistry*) override;
void SetAutofillClient(WebAutofillClient*) override;
WebAutofillClient* AutofillClient() override;
@@ -261,25 +262,28 @@ class CORE_EXPORT WebLocalFrameImpl final
const WebURLRequest&,
WebFrameLoadType,
const WebHistoryItem&,
- WebHistoryLoadType,
bool is_client_redirect,
- const base::UnguessableToken& devtools_navigation_token) override;
+ const base::UnguessableToken& devtools_navigation_token,
+ std::unique_ptr<WebDocumentLoader::ExtraData> extra_data,
+ const WebNavigationTimings& navigation_timings) override;
blink::mojom::CommitResult CommitSameDocumentNavigation(
const WebURL&,
WebFrameLoadType,
const WebHistoryItem&,
bool is_client_redirect) override;
void LoadJavaScriptURL(const WebURL&) override;
- void LoadData(const WebData&,
- const WebString& mime_type,
- const WebString& text_encoding,
- const WebURL& base_url,
- const WebURL& unreachable_url,
- bool replace,
- WebFrameLoadType,
- const WebHistoryItem&,
- WebHistoryLoadType,
- bool is_client_redirect) override;
+ void CommitDataNavigation(
+ const WebData&,
+ const WebString& mime_type,
+ const WebString& text_encoding,
+ const WebURL& base_url,
+ const WebURL& unreachable_url,
+ bool replace,
+ WebFrameLoadType,
+ const WebHistoryItem&,
+ bool is_client_redirect,
+ std::unique_ptr<WebDocumentLoader::ExtraData> navigation_data,
+ const WebNavigationTimings& navigation_timings) override;
FallbackContentResult MaybeRenderFallbackContent(
const WebURLError&) const override;
void ReportContentSecurityPolicyViolation(
@@ -322,13 +326,13 @@ class CORE_EXPORT WebLocalFrameImpl final
FrameScheduler* Scheduler() const override;
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) override;
WebInputMethodController* GetInputMethodController() override;
-
void ExtractSmartClipData(WebRect rect_in_viewport,
WebString& clip_text,
WebString& clip_html,
WebRect& clip_rect) override;
-
void AdvanceFocusInForm(WebFocusType) override;
+ void PerformMediaPlayerAction(const WebPoint&,
+ const WebMediaPlayerAction&) override;
void InitializeCoreFrame(Page&, FrameOwner*, const AtomicString& name);
LocalFrame* GetFrame() const { return frame_.Get(); }
@@ -337,16 +341,16 @@ class CORE_EXPORT WebLocalFrameImpl final
void WillDetachParent();
static WebLocalFrameImpl* Create(WebTreeScopeType,
- WebFrameClient*,
+ WebLocalFrameClient*,
InterfaceRegistry*,
WebFrame* opener);
static WebLocalFrameImpl* CreateMainFrame(WebView*,
- WebFrameClient*,
+ WebLocalFrameClient*,
InterfaceRegistry*,
WebFrame* opener,
const WebString& name,
WebSandboxFlags);
- static WebLocalFrameImpl* CreateProvisional(WebFrameClient*,
+ static WebLocalFrameImpl* CreateProvisional(WebLocalFrameClient*,
InterfaceRegistry*,
WebRemoteFrame*,
WebSandboxFlags,
@@ -384,7 +388,9 @@ class CORE_EXPORT WebLocalFrameImpl final
// allows us to navigate by pressing Enter after closing the Find box.
void SetFindEndstateFocusAndSelection();
- void DidFail(const ResourceError&, bool was_provisional, HistoryCommitType);
+ void DidFail(const ResourceError&,
+ bool was_provisional,
+ WebHistoryCommitType);
void DidFinish();
// Sets whether the WebLocalFrameImpl allows its document to be scrolled.
@@ -392,7 +398,7 @@ class CORE_EXPORT WebLocalFrameImpl final
// Otherwise, disallow scrolling.
void SetCanHaveScrollbars(bool) override;
- void SetClient(WebFrameClient* client) { client_ = client; }
+ void SetClient(WebLocalFrameClient* client) { client_ = client; }
WebFrameWidgetBase* FrameWidgetImpl() { return frame_widget_; }
@@ -439,10 +445,10 @@ class CORE_EXPORT WebLocalFrameImpl final
friend LocalFrameClientImpl;
WebLocalFrameImpl(WebTreeScopeType,
- WebFrameClient*,
+ WebLocalFrameClient*,
blink::InterfaceRegistry*);
WebLocalFrameImpl(WebRemoteFrame*,
- WebFrameClient*,
+ WebLocalFrameClient*,
blink::InterfaceRegistry*);
// Sets the local core frame and registers destruction observers.
@@ -458,7 +464,7 @@ class CORE_EXPORT WebLocalFrameImpl final
HitTestResult HitTestResultForVisualViewportPos(const IntPoint&);
WebPlugin* FocusedPluginIfInputMethodSupported();
- ScrollableArea* LayoutViewportScrollableArea() const;
+ ScrollableArea* LayoutViewport() const;
// A helper for DispatchBeforePrintEvent() and DispatchAfterPrintEvent().
void DispatchPrintEventRecursively(const AtomicString& event_type);
@@ -467,7 +473,7 @@ class CORE_EXPORT WebLocalFrameImpl final
void BindDevToolsAgentRequest(mojom::blink::DevToolsAgentAssociatedRequest);
- WebFrameClient* client_;
+ WebLocalFrameClient* client_;
// TODO(dcheng): Inline this field directly rather than going through Member.
const Member<LocalFrameClientImpl> local_frame_client_;
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 a0a8817a1c4..38324af6730 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
@@ -7,7 +7,6 @@
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom-blink.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
-#include "third_party/blink/renderer/platform/exported/web_active_gesture_animation.h"
namespace blink {
@@ -71,8 +70,9 @@ void WebViewFrameWidget::UpdateAllLifecyclePhasesAndCompositeForTesting() {
web_view_->UpdateAllLifecyclePhasesAndCompositeForTesting();
}
-void WebViewFrameWidget::Paint(WebCanvas* canvas, const WebRect& view_port) {
- return web_view_->Paint(canvas, view_port);
+void WebViewFrameWidget::PaintContent(cc::PaintCanvas* canvas,
+ const WebRect& view_port) {
+ return web_view_->PaintContent(canvas, view_port);
}
void WebViewFrameWidget::LayoutAndPaintAsync(base::OnceClosure callback) {
@@ -149,8 +149,8 @@ WebPagePopup* WebViewFrameWidget::GetPagePopup() const {
}
void WebViewFrameWidget::UpdateBrowserControlsState(
- WebBrowserControlsState constraints,
- WebBrowserControlsState current,
+ cc::BrowserControlsState constraints,
+ cc::BrowserControlsState current,
bool animate) {
return web_view_->UpdateBrowserControlsState(constraints, current, animate);
}
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 66251eae62e..d8d8ecdfe74 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
@@ -50,7 +50,7 @@ class CORE_EXPORT WebViewFrameWidget : public WebFrameWidgetBase {
void BeginFrame(base::TimeTicks last_frame_time) override;
void UpdateLifecycle(LifecycleUpdate requested_update) override;
void UpdateAllLifecyclePhasesAndCompositeForTesting() override;
- void Paint(WebCanvas*, const WebRect& view_port) override;
+ void PaintContent(cc::PaintCanvas*, const WebRect& view_port) override;
void LayoutAndPaintAsync(base::OnceClosure callback) override;
void CompositeAndReadbackAsync(
base::OnceCallback<void(const SkBitmap&)>) override;
@@ -74,8 +74,8 @@ class CORE_EXPORT WebViewFrameWidget : public WebFrameWidgetBase {
void WillCloseLayerTreeView() override;
SkColor BackgroundColor() const override;
WebPagePopup* GetPagePopup() const override;
- void UpdateBrowserControlsState(WebBrowserControlsState constraints,
- WebBrowserControlsState current,
+ void UpdateBrowserControlsState(cc::BrowserControlsState constraints,
+ cc::BrowserControlsState current,
bool animate) override;
void SetVisibilityState(mojom::PageVisibilityState) override;
void SetBackgroundColorOverride(SkColor) override;
diff --git a/chromium/third_party/blink/renderer/core/frame/window.idl b/chromium/third_party/blink/renderer/core/frame/window.idl
index a09665a4de4..2b97ed831cd 100644
--- a/chromium/third_party/blink/renderer/core/frame/window.idl
+++ b/chromium/third_party/blink/renderer/core/frame/window.idl
@@ -74,7 +74,7 @@
[CrossOrigin, Custom=Setter] attribute Window opener;
[Replaceable, CrossOrigin] readonly attribute Window? parent;
[CheckSecurity=ReturnValue, Custom=Getter] readonly attribute Element? frameElement;
- [CallWith=(ExecutionContext,CurrentWindow,EnteredWindow), RaisesException] Window? open(optional [TreatNullAs=EmptyString] USVString url="", optional DOMString target = "_blank", optional [TreatNullAs=EmptyString] DOMString features = "");
+ [CallWith=(ExecutionContext,CurrentWindow,EnteredWindow), RaisesException] Window? open(optional [TreatNullAs=EmptyString] URLString url="", optional DOMString target = "_blank", optional [TreatNullAs=EmptyString] DOMString features = "");
// indexed properties
// https://html.spec.whatwg.org/C/browsers.html#windowproxy-getownproperty
@@ -100,7 +100,9 @@
[Measure] long requestIdleCallback(IdleRequestCallback callback, optional IdleRequestOptions options);
void cancelIdleCallback(long handle);
- [CrossOrigin, Custom, RaisesException] void postMessage(any message, DOMString targetOrigin, optional sequence<object> transfer = []);
+ [CrossOrigin, CallWith=CurrentWindow, RaisesException] void postMessage(any message, USVString targetOrigin, optional sequence<object> transfer = []);
+
+ [CrossOrigin, CallWith=CurrentWindow, RaisesException, RuntimeEnabled=WindowPostMessageOptions] void postMessage(any message, optional sequence<object> transfer = [], optional WindowPostMessageOptions options);
// Custom elements
// https://w3c.github.io/webcomponents/spec/custom/#custom-elements-api
diff --git a/chromium/third_party/blink/renderer/core/frame/window_post_message_options.idl b/chromium/third_party/blink/renderer/core/frame/window_post_message_options.idl
new file mode 100644
index 00000000000..da0e1961654
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/frame/window_post_message_options.idl
@@ -0,0 +1,9 @@
+// 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.
+
+// https://github.com/dtapuska/useractivation
+
+dictionary WindowPostMessageOptions {
+ USVString targetOrigin = "/";
+};
diff --git a/chromium/third_party/blink/renderer/core/fullscreen/document_fullscreen.cc b/chromium/third_party/blink/renderer/core/fullscreen/document_fullscreen.cc
index e82c548cb4e..9ae4c2287d5 100644
--- a/chromium/third_party/blink/renderer/core/fullscreen/document_fullscreen.cc
+++ b/chromium/third_party/blink/renderer/core/fullscreen/document_fullscreen.cc
@@ -37,8 +37,14 @@ Element* DocumentFullscreen::fullscreenElement(Document& document) {
return Fullscreen::FullscreenElementForBindingFrom(document);
}
-void DocumentFullscreen::exitFullscreen(Document& document) {
- Fullscreen::ExitFullscreen(document);
+ScriptPromise DocumentFullscreen::exitFullscreen(ScriptState* script_state,
+ Document& document) {
+ return Fullscreen::ExitFullscreen(document, script_state);
+}
+
+void DocumentFullscreen::webkitExitFullscreen(Document& document) {
+ ScriptPromise promise = Fullscreen::ExitFullscreen(document);
+ DCHECK(promise.IsEmpty());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fullscreen/document_fullscreen.h b/chromium/third_party/blink/renderer/core/fullscreen/document_fullscreen.h
index 7b4895e2b5d..1b73f7b106c 100644
--- a/chromium/third_party/blink/renderer/core/fullscreen/document_fullscreen.h
+++ b/chromium/third_party/blink/renderer/core/fullscreen/document_fullscreen.h
@@ -26,7 +26,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FULLSCREEN_DOCUMENT_FULLSCREEN_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FULLSCREEN_DOCUMENT_FULLSCREEN_H_
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
namespace blink {
@@ -40,7 +42,8 @@ class DocumentFullscreen {
public:
static bool fullscreenEnabled(Document&);
static Element* fullscreenElement(Document&);
- static void exitFullscreen(Document&);
+ static ScriptPromise exitFullscreen(ScriptState*, Document&);
+ static void webkitExitFullscreen(Document&);
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(fullscreenchange);
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(fullscreenerror);
diff --git a/chromium/third_party/blink/renderer/core/fullscreen/document_fullscreen.idl b/chromium/third_party/blink/renderer/core/fullscreen/document_fullscreen.idl
index de3a8a2906f..c99b47569f2 100644
--- a/chromium/third_party/blink/renderer/core/fullscreen/document_fullscreen.idl
+++ b/chromium/third_party/blink/renderer/core/fullscreen/document_fullscreen.idl
@@ -24,9 +24,10 @@
[
ImplementedAs=DocumentFullscreen
] partial interface Document {
- [RuntimeEnabled=FullscreenUnprefixed] readonly attribute boolean fullscreenEnabled;
+ [LenientSetter, RuntimeEnabled=FullscreenUnprefixed] readonly attribute boolean fullscreenEnabled;
+ [LenientSetter, Unscopable, RuntimeEnabled=FullscreenUnprefixed, ImplementedAs=fullscreenElement] readonly attribute boolean fullscreen;
- [RuntimeEnabled=FullscreenUnprefixed] void exitFullscreen();
+ [CallWith=ScriptState, RuntimeEnabled=FullscreenUnprefixed] Promise<void> exitFullscreen();
[RuntimeEnabled=FullscreenUnprefixed] attribute EventHandler onfullscreenchange;
[RuntimeEnabled=FullscreenUnprefixed] attribute EventHandler onfullscreenerror;
@@ -34,12 +35,12 @@
// Mozilla version
[MeasureAs=PrefixedDocumentIsFullscreen, ImplementedAs=fullscreenElement] readonly attribute boolean webkitIsFullScreen;
[MeasureAs=PrefixedDocumentCurrentFullScreenElement, ImplementedAs=fullscreenElement] readonly attribute Element webkitCurrentFullScreenElement;
- [MeasureAs=PrefixedDocumentCancelFullScreen, ImplementedAs=exitFullscreen] void webkitCancelFullScreen();
+ [MeasureAs=PrefixedDocumentCancelFullScreen, ImplementedAs=webkitExitFullscreen] void webkitCancelFullScreen();
// W3C version
[MeasureAs=PrefixedDocumentFullscreenEnabled, ImplementedAs=fullscreenEnabled] readonly attribute boolean webkitFullscreenEnabled;
[MeasureAs=PrefixedDocumentFullscreenElement, ImplementedAs=fullscreenElement] readonly attribute Element webkitFullscreenElement;
- [MeasureAs=PrefixedDocumentExitFullscreen, ImplementedAs=exitFullscreen] void webkitExitFullscreen();
+ [MeasureAs=PrefixedDocumentExitFullscreen, ImplementedAs=webkitExitFullscreen] void webkitExitFullscreen();
attribute EventHandler onwebkitfullscreenchange;
attribute EventHandler onwebkitfullscreenerror;
diff --git a/chromium/third_party/blink/renderer/core/fullscreen/element_fullscreen.cc b/chromium/third_party/blink/renderer/core/fullscreen/element_fullscreen.cc
index 8d0509b9e29..2f38e2099e9 100644
--- a/chromium/third_party/blink/renderer/core/fullscreen/element_fullscreen.cc
+++ b/chromium/third_party/blink/renderer/core/fullscreen/element_fullscreen.cc
@@ -9,10 +9,12 @@
namespace blink {
-void ElementFullscreen::requestFullscreen(Element& element,
- const FullscreenOptions& options) {
- Fullscreen::RequestFullscreen(element, options,
- Fullscreen::RequestType::kUnprefixed);
+ScriptPromise ElementFullscreen::requestFullscreen(
+ ScriptState* script_state,
+ Element& element,
+ const FullscreenOptions& options) {
+ return Fullscreen::RequestFullscreen(
+ element, options, Fullscreen::RequestType::kUnprefixed, script_state);
}
void ElementFullscreen::webkitRequestFullscreen(Element& element) {
diff --git a/chromium/third_party/blink/renderer/core/fullscreen/element_fullscreen.h b/chromium/third_party/blink/renderer/core/fullscreen/element_fullscreen.h
index 0d1446daf62..3a7ad9d32f9 100644
--- a/chromium/third_party/blink/renderer/core/fullscreen/element_fullscreen.h
+++ b/chromium/third_party/blink/renderer/core/fullscreen/element_fullscreen.h
@@ -5,8 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FULLSCREEN_ELEMENT_FULLSCREEN_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FULLSCREEN_ELEMENT_FULLSCREEN_H_
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/fullscreen/fullscreen_options.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
namespace blink {
@@ -17,7 +19,9 @@ class ElementFullscreen {
STATIC_ONLY(ElementFullscreen);
public:
- static void requestFullscreen(Element&, const FullscreenOptions&);
+ static ScriptPromise requestFullscreen(ScriptState*,
+ Element&,
+ const FullscreenOptions&);
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(fullscreenchange);
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(fullscreenerror);
diff --git a/chromium/third_party/blink/renderer/core/fullscreen/element_fullscreen.idl b/chromium/third_party/blink/renderer/core/fullscreen/element_fullscreen.idl
index 36c45b32f6b..76d2d9c7b4f 100644
--- a/chromium/third_party/blink/renderer/core/fullscreen/element_fullscreen.idl
+++ b/chromium/third_party/blink/renderer/core/fullscreen/element_fullscreen.idl
@@ -9,7 +9,7 @@
] partial interface Element {
// TODO(dtapuska): If RuntimeEnabled=FullscreenUnprefixed is shipped before RuntimeEnabled=FullscreenOptions
// we need to split the optional FullscreenOptions out controlled by RuntimeEnabled=FullscreenOptions
- [RuntimeEnabled=FullscreenUnprefixed] void requestFullscreen(optional FullscreenOptions options);
+ [CallWith=ScriptState, RuntimeEnabled=FullscreenUnprefixed] Promise<void> requestFullscreen(optional FullscreenOptions options);
[RuntimeEnabled=FullscreenUnprefixed] attribute EventHandler onfullscreenchange;
[RuntimeEnabled=FullscreenUnprefixed] attribute EventHandler onfullscreenerror;
diff --git a/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc b/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc
index 365e652ee20..1cc5721b2ff 100644
--- a/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc
+++ b/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.cc
@@ -31,10 +31,13 @@
#include "base/macros.h"
#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_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/dom/document.h"
#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/hosts_using_features.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
@@ -45,8 +48,6 @@
#include "third_party/blink/renderer/core/html_element_type_helpers.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/layout/layout_block_flow.h"
-#include "third_party/blink/renderer/core/layout/layout_full_screen.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/svg/svg_svg_element.h"
#include "third_party/blink/renderer/platform/bindings/microtask.h"
@@ -57,6 +58,139 @@ namespace blink {
namespace {
+void FullscreenElementChanged(Document& document,
+ Element* old_element,
+ Element* new_element,
+ Fullscreen::RequestType new_request_type) {
+ DCHECK_NE(old_element, new_element);
+
+ document.GetStyleEngine().EnsureUAStyleForFullscreen();
+
+ if (old_element) {
+ DCHECK_NE(old_element, Fullscreen::FullscreenElementFrom(document));
+
+ old_element->PseudoStateChanged(CSSSelector::kPseudoFullScreen);
+
+ old_element->SetContainsFullScreenElement(false);
+ old_element->SetContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(
+ false);
+ }
+
+ if (new_element) {
+ DCHECK_EQ(new_element, Fullscreen::FullscreenElementFrom(document));
+
+ new_element->PseudoStateChanged(CSSSelector::kPseudoFullScreen);
+
+ // OOPIF: For RequestType::PrefixedForCrossProcessDescendant, |new_element|
+ // is the iframe element for the out-of-process frame that contains the
+ // fullscreen element. Hence, it must match :-webkit-full-screen-ancestor.
+ if (new_request_type ==
+ Fullscreen::RequestType::kPrefixedForCrossProcessDescendant) {
+ DCHECK(IsHTMLIFrameElement(new_element));
+ new_element->SetContainsFullScreenElement(true);
+ }
+ new_element->SetContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(
+ true);
+ }
+
+ if (document.GetFrame()) {
+ // SetIsInert recurses through subframes to propagate the inert bit as
+ // needed.
+ document.GetFrame()->SetIsInert(document.LocalOwner() &&
+ document.LocalOwner()->IsInert());
+ }
+
+ // Any element not contained by the fullscreen element is inert (see
+ // |Node::IsInert()|), so changing the fullscreen element will typically
+ // change the inertness of most elements. Clear the entire cache.
+ document.ClearAXObjectCache();
+
+ if (LocalFrame* frame = document.GetFrame()) {
+ // TODO(foolip): Synchronize hover state changes with animation frames.
+ // https://crbug.com/668758
+ frame->GetEventHandler().ScheduleHoverStateUpdate();
+ frame->GetChromeClient().FullscreenElementChanged(old_element, new_element);
+ }
+}
+
+using ElementRequestTypeMap =
+ HeapHashMap<WeakMember<Element>, Fullscreen::RequestType>;
+
+ElementRequestTypeMap& FullscreenFlagMap() {
+ DEFINE_STATIC_LOCAL(ElementRequestTypeMap, map, (new ElementRequestTypeMap));
+ return map;
+}
+
+bool HasFullscreenFlag(Element& element) {
+ return FullscreenFlagMap().Contains(&element);
+}
+
+void SetFullscreenFlag(Element& element, Fullscreen::RequestType request_type) {
+ FullscreenFlagMap().insert(&element, request_type);
+}
+
+void UnsetFullscreenFlag(Element& element) {
+ FullscreenFlagMap().erase(&element);
+}
+
+Fullscreen::RequestType GetRequestType(Element& element) {
+ return FullscreenFlagMap().find(&element)->value;
+}
+
+// https://fullscreen.spec.whatwg.org/#fullscreen-an-element
+void GoFullscreen(Element& element, Fullscreen::RequestType request_type) {
+ Document& document = element.GetDocument();
+ Element* old_element = Fullscreen::FullscreenElementFrom(document);
+
+ // To fullscreen an |element| within a |document|, set the |element|'s
+ // fullscreen flag and add it to |document|'s top layer.
+ DCHECK(!HasFullscreenFlag(element));
+ DCHECK(!element.IsInTopLayer());
+ SetFullscreenFlag(element, request_type);
+ document.AddToTopLayer(&element);
+
+ DCHECK_EQ(&element, Fullscreen::FullscreenElementFrom(document));
+ FullscreenElementChanged(document, old_element, &element, request_type);
+}
+
+// https://fullscreen.spec.whatwg.org/#unfullscreen-an-element
+void Unfullscreen(Element& element) {
+ Document& document = element.GetDocument();
+ Element* old_element = Fullscreen::FullscreenElementFrom(document);
+
+ // To unfullscreen an |element| within a |document|, unset the element's
+ // fullscreen flag and iframe fullscreen flag (if any), and remove it from
+ // |document|'s top layer.
+ DCHECK(element.IsInTopLayer());
+ DCHECK(HasFullscreenFlag(element));
+ UnsetFullscreenFlag(element);
+ document.RemoveFromTopLayer(&element);
+
+ Element* new_element = Fullscreen::FullscreenElementFrom(document);
+ if (old_element != new_element) {
+ Fullscreen::RequestType new_request_type =
+ new_element ? GetRequestType(*new_element)
+ : Fullscreen::RequestType::kUnprefixed;
+ FullscreenElementChanged(document, old_element, new_element,
+ new_request_type);
+ }
+}
+
+// https://fullscreen.spec.whatwg.org/#unfullscreen-a-document
+void Unfullscreen(Document& document) {
+ // To unfullscreen a |document|, unfullscreen all elements, within
+ // |document|'s top layer, whose fullscreen flag is set.
+
+ HeapVector<Member<Element>> fullscreen_elements;
+ for (Element* element : document.TopLayerElements()) {
+ if (HasFullscreenFlag(*element))
+ fullscreen_elements.push_back(element);
+ }
+
+ for (Element* element : fullscreen_elements)
+ Unfullscreen(*element);
+}
+
// https://html.spec.whatwg.org/multipage/embedded-content.html#allowed-to-use
bool AllowedToUseFullscreen(const Frame* frame) {
// To determine whether a Document object |document| is allowed to use the
@@ -66,23 +200,6 @@ bool AllowedToUseFullscreen(const Frame* frame) {
if (!frame)
return false;
- if (!IsSupportedInFeaturePolicy(mojom::FeaturePolicyFeature::kFullscreen)) {
- // 2. If |document|'s browsing context is a top-level browsing context, then
- // return true.
- if (frame->IsMainFrame())
- return true;
-
- // 3. If |document|'s browsing context has a browsing context container that
- // is an iframe element with an |allowattribute| attribute specified, and
- // whose node document is allowed to use the feature indicated by
- // |allowattribute|, then return true.
- if (frame->Owner() && frame->Owner()->AllowFullscreen())
- return AllowedToUseFullscreen(frame->Tree().Parent());
-
- // 4. Return false.
- return false;
- }
-
// 2. If Feature Policy is enabled, return the policy for "fullscreen"
// feature.
return frame->IsFeatureEnabled(mojom::FeaturePolicyFeature::kFullscreen);
@@ -249,9 +366,18 @@ Document& TopmostLocalAncestor(Document& document) {
return document;
}
+size_t CountFullscreenInTopLayer(const Document& document) {
+ size_t count = 0;
+ for (Element* element : document.TopLayerElements()) {
+ if (HasFullscreenFlag(*element))
+ ++count;
+ }
+ return count;
+}
+
// https://fullscreen.spec.whatwg.org/#simple-fullscreen-document
-bool IsSimpleFullscreenDocument(Document& document) {
- return Fullscreen::FullscreenElementStackSizeFrom(document) == 1;
+bool IsSimpleFullscreenDocument(const Document& document) {
+ return CountFullscreenInTopLayer(document) == 1;
}
// https://fullscreen.spec.whatwg.org/#collect-documents-to-unfullscreen
@@ -339,6 +465,11 @@ void EnqueueEvent(const AtomicString& type,
WrapPersistent(&document)));
}
+void DidEnterFullscreenTask(Document* document) {
+ DCHECK(document);
+ Fullscreen::DidEnterFullscreen(*document);
+}
+
} // anonymous namespace
const char Fullscreen::kSupplementName[] = "Fullscreen";
@@ -349,26 +480,30 @@ Fullscreen& Fullscreen::From(Document& document) {
fullscreen = new Fullscreen(document);
ProvideTo(document, fullscreen);
}
-
return *fullscreen;
}
-Fullscreen* Fullscreen::FromIfExistsSlow(Document& document) {
+Fullscreen* Fullscreen::FromIfExists(Document& document) {
+ if (!document.HasFullscreenSupplement())
+ return nullptr;
return Supplement<Document>::From<Fullscreen>(document);
}
Element* Fullscreen::FullscreenElementFrom(Document& document) {
- if (Fullscreen* found = FromIfExists(document))
- return found->FullscreenElement();
- return nullptr;
-}
+ // The fullscreen element is the topmost element in the document's top layer
+ // whose fullscreen flag is set, if any, and null otherwise.
+
+ const auto& elements = document.TopLayerElements();
+ for (auto it = elements.rbegin(); it != elements.rend(); ++it) {
+ Element* element = (*it).Get();
+ if (HasFullscreenFlag(*element))
+ return element;
+ }
-size_t Fullscreen::FullscreenElementStackSizeFrom(Document& document) {
- if (Fullscreen* found = FromIfExists(document))
- return found->fullscreen_element_stack_.size();
- return 0;
+ return nullptr;
}
+// https://fullscreen.spec.whatwg.org/#fullscreen-element
Element* Fullscreen::FullscreenElementForBindingFrom(TreeScope& scope) {
Element* element = FullscreenElementFrom(scope.GetDocument());
if (!element || !RuntimeEnabledFeatures::FullscreenUnprefixedEnabled())
@@ -391,20 +526,11 @@ Element* Fullscreen::FullscreenElementForBindingFrom(TreeScope& scope) {
}
bool Fullscreen::IsInFullscreenElementStack(const Element& element) {
- const Fullscreen* found = FromIfExists(element.GetDocument());
- if (!found)
- return false;
- for (size_t i = 0; i < found->fullscreen_element_stack_.size(); ++i) {
- if (found->fullscreen_element_stack_[i].first.Get() == &element)
- return true;
- }
- return false;
+ return HasFullscreenFlag(const_cast<Element&>(element));
}
Fullscreen::Fullscreen(Document& document)
- : Supplement<Document>(document),
- ContextLifecycleObserver(&document),
- full_screen_layout_object_(nullptr) {
+ : Supplement<Document>(document), ContextLifecycleObserver(&document) {
document.SetHasFullscreenSupplement();
}
@@ -415,11 +541,8 @@ Document* Fullscreen::GetDocument() {
}
void Fullscreen::ContextDestroyed(ExecutionContext*) {
- if (full_screen_layout_object_)
- full_screen_layout_object_->Destroy();
-
pending_requests_.clear();
- fullscreen_element_stack_.clear();
+ pending_exits_.clear();
}
// https://fullscreen.spec.whatwg.org/#dom-element-requestfullscreen
@@ -429,9 +552,10 @@ void Fullscreen::RequestFullscreen(Element& pending) {
RequestFullscreen(pending, FullscreenOptions(), RequestType::kPrefixed);
}
-void Fullscreen::RequestFullscreen(Element& pending,
- const FullscreenOptions& options,
- RequestType request_type) {
+ScriptPromise Fullscreen::RequestFullscreen(Element& pending,
+ const FullscreenOptions& options,
+ RequestType request_type,
+ ScriptState* script_state) {
RequestFullscreenScope scope;
// 1. Let |pending| be the context object.
@@ -440,12 +564,24 @@ void Fullscreen::RequestFullscreen(Element& pending,
Document& document = pending.GetDocument();
// 3. Let |promise| be a new promise.
- // TODO(foolip): Promises. https://crbug.com/644637
+ // For optimization allocate the ScriptPromiseResolver just after step 4.
+ ScriptPromiseResolver* resolver = nullptr;
// 4. If |pendingDoc| is not fully active, then reject |promise| with a
// TypeError exception and return |promise|.
- if (!document.IsActive() || !document.GetFrame())
- return;
+ if (!document.IsActive() || !document.GetFrame()) {
+ if (!script_state)
+ return ScriptPromise();
+ return ScriptPromise::Reject(
+ script_state, V8ThrowException::CreateTypeError(
+ script_state->GetIsolate(), "Document not active"));
+ }
+
+ if (script_state) {
+ // We should only be creating promises for unprefixed variants.
+ DCHECK_EQ(Fullscreen::RequestType::kUnprefixed, request_type);
+ resolver = ScriptPromiseResolver::Create(script_state);
+ }
bool for_cross_process_descendant =
request_type == RequestType::kPrefixedForCrossProcessDescendant;
@@ -474,6 +610,7 @@ void Fullscreen::RequestFullscreen(Element& pending,
error = true;
// 7. Return |promise|, and run the remaining steps in parallel.
+ ScriptPromise promise = resolver ? resolver->Promise() : ScriptPromise();
// 8. If |error| is false: Resize |pendingDoc|'s top-level browsing context's
// document's viewport's dimensions to match the dimensions of the screen of
@@ -486,7 +623,7 @@ void Fullscreen::RequestFullscreen(Element& pending,
}
From(document).pending_requests_.push_back(
- std::make_pair(&pending, request_type));
+ new PendingRequest(&pending, request_type, resolver));
LocalFrame& frame = *document.GetFrame();
frame.GetChromeClient().EnterFullscreen(frame, options);
} else {
@@ -494,36 +631,36 @@ void Fullscreen::RequestFullscreen(Element& pending,
// synchronously because when |error| is true, |ContinueRequestFullscreen()|
// will only queue a task and return. This is indistinguishable from, e.g.,
// enqueueing a microtask to continue at step 9.
- ContinueRequestFullscreen(document, pending, request_type,
+ ContinueRequestFullscreen(document, pending, request_type, resolver,
true /* error */);
}
-}
-void Fullscreen::DidEnterFullscreen() {
- if (!GetDocument())
- return;
+ return promise;
+}
+void Fullscreen::DidEnterFullscreen(Document& document) {
// We may be called synchronously from within
// |FullscreenController::EnterFullscreen()| if we were already fullscreen,
// but must still not synchronously change the fullscreen element. Instead
// enqueue a microtask to continue.
if (RequestFullscreenScope::RunningRequestFullscreen()) {
Microtask::EnqueueMicrotask(
- WTF::Bind(&Fullscreen::DidEnterFullscreen, WrapPersistent(this)));
+ WTF::Bind(DidEnterFullscreenTask, WrapPersistent(&document)));
return;
}
- ElementStack requests;
- requests.swap(pending_requests_);
- for (const ElementStackEntry& request : requests) {
- ContinueRequestFullscreen(*GetDocument(), *request.first, request.second,
- false /* error */);
+ PendingRequests requests;
+ requests.swap(From(document).pending_requests_);
+ for (const Member<PendingRequest>& request : requests) {
+ ContinueRequestFullscreen(document, *request->element(), request->type(),
+ request->resolver(), false /* error */);
}
}
void Fullscreen::ContinueRequestFullscreen(Document& document,
Element& pending,
RequestType request_type,
+ ScriptPromiseResolver* resolver,
bool error) {
DCHECK(document.IsActive());
DCHECK(document.GetFrame());
@@ -543,6 +680,13 @@ void Fullscreen::ContinueRequestFullscreen(Document& document,
// 10.2. Reject |promise| with a TypeError exception and terminate these
// steps.
+ if (resolver) {
+ ScriptState::Scope scope(resolver->GetScriptState());
+ // TODO(dtapuska): Change error to be something useful instead of just a
+ // boolean and return this to the user.
+ resolver->Reject(V8ThrowException::CreateTypeError(
+ resolver->GetScriptState()->GetIsolate(), "fullscreen error"));
+ }
return;
}
@@ -584,9 +728,7 @@ void Fullscreen::ContinueRequestFullscreen(Document& document,
// https://crbug.com/644695
// 13.4. Fullscreen |element| within |doc|.
- // TODO(foolip): Merge fullscreen element stack into top layer.
- // https://crbug.com/627790
- From(doc).PushFullscreenElementStack(*element, request_type);
+ GoFullscreen(*element, request_type);
// 13.5. Append (fullscreenchange, |element|) to |doc|'s list of pending
// fullscreen events.
@@ -594,10 +736,14 @@ void Fullscreen::ContinueRequestFullscreen(Document& document,
}
// 14. Resolve |promise| with undefined.
+ if (resolver) {
+ ScriptState::Scope scope(resolver->GetScriptState());
+ resolver->Resolve();
+ }
}
// https://fullscreen.spec.whatwg.org/#fully-exit-fullscreen
-void Fullscreen::FullyExitFullscreen(Document& document) {
+void Fullscreen::FullyExitFullscreen(Document& document, bool ua_originated) {
// TODO(foolip): The spec used to have a first step saying "Let |doc| be the
// top-level browsing context's document" which was removed in
// https://github.com/whatwg/fullscreen/commit/3243119d027a8ff5b80998eb1f17f8eba148a346.
@@ -605,28 +751,45 @@ void Fullscreen::FullyExitFullscreen(Document& document) {
Document& doc = TopmostLocalAncestor(document);
// 1. If |document|'s fullscreen element is null, terminate these steps.
- if (!FullscreenElementFrom(doc))
+ Element* fullscreen_element = FullscreenElementFrom(doc);
+ if (!fullscreen_element)
return;
// 2. Unfullscreen elements whose fullscreen flag is set, within
// |document|'s top layer, except for |document|'s fullscreen element.
- size_t stack_size = From(doc).fullscreen_element_stack_.size();
- From(doc).fullscreen_element_stack_.EraseAt(0, stack_size - 1);
- DCHECK_EQ(From(doc).fullscreen_element_stack_.size(), 1u);
+ HeapVector<Member<Element>> unfullscreen_elements;
+ for (Element* element : doc.TopLayerElements()) {
+ if (HasFullscreenFlag(*element) && element != fullscreen_element)
+ unfullscreen_elements.push_back(element);
+ }
+ for (Element* element : unfullscreen_elements)
+ Unfullscreen(*element);
+ DCHECK(IsSimpleFullscreenDocument(doc));
// 3. Exit fullscreen |document|.
- ExitFullscreen(doc);
+ ExitFullscreen(doc, nullptr, ua_originated);
}
// https://fullscreen.spec.whatwg.org/#exit-fullscreen
-void Fullscreen::ExitFullscreen(Document& doc) {
+ScriptPromise Fullscreen::ExitFullscreen(Document& doc,
+ ScriptState* script_state,
+ bool ua_originated) {
// 1. Let |promise| be a new promise.
- // TODO(foolip): Promises. https://crbug.com/644637
+ // ScriptPromiseResolver is allocated after step 2.
+ ScriptPromiseResolver* resolver = nullptr;
// 2. If |doc| is not fully active or |doc|'s fullscreen element is null, then
// reject |promise| with a TypeError exception and return |promise|.
- if (!doc.IsActive() || !doc.GetFrame() || !FullscreenElementFrom(doc))
- return;
+ if (!doc.IsActive() || !doc.GetFrame() || !FullscreenElementFrom(doc)) {
+ if (!script_state)
+ return ScriptPromise();
+ return ScriptPromise::Reject(
+ script_state, V8ThrowException::CreateTypeError(
+ script_state->GetIsolate(), "Document not active"));
+ }
+
+ if (script_state)
+ resolver = ScriptPromiseResolver::Create(script_state);
// 3. Let |resize| be false.
bool resize = false;
@@ -655,28 +818,68 @@ void Fullscreen::ExitFullscreen(Document& doc) {
resize = true;
}
+ // 7. If |doc|'s fullscreen element is not connected.
+ Element* element = FullscreenElementFrom(doc);
+ if (!element->isConnected()) {
+ RequestType request_type = GetRequestType(*element);
+
+ // 7.1. Append (fullscreenchange, |doc|'s fullscreen element) to
+ // |doc|'s list of pending fullscreen events.
+ EnqueueEvent(EventTypeNames::fullscreenchange, *element, doc, request_type);
+
+ // 7.2. Unfullscreen |element|.
+ Unfullscreen(*element);
+ }
+
// 7. Return |promise|, and run the remaining steps in parallel.
+ ScriptPromise promise = resolver ? resolver->Promise() : ScriptPromise();
// 8. If |resize| is true, resize |doc|'s viewport to its "normal" dimensions.
if (resize) {
- LocalFrame& frame = *doc.GetFrame();
- frame.GetChromeClient().ExitFullscreen(frame);
+ if (ua_originated) {
+ ContinueExitFullscreen(&doc, resolver, true /* resize */);
+ } else {
+ From(top_level_doc).pending_exits_.push_back(resolver);
+ LocalFrame& frame = *doc.GetFrame();
+ frame.GetChromeClient().ExitFullscreen(frame);
+ }
} else {
+ DCHECK(!ua_originated);
// Note: We are past the "in parallel" point, and |ContinueExitFullscreen()|
// will change script-observable state (document.fullscreenElement)
// synchronously, so we have to continue asynchronously.
- Microtask::EnqueueMicrotask(WTF::Bind(
- ContinueExitFullscreen, WrapWeakPersistent(&doc), false /* resize */));
+ Microtask::EnqueueMicrotask(
+ WTF::Bind(ContinueExitFullscreen, WrapPersistent(&doc),
+ WrapPersistent(resolver), false /* resize */));
}
+ return promise;
}
-void Fullscreen::DidExitFullscreen() {
- ContinueExitFullscreen(GetDocument(), true /* resize */);
+void Fullscreen::DidExitFullscreen(Document& document) {
+ // If this is a response to an ExitFullscreen call then
+ // continue exiting. Otherwise call FullyExitFullscreen.
+ Fullscreen& fullscreen = From(document);
+ PendingExits exits;
+ exits.swap(fullscreen.pending_exits_);
+ if (exits.IsEmpty()) {
+ FullyExitFullscreen(document, true /* ua_originated */);
+ } else {
+ for (const Member<PendingExit>& exit : exits)
+ ContinueExitFullscreen(&document, exit, true /* resize */);
+ }
}
-void Fullscreen::ContinueExitFullscreen(Document* doc, bool resize) {
- if (!doc || !doc->IsActive() || !doc->GetFrame())
+void Fullscreen::ContinueExitFullscreen(Document* doc,
+ ScriptPromiseResolver* resolver,
+ bool resize) {
+ if (!doc || !doc->IsActive() || !doc->GetFrame()) {
+ if (resolver) {
+ ScriptState::Scope scope(resolver->GetScriptState());
+ resolver->Reject(V8ThrowException::CreateTypeError(
+ resolver->GetScriptState()->GetIsolate(), "Document is not active"));
+ }
return;
+ }
if (resize) {
// See comment for step 6.
@@ -685,8 +888,13 @@ void Fullscreen::ContinueExitFullscreen(Document* doc, bool resize) {
// 9. If |doc|'s fullscreen element is null, then resolve |promise| with
// undefined and terminate these steps.
- if (!FullscreenElementFrom(*doc))
+ if (!FullscreenElementFrom(*doc)) {
+ if (resolver) {
+ ScriptState::Scope scope(resolver->GetScriptState());
+ resolver->Resolve();
+ }
return;
+ }
// 10. Let |exitDocs| be the result of collecting documents to unfullscreen
// given |doc|.
@@ -707,42 +915,43 @@ void Fullscreen::ContinueExitFullscreen(Document* doc, bool resize) {
// 12. For each |exitDoc| in |exitDocs|:
for (Document* exit_doc : exit_docs) {
- Fullscreen& fullscreen = From(*exit_doc);
- ElementStack& stack = fullscreen.fullscreen_element_stack_;
- DCHECK(!stack.IsEmpty());
+ Element* exit_element = FullscreenElementFrom(*exit_doc);
+ DCHECK(exit_element);
+ RequestType request_type = GetRequestType(*exit_element);
// 12.1. Append (fullscreenchange, |exitDoc|'s fullscreen element) to
// |exitDoc|'s list of pending fullscreen events.
- EnqueueEvent(EventTypeNames::fullscreenchange, *stack.back().first,
- *exit_doc, stack.back().second);
+ EnqueueEvent(EventTypeNames::fullscreenchange, *exit_element, *exit_doc,
+ request_type);
// 12.2. If |resize| is true, unfullscreen |exitDoc|.
// 12.3. Otherwise, unfullscreen |exitDoc|'s fullscreen element.
- if (resize) {
- while (!stack.IsEmpty())
- fullscreen.PopFullscreenElementStack();
- } else {
- fullscreen.PopFullscreenElementStack();
- }
+ if (resize)
+ Unfullscreen(*exit_doc);
+ else
+ Unfullscreen(*exit_element);
}
// 13. For each |descendantDoc| in |descendantDocs|:
for (Document* descendant_doc : descendant_docs) {
- Fullscreen& fullscreen = From(*descendant_doc);
- ElementStack& stack = fullscreen.fullscreen_element_stack_;
- DCHECK(!stack.IsEmpty());
+ Element* descendant_element = FullscreenElementFrom(*descendant_doc);
+ DCHECK(descendant_element);
+ RequestType request_type = GetRequestType(*descendant_element);
// 13.1. Append (fullscreenchange, |descendantDoc|'s fullscreen element) to
// |descendantDoc|'s list of pending fullscreen events.
- EnqueueEvent(EventTypeNames::fullscreenchange, *stack.back().first,
- *descendant_doc, stack.back().second);
+ EnqueueEvent(EventTypeNames::fullscreenchange, *descendant_element,
+ *descendant_doc, request_type);
// 13.2. Unfullscreen |descendantDoc|.
- while (!stack.IsEmpty())
- fullscreen.PopFullscreenElementStack();
+ Unfullscreen(*descendant_doc);
}
// 14. Resolve |promise| with undefined.
+ if (resolver) {
+ ScriptState::Scope scope(resolver->GetScriptState());
+ resolver->Resolve();
+ }
}
// https://fullscreen.spec.whatwg.org/#dom-document-fullscreenenabled
@@ -754,165 +963,56 @@ bool Fullscreen::FullscreenEnabled(Document& document) {
FullscreenIsSupported(document);
}
-void Fullscreen::SetFullScreenLayoutObject(LayoutFullScreen* layout_object) {
- if (layout_object == full_screen_layout_object_)
- return;
-
- if (layout_object && saved_placeholder_computed_style_) {
- layout_object->CreatePlaceholder(
- std::move(saved_placeholder_computed_style_),
- saved_placeholder_frame_rect_);
- } else if (layout_object && full_screen_layout_object_ &&
- full_screen_layout_object_->Placeholder()) {
- LayoutBlockFlow* placeholder = full_screen_layout_object_->Placeholder();
- layout_object->CreatePlaceholder(
- ComputedStyle::Clone(placeholder->StyleRef()),
- placeholder->FrameRect());
- }
-
- if (full_screen_layout_object_)
- full_screen_layout_object_->UnwrapLayoutObject();
- DCHECK(!full_screen_layout_object_);
-
- full_screen_layout_object_ = layout_object;
-}
-
-void Fullscreen::FullScreenLayoutObjectDestroyed() {
- full_screen_layout_object_ = nullptr;
+void Fullscreen::DidUpdateSize(Element& element) {
+ // StyleAdjuster will set the size so we need to do a style recalc.
+ // Normally changing size means layout so just doing a style recalc is a
+ // bit surprising.
+ element.SetNeedsStyleRecalc(
+ kLocalStyleChange,
+ StyleChangeReasonForTracing::Create(StyleChangeReason::kFullscreen));
}
void Fullscreen::ElementRemoved(Element& node) {
- DCHECK_EQ(GetDocument(), &node.GetDocument());
+ DCHECK(node.IsInTopLayer());
+ if (!HasFullscreenFlag(node))
+ return;
+
+ // 1. Let |document| be removedNode's node document.
+ Document& document = node.GetDocument();
// |Fullscreen::ElementRemoved()| is called for each removed element, so only
// the body of the spec "removing steps" loop appears here:
- // 2.1. If |node| is its node document's fullscreen element, exit fullscreen
+ // 3.1. If |node| is its node document's fullscreen element, exit fullscreen
// that document.
- if (FullscreenElement() == &node) {
- ExitFullscreen(node.GetDocument());
- return;
- }
-
- // 2.2. Otherwise, unfullscreen |node| within its node document.
- for (size_t i = 0; i < fullscreen_element_stack_.size(); ++i) {
- if (fullscreen_element_stack_[i].first.Get() == &node) {
- fullscreen_element_stack_.EraseAt(i);
- return;
- }
- }
-
- // Note: |node| was not in the fullscreen element stack.
-}
-
-void Fullscreen::PopFullscreenElementStack() {
- DCHECK(!fullscreen_element_stack_.IsEmpty());
-
- Element* old_element = FullscreenElement();
- fullscreen_element_stack_.pop_back();
-
- // Note: |requestType| is only used if |FullscreenElement()| is non-null.
- RequestType request_type = fullscreen_element_stack_.IsEmpty()
- ? RequestType::kUnprefixed
- : fullscreen_element_stack_.back().second;
- FullscreenElementChanged(old_element, FullscreenElement(), request_type);
-}
-
-void Fullscreen::PushFullscreenElementStack(Element& element,
- RequestType request_type) {
- Element* old_element = FullscreenElement();
- fullscreen_element_stack_.push_back(std::make_pair(&element, request_type));
-
- FullscreenElementChanged(old_element, &element, request_type);
-}
-
-void Fullscreen::FullscreenElementChanged(Element* old_element,
- Element* new_element,
- RequestType new_request_type) {
- DCHECK_NE(old_element, new_element);
-
- if (!GetDocument())
- return;
-
- GetDocument()->GetStyleEngine().EnsureUAStyleForFullscreen();
-
- if (full_screen_layout_object_)
- full_screen_layout_object_->UnwrapLayoutObject();
- DCHECK(!full_screen_layout_object_);
-
- if (old_element) {
- DCHECK_NE(old_element, FullscreenElement());
-
- old_element->PseudoStateChanged(CSSSelector::kPseudoFullScreen);
- old_element->PseudoStateChanged(CSSSelector::kPseudoFullscreen);
-
- old_element->SetContainsFullScreenElement(false);
- old_element->SetContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(
- false);
- }
-
- if (new_element) {
- DCHECK_EQ(new_element, FullscreenElement());
-
- new_element->PseudoStateChanged(CSSSelector::kPseudoFullScreen);
- new_element->PseudoStateChanged(CSSSelector::kPseudoFullscreen);
-
- // OOPIF: For RequestType::PrefixedForCrossProcessDescendant, |toElement| is
- // the iframe element for the out-of-process frame that contains the
- // fullscreen element. Hence, it must match :-webkit-full-screen-ancestor.
- if (new_request_type == RequestType::kPrefixedForCrossProcessDescendant) {
- DCHECK(IsHTMLIFrameElement(new_element));
- new_element->SetContainsFullScreenElement(true);
- }
- new_element->SetContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(
- true);
-
- // Create a placeholder block for the fullscreen element, to keep the page
- // from reflowing when the element is removed from the normal flow. Only do
- // this for a LayoutBox, as only a box will have a frameRect. The
- // placeholder will be created in setFullScreenLayoutObject() during layout.
- LayoutObject* layout_object = new_element->GetLayoutObject();
- bool should_create_placeholder = layout_object && layout_object->IsBox();
- if (should_create_placeholder) {
- saved_placeholder_frame_rect_ = ToLayoutBox(layout_object)->FrameRect();
- saved_placeholder_computed_style_ =
- ComputedStyle::Clone(layout_object->StyleRef());
- }
-
- if (new_element != GetDocument()->documentElement()) {
- LayoutFullScreen::WrapLayoutObject(
- layout_object, layout_object ? layout_object->Parent() : nullptr,
- GetDocument());
- }
- }
-
- if (LocalFrame* frame = GetDocument()->GetFrame()) {
- // TODO(foolip): Synchronize hover state changes with animation frames.
- // https://crbug.com/668758
- frame->GetEventHandler().ScheduleHoverStateUpdate();
- frame->GetChromeClient().FullscreenElementChanged(old_element, new_element);
-
- // Descendant frames may have been inert because their owner iframes were
- // outside of fullscreen element. SetIsInert recurses through subframes to
- // propagate the inert bit as needed.
- frame->SetIsInert(GetDocument()->LocalOwner() &&
- GetDocument()->LocalOwner()->IsInert());
+ if (IsFullscreenElement(node)) {
+ ExitFullscreen(document, nullptr, false);
+ } else {
+ // 3.2. Otherwise, unfullscreen |node| within its node document.
+ Unfullscreen(node);
}
- // TODO(foolip): This should not call |UpdateStyleAndLayoutTree()|.
- GetDocument()->UpdateStyleAndLayoutTree();
-
- // Any element not contained by the fullscreen element is inert (see
- // |Node::IsInert()|), so changing the fullscreen element will typically
- // change the inertness of most elements. Clear the entire cache.
- GetDocument()->ClearAXObjectCache();
+ // 3.3 If document's top layer contains node, remove node from document's top
+ // layer. This is done in Element::RemovedFrom.
}
void Fullscreen::Trace(blink::Visitor* visitor) {
visitor->Trace(pending_requests_);
- visitor->Trace(fullscreen_element_stack_);
+ visitor->Trace(pending_exits_);
Supplement<Document>::Trace(visitor);
ContextLifecycleObserver::Trace(visitor);
}
+Fullscreen::PendingRequest::PendingRequest(Element* element,
+ RequestType type,
+ ScriptPromiseResolver* resolver)
+ : element_(element), type_(type), resolver_(resolver) {}
+
+Fullscreen::PendingRequest::~PendingRequest() = default;
+
+void Fullscreen::PendingRequest::Trace(blink::Visitor* visitor) {
+ visitor->Trace(element_);
+ visitor->Trace(resolver_);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h b/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h
index 24b75842cbb..38fea663ca8 100644
--- a/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h
+++ b/chromium/third_party/blink/renderer/core/fullscreen/fullscreen.h
@@ -31,6 +31,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FULLSCREEN_FULLSCREEN_H_
#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -42,9 +43,8 @@
namespace blink {
-class ComputedStyle;
class FullscreenOptions;
-class LayoutFullScreen;
+class ScriptPromiseResolver;
// The Fullscreen class implements most of the Fullscreen API Standard,
// https://fullscreen.spec.whatwg.org/, especially its algorithms. It is a
@@ -61,10 +61,8 @@ class CORE_EXPORT Fullscreen final
virtual ~Fullscreen();
static Fullscreen& From(Document&);
- static Fullscreen* FromIfExists(Document&);
static Element* FullscreenElementFrom(Document&);
static Element* FullscreenElementForBindingFrom(TreeScope&);
- static size_t FullscreenElementStackSizeFrom(Document&);
static bool IsFullscreenElement(const Element&);
static bool IsInFullscreenElementStack(const Element&);
@@ -80,32 +78,26 @@ class CORE_EXPORT Fullscreen final
};
static void RequestFullscreen(Element&);
- static void RequestFullscreen(Element&,
- const FullscreenOptions&,
- RequestType);
+ static ScriptPromise RequestFullscreen(Element&,
+ const FullscreenOptions&,
+ RequestType,
+ ScriptState* state = nullptr);
- static void FullyExitFullscreen(Document&);
- static void ExitFullscreen(Document&);
+ static void FullyExitFullscreen(Document&, bool ua_originated = false);
+ static ScriptPromise ExitFullscreen(Document&,
+ ScriptState* state = nullptr,
+ bool ua_originated = false);
static bool FullscreenEnabled(Document&);
- Element* FullscreenElement() const {
- return !fullscreen_element_stack_.IsEmpty()
- ? fullscreen_element_stack_.back().first.Get()
- : nullptr;
- }
// Called by FullscreenController to notify that we've entered or exited
// fullscreen. All frames are notified, so there may be no pending request.
- void DidEnterFullscreen();
- void DidExitFullscreen();
+ static void DidEnterFullscreen(Document&);
+ static void DidExitFullscreen(Document&);
- void SetFullScreenLayoutObject(LayoutFullScreen*);
- LayoutFullScreen* FullScreenLayoutObject() const {
- return full_screen_layout_object_;
- }
- void FullScreenLayoutObjectDestroyed();
+ static void DidUpdateSize(Element&);
- void ElementRemoved(Element&);
+ static void ElementRemoved(Element&);
// ContextLifecycleObserver:
void ContextDestroyed(ExecutionContext*) override;
@@ -113,7 +105,7 @@ class CORE_EXPORT Fullscreen final
void Trace(blink::Visitor*) override;
private:
- static Fullscreen* FromIfExistsSlow(Document&);
+ static Fullscreen* FromIfExists(Document&);
explicit Fullscreen(Document&);
@@ -122,37 +114,48 @@ class CORE_EXPORT Fullscreen final
static void ContinueRequestFullscreen(Document&,
Element&,
RequestType,
+ ScriptPromiseResolver* resolver,
bool error);
- static void ContinueExitFullscreen(Document*, bool resize);
+ static void ContinueExitFullscreen(Document*,
+ ScriptPromiseResolver* resolver,
+ bool resize);
- void ClearFullscreenElementStack();
- void PopFullscreenElementStack();
- void PushFullscreenElementStack(Element&, RequestType);
void FullscreenElementChanged(Element* old_element,
Element* new_element,
RequestType new_request_type);
- using ElementStackEntry = std::pair<Member<Element>, RequestType>;
- using ElementStack = HeapVector<ElementStackEntry>;
- ElementStack pending_requests_;
- ElementStack fullscreen_element_stack_;
+ // Stores the pending request, promise and the type for executing
+ // the asynchronous portion of the request.
+ class PendingRequest : public GarbageCollectedFinalized<PendingRequest> {
+ public:
+ PendingRequest(Element* element,
+ RequestType type,
+ ScriptPromiseResolver* resolver);
+ virtual ~PendingRequest();
+ virtual void Trace(blink::Visitor* visitor);
+
+ Element* element() { return element_; }
+ RequestType type() { return type_; }
+ ScriptPromiseResolver* resolver() { return resolver_; }
+
+ private:
+ Member<Element> element_;
+ RequestType type_;
+ Member<ScriptPromiseResolver> resolver_;
+
+ DISALLOW_COPY_AND_ASSIGN(PendingRequest);
+ };
+ using PendingRequests = HeapVector<Member<PendingRequest>>;
+ PendingRequests pending_requests_;
- LayoutFullScreen* full_screen_layout_object_;
- LayoutRect saved_placeholder_frame_rect_;
- scoped_refptr<ComputedStyle> saved_placeholder_computed_style_;
+ using PendingExit = ScriptPromiseResolver;
+ using PendingExits = HeapVector<Member<PendingExit>>;
+ PendingExits pending_exits_;
};
-inline Fullscreen* Fullscreen::FromIfExists(Document& document) {
- if (!document.HasFullscreenSupplement())
- return nullptr;
- return FromIfExistsSlow(document);
-}
-
inline bool Fullscreen::IsFullscreenElement(const Element& element) {
- if (Fullscreen* found = FromIfExists(element.GetDocument()))
- return found->FullscreenElement() == &element;
- return false;
+ return FullscreenElementFrom(element.GetDocument()) == &element;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/geometry/dom_matrix.h b/chromium/third_party/blink/renderer/core/geometry/dom_matrix.h
index 6f7f1c474a0..a0b53bc7fbe 100644
--- a/chromium/third_party/blink/renderer/core/geometry/dom_matrix.h
+++ b/chromium/third_party/blink/renderer/core/geometry/dom_matrix.h
@@ -5,12 +5,12 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_GEOMETRY_DOM_MATRIX_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_GEOMETRY_DOM_MATRIX_H_
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_unrestricted_double_sequence.h"
#include "third_party/blink/renderer/core/geometry/dom_matrix_2d_init.h"
#include "third_party/blink/renderer/core/geometry/dom_matrix_init.h"
#include "third_party/blink/renderer/core/geometry/dom_matrix_read_only.h"
#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/geometry/dom_matrix_read_only.cc b/chromium/third_party/blink/renderer/core/geometry/dom_matrix_read_only.cc
index 42cce1270b7..ce881b7d5f3 100644
--- a/chromium/third_party/blink/renderer/core/geometry/dom_matrix_read_only.cc
+++ b/chromium/third_party/blink/renderer/core/geometry/dom_matrix_read_only.cc
@@ -360,7 +360,7 @@ const String DOMMatrixReadOnly::toString(
if (!std::isfinite(a()) || !std::isfinite(b()) || !std::isfinite(c()) ||
!std::isfinite(d()) || !std::isfinite(e()) || !std::isfinite(f())) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"DOMMatrix cannot be serialized with NaN or Infinity values.");
return String();
}
@@ -388,7 +388,7 @@ const String DOMMatrixReadOnly::toString(
!std::isfinite(m41()) || !std::isfinite(m42()) || !std::isfinite(m43()) ||
!std::isfinite(m44())) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"DOMMatrix cannot be serialized with NaN or Infinity values.");
return String();
}
@@ -479,7 +479,8 @@ void DOMMatrixReadOnly::SetMatrixValueFromString(
if (!value || value->IsCSSWideKeyword()) {
exception_state.ThrowDOMException(
- kSyntaxError, "Failed to parse '" + input_string + "'.");
+ DOMExceptionCode::kSyntaxError,
+ "Failed to parse '" + input_string + "'.");
return;
}
@@ -491,7 +492,7 @@ void DOMMatrixReadOnly::SetMatrixValueFromString(
}
if (TransformBuilder::HasRelativeLengths(ToCSSValueList(*value))) {
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"Lengths must be absolute, not relative");
return;
}
@@ -503,7 +504,8 @@ void DOMMatrixReadOnly::SetMatrixValueFromString(
if (operations.DependsOnBoxSize()) {
exception_state.ThrowDOMException(
- kSyntaxError, "Lengths must be absolute, not depend on the box size");
+ DOMExceptionCode::kSyntaxError,
+ "Lengths must be absolute, not depend on the box size");
return;
}
diff --git a/chromium/third_party/blink/renderer/core/geometry/dom_matrix_read_only.h b/chromium/third_party/blink/renderer/core/geometry/dom_matrix_read_only.h
index b264ee67a05..05d9535f1dc 100644
--- a/chromium/third_party/blink/renderer/core/geometry/dom_matrix_read_only.h
+++ b/chromium/third_party/blink/renderer/core/geometry/dom_matrix_read_only.h
@@ -7,11 +7,11 @@
#include <memory>
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_unrestricted_double_sequence.h"
#include "third_party/blink/renderer/core/geometry/dom_matrix_2d_init.h"
#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.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/heap/handle.h"
#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
diff --git a/chromium/third_party/blink/renderer/core/geometry/dom_matrix_test.cc b/chromium/third_party/blink/renderer/core/geometry/dom_matrix_test.cc
index a1d0ad4c1da..00b851ce793 100644
--- a/chromium/third_party/blink/renderer/core/geometry/dom_matrix_test.cc
+++ b/chromium/third_party/blink/renderer/core/geometry/dom_matrix_test.cc
@@ -5,8 +5,8 @@
#include "third_party/blink/renderer/core/geometry/dom_matrix.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/geometry/dom_point_read_only.cc b/chromium/third_party/blink/renderer/core/geometry/dom_point_read_only.cc
index 9836c1d5ca5..894032c5808 100644
--- a/chromium/third_party/blink/renderer/core/geometry/dom_point_read_only.cc
+++ b/chromium/third_party/blink/renderer/core/geometry/dom_point_read_only.cc
@@ -4,13 +4,13 @@
#include "third_party/blink/renderer/core/geometry/dom_point_read_only.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/geometry/dom_matrix_init.h"
#include "third_party/blink/renderer/core/geometry/dom_matrix_read_only.h"
#include "third_party/blink/renderer/core/geometry/dom_point.h"
#include "third_party/blink/renderer/core/geometry/dom_point_init.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/html/BUILD.gn b/chromium/third_party/blink/renderer/core/html/BUILD.gn
index 27b124d4fb7..fe667fbfe8b 100644
--- a/chromium/third_party/blink/renderer/core/html/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/html/BUILD.gn
@@ -9,6 +9,10 @@ blink_core_sources("html") {
split_count = 4
sources = [
+ "anchor_element_metrics.cc",
+ "anchor_element_metrics.h",
+ "anchor_element_metrics_sender.cc",
+ "anchor_element_metrics_sender.h",
"canvas/canvas_async_blob_creator.cc",
"canvas/canvas_async_blob_creator.h",
"canvas/canvas_context_creation_attributes_core.cc",
@@ -451,6 +455,8 @@ blink_core_sources("html") {
"imports/html_imports_controller.h",
"imports/link_import.cc",
"imports/link_import.h",
+ "lazy_load_frame_observer.cc",
+ "lazy_load_frame_observer.h",
"link_manifest.cc",
"link_manifest.h",
"link_rel_attribute.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
new file mode 100644
index 00000000000..6e4540bb56e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/anchor_element_metrics.cc
@@ -0,0 +1,274 @@
+// 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/html/anchor_element_metrics.h"
+
+#include "base/metrics/histogram_macros.h"
+#include "third_party/blink/public/mojom/loader/navigation_predictor.mojom-blink.h"
+#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/html/anchor_element_metrics_sender.h"
+#include "third_party/blink/renderer/core/html/html_anchor_element.h"
+#include "third_party/blink/renderer/core/html/html_frame_owner_element.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/paint/paint_layer.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
+#include "third_party/blink/renderer/platform/histogram.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+// If RecordAnchorMetricsClicked feature is enabled, then metrics of anchor
+// elements clicked by the user will be extracted and recorded.
+const base::Feature kRecordAnchorMetricsClicked{
+ "RecordAnchorMetricsClicked", base::FEATURE_DISABLED_BY_DEFAULT};
+
+namespace {
+
+// Helper function that returns the root document the anchor element is in.
+Document* GetRootDocument(const HTMLAnchorElement& anchor) {
+ return anchor.GetDocument().GetFrame()->LocalFrameRoot().GetDocument();
+}
+
+// Accumulated scroll offset of all frames up to the local root frame.
+int AccumulatedScrollOffset(const HTMLAnchorElement& anchor_element) {
+ IntSize offset;
+ Frame* frame = anchor_element.GetDocument().GetFrame();
+ while (frame && frame->View() && frame->IsLocalFrame()) {
+ offset += ToLocalFrame(frame)->View()->LayoutViewport()->ScrollOffsetInt();
+ frame = frame->Tree().Parent();
+ }
+ return offset.Height();
+}
+
+// Whether the element is inside an iframe.
+bool IsInIFrame(const HTMLAnchorElement& anchor_element) {
+ Frame* frame = anchor_element.GetDocument().GetFrame();
+ while (frame && frame->IsLocalFrame()) {
+ HTMLFrameOwnerElement* owner =
+ ToLocalFrame(frame)->GetDocument()->LocalOwner();
+ if (owner && IsHTMLIFrameElement(owner))
+ return true;
+ frame = frame->Tree().Parent();
+ }
+ return false;
+}
+
+// Whether the anchor element contains an image element.
+bool ContainsImage(const HTMLAnchorElement& anchor_element) {
+ for (Node* node = FlatTreeTraversal::FirstChild(anchor_element); node;
+ node = FlatTreeTraversal::Next(*node, &anchor_element)) {
+ if (IsHTMLImageElement(*node))
+ return true;
+ }
+ return false;
+}
+
+// Whether the link target has the same host as the root document.
+bool IsSameHost(const HTMLAnchorElement& anchor_element) {
+ String source_host = GetRootDocument(anchor_element)->Url().Host();
+ String target_host = anchor_element.Href().Host();
+ return source_host == target_host;
+}
+
+// Returns true if the two strings only differ by one number, and
+// the second number equals the first number plus one. Examples:
+// example.com/page9/cat5, example.com/page10/cat5 => true
+// example.com/page9/cat5, example.com/page10/cat10 => false
+bool IsStringIncrementedByOne(const String& source, const String& target) {
+ // Consecutive numbers should differ in length by at most 1.
+ int length_diff = target.length() - source.length();
+ if (length_diff < 0 || length_diff > 1)
+ return false;
+
+ // The starting position of difference.
+ unsigned int left = 0;
+ while (left < source.length() && left < target.length() &&
+ source[left] == target[left]) {
+ left++;
+ }
+
+ // There is no difference, or the difference is not a digit.
+ if (left == source.length() || left == target.length() ||
+ !u_isdigit(source[left]) || !u_isdigit(target[left])) {
+ return false;
+ }
+
+ // Expand towards right to extract the numbers.
+ unsigned int source_right = left + 1;
+ while (source_right < source.length() && u_isdigit(source[source_right]))
+ source_right++;
+
+ unsigned int target_right = left + 1;
+ while (target_right < target.length() && u_isdigit(target[target_right]))
+ target_right++;
+
+ int source_number = source.Substring(left, source_right - left).ToInt();
+ int target_number = target.Substring(left, target_right - left).ToInt();
+
+ // The second number should increment by one and the rest of the strings
+ // should be the same.
+ return source_number + 1 == target_number &&
+ source.Substring(source_right) == target.Substring(target_right);
+}
+
+// Extract source and target link url, and return IsStringIncrementedByOne().
+bool IsUrlIncrementedByOne(const HTMLAnchorElement& anchor_element) {
+ if (!IsSameHost(anchor_element))
+ return false;
+
+ String source_url = GetRootDocument(anchor_element)->Url().GetString();
+ String target_url = anchor_element.Href().GetString();
+ return IsStringIncrementedByOne(source_url, target_url);
+}
+
+// Returns the bounding box rect of a layout object, including visual
+// overflows.
+IntRect AbsoluteElementBoundingBoxRect(const LayoutObject* layout_object) {
+ Vector<LayoutRect> rects;
+ layout_object->AddElementVisualOverflowRects(rects, LayoutPoint());
+
+ return layout_object
+ ->LocalToAbsoluteQuad(FloatQuad(FloatRect(UnionRect(rects))))
+ .EnclosingBoundingBox();
+}
+
+} // anonymous namespace
+
+// static
+base::Optional<AnchorElementMetrics> AnchorElementMetrics::Create(
+ const HTMLAnchorElement* anchor_element) {
+ LocalFrame* local_frame = anchor_element->GetDocument().GetFrame();
+ LayoutObject* layout_object = anchor_element->GetLayoutObject();
+ if (!local_frame || !layout_object)
+ return base::nullopt;
+
+ LocalFrameView* local_frame_view = local_frame->View();
+ LocalFrameView* root_frame_view = local_frame->LocalFrameRoot().View();
+ if (!local_frame_view || !root_frame_view)
+ return base::nullopt;
+
+ IntRect viewport = root_frame_view->LayoutViewport()->VisibleContentRect();
+ if (viewport.Size().IsEmpty())
+ return base::nullopt;
+
+ // Use the viewport size to normalize anchor element metrics.
+ float base_height = static_cast<float>(viewport.Height());
+ float base_width = static_cast<float>(viewport.Width());
+
+ // The anchor element rect in the root frame.
+ IntRect target = local_frame_view->ConvertToRootFrame(
+ AbsoluteElementBoundingBoxRect(layout_object));
+
+ // Limit the element size to the viewport size.
+ float ratio_area = std::min(1.0f, target.Height() / base_height) *
+ std::min(1.0f, target.Width() / base_width);
+ float ratio_distance_top_to_visible_top = target.Y() / base_height;
+ float ratio_distance_center_to_visible_top =
+ (target.Y() + target.Height() / 2.0) / base_height;
+
+ float ratio_distance_root_top =
+ (target.Y() + AccumulatedScrollOffset(*anchor_element)) / base_height;
+
+ // Distance to the bottom is tricky if the element is inside sub/iframes.
+ // Here we use the target location in the root viewport, and calculate
+ // the distance from the bottom of the anchor element to the root bottom.
+ int root_height = GetRootDocument(*anchor_element)
+ ->GetLayoutView()
+ ->GetScrollableArea()
+ ->ContentsSize()
+ .Height();
+ int root_scrolled =
+ root_frame_view->LayoutViewport()->ScrollOffsetInt().Height();
+ float ratio_distance_root_bottom =
+ (root_height - root_scrolled - target.Y() - target.Height()) /
+ base_height;
+
+ // Get the anchor element rect that intersects with the viewport.
+ IntRect target_visible(target);
+ target_visible.Intersect(IntRect(IntPoint(), viewport.Size()));
+
+ // It guarantees to be less or equal to 1.
+ float ratio_visible_area = (target_visible.Height() / base_height) *
+ (target_visible.Width() / base_width);
+
+ 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,
+ IsInIFrame(*anchor_element), ContainsImage(*anchor_element),
+ IsSameHost(*anchor_element), IsUrlIncrementedByOne(*anchor_element));
+}
+
+// static
+base::Optional<AnchorElementMetrics>
+AnchorElementMetrics::MaybeExtractMetricsClicked(
+ const HTMLAnchorElement* anchor_element) {
+ if (!base::FeatureList::IsEnabled(kRecordAnchorMetricsClicked) ||
+ !anchor_element->Href().ProtocolIsInHTTPFamily())
+ return base::nullopt;
+
+ auto anchor_metrics = Create(anchor_element);
+ if (anchor_metrics.has_value()) {
+ anchor_metrics.value().RecordMetrics();
+ anchor_metrics.value().SendMetricsToBrowser();
+ }
+
+ return anchor_metrics;
+}
+
+void AnchorElementMetrics::SendMetricsToBrowser() const {
+ DCHECK(anchor_element_->GetDocument().GetFrame());
+
+ auto metrics = mojom::blink::AnchorElementMetrics::New();
+ metrics->ratio_area = ratio_area_;
+ metrics->ratio_distance_root_top = ratio_distance_root_top_;
+ metrics->ratio_distance_center_to_visible_top =
+ ratio_distance_center_to_visible_top_;
+ metrics->target_url = anchor_element_->Href();
+
+ Document* root_document =
+ anchor_element_->GetDocument().GetFrame()->LocalFrameRoot().GetDocument();
+ AnchorElementMetricsSender::From(*root_document)
+ ->SendClickedAnchorMetricsToBrowser(std::move(metrics));
+}
+
+void AnchorElementMetrics::RecordMetrics() const {
+ UMA_HISTOGRAM_PERCENTAGE("AnchorElementMetrics.Clicked.RatioArea",
+ int(ratio_area_ * 100));
+
+ UMA_HISTOGRAM_PERCENTAGE("AnchorElementMetrics.Clicked.RatioVisibleArea",
+ int(ratio_visible_area_ * 100));
+
+ UMA_HISTOGRAM_PERCENTAGE(
+ "AnchorElementMetrics.Clicked.RatioDistanceTopToVisibleTop",
+ int(std::min(ratio_distance_top_to_visible_top_, 1.0f) * 100));
+
+ UMA_HISTOGRAM_PERCENTAGE(
+ "AnchorElementMetrics.Clicked.RatioDistanceCenterToVisibleTop",
+ int(std::min(ratio_distance_center_to_visible_top_, 1.0f) * 100));
+
+ UMA_HISTOGRAM_COUNTS_10000(
+ "AnchorElementMetrics.Clicked.RatioDistanceRootTop",
+ int(std::min(ratio_distance_root_top_, 100.0f) * 100));
+
+ UMA_HISTOGRAM_COUNTS_10000(
+ "AnchorElementMetrics.Clicked.RatioDistanceRootBottom",
+ int(std::min(ratio_distance_root_bottom_, 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
new file mode 100644
index 00000000000..a65889a8b3c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/anchor_element_metrics.h
@@ -0,0 +1,120 @@
+// 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_HTML_ANCHOR_ELEMENT_METRICS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_ANCHOR_ELEMENT_METRICS_H_
+
+#include "base/feature_list.h"
+#include "base/optional.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/allocator.h"
+
+namespace blink {
+
+CORE_EXPORT extern const base::Feature kRecordAnchorMetricsClicked;
+
+class HTMLAnchorElement;
+
+class CORE_EXPORT AnchorElementMetrics {
+ STACK_ALLOCATED();
+
+ public:
+ // Creates AnchorElementMetrics from anchor element if possible. Then records
+ // the metrics, and sends them to the browser process.
+ static base::Optional<AnchorElementMetrics> MaybeExtractMetricsClicked(
+ const HTMLAnchorElement*);
+
+ // Upload anchor element features.
+ void RecordMetrics() const;
+
+ // Send anchor element features to browser process.
+ void SendMetricsToBrowser() const;
+
+ // Getters of anchor element features.
+ float GetRatioArea() const { return ratio_area_; }
+ float GetRatioVisibleArea() const { return ratio_visible_area_; }
+ float GetRatioDistanceTopToVisibleTop() const {
+ return ratio_distance_top_to_visible_top_;
+ }
+ float GetRatioDistanceCenterToVisibleTop() const {
+ return ratio_distance_center_to_visible_top_;
+ }
+ float GetRatioDistanceRootTop() const { return ratio_distance_root_top_; }
+ float GetRatioDistanceRootBottom() const {
+ return ratio_distance_root_bottom_;
+ }
+ bool GetIsInIframe() const { return is_in_iframe_; }
+ bool GetContainsImage() const { return contains_image_; }
+ bool GetIsSameHost() const { return is_same_host_; }
+ bool GetIsUrlIncrementedByOne() const { return is_url_incremented_by_one_; }
+
+ private:
+ // Extract features of the anchor element.
+ static base::Optional<AnchorElementMetrics> Create(const HTMLAnchorElement*);
+
+ // The anchor element that this class is associated with.
+ Member<const HTMLAnchorElement> anchor_element_;
+
+ // The ratio of the absolute/visible clickable region area of an anchor
+ // element, and the viewport area.
+ const float ratio_area_;
+ const float ratio_visible_area_;
+
+ // The distance between the top/center of the clickable region of an anchor
+ // element and the top edge of the visible region, divided by the viewport
+ // height.
+ const float ratio_distance_top_to_visible_top_;
+ const float ratio_distance_center_to_visible_top_;
+
+ // The distance between the top of the clickable region of an anchor element
+ // and the top edge of the root frame, divided by the viewport height.
+ const float ratio_distance_root_top_;
+
+ // The distance between the bottom of the clickable region of an anchor
+ // element and the bottom edge of the root frame, divided by the viewport
+ // height.
+ const float ratio_distance_root_bottom_;
+
+ // Whether the anchor element is within an iframe.
+ const bool is_in_iframe_;
+
+ // Whether the anchor element contains an image element.
+ const bool contains_image_;
+
+ // Whether the link target has the same host as the root document.
+ const bool is_same_host_;
+
+ // Whether the target url and the host url only differ by one number,
+ // and the number in target url equals the one in host url plus one.
+ const bool is_url_incremented_by_one_;
+
+ inline AnchorElementMetrics(const HTMLAnchorElement* anchor_element,
+ float ratio_area,
+ float ratio_visible_area,
+ float ratio_distance_top_to_visible_top,
+ float ratio_distance_center_to_visible_top,
+ float ratio_distance_root_top,
+ float ratio_distance_root_bottom,
+ bool is_in_iframe,
+ bool contains_image,
+ bool is_same_host,
+ bool is_url_incremented_by_one)
+ : anchor_element_(anchor_element),
+ ratio_area_(ratio_area),
+ ratio_visible_area_(ratio_visible_area),
+ ratio_distance_top_to_visible_top_(ratio_distance_top_to_visible_top),
+ ratio_distance_center_to_visible_top_(
+ ratio_distance_center_to_visible_top),
+ ratio_distance_root_top_(ratio_distance_root_top),
+ ratio_distance_root_bottom_(ratio_distance_root_bottom),
+ is_in_iframe_(is_in_iframe),
+ contains_image_(contains_image),
+ is_same_host_(is_same_host),
+ is_url_incremented_by_one_(is_url_incremented_by_one) {}
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_ANCHOR_ELEMENT_METRICS_H_
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
new file mode 100644
index 00000000000..437c346c9f7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/anchor_element_metrics_sender.cc
@@ -0,0 +1,50 @@
+// 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/html/anchor_element_metrics_sender.h"
+
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+
+namespace blink {
+
+// static
+const char AnchorElementMetricsSender::kSupplementName[] =
+ "DocumentAnchorElementMetricsSender";
+
+AnchorElementMetricsSender::~AnchorElementMetricsSender() = default;
+
+AnchorElementMetricsSender* AnchorElementMetricsSender::From(
+ Document& document) {
+ // Only root document owns the AnchorElementMetricsSender.
+ DCHECK(!document.ParentDocument());
+
+ AnchorElementMetricsSender* sender =
+ Supplement<Document>::From<AnchorElementMetricsSender>(document);
+ if (!sender) {
+ sender = new AnchorElementMetricsSender(document);
+ ProvideTo(document, sender);
+ }
+ return sender;
+}
+
+void AnchorElementMetricsSender::SendClickedAnchorMetricsToBrowser(
+ mojom::blink::AnchorElementMetricsPtr metric) const {
+ metrics_host_->UpdateAnchorElementMetrics(std::move(metric));
+}
+
+void AnchorElementMetricsSender::Trace(blink::Visitor* visitor) {
+ Supplement<Document>::Trace(visitor);
+}
+
+AnchorElementMetricsSender::AnchorElementMetricsSender(Document& document)
+ : Supplement<Document>(document) {
+ DCHECK(!document.ParentDocument());
+
+ document.GetFrame()->LocalFrameRoot().GetInterfaceProvider().GetInterface(
+ mojo::MakeRequest(&metrics_host_));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/anchor_element_metrics_sender.h b/chromium/third_party/blink/renderer/core/html/anchor_element_metrics_sender.h
new file mode 100644
index 00000000000..d51bac362d8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/anchor_element_metrics_sender.h
@@ -0,0 +1,50 @@
+// 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_HTML_ANCHOR_ELEMENT_METRICS_SENDER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_ANCHOR_ELEMENT_METRICS_SENDER_H_
+
+#include "base/macros.h"
+#include "third_party/blink/public/mojom/loader/navigation_predictor.mojom-blink.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+
+namespace blink {
+
+class Document;
+
+// AnchorElementMetricsSender is responsible to send anchor element metrics to
+// the browser process for a given document.
+class AnchorElementMetricsSender final
+ : public GarbageCollectedFinalized<AnchorElementMetricsSender>,
+ public Supplement<Document> {
+ USING_GARBAGE_COLLECTED_MIXIN(AnchorElementMetricsSender);
+
+ public:
+ static const char kSupplementName[];
+
+ virtual ~AnchorElementMetricsSender();
+
+ // Returns the anchor element metrics sender of the root document of
+ // |Document|. Constructs new one if it does not exist.
+ static AnchorElementMetricsSender* From(Document&);
+
+ // Send metrics of anchor element clicked by the user to the browser.
+ void SendClickedAnchorMetricsToBrowser(
+ mojom::blink::AnchorElementMetricsPtr metric) const;
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ explicit AnchorElementMetricsSender(Document&);
+
+ // Browser host to which the anchor element metrics are sent.
+ mojom::blink::AnchorElementMetricsHostPtr metrics_host_;
+
+ DISALLOW_COPY_AND_ASSIGN(AnchorElementMetricsSender);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_ANCHOR_ELEMENT_METRICS_SENDER_H_
diff --git a/chromium/third_party/blink/renderer/core/html/anchor_element_metrics_test.cc b/chromium/third_party/blink/renderer/core/html/anchor_element_metrics_test.cc
new file mode 100644
index 00000000000..98bc49e1186
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/anchor_element_metrics_test.cc
@@ -0,0 +1,260 @@
+// 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/html/anchor_element_metrics.h"
+
+#include "base/optional.h"
+#include "base/test/scoped_feature_list.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/html/html_anchor_element.h"
+#include "third_party/blink/renderer/core/html/html_iframe_element.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/testing/histogram_tester.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+
+namespace blink {
+
+class AnchorElementMetricsTest : public SimTest {
+ public:
+ static constexpr int kViewportWidth = 400;
+ static constexpr int kViewportHeight = 600;
+
+ // Helper function to test IsUrlIncrementedByOne().
+ bool IsIncrementedByOne(const String& source, const String& target) {
+ SimRequest main_resource(source, "text/html");
+ LoadURL(source);
+ main_resource.Complete("<a id='anchor' href=''>example</a>");
+ HTMLAnchorElement* anchor_element =
+ ToHTMLAnchorElement(GetDocument().getElementById("anchor"));
+ anchor_element->SetHref(AtomicString(target));
+
+ return AnchorElementMetrics::MaybeExtractMetricsClicked(anchor_element)
+ .value()
+ .GetIsUrlIncrementedByOne();
+ }
+
+ protected:
+ AnchorElementMetricsTest() = default;
+
+ void SetUp() override {
+ SimTest::SetUp();
+ WebView().Resize(WebSize(kViewportWidth, kViewportHeight));
+ feature_list_.InitAndEnableFeature(kRecordAnchorMetricsClicked);
+ }
+
+ base::test::ScopedFeatureList feature_list_;
+};
+
+// Test for IsUrlIncrementedByOne().
+TEST_F(AnchorElementMetricsTest, IsUrlIncrementedByOne) {
+ EXPECT_TRUE(
+ IsIncrementedByOne("http://example.com/p1", "http://example.com/p2"));
+ EXPECT_TRUE(IsIncrementedByOne("http://example.com/?p=9",
+ "http://example.com/?p=10"));
+ EXPECT_TRUE(IsIncrementedByOne("http://example.com/?p=12",
+ "http://example.com/?p=13"));
+ EXPECT_TRUE(IsIncrementedByOne("http://example.com/p9/cat1",
+ "http://example.com/p10/cat1"));
+ EXPECT_FALSE(
+ IsIncrementedByOne("http://example.com/1", "https://example.com/2"));
+ EXPECT_FALSE(
+ IsIncrementedByOne("http://example.com/1", "http://google.com/2"));
+ EXPECT_FALSE(
+ IsIncrementedByOne("http://example.com/p1", "http://example.com/p1"));
+ EXPECT_FALSE(
+ IsIncrementedByOne("http://example.com/p2", "http://example.com/p1"));
+ EXPECT_FALSE(IsIncrementedByOne("http://example.com/p9/cat1",
+ "http://example.com/p10/cat2"));
+}
+
+// Test that Finch can control the collection of anchor element metrics.
+TEST_F(AnchorElementMetricsTest, FinchControl) {
+ HistogramTester histogram_tester;
+
+ SimRequest resource("https://example.com/", "text/html");
+ LoadURL("https://example.com/");
+ resource.Complete("<a id='anchor' href='https://google.com/'>google</a>");
+ HTMLAnchorElement* anchor_element =
+ ToHTMLAnchorElement(GetDocument().getElementById("anchor"));
+
+ // With feature kRecordAnchorMetricsClicked disabled, we should not see any
+ // count in histograms.
+ base::test::ScopedFeatureList disabled_feature_list;
+ disabled_feature_list.InitAndDisableFeature(kRecordAnchorMetricsClicked);
+ AnchorElementMetrics::MaybeExtractMetricsClicked(anchor_element);
+ histogram_tester.ExpectTotalCount("AnchorElementMetrics.Clicked.RatioArea",
+ 0);
+
+ // If we enable feature kRecordAnchorMetricsClicked, we should see count is 1
+ // in histograms.
+ base::test::ScopedFeatureList enabled_feature_list;
+ enabled_feature_list.InitAndEnableFeature(kRecordAnchorMetricsClicked);
+ AnchorElementMetrics::MaybeExtractMetricsClicked(anchor_element);
+ histogram_tester.ExpectTotalCount("AnchorElementMetrics.Clicked.RatioArea",
+ 1);
+}
+
+// The main frame contains an anchor element, which contains an image element.
+TEST_F(AnchorElementMetricsTest, AnchorFeatureImageLink) {
+ SimRequest main_resource("https://example.com/", "text/html");
+
+ LoadURL("https://example.com/");
+
+ main_resource.Complete(String::Format(
+ R"HTML(
+ <body style='margin: 0px'>
+ <div style='height: %dpx;'></div>
+ <a id='anchor' href="https://example.com/page2">
+ <img height="300" width="200">
+ </a>
+ <div style='height: %d;'></div>
+ </body>)HTML",
+ kViewportHeight / 2, 10 * kViewportHeight));
+
+ Element* anchor = GetDocument().getElementById("anchor");
+ HTMLAnchorElement* anchor_element = ToHTMLAnchorElement(anchor);
+
+ auto feature =
+ AnchorElementMetrics::MaybeExtractMetricsClicked(anchor_element).value();
+ EXPECT_FLOAT_EQ(0.25, feature.GetRatioArea());
+ EXPECT_FLOAT_EQ(0.25, feature.GetRatioVisibleArea());
+ EXPECT_FLOAT_EQ(0.5, feature.GetRatioDistanceTopToVisibleTop());
+ EXPECT_FLOAT_EQ(0.75, feature.GetRatioDistanceCenterToVisibleTop());
+ EXPECT_FLOAT_EQ(0.5, feature.GetRatioDistanceRootTop());
+ EXPECT_FLOAT_EQ(10, feature.GetRatioDistanceRootBottom());
+ EXPECT_FALSE(feature.GetIsInIframe());
+ EXPECT_TRUE(feature.GetContainsImage());
+ EXPECT_TRUE(feature.GetIsSameHost());
+ EXPECT_FALSE(feature.GetIsUrlIncrementedByOne());
+}
+
+// The main frame contains an anchor element.
+// Features of the element are extracted.
+// Then the test scrolls down to check features again.
+TEST_F(AnchorElementMetricsTest, AnchorFeatureExtract) {
+ SimRequest main_resource("https://example.com/", "text/html");
+
+ LoadURL("https://example.com/");
+
+ main_resource.Complete(String::Format(
+ R"HTML(
+ <body style='margin: 0px'>
+ <div style='height: %dpx;'></div>
+ <a id='anchor' href="https://b.example.com">example</a>
+ <div style='height: %d;'></div>
+ </body>)HTML",
+ 2 * kViewportHeight, 10 * kViewportHeight));
+
+ Element* anchor = GetDocument().getElementById("anchor");
+ HTMLAnchorElement* anchor_element = ToHTMLAnchorElement(anchor);
+
+ auto feature =
+ AnchorElementMetrics::MaybeExtractMetricsClicked(anchor_element).value();
+ EXPECT_GT(feature.GetRatioArea(), 0);
+ EXPECT_FLOAT_EQ(feature.GetRatioDistanceRootTop(), 2);
+ EXPECT_FLOAT_EQ(feature.GetRatioDistanceTopToVisibleTop(), 2);
+ EXPECT_EQ(feature.GetIsInIframe(), false);
+
+ // Element not in the viewport.
+ EXPECT_GT(feature.GetRatioArea(), 0);
+ EXPECT_FLOAT_EQ(0, feature.GetRatioVisibleArea());
+ EXPECT_FLOAT_EQ(2, feature.GetRatioDistanceTopToVisibleTop());
+ EXPECT_LT(2, feature.GetRatioDistanceCenterToVisibleTop());
+ EXPECT_FLOAT_EQ(2, feature.GetRatioDistanceRootTop());
+ EXPECT_FLOAT_EQ(10, feature.GetRatioDistanceRootBottom());
+ EXPECT_FALSE(feature.GetIsInIframe());
+ EXPECT_FALSE(feature.GetContainsImage());
+ EXPECT_FALSE(feature.GetIsSameHost());
+ EXPECT_FALSE(feature.GetIsUrlIncrementedByOne());
+
+ // Scroll down to the anchor element.
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(0, kViewportHeight * 1.5), kProgrammaticScroll);
+
+ auto feature2 =
+ AnchorElementMetrics::MaybeExtractMetricsClicked(anchor_element).value();
+ EXPECT_LT(0, feature2.GetRatioVisibleArea());
+ EXPECT_FLOAT_EQ(0.5, feature2.GetRatioDistanceTopToVisibleTop());
+ EXPECT_LT(0.5, feature2.GetRatioDistanceCenterToVisibleTop());
+ EXPECT_FLOAT_EQ(2, feature2.GetRatioDistanceRootTop());
+ EXPECT_FLOAT_EQ(10, feature2.GetRatioDistanceRootBottom());
+}
+
+// The main frame contains an iframe. The iframe contains an anchor element.
+// Features of the element are extracted.
+// Then the test scrolls down in the main frame to check features again.
+// Then the test scrolls down in the iframe to check features again.
+TEST_F(AnchorElementMetricsTest, AnchorFeatureInIframe) {
+ SimRequest main_resource("https://example.com/page1", "text/html");
+ SimRequest iframe_resource("https://example.com/iframe.html", "text/html");
+ SimRequest image_resource("https://example.com/cat.png", "image/png");
+
+ LoadURL("https://example.com/page1");
+
+ main_resource.Complete(String::Format(
+ R"HTML(
+ <body style='margin: 0px'>
+ <div style='height: %dpx;'></div>
+ <iframe id='iframe' src='https://example.com/iframe.html'
+ style='width: 300px; height: %dpx;
+ border-style: none; padding: 0px; margin: 0px;'></iframe>
+ <div style='height: %dpx;'></div>
+ </body>)HTML",
+ 2 * kViewportHeight, kViewportHeight / 2, 10 * kViewportHeight));
+
+ iframe_resource.Complete(String::Format(
+ R"HTML(
+ <body style='margin: 0px'>
+ <div style='height: %dpx;'></div>
+ <a id='anchor' href="https://example.com/page2">example</a>
+ <div style='height: %dpx;'></div>
+ </body>)HTML",
+ kViewportHeight / 2, 5 * kViewportHeight));
+
+ Element* iframe = GetDocument().getElementById("iframe");
+ HTMLIFrameElement* iframe_element = ToHTMLIFrameElement(iframe);
+ Frame* sub = iframe_element->ContentFrame();
+ LocalFrame* subframe = ToLocalFrame(sub);
+
+ Element* anchor = subframe->GetDocument()->getElementById("anchor");
+ HTMLAnchorElement* anchor_element = ToHTMLAnchorElement(anchor);
+
+ auto feature =
+ AnchorElementMetrics::MaybeExtractMetricsClicked(anchor_element).value();
+ EXPECT_LT(0, feature.GetRatioArea());
+ EXPECT_FLOAT_EQ(0, feature.GetRatioVisibleArea());
+ EXPECT_FLOAT_EQ(2.5, feature.GetRatioDistanceTopToVisibleTop());
+ EXPECT_LT(2.5, feature.GetRatioDistanceCenterToVisibleTop());
+ EXPECT_FLOAT_EQ(2.5, feature.GetRatioDistanceRootTop());
+ EXPECT_TRUE(feature.GetIsInIframe());
+ EXPECT_FALSE(feature.GetContainsImage());
+ EXPECT_TRUE(feature.GetIsSameHost());
+ EXPECT_TRUE(feature.GetIsUrlIncrementedByOne());
+
+ // Scroll down the main frame.
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(0, kViewportHeight * 1.8), kProgrammaticScroll);
+
+ auto feature2 =
+ AnchorElementMetrics::MaybeExtractMetricsClicked(anchor_element).value();
+ EXPECT_LT(0, feature2.GetRatioVisibleArea());
+ EXPECT_FLOAT_EQ(0.7, feature2.GetRatioDistanceTopToVisibleTop());
+ EXPECT_FLOAT_EQ(2.5, feature2.GetRatioDistanceRootTop());
+
+ // Scroll down inside iframe. Now the anchor element is visible.
+ subframe->View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(0, kViewportHeight * 0.2), kProgrammaticScroll);
+
+ auto feature3 =
+ AnchorElementMetrics::MaybeExtractMetricsClicked(anchor_element).value();
+ EXPECT_LT(0, feature3.GetRatioVisibleArea());
+ EXPECT_FLOAT_EQ(0.5, feature3.GetRatioDistanceTopToVisibleTop());
+ EXPECT_FLOAT_EQ(2.5, feature3.GetRatioDistanceRootTop());
+ // The distance is expected to be 10.2 - height of the anchor element.
+ EXPECT_GT(10.2, feature3.GetRatioDistanceRootBottom());
+}
+
+} // namespace blink
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 b6323284d26..f0dc7b1ac34 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
@@ -13,22 +13,25 @@
#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/fileapi/blob.h"
+#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/graphics/image_data_buffer.h"
#include "third_party/blink/renderer/platform/histogram.h"
+#include "third_party/blink/renderer/platform/image-encoders/image_encoder_utils.h"
+#include "third_party/blink/renderer/platform/scheduler/public/background_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
-#include "third_party/blink/renderer/platform/threading/background_task_runner.h"
#include "third_party/blink/renderer/platform/web_task_runner.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
+#include "third_party/skia/include/core/SkColorSpaceXform.h"
#include "third_party/skia/include/core/SkSurface.h"
namespace blink {
namespace {
-const double kSlackBeforeDeadline =
- 0.001; // a small slack period between deadline and current time for safety
+// a small slack period between deadline and current time for safety
+constexpr TimeDelta kSlackBeforeDeadline = TimeDelta::FromMilliseconds(1);
/* The value is based on user statistics on Nov 2017. */
#if (defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN))
@@ -50,10 +53,8 @@ const double kIdleTaskCompleteTimeoutDelayMs = 5700.0;
const double kIdleTaskCompleteTimeoutDelayMs = 9000.0;
#endif
-bool IsDeadlineNearOrPassed(double deadline_seconds) {
- return (deadline_seconds - kSlackBeforeDeadline -
- CurrentTimeTicksInSeconds() <=
- 0);
+bool IsDeadlineNearOrPassed(TimeTicks deadline) {
+ return CurrentTimeTicks() >= deadline - kSlackBeforeDeadline;
}
String ConvertMimeTypeEnumToString(ImageEncoder::MimeType mime_type_enum) {
@@ -103,47 +104,47 @@ enum ElapsedTimeHistogramType {
void RecordElapsedTimeHistogram(ElapsedTimeHistogramType type,
ImageEncoder::MimeType mime_type,
- double elapsed_time) {
+ TimeDelta elapsed_time) {
if (type == kInitiateEncodingDelay) {
if (mime_type == ImageEncoder::kMimeTypePng) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(
CustomCountHistogram, to_blob_png_initiate_encoding_counter,
("Blink.Canvas.ToBlob.InitiateEncodingDelay.PNG", 0, 10000000, 50));
- to_blob_png_initiate_encoding_counter.Count(elapsed_time * 1000000.0);
+ to_blob_png_initiate_encoding_counter.CountMicroseconds(elapsed_time);
} else if (mime_type == ImageEncoder::kMimeTypeJpeg) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(
CustomCountHistogram, to_blob_jpeg_initiate_encoding_counter,
("Blink.Canvas.ToBlob.InitiateEncodingDelay.JPEG", 0, 10000000, 50));
- to_blob_jpeg_initiate_encoding_counter.Count(elapsed_time * 1000000.0);
+ to_blob_jpeg_initiate_encoding_counter.CountMicroseconds(elapsed_time);
}
} else if (type == kCompleteEncodingDelay) {
if (mime_type == ImageEncoder::kMimeTypePng) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(
CustomCountHistogram, to_blob_png_idle_encode_counter,
("Blink.Canvas.ToBlob.CompleteEncodingDelay.PNG", 0, 10000000, 50));
- to_blob_png_idle_encode_counter.Count(elapsed_time * 1000000.0);
+ to_blob_png_idle_encode_counter.CountMicroseconds(elapsed_time);
} else if (mime_type == ImageEncoder::kMimeTypeJpeg) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(
CustomCountHistogram, to_blob_jpeg_idle_encode_counter,
("Blink.Canvas.ToBlob.CompleteEncodingDelay.JPEG", 0, 10000000, 50));
- to_blob_jpeg_idle_encode_counter.Count(elapsed_time * 1000000.0);
+ to_blob_jpeg_idle_encode_counter.CountMicroseconds(elapsed_time);
}
} else if (type == kToBlobDuration) {
if (mime_type == ImageEncoder::kMimeTypePng) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(
CustomCountHistogram, to_blob_png_counter,
("Blink.Canvas.ToBlobDuration.PNG", 0, 10000000, 50));
- to_blob_png_counter.Count(elapsed_time * 1000000.0);
+ to_blob_png_counter.CountMicroseconds(elapsed_time);
} else if (mime_type == ImageEncoder::kMimeTypeJpeg) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(
CustomCountHistogram, to_blob_jpeg_counter,
("Blink.Canvas.ToBlobDuration.JPEG", 0, 10000000, 50));
- to_blob_jpeg_counter.Count(elapsed_time * 1000000.0);
+ to_blob_jpeg_counter.CountMicroseconds(elapsed_time);
} else if (mime_type == ImageEncoder::kMimeTypeWebp) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(
CustomCountHistogram, to_blob_webp_counter,
("Blink.Canvas.ToBlobDuration.WEBP", 0, 10000000, 50));
- to_blob_webp_counter.Count(elapsed_time * 1000000.0);
+ to_blob_webp_counter.CountMicroseconds(elapsed_time);
}
}
}
@@ -154,40 +155,50 @@ CanvasAsyncBlobCreator* CanvasAsyncBlobCreator::Create(
scoped_refptr<StaticBitmapImage> image,
const String& mime_type,
V8BlobCallback* callback,
- double start_time,
+ ToBlobFunctionType function_type,
+ TimeTicks start_time,
ExecutionContext* context) {
- return new CanvasAsyncBlobCreator(image,
- ConvertMimeTypeStringToEnum(mime_type),
- callback, start_time, context, nullptr);
+ ImageEncodeOptions options;
+ options.setType(mime_type);
+ return new CanvasAsyncBlobCreator(image, options, function_type, callback,
+ start_time, context, nullptr);
}
CanvasAsyncBlobCreator* CanvasAsyncBlobCreator::Create(
scoped_refptr<StaticBitmapImage> image,
- const String& mime_type,
- double start_time,
+ const ImageEncodeOptions& options,
+ ToBlobFunctionType function_type,
+ TimeTicks start_time,
ExecutionContext* context,
ScriptPromiseResolver* resolver) {
- return new CanvasAsyncBlobCreator(image,
- ConvertMimeTypeStringToEnum(mime_type),
- nullptr, start_time, context, resolver);
+ return new CanvasAsyncBlobCreator(image, options, function_type, nullptr,
+ start_time, context, resolver);
}
CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(
scoped_refptr<StaticBitmapImage> image,
- ImageEncoder::MimeType mime_type,
+ const ImageEncodeOptions& options,
+ ToBlobFunctionType function_type,
V8BlobCallback* callback,
- double start_time,
+ TimeTicks start_time,
ExecutionContext* context,
ScriptPromiseResolver* resolver)
: fail_encoder_initialization_for_test_(false),
image_(image),
context_(context),
- mime_type_(mime_type),
+ encode_options_(options),
+ function_type_(function_type),
start_time_(start_time),
static_bitmap_image_loaded_(false),
callback_(ToV8PersistentCallbackFunction(callback)),
script_promise_resolver_(resolver) {
DCHECK(image);
+
+ String mime_type_string = ImageEncoderUtils::ToEncodingMimeType(
+ encode_options_.type(),
+ ImageEncoderUtils::kEncodeReasonConvertToBlobPromise);
+ mime_type_ = ConvertMimeTypeStringToEnum(mime_type_string);
+
// We use pixmap to access the image pixels. Make the image unaccelerated if
// necessary.
image_ = image_->MakeUnaccelerated();
@@ -208,15 +219,74 @@ CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(
}
}
- // toBlob always encodes in sRGB and does not include the color space
- // information.
- if (skia_image->colorSpace()) {
- image_ = image_->ConvertToColorSpace(SkColorSpace::MakeSRGB(),
- SkTransferFunctionBehavior::kIgnore);
- skia_image = image_->PaintImageForCurrentFrame().GetSkImage();
+ // For kHTMLCanvasToBlobCallback and kOffscreenCanvasConvertToBlobPromise
+ // to-blob function types, we color convert to sRGB and do not tag the image
+ // with any color space info.
+ // For kHTMLCanvasConvertToBlobPromise to-blob function type, we color
+ // covnert to the requested color space and pixel format.
+ if (function_type_ != kHTMLCanvasConvertToBlobPromise) {
+ if (skia_image->colorSpace()) {
+ image_ = image_->ConvertToColorSpace(SkColorSpace::MakeSRGB());
+ skia_image = image_->PaintImageForCurrentFrame().GetSkImage();
+ }
+
+ if (skia_image->peekPixels(&src_data_)) {
+ src_data_.setColorSpace(nullptr);
+ static_bitmap_image_loaded_ = true;
+ }
+ DCHECK(!src_data_.colorSpace());
+ } else {
+ sk_sp<SkColorSpace> blob_color_space =
+ BlobColorSpaceToSkColorSpace(encode_options_.colorSpace());
+
+ if (!SkColorSpace::Equals(skia_image->colorSpace(),
+ blob_color_space.get())) {
+ if (!skia_image->colorSpace()) {
+ skia_image->peekPixels(&src_data_);
+ src_data_.setColorSpace(SkColorSpace::MakeSRGB());
+ skia_image = SkImage::MakeFromRaster(src_data_, nullptr, nullptr);
+ }
+ DCHECK(skia_image->colorSpace());
+ skia_image = skia_image->makeColorSpace(blob_color_space);
+ image_ = StaticBitmapImage::Create(skia_image);
+ }
+
+ if (skia_image->peekPixels(&src_data_))
+ static_bitmap_image_loaded_ = true;
+
+ // If the source image is 8 bit per channel but the blob is requested in
+ // 16 bpc PNG, we need to ensure the color type of the pixmap is
+ // kRGBA_F16_SkColorType to kick in 16 bit encoding in SkPngEncoder. Since
+ // SkPixmap only holds a pointer to data, we need a helper data member here.
+ if (mime_type_ == ImageEncoder::kMimeTypePng &&
+ encode_options_.pixelFormat() == kRGBA16ImagePixelFormatName &&
+ src_data_.colorType() == kN32_SkColorType) {
+ size_t data_length = src_data_.width() * src_data_.height() *
+ SkColorTypeBytesPerPixel(kRGBA_F16_SkColorType);
+ png_16bit_data_helper_ = SkData::MakeUninitialized(data_length);
+ SkColorSpaceXform::ColorFormat src_format =
+ SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat;
+ if (kN32_SkColorType == kBGRA_8888_SkColorType)
+ src_format = SkColorSpaceXform::ColorFormat::kBGRA_8888_ColorFormat;
+ if (SkColorSpaceXform::Apply(
+ src_data_.colorSpace(),
+ SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat,
+ png_16bit_data_helper_->writable_data(), src_data_.colorSpace(),
+ src_format, src_data_.addr(),
+ src_data_.width() * src_data_.height(),
+ SkColorSpaceXform::AlphaOp::kPreserve_AlphaOp)) {
+ SkImageInfo info = SkImageInfo::Make(
+ src_data_.width(), src_data_.height(), kRGBA_F16_SkColorType,
+ src_data_.alphaType(), src_data_.info().refColorSpace());
+ src_data_.reset(info, png_16bit_data_helper_->data(),
+ info.minRowBytes());
+ }
+ skia_image = SkImage::MakeFromRaster(src_data_, nullptr, nullptr);
+ image_ = StaticBitmapImage::Create(skia_image);
+ }
}
- if (skia_image->peekPixels(&src_data_)) {
+ if (static_bitmap_image_loaded_) {
// Ensure that the size of the to-be-encoded-image does not pass the maximum
// size supported by the encoders.
int max_dimension = ImageEncoder::MaxDimension(mime_type_);
@@ -226,11 +296,7 @@ CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(
std::min(info.height(), max_dimension));
src_data_.reset(info, src_data_.addr(), src_data_.rowBytes());
}
-
- src_data_.setColorSpace(nullptr);
- static_bitmap_image_loaded_ = true;
}
- DCHECK(!src_data_.colorSpace());
idle_task_status_ = kIdleTaskNotSupported;
num_rows_completed_ = 0;
@@ -238,11 +304,6 @@ CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(
parent_frame_task_runner_ =
context->GetTaskRunner(TaskType::kCanvasBlobSerialization);
}
- if (script_promise_resolver_) {
- function_type_ = kOffscreenCanvasToBlobPromise;
- } else {
- function_type_ = kHTMLCanvasToBlobCallback;
- }
}
CanvasAsyncBlobCreator::~CanvasAsyncBlobCreator() = default;
@@ -256,6 +317,13 @@ void CanvasAsyncBlobCreator::Dispose() {
image_ = nullptr;
}
+ImageEncodeOptions CanvasAsyncBlobCreator::GetImageEncodeOptionsForMimeType(
+ ImageEncoder::MimeType mime_type) {
+ ImageEncodeOptions encode_options;
+ encode_options.setType(ConvertMimeTypeEnumToString(mime_type));
+ return encode_options;
+}
+
bool CanvasAsyncBlobCreator::EncodeImage(const double& quality) {
std::unique_ptr<ImageDataBuffer> buffer = ImageDataBuffer::Create(src_data_);
if (!buffer)
@@ -273,7 +341,8 @@ void CanvasAsyncBlobCreator::ScheduleAsyncBlobCreation(const double& quality) {
}
if (mime_type_ == ImageEncoder::kMimeTypeWebp) {
if (!IsMainThread()) {
- DCHECK(function_type_ == kOffscreenCanvasToBlobPromise);
+ DCHECK(function_type_ == kHTMLCanvasConvertToBlobPromise ||
+ function_type_ == kOffscreenCanvasConvertToBlobPromise);
// When OffscreenCanvas.convertToBlob() occurs on worker thread,
// we do not need to use background task runner to reduce load on main.
// So we just directly encode images on the worker thread.
@@ -293,7 +362,7 @@ void CanvasAsyncBlobCreator::ScheduleAsyncBlobCreation(const double& quality) {
WrapPersistent(this)));
} else {
- BackgroundTaskRunner::PostOnBackgroundThread(
+ BackgroundScheduler::PostOnBackgroundThread(
FROM_HERE,
CrossThreadBind(&CanvasAsyncBlobCreator::EncodeImageOnEncoderThread,
WrapCrossThreadPersistent(this), quality));
@@ -313,20 +382,20 @@ void CanvasAsyncBlobCreator::ScheduleAsyncBlobCreation(const double& quality) {
}
void CanvasAsyncBlobCreator::ScheduleInitiateEncoding(double quality) {
- schedule_idle_task_start_time_ = WTF::CurrentTimeTicksInSeconds();
+ schedule_idle_task_start_time_ = WTF::CurrentTimeTicks();
Platform::Current()->CurrentThread()->Scheduler()->PostIdleTask(
FROM_HERE, WTF::Bind(&CanvasAsyncBlobCreator::InitiateEncoding,
WrapPersistent(this), quality));
}
void CanvasAsyncBlobCreator::InitiateEncoding(double quality,
- double deadline_seconds) {
+ TimeTicks deadline) {
if (idle_task_status_ == kIdleTaskSwitchedToImmediateTask) {
return;
}
RecordElapsedTimeHistogram(
kInitiateEncodingDelay, mime_type_,
- WTF::CurrentTimeTicksInSeconds() - schedule_idle_task_start_time_);
+ WTF::CurrentTimeTicks() - schedule_idle_task_start_time_);
DCHECK(idle_task_status_ == kIdleTaskNotStarted);
idle_task_status_ = kIdleTaskStarted;
@@ -337,17 +406,17 @@ void CanvasAsyncBlobCreator::InitiateEncoding(double quality,
}
// Re-use this time variable to collect data on complete encoding delay
- schedule_idle_task_start_time_ = WTF::CurrentTimeTicksInSeconds();
- IdleEncodeRows(deadline_seconds);
+ schedule_idle_task_start_time_ = WTF::CurrentTimeTicks();
+ IdleEncodeRows(deadline);
}
-void CanvasAsyncBlobCreator::IdleEncodeRows(double deadline_seconds) {
+void CanvasAsyncBlobCreator::IdleEncodeRows(TimeTicks deadline) {
if (idle_task_status_ == kIdleTaskSwitchedToImmediateTask) {
return;
}
for (int y = num_rows_completed_; y < src_data_.height(); ++y) {
- if (IsDeadlineNearOrPassed(deadline_seconds)) {
+ if (IsDeadlineNearOrPassed(deadline)) {
num_rows_completed_ = y;
Platform::Current()->CurrentThread()->Scheduler()->PostIdleTask(
FROM_HERE, WTF::Bind(&CanvasAsyncBlobCreator::IdleEncodeRows,
@@ -364,10 +433,10 @@ void CanvasAsyncBlobCreator::IdleEncodeRows(double deadline_seconds) {
num_rows_completed_ = src_data_.height();
idle_task_status_ = kIdleTaskCompleted;
- double elapsed_time =
- WTF::CurrentTimeTicksInSeconds() - schedule_idle_task_start_time_;
+ TimeDelta elapsed_time =
+ WTF::CurrentTimeTicks() - schedule_idle_task_start_time_;
RecordElapsedTimeHistogram(kCompleteEncodingDelay, mime_type_, elapsed_time);
- if (IsDeadlineNearOrPassed(deadline_seconds)) {
+ if (IsDeadlineNearOrPassed(deadline)) {
context_->GetTaskRunner(TaskType::kCanvasBlobSerialization)
->PostTask(FROM_HERE,
WTF::Bind(&CanvasAsyncBlobCreator::CreateBlobAndReturnResult,
@@ -405,7 +474,7 @@ void CanvasAsyncBlobCreator::ForceEncodeRowsOnCurrentThread() {
void CanvasAsyncBlobCreator::CreateBlobAndReturnResult() {
RecordIdleTaskStatusHistogram(idle_task_status_);
RecordElapsedTimeHistogram(kToBlobDuration, mime_type_,
- WTF::CurrentTimeTicksInSeconds() - start_time_);
+ WTF::CurrentTimeTicks() - start_time_);
Blob* result_blob = Blob::Create(encoded_image_.data(), encoded_image_.size(),
ConvertMimeTypeEnumToString(mime_type_));
@@ -435,8 +504,9 @@ void CanvasAsyncBlobCreator::CreateNullAndReturnResult() {
V8BlobCallback>::InvokeAndReportException,
WrapPersistent(callback_.Get()), nullptr, nullptr));
} else {
- script_promise_resolver_->Reject(DOMException::Create(
- kEncodingError, "Encoding of the source image has failed."));
+ script_promise_resolver_->Reject(
+ DOMException::Create(DOMExceptionCode::kEncodingError,
+ "Encoding of the source image has failed."));
}
// Avoid unwanted retention, see dispose().
Dispose();
@@ -468,7 +538,6 @@ bool CanvasAsyncBlobCreator::InitializeEncoder(double quality) {
SkJpegEncoder::Options options;
options.fQuality = ImageEncoder::ComputeJpegQuality(quality);
options.fAlphaOption = SkJpegEncoder::AlphaOption::kBlendOnBlack;
- options.fBlendBehavior = SkTransferFunctionBehavior::kIgnore;
if (options.fQuality == 100) {
options.fDownsample = SkJpegEncoder::Downsample::k444;
}
@@ -483,7 +552,6 @@ bool CanvasAsyncBlobCreator::InitializeEncoder(double quality) {
SkPngEncoder::Options options;
options.fFilterFlags = SkPngEncoder::FilterFlag::kSub;
options.fZLibLevel = 3;
- options.fUnpremulBehavior = SkTransferFunctionBehavior::kIgnore;
encoder_ = ImageEncoder::Create(&encoded_image_, src_data_, options);
}
@@ -561,4 +629,24 @@ void CanvasAsyncBlobCreator::Trace(blink::Visitor* visitor) {
visitor->Trace(script_promise_resolver_);
}
+sk_sp<SkColorSpace> CanvasAsyncBlobCreator::BlobColorSpaceToSkColorSpace(
+ String blob_color_space) {
+ SkColorSpace::Gamut gamut = SkColorSpace::kSRGB_Gamut;
+ if (blob_color_space == kDisplayP3ImageColorSpaceName)
+ gamut = SkColorSpace::kDCIP3_D65_Gamut;
+ else if (blob_color_space == kRec2020ImageColorSpaceName)
+ gamut = SkColorSpace::kRec2020_Gamut;
+ return SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, gamut);
+}
+
+bool CanvasAsyncBlobCreator::EncodeImageForConvertToBlobTest() {
+ if (!static_bitmap_image_loaded_)
+ return false;
+ std::unique_ptr<ImageDataBuffer> buffer = ImageDataBuffer::Create(src_data_);
+ if (!buffer)
+ return false;
+ return buffer->EncodeImage(encode_options_.type(), encode_options_.quality(),
+ &encoded_image_);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h b/chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h
index 23e1f8b2d4c..3b2875d712f 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_blob_callback.h"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/html/canvas/image_encode_options.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
@@ -24,22 +25,16 @@ namespace blink {
class ExecutionContext;
+constexpr const char* kSRGBImageColorSpaceName = "srgb";
+constexpr const char* kRec2020ImageColorSpaceName = "rec2020";
+constexpr const char* kDisplayP3ImageColorSpaceName = "display-p3";
+
+constexpr const char* kRGBA8ImagePixelFormatName = "8-8-8-8";
+constexpr const char* kRGBA16ImagePixelFormatName = "uint16";
+
class CORE_EXPORT CanvasAsyncBlobCreator
: public GarbageCollectedFinalized<CanvasAsyncBlobCreator> {
public:
- static CanvasAsyncBlobCreator* Create(scoped_refptr<StaticBitmapImage>,
- const String& mime_type,
- V8BlobCallback*,
- double start_time,
- ExecutionContext*);
- static CanvasAsyncBlobCreator* Create(scoped_refptr<StaticBitmapImage>,
- const String& mime_type,
- double start_time,
- ExecutionContext*,
- ScriptPromiseResolver*);
-
- void ScheduleAsyncBlobCreation(const double& quality);
- virtual ~CanvasAsyncBlobCreator();
// This enum is used to back an UMA histogram, and should therefore be treated
// as append-only.
@@ -53,29 +48,56 @@ class CORE_EXPORT CanvasAsyncBlobCreator
// types
kIdleTaskCount, // Should not be seen in production
};
-
enum ToBlobFunctionType {
kHTMLCanvasToBlobCallback,
- kOffscreenCanvasToBlobPromise,
+ kHTMLCanvasConvertToBlobPromise,
+ kOffscreenCanvasConvertToBlobPromise,
kNumberOfToBlobFunctionTypes
};
+ static CanvasAsyncBlobCreator* Create(scoped_refptr<StaticBitmapImage>,
+ const String& mime_type,
+ V8BlobCallback*,
+ ToBlobFunctionType function_type,
+ TimeTicks start_time,
+ ExecutionContext*);
+ static CanvasAsyncBlobCreator* Create(scoped_refptr<StaticBitmapImage>,
+ const ImageEncodeOptions& options,
+ ToBlobFunctionType function_type,
+ TimeTicks start_time,
+ ExecutionContext*,
+ ScriptPromiseResolver*);
+
+ void ScheduleAsyncBlobCreation(const double& quality);
+ virtual ~CanvasAsyncBlobCreator();
+
// Methods are virtual for mocking in unit tests
virtual void SignalTaskSwitchInStartTimeoutEventForTesting() {}
virtual void SignalTaskSwitchInCompleteTimeoutEventForTesting() {}
virtual void Trace(blink::Visitor*);
+ static sk_sp<SkColorSpace> BlobColorSpaceToSkColorSpace(
+ String blob_color_space);
+
+ bool EncodeImageForConvertToBlobTest();
+ Vector<unsigned char> GetEncodedImageForConvertToBlobTest() {
+ return encoded_image_;
+ }
+
protected:
CanvasAsyncBlobCreator(scoped_refptr<StaticBitmapImage>,
- ImageEncoder::MimeType,
+ const ImageEncodeOptions&,
+ ToBlobFunctionType,
V8BlobCallback*,
- double,
+ TimeTicks start_time,
ExecutionContext*,
ScriptPromiseResolver*);
+ static ImageEncodeOptions GetImageEncodeOptionsForMimeType(
+ ImageEncoder::MimeType);
// Methods are virtual for unit testing
virtual void ScheduleInitiateEncoding(double quality);
- virtual void IdleEncodeRows(double deadline_seconds);
+ virtual void IdleEncodeRows(TimeTicks deadline);
virtual void PostDelayedTaskToCurrentThread(const base::Location&,
base::OnceClosure,
double delay_ms);
@@ -83,7 +105,7 @@ class CORE_EXPORT CanvasAsyncBlobCreator
virtual void CreateBlobAndReturnResult();
virtual void CreateNullAndReturnResult();
- void InitiateEncoding(double quality, double deadline_seconds);
+ void InitiateEncoding(double quality, TimeTicks deadline);
protected:
IdleTaskStatus idle_task_status_;
@@ -101,15 +123,16 @@ class CORE_EXPORT CanvasAsyncBlobCreator
Member<ExecutionContext> context_;
SkPixmap src_data_;
- const ImageEncoder::MimeType mime_type_;
+ ImageEncoder::MimeType mime_type_;
+ const ImageEncodeOptions encode_options_;
+ ToBlobFunctionType function_type_;
+ sk_sp<SkData> png_16bit_data_helper_;
// Chrome metrics use
- double start_time_;
- double schedule_idle_task_start_time_;
+ TimeTicks start_time_;
+ TimeTicks schedule_idle_task_start_time_;
bool static_bitmap_image_loaded_;
- ToBlobFunctionType function_type_;
-
// Used when CanvasAsyncBlobCreator runs on main thread only
scoped_refptr<base::SingleThreadTaskRunner> parent_frame_task_runner_;
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator_test.cc b/chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator_test.cc
index 31f98290f20..e3b52699d79 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator_test.cc
@@ -9,6 +9,8 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/html/canvas/image_data.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
+#include "third_party/blink/renderer/platform/graphics/color_correction_test_utils.h"
+#include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/skia/include/core/SkSurface.h"
@@ -23,12 +25,14 @@ class MockCanvasAsyncBlobCreator : public CanvasAsyncBlobCreator {
ImageEncoder::MimeType mime_type,
Document* document,
bool fail_encoder_initialization = false)
- : CanvasAsyncBlobCreator(image,
- mime_type,
- nullptr,
- 0,
- document,
- nullptr) {
+ : CanvasAsyncBlobCreator(
+ image,
+ CanvasAsyncBlobCreator::GetImageEncodeOptionsForMimeType(mime_type),
+ kHTMLCanvasToBlobCallback,
+ nullptr,
+ TimeTicks(),
+ document,
+ nullptr) {
if (fail_encoder_initialization)
fail_encoder_initialization_for_test_ = true;
}
@@ -99,11 +103,10 @@ class MockCanvasAsyncBlobCreatorWithoutComplete
Platform::Current()->MainThread()->GetTaskRunner()->PostTask(
FROM_HERE,
WTF::Bind(&MockCanvasAsyncBlobCreatorWithoutComplete::InitiateEncoding,
- WrapPersistent(this), quality,
- std::numeric_limits<double>::max()));
+ WrapPersistent(this), quality, TimeTicks::Max()));
}
- void IdleEncodeRows(double deadline_seconds) override {
+ void IdleEncodeRows(TimeTicks deadline) override {
// Deliberately make idleEncodeRows do nothing so that idle task never
// completes
}
@@ -213,4 +216,102 @@ TEST_F(CanvasAsyncBlobCreatorTest, IdleTaskFailedWhenStartTimeoutEventHappens) {
AsyncBlobCreator()->GetIdleTaskStatus());
}
+static sk_sp<SkImage> DrawAndReturnImage(
+ const std::pair<sk_sp<SkColorSpace>, SkColorType>& color_space_param) {
+ SkPaint transparentRed, transparentGreen, transparentBlue, transparentBlack;
+ transparentRed.setARGB(128, 155, 27, 27);
+ transparentGreen.setARGB(128, 27, 155, 27);
+ transparentBlue.setARGB(128, 27, 27, 155);
+ transparentBlack.setARGB(128, 27, 27, 27);
+
+ SkImageInfo info = SkImageInfo::Make(2, 2, color_space_param.second,
+ SkAlphaType::kPremul_SkAlphaType,
+ color_space_param.first);
+ sk_sp<SkSurface> surface = SkSurface::MakeRaster(info);
+ surface->getCanvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), transparentRed);
+ surface->getCanvas()->drawRect(SkRect::MakeXYWH(1, 0, 1, 1),
+ transparentGreen);
+ surface->getCanvas()->drawRect(SkRect::MakeXYWH(0, 1, 1, 1), transparentBlue);
+ surface->getCanvas()->drawRect(SkRect::MakeXYWH(1, 1, 1, 1),
+ transparentBlack);
+ return surface->makeImageSnapshot();
+}
+
+TEST_F(CanvasAsyncBlobCreatorTest, ColorManagedConvertToBlob) {
+ std::list<std::pair<sk_sp<SkColorSpace>, SkColorType>> color_space_params;
+ color_space_params.push_back(std::pair<sk_sp<SkColorSpace>, SkColorType>(
+ SkColorSpace::MakeSRGB(), kN32_SkColorType));
+ color_space_params.push_back(std::pair<sk_sp<SkColorSpace>, SkColorType>(
+ SkColorSpace::MakeSRGBLinear(), kRGBA_F16_SkColorType));
+ color_space_params.push_back(std::pair<sk_sp<SkColorSpace>, SkColorType>(
+ SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma,
+ SkColorSpace::kDCIP3_D65_Gamut),
+ kRGBA_F16_SkColorType));
+ color_space_params.push_back(std::pair<sk_sp<SkColorSpace>, SkColorType>(
+ SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma,
+ SkColorSpace::kRec2020_Gamut),
+ kRGBA_F16_SkColorType));
+
+ std::list<String> blob_mime_types = {"image/png", "image/webp", "image/jpeg"};
+ std::list<String> blob_color_spaces = {kSRGBImageColorSpaceName,
+ kDisplayP3ImageColorSpaceName,
+ kRec2020ImageColorSpaceName};
+ // SkPngEncoder still does not support 16bit PNG encoding. Add
+ // kRGBA16ImagePixelFormatName to blob_pixel_formats when this is fixed.
+ // crbug.com/840372
+ // bugs.chromium.org/p/skia/issues/detail?id=7926
+ // https://fiddle.skia.org/c/b795f0141f4e1a5773bf9494b5bc87b5
+ std::list<String> blob_pixel_formats = {kRGBA8ImagePixelFormatName};
+
+ // The maximum difference locally observed is 3.
+ const unsigned uint8_color_tolerance = 5;
+ const float f16_color_tolerance = 0.01;
+ // The maximum difference locally observed has the order of e^-6.
+ const float xyz_d50_color_space_component_tolerance = 0.001;
+
+ for (auto color_space_param : color_space_params) {
+ for (auto blob_mime_type : blob_mime_types) {
+ for (auto blob_color_space : blob_color_spaces) {
+ for (auto blob_pixel_format : blob_pixel_formats) {
+ // Create the StaticBitmapImage in canvas_color_space
+ sk_sp<SkImage> source_image = DrawAndReturnImage(color_space_param);
+ scoped_refptr<UnacceleratedStaticBitmapImage> source_bitmap_image =
+ UnacceleratedStaticBitmapImage::Create(source_image);
+
+ // Prepare encoding options
+ ImageEncodeOptions options;
+ options.setQuality(1);
+ options.setType(blob_mime_type);
+ options.setColorSpace(blob_color_space);
+ options.setPixelFormat(blob_pixel_format);
+
+ // Encode the image using CanvasAsyncBlobCreator
+ CanvasAsyncBlobCreator* async_blob_creator =
+ CanvasAsyncBlobCreator::Create(
+ source_bitmap_image, options,
+ CanvasAsyncBlobCreator::ToBlobFunctionType::
+ kHTMLCanvasConvertToBlobPromise,
+ TimeTicks(), &GetDocument(), nullptr);
+ ASSERT_TRUE(async_blob_creator->EncodeImageForConvertToBlobTest());
+
+ sk_sp<SkData> sk_data = SkData::MakeWithCopy(
+ async_blob_creator->GetEncodedImageForConvertToBlobTest().data(),
+ async_blob_creator->GetEncodedImageForConvertToBlobTest().size());
+ sk_sp<SkImage> decoded_img = SkImage::MakeFromEncoded(sk_data);
+
+ sk_sp<SkImage> ref_image = source_image->makeColorSpace(
+ CanvasAsyncBlobCreator::BlobColorSpaceToSkColorSpace(
+ blob_color_space));
+
+ // Jpeg does not support transparent images.
+ bool compare_alpha = (blob_mime_type != "image/jpeg");
+ ASSERT_TRUE(ColorCorrectionTestUtils::MatchSkImages(
+ ref_image, decoded_img, uint8_color_tolerance,
+ f16_color_tolerance, xyz_d50_color_space_component_tolerance,
+ compare_alpha));
+ }
+ }
+ }
+ }
+}
}
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_context_creation_attributes_core.h b/chromium/third_party/blink/renderer/core/html/canvas/canvas_context_creation_attributes_core.h
index 298e186289a..03da0840b0e 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/canvas_context_creation_attributes_core.h
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_context_creation_attributes_core.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_CANVAS_CONTEXT_CREATION_ATTRIBUTES_CORE_H_
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/events/event_target.h"
+#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/wtf/text/wtf_string.h"
@@ -33,7 +33,7 @@ class CORE_EXPORT CanvasContextCreationAttributesCore {
bool stencil = false;
// This attribute is of type XRDevice, defined in modules/xr/XRDevice.h
- Member<EventTargetWithInlineData> compatible_xr_device;
+ Member<ScriptWrappable> compatible_xr_device;
void Trace(blink::Visitor*);
};
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc b/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc
index 955fa40e8b2..bcde1d0e928 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.cc
@@ -58,7 +58,7 @@ CanvasRenderingContext::CanvasRenderingContext(
color_params_.SetOpacityMode(kOpaque);
}
- if (!OriginTrials::lowLatencyCanvasEnabled(host->GetTopExecutionContext()))
+ if (!OriginTrials::LowLatencyCanvasEnabled(host->GetTopExecutionContext()))
creation_attributes_.low_latency = false;
// Make m_creationAttributes reflect the effective colorSpace and pixelFormat
@@ -100,16 +100,6 @@ void CanvasRenderingContext::Dispose() {
Platform::Current()->CurrentThread()->RemoveTaskObserver(this);
}
- if (Host() && Host()->GetTopExecutionContext() &&
- Host()->GetTopExecutionContext()->IsWorkerGlobalScope()) {
- WorkerAnimationFrameProvider* provider =
- ToWorkerGlobalScope(Host()->GetTopExecutionContext())
- ->GetAnimationFrameProvider();
- if (provider) {
- provider->RemoveContextToDispatch(this);
- }
- }
-
// HTMLCanvasElement and CanvasRenderingContext have a circular reference.
// When the pair is no longer reachable, their destruction order is non-
// deterministic, so the first of the two to be destroyed needs to notify
@@ -160,6 +150,9 @@ CanvasRenderingContext::ContextType CanvasRenderingContext::ContextTypeFromId(
return kContextWebgl;
if (id == "webgl2")
return kContextWebgl2;
+ if (id == "webgl2-compute" &&
+ RuntimeEnabledFeatures::WebGL2ComputeContextEnabled())
+ return kContextWebgl2Compute;
if (id == "bitmaprenderer")
return kContextImageBitmap;
if (id == "xrpresent")
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h b/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h
index a47646c52a3..4e74a0202bb 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h
+++ b/chromium/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h
@@ -73,6 +73,7 @@ class CORE_EXPORT CanvasRenderingContext : public ScriptWrappable,
kContextWebgl2 = 4,
kContextImageBitmap = 5,
kContextXRPresent = 6,
+ kContextWebgl2Compute = 7,
kContextTypeCount,
};
@@ -136,7 +137,7 @@ class CORE_EXPORT CanvasRenderingContext : public ScriptWrappable,
// Canvas2D-specific interface
virtual bool Is2d() const { return false; }
- virtual void RestoreCanvasMatrixClipStack(PaintCanvas*) const {}
+ virtual void RestoreCanvasMatrixClipStack(cc::PaintCanvas*) const {}
virtual void Reset() {}
virtual void ClearRect(double x, double y, double width, double height) {}
virtual void DidSetSurfaceSize() {}
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 85f604991d1..76934b8437e 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
@@ -4,7 +4,10 @@
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/skia/include/core/SkSurface.h"
@@ -30,15 +33,150 @@ CanvasRenderingContextHost::CreateTransparentImage(const IntSize& size) const {
return StaticBitmapImage::Create(surface->makeImageSnapshot());
}
+void CanvasRenderingContextHost::Commit(scoped_refptr<CanvasResource>,
+ const SkIRect&) {
+ NOTIMPLEMENTED();
+}
+
bool CanvasRenderingContextHost::IsPaintable() const {
return (RenderingContext() && RenderingContext()->IsPaintable()) ||
IsValidImageSize(Size());
}
void CanvasRenderingContextHost::RestoreCanvasMatrixClipStack(
- PaintCanvas* canvas) const {
+ cc::PaintCanvas* canvas) const {
if (RenderingContext())
RenderingContext()->RestoreCanvasMatrixClipStack(canvas);
}
+bool CanvasRenderingContextHost::Is3d() const {
+ return RenderingContext() && RenderingContext()->Is3d();
+}
+
+bool CanvasRenderingContextHost::Is2d() const {
+ return RenderingContext() && RenderingContext()->Is2d();
+}
+
+CanvasResourceProvider*
+CanvasRenderingContextHost::GetOrCreateCanvasResourceProvider(
+ AccelerationHint hint) {
+ if (!ResourceProvider() && !did_fail_to_create_resource_provider_) {
+ if (IsValidImageSize(Size())) {
+ base::WeakPtr<CanvasResourceDispatcher> dispatcher =
+ GetOrCreateResourceDispatcher()
+ ? GetOrCreateResourceDispatcher()->GetWeakPtr()
+ : nullptr;
+ if (Is3d()) {
+ CanvasResourceProvider::PresentationMode presentation_mode =
+ RuntimeEnabledFeatures::WebGLImageChromiumEnabled()
+ ? CanvasResourceProvider::kAllowImageChromiumPresentationMode
+ : CanvasResourceProvider::kDefaultPresentationMode;
+
+ ReplaceResourceProvider(CanvasResourceProvider::Create(
+ Size(),
+ SharedGpuContext::IsGpuCompositingEnabled()
+ ? CanvasResourceProvider::kAcceleratedCompositedResourceUsage
+ : CanvasResourceProvider::kSoftwareCompositedResourceUsage,
+ SharedGpuContext::ContextProviderWrapper(),
+ 0, // msaa_sample_count
+ ColorParams(), presentation_mode, std::move(dispatcher)));
+ } else {
+ bool want_acceleration =
+ hint == kPreferAcceleration && ShouldAccelerate2dContext();
+
+ CanvasResourceProvider::ResourceUsage usage =
+ want_acceleration
+ ? CanvasResourceProvider::kAcceleratedCompositedResourceUsage
+ : CanvasResourceProvider::kSoftwareCompositedResourceUsage;
+
+ CanvasResourceProvider::PresentationMode presentation_mode =
+ RuntimeEnabledFeatures::Canvas2dImageChromiumEnabled()
+ ? CanvasResourceProvider::kAllowImageChromiumPresentationMode
+ : CanvasResourceProvider::kDefaultPresentationMode;
+
+ ReplaceResourceProvider(CanvasResourceProvider::Create(
+ Size(), usage, SharedGpuContext::ContextProviderWrapper(),
+ GetMSAASampleCountFor2dContext(), ColorParams(), presentation_mode,
+ std::move(dispatcher)));
+
+ if (ResourceProvider()) {
+ // Always save an initial frame, to support resetting the top level
+ // matrix and clip.
+ ResourceProvider()->Canvas()->save();
+ ResourceProvider()->SetFilterQuality(FilterQuality());
+ ResourceProvider()->SetResourceRecyclingEnabled(true);
+ }
+ }
+ }
+ if (!ResourceProvider()) {
+ did_fail_to_create_resource_provider_ = true;
+ }
+ }
+ return ResourceProvider();
+}
+
+CanvasColorParams CanvasRenderingContextHost::ColorParams() const {
+ if (RenderingContext())
+ return RenderingContext()->ColorParams();
+ return CanvasColorParams();
+}
+
+ScriptPromise CanvasRenderingContextHost::convertToBlob(
+ ScriptState* script_state,
+ const ImageEncodeOptions& options,
+ ExceptionState& exception_state) const {
+ WTF::String object_name = "Canvas";
+ if (this->IsOffscreenCanvas())
+ object_name = "OffscreenCanvas";
+ std::stringstream error_msg;
+
+ if (this->IsOffscreenCanvas() && this->IsNeutered()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "OffscreenCanvas object is detached.");
+ return ScriptPromise();
+ }
+
+ if (!this->OriginClean()) {
+ error_msg << "Tainted " << object_name << " may not be exported.";
+ exception_state.ThrowSecurityError(error_msg.str().c_str());
+ return ScriptPromise();
+ }
+
+ if (!this->IsPaintable() || Size().IsEmpty()) {
+ error_msg << "The size of " << object_name << " iz zero.";
+ exception_state.ThrowDOMException(DOMExceptionCode::kIndexSizeError,
+ error_msg.str().c_str());
+ return ScriptPromise();
+ }
+
+ if (!RenderingContext()) {
+ error_msg << object_name << " has no rendering context.";
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ error_msg.str().c_str());
+ return ScriptPromise();
+ }
+
+ TimeTicks start_time = WTF::CurrentTimeTicks();
+ scoped_refptr<StaticBitmapImage> image_bitmap =
+ RenderingContext()->GetImage(kPreferNoAcceleration);
+ if (image_bitmap) {
+ ScriptPromiseResolver* resolver =
+ ScriptPromiseResolver::Create(script_state);
+ CanvasAsyncBlobCreator::ToBlobFunctionType function_type =
+ CanvasAsyncBlobCreator::kHTMLCanvasConvertToBlobPromise;
+ if (this->IsOffscreenCanvas()) {
+ function_type =
+ CanvasAsyncBlobCreator::kOffscreenCanvasConvertToBlobPromise;
+ }
+ CanvasAsyncBlobCreator* async_creator = CanvasAsyncBlobCreator::Create(
+ image_bitmap, options, function_type, start_time,
+ ExecutionContext::From(script_state), resolver);
+ async_creator->ScheduleAsyncBlobCreation(options.quality());
+ return resolver->Promise();
+ }
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotReadableError,
+ "Readback of the source image has failed.");
+ return ScriptPromise();
+}
+
} // namespace blink
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 229fd7f8e2d..e54af262dec 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
@@ -5,11 +5,12 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_CANVAS_RENDERING_CONTEXT_HOST_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_CANVAS_RENDERING_CONTEXT_HOST_H_
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/events/event_dispatcher.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
+#include "third_party/blink/renderer/core/html/canvas/image_encode_options.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/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
@@ -18,10 +19,13 @@
namespace blink {
+class CanvasColorParams;
class CanvasRenderingContext;
+class CanvasResource;
+class CanvasResourceDispatcher;
class FontSelector;
-class StaticBitmapImage;
class KURL;
+class StaticBitmapImage;
class CORE_EXPORT CanvasRenderingContextHost : public CanvasResourceHost,
public GarbageCollectedMixin {
@@ -34,21 +38,18 @@ class CORE_EXPORT CanvasRenderingContextHost : public CanvasResourceHost,
virtual void DidDraw() = 0;
virtual void FinalizeFrame() = 0;
- virtual void PushFrame(scoped_refptr<StaticBitmapImage> image,
- const SkIRect& damage_rect) {
- NOTIMPLEMENTED();
- }
+ virtual void PushFrame(scoped_refptr<CanvasResource> frame,
+ const SkIRect& damage_rect) = 0;
virtual bool OriginClean() const = 0;
virtual void SetOriginTainted() = 0;
virtual const IntSize& Size() const = 0;
virtual CanvasRenderingContext* RenderingContext() const = 0;
+ virtual CanvasResourceDispatcher* GetOrCreateResourceDispatcher() = 0;
virtual ExecutionContext* GetTopExecutionContext() const = 0;
virtual DispatchEventResult HostDispatchEvent(Event*) = 0;
virtual const KURL& GetExecutionContextUrl() const = 0;
- virtual void DiscardResourceProvider() = 0;
-
// If WebGL1 is disabled by enterprise policy or command line switch.
virtual bool IsWebGL1Enabled() const = 0;
// If WebGL2 is disabled by enterprise policy or command line switch.
@@ -60,25 +61,37 @@ class CORE_EXPORT CanvasRenderingContextHost : public CanvasResourceHost,
virtual FontSelector* GetFontSelector() = 0;
+ virtual bool ShouldAccelerate2dContext() const = 0;
+ virtual unsigned GetMSAASampleCountFor2dContext() const = 0;
+
// TODO(fserb): remove this.
virtual bool IsOffscreenCanvas() const { return false; }
+ virtual bool IsNeutered() const { return false; }
- virtual void Commit(scoped_refptr<StaticBitmapImage> bitmap_image,
- const SkIRect& damage_rect) {
- NOTIMPLEMENTED();
- }
+ virtual void Commit(scoped_refptr<CanvasResource> canvas_resource,
+ const SkIRect& damage_rect);
bool IsPaintable() const;
- virtual void RegisterContextToDispatch(CanvasRenderingContext*) {}
-
// Partial CanvasResourceHost implementation
- void RestoreCanvasMatrixClipStack(PaintCanvas*) const final;
+ void RestoreCanvasMatrixClipStack(cc::PaintCanvas*) const final;
+ CanvasResourceProvider* GetOrCreateCanvasResourceProvider(
+ AccelerationHint hint) final;
+
+ bool Is3d() const;
+ bool Is2d() const;
+ CanvasColorParams ColorParams() const;
+
+ ScriptPromise convertToBlob(ScriptState*,
+ const ImageEncodeOptions&,
+ ExceptionState&) const;
protected:
~CanvasRenderingContextHost() override {}
scoped_refptr<StaticBitmapImage> CreateTransparentImage(const IntSize&) const;
+
+ bool did_fail_to_create_resource_provider_ = false;
};
} // namespace blink
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 d61466f5894..8596b77e5f7 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
@@ -29,22 +29,20 @@
#include <math.h>
+#include <limits>
#include <memory>
+#include <utility>
#include "base/location.h"
+#include "base/numerics/checked_math.h"
#include "build/build_config.h"
-#include "gpu/config/gpu_feature_info.h"
-#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/core/css/css_font_selector.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/element.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/fileapi/file.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
@@ -74,18 +72,18 @@
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_timing.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h"
#include "third_party/blink/renderer/platform/graphics/canvas_heuristic_parameters.h"
#include "third_party/blink/renderer/platform/graphics/canvas_metrics.h"
+#include "third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/graphics/image_data_buffer.h"
-#include "third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/image-encoders/image_encoder_utils.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
#include "v8/include/v8.h"
namespace blink {
@@ -131,8 +129,6 @@ inline HTMLCanvasElement::HTMLCanvasElement(Document& document)
context_creation_was_blocked_(false),
ignore_reset_(false),
origin_clean_(true),
- did_fail_to_create_resource_provider_(false),
- resource_provider_is_clear_(false),
surface_layer_bridge_(nullptr),
gpu_memory_usage_(0),
externally_allocated_memory_(0),
@@ -201,7 +197,7 @@ void HTMLCanvasElement::setHeight(unsigned value,
ExceptionState& exception_state) {
if (IsPlaceholderRegistered()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Cannot resize canvas after call to transferControlToOffscreen().");
return;
}
@@ -212,7 +208,7 @@ void HTMLCanvasElement::setWidth(unsigned value,
ExceptionState& exception_state) {
if (IsPlaceholderRegistered()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Cannot resize canvas after call to transferControlToOffscreen().");
return;
}
@@ -261,7 +257,7 @@ CanvasRenderingContext* HTMLCanvasElement::GetCanvasRenderingContext(
// Unknown type.
if (context_type == CanvasRenderingContext::kContextTypeCount ||
(context_type == CanvasRenderingContext::kContextXRPresent &&
- !OriginTrials::webXREnabled(&GetDocument())))
+ !OriginTrials::WebXREnabled(&GetDocument())))
return nullptr;
// Log the aliased context type used.
@@ -312,14 +308,16 @@ CanvasRenderingContext* HTMLCanvasElement::GetCanvasRenderingContext(
}
if (attributes.low_latency &&
- OriginTrials::lowLatencyCanvasEnabled(&GetDocument())) {
+ OriginTrials::LowLatencyCanvasEnabled(&GetDocument())) {
CreateLayer();
SetNeedsUnbufferedInputEvents(true);
- // TODO(fserb): rename to CanvasFrameDispatcher
- frame_dispatcher_ = std::make_unique<OffscreenCanvasFrameDispatcher>(
+ frame_dispatcher_ = std::make_unique<CanvasResourceDispatcher>(
nullptr, surface_layer_bridge_->GetFrameSinkId().client_id(),
surface_layer_bridge_->GetFrameSinkId().sink_id(),
- OffscreenCanvasFrameDispatcher::kInvalidPlaceholderCanvasId, size_);
+ CanvasResourceDispatcher::kInvalidPlaceholderCanvasId, size_);
+ // We don't actually need the begin frame signal when in low latency mode,
+ // but we need to subscribe to it or else dispatching frames will not work.
+ frame_dispatcher_->SetNeedsBeginFrame(GetPage()->IsPageVisible());
}
SetNeedsCompositingUpdate();
@@ -368,7 +366,7 @@ bool HTMLCanvasElement::IsWebGLBlocked() const {
void HTMLCanvasElement::DidDraw(const FloatRect& rect) {
if (rect.IsEmpty())
return;
- resource_provider_is_clear_ = false;
+ canvas_is_clear_ = false;
ClearCopiedImage();
if (GetLayoutObject() && !LowLatencyEnabled())
GetLayoutObject()->SetMayNeedPaintInvalidation();
@@ -393,9 +391,7 @@ void HTMLCanvasElement::FinalizeFrame() {
// FinalizeFrame indicates the end of a script task that may have rendered
// into the canvas, now is a good time to unlock cache entries.
- auto* resource_provider = canvas2d_bridge_
- ? canvas2d_bridge_->GetResourceProvider()
- : ResourceProviderForWebGL();
+ auto* resource_provider = ResourceProvider();
if (resource_provider)
resource_provider->ReleaseLockedImages();
@@ -420,9 +416,10 @@ void HTMLCanvasElement::FinalizeFrame() {
if (!LowLatencyEnabled())
canvas2d_bridge_->FinalizeFrame();
- if (LowLatencyEnabled() && !dirty_rect_.IsEmpty()) {
+ if (LowLatencyEnabled() && !dirty_rect_.IsEmpty() &&
+ GetOrCreateCanvasResourceProvider(kPreferAcceleration)) {
// Push a frame
- double start_time = WTF::CurrentTimeTicksInSeconds();
+ base::TimeTicks start_time = WTF::CurrentTimeTicks();
scoped_refptr<StaticBitmapImage> image =
canvas2d_bridge_->NewImageSnapshot(kPreferAcceleration);
FloatRect src_rect(0, 0, Size().Width(), Size().Height());
@@ -430,7 +427,7 @@ void HTMLCanvasElement::FinalizeFrame() {
IntRect int_dirty = EnclosingIntRect(dirty_rect_);
SkIRect damage_rect = SkIRect::MakeXYWH(
int_dirty.X(), int_dirty.Y(), int_dirty.Width(), int_dirty.Height());
- frame_dispatcher_->DispatchFrame(image, start_time, damage_rect);
+ frame_dispatcher_->DispatchFrameSync(image, start_time, damage_rect);
(void)start_time;
(void)damage_rect;
dirty_rect_ = FloatRect();
@@ -462,7 +459,6 @@ void HTMLCanvasElement::DisableAcceleration(
if (bridge && canvas2d_bridge_) {
ReplaceExisting2dLayerBridge(std::move(bridge));
- UpdateMemoryUsage();
}
// We must force a paint invalidation on the canvas even if it's
@@ -576,8 +572,8 @@ void HTMLCanvasElement::Reset() {
// If the size of an existing buffer matches, we can just clear it instead of
// reallocating. This optimization is only done for 2D canvases for now.
if (had_resource_provider && old_size == new_size && Is2d()) {
- if (!resource_provider_is_clear_) {
- resource_provider_is_clear_ = true;
+ if (!canvas_is_clear_) {
+ canvas_is_clear_ = true;
context_->ClearRect(0, 0, width(), height());
}
return;
@@ -613,12 +609,6 @@ bool HTMLCanvasElement::PaintsIntoCanvasBuffer() const {
return true;
}
-CanvasColorParams HTMLCanvasElement::ColorParams() const {
- if (context_)
- return context_->ColorParams();
- return CanvasColorParams();
-}
-
void HTMLCanvasElement::NotifyListenersCanvasChanged() {
if (listeners_.size() == 0)
return;
@@ -651,13 +641,37 @@ void HTMLCanvasElement::NotifyListenersCanvasChanged() {
}
}
+// Returns an image and the image's resolution scale factor.
+static std::pair<blink::Image*, float> BrokenCanvas(float device_scale_factor) {
+ if (device_scale_factor >= 2) {
+ DEFINE_STATIC_REF(blink::Image, broken_canvas_hi_res,
+ (blink::Image::LoadPlatformResource("brokenCanvas@2x")));
+ return std::make_pair(broken_canvas_hi_res, 2);
+ }
+
+ DEFINE_STATIC_REF(blink::Image, broken_canvas_lo_res,
+ (blink::Image::LoadPlatformResource("brokenCanvas")));
+ return std::make_pair(broken_canvas_lo_res, 1);
+}
+
+SkFilterQuality HTMLCanvasElement::FilterQuality() const {
+ if (!isConnected())
+ return kLow_SkFilterQuality;
+ HTMLCanvasElement* non_const_this = const_cast<HTMLCanvasElement*>(this);
+ non_const_this->UpdateDistributionForFlatTreeTraversal();
+ const ComputedStyle* style = non_const_this->EnsureComputedStyle();
+ return (style && style->ImageRendering() == EImageRendering::kPixelated)
+ ? kNone_SkFilterQuality
+ : kLow_SkFilterQuality;
+}
+
void HTMLCanvasElement::Paint(GraphicsContext& context, const LayoutRect& r) {
if (context_creation_was_blocked_ ||
(context_ && context_->isContextLost())) {
float device_scale_factor =
blink::DeviceScaleFactorDeprecated(GetDocument().GetFrame());
std::pair<Image*, float> broken_canvas_and_image_scale_factor =
- ImageResourceContent::BrokenCanvas(device_scale_factor);
+ BrokenCanvas(device_scale_factor);
Image* broken_canvas = broken_canvas_and_image_scale_factor.first;
context.Save();
context.FillRect(FloatRect(r), Color(), SkBlendMode::kClear);
@@ -677,19 +691,13 @@ void HTMLCanvasElement::Paint(GraphicsContext& context, const LayoutRect& r) {
if (!context_ && !PlaceholderFrame())
return;
- const ComputedStyle* style = EnsureComputedStyle();
- SkFilterQuality filter_quality =
- (style && style->ImageRendering() == EImageRendering::kPixelated)
- ? kNone_SkFilterQuality
- : kLow_SkFilterQuality;
-
if (Is3d()) {
- context_->SetFilterQuality(filter_quality);
+ context_->SetFilterQuality(FilterQuality());
} else if (canvas2d_bridge_) {
- canvas2d_bridge_->SetFilterQuality(filter_quality);
+ canvas2d_bridge_->UpdateFilterQuality();
}
- if (HasResourceProvider() && !resource_provider_is_clear_)
+ if (HasResourceProvider() && !canvas_is_clear_)
PaintTiming::From(GetDocument()).MarkFirstContentfulPaint();
if (!PaintsIntoCanvasBuffer() && !GetDocument().Printing())
@@ -697,8 +705,10 @@ void HTMLCanvasElement::Paint(GraphicsContext& context, const LayoutRect& r) {
if (PlaceholderFrame()) {
DCHECK(GetDocument().Printing());
- context.DrawImage(PlaceholderFrame().get(), Image::kSyncDecode,
- PixelSnappedIntRect(r));
+ scoped_refptr<StaticBitmapImage> image_for_printing =
+ PlaceholderFrame()->Bitmap()->MakeUnaccelerated();
+ context.DrawImage(image_for_printing.get(), Image::kSyncDecode,
+ FloatRect(PixelSnappedIntRect(r)));
return;
}
@@ -713,14 +723,13 @@ void HTMLCanvasElement::Paint(GraphicsContext& context, const LayoutRect& r) {
scoped_refptr<StaticBitmapImage> snapshot =
canvas2d_bridge_
? canvas2d_bridge_->NewImageSnapshot(kPreferAcceleration)
- : (webgl_resource_provider_ ? webgl_resource_provider_->Snapshot()
- : nullptr);
+ : (ResourceProvider() ? ResourceProvider()->Snapshot() : nullptr);
if (snapshot) {
// GraphicsContext cannot handle gpu resource serialization.
snapshot = snapshot->MakeUnaccelerated();
DCHECK(!snapshot->IsTextureBacked());
context.DrawImage(snapshot.get(), Image::kSyncDecode,
- PixelSnappedIntRect(r), &src_rect,
+ FloatRect(PixelSnappedIntRect(r)), &src_rect,
composite_operator);
}
}
@@ -734,14 +743,6 @@ void HTMLCanvasElement::Paint(GraphicsContext& context, const LayoutRect& r) {
context_->MarkLayerComposited();
}
-bool HTMLCanvasElement::Is3d() const {
- return context_ && context_->Is3d();
-}
-
-bool HTMLCanvasElement::Is2d() const {
- return context_ && context_->Is2d();
-}
-
bool HTMLCanvasElement::IsAnimated2d() const {
return Is2d() && canvas2d_bridge_ &&
canvas2d_bridge_->WasDrawnToAfterSnapshot();
@@ -773,8 +774,8 @@ scoped_refptr<StaticBitmapImage> HTMLCanvasElement::ToStaticBitmapImage(
if (Is3d()) {
if (context_->CreationAttributes().premultiplied_alpha) {
context_->PaintRenderingResultsToCanvas(source_buffer);
- if (webgl_resource_provider_)
- image_bitmap = webgl_resource_provider_->Snapshot();
+ if (ResourceProvider())
+ image_bitmap = ResourceProvider()->Snapshot();
} else {
scoped_refptr<Uint8Array> data_array =
context_->PaintRenderingResultsToDataArray(source_buffer);
@@ -798,7 +799,7 @@ scoped_refptr<StaticBitmapImage> HTMLCanvasElement::ToStaticBitmapImage(
image_bitmap = canvas2d_bridge_->NewImageSnapshot(hint);
} else if (PlaceholderFrame()) {
DCHECK(PlaceholderFrame()->OriginClean());
- image_bitmap = PlaceholderFrame();
+ image_bitmap = PlaceholderFrame()->Bitmap();
}
}
if (!image_bitmap)
@@ -888,7 +889,7 @@ void HTMLCanvasElement::toBlob(V8BlobCallback* callback,
return;
}
- double start_time = WTF::CurrentTimeTicksInSeconds();
+ TimeTicks start_time = WTF::CurrentTimeTicks();
double quality = kUndefinedQualityValue;
if (!quality_argument.IsEmpty()) {
v8::Local<v8::Value> v8_value = quality_argument.V8Value();
@@ -905,7 +906,9 @@ void HTMLCanvasElement::toBlob(V8BlobCallback* callback,
ToStaticBitmapImage(kBackBuffer, kPreferNoAcceleration);
if (image_bitmap) {
async_creator = CanvasAsyncBlobCreator::Create(
- image_bitmap, encoding_mime_type, callback, start_time, &GetDocument());
+ image_bitmap, encoding_mime_type, callback,
+ CanvasAsyncBlobCreator::kHTMLCanvasToBlobCallback, start_time,
+ &GetDocument());
}
if (async_creator) {
@@ -940,6 +943,22 @@ bool HTMLCanvasElement::OriginClean() const {
return origin_clean_;
}
+bool HTMLCanvasElement::ShouldAccelerate2dContext() const {
+ return ShouldAccelerate(kNormalAccelerationCriteria);
+}
+
+CanvasResourceDispatcher* HTMLCanvasElement::GetOrCreateResourceDispatcher() {
+ // The HTMLCanvasElement override of this method never needs to 'create'
+ // because the frame_dispatcher is only used in low latency mode, in which
+ // case the dispatcher is created upfront.
+ return frame_dispatcher_.get();
+}
+
+void HTMLCanvasElement::PushFrame(scoped_refptr<CanvasResource> image,
+ const SkIRect& damage_rect) {
+ NOTIMPLEMENTED();
+}
+
bool HTMLCanvasElement::ShouldAccelerate(AccelerationCriteria criteria) const {
if (context_ && !Is2d())
return false;
@@ -948,16 +967,13 @@ bool HTMLCanvasElement::ShouldAccelerate(AccelerationCriteria criteria) const {
if (LowLatencyEnabled())
return false;
- if (!RuntimeEnabledFeatures::Accelerated2dCanvasEnabled())
- return false;
-
// The following is necessary for handling the special case of canvases in the
// dev tools overlay, which run in a process that supports accelerated 2d
// canvas but in a special compositing context that does not.
if (GetLayoutBox() && !GetLayoutBox()->HasAcceleratedCompositing())
return false;
- CheckedNumeric<int> checked_canvas_pixel_count = Size().Width();
+ base::CheckedNumeric<int> checked_canvas_pixel_count = Size().Width();
checked_canvas_pixel_count *= Size().Height();
if (!checked_canvas_pixel_count.IsValid())
return false;
@@ -984,10 +1000,6 @@ bool HTMLCanvasElement::ShouldAccelerate(AccelerationCriteria criteria) const {
return false;
}
- // Don't use accelerated canvas if compositor is in software mode.
- if (!SharedGpuContext::IsGpuCompositingEnabled())
- return false;
-
// Avoid creating |contextProvider| until we're sure we want to try use it,
// since it costs us GPU memory.
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper =
@@ -998,28 +1010,22 @@ bool HTMLCanvasElement::ShouldAccelerate(AccelerationCriteria criteria) const {
return false;
}
- const gpu::GpuFeatureInfo& gpu_feature_info =
- context_provider_wrapper->ContextProvider()->GetGpuFeatureInfo();
- if (gpu::kGpuFeatureStatusEnabled !=
- gpu_feature_info
- .status_values[gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS]) {
- // Accelerated 2D canvas is blacklisted.
- return false;
- }
-
- return true;
+ return context_provider_wrapper->Utils()->Accelerated2DCanvasFeatureEnabled();
}
-std::unique_ptr<Canvas2DLayerBridge>
-HTMLCanvasElement::CreateAccelerated2dBuffer(int* msaa_sample_count) {
+unsigned HTMLCanvasElement::GetMSAASampleCountFor2dContext() const {
+ unsigned msaa_sample_count = 0;
if (GetDocument().GetSettings()) {
- *msaa_sample_count =
+ msaa_sample_count =
GetDocument().GetSettings()->GetAccelerated2dCanvasMSAASampleCount();
}
+ return msaa_sample_count;
+}
+std::unique_ptr<Canvas2DLayerBridge>
+HTMLCanvasElement::CreateAccelerated2dBuffer() {
auto surface = std::make_unique<Canvas2DLayerBridge>(
- Size(), *msaa_sample_count, Canvas2DLayerBridge::kEnableAcceleration,
- ColorParams());
+ Size(), Canvas2DLayerBridge::kEnableAcceleration, ColorParams());
if (!surface->IsValid()) {
CanvasMetrics::CountCanvasContextUsage(
CanvasMetrics::kGPUAccelerated2DCanvasImageBufferCreationFailed);
@@ -1037,7 +1043,7 @@ HTMLCanvasElement::CreateAccelerated2dBuffer(int* msaa_sample_count) {
std::unique_ptr<Canvas2DLayerBridge>
HTMLCanvasElement::CreateUnaccelerated2dBuffer() {
auto surface = std::make_unique<Canvas2DLayerBridge>(
- Size(), 0, Canvas2DLayerBridge::kDisableAcceleration, ColorParams());
+ Size(), Canvas2DLayerBridge::kDisableAcceleration, ColorParams());
if (surface->IsValid()) {
CanvasMetrics::CountCanvasContextUsage(
CanvasMetrics::kUnaccelerated2DCanvasImageBufferCreated);
@@ -1049,23 +1055,20 @@ HTMLCanvasElement::CreateUnaccelerated2dBuffer() {
return nullptr;
}
-void HTMLCanvasElement::CreateCanvas2DLayerBridgeInternal(
+void HTMLCanvasElement::SetCanvas2DLayerBridgeInternal(
std::unique_ptr<Canvas2DLayerBridge> external_canvas2d_bridge) {
DCHECK(Is2d() && !canvas2d_bridge_);
-
did_fail_to_create_resource_provider_ = true;
- resource_provider_is_clear_ = true;
if (!IsValidImageSize(Size()))
return;
- int msaa_sample_count = 0;
if (external_canvas2d_bridge) {
if (external_canvas2d_bridge->IsValid())
canvas2d_bridge_ = std::move(external_canvas2d_bridge);
} else {
if (ShouldAccelerate(kNormalAccelerationCriteria)) {
- canvas2d_bridge_ = CreateAccelerated2dBuffer(&msaa_sample_count);
+ canvas2d_bridge_ = CreateAccelerated2dBuffer();
}
if (!canvas2d_bridge_) {
canvas2d_bridge_ = CreateUnaccelerated2dBuffer();
@@ -1085,7 +1088,7 @@ void HTMLCanvasElement::CreateCanvas2DLayerBridgeInternal(
// regardless of whether the rendering mode is accelerated or not. For
// consistency, we don't want to apply AA in accelerated canvases but not in
// unaccelerated canvases.
- if (!msaa_sample_count && GetDocument().GetSettings() &&
+ if (!GetMSAASampleCountFor2dContext() && GetDocument().GetSettings() &&
!GetDocument().GetSettings()->GetAntialiased2dCanvasEnabled())
context_->SetShouldAntialias(false);
@@ -1106,11 +1109,6 @@ void HTMLCanvasElement::Trace(blink::Visitor* visitor) {
HTMLElement::Trace(visitor);
}
-void HTMLCanvasElement::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(context_);
- HTMLElement::TraceWrappers(visitor);
-}
-
void HTMLCanvasElement::DisableDeferral(DisableDeferralReason reason) {
if (canvas2d_bridge_)
canvas2d_bridge_->DisableDeferral(reason);
@@ -1119,7 +1117,7 @@ void HTMLCanvasElement::DisableDeferral(DisableDeferralReason reason) {
Canvas2DLayerBridge* HTMLCanvasElement::GetOrCreateCanvas2DLayerBridge() {
DCHECK(Is2d());
if (!canvas2d_bridge_ && !did_fail_to_create_resource_provider_) {
- CreateCanvas2DLayerBridgeInternal(nullptr);
+ SetCanvas2DLayerBridgeInternal(nullptr);
if (did_fail_to_create_resource_provider_ && !Size().IsEmpty()) {
context_->LoseContext(CanvasRenderingContext::kSyntheticLostContext);
}
@@ -1127,42 +1125,21 @@ Canvas2DLayerBridge* HTMLCanvasElement::GetOrCreateCanvas2DLayerBridge() {
return canvas2d_bridge_.get();
}
-CanvasResourceProvider*
-HTMLCanvasElement::GetOrCreateCanvasResourceProviderForWebGL() {
- DCHECK(Is3d());
- if (!webgl_resource_provider_ && !did_fail_to_create_resource_provider_) {
- resource_provider_is_clear_ = true;
- if (IsValidImageSize(Size())) {
- webgl_resource_provider_ = CanvasResourceProvider::Create(
- size_,
- Platform::Current()->IsGpuCompositingDisabled()
- ? CanvasResourceProvider::kSoftwareResourceUsage
- : CanvasResourceProvider::kAcceleratedResourceUsage,
- SharedGpuContext::ContextProviderWrapper(), 0, ColorParams());
- }
- if (!webgl_resource_provider_) {
- did_fail_to_create_resource_provider_ = true;
- } else {
- UpdateMemoryUsage();
- }
- }
- return webgl_resource_provider_.get();
-}
-
-void HTMLCanvasElement::CreateCanvas2DLayerBridgeForTesting(
+void HTMLCanvasElement::SetCanvas2DLayerBridgeForTesting(
std::unique_ptr<Canvas2DLayerBridge> bridge,
const IntSize& size) {
DiscardResourceProvider();
SetIntegralAttribute(widthAttr, size.Width());
SetIntegralAttribute(heightAttr, size.Height());
- CreateCanvas2DLayerBridgeInternal(std::move(bridge));
+ SetCanvas2DLayerBridgeInternal(std::move(bridge));
}
scoped_refptr<Image> HTMLCanvasElement::CopiedImage(
SourceDrawingBuffer source_buffer,
AccelerationHint hint) {
- if (SurfaceLayerBridge())
- return PlaceholderFrame();
+ if (SurfaceLayerBridge()) {
+ return PlaceholderFrame()->Bitmap();
+ }
if (!IsPaintable())
return nullptr;
@@ -1188,8 +1165,8 @@ scoped_refptr<Image> HTMLCanvasElement::CopiedImage(
if (need_to_update) {
if (Is2d() && GetOrCreateCanvas2DLayerBridge()) {
copied_image_ = canvas2d_bridge_->NewImageSnapshot(hint);
- } else if (Is3d() && GetOrCreateCanvasResourceProviderForWebGL()) {
- copied_image_ = webgl_resource_provider_->Snapshot();
+ } else if (Is3d() && GetOrCreateCanvasResourceProvider(hint)) {
+ copied_image_ = ResourceProvider()->Snapshot();
}
UpdateMemoryUsage();
}
@@ -1198,9 +1175,8 @@ scoped_refptr<Image> HTMLCanvasElement::CopiedImage(
void HTMLCanvasElement::DiscardResourceProvider() {
canvas2d_bridge_.reset();
- webgl_resource_provider_.reset();
+ CanvasResourceHost::DiscardResourceProvider();
dirty_rect_ = FloatRect();
- UpdateMemoryUsage();
}
void HTMLCanvasElement::ClearCopiedImage() {
@@ -1249,12 +1225,9 @@ void HTMLCanvasElement::WillDrawImageTo2DContext(CanvasImageSource* source) {
source->IsAccelerated() && GetOrCreateCanvas2DLayerBridge() &&
!canvas2d_bridge_->IsAccelerated() &&
ShouldAccelerate(kIgnoreResourceLimitCriteria)) {
- int msaa_sample_count = 0;
- std::unique_ptr<Canvas2DLayerBridge> surface =
- CreateAccelerated2dBuffer(&msaa_sample_count);
+ std::unique_ptr<Canvas2DLayerBridge> surface = CreateAccelerated2dBuffer();
if (surface) {
ReplaceExisting2dLayerBridge(std::move(surface));
- UpdateMemoryUsage();
SetNeedsCompositingUpdate();
}
}
@@ -1276,7 +1249,7 @@ scoped_refptr<Image> HTMLCanvasElement::GetSourceImageForCanvas(
if (PlaceholderFrame()) {
*status = kNormalSourceImageStatus;
- return PlaceholderFrame();
+ return PlaceholderFrame()->Bitmap();
}
if (!context_) {
@@ -1302,8 +1275,8 @@ scoped_refptr<Image> HTMLCanvasElement::GetSourceImageForCanvas(
// use paintRenderingResultsToCanvas instead of getImage in order to keep a
// cached copy of the backing in the canvas's resource provider.
RenderingContext()->PaintRenderingResultsToCanvas(kBackBuffer);
- if (webgl_resource_provider_) {
- image = webgl_resource_provider_->Snapshot();
+ if (ResourceProvider()) {
+ image = ResourceProvider()->Snapshot();
} else {
image = CreateTransparentImage(Size());
}
@@ -1360,15 +1333,14 @@ ScriptPromise HTMLCanvasElement::CreateImageBitmap(
}
void HTMLCanvasElement::SetPlaceholderFrame(
- scoped_refptr<StaticBitmapImage> image,
- base::WeakPtr<OffscreenCanvasFrameDispatcher> dispatcher,
+ scoped_refptr<CanvasResource> image,
+ base::WeakPtr<CanvasResourceDispatcher> dispatcher,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
unsigned resource_id) {
OffscreenCanvasPlaceholder::SetPlaceholderFrame(
std::move(image), std::move(dispatcher), std::move(task_runner),
resource_id);
- IntSize new_size(PlaceholderFrame()->width(), PlaceholderFrame()->height());
- SetSize(new_size);
+ SetSize(PlaceholderFrame()->Size());
NotifyListenersCanvasChanged();
}
@@ -1462,8 +1434,8 @@ void HTMLCanvasElement::CreateLayer() {
if (frame) {
layer_tree_view =
frame->GetPage()->GetChromeClient().GetWebLayerTreeView(frame);
- surface_layer_bridge_ =
- std::make_unique<::blink::SurfaceLayerBridge>(layer_tree_view, this);
+ surface_layer_bridge_ = std::make_unique<::blink::SurfaceLayerBridge>(
+ layer_tree_view, this, base::DoNothing());
// Creates a placeholder layer first before Surface is created.
surface_layer_bridge_->CreateSolidColorLayer();
}
@@ -1503,9 +1475,9 @@ void HTMLCanvasElement::UpdateMemoryUsage() {
non_gpu_buffer_count++;
if (Is3d()) {
- if (webgl_resource_provider_) {
+ if (ResourceProvider()) {
non_gpu_buffer_count++;
- if (webgl_resource_provider_->IsAccelerated()) {
+ if (ResourceProvider()->IsAccelerated()) {
gpu_buffer_count += 2;
}
}
@@ -1518,7 +1490,8 @@ void HTMLCanvasElement::UpdateMemoryUsage() {
// a change from acceleration to non-accleration or vice versa.
if (gpu_buffer_count && !gpu_memory_usage_) {
// Switch from non-acceleration mode to acceleration mode
- CheckedNumeric<intptr_t> checked_usage = gpu_buffer_count * bytes_per_pixel;
+ base::CheckedNumeric<intptr_t> checked_usage =
+ gpu_buffer_count * bytes_per_pixel;
checked_usage *= width();
checked_usage *= height();
intptr_t gpu_memory_usage =
@@ -1537,7 +1510,7 @@ void HTMLCanvasElement::UpdateMemoryUsage() {
// Recomputation of externally memory usage computation is carried out
// in all cases.
- CheckedNumeric<intptr_t> checked_usage =
+ base::CheckedNumeric<intptr_t> checked_usage =
non_gpu_buffer_count * bytes_per_pixel;
checked_usage *= width();
checked_usage *= height();
@@ -1552,23 +1525,25 @@ void HTMLCanvasElement::UpdateMemoryUsage() {
}
void HTMLCanvasElement::ReplaceExisting2dLayerBridge(
- std::unique_ptr<Canvas2DLayerBridge> new_buffer) {
+ std::unique_ptr<Canvas2DLayerBridge> new_layer_bridge) {
+ scoped_refptr<StaticBitmapImage> image;
if (canvas2d_bridge_) {
- scoped_refptr<StaticBitmapImage> image =
- canvas2d_bridge_->NewImageSnapshot(kPreferNoAcceleration);
-
- // image can be null if alloaction failed in which case we should just
+ image = canvas2d_bridge_->NewImageSnapshot(kPreferNoAcceleration);
+ // image can be null if allocation failed in which case we should just
// abort the surface switch to reatain the old surface which is still
// functional.
if (!image)
return;
- new_buffer->DrawFullImage(image->PaintImageForCurrentFrame());
}
+ new_layer_bridge->SetCanvasResourceHost(this);
+ ReplaceResourceProvider(nullptr);
+ canvas2d_bridge_ = std::move(new_layer_bridge);
+ if (image)
+ canvas2d_bridge_->DrawFullImage(image->PaintImageForCurrentFrame());
- RestoreCanvasMatrixClipStack(new_buffer->Canvas());
- new_buffer->DidRestoreCanvasMatrixClipStack(new_buffer->Canvas());
- canvas2d_bridge_ = std::move(new_buffer);
- canvas2d_bridge_->SetCanvasResourceHost(this);
+ RestoreCanvasMatrixClipStack(canvas2d_bridge_->Canvas());
+ canvas2d_bridge_->DidRestoreCanvasMatrixClipStack(canvas2d_bridge_->Canvas());
+ UpdateMemoryUsage();
}
bool HTMLCanvasElement::HasImageBitmapContext() const {
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 1b39c6663f9..1b4daa38b71 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
@@ -39,6 +39,7 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_image_source.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h"
+#include "third_party/blink/renderer/core/html/canvas/image_encode_options.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap_source.h"
#include "third_party/blink/renderer/core/page/page_visibility_observer.h"
@@ -63,7 +64,6 @@ class Layer;
namespace blink {
class Canvas2DLayerBridge;
-class CanvasColorParams;
class CanvasContextCreationAttributesCore;
class CanvasDrawListener;
class CanvasRenderingContext;
@@ -75,10 +75,17 @@ class Image;
class ImageBitmapOptions;
class IntSize;
+#if defined(SUPPORT_WEBGL2_COMPUTE_CONTEXT)
+class
+ CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContextOrImageBitmapRenderingContextOrXRPresentationContext;
+typedef CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContextOrImageBitmapRenderingContextOrXRPresentationContext
+ RenderingContext;
+#else
class
CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContextOrXRPresentationContext;
typedef CanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrImageBitmapRenderingContextOrXRPresentationContext
RenderingContext;
+#endif
class CORE_EXPORT HTMLCanvasElement final
: public HTMLElement,
@@ -155,18 +162,13 @@ class CORE_EXPORT HTMLCanvasElement final
bool OriginClean() const override;
void SetOriginTainted() override { origin_clean_ = false; }
- bool Is3d() const;
- bool Is2d() const;
bool IsAnimated2d() const;
Canvas2DLayerBridge* GetCanvas2DLayerBridge() {
return canvas2d_bridge_.get();
}
Canvas2DLayerBridge* GetOrCreateCanvas2DLayerBridge();
- CanvasResourceProvider* GetOrCreateCanvasResourceProviderForWebGL();
- CanvasResourceProvider* ResourceProviderForWebGL() const {
- return webgl_resource_provider_.get();
- }
+
void DiscardResourceProvider() override;
FontSelector* GetFontSelector() override;
@@ -183,6 +185,11 @@ class CORE_EXPORT HTMLCanvasElement final
void FinalizeFrame() override;
+ CanvasResourceDispatcher* GetOrCreateResourceDispatcher() override;
+
+ void PushFrame(scoped_refptr<CanvasResource> image,
+ const SkIRect& damage_rect) override;
+
// ContextLifecycleObserver and PageVisibilityObserver implementation
void ContextDestroyed(ExecutionContext*) override;
@@ -208,6 +215,9 @@ class CORE_EXPORT HTMLCanvasElement final
void NotifyGpuContextLost() override;
void SetNeedsCompositingUpdate() override;
void UpdateMemoryUsage() override;
+ bool ShouldAccelerate2dContext() const override;
+ unsigned GetMSAASampleCountFor2dContext() const override;
+ SkFilterQuality FilterQuality() const override;
void DisableAcceleration(std::unique_ptr<Canvas2DLayerBridge>
unaccelerated_bridge_used_for_testing = nullptr);
@@ -220,16 +230,14 @@ class CORE_EXPORT HTMLCanvasElement final
const ImageBitmapOptions&) override;
// OffscreenCanvasPlaceholder implementation.
- void SetPlaceholderFrame(scoped_refptr<StaticBitmapImage>,
- base::WeakPtr<OffscreenCanvasFrameDispatcher>,
+ void SetPlaceholderFrame(scoped_refptr<CanvasResource>,
+ base::WeakPtr<CanvasResourceDispatcher>,
scoped_refptr<base::SingleThreadTaskRunner>,
unsigned resource_id) override;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
- void CreateCanvas2DLayerBridgeForTesting(std::unique_ptr<Canvas2DLayerBridge>,
- const IntSize&);
+ void SetCanvas2DLayerBridgeForTesting(std::unique_ptr<Canvas2DLayerBridge>,
+ const IntSize&);
static void RegisterRenderingContextFactory(
std::unique_ptr<CanvasRenderingContextFactory>);
@@ -315,15 +323,13 @@ class CORE_EXPORT HTMLCanvasElement final
void Reset();
- std::unique_ptr<Canvas2DLayerBridge> CreateAccelerated2dBuffer(
- int* msaa_sample_count);
+ std::unique_ptr<Canvas2DLayerBridge> CreateAccelerated2dBuffer();
std::unique_ptr<Canvas2DLayerBridge> CreateUnaccelerated2dBuffer();
- void CreateCanvas2DLayerBridgeInternal(std::unique_ptr<Canvas2DLayerBridge>);
+ void SetCanvas2DLayerBridgeInternal(std::unique_ptr<Canvas2DLayerBridge>);
void SetSurfaceSize(const IntSize&);
bool PaintsIntoCanvasBuffer() const;
- CanvasColorParams ColorParams() const;
scoped_refptr<StaticBitmapImage> ToStaticBitmapImage(SourceDrawingBuffer,
AccelerationHint) const;
@@ -344,6 +350,8 @@ class CORE_EXPORT HTMLCanvasElement final
// Used only for WebGL currently.
bool context_creation_was_blocked_;
+ bool canvas_is_clear_ = true;
+
bool ignore_reset_;
FloatRect dirty_rect_;
@@ -352,17 +360,10 @@ class CORE_EXPORT HTMLCanvasElement final
// It prevents repeated attempts in allocating resources after the first
// attempt failed.
- mutable bool did_fail_to_create_resource_provider_;
-
bool HasResourceProvider() {
- return canvas2d_bridge_ || webgl_resource_provider_;
+ return canvas2d_bridge_ || !!CanvasResourceHost::ResourceProvider();
}
- bool resource_provider_is_clear_;
-
- // This is only used by canvas with webgl rendering context.
- std::unique_ptr<CanvasResourceProvider> webgl_resource_provider_;
-
// Canvas2DLayerBridge is used when canvas has 2d rendering context
std::unique_ptr<Canvas2DLayerBridge> canvas2d_bridge_;
void ReplaceExisting2dLayerBridge(std::unique_ptr<Canvas2DLayerBridge>);
@@ -377,7 +378,7 @@ class CORE_EXPORT HTMLCanvasElement final
// Used for low latency mode.
// TODO: rename to CanvasFrameDispatcher.
- std::unique_ptr<OffscreenCanvasFrameDispatcher> frame_dispatcher_;
+ std::unique_ptr<CanvasResourceDispatcher> frame_dispatcher_;
bool did_notify_listeners_for_current_frame_ = false;
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.idl b/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.idl
index c440bacbfec..0fee23b07f5 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/canvas/html_canvas_element.idl
@@ -40,6 +40,8 @@ interface HTMLCanvasElement : HTMLElement
[MeasureAs=CanvasToDataURL, RaisesException] DOMString toDataURL(optional DOMString type = null, optional any arguments);
[MeasureAs=CanvasToBlob, RaisesException] void toBlob(BlobCallback _callback, optional DOMString type = null, optional any arguments);
+
+ [RuntimeEnabled=CanvasColorManagement, MeasureAs=CanvasConvertToBlob, RaisesException, CallWith=ScriptState] Promise<Blob> convertToBlob(optional ImageEncodeOptions options);
};
// https://html.spec.whatwg.org/multipage/canvas.html#blobcallback
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 31bf360acde..5adf504267c 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
@@ -28,26 +28,30 @@
#include "third_party/blink/renderer/core/html/canvas/image_data.h"
+#include "base/sys_byteorder.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_uint8_clamped_array.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap_options.h"
#include "third_party/blink/renderer/platform/graphics/color_behavior.h"
-#include "third_party/blink/renderer/platform/wtf/byte_swap.h"
#include "third_party/skia/include/core/SkColorSpaceXform.h"
#include "third_party/skia/include/core/SkSwizzle.h"
#include "v8/include/v8.h"
namespace blink {
+namespace {
+
bool RaiseDOMExceptionAndReturnFalse(ExceptionState* exception_state,
- ExceptionCode exception_code,
+ DOMExceptionCode exception_code,
const char* message) {
if (exception_state)
exception_state->ThrowDOMException(exception_code, message);
return false;
}
+} // namespace
+
bool ImageData::ValidateConstructorArguments(
const unsigned& param_flags,
const IntSize* size,
@@ -62,18 +66,18 @@ bool ImageData::ValidateConstructorArguments(
if ((param_flags & kParamWidth) && !width) {
return RaiseDOMExceptionAndReturnFalse(
- exception_state, kIndexSizeError,
+ exception_state, DOMExceptionCode::kIndexSizeError,
"The source width is zero or not a number.");
}
if ((param_flags & kParamHeight) && !height) {
return RaiseDOMExceptionAndReturnFalse(
- exception_state, kIndexSizeError,
+ exception_state, DOMExceptionCode::kIndexSizeError,
"The source height is zero or not a number.");
}
if (param_flags & (kParamWidth | kParamHeight)) {
- CheckedNumeric<unsigned> data_size = 4;
+ base::CheckedNumeric<unsigned> data_size = 4;
if (color_settings) {
data_size *=
ImageData::StorageFormatDataSize(color_settings->storageFormat());
@@ -82,14 +86,16 @@ bool ImageData::ValidateConstructorArguments(
data_size *= height;
if (!data_size.IsValid()) {
return RaiseDOMExceptionAndReturnFalse(
- exception_state, kIndexSizeError,
+ exception_state, DOMExceptionCode::kIndexSizeError,
"The requested image size exceeds the supported range.");
}
if (data_size.ValueOrDie() > v8::TypedArray::kMaxLength) {
- return RaiseDOMExceptionAndReturnFalse(
- exception_state, kV8RangeError,
- "Out of memory at ImageData creation.");
+ if (exception_state) {
+ exception_state->ThrowRangeError(
+ "Out of memory at ImageData creation.");
+ }
+ return false;
}
}
@@ -100,40 +106,40 @@ bool ImageData::ValidateConstructorArguments(
data->GetType() != DOMArrayBufferView::ViewType::kTypeUint16 &&
data->GetType() != DOMArrayBufferView::ViewType::kTypeFloat32) {
return RaiseDOMExceptionAndReturnFalse(
- exception_state, kNotSupportedError,
+ exception_state, DOMExceptionCode::kNotSupportedError,
"The input data type is not supported.");
}
if (!data->byteLength()) {
return RaiseDOMExceptionAndReturnFalse(
- exception_state, kIndexSizeError,
+ exception_state, DOMExceptionCode::kIndexSizeError,
"The input data has zero elements.");
}
data_length = data->byteLength() / data->TypeSize();
if (data_length % 4) {
return RaiseDOMExceptionAndReturnFalse(
- exception_state, kIndexSizeError,
+ exception_state, DOMExceptionCode::kIndexSizeError,
"The input data length is not a multiple of 4.");
}
if ((param_flags & kParamWidth) && (data_length / 4) % width) {
return RaiseDOMExceptionAndReturnFalse(
- exception_state, kIndexSizeError,
+ exception_state, DOMExceptionCode::kIndexSizeError,
"The input data length is not a multiple of (4 * width).");
}
if ((param_flags & kParamWidth) && (param_flags & kParamHeight) &&
height != data_length / (4 * width))
return RaiseDOMExceptionAndReturnFalse(
- exception_state, kIndexSizeError,
+ exception_state, DOMExceptionCode::kIndexSizeError,
"The input data length is not equal to (4 * width * height).");
}
if (param_flags & kParamSize) {
if (size->Width() <= 0 || size->Height() <= 0)
return false;
- CheckedNumeric<unsigned> data_size = 4;
+ base::CheckedNumeric<unsigned> data_size = 4;
data_size *= size->Width();
data_size *= size->Height();
if (!data_size.IsValid() ||
@@ -173,8 +179,7 @@ DOMArrayBufferView* ImageData::AllocateAndValidateDataArray(
if (!data_array ||
length != data_array->byteLength() / data_array->TypeSize()) {
if (exception_state)
- exception_state->ThrowDOMException(kV8RangeError,
- "Out of memory at ImageData creation");
+ exception_state->ThrowRangeError("Out of memory at ImageData creation");
return nullptr;
}
@@ -362,8 +367,7 @@ ImageData* ImageData::Create(scoped_refptr<StaticBitmapImage> image,
if (!f16_array)
return nullptr;
if (!pixmap.readPixels(image_info, f16_array->Data(),
- image_info.minRowBytes(), 0, 0,
- SkTransferFunctionBehavior::kIgnore)) {
+ image_info.minRowBytes())) {
NOTREACHED();
return nullptr;
}
@@ -494,7 +498,7 @@ ImageData* ImageData::CreateImageData(ImageDataArray& data,
// This function accepts size (0, 0) and always returns the ImageData in
// "srgb" color space and "uint8" storage format.
ImageData* ImageData::CreateForTest(const IntSize& size) {
- CheckedNumeric<unsigned> data_size = 4;
+ base::CheckedNumeric<unsigned> data_size = 4;
data_size *= size.Width();
data_size *= size.Height();
if (!data_size.IsValid() ||
@@ -571,7 +575,7 @@ ScriptPromise ImageData::CreateImageBitmap(ScriptState* script_state,
if (BufferBase()->IsNeutered()) {
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kInvalidStateError,
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
"The source data has been detached."));
}
return ImageBitmapSource::FulfillImageBitmap(
@@ -827,13 +831,13 @@ void ImageData::SwapU16EndiannessForSkColorSpaceXform(
int start_index = (crop_rect->X() + crop_rect->Y() * width()) * 4;
for (int i = 0; i < crop_rect->Height(); i++) {
for (int j = 0; j < crop_rect->Width(); j++)
- *(buffer + start_index + j) = WTF::Bswap16(*(buffer + start_index + j));
+ buffer[start_index + j] = base::ByteSwap(buffer[start_index + j]);
start_index += width() * 4;
}
return;
}
for (unsigned i = 0; i < size_.Area() * 4; i++)
- *(buffer + i) = WTF::Bswap16(*(buffer + i));
+ buffer[i] = base::ByteSwap(buffer[i]);
};
void ImageData::SwizzleIfNeeded(DataU8ColorType u8_color_type,
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 e39942274ad..ff86ba4d3fc 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
@@ -29,6 +29,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_IMAGE_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CANVAS_IMAGE_DATA_H_
+#include "base/numerics/checked_math.h"
#include "third_party/blink/renderer/bindings/core/v8/uint8_clamped_array_or_uint16_array_or_float32_array.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
@@ -42,7 +43,6 @@
#include "third_party/blink/renderer/platform/graphics/canvas_color_params.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
#include "third_party/blink/renderer/platform/wtf/compiler.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/skia/include/core/SkColorSpace.h"
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/image_data_test.cc b/chromium/third_party/blink/renderer/core/html/canvas/image_data_test.cc
index 2d68ee71ae1..49b90559388 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/image_data_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/canvas/image_data_test.cc
@@ -5,11 +5,9 @@
#include "third_party/blink/renderer/core/html/canvas/image_data.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/graphics/color_correction_test_utils.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
-#include "third_party/blink/renderer/platform/wtf/byte_swap.h"
#include "third_party/skia/include/core/SkColorSpaceXform.h"
namespace blink {
@@ -25,7 +23,7 @@ TEST_F(ImageDataTest, CreateImageDataTooBig) {
ImageData::Create(32767, 32767, exception_state);
if (!too_big_image_data) {
EXPECT_TRUE(exception_state.HadException());
- EXPECT_EQ(exception_state.Code(), kV8RangeError);
+ EXPECT_EQ(exception_state.CodeAs<ESErrorType>(), ESErrorType::kRangeError);
}
}
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 d1d0dfb4fe5..52acd816c69 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
@@ -141,7 +141,7 @@ ScriptPromise ImageElementBase::CreateImageBitmap(
return ScriptPromise::RejectWithDOMException(
script_state,
DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"No image can be retrieved from the provided element."));
}
Image* image = image_content->GetImage();
@@ -152,7 +152,7 @@ ScriptPromise ImageElementBase::CreateImageBitmap(
return ScriptPromise::RejectWithDOMException(
script_state,
DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"The image element contains an SVG image without intrinsic "
"dimensions, and no resize options or crop region are "
"specified."));
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/image_encode_options.idl b/chromium/third_party/blink/renderer/core/html/canvas/image_encode_options.idl
new file mode 100644
index 00000000000..b2aac7a3ce8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/canvas/image_encode_options.idl
@@ -0,0 +1,21 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+enum ImageColorSpace {
+ "srgb", // default
+ "rec2020",
+ "display-p3",
+};
+
+enum ImagePixelFormat {
+ "8-8-8-8", // default
+ "uint16",
+};
+
+dictionary ImageEncodeOptions {
+ DOMString type = "image/png";
+ unrestricted double quality = 1.0;
+ ImageColorSpace colorSpace = "srgb";
+ ImagePixelFormat pixelFormat = "8-8-8-8";
+};
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/text_metrics.cc b/chromium/third_party/blink/renderer/core/html/canvas/text_metrics.cc
index 1639dce6264..864bfe664f0 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/text_metrics.cc
+++ b/chromium/third_party/blink/renderer/core/html/canvas/text_metrics.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/html/canvas/text_metrics.h"
+#include "third_party/blink/renderer/platform/fonts/character_range.h"
namespace blink {
@@ -64,6 +65,12 @@ void TextMetrics::Update(const Font& font,
FloatRect bbox = font.BoundingBox(text_run);
const FontMetrics& font_metrics = font_data->GetFontMetrics();
+ Vector<CharacterRange> ranges = font.IndividualCharacterRanges(text_run);
+ advances_.resize(ranges.size());
+ for (unsigned i = 0; i < ranges.size(); i++) {
+ advances_[i] = ranges[i].start;
+ }
+
// x direction
width_ = bbox.Width();
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/text_metrics.h b/chromium/third_party/blink/renderer/core/html/canvas/text_metrics.h
index c132aa28c0e..51fc4e38880 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/text_metrics.h
+++ b/chromium/third_party/blink/renderer/core/html/canvas/text_metrics.h
@@ -51,6 +51,7 @@ class CORE_EXPORT TextMetrics final : public ScriptWrappable {
}
double width() const { return width_; }
+ const Vector<double>& advances() const { return advances_; }
double actualBoundingBoxLeft() const { return actual_bounding_box_left_; }
double actualBoundingBoxRight() const { return actual_bounding_box_right_; }
double fontBoundingBoxAscent() const { return font_bounding_box_ascent_; }
@@ -77,6 +78,7 @@ class CORE_EXPORT TextMetrics final : public ScriptWrappable {
// x-direction
double width_ = 0.0;
+ Vector<double> advances_;
double actual_bounding_box_left_ = 0.0;
double actual_bounding_box_right_ = 0.0;
diff --git a/chromium/third_party/blink/renderer/core/html/canvas/text_metrics.idl b/chromium/third_party/blink/renderer/core/html/canvas/text_metrics.idl
index e84a83117b7..bcaa5e2c1d7 100644
--- a/chromium/third_party/blink/renderer/core/html/canvas/text_metrics.idl
+++ b/chromium/third_party/blink/renderer/core/html/canvas/text_metrics.idl
@@ -29,6 +29,7 @@
interface TextMetrics {
// x-direction
readonly attribute float width; // advance width
+ [RuntimeEnabled=ExtendedTextMetrics] readonly attribute FrozenArray<double> advances;
[RuntimeEnabled=ExtendedTextMetrics] readonly attribute double actualBoundingBoxLeft;
[RuntimeEnabled=ExtendedTextMetrics] readonly attribute double actualBoundingBoxRight;
diff --git a/chromium/third_party/blink/renderer/core/html/custom/README.md b/chromium/third_party/blink/renderer/core/html/custom/README.md
index 289833db2aa..243b82bd0b7 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/README.md
+++ b/chromium/third_party/blink/renderer/core/html/custom/README.md
@@ -85,9 +85,9 @@ with CustomElement so you can run them with:
The custom element layout tests are generally in
third_party/WebKit/LayoutTests/custom-elements.
-All custom elements layout tests use the [W3C web-platform-tests
-harness](http://web-platform-tests.org/) and follow its style. The
-W3C is not very prescriptive, so be consistent with other custom
+All custom elements layout tests use the [web-platform-tests
+harness](https://web-platform-tests.org/) and follow its style. The
+WPT style is not very prescriptive, so be consistent with other custom
elements tests.
When naming tests, use short names describing what the test is doing.
@@ -99,8 +99,8 @@ behavior is.
###### Spec Tests
-These will be upstreamed to the W3C, replacing [the tests for
-registerElement](https://github.com/w3c/web-platform-tests/commits/master/custom-elements)
+These will be upstreamed to WPT, replacing [the tests for
+registerElement](https://github.com/web-platform-tests/wpt/tree/master/custom-elements)
we contributed earlier. To facilitate that, follow these guidelines:
* Keep the tests together in the `spec` directory.
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 f0656876a56..26751657467 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
@@ -73,8 +73,7 @@ bool CustomElement::ShouldCreateCustomElement(const QualifiedName& tag_name) {
bool CustomElement::ShouldCreateCustomizedBuiltinElement(
const AtomicString& local_name) {
return htmlElementTypeForTag(local_name) !=
- HTMLElementType::kHTMLUnknownElement &&
- RuntimeEnabledFeatures::CustomElementsBuiltinEnabled();
+ HTMLElementType::kHTMLUnknownElement;
}
bool CustomElement::ShouldCreateCustomizedBuiltinElement(
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 8f49b4bfbdd..c92798678d0 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
@@ -4,11 +4,9 @@
#include "third_party/blink/renderer/core/html/custom/custom_element_definition.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
#include "third_party/blink/renderer/core/dom/attr.h"
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/html/custom/custom_element.h"
#include "third_party/blink/renderer/core/html/custom/custom_element_adopted_callback_reaction.h"
#include "third_party/blink/renderer/core/html/custom/custom_element_attribute_changed_callback_reaction.h"
@@ -19,6 +17,7 @@
#include "third_party/blink/renderer/core/html/custom/custom_element_upgrade_reaction.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/html_element_factory.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -95,8 +94,10 @@ void CustomElementDefinition::CheckConstructorResult(
// 6.1.4. through 6.1.9.
const String message =
ErrorMessageForConstructorResult(element, document, tag_name);
- if (!message.IsEmpty())
- exception_state.ThrowDOMException(kNotSupportedError, message);
+ if (!message.IsEmpty()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ message);
+ }
}
HTMLElement* CustomElementDefinition::CreateElementForConstructor(
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 0b23b5da43c..009e8c08942 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
@@ -10,7 +10,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/create_element_flags.h"
#include "third_party/blink/renderer/core/html/custom/custom_element_descriptor.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" // For TraceWrapperBase
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -27,7 +27,7 @@ class QualifiedName;
class CORE_EXPORT CustomElementDefinition
: public GarbageCollectedFinalized<CustomElementDefinition>,
- public TraceWrapperBase {
+ public NameClient {
public:
// Each definition has an ID that is unique within the
// CustomElementRegistry that created it.
@@ -36,7 +36,6 @@ class CORE_EXPORT CustomElementDefinition
virtual ~CustomElementDefinition();
virtual void Trace(blink::Visitor*);
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {}
const char* NameInHeapSnapshot() const override {
return "CustomElementDefinition";
}
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.cc b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.cc
index fc958b2496a..5a9ed224a2a 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.cc
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.cc
@@ -33,13 +33,6 @@ void CustomElementReactionStack::Trace(blink::Visitor* visitor) {
visitor->Trace(backup_queue_);
}
-void CustomElementReactionStack::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- for (auto key : map_.Keys()) {
- visitor->TraceWrappers(key);
- }
-}
-
void CustomElementReactionStack::Push() {
stack_.push_back(nullptr);
}
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.h b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.h
index a6150b33b84..d90aa9cc631 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_reaction_stack.h
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
@@ -19,12 +19,11 @@ class Element;
// https://html.spec.whatwg.org/multipage/scripting.html#custom-element-reactions
class CORE_EXPORT CustomElementReactionStack final
: public GarbageCollected<CustomElementReactionStack>,
- public TraceWrapperBase {
+ public NameClient {
public:
CustomElementReactionStack();
void Trace(blink::Visitor*);
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "CustomElementReactionStack";
}
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 2b16cedb148..e1f7583daea 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
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/html/custom/custom_element_registry.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_custom_element_definition_builder.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
@@ -12,9 +11,9 @@
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/element_definition_options.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
-#include "third_party/blink/renderer/core/dom/exception_code.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/use_counter.h"
#include "third_party/blink/renderer/core/html/custom/ce_reactions_scope.h"
#include "third_party/blink/renderer/core/html/custom/custom_element.h"
#include "third_party/blink/renderer/core/html/custom/custom_element_definition.h"
@@ -25,6 +24,7 @@
#include "third_party/blink/renderer/core/html/custom/custom_element_upgrade_sorter.h"
#include "third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.h"
#include "third_party/blink/renderer/core/html_element_type_helpers.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
@@ -57,7 +57,8 @@ static bool ThrowIfInvalidName(const AtomicString& name,
if (CustomElement::IsValidName(name))
return false;
exception_state.ThrowDOMException(
- kSyntaxError, "\"" + name + "\" is not a valid custom element name");
+ DOMExceptionCode::kSyntaxError,
+ "\"" + name + "\" is not a valid custom element name");
return true;
}
@@ -67,7 +68,8 @@ static bool ThrowIfValidName(const AtomicString& name,
if (!CustomElement::IsValidName(name))
return false;
exception_state.ThrowDOMException(
- kNotSupportedError, "\"" + name + "\" is a valid custom element name");
+ DOMExceptionCode::kNotSupportedError,
+ "\"" + name + "\" is a valid custom element name");
return true;
}
@@ -117,14 +119,6 @@ void CustomElementRegistry::Trace(blink::Visitor* visitor) {
ScriptWrappable::Trace(visitor);
}
-void CustomElementRegistry::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(reaction_stack_);
- for (auto definition : definitions_)
- visitor->TraceWrappers(definition);
- ScriptWrappable::TraceWrappers(visitor);
-}
-
CustomElementDefinition* CustomElementRegistry::define(
ScriptState* script_state,
const AtomicString& name,
@@ -155,7 +149,7 @@ CustomElementDefinition* CustomElementRegistry::define(
if (NameIsDefined(name) || V0NameIsDefined(name)) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"this name has already been used with this registry");
return nullptr;
}
@@ -163,12 +157,17 @@ CustomElementDefinition* CustomElementRegistry::define(
if (!builder.CheckConstructorNotRegistered())
return nullptr;
+ // Polymer V2/V3 uses Custom Elements V1. <dom-module> is defined in its base
+ // library and is a strong signal that this is a Polymer V2+.
+ if (name == "dom-module") {
+ if (Document* document = owner_->document())
+ UseCounter::Count(*document, WebFeature::kPolymerV2Detected);
+ }
AtomicString local_name = name;
// Step 7. customized built-in elements definition
// element interface extends option checks
- if (RuntimeEnabledFeatures::CustomElementsBuiltinEnabled() &&
- options.hasExtends()) {
+ if (options.hasExtends()) {
// 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))
@@ -177,7 +176,8 @@ CustomElementDefinition* CustomElementRegistry::define(
if (htmlElementTypeForTag(extends) ==
HTMLElementType::kHTMLUnknownElement) {
exception_state.ThrowDOMException(
- kNotSupportedError, "\"" + extends + "\" is an HTMLUnknownElement");
+ DOMExceptionCode::kNotSupportedError,
+ "\"" + extends + "\" is an HTMLUnknownElement");
return nullptr;
}
// 7.3. Set localName to extends
@@ -192,7 +192,8 @@ CustomElementDefinition* CustomElementRegistry::define(
// DOMException and abort these steps.
if (element_definition_is_running_) {
exception_state.ThrowDOMException(
- kNotSupportedError, "an element definition is already being processed");
+ DOMExceptionCode::kNotSupportedError,
+ "an element definition is already being processed");
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_registry.h b/chromium/third_party/blink/renderer/core/html/custom/custom_element_registry.h
index 3aee6229840..ca2dd90e80d 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_registry.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_registry.h
@@ -69,7 +69,6 @@ class CORE_EXPORT CustomElementRegistry final : public ScriptWrappable {
void Entangle(V0CustomElementRegistrationContext*);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
friend class CustomElementRegistryTest;
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_registry_test.cc b/chromium/third_party/blink/renderer/core/html/custom/custom_element_registry_test.cc
index a914f62db7f..b36542033cc 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_registry_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_registry_test.cc
@@ -8,7 +8,6 @@
#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/css/css_style_sheet_init.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -16,6 +15,7 @@
#include "third_party/blink/renderer/core/dom/element_definition_options.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/dom/shadow_root_init.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/html/custom/ce_reactions_scope.h"
#include "third_party/blink/renderer/core/html/custom/custom_element_definition.h"
#include "third_party/blink/renderer/core/html/custom/custom_element_definition_builder.h"
@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/core/html/custom/custom_element_test_helpers.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/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -436,9 +437,7 @@ TEST_F(CustomElementRegistryTest, defineCustomElementWithStyle) {
RuntimeEnabledFeatures::SetConstructableStylesheetsEnabled(true);
NonThrowableExceptionState should_not_throw;
ElementDefinitionOptions options;
- CSSStyleSheet* sheet =
- CSSStyleSheet::Create(GetDocument(), ":host { color: red; }",
- CSSStyleSheetInit(), should_not_throw);
+ CSSStyleSheet* sheet = CSSStyleSheet::Create(GetDocument(), should_not_throw);
options.setStyle(sheet);
TestCustomElementDefinitionBuilder builder(sheet);
CustomElementDefinition* definition_a =
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_test.cc b/chromium/third_party/blink/renderer/core/html/custom/custom_element_test.cc
index df0a9890d37..5b14a04fbf3 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_test.cc
@@ -8,6 +8,7 @@
#include <memory>
#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/html/custom/custom_element_definition.h"
#include "third_party/blink/renderer/core/html/custom/custom_element_registry.h"
#include "third_party/blink/renderer/core/html/custom/custom_element_test_helpers.h"
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_test_helpers.h b/chromium/third_party/blink/renderer/core/html/custom/custom_element_test_helpers.h
index dacd24d686c..5573d939ebf 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_test_helpers.h
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_test_helpers.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_CUSTOM_CUSTOM_ELEMENT_TEST_HELPERS_H_
#include "base/macros.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/element_definition_options.h"
@@ -15,6 +14,7 @@
#include "third_party/blink/renderer/core/html/custom/custom_element_definition.h"
#include "third_party/blink/renderer/core/html/custom/custom_element_definition_builder.h"
#include "third_party/blink/renderer/core/html/html_document.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
diff --git a/chromium/third_party/blink/renderer/core/html/custom/custom_element_upgrade_sorter_test.cc b/chromium/third_party/blink/renderer/core/html/custom/custom_element_upgrade_sorter_test.cc
index cd8e83660ca..9bd894aef5a 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/custom_element_upgrade_sorter_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/custom/custom_element_upgrade_sorter_test.cc
@@ -6,7 +6,6 @@
#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_dictionary.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -16,6 +15,7 @@
#include "third_party/blink/renderer/core/html/html_document.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
diff --git a/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_exception.cc b/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_exception.cc
index f0b4ebf9f8e..e199eaadd23 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_exception.cc
+++ b/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_exception.cc
@@ -30,8 +30,7 @@
#include "third_party/blink/renderer/core/html/custom/v0_custom_element_exception.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -45,44 +44,44 @@ void V0CustomElementException::ThrowException(Reason reason,
switch (reason) {
case kCannotRegisterFromExtension:
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
Preamble(type) + "Elements cannot be registered from extensions.");
return;
case kConstructorPropertyNotConfigurable:
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
Preamble(type) +
"Prototype constructor property is not configurable.");
return;
case kContextDestroyedCheckingPrototype:
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
Preamble(type) + "The context is no longer valid.");
return;
case kContextDestroyedCreatingCallbacks:
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
Preamble(type) + "The context is no longer valid.");
return;
case kContextDestroyedRegisteringDefinition:
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
Preamble(type) + "The context is no longer valid.");
return;
case kExtendsIsInvalidName:
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
Preamble(type) +
"The tag name specified in 'extends' is not a valid tag name.");
return;
case kExtendsIsCustomElementName:
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
Preamble(type) +
"The tag name specified in "
"'extends' is a custom element "
@@ -91,19 +90,21 @@ void V0CustomElementException::ThrowException(Reason reason,
case kInvalidName:
exception_state.ThrowDOMException(
- kSyntaxError, Preamble(type) + "The type name is invalid.");
+ DOMExceptionCode::kSyntaxError,
+ Preamble(type) + "The type name is invalid.");
return;
case kPrototypeInUse:
exception_state.ThrowDOMException(
- kNotSupportedError, Preamble(type) +
- "The prototype is already in-use as "
- "an interface prototype object.");
+ DOMExceptionCode::kNotSupportedError,
+ Preamble(type) +
+ "The prototype is already in-use as "
+ "an interface prototype object.");
return;
case kTypeAlreadyRegistered:
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
Preamble(type) + "A type with that name is already registered.");
return;
}
diff --git a/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.cc b/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.cc
index 13ffce8e370..fd728fecde3 100644
--- a/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.cc
+++ b/chromium/third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.cc
@@ -30,7 +30,6 @@
#include "third_party/blink/renderer/core/html/custom/v0_custom_element_registration_context.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/html/custom/v0_custom_element.h"
@@ -41,6 +40,7 @@
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/svg/svg_unknown_element.h"
#include "third_party/blink/renderer/core/svg_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/base_checkable_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/base_checkable_input_type.cc
index 4b4a558300f..c8137f0297f 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/base_checkable_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/base_checkable_input_type.cc
@@ -62,7 +62,7 @@ void BaseCheckableInputType::RestoreFormControlState(
void BaseCheckableInputType::AppendToFormData(FormData& form_data) const {
if (GetElement().checked())
- form_data.append(GetElement().GetName(), GetElement().value());
+ form_data.AppendFromElement(GetElement().GetName(), GetElement().value());
}
void BaseCheckableInputType::HandleKeydownEvent(KeyboardEvent* event) {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/base_temporal_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/base_temporal_input_type.cc
index 6305600fa10..7cf6b0fb383 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/base_temporal_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/base_temporal_input_type.cc
@@ -191,7 +191,7 @@ bool BaseTemporalInputType::ValueMissing(const String& value) const {
return GetElement().IsRequired() && value.IsEmpty();
}
-bool BaseTemporalInputType::ShouldShowFocusRingOnMouseFocus() const {
+bool BaseTemporalInputType::MayTriggerVirtualKeyboard() const {
return true;
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/base_temporal_input_type.h b/chromium/third_party/blink/renderer/core/html/forms/base_temporal_input_type.h
index 72617e3af31..c48bf308795 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/base_temporal_input_type.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/base_temporal_input_type.h
@@ -101,7 +101,7 @@ class BaseTemporalInputType : public InputType {
String LocalizeValue(const String&) const override;
bool SupportsReadOnly() const override;
bool ShouldRespectListAttribute() override;
- bool ShouldShowFocusRingOnMouseFocus() const override;
+ bool MayTriggerVirtualKeyboard() const override;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc b/chromium/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc
index 628c3854337..e530f808439 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.cc
@@ -25,7 +25,6 @@
#include "third_party/blink/renderer/core/html/forms/chooser_only_temporal_input_type_view.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/dom/shadow_root.h"
@@ -33,6 +32,7 @@
#include "third_party/blink/renderer/core/html/html_div_element.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/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.cc b/chromium/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.cc
index 4de69ce8a60..4bd8a95e142 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.cc
@@ -26,7 +26,7 @@
#include "third_party/blink/renderer/core/html/forms/color_chooser_ui_controller.h"
#include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/blink/public/web/web_frame_client.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/html/forms/color_chooser_client.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
diff --git a/chromium/third_party/blink/renderer/core/html/forms/color_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/color_input_type.cc
index ab0b2d5e477..153c9b67d82 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/color_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/color_input_type.cc
@@ -30,7 +30,6 @@
#include "third_party/blink/renderer/core/html/forms/color_input_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/core/css_property_names.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
@@ -48,6 +47,7 @@
#include "third_party/blink/renderer/core/input_type_names.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -234,7 +234,7 @@ Element& ColorInputType::OwnerElement() const {
}
IntRect ColorInputType::ElementRectRelativeToViewport() const {
- return GetElement().GetDocument().View()->ContentsToViewport(
+ return GetElement().GetDocument().View()->FrameToViewport(
GetElement().PixelSnappedBoundingBox());
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/date_time_edit_element.cc b/chromium/third_party/blink/renderer/core/html/forms/date_time_edit_element.cc
index fd88a27f3d9..700e6c78a0d 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_time_edit_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_time_edit_element.cc
@@ -25,7 +25,6 @@
#include "third_party/blink/renderer/core/html/forms/date_time_edit_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#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"
@@ -35,6 +34,7 @@
#include "third_party/blink/renderer/core/html/shadow/shadow_element_names.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#include "third_party/blink/renderer/platform/text/date_time_format.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
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 6f2bfbaf0d2..2e46e6058ef 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
@@ -155,11 +155,11 @@ void DateTimeFieldElement::Initialize(const AtomicString& pseudo,
int ax_maximum) {
// On accessibility, DateTimeFieldElement acts like spin button.
setAttribute(roleAttr, AtomicString("spinbutton"));
- setAttribute(aria_valuetextAttr, AtomicString(VisibleValue()));
+ setAttribute(aria_placeholderAttr, AtomicString(Placeholder()));
setAttribute(aria_valueminAttr, AtomicString::Number(ax_minimum));
setAttribute(aria_valuemaxAttr, AtomicString::Number(ax_maximum));
- setAttribute(aria_helpAttr, AtomicString(ax_help_text));
+ setAttribute(aria_labelAttr, AtomicString(ax_help_text));
SetShadowPseudoId(pseudo);
AppendChild(Text::Create(GetDocument(), VisibleValue()));
}
@@ -218,10 +218,11 @@ void DateTimeFieldElement::UpdateVisibleValue(EventBehavior event_behavior) {
if (HasValue()) {
setAttribute(aria_valuenowAttr,
AtomicString::Number(ValueForARIAValueNow()));
+ setAttribute(aria_valuetextAttr, AtomicString(new_visible_value));
} else {
removeAttribute(aria_valuenowAttr);
+ removeAttribute(aria_valuetextAttr);
}
- setAttribute(aria_valuetextAttr, AtomicString(new_visible_value));
if (event_behavior == kDispatchEvent && field_owner_)
field_owner_->FieldValueChanged();
diff --git a/chromium/third_party/blink/renderer/core/html/forms/date_time_field_element.h b/chromium/third_party/blink/renderer/core/html/forms/date_time_field_element.h
index 94e41be73c7..f6cd41ebef9 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_time_field_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_time_field_element.h
@@ -64,6 +64,7 @@ class DateTimeFieldElement : public HTMLSpanElement {
virtual bool HasValue() const = 0;
bool IsDisabled() const;
virtual float MaximumWidth(const ComputedStyle&);
+ virtual String Placeholder() const = 0;
virtual void PopulateDateTimeFieldsState(DateTimeFieldsState&) = 0;
void RemoveEventHandler() { field_owner_ = nullptr; }
void SetDisabled();
diff --git a/chromium/third_party/blink/renderer/core/html/forms/date_time_local_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/date_time_local_input_type.cc
index 083cd0b302f..399fe7ae777 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_time_local_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_time_local_input_type.cc
@@ -30,12 +30,12 @@
#include "third_party/blink/renderer/core/html/forms/date_time_local_input_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
#include "third_party/blink/renderer/core/html/forms/date_time_fields_state.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/input_type_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/date_components.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.cc b/chromium/third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.cc
index 33268c41aa8..21e1612c224 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.cc
@@ -164,6 +164,10 @@ int DateTimeNumericFieldElement::Maximum() const {
return range_.maximum;
}
+String DateTimeNumericFieldElement::Placeholder() const {
+ return placeholder_;
+}
+
void DateTimeNumericFieldElement::SetEmptyValue(EventBehavior event_behavior) {
if (IsDisabled())
return;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.h b/chromium/third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.h
index eeb5fb5d978..ffd9fcaa9f3 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_time_numeric_field_element.h
@@ -79,6 +79,7 @@ class DateTimeNumericFieldElement : public DateTimeFieldElement {
bool HasValue() const final;
void Initialize(const AtomicString& pseudo, const String& ax_help_text);
int Maximum() const;
+ String Placeholder() const override;
void SetEmptyValue(EventBehavior = kDispatchNoEvent) final;
void SetValueAsInteger(int, EventBehavior = kDispatchNoEvent) override;
int ValueAsInteger() const final;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/date_time_symbolic_field_element.cc b/chromium/third_party/blink/renderer/core/html/forms/date_time_symbolic_field_element.cc
index 5039df9f369..25a3c572c28 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_time_symbolic_field_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_time_symbolic_field_element.cc
@@ -120,6 +120,10 @@ void DateTimeSymbolicFieldElement::SetValueAsInteger(
UpdateVisibleValue(event_behavior);
}
+String DateTimeSymbolicFieldElement::Placeholder() const {
+ return VisibleEmptyValue();
+}
+
void DateTimeSymbolicFieldElement::StepDown() {
if (HasValue()) {
if (!IndexIsInRange(--selected_index_))
diff --git a/chromium/third_party/blink/renderer/core/html/forms/date_time_symbolic_field_element.h b/chromium/third_party/blink/renderer/core/html/forms/date_time_symbolic_field_element.h
index 8f515406d1e..59cf9e95218 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/date_time_symbolic_field_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/date_time_symbolic_field_element.h
@@ -60,6 +60,7 @@ class DateTimeSymbolicFieldElement : public DateTimeFieldElement,
// DateTimeFieldElement functions.
void HandleKeyboardEvent(KeyboardEvent*) final;
float MaximumWidth(const ComputedStyle&) override;
+ String Placeholder() const override;
void StepDown() final;
void StepUp() final;
String Value() const final;
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 0494c275d10..eea198a77ef 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
@@ -36,7 +36,7 @@
#include "third_party/blink/public/platform/web_mouse_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_frame_client.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/public/web/web_view.h"
@@ -103,7 +103,7 @@ bool ExternalPopupMenu::ShowInternal() {
->LocalToAbsoluteQuad(FloatQuad(
ToLayoutBox(layout_object)->BorderBoundingBox())));
IntRect rect(quad.EnclosingBoundingBox());
- IntRect rect_in_viewport = local_frame_->View()->ContentsToViewport(rect);
+ IntRect rect_in_viewport = local_frame_->View()->FrameToViewport(rect);
web_external_popup_menu_->Show(rect_in_viewport);
return true;
}
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 ae817ac2662..12bcb903ae4 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
@@ -32,7 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_EXTERNAL_POPUP_MENU_H_
#include <memory>
-#include "third_party/blink/public/platform/web_canvas.h"
+#include "cc/paint/paint_canvas.h"
#include "third_party/blink/public/web/web_external_popup_menu_client.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/html/forms/popup_menu.h"
diff --git a/chromium/third_party/blink/renderer/core/html/forms/file_chooser.cc b/chromium/third_party/blink/renderer/core/html/forms/file_chooser.cc
index ebc3146a21d..bfab0af72fb 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/file_chooser.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/file_chooser.cc
@@ -41,6 +41,11 @@ FileChooser* FileChooserClient::NewFileChooser(
return chooser_.get();
}
+void FileChooserClient::DisconnectFileChooser() {
+ DCHECK(HasConnectedFileChooser());
+ chooser_->DisconnectClient();
+}
+
inline FileChooser::FileChooser(FileChooserClient* client,
const WebFileChooserParams& params)
: client_(client), params_(params) {}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/file_chooser.h b/chromium/third_party/blink/renderer/core/html/forms/file_chooser.h
index b0d4ce85213..879fcd9176e 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/file_chooser.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/file_chooser.h
@@ -67,6 +67,10 @@ class FileChooserClient : public GarbageCollectedMixin {
protected:
FileChooser* NewFileChooser(const WebFileChooserParams&);
+ bool HasConnectedFileChooser() const { return chooser_.get(); }
+
+ // This should be called if a user chose files or cancel the dialog.
+ void DisconnectFileChooser();
private:
scoped_refptr<FileChooser> chooser_;
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 ac9f83feee2..eb2f4437747 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
@@ -22,7 +22,6 @@
#include "third_party/blink/renderer/core/html/forms/file_input_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
@@ -38,6 +37,7 @@
#include "third_party/blink/renderer/core/layout/layout_file_upload_control.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/drag_data.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/file_metadata.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
@@ -124,12 +124,13 @@ void FileInputType::AppendToFormData(FormData& form_data) const {
FileList* file_list = GetElement().files();
unsigned num_files = file_list->length();
if (num_files == 0) {
- form_data.append(GetElement().GetName(), File::Create(""));
+ form_data.AppendFromElement(GetElement().GetName(), File::Create(""));
return;
}
- for (unsigned i = 0; i < num_files; ++i)
- form_data.append(GetElement().GetName(), file_list->item(i));
+ for (unsigned i = 0; i < num_files; ++i) {
+ form_data.AppendFromElement(GetElement().GetName(), file_list->item(i));
+ }
}
bool FileInputType::ValueMissing(const String& value) const {
@@ -170,6 +171,7 @@ void FileInputType::HandleDOMActivateEvent(Event* event) {
: WebFeature::kInputTypeFileInsecureOriginOpenChooser);
chrome_client->OpenFileChooser(document.GetFrame(), NewFileChooser(params));
+ chrome_client->RegisterPopupOpeningObserver(this);
}
event->SetDefaultHandled();
}
@@ -347,6 +349,11 @@ void FileInputType::SetFiles(FileList* files) {
void FileInputType::FilesChosen(const Vector<FileChooserFileInfo>& files) {
SetFiles(CreateFileList(files,
GetElement().FastHasAttribute(webkitdirectoryAttr)));
+ if (HasConnectedFileChooser()) {
+ DisconnectFileChooser();
+ if (auto* chrome_client = GetChromeClient())
+ chrome_client->UnregisterPopupOpeningObserver(this);
+ }
}
void FileInputType::SetFilesFromDirectory(const String& path) {
@@ -453,4 +460,12 @@ void FileInputType::HandleKeyupEvent(KeyboardEvent* event) {
KeyboardClickableInputTypeView::HandleKeyupEvent(event);
}
+void FileInputType::WillOpenPopup() {
+ // TODO(tkent): Should we disconnect the file chooser? crbug.com/637639
+ if (HasConnectedFileChooser()) {
+ UseCounter::Count(GetElement().GetDocument(),
+ WebFeature::kPopupOpenWhileFileChooserOpened);
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/file_input_type.h b/chromium/third_party/blink/renderer/core/html/forms/file_input_type.h
index 25aa374372f..4227f174f05 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/file_input_type.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/file_input_type.h
@@ -37,6 +37,7 @@
#include "third_party/blink/renderer/core/html/forms/file_chooser.h"
#include "third_party/blink/renderer/core/html/forms/input_type.h"
#include "third_party/blink/renderer/core/html/forms/keyboard_clickable_input_type_view.h"
+#include "third_party/blink/renderer/core/page/popup_opening_observer.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
@@ -46,7 +47,8 @@ class FileList;
class CORE_EXPORT FileInputType final : public InputType,
public KeyboardClickableInputTypeView,
- private FileChooserClient {
+ private FileChooserClient,
+ private PopupOpeningObserver {
USING_GARBAGE_COLLECTED_MIXIN(FileInputType);
public:
@@ -98,6 +100,9 @@ class CORE_EXPORT FileInputType final : public InputType,
// FileChooserClient implementation.
void FilesChosen(const Vector<FileChooserFileInfo>&) override;
+ // PopupOpeningObserver implementation.
+ void WillOpenPopup() override;
+
void SetFilesFromDirectory(const String&);
Member<FileList> file_list_;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/file_input_type_test.cc b/chromium/third_party/blink/renderer/core/html/forms/file_input_type_test.cc
index 9ea88efd7b3..f962ee437d6 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/file_input_type_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/file_input_type_test.cc
@@ -50,8 +50,8 @@ TEST(FileInputTypeTest, ignoreDroppedNonNativeFiles) {
InputType* file_input = FileInputType::Create(*input);
DataObject* native_file_raw_drag_data = DataObject::Create();
- const DragData native_file_drag_data(native_file_raw_drag_data, IntPoint(),
- IntPoint(), kDragOperationCopy);
+ const DragData native_file_drag_data(native_file_raw_drag_data, FloatPoint(),
+ FloatPoint(), kDragOperationCopy);
native_file_drag_data.PlatformData()->Add(File::Create("/native/path"));
native_file_drag_data.PlatformData()->SetFilesystemId("fileSystemId");
file_input->ReceiveDroppedFiles(&native_file_drag_data);
@@ -61,7 +61,7 @@ TEST(FileInputTypeTest, ignoreDroppedNonNativeFiles) {
DataObject* non_native_file_raw_drag_data = DataObject::Create();
const DragData non_native_file_drag_data(non_native_file_raw_drag_data,
- IntPoint(), IntPoint(),
+ FloatPoint(), FloatPoint(),
kDragOperationCopy);
FileMetadata metadata;
metadata.length = 1234;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/form_data.cc b/chromium/third_party/blink/renderer/core/html/forms/form_data.cc
index 517245f7a87..263ac487dcf 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/form_data.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/form_data.cc
@@ -98,7 +98,7 @@ void FormData::Trace(blink::Visitor* visitor) {
}
void FormData::append(const String& name, const String& value) {
- entries_.push_back(new Entry(Normalize(name), Normalize(value)));
+ entries_.push_back(new Entry(name, value));
}
void FormData::append(ScriptState* script_state,
@@ -113,10 +113,9 @@ void FormData::append(ScriptState* script_state,
}
void FormData::deleteEntry(const String& name) {
- const String normalized_name = Normalize(name);
size_t i = 0;
while (i < entries_.size()) {
- if (entries_[i]->name() == normalized_name) {
+ if (entries_[i]->name() == name) {
entries_.EraseAt(i);
} else {
++i;
@@ -125,9 +124,8 @@ void FormData::deleteEntry(const String& name) {
}
void FormData::get(const String& name, FormDataEntryValue& result) {
- const String normalized_name = Normalize(name);
for (const auto& entry : Entries()) {
- if (entry->name() == normalized_name) {
+ if (entry->name() == name) {
if (entry->IsString()) {
result.SetUSVString(entry->Value());
} else {
@@ -142,9 +140,8 @@ void FormData::get(const String& name, FormDataEntryValue& result) {
HeapVector<FormDataEntryValue> FormData::getAll(const String& name) {
HeapVector<FormDataEntryValue> results;
- const String normalized_name = Normalize(name);
for (const auto& entry : Entries()) {
- if (entry->name() != normalized_name)
+ if (entry->name() != name)
continue;
FormDataEntryValue value;
if (entry->IsString()) {
@@ -159,29 +156,27 @@ HeapVector<FormDataEntryValue> FormData::getAll(const String& name) {
}
bool FormData::has(const String& name) {
- const String normalized_name = Normalize(name);
for (const auto& entry : Entries()) {
- if (entry->name() == normalized_name)
+ if (entry->name() == name)
return true;
}
return false;
}
void FormData::set(const String& name, const String& value) {
- SetEntry(new Entry(Normalize(name), Normalize(value)));
+ SetEntry(new Entry(name, value));
}
void FormData::set(const String& name, Blob* blob, const String& filename) {
- SetEntry(new Entry(Normalize(name), blob, filename));
+ SetEntry(new Entry(name, blob, filename));
}
void FormData::SetEntry(const Entry* entry) {
DCHECK(entry);
- const String normalized_name = entry->name();
bool found = false;
size_t i = 0;
while (i < entries_.size()) {
- if (entries_[i]->name() != normalized_name) {
+ if (entries_[i]->name() != entry->name()) {
++i;
} else if (found) {
entries_.EraseAt(i);
@@ -195,12 +190,20 @@ void FormData::SetEntry(const Entry* entry) {
entries_.push_back(entry);
}
-void FormData::append(const String& name, int value) {
- append(name, String::Number(value));
+void FormData::append(const String& name, Blob* blob, const String& filename) {
+ entries_.push_back(new Entry(name, blob, filename));
}
-void FormData::append(const String& name, Blob* blob, const String& filename) {
- entries_.push_back(new Entry(Normalize(name), blob, filename));
+void FormData::AppendFromElement(const String& name, int value) {
+ append(Normalize(name), String::Number(value));
+}
+
+void FormData::AppendFromElement(const String& name, File* file) {
+ entries_.push_back(new Entry(Normalize(name), file, String()));
+}
+
+void FormData::AppendFromElement(const String& name, const String& value) {
+ entries_.push_back(new Entry(Normalize(name), Normalize(value)));
}
CString FormData::Encode(const String& string) const {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/form_data.h b/chromium/third_party/blink/renderer/core/html/forms/form_data.h
index d9074552acc..5ef582cf79c 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/form_data.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/form_data.h
@@ -83,8 +83,10 @@ class CORE_EXPORT FormData final
class Entry;
const HeapVector<Member<const Entry>>& Entries() const { return entries_; }
size_t size() const { return entries_.size(); }
- void append(const String& name, int value);
void append(const String& name, Blob*, const String& filename = String());
+ void AppendFromElement(const String& name, int value);
+ void AppendFromElement(const String& name, File* file);
+ void AppendFromElement(const String& name, const String& value);
// This flag is true if this FormData is created with a <form>, and its
// associated elements contain a non-empty password field.
diff --git a/chromium/third_party/blink/renderer/core/html/forms/form_data_test.cc b/chromium/third_party/blink/renderer/core/html/forms/form_data_test.cc
index 4dd7c8a13a5..03bb2f68521 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/form_data_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/form_data_test.cc
@@ -8,6 +8,37 @@
namespace blink {
+TEST(FormDataTest, append) {
+ FormData* fd = FormData::Create(UTF8Encoding());
+ fd->append("test\n1", "value\n1");
+ fd->append("test\r2", nullptr, "filename");
+
+ const FormData::Entry& entry1 = *fd->Entries()[0];
+ EXPECT_EQ("test\n1", entry1.name());
+ EXPECT_EQ("value\n1", entry1.Value());
+
+ const FormData::Entry& entry2 = *fd->Entries()[1];
+ EXPECT_EQ("test\r2", entry2.name());
+}
+
+TEST(FormDataTest, AppendFromElement) {
+ FormData* fd = FormData::Create(UTF8Encoding());
+ fd->AppendFromElement("Atomic\nNumber", 1);
+ fd->AppendFromElement("Periodic\nTable", nullptr);
+ fd->AppendFromElement("Noble\nGas", "He\rNe\nAr\r\nKr");
+
+ const FormData::Entry& entry1 = *fd->Entries()[0];
+ EXPECT_EQ("Atomic\r\nNumber", entry1.name());
+ EXPECT_EQ("1", entry1.Value());
+
+ const FormData::Entry& entry2 = *fd->Entries()[1];
+ EXPECT_EQ("Periodic\r\nTable", entry2.name());
+
+ const FormData::Entry& entry3 = *fd->Entries()[2];
+ EXPECT_EQ("Noble\r\nGas", entry3.name());
+ EXPECT_EQ("He\r\nNe\r\nAr\r\nKr", entry3.Value());
+}
+
TEST(FormDataTest, get) {
FormData* fd = FormData::Create(UTF8Encoding());
fd->append("name1", "value1");
diff --git a/chromium/third_party/blink/renderer/core/html/forms/hidden_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/hidden_input_type.cc
index 02bdd554181..47277e80186 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/hidden_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/hidden_input_type.cc
@@ -90,8 +90,8 @@ void HiddenInputType::SetValue(const String& sanitized_value,
void HiddenInputType::AppendToFormData(FormData& form_data) const {
if (DeprecatedEqualIgnoringCase(GetElement().GetName(), "_charset_")) {
- form_data.append(GetElement().GetName(),
- String(form_data.Encoding().GetName()));
+ form_data.AppendFromElement(GetElement().GetName(),
+ String(form_data.Encoding().GetName()));
return;
}
InputType::AppendToFormData(form_data);
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 6e1ba1efce9..13ad529582c 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
@@ -172,7 +172,7 @@ void HTMLButtonElement::SetActivatedSubmit(bool flag) {
void HTMLButtonElement::AppendToFormData(FormData& form_data) {
if (type_ == SUBMIT && !GetName().IsEmpty() && is_activated_submit_)
- form_data.append(GetName(), Value());
+ form_data.AppendFromElement(GetName(), Value());
}
void HTMLButtonElement::AccessKeyAction(bool send_mouse_events) {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_field_set_element.cc b/chromium/third_party/blink/renderer/core/html/forms/html_field_set_element.cc
index 34b273b7a15..e36583588de 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_field_set_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_field_set_element.cc
@@ -25,12 +25,12 @@
#include "third_party/blink/renderer/core/html/forms/html_field_set_element.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
+#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/dom/node_lists_node_data.h"
#include "third_party/blink/renderer/core/html/forms/html_legend_element.h"
#include "third_party/blink/renderer/core/html/html_collection.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/layout_fieldset.h"
-#include "third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_field_set_element.h b/chromium/third_party/blink/renderer/core/html/forms/html_field_set_element.h
index 3020e62468a..7e19e79f146 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_field_set_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_field_set_element.h
@@ -48,6 +48,7 @@ class CORE_EXPORT HTMLFieldSetElement final : public HTMLFormControlElement {
bool IsEnumeratable() const override { return true; }
bool SupportsFocus() const override;
LayoutObject* CreateLayoutObject(const ComputedStyle&) override;
+ bool ShouldForceLegacyLayout() const final { return true; }
const AtomicString& FormControlType() const override;
bool RecalcWillValidate() const override { return false; }
int tabIndex() const final;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.cc b/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.cc
index 76207df3f67..f0fd9883c82 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.cc
@@ -25,9 +25,10 @@
#include "third_party/blink/renderer/core/html/forms/html_form_control_element.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#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/events/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/html/forms/html_data_list_element.h"
#include "third_party/blink/renderer/core/html/forms/html_field_set_element.h"
@@ -40,7 +41,6 @@
#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/page/validation_message_client.h"
-#include "third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/text/bidi_text_run.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -52,10 +52,10 @@ using namespace HTMLNames;
HTMLFormControlElement::HTMLFormControlElement(const QualifiedName& tag_name,
Document& document)
: LabelableElement(tag_name, document),
+ autofill_state_(WebAutofillState::kNotFilled),
ancestor_disabled_state_(kAncestorDisabledStateUnknown),
data_list_ancestor_state_(kUnknown),
may_have_field_set_ancestor_(true),
- is_autofilled_(false),
has_validation_message_(false),
will_validate_initialized_(false),
will_validate_(true),
@@ -147,7 +147,7 @@ void HTMLFormControlElement::AncestorDisabledStateWasChanged() {
}
void HTMLFormControlElement::Reset() {
- SetAutofilled(false);
+ SetAutofillState(WebAutofillState::kNotFilled);
ResetImpl();
}
@@ -232,11 +232,11 @@ bool HTMLFormControlElement::IsAutofocusable() const {
return FastHasAttribute(autofocusAttr) && SupportsAutofocus();
}
-void HTMLFormControlElement::SetAutofilled(bool autofilled) {
- if (autofilled == is_autofilled_)
+void HTMLFormControlElement::SetAutofillState(WebAutofillState autofill_state) {
+ if (autofill_state == autofill_state_)
return;
- is_autofilled_ = autofilled;
+ autofill_state_ = autofill_state;
PseudoStateChanged(CSSSelector::kPseudoAutofill);
}
@@ -409,30 +409,13 @@ bool HTMLFormControlElement::IsKeyboardFocusable() const {
return IsFocusable();
}
-bool HTMLFormControlElement::ShouldShowFocusRingOnMouseFocus() const {
+bool HTMLFormControlElement::MayTriggerVirtualKeyboard() const {
return false;
}
bool HTMLFormControlElement::ShouldHaveFocusAppearance() const {
- return !WasFocusedByMouse() || ShouldShowFocusRingOnMouseFocus();
-}
-
-void HTMLFormControlElement::WillCallDefaultEventHandler(const Event& event) {
- if (!WasFocusedByMouse())
- return;
- if (!event.IsKeyboardEvent() || event.type() != EventTypeNames::keydown)
- return;
-
- bool old_should_have_focus_appearance = ShouldHaveFocusAppearance();
- SetWasFocusedByMouse(false);
-
- // Changes to WasFocusedByMouse may affect ShouldHaveFocusAppearance() and
- // LayoutTheme::IsFocused(). Inform LayoutTheme if
- // ShouldHaveFocusAppearance() changes.
- if (old_should_have_focus_appearance != ShouldHaveFocusAppearance() &&
- GetLayoutObject()) {
- GetLayoutObject()->InvalidateIfControlStateChanged(kFocusControlState);
- }
+ return (GetDocument().LastFocusType() != kWebFocusTypeMouse) ||
+ GetDocument().HadKeyboardEvent() || MayTriggerVirtualKeyboard();
}
int HTMLFormControlElement::tabIndex() const {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.h b/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.h
index b842357d012..a04b6f74193 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_form_control_element.h
@@ -25,6 +25,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_HTML_FORM_CONTROL_ELEMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_HTML_FORM_CONTROL_ELEMENT_H_
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/web/web_autofill_state.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/labelable_element.h"
@@ -122,10 +124,13 @@ class CORE_EXPORT HTMLFormControlElement : public LabelableElement,
bool IsAutofocusable() const;
- virtual bool ShouldShowFocusRingOnMouseFocus() const;
+ bool MayTriggerVirtualKeyboard() const override;
- bool IsAutofilled() const { return is_autofilled_; }
- void SetAutofilled(bool = true);
+ WebAutofillState GetAutofillState() const { return autofill_state_; }
+ bool IsAutofilled() const {
+ return autofill_state_ != WebAutofillState::kNotFilled;
+ }
+ void SetAutofillState(WebAutofillState = WebAutofillState::kAutofilled);
// The autofill section to which this element belongs (e.g. billing address,
// shipping address, .. .)
@@ -171,7 +176,6 @@ class CORE_EXPORT HTMLFormControlElement : public LabelableElement,
void DispatchBlurEvent(Element* new_focused_element,
WebFocusType,
InputDeviceCapabilities* source_capabilities) override;
- void WillCallDefaultEventHandler(const Event&) final;
void DidRecalcStyle(StyleRecalcChange) override;
@@ -202,6 +206,7 @@ class CORE_EXPORT HTMLFormControlElement : public LabelableElement,
unsigned unique_renderer_form_control_id_;
WebString autofill_section_;
+ enum WebAutofillState autofill_state_;
enum AncestorDisabledState {
kAncestorDisabledStateUnknown,
@@ -213,7 +218,7 @@ class CORE_EXPORT HTMLFormControlElement : public LabelableElement,
enum DataListAncestorState { kUnknown, kInsideDataList, kNotInsideDataList };
mutable enum DataListAncestorState data_list_ancestor_state_;
mutable bool may_have_field_set_ancestor_ : 1;
- bool is_autofilled_ : 1;
+
bool has_validation_message_ : 1;
// The initial value of m_willValidate depends on the derived class. We can't
// initialize it with a virtual function in the constructor. m_willValidate
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 6772bb25ff4..7fd27d29aae 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
@@ -74,8 +74,7 @@ HTMLFormElement::HTMLFormElement(Document& document)
has_elements_associated_by_parser_(false),
has_elements_associated_by_form_attribute_(false),
did_finish_parsing_children_(false),
- is_in_reset_function_(false),
- was_demoted_(false) {
+ is_in_reset_function_(false) {
static unsigned next_nique_renderer_form_id = 0;
unique_renderer_form_id_ = next_nique_renderer_form_id++;
}
@@ -105,41 +104,6 @@ bool HTMLFormElement::IsValidElement() {
nullptr, kCheckValidityDispatchNoEvent);
}
-bool HTMLFormElement::LayoutObjectIsNeeded(const ComputedStyle& style) const {
- if (!was_demoted_)
- return HTMLElement::LayoutObjectIsNeeded(style);
-
- ContainerNode* node = parentNode();
- if (!node || !node->GetLayoutObject())
- return HTMLElement::LayoutObjectIsNeeded(style);
- LayoutObject* parent_layout_object = node->GetLayoutObject();
- // FIXME: Shouldn't we also check for table caption (see |formIsTablePart|
- // below).
- // FIXME: This check is not correct for Shadow DOM.
- bool parent_is_table_element_part =
- (parent_layout_object->IsTable() && IsHTMLTableElement(*node)) ||
- (parent_layout_object->IsTableRow() && IsHTMLTableRowElement(*node)) ||
- (parent_layout_object->IsTableSection() && node->HasTagName(tbodyTag)) ||
- (parent_layout_object->IsLayoutTableCol() && node->HasTagName(colTag)) ||
- (parent_layout_object->IsTableCell() && IsHTMLTableRowElement(*node));
-
- if (!parent_is_table_element_part)
- return true;
-
- EDisplay display = style.Display();
- bool form_is_table_part =
- display == EDisplay::kTable || display == EDisplay::kInlineTable ||
- display == EDisplay::kTableRowGroup ||
- display == EDisplay::kTableHeaderGroup ||
- display == EDisplay::kTableFooterGroup ||
- display == EDisplay::kTableRow ||
- display == EDisplay::kTableColumnGroup ||
- display == EDisplay::kTableColumn || display == EDisplay::kTableCell ||
- display == EDisplay::kTableCaption;
-
- return form_is_table_part;
-}
-
Node::InsertionNotificationRequest HTMLFormElement::InsertedInto(
ContainerNode* insertion_point) {
HTMLElement::InsertedInto(insertion_point);
@@ -525,6 +489,8 @@ void HTMLFormElement::ScheduleFormSubmission(FormSubmission* submission) {
submission->CreateFrameLoadRequest(&GetDocument());
frame_load_request.GetResourceRequest().SetHasUserGesture(
Frame::HasTransientUserActivation(GetDocument().GetFrame()));
+ // TODO(dgozman): we lose information about triggering event and desired
+ // navigation policy here.
ToRemoteFrame(target_frame)->Navigate(frame_load_request);
}
}
@@ -834,12 +800,6 @@ void HTMLFormElement::FinishParsingChildren() {
did_finish_parsing_children_ = true;
}
-void HTMLFormElement::CloneNonAttributePropertiesFrom(const Element& source,
- CloneChildrenFlag flag) {
- was_demoted_ = ToHTMLFormElement(source).was_demoted_;
- HTMLElement::CloneNonAttributePropertiesFrom(source, flag);
-}
-
void HTMLFormElement::AnonymousNamedGetter(
const AtomicString& name,
RadioNodeListOrElement& return_value) {
@@ -883,12 +843,6 @@ void HTMLFormElement::AnonymousNamedGetter(
return_value.SetRadioNodeList(GetRadioNodeList(name, only_match_img));
}
-void HTMLFormElement::SetDemoted(bool demoted) {
- if (demoted)
- UseCounter::Count(GetDocument(), WebFeature::kDemotedFormElement);
- was_demoted_ = demoted;
-}
-
void HTMLFormElement::InvalidateDefaultButtonStyle() const {
for (const auto& control : ListedElements()) {
if (!control->IsFormControlElement())
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_form_element.h b/chromium/third_party/blink/renderer/core/html/forms/html_form_element.h
index 5097d87540a..3b79057bd29 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_form_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_form_element.h
@@ -75,8 +75,6 @@ class CORE_EXPORT HTMLFormElement final : public HTMLElement {
void submitFromJavaScript();
void reset();
- void SetDemoted(bool);
-
void SubmitImplicitly(Event*, bool from_implicit_submission_trigger);
String GetName() const;
@@ -117,7 +115,6 @@ class CORE_EXPORT HTMLFormElement final : public HTMLElement {
private:
explicit HTMLFormElement(Document&);
- bool LayoutObjectIsNeeded(const ComputedStyle&) const override;
InsertionNotificationRequest InsertedInto(ContainerNode*) override;
void RemovedFrom(ContainerNode*) override;
void FinishParsingChildren() override;
@@ -132,9 +129,6 @@ class CORE_EXPORT HTMLFormElement final : public HTMLElement {
return NamedItemType::kName;
}
- void CloneNonAttributePropertiesFrom(const Element&,
- CloneChildrenFlag) override;
-
void SubmitDialog(FormSubmission*);
void Submit(Event*, HTMLFormControlElement* submit_button);
@@ -186,7 +180,6 @@ class CORE_EXPORT HTMLFormElement final : public HTMLElement {
bool has_elements_associated_by_form_attribute_ : 1;
bool did_finish_parsing_children_ : 1;
bool is_in_reset_function_ : 1;
- bool was_demoted_ : 1;
};
} // namespace blink
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 d696f9bd7a3..da1847ae422 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
@@ -32,17 +32,14 @@
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_scroll_into_view_params.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_event_listener.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/css_property_names.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
#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/sync_reattach_context.h"
#include "third_party/blink/renderer/core/dom/v0_insertion_point.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/spellcheck/spell_checker.h"
@@ -71,6 +68,8 @@
#include "third_party/blink/renderer/core/layout/layout_object.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/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/language.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
@@ -293,8 +292,8 @@ bool HTMLInputElement::IsKeyboardFocusable() const {
return input_type_->IsKeyboardFocusable();
}
-bool HTMLInputElement::ShouldShowFocusRingOnMouseFocus() const {
- return input_type_->ShouldShowFocusRingOnMouseFocus();
+bool HTMLInputElement::MayTriggerVirtualKeyboard() const {
+ return input_type_->MayTriggerVirtualKeyboard();
}
void HTMLInputElement::UpdateFocusAppearanceWithOptions(
@@ -615,7 +614,7 @@ void HTMLInputElement::setSelectionStartForBinding(
bool is_null,
ExceptionState& exception_state) {
if (!input_type_->SupportsSelectionAPI()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The input element's type ('" +
input_type_->FormControlType() +
"') does not support selection.");
@@ -629,7 +628,7 @@ void HTMLInputElement::setSelectionEndForBinding(
bool is_null,
ExceptionState& exception_state) {
if (!input_type_->SupportsSelectionAPI()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The input element's type ('" +
input_type_->FormControlType() +
"') does not support selection.");
@@ -642,7 +641,7 @@ void HTMLInputElement::setSelectionDirectionForBinding(
const String& direction,
ExceptionState& exception_state) {
if (!input_type_->SupportsSelectionAPI()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The input element's type ('" +
input_type_->FormControlType() +
"') does not support selection.");
@@ -656,7 +655,7 @@ void HTMLInputElement::setSelectionRangeForBinding(
unsigned end,
ExceptionState& exception_state) {
if (!input_type_->SupportsSelectionAPI()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The input element's type ('" +
input_type_->FormControlType() +
"') does not support selection.");
@@ -671,7 +670,7 @@ void HTMLInputElement::setSelectionRangeForBinding(
const String& direction,
ExceptionState& exception_state) {
if (!input_type_->SupportsSelectionAPI()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The input element's type ('" +
input_type_->FormControlType() +
"') does not support selection.");
@@ -874,7 +873,6 @@ LayoutObject* HTMLInputElement::CreateLayoutObject(const ComputedStyle& style) {
}
void HTMLInputElement::AttachLayoutTree(AttachContext& context) {
- SyncReattachContext reattach_context(context);
TextControlElement::AttachLayoutTree(context);
if (GetLayoutObject()) {
input_type_->OnAttachWithLayoutObject();
@@ -1103,7 +1101,7 @@ void HTMLInputElement::setValue(const String& value,
TextFieldEventBehavior event_behavior) {
// FIXME: Remove type check.
if (type() == InputTypeNames::file && !value.IsEmpty()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"This input element accepts a filename, "
"which may only be programmatically set "
"to the empty string.");
@@ -1125,7 +1123,7 @@ void HTMLInputElement::setValue(const String& value,
// Set autofilled to false, as the value might have been set by the website.
// If the field was autofilled, it'll be set to true from that method.
- SetAutofilled(false);
+ SetAutofillState(WebAutofillState::kNotFilled);
EventQueueScope scope;
String sanitized_value = SanitizeValue(value);
@@ -1228,7 +1226,7 @@ void HTMLInputElement::SetValueFromRenderer(const String& value) {
SetNeedsValidityCheck();
// Clear autofill flag (and yellow background) on user edit.
- SetAutofilled(false);
+ SetAutofillState(WebAutofillState::kNotFilled);
}
EventDispatchHandlingState* HTMLInputElement::PreDispatchEventHandler(
@@ -1450,7 +1448,8 @@ bool HTMLInputElement::Multiple() const {
void HTMLInputElement::setSize(unsigned size, ExceptionState& exception_state) {
if (size == 0) {
exception_state.ThrowDOMException(
- kIndexSizeError, "The value provided is 0, which is an invalid size.");
+ DOMExceptionCode::kIndexSizeError,
+ "The value provided is 0, which is an invalid size.");
} else {
SetUnsignedIntegralAttribute(sizeAttr, size ? size : kDefaultSize,
kDefaultSize);
@@ -1816,7 +1815,7 @@ void ListAttributeTargetObserver::IdTargetChanged() {
void HTMLInputElement::setRangeText(const String& replacement,
ExceptionState& exception_state) {
if (!input_type_->SupportsSelectionAPI()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The input element's type ('" +
input_type_->FormControlType() +
"') does not support selection.");
@@ -1832,7 +1831,7 @@ void HTMLInputElement::setRangeText(const String& replacement,
const String& selection_mode,
ExceptionState& exception_state) {
if (!input_type_->SupportsSelectionAPI()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The input element's type ('" +
input_type_->FormControlType() +
"') does not support selection.");
@@ -1870,7 +1869,7 @@ bool HTMLInputElement::SetupDateTimeChooserParameters(
}
parameters.anchor_rect_in_screen =
- GetDocument().View()->ContentsToScreen(PixelSnappedBoundingBox());
+ GetDocument().View()->FrameToScreen(PixelSnappedBoundingBox());
parameters.double_value = input_type_->ValueAsDouble();
parameters.is_anchor_element_rtl =
input_type_view_->ComputedTextDirection() == TextDirection::kRtl;
@@ -1919,6 +1918,15 @@ scoped_refptr<ComputedStyle> HTMLInputElement::CustomStyleForLayoutObject() {
OriginalStyleForLayoutObject());
}
+void HTMLInputElement::DidRecalcStyle(StyleRecalcChange change) {
+ TextControlElement::DidRecalcStyle(change);
+ if (change != kReattach)
+ return;
+ ComputedStyle* style = GetNonAttachedStyle();
+ if (style && style->Display() != EDisplay::kNone)
+ input_type_view_->StartResourceLoading();
+}
+
void HTMLInputElement::DidNotifySubtreeInsertionsToDocument() {
ListAttributeTargetChanged();
}
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 eae585d7811..d87939dcde0 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
@@ -321,7 +321,7 @@ class CORE_EXPORT HTMLInputElement
bool HasCustomFocusLogic() const final;
bool IsKeyboardFocusable() const final;
- bool ShouldShowFocusRingOnMouseFocus() const final;
+ bool MayTriggerVirtualKeyboard() const final;
bool IsEnumeratable() const final;
bool IsInteractiveContent() const final;
bool SupportLabels() const final;
@@ -400,6 +400,7 @@ class CORE_EXPORT HTMLInputElement
void AddToRadioButtonGroup();
void RemoveFromRadioButtonGroup();
scoped_refptr<ComputedStyle> CustomStyleForLayoutObject() override;
+ void DidRecalcStyle(StyleRecalcChange) override;
AtomicString name_;
// The value string in |value| value mode.
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_input_element.idl b/chromium/third_party/blink/renderer/core/html/forms/html_input_element.idl
index 099fed4b526..880bb6a5ab8 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_input_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_input_element.idl
@@ -21,6 +21,9 @@
// https://html.spec.whatwg.org/#the-input-element
+// The `URLString` reference below is from Trusted Types:
+// https://github.com/WICG/trusted-types/, which is still WIP.
+// https://crbug.com/739170.
enum SelectionMode { "select", "start", "end", "preserve" };
[
@@ -58,7 +61,7 @@ enum SelectionMode { "select", "start", "end", "preserve" };
[CEReactions, Reflect] attribute boolean readOnly;
[CEReactions, Reflect] attribute boolean required;
[CEReactions, RaisesException=Setter, CustomElementCallbacks] attribute unsigned long size;
- [CEReactions, Reflect, URL] attribute DOMString src;
+ [CEReactions, Reflect, URL, RaisesException=Setter] attribute URLString src;
[CEReactions, Reflect] attribute DOMString step;
[CEReactions, CustomElementCallbacks] attribute DOMString type;
[CEReactions, Reflect=value, CustomElementCallbacks] attribute DOMString defaultValue;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_input_element_test.cc b/chromium/third_party/blink/renderer/core/html/forms/html_input_element_test.cc
index 6bbe2a3568e..83cdd180392 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_input_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_input_element_test.cc
@@ -9,13 +9,16 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
#include "third_party/blink/renderer/core/events/keyboard_event_init.h"
+#include "third_party/blink/renderer/core/fileapi/file_list.h"
#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/html/forms/date_time_chooser.h"
+#include "third_party/blink/renderer/core/html/forms/file_input_type.h"
#include "third_party/blink/renderer/core/html/forms/html_form_element.h"
#include "third_party/blink/renderer/core/html/forms/html_option_element.h"
#include "third_party/blink/renderer/core/html/html_body_element.h"
#include "third_party/blink/renderer/core/html/html_html_element.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
namespace blink {
@@ -203,4 +206,29 @@ TEST_F(HTMLInputElementTest, ChangingInputTypeCausesShadowRootToBeCreated) {
EXPECT_NE(nullptr, input->UserAgentShadowRoot());
}
+TEST_F(HTMLInputElementTest, RepaintAfterClearingFile) {
+ GetDocument().body()->SetInnerHTMLFromString("<input type='file' />");
+ HTMLInputElement* input =
+ ToHTMLInputElement(GetDocument().body()->firstChild());
+
+ Vector<FileChooserFileInfo> files;
+ files.push_back(
+ FileChooserFileInfo("/native/path/native-file", "display-name"));
+ FileList* list = FileInputType::CreateFileList(files, false);
+ ASSERT_TRUE(list);
+ EXPECT_EQ(1u, list->length());
+
+ input->setFiles(list);
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ ASSERT_TRUE(input->GetLayoutObject());
+ EXPECT_FALSE(input->GetLayoutObject()->ShouldCheckForPaintInvalidation());
+
+ input->setValue("");
+ GetDocument().UpdateStyleAndLayoutTree();
+
+ ASSERT_TRUE(input->GetLayoutObject());
+ EXPECT_TRUE(input->GetLayoutObject()->ShouldCheckForPaintInvalidation());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_option_element.cc b/chromium/third_party/blink/renderer/core/html/forms/html_option_element.cc
index adfc167c3b0..09cc2e27ee8 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_option_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_option_element.cc
@@ -26,8 +26,7 @@
#include "third_party/blink/renderer/core/html/forms/html_option_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
@@ -40,6 +39,7 @@
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_options_collection.cc b/chromium/third_party/blink/renderer/core/html/forms/html_options_collection.cc
index e195f8aad68..98c6e68bc5e 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_options_collection.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_options_collection.cc
@@ -21,12 +21,11 @@
#include "third_party/blink/renderer/core/html/forms/html_options_collection.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/html_element_or_long.h"
#include "third_party/blink/renderer/bindings/core/v8/html_option_element_or_html_opt_group_element.h"
#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/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_output_element.cc b/chromium/third_party/blink/renderer/core/html/forms/html_output_element.cc
index 69fa1c1768b..05478b0d4e9 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_output_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_output_element.cc
@@ -30,8 +30,8 @@
#include "third_party/blink/renderer/core/html/forms/html_output_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
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 db3a150b877..0f81481f811 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
@@ -31,12 +31,10 @@
#include "build/build_config.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/html_element_or_long.h"
#include "third_party/blink/renderer/bindings/core/v8/html_option_element_or_html_opt_group_element.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/attribute.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
#include "third_party/blink/renderer/core/dom/mutation_observer.h"
@@ -72,6 +70,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/core/page/spatial_navigation.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
@@ -257,7 +256,7 @@ void HTMLSelectElement::setValue(const String& value, bool send_events) {
HTMLOptionElement* previous_selected_option = SelectedOption();
SetSuggestedOption(nullptr);
if (is_autofilled_by_preview_)
- SetAutofilled(false);
+ SetAutofillState(WebAutofillState::kNotFilled);
SelectOptionFlags flags = kDeselectOtherOptions | kMakeOptionDirty;
if (send_events)
flags |= kDispatchInputAndChangeEvent;
@@ -323,7 +322,7 @@ void HTMLSelectElement::ParseAttribute(
}
}
-bool HTMLSelectElement::ShouldShowFocusRingOnMouseFocus() const {
+bool HTMLSelectElement::MayTriggerVirtualKeyboard() const {
return true;
}
@@ -965,7 +964,7 @@ void HTMLSelectElement::OptionRemoved(HTMLOptionElement& option) {
if (suggested_option_ == &option)
SetSuggestedOption(nullptr);
if (option.Selected())
- SetAutofilled(false);
+ SetAutofillState(WebAutofillState::kNotFilled);
SetNeedsValidityCheck();
last_on_change_selection_.clear();
@@ -1001,7 +1000,7 @@ void HTMLSelectElement::SelectOption(HTMLOptionElement* element,
// selectedOption() is O(N).
if (IsAutofilled() && SelectedOption() != element)
- SetAutofilled(false);
+ SetAutofillState(WebAutofillState::kNotFilled);
if (element) {
if (!element->Selected())
@@ -1232,7 +1231,7 @@ void HTMLSelectElement::AppendToFormData(FormData& form_data) {
for (auto* const option : GetOptionList()) {
if (option->Selected() && !option->IsDisabledFormControl())
- form_data.append(name, option->value());
+ form_data.AppendFromElement(name, option->value());
}
}
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 ee6b5ea52ba..1474997846d 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
@@ -180,7 +180,7 @@ class CORE_EXPORT HTMLSelectElement final
private:
const AtomicString& FormControlType() const override;
- bool ShouldShowFocusRingOnMouseFocus() const override;
+ bool MayTriggerVirtualKeyboard() const override;
void DispatchFocusEvent(
Element* old_focused_element,
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 1e76096534f..9dff47c1d26 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
@@ -26,12 +26,10 @@
#include "third_party/blink/renderer/core/html/forms/html_text_area_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/css_value_keywords.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/dom/exception_code.h"
#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/editing/frame_selection.h"
@@ -48,6 +46,7 @@
#include "third_party/blink/renderer/core/layout/layout_text_control_multi_line.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/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -131,12 +130,12 @@ void HTMLTextAreaElement::CollectStyleForPresentationAttribute(
if (ShouldWrapText()) {
AddPropertyToPresentationAttributeStyle(style, CSSPropertyWhiteSpace,
CSSValuePreWrap);
- AddPropertyToPresentationAttributeStyle(style, CSSPropertyWordWrap,
+ AddPropertyToPresentationAttributeStyle(style, CSSPropertyOverflowWrap,
CSSValueBreakWord);
} else {
AddPropertyToPresentationAttributeStyle(style, CSSPropertyWhiteSpace,
CSSValuePre);
- AddPropertyToPresentationAttributeStyle(style, CSSPropertyWordWrap,
+ AddPropertyToPresentationAttributeStyle(style, CSSPropertyOverflowWrap,
CSSValueNormal);
}
} else {
@@ -221,11 +220,11 @@ void HTMLTextAreaElement::AppendToFormData(FormData& form_data) {
const String& text =
(wrap_ == kHardWrap) ? ValueWithHardLineBreaks() : value();
- form_data.append(GetName(), text);
+ form_data.AppendFromElement(GetName(), text);
const AtomicString& dirname_attr_value = FastGetAttribute(dirnameAttr);
if (!dirname_attr_value.IsNull())
- form_data.append(dirname_attr_value, DirectionForFormData());
+ form_data.AppendFromElement(dirname_attr_value, DirectionForFormData());
}
void HTMLTextAreaElement::ResetImpl() {
@@ -242,7 +241,7 @@ bool HTMLTextAreaElement::IsKeyboardFocusable() const {
return IsFocusable();
}
-bool HTMLTextAreaElement::ShouldShowFocusRingOnMouseFocus() const {
+bool HTMLTextAreaElement::MayTriggerVirtualKeyboard() const {
return true;
}
@@ -292,7 +291,7 @@ void HTMLTextAreaElement::SubtreeHasChanged() {
UpdateValue();
CheckIfValueWasReverted(value());
SetNeedsValidityCheck();
- SetAutofilled(false);
+ SetAutofillState(WebAutofillState::kNotFilled);
UpdatePlaceholderVisibility();
if (!IsFocused())
diff --git a/chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.h b/chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.h
index 9c4347d1733..20fc30c33d0 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/html_text_area_element.h
@@ -122,7 +122,7 @@ class CORE_EXPORT HTMLTextAreaElement final : public TextControlElement {
void AppendToFormData(FormData&) override;
void ResetImpl() override;
bool HasCustomFocusLogic() const override;
- bool ShouldShowFocusRingOnMouseFocus() const override;
+ bool MayTriggerVirtualKeyboard() const override;
bool IsKeyboardFocusable() const override;
void UpdateFocusAppearanceWithOptions(SelectionBehaviorOnFocus,
const FocusOptions&) override;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/image_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/image_input_type.cc
index fed797033fd..b5fe2fd1de2 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/image_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/image_input_type.cc
@@ -24,10 +24,7 @@
#include "third_party/blink/renderer/core/html/forms/image_input_type.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
-#include "third_party/blink/renderer/core/dom/sync_reattach_context.h"
#include "third_party/blink/renderer/core/events/mouse_event.h"
-#include "third_party/blink/renderer/core/frame/deprecation.h"
-#include "third_party/blink/renderer/core/frame/use_counter.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/forms/html_input_element.h"
@@ -39,6 +36,7 @@
#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_image.h"
+#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -65,22 +63,15 @@ void ImageInputType::AppendToFormData(FormData& form_data) const {
return;
const AtomicString& name = GetElement().GetName();
if (name.IsEmpty()) {
- form_data.append("x", click_location_.X());
- form_data.append("y", click_location_.Y());
+ form_data.AppendFromElement("x", click_location_.X());
+ form_data.AppendFromElement("y", click_location_.Y());
return;
}
DEFINE_STATIC_LOCAL(String, dot_x_string, (".x"));
DEFINE_STATIC_LOCAL(String, dot_y_string, (".y"));
- form_data.append(name + dot_x_string, click_location_.X());
- form_data.append(name + dot_y_string, click_location_.Y());
-
- if (!GetElement().value().IsEmpty()) {
- Deprecation::CountDeprecation(
- GetElement().GetDocument(),
- WebFeature::kImageInputTypeFormDataWithNonEmptyValue);
- form_data.append(name, GetElement().value());
- }
+ form_data.AppendFromElement(name + dot_x_string, click_location_.X());
+ form_data.AppendFromElement(name + dot_y_string, click_location_.Y());
}
String ImageInputType::ResultForDialogSubmit() const {
@@ -116,7 +107,7 @@ void ImageInputType::HandleDOMActivateEvent(Event* event) {
LayoutObject* ImageInputType::CreateLayoutObject(
const ComputedStyle& style) const {
if (use_fallback_content_)
- return new LayoutBlockFlow(&GetElement());
+ return LayoutObjectFactory::CreateBlockFlow(GetElement(), style);
LayoutImage* image = new LayoutImage(&GetElement());
image->SetImageResource(LayoutImageResource::Create());
return image;
@@ -150,11 +141,15 @@ void ImageInputType::StartResourceLoading() {
HTMLImageLoader& image_loader = GetElement().EnsureImageLoader();
image_loader.UpdateFromElement();
+}
+void ImageInputType::OnAttachWithLayoutObject() {
LayoutObject* layout_object = GetElement().GetLayoutObject();
- if (!layout_object || !layout_object->IsLayoutImage())
+ DCHECK(layout_object);
+ if (!layout_object->IsLayoutImage())
return;
+ HTMLImageLoader& image_loader = GetElement().EnsureImageLoader();
LayoutImageResource* image_resource =
ToLayoutImage(layout_object)->ImageResource();
image_resource->SetImageResource(image_loader.GetContent());
@@ -263,14 +258,8 @@ void ImageInputType::EnsurePrimaryContent() {
}
void ImageInputType::ReattachFallbackContent() {
- if (GetElement().GetDocument().InStyleRecalc()) {
- // This can happen inside of AttachLayoutTree() in the middle of a
- // RebuildLayoutTree, so we need to reattach synchronously here.
- GetElement().ReattachLayoutTree(
- SyncReattachContext::CurrentAttachContext());
- } else {
+ if (!GetElement().GetDocument().InStyleRecalc())
GetElement().LazyReattachIfAttached();
- }
}
void ImageInputType::CreateShadowSubtree() {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/image_input_type.h b/chromium/third_party/blink/renderer/core/html/forms/image_input_type.h
index 13f721c24e0..ea47c1acb06 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/image_input_type.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/image_input_type.h
@@ -57,6 +57,7 @@ class ImageInputType final : public BaseButtonInputType {
void SrcAttributeChanged() override;
void ValueAttributeChanged() override;
void StartResourceLoading() override;
+ void OnAttachWithLayoutObject() override;
bool ShouldRespectAlignAttribute() override;
bool CanBeSuccessfulSubmitButton() override;
bool IsEnumeratable() override;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/input_type.cc
index 6e0ad2c33b7..a2771e45ee4 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/input_type.cc
@@ -32,11 +32,8 @@
#include <memory>
#include <utility>
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
#include "third_party/blink/renderer/core/fileapi/file_list.h"
@@ -71,6 +68,7 @@
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/json/json_values.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
@@ -159,7 +157,7 @@ bool InputType::IsFormDataAppendable() const {
}
void InputType::AppendToFormData(FormData& form_data) const {
- form_data.append(GetElement().GetName(), GetElement().value());
+ form_data.AppendFromElement(GetElement().GetName(), GetElement().value());
}
String InputType::ResultForDialogSubmit() const {
@@ -172,7 +170,8 @@ double InputType::ValueAsDate() const {
void InputType::SetValueAsDate(double, ExceptionState& exception_state) const {
exception_state.ThrowDOMException(
- kInvalidStateError, "This input element does not support Date values.");
+ DOMExceptionCode::kInvalidStateError,
+ "This input element does not support Date values.");
}
double InputType::ValueAsDouble() const {
@@ -183,7 +182,8 @@ void InputType::SetValueAsDouble(double double_value,
TextFieldEventBehavior event_behavior,
ExceptionState& exception_state) const {
exception_state.ThrowDOMException(
- kInvalidStateError, "This input element does not support Number values.");
+ DOMExceptionCode::kInvalidStateError,
+ "This input element does not support Number values.");
}
void InputType::SetValueAsDecimal(const Decimal& new_value,
@@ -457,7 +457,7 @@ bool InputType::IsKeyboardFocusable() const {
return GetElement().IsFocusable();
}
-bool InputType::ShouldShowFocusRingOnMouseFocus() const {
+bool InputType::MayTriggerVirtualKeyboard() const {
return false;
}
@@ -680,7 +680,7 @@ void InputType::ApplyStep(const Decimal& current,
// InvalidStateError exception, and abort these steps.
if (!step_range.HasStep()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"This form element does not have an allowed value step.");
return;
}
@@ -768,7 +768,7 @@ StepRange InputType::CreateStepRange(AnyStepHandling) const {
void InputType::StepUp(double n, ExceptionState& exception_state) {
if (!IsSteppable()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"This form element is not steppable.");
return;
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/input_type.h b/chromium/third_party/blink/renderer/core/html/forms/input_type.h
index 5b844c9057d..16ca8d1a0e7 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/input_type.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/input_type.h
@@ -153,7 +153,7 @@ class CORE_EXPORT InputType : public GarbageCollectedFinalized<InputType> {
void WarnIfValueIsInvalidAndElementIsVisible(const String&) const;
virtual bool IsKeyboardFocusable() const;
- virtual bool ShouldShowFocusRingOnMouseFocus() const;
+ virtual bool MayTriggerVirtualKeyboard() const;
virtual bool CanBeSuccessfulSubmitButton();
virtual bool MatchesDefaultPseudoClass();
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 4e66eb00022..08fbc4733c8 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
@@ -514,11 +514,7 @@ void InternalPopupMenu::Update() {
return;
needs_update_ = false;
- if (!OwnerElement()
- .GetDocument()
- .GetFrame()
- ->View()
- ->VisibleContentRect()
+ if (!IntRect(IntPoint(), OwnerElement().GetDocument().View()->Size())
.Intersects(OwnerElement().PixelSnappedBoundingBox())) {
Hide();
return;
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 3481a05ca5d..2263a99f65d 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
@@ -32,6 +32,7 @@
#include "third_party/blink/renderer/core/css/style_change_reason.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
diff --git a/chromium/third_party/blink/renderer/core/html/forms/number_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/number_input_type.cc
index e7bfdd2c5bd..67232ce9a40 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/number_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/number_input_type.cc
@@ -32,7 +32,6 @@
#include "third_party/blink/renderer/core/html/forms/number_input_type.h"
#include <limits>
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
#include "third_party/blink/renderer/core/events/before_text_inserted_event.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
@@ -43,6 +42,7 @@
#include "third_party/blink/renderer/core/input_type_names.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
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 e2c2d2f59ed..643ec24d789 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
@@ -38,6 +38,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/layout_test_support.h"
+#include "third_party/blink/renderer/platform/text/platform_locale.h"
namespace blink {
@@ -169,6 +170,9 @@ void PickerIndicatorElement::DidNotifySubtreeInsertionsToDocument() {
setAttribute(tabindexAttr, "0");
setAttribute(aria_haspopupAttr, "menu");
setAttribute(roleAttr, "button");
+ setAttribute(aria_labelAttr,
+ AtomicString(GetLocale().QueryString(
+ WebLocalizedString::kAXCalendarShowDatePicker)));
}
void PickerIndicatorElement::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/radio_button_group_scope.cc b/chromium/third_party/blink/renderer/core/html/forms/radio_button_group_scope.cc
index 9f997f23b71..2b5a5909561 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/radio_button_group_scope.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/radio_button_group_scope.cc
@@ -20,7 +20,7 @@
#include "third_party/blink/renderer/core/html/forms/radio_button_group_scope.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/input_type_names.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
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 8f80f9c8ce6..c709be1ef9e 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
@@ -33,8 +33,7 @@
#include <algorithm>
#include <limits>
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/events/scoped_event_queue.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
@@ -53,6 +52,7 @@
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/input_type_names.h"
#include "third_party/blink/renderer/core/layout/layout_slider.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
namespace blink {
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 6ce6d125af6..6ed61189f83 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
@@ -83,8 +83,12 @@ ListPicker.prototype._handleWindowMessage = function(event) {
this._config.anchorRectInScreen.y !== window.updateData.anchorRectInScreen.y ||
this._config.anchorRectInScreen.width !== window.updateData.anchorRectInScreen.width ||
this._config.anchorRectInScreen.height !== window.updateData.anchorRectInScreen.height) {
- this._config.anchorRectInScreen = window.updateData.anchorRectInScreen;
- this._fixWindowSize();
+ // 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/search_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/search_input_type.cc
index a14a67b7dce..76c81677b59 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/search_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/search_input_type.cc
@@ -31,7 +31,6 @@
#include "third_party/blink/renderer/core/html/forms/search_input_type.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
#include "third_party/blink/renderer/core/frame/web_feature.h"
@@ -41,6 +40,7 @@
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/input_type_names.h"
#include "third_party/blink/renderer/core/layout/layout_search_field.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -115,9 +115,11 @@ void SearchInputType::StartSearchEventTimer() {
return;
}
- // After typing the first key, we wait 0.5 seconds.
- // After the second key, 0.4 seconds, then 0.3, then 0.2 from then on.
- search_event_timer_.StartOneShot(max(0.2, 0.6 - 0.1 * length), FROM_HERE);
+ // After typing the first key, we wait 500ms.
+ // After the second key, 400ms, then 300, then 200 from then on.
+ unsigned step = std::min(length, 4u) - 1;
+ TimeDelta timeout = TimeDelta::FromMilliseconds(500 - 100 * step);
+ search_event_timer_.StartOneShot(timeout, FROM_HERE);
}
void SearchInputType::DispatchSearchEvent() {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/slider_thumb_element.cc b/chromium/third_party/blink/renderer/core/html/forms/slider_thumb_element.cc
index 1589e93e454..4e1399fa545 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/slider_thumb_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/slider_thumb_element.cc
@@ -44,6 +44,7 @@
#include "third_party/blink/renderer/core/html/shadow/shadow_element_names.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
+#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
#include "third_party/blink/renderer/core/layout/layout_slider_container.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
@@ -75,8 +76,9 @@ void SliderThumbElement::SetPositionFromValue() {
LayoutInvalidationReason::kSliderValueChanged);
}
-LayoutObject* SliderThumbElement::CreateLayoutObject(const ComputedStyle&) {
- return new LayoutBlockFlow(this);
+LayoutObject* SliderThumbElement::CreateLayoutObject(
+ const ComputedStyle& style) {
+ return LayoutObjectFactory::CreateBlockFlow(*this, style);
}
bool SliderThumbElement::IsDisabledFormControl() const {
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 88dc9b64e12..3f0f6190721 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
@@ -36,6 +36,8 @@ namespace blink {
class CORE_EXPORT SpinButtonElement final : public HTMLDivElement,
public PopupOpeningObserver {
+ USING_GARBAGE_COLLECTED_MIXIN(SpinButtonElement);
+
public:
enum UpDownState {
kIndeterminate, // Hovered, but the event is not handled.
diff --git a/chromium/third_party/blink/renderer/core/html/forms/step_range.h b/chromium/third_party/blink/renderer/core/html/forms/step_range.h
index b3177715881..9bd9daad946 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/step_range.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/step_range.h
@@ -22,8 +22,8 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_STEP_RANGE_H_
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/decimal.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/decimal.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/html/forms/submit_input_type.cc b/chromium/third_party/blink/renderer/core/html/forms/submit_input_type.cc
index d4d0a48280a..1391ae8173b 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/submit_input_type.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/submit_input_type.cc
@@ -51,9 +51,10 @@ const AtomicString& SubmitInputType::FormControlType() const {
}
void SubmitInputType::AppendToFormData(FormData& form_data) const {
- if (GetElement().IsActivatedSubmit())
- form_data.append(GetElement().GetName(),
- GetElement().ValueOrDefaultLabel());
+ if (GetElement().IsActivatedSubmit()) {
+ form_data.AppendFromElement(GetElement().GetName(),
+ GetElement().ValueOrDefaultLabel());
+ }
}
bool SubmitInputType::SupportsRequired() const {
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 18d2d34d9d1..950f28468c2 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
@@ -24,9 +24,7 @@
#include "third_party/blink/renderer/core/html/forms/text_control_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
@@ -56,6 +54,8 @@
#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/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -67,6 +67,7 @@ TextControlElement::TextControlElement(const QualifiedName& tag_name,
Document& doc)
: HTMLFormControlElementWithState(tag_name, doc),
last_change_was_user_edit_(false),
+ user_has_edited_the_field_(false),
cached_selection_start_(0),
cached_selection_end_(0) {
cached_selection_direction_ =
@@ -106,6 +107,7 @@ void TextControlElement::DefaultEventHandler(Event* event) {
if (event->type() == EventTypeNames::webkitEditableContentChanged &&
GetLayoutObject() && GetLayoutObject()->IsTextControl()) {
last_change_was_user_edit_ = !GetDocument().IsRunningExecCommand();
+ user_has_edited_the_field_ |= last_change_was_user_edit_;
if (IsFocused()) {
// Updating the cache in SelectionChanged() isn't enough because
@@ -280,9 +282,10 @@ void TextControlElement::setRangeText(const String& replacement,
ExceptionState& exception_state) {
if (start > end) {
exception_state.ThrowDOMException(
- kIndexSizeError, "The provided start value (" + String::Number(start) +
- ") is larger than the provided end value (" +
- String::Number(end) + ").");
+ DOMExceptionCode::kIndexSizeError,
+ "The provided start value (" + String::Number(start) +
+ ") is larger than the provided end value (" + String::Number(end) +
+ ").");
return;
}
if (OpenShadowRoot())
@@ -675,13 +678,15 @@ void TextControlElement::setMaxLength(int new_value,
ExceptionState& exception_state) {
int min = minLength();
if (new_value < 0) {
- exception_state.ThrowDOMException(
- kIndexSizeError, "The value provided (" + String::Number(new_value) +
- ") is not positive or 0.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kIndexSizeError,
+ "The value provided (" +
+ String::Number(new_value) +
+ ") is not positive or 0.");
} else if (min >= 0 && new_value < min) {
exception_state.ThrowDOMException(
- kIndexSizeError, ExceptionMessages::IndexExceedsMinimumBound(
- "maxLength", new_value, min));
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexExceedsMinimumBound("maxLength", new_value,
+ min));
} else {
SetIntegralAttribute(maxlengthAttr, new_value);
}
@@ -691,13 +696,15 @@ void TextControlElement::setMinLength(int new_value,
ExceptionState& exception_state) {
int max = maxLength();
if (new_value < 0) {
- exception_state.ThrowDOMException(
- kIndexSizeError, "The value provided (" + String::Number(new_value) +
- ") is not positive or 0.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kIndexSizeError,
+ "The value provided (" +
+ String::Number(new_value) +
+ ") is not positive or 0.");
} else if (max >= 0 && new_value > max) {
exception_state.ThrowDOMException(
- kIndexSizeError, ExceptionMessages::IndexExceedsMaximumBound(
- "minLength", new_value, max));
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexExceedsMaximumBound("minLength", new_value,
+ max));
} else {
SetIntegralAttribute(minlengthAttr, new_value);
}
@@ -745,6 +752,12 @@ void TextControlElement::ParseAttribute(
}
}
+bool TextControlElement::UserHasEditedTheField() const {
+ if (!IsTextControl())
+ return false;
+ return user_has_edited_the_field_;
+}
+
bool TextControlElement::LastChangeWasUserEdit() const {
if (!IsTextControl())
return false;
@@ -999,6 +1012,7 @@ void TextControlElement::CloneNonAttributePropertiesFrom(
const TextControlElement& source_element =
static_cast<const TextControlElement&>(source);
last_change_was_user_edit_ = source_element.last_change_was_user_edit_;
+ user_has_edited_the_field_ = source_element.user_has_edited_the_field_;
HTMLFormControlElement::CloneNonAttributePropertiesFrom(source, flag);
}
diff --git a/chromium/third_party/blink/renderer/core/html/forms/text_control_element.h b/chromium/third_party/blink/renderer/core/html/forms/text_control_element.h
index 68d679010cf..e479e520253 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/text_control_element.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/text_control_element.h
@@ -134,7 +134,10 @@ class CORE_EXPORT TextControlElement : public HTMLFormControlElementWithState {
void DropInnerEditorElement() { inner_editor_ = nullptr; }
void SelectionChanged(bool user_triggered);
+ bool UserHasEditedTheField() const;
bool LastChangeWasUserEdit() const;
+ // This is only used in tests, to fake the user's action
+ void SetUserHasEditedTheFieldForTest() { user_has_edited_the_field_ = true; }
virtual void SetInnerEditorValue(const String&);
String InnerEditorValue() const;
Node* CreatePlaceholderBreakElement() const;
@@ -218,6 +221,7 @@ class CORE_EXPORT TextControlElement : public HTMLFormControlElementWithState {
// zero-length String is a valid data.
String value_before_first_user_edit_;
bool last_change_was_user_edit_;
+ bool user_has_edited_the_field_;
unsigned cached_selection_start_;
unsigned cached_selection_end_;
diff --git a/chromium/third_party/blink/renderer/core/html/forms/text_control_element_test.cc b/chromium/third_party/blink/renderer/core/html/forms/text_control_element_test.cc
index 8b2b775a943..cf430c80937 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/text_control_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/forms/text_control_element_test.cc
@@ -8,6 +8,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.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/frame/local_frame_view.h"
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 9fd9e6a220d..5c59d0917ed 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
@@ -252,7 +252,7 @@ void SearchFieldCancelButtonElement::DefaultEventHandler(Event* event) {
ToMouseEvent(event)->button() ==
static_cast<short>(WebPointerProperties::Button::kLeft)) {
input->SetValueForUser("");
- input->SetAutofilled(false);
+ input->SetAutofillState(WebAutofillState::kNotFilled);
input->OnSearch();
event->SetDefaultHandled();
}
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 e48cbb46bd4..430db9f5a54 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
@@ -31,8 +31,8 @@
#include "third_party/blink/renderer/core/html/forms/text_field_input_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/style_change_reason.h"
+#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/events/before_text_inserted_event.h"
@@ -50,7 +50,8 @@
#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/paint/paint_layer.h"
-#include "third_party/blink/renderer/platform/event_dispatch_forbidden_scope.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/wtf/text/wtf_string.h"
namespace blink {
@@ -129,7 +130,7 @@ SpinButtonElement* TextFieldInputType::GetSpinButtonElement() const {
ShadowElementNames::SpinButton()));
}
-bool TextFieldInputType::ShouldShowFocusRingOnMouseFocus() const {
+bool TextFieldInputType::MayTriggerVirtualKeyboard() const {
return true;
}
@@ -494,8 +495,10 @@ void TextFieldInputType::AppendToFormData(FormData& form_data) const {
InputType::AppendToFormData(form_data);
const AtomicString& dirname_attr_value =
GetElement().FastGetAttribute(dirnameAttr);
- if (!dirname_attr_value.IsNull())
- form_data.append(dirname_attr_value, GetElement().DirectionForFormData());
+ if (!dirname_attr_value.IsNull()) {
+ form_data.AppendFromElement(dirname_attr_value,
+ GetElement().DirectionForFormData());
+ }
}
String TextFieldInputType::ConvertFromVisibleValue(
diff --git a/chromium/third_party/blink/renderer/core/html/forms/text_field_input_type.h b/chromium/third_party/blink/renderer/core/html/forms/text_field_input_type.h
index 909b56b20e1..9fd8ca56c72 100644
--- a/chromium/third_party/blink/renderer/core/html/forms/text_field_input_type.h
+++ b/chromium/third_party/blink/renderer/core/html/forms/text_field_input_type.h
@@ -80,7 +80,7 @@ class TextFieldInputType : public InputType,
private:
InputTypeView* CreateView() override;
ValueMode GetValueMode() const override;
- bool ShouldShowFocusRingOnMouseFocus() const final;
+ bool MayTriggerVirtualKeyboard() const final;
bool IsTextField() const final;
bool ValueMissing(const String&) const override;
void HandleBeforeTextInsertedEvent(BeforeTextInsertedEvent*) override;
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 91dd3986024..4862942b40a 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
@@ -32,10 +32,12 @@
#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/use_counter.h"
+#include "third_party/blink/renderer/core/html/anchor_element_metrics.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/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"
#include "third_party/blink/renderer/core/loader/ping_loader.h"
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/page.h"
@@ -73,7 +75,8 @@ bool HTMLAnchorElement::MatchesEnabledPseudoClass() const {
}
bool HTMLAnchorElement::ShouldHaveFocusAppearance() const {
- return !WasFocusedByMouse() || HTMLElement::SupportsFocus();
+ return (GetDocument().LastFocusType() != kWebFocusTypeMouse) ||
+ HTMLElement::SupportsFocus();
}
bool HTMLAnchorElement::IsMouseFocusable() const {
@@ -330,6 +333,8 @@ void HTMLAnchorElement::HandleClick(Event* event) {
WebFeature::kAnchorClickDispatchForNonConnectedNode);
}
+ AnchorElementMetrics::MaybeExtractMetricsClicked(this);
+
StringBuilder url;
url.Append(StripLeadingAndTrailingHTMLSpaces(FastGetAttribute(hrefAttr)));
AppendServerMapMousePosition(url, event);
@@ -340,10 +345,6 @@ void HTMLAnchorElement::HandleClick(Event* event) {
SendPings(completed_url);
ResourceRequest request(completed_url);
- request.SetUIStartTime(
- (event->PlatformTimeStamp() - TimeTicks()).InSecondsF());
- request.SetInputPerfMetricReportPolicy(
- InputToLoadPerfMetricReportPolicy::kReportLink);
ReferrerPolicy policy;
if (hasAttribute(referrerpolicyAttr) &&
@@ -367,30 +368,35 @@ void HTMLAnchorElement::HandleClick(Event* event) {
: WebFeature::
kHTMLAnchorElementDownloadInSandboxWithoutUserGesture);
}
- // TODO(jochen): Only set the suggested filename for URLs we can request.
- request.SetSuggestedFilename(
- static_cast<String>(FastGetAttribute(downloadAttr)));
- if (GetDocument().GetSecurityOrigin()->CanReadContent(completed_url)) {
- // TODO(jochen): Handle cross origin server redirects.
+ // Ignore the download attribute if we either can't read the content, or
+ // the event is an alt-click or similar.
+ if (NavigationPolicyFromEvent(event) != kNavigationPolicyDownload &&
+ GetDocument().GetSecurityOrigin()->CanReadContent(completed_url)) {
+ request.SetSuggestedFilename(
+ static_cast<String>(FastGetAttribute(downloadAttr)));
request.SetRequestContext(WebURLRequest::kRequestContextDownload);
request.SetRequestorOrigin(SecurityOrigin::Create(GetDocument().Url()));
- frame->Client()->DownloadURL(request);
+ frame->Client()->DownloadURL(request,
+ DownloadCrossOriginRedirects::kNavigate);
return;
}
}
request.SetRequestContext(WebURLRequest::kRequestContextHyperlink);
FrameLoadRequest frame_request(&GetDocument(), request,
getAttribute(targetAttr));
- frame_request.SetTriggeringEvent(event);
if (HasRel(kRelationNoReferrer)) {
frame_request.SetShouldSendReferrer(kNeverSendReferrer);
frame_request.SetShouldSetOpener(kNeverSetOpener);
}
if (HasRel(kRelationNoOpener))
frame_request.SetShouldSetOpener(kNeverSetOpener);
+ frame_request.SetTriggeringEventInfo(
+ event->isTrusted() ? WebTriggeringEventInfo::kFromTrustedEvent
+ : WebTriggeringEventInfo::kFromUntrustedEvent);
// TODO(japhet): Link clicks can be emulated via JS without a user gesture.
// Why doesn't this go through NavigationScheduler?
- frame->Loader().StartNavigation(frame_request);
+ frame->Loader().StartNavigation(frame_request, WebFrameLoadType::kStandard,
+ NavigationPolicyFromEvent(event));
}
bool IsEnterKeyKeydownEvent(Event* event) {
@@ -432,9 +438,4 @@ void HTMLAnchorElement::Trace(blink::Visitor* visitor) {
HTMLElement::Trace(visitor);
}
-void HTMLAnchorElement::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(rel_list_);
- HTMLElement::TraceWrappers(visitor);
-}
-
} // namespace blink
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 a03d11f5c20..46fa061558f 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
@@ -93,7 +93,6 @@ class CORE_EXPORT HTMLAnchorElement : public HTMLElement, public DOMURLUtils {
void SendPings(const KURL& destination_url) const;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
protected:
HTMLAnchorElement(const QualifiedName&, Document&);
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 d7d223e5518..7e379723313 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
@@ -96,6 +96,7 @@
"http-equiv",
"id",
"imgsizes",
+ "importance",
"incremental",
"inert",
"inputmode",
diff --git a/chromium/third_party/blink/renderer/core/html/html_base_element.cc b/chromium/third_party/blink/renderer/core/html/html_base_element.cc
index 0aa59e87658..ffc67f05147 100644
--- a/chromium/third_party/blink/renderer/core/html/html_base_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_base_element.cc
@@ -22,11 +22,13 @@
#include "third_party/blink/renderer/core/html/html_base_element.h"
+#include "third_party/blink/renderer/bindings/core/v8/usv_string_or_trusted_url.h"
#include "third_party/blink/renderer/core/dom/attribute.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_url.h"
namespace blink {
@@ -64,6 +66,10 @@ bool HTMLBaseElement::IsURLAttribute(const Attribute& attribute) const {
HTMLElement::IsURLAttribute(attribute);
}
+void HTMLBaseElement::href(USVStringOrTrustedURL& result) const {
+ result.SetUSVString(href());
+}
+
KURL HTMLBaseElement::href() const {
// This does not use the GetURLAttribute function because that will resolve
// relative to the document's base URL; base elements like this one can be
@@ -88,7 +94,22 @@ KURL HTMLBaseElement::href() const {
return url;
}
-void HTMLBaseElement::setHref(const AtomicString& value) {
+void HTMLBaseElement::setHref(const USVStringOrTrustedURL& stringOrUrl,
+ ExceptionState& exception_state) {
+ DCHECK(stringOrUrl.IsUSVString() ||
+ RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
+ DCHECK(!stringOrUrl.IsNull());
+
+ if (stringOrUrl.IsUSVString() && GetDocument().RequireTrustedTypes()) {
+ exception_state.ThrowTypeError(
+ "This document requires `TrustedURL` assignment.");
+ return;
+ }
+
+ AtomicString value(stringOrUrl.IsUSVString()
+ ? stringOrUrl.GetAsUSVString()
+ : stringOrUrl.GetAsTrustedURL()->toString());
+
setAttribute(hrefAttr, value);
}
diff --git a/chromium/third_party/blink/renderer/core/html/html_base_element.h b/chromium/third_party/blink/renderer/core/html/html_base_element.h
index 53268ac72d7..e05135dbeed 100644
--- a/chromium/third_party/blink/renderer/core/html/html_base_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_base_element.h
@@ -27,6 +27,9 @@
namespace blink {
+class ExceptionState;
+class USVStringOrTrustedURL;
+
class HTMLBaseElement final : public HTMLElement {
DEFINE_WRAPPERTYPEINFO();
@@ -34,7 +37,8 @@ class HTMLBaseElement final : public HTMLElement {
DECLARE_NODE_FACTORY(HTMLBaseElement);
KURL href() const;
- void setHref(const AtomicString&);
+ void href(USVStringOrTrustedURL&) const;
+ void setHref(const USVStringOrTrustedURL&, ExceptionState&);
private:
explicit HTMLBaseElement(Document&);
diff --git a/chromium/third_party/blink/renderer/core/html/html_base_element.idl b/chromium/third_party/blink/renderer/core/html/html_base_element.idl
index 82178cc4132..d6152128d97 100644
--- a/chromium/third_party/blink/renderer/core/html/html_base_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_base_element.idl
@@ -20,6 +20,6 @@
// https://html.spec.whatwg.org/#the-base-element
[HTMLConstructor]
interface HTMLBaseElement : HTMLElement {
- [CEReactions] attribute USVString href;
+ [CEReactions, RaisesException=Setter] attribute URLString href;
[CEReactions, Reflect] attribute DOMString target;
};
diff --git a/chromium/third_party/blink/renderer/core/html/html_collection.cc b/chromium/third_party/blink/renderer/core/html/html_collection.cc
index d8b5ef40c95..91f3891a194 100644
--- a/chromium/third_party/blink/renderer/core/html/html_collection.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_collection.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/core/dom/class_collection.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
+#include "third_party/blink/renderer/core/dom/node_child_removal_tracker.h"
#include "third_party/blink/renderer/core/dom/node_rare_data.h"
#include "third_party/blink/renderer/core/html/document_all_name_collection.h"
#include "third_party/blink/renderer/core/html/document_name_collection.h"
@@ -207,7 +208,12 @@ unsigned HTMLCollection::length() const {
}
Element* HTMLCollection::item(unsigned offset) const {
- return collection_items_cache_.NodeAt(*this, offset);
+ Element* element = collection_items_cache_.NodeAt(*this, offset);
+ if (element && element->GetDocument().InDOMNodeRemovedHandler()) {
+ if (NodeChildRemovalTracker::IsBeingRemoved(element))
+ GetDocument().CountDetachingNodeAccessInDOMNodeRemovedHandler();
+ }
+ return element;
}
static inline bool IsMatchingHTMLElement(const HTMLCollection& html_collection,
diff --git a/chromium/third_party/blink/renderer/core/html/html_details_element.cc b/chromium/third_party/blink/renderer/core/html/html_details_element.cc
index c001bd84d08..5f229ac5dc1 100644
--- a/chromium/third_party/blink/renderer/core/html/html_details_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_details_element.cc
@@ -21,7 +21,6 @@
#include "third_party/blink/renderer/core/html/html_details_element.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css_property_names.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
@@ -36,6 +35,8 @@
#include "third_party/blink/renderer/core/html/shadow/shadow_element_names.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
+#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
namespace blink {
@@ -69,8 +70,9 @@ void HTMLDetailsElement::DispatchPendingEvent() {
DispatchEvent(Event::Create(EventTypeNames::toggle));
}
-LayoutObject* HTMLDetailsElement::CreateLayoutObject(const ComputedStyle&) {
- return new LayoutBlockFlow(this);
+LayoutObject* HTMLDetailsElement::CreateLayoutObject(
+ const ComputedStyle& style) {
+ return LayoutObjectFactory::CreateBlockFlow(*this, style);
}
void HTMLDetailsElement::DidAddUserAgentShadowRoot(ShadowRoot& root) {
diff --git a/chromium/third_party/blink/renderer/core/html/html_details_element.h b/chromium/third_party/blink/renderer/core/html/html_details_element.h
index 3f602bb9487..35bf6574652 100644
--- a/chromium/third_party/blink/renderer/core/html/html_details_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_details_element.h
@@ -45,7 +45,6 @@ class HTMLDetailsElement final : public HTMLElement {
void DispatchPendingEvent();
LayoutObject* CreateLayoutObject(const ComputedStyle&) override;
- bool ShouldForceLegacyLayout() const final { return true; }
void ParseAttribute(const AttributeModificationParams&) override;
void DidAddUserAgentShadowRoot(ShadowRoot&) override;
bool IsInteractiveContent() const override;
diff --git a/chromium/third_party/blink/renderer/core/html/html_dialog_element.cc b/chromium/third_party/blink/renderer/core/html/html_dialog_element.cc
index d7ea8af28c4..a4edfeaa209 100644
--- a/chromium/third_party/blink/renderer/core/html/html_dialog_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_dialog_element.cc
@@ -25,16 +25,15 @@
#include "third_party/blink/renderer/core/html/html_dialog_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
#include "third_party/blink/renderer/core/html/forms/html_form_control_element.h"
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -151,14 +150,14 @@ void HTMLDialogElement::show() {
void HTMLDialogElement::showModal(ExceptionState& exception_state) {
if (FastHasAttribute(openAttr)) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The element already has an 'open' "
"attribute, and therefore cannot be "
"opened modally.");
return;
}
if (!isConnected()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The element is not in a Document.");
return;
}
diff --git a/chromium/third_party/blink/renderer/core/html/html_document.cc b/chromium/third_party/blink/renderer/core/html/html_document.cc
index 028badd919f..ab5c2a619a3 100644
--- a/chromium/third_party/blink/renderer/core/html/html_document.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_document.cc
@@ -55,6 +55,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/window_proxy.h"
+#include "third_party/blink/renderer/core/dom/document_init.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html_names.h"
@@ -72,6 +73,14 @@ HTMLDocument::HTMLDocument(const DocumentInit& initializer,
}
}
+HTMLDocument* HTMLDocument::Create(const DocumentInit& initializer) {
+ return new HTMLDocument(initializer);
+}
+
+HTMLDocument* HTMLDocument::CreateForTest() {
+ return new HTMLDocument(DocumentInit::Create());
+}
+
HTMLDocument::~HTMLDocument() = default;
Document* HTMLDocument::CloneDocumentWithoutChildren() const {
diff --git a/chromium/third_party/blink/renderer/core/html/html_document.h b/chromium/third_party/blink/renderer/core/html/html_document.h
index 641233a3c59..5db2931a7a5 100644
--- a/chromium/third_party/blink/renderer/core/html/html_document.h
+++ b/chromium/third_party/blink/renderer/core/html/html_document.h
@@ -33,12 +33,8 @@ class CORE_EXPORT HTMLDocument : public Document {
DEFINE_WRAPPERTYPEINFO();
public:
- static HTMLDocument* Create(const DocumentInit& initializer) {
- return new HTMLDocument(initializer);
- }
- static HTMLDocument* CreateForTest() {
- return new HTMLDocument(DocumentInit::Create());
- }
+ static HTMLDocument* Create(const DocumentInit& initializer);
+ static HTMLDocument* CreateForTest();
~HTMLDocument() override;
void AddNamedItem(const AtomicString& name);
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 d405eed4ac2..2b4aea46f74 100644
--- a/chromium/third_party/blink/renderer/core/html/html_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_element.cc
@@ -25,7 +25,6 @@
#include "third_party/blink/renderer/core/html/html_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_event_listener.h"
#include "third_party/blink/renderer/core/css/css_color_value.h"
#include "third_party/blink/renderer/core/css/css_markup.h"
@@ -36,7 +35,6 @@
#include "third_party/blink/renderer/core/dom/document_fragment.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
@@ -65,6 +63,7 @@
#include "third_party/blink/renderer/core/page/spatial_navigation.h"
#include "third_party/blink/renderer/core/svg/svg_svg_element.h"
#include "third_party/blink/renderer/core/xml_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/language.h"
#include "third_party/blink/renderer/platform/text/bidi_resolver.h"
#include "third_party/blink/renderer/platform/text/bidi_text_run.h"
@@ -257,7 +256,7 @@ void HTMLElement::CollectStyleForPresentationAttribute(
if (value.IsEmpty() || DeprecatedEqualIgnoringCase(value, "true")) {
AddPropertyToPresentationAttributeStyle(
style, CSSPropertyWebkitUserModify, CSSValueReadWrite);
- AddPropertyToPresentationAttributeStyle(style, CSSPropertyWordWrap,
+ AddPropertyToPresentationAttributeStyle(style, CSSPropertyOverflowWrap,
CSSValueBreakWord);
AddPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitLineBreak,
CSSValueAfterWhiteSpace);
@@ -269,7 +268,7 @@ void HTMLElement::CollectStyleForPresentationAttribute(
} else if (DeprecatedEqualIgnoringCase(value, "plaintext-only")) {
AddPropertyToPresentationAttributeStyle(
style, CSSPropertyWebkitUserModify, CSSValueReadWritePlaintextOnly);
- AddPropertyToPresentationAttributeStyle(style, CSSPropertyWordWrap,
+ AddPropertyToPresentationAttributeStyle(style, CSSPropertyOverflowWrap,
CSSValueBreakWord);
AddPropertyToPresentationAttributeStyle(style, CSSPropertyWebkitLineBreak,
CSSValueAfterWhiteSpace);
@@ -686,8 +685,9 @@ void HTMLElement::setOuterText(const String& text,
ExceptionState& exception_state) {
ContainerNode* parent = parentNode();
if (!parent) {
- exception_state.ThrowDOMException(kNoModificationAllowedError,
- "The element has no parent.");
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNoModificationAllowedError,
+ "The element has no parent.");
return;
}
@@ -703,7 +703,7 @@ void HTMLElement::setOuterText(const String& text,
// textToFragment might cause mutation events.
if (!parentNode())
- exception_state.ThrowDOMException(kHierarchyRequestError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kHierarchyRequestError,
"The element has no parent.");
if (exception_state.HadException())
@@ -788,7 +788,7 @@ void HTMLElement::setContentEditable(const String& enabled,
else if (DeprecatedEqualIgnoringCase(enabled, "inherit"))
removeAttribute(contenteditableAttr);
else
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"The value provided ('" + enabled +
"') is not one of 'true', 'false', "
"'plaintext-only', or 'inherit'.");
diff --git a/chromium/third_party/blink/renderer/core/html/html_embed_element.idl b/chromium/third_party/blink/renderer/core/html/html_embed_element.idl
index 020794f0654..fc16063a060 100644
--- a/chromium/third_party/blink/renderer/core/html/html_embed_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_embed_element.idl
@@ -20,13 +20,17 @@
// https://html.spec.whatwg.org/#the-embed-element
+// The `ScriptURLString` reference below is from Trusted Types:
+// https://github.com/WICG/trusted-types/, which is still WIP.
+// https://crbug.com/739170.
+
// TODO(yukishiino): HTMLEmbedElement should not have [OverrideBuiltins].
[
OverrideBuiltins,
ActiveScriptWrappable,
HTMLConstructor
] interface HTMLEmbedElement : HTMLElement {
- [CEReactions, Reflect, URL] attribute DOMString src;
+ [CEReactions, Reflect, URL, RaisesException=Setter] attribute ScriptURLString src;
[CEReactions, Reflect] attribute DOMString type;
[CEReactions, Reflect] attribute DOMString width;
[CEReactions, Reflect] attribute DOMString height;
diff --git a/chromium/third_party/blink/renderer/core/html/html_frame_element.idl b/chromium/third_party/blink/renderer/core/html/html_frame_element.idl
index 6b1773a0e1f..0950629ffa0 100644
--- a/chromium/third_party/blink/renderer/core/html/html_frame_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_frame_element.idl
@@ -19,11 +19,15 @@
*/
// https://html.spec.whatwg.org/#htmlframeelement
+
+// The `URLString` reference below is from Trusted Types:
+// https://github.com/WICG/trusted-types/, which is still WIP.
+// https://crbug.com/739170.
[HTMLConstructor]
interface HTMLFrameElement : HTMLElement {
[CEReactions, Reflect] attribute DOMString name;
[CEReactions, Reflect] attribute DOMString scrolling;
- [CEReactions, Reflect, URL] attribute USVString src;
+ [CEReactions, Reflect, URL, RaisesException=Setter] attribute URLString src;
[CEReactions, Reflect] attribute DOMString frameBorder;
[CEReactions, Reflect, URL] attribute USVString longDesc;
[CEReactions, Reflect] attribute boolean noResize;
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 3ec1385c743..e770805c114 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
@@ -168,7 +168,7 @@ scoped_refptr<const SecurityOrigin>
HTMLFrameElementBase::GetOriginForFeaturePolicy() const {
// Sandboxed frames have a unique origin.
if (GetSandboxFlags() & kSandboxOrigin)
- return SecurityOrigin::CreateUnique();
+ 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_owner_element.cc b/chromium/third_party/blink/renderer/core/html/html_frame_owner_element.cc
index d6a16ac7cad..645cbeef2cb 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
@@ -20,33 +20,27 @@
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
-#include <limits>
-
#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.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/remote_frame_view.h"
-#include "third_party/blink/renderer/core/geometry/dom_rect_read_only.h"
-#include "third_party/blink/renderer/core/intersection_observer/intersection_observer.h"
-#include "third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h"
+#include "third_party/blink/renderer/core/html/lazy_load_frame_observer.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.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/loader/frame_loader.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/paint/paint_layer.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/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
-#include "third_party/blink/renderer/platform/length.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -74,27 +68,6 @@ bool DoesParentAllowLazyLoadingChildren(Document& document) {
return containing_frame_owner->ShouldLazyLoadChildren();
}
-// Determine if the |bounding_client_rect| for a frame indicates that the frame
-// is probably hidden according to some experimental heuristics. Since hidden
-// frames are often used for analytics or communication, and lazily loading them
-// could break their functionality, so these heuristics are used to recognize
-// likely hidden frames and immediately load them so that they can function
-// properly.
-bool IsFrameProbablyHidden(const DOMRectReadOnly& bounding_client_rect) {
- // Tiny frames that are 4x4 or smaller are likely not intended to be seen by
- // the user. Note that this condition includes frames marked as
- // "display:none", since those frames would have dimensions of 0x0.
- if (bounding_client_rect.width() < 4.1 || bounding_client_rect.height() < 4.1)
- return true;
-
- // Frames that are positioned completely off the page above or to the left are
- // likely never intended to be visible to the user.
- if (bounding_client_rect.right() < 0.0 || bounding_client_rect.bottom() < 0.0)
- return true;
-
- return false;
-}
-
} // namespace
SubframeLoadingDisabler::SubtreeRootSet&
@@ -144,10 +117,17 @@ void HTMLFrameOwnerElement::SetContentFrame(Frame& frame) {
// There should be no lazy load in progress since before SetContentFrame,
// |this| frame element should have been disconnected.
- DCHECK(!lazy_load_intersection_observer_);
+ DCHECK(!lazy_load_frame_observer_ ||
+ !lazy_load_frame_observer_->IsLazyLoadPending());
content_frame_ = &frame;
+ // Invalidate compositing inputs, because a remote frame child can cause the
+ // owner to become composited.
+ if (auto* box = GetLayoutBox()) {
+ if (auto* layer = box->Layer())
+ layer->SetNeedsCompositingInputsUpdate();
+ }
SetNeedsStyleRecalc(kLocalStyleChange, StyleChangeReasonForTracing::Create(
StyleChangeReason::kFrame));
@@ -182,14 +162,13 @@ void HTMLFrameOwnerElement::DisconnectContentFrame() {
// Removing a subframe that was still loading can impact the result of
// AllDescendantsAreComplete that is consulted by Document::ShouldComplete.
- // Therefore we might need to re-check this after removing the subframe. The
+ // Therefore we might need to re-check this after removing the subframe. The
// re-check is not needed for local frames (which will handle re-checking from
// FrameLoader::DidFinishNavigation that responds to LocalFrame::Detach).
// OTOH, re-checking is required for OOPIFs - see https://crbug.com/779433.
Document& parent_doc = GetDocument();
- bool have_to_check_if_parent_is_completed = !parent_doc.IsLoadCompleted() &&
- ContentFrame()->IsRemoteFrame() &&
- ContentFrame()->IsLoading();
+ bool have_to_check_if_parent_is_completed =
+ ContentFrame()->IsRemoteFrame() && ContentFrame()->IsLoading();
// FIXME: Currently we don't do this in removedFrom because this causes an
// unload event in the subframe which could execute script that could then
@@ -270,6 +249,9 @@ void HTMLFrameOwnerElement::AddResourceTiming(const ResourceTimingInfo& info) {
}
void HTMLFrameOwnerElement::DispatchLoad() {
+ if (lazy_load_frame_observer_)
+ lazy_load_frame_observer_->RecordMetricsOnLoadFinished();
+
DispatchScopedEvent(Event::Create(EventTypeNames::load));
}
@@ -359,8 +341,8 @@ bool HTMLFrameOwnerElement::LoadOrRedirectSubframe(
if (ContentFrame()) {
// TODO(sclittle): Support lazily loading frame navigations.
- ContentFrame()->Navigate(GetDocument(), url, replace_current_item,
- UserGestureStatus::kNone);
+ ContentFrame()->ScheduleNavigation(GetDocument(), url, replace_current_item,
+ UserGestureStatus::kNone);
return true;
}
@@ -384,11 +366,11 @@ bool HTMLFrameOwnerElement::LoadOrRedirectSubframe(
policy, url, GetDocument().OutgoingReferrer()));
}
- FrameLoadType child_load_type = kFrameLoadTypeInitialInChildFrame;
+ WebFrameLoadType child_load_type = WebFrameLoadType::kReplaceCurrentItem;
if (!GetDocument().LoadEventFinished() &&
GetDocument().Loader()->LoadType() ==
- kFrameLoadTypeReloadBypassingCache) {
- child_load_type = kFrameLoadTypeReloadBypassingCache;
+ WebFrameLoadType::kReloadBypassingCache) {
+ child_load_type = WebFrameLoadType::kReloadBypassingCache;
request.SetCacheMode(mojom::FetchCacheMode::kBypassCache);
}
@@ -399,7 +381,8 @@ bool HTMLFrameOwnerElement::LoadOrRedirectSubframe(
if (IsPlugin())
request.SetSkipServiceWorker(true);
- if (RuntimeEnabledFeatures::LazyFrameLoadingEnabled() &&
+ if ((RuntimeEnabledFeatures::LazyFrameLoadingEnabled() ||
+ RuntimeEnabledFeatures::LazyFrameVisibleLoadTimeMetricsEnabled()) &&
should_lazy_load_children_ &&
// Only http:// or https:// URLs are eligible for lazy loading, excluding
// URLs like invalid or empty URLs, "about:blank", local file URLs, etc.
@@ -418,50 +401,29 @@ bool HTMLFrameOwnerElement::LoadOrRedirectSubframe(
// the viewport or visible.
should_lazy_load_children_ = false;
- lazy_load_intersection_observer_ = IntersectionObserver::Create(
- {Length(kLazyLoadRootMarginPx, kFixed)},
- {std::numeric_limits<float>::min()}, &GetDocument(),
- WTF::BindRepeating(&HTMLFrameOwnerElement::LoadIfHiddenOrNearViewport,
- WrapWeakPersistent(this), request, child_load_type));
+ DCHECK(!lazy_load_frame_observer_);
+ lazy_load_frame_observer_ = new LazyLoadFrameObserver(*this);
- lazy_load_intersection_observer_->observe(this);
- } else {
- child_frame->Loader().StartNavigation(
- FrameLoadRequest(&GetDocument(), request), child_load_type);
- }
- return true;
-}
-
-void HTMLFrameOwnerElement::LoadIfHiddenOrNearViewport(
- const ResourceRequest& resource_request,
- FrameLoadType frame_load_type,
- const HeapVector<Member<IntersectionObserverEntry>>& entries) {
- DCHECK(!entries.IsEmpty());
- DCHECK_EQ(this, entries.back()->target());
+ if (RuntimeEnabledFeatures::LazyFrameVisibleLoadTimeMetricsEnabled())
+ lazy_load_frame_observer_->StartTrackingVisibilityMetrics();
- if (!entries.back()->isIntersecting() &&
- !IsFrameProbablyHidden(*entries.back()->boundingClientRect())) {
- return;
+ if (RuntimeEnabledFeatures::LazyFrameLoadingEnabled()) {
+ lazy_load_frame_observer_->DeferLoadUntilNearViewport(request,
+ child_load_type);
+ return true;
+ }
}
- // The content frame of this element should not have changed, since any
- // pending lazy load should have been already been cancelled in
- // DisconnectContentFrame() if the content frame changes.
- DCHECK(ContentFrame());
-
- // Note that calling FrameLoader::Load() causes this intersection observer to
- // be disconnected.
- ToLocalFrame(ContentFrame())
- ->Loader()
- .StartNavigation(FrameLoadRequest(&GetDocument(), resource_request),
- frame_load_type);
+ child_frame->Loader().StartNavigation(
+ FrameLoadRequest(&GetDocument(), request), child_load_type);
+
+ return true;
}
void HTMLFrameOwnerElement::CancelPendingLazyLoad() {
- if (!lazy_load_intersection_observer_)
+ if (!lazy_load_frame_observer_)
return;
- lazy_load_intersection_observer_->disconnect();
- lazy_load_intersection_observer_.Clear();
+ lazy_load_frame_observer_->CancelPendingLazyLoad();
}
bool HTMLFrameOwnerElement::ShouldLazyLoadChildren() const {
@@ -471,7 +433,7 @@ bool HTMLFrameOwnerElement::ShouldLazyLoadChildren() const {
void HTMLFrameOwnerElement::Trace(blink::Visitor* visitor) {
visitor->Trace(content_frame_);
visitor->Trace(embedded_content_view_);
- visitor->Trace(lazy_load_intersection_observer_);
+ visitor->Trace(lazy_load_frame_observer_);
HTMLElement::Trace(visitor);
FrameOwner::Trace(visitor);
}
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 41b4d004b03..5e62e5ad01d 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
@@ -37,9 +37,8 @@ namespace blink {
class ExceptionState;
class Frame;
-class IntersectionObserver;
-class IntersectionObserverEntry;
class LayoutEmbeddedContent;
+class LazyLoadFrameObserver;
class WebPluginContainerImpl;
class CORE_EXPORT HTMLFrameOwnerElement : public HTMLElement,
@@ -119,10 +118,6 @@ class CORE_EXPORT HTMLFrameOwnerElement : public HTMLElement,
void CancelPendingLazyLoad();
- // TODO(sclittle): Make the root margins configurable via field trial
- // params instead of just hardcoding the value here.
- static constexpr int kLazyLoadRootMarginPx = 800;
-
void Trace(blink::Visitor*) override;
protected:
@@ -143,7 +138,7 @@ class CORE_EXPORT HTMLFrameOwnerElement : public HTMLElement,
// This method is intended to be overridden by specific frame classes.
virtual scoped_refptr<const SecurityOrigin> GetOriginForFeaturePolicy()
const {
- return SecurityOrigin::CreateUnique();
+ return SecurityOrigin::CreateUniqueOpaque();
}
// Return a feature policy container policy for this frame, based on the
@@ -168,18 +163,13 @@ class CORE_EXPORT HTMLFrameOwnerElement : public HTMLElement,
return kReferrerPolicyDefault;
}
- void LoadIfHiddenOrNearViewport(
- const ResourceRequest&,
- FrameLoadType,
- const HeapVector<Member<IntersectionObserverEntry>>&);
-
Member<Frame> content_frame_;
Member<EmbeddedContentView> embedded_content_view_;
SandboxFlags sandbox_flags_;
ParsedFeaturePolicy container_policy_;
- Member<IntersectionObserver> lazy_load_intersection_observer_;
+ Member<LazyLoadFrameObserver> lazy_load_frame_observer_;
bool should_lazy_load_children_;
};
diff --git a/chromium/third_party/blink/renderer/core/html/html_frame_owner_element_test.cc b/chromium/third_party/blink/renderer/core/html/html_frame_owner_element_test.cc
deleted file mode 100644
index d2d41673c35..00000000000
--- a/chromium/third_party/blink/renderer/core/html/html_frame_owner_element_test.cc
+++ /dev/null
@@ -1,308 +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/html/html_frame_owner_element.h"
-
-#include <algorithm>
-
-#include "third_party/blink/renderer/core/exported/web_view_impl.h"
-#include "third_party/blink/renderer/core/frame/local_frame_view.h"
-#include "third_party/blink/renderer/core/testing/sim/sim_compositor.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/float_rect.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"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-namespace {
-
-class LazyLoadFramesTest : public SimTest {
- public:
- static constexpr int kViewportWidth = 800;
- static constexpr int kViewportHeight = 600;
-
- LazyLoadFramesTest() : scoped_lazy_frame_loading_for_test_(true) {}
-
- void SetUp() override {
- SimTest::SetUp();
- WebView().Resize(WebSize(kViewportWidth, kViewportHeight));
- }
-
- private:
- ScopedLazyFrameLoadingForTest scoped_lazy_frame_loading_for_test_;
-};
-
-TEST_F(LazyLoadFramesTest, SameOriginFrameIsNotDeferred) {
- SimRequest main_resource("https://example.com/", "text/html");
- SimRequest child_frame_resource("https://example.com/subframe.html",
- "text/html");
-
- LoadURL("https://example.com/");
-
- main_resource.Complete(String::Format(
- R"HTML(
- <body onload='console.log("main body onload");'>
- <div style='height: %dpx;'></div>
- <iframe src='https://example.com/subframe.html'
- style='width: 200px; height: 200px;'
- onload='console.log("child frame element onload");'></iframe>
- </body>)HTML",
- kViewportHeight + HTMLFrameOwnerElement::kLazyLoadRootMarginPx));
-
- child_frame_resource.Complete("");
-
- Compositor().BeginFrame();
- test::RunPendingTasks();
-
- EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
- EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload"));
-}
-
-TEST_F(LazyLoadFramesTest, AboveTheFoldFrameIsNotDeferred) {
- SimRequest main_resource("https://example.com/", "text/html");
- SimRequest child_frame_resource("https://crossorigin.com/subframe.html",
- "text/html");
-
- LoadURL("https://example.com/");
-
- main_resource.Complete(String::Format(
- R"HTML(
- <body onload='console.log("main body onload");'>
- <div style='height: %dpx;'></div>
- <iframe src='https://crossorigin.com/subframe.html'
- style='width: 200px; height: 200px;'
- onload='console.log("child frame element onload");'></iframe>
- </body>)HTML",
- kViewportHeight - 100));
-
- Compositor().BeginFrame();
- test::RunPendingTasks();
-
- child_frame_resource.Complete("");
-
- test::RunPendingTasks();
-
- EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
- EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload"));
-}
-
-TEST_F(LazyLoadFramesTest, BelowTheFoldButNearViewportFrameIsNotDeferred) {
- SimRequest main_resource("https://example.com/", "text/html");
- SimRequest child_frame_resource("https://crossorigin.com/subframe.html",
- "text/html");
-
- LoadURL("https://example.com/");
-
- main_resource.Complete(String::Format(
- R"HTML(
- <body onload='console.log("main body onload");'>
- <div style='height: %dpx;'></div>
- <iframe src='https://crossorigin.com/subframe.html'
- style='width: 200px; height: 200px;'
- onload='console.log("child frame element onload");'></iframe>
- </body>)HTML",
- kViewportHeight + 100));
-
- Compositor().BeginFrame();
- test::RunPendingTasks();
-
- child_frame_resource.Complete("");
-
- test::RunPendingTasks();
-
- EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
- EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload"));
-}
-
-TEST_F(LazyLoadFramesTest, HiddenAndTinyFramesAreNotDeferred) {
- SimRequest main_resource("https://example.com/", "text/html");
-
- SimRequest display_none_frame_resource(
- "https://crossorigin.com/display_none.html", "text/html");
- SimRequest tiny_frame_resource("https://crossorigin.com/tiny.html",
- "text/html");
- SimRequest tiny_width_frame_resource(
- "https://crossorigin.com/tiny_width.html", "text/html");
- SimRequest tiny_height_frame_resource(
- "https://crossorigin.com/tiny_height.html", "text/html");
- SimRequest off_screen_left_frame_resource(
- "https://crossorigin.com/off_screen_left.html", "text/html");
- SimRequest off_screen_top_frame_resource(
- "https://crossorigin.com/off_screen_top.html", "text/html");
-
- LoadURL("https://example.com/");
-
- main_resource.Complete(String::Format(
- R"HTML(
- <head><style>
- /* Chrome by default sets borders for iframes, so explicitly specify
- * no borders, padding, or margins here so that the dimensions of the
- * tiny frames aren't artifically inflated past the dimensions that
- * the lazy loading logic considers "tiny". */
- iframe { border-style: none; padding: 0px; margin: 0px; }
- </style></head>
-
- <body onload='console.log("main body onload");'>
- <div style='height: %dpx'></div>
- <iframe src='https://crossorigin.com/display_none.html'
- style='display: none;'
- onload='console.log("display none element onload");'></iframe>
- <iframe src='https://crossorigin.com/tiny.html'
- style='width: 4px; height: 4px;'
- onload='console.log("tiny element onload");'></iframe>
- <iframe src='https://crossorigin.com/tiny_width.html'
- style='width: 0px; height: 200px;'
- onload='console.log("tiny width element onload");'></iframe>
- <iframe src='https://crossorigin.com/tiny_height.html'
- style='width: 200px; height: 0px;'
- onload='console.log("tiny height element onload");'></iframe>
- <iframe src='https://crossorigin.com/off_screen_left.html'
- style='position:relative;right:9000px;width:200px;height:200px;'
- onload='console.log("off screen left element onload");'></iframe>
- <iframe src='https://crossorigin.com/off_screen_top.html'
- style='position:relative;bottom:9000px;width:200px;height:200px;'
- onload='console.log("off screen top element onload");'></iframe>
- </body>
- )HTML",
- kViewportHeight + HTMLFrameOwnerElement::kLazyLoadRootMarginPx + 100));
-
- Compositor().BeginFrame();
- test::RunPendingTasks();
-
- display_none_frame_resource.Complete("");
- tiny_frame_resource.Complete("");
- tiny_width_frame_resource.Complete("");
- tiny_height_frame_resource.Complete("");
- off_screen_left_frame_resource.Complete("");
- off_screen_top_frame_resource.Complete("");
-
- test::RunPendingTasks();
-
- EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
- EXPECT_TRUE(ConsoleMessages().Contains("display none element onload"));
- EXPECT_TRUE(ConsoleMessages().Contains("tiny element onload"));
- EXPECT_TRUE(ConsoleMessages().Contains("tiny width element onload"));
- EXPECT_TRUE(ConsoleMessages().Contains("tiny height element onload"));
- EXPECT_TRUE(ConsoleMessages().Contains("off screen left element onload"));
- EXPECT_TRUE(ConsoleMessages().Contains("off screen top element onload"));
-}
-
-TEST_F(LazyLoadFramesTest, CrossOriginFrameIsDeferredUntilNearViewport) {
- SimRequest main_resource("https://example.com/", "text/html");
- LoadURL("https://example.com/");
-
- main_resource.Complete(String::Format(
- R"HTML(
- <body onload='console.log("main body onload");'>
- <div style='height: %dpx;'></div>
- <iframe src='https://crossorigin.com/subframe.html'
- style='width: 400px; height: 400px;'
- onload='console.log("child frame element onload");'></iframe>
- </body>)HTML",
- kViewportHeight + HTMLFrameOwnerElement::kLazyLoadRootMarginPx + 100));
-
- Compositor().BeginFrame();
- test::RunPendingTasks();
-
- EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
- EXPECT_FALSE(ConsoleMessages().Contains("child frame element onload"));
-
- SimRequest child_frame_resource("https://crossorigin.com/subframe.html",
- "text/html");
-
- // Scroll down near the child frame. This should cause the child frame to get
- // loaded.
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, kViewportHeight + 150), kProgrammaticScroll);
-
- Compositor().BeginFrame();
- test::RunPendingTasks();
-
- SimRequest nested_child_frame_resource("https://test.com/", "text/html");
-
- // There's another nested cross origin iframe inside the first child frame,
- // partway down such that it's not near the viewport. It should still be
- // loaded immediately, and not deferred, since it's nested inside a frame that
- // was previously deferred.
- child_frame_resource.Complete(
- "<div style='height: 200px;'></div>"
- "<iframe src='https://test.com/' style='width: 200px; height: 200px;'>"
- "</iframe>");
-
- test::RunPendingTasks();
- nested_child_frame_resource.Complete("");
- test::RunPendingTasks();
-
- EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
- EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload"));
-}
-
-TEST_F(LazyLoadFramesTest, AboutBlankNavigationIsNotDeferred) {
- SimRequest main_resource("https://example.com/", "text/html");
- SimRequest child_frame_resource("https://crossorigin.com/subframe.html",
- "text/html");
-
- LoadURL("https://example.com/");
-
- main_resource.Complete(String::Format(
- R"HTML(
- <body onload='BodyOnload()'>
- <script>
- function BodyOnload() {
- console.log('main body onload');
- document.getElementsByTagName('iframe')[0].src =
- 'https://crossorigin.com/subframe.html';
- }
- </script>
-
- <div style='height: %dpx;'></div>
- <iframe
- style='width: 200px; height: 200px;'
- onload='console.log("child frame element onload");'></iframe>
- </body>)HTML",
- kViewportHeight + HTMLFrameOwnerElement::kLazyLoadRootMarginPx + 100));
-
- Compositor().BeginFrame();
- test::RunPendingTasks();
-
- EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
- EXPECT_EQ(1, static_cast<int>(std::count(ConsoleMessages().begin(),
- ConsoleMessages().end(),
- "child frame element onload")));
-
- child_frame_resource.Complete("");
-
- Compositor().BeginFrame();
- test::RunPendingTasks();
-
- EXPECT_EQ(2, static_cast<int>(std::count(ConsoleMessages().begin(),
- ConsoleMessages().end(),
- "child frame element onload")));
-}
-
-TEST_F(LazyLoadFramesTest, JavascriptStringUrlIsNotDeferred) {
- SimRequest main_resource("https://example.com/", "text/html");
- LoadURL("https://example.com/");
-
- main_resource.Complete(String::Format(
- R"HTML(
- <body onload='console.log("main body onload");'>
- <div style='height: %dpx;'></div>
- <iframe src='javascript:"Hello World!";'
- style='width: 200px; height: 200px;'
- onload='console.log("child frame element onload");'></iframe>
- </body>)HTML",
- kViewportHeight + HTMLFrameOwnerElement::kLazyLoadRootMarginPx + 100));
-
- EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
- EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload"));
-}
-
-} // namespace
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/html_hyperlink_element_utils.idl b/chromium/third_party/blink/renderer/core/html/html_hyperlink_element_utils.idl
index ac6f340b390..c2e628caf4d 100644
--- a/chromium/third_party/blink/renderer/core/html/html_hyperlink_element_utils.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_hyperlink_element_utils.idl
@@ -7,7 +7,8 @@
[
NoInterfaceObject // Always used on target of 'implements'
] interface HTMLHyperlinkElementUtils {
- [CEReactions] stringifier attribute USVString href;
+
+ [CEReactions, RaisesException=Setter, CallWith=ScriptState] stringifier attribute URLString href;
readonly attribute USVString origin;
[CEReactions] attribute USVString protocol;
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 7b169fc1dd8..fae0cdf64c2 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,14 +24,17 @@
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
+#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_html_iframe_element.h"
#include "third_party/blink/renderer/core/css_property_names.h"
+#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/html/html_document.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_iframe.h"
-#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/policy/iframe_policy.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -207,8 +210,8 @@ void HTMLIFrameElement::ParseAttribute(
// proper solution.
// To avoid polluting the console, this is being recorded only once per
// page.
- if (name == "gesture" && value == "media" && GetDocument().GetPage() &&
- !GetDocument().GetPage()->GetUseCounter().HasRecordedMeasurement(
+ if (name == "gesture" && value == "media" && GetDocument().Loader() &&
+ !GetDocument().Loader()->GetUseCounter().HasRecordedMeasurement(
WebFeature::kHTMLIFrameElementGestureMedia)) {
UseCounter::Count(GetDocument(),
WebFeature::kHTMLIFrameElementGestureMedia);
@@ -236,44 +239,21 @@ ParsedFeaturePolicy HTMLIFrameElement::ConstructContainerPolicy(
// If allowfullscreen attribute is present and no fullscreen policy is set,
// enable the feature for all origins.
if (AllowFullscreen()) {
- bool has_fullscreen_policy = false;
- for (const auto& declaration : container_policy) {
- if (declaration.feature == mojom::FeaturePolicyFeature::kFullscreen) {
- has_fullscreen_policy = true;
- if (messages) {
- messages->push_back(
- "allow attribute is overriding 'allowfullscreen'.");
- }
- break;
- }
- }
- if (!has_fullscreen_policy) {
- ParsedFeaturePolicyDeclaration whitelist;
- whitelist.feature = mojom::FeaturePolicyFeature::kFullscreen;
- whitelist.matches_all_origins = true;
- container_policy.push_back(whitelist);
+ bool policy_changed = AllowFeatureEverywhereIfNotPresent(
+ mojom::FeaturePolicyFeature::kFullscreen, container_policy);
+ if (!policy_changed && messages) {
+ messages->push_back(
+ "Allow attribute will take precedence over 'allowfullscreen'.");
}
}
// If the allowpaymentrequest attribute is present and no 'payment' policy is
// set, enable the feature for all origins.
if (AllowPaymentRequest()) {
- bool has_payment_policy = false;
- for (const auto& declaration : container_policy) {
- if (declaration.feature == mojom::FeaturePolicyFeature::kPayment) {
- has_payment_policy = true;
- if (messages) {
- messages->push_back(
- "allow attribute is overriding 'allowpaymentrequest'.");
- }
- break;
- }
- }
- if (!has_payment_policy) {
- ParsedFeaturePolicyDeclaration whitelist;
- whitelist.feature = mojom::FeaturePolicyFeature::kPayment;
- whitelist.matches_all_origins = true;
- whitelist.origins = std::vector<url::Origin>(0UL);
- container_policy.push_back(whitelist);
+ bool policy_changed = AllowFeatureEverywhereIfNotPresent(
+ mojom::FeaturePolicyFeature::kPayment, container_policy);
+ if (!policy_changed && messages) {
+ messages->push_back(
+ "Allow attribute will take precedence over 'allowpaymentrequest'.");
}
}
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 88255f5b12c..c0d5a9c012c 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
@@ -19,10 +19,14 @@
*/
// https://html.spec.whatwg.org/#the-iframe-element
+
+// The `HTMLString` and `URLString` references below are from Trusted Types:
+// https://github.com/WICG/trusted-types/, which is still WIP.
+// https://crbug.com/739170.
[HTMLConstructor]
interface HTMLIFrameElement : HTMLElement {
- [CEReactions, Reflect, URL] attribute USVString src;
- [CEReactions, Reflect] attribute DOMString srcdoc;
+ [CEReactions, Reflect, URL, RaisesException=Setter] attribute URLString src;
+ [CEReactions, Reflect, RaisesException=Setter] attribute HTMLString srcdoc;
[CEReactions, Reflect] attribute DOMString name;
[PutForwards=value] readonly attribute DOMTokenList sandbox;
// Note: The seamless attribute was once supported, but was removed.
@@ -43,7 +47,7 @@ interface HTMLIFrameElement : HTMLElement {
// TODO(iclelland): add spec for JS exposure in the spec for Feature Policy.
// Please refer to this doc for more details for now:
// https://docs.google.com/a/chromium.org/document/d/1wvk3cXkblNnbkMcsKayseK-k0SMGiP9b9fQFgfpqQpc/edit?usp=sharing
- [RuntimeEnabled=FeaturePolicyJavaScriptInterface] readonly attribute Policy policy;
+ [OriginTrialEnabled=FeaturePolicyJavaScriptInterface] readonly attribute Policy policy;
// obsolete members
// https://html.spec.whatwg.org/#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 190213c4335..3ca5e96a1f0 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
@@ -40,13 +40,13 @@ TEST_F(HTMLIFrameElementTest, FramesUseCorrectOrigin) {
effective_origin = GetOriginForFeaturePolicy(frame_element);
EXPECT_FALSE(
effective_origin->IsSameSchemeHostPort(document->GetSecurityOrigin()));
- EXPECT_TRUE(effective_origin->IsUnique());
+ EXPECT_TRUE(effective_origin->IsOpaque());
frame_element->setAttribute(HTMLNames::srcAttr, "http://example.net/");
effective_origin = GetOriginForFeaturePolicy(frame_element);
EXPECT_FALSE(
effective_origin->IsSameSchemeHostPort(document->GetSecurityOrigin()));
- EXPECT_FALSE(effective_origin->IsUnique());
+ EXPECT_FALSE(effective_origin->IsOpaque());
}
// Test that a unique origin is used when constructing the container policy in a
@@ -65,13 +65,13 @@ TEST_F(HTMLIFrameElementTest, SandboxFramesUseCorrectOrigin) {
GetOriginForFeaturePolicy(frame_element);
EXPECT_FALSE(
effective_origin->IsSameSchemeHostPort(document->GetSecurityOrigin()));
- EXPECT_TRUE(effective_origin->IsUnique());
+ EXPECT_TRUE(effective_origin->IsOpaque());
frame_element->setAttribute(HTMLNames::srcAttr, "http://example.net/");
effective_origin = GetOriginForFeaturePolicy(frame_element);
EXPECT_FALSE(
effective_origin->IsSameSchemeHostPort(document->GetSecurityOrigin()));
- EXPECT_TRUE(effective_origin->IsUnique());
+ EXPECT_TRUE(effective_origin->IsOpaque());
}
// Test that a sandboxed iframe with the allow-same-origin sandbox flag uses the
@@ -90,7 +90,7 @@ TEST_F(HTMLIFrameElementTest, SameOriginSandboxFramesUseCorrectOrigin) {
GetOriginForFeaturePolicy(frame_element);
EXPECT_TRUE(
effective_origin->IsSameSchemeHostPort(document->GetSecurityOrigin()));
- EXPECT_FALSE(effective_origin->IsUnique());
+ EXPECT_FALSE(effective_origin->IsOpaque());
}
// Test that the parent document's origin is used when constructing the
@@ -126,7 +126,7 @@ TEST_F(HTMLIFrameElementTest, SandboxedSrcdocFramesUseCorrectOrigin) {
GetOriginForFeaturePolicy(frame_element);
EXPECT_FALSE(
effective_origin->IsSameSchemeHostPort(document->GetSecurityOrigin()));
- EXPECT_TRUE(effective_origin->IsUnique());
+ EXPECT_TRUE(effective_origin->IsOpaque());
}
// Test that iframes with relative src urls correctly construct their origin
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 1e4e9268e1b..8c29fcd4001 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
@@ -30,9 +30,9 @@
#include "third_party/blink/renderer/core/css_property_names.h"
#include "third_party/blink/renderer/core/dom/attribute.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
-#include "third_party/blink/renderer/core/dom/sync_reattach_context.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/html/canvas/html_canvas_element.h"
@@ -50,6 +50,7 @@
#include "third_party/blink/renderer/core/layout/adjust_for_absolute_zoom.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_image.h"
+#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
#include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
#include "third_party/blink/renderer/core/media_type_names.h"
@@ -57,7 +58,7 @@
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/style/content_data.h"
#include "third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h"
-#include "third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_url.h"
#include "third_party/blink/renderer/platform/network/mime/content_type.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
@@ -357,9 +358,7 @@ LayoutObject* HTMLImageElement::CreateLayoutObject(const ComputedStyle& style) {
switch (layout_disposition_) {
case LayoutDisposition::kFallbackContent:
- if (!RuntimeEnabledFeatures::LayoutNGEnabled())
- return new LayoutBlockFlow(this);
- return new LayoutNGBlockFlow(this);
+ return LayoutObjectFactory::CreateBlockFlow(*this, style);
case LayoutDisposition::kPrimaryContent: {
LayoutImage* image = new LayoutImage(this);
image->SetImageResource(LayoutImageResource::Create());
@@ -374,7 +373,6 @@ LayoutObject* HTMLImageElement::CreateLayoutObject(const ComputedStyle& style) {
}
void HTMLImageElement::AttachLayoutTree(AttachContext& context) {
- SyncReattachContext reattach_context(context);
HTMLElement::AttachLayoutTree(context);
if (GetLayoutObject() && GetLayoutObject()->IsImage()) {
LayoutImage* layout_image = ToLayoutImage(GetLayoutObject());
@@ -567,6 +565,11 @@ void HTMLImageElement::SetSrc(const String& value) {
setAttribute(srcAttr, AtomicString(value));
}
+void HTMLImageElement::SetSrc(const USVStringOrTrustedURL& value,
+ ExceptionState& exception_state) {
+ setAttribute(srcAttr, value, exception_state);
+}
+
void HTMLImageElement::setWidth(unsigned value) {
SetUnsignedIntegralAttribute(widthAttr, value);
}
@@ -752,7 +755,7 @@ void HTMLImageElement::EnsureFallbackForGeneratedContent() {
// appropriate for |m_layoutDisposition|. Force recreate it.
// TODO(engedy): Remove this hack. See: https://crbug.com/671953.
SetLayoutDisposition(LayoutDisposition::kFallbackContent,
- true /* forceReattach */);
+ true /* force_reattach */);
}
void HTMLImageElement::EnsureCollapsedOrFallbackContent() {
@@ -781,19 +784,15 @@ void HTMLImageElement::SetLayoutDisposition(
if (layout_disposition_ == layout_disposition && !force_reattach)
return;
+ DCHECK(!GetDocument().InStyleRecalc());
+
layout_disposition_ = layout_disposition;
- if (GetDocument().InStyleRecalc()) {
- // This can happen inside of AttachLayoutTree() in the middle of a
- // RebuildLayoutTree, so we need to reattach synchronously here.
- ReattachLayoutTree(SyncReattachContext::CurrentAttachContext());
- } else {
- if (layout_disposition_ == LayoutDisposition::kFallbackContent) {
- EventDispatchForbiddenScope::AllowUserAgentEvents allow_events;
- EnsureUserAgentShadowRoot();
- }
- LazyReattachIfAttached();
+ if (layout_disposition_ == LayoutDisposition::kFallbackContent) {
+ EventDispatchForbiddenScope::AllowUserAgentEvents allow_events;
+ EnsureUserAgentShadowRoot();
}
+ LazyReattachIfAttached();
}
scoped_refptr<ComputedStyle> HTMLImageElement::CustomStyleForLayoutObject() {
diff --git a/chromium/third_party/blink/renderer/core/html/html_image_element.h b/chromium/third_party/blink/renderer/core/html/html_image_element.h
index 8f8524d192e..14a6964d1ea 100644
--- a/chromium/third_party/blink/renderer/core/html/html_image_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_image_element.h
@@ -40,7 +40,9 @@ namespace blink {
class HTMLFormElement;
class ImageCandidate;
+class ExceptionState;
class ShadowRoot;
+class USVStringOrTrustedURL;
class CORE_EXPORT HTMLImageElement final
: public HTMLElement,
@@ -95,6 +97,7 @@ class CORE_EXPORT HTMLImageElement final
KURL Src() const;
void SetSrc(const String&);
+ void SetSrc(const USVStringOrTrustedURL&, ExceptionState&);
void setWidth(unsigned);
diff --git a/chromium/third_party/blink/renderer/core/html/html_image_element.idl b/chromium/third_party/blink/renderer/core/html/html_image_element.idl
index 6e46e502620..c3e798091f8 100644
--- a/chromium/third_party/blink/renderer/core/html/html_image_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_image_element.idl
@@ -27,7 +27,7 @@
NamedConstructor=Image(optional unsigned long width, optional unsigned long height)
] interface HTMLImageElement : HTMLElement {
[CEReactions, Reflect] attribute DOMString alt;
- [CEReactions, Reflect, URL] attribute DOMString src;
+ [CEReactions, Reflect, URL, RaisesException=Setter] attribute URLString src;
[CEReactions, Reflect] attribute DOMString srcset;
[CEReactions, Reflect] attribute DOMString sizes;
[CEReactions, Reflect, ReflectOnly=("anonymous","use-credentials"), ReflectEmpty="anonymous", ReflectInvalid="anonymous"] attribute DOMString? crossOrigin;
@@ -41,6 +41,7 @@
readonly attribute DOMString currentSrc;
[CEReactions, Reflect, ReflectOnly=("","no-referrer","origin","no-referrer-when-downgrade","origin-when-cross-origin","unsafe-url"), ReflectMissing="", ReflectInvalid=""] attribute DOMString referrerPolicy;
[RuntimeEnabled=ImageDecodingAttribute, CEReactions, Reflect, ReflectOnly=("async", "sync", "auto"), ReflectMissing="auto", ReflectInvalid="auto"] attribute DOMString decoding;
+ [CEReactions, RuntimeEnabled=PriorityHints, Reflect, ReflectOnly=("low", "auto", "high"), ReflectMissing="auto", ReflectInvalid="auto"] attribute DOMString importance;
// obsolete members
// https://html.spec.whatwg.org/#HTMLImageElement-partial
diff --git a/chromium/third_party/blink/renderer/core/html/html_image_fallback_helper.cc b/chromium/third_party/blink/renderer/core/html/html_image_fallback_helper.cc
index 9369b5706a8..c73fb09b4ed 100644
--- a/chromium/third_party/blink/renderer/core/html/html_image_fallback_helper.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_image_fallback_helper.cc
@@ -134,20 +134,12 @@ scoped_refptr<ComputedStyle> HTMLImageFallbackHelper::CustomStyleForAltText(
CSSValueInlineBlock);
place_holder->SetInlineStyleProperty(CSSPropertyPointerEvents,
CSSValueNone);
- CSSPrimitiveValue::UnitType unit =
- new_style->Height().IsPercent()
- ? CSSPrimitiveValue::UnitType::kPercentage
- : CSSPrimitiveValue::UnitType::kPixels;
-
- // The width and height reported by computed style are zoomed, but when
- // setting the width and height CSS properties we want pre-zoomed sizes.
- float scale_factor = unit == CSSPrimitiveValue::UnitType::kPixels
- ? new_style->EffectiveZoom()
- : 1.0f;
place_holder->SetInlineStyleProperty(
- CSSPropertyHeight, new_style->Height().Value() / scale_factor, unit);
+ CSSPropertyHeight,
+ *CSSValue::Create(new_style->Height(), new_style->EffectiveZoom()));
place_holder->SetInlineStyleProperty(
- CSSPropertyWidth, new_style->Width().Value() / scale_factor, unit);
+ CSSPropertyWidth,
+ *CSSValue::Create(new_style->Width(), new_style->EffectiveZoom()));
// 16px for the image and 2px for its top/left border/padding offset.
int pixels_for_alt_image = 18;
diff --git a/chromium/third_party/blink/renderer/core/html/html_li_element.cc b/chromium/third_party/blink/renderer/core/html/html_li_element.cc
index 56853bd5c12..30f2e50b133 100644
--- a/chromium/third_party/blink/renderer/core/html/html_li_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_li_element.cc
@@ -111,7 +111,7 @@ void HTMLLIElement::AttachLayoutTree(AttachContext& context) {
// inside. We don't want to change our style to say "inside" since that
// would affect nested nodes.
if (!list_node)
- ordinal->SetNotInList(true);
+ ordinal->SetNotInList(true, *this);
ParseValue(FastGetAttribute(valueAttr), ordinal);
}
diff --git a/chromium/third_party/blink/renderer/core/html/html_link_element.cc b/chromium/third_party/blink/renderer/core/html/html_link_element.cc
index 55c57cb9052..113961948b9 100644
--- a/chromium/third_party/blink/renderer/core/html/html_link_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_link_element.cc
@@ -105,6 +105,9 @@ void HTMLLinkElement::ParseAttribute(
Process();
} else if (name == integrityAttr) {
integrity_ = value;
+ } else if (name == importanceAttr &&
+ RuntimeEnabledFeatures::PriorityHintsEnabled()) {
+ importance_ = value;
} else if (name == disabledAttr) {
UseCounter::Count(GetDocument(), WebFeature::kHTMLLinkElementDisabled);
if (LinkStyle* link = GetLinkStyle())
@@ -126,11 +129,23 @@ bool HTMLLinkElement::ShouldLoadLink() {
!href.PotentiallyDanglingMarkup();
}
+bool HTMLLinkElement::IsLinkCreatedByParser() {
+ return IsCreatedByParser();
+}
+
bool HTMLLinkElement::LoadLink(const LinkLoadParameters& params) {
return link_loader_->LoadLink(params, GetDocument(),
NetworkHintsInterfaceImpl());
}
+void HTMLLinkElement::LoadStylesheet(const LinkLoadParameters& params,
+ const WTF::TextEncoding& charset,
+ FetchParameters::DeferOption defer_option,
+ ResourceClient* link_client) {
+ return link_loader_->LoadStylesheet(params, localName(), charset,
+ defer_option, GetDocument(), link_client);
+}
+
LinkResource* HTMLLinkElement::LinkResourceToProcess() {
if (!ShouldLoadLink()) {
// If we shouldn't load the link, but the link is already of type
@@ -370,9 +385,4 @@ void HTMLLinkElement::Trace(blink::Visitor* visitor) {
LinkLoaderClient::Trace(visitor);
}
-void HTMLLinkElement::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(rel_list_);
- HTMLElement::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/html_link_element.h b/chromium/third_party/blink/renderer/core/html/html_link_element.h
index a80224c1e28..56774e1a1a8 100644
--- a/chromium/third_party/blink/renderer/core/html/html_link_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_link_element.h
@@ -38,6 +38,7 @@
#include "third_party/blink/renderer/core/loader/link_loader.h"
#include "third_party/blink/renderer/core/loader/link_loader_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
+#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
namespace blink {
@@ -60,6 +61,7 @@ class CORE_EXPORT HTMLLinkElement final : public HTMLElement,
String TypeValue() const { return type_; }
String AsValue() const { return as_; }
String IntegrityValue() const { return integrity_; }
+ String ImportanceValue() const { return importance_; }
ReferrerPolicy GetReferrerPolicy() const { return referrer_policy_; }
const LinkRelAttribute& RelAttribute() const { return rel_attribute_; }
DOMTokenList& relList() const {
@@ -97,9 +99,14 @@ class CORE_EXPORT HTMLLinkElement final : public HTMLElement,
// From LinkLoaderClient
bool ShouldLoadLink() override;
+ bool IsLinkCreatedByParser() override;
// For LinkStyle
bool LoadLink(const LinkLoadParameters&);
+ void LoadStylesheet(const LinkLoadParameters&,
+ const WTF::TextEncoding&,
+ FetchParameters::DeferOption,
+ ResourceClient*);
bool IsAlternate() const {
return GetLinkStyle()->IsUnset() && rel_attribute_.IsAlternate();
}
@@ -110,8 +117,6 @@ class CORE_EXPORT HTMLLinkElement final : public HTMLElement,
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
private:
HTMLLinkElement(Document&, const CreateElementFlags);
@@ -156,6 +161,7 @@ class CORE_EXPORT HTMLLinkElement final : public HTMLElement,
String as_;
String media_;
String integrity_;
+ String importance_;
ReferrerPolicy referrer_policy_;
Member<DOMTokenList> sizes_;
Vector<IntSize> icon_sizes_;
diff --git a/chromium/third_party/blink/renderer/core/html/html_link_element.idl b/chromium/third_party/blink/renderer/core/html/html_link_element.idl
index 2465804e936..0a34d5da79c 100644
--- a/chromium/third_party/blink/renderer/core/html/html_link_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_link_element.idl
@@ -25,7 +25,7 @@ interface HTMLLinkElement : HTMLElement {
// FIXME: The disabled attribute has been removed from the spec:
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=14703
[Reflect, Measure] attribute boolean disabled;
- [Reflect, URL] attribute USVString href;
+ [Reflect, URL, RaisesException=Setter] attribute URLString href;
[CEReactions, Reflect, ReflectOnly=("anonymous","use-credentials"), ReflectEmpty="anonymous", ReflectInvalid="anonymous"] attribute DOMString? crossOrigin;
[CEReactions, Reflect] attribute DOMString rel;
[SameObject, PutForwards=value] readonly attribute DOMTokenList relList;
@@ -35,6 +35,7 @@ interface HTMLLinkElement : HTMLElement {
[Reflect, ReflectOnly=("script","style","image","video", "audio", "track", "font", "fetch")] attribute DOMString as;
[CEReactions, Reflect, ReflectOnly=("","no-referrer","origin","no-referrer-when-downgrade","origin-when-cross-origin","unsafe-url"), ReflectMissing="", ReflectInvalid=""] attribute DOMString referrerPolicy;
[PutForwards=value] readonly attribute DOMTokenList sizes;
+ [CEReactions, RuntimeEnabled=PriorityHints, Reflect, ReflectOnly=("low", "auto", "high"), ReflectMissing="auto", ReflectInvalid="auto"] attribute DOMString importance;
// obsolete members
// https://html.spec.whatwg.org/#HTMLLinkElement-partial
diff --git a/chromium/third_party/blink/renderer/core/html/html_marquee_element.cc b/chromium/third_party/blink/renderer/core/html/html_marquee_element.cc
index 6b6dbd26853..85588ab0613 100644
--- a/chromium/third_party/blink/renderer/core/html/html_marquee_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_marquee_element.cc
@@ -25,7 +25,6 @@
#include <cstdlib>
#include "base/macros.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_html_marquee_element.h"
#include "third_party/blink/renderer/core/animation/document_timeline.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect.h"
@@ -47,6 +46,7 @@
#include "third_party/blink/renderer/core/html/html_style_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/platform/bindings/exception_state.h"
namespace blink {
@@ -186,9 +186,10 @@ int HTMLMarqueeElement::loop() const {
void HTMLMarqueeElement::setLoop(int value, ExceptionState& exception_state) {
if (value <= 0 && value != -1) {
- exception_state.ThrowDOMException(
- kIndexSizeError, "The provided value (" + String::Number(value) +
- ") is neither positive nor -1.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kIndexSizeError,
+ "The provided value (" +
+ String::Number(value) +
+ ") is neither positive nor -1.");
return;
}
SetIntegralAttribute(HTMLNames::loopAttr, value);
diff --git a/chromium/third_party/blink/renderer/core/html/html_meta_element.cc b/chromium/third_party/blink/renderer/core/html/html_meta_element.cc
index f8d660b46b7..dbd315181f1 100644
--- a/chromium/third_party/blink/renderer/core/html/html_meta_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_meta_element.cc
@@ -27,6 +27,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/viewport_data.h"
#include "third_party/blink/renderer/core/html/html_head_element.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html_names.h"
@@ -304,18 +305,18 @@ float HTMLMetaElement::ParseViewportValueAsDPI(Document* document,
return value;
}
-ViewportDescription::ViewportFit HTMLMetaElement::ParseViewportFitValueAsEnum(
+blink::mojom::ViewportFit HTMLMetaElement::ParseViewportFitValueAsEnum(
bool& unknown_value,
const String& value_string) {
if (DeprecatedEqualIgnoringCase(value_string, "auto"))
- return ViewportDescription::ViewportFit::kAuto;
+ return mojom::ViewportFit::kAuto;
if (DeprecatedEqualIgnoringCase(value_string, "contain"))
- return ViewportDescription::ViewportFit::kContain;
+ return mojom::ViewportFit::kContain;
if (DeprecatedEqualIgnoringCase(value_string, "cover"))
- return ViewportDescription::ViewportFit::kCover;
+ return mojom::ViewportFit::kCover;
unknown_value = true;
- return ViewportDescription::ViewportFit::kAuto;
+ return mojom::ViewportFit::kAuto;
}
void HTMLMetaElement::ProcessViewportKeyValuePair(
@@ -366,7 +367,7 @@ void HTMLMetaElement::ProcessViewportKeyValuePair(
} else if (key_string == "minimal-ui") {
// Ignore vendor-specific argument.
} else if (key_string == "viewport-fit") {
- if (RuntimeEnabledFeatures::DisplayCutoutViewportFitEnabled()) {
+ if (RuntimeEnabledFeatures::DisplayCutoutAPIEnabled()) {
bool unknown_value = false;
description->SetViewportFit(
ParseViewportFitValueAsEnum(unknown_value, value_string));
@@ -457,19 +458,20 @@ void HTMLMetaElement::ProcessViewportContentAttribute(
ViewportDescription::Type origin) {
DCHECK(!content.IsNull());
- if (!GetDocument().ShouldOverrideLegacyDescription(origin))
+ ViewportData& viewport_data = GetDocument().GetViewportData();
+ if (!viewport_data.ShouldOverrideLegacyDescription(origin))
return;
ViewportDescription description_from_legacy_tag(origin);
- if (GetDocument().ShouldMergeWithLegacyDescription(origin))
- description_from_legacy_tag = GetDocument().GetViewportDescription();
+ if (viewport_data.ShouldMergeWithLegacyDescription(origin))
+ description_from_legacy_tag = viewport_data.GetViewportDescription();
GetViewportDescriptionFromContentAttribute(
content, description_from_legacy_tag, &GetDocument(),
GetDocument().GetSettings() &&
GetDocument().GetSettings()->GetViewportMetaZeroValuesQuirk());
- GetDocument().SetViewportDescription(description_from_legacy_tag);
+ viewport_data.SetViewportDescription(description_from_legacy_tag);
}
void HTMLMetaElement::ParseAttribute(
diff --git a/chromium/third_party/blink/renderer/core/html/html_meta_element.h b/chromium/third_party/blink/renderer/core/html/html_meta_element.h
index 9303f6e2ae3..207409164e8 100644
--- a/chromium/third_party/blink/renderer/core/html/html_meta_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_meta_element.h
@@ -24,8 +24,8 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_META_ELEMENT_H_
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/viewport_description.h"
#include "third_party/blink/renderer/core/html/html_element.h"
+#include "third_party/blink/renderer/core/page/viewport_description.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
namespace blink {
@@ -105,9 +105,8 @@ class CORE_EXPORT HTMLMetaElement final : public HTMLElement {
const String& key,
const String& value);
- static ViewportDescription::ViewportFit ParseViewportFitValueAsEnum(
- bool& unknown_value,
- const String& value);
+ static mojom::ViewportFit ParseViewportFitValueAsEnum(bool& unknown_value,
+ const String& value);
static void ReportViewportWarning(Document*,
ViewportErrorCode,
diff --git a/chromium/third_party/blink/renderer/core/html/html_meta_element_test.cc b/chromium/third_party/blink/renderer/core/html/html_meta_element_test.cc
index bca197d67d7..6bae8ac3083 100644
--- a/chromium/third_party/blink/renderer/core/html/html_meta_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_meta_element_test.cc
@@ -7,6 +7,7 @@
#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/frame/viewport_data.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -17,14 +18,16 @@ class HTMLMetaElementTest : public PageTestBase {
void SetUp() override {
PageTestBase::SetUp();
- RuntimeEnabledFeatures::SetDisplayCutoutViewportFitEnabled(true);
+ RuntimeEnabledFeatures::SetDisplayCutoutAPIEnabled(true);
GetDocument().GetSettings()->SetViewportMetaEnabled(true);
}
- ViewportDescription::ViewportFit LoadTestPageAndReturnViewportFit(
- const String& value) {
+ mojom::ViewportFit LoadTestPageAndReturnViewportFit(const String& value) {
LoadTestPageWithViewportFitValue(value);
- return GetDocument().GetViewportDescription().GetViewportFit();
+ return GetDocument()
+ .GetViewportData()
+ .GetViewportDescription()
+ .GetViewportFit();
}
private:
@@ -39,22 +42,22 @@ class HTMLMetaElementTest : public PageTestBase {
};
TEST_F(HTMLMetaElementTest, ViewportFit_Auto) {
- EXPECT_EQ(ViewportDescription::ViewportFit::kAuto,
+ EXPECT_EQ(mojom::ViewportFit::kAuto,
LoadTestPageAndReturnViewportFit("auto"));
}
TEST_F(HTMLMetaElementTest, ViewportFit_Contain) {
- EXPECT_EQ(ViewportDescription::ViewportFit::kContain,
+ EXPECT_EQ(mojom::ViewportFit::kContain,
LoadTestPageAndReturnViewportFit("contain"));
}
TEST_F(HTMLMetaElementTest, ViewportFit_Cover) {
- EXPECT_EQ(ViewportDescription::ViewportFit::kCover,
+ EXPECT_EQ(mojom::ViewportFit::kCover,
LoadTestPageAndReturnViewportFit("cover"));
}
TEST_F(HTMLMetaElementTest, ViewportFit_Invalid) {
- EXPECT_EQ(ViewportDescription::ViewportFit::kAuto,
+ EXPECT_EQ(mojom::ViewportFit::kAuto,
LoadTestPageAndReturnViewportFit("invalid"));
}
diff --git a/chromium/third_party/blink/renderer/core/html/html_meter_element.cc b/chromium/third_party/blink/renderer/core/html/html_meter_element.cc
index 6b4062d5fe7..b4a7f840649 100644
--- a/chromium/third_party/blink/renderer/core/html/html_meter_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_meter_element.cc
@@ -20,8 +20,6 @@
#include "third_party/blink/renderer/core/html/html_meter_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
@@ -30,6 +28,7 @@
#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/style/computed_style.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/html/html_object_element.cc b/chromium/third_party/blink/renderer/core/html/html_object_element.cc
index afe5ea48cb7..8537c83e021 100644
--- a/chromium/third_party/blink/renderer/core/html/html_object_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_object_element.cc
@@ -29,7 +29,6 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
-#include "third_party/blink/renderer/core/dom/sync_reattach_context.h"
#include "third_party/blink/renderer/core/dom/tag_collection.h"
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
@@ -329,15 +328,9 @@ const AtomicString HTMLObjectElement::ImageSourceURL() const {
return getAttribute(dataAttr);
}
-// TODO(schenney): crbug.com/572908 Remove this hack.
void HTMLObjectElement::ReattachFallbackContent() {
- if (GetDocument().InStyleRecalc()) {
- // This can happen inside of AttachLayoutTree() in the middle of a
- // RebuildLayoutTree, so we need to reattach synchronously here.
- ReattachLayoutTree(SyncReattachContext::CurrentAttachContext());
- } else {
+ if (!GetDocument().InStyleRecalc())
LazyReattachIfAttached();
- }
}
void HTMLObjectElement::RenderFallbackContent() {
@@ -428,11 +421,6 @@ void HTMLObjectElement::AssociateWith(HTMLFormElement* form) {
AssociateByParser(form);
}
-void HTMLObjectElement::AttachLayoutTree(AttachContext& context) {
- SyncReattachContext reattach_context(context);
- HTMLPlugInElement::AttachLayoutTree(context);
-}
-
const HTMLObjectElement* ToHTMLObjectElementFromListedElement(
const ListedElement* element) {
SECURITY_DCHECK(!element || !element->IsFormControlElement());
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 8f1009bc8d4..7e33237e2b3 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
@@ -80,7 +80,6 @@ class CORE_EXPORT HTMLObjectElement final : public HTMLPlugInElement,
FormAssociated* ToFormAssociatedOrNull() override { return this; };
void AssociateWith(HTMLFormElement*) override;
- void AttachLayoutTree(AttachContext&) final;
private:
HTMLObjectElement(Document&, const CreateElementFlags);
diff --git a/chromium/third_party/blink/renderer/core/html/html_object_element.idl b/chromium/third_party/blink/renderer/core/html/html_object_element.idl
index aad36a2b852..bd6d6db78a0 100644
--- a/chromium/third_party/blink/renderer/core/html/html_object_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_object_element.idl
@@ -26,7 +26,7 @@
ActiveScriptWrappable,
HTMLConstructor
] interface HTMLObjectElement : HTMLElement {
- [CEReactions, Reflect, URL] attribute DOMString data;
+ [CEReactions, Reflect, URL, RaisesException=Setter] attribute URLString data;
[CEReactions, Reflect] attribute DOMString type;
// TODO(foolip): attribute boolean typeMustMatch;
[CEReactions, Reflect] attribute DOMString name;
@@ -55,7 +55,7 @@
[CEReactions, Reflect] attribute unsigned long hspace;
[CEReactions, Reflect] attribute DOMString standby;
[CEReactions, Reflect] attribute unsigned long vspace;
- [CEReactions, Reflect, URL] attribute DOMString codeBase;
+ [CEReactions, Reflect, URL, RaisesException=Setter] attribute URLString codeBase;
[CEReactions, Reflect] attribute DOMString codeType;
[CEReactions, Reflect] attribute [TreatNullAs=EmptyString] DOMString border;
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 3e50bd4948c..d849d6968de 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
@@ -110,7 +110,9 @@ HTMLPlugInElement::HTMLPlugInElement(
// both classes share the same codepath in this class.
needs_plugin_update_(!flags.IsCreatedByParser()),
should_prefer_plug_ins_for_images_(prefer_plug_ins_for_images_option ==
- kShouldPreferPlugInsForImages) {}
+ kShouldPreferPlugInsForImages) {
+ SetHasCustomStyleCallbacks();
+}
HTMLPlugInElement::~HTMLPlugInElement() {
DCHECK(plugin_wrapper_.IsEmpty()); // cleared in detachLayoutTree()
@@ -216,21 +218,23 @@ void HTMLPlugInElement::AttachLayoutTree(AttachContext& context) {
return;
}
- if (IsImageType()) {
- if (!image_loader_)
- image_loader_ = HTMLImageLoader::Create(this);
- image_loader_->UpdateFromElement();
- } else if (NeedsPluginUpdate() && GetLayoutEmbeddedObject() &&
- !GetLayoutEmbeddedObject()->ShowsUnavailablePluginIndicator() &&
- GetObjectContentType() != ObjectContentType::kPlugin &&
- !is_delaying_load_event_) {
+ if (!IsImageType() && NeedsPluginUpdate() && GetLayoutEmbeddedObject() &&
+ !GetLayoutEmbeddedObject()->ShowsUnavailablePluginIndicator() &&
+ GetObjectContentType() != ObjectContentType::kPlugin &&
+ !is_delaying_load_event_) {
is_delaying_load_event_ = true;
GetDocument().IncrementLoadEventDelayCount();
GetDocument().LoadPluginsSoon();
}
- LayoutObject* layout_object = GetLayoutObject();
- if (layout_object && !layout_object->IsFloatingOrOutOfFlowPositioned())
- context.previous_in_flow = layout_object;
+ if (LayoutObject* layout_object = GetLayoutObject()) {
+ if (image_loader_ && layout_object->IsLayoutImage()) {
+ LayoutImageResource* image_resource =
+ ToLayoutImage(layout_object)->ImageResource();
+ image_resource->SetImageResource(image_loader_->GetContent());
+ }
+ if (!layout_object->IsFloatingOrOutOfFlowPositioned())
+ context.previous_in_flow = layout_object;
+ }
}
void HTMLPlugInElement::IntrinsicSizingInfoChanged() {
@@ -692,4 +696,15 @@ void HTMLPlugInElement::UpdateServiceTypeIfEmpty() {
}
}
+scoped_refptr<ComputedStyle> HTMLPlugInElement::CustomStyleForLayoutObject() {
+ scoped_refptr<ComputedStyle> style = OriginalStyleForLayoutObject();
+ if (IsImageType() && !GetLayoutObject() && style &&
+ LayoutObjectIsNeeded(*style)) {
+ if (!image_loader_)
+ image_loader_ = HTMLImageLoader::Create(this);
+ image_loader_->UpdateFromElement();
+ }
+ return style;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/html_plugin_element.h b/chromium/third_party/blink/renderer/core/html/html_plugin_element.h
index ce0fb4996eb..62e6624c9c2 100644
--- a/chromium/third_party/blink/renderer/core/html/html_plugin_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_plugin_element.h
@@ -170,6 +170,7 @@ class CORE_EXPORT HTMLPlugInElement
bool IsFocusableStyle() const final;
bool IsKeyboardFocusable() const final;
void DidAddUserAgentShadowRoot(ShadowRoot&) final;
+ scoped_refptr<ComputedStyle> CustomStyleForLayoutObject() final;
// HTMLElement overrides:
bool HasCustomFocusLogic() const override;
diff --git a/chromium/third_party/blink/renderer/core/html/html_progress_element.cc b/chromium/third_party/blink/renderer/core/html/html_progress_element.cc
index 67e50869244..d18eaed1f48 100644
--- a/chromium/third_party/blink/renderer/core/html/html_progress_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_progress_element.cc
@@ -20,14 +20,13 @@
#include "third_party/blink/renderer/core/html/html_progress_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html/shadow/progress_shadow_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/layout_progress.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
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 4181a0d3f9b..f0cad9ffdcf 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
@@ -19,6 +19,7 @@ class HTMLRubyElement final : public HTMLElement {
explicit HTMLRubyElement(Document&);
LayoutObject* CreateLayoutObject(const ComputedStyle&) override;
+ bool ShouldForceLegacyLayout() const final { return true; }
};
} // 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 c447e65414c..339453b3df8 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
@@ -23,7 +23,6 @@
#include "third_party/blink/renderer/core/html/html_script_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/script_event_listener.h"
#include "third_party/blink/renderer/core/dom/attribute.h"
@@ -35,6 +34,7 @@
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/script/script_loader.h"
#include "third_party/blink/renderer/core/script/script_runner.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -231,9 +231,4 @@ void HTMLScriptElement::Trace(blink::Visitor* visitor) {
ScriptElementBase::Trace(visitor);
}
-void HTMLScriptElement::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(loader_);
- HTMLElement::TraceWrappers(visitor);
-}
-
} // namespace blink
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 e163fc48278..b30157a1278 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
@@ -55,7 +55,6 @@ class CORE_EXPORT HTMLScriptElement final : public HTMLElement,
Document& GetDocument() const override;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
HTMLScriptElement(Document&, const CreateElementFlags);
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 0ff731c87e5..aae0b3cd9d5 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
@@ -34,6 +34,7 @@
#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/dom/events/event.h"
+#include "third_party/blink/renderer/core/dom/mutation_observer.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
@@ -412,6 +413,17 @@ Node::InsertionNotificationRequest HTMLSlotElement::InsertedInto(
if (root == insertion_point->ContainingShadowRoot()) {
// This slot is inserted into the same tree of |insertion_point|
root->DidAddSlot(*this);
+ } else if (RuntimeEnabledFeatures::IncrementalShadowDOMEnabled() &&
+ insertion_point->isConnected() &&
+ root->NeedsSlotAssignmentRecalc()) {
+ // Even when a slot and its containing shadow root is removed together
+ // and inserted together again, the slot's cached assigned nodes can be
+ // stale if the NeedsSlotAssignmentRecalc flag is set, and it may cause
+ // infinite recursion in DetachLayoutTree() when one of the stale node
+ // is a shadow-including ancestor of this slot by making a circular
+ // reference. Clear the cache here to avoid the situation.
+ // See http://crbug.com/849599 for details.
+ ClearAssignedNodesAndFlatTreeChildren();
}
}
return kInsertionDone;
@@ -440,10 +452,30 @@ void HTMLSlotElement::RemovedFrom(ContainerNode* insertion_point) {
// - For slot s2, s2.removedFrom(d) is called.
// ContainingShadowRoot() is okay to use here because 1) It doesn't use
- // kIsInShadowTreeFlag flag, and 2) TreeScope has been alreay updated for the
+ // kIsInShadowTreeFlag flag, and 2) TreeScope has been already updated for the
// slot.
- if (insertion_point->IsInV1ShadowTree() && !ContainingShadowRoot()) {
- // This slot was in a shadow tree and got disconnected from the shadow tree
+ if (ShadowRoot* shadow_root = ContainingShadowRoot()) {
+ // In this case, the shadow host (or its shadow-inclusive ancestor) was
+ // removed originally. In the above example, (this slot == s2) and
+ // (shadow_root == sr2). The shadow tree (sr2)'s structure didn't change at
+ // all.
+ if (RuntimeEnabledFeatures::IncrementalShadowDOMEnabled()) {
+ if (shadow_root->NeedsSlotAssignmentRecalc()) {
+ // Clear |assigned_nodes_| here, so that the referenced node can get
+ // garbage collected if they no longer needed. See also InsertedInto()'s
+ // comment for cases that stale |assigned_nodes| can be problematic.
+ ClearAssignedNodesAndFlatTreeChildren();
+ } else {
+ // We don't need to clear |assigned_nodes_| here. That's an important
+ // optimization.
+ }
+ } else {
+ ClearDistribution();
+ }
+ } else if (insertion_point->IsInV1ShadowTree()) {
+ // This slot was in a shadow tree and got disconnected from the shadow tree.
+ // In the above example, (this slot == s1), (insertion point == d)
+ // and (insertion_point->ContainingShadowRoot == sr1).
insertion_point->ContainingShadowRoot()->GetSlotAssignment().DidRemoveSlot(
*this);
if (RuntimeEnabledFeatures::IncrementalShadowDOMEnabled()) {
@@ -451,6 +483,8 @@ void HTMLSlotElement::RemovedFrom(ContainerNode* insertion_point) {
} else {
ClearDistribution();
}
+ } else {
+ DCHECK(assigned_nodes_.IsEmpty());
}
HTMLElement::RemovedFrom(insertion_point);
@@ -477,6 +511,14 @@ void HTMLSlotElement::DidRecalcStyle(StyleRecalcChange change) {
if (change < kIndependentInherit)
return;
for (auto& node : assigned_nodes_) {
+ if (change == kReattach && node->IsElementNode()) {
+ ToElement(node)->RecalcStyle(kReattach);
+ continue;
+ }
+ // We only need to pick up changes for inherited style, we do not actually
+ // need to match rules against this element but we do that for
+ // simplicity. If we ever stop doing this then we need to update
+ // StyleInvalidator::Invalidate as described in the comment there.
node->SetNeedsStyleRecalc(
kLocalStyleChange,
StyleChangeReasonForTracing::Create(
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 d3743d046b2..e9a7f683a4b 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
@@ -79,7 +79,7 @@ class CORE_EXPORT HTMLSlotElement final : public HTMLElement {
AtomicString GetName() const;
// This method can be slow because this has to traverse the children of a
- // shadow host. This method should be used only when m_assignedNodes is
+ // shadow host. This method should be used only when |assigned_nodes_| is
// dirty. e.g. To detect a slotchange event in DOM mutations.
bool HasAssignedNodesSlow() const;
bool FindHostChildWithSameSlotName() const;
diff --git a/chromium/third_party/blink/renderer/core/html/html_slot_element_test.cc b/chromium/third_party/blink/renderer/core/html/html_slot_element_test.cc
index 4bcc4c1d5a7..0dd92048504 100644
--- a/chromium/third_party/blink/renderer/core/html/html_slot_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_slot_element_test.cc
@@ -7,6 +7,8 @@
#include <array>
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/dom/shadow_root.h"
+#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
namespace blink {
@@ -128,4 +130,41 @@ TEST_F(HTMLSlotElementTest, TableSizeLimit) {
EXPECT_EQ(lcs, LongestCommonSubsequence(seq1, seq2));
}
+class HTMLSlotElementReattachTest : public testing::Test {
+ protected:
+ void SetUp() final {
+ dummy_page_holder_ = DummyPageHolder::Create(IntSize(800, 600));
+ }
+ Document& GetDocument() { return dummy_page_holder_->GetDocument(); }
+
+ private:
+ std::unique_ptr<DummyPageHolder> dummy_page_holder_;
+};
+
+TEST_F(HTMLSlotElementReattachTest, RecalcAssignedNodeStyleForReattach) {
+ GetDocument().body()->SetInnerHTMLFromString(R"HTML(
+ <div id='host'><span id='span'></span></div>
+ )HTML");
+
+ Element& host = *GetDocument().getElementById("host");
+ Element& span = *GetDocument().getElementById("span");
+
+ ShadowRoot& shadow_root =
+ host.AttachShadowRootInternal(ShadowRootType::kOpen);
+
+ shadow_root.SetInnerHTMLFromString(
+ R"HTML(<span><slot /></span>)HTML");
+
+ Element& shadow_span = *ToElement(shadow_root.firstChild());
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ shadow_span.setAttribute(HTMLNames::styleAttr, "display:block");
+
+ GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc);
+ GetDocument().documentElement()->RecalcStyle(kNoChange);
+
+ EXPECT_TRUE(shadow_span.GetNonAttachedStyle());
+ EXPECT_TRUE(span.GetNonAttachedStyle());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/html_source_element.cc b/chromium/third_party/blink/renderer/core/html/html_source_element.cc
index 58327a35662..ff13fd9afea 100644
--- a/chromium/third_party/blink/renderer/core/html/html_source_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_source_element.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/html/html_source_element.h"
#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/bindings/core/v8/usv_string_or_trusted_url.h"
#include "third_party/blink/renderer/core/css/media_list.h"
#include "third_party/blink/renderer/core/css/media_query_list.h"
#include "third_party/blink/renderer/core/css/media_query_matcher.h"
@@ -34,6 +35,7 @@
#include "third_party/blink/renderer/core/html/html_picture_element.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_url.h"
#define SOURCE_LOG_LEVEL 3
@@ -124,6 +126,11 @@ void HTMLSourceElement::SetSrc(const String& url) {
setAttribute(srcAttr, AtomicString(url));
}
+void HTMLSourceElement::SetSrc(const USVStringOrTrustedURL& usvStringOrURL,
+ ExceptionState& exception_state) {
+ setAttribute(srcAttr, usvStringOrURL, exception_state);
+}
+
const AtomicString& HTMLSourceElement::type() const {
return getAttribute(typeAttr);
}
diff --git a/chromium/third_party/blink/renderer/core/html/html_source_element.h b/chromium/third_party/blink/renderer/core/html/html_source_element.h
index 6d2cabd2da9..5d6fe8c704d 100644
--- a/chromium/third_party/blink/renderer/core/html/html_source_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_source_element.h
@@ -33,6 +33,8 @@
namespace blink {
+class USVStringOrTrustedURL;
+class ExceptionState;
class HTMLSourceElement final : public HTMLElement {
DEFINE_WRAPPERTYPEINFO();
@@ -44,6 +46,7 @@ class HTMLSourceElement final : public HTMLElement {
const AtomicString& type() const;
void SetSrc(const String&);
+ void SetSrc(const USVStringOrTrustedURL&, ExceptionState&);
void setType(const AtomicString&);
void ScheduleErrorEvent();
diff --git a/chromium/third_party/blink/renderer/core/html/html_source_element.idl b/chromium/third_party/blink/renderer/core/html/html_source_element.idl
index 82d94e153a2..1c51502078b 100644
--- a/chromium/third_party/blink/renderer/core/html/html_source_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/html_source_element.idl
@@ -26,7 +26,7 @@
// https://html.spec.whatwg.org/#the-source-element
[HTMLConstructor]
interface HTMLSourceElement : HTMLElement {
- [CEReactions, Reflect, URL] attribute USVString src;
+ [CEReactions, Reflect, URL, RaisesException=Setter] attribute URLString src;
[CEReactions] attribute DOMString type;
// https://html.spec.whatwg.org/#the-source-element-when-used-with-the-picture-element
diff --git a/chromium/third_party/blink/renderer/core/html/html_style_element.cc b/chromium/third_party/blink/renderer/core/html/html_style_element.cc
index 11a2f2c76a4..9822de60262 100644
--- a/chromium/third_party/blink/renderer/core/html/html_style_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_style_element.cc
@@ -77,7 +77,14 @@ void HTMLStyleElement::FinishParsingChildren() {
Node::InsertionNotificationRequest HTMLStyleElement::InsertedInto(
ContainerNode* insertion_point) {
HTMLElement::InsertedInto(insertion_point);
- return kInsertionShouldCallDidNotifySubtreeInsertions;
+ if (isConnected()) {
+ if (StyleElement::ProcessStyleSheet(GetDocument(), *this) ==
+ StyleElement::kProcessingFatalError) {
+ NotifyLoadedSheetAndAllCriticalSubresources(
+ kErrorOccurredLoadingSubresource);
+ }
+ }
+ return kInsertionDone;
}
void HTMLStyleElement::RemovedFrom(ContainerNode* insertion_point) {
@@ -85,13 +92,6 @@ void HTMLStyleElement::RemovedFrom(ContainerNode* insertion_point) {
StyleElement::RemovedFrom(*this, insertion_point);
}
-void HTMLStyleElement::DidNotifySubtreeInsertionsToDocument() {
- if (StyleElement::ProcessStyleSheet(GetDocument(), *this) ==
- StyleElement::kProcessingFatalError)
- NotifyLoadedSheetAndAllCriticalSubresources(
- kErrorOccurredLoadingSubresource);
-}
-
void HTMLStyleElement::ChildrenChanged(const ChildrenChange& change) {
HTMLElement::ChildrenChanged(change);
if (StyleElement::ChildrenChanged(*this) ==
diff --git a/chromium/third_party/blink/renderer/core/html/html_style_element.h b/chromium/third_party/blink/renderer/core/html/html_style_element.h
index b5e1b4bed0c..c8b672683f3 100644
--- a/chromium/third_party/blink/renderer/core/html/html_style_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_style_element.h
@@ -56,7 +56,6 @@ class CORE_EXPORT HTMLStyleElement final : public HTMLElement,
// overload from HTMLElement
void ParseAttribute(const AttributeModificationParams&) override;
InsertionNotificationRequest InsertedInto(ContainerNode*) override;
- void DidNotifySubtreeInsertionsToDocument() override;
void RemovedFrom(ContainerNode*) override;
void ChildrenChanged(const ChildrenChange&) override;
diff --git a/chromium/third_party/blink/renderer/core/html/html_summary_element.cc b/chromium/third_party/blink/renderer/core/html/html_summary_element.cc
index 865fb24cd53..0a7063bb35f 100644
--- a/chromium/third_party/blink/renderer/core/html/html_summary_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_summary_element.cc
@@ -20,7 +20,6 @@
#include "third_party/blink/renderer/core/html/html_summary_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/events/keyboard_event.h"
@@ -30,6 +29,8 @@
#include "third_party/blink/renderer/core/html/shadow/shadow_element_names.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
+#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -55,7 +56,7 @@ LayoutObject* HTMLSummaryElement::CreateLayoutObject(
display == EDisplay::kLayoutCustom ||
display == EDisplay::kInlineLayoutCustom)
return LayoutObject::CreateObject(this, style);
- return new LayoutBlockFlow(this);
+ return LayoutObjectFactory::CreateBlockFlow(*this, style);
}
void HTMLSummaryElement::DidAddUserAgentShadowRoot(ShadowRoot& root) {
diff --git a/chromium/third_party/blink/renderer/core/html/html_summary_element.h b/chromium/third_party/blink/renderer/core/html/html_summary_element.h
index d6b37ad51c9..081f9b0909f 100644
--- a/chromium/third_party/blink/renderer/core/html/html_summary_element.h
+++ b/chromium/third_party/blink/renderer/core/html/html_summary_element.h
@@ -39,7 +39,6 @@ class HTMLSummaryElement final : public HTMLElement {
explicit HTMLSummaryElement(Document&);
LayoutObject* CreateLayoutObject(const ComputedStyle&) override;
- bool ShouldForceLegacyLayout() const final { return true; }
void DefaultEventHandler(Event*) override;
bool HasActivationBehavior() const override;
void DidAddUserAgentShadowRoot(ShadowRoot&) override;
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 6f31786003b..85c52c066af 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
@@ -25,7 +25,6 @@
#include "third_party/blink/renderer/core/html/html_table_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_image_value.h"
#include "third_party/blink/renderer/core/css/css_inherited_value.h"
@@ -35,7 +34,6 @@
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/dom/attribute.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/node_lists_node_data.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/html/html_table_caption_element.h"
@@ -45,6 +43,7 @@
#include "third_party/blink/renderer/core/html/html_table_section_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/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/weborigin/referrer.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
@@ -88,7 +87,7 @@ HTMLTableSectionElement* HTMLTableElement::tHead() const {
void HTMLTableElement::setTHead(HTMLTableSectionElement* new_head,
ExceptionState& exception_state) {
if (new_head && !new_head->HasTagName(theadTag)) {
- exception_state.ThrowDOMException(kHierarchyRequestError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kHierarchyRequestError,
"Not a thead element.");
return;
}
@@ -115,7 +114,7 @@ HTMLTableSectionElement* HTMLTableElement::tFoot() const {
void HTMLTableElement::setTFoot(HTMLTableSectionElement* new_foot,
ExceptionState& exception_state) {
if (new_foot && !new_foot->HasTagName(tfootTag)) {
- exception_state.ThrowDOMException(kHierarchyRequestError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kHierarchyRequestError,
"Not a tfoot element.");
return;
}
@@ -184,7 +183,7 @@ HTMLTableRowElement* HTMLTableElement::insertRow(
ExceptionState& exception_state) {
if (index < -1) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
"The index provided (" + String::Number(index) + ") is less than -1.");
return nullptr;
}
@@ -199,7 +198,7 @@ HTMLTableRowElement* HTMLTableElement::insertRow(
if (!row) {
if (i != index) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
"The index provided (" + String::Number(index) +
") is greater than the number of rows in the table (" +
String::Number(i) + ").");
@@ -234,7 +233,7 @@ HTMLTableRowElement* HTMLTableElement::insertRow(
void HTMLTableElement::deleteRow(int index, ExceptionState& exception_state) {
if (index < -1) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
"The index provided (" + String::Number(index) + ") is less than -1.");
return;
}
@@ -254,7 +253,7 @@ void HTMLTableElement::deleteRow(int index, ExceptionState& exception_state) {
}
if (!row) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
"The index provided (" + String::Number(index) +
") is greater than the number of rows in the table (" +
String::Number(i) + ").");
@@ -349,9 +348,9 @@ void HTMLTableElement::CollectStyleForPresentationAttribute(
if (!value.IsEmpty()) {
if (DeprecatedEqualIgnoringCase(value, "center")) {
AddPropertyToPresentationAttributeStyle(
- style, CSSPropertyWebkitMarginStart, CSSValueAuto);
+ style, CSSPropertyMarginInlineStart, CSSValueAuto);
AddPropertyToPresentationAttributeStyle(
- style, CSSPropertyWebkitMarginEnd, CSSValueAuto);
+ style, CSSPropertyMarginInlineEnd, CSSValueAuto);
} else {
AddPropertyToPresentationAttributeStyle(style, CSSPropertyFloat, value);
}
diff --git a/chromium/third_party/blink/renderer/core/html/html_table_row_element.cc b/chromium/third_party/blink/renderer/core/html/html_table_row_element.cc
index f6a39a0fbbf..7b248e833a4 100644
--- a/chromium/third_party/blink/renderer/core/html/html_table_row_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_table_row_element.cc
@@ -25,9 +25,7 @@
#include "third_party/blink/renderer/core/html/html_table_row_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/node_lists_node_data.h"
#include "third_party/blink/renderer/core/html/html_collection.h"
#include "third_party/blink/renderer/core/html/html_table_cell_element.h"
@@ -35,6 +33,7 @@
#include "third_party/blink/renderer/core/html/html_table_rows_collection.h"
#include "third_party/blink/renderer/core/html/html_table_section_element.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -97,9 +96,9 @@ HTMLElement* HTMLTableRowElement::insertCell(int index,
int num_cells = children ? children->length() : 0;
if (index < -1 || index > num_cells) {
exception_state.ThrowDOMException(
- kIndexSizeError, "The value provided (" + String::Number(index) +
- ") is outside the range [-1, " +
- String::Number(num_cells) + "].");
+ DOMExceptionCode::kIndexSizeError,
+ "The value provided (" + String::Number(index) +
+ ") is outside the range [-1, " + String::Number(num_cells) + "].");
return nullptr;
}
@@ -120,9 +119,9 @@ void HTMLTableRowElement::deleteCell(int index,
// elements in the cells collection, then throw "IndexSizeError".
if (index < -1 || index >= num_cells) {
exception_state.ThrowDOMException(
- kIndexSizeError, "The value provided (" + String::Number(index) +
- ") is outside the range [0, " +
- String::Number(num_cells) + ").");
+ DOMExceptionCode::kIndexSizeError,
+ "The value provided (" + String::Number(index) +
+ ") is outside the range [0, " + String::Number(num_cells) + ").");
return;
}
// 2. If index is −1, remove the last element in the cells collection
diff --git a/chromium/third_party/blink/renderer/core/html/html_table_section_element.cc b/chromium/third_party/blink/renderer/core/html/html_table_section_element.cc
index 915834389da..640ee3942ea 100644
--- a/chromium/third_party/blink/renderer/core/html/html_table_section_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_table_section_element.cc
@@ -24,14 +24,13 @@
#include "third_party/blink/renderer/core/html/html_table_section_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/node_lists_node_data.h"
#include "third_party/blink/renderer/core/html/html_collection.h"
#include "third_party/blink/renderer/core/html/html_table_element.h"
#include "third_party/blink/renderer/core/html/html_table_row_element.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -60,9 +59,9 @@ HTMLElement* HTMLTableSectionElement::insertRow(
int num_rows = children ? static_cast<int>(children->length()) : 0;
if (index < -1 || index > num_rows) {
exception_state.ThrowDOMException(
- kIndexSizeError, "The provided index (" + String::Number(index) +
- " is outside the range [-1, " +
- String::Number(num_rows) + "].");
+ DOMExceptionCode::kIndexSizeError,
+ "The provided index (" + String::Number(index) +
+ " is outside the range [-1, " + String::Number(num_rows) + "].");
return nullptr;
}
@@ -88,9 +87,9 @@ void HTMLTableSectionElement::deleteRow(int index,
HTMLElement::RemoveChild(row, exception_state);
} else {
exception_state.ThrowDOMException(
- kIndexSizeError, "The provided index (" + String::Number(index) +
- " is outside the range [-1, " +
- String::Number(num_rows) + "].");
+ DOMExceptionCode::kIndexSizeError,
+ "The provided index (" + String::Number(index) +
+ " is outside the range [-1, " + String::Number(num_rows) + "].");
}
}
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 9502271d6d3..dc64c22fa32 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
@@ -76,9 +76,4 @@ void HTMLTemplateElement::Trace(blink::Visitor* visitor) {
HTMLElement::Trace(visitor);
}
-void HTMLTemplateElement::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(content_);
- HTMLElement::TraceWrappers(visitor);
-}
-
} // namespace blink
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 558624ca29e..3bee834fcea 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
@@ -52,8 +52,6 @@ class CORE_EXPORT HTMLTemplateElement final : public HTMLElement {
DocumentFragment* content() const;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
private:
void CloneNonAttributePropertiesFrom(const Element&,
CloneChildrenFlag) override;
diff --git a/chromium/third_party/blink/renderer/core/html/html_title_element.cc b/chromium/third_party/blink/renderer/core/html/html_title_element.cc
index 5941f983727..e2bfb87b6f1 100644
--- a/chromium/third_party/blink/renderer/core/html/html_title_element.cc
+++ b/chromium/third_party/blink/renderer/core/html/html_title_element.cc
@@ -23,11 +23,11 @@
#include "third_party/blink/renderer/core/html/html_title_element.h"
#include "base/auto_reset.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/child_list_mutation_scope.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/html_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/html/image_document.cc b/chromium/third_party/blink/renderer/core/html/image_document.cc
index 90c49f4d2e7..746d734590f 100644
--- a/chromium/third_party/blink/renderer/core/html/image_document.cc
+++ b/chromium/third_party/blink/renderer/core/html/image_document.cc
@@ -25,7 +25,6 @@
#include "third_party/blink/renderer/core/html/image_document.h"
#include <limits>
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
#include "third_party/blink/renderer/core/dom/raw_data_document_parser.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
@@ -51,6 +50,8 @@
#include "third_party/blink/renderer/core/loader/frame_loader.h"
#include "third_party/blink/renderer/core/loader/resource/image_resource.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/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/platform_chrome_client.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -353,7 +354,7 @@ void ImageDocument::ImageClicked(int x, int y) {
float scroll_y = (image_y * device_scale_factor) / scale -
static_cast<float>(GetFrame()->View()->Height()) / 2;
- GetFrame()->View()->LayoutViewportScrollableArea()->SetScrollOffset(
+ GetFrame()->View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(scroll_x, scroll_y), kProgrammaticScroll);
}
}
@@ -454,7 +455,8 @@ int ImageDocument::CalculateDivWidth() {
// of the frame.
// * Images smaller in either dimension are centered along that axis.
int viewport_width =
- GetFrame()->GetPage()->GetVisualViewport().Size().Width();
+ GetFrame()->GetPage()->GetVisualViewport().Size().Width() /
+ GetFrame()->PageZoomFactor();
// For huge images, minimum-scale=0.1 is still too big on small screens.
// Set the <div> width so that the image will shrink to fit the width of the
diff --git a/chromium/third_party/blink/renderer/core/html/image_document.h b/chromium/third_party/blink/renderer/core/html/image_document.h
index 1b057b15efc..67321223da9 100644
--- a/chromium/third_party/blink/renderer/core/html/image_document.h
+++ b/chromium/third_party/blink/renderer/core/html/image_document.h
@@ -96,6 +96,9 @@ class CORE_EXPORT ImageDocument final : public HTMLDocument {
enum ShrinkToFitMode { kViewport, kDesktop };
ShrinkToFitMode shrink_to_fit_mode_;
+
+ FRIEND_TEST_ALL_PREFIXES(ImageDocumentViewportTest, ZoomForDSFScaleImage);
+ FRIEND_TEST_ALL_PREFIXES(ImageDocumentViewportTest, DivWidthWithZoomForDSF);
};
DEFINE_DOCUMENT_TYPE_CASTS(ImageDocument);
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 abd0fde6c8c..97a78a6a961 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
@@ -7,11 +7,13 @@
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.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/document_parser.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/loader/empty_clients.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.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"
@@ -223,22 +225,16 @@ TEST_F(ImageDocumentTest, MAYBE(ImageCenteredAtDeviceScaleFactor)) {
EXPECT_TRUE(GetDocument().ShouldShrinkToFit());
GetDocument().ImageClicked(15, 27);
- ScrollOffset offset = GetDocument()
- .GetFrame()
- ->View()
- ->LayoutViewportScrollableArea()
- ->GetScrollOffset();
+ ScrollOffset offset =
+ GetDocument().GetFrame()->View()->LayoutViewport()->GetScrollOffset();
EXPECT_EQ(22, offset.Width());
EXPECT_EQ(42, offset.Height());
GetDocument().ImageClicked(20, 20);
GetDocument().ImageClicked(12, 15);
- offset = GetDocument()
- .GetFrame()
- ->View()
- ->LayoutViewportScrollableArea()
- ->GetScrollOffset();
+ offset =
+ GetDocument().GetFrame()->View()->LayoutViewport()->GetScrollOffset();
EXPECT_EQ(11, offset.Width());
EXPECT_EQ(22, offset.Height());
}
@@ -310,5 +306,99 @@ TEST_F(ImageDocumentViewportTest, HidingURLBarDoesntChangeImageLocation) {
EXPECT_EQ(175, rect->y());
}
+TEST_F(ImageDocumentViewportTest, ZoomForDSFScaleImage) {
+ v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
+ SimRequest request("https://example.com/test.jpg", "image/jpeg");
+ LoadURL("https://example.com/test.jpg");
+
+ Vector<unsigned char> jpeg = JpegImage();
+ Vector<char> data = Vector<char>();
+ data.Append(jpeg.data(), jpeg.size());
+ request.Complete(data);
+
+ HTMLImageElement* img = GetDocument().ImageElement();
+
+ // no zoom
+ WebView().Resize(IntSize(100, 100));
+ WebView().SetZoomFactorForDeviceScaleFactor(1.f);
+ Compositor().BeginFrame();
+ EXPECT_EQ(50u, img->width());
+ EXPECT_EQ(50u, img->height());
+ EXPECT_EQ(100, GetDocument().CalculateDivWidth());
+ EXPECT_EQ(1.f, GetVisualViewport().Scale());
+ EXPECT_EQ(100, GetVisualViewport().Width());
+ EXPECT_EQ(100, GetVisualViewport().Height());
+
+ // zoom-for-dsf = 4. WebView size is in physical pixel(400*400), image and
+ // visual viewport should be same in CSS pixel, as no dsf applied.
+ // This simulates running on two phones with different screen densities but
+ // same (physical) screen size, image document should displayed the same.
+ WebView().Resize(IntSize(400, 400));
+ WebView().SetZoomFactorForDeviceScaleFactor(4.f);
+ Compositor().BeginFrame();
+ EXPECT_EQ(50u, img->width());
+ EXPECT_EQ(50u, img->height());
+ EXPECT_EQ(100, GetDocument().CalculateDivWidth());
+ EXPECT_EQ(1.f, GetVisualViewport().Scale());
+ EXPECT_EQ(100, GetVisualViewport().Width());
+ EXPECT_EQ(100, GetVisualViewport().Height());
+}
+
+// Tests that with zoom factor for device scale factor, image with different
+// size fit in the viewport correctly.
+TEST_F(ImageDocumentViewportTest, DivWidthWithZoomForDSF) {
+ v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
+ SimRequest request("https://example.com/test.jpg", "image/jpeg");
+ LoadURL("https://example.com/test.jpg");
+
+ Vector<unsigned char> jpeg = JpegImage();
+ Vector<char> data = Vector<char>();
+ data.Append(jpeg.data(), jpeg.size());
+ request.Complete(data);
+
+ HTMLImageElement* img = GetDocument().ImageElement();
+
+ WebView().SetZoomFactorForDeviceScaleFactor(2.f);
+
+ // Image smaller then webview size, visual viewport is not zoomed, and image
+ // will be centered in the viewport.
+ WebView().Resize(IntSize(200, 200));
+ Compositor().BeginFrame();
+ EXPECT_EQ(50u, img->width());
+ EXPECT_EQ(50u, img->height());
+ EXPECT_EQ(100, GetDocument().CalculateDivWidth());
+ EXPECT_EQ(1.f, GetVisualViewport().Scale());
+ EXPECT_EQ(100, GetVisualViewport().Width());
+ EXPECT_EQ(100, GetVisualViewport().Height());
+ DOMRect* rect = img->getBoundingClientRect();
+ EXPECT_EQ(25, rect->x());
+ EXPECT_EQ(25, rect->y());
+
+ // Image wider than webview size, image should fill the visual viewport, and
+ // visual viewport zoom out to 0.5.
+ WebView().Resize(IntSize(50, 50));
+ Compositor().BeginFrame();
+ EXPECT_EQ(50u, img->width());
+ EXPECT_EQ(50u, img->height());
+ EXPECT_EQ(50, GetDocument().CalculateDivWidth());
+ EXPECT_EQ(0.5f, GetVisualViewport().Scale());
+ EXPECT_EQ(50, GetVisualViewport().Width());
+ EXPECT_EQ(50, GetVisualViewport().Height());
+
+ // When image is more than 10X wider than webview, shrink the image to fit the
+ // width of the screen.
+ WebView().Resize(IntSize(4, 20));
+ Compositor().BeginFrame();
+ EXPECT_EQ(20u, img->width());
+ EXPECT_EQ(20u, img->height());
+ EXPECT_EQ(20, GetDocument().CalculateDivWidth());
+ EXPECT_EQ(0.1f, GetVisualViewport().Scale());
+ EXPECT_EQ(20, GetVisualViewport().Width());
+ EXPECT_EQ(100, GetVisualViewport().Height());
+ rect = img->getBoundingClientRect();
+ EXPECT_EQ(0, rect->x());
+ EXPECT_EQ(40, rect->y());
+}
+
#undef MAYBE
} // namespace blink
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 6a211bea7b1..3d83cdfceef 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
@@ -33,6 +33,7 @@
#include <memory>
#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/document_init.h"
#include "third_party/blink/renderer/core/dom/document_parser.h"
#include "third_party/blink/renderer/core/html/custom/v0_custom_element_sync_microtask_queue.h"
#include "third_party/blink/renderer/core/html/html_document.h"
diff --git a/chromium/third_party/blink/renderer/core/html/imports/html_import_tree_root.cc b/chromium/third_party/blink/renderer/core/html/imports/html_import_tree_root.cc
index d095216213b..be259e347cb 100644
--- a/chromium/third_party/blink/renderer/core/html/imports/html_import_tree_root.cc
+++ b/chromium/third_party/blink/renderer/core/html/imports/html_import_tree_root.cc
@@ -87,8 +87,4 @@ void HTMLImportTreeRoot::Trace(blink::Visitor* visitor) {
HTMLImport::Trace(visitor);
}
-void HTMLImportTreeRoot::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(document_);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/imports/html_import_tree_root.h b/chromium/third_party/blink/renderer/core/html/imports/html_import_tree_root.h
index 502061c8e95..825fbb294ec 100644
--- a/chromium/third_party/blink/renderer/core/html/imports/html_import_tree_root.h
+++ b/chromium/third_party/blink/renderer/core/html/imports/html_import_tree_root.h
@@ -7,7 +7,7 @@
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/html/imports/html_import.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/timer.h"
@@ -16,7 +16,7 @@ namespace blink {
class HTMLImportChild;
class KURL;
-class HTMLImportTreeRoot final : public HTMLImport, public TraceWrapperBase {
+class HTMLImportTreeRoot final : public HTMLImport, public NameClient {
public:
static HTMLImportTreeRoot* Create(Document*);
@@ -35,7 +35,6 @@ class HTMLImportTreeRoot final : public HTMLImport, public TraceWrapperBase {
HTMLImportChild* Find(const KURL&) const;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "HTMLImportTreeRoot";
}
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 12830470013..b609bfc96fd 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
@@ -147,9 +147,4 @@ void HTMLImportsController::Trace(blink::Visitor* visitor) {
visitor->Trace(loaders_);
}
-void HTMLImportsController::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(root_);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/imports/html_imports_controller.h b/chromium/third_party/blink/renderer/core/html/imports/html_imports_controller.h
index d16cacfe246..6e4da83c167 100644
--- a/chromium/third_party/blink/renderer/core/html/imports/html_imports_controller.h
+++ b/chromium/third_party/blink/renderer/core/html/imports/html_imports_controller.h
@@ -32,7 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_IMPORTS_HTML_IMPORTS_CONTROLLER_H_
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -49,7 +49,7 @@ class KURL;
class HTMLImportsController final
: public GarbageCollected<HTMLImportsController>,
- public TraceWrapperBase {
+ public NameClient {
public:
static HTMLImportsController* Create(Document& master) {
return new HTMLImportsController(master);
@@ -72,7 +72,6 @@ class HTMLImportsController final
void Dispose();
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "HTMLImportsController";
}
diff --git a/chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc b/chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc
new file mode 100644
index 00000000000..4c4f9b2a756
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc
@@ -0,0 +1,360 @@
+// 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/html/lazy_load_frame_observer.h"
+
+#include <limits>
+
+#include "base/metrics/histogram_macros.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/frame.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/geometry/dom_rect_read_only.h"
+#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
+#include "third_party/blink/renderer/core/intersection_observer/intersection_observer.h"
+#include "third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h"
+#include "third_party/blink/renderer/core/loader/frame_load_request.h"
+#include "third_party/blink/renderer/core/loader/frame_loader.h"
+#include "third_party/blink/renderer/platform/heap/visitor.h"
+#include "third_party/blink/renderer/platform/length.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+namespace {
+
+// Determine if the |bounding_client_rect| for a frame indicates that the frame
+// is probably hidden according to some experimental heuristics. Since hidden
+// frames are often used for analytics or communication, and lazily loading them
+// could break their functionality, so these heuristics are used to recognize
+// likely hidden frames and immediately load them so that they can function
+// properly.
+bool IsFrameProbablyHidden(const DOMRectReadOnly& bounding_client_rect) {
+ // Tiny frames that are 4x4 or smaller are likely not intended to be seen by
+ // the user. Note that this condition includes frames marked as
+ // "display:none", since those frames would have dimensions of 0x0.
+ if (bounding_client_rect.width() < 4.1 || bounding_client_rect.height() < 4.1)
+ return true;
+
+ // Frames that are positioned completely off the page above or to the left are
+ // likely never intended to be visible to the user.
+ if (bounding_client_rect.right() < 0.0 || bounding_client_rect.bottom() < 0.0)
+ return true;
+
+ return false;
+}
+
+int GetLazyFrameLoadingViewportDistanceThresholdPx(const Document& document) {
+ const Settings* settings = document.GetSettings();
+ if (!settings)
+ return 0;
+
+ DCHECK(document.GetFrame() && document.GetFrame()->Client());
+ switch (document.GetFrame()->Client()->GetEffectiveConnectionType()) {
+ case WebEffectiveConnectionType::kTypeUnknown:
+ return settings->GetLazyFrameLoadingDistanceThresholdPxUnknown();
+ case WebEffectiveConnectionType::kTypeOffline:
+ return settings->GetLazyFrameLoadingDistanceThresholdPxOffline();
+ case WebEffectiveConnectionType::kTypeSlow2G:
+ return settings->GetLazyFrameLoadingDistanceThresholdPxSlow2G();
+ case WebEffectiveConnectionType::kType2G:
+ return settings->GetLazyFrameLoadingDistanceThresholdPx2G();
+ case WebEffectiveConnectionType::kType3G:
+ return settings->GetLazyFrameLoadingDistanceThresholdPx3G();
+ case WebEffectiveConnectionType::kType4G:
+ return settings->GetLazyFrameLoadingDistanceThresholdPx4G();
+ }
+ NOTREACHED();
+ return 0;
+}
+
+} // namespace
+
+LazyLoadFrameObserver::LazyLoadFrameObserver(HTMLFrameOwnerElement& element)
+ : element_(&element) {}
+
+void LazyLoadFrameObserver::DeferLoadUntilNearViewport(
+ const ResourceRequest& resource_request,
+ WebFrameLoadType frame_load_type) {
+ DCHECK(!lazy_load_intersection_observer_);
+ was_recorded_as_deferred_ = false;
+
+ lazy_load_intersection_observer_ = IntersectionObserver::Create(
+ {Length(GetLazyFrameLoadingViewportDistanceThresholdPx(
+ element_->GetDocument()),
+ kFixed)},
+ {std::numeric_limits<float>::min()}, &element_->GetDocument(),
+ WTF::BindRepeating(&LazyLoadFrameObserver::LoadIfHiddenOrNearViewport,
+ WrapWeakPersistent(this), resource_request,
+ frame_load_type));
+
+ lazy_load_intersection_observer_->observe(element_);
+}
+
+void LazyLoadFrameObserver::CancelPendingLazyLoad() {
+ if (!lazy_load_intersection_observer_)
+ return;
+ lazy_load_intersection_observer_->disconnect();
+ lazy_load_intersection_observer_.Clear();
+}
+
+void LazyLoadFrameObserver::LoadIfHiddenOrNearViewport(
+ const ResourceRequest& resource_request,
+ WebFrameLoadType frame_load_type,
+ const HeapVector<Member<IntersectionObserverEntry>>& entries) {
+ DCHECK(!entries.IsEmpty());
+ DCHECK_EQ(element_, entries.back()->target());
+
+ if (entries.back()->isIntersecting()) {
+ RecordInitialDeferralAction(
+ FrameInitialDeferralAction::kLoadedNearOrInViewport);
+ } else if (IsFrameProbablyHidden(*entries.back()->boundingClientRect())) {
+ RecordInitialDeferralAction(FrameInitialDeferralAction::kLoadedHidden);
+ } else {
+ RecordInitialDeferralAction(FrameInitialDeferralAction::kDeferred);
+ return;
+ }
+
+ if (was_recorded_as_deferred_) {
+ DCHECK(element_->GetDocument().GetFrame());
+ DCHECK(element_->GetDocument().GetFrame()->Client());
+
+ UMA_HISTOGRAM_ENUMERATION(
+ "Blink.LazyLoad.CrossOriginFrames.LoadStartedAfterBeingDeferred",
+ element_->GetDocument()
+ .GetFrame()
+ ->Client()
+ ->GetEffectiveConnectionType());
+ }
+
+ // The content frame of the element should not have changed, since any
+ // pending lazy load should have been already been cancelled in
+ // DisconnectContentFrame() if the content frame changes.
+ DCHECK(element_->ContentFrame());
+
+ // Note that calling FrameLoader::Load() causes the
+ // |lazy_load_intersection_observer| to be disconnected.
+ ToLocalFrame(element_->ContentFrame())
+ ->Loader()
+ .StartNavigation(
+ FrameLoadRequest(&element_->GetDocument(), resource_request),
+ frame_load_type);
+}
+
+void LazyLoadFrameObserver::StartTrackingVisibilityMetrics() {
+ DCHECK(time_when_first_visible_.is_null());
+ DCHECK(!visibility_metrics_observer_);
+
+ visibility_metrics_observer_ = IntersectionObserver::Create(
+ {}, {std::numeric_limits<float>::min()}, &element_->GetDocument(),
+ WTF::BindRepeating(
+ &LazyLoadFrameObserver::RecordMetricsOnVisibilityChanged,
+ WrapWeakPersistent(this)));
+
+ visibility_metrics_observer_->observe(element_);
+}
+
+void LazyLoadFrameObserver::RecordMetricsOnVisibilityChanged(
+ const HeapVector<Member<IntersectionObserverEntry>>& entries) {
+ DCHECK(!entries.IsEmpty());
+ DCHECK_EQ(element_, entries.back()->target());
+
+ if (IsFrameProbablyHidden(*entries.back()->boundingClientRect())) {
+ visibility_metrics_observer_->disconnect();
+ visibility_metrics_observer_.Clear();
+ return;
+ }
+
+ if (!has_above_the_fold_been_set_) {
+ is_initially_above_the_fold_ = entries.back()->isIntersecting();
+ has_above_the_fold_been_set_ = true;
+ }
+
+ if (!entries.back()->isIntersecting())
+ return;
+
+ DCHECK(time_when_first_visible_.is_null());
+ time_when_first_visible_ = CurrentTimeTicks();
+ RecordVisibilityMetricsIfLoadedAndVisible();
+
+ visibility_metrics_observer_->disconnect();
+ visibility_metrics_observer_.Clear();
+
+ // The below metrics require getting the effective connection type from the
+ // parent frame, so return early here if there's no parent frame to get the
+ // effective connection type from.
+ if (!element_->GetDocument().GetFrame())
+ return;
+
+ DCHECK(element_->GetDocument().GetFrame()->Client());
+
+ // On slow networks, iframes might not finish loading by the time the user
+ // leaves the page, so the visible load time metrics samples won't represent
+ // the slowest frames. To remedy this, record how often below the fold
+ // lazyload-eligible frames become visible before they've finished loading.
+ // This isn't recorded for above the fold frames since basically every above
+ // the fold frame would be visible before they finish loading.
+ if (time_when_first_load_finished_.is_null() &&
+ !is_initially_above_the_fold_) {
+ // Note: If the WebEffectiveConnectionType enum ever gets out of sync with
+ // net::EffectiveConnectionType, then this will have to be updated to record
+ // the sample in terms of net::EffectiveConnectionType instead of
+ // WebEffectiveConnectionType.
+ UMA_HISTOGRAM_ENUMERATION(
+ "Blink.VisibleBeforeLoaded.LazyLoadEligibleFrames.BelowTheFold",
+ element_->GetDocument()
+ .GetFrame()
+ ->Client()
+ ->GetEffectiveConnectionType());
+ }
+
+ if (was_recorded_as_deferred_) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Blink.LazyLoad.CrossOriginFrames.VisibleAfterBeingDeferred",
+ element_->GetDocument()
+ .GetFrame()
+ ->Client()
+ ->GetEffectiveConnectionType());
+ }
+}
+
+void LazyLoadFrameObserver::RecordMetricsOnLoadFinished() {
+ if (!time_when_first_load_finished_.is_null())
+ return;
+ time_when_first_load_finished_ = CurrentTimeTicks();
+ RecordVisibilityMetricsIfLoadedAndVisible();
+}
+
+void LazyLoadFrameObserver::RecordVisibilityMetricsIfLoadedAndVisible() {
+ if (time_when_first_load_finished_.is_null() ||
+ time_when_first_visible_.is_null() ||
+ !element_->GetDocument().GetFrame()) {
+ return;
+ }
+
+ DCHECK(has_above_the_fold_been_set_);
+
+ TimeDelta visible_load_delay =
+ time_when_first_load_finished_ - time_when_first_visible_;
+ if (visible_load_delay < TimeDelta())
+ visible_load_delay = TimeDelta();
+
+ switch (element_->GetDocument()
+ .GetFrame()
+ ->Client()
+ ->GetEffectiveConnectionType()) {
+ case WebEffectiveConnectionType::kTypeSlow2G:
+ if (is_initially_above_the_fold_) {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Blink.VisibleLoadTime.LazyLoadEligibleFrames.AboveTheFold.Slow2G",
+ visible_load_delay);
+ } else {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Blink.VisibleLoadTime.LazyLoadEligibleFrames.BelowTheFold.Slow2G",
+ visible_load_delay);
+ }
+ break;
+
+ case WebEffectiveConnectionType::kType2G:
+ if (is_initially_above_the_fold_) {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Blink.VisibleLoadTime.LazyLoadEligibleFrames.AboveTheFold.2G",
+ visible_load_delay);
+ } else {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Blink.VisibleLoadTime.LazyLoadEligibleFrames.BelowTheFold.2G",
+ visible_load_delay);
+ }
+ break;
+
+ case WebEffectiveConnectionType::kType3G:
+ if (is_initially_above_the_fold_) {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Blink.VisibleLoadTime.LazyLoadEligibleFrames.AboveTheFold.3G",
+ visible_load_delay);
+ } else {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Blink.VisibleLoadTime.LazyLoadEligibleFrames.BelowTheFold.3G",
+ visible_load_delay);
+ }
+ break;
+
+ case WebEffectiveConnectionType::kType4G:
+ if (is_initially_above_the_fold_) {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Blink.VisibleLoadTime.LazyLoadEligibleFrames.AboveTheFold.4G",
+ visible_load_delay);
+ } else {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "Blink.VisibleLoadTime.LazyLoadEligibleFrames.BelowTheFold.4G",
+ visible_load_delay);
+ }
+ break;
+
+ case WebEffectiveConnectionType::kTypeUnknown:
+ case WebEffectiveConnectionType::kTypeOffline:
+ // No VisibleLoadTime histograms are recorded for these effective
+ // connection types.
+ break;
+ }
+}
+
+void LazyLoadFrameObserver::RecordInitialDeferralAction(
+ FrameInitialDeferralAction action) {
+ if (was_recorded_as_deferred_)
+ return;
+
+ DCHECK(element_->GetDocument().GetFrame());
+ DCHECK(element_->GetDocument().GetFrame()->Client());
+
+ switch (element_->GetDocument()
+ .GetFrame()
+ ->Client()
+ ->GetEffectiveConnectionType()) {
+ case WebEffectiveConnectionType::kTypeUnknown:
+ UMA_HISTOGRAM_ENUMERATION(
+ "Blink.LazyLoad.CrossOriginFrames.InitialDeferralAction.Unknown",
+ action);
+ break;
+ case WebEffectiveConnectionType::kTypeOffline:
+ UMA_HISTOGRAM_ENUMERATION(
+ "Blink.LazyLoad.CrossOriginFrames.InitialDeferralAction.Offline",
+ action);
+ break;
+ case WebEffectiveConnectionType::kTypeSlow2G:
+ UMA_HISTOGRAM_ENUMERATION(
+ "Blink.LazyLoad.CrossOriginFrames.InitialDeferralAction.Slow2G",
+ action);
+ break;
+ case WebEffectiveConnectionType::kType2G:
+ UMA_HISTOGRAM_ENUMERATION(
+ "Blink.LazyLoad.CrossOriginFrames.InitialDeferralAction.2G", action);
+ break;
+ case WebEffectiveConnectionType::kType3G:
+ UMA_HISTOGRAM_ENUMERATION(
+ "Blink.LazyLoad.CrossOriginFrames.InitialDeferralAction.3G", action);
+ break;
+ case WebEffectiveConnectionType::kType4G:
+ UMA_HISTOGRAM_ENUMERATION(
+ "Blink.LazyLoad.CrossOriginFrames.InitialDeferralAction.4G", action);
+ break;
+ }
+
+ if (action == FrameInitialDeferralAction::kDeferred)
+ was_recorded_as_deferred_ = true;
+}
+
+void LazyLoadFrameObserver::Trace(blink::Visitor* visitor) {
+ visitor->Trace(element_);
+ visitor->Trace(lazy_load_intersection_observer_);
+ visitor->Trace(visibility_metrics_observer_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer.h b/chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer.h
new file mode 100644
index 00000000000..248e38f1cfe
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer.h
@@ -0,0 +1,93 @@
+// 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_HTML_LAZY_LOAD_FRAME_OBSERVER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_LAZY_LOAD_FRAME_OBSERVER_H_
+
+#include "third_party/blink/public/web/web_frame_load_type.h"
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
+#include "third_party/blink/renderer/platform/heap/member.h"
+#include "third_party/blink/renderer/platform/wtf/time.h"
+
+namespace blink {
+
+class IntersectionObserver;
+class IntersectionObserverEntry;
+class HTMLFrameOwnerElement;
+class ResourceRequest;
+class Visitor;
+
+class LazyLoadFrameObserver : public GarbageCollected<LazyLoadFrameObserver> {
+ public:
+ // This enum is logged to histograms, so values should not be reordered or
+ // reused, and it must match the corresponding enum
+ // "LazyLoad.FrameInitialDeferralAction" in
+ // tools/metrics/histograms/enums.xml.
+ enum class FrameInitialDeferralAction {
+ // The frame was not loaded immediately, and the load continued to be
+ // deferred.
+ kDeferred = 0,
+ // The frame was either visible or near enough to the viewport that it was
+ // loaded immediately.
+ kLoadedNearOrInViewport = 1,
+ // The frame was determined to likely be a hidden frame (e.g. analytics or
+ // communication iframes), so it was loaded immediately.
+ kLoadedHidden = 2,
+
+ kMaxValue = kLoadedHidden
+ };
+
+ explicit LazyLoadFrameObserver(HTMLFrameOwnerElement&);
+
+ void DeferLoadUntilNearViewport(const ResourceRequest&, WebFrameLoadType);
+ bool IsLazyLoadPending() const { return lazy_load_intersection_observer_; }
+ void CancelPendingLazyLoad();
+
+ void StartTrackingVisibilityMetrics();
+ void RecordMetricsOnLoadFinished();
+
+ void Trace(blink::Visitor*);
+
+ private:
+ void LoadIfHiddenOrNearViewport(
+ const ResourceRequest&,
+ WebFrameLoadType,
+ const HeapVector<Member<IntersectionObserverEntry>>&);
+
+ void RecordMetricsOnVisibilityChanged(
+ const HeapVector<Member<IntersectionObserverEntry>>&);
+
+ void RecordVisibilityMetricsIfLoadedAndVisible();
+ void RecordInitialDeferralAction(FrameInitialDeferralAction);
+
+ const Member<HTMLFrameOwnerElement> element_;
+
+ // The intersection observer responsible for loading the frame once it's near
+ // the viewport.
+ Member<IntersectionObserver> lazy_load_intersection_observer_;
+
+ // Used to record visibility-related metrics related to lazy load. This is an
+ // IntersectionObserver instead of just an ElementVisibilityObserver so that
+ // hidden frames can be detected in order to avoid recording metrics for them.
+ Member<IntersectionObserver> visibility_metrics_observer_;
+
+ // Keeps track of whether this frame was initially visible on the page.
+ bool is_initially_above_the_fold_ = false;
+ bool has_above_the_fold_been_set_ = false;
+
+ // Set when the frame first becomes visible (i.e. appears in the viewport).
+ TimeTicks time_when_first_visible_;
+ // Set when the first load event is dispatched for the frame.
+ TimeTicks time_when_first_load_finished_;
+
+ // Keeps track of whether the frame was initially recorded as having been
+ // deferred, so that the appropriate histograms can be recorded if the frame
+ // later gets loaded in for some reason.
+ bool was_recorded_as_deferred_ = false;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_LAZY_LOAD_FRAME_OBSERVER_H_
diff --git a/chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer_test.cc b/chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer_test.cc
new file mode 100644
index 00000000000..f987c930f60
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/lazy_load_frame_observer_test.cc
@@ -0,0 +1,739 @@
+// 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/html/lazy_load_frame_observer.h"
+
+#include <algorithm>
+#include <memory>
+#include <tuple>
+
+#include "third_party/blink/public/platform/web_effective_connection_type.h"
+#include "third_party/blink/renderer/core/exported/web_view_impl.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/paint/paint_layer_scrollable_area.h"
+#include "third_party/blink/renderer/core/testing/sim/sim_compositor.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/float_rect.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"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+namespace {
+
+constexpr std::pair<WebEffectiveConnectionType, const char*>
+ kVisibleLoadTimeAboveTheFoldHistogramNames[] = {
+ {WebEffectiveConnectionType::kTypeSlow2G,
+ "Blink.VisibleLoadTime.LazyLoadEligibleFrames.AboveTheFold.Slow2G"},
+ {WebEffectiveConnectionType::kType2G,
+ "Blink.VisibleLoadTime.LazyLoadEligibleFrames.AboveTheFold.2G"},
+ {WebEffectiveConnectionType::kType3G,
+ "Blink.VisibleLoadTime.LazyLoadEligibleFrames.AboveTheFold.3G"},
+ {WebEffectiveConnectionType::kType4G,
+ "Blink.VisibleLoadTime.LazyLoadEligibleFrames.AboveTheFold.4G"},
+};
+
+constexpr std::pair<WebEffectiveConnectionType, const char*>
+ kVisibleLoadTimeBelowTheFoldHistogramNames[] = {
+ {WebEffectiveConnectionType::kTypeSlow2G,
+ "Blink.VisibleLoadTime.LazyLoadEligibleFrames.BelowTheFold.Slow2G"},
+ {WebEffectiveConnectionType::kType2G,
+ "Blink.VisibleLoadTime.LazyLoadEligibleFrames.BelowTheFold.2G"},
+ {WebEffectiveConnectionType::kType3G,
+ "Blink.VisibleLoadTime.LazyLoadEligibleFrames.BelowTheFold.3G"},
+ {WebEffectiveConnectionType::kType4G,
+ "Blink.VisibleLoadTime.LazyLoadEligibleFrames.BelowTheFold.4G"},
+};
+
+constexpr std::pair<WebEffectiveConnectionType, const char*>
+ kInitialDeferralActionHistogramNames[] = {
+ {WebEffectiveConnectionType::kTypeUnknown,
+ "Blink.LazyLoad.CrossOriginFrames.InitialDeferralAction.Unknown"},
+ {WebEffectiveConnectionType::kTypeOffline,
+ "Blink.LazyLoad.CrossOriginFrames.InitialDeferralAction.Offline"},
+ {WebEffectiveConnectionType::kTypeSlow2G,
+ "Blink.LazyLoad.CrossOriginFrames.InitialDeferralAction.Slow2G"},
+ {WebEffectiveConnectionType::kType2G,
+ "Blink.LazyLoad.CrossOriginFrames.InitialDeferralAction.2G"},
+ {WebEffectiveConnectionType::kType3G,
+ "Blink.LazyLoad.CrossOriginFrames.InitialDeferralAction.3G"},
+ {WebEffectiveConnectionType::kType4G,
+ "Blink.LazyLoad.CrossOriginFrames.InitialDeferralAction.4G"},
+};
+
+// Convenience enums to make it easy to access the appropriate value of the
+// tuple parameters in the parameterized tests below, e.g. so that
+// std::get<LazyFrameLoadingFeatureStatus>(GetParam()) can be used instead of
+// std::get<0>(GetParam()) if they were just booleans.
+enum class LazyFrameLoadingFeatureStatus { kDisabled, kEnabled };
+enum class LazyFrameVisibleLoadTimeFeatureStatus { kDisabled, kEnabled };
+
+class LazyLoadFramesTest : public SimTest,
+ public ::testing::WithParamInterface<
+ std::tuple<LazyFrameLoadingFeatureStatus,
+ LazyFrameVisibleLoadTimeFeatureStatus,
+ WebEffectiveConnectionType>> {
+ public:
+ static constexpr int kViewportWidth = 800;
+ static constexpr int kViewportHeight = 600;
+
+ LazyLoadFramesTest()
+ : scoped_lazy_frame_loading_for_test_(
+ std::get<LazyFrameLoadingFeatureStatus>(GetParam()) ==
+ LazyFrameLoadingFeatureStatus::kEnabled),
+ scoped_lazy_frame_visible_load_time_metrics_for_test_(
+ std::get<LazyFrameVisibleLoadTimeFeatureStatus>(GetParam()) ==
+ LazyFrameVisibleLoadTimeFeatureStatus::kEnabled) {}
+
+ void SetUp() override {
+ SetEffectiveConnectionTypeForTesting(
+ std::get<WebEffectiveConnectionType>(GetParam()));
+
+ SimTest::SetUp();
+ WebView().Resize(WebSize(kViewportWidth, kViewportHeight));
+
+ Settings& settings = WebView().GetPage()->GetSettings();
+
+ // These should match the values that would be returned by
+ // GetLoadingDistanceThreshold().
+ settings.SetLazyFrameLoadingDistanceThresholdPxUnknown(200);
+ settings.SetLazyFrameLoadingDistanceThresholdPxOffline(300);
+ settings.SetLazyFrameLoadingDistanceThresholdPxSlow2G(400);
+ settings.SetLazyFrameLoadingDistanceThresholdPx2G(500);
+ settings.SetLazyFrameLoadingDistanceThresholdPx3G(600);
+ settings.SetLazyFrameLoadingDistanceThresholdPx4G(700);
+ }
+
+ int GetLoadingDistanceThreshold() const {
+ static constexpr int kDistanceThresholdByEffectiveConnectionType[] = {
+ 200, 300, 400, 500, 600, 700};
+ return kDistanceThresholdByEffectiveConnectionType[static_cast<int>(
+ std::get<WebEffectiveConnectionType>(GetParam()))];
+ }
+
+ void ExpectVisibleLoadTimeHistogramSamplesIfApplicable(
+ int expected_above_the_fold_count,
+ int expected_below_the_fold_count) {
+ if (!RuntimeEnabledFeatures::LazyFrameVisibleLoadTimeMetricsEnabled()) {
+ // Expect zero samples if the visible load time metrics feature is
+ // disabled.
+ expected_above_the_fold_count = 0;
+ expected_below_the_fold_count = 0;
+ }
+
+ for (const auto& pair : kVisibleLoadTimeAboveTheFoldHistogramNames) {
+ histogram_tester()->ExpectTotalCount(
+ pair.second,
+ std::get<WebEffectiveConnectionType>(GetParam()) == pair.first
+ ? expected_above_the_fold_count
+ : 0);
+ }
+ for (const auto& pair : kVisibleLoadTimeBelowTheFoldHistogramNames) {
+ histogram_tester()->ExpectTotalCount(
+ pair.second,
+ std::get<WebEffectiveConnectionType>(GetParam()) == pair.first
+ ? expected_below_the_fold_count
+ : 0);
+ }
+ }
+
+ void ExpectInitialDeferralActionHistogramSamplesIfApplicable(
+ LazyLoadFrameObserver::FrameInitialDeferralAction action,
+ int expected_count) {
+ for (const auto& pair : kInitialDeferralActionHistogramNames) {
+ if (RuntimeEnabledFeatures::LazyFrameLoadingEnabled() &&
+ std::get<WebEffectiveConnectionType>(GetParam()) == pair.first) {
+ histogram_tester()->ExpectUniqueSample(
+ pair.second, static_cast<int>(action), expected_count);
+ } else {
+ histogram_tester()->ExpectTotalCount(pair.second, 0);
+ }
+ }
+ }
+
+ void ExpectLoadStartedAfterDeferredSamplesIfApplicable(int expected_count) {
+ if (RuntimeEnabledFeatures::LazyFrameLoadingEnabled()) {
+ histogram_tester()->ExpectUniqueSample(
+ "Blink.LazyLoad.CrossOriginFrames.LoadStartedAfterBeingDeferred",
+ static_cast<int>(std::get<WebEffectiveConnectionType>(GetParam())),
+ expected_count);
+ } else {
+ histogram_tester()->ExpectTotalCount(
+ "Blink.LazyLoad.CrossOriginFrames.LoadStartedAfterBeingDeferred", 0);
+ }
+ }
+
+ void ExpectVisibleAfterDeferredSamplesIfApplicable(int expected_count) {
+ if (RuntimeEnabledFeatures::LazyFrameLoadingEnabled() &&
+ RuntimeEnabledFeatures::LazyFrameVisibleLoadTimeMetricsEnabled()) {
+ histogram_tester()->ExpectUniqueSample(
+ "Blink.LazyLoad.CrossOriginFrames.VisibleAfterBeingDeferred",
+ static_cast<int>(std::get<WebEffectiveConnectionType>(GetParam())),
+ expected_count);
+ } else {
+ histogram_tester()->ExpectTotalCount(
+ "Blink.LazyLoad.CrossOriginFrames.VisibleAfterBeingDeferred", 0);
+ }
+ }
+
+ HistogramTester* histogram_tester() { return &histogram_tester_; }
+
+ // Convenience function to load a page with a cross origin frame far down the
+ // page such that it's not near the viewport.
+ std::unique_ptr<SimRequest> LoadPageWithCrossOriginFrameFarFromViewport() {
+ SimRequest main_resource("https://example.com/", "text/html");
+ std::unique_ptr<SimRequest> child_frame_resource;
+
+ if (!RuntimeEnabledFeatures::LazyFrameLoadingEnabled()) {
+ // This SimRequest needs to be created now if the frame won't actually be
+ // lazily loaded. Otherwise, it'll be defined later to ensure that the
+ // subframe resource isn't requested until the page is scrolled down.
+ child_frame_resource.reset(
+ new SimRequest("https://crossorigin.com/subframe.html", "text/html"));
+ }
+
+ LoadURL("https://example.com/");
+
+ main_resource.Complete(String::Format(
+ R"HTML(
+ <body onload='console.log("main body onload");'>
+ <div style='height: %dpx;'></div>
+ <iframe src='https://crossorigin.com/subframe.html'
+ style='width: 400px; height: 400px;'
+ onload='console.log("child frame element onload");'></iframe>
+ </body>)HTML",
+ kViewportHeight + GetLoadingDistanceThreshold() + 100));
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ // If the child frame is being lazy loaded, then the body's load event
+ // should have already fired.
+ EXPECT_EQ(RuntimeEnabledFeatures::LazyFrameLoadingEnabled(),
+ ConsoleMessages().Contains("main body onload"));
+ EXPECT_FALSE(ConsoleMessages().Contains("child frame element onload"));
+
+ ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 0);
+
+ ExpectInitialDeferralActionHistogramSamplesIfApplicable(
+ LazyLoadFrameObserver::FrameInitialDeferralAction::kDeferred, 1);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.LazyLoad.CrossOriginFrames.LoadStartedAfterBeingDeferred", 0);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.LazyLoad.CrossOriginFrames.VisibleAfterBeingDeferred", 0);
+
+ if (!child_frame_resource) {
+ child_frame_resource.reset(
+ new SimRequest("https://crossorigin.com/subframe.html", "text/html"));
+ }
+
+ return child_frame_resource;
+ }
+
+ private:
+ ScopedLazyFrameLoadingForTest scoped_lazy_frame_loading_for_test_;
+ ScopedLazyFrameVisibleLoadTimeMetricsForTest
+ scoped_lazy_frame_visible_load_time_metrics_for_test_;
+
+ HistogramTester histogram_tester_;
+};
+
+TEST_P(LazyLoadFramesTest, SameOriginFrame) {
+ SimRequest main_resource("https://example.com/", "text/html");
+ SimRequest child_frame_resource("https://example.com/subframe.html",
+ "text/html");
+
+ LoadURL("https://example.com/");
+
+ main_resource.Complete(String::Format(
+ R"HTML(
+ <body onload='console.log("main body onload");'>
+ <div style='height: %dpx;'></div>
+ <iframe src='https://example.com/subframe.html'
+ style='width: 200px; height: 200px;'
+ onload='console.log("child frame element onload");'></iframe>
+ </body>)HTML",
+ kViewportHeight + GetLoadingDistanceThreshold() + 100));
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ child_frame_resource.Complete("");
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload"));
+
+ ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 0);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.VisibleBeforeLoaded.LazyLoadEligibleFrames.BelowTheFold", 0);
+
+ for (const auto& pair : kInitialDeferralActionHistogramNames)
+ histogram_tester()->ExpectTotalCount(pair.second, 0);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.LazyLoad.CrossOriginFrames.LoadStartedAfterBeingDeferred", 0);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.LazyLoad.CrossOriginFrames.VisibleAfterBeingDeferred", 0);
+}
+
+TEST_P(LazyLoadFramesTest, AboveTheFoldFrame) {
+ SimRequest main_resource("https://example.com/", "text/html");
+ SimRequest child_frame_resource("https://crossorigin.com/subframe.html",
+ "text/html");
+
+ LoadURL("https://example.com/");
+
+ main_resource.Complete(String::Format(
+ R"HTML(
+ <body onload='console.log("main body onload");'>
+ <div style='height: %dpx;'></div>
+ <iframe src='https://crossorigin.com/subframe.html'
+ style='width: 200px; height: 200px;'
+ onload='console.log("child frame element onload");'></iframe>
+ </body>)HTML",
+ kViewportHeight - 100));
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ // The child frame is visible, but hasn't finished loading yet, so no visible
+ // load time samples should have been recorded yet.
+ ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 0);
+
+ child_frame_resource.Complete("");
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload"));
+
+ ExpectVisibleLoadTimeHistogramSamplesIfApplicable(1, 0);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.VisibleBeforeLoaded.LazyLoadEligibleFrames.BelowTheFold", 0);
+
+ ExpectInitialDeferralActionHistogramSamplesIfApplicable(
+ LazyLoadFrameObserver::FrameInitialDeferralAction::
+ kLoadedNearOrInViewport,
+ 1);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.LazyLoad.CrossOriginFrames.LoadStartedAfterBeingDeferred", 0);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.LazyLoad.CrossOriginFrames.VisibleAfterBeingDeferred", 0);
+}
+
+TEST_P(LazyLoadFramesTest, BelowTheFoldButNearViewportFrame) {
+ SimRequest main_resource("https://example.com/", "text/html");
+ SimRequest child_frame_resource("https://crossorigin.com/subframe.html",
+ "text/html");
+
+ LoadURL("https://example.com/");
+
+ main_resource.Complete(String::Format(
+ R"HTML(
+ <body onload='console.log("main body onload");'>
+ <div style='height: %dpx;'></div>
+ <iframe src='https://crossorigin.com/subframe.html'
+ style='width: 200px; height: 200px;'
+ onload='console.log("child frame element onload");'></iframe>
+ </body>)HTML",
+ kViewportHeight + 100));
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ child_frame_resource.Complete("");
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload"));
+
+ // The frame is below the fold, but hasn't been scrolled down to yet, so there
+ // should be no samples in any of the below the fold visible load time
+ // histograms yet.
+ ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 0);
+
+ // Scroll down until the child frame is visible.
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 150),
+ kProgrammaticScroll);
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 1);
+
+ // The frame finished loading before it became visible, so there should be no
+ // samples in the VisibleBeforeLoaded histogram.
+ histogram_tester()->ExpectTotalCount(
+ "Blink.VisibleBeforeLoaded.LazyLoadEligibleFrames.BelowTheFold", 0);
+
+ ExpectInitialDeferralActionHistogramSamplesIfApplicable(
+ LazyLoadFrameObserver::FrameInitialDeferralAction::
+ kLoadedNearOrInViewport,
+ 1);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.LazyLoad.CrossOriginFrames.LoadStartedAfterBeingDeferred", 0);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.LazyLoad.CrossOriginFrames.VisibleAfterBeingDeferred", 0);
+}
+
+TEST_P(LazyLoadFramesTest, HiddenAndTinyFrames) {
+ SimRequest main_resource("https://example.com/", "text/html");
+
+ SimRequest display_none_frame_resource(
+ "https://crossorigin.com/display_none.html", "text/html");
+ SimRequest tiny_frame_resource("https://crossorigin.com/tiny.html",
+ "text/html");
+ SimRequest tiny_width_frame_resource(
+ "https://crossorigin.com/tiny_width.html", "text/html");
+ SimRequest tiny_height_frame_resource(
+ "https://crossorigin.com/tiny_height.html", "text/html");
+ SimRequest off_screen_left_frame_resource(
+ "https://crossorigin.com/off_screen_left.html", "text/html");
+ SimRequest off_screen_top_frame_resource(
+ "https://crossorigin.com/off_screen_top.html", "text/html");
+
+ LoadURL("https://example.com/");
+
+ main_resource.Complete(String::Format(
+ R"HTML(
+ <head><style>
+ /* Chrome by default sets borders for iframes, so explicitly specify
+ * no borders, padding, or margins here so that the dimensions of the
+ * tiny frames aren't artifically inflated past the dimensions that
+ * the lazy loading logic considers "tiny". */
+ iframe { border-style: none; padding: 0px; margin: 0px; }
+ </style></head>
+
+ <body onload='console.log("main body onload");'>
+ <div style='height: %dpx'></div>
+ <iframe src='https://crossorigin.com/display_none.html'
+ style='display: none;'
+ onload='console.log("display none element onload");'></iframe>
+ <iframe src='https://crossorigin.com/tiny.html'
+ style='width: 4px; height: 4px;'
+ onload='console.log("tiny element onload");'></iframe>
+ <iframe src='https://crossorigin.com/tiny_width.html'
+ style='width: 0px; height: 50px;'
+ onload='console.log("tiny width element onload");'></iframe>
+ <iframe src='https://crossorigin.com/tiny_height.html'
+ style='width: 50px; height: 0px;'
+ onload='console.log("tiny height element onload");'></iframe>
+ <iframe src='https://crossorigin.com/off_screen_left.html'
+ style='position:relative;right:9000px;width:50px;height:50px;'
+ onload='console.log("off screen left element onload");'></iframe>
+ <iframe src='https://crossorigin.com/off_screen_top.html'
+ style='position:relative;bottom:9000px;width:50px;height:50px;'
+ onload='console.log("off screen top element onload");'></iframe>
+ </body>
+ )HTML",
+ kViewportHeight + GetLoadingDistanceThreshold() + 100));
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ display_none_frame_resource.Complete("");
+ tiny_frame_resource.Complete("");
+ tiny_width_frame_resource.Complete("");
+ tiny_height_frame_resource.Complete("");
+ off_screen_left_frame_resource.Complete("");
+ off_screen_top_frame_resource.Complete("");
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("display none element onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("tiny element onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("tiny width element onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("tiny height element onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("off screen left element onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("off screen top element onload"));
+
+ ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 0);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.VisibleBeforeLoaded.LazyLoadEligibleFrames.BelowTheFold", 0);
+
+ // Scroll down to where the hidden frames are.
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(0, kViewportHeight + GetLoadingDistanceThreshold()),
+ kProgrammaticScroll);
+
+ // All of the frames on the page are hidden or tiny, so no visible load time
+ // samples should have been recorded for them.
+ ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 0);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.VisibleBeforeLoaded.LazyLoadEligibleFrames.BelowTheFold", 0);
+
+ ExpectInitialDeferralActionHistogramSamplesIfApplicable(
+ LazyLoadFrameObserver::FrameInitialDeferralAction::kLoadedHidden, 6);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.LazyLoad.CrossOriginFrames.LoadStartedAfterBeingDeferred", 0);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.LazyLoad.CrossOriginFrames.VisibleAfterBeingDeferred", 0);
+}
+
+TEST_P(LazyLoadFramesTest, LoadCrossOriginFrameFarFromViewport) {
+ std::unique_ptr<SimRequest> child_frame_resource =
+ LoadPageWithCrossOriginFrameFarFromViewport();
+
+ if (RuntimeEnabledFeatures::LazyFrameLoadingEnabled()) {
+ // If LazyFrameLoading is enabled, then scroll down near the child frame to
+ // cause the child frame to start loading.
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(0, 150), kProgrammaticScroll);
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+ }
+
+ EXPECT_FALSE(ConsoleMessages().Contains("child frame element onload"));
+ ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 0);
+
+ ExpectInitialDeferralActionHistogramSamplesIfApplicable(
+ LazyLoadFrameObserver::FrameInitialDeferralAction::kDeferred, 1);
+ ExpectLoadStartedAfterDeferredSamplesIfApplicable(1);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.LazyLoad.CrossOriginFrames.VisibleAfterBeingDeferred", 0);
+
+ child_frame_resource->Complete("");
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload"));
+ ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 0);
+
+ // Scroll down so that the child frame is visible.
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(0, GetLoadingDistanceThreshold() + 150),
+ kProgrammaticScroll);
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload"));
+ ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 1);
+
+ histogram_tester()->ExpectTotalCount(
+ "Blink.VisibleBeforeLoaded.LazyLoadEligibleFrames.BelowTheFold", 0);
+
+ ExpectInitialDeferralActionHistogramSamplesIfApplicable(
+ LazyLoadFrameObserver::FrameInitialDeferralAction::kDeferred, 1);
+ ExpectLoadStartedAfterDeferredSamplesIfApplicable(1);
+ ExpectVisibleAfterDeferredSamplesIfApplicable(1);
+}
+
+TEST_P(LazyLoadFramesTest,
+ CrossOriginFrameFarFromViewportBecomesVisibleBeforeFinishedLoading) {
+ std::unique_ptr<SimRequest> child_frame_resource =
+ LoadPageWithCrossOriginFrameFarFromViewport();
+
+ // Scroll down so that the child frame is visible.
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(0, GetLoadingDistanceThreshold() + 150),
+ kProgrammaticScroll);
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ EXPECT_FALSE(ConsoleMessages().Contains("child frame element onload"));
+ ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 0);
+
+ if (RuntimeEnabledFeatures::LazyFrameVisibleLoadTimeMetricsEnabled()) {
+ // Even though the child frame hasn't loaded yet, a sample should still have
+ // been recorded for VisibleBeforeLoaded.
+ histogram_tester()->ExpectUniqueSample(
+ "Blink.VisibleBeforeLoaded.LazyLoadEligibleFrames.BelowTheFold",
+ static_cast<int>(std::get<WebEffectiveConnectionType>(GetParam())), 1);
+ } else {
+ histogram_tester()->ExpectTotalCount(
+ "Blink.VisibleBeforeLoaded.LazyLoadEligibleFrames.BelowTheFold", 0);
+ }
+
+ ExpectInitialDeferralActionHistogramSamplesIfApplicable(
+ LazyLoadFrameObserver::FrameInitialDeferralAction::kDeferred, 1);
+ ExpectLoadStartedAfterDeferredSamplesIfApplicable(1);
+ ExpectVisibleAfterDeferredSamplesIfApplicable(1);
+
+ child_frame_resource->Complete("");
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload"));
+ ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 1);
+
+ // The samples recorded for VisibleBeforeLoaded should be unchanged.
+ histogram_tester()->ExpectTotalCount(
+ "Blink.VisibleBeforeLoaded.LazyLoadEligibleFrames.BelowTheFold",
+ RuntimeEnabledFeatures::LazyFrameVisibleLoadTimeMetricsEnabled() ? 1 : 0);
+
+ ExpectInitialDeferralActionHistogramSamplesIfApplicable(
+ LazyLoadFrameObserver::FrameInitialDeferralAction::kDeferred, 1);
+ ExpectLoadStartedAfterDeferredSamplesIfApplicable(1);
+ ExpectVisibleAfterDeferredSamplesIfApplicable(1);
+}
+
+TEST_P(LazyLoadFramesTest, NestedFrameInCrossOriginFrameFarFromViewport) {
+ std::unique_ptr<SimRequest> child_frame_resource =
+ LoadPageWithCrossOriginFrameFarFromViewport();
+
+ if (RuntimeEnabledFeatures::LazyFrameLoadingEnabled()) {
+ // If LazyFrameLoading is enabled, then scroll down near the child frame to
+ // cause the child frame to start loading.
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(0, 150), kProgrammaticScroll);
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+ }
+
+ // There's another nested cross origin iframe inside the first child frame,
+ // even further down such that it's not near the viewport. It should start
+ // loading immediately, even if LazyFrameLoading is enabled, since it's nested
+ // inside a frame that was previously deferred.
+ SimRequest nested_frame_resource("https://test.com/", "text/html");
+ child_frame_resource->Complete(String::Format(
+ "<div style='height: %dpx;'></div>"
+ "<iframe src='https://test.com/' style='width: 200px; height: 200px;'>"
+ "</iframe>",
+ kViewportHeight + GetLoadingDistanceThreshold() + 100));
+
+ nested_frame_resource.Complete("");
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload"));
+
+ // The child frame isn't visible, so no visible load time samples should have
+ // been recorded.
+ ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 0);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.VisibleBeforeLoaded.LazyLoadEligibleFrames.BelowTheFold", 0);
+
+ ExpectInitialDeferralActionHistogramSamplesIfApplicable(
+ LazyLoadFrameObserver::FrameInitialDeferralAction::kDeferred, 1);
+ ExpectLoadStartedAfterDeferredSamplesIfApplicable(1);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.LazyLoad.CrossOriginFrames.VisibleAfterBeingDeferred", 0);
+}
+
+TEST_P(LazyLoadFramesTest, AboutBlankChildFrameNavigation) {
+ SimRequest main_resource("https://example.com/", "text/html");
+ SimRequest child_frame_resource("https://crossorigin.com/subframe.html",
+ "text/html");
+
+ LoadURL("https://example.com/");
+
+ main_resource.Complete(String::Format(
+ R"HTML(
+ <body onload='BodyOnload()'>
+ <script>
+ function BodyOnload() {
+ console.log('main body onload');
+ document.getElementsByTagName('iframe')[0].src =
+ 'https://crossorigin.com/subframe.html';
+ }
+ </script>
+
+ <div style='height: %dpx;'></div>
+ <iframe
+ style='width: 200px; height: 200px;'
+ onload='console.log("child frame element onload");'></iframe>
+ </body>)HTML",
+ kViewportHeight + GetLoadingDistanceThreshold() + 100));
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+ EXPECT_EQ(1, static_cast<int>(std::count(ConsoleMessages().begin(),
+ ConsoleMessages().end(),
+ "child frame element onload")));
+
+ child_frame_resource.Complete("");
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ EXPECT_EQ(2, static_cast<int>(std::count(ConsoleMessages().begin(),
+ ConsoleMessages().end(),
+ "child frame element onload")));
+
+ ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 0);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.VisibleBeforeLoaded.LazyLoadEligibleFrames.BelowTheFold", 0);
+
+ for (const auto& pair : kInitialDeferralActionHistogramNames)
+ histogram_tester()->ExpectTotalCount(pair.second, 0);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.LazyLoad.CrossOriginFrames.LoadStartedAfterBeingDeferred", 0);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.LazyLoad.CrossOriginFrames.VisibleAfterBeingDeferred", 0);
+}
+
+TEST_P(LazyLoadFramesTest, JavascriptStringFrameUrl) {
+ SimRequest main_resource("https://example.com/", "text/html");
+ LoadURL("https://example.com/");
+
+ main_resource.Complete(String::Format(
+ R"HTML(
+ <body onload='console.log("main body onload");'>
+ <div style='height: %dpx;'></div>
+ <iframe src='javascript:"Hello World!";'
+ style='width: 200px; height: 200px;'
+ onload='console.log("child frame element onload");'></iframe>
+ </body>)HTML",
+ kViewportHeight + GetLoadingDistanceThreshold() + 100));
+
+ EXPECT_TRUE(ConsoleMessages().Contains("main body onload"));
+ EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload"));
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 0);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.VisibleBeforeLoaded.LazyLoadEligibleFrames.BelowTheFold", 0);
+
+ for (const auto& pair : kInitialDeferralActionHistogramNames)
+ histogram_tester()->ExpectTotalCount(pair.second, 0);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.LazyLoad.CrossOriginFrames.LoadStartedAfterBeingDeferred", 0);
+ histogram_tester()->ExpectTotalCount(
+ "Blink.LazyLoad.CrossOriginFrames.VisibleAfterBeingDeferred", 0);
+}
+
+INSTANTIATE_TEST_CASE_P(
+ LazyFrameLoading,
+ LazyLoadFramesTest,
+ ::testing::Combine(
+ ::testing::Values(LazyFrameLoadingFeatureStatus::kDisabled,
+ LazyFrameLoadingFeatureStatus::kEnabled),
+ ::testing::Values(LazyFrameVisibleLoadTimeFeatureStatus::kDisabled,
+ LazyFrameVisibleLoadTimeFeatureStatus::kEnabled),
+ ::testing::Values(WebEffectiveConnectionType::kTypeUnknown,
+ WebEffectiveConnectionType::kTypeOffline,
+ WebEffectiveConnectionType::kTypeSlow2G,
+ WebEffectiveConnectionType::kType2G,
+ WebEffectiveConnectionType::kType3G,
+ WebEffectiveConnectionType::kType4G)));
+
+} // namespace
+
+} // namespace blink
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 823de94e28c..86d9cc83d45 100644
--- a/chromium/third_party/blink/renderer/core/html/link_style.cc
+++ b/chromium/third_party/blink/renderer/core/html/link_style.cc
@@ -12,12 +12,11 @@
#include "third_party/blink/renderer/core/html/cross_origin_attribute.h"
#include "third_party/blink/renderer/core/html/html_link_element.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/core/loader/importance_attribute.h"
#include "third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.h"
#include "third_party/blink/renderer/core/loader/subresource_integrity_helper.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/loader/subresource_integrity.h"
#include "third_party/blink/renderer/platform/network/mime/content_type.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
@@ -253,14 +252,12 @@ void LinkStyle::SetCrossOriginStylesheetStatus(CSSStyleSheet* sheet) {
fetch_following_cors_ = false;
}
-// TODO(yoav): move that logic to LinkLoader
LinkStyle::LoadReturnValue LinkStyle::LoadStylesheetIfNeeded(
- const KURL& url,
- const WTF::TextEncoding& charset,
- const String& type) {
+ const LinkLoadParameters& params,
+ const WTF::TextEncoding& charset) {
if (disabled_state_ == kDisabled || !owner_->RelAttribute().IsStyleSheet() ||
- !StyleSheetTypeIsSupported(type) || !ShouldLoadResource() ||
- !url.IsValid())
+ !StyleSheetTypeIsSupported(params.type) || !ShouldLoadResource() ||
+ !params.href.IsValid())
return kNotNeeded;
if (GetResource()) {
@@ -294,44 +291,18 @@ LinkStyle::LoadReturnValue LinkStyle::LoadStylesheetIfNeeded(
owner_->IsCreatedByParser();
AddPendingSheet(blocking ? kBlocking : kNonBlocking);
- ResourceRequest resource_request(GetDocument().CompleteURL(url));
- ReferrerPolicy referrer_policy = owner_->GetReferrerPolicy();
- if (referrer_policy != kReferrerPolicyDefault) {
- resource_request.SetHTTPReferrer(SecurityPolicy::GenerateReferrer(
- referrer_policy, url, GetDocument().OutgoingReferrer()));
+ if (params.cross_origin != kCrossOriginAttributeNotSet) {
+ SetFetchFollowingCORS();
}
- ResourceLoaderOptions options;
- options.initiator_info.name = owner_->localName();
- FetchParameters params(resource_request, options);
- params.SetCharset(charset);
-
// Load stylesheets that are not needed for the layout immediately with low
// priority. When the link element is created by scripts, load the
// stylesheets asynchronously but in high priority.
- if (!media_query_matches || owner_->IsAlternate())
- params.SetDefer(FetchParameters::kLazyLoad);
+ FetchParameters::DeferOption defer_option =
+ !media_query_matches || owner_->IsAlternate() ? FetchParameters::kLazyLoad
+ : FetchParameters::kNoDefer;
- params.SetContentSecurityPolicyNonce(owner_->nonce());
-
- CrossOriginAttributeValue cross_origin =
- GetCrossOriginAttributeValue(owner_->FastGetAttribute(crossoriginAttr));
- if (cross_origin != kCrossOriginAttributeNotSet) {
- params.SetCrossOriginAccessControl(GetDocument().GetSecurityOrigin(),
- cross_origin);
- SetFetchFollowingCORS();
- }
-
- String integrity_attr = owner_->FastGetAttribute(integrityAttr);
- if (!integrity_attr.IsEmpty()) {
- IntegrityMetadataSet metadata_set;
- SubresourceIntegrity::ParseIntegrityAttribute(
- integrity_attr, SubresourceIntegrityHelper::GetFeatures(&GetDocument()),
- metadata_set);
- params.SetIntegrityMetadata(metadata_set);
- params.MutableResourceRequest().SetFetchIntegrity(integrity_attr);
- }
- CSSStyleSheetResource::Fetch(params, GetDocument().Fetcher(), this);
+ owner_->LoadStylesheet(params, charset, defer_option, this);
if (loading_ && !GetResource()) {
// Fetch() synchronous failure case.
@@ -353,7 +324,8 @@ void LinkStyle::Process() {
GetCrossOriginAttributeValue(owner_->FastGetAttribute(crossoriginAttr)),
owner_->TypeValue().DeprecatedLower(),
owner_->AsValue().DeprecatedLower(), owner_->Media().DeprecatedLower(),
- owner_->nonce(), owner_->IntegrityValue(), owner_->GetReferrerPolicy(),
+ owner_->nonce(), owner_->IntegrityValue(),
+ owner_->ImportanceValue().LowerASCII(), owner_->GetReferrerPolicy(),
owner_->GetNonEmptyURLAttribute(hrefAttr),
owner_->FastGetAttribute(srcsetAttr),
owner_->FastGetAttribute(imgsizesAttr));
@@ -378,8 +350,7 @@ void LinkStyle::Process() {
if (!sheet_ && !owner_->LoadLink(params))
return;
- if (LoadStylesheetIfNeeded(params.href, charset, params.type) == kNotNeeded &&
- sheet_) {
+ if (LoadStylesheetIfNeeded(params, charset) == kNotNeeded && sheet_) {
// we no longer contain a stylesheet, e.g. perhaps rel or type was changed
ClearSheet();
GetDocument().GetStyleEngine().SetNeedsActiveStyleUpdate(
diff --git a/chromium/third_party/blink/renderer/core/html/link_style.h b/chromium/third_party/blink/renderer/core/html/link_style.h
index 1c5f909095e..ba766ba18ab 100644
--- a/chromium/third_party/blink/renderer/core/html/link_style.h
+++ b/chromium/third_party/blink/renderer/core/html/link_style.h
@@ -9,13 +9,14 @@
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/html/link_resource.h"
#include "third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.h"
+#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
namespace blink {
class HTMLLinkElement;
-class KURL;
+struct LinkLoadParameters;
// LinkStyle handles dynamically change-able link resources, which is
// typically @rel="stylesheet".
@@ -62,9 +63,8 @@ class LinkStyle final : public LinkResource, ResourceClient {
void NotifyFinished(Resource*) override;
String DebugName() const override { return "LinkStyle"; }
enum LoadReturnValue { kLoaded, kNotNeeded, kBail };
- LoadReturnValue LoadStylesheetIfNeeded(const KURL&,
- const WTF::TextEncoding&,
- const String& type);
+ LoadReturnValue LoadStylesheetIfNeeded(const LinkLoadParameters&,
+ const WTF::TextEncoding&);
enum DisabledState { kUnset, kEnabledViaScript, kDisabled };
diff --git a/chromium/third_party/blink/renderer/core/html/list_item_ordinal.cc b/chromium/third_party/blink/renderer/core/html/list_item_ordinal.cc
index 5cb1c5b0ba1..1949d8b3f8f 100644
--- a/chromium/third_party/blink/renderer/core/html/list_item_ordinal.cc
+++ b/chromium/third_party/blink/renderer/core/html/list_item_ordinal.cc
@@ -34,7 +34,8 @@
namespace blink {
-ListItemOrdinal::ListItemOrdinal() : type_(kNeedsUpdate), not_in_list_(false) {}
+ListItemOrdinal::ListItemOrdinal()
+ : type_(kNeedsUpdate), not_in_list_(false), not_in_list_changed_(false) {}
bool ListItemOrdinal::IsList(const Node& node) {
return IsHTMLUListElement(node) || IsHTMLOListElement(node);
@@ -240,8 +241,19 @@ void ListItemOrdinal::ClearExplicitValue(const Node& item_node) {
InvalidateAfter(EnclosingList(&item_node), &item_node);
}
-void ListItemOrdinal::SetNotInList(bool not_in_list) {
+void ListItemOrdinal::SetNotInList(bool not_in_list, const Node& item_node) {
+ if (not_in_list_ == not_in_list)
+ return;
+
not_in_list_ = not_in_list;
+ SetNotInListChanged(true);
+ LayoutObject* layout_object = item_node.GetLayoutObject();
+ if (layout_object->IsLayoutNGListItem())
+ layout_object->NotifyOfSubtreeChange();
+}
+
+void ListItemOrdinal::SetNotInListChanged(bool changed) {
+ not_in_list_changed_ = changed;
}
unsigned ListItemOrdinal::ItemCountForOrderedList(
@@ -274,22 +286,11 @@ void ListItemOrdinal::ItemInsertedOrRemoved(
// If distribution recalc is needed, updateListMarkerNumber will be re-invoked
// after distribution is calculated.
const Node* item_node = layout_list_item->GetNode();
- if (item_node->GetDocument().ChildNeedsDistributionRecalc())
+ if (item_node->GetDocument().IsSlotAssignmentOrLegacyDistributionDirty())
return;
Node* list_node = EnclosingList(item_node);
- // TODO(kochi): Change this to CHECK(list_node) once crbug.com/734908
- // is resolved.
- if (!list_node)
- return;
-
- // Note: We don't need to invalidate list items in unassigned slots.
- if (RuntimeEnabledFeatures::IncrementalShadowDOMEnabled()) {
- if (ShadowRoot* shadow_root = list_node->ContainingShadowRoot()) {
- if (shadow_root->NeedsSlotAssignmentRecalc())
- return;
- }
- }
+ CHECK(list_node);
bool is_list_reversed = false;
if (auto* o_list_element = ToHTMLOListElementOrNull(list_node)) {
diff --git a/chromium/third_party/blink/renderer/core/html/list_item_ordinal.h b/chromium/third_party/blink/renderer/core/html/list_item_ordinal.h
index 6e16e754509..299c837f1fd 100644
--- a/chromium/third_party/blink/renderer/core/html/list_item_ordinal.h
+++ b/chromium/third_party/blink/renderer/core/html/list_item_ordinal.h
@@ -63,7 +63,9 @@ class CORE_EXPORT ListItemOrdinal {
// Get/set whether this item is in a list or not.
bool NotInList() const { return not_in_list_; }
- void SetNotInList(bool);
+ void SetNotInList(bool, const Node&);
+ bool NotInListChanged() const { return not_in_list_changed_; }
+ void SetNotInListChanged(bool);
static bool IsList(const Node&);
static bool IsListItem(const Node&);
@@ -110,6 +112,7 @@ class CORE_EXPORT ListItemOrdinal {
mutable int value_ = 0;
mutable unsigned type_ : 2; // ValueType
unsigned not_in_list_ : 1;
+ unsigned not_in_list_changed_ : 1;
};
} // namespace blink
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 2b382dc0094..70d13239678 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
@@ -251,13 +251,13 @@ bool AutoplayPolicy::RequestAutoplayByAttribute() {
return false;
}
-base::Optional<ExceptionCode> AutoplayPolicy::RequestPlay() {
+base::Optional<DOMExceptionCode> AutoplayPolicy::RequestPlay() {
if (!Frame::HasTransientUserActivation(element_->GetDocument().GetFrame())) {
autoplay_uma_helper_->OnAutoplayInitiated(AutoplaySource::kMethod);
if (IsGestureNeededForPlayback()) {
autoplay_uma_helper_->RecordCrossOriginAutoplayResult(
CrossOriginAutoplayResult::kAutoplayBlocked);
- return kNotAllowedError;
+ return DOMExceptionCode::kNotAllowedError;
}
if (IsGestureNeededForPlaybackIfCrossOriginExperimentEnabled()) {
@@ -278,10 +278,6 @@ base::Optional<ExceptionCode> AutoplayPolicy::RequestPlay() {
return base::nullopt;
}
-bool AutoplayPolicy::IsAutoplayingMuted() const {
- return IsAutoplayingMutedInternal(element_->muted());
-}
-
bool AutoplayPolicy::IsAutoplayingMutedInternal(bool muted) const {
return !element_->paused() && IsOrWillBeAutoplayingMutedInternal(muted);
}
@@ -336,6 +332,12 @@ bool AutoplayPolicy::WasAutoplayInitiated() const {
return *autoplay_initiated_;
}
+void AutoplayPolicy::EnsureAutoplayInitiatedSet() {
+ if (autoplay_initiated_)
+ return;
+ autoplay_initiated_ = false;
+}
+
bool AutoplayPolicy::IsGestureNeededForPlaybackIfPendingUserGestureIsLocked()
const {
if (element_->GetLoadType() == WebMediaPlayer::kLoadTypeMediaStream)
diff --git a/chromium/third_party/blink/renderer/core/html/media/autoplay_policy.h b/chromium/third_party/blink/renderer/core/html/media/autoplay_policy.h
index 6e24057c8b9..c3ece86de70 100644
--- a/chromium/third_party/blink/renderer/core/html/media/autoplay_policy.h
+++ b/chromium/third_party/blink/renderer/core/html/media/autoplay_policy.h
@@ -7,7 +7,7 @@
#include "base/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_code.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
@@ -68,16 +68,13 @@ class AutoplayPolicy final : public GarbageCollected<AutoplayPolicy> {
// Request the playback via play() method. This method will check the autoplay
// restrictions and record metrics. This method can only be called once
// per call of play().
- base::Optional<ExceptionCode> RequestPlay();
+ base::Optional<DOMExceptionCode> RequestPlay();
// Returns whether an umute action should pause an autoplaying element. The
// method will check autoplay restrictions and record metrics. This method can
// only be called once per call of setMuted().
bool RequestAutoplayUnmute();
- // Indicates the media element is autoplaying because of being muted.
- bool IsAutoplayingMuted() const;
-
// Indicates the media element is or will autoplay because of being
// muted.
CORE_EXPORT bool IsOrWillBeAutoplayingMuted() const;
@@ -102,6 +99,10 @@ class AutoplayPolicy final : public GarbageCollected<AutoplayPolicy> {
// should only return `true` when MEI allowed autoplay.
bool WasAutoplayInitiated() const;
+ // Ensure that `autoplay_initiated_` has a value. It is set to `false` to
+ // avoid false positives.
+ void EnsureAutoplayInitiatedSet();
+
virtual void Trace(blink::Visitor*);
private:
diff --git a/chromium/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc b/chromium/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc
index 83b395e0c39..5ba7fbdda2c 100644
--- a/chromium/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc
@@ -18,16 +18,16 @@
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/network/network_state_notifier.h"
-#include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink {
namespace {
-const int32_t kMaxOffscreenDurationUmaMS = 60 * 60 * 1000;
-const int32_t kOffscreenDurationUmaBucketCount = 50;
-const int32_t kMaxWaitTimeUmaMS = 30 * 1000;
-const int32_t kWaitTimeBucketCount = 50;
+constexpr TimeDelta kMaxOffscreenDurationUma = TimeDelta::FromHours(1);
+constexpr int32_t kOffscreenDurationUmaBucketCount = 50;
+
+constexpr TimeDelta kMaxWaitTimeUma = TimeDelta::FromSeconds(30);
+constexpr int32_t kWaitTimeBucketCount = 50;
// Returns a int64_t with the following structure:
// 0b0001 set if there is a user gesture on the stack.
@@ -59,11 +59,8 @@ AutoplayUmaHelper::AutoplayUmaHelper(HTMLMediaElement* element)
ContextLifecycleObserver(nullptr),
element_(element),
muted_video_play_method_visibility_observer_(nullptr),
- muted_video_autoplay_offscreen_start_time_ms_(0),
- muted_video_autoplay_offscreen_duration_ms_(0),
is_visible_(false),
- muted_video_offscreen_duration_visibility_observer_(nullptr),
- load_start_time_ms_(0.0) {
+ muted_video_offscreen_duration_visibility_observer_(nullptr) {
element->addEventListener(EventTypeNames::loadstart, this, false);
}
@@ -75,16 +72,13 @@ bool AutoplayUmaHelper::operator==(const EventListener& other) const {
void AutoplayUmaHelper::OnLoadStarted() {
if (element_->GetLoadType() == WebMediaPlayer::kLoadTypeURL)
- load_start_time_ms_ = CurrentTimeTicksInMilliseconds();
+ load_start_time_ = CurrentTimeTicks();
}
void AutoplayUmaHelper::OnAutoplayInitiated(AutoplaySource source) {
- int32_t autoplay_wait_time_ms = -1;
- if (load_start_time_ms_ != 0.0) {
- autoplay_wait_time_ms = static_cast<int32_t>(std::min<int64_t>(
- CurrentTimeTicksInMilliseconds() - load_start_time_ms_,
- std::numeric_limits<int32_t>::max()));
- }
+ base::Optional<TimeDelta> autoplay_wait_time;
+ if (!load_start_time_.is_null())
+ autoplay_wait_time = CurrentTimeTicks() - load_start_time_;
DEFINE_STATIC_LOCAL(EnumerationHistogram, video_histogram,
("Media.Video.Autoplay",
static_cast<int>(AutoplaySource::kNumberOfUmaSources)));
@@ -98,19 +92,6 @@ void AutoplayUmaHelper::OnAutoplayInitiated(AutoplaySource source) {
EnumerationHistogram, blocked_muted_video_histogram,
("Media.Video.Autoplay.Muted.Blocked", kAutoplayBlockedReasonMax));
- DEFINE_STATIC_LOCAL(CustomCountHistogram, wait_time_video_attrib_histogram,
- ("Media.Video.Autoplay.Attribute.WaitTime", 1,
- kMaxWaitTimeUmaMS, kWaitTimeBucketCount));
- DEFINE_STATIC_LOCAL(CustomCountHistogram, wait_time_audio_attrib_histogram,
- ("Media.Audio.Autoplay.Attribute.WaitTime", 1,
- kMaxWaitTimeUmaMS, kWaitTimeBucketCount));
- DEFINE_STATIC_LOCAL(CustomCountHistogram, wait_time_video_play_histogram,
- ("Media.Video.Autoplay.PlayMethod.WaitTime", 1,
- kMaxWaitTimeUmaMS, kWaitTimeBucketCount));
- DEFINE_STATIC_LOCAL(CustomCountHistogram, wait_time_audio_play_histogram,
- ("Media.Audio.Autoplay.PlayMethod.WaitTime", 1,
- kMaxWaitTimeUmaMS, kWaitTimeBucketCount));
-
// Autoplay already initiated
if (sources_.count(source))
return;
@@ -122,20 +103,32 @@ void AutoplayUmaHelper::OnAutoplayInitiated(AutoplaySource source) {
video_histogram.Count(static_cast<int>(source));
if (element_->muted())
muted_video_histogram.Count(static_cast<int>(source));
- if (autoplay_wait_time_ms >= 0) {
+ if (autoplay_wait_time.has_value()) {
if (source == AutoplaySource::kAttribute) {
- wait_time_video_attrib_histogram.Count(autoplay_wait_time_ms);
+ UMA_HISTOGRAM_CUSTOM_TIMES("Media.Video.Autoplay.Attribute.WaitTime",
+ *autoplay_wait_time,
+ TimeDelta::FromMilliseconds(1),
+ kMaxWaitTimeUma, kWaitTimeBucketCount);
} else if (source == AutoplaySource::kMethod) {
- wait_time_video_play_histogram.Count(autoplay_wait_time_ms);
+ UMA_HISTOGRAM_CUSTOM_TIMES("Media.Video.Autoplay.PlayMethod.WaitTime",
+ *autoplay_wait_time,
+ TimeDelta::FromMilliseconds(1),
+ kMaxWaitTimeUma, kWaitTimeBucketCount);
}
}
} else {
audio_histogram.Count(static_cast<int>(source));
- if (autoplay_wait_time_ms >= 0) {
+ if (autoplay_wait_time.has_value()) {
if (source == AutoplaySource::kAttribute) {
- wait_time_audio_attrib_histogram.Count(autoplay_wait_time_ms);
+ UMA_HISTOGRAM_CUSTOM_TIMES("Media.Audio.Autoplay.Attribute.WaitTime",
+ *autoplay_wait_time,
+ TimeDelta::FromMilliseconds(1),
+ kMaxWaitTimeUma, kWaitTimeBucketCount);
} else if (source == AutoplaySource::kMethod) {
- wait_time_audio_play_histogram.Count(autoplay_wait_time_ms);
+ UMA_HISTOGRAM_CUSTOM_TIMES("Media.Audio.Autoplay.PlayMethod.WaitTime",
+ *autoplay_wait_time,
+ TimeDelta::FromMilliseconds(1),
+ kMaxWaitTimeUma, kWaitTimeBucketCount);
}
}
}
@@ -352,12 +345,10 @@ void AutoplayUmaHelper::OnVisibilityChangedForMutedVideoOffscreenDuration(
return;
if (is_visible) {
- muted_video_autoplay_offscreen_duration_ms_ +=
- static_cast<int64_t>(CurrentTimeTicksInMilliseconds()) -
- muted_video_autoplay_offscreen_start_time_ms_;
+ muted_video_autoplay_offscreen_duration_ +=
+ CurrentTimeTicks() - muted_video_autoplay_offscreen_start_time_;
} else {
- muted_video_autoplay_offscreen_start_time_ms_ =
- static_cast<int64_t>(CurrentTimeTicksInMilliseconds());
+ muted_video_autoplay_offscreen_start_time_ = CurrentTimeTicks();
}
is_visible_ = is_visible;
@@ -430,8 +421,7 @@ void AutoplayUmaHelper::MaybeStartRecordingMutedVideoOffscreenDuration() {
return;
// Start recording muted video playing offscreen duration.
- muted_video_autoplay_offscreen_start_time_ms_ =
- static_cast<int64_t>(CurrentTimeTicksInMilliseconds());
+ muted_video_autoplay_offscreen_start_time_ = CurrentTimeTicks();
is_visible_ = false;
muted_video_offscreen_duration_visibility_observer_ =
new ElementVisibilityObserver(
@@ -449,28 +439,20 @@ void AutoplayUmaHelper::MaybeStopRecordingMutedVideoOffscreenDuration() {
return;
if (!is_visible_) {
- muted_video_autoplay_offscreen_duration_ms_ +=
- static_cast<int64_t>(CurrentTimeTicksInMilliseconds()) -
- muted_video_autoplay_offscreen_start_time_ms_;
+ muted_video_autoplay_offscreen_duration_ +=
+ CurrentTimeTicks() - muted_video_autoplay_offscreen_start_time_;
}
- // Since histograms uses int32_t, the duration needs to be limited to
- // std::numeric_limits<int32_t>::max().
- int32_t bounded_time = static_cast<int32_t>(
- std::min<int64_t>(muted_video_autoplay_offscreen_duration_ms_,
- std::numeric_limits<int32_t>::max()));
-
DCHECK(sources_.count(AutoplaySource::kMethod));
- DEFINE_STATIC_LOCAL(
- CustomCountHistogram, duration_histogram,
- ("Media.Video.Autoplay.Muted.PlayMethod.OffscreenDuration", 1,
- kMaxOffscreenDurationUmaMS, kOffscreenDurationUmaBucketCount));
- duration_histogram.Count(bounded_time);
+ UMA_HISTOGRAM_CUSTOM_TIMES(
+ "Media.Video.Autoplay.Muted.PlayMethod.OffscreenDuration",
+ muted_video_autoplay_offscreen_duration_, TimeDelta::FromMilliseconds(1),
+ kMaxOffscreenDurationUma, kOffscreenDurationUmaBucketCount);
muted_video_offscreen_duration_visibility_observer_->Stop();
muted_video_offscreen_duration_visibility_observer_ = nullptr;
- muted_video_autoplay_offscreen_duration_ms_ = 0;
+ muted_video_autoplay_offscreen_duration_ = TimeDelta();
MaybeUnregisterMediaElementPauseListener();
MaybeUnregisterContextDestroyedObserver();
}
diff --git a/chromium/third_party/blink/renderer/core/html/media/autoplay_uma_helper.h b/chromium/third_party/blink/renderer/core/html/media/autoplay_uma_helper.h
index defb52eaa9b..ce9bdd9a6bf 100644
--- a/chromium/third_party/blink/renderer/core/html/media/autoplay_uma_helper.h
+++ b/chromium/third_party/blink/renderer/core/html/media/autoplay_uma_helper.h
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/wtf/time.h"
#include <set>
@@ -133,10 +134,10 @@ class CORE_EXPORT AutoplayUmaHelper : public EventListener,
// The recording stops whenever the playback pauses or the page is unloaded.
// The starting time of autoplaying muted video.
- int64_t muted_video_autoplay_offscreen_start_time_ms_;
+ TimeTicks muted_video_autoplay_offscreen_start_time_;
// The duration an autoplaying muted video has been in offscreen.
- int64_t muted_video_autoplay_offscreen_duration_ms_;
+ TimeDelta muted_video_autoplay_offscreen_duration_;
// Whether an autoplaying muted video is visible.
bool is_visible_;
@@ -149,7 +150,7 @@ class CORE_EXPORT AutoplayUmaHelper : public EventListener,
Member<ElementVisibilityObserver>
muted_video_offscreen_duration_visibility_observer_;
- double load_start_time_ms_;
+ TimeTicks load_start_time_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/media/html_audio_element.h b/chromium/third_party/blink/renderer/core/html/media/html_audio_element.h
index 569b7b54593..87e78d00ba7 100644
--- a/chromium/third_party/blink/renderer/core/html/media/html_audio_element.h
+++ b/chromium/third_party/blink/renderer/core/html/media/html_audio_element.h
@@ -48,8 +48,11 @@ class CORE_EXPORT HTMLAudioElement final : public HTMLMediaElement {
// WebMediaPlayerClient implementation.
void MediaRemotingStarted(
const WebString& remote_device_friendly_name) override {}
- void PictureInPictureStopped() override {}
void MediaRemotingStopped(WebLocalizedString::Name error_msg) override {}
+ void PictureInPictureStopped() override { NOTREACHED(); }
+ void PictureInPictureControlClicked(const WebString& control_id) override {
+ NOTREACHED();
+ }
private:
HTMLAudioElement(Document&);
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 7695643644e..0ff8d187c58 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
@@ -43,7 +43,6 @@
#include "third_party/blink/public/platform/web_media_player_source.h"
#include "third_party/blink/public/platform/web_media_stream.h"
#include "third_party/blink/public/platform/web_screen_info.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/script_event_listener.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
@@ -53,6 +52,7 @@
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#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/events/event_queue.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -89,6 +89,8 @@
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/platform/audio/audio_bus.h"
#include "third_party/blink/renderer/platform/audio/audio_source_provider_client.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/microtask.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/histogram.h"
@@ -463,7 +465,8 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tag_name,
this,
&HTMLMediaElement::CheckViewportIntersectionTimerFired),
played_time_ranges_(),
- async_event_queue_(MediaElementEventQueue::Create(this, &document)),
+ async_event_queue_(EventQueue::Create(GetExecutionContext(),
+ TaskType::kMediaElementEvent)),
playback_rate_(1.0f),
default_playback_rate_(1.0f),
network_state_(kNetworkEmpty),
@@ -503,6 +506,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tag_name,
playing_remotely_(false),
in_overlay_fullscreen_video_(false),
mostly_filling_viewport_(false),
+ was_always_muted_(true),
audio_tracks_(AudioTrackList::Create(*this)),
video_tracks_(VideoTrackList::Create(*this)),
audio_source_node_(nullptr),
@@ -750,7 +754,9 @@ void HTMLMediaElement::ScheduleNextSourceChild() {
}
void HTMLMediaElement::ScheduleEvent(const AtomicString& event_name) {
- ScheduleEvent(Event::CreateCancelable(event_name));
+ Event* event = Event::CreateCancelable(event_name);
+ event->SetTarget(this);
+ ScheduleEvent(event);
}
void HTMLMediaElement::ScheduleEvent(Event* event) {
@@ -783,6 +789,11 @@ void HTMLMediaElement::SetSrc(const AtomicString& url) {
setAttribute(srcAttr, url);
}
+void HTMLMediaElement::SetSrc(const USVStringOrTrustedURL& stringOrURL,
+ ExceptionState& exception_state) {
+ setAttribute(srcAttr, stringOrURL, exception_state);
+}
+
void HTMLMediaElement::SetSrcObject(MediaStreamDescriptor* src_object) {
BLINK_MEDIA_LOG << "setSrcObject(" << (void*)this << ")";
src_object_ = src_object;
@@ -916,7 +927,7 @@ void HTMLMediaElement::InvokeLoadAlgorithm() {
// 4.6.2 - Take pending play promises and reject pending play promises
// with the result and an "AbortError" DOMException.
RecordPlayPromiseRejected(PlayPromiseRejectReason::kInterruptedByLoad);
- RejectPlayPromises(kAbortError,
+ RejectPlayPromises(DOMExceptionCode::kAbortError,
"The play() request was interrupted by a new load "
"request. https://goo.gl/LdLk22");
}
@@ -1289,7 +1300,13 @@ void HTMLMediaElement::StartPlayerLoad() {
web_media_player_->RequestRemotePlaybackDisabled(
FastHasAttribute(disableremoteplaybackAttr));
- web_media_player_->Load(GetLoadType(), source, CorsMode());
+ auto load_timing = web_media_player_->Load(GetLoadType(), source, CorsMode());
+ if (load_timing == WebMediaPlayer::LoadTiming::kDeferred) {
+ // Deferred media loading is not part of the spec, but intuition is that
+ // this should not hold up the Window's "load" event (similar to user
+ // gesture requirements).
+ SetShouldDelayLoadEvent(false);
+ }
if (IsFullscreen())
web_media_player_->EnteredFullscreen();
@@ -1565,7 +1582,7 @@ void HTMLMediaElement::NoneSupported(const String& input_message) {
ScheduleEvent(EventTypeNames::error);
// 6 - Reject pending play promises with NotSupportedError.
- ScheduleRejectPlayPromises(kNotSupportedError);
+ ScheduleRejectPlayPromises(DOMExceptionCode::kNotSupportedError);
CloseMediaSource();
@@ -1814,8 +1831,6 @@ void HTMLMediaElement::SetReadyState(ReadyState state) {
if (ready_state_ >= kHaveMetadata && old_state < kHaveMetadata) {
CreatePlaceholderTracksIfNecessary();
- SelectInitialTracksIfNecessary();
-
MediaFragmentURIParser fragment_parser(current_src_);
fragment_end_time_ = fragment_parser.EndTime();
@@ -1923,7 +1938,13 @@ void HTMLMediaElement::ProgressEventTimerFired(TimerBase*) {
sent_stalled_event_ = false;
if (GetLayoutObject())
GetLayoutObject()->UpdateFromElement();
- } else if (timedelta > 3.0 && !sent_stalled_event_) {
+ } else if (!media_source_ && timedelta > 3.0 && !sent_stalled_event_) {
+ // Note the !media_source_ condition above. The 'stalled' event is not
+ // fired when using MSE. MSE's resource is considered 'local' (we don't
+ // manage the donwload - the app does), so the HTML5 spec text around
+ // 'stalled' does not apply. See discussion in https://crbug.com/517240
+ // We also don't need to take any action wrt delaying-the-load-event.
+ // MediaSource disables the delayed load when first attached.
ScheduleEvent(EventTypeNames::stalled);
sent_stalled_event_ = true;
SetShouldDelayLoadEvent(false);
@@ -2246,9 +2267,9 @@ void HTMLMediaElement::setPlaybackRate(double rate,
// When the proposed playbackRate is unsupported, throw a NotSupportedError
// DOMException and don't update the value.
exception_state.ThrowDOMException(
- kNotSupportedError, "The provided playback rate (" +
- String::Number(rate) + ") is not in the " +
- "supported playback range.");
+ DOMExceptionCode::kNotSupportedError,
+ "The provided playback rate (" + String::Number(rate) +
+ ") is not in the " + "supported playback range.");
// Do not update |playback_rate_|.
return;
@@ -2373,19 +2394,19 @@ ScriptPromise HTMLMediaElement::playForBindings(ScriptState* script_state) {
ScriptPromise promise = resolver->Promise();
play_promise_resolvers_.push_back(resolver);
- base::Optional<ExceptionCode> code = Play();
+ base::Optional<DOMExceptionCode> code = Play();
if (code) {
DCHECK(!play_promise_resolvers_.IsEmpty());
play_promise_resolvers_.pop_back();
String message;
switch (code.value()) {
- case kNotAllowedError:
+ case DOMExceptionCode::kNotAllowedError:
message = autoplay_policy_->GetPlayErrorMessage();
RecordPlayPromiseRejected(
PlayPromiseRejectReason::kFailedAutoplayPolicy);
break;
- case kNotSupportedError:
+ case DOMExceptionCode::kNotSupportedError:
message = "The element has no supported sources.";
RecordPlayPromiseRejected(PlayPromiseRejectReason::kNoSupportedSources);
break;
@@ -2399,13 +2420,13 @@ ScriptPromise HTMLMediaElement::playForBindings(ScriptState* script_state) {
return promise;
}
-base::Optional<ExceptionCode> HTMLMediaElement::Play() {
+base::Optional<DOMExceptionCode> HTMLMediaElement::Play() {
BLINK_MEDIA_LOG << "play(" << (void*)this << ")";
- base::Optional<ExceptionCode> exception_code =
+ base::Optional<DOMExceptionCode> exception_code =
autoplay_policy_->RequestPlay();
- if (exception_code == kNotAllowedError) {
+ if (exception_code == DOMExceptionCode::kNotAllowedError) {
// If we're already playing, then this play would do nothing anyway.
// Call playInternal to handle scheduling the promise resolution.
if (!paused_) {
@@ -2418,7 +2439,7 @@ base::Optional<ExceptionCode> HTMLMediaElement::Play() {
autoplay_policy_->StopAutoplayMutedWhenVisible();
if (error_ && error_->code() == MediaError::kMediaErrSrcNotSupported)
- return kNotSupportedError;
+ return DOMExceptionCode::kNotSupportedError;
DCHECK(!exception_code.has_value());
@@ -2484,7 +2505,7 @@ void HTMLMediaElement::PauseInternal() {
// time to accurately reflect movie time at the moment we paused.
SetOfficialPlaybackPosition(CurrentPlaybackPosition());
- ScheduleRejectPlayPromises(kAbortError);
+ ScheduleRejectPlayPromises(DOMExceptionCode::kAbortError);
}
UpdatePlayState();
@@ -2585,7 +2606,7 @@ void HTMLMediaElement::setVolume(double vol, ExceptionState& exception_state) {
if (vol < 0.0f || vol > 1.0f) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
ExceptionMessages::IndexOutsideRange(
"volume", vol, 0.0, ExceptionMessages::kInclusiveBound, 1.0,
ExceptionMessages::kInclusiveBound));
@@ -2619,8 +2640,13 @@ void HTMLMediaElement::setMuted(bool muted) {
if (!muted_ && !autoplay_policy_->RequestAutoplayUnmute())
pause();
- // This is called after the volumechange event to make sure isAutoplayingMuted
- // returns the right value when webMediaPlayer receives the volume update.
+ // If playback was not paused by the autoplay policy and got unmuted, the
+ // element is marked as being allowed to play unmuted.
+ if (!muted_ && PotentiallyPlaying())
+ was_always_muted_ = false;
+
+ // This is called at the end to make sure the WebMediaPlayer has the right
+ // information.
if (GetWebMediaPlayer())
GetWebMediaPlayer()->SetVolume(EffectiveMediaVolume());
@@ -2629,6 +2655,9 @@ void HTMLMediaElement::setMuted(bool muted) {
void HTMLMediaElement::enterPictureInPicture(
WebMediaPlayer::PipWindowOpenedCallback callback) {
+ if (DisplayType() == WebMediaPlayer::DisplayType::kFullscreen)
+ Fullscreen::ExitFullscreen(GetDocument());
+
if (GetWebMediaPlayer())
GetWebMediaPlayer()->EnterPictureInPicture(std::move(callback));
}
@@ -3234,7 +3263,7 @@ void HTMLMediaElement::TimeChanged() {
// media element.
paused_ = true;
ScheduleEvent(EventTypeNames::pause);
- ScheduleRejectPlayPromises(kAbortError);
+ ScheduleRejectPlayPromises(DOMExceptionCode::kAbortError);
}
// Queue a task to fire a simple event named ended at the media element.
ScheduleEvent(EventTypeNames::ended);
@@ -3276,18 +3305,6 @@ void HTMLMediaElement::DurationChanged(double duration, bool request_seek) {
Seek(duration);
}
-void HTMLMediaElement::PlaybackStateChanged() {
- BLINK_MEDIA_LOG << "playbackStateChanged(" << (void*)this << ")";
-
- if (!GetWebMediaPlayer())
- return;
-
- if (GetWebMediaPlayer()->Paused())
- PauseInternal();
- else
- PlayInternal();
-}
-
void HTMLMediaElement::RequestSeek(double time) {
// The player is the source of this seek request.
setCurrentTime(time);
@@ -3355,8 +3372,8 @@ WebMediaPlayer::TrackId HTMLMediaElement::GetSelectedVideoTrackId() {
return track->id();
}
-bool HTMLMediaElement::IsAutoplayingMuted() {
- return autoplay_policy_->IsAutoplayingMuted();
+bool HTMLMediaElement::WasAlwaysMuted() {
+ return was_always_muted_;
}
// MediaPlayerPresentation methods
@@ -3443,6 +3460,17 @@ bool HTMLMediaElement::EndedPlayback(LoopCondition loop_condition) const {
// direction of playback is forwards, Either the media element does not have a
// loop attribute specified,
double now = CurrentPlaybackPosition();
+
+ // Log whether we get a playback position of infinity().
+ // TODO(ossu): Once this stat expires, the duration check, below, can be moved
+ // up to the top of the function.
+ UMA_HISTOGRAM_BOOLEAN("Media.MediaElement.PlaybackPositionIsInfinity",
+ now == std::numeric_limits<double>::infinity());
+ // If we have infinite duration, we'll never have played for long enough to
+ // have ended playback.
+ if (dur == std::numeric_limits<double>::infinity())
+ return false;
+
if (GetDirectionOfPlayback() == kForward) {
return dur > 0 && now >= dur &&
(loop_condition == LoopCondition::kIgnored || !Loop());
@@ -3472,6 +3500,9 @@ void HTMLMediaElement::UpdatePlayState() {
<< ") - shouldBePlaying = " << BoolString(should_be_playing)
<< ", isPlaying = " << BoolString(is_playing);
+ if (should_be_playing && !muted_)
+ was_always_muted_ = false;
+
if (should_be_playing) {
SetDisplayMode(kVideo);
@@ -3548,7 +3579,6 @@ void HTMLMediaElement::ContextDestroyed(ExecutionContext*) {
// Close the async event queue so that no events are enqueued.
CancelPendingEventsAndCallbacks();
- async_event_queue_->Close();
// Clear everything in the Media Element
ClearMediaPlayer();
@@ -3568,10 +3598,6 @@ void HTMLMediaElement::ContextDestroyed(ExecutionContext*) {
GetLayoutObject()->UpdateFromElement();
StopPeriodicTimers();
-
- // Ensure that hasPendingActivity() is not preventing garbage collection,
- // since otherwise this media element will simply leak.
- DCHECK(!HasPendingActivity());
}
bool HTMLMediaElement::HasPendingActivity() const {
@@ -3621,6 +3647,9 @@ bool HTMLMediaElement::IsFullscreen() const {
void HTMLMediaElement::DidEnterFullscreen() {
UpdateControlsVisibility();
+ if (DisplayType() == WebMediaPlayer::DisplayType::kPictureInPicture)
+ exitPictureInPicture(base::DoNothing());
+
if (web_media_player_) {
// FIXME: There is no embedder-side handling in layout test mode.
if (!LayoutTestSupport::IsRunningLayoutTest())
@@ -3714,7 +3743,8 @@ TextTrackContainer& HTMLMediaElement::EnsureTextTrackContainer() {
return ToTextTrackContainer(*first_child);
Node* to_be_inserted = first_child;
- if (first_child && first_child->IsMediaRemotingInterstitial()) {
+ if (first_child && (first_child->IsMediaRemotingInterstitial() ||
+ first_child->IsPictureInPictureInterstitial())) {
Node* second_child = first_child->nextSibling();
if (second_child && second_child->IsTextTrackContainer())
return ToTextTrackContainer(*second_child);
@@ -3995,14 +4025,6 @@ void HTMLMediaElement::Trace(blink::Visitor* visitor) {
PausableObject::Trace(visitor);
}
-void HTMLMediaElement::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(video_tracks_);
- visitor->TraceWrappers(audio_tracks_);
- visitor->TraceWrappers(text_tracks_);
- HTMLElement::TraceWrappers(visitor);
- Supplementable<HTMLMediaElement>::TraceWrappers(visitor);
-}
-
void HTMLMediaElement::CreatePlaceholderTracksIfNecessary() {
if (!MediaTracksEnabledInternally())
return;
@@ -4011,30 +4033,17 @@ void HTMLMediaElement::CreatePlaceholderTracksIfNecessary() {
// didn't explicitly announce the tracks.
if (HasAudio() && !audioTracks().length()) {
AddAudioTrack("audio", WebMediaPlayerClient::kAudioTrackKindMain,
- "Audio Track", "", false);
+ "Audio Track", "", true);
}
// Create a placeholder video track if the player says it has video but it
// didn't explicitly announce the tracks.
if (HasVideo() && !videoTracks().length()) {
AddVideoTrack("video", WebMediaPlayerClient::kVideoTrackKindMain,
- "Video Track", "", false);
+ "Video Track", "", true);
}
}
-void HTMLMediaElement::SelectInitialTracksIfNecessary() {
- if (!MediaTracksEnabledInternally())
- return;
-
- // Enable the first audio track if an audio track hasn't been enabled yet.
- if (audioTracks().length() > 0 && !audioTracks().HasEnabledTrack())
- audioTracks().AnonymousIndexedGetter(0)->setEnabled(true);
-
- // Select the first video track if a video track hasn't been selected yet.
- if (videoTracks().length() > 0 && videoTracks().selectedIndex() == -1)
- videoTracks().AnonymousIndexedGetter(0)->setSelected(true);
-}
-
void HTMLMediaElement::SetNetworkState(NetworkState state) {
if (network_state_ == state)
return;
@@ -4074,7 +4083,7 @@ void HTMLMediaElement::ScheduleResolvePlayPromises() {
WrapWeakPersistent(this)));
}
-void HTMLMediaElement::ScheduleRejectPlayPromises(ExceptionCode code) {
+void HTMLMediaElement::ScheduleRejectPlayPromises(DOMExceptionCode code) {
// TODO(mlamouri): per spec, we should create a new task but we can't create
// a new cancellable task without cancelling the previous one. There are two
// approaches then: cancel the previous task and create a new one with the
@@ -4117,31 +4126,32 @@ void HTMLMediaElement::RejectScheduledPlayPromises() {
// TODO(mlamouri): the message is generated based on the code because
// arguments can't be passed to a cancellable task. In order to save space
// used by the object, the string isn't saved.
- DCHECK(play_promise_error_code_ == kAbortError ||
- play_promise_error_code_ == kNotSupportedError);
- if (play_promise_error_code_ == kAbortError) {
+ DCHECK(play_promise_error_code_ == DOMExceptionCode::kAbortError ||
+ play_promise_error_code_ == DOMExceptionCode::kNotSupportedError);
+ if (play_promise_error_code_ == DOMExceptionCode::kAbortError) {
RecordPlayPromiseRejected(PlayPromiseRejectReason::kInterruptedByPause);
- RejectPlayPromisesInternal(kAbortError,
+ RejectPlayPromisesInternal(DOMExceptionCode::kAbortError,
"The play() request was interrupted by a call "
"to pause(). https://goo.gl/LdLk22");
} else {
RecordPlayPromiseRejected(PlayPromiseRejectReason::kNoSupportedSources);
RejectPlayPromisesInternal(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"Failed to load because no supported source was found.");
}
}
-void HTMLMediaElement::RejectPlayPromises(ExceptionCode code,
+void HTMLMediaElement::RejectPlayPromises(DOMExceptionCode code,
const String& message) {
play_promise_reject_list_.AppendVector(play_promise_resolvers_);
play_promise_resolvers_.clear();
RejectPlayPromisesInternal(code, message);
}
-void HTMLMediaElement::RejectPlayPromisesInternal(ExceptionCode code,
+void HTMLMediaElement::RejectPlayPromisesInternal(DOMExceptionCode code,
const String& message) {
- DCHECK(code == kAbortError || code == kNotSupportedError);
+ DCHECK(code == DOMExceptionCode::kAbortError ||
+ code == DOMExceptionCode::kNotSupportedError);
for (auto& resolver : play_promise_reject_list_)
resolver->Reject(DOMException::Create(code, message));
@@ -4260,6 +4270,15 @@ bool HTMLMediaElement::WasAutoplayInitiated() {
return autoplay_policy_->WasAutoplayInitiated();
}
+void HTMLMediaElement::RequestPlay() {
+ autoplay_policy_->EnsureAutoplayInitiatedSet();
+ PlayInternal();
+}
+
+void HTMLMediaElement::RequestPause() {
+ PauseInternal();
+}
+
bool HTMLMediaElement::MediaShouldBeOpaque() const {
return !IsMediaDataCORSSameOrigin(GetDocument().GetSecurityOrigin()) &&
ready_state_ < kHaveMetadata && !FastGetAttribute(srcAttr).IsEmpty();
diff --git a/chromium/third_party/blink/renderer/core/html/media/html_media_element.h b/chromium/third_party/blink/renderer/core/html/media/html_media_element.h
index 6de68a7bcbf..c9b109245ca 100644
--- a/chromium/third_party/blink/renderer/core/html/media/html_media_element.h
+++ b/chromium/third_party/blink/renderer/core/html/media/html_media_element.h
@@ -33,18 +33,17 @@
#include "third_party/blink/public/platform/web_audio_source_provider_client.h"
#include "third_party/blink/public/platform/web_media_player_client.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/events/media_element_event_queue.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/pausable_object.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/html/media/media_controls.h"
#include "third_party/blink/renderer/platform/audio/audio_source_provider.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
#include "third_party/blink/renderer/platform/supplementable.h"
+#include "third_party/blink/renderer/platform/timer.h"
#include "third_party/blink/renderer/platform/web_task_runner.h"
namespace cc {
@@ -61,14 +60,16 @@ class ContentType;
class CueTimeline;
class EnumerationHistogram;
class Event;
+class EventQueue;
class ExceptionState;
class HTMLMediaElementControlsList;
+class HTMLMediaSource;
class HTMLSourceElement;
class HTMLTrackElement;
class KURL;
class MediaError;
class MediaStreamDescriptor;
-class HTMLMediaSource;
+class ScriptPromiseResolver;
class ScriptState;
class TextTrack;
class TextTrackContainer;
@@ -110,8 +111,6 @@ class CORE_EXPORT HTMLMediaElement
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
void ClearWeakMembers(Visitor*);
WebMediaPlayer* GetWebMediaPlayer() const { return web_media_player_.get(); }
@@ -140,6 +139,7 @@ class CORE_EXPORT HTMLMediaElement
// network state
void SetSrc(const AtomicString&);
+ void SetSrc(const USVStringOrTrustedURL&, ExceptionState&);
const KURL& currentSrc() const { return current_src_; }
void SetSrcObject(MediaStreamDescriptor*);
MediaStreamDescriptor* GetSrcObject() const { return src_object_.Get(); }
@@ -191,7 +191,7 @@ class CORE_EXPORT HTMLMediaElement
bool Loop() const;
void SetLoop(bool);
ScriptPromise playForBindings(ScriptState*);
- base::Optional<ExceptionCode> Play();
+ base::Optional<DOMExceptionCode> Play();
void pause();
void RequestRemotePlayback();
void RequestRemotePlaybackControl();
@@ -401,7 +401,6 @@ class CORE_EXPORT HTMLMediaElement
void Repaint() final;
void DurationChanged() final;
void SizeChanged() final;
- void PlaybackStateChanged() final;
void SetCcLayer(cc::Layer*) final;
WebMediaPlayer::TrackId AddAudioTrack(const WebString&,
@@ -430,7 +429,7 @@ class CORE_EXPORT HTMLMediaElement
void OnBecamePersistentVideo(bool) override {}
bool HasSelectedVideoTrack() final;
WebMediaPlayer::TrackId GetSelectedVideoTrackId() final;
- bool IsAutoplayingMuted() final;
+ bool WasAlwaysMuted() final;
void ActivateViewportIntersectionMonitoring(bool) final;
bool HasNativeControls() final;
bool IsAudioElement() final;
@@ -441,6 +440,8 @@ class CORE_EXPORT HTMLMediaElement
gfx::ColorSpace TargetColorSpace() override;
bool WasAutoplayInitiated() override;
bool IsInAutoPIP() const override { return false; }
+ void RequestPlay() final;
+ void RequestPause() final;
void LoadTimerFired(TimerBase*);
void ProgressEventTimerFired(TimerBase*);
@@ -537,27 +538,23 @@ class CORE_EXPORT HTMLMediaElement
DirectionOfPlayback GetDirectionOfPlayback() const;
// Creates placeholder AudioTrack and/or VideoTrack objects when
- // WebMemediaPlayer objects advertise they have audio and/or video, but don't
+ // WebMediaPlayer objects advertise they have audio and/or video, but don't
// explicitly signal them via addAudioTrack() and addVideoTrack().
// FIXME: Remove this once all WebMediaPlayer implementations properly report
// their track info.
void CreatePlaceholderTracksIfNecessary();
- // Sets the selected/enabled tracks if they aren't set before we initially
- // transition to kHaveMetadata.
- void SelectInitialTracksIfNecessary();
-
void SetNetworkState(NetworkState);
void AudioTracksTimerFired(TimerBase*);
void ScheduleResolvePlayPromises();
- void ScheduleRejectPlayPromises(ExceptionCode);
+ void ScheduleRejectPlayPromises(DOMExceptionCode);
void ScheduleNotifyPlaying();
void ResolveScheduledPlayPromises();
void RejectScheduledPlayPromises();
- void RejectPlayPromises(ExceptionCode, const String&);
- void RejectPlayPromisesInternal(ExceptionCode, const String&);
+ void RejectPlayPromises(DOMExceptionCode, const String&);
+ void RejectPlayPromisesInternal(DOMExceptionCode, const String&);
EnumerationHistogram& ShowControlsHistogram() const;
@@ -568,7 +565,7 @@ class CORE_EXPORT HTMLMediaElement
TaskRunnerTimer<HTMLMediaElement> check_viewport_intersection_timer_;
Member<TimeRanges> played_time_ranges_;
- Member<MediaElementEventQueue> async_event_queue_;
+ Member<EventQueue> async_event_queue_;
double playback_rate_;
double default_playback_rate_;
@@ -664,6 +661,8 @@ class CORE_EXPORT HTMLMediaElement
bool mostly_filling_viewport_ : 1;
+ bool was_always_muted_ : 1;
+
TraceWrapperMember<AudioTrackList> audio_tracks_;
TraceWrapperMember<VideoTrackList> video_tracks_;
TraceWrapperMember<TextTrackList> text_tracks_;
@@ -676,7 +675,7 @@ class CORE_EXPORT HTMLMediaElement
TaskHandle play_promise_reject_task_handle_;
HeapVector<Member<ScriptPromiseResolver>> play_promise_resolve_list_;
HeapVector<Member<ScriptPromiseResolver>> play_promise_reject_list_;
- ExceptionCode play_promise_error_code_;
+ DOMExceptionCode play_promise_error_code_;
// This is a weak reference, since audio_source_node_ holds a reference to us.
// TODO(Oilpan): Consider making this a strongly traced pointer with oilpan
@@ -744,6 +743,7 @@ class CORE_EXPORT HTMLMediaElement
friend class MediaControlsRotateToFullscreenDelegateTest;
friend class MediaControlLoadingPanelElementTest;
friend class ContextMenuControllerTest;
+ friend class HTMLVideoElementTest;
Member<AutoplayPolicy> autoplay_policy_;
diff --git a/chromium/third_party/blink/renderer/core/html/media/html_media_element.idl b/chromium/third_party/blink/renderer/core/html/media/html_media_element.idl
index b1bfe6ebce6..61972ef547d 100644
--- a/chromium/third_party/blink/renderer/core/html/media/html_media_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/media/html_media_element.idl
@@ -25,6 +25,9 @@
// https://html.spec.whatwg.org/#media-elements
+// The `URLString` reference below is from Trusted Types:
+// https://github.com/WICG/trusted-types/, which is still WIP.
+// https://crbug.com/739170.
enum CanPlayTypeResult { "" /* empty string */, "maybe", "probably" };
[
ActiveScriptWrappable
@@ -34,7 +37,7 @@ enum CanPlayTypeResult { "" /* empty string */, "maybe", "probably" };
readonly attribute MediaError? error;
// network state
- [CEReactions, Reflect, URL] attribute DOMString src;
+ [CEReactions, Reflect, URL, RaisesException=Setter] attribute URLString src;
// FIXME: attribute MediaProvider? srcObject; crbug.com/387740
readonly attribute DOMString currentSrc;
[CEReactions, Reflect, ReflectOnly=("anonymous","use-credentials"), ReflectEmpty="anonymous", ReflectInvalid="anonymous"] attribute DOMString? crossOrigin;
diff --git a/chromium/third_party/blink/renderer/core/html/media/html_media_element_event_listeners_test.cc b/chromium/third_party/blink/renderer/core/html/media/html_media_element_event_listeners_test.cc
index da72e7eaa97..93c16ae0da1 100644
--- a/chromium/third_party/blink/renderer/core/html/media/html_media_element_event_listeners_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/html_media_element_event_listeners_test.cc
@@ -207,7 +207,7 @@ TEST_F(HTMLMediaElementEventListenersTest,
std::unique_ptr<UserGestureIndicator> gesture_indicator =
Frame::NotifyUserActivation(GetDocument().GetFrame());
Fullscreen::RequestFullscreen(*Video());
- Fullscreen::From(GetDocument()).DidEnterFullscreen();
+ Fullscreen::DidEnterFullscreen(GetDocument());
test::RunPendingTasks();
@@ -296,11 +296,8 @@ TEST_F(HTMLMediaElementWithMockSchedulerTest, OneTimeupdatePerSeek) {
// While playing, timeupdate should fire every 250 ms -> 4x per second as long
// as media player's CurrentTime continues to advance.
- EXPECT_CALL(*timeupdate_handler, handleEvent(_, _)).Times(3);
+ EXPECT_CALL(*timeupdate_handler, handleEvent(_, _)).Times(4);
platform_->RunForPeriodSeconds(1);
- // The 4th event was scheduled, but needs one more scheduler cycle to fire.
- EXPECT_CALL(*timeupdate_handler, handleEvent(_, _)).Times(1);
- platform_->RunUntilIdle();
// If media playback time is fixed, periodic timeupdate's should not continue
// to fire.
diff --git a/chromium/third_party/blink/renderer/core/html/media/html_media_element_test.cc b/chromium/third_party/blink/renderer/core/html/media/html_media_element_test.cc
index c852c3d8773..86a12b86f4d 100644
--- a/chromium/third_party/blink/renderer/core/html/media/html_media_element_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/html_media_element_test.cc
@@ -7,37 +7,61 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/autoplay.mojom-blink.h"
+#include "third_party/blink/public/platform/web_media_player_source.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/html/media/html_audio_element.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include "third_party/blink/renderer/core/html/media/media_error.h"
+#include "third_party/blink/renderer/core/html/track/audio_track_list.h"
+#include "third_party/blink/renderer/core/html/track/video_track_list.h"
#include "third_party/blink/renderer/core/loader/empty_clients.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
#include "third_party/blink/renderer/platform/network/network_state_notifier.h"
#include "third_party/blink/renderer/platform/testing/empty_web_media_player.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+using ::testing::AnyNumber;
+using ::testing::Return;
+using ::testing::_;
+
namespace blink {
class MockWebMediaPlayer : public EmptyWebMediaPlayer {
public:
+ MOCK_CONST_METHOD0(HasAudio, bool());
+ MOCK_CONST_METHOD0(HasVideo, bool());
MOCK_CONST_METHOD0(Duration, double());
MOCK_CONST_METHOD0(CurrentTime, double());
+ MOCK_METHOD1(EnabledAudioTracksChanged, void(const WebVector<TrackId>&));
+ MOCK_METHOD1(SelectedVideoTrackChanged, void(TrackId*));
+ MOCK_METHOD3(
+ Load,
+ WebMediaPlayer::LoadTiming(LoadType load_type,
+ const blink::WebMediaPlayerSource& source,
+ CORSMode cors_mode));
};
class WebMediaStubLocalFrameClient : public EmptyLocalFrameClient {
public:
- static WebMediaStubLocalFrameClient* Create() {
- return new WebMediaStubLocalFrameClient;
+ static WebMediaStubLocalFrameClient* Create(
+ std::unique_ptr<WebMediaPlayer> player) {
+ return new WebMediaStubLocalFrameClient(std::move(player));
}
+ WebMediaStubLocalFrameClient(std::unique_ptr<WebMediaPlayer> player)
+ : player_(std::move(player)) {}
+
std::unique_ptr<WebMediaPlayer> CreateWebMediaPlayer(
HTMLMediaElement&,
const WebMediaPlayerSource&,
WebMediaPlayerClient* client,
WebLayerTreeView*) override {
- return std::make_unique<MockWebMediaPlayer>();
+ DCHECK(player_) << " Empty injected player - already used?";
+ return std::move(player_);
}
+
+ private:
+ std::unique_ptr<WebMediaPlayer> player_;
};
enum class MediaTestParam { kAudio, kVideo };
@@ -45,8 +69,28 @@ enum class MediaTestParam { kAudio, kVideo };
class HTMLMediaElementTest : public testing::TestWithParam<MediaTestParam> {
protected:
void SetUp() override {
+ // Sniff the media player pointer to facilitate mocking.
+ auto mock_media_player = std::make_unique<MockWebMediaPlayer>();
+ media_player_ = mock_media_player.get();
+
+ // Most tests do not care about this call, nor its return value. Those that
+ // do will clear this expectation and set custom expectations/returns.
+ EXPECT_CALL(*mock_media_player, HasAudio())
+ .WillRepeatedly(testing::Return(true));
+ EXPECT_CALL(*mock_media_player, HasVideo())
+ .WillRepeatedly(testing::Return(true));
+ EXPECT_CALL(*mock_media_player, Duration())
+ .WillRepeatedly(testing::Return(1.0));
+ EXPECT_CALL(*mock_media_player, CurrentTime())
+ .WillRepeatedly(testing::Return(0));
+ EXPECT_CALL(*mock_media_player, Load(_, _, _))
+ .Times(AnyNumber())
+ .WillRepeatedly(Return(WebMediaPlayer::LoadTiming::kImmediate));
+
dummy_page_holder_ = DummyPageHolder::Create(
- IntSize(), nullptr, WebMediaStubLocalFrameClient::Create(), nullptr);
+ IntSize(), nullptr,
+ WebMediaStubLocalFrameClient::Create(std::move(mock_media_player)),
+ nullptr);
if (GetParam() == MediaTestParam::kAudio)
media_ = HTMLAudioElement::Create(dummy_page_holder_->GetDocument());
@@ -60,10 +104,14 @@ class HTMLMediaElementTest : public testing::TestWithParam<MediaTestParam> {
Media()->current_src_ = url;
}
+ MockWebMediaPlayer* MockMediaPlayer() { return media_player_; }
+
bool WasAutoplayInitiated() { return Media()->WasAutoplayInitiated(); }
bool CouldPlayIfEnoughData() { return Media()->CouldPlayIfEnoughData(); }
+ bool ShouldDelayLoadEvent() { return Media()->should_delay_load_event_; }
+
void SetReadyState(HTMLMediaElement::ReadyState state) {
Media()->SetReadyState(state);
}
@@ -78,6 +126,9 @@ class HTMLMediaElementTest : public testing::TestWithParam<MediaTestParam> {
private:
std::unique_ptr<DummyPageHolder> dummy_page_holder_;
Persistent<HTMLMediaElement> media_;
+
+ // Owned by WebMediaStubLocalFrameClient.
+ MockWebMediaPlayer* media_player_;
};
INSTANTIATE_TEST_CASE_P(Audio,
@@ -198,8 +249,6 @@ TEST_P(HTMLMediaElementTest, CouldPlayIfEnoughDataRespondsToEnded) {
MockWebMediaPlayer* mock_wmpi =
reinterpret_cast<MockWebMediaPlayer*>(Media()->GetWebMediaPlayer());
EXPECT_NE(mock_wmpi, nullptr);
- EXPECT_CALL(*mock_wmpi, Duration()).WillRepeatedly(testing::Return(1.0));
- EXPECT_CALL(*mock_wmpi, CurrentTime()).WillRepeatedly(testing::Return(0));
EXPECT_TRUE(CouldPlayIfEnoughData());
// Playback can only end once the ready state is above kHaveMetadata.
@@ -225,8 +274,6 @@ TEST_P(HTMLMediaElementTest, CouldPlayIfEnoughDataRespondsToError) {
MockWebMediaPlayer* mock_wmpi =
reinterpret_cast<MockWebMediaPlayer*>(Media()->GetWebMediaPlayer());
EXPECT_NE(mock_wmpi, nullptr);
- EXPECT_CALL(*mock_wmpi, Duration()).WillRepeatedly(testing::Return(1.0));
- EXPECT_CALL(*mock_wmpi, CurrentTime()).WillRepeatedly(testing::Return(0));
EXPECT_TRUE(CouldPlayIfEnoughData());
SetReadyState(HTMLMediaElement::kHaveMetadata);
@@ -238,6 +285,23 @@ TEST_P(HTMLMediaElementTest, CouldPlayIfEnoughDataRespondsToError) {
EXPECT_FALSE(CouldPlayIfEnoughData());
}
+TEST_P(HTMLMediaElementTest, CouldPlayIfEnoughDataInfiniteStreamNeverEnds) {
+ Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
+ Media()->Play();
+
+ test::RunPendingTasks();
+
+ EXPECT_CALL(*MockMediaPlayer(), Duration())
+ .WillRepeatedly(testing::Return(std::numeric_limits<double>::infinity()));
+ EXPECT_CALL(*MockMediaPlayer(), CurrentTime())
+ .WillRepeatedly(testing::Return(std::numeric_limits<double>::infinity()));
+
+ SetReadyState(HTMLMediaElement::kHaveMetadata);
+ EXPECT_FALSE(Media()->paused());
+ EXPECT_FALSE(Media()->ended());
+ EXPECT_TRUE(CouldPlayIfEnoughData());
+}
+
TEST_P(HTMLMediaElementTest, AutoplayInitiated_DocumentActivation_Low_Gesture) {
// Setup is the following:
// - Policy: DocumentUserActivation (aka. unified autoplay)
@@ -327,4 +391,57 @@ TEST_P(HTMLMediaElementTest, AutoplayInitiated_NoGestureRequired_NoGesture) {
EXPECT_TRUE(WasAutoplayInitiated());
}
+TEST_P(HTMLMediaElementTest,
+ DeferredMediaPlayerLoadDoesNotDelayWindowLoadEvent) {
+ // Source isn't really important, we just need something to let load algorithm
+ // run up to the point of calling WebMediaPlayer::Load().
+ Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
+
+ // WebMediaPlayer will signal that it will defer loading to some later time.
+ testing::Mock::VerifyAndClearExpectations(MockMediaPlayer());
+ EXPECT_CALL(*MockMediaPlayer(), Load(_, _, _))
+ .WillOnce(Return(WebMediaPlayer::LoadTiming::kDeferred));
+
+ // Window's 'load' event starts out "delayed".
+ EXPECT_TRUE(ShouldDelayLoadEvent());
+ Media()->load();
+ test::RunPendingTasks();
+
+ // No longer delayed because WMP loading is deferred.
+ EXPECT_FALSE(ShouldDelayLoadEvent());
+}
+
+TEST_P(HTMLMediaElementTest, ImmediateMediaPlayerLoadDoesDelayWindowLoadEvent) {
+ // Source isn't really important, we just need something to let load algorithm
+ // run up to the point of calling WebMediaPlayer::Load().
+ Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
+
+ // WebMediaPlayer will signal that it will do the load immediately.
+ EXPECT_CALL(*MockMediaPlayer(), Load(_, _, _))
+ .WillOnce(Return(WebMediaPlayer::LoadTiming::kImmediate));
+
+ // Window's 'load' event starts out "delayed".
+ EXPECT_TRUE(ShouldDelayLoadEvent());
+ Media()->load();
+ test::RunPendingTasks();
+
+ // Still delayed because WMP loading is not deferred.
+ EXPECT_TRUE(ShouldDelayLoadEvent());
+}
+
+TEST_P(HTMLMediaElementTest, DefaultTracksAreEnabled) {
+ // Default tracks should start enabled, not be created then enabled.
+ EXPECT_CALL(*MockMediaPlayer(), EnabledAudioTracksChanged(_)).Times(0);
+ EXPECT_CALL(*MockMediaPlayer(), SelectedVideoTrackChanged(_)).Times(0);
+
+ Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp));
+ test::RunPendingTasks();
+ SetReadyState(HTMLMediaElement::kHaveFutureData);
+
+ ASSERT_EQ(1u, Media()->audioTracks().length());
+ ASSERT_EQ(1u, Media()->videoTracks().length());
+ EXPECT_TRUE(Media()->audioTracks().AnonymousIndexedGetter(0)->enabled());
+ EXPECT_TRUE(Media()->videoTracks().AnonymousIndexedGetter(0)->selected());
+}
+
} // namespace blink
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 0b654ea9cce..9ec32c49d96 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
@@ -26,7 +26,7 @@
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include <memory>
-#include "third_party/blink/public/platform/web_canvas.h"
+#include "cc/paint/paint_canvas.h"
#include "third_party/blink/renderer/core/css_property_names.h"
#include "third_party/blink/renderer/core/dom/attribute.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -325,7 +325,7 @@ void HTMLVideoElement::UpdateDisplayState() {
}
void HTMLVideoElement::PaintCurrentFrame(
- PaintCanvas* canvas,
+ cc::PaintCanvas* canvas,
const IntRect& dest_rect,
const PaintFlags* flags,
int already_uploaded_id,
@@ -465,7 +465,11 @@ scoped_refptr<Image> HTMLVideoElement::GetSourceImageForCanvas(
// argument here? Currently we use unacceleration mode.
std::unique_ptr<CanvasResourceProvider> resource_provider =
CanvasResourceProvider::Create(
- intrinsic_size, CanvasResourceProvider::kSoftwareResourceUsage);
+ intrinsic_size, CanvasResourceProvider::kSoftwareResourceUsage,
+ nullptr, // context_provider_wrapper
+ 0, // msaa_sample_count
+ CanvasColorParams(), CanvasResourceProvider::kDefaultPresentationMode,
+ nullptr); // canvas_resource_dispatcher
if (!resource_provider) {
*status = kInvalidSourceImageStatus;
return nullptr;
@@ -505,14 +509,14 @@ ScriptPromise HTMLVideoElement::CreateImageBitmap(
if (getNetworkState() == HTMLMediaElement::kNetworkEmpty) {
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kInvalidStateError,
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
"The provided element has not retrieved data."));
}
if (getReadyState() <= HTMLMediaElement::kHaveMetadata) {
return ScriptPromise::RejectWithDOMException(
script_state,
DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"The provided element's player has no current data."));
}
@@ -550,6 +554,12 @@ void HTMLVideoElement::PictureInPictureStopped() {
.OnExitedPictureInPicture(nullptr);
}
+void HTMLVideoElement::PictureInPictureControlClicked(
+ const WebString& control_id) {
+ PictureInPictureController::From(GetDocument())
+ .OnPictureInPictureControlClicked(control_id);
+}
+
WebMediaPlayer::DisplayType HTMLVideoElement::DisplayType() const {
if (is_auto_picture_in_picture_ ||
PictureInPictureController::From(GetDocument())
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 40998321f40..9eabe309d6c 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
@@ -78,9 +78,9 @@ class CORE_EXPORT HTMLVideoElement final : public HTMLMediaElement,
// Used by canvas to gain raw pixel access
void PaintCurrentFrame(
- PaintCanvas*,
+ cc::PaintCanvas*,
const IntRect&,
- const PaintFlags*,
+ const cc::PaintFlags*,
int already_uploaded_id = -1,
WebMediaPlayer::VideoFrameUploadMetadata* = nullptr) const;
@@ -149,6 +149,7 @@ class CORE_EXPORT HTMLVideoElement final : public HTMLMediaElement,
void MediaRemotingStarted(const WebString& remote_device_friendly_name) final;
bool SupportsPictureInPicture() const final;
void PictureInPictureStopped() final;
+ void PictureInPictureControlClicked(const WebString& control_id) final;
void MediaRemotingStopped(WebLocalizedString::Name error_msg) final;
WebMediaPlayer::DisplayType DisplayType() const final;
bool IsInAutoPIP() const final;
diff --git a/chromium/third_party/blink/renderer/core/html/media/html_video_element_persistent_test.cc b/chromium/third_party/blink/renderer/core/html/media/html_video_element_persistent_test.cc
index 23a223b4533..7efa11b0502 100644
--- a/chromium/third_party/blink/renderer/core/html/media/html_video_element_persistent_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/html_video_element_persistent_test.cc
@@ -12,7 +12,6 @@
#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
#include "third_party/blink/renderer/core/fullscreen/fullscreen_options.h"
#include "third_party/blink/renderer/core/html/html_div_element.h"
-#include "third_party/blink/renderer/core/layout/layout_full_screen.h"
#include "third_party/blink/renderer/core/loader/empty_clients.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
@@ -61,11 +60,11 @@ class HTMLVideoElementPersistentTest : public PageTestBase {
FullscreenMockChromeClient& GetMockChromeClient() { return *chrome_client_; }
void SimulateDidEnterFullscreen() {
- Fullscreen::FromIfExists(GetDocument())->DidEnterFullscreen();
+ Fullscreen::DidEnterFullscreen(GetDocument());
}
void SimulateDidExitFullscreen() {
- Fullscreen::FromIfExists(GetDocument())->DidExitFullscreen();
+ Fullscreen::DidExitFullscreen(GetDocument());
}
void SimulateBecamePersistentVideo(bool value) {
diff --git a/chromium/third_party/blink/renderer/core/html/media/html_video_element_test.cc b/chromium/third_party/blink/renderer/core/html/media/html_video_element_test.cc
new file mode 100644
index 00000000000..534f6027f2f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/html/media/html_video_element_test.cc
@@ -0,0 +1,94 @@
+// 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/html/media/html_video_element.h"
+
+#include "cc/layers/layer.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/dom/shadow_root.h"
+#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/core/loader/empty_clients.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+#include "third_party/blink/renderer/platform/testing/empty_web_media_player.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+
+namespace blink {
+
+class HTMLVideoElementFrameClient : public EmptyLocalFrameClient {
+ public:
+ HTMLVideoElementFrameClient()
+ : player_(std::make_unique<EmptyWebMediaPlayer>()) {}
+
+ std::unique_ptr<WebMediaPlayer> CreateWebMediaPlayer(
+ HTMLMediaElement&,
+ const WebMediaPlayerSource&,
+ WebMediaPlayerClient* client,
+ WebLayerTreeView*) override {
+ DCHECK(player_) << " Empty injected player - already used?";
+ return std::move(player_);
+ }
+
+ private:
+ std::unique_ptr<WebMediaPlayer> player_;
+};
+
+class HTMLVideoElementTest : public PageTestBase {
+ public:
+ void SetUp() override {
+ SetupPageWithClients(nullptr, new HTMLVideoElementFrameClient(), nullptr);
+ video_ = HTMLVideoElement::Create(GetDocument());
+ GetDocument().body()->appendChild(video_);
+ }
+
+ void SetFakeCcLayer(cc::Layer* layer) { video_->SetCcLayer(layer); }
+
+ HTMLVideoElement* video() { return video_.Get(); }
+
+ private:
+ Persistent<HTMLVideoElement> video_;
+};
+
+TEST_F(HTMLVideoElementTest, PictureInPictureInterstitialAndTextContainer) {
+ scoped_refptr<cc::Layer> layer = cc::Layer::Create();
+ SetFakeCcLayer(layer.get());
+
+ video()->SetBooleanAttribute(HTMLNames::controlsAttr, true);
+ video()->SetSrc("http://example.com/foo.mp4");
+ test::RunPendingTasks();
+
+ // Simulate the text track being displayed.
+ video()->UpdateTextTrackDisplay();
+ video()->UpdateTextTrackDisplay();
+
+ // Simulate entering Picture-in-Picture.
+ video()->OnEnteredPictureInPicture();
+
+ // Simulate that text track are displayed again.
+ video()->UpdateTextTrackDisplay();
+
+ EXPECT_EQ(3u, video()->EnsureUserAgentShadowRoot().CountChildren());
+
+ // Reset cc::layer to avoid crashes depending on timing.
+ SetFakeCcLayer(nullptr);
+}
+
+TEST_F(HTMLVideoElementTest, PictureInPictureInterstitial_Reattach) {
+ scoped_refptr<cc::Layer> layer = cc::Layer::Create();
+ SetFakeCcLayer(layer.get());
+
+ video()->SetBooleanAttribute(HTMLNames::controlsAttr, true);
+ video()->SetSrc("http://example.com/foo.mp4");
+ test::RunPendingTasks();
+
+ // Simulate entering Picture-in-Picture.
+ video()->OnEnteredPictureInPicture();
+
+ // Try detaching and reattaching. This should not crash.
+ GetDocument().body()->removeChild(video());
+ GetDocument().body()->appendChild(video());
+ GetDocument().body()->removeChild(video());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/media/media_controls.cc b/chromium/third_party/blink/renderer/core/html/media/media_controls.cc
index 77b99d7e1f7..d24af6e56f5 100644
--- a/chromium/third_party/blink/renderer/core/html/media/media_controls.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/media_controls.cc
@@ -8,6 +8,39 @@
namespace blink {
+namespace {
+
+// The sizing class thresholds in pixels.
+constexpr int kMediaControlsSizingMediumThreshold = 741;
+constexpr int kMediaControlsSizingLargeThreshold = 1441;
+
+} // namespace
+
+// static
+MediaControlsSizingClass MediaControls::GetSizingClass(int width) {
+ if (width < kMediaControlsSizingMediumThreshold)
+ return MediaControlsSizingClass::kSmall;
+ if (width < kMediaControlsSizingLargeThreshold)
+ return MediaControlsSizingClass::kMedium;
+
+ return MediaControlsSizingClass::kLarge;
+}
+
+// static
+AtomicString MediaControls::GetSizingCSSClass(
+ MediaControlsSizingClass sizing_class) {
+ switch (sizing_class) {
+ case MediaControlsSizingClass::kSmall:
+ return kMediaControlsSizingSmallCSSClass;
+ case MediaControlsSizingClass::kMedium:
+ return kMediaControlsSizingMediumCSSClass;
+ case MediaControlsSizingClass::kLarge:
+ return kMediaControlsSizingLargeCSSClass;
+ }
+
+ NOTREACHED();
+}
+
MediaControls::MediaControls(HTMLMediaElement& media_element)
: media_element_(&media_element) {}
diff --git a/chromium/third_party/blink/renderer/core/html/media/media_controls.h b/chromium/third_party/blink/renderer/core/html/media/media_controls.h
index 780c4dd05d7..c9e9179d152 100644
--- a/chromium/third_party/blink/renderer/core/html/media/media_controls.h
+++ b/chromium/third_party/blink/renderer/core/html/media/media_controls.h
@@ -15,10 +15,25 @@ class HTMLDivElement;
class HTMLMediaElement;
class LayoutObject;
+// The CSS class names for the different sizing thresholds.
+const char kMediaControlsSizingSmallCSSClass[] = "sizing-small";
+const char kMediaControlsSizingMediumCSSClass[] = "sizing-medium";
+const char kMediaControlsSizingLargeCSSClass[] = "sizing-large";
+
+// The different media controls sizing classes.
+enum class MediaControlsSizingClass { kSmall, kMedium, kLarge };
+
// MediaControls is an interface to abstract the HTMLMediaElement controls. The
// implementation will be used using a Factory (see below).
class CORE_EXPORT MediaControls : public GarbageCollectedMixin {
public:
+ // Get the |MediaControlsSizingClass| based on the width of the element in
+ // pixels.
+ static MediaControlsSizingClass GetSizingClass(int width);
+
+ // Get the CSS class name from the |MediaControlsSizingClass|.
+ static AtomicString GetSizingCSSClass(MediaControlsSizingClass sizing_class);
+
MediaControls(HTMLMediaElement&);
virtual ~MediaControls() = default;
diff --git a/chromium/third_party/blink/renderer/core/html/media/media_custom_controls_fullscreen_detector.cc b/chromium/third_party/blink/renderer/core/html/media/media_custom_controls_fullscreen_detector.cc
index fffc4c9240f..6ece9151c10 100644
--- a/chromium/third_party/blink/renderer/core/html/media/media_custom_controls_fullscreen_detector.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/media_custom_controls_fullscreen_detector.cc
@@ -16,7 +16,7 @@ namespace blink {
namespace {
-constexpr double kCheckFullscreenIntervalSeconds = 1.0f;
+constexpr TimeDelta kCheckFullscreenInterval = TimeDelta::FromSeconds(1);
constexpr float kMostlyFillViewportThresholdOfOccupationProportion = 0.85f;
constexpr float kMostlyFillViewportThresholdOfVisibleProportion = 0.75f;
@@ -121,8 +121,8 @@ void MediaCustomControlsFullscreenDetector::handleEvent(
return;
}
- check_viewport_intersection_timer_.StartOneShot(
- kCheckFullscreenIntervalSeconds, FROM_HERE);
+ check_viewport_intersection_timer_.StartOneShot(kCheckFullscreenInterval,
+ FROM_HERE);
}
void MediaCustomControlsFullscreenDetector::ContextDestroyed() {
diff --git a/chromium/third_party/blink/renderer/core/html/media/media_document.cc b/chromium/third_party/blink/renderer/core/html/media/media_document.cc
index 081ea4e1fd1..184bbfd83e2 100644
--- a/chromium/third_party/blink/renderer/core/html/media/media_document.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/media_document.cc
@@ -27,7 +27,6 @@
#include "base/macros.h"
#include "third_party/blink/renderer/bindings/core/v8/add_event_listener_options_or_boolean.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#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/events/event_listener.h"
@@ -48,6 +47,7 @@
#include "third_party/blink/renderer/core/html_names.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/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/keyboard_codes.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.cc b/chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.cc
index ade20438ff8..f62a329645d 100644
--- a/chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.cc
+++ b/chromium/third_party/blink/renderer/core/html/media/media_remoting_interstitial.cc
@@ -5,17 +5,18 @@
#include "third_party/blink/renderer/core/html/media/media_remoting_interstitial.h"
#include "third_party/blink/public/platform/web_localized_string.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
namespace {
-constexpr double kStyleChangeTransSeconds = 0.2;
-constexpr double kHiddenAnimationSeconds = 0.3;
-constexpr double kShowToastSeconds = 5;
+constexpr TimeDelta kStyleChangeTransitionDuration =
+ TimeDelta::FromMilliseconds(200);
+constexpr TimeDelta kHiddenAnimationDuration = TimeDelta::FromMilliseconds(300);
+constexpr TimeDelta kShowToastDuration = TimeDelta::FromSeconds(5);
} // namespace
@@ -74,7 +75,8 @@ void MediaRemotingInterstitial::Show(
RemoveInlineStyleProperty(CSSPropertyDisplay);
SetInlineStyleProperty(CSSPropertyOpacity, 0,
CSSPrimitiveValue::UnitType::kNumber);
- toggle_interstitial_timer_.StartOneShot(kStyleChangeTransSeconds, FROM_HERE);
+ toggle_interstitial_timer_.StartOneShot(kStyleChangeTransitionDuration,
+ FROM_HERE);
}
void MediaRemotingInterstitial::Hide(WebLocalizedString::Name error_msg) {
@@ -96,7 +98,7 @@ void MediaRemotingInterstitial::Hide(WebLocalizedString::Name error_msg) {
}
SetInlineStyleProperty(CSSPropertyOpacity, 0,
CSSPrimitiveValue::UnitType::kNumber);
- toggle_interstitial_timer_.StartOneShot(kHiddenAnimationSeconds, FROM_HERE);
+ toggle_interstitial_timer_.StartOneShot(kHiddenAnimationDuration, FROM_HERE);
}
void MediaRemotingInterstitial::ToggleInterstitialTimerFired(TimerBase*) {
@@ -126,7 +128,7 @@ void MediaRemotingInterstitial::ToggleInterstitialTimerFired(TimerBase*) {
toast_message_->SetInlineStyleProperty(
CSSPropertyOpacity, 1, CSSPrimitiveValue::UnitType::kNumber);
state_ = HIDDEN;
- toggle_interstitial_timer_.StartOneShot(kShowToastSeconds, FROM_HERE);
+ toggle_interstitial_timer_.StartOneShot(kShowToastDuration, FROM_HERE);
}
}
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 79e9c08c53c..3a2e574498e 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
@@ -13,6 +13,7 @@ namespace blink {
class HTMLImageElement;
class HTMLVideoElement;
+class WebString;
// Media Remoting UI. DOM structure looks like:
//
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 26717150abb..5f760986991 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
@@ -6,49 +6,83 @@
#include "cc/layers/layer.h"
#include "third_party/blink/public/platform/web_localized_string.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/geometry/dom_rect_read_only.h"
#include "third_party/blink/renderer/core/html/html_image_element.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
+#include "third_party/blink/renderer/core/html/media/media_controls.h"
+#include "third_party/blink/renderer/core/resize_observer/resize_observer.h"
+#include "third_party/blink/renderer/core/resize_observer/resize_observer_entry.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
namespace {
-constexpr double kPictureInPictureStyleChangeTransSeconds = 0.2;
-constexpr double kPictureInPictureHiddenAnimationSeconds = 0.3;
+constexpr TimeDelta kPictureInPictureStyleChangeTransitionDuration =
+ TimeDelta::FromMilliseconds(200);
+constexpr TimeDelta kPictureInPictureHiddenAnimationSeconds =
+ TimeDelta::FromMilliseconds(300);
} // namespace
namespace blink {
+class PictureInPictureInterstitial::VideoElementResizeObserverDelegate final
+ : public ResizeObserver::Delegate {
+ public:
+ explicit VideoElementResizeObserverDelegate(
+ PictureInPictureInterstitial* interstitial)
+ : interstitial_(interstitial) {
+ DCHECK(interstitial);
+ }
+ ~VideoElementResizeObserverDelegate() override = default;
+
+ void OnResize(
+ const HeapVector<Member<ResizeObserverEntry>>& entries) override {
+ DCHECK_EQ(1u, entries.size());
+ DCHECK_EQ(entries[0]->target(), interstitial_->GetVideoElement());
+ DCHECK(entries[0]->contentRect());
+ interstitial_->NotifyElementSizeChanged(*entries[0]->contentRect());
+ }
+
+ void Trace(blink::Visitor* visitor) override {
+ visitor->Trace(interstitial_);
+ ResizeObserver::Delegate::Trace(visitor);
+ }
+
+ private:
+ Member<PictureInPictureInterstitial> interstitial_;
+};
+
PictureInPictureInterstitial::PictureInPictureInterstitial(
HTMLVideoElement& videoElement)
: HTMLDivElement(videoElement.GetDocument()),
+ resize_observer_(
+ ResizeObserver::Create(videoElement.GetDocument(),
+ new VideoElementResizeObserverDelegate(this))),
interstitial_timer_(
videoElement.GetDocument().GetTaskRunner(TaskType::kInternalMedia),
this,
&PictureInPictureInterstitial::ToggleInterstitialTimerFired),
video_element_(&videoElement) {
SetShadowPseudoId(AtomicString("-internal-media-interstitial"));
+
background_image_ = HTMLImageElement::Create(GetDocument());
background_image_->SetShadowPseudoId(
AtomicString("-internal-media-interstitial-background-image"));
background_image_->SetSrc(videoElement.getAttribute(HTMLNames::posterAttr));
- AppendChild(background_image_);
-
- pip_icon_ = HTMLDivElement::Create(GetDocument());
- pip_icon_->SetShadowPseudoId(
- AtomicString("-internal-picture-in-picture-icon"));
- AppendChild(pip_icon_);
+ ParserAppendChild(background_image_);
- HTMLDivElement* message_element_ = HTMLDivElement::Create(GetDocument());
+ message_element_ = HTMLDivElement::Create(GetDocument());
message_element_->SetShadowPseudoId(
- AtomicString("-internal-media-interstitial-message"));
+ AtomicString("-internal-picture-in-picture-interstitial-message"));
message_element_->setInnerText(
GetVideoElement().GetLocale().QueryString(
WebLocalizedString::kPictureInPictureInterstitialText),
ASSERT_NO_EXCEPTION);
- AppendChild(message_element_);
+ ParserAppendChild(message_element_);
+
+ resize_observer_->observe(video_element_);
}
void PictureInPictureInterstitial::Show() {
@@ -59,8 +93,8 @@ void PictureInPictureInterstitial::Show() {
interstitial_timer_.Stop();
should_be_visible_ = true;
RemoveInlineStyleProperty(CSSPropertyDisplay);
- interstitial_timer_.StartOneShot(kPictureInPictureStyleChangeTransSeconds,
- FROM_HERE);
+ interstitial_timer_.StartOneShot(
+ kPictureInPictureStyleChangeTransitionDuration, FROM_HERE);
DCHECK(GetVideoElement().CcLayer());
GetVideoElement().CcLayer()->SetIsDrawable(false);
@@ -82,6 +116,34 @@ void PictureInPictureInterstitial::Hide() {
GetVideoElement().CcLayer()->SetIsDrawable(true);
}
+Node::InsertionNotificationRequest PictureInPictureInterstitial::InsertedInto(
+ ContainerNode* root) {
+ if (GetVideoElement().isConnected() && !resize_observer_) {
+ resize_observer_ =
+ ResizeObserver::Create(GetVideoElement().GetDocument(),
+ new VideoElementResizeObserverDelegate(this));
+ resize_observer_->observe(&GetVideoElement());
+ }
+
+ return HTMLDivElement::InsertedInto(root);
+}
+
+void PictureInPictureInterstitial::RemovedFrom(ContainerNode*) {
+ DCHECK(!GetVideoElement().isConnected());
+
+ if (resize_observer_) {
+ resize_observer_->disconnect();
+ resize_observer_.Clear();
+ }
+}
+
+void PictureInPictureInterstitial::NotifyElementSizeChanged(
+ const DOMRectReadOnly& new_size) {
+ message_element_->setAttribute(
+ "class", MediaControls::GetSizingCSSClass(
+ MediaControls::GetSizingClass(new_size.width())));
+}
+
void PictureInPictureInterstitial::ToggleInterstitialTimerFired(TimerBase*) {
interstitial_timer_.Stop();
if (should_be_visible_) {
@@ -99,9 +161,9 @@ void PictureInPictureInterstitial::OnPosterImageChanged() {
}
void PictureInPictureInterstitial::Trace(blink::Visitor* visitor) {
+ visitor->Trace(resize_observer_);
visitor->Trace(video_element_);
visitor->Trace(background_image_);
- visitor->Trace(pip_icon_);
visitor->Trace(message_element_);
HTMLDivElement::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.h b/chromium/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.h
index cbabb23174b..991b29da40b 100644
--- a/chromium/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.h
+++ b/chromium/third_party/blink/renderer/core/html/media/picture_in_picture_interstitial.h
@@ -10,8 +10,10 @@
namespace blink {
+class DOMRectReadOnly;
class HTMLImageElement;
class HTMLVideoElement;
+class ResizeObserver;
// Picture in Picture UI. DOM structure looks like:
//
@@ -20,9 +22,7 @@ class HTMLVideoElement;
// +-HTMLImageElement
// | (-internal-media-interstitial-background-image)
// \-HTMLDivElement
-// | (-internal-picture-in-picture-icon)
-// \-HTMLDivElement
-// | (-internal-media-interstitial-message)
+// | (-internal-picture-in-picture-interstitial-message)
class PictureInPictureInterstitial final : public HTMLDivElement {
public:
explicit PictureInPictureInterstitial(HTMLVideoElement&);
@@ -35,23 +35,35 @@ class PictureInPictureInterstitial final : public HTMLDivElement {
HTMLVideoElement& GetVideoElement() const { return *video_element_; }
+ // Node override.
+ Node::InsertionNotificationRequest InsertedInto(ContainerNode*) override;
+ void RemovedFrom(ContainerNode*) override;
+
// Element:
void Trace(blink::Visitor*) override;
private:
+ class VideoElementResizeObserverDelegate;
+
// Node override.
bool IsPictureInPictureInterstitial() const override { return true; }
+ // Notify us that our controls enclosure has changed size.
+ void NotifyElementSizeChanged(const DOMRectReadOnly& new_size);
+
void ToggleInterstitialTimerFired(TimerBase*);
// Indicates whether the interstitial should be visible. It is updated
// when Show()/Hide() is called.
bool should_be_visible_ = false;
+ // Watches the video element for resize and updates the intersitial as
+ // necessary.
+ Member<ResizeObserver> resize_observer_;
+
TaskRunnerTimer<PictureInPictureInterstitial> interstitial_timer_;
Member<HTMLVideoElement> video_element_;
Member<HTMLImageElement> background_image_;
- Member<HTMLDivElement> pip_icon_;
Member<HTMLDivElement> message_element_;
};
diff --git a/chromium/third_party/blink/renderer/core/html/parser/css_preload_scanner.cc b/chromium/third_party/blink/renderer/core/html/parser/css_preload_scanner.cc
index 97a03b64885..cbe3e41b259 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/css_preload_scanner.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/css_preload_scanner.cc
@@ -298,7 +298,7 @@ void CSSPreloaderResourceClient::ScanCSS(
// TODO(csharrison): If this becomes an issue the CSSPreloadScanner may be
// augmented to take care of this case without performing an additional
// copy.
- double start_time = CurrentTimeTicksInMilliseconds();
+ TimeTicks start_time = CurrentTimeTicks();
const String& chunk = resource->SheetText(nullptr);
if (chunk.IsNull())
return;
@@ -316,10 +316,9 @@ void CSSPreloaderResourceClient::ScanCSS(
PreloadRequestStream preloads;
css_preload_scanner.Scan(chunk, SegmentedString(), preloads,
resource->GetResponse().Url());
- DEFINE_STATIC_LOCAL(CustomCountHistogram, css_scan_time_histogram,
- ("PreloadScanner.ExternalCSS.ScanTime", 1, 1000000, 50));
- css_scan_time_histogram.Count(
- (CurrentTimeTicksInMilliseconds() - start_time) * 1000);
+ UMA_HISTOGRAM_CUSTOM_TIMES(
+ "PreloadScanner.ExternalCSS.ScanTime", CurrentTimeTicks() - start_time,
+ TimeDelta::FromMilliseconds(1), TimeDelta::FromSeconds(1000), 50);
FetchPreloads(preloads);
}
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 1af53c1f0c2..a8dce6adcdd 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
@@ -691,7 +691,10 @@ void HTMLConstructionSite::InsertHTMLFormElement(AtomicHTMLToken* token,
ToHTMLFormElement(CreateElement(token, xhtmlNamespaceURI));
if (!OpenElements()->HasTemplateInHTMLScope())
form_ = form_element;
- form_element->SetDemoted(is_demoted);
+ if (is_demoted) {
+ UseCounter::Count(OwnerDocumentForCurrentNode(),
+ WebFeature::kDemotedFormElement);
+ }
AttachLater(CurrentNode(), form_element);
open_elements_.Push(HTMLStackItem::Create(form_element, token));
}
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_document_parser.cc b/chromium/third_party/blink/renderer/core/html/parser/html_document_parser.cc
index 93275aea30f..36069afb504 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_document_parser.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_document_parser.cc
@@ -175,11 +175,6 @@ void HTMLDocumentParser::Trace(blink::Visitor* visitor) {
HTMLParserScriptRunnerHost::Trace(visitor);
}
-void HTMLDocumentParser::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(script_runner_);
- ScriptableDocumentParser::TraceWrappers(visitor);
-}
-
void HTMLDocumentParser::Detach() {
if (have_background_parser_)
StopBackgroundParser();
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_document_parser.h b/chromium/third_party/blink/renderer/core/html/parser/html_document_parser.h
index 80fc7c1e21f..171f7eb4905 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_document_parser.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_document_parser.h
@@ -79,7 +79,6 @@ class CORE_EXPORT HTMLDocumentParser : public ScriptableDocumentParser,
}
~HTMLDocumentParser() override;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
// TODO(alexclarke): Remove when background parser goes away.
void Dispose();
diff --git a/chromium/third_party/blink/renderer/core/html/parser/html_parser_idioms.h b/chromium/third_party/blink/renderer/core/html/parser/html_parser_idioms.h
index 0149e4a4281..81dd1b81a07 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/html_parser_idioms.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/html_parser_idioms.h
@@ -27,7 +27,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/qualified_name.h"
-#include "third_party/blink/renderer/platform/decimal.h"
+#include "third_party/blink/renderer/platform/wtf/decimal.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
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 f69beac6c41..3feabddb03a 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
@@ -29,6 +29,7 @@
#include <memory>
#include "base/optional.h"
+#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
#include "third_party/blink/renderer/core/css/media_list.h"
#include "third_party/blink/renderer/core/css/media_query_evaluator.h"
#include "third_party/blink/renderer/core/css/media_values_cached.h"
@@ -36,6 +37,7 @@
#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/settings.h"
+#include "third_party/blink/renderer/core/frame/viewport_data.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/html_meta_element.h"
@@ -45,6 +47,7 @@
#include "third_party/blink/renderer/core/html/parser/html_tokenizer.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/input_type_names.h"
+#include "third_party/blink/renderer/core/loader/importance_attribute.h"
#include "third_party/blink/renderer/core/loader/link_loader.h"
#include "third_party/blink/renderer/core/loader/subresource_integrity_helper.h"
#include "third_party/blink/renderer/core/script/script_loader.h"
@@ -132,6 +135,8 @@ class TokenPreloadScanner::StartTagScanner {
source_size_set_(false),
defer_(FetchParameters::kNoDefer),
cross_origin_(kCrossOriginAttributeNotSet),
+ importance_(mojom::FetchImportanceMode::kImportanceAuto),
+ importance_mode_set_(false),
media_values_(media_values),
referrer_policy_set_(false),
referrer_policy_(kReferrerPolicyDefault),
@@ -262,6 +267,7 @@ class TokenPreloadScanner::StartTagScanner {
}
request->SetCrossOrigin(cross_origin_);
+ request->SetImportance(importance_);
request->SetNonce(nonce_);
request->SetCharset(Charset());
request->SetDefer(defer_);
@@ -320,10 +326,10 @@ class TokenPreloadScanner::StartTagScanner {
} else if (!referrer_policy_set_ &&
Match(attribute_name, referrerpolicyAttr) &&
!attribute_value.IsNull()) {
- referrer_policy_set_ = true;
- SecurityPolicy::ReferrerPolicyFromString(
- attribute_value, kSupportReferrerPolicyLegacyKeywords,
- &referrer_policy_);
+ SetReferrerPolicy(attribute_value, kSupportReferrerPolicyLegacyKeywords);
+ } else if (!importance_mode_set_ && Match(attribute_name, importanceAttr) &&
+ RuntimeEnabledFeatures::PriorityHintsEnabled()) {
+ SetImportance(attribute_value);
}
}
@@ -367,10 +373,8 @@ class TokenPreloadScanner::StartTagScanner {
} else if (!referrer_policy_set_ &&
Match(attribute_name, referrerpolicyAttr) &&
!attribute_value.IsNull()) {
- referrer_policy_set_ = true;
- SecurityPolicy::ReferrerPolicyFromString(
- attribute_value, kDoNotSupportReferrerPolicyLegacyKeywords,
- &referrer_policy_);
+ SetReferrerPolicy(attribute_value,
+ kDoNotSupportReferrerPolicyLegacyKeywords);
} else if (!integrity_attr_set_ && Match(attribute_name, integrityAttr)) {
integrity_attr_set_ = true;
SubresourceIntegrity::ParseIntegrityAttribute(
@@ -380,6 +384,9 @@ class TokenPreloadScanner::StartTagScanner {
srcset_attribute_value_ = attribute_value;
} else if (Match(attribute_name, imgsizesAttr) && !source_size_set_) {
ParseSourceSize(attribute_value);
+ } else if (!importance_mode_set_ && Match(attribute_name, importanceAttr) &&
+ RuntimeEnabledFeatures::PriorityHintsEnabled()) {
+ SetImportance(attribute_value);
}
}
@@ -566,6 +573,20 @@ class TokenPreloadScanner::StartTagScanner {
cross_origin_ = GetCrossOriginAttributeValue(cors_setting);
}
+ void SetReferrerPolicy(
+ const String& attribute_value,
+ ReferrerPolicyLegacyKeywordsSupport legacy_keywords_support) {
+ referrer_policy_set_ = true;
+ SecurityPolicy::ReferrerPolicyFromString(
+ attribute_value, legacy_keywords_support, &referrer_policy_);
+ }
+
+ void SetImportance(const String& importance) {
+ DCHECK(RuntimeEnabledFeatures::PriorityHintsEnabled());
+ importance_mode_set_ = true;
+ importance_ = GetFetchImportanceAttributeValue(importance);
+ }
+
void SetNonce(const String& nonce) { nonce_ = nonce; }
void SetDefer(FetchParameters::DeferOption defer) { defer_ = defer; }
@@ -593,6 +614,8 @@ class TokenPreloadScanner::StartTagScanner {
bool source_size_set_;
FetchParameters::DeferOption defer_;
CrossOriginAttributeValue cross_origin_;
+ mojom::FetchImportanceMode importance_;
+ bool importance_mode_set_;
String nonce_;
Member<MediaValuesCached> media_values_;
bool referrer_policy_set_;
@@ -914,7 +937,8 @@ CachedDocumentParameters::CachedDocumentParameters(Document* document) {
do_html_preload_scanning =
!document->GetSettings() ||
document->GetSettings()->GetDoHtmlPreloadScanning();
- default_viewport_min_width = document->ViewportDefaultMinWidth();
+ default_viewport_min_width =
+ document->GetViewportData().ViewportDefaultMinWidth();
viewport_meta_zero_values_quirk =
document->GetSettings() &&
document->GetSettings()->GetViewportMetaZeroValuesQuirk();
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 94ea23c67e9..f9ebf74bc25 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
@@ -34,11 +34,11 @@
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/css/media_values_cached.h"
-#include "third_party/blink/renderer/core/dom/viewport_description.h"
#include "third_party/blink/renderer/core/html/parser/compact_html_token.h"
#include "third_party/blink/renderer/core/html/parser/css_preload_scanner.h"
#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/text/segmented_string.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
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 3ee02bac30c..e3b72a13d59 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
@@ -657,7 +657,6 @@ TEST_F(HTMLPreloadScannerTest, testMetaAcceptCHInsecureDocument) {
all};
// For an insecure document, client hint should not be attached.
- WebRuntimeFeatures::EnableClientHintsPersistent(true);
RunSetUp(kViewportDisabled, kPreloadEnabled, kReferrerPolicyDefault,
false /* use_secure_document_url */);
Test(expect_no_client_hint);
@@ -666,13 +665,6 @@ TEST_F(HTMLPreloadScannerTest, testMetaAcceptCHInsecureDocument) {
RunSetUp(kViewportDisabled, kPreloadEnabled, kReferrerPolicyDefault,
true /* use_secure_document_url */);
Test(expect_client_hint);
-
- // For an insecure document, client hint should be attached if the persistent
- // client hints are not enabled.
- WebRuntimeFeatures::EnableClientHintsPersistent(false);
- RunSetUp(kViewportDisabled, kPreloadEnabled, kReferrerPolicyDefault,
- false /* use_secure_document_url */);
- Test(expect_client_hint);
}
TEST_F(HTMLPreloadScannerTest, testPreconnect) {
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 dd11e86bed8..bbfd0b70b7d 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
@@ -29,7 +29,6 @@
#include <memory>
#include "base/macros.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/document_fragment.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
@@ -49,6 +48,7 @@
#include "third_party/blink/renderer/core/xlink_names.h"
#include "third_party/blink/renderer/core/xml_names.h"
#include "third_party/blink/renderer/core/xmlns_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
@@ -552,7 +552,8 @@ void HTMLTreeBuilder::ProcessStartTagForInBody(AtomicHTMLToken* token) {
token->GetName() == bgsoundTag || token->GetName() == commandTag ||
token->GetName() == linkTag || token->GetName() == metaTag ||
token->GetName() == noframesTag || token->GetName() == scriptTag ||
- token->GetName() == styleTag || token->GetName() == titleTag) {
+ token->GetName() == styleTag || token->GetName() == titleTag ||
+ token->GetName() == templateTag) {
bool did_process = ProcessStartTagForInHead(token);
DCHECK(did_process);
return;
@@ -847,10 +848,6 @@ void HTMLTreeBuilder::ProcessStartTagForInBody(AtomicHTMLToken* token) {
ParseError(token);
return;
}
- if (token->GetName() == templateTag) {
- ProcessTemplateStartTag(token);
- return;
- }
tree_.ReconstructTheActiveFormattingElements();
tree_.InsertHTMLElement(token);
}
@@ -1237,10 +1234,6 @@ void HTMLTreeBuilder::ProcessStartTag(AtomicHTMLToken* token) {
ProcessStartTagForInHead(token);
return;
}
- if (token->GetName() == templateTag) {
- ProcessTemplateStartTag(token);
- return;
- }
ParseError(token);
break;
case kAfterFramesetMode:
@@ -1346,9 +1339,7 @@ void HTMLTreeBuilder::ProcessStartTag(AtomicHTMLToken* token) {
}
InsertionMode insertion_mode = kTemplateContentsMode;
- if (token->GetName() == frameTag)
- insertion_mode = kInFramesetMode;
- else if (token->GetName() == colTag)
+ if (token->GetName() == colTag)
insertion_mode = kInColumnGroupMode;
else if (IsCaptionColOrColgroupTag(token->GetName()) ||
IsTableBodyContextTag(token->GetName()))
@@ -2068,10 +2059,6 @@ void HTMLTreeBuilder::ProcessEndTag(AtomicHTMLToken* token) {
SetInsertionMode(kAfterFramesetMode);
return;
}
- if (token->GetName() == templateTag) {
- ProcessTemplateEndTag(token);
- return;
- }
break;
case kAfterFramesetMode:
DCHECK_EQ(GetInsertionMode(), kAfterFramesetMode);
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 ff177dd84ae..37d3d704128 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
@@ -13,6 +13,7 @@
#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/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
namespace blink {
@@ -44,6 +45,8 @@ Resource* PreloadRequest::Start(Document* document,
resource_request.SetRequestContext(ResourceFetcher::DetermineRequestContext(
resource_type_, is_image_set_, false));
+ resource_request.SetFetchImportanceMode(importance_);
+
ResourceLoaderOptions options;
options.initiator_info = initiator_info;
FetchParameters params(resource_request, options);
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 17555a79e54..04d1ac5f95c 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
@@ -8,6 +8,7 @@
#include <memory>
#include "base/memory/ptr_util.h"
+#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/script/script.h"
#include "third_party/blink/renderer/platform/cross_origin_attribute_value.h"
@@ -76,6 +77,11 @@ class CORE_EXPORT PreloadRequest {
}
CrossOriginAttributeValue CrossOrigin() const { return cross_origin_; }
+ void SetImportance(mojom::FetchImportanceMode importance) {
+ importance_ = importance;
+ }
+ mojom::FetchImportanceMode Importance() const { return importance_; }
+
void SetNonce(const String& nonce) { nonce_ = nonce; }
const String& Nonce() const { return nonce_; }
@@ -134,6 +140,7 @@ class CORE_EXPORT PreloadRequest {
resource_type_(resource_type),
script_type_(ScriptType::kClassic),
cross_origin_(kCrossOriginAttributeNotSet),
+ importance_(mojom::FetchImportanceMode::kImportanceAuto),
defer_(FetchParameters::kNoDefer),
resource_width_(resource_width),
client_hints_preferences_(client_hints_preferences),
@@ -153,6 +160,7 @@ class CORE_EXPORT PreloadRequest {
Resource::Type resource_type_;
ScriptType script_type_;
CrossOriginAttributeValue cross_origin_;
+ mojom::FetchImportanceMode importance_;
String nonce_;
FetchParameters::DeferOption defer_;
FetchParameters::ResourceWidth resource_width_;
diff --git a/chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder.cc b/chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder.cc
index f75f1e6d263..03dbb6f42b3 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder.cc
@@ -126,7 +126,8 @@ TextResourceDecoder::TextResourceDecoder(
checked_for_css_charset_(false),
checked_for_xml_charset_(false),
checked_for_meta_charset_(false),
- saw_error_(false) {
+ saw_error_(false),
+ detection_completed_(false) {
// TODO(hiroshige): Move the invariant check to TextResourceDecoderOptions.
if (options_.GetEncodingDetectionOption() ==
TextResourceDecoderOptions::kAlwaysUseUTF8ForText) {
@@ -373,7 +374,8 @@ void TextResourceDecoder::CheckForMetaCharset(const char* data, size_t length) {
void TextResourceDecoder::AutoDetectEncodingIfAllowed(const char* data,
size_t len) {
if (options_.GetEncodingDetectionOption() !=
- TextResourceDecoderOptions::kUseAllAutoDetection)
+ TextResourceDecoderOptions::kUseAllAutoDetection ||
+ detection_completed_)
return;
// Just checking hint_encoding_ suffices here because it's only set
@@ -386,6 +388,8 @@ void TextResourceDecoder::AutoDetectEncodingIfAllowed(const char* data,
if (DetectTextEncoding(data, len, options_.HintEncoding(), options_.HintURL(),
options_.HintLanguage(), &detected_encoding))
SetEncoding(detected_encoding, kEncodingFromContentSniffing);
+ if (detected_encoding != WTF::UnknownEncoding())
+ detection_completed_ = true;
}
String TextResourceDecoder::Decode(const char* data, size_t len) {
@@ -446,7 +450,7 @@ String TextResourceDecoder::Decode(const char* data, size_t len) {
codec_ = NewTextCodec(encoding_);
String result = codec_->Decode(
- data_for_decode, length_for_decode, WTF::kDoNotFlush,
+ data_for_decode, length_for_decode, WTF::FlushBehavior::kDoNotFlush,
options_.GetContentType() == TextResourceDecoderOptions::kXMLContent &&
!options_.GetUseLenientXMLDecoding(),
saw_error_);
@@ -474,7 +478,7 @@ String TextResourceDecoder::Flush() {
codec_ = NewTextCodec(encoding_);
String result = codec_->Decode(
- buffer_.data(), buffer_.size(), WTF::kFetchEOF,
+ buffer_.data(), buffer_.size(), WTF::FlushBehavior::kFetchEOF,
options_.GetContentType() == TextResourceDecoderOptions::kXMLContent &&
!options_.GetUseLenientXMLDecoding(),
saw_error_);
diff --git a/chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder.h b/chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder.h
index 4d4b24428a6..c47a5ee7f48 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder.h
+++ b/chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder.h
@@ -95,6 +95,7 @@ class CORE_EXPORT TextResourceDecoder {
bool checked_for_xml_charset_;
bool checked_for_meta_charset_;
bool saw_error_;
+ bool detection_completed_;
std::unique_ptr<HTMLMetaCharsetParser> charset_parser_;
diff --git a/chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder_test.cc b/chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder_test.cc
index 1e0b9e67c02..ae1912f48a6 100644
--- a/chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/parser/text_resource_decoder_test.cc
@@ -44,4 +44,26 @@ TEST(TextResourceDecoderTest, UTF16Pieces) {
EXPECT_EQ("foo", decoded);
}
+TEST(TextResourceDecoderTest, ContentSniffingStopsAfterSuccess) {
+ std::unique_ptr<TextResourceDecoder> decoder = TextResourceDecoder::Create(
+ TextResourceDecoderOptions::CreateWithAutoDetection(
+ TextResourceDecoderOptions::kPlainTextContent, WTF::UTF8Encoding(),
+ WTF::UTF8Encoding(), KURL("")));
+
+ std::string utf8_bytes =
+ "tnegirjji gosa gii beare s\xC3\xA1htt\xC3\xA1 \xC4\x8D\xC3"
+ "\xA1llit artihkkaliid. Maid don s\xC3\xA1ht\xC3\xA1t dievasmah";
+
+ std::string eucjp_bytes =
+ "<TITLE>"
+ "\xA5\xD1\xA5\xEF\xA1\xBC\xA5\xC1\xA5\xE3\xA1\xBC\xA5\xC8\xA1\xC3\xC5\xEA"
+ "\xBB\xF1\xBE\xF0\xCA\xF3\xA4\xCE\xA5\xD5\xA5\xA3\xA5\xB9\xA5\xB3</"
+ "TITLE>";
+
+ decoder->Decode(utf8_bytes.c_str(), utf8_bytes.length());
+ EXPECT_EQ(WTF::UTF8Encoding(), decoder->Encoding());
+ decoder->Decode(eucjp_bytes.c_str(), eucjp_bytes.length());
+ EXPECT_EQ(WTF::UTF8Encoding(), decoder->Encoding());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/plugin_document.cc b/chromium/third_party/blink/renderer/core/html/plugin_document.cc
index 5e50b2d2308..0a9ae8d42af 100644
--- a/chromium/third_party/blink/renderer/core/html/plugin_document.cc
+++ b/chromium/third_party/blink/renderer/core/html/plugin_document.cc
@@ -24,10 +24,12 @@
#include "third_party/blink/renderer/core/html/plugin_document.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css/css_color_value.h"
+#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/dom/raw_data_document_parser.h"
+#include "third_party/blink/renderer/core/events/before_unload_event.h"
#include "third_party/blink/renderer/core/exported/web_plugin_container_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/local_frame_view.h"
@@ -40,11 +42,45 @@
#include "third_party/blink/renderer/core/layout/layout_embedded_object.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/platform/bindings/exception_state.h"
namespace blink {
using namespace HTMLNames;
+class PluginDocument::BeforeUnloadEventListener : public EventListener {
+ public:
+ static BeforeUnloadEventListener* Create(PluginDocument* document) {
+ return new BeforeUnloadEventListener(document);
+ }
+
+ bool operator==(const EventListener& listener) const override {
+ return this == &listener;
+ }
+
+ void SetShowBeforeUnloadDialog(bool show_dialog) {
+ show_dialog_ = show_dialog;
+ }
+
+ void Trace(blink::Visitor* visitor) override {
+ visitor->Trace(doc_);
+ EventListener::Trace(visitor);
+ }
+
+ private:
+ explicit BeforeUnloadEventListener(PluginDocument* document)
+ : EventListener(kCPPEventListenerType), doc_(document) {}
+
+ void handleEvent(ExecutionContext*, Event* event) override {
+ DCHECK_EQ(event->type(), EventTypeNames::beforeunload);
+ if (show_dialog_)
+ ToBeforeUnloadEvent(event)->setReturnValue(g_empty_string);
+ }
+
+ Member<PluginDocument> doc_;
+ bool show_dialog_;
+};
+
// FIXME: Share more code with MediaDocumentParser.
class PluginDocumentParser : public RawDataDocumentParser {
public:
@@ -186,14 +222,28 @@ WebPluginContainerImpl* PluginDocument::GetPluginView() {
return plugin_node_ ? plugin_node_->OwnedPlugin() : nullptr;
}
+void PluginDocument::SetShowBeforeUnloadDialog(bool show_dialog) {
+ if (!before_unload_event_listener_) {
+ if (!show_dialog)
+ return;
+
+ before_unload_event_listener_ = BeforeUnloadEventListener::Create(this);
+ domWindow()->addEventListener(EventTypeNames::beforeunload,
+ before_unload_event_listener_, false);
+ }
+ before_unload_event_listener_->SetShowBeforeUnloadDialog(show_dialog);
+}
+
void PluginDocument::Shutdown() {
// Release the plugin node so that we don't have a circular reference.
plugin_node_ = nullptr;
+ before_unload_event_listener_ = nullptr;
HTMLDocument::Shutdown();
}
void PluginDocument::Trace(blink::Visitor* visitor) {
visitor->Trace(plugin_node_);
+ visitor->Trace(before_unload_event_listener_);
HTMLDocument::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/html/plugin_document.h b/chromium/third_party/blink/renderer/core/html/plugin_document.h
index ae2549a8570..5566a47a21f 100644
--- a/chromium/third_party/blink/renderer/core/html/plugin_document.h
+++ b/chromium/third_party/blink/renderer/core/html/plugin_document.h
@@ -48,16 +48,22 @@ class CORE_EXPORT PluginDocument final : public HTMLDocument {
WebPluginContainerImpl* GetPluginView();
+ void SetShowBeforeUnloadDialog(bool show_dialog);
+
void Shutdown() override;
void Trace(blink::Visitor*) override;
private:
+ class BeforeUnloadEventListener;
+
PluginDocument(const DocumentInit&, Color background_color);
DocumentParser* CreateParser() override;
Member<HTMLPlugInElement> plugin_node_;
+ Member<BeforeUnloadEventListener> before_unload_event_listener_;
+
const Color background_color_;
};
diff --git a/chromium/third_party/blink/renderer/core/html/time_ranges.cc b/chromium/third_party/blink/renderer/core/html/time_ranges.cc
index e5ef20f198c..6b4e24779c1 100644
--- a/chromium/third_party/blink/renderer/core/html/time_ranges.cc
+++ b/chromium/third_party/blink/renderer/core/html/time_ranges.cc
@@ -26,9 +26,9 @@
#include "third_party/blink/renderer/core/html/time_ranges.h"
#include <math.h>
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -108,7 +108,7 @@ double TimeRanges::start(unsigned index,
ExceptionState& exception_state) const {
if (index >= length()) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
ExceptionMessages::IndexExceedsMaximumBound("index", index, length()));
return 0;
}
@@ -118,7 +118,7 @@ double TimeRanges::start(unsigned index,
double TimeRanges::end(unsigned index, ExceptionState& exception_state) const {
if (index >= length()) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
ExceptionMessages::IndexExceedsMaximumBound("index", index, length()));
return 0;
}
diff --git a/chromium/third_party/blink/renderer/core/html/time_ranges_test.cc b/chromium/third_party/blink/renderer/core/html/time_ranges_test.cc
index 02de089382a..5f159533a73 100644
--- a/chromium/third_party/blink/renderer/core/html/time_ranges_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/time_ranges_test.cc
@@ -32,7 +32,7 @@
#include <sstream>
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/html/track/cue_timeline.cc b/chromium/third_party/blink/renderer/core/html/track/cue_timeline.cc
index b6597133285..83c161d0b50 100644
--- a/chromium/third_party/blink/renderer/core/html/track/cue_timeline.cc
+++ b/chromium/third_party/blink/renderer/core/html/track/cue_timeline.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/html/track/cue_timeline.h"
#include <algorithm>
+#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/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/html/track/html_track_element.h"
diff --git a/chromium/third_party/blink/renderer/core/html/track/html_track_element.idl b/chromium/third_party/blink/renderer/core/html/track/html_track_element.idl
index 926385641e7..bcafa6726f3 100644
--- a/chromium/third_party/blink/renderer/core/html/track/html_track_element.idl
+++ b/chromium/third_party/blink/renderer/core/html/track/html_track_element.idl
@@ -24,10 +24,14 @@
*/
// https://html.spec.whatwg.org/#the-track-element
+
+// The `URLString` reference below is from Trusted Types:
+// https://github.com/WICG/trusted-types/, which is still WIP.
+// https://crbug.com/739170.
[HTMLConstructor]
interface HTMLTrackElement : HTMLElement {
[CEReactions] attribute DOMString kind;
- [CEReactions, Reflect, URL] attribute DOMString src;
+ [CEReactions, Reflect, URL, RaisesException=Setter] attribute URLString src;
[CEReactions, Reflect] attribute DOMString srclang;
[CEReactions, Reflect] attribute DOMString label;
[CEReactions, Reflect] attribute boolean default;
diff --git a/chromium/third_party/blink/renderer/core/html/track/text_track.cc b/chromium/third_party/blink/renderer/core/html/track/text_track.cc
index e7d173de563..917e76a2f94 100644
--- a/chromium/third_party/blink/renderer/core/html/track/text_track.cc
+++ b/chromium/third_party/blink/renderer/core/html/track/text_track.cc
@@ -31,12 +31,11 @@
#include "third_party/blink/renderer/core/html/track/text_track.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/html/track/cue_timeline.h"
#include "third_party/blink/renderer/core/html/track/text_track_cue_list.h"
#include "third_party/blink/renderer/core/html/track/text_track_list.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -253,7 +252,7 @@ void TextTrack::removeCue(TextTrackCue* cue, ExceptionState& exception_state) {
// exception.
if (cue->track() != this) {
exception_state.ThrowDOMException(
- kNotFoundError,
+ DOMExceptionCode::kNotFoundError,
"The specified cue is not listed in the TextTrack's list of cues.");
return;
}
@@ -377,9 +376,4 @@ void TextTrack::Trace(blink::Visitor* visitor) {
EventTargetWithInlineData::Trace(visitor);
}
-void TextTrack::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(cues_);
- EventTargetWithInlineData::TraceWrappers(visitor);
- TrackBase::TraceWrappers(visitor);
-}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/track/text_track.h b/chromium/third_party/blink/renderer/core/html/track/text_track.h
index ae2260c32a5..323e86eeb7c 100644
--- a/chromium/third_party/blink/renderer/core/html/track/text_track.h
+++ b/chromium/third_party/blink/renderer/core/html/track/text_track.h
@@ -127,8 +127,6 @@ class CORE_EXPORT TextTrack : public EventTargetWithInlineData,
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
protected:
TextTrack(const AtomicString& kind,
const AtomicString& label,
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 e73511b4b06..2b39733f1f4 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
@@ -85,6 +85,11 @@ TextTrackContainer* TextTrackContainer::Create(
}
LayoutObject* TextTrackContainer::CreateLayoutObject(const ComputedStyle&) {
+ // TODO(mstensho): Should use LayoutObjectFactory to create the right type of
+ // object here, to enable LayoutNG, but currently we can't, because this will
+ // typically be a child of LayoutVideo (a legacy type), and we'll typically
+ // also insert a LayoutVTTCue (a LayoutBlockFlow type) child, which also isn't
+ // implemented in NG.
return new LayoutBlockFlow(this);
}
diff --git a/chromium/third_party/blink/renderer/core/html/track/text_track_cue.cc b/chromium/third_party/blink/renderer/core/html/track/text_track_cue.cc
index 13d61513fea..dd087a5a5a9 100644
--- a/chromium/third_party/blink/renderer/core/html/track/text_track_cue.cc
+++ b/chromium/third_party/blink/renderer/core/html/track/text_track_cue.cc
@@ -31,11 +31,10 @@
#include "third_party/blink/renderer/core/html/track/text_track_cue.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/html/track/text_track.h"
#include "third_party/blink/renderer/core/html/track/text_track_cue_list.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/html/track/text_track_cue_list.cc b/chromium/third_party/blink/renderer/core/html/track/text_track_cue_list.cc
index 2cfa63bbdf7..e176cc1d1c4 100644
--- a/chromium/third_party/blink/renderer/core/html/track/text_track_cue_list.cc
+++ b/chromium/third_party/blink/renderer/core/html/track/text_track_cue_list.cc
@@ -144,10 +144,4 @@ void TextTrackCueList::Trace(blink::Visitor* visitor) {
ScriptWrappable::Trace(visitor);
}
-void TextTrackCueList::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- for (auto cue : list_) {
- visitor->TraceWrappers(cue);
- }
- ScriptWrappable::TraceWrappers(visitor);
-}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/track/text_track_cue_list.h b/chromium/third_party/blink/renderer/core/html/track/text_track_cue_list.h
index 2550f3b8fc2..d47bff1bad8 100644
--- a/chromium/third_party/blink/renderer/core/html/track/text_track_cue_list.h
+++ b/chromium/third_party/blink/renderer/core/html/track/text_track_cue_list.h
@@ -57,7 +57,6 @@ class TextTrackCueList final : public ScriptWrappable {
void ValidateCueIndexes();
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
TextTrackCueList();
diff --git a/chromium/third_party/blink/renderer/core/html/track/text_track_list.cc b/chromium/third_party/blink/renderer/core/html/track/text_track_list.cc
index 991b69518ff..1e347714595 100644
--- a/chromium/third_party/blink/renderer/core/html/track/text_track_list.cc
+++ b/chromium/third_party/blink/renderer/core/html/track/text_track_list.cc
@@ -25,20 +25,16 @@
#include "third_party/blink/renderer/core/html/track/text_track_list.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/events/media_element_event_queue.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/html/track/inband_text_track.h"
#include "third_party/blink/renderer/core/html/track/loadable_text_track.h"
#include "third_party/blink/renderer/core/html/track/text_track.h"
#include "third_party/blink/renderer/core/html/track/track_event.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
-TextTrackList::TextTrackList(HTMLMediaElement* owner)
- : owner_(owner),
- async_event_queue_(
- MediaElementEventQueue::Create(this, &owner_->GetDocument())) {}
+TextTrackList::TextTrackList(HTMLMediaElement* owner) : owner_(owner) {}
TextTrackList::~TextTrackList() = default;
@@ -249,8 +245,8 @@ ExecutionContext* TextTrackList::GetExecutionContext() const {
void TextTrackList::ScheduleTrackEvent(const AtomicString& event_name,
TextTrack* track) {
- async_event_queue_->EnqueueEvent(FROM_HERE,
- TrackEvent::Create(event_name, track));
+ EnqueueEvent(TrackEvent::Create(event_name, track),
+ TaskType::kMediaElementEvent);
}
void TextTrackList::ScheduleAddTrackEvent(TextTrack* track) {
@@ -271,9 +267,8 @@ void TextTrackList::ScheduleChangeEvent() {
// ...
// Fire a simple event named change at the media element's textTracks
// attribute's TextTrackList object.
-
- async_event_queue_->EnqueueEvent(FROM_HERE,
- Event::Create(EventTypeNames::change));
+ EnqueueEvent(Event::Create(EventTypeNames::change),
+ TaskType::kMediaElementEvent);
}
void TextTrackList::ScheduleRemoveTrackEvent(TextTrack* track) {
@@ -303,21 +298,10 @@ HTMLMediaElement* TextTrackList::Owner() const {
void TextTrackList::Trace(blink::Visitor* visitor) {
visitor->Trace(owner_);
- visitor->Trace(async_event_queue_);
visitor->Trace(add_track_tracks_);
visitor->Trace(element_tracks_);
visitor->Trace(inband_tracks_);
EventTargetWithInlineData::Trace(visitor);
}
-void TextTrackList::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- for (auto track : add_track_tracks_)
- visitor->TraceWrappers(track);
- for (auto track : element_tracks_)
- visitor->TraceWrappers(track);
- for (auto track : inband_tracks_)
- visitor->TraceWrappers(track);
- EventTargetWithInlineData::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/html/track/text_track_list.h b/chromium/third_party/blink/renderer/core/html/track/text_track_list.h
index 57ce093c279..45fde7480e2 100644
--- a/chromium/third_party/blink/renderer/core/html/track/text_track_list.h
+++ b/chromium/third_party/blink/renderer/core/html/track/text_track_list.h
@@ -36,7 +36,6 @@
namespace blink {
-class MediaElementEventQueue;
class TextTrack;
class CORE_EXPORT TextTrackList final : public EventTargetWithInlineData {
@@ -75,8 +74,6 @@ class CORE_EXPORT TextTrackList final : public EventTargetWithInlineData {
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
private:
explicit TextTrackList(HTMLMediaElement*);
@@ -89,8 +86,6 @@ class CORE_EXPORT TextTrackList final : public EventTargetWithInlineData {
Member<HTMLMediaElement> owner_;
- Member<MediaElementEventQueue> async_event_queue_;
-
HeapVector<TraceWrapperMember<TextTrack>> add_track_tracks_;
HeapVector<TraceWrapperMember<TextTrack>> element_tracks_;
HeapVector<TraceWrapperMember<TextTrack>> inband_tracks_;
diff --git a/chromium/third_party/blink/renderer/core/html/track/track_list_base.h b/chromium/third_party/blink/renderer/core/html/track/track_list_base.h
index 0a921612a36..0ddbf151553 100644
--- a/chromium/third_party/blink/renderer/core/html/track/track_list_base.h
+++ b/chromium/third_party/blink/renderer/core/html/track/track_list_base.h
@@ -85,13 +85,6 @@ class TrackListBase : public EventTargetWithInlineData {
EventTargetWithInlineData::Trace(visitor);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- for (auto track : tracks_) {
- visitor->TraceWrappers(track);
- }
- EventTargetWithInlineData::TraceWrappers(visitor);
- }
-
private:
void ScheduleEvent(Event* event) {
event->SetTarget(this);
diff --git a/chromium/third_party/blink/renderer/core/html/track/vtt/buffered_line_reader_test.cc b/chromium/third_party/blink/renderer/core/html/track/vtt/buffered_line_reader_test.cc
index bc9d59d1e48..46198a646ee 100644
--- a/chromium/third_party/blink/renderer/core/html/track/vtt/buffered_line_reader_test.cc
+++ b/chromium/third_party/blink/renderer/core/html/track/vtt/buffered_line_reader_test.cc
@@ -154,7 +154,7 @@ enum NewlineType { kCr, kLf, kCrLf };
String LineBreakString(NewlineType type) {
static const char kBreakStrings[] = "\r\n";
return String(type == kLf ? kBreakStrings + 1 : kBreakStrings,
- type == kCrLf ? 2 : 1);
+ type == kCrLf ? 2u : 1u);
}
String MakeTestData(const char** lines, const NewlineType* breaks, int count) {
@@ -248,7 +248,7 @@ TEST(BufferedLineReaderTest, BufferBoundaryInCRLF_2) {
TEST(BufferedLineReaderTest, NormalizedNUL) {
BufferedLineReader reader;
- reader.Append(String("X\0Y\n", 4));
+ reader.Append(String("X\0Y\n", 4u));
String line;
ASSERT_TRUE(reader.GetLine(line));
ASSERT_EQ(line[1], kReplacementCharacter);
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 9c233de383a..53b4e16014c 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
@@ -30,8 +30,6 @@
#include "third_party/blink/renderer/core/html/track/vtt/vtt_cue.h"
#include "third_party/blink/renderer/bindings/core/v8/double_or_auto_keyword.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css_property_names.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/dom/document_fragment.h"
@@ -47,6 +45,8 @@
#include "third_party/blink/renderer/core/html/track/vtt/vtt_region.h"
#include "third_party/blink/renderer/core/html/track/vtt/vtt_scanner.h"
#include "third_party/blink/renderer/core/layout/layout_vtt_cue.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/text/bidi_resolver.h"
#include "third_party/blink/renderer/platform/text/text_run_iterator.h"
@@ -120,7 +120,7 @@ static bool IsInvalidPercentage(double value) {
static bool IsInvalidPercentage(double value, ExceptionState& exception_state) {
if (IsInvalidPercentage(value)) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
ExceptionMessages::IndexOutsideRange<double>(
"value", value, 0, ExceptionMessages::kInclusiveBound, 100,
ExceptionMessages::kInclusiveBound));
diff --git a/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_region.cc b/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_region.cc
index 15ec7ed1399..30af927f186 100644
--- a/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_region.cc
+++ b/chromium/third_party/blink/renderer/core/html/track/vtt/vtt_region.cc
@@ -31,15 +31,15 @@
#include "third_party/blink/renderer/core/html/track/vtt/vtt_region.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/core/dom/dom_token_list.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/geometry/dom_rect.h"
#include "third_party/blink/renderer/core/html/html_div_element.h"
#include "third_party/blink/renderer/core/html/track/vtt/vtt_parser.h"
#include "third_party/blink/renderer/core/html/track/vtt/vtt_scanner.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#define VTT_LOG_LEVEL 3
@@ -68,14 +68,14 @@ constexpr bool kDefaultScroll = false;
constexpr float kLineHeight = 5.33;
// Default scrolling animation time period (s).
-constexpr float kScrollTime = 0.433;
+constexpr TimeDelta kScrollTime = TimeDelta::FromMilliseconds(433);
bool IsNonPercentage(double value,
const char* method,
ExceptionState& exception_state) {
if (value < 0 || value > 100) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
ExceptionMessages::IndexOutsideRange(
"value", value, 0.0, ExceptionMessages::kInclusiveBound, 100.0,
ExceptionMessages::kInclusiveBound));
@@ -397,7 +397,7 @@ void VTTRegion::StartTimer() {
if (scroll_timer_.IsActive())
return;
- double duration = IsScrollingRegion() ? kScrollTime : 0;
+ TimeDelta duration = IsScrollingRegion() ? kScrollTime : TimeDelta();
scroll_timer_.StartOneShot(duration, FROM_HERE);
}
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 66ac364a122..0aa57d0afb6 100644
--- a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
+++ b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
@@ -6,6 +6,7 @@
#include <memory>
#include "base/memory/scoped_refptr.h"
+#include "base/numerics/checked_math.h"
#include "base/single_thread_task_runner.h"
#include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
#include "third_party/blink/renderer/core/html/canvas/image_data.h"
@@ -16,8 +17,7 @@
#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
-#include "third_party/blink/renderer/platform/threading/background_task_runner.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
+#include "third_party/blink/renderer/platform/scheduler/public/background_scheduler.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColorSpaceXformCanvas.h"
#include "third_party/skia/include/core/SkImageInfo.h"
@@ -138,7 +138,7 @@ ImageBitmap::ParsedOptions ParseOptions(const ImageBitmapOptions& options,
// each ImageBitmap() constructor, which makes sure that doing
// width * height * bytesPerPixel will never overflow unsigned.
bool DstBufferSizeHasOverflow(const ImageBitmap::ParsedOptions& options) {
- CheckedNumeric<unsigned> total_bytes = options.crop_rect.Width();
+ base::CheckedNumeric<unsigned> total_bytes = options.crop_rect.Width();
total_bytes *= options.crop_rect.Height();
total_bytes *=
SkColorTypeBytesPerPixel(options.color_params.GetSkColorType());
@@ -159,13 +159,26 @@ bool DstBufferSizeHasOverflow(const ImageBitmap::ParsedOptions& options) {
SkImageInfo GetSkImageInfo(sk_sp<SkImage> skia_image) {
SkColorType color_type = kN32_SkColorType;
+ sk_sp<SkColorSpace> color_space = skia_image->refColorSpace();
+
if (skia_image->colorType() == kRGBA_F16_SkColorType ||
(skia_image->colorSpace() && skia_image->colorSpace()->gammaIsLinear())) {
color_type = kRGBA_F16_SkColorType;
}
+
+ if (color_type == kN32_SkColorType && skia_image->colorSpace() &&
+ skia_image->colorSpace()->isSRGB()) {
+ // Skia is in the middle of transitioning this scenario from meaning
+ // linearly blended sRGB 8888 to non-linearly blended sRGB 8888. While the
+ // transition is happening, we'll strip the color space to force
+ // non-linearly blended sRGB 8888. (This nullptr will continue to mean
+ // non-linearly blended sRGB 8888 after the transition too, so there's
+ // really no harm leaving this indefinitely.)
+ color_space.reset(nullptr);
+ }
return SkImageInfo::Make(skia_image->width(), skia_image->height(),
color_type, skia_image->alphaType(),
- skia_image->refColorSpace());
+ std::move(color_space));
}
SkImageInfo GetSkImageInfo(const scoped_refptr<StaticBitmapImage>& image) {
@@ -434,20 +447,8 @@ scoped_refptr<StaticBitmapImage> ScaleImage(
scoped_refptr<StaticBitmapImage> ApplyColorSpaceConversion(
scoped_refptr<StaticBitmapImage>&& image,
ImageBitmap::ParsedOptions& options) {
- SkTransferFunctionBehavior transfer_function_behavior =
- SkTransferFunctionBehavior::kRespect;
- // We normally expect to respect transfer function. However, in two scenarios
- // we have to ignore the transfer function. First, when the source image is
- // unpremul. Second, when the source image is drawn using a
- // SkColorSpaceXformCanvas.
- sk_sp<SkImage> skia_image = image->PaintImageForCurrentFrame().GetSkImage();
- if (!skia_image->colorSpace() ||
- skia_image->alphaType() == kUnpremul_SkAlphaType)
- transfer_function_behavior = SkTransferFunctionBehavior::kIgnore;
-
return image->ConvertToColorSpace(
- options.color_params.GetSkColorSpaceForSkSurfaces(),
- transfer_function_behavior);
+ options.color_params.GetSkColorSpaceForSkSurfaces());
}
scoped_refptr<StaticBitmapImage> MakeBlankImage(
@@ -496,10 +497,12 @@ static scoped_refptr<StaticBitmapImage> CropImageAndApplyColorSpaceConversion(
// skia_image is premultiplied.
if (!skia_image->isOpaque() && image->Data() &&
skia_image->alphaType() == kPremul_SkAlphaType) {
+ const bool data_complete = true;
std::unique_ptr<ImageDecoder> decoder(ImageDecoder::Create(
- image->Data(), true,
+ image->Data(), data_complete,
parsed_options.premultiply_alpha ? ImageDecoder::kAlphaPremultiplied
: ImageDecoder::kAlphaNotPremultiplied,
+ ImageDecoder::kDefaultBitDepth,
parsed_options.has_color_space_conversion ? ColorBehavior::Tag()
: ColorBehavior::Ignore()));
if (!decoder)
@@ -605,7 +608,12 @@ ImageBitmap::ImageBitmap(HTMLVideoElement* video,
std::unique_ptr<CanvasResourceProvider> resource_provider =
CanvasResourceProvider::Create(
IntSize(video->videoWidth(), video->videoHeight()),
- CanvasResourceProvider::kSoftwareResourceUsage);
+ CanvasResourceProvider::kSoftwareResourceUsage,
+ nullptr, // context_provider_wrapper
+ 0, // msaa_sample_count
+ CanvasColorParams(), // TODO: set color space here to avoid clamping
+ CanvasResourceProvider::kDefaultPresentationMode,
+ nullptr); // canvas_resource_dispatcher
if (!resource_provider)
return;
@@ -925,13 +933,8 @@ void ImageBitmap::RasterizeImageOnBackgroundThread(
bool origin_clean,
std::unique_ptr<ParsedOptions> parsed_options) {
DCHECK(!IsMainThread());
- // TODO (zakerinasab): crbug.com/768844
- // For now only SVG is decoded async so it is fine to assume the color space
- // is SRGB. When other sources are decoded async (crbug.com/580202), make sure
- // that proper color space is used in SkImageInfo to avoid clipping the gamut
- // of the image bitmap source.
- SkImageInfo info = SkImageInfo::MakeS32(dst_rect.Width(), dst_rect.Height(),
- kPremul_SkAlphaType);
+ SkImageInfo info =
+ SkImageInfo::MakeN32Premul(dst_rect.Width(), dst_rect.Height());
sk_sp<SkSurface> surface = SkSurface::MakeRaster(info);
sk_sp<SkImage> skia_image;
if (surface) {
@@ -993,7 +996,7 @@ ScriptPromise ImageBitmap::CreateAsync(ImageElementBase* image,
draw_dst_rect, parsed_options.flip_y);
std::unique_ptr<ParsedOptions> passed_parsed_options =
std::make_unique<ParsedOptions>(parsed_options);
- BackgroundTaskRunner::PostOnBackgroundThread(
+ BackgroundScheduler::PostOnBackgroundThread(
FROM_HERE,
CrossThreadBind(&RasterizeImageOnBackgroundThread,
WrapCrossThreadPersistent(resolver),
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 44652b92588..b98ee617e30 100644
--- a/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.h
+++ b/chromium/third_party/blink/renderer/core/imagebitmap/image_bitmap.h
@@ -27,11 +27,6 @@ class ImageData;
class ImageDecoder;
class OffscreenCanvas;
-enum ColorSpaceInfoUpdate {
- kUpdateColorSpaceInformation,
- kDontUpdateColorSpaceInformation,
-};
-
class CORE_EXPORT ImageBitmap final : public ScriptWrappable,
public CanvasImageSource,
public ImageBitmapSource {
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 1539fc8b1f7..076b9beeaa6 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
@@ -35,7 +35,6 @@
#include "base/location.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_thread.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/fileapi/blob.h"
@@ -51,11 +50,12 @@
#include "third_party/blink/renderer/core/svg/graphics/svg_image.h"
#include "third_party/blink/renderer/core/svg/svg_image_element.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
+#include "third_party/blink/renderer/platform/scheduler/public/background_scheduler.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
-#include "third_party/blink/renderer/platform/threading/background_task_runner.h"
#include "v8/include/v8.h"
namespace blink {
@@ -196,7 +196,7 @@ ScriptPromise ImageBitmapFactories::createImageBitmap(
return ScriptPromise::RejectWithDOMException(
script_state,
DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
String::Format("The source image %s is 0.",
bitmap_source->BitmapSourceSize().Width()
? "height"
@@ -261,22 +261,18 @@ void ImageBitmapFactories::Trace(blink::Visitor* visitor) {
Supplement<WorkerGlobalScope>::Trace(visitor);
}
-void ImageBitmapFactories::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- Supplement<LocalDOMWindow>::TraceWrappers(visitor);
- Supplement<WorkerGlobalScope>::TraceWrappers(visitor);
-}
-
void ImageBitmapFactories::ImageBitmapLoader::RejectPromise(
ImageBitmapRejectionReason reason) {
switch (reason) {
case kUndecodableImageBitmapRejectionReason:
- resolver_->Reject(DOMException::Create(
- kInvalidStateError, "The source image could not be decoded."));
+ resolver_->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "The source image could not be decoded."));
break;
case kAllocationFailureImageBitmapRejectionReason:
- resolver_->Reject(DOMException::Create(
- kInvalidStateError, "The ImageBitmap could not be allocated."));
+ resolver_->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "The ImageBitmap could not be allocated."));
break;
default:
NOTREACHED();
@@ -301,7 +297,7 @@ void ImageBitmapFactories::ImageBitmapLoader::ScheduleAsyncImageBitmapDecoding(
DOMArrayBuffer* array_buffer) {
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
Platform::Current()->CurrentThread()->GetTaskRunner();
- BackgroundTaskRunner::PostOnBackgroundThread(
+ BackgroundScheduler::PostOnBackgroundThread(
FROM_HERE,
CrossThreadBind(
&ImageBitmapFactories::ImageBitmapLoader::DecodeImageOnDecoderThread,
@@ -323,10 +319,11 @@ void ImageBitmapFactories::ImageBitmapLoader::DecodeImageOnDecoderThread(
bool ignore_color_space = false;
if (color_space_conversion_option == "none")
ignore_color_space = true;
+ const bool data_complete = true;
std::unique_ptr<ImageDecoder> decoder(ImageDecoder::Create(
SegmentReader::CreateFromSkData(SkData::MakeWithoutCopy(
array_buffer->Data(), array_buffer->ByteLength())),
- true, alpha_op,
+ data_complete, alpha_op, ImageDecoder::kDefaultBitDepth,
ignore_color_space ? ColorBehavior::Ignore() : ColorBehavior::Tag()));
sk_sp<SkImage> frame;
if (decoder) {
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 0ad28c2e4c7..25bdf1ffd1e 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,6 +41,7 @@
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap_options.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"
#include "third_party/blink/renderer/platform/supplementable.h"
@@ -62,7 +63,7 @@ class ImageBitmapFactories final
: public GarbageCollectedFinalized<ImageBitmapFactories>,
public Supplement<LocalDOMWindow>,
public Supplement<WorkerGlobalScope>,
- public TraceWrapperBase {
+ public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(ImageBitmapFactories);
public:
@@ -95,7 +96,6 @@ class ImageBitmapFactories final
virtual ~ImageBitmapFactories() = default;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "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 fdf8c5352f9..6a743d0b354 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
@@ -17,8 +17,9 @@ ScriptPromise ImageBitmapSource::FulfillImageBitmap(ScriptState* script_state,
if (image_bitmap && image_bitmap->BitmapImage()) {
resolver->Resolve(image_bitmap);
} else {
- resolver->Reject(DOMException::Create(
- kInvalidStateError, "The ImageBitmap could not be allocated."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "The ImageBitmap could not be allocated."));
}
return promise;
}
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 3510c16c841..129d7b17f82 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
@@ -9,7 +9,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
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 0c3a9a678e5..7ca30281a5c 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
@@ -92,7 +92,7 @@ class ImageBitmapTest : public testing::Test {
// them from the cache.
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
ReplaceMemoryCacheForTesting(global_memory_cache_.Release());
SharedGpuContext::ResetForTesting();
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 20fd9481dce..5387f4ab222 100644
--- a/chromium/third_party/blink/renderer/core/input/event_handler.cc
+++ b/chromium/third_party/blink/renderer/core/input/event_handler.cc
@@ -35,7 +35,6 @@
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/clipboard/data_transfer.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
@@ -87,8 +86,10 @@
#include "third_party/blink/renderer/core/page/scrolling/scroll_state.h"
#include "third_party/blink/renderer/core/page/touch_adjustment.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/style/computed_style.h"
#include "third_party/blink/renderer/core/style/cursor_data.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -126,7 +127,8 @@ using namespace HTMLNames;
// The amount of time to wait for a cursor update on style and layout changes
// Set to 50Hz, no need to be faster than common screen refresh rate
-static const double kCursorUpdateInterval = 0.02;
+static constexpr TimeDelta kCursorUpdateInterval =
+ TimeDelta::FromMilliseconds(20);
static const int kMaximumCursorSize = 128;
@@ -227,42 +229,14 @@ void EventHandler::StartMiddleClickAutoscroll(LayoutObject* layout_object) {
controller->StartMiddleClickAutoscroll(
layout_object->GetFrame(),
frame_->GetPage()->GetVisualViewport().ViewportToRootFrame(
- mouse_event_manager_->LastKnownMousePosition()),
+ FloatPoint(mouse_event_manager_->LastKnownMousePosition())),
mouse_event_manager_->LastKnownMousePositionGlobal());
mouse_event_manager_->InvalidateClick();
}
-HitTestResult EventHandler::HitTestResultAtPoint(
- const LayoutPoint& point,
- HitTestRequest::HitTestRequestType hit_type,
- const LayoutRectOutsets& padding,
- const LayoutObject* stop_node) {
- TRACE_EVENT0("blink", "EventHandler::hitTestResultAtPoint");
-
- DCHECK((hit_type & HitTestRequest::kListBased) || padding.IsZero());
-
- // We always send hitTestResultAtPoint to the main frame if we have one,
- // otherwise we might hit areas that are obscured by higher frames.
- if (frame_->GetPage()) {
- LocalFrame& main_frame = frame_->LocalFrameRoot();
- if (frame_ != &main_frame) {
- LocalFrameView* frame_view = frame_->View();
- LocalFrameView* main_view = main_frame.View();
- if (frame_view && main_view) {
- LayoutPoint main_content_point = main_view->RootFrameToContents(
- frame_view->ContentsToRootFrame(point));
- return main_frame.GetEventHandler().HitTestResultAtPoint(
- main_content_point, hit_type, padding);
- }
- }
- }
-
- // hitTestResultAtPoint is specifically used to hitTest into all frames, thus
- // it always allows child frame content.
- HitTestRequest request(hit_type | HitTestRequest::kAllowChildFrameContent,
- stop_node);
- HitTestResult result(request, point, padding);
-
+void EventHandler::PerformHitTest(const HitTestLocation& location,
+ HitTestResult& result,
+ bool no_lifecycle_update) const {
// LayoutView::hitTest causes a layout, and we don't want to hit that until
// the first layout because until then, there is nothing shown on the screen -
// the user can't have intentionally clicked on something belonging to this
@@ -276,13 +250,59 @@ HitTestResult EventHandler::HitTestResultAtPoint(
if (!frame_->ContentLayoutObject() || !frame_->View() ||
!frame_->View()->DidFirstLayout() ||
!frame_->View()->LifecycleUpdatesActive())
- return result;
+ return;
- frame_->ContentLayoutObject()->HitTest(result);
- if (!request.ReadOnly())
+ if (no_lifecycle_update) {
+ frame_->ContentLayoutObject()->HitTestNoLifecycleUpdate(location, result);
+ } else {
+ frame_->ContentLayoutObject()->HitTest(location, result);
+ }
+ const HitTestRequest& request = result.GetHitTestRequest();
+ if (!request.ReadOnly()) {
frame_->GetDocument()->UpdateHoverActiveState(request,
result.InnerElement());
+ }
+}
+
+HitTestResult EventHandler::HitTestResultAtLocation(
+ const HitTestLocation& location,
+ HitTestRequest::HitTestRequestType hit_type,
+ const LayoutObject* stop_node,
+ bool no_lifecycle_update) {
+ TRACE_EVENT0("blink", "EventHandler::HitTestResultAtLocation");
+ // We always send HitTestResultAtLocation to the main frame if we have one,
+ // otherwise we might hit areas that are obscured by higher frames.
+ if (frame_->GetPage()) {
+ LocalFrame& main_frame = frame_->LocalFrameRoot();
+ if (frame_ != &main_frame) {
+ LocalFrameView* frame_view = frame_->View();
+ LocalFrameView* main_view = main_frame.View();
+ if (frame_view && main_view) {
+ if (location.IsRectBasedTest()) {
+ DCHECK(location.IsRectilinear());
+ LayoutPoint main_content_point =
+ main_view->ConvertFromRootFrame(frame_view->ConvertToRootFrame(
+ location.BoundingBox().Location()));
+ HitTestLocation adjusted_location(
+ (LayoutRect(main_content_point, location.BoundingBox().Size())));
+ return main_frame.GetEventHandler().HitTestResultAtLocation(
+ adjusted_location, hit_type, stop_node);
+ } else {
+ HitTestLocation adjusted_location(main_view->ConvertFromRootFrame(
+ frame_view->ConvertToRootFrame(location.Point())));
+ return main_frame.GetEventHandler().HitTestResultAtLocation(
+ adjusted_location, hit_type, stop_node);
+ }
+ }
+ }
+ }
+ // HitTestResultAtLocation is specifically used to hitTest into all frames,
+ // thus it always allows child frame content.
+ HitTestRequest request(hit_type | HitTestRequest::kAllowChildFrameContent,
+ stop_node);
+ HitTestResult result(request, location);
+ PerformHitTest(location, result, no_lifecycle_update);
return result;
}
@@ -352,14 +372,14 @@ void EventHandler::UpdateCursor() {
HitTestRequest request(HitTestRequest::kReadOnly |
HitTestRequest::kAllowChildFrameContent);
- HitTestResult result(
- request,
- view->ViewportToContents(mouse_event_manager_->LastKnownMousePosition()));
- layout_view->HitTest(result);
+ HitTestLocation location(
+ view->ViewportToFrame(mouse_event_manager_->LastKnownMousePosition()));
+ HitTestResult result(request, location);
+ layout_view->HitTest(location, result);
if (LocalFrame* frame = result.InnerNodeFrame()) {
EventHandler::OptionalCursor optional_cursor =
- frame->GetEventHandler().SelectCursor(result);
+ frame->GetEventHandler().SelectCursor(location, result);
if (optional_cursor.IsCursorChange()) {
view->SetCursor(optional_cursor.GetCursor());
}
@@ -367,12 +387,12 @@ void EventHandler::UpdateCursor() {
}
bool EventHandler::ShouldShowResizeForNode(const Node* node,
- const HitTestResult& result) {
+ const HitTestLocation& location) {
if (LayoutObject* layout_object = node->GetLayoutObject()) {
PaintLayer* layer = layout_object->EnclosingLayer();
if (layer->GetScrollableArea() &&
layer->GetScrollableArea()->IsPointInResizeControl(
- result.RoundedPointInMainFrame(), kResizerForPointer)) {
+ RoundedIntPoint(location.Point()), kResizerForPointer)) {
return true;
}
}
@@ -406,6 +426,7 @@ bool EventHandler::ShouldShowIBeamForNode(const Node* node,
}
EventHandler::OptionalCursor EventHandler::SelectCursor(
+ const HitTestLocation& location,
const HitTestResult& result) {
if (scroll_manager_->InResizeMode())
return kNoCursorChange;
@@ -423,7 +444,7 @@ EventHandler::OptionalCursor EventHandler::SelectCursor(
if (!node)
return SelectAutoCursor(result, node, IBeamCursor());
- if (ShouldShowResizeForNode(node, result))
+ if (ShouldShowResizeForNode(node, location))
return PointerCursor();
LayoutObject* layout_object = node->GetLayoutObject();
@@ -595,7 +616,7 @@ WebInputEventResult EventHandler::HandleMousePressEvent(
HitTestRequest request(HitTestRequest::kActive);
// Save the document point we generate in case the window coordinate is
// invalidated by what happens when we dispatch the event.
- LayoutPoint document_point = frame_->View()->RootFrameToContents(
+ LayoutPoint document_point = frame_->View()->ConvertFromRootFrame(
FlooredIntPoint(mouse_event.PositionInRootFrame()));
MouseEventWithHitTestResults mev =
frame_->GetDocument()->PerformMouseEventHitTest(request, document_point,
@@ -671,7 +692,7 @@ WebInputEventResult EventHandler::HandleMousePressEvent(
mev.InnerNode()->GetLayoutObject()
? mev.InnerNode()->GetLayoutObject()->EnclosingLayer()
: nullptr;
- IntPoint p = view->RootFrameToContents(
+ IntPoint p = view->ConvertFromRootFrame(
FlooredIntPoint(mouse_event.PositionInRootFrame()));
if (layer && layer->GetScrollableArea() &&
layer->GetScrollableArea()->IsPointInResizeControl(
@@ -688,7 +709,7 @@ WebInputEventResult EventHandler::HandleMousePressEvent(
// the same behavior and it's more compatible with other browsers.
GetSelectionController().InitializeSelectionState();
HitTestResult hit_test_result = EventHandlingUtil::HitTestResultInFrame(
- frame_, document_point, HitTestRequest::kReadOnly);
+ frame_, HitTestLocation(document_point), HitTestRequest::kReadOnly);
InputDeviceCapabilities* source_capabilities =
frame_->GetDocument()
->domWindow()
@@ -749,26 +770,25 @@ WebInputEventResult EventHandler::HandleMouseMoveEvent(
const WebMouseEvent& event,
const Vector<WebMouseEvent>& coalesced_events) {
TRACE_EVENT0("blink", "EventHandler::handleMouseMoveEvent");
- HitTestResult hovered_node = HitTestResult();
- WebInputEventResult result =
- HandleMouseMoveOrLeaveEvent(event, coalesced_events, &hovered_node);
+ HitTestResult hovered_node_result;
+ HitTestLocation location;
+ WebInputEventResult result = HandleMouseMoveOrLeaveEvent(
+ event, coalesced_events, &hovered_node_result, &location);
Page* page = frame_->GetPage();
if (!page)
return result;
if (PaintLayer* layer =
- EventHandlingUtil::LayerForNode(hovered_node.InnerNode())) {
+ EventHandlingUtil::LayerForNode(hovered_node_result.InnerNode())) {
if (ScrollableArea* layer_scrollable_area =
EventHandlingUtil::AssociatedScrollableArea(layer))
layer_scrollable_area->MouseMovedInContentArea();
}
- if (LocalFrameView* frame_view = frame_->View())
- frame_view->MouseMovedInContentArea();
-
- hovered_node.SetToShadowHostIfInRestrictedShadowRoot();
- page->GetChromeClient().MouseDidMoveOverElement(*frame_, hovered_node);
+ hovered_node_result.SetToShadowHostIfInRestrictedShadowRoot();
+ page->GetChromeClient().MouseDidMoveOverElement(*frame_, location,
+ hovered_node_result);
return result;
}
@@ -779,14 +799,15 @@ void EventHandler::HandleMouseLeaveEvent(const WebMouseEvent& event) {
Page* page = frame_->GetPage();
if (page)
page->GetChromeClient().ClearToolTip(*frame_);
- HandleMouseMoveOrLeaveEvent(event, Vector<WebMouseEvent>(), nullptr, false,
- true);
+ HandleMouseMoveOrLeaveEvent(event, Vector<WebMouseEvent>(), nullptr, nullptr,
+ false, true);
}
WebInputEventResult EventHandler::HandleMouseMoveOrLeaveEvent(
const WebMouseEvent& mouse_event,
const Vector<WebMouseEvent>& coalesced_events,
- HitTestResult* hovered_node,
+ HitTestResult* hovered_node_result,
+ HitTestLocation* hit_test_location,
bool only_update_scrollbars,
bool force_leave) {
DCHECK(frame_);
@@ -854,8 +875,9 @@ WebInputEventResult EventHandler::HandleMouseMoveOrLeaveEvent(
if (pointer_event_manager_->IsAnyTouchActive() && !force_leave)
hit_type |= HitTestRequest::kActive | HitTestRequest::kReadOnly;
HitTestRequest request(hit_type);
+ HitTestLocation out_location((LayoutPoint()));
MouseEventWithHitTestResults mev = MouseEventWithHitTestResults(
- mouse_event, HitTestResult(request, LayoutPoint()));
+ mouse_event, out_location, HitTestResult(request, out_location));
// We don't want to do a hit-test in forceLeave scenarios because there
// might actually be some other frame above this one at the specified
@@ -868,8 +890,11 @@ WebInputEventResult EventHandler::HandleMouseMoveOrLeaveEvent(
mouse_event);
}
- if (hovered_node)
- *hovered_node = mev.GetHitTestResult();
+ if (hovered_node_result)
+ *hovered_node_result = mev.GetHitTestResult();
+
+ if (hit_test_location)
+ *hit_test_location = mev.GetHitTestLocation();
Scrollbar* scrollbar = nullptr;
@@ -913,8 +938,8 @@ WebInputEventResult EventHandler::HandleMouseMoveOrLeaveEvent(
// subframe of the target node to be detached from its LocalFrameView, in
// which case the event should not be passed.
if (new_subframe->View()) {
- event_result = PassMouseMoveEventToSubframe(mev, coalesced_events,
- new_subframe, hovered_node);
+ event_result = PassMouseMoveEventToSubframe(
+ mev, coalesced_events, new_subframe, hovered_node_result);
}
} else {
if (scrollbar && !mouse_event_manager_->MousePressed()) {
@@ -924,7 +949,7 @@ WebInputEventResult EventHandler::HandleMouseMoveOrLeaveEvent(
}
if (LocalFrameView* view = frame_->View()) {
EventHandler::OptionalCursor optional_cursor =
- SelectCursor(mev.GetHitTestResult());
+ SelectCursor(mev.GetHitTestLocation(), mev.GetHitTestResult());
if (optional_cursor.IsCursorChange()) {
view->SetCursor(optional_cursor.GetCursor());
}
@@ -939,7 +964,11 @@ WebInputEventResult EventHandler::HandleMouseMoveOrLeaveEvent(
event_result = DispatchMousePointerEvent(
WebInputEvent::kPointerMove, mev.InnerNode(), mev.CanvasRegionId(),
mev.Event(), coalesced_events);
- if (event_result != WebInputEventResult::kNotHandled)
+ // https://w3c.github.io/uievents/#event-type-mousemove
+ // Since there is no default action for the mousemove event issue a
+ // mouse dragged event irrespective of whether the event is cancelled.
+ if (event_result != WebInputEventResult::kNotHandled &&
+ event_result != WebInputEventResult::kHandledApplication)
return event_result;
return mouse_event_manager_->HandleMouseDraggedEvent(mev);
@@ -1185,6 +1214,10 @@ void EventHandler::ClearDragState() {
should_only_fire_drag_over_event_ = false;
}
+void EventHandler::AnimateSnapFling(base::TimeTicks monotonic_time) {
+ scroll_manager_->AnimateSnapFling(monotonic_time);
+}
+
void EventHandler::SetCapturingMouseEventsNode(Node* n) {
capturing_mouse_events_node_ = n;
event_handler_will_reset_capturing_mouse_events_node_ = false;
@@ -1421,13 +1454,14 @@ bool EventHandler::GestureCorrespondsToAdjustedTouch(
}
bool EventHandler::BestClickableNodeForHitTestResult(
+ const HitTestLocation& location,
const HitTestResult& result,
IntPoint& target_point,
Node*& target_node) {
// FIXME: Unify this with the other best* functions which are very similar.
TRACE_EVENT0("input", "EventHandler::bestClickableNodeForHitTestResult");
- DCHECK(result.IsRectBasedTest());
+ DCHECK(location.IsRectBasedTest());
// If the touch is over a scrollbar, don't adjust the touch point since touch
// adjustment only takes into account DOM nodes so a touch over a scrollbar
@@ -1439,9 +1473,9 @@ bool EventHandler::BestClickableNodeForHitTestResult(
}
IntPoint touch_center =
- frame_->View()->ContentsToRootFrame(result.RoundedPointInMainFrame());
- IntRect touch_rect = frame_->View()->ContentsToRootFrame(
- result.GetHitTestLocation().EnclosingIntRect());
+ frame_->View()->ConvertToRootFrame(RoundedIntPoint(location.Point()));
+ IntRect touch_rect =
+ frame_->View()->ConvertToRootFrame(location.EnclosingIntRect());
HeapVector<Member<Node>, 11> nodes;
CopyToVector(result.ListBasedTestResult(), nodes);
@@ -1454,14 +1488,15 @@ bool EventHandler::BestClickableNodeForHitTestResult(
}
bool EventHandler::BestContextMenuNodeForHitTestResult(
+ const HitTestLocation& location,
const HitTestResult& result,
IntPoint& target_point,
Node*& target_node) {
- DCHECK(result.IsRectBasedTest());
+ DCHECK(location.IsRectBasedTest());
IntPoint touch_center =
- frame_->View()->ContentsToRootFrame(result.RoundedPointInMainFrame());
- IntRect touch_rect = frame_->View()->ContentsToRootFrame(
- result.GetHitTestLocation().EnclosingIntRect());
+ frame_->View()->ConvertToRootFrame(RoundedIntPoint(location.Point()));
+ IntRect touch_rect =
+ frame_->View()->ConvertToRootFrame(location.EnclosingIntRect());
HeapVector<Member<Node>, 11> nodes;
CopyToVector(result.ListBasedTestResult(), nodes);
@@ -1673,7 +1708,7 @@ GestureEventWithHitTestResults EventHandler::TargetGestureEvent(
event_with_hit_test_results.GetHitTestResult().InnerElement();
// TODO(https://crbug.com/668758): Use a normal BeginFrame update for this.
active_interval_timer_.StartOneShot(
- (kMinimumActiveInterval - active_interval).InSecondsF(), FROM_HERE);
+ kMinimumActiveInterval - active_interval, FROM_HERE);
}
return event_with_hit_test_results;
@@ -1686,9 +1721,9 @@ GestureEventWithHitTestResults EventHandler::HitTestResultForGestureEvent(
// disabled). Note that we don't yet apply hover/active state here because
// we need to resolve touch adjustment first so that we apply hover/active
// it to the final adjusted node.
+ hit_type |= HitTestRequest::kReadOnly;
WebGestureEvent adjusted_event = gesture_event;
- LayoutSize padding;
-
+ LayoutSize hit_rect_size;
if (ShouldApplyTouchAdjustment(gesture_event)) {
// If gesture_event unique id matches the stored touch event result, do
// point-base hit test. Otherwise add padding and do rect-based hit test.
@@ -1696,24 +1731,32 @@ GestureEventWithHitTestResults EventHandler::HitTestResultForGestureEvent(
adjusted_event.ApplyTouchAdjustment(
touch_adjustment_result_.adjusted_point);
} else {
- padding = GetHitTestRectForAdjustment(
- LayoutSize(adjusted_event.TapAreaInRootFrame()) * 0.5f);
- if (!padding.IsEmpty())
+ hit_rect_size = GetHitTestRectForAdjustment(
+ LayoutSize(adjusted_event.TapAreaInRootFrame()));
+ if (!hit_rect_size.IsEmpty())
hit_type |= HitTestRequest::kListBased;
}
}
- LayoutPoint hit_test_point(frame_->View()->RootFrameToContents(
- adjusted_event.PositionInRootFrame()));
- HitTestResult hit_test_result = HitTestResultAtPoint(
- hit_test_point, hit_type | HitTestRequest::kReadOnly,
- LayoutRectOutsets(padding.Height(), padding.Width(), padding.Height(),
- padding.Width()));
-
- if (hit_test_result.IsRectBasedTest()) {
+
+ HitTestLocation location;
+ LocalFrame& root_frame = frame_->LocalFrameRoot();
+ HitTestResult hit_test_result;
+ if (hit_rect_size.IsEmpty()) {
+ location = HitTestLocation(adjusted_event.PositionInRootFrame());
+ hit_test_result = root_frame.GetEventHandler().HitTestResultAtLocation(
+ location, hit_type);
+ } else {
+ LayoutPoint top_left(adjusted_event.PositionInRootFrame());
+ top_left.Move(-hit_rect_size * 0.5f);
+ location = HitTestLocation(LayoutRect(top_left, hit_rect_size));
+ hit_test_result = root_frame.GetEventHandler().HitTestResultAtLocation(
+ location, hit_type);
+ }
+
+ if (location.IsRectBasedTest()) {
// Adjust the location of the gesture to the most likely nearby node, as
// appropriate for the type of event.
- ApplyTouchAdjustment(&adjusted_event, &hit_test_result);
-
+ ApplyTouchAdjustment(&adjusted_event, location, &hit_test_result);
// Do a new hit-test at the (adjusted) gesture co-ordinates. This is
// necessary because rect-based hit testing and touch adjustment sometimes
// return a different node than what a point-based hit test would return for
@@ -1723,16 +1766,16 @@ GestureEventWithHitTestResults EventHandler::HitTestResultForGestureEvent(
LocalFrame* hit_frame = hit_test_result.InnerNodeFrame();
if (!hit_frame)
hit_frame = frame_;
+ location = HitTestLocation(hit_frame->View()->ConvertFromRootFrame(
+ LayoutPoint(adjusted_event.PositionInRootFrame())));
hit_test_result = EventHandlingUtil::HitTestResultInFrame(
- hit_frame,
- hit_frame->View()->RootFrameToContents(
- LayoutPoint(adjusted_event.PositionInRootFrame())),
+ hit_frame, location,
(hit_type | HitTestRequest::kReadOnly) & ~HitTestRequest::kListBased);
}
// If we did a rect-based hit test it must be resolved to the best single node
// by now to ensure consumers don't accidentally use one of the other
// candidates.
- DCHECK(!hit_test_result.IsRectBasedTest());
+ DCHECK(!location.IsRectBasedTest());
if (ShouldApplyTouchAdjustment(gesture_event) &&
(gesture_event.GetType() == WebInputEvent::kGestureTap ||
@@ -1743,10 +1786,12 @@ GestureEventWithHitTestResults EventHandler::HitTestResultForGestureEvent(
UMA_HISTOGRAM_COUNTS_100("Event.Touch.TouchAdjustment.AdjustDistance",
static_cast<int>(adjusted_distance));
}
- return GestureEventWithHitTestResults(adjusted_event, hit_test_result);
+ return GestureEventWithHitTestResults(adjusted_event, location,
+ hit_test_result);
}
void EventHandler::ApplyTouchAdjustment(WebGestureEvent* gesture_event,
+ HitTestLocation& location,
HitTestResult* hit_test_result) {
Node* adjusted_node = nullptr;
IntPoint adjusted_point =
@@ -1758,13 +1803,13 @@ void EventHandler::ApplyTouchAdjustment(WebGestureEvent* gesture_event,
case WebInputEvent::kGestureTapDown:
case WebInputEvent::kGestureShowPress:
adjusted = BestClickableNodeForHitTestResult(
- *hit_test_result, adjusted_point, adjusted_node);
+ location, *hit_test_result, adjusted_point, adjusted_node);
break;
case WebInputEvent::kGestureLongPress:
case WebInputEvent::kGestureLongTap:
case WebInputEvent::kGestureTwoFingerTap:
adjusted = BestContextMenuNodeForHitTestResult(
- *hit_test_result, adjusted_point, adjusted_node);
+ location, *hit_test_result, adjusted_point, adjusted_node);
break;
default:
NOTREACHED();
@@ -1775,8 +1820,10 @@ void EventHandler::ApplyTouchAdjustment(WebGestureEvent* gesture_event,
// FIXME: We should do this even when no candidate matches the node filter.
// crbug.com/398914
if (adjusted) {
- hit_test_result->ResolveRectBasedTest(
- adjusted_node, frame_->View()->RootFrameToContents(adjusted_point));
+ LayoutPoint point = frame_->View()->ConvertFromRootFrame(adjusted_point);
+ DCHECK(location.ContainsPoint(FloatPoint(point)));
+ DCHECK(location.IsRectBasedTest());
+ location = hit_test_result->ResolveRectBasedTest(adjusted_node, point);
gesture_event->ApplyTouchAdjustment(
WebFloatPoint(adjusted_point.X(), adjusted_point.Y()));
}
@@ -1793,7 +1840,7 @@ WebInputEventResult EventHandler::SendContextMenuEvent(
// up.
mouse_event_manager_->ReleaseMousePress();
LayoutPoint position_in_contents =
- v->RootFrameToContents(FlooredIntPoint(event.PositionInRootFrame()));
+ v->ConvertFromRootFrame(FlooredIntPoint(event.PositionInRootFrame()));
HitTestRequest request(HitTestRequest::kActive);
MouseEventWithHitTestResults mev =
frame_->GetDocument()->PerformMouseEventHitTest(
@@ -1860,7 +1907,7 @@ WebInputEventResult EventHandler::ShowNonLocatedContextMenu(
// In a multiline edit, firstRect.maxY() would end up on the next line, so
// take the midpoint.
int y = (first_rect.MaxY() + first_rect.Y()) / 2;
- location_in_root_frame = view->ContentsToRootFrame(IntPoint(x, y));
+ location_in_root_frame = view->ConvertToRootFrame(IntPoint(x, y));
} else if (focused_element) {
IntRect clipped_rect = focused_element->BoundsInViewport();
location_in_root_frame =
@@ -1868,7 +1915,8 @@ WebInputEventResult EventHandler::ShowNonLocatedContextMenu(
} else {
location_in_root_frame = IntPoint(
right_aligned
- ? visual_viewport.VisibleRect().MaxX() - kContextMenuMargin
+ ? visual_viewport.VisibleRect(kIncludeScrollbars).MaxX() -
+ kContextMenuMargin
: visual_viewport.GetScrollOffset().Width() + kContextMenuMargin,
visual_viewport.GetScrollOffset().Height() + kContextMenuMargin);
}
@@ -1877,7 +1925,7 @@ WebInputEventResult EventHandler::ShowNonLocatedContextMenu(
IntPoint location_in_viewport =
visual_viewport.RootFrameToViewport(location_in_root_frame);
IntPoint global_position =
- view->GetChromeClient()
+ ToChromeClient(view->GetChromeClient())
->ViewportToScreen(IntRect(location_in_viewport, IntSize()),
frame_->View())
.Location();
@@ -1889,7 +1937,8 @@ WebInputEventResult EventHandler::ShowNonLocatedContextMenu(
// Use the focused node as the target for hover and active.
HitTestRequest request(HitTestRequest::kActive);
- HitTestResult result(request, location_in_root_frame);
+ HitTestLocation location(location_in_root_frame);
+ HitTestResult result(request, location);
result.SetInnerNode(target_node);
doc->UpdateHoverActiveState(request, result.InnerElement());
@@ -1965,10 +2014,10 @@ void EventHandler::HoverTimerFired(TimerBase*) {
if (auto* layout_object = frame_->ContentLayoutObject()) {
if (LocalFrameView* view = frame_->View()) {
HitTestRequest request(HitTestRequest::kMove);
- HitTestResult result(request,
- view->ViewportToContents(
- mouse_event_manager_->LastKnownMousePosition()));
- layout_object->HitTest(result);
+ HitTestLocation location(view->ViewportToFrame(
+ mouse_event_manager_->LastKnownMousePosition()));
+ HitTestResult result(request, location);
+ layout_object->HitTest(location, result);
frame_->GetDocument()->UpdateHoverActiveState(request,
result.InnerElement());
}
@@ -2128,12 +2177,13 @@ WebInputEventResult EventHandler::PassMouseMoveEventToSubframe(
MouseEventWithHitTestResults& mev,
const Vector<WebMouseEvent>& coalesced_events,
LocalFrame* subframe,
- HitTestResult* hovered_node) {
+ HitTestResult* hovered_node,
+ HitTestLocation* hit_test_location) {
if (mouse_event_manager_->MouseDownMayStartDrag())
return WebInputEventResult::kNotHandled;
WebInputEventResult result =
subframe->GetEventHandler().HandleMouseMoveOrLeaveEvent(
- mev.Event(), coalesced_events, hovered_node);
+ mev.Event(), coalesced_events, hovered_node, hit_test_location);
if (result != WebInputEventResult::kNotHandled)
return result;
return WebInputEventResult::kHandledSystem;
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 bb36741ff49..48f11d93f1f 100644
--- a/chromium/third_party/blink/renderer/core/input/event_handler.h
+++ b/chromium/third_party/blink/renderer/core/input/event_handler.h
@@ -99,12 +99,12 @@ class CORE_EXPORT EventHandler final
void DispatchFakeMouseMoveEventSoon(MouseEventManager::FakeMouseMoveReason);
void DispatchFakeMouseMoveEventSoonInQuad(const FloatQuad&);
- HitTestResult HitTestResultAtPoint(
- const LayoutPoint&,
+ HitTestResult HitTestResultAtLocation(
+ const HitTestLocation&,
HitTestRequest::HitTestRequestType hit_type = HitTestRequest::kReadOnly |
HitTestRequest::kActive,
- const LayoutRectOutsets& padding = LayoutRectOutsets(),
- const LayoutObject* stop_node = nullptr);
+ const LayoutObject* stop_node = nullptr,
+ bool no_lifecycle_update = false);
bool MousePressed() const { return mouse_event_manager_->MousePressed(); }
bool IsMousePositionUnknown() const {
@@ -189,10 +189,12 @@ class CORE_EXPORT EventHandler final
WebInputEventResult HandleGestureScrollEnd(const WebGestureEvent&);
bool IsScrollbarHandlingGestures() const;
- bool BestClickableNodeForHitTestResult(const HitTestResult&,
+ bool BestClickableNodeForHitTestResult(const HitTestLocation& location,
+ const HitTestResult&,
IntPoint& target_point,
Node*& target_node);
- bool BestContextMenuNodeForHitTestResult(const HitTestResult&,
+ bool BestContextMenuNodeForHitTestResult(const HitTestLocation& location,
+ const HitTestResult&,
IntPoint& target_point,
Node*& target_node);
void CacheTouchAdjustmentResult(uint32_t, FloatPoint);
@@ -270,6 +272,8 @@ class CORE_EXPORT EventHandler final
return *event_handler_registry_;
}
+ void AnimateSnapFling(base::TimeTicks monotonic_time);
+
private:
enum NoCursorChangeType { kNoCursorChange };
@@ -294,10 +298,12 @@ class CORE_EXPORT EventHandler final
const WebMouseEvent&,
const Vector<WebMouseEvent>&,
HitTestResult* hovered_node = nullptr,
+ HitTestLocation* hit_test_location = nullptr,
bool only_update_scrollbars = false,
bool force_leave = false);
- void ApplyTouchAdjustment(WebGestureEvent*, HitTestResult*);
+ // Updates the event, location and result to the adjusted target.
+ void ApplyTouchAdjustment(WebGestureEvent*, HitTestLocation&, HitTestResult*);
WebInputEventResult HandleGestureTapDown(
const GestureEventWithHitTestResults&);
WebInputEventResult HandleGestureTap(const GestureEventWithHitTestResults&);
@@ -306,6 +312,10 @@ class CORE_EXPORT EventHandler final
WebInputEventResult HandleGestureLongTap(
const GestureEventWithHitTestResults&);
+ void PerformHitTest(const HitTestLocation& location,
+ HitTestResult&,
+ bool no_lifecycle_update) const;
+
void UpdateGestureTargetNodeForMouseEvent(
const GestureEventWithHitTestResults&);
@@ -313,8 +323,9 @@ class CORE_EXPORT EventHandler final
bool GestureCorrespondsToAdjustedTouch(const WebGestureEvent&);
bool IsSelectingLink(const HitTestResult&);
bool ShouldShowIBeamForNode(const Node*, const HitTestResult&);
- bool ShouldShowResizeForNode(const Node*, const HitTestResult&);
- OptionalCursor SelectCursor(const HitTestResult&);
+ bool ShouldShowResizeForNode(const Node*, const HitTestLocation&);
+ OptionalCursor SelectCursor(const HitTestLocation& location,
+ const HitTestResult&);
OptionalCursor SelectAutoCursor(const HitTestResult&,
Node*,
const Cursor& i_beam);
@@ -345,7 +356,8 @@ class CORE_EXPORT EventHandler final
MouseEventWithHitTestResults&,
const Vector<WebMouseEvent>&,
LocalFrame* subframe,
- HitTestResult* hovered_node = nullptr);
+ HitTestResult* hovered_node = nullptr,
+ HitTestLocation* hit_test_location = nullptr);
WebInputEventResult PassMouseReleaseEventToSubframe(
MouseEventWithHitTestResults&,
LocalFrame* subframe);
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 1e5b10ef418..399af96b68e 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
@@ -24,6 +24,7 @@
#include "third_party/blink/renderer/core/loader/empty_clients.h"
#include "third_party/blink/renderer/core/page/autoscroll_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/core/testing/page_test_base.h"
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
@@ -151,8 +152,8 @@ TEST_F(EventHandlerTest, dragSelectionAfterScroll) {
"</div>");
LocalFrameView* frame_view = GetDocument().View();
- frame_view->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 400), kProgrammaticScroll);
+ frame_view->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 400),
+ kProgrammaticScroll);
WebMouseEvent mouse_down_event(WebInputEvent::kMouseDown, WebFloatPoint(0, 0),
WebFloatPoint(100, 200),
@@ -347,9 +348,10 @@ TEST_F(EventHandlerTest, draggedSVGImagePositionTest) {
TEST_F(EventHandlerTest, HitOnNothingDoesNotShowIBeam) {
SetHtmlInnerHTML("");
+ HitTestLocation location((LayoutPoint(10, 10)));
HitTestResult hit =
- GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
- LayoutPoint(10, 10));
+ GetDocument().GetFrame()->GetEventHandler().HitTestResultAtLocation(
+ location);
EXPECT_FALSE(
GetDocument().GetFrame()->GetEventHandler().ShouldShowIBeamForNode(
GetDocument().body(), hit));
@@ -358,10 +360,10 @@ TEST_F(EventHandlerTest, HitOnNothingDoesNotShowIBeam) {
TEST_F(EventHandlerTest, HitOnTextShowsIBeam) {
SetHtmlInnerHTML("blabla");
Node* const text = GetDocument().body()->firstChild();
- LayoutPoint location =
- text->GetLayoutObject()->FirstFragment().VisualRect().Center();
+ HitTestLocation location(
+ text->GetLayoutObject()->FirstFragment().VisualRect().Center());
HitTestResult hit =
- GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+ GetDocument().GetFrame()->GetEventHandler().HitTestResultAtLocation(
location);
EXPECT_TRUE(text->CanStartSelection());
EXPECT_TRUE(
@@ -372,10 +374,10 @@ TEST_F(EventHandlerTest, HitOnTextShowsIBeam) {
TEST_F(EventHandlerTest, HitOnUserSelectNoneDoesNotShowIBeam) {
SetHtmlInnerHTML("<span style='user-select: none'>blabla</span>");
Node* const text = GetDocument().body()->firstChild()->firstChild();
- LayoutPoint location =
- text->GetLayoutObject()->FirstFragment().VisualRect().Center();
+ HitTestLocation location(
+ text->GetLayoutObject()->FirstFragment().VisualRect().Center());
HitTestResult hit =
- GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+ GetDocument().GetFrame()->GetEventHandler().HitTestResultAtLocation(
location);
EXPECT_FALSE(text->CanStartSelection());
EXPECT_FALSE(
@@ -389,10 +391,10 @@ TEST_F(EventHandlerTest, ShadowChildCanOverrideUserSelectNone) {
"<span style='user-select: text' id='bla'>blabla</span>", "host");
Node* const text = shadow_root->getElementById("bla")->firstChild();
- LayoutPoint location =
- text->GetLayoutObject()->FirstFragment().VisualRect().Center();
+ HitTestLocation location(
+ text->GetLayoutObject()->FirstFragment().VisualRect().Center());
HitTestResult hit =
- GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+ GetDocument().GetFrame()->GetEventHandler().HitTestResultAtLocation(
location);
EXPECT_TRUE(text->CanStartSelection());
EXPECT_TRUE(
@@ -407,10 +409,10 @@ TEST_F(EventHandlerTest, UserSelectAllCanOverrideUserSelectNone) {
"</div>");
Node* const text =
GetDocument().body()->firstChild()->firstChild()->firstChild();
- LayoutPoint location =
- text->GetLayoutObject()->FirstFragment().VisualRect().Center();
+ HitTestLocation location(
+ text->GetLayoutObject()->FirstFragment().VisualRect().Center());
HitTestResult hit =
- GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+ GetDocument().GetFrame()->GetEventHandler().HitTestResultAtLocation(
location);
EXPECT_TRUE(text->CanStartSelection());
EXPECT_TRUE(
@@ -425,10 +427,10 @@ TEST_F(EventHandlerTest, UserSelectNoneCanOverrideUserSelectAll) {
"</div>");
Node* const text =
GetDocument().body()->firstChild()->firstChild()->firstChild();
- LayoutPoint location =
- text->GetLayoutObject()->FirstFragment().VisualRect().Center();
+ HitTestLocation location(
+ text->GetLayoutObject()->FirstFragment().VisualRect().Center());
HitTestResult hit =
- GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+ GetDocument().GetFrame()->GetEventHandler().HitTestResultAtLocation(
location);
EXPECT_FALSE(text->CanStartSelection());
EXPECT_FALSE(
@@ -443,10 +445,10 @@ TEST_F(EventHandlerTest, UserSelectTextCanOverrideUserSelectNone) {
"</div>");
Node* const text =
GetDocument().body()->firstChild()->firstChild()->firstChild();
- LayoutPoint location =
- text->GetLayoutObject()->FirstFragment().VisualRect().Center();
+ HitTestLocation location(
+ text->GetLayoutObject()->FirstFragment().VisualRect().Center());
HitTestResult hit =
- GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+ GetDocument().GetFrame()->GetEventHandler().HitTestResultAtLocation(
location);
EXPECT_TRUE(text->CanStartSelection());
EXPECT_TRUE(
@@ -460,10 +462,10 @@ TEST_F(EventHandlerTest, UserSelectNoneCanOverrideUserSelectText) {
"<span style='user-select: none'>blabla</span>"
"</div>");
Node* const text = GetDocument().body()->firstChild()->firstChild()->firstChild();
- LayoutPoint location =
- text->GetLayoutObject()->FirstFragment().VisualRect().Center();
+ HitTestLocation location(
+ text->GetLayoutObject()->FirstFragment().VisualRect().Center());
HitTestResult hit =
- GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+ GetDocument().GetFrame()->GetEventHandler().HitTestResultAtLocation(
location);
EXPECT_FALSE(text->CanStartSelection());
EXPECT_FALSE(
@@ -477,10 +479,10 @@ TEST_F(EventHandlerTest, ShadowChildCanOverrideUserSelectText) {
"<span style='user-select: none' id='bla'>blabla</span>", "host");
Node* const text = shadow_root->getElementById("bla")->firstChild();
- LayoutPoint location =
- text->GetLayoutObject()->FirstFragment().VisualRect().Center();
+ HitTestLocation location(
+ text->GetLayoutObject()->FirstFragment().VisualRect().Center());
HitTestResult hit =
- GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+ GetDocument().GetFrame()->GetEventHandler().HitTestResultAtLocation(
location);
EXPECT_FALSE(text->CanStartSelection());
EXPECT_FALSE(
@@ -492,10 +494,10 @@ TEST_F(EventHandlerTest, InputFieldsCanStartSelection) {
SetHtmlInnerHTML("<input value='blabla'>");
auto* const field = ToHTMLInputElement(GetDocument().body()->firstChild());
Element* const text = field->InnerEditorElement();
- LayoutPoint location =
- text->GetLayoutObject()->FirstFragment().VisualRect().Center();
+ HitTestLocation location(
+ text->GetLayoutObject()->FirstFragment().VisualRect().Center());
HitTestResult hit =
- GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+ GetDocument().GetFrame()->GetEventHandler().HitTestResultAtLocation(
location);
EXPECT_TRUE(text->CanStartSelection());
EXPECT_TRUE(
@@ -512,10 +514,10 @@ TEST_F(EventHandlerTest, ReadOnlyInputDoesNotInheritUserSelect) {
ToHTMLInputElement(GetDocument().getElementById("sample"));
Node* const text = input->InnerEditorElement()->firstChild();
- LayoutPoint location =
- text->GetLayoutObject()->FirstFragment().VisualRect().Center();
+ HitTestLocation location(
+ text->GetLayoutObject()->FirstFragment().VisualRect().Center());
HitTestResult hit =
- GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+ GetDocument().GetFrame()->GetEventHandler().HitTestResultAtLocation(
location);
EXPECT_TRUE(text->CanStartSelection());
EXPECT_TRUE(
@@ -526,10 +528,10 @@ TEST_F(EventHandlerTest, ReadOnlyInputDoesNotInheritUserSelect) {
TEST_F(EventHandlerTest, ImagesCannotStartSelection) {
SetHtmlInnerHTML("<img>");
Element* const img = ToElement(GetDocument().body()->firstChild());
- LayoutPoint location =
- img->GetLayoutObject()->FirstFragment().VisualRect().Center();
+ HitTestLocation location(
+ img->GetLayoutObject()->FirstFragment().VisualRect().Center());
HitTestResult hit =
- GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+ GetDocument().GetFrame()->GetEventHandler().HitTestResultAtLocation(
location);
EXPECT_FALSE(img->CanStartSelection());
EXPECT_FALSE(
@@ -540,24 +542,24 @@ TEST_F(EventHandlerTest, ImagesCannotStartSelection) {
TEST_F(EventHandlerTest, AnchorTextCannotStartSelection) {
SetHtmlInnerHTML("<a href='bala'>link text</a>");
Node* const link = GetDocument().body()->firstChild();
- LayoutPoint location =
- link->GetLayoutObject()->FirstFragment().VisualRect().Center();
- HitTestResult hit =
- GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+ HitTestLocation location(
+ link->GetLayoutObject()->FirstFragment().VisualRect().Center());
+ HitTestResult result =
+ GetDocument().GetFrame()->GetEventHandler().HitTestResultAtLocation(
location);
Node* const text = link->firstChild();
EXPECT_FALSE(text->CanStartSelection());
- EXPECT_TRUE(hit.IsOverLink());
+ EXPECT_TRUE(result.IsOverLink());
// ShouldShowIBeamForNode() returns |cursor: auto|'s value.
// In https://github.com/w3c/csswg-drafts/issues/1598 it was decided that:
// a { cursor: auto } /* gives I-beam over links */
EXPECT_TRUE(
- GetDocument().GetFrame()->GetEventHandler().ShouldShowIBeamForNode(text,
- hit));
+ GetDocument().GetFrame()->GetEventHandler().ShouldShowIBeamForNode(
+ text, result));
EXPECT_EQ(GetDocument()
.GetFrame()
->GetEventHandler()
- .SelectCursor(hit)
+ .SelectCursor(location, result)
.GetCursor()
.GetType(),
Cursor::Type::kHand); // A hand signals ability to navigate.
@@ -566,21 +568,21 @@ TEST_F(EventHandlerTest, AnchorTextCannotStartSelection) {
TEST_F(EventHandlerTest, EditableAnchorTextCanStartSelection) {
SetHtmlInnerHTML("<a contenteditable='true' href='bala'>editable link</a>");
Node* const link = GetDocument().body()->firstChild();
- LayoutPoint location =
- link->GetLayoutObject()->FirstFragment().VisualRect().Center();
- HitTestResult hit =
- GetDocument().GetFrame()->GetEventHandler().HitTestResultAtPoint(
+ HitTestLocation location(
+ link->GetLayoutObject()->FirstFragment().VisualRect().Center());
+ HitTestResult result =
+ GetDocument().GetFrame()->GetEventHandler().HitTestResultAtLocation(
location);
Node* const text = link->firstChild();
EXPECT_TRUE(text->CanStartSelection());
- EXPECT_TRUE(hit.IsOverLink());
+ EXPECT_TRUE(result.IsOverLink());
EXPECT_TRUE(
- GetDocument().GetFrame()->GetEventHandler().ShouldShowIBeamForNode(text,
- hit));
+ GetDocument().GetFrame()->GetEventHandler().ShouldShowIBeamForNode(
+ text, result));
EXPECT_EQ(GetDocument()
.GetFrame()
->GetEventHandler()
- .SelectCursor(hit)
+ .SelectCursor(location, result)
.GetCursor()
.GetType(),
Cursor::Type::kIBeam); // An I-beam signals editability.
diff --git a/chromium/third_party/blink/renderer/core/input/event_handling_util.cc b/chromium/third_party/blink/renderer/core/input/event_handling_util.cc
index 9793265e4df..0ee5fc42034 100644
--- a/chromium/third_party/blink/renderer/core/input/event_handling_util.cc
+++ b/chromium/third_party/blink/renderer/core/input/event_handling_util.cc
@@ -10,6 +10,7 @@
#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/paint_layer.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/scroll/scrollable_area.h"
namespace blink {
@@ -17,18 +18,19 @@ namespace EventHandlingUtil {
HitTestResult HitTestResultInFrame(
LocalFrame* frame,
- const LayoutPoint& point,
+ const HitTestLocation& location,
HitTestRequest::HitTestRequestType hit_type) {
- HitTestResult result(HitTestRequest(hit_type), point);
+ DCHECK(!location.IsRectBasedTest());
+ HitTestResult result(HitTestRequest(hit_type), location);
if (!frame || !frame->ContentLayoutObject())
return result;
if (frame->View()) {
- IntRect rect = frame->View()->VisibleContentRect(kIncludeScrollbars);
- if (!rect.Contains(RoundedIntPoint(point)))
+ FloatRect rect(FloatPoint(), FloatSize(frame->View()->Size()));
+ if (!location.Intersects(rect))
return result;
}
- frame->ContentLayoutObject()->HitTest(result);
+ frame->ContentLayoutObject()->HitTest(location, result);
return result;
}
@@ -111,7 +113,7 @@ LayoutPoint ContentPointFromRootFrame(LocalFrame* frame,
LocalFrameView* view = frame->View();
// FIXME: Is it really OK to use the wrong coordinates here when view is 0?
// Historically the code would just crash; this is clearly no worse than that.
- return LayoutPoint(view ? view->RootFrameToContents(point_in_root_frame)
+ return LayoutPoint(view ? view->ConvertFromRootFrame(point_in_root_frame)
: point_in_root_frame);
}
diff --git a/chromium/third_party/blink/renderer/core/input/event_handling_util.h b/chromium/third_party/blink/renderer/core/input/event_handling_util.h
index 3713b320a23..a8ccd4720dd 100644
--- a/chromium/third_party/blink/renderer/core/input/event_handling_util.h
+++ b/chromium/third_party/blink/renderer/core/input/event_handling_util.h
@@ -13,15 +13,18 @@
namespace blink {
+class ContainerNode;
+class EventTarget;
class LocalFrame;
class ScrollableArea;
class PaintLayer;
+enum class DispatchEventResult;
namespace EventHandlingUtil {
HitTestResult HitTestResultInFrame(
LocalFrame*,
- const LayoutPoint&,
+ const HitTestLocation&,
HitTestRequest::HitTestRequestType hit_type = HitTestRequest::kReadOnly |
HitTestRequest::kActive);
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 513f0e3c1ac..dbe687c2fe8 100644
--- a/chromium/third_party/blink/renderer/core/input/gesture_manager.cc
+++ b/chromium/third_party/blink/renderer/core/input/gesture_manager.cc
@@ -19,6 +19,8 @@
#include "third_party/blink/renderer/core/input/input_device_capabilities.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/paint/paint_layer_scrollable_area.h"
+#include "third_party/blink/renderer/platform/scroll/scroll_animator_base.h"
#if BUILDFLAG(ENABLE_UNHANDLED_TAP)
#include "services/service_manager/public/cpp/interface_provider.h"
@@ -124,9 +126,6 @@ WebInputEventResult GestureManager::HandleGestureEventInFrame(
return HandleGestureLongTap(targeted_event);
case WebInputEvent::kGestureTwoFingerTap:
return HandleGestureTwoFingerTap(targeted_event);
- case WebInputEvent::kGesturePinchBegin:
- case WebInputEvent::kGesturePinchEnd:
- case WebInputEvent::kGesturePinchUpdate:
case WebInputEvent::kGestureTapCancel:
case WebInputEvent::kGestureTapUnconfirmed:
break;
@@ -156,10 +155,12 @@ WebInputEventResult GestureManager::HandleGestureTap(
uint64_t pre_dispatch_style_version = frame_->GetDocument()->StyleVersion();
HitTestResult current_hit_test = targeted_event.GetHitTestResult();
+ const HitTestLocation& current_hit_test_location =
+ targeted_event.GetHitTestLocation();
// We use the adjusted position so the application isn't surprised to see a
// event with co-ordinates outside the target's bounds.
- IntPoint adjusted_point = frame_view->RootFrameToContents(
+ IntPoint adjusted_point = frame_view->ConvertFromRootFrame(
FlooredIntPoint(gesture_event.PositionInRootFrame()));
const unsigned modifiers = gesture_event.GetModifiers();
@@ -190,12 +191,12 @@ WebInputEventResult GestureManager::HandleGestureTap(
if (current_hit_test.InnerNode()) {
LocalFrame& main_frame = frame_->LocalFrameRoot();
if (!main_frame.View() ||
- !main_frame.View()->UpdateLifecycleToPrePaintClean())
+ !main_frame.View()->UpdateAllLifecyclePhasesExceptPaint())
return WebInputEventResult::kNotHandled;
- adjusted_point = frame_view->RootFrameToContents(
+ adjusted_point = frame_view->ConvertFromRootFrame(
FlooredIntPoint(gesture_event.PositionInRootFrame()));
current_hit_test = EventHandlingUtil::HitTestResultInFrame(
- frame_, adjusted_point, hit_type);
+ frame_, HitTestLocation(adjusted_point), hit_type);
}
// Capture data for showUnhandledTapUIIfNeeded.
@@ -238,7 +239,8 @@ WebInputEventResult GestureManager::HandleGestureTap(
}
if (mouse_down_event_result == WebInputEventResult::kNotHandled) {
mouse_down_event_result = mouse_event_manager_->HandleMousePressEvent(
- MouseEventWithHitTestResults(fake_mouse_down, current_hit_test));
+ MouseEventWithHitTestResults(
+ fake_mouse_down, current_hit_test_location, current_hit_test));
}
}
@@ -255,9 +257,9 @@ WebInputEventResult GestureManager::HandleGestureTap(
LocalFrame& main_frame = frame_->LocalFrameRoot();
if (main_frame.View())
main_frame.View()->UpdateAllLifecyclePhases();
- adjusted_point = frame_view->RootFrameToContents(tapped_position);
+ adjusted_point = frame_view->ConvertFromRootFrame(tapped_position);
current_hit_test = EventHandlingUtil::HitTestResultInFrame(
- frame_, adjusted_point, hit_type);
+ frame_, HitTestLocation(adjusted_point), hit_type);
}
WebMouseEvent fake_mouse_up(
@@ -293,9 +295,11 @@ WebInputEventResult GestureManager::HandleGestureTap(
mouse_event_manager_->SetClickElement(nullptr);
}
- if (mouse_up_event_result == WebInputEventResult::kNotHandled)
+ if (mouse_up_event_result == WebInputEventResult::kNotHandled) {
mouse_up_event_result = mouse_event_manager_->HandleMouseReleaseEvent(
- MouseEventWithHitTestResults(fake_mouse_up, current_hit_test));
+ MouseEventWithHitTestResults(fake_mouse_up, current_hit_test_location,
+ current_hit_test));
+ }
mouse_event_manager_->ClearDragHeuristicState();
WebInputEventResult event_result = EventHandlingUtil::MergeEventResult(
@@ -327,10 +331,10 @@ WebInputEventResult GestureManager::HandleGestureLongPress(
// overhaul of the touch drag-and-drop code and LongPress is such a special
// scenario that it's unlikely to matter much in practice.
- IntPoint hit_test_point = frame_->View()->RootFrameToContents(
- FlooredIntPoint(gesture_event.PositionInRootFrame()));
+ HitTestLocation location(frame_->View()->ConvertFromRootFrame(
+ FlooredIntPoint(gesture_event.PositionInRootFrame())));
HitTestResult hit_test_result =
- frame_->GetEventHandler().HitTestResultAtPoint(hit_test_point);
+ frame_->GetEventHandler().HitTestResultAtLocation(location);
long_tap_should_invoke_context_menu_ = false;
bool hit_test_contains_links = hit_test_result.URLElement() ||
@@ -414,7 +418,7 @@ WebInputEventResult GestureManager::SendContextMenuEventForGesture(
if (!suppress_mouse_events_from_gestures_ && frame_->View()) {
HitTestRequest request(HitTestRequest::kActive);
- LayoutPoint document_point = frame_->View()->RootFrameToContents(
+ LayoutPoint document_point = frame_->View()->ConvertFromRootFrame(
FlooredIntPoint(targeted_event.Event().PositionInRootFrame()));
MouseEventWithHitTestResults mev =
frame_->GetDocument()->PerformMouseEventHitTest(request, document_point,
@@ -432,12 +436,10 @@ WebInputEventResult GestureManager::HandleGestureShowPress() {
LocalFrameView* view = frame_->View();
if (!view)
return WebInputEventResult::kNotHandled;
- if (ScrollAnimatorBase* scroll_animator = view->ExistingScrollAnimator())
- scroll_animator->CancelAnimation();
const LocalFrameView::ScrollableAreaSet* areas = view->ScrollableAreas();
if (!areas)
return WebInputEventResult::kNotHandled;
- for (const ScrollableArea* scrollable_area : *areas) {
+ for (const PaintLayerScrollableArea* scrollable_area : *areas) {
ScrollAnimatorBase* animator = scrollable_area->ExistingScrollAnimator();
if (animator)
animator->CancelAnimation();
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 2207b5de948..79e0df06a96 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
@@ -34,6 +34,7 @@
#include "third_party/blink/renderer/core/page/drag_state.h"
#include "third_party/blink/renderer/core/page/focus_controller.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/svg/svg_document_extensions.h"
#include "third_party/blink/renderer/platform/geometry/float_quad.h"
#include "third_party/blink/renderer/platform/histogram.h"
@@ -61,11 +62,13 @@ String CanvasRegionId(Node* node, const WebMouseEvent& mouse_event) {
// The amount of time to wait before sending a fake mouse event triggered
// during a scroll.
-constexpr double kFakeMouseMoveIntervalDuringScroll = 0.1;
+constexpr TimeDelta kFakeMouseMoveIntervalDuringScroll =
+ TimeDelta::FromMilliseconds(100);
// The amount of time to wait before sending a fake mouse event on style and
// layout changes sets to 50Hz, same as common screen refresh rate.
-constexpr double kFakeMouseMoveIntervalPerFrame = 0.02;
+constexpr TimeDelta kFakeMouseMoveIntervalPerFrame =
+ TimeDelta::FromMilliseconds(20);
// TODO(crbug.com/653490): Read these values from the OS.
#if defined(OS_MACOSX)
@@ -113,6 +116,7 @@ void MouseEventManager::Clear() {
drag_start_pos_ = LayoutPoint();
fake_mouse_move_event_timer_.Stop();
ResetDragState();
+ ClearDragDataTransfer();
}
MouseEventManager::~MouseEventManager() = default;
@@ -393,34 +397,18 @@ void MouseEventManager::SetNodeUnderMouse(
EventHandlingUtil::LayerForNode(node_under_mouse_.Get());
Page* page = frame_->GetPage();
- if (last_node_under_mouse &&
- (!node_under_mouse_ ||
- node_under_mouse_->GetDocument() != frame_->GetDocument())) {
- // The mouse has moved between frames.
- if (LocalFrame* frame = last_node_under_mouse->GetDocument().GetFrame()) {
- if (LocalFrameView* frame_view = frame->View())
- frame_view->MouseExitedContentArea();
- }
- } else if (page && (layer_for_last_node &&
- (!layer_for_node_under_mouse ||
- layer_for_node_under_mouse != layer_for_last_node))) {
+ if (page && (layer_for_last_node &&
+ (!layer_for_node_under_mouse ||
+ layer_for_node_under_mouse != layer_for_last_node))) {
// The mouse has moved between layers.
if (ScrollableArea* scrollable_area_for_last_node =
EventHandlingUtil::AssociatedScrollableArea(layer_for_last_node))
scrollable_area_for_last_node->MouseExitedContentArea();
}
- if (node_under_mouse_ &&
- (!last_node_under_mouse ||
- last_node_under_mouse->GetDocument() != frame_->GetDocument())) {
- // The mouse has moved between frames.
- if (LocalFrame* frame = node_under_mouse_->GetDocument().GetFrame()) {
- if (LocalFrameView* frame_view = frame->View())
- frame_view->MouseEnteredContentArea();
- }
- } else if (page && (layer_for_node_under_mouse &&
- (!layer_for_last_node ||
- layer_for_node_under_mouse != layer_for_last_node))) {
+ if (page && (layer_for_node_under_mouse &&
+ (!layer_for_last_node ||
+ layer_for_node_under_mouse != layer_for_last_node))) {
// The mouse has moved between layers.
if (ScrollableArea* scrollable_area_for_node_under_mouse =
EventHandlingUtil::AssociatedScrollableArea(
@@ -588,7 +576,7 @@ void MouseEventManager::HandleMousePressEventUpdateStates(
mouse_down_timestamp_ = mouse_event.TimeStamp();
if (LocalFrameView* view = frame_->View()) {
- mouse_down_pos_ = view->RootFrameToContents(
+ mouse_down_pos_ = view->ConvertFromRootFrame(
FlooredIntPoint(mouse_event.PositionInRootFrame()));
} else {
InvalidateClick();
@@ -638,7 +626,7 @@ void MouseEventManager::DispatchFakeMouseMoveEventSoon(
// during a scroll. This avoids a potential source of scroll jank.
// Or dispatch a fake mouse move to update hover states when the layout
// changes.
- double interval =
+ TimeDelta interval =
fake_mouse_move_reason ==
MouseEventManager::FakeMouseMoveReason::kDuringScroll
? kFakeMouseMoveIntervalDuringScroll
@@ -652,7 +640,7 @@ void MouseEventManager::DispatchFakeMouseMoveEventSoonInQuad(
if (!view)
return;
- if (!quad.ContainsPoint(view->ViewportToContents(last_known_mouse_position_)))
+ if (!quad.ContainsPoint(view->ViewportToFrame(last_known_mouse_position_)))
return;
DispatchFakeMouseMoveEventSoon(
@@ -668,12 +656,6 @@ WebInputEventResult MouseEventManager::HandleMousePressEvent(
frame_->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
- if (LocalFrameView* frame_view = frame_->View()) {
- if (frame_view->IsPointInScrollbarCorner(
- FlooredIntPoint(event.Event().PositionInRootFrame())))
- return WebInputEventResult::kNotHandled;
- }
-
bool single_click = event.Event().click_count <= 1;
mouse_down_may_start_drag_ =
@@ -687,8 +669,8 @@ WebInputEventResult MouseEventManager::HandleMousePressEvent(
single_click) {
svg_pan_ = true;
frame_->GetDocument()->AccessSVGExtensions().StartPan(
- frame_->View()->RootFrameToContents(
- FlooredIntPoint(event.Event().PositionInRootFrame())));
+ frame_->View()->ConvertFromRootFrame(FloatPoint(
+ FlooredIntPoint(event.Event().PositionInRootFrame()))));
return WebInputEventResult::kHandledSystem;
}
}
@@ -770,7 +752,7 @@ bool MouseEventManager::HandleDragDropIfPossible(
mouse_drag_event);
mouse_down_may_start_drag_ = true;
ResetDragState();
- mouse_down_pos_ = frame_->View()->RootFrameToContents(
+ mouse_down_pos_ = frame_->View()->ConvertFromRootFrame(
FlooredIntPoint(mouse_drag_event.PositionInRootFrame()));
return HandleDrag(mev, DragInitiator::kTouch);
}
@@ -888,8 +870,9 @@ bool MouseEventManager::HandleDrag(const MouseEventWithHitTestResults& event,
if (mouse_down_may_start_drag_) {
HitTestRequest request(HitTestRequest::kReadOnly);
- HitTestResult result(request, mouse_down_pos_);
- frame_->ContentLayoutObject()->HitTest(result);
+ HitTestLocation location(mouse_down_pos_);
+ HitTestResult result(request, location);
+ frame_->ContentLayoutObject()->HitTest(location, result);
Node* node = result.InnerNode();
if (node) {
DragController::SelectionDragPolicy selection_drag_policy =
@@ -1113,7 +1096,7 @@ bool MouseEventManager::DragThresholdExceeded(
if (!view)
return false;
IntPoint drag_location =
- view->RootFrameToContents(drag_location_in_root_frame);
+ view->ConvertFromRootFrame(drag_location_in_root_frame);
IntSize delta = drag_location - mouse_down_pos_;
// WebKit's drag thresholds depend on the type of object being dragged. If we
@@ -1138,7 +1121,7 @@ bool MouseEventManager::HandleSvgPanIfNeeded(bool is_release_event) {
return false;
svg_pan_ = !is_release_event;
frame_->GetDocument()->AccessSVGExtensions().UpdatePan(
- frame_->View()->ViewportToContents(last_known_mouse_position_));
+ frame_->View()->ViewportToFrame(last_known_mouse_position_));
return true;
}
diff --git a/chromium/third_party/blink/renderer/core/input/mouse_wheel_event_manager.cc b/chromium/third_party/blink/renderer/core/input/mouse_wheel_event_manager.cc
index 92eae6872da..9c88c1d580c 100644
--- a/chromium/third_party/blink/renderer/core/input/mouse_wheel_event_manager.cc
+++ b/chromium/third_party/blink/renderer/core/input/mouse_wheel_event_manager.cc
@@ -30,9 +30,6 @@ void MouseWheelEventManager::Clear() {
WebInputEventResult MouseWheelEventManager::HandleWheelEvent(
const WebMouseWheelEvent& event) {
- bool wheel_scroll_latching =
- RuntimeEnabledFeatures::TouchpadAndWheelScrollLatchingEnabled();
-
Document* doc = frame_->GetDocument();
if (!doc || !doc->GetLayoutView())
return WebInputEventResult::kNotHandled;
@@ -41,53 +38,32 @@ WebInputEventResult MouseWheelEventManager::HandleWheelEvent(
if (!view)
return WebInputEventResult::kNotHandled;
- if (wheel_scroll_latching) {
- const int kWheelEventPhaseEndedEventMask =
- WebMouseWheelEvent::kPhaseEnded | WebMouseWheelEvent::kPhaseCancelled;
- const int kWheelEventPhaseNoEventMask =
- kWheelEventPhaseEndedEventMask | WebMouseWheelEvent::kPhaseMayBegin;
-
- if ((event.phase & kWheelEventPhaseEndedEventMask) ||
- (event.momentum_phase & kWheelEventPhaseEndedEventMask)) {
- wheel_target_ = nullptr;
- }
+ const int kWheelEventPhaseEndedEventMask =
+ WebMouseWheelEvent::kPhaseEnded | WebMouseWheelEvent::kPhaseCancelled;
+ const int kWheelEventPhaseNoEventMask =
+ kWheelEventPhaseEndedEventMask | WebMouseWheelEvent::kPhaseMayBegin;
- if ((event.phase & kWheelEventPhaseNoEventMask) ||
- (event.momentum_phase & kWheelEventPhaseNoEventMask)) {
- // Filter wheel events with zero deltas and reset the wheel_target_ node.
- DCHECK(!event.delta_x && !event.delta_y);
- return WebInputEventResult::kNotHandled;
- }
+ if ((event.phase & kWheelEventPhaseEndedEventMask) ||
+ (event.momentum_phase & kWheelEventPhaseEndedEventMask)) {
+ wheel_target_ = nullptr;
+ }
- bool has_phase_info =
- event.phase != WebMouseWheelEvent::kPhaseNone ||
- event.momentum_phase != WebMouseWheelEvent::kPhaseNone;
- if (!has_phase_info) {
- // Synthetic wheel events generated from GesturePinchUpdate don't have
- // phase info. Send these events to the target under the cursor.
- wheel_target_ = FindTargetNode(event, doc, view);
- } else if (event.phase == WebMouseWheelEvent::kPhaseBegan ||
- !wheel_target_) {
- // Find and save the wheel_target_, this target will be used for the rest
- // of the current scrolling sequence.
- wheel_target_ = FindTargetNode(event, doc, view);
- }
- } else { // !wheel_scroll_latching, wheel_target_ will be updated for each
- // wheel event.
-#if defined(OS_MACOSX)
- // Filter Mac OS specific phases, usually with a zero-delta.
- // https://crbug.com/553732
- // TODO(chongz): EventSender sends events with
- // |WebMouseWheelEvent::PhaseNone|,
- // but it shouldn't.
- const int kWheelEventPhaseNoEventMask =
- WebMouseWheelEvent::kPhaseEnded | WebMouseWheelEvent::kPhaseCancelled |
- WebMouseWheelEvent::kPhaseMayBegin;
- if ((event.phase & kWheelEventPhaseNoEventMask) ||
- (event.momentum_phase & kWheelEventPhaseNoEventMask))
- return WebInputEventResult::kNotHandled;
-#endif
+ if ((event.phase & kWheelEventPhaseNoEventMask) ||
+ (event.momentum_phase & kWheelEventPhaseNoEventMask)) {
+ // Filter wheel events with zero deltas and reset the wheel_target_ node.
+ DCHECK(!event.delta_x && !event.delta_y);
+ return WebInputEventResult::kNotHandled;
+ }
+ bool has_phase_info = event.phase != WebMouseWheelEvent::kPhaseNone ||
+ event.momentum_phase != WebMouseWheelEvent::kPhaseNone;
+ if (!has_phase_info) {
+ // Synthetic wheel events generated from GesturePinchUpdate don't have
+ // phase info. Send these events to the target under the cursor.
+ wheel_target_ = FindTargetNode(event, doc, view);
+ } else if (event.phase == WebMouseWheelEvent::kPhaseBegan || !wheel_target_) {
+ // Find and save the wheel_target_, this target will be used for the rest
+ // of the current scrolling sequence.
wheel_target_ = FindTargetNode(event, doc, view);
}
@@ -102,10 +78,34 @@ WebInputEventResult MouseWheelEventManager::HandleWheelEvent(
if (wheel_target_) {
WheelEvent* dom_event =
WheelEvent::Create(event, wheel_target_->GetDocument().domWindow());
+ // The event handler might remove |wheel_target_| from DOM so we should get
+ // this value now (see https://crbug.com/857013).
+ bool should_enforce_vertical_scroll =
+ wheel_target_->GetDocument().IsVerticalScrollEnforced();
DispatchEventResult dom_event_result =
wheel_target_->DispatchEvent(dom_event);
- if (dom_event_result != DispatchEventResult::kNotCanceled)
- return EventHandlingUtil::ToWebInputEventResult(dom_event_result);
+ if (dom_event_result != DispatchEventResult::kNotCanceled) {
+ // Reset the target if the dom event is cancelled to make sure that new
+ // targeting happens for the next wheel event.
+ wheel_target_ = nullptr;
+ // TODO(ekaramad): This does not seem correct. The behavior of shift +
+ // scrolling seems different on Mac vs Linux/Windows. We need this done
+ // properly and perhaps even tag WebMouseWheelEvent with a scrolling
+ // direction (https://crbug.com/853292).
+ // When using shift + mouse scroll (to horizontally scroll), the expected
+ // value of |delta_x| is exactly zero.
+ bool is_vertical =
+ (std::abs(dom_event->deltaX()) < std::abs(dom_event->deltaY())) &&
+ (!dom_event->shiftKey() || dom_event->deltaX() != 0);
+ // TODO(ekaramad): If the only wheel handlers on the page are from such
+ // disabled frames we should simply start scrolling on CC and the events
+ // must get here as passive (https://crbug.com/853059).
+ // Overwriting the dispatch results ensures that vertical scroll cannot be
+ // blocked by disabled frames.
+ return (should_enforce_vertical_scroll && is_vertical)
+ ? WebInputEventResult::kNotHandled
+ : EventHandlingUtil::ToWebInputEventResult(dom_event_result);
+ }
}
return WebInputEventResult::kNotHandled;
@@ -121,11 +121,12 @@ Node* MouseWheelEventManager::FindTargetNode(const WebMouseWheelEvent& event,
const LocalFrameView* view) {
DCHECK(doc && doc->GetLayoutView() && view);
LayoutPoint v_point =
- view->RootFrameToContents(FlooredIntPoint(event.PositionInRootFrame()));
+ view->ConvertFromRootFrame(FlooredIntPoint(event.PositionInRootFrame()));
HitTestRequest request(HitTestRequest::kReadOnly);
- HitTestResult result(request, v_point);
- doc->GetLayoutView()->HitTest(result);
+ HitTestLocation location(v_point);
+ HitTestResult result(request, location);
+ doc->GetLayoutView()->HitTest(location, result);
Node* node = result.InnerNode();
// Wheel events should not dispatch to text nodes.
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 99194c3c383..1a981850154 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
@@ -328,27 +328,26 @@ void PointerEventManager::AdjustTouchPointerEvent(
DCHECK(pointer_event.pointer_type ==
WebPointerProperties::PointerType::kTouch);
- LayoutSize padding = GetHitTestRectForAdjustment(
- LayoutSize(pointer_event.width, pointer_event.height) * 0.5f);
+ LayoutSize hit_rect_size = GetHitTestRectForAdjustment(
+ LayoutSize(pointer_event.width, pointer_event.height));
- if (padding.IsEmpty())
+ if (hit_rect_size.IsEmpty())
return;
HitTestRequest::HitTestRequestType hit_type =
HitTestRequest::kTouchEvent | HitTestRequest::kReadOnly |
HitTestRequest::kActive | HitTestRequest::kListBased;
- LayoutPoint hit_test_point = frame_->View()->RootFrameToContents(
- LayoutPoint(pointer_event.PositionInWidget()));
+ LocalFrame& root_frame = frame_->LocalFrameRoot();
+ // TODO(szager): Shouldn't this be PositionInScreen() ?
+ LayoutPoint hit_test_point((FloatPoint)pointer_event.PositionInWidget());
+ hit_test_point.Move(-hit_rect_size * 0.5f);
+ HitTestLocation location(LayoutRect(hit_test_point, hit_rect_size));
HitTestResult hit_test_result =
- frame_->GetEventHandler().HitTestResultAtPoint(
- hit_test_point, hit_type,
- LayoutRectOutsets(padding.Height(), padding.Width(), padding.Height(),
- padding.Width()));
-
+ root_frame.GetEventHandler().HitTestResultAtLocation(location, hit_type);
Node* adjusted_node = nullptr;
IntPoint adjusted_point;
bool adjusted = frame_->GetEventHandler().BestClickableNodeForHitTestResult(
- hit_test_result, adjusted_point, adjusted_node);
+ location, hit_test_result, adjusted_point, adjusted_node);
if (adjusted)
pointer_event.SetPositionInWidget(adjusted_point.X(), adjusted_point.Y());
@@ -373,10 +372,10 @@ PointerEventManager::ComputePointerEventTarget(
HitTestRequest::HitTestRequestType hit_type = HitTestRequest::kTouchEvent |
HitTestRequest::kReadOnly |
HitTestRequest::kActive;
- LayoutPoint page_point = frame_->View()->RootFrameToContents(
- LayoutPoint(web_pointer_event.PositionInWidget()));
+ HitTestLocation location(frame_->View()->ConvertFromRootFrame(
+ LayoutPoint(web_pointer_event.PositionInWidget())));
HitTestResult hit_test_tesult =
- frame_->GetEventHandler().HitTestResultAtPoint(page_point, hit_type);
+ frame_->GetEventHandler().HitTestResultAtLocation(location, hit_type);
Node* node = hit_test_tesult.InnerNode();
if (node) {
pointer_event_target.target_frame = node->GetDocument().GetFrame();
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 fd3fb89ec15..f2ffe18d24b 100644
--- a/chromium/third_party/blink/renderer/core/input/scroll_manager.cc
+++ b/chromium/third_party/blink/renderer/core/input/scroll_manager.cc
@@ -17,6 +17,7 @@
#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/page/autoscroll_controller.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/overscroll_controller.h"
#include "third_party/blink/renderer/core/page/scrolling/root_scroller_controller.h"
@@ -24,13 +25,44 @@
#include "third_party/blink/renderer/core/page/scrolling/scroll_state.h"
#include "third_party/blink/renderer/core/page/scrolling/snap_coordinator.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/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/scroll/scroll_customization.h"
namespace blink {
+namespace {
+
+SnapFlingController::GestureScrollType ToGestureScrollType(
+ WebInputEvent::Type web_event_type) {
+ switch (web_event_type) {
+ case WebInputEvent::kGestureScrollBegin:
+ return SnapFlingController::GestureScrollType::kBegin;
+ case WebInputEvent::kGestureScrollUpdate:
+ return SnapFlingController::GestureScrollType::kUpdate;
+ case WebInputEvent::kGestureScrollEnd:
+ return SnapFlingController::GestureScrollType::kEnd;
+ default:
+ NOTREACHED();
+ return SnapFlingController::GestureScrollType::kBegin;
+ }
+}
+
+SnapFlingController::GestureScrollUpdateInfo GetGestureScrollUpdateInfo(
+ const WebGestureEvent& event) {
+ return {.delta = gfx::Vector2dF(-event.data.scroll_update.delta_x,
+ -event.data.scroll_update.delta_y),
+ .is_in_inertial_phase = event.data.scroll_update.inertial_phase ==
+ WebGestureEvent::kMomentumPhase,
+ .event_time = event.TimeStamp()};
+}
+
+} // namespace
ScrollManager::ScrollManager(LocalFrame& frame) : frame_(frame) {
+ if (RuntimeEnabledFeatures::CSSScrollSnapPointsEnabled())
+ snap_fling_controller_ = std::make_unique<cc::SnapFlingController>(this);
+
Clear();
}
@@ -455,6 +487,12 @@ WebInputEventResult ScrollManager::HandleGestureScrollUpdate(
return WebInputEventResult::kNotHandled;
}
}
+ if (snap_fling_controller_) {
+ if (snap_fling_controller_->HandleGestureScrollUpdate(
+ GetGestureScrollUpdateInfo(gesture_event))) {
+ return WebInputEventResult::kHandledSystem;
+ }
+ }
// Negate the deltas since the gesture event stores finger movement and
// scrolling occurs in the direction opposite the finger's movement
@@ -537,25 +575,6 @@ WebInputEventResult ScrollManager::HandleGestureScrollUpdate(
return WebInputEventResult::kNotHandled;
}
-void ScrollManager::SnapAtGestureScrollEnd() {
- if (!previous_gesture_scrolled_element_)
- return;
- SnapCoordinator* snap_coordinator =
- frame_->GetDocument()->GetSnapCoordinator();
- Element* document_element = frame_->GetDocument()->documentElement();
- LayoutBox* layout_box =
- previous_gesture_scrolled_element_ == document_element
- ? frame_->GetDocument()->GetLayoutView()
- : previous_gesture_scrolled_element_->GetLayoutBox();
- if (!snap_coordinator || !layout_box || !layout_box->GetScrollableArea() ||
- (!did_scroll_x_for_scroll_gesture_ && !did_scroll_y_for_scroll_gesture_))
- return;
-
- snap_coordinator->PerformSnapping(*layout_box,
- did_scroll_x_for_scroll_gesture_,
- did_scroll_y_for_scroll_gesture_);
-}
-
WebInputEventResult ScrollManager::HandleGestureScrollEnd(
const WebGestureEvent& gesture_event) {
TRACE_EVENT0("input", "ScrollManager::handleGestureScrollEnd");
@@ -588,6 +607,101 @@ WebInputEventResult ScrollManager::HandleGestureScrollEnd(
return WebInputEventResult::kNotHandled;
}
+LayoutBox* ScrollManager::LayoutBoxForSnapping() const {
+ Element* document_element = frame_->GetDocument()->documentElement();
+ return previous_gesture_scrolled_element_ == document_element
+ ? frame_->GetDocument()->GetLayoutView()
+ : previous_gesture_scrolled_element_->GetLayoutBox();
+}
+
+ScrollableArea* ScrollManager::ScrollableAreaForSnapping() const {
+ Element* document_element = frame_->GetDocument()->documentElement();
+ return previous_gesture_scrolled_element_ == document_element
+ ? frame_->View()->GetScrollableArea()
+ : previous_gesture_scrolled_element_->GetLayoutBox()
+ ->GetScrollableArea();
+}
+
+void ScrollManager::SnapAtGestureScrollEnd() {
+ if (!previous_gesture_scrolled_element_ ||
+ (!did_scroll_x_for_scroll_gesture_ && !did_scroll_y_for_scroll_gesture_))
+ return;
+ SnapCoordinator* snap_coordinator =
+ frame_->GetDocument()->GetSnapCoordinator();
+ LayoutBox* layout_box = LayoutBoxForSnapping();
+ if (!snap_coordinator || !layout_box)
+ return;
+
+ snap_coordinator->PerformSnapping(*layout_box,
+ did_scroll_x_for_scroll_gesture_,
+ did_scroll_y_for_scroll_gesture_);
+}
+
+bool ScrollManager::GetSnapFlingInfo(const gfx::Vector2dF& natural_displacement,
+ gfx::Vector2dF* out_initial_offset,
+ gfx::Vector2dF* out_target_offset) const {
+ if (!previous_gesture_scrolled_element_)
+ return false;
+
+ SnapCoordinator* snap_coordinator =
+ frame_->GetDocument()->GetSnapCoordinator();
+ LayoutBox* layout_box = LayoutBoxForSnapping();
+ if (!snap_coordinator || !layout_box || !layout_box->GetScrollableArea())
+ return false;
+ return snap_coordinator->GetSnapFlingInfo(
+ *layout_box, natural_displacement, out_initial_offset, out_target_offset);
+}
+
+gfx::Vector2dF ScrollManager::ScrollByForSnapFling(
+ const gfx::Vector2dF& delta) {
+ DCHECK(previous_gesture_scrolled_element_);
+ std::unique_ptr<ScrollStateData> scroll_state_data =
+ std::make_unique<ScrollStateData>();
+
+ // TODO(sunyunjia): Plumb the velocity of the snap curve as well.
+ scroll_state_data->delta_x = delta.x();
+ scroll_state_data->delta_y = delta.y();
+ scroll_state_data->is_in_inertial_phase = true;
+ scroll_state_data->from_user_input = true;
+ scroll_state_data->delta_granularity =
+ static_cast<double>(ScrollGranularity::kScrollByPrecisePixel);
+ scroll_state_data->delta_consumed_for_scroll_sequence =
+ delta_consumed_for_scroll_sequence_;
+ ScrollState* scroll_state = ScrollState::Create(std::move(scroll_state_data));
+ scroll_state->SetCurrentNativeScrollingElement(
+ previous_gesture_scrolled_element_);
+
+ CustomizedScroll(*scroll_state);
+
+ ScrollableArea* scrollable_area = ScrollableAreaForSnapping();
+ FloatPoint end_position = scrollable_area->ScrollPosition();
+ return gfx::Vector2dF(end_position.X(), end_position.Y());
+}
+
+void ScrollManager::ScrollEndForSnapFling() {
+ std::unique_ptr<ScrollStateData> scroll_state_data =
+ std::make_unique<ScrollStateData>();
+ scroll_state_data->is_ending = true;
+ scroll_state_data->is_in_inertial_phase = true;
+ scroll_state_data->from_user_input = true;
+ scroll_state_data->delta_consumed_for_scroll_sequence =
+ delta_consumed_for_scroll_sequence_;
+ ScrollState* scroll_state = ScrollState::Create(std::move(scroll_state_data));
+ CustomizedScroll(*scroll_state);
+ NotifyScrollPhaseEndForCustomizedScroll();
+ ClearGestureScrollState();
+}
+
+void ScrollManager::RequestAnimationForSnapFling() {
+ if (Page* page = frame_->GetPage())
+ page->GetChromeClient().ScheduleAnimation(frame_->View());
+}
+
+void ScrollManager::AnimateSnapFling(base::TimeTicks monotonic_time) {
+ DCHECK(snap_fling_controller_);
+ snap_fling_controller_->Animate(monotonic_time);
+}
+
Page* ScrollManager::GetPage() const {
return frame_->GetPage();
}
@@ -646,11 +760,12 @@ WebInputEventResult ScrollManager::HandleGestureScrollEvent(
TRACE_EVENT_SCOPE_THREAD);
LocalFrameView* view = frame_->View();
- LayoutPoint view_point = view->RootFrameToContents(
+ LayoutPoint view_point = view->ConvertFromRootFrame(
FlooredIntPoint(gesture_event.PositionInRootFrame()));
HitTestRequest request(HitTestRequest::kReadOnly);
- HitTestResult result(request, view_point);
- document->GetLayoutView()->HitTest(result);
+ HitTestLocation location(view_point);
+ HitTestResult result(request, location);
+ document->GetLayoutView()->HitTest(location, result);
event_target = result.InnerNode();
@@ -695,6 +810,13 @@ WebInputEventResult ScrollManager::HandleGestureScrollEvent(
}
}
+ if (snap_fling_controller_) {
+ if (gesture_event.IsGestureScroll() &&
+ (snap_fling_controller_->FilterEventForSnap(
+ ToGestureScrollType(gesture_event.GetType())))) {
+ return WebInputEventResult::kNotHandled;
+ }
+ }
switch (gesture_event.GetType()) {
case WebInputEvent::kGestureScrollBegin:
return HandleGestureScrollBegin(gesture_event);
@@ -704,9 +826,6 @@ WebInputEventResult ScrollManager::HandleGestureScrollEvent(
return HandleGestureScrollEnd(gesture_event);
case WebInputEvent::kGestureFlingStart:
case WebInputEvent::kGestureFlingCancel:
- case WebInputEvent::kGesturePinchBegin:
- case WebInputEvent::kGesturePinchEnd:
- case WebInputEvent::kGesturePinchUpdate:
return WebInputEventResult::kNotHandled;
default:
NOTREACHED();
@@ -728,7 +847,7 @@ bool ScrollManager::HandleScrollGestureOnResizer(
PaintLayer* layer = event_target->GetLayoutObject()
? event_target->GetLayoutObject()->EnclosingLayer()
: nullptr;
- IntPoint p = frame_->View()->RootFrameToContents(
+ IntPoint p = frame_->View()->ConvertFromRootFrame(
FlooredIntPoint(gesture_event.PositionInRootFrame()));
if (layer && layer->GetScrollableArea() &&
layer->GetScrollableArea()->IsPointInResizeControl(p,
diff --git a/chromium/third_party/blink/renderer/core/input/scroll_manager.h b/chromium/third_party/blink/renderer/core/input/scroll_manager.h
index 3849f4988e9..72f0136a007 100644
--- a/chromium/third_party/blink/renderer/core/input/scroll_manager.h
+++ b/chromium/third_party/blink/renderer/core/input/scroll_manager.h
@@ -14,6 +14,7 @@
#include "third_party/blink/renderer/platform/geometry/layout_size.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/scroll/scroll_snap_data.h"
#include "third_party/blink/renderer/platform/scroll/scroll_types.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
@@ -26,6 +27,7 @@ class LocalFrame;
class PaintLayer;
class PaintLayerScrollableArea;
class Page;
+class ScrollableArea;
class Scrollbar;
class ScrollState;
class WebGestureEvent;
@@ -34,9 +36,11 @@ class WebGestureEvent;
// user action that causes scrolling or resizing is determined in other *Manager
// classes and they call into this class for doing the work.
class CORE_EXPORT ScrollManager
- : public GarbageCollectedFinalized<ScrollManager> {
+ : public GarbageCollectedFinalized<ScrollManager>,
+ public SnapFlingClient {
public:
explicit ScrollManager(LocalFrame&);
+ virtual ~ScrollManager() = default;
void Trace(blink::Visitor*);
void Clear();
@@ -90,6 +94,16 @@ class CORE_EXPORT ScrollManager
void ClearResizeScrollableArea(bool should_not_be_null);
void SetResizeScrollableArea(PaintLayer*, IntPoint);
+ // SnapFlingClient implementation.
+ bool GetSnapFlingInfo(const gfx::Vector2dF& natural_displacement,
+ gfx::Vector2dF* out_initial_offset,
+ gfx::Vector2dF* out_target_offset) const override;
+ gfx::Vector2dF ScrollByForSnapFling(const gfx::Vector2dF& delta) override;
+ void ScrollEndForSnapFling() override;
+ void RequestAnimationForSnapFling() override;
+
+ void AnimateSnapFling(base::TimeTicks monotonic_time);
+
private:
WebInputEventResult HandleGestureScrollUpdate(const WebGestureEvent&);
WebInputEventResult HandleGestureScrollBegin(const WebGestureEvent&);
@@ -125,6 +139,9 @@ class CORE_EXPORT ScrollManager
void NotifyScrollPhaseBeginForCustomizedScroll(const ScrollState&);
void NotifyScrollPhaseEndForCustomizedScroll();
+ LayoutBox* LayoutBoxForSnapping() const;
+ ScrollableArea* ScrollableAreaForSnapping() const;
+
// NOTE: If adding a new field to this class please ensure that it is
// cleared in |ScrollManager::clear()|.
@@ -159,6 +176,8 @@ class CORE_EXPORT ScrollManager
Member<PaintLayerScrollableArea> resize_scrollable_area_;
+ std::unique_ptr<SnapFlingController> snap_fling_controller_;
+
LayoutSize
offset_from_resize_corner_; // In the coords of m_resizeScrollableArea.
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 2b7f3f2569e..e0b7f9c0d4f 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
@@ -21,8 +21,12 @@ class ScrollSnapTest : public SimTest {
// the pointer/finger's location on touch screen.
void GestureScroll(double x, double y, double delta_x, double delta_y);
void ScrollBegin(double x, double y, double hint_x, double hint_y);
- void ScrollUpdate(double x, double y, double delta_x, double delta_y);
- void ScrollEnd(double x, double y);
+ void ScrollUpdate(double x,
+ double y,
+ double delta_x,
+ double delta_y,
+ bool is_in_inertial_phase = false);
+ void ScrollEnd(double x, double y, bool is_in_inertial_phase = false);
void SetInitialScrollOffset(double x, double y);
};
@@ -99,7 +103,8 @@ void ScrollSnapTest::ScrollBegin(double x,
void ScrollSnapTest::ScrollUpdate(double x,
double y,
double delta_x,
- double delta_y) {
+ double delta_y,
+ bool is_in_inertial_phase) {
WebGestureEvent event(WebInputEvent::kGestureScrollUpdate,
WebInputEvent::kNoModifiers, CurrentTimeTicks(),
WebGestureDevice::kWebGestureDeviceTouchscreen);
@@ -107,16 +112,23 @@ void ScrollSnapTest::ScrollUpdate(double x,
event.SetPositionInScreen(WebFloatPoint(x, y));
event.data.scroll_update.delta_x = delta_x;
event.data.scroll_update.delta_y = delta_y;
+ if (is_in_inertial_phase) {
+ event.data.scroll_update.inertial_phase = WebGestureEvent::kMomentumPhase;
+ event.SetTimeStamp(base::TimeTicks());
+ }
event.SetFrameScale(1);
GetDocument().GetFrame()->GetEventHandler().HandleGestureScrollEvent(event);
}
-void ScrollSnapTest::ScrollEnd(double x, double y) {
+void ScrollSnapTest::ScrollEnd(double x, double y, bool is_in_inertial_phase) {
WebGestureEvent event(WebInputEvent::kGestureScrollEnd,
WebInputEvent::kNoModifiers, CurrentTimeTicks(),
WebGestureDevice::kWebGestureDeviceTouchscreen);
event.SetPositionInWidget(WebFloatPoint(x, y));
event.SetPositionInScreen(WebFloatPoint(x, y));
+ event.data.scroll_end.inertial_phase =
+ is_in_inertial_phase ? WebGestureEvent::kMomentumPhase
+ : WebGestureEvent::kNonMomentumPhase;
GetDocument().GetFrame()->GetEventHandler().HandleGestureScrollEvent(event);
}
@@ -163,6 +175,33 @@ TEST_F(ScrollSnapTest, ScrollSnapOnBoth) {
ASSERT_EQ(scroller->scrollTop(), 200);
}
+TEST_F(ScrollSnapTest, AnimateFlingToArriveAtSnapPoint) {
+ SetUpForDiv();
+ // Vertically align with the area.
+ SetInitialScrollOffset(0, 200);
+ Element* scroller = GetDocument().getElementById("scroller");
+ ASSERT_EQ(scroller->scrollLeft(), 0);
+ ASSERT_EQ(scroller->scrollTop(), 200);
+
+ ScrollBegin(100, 100, -5, 0);
+ // Starts with a non-inertial GSU.
+ ScrollUpdate(100, 100, -5, 0);
+ // Fling with an inertial GSU.
+ ScrollUpdate(95, 100, -5, 0, true);
+ ScrollEnd(90, 100);
+ Compositor().BeginFrame();
+ // Animate halfway through the fling.
+ Compositor().BeginFrame(0.2);
+ ASSERT_GT(scroller->scrollLeft(), 150);
+ ASSERT_LT(scroller->scrollLeft(), 180);
+ ASSERT_EQ(scroller->scrollTop(), 200);
+ // Finish the animation.
+ Compositor().BeginFrame(0.6);
+
+ ASSERT_EQ(scroller->scrollLeft(), 200);
+ ASSERT_EQ(scroller->scrollTop(), 200);
+}
+
TEST_F(ScrollSnapTest, SnapWhenBodyViewportDefining) {
v8::HandleScope HandleScope(v8::Isolate::GetCurrent());
WebView().Resize(WebSize(300, 300));
diff --git a/chromium/third_party/blink/renderer/core/input/touch.cc b/chromium/third_party/blink/renderer/core/input/touch.cc
index fe43d26da95..3cc4da79099 100644
--- a/chromium/third_party/blink/renderer/core/input/touch.cc
+++ b/chromium/third_party/blink/renderer/core/input/touch.cc
@@ -27,6 +27,7 @@
#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/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
namespace blink {
@@ -40,15 +41,14 @@ FloatPoint ContentsOffset(LocalFrame* frame) {
if (!frame_view)
return FloatPoint();
float scale = 1.0f / frame->PageZoomFactor();
- return FloatPoint(
- frame_view->LayoutViewportScrollableArea()->GetScrollOffset())
+ return FloatPoint(frame_view->LayoutViewport()->GetScrollOffset())
.ScaledBy(scale);
}
LayoutPoint PageToAbsolute(LocalFrame* frame, const FloatPoint& page_pos) {
FloatPoint converted_point;
if (frame && frame->View())
- converted_point = frame->View()->DocumentToAbsolute(page_pos);
+ converted_point = frame->View()->DocumentToFrame(page_pos);
else
converted_point = page_pos;
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 bc7068854d5..632763a1d21 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
@@ -55,7 +55,7 @@
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
#include "third_party/blink/renderer/core/layout/layout_tree_as_text.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
-#include "third_party/blink/renderer/platform/graphics/touch_action.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
@@ -212,16 +212,14 @@ WebViewImpl* TouchActionTest::SetupTest(
const int kScrollOffset = 100;
Document* document =
static_cast<Document*>(web_view->MainFrameImpl()->GetDocument());
- document->GetFrame()->View()->LayoutViewportScrollableArea()->SetScrollOffset(
+ document->GetFrame()->View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0, kScrollOffset), kProgrammaticScroll);
return web_view;
}
IntRect WindowClipRect(const LocalFrameView& frame_view) {
- LayoutRect clip_rect(
- LayoutPoint(),
- LayoutSize(frame_view.VisibleContentSize(kExcludeScrollbars)));
+ LayoutRect clip_rect(LayoutPoint(), LayoutSize(frame_view.Size()));
frame_view.GetLayoutView()->MapToVisualRectInAncestorSpace(
&frame_view.GetLayoutView()->ContainerForPaintInvalidation(), clip_rect,
0, kDefaultVisualRectFlags);
@@ -314,9 +312,10 @@ void TouchActionTest::RunTestOnTree(
// element we intended. This is the easiest way for a test to be broken,
// but has nothing really to do with touch action. Note that we can't use
// WebView's hit test API because it doesn't look into shadow DOM.
- IntPoint doc_point(main_frame_view->FrameToContents(window_point));
- HitTestResult result = main_frame->GetEventHandler().HitTestResultAtPoint(
- doc_point, HitTestRequest::kReadOnly | HitTestRequest::kActive);
+ HitTestLocation location(window_point);
+ HitTestResult result =
+ main_frame->GetEventHandler().HitTestResultAtLocation(
+ location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
ASSERT_EQ(element, result.InnerElement())
<< "Unexpected hit test result " << failure_context_pos
<< " Got element: \""
@@ -336,36 +335,32 @@ void TouchActionTest::RunTestOnTree(
SendTouchEvent(web_view, WebInputEvent::kPointerDown, window_point);
AtomicString expected_action = element->getAttribute("expected-action");
- if (expected_action == "auto") {
- // Auto is the default - no action set.
- EXPECT_EQ(0, client.TouchActionSetCount()) << failure_context_pos;
- EXPECT_EQ(TouchAction::kTouchActionAuto, client.LastTouchAction())
- << failure_context_pos;
- } else {
- // Should have received exactly one touch action.
- EXPECT_EQ(1, client.TouchActionSetCount()) << failure_context_pos;
- if (client.TouchActionSetCount()) {
- if (expected_action == "none") {
- EXPECT_EQ(TouchAction::kTouchActionNone, client.LastTouchAction())
- << failure_context_pos;
- } else if (expected_action == "pan-x") {
- EXPECT_EQ(TouchAction::kTouchActionPanX, client.LastTouchAction())
- << failure_context_pos;
- } else if (expected_action == "pan-y") {
- EXPECT_EQ(TouchAction::kTouchActionPanY, client.LastTouchAction())
- << failure_context_pos;
- } else if (expected_action == "pan-x-y") {
- EXPECT_EQ((TouchAction::kTouchActionPan), client.LastTouchAction())
- << failure_context_pos;
- } else if (expected_action == "manipulation") {
- EXPECT_EQ((TouchAction::kTouchActionManipulation),
- client.LastTouchAction())
- << failure_context_pos;
- } else {
- FAIL() << "Unrecognized expected-action \""
- << expected_action.Ascii().data() << "\" "
- << failure_context_pos;
- }
+ // Should have received exactly one touch action, even for auto.
+ EXPECT_EQ(1, client.TouchActionSetCount()) << failure_context_pos;
+ if (client.TouchActionSetCount()) {
+ if (expected_action == "auto") {
+ EXPECT_EQ(TouchAction::kTouchActionAuto, client.LastTouchAction())
+ << failure_context_pos;
+ } else if (expected_action == "none") {
+ EXPECT_EQ(TouchAction::kTouchActionNone, client.LastTouchAction())
+ << failure_context_pos;
+ } else if (expected_action == "pan-x") {
+ EXPECT_EQ(TouchAction::kTouchActionPanX, client.LastTouchAction())
+ << failure_context_pos;
+ } else if (expected_action == "pan-y") {
+ EXPECT_EQ(TouchAction::kTouchActionPanY, client.LastTouchAction())
+ << failure_context_pos;
+ } else if (expected_action == "pan-x-y") {
+ EXPECT_EQ((TouchAction::kTouchActionPan), client.LastTouchAction())
+ << failure_context_pos;
+ } else if (expected_action == "manipulation") {
+ EXPECT_EQ((TouchAction::kTouchActionManipulation),
+ client.LastTouchAction())
+ << failure_context_pos;
+ } else {
+ FAIL() << "Unrecognized expected-action \""
+ << expected_action.Ascii().data() << "\" "
+ << failure_context_pos;
}
}
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 ac14892e048..adc2e8d8a92 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
@@ -20,12 +20,34 @@
#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/histogram.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink {
namespace {
+// Returns true if there are event listeners of |handler_class| on |touch_node|
+// or any of its ancestors inside the document (including DOMWindow).
+bool HasEventHandlerInAncestorPath(
+ Node* touch_node,
+ EventHandlerRegistry::EventHandlerClass handler_class) {
+ Document& document = touch_node->GetDocument();
+ const EventTargetSet* event_target_set =
+ document.GetFrame()->GetEventHandlerRegistry().EventHandlerTargets(
+ handler_class);
+
+ if (event_target_set->Contains(document.domWindow()))
+ return true;
+
+ for (Node& ancestor : NodeTraversal::InclusiveAncestorsOf(*touch_node)) {
+ if (event_target_set->Contains(&ancestor))
+ return true;
+ }
+
+ return false;
+}
+
bool HasTouchHandlers(const EventHandlerRegistry& registry) {
return registry.HasEventHandlers(
EventHandlerRegistry::kTouchStartOrMoveEventBlocking) ||
@@ -464,6 +486,9 @@ TouchEventManager::DispatchTouchEventFromAccumulatdTouchPoints() {
}
}
+ if (should_enforce_vertical_scroll_)
+ event_result = EnsureVerticalScrollIsPossible(event_result);
+
// Suppress following touchmoves within the slop region if the touchstart is
// not consumed.
if (all_touch_points_pressed &&
@@ -507,11 +532,11 @@ void TouchEventManager::UpdateTouchAttributeMapsForPointerDown(
if (touch_sequence_document_ &&
(!touch_node || &touch_node->GetDocument() != touch_sequence_document_)) {
if (touch_sequence_document_->GetFrame()) {
- LayoutPoint frame_point = LayoutPoint(
- touch_sequence_document_->GetFrame()->View()->RootFrameToContents(
- event.PositionInWidget()));
+ HitTestLocation location(LayoutPoint(
+ touch_sequence_document_->GetFrame()->View()->ConvertFromRootFrame(
+ event.PositionInWidget())));
result = EventHandlingUtil::HitTestResultInFrame(
- touch_sequence_document_->GetFrame(), frame_point, hit_type);
+ touch_sequence_document_->GetFrame(), location, hit_type);
Node* node = result.InnerNode();
if (!node)
return;
@@ -547,14 +572,23 @@ void TouchEventManager::UpdateTouchAttributeMapsForPointerDown(
TouchAction effective_touch_action =
TouchActionUtil::ComputeEffectiveTouchAction(*touch_node);
- if (effective_touch_action != TouchAction::kTouchActionAuto) {
+
+ should_enforce_vertical_scroll_ =
+ touch_sequence_document_->IsVerticalScrollEnforced();
+ if (should_enforce_vertical_scroll_ &&
+ HasEventHandlerInAncestorPath(
+ touch_node, EventHandlerRegistry::kTouchStartOrMoveEventBlocking)) {
+ delayed_effective_touch_action_ = delayed_effective_touch_action_.value_or(
+ TouchAction::kTouchActionAuto) &
+ effective_touch_action;
+ }
+ if (!delayed_effective_touch_action_) {
frame_->GetPage()->GetChromeClient().SetTouchAction(frame_,
effective_touch_action);
-
- // Combine the current touch action sequence with the touch action
- // for the current finger press.
- current_touch_action_ &= effective_touch_action;
}
+ // Combine the current touch action sequence with the touch action
+ // for the current finger press.
+ current_touch_action_ &= effective_touch_action;
}
void TouchEventManager::HandleTouchPoint(
@@ -648,10 +682,44 @@ void TouchEventManager::AllTouchesReleasedCleanup() {
touch_sequence_document_.Clear();
current_touch_action_ = TouchAction::kTouchActionAuto;
last_coalesced_touch_event_ = WebTouchEvent();
+ // Ideally, we should have DCHECK(!delayed_effective_touch_action_) but we do
+ // we do actually get here from HandleTouchPoint(). Supposedly, if there has
+ // been a |touch_sequence_document_| and nothing in the |touch_attribute_map_|
+ // we still get here and if |touch_sequence_document| was of the type which
+ // cannot block scroll, then the flag is certainly set
+ // (https://crbug.com/345372).
+ delayed_effective_touch_action_ = base::nullopt;
+ should_enforce_vertical_scroll_ = false;
}
bool TouchEventManager::IsAnyTouchActive() const {
return !touch_attribute_map_.IsEmpty();
}
+WebInputEventResult TouchEventManager::EnsureVerticalScrollIsPossible(
+ WebInputEventResult event_result) {
+ bool prevent_defaulted =
+ event_result == WebInputEventResult::kHandledApplication;
+ if (prevent_defaulted && delayed_effective_touch_action_) {
+ // Make sure that only vertical scrolling is permitted.
+ *delayed_effective_touch_action_ &= TouchAction::kTouchActionPanY;
+ }
+
+ if (delayed_effective_touch_action_) {
+ // If 'touchstart' is preventDefault()-ed then we can proceed with reporting
+ // the effective 'touch-action'.
+ // TODO(ekaramad): This does not block horizontal scroll after enforcing
+ // vertical scrolling. We should ideally send the 'touch-action' to browser
+ // after the first 'touchmove' event has been dispatched.
+ // (https://crbug.com/844493).
+ frame_->GetPage()->GetChromeClient().SetTouchAction(
+ frame_, delayed_effective_touch_action_.value());
+ delayed_effective_touch_action_ = base::nullopt;
+ }
+
+ // If the event was canceled the result is ignored to make sure vertical
+ // scrolling is possible.
+ return prevent_defaulted ? WebInputEventResult::kNotHandled : event_result;
+}
+
} // namespace blink
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 ed3d1b31303..60357035711 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
@@ -22,6 +22,7 @@ namespace blink {
class LocalFrame;
class Document;
+class Touch;
// This class takes care of dispatching all touch events and
// maintaining related states.
@@ -84,6 +85,9 @@ class CORE_EXPORT TouchEventManager
// accumulating all move events or by discrete events pointerdown/up/cancel.
WebInputEventResult DispatchTouchEventFromAccumulatdTouchPoints();
+ // Used only if |should_enforce_vertical_scroll_| is set.
+ WebInputEventResult EnsureVerticalScrollIsPossible(WebInputEventResult);
+
// NOTE: If adding a new field to this class please ensure that it is
// cleared in |TouchEventManager::clear()|.
@@ -111,6 +115,26 @@ class CORE_EXPORT TouchEventManager
// a union of all touches. Reset when all touches are released.
TouchAction current_touch_action_;
+ // TODO(ekaramad): Send the update after 'touchmove' to make sure we are only
+ // enforcing vertical scroll.
+ // When true, the current touch sequence should be handled such that vertical
+ // scrolling is always possible. To this end, the output of event handlers for
+ // 'touchstart' and 'touchmove' is overwritten to not handled so that
+ // scrolling cannot be blocked. However, to ensure only vertical scrolling is
+ // possible, the update for effective 'touch-action' is postponed to after
+ // handling 'touchstart' handlers and potentially overwritten to 'pan-y' so
+ // that only horizontal scrolling is blocked.
+ bool should_enforce_vertical_scroll_ = false;
+ // When set to a value, the effective touch-action is sent to the browser
+ // after all 'touchstart' handlers have been invoked. This is used by feature
+ // policy to enforce specific directions of scroll in spite of scroll-blocking
+ // events being prevent defaulted. When multiple pointer down events occur
+ // during the same touch sequence, the value of effective touch action which
+ // is sent to the browser after handling each dispatched 'touchstart' is the
+ // intersection of all the previously calculated effective touch action values
+ // during the sequence.
+ base::Optional<TouchAction> delayed_effective_touch_action_;
+
DISALLOW_COPY_AND_ASSIGN(TouchEventManager);
};
diff --git a/chromium/third_party/blink/renderer/core/inspector/README.md b/chromium/third_party/blink/renderer/core/inspector/README.md
new file mode 100644
index 00000000000..e0315182b14
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/inspector/README.md
@@ -0,0 +1,3 @@
+# Chrome DevTools Protocol
+
+Contributing to Chrome DevTools Protocol: [docs.google.com](https://docs.google.com/document/d/1c-COD2kaK__5iMM5SEx-PzNA7HFmgttcYfOHHX0HaOM/edit?usp=sharing).
diff --git a/chromium/third_party/blink/renderer/core/inspector/browser_protocol.pdl b/chromium/third_party/blink/renderer/core/inspector/browser_protocol.pdl
index 12175433d43..b374349b8a4 100644
--- a/chromium/third_party/blink/renderer/core/inspector/browser_protocol.pdl
+++ b/chromium/third_party/blink/renderer/core/inspector/browser_protocol.pdl
@@ -1,6 +1,8 @@
# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+#
+# Contribuging to Chrome DevTools Protocol: https://docs.google.com/document/d/1c-COD2kaK__5iMM5SEx-PzNA7HFmgttcYfOHHX0HaOM/edit?usp=sharing
version
major 1
@@ -531,6 +533,9 @@ domain Browser
# substring in their name are extracted. An empty or absent query returns
# all histograms.
optional string query
+ # If true, retrieve delta since last call.
+ optional boolean delta
+
returns
# Histograms.
array of Histogram histograms
@@ -540,6 +545,8 @@ domain Browser
parameters
# Requested histogram name.
string name
+ # If true, retrieve delta since last call.
+ optional boolean delta
returns
# Histogram.
Histogram histogram
@@ -1442,6 +1449,20 @@ domain DOM
# Box model for the node.
BoxModel model
+ # Returns quads that describe node position on the page. This method
+ # might return multiple quads for inline nodes.
+ experimental command getContentQuads
+ parameters
+ # Identifier of the node.
+ optional NodeId nodeId
+ # Identifier of the backend node.
+ optional BackendNodeId backendNodeId
+ # JavaScript object id of the node wrapper.
+ optional Runtime.RemoteObjectId objectId
+ returns
+ # Quads that describe node layout relative to viewport.
+ array of Quad quads
+
# Returns the root DOM node (and optionally the subtree) to the caller.
command getDocument
parameters
@@ -2010,12 +2031,6 @@ experimental domain DOMSnapshot
# The index of a frame owner element's content document in the `domNodes` array returned by
# `getSnapshot`, if any.
optional integer contentDocumentIndex
- # Index of the imported document's node of a link element in the `domNodes` array returned by
- # `getSnapshot`, if any.
- optional integer importedDocumentIndex
- # Index of the content node of a template element in the `domNodes` array returned by
- # `getSnapshot`.
- optional integer templateContentIndex
# Type of a pseudo element node.
optional DOM.PseudoType pseudoType
# Shadow root type.
@@ -2076,6 +2091,116 @@ experimental domain DOMSnapshot
# Attribute/property value.
string value
+ # Index of the string in the strings table.
+ type StringIndex extends integer
+
+ # Index of the string in the strings table.
+ type ArrayOfStrings extends array of StringIndex
+
+ # Data that is only present on rare nodes.
+ type RareStringData extends object
+ properties
+ array of integer index
+ array of StringIndex value
+
+ type RareBooleanData extends object
+ properties
+ array of integer index
+
+ type RareIntegerData extends object
+ properties
+ array of integer index
+ array of integer value
+
+ type Rectangle extends array of number
+
+ # Document snapshot.
+ type DocumentSnapshot extends object
+ properties
+ # Document URL that `Document` or `FrameOwner` node points to.
+ StringIndex documentURL
+ # Base URL that `Document` or `FrameOwner` node uses for URL completion.
+ StringIndex baseURL
+ # Contains the document's content language.
+ StringIndex contentLanguage
+ # Contains the document's character set encoding.
+ StringIndex encodingName
+ # `DocumentType` node's publicId.
+ StringIndex publicId
+ # `DocumentType` node's systemId.
+ StringIndex systemId
+ # Frame ID for frame owner elements and also for the document node.
+ StringIndex frameId
+ # A table with dom nodes.
+ NodeTreeSnapshot nodes
+ # The nodes in the layout tree.
+ LayoutTreeSnapshot layout
+ # The post-layout inline text nodes.
+ TextBoxSnapshot textBoxes
+
+ # Table containing nodes.
+ type NodeTreeSnapshot extends object
+ properties
+ # Parent node index.
+ optional array of integer parentIndex
+ # `Node`'s nodeType.
+ optional array of integer nodeType
+ # `Node`'s nodeName.
+ optional array of StringIndex nodeName
+ # `Node`'s nodeValue.
+ optional array of StringIndex nodeValue
+ # `Node`'s id, corresponds to DOM.Node.backendNodeId.
+ optional array of DOM.BackendNodeId backendNodeId
+ # Attributes of an `Element` node. Flatten name, value pairs.
+ optional array of ArrayOfStrings attributes
+ # Only set for textarea elements, contains the text value.
+ optional RareStringData textValue
+ # Only set for input elements, contains the input's associated text value.
+ optional RareStringData inputValue
+ # Only set for radio and checkbox input elements, indicates if the element has been checked
+ optional RareBooleanData inputChecked
+ # Only set for option elements, indicates if the element has been selected
+ optional RareBooleanData optionSelected
+ # The index of the document in the list of the snapshot documents.
+ optional RareIntegerData contentDocumentIndex
+ # Type of a pseudo element node.
+ optional RareStringData pseudoType
+ # Whether this DOM node responds to mouse clicks. This includes nodes that have had click
+ # event listeners attached via JavaScript as well as anchor tags that naturally navigate when
+ # clicked.
+ optional RareBooleanData isClickable
+ # The selected url for nodes with a srcset attribute.
+ optional RareStringData currentSourceURL
+ # The url of the script (if any) that generates this node.
+ optional RareStringData originURL
+
+ # Details of an element in the DOM tree with a LayoutObject.
+ type LayoutTreeSnapshot extends object
+ properties
+ # The index of the related DOM node in the `domNodes` array returned by `getSnapshot`.
+ array of integer nodeIndex
+ # Index into the `computedStyles` array returned by `captureSnapshot`.
+ array of ArrayOfStrings styles
+ # The absolute position bounding box.
+ array of Rectangle bounds
+ # Contents of the LayoutText, if any.
+ array of StringIndex text
+
+ # Details of post layout rendered text positions. The exact layout should not be regarded as
+ # stable and may change between versions.
+ type TextBoxSnapshot extends object
+ properties
+ # Intex of th elayout tree node that owns this box collection.
+ array of integer layoutIndex
+ # The absolute position bounding box.
+ array of Rectangle bounds
+ # The starting index in characters, for this post layout textbox substring. Characters that
+ # would be represented as a surrogate pair in UTF-16 have length 2.
+ array of integer start
+ # The number of characters in this post layout textbox substring. Characters that would be
+ # represented as a surrogate pair in UTF-16 have length 2.
+ array of integer length
+
# Disables DOM snapshot agent for the given page.
command disable
@@ -2086,7 +2211,7 @@ experimental domain DOMSnapshot
# template contents, and imported documents) in a flattened array, as well as layout and
# white-listed computed style information for the nodes. Shadow DOM in the returned DOM tree is
# flattened.
- command getSnapshot
+ deprecated command getSnapshot
parameters
# Whitelist of computed styles to return.
array of string computedStyleWhitelist
@@ -2104,6 +2229,20 @@ experimental domain DOMSnapshot
# Whitelisted ComputedStyle properties for each node in the layout tree.
array of ComputedStyle computedStyles
+ # Returns a document snapshot, including the full DOM tree of the root node (including iframes,
+ # template contents, and imported documents) in a flattened array, as well as layout and
+ # white-listed computed style information for the nodes. Shadow DOM in the returned DOM tree is
+ # flattened.
+ command captureSnapshot
+ parameters
+ # Whitelist of computed styles to return.
+ array of string computedStyles
+ returns
+ # The nodes in the DOM tree. The DOMNode at index 0 corresponds to the root document.
+ array of DocumentSnapshot documents
+ # Shared string table that all string properties refer to with indexes.
+ array of string strings
+
# Query and modify DOM storage.
experimental domain DOMStorage
@@ -2321,6 +2460,16 @@ domain Emulation
# change is not observed by the page, e.g. viewport-relative elements do not change positions.
experimental optional Page.Viewport viewport
+ experimental command setScrollbarsHidden
+ parameters
+ # Whether scrollbars should be always hidden.
+ boolean hidden
+
+ experimental command setDocumentCookieDisabled
+ parameters
+ # Whether document.coookie API should be disabled.
+ boolean disabled
+
experimental command setEmitTouchEventsForMouse
parameters
# Whether touch emulation based on mouse input should be enabled.
@@ -2348,7 +2497,7 @@ domain Emulation
optional number accuracy
# Overrides value returned by the javascript navigator object.
- experimental command setNavigatorOverrides
+ experimental deprecated command setNavigatorOverrides
parameters
# The platform navigator.platform should return.
string platform
@@ -2420,6 +2569,16 @@ domain Emulation
# enabled.
number virtualTimeElapsed
+ # Allows overriding user agent with the given string.
+ command setUserAgentOverride
+ parameters
+ # User agent to use.
+ string userAgent
+ # Browser langugage to emulate.
+ optional string acceptLanguage
+ # The platform navigator.platform should return.
+ optional string platform
+
# This domain provides experimental commands only supported in headless mode.
experimental domain HeadlessExperimental
depends on Page
@@ -3361,8 +3520,10 @@ domain Network
# HTTP request data.
type Request extends object
properties
- # Request URL.
+ # Request URL (without fragment).
string url
+ # Fragment of the requested URL starting with hash, if present.
+ optional string urlFragment
# HTTP request method.
string method
# HTTP request headers.
@@ -3455,6 +3616,7 @@ domain Network
inspector
subresource-filter
content-type
+ collapsed-by-client
# HTTP response data.
type Response extends object
@@ -3662,16 +3824,22 @@ domain Network
properties
# Signed exchange signature label.
string label
+ # The hex string of signed exchange signature.
+ string signature
# Signed exchange signature integrity.
string integrity
# Signed exchange signature cert Url.
- string certUrl
+ optional string certUrl
+ # The hex string of signed exchange signature cert sha256.
+ optional string certSha256
# Signed exchange signature validity Url.
string validityUrl
# Signed exchange signature date.
integer date
# Signed exchange signature expires.
integer expires
+ # The encoded certificates.
+ optional array of string certificates
# Information about a signed exchange header.
# https://wicg.github.io/webpackage/draft-yasskin-httpbis-origin-signed-exchanges-impl.html#cbor-representation
@@ -3688,6 +3856,26 @@ domain Network
# Signed exchange response signature.
array of SignedExchangeSignature signatures
+ # Field type for a signed exchange related error.
+ experimental type SignedExchangeErrorField extends string
+ enum
+ signatureSig
+ signatureIntegrity
+ signatureCertUrl
+ signatureCertSha256
+ signatureValidityUrl
+ signatureTimestamps
+
+ # Information about a signed exchange response.
+ experimental type SignedExchangeError extends object
+ properties
+ # Error message.
+ string message
+ # The index of the signature which caused the error.
+ optional integer signatureIndex
+ # The field which caused the error.
+ optional SignedExchangeErrorField errorField
+
# Information about a signed exchange response.
experimental type SignedExchangeInfo extends object
properties
@@ -3698,7 +3886,7 @@ domain Network
# Security details for the signed exchange header.
optional SecurityDetails securityDetails
# Errors occurred while handling the signed exchagne.
- optional array of string errors
+ optional array of SignedExchangeError errors
# Tells whether clearing browser cache is supported.
deprecated command canClearBrowserCache
@@ -3954,9 +4142,14 @@ domain Network
# Allows overriding user agent with the given string.
command setUserAgentOverride
+ redirect Emulation
parameters
# User agent to use.
string userAgent
+ # Browser langugage to emulate.
+ optional string acceptLanguage
+ # The platform navigator.platform should return.
+ optional string platform
# Fired when data chunk was received over the network.
event dataReceived
@@ -4009,8 +4202,9 @@ domain Network
MonotonicTime timestamp
# Total number of bytes received for this request.
number encodedDataLength
- # Set when response was blocked due to being cross-site document response.
- optional boolean blockedCrossSiteDocument
+ # Set when 1) response was blocked by Cross-Origin Read Blocking and also
+ # 2) this needs to be reported to the DevTools console.
+ optional boolean shouldReportCorbBlocking
# Details of an intercepted HTTP request, which must be either allowed, blocked, modified or
# mocked.
@@ -4379,6 +4573,8 @@ domain Page
WebSocket
Manifest
SignedExchange
+ Ping
+ CSPViolationReport
Other
# Unique frame identifier.
@@ -4555,6 +4751,32 @@ domain Page
# Page scale factor.
number scale
+ # Generic font families collection.
+ experimental type FontFamilies extends object
+ properties
+ # The standard font-family.
+ optional string standard
+ # The fixed font-family.
+ optional string fixed
+ # The serif font-family.
+ optional string serif
+ # The sansSerif font-family.
+ optional string sansSerif
+ # The cursive font-family.
+ optional string cursive
+ # The fantasy font-family.
+ optional string fantasy
+ # The pictograph font-family.
+ optional string pictograph
+
+ # Default font sizes.
+ experimental type FontSizes extends object
+ properties
+ # Default standard font size.
+ optional integer standard
+ # Default fixed font size.
+ optional integer fixed
+
# Deprecated, please use addScriptToEvaluateOnNewDocument instead.
experimental deprecated command addScriptToEvaluateOnLoad
parameters
@@ -4879,6 +5101,18 @@ domain Page
# Mock gamma
number gamma
+ # Set generic font families.
+ experimental command setFontFamilies
+ parameters
+ # Specifies font families to set. If a font family is not specified, it won't be changed.
+ FontFamilies fontFamilies
+
+ # Set default font sizes.
+ experimental command setFontSizes
+ parameters
+ # Specifies font sizes to set. If a font size is not specified, it won't be changed.
+ FontSizes fontSizes
+
# Sets given markup as the document's HTML.
command setDocumentContent
parameters
@@ -4968,6 +5202,22 @@ domain Page
# Stops sending each frame in the `screencastFrame`.
experimental command stopScreencast
+ # Forces compilation cache to be generated for every subresource script.
+ experimental command setProduceCompilationCache
+ parameters
+ boolean enabled
+
+ # Seeds compilation cache for given url. Compilation cache does not survive
+ # cross-process navigation.
+ experimental command addCompilationCache
+ parameters
+ string url
+ # Base64-encoded data
+ string data
+
+ # Clears seeded compilation cache.
+ experimental command clearCompilationCache
+
event domContentEventFired
parameters
Network.MonotonicTime timestamp
@@ -5117,6 +5367,15 @@ domain Page
# Whether or not it was triggered by user gesture.
boolean userGesture
+ # Issued for every compilation cache generated. Is only available
+ # if Page.setGenerateCompilationCache is enabled.
+ experimental event compilationCacheProduced
+ parameters
+ string url
+ # Base64-encoded data
+ string data
+
+
domain Performance
# Run-time execution metric.
@@ -5556,6 +5815,14 @@ domain Target
command attachToTarget
parameters
TargetID targetId
+ # Enables "flat" access to the session via specifying sessionId attribute in the commands.
+ experimental optional boolean flatten
+ returns
+ # Id assigned to the session.
+ SessionID sessionId
+
+ # Attaches to the browser target, only uses flat sessionId mode.
+ experimental command attachToBrowserTarget
returns
# Id assigned to the session.
SessionID sessionId
@@ -5567,6 +5834,20 @@ domain Target
returns
boolean success
+ # Inject object to the target's main frame that provides a communication
+ # channel with browser target.
+ #
+ # Injected object will be available as `window[bindingName]`.
+ #
+ # The object has the follwing API:
+ # - `binding.send(json)` - a method to send messages over the remote debugging protocol
+ # - `binding.onmessage = json => handleMessage(json)` - a callback that will be called for the protocol notifications and command responses.
+ experimental command exposeDevToolsProtocol
+ parameters
+ TargetID targetId
+ # Binding name, 'cdp' if not specified.
+ optional string bindingName
+
# Creates a new empty BrowserContext. Similar to an incognito profile but you can have more than
# one.
experimental command createBrowserContext
@@ -5615,7 +5896,7 @@ domain Target
# Returns information about a target.
experimental command getTargetInfo
parameters
- TargetID targetId
+ optional TargetID targetId
returns
TargetInfo targetInfo
@@ -5696,6 +5977,15 @@ domain Target
parameters
TargetID targetId
+ # Issued when a target has crashed.
+ event targetCrashed
+ parameters
+ TargetID targetId
+ # Termination status type.
+ string status
+ # Termination error code.
+ integer errorCode
+
# Issued when some information about a target has changed. This only happens between
# `targetCreated` and `targetDestroyed`.
event targetInfoChanged
diff --git a/chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.cc b/chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.cc
index 97f6740eb24..77d1fd86d81 100644
--- a/chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.cc
@@ -100,7 +100,13 @@ DevToolsEmulator::DevToolsEmulator(WebViewImpl* web_view)
original_max_touch_points_(0),
embedder_script_enabled_(
web_view->GetPage()->GetSettings().GetScriptEnabled()),
- script_execution_disabled_(false) {}
+ script_execution_disabled_(false),
+ embedder_hide_scrollbars_(
+ web_view->GetPage()->GetSettings().GetHideScrollbars()),
+ scrollbars_hidden_(false),
+ embedder_cookie_enabled_(
+ web_view->GetPage()->GetSettings().GetCookieEnabled()),
+ document_cookie_disabled_(false) {}
DevToolsEmulator::~DevToolsEmulator() = default;
@@ -163,6 +169,18 @@ void DevToolsEmulator::SetScriptEnabled(bool enabled) {
web_view_->GetPage()->GetSettings().SetScriptEnabled(enabled);
}
+void DevToolsEmulator::SetHideScrollbars(bool hide) {
+ embedder_hide_scrollbars_ = hide;
+ if (!scrollbars_hidden_)
+ web_view_->GetPage()->GetSettings().SetHideScrollbars(hide);
+}
+
+void DevToolsEmulator::SetCookieEnabled(bool enabled) {
+ embedder_cookie_enabled_ = enabled;
+ if (!document_cookie_disabled_)
+ web_view_->GetPage()->GetSettings().SetCookieEnabled(enabled);
+}
+
void DevToolsEmulator::SetDoubleTapToZoomEnabled(bool enabled) {
double_tap_to_zoom_enabled_ = enabled;
}
@@ -457,7 +475,8 @@ base::Optional<IntRect> DevToolsEmulator::VisibleContentRectForPainting()
const {
if (!viewport_override_)
return base::nullopt;
- FloatSize viewport_size(web_view_->LayerTreeView()->GetViewportSize());
+ FloatSize viewport_size(
+ IntSize(web_view_->LayerTreeView()->GetViewportSize()));
viewport_size.Scale(1. / CompositorDeviceScaleFactor());
viewport_size.Scale(1. / viewport_override_->scale);
return EnclosingIntRect(
@@ -501,48 +520,20 @@ void DevToolsEmulator::SetScriptExecutionDisabled(
script_execution_disabled_ ? false : embedder_script_enabled_);
}
-bool DevToolsEmulator::HandleInputEvent(const WebInputEvent& input_event) {
- Page* page = web_view_->GetPage();
- if (!page)
- return false;
-
- if (!touch_event_emulation_enabled_ ||
- !WebInputEvent::IsPinchGestureEventType(input_event.GetType())) {
- return false;
- }
+void DevToolsEmulator::SetScrollbarsHidden(bool hidden) {
+ if (scrollbars_hidden_ == hidden)
+ return;
+ scrollbars_hidden_ = hidden;
+ web_view_->GetPage()->GetSettings().SetHideScrollbars(
+ scrollbars_hidden_ ? true : embedder_hide_scrollbars_);
+}
- // FIXME: This workaround is required for touch emulation on Mac, where
- // compositor-side pinch handling is not enabled. See http://crbug.com/138003.
- // TODO(lukasza): https://crbug.com/734201: Add OOPIF support.
- LocalFrameView* frame_view = page->DeprecatedLocalMainFrame()->View();
- WebGestureEvent scaled_event = TransformWebGestureEvent(
- frame_view, static_cast<const WebGestureEvent&>(input_event));
- float page_scale_factor = page->PageScaleFactor();
- if (scaled_event.GetType() == WebInputEvent::kGesturePinchBegin) {
- WebFloatPoint gesture_position = scaled_event.PositionInRootFrame();
- last_pinch_anchor_css_ = std::make_unique<IntPoint>(
- RoundedIntPoint(gesture_position + frame_view->GetScrollOffset()));
- last_pinch_anchor_dip_ =
- std::make_unique<IntPoint>(FlooredIntPoint(gesture_position));
- last_pinch_anchor_dip_->Scale(page_scale_factor, page_scale_factor);
- }
- if (scaled_event.GetType() == WebInputEvent::kGesturePinchUpdate &&
- last_pinch_anchor_css_) {
- float new_page_scale_factor = page_scale_factor * scaled_event.PinchScale();
- IntPoint anchor_css(*last_pinch_anchor_dip_.get());
- anchor_css.Scale(1.f / new_page_scale_factor, 1.f / new_page_scale_factor);
- web_view_->SetPageScaleFactor(new_page_scale_factor);
- // TODO(lukasza): https://crbug.com/734201: Add OOPIF support.
- if (web_view_->MainFrame()->IsWebLocalFrame()) {
- web_view_->MainFrame()->ToWebLocalFrame()->SetScrollOffset(
- ToIntSize(*last_pinch_anchor_css_.get() - ToIntSize(anchor_css)));
- }
- }
- if (scaled_event.GetType() == WebInputEvent::kGesturePinchEnd) {
- last_pinch_anchor_css_.reset();
- last_pinch_anchor_dip_.reset();
- }
- return true;
+void DevToolsEmulator::SetDocumentCookieDisabled(bool disabled) {
+ if (document_cookie_disabled_ == disabled)
+ return;
+ document_cookie_disabled_ = disabled;
+ web_view_->GetPage()->GetSettings().SetCookieEnabled(
+ document_cookie_disabled_ ? false : embedder_cookie_enabled_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.h b/chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.h
index c5292bb52e6..e860b7b2524 100644
--- a/chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.h
+++ b/chromium/third_party/blink/renderer/core/inspector/dev_tools_emulator.h
@@ -17,10 +17,8 @@
namespace blink {
-class IntPoint;
class IntRect;
class TransformationMatrix;
-class WebInputEvent;
class WebViewImpl;
class CORE_EXPORT DevToolsEmulator final
@@ -37,6 +35,8 @@ class CORE_EXPORT DevToolsEmulator final
void SetViewportStyle(WebViewportStyle);
void SetPluginsEnabled(bool);
void SetScriptEnabled(bool);
+ void SetHideScrollbars(bool);
+ void SetCookieEnabled(bool);
void SetDoubleTapToZoomEnabled(bool);
bool DoubleTapToZoomEnabled() const;
void SetAvailablePointerTypes(int);
@@ -53,8 +53,9 @@ class CORE_EXPORT DevToolsEmulator final
void ResetViewport();
bool ResizeIsDeviceSizeChange();
void SetTouchEventEmulationEnabled(bool, int max_touch_points);
- bool HandleInputEvent(const WebInputEvent&);
void SetScriptExecutionDisabled(bool);
+ void SetScrollbarsHidden(bool);
+ void SetDocumentCookieDisabled(bool);
// Notify the DevToolsEmulator about a scroll or scale change of the main
// frame. Updates the transform for a viewport override.
@@ -112,11 +113,15 @@ class CORE_EXPORT DevToolsEmulator final
bool double_tap_to_zoom_enabled_;
bool original_device_supports_touch_;
int original_max_touch_points_;
- std::unique_ptr<IntPoint> last_pinch_anchor_css_;
- std::unique_ptr<IntPoint> last_pinch_anchor_dip_;
bool embedder_script_enabled_;
bool script_execution_disabled_;
+
+ bool embedder_hide_scrollbars_;
+ bool scrollbars_hidden_;
+
+ bool embedder_cookie_enabled_;
+ bool document_cookie_disabled_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/dev_tools_host.cc b/chromium/third_party/blink/renderer/core/inspector/dev_tools_host.cc
index 83973b69430..e31a9f246e7 100644
--- a/chromium/third_party/blink/renderer/core/inspector/dev_tools_host.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/dev_tools_host.cc
@@ -57,6 +57,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -157,7 +158,8 @@ float DevToolsHost::zoomFactor() {
float zoom_factor = frontend_frame_->PageZoomFactor();
// Cancel the device scale factor applied to the zoom factor in
// use-zoom-for-dsf mode.
- const ChromeClient* client = frontend_frame_->View()->GetChromeClient();
+ const PlatformChromeClient* client =
+ frontend_frame_->View()->GetChromeClient();
float window_to_viewport_ratio = client->WindowToViewportScalar(1.0f);
return zoom_factor / window_to_viewport_ratio;
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/dom_editor.cc b/chromium/third_party/blink/renderer/core/inspector/dom_editor.cc
index a2ec5146d6c..1cc6f5a25b4 100644
--- a/chromium/third_party/blink/renderer/core/inspector/dom_editor.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/dom_editor.cc
@@ -32,7 +32,6 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/dom/element.h"
@@ -42,6 +41,7 @@
#include "third_party/blink/renderer/core/inspector/dom_patch_support.h"
#include "third_party/blink/renderer/core/inspector/inspector_history.h"
#include "third_party/blink/renderer/core/inspector/protocol/Protocol.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -446,8 +446,12 @@ bool DOMEditor::SetNodeValue(Node* node,
static Response ToResponse(ExceptionState& exception_state) {
if (exception_state.HadException()) {
- return Response::Error(DOMException::GetErrorName(exception_state.Code()) +
- " " + exception_state.Message());
+ String name_prefix = IsDOMExceptionCode(exception_state.Code())
+ ? DOMException::GetErrorName(
+ exception_state.CodeAs<DOMExceptionCode>()) +
+ " "
+ : g_empty_string;
+ return Response::Error(name_prefix + exception_state.Message());
}
return Response::OK();
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/dom_patch_support.cc b/chromium/third_party/blink/renderer/core/inspector/dom_patch_support.cc
index 9ab6003ac35..7806f4d7adf 100644
--- a/chromium/third_party/blink/renderer/core/inspector/dom_patch_support.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/dom_patch_support.cc
@@ -33,11 +33,11 @@
#include <memory>
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/attribute.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/document_fragment.h"
+#include "third_party/blink/renderer/core/dom/document_init.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/node_traversal.h"
#include "third_party/blink/renderer/core/dom/xml_document.h"
@@ -49,6 +49,7 @@
#include "third_party/blink/renderer/core/inspector/dom_editor.h"
#include "third_party/blink/renderer/core/inspector/inspector_history.h"
#include "third_party/blink/renderer/core/xml/parser/xml_document_parser.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/crypto.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
#include "third_party/blink/renderer/platform/wtf/hash_traits.h"
diff --git a/chromium/third_party/blink/renderer/core/inspector/identifiers_factory.cc b/chromium/third_party/blink/renderer/core/inspector/identifiers_factory.cc
index 6aa97f6d440..c414e4e394d 100644
--- a/chromium/third_party/blink/renderer/core/inspector/identifiers_factory.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/identifiers_factory.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/core/inspector/identifiers_factory.h"
+#include "base/atomic_sequence_num.h"
#include "base/process/process_handle.h"
#include "third_party/blink/renderer/core/dom/weak_identifier_map.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -36,16 +37,10 @@
namespace blink {
-namespace {
-
-volatile int g_last_used_identifier = 0;
-
-} // namespace
-
// static
String IdentifiersFactory::CreateIdentifier() {
- int identifier = AtomicIncrement(&g_last_used_identifier);
- return AddProcessIdPrefixTo(identifier);
+ static base::AtomicSequenceNumber last_used_identifier;
+ return AddProcessIdPrefixTo(last_used_identifier.GetNext());
}
// static
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 0b009286cc1..cdd317fd95c 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/inspector/inspector_animation_agent.h"
#include <memory>
+
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/animation/animation.h"
#include "third_party/blink/renderer/core/animation/animation_effect.h"
@@ -30,7 +31,6 @@
#include "third_party/blink/renderer/core/inspector/inspector_style_sheet.h"
#include "third_party/blink/renderer/core/inspector/v8_inspector_string.h"
#include "third_party/blink/renderer/platform/animation/timing_function.h"
-#include "third_party/blink/renderer/platform/decimal.h"
#include "third_party/blink/renderer/platform/wtf/text/base64.h"
namespace AnimationAgentState {
@@ -547,15 +547,18 @@ DocumentTimeline& InspectorAnimationAgent::ReferenceTimeline() {
double InspectorAnimationAgent::NormalizedStartTime(
blink::Animation& animation) {
+ double time_ms = animation.startTime().value_or(NullValue());
if (ReferenceTimeline().PlaybackRate() == 0) {
- return animation.startTime().value_or(NullValue()) +
- ReferenceTimeline().currentTime() -
- animation.TimelineInternal()->currentTime();
+ time_ms += ReferenceTimeline().currentTime() -
+ animation.TimelineInternal()->currentTime();
+ } else {
+ time_ms += (animation.TimelineInternal()->ZeroTime() -
+ ReferenceTimeline().ZeroTime())
+ .InMillisecondsF() *
+ ReferenceTimeline().PlaybackRate();
}
- return animation.startTime().value_or(NullValue()) +
- (animation.TimelineInternal()->ZeroTime() -
- ReferenceTimeline().ZeroTime()) *
- 1000 * ReferenceTimeline().PlaybackRate();
+ // Round to the closest microsecond.
+ return std::round(time_ms * 1000) / 1000;
}
void InspectorAnimationAgent::Trace(blink::Visitor* visitor) {
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 5010b17c2d1..b413b5869a0 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
@@ -33,8 +33,7 @@ bool EncodeAsImage(char* body,
Vector<unsigned char>* output) {
const WebSize maximum_size = WebSize(kMaximumEncodeImageWidthInPixels,
kMaximumEncodeImageHeightInPixels);
- SkBitmap bitmap =
- WebImage::FromData(WebData(body, size), maximum_size).GetSkBitmap();
+ SkBitmap bitmap = WebImage::FromData(WebData(body, size), maximum_size);
if (bitmap.isNull())
return false;
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 d7eda5c6c31..b06102238b5 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
@@ -26,7 +26,6 @@
#include "third_party/blink/renderer/core/inspector/inspector_css_agent.h"
#include "base/macros.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/animation/css/css_animation_data.h"
#include "third_party/blink/renderer/core/css/css_color_value.h"
#include "third_party/blink/renderer/core/css/css_computed_style_declaration.h"
@@ -86,6 +85,7 @@
#include "third_party/blink/renderer/core/style/style_image.h"
#include "third_party/blink/renderer/core/style_property_shorthand.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#include "third_party/blink/renderer/platform/fonts/font_custom_platform_data.h"
@@ -152,13 +152,9 @@ HeapVector<Member<Element>> ElementsFromRect(LayoutRect rect,
HitTestRequest::kPenetratingList |
HitTestRequest::kIgnoreClipping);
- LayoutPoint center = rect.Center();
- LayoutUnit horizontal_padding = rect.Width() / 2;
- LayoutUnit vertical_padding = rect.Height() / 2;
- LayoutRectOutsets padding(vertical_padding, horizontal_padding,
- vertical_padding, horizontal_padding);
- HitTestResult result(request, center, padding);
- document.GetFrame()->ContentLayoutObject()->HitTest(result);
+ HitTestLocation location(rect);
+ HitTestResult result(request, location);
+ document.GetFrame()->ContentLayoutObject()->HitTest(location, result);
HeapVector<Member<Element>> elements;
Node* previous_node = nullptr;
for (const auto hit_test_result_node : result.ListBasedTestResult()) {
@@ -1161,18 +1157,11 @@ Response InspectorCSSAgent::getComputedStyleForNode(
.build());
}
- std::unique_ptr<HashMap<AtomicString, scoped_refptr<CSSVariableData>>>
- variables = computed_style_info->GetVariables();
-
- if (variables && !variables->IsEmpty()) {
- for (const auto& it : *variables) {
- if (!it.value)
- continue;
- (*style)->addItem(protocol::CSS::CSSComputedStyleProperty::create()
- .setName(it.key)
- .setValue(it.value->TokenRange().Serialize())
- .build());
- }
+ for (const auto& it : computed_style_info->GetVariables()) {
+ (*style)->addItem(protocol::CSS::CSSComputedStyleProperty::create()
+ .setName(it.key)
+ .setValue(it.value->CssText())
+ .build());
}
return Response::OK();
}
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 16e8a85d335..6e6dc1c4910 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
@@ -33,7 +33,6 @@
#include <memory>
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/binding_security.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_node.h"
#include "third_party/blink/renderer/core/dom/attr.h"
@@ -80,6 +79,7 @@
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/xml/document_xpath_evaluator.h"
#include "third_party/blink/renderer/core/xml/xpath_result.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/wtf/text/cstring.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -148,8 +148,12 @@ void InspectorRevalidateDOMTask::Trace(blink::Visitor* visitor) {
Response InspectorDOMAgent::ToResponse(ExceptionState& exception_state) {
if (exception_state.HadException()) {
- return Response::Error(DOMException::GetErrorName(exception_state.Code()) +
- " " + exception_state.Message());
+ String name_prefix = IsDOMExceptionCode(exception_state.Code())
+ ? DOMException::GetErrorName(
+ exception_state.CodeAs<DOMExceptionCode>()) +
+ " "
+ : g_empty_string;
+ return Response::Error(name_prefix + exception_state.Message());
}
return Response::OK();
}
@@ -1293,6 +1297,21 @@ Response InspectorDOMAgent::getBoxModel(
return Response::OK();
}
+Response InspectorDOMAgent::getContentQuads(
+ Maybe<int> node_id,
+ Maybe<int> backend_node_id,
+ Maybe<String> object_id,
+ std::unique_ptr<protocol::Array<protocol::Array<double>>>* quads) {
+ Node* node = nullptr;
+ Response response = AssertNode(node_id, backend_node_id, object_id, node);
+ if (!response.isSuccess())
+ return response;
+ bool result = InspectorHighlight::GetContentQuads(node, quads);
+ if (!result)
+ return Response::Error("Could not compute content quads.");
+ return Response::OK();
+}
+
Response InspectorDOMAgent::getNodeForLocation(
int x,
int y,
@@ -1308,9 +1327,9 @@ Response InspectorDOMAgent::getNodeForLocation(
LayoutPoint document_point(x, y);
HitTestRequest request(HitTestRequest::kMove | HitTestRequest::kReadOnly |
HitTestRequest::kAllowChildFrameContent);
- HitTestResult result(request,
- document_->View()->DocumentToAbsolute(document_point));
- document_->GetFrame()->ContentLayoutObject()->HitTest(result);
+ HitTestLocation location(document_->View()->DocumentToFrame(document_point));
+ HitTestResult result(request, location);
+ document_->GetFrame()->ContentLayoutObject()->HitTest(location, result);
if (!include_user_agent_shadow_dom)
result.SetToShadowHostIfInRestrictedShadowRoot();
Node* node = result.InnerPossiblyPseudoNode();
@@ -1787,7 +1806,7 @@ void InspectorDOMAgent::CollectNodes(
}
}
-void InspectorDOMAgent::DomContentLoadedEventFired(LocalFrame* frame) {
+void InspectorDOMAgent::DOMContentLoadedEventFired(LocalFrame* frame) {
if (frame != inspected_frames_->Root())
return;
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_dom_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_dom_agent.h
index 235593d91d1..cf7a5d12641 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_dom_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_dom_agent.h
@@ -190,6 +190,12 @@ class CORE_EXPORT InspectorDOMAgent final
protocol::Maybe<int> backend_node_id,
protocol::Maybe<String> object_id,
std::unique_ptr<protocol::DOM::BoxModel>*) override;
+ protocol::Response getContentQuads(
+ protocol::Maybe<int> node_id,
+ protocol::Maybe<int> backend_node_id,
+ protocol::Maybe<String> object_id,
+ std::unique_ptr<protocol::Array<protocol::Array<double>>>* quads)
+ override;
protocol::Response getNodeForLocation(
int x,
int y,
@@ -212,7 +218,7 @@ class CORE_EXPORT InspectorDOMAgent final
void ReleaseDanglingNodes();
// Methods called from the InspectorInstrumentation.
- void DomContentLoadedEventFired(LocalFrame*);
+ void DOMContentLoadedEventFired(LocalFrame*);
void DidCommitLoad(LocalFrame*, DocumentLoader*);
void DidInsertDOMNode(Node*);
void WillRemoveDOMNode(Node*);
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.cc
index 0f827677c71..3a20c3da3c1 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.cc
@@ -71,6 +71,10 @@ static const char kWebglWarningFiredEventName[] = "webglWarningFired";
static const char kWebglErrorNameProperty[] = "webglErrorName";
static const char kScriptBlockedByCSPEventName[] = "scriptBlockedByCSP";
static const char kCanvasContextCreatedEventName[] = "canvasContextCreated";
+static const char kAudioContextCreatedEventName[] = "audioContextCreated";
+static const char kAudioContextClosedEventName[] = "audioContextClosed";
+static const char kAudioContextResumedEventName[] = "audioContextResumed";
+static const char kAudioContextSuspendedEventName[] = "audioContextSuspended";
namespace DOMDebuggerAgentState {
static const char kEventListenerBreakpoints[] = "eventListenerBreakpoints";
@@ -823,4 +827,28 @@ void InspectorDOMDebuggerAgent::DidCommitLoadForLocalFrame(LocalFrame*) {
dom_breakpoints_.clear();
}
+void InspectorDOMDebuggerAgent::DidCreateAudioContext() {
+ PauseOnNativeEventIfNeeded(
+ PreparePauseOnNativeEventData(kAudioContextCreatedEventName, nullptr),
+ true);
+}
+
+void InspectorDOMDebuggerAgent::DidCloseAudioContext() {
+ PauseOnNativeEventIfNeeded(
+ PreparePauseOnNativeEventData(kAudioContextClosedEventName, nullptr),
+ true);
+}
+
+void InspectorDOMDebuggerAgent::DidResumeAudioContext() {
+ PauseOnNativeEventIfNeeded(
+ PreparePauseOnNativeEventData(kAudioContextResumedEventName, nullptr),
+ true);
+}
+
+void InspectorDOMDebuggerAgent::DidSuspendAudioContext() {
+ PauseOnNativeEventIfNeeded(
+ PreparePauseOnNativeEventData(kAudioContextSuspendedEventName, nullptr),
+ true);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.h
index ef07c992418..f9856e29375 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.h
@@ -110,6 +110,10 @@ class CORE_EXPORT InspectorDOMDebuggerAgent final
void Will(const probe::UserCallback&);
void Did(const probe::UserCallback&);
void BreakableLocation(const char* name);
+ void DidCreateAudioContext();
+ void DidCloseAudioContext();
+ void DidResumeAudioContext();
+ void DidSuspendAudioContext();
protocol::Response disable() override;
void Restore() override;
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 0987c26c217..0da6c561fc6 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
@@ -63,6 +63,17 @@ std::unique_ptr<protocol::DOM::Rect> BuildRectForFloatRect(
.build();
}
+std::unique_ptr<protocol::Array<double>> BuildRectForFloatRect2(
+ const FloatRect& rect) {
+ std::unique_ptr<protocol::Array<double>> result =
+ protocol::Array<double>::create();
+ result->addItem(rect.X());
+ result->addItem(rect.Y());
+ result->addItem(rect.Width());
+ result->addItem(rect.Height());
+ return result;
+}
+
Document* GetEmbeddedDocument(PaintLayer* layer) {
// Documents are embedded on their own PaintLayer via a LayoutEmbeddedContent.
if (layer->GetLayoutObject().IsLayoutEmbeddedContent()) {
@@ -76,6 +87,26 @@ Document* GetEmbeddedDocument(PaintLayer* layer) {
return nullptr;
}
+std::unique_ptr<protocol::DOMSnapshot::RareStringData> StringData() {
+ return protocol::DOMSnapshot::RareStringData::create()
+ .setIndex(protocol::Array<int>::create())
+ .setValue(protocol::Array<int>::create())
+ .build();
+}
+
+std::unique_ptr<protocol::DOMSnapshot::RareIntegerData> IntegerData() {
+ return protocol::DOMSnapshot::RareIntegerData::create()
+ .setIndex(protocol::Array<int>::create())
+ .setValue(protocol::Array<int>::create())
+ .build();
+}
+
+std::unique_ptr<protocol::DOMSnapshot::RareBooleanData> BooleanData() {
+ return protocol::DOMSnapshot::RareBooleanData::create()
+ .setIndex(protocol::Array<int>::create())
+ .build();
+}
+
} // namespace
struct InspectorDOMSnapshotAgent::VectorStringHashTraits
@@ -203,8 +234,6 @@ Response InspectorDOMSnapshotAgent::getSnapshot(
layout_tree_nodes,
std::unique_ptr<protocol::Array<protocol::DOMSnapshot::ComputedStyle>>*
computed_styles) {
- DCHECK(!dom_nodes_ && !layout_tree_nodes_ && !computed_styles_);
-
Document* document = inspected_frames_->Root()->GetDocument();
if (!document)
return Response::Error("Document is not available");
@@ -247,6 +276,44 @@ Response InspectorDOMSnapshotAgent::getSnapshot(
return Response::OK();
}
+protocol::Response InspectorDOMSnapshotAgent::captureSnapshot(
+ std::unique_ptr<protocol::Array<String>> computed_styles,
+ std::unique_ptr<protocol::Array<protocol::DOMSnapshot::DocumentSnapshot>>*
+ documents,
+ std::unique_ptr<protocol::Array<String>>* strings) {
+ strings_ = protocol::Array<String>::create();
+ documents_ =
+ protocol::Array<protocol::DOMSnapshot::DocumentSnapshot>::create();
+
+ css_property_whitelist_ = std::make_unique<CSSPropertyWhitelist>();
+ // Look up the CSSPropertyIDs for each entry in |computed_styles|.
+ for (size_t i = 0; i < computed_styles->length(); i++) {
+ CSSPropertyID property_id = cssPropertyID(computed_styles->get(i));
+ if (property_id == CSSPropertyInvalid)
+ continue;
+ css_property_whitelist_->push_back(
+ std::make_pair(computed_styles->get(i), property_id));
+ }
+
+ for (LocalFrame* frame : *inspected_frames_) {
+ if (Document* document = frame->GetDocument())
+ document_order_map_.Set(document, document_order_map_.size());
+ }
+ for (LocalFrame* frame : *inspected_frames_) {
+ if (Document* document = frame->GetDocument())
+ VisitDocument2(document);
+ }
+
+ // Extract results from state and reset.
+ *documents = std::move(documents_);
+ *strings = std::move(strings_);
+ css_property_whitelist_.reset();
+ string_table_.clear();
+ document_order_map_.clear();
+ documents_.reset();
+ return Response::OK();
+}
+
int InspectorDOMSnapshotAgent::VisitNode(Node* node,
bool include_event_listeners,
bool include_user_agent_shadow_tree) {
@@ -294,7 +361,8 @@ int InspectorDOMSnapshotAgent::VisitNode(Node* node,
int index = dom_nodes_->length();
dom_nodes_->addItem(std::move(owned_value));
- int layoutNodeIndex = VisitLayoutTreeNode(node, index);
+ int layoutNodeIndex =
+ VisitLayoutTreeNode(node->GetLayoutObject(), node, index);
if (layoutNodeIndex != -1)
value->setLayoutNodeIndex(layoutNodeIndex);
@@ -344,22 +412,6 @@ int InspectorDOMSnapshotAgent::VisitNode(Node* node,
value->setFrameId(IdentifiersFactory::FrameId(frame));
}
- if (auto* link_element = ToHTMLLinkElementOrNull(*element)) {
- if (link_element->IsImport() && link_element->import() &&
- InspectorDOMAgent::InnerParentNode(link_element->import()) ==
- link_element) {
- value->setImportedDocumentIndex(
- VisitNode(link_element->import(), include_event_listeners,
- include_user_agent_shadow_tree));
- }
- }
-
- if (auto* template_element = ToHTMLTemplateElementOrNull(*element)) {
- value->setTemplateContentIndex(VisitNode(template_element->content(),
- include_event_listeners,
- include_user_agent_shadow_tree));
- }
-
if (auto* textarea_element = ToHTMLTextAreaElementOrNull(*element))
value->setTextValue(textarea_element->value());
@@ -379,10 +431,12 @@ int InspectorDOMSnapshotAgent::VisitNode(Node* node,
if (InspectorDOMAgent::GetPseudoElementType(element->GetPseudoId(),
&pseudo_type)) {
value->setPseudoType(pseudo_type);
+ VisitPseudoLayoutChildren(node, node->GetLayoutObject(), index);
}
} else {
- value->setPseudoElementIndexes(VisitPseudoElements(
- element, include_event_listeners, include_user_agent_shadow_tree));
+ value->setPseudoElementIndexes(
+ VisitPseudoElements(element, index, include_event_listeners,
+ include_user_agent_shadow_tree));
}
HTMLImageElement* image_element = ToHTMLImageElementOrNull(node);
@@ -414,6 +468,194 @@ int InspectorDOMSnapshotAgent::VisitNode(Node* node,
return index;
}
+int InspectorDOMSnapshotAgent::AddString(const String& string) {
+ if (string.IsEmpty())
+ return -1;
+ auto it = string_table_.find(string);
+ int index;
+ if (it == string_table_.end()) {
+ index = strings_->length();
+ strings_->addItem(string);
+ string_table_.Set(string, index);
+ } else {
+ index = it->value;
+ }
+ return index;
+}
+
+void InspectorDOMSnapshotAgent::SetRare(
+ protocol::DOMSnapshot::RareIntegerData* data,
+ int index,
+ int value) {
+ data->getIndex()->addItem(index);
+ data->getValue()->addItem(value);
+}
+
+void InspectorDOMSnapshotAgent::SetRare(
+ protocol::DOMSnapshot::RareStringData* data,
+ int index,
+ const String& value) {
+ data->getIndex()->addItem(index);
+ data->getValue()->addItem(AddString(value));
+}
+
+void InspectorDOMSnapshotAgent::SetRare(
+ protocol::DOMSnapshot::RareBooleanData* data,
+ int index) {
+ data->getIndex()->addItem(index);
+}
+
+void InspectorDOMSnapshotAgent::VisitDocument2(Document* document) {
+ // Update layout tree before traversal of document so that we inspect a
+ // current and consistent state of all trees. No need to do this if paint
+ // order was calculated, since layout trees were already updated during
+ // TraversePaintLayerTree().
+ document->UpdateStyleAndLayoutTree();
+ DocumentType* doc_type = document->doctype();
+
+ document_ =
+ protocol::DOMSnapshot::DocumentSnapshot::create()
+ .setDocumentURL(
+ AddString(InspectorDOMAgent::DocumentURLString(document)))
+ .setBaseURL(
+ AddString(InspectorDOMAgent::DocumentBaseURLString(document)))
+ .setContentLanguage(AddString(document->ContentLanguage()))
+ .setEncodingName(AddString(document->EncodingName()))
+ .setFrameId(
+ AddString(IdentifiersFactory::FrameId(document->GetFrame())))
+ .setPublicId(AddString(doc_type ? doc_type->publicId() : String()))
+ .setSystemId(AddString(doc_type ? doc_type->systemId() : String()))
+ .setNodes(protocol::DOMSnapshot::NodeTreeSnapshot::create()
+ .setParentIndex(protocol::Array<int>::create())
+ .setNodeType(protocol::Array<int>::create())
+ .setNodeName(protocol::Array<int>::create())
+ .setNodeValue(protocol::Array<int>::create())
+ .setBackendNodeId(protocol::Array<int>::create())
+ .setAttributes(
+ protocol::Array<protocol::Array<int>>::create())
+ .setTextValue(StringData())
+ .setInputValue(StringData())
+ .setInputChecked(BooleanData())
+ .setOptionSelected(BooleanData())
+ .setContentDocumentIndex(IntegerData())
+ .setPseudoType(StringData())
+ .setIsClickable(BooleanData())
+ .setCurrentSourceURL(StringData())
+ .setOriginURL(StringData())
+ .build())
+ .setLayout(
+ protocol::DOMSnapshot::LayoutTreeSnapshot::create()
+ .setNodeIndex(protocol::Array<int>::create())
+ .setBounds(protocol::Array<protocol::Array<double>>::create())
+ .setText(protocol::Array<int>::create())
+ .setStyles(protocol::Array<protocol::Array<int>>::create())
+ .build())
+ .setTextBoxes(
+ protocol::DOMSnapshot::TextBoxSnapshot::create()
+ .setLayoutIndex(protocol::Array<int>::create())
+ .setBounds(protocol::Array<protocol::Array<double>>::create())
+ .setStart(protocol::Array<int>::create())
+ .setLength(protocol::Array<int>::create())
+ .build())
+ .build();
+ VisitNode2(document, -1);
+ documents_->addItem(std::move(document_));
+}
+
+int InspectorDOMSnapshotAgent::VisitNode2(Node* node, int parent_index) {
+ String node_value;
+ switch (node->getNodeType()) {
+ case Node::kTextNode:
+ case Node::kAttributeNode:
+ case Node::kCommentNode:
+ case Node::kCdataSectionNode:
+ case Node::kDocumentFragmentNode:
+ node_value = node->nodeValue();
+ break;
+ default:
+ break;
+ }
+
+ auto* nodes = document_->getNodes();
+ int index = nodes->getNodeName(nullptr)->length();
+ int backend_node_id = DOMNodeIds::IdForNode(node);
+
+ // Create DOMNode object and add it to the result array before traversing
+ // children, so that parents appear before their children in the array.
+ nodes->getParentIndex(nullptr)->addItem(parent_index);
+
+ nodes->getNodeType(nullptr)->addItem(static_cast<int>(node->getNodeType()));
+ nodes->getNodeName(nullptr)->addItem(AddString(node->nodeName()));
+ nodes->getNodeValue(nullptr)->addItem(AddString(node_value));
+ nodes->getBackendNodeId(nullptr)->addItem(backend_node_id);
+ nodes->getAttributes(nullptr)->addItem(BuildArrayForElementAttributes2(node));
+ BuildLayoutTreeNode(node->GetLayoutObject(), node, index);
+
+ if (origin_url_map_ && origin_url_map_->Contains(backend_node_id)) {
+ String origin_url = origin_url_map_->at(backend_node_id);
+ // In common cases, it is implicit that a child node would have the same
+ // origin url as its parent, so no need to mark twice.
+ if (!node->parentNode() || origin_url_map_->at(DOMNodeIds::IdForNode(
+ node->parentNode())) != origin_url) {
+ SetRare(nodes->getOriginURL(nullptr), index, origin_url);
+ }
+ }
+
+ if (node->WillRespondToMouseClickEvents())
+ SetRare(nodes->getIsClickable(nullptr), index);
+
+ if (node->IsElementNode()) {
+ Element* element = ToElement(node);
+ if (node->IsFrameOwnerElement()) {
+ const HTMLFrameOwnerElement* frame_owner = ToHTMLFrameOwnerElement(node);
+ if (Document* doc = frame_owner->contentDocument()) {
+ SetRare(nodes->getContentDocumentIndex(nullptr), index,
+ document_order_map_.at(doc));
+ }
+ }
+
+ if (auto* textarea_element = ToHTMLTextAreaElementOrNull(*element)) {
+ SetRare(nodes->getTextValue(nullptr), index, textarea_element->value());
+ }
+
+ if (auto* input_element = ToHTMLInputElementOrNull(*element)) {
+ SetRare(nodes->getInputValue(nullptr), index, input_element->value());
+ if ((input_element->type() == InputTypeNames::radio) ||
+ (input_element->type() == InputTypeNames::checkbox)) {
+ if (input_element->checked()) {
+ SetRare(nodes->getInputChecked(nullptr), index);
+ }
+ }
+ }
+
+ if (auto* option_element = ToHTMLOptionElementOrNull(*element)) {
+ if (option_element->Selected()) {
+ SetRare(nodes->getOptionSelected(nullptr), index);
+ }
+ }
+
+ if (element->GetPseudoId()) {
+ protocol::DOM::PseudoType pseudo_type;
+ if (InspectorDOMAgent::GetPseudoElementType(element->GetPseudoId(),
+ &pseudo_type)) {
+ SetRare(nodes->getPseudoType(nullptr), index, pseudo_type);
+ VisitPseudoLayoutChildren2(node, node->GetLayoutObject(), index);
+ }
+ } else {
+ VisitPseudoElements2(element, index);
+ }
+
+ HTMLImageElement* image_element = ToHTMLImageElementOrNull(node);
+ if (image_element) {
+ SetRare(nodes->getCurrentSourceURL(nullptr), index,
+ image_element->currentSrc());
+ }
+ }
+ if (node->IsContainerNode())
+ VisitContainerChildren2(node, index);
+ return index;
+}
+
Node* InspectorDOMSnapshotAgent::FirstChild(
const Node& node,
bool include_user_agent_shadow_tree) {
@@ -473,30 +715,77 @@ InspectorDOMSnapshotAgent::VisitContainerChildren(
return children;
}
+void InspectorDOMSnapshotAgent::VisitContainerChildren2(Node* container,
+ int parent_index) {
+ if (!HasChildren(*container, false))
+ return;
+
+ for (Node* child = FirstChild(*container, false); child;
+ child = NextSibling(*child, false)) {
+ VisitNode2(child, parent_index);
+ }
+}
+
+void InspectorDOMSnapshotAgent::VisitPseudoLayoutChildren(
+ Node* pseudo_node,
+ LayoutObject* layout_object,
+ int index) {
+ for (LayoutObject* child = layout_object->SlowFirstChild(); child;
+ child = child->NextSibling()) {
+ VisitLayoutTreeNode(child, pseudo_node, index);
+ }
+}
+
+void InspectorDOMSnapshotAgent::VisitPseudoLayoutChildren2(
+ Node* pseudo_node,
+ LayoutObject* layout_object,
+ int index) {
+ for (LayoutObject* child = layout_object->SlowFirstChild(); child;
+ child = child->NextSibling()) {
+ BuildLayoutTreeNode(child, pseudo_node, index);
+ }
+}
+
std::unique_ptr<protocol::Array<int>>
InspectorDOMSnapshotAgent::VisitPseudoElements(
Element* parent,
+ int index,
bool include_event_listeners,
bool include_user_agent_shadow_tree) {
- if (!parent->GetPseudoElement(kPseudoIdBefore) &&
+ if (!parent->GetPseudoElement(kPseudoIdFirstLetter) &&
+ !parent->GetPseudoElement(kPseudoIdBefore) &&
!parent->GetPseudoElement(kPseudoIdAfter)) {
return nullptr;
}
auto pseudo_elements = protocol::Array<int>::create();
+ PseudoId pseudo_types[] = {kPseudoIdFirstLetter, kPseudoIdBefore,
+ kPseudoIdAfter};
+ for (PseudoId pseudo_id : pseudo_types) {
+ if (parent->GetPseudoElement(pseudo_id)) {
+ Node* pseudo_node = parent->GetPseudoElement(pseudo_id);
+ pseudo_elements->addItem(VisitNode(pseudo_node, include_event_listeners,
+ include_user_agent_shadow_tree));
+ }
+ }
+ return pseudo_elements;
+}
- if (parent->GetPseudoElement(kPseudoIdBefore)) {
- pseudo_elements->addItem(
- VisitNode(parent->GetPseudoElement(kPseudoIdBefore),
- include_event_listeners, include_user_agent_shadow_tree));
+void InspectorDOMSnapshotAgent::VisitPseudoElements2(Element* parent,
+ int parent_index) {
+ if (!parent->GetPseudoElement(kPseudoIdFirstLetter) &&
+ !parent->GetPseudoElement(kPseudoIdBefore) &&
+ !parent->GetPseudoElement(kPseudoIdAfter)) {
+ return;
}
- if (parent->GetPseudoElement(kPseudoIdAfter)) {
- pseudo_elements->addItem(VisitNode(parent->GetPseudoElement(kPseudoIdAfter),
- include_event_listeners,
- include_user_agent_shadow_tree));
+ PseudoId pseudo_types[] = {kPseudoIdFirstLetter, kPseudoIdBefore,
+ kPseudoIdAfter};
+ for (PseudoId i : pseudo_types) {
+ if (parent->GetPseudoElement(i)) {
+ Node* pseudo_node = parent->GetPseudoElement(i);
+ VisitNode2(pseudo_node, parent_index);
+ }
}
-
- return pseudo_elements;
}
std::unique_ptr<protocol::Array<protocol::DOMSnapshot::NameValue>>
@@ -515,15 +804,29 @@ InspectorDOMSnapshotAgent::BuildArrayForElementAttributes(Element* element) {
return attributes_value;
}
-int InspectorDOMSnapshotAgent::VisitLayoutTreeNode(Node* node, int node_index) {
- LayoutObject* layout_object = node->GetLayoutObject();
+std::unique_ptr<protocol::Array<int>>
+InspectorDOMSnapshotAgent::BuildArrayForElementAttributes2(Node* node) {
+ auto result = protocol::Array<int>::create();
+ if (!node->IsElementNode())
+ return result;
+ AttributeCollection attributes = ToElement(node)->Attributes();
+ for (const auto& attribute : attributes) {
+ result->addItem(AddString(attribute.GetName().ToString()));
+ result->addItem(AddString(attribute.Value()));
+ }
+ return result;
+}
+
+int InspectorDOMSnapshotAgent::VisitLayoutTreeNode(LayoutObject* layout_object,
+ Node* node,
+ int node_index) {
if (!layout_object)
return -1;
auto layout_tree_node = protocol::DOMSnapshot::LayoutTreeNode::create()
.setDomNodeIndex(node_index)
- .setBoundingBox(BuildRectForFloatRect(
- layout_object->AbsoluteBoundingBoxRect()))
+ .setBoundingBox(BuildRectForFloatRect(FloatRect(
+ layout_object->AbsoluteBoundingBoxRect())))
.build();
int style_index = GetStyleIndexForNode(node);
@@ -569,6 +872,46 @@ int InspectorDOMSnapshotAgent::VisitLayoutTreeNode(Node* node, int node_index) {
return index;
}
+int InspectorDOMSnapshotAgent::BuildLayoutTreeNode(LayoutObject* layout_object,
+ Node* node,
+ int node_index) {
+ if (!layout_object)
+ return -1;
+ auto* layout_tree_snapshot = document_->getLayout();
+ auto* text_box_snapshot = document_->getTextBoxes();
+
+ int layout_index = layout_tree_snapshot->getNodeIndex()->length();
+ layout_tree_snapshot->getNodeIndex()->addItem(node_index);
+ layout_tree_snapshot->getStyles()->addItem(BuildStylesForNode(node));
+ layout_tree_snapshot->getBounds()->addItem(BuildRectForFloatRect2(
+ FloatRect(layout_object->AbsoluteBoundingBoxRect())));
+
+ String text = layout_object->IsText() ? ToLayoutText(layout_object)->GetText()
+ : String();
+ layout_tree_snapshot->getText()->addItem(AddString(text));
+
+ if (!layout_object->IsText())
+ return layout_index;
+
+ LayoutText* layout_text = ToLayoutText(layout_object);
+ if (!layout_text->HasTextBoxes())
+ return layout_index;
+
+ for (const InlineTextBox* text_box : layout_text->TextBoxes()) {
+ FloatRect local_coords_text_box_rect(text_box->FrameRect());
+ FloatRect absolute_coords_text_box_rect =
+ layout_object->LocalToAbsoluteQuad(local_coords_text_box_rect)
+ .BoundingBox();
+ text_box_snapshot->getLayoutIndex()->addItem(layout_index);
+ text_box_snapshot->getBounds()->addItem(
+ BuildRectForFloatRect2(absolute_coords_text_box_rect));
+ text_box_snapshot->getStart()->addItem(text_box->Start());
+ text_box_snapshot->getLength()->addItem(text_box->Len());
+ }
+
+ return layout_index;
+}
+
int InspectorDOMSnapshotAgent::GetStyleIndexForNode(Node* node) {
CSSComputedStyleDeclaration* computed_style_info =
CSSComputedStyleDeclaration::Create(node, true);
@@ -611,6 +954,18 @@ int InspectorDOMSnapshotAgent::GetStyleIndexForNode(Node* node) {
return index;
}
+std::unique_ptr<protocol::Array<int>>
+InspectorDOMSnapshotAgent::BuildStylesForNode(Node* node) {
+ CSSComputedStyleDeclaration* computed_style_info =
+ CSSComputedStyleDeclaration::Create(node, true);
+ std::unique_ptr<protocol::Array<int>> result = protocol::Array<int>::create();
+ for (const auto& pair : *css_property_whitelist_) {
+ String value = computed_style_info->GetPropertyValue(pair.second);
+ result->addItem(AddString(value));
+ }
+ return result;
+}
+
void InspectorDOMSnapshotAgent::TraversePaintLayerTree(Document* document) {
// Update layout tree before traversal of document so that we inspect a
// current and consistent state of all trees.
@@ -638,10 +993,11 @@ void InspectorDOMSnapshotAgent::VisitPaintLayer(PaintLayer* layer) {
DCHECK(!embedded_document || !layer->FirstChild());
if (!embedded_document) {
- PaintLayerStackingNode* node = layer->StackingNode();
- PaintLayerStackingNodeIterator iterator(*node, kAllChildren);
- while (PaintLayerStackingNode* child_node = iterator.Next()) {
- VisitPaintLayer(child_node->Layer());
+ if (PaintLayerStackingNode* node = layer->StackingNode()) {
+ PaintLayerStackingNodeIterator iterator(*node, kAllChildren);
+ while (PaintLayer* child_layer = iterator.Next()) {
+ VisitPaintLayer(child_layer);
+ }
}
}
}
@@ -649,6 +1005,7 @@ void InspectorDOMSnapshotAgent::VisitPaintLayer(PaintLayer* layer) {
void InspectorDOMSnapshotAgent::Trace(blink::Visitor* visitor) {
visitor->Trace(inspected_frames_);
visitor->Trace(dom_debugger_agent_);
+ visitor->Trace(document_order_map_);
InspectorBaseAgent::Trace(visitor);
}
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 0d72223c1cd..b65e206b4a4 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
@@ -49,6 +49,11 @@ class CORE_EXPORT InspectorDOMSnapshotAgent final
layout_tree_nodes,
std::unique_ptr<protocol::Array<protocol::DOMSnapshot::ComputedStyle>>*
computed_styles) override;
+ protocol::Response captureSnapshot(
+ std::unique_ptr<protocol::Array<String>> computed_styles,
+ std::unique_ptr<protocol::Array<protocol::DOMSnapshot::DocumentSnapshot>>*
+ documents,
+ std::unique_ptr<protocol::Array<String>>* strings) override;
bool Enabled() const;
@@ -60,11 +65,21 @@ class CORE_EXPORT InspectorDOMSnapshotAgent final
InspectorDOMSnapshotAgent(InspectedFrames*, InspectorDOMDebuggerAgent*);
void InnerEnable();
- // Adds a DOMNode for the given Node to |dom_nodes_| and returns its index.
int VisitNode(Node*,
bool include_event_listeners,
bool include_user_agent_shadow_tree);
+ int AddString(const String& string);
+ void SetRare(protocol::DOMSnapshot::RareIntegerData* data,
+ int index,
+ int value);
+ void SetRare(protocol::DOMSnapshot::RareStringData* data,
+ int index,
+ const String& value);
+ void SetRare(protocol::DOMSnapshot::RareBooleanData* data, int index);
+ void VisitDocument2(Document*);
+ int VisitNode2(Node*, int parent_index);
+
// Helpers for VisitContainerChildren.
static Node* FirstChild(const Node& node,
bool include_user_agent_shadow_tree);
@@ -77,23 +92,38 @@ class CORE_EXPORT InspectorDOMSnapshotAgent final
Node* container,
bool include_event_listeners,
bool include_user_agent_shadow_tree);
+ void VisitContainerChildren2(Node* container, int parent_index);
+
+ // Collect LayoutTreeNodes owned by a pseudo element.
+ void VisitPseudoLayoutChildren(Node* pseudo_node,
+ LayoutObject* layout_object,
+ int index);
+ void VisitPseudoLayoutChildren2(Node* pseudo_node,
+ LayoutObject* layout_object,
+ int index);
+
std::unique_ptr<protocol::Array<int>> VisitPseudoElements(
Element* parent,
+ int index,
bool include_event_listeners,
bool include_user_agent_shadow_tree);
+ void VisitPseudoElements2(Element* parent, int parent_index);
std::unique_ptr<protocol::Array<protocol::DOMSnapshot::NameValue>>
BuildArrayForElementAttributes(Element*);
+ std::unique_ptr<protocol::Array<int>> BuildArrayForElementAttributes2(Node*);
- // Adds a LayoutTreeNode for the LayoutObject of the given Node to
- // |layout_tree_nodes_| and returns its index. Returns -1 if the Node has no
- // associated LayoutObject.
- int VisitLayoutTreeNode(Node*, int node_index);
+ // Adds a LayoutTreeNode for the LayoutObject to |layout_tree_nodes_| and
+ // returns its index. Returns -1 if the Node has no associated LayoutObject.
+ // Associates LayoutObjects under a pseudo element with the element.
+ int VisitLayoutTreeNode(LayoutObject*, Node*, int node_index);
+ int BuildLayoutTreeNode(LayoutObject*, Node*, int node_index);
// Returns the index of the ComputedStyle in |computed_styles_| for the given
// Node. Adds a new ComputedStyle if necessary, but ensures no duplicates are
// added to |computed_styles_|. Returns -1 if the node has no values for
// styles in |style_whitelist_|.
int GetStyleIndexForNode(Node*);
+ std::unique_ptr<protocol::Array<int>> BuildStylesForNode(Node*);
// Traverses the PaintLayer tree in paint order to fill |paint_order_map_|.
void TraversePaintLayerTree(Document*);
@@ -116,6 +146,14 @@ class CORE_EXPORT InspectorDOMSnapshotAgent final
layout_tree_nodes_;
std::unique_ptr<protocol::Array<protocol::DOMSnapshot::ComputedStyle>>
computed_styles_;
+
+ std::unique_ptr<protocol::Array<String>> strings_;
+ WTF::HashMap<String, int> string_table_;
+
+ std::unique_ptr<protocol::Array<protocol::DOMSnapshot::DocumentSnapshot>>
+ documents_;
+ std::unique_ptr<protocol::DOMSnapshot::DocumentSnapshot> document_;
+
// Maps a style string vector to an index in |computed_styles_|. Used to avoid
// duplicate entries in |computed_styles_|.
std::unique_ptr<ComputedStylesMap> computed_styles_map_;
@@ -127,7 +165,8 @@ class CORE_EXPORT InspectorDOMSnapshotAgent final
// Maps a backend node id to the url of the script (if any) that generates
// the corresponding node.
std::unique_ptr<OriginUrlMap> origin_url_map_;
-
+ using DocumentOrderMap = HeapHashMap<Member<Document>, int>;
+ DocumentOrderMap document_order_map_;
Member<InspectedFrames> inspected_frames_;
Member<InspectorDOMDebuggerAgent> dom_debugger_agent_;
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 c2bb9382fe9..6f2867e6f16 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
@@ -18,6 +18,7 @@
#include "third_party/blink/renderer/platform/geometry/double_rect.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
+#include "third_party/blink/renderer/platform/network/network_utils.h"
#include "third_party/blink/renderer/platform/scheduler/util/thread_cpu_throttler.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
@@ -28,6 +29,8 @@ using protocol::Response;
namespace EmulationAgentState {
static const char kScriptExecutionDisabled[] = "scriptExecutionDisabled";
+static const char kScrollbarsHidden[] = "scrollbarsHidden";
+static const char kDocumentCookieDisabled[] = "documentCookieDisabled";
static const char kTouchEventEmulationEnabled[] = "touchEventEmulationEnabled";
static const char kMaxTouchPoints[] = "maxTouchPoints";
static const char kEmulatedMedia[] = "emulatedMedia";
@@ -43,6 +46,8 @@ static const char kVirtualTimePolicy[] = "virtualTimePolicy";
static const char kVirtualTimeTaskStarvationCount[] =
"virtualTimeTaskStarvationCount";
static const char kWaitForNavigation[] = "waitForNavigation";
+static const char kUserAgentOverride[] = "userAgentOverride";
+static const char kAcceptLanguageOverride[] = "acceptLanguage";
} // namespace EmulationAgentState
InspectorEmulationAgent::InspectorEmulationAgent(
@@ -52,12 +57,33 @@ InspectorEmulationAgent::InspectorEmulationAgent(
InspectorEmulationAgent::~InspectorEmulationAgent() = default;
WebViewImpl* InspectorEmulationAgent::GetWebViewImpl() {
- return web_local_frame_->ViewImpl();
+ return web_local_frame_ ? web_local_frame_->ViewImpl() : nullptr;
}
void InspectorEmulationAgent::Restore() {
- setScriptExecutionDisabled(state_->booleanProperty(
- EmulationAgentState::kScriptExecutionDisabled, false));
+ String user_agent;
+ state_->getString(EmulationAgentState::kUserAgentOverride, &user_agent);
+ String accept_language;
+ state_->getString(EmulationAgentState::kAcceptLanguageOverride,
+ &accept_language);
+ String navigator_platform;
+ state_->getString(EmulationAgentState::kNavigatorPlatform,
+ &navigator_platform);
+ setUserAgentOverride(user_agent, accept_language, navigator_platform);
+ if (!web_local_frame_)
+ return;
+
+ // Following code only runs for pages.
+ if (state_->booleanProperty(EmulationAgentState::kScriptExecutionDisabled,
+ false)) {
+ GetWebViewImpl()->GetDevToolsEmulator()->SetScriptExecutionDisabled(true);
+ }
+ if (state_->booleanProperty(EmulationAgentState::kScrollbarsHidden, false))
+ GetWebViewImpl()->GetDevToolsEmulator()->SetScrollbarsHidden(true);
+ if (state_->booleanProperty(EmulationAgentState::kDocumentCookieDisabled,
+ false)) {
+ GetWebViewImpl()->GetDevToolsEmulator()->SetDocumentCookieDisabled(true);
+ }
setTouchEmulationEnabled(
state_->booleanProperty(EmulationAgentState::kTouchEventEmulationEnabled,
false),
@@ -75,10 +101,6 @@ void InspectorEmulationAgent::Restore() {
Maybe<protocol::DOM::RGBA>(std::move(rgba)));
}
}
- String navigator_platform;
- state_->getString(EmulationAgentState::kNavigatorPlatform,
- &navigator_platform);
- setNavigatorOverrides(navigator_platform);
String virtual_time_policy;
if (state_->getString(EmulationAgentState::kVirtualTimePolicy,
@@ -137,39 +159,86 @@ void InspectorEmulationAgent::Restore() {
}
Response InspectorEmulationAgent::disable() {
+ if (enabled_)
+ instrumenting_agents_->removeInspectorEmulationAgent(this);
setScriptExecutionDisabled(false);
+ setScrollbarsHidden(false);
+ setDocumentCookieDisabled(false);
setTouchEmulationEnabled(false, Maybe<int>());
setEmulatedMedia(String());
setCPUThrottlingRate(1);
setDefaultBackgroundColorOverride(Maybe<protocol::DOM::RGBA>());
if (virtual_time_setup_) {
- instrumenting_agents_->removeInspectorEmulationAgent(this);
+ DCHECK(web_local_frame_);
web_local_frame_->View()->Scheduler()->RemoveVirtualTimeObserver(this);
virtual_time_setup_ = false;
}
- setNavigatorOverrides(String());
+ setUserAgentOverride(String(), protocol::Maybe<String>(),
+ protocol::Maybe<String>());
return Response::OK();
}
Response InspectorEmulationAgent::resetPageScaleFactor() {
+ Response response = AssertPage();
+ if (!response.isSuccess())
+ return response;
GetWebViewImpl()->ResetScaleStateImmediately();
- return Response::OK();
+ return response;
}
Response InspectorEmulationAgent::setPageScaleFactor(double page_scale_factor) {
+ Response response = AssertPage();
+ if (!response.isSuccess())
+ return response;
GetWebViewImpl()->SetPageScaleFactor(static_cast<float>(page_scale_factor));
- return Response::OK();
+ return response;
}
Response InspectorEmulationAgent::setScriptExecutionDisabled(bool value) {
+ Response response = AssertPage();
+ if (!response.isSuccess())
+ return response;
+ if (state_->booleanProperty(EmulationAgentState::kScriptExecutionDisabled,
+ false) == value) {
+ return response;
+ }
state_->setBoolean(EmulationAgentState::kScriptExecutionDisabled, value);
GetWebViewImpl()->GetDevToolsEmulator()->SetScriptExecutionDisabled(value);
- return Response::OK();
+ return response;
+}
+
+Response InspectorEmulationAgent::setScrollbarsHidden(bool hidden) {
+ Response response = AssertPage();
+ if (!response.isSuccess())
+ return response;
+ if (state_->booleanProperty(EmulationAgentState::kScrollbarsHidden, false) ==
+ hidden) {
+ return response;
+ }
+ state_->setBoolean(EmulationAgentState::kScrollbarsHidden, hidden);
+ GetWebViewImpl()->GetDevToolsEmulator()->SetScrollbarsHidden(hidden);
+ return response;
+}
+
+Response InspectorEmulationAgent::setDocumentCookieDisabled(bool disabled) {
+ Response response = AssertPage();
+ if (!response.isSuccess())
+ return response;
+ if (state_->booleanProperty(EmulationAgentState::kDocumentCookieDisabled,
+ false) == disabled) {
+ return response;
+ }
+ state_->setBoolean(EmulationAgentState::kDocumentCookieDisabled, disabled);
+ GetWebViewImpl()->GetDevToolsEmulator()->SetDocumentCookieDisabled(disabled);
+ return response;
}
Response InspectorEmulationAgent::setTouchEmulationEnabled(
bool enabled,
protocol::Maybe<int> max_touch_points) {
+ Response response = AssertPage();
+ if (!response.isSuccess())
+ return response;
int max_points = max_touch_points.fromMaybe(1);
if (max_points < 1 || max_points > WebTouchEvent::kTouchesLengthCap) {
return Response::InvalidParams(
@@ -180,18 +249,24 @@ Response InspectorEmulationAgent::setTouchEmulationEnabled(
state_->setInteger(EmulationAgentState::kMaxTouchPoints, max_points);
GetWebViewImpl()->GetDevToolsEmulator()->SetTouchEventEmulationEnabled(
enabled, max_points);
- return Response::OK();
+ return response;
}
Response InspectorEmulationAgent::setEmulatedMedia(const String& media) {
+ Response response = AssertPage();
+ if (!response.isSuccess())
+ return response;
state_->setString(EmulationAgentState::kEmulatedMedia, media);
GetWebViewImpl()->GetPage()->GetSettings().SetMediaTypeOverride(media);
- return Response::OK();
+ return response;
}
Response InspectorEmulationAgent::setCPUThrottlingRate(double rate) {
+ Response response = AssertPage();
+ if (!response.isSuccess())
+ return response;
scheduler::ThreadCPUThrottler::GetInstance()->SetThrottlingRate(rate);
- return Response::OK();
+ return response;
}
Response InspectorEmulationAgent::setVirtualTimePolicy(
@@ -201,6 +276,9 @@ Response InspectorEmulationAgent::setVirtualTimePolicy(
protocol::Maybe<bool> wait_for_navigation,
protocol::Maybe<double> initial_virtual_time,
double* virtual_time_ticks_base_ms) {
+ Response response = AssertPage();
+ if (!response.isSuccess())
+ return response;
state_->setString(EmulationAgentState::kVirtualTimePolicy, policy);
PendingVirtualTimePolicy new_policy;
@@ -248,8 +326,8 @@ Response InspectorEmulationAgent::setVirtualTimePolicy(
state_->remove(EmulationAgentState::kVirtualTimeTaskStarvationCount);
}
+ InnerEnable();
if (!virtual_time_setup_) {
- instrumenting_agents_->addInspectorEmulationAgent(this);
web_local_frame_->View()->Scheduler()->AddVirtualTimeObserver(this);
virtual_time_setup_ = true;
}
@@ -276,11 +354,12 @@ Response InspectorEmulationAgent::setVirtualTimePolicy(
(virtual_time_base_ticks_ - WTF::TimeTicks()).InMillisecondsF();
}
- return Response::OK();
+ return response;
}
void InspectorEmulationAgent::ApplyVirtualTimePolicy(
const PendingVirtualTimePolicy& new_policy) {
+ DCHECK(web_local_frame_);
web_local_frame_->View()->Scheduler()->SetVirtualTimePolicy(
new_policy.policy);
virtual_time_base_ticks_ =
@@ -301,7 +380,7 @@ void InspectorEmulationAgent::ApplyVirtualTimePolicy(
}
}
-void InspectorEmulationAgent::FrameStartedLoading(LocalFrame*, FrameLoadType) {
+void InspectorEmulationAgent::FrameStartedLoading(LocalFrame*) {
if (pending_virtual_time_policy_) {
state_->setBoolean(EmulationAgentState::kWaitForNavigation, false);
ApplyVirtualTimePolicy(*pending_virtual_time_policy_);
@@ -309,16 +388,40 @@ void InspectorEmulationAgent::FrameStartedLoading(LocalFrame*, FrameLoadType) {
}
}
+void InspectorEmulationAgent::WillSendRequest(
+ ExecutionContext* execution_context,
+ unsigned long identifier,
+ DocumentLoader* loader,
+ ResourceRequest& request,
+ const ResourceResponse& redirect_response,
+ const FetchInitiatorInfo& initiator_info,
+ Resource::Type resource_type) {
+ String accept_lang_override;
+ state_->getString(EmulationAgentState::kAcceptLanguageOverride,
+ &accept_lang_override);
+ if (!accept_lang_override.IsEmpty() &&
+ request.HttpHeaderField("Accept-Language").IsEmpty()) {
+ request.SetHTTPHeaderField(
+ "Accept-Language",
+ AtomicString(
+ NetworkUtils::GenerateAcceptLanguageHeader(accept_lang_override)));
+ }
+}
+
Response InspectorEmulationAgent::setNavigatorOverrides(
const String& platform) {
+ Response response = AssertPage();
+ if (!response.isSuccess())
+ return response;
state_->setString(EmulationAgentState::kNavigatorPlatform, platform);
GetWebViewImpl()->GetPage()->GetSettings().SetNavigatorPlatformOverride(
platform);
- return Response::OK();
+ return response;
}
void InspectorEmulationAgent::VirtualTimeBudgetExpired() {
TRACE_EVENT_ASYNC_END0("renderer.scheduler", "VirtualTimeBudget", this);
+ DCHECK(web_local_frame_);
web_local_frame_->View()->Scheduler()->SetVirtualTimePolicy(
PageScheduler::VirtualTimePolicy::kPause);
state_->setString(EmulationAgentState::kVirtualTimePolicy,
@@ -342,6 +445,9 @@ void InspectorEmulationAgent::OnVirtualTimePaused(
Response InspectorEmulationAgent::setDefaultBackgroundColorOverride(
Maybe<protocol::DOM::RGBA> color) {
+ Response response = AssertPage();
+ if (!response.isSuccess())
+ return response;
if (!color.isJust()) {
// Clear the override and state.
GetWebViewImpl()->ClearBaseBackgroundColorOverride();
@@ -375,13 +481,63 @@ Response InspectorEmulationAgent::setDeviceMetricsOverride(
// We don't have to do anything other than reply to the client, as the
// emulation parameters should have already been updated by the handling of
// ViewMsg_EnableDeviceEmulation.
- return Response::OK();
+ return AssertPage();
}
Response InspectorEmulationAgent::clearDeviceMetricsOverride() {
// We don't have to do anything other than reply to the client, as the
// emulation parameters should have already been cleared by the handling of
// ViewMsg_DisableDeviceEmulation.
+ return AssertPage();
+}
+
+Response InspectorEmulationAgent::setUserAgentOverride(
+ const String& user_agent,
+ protocol::Maybe<String> accept_language,
+ protocol::Maybe<String> platform) {
+ if (!user_agent.IsEmpty() || accept_language.isJust() || platform.isJust())
+ InnerEnable();
+ state_->setString(EmulationAgentState::kUserAgentOverride, user_agent);
+ state_->setString(EmulationAgentState::kAcceptLanguageOverride,
+ accept_language.fromMaybe(String()));
+ state_->setString(EmulationAgentState::kNavigatorPlatform,
+ platform.fromMaybe(String()));
+ if (web_local_frame_) {
+ GetWebViewImpl()->GetPage()->GetSettings().SetNavigatorPlatformOverride(
+ platform.fromMaybe(String()));
+ }
+ return Response::OK();
+}
+
+void InspectorEmulationAgent::ApplyAcceptLanguageOverride(String* accept_lang) {
+ String accept_lang_override;
+ state_->getString(EmulationAgentState::kAcceptLanguageOverride,
+ &accept_lang_override);
+ if (!accept_lang_override.IsEmpty())
+ *accept_lang = accept_lang_override;
+}
+
+void InspectorEmulationAgent::ApplyUserAgentOverride(String* user_agent) {
+ String user_agent_override;
+ state_->getString(EmulationAgentState::kUserAgentOverride,
+ &user_agent_override);
+ if (!user_agent_override.IsEmpty())
+ *user_agent = user_agent_override;
+}
+
+void InspectorEmulationAgent::InnerEnable() {
+ if (enabled_)
+ return;
+ enabled_ = true;
+ instrumenting_agents_->addInspectorEmulationAgent(this);
+}
+
+Response InspectorEmulationAgent::AssertPage() {
+ if (!web_local_frame_) {
+ LOG(ERROR) << "Can only enable virtual time for pages, not workers";
+ return Response::InvalidParams(
+ "Can only enable virtual time for pages, not workers");
+ }
return Response::OK();
}
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 bec8867c1f6..1688b5747d4 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
@@ -11,13 +11,19 @@
#include "third_party/blink/renderer/core/inspector/inspector_base_agent.h"
#include "third_party/blink/renderer/core/inspector/protocol/Emulation.h"
#include "third_party/blink/renderer/core/loader/frame_loader_types.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/scheduler/public/page_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink {
+class DocumentLoader;
+class ExecutionContext;
+class ResourceRequest;
+class ResourceResponse;
class WebLocalFrameImpl;
class WebViewImpl;
+struct FetchInitiatorInfo;
namespace protocol {
namespace DOM {
@@ -36,6 +42,8 @@ class CORE_EXPORT InspectorEmulationAgent final
protocol::Response resetPageScaleFactor() override;
protocol::Response setPageScaleFactor(double) override;
protocol::Response setScriptExecutionDisabled(bool value) override;
+ protocol::Response setScrollbarsHidden(bool hidden) override;
+ protocol::Response setDocumentCookieDisabled(bool disabled) override;
protocol::Response setTouchEmulationEnabled(
bool enabled,
protocol::Maybe<int> max_touch_points) override;
@@ -65,9 +73,22 @@ class CORE_EXPORT InspectorEmulationAgent final
protocol::Maybe<protocol::Emulation::ScreenOrientation>,
protocol::Maybe<protocol::Page::Viewport>) override;
protocol::Response clearDeviceMetricsOverride() override;
+ protocol::Response setUserAgentOverride(
+ const String& user_agent,
+ protocol::Maybe<String> accept_language,
+ protocol::Maybe<String> platform) override;
// InspectorInstrumentation API
- void FrameStartedLoading(LocalFrame*, FrameLoadType);
+ void ApplyAcceptLanguageOverride(String* accept_lang);
+ void ApplyUserAgentOverride(String* user_agent);
+ void FrameStartedLoading(LocalFrame*);
+ void WillSendRequest(ExecutionContext*,
+ unsigned long identifier,
+ DocumentLoader*,
+ ResourceRequest&,
+ const ResourceResponse& redirect_response,
+ const FetchInitiatorInfo&,
+ Resource::Type);
// InspectorBaseAgent overrides.
protocol::Response disable() override;
@@ -81,7 +102,9 @@ class CORE_EXPORT InspectorEmulationAgent final
private:
WebViewImpl* GetWebViewImpl();
+ protocol::Response AssertPage();
void VirtualTimeBudgetExpired();
+ void InnerEnable();
struct PendingVirtualTimePolicy {
PageScheduler::VirtualTimePolicy policy;
@@ -97,6 +120,7 @@ class CORE_EXPORT InspectorEmulationAgent final
// Supports a virtual time policy change scheduled to occur after any
// navigation has started.
base::Optional<PendingVirtualTimePolicy> pending_virtual_time_policy_;
+ bool enabled_ = false;
DISALLOW_COPY_AND_ASSIGN(InspectorEmulationAgent);
};
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 4d319c9667b..71a3169d516 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.cc
@@ -117,8 +117,8 @@ class ShapePathBuilder : public PathBuilder {
FloatPoint TranslatePoint(const FloatPoint& point) override {
FloatPoint layout_object_point =
shape_outside_info_.ShapeToLayoutObjectPoint(point);
- return view_->ContentsToViewport(
- RoundedIntPoint(layout_object_.LocalToAbsolute(layout_object_point)));
+ return FloatPoint(view_->FrameToViewport(
+ RoundedIntPoint(layout_object_.LocalToAbsolute(layout_object_point))));
}
private:
@@ -152,21 +152,18 @@ Path QuadToPath(const FloatQuad& quad) {
return quad_path;
}
-FloatPoint ContentsPointToViewport(const LocalFrameView* view,
- FloatPoint point_in_contents) {
- LayoutPoint point_in_frame =
- view->ContentsToFrame(LayoutPoint(point_in_contents));
- FloatPoint point_in_root_frame =
- FloatPoint(view->ConvertToRootFrame(point_in_frame));
- return FloatPoint(view->GetPage()->GetVisualViewport().RootFrameToViewport(
- point_in_root_frame));
+FloatPoint FramePointToViewport(const LocalFrameView* view,
+ FloatPoint point_in_frame) {
+ FloatPoint point_in_root_frame = view->ConvertToRootFrame(point_in_frame);
+ return view->GetPage()->GetVisualViewport().RootFrameToViewport(
+ point_in_root_frame);
}
-void ContentsQuadToViewport(const LocalFrameView* view, FloatQuad& quad) {
- quad.SetP1(ContentsPointToViewport(view, quad.P1()));
- quad.SetP2(ContentsPointToViewport(view, quad.P2()));
- quad.SetP3(ContentsPointToViewport(view, quad.P3()));
- quad.SetP4(ContentsPointToViewport(view, quad.P4()));
+void FrameQuadToViewport(const LocalFrameView* view, FloatQuad& quad) {
+ quad.SetP1(FramePointToViewport(view, quad.P1()));
+ quad.SetP2(FramePointToViewport(view, quad.P2()));
+ quad.SetP3(FramePointToViewport(view, quad.P3()));
+ quad.SetP4(FramePointToViewport(view, quad.P4()));
}
const ShapeOutsideInfo* ShapeOutsideInfoForNode(Node* node,
@@ -187,7 +184,7 @@ const ShapeOutsideInfo* ShapeOutsideInfoForNode(Node* node,
LayoutRect shape_bounds =
shape_outside_info->ComputedShapePhysicalBoundingBox();
*bounds = layout_box->LocalToAbsoluteQuad(FloatRect(shape_bounds));
- ContentsQuadToViewport(containing_view, *bounds);
+ FrameQuadToViewport(containing_view, *bounds);
return shape_outside_info;
}
@@ -287,6 +284,36 @@ std::unique_ptr<protocol::DictionaryValue> BuildGridInfo(
return grid_info;
}
+void CollectQuadsRecursive(Node* node, Vector<FloatQuad>& out_quads) {
+ LayoutObject* layout_object = node->GetLayoutObject();
+ if (!layout_object)
+ return;
+
+ // For inline elements, absoluteQuads will return a line box based on the
+ // line-height and font metrics, which is technically incorrect as replaced
+ // elements like images should use their intristic height and expand the
+ // linebox as needed. To get an appropriate quads we descend
+ // into the children and have them add their boxes.
+ if (layout_object->IsLayoutInline()) {
+ for (Node* child = LayoutTreeBuilderTraversal::FirstChild(*node); child;
+ child = LayoutTreeBuilderTraversal::NextSibling(*child))
+ CollectQuadsRecursive(child, out_quads);
+ } else {
+ layout_object->AbsoluteQuads(out_quads);
+ }
+}
+
+void CollectQuads(Node* node, Vector<FloatQuad>& out_quads) {
+ CollectQuadsRecursive(node, out_quads);
+ LocalFrameView* containing_view =
+ node->GetLayoutObject() ? node->GetLayoutObject()->GetFrameView()
+ : nullptr;
+ if (containing_view) {
+ for (FloatQuad& quad : out_quads)
+ FrameQuadToViewport(containing_view, quad);
+ }
+}
+
} // namespace
InspectorHighlight::InspectorHighlight(float scale)
@@ -391,17 +418,10 @@ void InspectorHighlight::AppendNodeHighlight(
if (!layout_object)
return;
- // LayoutSVGRoot should be highlighted through the isBox() code path, all
- // other SVG elements should just dump their absoluteQuads().
- if (layout_object->GetNode() && layout_object->GetNode()->IsSVGElement() &&
- !layout_object->IsSVGRoot()) {
- Vector<FloatQuad> quads;
- layout_object->AbsoluteQuads(quads);
- LocalFrameView* containing_view = layout_object->GetFrameView();
- for (size_t i = 0; i < quads.size(); ++i) {
- if (containing_view)
- ContentsQuadToViewport(containing_view, quads[i]);
- AppendQuad(quads[i], highlight_config.content,
+ Vector<FloatQuad> svg_quads;
+ if (BuildSVGQuads(node, svg_quads)) {
+ for (size_t i = 0; i < svg_quads.size(); ++i) {
+ AppendQuad(svg_quads[i], highlight_config.content,
highlight_config.content_outline);
}
return;
@@ -460,8 +480,17 @@ bool InspectorHighlight::GetBoxModel(
return false;
FloatQuad content, padding, border, margin;
- if (!BuildNodeQuads(node, &content, &padding, &border, &margin))
+ Vector<FloatQuad> svg_quads;
+ if (BuildSVGQuads(node, svg_quads)) {
+ if (!svg_quads.size())
+ return false;
+ content = svg_quads[0];
+ padding = svg_quads[0];
+ border = svg_quads[0];
+ margin = svg_quads[0];
+ } else if (!BuildNodeQuads(node, &content, &padding, &border, &margin)) {
return false;
+ }
AdjustForAbsoluteZoom::AdjustFloatQuad(content, *layout_object);
AdjustForAbsoluteZoom::AdjustFloatQuad(padding, *layout_object);
@@ -475,7 +504,7 @@ bool InspectorHighlight::GetBoxModel(
margin.Scale(scale, scale);
IntRect bounding_box =
- view->ContentsToRootFrame(layout_object->AbsoluteBoundingBoxRect());
+ view->ConvertToRootFrame(layout_object->AbsoluteBoundingBoxRect());
LayoutBoxModelObject* model_object =
layout_object->IsBoxModelObject() ? ToLayoutBoxModelObject(layout_object)
: nullptr;
@@ -524,6 +553,40 @@ bool InspectorHighlight::GetBoxModel(
return true;
}
+// static
+bool InspectorHighlight::BuildSVGQuads(Node* node, Vector<FloatQuad>& quads) {
+ LayoutObject* layout_object = node->GetLayoutObject();
+ if (!layout_object)
+ return false;
+ if (!layout_object->GetNode() || !layout_object->GetNode()->IsSVGElement() ||
+ layout_object->IsSVGRoot())
+ return false;
+ CollectQuads(node, quads);
+ return true;
+}
+
+// static
+bool InspectorHighlight::GetContentQuads(
+ Node* node,
+ std::unique_ptr<protocol::Array<protocol::Array<double>>>* result) {
+ LayoutObject* layout_object = node->GetLayoutObject();
+ LocalFrameView* view = node->GetDocument().View();
+ if (!layout_object || !view)
+ return false;
+ Vector<FloatQuad> quads;
+ CollectQuads(node, quads);
+ float scale = 1 / view->GetPage()->GetVisualViewport().Scale();
+ for (FloatQuad& quad : quads) {
+ AdjustForAbsoluteZoom::AdjustFloatQuad(quad, *layout_object);
+ quad.Scale(scale, scale);
+ }
+
+ result->reset(new protocol::Array<protocol::Array<double>>());
+ for (FloatQuad& quad : quads)
+ (*result)->addItem(BuildArrayForQuad(quad));
+ return true;
+}
+
bool InspectorHighlight::BuildNodeQuads(Node* node,
FloatQuad* content,
FloatQuad* padding,
@@ -597,10 +660,10 @@ bool InspectorHighlight::BuildNodeQuads(Node* node,
*border = layout_object->LocalToAbsoluteQuad(FloatRect(border_box));
*margin = layout_object->LocalToAbsoluteQuad(FloatRect(margin_box));
- ContentsQuadToViewport(containing_view, *content);
- ContentsQuadToViewport(containing_view, *padding);
- ContentsQuadToViewport(containing_view, *border);
- ContentsQuadToViewport(containing_view, *margin);
+ FrameQuadToViewport(containing_view, *content);
+ FrameQuadToViewport(containing_view, *padding);
+ FrameQuadToViewport(containing_view, *border);
+ FrameQuadToViewport(containing_view, *margin);
return true;
}
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 669ce652bda..94cb9ad708f 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_highlight.h
@@ -51,12 +51,10 @@ class CORE_EXPORT InspectorHighlight {
~InspectorHighlight();
static bool GetBoxModel(Node*, std::unique_ptr<protocol::DOM::BoxModel>*);
+ static bool GetContentQuads(
+ Node*,
+ std::unique_ptr<protocol::Array<protocol::Array<double>>>*);
static InspectorHighlightConfig DefaultConfig();
- static bool BuildNodeQuads(Node*,
- FloatQuad* content,
- FloatQuad* padding,
- FloatQuad* border,
- FloatQuad* margin);
void AppendPath(std::unique_ptr<protocol::ListValue> path,
const Color& fill_color,
@@ -71,6 +69,12 @@ class CORE_EXPORT InspectorHighlight {
std::unique_ptr<protocol::DictionaryValue> AsProtocolValue() const;
private:
+ static bool BuildSVGQuads(Node*, Vector<FloatQuad>& quads);
+ static bool BuildNodeQuads(Node*,
+ FloatQuad* content,
+ FloatQuad* padding,
+ FloatQuad* border,
+ FloatQuad* margin);
void AppendNodeHighlight(Node*, const InspectorHighlightConfig&);
void AppendPathsForShapeOutside(Node*, const InspectorHighlightConfig&);
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_history.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_history.cc
index fc26f47a7cd..92094437a39 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_history.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_history.cc
@@ -30,8 +30,8 @@
#include "third_party/blink/renderer/core/inspector/inspector_history.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/node.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.cc
index 287f661f0d8..8b58a482463 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.cc
@@ -34,6 +34,7 @@
#include <memory>
#include "cc/base/region.h"
+#include "cc/layers/picture_layer.h"
#include "third_party/blink/public/platform/web_float_point.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
@@ -49,6 +50,7 @@
#include "third_party/blink/renderer/core/page/page.h"
#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/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/graphics/compositing_reasons.h"
#include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
@@ -303,16 +305,14 @@ InspectorLayerTreeAgent::BuildLayerTree() {
std::unique_ptr<Array<protocol::LayerTree::Layer>> layers =
Array<protocol::LayerTree::Layer>::create();
BuildLayerIdToNodeIdMap(compositor->RootLayer(), layer_id_to_node_id_map);
- auto* layer_for_scrolling = inspected_frames_->Root()
- ->View()
- ->LayoutViewportScrollableArea()
- ->LayerForScrolling();
+ auto* layer_for_scrolling =
+ inspected_frames_->Root()->View()->LayoutViewport()->LayerForScrolling();
int scrolling_layer_id =
layer_for_scrolling ? layer_for_scrolling->CcLayer()->id() : 0;
bool have_blocking_wheel_event_handlers =
inspected_frames_->Root()->GetChromeClient().EventListenerProperties(
- inspected_frames_->Root(), WebEventListenerClass::kMouseWheel) ==
- WebEventListenerProperties::kBlocking;
+ inspected_frames_->Root(), cc::EventListenerClass::kMouseWheel) ==
+ cc::EventListenerProperties::kBlocking;
GatherGraphicsLayers(RootGraphicsLayer(), layer_id_to_node_id_map, layers,
have_blocking_wheel_event_handlers, scrolling_layer_id);
@@ -434,8 +434,7 @@ Response InspectorLayerTreeAgent::makeSnapshot(const String& layer_id,
if (!layer->DrawsContent())
return Response::Error("Layer does not draw content");
- IntSize size = ExpandedIntSize(layer->Size());
- IntRect interest_rect(IntPoint(0, 0), size);
+ IntRect interest_rect(IntPoint(), layer->Size());
suppress_layer_paint_events_ = true;
// If we hit a devtool break point in the middle of document lifecycle, for
@@ -523,14 +522,15 @@ Response InspectorLayerTreeAgent::replaySnapshot(const String& snapshot_id,
Response response = GetSnapshotById(snapshot_id, snapshot);
if (!response.isSuccess())
return response;
- std::unique_ptr<Vector<char>> base64_data = snapshot->Replay(
+ Vector<char> base64_data = snapshot->Replay(
from_step.fromMaybe(0), to_step.fromMaybe(0), scale.fromMaybe(1.0));
- if (!base64_data)
+ if (base64_data.IsEmpty())
return Response::Error("Image encoding failed");
+ static constexpr char kUrlPrefix[] = "data:image/png;base64,";
StringBuilder url;
- url.Append("data:image/png;base64,");
- url.ReserveCapacity(url.length() + base64_data->size());
- url.Append(base64_data->begin(), base64_data->size());
+ url.ReserveCapacity(sizeof(kUrlPrefix) + base64_data.size());
+ url.Append(kUrlPrefix);
+ url.Append(base64_data.begin(), base64_data.size());
*data_url = url.ToString();
return Response::OK();
}
@@ -553,15 +553,15 @@ Response InspectorLayerTreeAgent::profileSnapshot(
FloatRect rect;
if (clip_rect.isJust())
ParseRect(clip_rect.fromJust(), &rect);
- std::unique_ptr<PictureSnapshot::Timings> timings = snapshot->Profile(
- min_repeat_count.fromMaybe(1), min_duration.fromMaybe(0),
- clip_rect.isJust() ? &rect : nullptr);
+ auto timings =
+ snapshot->Profile(min_repeat_count.fromMaybe(1),
+ TimeDelta::FromSecondsD(min_duration.fromMaybe(0)),
+ clip_rect.isJust() ? &rect : nullptr);
*out_timings = Array<Array<double>>::create();
- for (size_t i = 0; i < timings->size(); ++i) {
- const Vector<double>& row = (*timings)[i];
+ for (const auto& row : timings) {
std::unique_ptr<Array<double>> out_row = Array<double>::create();
- for (size_t j = 0; j < row.size(); ++j)
- out_row->addItem(row[j]);
+ for (TimeDelta delta : row)
+ out_row->addItem(delta.InSecondsF());
(*out_timings)->addItem(std::move(out_row));
}
return Response::OK();
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_log_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_log_agent.cc
index 5ffd0907a74..b9df4c5d20a 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_log_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_log_agent.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/inspector/inspector_log_agent.h"
+#include "base/format_macros.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/core/frame/performance_monitor.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
@@ -233,7 +234,9 @@ Response InspectorLogAgent::startViolationsReport(
if (violation == PerformanceMonitor::kAfterLast)
continue;
performance_monitor_->Subscribe(
- violation, settings->get(i)->getThreshold() / 1000, this);
+ violation,
+ base::TimeDelta::FromMillisecondsD(settings->get(i)->getThreshold()),
+ this);
}
return Response::OK();
}
@@ -246,10 +249,10 @@ Response InspectorLogAgent::stopViolationsReport() {
return Response::OK();
}
-void InspectorLogAgent::ReportLongLayout(double duration) {
- String message_text =
- String::Format("Forced reflow while executing JavaScript took %ldms",
- lround(duration * 1000));
+void InspectorLogAgent::ReportLongLayout(base::TimeDelta duration) {
+ String message_text = String::Format(
+ "Forced reflow while executing JavaScript took %" PRId64 "ms",
+ duration.InMilliseconds());
ConsoleMessage* message = ConsoleMessage::Create(
kViolationMessageSource, kVerboseMessageLevel, message_text);
ConsoleMessageAdded(message);
@@ -257,7 +260,7 @@ void InspectorLogAgent::ReportLongLayout(double duration) {
void InspectorLogAgent::ReportGenericViolation(PerformanceMonitor::Violation,
const String& text,
- double time,
+ base::TimeDelta time,
SourceLocation* location) {
ConsoleMessage* message = ConsoleMessage::Create(
kViolationMessageSource, kVerboseMessageLevel, text, location->Clone());
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_log_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_log_agent.h
index 8bfb0cce677..5ff38f0ca4b 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_log_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_log_agent.h
@@ -48,10 +48,10 @@ class CORE_EXPORT InspectorLogAgent
private:
// PerformanceMonitor::Client implementation.
- void ReportLongLayout(double duration) override;
+ void ReportLongLayout(base::TimeDelta duration) override;
void ReportGenericViolation(PerformanceMonitor::Violation,
const String& text,
- double time,
+ base::TimeDelta time,
SourceLocation*) override;
bool enabled_;
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 9ca967d0459..15aa529a806 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
@@ -37,12 +37,12 @@
#include "base/memory/scoped_refptr.h"
#include "build/build_config.h"
#include "services/network/public/mojom/request_context_frame_type.mojom-shared.h"
+#include "services/network/public/mojom/websocket.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_effective_connection_type.h"
#include "third_party/blink/public/platform/web_mixed_content_context_type.h"
#include "third_party/blink/public/platform/web_url_loader_client.h"
#include "third_party/blink/public/platform/web_url_request.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/scriptable_document_parser.h"
@@ -61,6 +61,7 @@
#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/xmlhttprequest/xml_http_request.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_info.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
@@ -74,8 +75,6 @@
#include "third_party/blink/renderer/platform/loader/fetch/unique_identifier.h"
#include "third_party/blink/renderer/platform/network/http_header_map.h"
#include "third_party/blink/renderer/platform/network/network_state_notifier.h"
-#include "third_party/blink/renderer/platform/network/web_socket_handshake_request.h"
-#include "third_party/blink/renderer/platform/network/web_socket_handshake_response.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/weborigin/referrer_policy.h"
@@ -96,7 +95,6 @@ static const char kNetworkAgentEnabled[] = "networkAgentEnabled";
static const char kExtraRequestHeaders[] = "extraRequestHeaders";
static const char kCacheDisabled[] = "cacheDisabled";
static const char kBypassServiceWorker[] = "bypassServiceWorker";
-static const char kUserAgentOverride[] = "userAgentOverride";
static const char kBlockedURLs[] = "blockedURLs";
static const char kTotalBufferSize[] = "totalBufferSize";
static const char kResourceBufferSize[] = "resourceBufferSize";
@@ -363,6 +361,8 @@ String BuildBlockedReason(ResourceRequestBlockedReason reason) {
return protocol::Network::BlockedReasonEnum::ContentType;
case ResourceRequestBlockedReason::kOther:
return protocol::Network::BlockedReasonEnum::Other;
+ case ResourceRequestBlockedReason::kCollapsedByClient:
+ return protocol::Network::BlockedReasonEnum::CollapsedByClient;
}
NOTREACHED();
return protocol::Network::BlockedReasonEnum::Other;
@@ -488,14 +488,17 @@ BuildObjectForResourceRequest(const ResourceRequest& request,
String postData;
bool hasPostData =
FormDataToString(request.HttpBody(), max_body_size, &postData);
+ KURL url = request.Url();
std::unique_ptr<protocol::Network::Request> result =
protocol::Network::Request::create()
- .setUrl(UrlWithoutFragment(request.Url()).GetString())
+ .setUrl(UrlWithoutFragment(url).GetString())
.setMethod(request.HttpMethod())
.setHeaders(BuildObjectForHeaders(request.HttpHeaderFields()))
.setInitialPriority(ResourcePriorityJSON(request.Priority()))
.setReferrerPolicy(GetReferrerPolicy(request.GetReferrerPolicy()))
.build();
+ if (url.FragmentIdentifier())
+ result->setUrlFragment("#" + url.FragmentIdentifier());
if (!postData.IsEmpty())
result->setPostData(postData);
if (hasPostData)
@@ -774,7 +777,8 @@ void InspectorNetworkAgent::WillSendRequestInternal(
if (initiator_info.name == FetchInitiatorTypeNames::xmlhttprequest)
type = InspectorPageAgent::kXHRResource;
- resources_data_->SetResourceType(request_id, type);
+ resources_data_->SetResourceType(
+ request_id, pending_request_ ? pending_request_type_ : type);
if (is_navigation)
return;
@@ -817,8 +821,15 @@ void InspectorNetworkAgent::WillSendRequestInternal(
CurrentTimeTicksInSeconds(), CurrentTime(), std::move(initiator_object),
BuildObjectForResourceResponse(redirect_response), resource_type,
std::move(maybe_frame_id), request.HasUserGesture());
- if (pending_xhr_replay_data_ && !pending_xhr_replay_data_->Async())
- GetFrontend()->flush();
+
+ if (pending_xhr_replay_data_) {
+ resources_data_->SetXHRReplayData(request_id,
+ pending_xhr_replay_data_.Get());
+ if (!pending_xhr_replay_data_->Async())
+ GetFrontend()->flush();
+ pending_xhr_replay_data_.Clear();
+ }
+ pending_request_ = nullptr;
}
void InspectorNetworkAgent::WillSendRequest(
@@ -857,6 +868,8 @@ void InspectorNetworkAgent::WillSendRequest(
request.SetReportRawHeaders(true);
+ request.SetDevToolsToken(devtools_token_);
+
if (state_->booleanProperty(NetworkAgentState::kCacheDisabled, false)) {
if (LoadsFromCacheOnly(request) &&
request.GetRequestContext() != WebURLRequest::kRequestContextInternal) {
@@ -874,12 +887,6 @@ void InspectorNetworkAgent::WillSendRequest(
WillSendRequestInternal(execution_context, identifier, loader, request,
redirect_response, initiator_info, type);
-
- if (!conditions_token_.IsEmpty()) {
- request.AddHTTPHeaderField(
- HTTPNames::X_DevTools_Emulate_Network_Conditions_Client_Id,
- AtomicString(conditions_token_));
- }
}
void InspectorNetworkAgent::MarkResourceAsCached(DocumentLoader* loader,
@@ -1005,7 +1012,7 @@ void InspectorNetworkAgent::DidFinishLoading(unsigned long identifier,
TimeTicks monotonic_finish_time,
int64_t encoded_data_length,
int64_t decoded_body_length,
- bool blocked_cross_site_document) {
+ bool should_report_corb_blocking) {
String request_id = IdentifiersFactory::RequestId(loader, identifier);
NetworkResourcesData::ResourceData const* resource_data =
resources_data_->Data(request_id);
@@ -1032,7 +1039,7 @@ void InspectorNetworkAgent::DidFinishLoading(unsigned long identifier,
// TODO(npm): Use TimeTicks in Network.h.
GetFrontend()->loadingFinished(
request_id, TimeTicksInSeconds(monotonic_finish_time),
- encoded_data_length, blocked_cross_site_document);
+ encoded_data_length, should_report_corb_blocking);
}
void InspectorNetworkAgent::DidReceiveCORSRedirectResponse(
@@ -1077,51 +1084,12 @@ void InspectorNetworkAgent::DidReceiveScriptResponse(unsigned long identifier) {
InspectorPageAgent::kScriptResource);
}
-void InspectorNetworkAgent::ClearPendingRequestData() {
- if (pending_request_type_ == InspectorPageAgent::kXHRResource)
- pending_xhr_replay_data_.Clear();
- pending_request_ = nullptr;
-}
-
// static
bool InspectorNetworkAgent::IsNavigation(DocumentLoader* loader,
unsigned long identifier) {
return loader && loader->MainResourceIdentifier() == identifier;
}
-void InspectorNetworkAgent::DocumentThreadableLoaderStartedLoadingForClient(
- unsigned long identifier,
- ThreadableLoaderClient* client) {
- if (!client)
- return;
- if (client != pending_request_) {
- DCHECK(!pending_request_);
- return;
- }
-
- String request_id = IdentifiersFactory::SubresourceRequestId(identifier);
- resources_data_->SetResourceType(request_id, pending_request_type_);
- if (pending_request_type_ == InspectorPageAgent::kXHRResource) {
- resources_data_->SetXHRReplayData(request_id,
- pending_xhr_replay_data_.Get());
- }
-
- ClearPendingRequestData();
-}
-
-void InspectorNetworkAgent::
- DocumentThreadableLoaderFailedToStartLoadingForClient(
- ThreadableLoaderClient* client) {
- if (!client)
- return;
- if (client != pending_request_) {
- DCHECK(!pending_request_);
- return;
- }
-
- ClearPendingRequestData();
-}
-
void InspectorNetworkAgent::WillLoadXHR(XMLHttpRequest* xhr,
ThreadableLoaderClient* client,
const AtomicString& method,
@@ -1139,7 +1107,9 @@ void InspectorNetworkAgent::WillLoadXHR(XMLHttpRequest* xhr,
pending_xhr_replay_data_->AddHeader(header.key, header.value);
}
-void InspectorNetworkAgent::DelayedRemoveReplayXHR(XMLHttpRequest* xhr) {
+void InspectorNetworkAgent::DidFinishXHR(XMLHttpRequest* xhr) {
+ // This method will be called from the XHR.
+ // We delay deleting the replay XHR, as deleting here may delete the caller.
if (!replay_xhrs_.Contains(xhr))
return;
replay_xhrs_to_be_deleted_.insert(xhr);
@@ -1147,35 +1117,6 @@ void InspectorNetworkAgent::DelayedRemoveReplayXHR(XMLHttpRequest* xhr) {
remove_finished_replay_xhr_timer_.StartOneShot(TimeDelta(), FROM_HERE);
}
-void InspectorNetworkAgent::DidFailXHRLoading(ExecutionContext* context,
- XMLHttpRequest* xhr,
- ThreadableLoaderClient* client,
- const AtomicString& method,
- const String& url) {
- DidFinishXHRInternal(context, xhr, client, method, url, false);
-}
-
-void InspectorNetworkAgent::DidFinishXHRLoading(ExecutionContext* context,
- XMLHttpRequest* xhr,
- ThreadableLoaderClient* client,
- const AtomicString& method,
- const String& url) {
- DidFinishXHRInternal(context, xhr, client, method, url, true);
-}
-
-void InspectorNetworkAgent::DidFinishXHRInternal(ExecutionContext* context,
- XMLHttpRequest* xhr,
- ThreadableLoaderClient* client,
- const AtomicString& method,
- const String& url,
- bool success) {
- ClearPendingRequestData();
-
- // This method will be called from the XHR.
- // We delay deleting the replay XHR, as deleting here may delete the caller.
- DelayedRemoveReplayXHR(xhr);
-}
-
void InspectorNetworkAgent::WillStartFetch(ThreadableLoaderClient* client) {
DCHECK(!pending_request_);
pending_request_ = client;
@@ -1200,32 +1141,6 @@ void InspectorNetworkAgent::WillDispatchEventSourceEvent(
data);
}
-void InspectorNetworkAgent::DidFinishEventSourceRequest(
- ThreadableLoaderClient* event_source) {
- ClearPendingRequestData();
-}
-
-void InspectorNetworkAgent::DetachClientRequest(
- ThreadableLoaderClient* client) {
- // This method is called by loader clients when finalizing
- // (i.e., from their "prefinalizers".) The client reference must
- // no longer be held onto upon completion.
- if (pending_request_ == client) {
- pending_request_ = nullptr;
- if (pending_request_type_ == InspectorPageAgent::kXHRResource) {
- pending_xhr_replay_data_.Clear();
- }
- }
-}
-
-void InspectorNetworkAgent::ApplyUserAgentOverride(String* user_agent) {
- String user_agent_override;
- state_->getString(NetworkAgentState::kUserAgentOverride,
- &user_agent_override);
- if (!user_agent_override.IsEmpty())
- *user_agent = user_agent_override;
-}
-
std::unique_ptr<protocol::Network::Initiator>
InspectorNetworkAgent::BuildInitiatorObject(
Document* document,
@@ -1304,11 +1219,14 @@ void InspectorNetworkAgent::DidCreateWebSocket(
void InspectorNetworkAgent::WillSendWebSocketHandshakeRequest(
ExecutionContext*,
unsigned long identifier,
- const WebSocketHandshakeRequest* request) {
+ network::mojom::blink::WebSocketHandshakeRequest* request) {
DCHECK(request);
+ HTTPHeaderMap headers;
+ for (auto& header : request->headers)
+ headers.Add(AtomicString(header->name), AtomicString(header->value));
std::unique_ptr<protocol::Network::WebSocketRequest> request_object =
protocol::Network::WebSocketRequest::create()
- .setHeaders(BuildObjectForHeaders(request->HeaderFields()))
+ .setHeaders(BuildObjectForHeaders(headers))
.build();
GetFrontend()->webSocketWillSendHandshakeRequest(
IdentifiersFactory::SubresourceRequestId(identifier),
@@ -1318,24 +1236,41 @@ void InspectorNetworkAgent::WillSendWebSocketHandshakeRequest(
void InspectorNetworkAgent::DidReceiveWebSocketHandshakeResponse(
ExecutionContext*,
unsigned long identifier,
- const WebSocketHandshakeRequest* request,
- const WebSocketHandshakeResponse* response) {
+ network::mojom::blink::WebSocketHandshakeRequest* request,
+ network::mojom::blink::WebSocketHandshakeResponse* response) {
DCHECK(response);
+
+ HTTPHeaderMap response_headers;
+ for (auto& header : response->headers) {
+ HTTPHeaderMap::AddResult add_result = response_headers.Add(
+ AtomicString(header->name), AtomicString(header->value));
+ if (!add_result.is_new_entry) {
+ // Protocol expects the "\n" separated format.
+ add_result.stored_value->value =
+ add_result.stored_value->value + "\n" + header->value;
+ }
+ }
+
std::unique_ptr<protocol::Network::WebSocketResponse> response_object =
protocol::Network::WebSocketResponse::create()
- .setStatus(response->StatusCode())
- .setStatusText(response->StatusText())
- .setHeaders(BuildObjectForHeaders(response->HeaderFields()))
+ .setStatus(response->status_code)
+ .setStatusText(response->status_text)
+ .setHeaders(BuildObjectForHeaders(response_headers))
.build();
+ if (!response->headers_text.IsEmpty())
+ response_object->setHeadersText(response->headers_text);
- if (!response->HeadersText().IsEmpty())
- response_object->setHeadersText(response->HeadersText());
if (request) {
- response_object->setRequestHeaders(
- BuildObjectForHeaders(request->HeaderFields()));
- if (!request->HeadersText().IsEmpty())
- response_object->setRequestHeadersText(request->HeadersText());
+ HTTPHeaderMap request_headers;
+ for (auto& header : request->headers) {
+ request_headers.Add(AtomicString(header->name),
+ AtomicString(header->value));
+ }
+ response_object->setRequestHeaders(BuildObjectForHeaders(request_headers));
+ if (!request->headers_text.IsEmpty())
+ response_object->setRequestHeadersText(request->headers_text);
}
+
GetFrontend()->webSocketHandshakeResponseReceived(
IdentifiersFactory::SubresourceRequestId(identifier),
CurrentTimeTicksInSeconds(), std::move(response_object));
@@ -1418,21 +1353,11 @@ void InspectorNetworkAgent::Enable(int total_buffer_size,
Response InspectorNetworkAgent::disable() {
DCHECK(!pending_request_);
state_->setBoolean(NetworkAgentState::kNetworkAgentEnabled, false);
- state_->setString(NetworkAgentState::kUserAgentOverride, "");
instrumenting_agents_->removeInspectorNetworkAgent(this);
resources_data_->Clear();
return Response::OK();
}
-Response InspectorNetworkAgent::setUserAgentOverride(const String& user_agent) {
- if (user_agent.Contains('\n') || user_agent.Contains('\r') ||
- user_agent.Contains('\0')) {
- return Response::Error("Invalid characters found in userAgent");
- }
- state_->setString(NetworkAgentState::kUserAgentOverride, user_agent);
- return Response::OK();
-}
-
Response InspectorNetworkAgent::setExtraHTTPHeaders(
std::unique_ptr<protocol::Network::Headers> headers) {
state_->setObject(NetworkAgentState::kExtraRequestHeaders,
@@ -1613,7 +1538,7 @@ void InspectorNetworkAgent::DidCommitLoad(LocalFrame* frame,
return;
if (state_->booleanProperty(NetworkAgentState::kCacheDisabled, false))
- GetMemoryCache()->EvictResources(MemoryCache::kDoNotEvictUnusedPreloads);
+ GetMemoryCache()->EvictResources();
resources_data_->Clear(IdentifiersFactory::LoaderId(loader));
}
@@ -1766,6 +1691,9 @@ InspectorNetworkAgent::InspectorNetworkAgent(
resources_data_(
NetworkResourcesData::Create(g_maximum_total_buffer_size,
g_maximum_resource_buffer_size)),
+ devtools_token_(worker_global_scope_
+ ? worker_global_scope_->GetParentDevToolsToken()
+ : inspected_frames->Root()->GetDevToolsFrameToken()),
pending_request_(nullptr),
remove_finished_replay_xhr_timer_(
worker_global_scope_
@@ -1777,9 +1705,6 @@ InspectorNetworkAgent::InspectorNetworkAgent(
max_post_data_size_(0) {
DCHECK((IsMainThread() && !worker_global_scope_) ||
(!IsMainThread() && worker_global_scope_));
- conditions_token_ = IdentifiersFactory::IdFromToken(
- worker_global_scope_ ? worker_global_scope_->GetParentDevToolsToken()
- : inspected_frames->Root()->GetDevToolsFrameToken());
}
void InspectorNetworkAgent::ShouldForceCORSPreflight(bool* result) {
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 b4437b5b84a..ccee3be2318 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
@@ -31,6 +31,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_NETWORK_AGENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_NETWORK_AGENT_H_
+#include "base/unguessable_token.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/inspector/inspected_frames.h"
#include "third_party/blink/renderer/core/inspector/inspector_base_agent.h"
@@ -40,6 +41,15 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+namespace network {
+namespace mojom {
+namespace blink {
+class WebSocketHandshakeResponse;
+class WebSocketHandshakeRequest;
+} // namespace blink
+} // namespace mojom
+} // namespace network
+
namespace blink {
class Document;
@@ -56,8 +66,6 @@ class ResourceResponse;
class ThreadableLoaderClient;
class XHRReplayData;
class XMLHttpRequest;
-class WebSocketHandshakeRequest;
-class WebSocketHandshakeResponse;
class WorkerGlobalScope;
class CORE_EXPORT InspectorNetworkAgent final
@@ -110,7 +118,7 @@ class CORE_EXPORT InspectorNetworkAgent final
TimeTicks monotonic_finish_time,
int64_t encoded_data_length,
int64_t decoded_body_length,
- bool blocked_cross_site_document);
+ bool should_report_corb_blocking);
void DidReceiveCORSRedirectResponse(unsigned long identifier,
DocumentLoader*,
const ResourceResponse&,
@@ -125,10 +133,6 @@ class CORE_EXPORT InspectorNetworkAgent final
void ShouldBlockRequest(const KURL&, bool* result);
void ShouldBypassServiceWorker(bool* result);
- void DocumentThreadableLoaderStartedLoadingForClient(unsigned long identifier,
- ThreadableLoaderClient*);
- void DocumentThreadableLoaderFailedToStartLoadingForClient(
- ThreadableLoaderClient*);
void WillLoadXHR(XMLHttpRequest*,
ThreadableLoaderClient*,
const AtomicString& method,
@@ -136,16 +140,7 @@ class CORE_EXPORT InspectorNetworkAgent final
bool async,
const HTTPHeaderMap& headers,
bool include_crendentials);
- void DidFailXHRLoading(ExecutionContext*,
- XMLHttpRequest*,
- ThreadableLoaderClient*,
- const AtomicString&,
- const String&);
- void DidFinishXHRLoading(ExecutionContext*,
- XMLHttpRequest*,
- ThreadableLoaderClient*,
- const AtomicString&,
- const String&);
+ void DidFinishXHR(XMLHttpRequest*);
void WillStartFetch(ThreadableLoaderClient*);
@@ -154,14 +149,9 @@ class CORE_EXPORT InspectorNetworkAgent final
const AtomicString& event_name,
const AtomicString& event_id,
const String& data);
- void DidFinishEventSourceRequest(ThreadableLoaderClient*);
-
- // Detach and remove all references to the given client.
- void DetachClientRequest(ThreadableLoaderClient*);
void WillDestroyResource(Resource*);
- void ApplyUserAgentOverride(String* user_agent);
void FrameScheduledNavigation(LocalFrame*, ScheduledNavigation*);
void FrameClearedScheduledNavigation(LocalFrame*);
void FrameScheduledClientNavigation(LocalFrame*);
@@ -171,13 +161,15 @@ class CORE_EXPORT InspectorNetworkAgent final
unsigned long identifier,
const KURL& request_url,
const String&);
- void WillSendWebSocketHandshakeRequest(ExecutionContext*,
- unsigned long identifier,
- const WebSocketHandshakeRequest*);
- void DidReceiveWebSocketHandshakeResponse(ExecutionContext*,
- unsigned long identifier,
- const WebSocketHandshakeRequest*,
- const WebSocketHandshakeResponse*);
+ void WillSendWebSocketHandshakeRequest(
+ ExecutionContext*,
+ unsigned long identifier,
+ network::mojom::blink::WebSocketHandshakeRequest*);
+ void DidReceiveWebSocketHandshakeResponse(
+ ExecutionContext*,
+ unsigned long identifier,
+ network::mojom::blink::WebSocketHandshakeRequest*,
+ network::mojom::blink::WebSocketHandshakeResponse*);
void DidCloseWebSocket(ExecutionContext*, unsigned long identifier);
void DidReceiveWebSocketFrame(unsigned long identifier,
int op_code,
@@ -196,7 +188,6 @@ class CORE_EXPORT InspectorNetworkAgent final
Maybe<int> resource_buffer_size,
Maybe<int> max_post_data_size) override;
protocol::Response disable() override;
- protocol::Response setUserAgentOverride(const String&) override;
protocol::Response setExtraHTTPHeaders(
std::unique_ptr<protocol::Network::Headers>) override;
void getResponseBody(const String& request_id,
@@ -253,7 +244,6 @@ class CORE_EXPORT InspectorNetworkAgent final
const ResourceResponse& redirect_response,
const FetchInitiatorInfo&,
InspectorPageAgent::ResourceType);
- void DelayedRemoveReplayXHR(XMLHttpRequest*);
void RemoveFinishedReplayXHRFired(TimerBase*);
void DidFinishXHRInternal(ExecutionContext*,
XMLHttpRequest*,
@@ -265,7 +255,6 @@ class CORE_EXPORT InspectorNetworkAgent final
bool CanGetResponseBodyBlob(const String& request_id);
void GetResponseBodyBlob(const String& request_id,
std::unique_ptr<GetResponseBodyCallback>);
- void ClearPendingRequestData();
static std::unique_ptr<protocol::Network::Initiator> BuildInitiatorObject(
Document*,
@@ -278,11 +267,11 @@ class CORE_EXPORT InspectorNetworkAgent final
Member<WorkerGlobalScope> worker_global_scope_;
v8_inspector::V8InspectorSession* v8_session_;
Member<NetworkResourcesData> resources_data_;
- String conditions_token_;
+ const base::UnguessableToken devtools_token_;
// Stores the pending ThreadableLoaderClient till an identifier for
// the load is generated by the loader and passed to the inspector
- // via the documentThreadableLoaderStartedLoadingForClient() method.
+ // via the WillSendRequest() method.
ThreadableLoaderClient* pending_request_;
InspectorPageAgent::ResourceType pending_request_type_;
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 18da2c716a0..13cbc84b416 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
@@ -97,9 +97,10 @@ Node* HoveredNodeForPoint(LocalFrame* frame,
if (ignore_pointer_events_none)
hit_type |= HitTestRequest::kIgnorePointerEventsNone;
HitTestRequest request(hit_type);
- HitTestResult result(request,
- frame->View()->RootFrameToContents(point_in_root_frame));
- frame->ContentLayoutObject()->HitTest(result);
+ HitTestLocation location(
+ frame->View()->ConvertFromRootFrame(point_in_root_frame));
+ HitTestResult result(request, location);
+ frame->ContentLayoutObject()->HitTest(location, result);
Node* node = result.InnerPossiblyPseudoNode();
while (node && node->getNodeType() == Node::kTextNode)
node = node->parentNode();
@@ -667,14 +668,12 @@ void InspectorOverlayAgent::RebuildOverlayPage() {
if (!view || !frame)
return;
- IntRect visible_rect_in_document =
- view->GetScrollableArea()->VisibleContentRect();
IntSize viewport_size = frame->GetPage()->GetVisualViewport().Size();
OverlayMainFrame()->View()->Resize(viewport_size);
OverlayPage()->GetVisualViewport().SetSize(viewport_size);
OverlayMainFrame()->SetPageZoomFactor(WindowToViewportScale());
- Reset(viewport_size, visible_rect_in_document.Location());
+ Reset(viewport_size);
DrawNodeHighlight();
DrawQuadHighlight();
@@ -859,8 +858,7 @@ LocalFrame* InspectorOverlayAgent::OverlayMainFrame() {
return ToLocalFrame(OverlayPage()->MainFrame());
}
-void InspectorOverlayAgent::Reset(const IntSize& viewport_size,
- const IntPoint& document_scroll_offset) {
+void InspectorOverlayAgent::Reset(const IntSize& viewport_size) {
std::unique_ptr<protocol::DictionaryValue> reset_data =
protocol::DictionaryValue::create();
reset_data->setDouble(
@@ -882,8 +880,12 @@ void InspectorOverlayAgent::Reset(const IntSize& viewport_size,
"pageZoomFactor",
frame_impl_->GetFrame()->PageZoomFactor() / WindowToViewportScale());
- reset_data->setInteger("scrollX", document_scroll_offset.X());
- reset_data->setInteger("scrollY", document_scroll_offset.Y());
+ // TODO(szager): These values have been zero since root layer scrolling
+ // landed. Probably they should be derived from
+ // LocalFrameView::LayoutViewport(); but I have no idea who the consumers
+ // of these values are, so I'm leaving them zero pending investigation.
+ reset_data->setInteger("scrollX", 0);
+ reset_data->setInteger("scrollY", 0);
EvaluateInOverlay("reset", std::move(reset_data));
}
@@ -1070,8 +1072,8 @@ bool InspectorOverlayAgent::HandleMouseUp(const WebMouseEvent& event) {
IntPoint p2 = screenshot_position_;
if (LocalFrame* frame = frame_impl_->GetFrame()) {
scale = frame->GetPage()->PageScaleFactor();
- p1 = frame->View()->RootFrameToContents(p1);
- p2 = frame->View()->RootFrameToContents(p2);
+ p1 = frame->View()->ConvertFromRootFrame(p1);
+ p2 = frame->View()->ConvertFromRootFrame(p2);
}
int min_x = std::min(p1.X(), p2.X());
int max_x = std::max(p1.X(), p2.X());
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 0d607601de1..ec0ad5f0b1c 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
@@ -151,8 +151,7 @@ class CORE_EXPORT InspectorOverlayAgent final
Page* OverlayPage();
LocalFrame* OverlayMainFrame();
- void Reset(const IntSize& viewport_size,
- const IntPoint& document_scroll_offset);
+ void Reset(const IntSize& viewport_size);
void EvaluateInOverlay(const String& method, const String& argument);
void EvaluateInOverlay(const String& method,
std::unique_ptr<protocol::Value> argument);
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 7f881fe3179..665eadcb132 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
@@ -35,6 +35,7 @@
#include "build/build_config.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/script_regexp.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_source_code.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/dom/dom_implementation.h"
@@ -62,6 +63,7 @@
#include "third_party/blink/renderer/core/loader/resource/script_resource.h"
#include "third_party/blink/renderer/core/loader/scheduled_navigation.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/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
@@ -88,6 +90,16 @@ static const char kPageAgentScriptsToEvaluateOnLoad[] =
static const char kScreencastEnabled[] = "screencastEnabled";
static const char kLifecycleEventsEnabled[] = "lifecycleEventsEnabled";
static const char kBypassCSPEnabled[] = "bypassCSPEnabled";
+static const char kStandardFontFamily[] = "standardFontFamily";
+static const char kFixedFontFamily[] = "fixedFontFamily";
+static const char kSerifFontFamily[] = "serifFontFamily";
+static const char kSansSerifFontFamily[] = "sansSerifFontFamily";
+static const char kCursiveFontFamily[] = "cursiveFontFamily";
+static const char kFantasyFontFamily[] = "fantasyFontFamily";
+static const char kPictographFontFamily[] = "pictographFontFamily";
+static const char kStandardFontSize[] = "standardFontSize";
+static const char kFixedFontSize[] = "fixedFontSize";
+static const char kProduceCompilationCache[] = "generateCompilationCache";
} // namespace PageAgentState
namespace {
@@ -348,7 +360,7 @@ bool InspectorPageAgent::CachedResourceContent(Resource* cached_resource,
MaybeEncodeTextContent(
cached_resource->ResourceBuffer()
? ToScriptResource(cached_resource)->DecodedText()
- : ToScriptResource(cached_resource)->SourceText(),
+ : ToScriptResource(cached_resource)->SourceText().ToString(),
cached_resource->ResourceBuffer(), result, base64_encoded);
return true;
default:
@@ -463,6 +475,57 @@ void InspectorPageAgent::Restore() {
enable();
if (state_->booleanProperty(PageAgentState::kBypassCSPEnabled, false))
setBypassCSP(true);
+
+ // Re-apply generic fonts overrides.
+ String font;
+ bool notifyGenericFontFamilyChange = false;
+ LocalFrame* frame = inspected_frames_->Root();
+ auto* settings = frame->GetSettings();
+ if (settings) {
+ auto& family_settings = settings->GetGenericFontFamilySettings();
+ if (state_->getString(PageAgentState::kStandardFontFamily, &font)) {
+ family_settings.UpdateStandard(AtomicString(font));
+ notifyGenericFontFamilyChange = true;
+ }
+ if (state_->getString(PageAgentState::kFixedFontFamily, &font)) {
+ family_settings.UpdateFixed(AtomicString(font));
+ notifyGenericFontFamilyChange = true;
+ }
+ if (state_->getString(PageAgentState::kSerifFontFamily, &font)) {
+ family_settings.UpdateSerif(AtomicString(font));
+ notifyGenericFontFamilyChange = true;
+ }
+ if (state_->getString(PageAgentState::kSansSerifFontFamily, &font)) {
+ family_settings.UpdateSansSerif(AtomicString(font));
+ notifyGenericFontFamilyChange = true;
+ }
+ if (state_->getString(PageAgentState::kCursiveFontFamily, &font)) {
+ family_settings.UpdateCursive(AtomicString(font));
+ notifyGenericFontFamilyChange = true;
+ }
+ if (state_->getString(PageAgentState::kFantasyFontFamily, &font)) {
+ family_settings.UpdateFantasy(AtomicString(font));
+ notifyGenericFontFamilyChange = true;
+ }
+ if (state_->getString(PageAgentState::kPictographFontFamily, &font)) {
+ family_settings.UpdatePictograph(AtomicString(font));
+ notifyGenericFontFamilyChange = true;
+ }
+ if (notifyGenericFontFamilyChange) {
+ settings->NotifyGenericFontFamilyChange();
+ }
+ }
+
+ // Re-apply default font size overrides.
+ int font_size;
+ if (settings) {
+ if (state_->getInteger(PageAgentState::kStandardFontSize, &font_size)) {
+ settings->SetDefaultFontSize(font_size);
+ }
+ if (state_->getInteger(PageAgentState::kFixedFontSize, &font_size)) {
+ settings->SetDefaultFixedFontSize(font_size);
+ }
+ }
}
Response InspectorPageAgent::enable() {
@@ -588,10 +651,11 @@ Response InspectorPageAgent::reload(
optional_script_to_evaluate_on_load.fromMaybe("");
v8_session_->setSkipAllPauses(true);
reloading_ = true;
- inspected_frames_->Root()->Reload(optional_bypass_cache.fromMaybe(false)
- ? kFrameLoadTypeReloadBypassingCache
- : kFrameLoadTypeReload,
- ClientRedirectPolicy::kNotClientRedirect);
+ inspected_frames_->Root()->Reload(
+ optional_bypass_cache.fromMaybe(false)
+ ? WebFrameLoadType::kReloadBypassingCache
+ : WebFrameLoadType::kReload,
+ ClientRedirectPolicy::kNotClientRedirect);
return Response::OK();
}
@@ -805,7 +869,7 @@ void InspectorPageAgent::DidClearDocumentOfWindowObject(LocalFrame* frame) {
}
}
-void InspectorPageAgent::DomContentLoadedEventFired(LocalFrame* frame) {
+void InspectorPageAgent::DOMContentLoadedEventFired(LocalFrame* frame) {
double timestamp = CurrentTimeTicksInSeconds();
if (frame == inspected_frames_->Root())
GetFrontend()->domContentEventFired(timestamp);
@@ -853,7 +917,7 @@ bool InspectorPageAgent::ScreencastEnabled() {
state_->booleanProperty(PageAgentState::kScreencastEnabled, false);
}
-void InspectorPageAgent::FrameStartedLoading(LocalFrame* frame, FrameLoadType) {
+void InspectorPageAgent::FrameStartedLoading(LocalFrame* frame) {
GetFrontend()->frameStartedLoading(IdentifiersFactory::FrameId(frame));
}
@@ -1073,7 +1137,7 @@ Response InspectorPageAgent::getLayoutMetrics(
main_frame->GetDocument()->UpdateStyleAndLayoutIgnorePendingStylesheets();
IntRect visible_contents =
- main_frame->View()->LayoutViewportScrollableArea()->VisibleContentRect();
+ main_frame->View()->LayoutViewport()->VisibleContentRect();
*out_layout_viewport = protocol::Page::LayoutViewport::create()
.setPageX(visible_contents.X())
.setPageY(visible_contents.Y())
@@ -1086,12 +1150,6 @@ Response InspectorPageAgent::getLayoutMetrics(
float page_zoom = main_frame->PageZoomFactor();
FloatRect visible_rect = visual_viewport.VisibleRect();
float scale = visual_viewport.Scale();
- float scrollbar_width =
- frame_view->LayoutViewportScrollableArea()->VerticalScrollbarWidth() /
- scale;
- float scrollbar_height =
- frame_view->LayoutViewportScrollableArea()->HorizontalScrollbarHeight() /
- scale;
IntSize content_size = frame_view->GetScrollableArea()->ContentsSize();
*out_content_size = protocol::DOM::Rect::create()
@@ -1101,20 +1159,19 @@ Response InspectorPageAgent::getLayoutMetrics(
.setHeight(content_size.Height())
.build();
- *out_visual_viewport =
- protocol::Page::VisualViewport::create()
- .setOffsetX(
- AdjustForAbsoluteZoom::AdjustScroll(visible_rect.X(), page_zoom))
- .setOffsetY(
- AdjustForAbsoluteZoom::AdjustScroll(visible_rect.Y(), page_zoom))
- .setPageX(AdjustForAbsoluteZoom::AdjustScroll(page_offset.Width(),
- page_zoom))
- .setPageY(AdjustForAbsoluteZoom::AdjustScroll(page_offset.Height(),
- page_zoom))
- .setClientWidth(visible_rect.Width() - scrollbar_width)
- .setClientHeight(visible_rect.Height() - scrollbar_height)
- .setScale(scale)
- .build();
+ *out_visual_viewport = protocol::Page::VisualViewport::create()
+ .setOffsetX(AdjustForAbsoluteZoom::AdjustScroll(
+ visible_rect.X(), page_zoom))
+ .setOffsetY(AdjustForAbsoluteZoom::AdjustScroll(
+ visible_rect.Y(), page_zoom))
+ .setPageX(AdjustForAbsoluteZoom::AdjustScroll(
+ page_offset.Width(), page_zoom))
+ .setPageY(AdjustForAbsoluteZoom::AdjustScroll(
+ page_offset.Height(), page_zoom))
+ .setClientWidth(visible_rect.Width())
+ .setClientHeight(visible_rect.Height())
+ .setScale(scale)
+ .build();
return Response::OK();
}
@@ -1150,6 +1207,138 @@ protocol::Response InspectorPageAgent::createIsolatedWorld(
return Response::OK();
}
+Response InspectorPageAgent::setFontFamilies(
+ std::unique_ptr<protocol::Page::FontFamilies> font_families) {
+ LocalFrame* frame = inspected_frames_->Root();
+ auto* settings = frame->GetSettings();
+ if (settings) {
+ auto& family_settings = settings->GetGenericFontFamilySettings();
+ if (font_families->hasStandard()) {
+ state_->setString(PageAgentState::kStandardFontFamily,
+ font_families->getStandard(String()));
+ family_settings.UpdateStandard(
+ AtomicString(font_families->getStandard(String())));
+ }
+ if (font_families->hasFixed()) {
+ state_->setString(PageAgentState::kFixedFontFamily,
+ font_families->getFixed(String()));
+ family_settings.UpdateFixed(
+ AtomicString(font_families->getFixed(String())));
+ }
+ if (font_families->hasSerif()) {
+ state_->setString(PageAgentState::kSerifFontFamily,
+ font_families->getSerif(String()));
+ family_settings.UpdateSerif(
+ AtomicString(font_families->getSerif(String())));
+ }
+ if (font_families->hasSansSerif()) {
+ state_->setString(PageAgentState::kSansSerifFontFamily,
+ font_families->getSansSerif(String()));
+ family_settings.UpdateSansSerif(
+ AtomicString(font_families->getSansSerif(String())));
+ }
+ if (font_families->hasCursive()) {
+ state_->setString(PageAgentState::kCursiveFontFamily,
+ font_families->getCursive(String()));
+ family_settings.UpdateCursive(
+ AtomicString(font_families->getCursive(String())));
+ }
+ if (font_families->hasFantasy()) {
+ state_->setString(PageAgentState::kFantasyFontFamily,
+ font_families->getFantasy(String()));
+ family_settings.UpdateFantasy(
+ AtomicString(font_families->getFantasy(String())));
+ }
+ if (font_families->hasPictograph()) {
+ state_->setString(PageAgentState::kPictographFontFamily,
+ font_families->getPictograph(String()));
+ family_settings.UpdatePictograph(
+ AtomicString(font_families->getPictograph(String())));
+ }
+ settings->NotifyGenericFontFamilyChange();
+ }
+
+ return Response::OK();
+}
+
+Response InspectorPageAgent::setFontSizes(
+ std::unique_ptr<protocol::Page::FontSizes> font_sizes) {
+ LocalFrame* frame = inspected_frames_->Root();
+ auto* settings = frame->GetSettings();
+ if (settings) {
+ if (font_sizes->hasStandard()) {
+ state_->setInteger(PageAgentState::kStandardFontSize,
+ font_sizes->getStandard(0));
+ settings->SetDefaultFontSize(font_sizes->getStandard(0));
+ }
+ if (font_sizes->hasFixed()) {
+ state_->setInteger(PageAgentState::kFixedFontSize,
+ font_sizes->getFixed(0));
+ settings->SetDefaultFixedFontSize(font_sizes->getFixed(0));
+ }
+ }
+
+ return Response::OK();
+}
+
+void InspectorPageAgent::ConsumeCompilationCache(
+ const ScriptSourceCode& source,
+ v8::ScriptCompiler::CachedData** cached_data) {
+ if (source.SourceLocationType() != ScriptSourceLocationType::kExternalFile)
+ return;
+ if (source.Url().IsEmpty())
+ return;
+ auto it = compilation_cache_.find(source.Url().GetString());
+ if (it == compilation_cache_.end())
+ return;
+ const Vector<char>& data = it->value;
+ *cached_data = new v8::ScriptCompiler::CachedData(
+ reinterpret_cast<const uint8_t*>(data.data()), data.size(),
+ v8::ScriptCompiler::CachedData::BufferNotOwned);
+}
+
+void InspectorPageAgent::ProduceCompilationCache(const ScriptSourceCode& source,
+ v8::Local<v8::Script> script) {
+ if (!state_->booleanProperty(PageAgentState::kProduceCompilationCache, false))
+ return;
+ KURL url = source.Url();
+ if (source.Streamer())
+ return;
+ if (source.SourceLocationType() != ScriptSourceLocationType::kExternalFile)
+ return;
+ if (url.IsEmpty())
+ return;
+ static const int kMinimalCodeLength = 1024;
+ if (source.Source().length() < kMinimalCodeLength)
+ return;
+ std::unique_ptr<v8::ScriptCompiler::CachedData> cached_data(
+ v8::ScriptCompiler::CreateCodeCache(script->GetUnboundScript()));
+ if (cached_data) {
+ String base64data = Base64Encode(
+ reinterpret_cast<const char*>(cached_data->data), cached_data->length);
+ GetFrontend()->compilationCacheProduced(url, base64data);
+ }
+}
+
+Response InspectorPageAgent::setProduceCompilationCache(bool enabled) {
+ state_->setBoolean(PageAgentState::kProduceCompilationCache, enabled);
+ return Response::OK();
+}
+
+Response InspectorPageAgent::addCompilationCache(const String& url,
+ const String& base64data) {
+ Vector<char> data;
+ if (!Base64Decode(base64data, data))
+ return Response::Error("data should be base64-encoded");
+ compilation_cache_.Set(url, std::move(data));
+ return Response::OK();
+}
+
+Response InspectorPageAgent::clearCompilationCache() {
+ compilation_cache_.clear();
+ return Response::OK();
+}
+
void InspectorPageAgent::Trace(blink::Visitor* visitor) {
visitor->Trace(inspected_frames_);
visitor->Trace(inspector_resource_content_loader_);
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 33444ec69bb..c5a48a9f1e1 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
@@ -32,6 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_INSPECTOR_PAGE_AGENT_H_
#include "base/macros.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_cache_options.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/Page.h"
@@ -152,16 +153,25 @@ class CORE_EXPORT InspectorPageAgent final
Maybe<String> world_name,
Maybe<bool> grant_universal_access,
int* execution_context_id) override;
+ protocol::Response setFontFamilies(
+ std::unique_ptr<protocol::Page::FontFamilies>) override;
+ protocol::Response setFontSizes(
+ std::unique_ptr<protocol::Page::FontSizes>) override;
+
+ protocol::Response setProduceCompilationCache(bool enabled) override;
+ protocol::Response addCompilationCache(const String& url,
+ const String& data) override;
+ protocol::Response clearCompilationCache() override;
// InspectorInstrumentation API
void DidClearDocumentOfWindowObject(LocalFrame*);
void DidNavigateWithinDocument(LocalFrame*);
- void DomContentLoadedEventFired(LocalFrame*);
+ void DOMContentLoadedEventFired(LocalFrame*);
void LoadEventFired(LocalFrame*);
void WillCommitLoad(LocalFrame*, DocumentLoader*);
void FrameAttachedToParent(LocalFrame*);
void FrameDetachedFromParent(LocalFrame*);
- void FrameStartedLoading(LocalFrame*, FrameLoadType);
+ void FrameStartedLoading(LocalFrame*);
void FrameStoppedLoading(LocalFrame*);
void FrameScheduledNavigation(LocalFrame*, ScheduledNavigation*);
void FrameClearedScheduledNavigation(LocalFrame*);
@@ -183,6 +193,10 @@ class CORE_EXPORT InspectorPageAgent final
const AtomicString&,
const WebWindowFeatures&,
bool);
+ void ConsumeCompilationCache(const ScriptSourceCode& source,
+ v8::ScriptCompiler::CachedData**);
+ void ProduceCompilationCache(const ScriptSourceCode& source,
+ v8::Local<v8::Script> script);
// Inspector Controller API
void Restore() override;
@@ -219,6 +233,7 @@ class CORE_EXPORT InspectorPageAgent final
std::unique_ptr<protocol::Page::FrameResourceTree> BuildObjectForResourceTree(
LocalFrame*);
Member<InspectedFrames> inspected_frames_;
+ HashMap<String, Vector<char>> compilation_cache_;
v8_inspector::V8InspectorSession* v8_session_;
Client* client_;
long last_script_identifier_;
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_performance_agent.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_performance_agent.cc
index f4f340a9625..85c4644d147 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_performance_agent.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_performance_agent.cc
@@ -207,14 +207,14 @@ void InspectorPerformanceAgent::Did(const probe::UpdateLayout& probe) {
layout_count_++;
}
-void InspectorPerformanceAgent::WillProcessTask(double start_time) {
- task_start_ticks_ = TimeTicksFromSeconds(start_time);
+void InspectorPerformanceAgent::WillProcessTask(base::TimeTicks start_time) {
+ task_start_ticks_ = start_time;
}
-void InspectorPerformanceAgent::DidProcessTask(double start_time,
- double end_time) {
- if (task_start_ticks_ == TimeTicksFromSeconds(start_time))
- task_duration_ += TimeDelta::FromSecondsD(end_time - start_time);
+void InspectorPerformanceAgent::DidProcessTask(base::TimeTicks start_time,
+ base::TimeTicks end_time) {
+ if (task_start_ticks_ == start_time)
+ task_duration_ += end_time - start_time;
task_start_ticks_ = TimeTicks();
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_performance_agent.h b/chromium/third_party/blink/renderer/core/inspector/inspector_performance_agent.h
index 98b919196cd..3e0d3f87acb 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_performance_agent.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_performance_agent.h
@@ -8,10 +8,10 @@
#include <memory>
#include "base/macros.h"
+#include "base/task/sequence_manager/task_time_observer.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/Performance.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_time_observer.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink {
@@ -57,8 +57,9 @@ class CORE_EXPORT InspectorPerformanceAgent final
void Did(const probe::UpdateLayout&);
// TaskTimeObserver implementation.
- void WillProcessTask(double start_time) override;
- void DidProcessTask(double start_time, double end_time) override;
+ void WillProcessTask(base::TimeTicks start_time) override;
+ void DidProcessTask(base::TimeTicks start_time,
+ base::TimeTicks end_time) override;
private:
explicit InspectorPerformanceAgent(InspectedFrames*);
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_protocol_config.json b/chromium/third_party/blink/renderer/core/inspector/inspector_protocol_config.json
index ed5456550b8..6c1a9dd42a0 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_protocol_config.json
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_protocol_config.json
@@ -89,7 +89,8 @@
{
"domain": "Emulation",
"include": ["forceViewport", "resetViewport", "resetPageScaleFactor", "setPageScaleFactor", "setScriptExecutionDisabled", "setTouchEmulationEnabled",
- "setEmulatedMedia", "setCPUThrottlingRate", "setVirtualTimePolicy", "setNavigatorOverrides", "setDefaultBackgroundColorOverride", "setDeviceMetricsOverride", "clearDeviceMetricsOverride"],
+ "setEmulatedMedia", "setCPUThrottlingRate", "setVirtualTimePolicy", "setNavigatorOverrides", "setDefaultBackgroundColorOverride", "setDeviceMetricsOverride", "clearDeviceMetricsOverride",
+ "setUserAgentOverride", "setScrollbarsHidden", "setDocumentCookieDisabled"],
"include_events": ["virtualTimeBudgetExpired", "virtualTimeAdvanced", "virtualTimePaused"]
},
{
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_session.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_session.cc
index db4053dbe6c..f8d7b79d0db 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_session.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_session.cc
@@ -129,7 +129,8 @@ void InspectorSession::SendProtocolResponse(int call_id,
}
String InspectorSession::GetStateToSend() {
- state_->setString(kV8StateKey, ToCoreString(v8_session_->stateJSON()));
+ if (v8_session_)
+ state_->setString(kV8StateKey, ToCoreString(v8_session_->stateJSON()));
String state_to_send = state_->serialize();
if (state_to_send == last_sent_state_)
state_to_send = String();
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 a8813121b60..9a06aaebc3b 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
@@ -26,7 +26,6 @@
#include "third_party/blink/renderer/core/inspector/inspector_style_sheet.h"
#include <algorithm>
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_regexp.h"
#include "third_party/blink/renderer/core/css/css_import_rule.h"
#include "third_party/blink/renderer/core/css/css_keyframe_rule.h"
@@ -54,6 +53,7 @@
#include "third_party/blink/renderer/core/inspector/inspector_network_agent.h"
#include "third_party/blink/renderer/core/inspector/inspector_resource_container.h"
#include "third_party/blink/renderer/core/svg/svg_style_element.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/text_position.h"
@@ -1019,7 +1019,7 @@ CSSStyleRule* InspectorStyleSheet::SetRuleSelector(
String* old_text,
ExceptionState& exception_state) {
if (!VerifySelectorText(page_style_sheet_->OwnerDocument(), text)) {
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"Selector or media text is not valid.");
return nullptr;
}
@@ -1027,7 +1027,8 @@ CSSStyleRule* InspectorStyleSheet::SetRuleSelector(
CSSRuleSourceData* source_data = FindRuleByHeaderRange(range);
if (!source_data || !source_data->HasProperties()) {
exception_state.ThrowDOMException(
- kNotFoundError, "Source range didn't match existing source range");
+ DOMExceptionCode::kNotFoundError,
+ "Source range didn't match existing source range");
return nullptr;
}
@@ -1035,7 +1036,7 @@ CSSStyleRule* InspectorStyleSheet::SetRuleSelector(
if (!rule || !rule->parentStyleSheet() ||
rule->type() != CSSRule::kStyleRule) {
exception_state.ThrowDOMException(
- kNotFoundError,
+ DOMExceptionCode::kNotFoundError,
"Source range didn't match existing style source range");
return nullptr;
}
@@ -1056,7 +1057,7 @@ CSSKeyframeRule* InspectorStyleSheet::SetKeyframeKey(
String* old_text,
ExceptionState& exception_state) {
if (!VerifyKeyframeKeyText(page_style_sheet_->OwnerDocument(), text)) {
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"Keyframe key text is not valid.");
return nullptr;
}
@@ -1064,7 +1065,8 @@ CSSKeyframeRule* InspectorStyleSheet::SetKeyframeKey(
CSSRuleSourceData* source_data = FindRuleByHeaderRange(range);
if (!source_data || !source_data->HasProperties()) {
exception_state.ThrowDOMException(
- kNotFoundError, "Source range didn't match existing source range");
+ DOMExceptionCode::kNotFoundError,
+ "Source range didn't match existing source range");
return nullptr;
}
@@ -1072,7 +1074,7 @@ CSSKeyframeRule* InspectorStyleSheet::SetKeyframeKey(
if (!rule || !rule->parentStyleSheet() ||
rule->type() != CSSRule::kKeyframeRule) {
exception_state.ThrowDOMException(
- kNotFoundError,
+ DOMExceptionCode::kNotFoundError,
"Source range didn't match existing style source range");
return nullptr;
}
@@ -1092,14 +1094,15 @@ CSSRule* InspectorStyleSheet::SetStyleText(const SourceRange& range,
String* old_text,
ExceptionState& exception_state) {
if (!VerifyStyleText(page_style_sheet_->OwnerDocument(), text)) {
- exception_state.ThrowDOMException(kSyntaxError, "Style text is not valid.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
+ "Style text is not valid.");
return nullptr;
}
CSSRuleSourceData* source_data = FindRuleByBodyRange(range);
if (!source_data || !source_data->HasProperties()) {
exception_state.ThrowDOMException(
- kNotFoundError,
+ DOMExceptionCode::kNotFoundError,
"Source range didn't match existing style source range");
return nullptr;
}
@@ -1109,7 +1112,7 @@ CSSRule* InspectorStyleSheet::SetStyleText(const SourceRange& range,
(rule->type() != CSSRule::kStyleRule &&
rule->type() != CSSRule::kKeyframeRule)) {
exception_state.ThrowDOMException(
- kNotFoundError,
+ DOMExceptionCode::kNotFoundError,
"Source range didn't match existing style source range");
return nullptr;
}
@@ -1134,7 +1137,7 @@ CSSMediaRule* InspectorStyleSheet::SetMediaRuleText(
String* old_text,
ExceptionState& exception_state) {
if (!VerifyMediaText(page_style_sheet_->OwnerDocument(), text)) {
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"Selector or media text is not valid.");
return nullptr;
}
@@ -1142,7 +1145,8 @@ CSSMediaRule* InspectorStyleSheet::SetMediaRuleText(
CSSRuleSourceData* source_data = FindRuleByHeaderRange(range);
if (!source_data || !source_data->HasMedia()) {
exception_state.ThrowDOMException(
- kNotFoundError, "Source range didn't match existing source range");
+ DOMExceptionCode::kNotFoundError,
+ "Source range didn't match existing source range");
return nullptr;
}
@@ -1150,7 +1154,7 @@ CSSMediaRule* InspectorStyleSheet::SetMediaRuleText(
if (!rule || !rule->parentStyleSheet() ||
rule->type() != CSSRule::kMediaRule) {
exception_state.ThrowDOMException(
- kNotFoundError,
+ DOMExceptionCode::kNotFoundError,
"Source range didn't match existing style source range");
return nullptr;
}
@@ -1193,7 +1197,7 @@ CSSStyleRule* InspectorStyleSheet::InsertCSSOMRuleInStyleSheet(
if (!style_rule) {
page_style_sheet_->deleteRule(index, ASSERT_NO_EXCEPTION);
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"The rule '" + rule_text + "' could not be added in style sheet.");
return nullptr;
}
@@ -1219,7 +1223,7 @@ CSSStyleRule* InspectorStyleSheet::InsertCSSOMRuleInMediaRule(
if (!style_rule) {
media_rule->deleteRule(index, ASSERT_NO_EXCEPTION);
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"The rule '" + rule_text + "' could not be added in media rule.");
return nullptr;
}
@@ -1238,7 +1242,8 @@ CSSStyleRule* InspectorStyleSheet::InsertCSSOMRuleBySourceRange(
if (rule_source_data->rule_header_range.start < source_range.start &&
source_range.start < rule_source_data->rule_body_range.start) {
exception_state.ThrowDOMException(
- kNotFoundError, "Cannot insert rule inside rule selector.");
+ DOMExceptionCode::kNotFoundError,
+ "Cannot insert rule inside rule selector.");
return nullptr;
}
if (source_range.start < rule_source_data->rule_body_range.start ||
@@ -1260,7 +1265,7 @@ CSSStyleRule* InspectorStyleSheet::InsertCSSOMRuleBySourceRange(
CSSRule* rule = RuleForSourceData(containing_rule_source_data);
if (!rule || rule->type() != CSSRule::kMediaRule) {
- exception_state.ThrowDOMException(kNotFoundError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotFoundError,
"Cannot insert rule in non-media rule.");
return nullptr;
}
@@ -1274,18 +1279,20 @@ CSSStyleRule* InspectorStyleSheet::AddRule(const String& rule_text,
SourceRange* added_range,
ExceptionState& exception_state) {
if (location.start != location.end) {
- exception_state.ThrowDOMException(kNotFoundError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotFoundError,
"Source range must be collapsed.");
return nullptr;
}
if (!VerifyRuleText(page_style_sheet_->OwnerDocument(), rule_text)) {
- exception_state.ThrowDOMException(kSyntaxError, "Rule text is not valid.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
+ "Rule text is not valid.");
return nullptr;
}
if (!source_data_) {
- exception_state.ThrowDOMException(kNotFoundError, "Style is read-only.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotFoundError,
+ "Style is read-only.");
return nullptr;
}
@@ -1302,7 +1309,8 @@ CSSStyleRule* InspectorStyleSheet::AddRule(const String& rule_text,
bool InspectorStyleSheet::DeleteRule(const SourceRange& range,
ExceptionState& exception_state) {
if (!source_data_) {
- exception_state.ThrowDOMException(kNotFoundError, "Style is read-only.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotFoundError,
+ "Style is read-only.");
return false;
}
@@ -1327,12 +1335,13 @@ bool InspectorStyleSheet::DeleteRule(const SourceRange& range,
CSSRule* rule = RuleForSourceData(found_data);
if (!rule) {
exception_state.ThrowDOMException(
- kNotFoundError, "No style rule could be found in given range.");
+ DOMExceptionCode::kNotFoundError,
+ "No style rule could be found in given range.");
return false;
}
CSSStyleSheet* style_sheet = rule->parentStyleSheet();
if (!style_sheet) {
- exception_state.ThrowDOMException(kNotFoundError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotFoundError,
"No parent stylesheet could be found.");
return false;
}
@@ -1340,7 +1349,8 @@ bool InspectorStyleSheet::DeleteRule(const SourceRange& range,
if (parent_rule) {
if (parent_rule->type() != CSSRule::kMediaRule) {
exception_state.ThrowDOMException(
- kNotFoundError, "Cannot remove rule from non-media rule.");
+ DOMExceptionCode::kNotFoundError,
+ "Cannot remove rule from non-media rule.");
return false;
}
CSSMediaRule* parent_media_rule = ToCSSMediaRule(parent_rule);
@@ -1896,7 +1906,8 @@ bool InspectorStyleSheetForInlineStyle::SetText(
const String& text,
ExceptionState& exception_state) {
if (!VerifyStyleText(&element_->GetDocument(), text)) {
- exception_state.ThrowDOMException(kSyntaxError, "Style text is not valid.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
+ "Style text is not valid.");
return false;
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_task_runner.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_task_runner.cc
index c20da199536..b76d7d34ccd 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_task_runner.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_task_runner.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/core/inspector/thread_debugger.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/web_task_runner.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_trace_events.cc b/chromium/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
index 5a787d12fe1..e22bd9a857f 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
@@ -8,7 +8,9 @@
#include <memory>
+#include "cc/layers/picture_layer.h"
#include "services/network/public/mojom/request_context_frame_type.mojom-shared.h"
+#include "third_party/blink/public/platform/web_layer_tree_view.h"
#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/core/animation/animation.h"
@@ -138,7 +140,7 @@ void InspectorTraceEvents::DidFinishLoading(unsigned long identifier,
TimeTicks finish_time,
int64_t encoded_data_length,
int64_t decoded_body_length,
- bool blocked_cross_site_document) {
+ bool should_report_corb_blocking) {
LocalFrame* frame = loader ? loader->GetFrame() : nullptr;
TRACE_EVENT_INSTANT1(
"devtools.timeline", "ResourceFinish", TRACE_EVENT_SCOPE_THREAD, "data",
@@ -208,8 +210,7 @@ void InspectorTraceEvents::PaintTiming(Document* document,
"frame", ToTraceValue(document->GetFrame()));
}
-void InspectorTraceEvents::FrameStartedLoading(LocalFrame* frame,
- FrameLoadType) {
+void InspectorTraceEvents::FrameStartedLoading(LocalFrame* frame) {
TRACE_EVENT_INSTANT1("devtools.timeline", "FrameStartedLoading",
TRACE_EVENT_SCOPE_THREAD, "frame", ToTraceValue(frame));
}
@@ -321,6 +322,7 @@ const char* PseudoTypeToString(CSSSelector::PseudoType pseudo_type) {
DEFINE_STRING_MAPPING(PseudoShadow)
DEFINE_STRING_MAPPING(PseudoSlotted)
DEFINE_STRING_MAPPING(PseudoSpatialNavigationFocus)
+ DEFINE_STRING_MAPPING(PseudoIsHtml)
DEFINE_STRING_MAPPING(PseudoListBox)
DEFINE_STRING_MAPPING(PseudoHostHasAppearance)
DEFINE_STRING_MAPPING(PseudoVideoPersistent)
@@ -928,6 +930,11 @@ std::unique_ptr<TracedValue> InspectorXhrLoadEvent::Data(
return value;
}
+static FloatPoint LocalCoordToFloatPoint(LocalFrameView* view,
+ const FloatPoint& local) {
+ return FloatPoint(view->ConvertToRootFrame(RoundedIntPoint(local)));
+}
+
static void LocalToPageQuad(const LayoutObject& layout_object,
const LayoutRect& rect,
FloatQuad* quad) {
@@ -935,10 +942,10 @@ static void LocalToPageQuad(const LayoutObject& layout_object,
LocalFrameView* view = frame->View();
FloatQuad absolute =
layout_object.LocalToAbsoluteQuad(FloatQuad(FloatRect(rect)));
- quad->SetP1(view->ContentsToRootFrame(RoundedIntPoint(absolute.P1())));
- quad->SetP2(view->ContentsToRootFrame(RoundedIntPoint(absolute.P2())));
- quad->SetP3(view->ContentsToRootFrame(RoundedIntPoint(absolute.P3())));
- quad->SetP4(view->ContentsToRootFrame(RoundedIntPoint(absolute.P4())));
+ quad->SetP1(LocalCoordToFloatPoint(view, absolute.P1()));
+ quad->SetP2(LocalCoordToFloatPoint(view, absolute.P2()));
+ quad->SetP3(LocalCoordToFloatPoint(view, absolute.P3()));
+ quad->SetP4(LocalCoordToFloatPoint(view, absolute.P4()));
}
const char InspectorLayerInvalidationTrackingEvent::
diff --git a/chromium/third_party/blink/renderer/core/inspector/inspector_trace_events.h b/chromium/third_party/blink/renderer/core/inspector/inspector_trace_events.h
index ad4153c8cd6..cd8112d1558 100644
--- a/chromium/third_party/blink/renderer/core/inspector/inspector_trace_events.h
+++ b/chromium/third_party/blink/renderer/core/inspector/inspector_trace_events.h
@@ -35,6 +35,7 @@ namespace blink {
class Animation;
class CSSStyleSheetResource;
class ContainerNode;
+class Document;
class DocumentLoader;
class Element;
class Event;
@@ -95,7 +96,7 @@ class CORE_EXPORT InspectorTraceEvents
TimeTicks monotonic_finish_time,
int64_t encoded_data_length,
int64_t decoded_body_length,
- bool blocked_cross_site_document);
+ bool should_report_corb_blocking);
void DidFailLoading(unsigned long identifier,
DocumentLoader*,
const ResourceError&);
@@ -111,7 +112,7 @@ class CORE_EXPORT InspectorTraceEvents
void PaintTiming(Document*, const char* name, double timestamp);
- void FrameStartedLoading(LocalFrame*, FrameLoadType);
+ void FrameStartedLoading(LocalFrame*);
void Trace(blink::Visitor*) {}
diff --git a/chromium/third_party/blink/renderer/core/inspector/main_thread_debugger.cc b/chromium/third_party/blink/renderer/core/inspector/main_thread_debugger.cc
index b2185c38a75..826eca01553 100644
--- a/chromium/third_party/blink/renderer/core/inspector/main_thread_debugger.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/main_thread_debugger.cc
@@ -58,6 +58,7 @@
#include "third_party/blink/renderer/core/inspector/identifiers_factory.h"
#include "third_party/blink/renderer/core/inspector/inspected_frames.h"
#include "third_party/blink/renderer/core/inspector/v8_inspector_string.h"
+#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/timing/memory_info.h"
#include "third_party/blink/renderer/core/workers/main_thread_worklet_global_scope.h"
@@ -253,18 +254,22 @@ void MainThreadDebugger::quitMessageLoopOnPause() {
void MainThreadDebugger::muteMetrics(int context_group_id) {
LocalFrame* frame = WeakIdentifierMap<LocalFrame>::Lookup(context_group_id);
- if (frame && frame->GetPage()) {
- frame->GetPage()->GetUseCounter().MuteForInspector();
+ if (!frame)
+ return;
+ if (frame->GetDocument() && frame->GetDocument()->Loader())
+ frame->GetDocument()->Loader()->GetUseCounter().MuteForInspector();
+ if (frame->GetPage())
frame->GetPage()->GetDeprecation().MuteForInspector();
- }
}
void MainThreadDebugger::unmuteMetrics(int context_group_id) {
LocalFrame* frame = WeakIdentifierMap<LocalFrame>::Lookup(context_group_id);
- if (frame && frame->GetPage()) {
- frame->GetPage()->GetUseCounter().UnmuteForInspector();
+ if (!frame)
+ return;
+ if (frame->GetDocument() && frame->GetDocument()->Loader())
+ frame->GetDocument()->Loader()->GetUseCounter().UnmuteForInspector();
+ if (frame->GetPage())
frame->GetPage()->GetDeprecation().UnmuteForInspector();
- }
}
v8::Local<v8::Context> MainThreadDebugger::ensureDefaultContextInGroup(
@@ -331,7 +336,8 @@ v8::MaybeLocal<v8::Value> MainThreadDebugger::memoryInfo(
ExecutionContext* execution_context = ToExecutionContext(context);
DCHECK(execution_context);
DCHECK(execution_context->IsDocument());
- return ToV8(MemoryInfo::Create(), context->Global(), isolate);
+ return ToV8(MemoryInfo::Create(MemoryInfo::Precision::Bucketized),
+ context->Global(), isolate);
}
void MainThreadDebugger::installAdditionalCommandLineAPI(
diff --git a/chromium/third_party/blink/renderer/core/inspector/main_thread_debugger.h b/chromium/third_party/blink/renderer/core/inspector/main_thread_debugger.h
index 56c016f674f..43a8e4b4e4d 100644
--- a/chromium/third_party/blink/renderer/core/inspector/main_thread_debugger.h
+++ b/chromium/third_party/blink/renderer/core/inspector/main_thread_debugger.h
@@ -34,6 +34,7 @@
#include <memory>
#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/dom/document_lifecycle.h"
#include "third_party/blink/renderer/core/inspector/thread_debugger.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -46,7 +47,6 @@ class ErrorEvent;
class LocalFrame;
class SecurityOrigin;
class SourceLocation;
-class DocumentLifecycle;
class CORE_EXPORT MainThreadDebugger final : public ThreadDebugger {
public:
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 1223eb8d898..b83e1c23a5e 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
@@ -32,6 +32,7 @@
#include "third_party/blink/renderer/core/dom/dom_implementation.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
+#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
namespace blink {
@@ -221,23 +222,6 @@ void NetworkResourcesData::ResponseReceived(const String& request_id,
resource_data->SetTextEncodingName(response.TextEncodingName());
resource_data->SetHTTPStatusCode(response.HttpStatusCode());
resource_data->SetRawHeaderSize(response.EncodedDataLength());
-
- String file_path = response.DownloadedFilePath();
- if (!file_path.IsEmpty()) {
- std::unique_ptr<BlobData> blob_data =
- BlobData::CreateForFileWithUnknownSize(file_path);
- AtomicString mime_type;
- if (response.IsHTTP())
- mime_type = ExtractMIMETypeFromMediaType(
- response.HttpHeaderField(HTTPNames::Content_Type));
- if (mime_type.IsEmpty())
- mime_type = response.MimeType();
- if (mime_type.IsEmpty())
- mime_type = AtomicString("text/plain");
- blob_data->SetContentType(mime_type);
- resource_data->SetDownloadedFileBlob(
- BlobDataHandle::Create(std::move(blob_data), -1));
- }
}
void NetworkResourcesData::BlobReceived(const String& request_id,
@@ -323,12 +307,8 @@ void NetworkResourcesData::MaybeAddResourceData(
DCHECK(data);
if (ResourceData* resource_data =
PrepareToAddResourceData(request_id, data->size())) {
- data->ForEachSegment([&resource_data](const char* segment,
- size_t segment_size,
- size_t segment_offset) {
- resource_data->AppendData(segment, segment_size);
- return true;
- });
+ for (const auto& span : *data)
+ resource_data->AppendData(span.data(), span.size());
}
}
diff --git a/chromium/third_party/blink/renderer/core/inspector/protocol_parser_test.cc b/chromium/third_party/blink/renderer/core/inspector/protocol_parser_test.cc
index 445f10e5017..e6b296510b2 100644
--- a/chromium/third_party/blink/renderer/core/inspector/protocol_parser_test.cc
+++ b/chromium/third_party/blink/renderer/core/inspector/protocol_parser_test.cc
@@ -17,13 +17,7 @@ static std::unique_ptr<protocol::Value> ParseJSON(const String& string) {
return protocol::StringUtil::parseJSON(string);
}
-// The test fails on Android. https://crbug.com/845816
-#if defined(OS_ANDROID)
-#define MAYBE_Reading DISABLED_Reading
-#else
-#define MAYBE_Reading Reading
-#endif
-TEST(ProtocolParserTest, MAYBE_Reading) {
+TEST(ProtocolParserTest, Reading) {
Value* tmp_value;
std::unique_ptr<Value> root;
std::unique_ptr<Value> root2;
diff --git a/chromium/third_party/blink/renderer/core/inspector/thread_debugger.h b/chromium/third_party/blink/renderer/core/inspector/thread_debugger.h
index 9f3d39f2f47..6550ceecbc3 100644
--- a/chromium/third_party/blink/renderer/core/inspector/thread_debugger.h
+++ b/chromium/third_party/blink/renderer/core/inspector/thread_debugger.h
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/dom/user_gesture_indicator.h"
#include "third_party/blink/renderer/core/inspector/console_types.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
+#include "third_party/blink/renderer/platform/cross_thread_copier.h"
#include "third_party/blink/renderer/platform/timer.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/chromium/third_party/blink/renderer/core/inspector/v8_inspector_string.h b/chromium/third_party/blink/renderer/core/inspector/v8_inspector_string.h
index ab8a7e1951c..4cd4c938d93 100644
--- a/chromium/third_party/blink/renderer/core/inspector/v8_inspector_string.h
+++ b/chromium/third_party/blink/renderer/core/inspector/v8_inspector_string.h
@@ -6,10 +6,11 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_INSPECTOR_V8_INSPECTOR_STRING_H_
#include <memory>
+
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/decimal.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "third_party/blink/renderer/platform/wtf/decimal.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/string_to_number.h"
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 521f54654a1..1918108e9fc 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
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/core/inspector/worker_inspector_controller.h"
#include "third_party/blink/renderer/core/CoreProbeSink.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"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
@@ -83,6 +84,7 @@ void WorkerInspectorController::ConnectFrontend(int session_id) {
DCHECK(worker_global_scope->EnsureFetcher());
session->Append(new InspectorNetworkAgent(
inspected_frames, worker_global_scope, session->V8Session()));
+ session->Append(new InspectorEmulationAgent(nullptr));
session->Append(
new InspectorWorkerAgent(inspected_frames, worker_global_scope));
}
diff --git a/chromium/third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.cc b/chromium/third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.cc
index a8f64601c31..e8b8c94d713 100644
--- a/chromium/third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.cc
+++ b/chromium/third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.cc
@@ -67,11 +67,4 @@ void ElementIntersectionObserverData::Trace(blink::Visitor* visitor) {
visitor->Trace(intersection_observations_);
}
-void ElementIntersectionObserverData::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- for (auto& entry : intersection_observations_) {
- visitor->TraceWrappers(entry.key);
- }
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.h b/chromium/third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.h
index 6b5d1b5b54e..48ef6791edf 100644
--- a/chromium/third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.h
+++ b/chromium/third_party/blink/renderer/core/intersection_observer/element_intersection_observer_data.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INTERSECTION_OBSERVER_ELEMENT_INTERSECTION_OBSERVER_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INTERSECTION_OBSERVER_ELEMENT_INTERSECTION_OBSERVER_DATA_H_
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -17,7 +17,7 @@ class IntersectionObserver;
class ElementIntersectionObserverData
: public GarbageCollected<ElementIntersectionObserverData>,
- public TraceWrapperBase {
+ public NameClient {
public:
ElementIntersectionObserverData();
@@ -30,7 +30,6 @@ class ElementIntersectionObserverData
void DeactivateAllIntersectionObservers(Node&);
void Trace(blink::Visitor*);
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "ElementIntersectionObserverData";
}
diff --git a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc
index c5548c16f7c..8b355a9f0b1 100644
--- a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc
+++ b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc
@@ -7,10 +7,29 @@
#include "third_party/blink/renderer/core/dom/element_rare_data.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer.h"
+#include "third_party/blink/renderer/core/layout/hit_test_result.h"
#include "third_party/blink/renderer/core/layout/intersection_geometry.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
namespace blink {
+namespace {
+
+bool IsOccluded(const Element& element, const IntersectionGeometry& geometry) {
+ HitTestResult hits(
+ element.GetLayoutObject()->HitTestForOcclusion(geometry.TargetRect()));
+ const HitTestResult::NodeSet& hit_nodes = hits.ListBasedTestResult();
+ for (const auto& node : hit_nodes) {
+ if (!node->contains(&element) &&
+ node->GetLayoutObject()->HasNonZeroEffectiveOpacity()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace
+
IntersectionObservation::IntersectionObservation(IntersectionObserver& observer,
Element& target)
: observer_(observer),
@@ -52,6 +71,7 @@ void IntersectionObservation::ComputeIntersectionObservations(
// any non-zero threshold.
unsigned new_threshold_index;
float new_visible_ratio;
+ bool is_visible = false;
if (geometry.DoesIntersect()) {
if (geometry.TargetRect().IsEmpty()) {
new_visible_ratio = 1;
@@ -65,6 +85,11 @@ void IntersectionObservation::ComputeIntersectionObservations(
}
new_threshold_index =
Observer()->FirstThresholdGreaterThan(new_visible_ratio);
+ if (RuntimeEnabledFeatures::IntersectionObserverV2Enabled() &&
+ Observer()->trackVisibility()) {
+ is_visible = !Target()->GetLayoutObject()->HasDistortingVisualEffects() &&
+ !IsOccluded(*Target(), geometry);
+ }
} else {
new_visible_ratio = 0;
new_threshold_index = 0;
@@ -73,12 +98,6 @@ void IntersectionObservation::ComputeIntersectionObservations(
// TODO(tkent): We can't use CHECK_LT due to a compile error.
CHECK(new_threshold_index < kMaxThresholdIndex);
- bool is_visible = false;
- if (RuntimeEnabledFeatures::IntersectionObserverV2Enabled() &&
- Observer()->trackVisibility()) {
- // TODO(szager): Determine visibility.
- }
-
if (last_threshold_index_ != new_threshold_index ||
last_is_visible_ != is_visible) {
FloatRect snapped_root_bounds(geometry.RootRect());
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 e6049513e78..2fba8dca939 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
@@ -7,13 +7,11 @@
#include <algorithm>
#include "base/macros.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_callback.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_intersection_observer_delegate.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_token_range.h"
#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
#include "third_party/blink/renderer/core/dom/element.h"
-#include "third_party/blink/renderer/core/dom/exception_code.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"
@@ -27,6 +25,7 @@
#include "third_party/blink/renderer/core/layout/layout_view.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/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/timer.h"
namespace blink {
@@ -80,7 +79,8 @@ void ParseRootMargin(String root_margin_parameter,
!exception_state.HadException()) {
if (root_margin.size() == 4) {
exception_state.ThrowDOMException(
- kSyntaxError, "Extra text found at the end of rootMargin.");
+ DOMExceptionCode::kSyntaxError,
+ "Extra text found at the end of rootMargin.");
break;
}
const CSSParserToken& token = token_range.ConsumeIncludingWhitespace();
@@ -99,13 +99,14 @@ void ParseRootMargin(String root_margin_parameter,
break;
default:
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"rootMargin must be specified in pixels or percent.");
}
break;
default:
exception_state.ThrowDOMException(
- kSyntaxError, "rootMargin must be specified in pixels or percent.");
+ DOMExceptionCode::kSyntaxError,
+ "rootMargin must be specified in pixels or percent.");
}
}
}
@@ -273,7 +274,7 @@ void IntersectionObserver::observe(Element* target,
if (LocalFrameView* frame_view = target_frame->View()) {
// The IntersectionObsever spec requires that at least one observation
// be recorded afer observe() is called, even if the frame is throttled.
- frame_view->SetNeedsIntersectionObservation();
+ frame_view->SetNeedsIntersectionObservation(LocalFrameView::kRequired);
frame_view->ScheduleAnimation();
}
}
@@ -387,10 +388,4 @@ void IntersectionObserver::Trace(blink::Visitor* visitor) {
ContextClient::Trace(visitor);
}
-void IntersectionObserver::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(delegate_);
- ScriptWrappable::TraceWrappers(visitor);
-}
-
} // namespace blink
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 3aca2474c2c..e9b5f859229 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
@@ -7,10 +7,10 @@
#include "base/callback.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_observation.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.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/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -96,7 +96,6 @@ class CORE_EXPORT IntersectionObserver final
bool HasPendingActivity() const override;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
explicit IntersectionObserver(IntersectionObserverDelegate&,
diff --git a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.cc b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.cc
index e324bde2703..92014efb8ea 100644
--- a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.cc
+++ b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.cc
@@ -105,12 +105,4 @@ void IntersectionObserverController::Trace(blink::Visitor* visitor) {
PausableObject::Trace(visitor);
}
-void IntersectionObserverController::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- for (const auto& observer : pending_intersection_observers_)
- visitor->TraceWrappers(observer);
- for (const auto& observer : intersection_observers_being_invoked_)
- visitor->TraceWrappers(observer);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h
index b3c357979f4..7f9b17187c8 100644
--- a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h
+++ b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_controller.h
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/dom/pausable_object.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
@@ -21,7 +22,7 @@ class Document;
class IntersectionObserverController
: public GarbageCollectedFinalized<IntersectionObserverController>,
public PausableObject,
- public TraceWrapperBase {
+ public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(IntersectionObserverController);
public:
@@ -37,7 +38,6 @@ class IntersectionObserverController
void RemoveTrackedObserversForRoot(const Node&);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "IntersectionObserverController";
}
diff --git a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_delegate.h b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_delegate.h
index 8247e84929c..7924ce00bb3 100644
--- a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_delegate.h
+++ b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_delegate.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_INTERSECTION_OBSERVER_INTERSECTION_OBSERVER_DELEGATE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_INTERSECTION_OBSERVER_INTERSECTION_OBSERVER_DELEGATE_H_
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
@@ -16,14 +16,13 @@ class IntersectionObserverEntry;
class IntersectionObserverDelegate
: public GarbageCollectedFinalized<IntersectionObserverDelegate>,
- public TraceWrapperBase {
+ public NameClient {
public:
virtual ~IntersectionObserverDelegate() = default;
virtual void Deliver(const HeapVector<Member<IntersectionObserverEntry>>&,
IntersectionObserver&) = 0;
virtual ExecutionContext* GetExecutionContext() const = 0;
virtual void Trace(blink::Visitor* visitor) {}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {}
const char* NameInHeapSnapshot() const override {
return "IntersectionObserverDelegate";
}
diff --git a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h
index 08050356485..c1daa4bab1d 100644
--- a/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h
+++ b/chromium/third_party/blink/renderer/core/intersection_observer/intersection_observer_entry.h
@@ -15,7 +15,7 @@ namespace blink {
class Element;
-class IntersectionObserverEntry final : public ScriptWrappable {
+class CORE_EXPORT IntersectionObserverEntry final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
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 0df836d2d53..c867a3d46d0 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
@@ -4,10 +4,13 @@
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer.h"
+#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer_delegate.h"
#include "third_party/blink/renderer/core/intersection_observer/intersection_observer_init.h"
+#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/testing/sim/sim_compositor.h"
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
@@ -24,49 +27,49 @@ class TestIntersectionObserverDelegate : public IntersectionObserverDelegate {
public:
TestIntersectionObserverDelegate(Document& document)
: document_(document), call_count_(0) {}
- void Deliver(const HeapVector<Member<IntersectionObserverEntry>>& entry,
+ void Deliver(const HeapVector<Member<IntersectionObserverEntry>>& entries,
IntersectionObserver&) override {
call_count_++;
-
- if (!entry.back()->intersectionRect()) {
- last_intersection_rect_ = FloatRect();
- } else {
- last_intersection_rect_ =
- FloatRect(entry.back()->intersectionRect()->x(),
- entry.back()->intersectionRect()->y(),
- entry.back()->intersectionRect()->width(),
- entry.back()->intersectionRect()->height());
- }
+ entries_.AppendVector(entries);
}
ExecutionContext* GetExecutionContext() const override { return document_; }
int CallCount() const { return call_count_; }
- FloatRect LastIntersectionRect() const { return last_intersection_rect_; }
+ int EntryCount() const { return entries_.size(); }
+ const IntersectionObserverEntry* LastEntry() const { return entries_.back(); }
+ FloatRect LastIntersectionRect() const {
+ if (entries_.IsEmpty())
+ return FloatRect();
+ const IntersectionObserverEntry* entry = entries_.back();
+ return FloatRect(entry->intersectionRect()->x(),
+ entry->intersectionRect()->y(),
+ entry->intersectionRect()->width(),
+ entry->intersectionRect()->height());
+ }
void Trace(blink::Visitor* visitor) override {
IntersectionObserverDelegate::Trace(visitor);
visitor->Trace(document_);
+ visitor->Trace(entries_);
}
private:
- FloatRect last_intersection_rect_;
Member<Document> document_;
+ HeapVector<Member<IntersectionObserverEntry>> entries_;
int call_count_;
};
} // namespace
-class IntersectionObserverTest
- : public testing::WithParamInterface<bool>,
- public SimTest,
- ScopedIntersectionObserverGeometryMapperForTest {
+class IntersectionObserverTest : public SimTest {};
+
+class IntersectionObserverV2Test : public IntersectionObserverTest,
+ public ScopedIntersectionObserverV2ForTest {
public:
- IntersectionObserverTest()
- : ScopedIntersectionObserverGeometryMapperForTest(GetParam()) {}
+ IntersectionObserverV2Test()
+ : IntersectionObserverTest(), ScopedIntersectionObserverV2ForTest(true) {}
};
-INSTANTIATE_TEST_CASE_P(All, IntersectionObserverTest, testing::Bool());
-
-TEST_P(IntersectionObserverTest, ObserveSchedulesFrame) {
+TEST_F(IntersectionObserverTest, ObserveSchedulesFrame) {
SimRequest main_resource("https://example.com/", "text/html");
LoadURL("https://example.com/");
main_resource.Complete("<div id='target'></div>");
@@ -90,7 +93,7 @@ TEST_P(IntersectionObserverTest, ObserveSchedulesFrame) {
EXPECT_TRUE(Compositor().NeedsBeginFrame());
}
-TEST_P(IntersectionObserverTest, ResumePostsTask) {
+TEST_F(IntersectionObserverTest, ResumePostsTask) {
WebView().Resize(WebSize(800, 600));
SimRequest main_resource("https://example.com/", "text/html");
LoadURL("https://example.com/");
@@ -118,8 +121,8 @@ TEST_P(IntersectionObserverTest, ResumePostsTask) {
// When document is not suspended, beginFrame() will generate notifications
// and post a task to deliver them.
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 300), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 300),
+ kProgrammaticScroll);
Compositor().BeginFrame();
EXPECT_EQ(observer_delegate->CallCount(), 1);
test::RunPendingTasks();
@@ -129,8 +132,8 @@ TEST_P(IntersectionObserverTest, ResumePostsTask) {
// but it will not be delivered. The notification will, however, be
// available via takeRecords();
GetDocument().PauseScheduledTasks();
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 0), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 0),
+ kProgrammaticScroll);
Compositor().BeginFrame();
EXPECT_EQ(observer_delegate->CallCount(), 2);
test::RunPendingTasks();
@@ -139,8 +142,8 @@ TEST_P(IntersectionObserverTest, ResumePostsTask) {
// Generate a notification while document is suspended; then resume document.
// Notification should happen in a post task.
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 300), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 300),
+ kProgrammaticScroll);
Compositor().BeginFrame();
test::RunPendingTasks();
EXPECT_EQ(observer_delegate->CallCount(), 2);
@@ -150,7 +153,54 @@ TEST_P(IntersectionObserverTest, ResumePostsTask) {
EXPECT_EQ(observer_delegate->CallCount(), 3);
}
-TEST_P(IntersectionObserverTest, DisconnectClearsNotifications) {
+TEST_F(IntersectionObserverTest, HitTestAfterMutation) {
+ WebView().Resize(WebSize(800, 600));
+ SimRequest main_resource("https://example.com/", "text/html");
+ LoadURL("https://example.com/");
+ main_resource.Complete(R"HTML(
+ <div id='leading-space' style='height: 700px;'></div>
+ <div id='target'></div>
+ <div id='trailing-space' style='height: 700px;'></div>
+ )HTML");
+
+ IntersectionObserverInit observer_init;
+ DummyExceptionStateForTesting exception_state;
+ TestIntersectionObserverDelegate* observer_delegate =
+ new TestIntersectionObserverDelegate(GetDocument());
+ IntersectionObserver* observer = IntersectionObserver::Create(
+ observer_init, *observer_delegate, exception_state);
+ ASSERT_FALSE(exception_state.HadException());
+
+ Element* target = GetDocument().getElementById("target");
+ ASSERT_TRUE(target);
+ observer->observe(target, exception_state);
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+ EXPECT_EQ(observer_delegate->CallCount(), 1);
+
+ GetDocument().View()->ScheduleAnimation();
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+ EXPECT_EQ(observer_delegate->CallCount(), 1);
+
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 300),
+ kProgrammaticScroll);
+
+ HitTestLocation location(LayoutPoint(0, 0));
+ HitTestResult result(
+ HitTestRequest(HitTestRequest::kReadOnly | HitTestRequest::kActive |
+ HitTestRequest::kAllowChildFrameContent),
+ location);
+ GetDocument().View()->GetLayoutView()->HitTest(location, result);
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+ EXPECT_EQ(observer_delegate->CallCount(), 2);
+}
+
+TEST_F(IntersectionObserverTest, DisconnectClearsNotifications) {
WebView().Resize(WebSize(800, 600));
SimRequest main_resource("https://example.com/", "text/html");
LoadURL("https://example.com/");
@@ -178,15 +228,15 @@ TEST_P(IntersectionObserverTest, DisconnectClearsNotifications) {
// If disconnect() is called while an observer has unsent notifications,
// those notifications should be discarded.
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 300), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 300),
+ kProgrammaticScroll);
Compositor().BeginFrame();
observer->disconnect();
test::RunPendingTasks();
EXPECT_EQ(observer_delegate->CallCount(), 1);
}
-TEST_P(IntersectionObserverTest, RootIntersectionWithForceZeroLayoutHeight) {
+TEST_F(IntersectionObserverTest, RootIntersectionWithForceZeroLayoutHeight) {
WebView().GetSettings()->SetForceZeroLayoutHeight(true);
WebView().Resize(WebSize(800, 600));
SimRequest main_resource("https://example.com/", "text/html");
@@ -227,8 +277,8 @@ TEST_P(IntersectionObserverTest, RootIntersectionWithForceZeroLayoutHeight) {
ASSERT_EQ(observer_delegate->CallCount(), 1);
EXPECT_TRUE(observer_delegate->LastIntersectionRect().IsEmpty());
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 600), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 600),
+ kProgrammaticScroll);
Compositor().BeginFrame();
test::RunPendingTasks();
ASSERT_EQ(observer_delegate->CallCount(), 2);
@@ -236,16 +286,15 @@ TEST_P(IntersectionObserverTest, RootIntersectionWithForceZeroLayoutHeight) {
EXPECT_EQ(FloatRect(200, 400, 100, 100),
observer_delegate->LastIntersectionRect());
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 1200), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 1200),
+ kProgrammaticScroll);
Compositor().BeginFrame();
test::RunPendingTasks();
ASSERT_EQ(observer_delegate->CallCount(), 3);
EXPECT_TRUE(observer_delegate->LastIntersectionRect().IsEmpty());
}
-TEST_P(IntersectionObserverTest, TrackVisibilityInit) {
- ScopedIntersectionObserverV2ForTest iov2_enabled(true);
+TEST_F(IntersectionObserverV2Test, TrackVisibilityInit) {
IntersectionObserverInit observer_init;
DummyExceptionStateForTesting exception_state;
TestIntersectionObserverDelegate* observer_delegate =
@@ -259,4 +308,158 @@ TEST_P(IntersectionObserverTest, TrackVisibilityInit) {
EXPECT_TRUE(observer->trackVisibility());
}
+TEST_F(IntersectionObserverV2Test, BasicOcclusion) {
+ WebView().Resize(WebSize(800, 600));
+ SimRequest main_resource("https://example.com/", "text/html");
+ LoadURL("https://example.com/");
+ main_resource.Complete(R"HTML(
+ <style>
+ div {
+ width: 100px;
+ height: 100px;
+ }
+ </style>
+ <div id='target'>
+ <div id='child'></div>
+ </div>
+ <div id='occluder'></div>
+ )HTML");
+
+ IntersectionObserverInit observer_init;
+ observer_init.setTrackVisibility(true);
+ DummyExceptionStateForTesting exception_state;
+ TestIntersectionObserverDelegate* observer_delegate =
+ new TestIntersectionObserverDelegate(GetDocument());
+ IntersectionObserver* observer = IntersectionObserver::Create(
+ observer_init, *observer_delegate, exception_state);
+ ASSERT_FALSE(exception_state.HadException());
+ Element* target = GetDocument().getElementById("target");
+ Element* occluder = GetDocument().getElementById("occluder");
+ ASSERT_TRUE(target);
+ observer->observe(target);
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+ ASSERT_FALSE(Compositor().NeedsBeginFrame());
+ EXPECT_EQ(observer_delegate->CallCount(), 1);
+ EXPECT_EQ(observer_delegate->EntryCount(), 1);
+ EXPECT_TRUE(observer_delegate->LastEntry()->isIntersecting());
+ EXPECT_TRUE(observer_delegate->LastEntry()->isVisible());
+
+ occluder->SetInlineStyleProperty(CSSPropertyMarginTop, "-10px");
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+ ASSERT_FALSE(Compositor().NeedsBeginFrame());
+ EXPECT_EQ(observer_delegate->CallCount(), 2);
+ EXPECT_EQ(observer_delegate->EntryCount(), 2);
+ EXPECT_TRUE(observer_delegate->LastEntry()->isIntersecting());
+ EXPECT_FALSE(observer_delegate->LastEntry()->isVisible());
+}
+
+TEST_F(IntersectionObserverV2Test, BasicOpacity) {
+ WebView().Resize(WebSize(800, 600));
+ SimRequest main_resource("https://example.com/", "text/html");
+ LoadURL("https://example.com/");
+ main_resource.Complete(R"HTML(
+ <style>
+ div {
+ width: 100px;
+ height: 100px;
+ }
+ </style>
+ <div id='transparent'>
+ <div id='target'></div>
+ </div>
+ )HTML");
+
+ IntersectionObserverInit observer_init;
+ observer_init.setTrackVisibility(true);
+ DummyExceptionStateForTesting exception_state;
+ TestIntersectionObserverDelegate* observer_delegate =
+ new TestIntersectionObserverDelegate(GetDocument());
+ IntersectionObserver* observer = IntersectionObserver::Create(
+ observer_init, *observer_delegate, exception_state);
+ ASSERT_FALSE(exception_state.HadException());
+ Element* target = GetDocument().getElementById("target");
+ Element* transparent = GetDocument().getElementById("transparent");
+ ASSERT_TRUE(target);
+ ASSERT_TRUE(transparent);
+ observer->observe(target);
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+ ASSERT_FALSE(Compositor().NeedsBeginFrame());
+ EXPECT_EQ(observer_delegate->CallCount(), 1);
+ EXPECT_EQ(observer_delegate->EntryCount(), 1);
+ EXPECT_TRUE(observer_delegate->LastEntry()->isIntersecting());
+ EXPECT_TRUE(observer_delegate->LastEntry()->isVisible());
+
+ transparent->SetInlineStyleProperty(CSSPropertyOpacity, "0.99");
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+ ASSERT_FALSE(Compositor().NeedsBeginFrame());
+ EXPECT_EQ(observer_delegate->CallCount(), 2);
+ EXPECT_EQ(observer_delegate->EntryCount(), 2);
+ EXPECT_TRUE(observer_delegate->LastEntry()->isIntersecting());
+ EXPECT_FALSE(observer_delegate->LastEntry()->isVisible());
+}
+
+TEST_F(IntersectionObserverV2Test, BasicTransform) {
+ WebView().Resize(WebSize(800, 600));
+ SimRequest main_resource("https://example.com/", "text/html");
+ LoadURL("https://example.com/");
+ main_resource.Complete(R"HTML(
+ <style>
+ div {
+ width: 100px;
+ height: 100px;
+ }
+ </style>
+ <div id='transformed'>
+ <div id='target'></div>
+ </div>
+ )HTML");
+
+ IntersectionObserverInit observer_init;
+ observer_init.setTrackVisibility(true);
+ DummyExceptionStateForTesting exception_state;
+ TestIntersectionObserverDelegate* observer_delegate =
+ new TestIntersectionObserverDelegate(GetDocument());
+ IntersectionObserver* observer = IntersectionObserver::Create(
+ observer_init, *observer_delegate, exception_state);
+ ASSERT_FALSE(exception_state.HadException());
+ Element* target = GetDocument().getElementById("target");
+ Element* transformed = GetDocument().getElementById("transformed");
+ ASSERT_TRUE(target);
+ ASSERT_TRUE(transformed);
+ observer->observe(target);
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+ ASSERT_FALSE(Compositor().NeedsBeginFrame());
+ EXPECT_EQ(observer_delegate->CallCount(), 1);
+ EXPECT_EQ(observer_delegate->EntryCount(), 1);
+ EXPECT_TRUE(observer_delegate->LastEntry()->isIntersecting());
+ EXPECT_TRUE(observer_delegate->LastEntry()->isVisible());
+
+ // 2D translations and proportional upscaling is permitted.
+ transformed->SetInlineStyleProperty(
+ CSSPropertyTransform, "translateX(10px) translateY(20px) scale(2)");
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+ ASSERT_FALSE(Compositor().NeedsBeginFrame());
+ EXPECT_EQ(observer_delegate->CallCount(), 1);
+ EXPECT_EQ(observer_delegate->EntryCount(), 1);
+
+ // Any other transform is not permitted.
+ transformed->SetInlineStyleProperty(CSSPropertyTransform, "skewX(10deg)");
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+ ASSERT_FALSE(Compositor().NeedsBeginFrame());
+ EXPECT_EQ(observer_delegate->CallCount(), 2);
+ EXPECT_EQ(observer_delegate->EntryCount(), 2);
+ EXPECT_TRUE(observer_delegate->LastEntry()->isIntersecting());
+ EXPECT_FALSE(observer_delegate->LastEntry()->isVisible());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/BUILD.gn b/chromium/third_party/blink/renderer/core/layout/BUILD.gn
index 052db1932e7..1cbe8b01257 100644
--- a/chromium/third_party/blink/renderer/core/layout/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/layout/BUILD.gn
@@ -44,6 +44,7 @@ blink_core_sources("layout") {
"custom/css_layout_worklet.h",
"custom/custom_layout_child.cc",
"custom/custom_layout_child.h",
+ "custom/custom_layout_constraints.cc",
"custom/custom_layout_constraints.h",
"custom/custom_layout_fragment.cc",
"custom/custom_layout_fragment.h",
@@ -92,6 +93,7 @@ blink_core_sources("layout") {
"hit_testing_transform_state.h",
"intersection_geometry.cc",
"intersection_geometry.h",
+ "intrinsic_sizing_info.h",
"jank_tracker.cc",
"jank_tracker.h",
"layout_analyzer.cc",
@@ -131,8 +133,6 @@ blink_core_sources("layout") {
"layout_frame.h",
"layout_frame_set.cc",
"layout_frame_set.h",
- "layout_full_screen.cc",
- "layout_full_screen.h",
"layout_geometry_map.cc",
"layout_geometry_map.h",
"layout_geometry_map_step.h",
@@ -170,6 +170,8 @@ blink_core_sources("layout") {
"layout_object.h",
"layout_object_child_list.cc",
"layout_object_child_list.h",
+ "layout_object_factory.cc",
+ "layout_object_factory.h",
"layout_object_inlines.h",
"layout_paged_flow_thread.cc",
"layout_paged_flow_thread.h",
@@ -284,6 +286,8 @@ blink_core_sources("layout") {
"min_max_size.h",
"multi_column_fragmentainer_group.cc",
"multi_column_fragmentainer_group.h",
+ "ng/exclusions/ng_exclusion.cc",
+ "ng/exclusions/ng_exclusion.h",
"ng/exclusions/ng_exclusion_space.cc",
"ng/exclusions/ng_exclusion_space.h",
"ng/exclusions/ng_layout_opportunity.cc",
@@ -319,6 +323,8 @@ blink_core_sources("layout") {
"ng/geometry/ng_static_position.cc",
"ng/geometry/ng_static_position.h",
"ng/inline/empty_offset_mapping_builder.h",
+ "ng/inline/ng_abstract_inline_text_box.cc",
+ "ng/inline/ng_abstract_inline_text_box.h",
"ng/inline/ng_baseline.cc",
"ng/inline/ng_baseline.h",
"ng/inline/ng_bidi_paragraph.cc",
@@ -413,8 +419,6 @@ blink_core_sources("layout") {
"ng/ng_constraint_space_builder.h",
"ng/ng_container_fragment_builder.cc",
"ng/ng_container_fragment_builder.h",
- "ng/ng_exclusion.cc",
- "ng/ng_exclusion.h",
"ng/ng_flex_layout_algorithm.cc",
"ng/ng_flex_layout_algorithm.h",
"ng/ng_floats_utils.cc",
diff --git a/chromium/third_party/blink/renderer/core/layout/api/line_layout_box_model.h b/chromium/third_party/blink/renderer/core/layout/api/line_layout_box_model.h
index 2d2f71e88c6..e9ddcad6e51 100644
--- a/chromium/third_party/blink/renderer/core/layout/api/line_layout_box_model.h
+++ b/chromium/third_party/blink/renderer/core/layout/api/line_layout_box_model.h
@@ -128,10 +128,6 @@ class LineLayoutBoxModel : public LineLayoutItem {
}
};
-inline LineLayoutBoxModel LineLayoutItem::EnclosingBoxModelObject() const {
- return LineLayoutBoxModel(GetLayoutObject()->EnclosingBoxModelObject());
-}
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_API_LINE_LAYOUT_BOX_MODEL_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/api/line_layout_item.h b/chromium/third_party/blink/renderer/core/layout/api/line_layout_item.h
index d9ca76d5685..fcc3467d2c1 100644
--- a/chromium/third_party/blink/renderer/core/layout/api/line_layout_item.h
+++ b/chromium/third_party/blink/renderer/core/layout/api/line_layout_item.h
@@ -23,7 +23,6 @@ class HitTestRequest;
class HitTestLocation;
class LayoutObject;
class LineLayoutBox;
-class LineLayoutBoxModel;
class LineLayoutAPIShim;
static LayoutObject* const kHashTableDeletedValue =
@@ -74,11 +73,6 @@ class LineLayoutItem {
// to the line layout code.
LineLayoutBox ContainingBlock() const;
- // Implemented in LineLayoutBoxModel.h
- // Intentionally returns a LineLayoutBoxModel to avoid exposing
- // LayoutBoxModelObject to the line layout code.
- LineLayoutBoxModel EnclosingBoxModelObject() const;
-
LineLayoutItem Container() const {
return LineLayoutItem(layout_object_->Container());
}
@@ -296,8 +290,8 @@ class LineLayoutItem {
}
LayoutRect VisualRect() const { return layout_object_->VisualRect(); }
- LayoutRect PartialInvalidationRect() const {
- return layout_object_->PartialInvalidationRect();
+ LayoutRect PartialInvalidationVisualRect() const {
+ return layout_object_->PartialInvalidationVisualRect();
}
bool IsHashTableDeletedValue() const {
diff --git a/chromium/third_party/blink/renderer/core/layout/counter_node.cc b/chromium/third_party/blink/renderer/core/layout/counter_node.cc
index 36feb4032f9..b700966283a 100644
--- a/chromium/third_party/blink/renderer/core/layout/counter_node.cc
+++ b/chromium/third_party/blink/renderer/core/layout/counter_node.cc
@@ -21,8 +21,8 @@
#include "third_party/blink/renderer/core/layout/counter_node.h"
+#include "base/numerics/checked_math.h"
#include "third_party/blink/renderer/core/layout/layout_counter.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
#ifndef NDEBUG
#include <stdio.h>
@@ -148,11 +148,11 @@ int CounterNode::ComputeCountInParent() const {
// https://drafts.csswg.org/css-lists-3/#valdef-counter-reset-custom-ident-integer
int increment = ActsAsReset() ? 0 : value_;
if (previous_sibling_) {
- return WTF::CheckAdd(previous_sibling_->count_in_parent_, increment)
+ return base::CheckAdd(previous_sibling_->count_in_parent_, increment)
.ValueOrDefault(previous_sibling_->count_in_parent_);
}
DCHECK_EQ(parent_->first_child_, this);
- return WTF::CheckAdd(parent_->value_, increment)
+ return base::CheckAdd(parent_->value_, increment)
.ValueOrDefault(parent_->value_);
}
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/css_layout_definition.cc b/chromium/third_party/blink/renderer/core/layout/custom/css_layout_definition.cc
index 6e690135457..e4ae9b6e270 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/css_layout_definition.cc
+++ b/chromium/third_party/blink/renderer/core/layout/custom/css_layout_definition.cc
@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
#include "third_party/blink/renderer/bindings/core/v8/script_iterator.h"
+#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_fragment_result_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_layout_fragment_request.h"
@@ -24,6 +25,24 @@
namespace blink {
+namespace {
+
+bool IsLogicalHeightDefinite(const LayoutCustom& layout_custom) {
+ if (layout_custom.HasOverrideLogicalHeight())
+ return true;
+
+ // In quirks mode the document and body element stretch to the viewport.
+ if (layout_custom.StretchesToViewport())
+ return true;
+
+ if (layout_custom.HasDefiniteLogicalHeight())
+ return true;
+
+ return false;
+}
+
+} // namespace
+
CSSLayoutDefinition::CSSLayoutDefinition(
ScriptState* script_state,
v8::Local<v8::Function> constructor,
@@ -53,7 +72,8 @@ CSSLayoutDefinition::Instance::Instance(CSSLayoutDefinition* definition,
bool CSSLayoutDefinition::Instance::Layout(
const LayoutCustom& layout_custom,
- FragmentResultOptions* fragment_result_options) {
+ FragmentResultOptions* fragment_result_options,
+ scoped_refptr<SerializedScriptValue>* fragment_result_data) {
ScriptState* script_state = definition_->GetScriptState();
ExecutionContext* execution_context = ExecutionContext::From(script_state);
@@ -92,8 +112,17 @@ bool CSSLayoutDefinition::Instance::Layout(
return false;
}
- CustomLayoutConstraints* constraints =
- new CustomLayoutConstraints(layout_custom.LogicalWidth());
+ LayoutUnit fixed_block_size(-1);
+ if (IsLogicalHeightDefinite(layout_custom)) {
+ LayoutBox::LogicalExtentComputedValues computed_values;
+ layout_custom.ComputeLogicalHeight(LayoutUnit(-1), LayoutUnit(),
+ computed_values);
+ fixed_block_size = computed_values.extent_;
+ }
+
+ CustomLayoutConstraints* constraints = new CustomLayoutConstraints(
+ layout_custom.LogicalWidth(), fixed_block_size,
+ layout_custom.GetConstraintData(), isolate);
// TODO(ikilpatrick): Instead of creating a new style_map each time here,
// store on LayoutCustom, and update when the style changes.
@@ -142,7 +171,7 @@ bool CSSLayoutDefinition::Instance::Layout(
CustomLayoutFragmentRequest* fragment_request =
V8LayoutFragmentRequest::ToImpl(v8::Local<v8::Object>::Cast(value));
- CustomLayoutFragment* fragment = fragment_request->PerformLayout();
+ CustomLayoutFragment* fragment = fragment_request->PerformLayout(isolate);
if (!fragment) {
execution_context->AddConsoleMessage(ConsoleMessage::Create(
kJSMessageSource, kInfoMessageLevel,
@@ -168,7 +197,7 @@ bool CSSLayoutDefinition::Instance::Layout(
v8::Local<v8::Array> results = v8::Array::New(isolate, requests.size());
uint32_t index = 0;
for (const auto& request : requests) {
- CustomLayoutFragment* fragment = request->PerformLayout();
+ CustomLayoutFragment* fragment = request->PerformLayout(isolate);
if (!fragment) {
execution_context->AddConsoleMessage(ConsoleMessage::Create(
@@ -224,6 +253,28 @@ bool CSSLayoutDefinition::Instance::Layout(
return false;
}
+ // Serialize any extra data provided by the web-developer to potentially pass
+ // up to the parent custom layout.
+ if (fragment_result_options->hasData()) {
+ // We serialize "kForStorage" so that SharedArrayBuffers can't be shared
+ // between LayoutWorkletGlobalScopes.
+ *fragment_result_data = SerializedScriptValue::Serialize(
+ isolate, fragment_result_options->data().V8Value(),
+ SerializedScriptValue::SerializeOptions(
+ SerializedScriptValue::kForStorage),
+ exception_state);
+ }
+
+ if (exception_state.HadException()) {
+ V8ScriptRunner::ReportException(isolate, exception_state.GetException());
+ exception_state.ClearException();
+ execution_context->AddConsoleMessage(
+ ConsoleMessage::Create(kJSMessageSource, kInfoMessageLevel,
+ "Unable to serialize the data provided in the "
+ "result, falling back to block layout."));
+ return false;
+ }
+
return true;
}
@@ -274,10 +325,11 @@ void CSSLayoutDefinition::Instance::Trace(blink::Visitor* visitor) {
visitor->Trace(definition_);
}
-void CSSLayoutDefinition::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(constructor_.Cast<v8::Value>());
- visitor->TraceWrappers(intrinsic_sizes_.Cast<v8::Value>());
- visitor->TraceWrappers(layout_.Cast<v8::Value>());
+void CSSLayoutDefinition::Trace(Visitor* visitor) {
+ visitor->Trace(constructor_.Cast<v8::Value>());
+ visitor->Trace(intrinsic_sizes_.Cast<v8::Value>());
+ visitor->Trace(layout_.Cast<v8::Value>());
+ visitor->Trace(script_state_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/css_layout_definition.h b/chromium/third_party/blink/renderer/core/layout/custom/css_layout_definition.h
index c0ff5e73cfc..ffba10e775d 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/css_layout_definition.h
+++ b/chromium/third_party/blink/renderer/core/layout/custom/css_layout_definition.h
@@ -7,8 +7,8 @@
#include "third_party/blink/renderer/core/css/cssom/css_style_value.h"
#include "third_party/blink/renderer/core/css_property_names.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/scoped_persistent.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -19,13 +19,14 @@ namespace blink {
class FragmentResultOptions;
class LayoutCustom;
class ScriptState;
+class SerializedScriptValue;
// Represents a javascript class registered on the LayoutWorkletGlobalScope by
// the author.
// https://drafts.css-houdini.org/css-layout-api/#layout-definition
class CSSLayoutDefinition final
: public GarbageCollectedFinalized<CSSLayoutDefinition>,
- public TraceWrapperBase {
+ public NameClient {
public:
CSSLayoutDefinition(
ScriptState*,
@@ -45,8 +46,11 @@ class CSSLayoutDefinition final
Instance(CSSLayoutDefinition*, v8::Local<v8::Object> instance);
// Runs the web developer defined layout, returns true if everything
- // succeeded, and populates the FragmentResultOptions dictionary.
- bool Layout(const LayoutCustom&, FragmentResultOptions*);
+ // succeeded. It populates the FragmentResultOptions dictionary, and
+ // fragment_result_data.
+ bool Layout(const LayoutCustom&,
+ FragmentResultOptions*,
+ scoped_refptr<SerializedScriptValue>* fragment_result_data);
void Trace(blink::Visitor*);
@@ -74,20 +78,20 @@ class CSSLayoutDefinition final
return child_custom_invalidation_properties_;
}
- ScriptState* GetScriptState() const { return script_state_.get(); }
+ ScriptState* GetScriptState() const { return script_state_; }
v8::Local<v8::Function> LayoutFunctionForTesting(v8::Isolate* isolate) {
return layout_.NewLocal(isolate);
}
- void Trace(blink::Visitor* visitor) {}
- void TraceWrappers(ScriptWrappableVisitor*) const override;
+ virtual void Trace(blink::Visitor* visitor);
+
const char* NameInHeapSnapshot() const override {
return "CSSLayoutDefinition";
}
private:
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
// This object keeps the class instances, constructor function, intrinsic
// sizes function, and layout function alive. It participates in wrapper
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_child.cc b/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_child.cc
index d5c687de2ca..cf6efdfd738 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_child.cc
+++ b/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_child.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/custom/custom_layout_child.h"
+#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h"
#include "third_party/blink/renderer/core/layout/custom/css_layout_definition.h"
#include "third_party/blink/renderer/core/layout/custom/custom_layout_fragment_request.h"
@@ -22,8 +23,26 @@ CustomLayoutChild::CustomLayoutChild(const CSSLayoutDefinition& definition,
definition.ChildCustomInvalidationProperties())) {}
CustomLayoutFragmentRequest* CustomLayoutChild::layoutNextFragment(
- const CustomLayoutConstraintsOptions& options) {
- return new CustomLayoutFragmentRequest(this, options);
+ ScriptState* script_state,
+ const CustomLayoutConstraintsOptions& options,
+ ExceptionState& exception_state) {
+ // 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);
+
+ if (exception_state.HadException())
+ return nullptr;
+ }
+
+ return new CustomLayoutFragmentRequest(this, options,
+ std::move(constraint_data));
}
void CustomLayoutChild::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_child.h b/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_child.h
index 4e1193e15b3..6312ea1659d 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_child.h
+++ b/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_child.h
@@ -32,7 +32,9 @@ class CustomLayoutChild : public ScriptWrappable {
// LayoutChild.idl
PrepopulatedComputedStylePropertyMap* styleMap() const { return style_map_; }
CustomLayoutFragmentRequest* layoutNextFragment(
- const CustomLayoutConstraintsOptions&);
+ ScriptState*,
+ const CustomLayoutConstraintsOptions&,
+ ExceptionState&);
LayoutBox* GetLayoutBox() const {
DCHECK(box_);
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_constraints.cc b/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_constraints.cc
new file mode 100644
index 00000000000..1583624017d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_constraints.cc
@@ -0,0 +1,56 @@
+// 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/layout/custom/custom_layout_constraints.h"
+
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+
+namespace blink {
+
+CustomLayoutConstraints::CustomLayoutConstraints(LayoutUnit fixed_inline_size,
+ LayoutUnit fixed_block_size,
+ SerializedScriptValue* data,
+ v8::Isolate* isolate)
+ : fixed_inline_size_(fixed_inline_size),
+ fixed_block_size_(fixed_block_size) {
+ if (data)
+ layout_worklet_world_v8_data_.Set(isolate, data->Deserialize(isolate));
+}
+
+CustomLayoutConstraints::~CustomLayoutConstraints() = default;
+
+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
+ // it is being accessed from.
+ DCHECK(ExecutionContext::From(script_state)->IsLayoutWorkletGlobalScope());
+ DCHECK(script_state->World().IsWorkerWorld());
+
+ if (layout_worklet_world_v8_data_.IsEmpty())
+ return ScriptValue::CreateNull(script_state);
+
+ return ScriptValue(script_state, layout_worklet_world_v8_data_.NewLocal(
+ script_state->GetIsolate()));
+}
+
+void CustomLayoutConstraints::Trace(blink::Visitor* visitor) {
+ visitor->Trace(layout_worklet_world_v8_data_);
+ ScriptWrappable::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_constraints.h b/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_constraints.h
index 7c3d6150412..a419cf2e3f9 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_constraints.h
+++ b/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_constraints.h
@@ -6,25 +6,39 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_CUSTOM_CUSTOM_LAYOUT_CONSTRAINTS_H_
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/layout_unit.h"
namespace blink {
+class ScriptState;
+class ScriptValue;
+class SerializedScriptValue;
+
// Represents the constraints given to the layout by the parent that isn't
// encapsulated by the style, or edges.
class CustomLayoutConstraints : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- CustomLayoutConstraints(LayoutUnit fixed_inline_size)
- : fixed_inline_size_(fixed_inline_size.ToDouble()) {}
- ~CustomLayoutConstraints() override = default;
+ CustomLayoutConstraints(LayoutUnit fixed_inline_size,
+ LayoutUnit fixed_block_size,
+ SerializedScriptValue* data,
+ v8::Isolate*);
+ ~CustomLayoutConstraints() override;
// LayoutConstraints.idl
double fixedInlineSize() const { return fixed_inline_size_; }
+ double fixedBlockSize(bool& is_null) const;
+ ScriptValue data(ScriptState*) const;
+
+ void Trace(blink::Visitor*) override;
private:
double fixed_inline_size_;
+ double fixed_block_size_;
+ TraceWrapperV8Reference<v8::Value> layout_worklet_world_v8_data_;
DISALLOW_COPY_AND_ASSIGN(CustomLayoutConstraints);
};
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_constraints_options.idl b/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_constraints_options.idl
index 8742a7752a5..5c16d5b799e 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_constraints_options.idl
+++ b/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_constraints_options.idl
@@ -17,5 +17,5 @@ dictionary CustomLayoutConstraintsOptions {
// double percentageInlineSize;
// double percentageBlockSize;
- // any data;
+ any data;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment.cc b/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment.cc
index 007fb389eea..52ec7c4861d 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment.cc
+++ b/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment.cc
@@ -4,17 +4,30 @@
#include "third_party/blink/renderer/core/layout/custom/custom_layout_fragment.h"
+#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/core/layout/custom/custom_layout_fragment_request.h"
+#include "third_party/blink/renderer/core/layout/custom/layout_custom.h"
+#include "third_party/blink/renderer/core/layout/layout_box.h"
namespace blink {
CustomLayoutFragment::CustomLayoutFragment(
CustomLayoutFragmentRequest* fragment_request,
const LayoutUnit inline_size,
- const LayoutUnit block_size)
+ const LayoutUnit block_size,
+ v8::Isolate* isolate)
: fragment_request_(fragment_request),
inline_size_(inline_size.ToDouble()),
- block_size_(block_size.ToDouble()) {}
+ block_size_(block_size.ToDouble()) {
+ // Immediately store the result data, so that it remains immutable between
+ // layout calls to the child.
+ if (GetLayoutBox()->IsLayoutCustom()) {
+ SerializedScriptValue* data =
+ ToLayoutCustom(GetLayoutBox())->GetFragmentResultData();
+ if (data)
+ layout_worklet_world_v8_data_.Set(isolate, data->Deserialize(isolate));
+ }
+}
LayoutBox* CustomLayoutFragment::GetLayoutBox() const {
return fragment_request_->GetLayoutBox();
@@ -24,8 +37,23 @@ bool CustomLayoutFragment::IsValid() const {
return fragment_request_->IsValid();
}
+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
+ // it is being accessed from.
+ DCHECK(ExecutionContext::From(script_state)->IsLayoutWorkletGlobalScope());
+ DCHECK(script_state->World().IsWorkerWorld());
+
+ if (layout_worklet_world_v8_data_.IsEmpty())
+ return ScriptValue::CreateNull(script_state);
+
+ return ScriptValue(script_state, layout_worklet_world_v8_data_.NewLocal(
+ script_state->GetIsolate()));
+}
+
void CustomLayoutFragment::Trace(blink::Visitor* visitor) {
visitor->Trace(fragment_request_);
+ visitor->Trace(layout_worklet_world_v8_data_);
ScriptWrappable::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment.h b/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment.h
index 8c18e76bb2c..7623897382e 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment.h
+++ b/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_CUSTOM_CUSTOM_LAYOUT_FRAGMENT_H_
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/layout_unit.h"
@@ -13,6 +14,8 @@ namespace blink {
class CustomLayoutFragmentRequest;
class LayoutBox;
+class ScriptState;
+class ScriptValue;
// This represents the result of a layout (on a LayoutChild).
//
@@ -30,7 +33,8 @@ class CustomLayoutFragment : public ScriptWrappable {
public:
CustomLayoutFragment(CustomLayoutFragmentRequest*,
const LayoutUnit inline_size,
- const LayoutUnit block_size);
+ const LayoutUnit block_size,
+ v8::Isolate*);
~CustomLayoutFragment() override = default;
double inlineSize() const { return inline_size_; }
@@ -42,6 +46,8 @@ class CustomLayoutFragment : public ScriptWrappable {
void setInlineOffset(double inline_offset) { inline_offset_ = inline_offset; }
void setBlockOffset(double block_offset) { block_offset_ = block_offset; }
+ ScriptValue data(ScriptState*) const;
+
LayoutBox* GetLayoutBox() const;
bool IsValid() const;
@@ -69,6 +75,8 @@ class CustomLayoutFragment : public ScriptWrappable {
double inline_offset_ = 0;
double block_offset_ = 0;
+ TraceWrapperV8Reference<v8::Value> layout_worklet_world_v8_data_;
+
DISALLOW_COPY_AND_ASSIGN(CustomLayoutFragment);
};
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment_request.cc b/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment_request.cc
index b401bbaf7ce..bdf41e1b1ff 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment_request.cc
+++ b/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment_request.cc
@@ -4,9 +4,11 @@
#include "third_party/blink/renderer/core/layout/custom/custom_layout_fragment_request.h"
+#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/core/layout/custom/custom_layout_child.h"
#include "third_party/blink/renderer/core/layout/custom/custom_layout_constraints_options.h"
#include "third_party/blink/renderer/core/layout/custom/custom_layout_fragment.h"
+#include "third_party/blink/renderer/core/layout/custom/layout_custom.h"
#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
@@ -14,10 +16,14 @@ namespace blink {
CustomLayoutFragmentRequest::CustomLayoutFragmentRequest(
CustomLayoutChild* child,
- const CustomLayoutConstraintsOptions& options)
- : child_(child), options_(options) {}
-
-CustomLayoutFragment* CustomLayoutFragmentRequest::PerformLayout() {
+ const CustomLayoutConstraintsOptions& options,
+ scoped_refptr<SerializedScriptValue> constraint_data)
+ : child_(child),
+ options_(options),
+ constraint_data_(std::move(constraint_data)) {}
+
+CustomLayoutFragment* CustomLayoutFragmentRequest::PerformLayout(
+ v8::Isolate* isolate) {
// Abort if the child we are trying to perform layout upon doesn't exist.
if (!IsValid())
return nullptr;
@@ -70,18 +76,24 @@ CustomLayoutFragment* CustomLayoutFragmentRequest::PerformLayout() {
}
}
+ if (box->IsLayoutCustom())
+ ToLayoutCustom(box)->SetConstraintData(constraint_data_);
+
box->ForceLayout();
box->ClearOverrideContainingBlockContentSize();
box->ClearOverrideSize();
+ if (box->IsLayoutCustom())
+ ToLayoutCustom(box)->ClearConstraintData();
+
LayoutUnit fragment_inline_size =
is_parallel_writing_mode ? box->LogicalWidth() : box->LogicalHeight();
LayoutUnit fragment_block_size =
is_parallel_writing_mode ? box->LogicalHeight() : box->LogicalWidth();
return new CustomLayoutFragment(this, fragment_inline_size,
- fragment_block_size);
+ fragment_block_size, isolate);
}
LayoutBox* CustomLayoutFragmentRequest::GetLayoutBox() const {
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment_request.h b/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment_request.h
index 60353643e9c..eafa09b3e28 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment_request.h
+++ b/chromium/third_party/blink/renderer/core/layout/custom/custom_layout_fragment_request.h
@@ -14,6 +14,7 @@ namespace blink {
class CustomLayoutChild;
class CustomLayoutFragment;
class LayoutBox;
+class SerializedScriptValue;
// This represents a request to perform layout on a child. It is an opaque
// object from the web developers point of view.
@@ -21,14 +22,16 @@ class CustomLayoutFragmentRequest : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- CustomLayoutFragmentRequest(CustomLayoutChild*,
- const CustomLayoutConstraintsOptions&);
+ CustomLayoutFragmentRequest(
+ CustomLayoutChild*,
+ const CustomLayoutConstraintsOptions&,
+ scoped_refptr<SerializedScriptValue> constraint_data);
~CustomLayoutFragmentRequest() override = default;
// Produces a CustomLayoutFragment from this CustomLayoutFragmentRequest. This
// may fail if the underlying LayoutBox represented by the CustomLayoutChild
// has been removed from the tree.
- CustomLayoutFragment* PerformLayout();
+ CustomLayoutFragment* PerformLayout(v8::Isolate*);
LayoutBox* GetLayoutBox() const;
bool IsValid() const;
@@ -38,6 +41,7 @@ class CustomLayoutFragmentRequest : public ScriptWrappable {
private:
Member<CustomLayoutChild> child_;
const CustomLayoutConstraintsOptions options_;
+ scoped_refptr<SerializedScriptValue> constraint_data_;
DISALLOW_COPY_AND_ASSIGN(CustomLayoutFragmentRequest);
};
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/fragment_result_options.idl b/chromium/third_party/blink/renderer/core/layout/custom/fragment_result_options.idl
index e33c23b6134..376cc5be01c 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/fragment_result_options.idl
+++ b/chromium/third_party/blink/renderer/core/layout/custom/fragment_result_options.idl
@@ -7,5 +7,5 @@
dictionary FragmentResultOptions {
double autoBlockSize = 0;
sequence<LayoutFragment> childFragments = [];
- // any data = null;
+ any data = null;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/layout_child.idl b/chromium/third_party/blink/renderer/core/layout/custom/layout_child.idl
index a1a223c0867..d49c2425bff 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/layout_child.idl
+++ b/chromium/third_party/blink/renderer/core/layout/custom/layout_child.idl
@@ -13,6 +13,6 @@ interface LayoutChild {
readonly attribute StylePropertyMapReadOnly styleMap;
// IntrinsicSizesRequest intrinsicSizes();
- LayoutFragmentRequest layoutNextFragment(CustomLayoutConstraintsOptions options);
+ [CallWith=ScriptState, RaisesException] LayoutFragmentRequest layoutNextFragment(optional CustomLayoutConstraintsOptions options);
};
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/layout_constraints.idl b/chromium/third_party/blink/renderer/core/layout/custom/layout_constraints.idl
index b64fca0fb85..028899ea07c 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/layout_constraints.idl
+++ b/chromium/third_party/blink/renderer/core/layout/custom/layout_constraints.idl
@@ -11,7 +11,7 @@
]
interface LayoutConstraints {
readonly attribute double fixedInlineSize;
- // readonly attribute double? fixedBlockSize;
+ readonly attribute double? fixedBlockSize;
// readonly attribute double availableInlineSize;
// readonly attribute double availableBlockSize;
@@ -19,5 +19,5 @@ interface LayoutConstraints {
// readonly attribute double percentageInlineSize;
// readonly attribute double percentageBlockSize;
- // readonly attribute any data;
+ [CallWith=ScriptState] readonly attribute any data;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/layout_custom.cc b/chromium/third_party/blink/renderer/core/layout/custom/layout_custom.cc
index cead5acc48f..bddcb4a2184 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/layout_custom.cc
+++ b/chromium/third_party/blink/renderer/core/layout/custom/layout_custom.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/custom/layout_custom.h"
+#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.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/layout/custom/custom_layout_fragment.h"
@@ -42,6 +43,23 @@ LayoutCustom::LayoutCustom(Element* element)
DCHECK(element);
}
+SerializedScriptValue* LayoutCustom::GetConstraintData() const {
+ return constraint_data_.get();
+}
+
+void LayoutCustom::SetConstraintData(
+ scoped_refptr<SerializedScriptValue> data) {
+ constraint_data_ = std::move(data);
+}
+
+void LayoutCustom::ClearConstraintData() {
+ constraint_data_ = nullptr;
+}
+
+SerializedScriptValue* LayoutCustom::GetFragmentResultData() const {
+ return fragment_result_data_.get();
+}
+
void LayoutCustom::AddChild(LayoutObject* new_child,
LayoutObject* before_child) {
// Only use the block-flow AddChild logic when we are unloaded, i.e. we
@@ -110,14 +128,20 @@ void LayoutCustom::UpdateBlockLayout(bool relayout_children) {
// fall back onto regular block layout.
bool success = PerformLayout(relayout_children, &layout_scope);
- if (!success)
+ if (!success) {
LayoutBlockFlow::UpdateBlockLayout(relayout_children);
+ DCHECK_EQ(fragment_result_data_, nullptr);
+ }
}
bool LayoutCustom::PerformLayout(bool relayout_children,
SubtreeLayoutScope* layout_scope) {
LayoutCustomPhaseScope phase_scope(*this);
+ // We clear the fragment result data, so that if we fallback to block layout,
+ // we don't pass invalid data up the tree to a custom layout parent.
+ fragment_result_data_ = nullptr;
+
// We need to fallback to block layout if we don't have a registered
// definition yet.
if (state_ == kUnloaded)
@@ -148,7 +172,9 @@ bool LayoutCustom::PerformLayout(bool relayout_children,
}
FragmentResultOptions fragment_result_options;
- if (!instance_->Layout(*this, &fragment_result_options))
+ scoped_refptr<SerializedScriptValue> fragment_result_data;
+ if (!instance_->Layout(*this, &fragment_result_options,
+ &fragment_result_data))
return false;
size_t index = 0;
@@ -215,7 +241,7 @@ bool LayoutCustom::PerformLayout(bool relayout_children,
: LayoutPoint(block_offset, logical_left));
}
- // Currently we only support
+ // Currently we only support exactly one LayoutFragment per LayoutChild.
if (index != child_fragments.size()) {
GetDocument().AddConsoleMessage(
ConsoleMessage::Create(kJSMessageSource, kInfoMessageLevel,
@@ -225,6 +251,10 @@ bool LayoutCustom::PerformLayout(bool relayout_children,
return false;
}
+ // We aren't able to fallback to block layout now, it's safe to set the
+ // result data.
+ fragment_result_data_ = std::move(fragment_result_data);
+
SetLogicalHeight(
LayoutUnit::FromDoubleRound(fragment_result_options.autoBlockSize()));
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/layout_custom.h b/chromium/third_party/blink/renderer/core/layout/custom/layout_custom.h
index 16ac0499d45..423368da014 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/layout_custom.h
+++ b/chromium/third_party/blink/renderer/core/layout/custom/layout_custom.h
@@ -36,6 +36,17 @@ class LayoutCustom final : public LayoutBlockFlow {
LayoutCustomState State() const { return state_; }
LayoutCustomPhase Phase() const { return phase_; }
+ // "ConstraintData" is the additional input data object passed from parent to
+ // child layouts. It must be set before a custom layout pass, then
+ // immediately cleared.
+ SerializedScriptValue* GetConstraintData() const;
+ void SetConstraintData(scoped_refptr<SerializedScriptValue> data);
+ void ClearConstraintData();
+
+ // "FragmentResultData" is the additional output data object passed from the
+ // child to parent.
+ SerializedScriptValue* GetFragmentResultData() const;
+
bool CreatesNewFormattingContext() const override { return true; }
void AddChild(LayoutObject* new_child, LayoutObject* before_child) override;
@@ -56,6 +67,9 @@ class LayoutCustom final : public LayoutBlockFlow {
LayoutCustomState state_;
LayoutCustomPhase phase_;
Persistent<CSSLayoutDefinition::Instance> instance_;
+
+ scoped_refptr<SerializedScriptValue> constraint_data_;
+ scoped_refptr<SerializedScriptValue> fragment_result_data_;
};
DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutCustom, IsLayoutCustom());
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/layout_fragment.idl b/chromium/third_party/blink/renderer/core/layout/custom/layout_fragment.idl
index 997f257e8f9..e142bcd24b3 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/layout_fragment.idl
+++ b/chromium/third_party/blink/renderer/core/layout/custom/layout_fragment.idl
@@ -16,5 +16,5 @@ interface LayoutFragment {
attribute double inlineOffset;
attribute double blockOffset;
- // readonly attribute any data;
+ [CallWith=ScriptState] readonly attribute any data;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope.cc b/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope.cc
index 06874831cc0..8397c2195ef 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope.cc
+++ b/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_object_parser.h"
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
#include "third_party/blink/renderer/core/css_property_names.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/main_thread_debugger.h"
@@ -68,7 +69,7 @@ void LayoutWorkletGlobalScope::registerLayout(
if (layout_definitions_.Contains(name)) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"A class with name:'" + name + "' is already registered.");
return;
}
@@ -132,7 +133,7 @@ void LayoutWorkletGlobalScope::registerLayout(
if (!existing_document_definition->RegisterAdditionalLayoutDefinition(
*definition)) {
document_definition_map->Set(name, kInvalidDocumentLayoutDefinition);
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"A class with name:'" + name +
"' was registered with a "
"different definition.");
@@ -162,11 +163,4 @@ void LayoutWorkletGlobalScope::Trace(blink::Visitor* visitor) {
MainThreadWorkletGlobalScope::Trace(visitor);
}
-void LayoutWorkletGlobalScope::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- for (auto definition : layout_definitions_)
- visitor->TraceWrappers(definition.value);
- MainThreadWorkletGlobalScope::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope.h b/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope.h
index a8e7fe0510c..a35185896af 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope.h
+++ b/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope.h
@@ -42,7 +42,6 @@ class CORE_EXPORT LayoutWorkletGlobalScope final
CSSLayoutDefinition* FindDefinition(const AtomicString& name);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
LayoutWorkletGlobalScope(LocalFrame*,
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc b/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc
index dad9635a1b0..078e62405f9 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc
+++ b/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.cc
@@ -8,9 +8,12 @@
#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_frame.h"
+#include "third_party/blink/renderer/core/frame/local_frame_client.h"
+#include "third_party/blink/renderer/core/loader/worker_fetch_context.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/workers/global_scope_creation_params.h"
+#include "third_party/blink/renderer/core/workers/worker_content_settings_client.h"
#include "third_party/blink/renderer/core/workers/worklet_module_responses_map.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/wtf.h"
@@ -32,12 +35,18 @@ LayoutWorkletGlobalScopeProxy::LayoutWorkletGlobalScopeProxy(
reporting_proxy_ =
std::make_unique<MainThreadWorkletReportingProxy>(document);
+ WorkerClients* worker_clients = WorkerClients::Create();
+ ProvideWorkerFetchContextToWorker(
+ worker_clients, frame->Client()->CreateWorkerFetchContext());
+ ProvideContentSettingsClientToWorker(
+ worker_clients, frame->Client()->CreateWorkerContentSettingsClient());
+
auto creation_params = std::make_unique<GlobalScopeCreationParams>(
document->Url(), ScriptType::kModule, document->UserAgent(),
- document->GetContentSecurityPolicy()->Headers().get(),
+ document->GetContentSecurityPolicy()->Headers(),
document->GetReferrerPolicy(), document->GetSecurityOrigin(),
- document->IsSecureContext(), nullptr /* worker_clients */,
- document->AddressSpace(), OriginTrialContext::GetTokens(document).get(),
+ document->IsSecureContext(), worker_clients, document->AddressSpace(),
+ OriginTrialContext::GetTokens(document).get(),
base::UnguessableToken::Create(), nullptr /* worker_settings */,
kV8CacheOptionsDefault, module_responses_map);
global_scope_ = LayoutWorkletGlobalScope::Create(
@@ -48,12 +57,13 @@ LayoutWorkletGlobalScopeProxy::LayoutWorkletGlobalScopeProxy(
void LayoutWorkletGlobalScopeProxy::FetchAndInvokeScript(
const KURL& module_url_record,
network::mojom::FetchCredentialsMode credentials_mode,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
WorkletPendingTasks* pending_tasks) {
DCHECK(IsMainThread());
- global_scope_->FetchAndInvokeScript(module_url_record, credentials_mode,
- std::move(outside_settings_task_runner),
- pending_tasks);
+ global_scope_->FetchAndInvokeScript(
+ module_url_record, credentials_mode, outside_settings_object,
+ std::move(outside_settings_task_runner), pending_tasks);
}
void LayoutWorkletGlobalScopeProxy::WorkletObjectDestroyed() {
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.h b/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.h
index a4d1f72a375..f6bcd144018 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.h
+++ b/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope_proxy.h
@@ -35,6 +35,7 @@ class CORE_EXPORT LayoutWorkletGlobalScopeProxy
void FetchAndInvokeScript(
const KURL& module_url_record,
network::mojom::FetchCredentialsMode,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
WorkletPendingTasks*) override;
void WorkletObjectDestroyed() override;
diff --git a/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_test.cc b/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_test.cc
index a1b3176c651..9d214566e45 100644
--- a/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/custom/layout_worklet_test.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_module.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.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/layout/custom/css_layout_definition.h"
#include "third_party/blink/renderer/core/layout/custom/layout_worklet_global_scope.h"
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 c7e273c97c2..05635caaa22 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
@@ -63,6 +63,8 @@ enum class TransformedWritingMode {
class FlexItem {
public:
FlexItem(LayoutBox*,
+ // flex_base_content_size includes scrollbar width but not border or
+ // padding.
LayoutUnit flex_base_content_size,
MinMaxSize min_max_sizes,
LayoutUnit main_axis_border_and_padding,
@@ -274,7 +276,7 @@ class FlexLayoutAlgorithm {
bool IsMultiline() const { return style_->FlexWrap() != EFlexWrap::kNowrap; }
const ComputedStyle* style_;
- LayoutUnit line_break_length_;
+ const LayoutUnit line_break_length_;
Vector<FlexItem>& all_items_;
Vector<FlexLine> flex_lines_;
size_t next_item_index_;
diff --git a/chromium/third_party/blink/renderer/core/layout/grid.cc b/chromium/third_party/blink/renderer/core/layout/grid.cc
index 29bda92142c..219dd6fa054 100644
--- a/chromium/third_party/blink/renderer/core/layout/grid.cc
+++ b/chromium/third_party/blink/renderer/core/layout/grid.cc
@@ -12,41 +12,56 @@
namespace blink {
+std::unique_ptr<Grid> Grid::Create(const LayoutGrid* layout_grid) {
+ return base::WrapUnique(new VectorGrid(layout_grid));
+}
+
Grid::Grid(const LayoutGrid* grid) : order_iterator_(grid) {}
-size_t Grid::NumTracks(GridTrackSizingDirection direction) const {
+VectorGrid::VectorGrid(const LayoutGrid* grid) : Grid(grid) {}
+
+size_t VectorGrid::NumTracks(GridTrackSizingDirection direction) const {
if (direction == kForRows)
- return grid_.size();
- return grid_.size() ? grid_[0].size() : 0;
+ return matrix_.size();
+ return matrix_.size() ? matrix_[0].size() : 0;
}
-void Grid::EnsureGridSize(size_t maximum_row_size, size_t maximum_column_size) {
+void VectorGrid::EnsureGridSize(size_t maximum_row_size,
+ size_t maximum_column_size) {
const size_t old_row_size = NumTracks(kForRows);
if (maximum_row_size > old_row_size) {
- grid_.Grow(maximum_row_size);
+ matrix_.Grow(maximum_row_size);
for (size_t row = old_row_size; row < NumTracks(kForRows); ++row)
- grid_[row].Grow(NumTracks(kForColumns));
+ matrix_[row].Grow(NumTracks(kForColumns));
}
if (maximum_column_size > NumTracks(kForColumns)) {
for (size_t row = 0; row < NumTracks(kForRows); ++row)
- grid_[row].Grow(maximum_column_size);
+ matrix_[row].Grow(maximum_column_size);
}
}
-void Grid::insert(LayoutBox& child, const GridArea& area) {
+void VectorGrid::insert(LayoutBox& child, const GridArea& area) {
DCHECK(area.rows.IsTranslatedDefinite());
DCHECK(area.columns.IsTranslatedDefinite());
EnsureGridSize(area.rows.EndLine(), area.columns.EndLine());
for (const auto& row : area.rows) {
for (const auto& column : area.columns)
- grid_[row][column].push_back(&child);
+ matrix_[row][column].push_back(&child);
}
SetGridItemArea(child, area);
}
+std::unique_ptr<Grid::GridIterator> VectorGrid::CreateIterator(
+ GridTrackSizingDirection direction,
+ size_t fixed_track_index,
+ size_t varying_track_index) const {
+ return base::WrapUnique(new VectorGridIterator(
+ *this, direction, fixed_track_index, varying_track_index));
+}
+
void Grid::SetSmallestTracksStart(int row_start, int column_start) {
smallest_row_start_ = row_start;
smallest_column_start_ = column_start;
@@ -73,10 +88,6 @@ void Grid::SetGridItemPaintOrder(const LayoutBox& item, size_t order) {
grid_items_indexes_map_.Set(&item, order);
}
-const GridCell& Grid::Cell(size_t row, size_t column) const {
- return grid_[row][column];
-}
-
#if DCHECK_IS_ON()
bool Grid::HasAnyGridItemPaintOrder() const {
return !grid_items_indexes_map_.IsEmpty();
@@ -131,22 +142,17 @@ GridSpan Grid::GridItemSpan(const LayoutBox& grid_item,
return direction == kForColumns ? area.columns : area.rows;
}
-void Grid::SetHasAnyOrthogonalGridItem(bool has_any_orthogonal_grid_item) {
- has_any_orthogonal_grid_item_ = has_any_orthogonal_grid_item;
-}
-
void Grid::SetNeedsItemsPlacement(bool needs_items_placement) {
needs_items_placement_ = needs_items_placement;
if (!needs_items_placement) {
- grid_.ShrinkToFit();
+ ConsolidateGridDataStructure();
return;
}
- grid_.resize(0);
+ ClearGridDataStructure();
grid_item_area_.clear();
grid_items_indexes_map_.clear();
- has_any_orthogonal_grid_item_ = false;
smallest_row_start_ = 0;
smallest_column_start_ = 0;
auto_repeat_columns_ = 0;
@@ -155,34 +161,39 @@ void Grid::SetNeedsItemsPlacement(bool needs_items_placement) {
auto_repeat_empty_rows_ = nullptr;
}
-GridIterator::GridIterator(const Grid& grid,
- GridTrackSizingDirection direction,
- size_t fixed_track_index,
- size_t varying_track_index)
- : grid_(grid.grid_),
- direction_(direction),
+Grid::GridIterator::GridIterator(GridTrackSizingDirection direction,
+ size_t fixed_track_index,
+ size_t varying_track_index)
+ : direction_(direction),
row_index_((direction == kForColumns) ? varying_track_index
: fixed_track_index),
column_index_((direction == kForColumns) ? fixed_track_index
: varying_track_index),
- child_index_(0) {
- DCHECK(!grid_.IsEmpty());
- DCHECK(!grid_[0].IsEmpty());
- DCHECK_LT(row_index_, grid_.size());
- DCHECK_LT(column_index_, grid_[0].size());
+ child_index_(0) {}
+
+VectorGridIterator::VectorGridIterator(const VectorGrid& grid,
+ GridTrackSizingDirection direction,
+ size_t fixed_track_index,
+ size_t varying_track_index)
+ : GridIterator(direction, fixed_track_index, varying_track_index),
+ matrix_(grid.matrix_) {
+ DCHECK(!matrix_.IsEmpty());
+ DCHECK(!matrix_[0].IsEmpty());
+ DCHECK_LT(row_index_, matrix_.size());
+ DCHECK_LT(column_index_, matrix_[0].size());
}
-LayoutBox* GridIterator::NextGridItem() {
- DCHECK(!grid_.IsEmpty());
- DCHECK(!grid_[0].IsEmpty());
+LayoutBox* VectorGridIterator::NextGridItem() {
+ DCHECK(!matrix_.IsEmpty());
+ DCHECK(!matrix_[0].IsEmpty());
size_t& varying_track_index =
(direction_ == kForColumns) ? row_index_ : column_index_;
const size_t end_of_varying_track_index =
- (direction_ == kForColumns) ? grid_.size() : grid_[0].size();
+ (direction_ == kForColumns) ? matrix_.size() : matrix_[0].size();
for (; varying_track_index < end_of_varying_track_index;
++varying_track_index) {
- const GridCell& children = grid_[row_index_][column_index_];
+ const GridCell& children = matrix_[row_index_][column_index_];
if (child_index_ < children.size())
return children[child_index_++];
@@ -191,19 +202,20 @@ LayoutBox* GridIterator::NextGridItem() {
return nullptr;
}
-bool GridIterator::CheckEmptyCells(size_t row_span, size_t column_span) const {
- DCHECK(!grid_.IsEmpty());
- DCHECK(!grid_[0].IsEmpty());
+bool VectorGridIterator::CheckEmptyCells(size_t row_span,
+ size_t column_span) const {
+ DCHECK(!matrix_.IsEmpty());
+ DCHECK(!matrix_[0].IsEmpty());
// Ignore cells outside current grid as we will grow it later if needed.
- size_t max_rows = std::min(row_index_ + row_span, grid_.size());
- size_t max_columns = std::min(column_index_ + column_span, grid_[0].size());
+ size_t max_rows = std::min(row_index_ + row_span, matrix_.size());
+ size_t max_columns = std::min(column_index_ + column_span, matrix_[0].size());
// This adds a O(N^2) behavior that shouldn't be a big deal as we expect
// spanning areas to be small.
for (size_t row = row_index_; row < max_rows; ++row) {
for (size_t column = column_index_; column < max_columns; ++column) {
- const GridCell& children = grid_[row][column];
+ const GridCell& children = matrix_[row][column];
if (!children.IsEmpty())
return false;
}
@@ -212,11 +224,11 @@ bool GridIterator::CheckEmptyCells(size_t row_span, size_t column_span) const {
return true;
}
-std::unique_ptr<GridArea> GridIterator::NextEmptyGridArea(
+std::unique_ptr<GridArea> VectorGridIterator::NextEmptyGridArea(
size_t fixed_track_span,
size_t varying_track_span) {
- DCHECK(!grid_.IsEmpty());
- DCHECK(!grid_[0].IsEmpty());
+ DCHECK(!matrix_.IsEmpty());
+ DCHECK(!matrix_[0].IsEmpty());
DCHECK_GE(fixed_track_span, 1u);
DCHECK_GE(varying_track_span, 1u);
@@ -228,7 +240,7 @@ std::unique_ptr<GridArea> GridIterator::NextEmptyGridArea(
size_t& varying_track_index =
(direction_ == kForColumns) ? row_index_ : column_index_;
const size_t end_of_varying_track_index =
- (direction_ == kForColumns) ? grid_.size() : grid_[0].size();
+ (direction_ == kForColumns) ? matrix_.size() : matrix_[0].size();
for (; varying_track_index < end_of_varying_track_index;
++varying_track_index) {
if (CheckEmptyCells(row_span, column_span)) {
diff --git a/chromium/third_party/blink/renderer/core/layout/grid.h b/chromium/third_party/blink/renderer/core/layout/grid.h
index 6164c179290..28b061d6cf9 100644
--- a/chromium/third_party/blink/renderer/core/layout/grid.h
+++ b/chromium/third_party/blink/renderer/core/layout/grid.h
@@ -29,23 +29,23 @@ class GridIterator;
// LayoutGrid object to place the grid items on a grid like structure, so that
// they could be accessed by rows/columns instead of just traversing the DOM or
// Layout trees.
-class Grid final {
+class Grid {
public:
- Grid(const LayoutGrid*);
+ static std::unique_ptr<Grid> Create(const LayoutGrid*);
+
+ virtual size_t NumTracks(GridTrackSizingDirection) const = 0;
+
+ virtual void EnsureGridSize(size_t maximum_row_size,
+ size_t maximum_column_size) = 0;
+ virtual void insert(LayoutBox&, const GridArea&) = 0;
- size_t NumTracks(GridTrackSizingDirection) const;
+ virtual const GridCell& Cell(size_t row, size_t column) const = 0;
- void EnsureGridSize(size_t maximum_row_size, size_t maximum_column_size);
- void insert(LayoutBox&, const GridArea&);
+ virtual ~Grid(){};
// Note that out of flow children are not grid items.
bool HasGridItems() const { return !grid_item_area_.IsEmpty(); }
- bool HasAnyOrthogonalGridItem() const {
- return has_any_orthogonal_grid_item_;
- }
- void SetHasAnyOrthogonalGridItem(bool);
-
GridArea GridItemArea(const LayoutBox&) const;
void SetGridItemArea(const LayoutBox&, GridArea);
@@ -54,8 +54,6 @@ class Grid final {
size_t GridItemPaintOrder(const LayoutBox&) const;
void SetGridItemPaintOrder(const LayoutBox&, size_t order);
- const GridCell& Cell(size_t row, size_t column) const;
-
int SmallestTrackStart(GridTrackSizingDirection) const;
void SetSmallestTracksStart(int row_start, int column_start);
@@ -81,6 +79,42 @@ class Grid final {
bool HasAnyGridItemPaintOrder() const;
#endif
+ class GridIterator {
+ public:
+ virtual LayoutBox* NextGridItem() = 0;
+
+ virtual std::unique_ptr<GridArea> NextEmptyGridArea(
+ size_t fixed_track_span,
+ size_t varying_track_span) = 0;
+
+ virtual ~GridIterator() = default;
+
+ protected:
+ // |direction| is the direction that is fixed to |fixed_track_index| so e.g
+ // GridIterator(grid_, kForColumns, 1) will walk over the rows of the 2nd
+ // column.
+ GridIterator(GridTrackSizingDirection,
+ size_t fixed_track_index,
+ size_t varying_track_index);
+
+ GridTrackSizingDirection direction_;
+ size_t row_index_;
+ size_t column_index_;
+ size_t child_index_;
+ DISALLOW_COPY_AND_ASSIGN(GridIterator);
+ };
+
+ virtual std::unique_ptr<GridIterator> CreateIterator(
+ GridTrackSizingDirection,
+ size_t fixed_track_index,
+ size_t varying_track_index = 0) const = 0;
+
+ protected:
+ Grid(const LayoutGrid*);
+
+ virtual void ClearGridDataStructure() = 0;
+ virtual void ConsolidateGridDataStructure() = 0;
+
private:
friend class GridIterator;
@@ -92,11 +126,8 @@ class Grid final {
size_t auto_repeat_columns_{0};
size_t auto_repeat_rows_{0};
- bool has_any_orthogonal_grid_item_{false};
bool needs_items_placement_{true};
- GridAsMatrix grid_;
-
HashMap<const LayoutBox*, GridArea> grid_item_area_;
HashMap<const LayoutBox*, size_t> grid_items_indexes_map_;
@@ -104,32 +135,50 @@ class Grid final {
std::unique_ptr<OrderedTrackIndexSet> auto_repeat_empty_rows_{nullptr};
};
-// TODO(svillar): ideally the Grid class should be the one returning an iterator
-// for its contents.
-class GridIterator final {
+class VectorGrid final : public Grid {
public:
- // |direction| is the direction that is fixed to |fixedTrackIndex| so e.g
- // GridIterator(m_grid, ForColumns, 1) will walk over the rows of the 2nd
- // column.
- GridIterator(const Grid&,
- GridTrackSizingDirection,
- size_t fixed_track_index,
- size_t varying_track_index = 0);
+ explicit VectorGrid(const LayoutGrid*);
+
+ size_t NumTracks(GridTrackSizingDirection) const override;
+ const GridCell& Cell(size_t row, size_t column) const override {
+ return matrix_[row][column];
+ }
+ void insert(LayoutBox&, const GridArea&) override;
- LayoutBox* NextGridItem();
+ private:
+ friend class VectorGridIterator;
- bool CheckEmptyCells(size_t row_span, size_t column_span) const;
+ void EnsureGridSize(size_t maximum_row_size,
+ size_t maximum_column_size) override;
- std::unique_ptr<GridArea> NextEmptyGridArea(size_t fixed_track_span,
- size_t varying_track_span);
+ void ClearGridDataStructure() override { matrix_.resize(0); };
+ void ConsolidateGridDataStructure() override { matrix_.ShrinkToFit(); }
+
+ std::unique_ptr<GridIterator> CreateIterator(
+ GridTrackSizingDirection,
+ size_t fixed_track_index,
+ size_t varying_track_index = 0) const override;
+
+ GridAsMatrix matrix_;
+};
+
+class VectorGridIterator final : public Grid::GridIterator {
+ public:
+ VectorGridIterator(const VectorGrid&,
+ GridTrackSizingDirection,
+ size_t fixed_track_span,
+ size_t varying_track_span = 0);
+
+ LayoutBox* NextGridItem() override;
+ std::unique_ptr<GridArea> NextEmptyGridArea(
+ size_t fixed_track_span,
+ size_t varying_track_span) override;
private:
- const GridAsMatrix& grid_;
- GridTrackSizingDirection direction_;
- size_t row_index_;
- size_t column_index_;
- size_t child_index_;
- DISALLOW_COPY_AND_ASSIGN(GridIterator);
+ bool CheckEmptyCells(size_t row_span, size_t column_span) const;
+
+ const GridAsMatrix& matrix_;
+ DISALLOW_COPY_AND_ASSIGN(VectorGridIterator);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/grid_baseline_alignment.cc b/chromium/third_party/blink/renderer/core/layout/grid_baseline_alignment.cc
index 7161b41cf78..07d539edcc4 100644
--- a/chromium/third_party/blink/renderer/core/layout/grid_baseline_alignment.cc
+++ b/chromium/third_party/blink/renderer/core/layout/grid_baseline_alignment.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/core/layout/grid_baseline_alignment.h"
-#include "third_party/blink/renderer/core/layout/layout_grid.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
@@ -83,13 +82,6 @@ bool GridBaselineAlignment::IsDescentBaselineForChild(
IsFlippedBlocksWritingMode(block_flow_)));
}
-bool GridBaselineAlignment::IsBaselineContextComputed(
- GridAxis baseline_axis) const {
- return baseline_axis == kGridColumnAxis
- ? !row_axis_alignment_context_.IsEmpty()
- : !col_axis_alignment_context_.IsEmpty();
-}
-
bool GridBaselineAlignment::IsHorizontalBaselineAxis(GridAxis axis) const {
return axis == kGridRowAxis ? IsHorizontalWritingMode(block_flow_)
: !IsHorizontalWritingMode(block_flow_);
@@ -122,7 +114,7 @@ const BaselineGroup& GridBaselineAlignment::GetBaselineGroupForChild(
return context->GetSharedGroup(child, preference);
}
-void GridBaselineAlignment::UpdateBaselineAlignmentContextIfNeeded(
+void GridBaselineAlignment::UpdateBaselineAlignmentContext(
ItemPosition preference,
unsigned shared_context,
LayoutBox& child,
@@ -168,46 +160,11 @@ LayoutUnit GridBaselineAlignment::BaselineOffsetForChild(
return LayoutUnit();
}
-base::Optional<LayoutUnit> GridBaselineAlignment::ExtentForBaselineAlignment(
- ItemPosition preference,
- unsigned shared_context,
- const LayoutBox& child,
- GridAxis baseline_axis) const {
- DCHECK(IsBaselinePosition(preference));
- if (!IsBaselineContextComputed(baseline_axis))
- return base::nullopt;
-
- auto& group = GetBaselineGroupForChild(preference, shared_context, child,
- baseline_axis);
- return group.MaxAscent() + group.MaxDescent();
-}
-
-bool GridBaselineAlignment::BaselineMayAffectIntrinsicSize(
- const GridTrackSizingAlgorithm& algorithm,
- GridTrackSizingDirection direction) const {
- const auto& contexts_map = direction == kForColumns
- ? col_axis_alignment_context_
- : row_axis_alignment_context_;
- for (const auto& context : contexts_map) {
- auto track_size = algorithm.GetGridTrackSize(direction, context.key);
- // TODO(lajava): Should we consider flexible tracks as well ?
- if (!track_size.IsContentSized())
- continue;
- for (const auto& group : context.value->SharedGroups()) {
- if (group.size() > 1) {
- auto grid_area_size =
- algorithm.Tracks(direction)[context.key].BaseSize();
- if (group.MaxAscent() + group.MaxDescent() > grid_area_size)
- return true;
- }
- }
- }
- return false;
-}
-
-void GridBaselineAlignment::Clear() {
- row_axis_alignment_context_.clear();
- col_axis_alignment_context_.clear();
+void GridBaselineAlignment::Clear(GridAxis baseline_axis) {
+ if (baseline_axis == kGridColumnAxis)
+ row_axis_alignment_context_.clear();
+ else
+ col_axis_alignment_context_.clear();
}
BaselineGroup::BaselineGroup(WritingMode block_flow,
diff --git a/chromium/third_party/blink/renderer/core/layout/grid_baseline_alignment.h b/chromium/third_party/blink/renderer/core/layout/grid_baseline_alignment.h
index a585074e82b..e39ab6d797e 100644
--- a/chromium/third_party/blink/renderer/core/layout/grid_baseline_alignment.h
+++ b/chromium/third_party/blink/renderer/core/layout/grid_baseline_alignment.h
@@ -10,8 +10,6 @@
namespace blink {
-class GridTrackSizingAlgorithm;
-
// These classes are used to implement the Baseline Alignment logic, as
// described in the CSS Box Alignment specification.
// https://drafts.csswg.org/css-align/#baseline-terms
@@ -142,10 +140,10 @@ class GridBaselineAlignment {
// Context the items belongs to.
// All the baseline offsets are updated accordingly based on the
// added item.
- void UpdateBaselineAlignmentContextIfNeeded(ItemPosition,
- unsigned shared_context,
- LayoutBox&,
- GridAxis);
+ void UpdateBaselineAlignmentContext(ItemPosition,
+ unsigned shared_context,
+ LayoutBox&,
+ GridAxis);
// Returns the baseline offset of a particular item, based on the
// max-ascent for its associated baseline-sharing group
@@ -154,18 +152,6 @@ class GridBaselineAlignment {
const LayoutBox&,
GridAxis) const;
- // Returns the sum of the 'max-ascent' and 'max-descent' of a particular
- // item's baseline-sharing group.
- base::Optional<LayoutUnit> ExtentForBaselineAlignment(ItemPosition,
- unsigned shared_context,
- const LayoutBox&,
- GridAxis) const;
-
- // Determines whether baseline algnment may affect the intrinsic
- // size of the grid container.
- bool BaselineMayAffectIntrinsicSize(const GridTrackSizingAlgorithm&,
- GridTrackSizingDirection) const;
-
// Sets the Grid Container's writing-mode so that we can avoid the
// dependecy of the LayoutGrid class for determining whether a grid
// item is orthogonal or not.
@@ -173,7 +159,7 @@ class GridBaselineAlignment {
// Clearing the Baseline Alignment context and their internal
// classes and data structures.
- void Clear();
+ void Clear(GridAxis);
private:
const BaselineGroup& GetBaselineGroupForChild(ItemPosition,
@@ -186,7 +172,6 @@ class GridBaselineAlignment {
LayoutUnit AscentForChild(const LayoutBox&, GridAxis) const;
LayoutUnit DescentForChild(const LayoutBox&, LayoutUnit, GridAxis) const;
bool IsDescentBaselineForChild(const LayoutBox&, GridAxis) const;
- bool IsBaselineContextComputed(GridAxis) const;
bool IsHorizontalBaselineAxis(GridAxis) const;
bool IsOrthogonalChildForBaseline(const LayoutBox&) const;
bool IsParallelToBaselineAxisForChild(const LayoutBox&, GridAxis) const;
diff --git a/chromium/third_party/blink/renderer/core/layout/grid_layout_utils.cc b/chromium/third_party/blink/renderer/core/layout/grid_layout_utils.cc
index 016f9c577a3..fbc5ba34e62 100644
--- a/chromium/third_party/blink/renderer/core/layout/grid_layout_utils.cc
+++ b/chromium/third_party/blink/renderer/core/layout/grid_layout_utils.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/core/layout/grid_layout_utils.h"
#include "third_party/blink/renderer/core/layout/layout_grid.h"
-#include "third_party/blink/renderer/platform/length_functions.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/layout/grid_layout_utils.h b/chromium/third_party/blink/renderer/core/layout/grid_layout_utils.h
index 0ee1910288b..2a0cfb82e16 100644
--- a/chromium/third_party/blink/renderer/core/layout/grid_layout_utils.h
+++ b/chromium/third_party/blink/renderer/core/layout/grid_layout_utils.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_GRID_LAYOUT_UTILS_H_
#include "third_party/blink/renderer/core/layout/layout_box.h"
-#include "third_party/blink/renderer/platform/layout_unit.h"
namespace blink {
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 950974a81c5..b92100e3b67 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
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.h"
-#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/core/layout/grid.h"
#include "third_party/blink/renderer/core/layout/grid_layout_utils.h"
#include "third_party/blink/renderer/core/layout/layout_grid.h"
@@ -78,6 +78,14 @@ void GridTrack::EnsureGrowthLimitIsBiggerThanBaseSize() {
growth_limit_ = base_size_;
}
+static GridAxis GridAxisForDirection(GridTrackSizingDirection direction) {
+ return direction == kForColumns ? kGridRowAxis : kGridColumnAxis;
+}
+
+static GridTrackSizingDirection GridDirectionForAxis(GridAxis axis) {
+ return axis == kGridRowAxis ? kForColumns : kForRows;
+}
+
class IndefiniteSizeStrategy final : public GridTrackSizingAlgorithmStrategy {
public:
IndefiniteSizeStrategy(GridTrackSizingAlgorithm& algorithm)
@@ -156,20 +164,74 @@ void GridTrackSizingAlgorithmStrategy::
child.SetOverrideContainingBlockContentLogicalHeight(size);
}
+LayoutSize GridTrackSizingAlgorithm::EstimatedGridAreaBreadthForChild(
+ const LayoutBox& child) const {
+ return {EstimatedGridAreaBreadthForChild(child, kForColumns),
+ EstimatedGridAreaBreadthForChild(child, kForRows)};
+}
+
+LayoutUnit GridTrackSizingAlgorithm::EstimatedGridAreaBreadthForChild(
+ const LayoutBox& child,
+ GridTrackSizingDirection direction) const {
+ const GridSpan& span = grid_.GridItemSpan(child, direction);
+ LayoutUnit grid_area_size;
+ bool grid_area_is_indefinite = false;
+ base::Optional<LayoutUnit> available_size = AvailableSpace(direction);
+ for (auto track_position : span) {
+ // We may need to estimate the grid area size before running the track
+ // sizing algorithm in order to perform the pre-layout of orthogonal
+ // items.
+ GridTrackSize track_size =
+ WasSetup() ? GetGridTrackSize(direction, track_position)
+ : RawGridTrackSize(direction, track_position);
+ GridLength max_track_size = track_size.MaxTrackBreadth();
+ if (max_track_size.IsContentSized() || max_track_size.IsFlex() ||
+ IsRelativeGridLengthAsAuto(max_track_size, direction)) {
+ grid_area_is_indefinite = true;
+ } else {
+ grid_area_size += ValueForLength(max_track_size.length(),
+ available_size.value_or(LayoutUnit()));
+ }
+ }
+
+ grid_area_size += layout_grid_->GuttersSize(
+ grid_, direction, span.StartLine(), span.IntegerSpan(), available_size);
+
+ GridTrackSizingDirection child_inline_direction =
+ GridLayoutUtils::FlowAwareDirectionForChild(*layout_grid_, child,
+ kForColumns);
+ if (grid_area_is_indefinite) {
+ return direction == child_inline_direction
+ ? std::max(child.MaxPreferredLogicalWidth(), grid_area_size)
+ : LayoutUnit(-1);
+ }
+ return grid_area_size;
+}
+
LayoutUnit GridTrackSizingAlgorithm::GridAreaBreadthForChild(
const LayoutBox& child,
- GridTrackSizingDirection direction) {
- if (direction == kForRows && sizing_state_ == kColumnSizingFirstIteration) {
+ GridTrackSizingDirection direction) const {
+ bool add_content_alignment_offset =
+ direction == kForColumns && sizing_state_ == kRowSizingFirstIteration;
+ if (direction == kForRows &&
+ (sizing_state_ == kColumnSizingFirstIteration ||
+ sizing_state_ == kColumnSizingSecondIteration)) {
DCHECK(GridLayoutUtils::IsOrthogonalChild(*layout_grid_, child));
- return layout_grid_->EstimatedGridAreaBreadthForChild(grid_, child,
- kForRows);
+ // TODO (jfernandez) Content Alignment should account for this heuristic
+ // https://github.com/w3c/csswg-drafts/issues/2697
+ if (sizing_state_ == kColumnSizingFirstIteration)
+ return EstimatedGridAreaBreadthForChild(child, kForRows);
+ add_content_alignment_offset = true;
}
- Vector<GridTrack>& all_tracks = Tracks(direction);
+ const Vector<GridTrack>& all_tracks = Tracks(direction);
const GridSpan& span = grid_.GridItemSpan(child, direction);
LayoutUnit grid_area_breadth;
- for (const auto& track_position : span)
+ for (const auto& track_position : span) {
grid_area_breadth += all_tracks[track_position].BaseSize();
+ if (add_content_alignment_offset)
+ grid_area_breadth += layout_grid_->GridItemOffset(direction);
+ }
grid_area_breadth +=
layout_grid_->GuttersSize(grid_, direction, span.StartLine(),
@@ -178,6 +240,23 @@ LayoutUnit GridTrackSizingAlgorithm::GridAreaBreadthForChild(
return grid_area_breadth;
}
+bool GridTrackSizingAlgorithm::IsIntrinsicSizedGridArea(const LayoutBox& child,
+ GridAxis axis) const {
+ DCHECK(WasSetup());
+ GridTrackSizingDirection direction = GridDirectionForAxis(axis);
+ const GridSpan& span = grid_.GridItemSpan(child, direction);
+ for (const auto& track_position : span) {
+ GridTrackSize track_size = RawGridTrackSize(direction, track_position);
+ // We consider fr units as 'auto' for the min sizing function.
+ // TODO(jfernandez): https://github.com/w3c/csswg-drafts/issues/2611
+ if (track_size.IsContentSized() || track_size.IsFitContent() ||
+ track_size.MinTrackBreadth().IsFlex() ||
+ (track_size.MaxTrackBreadth().IsFlex() && !AvailableSpace(direction)))
+ return true;
+ }
+ return false;
+}
+
bool GridTrackSizingAlgorithmStrategy::
UpdateOverrideContainingBlockContentSizeForChild(
LayoutBox& child,
@@ -194,28 +273,6 @@ bool GridTrackSizingAlgorithmStrategy::
return true;
}
-base::Optional<LayoutUnit>
-GridTrackSizingAlgorithmStrategy::ExtentForBaselineAlignment(
- const LayoutBox& child) const {
- const LayoutGrid& layout_grid = *GetLayoutGrid();
- GridAxis baseline_axis =
- GridLayoutUtils::IsOrthogonalChild(*GetLayoutGrid(), child)
- ? kGridRowAxis
- : kGridColumnAxis;
- if (!layout_grid.IsBaselineAlignmentForChild(child, baseline_axis))
- return base::nullopt;
-
- ItemPosition align =
- layout_grid.SelfAlignmentForChild(baseline_axis, child).GetPosition();
- const auto& span =
- baseline_axis == kGridColumnAxis
- ? algorithm_.GetGrid().GridItemSpan(child, kForRows)
- : algorithm_.GetGrid().GridItemSpan(child, kForColumns);
-
- return algorithm_.baseline_alignment_.ExtentForBaselineAlignment(
- align, span.StartLine(), child, baseline_axis);
-};
-
LayoutUnit GridTrackSizingAlgorithmStrategy::LogicalHeightForChild(
LayoutBox& child) const {
GridTrackSizingDirection child_block_direction =
@@ -234,11 +291,10 @@ LayoutUnit GridTrackSizingAlgorithmStrategy::LogicalHeightForChild(
child.LayoutIfNeeded();
- if (auto baseline_extent = ExtentForBaselineAlignment(child))
- return baseline_extent.value();
-
return child.LogicalHeight() +
- GridLayoutUtils::MarginLogicalHeightForChild(*GetLayoutGrid(), child);
+ GridLayoutUtils::MarginLogicalHeightForChild(*GetLayoutGrid(), child) +
+ algorithm_.BaselineOffsetForChild(child,
+ GridAxisForDirection(Direction()));
}
DISABLE_CFI_PERF
@@ -252,13 +308,10 @@ LayoutUnit GridTrackSizingAlgorithmStrategy::MinContentForChild(
// preferred width.
// See http://lists.w3.org/Archives/Public/www-style/2013Jan/0245.html
return child.MinPreferredLogicalWidth() +
- GridLayoutUtils::MarginLogicalWidthForChild(*GetLayoutGrid(), child);
- }
-
- if (Direction() == kForColumns && !AvailableSpace()) {
- DCHECK(GridLayoutUtils::IsOrthogonalChild(*GetLayoutGrid(), child));
- if (auto baseline_extent = ExtentForBaselineAlignment(child))
- return baseline_extent.value();
+ GridLayoutUtils::MarginLogicalWidthForChild(*GetLayoutGrid(),
+ child) +
+ algorithm_.BaselineOffsetForChild(child,
+ GridAxisForDirection(Direction()));
}
if (UpdateOverrideContainingBlockContentSizeForChild(
@@ -279,7 +332,10 @@ LayoutUnit GridTrackSizingAlgorithmStrategy::MaxContentForChild(
// preferred width.
// See http://lists.w3.org/Archives/Public/www-style/2013Jan/0245.html
return child.MaxPreferredLogicalWidth() +
- GridLayoutUtils::MarginLogicalWidthForChild(*GetLayoutGrid(), child);
+ GridLayoutUtils::MarginLogicalWidthForChild(*GetLayoutGrid(),
+ child) +
+ algorithm_.BaselineOffsetForChild(child,
+ GridAxisForDirection(Direction()));
}
if (UpdateOverrideContainingBlockContentSizeForChild(
@@ -310,8 +366,7 @@ LayoutUnit GridTrackSizingAlgorithmStrategy::MinSizeForChild(
algorithm_.GetGrid().GridItemSpan(child, Direction());
LayoutUnit max_breadth;
for (const auto& track_position : span) {
- GridTrackSize track_size =
- algorithm_.GetGridTrackSize(Direction(), track_position);
+ GridTrackSize track_size = GetGridTrackSize(Direction(), track_position);
if (!track_size.HasFixedMaxTrackBreadth())
return min_size;
max_breadth += ValueForLength(track_size.MaxTrackBreadth().length(),
@@ -333,11 +388,15 @@ LayoutUnit GridTrackSizingAlgorithmStrategy::MinSizeForChild(
if (!child_size.IsAuto())
return MinContentForChild(child);
+ LayoutUnit baseline_shim = algorithm_.BaselineOffsetForChild(
+ child, GridAxisForDirection(Direction()));
LayoutUnit grid_area_size =
algorithm_.GridAreaBreadthForChild(child, child_inline_direction);
- if (is_row_axis)
- return MinLogicalWidthForChild(child, child_min_size, grid_area_size);
+ if (is_row_axis) {
+ return MinLogicalWidthForChild(child, child_min_size, grid_area_size) +
+ baseline_shim;
+ }
bool override_size_has_changed =
UpdateOverrideContainingBlockContentSizeForChild(
@@ -347,39 +406,62 @@ LayoutUnit GridTrackSizingAlgorithmStrategy::MinSizeForChild(
return child.ComputeLogicalHeightUsing(kMinSize, child_min_size,
child.IntrinsicLogicalHeight()) +
GridLayoutUtils::MarginLogicalHeightForChild(*GetLayoutGrid(), child) +
- child.ScrollbarLogicalHeight();
+ child.ScrollbarLogicalHeight() + baseline_shim;
}
-void GridTrackSizingAlgorithm::UpdateBaselineAlignmentContextIfNeeded(
+bool GridTrackSizingAlgorithm::CanParticipateInBaselineAlignment(
+ const LayoutBox& child,
+ GridAxis baseline_axis) const {
+ if (child.NeedsLayout() ||
+ !layout_grid_->IsBaselineAlignmentForChild(child, baseline_axis))
+ return false;
+
+ // Baseline cyclic dependencies only happen with synthesized
+ // baselines. These cases include orthogonal or empty grid items
+ // and replaced elements.
+ bool is_parallel_to_baseline_axis =
+ baseline_axis == kGridColumnAxis
+ ? !GridLayoutUtils::IsOrthogonalChild(*layout_grid_, child)
+ : GridLayoutUtils::IsOrthogonalChild(*layout_grid_, child);
+ if (is_parallel_to_baseline_axis && child.FirstLineBoxBaseline() != -1)
+ return true;
+
+ // Baseline cyclic dependencies only happen in grid areas with
+ // intrinsically-sized tracks.
+ if (!IsIntrinsicSizedGridArea(child, baseline_axis))
+ return true;
+
+ return is_parallel_to_baseline_axis
+ ? !child.HasRelativeLogicalHeight()
+ : !child.HasRelativeLogicalWidth() &&
+ !child.StyleRef().LogicalWidth().IsAuto();
+}
+
+void GridTrackSizingAlgorithm::UpdateBaselineAlignmentContext(
LayoutBox& child,
GridAxis baseline_axis) {
- // TODO (lajava): We must ensure this method is not called as part of an
- // intrinsic size computation.
- if (!layout_grid_->IsBaselineAlignmentForChild(child, baseline_axis))
- return;
+ DCHECK(WasSetup());
+ DCHECK(CanParticipateInBaselineAlignment(child, baseline_axis));
+ DCHECK(!child.NeedsLayout());
- child.LayoutIfNeeded();
ItemPosition align =
layout_grid_->SelfAlignmentForChild(baseline_axis, child).GetPosition();
- const auto& span = baseline_axis == kGridColumnAxis
- ? grid_.GridItemSpan(child, kForRows)
- : grid_.GridItemSpan(child, kForColumns);
- baseline_alignment_.UpdateBaselineAlignmentContextIfNeeded(
- align, span.StartLine(), child, baseline_axis);
+ const auto& span =
+ grid_.GridItemSpan(child, GridDirectionForAxis(baseline_axis));
+ baseline_alignment_.UpdateBaselineAlignmentContext(align, span.StartLine(),
+ child, baseline_axis);
}
LayoutUnit GridTrackSizingAlgorithm::BaselineOffsetForChild(
const LayoutBox& child,
GridAxis baseline_axis) const {
- if (!layout_grid_->IsBaselineAlignmentForChild(child, baseline_axis))
+ if (!CanParticipateInBaselineAlignment(child, baseline_axis))
return LayoutUnit();
ItemPosition align =
layout_grid_->SelfAlignmentForChild(baseline_axis, child).GetPosition();
- const auto& span = baseline_axis == kGridColumnAxis
- ? grid_.GridItemSpan(child, kForRows)
- : grid_.GridItemSpan(child, kForColumns);
-
+ const auto& span =
+ grid_.GridItemSpan(child, GridDirectionForAxis(baseline_axis));
return baseline_alignment_.BaselineOffsetForChild(align, span.StartLine(),
child, baseline_axis);
}
@@ -484,11 +566,10 @@ double IndefiniteSizeStrategy::FindUsedFlexFraction(
// really matter as we know the track is a flex sized track. It'd be nice
// not to have to do that.
flex_fraction = std::max(
- flex_fraction, NormalizedFlexFraction(
- all_tracks[track_index],
- algorithm_.GetGridTrackSize(direction, track_index)
- .MaxTrackBreadth()
- .Flex()));
+ flex_fraction,
+ NormalizedFlexFraction(
+ all_tracks[track_index],
+ GetGridTrackSize(direction, track_index).MaxTrackBreadth().Flex()));
}
const Grid& grid = algorithm_.GetGrid();
@@ -496,8 +577,9 @@ double IndefiniteSizeStrategy::FindUsedFlexFraction(
return flex_fraction;
for (size_t i = 0; i < flexible_sized_tracks_index.size(); ++i) {
- GridIterator iterator(grid, direction, flexible_sized_tracks_index[i]);
- while (LayoutBox* grid_item = iterator.NextGridItem()) {
+ auto iterator =
+ grid.CreateIterator(direction, flexible_sized_tracks_index[i]);
+ while (LayoutBox* grid_item = iterator->NextGridItem()) {
const GridSpan& span = grid.GridItemSpan(*grid_item, direction);
// Do not include already processed items.
@@ -578,11 +660,10 @@ LayoutUnit IndefiniteSizeStrategy::MinContentForChild(LayoutBox& child) const {
// performed in LayoutGrid::LayoutOrthogonalWritingModeRoots.
DCHECK(GridLayoutUtils::IsOrthogonalChild(*GetLayoutGrid(), child));
- if (auto baseline_extent = ExtentForBaselineAlignment(child))
- return baseline_extent.value();
-
return child.LogicalHeight() +
- GridLayoutUtils::MarginLogicalHeightForChild(*GetLayoutGrid(), child);
+ GridLayoutUtils::MarginLogicalHeightForChild(*GetLayoutGrid(), child) +
+ algorithm_.BaselineOffsetForChild(child,
+ GridAxisForDirection(Direction()));
}
DISABLE_CFI_PERF
@@ -614,6 +695,7 @@ base::Optional<LayoutUnit> GridTrackSizingAlgorithm::AvailableSpace(
}
base::Optional<LayoutUnit> GridTrackSizingAlgorithm::AvailableSpace() const {
+ DCHECK(WasSetup());
return AvailableSpace(direction_);
}
@@ -701,9 +783,34 @@ GridTrackSize GridTrackSizingAlgorithm::RawGridTrackSize(
return track_styles[untranslated_index - auto_repeat_tracks_count];
}
+bool GridTrackSizingAlgorithm::IsRelativeGridLengthAsAuto(
+ const GridLength& length,
+ GridTrackSizingDirection direction) const {
+ if (!length.HasPercentage())
+ return false;
+ // TODO(svillar): we should remove the second check later. We need it
+ // because during the second iteration of the algorithm we set definite
+ // sizes in the grid container so percents would not resolve properly (it
+ // would think that the height is definite when it is not).
+ return !AvailableSpace(direction) ||
+ (direction == kForRows &&
+ !layout_grid_->CachedHasDefiniteLogicalHeight());
+}
+
+bool GridTrackSizingAlgorithm::IsRelativeSizedTrackAsAuto(
+ const GridTrackSize& track_size,
+ GridTrackSizingDirection direction) const {
+ if (track_size.MinTrackBreadth().HasPercentage())
+ return IsRelativeGridLengthAsAuto(track_size.MinTrackBreadth(), direction);
+ if (track_size.MaxTrackBreadth().HasPercentage())
+ return IsRelativeGridLengthAsAuto(track_size.MaxTrackBreadth(), direction);
+ return false;
+}
+
GridTrackSize GridTrackSizingAlgorithm::GetGridTrackSize(
GridTrackSizingDirection direction,
size_t translated_index) const {
+ DCHECK(WasSetup());
// Collapse empty auto repeat tracks if auto-fit.
if (grid_.HasAutoRepeatEmptyTracks(direction) &&
grid_.IsEmptyAutoRepeatTrack(direction, translated_index))
@@ -718,26 +825,23 @@ GridTrackSize GridTrackSizingAlgorithm::GetGridTrackSize(
GridLength max_track_breadth = track_size.MaxTrackBreadth();
// If the logical width/height of the grid container is indefinite, percentage
// values are treated as <auto>.
- if (min_track_breadth.HasPercentage() || max_track_breadth.HasPercentage()) {
- // TODO(svillar): we should remove the second check later. We need it
- // because during the second iteration of the algorithm we set definite
- // sizes in the grid container so percents would not resolve properly (it
- // would think that the height is definite when it is not).
- if (!AvailableSpace(direction) ||
- (direction == kForRows &&
- !layout_grid_->CachedHasDefiniteLogicalHeight())) {
- UseCounter::Count(layout_grid_->GetDocument(),
- WebFeature::kGridRowTrackPercentIndefiniteHeight);
- if (min_track_breadth.HasPercentage())
- min_track_breadth = Length(kAuto);
- if (max_track_breadth.HasPercentage())
- max_track_breadth = Length(kAuto);
+ if (IsRelativeSizedTrackAsAuto(track_size, direction)) {
+ if (direction == kForRows) {
+ Deprecation::CountDeprecation(
+ layout_grid_->GetDocument(),
+ WebFeature::kGridRowTrackPercentIndefiniteHeight);
}
+ if (min_track_breadth.HasPercentage())
+ min_track_breadth = Length(kAuto);
+ if (max_track_breadth.HasPercentage())
+ max_track_breadth = Length(kAuto);
}
// Flex sizes are invalid as a min sizing function. However we still can have
// a flexible |minTrackBreadth| if the track had a flex size directly (e.g.
// "1fr"), the spec says that in this case it implies an automatic minimum.
+ // TODO(jfernandez): https://github.com/w3c/csswg-drafts/issues/2611
+ // TODO(jfernandez): We may have to change IsIntrinsicSizedGridArea too.
if (min_track_breadth.IsFlex())
min_track_breadth = Length(kAuto);
@@ -1199,9 +1303,9 @@ void GridTrackSizingAlgorithm::ResolveIntrinsicTrackSizes() {
if (grid_.HasGridItems()) {
HashSet<LayoutBox*> items_set;
for (const auto& track_index : content_sized_tracks_index_) {
- GridIterator iterator(grid_, direction_, track_index);
+ auto iterator = grid_.CreateIterator(direction_, track_index);
GridTrack& track = Tracks(direction_)[track_index];
- while (LayoutBox* grid_item = iterator.NextGridItem()) {
+ while (auto* grid_item = iterator->NextGridItem()) {
if (items_set.insert(grid_item).is_new_entry) {
const GridSpan& span = grid_.GridItemSpan(*grid_item, direction_);
if (span.IntegerSpan() == 1) {
@@ -1472,13 +1576,27 @@ void GridTrackSizingAlgorithm::Setup(
}
Tracks(direction).resize(num_tracks);
- baseline_alignment_.SetBlockFlow(layout_grid_->StyleRef().GetWritingMode());
+ ComputeBaselineAlignmentContext();
needs_setup_ = false;
}
+void GridTrackSizingAlgorithm::ComputeBaselineAlignmentContext() {
+ if (sizing_state_ > kRowSizingFirstIteration)
+ return;
+ GridAxis axis = GridAxisForDirection(direction_);
+ baseline_alignment_.Clear(axis);
+ baseline_alignment_.SetBlockFlow(layout_grid_->StyleRef().GetWritingMode());
+ for (auto* child = layout_grid_->FirstInFlowChildBox(); child;
+ child = child->NextInFlowSiblingBox()) {
+ if (CanParticipateInBaselineAlignment(*child, axis))
+ UpdateBaselineAlignmentContext(*child, axis);
+ }
+}
+
// Described in https://drafts.csswg.org/css-grid/#algo-track-sizing
void GridTrackSizingAlgorithm::Run() {
+ DCHECK(WasSetup());
StateMachine state_machine(*this);
// Step 1.
@@ -1516,6 +1634,7 @@ void GridTrackSizingAlgorithm::Run() {
}
void GridTrackSizingAlgorithm::Reset() {
+ DCHECK(WasSetup());
sizing_state_ = kColumnSizingFirstIteration;
columns_.Shrink(0);
rows_.Shrink(0);
diff --git a/chromium/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.h b/chromium/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.h
index 07622f71df3..5127dd2cec0 100644
--- a/chromium/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.h
+++ b/chromium/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.h
@@ -94,18 +94,15 @@ class GridTrackSizingAlgorithm final {
// Required by LayoutGrid. Try to minimize the exposed surface.
const Grid& GetGrid() const { return grid_; }
- GridTrackSize GetGridTrackSize(GridTrackSizingDirection,
- size_t translated_index) const;
+ // TODO (jfernandez): We should remove any public getter for this attribute
+ // and encapsulate any access in the algorithm class.
+ Grid& GetMutableGrid() const { return grid_; }
LayoutUnit MinContentSize() const { return min_content_size_; };
LayoutUnit MaxContentSize() const { return max_content_size_; };
- void UpdateBaselineAlignmentContextIfNeeded(LayoutBox&, GridAxis);
LayoutUnit BaselineOffsetForChild(const LayoutBox&, GridAxis) const;
- bool BaselineMayAffectIntrinsicSize(
- GridTrackSizingDirection direction) const {
- return baseline_alignment_.BaselineMayAffectIntrinsicSize(*this, direction);
- }
- void ClearBaselineAlignment() { baseline_alignment_.Clear(); }
+
+ LayoutSize EstimatedGridAreaBreadthForChild(const LayoutBox& child) const;
Vector<GridTrack>& Tracks(GridTrackSizingDirection);
const Vector<GridTrack>& Tracks(GridTrackSizingDirection) const;
@@ -122,6 +119,12 @@ class GridTrackSizingAlgorithm final {
private:
base::Optional<LayoutUnit> AvailableSpace() const;
+ bool IsRelativeGridLengthAsAuto(const GridLength&,
+ GridTrackSizingDirection) const;
+ bool IsRelativeSizedTrackAsAuto(const GridTrackSize&,
+ GridTrackSizingDirection) const;
+ GridTrackSize GetGridTrackSize(GridTrackSizingDirection,
+ size_t translated_index) const;
GridTrackSize RawGridTrackSize(GridTrackSizingDirection,
size_t translated_index) const;
LayoutUnit ComputeTrackBasedSize() const;
@@ -147,9 +150,16 @@ class GridTrackSizingAlgorithm final {
Vector<GridTrack*>& tracks,
Vector<GridTrack*>* grow_beyond_growth_limits_tracks,
LayoutUnit& available_logical_space) const;
+ LayoutUnit EstimatedGridAreaBreadthForChild(const LayoutBox&,
+ GridTrackSizingDirection) const;
LayoutUnit GridAreaBreadthForChild(const LayoutBox&,
- GridTrackSizingDirection);
+ GridTrackSizingDirection) const;
+
+ void ComputeBaselineAlignmentContext();
+ void UpdateBaselineAlignmentContext(LayoutBox&, GridAxis);
+ bool CanParticipateInBaselineAlignment(const LayoutBox&, GridAxis) const;
+ bool IsIntrinsicSizedGridArea(const LayoutBox&, GridAxis) const;
void ComputeGridContainerIntrinsicSizes();
// Helper methods for step 4. Strech flexible tracks.
@@ -183,6 +193,7 @@ class GridTrackSizingAlgorithm final {
bool IsValidTransition() const;
// Data.
+ bool WasSetup() const { return !!strategy_; }
bool needs_setup_{true};
base::Optional<LayoutUnit> available_space_columns_;
base::Optional<LayoutUnit> available_space_rows_;
@@ -279,9 +290,6 @@ class GridTrackSizingAlgorithmStrategy {
base::Optional<LayoutUnit> = base::nullopt) const;
LayoutUnit ComputeTrackBasedSize() const;
- base::Optional<LayoutUnit> ExtentForBaselineAlignment(
- const LayoutBox& child) const;
-
GridTrackSizingDirection Direction() const { return algorithm_.direction_; }
double FindFrUnitSize(const GridSpan& tracks_span,
LayoutUnit left_over_space) const;
@@ -292,6 +300,11 @@ class GridTrackSizingAlgorithmStrategy {
return algorithm_.AvailableSpace();
}
+ GridTrackSize GetGridTrackSize(GridTrackSizingDirection direction,
+ size_t translated_index) const {
+ return algorithm_.GetGridTrackSize(direction, translated_index);
+ }
+
// Helper functions
static bool ShouldClearOverrideContainingBlockContentSizeForChild(
const LayoutGrid&,
diff --git a/chromium/third_party/blink/renderer/core/layout/hit_test_cache.cc b/chromium/third_party/blink/renderer/core/layout/hit_test_cache.cc
index 2d31ddef4a7..5b650e1ee6c 100644
--- a/chromium/third_party/blink/renderer/core/layout/hit_test_cache.cc
+++ b/chromium/third_party/blink/renderer/core/layout/hit_test_cache.cc
@@ -9,7 +9,8 @@
namespace blink {
-bool HitTestCache::LookupCachedResult(HitTestResult& hit_result,
+bool HitTestCache::LookupCachedResult(const HitTestLocation& location,
+ HitTestResult& hit_result,
uint64_t dom_tree_version) {
bool result = false;
HitHistogramMetric metric = HitHistogramMetric::MISS;
@@ -17,15 +18,14 @@ bool HitTestCache::LookupCachedResult(HitTestResult& hit_result,
metric = HitHistogramMetric::MISS_EXPLICIT_AVOID;
// For now we don't support rect based hit results.
} else if (dom_tree_version == dom_tree_version_ &&
- !hit_result.GetHitTestLocation().IsRectBasedTest()) {
+ !location.IsRectBasedTest()) {
for (const auto& cached_item : items_) {
- if (cached_item.GetHitTestLocation().Point() ==
- hit_result.GetHitTestLocation().Point()) {
+ if (cached_item.location.Point() == location.Point()) {
if (hit_result.GetHitTestRequest().EqualForCacheability(
- cached_item.GetHitTestRequest())) {
+ cached_item.result.GetHitTestRequest())) {
metric = HitHistogramMetric::HIT_EXACT_MATCH;
result = true;
- hit_result = cached_item;
+ hit_result = cached_item.result;
break;
}
metric = HitHistogramMetric::MISS_VALIDITY_RECT_MATCHES;
@@ -40,7 +40,17 @@ bool HitTestCache::LookupCachedResult(HitTestResult& hit_result,
return result;
}
-void HitTestCache::AddCachedResult(const HitTestResult& result,
+void HitTestCacheEntry::Trace(blink::Visitor* visitor) {
+ visitor->Trace(result);
+}
+
+void HitTestCacheEntry::CacheValues(const HitTestCacheEntry& other) {
+ *this = other;
+ result.CacheValues(other.result);
+}
+
+void HitTestCache::AddCachedResult(const HitTestLocation& location,
+ const HitTestResult& result,
uint64_t dom_tree_version) {
if (!result.IsCacheable())
return;
@@ -52,15 +62,17 @@ void HitTestCache::AddCachedResult(const HitTestResult& result,
return;
// For now don't support rect based or list based requests.
- if (result.GetHitTestLocation().IsRectBasedTest() ||
- result.GetHitTestRequest().ListBased())
+ if (location.IsRectBasedTest() || result.GetHitTestRequest().ListBased())
return;
if (dom_tree_version != dom_tree_version_)
Clear();
if (items_.size() < HIT_TEST_CACHE_SIZE)
items_.resize(update_index_ + 1);
- items_.at(update_index_).CacheValues(result);
+ HitTestCacheEntry cache_entry;
+ cache_entry.location = location;
+ cache_entry.result = result;
+ items_.at(update_index_).CacheValues(cache_entry);
dom_tree_version_ = dom_tree_version;
update_index_++;
diff --git a/chromium/third_party/blink/renderer/core/layout/hit_test_cache.h b/chromium/third_party/blink/renderer/core/layout/hit_test_cache.h
index c01a931521f..6ffdf8418e7 100644
--- a/chromium/third_party/blink/renderer/core/layout/hit_test_cache.h
+++ b/chromium/third_party/blink/renderer/core/layout/hit_test_cache.h
@@ -34,6 +34,16 @@ namespace blink {
// size of 1.
#define HIT_TEST_CACHE_SIZE (2)
+struct HitTestCacheEntry {
+ DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
+
+ void Trace(blink::Visitor*);
+ HitTestLocation location;
+ HitTestResult result;
+
+ void CacheValues(const HitTestCacheEntry&);
+};
+
class CORE_EXPORT HitTestCache final
: public GarbageCollectedFinalized<HitTestCache> {
public:
@@ -41,12 +51,16 @@ class CORE_EXPORT HitTestCache final
// Check the cache for a possible hit and update |result| if
// hit encountered; returning true. Otherwise false.
- bool LookupCachedResult(HitTestResult&, uint64_t dom_tree_version);
+ bool LookupCachedResult(const HitTestLocation&,
+ HitTestResult&,
+ uint64_t dom_tree_version);
void Clear();
// Adds a HitTestResult to the cache.
- void AddCachedResult(const HitTestResult&, uint64_t dom_tree_version);
+ void AddCachedResult(const HitTestLocation&,
+ const HitTestResult&,
+ uint64_t dom_tree_version);
void Trace(blink::Visitor*);
@@ -70,11 +84,14 @@ class CORE_EXPORT HitTestCache final
};
unsigned update_index_;
- HeapVector<HitTestResult, HIT_TEST_CACHE_SIZE> items_;
+
+ HeapVector<HitTestCacheEntry, HIT_TEST_CACHE_SIZE> items_;
uint64_t dom_tree_version_;
DISALLOW_COPY_AND_ASSIGN(HitTestCache);
};
} // namespace blink
+WTF_ALLOW_CLEAR_UNUSED_SLOTS_WITH_MEM_FUNCTIONS(blink::HitTestCacheEntry);
+
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_HIT_TEST_CACHE_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/hit_test_location.cc b/chromium/third_party/blink/renderer/core/layout/hit_test_location.cc
index c82e465c526..8d795dea108 100644
--- a/chromium/third_party/blink/renderer/core/layout/hit_test_location.cc
+++ b/chromium/third_party/blink/renderer/core/layout/hit_test_location.cc
@@ -28,6 +28,9 @@ namespace blink {
HitTestLocation::HitTestLocation()
: is_rect_based_(false), is_rectilinear_(true) {}
+HitTestLocation::HitTestLocation(const IntPoint& point)
+ : HitTestLocation(LayoutPoint(point)) {}
+
HitTestLocation::HitTestLocation(const LayoutPoint& point)
: point_(point),
bounding_box_(RectForPoint(point)),
@@ -44,6 +47,9 @@ HitTestLocation::HitTestLocation(const FloatPoint& point)
is_rect_based_(false),
is_rectilinear_(true) {}
+HitTestLocation::HitTestLocation(const DoublePoint& point)
+ : HitTestLocation(FloatPoint(point)) {}
+
HitTestLocation::HitTestLocation(const FloatPoint& point, const FloatQuad& quad)
: transformed_point_(point), transformed_rect_(quad), is_rect_based_(true) {
point_ = FlooredLayoutPoint(point);
@@ -51,12 +57,11 @@ HitTestLocation::HitTestLocation(const FloatPoint& point, const FloatQuad& quad)
is_rectilinear_ = quad.IsRectilinear();
}
-HitTestLocation::HitTestLocation(const LayoutPoint& center_point,
- const LayoutRectOutsets& padding)
- : point_(center_point),
- bounding_box_(RectForPoint(center_point, padding)),
- transformed_point_(center_point),
- is_rect_based_(!padding.IsZero()),
+HitTestLocation::HitTestLocation(const LayoutRect& rect)
+ : point_(rect.Center()),
+ bounding_box_(rect),
+ transformed_point_(point_),
+ is_rect_based_(true),
is_rectilinear_(true) {
transformed_rect_ = FloatQuad(FloatRect(bounding_box_));
}
diff --git a/chromium/third_party/blink/renderer/core/layout/hit_test_location.h b/chromium/third_party/blink/renderer/core/layout/hit_test_location.h
index ed335d89893..26704ceb2ba 100644
--- a/chromium/third_party/blink/renderer/core/layout/hit_test_location.h
+++ b/chromium/third_party/blink/renderer/core/layout/hit_test_location.h
@@ -41,12 +41,12 @@ class CORE_EXPORT HitTestLocation {
// Note that all points are in contents (aka "page") coordinate space for the
// document that is being hit tested.
HitTestLocation();
- HitTestLocation(const LayoutPoint&);
- HitTestLocation(const FloatPoint&);
- HitTestLocation(const FloatPoint&, const FloatQuad&);
- // Pass non-zero padding values to perform a rect-based hit test.
- HitTestLocation(const LayoutPoint& center_point,
- const LayoutRectOutsets& padding);
+ explicit HitTestLocation(const LayoutPoint&);
+ explicit HitTestLocation(const IntPoint&);
+ explicit HitTestLocation(const FloatPoint&);
+ explicit HitTestLocation(const DoublePoint&);
+ explicit HitTestLocation(const FloatPoint&, const FloatQuad&);
+ explicit HitTestLocation(const LayoutRect&);
HitTestLocation(const HitTestLocation&, const LayoutSize& offset);
HitTestLocation(const HitTestLocation&);
~HitTestLocation();
@@ -64,20 +64,10 @@ class CORE_EXPORT HitTestLocation {
}
// Returns the 1px x 1px hit test rect for a point.
- // TODO(pdr): Use a 0px x 0px rect for point-based tests and switch to
- // inclusive intersection checks which work with empty rects. Rect-based hit
- // testing is used even for point-based tests so a non-empty rect is currently
- // needed for LayoutRect::Intersects (see |HitTestLocation::IntersectsRect|).
+ // TODO(pdr): Should we be using a one-layout-unit rect instead?
static LayoutRect RectForPoint(const LayoutPoint& point) {
return LayoutRect(FlooredIntPoint(point), IntSize(1, 1));
}
- static LayoutRect RectForPoint(const LayoutPoint& point,
- const LayoutRectOutsets& padding) {
- LayoutRect rect = RectForPoint(point);
- rect.ExpandEdges(padding.Top(), padding.Right(), padding.Bottom(),
- padding.Left());
- return rect;
- }
bool Intersects(const LayoutRect&) const;
bool Intersects(const FloatRect&) const;
diff --git a/chromium/third_party/blink/renderer/core/layout/hit_test_result.cc b/chromium/third_party/blink/renderer/core/layout/hit_test_result.cc
index 2a15d5471d7..c45642f7473 100644
--- a/chromium/third_party/blink/renderer/core/layout/hit_test_result.cc
+++ b/chromium/third_party/blink/renderer/core/layout/hit_test_result.cc
@@ -52,34 +52,15 @@ HitTestResult::HitTestResult()
cacheable_(true),
is_over_embedded_content_view_(false) {}
-HitTestResult::HitTestResult(const HitTestRequest& request,
- const LayoutPoint& point)
- : hit_test_location_(point),
- hit_test_request_(request),
- cacheable_(true),
- point_in_inner_node_frame_(point),
- is_over_embedded_content_view_(false) {}
-
-HitTestResult::HitTestResult(const HitTestRequest& request,
- const LayoutPoint& center_point,
- const LayoutRectOutsets& padding)
- : hit_test_location_(center_point, padding),
- hit_test_request_(request),
- cacheable_(true),
- point_in_inner_node_frame_(center_point),
- is_over_embedded_content_view_(false) {}
-
HitTestResult::HitTestResult(const HitTestRequest& other_request,
- const HitTestLocation& other)
- : hit_test_location_(other),
- hit_test_request_(other_request),
+ const HitTestLocation& location)
+ : hit_test_request_(other_request),
cacheable_(true),
- point_in_inner_node_frame_(hit_test_location_.Point()),
+ point_in_inner_node_frame_(location.Point()),
is_over_embedded_content_view_(false) {}
HitTestResult::HitTestResult(const HitTestResult& other)
- : hit_test_location_(other.hit_test_location_),
- hit_test_request_(other.hit_test_request_),
+ : hit_test_request_(other.hit_test_request_),
cacheable_(other.cacheable_),
inner_node_(other.InnerNode()),
inner_possibly_pseudo_node_(other.inner_possibly_pseudo_node_),
@@ -98,7 +79,6 @@ HitTestResult::HitTestResult(const HitTestResult& other)
HitTestResult::~HitTestResult() = default;
HitTestResult& HitTestResult::operator=(const HitTestResult& other) {
- hit_test_location_ = other.hit_test_location_;
hit_test_request_ = other.hit_test_request_;
PopulateFromCachedResult(other);
@@ -117,7 +97,6 @@ bool HitTestResult::EqualForCacheability(const HitTestResult& other) const {
}
void HitTestResult::CacheValues(const HitTestResult& other) {
- *this = other;
hit_test_request_ =
other.hit_test_request_.GetType() & ~HitTestRequest::kAvoidCache;
}
@@ -237,12 +216,12 @@ LocalFrame* HitTestResult::InnerNodeFrame() const {
return nullptr;
}
-bool HitTestResult::IsSelected() const {
+bool HitTestResult::IsSelected(const HitTestLocation& location) const {
if (!inner_node_)
return false;
if (LocalFrame* frame = inner_node_->GetDocument().GetFrame())
- return frame->Selection().Contains(hit_test_location_.Point());
+ return frame->Selection().Contains(location.Point());
return false;
}
@@ -469,13 +448,9 @@ HitTestResult::NodeSet& HitTestResult::MutableListBasedTestResult() {
return *list_based_test_result_;
}
-void HitTestResult::ResolveRectBasedTest(
+HitTestLocation HitTestResult::ResolveRectBasedTest(
Node* resolved_inner_node,
const LayoutPoint& resolved_point_in_main_frame) {
- DCHECK(IsRectBasedTest());
- DCHECK(hit_test_location_.ContainsPoint(
- FloatPoint(resolved_point_in_main_frame)));
- hit_test_location_ = HitTestLocation(resolved_point_in_main_frame);
point_in_inner_node_frame_ = resolved_point_in_main_frame;
inner_node_ = nullptr;
inner_possibly_pseudo_node_ = nullptr;
@@ -488,7 +463,8 @@ void HitTestResult::ResolveRectBasedTest(
DCHECK(resolved_inner_node);
if (auto* layout_object = resolved_inner_node->GetLayoutObject())
layout_object->UpdateHitTestResult(*this, LayoutPoint());
- DCHECK(!IsRectBasedTest());
+
+ return HitTestLocation(resolved_point_in_main_frame);
}
Element* HitTestResult::InnerElement() const {
diff --git a/chromium/third_party/blink/renderer/core/layout/hit_test_result.h b/chromium/third_party/blink/renderer/core/layout/hit_test_result.h
index dd9f3b33e3d..817311af6aa 100644
--- a/chromium/third_party/blink/renderer/core/layout/hit_test_result.h
+++ b/chromium/third_party/blink/renderer/core/layout/hit_test_result.h
@@ -59,11 +59,6 @@ class CORE_EXPORT HitTestResult {
typedef HeapListHashSet<Member<Node>> NodeSet;
HitTestResult();
- HitTestResult(const HitTestRequest&, const LayoutPoint&);
- // Pass positive padding values to perform a rect-based hit test.
- HitTestResult(const HitTestRequest&,
- const LayoutPoint& center_point,
- const LayoutRectOutsets& padding);
HitTestResult(const HitTestRequest&, const HitTestLocation&);
HitTestResult(const HitTestResult&);
~HitTestResult();
@@ -71,7 +66,7 @@ class CORE_EXPORT HitTestResult {
void Trace(blink::Visitor*);
bool EqualForCacheability(const HitTestResult&) const;
- void CacheValues(const HitTestResult&);
+ void CacheValues(const HitTestResult& other);
// Populate this object based on another HitTestResult; similar to assignment
// operator but don't assign any of the request parameters. ie. This method
@@ -99,17 +94,6 @@ class CORE_EXPORT HitTestResult {
return is_over_embedded_content_view_;
}
- // Forwarded from HitTestLocation
- bool IsRectBasedTest() const { return hit_test_location_.IsRectBasedTest(); }
-
- // The hit-tested point in the coordinates of the main frame.
- const LayoutPoint& PointInMainFrame() const {
- return hit_test_location_.Point();
- }
- IntPoint RoundedPointInMainFrame() const {
- return RoundedIntPoint(PointInMainFrame());
- }
-
// The hit-tested point in the coordinates of the innerNode frame, the frame
// containing innerNode.
const LayoutPoint& PointInInnerNodeFrame() const {
@@ -135,9 +119,6 @@ class CORE_EXPORT HitTestResult {
void SetToShadowHostIfInRestrictedShadowRoot();
- const HitTestLocation& GetHitTestLocation() const {
- return hit_test_location_;
- }
const HitTestRequest& GetHitTestRequest() const { return hit_test_request_; }
void SetInnerNode(Node*);
@@ -148,7 +129,7 @@ class CORE_EXPORT HitTestResult {
is_over_embedded_content_view_ = b;
}
- bool IsSelected() const;
+ bool IsSelected(const HitTestLocation& location) const;
String Title(TextDirection&) const;
const AtomicString& AltDisplayString() const;
Image* GetImage() const;
@@ -191,14 +172,14 @@ class CORE_EXPORT HitTestResult {
// Collapse the rect-based test result into a single target at the specified
// location.
- void ResolveRectBasedTest(Node* resolved_inner_node,
- const LayoutPoint& resolved_point_in_main_frame);
+ HitTestLocation ResolveRectBasedTest(
+ Node* resolved_inner_node,
+ const LayoutPoint& resolved_point_in_main_frame);
private:
NodeSet& MutableListBasedTestResult(); // See above.
HTMLMediaElement* MediaElement() const;
- HitTestLocation hit_test_location_;
HitTestRequest hit_test_request_;
bool cacheable_;
diff --git a/chromium/third_party/blink/renderer/core/layout/intersection_geometry.cc b/chromium/third_party/blink/renderer/core/layout/intersection_geometry.cc
index c1e890d17fc..2efb1a9cfef 100644
--- a/chromium/third_party/blink/renderer/core/layout/intersection_geometry.cc
+++ b/chromium/third_party/blink/renderer/core/layout/intersection_geometry.cc
@@ -155,10 +155,26 @@ void IntersectionGeometry::ClipToRoot() {
LayoutBox* local_ancestor = nullptr;
if (!RootIsImplicit() || root_->GetDocument().IsInMainFrame())
local_ancestor = ToLayoutBox(root_);
- VisualRectFlags flags = static_cast<VisualRectFlags>(
- RuntimeEnabledFeatures::IntersectionObserverGeometryMapperEnabled()
- ? (kUseGeometryMapper | kEdgeInclusive)
- : kEdgeInclusive);
+ // If we're throttled, then we can't guarantee that geometry mapper is up to
+ // date, so we fall back to the slow path. If we're unthrottled, then ensure
+ // that prepaint has run and the frame view doesn't need a paint property
+ // update.
+#if DCHECK_IS_ON()
+ {
+ auto* frame_view = target_->GetFrameView();
+ auto* layout_view = frame_view->GetLayoutView();
+ DCHECK(frame_view->ShouldThrottleRendering() || !layout_view ||
+ !(layout_view->NeedsPaintPropertyUpdate() ||
+ layout_view->DescendantNeedsPaintPropertyUpdate()));
+ }
+#endif
+
+ VisualRectFlags use_geometry_mapper =
+ target_->GetFrameView()->ShouldThrottleRendering()
+ ? kDefaultVisualRectFlags
+ : kUseGeometryMapper;
+ VisualRectFlags flags =
+ static_cast<VisualRectFlags>(use_geometry_mapper | kEdgeInclusive);
does_intersect_ = target_->MapToVisualRectInAncestorSpace(
local_ancestor, intersection_rect_, flags);
if (!does_intersect_ || !local_ancestor)
@@ -172,17 +188,17 @@ void IntersectionGeometry::ClipToRoot() {
void IntersectionGeometry::MapTargetRectToTargetFrameCoordinates() {
Document& target_document = target_->GetDocument();
- LayoutSize scroll_position =
- LayoutSize(target_document.View()->GetScrollOffset());
MapRectUpToDocument(target_rect_, *target_, target_document);
- target_rect_.Move(-scroll_position);
}
void IntersectionGeometry::MapRootRectToRootFrameCoordinates() {
- root_->GetFrameView()->MapQuadToAncestorFrameIncludingScrollOffset(
- root_rect_, root_,
- RootIsImplicit() ? nullptr : root_->GetDocument().GetLayoutView(),
- kUseTransforms | kApplyContainerFlip);
+ root_rect_ = LayoutRect(
+ root_
+ ->LocalToAncestorQuad(
+ FloatQuad(FloatRect(root_rect_)),
+ RootIsImplicit() ? nullptr : root_->GetDocument().GetLayoutView(),
+ kUseTransforms | kApplyContainerFlip)
+ .BoundingBox());
}
void IntersectionGeometry::MapIntersectionRectToTargetFrameCoordinates() {
@@ -190,16 +206,10 @@ void IntersectionGeometry::MapIntersectionRectToTargetFrameCoordinates() {
if (RootIsImplicit()) {
LocalFrame* target_frame = target_document.GetFrame();
Frame& root_frame = target_frame->Tree().Top();
- LayoutSize scroll_position =
- LayoutSize(target_document.View()->GetScrollOffset());
if (target_frame != &root_frame)
MapRectDownToDocument(intersection_rect_, nullptr, target_document);
- intersection_rect_.Move(-scroll_position);
} else {
- LayoutSize scroll_position =
- LayoutSize(target_document.View()->GetScrollOffset());
MapRectUpToDocument(intersection_rect_, *root_, root_->GetDocument());
- intersection_rect_.Move(-scroll_position);
}
}
diff --git a/chromium/third_party/blink/renderer/core/layout/intrinsic_sizing_info.h b/chromium/third_party/blink/renderer/core/layout/intrinsic_sizing_info.h
new file mode 100644
index 00000000000..40ad57eeb58
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/intrinsic_sizing_info.h
@@ -0,0 +1,29 @@
+// 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_LAYOUT_INTRINSIC_SIZING_INFO_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_INTRINSIC_SIZING_INFO_H_
+
+#include "third_party/blink/renderer/platform/geometry/float_size.h"
+
+namespace blink {
+
+struct IntrinsicSizingInfo {
+ IntrinsicSizingInfo() : has_width(true), has_height(true) {}
+
+ FloatSize size;
+ FloatSize aspect_ratio;
+ bool has_width;
+ bool has_height;
+
+ void Transpose() {
+ size = size.TransposedSize();
+ aspect_ratio = aspect_ratio.TransposedSize();
+ std::swap(has_width, has_height);
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_INTRINSIC_SIZING_INFO_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/jank_tracker.cc b/chromium/third_party/blink/renderer/core/layout/jank_tracker.cc
index 3bb95502bab..24c209e7954 100644
--- a/chromium/third_party/blink/renderer/core/layout/jank_tracker.cc
+++ b/chromium/third_party/blink/renderer/core/layout/jank_tracker.cc
@@ -9,12 +9,14 @@
#include "third_party/blink/renderer/core/frame/location.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/paint/paint_layer.h"
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
namespace blink {
-static const float kTimerDelay = 3.0;
+static constexpr TimeDelta kTimerDelay = TimeDelta::FromSeconds(3);
+static const float kRegionGranularitySteps = 60.0;
static FloatPoint LogicalStart(const FloatRect& rect,
const LayoutObject& object) {
@@ -34,6 +36,11 @@ static float GetMoveDistance(const FloatRect& old_rect,
return std::max(fabs(location_delta.Width()), fabs(location_delta.Height()));
}
+static float RegionGranularityScale(const IntRect& viewport) {
+ return kRegionGranularitySteps /
+ std::min(viewport.Height(), viewport.Width());
+}
+
JankTracker::JankTracker(LocalFrameView* frame_view)
: frame_view_(frame_view),
score_(0.0),
@@ -99,6 +106,10 @@ void JankTracker::NotifyObjectPrePaint(const LayoutObject& object,
IntRect visible_new_visual_rect = RoundedIntRect(new_visual_rect_abs);
visible_new_visual_rect.Intersect(viewport);
+ float scale = RegionGranularityScale(viewport);
+ visible_old_visual_rect.Scale(scale);
+ visible_new_visual_rect.Scale(scale);
+
region_.Unite(Region(visible_old_visual_rect));
region_.Unite(Region(visible_new_visual_rect));
}
@@ -114,6 +125,7 @@ void JankTracker::NotifyPrePaintFinished() {
}
IntRect viewport = frame_view_->GetScrollableArea()->VisibleContentRect();
+ viewport.Scale(RegionGranularityScale(viewport));
double viewport_area = double(viewport.Width()) * double(viewport.Height());
double jank_fraction = region_.Area() / viewport_area;
@@ -122,7 +134,7 @@ void JankTracker::NotifyPrePaintFinished() {
DVLOG(1) << "viewport " << (jank_fraction * 100)
<< "% janked, raising score to " << score_;
- TRACE_EVENT_INSTANT1("blink", "FrameLayoutJank", TRACE_EVENT_SCOPE_THREAD,
+ TRACE_EVENT_INSTANT1("loading", "FrameLayoutJank", TRACE_EVENT_SCOPE_THREAD,
"viewportFraction", jank_fraction);
region_ = Region();
@@ -142,6 +154,13 @@ bool JankTracker::IsActive() {
return true;
}
+std::unique_ptr<TracedValue> JankTracker::TraceData() const {
+ std::unique_ptr<TracedValue> value = TracedValue::Create();
+ value->SetDouble("score", score_);
+ value->SetDouble("maxDistance", max_distance_);
+ return value;
+}
+
void JankTracker::TimerFired(TimerBase* timer) {
has_fired_ = true;
@@ -154,8 +173,9 @@ void JankTracker::TimerFired(TimerBase* timer) {
<< " is " << score_ << " with max move distance of "
<< max_distance_;
- TRACE_EVENT_INSTANT2("blink", "TotalLayoutJank", TRACE_EVENT_SCOPE_THREAD,
- "score", score_, "maxDistance", max_distance_);
+ TRACE_EVENT_INSTANT2("loading", "TotalLayoutJank", TRACE_EVENT_SCOPE_THREAD,
+ "data", TraceData(), "frame",
+ ToTraceValue(&frame_view_->GetFrame()));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/jank_tracker.h b/chromium/third_party/blink/renderer/core/layout/jank_tracker.h
index ee8a533d9a5..171bc0ca121 100644
--- a/chromium/third_party/blink/renderer/core/layout/jank_tracker.h
+++ b/chromium/third_party/blink/renderer/core/layout/jank_tracker.h
@@ -16,6 +16,7 @@ class LayoutObject;
class LayoutRect;
class LocalFrameView;
class PaintLayer;
+class TracedValue;
// Tracks "jank" from layout objects changing their visual location between
// animation frames.
@@ -32,9 +33,11 @@ class CORE_EXPORT JankTracker {
bool IsActive();
double Score() const { return score_; }
float MaxDistance() const { return max_distance_; }
+ void Dispose() { timer_.Stop(); }
private:
void TimerFired(TimerBase*);
+ std::unique_ptr<TracedValue> TraceData() const;
// This owns us.
UntracedMember<LocalFrameView> frame_view_;
diff --git a/chromium/third_party/blink/renderer/core/layout/jank_tracker_test.cc b/chromium/third_party/blink/renderer/core/layout/jank_tracker_test.cc
index bf258a2d320..dcc0fcd4f3f 100644
--- a/chromium/third_party/blink/renderer/core/layout/jank_tracker_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/jank_tracker_test.cc
@@ -33,6 +33,20 @@ TEST_F(JankTrackerTest, SimpleBlockMovement) {
EXPECT_FLOAT_EQ(60.0, GetJankTracker().MaxDistance());
}
+TEST_F(JankTrackerTest, GranularitySnapping) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #j { position: relative; width: 304px; height: 104px; }
+ </style>
+ <div id='j'></div>
+ )HTML");
+ GetDocument().getElementById("j")->setAttribute(HTMLNames::styleAttr,
+ AtomicString("top: 58px"));
+ GetFrameView().UpdateAllLifecyclePhases();
+ // Rect locations and sizes should snap to multiples of 600 / 60 = 10.
+ EXPECT_FLOAT_EQ(0.1, GetJankTracker().Score());
+}
+
TEST_F(JankTrackerTest, Transform) {
SetBodyInnerHTML(R"HTML(
<style>
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 c39c3d143a4..3ea1d5cb077 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_block.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_block.cc
@@ -50,6 +50,7 @@
#include "third_party/blink/renderer/core/layout/layout_flow_thread.h"
#include "third_party/blink/renderer/core/layout/layout_grid.h"
#include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h"
+#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -61,6 +62,7 @@
#include "third_party/blink/renderer/core/paint/block_painter.h"
#include "third_party/blink/renderer/core/paint/object_paint_invalidator.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/style/computed_style.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
@@ -158,12 +160,14 @@ void LayoutBlock::StyleWillChange(StyleDifference diff,
if (old_style && Parent()) {
bool old_style_contains_fixed_position =
- old_style->CanContainFixedPositionObjects(IsDocumentElement());
+ old_style->CanContainFixedPositionObjects(IsDocumentElement()) ||
+ ShouldApplyPaintContainment();
bool old_style_contains_absolute_position =
old_style_contains_fixed_position ||
old_style->CanContainAbsolutePositionObjects();
bool new_style_contains_fixed_position =
- new_style.CanContainFixedPositionObjects(IsDocumentElement());
+ new_style.CanContainFixedPositionObjects(IsDocumentElement()) ||
+ ShouldApplyPaintContainment();
bool new_style_contains_absolute_position =
new_style_contains_fixed_position ||
new_style.CanContainAbsolutePositionObjects();
@@ -259,7 +263,8 @@ void LayoutBlock::StyleDidChange(StyleDifference diff,
// transformed, or contain:paint is specified.
SetCanContainFixedPositionObjects(
IsLayoutView() || IsSVGForeignObject() || IsTextControl() ||
- new_style.CanContainFixedPositionObjects(IsDocumentElement()));
+ new_style.CanContainFixedPositionObjects(IsDocumentElement()) ||
+ ShouldApplyPaintContainment());
// It's possible for our border/padding to change, but for the overall logical
// width or height of the block to end up being the same. We keep track of
@@ -311,11 +316,7 @@ void LayoutBlock::AddChildBeforeDescendant(LayoutObject* new_child,
// If the requested insertion point is not one of our children, then this is
// because there is an anonymous container within this object that contains
// the beforeDescendant.
- if (before_descendant_container->IsAnonymousBlock()
- // Full screen layoutObjects and full screen placeholders act as anonymous
- // blocks, not tables:
- || before_descendant_container->IsLayoutFullScreen() ||
- before_descendant_container->IsLayoutFullScreenPlaceholder()) {
+ if (before_descendant_container->IsAnonymousBlock()) {
// Insert the child into the anonymous block box instead of here.
if (new_child->IsInline() ||
(new_child->IsFloatingOrOutOfFlowPositioned() && !IsFlexibleBox() &&
@@ -870,14 +871,13 @@ void LayoutBlock::MarkPositionedObjectsForLayout() {
}
}
-void LayoutBlock::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
- BlockPainter(*this).Paint(paint_info, paint_offset);
+void LayoutBlock::Paint(const PaintInfo& paint_info) const {
+ BlockPainter(*this).Paint(paint_info);
}
void LayoutBlock::PaintChildren(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
- BlockPainter(*this).PaintChildren(paint_info, paint_offset);
+ const LayoutPoint&) const {
+ BlockPainter(*this).PaintChildren(paint_info);
}
void LayoutBlock::PaintObject(const PaintInfo& paint_info,
@@ -885,38 +885,6 @@ void LayoutBlock::PaintObject(const PaintInfo& paint_info,
BlockPainter(*this).PaintObject(paint_info, paint_offset);
}
-LayoutUnit LayoutBlock::BlockDirectionOffset(
- const LayoutSize& offset_from_block) const {
- return IsHorizontalWritingMode() ? offset_from_block.Height()
- : offset_from_block.Width();
-}
-
-LayoutUnit LayoutBlock::InlineDirectionOffset(
- const LayoutSize& offset_from_block) const {
- return IsHorizontalWritingMode() ? offset_from_block.Width()
- : offset_from_block.Height();
-}
-
-LayoutUnit LayoutBlock::LogicalLeftSelectionOffset(
- const LayoutBlock* root_block,
- LayoutUnit position) const {
- // The border can potentially be further extended by our containingBlock().
- if (root_block != this)
- return ContainingBlock()->LogicalLeftSelectionOffset(
- root_block, position + LogicalTop());
- return LogicalLeftOffsetForContent();
-}
-
-LayoutUnit LayoutBlock::LogicalRightSelectionOffset(
- const LayoutBlock* root_block,
- LayoutUnit position) const {
- // The border can potentially be further extended by our containingBlock().
- if (root_block != this)
- return ContainingBlock()->LogicalRightSelectionOffset(
- root_block, position + LogicalTop());
- return LogicalRightOffsetForContent();
-}
-
TrackedLayoutBoxListHashSet* LayoutBlock::PositionedObjectsInternal() const {
return g_positioned_descendants_map ? g_positioned_descendants_map->at(this)
: nullptr;
@@ -1355,7 +1323,7 @@ void LayoutBlock::ComputeIntrinsicLogicalWidths(
LayoutUnit& min_logical_width,
LayoutUnit& max_logical_width) const {
// Size-contained elements don't consider their contents for preferred sizing.
- if (Style()->ContainsSize())
+ if (ShouldApplySizeContainment())
return;
if (ChildrenInline()) {
@@ -1749,7 +1717,7 @@ bool LayoutBlock::UseLogicalBottomMarginEdgeForInlineBlockBaseline() const {
// ancestors or siblings.
return (!Style()->IsOverflowVisible() &&
!ShouldIgnoreOverflowPropertyForInlineBlockBaseline()) ||
- Style()->ContainsSize();
+ ShouldApplySizeContainment();
}
LayoutUnit LayoutBlock::InlineBlockBaseline(
@@ -1978,24 +1946,28 @@ const char* LayoutBlock::GetName() const {
LayoutBlock* LayoutBlock::CreateAnonymousWithParentAndDisplay(
const LayoutObject* parent,
EDisplay display) {
- // FIXME: Do we need to convert all our inline displays to block-type in the
- // anonymous logic ?
- EDisplay new_display;
- LayoutBlock* new_box = nullptr;
- if (display == EDisplay::kFlex || display == EDisplay::kInlineFlex) {
- new_box = LayoutFlexibleBox::CreateAnonymous(&parent->GetDocument());
- new_display = EDisplay::kFlex;
- } else {
- new_box = LayoutBlockFlow::CreateAnonymous(&parent->GetDocument());
- new_display = EDisplay::kBlock;
- }
-
+ // TODO(layout-dev): Do we need to convert all our inline displays to block
+ // type in the anonymous logic?
+ const EDisplay new_display =
+ display == EDisplay::kFlex || display == EDisplay::kInlineFlex
+ ? EDisplay::kFlex
+ : EDisplay::kBlock;
scoped_refptr<ComputedStyle> new_style =
ComputedStyle::CreateAnonymousStyleWithDisplay(parent->StyleRef(),
new_display);
- parent->UpdateAnonymousChildStyle(*new_box, *new_style);
- new_box->SetStyle(std::move(new_style));
- return new_box;
+ parent->UpdateAnonymousChildStyle(nullptr, *new_style);
+ LayoutBlock* layout_block;
+ if (new_display == EDisplay::kFlex) {
+ layout_block = LayoutObjectFactory::CreateFlexibleBox(parent->GetDocument(),
+ *new_style);
+ } else {
+ DCHECK_EQ(new_display, EDisplay::kBlock);
+ layout_block =
+ LayoutObjectFactory::CreateBlockFlow(parent->GetDocument(), *new_style);
+ }
+ layout_block->SetDocumentForAnonymous(&parent->GetDocument());
+ layout_block->SetStyle(std::move(new_style));
+ return layout_block;
}
bool LayoutBlock::RecalcNormalFlowChildOverflowIfNeeded(
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_block.h b/chromium/third_party/blink/renderer/core/layout/layout_block.h
index b37858d572a..d3b523f344d 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_block.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_block.h
@@ -213,9 +213,6 @@ class CORE_EXPORT LayoutBlock : public LayoutBox {
PositionWithAffinity PositionForPoint(const LayoutPoint&) const override;
- LayoutUnit BlockDirectionOffset(const LayoutSize& offset_from_block) const;
- LayoutUnit InlineDirectionOffset(const LayoutSize& offset_from_block) const;
-
static LayoutBlock* CreateAnonymousWithParentAndDisplay(
const LayoutObject*,
EDisplay = EDisplay::kBlock);
@@ -303,11 +300,6 @@ class CORE_EXPORT LayoutBlock : public LayoutBox {
: LogicalWidth() - LogicalRightOffsetForContent();
}
- virtual LayoutUnit LogicalLeftSelectionOffset(const LayoutBlock* root_block,
- LayoutUnit position) const;
- virtual LayoutUnit LogicalRightSelectionOffset(const LayoutBlock* root_block,
- LayoutUnit position) const;
-
#if DCHECK_IS_ON()
void CheckPositionedObjectsNeedLayout();
#endif
@@ -369,11 +361,12 @@ class CORE_EXPORT LayoutBlock : public LayoutBox {
LayoutUnit BeforeMarginInLineDirection(LineDirectionMode) const;
- void Paint(const PaintInfo&, const LayoutPoint&) const override;
-
public:
- virtual void PaintObject(const PaintInfo&, const LayoutPoint&) const;
- virtual void PaintChildren(const PaintInfo&, const LayoutPoint&) const;
+ void Paint(const PaintInfo&) const override;
+ virtual void PaintObject(const PaintInfo&,
+ const LayoutPoint& paint_offset) const;
+ virtual void PaintChildren(const PaintInfo&,
+ const LayoutPoint& paint_offset) const;
void UpdateAfterLayout() override;
protected:
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 4d707008deb..0fcd90c4837 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
@@ -45,6 +45,7 @@
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h"
#include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h"
+#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
#include "third_party/blink/renderer/core/layout/layout_paged_flow_thread.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/line/glyph_overflow.h"
@@ -53,6 +54,8 @@
#include "third_party/blink/renderer/core/layout/line/line_width.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_line_height_metrics.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
+#include "third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_box_fragment.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"
@@ -63,6 +66,7 @@
#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"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
@@ -271,12 +275,13 @@ LayoutBlockFlow::LayoutBlockFlow(ContainerNode* node) : LayoutBlock(node) {
LayoutBlockFlow::~LayoutBlockFlow() = default;
-LayoutBlockFlow* LayoutBlockFlow::CreateAnonymous(Document* document) {
- // TODO(layout-ng): Find a way to check style.ForceLegacyLayout() Here
- LayoutBlockFlow* layout_block_flow = RuntimeEnabledFeatures::LayoutNGEnabled()
- ? new LayoutNGBlockFlow(nullptr)
- : new LayoutBlockFlow(nullptr);
+LayoutBlockFlow* LayoutBlockFlow::CreateAnonymous(
+ Document* document,
+ scoped_refptr<ComputedStyle> style) {
+ LayoutBlockFlow* layout_block_flow =
+ LayoutObjectFactory::CreateBlockFlow(*document, *style);
layout_block_flow->SetDocumentForAnonymous(document);
+ layout_block_flow->SetStyle(style);
return layout_block_flow;
}
@@ -2738,9 +2743,21 @@ void LayoutBlockFlow::RemoveFloatingObjectsFromDescendants() {
// If our children are inline, then the only boxes which could contain floats
// are atomic inlines (e.g. inline-block, float etc.) and these create
// formatting contexts, so can't pick up intruding floats from
- // ancestors/siblings - making them safe to skip.
- if (ChildrenInline())
+ // ancestors/siblings - making them safe to skip. We do need to examine the
+ // lines, though, as there may be pointers to the any of the objects that we
+ // are going to remove. Mark those lines dirty, to avoid accessing dangling
+ // pointers. Also, yikes!
+ if (ChildrenInline()) {
+ for (auto* line = FirstRootBox(); line; line = line->NextRootBox()) {
+ if (!line->IsDirty()) {
+ if (const auto* floats = line->FloatsPtr()) {
+ if (floats->size())
+ line->MarkDirty();
+ }
+ }
+ }
return;
+ }
for (LayoutObject* child = FirstChild(); child;
child = child->NextSibling()) {
// We don't skip blocks that create formatting contexts as they may have
@@ -3051,6 +3068,21 @@ LayoutInline* LayoutBlockFlow::InlineElementContinuation() const {
: nullptr;
}
+bool LayoutBlockFlow::NeedsAnonymousInlineWrapper() const {
+ // If ::first-line has background properties, create an anonymous inline
+ // wrapper. This helps paint code to handle it.
+ DCHECK(RuntimeEnabledFeatures::LayoutNGEnabled());
+ if (!GetDocument().GetStyleEngine().UsesFirstLineRules())
+ return false;
+ const ComputedStyle& first_line_style = FirstLineStyleRef();
+ const ComputedStyle& style = StyleRef();
+ if (&first_line_style == &style)
+ return false;
+ // We need an anonymous inline wrapper only if ::first-line has different
+ // background, but excessive anonymous inline will not harm.
+ return first_line_style.HasBackground();
+}
+
void LayoutBlockFlow::AddChild(LayoutObject* new_child,
LayoutObject* before_child) {
if (LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread()) {
@@ -3072,22 +3104,8 @@ void LayoutBlockFlow::AddChild(LayoutObject* new_child,
// children as blocks.
// So, if our children are currently inline and a block child has to be
// inserted, we move all our inline children into anonymous block boxes.
- bool child_is_block_level;
- bool layout_ng_enabled = RuntimeEnabledFeatures::LayoutNGEnabled();
- if (layout_ng_enabled && !FirstChild() &&
- (new_child->IsFloating() ||
- (new_child->IsOutOfFlowPositioned() &&
- !new_child->StyleRef().IsOriginalDisplayInlineType()))) {
- // TODO(kojii): We once forced all floats and OOF to create a block
- // container in LayoutNG, which turned out to be not a great way, but
- // completely turning this off breaks too much. When an OOF is an inline
- // type, we need to disable this so that we can compute the inline static
- // position. crbug.com/734554
- child_is_block_level = true;
- } else {
- child_is_block_level =
- !new_child->IsInline() && !new_child->IsFloatingOrOutOfFlowPositioned();
- }
+ bool child_is_block_level =
+ !new_child->IsInline() && !new_child->IsFloatingOrOutOfFlowPositioned();
if (ChildrenInline()) {
if (child_is_block_level) {
@@ -3101,6 +3119,22 @@ void LayoutBlockFlow::AddChild(LayoutObject* new_child,
DCHECK(before_child->IsAnonymousBlock());
DCHECK_EQ(before_child->Parent(), this);
}
+ } else if (UNLIKELY(RuntimeEnabledFeatures::LayoutNGEnabled() &&
+ IsLayoutNGContainingBlock(this) &&
+ NeedsAnonymousInlineWrapper())) {
+ LayoutObject* after_child =
+ before_child ? before_child->PreviousSibling() : LastChild();
+ if (after_child && after_child->IsAnonymous() &&
+ after_child->IsLayoutInline()) {
+ after_child->AddChild(new_child);
+ return;
+ }
+ LayoutInline* new_wrapper = LayoutInline::CreateAnonymous(&GetDocument());
+ new_wrapper->SetStyle(ComputedStyle::CreateAnonymousStyleWithDisplay(
+ StyleRef(), EDisplay::kInline));
+ LayoutBox::AddChild(new_wrapper, before_child);
+ new_wrapper->AddChild(new_child);
+ return;
}
} else if (!child_is_block_level) {
// This block has block children. We may want to put the new child into an
@@ -3124,8 +3158,7 @@ void LayoutBlockFlow::AddChild(LayoutObject* new_child,
LayoutBlockFlow* new_block = ToLayoutBlockFlow(CreateAnonymousBlock());
LayoutBox::AddChild(new_block, before_child);
// Reparent adjacent floating or out-of-flow siblings to the new box.
- if (!layout_ng_enabled)
- new_block->ReparentPrecedingFloatingOrOutOfFlowSiblings();
+ new_block->ReparentPrecedingFloatingOrOutOfFlowSiblings();
new_block->AddChild(new_child);
new_block->ReparentSubsequentFloatingOrOutOfFlowSiblings();
return;
@@ -3158,19 +3191,43 @@ void LayoutBlockFlow::RemoveChild(LayoutObject* old_child) {
return;
}
- // If this child is a block, and if our previous and next siblings are
- // both anonymous blocks with inline content, then we can go ahead and
- // fold the inline content back together.
+ // If this child is a block, and if our previous and next siblings are both
+ // anonymous blocks with inline content, then we can go ahead and fold the
+ // inline content back together. If only one of the siblings is such an
+ // anonymous blocks, check if the other sibling (and any of *its* siblings)
+ // are floating or out-of-flow positioned. In that case, they should be moved
+ // into the anonymous block.
LayoutObject* prev = old_child->PreviousSibling();
LayoutObject* next = old_child->NextSibling();
bool merged_anonymous_blocks = false;
if (prev && next && !old_child->IsInline() &&
- !old_child->VirtualContinuation() && prev->IsLayoutBlockFlow() &&
- next->IsLayoutBlockFlow()) {
- if (ToLayoutBlockFlow(prev)->MergeSiblingContiguousAnonymousBlock(
+ !old_child->VirtualContinuation()) {
+ if (prev->IsLayoutBlockFlow() && next->IsLayoutBlockFlow() &&
+ ToLayoutBlockFlow(prev)->MergeSiblingContiguousAnonymousBlock(
ToLayoutBlockFlow(next))) {
merged_anonymous_blocks = true;
next = nullptr;
+ } else if (prev->IsLayoutBlockFlow() &&
+ IsMergeableAnonymousBlock(ToLayoutBlockFlow(prev))) {
+ // The previous sibling is anonymous. Scan the next siblings and reparent
+ // any floating or out-of-flow positioned objects into the end of the
+ // previous anonymous block.
+ while (next && next->IsFloatingOrOutOfFlowPositioned()) {
+ LayoutObject* sibling = next->NextSibling();
+ MoveChildTo(ToLayoutBlockFlow(prev), next, nullptr, false);
+ next = sibling;
+ }
+ } else if (next->IsLayoutBlockFlow() &&
+ IsMergeableAnonymousBlock(ToLayoutBlockFlow(next))) {
+ // The next sibling is anonymous. Scan the previous siblings and reparent
+ // any floating or out-of-flow positioned objects into the start of the
+ // next anonymous block.
+ while (prev && prev->IsFloatingOrOutOfFlowPositioned()) {
+ LayoutObject* sibling = prev->PreviousSibling();
+ MoveChildTo(ToLayoutBlockFlow(next), prev,
+ ToLayoutBlockFlow(next)->FirstChild(), false);
+ prev = sibling;
+ }
}
}
@@ -3236,6 +3293,9 @@ void LayoutBlockFlow::MoveAllChildrenIncludingFloatsTo(
bool full_remove_insert) {
LayoutBlockFlow* to_block_flow = ToLayoutBlockFlow(to_block);
+ DCHECK(full_remove_insert ||
+ to_block_flow->ChildrenInline() == ChildrenInline());
+
// When a portion of the layout tree is being detached, anonymous blocks
// will be combined as their children are deleted. In this process, the
// anonymous block later in the tree is merged into the one preceding it.
@@ -4150,12 +4210,6 @@ bool LayoutBlockFlow::HitTestFloats(
if (!floating_objects_)
return false;
- LayoutPoint adjusted_location = accumulated_offset;
- if (IsLayoutView()) {
- ScrollOffset offset = ToLayoutView(this)->GetFrameView()->GetScrollOffset();
- adjusted_location.Move(LayoutSize(offset));
- }
-
const FloatingObjectSet& floating_object_set = floating_objects_->Set();
FloatingObjectSetIterator begin = floating_object_set.begin();
for (FloatingObjectSetIterator it = floating_object_set.end(); it != begin;) {
@@ -4169,7 +4223,7 @@ bool LayoutBlockFlow::HitTestFloats(
LayoutUnit y_offset = YPositionForFloatIncludingMargin(floating_object) -
floating_object.GetLayoutObject()->Location().Y();
LayoutPoint child_point = FlipFloatForWritingModeForChild(
- floating_object, adjusted_location + LayoutSize(x_offset, y_offset));
+ floating_object, accumulated_offset + LayoutSize(x_offset, y_offset));
if (floating_object.GetLayoutObject()->HitTestAllPhases(
result, location_in_container, child_point)) {
UpdateHitTestResult(
@@ -4373,7 +4427,7 @@ bool LayoutBlockFlow::CreatesNewFormattingContext() const {
IsFlexItemIncludingDeprecated() || IsTableCell() || IsTableCaption() ||
IsFieldset() || IsCustomItem() || IsDocumentElement() || IsGridItem() ||
IsWritingModeRoot() || Style()->Display() == EDisplay::kFlowRoot ||
- Style()->ContainsPaint() || Style()->ContainsLayout() ||
+ ShouldApplyPaintContainment() || ShouldApplyLayoutContainment() ||
Style()->SpecifiesColumns() ||
Style()->GetColumnSpan() == EColumnSpan::kAll) {
// The specs require this object to establish a new formatting context.
@@ -4414,17 +4468,6 @@ bool LayoutBlockFlow::CreatesNewFormattingContext() const {
return true;
}
- // NGBlockNode cannot compute margin collapsing across NG/non-NG boundary.
- // Create a new formatting context for non-NG node to prevent margin
- // collapsing.
- if (RuntimeEnabledFeatures::LayoutNGEnabled()) {
- if (Node* node = GetNode()) {
- if (node->IsElementNode() && ToElement(*node).ShouldForceLegacyLayout())
- return true;
- }
- return StyleRef().UserModify() != EUserModify::kReadOnly;
- }
-
return false;
}
@@ -4444,38 +4487,6 @@ void LayoutBlockFlow::MoveChildrenTo(LayoutBoxModelObject* to_box_model_object,
full_remove_insert);
}
-LayoutUnit LayoutBlockFlow::LogicalLeftSelectionOffset(
- const LayoutBlock* root_block,
- LayoutUnit position) const {
- LayoutUnit logical_left =
- LogicalLeftOffsetForLine(position, kDoNotIndentText);
- if (logical_left == LogicalLeftOffsetForContent())
- return LayoutBlock::LogicalLeftSelectionOffset(root_block, position);
-
- const LayoutBlock* cb = this;
- while (cb != root_block) {
- logical_left += cb->LogicalLeft();
- cb = cb->ContainingBlock();
- }
- return logical_left;
-}
-
-LayoutUnit LayoutBlockFlow::LogicalRightSelectionOffset(
- const LayoutBlock* root_block,
- LayoutUnit position) const {
- LayoutUnit logical_right =
- LogicalRightOffsetForLine(position, kDoNotIndentText);
- if (logical_right == LogicalRightOffsetForContent())
- return LayoutBlock::LogicalRightSelectionOffset(root_block, position);
-
- const LayoutBlock* cb = this;
- while (cb != root_block) {
- logical_right += cb->LogicalLeft();
- cb = cb->ContainingBlock();
- }
- return logical_right;
-}
-
RootInlineBox* LayoutBlockFlow::CreateRootInlineBox() {
return new RootInlineBox(LineLayoutItem(this));
}
@@ -4575,37 +4586,10 @@ LayoutBlockFlow::LayoutBlockFlowRareData& LayoutBlockFlow::EnsureRareData() {
}
void LayoutBlockFlow::PositionDialog() {
- HTMLDialogElement* dialog = ToHTMLDialogElement(GetNode());
- if (dialog->GetCenteringMode() == HTMLDialogElement::kNotCentered)
- return;
-
- bool can_center_dialog = (Style()->GetPosition() == EPosition::kAbsolute ||
- Style()->GetPosition() == EPosition::kFixed) &&
- Style()->HasAutoTopAndBottom();
-
- if (dialog->GetCenteringMode() == HTMLDialogElement::kCentered) {
- if (can_center_dialog)
- SetY(dialog->CenteredPosition());
- return;
- }
-
- DCHECK_EQ(dialog->GetCenteringMode(), HTMLDialogElement::kNeedsCentering);
- if (!can_center_dialog) {
- dialog->SetNotCentered();
- return;
- }
-
- auto* scrollable_area = GetDocument().View()->LayoutViewportScrollableArea();
- LayoutUnit top =
- LayoutUnit((Style()->GetPosition() == EPosition::kFixed)
- ? 0
- : scrollable_area->ScrollOffsetInt().Height());
-
- int visible_height = GetDocument().View()->Height();
- if (Size().Height() < visible_height)
- top += (visible_height - Size().Height()) / 2;
- SetY(top);
- dialog->SetCentered(top);
+ base::Optional<LayoutUnit> y =
+ ComputeAbsoluteDialogYPosition(*this, Size().Height());
+ if (y.has_value())
+ SetY(y.value());
}
void LayoutBlockFlow::SimplifiedNormalFlowInlineLayout() {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_block_flow.h b/chromium/third_party/blink/renderer/core/layout/layout_block_flow.h
index 6b0832a038b..8003efb0b11 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_block_flow.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_block_flow.h
@@ -102,7 +102,8 @@ class CORE_EXPORT LayoutBlockFlow : public LayoutBlock {
explicit LayoutBlockFlow(ContainerNode*);
~LayoutBlockFlow() override;
- static LayoutBlockFlow* CreateAnonymous(Document*);
+ static LayoutBlockFlow* CreateAnonymous(Document*,
+ scoped_refptr<ComputedStyle>);
bool BeingDestroyed() const { return being_destroyed_; }
bool IsLayoutBlockFlow() const final { return true; }
@@ -195,11 +196,6 @@ class CORE_EXPORT LayoutBlockFlow : public LayoutBlock {
return static_cast<RootInlineBox*>(LastLineBox());
}
- LayoutUnit LogicalLeftSelectionOffset(const LayoutBlock* root_block,
- LayoutUnit position) const override;
- LayoutUnit LogicalRightSelectionOffset(const LayoutBlock* root_block,
- LayoutUnit position) const override;
-
RootInlineBox* CreateAndAppendRootInlineBox();
RootInlineBox* ConstructLine(BidiRunList<BidiRun>&, const LineInfo&);
@@ -664,6 +660,7 @@ class CORE_EXPORT LayoutBlockFlow : public LayoutBlock {
void ReparentSubsequentFloatingOrOutOfFlowSiblings();
void ReparentPrecedingFloatingOrOutOfFlowSiblings();
+ bool NeedsAnonymousInlineWrapper() const;
void MakeChildrenInlineIfPossible();
void MakeChildrenNonInline(LayoutObject* insertion_point = nullptr);
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 9d80ecffbf2..cdb3d46b9c7 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
@@ -22,7 +22,7 @@
*/
#include "build/build_config.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_item.h"
#include "third_party/blink/renderer/core/layout/api/selection_state.h"
@@ -733,10 +733,6 @@ bool LayoutBlockFlow::CanContainFirstFormattedLine() const {
// line of an element. For example, the first line of an anonymous block
// box is only affected if it is the first child of its parent element.
// https://drafts.csswg.org/css-text-3/#text-indent-property
-
- // TODO(kojii): In LayoutNG, leading OOF creates a block box.
- // text-indent-first-line-002.html fails for this reason.
- // crbug.com/734554
return !(IsAnonymousBlock() && PreviousSibling());
}
@@ -1884,7 +1880,7 @@ void LayoutBlockFlow::ComputeInlinePreferredLogicalWidths(
}
// Ignore spaces after a list marker.
- if (child->IsListMarker())
+ if (child->IsListMarkerIncludingNG())
strip_front_spaces = true;
} else {
min_logical_width = std::max(min_logical_width, inline_min);
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_block_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_block_test.cc
index a3e95009066..a4fb4c9803e 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_block_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_block_test.cc
@@ -15,7 +15,9 @@ namespace blink {
class LayoutBlockTest : public RenderingTest {};
TEST_F(LayoutBlockTest, LayoutNameCalledWithNullStyle) {
- LayoutObject* obj = LayoutBlockFlow::CreateAnonymous(&GetDocument());
+ scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
+ LayoutObject* obj = LayoutBlockFlow::CreateAnonymous(&GetDocument(), style);
+ obj->SetStyleInternal(nullptr);
EXPECT_FALSE(obj->Style());
EXPECT_STREQ("LayoutBlockFlow (anonymous)",
obj->DecoratedName().Ascii().data());
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 d56be3429c1..9435e5ffc88 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_box.cc
@@ -73,11 +73,13 @@
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.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/style/shadow_list.h"
#include "third_party/blink/renderer/platform/geometry/double_rect.h"
#include "third_party/blink/renderer/platform/geometry/float_quad.h"
#include "third_party/blink/renderer/platform/geometry/float_rounded_rect.h"
#include "third_party/blink/renderer/platform/length_functions.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
@@ -270,6 +272,8 @@ void LayoutBox::StyleDidChange(StyleDifference diff,
ClearPercentHeightDescendants();
}
+ SetShouldClipOverflow(ComputeShouldClipOverflow());
+
// If our zoom factor changes and we have a defined scrollLeft/Top, we need to
// adjust that value into the new zoomed coordinate space. Note that the new
// scroll offset may be outside the normal min/max range of the scrollable
@@ -665,10 +669,9 @@ LayoutRect LayoutBox::ScrollRectToVisibleRecursive(
absolute_rect_for_parent =
GetScrollableArea()->ScrollIntoView(absolute_rect_to_scroll, params);
} else if (!parent_box && CanBeProgramaticallyScrolled()) {
- ScrollableArea* area_to_scroll =
- params.make_visible_in_visual_viewport
- ? GetFrameView()->GetScrollableArea()
- : GetFrameView()->LayoutViewportScrollableArea();
+ ScrollableArea* area_to_scroll = params.make_visible_in_visual_viewport
+ ? GetFrameView()->GetScrollableArea()
+ : GetFrameView()->LayoutViewport();
absolute_rect_for_parent =
area_to_scroll->ScrollIntoView(absolute_rect_to_scroll, params);
@@ -684,7 +687,7 @@ LayoutRect LayoutBox::ScrollRectToVisibleRecursive(
// end of the IPC call.
HTMLFrameOwnerElement* owner_element = GetDocument().LocalOwner();
if (owner_element && owner_element->GetLayoutObject() &&
- AllowedToPropageRecursiveScrollToParentFrame(params)) {
+ AllowedToPropagateRecursiveScrollToParentFrame(params)) {
parent_box = owner_element->GetLayoutObject()->EnclosingBox();
LayoutView* parent_view = owner_element->GetLayoutObject()->View();
absolute_rect_for_parent = EnclosingLayoutRect(
@@ -707,7 +710,7 @@ LayoutRect LayoutBox::ScrollRectToVisibleRecursive(
return parent_box->ScrollRectToVisibleRecursive(absolute_rect_for_parent,
params);
} else if (GetFrame()->IsLocalRoot() && !GetFrame()->IsMainFrame()) {
- if (AllowedToPropageRecursiveScrollToParentFrame(params)) {
+ if (AllowedToPropagateRecursiveScrollToParentFrame(params)) {
GetFrameView()->ScrollRectToVisibleInRemoteParent(
absolute_rect_for_parent, params);
}
@@ -989,9 +992,8 @@ LayoutUnit LayoutBox::VerticalScrollbarWidthClampedToContentBox() const {
LayoutUnit width(VerticalScrollbarWidth());
DCHECK_GE(width, LayoutUnit());
if (width) {
- LayoutUnit minimum_width = LogicalWidth() - BorderAndPaddingLogicalWidth();
- DCHECK_GE(minimum_width, LayoutUnit());
- width = std::min(width, minimum_width);
+ LayoutUnit maximum_width = LogicalWidth() - BorderAndPaddingLogicalWidth();
+ width = std::min(width, maximum_width.ClampNegativeToZero());
}
return width;
}
@@ -1028,7 +1030,7 @@ void LayoutBox::Autoscroll(const IntPoint& position_in_root_frame) {
return;
IntPoint absolute_position =
- frame_view->RootFrameToAbsolute(position_in_root_frame);
+ frame_view->ConvertFromRootFrame(position_in_root_frame);
ScrollRectToVisibleRecursive(
LayoutRect(absolute_position, LayoutSize(1, 1)),
WebScrollIntoViewParams(ScrollAlignment::kAlignToEdgeIfNeeded,
@@ -1036,12 +1038,8 @@ void LayoutBox::Autoscroll(const IntPoint& position_in_root_frame) {
kUserScroll));
}
-// There are two kinds of layoutObject that can autoscroll.
bool LayoutBox::CanAutoscroll() const {
- if (GetNode() && GetNode()->IsDocumentNode())
- return View()->GetFrameView()->IsScrollable();
-
- // Check for a box that can be scrolled in its own right.
+ // TODO(skobes): Remove one of these methods.
return CanBeScrolledAndHasScrollableArea();
}
@@ -1064,7 +1062,7 @@ IntSize LayoutBox::CalculateAutoscrollDirection(
ExcludeScrollbars(absolute_scrolling_box,
kExcludeOverlayScrollbarSizeForHitTesting);
- IntRect belt_box = View()->GetFrameView()->AbsoluteToRootFrame(
+ IntRect belt_box = View()->GetFrameView()->ConvertToRootFrame(
PixelSnappedIntRect(absolute_scrolling_box));
belt_box.Inflate(-kAutoscrollBeltSize);
IntPoint point = point_in_root_frame;
@@ -1113,41 +1111,33 @@ void LayoutBox::DispatchFakeMouseMoveEventSoon(EventHandler& event_handler) {
}
void LayoutBox::ScrollByRecursively(const ScrollOffset& delta) {
- if (delta.IsZero())
+ if (delta.IsZero() || !HasOverflowClip())
return;
- if (HasOverflowClip()) {
- PaintLayerScrollableArea* scrollable_area = GetScrollableArea();
- DCHECK(scrollable_area);
-
- ScrollOffset new_scroll_offset = scrollable_area->GetScrollOffset() + delta;
- scrollable_area->SetScrollOffset(new_scroll_offset, kProgrammaticScroll);
-
- // If this layer can't do the scroll we ask the next layer up that can
- // scroll to try.
- ScrollOffset remaining_scroll_offset =
- new_scroll_offset - scrollable_area->GetScrollOffset();
- if (!remaining_scroll_offset.IsZero() && Parent()) {
- if (LayoutBox* scrollable_box = EnclosingScrollableBox())
- scrollable_box->ScrollByRecursively(remaining_scroll_offset);
-
- LocalFrame* frame = GetFrame();
- if (frame && frame->GetPage())
- frame->GetPage()
- ->GetAutoscrollController()
- .UpdateAutoscrollLayoutObject();
+ PaintLayerScrollableArea* scrollable_area = GetScrollableArea();
+ DCHECK(scrollable_area);
+
+ ScrollOffset new_scroll_offset = scrollable_area->GetScrollOffset() + delta;
+ scrollable_area->SetScrollOffset(new_scroll_offset, kProgrammaticScroll);
+
+ // If this layer can't do the scroll we ask the next layer up that can
+ // scroll to try.
+ ScrollOffset remaining_scroll_offset =
+ new_scroll_offset - scrollable_area->GetScrollOffset();
+ if (!remaining_scroll_offset.IsZero() && Parent()) {
+ if (LayoutBox* scrollable_box = EnclosingScrollableBox())
+ scrollable_box->ScrollByRecursively(remaining_scroll_offset);
+
+ LocalFrame* frame = GetFrame();
+ if (frame && frame->GetPage()) {
+ frame->GetPage()
+ ->GetAutoscrollController()
+ .UpdateAutoscrollLayoutObject();
}
- } else if (View()->GetFrameView()) {
- // If we are here, we were called on a layoutObject that can be
- // programmatically scrolled, but doesn't have an overflow clip. Which means
- // that it is a document node that can be scrolled.
- // FIXME: Pass in DoubleSize. crbug.com/414283.
- View()->GetFrameView()->ScrollBy(delta, kUserScroll);
-
- // FIXME: If we didn't scroll the whole way, do we want to try looking at
- // the frames ownerElement?
- // https://bugs.webkit.org/show_bug.cgi?id=28237
}
+ // FIXME: If we didn't scroll the whole way, do we want to try looking at
+ // the frames ownerElement?
+ // https://bugs.webkit.org/show_bug.cgi?id=28237
}
bool LayoutBox::NeedsPreferredWidthsRecalculation() const {
@@ -1523,9 +1513,10 @@ bool LayoutBox::HitTestAllPhases(HitTestResult& result,
// If we have clipping, then we can't have any spillout.
// TODO(pdr): Why is this optimization not valid for the effective root?
if (!RootScrollerUtil::IsEffective(*this)) {
- LayoutRect overflow_box = (HasOverflowClip() || Style()->ContainsPaint())
- ? BorderBoxRect()
- : VisualOverflowRect();
+ LayoutRect overflow_box =
+ (HasOverflowClip() || ShouldApplyPaintContainment())
+ ? BorderBoxRect()
+ : VisualOverflowRect();
FlipForWritingMode(overflow_box);
LayoutPoint adjusted_location = accumulated_offset + Location();
overflow_box.MoveBy(adjusted_location);
@@ -1617,9 +1608,8 @@ bool LayoutBox::HitTestClippedOutByBorder(
Style()->GetRoundedBorderFor(border_rect));
}
-void LayoutBox::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
- BoxPainter(*this).Paint(paint_info, paint_offset);
+void LayoutBox::Paint(const PaintInfo& paint_info) const {
+ BoxPainter(*this).Paint(paint_info);
}
void LayoutBox::PaintBoxDecorationBackground(
@@ -1650,15 +1640,15 @@ bool LayoutBox::GetBackgroundPaintedExtent(LayoutRect& painted_extent) const {
}
BackgroundImageGeometry geometry(*this);
- // TODO(jchaffraix): This function should be rethought as it's called during
+ // TODO(schenney): This function should be rethought as it's called during
// and outside of the paint phase. Potentially returning different results at
- // different phases.
+ // different phases. crbug.com/732934
geometry.Calculate(nullptr, PaintPhase::kBlockBackground,
kGlobalPaintNormalPhase, Style()->BackgroundLayers(),
background_rect);
if (geometry.HasNonLocalGeometry())
return false;
- painted_extent = LayoutRect(geometry.DestRect());
+ painted_extent = LayoutRect(geometry.SnappedDestRect());
return true;
}
@@ -2115,8 +2105,8 @@ LayoutUnit LayoutBox::PerpendicularContainingBlockLogicalHeight() const {
if (!logical_height_length.IsFixed()) {
LayoutUnit fill_fallback_extent =
LayoutUnit(containing_block_style.IsHorizontalWritingMode()
- ? View()->GetFrameView()->VisibleContentSize().Height()
- : View()->GetFrameView()->VisibleContentSize().Width());
+ ? View()->GetFrameView()->Size().Height()
+ : View()->GetFrameView()->Size().Width());
LayoutUnit fill_available_extent =
ContainingBlock()->AvailableLogicalHeight(kExcludeMarginBorderPadding);
if (fill_available_extent == -1)
@@ -2403,14 +2393,6 @@ bool LayoutBox::PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const {
if (HasMask() || HasClipPath())
return false;
- // If the box has any kind of clip, we need issue paint invalidation to cover
- // the changed part of children when the box got resized. In SPv175 this is
- // handled by detecting paint property changes.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- if (HasClipRelatedProperty())
- return false;
- }
-
// If the box paints into its own backing, we can assume that it's painting
// may have some effect. For example, honoring the border-radius clip on
// a composited child paints into a mask for an otherwise non-painting
@@ -2643,8 +2625,9 @@ static float GetMaxWidthListMarker(const LayoutBox* layout_object) {
DISABLE_CFI_PERF
void LayoutBox::ComputeLogicalWidth(
LogicalExtentComputedValues& computed_values) const {
- computed_values.extent_ =
- Style()->ContainsSize() ? BorderAndPaddingLogicalWidth() : LogicalWidth();
+ computed_values.extent_ = ShouldApplySizeContainment()
+ ? BorderAndPaddingLogicalWidth()
+ : LogicalWidth();
computed_values.position_ = LogicalLeft();
computed_values.margins_.start_ = MarginStart();
computed_values.margins_.end_ = MarginEnd();
@@ -2797,9 +2780,14 @@ LayoutUnit LayoutBox::ComputeIntrinsicLogicalWidthUsing(
const Length& logical_width_length,
LayoutUnit available_logical_width,
LayoutUnit border_and_padding) const {
- if (logical_width_length.GetType() == kFillAvailable)
+ if (logical_width_length.GetType() == kFillAvailable) {
+ if (!IsHTMLMarqueeElement(GetNode())) {
+ UseCounter::Count(GetDocument(),
+ WebFeature::kCSSFillAvailableLogicalWidth);
+ }
return std::max(border_and_padding,
FillAvailableMeasure(available_logical_width));
+ }
LayoutUnit min_logical_width;
LayoutUnit max_logical_width;
@@ -3119,8 +3107,9 @@ static inline Length HeightForDocumentElement(const Document& document) {
void LayoutBox::ComputeLogicalHeight(
LogicalExtentComputedValues& computed_values) const {
- LayoutUnit height = Style()->ContainsSize() ? BorderAndPaddingLogicalHeight()
- : LogicalHeight();
+ LayoutUnit height = ShouldApplySizeContainment()
+ ? BorderAndPaddingLogicalHeight()
+ : LogicalHeight();
ComputeLogicalHeight(height, LogicalTop(), computed_values);
}
@@ -3310,10 +3299,15 @@ LayoutUnit LayoutBox::ComputeIntrinsicLogicalContentHeightUsing(
return IntrinsicSize().Height();
return intrinsic_content_height;
}
- if (logical_height_length.IsFillAvailable())
+ if (logical_height_length.IsFillAvailable()) {
+ if (!IsHTMLMarqueeElement(GetNode())) {
+ UseCounter::Count(GetDocument(),
+ WebFeature::kCSSFillAvailableLogicalHeight);
+ }
return ContainingBlock()->AvailableLogicalHeight(
kExcludeMarginBorderPadding) -
border_and_padding;
+ }
NOTREACHED();
return LayoutUnit();
}
@@ -3386,7 +3380,8 @@ LayoutUnit LayoutBox::ComputePercentageLogicalHeight(
LayoutUnit root_margin_border_padding_height;
while (!cb->IsLayoutView() &&
SkipContainingBlockForPercentHeightCalculation(cb)) {
- if (cb->IsBody() || cb->IsDocumentElement())
+ if ((cb->IsBody() || cb->IsDocumentElement()) &&
+ !HasOverrideContainingBlockContentLogicalHeight())
root_margin_border_padding_height += cb->MarginBefore() +
cb->MarginAfter() +
cb->BorderAndPaddingLogicalHeight();
@@ -3692,6 +3687,19 @@ LayoutUnit LayoutBox::ComputeReplacedLogicalHeightUsing(
LayoutUnit LayoutBox::AvailableLogicalHeight(
AvailableLogicalHeightType height_type) const {
+ if (RuntimeEnabledFeatures::LayoutNGEnabled()) {
+ // LayoutNG code is correct, Legacy code incorrectly ConstrainsMinMax
+ // when height is -1, and returns 0, not -1.
+ // The reason this code is NG-only is that this code causes perfomance
+ // regression for nested-percent-height-tables test case.
+ // This code gets executed 740 times in the test case.
+ // https://chromium-review.googlesource.com/c/chromium/src/+/1103289
+ LayoutUnit height =
+ AvailableLogicalHeightUsing(Style()->LogicalHeight(), height_type);
+ if (UNLIKELY(height == -1))
+ return height;
+ return ConstrainContentBoxLogicalHeightByMinMax(height, LayoutUnit(-1));
+ }
// http://www.w3.org/TR/CSS2/visudet.html#propdef-height - We are interested
// in the content height.
// FIXME: Should we pass intrinsicContentLogicalHeight() instead of -1 here?
@@ -3704,10 +3712,9 @@ LayoutUnit LayoutBox::AvailableLogicalHeightUsing(
const Length& h,
AvailableLogicalHeightType height_type) const {
if (IsLayoutView()) {
- return LayoutUnit(
- IsHorizontalWritingMode()
- ? ToLayoutView(this)->GetFrameView()->VisibleContentSize().Height()
- : ToLayoutView(this)->GetFrameView()->VisibleContentSize().Width());
+ return LayoutUnit(IsHorizontalWritingMode()
+ ? ToLayoutView(this)->GetFrameView()->Size().Height()
+ : ToLayoutView(this)->GetFrameView()->Size().Width());
}
// We need to stop here, since we don't want to increase the height of the
@@ -3765,6 +3772,7 @@ LayoutUnit LayoutBox::AvailableLogicalHeightUsing(
// mode.
LayoutUnit available_height =
ContainingBlockLogicalHeightForContent(height_type);
+ // FIXME: This is incorrect if available_height == -1 || 0
if (height_type == kExcludeMarginBorderPadding) {
// FIXME: Margin collapsing hasn't happened yet, so this incorrectly removes
// collapsed margins.
@@ -3807,8 +3815,7 @@ LayoutUnit LayoutBox::ContainingBlockLogicalWidthForPositioned(
// Don't use visibleContentRect since the PaintLayer's size has not been
// set yet.
LayoutSize viewport_size(
- frame_view->LayoutViewportScrollableArea()->ExcludeScrollbars(
- frame_view->Size()));
+ frame_view->LayoutViewport()->ExcludeScrollbars(frame_view->Size()));
return LayoutUnit(containing_block->IsHorizontalWritingMode()
? viewport_size.Width()
: viewport_size.Height());
@@ -3871,8 +3878,7 @@ LayoutUnit LayoutBox::ContainingBlockLogicalHeightForPositioned(
// Don't use visibleContentRect since the PaintLayer's size has not been
// set yet.
LayoutSize viewport_size(
- frame_view->LayoutViewportScrollableArea()->ExcludeScrollbars(
- frame_view->Size()));
+ frame_view->LayoutViewport()->ExcludeScrollbars(frame_view->Size()));
return containing_block->IsHorizontalWritingMode()
? viewport_size.Height()
: viewport_size.Width();
@@ -5112,7 +5118,12 @@ LayoutRectOutsets LayoutBox::ComputeVisualEffectOverflowOutsets() {
AddOutlineRects(outline_rects, LayoutPoint(),
OutlineRectsShouldIncludeBlockVisualOverflow());
LayoutRect rect = UnionRectEvenIfEmpty(outline_rects);
- SetOutlineMayBeAffectedByDescendants(rect.Size() != Size());
+ bool outline_affected = rect.Size() != Size();
+ // LayoutNG will set this flag for inline descendants
+ // which are not visible to Legacy code.
+ if (IsLayoutNGMixin())
+ outline_affected |= OutlineMayBeAffectedByDescendants();
+ SetOutlineMayBeAffectedByDescendants(outline_affected);
rect.Inflate(style.OutlineOutsetExtent());
outsets.Unite(rect.ToOutsets(Size()));
}
@@ -5380,12 +5391,15 @@ LayoutRect LayoutBox::LayoutOverflowRectForPropagation(
LayoutRect rect = BorderBoxRect();
// We want to include the margin, but only when it adds height. Quirky margins
// don't contribute height nor do the margins of self-collapsing blocks.
- if (!StyleRef().HasMarginAfterQuirk() && !IsSelfCollapsingBlock())
+ if (!StyleRef().HasMarginAfterQuirk() && !IsSelfCollapsingBlock()) {
+ const ComputedStyle* container_style =
+ container ? container->Style() : nullptr;
rect.Expand(IsHorizontalWritingMode()
- ? LayoutSize(LayoutUnit(), MarginAfter())
- : LayoutSize(MarginAfter(), LayoutUnit()));
+ ? LayoutSize(LayoutUnit(), MarginAfter(container_style))
+ : LayoutSize(MarginAfter(container_style), LayoutUnit()));
+ }
- if (!HasOverflowClip())
+ if (!HasOverflowClip() && !ShouldApplyLayoutContainment())
rect.Unite(LayoutOverflowRect());
bool has_transform = HasLayer() && Layer()->Transform();
@@ -5489,20 +5503,6 @@ LayoutPoint LayoutBox::FlipForWritingModeForChild(
point.Y());
}
-LayoutPoint LayoutBox::FlipForWritingModeForChildForPaint(
- const LayoutBox* child,
- const LayoutPoint& point) const {
- // Do nothing unless in FlippedBlocks(). Fast path optimization
- if (!Style()->IsFlippedBlocksWritingMode())
- return point;
- // If child will be painted by LayoutNG, and will use fragment.Offset(),
- // flip is not needed.
- if (!AdjustPaintOffsetScope::WillUseLegacyLocation(child))
- return point;
-
- return FlipForWritingModeForChild(child, point);
-}
-
LayoutBox* LayoutBox::LocationContainer() const {
// Location of a non-root SVG object derived from LayoutBox should not be
// affected by writing-mode of the containing box (SVGRoot).
@@ -5970,7 +5970,7 @@ void LayoutBox::RemoveSnapArea(const LayoutBox& snap_area) {
}
}
-bool LayoutBox::AllowedToPropageRecursiveScrollToParentFrame(
+bool LayoutBox::AllowedToPropagateRecursiveScrollToParentFrame(
const WebScrollIntoViewParams& params) {
if (!GetFrameView()->SafeToPropagateScrollToParent())
return false;
@@ -5978,12 +5978,7 @@ bool LayoutBox::AllowedToPropageRecursiveScrollToParentFrame(
if (params.GetScrollType() != kProgrammaticScroll)
return true;
- if (!IsSupportedInFeaturePolicy(
- mojom::FeaturePolicyFeature::kVerticalScroll)) {
- return true;
- }
- return GetFrame()->IsFeatureEnabled(
- mojom::FeaturePolicyFeature::kVerticalScroll);
+ return !GetDocument().IsVerticalScrollEnforced();
}
SnapAreaSet* LayoutBox::SnapAreas() const {
@@ -6038,8 +6033,8 @@ LayoutRect LayoutBox::DebugRect() const {
return rect;
}
-bool LayoutBox::ShouldClipOverflow() const {
- return HasOverflowClip() || StyleRef().ContainsPaint() || HasControlClip();
+bool LayoutBox::ComputeShouldClipOverflow() const {
+ return HasOverflowClip() || ShouldApplyPaintContainment() || HasControlClip();
}
void LayoutBox::MutableForPainting::
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 924dcac603a..f780aa5975a 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_box.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_box.h
@@ -29,6 +29,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/custom/custom_layout_child.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
+#include "third_party/blink/renderer/core/layout/min_max_size.h"
#include "third_party/blink/renderer/core/layout/overflow_model.h"
#include "third_party/blink/renderer/platform/scroll/scroll_types.h"
#include "third_party/blink/renderer/platform/wtf/compiler.h"
@@ -561,8 +562,8 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
// IE extensions. Used to calculate offsetWidth/Height. Overridden by inlines
// (LayoutFlow) to return the remaining width on a given line (and the height
// of a single line).
- LayoutUnit OffsetWidth() const override { return frame_rect_.Width(); }
- LayoutUnit OffsetHeight() const override { return frame_rect_.Height(); }
+ LayoutUnit OffsetWidth() const final { return frame_rect_.Width(); }
+ LayoutUnit OffsetHeight() const final { return frame_rect_.Height(); }
int PixelSnappedOffsetWidth(const Element*) const final;
int PixelSnappedOffsetHeight(const Element*) const final;
@@ -671,7 +672,7 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
FloatRect LocalBoundingBoxRectForAccessibility() const final;
void UpdateLayout() override;
- void Paint(const PaintInfo&, const LayoutPoint&) const override;
+ void Paint(const PaintInfo&) const override;
virtual bool IsInSelfHitTestingPhase(HitTestAction hit_test_action) const {
return hit_test_action == kHitTestForeground;
@@ -1057,11 +1058,6 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
int caret_offset,
LayoutUnit* extra_width_to_end_of_line = nullptr) const override;
- // Returns whether content which overflows should be clipped. This is not just
- // because of overflow clip, but other types of clip as well, such as
- // control clips or contain: paint.
- virtual bool ShouldClipOverflow() const;
-
// Returns the intersection of all overflow clips which apply.
virtual LayoutRect OverflowClipRect(
const LayoutPoint& location,
@@ -1072,9 +1068,11 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
// for this object.
LayoutRect ClippingRect(const LayoutPoint& location) const;
- virtual void PaintBoxDecorationBackground(const PaintInfo&,
- const LayoutPoint&) const;
- virtual void PaintMask(const PaintInfo&, const LayoutPoint&) const;
+ virtual void PaintBoxDecorationBackground(
+ const PaintInfo&,
+ const LayoutPoint& paint_offset) const;
+ virtual void PaintMask(const PaintInfo&,
+ const LayoutPoint& paint_offset) const;
void ImageChanged(WrappedImagePtr,
CanDeferInvalidation,
const IntRect* = nullptr) override;
@@ -1148,17 +1146,12 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
LinePositionMode = kPositionOnContainingLine) const override;
LayoutPoint OffsetPoint(const Element* parent) const;
- LayoutUnit OffsetLeft(const Element*) const override;
- LayoutUnit OffsetTop(const Element*) const override;
+ LayoutUnit OffsetLeft(const Element*) const final;
+ LayoutUnit OffsetTop(const Element*) const final;
LayoutPoint FlipForWritingModeForChild(const LayoutBox* child,
const LayoutPoint&) const;
- // NG: Like FlipForWritingModeForChild, except that it will not flip
- // if LayoutBox will be painted by NG using fragment.Offset.
- LayoutPoint FlipForWritingModeForChildForPaint(const LayoutBox* child,
- const LayoutPoint&) const;
-
WARN_UNUSED_RESULT LayoutUnit FlipForWritingMode(LayoutUnit position) const {
// The offset is in the block direction (y for horizontal writing modes, x
// for vertical writing modes).
@@ -1417,7 +1410,33 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
: LayoutRect(LayoutPoint(), PreviousSize());
}
+ // This function calculates the preferred widths for an object.
+ //
+ // This function is only expected to be called if
+ // the boolean preferredLogicalWidthsDirty is true. It also MUST clear the
+ // boolean before returning.
+ //
+ // See INTRINSIC SIZES / PREFERRED LOGICAL WIDTHS in layout_object.h for more
+ // details about those widths.
+ //
+ // This function is public only for use by LayoutNG. Other callers should go
+ // through MinPreferredLogicalWidth/MaxPreferredLogicalWidth.
+ virtual void ComputePreferredLogicalWidths() {
+ ClearPreferredLogicalWidthsDirty();
+ }
+
+ // LayoutNG can use this function to update our cache of preferred logical
+ // widths when the layout object is managed by NG. Should not be called by
+ // regular code.
+ // Also clears the "dirty" flag for preferred widths.
+ void SetPreferredLogicalWidthsFromNG(MinMaxSize sizes) {
+ min_preferred_logical_width_ = sizes.min_size;
+ max_preferred_logical_width_ = sizes.max_size;
+ ClearPreferredLogicalWidthsDirty();
+ }
+
protected:
+ virtual bool ComputeShouldClipOverflow() const;
virtual LayoutRect ControlClipRect(const LayoutPoint&) const {
return LayoutRect();
}
@@ -1601,18 +1620,6 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
LayoutUnit& min_logical_width,
LayoutUnit& max_logical_width) const;
- // This function calculates the preferred widths for an object.
- //
- // This function is only expected to be called if
- // the boolean preferredLogicalWidthsDirty is true. It also MUST clear the
- // boolean before returning.
- //
- // See INTRINSIC SIZES / PREFERRED LOGICAL WIDTHS in LayoutObject.h for more
- // details about those widths.
- virtual void ComputePreferredLogicalWidths() {
- ClearPreferredLogicalWidthsDirty();
- }
-
LayoutBoxRareData& EnsureRareData() {
if (!rare_data_)
rare_data_ = std::make_unique<LayoutBoxRareData>();
@@ -1642,7 +1649,7 @@ class CORE_EXPORT LayoutBox : public LayoutBoxModelObject {
// Returns true when the current recursive scroll into visible could propagate
// to parent frame.
- bool AllowedToPropageRecursiveScrollToParentFrame(
+ bool AllowedToPropagateRecursiveScrollToParentFrame(
const WebScrollIntoViewParams&);
LayoutRect DebugRect() const override;
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 9cedc31e5c3..778ffee5aaf 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
@@ -37,6 +37,7 @@
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/core/paint/object_paint_invalidator.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/style/shadow_list.h"
#include "third_party/blink/renderer/platform/length_functions.h"
#include "third_party/blink/renderer/platform/scroll/main_thread_scrolling_reason.h"
@@ -224,10 +225,8 @@ void LayoutBoxModelObject::StyleWillChange(StyleDifference diff,
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
ObjectPaintInvalidator(*this).SlowSetPaintingLayerNeedsRepaint();
} else {
- // The following disablers are valid because we need to invalidate based
- // on the current status.
+ // We need to invalidate based on the current compositing status.
DisableCompositingQueryAsserts compositing_disabler;
- DisablePaintInvalidationStateAsserts paint_disabler;
ObjectPaintInvalidator(*this)
.InvalidatePaintIncludingNonCompositingDescendants();
}
@@ -293,7 +292,7 @@ void LayoutBoxModelObject::StyleDidChange(StyleDifference diff,
Layer()->UpdateFilters(old_style, StyleRef());
Layer()->UpdateClipPath(old_style, StyleRef());
// Calls DestroyLayer() which clears the layer.
- Layer()->RemoveOnlyThisLayerAfterStyleChange();
+ Layer()->RemoveOnlyThisLayerAfterStyleChange(old_style);
if (EverHadLayout())
SetChildNeedsLayout();
if (had_transform_related_property) {
@@ -342,23 +341,6 @@ void LayoutBoxModelObject::StyleDidChange(StyleDifference diff,
}
}
- // Fixed-position is painted using transform. In the case that the object
- // gets the same layout after changing position property, although no
- // re-raster (rect-based invalidation) is needed, display items should
- // still update their paint offset.
- // For SPv175, invalidation for paint offset change is done during PrePaint.
- if (old_style && !RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- bool new_style_is_fixed_position =
- Style()->GetPosition() == EPosition::kFixed;
- bool old_style_is_fixed_position =
- old_style->GetPosition() == EPosition::kFixed;
- if (new_style_is_fixed_position != old_style_is_fixed_position) {
- ObjectPaintInvalidator(*this)
- .InvalidateDisplayItemClientsIncludingNonCompositingDescendants(
- PaintInvalidationReason::kStyle);
- }
- }
-
// The used style for body background may change due to computed style change
// on the document element because of background stealing.
// Refer to backgroundStolenForBeingBody() and
@@ -430,8 +412,7 @@ void LayoutBoxModelObject::StyleDidChange(StyleDifference diff,
}
}
- if (old_style && RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- HasLayer() && !Layer()->NeedsRepaint()) {
+ if (old_style && HasLayer() && !Layer()->NeedsRepaint()) {
if (old_style->BackfaceVisibility() != StyleRef().BackfaceVisibility()) {
// We need to repaint the layer to update the backface visibility value of
// the paint chunk.
@@ -1035,10 +1016,8 @@ bool LayoutBoxModelObject::IsSlowRepaintConstrainedObject() const {
FloatRect LayoutBoxModelObject::ComputeStickyConstrainingRect() const {
if (Layer()->AncestorOverflowLayer()->IsRootLayer()) {
- return View()
- ->GetFrameView()
- ->LayoutViewportScrollableArea()
- ->VisibleContentRect();
+ return FloatRect(
+ View()->GetFrameView()->LayoutViewport()->VisibleContentRect());
}
LayoutBox* enclosing_clipping_box =
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 ed71dfef77d..51ff438c497 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
@@ -7,12 +7,12 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/dom/document_lifecycle.h"
#include "third_party/blink/renderer/core/dom/dom_token_list.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.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"
-#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
namespace blink {
@@ -165,7 +165,8 @@ TEST_F(LayoutBoxModelObjectTest, StickyPositionInlineConstraints) {
EXPECT_EQ(
IntRect(0, 100, 10, 10),
EnclosingIntRect(GetScrollContainerRelativeStickyBoxRect(constraints)));
- EXPECT_EQ(IntRect(0, 50, 100, 100), sticky->ComputeStickyConstrainingRect());
+ EXPECT_EQ(IntRect(0, 50, 100, 100),
+ EnclosingIntRect(sticky->ComputeStickyConstrainingRect()));
}
// Verifies that the sticky constraints are correctly computed for sticky with
@@ -224,7 +225,7 @@ TEST_F(LayoutBoxModelObjectTest, StickyPositionVerticalRLInlineConstraints) {
IntRect(2190, 100, 10, 10),
EnclosingIntRect(GetScrollContainerRelativeStickyBoxRect(constraints)));
EXPECT_EQ(IntRect(2100, 50, 100, 100),
- sticky->ComputeStickyConstrainingRect());
+ EnclosingIntRect(sticky->ComputeStickyConstrainingRect()));
}
// Verifies that the sticky constraints are not affected by transforms
@@ -1170,8 +1171,6 @@ TEST_F(LayoutBoxModelObjectTest, StickyRemovedFromRootScrollableArea) {
}
TEST_F(LayoutBoxModelObjectTest, BackfaceVisibilityChange) {
- ScopedSlimmingPaintV175ForTest spv175(true);
-
AtomicString base_style =
"width: 100px; height: 100px; background: blue; position: absolute";
SetBodyInnerHTML("<div id='target' style='" + base_style + "'></div>");
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 b249dc796d2..054433df359 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_button.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_button.cc
@@ -56,10 +56,9 @@ void LayoutButton::RemoveChild(LayoutObject* old_child) {
}
}
-void LayoutButton::UpdateAnonymousChildStyle(const LayoutObject& child,
+void LayoutButton::UpdateAnonymousChildStyle(const LayoutObject* child,
ComputedStyle& child_style) const {
- DCHECK(!inner_ || &child == inner_);
-
+ DCHECK_EQ(inner_, child);
child_style.SetFlexGrow(1.0f);
// min-width: 0; is needed for correct shrinking.
child_style.SetMinWidth(Length(0, kFixed));
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_button.h b/chromium/third_party/blink/renderer/core/layout/layout_button.h
index c2b1e5cc8c6..a3846ca3b03 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_button.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_button.h
@@ -57,7 +57,7 @@ class LayoutButton final : public LayoutFlexibleBox {
LinePositionMode) const override;
private:
- void UpdateAnonymousChildStyle(const LayoutObject& child,
+ void UpdateAnonymousChildStyle(const LayoutObject* child,
ComputedStyle& child_style) const override;
bool HasLineIfEmpty() const override { return IsHTMLInputElement(GetNode()); }
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_counter.cc b/chromium/third_party/blink/renderer/core/layout/layout_counter.cc
index 4b33dc5ed54..81eab5fb614 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_counter.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_counter.cc
@@ -399,11 +399,13 @@ static CounterNode* MakeCounterNodeIfNeeded(LayoutObject& object,
scoped_refptr<CounterNode> old_previous_sibling = nullptr;
if (FindPlaceForCounter(object, identifier, false, old_parent,
old_previous_sibling)) {
- CounterNode* first_node_to_move =
- old_previous_sibling ? old_previous_sibling->NextSibling()
- : old_parent->FirstChild();
- CounterNode::MoveNonResetSiblingsToChildOf(first_node_to_move, *new_node,
- identifier);
+ if (!object.IsDescendantOf(&old_parent->Owner())) {
+ CounterNode* first_node_to_move =
+ old_previous_sibling ? old_previous_sibling->NextSibling()
+ : old_parent->FirstChild();
+ CounterNode::MoveNonResetSiblingsToChildOf(first_node_to_move,
+ *new_node, identifier);
+ }
}
}
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.cc b/chromium/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.cc
index e9ef81e07e7..1d8a9b6e426 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_deprecated_flexible_box.cc
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/core/layout/text_autosizer.h"
#include "third_party/blink/renderer/core/layout/text_run_constructor.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/fonts/font.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_details_marker.cc b/chromium/third_party/blink/renderer/core/layout/layout_details_marker.cc
index eacc61187ee..b5fdf263ff0 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_details_marker.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_details_marker.cc
@@ -54,9 +54,8 @@ LayoutDetailsMarker::Orientation LayoutDetailsMarker::GetOrientation() const {
return kRight;
}
-void LayoutDetailsMarker::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
- DetailsMarkerPainter(*this).Paint(paint_info, paint_offset);
+void LayoutDetailsMarker::Paint(const PaintInfo& paint_info) const {
+ DetailsMarkerPainter(*this).Paint(paint_info);
}
bool LayoutDetailsMarker::IsOpen() const {
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 4a9efb8a7dc..087b367b199 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
@@ -40,7 +40,7 @@ class LayoutDetailsMarker final : public LayoutBlockFlow {
return type == kLayoutObjectDetailsMarker ||
LayoutBlockFlow::IsOfType(type);
}
- void Paint(const PaintInfo&, const LayoutPoint&) const override;
+ void Paint(const PaintInfo&) const override;
bool PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const override {
return false;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_embedded_content.cc b/chromium/third_party/blink/renderer/core/layout/layout_embedded_content.cc
index ce2fcd590c5..b5991e0691c 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_embedded_content.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_embedded_content.cc
@@ -24,7 +24,7 @@
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.h"
#include "third_party/blink/renderer/core/frame/embedded_content_view.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -112,6 +112,9 @@ EmbeddedContentView* LayoutEmbeddedContent::GetEmbeddedContentView() const {
}
PaintLayerType LayoutEmbeddedContent::LayerTypeRequired() const {
+ if (RequiresAcceleratedCompositing())
+ return kNormalPaintLayer;
+
PaintLayerType type = LayoutReplaced::LayerTypeRequired();
if (type != kNoPaintLayer)
return type;
@@ -154,7 +157,7 @@ bool LayoutEmbeddedContent::NodeAtPointOverEmbeddedContentView(
// Check to see if we are really over the EmbeddedContentView itself (and not
// just in the border/padding area).
- if ((inside || result.IsRectBasedTest()) && !had_result &&
+ if ((inside || location_in_container.IsRectBasedTest()) && !had_result &&
result.InnerNode() == GetNode()) {
result.SetIsOverEmbeddedContentView(
ContentBoxRect().Contains(result.LocalPoint()));
@@ -193,9 +196,7 @@ bool LayoutEmbeddedContent::NodeAtPoint(
child_layout_view) {
LayoutPoint adjusted_location = accumulated_offset + Location();
LayoutPoint content_offset =
- LayoutPoint(BorderLeft() + PaddingLeft(),
- BorderTop() + PaddingTop()) -
- LayoutSize(local_frame_view->ScrollOffsetInt());
+ LayoutPoint(BorderLeft() + PaddingLeft(), BorderTop() + PaddingTop());
HitTestLocation new_hit_test_location(
location_in_container, -adjusted_location - content_offset);
HitTestRequest new_hit_test_request(result.GetHitTestRequest().GetType() |
@@ -204,8 +205,8 @@ bool LayoutEmbeddedContent::NodeAtPoint(
new_hit_test_location);
// The frame's layout and style must be up to date if we reach here.
- bool is_inside_child_frame =
- child_layout_view->HitTestNoLifecycleUpdate(child_frame_result);
+ bool is_inside_child_frame = child_layout_view->HitTestNoLifecycleUpdate(
+ new_hit_test_location, child_frame_result);
if (result.GetHitTestRequest().ListBased()) {
result.Append(child_frame_result);
@@ -256,12 +257,6 @@ void LayoutEmbeddedContent::StyleDidChange(StyleDifference diff,
if (!embedded_content_view)
return;
- // If the iframe has custom scrollbars, recalculate their style.
- if (FrameView* frame_view = ChildFrameView()) {
- if (frame_view->IsLocalFrameView())
- ToLocalFrameView(frame_view)->RecalculateCustomScrollbarStyle();
- }
-
if (Style()->Visibility() != EVisibility::kVisible) {
embedded_content_view->Hide();
} else {
@@ -276,9 +271,8 @@ void LayoutEmbeddedContent::UpdateLayout() {
ClearNeedsLayout();
}
-void LayoutEmbeddedContent::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
- EmbeddedContentPainter(*this).Paint(paint_info, paint_offset);
+void LayoutEmbeddedContent::Paint(const PaintInfo& paint_info) const {
+ EmbeddedContentPainter(*this).Paint(paint_info);
}
void LayoutEmbeddedContent::PaintContents(
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_embedded_content.h b/chromium/third_party/blink/renderer/core/layout/layout_embedded_content.h
index 028b87eaece..03a429008ef 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_embedded_content.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_embedded_content.h
@@ -29,6 +29,7 @@
namespace blink {
class EmbeddedContentView;
+class FrameView;
class WebPluginContainerImpl;
// LayoutObject for frames via LayoutFrame and LayoutIFrame, and plugins via
@@ -62,7 +63,8 @@ class CORE_EXPORT LayoutEmbeddedContent : public LayoutReplaced {
void UpdateGeometry(EmbeddedContentView&);
bool IsLayoutEmbeddedContent() const final { return true; }
- virtual void PaintContents(const PaintInfo&, const LayoutPoint&) const;
+ virtual void PaintContents(const PaintInfo&,
+ const LayoutPoint& paint_offset) const;
bool IsThrottledFrameView() const;
@@ -71,7 +73,7 @@ class CORE_EXPORT LayoutEmbeddedContent : public LayoutReplaced {
void StyleDidChange(StyleDifference, const ComputedStyle* old_style) final;
void UpdateLayout() override;
- void Paint(const PaintInfo&, const LayoutPoint&) const override;
+ void Paint(const PaintInfo&) const override;
CursorDirective GetCursor(const LayoutPoint&, Cursor&) const final;
bool CanBeSelectionLeafInternal() const final { return true; }
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_embedded_object.cc b/chromium/third_party/blink/renderer/core/layout/layout_embedded_object.cc
index df7644aec9a..696c65e019f 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_embedded_object.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_embedded_object.cc
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html/html_plugin_element.h"
#include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/core/layout/intrinsic_sizing_info.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/page/page.h"
@@ -48,17 +49,6 @@ LayoutEmbeddedObject::LayoutEmbeddedObject(Element* element)
LayoutEmbeddedObject::~LayoutEmbeddedObject() = default;
-PaintLayerType LayoutEmbeddedObject::LayerTypeRequired() const {
- // This can't just use LayoutEmbeddedContent::layerTypeRequired, because
- // PaintLayerCompositor doesn't loop through LayoutEmbeddedObjects the way it
- // does frames in order to update the self painting bit on their Layer.
- // Also, unlike iframes, embeds don't used the usesCompositing bit on
- // LayoutView in requiresAcceleratedCompositing.
- if (RequiresAcceleratedCompositing())
- return kNormalPaintLayer;
- return LayoutEmbeddedContent::LayerTypeRequired();
-}
-
static String LocalizedUnavailablePluginReplacementText(
Node* node,
LayoutEmbeddedObject::PluginAvailability availability) {
@@ -103,14 +93,13 @@ void LayoutEmbeddedObject::PaintContents(
LayoutEmbeddedContent::PaintContents(paint_info, paint_offset);
}
-void LayoutEmbeddedObject::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
+void LayoutEmbeddedObject::Paint(const PaintInfo& paint_info) const {
if (ShowsUnavailablePluginIndicator()) {
- LayoutReplaced::Paint(paint_info, paint_offset);
+ LayoutReplaced::Paint(paint_info);
return;
}
- LayoutEmbeddedContent::Paint(paint_info, paint_offset);
+ LayoutEmbeddedContent::Paint(paint_info);
}
void LayoutEmbeddedObject::PaintReplaced(
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_embedded_object.h b/chromium/third_party/blink/renderer/core/layout/layout_embedded_object.h
index 8b196e9db68..88d4ea15a1a 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_embedded_object.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_embedded_object.h
@@ -50,9 +50,11 @@ class LayoutEmbeddedObject final : public LayoutEmbeddedContent {
}
private:
- void PaintContents(const PaintInfo&, const LayoutPoint&) const final;
- void PaintReplaced(const PaintInfo&, const LayoutPoint&) const final;
- void Paint(const PaintInfo&, const LayoutPoint&) const final;
+ void PaintContents(const PaintInfo&,
+ const LayoutPoint& paint_offset) const final;
+ void PaintReplaced(const PaintInfo&,
+ const LayoutPoint& paint_offset) const final;
+ void Paint(const PaintInfo&) const final;
PaintInvalidationReason InvalidatePaint(
const PaintInvalidatorContext&) const final;
@@ -65,8 +67,6 @@ class LayoutEmbeddedObject final : public LayoutEmbeddedContent {
void ComputeIntrinsicSizingInfo(IntrinsicSizingInfo&) const override;
bool NeedsPreferredWidthsRecalculation() const override;
- PaintLayerType LayerTypeRequired() const final;
-
CompositingReasons AdditionalCompositingReasons() const override;
PluginAvailability plugin_availability_ = kPluginAvailable;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_fieldset.h b/chromium/third_party/blink/renderer/core/layout/layout_fieldset.h
index 925cc7c51c7..4d38cd04619 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_fieldset.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_fieldset.h
@@ -46,9 +46,11 @@ class LayoutFieldset final : public LayoutBlockFlow {
void ComputePreferredLogicalWidths() override;
- void PaintBoxDecorationBackground(const PaintInfo&,
- const LayoutPoint&) const override;
- void PaintMask(const PaintInfo&, const LayoutPoint&) const override;
+ void PaintBoxDecorationBackground(
+ const PaintInfo&,
+ const LayoutPoint& paint_offset) const override;
+ void PaintMask(const PaintInfo&,
+ const LayoutPoint& paint_offset) const override;
};
DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutFieldset, IsFieldset());
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_file_upload_control.h b/chromium/third_party/blink/renderer/core/layout/layout_file_upload_control.h
index 3d9dfed9d26..4c4d2cdccf4 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_file_upload_control.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_file_upload_control.h
@@ -59,7 +59,8 @@ class CORE_EXPORT LayoutFileUploadControl final : public LayoutBlockFlow {
LayoutUnit& min_logical_width,
LayoutUnit& max_logical_width) const override;
void ComputePreferredLogicalWidths() override;
- void PaintObject(const PaintInfo&, const LayoutPoint&) const override;
+ void PaintObject(const PaintInfo&,
+ const LayoutPoint& paint_offset) const override;
int MaxFilenameWidth() const;
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 baf3a07f6f0..054c5a5a12d 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
@@ -42,6 +42,7 @@
#include "third_party/blink/renderer/core/layout/text_autosizer.h"
#include "third_party/blink/renderer/core/paint/block_painter.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/style/computed_style.h"
#include "third_party/blink/renderer/platform/length_functions.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
@@ -65,15 +66,12 @@ LayoutFlexibleBox::LayoutFlexibleBox(Element* element)
LayoutFlexibleBox::~LayoutFlexibleBox() = default;
-LayoutFlexibleBox* LayoutFlexibleBox::CreateAnonymous(Document* document) {
- LayoutFlexibleBox* layout_object = new LayoutFlexibleBox(nullptr);
- layout_object->SetDocumentForAnonymous(document);
- return layout_object;
-}
-
void LayoutFlexibleBox::ComputeIntrinsicLogicalWidths(
LayoutUnit& min_logical_width,
LayoutUnit& max_logical_width) const {
+ if (ShouldApplySizeContainment())
+ return;
+
// FIXME: We're ignoring flex-basis here and we shouldn't. We can't start
// honoring it though until the flex shorthand stops setting it to 0. See
// https://bugs.webkit.org/show_bug.cgi?id=116117 and
@@ -180,7 +178,8 @@ LayoutUnit LayoutFlexibleBox::BaselinePosition(FontBaseline,
}
LayoutUnit LayoutFlexibleBox::FirstLineBoxBaseline() const {
- if (IsWritingModeRoot() || number_of_in_flow_children_on_first_line_ <= 0)
+ if (IsWritingModeRoot() || number_of_in_flow_children_on_first_line_ <= 0 ||
+ ShouldApplySizeContainment())
return LayoutUnit(-1);
LayoutBox* baseline_child = nullptr;
int child_number = 0;
@@ -426,8 +425,8 @@ void LayoutFlexibleBox::UpdateBlockLayout(bool relayout_children) {
}
void LayoutFlexibleBox::PaintChildren(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
- BlockPainter::PaintChildrenOfFlexibleBox(*this, paint_info, paint_offset);
+ const LayoutPoint&) const {
+ BlockPainter::PaintChildrenOfFlexibleBox(*this, paint_info);
}
void LayoutFlexibleBox::RepositionLogicalHeightDependentFlexItems(
@@ -510,7 +509,7 @@ LayoutUnit LayoutFlexibleBox::ChildIntrinsicLogicalHeight(
DCHECK(!HasOrthogonalFlow(child));
if (NeedToStretchChildLogicalHeight(child)) {
LayoutUnit child_intrinsic_content_logical_height;
- if (!child.StyleRef().ContainsSize()) {
+ if (!child.ShouldApplySizeContainment()) {
child_intrinsic_content_logical_height =
child.IntrinsicContentLogicalHeight();
}
@@ -866,7 +865,7 @@ LayoutUnit LayoutFlexibleBox::ComputeInnerFlexBaseSizeForChild(
return std::max(LayoutUnit(), ComputeMainAxisExtentForChild(
child, kMainOrPreferredSize, flex_basis));
- if (child.StyleRef().ContainsSize())
+ if (child.ShouldApplySizeContainment())
return LayoutUnit();
// The flex basis is indefinite (=auto), so we need to compute the actual
@@ -1094,7 +1093,7 @@ MinMaxSize LayoutFlexibleBox::ComputeMinAndMaxSizesForChild(
// computeMainAxisExtentForChild can return -1 when the child has a
// percentage min size, but we have an indefinite size in that axis.
sizes.min_size = std::max(LayoutUnit(), sizes.min_size);
- } else if (min.IsAuto() && !child.StyleRef().ContainsSize() &&
+ } else if (min.IsAuto() && !child.ShouldApplySizeContainment() &&
MainAxisOverflowForChild(child) == EOverflow::kVisible &&
!(IsColumnFlow() && child.IsFlexibleBox())) {
// TODO(cbiesinger): For now, we do not handle min-height: auto for nested
@@ -1301,12 +1300,11 @@ static LayoutUnit AlignmentOffset(LayoutUnit available_free_space,
void LayoutFlexibleBox::SetOverrideMainAxisContentSizeForChild(
LayoutBox& child,
LayoutUnit child_preferred_size) {
+ // child_preferred_size includes scrollbar width.
if (HasOrthogonalFlow(child)) {
- // TODO(rego): Shouldn't we add the scrollbar height too?
child.SetOverrideLogicalHeight(child_preferred_size +
child.BorderAndPaddingLogicalHeight());
} else {
- // TODO(rego): Shouldn't we add the scrollbar width too?
child.SetOverrideLogicalWidth(child_preferred_size +
child.BorderAndPaddingLogicalWidth());
}
@@ -1730,14 +1728,15 @@ void LayoutFlexibleBox::ApplyStretchAlignmentToChild(
// FIXME: Can avoid laying out here in some cases. See
// https://webkit.org/b/87905.
bool child_needs_relayout = desired_logical_height != child.LogicalHeight();
- if (child.IsLayoutBlock() &&
- ToLayoutBlock(child).HasPercentHeightDescendants() &&
- relaid_out_children_.Contains(&child)) {
+ if ((child.IsLayoutNGMixin() &&
+ ShouldForceLayoutForNGChild(ToLayoutBlockFlow(child))) ||
+ (child.IsLayoutBlock() &&
+ ToLayoutBlock(child).HasPercentHeightDescendants())) {
// Have to force another relayout even though the child is sized
// correctly, because its descendants are not sized correctly yet. Our
// previous layout of the child was done without an override height set.
// So, redo it here.
- child_needs_relayout = true;
+ child_needs_relayout = relaid_out_children_.Contains(&child);
}
if (child_needs_relayout || !child.HasOverrideLogicalHeight())
child.SetOverrideLogicalHeight(desired_logical_height);
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 def9538873b..bd15dbdec74 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
@@ -46,8 +46,6 @@ class CORE_EXPORT LayoutFlexibleBox : public LayoutBlock {
LayoutFlexibleBox(Element*);
~LayoutFlexibleBox() override;
- static LayoutFlexibleBox* CreateAnonymous(Document*);
-
const char* GetName() const override { return "LayoutFlexibleBox"; }
bool IsFlexibleBox() const final { return true; }
@@ -69,7 +67,8 @@ class CORE_EXPORT LayoutFlexibleBox : public LayoutBlock {
bool HasTopOverflow() const override;
bool HasLeftOverflow() const override;
- void PaintChildren(const PaintInfo&, const LayoutPoint&) const final;
+ void PaintChildren(const PaintInfo&,
+ const LayoutPoint& paint_offset) const final;
bool IsHorizontalFlow() const;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_frame_set.cc b/chromium/third_party/blink/renderer/core/layout/layout_frame_set.cc
index 302a1d5e580..a0d5dac003b 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_frame_set.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_frame_set.cc
@@ -50,9 +50,8 @@ HTMLFrameSetElement* LayoutFrameSet::FrameSet() const {
return ToHTMLFrameSetElement(GetNode());
}
-void LayoutFrameSet::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
- FrameSetPainter(*this).Paint(paint_info, paint_offset);
+void LayoutFrameSet::Paint(const PaintInfo& paint_info) const {
+ FrameSetPainter(*this).Paint(paint_info);
}
void LayoutFrameSet::ComputePreferredLogicalWidths() {
@@ -137,7 +136,9 @@ void LayoutFrameSet::LayOutAxis(GridAxis& axis,
for (int i = 0; i < grid_len; ++i) {
if (grid[i].IsAbsolute()) {
- grid_layout[i] = (grid_layout[i] * remaining_fixed) / total_fixed;
+ long long temp_product =
+ static_cast<long long>(grid_layout[i]) * remaining_fixed;
+ grid_layout[i] = temp_product / total_fixed;
remaining_len -= grid_layout[i];
}
}
@@ -155,7 +156,9 @@ void LayoutFrameSet::LayOutAxis(GridAxis& axis,
for (int i = 0; i < grid_len; ++i) {
if (grid[i].IsPercentage()) {
- grid_layout[i] = (grid_layout[i] * remaining_percent) / total_percent;
+ long long temp_product =
+ static_cast<long long>(grid_layout[i]) * remaining_percent;
+ grid_layout[i] = temp_product / total_percent;
remaining_len -= grid_layout[i];
}
}
@@ -203,7 +206,9 @@ void LayoutFrameSet::LayOutAxis(GridAxis& axis,
for (int i = 0; i < grid_len; ++i) {
if (grid[i].IsPercentage()) {
- change_percent = (remaining_percent * grid_layout[i]) / total_percent;
+ long long temp_product =
+ static_cast<long long>(grid_layout[i]) * remaining_percent;
+ change_percent = temp_product / total_percent;
grid_layout[i] += change_percent;
remaining_len -= change_percent;
}
@@ -217,7 +222,9 @@ void LayoutFrameSet::LayOutAxis(GridAxis& axis,
for (int i = 0; i < grid_len; ++i) {
if (grid[i].IsAbsolute()) {
- change_fixed = (remaining_fixed * grid_layout[i]) / total_fixed;
+ long long temp_product =
+ static_cast<long long>(grid_layout[i]) * remaining_fixed;
+ change_fixed = temp_product / total_fixed;
grid_layout[i] += change_fixed;
remaining_len -= change_fixed;
}
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 5c76f7b0e0b..8de95dd343c 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
@@ -129,7 +129,7 @@ class LayoutFrameSet final : public LayoutBox {
}
void UpdateLayout() override;
- void Paint(const PaintInfo&, const LayoutPoint&) const override;
+ void Paint(const PaintInfo&) const override;
void ComputePreferredLogicalWidths() override;
bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override;
CursorDirective GetCursor(const LayoutPoint&, Cursor&) const override;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_full_screen.cc b/chromium/third_party/blink/renderer/core/layout/layout_full_screen.cc
deleted file mode 100644
index a90fabbc6e6..00000000000
--- a/chromium/third_party/blink/renderer/core/layout/layout_full_screen.cc
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- */
-
-#include "third_party/blink/renderer/core/layout/layout_full_screen.h"
-
-#include "third_party/blink/public/platform/web_screen_info.h"
-#include "third_party/blink/renderer/core/frame/visual_viewport.h"
-#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
-#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
-#include "third_party/blink/renderer/core/page/page.h"
-
-namespace blink {
-
-namespace {
-
-class LayoutFullScreenPlaceholder final : public LayoutBlockFlow {
- public:
- LayoutFullScreenPlaceholder(LayoutFullScreen* owner)
- : LayoutBlockFlow(nullptr), owner_(owner) {
- SetDocumentForAnonymous(&owner->GetDocument());
- }
-
- // Must call SetStyleWithWritingModeOfParent() instead.
- void SetStyle(scoped_refptr<ComputedStyle>) = delete;
-
- bool CreatesNewFormattingContext() const override { return true; }
-
- private:
- bool IsOfType(LayoutObjectType type) const override {
- return type == kLayoutObjectLayoutFullScreenPlaceholder ||
- LayoutBlockFlow::IsOfType(type);
- }
- bool AnonymousHasStylePropagationOverride() override { return true; }
-
- void WillBeDestroyed() override;
-
- LayoutFullScreen* owner_;
-};
-
-void LayoutFullScreenPlaceholder::WillBeDestroyed() {
- owner_->ResetPlaceholder();
- LayoutBlockFlow::WillBeDestroyed();
-}
-
-} // namespace
-
-LayoutFullScreen::LayoutFullScreen()
- : LayoutFlexibleBox(nullptr), placeholder_(nullptr) {
- SetIsAtomicInlineLevel(false);
-}
-
-LayoutFullScreen* LayoutFullScreen::CreateAnonymous(Document* document) {
- LayoutFullScreen* layout_object = new LayoutFullScreen();
- layout_object->SetDocumentForAnonymous(document);
- return layout_object;
-}
-
-void LayoutFullScreen::WillBeDestroyed() {
- if (placeholder_) {
- // Remove children before self.
- if (LayoutObjectChildList* children = Children())
- children->DestroyLeftoverChildren();
- Remove();
- if (!placeholder_->BeingDestroyed())
- placeholder_->Destroy();
- DCHECK(!placeholder_);
- }
-
- // LayoutObjects are unretained, so notify the document (which holds a pointer
- // to a LayoutFullScreen) if its LayoutFullScreen is destroyed.
- Fullscreen& fullscreen = Fullscreen::From(GetDocument());
- if (fullscreen.FullScreenLayoutObject() == this)
- fullscreen.FullScreenLayoutObjectDestroyed();
-
- LayoutFlexibleBox::WillBeDestroyed();
-}
-
-scoped_refptr<ComputedStyle> LayoutFullScreen::CreateAnonymousStyle() {
- scoped_refptr<ComputedStyle> fullscreen_style = ComputedStyle::Create();
-
- // Create a stacking context:
- fullscreen_style->SetZIndex(INT_MAX);
- fullscreen_style->SetIsStackingContext(true);
-
- fullscreen_style->SetFontDescription(FontDescription());
- fullscreen_style->GetFont().Update(nullptr);
-
- fullscreen_style->SetDisplay(EDisplay::kFlex);
- fullscreen_style->SetJustifyContentPosition(ContentPosition::kCenter);
- // TODO (lajava): Since the FullScrenn layout object is anonymous, its Default
- // Alignment (align-items) value can't be used to resolve its children Self
- // Alignment 'auto' values.
- fullscreen_style->SetAlignItemsPosition(ItemPosition::kCenter);
- fullscreen_style->SetFlexDirection(EFlexDirection::kColumn);
-
- fullscreen_style->SetPosition(EPosition::kFixed);
- fullscreen_style->SetLeft(Length(0, blink::kFixed));
- fullscreen_style->SetTop(Length(0, blink::kFixed));
- IntSize viewport_size = GetDocument().GetPage()->GetVisualViewport().Size();
- fullscreen_style->SetWidth(Length(viewport_size.Width(), blink::kFixed));
- fullscreen_style->SetHeight(Length(viewport_size.Height(), blink::kFixed));
-
- fullscreen_style->SetBackgroundColor(StyleColor(Color::kBlack));
- return fullscreen_style;
-}
-
-void LayoutFullScreen::UpdateStyle() {
- scoped_refptr<ComputedStyle> style = CreateAnonymousStyle();
- SetStyleWithWritingModeOf(style, Parent());
-}
-
-LayoutObject* LayoutFullScreen::WrapLayoutObject(LayoutObject* object,
- LayoutObject* parent,
- Document* document) {
- // TODO: We should not modify the structure of the layout tree during layout.
- // crbug.com/370459
- DeprecatedDisableModifyLayoutTreeStructureAsserts disabler;
-
- // A fullscreen <html> element should not be wrapped (see crbug.com/676432).
- DCHECK(!object || object->GetNode() != document->documentElement());
-
- LayoutFullScreen* fullscreen_layout_object =
- LayoutFullScreen::CreateAnonymous(document);
- scoped_refptr<ComputedStyle> fullscreen_style =
- fullscreen_layout_object->CreateAnonymousStyle();
-
- if (parent &&
- !parent->IsChildAllowed(fullscreen_layout_object, *fullscreen_style)) {
- fullscreen_layout_object->Destroy();
- return nullptr;
- }
- parent = object ? object->Parent() : nullptr;
- fullscreen_layout_object->SetStyleWithWritingModeOf(fullscreen_style, parent);
-
- // |object->Parent()| can be null if the object is not yet attached
- // to |parent|.
- if (parent) {
- LayoutBlock* containing_block = object->ContainingBlock();
- DCHECK(containing_block);
- // Since we are moving the |object| to a new parent
- // |fullscreen_layout_object|, the line box tree underneath our
- // |containing_block| is not longer valid.
- if (containing_block->IsLayoutBlockFlow())
- ToLayoutBlockFlow(containing_block)->DeleteLineBoxTree();
-
- parent->AddChild(fullscreen_layout_object, object);
- object->Remove();
-
- // Always just do a full layout to ensure that line boxes get deleted
- // properly.
- // Because objects moved from |parent| to |fullscreen_layout_object|, we
- // want to make new line boxes instead of leaving the old ones around.
- parent->SetNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(
- LayoutInvalidationReason::kFullscreen);
- containing_block->SetNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(
- LayoutInvalidationReason::kFullscreen);
- }
- if (object) {
- fullscreen_layout_object->AddChild(object);
- fullscreen_layout_object
- ->SetNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(
- LayoutInvalidationReason::kFullscreen);
- }
-
- DCHECK(document);
- Fullscreen::From(*document).SetFullScreenLayoutObject(
- fullscreen_layout_object);
- return fullscreen_layout_object;
-}
-
-void LayoutFullScreen::UnwrapLayoutObject() {
- // FIXME: We should not modify the structure of the layout tree during
- // layout. crbug.com/370459
- DeprecatedDisableModifyLayoutTreeStructureAsserts disabler;
-
- if (Parent()) {
- for (LayoutObject* child = FirstChild(); child; child = FirstChild()) {
- // We have to clear the override size, because as a flexbox, we
- // may have set one on the child, and we don't want to leave that
- // lying around on the child.
- if (child->IsBox())
- ToLayoutBox(child)->ClearOverrideSize();
- child->Remove();
- Parent()->AddChild(child, this);
- Parent()->SetNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(
- LayoutInvalidationReason::kFullscreen);
- }
- }
- if (Placeholder())
- Placeholder()->Remove();
- Remove();
- Destroy();
-}
-
-void LayoutFullScreen::CreatePlaceholder(scoped_refptr<ComputedStyle> style,
- const LayoutRect& frame_rect) {
- if (style->Width().IsAuto())
- style->SetWidth(Length(frame_rect.Width(), kFixed));
- if (style->Height().IsAuto())
- style->SetHeight(Length(frame_rect.Height(), kFixed));
-
- if (placeholder_) {
- placeholder_->SetStyleWithWritingModeOfParent(std::move(style));
- return;
- }
-
- placeholder_ = new LayoutFullScreenPlaceholder(this);
- placeholder_->SetStyleWithWritingModeOf(std::move(style), Parent());
- if (Parent()) {
- Parent()->AddChild(placeholder_, this);
- Parent()->SetNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(
- LayoutInvalidationReason::kFullscreen);
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_full_screen.h b/chromium/third_party/blink/renderer/core/layout/layout_full_screen.h
deleted file mode 100644
index 63534f4f06b..00000000000
--- a/chromium/third_party/blink/renderer/core/layout/layout_full_screen.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_FULL_SCREEN_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_FULL_SCREEN_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_flexible_box.h"
-
-namespace blink {
-
-class LayoutBlockFlow;
-
-class CORE_EXPORT LayoutFullScreen final : public LayoutFlexibleBox {
- public:
- static LayoutFullScreen* CreateAnonymous(Document*);
-
- bool IsOfType(LayoutObjectType type) const override {
- return type == kLayoutObjectLayoutFullScreen ||
- LayoutFlexibleBox::IsOfType(type);
- }
- const char* GetName() const override { return "LayoutFullScreen"; }
-
- void ResetPlaceholder() { placeholder_ = nullptr; }
- LayoutBlockFlow* Placeholder() { return placeholder_; }
- void CreatePlaceholder(scoped_refptr<ComputedStyle>,
- const LayoutRect& frame_rect);
-
- static LayoutObject* WrapLayoutObject(LayoutObject*,
- LayoutObject*,
- Document*);
- void UnwrapLayoutObject();
-
- void UpdateStyle();
- bool AnonymousHasStylePropagationOverride() override { return true; }
-
- // Must call setStyleWithWritingModeOfParent() instead.
- void SetStyle(scoped_refptr<ComputedStyle>) = delete;
-
- private:
- LayoutFullScreen();
- void WillBeDestroyed() override;
- scoped_refptr<ComputedStyle> CreateAnonymousStyle();
-
- protected:
- LayoutBlockFlow* placeholder_;
- ItemPosition SelfAlignmentNormalBehavior(
- const LayoutBox* child = nullptr) const override {
- DCHECK(!child);
- return ItemPosition::kCenter;
- }
-};
-
-DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutFullScreen, IsLayoutFullScreen());
-
-} // namespace blink
-
-#endif
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_geometry_map_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_geometry_map_test.cc
index c5d0da335da..425ee90f87e 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_geometry_map_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_geometry_map_test.cc
@@ -34,7 +34,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
-#include "third_party/blink/public/web/web_frame_client.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
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 20b0f690b67..7048f7638ef 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/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/layout/grid_layout_utils.h"
#include "third_party/blink/renderer/core/layout/layout_state.h"
@@ -42,23 +43,10 @@
namespace blink {
-struct ContentAlignmentData {
- STACK_ALLOCATED();
-
- public:
- ContentAlignmentData() = default;
- ;
- ContentAlignmentData(LayoutUnit position, LayoutUnit distribution)
- : position_offset(position), distribution_offset(distribution) {}
-
- bool IsValid() { return position_offset >= 0 && distribution_offset >= 0; }
-
- LayoutUnit position_offset = LayoutUnit(-1);
- LayoutUnit distribution_offset = LayoutUnit(-1);
-};
-
LayoutGrid::LayoutGrid(Element* element)
- : LayoutBlock(element), grid_(this), track_sizing_algorithm_(this, grid_) {
+ : LayoutBlock(element),
+ grid_(Grid::Create(this)),
+ track_sizing_algorithm_(this, *grid_) {
DCHECK(!ChildrenInline());
if (!IsAnonymous())
UseCounter::Count(GetDocument(), WebFeature::kCSSGridLayout);
@@ -218,7 +206,7 @@ base::Optional<LayoutUnit> LayoutGrid::AvailableSpaceForGutters(
const GapLength& gap =
is_row_axis ? StyleRef().ColumnGap() : StyleRef().RowGap();
- if (!gap.IsNormal() && !gap.GetLength().IsPercent())
+ if (!gap.IsNormal() && !gap.GetLength().IsPercentOrCalc())
return base::nullopt;
return is_row_axis ? AvailableLogicalWidth()
@@ -232,7 +220,7 @@ LayoutUnit LayoutGrid::ComputeTrackBasedLogicalHeight() const {
for (const auto& row : all_rows)
logical_height += row.BaseSize();
- logical_height += GuttersSize(grid_, kForRows, 0, all_rows.size(),
+ logical_height += GuttersSize(*grid_, kForRows, 0, all_rows.size(),
AvailableSpaceForGutters(kForRows));
return logical_height;
@@ -241,7 +229,7 @@ LayoutUnit LayoutGrid::ComputeTrackBasedLogicalHeight() const {
void LayoutGrid::ComputeTrackSizesForDefiniteSize(
GridTrackSizingDirection direction,
LayoutUnit available_space) {
- track_sizing_algorithm_.Setup(direction, NumTracks(direction, grid_),
+ track_sizing_algorithm_.Setup(direction, NumTracks(direction, *grid_),
available_space);
track_sizing_algorithm_.Run();
@@ -253,28 +241,15 @@ void LayoutGrid::ComputeTrackSizesForDefiniteSize(
void LayoutGrid::RepeatTracksSizingIfNeeded(
LayoutUnit available_space_for_columns,
LayoutUnit available_space_for_rows) {
- // Baseline alignment may change item's intrinsic size, hence changing its
- // min-content contribution.
- // https://drafts.csswg.org/css-align-3/#baseline-align-content
- // https://drafts.csswg.org/css-align-3/#baseline-align-self
- bool baseline_affect_intrinsic_width =
- track_sizing_algorithm_.BaselineMayAffectIntrinsicSize(kForColumns);
- bool baseline_affect_intrinsic_height =
- track_sizing_algorithm_.BaselineMayAffectIntrinsicSize(kForRows);
-
// In orthogonal flow cases column track's size is determined by using the
// computed row track's size, which it was estimated during the first cycle of
// the sizing algorithm.
- bool has_any_orthogonal =
- track_sizing_algorithm_.GetGrid().HasAnyOrthogonalGridItem();
-
// TODO (lajava): these are just some of the cases which may require
// a new cycle of the sizing algorithm; there may be more. In addition, not
// all the cases with orthogonal flows require this extra cycle; we need a
// more specific condition to detect whether child's min-content contribution
// has changed or not.
- if (!baseline_affect_intrinsic_width && !baseline_affect_intrinsic_height &&
- !has_any_orthogonal)
+ if (!has_any_orthogonal_item_)
return;
// TODO (lajava): Whenever the min-content contribution of a grid item changes
@@ -288,13 +263,6 @@ void LayoutGrid::RepeatTracksSizingIfNeeded(
// and rows, to determine the final values.
ComputeTrackSizesForDefiniteSize(kForColumns, available_space_for_columns);
ComputeTrackSizesForDefiniteSize(kForRows, available_space_for_rows);
-
- if (baseline_affect_intrinsic_height &&
- StyleRef().LogicalHeight().IsIntrinsicOrAuto()) {
- SetLogicalHeight(ComputeTrackBasedLogicalHeight() +
- BorderAndPaddingLogicalHeight() +
- ScrollbarLogicalHeight());
- }
}
void LayoutGrid::UpdateBlockLayout(bool relayout_children) {
@@ -303,14 +271,12 @@ void LayoutGrid::UpdateBlockLayout(bool relayout_children) {
// We cannot perform a simplifiedLayout() on a dirty grid that
// has positioned items to be laid out.
if (!relayout_children &&
- (!grid_.NeedsItemsPlacement() || !PosChildNeedsLayout()) &&
+ (!grid_->NeedsItemsPlacement() || !PosChildNeedsLayout()) &&
SimplifiedLayout())
return;
SubtreeLayoutScope layout_scope(*this);
- track_sizing_algorithm_.ClearBaselineAlignment();
-
{
// LayoutState needs this deliberate scope to pop before updating scroll
// information (which may trigger relayout).
@@ -323,16 +289,22 @@ void LayoutGrid::UpdateBlockLayout(bool relayout_children) {
// we need to clear any override height set previously, so it doesn't
// interfere in current layout execution.
// Grid never uses the override width, that's why we don't need to clear it.
+ has_any_orthogonal_item_ = false;
for (auto* child = FirstInFlowChildBox(); child;
- child = child->NextInFlowSiblingBox())
+ child = child->NextInFlowSiblingBox()) {
child->ClearOverrideLogicalHeight();
+ if (GridLayoutUtils::IsOrthogonalChild(*this, *child))
+ has_any_orthogonal_item_ = true;
+ }
UpdateLogicalWidth();
TextAutosizer::LayoutScope text_autosizer_layout_scope(this, &layout_scope);
LayoutUnit available_space_for_columns = AvailableLogicalWidth();
- PlaceItemsOnGrid(grid_, available_space_for_columns);
+ PlaceItemsOnGrid(track_sizing_algorithm_, available_space_for_columns);
+
+ PerformGridItemsPreLayout(track_sizing_algorithm_);
// 1- First, the track sizing algorithm is used to resolve the sizes of the
// grid columns.
@@ -343,6 +315,11 @@ void LayoutGrid::UpdateBlockLayout(bool relayout_children) {
// resolve heights properly (like for positioned items for example).
ComputeTrackSizesForDefiniteSize(kForColumns, available_space_for_columns);
+ // 1.5- Compute Content Distribution offsets for column tracks
+ ComputeContentPositionAndDistributionOffset(
+ kForColumns, track_sizing_algorithm_.FreeSpace(kForColumns).value(),
+ NonCollapsedTracks(kForColumns));
+
// 2- Next, the track sizing algorithm resolves the sizes of the grid rows,
// using the grid column sizes calculated in the previous step.
if (CachedHasDefiniteLogicalHeight()) {
@@ -350,7 +327,7 @@ void LayoutGrid::UpdateBlockLayout(bool relayout_children) {
kForRows, AvailableLogicalHeight(kExcludeMarginBorderPadding));
} else {
ComputeTrackSizesForIndefiniteSize(track_sizing_algorithm_, kForRows,
- grid_, min_content_height_,
+ min_content_height_,
max_content_height_);
}
LayoutUnit track_based_logical_height = ComputeTrackBasedLogicalHeight() +
@@ -368,14 +345,10 @@ void LayoutGrid::UpdateBlockLayout(bool relayout_children) {
kForRows, LogicalHeight() - track_based_logical_height);
}
- // TODO (lajava): We need to compute baselines after step 2 so
- // items with a relative size (percentages) can resolve it before
- // determining its baseline. However, we only set item's grid area
- // (via override sizes) as part of the content-sized tracks sizing
- // logic. Hence, items located at fixed or flexible tracks can't
- // resolve correctly their size at this stage, which may lead to
- // an incorrect computation of their shared context's baseline.
- ComputeBaselineAlignmentContext();
+ // 2.5- Compute Content Distribution offsets for rows tracks
+ ComputeContentPositionAndDistributionOffset(
+ kForRows, track_sizing_algorithm_.FreeSpace(kForRows).value(),
+ NonCollapsedTracks(kForRows));
// 3- If the min-content contribution of any grid items have changed based
// on the row sizes calculated in step 2, steps 1 and 2 are repeated with
@@ -519,12 +492,17 @@ LayoutUnit LayoutGrid::GuttersSize(
void LayoutGrid::ComputeIntrinsicLogicalWidths(
LayoutUnit& min_logical_width,
LayoutUnit& max_logical_width) const {
- Grid grid(this);
- PlaceItemsOnGrid(grid, base::nullopt);
+ if (ShouldApplySizeContainment())
+ return;
+
+ std::unique_ptr<Grid> grid = Grid::Create(this);
+ GridTrackSizingAlgorithm algorithm(this, *grid);
+ PlaceItemsOnGrid(algorithm, base::nullopt);
- GridTrackSizingAlgorithm algorithm(this, grid);
- ComputeTrackSizesForIndefiniteSize(algorithm, kForColumns, grid,
- min_logical_width, max_logical_width);
+ PerformGridItemsPreLayout(algorithm);
+
+ ComputeTrackSizesForIndefiniteSize(algorithm, kForColumns, min_logical_width,
+ max_logical_width);
LayoutUnit scrollbar_width = LayoutUnit(ScrollbarLogicalWidth());
min_logical_width += scrollbar_width;
@@ -534,9 +512,9 @@ void LayoutGrid::ComputeIntrinsicLogicalWidths(
void LayoutGrid::ComputeTrackSizesForIndefiniteSize(
GridTrackSizingAlgorithm& algo,
GridTrackSizingDirection direction,
- Grid& grid,
LayoutUnit& min_intrinsic_size,
LayoutUnit& max_intrinsic_size) const {
+ const Grid& grid = algo.GetGrid();
algo.Setup(direction, NumTracks(direction, grid), base::nullopt);
algo.Run();
@@ -730,8 +708,8 @@ LayoutGrid::ComputeEmptyTracksForAutoRepeat(
} else {
for (size_t track_index = first_auto_repeat_track;
track_index < last_auto_repeat_track; ++track_index) {
- GridIterator iterator(grid, direction, track_index);
- if (!iterator.NextGridItem()) {
+ auto iterator = grid.CreateIterator(direction, track_index);
+ if (!iterator->NextGridItem()) {
if (!empty_track_indexes)
empty_track_indexes = std::make_unique<OrderedTrackIndexSet>();
empty_track_indexes->insert(track_index);
@@ -767,8 +745,9 @@ size_t LayoutGrid::ClampAutoRepeatTracks(GridTrackSizingDirection direction,
// (preferred widths). That's why we pass the responsibility to the caller who
// does know whether the available logical width is indefinite or not.
void LayoutGrid::PlaceItemsOnGrid(
- Grid& grid,
+ GridTrackSizingAlgorithm& algorithm,
base::Optional<LayoutUnit> available_logical_width) const {
+ Grid& grid = algorithm.GetMutableGrid();
size_t auto_repeat_rows = ComputeAutoRepeatTracksCount(
kForRows, ConvertLayoutUnitToOptional(
AvailableLogicalHeightForPercentageComputation()));
@@ -792,11 +771,9 @@ void LayoutGrid::PlaceItemsOnGrid(
Vector<LayoutBox*> auto_major_axis_auto_grid_items;
Vector<LayoutBox*> specified_major_axis_auto_grid_items;
- Vector<LayoutBox*> orthogonal_grid_items;
#if DCHECK_IS_ON()
DCHECK(!grid.HasAnyGridItemPaintOrder());
#endif
- DCHECK(!grid.HasAnyOrthogonalGridItem());
size_t child_index = 0;
for (LayoutBox* child = grid.GetOrderIterator().First(); child;
child = grid.GetOrderIterator().Next()) {
@@ -811,8 +788,6 @@ void LayoutGrid::PlaceItemsOnGrid(
if (!child->HasOverrideContainingBlockContentLogicalHeight())
child->SetOverrideContainingBlockContentLogicalHeight(LayoutUnit(-1));
- if (GridLayoutUtils::IsOrthogonalChild(*this, *child))
- orthogonal_grid_items.push_back(child);
grid.SetGridItemPaintOrder(*child, child_index++);
GridArea area = grid.GridItemArea(*child);
@@ -834,7 +809,6 @@ void LayoutGrid::PlaceItemsOnGrid(
}
grid.insert(*child, area);
}
- grid.SetHasAnyOrthogonalGridItem(!orthogonal_grid_items.IsEmpty());
#if DCHECK_IS_ON()
if (grid.HasGridItems()) {
@@ -858,14 +832,6 @@ void LayoutGrid::PlaceItemsOnGrid(
grid.SetNeedsItemsPlacement(false);
- // Blink does a pre-layout of all the orthogonal boxes in the layout
- // tree (see how LocalFrameView::PerformLayout calls its
- // LayoutOrthogonalWritingModeRoots function). However, grid items
- // don't participate in this process (see the function
- // PrepareOrthogonalWritingModeRootForLayout) because it's useless
- // and even wrong if they don't have their corresponding Grid Area.
- LayoutOrthogonalWritingModeRoots(grid, orthogonal_grid_items);
-
#if DCHECK_IS_ON()
for (LayoutBox* child = grid.GetOrderIterator().First(); child;
child = grid.GetOrderIterator().Next()) {
@@ -890,22 +856,39 @@ static bool PrepareOrthogonalWritingModeRootForLayout(LayoutObject& root) {
return true;
}
-// TODO(lajava): Consider rafactoring this code with
-// LocalFrameView::LayoutOrthogonalWritingModeRoots
-void LayoutGrid::LayoutOrthogonalWritingModeRoots(
- const Grid& grid,
- const Vector<LayoutBox*>& orthogonal_grid_items) const {
+void LayoutGrid::PerformGridItemsPreLayout(
+ const GridTrackSizingAlgorithm& algorithm) const {
+ DCHECK(!algorithm.GetGrid().NeedsItemsPlacement());
if (!GetDocument().View()->IsInPerformLayout())
return;
-
- for (auto* root : orthogonal_grid_items) {
- DCHECK(GridLayoutUtils::IsOrthogonalChild(*this, *root));
- if (PrepareOrthogonalWritingModeRootForLayout(*root)) {
- UpdateGridAreaLogicalSize(
- *root,
- LayoutSize(EstimatedGridAreaBreadthForChild(grid, *root, kForColumns),
- EstimatedGridAreaBreadthForChild(grid, *root, kForRows)));
- root->LayoutIfNeeded();
+ for (auto* child = FirstInFlowChildBox(); child;
+ child = child->NextInFlowSiblingBox()) {
+ // Blink does a pre-layout of all the orthogonal boxes in the layout
+ // tree (see how LocalFrameView::PerformLayout calls its
+ // LayoutOrthogonalWritingModeRoots function). However, grid items
+ // don't participate in this process (see the function
+ // PrepareOrthogonalWritingModeRootForLayout) because it's useless
+ // and even wrong if they don't have their corresponding Grid Area.
+ // TODO(jfernandez): Consider rafactoring this code with
+ // LocalFrameView::LayoutOrthogonalWritingModeRoots
+ if (GridLayoutUtils::IsOrthogonalChild(*this, *child)) {
+ if (PrepareOrthogonalWritingModeRootForLayout(*child)) {
+ UpdateGridAreaLogicalSize(
+ *child, algorithm.EstimatedGridAreaBreadthForChild(*child));
+ child->LayoutIfNeeded();
+ continue;
+ }
+ }
+ // We need to layout the item to know whether it must synthesize its
+ // baseline or not, which may imply a cyclic sizing dependency.
+ // TODO (jfernandez): Can we avoid it ?
+ if (IsBaselineAlignmentForChild(*child)) {
+ if (child->HasRelativeLogicalWidth() ||
+ child->HasRelativeLogicalHeight()) {
+ UpdateGridAreaLogicalSize(
+ *child, algorithm.EstimatedGridAreaBreadthForChild(*child));
+ }
+ child->LayoutIfNeeded();
}
}
}
@@ -1017,13 +1000,12 @@ void LayoutGrid::PlaceSpecifiedMajorAxisItemsOnGrid(
*Style(), *auto_grid_item, AutoPlacementMinorAxisDirection());
unsigned major_axis_initial_position = major_axis_positions.StartLine();
- GridIterator iterator(
- grid, AutoPlacementMajorAxisDirection(),
- major_axis_positions.StartLine(),
+ auto iterator = grid.CreateIterator(
+ AutoPlacementMajorAxisDirection(), major_axis_positions.StartLine(),
is_grid_auto_flow_dense
? 0
: minor_axis_cursors.at(major_axis_initial_position));
- std::unique_ptr<GridArea> empty_grid_area = iterator.NextEmptyGridArea(
+ std::unique_ptr<GridArea> empty_grid_area = iterator->NextEmptyGridArea(
major_axis_positions.IntegerSpan(), minor_axis_span_size);
if (!empty_grid_area) {
empty_grid_area = CreateEmptyGridAreaAtSpecifiedPositionsOutsideGrid(
@@ -1089,10 +1071,10 @@ void LayoutGrid::PlaceAutoMajorAxisItemOnGrid(
major_axis_auto_placement_cursor++;
if (major_axis_auto_placement_cursor < end_of_major_axis) {
- GridIterator iterator(grid, AutoPlacementMinorAxisDirection(),
- minor_axis_positions.StartLine(),
- major_axis_auto_placement_cursor);
- empty_grid_area = iterator.NextEmptyGridArea(
+ auto iterator = grid.CreateIterator(AutoPlacementMinorAxisDirection(),
+ minor_axis_positions.StartLine(),
+ major_axis_auto_placement_cursor);
+ empty_grid_area = iterator->NextEmptyGridArea(
minor_axis_positions.IntegerSpan(), major_axis_span_size);
}
@@ -1108,10 +1090,11 @@ void LayoutGrid::PlaceAutoMajorAxisItemOnGrid(
for (size_t major_axis_index = major_axis_auto_placement_cursor;
major_axis_index < end_of_major_axis; ++major_axis_index) {
- GridIterator iterator(grid, AutoPlacementMajorAxisDirection(),
- major_axis_index, minor_axis_auto_placement_cursor);
- empty_grid_area = iterator.NextEmptyGridArea(major_axis_span_size,
- minor_axis_span_size);
+ auto iterator = grid.CreateIterator(AutoPlacementMajorAxisDirection(),
+ major_axis_index,
+ minor_axis_auto_placement_cursor);
+ empty_grid_area = iterator->NextEmptyGridArea(major_axis_span_size,
+ minor_axis_span_size);
if (empty_grid_area) {
// Check that it fits in the minor axis direction, as we shouldn't grow
@@ -1158,10 +1141,10 @@ GridTrackSizingDirection LayoutGrid::AutoPlacementMinorAxisDirection() const {
}
void LayoutGrid::DirtyGrid() {
- if (grid_.NeedsItemsPlacement())
+ if (grid_->NeedsItemsPlacement())
return;
- grid_.SetNeedsItemsPlacement(true);
+ grid_->SetNeedsItemsPlacement(true);
grid_items_overflowing_grid_area_.resize(0);
}
@@ -1171,14 +1154,15 @@ Vector<LayoutUnit> LayoutGrid::TrackSizesForComputedStyle(
auto& positions = is_row_axis ? column_positions_ : row_positions_;
size_t num_positions = positions.size();
LayoutUnit offset_between_tracks =
- is_row_axis ? offset_between_columns_ : offset_between_rows_;
+ is_row_axis ? offset_between_columns_.distribution_offset
+ : offset_between_rows_.distribution_offset;
Vector<LayoutUnit> tracks;
if (num_positions < 2)
return tracks;
- DCHECK(!grid_.NeedsItemsPlacement());
- bool has_collapsed_tracks = grid_.HasAutoRepeatEmptyTracks(direction);
+ DCHECK(!grid_->NeedsItemsPlacement());
+ bool has_collapsed_tracks = grid_->HasAutoRepeatEmptyTracks(direction);
LayoutUnit gap = !has_collapsed_tracks ? GridGap(direction) : LayoutUnit();
tracks.ReserveCapacity(num_positions - 1);
for (size_t i = 0; i < num_positions - 2; ++i)
@@ -1190,11 +1174,11 @@ Vector<LayoutUnit> LayoutGrid::TrackSizesForComputedStyle(
return tracks;
size_t remaining_empty_tracks =
- grid_.AutoRepeatEmptyTracks(direction)->size();
+ grid_->AutoRepeatEmptyTracks(direction)->size();
size_t last_line = tracks.size();
gap = GridGap(direction);
for (size_t i = 1; i < last_line; ++i) {
- if (grid_.IsEmptyAutoRepeatTrack(direction, i - 1)) {
+ if (grid_->IsEmptyAutoRepeatTrack(direction, i - 1)) {
--remaining_empty_tracks;
} else {
// Remove the gap between consecutive non empty tracks. Remove it also
@@ -1203,7 +1187,7 @@ Vector<LayoutUnit> LayoutGrid::TrackSizesForComputedStyle(
bool all_remaining_tracks_are_empty =
remaining_empty_tracks == (last_line - i);
if (!all_remaining_tracks_are_empty ||
- !grid_.IsEmptyAutoRepeatTrack(direction, i))
+ !grid_->IsEmptyAutoRepeatTrack(direction, i))
tracks[i - 1] -= gap;
}
}
@@ -1217,17 +1201,36 @@ const StyleContentAlignmentData& LayoutGrid::ContentAlignmentNormalBehavior() {
return kNormalBehavior;
}
+static bool OverrideSizeChanged(const LayoutBox& child,
+ GridTrackSizingDirection direction,
+ LayoutSize size) {
+ if (direction == kForColumns) {
+ return !child.HasOverrideContainingBlockContentLogicalWidth() ||
+ child.OverrideContainingBlockContentLogicalWidth() != size.Width();
+ }
+ return !child.HasOverrideContainingBlockContentLogicalHeight() ||
+ child.OverrideContainingBlockContentLogicalHeight() != size.Height();
+}
+
+static bool HasRelativeBlockAxisSize(const LayoutGrid& grid,
+ const LayoutBox& child) {
+ return GridLayoutUtils::IsOrthogonalChild(grid, child)
+ ? child.HasRelativeLogicalWidth() ||
+ child.StyleRef().LogicalWidth().IsAuto()
+ : child.HasRelativeLogicalHeight();
+}
+
void LayoutGrid::UpdateGridAreaLogicalSize(
LayoutBox& child,
LayoutSize grid_area_logical_size) const {
// Because the grid area cannot be styled, we don't need to adjust
// the grid breadth to account for 'box-sizing'.
- if (child.OverrideContainingBlockContentLogicalWidth() !=
- grid_area_logical_size.Width() ||
- (child.OverrideContainingBlockContentLogicalHeight() !=
- grid_area_logical_size.Height() &&
- (child.HasRelativeLogicalHeight() ||
- GridLayoutUtils::IsOrthogonalChild(*this, child)))) {
+ bool grid_area_width_changed =
+ OverrideSizeChanged(child, kForColumns, grid_area_logical_size);
+ bool grid_area_height_changed =
+ OverrideSizeChanged(child, kForRows, grid_area_logical_size);
+ if (grid_area_width_changed ||
+ (grid_area_height_changed && HasRelativeBlockAxisSize(*this, child))) {
child.SetNeedsLayout(LayoutInvalidationReason::kGridChanged, kMarkOnlyThis);
}
@@ -1271,7 +1274,7 @@ void LayoutGrid::LayoutGridItems() {
UpdateAutoMarginsInColumnAxisIfNeeded(*child);
UpdateAutoMarginsInRowAxisIfNeeded(*child);
- const GridArea& area = grid_.GridItemArea(*child);
+ const GridArea& area = grid_->GridItemArea(*child);
#if DCHECK_IS_ON()
DCHECK_LT(area.columns.StartLine(),
track_sizing_algorithm_.Tracks(kForColumns).size());
@@ -1351,40 +1354,6 @@ void LayoutGrid::LayoutPositionedObjects(bool relayout_children,
}
}
-LayoutUnit LayoutGrid::EstimatedGridAreaBreadthForChild(
- const Grid& grid,
- const LayoutBox& child,
- GridTrackSizingDirection direction) const {
- const GridSpan& span = grid.GridItemSpan(child, direction);
- LayoutUnit grid_area_size;
- bool grid_area_is_indefinite = false;
- base::Optional<LayoutUnit> available_size =
- track_sizing_algorithm_.AvailableSpace(direction);
- for (auto track_position : span) {
- GridLength max_track_size =
- track_sizing_algorithm_.GetGridTrackSize(direction, track_position)
- .MaxTrackBreadth();
- if (max_track_size.IsContentSized() || max_track_size.IsFlex()) {
- grid_area_is_indefinite = true;
- } else {
- grid_area_size += ValueForLength(max_track_size.length(),
- available_size.value_or(LayoutUnit()));
- }
- }
-
- grid_area_size += GuttersSize(grid_, direction, span.StartLine(),
- span.IntegerSpan(), available_size);
-
- GridTrackSizingDirection child_inline_direction =
- GridLayoutUtils::FlowAwareDirectionForChild(*this, child, kForColumns);
- if (grid_area_is_indefinite) {
- return direction == child_inline_direction
- ? std::max(child.MaxPreferredLogicalWidth(), grid_area_size)
- : LayoutUnit(-1);
- }
- return grid_area_size;
-}
-
LayoutUnit LayoutGrid::GridAreaBreadthForChildIncludingAlignmentOffsets(
const LayoutBox& child,
GridTrackSizingDirection direction) const {
@@ -1421,12 +1390,12 @@ void LayoutGrid::PopulateGridPositionsForDirection(
size_t number_of_tracks = tracks.size();
size_t number_of_lines = number_of_tracks + 1;
size_t last_line = number_of_lines - 1;
- bool has_collapsed_tracks = grid_.HasAutoRepeatEmptyTracks(direction);
+ bool has_collapsed_tracks = grid_->HasAutoRepeatEmptyTracks(direction);
size_t number_of_collapsed_tracks =
- has_collapsed_tracks ? grid_.AutoRepeatEmptyTracks(direction)->size() : 0;
- ContentAlignmentData offset = ComputeContentPositionAndDistributionOffset(
- direction, track_sizing_algorithm_.FreeSpace(direction).value(),
- number_of_tracks - number_of_collapsed_tracks);
+ has_collapsed_tracks ? grid_->AutoRepeatEmptyTracks(direction)->size()
+ : 0;
+ const auto& offset =
+ direction == kForColumns ? offset_between_columns_ : offset_between_rows_;
auto& positions = is_row_axis ? column_positions_ : row_positions_;
positions.resize(number_of_lines);
auto border_and_padding =
@@ -1453,7 +1422,7 @@ void LayoutGrid::PopulateGridPositionsForDirection(
LayoutUnit offset_accumulator;
LayoutUnit gap_accumulator;
for (size_t i = 1; i < last_line; ++i) {
- if (grid_.IsEmptyAutoRepeatTrack(direction, i - 1)) {
+ if (grid_->IsEmptyAutoRepeatTrack(direction, i - 1)) {
--remaining_empty_tracks;
offset_accumulator += offset.distribution_offset;
} else {
@@ -1462,7 +1431,7 @@ void LayoutGrid::PopulateGridPositionsForDirection(
bool all_remaining_tracks_are_empty =
remaining_empty_tracks == (last_line - i);
if (!all_remaining_tracks_are_empty ||
- !grid_.IsEmptyAutoRepeatTrack(direction, i))
+ !grid_->IsEmptyAutoRepeatTrack(direction, i))
gap_accumulator += gap;
}
positions[i] += gap_accumulator - offset_accumulator;
@@ -1470,9 +1439,6 @@ void LayoutGrid::PopulateGridPositionsForDirection(
positions[last_line] += gap_accumulator - offset_accumulator;
}
}
- auto& offset_between_tracks =
- is_row_axis ? offset_between_columns_ : offset_between_rows_;
- offset_between_tracks = offset.distribution_offset;
}
static LayoutUnit ComputeOverflowAlignmentOffset(OverflowAlignment overflow,
@@ -1655,20 +1621,21 @@ LayoutUnit LayoutGrid::BaselinePosition(FontBaseline,
}
LayoutUnit LayoutGrid::FirstLineBoxBaseline() const {
- if (IsWritingModeRoot() || !grid_.HasGridItems())
+ if (IsWritingModeRoot() || !grid_->HasGridItems() ||
+ ShouldApplySizeContainment())
return LayoutUnit(-1);
const LayoutBox* baseline_child = nullptr;
const LayoutBox* first_child = nullptr;
bool is_baseline_aligned = false;
// Finding the first grid item in grid order.
for (size_t column = 0;
- !is_baseline_aligned && column < grid_.NumTracks(kForColumns);
+ !is_baseline_aligned && column < grid_->NumTracks(kForColumns);
column++) {
- for (size_t index = 0; index < grid_.Cell(0, column).size(); index++) {
- const LayoutBox* child = grid_.Cell(0, column)[index];
+ for (size_t index = 0; index < grid_->Cell(0, column).size(); index++) {
+ const LayoutBox* child = grid_->Cell(0, column)[index];
DCHECK(!child->IsOutOfFlowPositioned());
// If an item participates in baseline alignment, we select such item.
- if (IsBaselineAlignmentForChild(*child)) {
+ if (IsBaselineAlignmentForChild(*child, kGridColumnAxis)) {
// TODO (lajava): self-baseline and content-baseline alignment
// still not implemented.
baseline_child = child;
@@ -1677,8 +1644,8 @@ LayoutUnit LayoutGrid::FirstLineBoxBaseline() const {
}
if (!baseline_child) {
// Use dom order for items in the same cell.
- if (!first_child || (grid_.GridItemPaintOrder(*child) <
- grid_.GridItemPaintOrder(*first_child)))
+ if (!first_child || (grid_->GridItemPaintOrder(*child) <
+ grid_->GridItemPaintOrder(*first_child)))
first_child = child;
}
}
@@ -1718,6 +1685,11 @@ LayoutUnit LayoutGrid::InlineBlockBaseline(LineDirectionMode direction) const {
return SynthesizedBaselineFromContentBox(*this, direction) + margin_height;
}
+bool LayoutGrid::IsBaselineAlignmentForChild(const LayoutBox& child) const {
+ return IsBaselineAlignmentForChild(child, kGridRowAxis) ||
+ IsBaselineAlignmentForChild(child, kGridColumnAxis);
+}
+
bool LayoutGrid::IsBaselineAlignmentForChild(const LayoutBox& child,
GridAxis baseline_axis) const {
if (child.IsOutOfFlowPositioned())
@@ -1730,16 +1702,6 @@ bool LayoutGrid::IsBaselineAlignmentForChild(const LayoutBox& child,
return IsBaselinePosition(align) && !has_auto_margins;
}
-void LayoutGrid::ComputeBaselineAlignmentContext() {
- for (auto* child = FirstInFlowChildBox(); child;
- child = child->NextInFlowSiblingBox()) {
- track_sizing_algorithm_.UpdateBaselineAlignmentContextIfNeeded(
- *child, kGridRowAxis);
- track_sizing_algorithm_.UpdateBaselineAlignmentContextIfNeeded(
- *child, kGridColumnAxis);
- }
-}
-
LayoutUnit LayoutGrid::ColumnAxisBaselineOffsetForChild(
const LayoutBox& child) const {
return track_sizing_algorithm_.BaselineOffsetForChild(child, kGridColumnAxis);
@@ -1981,7 +1943,7 @@ LayoutUnit LayoutGrid::ResolveAutoStartGridPosition(
if (direction == kForRows || StyleRef().IsLeftToRightDirection())
return LayoutUnit();
- int last_line = NumTracks(kForColumns, grid_);
+ int last_line = NumTracks(kForColumns, *grid_);
ContentPosition position = StyleRef().ResolvedJustifyContentPosition(
ContentAlignmentNormalBehavior());
if (position == ContentPosition::kEnd)
@@ -2001,7 +1963,7 @@ LayoutUnit LayoutGrid::ResolveAutoEndGridPosition(
if (StyleRef().IsLeftToRightDirection())
return ClientLogicalWidth();
- int last_line = NumTracks(kForColumns, grid_);
+ int last_line = NumTracks(kForColumns, *grid_);
ContentPosition position = StyleRef().ResolvedJustifyContentPosition(
ContentAlignmentNormalBehavior());
if (position == ContentPosition::kEnd)
@@ -2026,10 +1988,10 @@ LayoutUnit LayoutGrid::GridAreaBreadthForOutOfFlowChild(
if (span.IsIndefinite())
return is_row_axis ? ClientLogicalWidth() : ClientLogicalHeight();
- int smallest_start = abs(grid_.SmallestTrackStart(direction));
+ int smallest_start = abs(grid_->SmallestTrackStart(direction));
int start_line = span.UntranslatedStartLine() + smallest_start;
int end_line = span.UntranslatedEndLine() + smallest_start;
- int last_line = NumTracks(direction, grid_);
+ int last_line = NumTracks(direction, *grid_);
GridPosition start_position = direction == kForColumns
? child.Style()->GridColumnStart()
: child.Style()->GridRowStart();
@@ -2067,10 +2029,11 @@ LayoutUnit LayoutGrid::GridAreaBreadthForOutOfFlowChild(
base::Optional<LayoutUnit> available_size_for_gutters =
AvailableSpaceForGutters(direction);
if (end_line > 0 && end_line < last_line) {
- DCHECK(!grid_.NeedsItemsPlacement());
- end -= GuttersSize(grid_, direction, end_line - 1, 2,
+ DCHECK(!grid_->NeedsItemsPlacement());
+ end -= GuttersSize(*grid_, direction, end_line - 1, 2,
available_size_for_gutters);
- end -= is_row_axis ? offset_between_columns_ : offset_between_rows_;
+ end -= is_row_axis ? offset_between_columns_.distribution_offset
+ : offset_between_rows_.distribution_offset;
}
}
// TODO (lajava): Is expectable that in some cases 'end' is smaller than
@@ -2177,7 +2140,8 @@ ContentPosition static ResolveContentDistributionFallback(
return ContentPosition::kNormal;
}
-static ContentAlignmentData ContentDistributionOffset(
+static void ComputeContentDistributionOffset(
+ ContentAlignmentData& offset,
const LayoutUnit& available_free_space,
ContentPosition& fallback_position,
ContentDistributionType distribution,
@@ -2186,30 +2150,41 @@ static ContentAlignmentData ContentDistributionOffset(
fallback_position == ContentPosition::kNormal)
fallback_position = ResolveContentDistributionFallback(distribution);
+ // Initialize to an invalid offset.
+ offset.position_offset = LayoutUnit(-1);
+ offset.distribution_offset = LayoutUnit(-1);
if (available_free_space <= 0)
- return {};
+ return;
+ LayoutUnit position_offset;
LayoutUnit distribution_offset;
switch (distribution) {
case ContentDistributionType::kSpaceBetween:
if (number_of_grid_tracks < 2)
- return {};
- return {LayoutUnit(), available_free_space / (number_of_grid_tracks - 1)};
+ return;
+ distribution_offset = available_free_space / (number_of_grid_tracks - 1);
+ position_offset = LayoutUnit();
+ break;
case ContentDistributionType::kSpaceAround:
if (number_of_grid_tracks < 1)
- return {};
+ return;
distribution_offset = available_free_space / number_of_grid_tracks;
- return {distribution_offset / 2, distribution_offset};
+ position_offset = distribution_offset / 2;
+ break;
case ContentDistributionType::kSpaceEvenly:
distribution_offset = available_free_space / (number_of_grid_tracks + 1);
- return {distribution_offset, distribution_offset};
+ position_offset = distribution_offset;
+ break;
case ContentDistributionType::kStretch:
case ContentDistributionType::kDefault:
- return {};
+ return;
+ default:
+ NOTREACHED();
+ return;
}
- NOTREACHED();
- return {};
+ offset.position_offset = position_offset;
+ offset.distribution_offset = distribution_offset;
}
StyleContentAlignmentData LayoutGrid::ContentAlignment(
@@ -2220,71 +2195,93 @@ StyleContentAlignmentData LayoutGrid::ContentAlignment(
ContentAlignmentNormalBehavior());
}
-ContentAlignmentData LayoutGrid::ComputeContentPositionAndDistributionOffset(
+void LayoutGrid::ComputeContentPositionAndDistributionOffset(
GridTrackSizingDirection direction,
const LayoutUnit& available_free_space,
- unsigned number_of_grid_tracks) const {
+ unsigned number_of_grid_tracks) {
+ auto& offset =
+ direction == kForColumns ? offset_between_columns_ : offset_between_rows_;
StyleContentAlignmentData content_alignment_data =
ContentAlignment(direction);
ContentPosition position = content_alignment_data.GetPosition();
// If <content-distribution> value can't be applied, 'position' will become
// the associated <content-position> fallback value.
- ContentAlignmentData content_alignment = ContentDistributionOffset(
- available_free_space, position, content_alignment_data.Distribution(),
- number_of_grid_tracks);
- if (content_alignment.IsValid())
- return content_alignment;
+ ComputeContentDistributionOffset(offset, available_free_space, position,
+ content_alignment_data.Distribution(),
+ number_of_grid_tracks);
+ if (offset.IsValid())
+ return;
// TODO (lajava): Default value for overflow isn't exaclty as 'unsafe'.
// https://drafts.csswg.org/css-align/#overflow-values
if (available_free_space == 0 ||
(available_free_space < 0 &&
- content_alignment_data.Overflow() == OverflowAlignment::kSafe))
- return {LayoutUnit(), LayoutUnit()};
+ content_alignment_data.Overflow() == OverflowAlignment::kSafe)) {
+ offset.position_offset = LayoutUnit();
+ offset.distribution_offset = LayoutUnit();
+ return;
+ }
+ LayoutUnit position_offset;
bool is_row_axis = direction == kForColumns;
switch (position) {
case ContentPosition::kLeft:
- if (is_row_axis)
- return {LayoutUnit(), LayoutUnit()};
+ DCHECK(is_row_axis);
+ position_offset = LayoutUnit();
break;
case ContentPosition::kRight:
- if (is_row_axis)
- return {available_free_space, LayoutUnit()};
+ DCHECK(is_row_axis);
+ position_offset = available_free_space;
break;
case ContentPosition::kCenter:
- return {available_free_space / 2, LayoutUnit()};
+ position_offset = available_free_space / 2;
+ break;
// Only used in flex layout, for other layout, it's equivalent to 'End'.
case ContentPosition::kFlexEnd:
+ U_FALLTHROUGH;
case ContentPosition::kEnd:
- if (is_row_axis)
- return {StyleRef().IsLeftToRightDirection() ? available_free_space
- : LayoutUnit(),
- LayoutUnit()};
- return {available_free_space, LayoutUnit()};
+ if (is_row_axis) {
+ position_offset = StyleRef().IsLeftToRightDirection()
+ ? available_free_space
+ : LayoutUnit();
+ } else {
+ position_offset = available_free_space;
+ }
+ break;
// Only used in flex layout, for other layout, it's equivalent to 'Start'.
case ContentPosition::kFlexStart:
+ U_FALLTHROUGH;
case ContentPosition::kStart:
- if (is_row_axis)
- return {StyleRef().IsLeftToRightDirection() ? LayoutUnit()
- : available_free_space,
- LayoutUnit()};
- return {LayoutUnit(), LayoutUnit()};
+ if (is_row_axis) {
+ position_offset = StyleRef().IsLeftToRightDirection()
+ ? LayoutUnit()
+ : available_free_space;
+ } else {
+ position_offset = LayoutUnit();
+ }
+ break;
case ContentPosition::kBaseline:
+ U_FALLTHROUGH;
case ContentPosition::kLastBaseline:
// FIXME: These two require implementing Baseline Alignment. For now, we
// always 'start' align the child. crbug.com/234191
- if (is_row_axis)
- return {StyleRef().IsLeftToRightDirection() ? LayoutUnit()
- : available_free_space,
- LayoutUnit()};
- return {LayoutUnit(), LayoutUnit()};
- case ContentPosition::kNormal:
+ if (is_row_axis) {
+ position_offset = StyleRef().IsLeftToRightDirection()
+ ? LayoutUnit()
+ : available_free_space;
+ } else {
+ position_offset = LayoutUnit();
+ }
break;
+ case ContentPosition::kNormal:
+ U_FALLTHROUGH;
+ default:
+ NOTREACHED();
+ return;
}
- NOTREACHED();
- return {LayoutUnit(), LayoutUnit()};
+ offset.position_offset = position_offset;
+ offset.distribution_offset = LayoutUnit();
}
LayoutUnit LayoutGrid::TranslateOutOfFlowRTLCoordinate(
@@ -2348,8 +2345,8 @@ LayoutPoint LayoutGrid::GridAreaLogicalPosition(const GridArea& area) const {
void LayoutGrid::PaintChildren(const PaintInfo& paint_info,
const LayoutPoint& paint_offset) const {
- DCHECK(!grid_.NeedsItemsPlacement());
- if (grid_.HasGridItems())
+ DCHECK(!grid_->NeedsItemsPlacement());
+ if (grid_->HasGridItems())
GridPainter(*this).PaintChildren(paint_info, paint_offset);
}
@@ -2358,6 +2355,17 @@ bool LayoutGrid::CachedHasDefiniteLogicalHeight() const {
return has_definite_logical_height_.value();
}
+size_t LayoutGrid::NonCollapsedTracks(
+ GridTrackSizingDirection direction) const {
+ auto& tracks = track_sizing_algorithm_.Tracks(direction);
+ size_t number_of_tracks = tracks.size();
+ bool has_collapsed_tracks = grid_->HasAutoRepeatEmptyTracks(direction);
+ size_t number_of_collapsed_tracks =
+ has_collapsed_tracks ? grid_->AutoRepeatEmptyTracks(direction)->size()
+ : 0;
+ return number_of_tracks - number_of_collapsed_tracks;
+}
+
size_t LayoutGrid::NumTracks(GridTrackSizingDirection direction,
const Grid& grid) const {
// Due to limitations in our internal representation, we cannot know the
@@ -2378,7 +2386,8 @@ size_t LayoutGrid::NumTracks(GridTrackSizingDirection direction,
LayoutUnit LayoutGrid::GridItemOffset(
GridTrackSizingDirection direction) const {
- return direction == kForRows ? offset_between_rows_ : offset_between_columns_;
+ return direction == kForRows ? offset_between_rows_.distribution_offset
+ : offset_between_columns_.distribution_offset;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_grid.h b/chromium/third_party/blink/renderer/core/layout/layout_grid.h
index 929e6954470..6fb09c71acd 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_grid.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_grid.h
@@ -36,10 +36,20 @@
namespace blink {
-struct ContentAlignmentData;
struct GridArea;
struct GridSpan;
+struct ContentAlignmentData {
+ public:
+ ContentAlignmentData() = default;
+ bool IsValid() { return position_offset >= 0 && distribution_offset >= 0; }
+
+ LayoutUnit position_offset = LayoutUnit(-1);
+ LayoutUnit distribution_offset = LayoutUnit(-1);
+
+ DISALLOW_COPY_AND_ASSIGN(ContentAlignmentData);
+};
+
enum GridAxisPosition { kGridAxisStart, kGridAxisEnd, kGridAxisCenter };
class LayoutGrid final : public LayoutBlock {
@@ -57,32 +67,32 @@ class LayoutGrid final : public LayoutBlock {
Vector<LayoutUnit> TrackSizesForComputedStyle(GridTrackSizingDirection) const;
const Vector<LayoutUnit>& ColumnPositions() const {
- DCHECK(!grid_.NeedsItemsPlacement());
+ DCHECK(!grid_->NeedsItemsPlacement());
return column_positions_;
}
const Vector<LayoutUnit>& RowPositions() const {
- DCHECK(!grid_.NeedsItemsPlacement());
+ DCHECK(!grid_->NeedsItemsPlacement());
return row_positions_;
}
const GridCell& GetGridCell(int row, int column) const {
- SECURITY_DCHECK(!grid_.NeedsItemsPlacement());
- return grid_.Cell(row, column);
+ SECURITY_DCHECK(!grid_->NeedsItemsPlacement());
+ return grid_->Cell(row, column);
}
const Vector<LayoutBox*>& ItemsOverflowingGridArea() const {
- SECURITY_DCHECK(!grid_.NeedsItemsPlacement());
+ SECURITY_DCHECK(!grid_->NeedsItemsPlacement());
return grid_items_overflowing_grid_area_;
}
int PaintIndexForGridItem(const LayoutBox* layout_box) const {
- SECURITY_DCHECK(!grid_.NeedsItemsPlacement());
- return grid_.GridItemPaintOrder(*layout_box);
+ SECURITY_DCHECK(!grid_->NeedsItemsPlacement());
+ return grid_->GridItemPaintOrder(*layout_box);
}
size_t AutoRepeatCountForDirection(GridTrackSizingDirection direction) const {
- return grid_.AutoRepeatTracks(direction);
+ return grid_->AutoRepeatTracks(direction);
}
LayoutUnit TranslateOutOfFlowRTLCoordinate(const LayoutBox&,
@@ -97,8 +107,8 @@ class LayoutGrid final : public LayoutBlock {
size_t span,
base::Optional<LayoutUnit> available_size) const;
bool CachedHasDefiniteLogicalHeight() const;
- bool IsBaselineAlignmentForChild(const LayoutBox& child,
- GridAxis = kGridColumnAxis) const;
+ bool IsBaselineAlignmentForChild(const LayoutBox& child) const;
+ bool IsBaselineAlignmentForChild(const LayoutBox& child, GridAxis) const;
StyleSelfAlignmentData SelfAlignmentForChild(
GridAxis,
@@ -108,9 +118,7 @@ class LayoutGrid final : public LayoutBlock {
LayoutUnit GridGap(GridTrackSizingDirection) const;
LayoutUnit GridItemOffset(GridTrackSizingDirection) const;
- LayoutUnit EstimatedGridAreaBreadthForChild(const Grid&,
- const LayoutBox&,
- GridTrackSizingDirection) const;
+ void UpdateGridAreaLogicalSize(LayoutBox&, LayoutSize) const;
StyleContentAlignmentData ContentAlignment(GridTrackSizingDirection) const;
@@ -164,11 +172,10 @@ class LayoutGrid final : public LayoutBlock {
Grid&,
GridTrackSizingDirection) const;
- void LayoutOrthogonalWritingModeRoots(const Grid&,
- const Vector<LayoutBox*>&) const;
+ void PerformGridItemsPreLayout(const GridTrackSizingAlgorithm&) const;
void PlaceItemsOnGrid(
- Grid&,
+ GridTrackSizingAlgorithm&,
base::Optional<LayoutUnit> available_logical_width) const;
void PopulateExplicitGridAndOrderIterator(Grid&) const;
std::unique_ptr<GridArea> CreateEmptyGridAreaAtSpecifiedPositionsOutsideGrid(
@@ -188,7 +195,6 @@ class LayoutGrid final : public LayoutBlock {
void ComputeTrackSizesForIndefiniteSize(GridTrackSizingAlgorithm&,
GridTrackSizingDirection,
- Grid&,
LayoutUnit& min_intrinsic_size,
LayoutUnit& max_intrinsic_size) const;
LayoutUnit ComputeTrackBasedLogicalHeight() const;
@@ -198,7 +204,6 @@ class LayoutGrid final : public LayoutBlock {
void RepeatTracksSizingIfNeeded(LayoutUnit available_space_for_columns,
LayoutUnit available_space_for_rows);
- void UpdateGridAreaLogicalSize(LayoutBox&, LayoutSize) const;
void LayoutGridItems();
void PrepareChildForPositionedLayout(LayoutBox&);
bool HasStaticPositionForChild(const LayoutBox&,
@@ -234,10 +239,10 @@ class LayoutGrid final : public LayoutBlock {
GridAxisPosition RowAxisPositionForChild(const LayoutBox&) const;
LayoutUnit RowAxisOffsetForChild(const LayoutBox&) const;
LayoutUnit ColumnAxisOffsetForChild(const LayoutBox&) const;
- ContentAlignmentData ComputeContentPositionAndDistributionOffset(
+ void ComputeContentPositionAndDistributionOffset(
GridTrackSizingDirection,
const LayoutUnit& available_free_space,
- unsigned number_of_grid_tracks) const;
+ unsigned number_of_grid_tracks);
LayoutPoint GridAreaLogicalPosition(const GridArea&) const;
LayoutPoint FindChildLogicalPosition(const LayoutBox&) const;
@@ -245,7 +250,8 @@ class LayoutGrid final : public LayoutBlock {
const LayoutBox&,
GridTrackSizingDirection) const;
- void PaintChildren(const PaintInfo&, const LayoutPoint&) const override;
+ void PaintChildren(const PaintInfo&,
+ const LayoutPoint& paint_offset) const override;
LayoutUnit AvailableAlignmentSpaceForChildBeforeStretching(
LayoutUnit grid_area_breadth_for_child,
@@ -298,6 +304,7 @@ class LayoutGrid final : public LayoutBlock {
size_t GridItemSpan(const LayoutBox&, GridTrackSizingDirection);
+ size_t NonCollapsedTracks(GridTrackSizingDirection) const;
size_t NumTracks(GridTrackSizingDirection, const Grid&) const;
static LayoutUnit OverrideContainingBlockContentSizeForChild(
@@ -309,13 +316,13 @@ class LayoutGrid final : public LayoutBlock {
LineDirectionMode);
static const StyleContentAlignmentData& ContentAlignmentNormalBehavior();
- Grid grid_;
+ std::unique_ptr<Grid> grid_;
GridTrackSizingAlgorithm track_sizing_algorithm_;
Vector<LayoutUnit> row_positions_;
Vector<LayoutUnit> column_positions_;
- LayoutUnit offset_between_columns_;
- LayoutUnit offset_between_rows_;
+ ContentAlignmentData offset_between_columns_;
+ ContentAlignmentData offset_between_rows_;
Vector<LayoutBox*> grid_items_overflowing_grid_area_;
typedef HashMap<const LayoutBox*, base::Optional<size_t>>
@@ -326,6 +333,7 @@ class LayoutGrid final : public LayoutBlock {
LayoutUnit min_content_height_{-1};
LayoutUnit max_content_height_{-1};
+ bool has_any_orthogonal_item_{false};
base::Optional<bool> has_definite_logical_height_;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_html_canvas.h b/chromium/third_party/blink/renderer/core/layout/layout_html_canvas.h
index 8d2e44dac2b..5058233b7c0 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_html_canvas.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_html_canvas.h
@@ -51,7 +51,8 @@ class LayoutHTMLCanvas final : public LayoutReplaced {
const char* GetName() const override { return "LayoutHTMLCanvas"; }
private:
- void PaintReplaced(const PaintInfo&, const LayoutPoint&) const override;
+ void PaintReplaced(const PaintInfo&,
+ const LayoutPoint& paint_offset) const override;
void IntrinsicSizeChanged() override { CanvasSizeChanged(); }
CompositingReasons AdditionalCompositingReasons() const override;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_image.cc b/chromium/third_party/blink/renderer/core/layout/layout_image.cc
index 976366b60e1..46c2078a03b 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_image.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_image.cc
@@ -36,12 +36,14 @@
#include "third_party/blink/renderer/core/html/html_image_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
+#include "third_party/blink/renderer/core/layout/intrinsic_sizing_info.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/paint/image_painter.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/svg/graphics/svg_image.h"
#include "third_party/blink/renderer/platform/feature_policy/feature_policy.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
@@ -53,8 +55,7 @@ bool CheckForOptimizedImagePolicy(const LocalFrame& frame,
ImageResourceContent* new_image) {
// Invert the image if the document does not have the 'legacy-image-formats'
// feature enabled, and the image is not one of the allowed formats.
- if (IsSupportedInFeaturePolicy(
- mojom::FeaturePolicyFeature::kLegacyImageFormats) &&
+ if (RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled() &&
!frame.IsFeatureEnabled(
mojom::FeaturePolicyFeature::kLegacyImageFormats)) {
if (!new_image->IsAcceptableContentType()) {
@@ -63,8 +64,7 @@ bool CheckForOptimizedImagePolicy(const LocalFrame& frame,
}
// Invert the image if the document does not have the image-compression'
// feature enabled and the image is not sufficiently-well-compressed.
- if (IsSupportedInFeaturePolicy(
- mojom::FeaturePolicyFeature::kImageCompression) &&
+ if (RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled() &&
!frame.IsFeatureEnabled(mojom::FeaturePolicyFeature::kImageCompression)) {
if (!new_image->IsAcceptableCompressionRatio())
return true;
@@ -75,8 +75,7 @@ bool CheckForOptimizedImagePolicy(const LocalFrame& frame,
bool CheckForMaxDownscalingImagePolicy(const LocalFrame& frame,
HTMLImageElement* element,
LayoutImage* layout_image) {
- if (!IsSupportedInFeaturePolicy(
- mojom::FeaturePolicyFeature::kMaxDownscalingImage) ||
+ if (!RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled() ||
frame.IsFeatureEnabled(mojom::FeaturePolicyFeature::kMaxDownscalingImage))
return false;
// Invert the image if the image's size is more than 2 times bigger than the
@@ -258,8 +257,13 @@ void LayoutImage::ImageNotifyFinished(ImageResourceContent* new_image) {
// Check for optimized image policies.
if (View() && View()->GetFrameView()) {
bool old_flag = ShouldInvertColor();
- is_legacy_format_or_compressed_image_ = CheckForOptimizedImagePolicy(
- View()->GetFrameView()->GetFrame(), this, new_image);
+ const LocalFrame& frame = View()->GetFrameView()->GetFrame();
+ is_legacy_format_or_compressed_image_ =
+ CheckForOptimizedImagePolicy(frame, this, new_image);
+ if (auto* image_element = ToHTMLImageElementOrNull(GetNode())) {
+ is_downscaled_image_ =
+ CheckForMaxDownscalingImagePolicy(frame, image_element, this);
+ }
if (old_flag != ShouldInvertColor())
UpdateShouldInvertColor();
}
@@ -276,9 +280,8 @@ void LayoutImage::PaintReplaced(const PaintInfo& paint_info,
ImagePainter(*this).PaintReplaced(paint_info, paint_offset);
}
-void LayoutImage::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
- ImagePainter(*this).Paint(paint_info, paint_offset);
+void LayoutImage::Paint(const PaintInfo& paint_info) const {
+ ImagePainter(*this).Paint(paint_info);
}
void LayoutImage::AreaElementFocusChanged(HTMLAreaElement* area_element) {
@@ -350,8 +353,7 @@ bool LayoutImage::NodeAtPoint(HitTestResult& result,
const HitTestLocation& location_in_container,
const LayoutPoint& accumulated_offset,
HitTestAction hit_test_action) {
- HitTestResult temp_result(result.GetHitTestRequest(),
- result.GetHitTestLocation());
+ HitTestResult temp_result(result);
bool inside = LayoutReplaced::NodeAtPoint(
temp_result, location_in_container, accumulated_offset, hit_test_action);
@@ -383,7 +385,7 @@ void LayoutImage::ComputeIntrinsicSizingInfo(
// Our intrinsicSize is empty if we're laying out generated images with
// relative width/height. Figure out the right intrinsic size to use.
if (intrinsic_sizing_info.size.IsEmpty() &&
- image_resource_->ImageHasRelativeSize()) {
+ image_resource_->ImageHasRelativeSize() && !IsLayoutNGListMarkerImage()) {
LayoutObject* containing_block =
IsOutOfFlowPositioned() ? Container() : ContainingBlock();
if (containing_block->IsBox()) {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_image.h b/chromium/third_party/blink/renderer/core/layout/layout_image.h
index 021c5035e57..e8742bea3a3 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_image.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_image.h
@@ -48,10 +48,6 @@ class SVGImage;
// See LayoutImageResource that holds this image.
class CORE_EXPORT LayoutImage : public LayoutReplaced {
public:
- // These are the paddings to use when displaying either alt text or an image.
- static const unsigned short kPaddingWidth = 4;
- static const unsigned short kPaddingHeight = 4;
-
LayoutImage(Element*);
~LayoutImage() override;
@@ -90,7 +86,7 @@ class CORE_EXPORT LayoutImage : public LayoutReplaced {
// When an image element violates feature policy optimized image policies, it
// should be rendered with inverted color.
- // https://github.com/WICG/feature-policy/blob/gh-pages/policies/optimized-images.md
+ // https://github.com/WICG/feature-policy/blob/master/policies/optimized-images.md
bool ShouldInvertColor() const;
void UpdateShouldInvertColor();
void UpdateShouldInvertColorForTest(bool);
@@ -106,7 +102,7 @@ class CORE_EXPORT LayoutImage : public LayoutReplaced {
CanDeferInvalidation,
const IntRect* = nullptr) override;
- void Paint(const PaintInfo&, const LayoutPoint&) const final;
+ void Paint(const PaintInfo&) const final;
bool IsOfType(LayoutObjectType type) const override {
return type == kLayoutObjectLayoutImage || LayoutReplaced::IsOfType(type);
@@ -121,7 +117,8 @@ class CORE_EXPORT LayoutImage : public LayoutReplaced {
private:
bool IsImage() const override { return true; }
- void PaintReplaced(const PaintInfo&, const LayoutPoint&) const override;
+ void PaintReplaced(const PaintInfo&,
+ const LayoutPoint& paint_offset) const override;
bool ForegroundIsKnownToBeOpaqueInRect(
const LayoutRect& local_rect,
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_image_resource.cc b/chromium/third_party/blink/renderer/core/layout/layout_image_resource.cc
index d84e9300e40..62ebf5cc5c5 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_image_resource.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_image_resource.cc
@@ -113,6 +113,12 @@ FloatSize LayoutImageResource::ImageSize(float multiplier) const {
return size;
}
+FloatSize LayoutImageResource::ImageSizeWithDefaultSize(
+ float multiplier,
+ const LayoutSize&) const {
+ return ImageSize(multiplier);
+}
+
float LayoutImageResource::DeviceScaleFactor() const {
return DeviceScaleFactorDeprecated(layout_object_->GetFrame());
}
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_image_resource.h b/chromium/third_party/blink/renderer/core/layout/layout_image_resource.h
index 2005a64d4fb..4d2776a9f6e 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_image_resource.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_image_resource.h
@@ -65,7 +65,9 @@ class CORE_EXPORT LayoutImageResource
virtual bool ImageHasRelativeSize() const;
virtual FloatSize ImageSize(float multiplier) const;
-
+ // Default size is effective when this is LayoutImageResourceStyleImage.
+ virtual FloatSize ImageSizeWithDefaultSize(float multiplier,
+ const LayoutSize&) const;
virtual WrappedImagePtr ImagePtr() const { return cached_image_.Get(); }
virtual void Trace(blink::Visitor* visitor) { visitor->Trace(cached_image_); }
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc b/chromium/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc
index af0dbd1ebba..d713f05773d 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc
@@ -70,11 +70,17 @@ scoped_refptr<Image> LayoutImageResourceStyleImage::GetImage(
FloatSize LayoutImageResourceStyleImage::ImageSize(float multiplier) const {
// TODO(davve): Find out the correct default object size in this context.
- return style_image_->ImageSize(layout_object_->GetDocument(), multiplier,
- LayoutSize(LayoutReplaced::kDefaultWidth,
- LayoutReplaced::kDefaultHeight));
+ return ImageSizeWithDefaultSize(multiplier,
+ LayoutSize(LayoutReplaced::kDefaultWidth,
+ LayoutReplaced::kDefaultHeight));
}
+FloatSize LayoutImageResourceStyleImage::ImageSizeWithDefaultSize(
+ float multiplier,
+ const LayoutSize& default_size) const {
+ return style_image_->ImageSize(layout_object_->GetDocument(), multiplier,
+ default_size);
+}
void LayoutImageResourceStyleImage::Trace(blink::Visitor* visitor) {
visitor->Trace(style_image_);
LayoutImageResource::Trace(visitor);
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_image_resource_style_image.h b/chromium/third_party/blink/renderer/core/layout/layout_image_resource_style_image.h
index 92067a2fef5..644d3e77a27 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_image_resource_style_image.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_image_resource_style_image.h
@@ -53,6 +53,8 @@ class LayoutImageResourceStyleImage final : public LayoutImageResource {
return style_image_->ImageHasRelativeSize();
}
FloatSize ImageSize(float multiplier) const override;
+ FloatSize ImageSizeWithDefaultSize(float multiplier,
+ const LayoutSize&) const override;
WrappedImagePtr ImagePtr() const override { return style_image_->Data(); }
void Trace(blink::Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_image_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_image_test.cc
new file mode 100644
index 00000000000..3258c1e8e75
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/layout_image_test.cc
@@ -0,0 +1,31 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/layout/layout_geometry_map.h"
+#include "third_party/blink/renderer/core/paint/paint_layer.h"
+#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
+
+namespace blink {
+
+using LayoutImageTest = RenderingTest;
+
+TEST_F(LayoutImageTest, HitTestUnderTransform) {
+ SetBodyInnerHTML(R"HTML(
+ <div style='transform: translateX(50px)'>
+ <img id=target style='width: 20px; height: 20px'/>
+ </div>
+ )HTML");
+
+ const auto& target = *GetDocument().getElementById("target");
+ HitTestLocation location(LayoutPoint(60, 10));
+ HitTestResult result(
+ HitTestRequest(HitTestRequest::kReadOnly | HitTestRequest::kActive |
+ HitTestRequest::kAllowChildFrameContent),
+ location);
+ GetLayoutView().HitTest(location, result);
+ EXPECT_EQ(LayoutPoint(60, 10), result.PointInInnerNodeFrame());
+ EXPECT_EQ(target, result.InnerNode());
+}
+
+} // 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 278a1099131..e287ac7b2a5 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_inline.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_inline.cc
@@ -29,7 +29,6 @@
#include "third_party/blink/renderer/core/layout/api/line_layout_box_model.h"
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
#include "third_party/blink/renderer/core/layout/layout_block.h"
-#include "third_party/blink/renderer/core/layout/layout_full_screen.h"
#include "third_party/blink/renderer/core/layout/layout_geometry_map.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -81,6 +80,12 @@ LayoutInline* LayoutInline::CreateAnonymous(Document* document) {
return layout_inline;
}
+bool LayoutInline::IsFirstLineAnonymous() const {
+ // TODO(kojii): We can add a flag, but this seems enough for now.
+ return IsAnonymous() && Parent() && Parent()->IsLayoutBlockFlow() &&
+ !PreviousSibling() && !NextSibling();
+}
+
void LayoutInline::WillBeDestroyed() {
// Make sure to destroy anonymous children first while they are still
// connected to the rest of the tree, so that they will properly dirty line
@@ -397,8 +402,8 @@ void LayoutInline::AddChildIgnoringContinuation(LayoutObject* new_child,
InFlowPositionedInlineAncestor(this))
new_style->SetPosition(positioned_ancestor->Style()->GetPosition());
- LayoutBlockFlow* new_box = LayoutBlockFlow::CreateAnonymous(&GetDocument());
- new_box->SetStyle(std::move(new_style));
+ LayoutBlockFlow* new_box =
+ LayoutBlockFlow::CreateAnonymous(&GetDocument(), std::move(new_style));
LayoutBoxModelObject* old_continuation = Continuation();
SetContinuation(new_box);
@@ -442,18 +447,6 @@ void LayoutInline::SplitInlines(LayoutBlockFlow* from_block,
DCHECK(IsDescendantOf(from_block));
DCHECK(!IsAnonymous());
- // If we're splitting the inline containing the fullscreened element,
- // |beforeChild| may be the layoutObject for the fullscreened element.
- // However, that layoutObject is wrapped in a LayoutFullScreen, so |this| is
- // not its parent. Since the splitting logic expects |this| to be the parent,
- // set |beforeChild| to be the LayoutFullScreen.
- if (Fullscreen* fullscreen = Fullscreen::FromIfExists(GetDocument())) {
- const Element* fullscreen_element = fullscreen->FullscreenElement();
- if (fullscreen_element && before_child &&
- before_child->GetNode() == fullscreen_element)
- before_child = fullscreen->FullScreenLayoutObject();
- }
-
// FIXME: Because splitting is O(n^2) as tags nest pathologically, we cap the
// depth at which we're willing to clone.
// There will eventually be a better approach to this problem that will let us
@@ -644,20 +637,8 @@ void LayoutInline::AddChildToContinuation(LayoutObject* new_child,
before_child);
}
-void LayoutInline::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
- if (RuntimeEnabledFeatures::LayoutNGEnabled()) {
- // Inline box with self painting layer is painted in this code path.
- if (LayoutBlockFlow* block_flow = EnclosingNGBlockFlow()) {
- if (NGPaintFragment* block_flow_fragment = block_flow->PaintFragment()) {
- block_flow_fragment->PaintInlineBoxForDescendants(paint_info,
- paint_offset, this);
- return;
- }
- }
- }
-
- InlinePainter(*this).Paint(paint_info, paint_offset);
+void LayoutInline::Paint(const PaintInfo& paint_info) const {
+ InlinePainter(*this).Paint(paint_info);
}
template <typename GeneratorContext>
@@ -915,13 +896,13 @@ bool LayoutInline::NodeAtPoint(HitTestResult& result,
for (const NGPaintFragment* fragment :
NGPaintFragment::InlineFragmentsFor(this)) {
// NGBoxFragmentPainter::NodeAtPoint() takes an offset that is accumulated
- // up to its parent fragment. Compute this offset.
+ // up to the fragment itself. Compute this offset.
LayoutPoint adjusted_location =
accumulated_offset +
- fragment->Parent()->InlineOffsetToContainerBox().ToLayoutPoint();
+ fragment->InlineOffsetToContainerBox().ToLayoutPoint();
if (NGBoxFragmentPainter(*fragment).NodeAtPoint(
result, location_in_container, adjusted_location,
- accumulated_offset, hit_test_action))
+ hit_test_action))
return true;
}
return false;
@@ -964,8 +945,9 @@ class HitTestCulledInlinesGeneratorContext {
bool LayoutInline::HitTestCulledInline(
HitTestResult& result,
const HitTestLocation& location_in_container,
- const LayoutPoint& accumulated_offset) {
- DCHECK(!AlwaysCreateLineBoxes());
+ const LayoutPoint& accumulated_offset,
+ const NGPaintFragment* container_fragment) {
+ DCHECK(container_fragment || !AlwaysCreateLineBoxes());
if (!VisibleToHitTestRequest(result.GetHitTestRequest()))
return false;
@@ -975,7 +957,26 @@ bool LayoutInline::HitTestCulledInline(
Region region_result;
HitTestCulledInlinesGeneratorContext context(region_result,
adjusted_location);
- GenerateCulledLineBoxRects(context, this);
+ if (container_fragment) {
+ DCHECK(EnclosingNGBlockFlow());
+ DCHECK(container_fragment->IsDescendantOfNotSelf(
+ *EnclosingNGBlockFlow()->PaintFragment()));
+ const NGPhysicalContainerFragment& traversal_root =
+ ToNGPhysicalContainerFragment(container_fragment->PhysicalFragment());
+ DCHECK(traversal_root.IsInline() || traversal_root.IsLineBox());
+ const LayoutPoint root_offset =
+ container_fragment->InlineOffsetToContainerBox().ToLayoutPoint();
+ const auto& descendants =
+ NGInlineFragmentTraversal::SelfFragmentsOf(traversal_root, this);
+ for (const auto& descendant : descendants) {
+ LayoutRect rect = descendant.RectInContainerBox().ToLayoutRect();
+ rect.MoveBy(root_offset);
+ context(rect);
+ }
+ } else {
+ DCHECK(!EnclosingNGBlockFlow());
+ GenerateCulledLineBoxRects(context, this);
+ }
if (context.Intersected()) {
UpdateHitTestResult(result, adjusted_location.Point());
@@ -988,15 +989,12 @@ bool LayoutInline::HitTestCulledInline(
PositionWithAffinity LayoutInline::PositionForPoint(
const LayoutPoint& point) const {
- if (const LayoutBlockFlow* ng_block_flow = EnclosingNGBlockFlow())
- return ng_block_flow->PositionForPoint(point);
-
- DCHECK(CanUseInlineBox(*this));
-
// FIXME: Does not deal with relative positioned inlines (should it?)
// If there are continuations, test them first because our containing block
// will not check them.
+ // TODO(layout-dev): Handle continuation with NG structures when NG has its
+ // own tree building.
LayoutBoxModelObject* continuation = Continuation();
while (continuation) {
if (continuation->IsInline() || continuation->SlowFirstChild())
@@ -1004,6 +1002,11 @@ PositionWithAffinity LayoutInline::PositionForPoint(
continuation = ToLayoutBlockFlow(continuation)->InlineElementContinuation();
}
+ if (const LayoutBlockFlow* ng_block_flow = EnclosingNGBlockFlow())
+ return ng_block_flow->PositionForPoint(point);
+
+ DCHECK(CanUseInlineBox(*this));
+
if (FirstLineBoxIncludingCulling()) {
// This inline actually has a line box. We must have clicked in the
// border/padding of one of these boxes. We
@@ -1177,8 +1180,7 @@ LayoutRect LayoutInline::LinesVisualOverflowBoundingBox() const {
auto children =
NGInlineFragmentTraversal::SelfFragmentsOf(*box_fragment, this);
for (const auto& child : children) {
- NGPhysicalOffsetRect child_rect =
- child.fragment->VisualRectWithContents();
+ NGPhysicalOffsetRect child_rect = child.fragment->InkOverflow();
child_rect.offset += child.offset_to_container_box;
result.Unite(child_rect);
}
@@ -1361,7 +1363,7 @@ LayoutSize LayoutInline::OffsetFromContainerInternal(
PaintLayerType LayoutInline::LayerTypeRequired() const {
return IsInFlowPositioned() || CreatesGroup() ||
Style()->ShouldCompositeForCurrentAnimations() ||
- Style()->ContainsPaint()
+ ShouldApplyPaintContainment()
? kNormalPaintLayer
: kNoPaintLayer;
}
@@ -1378,7 +1380,7 @@ void LayoutInline::ChildBecameNonInline(LayoutObject* child) {
}
void LayoutInline::UpdateHitTestResult(HitTestResult& result,
- const LayoutPoint& point) {
+ const LayoutPoint& point) const {
if (result.InnerNode())
return;
@@ -1649,6 +1651,10 @@ void LayoutInline::InvalidateDisplayItemClients(
if (RuntimeEnabledFeatures::LayoutNGEnabled()) {
auto fragments = NGPaintFragment::InlineFragmentsFor(this);
if (fragments.IsInLayoutNGInlineFormattingContext()) {
+ if (Container()->IsLayoutNGMixin() && StyleRef().HasOutline()) {
+ Container()->InvalidateDisplayItemClients(
+ PaintInvalidationReason::kOutline);
+ }
for (NGPaintFragment* fragment : fragments) {
paint_invalidator.InvalidateDisplayItemClient(*fragment,
invalidation_reason);
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 00c7f33a17f..c9ebb0bdcf4 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_inline.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_inline.h
@@ -34,6 +34,7 @@
namespace blink {
class LayoutBlockFlow;
+class NGPaintFragment;
// LayoutInline is the LayoutObject associated with display: inline.
// This is called an "inline box" in CSS 2.1.
@@ -137,6 +138,10 @@ class CORE_EXPORT LayoutInline : public LayoutBoxModelObject {
return ToElement(LayoutBoxModelObject::GetNode());
}
+ // True if this is an anonymous inline box for ::first-line that wraps the
+ // whole inline formatting context.
+ bool IsFirstLineAnonymous() const;
+
LayoutUnit MarginLeft() const final;
LayoutUnit MarginRight() const final;
LayoutUnit MarginTop() const final;
@@ -201,9 +206,15 @@ class CORE_EXPORT LayoutInline : public LayoutBoxModelObject {
int,
LayoutUnit* extra_width_to_end_of_line) const final;
+ // When this LayoutInline doesn't generate line boxes of its own, regenerate
+ // the rects of the line boxes and hit test the rects.
+ // In LayoutNG, |parent_fragment| is non-null, and limits the regenerated
+ // rects to be from descendant fragments of |parent_fragment|.
+ // In legacy, |parent_fragment| is always null, and all rects are regenerated.
bool HitTestCulledInline(HitTestResult&,
const HitTestLocation& location_in_container,
- const LayoutPoint& accumulated_offset);
+ const LayoutPoint& accumulated_offset,
+ const NGPaintFragment* parent_fragment = nullptr);
LayoutPoint FirstLineBoxTopLeft() const;
@@ -275,7 +286,7 @@ class CORE_EXPORT LayoutInline : public LayoutBoxModelObject {
void UpdateLayout() final { NOTREACHED(); } // Do nothing for layout()
- void Paint(const PaintInfo&, const LayoutPoint&) const final;
+ void Paint(const PaintInfo&) const final;
bool NodeAtPoint(HitTestResult&,
const HitTestLocation& location_in_container,
@@ -326,7 +337,7 @@ class CORE_EXPORT LayoutInline : public LayoutBoxModelObject {
void ChildBecameNonInline(LayoutObject* child) final;
- void UpdateHitTestResult(HitTestResult&, const LayoutPoint&) final;
+ void UpdateHitTestResult(HitTestResult&, const LayoutPoint&) const final;
void ImageChanged(WrappedImagePtr,
CanDeferInvalidation,
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 e71516b8509..ea46a2b0282 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
@@ -107,13 +107,14 @@ TEST_F(LayoutInlineTest, RegionHitTest) {
HitTestRequest hit_request(HitTestRequest::kTouchEvent |
HitTestRequest::kListBased);
- LayoutPoint hit_location(2, 5);
- LayoutRectOutsets padding(2, 1, 2, 1);
- HitTestResult hit_result(hit_request, hit_location, padding);
+
+ LayoutRect hit_rect(1, 3, 2, 4);
+ HitTestLocation location(hit_rect);
+ HitTestResult hit_result(hit_request, location);
LayoutPoint hit_offset;
- bool hit_outcome = lots_of_boxes->HitTestCulledInline(
- hit_result, hit_result.GetHitTestLocation(), hit_offset);
+ bool hit_outcome =
+ lots_of_boxes->HitTestCulledInline(hit_result, location, hit_offset);
// Assert checks that we both hit something and that the area covered
// by "something" totally contains the hit region.
EXPECT_TRUE(hit_outcome);
@@ -131,6 +132,7 @@ TEST_P(ParameterizedLayoutInlineTest, RelativePositionedHitTest) {
HitTestRequest::kActive);
const LayoutPoint container_offset(8, 8);
const LayoutPoint hit_location(18, 15);
+ HitTestLocation location(hit_location);
Element* div = GetDocument().QuerySelector("div");
Element* span = GetDocument().QuerySelector("span");
@@ -139,9 +141,9 @@ TEST_P(ParameterizedLayoutInlineTest, RelativePositionedHitTest) {
// Shouldn't hit anything in SPAN as it's in another paint layer
{
LayoutObject* layout_div = div->GetLayoutObject();
- HitTestResult hit_result(hit_request, hit_location);
- bool hit_outcome = layout_div->HitTestAllPhases(hit_result, hit_location,
- container_offset);
+ HitTestResult hit_result(hit_request, location);
+ bool hit_outcome =
+ layout_div->HitTestAllPhases(hit_result, location, container_offset);
EXPECT_TRUE(hit_outcome);
EXPECT_EQ(div, hit_result.InnerNode());
}
@@ -150,17 +152,17 @@ TEST_P(ParameterizedLayoutInlineTest, RelativePositionedHitTest) {
// the SPAN itself.
{
LayoutObject* layout_span = span->GetLayoutObject();
- HitTestResult hit_result(hit_request, hit_location);
- bool hit_outcome = layout_span->HitTestAllPhases(hit_result, hit_location,
- container_offset);
+ HitTestResult hit_result(hit_request, location);
+ bool hit_outcome =
+ layout_span->HitTestAllPhases(hit_result, location, container_offset);
EXPECT_TRUE(hit_outcome);
EXPECT_EQ(text, hit_result.InnerNode());
}
// Hit test from LayoutView to verify that everything works together.
{
- HitTestResult hit_result(hit_request, hit_location);
- bool hit_outcome = GetLayoutView().HitTest(hit_result);
+ HitTestResult hit_result(hit_request, location);
+ bool hit_outcome = GetLayoutView().HitTest(location, hit_result);
EXPECT_TRUE(hit_outcome);
EXPECT_EQ(text, hit_result.InnerNode());
}
@@ -186,18 +188,19 @@ TEST_P(ParameterizedLayoutInlineTest, MultilineRelativePositionedHitTest) {
// Hit test first line
{
LayoutPoint hit_location(13, 13);
+ HitTestLocation location(hit_location);
Node* target = GetElementById("span")->firstChild();
- HitTestResult hit_result(hit_request, hit_location);
- bool hit_outcome = layout_span->HitTestAllPhases(hit_result, hit_location,
- container_offset);
+ HitTestResult hit_result(hit_request, location);
+ bool hit_outcome =
+ layout_span->HitTestAllPhases(hit_result, location, container_offset);
EXPECT_TRUE(hit_outcome);
EXPECT_EQ(target, hit_result.InnerNode());
// Initiate a hit test from LayoutView to verify the "natural" process.
- HitTestResult layout_view_hit_result(hit_request, hit_location);
+ HitTestResult layout_view_hit_result(hit_request, location);
bool layout_view_hit_outcome =
- GetLayoutView().HitTest(layout_view_hit_result);
+ GetLayoutView().HitTest(location, layout_view_hit_result);
EXPECT_TRUE(layout_view_hit_outcome);
EXPECT_EQ(target, layout_view_hit_result.InnerNode());
}
@@ -205,18 +208,19 @@ TEST_P(ParameterizedLayoutInlineTest, MultilineRelativePositionedHitTest) {
// Hit test second line
{
LayoutPoint hit_location(13, 23);
+ HitTestLocation location(hit_location);
Node* target = GetElementById("line2")->firstChild();
- HitTestResult hit_result(hit_request, hit_location);
- bool hit_outcome = layout_span->HitTestAllPhases(hit_result, hit_location,
- container_offset);
+ HitTestResult hit_result(hit_request, location);
+ bool hit_outcome =
+ layout_span->HitTestAllPhases(hit_result, location, container_offset);
EXPECT_TRUE(hit_outcome);
EXPECT_EQ(target, hit_result.InnerNode());
// Initiate a hit test from LayoutView to verify the "natural" process.
- HitTestResult layout_view_hit_result(hit_request, hit_location);
+ HitTestResult layout_view_hit_result(hit_request, location);
bool layout_view_hit_outcome =
- GetLayoutView().HitTest(layout_view_hit_result);
+ GetLayoutView().HitTest(location, layout_view_hit_result);
EXPECT_TRUE(layout_view_hit_outcome);
EXPECT_EQ(target, layout_view_hit_result.InnerNode());
}
@@ -224,18 +228,19 @@ TEST_P(ParameterizedLayoutInlineTest, MultilineRelativePositionedHitTest) {
// Hit test image in third line
{
LayoutPoint hit_location(13, 33);
+ HitTestLocation location(hit_location);
Node* target = GetDocument().QuerySelector("img");
- HitTestResult hit_result(hit_request, hit_location);
- bool hit_outcome = layout_span->HitTestAllPhases(hit_result, hit_location,
- container_offset);
+ HitTestResult hit_result(hit_request, location);
+ bool hit_outcome =
+ layout_span->HitTestAllPhases(hit_result, location, container_offset);
EXPECT_TRUE(hit_outcome);
EXPECT_EQ(target, hit_result.InnerNode());
// Initiate a hit test from LayoutView to verify the "natural" process.
- HitTestResult layout_view_hit_result(hit_request, hit_location);
+ HitTestResult layout_view_hit_result(hit_request, location);
bool layout_view_hit_outcome =
- GetLayoutView().HitTest(layout_view_hit_result);
+ GetLayoutView().HitTest(location, layout_view_hit_result);
EXPECT_TRUE(layout_view_hit_outcome);
EXPECT_EQ(target, layout_view_hit_result.InnerNode());
}
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_list_box.cc b/chromium/third_party/blink/renderer/core/layout/layout_list_box.cc
index e654657b0e9..2e51a69f048 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_list_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_list_box.cc
@@ -37,6 +37,7 @@
#include "third_party/blink/renderer/core/html/forms/html_select_element.h"
#include "third_party/blink/renderer/core/html/html_div_element.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/scroll/scroll_alignment.h"
#include "third_party/blink/renderer/platform/scroll/scroll_types.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_list_item.cc b/chromium/third_party/blink/renderer/core/layout/layout_list_item.cc
index 9be563b0552..4c9de99ea96 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_list_item.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_list_item.cc
@@ -213,7 +213,7 @@ bool LayoutListItem::PrepareForBlockDirectionAlign(
// Create marker_container, set its height to 0px, and add it to li.
if (!marker_parent) {
LayoutObject* before_child = FirstNonMarkerChild(this);
- if (!marker_->IsInside() && before_child && before_child->IsLayoutBlock()) {
+ if (!marker_->IsInside() && before_child && !before_child->IsInline()) {
// Create marker_container and set its LogicalHeight to 0px.
LayoutBlock* marker_container = CreateAnonymousBlock();
if (line_box_parent)
@@ -297,19 +297,26 @@ void LayoutListItem::AddOverflowFromChildren() {
// Align marker_inline_box in block direction according to line_box_root's
// baseline.
void LayoutListItem::AlignMarkerInBlockDirection() {
+ // Specify wether need to restore to the original baseline which is the
+ // baseline of marker parent. Because we might adjust the position at the last
+ // layout pass. So if there's no line box in line_box_parent make sure it
+ // back to its original position.
+ bool back_to_original_baseline = false;
LayoutObject* line_box_parent = GetParentOfFirstLineBox(this, marker_);
- if (!line_box_parent || !line_box_parent->IsBox())
- return;
-
- LayoutBox* line_box_parent_block = ToLayoutBox(line_box_parent);
- // Don't align marker if line_box_parent has a different writing-mode.
- // Just let marker positioned at the left-top of line_box_parent.
- if (line_box_parent_block->IsWritingModeRoot())
- return;
+ LayoutBox* line_box_parent_block = nullptr;
+ if (!line_box_parent || !line_box_parent->IsBox()) {
+ back_to_original_baseline = true;
+ } else {
+ line_box_parent_block = ToLayoutBox(line_box_parent);
+ // Don't align marker if line_box_parent has a different writing-mode.
+ // Just let marker positioned at the left-top of line_box_parent.
+ if (line_box_parent_block->IsWritingModeRoot())
+ back_to_original_baseline = true;
+ }
InlineBox* marker_inline_box = marker_->InlineBoxWrapper();
RootInlineBox& marker_root = marker_inline_box->Root();
- if (line_box_parent_block->IsLayoutBlockFlow()) {
+ if (line_box_parent_block && line_box_parent_block->IsLayoutBlockFlow()) {
// If marker_ and line_box_parent_block share a same RootInlineBox, no need
// to align marker.
if (ToLayoutBlockFlow(line_box_parent_block)->FirstRootBox() ==
@@ -317,7 +324,15 @@ void LayoutListItem::AlignMarkerInBlockDirection() {
return;
}
- LayoutUnit offset = line_box_parent_block->FirstLineBoxBaseline();
+ LayoutUnit offset;
+ if (!back_to_original_baseline)
+ offset = line_box_parent_block->FirstLineBoxBaseline();
+
+ if (back_to_original_baseline || offset == -1) {
+ line_box_parent_block = marker_->ContainingBlock();
+ offset = line_box_parent_block->FirstLineBoxBaseline();
+ }
+
if (offset != -1) {
for (LayoutBox* o = line_box_parent_block; o != this; o = o->ParentBox())
offset += o->LogicalTop();
@@ -345,7 +360,8 @@ void LayoutListItem::AlignMarkerInBlockDirection() {
offset -= o->LogicalTop();
}
- marker_inline_box->MoveInBlockDirection(offset);
+ if (offset)
+ marker_inline_box->MoveInBlockDirection(offset);
}
}
@@ -492,9 +508,8 @@ void LayoutListItem::PositionListMarker() {
}
}
-void LayoutListItem::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
- ListItemPainter(*this).Paint(paint_info, paint_offset);
+void LayoutListItem::Paint(const PaintInfo& paint_info) const {
+ ListItemPainter(*this).Paint(paint_info);
}
const String& LayoutListItem::MarkerText() const {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_list_item.h b/chromium/third_party/blink/renderer/core/layout/layout_list_item.h
index 0d15897a380..a1bd9f98633 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_list_item.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_list_item.h
@@ -58,7 +58,7 @@ class LayoutListItem final : public LayoutBlockFlow {
void InsertedIntoTree() override;
void WillBeRemovedFromTree() override;
- void Paint(const PaintInfo&, const LayoutPoint&) const override;
+ void Paint(const PaintInfo&) const override;
void SubtreeDidChange() final;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_list_marker.cc b/chromium/third_party/blink/renderer/core/layout/layout_list_marker.cc
index 37451f7e409..5e34e8e29be 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_list_marker.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_list_marker.cc
@@ -114,9 +114,8 @@ bool LayoutListMarker::IsImage() const {
return image_ && !image_->ErrorOccurred();
}
-void LayoutListMarker::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
- ListMarkerPainter(*this).Paint(paint_info, paint_offset);
+void LayoutListMarker::Paint(const PaintInfo& paint_info) const {
+ ListMarkerPainter(*this).Paint(paint_info);
}
void LayoutListMarker::UpdateLayout() {
@@ -242,19 +241,12 @@ void LayoutListMarker::ComputePreferredLogicalWidths() {
return;
}
- const Font& font = Style()->GetFont();
- const SimpleFontData* font_data = font.PrimaryFont();
- DCHECK(font_data);
- if (!font_data)
- return;
-
LayoutUnit logical_width;
switch (GetListStyleCategory()) {
case ListStyleCategory::kNone:
break;
case ListStyleCategory::kSymbol:
- logical_width = LayoutUnit(
- (font_data->GetFontMetrics().Ascent() * 2 / 3 + 1) / 2 + 2);
+ logical_width = WidthOfSymbol(StyleRef());
break;
case ListStyleCategory::kLanguage:
logical_width = GetWidthOfTextWithSuffix();
@@ -269,6 +261,15 @@ void LayoutListMarker::ComputePreferredLogicalWidths() {
UpdateMargins();
}
+LayoutUnit LayoutListMarker::WidthOfSymbol(const ComputedStyle& style) {
+ const Font& font = style.GetFont();
+ const SimpleFontData* font_data = font.PrimaryFont();
+ DCHECK(font_data);
+ if (!font_data)
+ return LayoutUnit();
+ return LayoutUnit((font_data->GetFontMetrics().Ascent() * 2 / 3 + 1) / 2 + 2);
+}
+
void LayoutListMarker::UpdateMargins() {
LayoutUnit margin_start;
LayoutUnit margin_end;
@@ -469,28 +470,21 @@ LayoutRect LayoutListMarker::GetRelativeMarkerRect() const {
return LayoutRect(LayoutPoint(), ImageBulletSize());
LayoutRect relative_rect;
- const SimpleFontData* font_data = Style()->GetFont().PrimaryFont();
- DCHECK(font_data);
- if (!font_data)
- return relative_rect;
-
switch (GetListStyleCategory()) {
case ListStyleCategory::kNone:
return LayoutRect();
- case ListStyleCategory::kSymbol: {
- // TODO(wkorman): Review and clean up/document the calculations below.
- // http://crbug.com/543193
- const FontMetrics& font_metrics = font_data->GetFontMetrics();
- int ascent = font_metrics.Ascent();
- int bullet_width = (ascent * 2 / 3 + 1) / 2;
- relative_rect = LayoutRect(1, 3 * (ascent - ascent * 2 / 3) / 2,
- bullet_width, bullet_width);
- } break;
- case ListStyleCategory::kLanguage:
+ case ListStyleCategory::kSymbol:
+ return RelativeSymbolMarkerRect(StyleRef(), Size().Width());
+ case ListStyleCategory::kLanguage: {
+ const SimpleFontData* font_data = Style()->GetFont().PrimaryFont();
+ DCHECK(font_data);
+ if (!font_data)
+ return relative_rect;
relative_rect =
LayoutRect(LayoutUnit(), LayoutUnit(), GetWidthOfTextWithSuffix(),
LayoutUnit(font_data->GetFontMetrics().Height()));
break;
+ }
}
if (!Style()->IsHorizontalWritingMode()) {
@@ -498,7 +492,29 @@ LayoutRect LayoutListMarker::GetRelativeMarkerRect() const {
relative_rect.SetX(Size().Width() - relative_rect.X() -
relative_rect.Width());
}
+ return relative_rect;
+}
+LayoutRect LayoutListMarker::RelativeSymbolMarkerRect(
+ const ComputedStyle& style,
+ LayoutUnit width) {
+ LayoutRect relative_rect;
+ const SimpleFontData* font_data = style.GetFont().PrimaryFont();
+ DCHECK(font_data);
+ if (!font_data)
+ return LayoutRect();
+
+ // TODO(wkorman): Review and clean up/document the calculations below.
+ // http://crbug.com/543193
+ const FontMetrics& font_metrics = font_data->GetFontMetrics();
+ int ascent = font_metrics.Ascent();
+ int bullet_width = (ascent * 2 / 3 + 1) / 2;
+ relative_rect = LayoutRect(1, 3 * (ascent - ascent * 2 / 3) / 2, bullet_width,
+ bullet_width);
+ if (!style.IsHorizontalWritingMode()) {
+ relative_rect = relative_rect.TransposedRect();
+ relative_rect.SetX(width - relative_rect.X() - relative_rect.Width());
+ }
return relative_rect;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_list_marker.h b/chromium/third_party/blink/renderer/core/layout/layout_list_marker.h
index 0d53ea51e60..d5c81ada32f 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_list_marker.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_list_marker.h
@@ -67,6 +67,9 @@ class LayoutListMarker final : public LayoutBox {
LayoutUnit marker_inline_size);
LayoutRect GetRelativeMarkerRect() const;
+ static LayoutRect RelativeSymbolMarkerRect(const ComputedStyle&, LayoutUnit);
+ static LayoutUnit WidthOfSymbol(const ComputedStyle&);
+
bool IsImage() const override;
const StyleImage* GetImage() const { return image_.Get(); }
const LayoutListItem* ListItem() const { return list_item_; }
@@ -90,7 +93,7 @@ class LayoutListMarker final : public LayoutBox {
return type == kLayoutObjectListMarker || LayoutBox::IsOfType(type);
}
- void Paint(const PaintInfo&, const LayoutPoint&) const override;
+ void Paint(const PaintInfo&) const override;
void UpdateLayout() override;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_media.cc b/chromium/third_party/blink/renderer/core/layout/layout_media.cc
index 70c0aee3661..bd60a3f2faf 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_media.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_media.cc
@@ -128,7 +128,8 @@ bool LayoutMedia::IsChildAllowed(LayoutObject* child,
return false;
}
-void LayoutMedia::PaintReplaced(const PaintInfo&, const LayoutPoint&) const {}
+void LayoutMedia::PaintReplaced(const PaintInfo&,
+ const LayoutPoint& paint_offset) const {}
LayoutUnit LayoutMedia::ComputePanelWidth(const LayoutRect& media_rect) const {
// TODO(mlamouri): we don't know if the main frame has an horizontal scrollbar
@@ -145,23 +146,26 @@ LayoutUnit LayoutMedia::ComputePanelWidth(const LayoutRect& media_rect) const {
Page* page = GetDocument().GetPage();
LocalFrame* main_frame = page->DeprecatedLocalMainFrame();
LocalFrameView* page_view = main_frame ? main_frame->View() : nullptr;
- if (!main_frame || !page_view)
+ if (!main_frame || !page_view || !page_view->GetLayoutView())
return media_rect.Width();
// If the main frame can have a scrollbar, we'll never be cut off.
// TODO(crbug.com/771379): Once we no longer assume that the video is in the
// main frame for the visibility calculation below, we will only care about
// the video's frame's scrollbar check below.
- if (page_view->EffectiveHorizontalScrollbarMode() != kScrollbarAlwaysOff)
+ ScrollbarMode h_mode, v_mode;
+ page_view->GetLayoutView()->CalculateScrollbarModes(h_mode, v_mode);
+ if (h_mode != kScrollbarAlwaysOff)
return media_rect.Width();
// If the video's frame (can be different from main frame if video is in an
// iframe) can have a scrollbar, we'll never be cut off.
LocalFrame* media_frame = GetFrame();
LocalFrameView* media_page_view = media_frame ? media_frame->View() : nullptr;
- if (media_page_view && media_page_view->EffectiveHorizontalScrollbarMode() !=
- kScrollbarAlwaysOff) {
- return media_rect.Width();
+ if (media_page_view && media_page_view->GetLayoutView()) {
+ media_page_view->GetLayoutView()->CalculateScrollbarModes(h_mode, v_mode);
+ if (h_mode != kScrollbarAlwaysOff)
+ return media_rect.Width();
}
// TODO(crbug.com/771379): This code assumes the video is in the main frame.
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_media.h b/chromium/third_party/blink/renderer/core/layout/layout_media.h
index f2a37a50b43..ac235d2a763 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_media.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_media.h
@@ -79,7 +79,8 @@ class LayoutMedia : public LayoutImage {
bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const final;
bool IsImage() const final { return false; }
- void PaintReplaced(const PaintInfo&, const LayoutPoint&) const override;
+ void PaintReplaced(const PaintInfo&,
+ const LayoutPoint& paint_offset) const override;
bool BackgroundShouldAlwaysBeClipped() const final { return false; }
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_menu_list.cc b/chromium/third_party/blink/renderer/core/layout/layout_menu_list.cc
index 22186050829..5a05b42ab92 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_menu_list.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_menu_list.cc
@@ -27,7 +27,7 @@
#include "third_party/blink/renderer/core/layout/layout_menu_list.h"
#include <math.h>
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html/forms/html_option_element.h"
@@ -57,7 +57,7 @@ LayoutMenuList::~LayoutMenuList() = default;
// insertion point to prevent children from rendering.
bool LayoutMenuList::IsChildAllowed(LayoutObject* object,
const ComputedStyle&) const {
- return object->IsAnonymous() && !object->IsLayoutFullScreen();
+ return object->IsAnonymous();
}
scoped_refptr<ComputedStyle> LayoutMenuList::CreateInnerStyle() {
@@ -88,8 +88,8 @@ void LayoutMenuList::CreateInnerBlock() {
// Create an anonymous block.
DCHECK(!FirstChild());
- inner_block_ = LayoutBlockFlow::CreateAnonymous(&GetDocument());
- inner_block_->SetStyle(CreateInnerStyle());
+ inner_block_ =
+ LayoutBlockFlow::CreateAnonymous(&GetDocument(), CreateInnerStyle());
button_text_ = LayoutText::CreateEmptyAnonymous(GetDocument());
// We need to set the text explicitly though it was specified in the
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc b/chromium/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc
index af7df35da9c..087c84fcb6d 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc
@@ -143,10 +143,9 @@ void LayoutMultiColumnSpannerPlaceholder::ComputeLogicalHeight(
}
void LayoutMultiColumnSpannerPlaceholder::Paint(
- const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
+ const PaintInfo& paint_info) const {
if (!layout_object_in_flow_thread_->HasSelfPaintingLayer())
- layout_object_in_flow_thread_->Paint(paint_info, paint_offset);
+ layout_object_in_flow_thread_->Paint(paint_info);
}
bool LayoutMultiColumnSpannerPlaceholder::NodeAtPoint(
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h b/chromium/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h
index 7a24bd45aae..41fcd594689 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h
@@ -59,7 +59,7 @@ class LayoutMultiColumnSpannerPlaceholder final : public LayoutBox {
void ComputeLogicalHeight(LayoutUnit logical_height,
LayoutUnit logical_top,
LogicalExtentComputedValues&) const override;
- void Paint(const PaintInfo&, const LayoutPoint& paint_offset) const override;
+ void Paint(const PaintInfo&) const override;
bool NodeAtPoint(HitTestResult&,
const HitTestLocation& location_in_container,
const LayoutPoint& accumulated_offset,
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 21754a49bda..1742a37f570 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_object.cc
@@ -32,11 +32,11 @@
#include <memory>
#include "third_party/blink/public/platform/web_scroll_into_view_params.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/animation/element_animations.h"
#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/dom/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/first_letter_pseudo_element.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
@@ -70,6 +70,7 @@
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/layout_list_item.h"
#include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h"
+#include "third_party/blink/renderer/core/layout/layout_object_factory.h"
#include "third_party/blink/renderer/core/layout/layout_scrollbar_part.h"
#include "third_party/blink/renderer/core/layout/layout_table_caption.h"
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
@@ -79,10 +80,6 @@
#include "third_party/blink/renderer/core/layout/layout_theme.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
-#include "third_party/blink/renderer/core/layout/ng/layout_ng_flexible_box.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/list/layout_ng_list_item.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
#include "third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h"
@@ -91,8 +88,10 @@
#include "third_party/blink/renderer/core/layout/svg/svg_resources_cache.h"
#include "third_party/blink/renderer/core/page/autoscroll_controller.h"
#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/object_paint_invalidator.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/style/content_data.h"
#include "third_party/blink/renderer/core/style/cursor_data.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
@@ -102,6 +101,7 @@
#include "third_party/blink/renderer/platform/instance_counters.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/scroll/smooth_scroll_sequencer.h"
#include "third_party/blink/renderer/platform/transforms/transform_state.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -114,13 +114,6 @@ namespace blink {
namespace {
-static bool g_modify_layout_tree_structure_any_state = false;
-
-inline bool ShouldUseNewLayout(const ComputedStyle& style) {
- return RuntimeEnabledFeatures::LayoutNGEnabled() &&
- !style.ForceLegacyLayout();
-}
-
template <typename Predicate>
LayoutObject* FindAncestorByPredicate(const LayoutObject* descendant,
LayoutObject::AncestorSkipInfo* skip_info,
@@ -205,7 +198,7 @@ void* LayoutObject::operator new(size_t sz) {
void LayoutObject::operator delete(void* ptr) {
DCHECK(IsMainThread());
- WTF::PartitionFree(ptr);
+ base::PartitionFree(ptr);
}
LayoutObject* LayoutObject::CreateObject(Element* element,
@@ -245,13 +238,9 @@ LayoutObject* LayoutObject::CreateObject(Element* element,
case EDisplay::kBlock:
case EDisplay::kFlowRoot:
case EDisplay::kInlineBlock:
- if (ShouldUseNewLayout(style))
- return new LayoutNGBlockFlow(element);
- return new LayoutBlockFlow(element);
+ return LayoutObjectFactory::CreateBlockFlow(*element, style);
case EDisplay::kListItem:
- if (ShouldUseNewLayout(style))
- return new LayoutNGListItem(element);
- return new LayoutListItem(element);
+ return LayoutObjectFactory::CreateListItem(*element, style);
case EDisplay::kTable:
case EDisplay::kInlineTable:
return new LayoutTable(element);
@@ -265,23 +254,15 @@ LayoutObject* LayoutObject::CreateObject(Element* element,
case EDisplay::kTableColumn:
return new LayoutTableCol(element);
case EDisplay::kTableCell:
- if (ShouldUseNewLayout(style))
- return new LayoutNGTableCell(element);
- return new LayoutTableCell(element);
+ return LayoutObjectFactory::CreateTableCell(*element, style);
case EDisplay::kTableCaption:
- if (ShouldUseNewLayout(style))
- return new LayoutNGTableCaption(element);
- return new LayoutTableCaption(element);
+ return LayoutObjectFactory::CreateTableCaption(*element, style);
case EDisplay::kWebkitBox:
case EDisplay::kWebkitInlineBox:
return new LayoutDeprecatedFlexibleBox(*element);
case EDisplay::kFlex:
case EDisplay::kInlineFlex:
- if (RuntimeEnabledFeatures::LayoutNGFlexBoxEnabled() &&
- ShouldUseNewLayout(style)) {
- return new LayoutNGFlexibleBox(element);
- }
- return new LayoutFlexibleBox(element);
+ return LayoutObjectFactory::CreateFlexibleBox(*element, style);
case EDisplay::kGrid:
case EDisplay::kInlineGrid:
return new LayoutGrid(element);
@@ -492,7 +473,7 @@ bool LayoutObject::HasClipRelatedProperty() const {
// CSS clip-path/mask/filter induces a stacking context and applies inherited
// clip to that stacking context, while resetting clip for descendants. This
// special behavior is already handled elsewhere.
- if (HasClip() || HasOverflowClip() || Style()->ContainsPaint())
+ if (HasClip() || HasOverflowClip() || ShouldApplyPaintContainment())
return true;
if (IsBox() && ToLayoutBox(this)->HasControlClip())
return true;
@@ -553,13 +534,6 @@ LayoutObject* LayoutObject::PreviousInPreOrder(
return PreviousInPreOrder();
}
-LayoutObject* LayoutObject::ChildAt(unsigned index) const {
- LayoutObject* child = SlowFirstChild();
- for (unsigned i = 0; child && i < index; i++)
- child = child->NextSibling();
- return child;
-}
-
LayoutObject* LayoutObject::LastLeafChild() const {
LayoutObject* r = SlowLastChild();
while (r) {
@@ -747,18 +721,6 @@ LayoutBox* LayoutObject::EnclosingBox() const {
return nullptr;
}
-LayoutBoxModelObject* LayoutObject::EnclosingBoxModelObject() const {
- LayoutObject* curr = const_cast<LayoutObject*>(this);
- while (curr) {
- if (curr->IsBoxModelObject())
- return ToLayoutBoxModelObject(curr);
- curr = curr->Parent();
- }
-
- NOTREACHED();
- return nullptr;
-}
-
LayoutBlockFlow* LayoutObject::EnclosingNGBlockFlow() const {
if (!RuntimeEnabledFeatures::LayoutNGEnabled())
return nullptr;
@@ -829,7 +791,8 @@ static inline bool ObjectIsRelayoutBoundary(const LayoutObject* object) {
return false;
const ComputedStyle* style = object->Style();
- if (style->ContainsLayout() && style->ContainsSize())
+ if (object->ShouldApplyLayoutContainment() &&
+ object->ShouldApplySizeContainment())
return true;
if (!object->HasOverflowClip())
@@ -984,12 +947,27 @@ void LayoutObject::ClearPreferredLogicalWidthsDirty() {
bitfields_.SetPreferredLogicalWidthsDirty(false);
}
+static inline bool NGKeepInvalidatingBeyond(LayoutObject* o) {
+ // Because LayoutNG does not work on individual inline objects, we can't
+ // use a dirty width on an inline as a signal that it is safe to stop --
+ // inlines never get marked as clean. Instead, we need to keep going to the
+ // next block container.
+ // Atomic inlines do not have this problem as they are treated like blocks
+ // in this context.
+ if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+ return false;
+ if (o->IsLayoutInline() || o->IsText())
+ return true;
+ return false;
+}
+
inline void LayoutObject::InvalidateContainerPreferredLogicalWidths() {
// In order to avoid pathological behavior when inlines are deeply nested, we
// do include them in the chain that we mark dirty (even though they're kind
// of irrelevant).
LayoutObject* o = IsTableCell() ? ContainingBlock() : Container();
- while (o && !o->PreferredLogicalWidthsDirty()) {
+ while (o &&
+ (!o->PreferredLogicalWidthsDirty() || NGKeepInvalidatingBeyond(o))) {
// Don't invalidate the outermost object of an unrooted subtree. That object
// will be invalidated when the subtree is added to the document.
LayoutObject* container =
@@ -1010,7 +988,7 @@ LayoutObject* LayoutObject::ContainerForAbsolutePosition(
AncestorSkipInfo* skip_info) const {
return FindAncestorByPredicate(this, skip_info, [](LayoutObject* candidate) {
if (!candidate->CanContainAbsolutePositionObjects() &&
- candidate->StyleRef().ContainsLayout()) {
+ candidate->ShouldApplyLayoutContainment()) {
UseCounter::Count(candidate->GetDocument(),
WebFeature::kCSSContainLayoutPositionedDescendants);
}
@@ -1023,7 +1001,7 @@ LayoutObject* LayoutObject::ContainerForFixedPosition(
DCHECK(!IsText());
return FindAncestorByPredicate(this, skip_info, [](LayoutObject* candidate) {
if (!candidate->CanContainFixedPositionObjects() &&
- candidate->StyleRef().ContainsLayout()) {
+ candidate->ShouldApplyLayoutContainment()) {
UseCounter::Count(candidate->GetDocument(),
WebFeature::kCSSContainLayoutPositionedDescendants);
}
@@ -1052,7 +1030,7 @@ const LayoutBlock* LayoutObject::InclusiveContainingBlock() const {
LayoutBlock* LayoutObject::ContainingBlock(AncestorSkipInfo* skip_info) const {
LayoutObject* object = Parent();
if (!object && IsLayoutScrollbarPart())
- object = ToLayoutScrollbarPart(this)->ScrollbarStyleSource();
+ object = ToLayoutScrollbarPart(this)->GetScrollableArea()->GetLayoutBox();
if (!IsTextOrSVGChild()) {
if (style_->GetPosition() == EPosition::kFixed)
return ContainingBlockForFixedPosition(skip_info);
@@ -1261,11 +1239,8 @@ bool LayoutObject::GetUpperLeftCorner(ExpandScrollMargin expand,
// document. Scroll to the bottom.
// FIXME: who said anything about scrolling?
if (!runner && GetDocument().View()) {
- point = FloatPoint(0, GetDocument()
- .View()
- ->LayoutViewportScrollableArea()
- ->ContentsSize()
- .Height());
+ point = FloatPoint(
+ 0, GetDocument().View()->LayoutViewport()->ContentsSize().Height());
return true;
}
return false;
@@ -1339,15 +1314,6 @@ bool LayoutObject::GetLowerRightCorner(ExpandScrollMargin expand,
return true;
}
-IntRect LayoutObject::AbsoluteElementBoundingBoxRect() const {
- Vector<LayoutRect> rects;
- const LayoutBoxModelObject& container = EnclosingLayer()->GetLayoutObject();
- AddElementVisualOverflowRects(
- rects, LayoutPoint(LocalToAncestorPoint(FloatPoint(), &container)));
- return container.LocalToAbsoluteQuad(FloatQuad(FloatRect(UnionRect(rects))))
- .EnclosingBoundingBox();
-}
-
FloatRect LayoutObject::AbsoluteBoundingBoxRectForRange(
const EphemeralRange& range) {
if (range.IsNull() || !range.StartPosition().ComputeContainerNode())
@@ -1374,7 +1340,7 @@ IntRect LayoutObject::AbsoluteBoundingBoxRectIncludingDescendants() const {
return result;
}
-void LayoutObject::Paint(const PaintInfo&, const LayoutPoint&) const {}
+void LayoutObject::Paint(const PaintInfo&) const {}
const LayoutBoxModelObject& LayoutObject::ContainerForPaintInvalidation()
const {
@@ -1422,6 +1388,58 @@ const LayoutBoxModelObject* LayoutObject::EnclosingCompositedContainer() const {
return container;
}
+bool LayoutObject::HasDistortingVisualEffects() const {
+ // TODO(szager): Check occlusion information propagated from out-of-process
+ // parent frame.
+ PropertyTreeState paint_properties = EnclosingLayer()
+ ->GetLayoutObject()
+ .FirstFragment()
+ .LocalBorderBoxProperties();
+
+ // No filters, no blends, no opacity < 100%.
+ const EffectPaintPropertyNode* effects = paint_properties.Effect();
+ while (effects && !effects->IsRoot()) {
+ if (!effects->Filter().IsEmpty() ||
+ effects->GetColorFilter() != kColorFilterNone ||
+ effects->BlendMode() != SkBlendMode::kSrcOver ||
+ effects->Opacity() != 1.0) {
+ return true;
+ }
+ effects = effects->Parent();
+ }
+
+ PropertyTreeState root_properties = GetDocument()
+ .GetFrame()
+ ->LocalFrameRoot()
+ .ContentLayoutObject()
+ ->FirstFragment()
+ .LocalBorderBoxProperties();
+
+ // The only allowed transforms are 2D translation and proportional up-scaling.
+ const TransformationMatrix& matrix =
+ GeometryMapper::SourceToDestinationProjection(
+ paint_properties.Transform(), root_properties.Transform());
+ if (!matrix.Is2DProportionalUpscaleAndOr2DTranslation())
+ return true;
+
+ return false;
+}
+
+bool LayoutObject::HasNonZeroEffectiveOpacity() const {
+ PropertyTreeState paint_properties = EnclosingLayer()
+ ->GetLayoutObject()
+ .FirstFragment()
+ .LocalBorderBoxProperties();
+
+ const EffectPaintPropertyNode* effects = paint_properties.Effect();
+ while (effects && !effects->IsRoot()) {
+ if (effects->Opacity() == 0.0)
+ return false;
+ effects = effects->Parent();
+ }
+ return true;
+}
+
String LayoutObject::DecoratedName() const {
StringBuilder name;
name.Append(GetName());
@@ -1503,10 +1521,13 @@ IntSize LayoutObject::ScrollAdjustmentForPaintInvalidation(
}
void LayoutObject::InvalidatePaintRectangle(const LayoutRect& dirty_rect) {
+ DCHECK_NE(GetDocument().Lifecycle().GetState(), DocumentLifecycle::kInPaint);
+
if (dirty_rect.IsEmpty())
return;
- SetPartialInvalidationRect(UnionRect(dirty_rect, PartialInvalidationRect()));
+ fragment_.SetPartialInvalidationLocalRect(
+ UnionRect(dirty_rect, fragment_.PartialInvalidationLocalRect()));
// Not using the WithoutGeometryChange version because we need to map the
// partial invalidated rect to visual rect in backing or the containing
@@ -1520,7 +1541,7 @@ LayoutRect LayoutObject::AbsoluteSelectionRect() const {
MapToVisualRectInAncestorSpace(View(), selection_rect);
if (LocalFrameView* frame_view = GetFrameView())
- selection_rect = frame_view->DocumentToAbsolute(selection_rect);
+ selection_rect = frame_view->DocumentToFrame(selection_rect);
return selection_rect;
}
@@ -1549,13 +1570,24 @@ LayoutRect LayoutObject::VisualRectIncludingCompositedScrolling(
}
void LayoutObject::ClearPreviousVisualRects() {
- fragment_.SetVisualRect(LayoutRect());
- fragment_.SetLocationInBacking(LayoutPoint());
- fragment_.SetSelectionVisualRect(LayoutRect());
+ DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
+
+ for (auto* fragment = &fragment_; fragment;
+ fragment = fragment->NextFragment()) {
+ fragment->SetVisualRect(LayoutRect());
+ fragment->SetSelectionVisualRect(LayoutRect());
+ }
+
+ if (IsInline()) {
+ auto fragments = NGPaintFragment::InlineFragmentsFor(this);
+ if (fragments.IsInLayoutNGInlineFormattingContext()) {
+ for (auto* fragment : fragments) {
+ fragment->SetVisualRect(LayoutRect());
+ fragment->SetSelectionVisualRect(LayoutRect());
+ }
+ }
+ }
- // Ensure check paint invalidation of subtree that would be triggered by
- // location change if we had valid previous location.
- SetMayNeedPaintInvalidationSubtree();
// After clearing ("invalidating") the visual rects, mark this object as
// needing to re-compute them.
SetShouldDoFullPaintInvalidation();
@@ -1578,7 +1610,6 @@ bool LayoutObject::MapToVisualRectInAncestorSpaceInternalFastPath(
VisualRectFlags visual_rect_flags,
bool& intersects) const {
if (!(visual_rect_flags & kUseGeometryMapper) ||
- !RuntimeEnabledFeatures::SlimmingPaintV175Enabled() ||
!FirstFragment().HasLocalBorderBoxProperties() || !ancestor ||
!ancestor->FirstFragment().HasLocalBorderBoxProperties()) {
intersects = true;
@@ -1663,6 +1694,19 @@ bool LayoutObject::MapToVisualRectInAncestorSpaceInternal(
return true;
}
+HitTestResult LayoutObject::HitTestForOcclusion(
+ const LayoutRect& hit_rect) const {
+ LocalFrame* frame = GetDocument().GetFrame();
+ DCHECK(!frame->View()->NeedsLayout());
+ HitTestRequest::HitTestRequestType hit_type =
+ HitTestRequest::kListBased | HitTestRequest::kPenetratingList |
+ HitTestRequest::kIgnorePointerEventsNone | HitTestRequest::kReadOnly |
+ HitTestRequest::kIgnoreClipping;
+ HitTestLocation location(hit_rect);
+ return frame->GetEventHandler().HitTestResultAtLocation(location, hit_type,
+ this, true);
+}
+
void LayoutObject::DirtyLinesFromChangedChild(LayoutObject*, MarkingBehavior) {}
std::ostream& operator<<(std::ostream& out, const LayoutObject& object) {
@@ -1794,50 +1838,6 @@ StyleDifference LayoutObject::AdjustStyleDifference(
diff.SetNeedsFullLayout();
}
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- // If transform changed, and the layer does not paint into its own separate
- // backing, then we need to invalidate paints.
- if (diff.TransformChanged()) {
- // Text nodes share style with their parents but transforms don't apply to
- // them, hence the !isText() check.
- if (!IsText() &&
- (!HasLayer() || !ToLayoutBoxModelObject(this)
- ->Layer()
- ->HasStyleDeterminedDirectCompositingReasons()))
- diff.SetNeedsPaintInvalidationSubtree();
- }
-
- // If opacity or zIndex changed, and the layer does not paint into its own
- // separate backing, then we need to invalidate paints (also
- // ignoring text nodes).
- if (diff.OpacityChanged() || diff.ZIndexChanged()) {
- if (!IsText() &&
- (!HasLayer() || !ToLayoutBoxModelObject(this)
- ->Layer()
- ->HasStyleDeterminedDirectCompositingReasons()))
- diff.SetNeedsPaintInvalidationSubtree();
- }
-
- // If filter changed, and the layer does not paint into its own separate
- // backing or it paints with filters, then we need to invalidate paints.
- if (diff.FilterChanged() && HasLayer()) {
- PaintLayer* layer = ToLayoutBoxModelObject(this)->Layer();
- if (!layer->HasStyleDeterminedDirectCompositingReasons() ||
- layer->PaintsWithFilters())
- diff.SetNeedsPaintInvalidationSubtree();
- }
-
- // If backdrop filter changed, and the layer does not paint into its own
- // separate backing or it paints with filters, then we need to invalidate
- // paints.
- if (diff.BackdropFilterChanged() && HasLayer()) {
- PaintLayer* layer = ToLayoutBoxModelObject(this)->Layer();
- if (!layer->HasStyleDeterminedDirectCompositingReasons() ||
- layer->PaintsWithBackdropFilters())
- diff.SetNeedsPaintInvalidationSubtree();
- }
- }
-
// TODO(wangxianzhu): We may avoid subtree paint invalidation on CSS clip
// change for SPv2.
if (diff.CssClipChanged())
@@ -2074,14 +2074,15 @@ void LayoutObject::SetStyle(scoped_refptr<ComputedStyle> style) {
SetMayNeedPaintInvalidation();
// Text nodes share style with their parents but the paint properties don't
- // apply to them, hence the !isText() check.
- // In SPv175 mode, if property nodes are added or removed as a result of these
- // style changes, PaintPropertyTreeBuilder will call SetNeedsRepaint
- // to cause re-generation of PaintChunks.
+ // apply to them, hence the !isText() check. If property nodes are added or
+ // removed as a result of these style changes, PaintPropertyTreeBuilder will
+ // call SetNeedsRepaint to cause re-generation of PaintChunks.
if (!IsText() && (diff.TransformChanged() || diff.OpacityChanged() ||
diff.ZIndexChanged() || diff.FilterChanged() ||
- diff.BackdropFilterChanged() || diff.CssClipChanged()))
+ diff.BackdropFilterChanged() || diff.CssClipChanged() ||
+ diff.BlendModeChanged())) {
SetNeedsPaintPropertyUpdate();
+ }
}
void LayoutObject::StyleWillChange(StyleDifference diff,
@@ -2097,6 +2098,11 @@ void LayoutObject::StyleWillChange(StyleDifference diff,
cache->ChildrenChanged(Parent());
}
+ if (diff.TransformChanged()) {
+ if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache())
+ cache->LocationChanged(this);
+ }
+
// Keep layer hierarchy visibility bits up to date if visibility changes.
if (visibility_changed) {
// We might not have an enclosing layer yet because we might not be in the
@@ -2163,6 +2169,8 @@ void LayoutObject::StyleWillChange(StyleDifference diff,
registry.DidRemoveEventHandler(*GetNode(),
EventHandlerRegistry::kTouchAction);
}
+ if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled())
+ MarkEffectiveWhitelistedTouchActionChanged();
}
}
@@ -2283,7 +2291,7 @@ void LayoutObject::ApplyPseudoStyleChanges(const ComputedStyle& old_style) {
if (old_style.HasPseudoStyle(kPseudoIdSelection) ||
StyleRef().HasPseudoStyle(kPseudoIdSelection))
- InvalidateSelectionOfSelectedChildren();
+ InvalidateSelectedChildrenOnStyleChange();
}
void LayoutObject::ApplyFirstLineChanges(const ComputedStyle& old_style) {
@@ -2323,7 +2331,10 @@ void LayoutObject::PropagateStyleToAnonymousChildren() {
ToLayoutBlockFlow(child)->IsAnonymousBlockContinuation())
new_style->SetPosition(child->Style()->GetPosition());
- UpdateAnonymousChildStyle(*child, *new_style);
+ if (child->IsLayoutNGListMarker())
+ new_style->SetWhiteSpace(child->Style()->WhiteSpace());
+
+ UpdateAnonymousChildStyle(child, *new_style);
child->SetStyle(std::move(new_style));
}
@@ -3128,15 +3139,6 @@ static bool FindReferencingScrollAnchors(
}
layer = layer->Parent();
}
- if (LocalFrameView* view = layout_object->GetFrameView()) {
- ScrollAnchor* anchor = view->GetScrollAnchor();
- DCHECK(anchor);
- if (anchor->RefersTo(layout_object)) {
- found = true;
- if (behavior == kClear)
- anchor->NotifyRemoved(layout_object);
- }
- }
return found;
}
@@ -3182,6 +3184,9 @@ void LayoutObject::SetNeedsPaintPropertyUpdate() {
bitfields_.SetNeedsPaintPropertyUpdate(true);
LayoutObject* ancestor = ParentCrossingFrames();
+
+ GetFrameView()->SetNeedsIntersectionObservation(LocalFrameView::kDesired);
+
while (ancestor && !ancestor->DescendantNeedsPaintPropertyUpdate()) {
ancestor->bitfields_.SetDescendantNeedsPaintPropertyUpdate(true);
ancestor = ancestor->ParentCrossingFrames();
@@ -3358,7 +3363,7 @@ Node* LayoutObject::NodeForHitTest() const {
}
void LayoutObject::UpdateHitTestResult(HitTestResult& result,
- const LayoutPoint& point) {
+ const LayoutPoint& point) const {
if (result.InnerNode())
return;
@@ -3410,6 +3415,7 @@ static scoped_refptr<ComputedStyle> FirstLineStyleForCachedUncachedType(
StyleCacheState type,
const LayoutObject* layout_object,
ComputedStyle* style) {
+ DCHECK(layout_object);
const LayoutObject* layout_object_for_first_line_style = layout_object;
if (layout_object->IsBeforeOrAfterContent())
layout_object_for_first_line_style = layout_object->Parent();
@@ -3424,10 +3430,25 @@ static scoped_refptr<ComputedStyle> FirstLineStyleForCachedUncachedType(
return first_line_block->GetUncachedPseudoStyle(
PseudoStyleRequest(kPseudoIdFirstLine), style);
}
- } else if (!layout_object_for_first_line_style->IsAnonymous() &&
- layout_object_for_first_line_style->IsLayoutInline() &&
- !layout_object_for_first_line_style->GetNode()
- ->IsFirstLetterPseudoElement()) {
+ } else if (layout_object_for_first_line_style->IsLayoutInline()) {
+ if (layout_object_for_first_line_style->IsAnonymous()) {
+ // Anonymous inline box for ::first-line should inherit background.
+ if (ToLayoutInline(layout_object_for_first_line_style)
+ ->IsFirstLineAnonymous()) {
+ // TODO(kojii): This function must return a style that is referred by
+ // someone else, and that we can't create an inherited style here.
+ // Returning parent's style seems to work for now.
+ return FirstLineStyleForCachedUncachedType(
+ type, layout_object->Parent(), style);
+ }
+ // TODO(kojii): This does not look correct, but creating a first-line
+ // style for anonymous inline box does not seem easy for now.
+ return nullptr;
+ }
+ if (layout_object_for_first_line_style->GetNode()
+ ->IsFirstLetterPseudoElement()) {
+ return nullptr;
+ }
const ComputedStyle* parent_style =
layout_object_for_first_line_style->Parent()->FirstLineStyle();
if (parent_style != layout_object_for_first_line_style->Parent()->Style()) {
@@ -3475,7 +3496,8 @@ ComputedStyle* LayoutObject::GetCachedPseudoStyle(
if (!element)
return nullptr;
- return element->PseudoStyle(PseudoStyleRequest(pseudo), parent_style);
+ return element->CachedStyleForPseudoElement(PseudoStyleRequest(pseudo),
+ parent_style);
}
scoped_refptr<ComputedStyle> LayoutObject::GetUncachedPseudoStyle(
@@ -3492,7 +3514,7 @@ scoped_refptr<ComputedStyle> LayoutObject::GetUncachedPseudoStyle(
if (element->IsPseudoElement())
return nullptr;
- return element->GetUncachedPseudoStyle(request, parent_style);
+ return element->StyleForPseudoElement(request, parent_style);
}
void LayoutObject::AddAnnotatedRegions(Vector<AnnotatedRegionValue>& regions) {
@@ -3524,6 +3546,10 @@ bool LayoutObject::WillRenderImage() {
if (GetDocument().IsContextPaused())
return false;
+ // Suspend animations when the page is not visible.
+ if (GetDocument().hidden())
+ return false;
+
// If we're not in a window (i.e., we're dormant from being in a background
// tab) then we don't want to render either.
return GetDocument().View()->IsVisible();
@@ -3853,10 +3879,7 @@ void LayoutObject::ClearPaintInvalidationFlags() {
#if DCHECK_IS_ON()
DCHECK(!ShouldCheckForPaintInvalidation() || PaintInvalidationStateIsDirty());
#endif
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() ||
- !RuntimeEnabledFeatures::PartialRasterInvalidationEnabled())
- fragment_.SetPartialInvalidationRect(LayoutRect());
-
+ fragment_.SetPartialInvalidationLocalRect(LayoutRect());
ClearShouldDoFullPaintInvalidation();
bitfields_.SetMayNeedPaintInvalidation(false);
bitfields_.SetMayNeedPaintInvalidationSubtree(false);
@@ -3867,18 +3890,7 @@ void LayoutObject::ClearPaintInvalidationFlags() {
}
bool LayoutObject::IsAllowedToModifyLayoutTreeStructure(Document& document) {
- return DeprecatedDisableModifyLayoutTreeStructureAsserts::
- CanModifyLayoutTreeStateInAnyState() ||
- document.Lifecycle().StateAllowsLayoutTreeMutations();
-}
-
-DeprecatedDisableModifyLayoutTreeStructureAsserts::
- DeprecatedDisableModifyLayoutTreeStructureAsserts()
- : disabler_(&g_modify_layout_tree_structure_any_state, true) {}
-
-bool DeprecatedDisableModifyLayoutTreeStructureAsserts::
- CanModifyLayoutTreeStateInAnyState() {
- return g_modify_layout_tree_structure_any_state;
+ return document.Lifecycle().StateAllowsLayoutTreeMutations();
}
void LayoutObject::
@@ -3912,7 +3924,7 @@ LayoutRect LayoutObject::DebugRect() const {
return rect;
}
-void LayoutObject::InvalidateSelectionOfSelectedChildren() {
+void LayoutObject::InvalidateSelectedChildrenOnStyleChange() {
// setSelectionState() propagates the state up the containing block chain to
// tell if a block contains selected nodes or not. If this layout object is
// not a block, we need to get the selection state from the containing block
@@ -3933,7 +3945,22 @@ void LayoutObject::InvalidateSelectionOfSelectedChildren() {
continue;
if (child->GetSelectionState() == SelectionState::kNone)
continue;
- child->SetShouldInvalidateSelection();
+ if (RuntimeEnabledFeatures::LayoutNGEnabled()) {
+ child->SetShouldDoFullPaintInvalidation(
+ PaintInvalidationReason::kSelection);
+ } else {
+ child->SetShouldInvalidateSelection();
+ }
+ }
+}
+
+void LayoutObject::MarkEffectiveWhitelistedTouchActionChanged() {
+ bitfields_.SetEffectiveWhitelistedTouchActionChanged(true);
+
+ LayoutObject* obj = ParentCrossingFrames();
+ while (obj && !obj->DescendantEffectiveWhitelistedTouchActionChanged()) {
+ obj->bitfields_.SetDescendantEffectiveWhitelistedTouchActionChanged(true);
+ obj = obj->ParentCrossingFrames();
}
}
@@ -3995,14 +4022,7 @@ const LayoutObject* AssociatedLayoutObjectOf(const Node& node,
if (static_cast<unsigned>(offset_in_node) >= threshold)
return layout_object;
}
- LayoutObject* first_letter_layout_object =
- layout_text_fragment->GetFirstLetterPseudoElement()->GetLayoutObject();
- // TODO(yosin): We're not sure when |firstLetterLayoutObject| has
- // multiple child layout object.
- LayoutObject* child = first_letter_layout_object->SlowFirstChild();
- CHECK(child && child->IsText());
- DCHECK_EQ(child, first_letter_layout_object->SlowLastChild());
- return child;
+ return layout_text_fragment->GetFirstLetterPart();
}
bool LayoutObject::CanBeSelectionLeaf() const {
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 25a0dc1757e..8c7bd54890c 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_object.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_object.h
@@ -34,10 +34,10 @@
#include "third_party/blink/renderer/core/dom/document_lifecycle.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/editing/forward.h"
-#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/api/hit_test_action.h"
#include "third_party/blink/renderer/core/layout/api/selection_state.h"
+#include "third_party/blink/renderer/core/layout/hit_test_result.h"
#include "third_party/blink/renderer/core/layout/layout_object_child_list.h"
#include "third_party/blink/renderer/core/layout/map_coordinates_flags.h"
#include "third_party/blink/renderer/core/layout/subtree_layout_scope.h"
@@ -50,6 +50,7 @@
#include "third_party/blink/renderer/platform/geometry/float_quad.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/graphics/compositing_reasons.h"
+#include "third_party/blink/renderer/platform/graphics/image_orientation.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item_client.h"
#include "third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h"
#include "third_party/blink/renderer/platform/graphics/touch_action_rect.h"
@@ -62,7 +63,6 @@ class AffineTransform;
class Cursor;
class HitTestLocation;
class HitTestRequest;
-class HitTestResult;
class InlineBox;
class LayoutBoxModelObject;
class LayoutBlock;
@@ -71,6 +71,7 @@ class LayoutFlowThread;
class LayoutGeometryMap;
class LayoutMultiColumnSpannerPlaceholder;
class LayoutView;
+class LocalFrameView;
class NGPhysicalBoxFragment;
class ObjectPaintProperties;
class PaintLayer;
@@ -82,8 +83,9 @@ struct WebScrollIntoViewParams;
enum VisualRectFlags {
kDefaultVisualRectFlags = 0,
- kEdgeInclusive = 1,
- kUseGeometryMapper = 2, // Use the GeometryMapper fast-path, if possible.
+ kEdgeInclusive = 1 << 0,
+ // Use the GeometryMapper fast-path, if possible.
+ kUseGeometryMapper = 1 << 1,
};
enum CursorDirective { kSetCursorBasedOnStyle, kSetCursor, kDoNotSetCursor };
@@ -208,8 +210,6 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
public DisplayItemClient {
friend class LayoutObjectChildList;
FRIEND_TEST_ALL_PREFIXES(LayoutObjectTest, MutableForPaintingClearPaintFlags);
- FRIEND_TEST_ALL_PREFIXES(LayoutObjectTest,
- LocationInBackingAndSelectionVisualRect);
friend class VisualRectMappingTest;
public:
@@ -226,17 +226,34 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
// state (e.g. positioning).
String DecoratedName() const;
+ // This is an inexact determination of whether the display of this objects is
+ // altered or obscured by CSS effects.
+ bool HasDistortingVisualEffects() const;
+
+ // Returns false iff this object or one of its ancestors has opacity:0.
+ bool HasNonZeroEffectiveOpacity() const;
+
// DisplayItemClient methods.
// Do not call VisualRect directly outside of the DisplayItemClient
// interface, use a per-fragment one on FragmentData instead.
private:
+ // Hide DisplayItemClient methods whose names are too generic for
+ // LayoutObject. Use LayoutObject methods instead, or explicitly cast.
+ using DisplayItemClient::Invalidate;
+ using DisplayItemClient::IsValid;
+
LayoutRect VisualRect() const final;
+ void ClearPartialInvalidationVisualRect() const final {
+ return GetMutableForPainting()
+ .FirstFragment()
+ .SetPartialInvalidationVisualRect(LayoutRect());
+ }
+
public:
- void ClearPartialInvalidationRect() const final {
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
- return GetMutableForPainting().SetPartialInvalidationRect(LayoutRect());
+ LayoutRect PartialInvalidationVisualRect() const final {
+ return FirstFragment().PartialInvalidationVisualRect();
}
String DebugName() const final;
@@ -272,7 +289,6 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
const LayoutObject* stay_within) const;
LayoutObject* PreviousInPreOrder() const;
LayoutObject* PreviousInPreOrder(const LayoutObject* stay_within) const;
- LayoutObject* ChildAt(unsigned) const;
LayoutObject* LastLeafChild() const;
@@ -305,7 +321,6 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
// Convenience function for getting to the nearest enclosing box of a
// LayoutObject.
LayoutBox* EnclosingBox() const;
- LayoutBoxModelObject* EnclosingBoxModelObject() const;
LayoutBox* EnclosingScrollableBox() const;
@@ -425,6 +440,24 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
UniqueObjectId UniqueId() const { return fragment_.UniqueId(); }
+ inline bool ShouldApplyPaintContainment() const {
+ return StyleRef().ContainsPaint() &&
+ (!IsInline() || IsAtomicInlineLevel()) && !IsRubyText() &&
+ (!IsTablePart() || IsLayoutBlockFlow());
+ }
+
+ inline bool ShouldApplyLayoutContainment() const {
+ return StyleRef().ContainsLayout() &&
+ (!IsInline() || IsAtomicInlineLevel()) && !IsRubyText() &&
+ (!IsTablePart() || IsLayoutBlockFlow());
+ }
+
+ inline bool ShouldApplySizeContainment() const {
+ return StyleRef().ContainsSize() &&
+ (!IsInline() || IsAtomicInlineLevel()) && !IsRubyText() &&
+ (!IsTablePart() || IsTableCaption()) && !IsTable();
+ }
+
private:
//////////////////////////////////////////
// Helper functions. Dangerous to use!
@@ -546,12 +579,6 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
bool IsQuote() const { return IsOfType(kLayoutObjectQuote); }
bool IsLayoutButton() const { return IsOfType(kLayoutObjectLayoutButton); }
bool IsLayoutCustom() const { return IsOfType(kLayoutObjectLayoutCustom); }
- bool IsLayoutFullScreen() const {
- return IsOfType(kLayoutObjectLayoutFullScreen);
- }
- bool IsLayoutFullScreenPlaceholder() const {
- return IsOfType(kLayoutObjectLayoutFullScreenPlaceholder);
- }
bool IsLayoutGrid() const { return IsOfType(kLayoutObjectLayoutGrid); }
bool IsLayoutIFrame() const { return IsOfType(kLayoutObjectLayoutIFrame); }
bool IsLayoutImage() const { return IsOfType(kLayoutObjectLayoutImage); }
@@ -767,12 +794,11 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
// LayoutTextFragment are not LayoutBlocks and will return false.
// See https://bugs.webkit.org/show_bug.cgi?id=56709.
return IsAnonymous() &&
- (Style()->Display() == EDisplay::kBlock ||
- Style()->Display() == EDisplay::kWebkitBox) &&
- Style()->StyleType() == kPseudoIdNone && IsLayoutBlock() &&
+ (StyleRef().Display() == EDisplay::kBlock ||
+ StyleRef().Display() == EDisplay::kWebkitBox) &&
+ StyleRef().StyleType() == kPseudoIdNone && IsLayoutBlock() &&
!IsListMarker() && !IsLayoutFlowThread() &&
- !IsLayoutMultiColumnSet() && !IsLayoutFullScreen() &&
- !IsLayoutFullScreenPlaceholder();
+ !IsLayoutMultiColumnSet();
}
bool IsElementContinuation() const {
return GetNode() && GetNode()->GetLayoutObject() != this;
@@ -798,11 +824,11 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
bool IsStickyPositioned() const { return bitfields_.IsStickyPositioned(); }
bool IsFixedPositioned() const {
return IsOutOfFlowPositioned() &&
- Style()->GetPosition() == EPosition::kFixed;
+ StyleRef().GetPosition() == EPosition::kFixed;
}
bool IsAbsolutePositioned() const {
return IsOutOfFlowPositioned() &&
- Style()->GetPosition() == EPosition::kAbsolute;
+ StyleRef().GetPosition() == EPosition::kAbsolute;
}
bool IsPositioned() const { return bitfields_.IsPositioned(); }
@@ -814,7 +840,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
return bitfields_.HorizontalWritingMode();
}
bool HasFlippedBlocksWritingMode() const {
- return Style()->IsFlippedBlocksWritingMode();
+ return StyleRef().IsFlippedBlocksWritingMode();
}
bool HasLayer() const { return bitfields_.HasLayer(); }
@@ -870,34 +896,32 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
// CSS clip only applies when position is absolute or fixed. Prefer this check
// over !Style()->HasAutoClip().
bool HasClip() const {
- return IsOutOfFlowPositioned() && !Style()->HasAutoClip();
+ return IsOutOfFlowPositioned() && !StyleRef().HasAutoClip();
}
bool HasOverflowClip() const { return bitfields_.HasOverflowClip(); }
+ bool ShouldClipOverflow() const { return bitfields_.ShouldClipOverflow(); }
bool HasClipRelatedProperty() const;
bool HasTransformRelatedProperty() const {
return bitfields_.HasTransformRelatedProperty();
}
bool IsTransformApplicable() const { return IsBox() || IsSVG(); }
- bool HasMask() const { return Style() && Style()->HasMask(); }
- bool HasClipPath() const { return Style() && Style()->ClipPath(); }
+ bool HasMask() const { return StyleRef().HasMask(); }
+ bool HasClipPath() const { return StyleRef().ClipPath(); }
bool HasHiddenBackface() const {
- return Style() &&
- Style()->BackfaceVisibility() == EBackfaceVisibility::kHidden;
- }
- bool HasBackdropFilter() const {
- return Style() && Style()->HasBackdropFilter();
+ return StyleRef().BackfaceVisibility() == EBackfaceVisibility::kHidden;
}
+ bool HasBackdropFilter() const { return StyleRef().HasBackdropFilter(); }
// 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 (Style() && Style()->HasFilter()) || HasReflection();
+ return StyleRef().HasFilter() || HasReflection();
}
- bool HasShapeOutside() const { return Style() && Style()->ShapeOutside(); }
+ bool HasShapeOutside() const { return StyleRef().ShapeOutside(); }
// The pseudo element style can be cached or uncached. Use the cached method
// if the pseudo element doesn't respect any pseudo classes (and therefore
@@ -939,7 +963,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
return nullptr;
}
bool IsColumnSpanAll() const {
- return Style()->GetColumnSpan() == EColumnSpan::kAll &&
+ return StyleRef().GetColumnSpan() == EColumnSpan::kAll &&
SpannerPlaceholder();
}
@@ -953,7 +977,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
// TODO(cbiesinger): Remove when buttons are implemented with align-items
// instead of flex box. crbug.com/226252.
bool BehavesLikeBlockContainer() const {
- return (IsLayoutBlockFlow() && Style()->IsDisplayBlockContainer()) ||
+ return (IsLayoutBlockFlow() && StyleRef().IsDisplayBlockContainer()) ||
IsLayoutButton();
}
@@ -1104,6 +1128,9 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
void SetHasOverflowClip(bool has_overflow_clip) {
bitfields_.SetHasOverflowClip(has_overflow_clip);
}
+ void SetShouldClipOverflow(bool should_clip_overflow) {
+ bitfields_.SetShouldClipOverflow(should_clip_overflow);
+ }
void SetHasLayer(bool has_layer) { bitfields_.SetHasLayer(has_layer); }
void SetHasTransformRelatedProperty(bool has_transform) {
bitfields_.SetHasTransformRelatedProperty(has_transform);
@@ -1115,9 +1142,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
bitfields_.SetCanContainFixedPositionObjects(can_contain_fixed_position);
}
- // paintOffset is the offset from the origin of the GraphicsContext at which
- // to paint the current object.
- virtual void Paint(const PaintInfo&, const LayoutPoint& paint_offset) const;
+ virtual void Paint(const PaintInfo&) const;
virtual bool RecalcOverflowAfterStyleChange();
@@ -1183,7 +1208,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
// continuations and some psuedo elements) and it is important that the
// node be consistent between point- and list-based hit test results.
virtual Node* NodeForHitTest() const;
- virtual void UpdateHitTestResult(HitTestResult&, const LayoutPoint&);
+ virtual void UpdateHitTestResult(HitTestResult&, const LayoutPoint&) const;
virtual bool NodeAtPoint(HitTestResult&,
const HitTestLocation& location_in_container,
const LayoutPoint& accumulated_offset,
@@ -1415,7 +1440,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
}
inline Color ResolveColor(const CSSProperty& color_property) const {
- return Style()->VisitedDependentColor(color_property);
+ return StyleRef().VisitedDependentColor(color_property);
}
virtual CursorDirective GetCursor(const LayoutPoint&, Cursor&) const;
@@ -1430,8 +1455,9 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
bool IsPaintInvalidationContainer() const;
- // Invalidate the paint of a specific subrectangle within a given object. The
- // rect is in the object's coordinate space.
+ // Invalidate the raster of a specific sub-rectangle within the object. The
+ // rect is in the object's local coordinate space. This is useful e.g. when
+ // a small region of a canvas changes.
void InvalidatePaintRectangle(const LayoutRect&);
void SetShouldDoFullPaintInvalidationIncludingNonCompositingDescendants();
@@ -1487,6 +1513,12 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
TransformState&,
VisualRectFlags = kDefaultVisualRectFlags) const;
+ // Do a rect-based hit test with this object as the stop node.
+ HitTestResult HitTestForOcclusion(const LayoutRect&) const;
+ HitTestResult HitTestForOcclusion() const {
+ return HitTestForOcclusion(AbsoluteVisualRect());
+ }
+
// Return the offset to the column in which the specified point (in
// flow-thread coordinates) lives. This is used to convert a flow-thread point
// to a point in the containing coordinate space.
@@ -1500,8 +1532,8 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
return (IsFloating() || IsOutOfFlowPositioned());
}
- bool IsTransparent() const { return Style()->HasOpacity(); }
- float Opacity() const { return Style()->Opacity(); }
+ bool IsTransparent() const { return StyleRef().HasOpacity(); }
+ float Opacity() const { return StyleRef().Opacity(); }
bool HasReflection() const { return bitfields_.HasReflection(); }
@@ -1569,6 +1601,14 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
return IsFlexibleBox() || IsDeprecatedFlexibleBox();
}
+ bool IsListItemIncludingNG() const {
+ return IsListItem() || IsLayoutNGListItem();
+ }
+
+ bool IsListMarkerIncludingNG() const {
+ return IsListMarker() || IsLayoutNGListMarker();
+ }
+
virtual bool IsCombineText() const { return false; }
virtual int CaretMinOffset() const;
@@ -1590,15 +1630,15 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
}
bool VisibleToHitTestRequest(const HitTestRequest& request) const {
- return Style()->Visibility() == EVisibility::kVisible &&
+ return StyleRef().Visibility() == EVisibility::kVisible &&
(request.IgnorePointerEventsNone() ||
- Style()->PointerEvents() != EPointerEvents::kNone) &&
+ StyleRef().PointerEvents() != EPointerEvents::kNone) &&
!IsInert();
}
// Warning: inertness can change without causing relayout.
bool VisibleToHitTesting() const {
- return Style()->VisibleToHitTesting() && !IsInert();
+ return StyleRef().VisibleToHitTesting() && !IsInert();
}
// Map points and quads through elements, potentially via 3d transforms. You
@@ -1634,7 +1674,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
bool CreatesGroup() const {
return IsTransparent() || HasMask() || HasClipPath() ||
- HasFilterInducingProperty() || Style()->HasBlendMode();
+ HasFilterInducingProperty() || StyleRef().HasBlendMode();
}
// Collects rectangles that the outline of this object would be drawing along
@@ -1670,11 +1710,6 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
AddOutlineRects(rects, additional_offset, kIncludeBlockVisualOverflow);
}
- // Returns the rect enclosing united visual overflow of the DOM subtree under
- // this object. It includes continuations which may be not in the layout
- // subtree of this object.
- virtual IntRect AbsoluteElementBoundingBoxRect() const;
-
// Compute a list of hit-test rectangles per layer rooted at this
// layoutObject with at most the given touch action.
virtual void ComputeLayerHitTestRects(LayerHitTestRects&, TouchAction) const;
@@ -1755,9 +1790,9 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
virtual bool HasNonCompositedScrollbars() const { return false; }
- // Called before anonymousChild.setStyle(). Override to set custom styles for
- // the child.
- virtual void UpdateAnonymousChildStyle(const LayoutObject& anonymous_child,
+ // Called before setting style for existing/new anonymous child. Override to
+ // set custom styles for the child. For new anonymous child, |child| is null.
+ virtual void UpdateAnonymousChildStyle(const LayoutObject* child,
ComputedStyle& style) const {}
// Returns a rect corresponding to this LayoutObject's bounds for use in
@@ -1776,8 +1811,36 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
void InvalidateClipPathCache();
- // Call |SetShouldInvalidateSelection| on all selected children.
- void InvalidateSelectionOfSelectedChildren();
+ // Call |SetShouldDoFullPaintInvalidation| for LayoutNG or
+ // |SetShouldInvalidateSelection| on all selected children.
+ void InvalidateSelectedChildrenOnStyleChange();
+
+ // The whitelisted touch action is the union of the effective touch action
+ // (from style) and blocking touch event handlers.
+ TouchAction EffectiveWhitelistedTouchAction() const {
+ if (InsideBlockingTouchEventHandler())
+ return TouchAction::kTouchActionNone;
+ return StyleRef().GetEffectiveTouchAction();
+ }
+
+ // Whether this object's Node has a blocking touch event handler on itself
+ // or an ancestor.
+ bool InsideBlockingTouchEventHandler() const {
+ return bitfields_.InsideBlockingTouchEventHandler();
+ }
+ // Mark this object as having a |EffectiveWhitelistedTouchAction| changed, and
+ // mark all ancestors as having a descendant that changed. This will cause a
+ // PrePaint tree walk to update effective whitelisted touch action.
+ void MarkEffectiveWhitelistedTouchActionChanged();
+ bool EffectiveWhitelistedTouchActionChanged() const {
+ return bitfields_.EffectiveWhitelistedTouchActionChanged();
+ }
+ bool DescendantEffectiveWhitelistedTouchActionChanged() const {
+ return bitfields_.DescendantEffectiveWhitelistedTouchActionChanged();
+ }
+ void UpdateInsideBlockingTouchEventHandler(bool inside) {
+ bitfields_.SetInsideBlockingTouchEventHandler(inside);
+ }
// Painters can use const methods only, except for these explicitly declared
// methods.
@@ -1792,6 +1855,10 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
layout_object_.bitfields_.SetNeedsPaintPropertyUpdate(false);
layout_object_.bitfields_.SetSubtreeNeedsPaintPropertyUpdate(false);
layout_object_.bitfields_.SetDescendantNeedsPaintPropertyUpdate(false);
+ layout_object_.bitfields_.SetEffectiveWhitelistedTouchActionChanged(
+ false);
+ layout_object_.bitfields_
+ .SetDescendantEffectiveWhitelistedTouchActionChanged(false);
}
void SetMayNeedPaintInvalidation() {
layout_object_.SetMayNeedPaintInvalidation();
@@ -1839,12 +1906,18 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
layout_object_.SetSubtreeNeedsPaintPropertyUpdate();
}
- void SetPartialInvalidationRect(const LayoutRect& r) {
- layout_object_.SetPartialInvalidationRect(r);
+ void SetPartialInvalidationVisualRect(const LayoutRect& r) {
+ DCHECK_EQ(layout_object_.GetDocument().Lifecycle().GetState(),
+ DocumentLifecycle::kInPrePaint);
+ FirstFragment().SetPartialInvalidationVisualRect(r);
}
void InvalidateClipPathCache() { layout_object_.InvalidateClipPathCache(); }
+ void UpdateInsideBlockingTouchEventHandler(bool inside) {
+ layout_object_.UpdateInsideBlockingTouchEventHandler(inside);
+ }
+
#if DCHECK_IS_ON()
// Same as setNeedsPaintPropertyUpdate() but does not mark ancestors as
// having a descendant needing a paint property update.
@@ -1861,7 +1934,6 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
protected:
friend class LayoutBoxModelObject;
friend class LayoutScrollbar;
- friend class PaintInvalidationCapableScrollableArea;
friend class PaintInvalidator;
friend class PaintPropertyTreeBuilder;
friend class PrePaintTreeWalk;
@@ -1871,8 +1943,6 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
canStartElementOnCompositorEffectSPv2);
FRIEND_TEST_ALL_PREFIXES(PrePaintTreeWalkTest, ClipRects);
FRIEND_TEST_ALL_PREFIXES(LayoutObjectTest, VisualRect);
- FRIEND_TEST_ALL_PREFIXES(LayoutObjectTest,
- LocationInBackingAndSelectionVisualRect);
FRIEND_TEST_ALL_PREFIXES(BoxPaintInvalidatorTest,
ComputePaintInvalidationReasonBasic);
@@ -1961,8 +2031,8 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
LayoutRect SelectionVisualRect() const {
return fragment_.SelectionVisualRect();
}
- LayoutRect PartialInvalidationRect() const override {
- return fragment_.PartialInvalidationRect();
+ LayoutRect PartialInvalidationLocalRect() const {
+ return fragment_.PartialInvalidationLocalRect();
}
void InvalidateIfControlStateChanged(ControlState);
@@ -2004,8 +2074,6 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
kLayoutObjectLayoutButton,
kLayoutObjectLayoutCustom,
kLayoutObjectLayoutFlowThread,
- kLayoutObjectLayoutFullScreen,
- kLayoutObjectLayoutFullScreenPlaceholder,
kLayoutObjectLayoutGrid,
kLayoutObjectLayoutIFrame,
kLayoutObjectLayoutImage,
@@ -2122,17 +2190,12 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
virtual void ComputeSelfHitTestRects(Vector<LayoutRect>&,
const LayoutPoint& layer_offset) const {}
- void SetPartialInvalidationRect(const LayoutRect& rect) {
- fragment_.SetPartialInvalidationRect(rect);
- }
-
#if DCHECK_IS_ON()
virtual bool PaintInvalidationStateIsDirty() const {
return BackgroundChangedSinceLastPaintInvalidation() ||
ShouldCheckForPaintInvalidation() || ShouldInvalidateSelection() ||
NeedsPaintOffsetAndVisualRectUpdate() ||
- (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- !fragment_.PartialInvalidationRect().IsEmpty());
+ !fragment_.PartialInvalidationLocalRect().IsEmpty();
}
#endif
@@ -2321,6 +2384,7 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
horizontal_writing_mode_(true),
has_layer_(false),
has_overflow_clip_(false),
+ should_clip_overflow_(false),
has_transform_related_property_(false),
has_reflection_(false),
can_contain_fixed_position_objects_(false),
@@ -2346,6 +2410,9 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
outline_may_be_affected_by_descendants_(false),
previous_outline_may_be_affected_by_descendants_(false),
is_truncated_(false),
+ inside_blocking_touch_event_handler_(false),
+ effective_whitelisted_touch_action_changed_(true),
+ descendant_effective_whitelisted_touch_action_changed_(false),
positioned_state_(kIsStaticallyPositioned),
selection_state_(static_cast<unsigned>(SelectionState::kNone)),
background_obscuration_state_(kBackgroundObscurationStatusInvalid),
@@ -2464,6 +2531,11 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
// details). Only set for LayoutBoxes and descendants.
ADD_BOOLEAN_BITFIELD(has_overflow_clip_, HasOverflowClip);
+ // Returns whether content which overflows should be clipped. This is not
+ // just because of overflow clip, but other types of clip as well, such as
+ // control clips or contain: paint.
+ ADD_BOOLEAN_BITFIELD(should_clip_overflow_, ShouldClipOverflow);
+
// This boolean is the cached value from
// ComputedStyle::hasTransformRelatedProperty.
ADD_BOOLEAN_BITFIELD(has_transform_related_property_,
@@ -2547,9 +2619,28 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
ADD_BOOLEAN_BITFIELD(is_truncated_, IsTruncated);
+ // Whether this object's Node has a blocking touch event handler on itself
+ // or an ancestor. This is updated during the PrePaint phase.
+ ADD_BOOLEAN_BITFIELD(inside_blocking_touch_event_handler_,
+ InsideBlockingTouchEventHandler);
+
+ // Set when |EffectiveWhitelistedTouchAction| changes (i.e., blocking touch
+ // event handlers change or effective touch action style changes). This only
+ // needs to be set on the object that changes as the PrePaint walk will
+ // ensure descendants are updated.
+ ADD_BOOLEAN_BITFIELD(effective_whitelisted_touch_action_changed_,
+ EffectiveWhitelistedTouchActionChanged);
+
+ // Set when a descendant's |EffectiveWhitelistedTouchAction| changes. This
+ // is used to ensure the PrePaint tree walk processes objects with
+ // |effective_whitelisted_touch_action_changed_|.
+ ADD_BOOLEAN_BITFIELD(descendant_effective_whitelisted_touch_action_changed_,
+ DescendantEffectiveWhitelistedTouchActionChanged);
+
protected:
// Use protected to avoid warning about unused variable.
- unsigned unused_bits_ : 4;
+ // Increment this to 63 if a new bit is added.
+ // unsigned unused_bits_ : 0;
private:
// This is the cached 'position' value of this object
@@ -2669,21 +2760,6 @@ class CORE_EXPORT LayoutObject : public ImageResourceObserver,
DISALLOW_COPY_AND_ASSIGN(LayoutObject);
};
-// FIXME: remove this once the layout object lifecycle ASSERTS are no longer
-// hit.
-class DeprecatedDisableModifyLayoutTreeStructureAsserts {
- STACK_ALLOCATED();
-
- public:
- DeprecatedDisableModifyLayoutTreeStructureAsserts();
-
- static bool CanModifyLayoutTreeStateInAnyState();
-
- private:
- base::AutoReset<bool> disabler_;
- DISALLOW_COPY_AND_ASSIGN(DeprecatedDisableModifyLayoutTreeStructureAsserts);
-};
-
// Allow equality comparisons of LayoutObjects by reference or pointer,
// interchangeably.
DEFINE_COMPARISON_OPERATORS_WITH_REFERENCES(LayoutObject)
@@ -2693,7 +2769,7 @@ inline bool LayoutObject::DocumentBeingDestroyed() const {
}
inline bool LayoutObject::IsBeforeContent() const {
- if (Style()->StyleType() != kPseudoIdBefore)
+ if (StyleRef().StyleType() != kPseudoIdBefore)
return false;
// Text nodes don't have their own styles, so ignore the style on a text node.
if (IsText() && !IsBR())
@@ -2702,7 +2778,7 @@ inline bool LayoutObject::IsBeforeContent() const {
}
inline bool LayoutObject::IsAfterContent() const {
- if (Style()->StyleType() != kPseudoIdAfter)
+ if (StyleRef().StyleType() != kPseudoIdAfter)
return false;
// Text nodes don't have their own styles, so ignore the style on a text node.
if (IsText() && !IsBR())
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 9d85f86f006..985e6b03452 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
@@ -26,7 +26,7 @@
#include "third_party/blink/renderer/core/layout/layout_object_child_list.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/layout/layout_counter.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
@@ -242,14 +242,6 @@ void LayoutObjectChildList::InvalidatePaintOnRemoval(LayoutObject& old_child) {
old_child.View()->SetShouldDoFullPaintInvalidation();
ObjectPaintInvalidator paint_invalidator(old_child);
paint_invalidator.SlowSetPaintingLayerNeedsRepaint();
-
- // For SPv175 raster invalidation will be done in PaintController.
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- paint_invalidator.InvalidatePaintOfPreviousVisualRect(
- old_child.ContainerForPaintInvalidation(),
- PaintInvalidationReason::kDisappeared);
}
} // namespace blink
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
new file mode 100644
index 00000000000..24507395c13
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/layout_object_factory.cc
@@ -0,0 +1,95 @@
+// 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/layout/layout_object_factory.h"
+
+#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
+#include "third_party/blink/renderer/core/layout/layout_flexible_box.h"
+#include "third_party/blink/renderer/core/layout/layout_list_item.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/layout_view.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
+#include "third_party/blink/renderer/core/layout/ng/layout_ng_flexible_box.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/list/layout_ng_list_item.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+
+namespace blink {
+
+namespace {
+
+inline bool ShouldUseNewLayout(Document& document, const ComputedStyle& style) {
+ if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+ return false;
+ bool requires_ng_block_fragmentation =
+ document.Printing() ||
+ (document.GetLayoutView() &&
+ document.GetLayoutView()->StyleRef().IsOverflowPaged());
+ if (requires_ng_block_fragmentation &&
+ !RuntimeEnabledFeatures::LayoutNGBlockFragmentationEnabled())
+ return false;
+ return !style.ForceLegacyLayout();
+}
+
+inline Element* GetElementForLayoutObject(Node& node) {
+ if (node.IsElementNode())
+ return &ToElement(node);
+ // If |node| is a Document, the layout object is going to be anonymous.
+ DCHECK(node.IsDocumentNode());
+ return nullptr;
+}
+
+} // anonymous namespace
+
+LayoutBlockFlow* LayoutObjectFactory::CreateBlockFlow(
+ Node& node,
+ const ComputedStyle& style) {
+ Element* element = GetElementForLayoutObject(node);
+ if (ShouldUseNewLayout(node.GetDocument(), style))
+ return new LayoutNGBlockFlow(element);
+ return new LayoutBlockFlow(element);
+}
+
+LayoutBlock* LayoutObjectFactory::CreateFlexibleBox(
+ Node& node,
+ const ComputedStyle& style) {
+ Element* element = GetElementForLayoutObject(node);
+ if (RuntimeEnabledFeatures::LayoutNGFlexBoxEnabled() &&
+ ShouldUseNewLayout(node.GetDocument(), style))
+ return new LayoutNGFlexibleBox(element);
+ return new LayoutFlexibleBox(element);
+}
+
+LayoutBlockFlow* LayoutObjectFactory::CreateListItem(
+ Node& node,
+ const ComputedStyle& style) {
+ Element* element = GetElementForLayoutObject(node);
+ if (ShouldUseNewLayout(node.GetDocument(), style))
+ return new LayoutNGListItem(element);
+ return new LayoutListItem(element);
+}
+
+LayoutTableCaption* LayoutObjectFactory::CreateTableCaption(
+ Node& node,
+ const ComputedStyle& style) {
+ Element* element = GetElementForLayoutObject(node);
+ if (ShouldUseNewLayout(node.GetDocument(), style))
+ return new LayoutNGTableCaption(element);
+ return new LayoutTableCaption(element);
+}
+
+LayoutTableCell* LayoutObjectFactory::CreateTableCell(
+ Node& node,
+ const ComputedStyle& style) {
+ Element* element = GetElementForLayoutObject(node);
+ if (ShouldUseNewLayout(node.GetDocument(), style))
+ return new LayoutNGTableCell(element);
+ return new LayoutTableCell(element);
+}
+
+} // 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
new file mode 100644
index 00000000000..5e99c9a5ca6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/layout_object_factory.h
@@ -0,0 +1,39 @@
+// 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_LAYOUT_LAYOUT_OBJECT_FACTORY_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_OBJECT_FACTORY_H_
+
+#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+
+namespace blink {
+
+class LayoutBlock;
+class LayoutBlockFlow;
+class LayoutTableCaption;
+class LayoutTableCell;
+
+// Helper class for creation of certain LayoutObject-derived objects that may
+// need to be of different types, depending on whether or not LayoutNG is to be
+// used in the given context.
+class LayoutObjectFactory {
+ STATIC_ONLY(LayoutObjectFactory);
+
+ public:
+ // The following methods will create and return some LayoutObject-derived
+ // object. If |node| is of type Element, it will be associated with the new
+ // LayoutObject. Otherwise it will be assumed to be a Document node, in which
+ // case the LayoutObject created will be anonymous. The |style| reference
+ // passed will only be used to determine which object type to create.
+ static LayoutBlockFlow* CreateBlockFlow(Node&, const ComputedStyle&);
+ static LayoutBlock* CreateFlexibleBox(Node&, const ComputedStyle&);
+ static LayoutBlockFlow* CreateListItem(Node&, const ComputedStyle&);
+ static LayoutTableCaption* CreateTableCaption(Node&, const ComputedStyle&);
+ static LayoutTableCell* CreateTableCell(Node&, const ComputedStyle&);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_OBJECT_FACTORY_H_
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 5d240d4b73a..e72b057182c 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
@@ -728,6 +728,46 @@ TEST_F(LayoutObjectTest, DisplayContentsSVGGElementInHTML) {
ASSERT_FALSE(text->GetLayoutObject());
}
+TEST_F(LayoutObjectTest, HasDistortingVisualEffects) {
+ SetBodyInnerHTML(R"HTML(
+ <div id=opaque style='opacity:1'><div class=inner></div></div>
+ <div id=transparent style='opacity:0.99'><div class=inner></div></div>
+ <div id=blurred style='filter:blur(5px)'><div class=inner></div></div>
+ <div id=blended style='mix-blend-mode:hue'><div class=inner></div></div>
+ <div id=good-transform style='transform:translateX(10px) scale(1.6)'>
+ <div class=inner></div>
+ </div>
+ <div id=bad-transform style='transform:rotate(45deg)'>
+ <div class=inner></div>
+ </div>
+ )HTML");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ Element* outer = GetDocument().getElementById("opaque");
+ Element* inner = outer->QuerySelector(".inner");
+ ASSERT_FALSE(inner->GetLayoutObject()->HasDistortingVisualEffects());
+
+ outer = GetDocument().getElementById("transparent");
+ inner = outer->QuerySelector(".inner");
+ ASSERT_TRUE(inner->GetLayoutObject()->HasDistortingVisualEffects());
+
+ outer = GetDocument().getElementById("blurred");
+ inner = outer->QuerySelector(".inner");
+ ASSERT_TRUE(inner->GetLayoutObject()->HasDistortingVisualEffects());
+
+ outer = GetDocument().getElementById("blended");
+ inner = outer->QuerySelector(".inner");
+ ASSERT_TRUE(inner->GetLayoutObject()->HasDistortingVisualEffects());
+
+ outer = GetDocument().getElementById("good-transform");
+ inner = outer->QuerySelector(".inner");
+ ASSERT_FALSE(inner->GetLayoutObject()->HasDistortingVisualEffects());
+
+ outer = GetDocument().getElementById("bad-transform");
+ inner = outer->QuerySelector(".inner");
+ ASSERT_TRUE(inner->GetLayoutObject()->HasDistortingVisualEffects());
+}
+
class LayoutObjectSimTest : public SimTest {
public:
bool DocumentHasTouchActionRegion(const EventHandlerRegistry& registry) {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_progress.cc b/chromium/third_party/blink/renderer/core/layout/layout_progress.cc
index d818339bc51..83fe6ed2204 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_progress.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_progress.cc
@@ -31,9 +31,6 @@ namespace blink {
LayoutProgress::LayoutProgress(HTMLProgressElement* element)
: LayoutBlockFlow(element),
position_(HTMLProgressElement::kInvalidPosition),
- animation_start_time_(0),
- animation_repeat_interval_(0),
- animation_duration_(0),
animating_(false),
animation_timer_(
element->GetDocument().GetTaskRunner(TaskType::kInternalDefault),
@@ -62,10 +59,11 @@ void LayoutProgress::UpdateFromElement() {
}
double LayoutProgress::AnimationProgress() const {
- return animating_ ? (fmod((CurrentTime() - animation_start_time_),
- animation_duration_) /
- animation_duration_)
- : 0;
+ if (!animating_)
+ return 0;
+ TimeDelta elapsed = CurrentTimeTicks() - animation_start_time_;
+ return (elapsed % animation_duration_).InSecondsF() /
+ animation_duration_.InSecondsF();
}
bool LayoutProgress::IsDeterminate() const {
@@ -93,14 +91,14 @@ void LayoutProgress::UpdateAnimationState() {
animation_repeat_interval_ =
LayoutTheme::GetTheme().AnimationRepeatIntervalForProgressBar();
- bool animating =
- !IsDeterminate() && Style()->HasAppearance() && animation_duration_ > 0;
+ bool animating = !IsDeterminate() && Style()->HasAppearance() &&
+ animation_duration_ > TimeDelta();
if (animating == animating_)
return;
animating_ = animating;
if (animating_) {
- animation_start_time_ = CurrentTime();
+ animation_start_time_ = CurrentTimeTicks();
animation_timer_.StartOneShot(animation_repeat_interval_, FROM_HERE);
} else {
animation_timer_.Stop();
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_progress.h b/chromium/third_party/blink/renderer/core/layout/layout_progress.h
index 6e606be37dd..ab8a0cbd65f 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_progress.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_progress.h
@@ -58,9 +58,9 @@ class CORE_EXPORT LayoutProgress final : public LayoutBlockFlow {
void UpdateAnimationState();
double position_;
- double animation_start_time_;
- double animation_repeat_interval_;
- double animation_duration_;
+ TimeTicks animation_start_time_;
+ TimeDelta animation_repeat_interval_;
+ TimeDelta animation_duration_;
bool animating_;
TaskRunnerTimer<LayoutProgress> animation_timer_;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_replaced.cc b/chromium/third_party/blink/renderer/core/layout/layout_replaced.cc
index 0b8fb3761b8..f61b89843f8 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_replaced.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_replaced.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
#include "third_party/blink/renderer/core/layout/api/line_layout_block_flow.h"
+#include "third_party/blink/renderer/core/layout/intrinsic_sizing_info.h"
#include "third_party/blink/renderer/core/layout/layout_analyzer.h"
#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/layout_image.h"
@@ -115,9 +116,8 @@ void LayoutReplaced::IntrinsicSizeChanged() {
LayoutInvalidationReason::kSizeChanged);
}
-void LayoutReplaced::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
- ReplacedPainter(*this).Paint(paint_info, paint_offset);
+void LayoutReplaced::Paint(const PaintInfo& paint_info) const {
+ ReplacedPainter(*this).Paint(paint_info);
}
bool LayoutReplaced::HasReplacedLogicalHeight() const {
@@ -638,6 +638,11 @@ LayoutRect LayoutReplaced::ReplacedContentRect() const {
void LayoutReplaced::ComputeIntrinsicSizingInfo(
IntrinsicSizingInfo& intrinsic_sizing_info) const {
+ if (ShouldApplySizeContainment()) {
+ intrinsic_sizing_info.size = FloatSize();
+ return;
+ }
+
intrinsic_sizing_info.size = FloatSize(IntrinsicLogicalWidth().ToFloat(),
IntrinsicLogicalHeight().ToFloat());
@@ -962,6 +967,19 @@ LayoutRect LayoutReplaced::LocalSelectionRect() const {
if (GetSelectionState() == SelectionState::kNone)
return LayoutRect();
+ if (IsInline()) {
+ const auto fragments = NGPaintFragment::InlineFragmentsFor(this);
+ if (fragments.IsInLayoutNGInlineFormattingContext()) {
+ LayoutRect rect;
+ for (const NGPaintFragment* fragment : fragments) {
+ const NGPhysicalOffsetRect fragment_rect =
+ fragment->ComputeLocalSelectionRectForReplaced();
+ rect.Unite(fragment_rect.ToLayoutRect());
+ }
+ return rect;
+ }
+ }
+
if (!InlineBoxWrapper()) {
// We're a block-level replaced element. Just return our own dimensions.
return LayoutRect(LayoutPoint(), Size());
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_replaced.h b/chromium/third_party/blink/renderer/core/layout/layout_replaced.h
index 4ae22643a55..6d403787109 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_replaced.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_replaced.h
@@ -70,7 +70,8 @@ class CORE_EXPORT LayoutReplaced : public LayoutBox {
static const int kDefaultWidth;
static const int kDefaultHeight;
bool CanHaveChildren() const override { return false; }
- virtual void PaintReplaced(const PaintInfo&, const LayoutPoint&) const {}
+ virtual void PaintReplaced(const PaintInfo&,
+ const LayoutPoint& paint_offset) const {}
LayoutRect LocalSelectionRect() const final;
bool HasObjectFit() const {
@@ -78,7 +79,7 @@ class CORE_EXPORT LayoutReplaced : public LayoutBox {
ComputedStyleInitialValues::InitialObjectFit();
}
- void Paint(const PaintInfo&, const LayoutPoint&) const override;
+ void Paint(const PaintInfo&) const override;
// Replaced objects often have contents to paint.
bool PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const override {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar.cc b/chromium/third_party/blink/renderer/core/layout/layout_scrollbar.cc
index 075f947777d..ac5ed054977 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_scrollbar.cc
@@ -86,17 +86,26 @@ LayoutScrollbar::~LayoutScrollbar() {
UpdateScrollbarParts(true);
}
+int LayoutScrollbar::HypotheticalScrollbarThickness(
+ ScrollbarOrientation orientation,
+ const LayoutBox& enclosing_box,
+ const LayoutObject& style_source) {
+ scoped_refptr<ComputedStyle> part_style = style_source.GetUncachedPseudoStyle(
+ PseudoStyleRequest(kPseudoIdScrollbar, nullptr, kScrollbarBGPart),
+ style_source.Style());
+ if (orientation == kHorizontalScrollbar) {
+ return LayoutScrollbarPart::ComputeScrollbarHeight(
+ enclosing_box.ClientHeight().ToInt(), part_style.get());
+ }
+ return LayoutScrollbarPart::ComputeScrollbarWidth(
+ enclosing_box.ClientWidth().ToInt(), part_style.get());
+}
+
void LayoutScrollbar::Trace(blink::Visitor* visitor) {
visitor->Trace(style_source_);
Scrollbar::Trace(visitor);
}
-LayoutBox* LayoutScrollbar::StyleSource() const {
- return style_source_ && style_source_->GetLayoutObject()
- ? style_source_->GetLayoutObject()->EnclosingBox()
- : nullptr;
-}
-
void LayoutScrollbar::DisconnectFromScrollableArea() {
UpdateScrollbarParts(true);
Scrollbar::DisconnectFromScrollableArea();
@@ -141,11 +150,11 @@ void LayoutScrollbar::SetPressedPart(ScrollbarPart part) {
scoped_refptr<ComputedStyle> LayoutScrollbar::GetScrollbarPseudoStyle(
ScrollbarPart part_type,
PseudoId pseudo_id) {
- if (!StyleSource())
+ if (!style_source_->GetLayoutObject())
return nullptr;
-
- return StyleSource()->GetUncachedPseudoStyle(
- PseudoStyleRequest(pseudo_id, this, part_type), StyleSource()->Style());
+ return style_source_->StyleForPseudoElement(
+ PseudoStyleRequest(pseudo_id, this, part_type),
+ style_source_->GetLayoutObject()->Style());
}
void LayoutScrollbar::UpdateScrollbarParts(bool destroy) {
@@ -178,7 +187,7 @@ void LayoutScrollbar::UpdateScrollbarParts(bool destroy) {
SetFrameRect(
IntRect(Location(), IntSize(is_horizontal ? Width() : new_thickness,
is_horizontal ? new_thickness : Height())));
- if (LayoutBox* box = StyleSource()) {
+ if (LayoutBox* box = GetScrollableArea()->GetLayoutBox()) {
if (box->IsLayoutBlock())
ToLayoutBlock(box)->NotifyScrollbarThicknessChanged();
box->SetChildNeedsLayout();
@@ -261,7 +270,7 @@ void LayoutScrollbar::UpdateScrollbarPart(ScrollbarPart part_type,
LayoutScrollbarPart* part_layout_object = parts_.at(part_type);
if (!part_layout_object && need_layout_object && scrollable_area_) {
part_layout_object = LayoutScrollbarPart::CreateAnonymous(
- &StyleSource()->GetDocument(), scrollable_area_, this, part_type);
+ &style_source_->GetDocument(), scrollable_area_, this, part_type);
parts_.Set(part_type, part_layout_object);
SetNeedsPaintInvalidation(part_type);
} else if (part_layout_object && !need_layout_object) {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar.h b/chromium/third_party/blink/renderer/core/layout/layout_scrollbar.h
index 8b070820d45..9e0463e6849 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_scrollbar.h
@@ -36,6 +36,7 @@ namespace blink {
class ComputedStyle;
class Element;
class LayoutBox;
+class LayoutObject;
class LayoutScrollbarPart;
class LayoutScrollbar final : public Scrollbar {
@@ -45,10 +46,16 @@ class LayoutScrollbar final : public Scrollbar {
Element*);
~LayoutScrollbar() override;
- // The LayoutBox that supplies our style information. If the scrollbar is for
- // a document, this is either the <body> or <html> element. Otherwise, it is
- // the element that owns our PaintLayerScrollableArea.
- LayoutBox* StyleSource() const;
+ // Return the thickness that a custom scrollbar would have, without actually
+ // constructing the scrollbar.
+ static int HypotheticalScrollbarThickness(ScrollbarOrientation,
+ const LayoutBox& enclosing_box,
+ const LayoutObject& style_source);
+
+ // The Element that supplies our style information. If the scrollbar is
+ // for a document, this is either the <body> or <html> element. Otherwise, it
+ // is the element that owns our PaintLayerScrollableArea.
+ Element* StyleSource() const { return style_source_.Get(); }
IntRect ButtonRect(ScrollbarPart) const;
IntRect TrackRect(int start_length, int end_length) const;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_part.cc b/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_part.cc
index 8f847af6110..a11e72a8884 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_part.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_part.cc
@@ -100,50 +100,74 @@ void LayoutScrollbarPart::UpdateLayout() {
void LayoutScrollbarPart::LayoutHorizontalPart() {
if (part_ == kScrollbarBGPart) {
SetWidth(LayoutUnit(scrollbar_->Width()));
- ComputeScrollbarHeight();
+ UpdateScrollbarHeight();
} else {
- ComputeScrollbarWidth();
+ UpdateScrollbarWidth();
SetHeight(LayoutUnit(scrollbar_->Height()));
}
}
void LayoutScrollbarPart::LayoutVerticalPart() {
if (part_ == kScrollbarBGPart) {
- ComputeScrollbarWidth();
+ UpdateScrollbarWidth();
SetHeight(LayoutUnit(scrollbar_->Height()));
} else {
SetWidth(LayoutUnit(scrollbar_->Width()));
- ComputeScrollbarHeight();
+ UpdateScrollbarHeight();
}
}
-int LayoutScrollbarPart::CalcScrollbarThicknessUsing(SizeType size_type,
- const Length& length,
- int containing_length) {
+static int CalcScrollbarThicknessUsing(SizeType size_type,
+ const Length& length,
+ int containing_length,
+ ScrollbarTheme* theme) {
if (!length.IsIntrinsicOrAuto() || (size_type == kMinSize && length.IsAuto()))
return MinimumValueForLength(length, LayoutUnit(containing_length)).ToInt();
- return scrollbar_->GetTheme().ScrollbarThickness();
+ return theme->ScrollbarThickness();
}
-void LayoutScrollbarPart::ComputeScrollbarWidth() {
- if (!scrollbar_->StyleSource())
+int LayoutScrollbarPart::ComputeScrollbarWidth(int visible_size,
+ const ComputedStyle* style) {
+ LayoutScrollbarTheme* theme = LayoutScrollbarTheme::GetLayoutScrollbarTheme();
+ int w = CalcScrollbarThicknessUsing(kMainOrPreferredSize, style->Width(),
+ visible_size, theme);
+ int min_width = CalcScrollbarThicknessUsing(kMinSize, style->MinWidth(),
+ visible_size, theme);
+ int max_width = w;
+ if (!style->MaxWidth().IsMaxSizeNone()) {
+ max_width = CalcScrollbarThicknessUsing(kMaxSize, style->MaxWidth(),
+ visible_size, theme);
+ }
+
+ return std::max(min_width, std::min(max_width, w));
+}
+
+int LayoutScrollbarPart::ComputeScrollbarHeight(int visible_size,
+ const ComputedStyle* style) {
+ LayoutScrollbarTheme* theme = LayoutScrollbarTheme::GetLayoutScrollbarTheme();
+ int h = CalcScrollbarThicknessUsing(kMainOrPreferredSize, style->Height(),
+ visible_size, theme);
+ int min_height = CalcScrollbarThicknessUsing(kMinSize, style->MinHeight(),
+ visible_size, theme);
+ int max_height = h;
+ if (!style->MaxHeight().IsMaxSizeNone()) {
+ max_height = CalcScrollbarThicknessUsing(kMaxSize, style->MaxHeight(),
+ visible_size, theme);
+ }
+ return std::max(min_height, std::min(max_height, h));
+}
+
+void LayoutScrollbarPart::UpdateScrollbarWidth() {
+ LayoutBox* box = scrollbar_->GetScrollableArea()->GetLayoutBox();
+ if (!box)
return;
// FIXME: We are querying layout information but nothing guarantees that it's
// up to date, especially since we are called at style change.
// FIXME: Querying the style's border information doesn't work on table cells
// with collapsing borders.
- int visible_size = scrollbar_->StyleSource()->Size().Width() -
- scrollbar_->StyleSource()->Style()->BorderLeftWidth() -
- scrollbar_->StyleSource()->Style()->BorderRightWidth();
- int w = CalcScrollbarThicknessUsing(kMainOrPreferredSize, Style()->Width(),
- visible_size);
- int min_width =
- CalcScrollbarThicknessUsing(kMinSize, Style()->MinWidth(), visible_size);
- int max_width = Style()->MaxWidth().IsMaxSizeNone()
- ? w
- : CalcScrollbarThicknessUsing(
- kMaxSize, Style()->MaxWidth(), visible_size);
- SetWidth(LayoutUnit(std::max(min_width, std::min(max_width, w))));
+ int visible_size = box->Size().Width() - box->Style()->BorderLeftWidth() -
+ box->Style()->BorderRightWidth();
+ SetWidth(LayoutUnit(ComputeScrollbarWidth(visible_size, Style())));
// Buttons and track pieces can all have margins along the axis of the
// scrollbar. Values are rounded because scrollbar parts need to be rendered
@@ -156,25 +180,17 @@ void LayoutScrollbarPart::ComputeScrollbarWidth() {
.Round()));
}
-void LayoutScrollbarPart::ComputeScrollbarHeight() {
- if (!scrollbar_->StyleSource())
+void LayoutScrollbarPart::UpdateScrollbarHeight() {
+ LayoutBox* box = scrollbar_->GetScrollableArea()->GetLayoutBox();
+ if (!box)
return;
// FIXME: We are querying layout information but nothing guarantees that it's
// up to date, especially since we are called at style change.
// FIXME: Querying the style's border information doesn't work on table cells
// with collapsing borders.
- int visible_size = scrollbar_->StyleSource()->Size().Height() -
- scrollbar_->StyleSource()->Style()->BorderTopWidth() -
- scrollbar_->StyleSource()->Style()->BorderBottomWidth();
- int h = CalcScrollbarThicknessUsing(kMainOrPreferredSize, Style()->Height(),
- visible_size);
- int min_height =
- CalcScrollbarThicknessUsing(kMinSize, Style()->MinHeight(), visible_size);
- int max_height = Style()->MaxHeight().IsMaxSizeNone()
- ? h
- : CalcScrollbarThicknessUsing(
- kMaxSize, Style()->MaxHeight(), visible_size);
- SetHeight(LayoutUnit(std::max(min_height, std::min(max_height, h))));
+ int visible_size = box->Size().Height() - box->Style()->BorderTopWidth() -
+ box->Style()->BorderBottomWidth();
+ SetHeight(LayoutUnit(ComputeScrollbarHeight(visible_size, Style())));
// Buttons and track pieces can all have margins along the axis of the
// scrollbar. Values are rounded because scrollbar parts need to be rendered
@@ -221,10 +237,6 @@ void LayoutScrollbarPart::ImageChanged(WrappedImagePtr image,
LayoutBlock::ImageChanged(image, defer, rect);
}
-LayoutObject* LayoutScrollbarPart::ScrollbarStyleSource() const {
- return (!scrollbar_) ? nullptr : scrollbar_->StyleSource();
-}
-
void LayoutScrollbarPart::SetNeedsPaintInvalidation() {
if (scrollbar_) {
scrollbar_->SetNeedsPaintInvalidation(kAllParts);
@@ -233,13 +245,6 @@ void LayoutScrollbarPart::SetNeedsPaintInvalidation() {
// This LayoutScrollbarPart is a scroll corner or a resizer.
DCHECK_EQ(part_, kNoPart);
- if (LocalFrameView* frame_view = View()->GetFrameView()) {
- if (frame_view->IsFrameViewScrollCorner(this)) {
- frame_view->SetScrollCornerNeedsPaintInvalidation();
- return;
- }
- }
-
scrollable_area_->SetScrollCornerNeedsPaintInvalidation();
}
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_part.h b/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_part.h
index 3903e7dc99f..d16bd3fb68e 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_part.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_part.h
@@ -47,6 +47,9 @@ class LayoutScrollbarPart final : public LayoutBlock {
void UpdateLayout() override;
+ static int ComputeScrollbarWidth(int visible_size, const ComputedStyle*);
+ static int ComputeScrollbarHeight(int visible_size, const ComputedStyle*);
+
// Scrollbar parts needs to be rendered at device pixel boundaries.
LayoutUnit MarginTop() const override {
DCHECK(IsIntegerValue(LayoutBlock::MarginTop()));
@@ -69,7 +72,7 @@ class LayoutScrollbarPart final : public LayoutBlock {
return type == kLayoutObjectLayoutScrollbarPart ||
LayoutBlock::IsOfType(type);
}
- LayoutObject* ScrollbarStyleSource() const;
+ ScrollableArea* GetScrollableArea() const { return scrollable_area_; }
// Must call setStyleWithWritingModeOfParent() instead.
void SetStyle(scoped_refptr<ComputedStyle>) = delete;
@@ -100,11 +103,8 @@ class LayoutScrollbarPart final : public LayoutBlock {
void LayoutHorizontalPart();
void LayoutVerticalPart();
- void ComputeScrollbarWidth();
- void ComputeScrollbarHeight();
- int CalcScrollbarThicknessUsing(SizeType,
- const Length&,
- int containing_length);
+ void UpdateScrollbarWidth();
+ void UpdateScrollbarHeight();
void SetNeedsPaintInvalidation();
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_theme.h b/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_theme.h
index 053df443971..fe60d6d1e0e 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_theme.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_scrollbar_theme.h
@@ -60,11 +60,11 @@ class LayoutScrollbarTheme final : public ScrollbarTheme {
.ShouldSnapBackToDragOrigin(scrollbar, event);
}
- double InitialAutoscrollTimerDelay() override {
+ TimeDelta InitialAutoscrollTimerDelay() override {
return ScrollbarTheme::DeprecatedStaticGetTheme()
.InitialAutoscrollTimerDelay();
}
- double AutoscrollTimerDelay() override {
+ TimeDelta AutoscrollTimerDelay() override {
return ScrollbarTheme::DeprecatedStaticGetTheme().AutoscrollTimerDelay();
}
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_table.cc b/chromium/third_party/blink/renderer/core/layout/layout_table.cc
index 0e1dfe389a5..d1231377016 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_table.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_table.cc
@@ -92,6 +92,8 @@ void LayoutTable::StyleDidChange(StyleDifference diff,
// In the collapsed border model, there is no cell spacing.
h_spacing_ = ShouldCollapseBorders() ? 0 : Style()->HorizontalBorderSpacing();
v_spacing_ = ShouldCollapseBorders() ? 0 : Style()->VerticalBorderSpacing();
+ DCHECK_GE(h_spacing_, 0);
+ DCHECK_GE(v_spacing_, 0);
if (!table_layout_ ||
Style()->IsFixedTableLayout() != old_fixed_table_layout) {
@@ -1006,9 +1008,13 @@ void LayoutTable::ComputePreferredLogicalWidths() {
table_layout_->ApplyPreferredLogicalWidthQuirks(min_preferred_logical_width_,
max_preferred_logical_width_);
- for (unsigned i = 0; i < captions_.size(); i++)
+ for (unsigned i = 0; i < captions_.size(); i++) {
min_preferred_logical_width_ = std::max(
min_preferred_logical_width_, captions_[i]->MinPreferredLogicalWidth());
+ // Note: using captions' min-width is intentional here:
+ max_preferred_logical_width_ = std::max(
+ max_preferred_logical_width_, captions_[i]->MinPreferredLogicalWidth());
+ }
const ComputedStyle& style_to_use = StyleRef();
// FIXME: This should probably be checking for isSpecified since you should be
@@ -1034,10 +1040,17 @@ void LayoutTable::ComputePreferredLogicalWidths() {
std::min(max_preferred_logical_width_,
AdjustContentBoxLogicalWidthForBoxSizing(
style_to_use.LogicalMaxWidth().Value()));
- max_preferred_logical_width_ =
- std::max(min_preferred_logical_width_, max_preferred_logical_width_);
}
+ // 2 cases need this:
+ // 1. When max_preferred_logical_width is shrunk to the specified max-width in
+ // the block above but max-width < min_preferred_logical_width.
+ // 2. We buggily calculate min > max for some tables with colspans and
+ // percent widths. See fast/table/spans-min-greater-than-max-crash.html and
+ // http://crbug.com/857185
+ max_preferred_logical_width_ =
+ std::max(min_preferred_logical_width_, max_preferred_logical_width_);
+
// FIXME: We should be adding borderAndPaddingLogicalWidth here, but
// m_tableLayout->computePreferredLogicalWidths already does, so a bunch of
// tests break doing this naively.
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_table.h b/chromium/third_party/blink/renderer/core/layout/layout_table.h
index 9008bf3a7b5..6b9835b310b 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_table.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_table.h
@@ -387,10 +387,11 @@ class CORE_EXPORT LayoutTable final : public LayoutBlock {
void AddColumn(const LayoutTableCol*);
void RemoveColumn(const LayoutTableCol*);
- void PaintBoxDecorationBackground(const PaintInfo&,
- const LayoutPoint&) const final;
+ void PaintBoxDecorationBackground(
+ const PaintInfo&,
+ const LayoutPoint& paint_offset) const final;
- void PaintMask(const PaintInfo&, const LayoutPoint&) const final;
+ void PaintMask(const PaintInfo&, const LayoutPoint& paint_offset) const final;
void SubtractCaptionRect(LayoutRect&) const;
@@ -422,9 +423,6 @@ class CORE_EXPORT LayoutTable final : public LayoutBlock {
return is_any_column_ever_collapsed_;
}
- // Expose for LayoutTableCol::LocalVisualRectIgnoringVisibility().
- using LayoutBlock::LocalVisualRectIgnoringVisibility;
-
protected:
void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
void SimplifiedNormalFlowLayout() override;
@@ -439,7 +437,8 @@ class CORE_EXPORT LayoutTable final : public LayoutBlock {
return type == kLayoutObjectTable || LayoutBlock::IsOfType(type);
}
- void PaintObject(const PaintInfo&, const LayoutPoint&) const override;
+ void PaintObject(const PaintInfo&,
+ const LayoutPoint& paint_offset) const override;
void UpdateLayout() override;
void ComputeIntrinsicLogicalWidths(LayoutUnit& min_width,
LayoutUnit& max_width) const override;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_table_box_component.cc b/chromium/third_party/blink/renderer/core/layout/layout_table_box_component.cc
index 49e4040afb9..03a3cc2cd04 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_table_box_component.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_table_box_component.cc
@@ -51,7 +51,7 @@ void LayoutTableBoxComponent::MutableForPainting::UpdatePaintResult(
auto& box = static_cast<LayoutTableBoxComponent&>(layout_object_);
if (box.last_paint_result_ != kFullyPainted &&
box.last_paint_rect_ != paint_rect)
- layout_object_.SetDisplayItemsUncached();
+ static_cast<const DisplayItemClient&>(layout_object_).Invalidate();
box.last_paint_result_ = paint_result;
box.last_paint_rect_ = paint_rect;
@@ -61,7 +61,8 @@ void LayoutTableBoxComponent::StyleDidChange(StyleDifference diff,
const ComputedStyle* old_style) {
LayoutBox::StyleDidChange(diff, old_style);
SetCanContainFixedPositionObjects(
- Style()->CanContainFixedPositionObjects(false));
+ Style()->CanContainFixedPositionObjects(false) ||
+ ShouldApplyPaintContainment());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_table_cell.cc b/chromium/third_party/blink/renderer/core/layout/layout_table_cell.cc
index 6663af368fd..e08a856cf69 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_table_cell.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_table_cell.cc
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/layout/collapsed_border_value.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_table_col.h"
#include "third_party/blink/renderer/core/layout/subtree_layout_scope.h"
#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
@@ -365,6 +366,21 @@ LayoutSize LayoutTableCell::OffsetFromContainerInternal(
return offset;
}
+void LayoutTableCell::SetIsSpanningCollapsedRow(bool spanning_collapsed_row) {
+ if (is_spanning_collapsed_row_ != spanning_collapsed_row) {
+ is_spanning_collapsed_row_ = spanning_collapsed_row;
+ SetShouldClipOverflow(ComputeShouldClipOverflow());
+ }
+}
+
+void LayoutTableCell::SetIsSpanningCollapsedColumn(
+ bool spanning_collapsed_column) {
+ if (is_spanning_collapsed_column_ != spanning_collapsed_column) {
+ is_spanning_collapsed_column_ = spanning_collapsed_column;
+ SetShouldClipOverflow(ComputeShouldClipOverflow());
+ }
+}
+
void LayoutTableCell::ComputeOverflow(LayoutUnit old_client_after_edge,
bool recompute_floats) {
LayoutBlockFlow::ComputeOverflow(old_client_after_edge, recompute_floats);
@@ -417,9 +433,9 @@ void LayoutTableCell::ComputeOverflow(LayoutUnit old_client_after_edge,
collapsed_border_values_->SetLocalVisualRect(rect);
}
-bool LayoutTableCell::ShouldClipOverflow() const {
+bool LayoutTableCell::ComputeShouldClipOverflow() const {
return IsSpanningCollapsedRow() || IsSpanningCollapsedColumn() ||
- LayoutBox::ShouldClipOverflow();
+ LayoutBox::ComputeShouldClipOverflow();
}
LayoutUnit LayoutTableCell::CellBaselinePosition() const {
@@ -519,9 +535,9 @@ CollapsedBorderValue LayoutTableCell::ComputeCollapsedStartBorder() const {
// For the start border, we need to check, in order of precedence:
// (1) Our start border.
const CSSProperty& start_color_property =
- ResolveBorderProperty(GetCSSPropertyWebkitBorderStartColor());
+ ResolveBorderProperty(GetCSSPropertyBorderInlineStartColor());
const CSSProperty& end_color_property =
- ResolveBorderProperty(GetCSSPropertyWebkitBorderEndColor());
+ ResolveBorderProperty(GetCSSPropertyBorderInlineEndColor());
CollapsedBorderValue result(BorderStartInTableDirection(),
ResolveColor(start_color_property),
kBorderPrecedenceCell);
@@ -652,9 +668,9 @@ CollapsedBorderValue LayoutTableCell::ComputeCollapsedEndBorder() const {
// For end border, we need to check, in order of precedence:
// (1) Our end border.
const CSSProperty& start_color_property =
- ResolveBorderProperty(GetCSSPropertyWebkitBorderStartColor());
+ ResolveBorderProperty(GetCSSPropertyBorderInlineStartColor());
const CSSProperty& end_color_property =
- ResolveBorderProperty(GetCSSPropertyWebkitBorderEndColor());
+ ResolveBorderProperty(GetCSSPropertyBorderInlineEndColor());
CollapsedBorderValue result = CollapsedBorderValue(
BorderEndInTableDirection(), ResolveColor(end_color_property),
kBorderPrecedenceCell);
@@ -777,9 +793,9 @@ CollapsedBorderValue LayoutTableCell::ComputeCollapsedBeforeBorder() const {
// For before border, we need to check, in order of precedence:
// (1) Our before border.
const CSSProperty& before_color_property =
- ResolveBorderProperty(GetCSSPropertyWebkitBorderBeforeColor());
+ ResolveBorderProperty(GetCSSPropertyBorderBlockStartColor());
const CSSProperty& after_color_property =
- ResolveBorderProperty(GetCSSPropertyWebkitBorderAfterColor());
+ ResolveBorderProperty(GetCSSPropertyBorderBlockEndColor());
CollapsedBorderValue result = CollapsedBorderValue(
Style()->BorderBeforeStyle(), Style()->BorderBeforeWidth(),
ResolveColor(before_color_property), kBorderPrecedenceCell);
@@ -908,9 +924,9 @@ CollapsedBorderValue LayoutTableCell::ComputeCollapsedAfterBorder() const {
// For after border, we need to check, in order of precedence:
// (1) Our after border.
const CSSProperty& before_color_property =
- ResolveBorderProperty(GetCSSPropertyWebkitBorderBeforeColor());
+ ResolveBorderProperty(GetCSSPropertyBorderBlockStartColor());
const CSSProperty& after_color_property =
- ResolveBorderProperty(GetCSSPropertyWebkitBorderAfterColor());
+ ResolveBorderProperty(GetCSSPropertyBorderBlockEndColor());
CollapsedBorderValue result = CollapsedBorderValue(
Style()->BorderAfterStyle(), Style()->BorderAfterWidth(),
ResolveColor(after_color_property), kBorderPrecedenceCell);
@@ -1048,11 +1064,6 @@ bool LayoutTableCell::IsFirstColumnCollapsed() const {
return Table()->IsAbsoluteColumnCollapsed(AbsoluteColumnIndex());
}
-void LayoutTableCell::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
- TableCellPainter(*this).Paint(paint_info, paint_offset);
-}
-
void LayoutTableCell::UpdateCollapsedBorderValues() const {
bool changed = false;
@@ -1147,20 +1158,23 @@ void LayoutTableCell::ScrollbarsChanged(bool horizontal_scrollbar_changed,
}
}
-LayoutTableCell* LayoutTableCell::CreateAnonymous(Document* document) {
- LayoutTableCell* layout_object = new LayoutTableCell(nullptr);
+LayoutTableCell* LayoutTableCell::CreateAnonymous(
+ Document* document,
+ scoped_refptr<ComputedStyle> style) {
+ LayoutTableCell* layout_object =
+ LayoutObjectFactory::CreateTableCell(*document, *style);
layout_object->SetDocumentForAnonymous(document);
+ layout_object->SetStyle(std::move(style));
return layout_object;
}
LayoutTableCell* LayoutTableCell::CreateAnonymousWithParent(
const LayoutObject* parent) {
- LayoutTableCell* new_cell =
- LayoutTableCell::CreateAnonymous(&parent->GetDocument());
scoped_refptr<ComputedStyle> new_style =
ComputedStyle::CreateAnonymousStyleWithDisplay(parent->StyleRef(),
EDisplay::kTableCell);
- new_cell->SetStyle(std::move(new_style));
+ LayoutTableCell* new_cell = LayoutTableCell::CreateAnonymous(
+ &parent->GetDocument(), std::move(new_style));
return new_cell;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_table_cell.h b/chromium/third_party/blink/renderer/core/layout/layout_table_cell.h
index ef20ef0213d..859bb4f7c4c 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_table_cell.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_table_cell.h
@@ -197,8 +197,6 @@ class CORE_EXPORT LayoutTableCell : public LayoutBlockFlow {
void UpdateLayout() override;
- void Paint(const PaintInfo&, const LayoutPoint&) const override;
-
LayoutUnit CellBaselinePosition() const;
bool IsBaselineAligned() const {
EVerticalAlign va = Style()->VerticalAlign();
@@ -237,7 +235,8 @@ class CORE_EXPORT LayoutTableCell : public LayoutBlockFlow {
cell_children_need_layout_ = b;
}
- static LayoutTableCell* CreateAnonymous(Document*);
+ static LayoutTableCell* CreateAnonymous(Document*,
+ scoped_refptr<ComputedStyle>);
static LayoutTableCell* CreateAnonymousWithParent(const LayoutObject*);
LayoutBox* CreateAnonymousBoxWithSameTypeAs(
const LayoutObject* parent) const override {
@@ -332,15 +331,11 @@ class CORE_EXPORT LayoutTableCell : public LayoutBlockFlow {
other->RowIndex() + other->ResolvedRowSpan();
}
- void SetIsSpanningCollapsedRow(bool spanningCollapsedRow) {
- is_spanning_collapsed_row_ = spanningCollapsedRow;
- }
+ void SetIsSpanningCollapsedRow(bool spanning_collapsed_row);
bool IsSpanningCollapsedRow() const { return is_spanning_collapsed_row_; }
- void SetIsSpanningCollapsedColumn(bool spanningCollapsedColumn) {
- is_spanning_collapsed_column_ = spanningCollapsedColumn;
- }
+ void SetIsSpanningCollapsedColumn(bool spanningCollapsedColumn);
bool IsSpanningCollapsedColumn() const {
return is_spanning_collapsed_column_;
@@ -380,11 +375,13 @@ class CORE_EXPORT LayoutTableCell : public LayoutBlockFlow {
void UpdateLogicalWidth() override;
- void PaintBoxDecorationBackground(const PaintInfo&,
- const LayoutPoint&) const override;
- void PaintMask(const PaintInfo&, const LayoutPoint&) const override;
+ void PaintBoxDecorationBackground(
+ const PaintInfo&,
+ const LayoutPoint& paint_offset) const override;
+ void PaintMask(const PaintInfo&,
+ const LayoutPoint& paint_offset) const override;
- bool ShouldClipOverflow() const override;
+ bool ComputeShouldClipOverflow() const override;
using CollapsedBorderValuesMethod =
const CollapsedBorderValue& (CollapsedBorderValues::*)() const;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_table_cell_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_table_cell_test.cc
index 74cc3ee423d..3647756046d 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_table_cell_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_table_cell_test.cc
@@ -34,7 +34,9 @@ class LayoutTableCellDeathTest : public RenderingTest {
protected:
void SetUp() override {
RenderingTest::SetUp();
- cell_ = LayoutTableCell::CreateAnonymous(&GetDocument());
+ auto style = ComputedStyle::Create();
+ style->SetDisplay(EDisplay::kTableCell);
+ cell_ = LayoutTableCell::CreateAnonymous(&GetDocument(), std::move(style));
}
void TearDown() override {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_table_col.cc b/chromium/third_party/blink/renderer/core/layout/layout_table_col.cc
index f30f7ce3266..d24abbb60c7 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_table_col.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_table_col.cc
@@ -108,25 +108,10 @@ bool LayoutTableCol::CanHaveChildren() const {
return IsTableColumnGroup();
}
-LayoutRect LayoutTableCol::LocalVisualRectIgnoringVisibility() const {
- // On SPv175, raster invalidation is based on paint result. LayoutTableCol
- // paints nothing (its background is painted by LayoutTableSection) so should
- // not issue any raster invalidation.
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return LayoutRect();
-
- // Entire table gets invalidated, instead of invalidating
- // every cell in the column. This is simpler, but suboptimal.
-
- LayoutTable* table = Table();
- if (!table)
- return LayoutRect();
-
- // The correctness of this method depends on the fact that LayoutTableCol's
- // location is always zero.
- DCHECK(Location() == LayoutPoint());
-
- return table->LocalVisualRectIgnoringVisibility();
+bool LayoutTableCol::PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const {
+ // LayoutTableCol paints nothing by itself. Its background is painted by
+ // LayoutTableSection.
+ return true;
}
void LayoutTableCol::ClearPreferredLogicalWidthsDirtyBits() {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_table_col.h b/chromium/third_party/blink/renderer/core/layout/layout_table_col.h
index 13845769221..2496e1b4f6f 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_table_col.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_table_col.h
@@ -95,7 +95,7 @@ class LayoutTableCol final : public LayoutTableBoxComponent {
bool CanHaveChildren() const override;
PaintLayerType LayerTypeRequired() const override { return kNoPaintLayer; }
- LayoutRect LocalVisualRectIgnoringVisibility() const final;
+ bool PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const final;
void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_table_col_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_table_col_test.cc
index 354b5227830..20df3f2a685 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_table_col_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_table_col_test.cc
@@ -5,36 +5,12 @@
#include "third_party/blink/renderer/core/layout/layout_table_col.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 blink {
using LayoutTableColTest = RenderingTest;
-TEST_F(LayoutTableColTest, LocalVisualRectSPv1) {
- ScopedSlimmingPaintV175ForTest spv175(false);
- SetBodyInnerHTML(R"HTML(
- <table id='table' style='width: 200px; height: 200px'>
- <col id='col1' style='visibility: hidden'>
- <col id='col2' style='visibility: collapse'>
- <col id='col3'>
- <tr><td></td><td></td></tr>
- </table>
- )HTML");
-
- auto table_local_visual_rect =
- GetLayoutObjectByElementId("table")->LocalVisualRect();
- EXPECT_NE(LayoutRect(), table_local_visual_rect);
- EXPECT_EQ(table_local_visual_rect,
- GetLayoutObjectByElementId("col1")->LocalVisualRect());
- EXPECT_EQ(table_local_visual_rect,
- GetLayoutObjectByElementId("col2")->LocalVisualRect());
- EXPECT_EQ(table_local_visual_rect,
- GetLayoutObjectByElementId("col3")->LocalVisualRect());
-}
-
-TEST_F(LayoutTableColTest, LocalVisualRectSPv175) {
- ScopedSlimmingPaintV175ForTest spv175(true);
+TEST_F(LayoutTableColTest, LocalVisualRect) {
SetBodyInnerHTML(R"HTML(
<table style='width: 200px; height: 200px'>
<col id='col1' style='visibility: hidden'>
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_table_row.cc b/chromium/third_party/blink/renderer/core/layout/layout_table_row.cc
index 7291dc3f1a9..a8f12d0d977 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_table_row.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_table_row.cc
@@ -266,9 +266,8 @@ LayoutBox::PaginationBreakability LayoutTableRow::GetPaginationBreakability()
return breakability;
}
-void LayoutTableRow::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
- TableRowPainter(*this).Paint(paint_info, paint_offset);
+void LayoutTableRow::Paint(const PaintInfo& paint_info) const {
+ TableRowPainter(*this).Paint(paint_info);
}
LayoutTableRow* LayoutTableRow::CreateAnonymous(Document* document) {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_table_row.h b/chromium/third_party/blink/renderer/core/layout/layout_table_row.h
index ccb43ef8577..649d16a7862 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_table_row.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_table_row.h
@@ -148,7 +148,7 @@ class CORE_EXPORT LayoutTableRow final : public LayoutTableBoxComponent {
return kNoPaintLayer;
}
- void Paint(const PaintInfo&, const LayoutPoint&) const override;
+ void Paint(const PaintInfo&) const override;
void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
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 7cd66cfba55..94b85608727 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
@@ -958,6 +958,7 @@ int LayoutTableSection::CalcRowLogicalHeight() {
total_collapsed_height += row_collapsed_height_[r];
// Adjust row position according to the height collapsed so far.
row_pos_[r + 1] -= total_collapsed_height;
+ DCHECK_GE(row_pos_[r + 1], row_pos_[r]);
}
}
@@ -1186,13 +1187,21 @@ void LayoutTableSection::LayoutRows() {
if (LayoutTableRow* row = grid_[r].row) {
row->SetLogicalLocation(LayoutPoint(0, row_pos_[r]));
row->SetLogicalWidth(LogicalWidth());
- LayoutUnit row_logical_height(row_pos_[r + 1] - row_pos_[r] - vspacing);
+ LayoutUnit row_logical_height;
+ // If the row is collapsed then it has 0 height. vspacing was implicitly
+ // removed earlier, when row_pos_[r+1] was set to row_pos[r].
+ if (!RowHasVisibilityCollapse(r)) {
+ row_logical_height =
+ LayoutUnit(row_pos_[r + 1] - row_pos_[r] - vspacing);
+ }
+ DCHECK_GE(row_logical_height, 0);
if (state.IsPaginated() && r + 1 < total_rows) {
// If the next row has a pagination strut, we need to subtract it. It
// should not be included in this row's height.
if (LayoutTableRow* next_row_object = grid_[r + 1].row)
row_logical_height -= next_row_object->PaginationStrut();
}
+ DCHECK_GE(row_logical_height, 0);
row->SetLogicalHeight(row_logical_height);
row->UpdateAfterLayout();
}
@@ -1480,9 +1489,8 @@ LayoutUnit LayoutTableSection::FirstLineBoxBaseline() const {
return first_line_baseline;
}
-void LayoutTableSection::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
- TableSectionPainter(*this).Paint(paint_info, paint_offset);
+void LayoutTableSection::Paint(const PaintInfo& paint_info) const {
+ TableSectionPainter(*this).Paint(paint_info);
}
LayoutRect LayoutTableSection::LogicalRectForWritingModeAndDirection(
@@ -2024,8 +2032,20 @@ void LayoutTableSection::AdjustRowForPagination(LayoutTableRow& row_object,
pagination_strut -= offset_from_top_of_page.ToInt();
// If we have a header group we will paint it at the top of each page,
- // move the rows down to accomodate it.
- pagination_strut += OffsetForRepeatedHeader();
+ // move the rows down to accommodate it.
+ int additional_adjustment = OffsetForRepeatedHeader();
+
+ // If the table collapses borders, push the row down by the max height of the
+ // outer half borders to make the whole collapsed borders on the next page.
+ if (Table()->ShouldCollapseBorders()) {
+ for (const auto* cell = row_object.FirstCell(); cell;
+ cell = cell->NextCell()) {
+ additional_adjustment = std::max<int>(additional_adjustment,
+ cell->CollapsedOuterBorderBefore());
+ }
+ }
+
+ pagination_strut += additional_adjustment;
row_object.SetPaginationStrut(LayoutUnit(pagination_strut));
// We have inserted a pagination strut before the row. Adjust the logical top
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_table_section.h b/chromium/third_party/blink/renderer/core/layout/layout_table_section.h
index bb5db5e64b1..bbea621101c 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_table_section.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_table_section.h
@@ -225,7 +225,7 @@ class CORE_EXPORT LayoutTableSection final : public LayoutTableBoxComponent {
return CreateAnonymousWithParent(parent);
}
- void Paint(const PaintInfo&, const LayoutPoint&) const override;
+ void Paint(const PaintInfo&) const override;
// Flip the rect so it aligns with the coordinates used by the rowPos and
// columnPos vectors.
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_table_section_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_table_section_test.cc
index 03586abac72..78a184c9b6d 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_table_section_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_table_section_test.cc
@@ -383,6 +383,22 @@ TEST_F(LayoutTableSectionTest, OverflowingCells) {
EXPECT_EQ(big_section->FullTableEffectiveColumnSpan(), columns);
}
+TEST_F(LayoutTableSectionTest, RowCollapseNegativeHeightCrash) {
+ // Table % height triggers the heuristic check for relayout of cells at
+ // https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/layout/layout_table_section.cc?rcl=5ea6fa63d8809f990d662182d971facbf557f812&l=1899
+ // Cell child needs a % height to set cell_children_flex at line 1907, which
+ // caused a negative override height to get set at 1929, which DCHECKed.
+ SetBodyInnerHTML(R"HTML(
+ <table style="height:50%">
+ <tr style="visibility:collapse">
+ <td>
+ <div style="height:50%"></div>
+ </td>
+ </tr>
+ </table>
+ )HTML");
+}
+
} // anonymous namespace
} // namespace blink
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 f5f6ed18829..bb8a4d4515e 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_text.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_text.cc
@@ -28,7 +28,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_thread.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
@@ -50,6 +50,7 @@
#include "third_party/blink/renderer/core/layout/line/glyph_overflow.h"
#include "third_party/blink/renderer/core/layout/line/inline_text_box.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_logical_rect.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h"
@@ -97,7 +98,9 @@ class SecureTextTimer final : public TimerBase {
void RestartWithNewText(unsigned last_typed_character_offset) {
last_typed_character_offset_ = last_typed_character_offset;
if (Settings* settings = layout_text_->GetDocument().GetSettings()) {
- StartOneShot(settings->GetPasswordEchoDurationInSeconds(), FROM_HERE);
+ StartOneShot(
+ TimeDelta::FromSecondsD(settings->GetPasswordEchoDurationInSeconds()),
+ FROM_HERE);
}
}
void Invalidate() { last_typed_character_offset_ = -1; }
@@ -680,7 +683,9 @@ PositionWithAffinity LayoutText::PositionForPoint(
if (LineDirectionPointFitsInBox(point_line_direction.ToInt(), box,
should_affinity_be_downstream)) {
return CreatePositionWithAffinityForBoxAfterAdjustingOffsetForBiDi(
- box, box->OffsetForPosition(point_line_direction),
+ box,
+ box->OffsetForPosition(point_line_direction, IncludePartialGlyphs,
+ BreakGlyphs),
should_affinity_be_downstream);
}
}
@@ -694,7 +699,9 @@ PositionWithAffinity LayoutText::PositionForPoint(
should_affinity_be_downstream);
return CreatePositionWithAffinityForBoxAfterAdjustingOffsetForBiDi(
last_box,
- last_box->OffsetForPosition(point_line_direction) + last_box->Start(),
+ last_box->OffsetForPosition(point_line_direction, IncludePartialGlyphs,
+ BreakGlyphs) +
+ last_box->Start(),
should_affinity_be_downstream);
}
return CreatePositionWithAffinity(0);
@@ -1033,7 +1040,7 @@ static float MaxWordFragmentWidth(LayoutText* layout_text,
return 0;
float minimum_fragment_width_to_consider =
- Hyphenation::MinimumPrefixWidth(font);
+ font.GetFontDescription().MinimumPrefixWidthToHyphenate();
float max_fragment_width = 0;
TextRun run = ConstructTextRun(font, layout_text, word_offset, word_length,
style, text_direction);
@@ -1451,7 +1458,7 @@ UChar32 LayoutText::LastCharacterAfterWhitespaceCollapsing() const {
}
FloatPoint LayoutText::FirstRunOrigin() const {
- return IntPoint(FirstRunX(), FirstRunY());
+ return FloatPoint(FirstRunX(), FirstRunY());
}
float LayoutText::FirstRunX() const {
@@ -1902,7 +1909,7 @@ LayoutRect LayoutText::LocalSelectionRect() const {
if (status.start == status.end)
continue;
NGPhysicalOffsetRect fragment_rect =
- fragment->ComputeLocalSelectionRect(status);
+ fragment->ComputeLocalSelectionRectForText(status);
fragment_rect.offset += fragment->InlineOffsetToContainerBox();
rect.Unite(fragment_rect.ToLayoutRect());
}
@@ -2214,8 +2221,18 @@ void LayoutText::MomentarilyRevealLastTypedCharacter(
}
scoped_refptr<AbstractInlineTextBox> LayoutText::FirstAbstractInlineTextBox() {
- return AbstractInlineTextBox::GetOrCreate(LineLayoutText(this),
- FirstTextBox());
+ if (RuntimeEnabledFeatures::LayoutNGEnabled()) {
+ LayoutObject* const first_letter_part = GetFirstLetterPart();
+ auto fragments = NGPaintFragment::InlineFragmentsFor(
+ first_letter_part ? first_letter_part : this);
+ if (!fragments.IsEmpty() &&
+ fragments.IsInLayoutNGInlineFormattingContext()) {
+ return NGAbstractInlineTextBox::GetOrCreate(LineLayoutText(this),
+ **fragments.begin());
+ }
+ }
+ return LegacyAbstractInlineTextBox::GetOrCreate(LineLayoutText(this),
+ FirstTextBox());
}
void LayoutText::InvalidateDisplayItemClients(
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 6fac55a2ad1..c5773395249 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_text.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_text.h
@@ -94,6 +94,9 @@ class CORE_EXPORT LayoutText : public LayoutObject {
virtual unsigned TextStartOffset() const { return 0; }
String PlainText() const;
+ // Returns first letter part of |LayoutTextFragment|.
+ virtual LayoutText* GetFirstLetterPart() const { return nullptr; }
+
InlineTextBox* CreateInlineTextBox(int start, unsigned short length);
void DirtyOrDeleteLineBoxesIfNeeded(bool full_layout);
void DirtyLineBoxes();
@@ -201,6 +204,9 @@ class CORE_EXPORT LayoutText : public LayoutObject {
const InlineTextBoxList& TextBoxes() const { return text_boxes_; }
+ // Returns first |InlineTextBox| produces for associated |Node|.
+ // Note: When |this| is remaining part of ::first-letter, this function
+ // returns first-letter part of |InlineTextBox| instead of remaining part.
InlineTextBox* FirstTextBox() const { return text_boxes_.First(); }
InlineTextBox* LastTextBox() const { return text_boxes_.Last(); }
@@ -266,6 +272,9 @@ class CORE_EXPORT LayoutText : public LayoutObject {
void AutosizingMultiplerChanged() {
known_to_have_no_overflow_and_no_fallback_fonts_ = false;
+
+ // The font size is changing, so we need to make sure to rebuild everything.
+ valid_ng_items_ = false;
}
OnlyWhitespaceOrNbsp ContainsOnlyWhitespaceOrNbsp() const;
@@ -325,7 +334,7 @@ class CORE_EXPORT LayoutText : public LayoutObject {
unsigned length() const final { return TextLength(); }
// See the class comment as to why we shouldn't call this function directly.
- void Paint(const PaintInfo&, const LayoutPoint&) const final { NOTREACHED(); }
+ void Paint(const PaintInfo&) const final { NOTREACHED(); }
void UpdateLayout() final { NOTREACHED(); }
bool NodeAtPoint(HitTestResult&,
const HitTestLocation&,
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_text_combine.h b/chromium/third_party/blink/renderer/core/layout/layout_text_combine.h
index 2afca4e195c..9ad8dc9fa11 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_text_combine.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_text_combine.h
@@ -26,6 +26,8 @@
namespace blink {
+class GraphicsContext;
+
// LayoutTextCombine uses different coordinate systems for layout and
// inlineTextBox, because it is treated as 1em-box character in vertical flow
// for the layout, while its inline box is in horizontal flow.
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 986814a2177..5799f09fddd 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
@@ -64,7 +64,7 @@ void LayoutTextControl::StyleDidChange(StyleDifference diff,
// ::selection style is or was present on LayoutTextControl.
if (StyleRef().HasPseudoStyle(kPseudoIdSelection) ||
(old_style && old_style->HasPseudoStyle(kPseudoIdSelection))) {
- inner_editor_layout_object->InvalidateSelectionOfSelectedChildren();
+ inner_editor_layout_object->InvalidateSelectedChildrenOnStyleChange();
}
}
GetTextControlElement()->UpdatePlaceholderVisibility();
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc b/chromium/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc
index 6263ec7939b..f01b6cd9f56 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc
@@ -34,12 +34,8 @@
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
#include "third_party/blink/renderer/core/layout/layout_analyzer.h"
#include "third_party/blink/renderer/core/layout/layout_theme.h"
-#include "third_party/blink/renderer/core/paint/adjust_paint_offset_scope.h"
-#include "third_party/blink/renderer/core/paint/paint_info.h"
-#include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/core/paint/theme_painter.h"
+#include "third_party/blink/renderer/core/paint/text_control_single_line_painter.h"
#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
-#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
namespace blink {
@@ -67,37 +63,8 @@ inline HTMLElement* LayoutTextControlSingleLine::InnerSpinButtonElement()
ShadowElementNames::SpinButton()));
}
-// TODO(wangxianzhu): Move this into TextControlSingleLinePainter.
-void LayoutTextControlSingleLine::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
- LayoutTextControl::Paint(paint_info, paint_offset);
-
- if (ShouldPaintSelfBlockBackground(paint_info.phase) &&
- should_draw_caps_lock_indicator_) {
- // TODO(wangxianzhu): This display item may have conflicting id with the
- // normal background. Should we allocate another DisplayItem::Type?
- if (DrawingRecorder::UseCachedDrawingIfPossible(paint_info.context, *this,
- paint_info.phase))
- return;
-
- LayoutRect contents_rect = ContentBoxRect();
-
- // Center in the block progression direction.
- if (IsHorizontalWritingMode())
- contents_rect.SetY((Size().Height() - contents_rect.Height()) / 2);
- else
- contents_rect.SetX((Size().Width() - contents_rect.Width()) / 2);
-
- // Convert the rect into the coords used for painting the content.
- AdjustPaintOffsetScope adjustment(*this, paint_info, paint_offset);
- const auto& local_paint_info = adjustment.GetPaintInfo();
- contents_rect.MoveBy(adjustment.AdjustedPaintOffset());
- IntRect snapped_rect = PixelSnappedIntRect(contents_rect);
- DrawingRecorder recorder(local_paint_info.context, *this,
- local_paint_info.phase);
- LayoutTheme::GetTheme().Painter().PaintCapsLockIndicator(
- *this, local_paint_info, snapped_rect);
- }
+void LayoutTextControlSingleLine::Paint(const PaintInfo& paint_info) const {
+ TextControlSingleLinePainter(*this).Paint(paint_info);
}
void LayoutTextControlSingleLine::UpdateLayout() {
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_text_control_single_line.h b/chromium/third_party/blink/renderer/core/layout/layout_text_control_single_line.h
index c849f746f54..02347ad00e6 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_text_control_single_line.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_text_control_single_line.h
@@ -37,6 +37,9 @@ class LayoutTextControlSingleLine : public LayoutTextControl {
~LayoutTextControlSingleLine() override;
void CapsLockStateMayHaveChanged();
+ bool ShouldDrawCapsLockIndicator() const {
+ return should_draw_caps_lock_indicator_;
+ }
protected:
Element* ContainerElement() const;
@@ -50,7 +53,7 @@ class LayoutTextControlSingleLine : public LayoutTextControl {
return type == kLayoutObjectTextField || LayoutTextControl::IsOfType(type);
}
- void Paint(const PaintInfo&, const LayoutPoint&) const override;
+ void Paint(const PaintInfo&) const override;
void UpdateLayout() override;
bool NodeAtPoint(HitTestResult&,
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_text_fragment.cc b/chromium/third_party/blink/renderer/core/layout/layout_text_fragment.cc
index 41153d33ddc..1e34a60f88c 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_text_fragment.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_text_fragment.cc
@@ -160,8 +160,21 @@ Text* LayoutTextFragment::AssociatedTextNode() const {
return (node && node->IsTextNode()) ? ToText(node) : nullptr;
}
+LayoutText* LayoutTextFragment::GetFirstLetterPart() const {
+ if (!is_remaining_text_layout_object_)
+ return nullptr;
+ // Node: We assume first letter pseudo element has only one child and it
+ // is LayoutTextFragment.
+ LayoutObject* const first_letter_container =
+ GetFirstLetterPseudoElement()->GetLayoutObject();
+ LayoutObject* const child = first_letter_container->SlowFirstChild();
+ CHECK(child->IsText());
+ DCHECK_EQ(child, first_letter_container->SlowLastChild());
+ return ToLayoutTextFragment(child);
+}
+
void LayoutTextFragment::UpdateHitTestResult(HitTestResult& result,
- const LayoutPoint& point) {
+ const LayoutPoint& point) const {
if (result.InnerNode())
return;
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_text_fragment.h b/chromium/third_party/blink/renderer/core/layout/layout_text_fragment.h
index 3782d3d41f6..42bcacb1f1f 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_text_fragment.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_text_fragment.h
@@ -94,6 +94,7 @@ class CORE_EXPORT LayoutTextFragment final : public LayoutText {
}
Text* AssociatedTextNode() const;
+ LayoutText* GetFirstLetterPart() const override;
protected:
void WillBeDestroyed() override;
@@ -102,7 +103,7 @@ class CORE_EXPORT LayoutTextFragment final : public LayoutText {
LayoutBlock* BlockForAccompanyingFirstLetter() const;
UChar PreviousCharacter() const override;
- void UpdateHitTestResult(HitTestResult&, const LayoutPoint&) override;
+ void UpdateHitTestResult(HitTestResult&, const LayoutPoint&) const override;
unsigned start_;
unsigned fragment_length_;
@@ -116,8 +117,8 @@ class CORE_EXPORT LayoutTextFragment final : public LayoutText {
DEFINE_TYPE_CASTS(LayoutTextFragment,
LayoutObject,
object,
- ToLayoutText(object)->IsTextFragment(),
- ToLayoutText(object).IsTextFragment());
+ (object->IsText() && ToLayoutText(object)->IsTextFragment()),
+ (object.IsText() && ToLayoutText(object).IsTextFragment()));
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_text_fragment_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_text_fragment_test.cc
index 9e7d584eb2e..a29e6db7d86 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_text_fragment_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_text_fragment_test.cc
@@ -26,7 +26,7 @@ class LayoutTextFragmentTest : public RenderingTest {
void SetAhemBody(const char* message, const unsigned width) {
SetBodyInnerHTML(String::Format(
- "<div id='target' style='font: Ahem; width: %uem'>%s</div>", width,
+ "<div id='target' style='font: 10px Ahem; width: %uem'>%s</div>", width,
message));
}
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_text_test.cc b/chromium/third_party/blink/renderer/core/layout/layout_text_test.cc
index 255966a250f..5511b99eb41 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_text_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_text_test.cc
@@ -27,7 +27,7 @@ class LayoutTextTest : public RenderingTest {
void SetAhemBody(const char* message, const unsigned width) {
SetBodyInnerHTML(String::Format(
- "<div id='target' style='font: Ahem; width: %uem'>%s</div>", width,
+ "<div id='target' style='font: 10px Ahem; width: %uem'>%s</div>", width,
message));
}
@@ -617,12 +617,9 @@ TEST_P(ParameterizedLayoutTextTest, LocalSelectionRect) {
EXPECT_EQ(LayoutRect(10, 0, 50, 10), GetSelectionRectFor("f^oo ba|r"));
EXPECT_EQ(LayoutRect(0, 0, 40, 20),
GetSelectionRectFor("<div style='width: 2em'>f^oo ba|r</div>"));
- EXPECT_EQ(
- LayoutNGEnabled() ? LayoutRect(0, 0, 0, 0) : LayoutRect(30, 0, 10, 10),
- GetSelectionRectFor("foo^<br id='target'>|bar"));
- EXPECT_EQ(
- LayoutNGEnabled() ? LayoutRect(10, 0, 30, 10) : LayoutRect(10, 0, 20, 10),
- GetSelectionRectFor("f^oo<br>b|ar"));
+ EXPECT_EQ(LayoutRect(30, 0, 10, 10),
+ GetSelectionRectFor("foo^<br id='target'>|bar"));
+ EXPECT_EQ(LayoutRect(10, 0, 20, 10), GetSelectionRectFor("f^oo<br>b|ar"));
EXPECT_EQ(LayoutRect(10, 0, 30, 10),
GetSelectionRectFor("<div>f^oo</div><div>b|ar</div>"));
EXPECT_EQ(LayoutRect(30, 0, 10, 10), GetSelectionRectFor("foo^ |bar"));
@@ -639,4 +636,97 @@ TEST_P(ParameterizedLayoutTextTest, LocalSelectionRect) {
GetSelectionRectFor("foo^ |"));
}
+TEST_P(ParameterizedLayoutTextTest, LocalSelectionRectLineBreak) {
+ LoadAhem();
+ EXPECT_EQ(LayoutRect(30, 0, 10, 10),
+ GetSelectionRectFor("f^oo<br id='target'><br>ba|r"));
+ EXPECT_EQ(LayoutRect(0, 10, 10, 10),
+ GetSelectionRectFor("f^oo<br><br id='target'>ba|r"));
+}
+
+TEST_P(ParameterizedLayoutTextTest, LocalSelectionRectLineBreakPre) {
+ LoadAhem();
+ EXPECT_EQ(
+ LayoutRect(30, 0, 10, 10),
+ GetSelectionRectFor("<div style='white-space:pre;'>foo^\n|\nbar</div>"));
+ EXPECT_EQ(
+ LayoutNGEnabled() ? LayoutRect(0, 10, 10, 10) : LayoutRect(0, 0, 50, 20),
+ GetSelectionRectFor("<div style='white-space:pre;'>foo\n^\n|bar</div>"));
+}
+
+TEST_P(ParameterizedLayoutTextTest, LocalSelectionRectRTL) {
+ LoadAhem();
+ // TODO(yoichio) : Fix LastLogicalLeafIgnoringLineBreak so that 'foo' is the
+ // last fragment.
+ EXPECT_EQ(LayoutNGEnabled() ? LayoutRect(-10, 0, 30, 20)
+ : LayoutRect(-10, 0, 40, 20),
+ GetSelectionRectFor("<div style='width: 2em' dir=rtl>"
+ "f^oo ba|r baz</div>"));
+ EXPECT_EQ(LayoutRect(0, 0, 40, 20),
+ GetSelectionRectFor("<div style='width: 2em' dir=ltr>"
+ "f^oo ba|r baz</div>"));
+}
+
+TEST_P(ParameterizedLayoutTextTest, LocalSelectionRectVertical) {
+ LoadAhem();
+ EXPECT_EQ(
+ LayoutRect(0, 0, 20, 40),
+ GetSelectionRectFor("<div style='writing-mode: vertical-lr; height: 2em'>"
+ "f^oo ba|r baz</div>"));
+ // TODO(yoichio): This is caused by mixing lrt between vertical and logical.
+ EXPECT_EQ(
+ LayoutNGEnabled() ? LayoutRect(10, 0, 20, 40) : LayoutRect(0, 0, 20, 40),
+ GetSelectionRectFor("<div style='writing-mode: vertical-rl; height: 2em'>"
+ "f^oo ba|r baz</div>"));
+}
+
+TEST_P(ParameterizedLayoutTextTest, LocalSelectionRectVerticalRTL) {
+ LoadAhem();
+ EXPECT_EQ(LayoutNGEnabled() ? LayoutRect(0, -10, 20, 30)
+ : LayoutRect(0, -10, 20, 40),
+ GetSelectionRectFor(
+ "<div style='writing-mode: vertical-lr; height: 2em' dir=rtl>"
+ "f^oo ba|r baz</div>"));
+ EXPECT_EQ(LayoutNGEnabled() ? LayoutRect(10, -10, 20, 30)
+ : LayoutRect(0, -10, 20, 40),
+ GetSelectionRectFor(
+ "<div style='writing-mode: vertical-rl; height: 2em' dir=rtl>"
+ "f^oo ba|r baz</div>"));
+}
+
+TEST_P(ParameterizedLayoutTextTest, LocalSelectionRectLineHeight) {
+ LoadAhem();
+ EXPECT_EQ(LayoutNGEnabled() ? LayoutRect(10, 0, 10, 50)
+ : LayoutRect(10, 20, 10, 10),
+ GetSelectionRectFor("<div style='line-height: 50px; width:1em;'>"
+ "f^o|o bar baz</div>"));
+ EXPECT_EQ(LayoutNGEnabled() ? LayoutRect(10, 50, 10, 50)
+ : LayoutRect(10, 30, 10, 50),
+ GetSelectionRectFor("<div style='line-height: 50px; width:1em;'>"
+ "foo b^a|r baz</div>"));
+ EXPECT_EQ(LayoutNGEnabled() ? LayoutRect(10, 100, 10, 50)
+ : LayoutRect(10, 80, 10, 50),
+ GetSelectionRectFor("<div style='line-height: 50px; width:1em;'>"
+ "foo bar b^a|</div>"));
+}
+
+TEST_P(ParameterizedLayoutTextTest, LocalSelectionRectLineHeightVertical) {
+ LoadAhem();
+ EXPECT_EQ(LayoutNGEnabled() ? LayoutRect(0, 10, 50, 10)
+ : LayoutRect(20, 10, 50, 10),
+ GetSelectionRectFor("<div style='line-height: 50px; height:1em; "
+ "writing-mode:vertical-lr'>"
+ "f^o|o bar baz</div>"));
+ EXPECT_EQ(LayoutNGEnabled() ? LayoutRect(50, 10, 50, 10)
+ : LayoutRect(70, 10, 50, 10),
+ GetSelectionRectFor("<div style='line-height: 50px; height:1em; "
+ "writing-mode:vertical-lr'>"
+ "foo b^a|r baz</div>"));
+ EXPECT_EQ(LayoutNGEnabled() ? LayoutRect(100, 10, 50, 10)
+ : LayoutRect(120, 10, 10, 10),
+ GetSelectionRectFor("<div style='line-height: 50px; height:1em; "
+ "writing-mode:vertical-lr'>"
+ "foo bar b^a|z</div>"));
+}
+
} // namespace blink
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 fe2ee59d0ec..4bd730e8b3a 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme.cc
@@ -582,12 +582,12 @@ void LayoutTheme::AdjustInnerSpinButtonStyle(ComputedStyle&) const {}
void LayoutTheme::AdjustMenuListStyle(ComputedStyle&, Element*) const {}
-double LayoutTheme::AnimationRepeatIntervalForProgressBar() const {
- return 0;
+TimeDelta LayoutTheme::AnimationRepeatIntervalForProgressBar() const {
+ return TimeDelta();
}
-double LayoutTheme::AnimationDurationForProgressBar() const {
- return 0;
+TimeDelta LayoutTheme::AnimationDurationForProgressBar() const {
+ return TimeDelta();
}
bool LayoutTheme::ShouldHaveSpinButton(HTMLInputElement* input_element) const {
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 0a7a6a6035c..363ef2d9a7d 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme.h
@@ -36,7 +36,6 @@
namespace blink {
-class ChromeClient;
class ComputedStyle;
class Element;
class FileList;
@@ -46,6 +45,7 @@ class HTMLInputElement;
class LengthSize;
class Locale;
class Node;
+class PlatformChromeClient;
class Theme;
class ThemePainter;
@@ -190,7 +190,7 @@ class CORE_EXPORT LayoutTheme : public RefCounted<LayoutTheme> {
virtual int PopupInternalPaddingStart(const ComputedStyle&) const {
return 0;
}
- virtual int PopupInternalPaddingEnd(const ChromeClient*,
+ virtual int PopupInternalPaddingEnd(const PlatformChromeClient*,
const ComputedStyle&) const {
return 0;
}
@@ -206,9 +206,9 @@ class CORE_EXPORT LayoutTheme : public RefCounted<LayoutTheme> {
virtual void AdjustProgressBarBounds(ComputedStyle& style) const {}
// Returns the repeat interval of the animation for the progress bar.
- virtual double AnimationRepeatIntervalForProgressBar() const;
+ virtual TimeDelta AnimationRepeatIntervalForProgressBar() const;
// Returns the duration of the animation for the progress bar.
- virtual double AnimationDurationForProgressBar() const;
+ virtual TimeDelta AnimationDurationForProgressBar() const;
// Returns size of one slider tick mark for a horizontal track.
// For vertical tracks we rotate it and use it. i.e. Width is always length
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 e00e520626e..1c2a0a8b5d5 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
@@ -28,11 +28,11 @@
#include "third_party/blink/public/platform/web_theme_engine.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/layout/layout_theme_font_provider.h"
-#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/data_resource_helper.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/layout_test_support.h"
+#include "third_party/blink/renderer/platform/platform_chrome_client.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -317,7 +317,7 @@ int LayoutThemeDefault::PopupInternalPaddingStart(
}
int LayoutThemeDefault::PopupInternalPaddingEnd(
- const ChromeClient* client,
+ const PlatformChromeClient* client,
const ComputedStyle& style) const {
if (style.Appearance() == kNoControlPart)
return 0;
@@ -344,7 +344,7 @@ int LayoutThemeDefault::MenuListArrowWidthInDIP() const {
}
float LayoutThemeDefault::ClampedMenuListArrowPaddingSize(
- const ChromeClient* client,
+ const PlatformChromeClient* client,
const ComputedStyle& style) const {
if (cached_menu_list_arrow_padding_size_ > 0 &&
style.EffectiveZoom() == cached_menu_list_arrow_zoom_level_)
@@ -381,16 +381,17 @@ int LayoutThemeDefault::MenuListInternalPadding(const ComputedStyle& style,
}
//
-// Following values are come from default of GTK+
+// The following values come from the defaults of GTK+.
//
static const int kProgressAnimationFrames = 10;
-static const double kProgressAnimationInterval = 0.125;
+static constexpr TimeDelta kProgressAnimationInterval =
+ TimeDelta::FromMilliseconds(125);
-double LayoutThemeDefault::AnimationRepeatIntervalForProgressBar() const {
+TimeDelta LayoutThemeDefault::AnimationRepeatIntervalForProgressBar() const {
return kProgressAnimationInterval;
}
-double LayoutThemeDefault::AnimationDurationForProgressBar() const {
+TimeDelta LayoutThemeDefault::AnimationDurationForProgressBar() const {
return kProgressAnimationInterval * kProgressAnimationFrames *
2; // "2" for back and forth
}
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 ba106da1757..994d74e81f6 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
@@ -107,12 +107,12 @@ class CORE_EXPORT LayoutThemeDefault : public LayoutTheme {
void AdjustMenuListStyle(ComputedStyle&, Element*) const override;
void AdjustMenuListButtonStyle(ComputedStyle&, Element*) const override;
- double AnimationRepeatIntervalForProgressBar() const override;
- double AnimationDurationForProgressBar() const override;
+ TimeDelta AnimationRepeatIntervalForProgressBar() const override;
+ TimeDelta AnimationDurationForProgressBar() const override;
// These methods define the padding for the MenuList's inner block.
int PopupInternalPaddingStart(const ComputedStyle&) const override;
- int PopupInternalPaddingEnd(const ChromeClient*,
+ int PopupInternalPaddingEnd(const PlatformChromeClient*,
const ComputedStyle&) const override;
int PopupInternalPaddingTop(const ComputedStyle&) const override;
int PopupInternalPaddingBottom(const ComputedStyle&) const override;
@@ -121,7 +121,7 @@ class CORE_EXPORT LayoutThemeDefault : public LayoutTheme {
// thickness, which is 3px or 4px, and we use the value from the default Aura
// theme.
int MenuListArrowWidthInDIP() const;
- float ClampedMenuListArrowPaddingSize(const ChromeClient*,
+ float ClampedMenuListArrowPaddingSize(const PlatformChromeClient*,
const ComputedStyle&) const;
static void SetSelectionColors(unsigned active_background_color,
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_theme_mac.h b/chromium/third_party/blink/renderer/core/layout/layout_theme_mac.h
index f0ffd0fb0da..6ec0a66a931 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_theme_mac.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_theme_mac.h
@@ -77,7 +77,7 @@ class LayoutThemeMac final : public LayoutTheme {
int SliderTickOffsetFromTrackCenter() const override;
int PopupInternalPaddingStart(const ComputedStyle&) const override;
- int PopupInternalPaddingEnd(const ChromeClient*,
+ int PopupInternalPaddingEnd(const PlatformChromeClient*,
const ComputedStyle&) const override;
int PopupInternalPaddingTop(const ComputedStyle&) const override;
int PopupInternalPaddingBottom(const ComputedStyle&) const override;
@@ -86,9 +86,9 @@ class LayoutThemeMac final : public LayoutTheme {
bool PopsMenuBySpaceKey() const final { return true; }
// Returns the repeat interval of the animation for the progress bar.
- double AnimationRepeatIntervalForProgressBar() const override;
+ TimeDelta AnimationRepeatIntervalForProgressBar() const override;
// Returns the duration of the animation for the progress bar.
- double AnimationDurationForProgressBar() const override;
+ TimeDelta AnimationDurationForProgressBar() const override;
Color SystemColor(CSSValueID) const override;
@@ -153,7 +153,8 @@ class LayoutThemeMac final : public LayoutTheme {
// We estimate the animation rate of a Mac OS X progress bar is 33 fps.
// Hard code the value here because we haven't found API for it.
- static constexpr double kProgressAnimationFrameRate = 0.033;
+ static constexpr TimeDelta kProgressAnimationFrameRate =
+ TimeDelta::FromMilliseconds(33);
// Mac OS X progress bar animation seems to have 256 frames.
static constexpr double kProgressAnimationNumFrames = 256;
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 d2d26f07ab9..00c31f0fcf5 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
@@ -697,11 +697,13 @@ const int* LayoutThemeMac::ProgressBarHeights() const {
return kSizes;
}
-double LayoutThemeMac::AnimationRepeatIntervalForProgressBar() const {
+constexpr TimeDelta LayoutThemeMac::kProgressAnimationFrameRate;
+
+TimeDelta LayoutThemeMac::AnimationRepeatIntervalForProgressBar() const {
return kProgressAnimationFrameRate;
}
-double LayoutThemeMac::AnimationDurationForProgressBar() const {
+TimeDelta LayoutThemeMac::AnimationDurationForProgressBar() const {
return kProgressAnimationNumFrames * kProgressAnimationFrameRate;
}
@@ -759,7 +761,7 @@ int LayoutThemeMac::PopupInternalPaddingStart(
return 0;
}
-int LayoutThemeMac::PopupInternalPaddingEnd(const ChromeClient*,
+int LayoutThemeMac::PopupInternalPaddingEnd(const PlatformChromeClient*,
const ComputedStyle& style) const {
if (style.Appearance() == kMenulistPart)
return PopupButtonPadding(
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_tree_as_text.cc b/chromium/third_party/blink/renderer/core/layout/layout_tree_as_text.cc
index f7d8c402de2..f589fe02384 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_tree_as_text.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_tree_as_text.cc
@@ -59,6 +59,7 @@
#include "third_party/blink/renderer/core/page/print_context.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"
#include "third_party/blink/renderer/platform/layout_unit.h"
#include "third_party/blink/renderer/platform/wtf/hex_number.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
@@ -628,10 +629,10 @@ static void Write(WTF::TextStream& ts,
ts << " transparent";
if (layer.GetLayoutObject().HasOverflowClip()) {
- ScrollableArea* scrollable_area = layer.GetScrollableArea();
+ PaintLayerScrollableArea* scrollable_area = layer.GetScrollableArea();
ScrollOffset adjusted_scroll_offset =
scrollable_area->GetScrollOffset() +
- ToFloatSize(scrollable_area->ScrollOrigin());
+ ToFloatSize(FloatPoint(scrollable_area->ScrollOrigin()));
if (adjusted_scroll_offset.Width())
ts << " scrollX " << adjusted_scroll_offset.Width();
if (adjusted_scroll_offset.Height())
@@ -680,12 +681,14 @@ static void Write(WTF::TextStream& ts,
Write(ts, layer.GetLayoutObject(), indent + 1, behavior);
}
-static Vector<PaintLayerStackingNode*> NormalFlowListFor(
+static PaintLayerStackingNode::PaintLayers NormalFlowListFor(
PaintLayerStackingNode* node) {
- PaintLayerStackingNodeIterator it(*node, kNormalFlowChildren);
- Vector<PaintLayerStackingNode*> vector;
- while (PaintLayerStackingNode* normal_flow_child = it.Next())
- vector.push_back(normal_flow_child);
+ PaintLayerStackingNode::PaintLayers vector;
+ if (node) {
+ PaintLayerStackingNodeIterator it(*node, kNormalFlowChildren);
+ while (PaintLayer* normal_flow_child = it.Next())
+ vector.push_back(normal_flow_child);
+ }
return vector;
}
@@ -701,12 +704,9 @@ void LayoutTreeAsText::WriteLayers(WTF::TextStream& ts,
ClipRect damage_rect, clip_rect_to_apply;
layer->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(ClipRectsContext(root_layer, kUncachedClipRects),
- &layer->GetLayoutObject().FirstFragment(), paint_rect,
+ &layer->GetLayoutObject().FirstFragment(), &paint_rect,
layer_bounds, damage_rect, clip_rect_to_apply);
- // Ensure our lists are up to date.
- layer->StackingNode()->UpdateLayerListsIfNeeded();
-
LayoutPoint offset_from_root;
layer->ConvertToLayerCoords(root_layer, offset_from_root);
bool should_paint =
@@ -726,58 +726,68 @@ void LayoutTreeAsText::WriteLayers(WTF::TextStream& ts,
}
#endif
- Vector<PaintLayerStackingNode*>* neg_list =
- layer->StackingNode()->NegZOrderList();
- bool paints_background_separately = neg_list && neg_list->size() > 0;
- if (should_paint && paints_background_separately)
- Write(ts, *layer, layer_bounds, damage_rect.Rect(),
- clip_rect_to_apply.Rect(), kLayerPaintPhaseBackground, indent,
- behavior, marked_layer);
-
- if (neg_list) {
- int curr_indent = indent;
- if (behavior & kLayoutAsTextShowLayerNesting) {
- WriteIndent(ts, indent);
- ts << " negative z-order list(" << neg_list->size() << ")\n";
- ++curr_indent;
+ bool paints_background_separately = false;
+ if (layer->StackingNode()) {
+ PaintLayerStackingNode::PaintLayers* neg_list =
+ layer->StackingNode()->NegZOrderList();
+ paints_background_separately = neg_list && neg_list->size() > 0;
+ if (should_paint && paints_background_separately) {
+ Write(ts, *layer, layer_bounds, damage_rect.Rect(),
+ clip_rect_to_apply.Rect(), kLayerPaintPhaseBackground, indent,
+ behavior, marked_layer);
+ }
+
+ if (neg_list) {
+ int curr_indent = indent;
+ if (behavior & kLayoutAsTextShowLayerNesting) {
+ WriteIndent(ts, indent);
+ ts << " negative z-order list(" << neg_list->size() << ")\n";
+ ++curr_indent;
+ }
+ for (unsigned i = 0; i != neg_list->size(); ++i) {
+ WriteLayers(ts, root_layer, neg_list->at(i), paint_rect, curr_indent,
+ behavior, marked_layer);
+ }
}
- for (unsigned i = 0; i != neg_list->size(); ++i)
- WriteLayers(ts, root_layer, neg_list->at(i)->Layer(), paint_rect,
- curr_indent, behavior, marked_layer);
}
- if (should_paint)
+ if (should_paint) {
Write(ts, *layer, layer_bounds, damage_rect.Rect(),
clip_rect_to_apply.Rect(),
paints_background_separately ? kLayerPaintPhaseForeground
: kLayerPaintPhaseAll,
indent, behavior, marked_layer);
+ }
- Vector<PaintLayerStackingNode*> normal_flow_list =
- NormalFlowListFor(layer->StackingNode());
- if (!normal_flow_list.IsEmpty()) {
- int curr_indent = indent;
- if (behavior & kLayoutAsTextShowLayerNesting) {
- WriteIndent(ts, indent);
- ts << " normal flow list(" << normal_flow_list.size() << ")\n";
- ++curr_indent;
+ if (layer->StackingNode()) {
+ PaintLayerStackingNode::PaintLayers normal_flow_list =
+ NormalFlowListFor(layer->StackingNode());
+ if (!normal_flow_list.IsEmpty()) {
+ int curr_indent = indent;
+ if (behavior & kLayoutAsTextShowLayerNesting) {
+ WriteIndent(ts, indent);
+ ts << " normal flow list(" << normal_flow_list.size() << ")\n";
+ ++curr_indent;
+ }
+ for (unsigned i = 0; i != normal_flow_list.size(); ++i) {
+ WriteLayers(ts, root_layer, normal_flow_list.at(i), paint_rect,
+ curr_indent, behavior, marked_layer);
+ }
}
- for (unsigned i = 0; i != normal_flow_list.size(); ++i)
- WriteLayers(ts, root_layer, normal_flow_list.at(i)->Layer(), paint_rect,
- curr_indent, behavior, marked_layer);
- }
-
- if (Vector<PaintLayerStackingNode*>* pos_list =
- layer->StackingNode()->PosZOrderList()) {
- int curr_indent = indent;
- if (behavior & kLayoutAsTextShowLayerNesting) {
- WriteIndent(ts, indent);
- ts << " positive z-order list(" << pos_list->size() << ")\n";
- ++curr_indent;
+
+ if (PaintLayerStackingNode::PaintLayers* pos_list =
+ layer->StackingNode()->PosZOrderList()) {
+ int curr_indent = indent;
+ if (behavior & kLayoutAsTextShowLayerNesting) {
+ WriteIndent(ts, indent);
+ ts << " positive z-order list(" << pos_list->size() << ")\n";
+ ++curr_indent;
+ }
+ for (unsigned i = 0; i != pos_list->size(); ++i) {
+ WriteLayers(ts, root_layer, pos_list->at(i), paint_rect, curr_indent,
+ behavior, marked_layer);
+ }
}
- for (unsigned i = 0; i != pos_list->size(); ++i)
- WriteLayers(ts, root_layer, pos_list->at(i)->Layer(), paint_rect,
- curr_indent, behavior, marked_layer);
}
}
@@ -861,7 +871,7 @@ String ExternalRepresentation(LocalFrame* frame,
LayoutAsTextBehavior behavior,
const PaintLayer* marked_layer) {
if (!(behavior & kLayoutAsTextDontUpdateLayout)) {
- bool success = frame->View()->UpdateLifecycleToPrePaintClean();
+ bool success = frame->View()->UpdateAllLifecyclePhasesExceptPaint();
DCHECK(success);
};
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_video.cc b/chromium/third_party/blink/renderer/core/layout/layout_video.cc
index b66e83313a3..dbb9797d76a 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_video.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_video.cc
@@ -25,11 +25,9 @@
#include "third_party/blink/renderer/core/layout/layout_video.h"
+#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
-#include "third_party/blink/renderer/core/html_names.h"
-#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
-#include "third_party/blink/renderer/core/layout/layout_full_screen.h"
#include "third_party/blink/renderer/core/paint/video_painter.h"
namespace blink {
@@ -187,44 +185,6 @@ bool LayoutVideo::SupportsAcceleratedRendering() const {
return !!MediaElement()->CcLayer();
}
-static const LayoutBlock* LayoutObjectPlaceholder(
- const LayoutObject* layout_object) {
- LayoutObject* parent = layout_object->Parent();
- if (!parent)
- return nullptr;
-
- LayoutFullScreen* full_screen =
- parent->IsLayoutFullScreen() ? ToLayoutFullScreen(parent) : nullptr;
- if (!full_screen)
- return nullptr;
-
- return full_screen->Placeholder();
-}
-
-LayoutUnit LayoutVideo::OffsetLeft(const Element* parent) const {
- if (const LayoutBlock* block = LayoutObjectPlaceholder(this))
- return block->OffsetLeft(parent);
- return LayoutMedia::OffsetLeft(parent);
-}
-
-LayoutUnit LayoutVideo::OffsetTop(const Element* parent) const {
- if (const LayoutBlock* block = LayoutObjectPlaceholder(this))
- return block->OffsetTop(parent);
- return LayoutMedia::OffsetTop(parent);
-}
-
-LayoutUnit LayoutVideo::OffsetWidth() const {
- if (const LayoutBlock* block = LayoutObjectPlaceholder(this))
- return block->OffsetWidth();
- return LayoutMedia::OffsetWidth();
-}
-
-LayoutUnit LayoutVideo::OffsetHeight() const {
- if (const LayoutBlock* block = LayoutObjectPlaceholder(this))
- return block->OffsetHeight();
- return LayoutMedia::OffsetHeight();
-}
-
CompositingReasons LayoutVideo::AdditionalCompositingReasons() const {
HTMLMediaElement* element = ToHTMLMediaElement(GetNode());
if (element->IsFullscreen() && element->UsesOverlayFullscreenVideo())
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_video.h b/chromium/third_party/blink/renderer/core/layout/layout_video.h
index c89807d5956..163058f6eef 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_video.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_video.h
@@ -63,7 +63,8 @@ class LayoutVideo final : public LayoutMedia {
return type == kLayoutObjectVideo || LayoutMedia::IsOfType(type);
}
- void PaintReplaced(const PaintInfo&, const LayoutPoint&) const override;
+ void PaintReplaced(const PaintInfo&,
+ const LayoutPoint& paint_offset) const override;
void UpdateLayout() override;
@@ -73,11 +74,6 @@ class LayoutVideo final : public LayoutMedia {
LayoutUnit estimated_used_width = LayoutUnit()) const override;
LayoutUnit MinimumReplacedHeight() const override;
- LayoutUnit OffsetLeft(const Element*) const override;
- LayoutUnit OffsetTop(const Element*) const override;
- LayoutUnit OffsetWidth() const override;
- LayoutUnit OffsetHeight() const override;
-
CompositingReasons AdditionalCompositingReasons() const override;
void UpdatePlayer();
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 bc3bf00be63..c71691161e5 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_view.cc
+++ b/chromium/third_party/blink/renderer/core/layout/layout_view.cc
@@ -23,10 +23,13 @@
#include <inttypes.h>
+#include "build/build_config.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_screen_info.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/frame_selection.h"
+#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.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"
@@ -40,8 +43,10 @@
#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/page.h"
+#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_context.h"
#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/paint/view_painter.h"
#include "third_party/blink/renderer/core/svg/svg_document_extensions.h"
#include "third_party/blink/renderer/platform/geometry/float_quad.h"
@@ -52,6 +57,10 @@
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/transforms/transform_state.h"
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+#include "third_party/blink/renderer/platform/fonts/font_cache.h"
+#endif
+
namespace blink {
namespace {
@@ -59,26 +68,24 @@ namespace {
class HitTestLatencyRecorder {
public:
HitTestLatencyRecorder(bool allows_child_frame_content)
- : start_(WTF::CurrentTimeTicksInSeconds()),
+ : start_(CurrentTimeTicks()),
allows_child_frame_content_(allows_child_frame_content) {}
~HitTestLatencyRecorder() {
- int duration =
- static_cast<int>((WTF::CurrentTimeTicksInSeconds() - start_) * 1000000);
-
+ TimeDelta duration = CurrentTimeTicks() - start_;
if (allows_child_frame_content_) {
DEFINE_STATIC_LOCAL(CustomCountHistogram, recursive_latency_histogram,
("Event.Latency.HitTestRecursive", 0, 10000000, 100));
- recursive_latency_histogram.Count(duration);
+ recursive_latency_histogram.CountMicroseconds(duration);
} else {
DEFINE_STATIC_LOCAL(CustomCountHistogram, latency_histogram,
("Event.Latency.HitTest", 0, 10000000, 100));
- latency_histogram.Count(duration);
+ latency_histogram.CountMicroseconds(duration);
}
}
private:
- double start_;
+ TimeTicks start_;
bool allows_child_frame_content_;
};
@@ -92,7 +99,9 @@ LayoutView::LayoutView(Document* document)
layout_counter_count_(0),
hit_test_count_(0),
hit_test_cache_hits_(0),
- hit_test_cache_(HitTestCache::Create()) {
+ hit_test_cache_(HitTestCache::Create()),
+ autosize_h_scrollbar_mode_(kScrollbarAuto),
+ autosize_v_scrollbar_mode_(kScrollbarAuto) {
// init LayoutObject attributes
SetInline(false);
@@ -106,7 +115,8 @@ LayoutView::LayoutView(Document* document)
LayoutView::~LayoutView() = default;
-bool LayoutView::HitTest(HitTestResult& result) {
+bool LayoutView::HitTest(const HitTestLocation& location,
+ HitTestResult& result) {
// We have to recursively update layout/style here because otherwise, when the
// hit test recurses into a child document, it could trigger a layout on the
// parent document, which can destroy PaintLayer that are higher up in the
@@ -115,43 +125,43 @@ bool LayoutView::HitTest(HitTestResult& result) {
// Note that if an iframe has its render pipeline throttled, it will not
// update layout here, and it will also not propagate the hit test into the
// iframe's inner document.
- if (!GetFrameView()->UpdateLifecycleToPrePaintClean())
+ if (!GetFrameView()->UpdateAllLifecyclePhasesExceptPaint())
return false;
HitTestLatencyRecorder hit_test_latency_recorder(
result.GetHitTestRequest().AllowsChildFrameContent());
- return HitTestNoLifecycleUpdate(result);
+ return HitTestNoLifecycleUpdate(location, result);
}
-bool LayoutView::HitTestNoLifecycleUpdate(HitTestResult& result) {
+bool LayoutView::HitTestNoLifecycleUpdate(const HitTestLocation& location,
+ HitTestResult& result) {
TRACE_EVENT_BEGIN0("blink,devtools.timeline", "HitTest");
hit_test_count_++;
- DCHECK(!result.GetHitTestLocation().IsRectBasedTest() ||
- result.GetHitTestRequest().ListBased());
+ DCHECK(!location.IsRectBasedTest() || result.GetHitTestRequest().ListBased());
uint64_t dom_tree_version = GetDocument().DomTreeVersion();
HitTestResult cache_result = result;
bool hit_layer = false;
- if (hit_test_cache_->LookupCachedResult(cache_result, dom_tree_version)) {
+ if (hit_test_cache_->LookupCachedResult(location, cache_result,
+ dom_tree_version)) {
hit_test_cache_hits_++;
hit_layer = true;
result = cache_result;
} else {
- hit_layer = Layer()->HitTest(result);
-
- // LocalFrameView scrollbars are not the same as Layer scrollbars tested by
- // Layer::hitTestOverflowControls, so we need to test LocalFrameView
- // scrollbars separately here. Note that it's important we do this after the
- // hit test above, because that may overwrite the entire HitTestResult when
- // it finds a hit.
- IntPoint frame_point = GetFrameView()->ContentsToFrame(
- result.GetHitTestLocation().RoundedPoint());
- if (Scrollbar* frame_scrollbar =
- GetFrameView()->ScrollbarAtFramePoint(frame_point)) {
- result.SetScrollbar(frame_scrollbar);
- hit_layer = true;
+ LocalFrameView* frame_view = GetFrameView();
+ LayoutRect hit_test_area;
+ if (frame_view) {
+ // Start with a rect sized to the frame, to ensure we include the
+ // scrollbars.
+ hit_test_area = LayoutRect(LayoutPoint(), LayoutSize(frame_view->Size()));
+ if (result.GetHitTestRequest().IgnoreClipping()) {
+ hit_test_area.Unite(
+ frame_view->DocumentToFrame(LayoutRect(DocumentRect())));
+ }
}
+ hit_layer = Layer()->HitTest(location, result, hit_test_area);
+
// If hitTestResult include scrollbar, innerNode should be the parent of the
// scrollbar.
if (result.GetScrollbar()) {
@@ -177,13 +187,12 @@ bool LayoutView::HitTestNoLifecycleUpdate(HitTestResult& result) {
}
if (hit_layer)
- hit_test_cache_->AddCachedResult(result, dom_tree_version);
+ hit_test_cache_->AddCachedResult(location, result, dom_tree_version);
}
- TRACE_EVENT_END1(
- "blink,devtools.timeline", "HitTest", "endData",
- InspectorHitTestEvent::EndData(result.GetHitTestRequest(),
- result.GetHitTestLocation(), result));
+ TRACE_EVENT_END1("blink,devtools.timeline", "HitTest", "endData",
+ InspectorHitTestEvent::EndData(result.GetHitTestRequest(),
+ location, result));
return hit_layer;
}
@@ -290,7 +299,7 @@ void LayoutView::UpdateBlockLayout(bool relayout_children) {
}
void LayoutView::UpdateLayout() {
- if (!GetDocument().Paginated())
+ if (!GetDocument().Printing())
SetPageLogicalHeight(LayoutUnit());
// TODO(wangxianzhu): Move this into ViewPaintInvalidator.
@@ -314,6 +323,21 @@ void LayoutView::UpdateLayout() {
DCHECK(!layout_state_);
LayoutState root_layout_state(*this);
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+ // The font code in FontPlatformData does not have a direct connection to the
+ // document, the frame or anything from which we could retrieve the device
+ // scale factor. After using zoom for DSF, the GraphicsContext does only ever
+ // have a DSF of 1 on Linux. In order for the font code to be aware of an up
+ // to date DSF when layout happens, we plumb this through to the FontCache, so
+ // that we can correctly retrieve RenderStyleForStrike from out of
+ // process. crbug.com/845468
+ FontCache::SetDeviceScaleFactor(GetFrameView()
+ ->GetFrame()
+ .GetChromeClient()
+ .GetScreenInfo()
+ .device_scale_factor);
+#endif
+
LayoutBlockFlow::UpdateLayout();
#if DCHECK_IS_ON()
@@ -350,16 +374,7 @@ void LayoutView::MapLocalToAncestor(const LayoutBoxModelObject* ancestor,
if (mode & kTraverseDocumentBoundaries) {
auto* parent_doc_layout_object = GetFrame()->OwnerLayoutObject();
if (parent_doc_layout_object) {
- if (!(mode & kInputIsInFrameCoordinates)) {
- transform_state.Move(
- LayoutSize(-GetFrame()->View()->GetScrollOffset()));
- } else {
- // The flag applies to immediate LayoutView only.
- mode &= ~kInputIsInFrameCoordinates;
- }
-
transform_state.Move(parent_doc_layout_object->ContentBoxOffset());
-
parent_doc_layout_object->MapLocalToAncestor(ancestor, transform_state,
mode);
} else {
@@ -376,7 +391,6 @@ const LayoutObject* LayoutView::PushMappingToContainer(
if (geometry_map.GetMapCoordinatesFlags() & kTraverseDocumentBoundaries) {
if (auto* parent_doc_layout_object = GetFrame()->OwnerLayoutObject()) {
- offset = -LayoutSize(frame_view_->GetScrollOffset());
offset += parent_doc_layout_object->ContentBoxOffset();
container = parent_doc_layout_object;
}
@@ -410,7 +424,6 @@ void LayoutView::MapAncestorToLocal(const LayoutBoxModelObject* ancestor,
mode & ~kIsFixed);
transform_state.Move(parent_doc_layout_object->ContentBoxOffset());
- transform_state.Move(LayoutSize(-GetFrame()->View()->GetScrollOffset()));
}
} else {
DCHECK(this == ancestor || !ancestor);
@@ -426,13 +439,12 @@ void LayoutView::ComputeSelfHitTestRects(Vector<LayoutRect>& rects,
// just use the viewport size (containing block) here because we want to
// ensure this includes all children (so we can avoid walking them
// explicitly).
- rects.push_back(LayoutRect(LayoutPoint::Zero(),
- LayoutSize(GetFrameView()->ContentsSize())));
+ rects.push_back(
+ LayoutRect(LayoutPoint::Zero(), LayoutSize(GetFrameView()->Size())));
}
-void LayoutView::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
- ViewPainter(*this).Paint(paint_info, paint_offset);
+void LayoutView::Paint(const PaintInfo& paint_info) const {
+ ViewPainter(*this).Paint(paint_info);
}
void LayoutView::PaintBoxDecorationBackground(const PaintInfo& paint_info,
@@ -500,7 +512,7 @@ bool LayoutView::MapToVisualRectInAncestorSpaceInternal(
MapCoordinatesFlags mode,
VisualRectFlags visual_rect_flags) const {
if (mode & kIsFixed)
- transform_state.Move(OffsetForFixedPosition(true));
+ transform_state.Move(OffsetForFixedPosition());
// Apply our transform if we have one (because of full page zooming).
if (Layer() && Layer()->Transform()) {
@@ -523,21 +535,16 @@ bool LayoutView::MapToVisualRectInAncestorSpaceInternal(
if (LayoutBox* obj = owner->GetLayoutBox()) {
LayoutRect rect(transform_state.LastPlanarQuad().BoundingBox());
- if (!(mode & kInputIsInFrameCoordinates)) {
- // Intersect the viewport with the visual rect.
- LayoutRect view_rectangle = ViewRect();
- if (visual_rect_flags & kEdgeInclusive) {
- if (!rect.InclusiveIntersect(view_rectangle)) {
- transform_state.SetQuad(FloatQuad(FloatRect(rect)));
- return false;
- }
- } else {
- rect.Intersect(view_rectangle);
+ LayoutRect view_rectangle = ViewRect();
+ if (visual_rect_flags & kEdgeInclusive) {
+ if (!rect.InclusiveIntersect(view_rectangle)) {
+ transform_state.SetQuad(FloatQuad(FloatRect(rect)));
+ return false;
}
-
- // Adjust for scroll offset of the view.
- rect.MoveBy(-view_rectangle.Location());
+ } else {
+ rect.Intersect(view_rectangle);
}
+
// Frames are painted at rounded-int position. Since we cannot efficiently
// compute the subpixel offset of painting at this point in a a bottom-up
// walk, round to the enclosing int rect, which will enclose the actual
@@ -557,26 +564,8 @@ bool LayoutView::MapToVisualRectInAncestorSpaceInternal(
return false;
}
-LayoutSize LayoutView::OffsetForFixedPosition(
- bool include_pending_scroll) const {
- FloatSize adjustment;
- if (frame_view_) {
- adjustment += frame_view_->GetScrollOffset();
-
- // FIXME: Paint invalidation should happen after scroll updates, so there
- // should be no pending scroll delta.
- // However, we still have paint invalidation during layout, so we can't
- // DCHECK for now. crbug.com/434950.
- // DCHECK(m_frameView->pendingScrollDelta().isZero());
- // If we have a pending scroll, invalidate the previous scroll position.
- if (include_pending_scroll && !frame_view_->PendingScrollDelta().IsZero())
- adjustment -= frame_view_->PendingScrollDelta();
- }
-
- if (HasOverflowClip())
- adjustment += FloatSize(ScrolledContentOffset());
-
- return RoundedLayoutSize(adjustment);
+LayoutSize LayoutView::OffsetForFixedPosition() const {
+ return HasOverflowClip() ? LayoutSize(ScrolledContentOffset()) : LayoutSize();
}
void LayoutView::AbsoluteRects(Vector<IntRect>& rects,
@@ -611,7 +600,7 @@ LayoutRect LayoutView::ViewRect() const {
if (ShouldUsePrintingLayout())
return LayoutRect(LayoutPoint(), Size());
if (frame_view_)
- return LayoutRect(frame_view_->VisibleContentRect());
+ return LayoutRect(LayoutPoint(), LayoutSize(frame_view_->Size()));
return LayoutRect();
}
@@ -630,6 +619,13 @@ LayoutRect LayoutView::OverflowClipRect(
return rect;
}
+void LayoutView::SetAutosizeScrollbarModes(ScrollbarMode h_mode,
+ ScrollbarMode v_mode) {
+ DCHECK_EQ(v_mode == kScrollbarAuto, h_mode == kScrollbarAuto);
+ autosize_v_scrollbar_mode_ = v_mode;
+ autosize_h_scrollbar_mode_ = h_mode;
+}
+
void LayoutView::CalculateScrollbarModes(ScrollbarMode& h_mode,
ScrollbarMode& v_mode) const {
#define RETURN_SCROLLBAR_MODE(mode) \
@@ -638,6 +634,15 @@ void LayoutView::CalculateScrollbarModes(ScrollbarMode& h_mode,
return; \
}
+ // FrameViewAutoSizeInfo manually controls the appearance of the main frame's
+ // scrollbars so defer to those if we're in AutoSize mode.
+ if (AutosizeVerticalScrollbarMode() != kScrollbarAuto ||
+ AutosizeHorizontalScrollbarMode() != kScrollbarAuto) {
+ h_mode = AutosizeHorizontalScrollbarMode();
+ v_mode = AutosizeVerticalScrollbarMode();
+ return;
+ }
+
LocalFrame* frame = GetFrame();
if (!frame)
RETURN_SCROLLBAR_MODE(kScrollbarAlwaysOff);
@@ -738,10 +743,9 @@ IntSize LayoutView::GetLayoutSize(
if (!frame_view_)
return IntSize();
- IntSize result = frame_view_->GetLayoutSize(kIncludeScrollbars);
+ IntSize result = frame_view_->GetLayoutSize();
if (scrollbar_inclusion == kExcludeScrollbars)
- result =
- frame_view_->LayoutViewportScrollableArea()->ExcludeScrollbars(result);
+ result = frame_view_->LayoutViewport()->ExcludeScrollbars(result);
return result;
}
@@ -793,7 +797,7 @@ void LayoutView::UpdateAfterLayout() {
}
void LayoutView::UpdateHitTestResult(HitTestResult& result,
- const LayoutPoint& point) {
+ const LayoutPoint& point) const {
if (result.InnerNode())
return;
@@ -857,6 +861,28 @@ void LayoutView::UpdateFromStyle() {
SetHasBoxDecorationBackground(true);
}
+bool LayoutView::RecalcOverflowAfterStyleChange() {
+ if (!NeedsOverflowRecalcAfterStyleChange())
+ return false;
+ bool result = LayoutBlockFlow::RecalcOverflowAfterStyleChange();
+ if (result) {
+ // Changing overflow should notify scrolling coordinator to ensures that it
+ // updates non-fast scroll rects even if there is no layout.
+ if (ScrollingCoordinator* scrolling_coordinator =
+ GetDocument().GetPage()->GetScrollingCoordinator()) {
+ GetFrameView()->GetScrollingContext()->SetScrollGestureRegionIsDirty(
+ true);
+ }
+ if (NeedsLayout())
+ return result;
+ if (GetFrameView()->VisualViewportSuppliesScrollbars())
+ SetMayNeedPaintInvalidation();
+ GetFrameView()->AdjustViewSize();
+ SetNeedsPaintPropertyUpdate();
+ }
+ return result;
+}
+
LayoutRect LayoutView::DebugRect() const {
LayoutRect rect;
LayoutBlock* block = ContainingBlock();
@@ -899,4 +925,26 @@ void LayoutView::UpdateCounters() {
}
}
+Vector<IntRect> LayoutView::GetTickmarks() const {
+ if (!tickmarks_override_.IsEmpty())
+ return tickmarks_override_;
+
+ return GetDocument().Markers().LayoutRectsForTextMatchMarkers();
+}
+
+void LayoutView::OverrideTickmarks(const Vector<IntRect>& tickmarks) {
+ tickmarks_override_ = tickmarks;
+ InvalidatePaintForTickmarks();
+}
+
+void LayoutView::InvalidatePaintForTickmarks() {
+ ScrollableArea* scrollable_area = GetScrollableArea();
+ if (!scrollable_area)
+ return;
+ Scrollbar* scrollbar = scrollable_area->VerticalScrollbar();
+ if (!scrollbar)
+ return;
+ scrollbar->SetNeedsPaintInvalidation(static_cast<ScrollbarPart>(~kThumbPart));
+}
+
} // namespace blink
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 867d64060c1..fed51c0988f 100644
--- a/chromium/third_party/blink/renderer/core/layout/layout_view.h
+++ b/chromium/third_party/blink/renderer/core/layout/layout_view.h
@@ -63,8 +63,9 @@ class CORE_EXPORT LayoutView final : public LayoutBlockFlow {
// hitTest() will update layout, style and compositing first while
// hitTestNoLifecycleUpdate() does not.
- bool HitTest(HitTestResult&);
- bool HitTestNoLifecycleUpdate(HitTestResult&);
+ bool HitTest(const HitTestLocation& location, HitTestResult&);
+ bool HitTestNoLifecycleUpdate(const HitTestLocation& location,
+ HitTestResult&);
// Returns the total count of calls to HitTest, for testing.
unsigned HitTestCount() const { return hit_test_count_; }
@@ -136,13 +137,14 @@ class CORE_EXPORT LayoutView final : public LayoutBlockFlow {
const LayoutBoxModelObject* ancestor,
TransformState&,
VisualRectFlags = kDefaultVisualRectFlags) const override;
- LayoutSize OffsetForFixedPosition(bool include_pending_scroll = false) const;
+ LayoutSize OffsetForFixedPosition() const;
void InvalidatePaintForViewAndCompositedLayers();
- void Paint(const PaintInfo&, const LayoutPoint&) const override;
- void PaintBoxDecorationBackground(const PaintInfo&,
- const LayoutPoint&) const override;
+ void Paint(const PaintInfo&) const override;
+ void PaintBoxDecorationBackground(
+ const PaintInfo&,
+ const LayoutPoint& paint_offset) const override;
void ClearSelection();
void CommitPendingSelection();
@@ -158,6 +160,15 @@ class CORE_EXPORT LayoutView final : public LayoutBlockFlow {
OverlayScrollbarClipBehavior =
kIgnorePlatformOverlayScrollbarSize) const override;
+ // If either direction has a non-auto mode, the other must as well.
+ void SetAutosizeScrollbarModes(ScrollbarMode h_mode, ScrollbarMode v_mode);
+ ScrollbarMode AutosizeHorizontalScrollbarMode() const {
+ return autosize_h_scrollbar_mode_;
+ }
+ ScrollbarMode AutosizeVerticalScrollbarMode() const {
+ return autosize_v_scrollbar_mode_;
+ }
+
void CalculateScrollbarModes(ScrollbarMode& h_mode,
ScrollbarMode& v_mode) const;
@@ -165,7 +176,7 @@ class CORE_EXPORT LayoutView final : public LayoutBlockFlow {
LayoutState* GetLayoutState() const { return layout_state_; }
- void UpdateHitTestResult(HitTestResult&, const LayoutPoint&) override;
+ void UpdateHitTestResult(HitTestResult&, const LayoutPoint&) const override;
ViewFragmentationContext* FragmentationContext() const {
return fragmentation_context_.get();
@@ -242,6 +253,20 @@ class CORE_EXPORT LayoutView final : public LayoutBlockFlow {
IntSize ScrolledContentOffset() const override;
+ // Returns the coordinates of find-in-page scrollbar tickmarks. These come
+ // from DocumentMarkerController, unless overridden by SetTickmarks.
+ Vector<IntRect> GetTickmarks() const;
+
+ // Sets the coordinates of find-in-page scrollbar tickmarks, bypassing
+ // DocumentMarkerController. This is used by the PDF plugin.
+ void OverrideTickmarks(const Vector<IntRect>&);
+
+ // Issues a paint invalidation on the layout viewport's vertical scrollbar
+ // (which is responsible for painting the tickmarks).
+ void InvalidatePaintForTickmarks();
+
+ bool RecalcOverflowAfterStyleChange() override;
+
private:
void MapLocalToAncestor(
const LayoutBoxModelObject* ancestor,
@@ -302,6 +327,14 @@ class CORE_EXPORT LayoutView final : public LayoutBlockFlow {
unsigned hit_test_count_;
unsigned hit_test_cache_hits_;
Persistent<HitTestCache> hit_test_cache_;
+
+ // FrameViewAutoSizeInfo controls scrollbar appearance manually rather than
+ // relying on layout. These members are used to override the ScrollbarModes
+ // calculated from style. kScrollbarAuto disables the override.
+ ScrollbarMode autosize_h_scrollbar_mode_;
+ ScrollbarMode autosize_v_scrollbar_mode_;
+
+ Vector<IntRect> tickmarks_override_;
};
DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutView, IsLayoutView());
diff --git a/chromium/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.cc b/chromium/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.cc
index 64c42b0dda4..26865edd839 100644
--- a/chromium/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.cc
@@ -30,42 +30,52 @@
#include "third_party/blink/renderer/core/layout/line/abstract_inline_text_box.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#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/platform/text/text_break_iterator.h"
namespace blink {
-AbstractInlineTextBox::InlineToAbstractInlineTextBoxHashMap*
- AbstractInlineTextBox::g_abstract_inline_text_box_map_ = nullptr;
+AbstractInlineTextBox::AbstractInlineTextBox(LineLayoutText line_layout_item)
+ : line_layout_item_(line_layout_item) {}
-scoped_refptr<AbstractInlineTextBox> AbstractInlineTextBox::GetOrCreate(
+AbstractInlineTextBox::~AbstractInlineTextBox() {
+ DCHECK(!line_layout_item_);
+}
+
+// ----
+
+LegacyAbstractInlineTextBox::InlineToLegacyAbstractInlineTextBoxHashMap*
+ LegacyAbstractInlineTextBox::g_abstract_inline_text_box_map_ = nullptr;
+
+scoped_refptr<AbstractInlineTextBox> LegacyAbstractInlineTextBox::GetOrCreate(
LineLayoutText line_layout_text,
InlineTextBox* inline_text_box) {
if (!inline_text_box)
return nullptr;
- if (!g_abstract_inline_text_box_map_)
+ if (!g_abstract_inline_text_box_map_) {
g_abstract_inline_text_box_map_ =
- new InlineToAbstractInlineTextBoxHashMap();
+ new InlineToLegacyAbstractInlineTextBoxHashMap();
+ }
- InlineToAbstractInlineTextBoxHashMap::const_iterator it =
+ InlineToLegacyAbstractInlineTextBoxHashMap::const_iterator it =
g_abstract_inline_text_box_map_->find(inline_text_box);
if (it != g_abstract_inline_text_box_map_->end())
return it->value;
scoped_refptr<AbstractInlineTextBox> obj = base::AdoptRef(
- new AbstractInlineTextBox(line_layout_text, inline_text_box));
+ new LegacyAbstractInlineTextBox(line_layout_text, inline_text_box));
g_abstract_inline_text_box_map_->Set(inline_text_box, obj);
return obj;
}
-void AbstractInlineTextBox::WillDestroy(InlineTextBox* inline_text_box) {
+void LegacyAbstractInlineTextBox::WillDestroy(InlineTextBox* inline_text_box) {
if (!g_abstract_inline_text_box_map_)
return;
- InlineToAbstractInlineTextBoxHashMap::const_iterator it =
+ InlineToLegacyAbstractInlineTextBoxHashMap::const_iterator it =
g_abstract_inline_text_box_map_->find(inline_text_box);
if (it != g_abstract_inline_text_box_map_->end()) {
it->value->Detach();
@@ -73,51 +83,62 @@ void AbstractInlineTextBox::WillDestroy(InlineTextBox* inline_text_box) {
}
}
-AbstractInlineTextBox::~AbstractInlineTextBox() {
- DCHECK(!line_layout_item_);
+LegacyAbstractInlineTextBox::LegacyAbstractInlineTextBox(
+ LineLayoutText line_layout_item,
+ InlineTextBox* inline_text_box)
+ : AbstractInlineTextBox(line_layout_item),
+ inline_text_box_(inline_text_box) {}
+
+LegacyAbstractInlineTextBox::~LegacyAbstractInlineTextBox() {
DCHECK(!inline_text_box_);
}
void AbstractInlineTextBox::Detach() {
+ DCHECK(GetLineLayoutItem());
if (Node* node = GetNode()) {
if (AXObjectCache* cache = node->GetDocument().ExistingAXObjectCache())
cache->Remove(this);
}
line_layout_item_ = LineLayoutText(nullptr);
+}
+
+void LegacyAbstractInlineTextBox::Detach() {
+ AbstractInlineTextBox::Detach();
inline_text_box_ = nullptr;
}
-scoped_refptr<AbstractInlineTextBox> AbstractInlineTextBox::NextInlineTextBox()
- const {
+scoped_refptr<AbstractInlineTextBox>
+LegacyAbstractInlineTextBox::NextInlineTextBox() const {
DCHECK(!inline_text_box_ ||
!inline_text_box_->GetLineLayoutItem().NeedsLayout());
if (!inline_text_box_)
return nullptr;
- return GetOrCreate(line_layout_item_,
+ return GetOrCreate(GetLineLayoutItem(),
inline_text_box_->NextForSameLayoutObject());
}
-LayoutRect AbstractInlineTextBox::LocalBounds() const {
- if (!inline_text_box_ || !line_layout_item_)
+LayoutRect LegacyAbstractInlineTextBox::LocalBounds() const {
+ if (!inline_text_box_ || !GetLineLayoutItem())
return LayoutRect();
return inline_text_box_->FrameRect();
}
-unsigned AbstractInlineTextBox::Len() const {
+unsigned LegacyAbstractInlineTextBox::Len() const {
if (!inline_text_box_)
return 0;
return inline_text_box_->Len();
}
-AbstractInlineTextBox::Direction AbstractInlineTextBox::GetDirection() const {
- if (!inline_text_box_ || !line_layout_item_)
+AbstractInlineTextBox::Direction LegacyAbstractInlineTextBox::GetDirection()
+ const {
+ if (!inline_text_box_ || !GetLineLayoutItem())
return kLeftToRight;
- if (line_layout_item_.Style()->IsHorizontalWritingMode()) {
+ if (GetLineLayoutItem().Style()->IsHorizontalWritingMode()) {
return (inline_text_box_->Direction() == TextDirection::kRtl
? kRightToLeft
: kLeftToRight);
@@ -127,12 +148,12 @@ AbstractInlineTextBox::Direction AbstractInlineTextBox::GetDirection() const {
}
Node* AbstractInlineTextBox::GetNode() const {
- if (!line_layout_item_)
+ if (!GetLineLayoutItem())
return nullptr;
- return line_layout_item_.GetNode();
+ return GetLineLayoutItem().GetNode();
}
-void AbstractInlineTextBox::CharacterWidths(Vector<float>& widths) const {
+void LegacyAbstractInlineTextBox::CharacterWidths(Vector<float>& widths) const {
if (!inline_text_box_)
return;
@@ -141,7 +162,7 @@ void AbstractInlineTextBox::CharacterWidths(Vector<float>& widths) const {
void AbstractInlineTextBox::GetWordBoundaries(
Vector<WordBoundaries>& words) const {
- if (!inline_text_box_)
+ if (Len() == 0)
return;
String text = GetText();
@@ -161,13 +182,13 @@ void AbstractInlineTextBox::GetWordBoundaries(
}
}
-String AbstractInlineTextBox::GetText() const {
- if (!inline_text_box_ || !line_layout_item_)
+String LegacyAbstractInlineTextBox::GetText() const {
+ if (!inline_text_box_ || !GetLineLayoutItem())
return String();
unsigned start = inline_text_box_->Start();
unsigned len = inline_text_box_->Len();
- if (Node* node = line_layout_item_.GetNode()) {
+ if (Node* node = GetLineLayoutItem().GetNode()) {
if (node->IsTextNode()) {
return PlainText(
EphemeralRange(Position(node, start), Position(node, start + len)),
@@ -179,7 +200,8 @@ String AbstractInlineTextBox::GetText() const {
TextIteratorBehavior::IgnoresStyleVisibilityBehavior());
}
- String result = line_layout_item_.GetText()
+ String result = GetLineLayoutItem()
+ .GetText()
.Substring(start, len)
.SimplifyWhiteSpace(WTF::kDoNotStripWhiteSpace);
if (inline_text_box_->NextForSameLayoutObject() &&
@@ -190,19 +212,20 @@ String AbstractInlineTextBox::GetText() const {
return result;
}
-bool AbstractInlineTextBox::IsFirst() const {
+bool LegacyAbstractInlineTextBox::IsFirst() const {
DCHECK(!inline_text_box_ ||
!inline_text_box_->GetLineLayoutItem().NeedsLayout());
return !inline_text_box_ || !inline_text_box_->PrevForSameLayoutObject();
}
-bool AbstractInlineTextBox::IsLast() const {
+bool LegacyAbstractInlineTextBox::IsLast() const {
DCHECK(!inline_text_box_ ||
!inline_text_box_->GetLineLayoutItem().NeedsLayout());
return !inline_text_box_ || !inline_text_box_->NextForSameLayoutObject();
}
-scoped_refptr<AbstractInlineTextBox> AbstractInlineTextBox::NextOnLine() const {
+scoped_refptr<AbstractInlineTextBox> LegacyAbstractInlineTextBox::NextOnLine()
+ const {
DCHECK(!inline_text_box_ ||
!inline_text_box_->GetLineLayoutItem().NeedsLayout());
if (!inline_text_box_)
@@ -216,8 +239,8 @@ scoped_refptr<AbstractInlineTextBox> AbstractInlineTextBox::NextOnLine() const {
return nullptr;
}
-scoped_refptr<AbstractInlineTextBox> AbstractInlineTextBox::PreviousOnLine()
- const {
+scoped_refptr<AbstractInlineTextBox>
+LegacyAbstractInlineTextBox::PreviousOnLine() const {
DCHECK(!inline_text_box_ ||
!inline_text_box_->GetLineLayoutItem().NeedsLayout());
if (!inline_text_box_)
diff --git a/chromium/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.h b/chromium/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.h
index 33a51bba342..87392ea2867 100644
--- a/chromium/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.h
+++ b/chromium/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.h
@@ -47,19 +47,6 @@ class InlineTextBox;
// get information about InlineTextBoxes without tight coupling.
class CORE_EXPORT AbstractInlineTextBox
: public RefCounted<AbstractInlineTextBox> {
- private:
- AbstractInlineTextBox(LineLayoutText line_layout_item,
- InlineTextBox* inline_text_box)
- : line_layout_item_(line_layout_item),
- inline_text_box_(inline_text_box) {}
-
- static scoped_refptr<AbstractInlineTextBox> GetOrCreate(LineLayoutText,
- InlineTextBox*);
- static void WillDestroy(InlineTextBox*);
-
- friend class LayoutText;
- friend class InlineTextBox;
-
public:
struct WordBoundaries {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
@@ -71,34 +58,71 @@ class CORE_EXPORT AbstractInlineTextBox
enum Direction { kLeftToRight, kRightToLeft, kTopToBottom, kBottomToTop };
- ~AbstractInlineTextBox();
+ virtual ~AbstractInlineTextBox();
LineLayoutText GetLineLayoutItem() const { return line_layout_item_; }
- scoped_refptr<AbstractInlineTextBox> NextInlineTextBox() const;
- LayoutRect LocalBounds() const;
- unsigned Len() const;
- Direction GetDirection() const;
+ virtual void Detach();
+ virtual scoped_refptr<AbstractInlineTextBox> NextInlineTextBox() const = 0;
+ virtual LayoutRect LocalBounds() const = 0;
+ virtual unsigned Len() const = 0;
+ virtual Direction GetDirection() const = 0;
Node* GetNode() const;
- void CharacterWidths(Vector<float>&) const;
+ virtual void CharacterWidths(Vector<float>&) const = 0;
void GetWordBoundaries(Vector<WordBoundaries>&) const;
- String GetText() const;
- bool IsFirst() const;
- bool IsLast() const;
- scoped_refptr<AbstractInlineTextBox> NextOnLine() const;
- scoped_refptr<AbstractInlineTextBox> PreviousOnLine() const;
+ virtual String GetText() const = 0;
+ virtual bool IsFirst() const = 0;
+ virtual bool IsLast() const = 0;
+ virtual scoped_refptr<AbstractInlineTextBox> NextOnLine() const = 0;
+ virtual scoped_refptr<AbstractInlineTextBox> PreviousOnLine() const = 0;
- private:
- void Detach();
+ protected:
+ explicit AbstractInlineTextBox(LineLayoutText line_layout_item);
+ private:
// Weak ptrs; these are nulled when InlineTextBox::destroy() calls
// AbstractInlineTextBox::willDestroy.
LineLayoutText line_layout_item_;
+};
+
+// The implementation of |AbstractInlineTextBox| for legacy layout.
+// See also |NGAbstractInlineTextBox| for LayoutNG.
+class CORE_EXPORT LegacyAbstractInlineTextBox final
+ : public AbstractInlineTextBox {
+ private:
+ LegacyAbstractInlineTextBox(LineLayoutText line_layout_item,
+ InlineTextBox* inline_text_box);
+
+ static scoped_refptr<AbstractInlineTextBox> GetOrCreate(LineLayoutText,
+ InlineTextBox*);
+ static void WillDestroy(InlineTextBox*);
+
+ friend class LayoutText;
+ friend class InlineTextBox;
+
+ public:
+ ~LegacyAbstractInlineTextBox() final;
+
+ private:
+ // Implementations of AbstractInlineTextBox member functions.
+ void Detach() final;
+ scoped_refptr<AbstractInlineTextBox> NextInlineTextBox() const final;
+ LayoutRect LocalBounds() const final;
+ unsigned Len() const final;
+ Direction GetDirection() const final;
+ void CharacterWidths(Vector<float>&) const final;
+ String GetText() const final;
+ bool IsFirst() const final;
+ bool IsLast() const final;
+ scoped_refptr<AbstractInlineTextBox> NextOnLine() const final;
+ scoped_refptr<AbstractInlineTextBox> PreviousOnLine() const final;
+
InlineTextBox* inline_text_box_;
typedef HashMap<InlineTextBox*, scoped_refptr<AbstractInlineTextBox>>
- InlineToAbstractInlineTextBoxHashMap;
- static InlineToAbstractInlineTextBoxHashMap* g_abstract_inline_text_box_map_;
+ InlineToLegacyAbstractInlineTextBoxHashMap;
+ static InlineToLegacyAbstractInlineTextBoxHashMap*
+ g_abstract_inline_text_box_map_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h b/chromium/third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h
index b948bc287b7..9a3994b07c8 100644
--- a/chromium/third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h
+++ b/chromium/third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h
@@ -866,7 +866,8 @@ ALWAYS_INLINE bool BreakingContext::RewindToMidWordBreak(
x_pos_to_break += LayoutUnit::Epsilon();
if (run.Rtl())
x_pos_to_break = word_measurement.width - x_pos_to_break;
- len = font.OffsetForPosition(run, x_pos_to_break, false);
+ len = font.OffsetForPosition(run, x_pos_to_break, OnlyFullGlyphs,
+ DontBreakGlyphs);
int end = start + len;
if (len) {
end = break_iterator.PreviousBreakOpportunity(end, start);
@@ -900,14 +901,17 @@ ALWAYS_INLINE bool BreakingContext::Hyphenate(
float max_prefix_width = width_.AvailableWidth() - width_.CurrentWidth() -
hyphen_width - last_space_word_spacing;
- if (max_prefix_width <= Hyphenation::MinimumPrefixWidth(font))
+ if (max_prefix_width <=
+ font.GetFontDescription().MinimumPrefixWidthToHyphenate()) {
return false;
+ }
TextRun run = ConstructTextRun(font, text, start, len, style);
run.SetTabSize(!collapse_white_space_, style.GetTabSize());
run.SetXPos(width_.CurrentWidth());
- unsigned max_prefix_length =
- font.OffsetForPosition(run, max_prefix_width, false);
+ // TODO(fserb): Check if this need to be BreakGlyphs.
+ unsigned max_prefix_length = font.OffsetForPosition(
+ run, max_prefix_width, OnlyFullGlyphs, DontBreakGlyphs);
if (max_prefix_length < Hyphenation::kMinimumPrefixLength)
return false;
diff --git a/chromium/third_party/blink/renderer/core/layout/line/ellipsis_box.cc b/chromium/third_party/blink/renderer/core/layout/line/ellipsis_box.cc
index c0b4ef1a4ca..416e2791354 100644
--- a/chromium/third_party/blink/renderer/core/layout/line/ellipsis_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/line/ellipsis_box.cc
@@ -43,8 +43,8 @@ IntRect EllipsisBox::SelectionRect() const {
const Font& font = style.GetFont();
return EnclosingIntRect(font.SelectionRectForText(
ConstructTextRun(font, str_, style, TextRun::kAllowTrailingExpansion),
- IntPoint(LogicalLeft().ToInt(),
- (LogicalTop() + Root().SelectionTop()).ToInt()),
+ FloatPoint(LogicalLeft().ToInt(),
+ (LogicalTop() + Root().SelectionTop()).ToInt()),
Root().SelectionHeight().ToInt()));
}
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 5e707f5c9f9..91a6f9381fd 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
@@ -84,7 +84,7 @@ void* InlineBox::operator new(size_t sz) {
}
void InlineBox::operator delete(void* ptr) {
- WTF::PartitionFree(ptr);
+ base::PartitionFree(ptr);
}
const char* InlineBox::BoxName() const {
@@ -96,13 +96,11 @@ String InlineBox::DebugName() const {
}
LayoutRect InlineBox::VisualRect() const {
- // TODO(wangxianzhu): tighten it.
return GetLineLayoutItem().VisualRect();
}
-LayoutRect InlineBox::PartialInvalidationRect() const {
- // TODO(wangxianzhu): tighten it.
- return GetLineLayoutItem().PartialInvalidationRect();
+LayoutRect InlineBox::PartialInvalidationVisualRect() const {
+ return GetLineLayoutItem().PartialInvalidationVisualRect();
}
#ifndef NDEBUG
@@ -238,10 +236,10 @@ void InlineBox::Move(const LayoutSize& delta) {
}
void InlineBox::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset,
- LayoutUnit /* lineTop */,
- LayoutUnit /* lineBottom */) const {
- BlockPainter::PaintInlineBox(*this, paint_info, paint_offset);
+ const LayoutPoint&,
+ LayoutUnit,
+ LayoutUnit) const {
+ BlockPainter::PaintInlineBox(*this, paint_info);
}
bool InlineBox::NodeAtPoint(HitTestResult& result,
diff --git a/chromium/third_party/blink/renderer/core/layout/line/inline_box.h b/chromium/third_party/blink/renderer/core/layout/line/inline_box.h
index ae29ffb06f4..68b713b258a 100644
--- a/chromium/third_party/blink/renderer/core/layout/line/inline_box.h
+++ b/chromium/third_party/blink/renderer/core/layout/line/inline_box.h
@@ -41,14 +41,6 @@ class RootInlineBox;
enum MarkLineBoxes { kMarkLineBoxesDirty, kDontMarkLineBoxes };
-// Returns whether the position type is CSS "line-over"; i.e., ascender side
-// or "top" side of a line box.
-// https://drafts.csswg.org/css-writing-modes-3/#line-over
-static inline bool IsLineOverSide(FontVerticalPositionType type) {
- return type == FontVerticalPositionType::TextTop ||
- type == FontVerticalPositionType::TopOfEmHeight;
-}
-
// InlineBox represents a rectangle that occurs on a line. It corresponds to
// some LayoutObject (i.e., it represents a portion of that LayoutObject).
class CORE_EXPORT InlineBox : public DisplayItemClient {
@@ -139,7 +131,7 @@ class CORE_EXPORT InlineBox : public DisplayItemClient {
// DisplayItemClient methods
String DebugName() const override;
LayoutRect VisualRect() const override;
- LayoutRect PartialInvalidationRect() const override;
+ LayoutRect PartialInvalidationVisualRect() const override;
bool IsText() const { return bitfields_.IsText(); }
void SetIsText(bool is_text) { bitfields_.SetIsText(is_text); }
diff --git a/chromium/third_party/blink/renderer/core/layout/line/inline_text_box.cc b/chromium/third_party/blink/renderer/core/layout/line/inline_text_box.cc
index 4a8efe6dc91..80dca35b5f4 100644
--- a/chromium/third_party/blink/renderer/core/layout/line/inline_text_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/line/inline_text_box.cc
@@ -58,7 +58,7 @@ typedef WTF::HashMap<const InlineTextBox*, LayoutRect> InlineTextBoxOverflowMap;
static InlineTextBoxOverflowMap* g_text_boxes_with_overflow;
void InlineTextBox::Destroy() {
- AbstractInlineTextBox::WillDestroy(this);
+ LegacyAbstractInlineTextBox::WillDestroy(this);
if (!KnownToHaveNoOverflow() && g_text_boxes_with_overflow)
g_text_boxes_with_overflow->erase(this);
@@ -424,7 +424,10 @@ LayoutUnit InlineTextBox::PlaceEllipsisBox(bool flow_is_ltr,
// more accurate position in rtl text.
// TODO(crbug.com/722043: This doesn't always give the best results.
bool ltr = IsLeftToRightDirection();
- int offset = OffsetForPosition(ellipsis_x, !ltr);
+ int offset = OffsetForPosition(ellipsis_x,
+ ltr ? OnlyFullGlyphs : IncludePartialGlyphs,
+ DontBreakGlyphs);
+
// Full truncation is only necessary when we're flowing left-to-right.
if (flow_is_ltr && offset == 0 && ltr == flow_is_ltr) {
// No characters should be laid out. Set ourselves to full truncation and
@@ -625,7 +628,8 @@ LayoutUnit InlineTextBox::TextPos() const {
}
int InlineTextBox::OffsetForPosition(LayoutUnit line_offset,
- bool include_partial_glyphs) const {
+ IncludePartialGlyphsOption partial_glyphs,
+ BreakGlyphsOption break_glyphs) const {
if (IsLineBreak())
return 0;
@@ -639,7 +643,7 @@ int InlineTextBox::OffsetForPosition(LayoutUnit line_offset,
const Font& font = style.GetFont();
return font.OffsetForPosition(ConstructTextRun(style),
(line_offset - LogicalLeft()).ToFloat(),
- include_partial_glyphs);
+ partial_glyphs, break_glyphs);
}
LayoutUnit InlineTextBox::PositionForOffset(int offset) const {
@@ -655,10 +659,10 @@ LayoutUnit InlineTextBox::PositionForOffset(int offset) const {
int from = !IsLeftToRightDirection() ? offset - start_ : 0;
int to = !IsLeftToRightDirection() ? len_ : offset - start_;
// FIXME: Do we need to add rightBearing here?
- return LayoutUnit(
- font.SelectionRectForText(ConstructTextRun(style_to_use),
- IntPoint(LogicalLeft().ToInt(), 0), 0, from, to)
- .MaxX());
+ return LayoutUnit(font.SelectionRectForText(
+ ConstructTextRun(style_to_use),
+ FloatPoint(LogicalLeft().ToInt(), 0), 0, from, to)
+ .MaxX());
}
bool InlineTextBox::ContainsCaretOffset(int offset) const {
diff --git a/chromium/third_party/blink/renderer/core/layout/line/inline_text_box.h b/chromium/third_party/blink/renderer/core/layout/line/inline_text_box.h
index cace2c53f5a..fb346171800 100644
--- a/chromium/third_party/blink/renderer/core/layout/line/inline_text_box.h
+++ b/chromium/third_party/blink/renderer/core/layout/line/inline_text_box.h
@@ -206,7 +206,8 @@ class CORE_EXPORT InlineTextBox : public InlineBox {
public:
virtual int OffsetForPosition(LayoutUnit x,
- bool include_partial_glyphs = true) const;
+ IncludePartialGlyphsOption,
+ BreakGlyphsOption) const;
virtual LayoutUnit PositionForOffset(int offset) const;
// Returns false for offset after line break.
diff --git a/chromium/third_party/blink/renderer/core/layout/line/line_box_list.h b/chromium/third_party/blink/renderer/core/layout/line/line_box_list.h
index 6967cd82fad..9bb03d9ce19 100644
--- a/chromium/third_party/blink/renderer/core/layout/line/line_box_list.h
+++ b/chromium/third_party/blink/renderer/core/layout/line/line_box_list.h
@@ -47,7 +47,7 @@ class LineLayoutBoxModel;
class LineLayoutItem;
template <typename InlineBoxType>
-class CORE_TEMPLATE_CLASS_EXPORT InlineBoxList {
+class InlineBoxList {
DISALLOW_NEW();
public:
diff --git a/chromium/third_party/blink/renderer/core/layout/line/root_inline_box.cc b/chromium/third_party/blink/renderer/core/layout/line/root_inline_box.cc
index 8cb5e52f5be..04f3b7eb9aa 100644
--- a/chromium/third_party/blink/renderer/core/layout/line/root_inline_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/line/root_inline_box.cc
@@ -722,12 +722,11 @@ LayoutUnit RootInlineBox::VerticalPositionForBox(
BaselineType(), first_line, line_direction) -
font_metrics.Ascent(BaselineType());
} else if (vertical_align == EVerticalAlign::kMiddle) {
- vertical_position = LayoutUnit(
- (vertical_position - LayoutUnit(font_metrics.XHeight() / 2) -
- box_model.LineHeight(first_line, line_direction) / 2 +
- box_model.BaselinePosition(BaselineType(), first_line,
- line_direction))
- .Round());
+ vertical_position = vertical_position -
+ LayoutUnit(font_metrics.XHeight() / 2) -
+ box_model.LineHeight(first_line, line_direction) / 2 +
+ box_model.BaselinePosition(BaselineType(), first_line,
+ line_direction);
} else if (vertical_align == EVerticalAlign::kTextBottom) {
vertical_position += font_metrics.Descent(BaselineType());
// lineHeight - baselinePosition is always 0 for replaced elements (except
diff --git a/chromium/third_party/blink/renderer/core/layout/map_coordinates_flags.h b/chromium/third_party/blink/renderer/core/layout/map_coordinates_flags.h
index 5a3af39fece..08bb2ceeac2 100644
--- a/chromium/third_party/blink/renderer/core/layout/map_coordinates_flags.h
+++ b/chromium/third_party/blink/renderer/core/layout/map_coordinates_flags.h
@@ -19,20 +19,13 @@ enum MapCoordinatesMode {
kApplyContainerFlip = 1 << 2,
kTraverseDocumentBoundaries = 1 << 3,
- // Applies to LayoutView::mapLocalToAncestor() and LayoutView::
- // mapToVisualRectInAncestorSpace() only, to indicate the input point or rect
- // is in frame coordinates instead of frame contents coordinates. This
- // disables view clipping and scroll offset adjustment.
- // TODO(wangxianzhu): Remove this when root-layer-scrolls launches.
- kInputIsInFrameCoordinates = 1 << 4,
-
// Ignore offset adjustments caused by position:sticky calculations when
// walking the chain.
- kIgnoreStickyOffset = 1 << 5,
+ kIgnoreStickyOffset = 1 << 4,
// Ignore scroll offset from container, i.e. scrolling has no effect on mapped
// position.
- kIgnoreScrollOffset = 1 << 6,
+ kIgnoreScrollOffset = 1 << 5,
};
typedef unsigned MapCoordinatesFlags;
diff --git a/chromium/third_party/blink/renderer/core/layout/map_coordinates_test.cc b/chromium/third_party/blink/renderer/core/layout/map_coordinates_test.cc
index dc608308fa3..c6bca021396 100644
--- a/chromium/third_party/blink/renderer/core/layout/map_coordinates_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/map_coordinates_test.cc
@@ -5,6 +5,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
#include "third_party/blink/renderer/core/layout/layout_view.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/transforms/transform_state.h"
@@ -549,14 +550,11 @@ TEST_F(MapCoordinatesTest, FixedPosInFixedPosScrollView) {
LayoutBox* view = html->ParentBox();
ASSERT_TRUE(view->IsLayoutView());
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0.0, 50), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0.0, 50),
+ kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_EQ(50, GetDocument()
- .View()
- ->LayoutViewportScrollableArea()
- ->ScrollOffsetInt()
- .Height());
+ EXPECT_EQ(50,
+ GetDocument().View()->LayoutViewport()->ScrollOffsetInt().Height());
FloatPoint mapped_point = MapLocalToAncestor(target, view, FloatPoint());
EXPECT_EQ(AdjustForFrameScroll(FloatPoint(200, 250)), mapped_point);
@@ -585,14 +583,11 @@ TEST_F(MapCoordinatesTest, FixedPosInAbsolutePosScrollView) {
LayoutBox* view = html->ParentBox();
ASSERT_TRUE(view->IsLayoutView());
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0.0, 50), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0.0, 50),
+ kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_EQ(50, GetDocument()
- .View()
- ->LayoutViewportScrollableArea()
- ->ScrollOffsetInt()
- .Height());
+ EXPECT_EQ(50,
+ GetDocument().View()->LayoutViewport()->ScrollOffsetInt().Height());
FloatPoint mapped_point = MapLocalToAncestor(target, view, FloatPoint());
EXPECT_EQ(AdjustForFrameScroll(FloatPoint(200, 250)), mapped_point);
@@ -615,14 +610,11 @@ TEST_F(MapCoordinatesTest, FixedPosInTransform) {
<div class='spacer'></div>
)HTML");
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0.0, 50), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0.0, 50),
+ kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_EQ(50, GetDocument()
- .View()
- ->LayoutViewportScrollableArea()
- ->ScrollOffsetInt()
- .Height());
+ EXPECT_EQ(50,
+ GetDocument().View()->LayoutViewport()->ScrollOffsetInt().Height());
LayoutBox* target = ToLayoutBox(GetLayoutObjectByElementId("target"));
LayoutBox* container = ToLayoutBox(GetLayoutObjectByElementId("container"));
@@ -657,14 +649,11 @@ TEST_F(MapCoordinatesTest, FixedPosInContainPaint) {
<div class='spacer'></div>
)HTML");
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0.0, 50), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0.0, 50),
+ kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_EQ(50, GetDocument()
- .View()
- ->LayoutViewportScrollableArea()
- ->ScrollOffsetInt()
- .Height());
+ EXPECT_EQ(50,
+ GetDocument().View()->LayoutViewport()->ScrollOffsetInt().Height());
LayoutBox* target = ToLayoutBox(GetLayoutObjectByElementId("target"));
LayoutBox* container = ToLayoutBox(GetLayoutObjectByElementId("container"));
@@ -703,7 +692,7 @@ TEST_F(MapCoordinatesTest, FixedPosInIFrameWhenMainFrameScrolled) {
"<style>body { margin: 0; } #target { width: 200px; height: 200px; "
"position:fixed}</style><div id=target></div>");
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0.0, 1000), kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
@@ -734,7 +723,7 @@ TEST_F(MapCoordinatesTest, IFrameTransformed) {
GetDocument().View()->UpdateAllLifecyclePhases();
- ChildDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
+ ChildDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0.0, 1000), kProgrammaticScroll);
ChildDocument().View()->UpdateAllLifecyclePhases();
@@ -770,7 +759,7 @@ TEST_F(MapCoordinatesTest, FixedPosInScrolledIFrameWithTransform) {
)HTML");
GetDocument().View()->UpdateAllLifecyclePhases();
- ChildDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
+ ChildDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0.0, 1000), kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
diff --git a/chromium/third_party/blink/renderer/core/layout/min_max_size.cc b/chromium/third_party/blink/renderer/core/layout/min_max_size.cc
index af63404c276..3cd2e563726 100644
--- a/chromium/third_party/blink/renderer/core/layout/min_max_size.cc
+++ b/chromium/third_party/blink/renderer/core/layout/min_max_size.cc
@@ -23,6 +23,12 @@ MinMaxSize& MinMaxSize::operator+=(const LayoutUnit length) {
return *this;
}
+MinMaxSize& MinMaxSize::operator-=(const LayoutUnit length) {
+ min_size -= length;
+ max_size -= length;
+ return *this;
+}
+
std::ostream& operator<<(std::ostream& stream, const MinMaxSize& value) {
return stream << "(" << value.min_size << ", " << value.max_size << ")";
}
diff --git a/chromium/third_party/blink/renderer/core/layout/min_max_size.h b/chromium/third_party/blink/renderer/core/layout/min_max_size.h
index 6a1f67bd4d0..c760104d808 100644
--- a/chromium/third_party/blink/renderer/core/layout/min_max_size.h
+++ b/chromium/third_party/blink/renderer/core/layout/min_max_size.h
@@ -30,6 +30,7 @@ struct CORE_EXPORT MinMaxSize {
}
MinMaxSize& operator+=(const LayoutUnit);
+ MinMaxSize& operator-=(const LayoutUnit);
};
CORE_EXPORT std::ostream& operator<<(std::ostream&, const MinMaxSize&);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion.cc b/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion.cc
new file mode 100644
index 00000000000..66d3f693cf8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion.cc
@@ -0,0 +1,13 @@
+// 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/layout/ng/exclusions/ng_exclusion.h"
+
+namespace blink {
+
+bool NGExclusion::operator==(const NGExclusion& other) const {
+ return std::tie(other.rect, other.type) == std::tie(rect, type);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion.h b/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion.h
new file mode 100644
index 00000000000..1a67e0d14f0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion.h
@@ -0,0 +1,54 @@
+// 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_EXCLUSIONS_NG_EXCLUSION_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_EXCLUSIONS_NG_EXCLUSION_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_rect.h"
+#include "third_party/blink/renderer/core/style/computed_style_constants.h"
+#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
+
+namespace blink {
+
+class LayoutBox;
+
+struct CORE_EXPORT NGExclusionShapeData {
+ NGExclusionShapeData(const LayoutBox* layout_box,
+ const NGBoxStrut& margins,
+ const NGBoxStrut& shape_insets)
+ : layout_box(layout_box), margins(margins), shape_insets(shape_insets) {}
+
+ const LayoutBox* layout_box;
+ const NGBoxStrut margins;
+ const NGBoxStrut shape_insets;
+};
+
+// Struct that represents an exclusion. This currently is just a float but
+// we've named it an exclusion to potentially support other types in the future.
+struct CORE_EXPORT NGExclusion : public RefCounted<NGExclusion> {
+ static scoped_refptr<NGExclusion> Create(
+ const NGBfcRect& rect,
+ const EFloat type,
+ std::unique_ptr<NGExclusionShapeData> shape_data = nullptr) {
+ return base::AdoptRef(new NGExclusion(rect, type, std::move(shape_data)));
+ }
+
+ const NGBfcRect rect;
+ const EFloat type;
+ const std::unique_ptr<NGExclusionShapeData> shape_data;
+
+ bool operator==(const NGExclusion& other) const;
+ bool operator!=(const NGExclusion& other) const { return !(*this == other); }
+
+ private:
+ NGExclusion(const NGBfcRect& rect,
+ const EFloat type,
+ std::unique_ptr<NGExclusionShapeData> shape_data)
+ : rect(rect), type(type), shape_data(std::move(shape_data)) {}
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_EXCLUSIONS_NG_EXCLUSION_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.cc b/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.cc
index 3c572fb11eb..2ce9008b4b1 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.cc
@@ -4,7 +4,8 @@
#include "third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_exclusion.h"
+#include "base/optional.h"
+#include "third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion.h"
namespace blink {
@@ -16,7 +17,7 @@ namespace {
// We don't explicitly check the inline-size/block-size of the opportunity as
// they are always produced in the order.
void InsertOpportunity(const NGLayoutOpportunity& opportunity,
- Vector<NGLayoutOpportunity>* opportunities) {
+ Vector<NGLayoutOpportunity, 4>* opportunities) {
if (opportunities->IsEmpty()) {
opportunities->push_back(opportunity);
return;
@@ -162,6 +163,20 @@ NGLayoutOpportunity CreateLayoutOpportunity(
} // namespace
NGExclusionSpace::NGExclusionSpace()
+ : exclusions_(RefVector<scoped_refptr<const NGExclusion>>::Create()),
+ num_exclusions_(0),
+ derived_geometry_(nullptr) {}
+
+NGExclusionSpace::NGExclusionSpace(const NGExclusionSpace& other)
+ : exclusions_(other.exclusions_),
+ num_exclusions_(other.num_exclusions_),
+ derived_geometry_(std::move(other.derived_geometry_)) {
+ // This copy-constructor does fun things. It moves the derived_geometry_ to
+ // the newly created exclusion space where it'll more-likely be used.
+ other.derived_geometry_ = nullptr;
+}
+
+NGExclusionSpace::DerivedGeometry::DerivedGeometry()
: last_float_block_start_(LayoutUnit::Min()),
left_float_clear_offset_(LayoutUnit::Min()),
right_float_clear_offset_(LayoutUnit::Min()) {
@@ -170,6 +185,30 @@ NGExclusionSpace::NGExclusionSpace()
}
void NGExclusionSpace::Add(scoped_refptr<const NGExclusion> exclusion) {
+ DCHECK_LE(num_exclusions_, exclusions_->size());
+
+ // Perform a copy-on-write if the number of exclusions has gone out of sync.
+ if (num_exclusions_ != exclusions_->size()) {
+ scoped_refptr<RefVector<scoped_refptr<const NGExclusion>>> exclusions =
+ RefVector<scoped_refptr<const NGExclusion>>::Create();
+ exclusions->GetMutableVector()->AppendRange(
+ exclusions_->GetVector().begin(),
+ exclusions_->GetVector().begin() + num_exclusions_);
+ std::swap(exclusions_, exclusions);
+
+ // The derived_geometry_ is now invalid.
+ derived_geometry_ = nullptr;
+ }
+
+ if (derived_geometry_)
+ derived_geometry_->Add(exclusion);
+
+ exclusions_->push_back(std::move(exclusion));
+ num_exclusions_++;
+}
+
+void NGExclusionSpace::DerivedGeometry::Add(
+ scoped_refptr<const NGExclusion> exclusion) {
last_float_block_start_ =
std::max(last_float_block_start_, exclusion->rect.BlockStartOffset());
@@ -197,13 +236,36 @@ void NGExclusionSpace::Add(scoped_refptr<const NGExclusion> exclusion) {
//
// NOTE: This could potentially be done lazily when we query the exclusion
// space for a layout opportunity.
- for (size_t i = 0; i < shelves_.size();) {
+ for (size_t i = 0; i < shelves_.size(); ++i) {
+ // Check if we need to insert a new shelf between two other shelves. E.g.
+ //
+ // 0 1 2 3 4 5 6 7 8
+ // 0 +-----+X----X+---+
+ // |xxxxx| |xxx|
+ // 10 +-----+ |xxx|
+ // +---+ |xxx|
+ // 20 |NEW| |xxx|
+ // X-----------X|xxx|
+ // 30 |xxx|
+ // X----------------X
+ //
+ // In the above example the "NEW" left exclusion creates a shelf between
+ // the two other shelves drawn.
+ //
+ // NOTE: We calculate this upfront as we may remove the shelf we need to
+ // check against.
+ //
+ // NOTE: If there is no "next" shelf, we consider this between shelves.
+ bool is_between_shelves =
+ exclusion_end_offset >= shelves_[i].block_offset &&
+ (i + 1 >= shelves_.size() ||
+ exclusion_end_offset < shelves_[i + 1].block_offset);
+
// We modify the current shelf in-place. However we need to keep a copy of
// the shelf if we need to insert a new shelf later in the loop.
- NGShelf shelf_copy(shelves_[i]);
-
- bool is_between_shelves;
- bool removed_shelf = false;
+ base::Optional<NGShelf> shelf_copy;
+ if (is_between_shelves)
+ shelf_copy = shelves_[i];
// A new scope is created as shelf may be removed.
{
@@ -303,31 +365,6 @@ void NGExclusionSpace::Add(scoped_refptr<const NGExclusion> exclusion) {
bool is_intersecting =
!is_below && exclusion_end_offset > shelf.block_offset;
- // Check if we need to insert a new shelf between two other shelves. E.g.
- // two other shelves. E.g.
- //
- // 0 1 2 3 4 5 6 7 8
- // 0 +-----+X----X+---+
- // |xxxxx| |xxx|
- // 10 +-----+ |xxx|
- // +---+ |xxx|
- // 20 |NEW| |xxx|
- // X-----------X|xxx|
- // 30 |xxx|
- // X----------------X
- //
- // In the above example the "NEW" left exclusion creates a shelf between
- // the two other shelves drawn.
- //
- // NOTE: We calculate this before we need it as the next if-statement
- // block may remove the shelf that we need to check against.
- //
- // NOTE: If there is no "next" shelf, we consider this between shelves.
- is_between_shelves =
- exclusion_end_offset >= shelf.block_offset &&
- (i + 1 >= shelves_.size() ||
- exclusion_end_offset < shelves_[i + 1].block_offset);
-
// We need to reduce the size of the shelf.
if (is_below || is_intersecting) {
if (exclusion->type == EFloat::kLeft) {
@@ -382,7 +419,7 @@ void NGExclusionSpace::Add(scoped_refptr<const NGExclusion> exclusion) {
shelf.line_right == shelves_[i - 1].line_right;
if (is_same_as_previous) {
shelves_.EraseAt(i);
- removed_shelf = true;
+ --i;
}
}
}
@@ -392,48 +429,43 @@ void NGExclusionSpace::Add(scoped_refptr<const NGExclusion> exclusion) {
DCHECK(!inserted);
inserted = true;
#endif
+ DCHECK(shelf_copy.has_value());
// We only want to add the shelf if it's at a different block offset.
- if (exclusion_end_offset != shelf_copy.block_offset) {
+ if (exclusion_end_offset != shelf_copy->block_offset) {
NGShelf new_shelf(/* block_offset */ exclusion_end_offset);
- CollectSolidEdges(shelf_copy.line_left_edges, new_shelf.block_offset,
+ CollectSolidEdges(shelf_copy->line_left_edges, new_shelf.block_offset,
&new_shelf.line_left_edges);
- CollectSolidEdges(shelf_copy.line_right_edges, new_shelf.block_offset,
+ CollectSolidEdges(shelf_copy->line_right_edges, new_shelf.block_offset,
&new_shelf.line_right_edges);
// If we didn't find any edges, the line_left/line_right of the shelf
// are pushed out to be the minimum/maximum.
new_shelf.line_left = new_shelf.line_left_edges.IsEmpty()
? LayoutUnit::Min()
- : shelf_copy.line_left;
+ : shelf_copy->line_left;
new_shelf.line_right = new_shelf.line_right_edges.IsEmpty()
? LayoutUnit::Max()
- : shelf_copy.line_right;
+ : shelf_copy->line_right;
- size_t insert_index = removed_shelf ? i : i + 1;
- shelves_.insert(insert_index, new_shelf);
+ shelves_.insert(i + 1, new_shelf);
}
// It's safe to early exit out of this loop now. This exclusion won't
// have any effect on subsequent shelves.
break;
}
-
- if (!removed_shelf)
- ++i;
}
#if DCHECK_IS_ON()
// We must have performed a new shelf insertion.
DCHECK(inserted);
#endif
-
- exclusions_.push_back(std::move(exclusion));
}
-NGLayoutOpportunity NGExclusionSpace::FindLayoutOpportunity(
+NGLayoutOpportunity NGExclusionSpace::DerivedGeometry::FindLayoutOpportunity(
const NGBfcOffset& offset,
const LayoutUnit available_inline_size,
const NGLogicalSize& minimum_size) const {
@@ -459,7 +491,8 @@ NGLayoutOpportunity NGExclusionSpace::FindLayoutOpportunity(
return NGLayoutOpportunity();
}
-Vector<NGLayoutOpportunity> NGExclusionSpace::AllLayoutOpportunities(
+Vector<NGLayoutOpportunity>
+NGExclusionSpace::DerivedGeometry::AllLayoutOpportunities(
const NGBfcOffset& offset,
const LayoutUnit available_inline_size) const {
Vector<NGLayoutOpportunity> opportunities;
@@ -515,7 +548,8 @@ Vector<NGLayoutOpportunity> NGExclusionSpace::AllLayoutOpportunities(
return opportunities;
}
-LayoutUnit NGExclusionSpace::ClearanceOffset(EClear clear_type) const {
+LayoutUnit NGExclusionSpace::DerivedGeometry::ClearanceOffset(
+ EClear clear_type) const {
switch (clear_type) {
case EClear::kNone:
return LayoutUnit::Min(); // Nothing to do here.
@@ -532,8 +566,22 @@ LayoutUnit NGExclusionSpace::ClearanceOffset(EClear clear_type) const {
return LayoutUnit::Min();
}
+const NGExclusionSpace::DerivedGeometry& NGExclusionSpace::GetDerivedGeometry()
+ const {
+ // Re-build the geometry if it isn't present.
+ if (!derived_geometry_) {
+ derived_geometry_ = std::make_unique<DerivedGeometry>();
+ DCHECK_LE(num_exclusions_, exclusions_->size());
+ for (size_t i = 0; i < num_exclusions_; ++i)
+ derived_geometry_->Add(exclusions_->GetVector()[i]);
+ }
+
+ return *derived_geometry_;
+}
+
bool NGExclusionSpace::operator==(const NGExclusionSpace& other) const {
- return exclusions_ == other.exclusions_;
+ return num_exclusions_ == other.num_exclusions_ &&
+ exclusions_ == other.exclusions_;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h b/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h
index 190a934ae6e..1907888de13 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion_space.h
@@ -6,12 +6,13 @@
#define NGExclusionSpace_h
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion.h"
#include "third_party/blink/renderer/core/layout/ng/exclusions/ng_layout_opportunity.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_offset.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_rect.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_exclusion.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
#include "third_party/blink/renderer/platform/layout_unit.h"
+#include "third_party/blink/renderer/platform/wtf/ref_vector.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -24,6 +25,7 @@ namespace blink {
class CORE_EXPORT NGExclusionSpace {
public:
NGExclusionSpace();
+ NGExclusionSpace(const NGExclusionSpace&);
~NGExclusionSpace(){};
void Add(scoped_refptr<const NGExclusion> exclusion);
@@ -35,17 +37,27 @@ class CORE_EXPORT NGExclusionSpace {
NGLayoutOpportunity FindLayoutOpportunity(
const NGBfcOffset& offset,
const LayoutUnit available_inline_size,
- const NGLogicalSize& minimum_size) const;
+ const NGLogicalSize& minimum_size) const {
+ return GetDerivedGeometry().FindLayoutOpportunity(
+ offset, available_inline_size, minimum_size);
+ }
Vector<NGLayoutOpportunity> AllLayoutOpportunities(
const NGBfcOffset& offset,
- const LayoutUnit available_inline_size) const;
+ const LayoutUnit available_inline_size) const {
+ return GetDerivedGeometry().AllLayoutOpportunities(offset,
+ available_inline_size);
+ }
// Returns the clearance offset based on the provided {@code clear_type}.
- LayoutUnit ClearanceOffset(EClear clear_type) const;
+ LayoutUnit ClearanceOffset(EClear clear_type) const {
+ return GetDerivedGeometry().ClearanceOffset(clear_type);
+ }
// Returns the block start offset of the last float added.
- LayoutUnit LastFloatBlockStart() const { return last_float_block_start_; }
+ LayoutUnit LastFloatBlockStart() const {
+ return GetDerivedGeometry().LastFloatBlockStart();
+ }
bool operator==(const NGExclusionSpace& other) const;
bool operator!=(const NGExclusionSpace& other) const {
@@ -119,52 +131,105 @@ class CORE_EXPORT NGExclusionSpace {
};
private:
- Vector<scoped_refptr<const NGExclusion>> exclusions_;
-
- // See NGShelf for a broad description of what shelves are. We always begin
- // with one, which has the internal value of:
- // {
- // block_offset: LayoutUnit::Min(),
- // line_left: LayoutUnit::Min(),
- // line_right: LayoutUnit::Max(),
- // }
+ // In order to reduce the amount of Vector copies, instances of a
+ // NGExclusionSpace can share the same exclusions_ Vector. See the copy
+ // constructor.
//
- // The list of opportunities represent "closed-off" areas. E.g.
+ // We implement a copy-on-write behaviour when adding an exclusion (if
+ // exclusions_.size(), and num_exclusions_ differs).
//
- // 0 1 2 3 4 5 6 7 8
- // 0 +---+. .+---+
- // |xxx|. .|xxx|
- // 10 |xxx|. .|xxx|
- // +---+. .+---+
- // 20 ........
- // +---+
- // 30 |xxx|
- // |xxx|
- // 40 +---+
+ // num_exclusions_ is how many exclusions *this* instance of an exclusion
+ // space has, which may differ to the number of exclusions in the Vector.
+ scoped_refptr<RefVector<scoped_refptr<const NGExclusion>>> exclusions_;
+ size_t num_exclusions_;
+
+ // The derived geometry struct, is the data-structure which handles all of the
+ // queries on the exclusion space. It can always be rebuilt from exclusions_
+ // and num_exclusions_. This is mutable as it is passed down a chain of
+ // exclusion spaces inside the copy constructor. E.g.
//
- // In the above example the opportunity is represented with the dotted line.
- // It has the internal values of:
- // {
- // start_offset: {20, LayoutUnit::Min()},
- // end_offset: {65, 25},
- // }
- // Once an opportunity has been created, it can never been changed due to the
- // property that floats always align their block-start edges.
+ // NGExclusionSpace space1;
+ // space1.Add(exclusion1);
+ // space1.LastFloatBlockStart(); // Builds derived_geometry_ to answer query.
+ //
+ // NGExclusionSpace space2(space1); // Moves derived_geometry_ to space2.
+ // space2.Add(exclusion2); // Modifies derived_geometry_.
+ //
+ // space1.LastFloatBlockStart(); // Re-builds derived_geometry_.
//
- // We exploit this property by keeping this list of "closed-off" areas, and
- // removing shelves to make insertion faster.
- Vector<NGShelf> shelves_;
- Vector<NGLayoutOpportunity> opportunities_;
-
- // This member is used for implementing the "top edge alignment rule" for
- // floats. Floats can be positioned at negative offsets, hence is initialized
- // the minimum value.
- LayoutUnit last_float_block_start_;
-
- // These members are used for keeping track of the "lowest" offset for each
- // type of float. This is used for implementing float clearance.
- LayoutUnit left_float_clear_offset_;
- LayoutUnit right_float_clear_offset_;
+ // This is efficient (desirable) as the common usage pattern is only the last
+ // exclusion space in the copy-chain is used for answering queries. Only when
+ // we trigger a (rare) re-layout case will we need to rebuild the
+ // derived_geometry_ data-structure.
+ struct DerivedGeometry {
+ DerivedGeometry();
+
+ void Add(scoped_refptr<const NGExclusion> exclusion);
+
+ NGLayoutOpportunity FindLayoutOpportunity(
+ const NGBfcOffset& offset,
+ const LayoutUnit available_inline_size,
+ const NGLogicalSize& minimum_size) const;
+
+ Vector<NGLayoutOpportunity> AllLayoutOpportunities(
+ const NGBfcOffset& offset,
+ const LayoutUnit available_inline_size) const;
+
+ LayoutUnit ClearanceOffset(EClear clear_type) const;
+ LayoutUnit LastFloatBlockStart() const { return last_float_block_start_; }
+
+ // See NGShelf for a broad description of what shelves are. We always begin
+ // with one, which has the internal value of:
+ // {
+ // block_offset: LayoutUnit::Min(),
+ // line_left: LayoutUnit::Min(),
+ // line_right: LayoutUnit::Max(),
+ // }
+ //
+ // The list of opportunities represent "closed-off" areas. E.g.
+ //
+ // 0 1 2 3 4 5 6 7 8
+ // 0 +---+. .+---+
+ // |xxx|. .|xxx|
+ // 10 |xxx|. .|xxx|
+ // +---+. .+---+
+ // 20 ........
+ // +---+
+ // 30 |xxx|
+ // |xxx|
+ // 40 +---+
+ //
+ // In the above example the opportunity is represented with the dotted line.
+ // It has the internal values of:
+ // {
+ // start_offset: {20, LayoutUnit::Min()},
+ // end_offset: {65, 25},
+ // }
+ // Once an opportunity has been created, it can never been changed due to
+ // the property that floats always align their block-start edges.
+ //
+ // We exploit this property by keeping this list of "closed-off" areas, and
+ // removing shelves to make insertion faster.
+ Vector<NGShelf, 4> shelves_;
+ Vector<NGLayoutOpportunity, 4> opportunities_;
+
+ // This member is used for implementing the "top edge alignment rule" for
+ // floats. Floats can be positioned at negative offsets, hence is
+ // initialized the minimum value.
+ LayoutUnit last_float_block_start_;
+
+ // These members are used for keeping track of the "lowest" offset for each
+ // type of float. This is used for implementing float clearance.
+ LayoutUnit left_float_clear_offset_;
+ LayoutUnit right_float_clear_offset_;
+ };
+
+ // Returns the derived_geometry_ member, potentially re-built from the
+ // exclusions_, and num_exclusions_ members.
+ const DerivedGeometry& GetDerivedGeometry() const;
+
+ // See DerivedGeometry struct description.
+ mutable std::unique_ptr<DerivedGeometry> derived_geometry_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_layout_opportunity.cc b/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_layout_opportunity.cc
index 34d8691aac6..0672d751fc4 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_layout_opportunity.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_layout_opportunity.cc
@@ -123,14 +123,16 @@ LayoutUnit NGLayoutOpportunity::ComputeLineLeftOffset(
// increasing the line_left when an exclusion intersects.
LayoutUnit line_left = space.BfcOffset().line_offset;
for (auto& exclusion : shape_exclusions->line_left_shapes) {
+ if (!IntersectsExclusion(*exclusion, bfc_block_offset, line_block_size))
+ continue;
+
if (exclusion->shape_data) {
LineSegment segment =
ExcludedSegment(*exclusion, bfc_block_offset, line_block_size);
if (segment.is_valid)
line_left = std::max(line_left, segment.logical_right);
} else {
- if (IntersectsExclusion(*exclusion, bfc_block_offset, line_block_size))
- line_left = std::max(line_left, exclusion->rect.LineEndOffset());
+ line_left = std::max(line_left, exclusion->rect.LineEndOffset());
}
}
@@ -155,14 +157,16 @@ LayoutUnit NGLayoutOpportunity::ComputeLineRightOffset(
// We rebuild this offset from the line-right end, checking each exclusion and
// reducing the line_right when an exclusion intersects.
for (auto& exclusion : shape_exclusions->line_right_shapes) {
+ if (!IntersectsExclusion(*exclusion, bfc_block_offset, line_block_size))
+ continue;
+
if (exclusion->shape_data) {
LineSegment segment =
ExcludedSegment(*exclusion, bfc_block_offset, line_block_size);
if (segment.is_valid)
line_right = std::min(line_right, segment.logical_left);
} else {
- if (IntersectsExclusion(*exclusion, bfc_block_offset, line_block_size))
- line_right = std::min(line_right, exclusion->rect.LineStartOffset());
+ line_right = std::min(line_right, exclusion->rect.LineStartOffset());
}
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_shape_exclusions.h b/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_shape_exclusions.h
index 8130c956c7f..667d37fa45c 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_shape_exclusions.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/exclusions/ng_shape_exclusions.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_EXCLUSIONS_NG_SHAPE_EXCLUSIONS_H_
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_exclusion.h"
+#include "third_party/blink/renderer/core/layout/ng/exclusions/ng_exclusion.h"
#include "third_party/blink/renderer/platform/layout_unit.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.cc b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.cc
index d9456df52e4..88fdc42ff13 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.cc
@@ -80,6 +80,28 @@ std::ostream& operator<<(std::ostream& stream, const NGBoxStrut& value) {
return stream << value.ToString();
}
+NGBoxStrut::NGBoxStrut(const NGLineBoxStrut& line_relative,
+ bool is_flipped_lines) {
+ if (!is_flipped_lines) {
+ *this = {line_relative.inline_start, line_relative.inline_end,
+ line_relative.line_over, line_relative.line_under};
+ } else {
+ *this = {line_relative.inline_start, line_relative.inline_end,
+ line_relative.line_under, line_relative.line_over};
+ }
+}
+
+NGLineBoxStrut::NGLineBoxStrut(const NGBoxStrut& flow_relative,
+ bool is_flipped_lines) {
+ if (!is_flipped_lines) {
+ *this = {flow_relative.inline_start, flow_relative.inline_end,
+ flow_relative.block_start, flow_relative.block_end};
+ } else {
+ *this = {flow_relative.inline_start, flow_relative.inline_end,
+ flow_relative.block_end, flow_relative.block_start};
+ }
+}
+
NGPixelSnappedPhysicalBoxStrut NGPhysicalBoxStrut::SnapToDevicePixels() const {
return NGPixelSnappedPhysicalBoxStrut(top.Round(), right.Round(),
bottom.Round(), left.Round());
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h
index c6566b7652c..dc01037d61b 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h
@@ -13,6 +13,7 @@
namespace blink {
+struct NGLineBoxStrut;
struct NGPhysicalBoxStrut;
// This struct is used for storing margins, borders or padding of a box on all
@@ -27,6 +28,7 @@ struct CORE_EXPORT NGBoxStrut {
inline_end(inline_end),
block_start(block_start),
block_end(block_end) {}
+ NGBoxStrut(const NGLineBoxStrut&, bool is_flipped_lines);
LayoutUnit LineLeft(TextDirection direction) const {
return IsLtr(direction) ? inline_start : inline_end;
@@ -86,6 +88,33 @@ struct CORE_EXPORT NGBoxStrut {
CORE_EXPORT std::ostream& operator<<(std::ostream&, const NGBoxStrut&);
+// A variant of NGBoxStrut in the line-relative coordinate system.
+//
+// 'line-over' is 'block-start' and 'line-under' is 'block-end' unless it is in
+// flipped-lines writing-mode (i.e., 'vertical-lr'), in which case they are
+// swapped.
+//
+// https://drafts.csswg.org/css-writing-modes-3/#line-mappings
+struct CORE_EXPORT NGLineBoxStrut {
+ NGLineBoxStrut() = default;
+ NGLineBoxStrut(LayoutUnit inline_start,
+ LayoutUnit inline_end,
+ LayoutUnit line_over,
+ LayoutUnit line_under)
+ : inline_start(inline_start),
+ inline_end(inline_end),
+ line_over(line_over),
+ line_under(line_under) {}
+ NGLineBoxStrut(const NGBoxStrut&, bool is_flipped_lines);
+
+ LayoutUnit InlineSum() const { return inline_start + inline_end; }
+
+ LayoutUnit inline_start;
+ LayoutUnit inline_end;
+ LayoutUnit line_over;
+ LayoutUnit line_under;
+};
+
struct NGPixelSnappedPhysicalBoxStrut;
// Struct to store physical dimensions, independent of writing mode and
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_margin_strut.cc b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_margin_strut.cc
index 924c5699f14..dac9dbeeccc 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_margin_strut.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_margin_strut.cc
@@ -9,10 +9,14 @@
namespace blink {
LayoutUnit NGMarginStrut::Sum() const {
+ if (discard_margins)
+ return LayoutUnit();
return std::max(quirky_positive_margin, positive_margin) + negative_margin;
}
LayoutUnit NGMarginStrut::QuirkyContainerSum() const {
+ if (discard_margins)
+ return LayoutUnit();
return positive_margin + negative_margin;
}
@@ -34,6 +38,8 @@ void NGMarginStrut::Append(const LayoutUnit& value, bool is_quirky) {
}
bool NGMarginStrut::IsEmpty() const {
+ if (discard_margins)
+ return true;
return positive_margin == LayoutUnit() && negative_margin == LayoutUnit() &&
quirky_positive_margin == LayoutUnit();
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_margin_strut.h b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_margin_strut.h
index 8e2e7e44a6b..e46e7a73bf1 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_margin_strut.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/geometry/ng_margin_strut.h
@@ -24,6 +24,10 @@ struct CORE_EXPORT NGMarginStrut {
// See comment inside NGBlockLayoutAlgorithm for when this occurs.
bool is_quirky_container_start = false;
+ // If set, we will discard all adjoining margins, which is the
+ // effect of -webkit-margin-collapse:discard.
+ bool discard_margins = false;
+
// Appends negative or positive value to the current margin strut.
void Append(const LayoutUnit& value, bool is_quirky);
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
new file mode 100644
index 00000000000..614d0403810
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.cc
@@ -0,0 +1,224 @@
+// 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/layout/ng/inline/ng_abstract_inline_text_box.h"
+
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.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_physical_text_fragment.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h"
+#include "third_party/blink/renderer/platform/fonts/character_range.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h"
+
+namespace blink {
+
+NGAbstractInlineTextBox::FragmentToNGAbstractInlineTextBoxHashMap*
+ NGAbstractInlineTextBox::g_abstract_inline_text_box_map_ = nullptr;
+
+scoped_refptr<AbstractInlineTextBox> NGAbstractInlineTextBox::GetOrCreate(
+ LineLayoutText line_layout_item,
+ const NGPaintFragment& fragment) {
+ DCHECK(fragment.GetLayoutObject()->IsText()) << fragment.GetLayoutObject();
+ if (!g_abstract_inline_text_box_map_) {
+ g_abstract_inline_text_box_map_ =
+ new FragmentToNGAbstractInlineTextBoxHashMap();
+ }
+ const auto it = g_abstract_inline_text_box_map_->find(&fragment);
+ if (it != g_abstract_inline_text_box_map_->end())
+ return it->value;
+ scoped_refptr<AbstractInlineTextBox> obj =
+ base::AdoptRef(new NGAbstractInlineTextBox(line_layout_item, fragment));
+ g_abstract_inline_text_box_map_->Set(&fragment, obj);
+ return obj;
+}
+
+void NGAbstractInlineTextBox::WillDestroy(NGPaintFragment* fragment) {
+ if (!g_abstract_inline_text_box_map_)
+ return;
+ const auto it = g_abstract_inline_text_box_map_->find(fragment);
+ if (it != g_abstract_inline_text_box_map_->end()) {
+ it->value->Detach();
+ g_abstract_inline_text_box_map_->erase(fragment);
+ }
+}
+
+NGAbstractInlineTextBox::NGAbstractInlineTextBox(
+ LineLayoutText line_layout_item,
+ const NGPaintFragment& fragment)
+ : AbstractInlineTextBox(line_layout_item), fragment_(&fragment) {
+ DCHECK(fragment_->PhysicalFragment().IsText()) << fragment_;
+}
+
+NGAbstractInlineTextBox::~NGAbstractInlineTextBox() {
+ DCHECK(!fragment_);
+}
+
+void NGAbstractInlineTextBox::Detach() {
+ if (Node* const node = GetNode()) {
+ if (AXObjectCache* cache = node->GetDocument().ExistingAXObjectCache())
+ cache->InlineTextBoxesUpdated(GetLineLayoutItem());
+ }
+ AbstractInlineTextBox::Detach();
+ fragment_ = nullptr;
+}
+
+bool NGAbstractInlineTextBox::HasSoftWrapToNextLine() const {
+ return ToNGPhysicalLineBoxFragment(
+ fragment_->ContainerLineBox()->PhysicalFragment())
+ .HasSoftWrapToNextLine();
+}
+
+const NGPhysicalTextFragment& NGAbstractInlineTextBox::PhysicalTextFragment()
+ const {
+ return ToNGPhysicalTextFragment(fragment_->PhysicalFragment());
+}
+
+bool NGAbstractInlineTextBox::NeedsLayout() const {
+ return fragment_->GetLayoutObject()->NeedsLayout();
+}
+
+bool NGAbstractInlineTextBox::NeedsTrailingSpace() const {
+ if (!HasSoftWrapToNextLine())
+ return false;
+ const NGPaintFragment* next_fragment = NextTextFragmentForSameLayoutObject();
+ if (!next_fragment)
+ return false;
+ return ToNGPhysicalTextFragment(next_fragment->PhysicalFragment())
+ .StartOffset() != PhysicalTextFragment().EndOffset();
+}
+
+const NGPaintFragment*
+NGAbstractInlineTextBox::NextTextFragmentForSameLayoutObject() const {
+ const auto fragments =
+ NGPaintFragment::InlineFragmentsFor(fragment_->GetLayoutObject());
+ const auto it =
+ std::find_if(fragments.begin(), fragments.end(),
+ [&](const auto& sibling) { return fragment_ == sibling; });
+ DCHECK(it != fragments.end());
+ const auto next_it = std::next(it);
+ return next_it == fragments.end() ? nullptr : *next_it;
+}
+
+scoped_refptr<AbstractInlineTextBox>
+NGAbstractInlineTextBox::NextInlineTextBox() const {
+ if (!fragment_)
+ return nullptr;
+ DCHECK(!NeedsLayout());
+ const NGPaintFragment* next_fragment = NextTextFragmentForSameLayoutObject();
+ if (!next_fragment)
+ return nullptr;
+ return GetOrCreate(GetLineLayoutItem(), *next_fragment);
+}
+
+LayoutRect NGAbstractInlineTextBox::LocalBounds() const {
+ if (!fragment_ || !GetLineLayoutItem())
+ return LayoutRect();
+ return LayoutRect(fragment_->InlineOffsetToContainerBox().ToLayoutPoint(),
+ fragment_->Size().ToLayoutSize());
+}
+
+unsigned NGAbstractInlineTextBox::Len() const {
+ if (!fragment_)
+ return 0;
+ if (NeedsTrailingSpace())
+ return PhysicalTextFragment().Length() + 1;
+ return PhysicalTextFragment().Length();
+}
+
+AbstractInlineTextBox::Direction NGAbstractInlineTextBox::GetDirection() const {
+ if (!fragment_ || !GetLineLayoutItem())
+ return kLeftToRight;
+ const TextDirection text_direction =
+ PhysicalTextFragment().ResolvedDirection();
+ if (GetLineLayoutItem().Style()->IsHorizontalWritingMode())
+ return IsLtr(text_direction) ? kLeftToRight : kRightToLeft;
+ return IsLtr(text_direction) ? kTopToBottom : kBottomToTop;
+}
+
+void NGAbstractInlineTextBox::CharacterWidths(Vector<float>& widths) const {
+ if (!fragment_)
+ return;
+ if (!PhysicalTextFragment().TextShapeResult()) {
+ // When |fragment_| for BR, we don't have shape result.
+ // "aom-computed-boolean-properties.html" reaches here.
+ widths.resize(Len());
+ return;
+ }
+ const ShapeResult& shape_result = *PhysicalTextFragment().TextShapeResult();
+ ShapeResultBuffer buffer;
+ buffer.AppendResult(&shape_result);
+ const Vector<CharacterRange> ranges = buffer.IndividualCharacterRanges(
+ shape_result.Direction(), shape_result.Width());
+ widths.ReserveCapacity(ranges.size());
+ widths.resize(0);
+ for (const auto& range : ranges)
+ widths.push_back(range.Width());
+ // The shaper can fail to return glyph metrics for all characters (see
+ // crbug.com/613915 and crbug.com/615661) so add empty ranges to ensure all
+ // characters have an associated range.
+ widths.resize(Len());
+}
+
+String NGAbstractInlineTextBox::GetText() const {
+ if (!fragment_ || !GetLineLayoutItem())
+ return String();
+ // For compatibility with |InlineTextBox|, we should have a space character
+ // for soft line break.
+ // Following tests require this:
+ // - accessibility/inline-text-change-style.html
+ // - accessibility/inline-text-changes.html
+ // - accessibility/inline-text-word-boundaries.html
+ if (NeedsTrailingSpace())
+ return PhysicalTextFragment().Text().ToString() + " ";
+ return PhysicalTextFragment().Text().ToString();
+}
+
+bool NGAbstractInlineTextBox::IsFirst() const {
+ if (!fragment_)
+ return true;
+ DCHECK(!NeedsLayout());
+ const auto fragments =
+ NGPaintFragment::InlineFragmentsFor(fragment_->GetLayoutObject());
+ return fragment_ == &fragments.front();
+}
+
+bool NGAbstractInlineTextBox::IsLast() const {
+ if (!fragment_)
+ return true;
+ DCHECK(!NeedsLayout());
+ const auto fragments =
+ NGPaintFragment::InlineFragmentsFor(fragment_->GetLayoutObject());
+ return fragment_ == &fragments.back();
+}
+
+scoped_refptr<AbstractInlineTextBox> NGAbstractInlineTextBox::NextOnLine()
+ const {
+ if (!fragment_)
+ return nullptr;
+ DCHECK(!NeedsLayout());
+ DCHECK(fragment_->ContainerLineBox());
+ NGPaintFragmentTraversal cursor(*fragment_->ContainerLineBox(), *fragment_);
+ for (cursor.MoveToNext(); !cursor.IsAtEnd(); cursor.MoveToNext()) {
+ if (cursor->GetLayoutObject()->IsText())
+ return GetOrCreate(GetLineLayoutItem(), *cursor);
+ }
+ return nullptr;
+}
+
+scoped_refptr<AbstractInlineTextBox> NGAbstractInlineTextBox::PreviousOnLine()
+ const {
+ if (!fragment_)
+ return nullptr;
+ DCHECK(!NeedsLayout());
+ DCHECK(fragment_->ContainerLineBox());
+ NGPaintFragmentTraversal cursor(*fragment_->ContainerLineBox(), *fragment_);
+ for (cursor.MoveToPrevious(); !cursor.IsAtEnd(); cursor.MoveToPrevious()) {
+ if (cursor->GetLayoutObject()->IsText())
+ return GetOrCreate(GetLineLayoutItem(), *cursor);
+ }
+ return nullptr;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.h
new file mode 100644
index 00000000000..4932dec9d7d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.h
@@ -0,0 +1,68 @@
+// 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_LAYOUT_NG_INLINE_NG_ABSTRACT_INLINE_TEXT_BOX_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_ABSTRACT_INLINE_TEXT_BOX_H_
+
+#include "third_party/blink/renderer/core/layout/line/abstract_inline_text_box.h"
+
+namespace blink {
+
+class NGPaintFragment;
+class NGPhysicalTextFragment;
+
+// The implementation of |AbstractInlineTextBox| for LayoutNG.
+// See also |LegacyAbstractInlineTextBox| for legacy layout.
+class CORE_EXPORT NGAbstractInlineTextBox final : public AbstractInlineTextBox {
+ private:
+ // Returns existing or newly created |NGAbstractInlineTextBox|.
+ // * |line_layout_item| is |LayoutText| associated to |fragment|. For first
+ // letter part, it is remaining part of |LayoutTextFragment|.
+ // * |fragment| should be attached to |NGPhysicalTextFragment|.
+ static scoped_refptr<AbstractInlineTextBox> GetOrCreate(
+ LineLayoutText line_layout_item,
+ const NGPaintFragment& fragment);
+ static void WillDestroy(NGPaintFragment*);
+
+ friend class LayoutText;
+ friend class NGPaintFragment;
+
+ public:
+ ~NGAbstractInlineTextBox() final;
+
+ private:
+ NGAbstractInlineTextBox(LineLayoutText line_layout_item,
+ const NGPaintFragment& fragment);
+
+ bool HasSoftWrapToNextLine() const;
+ const NGPhysicalTextFragment& PhysicalTextFragment() const;
+ bool NeedsLayout() const;
+ bool NeedsTrailingSpace() const;
+ // Returns next fragment associated to |LayoutText|.
+ const NGPaintFragment* NextTextFragmentForSameLayoutObject() const;
+
+ // Implementations of AbstractInlineTextBox member functions.
+ void Detach() final;
+ scoped_refptr<AbstractInlineTextBox> NextInlineTextBox() const final;
+ LayoutRect LocalBounds() const final;
+ unsigned Len() const final;
+ Direction GetDirection() const final;
+ void CharacterWidths(Vector<float>&) const final;
+ String GetText() const final;
+ bool IsFirst() const final;
+ bool IsLast() const final;
+ scoped_refptr<AbstractInlineTextBox> NextOnLine() const final;
+ scoped_refptr<AbstractInlineTextBox> PreviousOnLine() const final;
+
+ const NGPaintFragment* fragment_;
+
+ using FragmentToNGAbstractInlineTextBoxHashMap =
+ HashMap<const NGPaintFragment*, scoped_refptr<AbstractInlineTextBox>>;
+ static FragmentToNGAbstractInlineTextBoxHashMap*
+ g_abstract_inline_text_box_map_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_INLINE_NG_ABSTRACT_INLINE_TEXT_BOX_H_
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_baseline.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_baseline.cc
index e43c7bcd284..a65589efaea 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_baseline.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_baseline.cc
@@ -23,7 +23,7 @@ bool NGBaseline::ShouldPropagateBaselines(const NGLayoutInputNode node) {
if (node.IsInline())
return true;
- return ShouldPropagateBaselines(ToLayoutBox(node.GetLayoutObject()));
+ return ShouldPropagateBaselines(node.GetLayoutBox());
}
bool NGBaseline::ShouldPropagateBaselines(LayoutBox* layout_box) {
@@ -39,12 +39,6 @@ bool NGBaseline::ShouldPropagateBaselines(LayoutBox* layout_box) {
if (!NGBlockNode(layout_box).CanUseNewLayout())
return true;
- // CSS defines certain cases to synthesize baselines from box. See comments in
- // UseLogicalBottomMarginEdgeForInlineBlockBaseline().
- const LayoutBlock* layout_block = ToLayoutBlock(layout_box);
- if (layout_block->UseLogicalBottomMarginEdgeForInlineBlockBaseline())
- return false;
-
return true;
}
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 cadd9c38992..a139ca08482 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
@@ -160,7 +160,8 @@ CaretPositionResolution TryResolveCaretPositionByBoxFragmentSide(
const NGPaintFragment& fragment,
unsigned offset,
TextAffinity affinity) {
- if (!fragment.GetNode()) {
+ // There is no caret position at a pseudo or generated box side.
+ if (!fragment.GetNode() || fragment.GetNode()->IsPseudoElement()) {
// TODO(xiaochengh): This leads to false negatives for, e.g., RUBY, where an
// anonymous wrapping inline block is created.
return CaretPositionResolution();
@@ -289,25 +290,40 @@ NGCaretPosition ComputeNGCaretPosition(const PositionWithAffinity& position) {
}
Position NGCaretPosition::ToPositionInDOMTree() const {
+ return ToPositionInDOMTreeWithAffinity().GetPosition();
+}
+
+PositionWithAffinity NGCaretPosition::ToPositionInDOMTreeWithAffinity() const {
if (!fragment)
- return Position();
+ return PositionWithAffinity();
switch (position_type) {
case NGCaretPositionType::kBeforeBox:
if (!fragment->GetNode())
- return Position();
- return Position::BeforeNode(*fragment->GetNode());
+ return PositionWithAffinity();
+ return PositionWithAffinity(Position::BeforeNode(*fragment->GetNode()),
+ TextAffinity::kDownstream);
case NGCaretPositionType::kAfterBox:
if (!fragment->GetNode())
- return Position();
- return Position::AfterNode(*fragment->GetNode());
+ return PositionWithAffinity();
+ return PositionWithAffinity(Position::AfterNode(*fragment->GetNode()),
+ TextAffinity::kUpstreamIfPossible);
case NGCaretPositionType::kAtTextOffset:
DCHECK(text_offset.has_value());
const NGOffsetMapping* mapping =
NGOffsetMapping::GetFor(fragment->GetLayoutObject());
- return mapping->GetFirstPosition(*text_offset);
+ const Position position = mapping->GetFirstPosition(*text_offset);
+ if (position.IsNull())
+ return PositionWithAffinity();
+ const NGPhysicalTextFragment& text_fragment =
+ ToNGPhysicalTextFragment(fragment->PhysicalFragment());
+ const TextAffinity affinity =
+ text_offset.value() == text_fragment.EndOffset()
+ ? TextAffinity::kUpstreamIfPossible
+ : TextAffinity::kDownstream;
+ return PositionWithAffinity(position, affinity);
}
NOTREACHED();
- return Position();
+ return PositionWithAffinity();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.h
index e6a963099c6..cb3beefdfe1 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.h
@@ -32,6 +32,7 @@ struct NGCaretPosition {
bool IsNull() const { return !fragment; }
Position ToPositionInDOMTree() const;
+ PositionWithAffinity ToPositionInDOMTreeWithAffinity() const;
const NGPaintFragment* fragment = nullptr; // owned by root LayoutNGMixin
NGCaretPositionType position_type;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position_test.cc
index da232c2bf83..6446ddb34de 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_caret_position_test.cc
@@ -276,4 +276,23 @@ TEST_F(NGCaretPositionTest, CaretPositionAtSoftLineWrapBetweenDeepTextNodes) {
fragment_d, kAtTextOffset, base::Optional<unsigned>(wrap_offset));
}
+TEST_F(NGCaretPositionTest, InlineBlockBeforeContent) {
+ SetInlineFormattingContext(
+ "t",
+ "<style>span::before{display:inline-block; content:'foo'}</style>"
+ "<span id=span>bar</span>",
+ 100); // Line width doesn't matter here.
+ const Node* text = GetElementById("span")->firstChild();
+ const NGPhysicalFragment* text_fragment = FragmentOf(text);
+
+ // Test caret position of "|bar", which shouldn't be affected by ::before
+ const Position position(text, 0);
+ const NGOffsetMapping& mapping = *NGOffsetMapping::GetFor(position);
+ const unsigned text_offset = mapping.GetTextContentOffset(position).value();
+
+ TEST_CARET(ComputeNGCaretPosition(text_offset, TextAffinity::kDownstream),
+ text_fragment, kAtTextOffset,
+ base::Optional<unsigned>(text_offset));
+}
+
} // namespace blink
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 fca16e8c347..97202bc6428 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
@@ -15,12 +15,41 @@
namespace blink {
+namespace {
+
+NGLineHeightMetrics ComputeEmphasisMarkOutsets(const ComputedStyle& style) {
+ if (style.GetTextEmphasisMark() == TextEmphasisMark::kNone)
+ return NGLineHeightMetrics();
+
+ const Font& font = style.GetFont();
+ LayoutUnit emphasis_mark_height =
+ LayoutUnit(font.EmphasisMarkHeight(style.TextEmphasisMarkString()));
+ DCHECK_GT(emphasis_mark_height, LayoutUnit());
+ return style.GetTextEmphasisLineLogicalSide() == LineLogicalSide::kOver
+ ? NGLineHeightMetrics(emphasis_mark_height, LayoutUnit())
+ : NGLineHeightMetrics(LayoutUnit(), emphasis_mark_height);
+}
+
+} // namespace
+
void NGInlineBoxState::ComputeTextMetrics(const ComputedStyle& style,
FontBaseline baseline_type) {
text_metrics = NGLineHeightMetrics(style, baseline_type);
text_top = -text_metrics.ascent;
text_height = text_metrics.LineHeight();
- text_metrics.AddLeading(style.ComputedLineHeightAsFixed());
+
+ NGLineHeightMetrics emphasis_marks_outsets =
+ ComputeEmphasisMarkOutsets(style);
+ if (emphasis_marks_outsets.IsEmpty()) {
+ text_metrics.AddLeading(style.ComputedLineHeightAsFixed());
+ } else {
+ NGLineHeightMetrics emphasis_marks_metrics = text_metrics;
+ emphasis_marks_metrics += emphasis_marks_outsets;
+ text_metrics.AddLeading(style.ComputedLineHeightAsFixed());
+ text_metrics.Unite(emphasis_marks_metrics);
+ // TODO: Is this correct to include into text_metrics? How do we use
+ // text_metrics after this point?
+ }
metrics.Unite(text_metrics);
@@ -37,7 +66,7 @@ void NGInlineBoxState::AccumulateUsedFonts(const ShapeResult* shape_result,
FontBaseline baseline_type) {
HashSet<const SimpleFontData*> fallback_fonts;
shape_result->FallbackFonts(&fallback_fonts);
- for (auto* const fallback_font : fallback_fonts) {
+ for (const SimpleFontData* const fallback_font : fallback_fonts) {
NGLineHeightMetrics fallback_metrics(fallback_font->GetFontMetrics(),
baseline_type);
fallback_metrics.AddLeading(
@@ -61,7 +90,7 @@ LayoutObject*
NGInlineLayoutStateStack::ContainingLayoutObjectForAbsolutePositionObjects()
const {
for (unsigned i = stack_.size(); i-- > 1;) {
- const auto& box = stack_[i];
+ const NGInlineBoxState& box = stack_[i];
DCHECK(box.style);
if (box.style->CanContainAbsolutePositionObjects()) {
DCHECK(box.item->GetLayoutObject());
@@ -82,7 +111,7 @@ NGInlineBoxState* NGInlineLayoutStateStack::OnBeginPlaceItems(
box->fragment_start = 0;
} else {
// For the following lines, clear states that are not shared across lines.
- for (auto& box : stack_) {
+ for (NGInlineBoxState& box : stack_) {
box.fragment_start = 0;
if (!line_height_quirk)
box.metrics = box.text_metrics;
@@ -136,8 +165,8 @@ NGInlineBoxState* NGInlineLayoutStateStack::OnOpenTag(
DCHECK_EQ(item_result.margins.inline_start, LayoutUnit());
DCHECK_EQ(item_result.inline_size, LayoutUnit());
}
- box->border_padding_block_start = item_result.borders_paddings_block_start;
- box->border_padding_block_end = item_result.borders_paddings_block_end;
+ box->border_padding_line_over = item_result.borders_paddings_line_over;
+ box->border_padding_line_under = item_result.borders_paddings_line_under;
return box;
}
@@ -182,10 +211,21 @@ void NGInlineLayoutStateStack::EndBoxState(
PositionPending position_pending =
ApplyBaselineShift(box, line_box, baseline_type);
+ // We are done here if there is no parent box.
+ if (box == stack_.begin())
+ return;
+ NGInlineBoxState& parent_box = *std::prev(box);
+
+ // Propagate necessary data back to the parent box.
+
// Unite the metrics to the parent box.
- if (position_pending == kPositionNotPending && box != stack_.begin()) {
- box[-1].metrics.Unite(box->metrics);
- }
+ if (position_pending == kPositionNotPending)
+ parent_box.metrics.Unite(box->metrics);
+
+ // Create box fragments for parent if the current box has properties (e.g.,
+ // margin) that make it tricky to compute the parent's rects.
+ if (box->ParentNeedsBoxFragment(parent_box))
+ parent_box.SetNeedsBoxFragment();
}
void NGInlineBoxState::SetNeedsBoxFragment() {
@@ -208,6 +248,23 @@ void NGInlineBoxState::SetLineRightForBoxFragment(
}
}
+bool NGInlineBoxState::ParentNeedsBoxFragment(
+ const NGInlineBoxState& parent) const {
+ if (!parent.item)
+ return false;
+ // Below are the known cases where parent rect may not equal the union of
+ // its child rects.
+ if (margin_inline_start || margin_inline_end)
+ return true;
+ // Inline box height is determined by font metrics, which can be different
+ // from the height of its child atomic inline.
+ if (item && item->Type() == NGInlineItem::kAtomicInline)
+ return true;
+ // Returns true when parent and child boxes have different font metrics, since
+ // they may have different heights and/or locations in block direction.
+ return text_metrics != parent.text_metrics;
+}
+
// Crete a placeholder for a box fragment.
// We keep a flat list of fragments because it is more suitable for operations
// such as ApplyBaselineShift. Later, CreateBoxFragments() creates box fragments
@@ -228,10 +285,10 @@ void NGInlineLayoutStateStack::AddBoxFragmentPlaceholder(
// Extend the block direction of the box by borders and paddings. Inline
// direction is already included into positions in NGLineBreaker.
NGLogicalOffset offset(LayoutUnit(),
- -metrics.ascent - box->border_padding_block_start);
+ -metrics.ascent - box->border_padding_line_over);
NGLogicalSize size(LayoutUnit(), metrics.LineHeight() +
- box->border_padding_block_start +
- box->border_padding_block_end);
+ box->border_padding_line_over +
+ box->border_padding_line_under);
unsigned fragment_end = line_box->size();
DCHECK(box->item);
@@ -289,7 +346,7 @@ void NGInlineLayoutStateStack::PrepareForReorder(
NGLineBoxFragmentBuilder::ChildList* line_box) {
// Set indexes of BoxData to the children of the line box.
unsigned box_data_index = 0;
- for (const auto& box_data : box_data_list_) {
+ for (const BoxData& box_data : box_data_list_) {
box_data_index++;
for (unsigned i = box_data.fragment_start; i < box_data.fragment_end; i++) {
NGLineBoxFragmentBuilder::Child& child = (*line_box)[i];
@@ -300,7 +357,7 @@ void NGInlineLayoutStateStack::PrepareForReorder(
// When boxes are nested, placeholders have indexes to which box it should be
// added. Copy them to BoxData.
- for (auto& box_data : box_data_list_) {
+ for (BoxData& box_data : box_data_list_) {
const NGLineBoxFragmentBuilder::Child& placeholder =
(*line_box)[box_data.fragment_end];
DCHECK(!placeholder.HasFragment());
@@ -312,11 +369,11 @@ void NGInlineLayoutStateStack::PrepareForReorder(
void NGInlineLayoutStateStack::UpdateAfterReorder(
NGLineBoxFragmentBuilder::ChildList* line_box) {
// Compute start/end of boxes from the children of the line box.
- for (auto& box_data : box_data_list_)
+ for (BoxData& box_data : box_data_list_)
box_data.fragment_start = box_data.fragment_end = 0;
for (unsigned i = 0; i < line_box->size(); i++) {
- const auto& child = (*line_box)[i];
- if (!child.HasFragment())
+ const NGLineBoxFragmentBuilder::Child& child = (*line_box)[i];
+ if (child.IsPlaceholder())
continue;
if (unsigned box_data_index = child.box_data_index) {
BoxData& box_data = box_data_list_[box_data_index - 1];
@@ -327,7 +384,7 @@ void NGInlineLayoutStateStack::UpdateAfterReorder(
}
// Extend start/end of boxes when they are nested.
- for (auto& box_data : box_data_list_) {
+ for (BoxData& box_data : box_data_list_) {
if (box_data.box_data_index) {
BoxData& parent_box_data = box_data_list_[box_data.box_data_index - 1];
if (!parent_box_data.fragment_end) {
@@ -344,7 +401,7 @@ void NGInlineLayoutStateStack::UpdateAfterReorder(
#if DCHECK_IS_ON()
// Check all BoxData have ranges.
- for (const auto& box_data : box_data_list_) {
+ for (const BoxData& box_data : box_data_list_) {
DCHECK_NE(box_data.fragment_end, 0u);
DCHECK_GT(box_data.fragment_end, box_data.fragment_start);
}
@@ -356,7 +413,7 @@ LayoutUnit NGInlineLayoutStateStack::ComputeInlinePositions(
// 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 (auto& child : *line_box) {
+ for (NGLineBoxFragmentBuilder::Child& child : *line_box) {
child.offset.inline_offset += position;
// Box margins/boders/paddings will be processed later.
// TODO(kojii): we could optimize this if the reordering did not occur.
@@ -368,27 +425,12 @@ LayoutUnit NGInlineLayoutStateStack::ComputeInlinePositions(
if (box_data_list_.IsEmpty())
return position;
- // Compute inline positions of inline boxes.
- for (auto& box_data : box_data_list_) {
+ // Adjust child offsets for margin/border/padding of inline boxes.
+ for (BoxData& box_data : box_data_list_) {
unsigned start = box_data.fragment_start;
unsigned end = box_data.fragment_end;
DCHECK_GT(end, start);
- NGLineBoxFragmentBuilder::Child& start_child = (*line_box)[start];
-
- // Clamping left offset is not defined, match to the existing behavior.
- LayoutUnit line_left_offset =
- start_child.offset.inline_offset.ClampNegativeToZero();
- LayoutUnit line_right_offset = end < line_box->size()
- ? (*line_box)[end].offset.inline_offset
- : position;
- box_data.offset.inline_offset =
- line_left_offset + box_data.margin_line_left;
- box_data.size.inline_size =
- line_right_offset - line_left_offset +
- box_data.margin_border_padding_line_left - box_data.margin_line_left +
- box_data.margin_border_padding_line_right - box_data.margin_line_right;
- // Adjust child offsets for margin/border/padding.
if (box_data.margin_border_padding_line_left) {
line_box->MoveInInlineDirection(box_data.margin_border_padding_line_left,
start, line_box->size());
@@ -402,6 +444,39 @@ LayoutUnit NGInlineLayoutStateStack::ComputeInlinePositions(
}
}
+ // Compute positions and sizes of inline boxes.
+ //
+ // Accumulate margin/border/padding of boxes for each child, to place nested
+ // parent boxes relative to the leaf (text or atomic inline) child.
+ struct LinePadding {
+ LayoutUnit line_left;
+ LayoutUnit line_right;
+ };
+ Vector<LinePadding, 32> accumulated_padding(line_box->size());
+ for (BoxData& box_data : box_data_list_) {
+ // Compute line-left and line-right edge of this box by accomodating
+ // border/padding of this box and margin/border/padding of descendants
+ // boxes, while accumulating its margin/border/padding.
+ unsigned start = box_data.fragment_start;
+ NGLineBoxFragmentBuilder::Child& start_child = (*line_box)[start];
+ LayoutUnit line_left_offset = start_child.offset.inline_offset;
+ LinePadding& start_padding = accumulated_padding[start];
+ start_padding.line_left += box_data.margin_border_padding_line_left;
+ line_left_offset -= start_padding.line_left - box_data.margin_line_left;
+
+ DCHECK_GT(box_data.fragment_end, start);
+ unsigned last = box_data.fragment_end - 1;
+ NGLineBoxFragmentBuilder::Child& last_child = (*line_box)[last];
+ LayoutUnit line_right_offset =
+ last_child.offset.inline_offset + last_child.inline_size;
+ LinePadding& last_padding = accumulated_padding[last];
+ last_padding.line_right += box_data.margin_border_padding_line_right;
+ line_right_offset += last_padding.line_right - box_data.margin_line_right;
+
+ box_data.offset.inline_offset = line_left_offset;
+ box_data.size.inline_size = line_right_offset - line_left_offset;
+ }
+
return position;
}
@@ -409,7 +484,7 @@ void NGInlineLayoutStateStack::CreateBoxFragments(
NGLineBoxFragmentBuilder::ChildList* line_box) {
DCHECK(!box_data_list_.IsEmpty());
- for (auto& box_data : box_data_list_) {
+ for (BoxData& box_data : box_data_list_) {
unsigned start = box_data.fragment_start;
unsigned end = box_data.fragment_end;
DCHECK_GT(end, start);
@@ -463,8 +538,8 @@ NGInlineLayoutStateStack::BoxData::CreateBoxFragment(
// NGInlineLayoutAlgorithm can handle them later.
DCHECK(!child.HasInFlowFragment());
}
-
- return box.ToBoxFragment();
+ box.MoveOutOfFlowDescendantCandidatesToDescendants();
+ return box.ToInlineBoxFragment();
}
NGInlineLayoutStateStack::PositionPending
@@ -477,7 +552,7 @@ NGInlineLayoutStateStack::ApplyBaselineShift(
// |pending_descendants|.
LayoutUnit baseline_shift;
if (!box->pending_descendants.IsEmpty()) {
- for (auto& child : box->pending_descendants) {
+ for (NGPendingPositions& child : box->pending_descendants) {
if (child.metrics.IsEmpty()) {
// This can happen with boxes with no content in quirks mode
child.metrics = NGLineHeightMetrics(LayoutUnit(), LayoutUnit());
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 626ad129d87..bfd5b61b6e5 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
@@ -57,14 +57,14 @@ struct NGInlineBoxState {
// is set.
bool has_start_edge = false;
bool has_end_edge = false;
- NGBoxStrut padding;
+ NGLineBoxStrut padding;
// |CreateBoxFragment()| needs margin, border+padding, and the sum of them.
LayoutUnit margin_inline_start;
LayoutUnit margin_inline_end;
LayoutUnit margin_border_padding_inline_start;
LayoutUnit margin_border_padding_inline_end;
- LayoutUnit border_padding_block_start;
- LayoutUnit border_padding_block_end;
+ LayoutUnit border_padding_line_over;
+ LayoutUnit border_padding_line_under;
Vector<NGPendingPositions> pending_descendants;
bool include_used_fonts = false;
@@ -91,6 +91,12 @@ struct NGInlineBoxState {
void SetLineRightForBoxFragment(const NGInlineItem&,
const NGInlineItemResult&);
+ // In certain circumstances, the parent's rects is not a simple union of its
+ // children fragments' rects, e.g., when children have margin. In such cases,
+ // we should create box fragments for the parent to avoid hacky fixup when
+ // computing its rects.
+ bool ParentNeedsBoxFragment(const NGInlineBoxState& parent) const;
+
// Returns if the text style can be added without open-tag.
// Text with different font or vertical-align needs to be wrapped with an
// inline box.
@@ -179,7 +185,7 @@ class CORE_EXPORT NGInlineLayoutStateStack {
bool has_line_left_edge = false;
bool has_line_right_edge = false;
- NGBoxStrut padding;
+ NGLineBoxStrut padding;
// |CreateBoxFragment()| needs margin, border+padding, and the sum of them.
LayoutUnit margin_line_left;
LayoutUnit margin_line_right;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.cc
index 353acbabc68..6ce8dc88622 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.cc
@@ -14,70 +14,153 @@ namespace {
using Result = NGPhysicalFragmentWithOffset;
-// Traverse the subtree of |container|, and collect the fragments satisfying
-// |filter| into the |results| vector. Guarantees to call |filter.AddOnEnter()|
-// for all fragments in preorder, and call |filter.RemoveOnExit()| on all
-// fragments in postorder. A fragment is collected if |AddOnEnter()| returns
-// true and |RemoveOnExit()| returns false on it.
-template <typename Filter, size_t inline_capacity>
-void CollectInlineFragments(const NGPhysicalContainerFragment& container,
- NGPhysicalOffset offset_to_container_box,
- Filter& filter,
- Vector<Result, inline_capacity>* results) {
- DCHECK(container.IsInline() || container.IsLineBox() ||
- (container.IsBlockFlow() &&
- ToNGPhysicalBoxFragment(container).ChildrenInline()));
- for (const auto& child : container.Children()) {
- NGPhysicalOffset child_offset = child->Offset() + offset_to_container_box;
-
- if (filter.AddOnEnter(child.get())) {
- results->push_back(
- NGPhysicalFragmentWithOffset{child.get(), child_offset});
- }
+class NGPhysicalFragmentCollectorBase {
+ STACK_ALLOCATED();
+
+ public:
+ virtual Vector<Result> CollectFrom(const NGPhysicalFragment&) = 0;
+
+ protected:
+ explicit NGPhysicalFragmentCollectorBase() = default;
+
+ virtual void Visit() = 0;
+
+ const NGPhysicalFragment& GetFragment() const { return *current_fragment_; }
+ void SetShouldStopTraversing() { should_stop_traversing_ = true; }
+ bool HasStoppedTraversing() const { return should_stop_traversing_; }
+
+ void Emit() {
+ results_.push_back(Result{current_fragment_, current_offset_to_root_});
+ }
+
+ // Visits and collets fragments in the subtree rooted at |fragment|.
+ // |fragment| itself is not visited.
+ Vector<Result> CollectExclusivelyFrom(const NGPhysicalFragment& fragment) {
+ current_fragment_ = &fragment;
+ root_fragment_ = &fragment;
+ VisitChildren();
+ return std::move(results_);
+ }
+
+ // Visits and collets fragments in the subtree rooted at |fragment|.
+ // |fragment| itself is visited.
+ Vector<Result> CollectInclusivelyFrom(const NGPhysicalFragment& fragment) {
+ current_fragment_ = &fragment;
+ root_fragment_ = &fragment;
+ Visit();
+ return std::move(results_);
+ }
+
+ void VisitChildren() {
+ if (should_stop_traversing_)
+ return;
+
+ const NGPhysicalFragment& fragment = *current_fragment_;
+ if (!fragment.IsContainer())
+ return;
// Traverse descendants unless the fragment is laid out separately from the
// inline layout algorithm.
- if (child->IsContainer() && !child->IsBlockLayoutRoot()) {
- CollectInlineFragments(ToNGPhysicalContainerFragment(*child),
- child_offset, filter, results);
- }
+ if (&fragment != root_fragment_ && fragment.IsBlockLayoutRoot())
+ return;
+
+ DCHECK(fragment.IsContainer());
+ DCHECK(fragment.IsInline() || fragment.IsLineBox() ||
+ (fragment.IsBlockFlow() &&
+ ToNGPhysicalBoxFragment(fragment).ChildrenInline()));
- if (filter.RemoveOnExit(child.get())) {
- DCHECK(results->size());
- DCHECK_EQ(results->back().fragment, child.get());
- results->pop_back();
+ for (const auto& child :
+ ToNGPhysicalContainerFragment(fragment).Children()) {
+ base::AutoReset<NGPhysicalOffset> offset_resetter(
+ &current_offset_to_root_, current_offset_to_root_ + child->Offset());
+ base::AutoReset<const NGPhysicalFragment*> fragment_resetter(
+ &current_fragment_, child.get());
+ Visit();
+
+ if (should_stop_traversing_)
+ return;
}
}
-}
-// The filter for CollectInlineFragments() collecting all fragments traversed.
-class AddAllFilter {
+ private:
+ const NGPhysicalFragment* root_fragment_ = nullptr;
+ const NGPhysicalFragment* current_fragment_ = nullptr;
+ NGPhysicalOffset current_offset_to_root_;
+ Vector<Result> results_;
+ bool should_stop_traversing_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(NGPhysicalFragmentCollectorBase);
+};
+
+// The visitor emitting all visited fragments.
+class DescendantCollector final : public NGPhysicalFragmentCollectorBase {
+ STACK_ALLOCATED();
+
public:
- bool AddOnEnter(const NGPhysicalFragment*) const { return true; }
- bool RemoveOnExit(const NGPhysicalFragment*) const { return false; }
+ DescendantCollector() = default;
+
+ Vector<Result> CollectFrom(const NGPhysicalFragment& fragment) final {
+ return CollectExclusivelyFrom(fragment);
+ }
+
+ private:
+ void Visit() final {
+ Emit();
+ VisitChildren();
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(DescendantCollector);
};
-// The filter for CollectInlineFragments() collecting fragments generated from
-// the given LayoutInline with supporting culled inline.
+// The visitor emitting all visited fragments.
+class InclusiveDescendantCollector final
+ : public NGPhysicalFragmentCollectorBase {
+ STACK_ALLOCATED();
+
+ public:
+ InclusiveDescendantCollector() = default;
+
+ Vector<Result> CollectFrom(const NGPhysicalFragment& fragment) final {
+ return CollectInclusivelyFrom(fragment);
+ }
+
+ private:
+ void Visit() final {
+ Emit();
+ VisitChildren();
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(InclusiveDescendantCollector);
+};
+
+// The visitor emitting fragments generated from the given LayoutInline,
+// supporting culled inline.
// Note: Since we apply culled inline per line, we have a fragment for
// LayoutInline in second line but not in first line in
// "t0803-c5502-imrgn-r-01-b-ag.html".
-class LayoutInlineFilter {
+class LayoutInlineCollector final : public NGPhysicalFragmentCollectorBase {
+ STACK_ALLOCATED();
+
public:
- explicit LayoutInlineFilter(const LayoutInline& container) {
- CollectInclusiveDescendnats(container);
+ explicit LayoutInlineCollector(const LayoutInline& container) {
+ CollectInclusiveDescendants(container);
}
- bool AddOnEnter(const NGPhysicalFragment* fragment) {
- if (fragment->IsLineBox())
- return false;
- return inclusive_descendants_.Contains(fragment->GetLayoutObject());
+ Vector<Result> CollectFrom(const NGPhysicalFragment& fragment) final {
+ return CollectExclusivelyFrom(fragment);
}
- bool RemoveOnExit(const NGPhysicalFragment*) const { return false; }
-
private:
- void CollectInclusiveDescendnats(const LayoutInline& container) {
+ void Visit() final {
+ if (!GetFragment().IsLineBox() &&
+ inclusive_descendants_.Contains(GetFragment().GetLayoutObject())) {
+ Emit();
+ return;
+ }
+ VisitChildren();
+ }
+
+ void CollectInclusiveDescendants(const LayoutInline& container) {
inclusive_descendants_.insert(&container);
for (const LayoutObject* node = container.FirstChild(); node;
node = node->NextSibling()) {
@@ -89,127 +172,136 @@ class LayoutInlineFilter {
}
if (!node->IsLayoutInline())
continue;
- CollectInclusiveDescendnats(ToLayoutInline(*node));
+ CollectInclusiveDescendants(ToLayoutInline(*node));
}
}
HashSet<const LayoutObject*> inclusive_descendants_;
+
+ DISALLOW_COPY_AND_ASSIGN(LayoutInlineCollector);
};
-// The filter for CollectInlineFragments() collecting fragments generated from
-// the given LayoutObject.
-class LayoutObjectFilter {
+// The visitor emitting all fragments generated from the given LayoutObject.
+class LayoutObjectCollector final : public NGPhysicalFragmentCollectorBase {
+ STACK_ALLOCATED();
+
public:
- explicit LayoutObjectFilter(const LayoutObject* layout_object)
- : layout_object_(layout_object) {
- DCHECK(layout_object);
- }
+ explicit LayoutObjectCollector(const LayoutObject* layout_object)
+ : target_(layout_object) {}
- bool AddOnEnter(const NGPhysicalFragment* fragment) const {
- return fragment->GetLayoutObject() == layout_object_;
+ Vector<Result> CollectFrom(const NGPhysicalFragment& fragment) final {
+ return CollectExclusivelyFrom(fragment);
}
- bool RemoveOnExit(const NGPhysicalFragment*) const { return false; }
private:
- const LayoutObject* layout_object_;
+ void Visit() final {
+ if (GetFragment().GetLayoutObject() == target_)
+ Emit();
+ VisitChildren();
+ }
+
+ const LayoutObject* target_;
+
+ DISALLOW_COPY_AND_ASSIGN(LayoutObjectCollector);
};
-// The filter for CollectInlineFragments() collecting inclusive ancestors of the
-// given fragment with the algorithm that, |fragment| is an ancestor of |target|
-// if and only if both of the following are true:
-// - |fragment| precedes |target| in preorder traversal
-// - |fragment| succeeds |target| in postorder traversal
-class InclusiveAncestorFilter {
+// The visitor emitting ancestors of the given fragment in bottom-up order.
+class AncestorCollector : public NGPhysicalFragmentCollectorBase {
+ STACK_ALLOCATED();
+
public:
- explicit InclusiveAncestorFilter(const NGPhysicalFragment& target)
- : target_(&target) {}
+ explicit AncestorCollector(const NGPhysicalFragment& target)
+ : target_(target) {}
- bool AddOnEnter(const NGPhysicalFragment* fragment) {
- if (fragment == target_)
- has_entered_target_ = true;
- ancestors_precede_in_preorder_.push_back(!has_entered_target_);
- return true;
+ Vector<Result> CollectFrom(const NGPhysicalFragment& fragment) final {
+ // TODO(xiaochengh): Change this into CollectInclusivlyFrom() to include
+ // subtree root to align with NodeTraversal::AncestorsOf().
+ return CollectExclusivelyFrom(fragment);
}
- bool RemoveOnExit(const NGPhysicalFragment* fragment) {
- if (fragment != target_) {
- const bool precedes_in_preorder = ancestors_precede_in_preorder_.back();
- ancestors_precede_in_preorder_.pop_back();
- return !precedes_in_preorder || !has_exited_target_;
+ private:
+ void Visit() final {
+ if (&GetFragment() == &target_) {
+ SetShouldStopTraversing();
+ return;
}
- has_exited_target_ = true;
- ancestors_precede_in_preorder_.pop_back();
- return false;
+
+ VisitChildren();
+ if (HasStoppedTraversing())
+ Emit();
+ }
+
+ const NGPhysicalFragment& target_;
+};
+
+// The visitor emitting inclusive ancestors of the given fragment in bottom-up
+// order.
+class InclusiveAncestorCollector : public NGPhysicalFragmentCollectorBase {
+ STACK_ALLOCATED();
+
+ public:
+ explicit InclusiveAncestorCollector(const NGPhysicalFragment& target)
+ : target_(target) {}
+
+ Vector<Result> CollectFrom(const NGPhysicalFragment& fragment) final {
+ // TODO(xiaochengh): Change this into CollectInclusivlyFrom() to include
+ // subtree root to align with NodeTraversal::InclusiveAncestorsOf().
+ return CollectExclusivelyFrom(fragment);
}
private:
- const NGPhysicalFragment* target_;
+ void Visit() final {
+ if (&GetFragment() == &target_) {
+ SetShouldStopTraversing();
+ Emit();
+ return;
+ }
- bool has_entered_target_ = false;
- bool has_exited_target_ = false;
+ VisitChildren();
+ if (HasStoppedTraversing())
+ Emit();
+ }
- // For each currently entered but not-yet-exited fragment, stores a boolean of
- // whether it precedes |target_| in preorder.
- Vector<bool> ancestors_precede_in_preorder_;
+ const NGPhysicalFragment& target_;
};
} // namespace
// static
-Vector<Result, 1> NGInlineFragmentTraversal::SelfFragmentsOf(
+Vector<Result> NGInlineFragmentTraversal::SelfFragmentsOf(
const NGPhysicalContainerFragment& container,
const LayoutObject* layout_object) {
if (layout_object->IsLayoutInline()) {
- LayoutInlineFilter filter(*ToLayoutInline(layout_object));
- Vector<Result, 1> results;
- CollectInlineFragments(container, {}, filter, &results);
- return results;
- }
- LayoutObjectFilter filter(layout_object);
- Vector<Result, 1> results;
- CollectInlineFragments(container, {}, filter, &results);
- return results;
+ return LayoutInlineCollector(ToLayoutInline(*layout_object))
+ .CollectFrom(container);
+ }
+ return LayoutObjectCollector(layout_object).CollectFrom(container);
}
// static
Vector<Result> NGInlineFragmentTraversal::DescendantsOf(
const NGPhysicalContainerFragment& container) {
- AddAllFilter add_all;
- Vector<Result> results;
- CollectInlineFragments(container, {}, add_all, &results);
- return results;
+ return DescendantCollector().CollectFrom(container);
}
// static
Vector<Result> NGInlineFragmentTraversal::InclusiveDescendantsOf(
const NGPhysicalFragment& root) {
- Vector<Result> results =
- root.IsContainer() ? DescendantsOf(ToNGPhysicalContainerFragment(root))
- : Vector<Result>();
- results.push_front(Result{&root, {}});
- return results;
+ return InclusiveDescendantCollector().CollectFrom(root);
}
// static
Vector<Result> NGInlineFragmentTraversal::InclusiveAncestorsOf(
const NGPhysicalContainerFragment& container,
const NGPhysicalFragment& target) {
- InclusiveAncestorFilter inclusive_ancestors_of(target);
- Vector<Result> results;
- CollectInlineFragments(container, {}, inclusive_ancestors_of, &results);
- std::reverse(results.begin(), results.end());
- return results;
+ return InclusiveAncestorCollector(target).CollectFrom(container);
}
// static
Vector<Result> NGInlineFragmentTraversal::AncestorsOf(
const NGPhysicalContainerFragment& container,
const NGPhysicalFragment& target) {
- Vector<Result> results = InclusiveAncestorsOf(container, target);
- DCHECK(results.size());
- DCHECK_EQ(results.front().fragment, &target);
- results.erase(results.begin());
- return results;
+ return AncestorCollector(target).CollectFrom(container);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.h
index 27fb2e44c87..ef8bfd61034 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.h
@@ -44,7 +44,7 @@ class CORE_EXPORT NGInlineFragmentTraversal {
// Returns list of inline fragments produced from the specified LayoutObject.
// The search is restricted in the subtree of |container|.
- static Vector<NGPhysicalFragmentWithOffset, 1> SelfFragmentsOf(
+ static Vector<NGPhysicalFragmentWithOffset> SelfFragmentsOf(
const NGPhysicalContainerFragment& container,
const LayoutObject* target);
};
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal_test.cc
index 40bf8c8431a..822aca55e9f 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal_test.cc
@@ -106,10 +106,7 @@ TEST_F(NGInlineFragmentTraversalTest, SelfFragmentsOf) {
// <b> generates two box fragments since its content is in two lines.
EXPECT_NEXT_BOX(iter, "filter");
- EXPECT_NEXT_TEXT(iter, "bar");
- EXPECT_NEXT_TEXT(iter, "\n");
EXPECT_NEXT_BOX(iter, "filter");
- EXPECT_NEXT_TEXT(iter, "baz");
EXPECT_EQ(iter, descendants.end());
}
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 8e5a6288ddf..4ae097be73a 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
@@ -37,6 +37,19 @@ bool IsInlineBoxEmpty(const ComputedStyle& style,
return true;
}
+// TODO(xiaochengh): Deduplicate with a similar function in ng_paint_fragment.cc
+// ::before, ::after and ::first-letter can be hit test targets.
+bool CanBeHitTestTargetPseudoNodeStyle(const ComputedStyle& style) {
+ switch (style.StyleType()) {
+ case kPseudoIdBefore:
+ case kPseudoIdAfter:
+ case kPseudoIdFirstLetter:
+ return true;
+ default:
+ return false;
+ }
+}
+
} // namespace
NGInlineItem::NGInlineItem(NGInlineItemType type,
@@ -47,17 +60,20 @@ NGInlineItem::NGInlineItem(NGInlineItemType type,
bool end_may_collapse)
: start_offset_(start),
end_offset_(end),
- script_(USCRIPT_INVALID_CODE),
style_(style),
layout_object_(layout_object),
type_(type),
+ script_(0),
+ font_fallback_priority_(0),
+ render_orientation_(0),
bidi_level_(UBIDI_LTR),
shape_options_(kPreContext | kPostContext),
is_empty_item_(false),
should_create_box_fragment_(false),
style_variant_(static_cast<unsigned>(NGStyleVariant::kStandard)),
end_collapse_type_(kNotCollapsible),
- end_may_collapse_(end_may_collapse) {
+ end_may_collapse_(end_may_collapse),
+ is_symbol_marker_(false) {
DCHECK_GE(end, start);
ComputeBoxProperties();
}
@@ -68,18 +84,21 @@ NGInlineItem::NGInlineItem(const NGInlineItem& other,
scoped_refptr<const ShapeResult> shape_result)
: start_offset_(start),
end_offset_(end),
- script_(other.script_),
shape_result_(shape_result),
style_(other.style_),
layout_object_(other.layout_object_),
type_(other.type_),
+ script_(other.script_),
+ font_fallback_priority_(other.font_fallback_priority_),
+ render_orientation_(other.render_orientation_),
bidi_level_(other.bidi_level_),
shape_options_(other.shape_options_),
is_empty_item_(other.is_empty_item_),
should_create_box_fragment_(other.should_create_box_fragment_),
style_variant_(other.style_variant_),
end_collapse_type_(other.end_collapse_type_),
- end_may_collapse_(other.end_may_collapse_) {
+ end_may_collapse_(other.end_may_collapse_),
+ is_symbol_marker_(other.is_symbol_marker_) {
DCHECK_GE(end, start);
}
@@ -95,7 +114,7 @@ void NGInlineItem::ComputeBoxProperties() {
if (type_ == NGInlineItem::kOpenTag) {
DCHECK(style_ && layout_object_ && layout_object_->IsLayoutInline());
- if (layout_object_->HasBoxDecorationBackground() || style_->HasPadding() ||
+ if (style_->HasBoxDecorationBackground() || style_->HasPadding() ||
style_->HasMargin()) {
is_empty_item_ = IsInlineBoxEmpty(*style_, *layout_object_);
should_create_box_fragment_ = true;
@@ -104,7 +123,10 @@ void NGInlineItem::ComputeBoxProperties() {
should_create_box_fragment_ =
ToLayoutBoxModelObject(layout_object_)->HasSelfPaintingLayer() ||
style_->HasOutline() || style_->CanContainAbsolutePositionObjects() ||
- style_->CanContainFixedPositionObjects(false);
+ style_->CanContainFixedPositionObjects(false) ||
+ ToLayoutBoxModelObject(layout_object_)
+ ->ShouldApplyPaintContainment() ||
+ CanBeHitTestTargetPseudoNodeStyle(*style_);
}
return;
}
@@ -121,6 +143,96 @@ const char* NGInlineItem::NGInlineItemTypeToString(int val) const {
return kNGInlineItemTypeStrings[val];
}
+UScriptCode NGInlineItem::Script() const {
+ return script_ != kInvalidScript ? static_cast<UScriptCode>(script_)
+ : USCRIPT_INVALID_CODE;
+}
+
+FontFallbackPriority NGInlineItem::GetFontFallbackPriority() const {
+ return static_cast<enum FontFallbackPriority>(font_fallback_priority_);
+}
+
+OrientationIterator::RenderOrientation NGInlineItem::RenderOrientation() const {
+ return static_cast<OrientationIterator::RenderOrientation>(
+ render_orientation_);
+}
+
+RunSegmenter::RunSegmenterRange NGInlineItem::CreateRunSegmenterRange() const {
+ return {start_offset_, end_offset_, Script(), RenderOrientation(),
+ GetFontFallbackPriority()};
+}
+
+bool NGInlineItem::EqualsRunSegment(const NGInlineItem& other) const {
+ return script_ == other.script_ &&
+ font_fallback_priority_ == other.font_fallback_priority_ &&
+ render_orientation_ == other.render_orientation_;
+}
+
+void NGInlineItem::SetRunSegment(const RunSegmenter::RunSegmenterRange& range) {
+ DCHECK_EQ(Type(), NGInlineItem::kText);
+
+ // Orientation should be set in a separate pass. See
+ // NGInlineNode::SegmentScriptRuns().
+ DCHECK_EQ(range.render_orientation, OrientationIterator::kOrientationKeep);
+
+ script_ = static_cast<unsigned>(range.script);
+ font_fallback_priority_ = static_cast<unsigned>(range.font_fallback_priority);
+
+ // Ensure our bit fields are large enough by reading them back.
+ DCHECK_EQ(range.script, Script());
+ DCHECK_EQ(range.font_fallback_priority, GetFontFallbackPriority());
+}
+
+void NGInlineItem::SetFontOrientation(
+ OrientationIterator::RenderOrientation orientation) {
+ DCHECK_EQ(Type(), NGInlineItem::kText);
+
+ // Ensure the value can fit in the bit field.
+ DCHECK_LT(static_cast<unsigned>(orientation), 1u << 1);
+
+ render_orientation_ = orientation != 0;
+}
+
+unsigned NGInlineItem::PopulateItemsFromRun(
+ Vector<NGInlineItem>& items,
+ unsigned index,
+ const RunSegmenter::RunSegmenterRange& range) {
+ DCHECK_GE(range.end, items[index].start_offset_);
+
+ for (;; index++) {
+ NGInlineItem& item = items[index];
+ DCHECK_LE(item.start_offset_, range.end);
+
+ if (item.Type() == NGInlineItem::kText)
+ item.SetRunSegment(range);
+
+ if (range.end == item.end_offset_)
+ break;
+ if (range.end < item.end_offset_) {
+ Split(items, index, range.end);
+ break;
+ }
+ }
+ return index + 1;
+}
+
+unsigned NGInlineItem::PopulateItemsFromFontOrientation(
+ Vector<NGInlineItem>& items,
+ unsigned index,
+ unsigned end_offset,
+ OrientationIterator::RenderOrientation orientation) {
+ // FontOrientaiton is set per item, end_offset should be within this item.
+ NGInlineItem& item = items[index];
+ DCHECK_GE(end_offset, item.start_offset_);
+ DCHECK_LE(end_offset, item.end_offset_);
+
+ item.SetFontOrientation(orientation);
+
+ if (end_offset < item.end_offset_)
+ Split(items, index, end_offset);
+ return index + 1;
+}
+
void NGInlineItem::SetBidiLevel(UBiDiLevel level) {
// Invalidate ShapeResult because it depends on the resolved direction.
if (DirectionFromLevel(level) != DirectionFromLevel(bidi_level_))
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 1b40a3a53d7..2e2a046614a 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/ng/inline/ng_offset_mapping.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"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h"
#include "third_party/blink/renderer/platform/text/text_direction.h"
@@ -77,7 +78,9 @@ class CORE_EXPORT NGInlineItem {
NGInlineItemType Type() const { return static_cast<NGInlineItemType>(type_); }
const char* NGInlineItemTypeToString(int val) const;
- const ShapeResult* TextShapeResult() const { return shape_result_.get(); }
+ scoped_refptr<const ShapeResult> TextShapeResult() const {
+ return shape_result_;
+ }
NGLayoutInlineShapeOptions ShapeOptions() const {
return static_cast<NGLayoutInlineShapeOptions>(shape_options_);
}
@@ -100,7 +103,6 @@ class CORE_EXPORT NGInlineItem {
// direction.
UBiDiLevel BidiLevelForReorder() const;
- UScriptCode GetScript() const { return script_; }
const ComputedStyle* Style() const { return style_.get(); }
LayoutObject* GetLayoutObject() const { return layout_object_; }
@@ -129,6 +131,26 @@ class CORE_EXPORT NGInlineItem {
bool EndMayCollapse() const { return end_may_collapse_; }
static void Split(Vector<NGInlineItem>&, unsigned index, unsigned offset);
+
+ // Get RunSegmenter properties.
+ UScriptCode Script() const;
+ FontFallbackPriority GetFontFallbackPriority() const;
+ OrientationIterator::RenderOrientation RenderOrientation() const;
+ RunSegmenter::RunSegmenterRange CreateRunSegmenterRange() const;
+ // Whether the other item has the same RunSegmenter properties or not.
+ bool EqualsRunSegment(const NGInlineItem&) const;
+ // Set RunSegmenter properties.
+ static unsigned PopulateItemsFromRun(Vector<NGInlineItem>&,
+ unsigned index,
+ const RunSegmenter::RunSegmenterRange&);
+ void SetRunSegment(const RunSegmenter::RunSegmenterRange&);
+ static unsigned PopulateItemsFromFontOrientation(
+ Vector<NGInlineItem>&,
+ unsigned index,
+ unsigned end_offset,
+ OrientationIterator::RenderOrientation);
+ void SetFontOrientation(OrientationIterator::RenderOrientation);
+
void SetBidiLevel(UBiDiLevel);
static unsigned SetBidiLevel(Vector<NGInlineItem>&,
unsigned index,
@@ -138,6 +160,9 @@ 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:
@@ -145,19 +170,27 @@ class CORE_EXPORT NGInlineItem {
unsigned start_offset_;
unsigned end_offset_;
- UScriptCode script_;
scoped_refptr<const ShapeResult> shape_result_;
scoped_refptr<const ComputedStyle> style_;
LayoutObject* layout_object_;
+ // UScriptCode is -1 (USCRIPT_INVALID_CODE) to 177 as of ICU 60.
+ // This can be packed to 8 bits, by handling -1 separately.
+ static constexpr unsigned kScriptBits = 8;
+ static constexpr unsigned kInvalidScript = (1 << kScriptBits) - 1;
+
unsigned type_ : 4;
- unsigned bidi_level_ : 8; // UBiDiLevel is defined as uint8_t.
+ unsigned script_ : kScriptBits;
+ unsigned font_fallback_priority_ : 2; // FontFallbackPriority.
+ unsigned render_orientation_ : 1; // RenderOrientation (excl. kInvalid.)
+ unsigned bidi_level_ : 8; // UBiDiLevel is defined as uint8_t.
unsigned shape_options_ : 2;
unsigned is_empty_item_ : 1;
unsigned should_create_box_fragment_ : 1;
unsigned style_variant_ : 2;
unsigned end_collapse_type_ : 2; // NGCollapseType
unsigned end_may_collapse_ : 1;
+ unsigned is_symbol_marker_ : 1;
friend class NGInlineNode;
};
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 43cdd7b803a..50ee0dee064 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
@@ -15,8 +15,13 @@ NGInlineItemResult::NGInlineItemResult()
NGInlineItemResult::NGInlineItemResult(const NGInlineItem* item,
unsigned index,
unsigned start,
- unsigned end)
- : item(item), item_index(index), start_offset(start), end_offset(end) {}
+ unsigned end,
+ bool should_create_line_box)
+ : item(item),
+ item_index(index),
+ start_offset(start),
+ end_offset(end),
+ should_create_line_box(should_create_line_box) {}
void NGLineInfo::SetLineStyle(const NGInlineNode& node,
const NGInlineItemsData& items_data,
@@ -26,7 +31,7 @@ void NGLineInfo::SetLineStyle(const NGInlineNode& node,
bool is_after_forced_break) {
use_first_line_style_ = use_first_line_style;
items_data_ = &items_data;
- line_style_ = node.GetLayoutObject()->Style(use_first_line_style_);
+ line_style_ = node.GetLayoutBox()->Style(use_first_line_style_);
if (line_style_->ShouldUseTextIndent(is_first_line, is_after_forced_break)) {
// 'text-indent' applies to block container, and percentage is of its
@@ -47,11 +52,13 @@ void NGLineInfo::SetLineStyle(const NGInlineNode& node,
}
#if DCHECK_IS_ON()
-void NGInlineItemResult::CheckConsistency() const {
+void NGInlineItemResult::CheckConsistency(bool during_line_break) const {
DCHECK(item);
if (item->Type() == NGInlineItem::kText) {
- DCHECK(shape_result);
DCHECK_LT(start_offset, end_offset);
+ if (during_line_break && !shape_result)
+ return;
+ DCHECK(shape_result);
DCHECK_EQ(end_offset - start_offset, shape_result->NumCharacters());
DCHECK_EQ(start_offset, shape_result->StartIndexForResult());
DCHECK_EQ(end_offset, shape_result->EndIndexForResult());
@@ -59,6 +66,20 @@ void NGInlineItemResult::CheckConsistency() const {
}
#endif
+LayoutUnit NGLineInfo::ComputeWidth() const {
+ LayoutUnit inline_size = TextIndent();
+ for (const NGInlineItemResult& item_result : Results())
+ inline_size += item_result.inline_size;
+
+ if (UNLIKELY(line_end_fragment_)) {
+ inline_size += line_end_fragment_->Size()
+ .ConvertToLogical(LineStyle().GetWritingMode())
+ .inline_size;
+ }
+
+ return inline_size;
+}
+
void NGLineInfo::SetLineBfcOffset(NGBfcOffset line_bfc_offset,
LayoutUnit available_width,
LayoutUnit width) {
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 514ae11066d..70ecc25ca16 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
@@ -51,12 +51,12 @@ struct CORE_EXPORT NGInlineItemResult {
scoped_refptr<NGLayoutResult> layout_result;
// Margins and padding for atomic inline items and open/close tags.
- NGBoxStrut margins;
- NGBoxStrut padding;
+ NGLineBoxStrut margins;
+ NGLineBoxStrut padding;
// Borders/padding for open tags.
- LayoutUnit borders_paddings_block_start;
- LayoutUnit borders_paddings_block_end;
+ LayoutUnit borders_paddings_line_over;
+ LayoutUnit borders_paddings_line_under;
// Has start/end edge for open/close tags.
bool has_edge = false;
@@ -78,6 +78,22 @@ struct CORE_EXPORT NGInlineItemResult {
// characters.
bool has_only_trailing_spaces = false;
+ // We don't create "certain zero-height line boxes".
+ // https://drafts.csswg.org/css2/visuren.html#phantom-line-box
+ // Such line boxes do not prevent two margins being "adjoining", and thus
+ // collapsing.
+ // https://drafts.csswg.org/css2/box.html#collapsing-margins
+ //
+ // This field should be initialized to the previous value in the
+ // NGInlineItemResults list. If line breaker rewinds NGInlineItemResults
+ // list, we can still look at the last value in the list to determine if we
+ // need a line box. E.g.
+ // [float should_create_line_box: false], [text should_create_line_box: true]
+ //
+ // If "text" doesn't fit, and we rewind so that we only have "float", we can
+ // correctly determine that we don't need a line box.
+ bool should_create_line_box = false;
+
// End effects for text items.
// The effects are included in |shape_result|, but not in text content.
NGTextEndEffect text_end_effect = NGTextEndEffect::kNone;
@@ -86,10 +102,11 @@ struct CORE_EXPORT NGInlineItemResult {
NGInlineItemResult(const NGInlineItem*,
unsigned index,
unsigned start,
- unsigned end);
+ unsigned end,
+ bool should_create_line_box);
#if DCHECK_IS_ON()
- void CheckConsistency() const;
+ void CheckConsistency(bool during_line_break = false) const;
#endif
};
@@ -105,9 +122,6 @@ class CORE_EXPORT NGLineInfo {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
public:
- NGLineInfo() = default;
- explicit NGLineInfo(size_t capacity) : results_(capacity) {}
-
const NGInlineItemsData& ItemsData() const {
DCHECK(items_data_);
return *items_data_;
@@ -137,8 +151,14 @@ class CORE_EXPORT NGLineInfo {
bool IsLastLine() const { return is_last_line_; }
void SetIsLastLine(bool is_last_line) { is_last_line_ = is_last_line; }
+ // If the line is marked as empty, it means that there's no content that
+ // requires it to be present at all, e.g. when there are only close tags with
+ // no margin/border/padding.
+ bool IsEmptyLine() const { return is_empty_line_; }
+ void SetIsEmptyLine() { is_empty_line_ = true; }
+
// NGInlineItemResults for this line.
- NGInlineItemResults& Results() { return results_; }
+ NGInlineItemResults* MutableResults() { return &results_; }
const NGInlineItemResults& Results() const { return results_; }
LayoutUnit TextIndent() const { return text_indent_; }
@@ -146,6 +166,7 @@ class CORE_EXPORT NGLineInfo {
NGBfcOffset LineBfcOffset() const { return line_bfc_offset_; }
LayoutUnit AvailableWidth() const { return available_width_; }
LayoutUnit Width() const { return width_; }
+ LayoutUnit ComputeWidth() const;
void SetLineBfcOffset(NGBfcOffset line_bfc_offset,
LayoutUnit available_width,
LayoutUnit width);
@@ -183,6 +204,7 @@ class CORE_EXPORT NGLineInfo {
bool use_first_line_style_ = false;
bool is_last_line_ = false;
+ bool is_empty_line_ = false;
};
} // namespace blink
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 7fad403e72e..ae1cb609e0a 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
@@ -95,19 +95,21 @@ bool ShouldRemoveNewlineSlow(const StringBuilder& before,
if (before.Is8Bit() || after.Is8Bit())
return false;
- // Remove if East Asian Widths of both before/after the newline are Wide.
+ // Remove if East Asian Widths of both before/after the newline are Wide, and
+ // neither side is Hangul.
+ // TODO(layout-dev): Don't remove if any side is Emoji.
if (U16_IS_TRAIL(last) && space_index >= 2) {
UChar last_last = before[space_index - 2];
if (U16_IS_LEAD(last_last))
last = U16_GET_SUPPLEMENTARY(last_last, last);
}
- if (IsEastAsianWidthWide(last, before_style)) {
+ if (!Character::IsHangul(last) && IsEastAsianWidthWide(last, before_style)) {
if (U16_IS_LEAD(next) && after.length() > 1) {
UChar next_next = after[1];
if (U16_IS_TRAIL(next_next))
next = U16_GET_SUPPLEMENTARY(next, next_next);
}
- if (IsEastAsianWidthWide(next, after_style))
+ if (!Character::IsHangul(next) && IsEastAsianWidthWide(next, after_style))
return true;
}
@@ -799,6 +801,13 @@ void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::Exit(
}
}
+template <typename OffsetMappingBuilder>
+void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::SetIsSymbolMarker(
+ bool b) {
+ DCHECK(!items_->IsEmpty());
+ items_->back().SetIsSymbolMarker(b);
+}
+
template class CORE_TEMPLATE_EXPORT
NGInlineItemsBuilderTemplate<EmptyOffsetMappingBuilder>;
template class CORE_TEMPLATE_EXPORT
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 53e34b6cef3..e944f9ac38f 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
@@ -36,7 +36,7 @@ class LayoutText;
// offsets in |text_|.
// See https://goo.gl/CJbxky for more details about offset mapping.
template <typename OffsetMappingBuilder>
-class CORE_TEMPLATE_CLASS_EXPORT NGInlineItemsBuilderTemplate {
+class NGInlineItemsBuilderTemplate {
STACK_ALLOCATED();
public:
@@ -107,6 +107,8 @@ class CORE_TEMPLATE_CLASS_EXPORT NGInlineItemsBuilderTemplate {
OffsetMappingBuilder& GetOffsetMappingBuilder() { return mapping_builder_; }
+ void SetIsSymbolMarker(bool b);
+
private:
Vector<NGInlineItem>* items_;
StringBuilder text_;
@@ -155,10 +157,11 @@ class CORE_TEMPLATE_CLASS_EXPORT NGInlineItemsBuilderTemplate {
};
template <>
-String NGInlineItemsBuilderTemplate<NGOffsetMappingBuilder>::ToString();
+CORE_EXPORT String
+NGInlineItemsBuilderTemplate<NGOffsetMappingBuilder>::ToString();
template <>
-bool NGInlineItemsBuilderTemplate<NGOffsetMappingBuilder>::Append(
+CORE_EXPORT bool NGInlineItemsBuilderTemplate<NGOffsetMappingBuilder>::Append(
const String&,
LayoutObject*,
const Vector<NGInlineItem*>&);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder_test.cc
index ae5a273962c..1d75a511be4 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder_test.cc
@@ -68,10 +68,13 @@ class NGInlineItemsBuilderTest : public PageTestBase {
const String& TestAppend(Vector<Input> inputs) {
items_.clear();
+ Vector<LayoutText*> anonymous_objects;
NGInlineItemsBuilderForOffsetMapping builder(&items_);
for (Input& input : inputs) {
- if (!input.layout_text)
+ if (!input.layout_text) {
input.layout_text = LayoutText::CreateEmptyAnonymous(GetDocument());
+ anonymous_objects.push_back(input.layout_text);
+ }
builder.Append(input.text, GetStyle(input.whitespace).get(),
input.layout_text);
}
@@ -79,6 +82,8 @@ class NGInlineItemsBuilderTest : public PageTestBase {
collapsed_ = GetCollapsed(builder.GetOffsetMappingBuilder());
ValidateItems();
CheckReuseItemsProducesSameResult(inputs);
+ for (LayoutObject* anonymous_object : anonymous_objects)
+ anonymous_object->Destroy();
return text_;
}
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 0d04530a405..303800dd4db 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
@@ -50,20 +50,31 @@ struct NGLineAlign {
NGLineAlign::NGLineAlign(const NGLineInfo& line_info) {
space = line_info.AvailableWidth() - line_info.Width();
- // Eliminate trailing spaces from the alignment space.
+ // Compute the end text offset of this line for the alignment purpose.
+ // Trailing spaces are not part of the alignment space even when they are
+ // preserved.
const NGInlineItemResults& item_results = line_info.Results();
for (auto it = item_results.rbegin(); it != item_results.rend(); ++it) {
const NGInlineItemResult& item_result = *it;
- if (!item_result.has_only_trailing_spaces) {
- end_offset = item_result.end_offset;
- space += trailing_spaces_width;
- return;
+
+ // If this item is opaque to whitespace collapsing, whitespace before this
+ // item maybe collapsed. Keep looking for previous items.
+ if (item_result.item && item_result.item->EndCollapseType() ==
+ NGInlineItem::kOpaqueToCollapsing) {
+ continue;
+ }
+
+ if (item_result.has_only_trailing_spaces) {
+ trailing_spaces_width += item_result.inline_size;
+ continue;
}
- trailing_spaces_width += item_result.inline_size;
+
+ end_offset = item_result.end_offset;
+ space += trailing_spaces_width;
+ return;
}
// An empty line, or only trailing spaces.
- DCHECK_EQ(space, line_info.AvailableWidth() - line_info.TextIndent());
end_offset = line_info.StartOffset();
space += trailing_spaces_width;
}
@@ -153,7 +164,8 @@ void NGInlineLayoutAlgorithm::PrepareBoxStates(
void NGInlineLayoutAlgorithm::CreateLine(NGLineInfo* line_info,
NGExclusionSpace* exclusion_space) {
- NGInlineItemResults* line_items = &line_info->Results();
+ // Needs MutableResults to move ShapeResult out of the NGLineInfo.
+ NGInlineItemResults* line_items = line_info->MutableResults();
line_box_.clear();
// Apply justification before placing items, because it affects size/position
@@ -177,7 +189,13 @@ void NGInlineLayoutAlgorithm::CreateLine(NGLineInfo* line_info,
NGInlineBoxState* box =
box_states_->OnBeginPlaceItems(&line_style, baseline_type_, quirks_mode_);
- for (auto& item_result : *line_items) {
+ // In order to match other browsers when list-style-type: none, pretend
+ // there's an invisible marker here.
+ if (line_style.Display() == EDisplay::kListItem &&
+ line_style.ListStyleType() == EListStyleType::kNone)
+ box->ComputeTextMetrics(line_style, baseline_type_);
+
+ for (NGInlineItemResult& item_result : *line_items) {
DCHECK(item_result.item);
const NGInlineItem& item = *item_result.item;
if (item.Type() == NGInlineItem::kText) {
@@ -195,9 +213,15 @@ void NGInlineLayoutAlgorithm::CreateLine(NGLineInfo* line_info,
baseline_type_);
}
- text_builder.SetItem(NGPhysicalTextFragment::kNormalText,
- line_info->ItemsData(), &item_result,
- box->text_height);
+ if (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);
+ }
line_box_.AddChild(text_builder.ToTextFragment(), box->text_top,
item_result.inline_size, item.BidiLevel());
} else if (item.Type() == NGInlineItem::kControl) {
@@ -234,9 +258,10 @@ void NGInlineLayoutAlgorithm::CreateLine(NGLineInfo* line_info,
IsLtr(line_info->BaseDirection()) ? 0 : 1, box);
}
- if (line_box_.IsEmpty() && !container_builder_.UnpositionedListMarker()) {
- return; // The line was empty.
- }
+ // We can return early if we don't have any children (and don't need to
+ // create a line-box for a list marker, etc).
+ if (line_box_.IsEmpty() && line_info->IsEmptyLine())
+ return;
box_states_->OnEndPlaceItems(&line_box_, baseline_type_);
@@ -267,20 +292,17 @@ void NGInlineLayoutAlgorithm::CreateLine(NGLineInfo* line_info,
// Handle out-of-flow positioned objects. They need inline offsets for their
// static positions.
- if (!PlaceOutOfFlowObjects(*line_info, line_box_metrics) &&
- !container_builder_.UnpositionedListMarker()) {
- // If we have out-of-flow objects but nothing else, we don't have line box
- // metrics nor BFC offset. Exit early.
+ PlaceOutOfFlowObjects(*line_info, line_box_metrics);
+
+ // 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())
return;
- }
DCHECK(!line_box_metrics.IsEmpty());
NGBfcOffset line_bfc_offset(line_info->LineBfcOffset());
- // TODO(kojii): Implement flipped line (vertical-lr). In this case, line_top
- // and block_start do not match.
-
// Up until this point, children are placed so that the dominant baseline is
// at 0. Move them to the final baseline position, and set the logical top of
// the line box to the line top.
@@ -411,7 +433,7 @@ void NGInlineLayoutAlgorithm::PlaceLayoutResult(NGInlineItemResult* item_result,
if (box)
box->metrics.Unite(metrics);
- LayoutUnit line_top = item_result->margins.block_start - metrics.ascent;
+ LayoutUnit line_top = item_result->margins.line_over - metrics.ascent;
line_box_.AddChild(std::move(item_result->layout_result),
NGLogicalOffset{inline_offset, line_top},
item_result->inline_size, item.BidiLevel());
@@ -419,21 +441,29 @@ void NGInlineLayoutAlgorithm::PlaceLayoutResult(NGInlineItemResult* item_result,
// Place all out-of-flow objects in |line_box_| and clear them.
// @return whether |line_box_| has any in-flow fragments.
-bool NGInlineLayoutAlgorithm::PlaceOutOfFlowObjects(
+void NGInlineLayoutAlgorithm::PlaceOutOfFlowObjects(
const NGLineInfo& line_info,
const NGLineHeightMetrics& line_box_metrics) {
- bool has_fragments = false;
- for (auto& child : line_box_) {
+ for (NGLineBoxFragmentBuilder::Child& child : line_box_) {
if (LayoutObject* box = child.out_of_flow_positioned_box) {
// The static position is at the line-top. Ignore the block_offset.
NGLogicalOffset static_offset(child.offset.inline_offset, LayoutUnit());
// If a block-level box appears in the middle of a line, move the static
// position to where the next block will be placed.
- if (static_offset.inline_offset &&
- !box->StyleRef().IsOriginalDisplayInlineType()) {
- static_offset.inline_offset = LayoutUnit();
- if (!line_box_metrics.IsEmpty())
+ if (!box->StyleRef().IsOriginalDisplayInlineType()) {
+ LayoutUnit line_offset;
+ if (!line_info.IsEmptyLine()) {
+ line_offset = line_info.LineBfcOffset().line_offset -
+ ConstraintSpace().BfcOffset().line_offset;
+ }
+ line_offset += line_info.TextIndent();
+
+ // We need to subtract the line offset, in order to ignore
+ // floats and text-indent.
+ static_offset.inline_offset = -line_offset;
+
+ if (child.offset.inline_offset && !line_box_metrics.IsEmpty())
static_offset.block_offset = line_box_metrics.LineHeight();
}
@@ -443,11 +473,8 @@ bool NGInlineLayoutAlgorithm::PlaceOutOfFlowObjects(
child.out_of_flow_positioned_box = child.out_of_flow_containing_box =
nullptr;
- } else if (!has_fragments) {
- has_fragments = child.HasFragment();
}
}
- return has_fragments;
}
// Place a list marker.
@@ -490,7 +517,7 @@ bool NGInlineLayoutAlgorithm::ApplyJustify(NGLineInfo* line_info) {
if (!spacing.HasExpansion())
return false; // no expansion opportunities exist.
- for (NGInlineItemResult& item_result : line_info->Results()) {
+ for (NGInlineItemResult& item_result : *line_info->MutableResults()) {
if (item_result.has_only_trailing_spaces)
break;
if (item_result.shape_result) {
@@ -508,8 +535,16 @@ bool NGInlineLayoutAlgorithm::ApplyJustify(NGLineInfo* line_info) {
shape_result->StartIndexForResult());
item_result.inline_size = shape_result->SnappedWidth();
item_result.shape_result = std::move(shape_result);
- } else {
- // TODO(kojii): Implement atomic inline.
+ } else if (item_result.item->Type() == NGInlineItem::kAtomicInline) {
+ float offset = 0.f;
+ DCHECK_LE(line_info->StartOffset(), item_result.start_offset);
+ unsigned line_text_offset =
+ item_result.start_offset - line_info->StartOffset();
+ DCHECK_EQ(kObjectReplacementCharacter, line_text[line_text_offset]);
+ float space = spacing.ComputeSpacing(line_text_offset, offset);
+ item_result.inline_size += space;
+ // |offset| is non-zero only before CJK characters.
+ DCHECK_EQ(offset, 0.f);
}
}
return true;
@@ -564,12 +599,21 @@ scoped_refptr<NGLayoutResult> NGInlineLayoutAlgorithm::Layout() {
bool is_empty_inline = Node().IsEmptyInline();
if (is_empty_inline) {
+ // Margins should collapse across "certain zero-height line boxes".
+ // https://drafts.csswg.org/css2/box.html#collapsing-margins
+ container_builder_.SetEndMarginStrut(ConstraintSpace().MarginStrut());
+
// We're just going to collapse through this one, so whatever went in on one
// side will go out on the other side. The position of the adjoining floats
// will be affected by any subsequent block, until the BFC offset is
// resolved.
container_builder_.AddAdjoiningFloatTypes(
ConstraintSpace().AdjoiningFloatTypes());
+
+ // For the empty lines, most of the logic here are not necessary, but in
+ // some edge cases we still need to create box fragments, such as when it
+ // has a containing block for out of flow objects. For now, use the code
+ // path than to create a fast code path for the stability.
} else {
DCHECK(ConstraintSpace().MarginStrut().IsEmpty());
container_builder_.SetBfcOffset(ConstraintSpace().BfcOffset());
@@ -584,26 +628,6 @@ scoped_refptr<NGLayoutResult> NGInlineLayoutAlgorithm::Layout() {
unsigned handled_item_index =
PositionLeadingItems(initial_exclusion_space.get());
- // If we are an empty inline, we don't have to run the full algorithm, we can
- // return now as we should have positioned all of our floats.
- if (is_empty_inline) {
- DCHECK_EQ(handled_item_index, Node().ItemsData(false).items.size());
-
- container_builder_.SwapPositionedFloats(&positioned_floats_);
- container_builder_.SetEndMarginStrut(ConstraintSpace().MarginStrut());
- container_builder_.SetExclusionSpace(std::move(initial_exclusion_space));
-
- Vector<NGOutOfFlowPositionedDescendant> descendant_candidates;
- container_builder_.GetAndClearOutOfFlowDescendantCandidates(
- &descendant_candidates, nullptr);
- for (auto& descendant : descendant_candidates)
- container_builder_.AddOutOfFlowDescendant(descendant);
-
- return container_builder_.ToLineBoxFragment();
- }
-
- DCHECK(container_builder_.BfcOffset());
-
// We query all the layout opportunities on the initial exclusion space up
// front, as if the line breaker may add floats and change the opportunities.
const Vector<NGLayoutOpportunity> opportunities =
@@ -612,7 +636,8 @@ scoped_refptr<NGLayoutResult> NGInlineLayoutAlgorithm::Layout() {
ConstraintSpace().AvailableSize().inline_size);
Vector<NGPositionedFloat> positioned_floats;
- DCHECK(unpositioned_floats_.IsEmpty());
+ // We shouldn't have any unpositioned floats if we aren't empty.
+ DCHECK(unpositioned_floats_.IsEmpty() || is_empty_inline);
std::unique_ptr<NGExclusionSpace> exclusion_space;
NGInlineBreakToken* break_token = BreakToken();
@@ -653,15 +678,12 @@ scoped_refptr<NGLayoutResult> NGInlineLayoutAlgorithm::Layout() {
line_block_size, block_delta);
NGLineInfo line_info;
- NGLineBreaker line_breaker(
- Node(), NGLineBreakerMode::kContent, constraint_space_,
- &positioned_floats, &unpositioned_floats_, &container_builder_,
- exclusion_space.get(), handled_item_index, break_token);
-
- // TODO(ikilpatrick): Does this always succeed when we aren't an empty
- // inline?
- if (!line_breaker.NextLine(line_opportunity, &line_info))
- break;
+ NGLineBreaker line_breaker(Node(), NGLineBreakerMode::kContent,
+ constraint_space_, &positioned_floats,
+ &unpositioned_floats_, &container_builder_,
+ exclusion_space.get(), handled_item_index,
+ line_opportunity, break_token);
+ line_breaker.NextLine(&line_info);
// If this fragment will be larger than the inline-size of the opportunity,
// *and* the opportunity is smaller than the available inline-size, and the
@@ -692,29 +714,35 @@ scoped_refptr<NGLayoutResult> NGInlineLayoutAlgorithm::Layout() {
// We now can check the block-size of the fragment, and it fits within the
// opportunity.
- LayoutUnit block_size = container_builder_.ComputeBlockSize();
+ LayoutUnit line_height = container_builder_.LineHeight();
// Now that we have the block-size of the line, we can re-test the layout
// opportunity to see if we fit into the (potentially) non-rectangular
// shape area.
+ //
// If the AvailableInlineSize changes we need to run the line breaker again
// with the calculated line_block_size. This is *safe* as the line breaker
// won't produce a line which has a larger block-size, (as it can only
// decrease or stay the same size).
- if (UNLIKELY(opportunity.HasShapeExclusions())) {
+ //
+ // We skip attempting to fit empty lines into the shape area, as they
+ // should only contain floats and/or abs-pos which shouldn't be affected by
+ // this logic.
+ if (UNLIKELY(opportunity.HasShapeExclusions() &&
+ !line_info.IsEmptyLine())) {
NGLineLayoutOpportunity line_opportunity_with_height =
opportunity.ComputeLineLayoutOpportunity(ConstraintSpace(),
- block_size, block_delta);
+ line_height, block_delta);
if (line_opportunity_with_height.AvailableInlineSize() !=
line_opportunity.AvailableInlineSize()) {
- line_block_size = block_size;
+ line_block_size = line_height;
continue;
}
}
// Check if the line will fit in the current opportunity.
- if (block_size + block_delta > opportunity.rect.BlockSize()) {
+ if (line_height + block_delta > opportunity.rect.BlockSize()) {
block_delta = LayoutUnit();
line_block_size = LayoutUnit();
++opportunities_it;
@@ -725,74 +753,64 @@ scoped_refptr<NGLayoutResult> NGInlineLayoutAlgorithm::Layout() {
ConstraintSpace().BfcOffset().block_offset)
container_builder_.SetIsPushedByFloats();
- LayoutUnit line_height = container_builder_.LineHeight();
-
// Success!
positioned_floats_.AppendVector(positioned_floats);
container_builder_.SetBreakToken(
line_breaker.CreateBreakToken(line_info, std::move(box_states_)));
- // Place any remaining floats which couldn't fit on the line.
- PositionPendingFloats(line_height, exclusion_space.get());
-
- // A <br clear=both> will strech the line-box height, such that the
- // block-end edge will clear any floats.
- // TODO(ikilpatrick): Move this into ng_block_layout_algorithm.
- container_builder_.SetBlockSize(
- ComputeContentSize(line_info, *exclusion_space, line_height));
-
+ if (is_empty_inline) {
+ DCHECK_EQ(container_builder_.BlockSize(), 0);
+ } else {
+ // Place any remaining floats which couldn't fit on the line.
+ PositionPendingFloats(line_height, exclusion_space.get());
+
+ // A <br clear=both> will strech the line-box height, such that the
+ // block-end edge will clear any floats.
+ // TODO(ikilpatrick): Move this into ng_block_layout_algorithm.
+ container_builder_.SetBlockSize(
+ ComputeContentSize(line_info, *exclusion_space, line_height));
+ }
break;
}
// We shouldn't have any unpositioned floats if we aren't empty.
- DCHECK(unpositioned_floats_.IsEmpty());
+ DCHECK(unpositioned_floats_.IsEmpty() || is_empty_inline);
container_builder_.SwapPositionedFloats(&positioned_floats_);
container_builder_.SetExclusionSpace(
exclusion_space ? std::move(exclusion_space)
: std::move(initial_exclusion_space));
-
- Vector<NGOutOfFlowPositionedDescendant> descendant_candidates;
- container_builder_.GetAndClearOutOfFlowDescendantCandidates(
- &descendant_candidates, nullptr);
- for (auto& descendant : descendant_candidates)
- container_builder_.AddOutOfFlowDescendant(descendant);
+ container_builder_.MoveOutOfFlowDescendantCandidatesToDescendants();
return container_builder_.ToLineBoxFragment();
}
// This positions any "leading" floats within the given exclusion space.
// If we are also an empty inline, it will add any out-of-flow descendants.
-// TODO(ikilpatrick): Do we need to always add the OOFs here?
unsigned NGInlineLayoutAlgorithm::PositionLeadingItems(
NGExclusionSpace* exclusion_space) {
const Vector<NGInlineItem>& items = Node().ItemsData(false).items;
- bool is_empty_inline = Node().IsEmptyInline();
LayoutUnit bfc_line_offset = ConstraintSpace().BfcOffset().line_offset;
unsigned index = BreakToken() ? BreakToken()->ItemIndex() : 0;
for (; index < items.size(); ++index) {
- const auto& item = items[index];
+ const NGInlineItem& item = items[index];
if (item.Type() == NGInlineItem::kFloating) {
NGBlockNode node(ToLayoutBox(item.GetLayoutObject()));
NGBoxStrut margins =
ComputeMarginsForContainer(ConstraintSpace(), node.Style());
- auto unpositioned_float = NGUnpositionedFloat::Create(
- ConstraintSpace().AvailableSize(),
- ConstraintSpace().PercentageResolutionSize(), bfc_line_offset,
- bfc_line_offset, margins, node, /* break_token */ nullptr);
+ scoped_refptr<NGUnpositionedFloat> unpositioned_float =
+ NGUnpositionedFloat::Create(
+ ConstraintSpace().AvailableSize(),
+ ConstraintSpace().PercentageResolutionSize(), bfc_line_offset,
+ bfc_line_offset, margins, node, /* break_token */ nullptr);
AddUnpositionedFloat(&unpositioned_floats_, &container_builder_,
std::move(unpositioned_float));
- } else if (is_empty_inline &&
- item.Type() == NGInlineItem::kOutOfFlowPositioned) {
- NGBlockNode node(ToLayoutBox(item.GetLayoutObject()));
- container_builder_.AddInlineOutOfFlowChildCandidate(
- node, NGLogicalOffset(), Style().Direction(), nullptr);
}
// Abort if we've found something that makes this a non-empty inline.
if (!item.IsEmptyItem()) {
- DCHECK(!is_empty_inline);
+ DCHECK(!Node().IsEmptyInline());
break;
}
}
@@ -821,7 +839,7 @@ void NGInlineLayoutAlgorithm::PositionPendingFloats(
LayoutUnit origin_block_offset = bfc_offset.block_offset + content_size;
LayoutUnit from_block_offset = bfc_offset.block_offset;
- const auto positioned_floats =
+ const Vector<NGPositionedFloat> positioned_floats =
PositionFloats(origin_block_offset, from_block_offset,
unpositioned_floats_, ConstraintSpace(), exclusion_space);
@@ -843,8 +861,8 @@ void NGInlineLayoutAlgorithm::BidiReorder() {
Vector<UBiDiLevel, 32> levels;
logical_items.ReserveInitialCapacity(line_box_.size());
levels.ReserveInitialCapacity(line_box_.size());
- for (auto& item : line_box_) {
- if (!item.HasFragment() && !item.HasBidiLevel())
+ for (NGLineBoxFragmentBuilder::Child& item : line_box_) {
+ if (item.IsPlaceholder())
continue;
levels.push_back(item.bidi_level);
logical_items.AddChild(std::move(item));
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 017544f453a..4fcf7b1026a 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
@@ -72,7 +72,7 @@ class CORE_EXPORT NGInlineLayoutAlgorithm final
void PlaceLayoutResult(NGInlineItemResult*,
NGInlineBoxState*,
LayoutUnit inline_offset = LayoutUnit());
- bool PlaceOutOfFlowObjects(const NGLineInfo&, const NGLineHeightMetrics&);
+ void PlaceOutOfFlowObjects(const NGLineInfo&, const NGLineHeightMetrics&);
void PlaceListMarker(const NGInlineItem&,
NGInlineItemResult*,
const NGLineInfo&);
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 654b7eb887e..6476e38750a 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
@@ -266,10 +266,11 @@ TEST_F(NGInlineLayoutAlgorithmTest, TextFloatsAroundFloatsBefore) {
ToNGPhysicalBoxFragment(html_fragment->Children()[0].get());
auto* container_fragment =
ToNGPhysicalBoxFragment(body_fragment->Children()[0].get());
- auto* span_box_fragments_wrapper =
- ToNGPhysicalBoxFragment(container_fragment->Children()[3].get());
Vector<NGPhysicalLineBoxFragment*> line_boxes;
- for (const auto& child : span_box_fragments_wrapper->Children()) {
+ for (const auto& child : container_fragment->Children()) {
+ if (!child->IsLineBox())
+ continue;
+
line_boxes.push_back(ToNGPhysicalLineBoxFragment(child.get()));
}
@@ -433,8 +434,8 @@ TEST_F(NGInlineLayoutAlgorithmTest, PositionFloatsWithMargins) {
EXPECT_EQ(LayoutUnit(53), span->OffsetLeft());
}
-// Test glyph bounding box causes visual overflow.
-TEST_F(NGInlineLayoutAlgorithmTest, VisualRect) {
+// Test glyph bounding box causes ink overflow.
+TEST_F(NGInlineLayoutAlgorithmTest, InkOverflow) {
LoadAhem();
SetBodyInnerHTML(R"HTML(
<!DOCTYPE html>
@@ -452,9 +453,9 @@ TEST_F(NGInlineLayoutAlgorithmTest, VisualRect) {
EXPECT_EQ(LayoutUnit(10), box_fragment->Size().height);
- NGPhysicalOffsetRect visual_rect = box_fragment->ContentsVisualRect();
- EXPECT_EQ(LayoutUnit(-5), visual_rect.offset.top);
- EXPECT_EQ(LayoutUnit(20), visual_rect.size.height);
+ NGPhysicalOffsetRect ink_overflow = box_fragment->ContentsInkOverflow();
+ EXPECT_EQ(LayoutUnit(-5), ink_overflow.offset.top);
+ EXPECT_EQ(LayoutUnit(20), ink_overflow.size.height);
}
TEST_F(NGInlineLayoutAlgorithmTest,
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 bf394eba54f..9cecafec27e 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
@@ -8,6 +8,7 @@
#include <memory>
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
+#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_text.h"
#include "third_party/blink/renderer/core/layout/ng/inline/layout_ng_text.h"
@@ -19,13 +20,16 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.h"
#include "third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.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_list_marker.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.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_positioned_float.h"
#include "third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
@@ -65,6 +69,9 @@ void CollectInlinesInternal(
String* previous_text) {
builder->EnterBlock(block->Style());
LayoutObject* node = GetLayoutObjectForFirstChildNode(block);
+
+ const LayoutObject* symbol =
+ LayoutNGListItem::FindSymbolMarkerLayoutText(block);
while (node) {
if (node->IsText()) {
LayoutText* layout_text = ToLayoutText(node);
@@ -87,6 +94,10 @@ void CollectInlinesInternal(
else
builder->Append(layout_text->GetText(), node->Style(), layout_text);
}
+
+ if (symbol == layout_text)
+ builder->SetIsSymbolMarker(true);
+
ClearNeedsLayoutIfUpdatingLayout<OffsetMappingBuilder>(layout_text);
} else if (node->IsFloating()) {
@@ -195,19 +206,8 @@ bool NGInlineNode::InLineHeightQuirksMode() const {
}
bool NGInlineNode::CanContainFirstFormattedLine() const {
- // TODO(kojii): In LayoutNG, leading OOF creates an anonymous block box,
- // and that |LayoutBlockFlow::CanContainFirstFormattedLine()| does not work.
- // crbug.com/734554
- LayoutObject* layout_object = GetLayoutBlockFlow();
- if (!layout_object->IsAnonymousBlock())
- return true;
- for (;;) {
- layout_object = layout_object->PreviousSibling();
- if (!layout_object)
- return true;
- if (!layout_object->IsFloatingOrOutOfFlowPositioned())
- return false;
- }
+ DCHECK(GetLayoutBlockFlow());
+ return GetLayoutBlockFlow()->CanContainFirstFormattedLine();
}
NGInlineNodeData* NGInlineNode::MutableData() {
@@ -326,6 +326,71 @@ void NGInlineNode::CollectInlines(NGInlineNodeData* data,
}
void NGInlineNode::SegmentText(NGInlineNodeData* data) {
+ SegmentBidiRuns(data);
+ SegmentScriptRuns(data);
+ SegmentFontOrientation(data);
+}
+
+// Segment NGInlineItem by script, Emoji, and orientation using RunSegmenter.
+void NGInlineNode::SegmentScriptRuns(NGInlineNodeData* data) {
+ if (data->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::PopulateItemsFromRun(data->items, 0, range);
+ }
+ return;
+ }
+
+ // Segment by script and Emoji.
+ // Orientation is segmented separately, because it may vary by items.
+ Vector<NGInlineItem>& items = data->items;
+ String& text_content = data->text_content;
+ text_content.Ensure16Bit();
+ RunSegmenter segmenter(text_content.Characters16(), text_content.length(),
+ FontOrientation::kHorizontal);
+ RunSegmenter::RunSegmenterRange range = RunSegmenter::NullRange();
+ for (unsigned item_index = 0; segmenter.Consume(&range);) {
+ DCHECK_EQ(items[item_index].start_offset_, range.start);
+ item_index = NGInlineItem::PopulateItemsFromRun(items, item_index, range);
+ }
+}
+
+void NGInlineNode::SegmentFontOrientation(NGInlineNodeData* data) {
+ // Segment by orientation, only if vertical writing mode and items with
+ // 'text-orientation: mixed'.
+ if (GetLayoutBlockFlow()->IsHorizontalWritingMode())
+ return;
+
+ Vector<NGInlineItem>& items = data->items;
+ String& text_content = data->text_content;
+ text_content.Ensure16Bit();
+
+ for (unsigned item_index = 0; item_index < items.size();) {
+ NGInlineItem& item = items[item_index];
+ if (item.Type() != NGInlineItem::kText ||
+ item.Style()->GetFont().GetFontDescription().Orientation() !=
+ FontOrientation::kVerticalMixed) {
+ item_index++;
+ continue;
+ }
+ unsigned start_offset = item.StartOffset();
+ OrientationIterator iterator(text_content.Characters16() + start_offset,
+ item.Length(),
+ FontOrientation::kVerticalMixed);
+ unsigned end_offset;
+ OrientationIterator::RenderOrientation orientation;
+ while (iterator.Consume(&end_offset, &orientation)) {
+ item_index = NGInlineItem::PopulateItemsFromFontOrientation(
+ items, item_index, end_offset + start_offset, orientation);
+ }
+ }
+}
+
+// Segment bidi runs by resolving bidi embedding levels.
+// http://unicode.org/reports/tr9/#Resolving_Embedding_Levels
+void NGInlineNode::SegmentBidiRuns(NGInlineNodeData* data) {
if (!data->is_bidi_enabled_) {
data->SetBaseDirection(TextDirection::kLtr);
return;
@@ -370,8 +435,6 @@ void NGInlineNode::SegmentText(NGInlineNodeData* data) {
void NGInlineNode::ShapeText(NGInlineItemsData* data,
NGInlineItemsData* previous_data) {
- // TODO(eae): Add support for shaping latin-1 text?
- data->text_content.Ensure16Bit();
ShapeText(data->text_content, &data->items,
previous_data ? &previous_data->text_content : nullptr);
}
@@ -380,7 +443,7 @@ void NGInlineNode::ShapeText(const String& text_content,
Vector<NGInlineItem>* items,
const String* previous_text) {
// Provide full context of the entire node to the shaper.
- HarfBuzzShaper shaper(text_content.Characters16(), text_content.length());
+ HarfBuzzShaper shaper(text_content);
ShapeResultSpacing<String> spacing(text_content);
for (unsigned index = 0; index < items->size();) {
@@ -405,9 +468,12 @@ void NGInlineNode::ShapeText(const String& text_content,
if (item.Type() == NGInlineItem::kText) {
// Shape adjacent items together if the font and direction matches to
// allow ligatures and kerning to apply.
+ // Also run segment properties must match because NGInlineItem gives
+ // pre-segmented range to HarfBuzzShaper.
// TODO(kojii): Figure out the exact conditions under which this
// behavior is desirable.
- if (font != item.Style()->GetFont() || direction != item.Direction())
+ if (font != item.Style()->GetFont() || direction != item.Direction() ||
+ !item.EqualsRunSegment(start_item))
break;
end_offset = item.EndOffset();
} else if (item.Type() == NGInlineItem::kOpenTag ||
@@ -459,8 +525,11 @@ void NGInlineNode::ShapeText(const String& text_content,
}
// Shape each item with the full context of the entire node.
- scoped_refptr<ShapeResult> shape_result =
- shaper.Shape(&font, direction, start_item.StartOffset(), end_offset);
+ RunSegmenter::RunSegmenterRange range =
+ start_item.CreateRunSegmenterRange();
+ range.end = end_offset;
+ scoped_refptr<ShapeResult> shape_result = shaper.Shape(
+ &font, direction, start_item.StartOffset(), end_offset, &range);
if (UNLIKELY(spacing.SetSpacing(font.GetFontDescription())))
shape_result->ApplySpacing(spacing);
@@ -494,7 +563,7 @@ void NGInlineNode::ShapeText(const String& text_content,
void NGInlineNode::ShapeTextForFirstLineIfNeeded(NGInlineNodeData* data) {
// First check if the document has any :first-line rules.
DCHECK(!data->first_line_items_);
- LayoutObject* layout_object = GetLayoutObject();
+ LayoutObject* layout_object = GetLayoutBox();
if (!layout_object->GetDocument().GetStyleEngine().UsesFirstLineRules())
return;
@@ -533,6 +602,22 @@ void NGInlineNode::ShapeTextForFirstLineIfNeeded(NGInlineNodeData* data) {
}
}
+ // Check if we have a first-line anonymous inline box. It is the first
+ // open-tag if we have.
+ for (auto& item : first_line_items->items) {
+ if (item.Type() == NGInlineItem::kOpenTag) {
+ if (item.layout_object_->IsAnonymous() &&
+ item.layout_object_->IsLayoutInline() &&
+ item.layout_object_->Parent() == GetLayoutBox() &&
+ ToLayoutInline(item.layout_object_)->IsFirstLineAnonymous()) {
+ item.should_create_box_fragment_ = true;
+ }
+ break;
+ }
+ if (item.Type() != NGInlineItem::kBidiControl)
+ break;
+ }
+
// Re-shape if the font is different.
if (needs_reshape || FirstLineNeedsReshape(*first_line_style, *block_style))
ShapeText(first_line_items.get());
@@ -583,26 +668,28 @@ static LayoutUnit ComputeContentSize(NGInlineNode node,
Vector<scoped_refptr<NGUnpositionedFloat>> unpositioned_floats;
scoped_refptr<NGInlineBreakToken> break_token;
- NGLineInfo line_info;
NGExclusionSpace empty_exclusion_space;
NGLineLayoutOpportunity line_opportunity(available_inline_size);
LayoutUnit result;
LayoutUnit previous_floats_inline_size =
input.float_left_inline_size + input.float_right_inline_size;
+ DCHECK_GE(previous_floats_inline_size, 0);
while (!break_token || !break_token->IsFinished()) {
unpositioned_floats.clear();
- NGLineBreaker line_breaker(node, mode, *space, &positioned_floats,
- &unpositioned_floats,
- nullptr /* container_builder */,
- &empty_exclusion_space, 0u, break_token.get());
- if (!line_breaker.NextLine(line_opportunity, &line_info))
+ NGLineInfo line_info;
+ NGLineBreaker line_breaker(
+ node, mode, *space, &positioned_floats, &unpositioned_floats,
+ nullptr /* container_builder */, &empty_exclusion_space, 0u,
+ line_opportunity, break_token.get());
+ line_breaker.NextLine(&line_info);
+
+ if (line_info.Results().IsEmpty())
break;
break_token = line_breaker.CreateBreakToken(line_info, nullptr);
- LayoutUnit inline_size = line_info.TextIndent();
- for (const NGInlineItemResult item_result : line_info.Results())
- inline_size += item_result.inline_size;
+ LayoutUnit inline_size = line_info.Width();
+ DCHECK_EQ(inline_size, line_info.ComputeWidth().ClampNegativeToZero());
// There should be no positioned floats while determining the min/max sizes.
DCHECK_EQ(positioned_floats.size(), 0u);
@@ -643,7 +730,10 @@ static LayoutUnit ComputeContentSize(NGInlineNode node,
floats_inline_size = LayoutUnit();
}
- floats_inline_size += child_sizes.max_size + child_inline_margins;
+ // When negative margins move the float outside the content area,
+ // such float should not affect the content size.
+ floats_inline_size +=
+ (child_sizes.max_size + child_inline_margins).ClampNegativeToZero();
previous_float_type = float_style.Floating();
}
}
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 7685706584d..73d49d80621 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
@@ -80,6 +80,9 @@ class CORE_EXPORT NGInlineNode : public NGLayoutInputNode {
void CollectInlines(NGInlineNodeData*,
NGInlineNodeData* previous_data = nullptr);
void SegmentText(NGInlineNodeData*);
+ void SegmentScriptRuns(NGInlineNodeData*);
+ void SegmentFontOrientation(NGInlineNodeData*);
+ void SegmentBidiRuns(NGInlineNodeData*);
void ShapeText(NGInlineItemsData*,
NGInlineItemsData* previous_data = nullptr);
void ShapeText(const String& text,
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 f04e5e70b56..c06d5dcefb0 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
@@ -359,7 +359,7 @@ TEST_F(NGInlineNodeTest, SegmentBidiIsolate) {
NGInlineNodeForTest node = CreateInlineNode();
node = CreateBidiIsolateNode(node, style_.get(), layout_object_);
Vector<NGInlineItem>& items = node.Items();
- ASSERT_EQ(9u, items.size());
+ ASSERT_EQ(10u, items.size());
TEST_ITEM_OFFSET_DIR(items[0], 0u, 6u, TextDirection::kLtr);
TEST_ITEM_OFFSET_DIR(items[1], 6u, 7u, TextDirection::kLtr);
TEST_ITEM_OFFSET_DIR(items[2], 7u, 13u, TextDirection::kRtl);
@@ -368,7 +368,8 @@ TEST_F(NGInlineNodeTest, SegmentBidiIsolate) {
TEST_ITEM_OFFSET_DIR(items[5], 15u, 16u, TextDirection::kRtl);
TEST_ITEM_OFFSET_DIR(items[6], 16u, 21u, TextDirection::kRtl);
TEST_ITEM_OFFSET_DIR(items[7], 21u, 22u, TextDirection::kLtr);
- TEST_ITEM_OFFSET_DIR(items[8], 22u, 28u, TextDirection::kLtr);
+ TEST_ITEM_OFFSET_DIR(items[8], 22u, 23u, TextDirection::kLtr);
+ TEST_ITEM_OFFSET_DIR(items[9], 23u, 28u, TextDirection::kLtr);
}
#define TEST_TEXT_FRAGMENT(fragment, start_offset, end_offset) \
@@ -385,12 +386,13 @@ TEST_F(NGInlineNodeTest, CreateLineBidiIsolate) {
node.ShapeText();
Vector<scoped_refptr<const NGPhysicalTextFragment>> fragments;
CreateLine(node, &fragments);
- ASSERT_EQ(5u, fragments.size());
+ ASSERT_EQ(6u, fragments.size());
TEST_TEXT_FRAGMENT(fragments[0], 0u, 6u);
TEST_TEXT_FRAGMENT(fragments[1], 16u, 21u);
TEST_TEXT_FRAGMENT(fragments[2], 14u, 15u);
TEST_TEXT_FRAGMENT(fragments[3], 7u, 13u);
- TEST_TEXT_FRAGMENT(fragments[4], 22u, 28u);
+ TEST_TEXT_FRAGMENT(fragments[4], 22u, 23u);
+ TEST_TEXT_FRAGMENT(fragments[5], 23u, 28u);
}
TEST_F(NGInlineNodeTest, MinMaxSize) {
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 2b7a7e3d58e..5e01951043f 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
@@ -36,19 +36,6 @@ LayoutUnit NGLineBoxFragmentBuilder::LineHeight() const {
return metrics_.LineHeight().ClampNegativeToZero();
}
-LayoutUnit NGLineBoxFragmentBuilder::ComputeBlockSize() const {
- LayoutUnit block_size;
- WritingMode writing_mode(node_.Style().GetWritingMode());
-
- for (size_t i = 0; i < children_.size(); ++i) {
- block_size = std::max(
- block_size, offsets_[i].block_offset +
- NGFragment(writing_mode, *children_[i]).BlockSize());
- }
-
- return block_size;
-}
-
const NGPhysicalFragment* NGLineBoxFragmentBuilder::Child::PhysicalFragment()
const {
return layout_result ? layout_result->PhysicalFragment().get()
@@ -142,25 +129,21 @@ void NGLineBoxFragmentBuilder::AddChildren(ChildList& children) {
scoped_refptr<NGLayoutResult> NGLineBoxFragmentBuilder::ToLineBoxFragment() {
DCHECK_EQ(offsets_.size(), children_.size());
- WritingMode writing_mode(node_.Style().GetWritingMode());
- NGPhysicalSize physical_size = Size().ConvertToPhysical(writing_mode);
+ WritingMode line_writing_mode(ToLineWritingMode(GetWritingMode()));
+ NGPhysicalSize physical_size = Size().ConvertToPhysical(line_writing_mode);
- NGPhysicalOffsetRect contents_visual_rect({}, physical_size);
- NGPhysicalOffsetRect scrollable_overflow({}, physical_size);
+ NGPhysicalOffsetRect contents_ink_overflow({}, physical_size);
for (size_t i = 0; i < children_.size(); ++i) {
NGPhysicalFragment* child = children_[i].get();
child->SetOffset(offsets_[i].ConvertToPhysical(
- writing_mode, Direction(), physical_size, child->Size()));
- child->PropagateContentsVisualRect(&contents_visual_rect);
- NGPhysicalOffsetRect child_scroll_overflow = child->ScrollableOverflow();
- child_scroll_overflow.offset += child->Offset();
- scrollable_overflow.Unite(child_scroll_overflow);
+ line_writing_mode, Direction(), physical_size, child->Size()));
+ child->PropagateContentsInkOverflow(&contents_ink_overflow);
}
scoped_refptr<NGPhysicalLineBoxFragment> fragment =
base::AdoptRef(new NGPhysicalLineBoxFragment(
Style(), style_variant_, physical_size, children_,
- contents_visual_rect, scrollable_overflow, metrics_, base_direction_,
+ contents_ink_overflow, metrics_, base_direction_,
break_token_ ? std::move(break_token_)
: NGInlineBreakToken::Create(node_)));
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 9ea29183fb1..be0369eaaf2 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
@@ -22,6 +22,7 @@ struct NGPositionedFloat;
class CORE_EXPORT NGLineBoxFragmentBuilder final
: public NGContainerFragmentBuilder {
STACK_ALLOCATED();
+
public:
NGLineBoxFragmentBuilder(NGInlineNode,
scoped_refptr<const ComputedStyle>,
@@ -32,7 +33,6 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
void Reset();
LayoutUnit LineHeight() const;
- LayoutUnit ComputeBlockSize() const;
const NGLineHeightMetrics& Metrics() const { return metrics_; }
void SetMetrics(const NGLineHeightMetrics&);
@@ -107,6 +107,7 @@ class CORE_EXPORT NGLineBoxFragmentBuilder final
return HasInFlowFragment() || HasOutOfFlowFragment();
}
bool HasBidiLevel() const { return bidi_level != 0xff; }
+ bool IsPlaceholder() const { return !HasFragment() && !HasBidiLevel(); }
const NGPhysicalFragment* PhysicalFragment() const;
};
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 79294415634..31fa4092c6d 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h"
+#include "third_party/blink/renderer/core/layout/layout_list_marker.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_bidi_paragraph.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_node.h"
@@ -33,19 +34,12 @@ inline bool CanBreakAfterLast(const NGInlineItemResults& item_results) {
return !item_results.IsEmpty() && item_results.back().can_break_after;
}
-} // namespace
-
-NGLineBreaker::LineData::LineData(NGInlineNode node,
- const NGInlineBreakToken* break_token) {
- is_first_formatted_line = (!break_token || (!break_token->ItemIndex() &&
- !break_token->TextOffset())) &&
- node.CanContainFirstFormattedLine();
- use_first_line_style = is_first_formatted_line && node.GetLayoutObject()
- ->GetDocument()
- .GetStyleEngine()
- .UsesFirstLineRules();
+inline bool ShouldCreateLineBox(const NGInlineItemResults& item_results) {
+ return !item_results.IsEmpty() && item_results.back().should_create_line_box;
}
+} // namespace
+
NGLineBreaker::NGLineBreaker(
NGInlineNode node,
NGLineBreakerMode mode,
@@ -55,10 +49,20 @@ NGLineBreaker::NGLineBreaker(
NGContainerFragmentBuilder* container_builder,
NGExclusionSpace* exclusion_space,
unsigned handled_float_index,
+ const NGLineLayoutOpportunity& line_opportunity,
const NGInlineBreakToken* break_token)
- : line_(node, break_token),
+ : line_opportunity_(line_opportunity),
node_(node),
- items_data_(node.ItemsData(line_.use_first_line_style)),
+ is_first_formatted_line_((!break_token || (!break_token->ItemIndex() &&
+ !break_token->TextOffset())) &&
+ node.CanContainFirstFormattedLine()),
+ use_first_line_style_(is_first_formatted_line_ &&
+ node.GetLayoutBox()
+ ->GetDocument()
+ .GetStyleEngine()
+ .UsesFirstLineRules()),
+ in_line_height_quirks_mode_(node.InLineHeightQuirksMode()),
+ items_data_(node.ItemsData(use_first_line_style_)),
mode_(mode),
constraint_space_(space),
positioned_floats_(positioned_floats),
@@ -66,12 +70,10 @@ NGLineBreaker::NGLineBreaker(
container_builder_(container_builder),
exclusion_space_(exclusion_space),
break_iterator_(items_data_.text_content),
- shaper_(items_data_.text_content.Characters16(),
- items_data_.text_content.length()),
+ shaper_(items_data_.text_content),
spacing_(items_data_.text_content),
handled_floats_end_item_index_(handled_float_index),
- base_direction_(node_.BaseDirection()),
- in_line_height_quirks_mode_(node.InLineHeightQuirksMode()) {
+ base_direction_(node_.BaseDirection()) {
break_iterator_.SetBreakSpace(BreakSpaceType::kBeforeSpaceRun);
if (break_token) {
@@ -88,36 +90,32 @@ NGLineBreaker::NGLineBreaker(
// header.
NGLineBreaker::~NGLineBreaker() = default;
-inline NGInlineItemResult* NGLineBreaker::AddItem(
- const NGInlineItem& item,
- unsigned end_offset,
- NGInlineItemResults* item_results) {
+inline NGInlineItemResult* NGLineBreaker::AddItem(const NGInlineItem& item,
+ unsigned end_offset) {
DCHECK_LE(end_offset, item.EndOffset());
- item_results->push_back(
- NGInlineItemResult(&item, item_index_, offset_, end_offset));
- return &item_results->back();
+ item_results_->push_back(
+ NGInlineItemResult(&item, item_index_, offset_, end_offset,
+ ShouldCreateLineBox(*item_results_)));
+ return &item_results_->back();
}
-inline NGInlineItemResult* NGLineBreaker::AddItem(
- const NGInlineItem& item,
- NGInlineItemResults* item_results) {
- return AddItem(item, item.EndOffset(), item_results);
+inline NGInlineItemResult* NGLineBreaker::AddItem(const NGInlineItem& item) {
+ return AddItem(item, item.EndOffset());
}
void NGLineBreaker::SetLineEndFragment(
- scoped_refptr<NGPhysicalTextFragment> fragment,
- NGLineInfo* line_info) {
+ scoped_refptr<NGPhysicalTextFragment> fragment) {
bool is_horizontal =
IsHorizontalWritingMode(constraint_space_.GetWritingMode());
- if (line_info->LineEndFragment()) {
- const NGPhysicalSize& size = line_info->LineEndFragment()->Size();
- line_.position -= is_horizontal ? size.width : size.height;
+ if (line_info_->LineEndFragment()) {
+ const NGPhysicalSize& size = line_info_->LineEndFragment()->Size();
+ position_ -= is_horizontal ? size.width : size.height;
}
if (fragment) {
const NGPhysicalSize& size = fragment->Size();
- line_.position += is_horizontal ? size.width : size.height;
+ position_ += is_horizontal ? size.width : size.height;
}
- line_info->SetLineEndFragment(std::move(fragment));
+ line_info_->SetLineEndFragment(std::move(fragment));
}
inline void NGLineBreaker::ComputeCanBreakAfter(
@@ -126,27 +124,15 @@ inline void NGLineBreaker::ComputeCanBreakAfter(
auto_wrap_ && break_iterator_.IsBreakable(item_result->end_offset);
}
-// True if |item| is trailing; i.e., |item| and all items after it are opaque to
-// whitespace collapsing.
-bool NGLineBreaker::IsTrailing(const NGInlineItem& item,
- const NGLineInfo& line_info) const {
- const Vector<NGInlineItem>& items = line_info.ItemsData().items;
- for (const NGInlineItem* it = &item; it != items.end(); ++it) {
- if (it->EndCollapseType() != NGInlineItem::kOpaqueToCollapsing)
- return false;
- }
- return true;
-}
-
// Compute the base direction for bidi algorithm for this line.
-void NGLineBreaker::ComputeBaseDirection(const NGLineInfo& line_info) {
+void NGLineBreaker::ComputeBaseDirection() {
// If 'unicode-bidi' is not 'plaintext', use the base direction of the block.
if (!previous_line_had_forced_break_ ||
node_.Style().GetUnicodeBidi() != UnicodeBidi::kPlaintext)
return;
// If 'unicode-bidi: plaintext', compute the base direction for each paragraph
// (separated by forced break.)
- const String& text = line_info.ItemsData().text_content;
+ const String& text = Text();
if (text.Is8Bit())
return;
size_t end_offset = text.find(kNewlineCharacter, offset_);
@@ -157,67 +143,77 @@ void NGLineBreaker::ComputeBaseDirection(const NGLineInfo& line_info) {
}
// Initialize internal states for the next line.
-void NGLineBreaker::PrepareNextLine(
- const NGLineLayoutOpportunity& line_opportunity,
- NGLineInfo* line_info) {
- NGInlineItemResults* item_results = &line_info->Results();
- item_results->clear();
- line_info->SetStartOffset(offset_);
- line_info->SetLineStyle(
- node_, items_data_, constraint_space_, line_.is_first_formatted_line,
- line_.use_first_line_style, previous_line_had_forced_break_);
+void NGLineBreaker::PrepareNextLine() {
+ // NGLineInfo is not supposed to be re-used becase it's not much gain and to
+ // avoid rare code path.
+ DCHECK(item_results_->IsEmpty());
+
+ line_info_->SetStartOffset(offset_);
+ line_info_->SetLineStyle(node_, items_data_, constraint_space_,
+ is_first_formatted_line_, use_first_line_style_,
+ previous_line_had_forced_break_);
// Set the initial style of this line from the break token. Example:
// <p>...<span>....</span></p>
// When the line wraps in <span>, the 2nd line needs to start with the style
// of the <span>.
- override_break_anywhere_ = false;
- SetCurrentStyle(current_style_ ? *current_style_ : line_info->LineStyle());
- ComputeBaseDirection(*line_info);
- line_info->SetBaseDirection(base_direction_);
-
- line_.is_after_forced_break = false;
- line_.should_create_line_box = false;
+ SetCurrentStyle(current_style_ ? *current_style_ : line_info_->LineStyle());
+ ComputeBaseDirection();
+ line_info_->SetBaseDirection(base_direction_);
// Use 'text-indent' as the initial position. This lets tab positions to align
// regardless of 'text-indent'.
- line_.position = line_info->TextIndent();
-
- line_.line_opportunity = line_opportunity;
+ position_ = line_info_->TextIndent();
}
-bool NGLineBreaker::NextLine(const NGLineLayoutOpportunity& line_opportunity,
- NGLineInfo* line_info) {
- PrepareNextLine(line_opportunity, line_info);
- BreakLine(line_info);
+void NGLineBreaker::NextLine(NGLineInfo* line_info) {
+ line_info_ = line_info;
+ item_results_ = line_info->MutableResults();
+
+ PrepareNextLine();
+ BreakLine();
+ if (!trailing_spaces_collapsed_)
+ RemoveTrailingCollapsibleSpace();
- if (line_info->Results().IsEmpty())
- return false;
+#if DCHECK_IS_ON()
+ for (const auto& result : *item_results_)
+ result.CheckConsistency();
+#endif
+ // We should create a line-box when:
+ // - We have an item which needs a line box (text, etc).
+ // - A list-marker is present, and it would be the last line or last line
+ // before a forced new-line.
+ // - During min/max content sizing (to correctly determine the line width).
+ //
// TODO(kojii): There are cases where we need to PlaceItems() without creating
// line boxes. These cases need to be reviewed.
- if (line_.should_create_line_box)
- ComputeLineLocation(line_info);
-
- return true;
+ if (ShouldCreateLineBox(*item_results_) ||
+ (has_list_marker_ && line_info_->IsLastLine()) ||
+ mode_ != NGLineBreakerMode::kContent)
+ ComputeLineLocation();
+ else
+ line_info_->SetIsEmptyLine();
+
+ line_info_ = nullptr;
+ item_results_ = nullptr;
}
-void NGLineBreaker::BreakLine(NGLineInfo* line_info) {
- NGInlineItemResults* item_results = &line_info->Results();
- const Vector<NGInlineItem>& items = line_info->ItemsData().items;
- LineBreakState state = LineBreakState::kContinue;
- while (state != LineBreakState::kDone) {
+void NGLineBreaker::BreakLine() {
+ const Vector<NGInlineItem>& items = Items();
+ state_ = LineBreakState::kLeading;
+ while (state_ != LineBreakState::kDone) {
// Check overflow even if |item_index_| is at the end of the block, because
// the last item of the block may have caused overflow. In that case,
// |HandleOverflow| will rewind |item_index_|.
- if (state == LineBreakState::kContinue && auto_wrap_ && !line_.CanFit()) {
- state = HandleOverflow(line_info);
+ if (state_ == LineBreakState::kContinue && auto_wrap_ &&
+ position_ > AvailableWidthToFit()) {
+ HandleOverflow();
}
// If we reach at the end of the block, this is the last line.
DCHECK_LE(item_index_, items.size());
if (item_index_ == items.size()) {
- RemoveTrailingCollapsibleSpace(line_info);
- line_info->SetIsLastLine(true);
+ line_info_->SetIsLastLine(true);
return;
}
@@ -225,55 +221,57 @@ void NGLineBreaker::BreakLine(NGLineInfo* line_info) {
// They (or part of them) may also overhang the available width.
const NGInlineItem& item = items[item_index_];
if (item.Type() == NGInlineItem::kText) {
- state = HandleText(item, state, line_info);
+ HandleText(item);
#if DCHECK_IS_ON()
- if (!item_results->IsEmpty())
- item_results->back().CheckConsistency();
+ if (!item_results_->IsEmpty())
+ item_results_->back().CheckConsistency(true);
#endif
continue;
}
if (item.Type() == NGInlineItem::kCloseTag) {
- HandleCloseTag(item, item_results);
+ HandleCloseTag(item);
continue;
}
if (item.Type() == NGInlineItem::kControl) {
- state = HandleControlItem(item, state, line_info);
+ HandleControlItem(item);
+ continue;
+ }
+ if (item.Type() == NGInlineItem::kFloating) {
+ HandleFloat(item);
continue;
}
if (item.Type() == NGInlineItem::kBidiControl) {
- state = HandleBidiControlItem(item, state, line_info);
+ HandleBidiControlItem(item);
continue;
}
// Items after this point are not trailable. Break at the earliest break
// opportunity if we're trailing.
- if (state == LineBreakState::kTrailing &&
- CanBreakAfterLast(*item_results)) {
- line_info->SetIsLastLine(false);
+ if (state_ == LineBreakState::kTrailing &&
+ CanBreakAfterLast(*item_results_)) {
+ line_info_->SetIsLastLine(false);
return;
}
if (item.Type() == NGInlineItem::kAtomicInline) {
- HandleAtomicInline(item, line_info);
+ HandleAtomicInline(item);
} else if (item.Type() == NGInlineItem::kOpenTag) {
- HandleOpenTag(item, AddItem(item, item_results));
- } else if (item.Type() == NGInlineItem::kFloating) {
- HandleFloat(item, line_info, AddItem(item, item_results));
+ HandleOpenTag(item);
} else if (item.Type() == NGInlineItem::kOutOfFlowPositioned) {
DCHECK_EQ(item.Length(), 0u);
- AddItem(item, item_results);
+ AddItem(item);
MoveToNextOf(item);
} else if (item.Length()) {
NOTREACHED();
// For other items with text (e.g., bidi controls), use their text to
// determine the break opportunity.
- NGInlineItemResult* item_result = AddItem(item, item_results);
+ NGInlineItemResult* item_result = AddItem(item);
item_result->can_break_after =
break_iterator_.IsBreakable(item_result->end_offset);
MoveToNextOf(item);
} else if (item.Type() == NGInlineItem::kListMarker) {
- line_.should_create_line_box = true;
- NGInlineItemResult* item_result = AddItem(item, item_results);
+ NGInlineItemResult* item_result = AddItem(item);
+ has_list_marker_ = true;
DCHECK(!item_result->can_break_after);
MoveToNextOf(item);
} else {
@@ -283,84 +281,111 @@ void NGLineBreaker::BreakLine(NGLineInfo* line_info) {
}
}
-// Re-compute the current position from NGInlineItemResults.
+// Re-compute the current position from NGLineInfo.
// The current position is usually updated as NGLineBreaker builds
// NGInlineItemResults. This function re-computes it when it was lost.
-void NGLineBreaker::UpdatePosition(const NGInlineItemResults& results) {
- LayoutUnit position;
- for (const NGInlineItemResult& item_result : results)
- position += item_result.inline_size;
- line_.position = position;
+void NGLineBreaker::UpdatePosition() {
+ position_ = line_info_->ComputeWidth();
}
-void NGLineBreaker::ComputeLineLocation(NGLineInfo* line_info) const {
- LayoutUnit bfc_line_offset = line_.line_opportunity.line_left_offset;
- LayoutUnit available_width = line_.AvailableWidth();
+void NGLineBreaker::ComputeLineLocation() const {
+ LayoutUnit bfc_line_offset = line_opportunity_.line_left_offset;
+ LayoutUnit available_width = AvailableWidth();
+ DCHECK_EQ(position_, line_info_->ComputeWidth());
// Negative margins can make the position negative, but the inline size is
// always positive or 0.
- line_info->SetLineBfcOffset(
- {bfc_line_offset, line_.line_opportunity.bfc_block_offset},
- available_width, line_.position.ClampNegativeToZero());
+ line_info_->SetLineBfcOffset(
+ {bfc_line_offset, line_opportunity_.bfc_block_offset}, available_width,
+ position_.ClampNegativeToZero());
}
-NGLineBreaker::LineBreakState NGLineBreaker::HandleText(
- const NGInlineItem& item,
- LineBreakState state,
- NGLineInfo* line_info) {
+void NGLineBreaker::HandleText(const NGInlineItem& item) {
DCHECK_EQ(item.Type(), NGInlineItem::kText);
DCHECK(item.TextShapeResult());
- NGInlineItemResults* item_results = &line_info->Results();
// If we're trailing, only trailing spaces can be included in this line.
- if (state == LineBreakState::kTrailing && CanBreakAfterLast(*item_results)) {
- return HandleTrailingSpaces(item, line_info);
+ if (state_ == LineBreakState::kTrailing &&
+ CanBreakAfterLast(*item_results_)) {
+ return HandleTrailingSpaces(item);
}
- line_.should_create_line_box = true;
- NGInlineItemResult* item_result = AddItem(item, item_results);
- LayoutUnit available_width = line_.AvailableWidth();
+ // Skip leading collapsible spaces.
+ // Most cases such spaces are handled as trailing spaces of the previous line,
+ // but there are some cases doing so is too complex.
+ if (state_ == LineBreakState::kLeading) {
+ state_ = LineBreakState::kContinue;
+ if (item.Style()->CollapseWhiteSpace() &&
+ Text()[offset_] == kSpaceCharacter) {
+ // Skipping one whitespace removes all collapsible spaces because
+ // collapsible spaces are collapsed to single space in
+ // NGInlineItemBuilder.
+ ++offset_;
+ if (offset_ == item.EndOffset()) {
+ MoveToNextOf(item);
+ return;
+ }
+ }
+ }
+
+ NGInlineItemResult* item_result = AddItem(item);
+ item_result->should_create_line_box = true;
+ LayoutUnit available_width = AvailableWidthToFit();
if (auto_wrap_) {
// Try to break inside of this text item.
- BreakText(item_result, item, available_width - line_.position, line_info);
- LayoutUnit next_position = line_.position + item_result->inline_size;
+ BreakText(item_result, item, available_width - position_);
+
+ if (item.IsSymbolMarker()) {
+ LayoutUnit symbol_width = LayoutListMarker::WidthOfSymbol(*item.Style());
+ if (symbol_width > 0)
+ item_result->inline_size = symbol_width;
+ }
+
+ LayoutUnit next_position = position_ + item_result->inline_size;
bool is_overflow = next_position > available_width;
- line_.position = next_position;
+ DCHECK(is_overflow || item_result->shape_result);
+ position_ = next_position;
item_result->may_break_inside = !is_overflow;
MoveToNextOf(*item_result);
- if (!is_overflow || state == LineBreakState::kTrailing) {
+ if (!is_overflow ||
+ (state_ == LineBreakState::kTrailing && item_result->shape_result)) {
if (item_result->end_offset < item.EndOffset()) {
// The break point found, and text follows. Break here, after trailing
// spaces.
- return HandleTrailingSpaces(item, line_info);
+ return HandleTrailingSpaces(item);
}
// The break point found, but items that prohibit breaking before them may
// follow. Continue looking next items.
- return state;
+ return;
}
- return HandleOverflow(line_info);
+ return HandleOverflow();
}
// Add the rest of the item if !auto_wrap.
// Because the start position may need to reshape, run ShapingLineBreaker
// with max available width.
- BreakText(item_result, item, LayoutUnit::Max(), line_info);
+ BreakText(item_result, item, LayoutUnit::Max());
+
+ if (item.IsSymbolMarker()) {
+ LayoutUnit symbol_width = LayoutListMarker::WidthOfSymbol(*item.Style());
+ if (symbol_width > 0)
+ item_result->inline_size = symbol_width;
+ }
+
DCHECK_EQ(item_result->end_offset, item.EndOffset());
DCHECK(!item_result->may_break_inside);
item_result->can_break_after = false;
- line_.position += item_result->inline_size;
+ position_ += item_result->inline_size;
MoveToNextOf(item);
- return state;
}
void NGLineBreaker::BreakText(NGInlineItemResult* item_result,
const NGInlineItem& item,
- LayoutUnit available_width,
- NGLineInfo* line_info) {
+ LayoutUnit available_width) {
DCHECK_EQ(item.Type(), NGInlineItem::kText);
item.AssertOffset(item_result->start_offset);
@@ -370,19 +395,42 @@ void NGLineBreaker::BreakText(NGInlineItemResult* item_result,
// expensive?
DCHECK_EQ(item.TextShapeResult()->StartIndexForResult(), item.StartOffset());
DCHECK_EQ(item.TextShapeResult()->EndIndexForResult(), item.EndOffset());
+ RunSegmenter::RunSegmenterRange segment_range =
+ item.CreateRunSegmenterRange();
ShapingLineBreaker breaker(&shaper_, &item.Style()->GetFont(),
item.TextShapeResult(), &break_iterator_,
- &spacing_, hyphenation_);
+ &segment_range, &spacing_, hyphenation_);
if (!enable_soft_hyphen_)
breaker.DisableSoftHyphen();
available_width = std::max(LayoutUnit(0), available_width);
+
+ // Use kStartShouldBeSafe if at the beginning of a line.
+ unsigned options = ShapingLineBreaker::kDefaultOptions;
+ if (offset_ != line_info_->StartOffset())
+ options |= ShapingLineBreaker::kDontReshapeStart;
+
+ // Use kNoResultIfOverflow if 'break-word' and we're trying to break normally
+ // because if this item overflows, we will rewind and break line again. The
+ // overflowing ShapeResult is not needed.
+ if (break_anywhere_if_overflow_ && !override_break_anywhere_)
+ options |= ShapingLineBreaker::kNoResultIfOverflow;
ShapingLineBreaker::Result result;
- scoped_refptr<ShapeResult> shape_result =
- breaker.ShapeLine(item_result->start_offset, available_width,
- offset_ == line_info->StartOffset(), &result);
- DCHECK_GT(shape_result->NumCharacters(), 0u);
+ scoped_refptr<const ShapeResult> shape_result = breaker.ShapeLine(
+ item_result->start_offset, available_width, options, &result);
+
+ // If this item overflows and 'break-word' is set, this line will be
+ // rewinded. Making this item long enough to overflow is enough.
+ if (!shape_result) {
+ DCHECK(options & ShapingLineBreaker::kNoResultIfOverflow);
+ item_result->inline_size = available_width + 1;
+ item_result->end_offset = item.EndOffset();
+ return;
+ }
+ DCHECK_EQ(shape_result->NumCharacters(),
+ result.break_offset - item_result->start_offset);
+
if (result.is_hyphenated) {
- AppendHyphen(item, line_info);
+ AppendHyphen(item);
// TODO(kojii): Implement when adding a hyphen caused overflow.
// crbug.com/714962: Should be removed when switched to NGPaint.
item_result->text_end_effect = NGTextEndEffect::kHyphen;
@@ -409,42 +457,103 @@ void NGLineBreaker::BreakText(NGInlineItemResult* item_result,
}
}
-NGLineBreaker::LineBreakState NGLineBreaker::HandleTrailingSpaces(
- const NGInlineItem& item,
- NGLineInfo* line_info) {
+// Re-shape the specified range of |NGInlineItem|.
+scoped_refptr<ShapeResult> NGLineBreaker::ShapeText(const NGInlineItem& item,
+ unsigned start,
+ unsigned end) {
+ RunSegmenter::RunSegmenterRange segment_range =
+ item.CreateRunSegmenterRange();
+ scoped_refptr<ShapeResult> result = shaper_.Shape(
+ &item.Style()->GetFont(), item.TextShapeResult()->Direction(), start, end,
+ &segment_range);
+ if (UNLIKELY(spacing_.HasSpacing()))
+ result->ApplySpacing(spacing_);
+ return result;
+}
+
+// Compute a new ShapeResult for the specified end offset.
+// The end is re-shaped if it is not safe-to-break.
+scoped_refptr<ShapeResult> NGLineBreaker::TruncateLineEndResult(
+ const NGInlineItemResult& item_result,
+ unsigned end_offset) {
+ DCHECK(item_result.item);
+ DCHECK(item_result.shape_result);
+ const ShapeResult& source_result = *item_result.shape_result;
+ const unsigned start_offset = item_result.start_offset;
+ DCHECK_GE(start_offset, source_result.StartIndexForResult());
+ DCHECK_LE(end_offset, source_result.EndIndexForResult());
+ DCHECK(start_offset > source_result.StartIndexForResult() ||
+ end_offset < source_result.EndIndexForResult());
+
+ scoped_refptr<ShapeResult> new_result;
+ unsigned last_safe = source_result.PreviousSafeToBreakOffset(end_offset);
+ DCHECK_LE(last_safe, end_offset);
+ if (last_safe > start_offset)
+ new_result = source_result.SubRange(start_offset, last_safe);
+ if (last_safe < end_offset) {
+ scoped_refptr<ShapeResult> end_result = ShapeText(
+ *item_result.item, std::max(last_safe, start_offset), end_offset);
+ if (new_result)
+ end_result->CopyRange(0, end_offset, new_result.get());
+ else
+ new_result = std::move(end_result);
+ }
+ DCHECK(new_result);
+ return new_result;
+}
+
+// Update |ShapeResult| in |item_result| to match to its |start_offset| and
+// |end_offset|. The end is re-shaped if it is not safe-to-break.
+void NGLineBreaker::UpdateShapeResult(NGInlineItemResult* item_result) {
+ DCHECK(item_result);
+ item_result->shape_result =
+ TruncateLineEndResult(*item_result, item_result->end_offset);
+ DCHECK(item_result->shape_result);
+ item_result->inline_size = item_result->shape_result->SnappedWidth();
+}
+
+void NGLineBreaker::HandleTrailingSpaces(const NGInlineItem& item) {
DCHECK_EQ(item.Type(), NGInlineItem::kText);
DCHECK_LT(offset_, item.EndOffset());
const String& text = Text();
- NGInlineItemResults* item_results = &line_info->Results();
DCHECK(item.Style());
const ComputedStyle& style = *item.Style();
if (style.CollapseWhiteSpace()) {
- if (text[offset_] != kSpaceCharacter)
- return LineBreakState::kDone;
+ if (text[offset_] != kSpaceCharacter) {
+ state_ = LineBreakState::kDone;
+ return;
+ }
// Skipping one whitespace removes all collapsible spaces because
// collapsible spaces are collapsed to single space in NGInlineItemBuilder.
offset_++;
+ trailing_spaces_collapsed_ = true;
// Make the last item breakable after, even if it was nowrap.
- DCHECK(!item_results->IsEmpty());
- item_results->back().can_break_after = true;
+ DCHECK(!item_results_->IsEmpty());
+ item_results_->back().can_break_after = true;
} else {
// Find the end of the run of space characters in this item.
// Other white space characters (e.g., tab) are not included in this item.
DCHECK(style.BreakOnlyAfterWhiteSpace());
+ trailing_spaces_collapsed_ = true;
unsigned end = offset_;
while (end < item.EndOffset() && text[end] == kSpaceCharacter)
end++;
- if (end == offset_)
- return LineBreakState::kDone;
+ if (end == offset_) {
+ state_ = LineBreakState::kDone;
+ return;
+ }
- NGInlineItemResult* item_result = AddItem(item, end, item_results);
+ NGInlineItemResult* item_result = AddItem(item, end);
item_result->has_only_trailing_spaces = true;
- // TODO(kojii): Should reshape if it's not safe to break.
- item_result->shape_result = item.TextShapeResult()->SubRange(offset_, end);
- item_result->inline_size = item_result->shape_result->SnappedWidth();
- line_.position += item_result->inline_size;
+ item_result->shape_result = item.TextShapeResult();
+ if (item_result->start_offset == item.StartOffset() &&
+ item_result->end_offset == item.EndOffset())
+ item_result->inline_size = item_result->shape_result->SnappedWidth();
+ else
+ UpdateShapeResult(item_result);
+ position_ += item_result->inline_size;
item_result->can_break_after =
end < text.length() && !IsBreakableSpace(text[end]);
offset_ = end;
@@ -453,101 +562,143 @@ NGLineBreaker::LineBreakState NGLineBreaker::HandleTrailingSpaces(
// If non-space characters follow, the line is done.
// Otherwise keep checking next items for the break point.
DCHECK_LE(offset_, item.EndOffset());
- if (offset_ < item.EndOffset())
- return LineBreakState::kDone;
+ if (offset_ < item.EndOffset()) {
+ state_ = LineBreakState::kDone;
+ return;
+ }
item_index_++;
- return LineBreakState::kTrailing;
+ state_ = LineBreakState::kTrailing;
}
// Remove trailing collapsible spaces in |line_info|.
// https://drafts.csswg.org/css-text-3/#white-space-phase-2
-void NGLineBreaker::RemoveTrailingCollapsibleSpace(NGLineInfo* line_info) {
- NGInlineItemResults* item_results = &line_info->Results();
- if (item_results->IsEmpty())
+void NGLineBreaker::RemoveTrailingCollapsibleSpace() {
+ DCHECK(!trailing_spaces_collapsed_);
+
+ ComputeTrailingCollapsibleSpace();
+ trailing_spaces_collapsed_ = true;
+ if (!trailing_collapsible_space_.has_value())
return;
- for (auto it = item_results->rbegin(); it != item_results->rend(); ++it) {
+
+ // We have a trailing collapsible space. Remove it.
+ NGInlineItemResult* item_result = trailing_collapsible_space_->item_result;
+ position_ -= item_result->inline_size;
+ if (scoped_refptr<const ShapeResult>& collapsed_shape_result =
+ trailing_collapsible_space_->collapsed_shape_result) {
+ DCHECK_GE(item_result->end_offset, item_result->start_offset + 2);
+ --item_result->end_offset;
+ item_result->shape_result = std::move(collapsed_shape_result);
+ item_result->inline_size = item_result->shape_result->SnappedWidth();
+ position_ += item_result->inline_size;
+ } else {
+ item_results_->erase(item_result);
+ }
+ trailing_collapsible_space_.reset();
+}
+
+// Compute the width of trailing spaces without removing it.
+LayoutUnit NGLineBreaker::TrailingCollapsibleSpaceWidth() {
+ if (trailing_spaces_collapsed_)
+ return LayoutUnit();
+
+ ComputeTrailingCollapsibleSpace();
+ if (!trailing_collapsible_space_.has_value())
+ return LayoutUnit();
+
+ // Normally, the width of new_reuslt is smaller, but technically it can be
+ // larger. In such case, it means the trailing spaces has negative width.
+ NGInlineItemResult* item_result = trailing_collapsible_space_->item_result;
+ if (scoped_refptr<const ShapeResult>& collapsed_shape_result =
+ trailing_collapsible_space_->collapsed_shape_result) {
+ return item_result->inline_size - collapsed_shape_result->SnappedWidth();
+ }
+ return item_result->inline_size;
+}
+
+// Find trailing collapsible space if exists. The result is cached to
+// |trailing_collapsible_space_|.
+void NGLineBreaker::ComputeTrailingCollapsibleSpace() {
+ DCHECK(!trailing_spaces_collapsed_);
+
+ for (auto it = item_results_->rbegin(); it != item_results_->rend(); ++it) {
NGInlineItemResult& item_result = *it;
DCHECK(item_result.item);
const NGInlineItem& item = *item_result.item;
if (item.EndCollapseType() == NGInlineItem::kOpaqueToCollapsing)
continue;
if (item.Type() != NGInlineItem::kText)
- return;
- const String& text = Text();
- if (text[item_result.end_offset - 1] != kSpaceCharacter)
- return;
+ break;
+ DCHECK_GT(item_result.end_offset, 0u);
DCHECK(item.Style());
- if (!item.Style()->CollapseWhiteSpace())
- return;
+ if (Text()[item_result.end_offset - 1] != kSpaceCharacter ||
+ !item.Style()->CollapseWhiteSpace() ||
+ // |shape_result| is nullptr if this is an overflow because BreakText()
+ // uses kNoResultIfOverflow option.
+ !item_result.shape_result)
+ break;
- // We have a trailing collapsible space. Remove it.
- line_.position -= item_result.inline_size;
- --item_result.end_offset;
- if (item_result.end_offset == item_result.start_offset) {
- unsigned index = std::distance(item_results->begin(), &item_result);
- item_results->EraseAt(index);
- } else {
- // TODO(kojii): Should reshape if it's not safe to break.
- item_result.shape_result = item_result.shape_result->SubRange(
- item_result.start_offset, item_result.end_offset);
- item_result.inline_size = item_result.shape_result->SnappedWidth();
- line_.position += item_result.inline_size;
+ if (!trailing_collapsible_space_.has_value() ||
+ trailing_collapsible_space_->item_result != &item_result) {
+ trailing_collapsible_space_.emplace();
+ trailing_collapsible_space_->item_result = &item_result;
+ if (item_result.end_offset - 1 > item_result.start_offset) {
+ trailing_collapsible_space_->collapsed_shape_result =
+ TruncateLineEndResult(item_result, item_result.end_offset - 1);
+ }
}
return;
}
+
+ trailing_collapsible_space_.reset();
}
-void NGLineBreaker::AppendHyphen(const NGInlineItem& item,
- NGLineInfo* line_info) {
+void NGLineBreaker::AppendHyphen(const NGInlineItem& item) {
DCHECK(item.Style());
const ComputedStyle& style = *item.Style();
TextDirection direction = style.Direction();
String hyphen_string = style.HyphenString();
- hyphen_string.Ensure16Bit();
- HarfBuzzShaper shaper(hyphen_string.Characters16(), hyphen_string.length());
+ HarfBuzzShaper shaper(hyphen_string);
scoped_refptr<ShapeResult> hyphen_result =
shaper.Shape(&style.GetFont(), direction);
NGTextFragmentBuilder builder(node_, constraint_space_.GetWritingMode());
builder.SetText(item.GetLayoutObject(), hyphen_string, &style,
/* is_ellipsis_style */ false, std::move(hyphen_result));
- SetLineEndFragment(builder.ToTextFragment(), line_info);
+ SetLineEndFragment(builder.ToTextFragment());
}
// Measure control items; new lines and tab, that are similar to text, affect
// layout, but do not need shaping/painting.
-NGLineBreaker::LineBreakState NGLineBreaker::HandleControlItem(
- const NGInlineItem& item,
- LineBreakState state,
- NGLineInfo* line_info) {
+void NGLineBreaker::HandleControlItem(const NGInlineItem& item) {
DCHECK_EQ(item.Length(), 1u);
- line_.should_create_line_box = true;
UChar character = Text()[item.StartOffset()];
switch (character) {
case kNewlineCharacter: {
- NGInlineItemResult* item_result = AddItem(item, &line_info->Results());
+ NGInlineItemResult* item_result = AddItem(item);
+ item_result->should_create_line_box = true;
item_result->has_only_trailing_spaces = true;
- line_.is_after_forced_break = true;
- line_info->SetIsLastLine(true);
- state = LineBreakState::kDone;
+ is_after_forced_break_ = true;
+ line_info_->SetIsLastLine(true);
+ state_ = LineBreakState::kDone;
break;
}
case kTabulationCharacter: {
- NGInlineItemResult* item_result = AddItem(item, &line_info->Results());
+ NGInlineItemResult* item_result = AddItem(item);
+ item_result->should_create_line_box = true;
DCHECK(item.Style());
const ComputedStyle& style = *item.Style();
const Font& font = style.GetFont();
- item_result->inline_size =
- font.TabWidth(style.GetTabSize(), line_.position);
- line_.position += item_result->inline_size;
+ item_result->inline_size = font.TabWidth(style.GetTabSize(), position_);
+ position_ += item_result->inline_size;
item_result->has_only_trailing_spaces =
- state == LineBreakState::kTrailing;
+ state_ == LineBreakState::kTrailing;
ComputeCanBreakAfter(item_result);
break;
}
case kZeroWidthSpaceCharacter: {
// <wbr> tag creates break opportunities regardless of auto_wrap.
- NGInlineItemResult* item_result = AddItem(item, &line_info->Results());
+ NGInlineItemResult* item_result = AddItem(item);
+ item_result->should_create_line_box = true;
item_result->can_break_after = true;
break;
}
@@ -562,15 +713,10 @@ NGLineBreaker::LineBreakState NGLineBreaker::HandleControlItem(
break;
}
MoveToNextOf(item);
- return state;
}
-NGLineBreaker::LineBreakState NGLineBreaker::HandleBidiControlItem(
- const NGInlineItem& item,
- LineBreakState state,
- NGLineInfo* line_info) {
+void NGLineBreaker::HandleBidiControlItem(const NGInlineItem& item) {
DCHECK_EQ(item.Length(), 1u);
- NGInlineItemResults* item_results = &line_info->Results();
// Bidi control characters have enter/exit semantics. Handle "enter"
// characters simialr to open-tag, while "exit" (pop) characters similar to
@@ -579,34 +725,33 @@ NGLineBreaker::LineBreakState NGLineBreaker::HandleBidiControlItem(
bool is_pop = character == kPopDirectionalIsolateCharacter ||
character == kPopDirectionalFormattingCharacter;
if (is_pop) {
- if (!item_results->IsEmpty()) {
- NGInlineItemResult* item_result = AddItem(item, item_results);
- NGInlineItemResult* last = &(*item_results)[item_results->size() - 2];
+ if (!item_results_->IsEmpty()) {
+ NGInlineItemResult* item_result = AddItem(item);
+ NGInlineItemResult* last = &(*item_results_)[item_results_->size() - 2];
item_result->can_break_after = last->can_break_after;
last->can_break_after = false;
} else {
- AddItem(item, item_results);
+ AddItem(item);
}
} else {
- if (state == LineBreakState::kTrailing &&
- CanBreakAfterLast(*item_results)) {
- line_info->SetIsLastLine(false);
+ if (state_ == LineBreakState::kTrailing &&
+ CanBreakAfterLast(*item_results_)) {
+ line_info_->SetIsLastLine(false);
MoveToNextOf(item);
- return LineBreakState::kDone;
+ state_ = LineBreakState::kDone;
+ return;
}
- NGInlineItemResult* item_result = AddItem(item, item_results);
+ NGInlineItemResult* item_result = AddItem(item);
DCHECK(!item_result->can_break_after);
}
MoveToNextOf(item);
- return state;
}
-void NGLineBreaker::HandleAtomicInline(const NGInlineItem& item,
- NGLineInfo* line_info) {
+void NGLineBreaker::HandleAtomicInline(const NGInlineItem& item) {
DCHECK_EQ(item.Type(), NGInlineItem::kAtomicInline);
- line_.should_create_line_box = true;
- NGInlineItemResult* item_result = AddItem(item, &line_info->Results());
+ NGInlineItemResult* item_result = AddItem(item);
+ item_result->should_create_line_box = true;
// When we're just computing min/max content sizes, we can skip the full
// layout and just compute those sizes. On the other hand, for regular
// layout we need to do the full layout and get the layout result.
@@ -616,8 +761,8 @@ void NGLineBreaker::HandleAtomicInline(const NGInlineItem& item,
item_result->layout_result =
NGBlockNode(ToLayoutBox(item.GetLayoutObject()))
.LayoutAtomicInline(constraint_space_,
- line_info->LineStyle().GetFontBaseline(),
- line_info->UseFirstLineStyle());
+ line_info_->LineStyle().GetFontBaseline(),
+ line_info_->UseFirstLineStyle());
DCHECK(item_result->layout_result->PhysicalFragment());
item_result->inline_size =
@@ -636,12 +781,18 @@ void NGLineBreaker::HandleAtomicInline(const NGInlineItem& item,
}
DCHECK(item.Style());
+ const ComputedStyle& style = *item.Style();
+ bool is_flipped_lines = style.IsFlippedLinesWritingMode();
item_result->margins =
- ComputeMarginsForVisualContainer(constraint_space_, *item.Style());
- item_result->padding = ComputePadding(constraint_space_, *item.Style());
+ NGLineBoxStrut(ComputeMarginsForVisualContainer(constraint_space_, style),
+ is_flipped_lines);
+ item_result->padding = NGLineBoxStrut(
+ ComputePadding(constraint_space_, style), is_flipped_lines);
item_result->inline_size += item_result->margins.InlineSum();
- line_.position += item_result->inline_size;
+ if (state_ == LineBreakState::kLeading)
+ state_ = LineBreakState::kContinue;
+ position_ += item_result->inline_size;
ComputeCanBreakAfter(item_result);
MoveToNextOf(item);
}
@@ -660,9 +811,7 @@ void NGLineBreaker::HandleAtomicInline(const NGInlineItem& item,
// We have this check if there are already UnpositionedFloats as we aren't
// allowed to position a float "above" another float which has come before us
// in the document.
-void NGLineBreaker::HandleFloat(const NGInlineItem& item,
- NGLineInfo* line_info,
- NGInlineItemResult* item_result) {
+void NGLineBreaker::HandleFloat(const NGInlineItem& item) {
// When rewind occurs, an item may be handled multiple times.
// Since floats are put into a separate list, avoid handling same floats
// twice.
@@ -672,18 +821,12 @@ void NGLineBreaker::HandleFloat(const NGInlineItem& item,
// Additionally, we need to skip floats if we're retrying a line after a
// fragmentainer break. In that case the floats associated with this line will
// already have been processed.
+ NGInlineItemResult* item_result = AddItem(item);
ComputeCanBreakAfter(item_result);
MoveToNextOf(item);
if (item_index_ <= handled_floats_end_item_index_ || ignore_floats_)
return;
- // Floats need to know the current line width to determine whether to put it
- // into the current line or to the next line. Remove trailing spaces if this
- // float is trailing, because whitespace should be collapsed across floats,
- // and this logic requires the width after trailing spaces are collapsed.
- if (IsTrailing(item, *line_info))
- RemoveTrailingCollapsibleSpace(line_info);
-
NGBlockNode node(ToLayoutBox(item.GetLayoutObject()));
const ComputedStyle& float_style = node.Style();
@@ -706,7 +849,21 @@ void NGLineBreaker::HandleFloat(const NGInlineItem& item,
margins.InlineSum())
.ClampNegativeToZero();
- LayoutUnit bfc_block_offset = line_.line_opportunity.bfc_block_offset;
+ LayoutUnit bfc_block_offset = line_opportunity_.bfc_block_offset;
+
+ bool can_fit_float =
+ position_ + inline_margin_size <=
+ line_opportunity_.AvailableFloatInlineSize().AddEpsilon();
+ if (!can_fit_float) {
+ // Floats need to know the current line width to determine whether to put it
+ // into the current line or to the next line. Trailing spaces will be
+ // removed if this line breaks here because they should be collapsed across
+ // floats, but they are still included in the current line position at this
+ // point. Exclude it when computing whether this float can fit or not.
+ can_fit_float =
+ position_ + inline_margin_size - TrailingCollapsibleSpaceWidth() <=
+ line_opportunity_.AvailableFloatInlineSize().AddEpsilon();
+ }
// The float should be positioned after the current line if:
// - It can't fit within the non-shape area. (Assuming the current position
@@ -717,7 +874,7 @@ void NGLineBreaker::HandleFloat(const NGInlineItem& item,
// unpositioned_floats to manually adjust the min/max-content size after
// the line breaker has run).
bool float_after_line =
- !line_.CanFloatFit(inline_margin_size) ||
+ !can_fit_float ||
exclusion_space_->LastFloatBlockStart() > bfc_block_offset ||
exclusion_space_->ClearanceOffset(float_style.Clear()) >
bfc_block_offset ||
@@ -743,11 +900,10 @@ void NGLineBreaker::HandleFloat(const NGInlineItem& item,
DCHECK_EQ(bfc_block_offset, opportunity.rect.BlockStartOffset());
- line_.line_opportunity = opportunity.ComputeLineLayoutOpportunity(
- constraint_space_, line_.line_opportunity.line_block_size,
- LayoutUnit());
+ line_opportunity_ = opportunity.ComputeLineLayoutOpportunity(
+ constraint_space_, line_opportunity_.line_block_size, LayoutUnit());
- DCHECK_GE(line_.AvailableWidth(), LayoutUnit());
+ DCHECK_GE(AvailableWidth(), LayoutUnit());
}
}
@@ -762,38 +918,42 @@ bool NGLineBreaker::ComputeOpenTagResult(
if (item.ShouldCreateBoxFragment() &&
(style.HasBorder() || style.HasPadding() ||
(style.HasMargin() && item_result->has_edge))) {
- NGBoxStrut borders = ComputeBorders(constraint_space, style);
- NGBoxStrut paddings = ComputePadding(constraint_space, style);
- item_result->padding = paddings;
- item_result->borders_paddings_block_start =
- borders.block_start + paddings.block_start;
- item_result->borders_paddings_block_end =
- borders.block_end + paddings.block_end;
+ bool is_flipped_lines = style.IsFlippedLinesWritingMode();
+ NGLineBoxStrut borders = NGLineBoxStrut(
+ ComputeBorders(constraint_space, style), is_flipped_lines);
+ item_result->padding = NGLineBoxStrut(
+ ComputePadding(constraint_space, style), is_flipped_lines);
+ item_result->borders_paddings_line_over =
+ borders.line_over + item_result->padding.line_over;
+ item_result->borders_paddings_line_under =
+ borders.line_under + item_result->padding.line_under;
if (item_result->has_edge) {
- item_result->margins = ComputeMarginsForSelf(constraint_space, style);
+ item_result->margins = NGLineBoxStrut(
+ ComputeMarginsForSelf(constraint_space, style), is_flipped_lines);
item_result->inline_size = item_result->margins.inline_start +
- borders.inline_start + paddings.inline_start;
+ borders.inline_start +
+ item_result->padding.inline_start;
return true;
}
}
return false;
}
-void NGLineBreaker::HandleOpenTag(const NGInlineItem& item,
- NGInlineItemResult* item_result) {
+void NGLineBreaker::HandleOpenTag(const NGInlineItem& item) {
+ NGInlineItemResult* item_result = AddItem(item);
DCHECK(!item_result->can_break_after);
if (ComputeOpenTagResult(item, constraint_space_, item_result)) {
- line_.position += item_result->inline_size;
+ position_ += item_result->inline_size;
// While the spec defines "non-zero margins, padding, or borders" prevents
// line boxes to be zero-height, tests indicate that only inline direction
// of them do so. See should_create_line_box_.
// Force to create a box, because such inline boxes affect line heights.
- if (!line_.should_create_line_box &&
+ if (!item_result->should_create_line_box &&
(item_result->inline_size ||
(item_result->margins.inline_start && !in_line_height_quirks_mode_)))
- line_.should_create_line_box = true;
+ item_result->should_create_line_box = true;
}
DCHECK(item.Style());
@@ -802,24 +962,25 @@ void NGLineBreaker::HandleOpenTag(const NGInlineItem& item,
MoveToNextOf(item);
}
-void NGLineBreaker::HandleCloseTag(const NGInlineItem& item,
- NGInlineItemResults* item_results) {
- NGInlineItemResult* item_result = AddItem(item, item_results);
+void NGLineBreaker::HandleCloseTag(const NGInlineItem& item) {
+ NGInlineItemResult* item_result = AddItem(item);
item_result->has_edge = item.HasEndEdge();
if (item_result->has_edge) {
DCHECK(item.Style());
const ComputedStyle& style = *item.Style();
- item_result->margins = ComputeMarginsForSelf(constraint_space_, style);
+ bool is_flipped_lines = style.IsFlippedLinesWritingMode();
+ item_result->margins = NGLineBoxStrut(
+ ComputeMarginsForSelf(constraint_space_, style), is_flipped_lines);
NGBoxStrut borders = ComputeBorders(constraint_space_, style);
NGBoxStrut paddings = ComputePadding(constraint_space_, style);
item_result->inline_size = item_result->margins.inline_end +
borders.inline_end + paddings.inline_end;
- line_.position += item_result->inline_size;
+ position_ += item_result->inline_size;
- if (!line_.should_create_line_box &&
+ if (!item_result->should_create_line_box &&
(item_result->inline_size ||
(item_result->margins.inline_end && !in_line_height_quirks_mode_)))
- line_.should_create_line_box = true;
+ item_result->should_create_line_box = true;
}
DCHECK(item.GetLayoutObject() && item.GetLayoutObject()->Parent());
bool was_auto_wrap = auto_wrap_;
@@ -831,8 +992,8 @@ void NGLineBreaker::HandleCloseTag(const NGInlineItem& item,
// TODO(kojii): There should be a result before close tag, but there are cases
// that doesn't because of the way we handle trailing spaces. This needs to be
// revisited.
- if (item_results->size() >= 2) {
- NGInlineItemResult* last = &(*item_results)[item_results->size() - 2];
+ if (item_results_->size() >= 2) {
+ NGInlineItemResult* last = &(*item_results_)[item_results_->size() - 2];
if (was_auto_wrap == auto_wrap_) {
item_result->can_break_after = last->can_break_after;
last->can_break_after = false;
@@ -859,31 +1020,26 @@ void NGLineBreaker::HandleCloseTag(const NGInlineItem& item,
// Handles when the last item overflows.
// At this point, item_results does not fit into the current line, and there
// are no break opportunities in item_results.back().
-NGLineBreaker::LineBreakState NGLineBreaker::HandleOverflow(
- NGLineInfo* line_info) {
- return HandleOverflow(line_info, line_.AvailableWidth());
-}
-
-NGLineBreaker::LineBreakState NGLineBreaker::HandleOverflow(
- NGLineInfo* line_info,
- LayoutUnit available_width) {
- NGInlineItemResults* item_results = &line_info->Results();
- LayoutUnit width_to_rewind = line_.position - available_width;
+void NGLineBreaker::HandleOverflow() {
+ LayoutUnit available_width = AvailableWidthToFit();
+ LayoutUnit width_to_rewind = position_ - available_width;
DCHECK_GT(width_to_rewind, 0);
+ bool position_maybe_changed = false;
// Keep track of the shortest break opportunity.
unsigned break_before = 0;
// Search for a break opportunity that can fit.
- for (unsigned i = item_results->size(); i;) {
- NGInlineItemResult* item_result = &(*item_results)[--i];
+ for (unsigned i = item_results_->size(); i;) {
+ NGInlineItemResult* item_result = &(*item_results_)[--i];
// Try to break after this item.
- if (i < item_results->size() - 1 && item_result->can_break_after) {
+ if (i < item_results_->size() - 1 && item_result->can_break_after) {
if (width_to_rewind <= 0) {
- line_.position = available_width + width_to_rewind;
- Rewind(line_info, i + 1);
- return LineBreakState::kTrailing;
+ position_ = available_width + width_to_rewind;
+ Rewind(i + 1);
+ state_ = LineBreakState::kTrailing;
+ return;
}
break_before = i + 1;
}
@@ -900,33 +1056,32 @@ NGLineBreaker::LineBreakState NGLineBreaker::HandleOverflow(
LayoutUnit item_available_width =
std::min(-next_width_to_rewind, item_result->inline_size - 1);
SetCurrentStyle(*item.Style());
- BreakText(item_result, item, item_available_width, line_info);
+ BreakText(item_result, item, item_available_width);
#if DCHECK_IS_ON()
- item_result->CheckConsistency();
+ item_result->CheckConsistency(true);
#endif
+ // If BreakText() changed this item small enough to fit, break here.
if (item_result->inline_size <= item_available_width) {
DCHECK(item_result->end_offset < item.EndOffset());
DCHECK(item_result->can_break_after);
- DCHECK_LE(i + 1, item_results->size());
- if (i + 1 == item_results->size()) {
+ DCHECK_LE(i + 1, item_results_->size());
+ if (i + 1 == item_results_->size()) {
// If this is the last item, adjust states to accomodate the change.
- line_.position =
+ position_ =
available_width + next_width_to_rewind + item_result->inline_size;
- if (line_info->LineEndFragment())
- SetLineEndFragment(nullptr, line_info);
-#if DCHECK_IS_ON()
- LayoutUnit position_fast = line_.position;
- UpdatePosition(line_info->Results());
- DCHECK_EQ(line_.position, position_fast);
-#endif
+ if (line_info_->LineEndFragment())
+ SetLineEndFragment(nullptr);
+ DCHECK_EQ(position_, line_info_->ComputeWidth());
item_index_ = item_result->item_index;
offset_ = item_result->end_offset;
items_data_.AssertOffset(item_index_, offset_);
} else {
- Rewind(line_info, i + 1);
+ Rewind(i + 1);
}
- return LineBreakState::kTrailing;
+ state_ = LineBreakState::kTrailing;
+ return;
}
+ position_maybe_changed = true;
}
width_to_rewind = next_width_to_rewind;
@@ -937,65 +1092,81 @@ NGLineBreaker::LineBreakState NGLineBreaker::HandleOverflow(
if (break_anywhere_if_overflow_ && !override_break_anywhere_) {
override_break_anywhere_ = true;
break_iterator_.SetBreakType(LineBreakType::kBreakCharacter);
- Rewind(line_info, 0);
- return LineBreakState::kContinue;
+ if (!item_results_->IsEmpty())
+ Rewind(0);
+ state_ = LineBreakState::kLeading;
+ return;
}
// Let this line overflow.
// If there was a break opportunity, the overflow should stop there.
if (break_before) {
- Rewind(line_info, break_before);
- return LineBreakState::kTrailing;
+ Rewind(break_before);
+ state_ = LineBreakState::kTrailing;
+ return;
}
- return LineBreakState::kTrailing;
+ if (position_maybe_changed) {
+ UpdatePosition();
+ }
+
+ state_ = LineBreakState::kTrailing;
}
-void NGLineBreaker::Rewind(NGLineInfo* line_info, unsigned new_end) {
- NGInlineItemResults* item_results = &line_info->Results();
- DCHECK_LT(new_end, item_results->size());
+void NGLineBreaker::Rewind(unsigned new_end) {
+ NGInlineItemResults& item_results = *item_results_;
+ DCHECK_LT(new_end, item_results.size());
+
+ // Avoid rewinding floats if possible. They will be added back anyway while
+ // processing trailing items even when zero available width. Also this saves
+ // most cases where our support for rewinding positioned floats is not great
+ // yet (see below.)
+ while (item_results[new_end].item->Type() == NGInlineItem::kFloating) {
+ ++new_end;
+ if (new_end == item_results.size()) {
+ UpdatePosition();
+ return;
+ }
+ }
- // TODO(ikilpatrick): Add DCHECK that we never rewind past any floats.
+ // Because floats are added to |positioned_floats_| or |unpositioned_floats_|,
+ // rewinding them needs to remove from these lists too.
+ for (unsigned i = item_results.size(); i > new_end;) {
+ NGInlineItemResult& rewind = item_results[--i];
+ if (rewind.item->Type() == NGInlineItem::kFloating) {
+ NGBlockNode float_node(ToLayoutBox(rewind.item->GetLayoutObject()));
+ if (!RemoveUnpositionedFloat(unpositioned_floats_, float_node)) {
+ // TODO(kojii): We do not have mechanism to remove once positioned
+ // floats yet, and that rewinding them may lay it out twice. For now,
+ // prohibit rewinding positioned floats. This may results in incorrect
+ // layout, but still better than rewinding them.
+ new_end = i + 1;
+ if (new_end == item_results.size()) {
+ UpdatePosition();
+ return;
+ }
+ break;
+ }
+ }
+ }
if (new_end) {
// Use |results[new_end - 1].end_offset| because it may have been truncated
// and may not be equal to |results[new_end].start_offset|.
- MoveToNextOf((*item_results)[new_end - 1]);
+ MoveToNextOf(item_results[new_end - 1]);
} else {
// When rewinding all items, use |results[0].start_offset|.
- const NGInlineItemResult& first_remove = (*item_results)[new_end];
+ const NGInlineItemResult& first_remove = item_results[new_end];
item_index_ = first_remove.item_index;
offset_ = first_remove.start_offset;
}
- // TODO(kojii): Should we keep results for the next line? We don't need to
- // re-layout atomic inlines.
- item_results->Shrink(new_end);
-
- SetLineEndFragment(nullptr, line_info);
- UpdatePosition(line_info->Results());
-}
+ item_results.Shrink(new_end);
-// Returns the LayoutObject at the current index/offset.
-// This is to tie generated fragments to the source DOM node/LayoutObject for
-// paint invalidations, hit testing, etc.
-LayoutObject* NGLineBreaker::CurrentLayoutObject(
- const NGLineInfo& line_info) const {
- const Vector<NGInlineItem>& items = line_info.ItemsData().items;
- DCHECK_LE(item_index_, items.size());
- // Find the next item that has LayoutObject. Some items such as bidi controls
- // do not have LayoutObject.
- for (unsigned i = item_index_; i < items.size(); i++) {
- if (LayoutObject* layout_object = items[i].GetLayoutObject())
- return layout_object;
- }
- // Find the last item if there were no LayoutObject afterwards.
- for (unsigned i = item_index_; i--;) {
- if (LayoutObject* layout_object = items[i].GetLayoutObject())
- return layout_object;
- }
- NOTREACHED();
- return nullptr;
+ trailing_spaces_collapsed_ = false;
+ trailing_collapsible_space_.reset();
+ SetLineEndFragment(nullptr);
+ UpdatePosition();
}
void NGLineBreaker::SetCurrentStyle(const ComputedStyle& style) {
@@ -1058,7 +1229,7 @@ scoped_refptr<NGInlineBreakToken> NGLineBreaker::CreateBreakToken(
return NGInlineBreakToken::Create(node_);
return NGInlineBreakToken::Create(
node_, current_style_.get(), item_index_, offset_,
- ((line_.is_after_forced_break ? NGInlineBreakToken::kIsForcedBreak : 0) |
+ ((is_after_forced_break_ ? NGInlineBreakToken::kIsForcedBreak : 0) |
(line_info.UseFirstLineStyle() ? NGInlineBreakToken::kUseFirstLineStyle
: 0)),
std::move(state_stack));
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 b0838c40a67..5f52e8c952e 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
@@ -5,11 +5,12 @@
#ifndef NGLineBreaker_h
#define NGLineBreaker_h
+#include "base/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/exclusions/ng_line_layout_opportunity.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/platform/fonts/shaping/harf_buzz_shaper.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h"
#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
@@ -43,12 +44,13 @@ class CORE_EXPORT NGLineBreaker {
NGContainerFragmentBuilder* container_builder,
NGExclusionSpace*,
unsigned handled_float_index,
+ const NGLineLayoutOpportunity&,
const NGInlineBreakToken* = nullptr);
~NGLineBreaker();
// Compute the next line break point and produces NGInlineItemResults for
// the line.
- bool NextLine(const NGLineLayoutOpportunity& line_opportunity, NGLineInfo*);
+ void NextLine(NGLineInfo*);
// Create an NGInlineBreakToken for the last line returned by NextLine().
scoped_refptr<NGInlineBreakToken> CreateBreakToken(
@@ -62,63 +64,20 @@ class CORE_EXPORT NGLineBreaker {
NGInlineItemResult*);
private:
- // This struct holds information for the current line.
- struct LineData {
- STACK_ALLOCATED();
-
- LineData(NGInlineNode node, const NGInlineBreakToken* break_token);
-
- // The current position from inline_start. Unlike NGInlineLayoutAlgorithm
- // that computes position in visual order, this position in logical order.
- LayoutUnit position;
-
- NGLineLayoutOpportunity line_opportunity;
-
- // True if this line is the "first formatted line".
- // https://www.w3.org/TR/CSS22/selector.html#first-formatted-line
- bool is_first_formatted_line;
-
- bool use_first_line_style;
-
- // We don't create "certain zero-height line boxes".
- // https://drafts.csswg.org/css2/visuren.html#phantom-line-box
- // Such line boxes do not prevent two margins being "adjoining", and thus
- // collapsing.
- // https://drafts.csswg.org/css2/box.html#collapsing-margins
- bool should_create_line_box = false;
-
- // Set when the line ended with a forced break. Used to setup the states for
- // the next line.
- bool is_after_forced_break = false;
-
- LayoutUnit AvailableWidth() const {
- return line_opportunity.AvailableInlineSize();
- }
- bool CanFit() const { return position <= AvailableWidth(); }
- bool CanFit(LayoutUnit extra) const {
- return position + extra <= AvailableWidth();
- }
- bool CanFloatFit(LayoutUnit extra) const {
- return position + extra <= line_opportunity.AvailableFloatInlineSize();
- }
- };
-
const String& Text() const { return items_data_.text_content; }
const Vector<NGInlineItem>& Items() const { return items_data_.items; }
- NGInlineItemResult* AddItem(const NGInlineItem&,
- unsigned end_offset,
- NGInlineItemResults*);
- NGInlineItemResult* AddItem(const NGInlineItem&, NGInlineItemResults*);
- void SetLineEndFragment(scoped_refptr<NGPhysicalTextFragment>, NGLineInfo*);
+ NGInlineItemResult* AddItem(const NGInlineItem&, unsigned end_offset);
+ NGInlineItemResult* AddItem(const NGInlineItem&);
+ void SetLineEndFragment(scoped_refptr<NGPhysicalTextFragment>);
void ComputeCanBreakAfter(NGInlineItemResult*) const;
- void BreakLine(NGLineInfo*);
+ void BreakLine();
- void PrepareNextLine(const NGLineLayoutOpportunity&, NGLineInfo*);
+ void PrepareNextLine();
- void UpdatePosition(const NGInlineItemResults&);
- void ComputeLineLocation(NGLineInfo*) const;
+ void UpdatePosition();
+ void ComputeLineLocation() const;
enum class LineBreakState {
// The line breaking is complete.
@@ -129,72 +88,81 @@ class CORE_EXPORT NGLineBreaker {
// when it is overflowing.
kTrailing,
- // The initial state. Looking for items to break the line.
+ // The initial state, until the first character is found.
+ kLeading,
+
+ // Looking for more items to fit into the current line.
kContinue,
};
- LineBreakState HandleText(const NGInlineItem&, LineBreakState, NGLineInfo*);
+ void HandleText(const NGInlineItem&);
void BreakText(NGInlineItemResult*,
const NGInlineItem&,
- LayoutUnit available_width,
- NGLineInfo*);
- LineBreakState HandleTrailingSpaces(const NGInlineItem&, NGLineInfo*);
- void RemoveTrailingCollapsibleSpace(NGLineInfo*);
- void AppendHyphen(const NGInlineItem& item, NGLineInfo*);
-
- LineBreakState HandleControlItem(const NGInlineItem&,
- LineBreakState,
- NGLineInfo*);
- LineBreakState HandleBidiControlItem(const NGInlineItem&,
- LineBreakState,
- NGLineInfo*);
- void HandleAtomicInline(const NGInlineItem&, NGLineInfo*);
- void HandleFloat(const NGInlineItem&, NGLineInfo*, NGInlineItemResult*);
-
- void HandleOpenTag(const NGInlineItem&, NGInlineItemResult*);
- void HandleCloseTag(const NGInlineItem&, NGInlineItemResults*);
-
- LineBreakState HandleOverflow(NGLineInfo*);
- LineBreakState HandleOverflow(NGLineInfo*, LayoutUnit available_width);
- void Rewind(NGLineInfo*, unsigned new_end);
-
- LayoutObject* CurrentLayoutObject(const NGLineInfo&) const;
+ LayoutUnit available_width);
+
+ scoped_refptr<ShapeResult> TruncateLineEndResult(
+ const NGInlineItemResult& item_result,
+ unsigned end_offset);
+ void UpdateShapeResult(NGInlineItemResult*);
+ scoped_refptr<ShapeResult> ShapeText(const NGInlineItem& item,
+ unsigned start,
+ unsigned end);
+
+ void HandleTrailingSpaces(const NGInlineItem&);
+ void RemoveTrailingCollapsibleSpace();
+ LayoutUnit TrailingCollapsibleSpaceWidth();
+ void ComputeTrailingCollapsibleSpace();
+
+ void AppendHyphen(const NGInlineItem& item);
+
+ void HandleControlItem(const NGInlineItem&);
+ void HandleBidiControlItem(const NGInlineItem&);
+ void HandleAtomicInline(const NGInlineItem&);
+ void HandleFloat(const NGInlineItem&);
+
+ void HandleOpenTag(const NGInlineItem&);
+ void HandleCloseTag(const NGInlineItem&);
+
+ void HandleOverflow();
+ void Rewind(unsigned new_end);
void SetCurrentStyle(const ComputedStyle&);
void MoveToNextOf(const NGInlineItem&);
void MoveToNextOf(const NGInlineItemResult&);
- void ComputeBaseDirection(const NGLineInfo&);
- bool IsTrailing(const NGInlineItem&, const NGLineInfo&) const;
+ void ComputeBaseDirection();
- LineData line_;
- NGInlineNode node_;
- const NGInlineItemsData& items_data_;
+ LayoutUnit AvailableWidth() const {
+ return line_opportunity_.AvailableInlineSize();
+ }
+ LayoutUnit AvailableWidthToFit() const {
+ return AvailableWidth().AddEpsilon();
+ }
- NGLineBreakerMode mode_;
- const NGConstraintSpace& constraint_space_;
- Vector<NGPositionedFloat>* positioned_floats_;
- Vector<scoped_refptr<NGUnpositionedFloat>>* unpositioned_floats_;
- NGContainerFragmentBuilder* container_builder_; /* May be nullptr */
- NGExclusionSpace* exclusion_space_;
- scoped_refptr<const ComputedStyle> current_style_;
+ // These fields are the output of the current line.
+ // NGInlineItemResults is a pointer because the move operation is not cheap
+ // due to its inline buffer.
+ NGLineInfo* line_info_ = nullptr;
+ NGInlineItemResults* item_results_ = nullptr;
+ // Represents the current offset of the input.
+ LineBreakState state_;
unsigned item_index_ = 0;
unsigned offset_ = 0;
- LazyLineBreakIterator break_iterator_;
- HarfBuzzShaper shaper_;
- ShapeResultSpacing<String> spacing_;
- bool previous_line_had_forced_break_ = false;
- const Hyphenation* hyphenation_ = nullptr;
- // Keep track of handled float items. See HandleFloat().
- unsigned handled_floats_end_item_index_;
+ // The current position from inline_start. Unlike NGInlineLayoutAlgorithm
+ // that computes position in visual order, this position in logical order.
+ LayoutUnit position_;
+ NGLineLayoutOpportunity line_opportunity_;
- // The current base direction for the bidi algorithm.
- // This is copied from NGInlineNode, then updated after each forced line break
- // if 'unicode-bidi: plaintext'.
- TextDirection base_direction_;
+ NGInlineNode node_;
+
+ // True if this line is the "first formatted line".
+ // https://www.w3.org/TR/CSS22/selector.html#first-formatted-line
+ bool is_first_formatted_line_ = false;
+
+ bool use_first_line_style_ = false;
// True when current box allows line wrapping.
bool auto_wrap_ = false;
@@ -214,7 +182,49 @@ class CORE_EXPORT NGLineBreaker {
// https://quirks.spec.whatwg.org/#the-line-height-calculation-quirk
bool in_line_height_quirks_mode_ = false;
+ // True when the line we are breaking has a list marker.
+ bool has_list_marker_ = false;
+
+ // True if trailing collapsible spaces have been collapsed.
+ bool trailing_spaces_collapsed_ = false;
+
+ // Set when the line ended with a forced break. Used to setup the states for
+ // the next line.
+ bool is_after_forced_break_ = false;
+
bool ignore_floats_ = false;
+
+ const NGInlineItemsData& items_data_;
+
+ NGLineBreakerMode mode_;
+ const NGConstraintSpace& constraint_space_;
+ Vector<NGPositionedFloat>* positioned_floats_;
+ Vector<scoped_refptr<NGUnpositionedFloat>>* unpositioned_floats_;
+ NGContainerFragmentBuilder* container_builder_; /* May be nullptr */
+ NGExclusionSpace* exclusion_space_;
+ scoped_refptr<const ComputedStyle> current_style_;
+
+ LazyLineBreakIterator break_iterator_;
+ HarfBuzzShaper shaper_;
+ ShapeResultSpacing<String> spacing_;
+ bool previous_line_had_forced_break_ = false;
+ const Hyphenation* hyphenation_ = nullptr;
+
+ // Cache the result of |ComputeTrailingCollapsibleSpace| to avoid shaping
+ // multiple times.
+ struct TrailingCollapsibleSpace {
+ NGInlineItemResult* item_result;
+ scoped_refptr<const ShapeResult> collapsed_shape_result;
+ };
+ base::Optional<TrailingCollapsibleSpace> trailing_collapsible_space_;
+
+ // Keep track of handled float items. See HandleFloat().
+ unsigned handled_floats_end_item_index_;
+
+ // The current base direction for the bidi algorithm.
+ // This is copied from NGInlineNode, then updated after each forced line break
+ // if 'unicode-bidi: plaintext'.
+ TextDirection base_direction_;
};
} // namespace blink
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 30c5402b812..1a6baf2a451 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
@@ -48,13 +48,16 @@ class NGLineBreakerTest : public NGBaseLayoutAlgorithmTest {
Vector<NGInlineItemResults> lines;
NGExclusionSpace exclusion_space;
NGLineLayoutOpportunity line_opportunity(available_width);
- NGLineInfo line_info;
while (!break_token || !break_token->IsFinished()) {
+ NGLineInfo line_info;
NGLineBreaker line_breaker(node, NGLineBreakerMode::kContent, *space,
&positioned_floats, &unpositioned_floats,
/* container_builder */ nullptr,
- &exclusion_space, 0u, break_token.get());
- if (!line_breaker.NextLine(line_opportunity, &line_info))
+ &exclusion_space, 0u, line_opportunity,
+ break_token.get());
+ line_breaker.NextLine(&line_info);
+
+ if (line_info.Results().IsEmpty())
break;
break_token = line_breaker.CreateBreakToken(line_info, nullptr);
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_height_metrics.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_height_metrics.cc
index b83d812d685..7b773abd116 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_height_metrics.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_height_metrics.cc
@@ -25,8 +25,10 @@ NGLineHeightMetrics::NGLineHeightMetrics(const FontMetrics& font_metrics,
void NGLineHeightMetrics::Initialize(const FontMetrics& font_metrics,
FontBaseline baseline_type) {
- ascent = font_metrics.FixedAscent(baseline_type);
- descent = font_metrics.FixedDescent(baseline_type);
+ // TODO(kojii): In future, we'd like to use LayoutUnit metrics to support
+ // sub-CSS-pixel layout.
+ ascent = LayoutUnit(font_metrics.Ascent(baseline_type));
+ descent = LayoutUnit(font_metrics.Descent(baseline_type));
}
void NGLineHeightMetrics::AddLeading(LayoutUnit line_height) {
@@ -49,4 +51,12 @@ void NGLineHeightMetrics::Unite(const NGLineHeightMetrics& other) {
descent = std::max(descent, other.descent);
}
+void NGLineHeightMetrics::operator+=(const NGLineHeightMetrics& other) {
+ DCHECK(ascent != LayoutUnit::Min() && descent != LayoutUnit::Min());
+ DCHECK(other.ascent != LayoutUnit::Min() &&
+ other.descent != LayoutUnit::Min());
+ ascent += other.ascent;
+ descent += other.descent;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_height_metrics.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_height_metrics.h
index 978c170044e..e5ef21b8580 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_height_metrics.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_height_metrics.h
@@ -33,6 +33,13 @@ struct NGLineHeightMetrics {
bool IsEmpty() const { return ascent == LayoutUnit::Min(); }
+ bool operator==(const NGLineHeightMetrics& other) const {
+ return ascent == other.ascent && descent == other.descent;
+ }
+ bool operator!=(const NGLineHeightMetrics& other) const {
+ return !operator==(other);
+ }
+
// Add the leading. Half the leading is added to ascent and descent each.
// https://drafts.csswg.org/css2/visudet.html#leading
void AddLeading(LayoutUnit line_height);
@@ -43,6 +50,8 @@ struct NGLineHeightMetrics {
// Unite a metrics for an inline box to a metrics for a line box.
void Unite(const NGLineHeightMetrics&);
+ void operator+=(const NGLineHeightMetrics&);
+
// Ascent and descent of glyphs, or synthesized for replaced elements.
// Then united to compute 'text-top' and 'text-bottom' of line boxes.
LayoutUnit ascent;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_truncator.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_truncator.cc
index ae76600c718..919cb689b26 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_truncator.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_line_truncator.cc
@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_text_fragment_builder.h"
#include "third_party/blink/renderer/platform/fonts/font_baseline.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h"
namespace blink {
@@ -54,7 +54,7 @@ LayoutUnit NGLineTruncator::TruncateLine(
font_data && font_data->GlyphForCharacter(kHorizontalEllipsisCharacter)
? String(&kHorizontalEllipsisCharacter, 1)
: String(u"...");
- HarfBuzzShaper shaper(ellipsis_text.Characters16(), ellipsis_text.length());
+ HarfBuzzShaper shaper(ellipsis_text);
scoped_refptr<ShapeResult> ellipsis_shape_result =
shaper.Shape(&font, line_direction_);
LayoutUnit ellipsis_width = ellipsis_shape_result->SnappedWidth();
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc
index e341ddffdae..3187df368dd 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc
@@ -5,48 +5,17 @@
#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_inline_break_token.h"
-#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_relative_utils.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
-namespace {
-
-static const NGPhysicalFragment* LastLogicalLeafExceptLinebreakInternal(
- const NGPhysicalFragment& runner,
- TextDirection direction) {
- if (runner.IsText()) {
- if (ToNGPhysicalTextFragment(runner).IsLineBreak())
- return nullptr;
- return &runner;
- }
- if (!runner.IsContainer() || runner.IsBlockLayoutRoot())
- return &runner;
- const auto& children = ToNGPhysicalContainerFragment(runner).Children();
- for (size_t i = 0; i < children.size(); i++) {
- // TODO(xiaochengh): This isn't correct for mixed Bidi. Fix it. Besides, we
- // should compute and store it during layout.
- // We want a logical last child in a line.
- const size_t index =
- direction == TextDirection::kLtr ? (children.size() - 1 - i) : i;
- const NGPhysicalFragment* child = children[index].get();
- DCHECK(child);
- if (const NGPhysicalFragment* candidate =
- LastLogicalLeafExceptLinebreakInternal(*child, direction))
- return candidate;
- }
- return nullptr;
-}
-
-} // namespace
-
NGPhysicalLineBoxFragment::NGPhysicalLineBoxFragment(
const ComputedStyle& style,
NGStyleVariant style_variant,
NGPhysicalSize size,
Vector<scoped_refptr<NGPhysicalFragment>>& children,
- const NGPhysicalOffsetRect& contents_visual_rect,
- const NGPhysicalOffsetRect& scrollable_overflow,
+ const NGPhysicalOffsetRect& contents_ink_overflow,
const NGLineHeightMetrics& metrics,
TextDirection base_direction,
scoped_refptr<NGBreakToken> break_token)
@@ -57,22 +26,43 @@ NGPhysicalLineBoxFragment::NGPhysicalLineBoxFragment(
kFragmentLineBox,
0,
children,
- contents_visual_rect,
+ contents_ink_overflow,
std::move(break_token)),
- scrollable_overflow_(scrollable_overflow),
metrics_(metrics) {
base_direction_ = static_cast<unsigned>(base_direction);
}
-LayoutUnit NGPhysicalLineBoxFragment::BaselinePosition(FontBaseline) const {
+NGLineHeightMetrics NGPhysicalLineBoxFragment::BaselineMetrics(
+ FontBaseline) const {
// TODO(kojii): Computing other baseline types than the used one is not
// implemented yet.
// TODO(kojii): We might need locale/script to look up OpenType BASE table.
- return metrics_.ascent;
+ return metrics_;
}
-NGPhysicalOffsetRect NGPhysicalLineBoxFragment::VisualRectWithContents() const {
- return ContentsVisualRect();
+NGPhysicalOffsetRect NGPhysicalLineBoxFragment::InkOverflow() const {
+ return ContentsInkOverflow();
+}
+
+NGPhysicalOffsetRect NGPhysicalLineBoxFragment::ScrollableOverflow(
+ const ComputedStyle* container_style,
+ NGPhysicalSize container_physical_size) const {
+ WritingMode container_writing_mode = container_style->GetWritingMode();
+ TextDirection container_direction = container_style->Direction();
+ NGPhysicalOffsetRect overflow({}, Size());
+ for (const auto& child : Children()) {
+ NGPhysicalOffsetRect child_scroll_overflow = child->ScrollableOverflow();
+ child_scroll_overflow.offset += child->Offset();
+ // If child has the same style as parent, parent will compute relative
+ // offset.
+ if (&child->Style() != container_style) {
+ child_scroll_overflow.offset +=
+ ComputeRelativeOffset(child->Style(), container_writing_mode,
+ container_direction, container_physical_size);
+ }
+ overflow.Unite(child_scroll_overflow);
+ }
+ return overflow;
}
const NGPhysicalFragment* NGPhysicalLineBoxFragment::FirstLogicalLeaf() const {
@@ -115,13 +105,6 @@ const NGPhysicalFragment* NGPhysicalLineBoxFragment::LastLogicalLeaf() const {
return runner;
}
-const NGPhysicalFragment*
-NGPhysicalLineBoxFragment::LastLogicalLeafIgnoringLineBreak() const {
- if (Children().IsEmpty())
- return nullptr;
- return LastLogicalLeafExceptLinebreakInternal(*this, this->BaseDirection());
-}
-
bool NGPhysicalLineBoxFragment::HasSoftWrapToNextLine() const {
DCHECK(BreakToken());
DCHECK(BreakToken()->IsInlineType());
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h
index b92b910d2b3..7ca454dcb6b 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h
@@ -20,8 +20,7 @@ class CORE_EXPORT NGPhysicalLineBoxFragment final
NGStyleVariant style_variant,
NGPhysicalSize size,
Vector<scoped_refptr<NGPhysicalFragment>>& children,
- const NGPhysicalOffsetRect& contents_visual_rect,
- const NGPhysicalOffsetRect& scrollable_overflow,
+ const NGPhysicalOffsetRect& contents_ink_overflow,
const NGLineHeightMetrics&,
TextDirection base_direction,
scoped_refptr<NGBreakToken> break_token = nullptr);
@@ -36,23 +35,23 @@ class CORE_EXPORT NGPhysicalLineBoxFragment final
}
// Compute baseline for the specified baseline type.
- LayoutUnit BaselinePosition(FontBaseline) const;
+ NGLineHeightMetrics BaselineMetrics(FontBaseline) const;
- // VisualRect of itself including contents, in the local coordinate.
- NGPhysicalOffsetRect VisualRectWithContents() const;
+ // Ink overflow of itself including contents, in the local coordinate.
+ NGPhysicalOffsetRect InkOverflow() const;
// Scrollable overflow. including contents, in the local coordinate.
- NGPhysicalOffsetRect ScrollableOverflow() const {
- return scrollable_overflow_;
- }
+ // ScrollableOverflow is not precomputed/cached because it cannot be computed
+ // when LineBox is generated because it needs container dimensions to
+ // resolve relative position of its children.
+ NGPhysicalOffsetRect ScrollableOverflow(
+ const ComputedStyle* container_style,
+ NGPhysicalSize container_physical_size) const;
// Returns the first/last leaf fragment in the line in logical order. Returns
// nullptr if the line box is empty.
const NGPhysicalFragment* FirstLogicalLeaf() const;
const NGPhysicalFragment* LastLogicalLeaf() const;
- // Returns the last leaf fragment in the line in logical order except line
- // break. Returns nullptr if such fragment doesn't exist.
- const NGPhysicalFragment* LastLogicalLeafIgnoringLineBreak() const;
// Whether the content soft-wraps to the next line.
bool HasSoftWrapToNextLine() const;
@@ -60,12 +59,11 @@ class CORE_EXPORT NGPhysicalLineBoxFragment final
scoped_refptr<NGPhysicalFragment> CloneWithoutOffset() const {
Vector<scoped_refptr<NGPhysicalFragment>> children_copy(children_);
return base::AdoptRef(new NGPhysicalLineBoxFragment(
- Style(), StyleVariant(), size_, children_copy, contents_visual_rect_,
- scrollable_overflow_, metrics_, BaseDirection(), break_token_));
+ Style(), StyleVariant(), size_, children_copy, contents_ink_overflow_,
+ metrics_, BaseDirection(), break_token_));
}
private:
- NGPhysicalOffsetRect scrollable_overflow_;
NGLineHeightMetrics metrics_;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment_test.cc
index 331fb87d70b..cd44fd8ea05 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment_test.cc
@@ -59,7 +59,6 @@ TEST_F(NGPhysicalLineBoxFragmentTest, FirstLastLogicalLeafInSimpleText) {
"</div>");
EXPECT_TEXT_FRAGMENT("foo", GetLineBox()->FirstLogicalLeaf());
EXPECT_TEXT_FRAGMENT("bar", GetLineBox()->LastLogicalLeaf());
- EXPECT_TEXT_FRAGMENT("bar", GetLineBox()->LastLogicalLeafIgnoringLineBreak());
}
TEST_F(NGPhysicalLineBoxFragmentTest, FirstLastLogicalLeafInRtlText) {
@@ -70,7 +69,6 @@ TEST_F(NGPhysicalLineBoxFragmentTest, FirstLastLogicalLeafInRtlText) {
"</bdo>");
EXPECT_TEXT_FRAGMENT("foo", GetLineBox()->FirstLogicalLeaf());
EXPECT_TEXT_FRAGMENT("bar", GetLineBox()->LastLogicalLeaf());
- EXPECT_TEXT_FRAGMENT("bar", GetLineBox()->LastLogicalLeafIgnoringLineBreak());
}
TEST_F(NGPhysicalLineBoxFragmentTest,
@@ -83,7 +81,6 @@ TEST_F(NGPhysicalLineBoxFragmentTest,
"</div>");
EXPECT_TEXT_FRAGMENT("f", GetLineBox()->FirstLogicalLeaf());
EXPECT_TEXT_FRAGMENT("r", GetLineBox()->LastLogicalLeaf());
- EXPECT_TEXT_FRAGMENT("r", GetLineBox()->LastLogicalLeafIgnoringLineBreak());
}
TEST_F(NGPhysicalLineBoxFragmentTest, FirstLastLogicalLeafWithInlineBlock) {
@@ -95,26 +92,12 @@ TEST_F(NGPhysicalLineBoxFragmentTest, FirstLastLogicalLeafWithInlineBlock) {
"</div>");
EXPECT_BOX_FRAGMENT("foo", GetLineBox()->FirstLogicalLeaf());
EXPECT_BOX_FRAGMENT("baz", GetLineBox()->LastLogicalLeaf());
- EXPECT_BOX_FRAGMENT("baz", GetLineBox()->LastLogicalLeafIgnoringLineBreak());
}
TEST_F(NGPhysicalLineBoxFragmentTest, FirstLastLogicalLeafWithImages) {
SetBodyInnerHTML("<div id=root><img id=img1>foo<img id=img2></div>");
EXPECT_BOX_FRAGMENT("img1", GetLineBox()->FirstLogicalLeaf());
EXPECT_BOX_FRAGMENT("img2", GetLineBox()->LastLogicalLeaf());
- EXPECT_BOX_FRAGMENT("img2", GetLineBox()->LastLogicalLeafIgnoringLineBreak());
-}
-
-TEST_F(NGPhysicalLineBoxFragmentTest, LastLogicalLeafSoftWrap) {
- SetBodyInnerHTML("<div id=root style='width: 2em'>foo bar</div>");
- EXPECT_TEXT_FRAGMENT("foo", GetLineBox()->LastLogicalLeaf());
- EXPECT_TEXT_FRAGMENT("foo", GetLineBox()->LastLogicalLeafIgnoringLineBreak());
-}
-
-TEST_F(NGPhysicalLineBoxFragmentTest, LastLogicalLeafHardWrap) {
- SetBodyInnerHTML("<div id=root>foo<br>bar</div>");
- EXPECT_TEXT_FRAGMENT("\n", GetLineBox()->LastLogicalLeaf());
- EXPECT_TEXT_FRAGMENT("foo", GetLineBox()->LastLogicalLeafIgnoringLineBreak());
}
} // namespace blink
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 d75f591cc0f..7c705969eb7 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
@@ -58,24 +58,31 @@ LayoutUnit NGPhysicalTextFragment::InlinePositionForOffset(
AdjustMidCluster::kToEnd);
}
-NGPhysicalOffsetRect NGPhysicalTextFragment::LocalRect(
- unsigned start_offset,
- unsigned end_offset) const {
+std::pair<LayoutUnit, LayoutUnit>
+NGPhysicalTextFragment::LineLeftAndRightForOffsets(unsigned start_offset,
+ unsigned end_offset) const {
DCHECK_LE(start_offset, end_offset);
DCHECK_GE(start_offset, start_offset_);
DCHECK_LE(end_offset, end_offset_);
- LayoutUnit start_position = InlinePositionForOffset(
+ const LayoutUnit start_position = InlinePositionForOffset(
start_offset, LayoutUnit::FromFloatFloor, AdjustMidCluster::kToStart);
- LayoutUnit end_position = InlinePositionForOffset(
+ const LayoutUnit end_position = InlinePositionForOffset(
end_offset, LayoutUnit::FromFloatCeil, AdjustMidCluster::kToEnd);
// Swap positions if RTL.
- if (UNLIKELY(start_position > end_position))
- std::swap(start_position, end_position);
-
- LayoutUnit inline_size = end_position - start_position;
+ return (UNLIKELY(start_position > end_position))
+ ? std::make_pair(end_position, start_position)
+ : std::make_pair(start_position, end_position);
+}
+NGPhysicalOffsetRect NGPhysicalTextFragment::LocalRect(
+ unsigned start_offset,
+ unsigned end_offset) const {
+ LayoutUnit start_position, end_position;
+ std::tie(start_position, end_position) =
+ LineLeftAndRightForOffsets(start_offset, end_offset);
+ const LayoutUnit inline_size = end_position - start_position;
switch (LineOrientation()) {
case NGLineOrientation::kHorizontal:
return {{start_position, LayoutUnit()}, {inline_size, Size().height}};
@@ -89,23 +96,24 @@ NGPhysicalOffsetRect NGPhysicalTextFragment::LocalRect(
return {};
}
-NGPhysicalOffsetRect NGPhysicalTextFragment::SelfVisualRect() const {
+NGPhysicalOffsetRect NGPhysicalTextFragment::SelfInkOverflow() const {
if (UNLIKELY(!shape_result_))
return LocalRect();
// Glyph bounds is in logical coordinate, origin at the alphabetic baseline.
- LayoutRect visual_rect = EnclosingLayoutRect(shape_result_->Bounds());
+ LayoutRect ink_overflow = EnclosingLayoutRect(shape_result_->Bounds());
// Make the origin at the logical top of this fragment.
const ComputedStyle& style = Style();
const Font& font = style.GetFont();
if (const SimpleFontData* font_data = font.PrimaryFont()) {
- visual_rect.SetY(visual_rect.Y() + font_data->GetFontMetrics().FixedAscent(
- kAlphabeticBaseline));
+ ink_overflow.SetY(
+ ink_overflow.Y() +
+ font_data->GetFontMetrics().FixedAscent(kAlphabeticBaseline));
}
if (float stroke_width = style.TextStrokeWidth()) {
- visual_rect.Inflate(LayoutUnit::FromFloatCeil(stroke_width / 2.0f));
+ ink_overflow.Inflate(LayoutUnit::FromFloatCeil(stroke_width / 2.0f));
}
if (style.GetTextEmphasisMark() != TextEmphasisMark::kNone) {
@@ -113,13 +121,13 @@ NGPhysicalOffsetRect NGPhysicalTextFragment::SelfVisualRect() const {
LayoutUnit(font.EmphasisMarkHeight(style.TextEmphasisMarkString()));
DCHECK_GT(emphasis_mark_height, LayoutUnit());
if (style.GetTextEmphasisLineLogicalSide() == LineLogicalSide::kOver) {
- visual_rect.ShiftYEdgeTo(
- std::min(visual_rect.Y(), -emphasis_mark_height));
+ ink_overflow.ShiftYEdgeTo(
+ std::min(ink_overflow.Y(), -emphasis_mark_height));
} else {
LayoutUnit logical_height =
style.IsHorizontalWritingMode() ? Size().height : Size().width;
- visual_rect.ShiftMaxYEdgeTo(
- std::max(visual_rect.MaxY(), logical_height + emphasis_mark_height));
+ ink_overflow.ShiftMaxYEdgeTo(
+ std::max(ink_overflow.MaxY(), logical_height + emphasis_mark_height));
}
}
@@ -129,16 +137,16 @@ NGPhysicalOffsetRect NGPhysicalTextFragment::SelfVisualRect() const {
LayoutRectOutsets(text_shadow->RectOutsetsIncludingOriginal()),
style.GetWritingMode());
text_shadow_logical_outsets.ClampNegativeToZero();
- visual_rect.Expand(text_shadow_logical_outsets);
+ ink_overflow.Expand(text_shadow_logical_outsets);
}
- visual_rect = LayoutRect(EnclosingIntRect(visual_rect));
+ ink_overflow = LayoutRect(EnclosingIntRect(ink_overflow));
// Uniting the frame rect ensures that non-ink spaces such side bearings, or
// even space characters, are included in the visual rect for decorations.
- NGPhysicalOffsetRect local_visual_rect = ConvertToLocal(visual_rect);
- local_visual_rect.Unite(LocalRect());
- return local_visual_rect;
+ NGPhysicalOffsetRect local_ink_overflow = ConvertToLocal(ink_overflow);
+ local_ink_overflow.Unite(LocalRect());
+ return local_ink_overflow;
}
scoped_refptr<NGPhysicalFragment> NGPhysicalTextFragment::TrimText(
@@ -184,9 +192,9 @@ unsigned NGPhysicalTextFragment::TextOffsetForPoint(
DCHECK(TextShapeResult());
const LayoutUnit& point_in_line_direction =
Style().IsHorizontalWritingMode() ? point.left : point.top;
- const bool include_partial_glyphs = true;
return TextShapeResult()->OffsetForPosition(point_in_line_direction.ToFloat(),
- include_partial_glyphs) +
+ IncludePartialGlyphs,
+ BreakGlyphs) +
StartOffset();
}
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 f6921d10546..19758ce7666 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
@@ -41,11 +41,18 @@ enum class NGLineOrientation {
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 IsAnonymousText() for them.
+ kGeneratedText,
// When adding new values, make sure the bit size of |sub_type_| is large
// enough to store.
};
@@ -77,6 +84,8 @@ class CORE_EXPORT NGPhysicalTextFragment final : public NGPhysicalFragment {
}
NGTextType TextType() const { return static_cast<NGTextType>(sub_type_); }
+ // True if this is a generated text.
+ bool IsGeneratedText() const { return TextType() == kGeneratedText; }
// True if this is a forced line break.
bool IsLineBreak() const { return TextType() == kForcedLineBreak; }
// True if this is not for painting; i.e., a forced line break, a tabulation,
@@ -114,7 +123,7 @@ class CORE_EXPORT NGPhysicalTextFragment final : public NGPhysicalFragment {
// The visual bounding box that includes glpyh bounding box and CSS
// properties, in local coordinates.
- NGPhysicalOffsetRect SelfVisualRect() const;
+ NGPhysicalOffsetRect SelfInkOverflow() const;
NGTextEndEffect EndEffect() const {
return static_cast<NGTextEndEffect>(end_effect_);
@@ -142,6 +151,13 @@ class CORE_EXPORT NGPhysicalTextFragment final : public NGPhysicalFragment {
UBiDiLevel BidiLevel() const override;
TextDirection ResolvedDirection() const override;
+ // Compute line-relative coordinates for given offsets, this is not
+ // flow-relative:
+ // https://drafts.csswg.org/css-writing-modes-3/#line-directions
+ std::pair<LayoutUnit, LayoutUnit> LineLeftAndRightForOffsets(
+ unsigned start_offset,
+ unsigned end_offset) const;
+
private:
LayoutUnit InlinePositionForOffset(unsigned offset,
LayoutUnit (*round)(float),
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 48cc659c404..8962d687d27 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
@@ -35,6 +35,10 @@ class NGPhysicalTextFragmentTest : public NGLayoutTest {
}
return result;
}
+
+ static std::string GetText(const NGPhysicalTextFragment& fragment) {
+ return fragment.Text().ToString().Utf8().data();
+ }
};
TEST_F(NGPhysicalTextFragmentTest, LocalRect) {
@@ -155,6 +159,32 @@ TEST_F(NGPhysicalTextFragmentTest, BeforeAndAfterAreAnonymousText) {
EXPECT_TRUE(after.IsAnonymousText());
}
+TEST_F(NGPhysicalTextFragmentTest, Ellipsis) {
+ LoadAhem();
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #sample {
+ font: 10px/1 Ahem;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ width: 4ch;
+ }
+ </style>
+ <p id="sample">abcdef</p>
+ )HTML");
+ auto text_fragments = CollectTextFragmentsInContainer("sample");
+ ASSERT_EQ(2u, text_fragments.size());
+
+ const NGPhysicalTextFragment& abcdef = *text_fragments[0];
+ const NGPhysicalTextFragment& ellipsis = *text_fragments[1];
+ EXPECT_EQ(NGPhysicalTextFragment::kNormalText, abcdef.TextType());
+ EXPECT_FALSE(abcdef.IsGeneratedText());
+ EXPECT_EQ(u8"abc", GetText(abcdef));
+ EXPECT_EQ(NGPhysicalTextFragment::kGeneratedText, ellipsis.TextType());
+ EXPECT_TRUE(ellipsis.IsGeneratedText());
+ EXPECT_EQ(u8"\u2026", GetText(ellipsis));
+}
+
TEST_F(NGPhysicalTextFragmentTest, ListMarkerIsAnonymousText) {
SetBodyInnerHTML(
"<ol style='list-style-position:inside'>"
@@ -170,6 +200,37 @@ TEST_F(NGPhysicalTextFragmentTest, ListMarkerIsAnonymousText) {
EXPECT_FALSE(text.IsAnonymousText());
}
+TEST_F(NGPhysicalTextFragmentTest, SoftHyphen) {
+ LoadAhem();
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #sample {
+ font: 10px/1 Ahem;
+ width: 3ch;
+ }
+ </style>
+ <p id="sample">abc&shy;def</p>
+ )HTML");
+ auto text_fragments = CollectTextFragmentsInContainer("sample");
+ ASSERT_EQ(3u, text_fragments.size());
+
+ 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_FALSE(abc.IsGeneratedText());
+ // Note: ShapeResult::RunInfo.width_ == 0 for U+00AD
+ EXPECT_EQ(u8"abc\u00AD", GetText(abc));
+ EXPECT_EQ(NGPhysicalTextFragment::kGeneratedText, shy.TextType());
+ EXPECT_TRUE(shy.IsGeneratedText());
+ // Note: |ComputedStyle::HypenString()| returns "-" or U+2010 based on
+ // glyph availability.
+ if (GetText(shy) != "-")
+ EXPECT_EQ(u8"\u2010", GetText(shy));
+ EXPECT_EQ(NGPhysicalTextFragment::kNormalText, def.TextType());
+ EXPECT_FALSE(def.IsGeneratedText());
+}
+
TEST_F(NGPhysicalTextFragmentTest, QuotationMarksAreAnonymousText) {
SetBodyInnerHTML("<div id=div><q>text</q></div>");
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 9ee319a8d3c..c1cbefd220e 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
@@ -40,6 +40,8 @@ void NGTextFragmentBuilder::SetItem(
const NGInlineItemsData& items_data,
NGInlineItemResult* item_result,
LayoutUnit line_height) {
+ DCHECK_NE(text_type, NGPhysicalTextFragment::kGeneratedText)
+ << "Please use SetText() instead.";
DCHECK(item_result);
DCHECK(item_result->item->Style());
@@ -65,7 +67,7 @@ void NGTextFragmentBuilder::SetText(
DCHECK(style);
DCHECK(shape_result);
- text_type_ = NGPhysicalTextFragment::kNormalText;
+ text_type_ = NGPhysicalTextFragment::kGeneratedText;
text_ = text;
item_index_ = std::numeric_limits<unsigned>::max();
start_offset_ = shape_result->StartIndexForResult();
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 68efb30de15..df788efc4cb 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,6 +29,8 @@ class CORE_EXPORT NGTextFragmentBuilder final : public NGBaseFragmentBuilder {
const NGInlineItemsData&,
NGInlineItemResult*,
LayoutUnit line_height);
+
+ // Set text for generated text, e.g. hyphen and ellipsis.
void SetText(LayoutObject*,
const String& text,
scoped_refptr<const ComputedStyle>,
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.cc b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.cc
index 6b81fd15240..6100ce6b12f 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.cc
@@ -5,9 +5,11 @@
#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_analyzer.h"
+#include "third_party/blink/renderer/core/layout/min_max_size.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_data.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_fragment_builder.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"
@@ -26,9 +28,40 @@ bool LayoutNGBlockFlow::IsOfType(LayoutObjectType type) const {
LayoutNGMixin<LayoutBlockFlow>::IsOfType(type);
}
+void LayoutNGBlockFlow::ComputeIntrinsicLogicalWidths(
+ LayoutUnit& min_logical_width,
+ LayoutUnit& max_logical_width) const {
+ NGBlockNode node(const_cast<LayoutNGBlockFlow*>(this));
+ if (!node.CanUseNewLayout()) {
+ LayoutBlockFlow::ComputeIntrinsicLogicalWidths(min_logical_width,
+ max_logical_width);
+ return;
+ }
+ MinMaxSize sizes =
+ node.ComputeMinMaxSize(StyleRef().GetWritingMode(), MinMaxSizeInput());
+ // ComputeMinMaxSize returns a border-box size. This function needs to return
+ // content-box plus scrollbar.
+ // We can't just call BorderAndPaddingLogicalWidth() here because that
+ // handles percentages differently from NG intrinsic sizing.
+ scoped_refptr<NGConstraintSpace> space =
+ NGConstraintSpaceBuilder(node.Style().GetWritingMode(),
+ node.InitialContainingBlockSize())
+ .ToConstraintSpace(node.Style().GetWritingMode());
+ sizes -=
+ (ComputeBorders(*space, StyleRef()) + ComputePadding(*space, StyleRef()))
+ .InlineSum();
+ min_logical_width = sizes.min_size;
+ max_logical_width = sizes.max_size;
+}
+
void LayoutNGBlockFlow::UpdateBlockLayout(bool relayout_children) {
LayoutAnalyzer::BlockScope analyzer(*this);
+ // This block is an entry-point from the legacy engine to LayoutNG. This means
+ // that we need to be at a formatting context boundary, since NG and legacy
+ // don't cooperate on e.g. margin collapsing.
+ DCHECK(CreatesNewFormattingContext());
+
if (IsOutOfFlowPositioned()) {
UpdateOutOfFlowBlockLayout();
return;
@@ -202,11 +235,15 @@ void LayoutNGBlockFlow::UpdateOutOfFlowBlockLayout() {
if (css_container->IsBox())
scrollbar_sizes =
NGBlockNode(ToLayoutBox(css_container)).GetScrollbarSizes();
+ // We really only want to lay out ourselves here, so we pass |this| to
+ // Run(). Otherwise, NGOutOfFlowLayoutPart may also lay out other objects
+ // it discovers that are part of the same containing block, but those
+ // should get laid out by the actual containing block.
NGOutOfFlowLayoutPart(&container_builder,
css_container->CanContainAbsolutePositionObjects(),
css_container->CanContainFixedPositionObjects(),
scrollbar_sizes, *constraint_space, *container_style)
- .Run(/* update_legacy */ false);
+ .Run(/* only_layout */ this);
scoped_refptr<NGLayoutResult> result = container_builder.ToBoxFragment();
// These are the unpositioned OOF descendants of the current OOF block.
for (NGOutOfFlowPositionedDescendant descendant :
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h
index f36533ea284..4f552c174ab 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h
@@ -24,6 +24,11 @@ class CORE_EXPORT LayoutNGBlockFlow : public LayoutNGMixin<LayoutBlockFlow> {
protected:
bool IsOfType(LayoutObjectType) const override;
+ protected:
+ void ComputeIntrinsicLogicalWidths(
+ LayoutUnit& min_logical_width,
+ LayoutUnit& max_logical_width) const override;
+
private:
void UpdateOutOfFlowBlockLayout();
};
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/layout_ng_flexible_box.cc
index 5db1077417f..0d78f32b213 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_flexible_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/layout_ng_flexible_box.cc
@@ -19,6 +19,9 @@ LayoutNGFlexibleBox::LayoutNGFlexibleBox(Element* element)
void LayoutNGFlexibleBox::UpdateBlockLayout(bool relayout_children) {
LayoutAnalyzer::BlockScope analyzer(*this);
+ // TODO(dgrogan): Reuse logic from LayoutNGBlockFlow's
+ // UpdateOutOfFlowBlockLayout when this flexbox is out of flow.
+
scoped_refptr<NGConstraintSpace> constraint_space =
NGConstraintSpace::CreateFromLayoutObject(*this);
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 19c0da2d6fd..6351676134d 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
@@ -13,12 +13,15 @@
#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/inline/ng_inline_node_data.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h"
#include "third_party/blink/renderer/core/layout/ng/ng_layout_utils.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_relative_utils.h"
#include "third_party/blink/renderer/core/page/scrolling/root_scroller_util.h"
+#include "third_party/blink/renderer/core/paint/adjust_paint_offset_scope.h"
#include "third_party/blink/renderer/core/paint/ng/ng_block_flow_painter.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
@@ -72,44 +75,17 @@ void LayoutNGMixin<Base>::AddOverflowFromChildren() {
// |ComputeOverflow()| calls this, which is called from
// |CopyFragmentDataToLayoutBox()| and |RecalcOverflowAfterStyleChange()|.
// Add overflow from the last layout cycle.
- if (Base::ChildrenInline()) {
- if (const NGPhysicalBoxFragment* physical_fragment = CurrentFragment()) {
- // LayoutOverflow is only computed if overflow is not hidden
- if (physical_fragment->Style().OverflowX() != EOverflow::kHidden ||
- physical_fragment->Style().OverflowY() != EOverflow::kHidden) {
- // inline-end LayoutOverflow padding spec is still undecided:
- // https://github.com/w3c/csswg-drafts/issues/129
- // For backwards compatibility, if container clips overflow,
- // padding is added to the inline-end for inline children.
- base::Optional<NGPhysicalBoxStrut> padding_strut;
- if (Base::HasOverflowClip()) {
- padding_strut =
- NGBoxStrut(LayoutUnit(), Base::PaddingEnd(), LayoutUnit(),
- LayoutUnit())
- .ConvertToPhysical(Base::StyleRef().GetWritingMode(),
- Base::StyleRef().Direction());
- }
- NGPhysicalOffsetRect children_overflow;
- for (const auto& child : physical_fragment->Children()) {
- NGPhysicalOffsetRect child_scrollable_overflow =
- child->ScrollableOverflow();
- child_scrollable_overflow.offset += child->Offset();
- if (child->IsLineBox() && padding_strut) {
- child_scrollable_overflow.Expand(*padding_strut);
- }
- children_overflow.Unite(child_scrollable_overflow);
- }
- Base::AddLayoutOverflow(children_overflow.ToLayoutFlippedRect(
- physical_fragment->Style(), physical_fragment->Size()));
- }
+ if (const NGPhysicalBoxFragment* physical_fragment = CurrentFragment()) {
+ AddScrollingOverflowFromChildren();
+ if (Base::ChildrenInline()) {
Base::AddSelfVisualOverflow(
- physical_fragment->SelfVisualRect().ToLayoutFlippedRect(
+ physical_fragment->SelfInkOverflow().ToLayoutFlippedRect(
physical_fragment->Style(), physical_fragment->Size()));
// TODO(kojii): If |RecalcOverflowAfterStyleChange()|, we need to
// re-compute glyph bounding box. How to detect it and how to re-compute
// is TBD.
Base::AddContentsVisualOverflow(
- physical_fragment->ContentsVisualRect().ToLayoutFlippedRect(
+ physical_fragment->ContentsInkOverflow().ToLayoutFlippedRect(
physical_fragment->Style(), physical_fragment->Size()));
// TODO(kojii): The above code computes visual overflow only, we fallback
// to LayoutBlock for AddLayoutOverflow() for now. It doesn't compute
@@ -120,6 +96,74 @@ void LayoutNGMixin<Base>::AddOverflowFromChildren() {
}
template <typename Base>
+void LayoutNGMixin<Base>::AddScrollingOverflowFromChildren() {
+ bool children_inline = Base::ChildrenInline();
+
+ const NGPhysicalBoxFragment* physical_fragment = CurrentFragment();
+ DCHECK(physical_fragment);
+ // inline-end LayoutOverflow padding spec is still undecided:
+ // https://github.com/w3c/csswg-drafts/issues/129
+ // For backwards compatibility, if container clips overflow,
+ // padding is added to the inline-end for inline children.
+ base::Optional<NGPhysicalBoxStrut> padding_strut;
+ if (Base::HasOverflowClip()) {
+ padding_strut =
+ NGBoxStrut(LayoutUnit(), Base::PaddingEnd(), LayoutUnit(), LayoutUnit())
+ .ConvertToPhysical(Base::StyleRef().GetWritingMode(),
+ Base::StyleRef().Direction());
+ }
+
+ NGPhysicalOffsetRect children_overflow;
+
+ // Only add overflow for fragments NG has not reflected into Legacy.
+ // These fragments are:
+ // - inline fragments,
+ // - out of flow fragments whose css container is inline box.
+ // TODO(layout-dev) Transfroms also need to be applied to compute overflow
+ // correctly. NG is not yet transform-aware. crbug.com/855965
+ if (!physical_fragment->Children().IsEmpty()) {
+ for (const auto& child : physical_fragment->Children()) {
+ NGPhysicalOffsetRect child_scrollable_overflow;
+ if (child->IsOutOfFlowPositioned()) {
+ child_scrollable_overflow = child->ScrollableOverflow();
+ } else if (children_inline && child->IsLineBox()) {
+ DCHECK(child->IsLineBox());
+ child_scrollable_overflow =
+ ToNGPhysicalLineBoxFragment(*child).ScrollableOverflow(
+ Base::Style(), physical_fragment->Size());
+ if (padding_strut)
+ child_scrollable_overflow.Expand(*padding_strut);
+ } else {
+ continue;
+ }
+ child_scrollable_overflow.offset += child->Offset();
+ children_overflow.Unite(child_scrollable_overflow);
+ }
+ }
+
+ // LayoutOverflow takes flipped blocks coordinates, adjust as needed.
+ LayoutRect children_flipped_overflow = children_overflow.ToLayoutFlippedRect(
+ physical_fragment->Style(), physical_fragment->Size());
+ if (physical_fragment->Style().IsFlippedBlocksWritingMode()) {
+ // Legacy overflow coordinate system for flipped blocks is broken.
+ // It coordinates are "flipped blocks pretending scrollbar does
+ // not exist. This is the scrollbar adjustment.
+ // For details, see comments in LayoutBox::NoOverflowRect
+ LayoutObject* layout_object = physical_fragment->GetLayoutObject();
+ if (layout_object && layout_object->IsBox()) {
+ const LayoutBox* box = ToLayoutBox(layout_object);
+ if (!box->ShouldPlaceBlockDirectionScrollbarOnLogicalLeft()) {
+ LayoutUnit right_scrollbar_width =
+ LayoutUnit(box->VerticalScrollbarWidth());
+ children_flipped_overflow.SetX(children_flipped_overflow.X() -
+ right_scrollbar_width);
+ }
+ }
+ }
+ Base::AddLayoutOverflow(children_flipped_overflow);
+}
+
+template <typename Base>
void LayoutNGMixin<Base>::AddOutlineRects(
Vector<LayoutRect>& rects,
const LayoutPoint& additional_offset,
@@ -248,12 +292,11 @@ void LayoutNGMixin<Base>::InvalidateDisplayItemClients(
}
template <typename Base>
-void LayoutNGMixin<Base>::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const {
+void LayoutNGMixin<Base>::Paint(const PaintInfo& paint_info) const {
if (PaintFragment())
- NGBlockFlowPainter(*this).Paint(paint_info, paint_offset);
+ NGBlockFlowPainter(*this).Paint(paint_info);
else
- LayoutBlockFlow::Paint(paint_info, paint_offset);
+ LayoutBlockFlow::Paint(paint_info);
}
template <typename Base>
@@ -266,28 +309,28 @@ bool LayoutNGMixin<Base>::NodeAtPoint(
return LayoutBlockFlow::NodeAtPoint(result, location_in_container,
accumulated_offset, action);
}
- LayoutPoint offset = PaintFragment()->PhysicalFragment().IsPlacedByLayoutNG()
- ? PaintFragment()->Offset().ToLayoutPoint()
- : Base::Location();
- LayoutPoint adjusted_location = accumulated_offset + offset;
+ // In LayoutBox::NodeAtPoint() and subclass overrides, it is guaranteed that
+ // |accumulated_offset + Location()| equals the physical offset of the current
+ // LayoutBox in the paint layer, regardless of writing mode or whether the box
+ // was placed by NG or legacy.
+ const LayoutPoint physical_offset = accumulated_offset + Base::Location();
if (!RootScrollerUtil::IsEffective(*this)) {
// Check if we need to do anything at all.
// If we have clipping, then we can't have any spillout.
LayoutRect overflow_box = Base::HasOverflowClip()
? Base::BorderBoxRect()
: Base::VisualOverflowRect();
- overflow_box.MoveBy(adjusted_location);
+ overflow_box.MoveBy(physical_offset);
if (!location_in_container.Intersects(overflow_box))
return false;
}
if (Base::IsInSelfHitTestingPhase(action) && Base::HasOverflowClip() &&
Base::HitTestOverflowControl(result, location_in_container,
- adjusted_location))
+ physical_offset))
return true;
return NGBlockFlowPainter(*this).NodeAtPoint(result, location_in_container,
- accumulated_offset,
- accumulated_offset, action);
+ physical_offset, action);
}
template <typename Base>
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 3f7511fd9b9..4ffae304592 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
@@ -25,7 +25,7 @@ struct NGInlineNodeData;
// LayoutBlockFlow.
template <typename Base>
-class CORE_TEMPLATE_CLASS_EXPORT LayoutNGMixin : public Base {
+class LayoutNGMixin : public Base {
public:
explicit LayoutNGMixin(Element* element);
~LayoutNGMixin() override;
@@ -42,7 +42,7 @@ class CORE_TEMPLATE_CLASS_EXPORT LayoutNGMixin : public Base {
void InvalidateDisplayItemClients(PaintInvalidationReason) const override;
- void Paint(const PaintInfo&, const LayoutPoint&) const override;
+ void Paint(const PaintInfo&) const override;
bool NodeAtPoint(HitTestResult&,
const HitTestLocation& location_in_container,
@@ -76,6 +76,10 @@ class CORE_TEMPLATE_CLASS_EXPORT LayoutNGMixin : public Base {
void AddOverflowFromChildren() override;
+ private:
+ void AddScrollingOverflowFromChildren();
+
+ protected:
void AddOutlineRects(
Vector<LayoutRect>&,
const LayoutPoint& additional_offset,
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.cc b/chromium/third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.cc
index 6f504c9b9da..88ccb44c29f 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/legacy_layout_tree_walking.cc
@@ -53,6 +53,10 @@ bool IsManagedByLayoutNG(const LayoutObject& object) {
const auto* containing_block = object.ContainingBlock();
if (!containing_block)
return false;
+ return IsLayoutNGContainingBlock(containing_block);
+}
+
+bool IsLayoutNGContainingBlock(const LayoutBlock* containing_block) {
if (containing_block->IsLayoutFlowThread())
containing_block = containing_block->ContainingBlock();
return containing_block && (containing_block->IsLayoutNGMixin() ||
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 ab67358c6c0..79bf10cf631 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
@@ -28,6 +28,11 @@ bool AreNGBlockFlowChildrenInline(const LayoutBlock*);
// LayoutNG engine (i.e. its containing block is a LayoutNG object as well).
bool IsManagedByLayoutNG(const LayoutObject&);
+// Return true if the block is of NG type, or if it's a block invisible to
+// LayoutNG and it has an NG containg block. False if it's hosted by the legacy
+// layout engine.
+bool IsLayoutNGContainingBlock(const LayoutBlock*);
+
} // namespace blink
#endif // LegacyLayoutTreeWalking_h
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc
index f4e79477808..ae9625d9aa3 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc
@@ -63,6 +63,21 @@ void LayoutNGListItem::OrdinalValueChanged() {
}
void LayoutNGListItem::SubtreeDidChange() {
+ if (!marker_)
+ return;
+
+ if (ordinal_.NotInListChanged()) {
+ UpdateMarker();
+ ordinal_.SetNotInListChanged(false);
+ return;
+ }
+
+ // Make sure outside marker is the direct child of ListItem.
+ if (!IsInside() && marker_->Parent() != this) {
+ marker_->Remove();
+ AddChild(marker_, FirstChild());
+ }
+
UpdateMarkerContentIfNeeded();
}
@@ -166,7 +181,7 @@ LayoutNGListItem::MarkerType LayoutNGListItem::MarkerText(
text->Append(ListMarkerText::GetText(Style()->ListStyleType(), 0));
if (format == kWithSuffix)
text->Append(' ');
- return kStatic;
+ return kSymbolValue;
case EListStyleType::kArabicIndic:
case EListStyleType::kArmenian:
case EListStyleType::kBengali:
@@ -239,8 +254,7 @@ String LayoutNGListItem::MarkerTextWithoutSuffix() const {
}
void LayoutNGListItem::UpdateMarkerContentIfNeeded() {
- if (!marker_)
- return;
+ DCHECK(marker_);
LayoutObject* child = marker_->SlowFirstChild();
if (IsMarkerImage()) {
@@ -270,12 +284,12 @@ void LayoutNGListItem::UpdateMarkerContentIfNeeded() {
// Create a LayoutText in it.
LayoutText* text = nullptr;
if (child) {
- if (!child->IsText()) {
- child->Destroy();
- child = nullptr;
- } else {
+ if (child->IsText()) {
text = ToLayoutText(child);
text->SetStyle(marker_->MutableStyle());
+ } else {
+ child->Destroy();
+ child = nullptr;
}
}
if (!child) {
@@ -286,4 +300,29 @@ void LayoutNGListItem::UpdateMarkerContentIfNeeded() {
}
}
}
+
+LayoutObject* LayoutNGListItem::SymbolMarkerLayoutText() const {
+ if (marker_type_ != kSymbolValue)
+ return nullptr;
+ DCHECK(marker_);
+ return marker_->SlowFirstChild();
+}
+
+const LayoutObject* LayoutNGListItem::FindSymbolMarkerLayoutText(
+ const LayoutObject* object) {
+ if (!object)
+ return nullptr;
+
+ if (object->IsLayoutNGListItem())
+ return ToLayoutNGListItem(object)->SymbolMarkerLayoutText();
+
+ if (object->IsLayoutNGListMarker())
+ return ToLayoutNGListMarker(object)->SymbolMarkerLayoutText();
+
+ if (object->IsAnonymousBlock())
+ return FindSymbolMarkerLayoutText(object->Parent());
+
+ return nullptr;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h
index 21f1e4e8ecc..a060bb11312 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h
@@ -36,6 +36,9 @@ class CORE_EXPORT LayoutNGListItem final : public LayoutNGBlockFlow {
void OrdinalValueChanged();
void WillCollectInlines() override;
+ LayoutObject* SymbolMarkerLayoutText() const;
+ static const LayoutObject* FindSymbolMarkerLayoutText(const LayoutObject*);
+
const char* GetName() const override { return "LayoutNGListItem"; }
private:
@@ -50,7 +53,7 @@ class CORE_EXPORT LayoutNGListItem final : public LayoutNGBlockFlow {
bool IsInside() const;
enum MarkerTextFormat { kWithSuffix, kWithoutSuffix };
- enum MarkerType { kStatic, kOrdinalValue };
+ enum MarkerType { kStatic, kOrdinalValue, kSymbolValue };
MarkerType MarkerText(StringBuilder*, MarkerTextFormat) const;
void UpdateMarkerText();
void UpdateMarkerText(LayoutText*);
@@ -60,7 +63,7 @@ class CORE_EXPORT LayoutNGListItem final : public LayoutNGBlockFlow {
ListItemOrdinal ordinal_;
LayoutObject* marker_ = nullptr;
- unsigned marker_type_ : 1; // MarkerType
+ unsigned marker_type_ : 2; // MarkerType
unsigned is_marker_text_updated_ : 1;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.cc b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.cc
index 9bed606e8ef..b7cd49debf1 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.h"
+#include "third_party/blink/renderer/core/layout/layout_text.h"
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
namespace blink {
@@ -60,4 +61,25 @@ bool LayoutNGListMarker::IsContentImage() const {
return ListItem()->IsMarkerImage();
}
+LayoutObject* LayoutNGListMarker::SymbolMarkerLayoutText() const {
+ return ListItem()->SymbolMarkerLayoutText();
+}
+
+String LayoutNGListMarker::TextAlternative() const {
+ return ToLayoutText(FirstChild())->GetText();
+}
+
+bool LayoutNGListMarker::NeedsOccupyWholeLine() const {
+ if (!GetDocument().InQuirksMode())
+ return false;
+
+ LayoutObject* next_sibling = NextSibling();
+ if (next_sibling && next_sibling->GetNode() &&
+ (IsHTMLUListElement(*next_sibling->GetNode()) ||
+ IsHTMLOListElement(*next_sibling->GetNode())))
+ return true;
+
+ return false;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.h b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.h
index 9ac18260293..469de1bebe9 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.h
@@ -33,12 +33,19 @@ class CORE_EXPORT LayoutNGListMarker final
bool IsContentImage() const;
+ LayoutObject* SymbolMarkerLayoutText() const;
+
+ // Marker text with suffix, e.g. "1. ", for use in accessibility.
+ String TextAlternative() const;
+
const char* GetName() const override { return "LayoutNGListMarker"; }
+ LayoutNGListItem* ListItem() const;
+
+ bool NeedsOccupyWholeLine() const;
+
private:
bool IsOfType(LayoutObjectType) const override;
-
- LayoutNGListItem* ListItem() const;
};
DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutNGListMarker, IsLayoutNGListMarker());
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.cc b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.cc
index fbd11c2a09d..653ab1b4682 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.h"
+#include "third_party/blink/renderer/core/layout/intrinsic_sizing_info.h"
#include "third_party/blink/renderer/core/svg/graphics/svg_image.h"
namespace blink {
@@ -21,14 +22,11 @@ bool LayoutNGListMarkerImage::IsOfType(LayoutObjectType type) const {
return type == kLayoutObjectNGListMarkerImage || LayoutImage::IsOfType(type);
}
-// Use default_size(ascent/2) to compute ConcreteObjectSize as svg's intrinsic
-// size. Otherwise the width of svg marker will be out of control.
-void LayoutNGListMarkerImage::ComputeSVGIntrinsicSizingInfoByDefaultSize(
+// Because ImageResource() is always LayoutImageResourceStyleImage. So we could
+// use StyleImage::ImageSize to determine the concrete object size with
+// default object size(ascent/2 x ascent/2).
+void LayoutNGListMarkerImage::ComputeIntrinsicSizingInfoByDefaultSize(
IntrinsicSizingInfo& intrinsic_sizing_info) const {
- DCHECK(CachedImage());
- Image* image = CachedImage()->GetImage();
- DCHECK(image && image->IsSVGImage());
-
const SimpleFontData* font_data = Style()->GetFont().PrimaryFont();
DCHECK(font_data);
if (!font_data)
@@ -36,14 +34,14 @@ void LayoutNGListMarkerImage::ComputeSVGIntrinsicSizingInfoByDefaultSize(
LayoutUnit bullet_width =
font_data->GetFontMetrics().Ascent() / LayoutUnit(2);
- FloatSize default_size(bullet_width, bullet_width);
- default_size.Scale(1 / Style()->EffectiveZoom());
- FloatSize concrete_size = ToSVGImage(image)->ConcreteObjectSize(default_size);
- concrete_size.Scale(Style()->EffectiveZoom() * ImageDevicePixelRatio());
- LayoutSize svg_image_size(RoundedLayoutSize(concrete_size));
-
- intrinsic_sizing_info.size.SetWidth(svg_image_size.Width());
- intrinsic_sizing_info.size.SetHeight(svg_image_size.Height());
+ LayoutSize default_object_size(bullet_width, bullet_width);
+ FloatSize concrete_size = ImageResource()->ImageSizeWithDefaultSize(
+ Style()->EffectiveZoom(), default_object_size);
+ concrete_size.Scale(ImageDevicePixelRatio());
+ LayoutSize image_size(RoundedLayoutSize(concrete_size));
+
+ intrinsic_sizing_info.size.SetWidth(image_size.Width());
+ intrinsic_sizing_info.size.SetHeight(image_size.Height());
intrinsic_sizing_info.has_width = true;
intrinsic_sizing_info.has_height = true;
}
@@ -52,17 +50,10 @@ void LayoutNGListMarkerImage::ComputeIntrinsicSizingInfo(
IntrinsicSizingInfo& intrinsic_sizing_info) const {
LayoutImage::ComputeIntrinsicSizingInfo(intrinsic_sizing_info);
- // If this is an SVG image without intrinsic width and height,
- // compute an intrinsic size using the concrete object size resolved
- // with a default object size of 1em x 1em.
- // TODO(fs): Apply this more generally to all images (CSS <image> values)
- // that have no intrinsic width or height. I.e just always compute the
- // concrete object size here.
- if (intrinsic_sizing_info.size.IsEmpty() && CachedImage()) {
- Image* image = CachedImage()->GetImage();
- if (image && image->IsSVGImage())
- ComputeSVGIntrinsicSizingInfoByDefaultSize(intrinsic_sizing_info);
- }
+ // If this is an image without intrinsic width and height, compute the
+ // concrete object size by using the specified default object size.
+ if (intrinsic_sizing_info.size.IsEmpty() && ImageResource())
+ ComputeIntrinsicSizingInfoByDefaultSize(intrinsic_sizing_info);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.h b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.h
index 050b8ae5ee4..8d38ae23317 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.h
@@ -20,7 +20,7 @@ class CORE_EXPORT LayoutNGListMarkerImage final : public LayoutImage {
private:
bool IsOfType(LayoutObjectType) const override;
- void ComputeSVGIntrinsicSizingInfoByDefaultSize(IntrinsicSizingInfo&) const;
+ void ComputeIntrinsicSizingInfoByDefaultSize(IntrinsicSizingInfo&) const;
void ComputeIntrinsicSizingInfo(IntrinsicSizingInfo&) const final;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc b/chromium/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc
index cfd4aad7ddd..876df626a78 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.cc
@@ -18,7 +18,7 @@ NGUnpositionedListMarker::NGUnpositionedListMarker(LayoutNGListMarker* marker)
: marker_layout_object_(marker) {}
NGUnpositionedListMarker::NGUnpositionedListMarker(const NGBlockNode& node)
- : NGUnpositionedListMarker(ToLayoutNGListMarker(node.GetLayoutObject())) {}
+ : NGUnpositionedListMarker(ToLayoutNGListMarker(node.GetLayoutBox())) {}
// Returns true if this is an image marker.
bool NGUnpositionedListMarker::IsImage() const {
@@ -55,7 +55,8 @@ bool NGUnpositionedListMarker::AddToBox(
FontBaseline baseline_type,
const NGPhysicalFragment& content,
NGLogicalOffset* content_offset,
- NGFragmentBuilder* container_builder) const {
+ NGFragmentBuilder* container_builder,
+ const NGBoxStrut& border_scrollbar_padding) const {
// Baselines from two different writing-mode cannot be aligned.
if (UNLIKELY(space.GetWritingMode() != content.Style().GetWritingMode()))
return false;
@@ -63,7 +64,16 @@ bool NGUnpositionedListMarker::AddToBox(
// Compute the baseline of the child content.
NGLineHeightMetrics content_metrics;
if (content.IsLineBox()) {
- content_metrics = ToNGPhysicalLineBoxFragment(content).Metrics();
+ const NGPhysicalLineBoxFragment& line_box =
+ ToNGPhysicalLineBoxFragment(content);
+
+ // If this child is an empty line-box, the list marker should be aligned
+ // with the next non-empty line box produced. (This can occur with floats
+ // producing empty line-boxes).
+ if (line_box.Children().IsEmpty() && !line_box.BreakToken()->IsFinished())
+ return false;
+
+ content_metrics = line_box.Metrics();
} else {
NGBoxFragment content_fragment(space.GetWritingMode(),
ToNGPhysicalBoxFragment(content));
@@ -87,9 +97,9 @@ bool NGUnpositionedListMarker::AddToBox(
// Compute the inline offset of the marker.
NGBoxFragment marker_fragment(space.GetWritingMode(),
marker_physical_fragment);
- NGLogicalSize maker_size = marker_fragment.Size();
- NGLogicalOffset marker_offset(InlineOffset(maker_size.inline_size),
- content_offset->block_offset);
+ NGLogicalOffset marker_offset(
+ InlineOffset(marker_fragment.Size().inline_size),
+ content_offset->block_offset);
// Adjust the block offset to align baselines of the marker and the content.
NGLineHeightMetrics marker_metrics = marker_fragment.BaselineMetrics(
@@ -102,6 +112,9 @@ bool NGUnpositionedListMarker::AddToBox(
// push the content down.
content_offset->block_offset -= baseline_adjust;
}
+ marker_offset.inline_offset += ComputeIntrudedFloatOffset(
+ space, container_builder, border_scrollbar_padding,
+ marker_offset.block_offset);
DCHECK(container_builder);
container_builder->AddChild(std::move(marker_layout_result), marker_offset);
@@ -132,4 +145,40 @@ LayoutUnit NGUnpositionedListMarker::AddToBoxWithoutLineBoxes(
return marker_size.block_size;
}
+// Find the opportunity for marker, and compare it to ListItem, then compute the
+// diff as intruded offset.
+LayoutUnit NGUnpositionedListMarker::ComputeIntrudedFloatOffset(
+ const NGConstraintSpace& space,
+ const NGFragmentBuilder* container_builder,
+ const NGBoxStrut& border_scrollbar_padding,
+ LayoutUnit marker_block_offset) const {
+ DCHECK(container_builder);
+ // Because opportunity.rect is in the content area of LI, so origin_offset
+ // should plus border_scrollbar_padding.inline_start, and available_size
+ // should minus border_scrollbar_padding.
+ NGBfcOffset bfc_offset = container_builder->BfcOffset().value();
+ NGBfcOffset origin_offset = {
+ bfc_offset.line_offset + border_scrollbar_padding.inline_start,
+ bfc_offset.block_offset + marker_block_offset};
+ LayoutUnit available_size = container_builder->InlineSize() -
+ border_scrollbar_padding.inline_start -
+ border_scrollbar_padding.inline_end;
+ NGLayoutOpportunity opportunity =
+ space.ExclusionSpace().FindLayoutOpportunity(
+ origin_offset, available_size, NGLogicalSize());
+ DCHECK(marker_layout_object_);
+ const TextDirection direction = marker_layout_object_->StyleRef().Direction();
+ if (direction == TextDirection::kLtr) {
+ // If Ltr, compare the left side.
+ if (opportunity.rect.LineStartOffset() > origin_offset.line_offset)
+ return opportunity.rect.LineStartOffset() - origin_offset.line_offset;
+ } else if (opportunity.rect.LineEndOffset() <
+ origin_offset.line_offset + available_size) {
+ // If Rtl, Compare the right side.
+ return origin_offset.line_offset + available_size -
+ opportunity.rect.LineEndOffset();
+ }
+ return LayoutUnit(0);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h b/chromium/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h
index 30e19bf3693..e6166ea6d12 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h
@@ -7,6 +7,7 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/ng/geometry/ng_box_strut.h"
#include "third_party/blink/renderer/platform/fonts/font_baseline.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
@@ -49,7 +50,8 @@ class CORE_EXPORT NGUnpositionedListMarker final {
FontBaseline,
const NGPhysicalFragment& content,
NGLogicalOffset* content_offset,
- NGFragmentBuilder*) const;
+ NGFragmentBuilder*,
+ const NGBoxStrut&) const;
// Add a fragment for an outside list marker when the list item has no line
// boxes.
@@ -57,13 +59,17 @@ class CORE_EXPORT NGUnpositionedListMarker final {
LayoutUnit AddToBoxWithoutLineBoxes(const NGConstraintSpace&,
FontBaseline,
NGFragmentBuilder*) const;
+ LayoutUnit InlineOffset(const LayoutUnit marker_inline_size) const;
private:
bool IsImage() const;
- LayoutUnit InlineOffset(const LayoutUnit marker_inline_size) const;
scoped_refptr<NGLayoutResult> Layout(const NGConstraintSpace&,
FontBaseline) const;
+ LayoutUnit ComputeIntrudedFloatOffset(const NGConstraintSpace&,
+ const NGFragmentBuilder*,
+ const NGBoxStrut&,
+ LayoutUnit) const;
LayoutNGListMarker* marker_layout_object_;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc
index 4da55760b6b..66eea686f8c 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc
@@ -4,9 +4,13 @@
#include "third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h"
+#include "third_party/blink/renderer/core/frame/local_frame_view.h"
+#include "third_party/blink/renderer/core/html/html_dialog_element.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_static_position.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
#include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/length_functions.h"
@@ -16,13 +20,15 @@ namespace {
bool AbsoluteHorizontalNeedsEstimate(const ComputedStyle& style) {
Length width = style.Width();
- return width.IsIntrinsic() ||
+ return width.IsIntrinsic() || style.MinWidth().IsIntrinsic() ||
+ style.MaxWidth().IsIntrinsic() ||
(width.IsAuto() && (style.Left().IsAuto() || style.Right().IsAuto()));
}
bool AbsoluteVerticalNeedsEstimate(const ComputedStyle& style) {
Length height = style.Height();
- return height.IsIntrinsic() ||
+ return height.IsIntrinsic() || style.MinHeight().IsIntrinsic() ||
+ style.MaxHeight().IsIntrinsic() ||
(height.IsAuto() && (style.Top().IsAuto() || style.Bottom().IsAuto()));
}
@@ -128,18 +134,16 @@ LayoutUnit ComputeAvailableHeight(
LayoutUnit HorizontalBorderPadding(const NGConstraintSpace& space,
const ComputedStyle& style) {
- NGLogicalSize percentage_logical = space.PercentageResolutionSize();
- return ValueForLength(style.PaddingLeft(), percentage_logical.inline_size) +
- ValueForLength(style.PaddingRight(), percentage_logical.inline_size) +
+ return ResolveMarginPaddingLength(space, style.PaddingLeft()) +
+ ResolveMarginPaddingLength(space, style.PaddingRight()) +
LayoutUnit(style.BorderLeftWidth()) +
LayoutUnit(style.BorderRightWidth());
}
LayoutUnit VerticalBorderPadding(const NGConstraintSpace& space,
const ComputedStyle& style) {
- NGLogicalSize percentage_logical = space.PercentageResolutionSize();
- return ValueForLength(style.PaddingTop(), percentage_logical.inline_size) +
- ValueForLength(style.PaddingBottom(), percentage_logical.inline_size) +
+ return ResolveMarginPaddingLength(space, style.PaddingTop()) +
+ ResolveMarginPaddingLength(space, style.PaddingBottom()) +
LayoutUnit(style.BorderTopWidth()) +
LayoutUnit(style.BorderBottomWidth());
}
@@ -154,17 +158,15 @@ void ComputeAbsoluteHorizontal(const NGConstraintSpace& space,
const WritingMode container_writing_mode,
const TextDirection container_direction,
NGAbsolutePhysicalPosition* position) {
- NGLogicalSize percentage_logical = space.PercentageResolutionSize();
NGPhysicalSize percentage_physical =
- percentage_logical.ConvertToPhysical(space.GetWritingMode());
+ space.PercentageResolutionSize().ConvertToPhysical(
+ space.GetWritingMode());
base::Optional<LayoutUnit> margin_left;
if (!style.MarginLeft().IsAuto())
- margin_left =
- ValueForLength(style.MarginLeft(), percentage_logical.inline_size);
+ margin_left = ResolveMarginPaddingLength(space, style.MarginLeft());
base::Optional<LayoutUnit> margin_right;
if (!style.MarginRight().IsAuto())
- margin_right =
- ValueForLength(style.MarginRight(), percentage_logical.inline_size);
+ margin_right = ResolveMarginPaddingLength(space, style.MarginRight());
base::Optional<LayoutUnit> left;
if (!style.Left().IsAuto())
left = ValueForLength(style.Left(), percentage_physical.width);
@@ -304,6 +306,8 @@ void ComputeAbsoluteHorizontal(const NGConstraintSpace& space,
position->inset.left = *left + *margin_left;
position->inset.right = *right + *margin_right;
+ position->margins.left = *margin_left;
+ position->margins.right = *margin_right;
position->size.width = *width;
}
@@ -317,18 +321,16 @@ void ComputeAbsoluteVertical(const NGConstraintSpace& space,
const WritingMode container_writing_mode,
const TextDirection container_direction,
NGAbsolutePhysicalPosition* position) {
- NGLogicalSize percentage_logical = space.PercentageResolutionSize();
NGPhysicalSize percentage_physical =
- percentage_logical.ConvertToPhysical(space.GetWritingMode());
+ space.PercentageResolutionSize().ConvertToPhysical(
+ space.GetWritingMode());
base::Optional<LayoutUnit> margin_top;
if (!style.MarginTop().IsAuto())
- margin_top =
- ValueForLength(style.MarginTop(), percentage_logical.inline_size);
+ margin_top = ResolveMarginPaddingLength(space, style.MarginTop());
base::Optional<LayoutUnit> margin_bottom;
if (!style.MarginBottom().IsAuto())
- margin_bottom =
- ValueForLength(style.MarginBottom(), percentage_logical.inline_size);
+ margin_bottom = ResolveMarginPaddingLength(space, style.MarginBottom());
base::Optional<LayoutUnit> top;
if (!style.Top().IsAuto())
top = ValueForLength(style.Top(), percentage_physical.height);
@@ -467,6 +469,8 @@ void ComputeAbsoluteVertical(const NGConstraintSpace& space,
position->inset.top = *top + *margin_top;
position->inset.bottom = *bottom + *margin_bottom;
+ position->margins.top = *margin_top;
+ position->margins.bottom = *margin_bottom;
position->size.height = *height;
}
@@ -493,6 +497,50 @@ bool AbsoluteNeedsChildInlineSize(const ComputedStyle& style) {
return AbsoluteVerticalNeedsEstimate(style);
}
+base::Optional<LayoutUnit> ComputeAbsoluteDialogYPosition(
+ const LayoutObject& dialog,
+ LayoutUnit height) {
+ if (!IsHTMLDialogElement(dialog.GetNode()))
+ return base::nullopt;
+
+ // This code implements <dialog> static position spec.
+ // //
+ // https://html.spec.whatwg.org/multipage/interactive-elements.html#the-dialog-element
+ HTMLDialogElement* dialog_node = ToHTMLDialogElement(dialog.GetNode());
+ if (dialog_node->GetCenteringMode() == HTMLDialogElement::kNotCentered)
+ return base::nullopt;
+
+ bool can_center_dialog =
+ (dialog.Style()->GetPosition() == EPosition::kAbsolute ||
+ dialog.Style()->GetPosition() == EPosition::kFixed) &&
+ dialog.Style()->HasAutoTopAndBottom();
+
+ if (dialog_node->GetCenteringMode() == HTMLDialogElement::kCentered) {
+ if (can_center_dialog)
+ return dialog_node->CenteredPosition();
+ return base::nullopt;
+ }
+
+ DCHECK_EQ(dialog_node->GetCenteringMode(),
+ HTMLDialogElement::kNeedsCentering);
+ if (!can_center_dialog) {
+ dialog_node->SetNotCentered();
+ return base::nullopt;
+ }
+
+ auto* scrollable_area = dialog.GetDocument().View()->LayoutViewport();
+ LayoutUnit top =
+ LayoutUnit((dialog.Style()->GetPosition() == EPosition::kFixed)
+ ? 0
+ : scrollable_area->ScrollOffsetInt().Height());
+
+ int visible_height = dialog.GetDocument().View()->Height();
+ if (height < visible_height)
+ top += (visible_height - height) / 2;
+ dialog_node->SetCentered(top);
+ return top;
+}
+
NGAbsolutePhysicalPosition ComputePartialAbsoluteWithChildInlineSize(
const NGConstraintSpace& space,
const ComputedStyle& style,
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h
index ede1012089f..22e207b4dad 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h
@@ -15,15 +15,24 @@
namespace blink {
class ComputedStyle;
+class LayoutObject;
class NGConstraintSpace;
struct NGStaticPosition;
struct CORE_EXPORT NGAbsolutePhysicalPosition {
NGPhysicalBoxStrut inset;
NGPhysicalSize size;
+ NGPhysicalBoxStrut margins;
String ToString() const;
};
+// Implements <dialog> special case abspos static positining.
+// Returns new dialog top position if layout_dialog requires
+// <dialog> abspos centering.
+CORE_EXPORT base::Optional<LayoutUnit> ComputeAbsoluteDialogYPosition(
+ const LayoutObject& layout_dialog,
+ LayoutUnit height);
+
// The following routines implement absolute size resolution algorithm.
// https://www.w3.org/TR/css-position-3/#abs-non-replaced-width
//
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.cc
index 677b440e3b7..95365fa5ad5 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.cc
@@ -19,6 +19,15 @@ void NGBaseLayoutAlgorithmTest::SetUp() {
EnableCompositing();
}
+void NGBaseLayoutAlgorithmTest::AdvanceToLayoutPhase() {
+ if (GetDocument().Lifecycle().GetState() ==
+ DocumentLifecycle::kInPerformLayout)
+ return;
+ GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc);
+ GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kStyleClean);
+ GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInPerformLayout);
+}
+
std::pair<scoped_refptr<NGPhysicalBoxFragment>,
scoped_refptr<NGConstraintSpace>>
NGBaseLayoutAlgorithmTest::RunBlockLayoutAlgorithmForElement(Element* element) {
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.h
index c377e3ac66b..9ee54bdbde8 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_base_layout_algorithm_test.h
@@ -28,6 +28,10 @@ class NGBaseLayoutAlgorithmTest
protected:
void SetUp() override;
+ // Should be called before calling Layout(), if you're not using
+ // RunBlockLayoutAlgorithmForElement.
+ void AdvanceToLayoutPhase();
+
std::pair<scoped_refptr<NGPhysicalBoxFragment>,
scoped_refptr<NGConstraintSpace>>
RunBlockLayoutAlgorithmForElement(Element* element);
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 baa5f80f16e..bd3d4fcdab5 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
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/layout/layout_object.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/layout_ng_list_marker.h"
#include "third_party/blink/renderer/core/layout/ng/list/ng_unpositioned_list_marker.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h"
#include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
@@ -27,6 +28,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_positioned_float.h"
#include "third_party/blink/renderer/core/layout/ng/ng_space_utils.h"
#include "third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h"
+#include "third_party/blink/renderer/core/layout/text_autosizer.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
@@ -117,6 +119,63 @@ NGLogicalOffset LogicalFromBfcOffsets(const NGFragment& fragment,
child_bfc_offset.block_offset - parent_bfc_offset.block_offset};
}
+// Create a child constraint space with only extrinsic block sizing data. This
+// will and can not be used for final layout, but is needed in an intermediate
+// measure pass that calculates the min/max size contribution from a child that
+// establishes an orthogonal flow root.
+//
+// Note that it's the child's *block* size that will be propagated as min/max
+// inline size to the container. Therefore it's crucial to provide the child
+// with an available inline size (which can be derived from the block size of
+// the container if definite). We'll provide any extrinsic available block size
+// that we have. This includes fixed and resolvable percentage sizes, for
+// instance, while auto will not resolve. If no extrinsic size can be
+// determined, we will resort to using a fallback later on, such as the initial
+// containing block size. Spec:
+// https://www.w3.org/TR/css-writing-modes-3/#orthogonal-auto
+scoped_refptr<NGConstraintSpace> CreateExtrinsicConstraintSpace(
+ const NGConstraintSpace& container_space,
+ NGBlockNode container,
+ NGBlockNode child) {
+ LayoutUnit extrinsic_block_size = ComputeBlockSizeForFragment(
+ container_space, container.Style(), NGSizeIndefinite);
+ if (extrinsic_block_size != NGSizeIndefinite) {
+ extrinsic_block_size -=
+ CalculateBorderScrollbarPadding(container_space, container).BlockSum();
+ extrinsic_block_size = std::max(extrinsic_block_size, LayoutUnit());
+ }
+ NGLogicalSize extrinsic_size(NGSizeIndefinite, extrinsic_block_size);
+
+ return NGConstraintSpaceBuilder(container_space)
+ .SetAvailableSize(extrinsic_size)
+ .SetPercentageResolutionSize(extrinsic_size)
+ .SetIsIntermediateLayout(true)
+ .SetIsNewFormattingContext(child.CreatesNewFormattingContext())
+ .SetFloatsBfcOffset(NGBfcOffset())
+ .ToConstraintSpace(child.Style().GetWritingMode());
+}
+
+// Stop margin collapsing on one side of a block when
+// -webkit-margin-{after,before}-collapse is something other than 'collapse'
+// (the initial value)
+void StopMarginCollapsing(EMarginCollapse collapse_value,
+ LayoutUnit this_margin,
+ LayoutUnit* logical_block_offset,
+ NGMarginStrut* margin_strut) {
+ DCHECK_NE(collapse_value, EMarginCollapse::kCollapse);
+ if (collapse_value == EMarginCollapse::kSeparate) {
+ // Separate margins between previously adjoining margins and this margin,
+ // AND between this margin and adjoining margins to come.
+ *logical_block_offset += margin_strut->Sum() + this_margin;
+ *margin_strut = NGMarginStrut();
+ return;
+ }
+ DCHECK_EQ(collapse_value, EMarginCollapse::kDiscard);
+ // Discard previously adjoining margins, this margin AND all adjoining margins
+ // to come, so that the sum becomes 0.
+ margin_strut->discard_margins = true;
+}
+
} // namespace
NGBlockLayoutAlgorithm::NGBlockLayoutAlgorithm(NGBlockNode node,
@@ -135,7 +194,7 @@ base::Optional<MinMaxSize> NGBlockLayoutAlgorithm::ComputeMinMaxSize(
MinMaxSize sizes;
// Size-contained elements don't consider their contents for intrinsic sizing.
- if (Style().ContainsSize())
+ if (node_.ShouldApplySizeContainment())
return sizes;
const TextDirection direction = Style().Direction();
@@ -171,7 +230,7 @@ base::Optional<MinMaxSize> NGBlockLayoutAlgorithm::ComputeMinMaxSize(
}
MinMaxSizeInput child_input;
- if (!child.CreatesNewFormattingContext())
+ if (child.IsInline() || child.IsAnonymousBlock())
child_input = {float_left_inline_size, float_right_inline_size};
MinMaxSize child_sizes;
@@ -185,9 +244,21 @@ base::Optional<MinMaxSize> NGBlockLayoutAlgorithm::ComputeMinMaxSize(
child_sizes =
child.ComputeMinMaxSize(Style().GetWritingMode(), child_input);
} else {
+ // We'll need extrinsic sizing data when computing min/max for orthogonal
+ // flow roots.
+ scoped_refptr<NGConstraintSpace> extrinsic_constraint_space;
+ const NGConstraintSpace* optional_constraint_space = nullptr;
+ if (!IsParallelWritingMode(Style().GetWritingMode(),
+ child.Style().GetWritingMode())) {
+ extrinsic_constraint_space = CreateExtrinsicConstraintSpace(
+ ConstraintSpace(), Node(), ToNGBlockNode(child));
+ optional_constraint_space = extrinsic_constraint_space.get();
+ }
child_sizes = ComputeMinAndMaxContentContribution(
- Style().GetWritingMode(), child, child_input);
+ Style().GetWritingMode(), child, child_input,
+ optional_constraint_space);
}
+ DCHECK_LE(child_sizes.min_size, child_sizes.max_size) << child.ToString();
// Determine the max inline contribution of the child.
NGBoxStrut margins = ComputeMinMaxMargins(Style(), child);
@@ -197,10 +268,16 @@ base::Optional<MinMaxSize> NGBlockLayoutAlgorithm::ComputeMinMaxSize(
// 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();
- if (child_style.Floating() == EFloat::kLeft)
- float_left_inline_size += float_inline_size;
- else
- float_right_inline_size += float_inline_size;
+
+ // 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
+ // the content size.
+ if (float_inline_size > 0) {
+ if (child_style.Floating() == EFloat::kLeft)
+ float_left_inline_size += float_inline_size;
+ else
+ float_right_inline_size += float_inline_size;
+ }
max_inline_contribution =
float_left_inline_size + float_right_inline_size;
@@ -248,7 +325,7 @@ base::Optional<MinMaxSize> NGBlockLayoutAlgorithm::ComputeMinMaxSize(
}
DCHECK_GE(sizes.min_size, LayoutUnit());
- DCHECK_GE(sizes.max_size, sizes.min_size);
+ DCHECK_LE(sizes.min_size, sizes.max_size) << Node().ToString();
sizes +=
CalculateBorderScrollbarPadding(ConstraintSpace(), node_).InlineSum();
@@ -270,12 +347,8 @@ NGLogicalOffset NGBlockLayoutAlgorithm::CalculateLogicalOffset(
border_scrollbar_padding_.inline_start + child_margins.inline_start;
if (child.IsInline()) {
- LayoutUnit offset =
- LineOffsetForTextAlign(Style().GetTextAlign(), Style().Direction(),
- child_available_size_.inline_size, LayoutUnit());
- if (IsRtl(Style().Direction()))
- offset = child_available_size_.inline_size - offset;
- inline_offset += offset;
+ inline_offset +=
+ InlineOffsetForTextAlign(Style(), child_available_size_.inline_size);
}
// If we've reached here, both the child and the current layout don't have a
@@ -286,29 +359,23 @@ NGLogicalOffset NGBlockLayoutAlgorithm::CalculateLogicalOffset(
}
scoped_refptr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
- base::Optional<MinMaxSize> min_max_size;
- if (NeedMinMaxSize(ConstraintSpace(), Style())) {
- MinMaxSizeInput zero_input;
- min_max_size = ComputeMinMaxSize(zero_input);
- }
-
border_scrollbar_padding_ =
CalculateBorderScrollbarPadding(ConstraintSpace(), Node());
- NGLogicalSize size = CalculateBorderBoxSize(
- ConstraintSpace(), Style(), min_max_size, CalculateDefaultBlockSize());
+ NGLogicalSize border_box_size = CalculateBorderBoxSize(
+ ConstraintSpace(), Node(), CalculateDefaultBlockSize());
// Our calculated block-axis size may be indefinite at this point.
// If so, just leave the size as NGSizeIndefinite instead of subtracting
// borders and padding.
NGLogicalSize adjusted_size =
- CalculateContentBoxSize(size, border_scrollbar_padding_);
+ CalculateContentBoxSize(border_box_size, border_scrollbar_padding_);
child_available_size_ = adjusted_size;
// Anonymous constraint spaces are auto-sized. Don't let that affect
// block-axis percentage resolution.
- if (ConstraintSpace().IsAnonymous() || Node().IsAnonymous())
+ if (ConstraintSpace().IsAnonymous() || Node().IsAnonymousBlock())
child_percentage_size_ = ConstraintSpace().PercentageResolutionSize();
else
child_percentage_size_ = adjusted_size;
@@ -316,7 +383,7 @@ scoped_refptr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
!ConstraintSpace().FixedSizeBlockIsDefinite())
child_percentage_size_.block_size = NGSizeIndefinite;
- container_builder_.SetInlineSize(size.inline_size);
+ container_builder_.SetInlineSize(border_box_size.inline_size);
if (NGFloatTypes float_types = ConstraintSpace().AdjoiningFloatTypes()) {
DCHECK(!ConstraintSpace().IsNewFormattingContext());
@@ -337,18 +404,25 @@ scoped_refptr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
is_resuming_ ? LayoutUnit() : border_scrollbar_padding_.block_start;
NGPreviousInflowPosition previous_inflow_position = {
- ConstraintSpace().BfcOffset().block_offset, LayoutUnit(),
- ConstraintSpace().MarginStrut(),
+ LayoutUnit(), ConstraintSpace().MarginStrut(),
/* empty_block_affected_by_clearance */ false};
- // Margins collapsing: Do not collapse margins between parent and its child if
- // there is border/padding between them. Then we can and must resolve the BFC
- // offset now. Also, if this is a new formatting context, or if we're resuming
- // layout from a break token, we need to resolve the BFC offset now. Margin
- // struts cannot pass from one fragment to another if they are generated by
- // the same block; they must be dealt with at the first fragment.
+ // Do not collapse margins between parent and its child if:
+ //
+ // A: There is border/padding between them.
+ // B: This is a new formatting context
+ // C: We're resuming layout from a break token. Margin struts cannot pass from
+ // one fragment to another if they are generated by the same block; they
+ // must be dealt with at the first fragment.
+ // D: We're forced to stop margin collapsing by a CSS property
+ //
+ // In all those cases we can and must resolve the BFC offset now.
if (border_scrollbar_padding_.block_start || is_resuming_ ||
- ConstraintSpace().IsNewFormattingContext()) {
+ ConstraintSpace().IsNewFormattingContext() ||
+ Style().MarginBeforeCollapse() != EMarginCollapse::kCollapse) {
+ bool discard_subsequent_margins =
+ previous_inflow_position.margin_strut.discard_margins &&
+ !border_scrollbar_padding_.block_start;
if (!ResolveBfcOffset(&previous_inflow_position)) {
// There should be no preceding content that depends on the BFC offset of
// a new formatting context block, and likewise when resuming from a break
@@ -358,8 +432,14 @@ scoped_refptr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
return container_builder_.Abort(NGLayoutResult::kBfcOffsetResolved);
}
// Move to the content edge. This is where the first child should be placed.
- previous_inflow_position.bfc_block_offset += content_edge;
previous_inflow_position.logical_block_offset = content_edge;
+
+ // If we resolved the BFC offset now, the margin strut has been reset. If
+ // margins are to be discarded, and this box would otherwise have adjoining
+ // margins between its own margin and those subsequent content, we need to
+ // make sure subsequent content discard theirs.
+ if (discard_subsequent_margins)
+ previous_inflow_position.margin_strut.discard_margins = true;
}
#if DCHECK_IS_ON()
@@ -395,7 +475,11 @@ scoped_refptr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
if (node_.IsQuirkyContainer())
previous_inflow_position.margin_strut.is_quirky_container_start = true;
- intrinsic_block_size_ = content_edge;
+ // Before we descend into children (but after we have determined our inline
+ // size), give the autosizer an opportunity to adjust the font size on the
+ // children.
+ TextAutosizer::NGLayoutScope text_autosizer_layout_scope(
+ Node(), border_box_size.inline_size);
scoped_refptr<NGBreakToken> previous_inline_break_token;
@@ -411,7 +495,9 @@ scoped_refptr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
} else if (child.IsFloating()) {
HandleFloat(previous_inflow_position, ToNGBlockNode(child),
ToNGBlockBreakToken(child_break_token));
- } else if (child.IsListMarker()) {
+ } else if (child.IsListMarker() &&
+ !ToLayoutNGListMarker(child.GetLayoutBox())
+ ->NeedsOccupyWholeLine()) {
container_builder_.SetUnpositionedListMarker(
NGUnpositionedListMarker(ToNGBlockNode(child)));
} else {
@@ -435,7 +521,9 @@ scoped_refptr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
// We need to abort the layout, as our BFC offset was resolved.
return container_builder_.Abort(NGLayoutResult::kBfcOffsetResolved);
}
- if (container_builder_.DidBreak() && IsFragmentainerOutOfSpace())
+ if (container_builder_.DidBreak() &&
+ IsFragmentainerOutOfSpace(
+ previous_inflow_position.logical_block_offset))
break;
has_processed_first_child_ = true;
}
@@ -443,6 +531,10 @@ scoped_refptr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
NGMarginStrut end_margin_strut = previous_inflow_position.margin_strut;
+ // The intrinsic block size is not allowed to be less than the content edge
+ // offset, as that could give us a negative content box size.
+ intrinsic_block_size_ = content_edge;
+
// If the current layout is a new formatting context, we need to encapsulate
// all of our floats.
if (ConstraintSpace().IsNewFormattingContext()) {
@@ -495,20 +587,33 @@ scoped_refptr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
intrinsic_block_size_ += border_scrollbar_padding_.block_end;
end_margin_strut = NGMarginStrut();
+ } else {
+ // Update our intrinsic block size to be just past the block-end border edge
+ // of the last in-flow child. The pending margin is to be propagated to our
+ // container, so ignore it.
+ intrinsic_block_size_ = std::max(
+ intrinsic_block_size_, previous_inflow_position.logical_block_offset);
}
- // Recompute the block-axis size now that we know our content size.
intrinsic_block_size_ = std::max(intrinsic_block_size_,
CalculateMinimumBlockSize(end_margin_strut));
- size.block_size = ComputeBlockSizeForFragment(ConstraintSpace(), Style(),
- intrinsic_block_size_);
- container_builder_.SetBlockSize(size.block_size);
+
+ // With contain:size we need to ignore all kinds of intrinsic sizing. If block
+ // height was specified as auto, its content-box size will become 0.
+ if (Node().ShouldApplySizeContainment())
+ intrinsic_block_size_ = border_scrollbar_padding_.BlockSum();
+
+ // Recompute the block-axis size now that we know our content size.
+ border_box_size.block_size = ComputeBlockSizeForFragment(
+ ConstraintSpace(), Style(), intrinsic_block_size_);
+ container_builder_.SetBlockSize(border_box_size.block_size);
// If our BFC offset is still unknown, there's one last thing to take into
// consideration: Non-empty blocks always know their position in space. If we
// have a break token, it means that we know the blocks' position even if
// they're empty; it will be at the very start of the fragmentainer.
- if (!container_builder_.BfcOffset() && (size.block_size || BreakToken())) {
+ if (!container_builder_.BfcOffset() &&
+ (border_box_size.block_size || BreakToken())) {
if (!ResolveBfcOffset(&previous_inflow_position))
return container_builder_.Abort(NGLayoutResult::kBfcOffsetResolved);
DCHECK(container_builder_.BfcOffset());
@@ -573,9 +678,18 @@ scoped_refptr<NGLayoutResult> NGBlockLayoutAlgorithm::Layout() {
void NGBlockLayoutAlgorithm::HandleOutOfFlowPositioned(
const NGPreviousInflowPosition& previous_inflow_position,
NGBlockNode child) {
+ const ComputedStyle& child_style = child.Style();
+ LayoutUnit inline_offset = border_scrollbar_padding_.inline_start;
+ if (child_style.IsOriginalDisplayInlineType()) {
+ // If this out-of-flow child is inline type, its static position should
+ // honor the 'text-align' property.
+ inline_offset +=
+ InlineOffsetForTextAlign(Style(), child_available_size_.inline_size);
+ }
+
// TODO(ikilpatrick): Determine which of the child's margins need to be
// included for the static position.
- NGLogicalOffset offset = {border_scrollbar_padding_.inline_start,
+ NGLogicalOffset offset = {inline_offset,
previous_inflow_position.logical_block_offset};
// We only include the margin strut in the OOF static-position if we know we
@@ -617,8 +731,7 @@ void NGBlockLayoutAlgorithm::HandleFloat(
// <div style="margin-bottom: 30px"></div>
LayoutUnit origin_block_offset =
container_builder_.BfcOffset()
- ? previous_inflow_position.bfc_block_offset +
- previous_inflow_position.margin_strut.Sum()
+ ? NextBorderEdge(previous_inflow_position)
: ConstraintSpace().FloatsBfcOffset().value().block_offset;
PositionPendingFloats(origin_block_offset);
}
@@ -633,6 +746,7 @@ bool NGBlockLayoutAlgorithm::HandleNewFormattingContext(
DCHECK(!child.IsFloating());
DCHECK(!child.IsOutOfFlowPositioned());
DCHECK(child.CreatesNewFormattingContext());
+ DCHECK(child.IsBlock());
const ComputedStyle& child_style = child.Style();
const TextDirection direction = ConstraintSpace().Direction();
@@ -684,7 +798,7 @@ bool NGBlockLayoutAlgorithm::HandleNewFormattingContext(
child_margin_got_separated =
bfc_offset.block_offset != adjoining_bfc_offset_estimate;
} else if (has_clearance_past_adjoining_floats) {
- child_bfc_offset_estimate = previous_inflow_position->NextBorderEdge();
+ child_bfc_offset_estimate = NextBorderEdge(*previous_inflow_position);
child_margin_got_separated = true;
}
@@ -765,10 +879,22 @@ bool NGBlockLayoutAlgorithm::HandleNewFormattingContext(
const auto& physical_fragment = *layout_result->PhysicalFragment();
NGFragment fragment(ConstraintSpace().GetWritingMode(), physical_fragment);
- // Auto-margins are applied within the layout opportunity which fits.
+ // Auto-margins are applied within the layout opportunity which fits. We'll
+ // pretend that computed margins are 0 here, as they have already been
+ // excluded from the layout opportunity rectangle.
NGBoxStrut auto_margins;
- ApplyAutoMargins(child_style, Style(), opportunity.rect.InlineSize(),
- fragment.InlineSize(), &auto_margins);
+ if (child.IsListMarker() &&
+ ToLayoutNGListMarker(child.GetLayoutBox())->NeedsOccupyWholeLine()) {
+ // Deal with marker's margin. It happens only when marker
+ // NeedsOccupyWholeLine().
+ auto_margins.inline_start = NGUnpositionedListMarker(ToNGBlockNode(child))
+ .InlineOffset(fragment.InlineSize());
+ auto_margins.inline_end = opportunity.rect.InlineSize() -
+ fragment.InlineSize() - auto_margins.inline_start;
+ } else {
+ ResolveInlineMargins(child_style, Style(), opportunity.rect.InlineSize(),
+ fragment.InlineSize(), &auto_margins);
+ }
NGBfcOffset child_bfc_offset(opportunity.rect.start_offset.line_offset +
auto_margins.LineLeft(direction),
@@ -783,8 +909,8 @@ bool NGBlockLayoutAlgorithm::HandleNewFormattingContext(
child_margin_got_separated ||
child_bfc_offset.block_offset > child_bfc_offset_estimate ||
layout_result->IsPushedByFloats();
- if (BreakBeforeChild(child, *layout_result, logical_offset.block_offset,
- is_pushed_by_floats))
+ if (BreakBeforeChild(child, *layout_result, previous_inflow_position,
+ logical_offset.block_offset, is_pushed_by_floats))
return true;
EBreakBetween break_after = JoinFragmentainerBreakValues(
layout_result->FinalBreakAfter(), child.Style().BreakAfter());
@@ -793,13 +919,16 @@ bool NGBlockLayoutAlgorithm::HandleNewFormattingContext(
PositionOrPropagateListMarker(*layout_result, &logical_offset);
- intrinsic_block_size_ =
- std::max(intrinsic_block_size_,
- logical_offset.block_offset + fragment.BlockSize());
-
container_builder_.AddChild(layout_result, logical_offset);
container_builder_.PropagateBreak(layout_result);
+ // The margins we store will be used by e.g. getComputedStyle().
+ // When calculating these values, ignore any floats that might have
+ // affected the child. This is what Edge does.
+ ResolveInlineMargins(child_style, Style(), child_available_size_.inline_size,
+ fragment.InlineSize(), &child_data.margins);
+ ToNGBlockNode(child).StoreMargins(ConstraintSpace(), child_data.margins);
+
*previous_inflow_position = ComputeInflowPosition(
*previous_inflow_position, child, child_data, child_bfc_offset,
logical_offset, *layout_result, fragment,
@@ -901,6 +1030,13 @@ bool NGBlockLayoutAlgorithm::HandleInflow(
bool is_non_empty_inline =
child.IsInline() && !ToNGInlineNode(child).IsEmptyInline();
+ // We update marker text in WillCollectInlines(). If ListItem isn't
+ // ChildrenInline(), we should WillCollectInlines() manually.
+ if (Node().IsListItem() && !child.IsInline()) {
+ LayoutBlockFlow* block = ToLayoutBlockFlow(Node().GetLayoutBox());
+ block->WillCollectInlines();
+ }
+
bool has_clearance_past_adjoining_floats =
child.IsBlock() &&
HasClearancePastAdjoiningFloats(container_builder_.AdjoiningFloatTypes(),
@@ -979,8 +1115,7 @@ bool NGBlockLayoutAlgorithm::HandleInflow(
// is past the relevant floats. If it's not, we need to apply clearance
// before it.
LayoutUnit child_block_offset_estimate =
- previous_inflow_position->bfc_block_offset +
- layout_result->EndMarginStrut().Sum();
+ BfcBlockOffset() + layout_result->EndMarginStrut().Sum();
if (child_block_offset_estimate < child_space->ClearanceOffset() ||
child_space->ShouldForceClearance())
has_clearance = empty_block_affected_by_clearance = true;
@@ -1115,7 +1250,8 @@ bool NGBlockLayoutAlgorithm::HandleInflow(
child, fragment, child_data.margins, child_bfc_offset);
if (ConstraintSpace().HasBlockFragmentation()) {
- if (BreakBeforeChild(child, *layout_result, logical_offset.block_offset,
+ if (BreakBeforeChild(child, *layout_result, previous_inflow_position,
+ logical_offset.block_offset,
layout_result->IsPushedByFloats()))
return true;
EBreakBetween break_after = JoinFragmentainerBreakValues(
@@ -1125,20 +1261,7 @@ bool NGBlockLayoutAlgorithm::HandleInflow(
PositionOrPropagateListMarker(*layout_result, &logical_offset);
- // Only modify intrinsic_block_size_ if the fragment is non-empty block.
- //
- // Empty blocks don't immediately contribute to our size, instead we wait to
- // see what the final margin produced, e.g.
- // <div style="display: flow-root">
- // <div style="margin-top: -8px"></div>
- // <div style="margin-top: 10px"></div>
- // </div>
- if (!is_empty_block) {
- DCHECK(container_builder_.BfcOffset());
- intrinsic_block_size_ =
- std::max(intrinsic_block_size_,
- logical_offset.block_offset + fragment.BlockSize());
- } else if (!container_builder_.BfcOffset()) {
+ if (is_empty_block && !container_builder_.BfcOffset()) {
container_builder_.AddAdjoiningFloatTypes(
layout_result->AdjoiningFloatTypes());
}
@@ -1147,6 +1270,9 @@ bool NGBlockLayoutAlgorithm::HandleInflow(
if (child.IsBlock())
container_builder_.PropagateBreak(layout_result);
+ if (child.IsBlock())
+ ToNGBlockNode(child).StoreMargins(ConstraintSpace(), child_data.margins);
+
*previous_inflow_position =
ComputeInflowPosition(*previous_inflow_position, child, child_data,
child_bfc_offset, logical_offset, *layout_result,
@@ -1174,14 +1300,25 @@ NGInflowChildData NGBlockLayoutAlgorithm::ComputeChildData(
// Non empty border/padding, and new FC use cases are handled inside of the
// child's layout
NGMarginStrut margin_strut = previous_inflow_position.margin_strut;
- margin_strut.Append(margins.block_start,
- child.Style().HasMarginBeforeQuirk());
+
+ LayoutUnit logical_block_offset =
+ previous_inflow_position.logical_block_offset;
+
+ if (child.Style().MarginBeforeCollapse() != EMarginCollapse::kCollapse) {
+ // Stop margin collapsing on the block-start side of the child.
+ StopMarginCollapsing(child.Style().MarginBeforeCollapse(),
+ margins.block_start, &logical_block_offset,
+ &margin_strut);
+ } else {
+ margin_strut.Append(margins.block_start,
+ child.Style().HasMarginBeforeQuirk());
+ }
NGBfcOffset child_bfc_offset = {
ConstraintSpace().BfcOffset().line_offset +
border_scrollbar_padding_.LineLeft(ConstraintSpace().Direction()) +
margins.LineLeft(ConstraintSpace().Direction()),
- previous_inflow_position.bfc_block_offset};
+ BfcBlockOffset() + logical_block_offset};
return {child_bfc_offset, margin_strut, margins, force_clearance};
}
@@ -1195,18 +1332,20 @@ NGPreviousInflowPosition NGBlockLayoutAlgorithm::ComputeInflowPosition(
const NGLayoutResult& layout_result,
const NGFragment& fragment,
bool empty_block_affected_by_clearance) {
- // Determine the child's end BFC block offset and logical offset, for the
- // next child to use.
- LayoutUnit child_end_bfc_block_offset;
+ // Determine the child's end logical offset, for the next child to use.
LayoutUnit logical_block_offset;
bool is_empty_block = IsEmptyBlock(child, layout_result);
if (is_empty_block) {
// The default behaviour for empty blocks is they just pass through the
// previous inflow position.
- child_end_bfc_block_offset = previous_inflow_position.bfc_block_offset;
+ logical_block_offset = previous_inflow_position.logical_block_offset;
if (empty_block_affected_by_clearance) {
+ // If there's clearance, we must have applied that by now and thus
+ // resolved our BFC offset.
+ DCHECK(container_builder_.BfcOffset());
+
// If an empty block was affected by clearance (that is it got pushed
// down past a float), we need to do something slightly bizarre.
//
@@ -1242,35 +1381,35 @@ NGPreviousInflowPosition NGBlockLayoutAlgorithm::ComputeInflowPosition(
// not participate in any subsequent margin collapsing.
LayoutUnit margin_before_clearance =
previous_inflow_position.margin_strut.Sum();
- child_end_bfc_block_offset += margin_before_clearance;
+ logical_block_offset += margin_before_clearance;
// Calculate and apply actual clearance.
LayoutUnit clearance = child_bfc_offset.value().block_offset -
layout_result.EndMarginStrut().Sum() -
- previous_inflow_position.NextBorderEdge();
- child_end_bfc_block_offset += clearance;
+ NextBorderEdge(previous_inflow_position);
+ logical_block_offset += clearance;
}
-
- // The logical block offset needs to go through exactly the same change as
- // the BFC block offset here.
- logical_block_offset = previous_inflow_position.logical_block_offset +
- child_end_bfc_block_offset -
- previous_inflow_position.bfc_block_offset;
-
- if (!container_builder_.BfcOffset()) {
- DCHECK_EQ(child_end_bfc_block_offset,
- ConstraintSpace().BfcOffset().block_offset);
+ if (!container_builder_.BfcOffset())
DCHECK_EQ(logical_block_offset, LayoutUnit());
- }
} else {
- child_end_bfc_block_offset =
- child_bfc_offset.value().block_offset + fragment.BlockSize();
logical_block_offset = logical_offset.block_offset + fragment.BlockSize();
}
NGMarginStrut margin_strut = layout_result.EndMarginStrut();
- margin_strut.Append(child_data.margins.block_end,
- child.Style().HasMarginAfterQuirk());
+
+ if (child.Style().MarginAfterCollapse() != EMarginCollapse::kCollapse) {
+ // Stop margin collapsing on the block-end side of the child.
+ StopMarginCollapsing(child.Style().MarginAfterCollapse(),
+ child_data.margins.block_end, &logical_block_offset,
+ &margin_strut);
+ } else {
+ // An empty block's end margin can "inherit" quirkiness from its start
+ // margin. E.g.
+ // <ol style="margin-bottom: 20px"></ol>
+ bool is_quirky = (is_empty_block && child.Style().HasMarginBeforeQuirk()) ||
+ child.Style().HasMarginAfterQuirk();
+ margin_strut.Append(child_data.margins.block_end, is_quirky);
+ }
// This flag is subtle, but in order to determine our size correctly we need
// to check if our last child is an empty block, and it was affected by
@@ -1287,7 +1426,7 @@ NGPreviousInflowPosition NGBlockLayoutAlgorithm::ComputeInflowPosition(
(previous_inflow_position.empty_block_affected_by_clearance &&
is_empty_block);
- return {child_end_bfc_block_offset, logical_block_offset, margin_strut,
+ return {logical_block_offset, margin_strut,
empty_or_sibling_empty_affected_by_clearance};
}
@@ -1324,12 +1463,13 @@ LayoutUnit NGBlockLayoutAlgorithm::FragmentainerSpaceAvailable() const {
container_builder_.BfcOffset()->block_offset;
}
-bool NGBlockLayoutAlgorithm::IsFragmentainerOutOfSpace() const {
+bool NGBlockLayoutAlgorithm::IsFragmentainerOutOfSpace(
+ LayoutUnit block_offset) const {
if (!ConstraintSpace().HasBlockFragmentation())
return false;
if (!container_builder_.BfcOffset().has_value())
return false;
- return intrinsic_block_size_ >= FragmentainerSpaceAvailable();
+ return block_offset >= FragmentainerSpaceAvailable();
}
void NGBlockLayoutAlgorithm::FinalizeForFragmentation() {
@@ -1412,6 +1552,7 @@ void NGBlockLayoutAlgorithm::FinalizeForFragmentation() {
bool NGBlockLayoutAlgorithm::BreakBeforeChild(
NGLayoutInputNode child,
const NGLayoutResult& layout_result,
+ NGPreviousInflowPosition* previous_inflow_position,
LayoutUnit block_offset,
bool is_pushed_by_floats) {
DCHECK(ConstraintSpace().HasBlockFragmentation());
@@ -1519,7 +1660,8 @@ bool NGBlockLayoutAlgorithm::BreakBeforeChild(
// content, due to the break) should still be occupied by this container.
// TODO(mstensho): Figure out if we really need to <0 here. It doesn't seem
// right to have negative available space.
- intrinsic_block_size_ = space_available.ClampNegativeToZero();
+ previous_inflow_position->logical_block_offset =
+ space_available.ClampNegativeToZero();
// Drop the fragment on the floor and retry at the start of the next
// fragmentainer.
container_builder_.AddBreakBeforeChild(child);
@@ -1632,24 +1774,15 @@ NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins(
if (ShouldIgnoreBlockStartMargin(ConstraintSpace(), child, child_break_token))
margins.block_start = LayoutUnit();
- // TODO(ikilpatrick): Move the auto margins calculation for different writing
- // modes to post-layout.
- if (!child.IsFloating() && !child.CreatesNewFormattingContext()) {
- base::Optional<MinMaxSize> sizes;
- if (NeedMinMaxSize(*space, child_style)) {
- // We only want to guess the child's size here, so preceding floats are of
- // no interest.
- MinMaxSizeInput zero_input;
- sizes = child.ComputeMinMaxSize(child_style.GetWritingMode(), zero_input);
- }
+ // As long as the child isn't establishing a new formatting context, we need
+ // to resolve auto margins before layout, to be able to position child floats
+ // correctly.
+ if (!child.CreatesNewFormattingContext()) {
+ LayoutUnit child_inline_size = ComputeInlineSizeForFragment(*space, child);
- LayoutUnit child_inline_size =
- ComputeInlineSizeForFragment(*space, child_style, sizes);
-
- // TODO(ikilpatrick): ApplyAutoMargins looks wrong as its not respecting
- // the parents writing mode?
- ApplyAutoMargins(child_style, Style(), space->AvailableSize().inline_size,
- child_inline_size, &margins);
+ ResolveInlineMargins(child_style, Style(),
+ space->AvailableSize().inline_size, child_inline_size,
+ &margins);
}
return margins;
}
@@ -1748,6 +1881,33 @@ NGBlockLayoutAlgorithm::CreateConstraintSpaceForChild(
return space_builder.ToConstraintSpace(writing_mode);
}
+LayoutUnit NGBlockLayoutAlgorithm::ComputeLineBoxBaselineOffset(
+ const NGBaselineRequest& request,
+ const NGPhysicalLineBoxFragment& line_box,
+ LayoutUnit line_box_block_offset) const {
+ NGLineHeightMetrics metrics = line_box.BaselineMetrics(request.baseline_type);
+
+ // NGLineHeightMetrics is line-relative, which matches to the flow-relative
+ // unless this box is in flipped-lines writing-mode.
+ if (!Style().IsFlippedLinesWritingMode())
+ return metrics.ascent + line_box_block_offset;
+
+ if (Node().IsInlineLevel()) {
+ // If this box is inline-level, since we're in NGBlockLayoutAlgorithm, this
+ // is an inline-block.
+ DCHECK(Node().IsAtomicInlineLevel());
+ // This box will be flipped when the containing line is flipped. Compute the
+ // baseline offset from the block-end (right in vertical-lr) content edge.
+ line_box_block_offset = container_builder_.Size().block_size -
+ (line_box_block_offset + line_box.Size().width);
+ return metrics.ascent + line_box_block_offset;
+ }
+
+ // Otherwise, the baseline is offset by the descent from the block-start
+ // content edge.
+ return metrics.descent + line_box_block_offset;
+}
+
// Add a baseline from a child box fragment.
// @return false if the specified child is not a box or is OOF.
bool NGBlockLayoutAlgorithm::AddBaseline(const NGBaselineRequest& request,
@@ -1762,8 +1922,9 @@ bool NGBlockLayoutAlgorithm::AddBaseline(const NGBaselineRequest& request,
if (line_box->Children().IsEmpty())
return false;
- LayoutUnit offset = line_box->BaselinePosition(request.baseline_type);
- container_builder_.AddBaseline(request, offset + child_offset);
+ LayoutUnit offset =
+ ComputeLineBoxBaselineOffset(request, *line_box, child_offset);
+ container_builder_.AddBaseline(request, offset);
return true;
}
@@ -1793,12 +1954,16 @@ void NGBlockLayoutAlgorithm::PropagateBaselinesFromChildren() {
for (const auto& request : requests) {
switch (request.algorithm_type) {
case NGBaselineAlgorithmType::kAtomicInline:
+ if (Node().UseLogicalBottomMarginEdgeForInlineBlockBaseline())
+ break;
+
for (unsigned i = container_builder_.Children().size(); i--;) {
if (AddBaseline(request, container_builder_.Children()[i].get(),
container_builder_.Offsets()[i].block_offset))
break;
}
break;
+
case NGBaselineAlgorithmType::kFirstLine:
for (unsigned i = 0; i < container_builder_.Children().size(); i++) {
if (AddBaseline(request, container_builder_.Children()[i].get(),
@@ -1842,7 +2007,6 @@ bool NGBlockLayoutAlgorithm::ResolveBfcOffset(
// caller, for subsequent layout to continue at the right position. Whether we
// need to add border+padding or not isn't something we should determine here,
// so it must be dealt with as part of initializing the layout algorithm.
- previous_inflow_position->bfc_block_offset = bfc_block_offset;
previous_inflow_position->logical_block_offset = LayoutUnit();
previous_inflow_position->margin_strut = NGMarginStrut();
@@ -1977,7 +2141,7 @@ void NGBlockLayoutAlgorithm::PositionOrPropagateListMarker(
}
if (list_marker.AddToBox(constraint_space_, Style().GetFontBaseline(),
*layout_result.PhysicalFragment(), content_offset,
- &container_builder_))
+ &container_builder_, border_scrollbar_padding_))
return;
// If the list marker could not be positioned against this child because it
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 8a51fde1456..6e979c6e022 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
@@ -18,17 +18,11 @@ namespace blink {
class NGConstraintSpace;
class NGFragment;
class NGLayoutResult;
+class NGPhysicalLineBoxFragment;
// This struct is used for communicating to a child the position of the previous
// inflow child. This will be used to calculate the position of the next child.
struct NGPreviousInflowPosition {
- // Return the BFC offset of the next block-start border edge we'd get if we
- // commit pending margins.
- LayoutUnit NextBorderEdge() const {
- return bfc_block_offset + margin_strut.Sum();
- }
-
- LayoutUnit bfc_block_offset;
LayoutUnit logical_block_offset;
NGMarginStrut margin_strut;
bool empty_block_affected_by_clearance;
@@ -66,6 +60,23 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
scoped_refptr<NGLayoutResult> Layout() override;
private:
+ // Return the BFC offset of this block.
+ LayoutUnit BfcBlockOffset() const {
+ // If we have resolved our BFC offset, use that.
+ if (container_builder_.BfcOffset())
+ return container_builder_.BfcOffset()->block_offset;
+ // Otherwise fall back to the BFC offset assigned by the parent algorithm.
+ return ConstraintSpace().BfcOffset().block_offset;
+ }
+
+ // Return the BFC offset of the next block-start border edge (for some child)
+ // we'd get if we commit pending margins.
+ LayoutUnit NextBorderEdge(
+ const NGPreviousInflowPosition& previous_inflow_position) const {
+ return BfcBlockOffset() + previous_inflow_position.logical_block_offset +
+ previous_inflow_position.margin_strut.Sum();
+ }
+
NGBoxStrut CalculateMargins(NGLayoutInputNode child,
const NGBreakToken* child_break_token);
@@ -156,12 +167,16 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
// Return true if the node being laid out by this fragmentainer has used all
// the available space in the current fragmentainer.
- bool IsFragmentainerOutOfSpace() const;
+ // |block_offset| is the border-edge relative block offset we want to check
+ // whether fits within the fragmentainer or not.
+ bool IsFragmentainerOutOfSpace(LayoutUnit block_offset) const;
// Insert a fragmentainer break before the child if necessary.
- // Return true if a break was inserted, false otherwise.
+ // Update previous in-flow position and return true if a break was inserted.
+ // Otherwise return false.
bool BreakBeforeChild(NGLayoutInputNode child,
const NGLayoutResult&,
+ NGPreviousInflowPosition*,
LayoutUnit block_offset,
bool is_pushed_by_floats);
@@ -184,6 +199,14 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
const NGPhysicalFragment*,
LayoutUnit child_offset);
+ // Compute the baseline offset of a line box from the content box.
+ // Line boxes are in line-relative coordinates. This function returns the
+ // offset in flow-relative coordinates.
+ LayoutUnit ComputeLineBoxBaselineOffset(
+ const NGBaselineRequest&,
+ const NGPhysicalLineBoxFragment&,
+ LayoutUnit line_box_block_offset) const;
+
// If still unresolved, resolve the fragment's BFC offset.
//
// This includes applying clearance, so the bfc_block_offset passed won't be
@@ -201,7 +224,7 @@ class CORE_EXPORT NGBlockLayoutAlgorithm
// margin, so here's a convenience overload for that.
bool ResolveBfcOffset(NGPreviousInflowPosition* previous_inflow_position) {
return ResolveBfcOffset(previous_inflow_position,
- previous_inflow_position->NextBorderEdge());
+ NextBorderEdge(*previous_inflow_position));
}
// Return true if the BFC offset has changed and this means that we need to
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 fc1e2732a14..4103730530c 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
@@ -2019,6 +2019,8 @@ TEST_F(NGBlockLayoutAlgorithmTest, FloatFragmentationOrthogonalFlows) {
NGLogicalSize(LayoutUnit(1000), NGSizeIndefinite), false, true,
kFragmentainerSpaceAvailable);
+ AdvanceToLayoutPhase();
+
scoped_refptr<const NGPhysicalFragment> fragment =
NGBlockLayoutAlgorithm(node, *space).Layout()->PhysicalFragment();
EXPECT_EQ(NGPhysicalSize(LayoutUnit(150), LayoutUnit(60)), fragment->Size());
@@ -2306,5 +2308,15 @@ TEST_F(NGBlockLayoutAlgorithmTest, RootFragmentOffsetInsideLegacy) {
// fragment->Offset());
}
+// TODO(dgrogan): Move this to ng_flex_layout_algorithm_test.cc if there ever is
+// one.
+TEST_F(NGBlockLayoutAlgorithmTest, DetailsFlexDoesntCrash) {
+ SetBodyInnerHTML(R"HTML(
+ <details style="display:flex"></details>
+ )HTML");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ // No crash is good.
+}
+
} // namespace
} // namespace blink
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 e30210096e9..412a763099d 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
@@ -6,6 +6,7 @@
#include <memory>
+#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h"
#include "third_party/blink/renderer/core/layout/layout_multi_column_set.h"
@@ -41,28 +42,34 @@ inline LayoutMultiColumnFlowThread* GetFlowThread(const LayoutBox& box) {
return ToLayoutBlockFlow(box).MultiColumnFlowThread();
}
-scoped_refptr<NGLayoutResult> LayoutWithAlgorithm(
- const ComputedStyle& style,
- NGBlockNode node,
- LayoutBox* box,
- const NGConstraintSpace& space,
- NGBreakToken* break_token) {
- auto* token = ToNGBlockBreakToken(break_token);
- if (style.IsDisplayFlexibleBox())
- return NGFlexLayoutAlgorithm(node, space, token).Layout();
- // If there's a legacy layout box, we can only do block fragmentation if we
- // would have done block fragmentation with the legacy engine. Otherwise
- // writing data back into the legacy tree will fail. Look for the flow
- // thread.
- if (!box || GetFlowThread(*box)) {
- if (style.IsOverflowPaged())
- return NGPageLayoutAlgorithm(node, space, token).Layout();
- if (style.SpecifiesColumns())
- return NGColumnLayoutAlgorithm(node, space, token).Layout();
- NOTREACHED();
+#define WITH_ALGORITHM(ret, func, argdecl, args) \
+ ret func##WithAlgorithm(NGBlockNode node, const NGConstraintSpace& space, \
+ NGBreakToken* break_token, argdecl) { \
+ auto* token = ToNGBlockBreakToken(break_token); \
+ const ComputedStyle& style = node.Style(); \
+ if (node.GetLayoutBox()->IsLayoutNGFlexibleBox()) \
+ return NGFlexLayoutAlgorithm(node, space, token).func args; \
+ /* If there's a legacy layout box, we can only do block fragmentation if \
+ * we would have done block fragmentation with the legacy engine. \
+ * Otherwise writing data back into the legacy tree will fail. Look for \
+ * the flow thread. */ \
+ if (GetFlowThread(*node.GetLayoutBox())) { \
+ if (style.IsOverflowPaged()) \
+ return NGPageLayoutAlgorithm(node, space, token).func args; \
+ if (style.SpecifiesColumns()) \
+ return NGColumnLayoutAlgorithm(node, space, token).func args; \
+ NOTREACHED(); \
+ } \
+ return NGBlockLayoutAlgorithm(node, space, token).func args; \
}
- return NGBlockLayoutAlgorithm(node, space, token).Layout();
-}
+
+WITH_ALGORITHM(scoped_refptr<NGLayoutResult>, Layout, void*, ())
+WITH_ALGORITHM(base::Optional<MinMaxSize>,
+ ComputeMinMaxSize,
+ MinMaxSizeInput input,
+ (input))
+
+#undef WITH_ALGORITHM
bool IsFloatFragment(const NGPhysicalFragment& fragment) {
const LayoutObject* layout_object = fragment.GetLayoutObject();
@@ -158,6 +165,16 @@ void CopyFragmentDataToLayoutBoxForInlineChildren(
}
}
+NGConstraintSpaceBuilder CreateConstraintSpaceBuilderForMinMax(
+ NGBlockNode node) {
+ return NGConstraintSpaceBuilder(node.Style().GetWritingMode(),
+ node.InitialContainingBlockSize())
+ .SetTextDirection(node.Style().Direction())
+ .SetIsIntermediateLayout(true)
+ .SetIsNewFormattingContext(node.CreatesNewFormattingContext())
+ .SetFloatsBfcOffset(NGBfcOffset());
+}
+
} // namespace
NGBlockNode::NGBlockNode(LayoutBox* box) : NGLayoutInputNode(box, kBlock) {}
@@ -169,6 +186,7 @@ scoped_refptr<NGLayoutResult> NGBlockNode::Layout(
if (!CanUseNewLayout()) {
return RunOldLayout(constraint_space);
}
+
LayoutBlockFlow* block_flow =
box_->IsLayoutNGMixin() ? ToLayoutBlockFlow(box_) : nullptr;
NGLayoutInputNode first_child = FirstChild();
@@ -205,8 +223,26 @@ scoped_refptr<NGLayoutResult> NGBlockNode::Layout(
}
}
- layout_result =
- LayoutWithAlgorithm(Style(), *this, box_, constraint_space, break_token);
+ // This follows the code from LayoutBox::UpdateLogicalWidth
+ if (box_->NeedsPreferredWidthsRecalculation() &&
+ !box_->PreferredLogicalWidthsDirty()) {
+ // Laying out this object means that its containing block is also being
+ // laid out. This object is special, in that its min/max widths depend on
+ // the ancestry (min/max width calculation should ideally be strictly
+ // bottom-up, but that's not always the case), so since the containing
+ // block size may have changed, we need to recalculate the min/max widths
+ // of this object, and every child that has the same issue, recursively.
+ box_->SetPreferredLogicalWidthsDirty(kMarkOnlyThis);
+ // Since all this takes place during actual layout, instead of being part
+ // of min/max the width calculation machinery, we need to enter said
+ // machinery here, to make sure that what was dirtied is actualy
+ // recalculated. Leaving things dirty would mean that any subsequent
+ // dirtying of descendants would fail.
+ box_->ComputePreferredLogicalWidths();
+ }
+
+ layout_result = LayoutWithAlgorithm(*this, constraint_space, break_token,
+ /* ignored */ nullptr);
if (block_flow) {
block_flow->SetCachedLayoutResult(constraint_space, break_token,
layout_result);
@@ -241,33 +277,30 @@ MinMaxSize NGBlockNode::ComputeMinMaxSize(
WritingMode container_writing_mode,
const MinMaxSizeInput& input,
const NGConstraintSpace* constraint_space) {
+ bool is_orthogonal_flow_root =
+ !IsParallelWritingMode(container_writing_mode, Style().GetWritingMode());
+
MinMaxSize sizes;
- if (!CanUseNewLayout()) {
- // TODO(layout-ng): This could be somewhat optimized by directly calling
- // computeIntrinsicLogicalWidths, but that function is currently private.
- // Consider doing that if this becomes a performance issue.
- sizes.min_size = box_->ComputeLogicalWidthUsing(
- kMainOrPreferredSize, Length(kMinContent), LayoutUnit(),
- box_->ContainingBlock());
- sizes.max_size = box_->ComputeLogicalWidthUsing(
- kMainOrPreferredSize, Length(kMaxContent), LayoutUnit(),
- box_->ContainingBlock());
- return 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 && !box_->GetFrameView()->IsInPerformLayout())) {
+ return ComputeMinMaxSizeFromLegacy();
}
scoped_refptr<NGConstraintSpace> zero_constraint_space =
- NGConstraintSpaceBuilder(Style().GetWritingMode(),
- InitialContainingBlockSize())
- .SetTextDirection(Style().Direction())
- .SetIsIntermediateLayout(true)
- .SetFloatsBfcOffset(NGBfcOffset())
- .ToConstraintSpace(Style().GetWritingMode());
+ CreateConstraintSpaceBuilderForMinMax(*this).ToConstraintSpace(
+ Style().GetWritingMode());
+
+ 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);
- if (!constraint_space)
constraint_space = zero_constraint_space.get();
+ }
- if (!IsParallelWritingMode(container_writing_mode,
- Style().GetWritingMode())) {
+ if (is_orthogonal_flow_root) {
scoped_refptr<NGLayoutResult> layout_result = Layout(*constraint_space);
DCHECK_EQ(layout_result->Status(), NGLayoutResult::kSuccess);
NGBoxFragment fragment(
@@ -277,13 +310,18 @@ MinMaxSize NGBlockNode::ComputeMinMaxSize(
return sizes;
}
- // TODO(layout-ng): We need to make sure to use the right algorithm
- NGBlockLayoutAlgorithm minmax_algorithm(*this, *constraint_space);
base::Optional<MinMaxSize> maybe_sizes =
- minmax_algorithm.ComputeMinMaxSize(input);
+ ComputeMinMaxSizeWithAlgorithm(*this, *constraint_space,
+ /* break token */ nullptr, input);
if (maybe_sizes.has_value())
return *maybe_sizes;
+ 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 ComputeMinMaxSizeFromLegacy();
+ }
+
// Have to synthesize this value.
scoped_refptr<NGLayoutResult> layout_result = Layout(*zero_constraint_space);
NGBoxFragment min_fragment(
@@ -293,12 +331,9 @@ MinMaxSize NGBlockNode::ComputeMinMaxSize(
// Now, redo with infinite space for max_content
scoped_refptr<NGConstraintSpace> infinite_constraint_space =
- NGConstraintSpaceBuilder(Style().GetWritingMode(),
- InitialContainingBlockSize())
- .SetTextDirection(Style().Direction())
+ CreateConstraintSpaceBuilderForMinMax(*this)
.SetAvailableSize({LayoutUnit::Max(), LayoutUnit()})
.SetPercentageResolutionSize({LayoutUnit(), LayoutUnit()})
- .SetIsIntermediateLayout(true)
.ToConstraintSpace(Style().GetWritingMode());
layout_result = Layout(*infinite_constraint_space);
@@ -309,6 +344,20 @@ MinMaxSize NGBlockNode::ComputeMinMaxSize(
return sizes;
}
+MinMaxSize NGBlockNode::ComputeMinMaxSizeFromLegacy() const {
+ // TODO(layout-ng): This could be somewhat optimized by directly calling
+ // computeIntrinsicLogicalWidths, but that function is currently private.
+ // Consider doing that if this becomes a performance issue.
+ MinMaxSize sizes;
+ sizes.min_size =
+ box_->ComputeLogicalWidthUsing(kMainOrPreferredSize, Length(kMinContent),
+ LayoutUnit(), box_->ContainingBlock());
+ sizes.max_size =
+ box_->ComputeLogicalWidthUsing(kMainOrPreferredSize, Length(kMaxContent),
+ LayoutUnit(), box_->ContainingBlock());
+ return sizes;
+}
+
NGBoxStrut NGBlockNode::GetScrollbarSizes() const {
NGPhysicalBoxStrut sizes;
const ComputedStyle& style = box_->StyleRef();
@@ -359,7 +408,7 @@ bool NGBlockNode::CanUseNewLayout() const {
String NGBlockNode::ToString() const {
return String::Format("NGBlockNode: '%s'",
- GetLayoutObject()->DebugName().Ascii().data());
+ GetLayoutBox()->DebugName().Ascii().data());
}
void NGBlockNode::CopyFragmentDataToLayoutBox(
@@ -402,6 +451,9 @@ void NGBlockNode::CopyFragmentDataToLayoutBox(
intrinsic_content_logical_height -= border_scrollbar_padding.BlockSum();
box_->SetLogicalHeight(logical_height);
box_->SetIntrinsicContentLogicalHeight(intrinsic_content_logical_height);
+ // TODO(mstensho): This should always be done by the parent algorithm, since
+ // we may have auto margins, which only the parent is able to resolve. Remove
+ // the following line when all layout modes do this properly.
box_->SetMargin(ComputePhysicalMargins(constraint_space, Style()));
LayoutMultiColumnFlowThread* flow_thread = GetFlowThread(*box_);
@@ -521,16 +573,23 @@ void NGBlockNode::CopyChildFragmentPosition(
LayoutBlock* containing_block = layout_box->ContainingBlock();
// LegacyLayout flips vertical-rl horizontal coordinates before paint.
- // NGLayout flips X location for LegacyLayout compatibility.
- if (containing_block->StyleRef().IsFlippedBlocksWritingMode()) {
+ // NGLayout flips X location for LegacyLayout compatibility. horizontal_offset
+ // will be the offset from the left edge of the container to the left edge of
+ // the layout object, except when in vertical-rl: Then it will be the offset
+ // from the right edge of the container to the right edge of the layout
+ // object.
+ LayoutUnit horizontal_offset =
+ fragment.Offset().left + additional_offset.left;
+ bool has_flipped_x_axis =
+ containing_block->StyleRef().IsFlippedBlocksWritingMode();
+ if (has_flipped_x_axis) {
NGBoxStrut scrollbars = GetScrollbarSizes();
LayoutUnit container_width =
containing_block->Size().Width() - scrollbars.block_start;
- layout_box->SetX(container_width - fragment.Offset().left -
- additional_offset.left - fragment.Size().width);
- } else {
- layout_box->SetX(fragment.Offset().left + additional_offset.left);
+ horizontal_offset =
+ container_width - horizontal_offset - fragment.Size().width;
}
+ layout_box->SetX(horizontal_offset);
layout_box->SetY(fragment.Offset().top + additional_offset.top);
// Floats need an associated FloatingObject for painting.
@@ -538,8 +597,12 @@ void NGBlockNode::CopyChildFragmentPosition(
FloatingObject* floating_object =
ToLayoutBlockFlow(containing_block)->InsertFloatingObject(*layout_box);
floating_object->SetIsInPlacedTree(false);
- floating_object->SetX(fragment.Offset().left + additional_offset.left -
- layout_box->MarginLeft());
+ LayoutUnit horizontal_margin_edge_offset = horizontal_offset;
+ if (has_flipped_x_axis)
+ horizontal_margin_edge_offset -= layout_box->MarginRight();
+ else
+ horizontal_margin_edge_offset -= layout_box->MarginLeft();
+ floating_object->SetX(horizontal_margin_edge_offset);
floating_object->SetY(fragment.Offset().top + additional_offset.top -
layout_box->MarginTop());
floating_object->SetIsPlaced(true);
@@ -547,6 +610,23 @@ void NGBlockNode::CopyChildFragmentPosition(
}
}
+bool NGBlockNode::IsInlineLevel() const {
+ return GetLayoutBox()->IsInline();
+}
+
+bool NGBlockNode::IsAtomicInlineLevel() const {
+ // LayoutObject::IsAtomicInlineLevel() returns true for e.g., <img
+ // style="display: block">. Check IsInline() as well.
+ return GetLayoutBox()->IsAtomicInlineLevel() && GetLayoutBox()->IsInline();
+}
+
+bool NGBlockNode::UseLogicalBottomMarginEdgeForInlineBlockBaseline() const {
+ LayoutBox* layout_box = GetLayoutBox();
+ return layout_box->IsLayoutBlock() &&
+ ToLayoutBlock(layout_box)
+ ->UseLogicalBottomMarginEdgeForInlineBlockBaseline();
+}
+
scoped_refptr<NGLayoutResult> NGBlockNode::LayoutAtomicInline(
const NGConstraintSpace& parent_constraint_space,
FontBaseline baseline_type,
@@ -556,7 +636,7 @@ scoped_refptr<NGLayoutResult> NGBlockNode::LayoutAtomicInline(
// Request to compute baseline during the layout, except when we know the box
// would synthesize box-baseline.
- if (NGBaseline::ShouldPropagateBaselines(ToLayoutBox(GetLayoutObject()))) {
+ if (NGBaseline::ShouldPropagateBaselines(GetLayoutBox())) {
space_builder.AddBaselineRequest(
{NGBaselineAlgorithmType::kAtomicInline, baseline_type});
}
@@ -575,43 +655,57 @@ scoped_refptr<NGLayoutResult> NGBlockNode::LayoutAtomicInline(
scoped_refptr<NGLayoutResult> NGBlockNode::RunOldLayout(
const NGConstraintSpace& constraint_space) {
- LayoutUnit inline_size =
- Style().LogicalWidth().IsPercent()
- ? constraint_space.PercentageResolutionSize().inline_size
- : constraint_space.AvailableSize().inline_size;
- LayoutUnit block_size =
- Style().LogicalHeight().IsPercent()
- ? constraint_space.PercentageResolutionSize().block_size
- : constraint_space.AvailableSize().block_size;
- LayoutObject* containing_block = box_->ContainingBlock();
+ // This is an exit-point from LayoutNG to the legacy engine. This means that
+ // we need to be at a formatting context boundary, since NG and legacy don't
+ // cooperate on e.g. margin collapsing.
+ DCHECK(!box_->IsLayoutBlock() ||
+ ToLayoutBlock(box_)->CreatesNewFormattingContext());
+
WritingMode writing_mode = Style().GetWritingMode();
- bool parallel_writing_mode;
- if (!containing_block) {
- parallel_writing_mode = true;
- } else {
- parallel_writing_mode = IsParallelWritingMode(
- containing_block->StyleRef().GetWritingMode(), writing_mode);
- }
- if (parallel_writing_mode) {
- box_->SetOverrideContainingBlockContentLogicalWidth(inline_size);
- box_->SetOverrideContainingBlockContentLogicalHeight(block_size);
- } else {
- // OverrideContainingBlock should be in containing block writing mode.
- box_->SetOverrideContainingBlockContentLogicalWidth(block_size);
- box_->SetOverrideContainingBlockContentLogicalHeight(inline_size);
- }
+ const NGConstraintSpace* old_space =
+ box_->IsLayoutNGMixin() ? ToLayoutBlockFlow(box_)->CachedConstraintSpace()
+ : nullptr;
+ if (!old_space || box_->NeedsLayout() || *old_space != constraint_space) {
+ LayoutUnit inline_size =
+ Style().LogicalWidth().IsPercent()
+ ? constraint_space.PercentageResolutionSize().inline_size
+ : constraint_space.AvailableSize().inline_size;
+ LayoutUnit block_size =
+ Style().LogicalHeight().IsPercent()
+ ? constraint_space.PercentageResolutionSize().block_size
+ : constraint_space.AvailableSize().block_size;
+ LayoutObject* containing_block = box_->ContainingBlock();
+ bool parallel_writing_mode;
+ if (!containing_block) {
+ parallel_writing_mode = true;
+ } else {
+ parallel_writing_mode = IsParallelWritingMode(
+ containing_block->StyleRef().GetWritingMode(), writing_mode);
+ }
+ if (parallel_writing_mode) {
+ box_->SetOverrideContainingBlockContentLogicalWidth(inline_size);
+ box_->SetOverrideContainingBlockContentLogicalHeight(block_size);
+ } else {
+ // OverrideContainingBlock should be in containing block writing mode.
+ box_->SetOverrideContainingBlockContentLogicalWidth(block_size);
+ box_->SetOverrideContainingBlockContentLogicalHeight(inline_size);
+ }
- if (constraint_space.IsFixedSizeInline()) {
- box_->SetOverrideLogicalWidth(constraint_space.AvailableSize().inline_size);
- }
- if (constraint_space.IsFixedSizeBlock()) {
- box_->SetOverrideLogicalHeight(constraint_space.AvailableSize().block_size);
- }
+ if (constraint_space.IsFixedSizeInline()) {
+ box_->SetOverrideLogicalWidth(
+ constraint_space.AvailableSize().inline_size);
+ }
+ if (constraint_space.IsFixedSizeBlock()) {
+ box_->SetOverrideLogicalHeight(
+ constraint_space.AvailableSize().block_size);
+ }
+ box_->ComputeAndSetBlockDirectionMargins(box_->ContainingBlock());
- if (box_->IsLayoutNGMixin() && box_->NeedsLayout()) {
- ToLayoutBlockFlow(box_)->LayoutBlockFlow::UpdateBlockLayout(true);
- } else {
- box_->ForceLayout();
+ if (box_->IsLayoutNGMixin() && box_->NeedsLayout()) {
+ ToLayoutBlockFlow(box_)->LayoutBlockFlow::UpdateBlockLayout(true);
+ } else {
+ box_->ForceLayout();
+ }
}
NGLogicalSize box_size(box_->LogicalWidth(), box_->LogicalHeight());
// TODO(kojii): Implement use_first_line_style.
@@ -735,4 +829,13 @@ void NGBlockNode::SaveStaticOffsetForLegacy(
}
}
+void NGBlockNode::StoreMargins(const NGConstraintSpace& constraint_space,
+ const NGBoxStrut& margins) {
+ if (constraint_space.IsIntermediateLayout())
+ return;
+ NGPhysicalBoxStrut physical_margins = margins.ConvertToPhysical(
+ constraint_space.GetWritingMode(), constraint_space.Direction());
+ box_->SetMargin(physical_margins);
+}
+
} // 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 7120a177c1b..1872bc7a615 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
@@ -35,7 +35,8 @@ class CORE_EXPORT NGBlockNode final : public NGLayoutInputNode {
NGBreakToken* break_token = nullptr);
NGLayoutInputNode NextSibling() const;
- // Computes the value of min-content and max-content for this box.
+ // Computes the value of min-content and max-content for this node's border
+ // box.
// If the underlying layout algorithm's ComputeMinMaxSize returns
// no value, this function will synthesize these sizes using Layout with
// special constraint spaces -- infinite available size for max content, zero
@@ -44,17 +45,31 @@ class CORE_EXPORT NGBlockNode final : public NGLayoutInputNode {
// An optional constraint space may be supplied, which will be used to resolve
// percentage padding on this node, to set up the right min/max size
// contribution. This is typically desirable for the subtree root of the
- // min/max calculation (e.g. the node that will undergo shrink-to-fit). This
- // constraint space will not be passed on to children. If no constraint space
- // is specified, a zero-sized one will be used.
+ // min/max calculation (e.g. the node that will undergo shrink-to-fit). It is
+ // also used to provide provide a sensible available inline size when
+ // calculating min/max for orthogonal flows. This constraint space will not be
+ // passed on to children. If no constraint space is specified, a zero-sized
+ // one will be used.
+ // 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.
MinMaxSize ComputeMinMaxSize(WritingMode container_writing_mode,
const MinMaxSizeInput&,
const NGConstraintSpace* = nullptr);
+ MinMaxSize ComputeMinMaxSizeFromLegacy() const;
+
NGBoxStrut GetScrollbarSizes() const;
NGLayoutInputNode FirstChild() const;
+ bool IsInlineLevel() const;
+ bool IsAtomicInlineLevel() const;
+
+ // CSS defines certain cases to synthesize inline block baselines from box.
+ // See comments in UseLogicalBottomMarginEdgeForInlineBlockBaseline().
+ bool UseLogicalBottomMarginEdgeForInlineBlockBaseline() const;
+
// Layout an atomic inline; e.g., inline block.
scoped_refptr<NGLayoutResult> LayoutAtomicInline(const NGConstraintSpace&,
FontBaseline,
@@ -72,6 +87,9 @@ class CORE_EXPORT NGBlockNode final : public NGLayoutInputNode {
void SaveStaticOffsetForLegacy(const NGLogicalOffset&,
const LayoutObject* offset_container);
+ // Write back resolved margins to legacy.
+ void StoreMargins(const NGConstraintSpace&, const NGBoxStrut& margins);
+
static bool CanUseNewLayout(const LayoutBox&);
bool CanUseNewLayout() const;
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 202a5744538..b623795dfef 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
@@ -67,9 +67,9 @@ TEST_F(NGBlockNodeForTest, ChildFloatBeforeInline) {
)HTML");
NGBlockNode container(ToLayoutBox(GetLayoutObjectByElementId("container")));
NGLayoutInputNode child1 = container.FirstChild();
- EXPECT_TRUE(child1 && child1.IsBlock());
+ EXPECT_TRUE(child1 && child1.IsInline());
NGLayoutInputNode child2 = child1.NextSibling();
- EXPECT_TRUE(child2 && child2.IsBlock());
+ EXPECT_EQ(child2, nullptr);
}
TEST_F(NGBlockNodeForTest, ChildFloatAfterInline) {
@@ -97,7 +97,7 @@ TEST_F(NGBlockNodeForTest, ChildFloatOnly) {
)HTML");
NGBlockNode container(ToLayoutBox(GetLayoutObjectByElementId("container")));
NGLayoutInputNode child1 = container.FirstChild();
- EXPECT_TRUE(child1 && child1.IsBlock());
+ EXPECT_TRUE(child1 && child1.IsInline());
NGLayoutInputNode child2 = child1.NextSibling();
EXPECT_EQ(child2, nullptr);
}
@@ -114,7 +114,7 @@ TEST_F(NGBlockNodeForTest, ChildFloatWithSpaces) {
)HTML");
NGBlockNode container(ToLayoutBox(GetLayoutObjectByElementId("container")));
NGLayoutInputNode child1 = container.FirstChild();
- EXPECT_TRUE(child1 && child1.IsBlock());
+ EXPECT_TRUE(child1 && child1.IsInline());
NGLayoutInputNode child2 = child1.NextSibling();
EXPECT_EQ(child2, nullptr);
}
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 2f25a62eb2b..209816b0278 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
@@ -71,13 +71,10 @@ NGColumnLayoutAlgorithm::NGColumnLayoutAlgorithm(NGBlockNode node,
: NGLayoutAlgorithm(node, space, ToNGBlockBreakToken(break_token)) {}
scoped_refptr<NGLayoutResult> NGColumnLayoutAlgorithm::Layout() {
- base::Optional<MinMaxSize> min_max_size;
- if (NeedMinMaxSize(ConstraintSpace(), Style()))
- min_max_size = ComputeMinMaxSize(MinMaxSizeInput());
NGBoxStrut border_scrollbar_padding =
CalculateBorderScrollbarPadding(ConstraintSpace(), Node());
NGLogicalSize border_box_size =
- CalculateBorderBoxSize(ConstraintSpace(), Style(), min_max_size);
+ CalculateBorderBoxSize(ConstraintSpace(), Node());
NGLogicalSize content_box_size =
CalculateContentBoxSize(border_box_size, border_scrollbar_padding);
NGLogicalSize column_size = CalculateColumnSize(content_box_size);
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 5d5f59ec473..a01c253edd6 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
@@ -487,6 +487,7 @@ TEST_F(NGColumnLayoutAlgorithmTest, FloatInOneColumn) {
offset:0,0 size:320x100
offset:0,0 size:100x100
offset:0,0 size:75x100
+ offset:0,0 size:0x0
)DUMP";
EXPECT_EQ(expectation, dump);
}
@@ -517,6 +518,7 @@ TEST_F(NGColumnLayoutAlgorithmTest, TwoFloatsInOneColumn) {
offset:0,0 size:100x100
offset:0,0 size:15x100
offset:84,0 size:16x100
+ offset:0,0 size:0x0
)DUMP";
EXPECT_EQ(expectation, dump);
}
@@ -547,6 +549,7 @@ TEST_F(NGColumnLayoutAlgorithmTest, TwoFloatsInTwoColumns) {
offset:0,0 size:100x100
offset:0,0 size:15x100
offset:84,0 size:16x100
+ offset:0,0 size:0x0
offset:110,0 size:100x50
offset:0,0 size:15x50
offset:84,0 size:16x50
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space.cc
index e6c27f43071..f2a01834562 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_constraint_space.cc
@@ -157,7 +157,7 @@ scoped_refptr<NGConstraintSpace> NGConstraintSpace::CreateFromLayoutObject(
NGConstraintSpaceBuilder builder(writing_mode, initial_containing_block_size);
- if (!box.IsWritingModeRoot()) {
+ if (!box.IsWritingModeRoot() || box.IsGridItem()) {
// Add all types because we don't know which baselines will be requested.
FontBaseline baseline_type = box.StyleRef().GetFontBaseline();
bool synthesize_inline_block_baseline =
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 d3c783914e8..e66e4791e93 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
@@ -203,6 +203,12 @@ void NGContainerFragmentBuilder::GetAndClearOutOfFlowDescendantCandidates(
oof_positioned_candidates_.clear();
}
+void NGContainerFragmentBuilder::
+ MoveOutOfFlowDescendantCandidatesToDescendants() {
+ GetAndClearOutOfFlowDescendantCandidates(&oof_positioned_descendants_,
+ nullptr);
+}
+
#ifndef NDEBUG
String NGContainerFragmentBuilder::ToString() const {
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 448360170e1..ce44f7a02ba 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
@@ -116,6 +116,10 @@ class CORE_EXPORT NGContainerFragmentBuilder : public NGBaseFragmentBuilder {
Vector<NGOutOfFlowPositionedDescendant>* descendant_candidates,
const LayoutObject* container);
+ // Utility routine to move all OOF descendant candidates to descendants.
+ // Use if fragment cannot hold any OOF children.
+ void MoveOutOfFlowDescendantCandidatesToDescendants();
+
NGContainerFragmentBuilder& SetIsPushedByFloats() {
is_pushed_by_floats_ = true;
return *this;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_exclusion.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_exclusion.cc
deleted file mode 100644
index d6e3465f4ab..00000000000
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_exclusion.cc
+++ /dev/null
@@ -1,13 +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/layout/ng/ng_exclusion.h"
-
-namespace blink {
-
-bool NGExclusion::operator==(const NGExclusion& other) const {
- return std::tie(other.rect, other.type) == std::tie(rect, type);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_exclusion.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_exclusion.h
deleted file mode 100644
index a22f4409e6a..00000000000
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_exclusion.h
+++ /dev/null
@@ -1,54 +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 NGExclusion_h
-#define NGExclusion_h
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/ng/geometry/ng_bfc_rect.h"
-#include "third_party/blink/renderer/core/style/computed_style_constants.h"
-#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
-
-namespace blink {
-
-class LayoutBox;
-
-struct CORE_EXPORT NGExclusionShapeData {
- NGExclusionShapeData(const LayoutBox* layout_box,
- const NGBoxStrut& margins,
- const NGBoxStrut& shape_insets)
- : layout_box(layout_box), margins(margins), shape_insets(shape_insets) {}
-
- const LayoutBox* layout_box;
- const NGBoxStrut margins;
- const NGBoxStrut shape_insets;
-};
-
-// Struct that represents an exclusion. This currently is just a float but
-// we've named it an exclusion to potentially support other types in the future.
-struct CORE_EXPORT NGExclusion : public RefCounted<NGExclusion> {
- static scoped_refptr<NGExclusion> Create(
- const NGBfcRect& rect,
- const EFloat type,
- std::unique_ptr<NGExclusionShapeData> shape_data = nullptr) {
- return base::AdoptRef(new NGExclusion(rect, type, std::move(shape_data)));
- }
-
- const NGBfcRect rect;
- const EFloat type;
- const std::unique_ptr<NGExclusionShapeData> shape_data;
-
- bool operator==(const NGExclusion& other) const;
- bool operator!=(const NGExclusion& other) const { return !(*this == other); }
-
- private:
- NGExclusion(const NGBfcRect& rect,
- const EFloat type,
- std::unique_ptr<NGExclusionShapeData> shape_data)
- : rect(rect), type(type), shape_data(std::move(shape_data)) {}
-};
-
-} // namespace blink
-
-#endif // NGExclusion_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/ng_flex_layout_algorithm.cc
index 4445b9b5f0a..c6e35dfa207 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_flex_layout_algorithm.cc
@@ -26,75 +26,91 @@ scoped_refptr<NGLayoutResult> NGFlexLayoutAlgorithm::Layout() {
DCHECK(!NeedMinMaxSize(ConstraintSpace(), Style()))
<< "Don't support that yet";
- LayoutUnit container_logical_width = ComputeInlineSizeForFragment(
- ConstraintSpace(), Style(), /* MinMaxSize */ base::nullopt);
+ LayoutUnit flex_container_border_box_inline_size =
+ ComputeInlineSizeForFragment(ConstraintSpace(), Node());
+ LayoutUnit flex_container_content_inline_size =
+ flex_container_border_box_inline_size -
+ CalculateBorderScrollbarPadding(ConstraintSpace(), Node()).InlineSum();
Vector<FlexItem> flex_items;
- for (NGLayoutInputNode child = Node().FirstChild(); child;
- child = child.NextSibling()) {
+ for (NGLayoutInputNode generic_child = Node().FirstChild(); generic_child;
+ generic_child = generic_child.NextSibling()) {
+ NGBlockNode child = ToNGBlockNode(generic_child);
if (child.IsOutOfFlowPositioned())
continue;
- // Assume row flexbox with no orthogonal items, which lets us just use
- // MinMaxSize for flex base size. An orthogonal item would need full layout.
- // TODO(layout-ng): Now that ComputeMinMaxSize takes a writing mode, this
- // should be easy to fix by just passing an appropriate constraint space to
- // ComputeMinMaxSize.
- DCHECK(IsParallelWritingMode(Node().Style().GetWritingMode(),
- child.Style().GetWritingMode()))
- << "Orthogonal items aren't supported yet.";
- MinMaxSizeInput zero_input;
- MinMaxSize min_max_sizes =
- child.ComputeMinMaxSize(ConstraintSpace().GetWritingMode(), zero_input);
- LayoutUnit flex_base_content_size;
+ NGConstraintSpaceBuilder space_builder(ConstraintSpace());
+ // TODO(dgrogan): Set the percentage size also, which is possibly
+ // flex_container_content_inline_size. Also change NGSizeIndefinite to
+ // container size if it's definite.
+ space_builder.SetAvailableSize(
+ NGLogicalSize{flex_container_content_inline_size, NGSizeIndefinite});
+ scoped_refptr<NGConstraintSpace> child_space =
+ space_builder.ToConstraintSpace(child.Style().GetWritingMode());
+
+ LayoutUnit main_axis_border_and_padding =
+ ComputeBorders(*child_space, child.Style()).InlineSum() +
+ ComputePadding(*child_space, child.Style()).InlineSum();
+ // ComputeMinMaxSize will layout the child if it has an orthogonal writing
+ // mode. MinMaxSize will be in the container's inline direction.
+ MinMaxSizeInput zero_input;
+ MinMaxSize min_max_sizes_border_box = child.ComputeMinMaxSize(
+ ConstraintSpace().GetWritingMode(), zero_input, child_space.get());
+
+ // Spec calls this "flex base size"
+ // https://www.w3.org/TR/css-flexbox-1/#algo-main-item
+ // Blink's FlexibleBoxAlgorithm expects it to be content + scrollbar widths,
+ // but no padding or border.
+ LayoutUnit flex_base_border_box;
if (child.Style().FlexBasis().IsAuto() && child.Style().Width().IsAuto()) {
- flex_base_content_size = min_max_sizes.max_size;
+ flex_base_border_box = min_max_sizes_border_box.max_size;
} else {
Length length_to_resolve = child.Style().FlexBasis();
if (length_to_resolve.IsAuto())
length_to_resolve = child.Style().Width();
DCHECK(!length_to_resolve.IsAuto());
- // TODO(dgrogan): ResolveInlineLength will handle all the types?
- DCHECK(length_to_resolve.IsFixed())
- << "We only support auto and fixed flex base sizes";
- flex_base_content_size = LayoutUnit(length_to_resolve.Value());
+ // TODO(dgrogan): Use ResolveBlockLength here for column flex boxes.
+
+ flex_base_border_box = ResolveInlineLength(
+ *child_space, child.Style(), min_max_sizes_border_box,
+ length_to_resolve, LengthResolveType::kContentSize,
+ LengthResolvePhase::kLayout);
}
- NGConstraintSpaceBuilder space_builder(ConstraintSpace());
- // TODO(dgrogan): Set the percentage size also.
- space_builder.SetAvailableSize(
- NGLogicalSize{container_logical_width, NGSizeIndefinite});
- scoped_refptr<NGConstraintSpace> child_space =
- space_builder.ToConstraintSpace(child.Style().GetWritingMode());
+ LayoutUnit flex_base_content_size =
+ flex_base_border_box - main_axis_border_and_padding;
- LayoutUnit main_axis_border_and_padding =
- ComputeBorders(*child_space, child.Style()).InlineSum() +
- ComputePadding(*child_space, child.Style()).InlineSum();
LayoutUnit main_axis_margin =
ComputeMarginsForSelf(*child_space, child.Style()).InlineSum();
// TODO(dgrogan): When child has a min/max-{width,height} set, call
// Resolve{Inline,Block}Length here with child's style and constraint space.
- // Fill this in with the results.
+ // Pass kMinSize, kMaxSize as appropriate.
+ // Further, min-width:auto has special meaning for flex items. We'll need to
+ // calculate that here by either extracting the logic from legacy or
+ // reimplementing. When resolved, pass it here.
+ // https://www.w3.org/TR/css-flexbox-1/#min-size-auto
MinMaxSize min_max_sizes_in_main_axis_direction{LayoutUnit(),
LayoutUnit::Max()};
- flex_items.emplace_back(ToLayoutBox(Node().GetLayoutObject()),
- flex_base_content_size,
+ flex_items.emplace_back(child.GetLayoutBox(), flex_base_content_size,
min_max_sizes_in_main_axis_direction,
main_axis_border_and_padding, main_axis_margin);
flex_items.back().ng_input_node = child;
}
- FlexLayoutAlgorithm algorithm(&Style(), container_logical_width, flex_items);
+ FlexLayoutAlgorithm algorithm(&Style(), flex_container_content_inline_size,
+ flex_items);
NGBoxStrut borders_scrollbar_padding =
CalculateBorderScrollbarPadding(ConstraintSpace(), Node());
LayoutUnit main_axis_offset = borders_scrollbar_padding.InlineSum();
LayoutUnit cross_axis_offset = borders_scrollbar_padding.BlockSum();
FlexLine* line;
- while ((line = algorithm.ComputeNextFlexLine(container_logical_width))) {
- line->SetContainerMainInnerSize(container_logical_width);
+ while ((line = algorithm.ComputeNextFlexLine(
+ flex_container_content_inline_size))) {
+ // TODO(dgrogan): This parameter is more complicated for columns.
+ line->SetContainerMainInnerSize(flex_container_content_inline_size);
line->FreezeInflexibleItems();
while (!line->ResolveFlexibleLengths()) {
continue;
@@ -104,7 +120,9 @@ scoped_refptr<NGLayoutResult> NGFlexLayoutAlgorithm::Layout() {
NGConstraintSpaceBuilder space_builder(ConstraintSpace());
// TODO(dgrogan): Set the percentage size also.
space_builder.SetAvailableSize(
- {flex_item.flexed_content_size, NGSizeIndefinite});
+ {flex_item.flexed_content_size +
+ flex_item.main_axis_border_and_padding,
+ NGSizeIndefinite});
space_builder.SetIsFixedSizeInline(true);
scoped_refptr<NGConstraintSpace> child_space =
space_builder.ToConstraintSpace(
@@ -113,6 +131,9 @@ scoped_refptr<NGLayoutResult> NGFlexLayoutAlgorithm::Layout() {
flex_item.ng_input_node.Layout(*child_space, nullptr /*break token*/);
flex_item.cross_axis_size =
flex_item.layout_result->PhysicalFragment()->Size().height;
+ // TODO(dgrogan): Port logic from
+ // LayoutFlexibleBox::CrossAxisIntrinsicExtentForChild?
+ flex_item.cross_axis_intrinsic_size = flex_item.cross_axis_size;
}
// cross_axis_offset is updated in each iteration of the loop, for passing
// in to the next iteration.
@@ -124,7 +145,17 @@ scoped_refptr<NGLayoutResult> NGFlexLayoutAlgorithm::Layout() {
flex_item.layout_result,
{flex_item.desired_location.X(), flex_item.desired_location.Y()});
}
+
+ // TODO(dgrogan): For column flex containers, keep track of tallest flex
+ // line and pass to ComputeBlockSizeForFragment as content_size.
}
+ LayoutUnit intrinsic_block_content_size = cross_axis_offset;
+ LayoutUnit intrinsic_block_size =
+ intrinsic_block_content_size + borders_scrollbar_padding.BlockSum();
+ LayoutUnit block_size = ComputeBlockSizeForFragment(
+ ConstraintSpace(), Style(), intrinsic_block_size);
+ container_builder_.SetBlockSize(block_size);
+ container_builder_.SetInlineSize(flex_container_border_box_inline_size);
return container_builder_.ToBoxFragment();
}
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 0adf9fbfd3b..c6d40fe1f63 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_floats_utils.h"
+#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/min_max_size.h"
#include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
@@ -214,13 +215,19 @@ LayoutUnit ComputeInlineSizeForUnpositionedFloat(
// because NG cannot figure out the size of such objects on its own,
// especially not for tables.
if (is_same_writing_mode && unpositioned_float->node.CanUseNewLayout()) {
- base::Optional<MinMaxSize> min_max_size;
- if (NeedMinMaxSize(*space.get(), style)) {
- MinMaxSizeInput zero_input; // Floats do not intrude into floats.
- min_max_size = unpositioned_float->node.ComputeMinMaxSize(
- style.GetWritingMode(), zero_input);
- }
- return ComputeInlineSizeForFragment(*space.get(), style, min_max_size);
+ return ComputeInlineSizeForFragment(*space.get(), unpositioned_float->node);
+ }
+
+ // Here we need to lay out the float. However, it is possible that we are
+ // not inside Layout, in which case we may not be able to actually lay out
+ // the node. Instead, we have to fallback to legacy sizing.
+ if (!unpositioned_float->node.GetLayoutBox()
+ ->GetFrameView()
+ ->IsInPerformLayout()) {
+ LayoutBox* box = unpositioned_float->node.GetLayoutBox();
+ LayoutBox::LogicalExtentComputedValues values;
+ box->ComputeLogicalWidth(values);
+ return values.extent_;
}
// A float which has a different writing mode can't fragment, and we
@@ -302,8 +309,8 @@ NGPositionedFloat PositionFloat(LayoutUnit origin_block_offset,
// Add the float as an exclusion.
scoped_refptr<NGExclusion> exclusion = CreateExclusion(
float_fragment, float_margin_bfc_offset, unpositioned_float->margins,
- ToLayoutBox(unpositioned_float->node.GetLayoutObject()),
- *unpositioned_float, parent_space, parent_space.Direction(),
+ unpositioned_float->node.GetLayoutBox(), *unpositioned_float,
+ parent_space, parent_space.Direction(),
unpositioned_float->IsRight() ? EFloat::kRight : EFloat::kLeft);
exclusion_space->Add(std::move(exclusion));
@@ -339,6 +346,10 @@ void AddUnpositionedFloat(
Vector<scoped_refptr<NGUnpositionedFloat>>* unpositioned_floats,
NGContainerFragmentBuilder* fragment_builder,
scoped_refptr<NGUnpositionedFloat> unpositioned_float) {
+ // The same float node should not be added more than once.
+ DCHECK(
+ !RemoveUnpositionedFloat(unpositioned_floats, unpositioned_float->node));
+
if (fragment_builder && !fragment_builder->BfcOffset()) {
fragment_builder->AddAdjoiningFloatTypes(
unpositioned_float->IsLeft() ? kFloatTypeLeft : kFloatTypeRight);
@@ -346,6 +357,19 @@ void AddUnpositionedFloat(
unpositioned_floats->push_back(std::move(unpositioned_float));
}
+bool RemoveUnpositionedFloat(
+ Vector<scoped_refptr<NGUnpositionedFloat>>* unpositioned_floats,
+ NGBlockNode float_node) {
+ for (scoped_refptr<NGUnpositionedFloat>& unpositioned_float :
+ *unpositioned_floats) {
+ if (unpositioned_float->node == float_node) {
+ unpositioned_floats->erase(&unpositioned_float);
+ return true;
+ }
+ }
+ return false;
+}
+
NGFloatTypes ToFloatTypes(EClear clear) {
switch (clear) {
default:
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_floats_utils.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_floats_utils.h
index 10973f6693a..ffd1b872d72 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_floats_utils.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_floats_utils.h
@@ -13,6 +13,7 @@
namespace blink {
+class NGBlockNode;
class NGConstraintSpace;
class NGContainerFragmentBuilder;
class NGExclusionSpace;
@@ -59,6 +60,11 @@ void AddUnpositionedFloat(
NGContainerFragmentBuilder* fragment_builder,
scoped_refptr<NGUnpositionedFloat> unpositioned_float);
+// Remove a pending float from the list.
+bool RemoveUnpositionedFloat(
+ Vector<scoped_refptr<NGUnpositionedFloat>>* unpositioned_floats,
+ NGBlockNode float_node);
+
NGFloatTypes ToFloatTypes(EClear clear);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.cc
index 028a6d2283e..00f5fbe8cec 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_fragment_builder.cc
@@ -44,7 +44,7 @@ NGFragmentBuilder::NGFragmentBuilder(NGLayoutInputNode node,
TextDirection direction)
: NGContainerFragmentBuilder(style, writing_mode, direction),
node_(node),
- layout_object_(node.GetLayoutObject()),
+ layout_object_(node.GetLayoutBox()),
box_type_(NGPhysicalFragment::NGBoxType::kNormalBox),
is_old_layout_root_(false),
did_break_(false) {}
@@ -69,10 +69,20 @@ NGFragmentBuilder& NGFragmentBuilder::SetIntrinsicBlockSize(
}
NGFragmentBuilder& NGFragmentBuilder::SetPadding(const NGBoxStrut& padding) {
+ DCHECK_NE(BoxType(), NGPhysicalFragment::kInlineBox);
padding_ = padding;
return *this;
}
+NGFragmentBuilder& NGFragmentBuilder::SetPadding(
+ const NGLineBoxStrut& padding) {
+ DCHECK_EQ(BoxType(), NGPhysicalFragment::kInlineBox);
+ // Convert to flow-relative, because ToInlineBoxFragment() will convert
+ // the padding to physical coordinates using flow-relative writing-mode.
+ padding_ = NGBoxStrut(padding, IsFlippedLinesWritingMode(GetWritingMode()));
+ return *this;
+}
+
NGContainerFragmentBuilder& NGFragmentBuilder::AddChild(
scoped_refptr<NGPhysicalFragment> child,
const NGLogicalOffset& child_offset) {
@@ -253,16 +263,29 @@ EBreakBetween NGFragmentBuilder::JoinedBreakBetweenValue(
}
scoped_refptr<NGLayoutResult> NGFragmentBuilder::ToBoxFragment() {
+ DCHECK_NE(BoxType(), NGPhysicalFragment::kInlineBox);
+ return ToBoxFragment(GetWritingMode());
+}
+
+scoped_refptr<NGLayoutResult> NGFragmentBuilder::ToInlineBoxFragment() {
+ // The logical coordinate for inline box uses line-relative writing-mode, not
+ // flow-relative.
+ DCHECK_EQ(BoxType(), NGPhysicalFragment::kInlineBox);
+ return ToBoxFragment(ToLineWritingMode(GetWritingMode()));
+}
+
+scoped_refptr<NGLayoutResult> NGFragmentBuilder::ToBoxFragment(
+ WritingMode block_or_line_writing_mode) {
DCHECK_EQ(offsets_.size(), children_.size());
NGPhysicalSize physical_size = Size().ConvertToPhysical(GetWritingMode());
- NGPhysicalOffsetRect contents_visual_rect({}, physical_size);
+ NGPhysicalOffsetRect contents_ink_overflow({}, physical_size);
for (size_t i = 0; i < children_.size(); ++i) {
NGPhysicalFragment* child = children_[i].get();
child->SetOffset(offsets_[i].ConvertToPhysical(
- GetWritingMode(), Direction(), physical_size, child->Size()));
- child->PropagateContentsVisualRect(&contents_visual_rect);
+ block_or_line_writing_mode, Direction(), physical_size, child->Size()));
+ child->PropagateContentsInkOverflow(&contents_ink_overflow);
}
scoped_refptr<NGBreakToken> break_token;
@@ -287,7 +310,7 @@ scoped_refptr<NGLayoutResult> NGFragmentBuilder::ToBoxFragment() {
layout_object_, Style(), style_variant_, physical_size, children_,
padding_.ConvertToPhysical(GetWritingMode(), Direction())
.SnapToDevicePixels(),
- contents_visual_rect, baselines_, BoxType(), is_old_layout_root_,
+ contents_ink_overflow, baselines_, BoxType(), is_old_layout_root_,
border_edges_.ToPhysical(GetWritingMode()), std::move(break_token)));
Vector<NGPositionedFloat> positioned_floats;
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 478b43e42d4..c1512e5c609 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
@@ -41,6 +41,7 @@ class CORE_EXPORT NGFragmentBuilder final : public NGContainerFragmentBuilder {
NGFragmentBuilder& SetIntrinsicBlockSize(LayoutUnit);
NGFragmentBuilder& SetPadding(const NGBoxStrut&);
+ NGFragmentBuilder& SetPadding(const NGLineBoxStrut&);
using NGContainerFragmentBuilder::AddChild;
@@ -122,6 +123,7 @@ class CORE_EXPORT NGFragmentBuilder final : public NGContainerFragmentBuilder {
// Creates the fragment. Can only be called once.
scoped_refptr<NGLayoutResult> ToBoxFragment();
+ scoped_refptr<NGLayoutResult> ToInlineBoxFragment();
scoped_refptr<NGLayoutResult> Abort(NGLayoutResult::NGLayoutResultStatus);
@@ -178,6 +180,8 @@ class CORE_EXPORT NGFragmentBuilder final : public NGContainerFragmentBuilder {
LayoutObject* GetLayoutObject() { return layout_object_; }
private:
+ scoped_refptr<NGLayoutResult> ToBoxFragment(WritingMode);
+
NGLayoutInputNode node_;
LayoutObject* layout_object_;
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 63cb0d76d03..6c457155401 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h"
+#include "third_party/blink/renderer/core/layout/intrinsic_sizing_info.h"
#include "third_party/blink/renderer/core/layout/layout_replaced.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/min_max_size.h"
@@ -95,8 +96,8 @@ bool NGLayoutInputNode::IsListMarker() const {
return IsBlock() && box_->IsLayoutNGListMarker();
}
-bool NGLayoutInputNode::IsAnonymous() const {
- return box_->IsAnonymous();
+bool NGLayoutInputNode::IsAnonymousBlock() const {
+ return box_->IsAnonymousBlock();
}
bool NGLayoutInputNode::IsQuirkyContainer() const {
@@ -182,14 +183,14 @@ NGPhysicalSize NGLayoutInputNode::InitialContainingBlockSize() const {
LayoutUnit(icb_size.Height())};
}
-LayoutObject* NGLayoutInputNode::GetLayoutObject() const {
- return box_;
-}
-
const ComputedStyle& NGLayoutInputNode::Style() const {
return box_->StyleRef();
}
+bool NGLayoutInputNode::ShouldApplySizeContainment() const {
+ return box_->ShouldApplySizeContainment();
+}
+
String NGLayoutInputNode::ToString() const {
return IsInline() ? ToNGInlineNode(*this).ToString()
: ToNGBlockNode(*this).ToString();
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 4ac0d3ec824..c19c680d819 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
@@ -60,7 +60,7 @@ class CORE_EXPORT NGLayoutInputNode {
bool ShouldBeConsideredAsReplaced() const;
bool IsListItem() const;
bool IsListMarker() const;
- bool IsAnonymous() const;
+ bool IsAnonymousBlock() const;
// If the node is a quirky container for margin collapsing, see:
// https://html.spec.whatwg.org/#margin-collapsing-quirks
@@ -72,6 +72,7 @@ class CORE_EXPORT NGLayoutInputNode {
// Performs layout on this input node, will return the layout result.
scoped_refptr<NGLayoutResult> Layout(const NGConstraintSpace&, NGBreakToken*);
+ // Returns border box.
MinMaxSize ComputeMinMaxSize(WritingMode,
const MinMaxSizeInput&,
const NGConstraintSpace* = nullptr);
@@ -94,10 +95,12 @@ class CORE_EXPORT NGLayoutInputNode {
NGPhysicalSize InitialContainingBlockSize() const;
// Returns the LayoutObject which is associated with this node.
- LayoutObject* GetLayoutObject() const;
+ LayoutBox* GetLayoutBox() const { return box_; };
const ComputedStyle& Style() const;
+ bool ShouldApplySizeContainment() const;
+
String ToString() const;
explicit operator bool() const { return box_ != nullptr; }
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_test.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_test.h
index 7f881af1fa1..f0eb0962f8c 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_test.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_layout_test.h
@@ -10,7 +10,7 @@
namespace blink {
-// The NGLayoutTest is intended to let all NGFooTest classes easiy inherit
+// The NGLayoutTest is intended to let all NGFooTest classes easily inherit
// ScopedLayoutNGForTest as well as RenderingTest. The ScopedLayoutNGForTest
// ensures original settings are restored for other tests.
// See http://crbug.com/769541 for more details.
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 06afd4f1d9f..9a32ed00bee 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
@@ -282,7 +282,9 @@ MinMaxSize ComputeMinAndMaxContentContribution(
Length inline_size = writing_mode == WritingMode::kHorizontalTb
? style.Width()
: style.Height();
- if (inline_size.IsAuto() || inline_size.IsPercentOrCalc()) {
+ if (inline_size.IsAuto() || inline_size.IsPercentOrCalc() ||
+ inline_size.GetType() == kFillAvailable ||
+ inline_size.GetType() == kFitContent) {
CHECK(min_and_max.has_value());
computed_sizes = *min_and_max;
} else {
@@ -337,6 +339,20 @@ MinMaxSize ComputeMinAndMaxContentContribution(
NGLayoutInputNode node,
const MinMaxSizeInput& input,
const NGConstraintSpace* constraint_space) {
+ LayoutBox* box = node.GetLayoutBox();
+ if (IsParallelWritingMode(writing_mode, node.Style().GetWritingMode())) {
+ if (!box->PreferredLogicalWidthsDirty()) {
+ return {box->MinPreferredLogicalWidth(), box->MaxPreferredLogicalWidth()};
+ }
+ // Tables are special; even if a width is specified, they may end up being
+ // sized different. So we just always let the table code handle this.
+ // Replaced elements may size themselves using aspect ratios and block
+ // sizes, so we pass that on as well.
+ if (box->IsTable() || box->IsTablePart() || box->IsLayoutReplaced()) {
+ return {box->MinPreferredLogicalWidth(), box->MaxPreferredLogicalWidth()};
+ }
+ }
+
base::Optional<MinMaxSize> minmax;
if (NeedMinMaxSizeForContentContribution(writing_mode, node.Style())) {
scoped_refptr<NGConstraintSpace> adjusted_constraint_space;
@@ -348,7 +364,10 @@ MinMaxSize ComputeMinAndMaxContentContribution(
// definition.
NGConstraintSpaceBuilder builder(*constraint_space);
builder.SetAvailableSize(constraint_space->AvailableSize())
+ .SetPercentageResolutionSize(
+ constraint_space->PercentageResolutionSize())
.SetFloatsBfcOffset(NGBfcOffset())
+ .SetIsNewFormattingContext(node.CreatesNewFormattingContext())
.SetIsShrinkToFit(true);
adjusted_constraint_space =
builder.ToConstraintSpace(node.Style().GetWritingMode());
@@ -357,21 +376,53 @@ MinMaxSize ComputeMinAndMaxContentContribution(
minmax = node.ComputeMinMaxSize(writing_mode, input, constraint_space);
}
- return ComputeMinAndMaxContentContribution(writing_mode, node.Style(),
- minmax);
+ MinMaxSize sizes =
+ ComputeMinAndMaxContentContribution(writing_mode, node.Style(), minmax);
+ if (IsParallelWritingMode(writing_mode, node.Style().GetWritingMode()))
+ box->SetPreferredLogicalWidthsFromNG(sizes);
+ return sizes;
}
-LayoutUnit ComputeInlineSizeForFragment(
- const NGConstraintSpace& space,
- const ComputedStyle& style,
- const base::Optional<MinMaxSize>& min_and_max) {
+LayoutUnit ComputeInlineSizeForFragment(const NGConstraintSpace& space,
+ NGLayoutInputNode node,
+ const MinMaxSize* override_minmax) {
if (space.IsFixedSizeInline())
return space.AvailableSize().inline_size;
+ const ComputedStyle& style = node.Style();
Length logical_width = style.LogicalWidth();
if (logical_width.IsAuto() && space.IsShrinkToFit())
logical_width = Length(kFitContent);
+ LayoutBox* box = node.GetLayoutBox();
+ if (!box->PreferredLogicalWidthsDirty() && !override_minmax) {
+ if (logical_width.GetType() == kFitContent) {
+ // This is not as easy as {min, max}.ShrinkToFit() because we also need
+ // to subtract inline margins from the available size. The code in
+ // ResolveInlineLength knows how to handle that, just call that.
+
+ MinMaxSize min_and_max = {box->MinPreferredLogicalWidth(),
+ box->MaxPreferredLogicalWidth()};
+ return ResolveInlineLength(space, style, min_and_max, logical_width,
+ LengthResolveType::kContentSize,
+ LengthResolvePhase::kLayout);
+ }
+ if (logical_width.GetType() == kMinContent)
+ return box->MinPreferredLogicalWidth();
+ if (logical_width.GetType() == kMaxContent)
+ return box->MaxPreferredLogicalWidth();
+ }
+
+ base::Optional<MinMaxSize> min_and_max;
+ if (NeedMinMaxSize(space, style)) {
+ if (override_minmax) {
+ min_and_max = *override_minmax;
+ } else {
+ min_and_max = node.ComputeMinMaxSize(space.GetWritingMode(),
+ MinMaxSizeInput(), &space);
+ }
+ }
+
LayoutUnit extent = ResolveInlineLength(
space, style, min_and_max, logical_width, LengthResolveType::kContentSize,
LengthResolvePhase::kLayout);
@@ -649,11 +700,11 @@ NGBoxStrut ComputePadding(const NGConstraintSpace& constraint_space,
return padding;
}
-void ApplyAutoMargins(const ComputedStyle& style,
- const ComputedStyle& containing_block_style,
- LayoutUnit available_inline_size,
- LayoutUnit inline_size,
- NGBoxStrut* margins) {
+void ResolveInlineMargins(const ComputedStyle& style,
+ const ComputedStyle& containing_block_style,
+ LayoutUnit available_inline_size,
+ LayoutUnit inline_size,
+ NGBoxStrut* margins) {
DCHECK(margins) << "Margins cannot be NULL here";
const LayoutUnit used_space = inline_size + margins->InlineSum();
const LayoutUnit available_space = available_inline_size - used_space;
@@ -742,6 +793,14 @@ LayoutUnit LineOffsetForTextAlign(ETextAlign text_align,
}
}
+LayoutUnit InlineOffsetForTextAlign(const ComputedStyle& container_style,
+ LayoutUnit space_left) {
+ TextDirection direction = container_style.Direction();
+ LayoutUnit line_offset = LineOffsetForTextAlign(
+ container_style.GetTextAlign(), direction, space_left, LayoutUnit());
+ return IsLtr(direction) ? line_offset : space_left - line_offset;
+}
+
LayoutUnit ConstrainByMinMax(LayoutUnit length,
LayoutUnit min,
LayoutUnit max) {
@@ -759,9 +818,9 @@ NGBoxStrut CalculateBorderScrollbarPadding(
if (constraint_space.IsAnonymous())
return NGBoxStrut();
NGBoxStrut border_intrinsic_padding;
- if (node.GetLayoutObject()->IsTableCell()) {
+ if (node.GetLayoutBox()->IsTableCell()) {
// Use values calculated by the table layout code
- const LayoutTableCell* cell = ToLayoutTableCell(node.GetLayoutObject());
+ const LayoutTableCell* cell = ToLayoutTableCell(node.GetLayoutBox());
// TODO(karlo): intrinsic padding can sometimes be negative; that
// seems insane, but works in the old code; in NG it trips
// DCHECKs.
@@ -776,6 +835,14 @@ NGBoxStrut CalculateBorderScrollbarPadding(
node.GetScrollbarSizes();
}
+NGLogicalSize CalculateBorderBoxSize(const NGConstraintSpace& constraint_space,
+ const NGBlockNode& node,
+ LayoutUnit block_content_size) {
+ return NGLogicalSize(ComputeInlineSizeForFragment(constraint_space, node),
+ ComputeBlockSizeForFragment(
+ constraint_space, node.Style(), block_content_size));
+}
+
NGLogicalSize CalculateContentBoxSize(
const NGLogicalSize border_box_size,
const NGBoxStrut& border_scrollbar_padding) {
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 2960d4236fe..bfabf58d634 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
@@ -50,8 +50,10 @@ CORE_EXPORT bool NeedMinMaxSize(const ComputedStyle&);
CORE_EXPORT bool NeedMinMaxSizeForContentContribution(WritingMode mode,
const ComputedStyle&);
-// Convert an inline-axis length to a layout unit using the given constraint
-// space.
+// Resolve means translate a Length to a LayoutUnit, using parent info
+// (represented by ConstraintSpace) as necessary for things like percents.
+//
+// MinMaxSize is used only when the length is intrinsic (fit-content, etc)
CORE_EXPORT LayoutUnit ResolveInlineLength(const NGConstraintSpace&,
const ComputedStyle&,
const base::Optional<MinMaxSize>&,
@@ -59,8 +61,8 @@ CORE_EXPORT LayoutUnit ResolveInlineLength(const NGConstraintSpace&,
LengthResolveType,
LengthResolvePhase);
-// Convert a block-axis length to a layout unit using the given constraint
-// space and content size.
+// Same as ResolveInlineLength, except here content_size roughly plays the part
+// of MinMaxSize.
CORE_EXPORT LayoutUnit ResolveBlockLength(const NGConstraintSpace&,
const ComputedStyle&,
const Length&,
@@ -103,17 +105,16 @@ MinMaxSize ComputeMinAndMaxContentContribution(
const MinMaxSizeInput& input,
const NGConstraintSpace* space = nullptr);
-// Resolves the given length to a layout unit, constraining it by the min
-// logical width and max logical width properties from the ComputedStyle
-// object.
+// Resolves the computed value in style.logicalWidth (Length) to a layout unit,
+// then constrains the result by the resolved min logical width and max logical
+// width from the ComputedStyle object. Calls Node::ComputeMinMaxSize if needed.
+// override_minmax is provided *solely* for use by unit tests.
CORE_EXPORT LayoutUnit
ComputeInlineSizeForFragment(const NGConstraintSpace&,
- const ComputedStyle&,
- const base::Optional<MinMaxSize>&);
+ NGLayoutInputNode,
+ const MinMaxSize* override_minmax = nullptr);
-// Resolves the given length to a layout unit, constraining it by the min
-// logical height and max logical height properties from the ComputedStyle
-// object.
+// Same as ComputeInlineSizeForFragment, but uses height instead of width.
CORE_EXPORT LayoutUnit ComputeBlockSizeForFragment(const NGConstraintSpace&,
const ComputedStyle&,
LayoutUnit content_size);
@@ -173,15 +174,16 @@ CORE_EXPORT NGBoxStrut ComputeBorders(const NGConstraintSpace& constraint_space,
CORE_EXPORT NGBoxStrut ComputePadding(const NGConstraintSpace&,
const ComputedStyle&);
-// Resolves margin: auto in the inline direction.
-// This uses the available size from the constraint space and inline size to
-// compute the margins that are auto, if any, and adjusts
-// the given NGBoxStrut accordingly.
-CORE_EXPORT void ApplyAutoMargins(const ComputedStyle& child_style,
- const ComputedStyle& containing_block_style,
- LayoutUnit available_inline_size,
- LayoutUnit inline_size,
- NGBoxStrut* margins);
+// Convert inline margins from computed to used values. This will resolve 'auto'
+// values and over-constrainedness. This uses the available size from the
+// constraint space and inline size to compute the margins that are auto, if
+// any, and adjusts the given NGBoxStrut accordingly.
+CORE_EXPORT void ResolveInlineMargins(
+ const ComputedStyle& child_style,
+ const ComputedStyle& containing_block_style,
+ LayoutUnit available_inline_size,
+ LayoutUnit inline_size,
+ NGBoxStrut* margins);
// Calculate the adjustment needed for the line's left position, based on
// text-align, direction and amount of unused space.
@@ -190,6 +192,11 @@ CORE_EXPORT LayoutUnit LineOffsetForTextAlign(ETextAlign,
LayoutUnit space_left,
LayoutUnit trailing_spaces_width);
+// Same as |LineOffsetForTextAlign| but returns the logical inline offset
+// instead of line-left offset.
+CORE_EXPORT LayoutUnit InlineOffsetForTextAlign(const ComputedStyle&,
+ LayoutUnit space_left);
+
CORE_EXPORT LayoutUnit ConstrainByMinMax(LayoutUnit length,
LayoutUnit min,
LayoutUnit max);
@@ -198,15 +205,10 @@ NGBoxStrut CalculateBorderScrollbarPadding(
const NGConstraintSpace& constraint_space,
const NGBlockNode node);
-inline NGLogicalSize CalculateBorderBoxSize(
+NGLogicalSize CalculateBorderBoxSize(
const NGConstraintSpace& constraint_space,
- const ComputedStyle& style,
- const base::Optional<MinMaxSize>& min_and_max,
- LayoutUnit block_content_size = NGSizeIndefinite) {
- return NGLogicalSize(
- ComputeInlineSizeForFragment(constraint_space, style, min_and_max),
- ComputeBlockSizeForFragment(constraint_space, style, block_content_size));
-}
+ const NGBlockNode& node,
+ LayoutUnit block_content_size = NGSizeIndefinite);
NGLogicalSize CalculateContentBoxSize(
const NGLogicalSize border_box_size,
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 63dbcd82766..a6577d9af92 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
@@ -6,8 +6,10 @@
#include "base/memory/scoped_refptr.h"
#include "testing/gtest/include/gtest/gtest.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_constraint_space_builder.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_layout_test.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/calculation_value.h"
#include "third_party/blink/renderer/platform/layout_unit.h"
@@ -16,28 +18,28 @@
namespace blink {
namespace {
+static scoped_refptr<NGConstraintSpace> ConstructConstraintSpace(
+ int inline_size,
+ int block_size,
+ bool fixed_inline = false,
+ bool fixed_block = false,
+ WritingMode writing_mode = WritingMode::kHorizontalTb) {
+ NGLogicalSize size = {LayoutUnit(inline_size), LayoutUnit(block_size)};
+
+ return NGConstraintSpaceBuilder(
+ writing_mode,
+ /* icb_size */ size.ConvertToPhysical(writing_mode))
+ .SetAvailableSize(size)
+ .SetPercentageResolutionSize(size)
+ .SetIsFixedSizeInline(fixed_inline)
+ .SetIsFixedSizeBlock(fixed_block)
+ .ToConstraintSpace(writing_mode);
+}
+
class NGLengthUtilsTest : public testing::Test {
protected:
void SetUp() override { style_ = ComputedStyle::Create(); }
- static scoped_refptr<NGConstraintSpace> ConstructConstraintSpace(
- int inline_size,
- int block_size,
- bool fixed_inline = false,
- bool fixed_block = false,
- WritingMode writing_mode = WritingMode::kHorizontalTb) {
- NGLogicalSize size = {LayoutUnit(inline_size), LayoutUnit(block_size)};
-
- return NGConstraintSpaceBuilder(
- writing_mode,
- /* icb_size */ size.ConvertToPhysical(writing_mode))
- .SetAvailableSize(size)
- .SetPercentageResolutionSize(size)
- .SetIsFixedSizeInline(fixed_inline)
- .SetIsFixedSizeBlock(fixed_block)
- .ToConstraintSpace(writing_mode);
- }
-
LayoutUnit ResolveInlineLength(
const Length& length,
LengthResolveType type = LengthResolveType::kContentSize,
@@ -60,14 +62,6 @@ class NGLengthUtilsTest : public testing::Test {
content_size, type, phase);
}
- LayoutUnit ComputeInlineSizeForFragment(
- scoped_refptr<const NGConstraintSpace> constraint_space =
- ConstructConstraintSpace(200, 300),
- const MinMaxSize& sizes = MinMaxSize()) {
- return ::blink::ComputeInlineSizeForFragment(*constraint_space, *style_,
- sizes);
- }
-
LayoutUnit ComputeBlockSizeForFragment(
scoped_refptr<const NGConstraintSpace> constraint_space =
ConstructConstraintSpace(200, 300),
@@ -79,6 +73,28 @@ class NGLengthUtilsTest : public testing::Test {
scoped_refptr<ComputedStyle> style_;
};
+class NGLengthUtilsTestWithNode : public NGLayoutTest {
+ public:
+ void SetUp() override {
+ NGLayoutTest::SetUp();
+ style_ = ComputedStyle::Create();
+ }
+
+ LayoutUnit ComputeInlineSizeForFragment(
+ scoped_refptr<const NGConstraintSpace> constraint_space =
+ ConstructConstraintSpace(200, 300),
+ const MinMaxSize& sizes = MinMaxSize()) {
+ LayoutBox* body = ToLayoutBox(GetDocument().body()->GetLayoutObject());
+ body->SetStyle(style_);
+ body->SetPreferredLogicalWidthsDirty();
+ NGBlockNode node(body);
+ return ::blink::ComputeInlineSizeForFragment(*constraint_space, node,
+ &sizes);
+ }
+
+ scoped_refptr<ComputedStyle> style_;
+};
+
TEST_F(NGLengthUtilsTest, testResolveInlineLength) {
EXPECT_EQ(LayoutUnit(60), ResolveInlineLength(Length(30, kPercent)));
EXPECT_EQ(LayoutUnit(150), ResolveInlineLength(Length(150, kFixed)));
@@ -143,7 +159,6 @@ TEST_F(NGLengthUtilsTest, testComputeContentContribution) {
EXPECT_EQ(expected, ComputeMinAndMaxContentContribution(
style_->GetWritingMode(), *style_, sizes));
- expected = MinMaxSize{LayoutUnit(), LayoutUnit()};
style_->SetLogicalWidth(Length(kFillAvailable));
EXPECT_EQ(expected, ComputeMinAndMaxContentContribution(
style_->GetWritingMode(), *style_, sizes));
@@ -222,7 +237,7 @@ TEST_F(NGLengthUtilsTest, testComputeContentContribution) {
style_->GetWritingMode(), *style_, sizes));
}
-TEST_F(NGLengthUtilsTest, testComputeInlineSizeForFragment) {
+TEST_F(NGLengthUtilsTestWithNode, testComputeInlineSizeForFragment) {
MinMaxSize sizes;
sizes.min_size = LayoutUnit(30);
sizes.max_size = LayoutUnit(40);
@@ -432,8 +447,8 @@ TEST_F(NGLengthUtilsTest, testAutoMargins) {
LayoutUnit kAvailableInlineSize(200);
NGBoxStrut margins;
- ApplyAutoMargins(*style_, *style_, kAvailableInlineSize, kInlineSize,
- &margins);
+ ResolveInlineMargins(*style_, *style_, kAvailableInlineSize, kInlineSize,
+ &margins);
EXPECT_EQ(LayoutUnit(), margins.block_start);
EXPECT_EQ(LayoutUnit(), margins.block_end);
@@ -442,16 +457,16 @@ TEST_F(NGLengthUtilsTest, testAutoMargins) {
style_->SetMarginLeft(Length(0, kFixed));
margins = NGBoxStrut();
- ApplyAutoMargins(*style_, *style_, kAvailableInlineSize, kInlineSize,
- &margins);
+ ResolveInlineMargins(*style_, *style_, kAvailableInlineSize, kInlineSize,
+ &margins);
EXPECT_EQ(LayoutUnit(0), margins.inline_start);
EXPECT_EQ(LayoutUnit(50), margins.inline_end);
style_->SetMarginLeft(Length(kAuto));
style_->SetMarginRight(Length(0, kFixed));
margins = NGBoxStrut();
- ApplyAutoMargins(*style_, *style_, kAvailableInlineSize, kInlineSize,
- &margins);
+ ResolveInlineMargins(*style_, *style_, kAvailableInlineSize, kInlineSize,
+ &margins);
EXPECT_EQ(LayoutUnit(50), margins.inline_start);
EXPECT_EQ(LayoutUnit(0), margins.inline_end);
@@ -461,8 +476,8 @@ TEST_F(NGLengthUtilsTest, testAutoMargins) {
style_->SetMarginRight(Length(5000, kFixed));
margins = NGBoxStrut();
margins.inline_end = LayoutUnit(5000);
- ApplyAutoMargins(*style_, *style_, kAvailableInlineSize, kInlineSize,
- &margins);
+ ResolveInlineMargins(*style_, *style_, kAvailableInlineSize, kInlineSize,
+ &margins);
EXPECT_EQ(LayoutUnit(0), margins.inline_start);
EXPECT_EQ(LayoutUnit(50), margins.inline_end);
}
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 bd18926e320..ecc0b55d5c2 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
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h"
+#include "third_party/blink/renderer/core/layout/layout_block.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/ng/inline/ng_physical_line_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h"
@@ -38,18 +40,21 @@ NGOutOfFlowLayoutPart::NGOutOfFlowLayoutPart(
default_containing_block_.style = &container_style;
default_containing_block_.content_size = container_builder_->Size();
- default_containing_block_.content_size.inline_size -=
- borders_and_scrollers.InlineSum();
- default_containing_block_.content_size.block_size -=
- borders_and_scrollers.BlockSum();
-
+ default_containing_block_.content_size.inline_size =
+ std::max(default_containing_block_.content_size.inline_size -
+ borders_and_scrollers.InlineSum(),
+ LayoutUnit());
+ default_containing_block_.content_size.block_size =
+ std::max(default_containing_block_.content_size.block_size -
+ borders_and_scrollers.BlockSum(),
+ LayoutUnit());
default_containing_block_.content_offset = NGLogicalOffset{
borders_and_scrollers.inline_start, borders_and_scrollers.block_start};
default_containing_block_.content_physical_offset =
NGPhysicalOffset(physical_borders.left, physical_borders.top);
}
-void NGOutOfFlowLayoutPart::Run(bool update_legacy) {
+void NGOutOfFlowLayoutPart::Run(LayoutBox* only_layout) {
Vector<NGOutOfFlowPositionedDescendant> descendant_candidates;
container_builder_->GetAndClearOutOfFlowDescendantCandidates(
&descendant_candidates, container_builder_->GetLayoutObject());
@@ -57,12 +62,13 @@ void NGOutOfFlowLayoutPart::Run(bool update_legacy) {
while (descendant_candidates.size() > 0) {
ComputeInlineContainingBlocks(descendant_candidates);
for (auto& candidate : descendant_candidates) {
- if (IsContainingBlockForDescendant(candidate)) {
+ if (IsContainingBlockForDescendant(candidate) &&
+ (!only_layout || candidate.node.GetLayoutBox() == only_layout)) {
NGLogicalOffset offset;
scoped_refptr<NGLayoutResult> result =
LayoutDescendant(candidate, &offset);
container_builder_->AddChild(std::move(result), offset);
- if (update_legacy)
+ if (candidate.node.GetLayoutBox() != only_layout)
candidate.node.UseOldOutOfFlowPositioning();
} else {
container_builder_->AddOutOfFlowDescendant(candidate);
@@ -287,11 +293,27 @@ scoped_refptr<NGLayoutResult> NGOutOfFlowLayoutPart::LayoutDescendant(
WritingMode container_writing_mode(container_info.style->GetWritingMode());
WritingMode descendant_writing_mode(descendant.node.Style().GetWritingMode());
- // Adjust the static_position origin. The static_position coordinate origin is
- // relative to the container's border box, ng_absolute_utils expects it to be
- // relative to the container's padding box.
+ // Adjust the static_position origin.
+ // The static_position coordinate origin is relative to default_container's
+ // border box.
+ // ng_absolute_utils expects static position to be relative to
+ // the container's padding box.
+ // Adjust static position by offset of container from default container,
+ // and default_container border width.
NGStaticPosition static_position(descendant.static_position);
- static_position.offset -= container_info.content_physical_offset;
+ NGPhysicalSize default_containing_block_physical_size =
+ default_containing_block_.content_size.ConvertToPhysical(
+ default_containing_block_.style->GetWritingMode());
+ NGPhysicalOffset default_container_physical_offset =
+ container_info.default_container_offset.ConvertToPhysical(
+ default_containing_block_.style->GetWritingMode(),
+ default_containing_block_.style->Direction(),
+ default_containing_block_physical_size,
+ default_containing_block_physical_size);
+
+ static_position.offset = static_position.offset -
+ default_containing_block_.content_physical_offset -
+ default_container_physical_offset;
// The block estimate is in the descendant's writing mode.
scoped_refptr<NGConstraintSpace> descendant_constraint_space =
@@ -375,14 +397,27 @@ scoped_refptr<NGLayoutResult> NGOutOfFlowLayoutPart::LayoutDescendant(
offset->inline_offset +=
container_info.default_container_offset.inline_offset;
offset->block_offset += container_info.default_container_offset.block_offset;
+
+ base::Optional<LayoutUnit> y = ComputeAbsoluteDialogYPosition(
+ *descendant.node.GetLayoutBox(),
+ layout_result->PhysicalFragment()->Size().height);
+ if (y.has_value()) {
+ if (IsHorizontalWritingMode(container_writing_mode))
+ offset->block_offset = y.value();
+ else
+ offset->inline_offset = y.value();
+ }
+
return layout_result;
}
bool NGOutOfFlowLayoutPart::IsContainingBlockForDescendant(
const NGOutOfFlowPositionedDescendant& descendant) {
EPosition position = descendant.node.Style().GetPosition();
+
+ // Descendants whose containing block is inline are always positioned
+ // inside closest parent block flow.
if (descendant.inline_container) {
- DCHECK(position == EPosition::kAbsolute);
return true;
}
return (contains_absolute_ && position == EPosition::kAbsolute) ||
@@ -398,7 +433,7 @@ scoped_refptr<NGLayoutResult> NGOutOfFlowLayoutPart::GenerateFragment(
NGBlockNode descendant,
const ContainingBlockInfo& container_info,
const base::Optional<LayoutUnit>& block_estimate,
- const NGAbsolutePhysicalPosition node_position) {
+ const NGAbsolutePhysicalPosition& node_position) {
// As the block_estimate is always in the descendant's writing mode, we build
// the constraint space in the descendant's writing mode.
WritingMode writing_mode(descendant.Style().GetWritingMode());
@@ -426,7 +461,17 @@ scoped_refptr<NGLayoutResult> NGOutOfFlowLayoutPart::GenerateFragment(
scoped_refptr<NGConstraintSpace> space =
builder.ToConstraintSpace(writing_mode);
- return descendant.Layout(*space);
+ scoped_refptr<NGLayoutResult> result = descendant.Layout(*space);
+
+ // Legacy Grid and Flexbox seem to handle oof margins correctly
+ // on their own, and break if we set them here.
+ if (!descendant.GetLayoutBox()
+ ->ContainingBlock()
+ ->Style()
+ ->IsDisplayFlexibleOrGridBox())
+ descendant.GetLayoutBox()->SetMargin(node_position.margins);
+
+ return result;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h
index d5e0f691fe6..f89781dc8bc 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h
@@ -15,6 +15,7 @@
namespace blink {
class ComputedStyle;
+class LayoutBox;
class LayoutObject;
class NGBlockNode;
class NGFragmentBuilder;
@@ -37,9 +38,13 @@ class CORE_EXPORT NGOutOfFlowLayoutPart {
const NGConstraintSpace& container_space,
const ComputedStyle& container_style);
- // update_legacy will place NG OOF descendants into their Legacy container.
- // It should be false if OOF descendants have already been placed into Legacy.
- void Run(bool update_legacy = true);
+ // Normally this function lays out and positions all out-of-flow objects
+ // from the container_builder and additional ones it discovers through laying
+ // out those objects. However, if only_layout is specified, only that object
+ // will get laid out; any additional ones will be stored as out-of-flow
+ // descendants in the builder for use via
+ // LayoutResult::OutOfFlowPositionedDescendants.
+ void Run(LayoutBox* only_layout = nullptr);
private:
// Information needed to position descendant within a containing block.
@@ -83,7 +88,7 @@ class CORE_EXPORT NGOutOfFlowLayoutPart {
NGBlockNode node,
const ContainingBlockInfo&,
const base::Optional<LayoutUnit>& block_estimate,
- const NGAbsolutePhysicalPosition node_position);
+ const NGAbsolutePhysicalPosition& node_position);
NGFragmentBuilder* container_builder_;
bool contains_absolute_;
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 110e07f58f9..bc3ab40e461 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
@@ -22,13 +22,10 @@ NGPageLayoutAlgorithm::NGPageLayoutAlgorithm(NGBlockNode node,
: NGLayoutAlgorithm(node, space, ToNGBlockBreakToken(break_token)) {}
scoped_refptr<NGLayoutResult> NGPageLayoutAlgorithm::Layout() {
- base::Optional<MinMaxSize> min_max_size;
- if (NeedMinMaxSize(ConstraintSpace(), Style()))
- min_max_size = ComputeMinMaxSize(MinMaxSizeInput());
NGBoxStrut border_scrollbar_padding =
CalculateBorderScrollbarPadding(ConstraintSpace(), Node());
NGLogicalSize border_box_size =
- CalculateBorderBoxSize(ConstraintSpace(), Style(), min_max_size);
+ CalculateBorderBoxSize(ConstraintSpace(), Node());
NGLogicalSize content_box_size =
CalculateContentBoxSize(border_box_size, border_scrollbar_padding);
NGLogicalSize page_size = content_box_size;
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 ff2e044f2f5..5379dec7c92 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
@@ -6,7 +6,9 @@
#include "third_party/blink/renderer/core/editing/position_with_affinity.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_object.h"
+#include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.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_line_box_fragment.h"
@@ -21,7 +23,7 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment(
NGPhysicalSize size,
Vector<scoped_refptr<NGPhysicalFragment>>& children,
const NGPixelSnappedPhysicalBoxStrut& padding,
- const NGPhysicalOffsetRect& contents_visual_rect,
+ const NGPhysicalOffsetRect& contents_ink_overflow,
Vector<NGBaseline>& baselines,
NGBoxType box_type,
bool is_old_layout_root,
@@ -34,7 +36,7 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment(
kFragmentBox,
box_type,
children,
- contents_visual_rect,
+ contents_ink_overflow,
std::move(break_token)),
baselines_(std::move(baselines)),
padding_(padding) {
@@ -58,6 +60,12 @@ NGPhysicalBoxFragment::NGPhysicalBoxFragment(
!descendant_outlines_.IsEmpty());
}
+bool NGPhysicalBoxFragment::IsFirstLineAnonymousInlineBox() const {
+ return IsInlineBox() && UsesFirstLineStyle() &&
+ layout_object_->IsAnonymous() && layout_object_->IsLayoutInline() &&
+ ToLayoutInline(layout_object_)->IsFirstLineAnonymous();
+}
+
const NGBaseline* NGPhysicalBoxFragment::Baseline(
const NGBaselineRequest& request) const {
for (const auto& baseline : baselines_) {
@@ -138,30 +146,30 @@ LayoutSize NGPhysicalBoxFragment::ScrollSize() const {
return LayoutSize(box->ScrollWidth(), box->ScrollHeight());
}
-NGPhysicalOffsetRect NGPhysicalBoxFragment::SelfVisualRect() const {
+NGPhysicalOffsetRect NGPhysicalBoxFragment::SelfInkOverflow() const {
const ComputedStyle& style = Style();
- LayoutRect visual_rect({}, Size().ToLayoutSize());
+ LayoutRect ink_overflow({}, Size().ToLayoutSize());
DCHECK(GetLayoutObject());
if (style.HasVisualOverflowingEffect()) {
if (GetLayoutObject()->IsBox()) {
- visual_rect.Expand(style.BoxDecorationOutsets());
+ ink_overflow.Expand(style.BoxDecorationOutsets());
if (style.HasOutline()) {
Vector<LayoutRect> outline_rects;
// The result rects are in coordinates of this object's border box.
AddSelfOutlineRects(&outline_rects, LayoutPoint());
LayoutRect rect = UnionRectEvenIfEmpty(outline_rects);
rect.Inflate(style.OutlineOutsetExtent());
- visual_rect.Unite(rect);
+ ink_overflow.Unite(rect);
}
} else {
// TODO(kojii): Implement for inline boxes.
DCHECK(GetLayoutObject()->IsLayoutInline());
- visual_rect.Expand(style.BoxDecorationOutsets());
+ ink_overflow.Expand(style.BoxDecorationOutsets());
}
}
- visual_rect.Unite(descendant_outlines_.ToLayoutRect());
- return NGPhysicalOffsetRect(visual_rect);
+ ink_overflow.Unite(descendant_outlines_.ToLayoutRect());
+ return NGPhysicalOffsetRect(ink_overflow);
}
void NGPhysicalBoxFragment::AddSelfOutlineRects(
@@ -205,7 +213,7 @@ void NGPhysicalBoxFragment::AddSelfOutlineRects(
DCHECK(child->GetLayoutObject());
LayoutObject* child_layout = child->GetLayoutObject();
Vector<LayoutRect> child_rects;
- child_rects.push_back(child->VisualRectWithContents().ToLayoutRect());
+ child_rects.push_back(child->InkOverflow().ToLayoutRect());
child_layout->LocalToAncestorRects(
child_rects, ToLayoutBoxModelObject(GetLayoutObject()), LayoutPoint(),
additional_offset);
@@ -215,13 +223,13 @@ void NGPhysicalBoxFragment::AddSelfOutlineRects(
}
}
-NGPhysicalOffsetRect NGPhysicalBoxFragment::VisualRectWithContents() const {
- if (HasOverflowClip() || Style().HasMask())
- return SelfVisualRect();
+NGPhysicalOffsetRect NGPhysicalBoxFragment::InkOverflow(bool apply_clip) const {
+ if ((apply_clip && HasOverflowClip()) || Style().HasMask())
+ return SelfInkOverflow();
- NGPhysicalOffsetRect visual_rect = SelfVisualRect();
- visual_rect.Unite(ContentsVisualRect());
- return visual_rect;
+ NGPhysicalOffsetRect ink_overflow = SelfInkOverflow();
+ ink_overflow.Unite(ContentsInkOverflow());
+ return ink_overflow;
}
UBiDiLevel NGPhysicalBoxFragment::BidiLevel() const {
@@ -246,7 +254,7 @@ scoped_refptr<NGPhysicalFragment> NGPhysicalBoxFragment::CloneWithoutOffset()
scoped_refptr<NGPhysicalFragment> physical_fragment =
base::AdoptRef(new NGPhysicalBoxFragment(
layout_object_, Style(), StyleVariant(), size_, children_copy,
- padding_, contents_visual_rect_, baselines_copy, BoxType(),
+ padding_, contents_ink_overflow_, baselines_copy, BoxType(),
is_old_layout_root_, border_edge_, break_token_));
return physical_fragment;
}
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 f2f8a3b88c7..f3f8a868658 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
@@ -23,13 +23,16 @@ class CORE_EXPORT NGPhysicalBoxFragment final
NGPhysicalSize size,
Vector<scoped_refptr<NGPhysicalFragment>>& children,
const NGPixelSnappedPhysicalBoxStrut& padding,
- const NGPhysicalOffsetRect& contents_visual_rect,
+ const NGPhysicalOffsetRect& contents_ink_overflow,
Vector<NGBaseline>& baselines,
NGBoxType box_type,
bool is_old_layout_root,
unsigned, // NGBorderEdges::Physical
scoped_refptr<NGBreakToken> break_token = nullptr);
+ // True if this is an anonymous inline box for ::first-line.
+ bool IsFirstLineAnonymousInlineBox() const;
+
const NGBaseline* Baseline(const NGBaselineRequest&) const;
const NGPixelSnappedPhysicalBoxStrut& Padding() const { return padding_; }
@@ -55,10 +58,10 @@ class CORE_EXPORT NGPhysicalBoxFragment final
// Visual rect of this box in the local coordinate. Does not include children
// even if they overflow this box.
- NGPhysicalOffsetRect SelfVisualRect() const;
+ NGPhysicalOffsetRect SelfInkOverflow() const;
- // VisualRect of itself including contents, in the local coordinate.
- NGPhysicalOffsetRect VisualRectWithContents() const;
+ // Ink overflow including contents, in the local coordinates.
+ NGPhysicalOffsetRect InkOverflow(bool apply_clip) const;
void AddSelfOutlineRects(Vector<LayoutRect>*,
const LayoutPoint& additional_offset) const;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment_test.cc
index d0b66f10ea9..ccc8d918fe1 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment_test.cc
@@ -22,7 +22,7 @@ class NGPhysicalBoxFragmentTest : public NGLayoutTest {
// instead of using |contenteditable|.
// Tests that a normal old layout root box fragment has correct box type.
-TEST_F(NGPhysicalBoxFragmentTest, NormalOldLayoutRoot) {
+TEST_F(NGPhysicalBoxFragmentTest, DISABLED_NormalOldLayoutRoot) {
SetBodyInnerHTML("<div contenteditable>X</div>");
const NGPhysicalFragment* fragment =
GetBodyFragment().Children().front().get();
@@ -33,8 +33,10 @@ TEST_F(NGPhysicalBoxFragmentTest, NormalOldLayoutRoot) {
EXPECT_TRUE(fragment->IsBlockLayoutRoot());
}
+// TODO(editing-dev): Once LayoutNG supports editing, we should change this
+// test to use LayoutNG tree.
// Tests that a float old layout root box fragment has correct box type.
-TEST_F(NGPhysicalBoxFragmentTest, FloatOldLayoutRoot) {
+TEST_F(NGPhysicalBoxFragmentTest, DISABLED_FloatOldLayoutRoot) {
SetBodyInnerHTML("<span contenteditable style='float:left'>X</span>foo");
const NGPhysicalFragment* fragment =
GetBodyFragment().Children().front().get();
@@ -45,8 +47,10 @@ TEST_F(NGPhysicalBoxFragmentTest, FloatOldLayoutRoot) {
EXPECT_TRUE(fragment->IsBlockLayoutRoot());
}
+// TODO(editing-dev): Once LayoutNG supports editing, we should change this
+// test to use LayoutNG tree.
// Tests that an inline block old layout root box fragment has correct box type.
-TEST_F(NGPhysicalBoxFragmentTest, InlineBlockOldLayoutRoot) {
+TEST_F(NGPhysicalBoxFragmentTest, DISABLED_InlineBlockOldLayoutRoot) {
SetBodyInnerHTML(
"<span contenteditable style='display:inline-block'>X</span>foo");
const NGPhysicalContainerFragment* line_box =
@@ -59,9 +63,11 @@ TEST_F(NGPhysicalBoxFragmentTest, InlineBlockOldLayoutRoot) {
EXPECT_TRUE(fragment->IsBlockLayoutRoot());
}
+// TODO(editing-dev): Once LayoutNG supports editing, we should change this
+// test to use LayoutNG tree.
// Tests that an out-of-flow positioned old layout root box fragment has correct
// box type.
-TEST_F(NGPhysicalBoxFragmentTest, OutOfFlowPositionedOldLayoutRoot) {
+TEST_F(NGPhysicalBoxFragmentTest, DISABLED_OutOfFlowPositionedOldLayoutRoot) {
SetBodyInnerHTML(
"<style>body {position: absolute}</style>"
"<div contenteditable style='position: absolute'>X</div>");
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 3c6fe5fbb87..69deaa9d244 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
@@ -14,7 +14,7 @@ NGPhysicalContainerFragment::NGPhysicalContainerFragment(
NGFragmentType type,
unsigned sub_type,
Vector<scoped_refptr<NGPhysicalFragment>>& children,
- const NGPhysicalOffsetRect& contents_visual_rect,
+ const NGPhysicalOffsetRect& contents_ink_overflow,
scoped_refptr<NGBreakToken> break_token)
: NGPhysicalFragment(layout_object,
style,
@@ -24,7 +24,7 @@ NGPhysicalContainerFragment::NGPhysicalContainerFragment(
sub_type,
std::move(break_token)),
children_(std::move(children)),
- contents_visual_rect_(contents_visual_rect) {
+ contents_ink_overflow_(contents_ink_overflow) {
DCHECK(children.IsEmpty()); // Ensure move semantics is used.
}
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 4d80ac63b5b..52da5f09119 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
@@ -18,9 +18,9 @@ class CORE_EXPORT NGPhysicalContainerFragment : public NGPhysicalFragment {
return children_;
}
- // Visual rect of children in the local coordinate.
- const NGPhysicalOffsetRect& ContentsVisualRect() const {
- return contents_visual_rect_;
+ // Ink overflow of children in local coordinates.
+ const NGPhysicalOffsetRect& ContentsInkOverflow() const {
+ return contents_ink_overflow_;
}
protected:
@@ -33,11 +33,11 @@ class CORE_EXPORT NGPhysicalContainerFragment : public NGPhysicalFragment {
NGFragmentType,
unsigned sub_type,
Vector<scoped_refptr<NGPhysicalFragment>>& children,
- const NGPhysicalOffsetRect& contents_visual_rect,
+ const NGPhysicalOffsetRect& contents_ink_overflow,
scoped_refptr<NGBreakToken> = nullptr);
Vector<scoped_refptr<NGPhysicalFragment>> children_;
- NGPhysicalOffsetRect contents_visual_rect_;
+ NGPhysicalOffsetRect contents_ink_overflow_;
};
DEFINE_TYPE_CASTS(NGPhysicalContainerFragment,
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 675d046c7c4..760b1285032 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
@@ -43,16 +43,16 @@ bool AppendFragmentOffsetAndSize(const NGPhysicalFragment* fragment,
if (flags & NGPhysicalFragment::DumpOverflow) {
if (has_content)
builder->Append(" ");
- NGPhysicalOffsetRect overflow = fragment->VisualRectWithContents();
+ NGPhysicalOffsetRect overflow = fragment->InkOverflow();
if (overflow.size.width != fragment->Size().width ||
overflow.size.height != fragment->Size().height) {
- builder->Append(" visualRectWithContents: ");
+ builder->Append(" InkOverflow: ");
builder->Append(overflow.ToString());
has_content = true;
}
if (has_content)
builder->Append(" ");
- overflow = fragment->SelfVisualRect();
+ overflow = fragment->SelfInkOverflow();
if (overflow.size.width != fragment->Size().width ||
overflow.size.height != fragment->Size().height) {
builder->Append(" visualRect: ");
@@ -132,6 +132,12 @@ void AppendFragmentToString(const NGPhysicalFragment* fragment,
has_content =
AppendFragmentOffsetAndSize(fragment, builder, flags, has_content);
+ if (flags & NGPhysicalFragment::DumpNodeName &&
+ fragment->GetLayoutObject()) {
+ if (has_content)
+ builder->Append(" ");
+ builder->Append(fragment->GetLayoutObject()->DebugName());
+ }
builder->Append("\n");
if (flags & NGPhysicalFragment::DumpSubtree) {
@@ -304,12 +310,12 @@ NGPixelSnappedPhysicalBoxStrut NGPhysicalFragment::BorderWidths() const {
return box_strut.SnapToDevicePixels();
}
-NGPhysicalOffsetRect NGPhysicalFragment::SelfVisualRect() const {
+NGPhysicalOffsetRect NGPhysicalFragment::SelfInkOverflow() const {
switch (Type()) {
case NGPhysicalFragment::kFragmentBox:
- return ToNGPhysicalBoxFragment(*this).SelfVisualRect();
+ return ToNGPhysicalBoxFragment(*this).SelfInkOverflow();
case NGPhysicalFragment::kFragmentText:
- return ToNGPhysicalTextFragment(*this).SelfVisualRect();
+ return ToNGPhysicalTextFragment(*this).SelfInkOverflow();
case NGPhysicalFragment::kFragmentLineBox:
return {{}, Size()};
}
@@ -317,14 +323,14 @@ NGPhysicalOffsetRect NGPhysicalFragment::SelfVisualRect() const {
return {{}, Size()};
}
-NGPhysicalOffsetRect NGPhysicalFragment::VisualRectWithContents() const {
+NGPhysicalOffsetRect NGPhysicalFragment::InkOverflow(bool apply_clip) const {
switch (Type()) {
case NGPhysicalFragment::kFragmentBox:
- return ToNGPhysicalBoxFragment(*this).VisualRectWithContents();
+ return ToNGPhysicalBoxFragment(*this).InkOverflow(apply_clip);
case NGPhysicalFragment::kFragmentText:
- return ToNGPhysicalTextFragment(*this).SelfVisualRect();
+ return ToNGPhysicalTextFragment(*this).SelfInkOverflow();
case NGPhysicalFragment::kFragmentLineBox:
- return ToNGPhysicalLineBoxFragment(*this).VisualRectWithContents();
+ return ToNGPhysicalLineBoxFragment(*this).InkOverflow();
}
NOTREACHED();
return {{}, Size()};
@@ -337,17 +343,19 @@ NGPhysicalOffsetRect NGPhysicalFragment::ScrollableOverflow() const {
case NGPhysicalFragment::kFragmentText:
return {{}, Size()};
case NGPhysicalFragment::kFragmentLineBox:
- return ToNGPhysicalLineBoxFragment(*this).ScrollableOverflow();
+ NOTREACHED()
+ << "You must call NGLineBoxFragment::ScrollableOverflow explicitly.";
+ break;
}
NOTREACHED();
return {{}, Size()};
}
-void NGPhysicalFragment::PropagateContentsVisualRect(
- NGPhysicalOffsetRect* parent_visual_rect) const {
- NGPhysicalOffsetRect visual_rect = VisualRectWithContents();
- visual_rect.offset += Offset();
- parent_visual_rect->Unite(visual_rect);
+void NGPhysicalFragment::PropagateContentsInkOverflow(
+ NGPhysicalOffsetRect* parent_ink_overflow) const {
+ NGPhysicalOffsetRect ink_overflow = InkOverflow();
+ ink_overflow.offset += Offset();
+ parent_ink_overflow->Unite(ink_overflow);
}
const Vector<NGInlineItem>& NGPhysicalFragment::InlineItemsOfContainingBlock()
@@ -442,7 +450,7 @@ String NGPhysicalFragment::DumpFragmentTree(DumpFlags flags,
#ifndef NDEBUG
void NGPhysicalFragment::ShowFragmentTree() const {
- DumpFlags dump_flags = DumpAll & ~DumpOverflow;
+ DumpFlags dump_flags = DumpAll; //& ~DumpOverflow;
LOG(INFO) << "\n" << DumpFragmentTree(dump_flags).Utf8().data();
}
#endif // !NDEBUG
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 1932d3ebefb..2f6642cca0a 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
@@ -169,17 +169,17 @@ class CORE_EXPORT NGPhysicalFragment
// with LegacyLayout.
LayoutObject* GetLayoutObject() const { return layout_object_; }
- // VisualRect of itself, not including contents, in the local coordinate.
- NGPhysicalOffsetRect SelfVisualRect() const;
+ // InkOverflow of itself, not including contents, in the local coordinate.
+ NGPhysicalOffsetRect SelfInkOverflow() const;
- // VisualRect of itself including contents, in the local coordinate.
- NGPhysicalOffsetRect VisualRectWithContents() const;
+ // InkOverflow of itself including contents, in the local coordinate.
+ NGPhysicalOffsetRect InkOverflow(bool apply_clip = true) const;
// Scrollable overflow. including contents, in the local coordinate.
NGPhysicalOffsetRect ScrollableOverflow() const;
// Unite visual rect to propagate to parent's ContentsVisualRect.
- void PropagateContentsVisualRect(NGPhysicalOffsetRect*) const;
+ void PropagateContentsInkOverflow(NGPhysicalOffsetRect*) const;
// Should only be used by the parent fragment's layout.
void SetOffset(NGPhysicalOffset offset) {
@@ -211,6 +211,7 @@ class CORE_EXPORT NGPhysicalFragment
DumpTextOffsets = 0x40,
DumpSelfPainting = 0x80,
DumpOverflow = 0x100,
+ DumpNodeName = 0x200,
DumpAll = -1
};
typedef int DumpFlags;
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_relative_utils.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_relative_utils.cc
index 948b54dc2a0..9a48401064a 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_relative_utils.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_relative_utils.cc
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/core/layout/ng/ng_relative_utils.h"
#include "base/optional.h"
-#include "third_party/blink/renderer/core/layout/ng/geometry/ng_logical_offset.h"
+#include "third_party/blink/renderer/core/layout/ng/geometry/ng_physical_offset.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_physical_size.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/length_functions.h"
@@ -13,13 +13,13 @@
namespace blink {
// Returns the child's relative position wrt the containing fragment.
-NGLogicalOffset ComputeRelativeOffset(const ComputedStyle& child_style,
- WritingMode container_writing_mode,
- TextDirection container_direction,
- NGLogicalSize container_logical_size) {
- NGLogicalOffset offset;
- NGPhysicalSize container_size =
- container_logical_size.ConvertToPhysical(container_writing_mode);
+NGPhysicalOffset ComputeRelativeOffset(const ComputedStyle& child_style,
+ WritingMode container_writing_mode,
+ TextDirection container_direction,
+ NGPhysicalSize container_size) {
+ NGPhysicalOffset offset;
+ if (child_style.GetPosition() != EPosition::kRelative)
+ return offset;
base::Optional<LayoutUnit> left, right, top, bottom;
@@ -32,6 +32,10 @@ NGLogicalOffset ComputeRelativeOffset(const ComputedStyle& child_style,
if (!child_style.Bottom().IsAuto())
bottom = ValueForLength(child_style.Bottom(), container_size.height);
+ // Common case optimization
+ if (!left && !right && !top && !bottom)
+ return offset;
+
// Implements confict resolution rules from spec:
// https://www.w3.org/TR/css-position-3/#rel-pos
if (!left && !right) {
@@ -51,26 +55,18 @@ NGLogicalOffset ComputeRelativeOffset(const ComputedStyle& child_style,
if (!bottom)
bottom = -top.value();
- bool is_ltr = container_direction == TextDirection::kLtr;
-
- switch (container_writing_mode) {
- case WritingMode::kHorizontalTb:
- offset.inline_offset = is_ltr ? left.value() : right.value();
- offset.block_offset = top.value();
- break;
- case WritingMode::kVerticalRl:
- case WritingMode::kSidewaysRl:
- offset.inline_offset = is_ltr ? top.value() : bottom.value();
- offset.block_offset = right.value();
- break;
- case WritingMode::kVerticalLr:
- offset.inline_offset = is_ltr ? top.value() : bottom.value();
- offset.block_offset = left.value();
- break;
- case WritingMode::kSidewaysLr:
- offset.inline_offset = is_ltr ? bottom.value() : top.value();
- offset.block_offset = left.value();
- break;
+ if (IsHorizontalWritingMode(container_writing_mode)) {
+ if (IsLtr(container_direction))
+ offset.left = left.value();
+ else
+ offset.left = -right.value();
+ offset.top = top.value();
+ } else {
+ if (IsLtr(container_direction))
+ offset.top = top.value();
+ else
+ offset.top = -bottom.value();
+ offset.left = left.value();
}
return offset;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_relative_utils.h b/chromium/third_party/blink/renderer/core/layout/ng/ng_relative_utils.h
index f8ed7d8e381..1291a8e2f87 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_relative_utils.h
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_relative_utils.h
@@ -12,16 +12,16 @@
namespace blink {
class ComputedStyle;
-struct NGLogicalOffset;
+struct NGPhysicalOffset;
// Implements relative positioning spec:
// https://www.w3.org/TR/css-position-3/#rel-pos
// Return relative position offset as defined by style.
-CORE_EXPORT NGLogicalOffset
+CORE_EXPORT NGPhysicalOffset
ComputeRelativeOffset(const ComputedStyle& child_style,
WritingMode container_writing_mode,
TextDirection container_direction,
- NGLogicalSize container_size);
+ NGPhysicalSize container_size);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_relative_utils_test.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_relative_utils_test.cc
index 47cfa6434a0..f6d93e5facf 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_relative_utils_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_relative_utils_test.cc
@@ -5,14 +5,15 @@
#include "third_party/blink/renderer/core/layout/ng/ng_relative_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/core/layout/ng/geometry/ng_logical_offset.h"
+#include "third_party/blink/renderer/core/layout/ng/geometry/ng_physical_offset.h"
+#include "third_party/blink/renderer/core/layout/ng/geometry/ng_physical_size.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
namespace {
-const LayoutUnit kInlineSize{100};
-const LayoutUnit kBlockSize{200};
+const LayoutUnit kHorizontalSize{100};
+const LayoutUnit kVerticalSize{200};
const LayoutUnit kLeft{3};
const LayoutUnit kRight{5};
const LayoutUnit kTop{7};
@@ -24,7 +25,8 @@ class NGRelativeUtilsTest : public testing::Test {
protected:
void SetUp() override {
style_ = ComputedStyle::Create();
- container_size_ = NGLogicalSize{kInlineSize, kBlockSize};
+ style_->SetPosition(EPosition::kRelative);
+ container_size_ = NGPhysicalSize{kHorizontalSize, kVerticalSize};
}
void SetTRBL(LayoutUnit top,
@@ -44,18 +46,18 @@ class NGRelativeUtilsTest : public testing::Test {
}
scoped_refptr<ComputedStyle> style_;
- NGLogicalSize container_size_;
+ NGPhysicalSize container_size_;
};
TEST_F(NGRelativeUtilsTest, HorizontalTB) {
- NGLogicalOffset offset;
+ NGPhysicalOffset offset;
// Everything auto defaults to kZero,kZero
SetTRBL(kAuto, kAuto, kAuto, kAuto);
offset = ComputeRelativeOffset(*style_, WritingMode::kHorizontalTb,
TextDirection::kLtr, container_size_);
- EXPECT_EQ(offset.inline_offset, kZero);
- EXPECT_EQ(offset.block_offset, kZero);
+ EXPECT_EQ(offset.left, kZero);
+ EXPECT_EQ(offset.top, kZero);
// Set all sides
SetTRBL(kTop, kRight, kBottom, kLeft);
@@ -63,25 +65,25 @@ TEST_F(NGRelativeUtilsTest, HorizontalTB) {
// kLtr
offset = ComputeRelativeOffset(*style_, WritingMode::kHorizontalTb,
TextDirection::kLtr, container_size_);
- EXPECT_EQ(offset.inline_offset, kLeft);
- EXPECT_EQ(offset.block_offset, kTop);
+ EXPECT_EQ(offset.left, kLeft);
+ EXPECT_EQ(offset.top, kTop);
// kRtl
offset = ComputeRelativeOffset(*style_, WritingMode::kHorizontalTb,
TextDirection::kRtl, container_size_);
- EXPECT_EQ(offset.inline_offset, kRight);
- EXPECT_EQ(offset.block_offset, kTop);
+ EXPECT_EQ(offset.left, -kRight);
+ EXPECT_EQ(offset.top, kTop);
// Set only non-default sides
SetTRBL(kAuto, kRight, kBottom, kAuto);
offset = ComputeRelativeOffset(*style_, WritingMode::kHorizontalTb,
TextDirection::kLtr, container_size_);
- EXPECT_EQ(offset.inline_offset, -kRight);
- EXPECT_EQ(offset.block_offset, -kBottom);
+ EXPECT_EQ(offset.left, -kRight);
+ EXPECT_EQ(offset.top, -kBottom);
}
TEST_F(NGRelativeUtilsTest, VerticalRightLeft) {
- NGLogicalOffset offset;
+ NGPhysicalOffset offset;
// Set all sides
SetTRBL(kTop, kRight, kBottom, kLeft);
@@ -89,25 +91,25 @@ TEST_F(NGRelativeUtilsTest, VerticalRightLeft) {
// kLtr
offset = ComputeRelativeOffset(*style_, WritingMode::kVerticalRl,
TextDirection::kLtr, container_size_);
- EXPECT_EQ(offset.inline_offset, kTop);
- EXPECT_EQ(offset.block_offset, kRight);
+ EXPECT_EQ(offset.top, kTop);
+ EXPECT_EQ(offset.left, kLeft);
// kRtl
offset = ComputeRelativeOffset(*style_, WritingMode::kVerticalRl,
TextDirection::kRtl, container_size_);
- EXPECT_EQ(offset.inline_offset, kBottom);
- EXPECT_EQ(offset.block_offset, kRight);
+ EXPECT_EQ(offset.top, -kBottom);
+ EXPECT_EQ(offset.left, kLeft);
// Set only non-default sides
- SetTRBL(kAuto, kAuto, kBottom, kLeft);
+ SetTRBL(kAuto, kRight, kBottom, kAuto);
offset = ComputeRelativeOffset(*style_, WritingMode::kVerticalRl,
TextDirection::kLtr, container_size_);
- EXPECT_EQ(offset.inline_offset, -kBottom);
- EXPECT_EQ(offset.block_offset, -kLeft);
+ EXPECT_EQ(offset.top, -kBottom);
+ EXPECT_EQ(offset.left, -kRight);
}
TEST_F(NGRelativeUtilsTest, VerticalLeftRight) {
- NGLogicalOffset offset;
+ NGPhysicalOffset offset;
// Set all sides
SetTRBL(kTop, kRight, kBottom, kLeft);
@@ -115,21 +117,21 @@ TEST_F(NGRelativeUtilsTest, VerticalLeftRight) {
// kLtr
offset = ComputeRelativeOffset(*style_, WritingMode::kVerticalLr,
TextDirection::kLtr, container_size_);
- EXPECT_EQ(offset.inline_offset, kTop);
- EXPECT_EQ(offset.block_offset, kLeft);
+ EXPECT_EQ(offset.top, kTop);
+ EXPECT_EQ(offset.left, kLeft);
// kRtl
offset = ComputeRelativeOffset(*style_, WritingMode::kVerticalLr,
TextDirection::kRtl, container_size_);
- EXPECT_EQ(offset.inline_offset, kBottom);
- EXPECT_EQ(offset.block_offset, kLeft);
+ EXPECT_EQ(offset.top, -kBottom);
+ EXPECT_EQ(offset.left, kLeft);
// Set only non-default sides
SetTRBL(kAuto, kRight, kBottom, kAuto);
offset = ComputeRelativeOffset(*style_, WritingMode::kVerticalLr,
TextDirection::kLtr, container_size_);
- EXPECT_EQ(offset.inline_offset, -kBottom);
- EXPECT_EQ(offset.block_offset, -kRight);
+ EXPECT_EQ(offset.top, -kBottom);
+ EXPECT_EQ(offset.left, -kRight);
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.cc b/chromium/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.cc
index e8853136e82..f902a9947cf 100644
--- a/chromium/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.cc
+++ b/chromium/third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.cc
@@ -41,18 +41,15 @@ int NGTextDecorationOffset::ComputeUnderlineOffsetForUnder(
}
// Compute offset to the farthest position of the decorating box.
- // TODO(layout-dev): This is quite incorrect.
- LayoutUnit logical_top = text_fragment_.Offset().top;
- LayoutUnit position = logical_top + offset;
- int offset_int = position.Floor();
+ // TODO(layout-dev): This does not take farthest offset within the decorating
+ // box into account, only the position within this text fragment.
+ int offset_int = offset.Floor();
// Gaps are not needed for TextTop because it generally has internal
// leadings.
if (position_type == FontVerticalPositionType::TextTop)
return offset_int;
-
- // TODO(layout-dev): Add or subtract one depending on side (IsLineOverSide).
- return offset_int + 1;
+ return !IsLineOverSide(position_type) ? offset_int + 1 : offset_int - 1;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/paint_containment_test.cc b/chromium/third_party/blink/renderer/core/layout/paint_containment_test.cc
index 96e6ff24b57..dcc1d0a5834 100644
--- a/chromium/third_party/blink/renderer/core/layout/paint_containment_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/paint_containment_test.cc
@@ -22,14 +22,14 @@ static void CheckIsClippingStackingContextAndContainer(
LayoutBoxModelObject& obj) {
EXPECT_TRUE(obj.CanContainFixedPositionObjects());
EXPECT_TRUE(obj.HasClipRelatedProperty());
- EXPECT_TRUE(obj.Style()->ContainsPaint());
+ EXPECT_TRUE(obj.ShouldApplyPaintContainment());
// TODO(leviw): Ideally, we wouldn't require a paint layer to handle the
// clipping and stacking performed by paint containment.
DCHECK(obj.Layer());
PaintLayer* layer = obj.Layer();
EXPECT_TRUE(layer->StackingNode() &&
- layer->StackingNode()->IsStackingContext());
+ layer->GetLayoutObject().StyleRef().IsStackingContext());
}
TEST_F(PaintContainmentTest, BlockPaintContainment) {
@@ -50,12 +50,10 @@ TEST_F(PaintContainmentTest, InlinePaintContainment) {
"<div><span id='test' style='contain: paint'>Foo</span></div>");
Element* span = GetDocument().getElementById(AtomicString("test"));
DCHECK(span);
- // The inline should have been coerced into a block in StyleAdjuster.
+ // Paint containment shouldn't apply to non-atomic inlines.
LayoutObject* obj = span->GetLayoutObject();
DCHECK(obj);
- DCHECK(obj->IsLayoutBlock());
- LayoutBlock& layout_block = ToLayoutBlock(*obj);
- CheckIsClippingStackingContextAndContainer(layout_block);
+ EXPECT_FALSE(obj->IsLayoutBlock());
}
TEST_F(PaintContainmentTest, SvgWithContainmentShouldNotCrash) {
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 a8a634ad272..af6c5f78871 100644
--- a/chromium/third_party/blink/renderer/core/layout/scroll_anchor.cc
+++ b/chromium/third_party/blink/renderer/core/layout/scroll_anchor.cc
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/dom/nth_index_cache.h"
#include "third_party/blink/renderer/core/dom/static_node_list.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
+#include "third_party/blink/renderer/core/frame/root_frame_viewport.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
@@ -577,10 +578,7 @@ void ScrollAnchor::ClearSelf() {
void ScrollAnchor::Dispose() {
if (scroller_) {
- LocalFrameView* frame_view =
- scroller_->IsLocalFrameView()
- ? static_cast<LocalFrameView*>(scroller_.Get())
- : ScrollerLayoutBox(scroller_)->GetFrameView();
+ LocalFrameView* frame_view = ScrollerLayoutBox(scroller_)->GetFrameView();
ScrollableArea* owning_scroller =
scroller_->IsRootFrameViewport()
? &ToRootFrameViewport(scroller_)->LayoutViewport()
@@ -609,12 +607,6 @@ void ScrollAnchor::Clear() {
}
layer = layer->Parent();
}
-
- if (LocalFrameView* view = layout_object->GetFrameView()) {
- ScrollAnchor* anchor = view->GetScrollAnchor();
- DCHECK(anchor);
- anchor->ClearSelf();
- }
}
bool ScrollAnchor::RefersTo(const LayoutObject* layout_object) 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 04e9d99d1ae..fabe57dd059 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/layout/scroll_anchor.h"
#include "third_party/blink/renderer/core/dom/static_node_list.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/geometry/dom_rect.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
@@ -30,7 +31,7 @@ class ScrollAnchorTest : public RenderingTest {
}
ScrollableArea* LayoutViewport() {
- return GetDocument().View()->LayoutViewportScrollableArea();
+ return GetDocument().View()->LayoutViewport();
}
VisualViewport& GetVisualViewport() {
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 4765f26297c..e35ef1a32f5 100644
--- a/chromium/third_party/blink/renderer/core/layout/scrollbars_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/scrollbars_test.cc
@@ -134,14 +134,14 @@ class ScrollbarsTestWithVirtualTimer : public ScrollbarsTest {
// Some task queues may have repeating v8 tasks that run forever so we impose
// a hard (virtual) time limit.
- void RunTasksForPeriod(double delay_ms) {
+ void RunTasksForPeriod(TimeDelta delay) {
TimeAdvance();
scheduler::GetSingleThreadTaskRunnerForTesting()->PostDelayedTask(
FROM_HERE,
WTF::Bind(
&ScrollbarsTestWithVirtualTimer::StopVirtualTimeAndExitRunLoop,
WTF::Unretained(this)),
- TimeDelta::FromMillisecondsD(delay_ms));
+ delay);
test::EnterRunLoop();
}
};
@@ -154,7 +154,7 @@ TEST_F(ScrollbarsTest, DocumentStyleRecalcPreservesScrollbars) {
request.Complete(R"HTML(
<!DOCTYPE html>
<style> body { width: 1600px; height: 1200px; } </style>)HTML");
- auto* layout_viewport = GetDocument().View()->LayoutViewportScrollableArea();
+ auto* layout_viewport = GetDocument().View()->LayoutViewport();
Compositor().BeginFrame();
ASSERT_TRUE(layout_viewport->VerticalScrollbar() &&
@@ -277,8 +277,7 @@ TEST_F(ScrollbarsTest, CustomScrollbarsCauseLayoutOnExistenceChange) {
<div id='box' class='box'></div>
)HTML");
- ScrollableArea* layout_viewport =
- GetDocument().View()->LayoutViewportScrollableArea();
+ ScrollableArea* layout_viewport = GetDocument().View()->LayoutViewport();
Compositor().BeginFrame();
@@ -319,8 +318,7 @@ TEST_F(ScrollbarsTest, TransparentBackgroundUsesDarkOverlayColorTheme) {
// are enabled.
DCHECK(GetScrollbarTheme().UsesOverlayScrollbars());
- ScrollableArea* layout_viewport =
- GetDocument().View()->LayoutViewportScrollableArea();
+ ScrollableArea* layout_viewport = GetDocument().View()->LayoutViewport();
EXPECT_EQ(kScrollbarOverlayColorThemeDark,
layout_viewport->GetScrollbarOverlayColorTheme());
@@ -341,8 +339,7 @@ TEST_F(ScrollbarsTest, BodyBackgroundChangesOverlayColorTheme) {
// are enabled.
DCHECK(GetScrollbarTheme().UsesOverlayScrollbars());
- ScrollableArea* layout_viewport =
- GetDocument().View()->LayoutViewportScrollableArea();
+ ScrollableArea* layout_viewport = GetDocument().View()->LayoutViewport();
EXPECT_EQ(kScrollbarOverlayColorThemeDark,
layout_viewport->GetScrollbarOverlayColorTheme());
@@ -388,8 +385,7 @@ TEST_F(ScrollbarsTest, OverlayScrollbarChangeToDisplayNoneDynamically) {
ScrollableArea* scrollable_div =
ToLayoutBox(div->GetLayoutObject())->GetScrollableArea();
- ScrollableArea* scrollable_root =
- GetDocument().View()->LayoutViewportScrollableArea();
+ ScrollableArea* scrollable_root = GetDocument().View()->LayoutViewport();
DCHECK(scrollable_div->VerticalScrollbar());
DCHECK(scrollable_div->VerticalScrollbar()->IsOverlayScrollbar());
@@ -488,8 +484,7 @@ TEST_F(ScrollbarsTest, HidingScrollbarsOnScrollableAreaDisablesScrollbars) {
Element* scroller = document.getElementById("scroller");
ScrollableArea* scroller_area =
ToLayoutBox(scroller->GetLayoutObject())->GetScrollableArea();
- ScrollableArea* frame_scroller_area =
- frame_view->LayoutViewportScrollableArea();
+ ScrollableArea* frame_scroller_area = frame_view->LayoutViewport();
// Scrollbars are hidden at start.
scroller_area->SetScrollbarsHiddenIfOverlay(true);
@@ -603,7 +598,7 @@ TEST_F(ScrollbarsTest, MouseOverLinkAndOverlayScrollbar) {
WebView()
.MainFrameImpl()
->GetFrameView()
- ->LayoutViewportScrollableArea()
+ ->LayoutViewport()
->SetScrollbarsHiddenIfOverlay(false);
Document& document = GetDocument();
@@ -640,7 +635,7 @@ TEST_F(ScrollbarsTest, MouseOverLinkAndOverlayScrollbar) {
WebView()
.MainFrameImpl()
->GetFrameView()
- ->LayoutViewportScrollableArea()
+ ->LayoutViewport()
->SetScrollbarsHiddenIfOverlay(true);
// Ensure hittest only has link
@@ -756,7 +751,7 @@ TEST_F(ScrollbarsTest, MouseOverScrollbarAndIFrame) {
WebView()
.MainFrameImpl()
->GetFrameView()
- ->LayoutViewportScrollableArea()
+ ->LayoutViewport()
->SetScrollbarsHiddenIfOverlay(false);
frame_resource.Complete("<!DOCTYPE html>");
@@ -794,7 +789,7 @@ TEST_F(ScrollbarsTest, MouseOverScrollbarAndIFrame) {
WebView()
.MainFrameImpl()
->GetFrameView()
- ->LayoutViewportScrollableArea()
+ ->LayoutViewport()
->SetScrollbarsHiddenIfOverlay(true);
// Ensure hittest has IFRAME and no scrollbar.
@@ -1060,8 +1055,7 @@ TEST_F(ScrollbarsTest, CustomScrollbarChangeToMobileByEmulator) {
Document& document = GetDocument();
- ScrollableArea* root_scrollable =
- document.View()->LayoutViewportScrollableArea();
+ ScrollableArea* root_scrollable = document.View()->LayoutViewport();
Element* div = document.getElementById("d1");
@@ -1174,9 +1168,7 @@ TEST_F(ScrollbarsTestWithVirtualTimer,
TEST_F(ScrollbarsTestWithVirtualTimer, TestNonCompositedOverlayScrollbarsFade) {
#endif
TimeAdvance();
- constexpr double kMockOverlayFadeOutDelayInSeconds = 5.0;
- constexpr double kMockOverlayFadeOutDelayMS =
- kMockOverlayFadeOutDelayInSeconds * 1000;
+ constexpr TimeDelta kMockOverlayFadeOutDelay = TimeDelta::FromSeconds(5);
ScrollbarTheme& theme = GetScrollbarTheme();
// This test relies on mock overlay scrollbars.
@@ -1184,13 +1176,12 @@ TEST_F(ScrollbarsTestWithVirtualTimer, TestNonCompositedOverlayScrollbarsFade) {
ASSERT_TRUE(theme.UsesOverlayScrollbars());
ScrollbarThemeOverlayMock& mock_overlay_theme =
(ScrollbarThemeOverlayMock&)theme;
- mock_overlay_theme.SetOverlayScrollbarFadeOutDelay(
- kMockOverlayFadeOutDelayInSeconds);
+ mock_overlay_theme.SetOverlayScrollbarFadeOutDelay(kMockOverlayFadeOutDelay);
WebView().Resize(WebSize(640, 480));
SimRequest request("https://example.com/test.html", "text/html");
LoadURL("https://example.com/test.html");
- RunTasksForPeriod(kMockOverlayFadeOutDelayMS);
+ RunTasksForPeriod(kMockOverlayFadeOutDelay);
request.Complete(R"HTML(
<!DOCTYPE html>
<style>
@@ -1225,14 +1216,14 @@ TEST_F(ScrollbarsTestWithVirtualTimer, TestNonCompositedOverlayScrollbarsFade) {
DCHECK(!scrollable_area->UsesCompositedScrolling());
EXPECT_FALSE(scrollable_area->ScrollbarsHiddenIfOverlay());
- RunTasksForPeriod(kMockOverlayFadeOutDelayMS);
+ RunTasksForPeriod(kMockOverlayFadeOutDelay);
EXPECT_TRUE(scrollable_area->ScrollbarsHiddenIfOverlay());
scrollable_area->SetScrollOffset(ScrollOffset(10, 10), kProgrammaticScroll,
kScrollBehaviorInstant);
EXPECT_FALSE(scrollable_area->ScrollbarsHiddenIfOverlay());
- RunTasksForPeriod(kMockOverlayFadeOutDelayMS);
+ RunTasksForPeriod(kMockOverlayFadeOutDelay);
EXPECT_TRUE(scrollable_area->ScrollbarsHiddenIfOverlay());
MainFrame().ExecuteScript(WebScriptSource(
@@ -1246,7 +1237,7 @@ TEST_F(ScrollbarsTestWithVirtualTimer, TestNonCompositedOverlayScrollbarsFade) {
Compositor().BeginFrame();
EXPECT_FALSE(scrollable_area->ScrollbarsHiddenIfOverlay());
- RunTasksForPeriod(kMockOverlayFadeOutDelayMS);
+ RunTasksForPeriod(kMockOverlayFadeOutDelay);
EXPECT_TRUE(scrollable_area->ScrollbarsHiddenIfOverlay());
// Non-composited scrollbars don't fade out while mouse is over.
@@ -1255,13 +1246,13 @@ TEST_F(ScrollbarsTestWithVirtualTimer, TestNonCompositedOverlayScrollbarsFade) {
kScrollBehaviorInstant);
EXPECT_FALSE(scrollable_area->ScrollbarsHiddenIfOverlay());
scrollable_area->MouseEnteredScrollbar(*scrollable_area->VerticalScrollbar());
- RunTasksForPeriod(kMockOverlayFadeOutDelayMS);
+ RunTasksForPeriod(kMockOverlayFadeOutDelay);
EXPECT_FALSE(scrollable_area->ScrollbarsHiddenIfOverlay());
scrollable_area->MouseExitedScrollbar(*scrollable_area->VerticalScrollbar());
- RunTasksForPeriod(kMockOverlayFadeOutDelayMS);
+ RunTasksForPeriod(kMockOverlayFadeOutDelay);
EXPECT_TRUE(scrollable_area->ScrollbarsHiddenIfOverlay());
- mock_overlay_theme.SetOverlayScrollbarFadeOutDelay(0.0);
+ mock_overlay_theme.SetOverlayScrollbarFadeOutDelay(TimeDelta());
}
typedef bool TestParamOverlayScrollbar;
@@ -1289,8 +1280,8 @@ class StubWebThemeEngine : public WebThemeEngine {
}
}
void GetOverlayScrollbarStyle(ScrollbarStyle* style) override {
- style->fade_out_delay_seconds = 0;
- style->fade_out_duration_seconds = 0;
+ style->fade_out_delay = TimeDelta();
+ style->fade_out_duration = TimeDelta();
style->thumb_thickness = 3;
style->scrollbar_margin = 0;
style->color = SkColorSetARGB(128, 64, 64, 64);
@@ -1353,8 +1344,7 @@ TEST_P(ScrollbarAppearanceTest, NativeScrollbarChangeToMobileByEmulator) {
Document& document = GetDocument();
- ScrollableArea* root_scrollable =
- document.View()->LayoutViewportScrollableArea();
+ ScrollableArea* root_scrollable = document.View()->LayoutViewport();
Element* div = document.getElementById("d1");
@@ -1425,8 +1415,7 @@ TEST_P(ScrollbarAppearanceTest, ThemeEngineDefinesMinimumThumbLength) {
request.Complete(R"HTML(
<!DOCTYPE html>
<style> body { width: 1000000px; height: 1000000px; } </style>)HTML");
- ScrollableArea* scrollable_area =
- GetDocument().View()->LayoutViewportScrollableArea();
+ ScrollableArea* scrollable_area = GetDocument().View()->LayoutViewport();
Compositor().BeginFrame();
ASSERT_TRUE(scrollable_area->VerticalScrollbar());
@@ -1451,8 +1440,7 @@ TEST_P(ScrollbarAppearanceTest, HugeScrollingThumbPosition) {
request.Complete(R"HTML(
<!DOCTYPE html>
<style> body { margin: 0px; height: 10000000px; } </style>)HTML");
- ScrollableArea* scrollable_area =
- GetDocument().View()->LayoutViewportScrollableArea();
+ ScrollableArea* scrollable_area = GetDocument().View()->LayoutViewport();
Compositor().BeginFrame();
@@ -1501,7 +1489,7 @@ TEST_F(ScrollbarsTest, WideBodyShouldNotHaveScrollbars) {
}
)HTML");
Compositor().BeginFrame();
- auto* layout_viewport = GetDocument().View()->LayoutViewportScrollableArea();
+ auto* layout_viewport = GetDocument().View()->LayoutViewport();
EXPECT_FALSE(layout_viewport->VerticalScrollbar());
EXPECT_FALSE(layout_viewport->HorizontalScrollbar());
}
@@ -1525,7 +1513,7 @@ TEST_F(ScrollbarsTest, TallBodyShouldNotHaveScrollbars) {
}
)HTML");
Compositor().BeginFrame();
- auto* layout_viewport = GetDocument().View()->LayoutViewportScrollableArea();
+ auto* layout_viewport = GetDocument().View()->LayoutViewport();
EXPECT_FALSE(layout_viewport->VerticalScrollbar());
EXPECT_FALSE(layout_viewport->HorizontalScrollbar());
}
@@ -1550,7 +1538,7 @@ TEST_F(ScrollbarsTest, TallAndWideBodyShouldNotHaveScrollbars) {
}
)HTML");
Compositor().BeginFrame();
- auto* layout_viewport = GetDocument().View()->LayoutViewportScrollableArea();
+ auto* layout_viewport = GetDocument().View()->LayoutViewport();
EXPECT_FALSE(layout_viewport->VerticalScrollbar());
EXPECT_FALSE(layout_viewport->HorizontalScrollbar());
}
@@ -1575,7 +1563,7 @@ TEST_F(ScrollbarsTest, BodySizeEqualWindowSizeShouldNotHaveScrollbars) {
}
)HTML");
Compositor().BeginFrame();
- auto* layout_viewport = GetDocument().View()->LayoutViewportScrollableArea();
+ auto* layout_viewport = GetDocument().View()->LayoutViewport();
EXPECT_FALSE(layout_viewport->VerticalScrollbar());
EXPECT_FALSE(layout_viewport->HorizontalScrollbar());
}
@@ -1601,7 +1589,7 @@ TEST_F(ScrollbarsTest, WidePercentageBodyShouldHaveScrollbar) {
</style>
)HTML");
Compositor().BeginFrame();
- auto* layout_viewport = GetDocument().View()->LayoutViewportScrollableArea();
+ auto* layout_viewport = GetDocument().View()->LayoutViewport();
EXPECT_FALSE(layout_viewport->VerticalScrollbar());
EXPECT_TRUE(layout_viewport->HorizontalScrollbar());
}
@@ -1627,7 +1615,7 @@ TEST_F(ScrollbarsTest, WidePercentageAndTallBodyShouldHaveScrollbar) {
</style>
)HTML");
Compositor().BeginFrame();
- auto* layout_viewport = GetDocument().View()->LayoutViewportScrollableArea();
+ auto* layout_viewport = GetDocument().View()->LayoutViewport();
EXPECT_FALSE(layout_viewport->VerticalScrollbar());
EXPECT_TRUE(layout_viewport->HorizontalScrollbar());
}
@@ -1653,7 +1641,7 @@ TEST_F(ScrollbarsTest, TallPercentageBodyShouldHaveScrollbar) {
</style>
)HTML");
Compositor().BeginFrame();
- auto* layout_viewport = GetDocument().View()->LayoutViewportScrollableArea();
+ auto* layout_viewport = GetDocument().View()->LayoutViewport();
EXPECT_TRUE(layout_viewport->VerticalScrollbar());
EXPECT_FALSE(layout_viewport->HorizontalScrollbar());
}
@@ -1679,7 +1667,7 @@ TEST_F(ScrollbarsTest, TallPercentageAndWideBodyShouldHaveScrollbar) {
</style>
)HTML");
Compositor().BeginFrame();
- auto* layout_viewport = GetDocument().View()->LayoutViewportScrollableArea();
+ auto* layout_viewport = GetDocument().View()->LayoutViewport();
EXPECT_TRUE(layout_viewport->VerticalScrollbar());
EXPECT_FALSE(layout_viewport->HorizontalScrollbar());
}
@@ -1705,7 +1693,7 @@ TEST_F(ScrollbarsTest, TallAndWidePercentageBodyShouldHaveScrollbars) {
</style>
)HTML");
Compositor().BeginFrame();
- auto* layout_viewport = GetDocument().View()->LayoutViewportScrollableArea();
+ auto* layout_viewport = GetDocument().View()->LayoutViewport();
EXPECT_TRUE(layout_viewport->VerticalScrollbar());
EXPECT_TRUE(layout_viewport->HorizontalScrollbar());
}
@@ -1789,7 +1777,7 @@ TEST_F(ScrollbarsTest, AutosizeTest) {
test::RunPendingTasks();
LocalFrameView* frame_view = WebView().MainFrameImpl()->GetFrameView();
- ScrollableArea* layout_viewport = frame_view->LayoutViewportScrollableArea();
+ ScrollableArea* layout_viewport = frame_view->LayoutViewport();
// Enable auto size mode where the frame is resized such that the content
// doesn't need scrollbars (up to a maximum).
@@ -1910,7 +1898,6 @@ TEST_F(ScrollbarsTest, PLSADisposeShouldClearPointerInLayers) {
document.UpdateStyleAndLayout();
EXPECT_FALSE(paint_layer->GetScrollableArea());
- EXPECT_FALSE(graphics_layer->GetScrollableArea());
}
TEST_F(ScrollbarsTest, OverlayScrollbarHitTest) {
@@ -1940,7 +1927,7 @@ TEST_F(ScrollbarsTest, OverlayScrollbarHitTest) {
WebView()
.MainFrameImpl()
->GetFrameView()
- ->LayoutViewportScrollableArea()
+ ->LayoutViewport()
->SetScrollbarsHiddenIfOverlay(false);
frame_resource.Complete("<!DOCTYPE html><body style='height: 999px'></body>");
@@ -1951,7 +1938,7 @@ TEST_F(ScrollbarsTest, OverlayScrollbarHitTest) {
ToHTMLIFrameElement(GetDocument().getElementById("iframe"));
iframe_element->contentDocument()
->View()
- ->LayoutViewportScrollableArea()
+ ->LayoutViewport()
->SetScrollbarsHiddenIfOverlay(false);
// Hit test on and off the main frame scrollbar.
@@ -1985,7 +1972,7 @@ TEST_F(ScrollbarsTest, AllowMiddleButtonPressOnScrollbar) {
Compositor().BeginFrame();
ScrollableArea* scrollable_area =
- WebView().MainFrameImpl()->GetFrameView()->LayoutViewportScrollableArea();
+ WebView().MainFrameImpl()->GetFrameView()->LayoutViewport();
Scrollbar* scrollbar = scrollable_area->VerticalScrollbar();
ASSERT_TRUE(scrollbar);
@@ -2017,7 +2004,7 @@ TEST_F(ScrollbarsTest, MiddleDownShouldNotAffectScrollbarPress) {
Compositor().BeginFrame();
ScrollableArea* scrollable_area =
- WebView().MainFrameImpl()->GetFrameView()->LayoutViewportScrollableArea();
+ WebView().MainFrameImpl()->GetFrameView()->LayoutViewport();
Scrollbar* scrollbar = scrollable_area->VerticalScrollbar();
ASSERT_TRUE(scrollbar);
@@ -2050,6 +2037,83 @@ TEST_F(ScrollbarsTest, MiddleDownShouldNotAffectScrollbarPress) {
EXPECT_EQ(scrollbar->PressedPart(), ScrollbarPart::kNoPart);
}
+// For infinite scrolling page (load more content when scroll to bottom), user
+// press on scrollbar button should keep scrolling after content loaded.
+// Disable on Android since VirtualTime not work for Android.
+// http://crbug.com/633321
+#if defined(OS_ANDROID)
+TEST_F(ScrollbarsTestWithVirtualTimer,
+ DISABLED_PressScrollbarButtonOnInfiniteScrolling) {
+#else
+TEST_F(ScrollbarsTestWithVirtualTimer,
+ PressScrollbarButtonOnInfiniteScrolling) {
+#endif
+ TimeAdvance();
+ GetDocument().GetFrame()->GetSettings()->SetScrollAnimatorEnabled(false);
+ WebView().Resize(WebSize(200, 200));
+
+ SimRequest request("https://example.com/test.html", "text/html");
+ LoadURL("https://example.com/test.html");
+ RunTasksForPeriod(TimeDelta::FromMilliseconds(1000));
+ request.Complete(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ html, body{
+ margin: 0;
+ }
+ ::-webkit-scrollbar {
+ width: 30px;
+ height: 30px;
+ }
+ ::-webkit-scrollbar-button {
+ width: 30px;
+ height: 30px;
+ background: #00FF00;
+ }
+ ::-webkit-scrollbar-thumb {
+ background: #0000FF;
+ }
+ ::-webkit-scrollbar-track {
+ background: #aaaaaa;
+ }
+ #big {
+ height: 400px;
+ }
+ </style>
+ <div id='big'>
+ </div>
+ )HTML");
+
+ Compositor().BeginFrame();
+
+ ScrollableArea* scrollable_area =
+ WebView().MainFrameImpl()->GetFrameView()->LayoutViewport();
+ Scrollbar* scrollbar = scrollable_area->VerticalScrollbar();
+
+ // Scroll to bottom.
+ scrollable_area->SetScrollOffset(ScrollOffset(0, 400), kProgrammaticScroll,
+ kScrollBehaviorInstant);
+ EXPECT_EQ(scrollable_area->ScrollOffsetInt(), IntSize(0, 200));
+
+ HandleMouseMoveEvent(195, 195);
+ HandleMousePressEvent(195, 195);
+ ASSERT_EQ(scrollbar->PressedPart(), ScrollbarPart::kForwardButtonEndPart);
+
+ // Wait for 2 delay.
+ RunTasksForPeriod(TimeDelta::FromMilliseconds(1000));
+ RunTasksForPeriod(TimeDelta::FromMilliseconds(1000));
+ // Change #big size.
+ MainFrame().ExecuteScript(WebScriptSource(
+ "document.getElementById('big').style.height = '1000px';"));
+ Compositor().BeginFrame();
+
+ RunTasksForPeriod(TimeDelta::FromMilliseconds(1000));
+ RunTasksForPeriod(TimeDelta::FromMilliseconds(1000));
+
+ // Keep Scrolling.
+ EXPECT_GT(scrollable_area->ScrollOffsetInt().Height(), 200);
+}
+
class ScrollbarTrackMarginsTest : public ScrollbarsTest {
public:
void PrepareTest(const String& track_style) {
diff --git a/chromium/third_party/blink/renderer/core/layout/shapes/polygon_shape.h b/chromium/third_party/blink/renderer/core/layout/shapes/polygon_shape.h
index 97f76361219..87ba2f40b8d 100644
--- a/chromium/third_party/blink/renderer/core/layout/shapes/polygon_shape.h
+++ b/chromium/third_party/blink/renderer/core/layout/shapes/polygon_shape.h
@@ -64,7 +64,7 @@ class OffsetPolygonEdge final : public VertexPair {
class PolygonShape final : public Shape {
public:
- PolygonShape(std::unique_ptr<Vector<FloatPoint>> vertices, WindRule fill_rule)
+ PolygonShape(Vector<FloatPoint> vertices, WindRule fill_rule)
: Shape(), polygon_(std::move(vertices)) {}
LayoutRect ShapeMarginLogicalBoundingBox() const override;
diff --git a/chromium/third_party/blink/renderer/core/layout/shapes/shape.cc b/chromium/third_party/blink/renderer/core/layout/shapes/shape.cc
index ebfa930ec9c..22bee377b05 100644
--- a/chromium/third_party/blink/renderer/core/layout/shapes/shape.cc
+++ b/chromium/third_party/blink/renderer/core/layout/shapes/shape.cc
@@ -80,9 +80,8 @@ static std::unique_ptr<Shape> CreateEllipseShape(const FloatPoint& center,
radii);
}
-static std::unique_ptr<Shape> CreatePolygonShape(
- std::unique_ptr<Vector<FloatPoint>> vertices,
- WindRule fill_rule) {
+static std::unique_ptr<Shape> CreatePolygonShape(Vector<FloatPoint> vertices,
+ WindRule fill_rule) {
return std::make_unique<PolygonShape>(std::move(vertices), fill_rule);
}
@@ -165,12 +164,11 @@ std::unique_ptr<Shape> Shape::CreateShape(const BasicShape* basic_shape,
const Vector<Length>& values = polygon->Values();
size_t values_size = values.size();
DCHECK(!(values_size % 2));
- std::unique_ptr<Vector<FloatPoint>> vertices =
- std::make_unique<Vector<FloatPoint>>(values_size / 2);
+ Vector<FloatPoint> vertices(values_size / 2);
for (unsigned i = 0; i < values_size; i += 2) {
FloatPoint vertex(FloatValueForLength(values.at(i), box_width),
FloatValueForLength(values.at(i + 1), box_height));
- (*vertices)[i / 2] = PhysicalPointToLogical(
+ vertices[i / 2] = PhysicalPointToLogical(
vertex, logical_box_size.Height().ToFloat(), writing_mode);
}
shape = CreatePolygonShape(std::move(vertices), polygon->GetWindRule());
@@ -255,16 +253,16 @@ static bool ExtractImageData(Image* image,
// for layout, which is not allowed. See https://crbug.com/429346
ImageObserverDisabler disabler(image);
PaintFlags flags;
- IntRect image_source_rect(IntPoint(), image->Size());
+ FloatRect image_source_rect(FloatPoint(), FloatSize(image->Size()));
IntRect image_dest_rect(IntPoint(), image_size);
// TODO(ccameron): No color conversion is required here.
- std::unique_ptr<PaintCanvas> canvas =
+ std::unique_ptr<cc::PaintCanvas> canvas =
color_params.WrapCanvas(surface->getCanvas());
canvas->save();
canvas->clear(SK_ColorTRANSPARENT);
- image->Draw(canvas.get(), flags, image_dest_rect, image_source_rect,
- kDoNotRespectImageOrientation,
+ image->Draw(canvas.get(), flags, FloatRect(image_dest_rect),
+ image_source_rect, kDoNotRespectImageOrientation,
Image::kDoNotClampImageToSourceRect, Image::kSyncDecode);
return StaticBitmapImage::ConvertToArrayBufferContents(
diff --git a/chromium/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc b/chromium/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc
index 61f6ccb7d1d..7c9f0ec90d2 100644
--- a/chromium/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc
+++ b/chromium/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc
@@ -237,8 +237,7 @@ const Shape& ShapeOutsideInfo::ComputedShape() const {
break;
case ShapeValue::kBox: {
const FloatRoundedRect& shape_rect = style.GetRoundedBorderFor(
- LayoutRect(LayoutPoint(), reference_box_logical_size_),
- layout_box_.View());
+ LayoutRect(LayoutPoint(), reference_box_logical_size_));
shape_ = Shape::CreateLayoutBoxShape(shape_rect, writing_mode, margin);
break;
}
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 fa11a5a8020..3dda0b8b574 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
@@ -162,18 +162,10 @@ void LayoutSVGContainer::DescendantIsolationRequirementsChanged(
Parent()->DescendantIsolationRequirementsChanged(state);
}
-void LayoutSVGContainer::Paint(const PaintInfo& paint_info,
- const LayoutPoint&) const {
+void LayoutSVGContainer::Paint(const PaintInfo& paint_info) const {
SVGContainerPainter(*this).Paint(paint_info);
}
-void LayoutSVGContainer::AddOutlineRects(
- Vector<LayoutRect>& rects,
- const LayoutPoint&,
- IncludeBlockVisualOverflowOrNot) const {
- rects.push_back(LayoutRect(VisualRectInLocalSVGCoordinates()));
-}
-
void LayoutSVGContainer::UpdateCachedBoundaries() {
SVGLayoutSupport::ComputeContainerBoundingBoxes(
this, object_bounding_box_, object_bounding_box_valid_,
@@ -194,8 +186,9 @@ bool LayoutSVGContainer::NodeAtFloatPoint(HitTestResult& result,
if (child->NodeAtFloatPoint(result, local_point, hit_test_action)) {
const LayoutPoint& local_layout_point = LayoutPoint(local_point);
UpdateHitTestResult(result, local_layout_point);
- if (result.AddNodeToListBasedTestResult(
- child->GetNode(), local_layout_point) == kStopHitTesting)
+ HitTestLocation location(local_layout_point);
+ if (result.AddNodeToListBasedTestResult(child->GetNode(), location) ==
+ kStopHitTesting)
return true;
}
}
@@ -209,8 +202,9 @@ bool LayoutSVGContainer::NodeAtFloatPoint(HitTestResult& result,
ObjectBoundingBox().Contains(local_point)) {
const LayoutPoint& local_layout_point = LayoutPoint(local_point);
UpdateHitTestResult(result, local_layout_point);
- if (result.AddNodeToListBasedTestResult(
- GetElement(), local_layout_point) == kStopHitTesting)
+ HitTestLocation location(local_layout_point);
+ if (result.AddNodeToListBasedTestResult(GetElement(), location) ==
+ kStopHitTesting)
return true;
}
}
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 43897cd88b6..76b501fd49c 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
@@ -48,7 +48,7 @@ class LayoutSVGContainer : public LayoutSVGModelObject {
return Children()->LastChild();
}
- void Paint(const PaintInfo&, const LayoutPoint&) const override;
+ void Paint(const PaintInfo&) const override;
void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
void SetNeedsBoundariesUpdate() final { needs_boundaries_update_ = true; }
bool DidScreenScaleFactorChange() const {
@@ -79,9 +79,6 @@ class LayoutSVGContainer : public LayoutSVGModelObject {
void AddChild(LayoutObject* child,
LayoutObject* before_child = nullptr) final;
void RemoveChild(LayoutObject*) final;
- void AddOutlineRects(Vector<LayoutRect>&,
- const LayoutPoint& additional_offset,
- IncludeBlockVisualOverflowOrNot) const final;
FloatRect StrokeBoundingBox() const final { return stroke_bounding_box_; }
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.cc
index ad066f7f40e..10e0f3467e8 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_ellipse.cc
@@ -94,6 +94,10 @@ void LayoutSVGEllipse::CalculateRadiiAndCenter() {
} else {
radii_ = ToFloatSize(length_context.ResolveLengthPair(
svg_style.Rx(), svg_style.Ry(), style));
+ if (svg_style.Rx().IsAuto())
+ radii_.SetWidth(radii_.Height());
+ else if (svg_style.Ry().IsAuto())
+ radii_.SetHeight(radii_.Width());
}
}
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc
index 9f9a508adc1..3d21038a246 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc
@@ -42,8 +42,7 @@ bool LayoutSVGForeignObject::IsChildAllowed(LayoutObject* child,
return !child->IsSVGChild();
}
-void LayoutSVGForeignObject::Paint(const PaintInfo& paint_info,
- const LayoutPoint&) const {
+void LayoutSVGForeignObject::Paint(const PaintInfo& paint_info) const {
SVGForeignObjectPainter(*this).Paint(paint_info);
}
@@ -133,41 +132,29 @@ bool LayoutSVGForeignObject::NodeAtFloatPoint(HitTestResult& result,
return false;
FloatPoint local_point = local_transform.Inverse().MapPoint(point_in_parent);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- LayoutPoint point_in_foreign_object(local_point);
- // |local_point| already includes the offset of the <foreignObject> element,
- // but PaintLayer::HitTestLayer assumes it has not been.
- point_in_foreign_object.MoveBy(-Layer()->LayoutBoxLocation());
- HitTestResult layer_result(result.GetHitTestRequest(),
- point_in_foreign_object);
- bool retval = Layer()->HitTest(layer_result);
-
- // Preserve the "point in inner node frame" from the original request,
- // since |layer_result| is a hit test rooted at the <foreignObject> element,
- // not the frame, due to the constructor above using
- // |point_in_foreign_object| as its "point in inner node frame".
- // TODO(chrishtr): refactor the PaintLayer and HitTestResults code around
- // this, to better support hit tests that don't start at frame boundaries.
- LayoutPoint original_point_in_inner_node_frame =
- result.PointInInnerNodeFrame();
+ LayoutPoint point_in_foreign_object(local_point);
+ // |local_point| already includes the offset of the <foreignObject> element,
+ // but PaintLayer::HitTestLayer assumes it has not been.
+ point_in_foreign_object.MoveBy(-Layer()->LayoutBoxLocation());
+ HitTestLocation location(point_in_foreign_object);
+ HitTestResult layer_result(result.GetHitTestRequest(), location);
+ bool retval = Layer()->HitTest(location, layer_result,
+ LayoutRect(LayoutRect::InfiniteIntRect()));
+
+ // Preserve the "point in inner node frame" from the original request,
+ // since |layer_result| is a hit test rooted at the <foreignObject> element,
+ // not the frame, due to the constructor above using
+ // |point_in_foreign_object| as its "point in inner node frame".
+ // TODO(chrishtr): refactor the PaintLayer and HitTestResults code around
+ // this, to better support hit tests that don't start at frame boundaries.
+ LayoutPoint original_point_in_inner_node_frame =
+ result.PointInInnerNodeFrame();
+ if (result.GetHitTestRequest().ListBased())
+ result.Append(layer_result);
+ else
result = layer_result;
- result.SetPointInInnerNodeFrame(original_point_in_inner_node_frame);
- return retval;
- }
-
- // Early exit if local point is not contained in clipped viewport area
- if (SVGLayoutSupport::IsOverflowHidden(*this) &&
- !FrameRect().Contains(LayoutPoint(local_point)))
- return false;
-
- // FOs establish a stacking context, so we need to hit-test all layers.
- HitTestLocation hit_test_location(local_point);
- return LayoutBlock::NodeAtPoint(result, hit_test_location, LayoutPoint(),
- kHitTestForeground) ||
- LayoutBlock::NodeAtPoint(result, hit_test_location, LayoutPoint(),
- kHitTestFloat) ||
- LayoutBlock::NodeAtPoint(result, hit_test_location, LayoutPoint(),
- kHitTestChildBlockBackgrounds);
+ result.SetPointInInnerNodeFrame(original_point_in_inner_node_frame);
+ return retval;
}
bool LayoutSVGForeignObject::NodeAtPoint(
@@ -175,22 +162,14 @@ bool LayoutSVGForeignObject::NodeAtPoint(
const HitTestLocation& location_in_parent,
const LayoutPoint& accumulated_offset,
HitTestAction hit_test_action) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- return LayoutBlock::NodeAtPoint(result, location_in_parent,
- accumulated_offset, hit_test_action);
- }
- NOTREACHED();
- return false;
+ // Skip LayoutSVGBlock's override.
+ return LayoutBlockFlow::NodeAtPoint(result, location_in_parent,
+ accumulated_offset, hit_test_action);
}
PaintLayerType LayoutSVGForeignObject::LayerTypeRequired() const {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return LayoutBlockFlow::LayerTypeRequired();
- return kNoPaintLayer;
-}
-
-bool LayoutSVGForeignObject::AllowsOverflowClip() const {
- return RuntimeEnabledFeatures::SlimmingPaintV175Enabled();
+ // Skip LayoutSVGBlock's override.
+ return LayoutBlockFlow::LayerTypeRequired();
}
void LayoutSVGForeignObject::StyleDidChange(StyleDifference diff,
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h
index 4dffb3efd69..084e0431b1e 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h
@@ -48,7 +48,7 @@ class LayoutSVGForeignObject final : public LayoutSVGBlock {
bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const override;
- void Paint(const PaintInfo&, const LayoutPoint&) const override;
+ void Paint(const PaintInfo&) const override;
void UpdateLayout() override;
@@ -78,7 +78,6 @@ class LayoutSVGForeignObject final : public LayoutSVGBlock {
PaintLayerType LayerTypeRequired() const override;
private:
- bool AllowsOverflowClip() const override;
LayoutUnit ElementX() const;
LayoutUnit ElementY() const;
LayoutUnit ElementWidth() const;
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc
index 6736f00c101..fe6dd0835ba 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object_test.cc
@@ -284,8 +284,9 @@ TEST_F(LayoutSVGForeignObjectTest,
EXPECT_EQ(foreignObject, GetDocument().ElementFromPoint(205, 255));
HitTestRequest request(HitTestRequest::kReadOnly | HitTestRequest::kActive);
- HitTestResult result(request, LayoutPoint(206, 206));
- GetDocument().GetLayoutView()->Layer()->HitTest(result);
+ HitTestLocation location((LayoutPoint(206, 206)));
+ HitTestResult result(request, location);
+ GetDocument().GetLayoutView()->HitTest(location, result);
EXPECT_EQ(target, result.InnerNode());
EXPECT_EQ(LayoutPoint(206, 206), result.PointInInnerNodeFrame());
}
@@ -309,18 +310,57 @@ TEST_F(LayoutSVGForeignObjectTest,
const auto& svg = *GetDocument().getElementById("svg");
const auto& target = *GetDocument().getElementById("target");
- const auto& foreignObject = *GetDocument().getElementById("foreignObject");
+ const auto& foreign_object = *GetDocument().getElementById("foreignObject");
EXPECT_EQ(svg, GetDocument().ElementFromPoint(1, 1));
- EXPECT_EQ(foreignObject, GetDocument().ElementFromPoint(231, 201));
+ EXPECT_EQ(foreign_object, GetDocument().ElementFromPoint(231, 201));
EXPECT_EQ(target, GetDocument().ElementFromPoint(236, 206));
- EXPECT_EQ(foreignObject, GetDocument().ElementFromPoint(235, 255));
+ EXPECT_EQ(foreign_object, GetDocument().ElementFromPoint(235, 255));
HitTestRequest request(HitTestRequest::kReadOnly | HitTestRequest::kActive);
- HitTestResult result(request, LayoutPoint(236, 206));
- GetDocument().GetLayoutView()->Layer()->HitTest(result);
+ HitTestLocation location((LayoutPoint(236, 206)));
+ HitTestResult result(request, location);
+ GetDocument().GetLayoutView()->HitTest(location, result);
EXPECT_EQ(target, result.InnerNode());
EXPECT_EQ(LayoutPoint(236, 206), result.PointInInnerNodeFrame());
}
+TEST_F(LayoutSVGForeignObjectTest, HitTestUnderScrollingAncestor) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ * {
+ margin: 0
+ }
+ </style>
+ <div id=scroller style="width: 500px; height: 500px; overflow: auto">
+ <svg width="3000" height="3000">
+ <foreignObject width="3000" height="3000">
+ <div id="target" style="width: 3000px; height: 3000px; background: red">
+ </div>
+ </foreignObject>
+ </svg>
+ </div>
+ )HTML");
+
+ auto& scroller = *GetDocument().getElementById("scroller");
+ const auto& target = *GetDocument().getElementById("target");
+
+ EXPECT_EQ(target, GetDocument().ElementFromPoint(450, 450));
+
+ HitTestRequest request(HitTestRequest::kReadOnly | HitTestRequest::kActive);
+ HitTestLocation location((LayoutPoint(450, 450)));
+ HitTestResult result(request, location);
+ GetDocument().GetLayoutView()->HitTest(location, result);
+ EXPECT_EQ(target, result.InnerNode());
+ EXPECT_EQ(LayoutPoint(450, 450), result.PointInInnerNodeFrame());
+
+ scroller.setScrollTop(3000);
+
+ EXPECT_EQ(target, GetDocument().ElementFromPoint(450, 450));
+
+ GetDocument().GetLayoutView()->HitTest(location, result);
+ EXPECT_EQ(target, result.InnerNode());
+ EXPECT_EQ(LayoutPoint(450, 450), result.PointInInnerNodeFrame());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.h b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.h
index 28bbe38aef3..a5228b1a8e2 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_hidden_container.h
@@ -44,7 +44,7 @@ class LayoutSVGHiddenContainer : public LayoutSVGContainer {
private:
// LayoutSVGHiddenContainer paints nothing.
- void Paint(const PaintInfo&, const LayoutPoint&) const final {}
+ void Paint(const PaintInfo&) const final {}
bool PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const final {
return true;
}
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc
index 9e1f3e87b08..97934da411b 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.cc
@@ -143,8 +143,7 @@ void LayoutSVGImage::UpdateLayout() {
ClearNeedsLayout();
}
-void LayoutSVGImage::Paint(const PaintInfo& paint_info,
- const LayoutPoint&) const {
+void LayoutSVGImage::Paint(const PaintInfo& paint_info) const {
SVGImagePainter(*this).Paint(paint_info);
}
@@ -170,9 +169,10 @@ bool LayoutSVGImage::NodeAtFloatPoint(HitTestResult& result,
if (hit_rules.can_hit_fill || hit_rules.can_hit_bounding_box) {
if (object_bounding_box_.Contains(local_point)) {
const LayoutPoint& local_layout_point = LayoutPoint(local_point);
+ HitTestLocation location(local_layout_point);
UpdateHitTestResult(result, local_layout_point);
- if (result.AddNodeToListBasedTestResult(
- GetElement(), local_layout_point) == kStopHitTesting)
+ if (result.AddNodeToListBasedTestResult(GetElement(), location) ==
+ kStopHitTesting)
return true;
}
}
@@ -196,12 +196,4 @@ void LayoutSVGImage::ImageChanged(WrappedImagePtr,
SetShouldDoFullPaintInvalidation(PaintInvalidationReason::kImage);
}
-void LayoutSVGImage::AddOutlineRects(Vector<LayoutRect>& rects,
- const LayoutPoint&,
- IncludeBlockVisualOverflowOrNot) const {
- // this is called from paint() after the localTransform has already been
- // applied
- rects.push_back(LayoutRect(VisualRectInLocalSVGCoordinates()));
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.h b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.h
index 4b834d11d15..3507df8c5b3 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_image.h
@@ -58,16 +58,12 @@ class LayoutSVGImage final : public LayoutSVGModelObject {
private:
FloatRect StrokeBoundingBox() const override { return object_bounding_box_; }
- void AddOutlineRects(Vector<LayoutRect>&,
- const LayoutPoint& additional_offset,
- IncludeBlockVisualOverflowOrNot) const override;
-
void ImageChanged(WrappedImagePtr,
CanDeferInvalidation,
const IntRect* = nullptr) override;
void UpdateLayout() override;
- void Paint(const PaintInfo&, const LayoutPoint&) const override;
+ void Paint(const PaintInfo&) const override;
bool UpdateBoundingBox();
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
index c8708e90b56..4704f6dd071 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.cc
@@ -87,6 +87,15 @@ void LayoutSVGModelObject::AbsoluteQuads(Vector<FloatQuad>& quads,
quads.push_back(LocalToAbsoluteQuad(StrokeBoundingBox(), mode));
}
+// This method is called from inside PaintOutline(), and since we call
+// PaintOutline() while transformed to our coord system, return local coords.
+void LayoutSVGModelObject::AddOutlineRects(
+ Vector<LayoutRect>& rects,
+ const LayoutPoint&,
+ IncludeBlockVisualOverflowOrNot) const {
+ rects.push_back(LayoutRect(VisualRectInLocalSVGCoordinates()));
+}
+
FloatRect LayoutSVGModelObject::LocalBoundingBoxRectForAccessibility() const {
return StrokeBoundingBox();
}
@@ -148,12 +157,4 @@ bool LayoutSVGModelObject::NodeAtPoint(HitTestResult&,
return false;
}
-// The SVG addOutlineRects() method adds rects in local coordinates so the
-// default absoluteElementBoundingBoxRect() returns incorrect values for SVG
-// objects. Overriding this method provides access to the absolute bounds.
-IntRect LayoutSVGModelObject::AbsoluteElementBoundingBoxRect() const {
- return LocalToAbsoluteQuad(FloatQuad(VisualRectInLocalSVGCoordinates()))
- .EnclosingBoundingBox();
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h
index 8aa97b793eb..386623b322d 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h
@@ -100,7 +100,9 @@ class LayoutSVGModelObject : public LayoutObject {
const HitTestLocation& location_in_container,
const LayoutPoint& accumulated_offset,
HitTestAction) final;
- IntRect AbsoluteElementBoundingBoxRect() const final;
+ void AddOutlineRects(Vector<LayoutRect>&,
+ const LayoutPoint& additional_offset,
+ IncludeBlockVisualOverflowOrNot) const final;
protected:
FloatRect local_visual_rect_;
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_path.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_path.cc
index a3eee4a939e..76c671628c6 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_path.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_path.cc
@@ -51,9 +51,7 @@ void LayoutSVGPath::WillBeDestroyed() {
void LayoutSVGPath::UpdateShapeFromElement() {
LayoutSVGShape::UpdateShapeFromElement();
- ProcessMarkerPositions();
-
- stroke_bounding_box_ = CalculateUpdatedStrokeBoundingBox();
+ UpdateMarkers();
}
FloatRect LayoutSVGPath::HitTestStrokeBoundingBox() const {
@@ -62,71 +60,47 @@ FloatRect LayoutSVGPath::HitTestStrokeBoundingBox() const {
return ApproximateStrokeBoundingBox(fill_bounding_box_);
}
-FloatRect LayoutSVGPath::CalculateUpdatedStrokeBoundingBox() const {
- FloatRect stroke_bounding_box = stroke_bounding_box_;
- if (!marker_positions_.IsEmpty())
- stroke_bounding_box.Unite(MarkerRect(StrokeWidth()));
- return stroke_bounding_box;
-}
+void LayoutSVGPath::UpdateMarkers() {
+ marker_positions_.clear();
-FloatRect LayoutSVGPath::MarkerRect(float stroke_width) const {
- DCHECK(!marker_positions_.IsEmpty());
+ if (!StyleRef().SvgStyle().HasMarkers() ||
+ !SVGResources::SupportsMarkers(*ToSVGGraphicsElement(GetElement())))
+ return;
SVGResources* resources =
SVGResourcesCache::CachedResourcesForLayoutObject(*this);
- DCHECK(resources);
+ if (!resources)
+ return;
LayoutSVGResourceMarker* marker_start = resources->MarkerStart();
LayoutSVGResourceMarker* marker_mid = resources->MarkerMid();
LayoutSVGResourceMarker* marker_end = resources->MarkerEnd();
- DCHECK(marker_start || marker_mid || marker_end);
+ if (!(marker_start || marker_mid || marker_end))
+ return;
- FloatRect boundaries;
- unsigned size = marker_positions_.size();
- for (unsigned i = 0; i < size; ++i) {
- if (LayoutSVGResourceMarker* marker = SVGMarkerData::MarkerForType(
- marker_positions_[i].type, marker_start, marker_mid, marker_end))
- boundaries.Unite(marker->MarkerBoundaries(marker->MarkerTransformation(
- marker_positions_[i].origin, marker_positions_[i].angle,
- stroke_width)));
+ {
+ SVGMarkerData marker_data(
+ marker_positions_,
+ marker_start &&
+ marker_start->OrientType() == kSVGMarkerOrientAutoStartReverse);
+ GetPath().Apply(&marker_data, SVGMarkerData::UpdateFromPathElement);
+ marker_data.PathIsDone();
}
- return boundaries;
-}
-
-bool LayoutSVGPath::ShouldGenerateMarkerPositions() const {
- if (!Style()->SvgStyle().HasMarkers())
- return false;
- if (!SVGResources::SupportsMarkers(*ToSVGGraphicsElement(GetElement())))
- return false;
-
- SVGResources* resources =
- SVGResourcesCache::CachedResourcesForLayoutObject(*this);
- if (!resources)
- return false;
-
- return resources->MarkerStart() || resources->MarkerMid() ||
- resources->MarkerEnd();
-}
-
-void LayoutSVGPath::ProcessMarkerPositions() {
- marker_positions_.clear();
-
- if (!ShouldGenerateMarkerPositions())
+ if (marker_positions_.IsEmpty())
return;
- SVGResources* resources =
- SVGResourcesCache::CachedResourcesForLayoutObject(*this);
- DCHECK(resources);
-
- LayoutSVGResourceMarker* marker_start = resources->MarkerStart();
+ const float stroke_width = StrokeWidth();
+ FloatRect boundaries;
+ for (const auto& position : marker_positions_) {
+ if (LayoutSVGResourceMarker* marker = SVGMarkerData::MarkerForType(
+ position.type, marker_start, marker_mid, marker_end)) {
+ boundaries.Unite(marker->MarkerBoundaries(marker->MarkerTransformation(
+ position.origin, position.angle, stroke_width)));
+ }
+ }
- SVGMarkerData marker_data(marker_positions_,
- marker_start ? marker_start->OrientType() ==
- kSVGMarkerOrientAutoStartReverse
- : false);
- GetPath().Apply(&marker_data, SVGMarkerData::UpdateFromPathElement);
- marker_data.PathIsDone();
+ stroke_bounding_box_.Unite(boundaries);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_path.h b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_path.h
index b1f6c080e44..b7e127d53b5 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_path.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_path.h
@@ -47,11 +47,8 @@ class LayoutSVGPath final : public LayoutSVGShape {
void UpdateShapeFromElement() override;
FloatRect HitTestStrokeBoundingBox() const override;
- FloatRect CalculateUpdatedStrokeBoundingBox() const;
- FloatRect MarkerRect(float stroke_width) const;
- bool ShouldGenerateMarkerPositions() const;
- void ProcessMarkerPositions();
+ void UpdateMarkers();
Vector<MarkerPosition> marker_positions_;
};
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc
index 5be8e9757a3..08521d86d0a 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_clipper.cc
@@ -194,7 +194,7 @@ sk_sp<const PaintRecord> LayoutSVGResourceClipper::CreatePaintRecord() {
// Use the LayoutObject of the direct child even if it is a <use>. In that
// case, we will paint the targeted element indirectly.
const LayoutObject* layout_object = child_element.GetLayoutObject();
- layout_object->Paint(info, IntPoint());
+ layout_object->Paint(info);
}
cached_paint_record_ = builder.EndRecording();
@@ -244,8 +244,8 @@ bool LayoutSVGResourceClipper::HitTestClipContent(
Traversal<SVGElement>::ChildrenOf(*GetElement())) {
if (!ContributesToClip(child_element))
continue;
- IntPoint hit_point;
- HitTestResult result(HitTestRequest::kSVGClipContent, hit_point);
+ HitTestLocation location((LayoutPoint()));
+ HitTestResult result(HitTestRequest::kSVGClipContent, location);
LayoutObject* layout_object = child_element.GetLayoutObject();
DCHECK(!layout_object->IsBoxModelObject() ||
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.cc
index af180fc1017..a78a21d8688 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.cc
@@ -28,7 +28,6 @@
#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/core/paint/svg_paint_context.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
#include "third_party/blink/renderer/core/svg/svg_fit_to_view_box.h"
#include "third_party/blink/renderer/core/svg/svg_pattern_element.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
@@ -215,7 +214,7 @@ sk_sp<PaintRecord> LayoutSVGResourcePattern::AsPaintRecord(
child = child->NextSibling())
SVGPaintContext::PaintResourceSubtree(builder.Context(), child);
PaintRecorder paint_recorder;
- PaintCanvas* canvas = paint_recorder.beginRecording(bounds);
+ cc::PaintCanvas* canvas = paint_recorder.beginRecording(bounds);
canvas->save();
canvas->concat(AffineTransformToSkMatrix(tile_transform));
builder.EndRecording(*canvas);
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 caa1a0d5809..a7b509a274d 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
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/frame/frame_owner.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/layout/hit_test_result.h"
+#include "third_party/blink/renderer/core/layout/intrinsic_sizing_info.h"
#include "third_party/blink/renderer/core/layout/layout_analyzer.h"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
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 70952638ac7..a79fff4435a 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
@@ -84,9 +84,6 @@ class CORE_EXPORT LayoutSVGRoot final : public LayoutReplaced {
}
bool ShouldApplyViewportClip() const;
- bool ShouldClipOverflow() const override {
- return LayoutBox::ShouldClipOverflow() || ShouldApplyViewportClip();
- }
LayoutRect VisualOverflowRect() const override;
@@ -97,6 +94,10 @@ class CORE_EXPORT LayoutSVGRoot final : public LayoutReplaced {
bool PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const final;
private:
+ bool ComputeShouldClipOverflow() const override {
+ return LayoutBox::ComputeShouldClipOverflow() || ShouldApplyViewportClip();
+ }
+
const LayoutObjectChildList* Children() const { return &children_; }
LayoutObjectChildList* Children() { return &children_; }
@@ -116,7 +117,8 @@ class CORE_EXPORT LayoutSVGRoot final : public LayoutReplaced {
LayoutUnit ComputeReplacedLogicalHeight(
LayoutUnit estimated_used_width = LayoutUnit()) const override;
void UpdateLayout() override;
- void PaintReplaced(const PaintInfo&, const LayoutPoint&) const override;
+ void PaintReplaced(const PaintInfo&,
+ const LayoutPoint& paint_offset) const override;
void WillBeDestroyed() override;
void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
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 7d84e24d65c..452e6ad9342 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
@@ -342,19 +342,10 @@ void LayoutSVGShape::UpdateNonScalingStrokeData() {
rare_data.non_scaling_stroke_path_.Transform(t);
}
-void LayoutSVGShape::Paint(const PaintInfo& paint_info,
- const LayoutPoint&) const {
+void LayoutSVGShape::Paint(const PaintInfo& paint_info) const {
SVGShapePainter(*this).Paint(paint_info);
}
-// This method is called from inside paintOutline() since we call paintOutline()
-// while transformed to our coord system, return local coords
-void LayoutSVGShape::AddOutlineRects(Vector<LayoutRect>& rects,
- const LayoutPoint&,
- IncludeBlockVisualOverflowOrNot) const {
- rects.push_back(LayoutRect(VisualRectInLocalSVGCoordinates()));
-}
-
bool LayoutSVGShape::NodeAtFloatPoint(HitTestResult& result,
const FloatPoint& point_in_parent,
HitTestAction hit_test_action) {
@@ -374,7 +365,8 @@ bool LayoutSVGShape::NodeAtFloatPoint(HitTestResult& result,
hit_rules)) {
const LayoutPoint& local_layout_point = LayoutPoint(local_point);
UpdateHitTestResult(result, local_layout_point);
- if (result.AddNodeToListBasedTestResult(GetElement(), local_layout_point) ==
+ HitTestLocation location(local_layout_point);
+ if (result.AddNodeToListBasedTestResult(GetElement(), location) ==
kStopHitTesting)
return true;
}
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 d2bdfa17f82..0daeb6bdae9 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
@@ -155,10 +155,7 @@ class LayoutSVGShape : public LayoutSVGModelObject {
LayoutSVGModelObject::IsOfType(type);
}
void UpdateLayout() final;
- void Paint(const PaintInfo&, const LayoutPoint&) const final;
- void AddOutlineRects(Vector<LayoutRect>&,
- const LayoutPoint& additional_offset,
- IncludeBlockVisualOverflowOrNot) const final;
+ void Paint(const PaintInfo&) const final;
bool NodeAtFloatPoint(HitTestResult&,
const FloatPoint& point_in_parent,
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc
index 5a85c7afdf3..a27aece4d05 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_text.cc
@@ -328,8 +328,9 @@ bool LayoutSVGText::NodeAtFloatPoint(HitTestResult& result,
ObjectBoundingBox().Contains(local_point)) {
const LayoutPoint& local_layout_point = LayoutPoint(local_point);
UpdateHitTestResult(result, local_layout_point);
- if (result.AddNodeToListBasedTestResult(
- GetElement(), local_layout_point) == kStopHitTesting)
+ HitTestLocation location(local_layout_point);
+ if (result.AddNodeToListBasedTestResult(GetElement(), location) ==
+ kStopHitTesting)
return true;
}
}
@@ -365,8 +366,7 @@ void LayoutSVGText::AbsoluteQuads(Vector<FloatQuad>& quads,
quads.push_back(LocalToAbsoluteQuad(StrokeBoundingBox(), mode));
}
-void LayoutSVGText::Paint(const PaintInfo& paint_info,
- const LayoutPoint&) const {
+void LayoutSVGText::Paint(const PaintInfo& paint_info) const {
SVGTextPainter(*this).Paint(paint_info);
}
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_text.h b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_text.h
index 1523d8f454c..77a6eda5b56 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_text.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/layout_svg_text.h
@@ -71,7 +71,7 @@ class LayoutSVGText final : public LayoutSVGBlock {
return type == kLayoutObjectSVGText || LayoutSVGBlock::IsOfType(type);
}
- void Paint(const PaintInfo&, const LayoutPoint&) const override;
+ void Paint(const PaintInfo&) const override;
bool NodeAtFloatPoint(HitTestResult&,
const FloatPoint& point_in_parent,
HitTestAction) override;
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc b/chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc
index dfaacf6e1e9..6965c0646ab 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc
@@ -57,7 +57,9 @@ void SVGInlineTextBox::DirtyLineBoxes() {
next_box->DirtyLineBoxes();
}
-int SVGInlineTextBox::OffsetForPosition(LayoutUnit, bool) const {
+int SVGInlineTextBox::OffsetForPosition(LayoutUnit,
+ IncludePartialGlyphsOption,
+ BreakGlyphsOption) const {
// SVG doesn't use the standard offset <-> position selection system, as it's
// not suitable for SVGs complex needs. Vertical text selection, inline boxes
// spanning multiple lines (contrary to HTML, etc.)
@@ -80,11 +82,10 @@ int SVGInlineTextBox::OffsetForPositionInFragment(
if (fragment.AffectedByTextLength())
position /= fragment.length_adjust_scale;
- const bool include_partial_glyphs = true;
TextRun text_run = ConstructTextRun(line_layout_item.StyleRef(), fragment);
return fragment.character_offset - Start() +
line_layout_item.ScaledFont().OffsetForPosition(
- text_run, position, include_partial_glyphs);
+ text_run, position, IncludePartialGlyphs, BreakGlyphs);
}
LayoutUnit SVGInlineTextBox::PositionForOffset(int) const {
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h b/chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h
index ced60f14c39..00cbed811a4 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h
+++ b/chromium/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h
@@ -39,7 +39,8 @@ class SVGInlineTextBox final : public InlineTextBox {
void SetLogicalHeight(LayoutUnit height) { logical_height_ = height; }
int OffsetForPosition(LayoutUnit x,
- bool include_partial_glyphs = true) const override;
+ IncludePartialGlyphsOption,
+ BreakGlyphsOption) const override;
LayoutUnit PositionForOffset(int offset) const override;
void Paint(const PaintInfo&,
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/svg_layout_support.cc b/chromium/third_party/blink/renderer/core/layout/svg/svg_layout_support.cc
index 45a7d90fa47..76eb82dd829 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/svg_layout_support.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/svg_layout_support.cc
@@ -39,6 +39,7 @@
#include "third_party/blink/renderer/core/layout/svg/svg_resources_cache.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
+#include "third_party/blink/renderer/core/style/shape_clip_path_operation.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/platform/graphics/stroke_data.h"
#include "third_party/blink/renderer/platform/transforms/transform_state.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/svg/svg_layout_tree_as_text.cc b/chromium/third_party/blink/renderer/core/layout/svg/svg_layout_tree_as_text.cc
index 8dbf9a61289..3510f53ef7b 100644
--- a/chromium/third_party/blink/renderer/core/layout/svg/svg_layout_tree_as_text.cc
+++ b/chromium/third_party/blink/renderer/core/layout/svg/svg_layout_tree_as_text.cc
@@ -49,6 +49,8 @@
#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/core/paint/paint_layer.h"
+#include "third_party/blink/renderer/core/style/reference_clip_path_operation.h"
+#include "third_party/blink/renderer/core/style/style_svg_resource.h"
#include "third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h"
#include "third_party/blink/renderer/core/svg/linear_gradient_attributes.h"
#include "third_party/blink/renderer/core/svg/pattern_attributes.h"
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 b0c868405df..2d2add6f740 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,8 @@
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_paint_server.h"
#include "third_party/blink/renderer/core/layout/svg/svg_resources_cache.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"
#include "third_party/blink/renderer/core/svg/svg_pattern_element.h"
#include "third_party/blink/renderer/core/svg/svg_resource.h"
#include "third_party/blink/renderer/core/svg/svg_tree_scope_resources.h"
diff --git a/chromium/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.cc b/chromium/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.cc
index 55ebf8da585..1a8efd8a9d2 100644
--- a/chromium/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.cc
+++ b/chromium/third_party/blink/renderer/core/layout/table_layout_algorithm_auto.cc
@@ -208,12 +208,25 @@ void TableLayoutAlgorithmAuto::FullRecalc() {
static bool ShouldScaleColumnsForParent(LayoutTable* table) {
LayoutBlock* cb = table->ContainingBlock();
+ // TODO(layout-dev): We can probably abort before reaching LayoutView in many
+ // cases. For example, if we find an object with contain:size, or even if we
+ // find a regular block with fixed logical width.
while (!cb->IsLayoutView()) {
// It doesn't matter if our table is auto or fixed: auto means we don't
// scale. Fixed doesn't care if we do or not because it doesn't depend
// on the cell contents' preferred widths.
if (cb->IsTableCell())
return false;
+ // The max logical width of a table may be "infinity" (or kTableMaxWidth, to
+ // be more exact) if the sum of the columns' percentages is 100% or more,
+ // AND there is at least one column that has a non-percentage-based positive
+ // logical width. In such situations no table logical width will be large
+ // enough to satisfy the constraint set by the contents. So the idea is to
+ // use ~infinity to make sure we use all available size in the containing
+ // block. However, this just doesn't work if this is a flex or grid item, so
+ // disallow scaling in that case.
+ if (cb->IsFlexibleBox() || cb->IsLayoutGrid())
+ return false;
cb = cb->ContainingBlock();
}
return true;
diff --git a/chromium/third_party/blink/renderer/core/layout/text_autosizer.cc b/chromium/third_party/blink/renderer/core/layout/text_autosizer.cc
index 234d7eb8b66..e819f7b4442 100644
--- a/chromium/third_party/blink/renderer/core/layout/text_autosizer.cc
+++ b/chromium/third_party/blink/renderer/core/layout/text_autosizer.cc
@@ -39,6 +39,7 @@
#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"
+#include "third_party/blink/renderer/core/frame/viewport_data.h"
#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/html/forms/html_text_area_element.h"
#include "third_party/blink/renderer/core/layout/layout_block.h"
@@ -50,6 +51,8 @@
#include "third_party/blink/renderer/core/layout/layout_table.h"
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_block_node.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/platform/geometry/int_rect.h"
@@ -100,7 +103,7 @@ static bool IsPotentialClusterRoot(const LayoutObject* layout_object) {
if (layout_object->IsInline() &&
!layout_object->Style()->IsDisplayReplacedType())
return false;
- if (layout_object->IsListItem())
+ if (layout_object->IsListItemIncludingNG())
return (layout_object->IsFloating() ||
layout_object->IsOutOfFlowPositioned());
@@ -457,13 +460,13 @@ float TextAutosizer::Inflate(LayoutObject* parent,
if (has_text_child) {
ApplyMultiplier(parent, multiplier,
layouter); // Parent handles line spacing.
- } else if (!parent->IsListItem()) {
+ } else if (!parent->IsListItemIncludingNG()) {
// For consistency, a block with no immediate text child should always have
// a multiplier of 1.
ApplyMultiplier(parent, 1, layouter);
}
- if (parent->IsListItem()) {
+ if (parent->IsListItemIncludingNG()) {
float multiplier = ClusterMultiplier(cluster);
ApplyMultiplier(parent, multiplier, layouter);
@@ -471,10 +474,18 @@ float TextAutosizer::Inflate(LayoutObject* parent,
// that you have a list item for a form inside it. The list marker then ends
// up inside the form and when we try to get the clusterMultiplier we have
// the wrong cluster root to work from and get the wrong value.
- LayoutListItem* item = ToLayoutListItem(parent);
- if (LayoutListMarker* marker = item->Marker()) {
- ApplyMultiplier(marker, multiplier, layouter);
- marker->SetPreferredLogicalWidthsDirty(kMarkOnlyThis);
+ LayoutObject* marker = nullptr;
+ if (parent->IsListItem())
+ marker = ToLayoutListItem(parent)->Marker();
+ else if (parent->IsLayoutNGListItem())
+ marker = ToLayoutNGListItem(parent)->Marker();
+
+ // A LayoutNGListMarker has a text child that needs its font multiplier
+ // updated. Just mark the entire subtree, to make sure we get to it.
+ for (LayoutObject* walker = marker; walker;
+ walker = walker->NextInPreOrder(marker)) {
+ ApplyMultiplier(walker, multiplier, layouter);
+ walker->SetPreferredLogicalWidthsDirty(kMarkOnlyThis);
}
}
@@ -592,7 +603,8 @@ void TextAutosizer::UpdatePageInfo() {
// If the page has a meta viewport or @viewport, don't apply the device
// scale adjustment.
if (!main_frame.GetDocument()
- ->GetViewportDescription()
+ ->GetViewportData()
+ .GetViewportDescription()
.IsSpecifiedByAuthor()) {
page_info_.device_scale_adjustment_ =
document_->GetSettings()->GetDeviceScaleAdjustment();
@@ -962,7 +974,8 @@ float TextAutosizer::WidthFromBlock(const LayoutBlock* block) const {
CHECK(block);
CHECK(block->Style());
- if (!(block->IsTable() || block->IsTableCell() || block->IsListItem()))
+ if (!(block->IsTable() || block->IsTableCell() ||
+ block->IsListItemIncludingNG()))
return block->ContentLogicalWidth().ToFloat();
if (!block->ContainingBlock())
@@ -1080,7 +1093,7 @@ const LayoutObject* TextAutosizer::FindTextLeaf(
size_t& depth,
TextLeafSearch first_or_last) const {
// List items are treated as text due to the marker.
- if (parent->IsListItem())
+ if (parent->IsListItemIncludingNG())
return parent;
if (parent->IsText())
@@ -1149,6 +1162,7 @@ void TextAutosizer::ApplyMultiplier(LayoutObject* layout_object,
layout_object->SetNeedsLayoutAndFullPaintInvalidation(
LayoutInvalidationReason::kTextAutosizing, kMarkContainerChain,
layouter);
+ layout_object->MarkContainerNeedsCollectInlines();
break;
case kLayoutNeeded:
@@ -1334,6 +1348,35 @@ TextAutosizer::DeferUpdatePageInfo::DeferUpdatePageInfo(Page* page)
}
}
+TextAutosizer::NGLayoutScope::NGLayoutScope(const NGBlockNode& node,
+ LayoutUnit inline_size)
+ : text_autosizer_(node.GetLayoutBox()->GetDocument().GetTextAutosizer()),
+ block_(ToLayoutBlockFlow(node.GetLayoutBox())) {
+ if (!text_autosizer_ || !text_autosizer_->ShouldHandleLayout() ||
+ block_->IsLayoutNGListMarker()) {
+ // Bail if text autosizing isn't enabled, but also if this is a
+ // IsLayoutNGListMarker. They are super-small blocks, and using them to
+ // determine if we should autosize the text will typically always yield
+ // false, overriding whatever its parent (typically the list item) has
+ // already correctly determined.
+ text_autosizer_ = nullptr;
+ return;
+ }
+
+ // In order for the text autosizer to do anything useful at all, it needs to
+ // know the inline size of the block. So set it. LayoutNG normally writes back
+ // to the legacy tree *after* layout, but this one must be set before, at
+ // least if the autosizer is enabled.
+ block_->SetLogicalWidth(inline_size);
+
+ text_autosizer_->BeginLayout(block_, nullptr);
+}
+
+TextAutosizer::NGLayoutScope::~NGLayoutScope() {
+ if (text_autosizer_)
+ text_autosizer_->EndLayout(block_);
+}
+
TextAutosizer::DeferUpdatePageInfo::~DeferUpdatePageInfo() {
if (TextAutosizer* text_autosizer =
main_frame_->GetDocument()->GetTextAutosizer()) {
diff --git a/chromium/third_party/blink/renderer/core/layout/text_autosizer.h b/chromium/third_party/blink/renderer/core/layout/text_autosizer.h
index fd7a5aa759e..ad1deecc343 100644
--- a/chromium/third_party/blink/renderer/core/layout/text_autosizer.h
+++ b/chromium/third_party/blink/renderer/core/layout/text_autosizer.h
@@ -36,6 +36,7 @@
#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/layout_unit.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
@@ -49,6 +50,7 @@ class LayoutObject;
class LayoutTable;
class LayoutText;
class LocalFrame;
+class NGBlockNode;
class Page;
class SubtreeLayoutScope;
@@ -93,6 +95,18 @@ class CORE_EXPORT TextAutosizer final
explicit TableLayoutScope(LayoutTable*);
};
+ class NGLayoutScope {
+ STACK_ALLOCATED();
+
+ public:
+ explicit NGLayoutScope(const NGBlockNode& node, LayoutUnit inline_size);
+ ~NGLayoutScope();
+
+ protected:
+ Member<TextAutosizer> text_autosizer_;
+ LayoutBlock* block_;
+ };
+
class CORE_EXPORT DeferUpdatePageInfo {
STACK_ALLOCATED();
diff --git a/chromium/third_party/blink/renderer/core/layout/visual_rect_mapping_test.cc b/chromium/third_party/blink/renderer/core/layout/visual_rect_mapping_test.cc
index f890185dda6..ede3906bcba 100644
--- a/chromium/third_party/blink/renderer/core/layout/visual_rect_mapping_test.cc
+++ b/chromium/third_party/blink/renderer/core/layout/visual_rect_mapping_test.cc
@@ -6,6 +6,7 @@
#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/paint_layer.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/paint/paint_property_tree_printer.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
@@ -22,7 +23,7 @@ class VisualRectMappingTest : public PaintTestConfigurations,
protected:
LayoutView& GetLayoutView() const { return *GetDocument().GetLayoutView(); }
- enum Flags { ContainsEnclosingIntRect = 1 << 0, AdjustForBacking = 1 << 1 };
+ enum Flags { kContainsEnclosingIntRect = 1 << 0 };
void CheckPaintInvalidationVisualRect(
const LayoutObject& object,
@@ -35,16 +36,7 @@ class VisualRectMappingTest : public PaintTestConfigurations,
if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
EXPECT_EQ(&ancestor, &object.ContainerForPaintInvalidation());
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(expected_visual_rect_in_ancestor, object.VisualRect());
- if (!object.FirstFragment().NextFragment()) {
- EXPECT_EQ(expected_visual_rect_in_ancestor,
- object.FirstFragment().VisualRect());
- }
- }
-
- CheckVisualRect(object, ancestor, rect, expected_visual_rect_in_ancestor,
- AdjustForBacking);
+ CheckVisualRect(object, ancestor, rect, expected_visual_rect_in_ancestor);
}
void CheckVisualRect(const LayoutObject& object,
@@ -74,7 +66,6 @@ class VisualRectMappingTest : public PaintTestConfigurations,
// The following condition can be false if paintInvalidationContainer is
// a LayoutView and compositing is not enabled.
if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled() &&
- (flags && AdjustForBacking) &&
ancestor.IsPaintInvalidationContainer()) {
PaintLayer::MapRectInPaintInvalidationContainerToBacking(ancestor,
slow_map_rect);
@@ -83,7 +74,7 @@ class VisualRectMappingTest : public PaintTestConfigurations,
geometry_mapper_rect = FloatClipRect(FloatRect(temp));
}
- if (flags & ContainsEnclosingIntRect) {
+ if (flags & kContainsEnclosingIntRect) {
EXPECT_TRUE(
EnclosingIntRect(slow_map_rect)
.Contains(EnclosingIntRect(expected_visual_rect_in_ancestor)));
@@ -217,7 +208,7 @@ TEST_P(VisualRectMappingTest, LayoutView) {
// This case involves clipping: frame height is 50, y-coordinate of result
// rect is 13, so height should be clipped to (50 - 13) == 37.
- ChildDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
+ ChildDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0, 47), kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
@@ -292,7 +283,7 @@ TEST_P(VisualRectMappingTest, LayoutViewDisplayNone) {
// This part is copied from the LayoutView test, just to ensure that the
// mapped rect is valid before display:none is set on the iframe.
- ChildDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
+ ChildDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0, 47), kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
@@ -810,7 +801,7 @@ TEST_P(VisualRectMappingTest, ShouldAccountForPreserve3d) {
LayoutRect output(matrix.MapRect(FloatRect(original_rect)));
CheckVisualRect(*target, *target->View(), original_rect, output,
- ContainsEnclosingIntRect);
+ kContainsEnclosingIntRect);
}
TEST_P(VisualRectMappingTest, ShouldAccountForPreserve3dNested) {
@@ -874,7 +865,7 @@ TEST_P(VisualRectMappingTest, ShouldAccountForPerspective) {
LayoutRect output(matrix.MapRect(FloatRect(original_rect)));
CheckVisualRect(*target, *target->View(), original_rect, output,
- ContainsEnclosingIntRect);
+ kContainsEnclosingIntRect);
}
TEST_P(VisualRectMappingTest, ShouldAccountForPerspectiveNested) {
@@ -978,7 +969,7 @@ TEST_P(VisualRectMappingTest, FixedContentsInIframe) {
LayoutRect(0, 0, 400, 300), fixed,
root_view, kDefaultVisualRectFlags, true);
- ChildDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
+ ChildDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0, 50), kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
@@ -1012,8 +1003,8 @@ TEST_P(VisualRectMappingTest, FixedContentsWithScrollOffset) {
LayoutRect(0, -10, 400, 300), fixed,
ancestor, kDefaultVisualRectFlags, true);
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 50), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 50),
+ kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
// The fixed element does not scroll but the ancestor does which changes the
@@ -1040,8 +1031,8 @@ TEST_P(VisualRectMappingTest, FixedContentsUnderViewWithScrollOffset) {
LayoutRect(0, 0, 400, 300), LayoutRect(0, 0, 400, 300), fixed,
fixed->View(), kDefaultVisualRectFlags, true);
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 50), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 50),
+ kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
// Results of mapping to ancestor are in absolute coordinates of the
diff --git a/chromium/third_party/blink/renderer/core/layout/web_font_rendering_win.cc b/chromium/third_party/blink/renderer/core/layout/web_font_rendering_win.cc
index c13d619fed9..108d583bd5d 100644
--- a/chromium/third_party/blink/renderer/core/layout/web_font_rendering_win.cc
+++ b/chromium/third_party/blink/renderer/core/layout/web_font_rendering_win.cc
@@ -14,11 +14,6 @@ void WebFontRendering::SetSkiaFontManager(sk_sp<SkFontMgr> font_mgr) {
}
// static
-void WebFontRendering::SetDeviceScaleFactor(float device_scale_factor) {
- FontCache::SetDeviceScaleFactor(device_scale_factor);
-}
-
-// static
void WebFontRendering::AddSideloadedFontForTesting(sk_sp<SkTypeface> typeface) {
FontCache::AddSideloadedFontForTesting(std::move(typeface));
}
diff --git a/chromium/third_party/blink/renderer/core/loader/BUILD.gn b/chromium/third_party/blink/renderer/core/loader/BUILD.gn
index 82f6e8bc9d3..49b4ead3dc5 100644
--- a/chromium/third_party/blink/renderer/core/loader/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/loader/BUILD.gn
@@ -44,6 +44,8 @@ blink_core_sources("loader") {
"idleness_detector.h",
"image_loader.cc",
"image_loader.h",
+ "importance_attribute.cc",
+ "importance_attribute.h",
"interactive_detector.cc",
"interactive_detector.h",
"link_loader.cc",
@@ -66,8 +68,10 @@ blink_core_sources("loader") {
"modulescript/module_tree_linker.h",
"modulescript/module_tree_linker_registry.cc",
"modulescript/module_tree_linker_registry.h",
- "modulescript/worker_or_worklet_module_script_fetcher.cc",
- "modulescript/worker_or_worklet_module_script_fetcher.h",
+ "modulescript/worker_module_script_fetcher.cc",
+ "modulescript/worker_module_script_fetcher.h",
+ "modulescript/worklet_module_script_fetcher.cc",
+ "modulescript/worklet_module_script_fetcher.h",
"navigation_policy.cc",
"navigation_policy.h",
"navigation_scheduler.cc",
@@ -77,6 +81,8 @@ blink_core_sources("loader") {
"ping_loader.h",
"prerenderer_client.cc",
"prerenderer_client.h",
+ "previews_resource_loading_hints_receiver_impl.cc",
+ "previews_resource_loading_hints_receiver_impl.h",
"private/frame_client_hints_preferences_context.cc",
"private/frame_client_hints_preferences_context.h",
"private/prerender_handle.cc",
diff --git a/chromium/third_party/blink/renderer/core/loader/allowed_by_nosniff_test.cc b/chromium/third_party/blink/renderer/core/loader/allowed_by_nosniff_test.cc
index 227f7a04f2e..9cf9722758e 100644
--- a/chromium/third_party/blink/renderer/core/loader/allowed_by_nosniff_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/allowed_by_nosniff_test.cc
@@ -20,6 +20,7 @@ class AllowedByNosniffTest : public testing::Test {
// Create a new dummy page holder for each test, so that we get a fresh
// set of counters for each.
dummy_page_holder_ = DummyPageHolder::Create();
+ Page::InsertOrdinaryPageForTesting(&dummy_page_holder_->GetPage());
}
Document* doc() { return &dummy_page_holder_->GetDocument(); }
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 7c26de4bf4b..f0aa3cdf1ac 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
@@ -25,16 +25,15 @@
#include "third_party/blink/renderer/core/loader/appcache/application_cache.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#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/dom/exception_code.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/core/frame/hosts_using_features.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/use_counter.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/platform/bindings/exception_state.h"
namespace blink {
@@ -68,7 +67,8 @@ void ApplicationCache::update(ExceptionState& exception_state) {
ApplicationCacheHost* cache_host = GetApplicationCacheHost();
if (!cache_host || !cache_host->Update()) {
exception_state.ThrowDOMException(
- kInvalidStateError, "there is no application cache to update.");
+ DOMExceptionCode::kInvalidStateError,
+ "there is no application cache to update.");
}
}
@@ -77,7 +77,8 @@ void ApplicationCache::swapCache(ExceptionState& exception_state) {
ApplicationCacheHost* cache_host = GetApplicationCacheHost();
if (!cache_host || !cache_host->SwapCache()) {
exception_state.ThrowDOMException(
- kInvalidStateError, "there is no newer application cache to swap to.");
+ DOMExceptionCode::kInvalidStateError,
+ "there is no newer application cache to swap to.");
}
}
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 8410f306917..e9ff97a6719 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
@@ -37,7 +37,6 @@
#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_vector.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/deprecation.h"
@@ -53,6 +52,7 @@
#include "third_party/blink/renderer/core/page/frame_tree.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.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/weborigin/security_origin.h"
@@ -165,7 +165,8 @@ void ApplicationCacheHost::SelectCacheWithManifest(const KURL& manifest_url) {
// navigation algorithm. The navigation will not result in the same resource
// being loaded, because "foreign" entries are never picked during
// navigation. see ApplicationCacheGroup::selectCache()
- frame->Navigate(*document, document->Url(), true, UserGestureStatus::kNone);
+ frame->ScheduleNavigation(*document, document->Url(), true,
+ UserGestureStatus::kNone);
}
}
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 de4869abd54..996c07442f3 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
@@ -17,7 +17,6 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_priority.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loading_log.h"
-#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
#include "third_party/blink/renderer/platform/weborigin/origin_access_entry.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
@@ -87,6 +86,21 @@ const char* GetDestinationFromContext(WebURLRequest::RequestContext context) {
return "";
}
+MessageSource ConvertLogSourceToMessageSource(FetchContext::LogSource source) {
+ // When LogSource is extended, this switch statement should be modified to
+ // convert LogSource to blink::MessageSource.
+ switch (source) {
+ case FetchContext::kJSSource:
+ return kJSMessageSource;
+ case FetchContext::kSecuritySource:
+ return kSecurityMessageSource;
+ case FetchContext::kOtherSource:
+ return kOtherMessageSource;
+ }
+ NOTREACHED();
+ return kOtherMessageSource;
+}
+
} // namespace
void BaseFetchContext::AddAdditionalRequestHeaders(ResourceRequest& request,
@@ -95,8 +109,10 @@ void BaseFetchContext::AddAdditionalRequestHeaders(ResourceRequest& request,
if (!is_main_resource) {
if (!request.DidSetHTTPReferrer()) {
request.SetHTTPReferrer(SecurityPolicy::GenerateReferrer(
- GetReferrerPolicy(), request.Url(), GetOutgoingReferrer()));
- request.SetHTTPOriginIfNeeded(GetSecurityOrigin());
+ GetFetchClientSettingsObject()->GetReferrerPolicy(), request.Url(),
+ GetFetchClientSettingsObject()->GetOutgoingReferrer()));
+ request.SetHTTPOriginIfNeeded(
+ GetFetchClientSettingsObject()->GetSecurityOrigin());
} else {
DCHECK_EQ(SecurityPolicy::GenerateReferrer(request.GetReferrerPolicy(),
request.Url(),
@@ -131,10 +147,9 @@ void BaseFetchContext::AddAdditionalRequestHeaders(ResourceRequest& request,
}
}
- String value = String::Format(
- "cause=%s, destination=%s, target=subresource, site=%s",
- request.HasUserGesture() ? "user-activation" : "forced",
- destination_value, site_value);
+ String value =
+ String::Format("destination=%s, target=subresource, site=%s",
+ destination_value, site_value);
request.AddHTTPHeaderField("Sec-Metadata", AtomicString(value));
}
}
@@ -159,22 +174,16 @@ base::Optional<ResourceRequestBlockedReason> BaseFetchContext::CanRequest(
return blocked_reason;
}
-void BaseFetchContext::AddWarningConsoleMessage(const String& message,
- LogSource source) const {
- // When LogSource is extended, this DCHECK should be replaced with a logic to
- // convert LogSource to blink::MessageSource.
- DCHECK_EQ(source, kJSSource);
- AddConsoleMessage(
- ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, message));
+void BaseFetchContext::AddInfoConsoleMessage(const String& message,
+ LogSource source) const {
+ AddConsoleMessage(ConsoleMessage::Create(
+ ConvertLogSourceToMessageSource(source), kInfoMessageLevel, message));
}
void BaseFetchContext::AddErrorConsoleMessage(const String& message,
LogSource source) const {
- // When LogSource is extended, this DCHECK should be replaced with a logic to
- // convert LogSource to blink::MessageSource.
- DCHECK_EQ(source, kJSSource);
- AddConsoleMessage(
- ConsoleMessage::Create(kJSMessageSource, kErrorMessageLevel, message));
+ AddConsoleMessage(ConsoleMessage::Create(
+ ConvertLogSourceToMessageSource(source), kErrorMessageLevel, message));
}
bool BaseFetchContext::IsAdResource(
@@ -211,15 +220,6 @@ void BaseFetchContext::PrintAccessDeniedMessage(const KURL& url) const {
kErrorMessageLevel, message));
}
-void BaseFetchContext::AddCSPHeaderIfNecessary(Resource::Type type,
- ResourceRequest& request) {
- const ContentSecurityPolicy* csp = GetContentSecurityPolicy();
- if (!csp)
- return;
- if (csp->ShouldSendCSPHeader(type))
- request.AddHTTPHeaderField("CSP", "active");
-}
-
base::Optional<ResourceRequestBlockedReason>
BaseFetchContext::CheckCSPForRequest(
WebURLRequest::RequestContext request_context,
@@ -412,33 +412,6 @@ BaseFetchContext::CanRequestInternal(
return base::nullopt;
}
-base::Optional<ResourceRequestBlockedReason>
-BaseFetchContext::CheckResponseNosniff(
- WebURLRequest::RequestContext request_context,
- const ResourceResponse& response) const {
- bool sniffing_allowed =
- ParseContentTypeOptionsHeader(response.HttpHeaderField(
- HTTPNames::X_Content_Type_Options)) != kContentTypeOptionsNosniff;
- if (sniffing_allowed)
- return base::nullopt;
-
- String mime_type = response.HttpContentType();
- if (request_context == WebURLRequest::kRequestContextStyle &&
- !MIMETypeRegistry::IsSupportedStyleSheetMIMEType(mime_type)) {
- AddConsoleMessage(ConsoleMessage::Create(
- kSecurityMessageSource, kErrorMessageLevel,
- "Refused to apply style from '" + response.Url().ElidedString() +
- "' because its MIME type ('" + mime_type + "') " +
- "is not a supported stylesheet MIME type, and strict MIME checking "
- "is enabled."));
- return ResourceRequestBlockedReason::kContentType;
- }
- // TODO(mkwst): Move the 'nosniff' bit of 'AllowedByNosniff::MimeTypeAsScript'
- // here alongside the style checks, and put its use counters somewhere else.
-
- return base::nullopt;
-}
-
void BaseFetchContext::Trace(blink::Visitor* visitor) {
FetchContext::Trace(visitor);
}
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 55b53796b16..3bb6b18d7fa 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
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/web_feature_forward.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_context.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
@@ -44,12 +45,11 @@ class CORE_EXPORT BaseFetchContext : public FetchContext {
const ResourceLoaderOptions&,
SecurityViolationReportingPolicy,
ResourceRequest::RedirectStatus) const override;
- base::Optional<ResourceRequestBlockedReason> CheckResponseNosniff(
- WebURLRequest::RequestContext,
- const ResourceResponse&) const override;
void Trace(blink::Visitor*) override;
+ virtual const FetchClientSettingsObject* GetFetchClientSettingsObject()
+ const = 0;
virtual KURL GetSiteForCookies() const = 0;
virtual SubresourceFilter* GetSubresourceFilter() const = 0;
virtual void CountUsage(WebFeature) const = 0;
@@ -58,7 +58,7 @@ class CORE_EXPORT BaseFetchContext : public FetchContext {
virtual std::unique_ptr<WebSocketHandshakeThrottle>
CreateWebSocketHandshakeThrottle() = 0;
- void AddWarningConsoleMessage(const String&, LogSource) const override;
+ void AddInfoConsoleMessage(const String&, LogSource) const override;
void AddErrorConsoleMessage(const String&, LogSource) const override;
bool IsAdResource(const KURL&,
Resource::Type,
@@ -86,8 +86,6 @@ class CORE_EXPORT BaseFetchContext : public FetchContext {
SecurityViolationReportingPolicy) const = 0;
virtual bool ShouldBlockFetchAsCredentialedSubresource(const ResourceRequest&,
const KURL&) const = 0;
- virtual ReferrerPolicy GetReferrerPolicy() const = 0;
- virtual String GetOutgoingReferrer() const = 0;
virtual const KURL& Url() const = 0;
virtual const SecurityOrigin* GetParentSecurityOrigin() const = 0;
virtual base::Optional<mojom::IPAddressSpace> GetAddressSpace() const = 0;
@@ -95,11 +93,9 @@ class CORE_EXPORT BaseFetchContext : public FetchContext {
virtual void AddConsoleMessage(ConsoleMessage*) const = 0;
- // Utility method that can be used to implement other methods.
+ private:
void PrintAccessDeniedMessage(const KURL&) const;
- void AddCSPHeaderIfNecessary(Resource::Type, ResourceRequest&);
- private:
// Utility methods that are used in default implement for CanRequest,
// CanFollowRedirect and AllowResponse.
base::Optional<ResourceRequestBlockedReason> CanRequestInternal(
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 fda0338ab1e..e6937a748a9 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
@@ -33,6 +33,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/websocket_handshake_throttle.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h"
#include "third_party/blink/renderer/core/testing/null_execution_context.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
@@ -42,10 +43,16 @@ namespace blink {
class MockBaseFetchContext final : public BaseFetchContext {
public:
explicit MockBaseFetchContext(ExecutionContext* execution_context)
- : execution_context_(execution_context) {}
+ : execution_context_(execution_context),
+ fetch_client_settings_object_(
+ new FetchClientSettingsObjectImpl(*execution_context)) {}
~MockBaseFetchContext() override = default;
// BaseFetchContext overrides:
+ const FetchClientSettingsObject* GetFetchClientSettingsObject()
+ const override {
+ return fetch_client_settings_object_.Get();
+ }
KURL GetSiteForCookies() const override { return KURL(); }
bool AllowScriptFromSource(const KURL&) const override { return false; }
SubresourceFilter* GetSubresourceFilter() const override { return nullptr; }
@@ -79,16 +86,10 @@ class MockBaseFetchContext final : public BaseFetchContext {
const KURL&) const override {
return false;
}
- ReferrerPolicy GetReferrerPolicy() const override {
- return execution_context_->GetReferrerPolicy();
- }
- String GetOutgoingReferrer() const override {
- return execution_context_->OutgoingReferrer();
- }
const KURL& Url() const override { return execution_context_->Url(); }
const SecurityOrigin* GetSecurityOrigin() const override {
- return execution_context_->GetSecurityOrigin();
+ return fetch_client_settings_object_->GetSecurityOrigin();
}
const SecurityOrigin* GetParentSecurityOrigin() const override {
return nullptr;
@@ -104,6 +105,7 @@ class MockBaseFetchContext final : public BaseFetchContext {
void Trace(blink::Visitor* visitor) override {
visitor->Trace(execution_context_);
+ visitor->Trace(fetch_client_settings_object_);
BaseFetchContext::Trace(visitor);
}
@@ -112,6 +114,7 @@ class MockBaseFetchContext final : public BaseFetchContext {
private:
Member<ExecutionContext> execution_context_;
+ Member<FetchClientSettingsObjectImpl> fetch_client_settings_object_;
bool is_detached_ = false;
};
diff --git a/chromium/third_party/blink/renderer/core/loader/document_load_timing.cc b/chromium/third_party/blink/renderer/core/loader/document_load_timing.cc
index c07aa85f0a5..4bd6c65b6b9 100644
--- a/chromium/third_party/blink/renderer/core/loader/document_load_timing.cc
+++ b/chromium/third_party/blink/renderer/core/loader/document_load_timing.cc
@@ -34,8 +34,7 @@
namespace blink {
DocumentLoadTiming::DocumentLoadTiming(DocumentLoader& document_loader)
- : reference_wall_time_(0.0),
- redirect_count_(0),
+ : redirect_count_(0),
has_cross_origin_redirect_(false),
has_same_origin_as_previous_document_(false),
document_loader_(document_loader) {}
@@ -55,37 +54,24 @@ void DocumentLoadTiming::NotifyDocumentTimingChanged() {
}
void DocumentLoadTiming::EnsureReferenceTimesSet() {
- if (!reference_wall_time_)
- reference_wall_time_ = CurrentTime();
+ if (reference_wall_time_.is_zero())
+ reference_wall_time_ = TimeDelta::FromSecondsD(CurrentTime());
if (reference_monotonic_time_.is_null())
reference_monotonic_time_ = CurrentTimeTicks();
}
-double DocumentLoadTiming::MonotonicTimeToZeroBasedDocumentTime(
+TimeDelta DocumentLoadTiming::MonotonicTimeToZeroBasedDocumentTime(
TimeTicks monotonic_time) const {
if (monotonic_time.is_null() || reference_monotonic_time_.is_null())
- return 0.0;
- return (monotonic_time - reference_monotonic_time_).InSecondsF();
+ return TimeDelta();
+ return monotonic_time - reference_monotonic_time_;
}
-double DocumentLoadTiming::MonotonicTimeToPseudoWallTime(
+TimeDelta DocumentLoadTiming::MonotonicTimeToPseudoWallTime(
TimeTicks monotonic_time) const {
if (monotonic_time.is_null() || reference_monotonic_time_.is_null())
- return 0.0;
- return (monotonic_time + TimeDelta::FromSecondsD(reference_wall_time_) -
- reference_monotonic_time_)
- .InSecondsF();
-}
-
-TimeTicks DocumentLoadTiming::PseudoWallTimeToMonotonicTime(
- double pseudo_wall_time) const {
- if (!pseudo_wall_time)
- return TimeTicks();
- DCHECK_GE(TimeTicksInSeconds(reference_monotonic_time_) + pseudo_wall_time -
- reference_wall_time_,
- 0);
- return reference_monotonic_time_ +
- TimeDelta::FromSecondsD(pseudo_wall_time - reference_wall_time_);
+ return TimeDelta();
+ return monotonic_time + reference_wall_time_ - reference_monotonic_time_;
}
void DocumentLoadTiming::MarkNavigationStart() {
@@ -93,11 +79,11 @@ void DocumentLoadTiming::MarkNavigationStart() {
// they have a more accurate timestamp.
if (!navigation_start_.is_null()) {
DCHECK(!reference_monotonic_time_.is_null());
- DCHECK(reference_wall_time_);
+ DCHECK(!reference_wall_time_.is_zero());
return;
}
DCHECK(reference_monotonic_time_.is_null());
- DCHECK(!reference_wall_time_);
+ DCHECK(reference_wall_time_.is_zero());
EnsureReferenceTimesSet();
navigation_start_ = reference_monotonic_time_;
TRACE_EVENT_MARK_WITH_TIMESTAMP2(
@@ -128,7 +114,7 @@ void DocumentLoadTiming::SetNavigationStart(TimeTicks navigation_start) {
// The reference times are adjusted based on the embedder's navigationStart.
DCHECK(!reference_monotonic_time_.is_null());
- DCHECK(reference_wall_time_);
+ DCHECK(!reference_wall_time_.is_zero());
reference_wall_time_ = MonotonicTimeToPseudoWallTime(navigation_start);
reference_monotonic_time_ = navigation_start;
NotifyDocumentTimingChanged();
diff --git a/chromium/third_party/blink/renderer/core/loader/document_load_timing.h b/chromium/third_party/blink/renderer/core/loader/document_load_timing.h
index 20e23aea5f2..afe09495e27 100644
--- a/chromium/third_party/blink/renderer/core/loader/document_load_timing.h
+++ b/chromium/third_party/blink/renderer/core/loader/document_load_timing.h
@@ -43,9 +43,8 @@ class CORE_EXPORT DocumentLoadTiming final {
public:
explicit DocumentLoadTiming(DocumentLoader&);
- double MonotonicTimeToZeroBasedDocumentTime(TimeTicks) const;
- double MonotonicTimeToPseudoWallTime(TimeTicks) const;
- TimeTicks PseudoWallTimeToMonotonicTime(double) const;
+ TimeDelta MonotonicTimeToZeroBasedDocumentTime(TimeTicks) const;
+ TimeDelta MonotonicTimeToPseudoWallTime(TimeTicks) const;
void MarkNavigationStart();
void SetNavigationStart(TimeTicks);
@@ -100,7 +99,7 @@ class CORE_EXPORT DocumentLoadTiming final {
std::unique_ptr<TracedValue> GetNavigationStartTracingData() const;
TimeTicks reference_monotonic_time_;
- double reference_wall_time_;
+ TimeDelta reference_wall_time_;
TimeTicks navigation_start_;
TimeTicks unload_event_start_;
TimeTicks unload_event_end_;
diff --git a/chromium/third_party/blink/renderer/core/loader/document_load_timing_test.cc b/chromium/third_party/blink/renderer/core/loader/document_load_timing_test.cc
index e1264bdb000..4f03a743fad 100644
--- a/chromium/third_party/blink/renderer/core/loader/document_load_timing_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/document_load_timing_test.cc
@@ -22,10 +22,10 @@ TEST_F(DocumentLoadTimingTest, ensureValidNavigationStartAfterEmbedder) {
timing.SetNavigationStart(TimeTicksFromSeconds(embedder_navigation_start));
double real_wall_time = CurrentTime();
- double adjusted_wall_time =
+ TimeDelta adjusted_wall_time =
timing.MonotonicTimeToPseudoWallTime(timing.NavigationStart());
- EXPECT_NEAR(adjusted_wall_time, real_wall_time + delta, .001);
+ EXPECT_NEAR(adjusted_wall_time.InSecondsF(), real_wall_time + delta, .001);
}
TEST_F(DocumentLoadTimingTest, correctTimingDeltas) {
@@ -43,15 +43,17 @@ TEST_F(DocumentLoadTimingTest, correctTimingDeltas) {
// dominated by the navigationStartDelta, but similar to currentTime().
timing.MarkLoadEventEnd();
double real_wall_load_event_end = CurrentTime();
- double adjusted_load_event_end =
+ TimeDelta adjusted_load_event_end =
timing.MonotonicTimeToPseudoWallTime(timing.LoadEventEnd());
- EXPECT_NEAR(adjusted_load_event_end, real_wall_load_event_end, .001);
+ EXPECT_NEAR(adjusted_load_event_end.InSecondsF(), real_wall_load_event_end,
+ .001);
- double adjusted_navigation_start =
+ TimeDelta adjusted_navigation_start =
timing.MonotonicTimeToPseudoWallTime(timing.NavigationStart());
- EXPECT_NEAR(adjusted_load_event_end - adjusted_navigation_start,
- -navigation_start_delta, .001);
+ EXPECT_NEAR(
+ (adjusted_load_event_end - adjusted_navigation_start).InSecondsF(),
+ -navigation_start_delta, .001);
}
} // namespace blink
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 8865e24d502..0b35e877723 100644
--- a/chromium/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/document_loader.cc
@@ -31,11 +31,12 @@
#include <memory>
#include "base/auto_reset.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/web/web_history_commit_type.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/document_parser.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/dom/scriptable_document_parser.h"
@@ -69,6 +70,7 @@
#include "third_party/blink/renderer/core/loader/resource/script_resource.h"
#include "third_party/blink/renderer/core/loader/subresource_filter.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
+#include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
#include "third_party/blink/renderer/core/page/frame_tree.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
@@ -85,6 +87,7 @@
#include "third_party/blink/renderer/platform/mhtml/archive_resource.h"
#include "third_party/blink/renderer/platform/mhtml/mhtml_archive.h"
#include "third_party/blink/renderer/platform/network/content_security_policy_response_headers.h"
+#include "third_party/blink/renderer/platform/network/encoded_form_data.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/network/mime/mime_type_registry.h"
@@ -116,12 +119,12 @@ DocumentLoader::DocumentLoader(
original_request_(req),
substitute_data_(substitute_data),
request_(req),
- load_type_(kFrameLoadTypeStandard),
+ load_type_(WebFrameLoadType::kStandard),
is_client_redirect_(client_redirect_policy ==
ClientRedirectPolicy::kClientRedirect),
replaces_current_history_item_(false),
data_received_(false),
- navigation_type_(kNavigationTypeOther),
+ navigation_type_(kWebNavigationTypeOther),
document_load_timing_(*this),
application_cache_host_(ApplicationCacheHost::Create(this)),
was_blocked_after_csp_(false),
@@ -130,7 +133,10 @@ DocumentLoader::DocumentLoader(
in_data_received_(false),
data_buffer_(SharedBuffer::Create()),
devtools_navigation_token_(devtools_navigation_token),
- user_activated_(false) {
+ user_activated_(false),
+ use_counter_(frame_->GetChromeClient().IsSVGImageChromeClient()
+ ? UseCounter::kSVGImageContext
+ : UseCounter::kDefaultContext) {
DCHECK(frame_);
// The document URL needs to be added to the head of the list as that is
@@ -171,6 +177,7 @@ void DocumentLoader::Trace(blink::Visitor* visitor) {
visitor->Trace(document_load_timing_);
visitor->Trace(application_cache_host_);
visitor->Trace(content_security_policy_);
+ visitor->Trace(use_counter_);
RawResourceClient::Trace(visitor);
}
@@ -284,19 +291,19 @@ void DocumentLoader::MarkAsCommitted() {
state_ = kCommitted;
}
-static HistoryCommitType LoadTypeToCommitType(FrameLoadType type) {
+static WebHistoryCommitType LoadTypeToCommitType(WebFrameLoadType type) {
switch (type) {
- case kFrameLoadTypeStandard:
- return kStandardCommit;
- case kFrameLoadTypeInitialInChildFrame:
- case kFrameLoadTypeInitialHistoryLoad:
- return kInitialCommitInChildFrame;
- case kFrameLoadTypeBackForward:
- return kBackForwardCommit;
- default:
- break;
+ case WebFrameLoadType::kStandard:
+ return kWebStandardCommit;
+ case WebFrameLoadType::kBackForward:
+ return kWebBackForwardCommit;
+ case WebFrameLoadType::kReload:
+ case WebFrameLoadType::kReplaceCurrentItem:
+ case WebFrameLoadType::kReloadBypassingCache:
+ return kWebHistoryInertCommit;
}
- return kHistoryInertCommit;
+ NOTREACHED();
+ return kWebHistoryInertCommit;
}
void DocumentLoader::UpdateForSameDocumentNavigation(
@@ -304,17 +311,17 @@ void DocumentLoader::UpdateForSameDocumentNavigation(
SameDocumentNavigationSource same_document_navigation_source,
scoped_refptr<SerializedScriptValue> data,
HistoryScrollRestorationType scroll_restoration_type,
- FrameLoadType type,
+ WebFrameLoadType type,
Document* initiating_document) {
- if (type == kFrameLoadTypeStandard && initiating_document &&
+ if (type == WebFrameLoadType::kStandard && initiating_document &&
!initiating_document->CanCreateHistoryEntry()) {
- type = kFrameLoadTypeReplaceCurrentItem;
+ type = WebFrameLoadType::kReplaceCurrentItem;
}
KURL old_url = request_.Url();
original_request_.SetURL(new_url);
request_.SetURL(new_url);
- SetReplacesCurrentHistoryItem(type != kFrameLoadTypeStandard);
+ SetReplacesCurrentHistoryItem(type != WebFrameLoadType::kStandard);
if (same_document_navigation_source == kSameDocumentNavigationHistoryApi) {
request_.SetHTTPMethod(HTTPNames::GET);
request_.SetHTTPBody(nullptr);
@@ -334,9 +341,9 @@ void DocumentLoader::UpdateForSameDocumentNavigation(
history_item_->SetStateObject(std::move(data));
history_item_->SetScrollRestorationType(scroll_restoration_type);
}
- HistoryCommitType commit_type = LoadTypeToCommitType(type);
+ WebHistoryCommitType commit_type = LoadTypeToCommitType(type);
frame_->GetFrameScheduler()->DidCommitProvisionalLoad(
- commit_type == kHistoryInertCommit, type == kFrameLoadTypeReload,
+ commit_type == kWebHistoryInertCommit, type == WebFrameLoadType::kReload,
frame_->IsLocalRoot());
GetLocalFrameClient().DidFinishSameDocumentNavigation(
history_item_.Get(), commit_type, initiating_document);
@@ -349,7 +356,7 @@ const KURL& DocumentLoader::UrlForHistory() const {
void DocumentLoader::SetHistoryItemStateForCommit(
HistoryItem* old_item,
- FrameLoadType load_type,
+ WebFrameLoadType load_type,
HistoryNavigationType navigation_type) {
if (!history_item_ || !IsBackForwardLoadType(load_type))
history_item_ = HistoryItem::Create();
@@ -369,9 +376,9 @@ void DocumentLoader::SetHistoryItemStateForCommit(
// navigation, unless the before and after pages are logically related. This
// means they have the same url (ignoring fragment) and the new item was
// loaded via reload or client redirect.
- HistoryCommitType history_commit_type = LoadTypeToCommitType(load_type);
+ WebHistoryCommitType history_commit_type = LoadTypeToCommitType(load_type);
if (navigation_type == HistoryNavigationType::kDifferentDocument &&
- (history_commit_type != kHistoryInertCommit ||
+ (history_commit_type != kWebHistoryInertCommit ||
!EqualIgnoringFragmentIdentifier(old_item->Url(), history_item_->Url())))
return;
history_item_->SetDocumentSequenceNumber(old_item->DocumentSequenceNumber());
@@ -384,7 +391,7 @@ void DocumentLoader::SetHistoryItemStateForCommit(
// a no-op. Only treat this as identical if the navigation did not create a
// back/forward entry and the url is identical or it was loaded via
// history.replaceState().
- if (history_commit_type == kHistoryInertCommit &&
+ if (history_commit_type == kWebHistoryInertCommit &&
(navigation_type == HistoryNavigationType::kHistoryApi ||
old_item->Url() == history_item_->Url())) {
history_item_->SetStateObject(old_item->StateObject());
@@ -405,9 +412,9 @@ void DocumentLoader::NotifyFinished(Resource* resource) {
application_cache_host_->FailedLoadingMainResource();
if (resource->GetResourceError().WasBlockedByResponse()) {
- probe::CanceledAfterReceivedResourceResponse(
- frame_, this, MainResourceIdentifier(), resource->GetResponse(),
- resource);
+ probe::didReceiveResourceResponse(frame_->GetDocument(),
+ MainResourceIdentifier(), this,
+ resource->GetResponse(), resource);
}
LoadFailed(resource->GetResourceError());
@@ -419,7 +426,7 @@ void DocumentLoader::LoadFailed(const ResourceError& error) {
frame_->Owner()->RenderFallbackContent();
fetcher_->ClearResourcesFromPreviousFetcher();
- HistoryCommitType history_commit_type = LoadTypeToCommitType(load_type_);
+ WebHistoryCommitType history_commit_type = LoadTypeToCommitType(load_type_);
switch (state_) {
case kNotStarted:
probe::frameClearedScheduledClientNavigation(frame_);
@@ -507,13 +514,6 @@ bool DocumentLoader::RedirectReceived(
fetcher_->StopFetching();
return false;
}
- if (GetFrameLoader().ShouldContinueForRedirectNavigationPolicy(
- request_, SubstituteData(), this, kCheckContentSecurityPolicy,
- navigation_type_, kNavigationPolicyCurrentTab, load_type_,
- IsClientRedirect(), nullptr) != kNavigationPolicyCurrentTab) {
- fetcher_->StopFetching();
- return false;
- }
DCHECK(!GetTiming().FetchStart().is_null());
AppendRedirect(request_url);
@@ -524,8 +524,8 @@ bool DocumentLoader::RedirectReceived(
// back/forward navigation only. In the other case, clearing it is a no-op.
history_item_.Clear();
- GetLocalFrameClient().DispatchDidReceiveServerRedirectForProvisionalLoad();
-
+ // TODO(creis): Determine if we need to clear any history state
+ // in embedder to fix https://crbug.com/671276.
return true;
}
@@ -562,8 +562,9 @@ bool DocumentLoader::ShouldContinueForResponse() const {
void DocumentLoader::CancelLoadAfterCSPDenied(
const ResourceResponse& response) {
- probe::CanceledAfterReceivedResourceResponse(
- frame_, this, MainResourceIdentifier(), response, GetResource());
+ probe::didReceiveResourceResponse(frame_->GetDocument(),
+ MainResourceIdentifier(), this, response,
+ GetResource());
SetWasBlockedAfterCSP();
@@ -648,8 +649,11 @@ void DocumentLoader::ResponseReceived(
DCHECK(!frame_->GetPage()->Paused());
+ // Pre-commit state, count usage the use counter associated with "this"
+ // (provisional document loader) instead of frame_'s document loader.
if (response.DidServiceWorkerNavigationPreload())
- UseCounter::Count(frame_, WebFeature::kServiceWorkerNavigationPreload);
+ UseCounter::Count(this, WebFeature::kServiceWorkerNavigationPreload);
+
response_ = response;
if (IsArchiveMIMEType(response_.MimeType()) &&
@@ -657,8 +661,9 @@ void DocumentLoader::ResponseReceived(
resource->SetDataBufferingPolicy(kBufferData);
if (!ShouldContinueForResponse()) {
- probe::ContinueWithPolicyIgnore(frame_, this, resource->Identifier(),
- response_, resource);
+ probe::didReceiveResourceResponse(frame_->GetDocument(),
+ resource->Identifier(), this, response_,
+ resource);
fetcher_->StopFetching();
return;
}
@@ -707,12 +712,13 @@ void DocumentLoader::CommitNavigation(const AtomicString& mime_type,
if (!Document::ThreadedParsingEnabledForTesting())
parsing_policy = kForceSynchronousParsing;
- InstallNewDocument(Url(), owner_document,
- frame_->ShouldReuseDefaultView(Url())
- ? WebGlobalObjectReusePolicy::kUseExisting
- : WebGlobalObjectReusePolicy::kCreateNew,
- mime_type, encoding, InstallNewDocumentReason::kNavigation,
- parsing_policy, overriding_url);
+ InstallNewDocument(
+ Url(), owner_document,
+ frame_->ShouldReuseDefaultView(Url(), GetContentSecurityPolicy())
+ ? WebGlobalObjectReusePolicy::kUseExisting
+ : WebGlobalObjectReusePolicy::kCreateNew,
+ mime_type, encoding, InstallNewDocumentReason::kNavigation,
+ parsing_policy, overriding_url);
parser_->SetDocumentWasLoadedAsPartOfNavigation();
if (request_.WasDiscarded())
frame_->GetDocument()->SetWasDiscarded(true);
@@ -771,12 +777,8 @@ void DocumentLoader::ProcessDataBuffer() {
// Process data received in reentrant invocations. Note that the invocations
// of processData() may queue more data in reentrant invocations, so iterate
// until it's empty.
- const char* segment;
- size_t pos = 0;
- while (size_t length = data_buffer_->GetSomeData(segment, pos)) {
- ProcessData(segment, length);
- pos += length;
- }
+ for (const auto& span : *data_buffer_)
+ ProcessData(span.data(), span.size());
// All data has been consumed, so flush the buffer.
data_buffer_->Clear();
}
@@ -844,11 +846,8 @@ bool DocumentLoader::MaybeCreateArchive() {
return false;
scoped_refptr<SharedBuffer> data(main_resource->Data());
- data->ForEachSegment(
- [this](const char* segment, size_t segment_size, size_t segment_offset) {
- CommitData(segment, segment_size);
- return true;
- });
+ for (const auto& span : *data)
+ CommitData(span.data(), span.size());
return true;
}
@@ -907,7 +906,9 @@ void DocumentLoader::DidInstallNewDocument(Document* document) {
if (history_item_ && IsBackForwardLoadType(load_type_))
document->SetStateForNewFormElements(history_item_->GetDocumentState());
- document->GetClientHintsPreferences().UpdateFrom(client_hints_preferences_);
+ DCHECK(document->GetFrame());
+ document->GetFrame()->GetClientHintsPreferences().UpdateFrom(
+ client_hints_preferences_);
// TODO(japhet): There's no reason to wait until commit to set these bits.
Settings* settings = document->GetSettings();
@@ -954,15 +955,18 @@ void DocumentLoader::DidCommitNavigation(
return;
if (!frame_->Loader().StateMachine()->CommittedMultipleRealLoads() &&
- load_type_ == kFrameLoadTypeStandard) {
+ load_type_ == WebFrameLoadType::kStandard) {
frame_->Loader().StateMachine()->AdvanceTo(
FrameLoaderStateMachine::kCommittedMultipleRealLoads);
}
- HistoryCommitType commit_type = LoadTypeToCommitType(load_type_);
+ WebHistoryCommitType commit_type = LoadTypeToCommitType(load_type_);
frame_->GetFrameScheduler()->DidCommitProvisionalLoad(
- commit_type == kHistoryInertCommit, load_type_ == kFrameLoadTypeReload,
- frame_->IsLocalRoot());
+ commit_type == kWebHistoryInertCommit,
+ load_type_ == WebFrameLoadType::kReload, frame_->IsLocalRoot());
+ // When a new navigation commits in the frame, subresource loading should be
+ // resumed.
+ frame_->ResumeSubresourceLoading();
GetLocalFrameClient().DispatchDidCommitLoad(history_item_.Get(), commit_type,
global_object_reuse_policy);
@@ -974,18 +978,15 @@ void DocumentLoader::DidCommitNavigation(
->GetContentSecurityPolicy()
->ReportAccumulatedHeaders(&GetLocalFrameClient());
- // didObserveLoadingBehavior() must be called after dispatchDidCommitLoad() is
+ // DidObserveLoadingBehavior() must be called after DispatchDidCommitLoad() is
// called for the metrics tracking logic to handle it properly.
if (service_worker_network_provider_ &&
- service_worker_network_provider_->HasControllerServiceWorker()) {
+ service_worker_network_provider_->IsControlledByServiceWorker() ==
+ blink::mojom::ControllerServiceWorkerMode::kControlled) {
GetLocalFrameClient().DidObserveLoadingBehavior(
kWebLoadingBehaviorServiceWorkerControlled);
}
- // Links with media values need more information (like viewport information).
- // This happens after the first chunk is parsed in HTMLDocumentParser.
- DispatchLinkHeaderPreloads(nullptr, LinkLoader::kOnlyLoadNonMedia);
-
Document* document = frame_->GetDocument();
InteractiveDetector* interactive_detector =
InteractiveDetector::From(*document);
@@ -994,16 +995,24 @@ void DocumentLoader::DidCommitNavigation(
TRACE_EVENT1("devtools.timeline", "CommitLoad", "data",
InspectorCommitLoadEvent::Data(frame_));
+
+ // Needs to run before dispatching preloads, as it may evict the memory cache.
probe::didCommitLoad(frame_, this);
+
+ // Links with media values need more information (like viewport information).
+ // This happens after the first chunk is parsed in HTMLDocumentParser.
+ DispatchLinkHeaderPreloads(nullptr, LinkLoader::kOnlyLoadNonMedia);
+
frame_->GetPage()->DidCommitLoad(frame_);
+ GetUseCounter().DidCommitLoad(frame_);
// Report legacy Symantec certificates after Page::DidCommitLoad, because the
// latter clears the console.
if (response_.IsLegacySymantecCert()) {
UseCounter::Count(
- frame_, frame_->Tree().Parent()
- ? WebFeature::kLegacySymantecCertInSubframeMainResource
- : WebFeature::kLegacySymantecCertMainFrameResource);
+ this, frame_->Tree().Parent()
+ ? WebFeature::kLegacySymantecCertInSubframeMainResource
+ : WebFeature::kLegacySymantecCertMainFrameResource);
GetLocalFrameClient().ReportLegacySymantecCert(response_.Url(),
false /* did_fail */);
}
@@ -1113,6 +1122,14 @@ void DocumentLoader::InstallNewDocument(
OriginTrialContext::AddTokensFromHeader(
document, response_.HttpHeaderField(HTTPNames::Origin_Trial));
}
+ bool stale_while_revalidate_enabled =
+ OriginTrials::StaleWhileRevalidateEnabled(document);
+ fetcher_->SetStaleWhileRevalidateEnabled(stale_while_revalidate_enabled);
+
+ // If stale while revalidate is enabled via Origin Trials count it as such.
+ if (stale_while_revalidate_enabled &&
+ !RuntimeEnabledFeatures::StaleWhileRevalidateEnabledByRuntimeFlag())
+ UseCounter::Count(frame_, WebFeature::kStaleWhileRevalidateEnabled);
parser_ = document->OpenForNavigation(parsing_policy, mime_type, encoding);
@@ -1179,12 +1196,8 @@ void DocumentLoader::ResumeParser() {
// Append data to the parser that may have been received while the parser
// was blocked.
- const char* segment;
- size_t pos = 0;
- while (size_t length = committed_data_buffer_->GetSomeData(segment, pos)) {
- parser_->AppendBytes(segment, length);
- pos += length;
- }
+ for (const auto& span : *committed_data_buffer_)
+ parser_->AppendBytes(span.data(), span.size());
committed_data_buffer_->Clear();
// DataReceived may be called in a nested message loop.
@@ -1198,11 +1211,29 @@ void DocumentLoader::ResumeParser() {
}
}
-DEFINE_WEAK_IDENTIFIER_MAP(DocumentLoader);
+void DocumentLoader::UpdateNavigationTimings(
+ base::TimeTicks navigation_start_time,
+ base::TimeTicks redirect_start_time,
+ base::TimeTicks redirect_end_time,
+ base::TimeTicks fetch_start_time) {
+ // If we don't have any navigation timings yet, just start the navigation.
+ if (navigation_start_time.is_null()) {
+ GetTiming().SetNavigationStart(CurrentTimeTicks());
+ return;
+ }
-STATIC_ASSERT_ENUM(kWebStandardCommit, kStandardCommit);
-STATIC_ASSERT_ENUM(kWebBackForwardCommit, kBackForwardCommit);
-STATIC_ASSERT_ENUM(kWebInitialCommitInChildFrame, kInitialCommitInChildFrame);
-STATIC_ASSERT_ENUM(kWebHistoryInertCommit, kHistoryInertCommit);
+ GetTiming().SetNavigationStart(navigation_start_time);
+ if (!redirect_start_time.is_null()) {
+ GetTiming().SetRedirectStart(redirect_start_time);
+ GetTiming().SetRedirectEnd(redirect_end_time);
+ }
+ if (!fetch_start_time.is_null()) {
+ // If we started fetching, we should have started the navigation.
+ DCHECK(!navigation_start_time.is_null());
+ GetTiming().SetFetchStart(fetch_start_time);
+ }
+}
+
+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 ae797c37588..ae6d876fe2e 100644
--- a/chromium/third_party/blink/renderer/core/loader/document_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/document_loader.h
@@ -34,18 +34,21 @@
#include "base/memory/scoped_refptr.h"
#include "base/unguessable_token.h"
#include "third_party/blink/public/platform/web_loading_behavior_flag.h"
+#include "third_party/blink/public/web/web_frame_load_type.h"
#include "third_party/blink/public/web/web_global_object_reuse_policy.h"
+#include "third_party/blink/public/web/web_navigation_type.h"
#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/viewport_description.h"
#include "third_party/blink/renderer/core/dom/weak_identifier_map.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/frame_types.h"
+#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/html/parser/parser_synchronization_policy.h"
#include "third_party/blink/renderer/core/loader/document_load_timing.h"
#include "third_party/blink/renderer/core/loader/frame_loader_types.h"
#include "third_party/blink/renderer/core/loader/link_loader.h"
#include "third_party/blink/renderer/core/loader/navigation_policy.h"
+#include "third_party/blink/renderer/core/page/viewport_description.h"
#include "third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h"
#include "third_party/blink/renderer/platform/loader/fetch/raw_resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
@@ -132,7 +135,7 @@ class CORE_EXPORT DocumentLoader
SameDocumentNavigationSource,
scoped_refptr<SerializedScriptValue>,
HistoryScrollRestorationType,
- FrameLoadType,
+ WebFrameLoadType,
Document*);
const ResourceResponse& GetResponse() const { return response_; }
bool IsClientRedirect() const { return is_client_redirect_; }
@@ -160,11 +163,11 @@ class CORE_EXPORT DocumentLoader
void SetSentDidFinishLoad() { state_ = kSentDidFinishLoad; }
bool SentDidFinishLoad() const { return state_ == kSentDidFinishLoad; }
- FrameLoadType LoadType() const { return load_type_; }
- void SetLoadType(FrameLoadType load_type) { load_type_ = load_type; }
+ WebFrameLoadType LoadType() const { return load_type_; }
+ void SetLoadType(WebFrameLoadType load_type) { load_type_ = load_type; }
- NavigationType GetNavigationType() const { return navigation_type_; }
- void SetNavigationType(NavigationType navigation_type) {
+ WebNavigationType GetNavigationType() const { return navigation_type_; }
+ void SetNavigationType(WebNavigationType navigation_type) {
navigation_type_ = navigation_type;
}
@@ -250,6 +253,24 @@ class CORE_EXPORT DocumentLoader
void BlockParser();
void ResumeParser();
+ // Returns the currently stored content security policy, if this is called
+ // after the document has been installed it will return nullptr as the
+ // CSP belongs to the document at that point.
+ const ContentSecurityPolicy* GetContentSecurityPolicy() const {
+ return content_security_policy_.Get();
+ }
+
+ // Updates navigation timings with provided values. This
+ // should be called before WebLocalFrameClient::didCommitProvisionalLoad.
+ // Calling it later may confuse users, because JavaScript may have run and
+ // the user may have already recorded the original value.
+ // Note: if |redirect_start_time| is null, redirect timings are not updated.
+ void UpdateNavigationTimings(base::TimeTicks navigation_start_time,
+ base::TimeTicks redirect_start_time,
+ base::TimeTicks redirect_end_time,
+ base::TimeTicks fetch_start_time);
+ UseCounter& GetUseCounter() { return use_counter_; }
+
protected:
DocumentLoader(LocalFrame*,
const ResourceRequest&,
@@ -303,7 +324,7 @@ class CORE_EXPORT DocumentLoader
kHistoryApi
};
void SetHistoryItemStateForCommit(HistoryItem* old_item,
- FrameLoadType,
+ WebFrameLoadType,
HistoryNavigationType);
// RawResourceClient implementation
@@ -357,13 +378,13 @@ class CORE_EXPORT DocumentLoader
ResourceResponse response_;
- FrameLoadType load_type_;
+ WebFrameLoadType load_type_;
bool is_client_redirect_;
bool replaces_current_history_item_;
bool data_received_;
- NavigationType navigation_type_;
+ WebNavigationType navigation_type_;
DocumentLoadTiming document_load_timing_;
@@ -400,6 +421,12 @@ class CORE_EXPORT DocumentLoader
// Whether this load request comes from a user activation.
bool user_activated_;
+ // This UseCounter tracks feature usage associated with the lifetime of the
+ // document load. Features recorded prior to commit will be recorded locally.
+ // Once commited, feature usage will be piped to the browser side page load
+ // metrics that aggregates usage from frames to one page load and report
+ // feature usage to UMA histograms per page load.
+ UseCounter use_counter_;
};
DECLARE_WEAK_IDENTIFIER_MAP(DocumentLoader);
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 fdca1baa360..fcd037d3b09 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
@@ -114,7 +114,7 @@ TEST_F(DocumentLoaderTest, MultiChunkWithReentrancy) {
DispatchOneByte();
}
- // WebFrameClient overrides:
+ // WebLocalFrameClient overrides:
void FrameDetached(DetachType detach_type) override {
if (dispatching_did_receive_data_) {
// This should be called by the first didReceiveData() call, since
@@ -179,8 +179,8 @@ TEST_F(DocumentLoaderTest, MultiChunkWithReentrancy) {
EXPECT_TRUE(child_delegate.ServedReentrantly());
- // delegate is a WebFrameClient and stack-allocated, so manually reset() the
- // WebViewHelper here.
+ // delegate is a WebLocalFrameClient and stack-allocated, so manually reset()
+ // the WebViewHelper here.
web_view_helper_.Reset();
}
diff --git a/chromium/third_party/blink/renderer/core/loader/document_threadable_loader.cc b/chromium/third_party/blink/renderer/core/loader/document_threadable_loader.cc
index b929ca1f66c..f31e63d0913 100644
--- a/chromium/third_party/blink/renderer/core/loader/document_threadable_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/document_threadable_loader.cc
@@ -34,8 +34,10 @@
#include <memory>
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
+#include "services/network/public/cpp/cors/cors_error_status.h"
#include "services/network/public/mojom/cors.mojom-blink.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
+#include "third_party/blink/public/common/service_worker/service_worker_utils.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_cors.h"
@@ -56,6 +58,7 @@
#include "third_party/blink/renderer/core/loader/threadable_loading_context.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/heap/self_keep_alive.h"
#include "third_party/blink/renderer/platform/loader/cors/cors.h"
#include "third_party/blink/renderer/platform/loader/cors/cors_error_string.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
@@ -271,7 +274,6 @@ DocumentThreadableLoader::DocumentThreadableLoader(
GetExecutionContext()->GetTaskRunner(TaskType::kNetworking),
this,
&DocumentThreadableLoader::DidTimeout),
- request_started_seconds_(0.0),
cors_redirect_limit_(0),
redirect_mode_(network::mojom::FetchRedirectMode::kFollow),
override_referrer_(false) {
@@ -309,8 +311,6 @@ void DocumentThreadableLoader::Start(const ResourceRequest& request) {
// corresponds to this line, but divert |cors_flag_| here for convenience.
if (cors_flag_ && request.GetFetchRequestMode() ==
network::mojom::FetchRequestMode::kSameOrigin) {
- probe::documentThreadableLoaderFailedToStartLoadingForClient(
- GetExecutionContext(), client_);
ThreadableLoaderClient* client = client_;
Clear();
ResourceError error = ResourceError::CancelledDueToAccessCheckError(
@@ -323,7 +323,7 @@ void DocumentThreadableLoader::Start(const ResourceRequest& request) {
return;
}
- request_started_seconds_ = CurrentTimeTicksInSeconds();
+ request_started_ = CurrentTimeTicks();
// Save any headers on the request here. If this request redirects
// cross-origin, we cancel the old request create a new one, and copy these
@@ -340,6 +340,33 @@ void DocumentThreadableLoader::Start(const ResourceRequest& request) {
if (should_bypass_service_worker)
new_request.SetSkipServiceWorker(true);
+ // In S13nServiceWorker, if the controller service worker has no fetch event
+ // handler, it's skipped entirely, so we should treat that case the same as
+ // having no controller. In non-S13nServiceWorker, we can't do that since we
+ // don't know which service worker will handle the request since it's
+ // determined on the browser process and skipWaiting() can happen in the
+ // meantime.
+ //
+ // TODO(crbug.com/715640): When non-S13nServiceWorker is removed,
+ // is_controlled_by_service_worker is the same as
+ // ControllerServiceWorkerMode::kControlled, so this code can be simplified.
+ bool is_controlled_by_service_worker = false;
+ switch (
+ loading_context_->GetResourceFetcher()->IsControlledByServiceWorker()) {
+ case blink::mojom::ControllerServiceWorkerMode::kControlled:
+ is_controlled_by_service_worker = true;
+ break;
+ case blink::mojom::ControllerServiceWorkerMode::kNoFetchEventHandler:
+ if (ServiceWorkerUtils::IsServicificationEnabled())
+ is_controlled_by_service_worker = false;
+ else
+ is_controlled_by_service_worker = true;
+ break;
+ case blink::mojom::ControllerServiceWorkerMode::kNoController:
+ is_controlled_by_service_worker = false;
+ break;
+ }
+
// Process the CORS protocol inside the DocumentThreadableLoader for the
// following cases:
//
@@ -363,7 +390,7 @@ void DocumentThreadableLoader::Start(const ResourceRequest& request) {
if (!async_ || new_request.GetSkipServiceWorker() ||
!SchemeRegistry::ShouldTreatURLSchemeAsAllowingServiceWorkers(
new_request.Url().Protocol()) ||
- !loading_context_->GetResourceFetcher()->IsControlledByServiceWorker()) {
+ !is_controlled_by_service_worker) {
DispatchInitialRequest(new_request);
return;
}
@@ -434,8 +461,6 @@ void DocumentThreadableLoader::MakeCrossOriginAccessRequest(
// send a request, preflighted or not, that's guaranteed to be denied.
if (!SchemeRegistry::ShouldTreatURLSchemeAsCORSEnabled(
request.Url().Protocol())) {
- probe::documentThreadableLoaderFailedToStartLoadingForClient(
- GetExecutionContext(), client_);
DispatchDidFailAccessControlCheck(
ResourceError::CancelledDueToAccessCheckError(
request.Url(), ResourceRequestBlockedReason::kOther,
@@ -543,7 +568,7 @@ void DocumentThreadableLoader::OverrideTimeout(
// |m_requestStartedSeconds| == 0.0 indicates loading is already finished and
// |m_timeoutTimer| is already stopped, and thus we do nothing for such cases.
// See https://crbug.com/551663 for details.
- if (request_started_seconds_ <= 0.0)
+ if (request_started_ <= TimeTicks())
return;
timeout_timer_.Stop();
@@ -555,10 +580,9 @@ void DocumentThreadableLoader::OverrideTimeout(
// was initially sent, however other uses of this method may need to
// behave differently, in which case this should be re-arranged somehow.
if (timeout_milliseconds) {
- double elapsed_time =
- CurrentTimeTicksInSeconds() - request_started_seconds_;
- double next_fire = timeout_milliseconds / 1000.0;
- double resolved_time = std::max(next_fire - elapsed_time, 0.0);
+ TimeDelta elapsed_time = CurrentTimeTicks() - request_started_;
+ TimeDelta next_fire = TimeDelta::FromMilliseconds(timeout_milliseconds);
+ TimeDelta resolved_time = std::max(next_fire - elapsed_time, TimeDelta());
timeout_timer_.StartOneShot(resolved_time, FROM_HERE);
}
}
@@ -590,7 +614,7 @@ void DocumentThreadableLoader::SetDefersLoading(bool value) {
void DocumentThreadableLoader::Clear() {
client_ = nullptr;
timeout_timer_.Stop();
- request_started_seconds_ = 0.0;
+ request_started_ = TimeTicks();
if (GetResource())
checker_.WillRemoveClient();
ClearResource();
@@ -609,7 +633,6 @@ bool DocumentThreadableLoader::RedirectReceived(
const ResourceResponse& redirect_response) {
DCHECK(client_);
DCHECK_EQ(resource, GetResource());
- DCHECK(async_);
checker_.RedirectReceived();
@@ -617,6 +640,7 @@ bool DocumentThreadableLoader::RedirectReceived(
const KURL& original_url = redirect_response.Url();
if (!actual_request_.IsNull()) {
+ DCHECK(!out_of_blink_cors_);
ReportResponseReceived(resource->Identifier(), redirect_response);
HandlePreflightFailure(
@@ -656,6 +680,15 @@ bool DocumentThreadableLoader::RedirectReceived(
return false;
}
+ if (out_of_blink_cors_) {
+ client_->DidReceiveRedirectTo(new_url);
+ if (client_->IsDocumentThreadableLoaderClient()) {
+ return static_cast<DocumentThreadableLoaderClient*>(client_)
+ ->WillFollowRedirect(new_url, redirect_response);
+ }
+ return true;
+ }
+
// Allow same origin requests to continue after allowing clients to audit the
// redirect.
if (IsAllowedRedirect(new_request.GetFetchRequestMode(), new_url)) {
@@ -697,7 +730,7 @@ bool DocumentThreadableLoader::RedirectReceived(
if (cors_flag_) {
// The redirect response must pass the access control check if the CORS
// flag is set.
- base::Optional<network::mojom::CORSError> access_error = CORS::CheckAccess(
+ base::Optional<network::CORSErrorStatus> access_error = CORS::CheckAccess(
original_url, redirect_response.HttpStatusCode(),
redirect_response.HttpHeaderFields(),
new_request.GetFetchCredentialsMode(), *GetSecurityOrigin());
@@ -707,8 +740,7 @@ bool DocumentThreadableLoader::RedirectReceived(
original_url, ResourceRequestBlockedReason::kOther,
CORS::GetErrorString(CORS::ErrorParameter::CreateForAccessCheck(
*access_error, original_url,
- redirect_response.HttpStatusCode(),
- redirect_response.HttpHeaderFields(), *GetSecurityOrigin(),
+ redirect_response.HttpStatusCode(), *GetSecurityOrigin(),
request_context_, new_url))));
return false;
}
@@ -735,7 +767,7 @@ bool DocumentThreadableLoader::RedirectReceived(
scoped_refptr<const SecurityOrigin> new_origin =
SecurityOrigin::Create(new_url);
if (!original_origin->IsSameSchemeHostPort(new_origin.get()))
- security_origin_ = SecurityOrigin::CreateUnique();
+ security_origin_ = SecurityOrigin::CreateUniqueOpaque();
}
// Set |cors_flag_| so that further logic (corresponds to the main fetch in
@@ -791,7 +823,6 @@ void DocumentThreadableLoader::DataDownloaded(Resource* resource,
DCHECK(client_);
DCHECK_EQ(resource, GetResource());
DCHECK(actual_request_.IsNull());
- DCHECK(async_);
checker_.DataDownloaded();
client_->DidDownloadData(data_length);
@@ -802,7 +833,6 @@ void DocumentThreadableLoader::DidReceiveResourceTiming(
const ResourceTimingInfo& info) {
DCHECK(client_);
DCHECK_EQ(resource, GetResource());
- DCHECK(async_);
client_->DidReceiveResourceTiming(info);
}
@@ -812,42 +842,25 @@ void DocumentThreadableLoader::DidDownloadToBlob(
scoped_refptr<BlobDataHandle> blob) {
DCHECK(client_);
DCHECK_EQ(resource, GetResource());
- DCHECK(async_);
checker_.DidDownloadToBlob();
client_->DidDownloadToBlob(std::move(blob));
}
-void DocumentThreadableLoader::ResponseReceived(
- Resource* resource,
- const ResourceResponse& response,
- std::unique_ptr<WebDataConsumerHandle> handle) {
- DCHECK_EQ(resource, GetResource());
- DCHECK(async_);
-
- checker_.ResponseReceived();
-
- if (handle)
- is_using_data_consumer_handle_ = true;
-
- HandleResponse(resource->Identifier(), fetch_request_mode_,
- fetch_credentials_mode_, response, std::move(handle));
-}
void DocumentThreadableLoader::HandlePreflightResponse(
const ResourceResponse& response) {
- base::Optional<network::mojom::CORSError> cors_error =
+ base::Optional<network::CORSErrorStatus> cors_error_status =
CORS::CheckPreflightAccess(response.Url(), response.HttpStatusCode(),
response.HttpHeaderFields(),
actual_request_.GetFetchCredentialsMode(),
*GetSecurityOrigin());
- if (cors_error) {
+ if (cors_error_status) {
HandlePreflightFailure(
response.Url(),
CORS::GetErrorString(CORS::ErrorParameter::CreateForAccessCheck(
- *cors_error, response.Url(), 0 /* do not provide the status_code */,
- response.HttpHeaderFields(), *GetSecurityOrigin(),
- request_context_)));
+ *cors_error_status, response.Url(), 0 /* status_code */,
+ *GetSecurityOrigin(), request_context_)));
return;
}
@@ -862,14 +875,14 @@ void DocumentThreadableLoader::HandlePreflightResponse(
}
if (actual_request_.IsExternalRequest()) {
- base::Optional<network::mojom::CORSError> external_preflight_status =
+ base::Optional<network::CORSErrorStatus> external_preflight_status =
CORS::CheckExternalPreflight(response.HttpHeaderFields());
if (external_preflight_status) {
HandlePreflightFailure(
response.Url(),
CORS::GetErrorString(
CORS::ErrorParameter::CreateForExternalPreflightCheck(
- *external_preflight_status, response.HttpHeaderFields())));
+ *external_preflight_status)));
return;
}
}
@@ -897,27 +910,33 @@ void DocumentThreadableLoader::ReportResponseReceived(
frame->Console().ReportResourceResponseReceived(loader, identifier, response);
}
-void DocumentThreadableLoader::HandleResponse(
- unsigned long identifier,
- network::mojom::FetchRequestMode request_mode,
- network::mojom::FetchCredentialsMode credentials_mode,
+void DocumentThreadableLoader::ResponseReceived(
+ Resource* resource,
const ResourceResponse& response,
std::unique_ptr<WebDataConsumerHandle> handle) {
+ DCHECK_EQ(resource, GetResource());
DCHECK(client_);
+ checker_.ResponseReceived();
+
+ if (handle)
+ is_using_data_consumer_handle_ = true;
+
// TODO(toyoshim): Support OOR-CORS preflight and Service Worker case.
// Note that CORS-preflight is usually handled in the Network Service side,
// but still done in Blink side when it is needed on redirects.
// https://crbug.com/736308.
- if (out_of_blink_cors_ && actual_request_.IsNull() &&
- !response.WasFetchedViaServiceWorker()) {
- client_->DidReceiveResponse(identifier, response, std::move(handle));
+ if (out_of_blink_cors_ && !response.WasFetchedViaServiceWorker()) {
+ DCHECK(actual_request_.IsNull());
+ fallback_request_for_service_worker_ = ResourceRequest();
+ client_->DidReceiveResponse(resource->Identifier(), response,
+ std::move(handle));
return;
}
// Code path for legacy Blink CORS.
if (!actual_request_.IsNull()) {
- ReportResponseReceived(identifier, response);
+ ReportResponseReceived(resource->Identifier(), response);
HandlePreflightResponse(response);
return;
}
@@ -929,7 +948,7 @@ void DocumentThreadableLoader::HandleResponse(
// therefore fallback-to-network is handled in the browser process when
// the ServiceWorker does not call respondWith().)
DCHECK(!fallback_request_for_service_worker_.IsNull());
- ReportResponseReceived(identifier, response);
+ ReportResponseReceived(resource->Identifier(), response);
LoadFallbackRequestForServiceWorker();
return;
}
@@ -939,7 +958,7 @@ void DocumentThreadableLoader::HandleResponse(
// We dispatch a CORS failure for the case.
// TODO(yhirano): This is probably not spec conformant. Fix it after
// https://github.com/w3c/preload/issues/100 is addressed.
- if (request_mode != network::mojom::FetchRequestMode::kNoCORS &&
+ if (fetch_request_mode_ != network::mojom::FetchRequestMode::kNoCORS &&
response.ResponseTypeViaServiceWorker() ==
network::mojom::FetchResponseType::kOpaque) {
DispatchDidFailAccessControlCheck(
@@ -952,7 +971,8 @@ void DocumentThreadableLoader::HandleResponse(
}
fallback_request_for_service_worker_ = ResourceRequest();
- client_->DidReceiveResponse(identifier, response, std::move(handle));
+ client_->DidReceiveResponse(resource->Identifier(), response,
+ std::move(handle));
return;
}
@@ -968,24 +988,24 @@ void DocumentThreadableLoader::HandleResponse(
fallback_request_for_service_worker_.Url()));
fallback_request_for_service_worker_ = ResourceRequest();
- if (CORS::IsCORSEnabledRequestMode(request_mode) && cors_flag_) {
- base::Optional<network::mojom::CORSError> access_error = CORS::CheckAccess(
+ if (CORS::IsCORSEnabledRequestMode(fetch_request_mode_) && cors_flag_) {
+ base::Optional<network::CORSErrorStatus> access_error = CORS::CheckAccess(
response.Url(), response.HttpStatusCode(), response.HttpHeaderFields(),
- credentials_mode, *GetSecurityOrigin());
+ fetch_credentials_mode_, *GetSecurityOrigin());
if (access_error) {
- ReportResponseReceived(identifier, response);
+ ReportResponseReceived(resource->Identifier(), response);
DispatchDidFailAccessControlCheck(
ResourceError::CancelledDueToAccessCheckError(
response.Url(), ResourceRequestBlockedReason::kOther,
CORS::GetErrorString(CORS::ErrorParameter::CreateForAccessCheck(
*access_error, response.Url(), response.HttpStatusCode(),
- response.HttpHeaderFields(), *GetSecurityOrigin(),
- request_context_))));
+ *GetSecurityOrigin(), request_context_))));
return;
}
}
- client_->DidReceiveResponse(identifier, response, std::move(handle));
+ client_->DidReceiveResponse(resource->Identifier(), response,
+ std::move(handle));
}
void DocumentThreadableLoader::SetSerializedCachedMetadata(Resource*,
@@ -1002,47 +1022,41 @@ void DocumentThreadableLoader::DataReceived(Resource* resource,
const char* data,
size_t data_length) {
DCHECK_EQ(resource, GetResource());
- DCHECK(async_);
+ DCHECK(client_);
checker_.DataReceived();
if (is_using_data_consumer_handle_)
return;
- // TODO(junov): Fix the ThreadableLoader ecosystem to use size_t. Until then,
- // we use safeCast to trap potential overflows.
- HandleReceivedData(data, SafeCast<unsigned>(data_length));
-}
-
-void DocumentThreadableLoader::HandleReceivedData(const char* data,
- size_t data_length) {
- DCHECK(client_);
-
// Preflight data should be invisible to clients.
if (!actual_request_.IsNull())
return;
DCHECK(fallback_request_for_service_worker_.IsNull());
- client_->DidReceiveData(data, data_length);
+ // TODO(junov): Fix the ThreadableLoader ecosystem to use size_t. Until then,
+ // we use safeCast to trap potential overflows.
+ client_->DidReceiveData(data, SafeCast<unsigned>(data_length));
}
void DocumentThreadableLoader::NotifyFinished(Resource* resource) {
DCHECK(client_);
DCHECK_EQ(resource, GetResource());
- DCHECK(async_);
checker_.NotifyFinished(resource);
- if (resource->ErrorOccurred()) {
+ // Don't throw an exception for failed sync local file loads.
+ // TODO(japhet): This logic has been moved around but unchanged since 2007.
+ // Tested by fast/xmlhttprequest/xmlhttprequest-missing-file-exception.html
+ // Do we still need this?
+ bool is_sync_to_local_file = resource->Url().IsLocalFile() && !async_;
+
+ if (resource->ErrorOccurred() && !is_sync_to_local_file) {
DispatchDidFail(resource->GetResourceError());
- } else {
- HandleSuccessfulFinish(resource->Identifier());
+ return;
}
-}
-void DocumentThreadableLoader::HandleSuccessfulFinish(
- unsigned long identifier) {
DCHECK(fallback_request_for_service_worker_.IsNull());
if (!actual_request_.IsNull()) {
@@ -1056,7 +1070,7 @@ void DocumentThreadableLoader::HandleSuccessfulFinish(
// downloaded file.
Persistent<Resource> protect = GetResource();
Clear();
- client->DidFinishLoading(identifier);
+ client->DidFinishLoading(resource->Identifier());
}
void DocumentThreadableLoader::DidTimeout(TimerBase* timer) {
@@ -1100,7 +1114,7 @@ void DocumentThreadableLoader::LoadActualRequest() {
void DocumentThreadableLoader::HandlePreflightFailure(
const KURL& url,
const String& error_description) {
- // Prevent handleSuccessfulFinish() from bypassing access check.
+ // Prevent NotifyFinished() from bypassing access check.
actual_request_ = ResourceRequest();
DispatchDidFailAccessControlCheck(
@@ -1124,15 +1138,15 @@ void DocumentThreadableLoader::DispatchDidFail(const ResourceError& error) {
if (error.CORSErrorStatus()) {
DCHECK(out_of_blink_cors_);
// TODO(toyoshim): Should consider to pass correct arguments instead of
- // KURL(), 0, and HTTPHeaderMap() to GetErrorString().
+ // KURL(), and 0 to GetErrorString().
// We still need plumbing some more information.
GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create(
kJSMessageSource, kErrorMessageLevel,
"Failed to load " + error.FailingURL() + ": " +
- CORS::GetErrorString(
- CORS::ErrorParameter::Create(
- *error.CORSErrorStatus(), KURL(error.FailingURL()), KURL(),
- 0, HTTPHeaderMap(), *GetSecurityOrigin(), request_context_))
+ CORS::GetErrorString(CORS::ErrorParameter::Create(
+ *error.CORSErrorStatus(),
+ KURL(error.FailingURL()), KURL(), 0,
+ *GetSecurityOrigin(), request_context_))
.Utf8()
.data()));
}
@@ -1141,127 +1155,6 @@ void DocumentThreadableLoader::DispatchDidFail(const ResourceError& error) {
client->DidFail(error);
}
-void DocumentThreadableLoader::LoadRequestAsync(
- const ResourceRequest& request,
- ResourceLoaderOptions resource_loader_options) {
- if (!actual_request_.IsNull())
- resource_loader_options.data_buffering_policy = kBufferData;
-
- // The timer can be active if this is the actual request of a
- // CORS-with-preflight request.
- if (options_.timeout_milliseconds > 0 && !timeout_timer_.IsActive()) {
- timeout_timer_.StartOneShot(options_.timeout_milliseconds / 1000.0,
- FROM_HERE);
- }
-
- FetchParameters new_params(request, resource_loader_options);
- if (request.GetFetchRequestMode() ==
- network::mojom::FetchRequestMode::kNoCORS) {
- new_params.SetOriginRestriction(FetchParameters::kNoOriginRestriction);
- }
- DCHECK(!GetResource());
-
- ResourceFetcher* fetcher = loading_context_->GetResourceFetcher();
- if (request.GetRequestContext() == WebURLRequest::kRequestContextVideo ||
- request.GetRequestContext() == WebURLRequest::kRequestContextAudio) {
- RawResource::FetchMedia(new_params, fetcher, this);
- } else if (request.GetRequestContext() ==
- WebURLRequest::kRequestContextManifest) {
- RawResource::FetchManifest(new_params, fetcher, this);
- } else {
- RawResource::Fetch(new_params, fetcher, this);
- }
- checker_.WillAddClient();
-
- if (GetResource()->IsLoading()) {
- unsigned long identifier = GetResource()->Identifier();
- probe::documentThreadableLoaderStartedLoadingForClient(
- GetExecutionContext(), identifier, client_);
- } else {
- probe::documentThreadableLoaderFailedToStartLoadingForClient(
- GetExecutionContext(), client_);
- }
-}
-
-void DocumentThreadableLoader::LoadRequestSync(
- const ResourceRequest& request,
- ResourceLoaderOptions resource_loader_options) {
- FetchParameters fetch_params(request, resource_loader_options);
- if (request.GetFetchRequestMode() ==
- network::mojom::FetchRequestMode::kNoCORS) {
- fetch_params.SetOriginRestriction(FetchParameters::kNoOriginRestriction);
- }
- if (options_.timeout_milliseconds > 0) {
- fetch_params.MutableResourceRequest().SetTimeoutInterval(
- options_.timeout_milliseconds / 1000.0);
- }
- RawResource* resource = RawResource::FetchSynchronously(
- fetch_params, loading_context_->GetResourceFetcher());
- ResourceResponse response = resource->GetResponse();
- unsigned long identifier = resource->Identifier();
- probe::documentThreadableLoaderStartedLoadingForClient(GetExecutionContext(),
- identifier, client_);
- ThreadableLoaderClient* client = client_;
- const KURL& request_url = request.Url();
-
- // No exception for file:/// resources, see <rdar://problem/4962298>. Also, if
- // we have an HTTP response, then it wasn't a network error in fact.
- if (resource->LoadFailedOrCanceled() && !request_url.IsLocalFile() &&
- response.HttpStatusCode() <= 0) {
- DispatchDidFail(resource->GetResourceError());
- return;
- }
-
- // FIXME: A synchronous request does not tell us whether a redirect happened
- // or not, so we guess by comparing the request and response URLs. This isn't
- // a perfect test though, since a server can serve a redirect to the same URL
- // that was requested. Also comparing the request and response URLs as strings
- // will fail if the requestURL still has its credentials.
- if (request_url != response.Url() &&
- !IsAllowedRedirect(request.GetFetchRequestMode(), response.Url())) {
- client_ = nullptr;
- client->DidFailRedirectCheck();
- return;
- }
-
- HandleResponse(identifier, request.GetFetchRequestMode(),
- request.GetFetchCredentialsMode(), response, nullptr);
-
- // HandleResponse() may detect an error. In such a case (check |m_client| as
- // it gets reset by clear() call), skip the rest.
- //
- // |this| is alive here since loadResourceSynchronously() keeps it alive until
- // the end of the function.
- if (!client_)
- return;
-
- if (scoped_refptr<const SharedBuffer> data = resource->ResourceBuffer()) {
- data->ForEachSegment([this](const char* segment, size_t segment_size,
- size_t segment_offset) -> bool {
- HandleReceivedData(segment, segment_size);
- // The client may cancel this loader in handleReceivedData().
- return client_;
- });
- }
-
- // The client may cancel this loader in handleReceivedData(). In such a case,
- // skip the rest.
- if (!client_)
- return;
-
- base::Optional<int64_t> downloaded_file_length =
- resource->DownloadedFileLength();
- if (downloaded_file_length) {
- client_->DidDownloadData(*downloaded_file_length);
- }
- if (request.DownloadToBlob()) {
- if (resource->DownloadedBlob())
- client_->DidDownloadData(resource->DownloadedBlob()->size());
- client_->DidDownloadToBlob(resource->DownloadedBlob());
- }
-
- HandleSuccessfulFinish(identifier);
-}
void DocumentThreadableLoader::LoadRequest(
ResourceRequest& request,
@@ -1290,10 +1183,44 @@ void DocumentThreadableLoader::LoadRequest(
request.SetAllowStoredCredentials(allow_stored_credentials);
resource_loader_options.security_origin = security_origin_;
- if (async_)
- LoadRequestAsync(request, resource_loader_options);
- else
- LoadRequestSync(request, resource_loader_options);
+
+ if (!actual_request_.IsNull())
+ resource_loader_options.data_buffering_policy = kBufferData;
+
+ TimeDelta timeout =
+ TimeDelta::FromMilliseconds(options_.timeout_milliseconds);
+ if (options_.timeout_milliseconds > 0) {
+ if (!async_) {
+ request.SetTimeoutInterval(timeout);
+ } else if (!timeout_timer_.IsActive()) {
+ // The timer can be active if this is the actual request of a
+ // CORS-with-preflight request.
+ timeout_timer_.StartOneShot(timeout, FROM_HERE);
+ }
+ }
+
+ FetchParameters new_params(request, resource_loader_options);
+ if (request.GetFetchRequestMode() ==
+ network::mojom::FetchRequestMode::kNoCORS) {
+ new_params.SetOriginRestriction(FetchParameters::kNoOriginRestriction);
+ }
+ DCHECK(!GetResource());
+
+ checker_.WillAddClient();
+ ResourceFetcher* fetcher = loading_context_->GetResourceFetcher();
+ if (request.GetRequestContext() == WebURLRequest::kRequestContextVideo ||
+ request.GetRequestContext() == WebURLRequest::kRequestContextAudio) {
+ DCHECK(async_);
+ RawResource::FetchMedia(new_params, fetcher, this);
+ } else if (request.GetRequestContext() ==
+ WebURLRequest::kRequestContextManifest) {
+ DCHECK(async_);
+ RawResource::FetchManifest(new_params, fetcher, this);
+ } else if (async_) {
+ RawResource::Fetch(new_params, fetcher, this);
+ } else {
+ RawResource::FetchSynchronously(new_params, fetcher, this);
+ }
}
bool DocumentThreadableLoader::IsAllowedRedirect(
diff --git a/chromium/third_party/blink/renderer/core/loader/document_threadable_loader.h b/chromium/third_party/blink/renderer/core/loader/document_threadable_loader.h
index 4a12b51c734..2082201e8a1 100644
--- a/chromium/third_party/blink/renderer/core/loader/document_threadable_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/document_threadable_loader.h
@@ -134,19 +134,6 @@ class CORE_EXPORT DocumentThreadableLoader final : public ThreadableLoader,
void ReportResponseReceived(unsigned long identifier,
const ResourceResponse&);
- // Methods containing code to handle resource fetch results which are common
- // to both sync and async mode.
- //
- // The FetchCredentialsMode argument must be the request's credentials mode.
- // It's used for CORS check.
- void HandleResponse(unsigned long identifier,
- network::mojom::FetchRequestMode,
- network::mojom::FetchCredentialsMode,
- const ResourceResponse&,
- std::unique_ptr<WebDataConsumerHandle>);
- void HandleReceivedData(const char* data, size_t data_length);
- void HandleSuccessfulFinish(unsigned long identifier);
-
void DidTimeout(TimerBase*);
// Calls the appropriate loading method according to policy and data about
// origin. Only for handling the initial load (including fallback after
@@ -165,15 +152,12 @@ class CORE_EXPORT DocumentThreadableLoader final : public ThreadableLoader,
// m_client.
void HandlePreflightFailure(const KURL&, const String& error_description);
// Investigates the response for the preflight request. If successful,
- // the actual request will be made later in handleSuccessfulFinish().
+ // the actual request will be made later in NotifyFinished().
void HandlePreflightResponse(const ResourceResponse&);
void DispatchDidFailAccessControlCheck(const ResourceError&);
void DispatchDidFail(const ResourceError&);
- void LoadRequestAsync(const ResourceRequest&, ResourceLoaderOptions);
- void LoadRequestSync(const ResourceRequest&, ResourceLoaderOptions);
-
void PrepareCrossOriginRequest(ResourceRequest&) const;
// This method modifies the ResourceRequest by calling
@@ -235,8 +219,7 @@ class CORE_EXPORT DocumentThreadableLoader final : public ThreadableLoader,
HTTPHeaderMap request_headers_;
TaskRunnerTimer<DocumentThreadableLoader> timeout_timer_;
- double request_started_seconds_; // Time an asynchronous fetch request is
- // started
+ TimeTicks request_started_; // Time an asynchronous fetch request is started
// Max number of times that this DocumentThreadableLoader can follow
// cross-origin redirects. This is used to limit the number of redirects. But
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 838d7971102..b07f958a261 100644
--- a/chromium/third_party/blink/renderer/core/loader/empty_clients.cc
+++ b/chromium/third_party/blink/renderer/core/loader/empty_clients.cc
@@ -28,8 +28,9 @@
#include "third_party/blink/renderer/core/loader/empty_clients.h"
#include <memory>
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider_client.h"
+#include "cc/layers/layer.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider_client.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_application_cache_host.h"
#include "third_party/blink/public/platform/web_media_player.h"
@@ -41,7 +42,6 @@
#include "third_party/blink/renderer/core/html/forms/file_chooser.h"
#include "third_party/blink/renderer/core/html/forms/html_form_element.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
-#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy.h"
namespace blink {
@@ -88,6 +88,9 @@ void EmptyChromeClient::AttachRootGraphicsLayer(GraphicsLayer* layer,
page->GetVisualViewport().AttachLayerTree(layer);
}
+void EmptyChromeClient::AttachRootLayer(scoped_refptr<cc::Layer>, LocalFrame*) {
+}
+
String EmptyChromeClient::AcceptLanguages() {
return String();
}
@@ -96,7 +99,7 @@ NavigationPolicy EmptyLocalFrameClient::DecidePolicyForNavigation(
const ResourceRequest&,
Document* origin_document,
DocumentLoader*,
- NavigationType,
+ WebNavigationType,
NavigationPolicy,
bool,
bool,
@@ -116,7 +119,9 @@ DocumentLoader* EmptyLocalFrameClient::CreateDocumentLoader(
const ResourceRequest& request,
const SubstituteData& substitute_data,
ClientRedirectPolicy client_redirect_policy,
- const base::UnguessableToken& devtools_navigation_token) {
+ const base::UnguessableToken& devtools_navigation_token,
+ std::unique_ptr<WebDocumentLoader::ExtraData> extra_data,
+ const WebNavigationTimings& navigation_timings) {
DCHECK(frame);
return DocumentLoader::Create(frame, request, substitute_data,
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 1bc2a94c045..dbb68e5e649 100644
--- a/chromium/third_party/blink/renderer/core/loader/empty_clients.h
+++ b/chromium/third_party/blink/renderer/core/loader/empty_clients.h
@@ -32,9 +32,9 @@
#include <memory>
#include "base/macros.h"
+#include "cc/paint/paint_canvas.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/web_canvas.h"
#include "third_party/blink/public/platform/web_focus_type.h"
#include "third_party/blink/public/platform/web_menu_source_type.h"
#include "third_party/blink/public/platform/web_screen_info.h"
@@ -116,7 +116,7 @@ class CORE_EXPORT EmptyChromeClient : public ChromeClient {
void StartDragging(LocalFrame*,
const WebDragData&,
WebDragOperationsMask,
- const WebImage& drag_image,
+ const SkBitmap& drag_image,
const WebPoint& drag_image_offset) override {}
bool AcceptsLoadDrops() const override { return true; }
@@ -195,15 +195,15 @@ class CORE_EXPORT EmptyChromeClient : public ChromeClient {
void AttachRootGraphicsLayer(GraphicsLayer*, LocalFrame* local_root) override;
void AttachRootLayer(scoped_refptr<cc::Layer>,
- LocalFrame* local_root) override {}
+ LocalFrame* local_root) override;
void SetEventListenerProperties(LocalFrame*,
- WebEventListenerClass,
- WebEventListenerProperties) override {}
- WebEventListenerProperties EventListenerProperties(
+ cc::EventListenerClass,
+ cc::EventListenerProperties) override {}
+ cc::EventListenerProperties EventListenerProperties(
LocalFrame*,
- WebEventListenerClass event_class) const override {
- return WebEventListenerProperties::kNothing;
+ cc::EventListenerClass event_class) const override {
+ return cc::EventListenerProperties::kNone;
}
void SetHasScrollEventHandlers(LocalFrame*, bool) override {}
void SetNeedsLowLatencyInput(LocalFrame*, bool) override {}
@@ -250,18 +250,18 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
const ResourceResponse&) override {}
void DispatchDidHandleOnloadEvents() override {}
- void DispatchDidReceiveServerRedirectForProvisionalLoad() override {}
void DispatchWillCommitProvisionalLoad() override {}
void DispatchDidStartProvisionalLoad(DocumentLoader*,
ResourceRequest&) override {}
void DispatchDidReceiveTitle(const String&) override {}
void DispatchDidChangeIcons(IconType) override {}
void DispatchDidCommitLoad(HistoryItem*,
- HistoryCommitType,
+ WebHistoryCommitType,
WebGlobalObjectReusePolicy) override {}
void DispatchDidFailProvisionalLoad(const ResourceError&,
- HistoryCommitType) override {}
- void DispatchDidFailLoad(const ResourceError&, HistoryCommitType) override {}
+ WebHistoryCommitType) override {}
+ void DispatchDidFailLoad(const ResourceError&,
+ WebHistoryCommitType) override {}
void DispatchDidFinishDocumentLoad() override {}
void DispatchDidFinishLoad() override {}
void DispatchDidChangeThemeColor() override {}
@@ -270,7 +270,7 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
const ResourceRequest&,
Document* origin_document,
DocumentLoader*,
- NavigationType,
+ WebNavigationType,
NavigationPolicy,
bool,
bool,
@@ -288,7 +288,8 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
void ForwardResourceTimingToParent(const WebResourceTimingInfo&) override {}
- void DownloadURL(const ResourceRequest&) override {}
+ void DownloadURL(const ResourceRequest&,
+ DownloadCrossOriginRedirects) override {}
void LoadErrorPage(int reason) override {}
DocumentLoader* CreateDocumentLoader(
@@ -296,7 +297,9 @@ class CORE_EXPORT EmptyLocalFrameClient : public LocalFrameClient {
const ResourceRequest&,
const SubstituteData&,
ClientRedirectPolicy,
- const base::UnguessableToken& devtools_navigation_token) override;
+ const base::UnguessableToken& devtools_navigation_token,
+ std::unique_ptr<WebDocumentLoader::ExtraData> extra_data,
+ const WebNavigationTimings& navigation_timings) override;
String UserAgent() override { return ""; }
@@ -411,7 +414,7 @@ class CORE_EXPORT EmptyRemoteFrameClient : public RemoteFrameClient {
void Navigate(const ResourceRequest&,
bool should_replace_current_entry,
mojom::blink::BlobURLTokenPtr) override {}
- void Reload(FrameLoadType, ClientRedirectPolicy) override {}
+ void Reload(WebFrameLoadType, ClientRedirectPolicy) override {}
unsigned BackForwardLength() override { return 0; }
void CheckCompleted() override {}
void ForwardPostMessage(MessageEvent*,
@@ -428,7 +431,7 @@ class CORE_EXPORT EmptyRemoteFrameClient : public RemoteFrameClient {
void SetInheritedEffectiveTouchAction(TouchAction) override {}
void UpdateRenderThrottlingStatus(bool is_throttled,
bool subtree_throttled) override {}
- uint32_t Print(const IntRect& rect, WebCanvas* canvas) const override {
+ uint32_t Print(const IntRect& rect, cc::PaintCanvas* canvas) const override {
return 0;
}
diff --git a/chromium/third_party/blink/renderer/core/loader/form_submission.cc b/chromium/third_party/blink/renderer/core/loader/form_submission.cc
index 172589e342b..ef30dcc6ae3 100644
--- a/chromium/third_party/blink/renderer/core/loader/form_submission.cc
+++ b/chromium/third_party/blink/renderer/core/loader/form_submission.cc
@@ -155,8 +155,18 @@ inline FormSubmission::FormSubmission(SubmitMethod method,
content_type_(content_type),
form_(form),
form_data_(std::move(data)),
- boundary_(boundary),
- event_(event) {}
+ boundary_(boundary) {
+ if (event) {
+ triggering_event_info_ = event->isTrusted()
+ ? WebTriggeringEventInfo::kFromTrustedEvent
+ : WebTriggeringEventInfo::kFromUntrustedEvent;
+ if (event->UnderlyingEvent())
+ event = event->UnderlyingEvent();
+ } else {
+ triggering_event_info_ = WebTriggeringEventInfo::kNotFromEvent;
+ }
+ navigation_policy_ = NavigationPolicyFromEvent(event);
+}
inline FormSubmission::FormSubmission(const String& result)
: method_(kDialogMethod), result_(result) {}
@@ -255,7 +265,6 @@ FormSubmission* FormSubmission::Create(HTMLFormElement* form,
void FormSubmission::Trace(blink::Visitor* visitor) {
visitor->Trace(form_);
- visitor->Trace(event_);
}
KURL FormSubmission::RequestURL() const {
@@ -289,9 +298,10 @@ FrameLoadRequest FormSubmission::CreateFrameLoadRequest(
frame_request.GetResourceRequest().SetURL(RequestURL());
- frame_request.SetTriggeringEvent(event_);
frame_request.SetForm(form_);
+ frame_request.SetTriggeringEventInfo(triggering_event_info_);
+
return frame_request;
}
diff --git a/chromium/third_party/blink/renderer/core/loader/form_submission.h b/chromium/third_party/blink/renderer/core/loader/form_submission.h
index 4c2f4ff68f8..14ddd3ba497 100644
--- a/chromium/third_party/blink/renderer/core/loader/form_submission.h
+++ b/chromium/third_party/blink/renderer/core/loader/form_submission.h
@@ -32,7 +32,9 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_FORM_SUBMISSION_H_
#include "base/macros.h"
+#include "third_party/blink/public/web/web_triggering_event_info.h"
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
+#include "third_party/blink/renderer/core/loader/navigation_policy.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/referrer.h"
@@ -108,6 +110,7 @@ class FormSubmission : public GarbageCollectedFinalized<FormSubmission> {
void ClearTarget() { target_ = g_null_atom; }
HTMLFormElement* Form() const { return form_.Get(); }
EncodedFormData* Data() const { return form_data_.get(); }
+ NavigationPolicy GetNavigationPolicy() const { return navigation_policy_; }
const String& Result() const { return result_; }
@@ -131,7 +134,8 @@ class FormSubmission : public GarbageCollectedFinalized<FormSubmission> {
Member<HTMLFormElement> form_;
scoped_refptr<EncodedFormData> form_data_;
String boundary_;
- Member<Event> event_;
+ NavigationPolicy navigation_policy_;
+ WebTriggeringEventInfo triggering_event_info_;
String result_;
};
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 c2f48797982..ccfe5714611 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
@@ -35,19 +35,21 @@
#include "base/feature_list.h"
#include "base/optional.h"
+#include "build/build_config.h"
#include "services/network/public/mojom/request_context_frame_type.mojom-blink.h"
+#include "third_party/blink/public/common/blob/blob_utils.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/platform/modules/fetch/fetch_api_request.mojom-shared.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_application_cache_host.h"
#include "third_party/blink/public/platform/web_effective_connection_type.h"
#include "third_party/blink/public/platform/web_insecure_request_policy.h"
#include "third_party/blink/public/platform/websocket_handshake_throttle.h"
#include "third_party/blink/public/web/web_frame.h"
-#include "third_party/blink/public/web/web_frame_client.h"
#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -108,8 +110,13 @@ namespace {
// 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
enum class RequestMethod { kIsPost, kIsNotPost };
enum class RequestType { kIsConditional, kIsNotConditional };
@@ -118,18 +125,21 @@ enum class ResourceType { kIsMainResource, kIsNotMainResource };
void MaybeRecordCTPolicyComplianceUseCounter(
LocalFrame* frame,
Resource::Type resource_type,
- ResourceResponse::CTPolicyCompliance compliance) {
+ ResourceResponse::CTPolicyCompliance compliance,
+ DocumentLoader* loader) {
if (compliance != ResourceResponse::kCTPolicyDoesNotComply)
return;
// Exclude main-frame navigation requests; those are tracked elsewhere.
if (!frame->Tree().Parent() && resource_type == Resource::kMainResource)
return;
- UseCounter::Count(
- frame,
- frame->Tree().Parent()
- ? WebFeature::kCertificateTransparencyNonCompliantResourceInSubframe
- : WebFeature::
- kCertificateTransparencyNonCompliantSubresourceInMainFrame);
+ if (loader) {
+ loader->GetUseCounter().Count(
+ frame->Tree().Parent()
+ ? WebFeature::kCertificateTransparencyNonCompliantResourceInSubframe
+ : WebFeature::
+ kCertificateTransparencyNonCompliantSubresourceInMainFrame,
+ frame);
+ }
}
void RecordLegacySymantecCertUseCounter(LocalFrame* frame,
@@ -142,32 +152,30 @@ void RecordLegacySymantecCertUseCounter(LocalFrame* frame,
}
// Determines FetchCacheMode for a main resource, or FetchCacheMode that is
-// corresponding to FrameLoadType.
-// TODO(toyoshim): Probably, we should split FrameLoadType to FetchCacheMode
+// corresponding to WebFrameLoadType.
+// TODO(toyoshim): Probably, we should split WebFrameLoadType to FetchCacheMode
// conversion logic into a separate function.
mojom::FetchCacheMode DetermineCacheMode(RequestMethod method,
RequestType request_type,
ResourceType resource_type,
- FrameLoadType load_type) {
+ WebFrameLoadType load_type) {
switch (load_type) {
- case kFrameLoadTypeStandard:
- case kFrameLoadTypeReplaceCurrentItem:
- case kFrameLoadTypeInitialInChildFrame:
+ case WebFrameLoadType::kStandard:
+ case WebFrameLoadType::kReplaceCurrentItem:
return (request_type == RequestType::kIsConditional ||
method == RequestMethod::kIsPost)
? mojom::FetchCacheMode::kValidateCache
: mojom::FetchCacheMode::kDefault;
- case kFrameLoadTypeBackForward:
- case kFrameLoadTypeInitialHistoryLoad:
+ case WebFrameLoadType::kBackForward:
// Mutates the policy for POST requests to avoid form resubmission.
return method == RequestMethod::kIsPost
? mojom::FetchCacheMode::kOnlyIfCached
: mojom::FetchCacheMode::kForceCache;
- case kFrameLoadTypeReload:
+ case WebFrameLoadType::kReload:
return resource_type == ResourceType::kIsMainResource
? mojom::FetchCacheMode::kValidateCache
: mojom::FetchCacheMode::kDefault;
- case kFrameLoadTypeReloadBypassingCache:
+ case WebFrameLoadType::kReloadBypassingCache:
return mojom::FetchCacheMode::kBypassCache;
}
NOTREACHED();
@@ -188,7 +196,7 @@ mojom::FetchCacheMode DetermineFrameCacheMode(Frame* frame,
// Does not propagate cache policy for subresources after the load event.
// TODO(toyoshim): We should be able to remove following parents' policy check
- // if each frame has a relevant FrameLoadType for reload and history
+ // if each frame has a relevant WebFrameLoadType for reload and history
// navigations.
if (resource_type == ResourceType::kIsNotMainResource &&
ToLocalFrame(frame)->GetDocument()->LoadEventFinished()) {
@@ -196,9 +204,9 @@ mojom::FetchCacheMode DetermineFrameCacheMode(Frame* frame,
}
// Respects BypassingCache rather than parent's policy.
- FrameLoadType load_type =
+ WebFrameLoadType load_type =
ToLocalFrame(frame)->Loader().GetDocumentLoader()->LoadType();
- if (load_type == kFrameLoadTypeReloadBypassingCache)
+ if (load_type == WebFrameLoadType::kReloadBypassingCache)
return mojom::FetchCacheMode::kBypassCache;
// Respects parent's policy if it has a special one.
@@ -207,7 +215,7 @@ mojom::FetchCacheMode DetermineFrameCacheMode(Frame* frame,
if (parent_cache_mode != mojom::FetchCacheMode::kDefault)
return parent_cache_mode;
- // Otherwise, follows FrameLoadType. Use kIsNotPost, kIsNotConditional, and
+ // Otherwise, follows WebFrameLoadType. Use kIsNotPost, kIsNotConditional, and
// kIsNotMainResource to obtain a representative policy for the frame.
return DetermineCacheMode(RequestMethod::kIsNotPost,
RequestType::kIsNotConditional,
@@ -218,10 +226,7 @@ mojom::FetchCacheMode DetermineFrameCacheMode(Frame* frame,
struct FrameFetchContext::FrozenState final
: GarbageCollectedFinalized<FrozenState> {
- FrozenState(ReferrerPolicy referrer_policy,
- const String& outgoing_referrer,
- const KURL& url,
- scoped_refptr<const SecurityOrigin> security_origin,
+ FrozenState(const KURL& url,
scoped_refptr<const SecurityOrigin> parent_security_origin,
const base::Optional<mojom::IPAddressSpace>& address_space,
const ContentSecurityPolicy* content_security_policy,
@@ -232,10 +237,7 @@ struct FrameFetchContext::FrozenState final
const String& user_agent,
bool is_main_frame,
bool is_svg_image_chrome_client)
- : referrer_policy(referrer_policy),
- outgoing_referrer(outgoing_referrer),
- url(url),
- security_origin(std::move(security_origin)),
+ : url(url),
parent_security_origin(std::move(parent_security_origin)),
address_space(address_space),
content_security_policy(content_security_policy),
@@ -247,10 +249,7 @@ struct FrameFetchContext::FrozenState final
is_main_frame(is_main_frame),
is_svg_image_chrome_client(is_svg_image_chrome_client) {}
- const ReferrerPolicy referrer_policy;
- const String outgoing_referrer;
const KURL url;
- const scoped_refptr<const SecurityOrigin> security_origin;
const scoped_refptr<const SecurityOrigin> parent_security_origin;
const base::Optional<mojom::IPAddressSpace> address_space;
const Member<const ContentSecurityPolicy> content_security_policy;
@@ -290,6 +289,10 @@ FrameFetchContext::FrameFetchContext(DocumentLoader* loader, Document* document)
document_(document),
save_data_enabled_(GetNetworkStateNotifier().SaveDataEnabled() &&
!GetSettings()->GetDataSaverHoldbackWebApi()) {
+ if (document_) {
+ fetch_client_settings_object_ =
+ new FetchClientSettingsObjectImpl(*document_);
+ }
DCHECK(GetFrame());
}
@@ -298,6 +301,8 @@ void FrameFetchContext::ProvideDocumentToContext(FetchContext& context,
DCHECK(document);
CHECK(context.IsFrameFetchContext());
static_cast<FrameFetchContext&>(context).document_ = document;
+ static_cast<FrameFetchContext&>(context).fetch_client_settings_object_ =
+ new FetchClientSettingsObjectImpl(*document);
}
FrameFetchContext::~FrameFetchContext() {
@@ -338,12 +343,29 @@ FrameFetchContext::GetLoadingTaskRunner() {
return GetFrame()->GetTaskRunner(TaskType::kNetworking);
}
+std::unique_ptr<scheduler::WebResourceLoadingTaskRunnerHandle>
+FrameFetchContext::CreateResourceLoadingTaskRunnerHandle() {
+ if (IsDetached()) {
+ return scheduler::WebResourceLoadingTaskRunnerHandle::CreateUnprioritized(
+ FetchContext::GetLoadingTaskRunner());
+ }
+ return GetFrame()
+ ->GetFrameScheduler()
+ ->CreateResourceLoadingTaskRunnerHandle();
+}
+
FrameScheduler* FrameFetchContext::GetFrameScheduler() const {
if (IsDetached())
return nullptr;
return GetFrame()->GetFrameScheduler();
}
+const FetchClientSettingsObject*
+FrameFetchContext::GetFetchClientSettingsObject() const {
+ DCHECK(fetch_client_settings_object_);
+ return fetch_client_settings_object_.Get();
+}
+
KURL FrameFetchContext::GetSiteForCookies() const {
if (IsDetached())
return frozen_state_->site_for_cookies;
@@ -431,9 +453,9 @@ mojom::FetchCacheMode FrameFetchContext::ResourceRequestCachePolicy(
: RequestType::kIsNotConditional,
ResourceType::kIsMainResource, MasterDocumentLoader()->LoadType());
// Follows the parent frame's policy.
- // TODO(toyoshim): Probably, FrameLoadType for each frame should have a
+ // TODO(toyoshim): Probably, WebFrameLoadType for each frame should have a
// right type for reload or history navigations, and should not need to
- // check parent's frame policy here. Once it has a right FrameLoadType,
+ // check parent's frame policy here. Once it has a right WebFrameLoadType,
// we can remove Resource::Type argument from determineFrameCacheMode.
// See also crbug.com/332602.
if (cache_mode != mojom::FetchCacheMode::kDefault)
@@ -547,8 +569,11 @@ void FrameFetchContext::DispatchDidReceiveResponse(
if (IsDetached())
return;
+ DCHECK(resource);
+
MaybeRecordCTPolicyComplianceUseCounter(GetFrame(), resource->GetType(),
- response.GetCTPolicyCompliance());
+ response.GetCTPolicyCompliance(),
+ MasterDocumentLoader());
if (response_type == ResourceResponseType::kFromMemoryCache) {
// Note: probe::willSendRequest needs to precede before this probe method.
@@ -567,12 +592,6 @@ void FrameFetchContext::DispatchDidReceiveResponse(
document_loader_ == document_loader_->GetFrame()
->Loader()
.GetProvisionalDocumentLoader()) {
- FrameClientHintsPreferencesContext hints_context(GetFrame());
- document_loader_->GetClientHintsPreferences()
- .UpdateFromAcceptClientHintsHeader(
- response.HttpHeaderField(HTTPNames::Accept_CH), response.Url(),
- &hints_context);
-
// When response is received with a provisional docloader, the resource
// haven't committed yet, and we cannot load resources, only preconnect.
resource_loading_policy = LinkLoader::kDoNotLoadResources;
@@ -583,10 +602,12 @@ void FrameFetchContext::DispatchDidReceiveResponse(
if (frame_url == NullURL())
frame_url = document_loader_->Url();
- // Check if |response| belongs to a resource in the main frame, and if belongs
- // to the same origin as frame top request.
- if (SecurityOrigin::AreSameSchemeHostPort(response.Url(), frame_url) &&
- GetFrame()->IsMainFrame()) {
+ // The accept-ch-lifetime header is honored only on the navigation responses.
+ // Further, the navigation response should be from a top level frame (i.e.,
+ // main frame) or the origin of the response should match the origin of the
+ // top level frame.
+ if ((resource->GetType() == Resource::kMainResource) &&
+ (IsMainFrame() || IsFirstPartyOrigin(response.Url()))) {
ParseAndPersistClientHints(response);
}
@@ -636,20 +657,6 @@ void FrameFetchContext::DispatchDidReceiveEncodedData(unsigned long identifier,
encoded_data_length);
}
-void FrameFetchContext::DispatchDidDownloadData(unsigned long identifier,
- int data_length,
- int encoded_data_length) {
- if (IsDetached())
- return;
-
- GetFrame()->Loader().Progress().IncrementProgress(identifier, data_length);
- probe::didReceiveData(GetFrame()->GetDocument(), identifier,
- MasterDocumentLoader(), nullptr, data_length);
- probe::didReceiveEncodedDataLength(GetFrame()->GetDocument(),
- MasterDocumentLoader(), identifier,
- encoded_data_length);
-}
-
void FrameFetchContext::DispatchDidDownloadToBlob(unsigned long identifier,
BlobDataHandle* blob) {
if (IsDetached() || !blob)
@@ -664,7 +671,7 @@ void FrameFetchContext::DispatchDidFinishLoading(
TimeTicks finish_time,
int64_t encoded_data_length,
int64_t decoded_body_length,
- bool blocked_cross_site_document) {
+ bool should_report_corb_blocking) {
if (IsDetached())
return;
@@ -672,7 +679,7 @@ void FrameFetchContext::DispatchDidFinishLoading(
probe::didFinishLoading(GetFrame()->GetDocument(), identifier,
MasterDocumentLoader(), finish_time,
encoded_data_length, decoded_body_length,
- blocked_cross_site_document);
+ should_report_corb_blocking);
if (document_) {
InteractiveDetector* interactive_detector(
InteractiveDetector::From(*document_));
@@ -690,16 +697,19 @@ void FrameFetchContext::DispatchDidFail(const KURL& url,
if (IsDetached())
return;
- if (NetworkUtils::IsCertificateTransparencyRequiredError(error.ErrorCode())) {
- UseCounter::Count(
- GetFrame()->GetDocument(),
- WebFeature::kCertificateTransparencyRequiredErrorOnResourceLoad);
- }
+ if (DocumentLoader* loader = MasterDocumentLoader()) {
+ if (NetworkUtils::IsCertificateTransparencyRequiredError(
+ error.ErrorCode())) {
+ loader->GetUseCounter().Count(
+ WebFeature::kCertificateTransparencyRequiredErrorOnResourceLoad,
+ GetFrame());
+ }
- if (NetworkUtils::IsLegacySymantecCertError(error.ErrorCode())) {
- UseCounter::Count(GetFrame()->GetDocument(),
- WebFeature::kDistrustedLegacySymantecSubresource);
- GetLocalFrameClient()->ReportLegacySymantecCert(url, true /* did_fail */);
+ if (NetworkUtils::IsLegacySymantecCertError(error.ErrorCode())) {
+ loader->GetUseCounter().Count(
+ WebFeature::kDistrustedLegacySymantecSubresource, GetFrame());
+ GetLocalFrameClient()->ReportLegacySymantecCert(url, true /* did_fail */);
+ }
}
GetFrame()->Loader().Progress().CompleteProgress(identifier);
@@ -815,20 +825,23 @@ bool FrameFetchContext::AllowImage(bool images_enabled, const KURL& url) const {
return GetContentSettingsClient()->AllowImage(images_enabled, url);
}
-bool FrameFetchContext::IsControlledByServiceWorker() const {
+blink::mojom::ControllerServiceWorkerMode
+FrameFetchContext::IsControlledByServiceWorker() const {
if (IsDetached())
- return false;
+ return blink::mojom::ControllerServiceWorkerMode::kNoController;
DCHECK(MasterDocumentLoader());
auto* service_worker_network_provider =
MasterDocumentLoader()->GetServiceWorkerNetworkProvider();
- return service_worker_network_provider &&
- service_worker_network_provider->HasControllerServiceWorker();
+ if (!service_worker_network_provider)
+ return blink::mojom::ControllerServiceWorkerMode::kNoController;
+ return service_worker_network_provider->IsControlledByServiceWorker();
}
int64_t FrameFetchContext::ServiceWorkerID() const {
- DCHECK(IsControlledByServiceWorker());
+ DCHECK(IsControlledByServiceWorker() !=
+ blink::mojom::ControllerServiceWorkerMode::kNoController);
DCHECK(MasterDocumentLoader());
auto* service_worker_network_provider =
MasterDocumentLoader()->GetServiceWorkerNetworkProvider();
@@ -875,15 +888,16 @@ bool FrameFetchContext::UpdateTimingInfoForIFrameNavigation(
return false;
// Do not report iframe navigation that restored from history, since its
// location may have been changed after initial navigation.
- if (MasterDocumentLoader()->LoadType() == kFrameLoadTypeInitialHistoryLoad)
+ if (MasterDocumentLoader()->LoadType() == WebFrameLoadType::kBackForward)
return false;
return true;
}
const SecurityOrigin* FrameFetchContext::GetSecurityOrigin() const {
- if (IsDetached())
- return frozen_state_->security_origin.get();
- return document_ ? document_->GetSecurityOrigin() : nullptr;
+ // This can be called before |fetch_client_settings_object_| is set.
+ if (!fetch_client_settings_object_)
+ return nullptr;
+ return fetch_client_settings_object_->GetSecurityOrigin();
}
void FrameFetchContext::ModifyRequestForCSP(ResourceRequest& resource_request) {
@@ -902,42 +916,28 @@ void FrameFetchContext::AddClientHintsIfNecessary(
ResourceRequest& request) {
WebEnabledClientHints enabled_hints;
- bool is_1p_origin = false;
-
- if (blink::RuntimeEnabledFeatures::ClientHintsPersistentEnabled()) {
- // If the feature is enabled, then client hints are allowed only on secure
- // URLs.
- if (!ClientHintsPreferences::IsClientHintsAllowed(request.Url()))
- return;
+ // If the feature is enabled, then client hints are allowed only on secure
+ // URLs.
+ if (!ClientHintsPreferences::IsClientHintsAllowed(request.Url()))
+ return;
- // Check if |url| is allowed to run JavaScript. If not, client hints are not
- // attached to the requests that initiate on the render side.
- if (!AllowScriptFromSourceWithoutNotifying(request.Url())) {
- return;
- }
+ // Check if |url| is allowed to run JavaScript. If not, client hints are not
+ // attached to the requests that initiate on the render side.
+ if (!AllowScriptFromSourceWithoutNotifying(request.Url()))
+ return;
- if (IsDetached())
- return;
+ bool is_1p_origin = IsFirstPartyOrigin(request.Url());
- is_1p_origin =
- GetFrame()
- ->Tree()
- .Top()
- .GetSecurityContext()
- ->GetSecurityOrigin()
- ->IsSameSchemeHostPort(SecurityOrigin::Create(request.Url()).get());
-
- if (!base::FeatureList::IsEnabled(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);
- }
+ if (!base::FeatureList::IsEnabled(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);
}
if (ShouldSendClientHint(mojom::WebClientHintsType::kDeviceMemory,
@@ -1015,7 +1015,10 @@ void FrameFetchContext::PopulateResourceRequest(
ResourceRequest& request) {
ModifyRequestForCSP(request);
AddClientHintsIfNecessary(hints_preferences, resource_width, request);
- AddCSPHeaderIfNecessary(type, request);
+
+ const ContentSecurityPolicy* csp = GetContentSecurityPolicy();
+ if (csp && csp->ShouldSendCSPHeader(type))
+ request.AddHTTPHeaderField("CSP", "active");
}
void FrameFetchContext::SetFirstPartyCookieAndRequestorOrigin(
@@ -1080,6 +1083,18 @@ bool FrameFetchContext::AllowScriptFromSourceWithoutNotifying(
return true;
}
+bool FrameFetchContext::IsFirstPartyOrigin(const KURL& url) const {
+ if (IsDetached())
+ return false;
+
+ return GetFrame()
+ ->Tree()
+ .Top()
+ .GetSecurityContext()
+ ->GetSecurityOrigin()
+ ->IsSameSchemeHostPort(SecurityOrigin::Create(url).get());
+}
+
bool FrameFetchContext::ShouldBlockRequestByInspector(const KURL& url) const {
if (IsDetached())
return false;
@@ -1118,7 +1133,8 @@ bool FrameFetchContext::IsSVGImageChromeClient() const {
void FrameFetchContext::CountUsage(WebFeature feature) const {
if (IsDetached())
return;
- UseCounter::Count(GetFrame(), feature);
+ if (DocumentLoader* loader = MasterDocumentLoader())
+ loader->GetUseCounter().Count(feature, GetFrame());
}
void FrameFetchContext::CountDeprecation(WebFeature feature) const {
@@ -1133,7 +1149,7 @@ bool FrameFetchContext::ShouldBlockWebSocketByMixedContentCheck(
// TODO(yhirano): Implement the detached case.
return false;
}
- return !MixedContentChecker::IsWebSocketAllowed(GetFrame(), url);
+ return !MixedContentChecker::IsWebSocketAllowed(*this, GetFrame(), url);
}
std::unique_ptr<WebSocketHandshakeThrottle>
@@ -1199,18 +1215,6 @@ bool FrameFetchContext::ShouldBlockFetchAsCredentialedSubresource(
return RuntimeEnabledFeatures::BlockCredentialedSubresourcesEnabled();
}
-ReferrerPolicy FrameFetchContext::GetReferrerPolicy() const {
- if (IsDetached())
- return frozen_state_->referrer_policy;
- return document_->GetReferrerPolicy();
-}
-
-String FrameFetchContext::GetOutgoingReferrer() const {
- if (IsDetached())
- return frozen_state_->outgoing_referrer;
- return document_->OutgoingReferrer();
-}
-
const KURL& FrameFetchContext::Url() const {
if (IsDetached())
return frozen_state_->url;
@@ -1297,14 +1301,15 @@ scoped_refptr<const SecurityOrigin> FrameFetchContext::GetRequestorOrigin() {
return GetSecurityOrigin();
}
-ClientHintsPreferences FrameFetchContext::GetClientHintsPreferences() const {
+const ClientHintsPreferences FrameFetchContext::GetClientHintsPreferences()
+ const {
if (IsDetached())
return frozen_state_->client_hints_preferences;
- if (!document_)
+ if (!document_ || !document_->GetFrame())
return ClientHintsPreferences();
- return document_->GetClientHintsPreferences();
+ return document_->GetFrame()->GetClientHintsPreferences();
}
float FrameFetchContext::GetDevicePixelRatio() const {
@@ -1330,16 +1335,26 @@ bool FrameFetchContext::ShouldSendClientHint(
void FrameFetchContext::ParseAndPersistClientHints(
const ResourceResponse& response) {
- ClientHintsPreferences hints_preferences;
- WebEnabledClientHints enabled_client_hints;
- TimeDelta persist_duration;
FrameClientHintsPreferencesContext hints_context(GetFrame());
- hints_preferences.UpdatePersistentHintsFromHeaders(
- response, &hints_context, enabled_client_hints, &persist_duration);
+ document_loader_->GetClientHintsPreferences()
+ .UpdateFromAcceptClientHintsLifetimeHeader(
+ response.HttpHeaderField(HTTPNames::Accept_CH_Lifetime),
+ response.Url(), &hints_context);
+
+ document_loader_->GetClientHintsPreferences()
+ .UpdateFromAcceptClientHintsHeader(
+ response.HttpHeaderField(HTTPNames::Accept_CH), response.Url(),
+ &hints_context);
+
+ // Notify content settings client of persistent client hints.
+ TimeDelta persist_duration =
+ document_loader_->GetClientHintsPreferences().GetPersistDuration();
if (persist_duration.InSeconds() <= 0)
return;
+ WebEnabledClientHints enabled_client_hints =
+ document_loader_->GetClientHintsPreferences().GetWebEnabledClientHints();
if (!AllowScriptFromSourceWithoutNotifying(response.Url())) {
// Do not persist client hint preferences if the JavaScript is disabled.
return;
@@ -1351,7 +1366,6 @@ void FrameFetchContext::ParseAndPersistClientHints(
std::unique_ptr<WebURLLoader> FrameFetchContext::CreateURLLoader(
const ResourceRequest& request,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
const ResourceLoaderOptions& options) {
DCHECK(!IsDetached());
WrappedResourceRequest webreq(request);
@@ -1366,26 +1380,39 @@ std::unique_ptr<WebURLLoader> FrameFetchContext::CreateURLLoader(
// actually creating the URL loader here. Other subresource loading will
// immediately create the URL loader so resolving those blob URLs here is
// simplest.
+ // Don't resolve the URL again if this is a shared worker request though, as
+ // in that case the browser process will have already done so and the code
+ // here should just go through the normal non-blob specific code path (note
+ // that this is only strictly true if NetworkService/S13nSW is enabled, but if
+ // that isn't the case we're going to run into race conditions resolving the
+ // blob URL anyway so it doesn't matter if the blob URL gets resolved here or
+ // later in the browser process, so skipping blob URL resolution here for all
+ // shared worker loads is okay even with NetworkService/S13nSW disabled).
+ // TODO(mek): Move the RequestContext check to the worker side's relevant
+ // callsite when we make Shared Worker loading off-main-thread.
if (document_ && request.Url().ProtocolIs("blob") &&
- RuntimeEnabledFeatures::MojoBlobURLsEnabled() && !url_loader_factory) {
+ BlobUtils::MojoBlobURLsEnabled() && !url_loader_factory &&
+ request.GetRequestContext() !=
+ WebURLRequest::kRequestContextSharedWorker) {
document_->GetPublicURLManager().Resolve(request.Url(),
MakeRequest(&url_loader_factory));
}
if (url_loader_factory) {
return Platform::Current()
->WrapURLLoaderFactory(url_loader_factory.PassInterface().PassHandle())
- ->CreateURLLoader(webreq, task_runner);
+ ->CreateURLLoader(webreq, CreateResourceLoadingTaskRunnerHandle());
}
if (MasterDocumentLoader()->GetServiceWorkerNetworkProvider()) {
- auto loader = MasterDocumentLoader()
- ->GetServiceWorkerNetworkProvider()
- ->CreateURLLoader(webreq, task_runner);
+ auto loader =
+ MasterDocumentLoader()
+ ->GetServiceWorkerNetworkProvider()
+ ->CreateURLLoader(webreq, CreateResourceLoadingTaskRunnerHandle());
if (loader)
return loader;
}
- return GetFrame()->GetURLLoaderFactory()->CreateURLLoader(webreq,
- task_runner);
+ return GetFrame()->GetURLLoaderFactory()->CreateURLLoader(
+ webreq, CreateResourceLoadingTaskRunnerHandle());
}
FetchContext* FrameFetchContext::Detach() {
@@ -1394,20 +1421,22 @@ FetchContext* FrameFetchContext::Detach() {
if (document_) {
frozen_state_ = new FrozenState(
- GetReferrerPolicy(), GetOutgoingReferrer(), Url(), GetSecurityOrigin(),
- GetParentSecurityOrigin(), GetAddressSpace(),
+ Url(), GetParentSecurityOrigin(), GetAddressSpace(),
GetContentSecurityPolicy(), GetSiteForCookies(), GetRequestorOrigin(),
GetClientHintsPreferences(), GetDevicePixelRatio(), GetUserAgent(),
IsMainFrame(), IsSVGImageChromeClient());
+ fetch_client_settings_object_ =
+ new FetchClientSettingsObjectSnapshot(*document_);
} else {
// Some getters are unavailable in this case.
frozen_state_ = new FrozenState(
- kReferrerPolicyDefault, String(), NullURL(), GetSecurityOrigin(),
- GetParentSecurityOrigin(), GetAddressSpace(),
+ NullURL(), GetParentSecurityOrigin(), GetAddressSpace(),
GetContentSecurityPolicy(), GetSiteForCookies(),
- SecurityOrigin::CreateUnique(), GetClientHintsPreferences(),
+ SecurityOrigin::CreateUniqueOpaque(), GetClientHintsPreferences(),
GetDevicePixelRatio(), GetUserAgent(), IsMainFrame(),
IsSVGImageChromeClient());
+ fetch_client_settings_object_ = new FetchClientSettingsObjectSnapshot(
+ NullURL(), nullptr, kReferrerPolicyDefault, String());
}
// This is needed to break a reference cycle in which off-heap
@@ -1421,6 +1450,7 @@ void FrameFetchContext::Trace(blink::Visitor* visitor) {
visitor->Trace(document_loader_);
visitor->Trace(document_);
visitor->Trace(frozen_state_);
+ visitor->Trace(fetch_client_settings_object_);
BaseFetchContext::Trace(visitor);
}
@@ -1475,6 +1505,13 @@ ResourceLoadPriority FrameFetchContext::ModifyPriorityForExperiments(
return ResourceLoadPriority::kLowest;
}
+void FrameFetchContext::DispatchNetworkQuiet() {
+ if (WebServiceWorkerNetworkProvider* service_worker_network_provider =
+ MasterDocumentLoader()->GetServiceWorkerNetworkProvider()) {
+ service_worker_network_provider->DispatchNetworkQuiet();
+ }
+}
+
base::Optional<ResourceRequestBlockedReason> FrameFetchContext::CanRequest(
Resource::Type type,
const ResourceRequest& resource_request,
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 f59d0d856c0..d2a808077e7 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,12 @@
#include "base/optional.h"
#include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-blink.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/loader/base_fetch_context.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
@@ -115,16 +118,13 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
int data_length) override;
void DispatchDidReceiveEncodedData(unsigned long identifier,
int encoded_data_length) override;
- void DispatchDidDownloadData(unsigned long identifier,
- int data_length,
- int encoded_data_length) override;
void DispatchDidDownloadToBlob(unsigned long identifier,
BlobDataHandle*) override;
void DispatchDidFinishLoading(unsigned long identifier,
TimeTicks finish_time,
int64_t encoded_data_length,
int64_t decoded_body_length,
- bool blocked_cross_site_document) override;
+ bool should_report_corb_blocking) override;
void DispatchDidFail(const KURL&,
unsigned long identifier,
const ResourceError&,
@@ -139,7 +139,8 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
void AddResourceTiming(const ResourceTimingInfo&) override;
bool AllowImage(bool images_enabled, const KURL&) const override;
- bool IsControlledByServiceWorker() const override;
+ blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker()
+ const override;
int64_t ServiceWorkerID() const override;
int ApplicationCacheHostID() const override;
@@ -165,7 +166,6 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
std::unique_ptr<WebURLLoader> CreateURLLoader(
const ResourceRequest&,
- scoped_refptr<base::SingleThreadTaskRunner>,
const ResourceLoaderOptions&) override;
ResourceLoadScheduler::ThrottlingPolicy InitialLoadThrottlingPolicy()
@@ -183,6 +183,7 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
ResourceLoadPriority ModifyPriorityForExperiments(
ResourceLoadPriority) const override;
+ void DispatchNetworkQuiet() override;
private:
friend class FrameFetchContextTest;
@@ -205,8 +206,12 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
// FetchContext overrides:
FrameScheduler* GetFrameScheduler() const override;
scoped_refptr<base::SingleThreadTaskRunner> GetLoadingTaskRunner() override;
+ std::unique_ptr<scheduler::WebResourceLoadingTaskRunnerHandle>
+ CreateResourceLoadingTaskRunnerHandle() override;
// BaseFetchContext overrides:
+ const FetchClientSettingsObject* GetFetchClientSettingsObject()
+ const override;
KURL GetSiteForCookies() const override;
SubresourceFilter* GetSubresourceFilter() const override;
bool AllowScriptFromSource(const KURL&) const override;
@@ -231,8 +236,6 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
bool ShouldBlockFetchAsCredentialedSubresource(const ResourceRequest&,
const KURL&) const override;
- ReferrerPolicy GetReferrerPolicy() const override;
- String GetOutgoingReferrer() const override;
const KURL& Url() const override;
const SecurityOrigin* GetParentSecurityOrigin() const override;
base::Optional<mojom::IPAddressSpace> GetAddressSpace() const override;
@@ -243,7 +246,7 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
Settings* GetSettings() const;
String GetUserAgent() const;
scoped_refptr<const SecurityOrigin> GetRequestorOrigin();
- ClientHintsPreferences GetClientHintsPreferences() const;
+ const ClientHintsPreferences GetClientHintsPreferences() const;
float GetDevicePixelRatio() const;
bool ShouldSendClientHint(mojom::WebClientHintsType,
const ClientHintsPreferences&,
@@ -262,6 +265,10 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
// JavaScript was blocked from being executed.
bool AllowScriptFromSourceWithoutNotifying(const KURL&) const;
+ // Returns true if the origin of |url| is same as the origin of the top level
+ // frame's main resource.
+ bool IsFirstPartyOrigin(const KURL& url) const;
+
Member<DocumentLoader> document_loader_;
Member<Document> document_;
@@ -272,6 +279,8 @@ class CORE_EXPORT FrameFetchContext final : public BaseFetchContext {
// Non-null only when detached.
Member<const FrozenState> frozen_state_;
+
+ Member<FetchClientSettingsObject> fetch_client_settings_object_;
};
} // namespace blink
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 aee6c718fa4..ef4702cd0fb 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
@@ -31,6 +31,8 @@
#include "third_party/blink/renderer/core/loader/frame_fetch_context.h"
#include <memory>
+
+#include "build/build_config.h"
#include "services/network/public/mojom/request_context_frame_type.mojom-blink.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -246,12 +248,13 @@ class FrameFetchContextSubresourceFilterTest : public FrameFetchContextTest {
void AppendExecutingScriptToAdTracker(const String& url) {
AdTracker* ad_tracker = document->GetFrame()->GetAdTracker();
- ad_tracker->WillExecuteScript(url);
+ ad_tracker->WillExecuteScript(document, url);
}
void AppendAdScriptToAdTracker(const KURL& ad_script_url) {
AdTracker* ad_tracker = document->GetFrame()->GetAdTracker();
- ad_tracker->AppendToKnownAdScripts(ad_script_url);
+ ad_tracker->AppendToKnownAdScripts(*(document.Get()),
+ ad_script_url.GetString());
}
private:
@@ -286,6 +289,7 @@ class FrameFetchContextMockedLocalFrameClientTest
dummy_page_holder =
DummyPageHolder::Create(IntSize(500, 500), nullptr, client);
dummy_page_holder->GetPage().SetDeviceScaleFactorDeprecated(1.0);
+ Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
document = &dummy_page_holder->GetDocument();
document->SetURL(main_resource_url);
fetch_context =
@@ -628,73 +632,37 @@ TEST_F(FrameFetchContextHintsTest, MonitorDeviceMemorySecureTransport) {
ExpectHeader("https://www.example.com/1.gif", "Device-Memory", false, "");
ClientHintsPreferences preferences;
preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDeviceMemory);
- document->GetClientHintsPreferences().UpdateFrom(preferences);
+ document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ApproximatedDeviceMemory::SetPhysicalMemoryMBForTesting(4096);
ExpectHeader("https://www.example.com/1.gif", "Device-Memory", true, "4");
ExpectHeader("https://www.example.com/1.gif", "DPR", false, "");
ExpectHeader("https://www.example.com/1.gif", "Width", false, "");
ExpectHeader("https://www.example.com/1.gif", "Viewport-Width", false, "");
- // The origin of the resource does not match the origin of the main frame
- // resource. Client hint should not be attached.
+// On non-Android platforms, the client hints should be sent only to the first
+// party origins.
+#if defined(OS_ANDROID)
+ ExpectHeader("https://www.someother-example.com/1.gif", "Device-Memory", true,
+ "4");
+#else
ExpectHeader("https://www.someother-example.com/1.gif", "Device-Memory",
false, "");
+#endif
}
-// Verify that the client hints should be attached for subresources fetched
-// over secure transport. Tests when the persistent client hint feature is not
-// enabled.
-TEST_F(FrameFetchContextHintsTest,
- MonitorDeviceMemorySecureTransportPersistentHintsDisabled) {
- WebRuntimeFeatures::EnableClientHintsPersistent(false);
- ExpectHeader("https://www.example.com/1.gif", "Device-Memory", false, "");
+// Verify that client hints are not attached when the resources do not belong to
+// a secure context.
+TEST_F(FrameFetchContextHintsTest, MonitorDeviceMemoryHintsInsecureContext) {
+ // Verify that client hints are not attached when the resources do not belong
+ // 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);
- document->GetClientHintsPreferences().UpdateFrom(preferences);
+ document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ApproximatedDeviceMemory::SetPhysicalMemoryMBForTesting(4096);
- ExpectHeader("https://www.example.com/1.gif", "Device-Memory", true, "4");
- ExpectHeader("https://www.example.com/1.gif", "DPR", false, "");
- ExpectHeader("https://www.example.com/1.gif", "Width", false, "");
- ExpectHeader("https://www.example.com/1.gif", "Viewport-Width", false, "");
- // The origin of the resource does not match the origin of the main frame
- // resource. Client hint should be attached since the persisten client hint
- // feature is not enabled.
- ExpectHeader("https://www.someother-example.com/1.gif", "Device-Memory", true,
- "4");
-}
-
-// Verify that client hints are not attched when the resources do not belong to
-// a secure context.
-TEST_F(FrameFetchContextHintsTest, MonitorDeviceMemoryHintsInsecureContext) {
- WebRuntimeFeatures::EnableClientHintsPersistent(false);
ExpectHeader("http://www.example.com/1.gif", "Device-Memory", false, "");
-
- {
- ClientHintsPreferences preferences;
- preferences.SetShouldSendForTesting(
- mojom::WebClientHintsType::kDeviceMemory);
- document->GetClientHintsPreferences().UpdateFrom(preferences);
- ApproximatedDeviceMemory::SetPhysicalMemoryMBForTesting(4096);
- ExpectHeader("http://www.example.com/1.gif", "Device-Memory", true, "4");
- ExpectHeader("http://www.example.com/1.gif", "DPR", false, "");
- ExpectHeader("http://www.example.com/1.gif", "Width", false, "");
- ExpectHeader("http://www.example.com/1.gif", "Viewport-Width", false, "");
- }
-
- {
- // Verify that client hints are not attched when the resources do not belong
- // to a secure context and the persistent client hint features is enabled.
- WebRuntimeFeatures::EnableClientHintsPersistent(true);
- ExpectHeader("http://www.example.com/1.gif", "Device-Memory", false, "");
- ClientHintsPreferences preferences;
- preferences.SetShouldSendForTesting(
- mojom::WebClientHintsType::kDeviceMemory);
- document->GetClientHintsPreferences().UpdateFrom(preferences);
- ApproximatedDeviceMemory::SetPhysicalMemoryMBForTesting(4096);
- ExpectHeader("http://www.example.com/1.gif", "Device-Memory", false, "");
- ExpectHeader("http://www.example.com/1.gif", "DPR", false, "");
- ExpectHeader("http://www.example.com/1.gif", "Width", false, "");
- ExpectHeader("http://www.example.com/1.gif", "Viewport-Width", false, "");
- }
+ ExpectHeader("http://www.example.com/1.gif", "DPR", false, "");
+ ExpectHeader("http://www.example.com/1.gif", "Width", false, "");
+ ExpectHeader("http://www.example.com/1.gif", "Viewport-Width", false, "");
}
// Verify that client hints are attched when the resources belong to a local
@@ -706,7 +674,7 @@ TEST_F(FrameFetchContextHintsTest, MonitorDeviceMemoryHintsLocalContext) {
ExpectHeader("http://localhost/1.gif", "Device-Memory", false, "");
ClientHintsPreferences preferences;
preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDeviceMemory);
- document->GetClientHintsPreferences().UpdateFrom(preferences);
+ document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ApproximatedDeviceMemory::SetPhysicalMemoryMBForTesting(4096);
ExpectHeader("http://localhost/1.gif", "Device-Memory", true, "4");
ExpectHeader("http://localhost/1.gif", "DPR", false, "");
@@ -718,7 +686,7 @@ TEST_F(FrameFetchContextHintsTest, MonitorDeviceMemoryHints) {
ExpectHeader("https://www.example.com/1.gif", "Device-Memory", false, "");
ClientHintsPreferences preferences;
preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDeviceMemory);
- document->GetClientHintsPreferences().UpdateFrom(preferences);
+ document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ApproximatedDeviceMemory::SetPhysicalMemoryMBForTesting(4096);
ExpectHeader("https://www.example.com/1.gif", "Device-Memory", true, "4");
ApproximatedDeviceMemory::SetPhysicalMemoryMBForTesting(2048);
@@ -736,7 +704,7 @@ TEST_F(FrameFetchContextHintsTest, MonitorDPRHints) {
ExpectHeader("https://www.example.com/1.gif", "DPR", false, "");
ClientHintsPreferences preferences;
preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDpr);
- document->GetClientHintsPreferences().UpdateFrom(preferences);
+ document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ExpectHeader("https://www.example.com/1.gif", "DPR", true, "1");
dummy_page_holder->GetPage().SetDeviceScaleFactorDeprecated(2.5);
ExpectHeader("https://www.example.com/1.gif", "DPR", true, "2.5");
@@ -745,28 +713,11 @@ TEST_F(FrameFetchContextHintsTest, MonitorDPRHints) {
}
TEST_F(FrameFetchContextHintsTest, MonitorDPRHintsInsecureTransport) {
- WebRuntimeFeatures::EnableClientHintsPersistent(false);
- ExpectHeader("http://www.example.com/1.gif", "DPR", false, "");
-
- {
- ClientHintsPreferences preferences;
- preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDpr);
- document->GetClientHintsPreferences().UpdateFrom(preferences);
- ExpectHeader("http://www.example.com/1.gif", "DPR", true, "1");
- dummy_page_holder->GetPage().SetDeviceScaleFactorDeprecated(2.5);
- ExpectHeader("http://www.example.com/1.gif", "DPR", true, "2.5");
- ExpectHeader("http://www.example.com/1.gif", "Width", false, "");
- ExpectHeader("http://www.example.com/1.gif", "Viewport-Width", false, "");
- }
-
- {
- WebRuntimeFeatures::EnableClientHintsPersistent(true);
ExpectHeader("http://www.example.com/1.gif", "DPR", false, "");
dummy_page_holder->GetPage().SetDeviceScaleFactorDeprecated(2.5);
ExpectHeader("http://www.example.com/1.gif", "DPR", false, " ");
ExpectHeader("http://www.example.com/1.gif", "Width", false, "");
ExpectHeader("http://www.example.com/1.gif", "Viewport-Width", false, "");
- }
}
TEST_F(FrameFetchContextHintsTest, MonitorResourceWidthHints) {
@@ -774,7 +725,7 @@ TEST_F(FrameFetchContextHintsTest, MonitorResourceWidthHints) {
ClientHintsPreferences preferences;
preferences.SetShouldSendForTesting(
mojom::WebClientHintsType::kResourceWidth);
- document->GetClientHintsPreferences().UpdateFrom(preferences);
+ 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);
ExpectHeader("https://www.example.com/1.gif", "DPR", false, "");
@@ -789,7 +740,7 @@ TEST_F(FrameFetchContextHintsTest, MonitorViewportWidthHints) {
ClientHintsPreferences preferences;
preferences.SetShouldSendForTesting(
mojom::WebClientHintsType::kViewportWidth);
- document->GetClientHintsPreferences().UpdateFrom(preferences);
+ document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ExpectHeader("https://www.example.com/1.gif", "Viewport-Width", true, "500");
dummy_page_holder->GetFrameView().SetLayoutSizeFixedToFrameSize(false);
dummy_page_holder->GetFrameView().SetLayoutSize(IntSize(800, 800));
@@ -819,7 +770,7 @@ TEST_F(FrameFetchContextHintsTest, MonitorAllHints) {
preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kDownlink);
preferences.SetShouldSendForTesting(mojom::WebClientHintsType::kEct);
ApproximatedDeviceMemory::SetPhysicalMemoryMBForTesting(4096);
- document->GetClientHintsPreferences().UpdateFrom(preferences);
+ document->GetFrame()->GetClientHintsPreferences().UpdateFrom(preferences);
ExpectHeader("https://www.example.com/1.gif", "Device-Memory", true, "4");
ExpectHeader("https://www.example.com/1.gif", "DPR", true, "1");
ExpectHeader("https://www.example.com/1.gif", "Width", true, "400", 400);
@@ -860,20 +811,20 @@ TEST_F(FrameFetchContextTest, MainResourceCachePolicy) {
post_request, Resource::kMainResource, FetchParameters::kNoDefer));
// Re-post
- document->Loader()->SetLoadType(kFrameLoadTypeBackForward);
+ document->Loader()->SetLoadType(WebFrameLoadType::kBackForward);
EXPECT_EQ(
mojom::FetchCacheMode::kOnlyIfCached,
fetch_context->ResourceRequestCachePolicy(
post_request, Resource::kMainResource, FetchParameters::kNoDefer));
- // FrameLoadTypeReload
- document->Loader()->SetLoadType(kFrameLoadTypeReload);
+ // WebFrameLoadType::kReload
+ document->Loader()->SetLoadType(WebFrameLoadType::kReload);
EXPECT_EQ(mojom::FetchCacheMode::kValidateCache,
fetch_context->ResourceRequestCachePolicy(
request, Resource::kMainResource, FetchParameters::kNoDefer));
// Conditional request
- document->Loader()->SetLoadType(kFrameLoadTypeStandard);
+ document->Loader()->SetLoadType(WebFrameLoadType::kStandard);
ResourceRequest conditional("http://www.example.com");
conditional.SetHTTPHeaderField(HTTPNames::If_Modified_Since, "foo");
EXPECT_EQ(
@@ -881,21 +832,21 @@ TEST_F(FrameFetchContextTest, MainResourceCachePolicy) {
fetch_context->ResourceRequestCachePolicy(
conditional, Resource::kMainResource, FetchParameters::kNoDefer));
- // FrameLoadTypeReloadBypassingCache
- document->Loader()->SetLoadType(kFrameLoadTypeReloadBypassingCache);
+ // WebFrameLoadType::kReloadBypassingCache
+ document->Loader()->SetLoadType(WebFrameLoadType::kReloadBypassingCache);
EXPECT_EQ(mojom::FetchCacheMode::kBypassCache,
fetch_context->ResourceRequestCachePolicy(
request, Resource::kMainResource, FetchParameters::kNoDefer));
- // FrameLoadTypeReloadBypassingCache with a conditional request
- document->Loader()->SetLoadType(kFrameLoadTypeReloadBypassingCache);
+ // WebFrameLoadType::kReloadBypassingCache with a conditional request
+ document->Loader()->SetLoadType(WebFrameLoadType::kReloadBypassingCache);
EXPECT_EQ(
mojom::FetchCacheMode::kBypassCache,
fetch_context->ResourceRequestCachePolicy(
conditional, Resource::kMainResource, FetchParameters::kNoDefer));
- // FrameLoadTypeReloadBypassingCache with a post request
- document->Loader()->SetLoadType(kFrameLoadTypeReloadBypassingCache);
+ // WebFrameLoadType::kReloadBypassingCache with a post request
+ document->Loader()->SetLoadType(WebFrameLoadType::kReloadBypassingCache);
EXPECT_EQ(
mojom::FetchCacheMode::kBypassCache,
fetch_context->ResourceRequestCachePolicy(
@@ -905,19 +856,19 @@ TEST_F(FrameFetchContextTest, MainResourceCachePolicy) {
FrameFetchContext* child_fetch_context = CreateChildFrame();
// Child frame as part of back/forward
- document->Loader()->SetLoadType(kFrameLoadTypeBackForward);
+ document->Loader()->SetLoadType(WebFrameLoadType::kBackForward);
EXPECT_EQ(mojom::FetchCacheMode::kForceCache,
child_fetch_context->ResourceRequestCachePolicy(
request, Resource::kMainResource, FetchParameters::kNoDefer));
// Child frame as part of reload
- document->Loader()->SetLoadType(kFrameLoadTypeReload);
+ document->Loader()->SetLoadType(WebFrameLoadType::kReload);
EXPECT_EQ(mojom::FetchCacheMode::kDefault,
child_fetch_context->ResourceRequestCachePolicy(
request, Resource::kMainResource, FetchParameters::kNoDefer));
// Child frame as part of reload bypassing cache
- document->Loader()->SetLoadType(kFrameLoadTypeReloadBypassingCache);
+ document->Loader()->SetLoadType(WebFrameLoadType::kReloadBypassingCache);
EXPECT_EQ(mojom::FetchCacheMode::kBypassCache,
child_fetch_context->ResourceRequestCachePolicy(
request, Resource::kMainResource, FetchParameters::kNoDefer));
@@ -925,9 +876,9 @@ TEST_F(FrameFetchContextTest, MainResourceCachePolicy) {
// Per-frame bypassing reload, but parent load type is different.
// This is not the case users can trigger through user interfaces, but for
// checking code correctness and consistency.
- document->Loader()->SetLoadType(kFrameLoadTypeReload);
+ document->Loader()->SetLoadType(WebFrameLoadType::kReload);
child_frame->Loader().GetDocumentLoader()->SetLoadType(
- kFrameLoadTypeReloadBypassingCache);
+ WebFrameLoadType::kReloadBypassingCache);
EXPECT_EQ(mojom::FetchCacheMode::kBypassCache,
child_fetch_context->ResourceRequestCachePolicy(
request, Resource::kMainResource, FetchParameters::kNoDefer));
@@ -945,40 +896,40 @@ TEST_F(FrameFetchContextTest, SubResourceCachePolicy) {
fetch_context->ResourceRequestCachePolicy(
request, Resource::kMock, FetchParameters::kNoDefer));
- // FrameLoadTypeReload should not affect sub-resources
- document->Loader()->SetLoadType(kFrameLoadTypeReload);
+ // WebFrameLoadType::kReload should not affect sub-resources
+ document->Loader()->SetLoadType(WebFrameLoadType::kReload);
EXPECT_EQ(mojom::FetchCacheMode::kDefault,
fetch_context->ResourceRequestCachePolicy(
request, Resource::kMock, FetchParameters::kNoDefer));
// Conditional request
- document->Loader()->SetLoadType(kFrameLoadTypeStandard);
+ document->Loader()->SetLoadType(WebFrameLoadType::kStandard);
ResourceRequest conditional("http://www.example.com/mock");
conditional.SetHTTPHeaderField(HTTPNames::If_Modified_Since, "foo");
EXPECT_EQ(mojom::FetchCacheMode::kValidateCache,
fetch_context->ResourceRequestCachePolicy(
conditional, Resource::kMock, FetchParameters::kNoDefer));
- // FrameLoadTypeReloadBypassingCache
- document->Loader()->SetLoadType(kFrameLoadTypeReloadBypassingCache);
+ // WebFrameLoadType::kReloadBypassingCache
+ document->Loader()->SetLoadType(WebFrameLoadType::kReloadBypassingCache);
EXPECT_EQ(mojom::FetchCacheMode::kBypassCache,
fetch_context->ResourceRequestCachePolicy(
request, Resource::kMock, FetchParameters::kNoDefer));
- // FrameLoadTypeReloadBypassingCache with a conditional request
- document->Loader()->SetLoadType(kFrameLoadTypeReloadBypassingCache);
+ // WebFrameLoadType::kReloadBypassingCache with a conditional request
+ document->Loader()->SetLoadType(WebFrameLoadType::kReloadBypassingCache);
EXPECT_EQ(mojom::FetchCacheMode::kBypassCache,
fetch_context->ResourceRequestCachePolicy(
conditional, Resource::kMock, FetchParameters::kNoDefer));
// Back/forward navigation
- document->Loader()->SetLoadType(kFrameLoadTypeBackForward);
+ document->Loader()->SetLoadType(WebFrameLoadType::kBackForward);
EXPECT_EQ(mojom::FetchCacheMode::kForceCache,
fetch_context->ResourceRequestCachePolicy(
request, Resource::kMock, FetchParameters::kNoDefer));
// Back/forward navigation with a conditional request
- document->Loader()->SetLoadType(kFrameLoadTypeBackForward);
+ document->Loader()->SetLoadType(WebFrameLoadType::kBackForward);
EXPECT_EQ(mojom::FetchCacheMode::kForceCache,
fetch_context->ResourceRequestCachePolicy(
conditional, Resource::kMock, FetchParameters::kNoDefer));
@@ -1144,7 +1095,7 @@ TEST_F(FrameFetchContextTest, ChangeDataSaverConfig) {
GetNetworkStateNotifier().SetSaveDataEnabledOverride(false);
RecreateFetchContext();
- document->Loader()->SetLoadType(kFrameLoadTypeReload);
+ document->Loader()->SetLoadType(WebFrameLoadType::kReload);
fetch_context->AddAdditionalRequestHeaders(resource_request,
kFetchMainResource);
EXPECT_EQ(String(), resource_request.HttpHeaderField("Save-Data"));
@@ -1157,7 +1108,7 @@ TEST_F(FrameFetchContextTest, ChangeDataSaverConfig) {
GetNetworkStateNotifier().SetSaveDataEnabledOverride(false);
RecreateFetchContext();
- document->Loader()->SetLoadType(kFrameLoadTypeReload);
+ document->Loader()->SetLoadType(WebFrameLoadType::kReload);
fetch_context->AddAdditionalRequestHeaders(resource_request,
kFetchMainResource);
EXPECT_EQ(String(), resource_request.HttpHeaderField("Save-Data"));
@@ -1186,87 +1137,6 @@ TEST_F(FrameFetchContextMockedLocalFrameClientTest,
CreateUniqueIdentifier(), resource_request, resource->GetResponse());
}
-// Tests that the client hints lifetime header is parsed correctly only when the
-// frame belongs to a secure context.
-// TODO(lunalu): remove this test when blink side use counter is removed
-// (crbug.com/811948).
-TEST_F(FrameFetchContextMockedLocalFrameClientTest,
- PersistClientHintsSecureContext) {
- HistogramTester histogram_tester;
-
- {
- ASSERT_EQ(url.Host(), main_resource_url.Host());
- ASSERT_EQ("https", url.Protocol());
- ResourceRequest resource_request(url);
- resource_request.SetRequestContext(WebURLRequest::kRequestContextImage);
- resource_request.SetFetchCredentialsMode(
- network::mojom::FetchCredentialsMode::kOmit);
- ResourceResponse response(url);
- response.SetHTTPHeaderField("accept-ch", "dpr");
- response.SetHTTPHeaderField("accept-ch-lifetime", "3600");
- Resource* resource = MockResource::Create(resource_request);
- resource->SetResponse(response);
- fetch_context->DispatchDidReceiveResponse(
- CreateUniqueIdentifier(), response, resource_request.GetFrameType(),
- resource_request.GetRequestContext(), resource,
- FetchContext::ResourceResponseType::kNotFromMemoryCache);
-
- histogram_tester.ExpectBucketCount(
- "Blink.UseCounter.Features_Legacy",
- static_cast<int>(WebFeature::kPersistentClientHintHeader), 1);
- }
-
- {
- // Try with a different resource that has a different origin than the main
- // frame.
- ASSERT_NE(different_host_url.Host(), main_resource_url.Host());
- ASSERT_EQ("https", different_host_url.Protocol());
- ResourceRequest resource_request(different_host_url);
- resource_request.SetRequestContext(WebURLRequest::kRequestContextImage);
- resource_request.SetFetchCredentialsMode(
- network::mojom::FetchCredentialsMode::kOmit);
- ResourceResponse response(different_host_url);
- response.SetHTTPHeaderField("accept-ch", "dpr");
- response.SetHTTPHeaderField("accept-ch-lifetime", "3600");
- Resource* resource = MockResource::Create(resource_request);
- resource->SetResponse(response);
- fetch_context->DispatchDidReceiveResponse(
- CreateUniqueIdentifier(), response, resource_request.GetFrameType(),
- resource_request.GetRequestContext(), resource,
- FetchContext::ResourceResponseType::kNotFromMemoryCache);
-
- // There should not be a change in the usage count.
- histogram_tester.ExpectBucketCount(
- "Blink.UseCounter.Features_Legacy",
- static_cast<int>(WebFeature::kPersistentClientHintHeader), 1);
- }
-
- {
- // Next, try with a HTTP URL.
- ASSERT_EQ(http_url.Host(), main_resource_url.Host());
- ASSERT_EQ("http", http_url.Protocol());
- ResourceRequest resource_request(http_url);
- resource_request.SetRequestContext(WebURLRequest::kRequestContextImage);
- resource_request.SetFetchCredentialsMode(
- network::mojom::FetchCredentialsMode::kOmit);
-
- ResourceResponse response(http_url);
- response.SetHTTPHeaderField("accept-ch", "dpr");
- response.SetHTTPHeaderField("accept-ch-lifetime", "3600");
- Resource* resource = MockResource::Create(resource_request);
- resource->SetResponse(response);
- fetch_context->DispatchDidReceiveResponse(
- CreateUniqueIdentifier(), response, resource_request.GetFrameType(),
- resource_request.GetRequestContext(), resource,
- FetchContext::ResourceResponseType::kNotFromMemoryCache);
-
- // There should not be a change in the usage count.
- histogram_tester.ExpectBucketCount(
- "Blink.UseCounter.Features_Legacy",
- static_cast<int>(WebFeature::kPersistentClientHintHeader), 1);
- }
-}
-
// Tests that when a resource with certificate errors is loaded from the memory
// cache, the embedder is notified.
TEST_F(FrameFetchContextMockedLocalFrameClientTest,
@@ -1345,26 +1215,6 @@ TEST_F(FrameFetchContextSubresourceFilterTest, AdTaggingBasedOnFrame) {
EXPECT_EQ(0, GetFilteredLoadCallCount());
}
-// Tests that if a subresource is allowed as per subresource filter ruleset and
-// is not fetched from a frame that is tagged as an ad, then the subresource
-// should be tagged as ad if one of the executing scripts is tagged as an ad.
-TEST_F(FrameFetchContextSubresourceFilterTest,
- AdTaggingBasedOnExecutingScript) {
- SetFilterPolicy(WebDocumentSubresourceFilter::kAllow,
- false /* is_associated_with_ad_subframe */);
-
- KURL ad_script_url("https://example.com/bar.js");
- AppendAdScriptToAdTracker(ad_script_url);
- AppendExecutingScriptToAdTracker(ad_script_url.GetString());
-
- EXPECT_EQ(base::nullopt, CanRequestAndVerifyIsAd(false));
- EXPECT_EQ(0, GetFilteredLoadCallCount());
-
- // After WillSendRequest probe, it should be marked as an ad.
- EXPECT_TRUE(DispatchWillSendRequestAndVerifyIsAd(
- KURL("https://www.example.com/image.jpg")));
-}
-
TEST_F(FrameFetchContextTest, AddAdditionalRequestHeadersWhenDetached) {
const KURL document_url("https://www2.example.com/fuga/hoge.html");
const String origin = "https://www2.example.com";
@@ -1476,13 +1326,6 @@ TEST_F(FrameFetchContextTest, DispatchDidReceiveEncodedDataWhenDetached) {
// Should not crash.
}
-TEST_F(FrameFetchContextTest, DispatchDidDownloadDataWhenDetached) {
- dummy_page_holder = nullptr;
-
- fetch_context->DispatchDidDownloadData(4, 7, 9);
- // Should not crash.
-}
-
TEST_F(FrameFetchContextTest, DispatchDidFinishLoadingWhenDetached) {
dummy_page_holder = nullptr;
@@ -1555,7 +1398,8 @@ TEST_F(FrameFetchContextTest, AllowImageWhenDetached) {
TEST_F(FrameFetchContextTest, IsControlledByServiceWorkerWhenDetached) {
dummy_page_holder = nullptr;
- EXPECT_FALSE(fetch_context->IsControlledByServiceWorker());
+ EXPECT_EQ(blink::mojom::ControllerServiceWorkerMode::kNoController,
+ fetch_context->IsControlledByServiceWorker());
}
TEST_F(FrameFetchContextTest, IsMainFrameWhenDetached) {
@@ -1601,13 +1445,6 @@ TEST_F(FrameFetchContextTest, UpdateTimingInfoForIFrameNavigationWhenDetached) {
// Should not crash.
}
-TEST_F(FrameFetchContextTest, AddConsoleMessageWhenDetached) {
- dummy_page_holder = nullptr;
-
- fetch_context->AddWarningConsoleMessage("foobar", FetchContext::kJSSource);
- // Should not crash.
-}
-
TEST_F(FrameFetchContextTest, GetSecurityOriginWhenDetached) {
scoped_refptr<SecurityOrigin> origin =
SecurityOrigin::Create(KURL("https://www.example.com"));
@@ -1635,13 +1472,13 @@ TEST_F(FrameFetchContextTest, PopulateResourceRequestWhenDetached) {
FetchParameters::ResourceWidth resource_width;
ResourceLoaderOptions options;
- document->GetClientHintsPreferences().SetShouldSendForTesting(
+ document->GetFrame()->GetClientHintsPreferences().SetShouldSendForTesting(
mojom::WebClientHintsType::kDeviceMemory);
- document->GetClientHintsPreferences().SetShouldSendForTesting(
+ document->GetFrame()->GetClientHintsPreferences().SetShouldSendForTesting(
mojom::WebClientHintsType::kDpr);
- document->GetClientHintsPreferences().SetShouldSendForTesting(
+ document->GetFrame()->GetClientHintsPreferences().SetShouldSendForTesting(
mojom::WebClientHintsType::kResourceWidth);
- document->GetClientHintsPreferences().SetShouldSendForTesting(
+ document->GetFrame()->GetClientHintsPreferences().SetShouldSendForTesting(
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 878cec12e4e..0b30b8daa12 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
+#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
@@ -96,7 +97,7 @@ FrameLoadRequest::FrameLoadRequest(
SecurityOrigin::Create(origin_document->Url()));
if (resource_request.Url().ProtocolIs("blob") &&
- RuntimeEnabledFeatures::MojoBlobURLsEnabled()) {
+ BlobUtils::MojoBlobURLsEnabled()) {
blob_url_token_ = base::MakeRefCounted<
base::RefCountedData<mojom::blink::BlobURLTokenPtr>>();
origin_document->GetPublicURLManager().Resolve(
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 ff502218a33..29230b12329 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
@@ -27,17 +27,18 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_FRAME_LOAD_REQUEST_H_
#include "base/unguessable_token.h"
+#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink.h"
+#include "third_party/blink/public/web/web_triggering_event_info.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/frame/frame_types.h"
#include "third_party/blink/renderer/core/loader/frame_loader_types.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
#include "third_party/blink/renderer/platform/loader/fetch/substitute_data.h"
namespace blink {
class HTMLFormElement;
-class ResourceRequest;
-class SubstituteData;
struct CORE_EXPORT FrameLoadRequest {
STACK_ALLOCATED();
@@ -85,9 +86,12 @@ struct CORE_EXPORT FrameLoadRequest {
client_redirect_ = client_redirect;
}
- Event* TriggeringEvent() const { return triggering_event_.Get(); }
- void SetTriggeringEvent(Event* triggering_event) {
- triggering_event_ = triggering_event;
+ WebTriggeringEventInfo TriggeringEventInfo() const {
+ return triggering_event_info_;
+ }
+ void SetTriggeringEventInfo(WebTriggeringEventInfo info) {
+ DCHECK(info != WebTriggeringEventInfo::kUnknown);
+ triggering_event_info_ = info;
}
HTMLFormElement* Form() const { return form_.Get(); }
@@ -153,7 +157,8 @@ struct CORE_EXPORT FrameLoadRequest {
SubstituteData substitute_data_;
bool replaces_current_item_;
ClientRedirectPolicy client_redirect_;
- Member<Event> triggering_event_;
+ WebTriggeringEventInfo triggering_event_info_ =
+ WebTriggeringEventInfo::kNotFromEvent;
Member<HTMLFormElement> form_;
ShouldSendReferrer should_send_referrer_;
ShouldSetOpener should_set_opener_;
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 8fea0821d8d..00dd9874383 100644
--- a/chromium/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -40,7 +40,7 @@
#include "base/auto_reset.h"
#include "services/network/public/mojom/request_context_frame_type.mojom-blink.h"
#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/web/web_frame_load_type.h"
@@ -49,11 +49,6 @@
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.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/viewport_description.h"
-#include "third_party/blink/renderer/core/events/gesture_event.h"
-#include "third_party/blink/renderer/core/events/keyboard_event.h"
-#include "third_party/blink/renderer/core/events/mouse_event.h"
#include "third_party/blink/renderer/core/events/page_transition_event.h"
#include "third_party/blink/renderer/core/frame/content_settings_client.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
@@ -83,11 +78,15 @@
#include "third_party/blink/renderer/core/page/frame_tree.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
+#include "third_party/blink/renderer/core/page/viewport_description.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/svg/graphics/svg_image.h"
#include "third_party/blink/renderer/core/xml/parser/xml_document_parser.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.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"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/instance_counters.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -111,65 +110,38 @@ namespace blink {
using namespace HTMLNames;
-bool IsBackForwardLoadType(FrameLoadType type) {
- return type == kFrameLoadTypeBackForward ||
- type == kFrameLoadTypeInitialHistoryLoad;
+bool IsBackForwardLoadType(WebFrameLoadType type) {
+ return type == WebFrameLoadType::kBackForward;
}
-bool IsReloadLoadType(FrameLoadType type) {
- return type == kFrameLoadTypeReload ||
- type == kFrameLoadTypeReloadBypassingCache;
+bool IsReloadLoadType(WebFrameLoadType type) {
+ return type == WebFrameLoadType::kReload ||
+ type == WebFrameLoadType::kReloadBypassingCache;
}
-static bool NeedsHistoryItemRestore(FrameLoadType type) {
- // FrameLoadtypeInitialHistoryLoad is intentionally excluded.
- return type == kFrameLoadTypeBackForward || IsReloadLoadType(type);
-}
-
-static NavigationPolicy MaybeCheckCSP(
- const ResourceRequest& request,
- NavigationType type,
- LocalFrame* frame,
- NavigationPolicy policy,
- bool should_check_main_world_content_security_policy,
- ContentSecurityPolicy::CheckHeaderType check_header_type) {
- // TODO(arthursonzogni): 'frame-src' check is disabled on the
- // renderer side, but is enforced on the browser side.
- // See http://crbug.com/692595 for understanding why it
- // can't be enforced on both sides instead.
-
- // 'form-action' check in the frame that is navigating is disabled on the
- // renderer side, but is enforced on the browser side instead.
- // N.B. check in the frame that initiates the navigation stills occurs in
- // blink and is not enforced on the browser-side.
- // TODO(arthursonzogni) The 'form-action' check should be fully disabled
- // in blink, except when the form submission doesn't trigger a navigation
- // (i.e. javascript urls). Please see https://crbug.com/701749.
-
- // TODO(dgozman): find better place for the comments above and
- // remove this method entirely.
- return policy;
+static bool NeedsHistoryItemRestore(WebFrameLoadType type) {
+ return type == WebFrameLoadType::kBackForward || IsReloadLoadType(type);
}
static SinglePageAppNavigationType CategorizeSinglePageAppNavigation(
SameDocumentNavigationSource same_document_navigation_source,
- FrameLoadType frame_load_type) {
+ WebFrameLoadType frame_load_type) {
// |SinglePageAppNavigationType| falls into this grid according to different
- // combinations of |FrameLoadType| and |SameDocumentNavigationSource|:
+ // combinations of |WebFrameLoadType| and |SameDocumentNavigationSource|:
//
- // HistoryApi Default
- // kFrameLoadTypeBackForward illegal otherFragmentNav
- // !kFrameLoadTypeBackForward sameDocBack/Forward historyPushOrReplace
+ // HistoryApi Default
+ // kBackForward illegal otherFragmentNav
+ // !kBackForward sameDocBack/Forward historyPushOrReplace
switch (same_document_navigation_source) {
case kSameDocumentNavigationDefault:
- if (frame_load_type == kFrameLoadTypeBackForward) {
+ if (frame_load_type == WebFrameLoadType::kBackForward) {
return kSPANavTypeSameDocumentBackwardOrForward;
}
return kSPANavTypeOtherFragmentNavigation;
case kSameDocumentNavigationHistoryApi:
// It's illegal to have both kSameDocumentNavigationHistoryApi and
- // kFrameLoadTypeBackForward.
- DCHECK(frame_load_type != kFrameLoadTypeBackForward);
+ // WebFrameLoadType::kBackForward.
+ DCHECK(frame_load_type != WebFrameLoadType::kBackForward);
return kSPANavTypeHistoryPushStateOrReplaceState;
}
NOTREACHED();
@@ -177,12 +149,13 @@ static SinglePageAppNavigationType CategorizeSinglePageAppNavigation(
}
ResourceRequest FrameLoader::ResourceRequestForReload(
- FrameLoadType frame_load_type,
+ WebFrameLoadType frame_load_type,
ClientRedirectPolicy client_redirect_policy) {
DCHECK(IsReloadLoadType(frame_load_type));
- const auto cache_mode = frame_load_type == kFrameLoadTypeReloadBypassingCache
- ? mojom::FetchCacheMode::kBypassCache
- : mojom::FetchCacheMode::kValidateCache;
+ const auto cache_mode =
+ frame_load_type == WebFrameLoadType::kReloadBypassingCache
+ ? mojom::FetchCacheMode::kBypassCache
+ : mojom::FetchCacheMode::kValidateCache;
if (!document_loader_ || !document_loader_->GetHistoryItem())
return ResourceRequest();
ResourceRequest request =
@@ -205,7 +178,7 @@ ResourceRequest FrameLoader::ResourceRequestForReload(
}
request.SetSkipServiceWorker(frame_load_type ==
- kFrameLoadTypeReloadBypassingCache);
+ WebFrameLoadType::kReloadBypassingCache);
return request;
}
@@ -244,10 +217,11 @@ void FrameLoader::Init() {
frame_->IsMainFrame() ? network::mojom::RequestContextFrameType::kTopLevel
: network::mojom::RequestContextFrameType::kNested);
- provisional_document_loader_ =
- Client()->CreateDocumentLoader(frame_, initial_request, SubstituteData(),
- ClientRedirectPolicy::kNotClientRedirect,
- base::UnguessableToken::Create());
+ provisional_document_loader_ = Client()->CreateDocumentLoader(
+ frame_, initial_request, SubstituteData(),
+ ClientRedirectPolicy::kNotClientRedirect,
+ base::UnguessableToken::Create(), nullptr /* extra_data */,
+ WebNavigationTimings());
provisional_document_loader_->StartLoading();
frame_->GetDocument()->CancelParsing();
@@ -303,7 +277,7 @@ void FrameLoader::SaveScrollAnchor() {
HistoryItem* history_item = document_loader_->GetHistoryItem();
if (ScrollableArea* layout_scrollable_area =
- frame_->View()->LayoutViewportScrollableArea()) {
+ frame_->View()->LayoutViewport()) {
ScrollAnchor* scroll_anchor = layout_scrollable_area->GetScrollAnchor();
DCHECK(scroll_anchor);
@@ -330,8 +304,7 @@ void FrameLoader::SaveScrollState() {
return;
HistoryItem* history_item = document_loader_->GetHistoryItem();
- if (ScrollableArea* layout_scrollable_area =
- frame_->View()->LayoutViewportScrollableArea())
+ if (ScrollableArea* layout_scrollable_area = frame_->View()->LayoutViewport())
history_item->SetScrollOffset(layout_scrollable_area->GetScrollOffset());
history_item->SetVisualViewportScrollOffset(ToScrollOffset(
frame_->GetPage()->GetVisualViewport().VisibleRect().Location()));
@@ -365,7 +338,7 @@ void FrameLoader::DidExplicitOpen() {
if ((parent->IsLocalFrame() &&
ToLocalFrame(parent)->GetDocument()->LoadEventStillNeeded()) ||
(parent->IsRemoteFrame() && parent->IsLoading())) {
- progress_tracker_->ProgressStarted(document_loader_->LoadType());
+ progress_tracker_->ProgressStarted();
}
}
@@ -393,8 +366,12 @@ void FrameLoader::ReplaceDocumentWhileExecutingJavaScriptURL(
// Compute this before clearing the frame, because it may need to inherit an
// aliased security context.
+ // The document CSP is the correct one as it is used for CSP checks
+ // done previously before getting here:
+ // HTMLFormElement::ScheduleFormSubmission
+ // HTMLFrameElementBase::OpenURL
WebGlobalObjectReusePolicy global_object_reuse_policy =
- frame_->ShouldReuseDefaultView(url)
+ frame_->ShouldReuseDefaultView(url, document->GetContentSecurityPolicy())
? WebGlobalObjectReusePolicy::kUseExisting
: WebGlobalObjectReusePolicy::kCreateNew;
@@ -432,16 +409,12 @@ void FrameLoader::FinishedParsing() {
document_loader_ ? document_loader_->IsCommittedButEmpty() : true);
}
- frame_->GetDocument()->CheckCompleted();
-
- if (!frame_->View())
- return;
+ if (frame_->View()) {
+ ProcessFragment(frame_->GetDocument()->Url(), document_loader_->LoadType(),
+ kNavigationToDifferentDocument);
+ }
- // Check if the scrollbars are really needed for the content. If not, remove
- // them, relayout, and repaint.
- frame_->View()->RestoreScrollbar();
- ProcessFragment(frame_->GetDocument()->Url(), document_loader_->LoadType(),
- kNavigationToDifferentDocument);
+ frame_->GetDocument()->CheckCompleted();
}
bool FrameLoader::AllAncestorsAreComplete() const {
@@ -473,7 +446,7 @@ void FrameLoader::DidFinishNavigation() {
// size clamping.
RestoreScrollPositionAndViewState();
if (document_loader_)
- document_loader_->SetLoadType(kFrameLoadTypeStandard);
+ document_loader_->SetLoadType(WebFrameLoadType::kStandard);
frame_->DomWindow()->FinishedLoading();
}
@@ -509,7 +482,7 @@ void FrameLoader::UpdateForSameDocumentNavigation(
SameDocumentNavigationSource same_document_navigation_source,
scoped_refptr<SerializedScriptValue> data,
HistoryScrollRestorationType scroll_restoration_type,
- FrameLoadType type,
+ WebFrameLoadType type,
Document* initiating_document) {
SinglePageAppNavigationType single_page_app_navigation_type =
CategorizeSinglePageAppNavigation(same_document_navigation_source, type);
@@ -555,12 +528,12 @@ void FrameLoader::ClearInitialScrollState() {
void FrameLoader::LoadInSameDocument(
const KURL& url,
scoped_refptr<SerializedScriptValue> state_object,
- FrameLoadType frame_load_type,
+ WebFrameLoadType frame_load_type,
HistoryItem* history_item,
ClientRedirectPolicy client_redirect,
Document* initiating_document) {
// If we have a state object, we cannot also be a new navigation.
- DCHECK(!state_object || frame_load_type == kFrameLoadTypeBackForward);
+ DCHECK(!state_object || frame_load_type == WebFrameLoadType::kBackForward);
// If we have a provisional request for a different document, a fragment
// scroll should cancel it.
@@ -603,9 +576,9 @@ void FrameLoader::LoadInSameDocument(
: SerializedScriptValue::NullValue());
if (history_item) {
- RestoreScrollPositionAndViewState(frame_load_type, kHistorySameDocumentLoad,
- view_state.get(),
- history_item->ScrollRestorationType());
+ RestoreScrollPositionAndViewState(
+ frame_load_type, true /* is_same_document */, view_state.get(),
+ history_item->ScrollRestorationType());
}
// We need to scroll to the fragment whether or not a hash change occurred,
@@ -640,22 +613,22 @@ void FrameLoader::SetReferrerForFrameRequest(FrameLoadRequest& frame_request) {
request.SetHTTPOriginToMatchReferrerIfNeeded();
}
-FrameLoadType FrameLoader::DetermineFrameLoadType(
+WebFrameLoadType FrameLoader::DetermineFrameLoadType(
const FrameLoadRequest& request) {
if (frame_->Tree().Parent() &&
!state_machine_.CommittedFirstRealDocumentLoad())
- return kFrameLoadTypeInitialInChildFrame;
+ return WebFrameLoadType::kReplaceCurrentItem;
if (!frame_->Tree().Parent() && !Client()->BackForwardLength()) {
if (Opener() && request.GetResourceRequest().Url().IsEmpty())
- return kFrameLoadTypeReplaceCurrentItem;
- return kFrameLoadTypeStandard;
+ return WebFrameLoadType::kReplaceCurrentItem;
+ return WebFrameLoadType::kStandard;
}
if (request.GetResourceRequest().GetCacheMode() ==
mojom::FetchCacheMode::kValidateCache)
- return kFrameLoadTypeReload;
+ return WebFrameLoadType::kReload;
if (request.GetResourceRequest().GetCacheMode() ==
mojom::FetchCacheMode::kBypassCache)
- return kFrameLoadTypeReloadBypassingCache;
+ return WebFrameLoadType::kReloadBypassingCache;
// From the HTML5 spec for location.assign():
// "If the browsing context's session history contains only one Document,
// and that was the about:blank Document created when the browsing context
@@ -663,31 +636,31 @@ FrameLoadType FrameLoader::DetermineFrameLoadType(
if (request.ReplacesCurrentItem() ||
(!state_machine_.CommittedMultipleRealLoads() &&
DeprecatedEqualIgnoringCase(frame_->GetDocument()->Url(), BlankURL())))
- return kFrameLoadTypeReplaceCurrentItem;
+ return WebFrameLoadType::kReplaceCurrentItem;
if (request.GetResourceRequest().Url() == document_loader_->UrlForHistory()) {
if (request.GetResourceRequest().HttpMethod() == HTTPNames::POST)
- return kFrameLoadTypeStandard;
+ return WebFrameLoadType::kStandard;
if (!request.OriginDocument())
- return kFrameLoadTypeReload;
- return kFrameLoadTypeReplaceCurrentItem;
+ return WebFrameLoadType::kReload;
+ return WebFrameLoadType::kReplaceCurrentItem;
}
if (request.GetSubstituteData().FailingURL() ==
document_loader_->UrlForHistory() &&
- document_loader_->LoadType() == kFrameLoadTypeReload)
- return kFrameLoadTypeReload;
+ document_loader_->LoadType() == WebFrameLoadType::kReload)
+ return WebFrameLoadType::kReload;
if (request.GetResourceRequest().Url().IsEmpty() &&
request.GetSubstituteData().FailingURL().IsEmpty()) {
- return kFrameLoadTypeReplaceCurrentItem;
+ return WebFrameLoadType::kReplaceCurrentItem;
}
if (request.OriginDocument() &&
!request.OriginDocument()->CanCreateHistoryEntry())
- return kFrameLoadTypeReplaceCurrentItem;
+ return WebFrameLoadType::kReplaceCurrentItem;
- return kFrameLoadTypeStandard;
+ return WebFrameLoadType::kStandard;
}
bool FrameLoader::PrepareRequestForThisFrame(FrameLoadRequest& request) {
@@ -716,7 +689,6 @@ bool FrameLoader::PrepareRequestForThisFrame(FrameLoadRequest& request) {
// embedder figure out what to do with it. Navigations to filesystem URLs are
// always blocked here.
if (frame_->IsMainFrame() &&
- !request.GetResourceRequest().IsSameDocumentNavigation() &&
!frame_->Client()->AllowContentInitiatedDataUrlNavigations(
request.OriginDocument()->Url()) &&
(url.ProtocolIs("filesystem") ||
@@ -734,144 +706,60 @@ bool FrameLoader::PrepareRequestForThisFrame(FrameLoadRequest& request) {
return true;
}
-static bool ShouldNavigateTargetFrame(NavigationPolicy policy) {
- switch (policy) {
- case kNavigationPolicyCurrentTab:
- return true;
-
- // Navigation will target a *new* frame (e.g. because of a ctrl-click),
- // so the target frame can be ignored.
- case kNavigationPolicyNewBackgroundTab:
- case kNavigationPolicyNewForegroundTab:
- case kNavigationPolicyNewWindow:
- case kNavigationPolicyNewPopup:
- return false;
-
- // Navigation won't really target any specific frame,
- // so the target frame can be ignored.
- case kNavigationPolicyIgnore:
- case kNavigationPolicyDownload:
- return false;
-
- case kNavigationPolicyHandledByClient:
- // Impossible, because at this point we shouldn't yet have called
- // client()->decidePolicyForNavigation(...).
- NOTREACHED();
- return true;
-
- default:
- NOTREACHED() << policy;
- return true;
- }
-}
-
-static NavigationType DetermineNavigationType(FrameLoadType frame_load_type,
- bool is_form_submission,
- bool have_event) {
+static WebNavigationType DetermineNavigationType(
+ WebFrameLoadType frame_load_type,
+ bool is_form_submission,
+ bool have_event) {
bool is_reload = IsReloadLoadType(frame_load_type);
bool is_back_forward = IsBackForwardLoadType(frame_load_type);
if (is_form_submission) {
- return (is_reload || is_back_forward) ? kNavigationTypeFormResubmitted
- : kNavigationTypeFormSubmitted;
+ return (is_reload || is_back_forward) ? kWebNavigationTypeFormResubmitted
+ : kWebNavigationTypeFormSubmitted;
}
if (have_event)
- return kNavigationTypeLinkClicked;
+ return kWebNavigationTypeLinkClicked;
if (is_reload)
- return kNavigationTypeReload;
+ return kWebNavigationTypeReload;
if (is_back_forward)
- return kNavigationTypeBackForward;
- return kNavigationTypeOther;
+ return kWebNavigationTypeBackForward;
+ return kWebNavigationTypeOther;
}
static WebURLRequest::RequestContext DetermineRequestContextFromNavigationType(
- const NavigationType navigation_type) {
+ const WebNavigationType navigation_type) {
switch (navigation_type) {
- case kNavigationTypeLinkClicked:
+ case kWebNavigationTypeLinkClicked:
return WebURLRequest::kRequestContextHyperlink;
- case kNavigationTypeOther:
+ case kWebNavigationTypeOther:
return WebURLRequest::kRequestContextLocation;
- case kNavigationTypeFormResubmitted:
- case kNavigationTypeFormSubmitted:
+ case kWebNavigationTypeFormResubmitted:
+ case kWebNavigationTypeFormSubmitted:
return WebURLRequest::kRequestContextForm;
- case kNavigationTypeBackForward:
- case kNavigationTypeReload:
+ case kWebNavigationTypeBackForward:
+ case kWebNavigationTypeReload:
return WebURLRequest::kRequestContextInternal;
}
NOTREACHED();
return WebURLRequest::kRequestContextHyperlink;
}
-static NavigationPolicy NavigationPolicyForRequest(
- const FrameLoadRequest& request) {
- NavigationPolicy policy = kNavigationPolicyCurrentTab;
- Event* event = request.TriggeringEvent();
- if (!event)
- return policy;
-
- if (request.Form() && event->UnderlyingEvent())
- event = event->UnderlyingEvent();
-
- if (event->IsMouseEvent()) {
- MouseEvent* mouse_event = ToMouseEvent(event);
- NavigationPolicyFromMouseEvent(
- mouse_event->button(), mouse_event->ctrlKey(), mouse_event->shiftKey(),
- mouse_event->altKey(), mouse_event->metaKey(), &policy);
- } else if (event->IsKeyboardEvent()) {
- // The click is simulated when triggering the keypress event.
- KeyboardEvent* key_event = ToKeyboardEvent(event);
- NavigationPolicyFromMouseEvent(0, key_event->ctrlKey(),
- key_event->shiftKey(), key_event->altKey(),
- key_event->metaKey(), &policy);
- } else if (event->IsGestureEvent()) {
- // The click is simulated when triggering the gesture-tap event
- GestureEvent* gesture_event = ToGestureEvent(event);
- NavigationPolicyFromMouseEvent(
- 0, gesture_event->ctrlKey(), gesture_event->shiftKey(),
- gesture_event->altKey(), gesture_event->metaKey(), &policy);
- }
- return policy;
-}
-
void FrameLoader::StartNavigation(const FrameLoadRequest& passed_request,
- FrameLoadType frame_load_type,
- HistoryItem* history_item,
- HistoryLoadType history_load_type) {
+ WebFrameLoadType frame_load_type,
+ NavigationPolicy policy) {
CHECK(!passed_request.GetSubstituteData().IsValid());
- CHECK(frame_load_type != kFrameLoadTypeBackForward);
- CHECK(!history_item);
- CHECK(history_load_type == kHistoryDifferentDocumentLoad);
- return LoadInternal(passed_request, frame_load_type, history_item,
- history_load_type, true /* check_with_client */);
-}
-
-void FrameLoader::CommitNavigation(const FrameLoadRequest& passed_request,
- FrameLoadType frame_load_type,
- HistoryItem* history_item,
- HistoryLoadType history_load_type) {
- CHECK(!passed_request.OriginDocument());
- CHECK(passed_request.FrameName().IsEmpty());
- CHECK(!passed_request.TriggeringEvent());
- CHECK(!passed_request.Form());
- return LoadInternal(passed_request, frame_load_type, history_item,
- history_load_type, false /* check_with_client */);
-}
+ CHECK(!IsBackForwardLoadType(frame_load_type));
+ DCHECK(passed_request.TriggeringEventInfo() !=
+ WebTriggeringEventInfo::kUnknown);
+ DCHECK(policy != kNavigationPolicyHandledByClient &&
+ policy != kNavigationPolicyHandledByClientForInitialHistory);
-void FrameLoader::LoadInternal(const FrameLoadRequest& passed_request,
- FrameLoadType frame_load_type,
- HistoryItem* history_item,
- HistoryLoadType history_load_type,
- bool check_with_client) {
DCHECK(frame_->GetDocument());
-
if (HTMLFrameOwnerElement* element = frame_->DeprecatedLocalOwner())
element->CancelPendingLazyLoad();
- if (IsBackForwardLoadType(frame_load_type) && !frame_->IsNavigationAllowed())
- return;
-
if (in_stop_all_loaders_)
return;
@@ -890,9 +778,11 @@ void FrameLoader::LoadInternal(const FrameLoadRequest& passed_request,
AtomicString(request.FrameName()), *frame_,
request.GetResourceRequest().Url());
- NavigationPolicy policy = NavigationPolicyForRequest(request);
- if (target_frame && target_frame != frame_ &&
- ShouldNavigateTargetFrame(policy)) {
+ // Downloads and navigations which specifically target a *new* frame
+ // (e.g. because of a ctrl-click) should ignore the target.
+ bool should_navigate_target_frame = policy == kNavigationPolicyCurrentTab;
+
+ if (target_frame && target_frame != frame_ && should_navigate_target_frame) {
if (target_frame->IsLocalFrame() &&
!ToLocalFrame(target_frame)->IsNavigationAllowed()) {
return;
@@ -912,60 +802,115 @@ void FrameLoader::LoadInternal(const FrameLoadRequest& passed_request,
if (!target_frame && !request.FrameName().IsEmpty()) {
if (policy == kNavigationPolicyDownload) {
- Client()->DownloadURL(request.GetResourceRequest());
+ Client()->DownloadURL(request.GetResourceRequest(),
+ DownloadCrossOriginRedirects::kFollow);
return; // Navigation/download will be handled by the client.
- } else if (ShouldNavigateTargetFrame(policy)) {
+ } else if (should_navigate_target_frame) {
request.GetResourceRequest().SetFrameType(
network::mojom::RequestContextFrameType::kAuxiliary);
- CreateWindowForRequest(request, *frame_, policy);
+ CreateWindowForRequest(request, *frame_);
return; // Navigation will be handled by the new frame/window.
}
}
- if (!frame_->IsNavigationAllowed())
+ // TODO(dgozman): merge page dismissal check and FrameNavigationDisabler.
+ if (!frame_->IsNavigationAllowed() ||
+ frame_->GetDocument()->PageDismissalEventBeingDispatched() !=
+ Document::kNoDismissal) {
return;
+ }
const KURL& url = request.GetResourceRequest().Url();
- FrameLoadType new_load_type = (frame_load_type == kFrameLoadTypeStandard)
- ? DetermineFrameLoadType(request)
- : frame_load_type;
+ if (frame_load_type == WebFrameLoadType::kStandard)
+ frame_load_type = DetermineFrameLoadType(request);
- bool same_document_history_navigation =
- IsBackForwardLoadType(new_load_type) &&
- history_load_type == kHistorySameDocumentLoad;
bool same_document_navigation =
policy == kNavigationPolicyCurrentTab &&
ShouldPerformFragmentNavigation(request.Form(),
request.GetResourceRequest().HttpMethod(),
- new_load_type, url);
+ frame_load_type, url);
// Perform same document navigation.
- if (same_document_history_navigation || same_document_navigation) {
+ if (same_document_navigation) {
CommitSameDocumentNavigation(
- request.GetResourceRequest().Url(), new_load_type, history_item,
+ request.GetResourceRequest().Url(), frame_load_type, nullptr,
request.ClientRedirect(), request.OriginDocument(),
- request.TriggeringEvent());
+ request.TriggeringEventInfo() != WebTriggeringEventInfo::kNotFromEvent);
return;
}
- // PlzNavigate
- // If the loader classifies this navigation as a different document navigation
- // while the browser intended the navigation to be same-document, it means
- // that a different navigation must have committed while the IPC was sent.
- // This navigation is no more same-document. The navigation is simply dropped.
- if (request.GetResourceRequest().IsSameDocumentNavigation())
+ StartLoad(request, frame_load_type, policy, nullptr,
+ true /* check_with_client */, nullptr /* extra_data */,
+ WebNavigationTimings());
+
+ // TODO(csharrison): In M70 when UserActivation v2 should ship, we can remove
+ // the check that the pages are equal, because consumption should not be
+ // shared across pages.
+ const Document* origin_document = request.OriginDocument();
+ if (frame_->IsMainFrame() && origin_document &&
+ frame_->GetPage() == origin_document->GetPage()) {
+ Frame::ConsumeTransientUserActivation(frame_);
+ }
+}
+
+void FrameLoader::CommitNavigation(
+ const FrameLoadRequest& passed_request,
+ WebFrameLoadType frame_load_type,
+ HistoryItem* history_item,
+ std::unique_ptr<WebDocumentLoader::ExtraData> extra_data,
+ const WebNavigationTimings& navigation_timings) {
+ CHECK(!passed_request.OriginDocument());
+ CHECK(passed_request.FrameName().IsEmpty());
+ CHECK(!passed_request.Form());
+ CHECK(passed_request.TriggeringEventInfo() ==
+ WebTriggeringEventInfo::kNotFromEvent);
+ DCHECK(frame_->GetDocument());
+
+ if (in_stop_all_loaders_ || !frame_->IsNavigationAllowed() ||
+ frame_->GetDocument()->PageDismissalEventBeingDispatched() !=
+ Document::kNoDismissal) {
+ // Any of the checks above should not be necessary.
+ // Unfortunately, in the case of sync IPCs like print() there might be
+ // reentrancy and, for example, frame detach happening.
+ // See fast/loader/detach-while-printing.html for a repro.
+ // TODO(https://crbug.com/862088): we should probably ignore print()
+ // call in this case instead.
return;
+ }
+
+ // TODO(dgozman): figure out the better place for this check
+ // to cancel lazy load both on start and commit. Perhaps
+ // CreateDocumentLoader() is a good one.
+ if (HTMLFrameOwnerElement* element = frame_->DeprecatedLocalOwner())
+ element->CancelPendingLazyLoad();
+
+ FrameLoadRequest request(passed_request);
+ request.GetResourceRequest().SetHasUserGesture(
+ Frame::HasTransientUserActivation(frame_));
+
+ if (frame_load_type == WebFrameLoadType::kStandard)
+ frame_load_type = DetermineFrameLoadType(request);
- StartLoad(request, new_load_type, policy, history_item, check_with_client);
+ // Note: we might actually classify this navigation as same document
+ // right here in the following circumstances:
+ // - the loader has already committed a navigation and notified the browser
+ // process which did not receive a message about that just yet;
+ // - meanwhile, the browser process sent us a command to commit this new
+ // "cross-document" navigation, while it's actually same-document
+ // with regards to the last commit.
+ // In this rare case, we intentionally proceed as cross-document.
+ StartLoad(request, frame_load_type, kNavigationPolicyCurrentTab, history_item,
+ false /* check_with_client */, std::move(extra_data),
+ navigation_timings);
}
mojom::CommitResult FrameLoader::CommitSameDocumentNavigation(
const KURL& url,
- FrameLoadType frame_load_type,
+ WebFrameLoadType frame_load_type,
HistoryItem* history_item,
ClientRedirectPolicy client_redirect_policy,
Document* origin_document,
- Event* triggering_event) {
+ bool has_event) {
DCHECK(!IsReloadLoadType(frame_load_type));
DCHECK(frame_->GetDocument());
@@ -994,9 +939,9 @@ mojom::CommitResult FrameLoader::CommitSameDocumentNavigation(
if (!history_navigation) {
document_loader_->SetNavigationType(
- DetermineNavigationType(frame_load_type, false, triggering_event));
+ DetermineNavigationType(frame_load_type, false, has_event));
if (ShouldTreatURLAsSameAsCurrent(url))
- frame_load_type = kFrameLoadTypeReplaceCurrentItem;
+ frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
}
// Perform the same-document navigation.
@@ -1103,6 +1048,14 @@ bool FrameLoader::PrepareForCommit() {
if (!frame_->Client())
return false;
DCHECK_EQ(provisional_document_loader_, pdl);
+
+ // Flush microtask queue so that they all run on pre-navigation context.
+ Microtask::PerformCheckpoint(V8PerIsolateData::MainThreadIsolate());
+
+ // Ensure that the frame_ hasn't detached from running the microtasks.
+ if (!frame_->Client())
+ return false;
+
// No more events will be dispatched so detach the Document.
// TODO(yoav): Should we also be nullifying domWindow's document (or
// domWindow) since the doc is now detached?
@@ -1133,22 +1086,6 @@ void FrameLoader::CommitProvisionalLoad() {
if (!PrepareForCommit())
return;
- // If we are loading a local root, it is important to explicitly set the event
- // listener properties to Nothing as this triggers notifications to the
- // client. Clients may assume the presence of handlers for touch and wheel
- // events, so these notifications tell it there are (presently) no handlers.
- if (frame_->IsLocalRoot()) {
- frame_->GetPage()->GetChromeClient().SetEventListenerProperties(
- frame_, WebEventListenerClass::kTouchStartOrMove,
- WebEventListenerProperties::kNothing);
- frame_->GetPage()->GetChromeClient().SetEventListenerProperties(
- frame_, WebEventListenerClass::kMouseWheel,
- WebEventListenerProperties::kNothing);
- frame_->GetPage()->GetChromeClient().SetEventListenerProperties(
- frame_, WebEventListenerClass::kTouchEndOrCancel,
- WebEventListenerProperties::kNothing);
- }
-
Client()->TransitionToCommittedForNewPage();
frame_->GetNavigationScheduler().Cancel();
@@ -1165,18 +1102,18 @@ void FrameLoader::RestoreScrollPositionAndViewState() {
}
base::AutoReset<bool> in_restore_scroll(&in_restore_scroll_, true);
RestoreScrollPositionAndViewState(
- GetDocumentLoader()->LoadType(), kHistoryDifferentDocumentLoad,
+ GetDocumentLoader()->LoadType(), false /* is_same_document */,
GetDocumentLoader()->GetHistoryItem()->GetViewState(),
GetDocumentLoader()->GetHistoryItem()->ScrollRestorationType());
}
void FrameLoader::RestoreScrollPositionAndViewState(
- FrameLoadType load_type,
- HistoryLoadType history_load_type,
+ WebFrameLoadType load_type,
+ bool is_same_document,
HistoryItem::ViewState* view_state,
HistoryScrollRestorationType scroll_restoration_type) {
LocalFrameView* view = frame_->View();
- if (!view || !view->LayoutViewportScrollableArea() ||
+ if (!view || !view->LayoutViewport() ||
!state_machine_.CommittedFirstRealDocumentLoad() ||
!frame_->IsAttached()) {
return;
@@ -1198,11 +1135,10 @@ void FrameLoader::RestoreScrollPositionAndViewState(
// is complete, or if the navigation is same-document (as the new page may
// be smaller than the previous page).
bool can_restore_without_clamping =
- view->LayoutViewportScrollableArea()->ClampScrollOffset(
- view_state->scroll_offset_) == view_state->scroll_offset_;
+ view->LayoutViewport()->ClampScrollOffset(view_state->scroll_offset_) ==
+ view_state->scroll_offset_;
- bool should_force_clamping =
- !frame_->IsLoading() || history_load_type == kHistorySameDocumentLoad;
+ bool should_force_clamping = !frame_->IsLoading() || is_same_document;
// Here |can_restore_without_clamping| is false, but layout might be necessary
// to ensure correct content size.
if (!can_restore_without_clamping && should_force_clamping)
@@ -1216,25 +1152,24 @@ void FrameLoader::RestoreScrollPositionAndViewState(
return;
if (should_restore_scroll) {
- ScrollOffset previous_offset =
- view->LayoutViewportScrollableArea()->GetScrollOffset();
+ ScrollOffset previous_offset = view->LayoutViewport()->GetScrollOffset();
// TODO(pnoland): attempt to restore the anchor in more places than this.
// Anchor-based restore should allow for earlier restoration.
bool did_restore =
ShouldSerializeScrollAnchor() &&
- view->LayoutViewportScrollableArea()->RestoreScrollAnchor(
+ view->LayoutViewport()->RestoreScrollAnchor(
{view_state->scroll_anchor_data_.selector_,
LayoutPoint(view_state->scroll_anchor_data_.offset_.x,
view_state->scroll_anchor_data_.offset_.y),
view_state->scroll_anchor_data_.simhash_});
if (!did_restore) {
- view->LayoutViewportScrollableArea()->SetScrollOffset(
- view_state->scroll_offset_, kProgrammaticScroll);
+ view->LayoutViewport()->SetScrollOffset(view_state->scroll_offset_,
+ kProgrammaticScroll);
}
- did_restore |= (previous_offset !=
- view->LayoutViewportScrollableArea()->GetScrollOffset());
+ did_restore |=
+ (previous_offset != view->LayoutViewport()->GetScrollOffset());
// Measure how many successful scroll restoration may impacted if we allow
// using js scroll to prevent browser scroll restoration.
@@ -1255,9 +1190,8 @@ void FrameLoader::RestoreScrollPositionAndViewState(
// the main frame and the visual viewport as best as we can.
if (visual_viewport_offset.Width() == -1 &&
visual_viewport_offset.Height() == -1) {
- visual_viewport_offset =
- view_state->scroll_offset_ -
- view->LayoutViewportScrollableArea()->GetScrollOffset();
+ visual_viewport_offset = view_state->scroll_offset_ -
+ view->LayoutViewport()->GetScrollOffset();
}
VisualViewport& visual_viewport = frame_->GetPage()->GetVisualViewport();
@@ -1305,14 +1239,14 @@ void FrameLoader::DetachProvisionalDocumentLoader(DocumentLoader* loader) {
bool FrameLoader::ShouldPerformFragmentNavigation(bool is_form_submission,
const String& http_method,
- FrameLoadType load_type,
+ WebFrameLoadType load_type,
const KURL& url) {
// We don't do this if we are submitting a form with method other than "GET",
// explicitly reloading, currently displaying a frameset, or if the URL does
// not have a fragment.
return DeprecatedEqualIgnoringCase(http_method, HTTPNames::GET) &&
!IsReloadLoadType(load_type) &&
- load_type != kFrameLoadTypeBackForward &&
+ load_type != WebFrameLoadType::kBackForward &&
url.HasFragmentIdentifier() &&
// For provisional LocalFrame, there is no real document loaded and
// the initial empty document should not be considered, so there is
@@ -1325,7 +1259,7 @@ bool FrameLoader::ShouldPerformFragmentNavigation(bool is_form_submission,
}
void FrameLoader::ProcessFragment(const KURL& url,
- FrameLoadType frame_load_type,
+ WebFrameLoadType frame_load_type,
LoadStartType load_start_type) {
LocalFrameView* view = frame_->View();
if (!view)
@@ -1411,16 +1345,16 @@ NavigationPolicy FrameLoader::ShouldContinueForNavigationPolicy(
DocumentLoader* loader,
ContentSecurityPolicyDisposition
should_check_main_world_content_security_policy,
- NavigationType type,
+ WebNavigationType type,
NavigationPolicy policy,
- FrameLoadType frame_load_type,
+ WebFrameLoadType frame_load_type,
bool is_client_redirect,
WebTriggeringEventInfo triggering_event_info,
HTMLFormElement* form,
mojom::blink::BlobURLTokenPtr blob_url_token,
bool check_with_client) {
- // Don't ask if we are loading an empty URL.
- if (request.Url().IsEmpty() || substitute_data.IsValid())
+ // Don't ask if we already have the data.
+ if (substitute_data.IsValid())
return kNavigationPolicyCurrentTab;
// Check for non-escaped new lines in the url.
@@ -1432,23 +1366,18 @@ NavigationPolicy FrameLoader::ShouldContinueForNavigationPolicy(
return kNavigationPolicyIgnore;
}
- if (MaybeCheckCSP(request, type, frame_, policy,
- should_check_main_world_content_security_policy ==
- kCheckContentSecurityPolicy,
- ContentSecurityPolicy::CheckHeaderType::kCheckEnforce) ==
- kNavigationPolicyIgnore) {
- return kNavigationPolicyIgnore;
+ if (!check_with_client) {
+ DCHECK_EQ(kNavigationPolicyCurrentTab, policy);
+ return policy;
}
bool replaces_current_history_item =
- frame_load_type == kFrameLoadTypeReplaceCurrentItem;
+ frame_load_type == WebFrameLoadType::kReplaceCurrentItem;
policy = Client()->DecidePolicyForNavigation(
request, origin_document, loader, type, policy,
replaces_current_history_item, is_client_redirect, triggering_event_info,
form, should_check_main_world_content_security_policy,
std::move(blob_url_token));
- if (!check_with_client)
- CHECK_EQ(kNavigationPolicyCurrentTab, policy);
DCHECK(policy == kNavigationPolicyCurrentTab ||
policy == kNavigationPolicyIgnore ||
policy == kNavigationPolicyHandledByClient ||
@@ -1457,102 +1386,45 @@ NavigationPolicy FrameLoader::ShouldContinueForNavigationPolicy(
return policy;
}
-NavigationPolicy FrameLoader::ShouldContinueForRedirectNavigationPolicy(
- const ResourceRequest& request,
- const SubstituteData& substitute_data,
- DocumentLoader* loader,
- ContentSecurityPolicyDisposition
- should_check_main_world_content_security_policy,
- NavigationType type,
- NavigationPolicy policy,
- FrameLoadType frame_load_type,
- bool is_client_redirect,
- HTMLFormElement* form) {
- // Check report-only CSP policies, which are not checked by
- // ShouldContinueForNavigationPolicy.
- MaybeCheckCSP(request, type, frame_, policy,
- should_check_main_world_content_security_policy ==
- kCheckContentSecurityPolicy,
- ContentSecurityPolicy::CheckHeaderType::kCheckReportOnly);
-
- return ShouldContinueForNavigationPolicy(
- request,
- // |origin_document| is not set. It doesn't really matter here. It is
- // useful for PlzNavigate (aka browser-side-navigation). It is used
- // during the first navigation and not during redirects.
- nullptr, // origin_document
- substitute_data, loader, should_check_main_world_content_security_policy,
- type, policy, frame_load_type, is_client_redirect,
- WebTriggeringEventInfo::kNotFromEvent, form, nullptr /* blob_url_token */,
- true /* check_with_client */);
-}
-
void FrameLoader::ClientDroppedNavigation() {
if (!provisional_document_loader_ || provisional_document_loader_->DidStart())
return;
DetachProvisionalDocumentLoader(provisional_document_loader_);
+ // Forcibly instantiate WindowProxy for initial frame document.
+ // This is only required when frame navigation is aborted, e.g. due to
+ // mixed content.
+ // TODO(lushnikov): this should be done in Init for initial empty doc, but
+ // that breaks extensions abusing SetForceMainWorldInitialization setting
+ // and relying on the number of created window proxies.
+ Settings* settings = frame_->GetSettings();
+ if (settings && settings->GetForceMainWorldInitialization()) {
+ // Forcibly instantiate WindowProxy.
+ frame_->GetScriptController().WindowProxy(DOMWrapperWorld::MainWorld());
+ }
}
-NavigationPolicy FrameLoader::CheckLoadCanStart(
+void FrameLoader::StartLoad(
FrameLoadRequest& frame_load_request,
- FrameLoadType type,
+ WebFrameLoadType type,
NavigationPolicy navigation_policy,
- NavigationType navigation_type,
- bool check_with_client) {
- if (frame_->GetDocument()->PageDismissalEventBeingDispatched() !=
- Document::kNoDismissal) {
- return kNavigationPolicyIgnore;
- }
-
- // Record the latest requiredCSP value that will be used when sending this
- // request.
- ResourceRequest& resource_request = frame_load_request.GetResourceRequest();
- RecordLatestRequiredCSP();
- // Before modifying the request, check report-only CSP headers to give the
- // site owner a chance to learn about requests that need to be modified.
- MaybeCheckCSP(
- resource_request, navigation_type, frame_, navigation_policy,
- frame_load_request.ShouldCheckMainWorldContentSecurityPolicy() ==
- kCheckContentSecurityPolicy,
- ContentSecurityPolicy::CheckHeaderType::kCheckReportOnly);
- ModifyRequestForCSP(resource_request, frame_load_request.OriginDocument());
-
- WebTriggeringEventInfo triggering_event_info =
- WebTriggeringEventInfo::kNotFromEvent;
- if (frame_load_request.TriggeringEvent()) {
- triggering_event_info = frame_load_request.TriggeringEvent()->isTrusted()
- ? WebTriggeringEventInfo::kFromTrustedEvent
- : WebTriggeringEventInfo::kFromUntrustedEvent;
- }
- return ShouldContinueForNavigationPolicy(
- resource_request, frame_load_request.OriginDocument(),
- frame_load_request.GetSubstituteData(), nullptr,
- frame_load_request.ShouldCheckMainWorldContentSecurityPolicy(),
- navigation_type, navigation_policy, type,
- frame_load_request.ClientRedirect() ==
- ClientRedirectPolicy::kClientRedirect,
- triggering_event_info, frame_load_request.Form(),
- frame_load_request.GetBlobURLToken(), check_with_client);
-}
-
-void FrameLoader::StartLoad(FrameLoadRequest& frame_load_request,
- FrameLoadType type,
- NavigationPolicy navigation_policy,
- HistoryItem* history_item,
- bool check_with_client) {
+ HistoryItem* history_item,
+ bool check_with_client,
+ std::unique_ptr<WebDocumentLoader::ExtraData> extra_data,
+ const WebNavigationTimings& navigation_timings) {
DCHECK(Client()->HasWebView());
ResourceRequest& resource_request = frame_load_request.GetResourceRequest();
- NavigationType navigation_type = DetermineNavigationType(
+ WebNavigationType navigation_type = DetermineNavigationType(
type, resource_request.HttpBody() || frame_load_request.Form(),
- frame_load_request.TriggeringEvent());
+ frame_load_request.TriggeringEventInfo() !=
+ WebTriggeringEventInfo::kNotFromEvent);
resource_request.SetRequestContext(
DetermineRequestContextFromNavigationType(navigation_type));
resource_request.SetFrameType(
frame_->IsMainFrame() ? network::mojom::RequestContextFrameType::kTopLevel
: network::mojom::RequestContextFrameType::kNested);
- Document* origin_document = frame_load_request.OriginDocument();
+ Document* origin_document = frame_load_request.OriginDocument();
if (origin_document && origin_document->GetContentSecurityPolicy()
->ExperimentalFeaturesEnabled()) {
WebContentSecurityPolicyList initiator_csp =
@@ -1561,60 +1433,53 @@ void FrameLoader::StartLoad(FrameLoadRequest& frame_load_request,
resource_request.SetInitiatorCSP(initiator_csp);
}
- bool had_placeholder_client_document_loader =
- provisional_document_loader_ && !provisional_document_loader_->DidStart();
- navigation_policy =
- CheckLoadCanStart(frame_load_request, type, navigation_policy,
- navigation_type, check_with_client);
- if (navigation_policy == kNavigationPolicyIgnore) {
- if (had_placeholder_client_document_loader &&
- !resource_request.CheckForBrowserSideNavigation()) {
- DetachDocumentLoader(provisional_document_loader_);
- }
- return;
- }
+ // Record the latest requiredCSP value that will be used when sending this
+ // request.
+ RecordLatestRequiredCSP();
- // For PlzNavigate placeholder DocumentLoaders, don't send failure callbacks
- // for a placeholder simply being replaced with a new DocumentLoader.
- if (had_placeholder_client_document_loader)
- provisional_document_loader_->SetSentDidFinishLoad();
- frame_->GetDocument()->CancelParsing();
+ // TODO(arthursonzogni): 'frame-src' check is disabled on the
+ // renderer side, but is enforced on the browser side.
+ // See http://crbug.com/692595 for understanding why it
+ // can't be enforced on both sides instead.
- // If we're starting a regular navigation on a regular document (i.e., there
- // was no placeholder DocumentLoader), it's not enough to cancel parsing, but
- // we also have to check whether the document was completed, so it's in a
- // defined state should the navigation fail.
- if (!had_placeholder_client_document_loader &&
- type == kFrameLoadTypeStandard &&
- (navigation_policy == kNavigationPolicyCurrentTab ||
- navigation_policy == kNavigationPolicyHandledByClient)) {
- frame_->GetDocument()->CheckCompleted();
- }
- DetachDocumentLoader(provisional_document_loader_);
+ // 'form-action' check in the frame that is navigating is disabled on the
+ // renderer side, but is enforced on the browser side instead.
+ // N.B. check in the frame that initiates the navigation stills occurs in
+ // blink and is not enforced on the browser-side.
+ // TODO(arthursonzogni) The 'form-action' check should be fully disabled
+ // in blink, except when the form submission doesn't trigger a navigation
+ // (i.e. javascript urls). Please see https://crbug.com/701749.
+
+ // Report-only CSP headers are checked in browser.
+ ModifyRequestForCSP(resource_request, origin_document);
+
+ navigation_policy = ShouldContinueForNavigationPolicy(
+ resource_request, origin_document, frame_load_request.GetSubstituteData(),
+ nullptr, frame_load_request.ShouldCheckMainWorldContentSecurityPolicy(),
+ navigation_type, navigation_policy, type,
+ frame_load_request.ClientRedirect() ==
+ ClientRedirectPolicy::kClientRedirect,
+ frame_load_request.TriggeringEventInfo(), frame_load_request.Form(),
+ frame_load_request.GetBlobURLToken(), check_with_client);
- // beforeunload fired above, and detaching a DocumentLoader can fire events,
- // which can detach this frame.
+ // 'beforeunload' can be fired above, which can detach this frame from inside
+ // the event handler.
if (!frame_->GetPage())
return;
- progress_tracker_->ProgressStarted(type);
- // TODO(japhet): This case wants to flag the frame as loading and do nothing
- // else. It'd be nice if it could go through the placeholder DocumentLoader
- // path, too.
- if (navigation_policy == kNavigationPolicyHandledByClientForInitialHistory)
+ if (navigation_policy == kNavigationPolicyIgnore) {
+ // This could only happen from StartNavigation, which must not clear
+ // CheckForBrowserSideNavigation bit.
+ CHECK(resource_request.CheckForBrowserSideNavigation());
return;
- DCHECK(navigation_policy == kNavigationPolicyCurrentTab ||
- navigation_policy == kNavigationPolicyHandledByClient);
+ }
- provisional_document_loader_ = CreateDocumentLoader(
- resource_request, frame_load_request, type, navigation_type);
+ if (!CancelProvisionalLoaderForNewNavigation(navigation_policy))
+ return;
- // PlzNavigate: We need to ensure that script initiated navigations are
- // honored.
- if (!had_placeholder_client_document_loader ||
- navigation_policy == kNavigationPolicyHandledByClient) {
- frame_->GetNavigationScheduler().Cancel();
- }
+ provisional_document_loader_ = CreateDocumentLoader(
+ resource_request, frame_load_request, type, navigation_type,
+ std::move(extra_data), navigation_timings);
if (frame_load_request.Form())
Client()->DispatchWillSubmitForm(frame_load_request.Form());
@@ -1627,7 +1492,6 @@ void FrameLoader::StartLoad(FrameLoadRequest& frame_load_request,
provisional_document_loader_->SetItemForHistoryNavigation(history_item);
}
- DCHECK(!frame_load_request.GetResourceRequest().IsSameDocumentNavigation());
frame_->GetFrameScheduler()->DidStartProvisionalLoad(frame_->IsMainFrame());
// TODO(ananta):
@@ -1650,6 +1514,51 @@ void FrameLoader::StartLoad(FrameLoadRequest& frame_load_request,
TakeObjectSnapshot();
}
+bool FrameLoader::CancelProvisionalLoaderForNewNavigation(
+ NavigationPolicy navigation_policy) {
+ bool had_placeholder_client_document_loader =
+ provisional_document_loader_ && !provisional_document_loader_->DidStart();
+
+ // For placeholder DocumentLoaders, don't send failure callbacks
+ // for a placeholder simply being replaced with a new DocumentLoader.
+ if (had_placeholder_client_document_loader)
+ provisional_document_loader_->SetSentDidFinishLoad();
+
+ // This seems to correspond to step 9 of the specification:
+ // "9. Abort the active document of browsingContext."
+ // https://html.spec.whatwg.org/#navigate
+ frame_->GetDocument()->Abort();
+ // document.onreadystatechange can fire in Abort(), which can:
+ // 1) Detach this frame.
+ // 2) Stop the provisional DocumentLoader (i.e window.stop()).
+ if (!frame_->GetPage())
+ return false;
+
+ DetachDocumentLoader(provisional_document_loader_);
+ // Detaching the provisional DocumentLoader above may leave the frame without
+ // any loading DocumentLoader. It can causes the 'load' event to fire, which
+ // can be used to detach this frame.
+ if (!frame_->GetPage())
+ return false;
+
+ progress_tracker_->ProgressStarted();
+ // TODO(japhet): This case wants to flag the frame as loading and do nothing
+ // else. It'd be nice if it could go through the placeholder DocumentLoader
+ // path, too.
+ if (navigation_policy == kNavigationPolicyHandledByClientForInitialHistory)
+ return false;
+ DCHECK(navigation_policy == kNavigationPolicyCurrentTab ||
+ navigation_policy == kNavigationPolicyHandledByClient);
+
+ // We need to ensure that script initiated navigations are honored.
+ if (!had_placeholder_client_document_loader ||
+ navigation_policy == kNavigationPolicyHandledByClient) {
+ frame_->GetNavigationScheduler().Cancel();
+ }
+
+ return true;
+}
+
bool FrameLoader::ShouldTreatURLAsSameAsCurrent(const KURL& url) const {
return document_loader_->GetHistoryItem() &&
url == document_loader_->GetHistoryItem()->Url();
@@ -1767,22 +1676,23 @@ void FrameLoader::ModifyRequestForCSP(ResourceRequest& resource_request,
// static
void FrameLoader::UpgradeInsecureRequest(ResourceRequest& resource_request,
- Document* origin_document) {
+ ExecutionContext* origin_context) {
// We always upgrade requests that meet any of the following criteria:
// 1. Are for subresources.
// 2. Are for nested frames.
// 3. Are form submissions.
- // 4. Whose hosts are contained in the origin_document's upgrade insecure
+ // 4. Whose hosts are contained in the origin_context's upgrade insecure
// navigations set.
// This happens for:
// * Browser initiated main document loading. No upgrade required.
// * Navigation initiated by a frame in another process. URL should have
// already been upgraded in the initiator's process.
- if (!origin_document)
+ if (!origin_context)
return;
- if (!(origin_document->GetInsecureRequestPolicy() & kUpgradeInsecureRequests))
+ if (!(origin_context->GetSecurityContext().GetInsecureRequestPolicy() &
+ kUpgradeInsecureRequests))
return;
// Nested frames are always upgraded on the browser process.
@@ -1791,6 +1701,11 @@ void FrameLoader::UpgradeInsecureRequest(ResourceRequest& resource_request,
return;
}
+ // We set the UpgradeIfInsecure flag even if the current request wasn't
+ // upgraded (due to already being HTTPS), since we still need to upgrade
+ // redirects if they are not to HTTPS URLs.
+ resource_request.SetUpgradeIfInsecure(true);
+
KURL url = resource_request.Url();
if (!url.ProtocolIs("http"))
return;
@@ -1799,10 +1714,10 @@ void FrameLoader::UpgradeInsecureRequest(ResourceRequest& resource_request,
network::mojom::RequestContextFrameType::kNone ||
resource_request.GetRequestContext() ==
WebURLRequest::kRequestContextForm ||
- (!url.Host().IsNull() &&
- origin_document->InsecureNavigationsToUpgrade()->Contains(
- url.Host().Impl()->GetHash()))) {
- UseCounter::Count(origin_document,
+ (!url.Host().IsNull() && origin_context->GetSecurityContext()
+ .InsecureNavigationsToUpgrade()
+ ->Contains(url.Host().Impl()->GetHash()))) {
+ UseCounter::Count(origin_context,
WebFeature::kUpgradeInsecureRequestsUpgradedRequest);
url.SetProtocol("https");
if (url.Port() == 80)
@@ -1845,47 +1760,35 @@ inline void FrameLoader::TakeObjectSnapshot() const {
DocumentLoader* FrameLoader::CreateDocumentLoader(
const ResourceRequest& request,
const FrameLoadRequest& frame_load_request,
- FrameLoadType load_type,
- NavigationType navigation_type) {
+ WebFrameLoadType load_type,
+ WebNavigationType navigation_type,
+ std::unique_ptr<WebDocumentLoader::ExtraData> extra_data,
+ const WebNavigationTimings& navigation_timings) {
DocumentLoader* loader = Client()->CreateDocumentLoader(
frame_, request,
frame_load_request.GetSubstituteData().IsValid()
? frame_load_request.GetSubstituteData()
: DefaultSubstituteDataForURL(request.Url()),
frame_load_request.ClientRedirect(),
- frame_load_request.GetDevToolsNavigationToken());
+ frame_load_request.GetDevToolsNavigationToken(), std::move(extra_data),
+ navigation_timings);
loader->SetLoadType(load_type);
loader->SetNavigationType(navigation_type);
// TODO(japhet): This is needed because the browser process DCHECKs if the
// first entry we commit in a new frame has replacement set. It's unclear
// whether the DCHECK is right, investigate removing this special case.
- bool replace_current_item = load_type == kFrameLoadTypeReplaceCurrentItem &&
- (!Opener() || !request.Url().IsEmpty());
+ bool replace_current_item =
+ load_type == WebFrameLoadType::kReplaceCurrentItem &&
+ (!Opener() || !request.Url().IsEmpty());
loader->SetReplacesCurrentHistoryItem(replace_current_item);
probe::lifecycleEvent(frame_, loader, "init", CurrentTimeTicksInSeconds());
return loader;
}
-STATIC_ASSERT_ENUM(kWebHistorySameDocumentLoad, kHistorySameDocumentLoad);
-STATIC_ASSERT_ENUM(kWebHistoryDifferentDocumentLoad,
- kHistoryDifferentDocumentLoad);
-
STATIC_ASSERT_ENUM(kWebHistoryScrollRestorationManual,
kScrollRestorationManual);
STATIC_ASSERT_ENUM(kWebHistoryScrollRestorationAuto, kScrollRestorationAuto);
-STATIC_ASSERT_ENUM(WebFrameLoadType::kStandard, kFrameLoadTypeStandard);
-STATIC_ASSERT_ENUM(WebFrameLoadType::kBackForward, kFrameLoadTypeBackForward);
-STATIC_ASSERT_ENUM(WebFrameLoadType::kReload, kFrameLoadTypeReload);
-STATIC_ASSERT_ENUM(WebFrameLoadType::kReplaceCurrentItem,
- kFrameLoadTypeReplaceCurrentItem);
-STATIC_ASSERT_ENUM(WebFrameLoadType::kInitialInChildFrame,
- kFrameLoadTypeInitialInChildFrame);
-STATIC_ASSERT_ENUM(WebFrameLoadType::kInitialHistoryLoad,
- kFrameLoadTypeInitialHistoryLoad);
-STATIC_ASSERT_ENUM(WebFrameLoadType::kReloadBypassingCache,
- kFrameLoadTypeReloadBypassingCache);
-
} // namespace blink
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 ef54c5c43ea..60752b5957b 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,10 @@
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink.h"
#include "third_party/blink/public/platform/web_insecure_request_policy.h"
#include "third_party/blink/public/web/commit_result.mojom-shared.h"
+#include "third_party/blink/public/web/web_document_loader.h"
+#include "third_party/blink/public/web/web_frame_load_type.h"
+#include "third_party/blink/public/web/web_navigation_timings.h"
+#include "third_party/blink/public/web/web_navigation_type.h"
#include "third_party/blink/public/web/web_triggering_event_info.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/icon_url.h"
@@ -60,7 +64,7 @@ namespace blink {
class Document;
class DocumentLoader;
-class Event;
+class ExecutionContext;
class HTMLFormElement;
class LocalFrame;
class Frame;
@@ -71,8 +75,8 @@ class SerializedScriptValue;
class SubstituteData;
struct FrameLoadRequest;
-CORE_EXPORT bool IsBackForwardLoadType(FrameLoadType);
-CORE_EXPORT bool IsReloadLoadType(FrameLoadType);
+CORE_EXPORT bool IsBackForwardLoadType(WebFrameLoadType);
+CORE_EXPORT bool IsReloadLoadType(WebFrameLoadType);
class CORE_EXPORT FrameLoader final {
DISALLOW_NEW();
@@ -84,42 +88,42 @@ class CORE_EXPORT FrameLoader final {
void Init();
ResourceRequest ResourceRequestForReload(
- FrameLoadType,
+ WebFrameLoadType,
ClientRedirectPolicy = ClientRedirectPolicy::kNotClientRedirect);
ProgressTracker& Progress() const { return *progress_tracker_; }
// Starts a navigation. It will eventually send the navigation to the
// browser process, or call LoadInSameDocument for same-document navigation.
- // For reloads, an appropriate FrameLoadType should be given. Otherwise,
- // FrameLoadTypeStandard should be used (and the final FrameLoadType
+ // For reloads, an appropriate WebFrameLoadType should be given. Otherwise,
+ // kStandard should be used (and the final WebFrameLoadType
// will be computed).
- // TODO(dgozman): remove history parameters.
void StartNavigation(const FrameLoadRequest&,
- FrameLoadType = kFrameLoadTypeStandard,
- HistoryItem* = nullptr,
- HistoryLoadType = kHistoryDifferentDocumentLoad);
+ WebFrameLoadType = WebFrameLoadType::kStandard,
+ NavigationPolicy = kNavigationPolicyCurrentTab);
// Called when the browser process has asked this renderer process to commit
// a navigation in this frame. This method skips most of the checks assuming
// that browser process has already performed any checks necessary.
// For history navigations, a history item should be provided and
- // an appropriate FrameLoadType should be given.
- void CommitNavigation(const FrameLoadRequest&,
- FrameLoadType = kFrameLoadTypeStandard,
- HistoryItem* = nullptr,
- HistoryLoadType = kHistoryDifferentDocumentLoad);
+ // an appropriate WebFrameLoadType should be given.
+ void CommitNavigation(
+ const FrameLoadRequest&,
+ WebFrameLoadType = WebFrameLoadType::kStandard,
+ HistoryItem* = nullptr,
+ std::unique_ptr<WebDocumentLoader::ExtraData> extra_data = nullptr,
+ const WebNavigationTimings& navigation_timings = WebNavigationTimings());
// Called when the browser process has asked this renderer process to commit a
// same document navigation in that frame. Returns false if the navigation
// cannot commit, true otherwise.
mojom::CommitResult CommitSameDocumentNavigation(
const KURL&,
- FrameLoadType,
+ WebFrameLoadType,
HistoryItem*,
ClientRedirectPolicy,
Document* origin_document = nullptr,
- Event* triggering_event = nullptr);
+ bool has_event = false);
// Warning: stopAllLoaders can and will detach the LocalFrame out from under
// you. All callers need to either protect the LocalFrame or guarantee they
@@ -197,7 +201,7 @@ class CORE_EXPORT FrameLoader final {
SameDocumentNavigationSource,
scoped_refptr<SerializedScriptValue>,
HistoryScrollRestorationType,
- FrameLoadType,
+ WebFrameLoadType,
Document*);
bool ShouldSerializeScrollAnchor();
@@ -213,28 +217,15 @@ class CORE_EXPORT FrameLoader final {
const SubstituteData&,
DocumentLoader*,
ContentSecurityPolicyDisposition,
- NavigationType,
+ WebNavigationType,
NavigationPolicy,
- FrameLoadType,
+ WebFrameLoadType,
bool is_client_redirect,
WebTriggeringEventInfo,
HTMLFormElement*,
mojom::blink::BlobURLTokenPtr,
bool check_with_client);
- // Like ShouldContinueForNavigationPolicy, but should be used when following
- // redirects.
- NavigationPolicy ShouldContinueForRedirectNavigationPolicy(
- const ResourceRequest&,
- const SubstituteData&,
- DocumentLoader*,
- ContentSecurityPolicyDisposition,
- NavigationType,
- NavigationPolicy,
- FrameLoadType,
- bool is_client_redirect,
- HTMLFormElement*);
-
// Note: When a PlzNavigtate navigation is handled by the client, we will
// have created a dummy provisional DocumentLoader, so this will return true
// while the client handles the navigation.
@@ -247,48 +238,43 @@ class CORE_EXPORT FrameLoader final {
void Trace(blink::Visitor*);
static void SetReferrerForFrameRequest(FrameLoadRequest&);
- static void UpgradeInsecureRequest(ResourceRequest&, Document*);
+ static void UpgradeInsecureRequest(ResourceRequest&, ExecutionContext*);
void ClientDroppedNavigation();
private:
bool PrepareRequestForThisFrame(FrameLoadRequest&);
- FrameLoadType DetermineFrameLoadType(const FrameLoadRequest&);
+ WebFrameLoadType DetermineFrameLoadType(const FrameLoadRequest&);
SubstituteData DefaultSubstituteDataForURL(const KURL&);
bool ShouldPerformFragmentNavigation(bool is_form_submission,
const String& http_method,
- FrameLoadType,
+ WebFrameLoadType,
const KURL&);
- void ProcessFragment(const KURL&, FrameLoadType, LoadStartType);
-
- NavigationPolicy CheckLoadCanStart(FrameLoadRequest&,
- FrameLoadType,
- NavigationPolicy,
- NavigationType,
- bool check_with_client);
- void LoadInternal(const FrameLoadRequest&,
- FrameLoadType,
- HistoryItem*,
- HistoryLoadType,
- bool check_with_client);
+ void ProcessFragment(const KURL&, WebFrameLoadType, LoadStartType);
+
+ // Returns whether we should continue with new navigation.
+ bool CancelProvisionalLoaderForNewNavigation(NavigationPolicy);
+
void StartLoad(FrameLoadRequest&,
- FrameLoadType,
+ WebFrameLoadType,
NavigationPolicy,
HistoryItem*,
- bool check_with_client);
+ bool check_with_client,
+ std::unique_ptr<WebDocumentLoader::ExtraData>,
+ const WebNavigationTimings&);
void ClearInitialScrollState();
void LoadInSameDocument(const KURL&,
scoped_refptr<SerializedScriptValue> state_object,
- FrameLoadType,
+ WebFrameLoadType,
HistoryItem*,
ClientRedirectPolicy,
Document*);
- void RestoreScrollPositionAndViewState(FrameLoadType,
- HistoryLoadType,
+ void RestoreScrollPositionAndViewState(WebFrameLoadType,
+ bool is_same_document,
HistoryItem::ViewState*,
HistoryScrollRestorationType);
@@ -299,10 +285,13 @@ class CORE_EXPORT FrameLoader final {
std::unique_ptr<TracedValue> ToTracedValue() const;
void TakeObjectSnapshot() const;
- DocumentLoader* CreateDocumentLoader(const ResourceRequest&,
- const FrameLoadRequest&,
- FrameLoadType,
- NavigationType);
+ DocumentLoader* CreateDocumentLoader(
+ const ResourceRequest&,
+ const FrameLoadRequest&,
+ WebFrameLoadType,
+ WebNavigationType,
+ std::unique_ptr<WebDocumentLoader::ExtraData>,
+ const WebNavigationTimings&);
LocalFrameClient* Client() const;
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 99755a7e847..9f8a0129b04 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
@@ -31,26 +31,6 @@
namespace blink {
-// See WebFrameLoadType in public/web/WebFrameLoadType.h for details.
-enum FrameLoadType {
- kFrameLoadTypeStandard,
- kFrameLoadTypeBackForward,
- kFrameLoadTypeReload,
- kFrameLoadTypeReplaceCurrentItem,
- kFrameLoadTypeInitialInChildFrame,
- kFrameLoadTypeInitialHistoryLoad,
- kFrameLoadTypeReloadBypassingCache,
-};
-
-enum NavigationType {
- kNavigationTypeLinkClicked,
- kNavigationTypeFormSubmitted,
- kNavigationTypeBackForward,
- kNavigationTypeReload,
- kNavigationTypeFormResubmitted,
- kNavigationTypeOther
-};
-
enum ShouldSendReferrer { kMaybeSendReferrer, kNeverSendReferrer };
enum ShouldSetOpener { kMaybeSetOpener, kNeverSetOpener };
@@ -70,18 +50,6 @@ enum SameDocumentNavigationSource {
kSameDocumentNavigationHistoryApi,
};
-enum HistoryLoadType {
- kHistorySameDocumentLoad,
- kHistoryDifferentDocumentLoad
-};
-
-enum HistoryCommitType {
- kStandardCommit,
- kBackForwardCommit,
- kInitialCommitInChildFrame,
- kHistoryInertCommit
-};
-
enum HistoryScrollRestorationType {
kScrollRestorationAuto,
kScrollRestorationManual
diff --git a/chromium/third_party/blink/renderer/core/loader/history_item.cc b/chromium/third_party/blink/renderer/core/loader/history_item.cc
index 4be64ce2a29..d590ed74966 100644
--- a/chromium/third_party/blink/renderer/core/loader/history_item.cc
+++ b/chromium/third_party/blink/renderer/core/loader/history_item.cc
@@ -28,8 +28,10 @@
#include <memory>
#include <utility>
+#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/core/html/forms/form_controller.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
+#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/cstring.h"
diff --git a/chromium/third_party/blink/renderer/core/loader/history_item.h b/chromium/third_party/blink/renderer/core/loader/history_item.h
index 2c3263e35f6..89bb9165d07 100644
--- a/chromium/third_party/blink/renderer/core/loader/history_item.h
+++ b/chromium/third_party/blink/renderer/core/loader/history_item.h
@@ -27,14 +27,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_HISTORY_ITEM_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_HISTORY_ITEM_H_
-#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
#include "third_party/blink/public/platform/web_scroll_anchor_data.h"
-#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/loader/frame_loader_types.h"
-#include "third_party/blink/renderer/platform/geometry/float_point.h"
-#include "third_party/blink/renderer/platform/geometry/int_point.h"
-#include "third_party/blink/renderer/platform/geometry/layout_point.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/scroll/scroll_types.h"
#include "third_party/blink/renderer/platform/weborigin/referrer.h"
@@ -46,6 +41,11 @@ class DocumentState;
class EncodedFormData;
class KURL;
class ResourceRequest;
+class SerializedScriptValue;
+
+namespace mojom {
+enum class FetchCacheMode : int32_t;
+} // namespace mojom
class CORE_EXPORT HistoryItem final
: public GarbageCollectedFinalized<HistoryItem> {
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 5a936c70d53..fb240b62f5e 100644
--- a/chromium/third_party/blink/renderer/core/loader/http_equiv.cc
+++ b/chromium/third_party/blink/renderer/core/loader/http_equiv.cc
@@ -7,6 +7,7 @@
#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/scriptable_document_parser.h"
+#include "third_party/blink/renderer/core/frame/content_settings_client.h"
#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/local_frame.h"
@@ -24,6 +25,65 @@
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()
+ ->IsSameSchemeHostPort(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
+// script was blocked. This method should be called only when there is a need
+// to check the settings, and where blocked setting doesn't really imply that
+// JavaScript was blocked from being executed.
+bool AllowScriptFromSourceWithoutNotifying(
+ const KURL& url,
+ ContentSettingsClient* settings_client,
+ Settings* settings) {
+ if (settings_client && !settings_client->AllowScriptFromSource(
+ !settings || settings->GetScriptEnabled(), url)) {
+ return false;
+ }
+ return true;
+}
+
+// Notifies content settings client of persistent client hint headers.
+void NotifyPersistentClientHintsToContentSettingsClient(Document& document) {
+ TimeDelta 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;
+ }
+
+ document.GetFrame()->GetContentSettingsClient()->PersistClientHints(
+ enabled_client_hints, persist_duration, document.Url());
+}
+
+} // namespace
+
void HttpEquiv::Process(Document& document,
const AtomicString& equiv,
const AtomicString& content,
@@ -47,8 +107,10 @@ void HttpEquiv::Process(Document& document,
kSecurityMessageSource, kErrorMessageLevel,
"X-Frame-Options may only be set via an HTTP header sent along with a "
"document. It may not be set inside <meta>."));
- } else if (EqualIgnoringASCIICase(equiv, "accept-ch")) {
+ } else if (EqualIgnoringASCIICase(equiv, HTTPNames::Accept_CH)) {
ProcessHttpEquivAcceptCH(document, content);
+ } else if (EqualIgnoringASCIICase(equiv, HTTPNames::Accept_CH_Lifetime)) {
+ ProcessHttpEquivAcceptCHLifetime(document, content);
} else if (EqualIgnoringASCIICase(equiv, "content-security-policy") ||
EqualIgnoringASCIICase(equiv,
"content-security-policy-report-only")) {
@@ -86,13 +148,28 @@ void HttpEquiv::ProcessHttpEquivContentSecurityPolicy(
void HttpEquiv::ProcessHttpEquivAcceptCH(Document& document,
const AtomicString& content) {
- if (!document.GetFrame())
+ LocalFrame* frame = document.GetFrame();
+ if (!frame)
return;
UseCounter::Count(document, WebFeature::kClientHintsMetaAcceptCH);
- FrameClientHintsPreferencesContext hints_context(document.GetFrame());
- document.GetClientHintsPreferences().UpdateFromAcceptClientHintsHeader(
+ 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)
+ return;
+
+ UseCounter::Count(document, WebFeature::kClientHintsMetaAcceptCHLifetime);
+ FrameClientHintsPreferencesContext hints_context(frame);
+ frame->GetClientHintsPreferences().UpdateFromAcceptClientHintsLifetimeHeader(
content, document.Url(), &hints_context);
+ NotifyPersistentClientHintsToContentSettingsClient(document);
}
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 8c7cd0a2aa4..f590063d690 100644
--- a/chromium/third_party/blink/renderer/core/loader/http_equiv.h
+++ b/chromium/third_party/blink/renderer/core/loader/http_equiv.h
@@ -45,6 +45,8 @@ 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 5d31806255a..ef0fd583789 100644
--- a/chromium/third_party/blink/renderer/core/loader/idleness_detector.cc
+++ b/chromium/third_party/blink/renderer/core/loader/idleness_detector.cc
@@ -124,10 +124,9 @@ TimeTicks IdlenessDetector::GetNetworkIdleTime() {
return network_0_quiet_start_time_;
}
-void IdlenessDetector::WillProcessTask(double start_time_seconds) {
+void IdlenessDetector::WillProcessTask(base::TimeTicks start_time) {
// If we have idle time and we are kNetworkQuietWindow seconds past it, emit
// idle signals.
- TimeTicks start_time = TimeTicksFromSeconds(start_time_seconds);
DocumentLoader* loader = local_frame_->Loader().GetDocumentLoader();
if (in_network_2_quiet_period_ && !network_2_quiet_.is_null() &&
start_time - network_2_quiet_ > kNetworkQuietWindow) {
@@ -156,11 +155,8 @@ void IdlenessDetector::WillProcessTask(double start_time_seconds) {
Stop();
}
-void IdlenessDetector::DidProcessTask(double start_time_seconds,
- double end_time_seconds) {
- TimeTicks start_time = TimeTicksFromSeconds(start_time_seconds);
- TimeTicks end_time = TimeTicksFromSeconds(end_time_seconds);
-
+void IdlenessDetector::DidProcessTask(base::TimeTicks start_time,
+ base::TimeTicks end_time) {
// Shift idle timestamps with the duration of the task, we were not idle.
if (in_network_2_quiet_period_ && !network_2_quiet_.is_null())
network_2_quiet_ += end_time - start_time;
diff --git a/chromium/third_party/blink/renderer/core/loader/idleness_detector.h b/chromium/third_party/blink/renderer/core/loader/idleness_detector.h
index aabb07081aa..e898c71fba8 100644
--- a/chromium/third_party/blink/renderer/core/loader/idleness_detector.h
+++ b/chromium/third_party/blink/renderer/core/loader/idleness_detector.h
@@ -6,9 +6,9 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_IDLENESS_DETECTOR_H_
#include "base/macros.h"
+#include "base/task/sequence_manager/task_time_observer.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/scheduler/base/task_time_observer.h"
#include "third_party/blink/renderer/platform/timer.h"
namespace blink {
@@ -16,11 +16,11 @@ namespace blink {
class LocalFrame;
class ResourceFetcher;
-// IdlenessDetector observes network request count everytime a load is
-// finshed after DOMContentLoadedEventEnd is fired, and emit network almost idle
-// signal when there are no more than 2 network connection active in 0.5 second,
-// and emit network idle signal when there is 0 network connection active in 0.5
-// second.
+// IdlenessDetector observes the resource request count every time a load is
+// finshed after DOMContentLoadedEventEnd is fired. It emits a network almost
+// idle signal when there are no more than 2 network connections active in 0.5
+// seconds, and a network idle signal when there are 0 network connections
+// active in 0.5 seconds.
class CORE_EXPORT IdlenessDetector
: public GarbageCollectedFinalized<IdlenessDetector>,
public base::sequence_manager::TaskTimeObserver {
@@ -51,8 +51,9 @@ class CORE_EXPORT IdlenessDetector
static constexpr int kNetworkQuietMaximumConnections = 2;
// TaskTimeObserver implementation.
- void WillProcessTask(double start_time) override;
- void DidProcessTask(double start_time, double end_time) override;
+ void WillProcessTask(base::TimeTicks start_time) override;
+ void DidProcessTask(base::TimeTicks start_time,
+ base::TimeTicks end_time) override;
void Stop();
void NetworkQuietTimerFired(TimerBase*);
diff --git a/chromium/third_party/blink/renderer/core/loader/idleness_detector_test.cc b/chromium/third_party/blink/renderer/core/loader/idleness_detector_test.cc
index 0e87fdba3dd..fa7542d5eb4 100644
--- a/chromium/third_party/blink/renderer/core/loader/idleness_detector_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/idleness_detector_test.cc
@@ -13,8 +13,8 @@ namespace blink {
class IdlenessDetectorTest : public PageTestBase {
protected:
void SetUp() override {
- platform_time_ = 1;
- platform_->AdvanceClockSeconds(platform_time_);
+ platform_time_ = CurrentTimeTicks();
+ DCHECK(!platform_time_.is_null());
PageTestBase::SetUp();
}
@@ -29,59 +29,62 @@ class IdlenessDetectorTest : public PageTestBase {
!Detector()->in_network_0_quiet_period_;
}
- void WillProcessTask(double start_time) {
+ void WillProcessTask(base::TimeTicks start_time) {
DCHECK(start_time >= platform_time_);
- platform_->AdvanceClockSeconds(start_time - platform_time_);
+ platform_->AdvanceClock(start_time - platform_time_);
platform_time_ = start_time;
Detector()->WillProcessTask(start_time);
}
- void DidProcessTask(double start_time, double end_time) {
+ void DidProcessTask(base::TimeTicks start_time, base::TimeTicks end_time) {
DCHECK(start_time < end_time);
- platform_->AdvanceClockSeconds(end_time - start_time);
+ platform_->AdvanceClock(end_time - start_time);
platform_time_ = end_time;
Detector()->DidProcessTask(start_time, end_time);
}
- protected:
+ static base::TimeTicks SecondsToTimeTicks(double seconds) {
+ return base::TimeTicks() + base::TimeDelta::FromSecondsD(seconds);
+ }
+
ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
platform_;
private:
- double platform_time_;
+ base::TimeTicks platform_time_;
};
TEST_F(IdlenessDetectorTest, NetworkQuietBasic) {
EXPECT_TRUE(IsNetworkQuietTimerActive());
- WillProcessTask(1);
- DidProcessTask(1, 1.01);
+ WillProcessTask(SecondsToTimeTicks(1));
+ DidProcessTask(SecondsToTimeTicks(1), SecondsToTimeTicks(1.01));
- WillProcessTask(1.52);
+ WillProcessTask(SecondsToTimeTicks(1.52));
EXPECT_TRUE(HadNetworkQuiet());
- DidProcessTask(1.52, 1.53);
+ DidProcessTask(SecondsToTimeTicks(1.52), SecondsToTimeTicks(1.53));
}
TEST_F(IdlenessDetectorTest, NetworkQuietWithLongTask) {
EXPECT_TRUE(IsNetworkQuietTimerActive());
- WillProcessTask(1);
- DidProcessTask(1, 1.01);
+ WillProcessTask(SecondsToTimeTicks(1));
+ DidProcessTask(SecondsToTimeTicks(1), SecondsToTimeTicks(1.01));
- WillProcessTask(1.02);
- DidProcessTask(1.02, 1.6);
+ WillProcessTask(SecondsToTimeTicks(1.02));
+ DidProcessTask(SecondsToTimeTicks(1.02), SecondsToTimeTicks(1.6));
EXPECT_FALSE(HadNetworkQuiet());
- WillProcessTask(2.11);
+ WillProcessTask(SecondsToTimeTicks(2.11));
EXPECT_TRUE(HadNetworkQuiet());
- DidProcessTask(2.11, 2.12);
+ DidProcessTask(SecondsToTimeTicks(2.11), SecondsToTimeTicks(2.12));
}
TEST_F(IdlenessDetectorTest, NetworkQuietWatchdogTimerFired) {
EXPECT_TRUE(IsNetworkQuietTimerActive());
- WillProcessTask(1);
- DidProcessTask(1, 1.01);
+ WillProcessTask(SecondsToTimeTicks(1));
+ DidProcessTask(SecondsToTimeTicks(1), SecondsToTimeTicks(1.01));
platform_->RunForPeriodSeconds(3);
EXPECT_FALSE(IsNetworkQuietTimerActive());
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 e599c1a10c2..59be0be3554 100644
--- a/chromium/third_party/blink/renderer/core/loader/image_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/image_loader.cc
@@ -28,7 +28,6 @@
#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
#include "third_party/blink/public/platform/web_client_hints_type.h"
#include "third_party/blink/public/platform/web_url_request.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -44,8 +43,10 @@
#include "third_party/blink/renderer/core/layout/layout_image.h"
#include "third_party/blink/renderer/core/layout/layout_video.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_image.h"
+#include "third_party/blink/renderer/core/loader/importance_attribute.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/svg/graphics/svg_image.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/microtask.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
@@ -87,7 +88,6 @@ class ImageLoader::Task {
should_bypass_main_world_csp_(ShouldBypassMainWorldCSP(loader)),
update_behavior_(update_behavior),
referrer_policy_(referrer_policy),
-
weak_factory_(this) {
ExecutionContext& context = loader_->GetElement()->GetDocument();
probe::AsyncTaskScheduled(&context, "Image", this);
@@ -111,12 +111,13 @@ class ImageLoader::Task {
return;
ExecutionContext& context = loader_->GetElement()->GetDocument();
probe::AsyncTask async_task(&context, this);
- if (script_state_->ContextIsValid()) {
- ScriptState::Scope scope(script_state_.get());
+ if (script_state_ && script_state_->ContextIsValid()) {
+ ScriptState::Scope scope(script_state_);
loader_->DoUpdateFromElement(should_bypass_main_world_csp_,
update_behavior_, request_url_,
referrer_policy_);
} else {
+ // This call does not access v8::Context internally.
loader_->DoUpdateFromElement(should_bypass_main_world_csp_,
update_behavior_, request_url_,
referrer_policy_);
@@ -134,7 +135,7 @@ class ImageLoader::Task {
WeakPersistent<ImageLoader> loader_;
BypassMainWorldBehavior should_bypass_main_world_csp_;
UpdateFromElementBehavior update_behavior_;
- scoped_refptr<ScriptState> script_state_;
+ WeakPersistent<ScriptState> script_state_;
ReferrerPolicy referrer_policy_;
KURL request_url_;
base::WeakPtrFactory<Task> weak_factory_;
@@ -301,6 +302,13 @@ static void ConfigureRequest(
element.GetDocument().GetSecurityOrigin(), cross_origin);
}
+ if (RuntimeEnabledFeatures::PriorityHintsEnabled()) {
+ mojom::FetchImportanceMode importance_mode =
+ GetFetchImportanceAttributeValue(
+ element.FastGetAttribute(HTMLNames::importanceAttr));
+ params.SetFetchImportanceMode(importance_mode);
+ }
+
if (client_hints_preferences.ShouldSend(
mojom::WebClientHintsType::kResourceWidth) &&
IsHTMLImageElement(element))
@@ -422,9 +430,10 @@ void ImageLoader::DoUpdateFromElement(BypassMainWorldBehavior bypass_behavior,
resource_request.SetSkipServiceWorker(true);
}
+ DCHECK(document.GetFrame());
FetchParameters params(resource_request, resource_loader_options);
ConfigureRequest(params, bypass_behavior, *element_,
- document.GetClientHintsPreferences());
+ document.GetFrame()->GetClientHintsPreferences());
if (update_behavior != kUpdateForcedReload && document.GetFrame())
document.GetFrame()->MaybeAllowImagePlaceholder(params);
@@ -514,7 +523,6 @@ void ImageLoader::UpdateFromElement(UpdateFromElementBehavior update_behavior,
request.SetFetchCredentialsMode(
network::mojom::FetchCredentialsMode::kOmit);
ImageResource* image_resource = ImageResource::Create(request);
- image_resource->SetStatus(ResourceStatus::kPending);
image_resource->NotifyStartLoad();
SetImageForImageDocument(image_resource);
return;
@@ -763,7 +771,7 @@ ScriptPromise ImageLoader::Decode(ScriptState* script_state,
// that comes from iframe.contentDocument.createElement("img") and the iframe
// is destroyed).
if (!script_state->ContextIsValid()) {
- exception_state.ThrowDOMException(kEncodingError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kEncodingError,
"The source image cannot be decoded.");
return ScriptPromise();
}
@@ -806,7 +814,7 @@ void ImageLoader::DecodeRequest::Resolve() {
void ImageLoader::DecodeRequest::Reject() {
resolver_->Reject(DOMException::Create(
- kEncodingError, "The source image cannot be decoded."));
+ DOMExceptionCode::kEncodingError, "The source image cannot be decoded."));
loader_ = nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/loader/importance_attribute.cc b/chromium/third_party/blink/renderer/core/loader/importance_attribute.cc
new file mode 100644
index 00000000000..d2a836df313
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/loader/importance_attribute.cc
@@ -0,0 +1,18 @@
+// 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/loader/importance_attribute.h"
+
+namespace blink {
+
+mojom::FetchImportanceMode GetFetchImportanceAttributeValue(
+ const String& value) {
+ if (EqualIgnoringASCIICase(value, "low"))
+ return mojom::FetchImportanceMode::kImportanceLow;
+ if (EqualIgnoringASCIICase(value, "high"))
+ return mojom::FetchImportanceMode::kImportanceHigh;
+ return mojom::FetchImportanceMode::kImportanceAuto;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/importance_attribute.h b/chromium/third_party/blink/renderer/core/loader/importance_attribute.h
new file mode 100644
index 00000000000..ccb1f9c2ff8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/loader/importance_attribute.h
@@ -0,0 +1,18 @@
+// 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_LOADER_IMPORTANCE_ATTRIBUTE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_IMPORTANCE_ATTRIBUTE_H_
+
+#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+mojom::FetchImportanceMode GetFetchImportanceAttributeValue(
+ const String& value);
+
+} // namespace blink
+
+#endif
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 c7bd5eb9716..f70b9be7318 100644
--- a/chromium/third_party/blink/renderer/core/loader/interactive_detector.cc
+++ b/chromium/third_party/blink/renderer/core/loader/interactive_detector.cc
@@ -22,6 +22,10 @@ constexpr auto kTimeToInteractiveWindow = TimeDelta::FromSeconds(5);
// requests for this duration of time.
constexpr int kNetworkQuietMaximumConnections = 2;
+const char kHistogramInputDelay[] = "PageLoad.InteractiveTiming.InputDelay";
+const char kHistogramInputTimestamp[] =
+ "PageLoad.InteractiveTiming.InputTimestamp";
+
// static
const char InteractiveDetector::kSupplementName[] = "InteractiveDetector";
@@ -44,15 +48,13 @@ InteractiveDetector::InteractiveDetector(
Document& document,
NetworkActivityChecker* network_activity_checker)
: Supplement<Document>(document),
+ ContextLifecycleObserver(&document),
network_activity_checker_(network_activity_checker),
time_to_interactive_timer_(
document.GetTaskRunner(TaskType::kInternalDefault),
this,
- &InteractiveDetector::TimeToInteractiveTimerFired) {}
-
-InteractiveDetector::~InteractiveDetector() {
- LongTaskDetector::Instance().UnregisterObserver(this);
-}
+ &InteractiveDetector::TimeToInteractiveTimerFired),
+ initial_visibility_(document.GetPageVisibilityState()) {}
void InteractiveDetector::SetNavigationStartTime(
TimeTicks navigation_start_time) {
@@ -136,14 +138,47 @@ TimeTicks InteractiveDetector::GetFirstInputTimestamp() const {
return page_event_times_.first_input_timestamp;
}
+TimeDelta InteractiveDetector::GetLongestInputDelay() const {
+ return page_event_times_.longest_input_delay;
+}
+
+TimeTicks InteractiveDetector::GetLongestInputTimestamp() const {
+ return page_event_times_.longest_input_timestamp;
+}
+
+bool InteractiveDetector::PageWasBackgroundedSinceEvent(TimeTicks event_time) {
+ DCHECK(GetSupplementable());
+ if (GetSupplementable()->GetPageVisibilityState() ==
+ mojom::PageVisibilityState::kHidden) {
+ return true;
+ }
+
+ mojom::PageVisibilityState curr_visibility = initial_visibility_;
+ TimeTicks visibility_start = page_event_times_.nav_start;
+ for (auto change_event : visibility_change_events_) {
+ TimeTicks visibility_end = change_event.timestamp;
+ if (curr_visibility == mojom::PageVisibilityState::kHidden &&
+ event_time < visibility_end) {
+ // [event_time, now] intersects a backgrounded range.
+ return true;
+ }
+ curr_visibility = change_event.visibility;
+ visibility_start = visibility_end;
+ }
+
+ return false;
+} // namespace blink
+
// This is called early enough in the pipeline that we don't need to worry about
// javascript dispatching untrusted input events.
-void InteractiveDetector::HandleForFirstInputDelay(const WebInputEvent& event) {
- if (!page_event_times_.first_input_delay.is_zero())
- return;
-
+void InteractiveDetector::HandleForInputDelay(const WebInputEvent& event) {
DCHECK(event.GetType() != WebInputEvent::kTouchStart);
+ // This only happens sometimes on tests unrelated to InteractiveDetector. It
+ // is safe to ignore events that are not properly initialized.
+ if (event.TimeStamp().is_null())
+ return;
+
// We can't report a pointerDown until the pointerUp, in case it turns into a
// scroll.
if (event.GetType() == WebInputEvent::kPointerDown) {
@@ -167,6 +202,10 @@ void InteractiveDetector::HandleForFirstInputDelay(const WebInputEvent& event) {
TimeDelta delay;
TimeTicks event_timestamp;
if (event.GetType() == WebInputEvent::kPointerUp) {
+ // PointerUp by itself is not considered a significant input.
+ if (pending_pointerdown_timestamp_.is_null())
+ return;
+
// It is possible that this pointer up doesn't match with the pointer down
// whose delay is stored in pending_pointerdown_delay_. In this case, the
// user gesture started by this event contained some non-scroll input, so we
@@ -180,11 +219,32 @@ void InteractiveDetector::HandleForFirstInputDelay(const WebInputEvent& event) {
pending_pointerdown_delay_ = base::TimeDelta();
pending_pointerdown_timestamp_ = base::TimeTicks();
+ bool input_delay_metrics_changed = false;
- page_event_times_.first_input_delay = delay;
- page_event_times_.first_input_timestamp = event_timestamp;
+ if (page_event_times_.first_input_delay.is_zero()) {
+ page_event_times_.first_input_delay = delay;
+ page_event_times_.first_input_timestamp = event_timestamp;
+ input_delay_metrics_changed = true;
+ }
- if (GetSupplementable()->Loader())
+ UMA_HISTOGRAM_CUSTOM_TIMES(kHistogramInputDelay, delay,
+ base::TimeDelta::FromMilliseconds(1),
+ base::TimeDelta::FromSeconds(60), 50);
+ UMA_HISTOGRAM_CUSTOM_TIMES(kHistogramInputTimestamp,
+ event_timestamp - page_event_times_.nav_start,
+ base::TimeDelta::FromMilliseconds(10),
+ base::TimeDelta::FromMinutes(10), 100);
+
+ // Only update longest input delay if page was not backgrounded while the
+ // input was queued.
+ if (delay > page_event_times_.longest_input_delay &&
+ !PageWasBackgroundedSinceEvent(event_timestamp)) {
+ page_event_times_.longest_input_delay = delay;
+ page_event_times_.longest_input_timestamp = event_timestamp;
+ input_delay_metrics_changed = true;
+ }
+
+ if (GetSupplementable()->Loader() && input_delay_metrics_changed)
GetSupplementable()->Loader()->DidChangePerformanceTiming();
}
@@ -305,13 +365,9 @@ void InteractiveDetector::OnInvalidatingInputEvent(
GetSupplementable()->Loader()->DidChangePerformanceTiming();
}
-void InteractiveDetector::OnFirstInputDelay(TimeDelta delay) {
- if (!page_event_times_.first_input_delay.is_zero())
- return;
-
- page_event_times_.first_input_delay = delay;
- if (GetSupplementable()->Loader())
- GetSupplementable()->Loader()->DidChangePerformanceTiming();
+void InteractiveDetector::OnPageVisibilityChanged(
+ mojom::PageVisibilityState visibility) {
+ visibility_change_events_.push_back({CurrentTimeTicks(), visibility});
}
void InteractiveDetector::TimeToInteractiveTimerFired(TimerBase*) {
@@ -468,8 +524,13 @@ void InteractiveDetector::OnTimeToInteractiveDetected() {
}
}
+void InteractiveDetector::ContextDestroyed(ExecutionContext*) {
+ LongTaskDetector::Instance().UnregisterObserver(this);
+}
+
void InteractiveDetector::Trace(Visitor* visitor) {
Supplement<Document>::Trace(visitor);
+ ContextLifecycleObserver::Trace(visitor);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/interactive_detector.h b/chromium/third_party/blink/renderer/core/loader/interactive_detector.h
index f5177b942f3..0e62b777501 100644
--- a/chromium/third_party/blink/renderer/core/loader/interactive_detector.h
+++ b/chromium/third_party/blink/renderer/core/loader/interactive_detector.h
@@ -9,6 +9,8 @@
#include "base/optional.h"
#include "base/time/time.h"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/core/page/page_visibility_state.h"
#include "third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/long_task_detector.h"
@@ -29,6 +31,7 @@ class WebInputEvent;
class CORE_EXPORT InteractiveDetector
: public GarbageCollectedFinalized<InteractiveDetector>,
public Supplement<Document>,
+ public ContextLifecycleObserver,
public LongTaskObserver {
USING_GARBAGE_COLLECTED_MIXIN(InteractiveDetector);
@@ -54,7 +57,7 @@ class CORE_EXPORT InteractiveDetector
// Exposed for tests. See crbug.com/810381. We must use a consistent address
// for the supplement name.
static const char* SupplementName();
- ~InteractiveDetector() override;
+ ~InteractiveDetector() override = default;
// Calls to CurrentTimeTicksInSeconds is expensive, so we try not to call it
// unless we really have to. If we already have the event time available, we
@@ -68,7 +71,7 @@ class CORE_EXPORT InteractiveDetector
FirstMeaningfulPaintDetector::HadUserInput user_input_before_fmp);
void OnDomContentLoadedEnd(TimeTicks dcl_time);
void OnInvalidatingInputEvent(TimeTicks invalidation_time);
- void OnFirstInputDelay(TimeDelta delay_seconds);
+ void OnPageVisibilityChanged(mojom::PageVisibilityState);
// Returns Interactive Time if already detected, or 0.0 otherwise.
TimeTicks GetInteractiveTime() const;
@@ -90,9 +93,21 @@ class CORE_EXPORT InteractiveDetector
// The timestamp of the event whose delay is reported by GetFirstInputDelay().
TimeTicks GetFirstInputTimestamp() const;
+ // Queueing Time of the meaningful input event with longest delay. Meaningful
+ // input events are click, tap, key press, cancellable touchstart, or pointer
+ // down followed by a pointer up.
+ TimeDelta GetLongestInputDelay() const;
+
+ // The timestamp of the event whose delay is reported by
+ // GetLongestInputDelay().
+ TimeTicks GetLongestInputTimestamp() const;
+
// Process an input event, updating first_input_delay and
// first_input_timestamp if needed.
- void HandleForFirstInputDelay(const WebInputEvent&);
+ void HandleForInputDelay(const WebInputEvent&);
+
+ // ContextLifecycleObserver
+ void ContextDestroyed(ExecutionContext*) override;
void Trace(Visitor*) override;
@@ -112,16 +127,24 @@ class CORE_EXPORT InteractiveDetector
TimeTicks nav_start;
TimeTicks first_invalidating_input;
TimeDelta first_input_delay;
+ TimeDelta longest_input_delay;
TimeTicks first_input_timestamp;
+ TimeTicks longest_input_timestamp;
bool first_meaningful_paint_invalidated = false;
} page_event_times_;
+ struct VisibilityChangeEvent {
+ TimeTicks timestamp;
+ mojom::PageVisibilityState visibility;
+ };
+
// Stores sufficiently long quiet windows on main thread and network.
std::vector<PODInterval<TimeTicks>> main_thread_quiet_windows_;
std::vector<PODInterval<TimeTicks>> network_quiet_windows_;
// Start times of currently active main thread and network quiet windows.
- // Values of 0.0 implies main thread or network is not quiet at the moment.
+ // Null TimeTicks values indicate main thread or network is not quiet at the
+ // moment.
TimeTicks active_main_thread_quiet_window_start_;
TimeTicks active_network_quiet_window_start_;
@@ -148,6 +171,12 @@ class CORE_EXPORT InteractiveDetector
void CheckTimeToInteractiveReached();
void OnTimeToInteractiveDetected();
+ std::vector<VisibilityChangeEvent> visibility_change_events_;
+ mojom::PageVisibilityState initial_visibility_;
+ // Returns true if page was ever backgrounded in the range
+ // [event_time, CurrentTimeTicks()].
+ bool PageWasBackgroundedSinceEvent(TimeTicks event_time);
+
// Finds a window of length kTimeToInteractiveWindowSeconds after lower_bound
// such that both main thread and network are quiet. Returns the end of last
// long task before that quiet window, or lower_bound, whichever is bigger -
diff --git a/chromium/third_party/blink/renderer/core/loader/interactive_detector_test.cc b/chromium/third_party/blink/renderer/core/loader/interactive_detector_test.cc
index 63928280805..31a5a8505c6 100644
--- a/chromium/third_party/blink/renderer/core/loader/interactive_detector_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/interactive_detector_test.cc
@@ -34,12 +34,6 @@ int NetworkActivityCheckerForTest::GetActiveConnections() {
return active_connections_;
}
-struct TaskTiming {
- double start;
- double end;
- TaskTiming(double start, double end) : start(start), end(end) {}
-};
-
class InteractiveDetectorTest : public testing::Test {
public:
InteractiveDetectorTest() {
@@ -63,13 +57,13 @@ class InteractiveDetectorTest : public testing::Test {
// Public because it's executed on a task queue.
void DummyTaskWithDuration(double duration_seconds) {
platform_->AdvanceClockSeconds(duration_seconds);
- dummy_task_end_time_ = CurrentTimeTicksInSeconds();
+ dummy_task_end_time_ = CurrentTimeTicks();
}
protected:
InteractiveDetector* GetDetector() { return detector_; }
- double GetDummyTaskEndTime() { return dummy_task_end_time_; }
+ TimeTicks GetDummyTaskEndTime() { return dummy_task_end_time_; }
NetworkActivityCheckerForTest* GetNetworkActivityChecker() {
// We know in this test context that network_activity_checker_ is an
@@ -78,38 +72,36 @@ class InteractiveDetectorTest : public testing::Test {
detector_->network_activity_checker_.get());
}
- void SimulateNavigationStart(double nav_start_time) {
+ void SimulateNavigationStart(TimeTicks nav_start_time) {
RunTillTimestamp(nav_start_time);
- detector_->SetNavigationStartTime(TimeTicksFromSeconds(nav_start_time));
+ detector_->SetNavigationStartTime(nav_start_time);
}
- void SimulateLongTask(double start, double end) {
- CHECK(end - start >= 0.05);
+ void SimulateLongTask(TimeTicks start, TimeTicks end) {
+ CHECK(end - start >= TimeDelta::FromSecondsD(0.05));
RunTillTimestamp(end);
- detector_->OnLongTaskDetected(TimeTicksFromSeconds(start),
- TimeTicksFromSeconds(end));
+ detector_->OnLongTaskDetected(start, end);
}
- void SimulateDOMContentLoadedEnd(double dcl_time) {
+ void SimulateDOMContentLoadedEnd(TimeTicks dcl_time) {
RunTillTimestamp(dcl_time);
- detector_->OnDomContentLoadedEnd(TimeTicksFromSeconds(dcl_time));
+ detector_->OnDomContentLoadedEnd(dcl_time);
}
- void SimulateFMPDetected(double fmp_time, double detection_time) {
+ void SimulateFMPDetected(TimeTicks fmp_time, TimeTicks detection_time) {
RunTillTimestamp(detection_time);
detector_->OnFirstMeaningfulPaintDetected(
- TimeTicksFromSeconds(fmp_time),
- FirstMeaningfulPaintDetector::kNoUserInput);
+ fmp_time, FirstMeaningfulPaintDetector::kNoUserInput);
}
- void SimulateInteractiveInvalidatingInput(double timestamp) {
+ void SimulateInteractiveInvalidatingInput(TimeTicks timestamp) {
RunTillTimestamp(timestamp);
- detector_->OnInvalidatingInputEvent(TimeTicksFromSeconds(timestamp));
+ detector_->OnInvalidatingInputEvent(timestamp);
}
- void RunTillTimestamp(double target_time) {
- double current_time = CurrentTimeTicksInSeconds();
- platform_->RunForPeriodSeconds(std::max(0.0, target_time - current_time));
+ void RunTillTimestamp(TimeTicks target_time) {
+ TimeTicks current_time = CurrentTimeTicks();
+ platform_->RunForPeriod(std::max(TimeDelta(), target_time - current_time));
}
int GetActiveConnections() {
@@ -120,23 +112,21 @@ class InteractiveDetectorTest : public testing::Test {
GetNetworkActivityChecker()->SetActiveConnections(active_connections);
}
- void SimulateResourceLoadBegin(double load_begin_time) {
+ void SimulateResourceLoadBegin(TimeTicks load_begin_time) {
RunTillTimestamp(load_begin_time);
- detector_->OnResourceLoadBegin(TimeTicksFromSeconds(load_begin_time));
+ detector_->OnResourceLoadBegin(load_begin_time);
// ActiveConnections is incremented after detector runs OnResourceLoadBegin;
SetActiveConnections(GetActiveConnections() + 1);
}
- void SimulateResourceLoadEnd(double load_finish_time) {
+ void SimulateResourceLoadEnd(TimeTicks load_finish_time) {
RunTillTimestamp(load_finish_time);
int active_connections = GetActiveConnections();
SetActiveConnections(active_connections - 1);
- detector_->OnResourceLoadEnd(TimeTicksFromSeconds(load_finish_time));
+ detector_->OnResourceLoadEnd(load_finish_time);
}
- double GetInteractiveTime() {
- return TimeTicksInSeconds(detector_->GetInteractiveTime());
- }
+ TimeTicks GetInteractiveTime() { return detector_->GetInteractiveTime(); }
ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
platform_;
@@ -144,7 +134,7 @@ class InteractiveDetectorTest : public testing::Test {
private:
Persistent<InteractiveDetector> detector_;
std::unique_ptr<DummyPageHolder> dummy_page_holder_;
- double dummy_task_end_time_ = 0.0;
+ TimeTicks dummy_task_end_time_;
};
// Note: The tests currently assume kTimeToInteractiveWindowSeconds is 5
@@ -160,308 +150,374 @@ class InteractiveDetectorTest : public testing::Test {
// The name shows the ordering of these events in the test.
TEST_F(InteractiveDetectorTest, FMP_DCL_FmpDetect) {
- double t0 = CurrentTimeTicksInSeconds();
+ TimeTicks t0 = CurrentTimeTicks();
SimulateNavigationStart(t0);
// Network is forever quiet for this test.
SetActiveConnections(1);
- SimulateDOMContentLoadedEnd(t0 + 3.0);
- SimulateFMPDetected(/* fmp_time */ t0 + 5.0, /* detection_time */ t0 + 7.0);
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(3));
+ SimulateFMPDetected(/* fmp_time */ t0 + TimeDelta::FromSeconds(5),
+ /* detection_time */ t0 + TimeDelta::FromSeconds(7));
// Run until 5 seconds after FMP.
- RunTillTimestamp((t0 + 5.0) + 5.0 + 0.1);
+ RunTillTimestamp((t0 + TimeDelta::FromSeconds(5)) +
+ TimeDelta::FromSecondsD(5.0 + 0.1));
// Reached TTI at FMP.
- EXPECT_EQ(GetInteractiveTime(), t0 + 5.0);
+ EXPECT_EQ(GetInteractiveTime(), t0 + TimeDelta::FromSeconds(5));
}
TEST_F(InteractiveDetectorTest, DCL_FMP_FmpDetect) {
- double t0 = CurrentTimeTicksInSeconds();
+ TimeTicks t0 = CurrentTimeTicks();
SimulateNavigationStart(t0);
// Network is forever quiet for this test.
SetActiveConnections(1);
- SimulateDOMContentLoadedEnd(t0 + 5.0);
- SimulateFMPDetected(/* fmp_time */ t0 + 3.0, /* detection_time */ t0 + 7.0);
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(5));
+ SimulateFMPDetected(/* fmp_time */ t0 + TimeDelta::FromSeconds(3),
+ /* detection_time */ t0 + TimeDelta::FromSeconds(7));
// Run until 5 seconds after FMP.
- RunTillTimestamp((t0 + 3.0) + 5.0 + 0.1);
+ RunTillTimestamp((t0 + TimeDelta::FromSeconds(3)) +
+ TimeDelta::FromSecondsD(5.0 + 0.1));
// Reached TTI at DCL.
- EXPECT_EQ(GetInteractiveTime(), t0 + 5.0);
+ EXPECT_EQ(GetInteractiveTime(), t0 + TimeDelta::FromSeconds(5));
}
TEST_F(InteractiveDetectorTest, InstantDetectionAtFmpDetectIfPossible) {
- double t0 = CurrentTimeTicksInSeconds();
+ TimeTicks t0 = CurrentTimeTicks();
SimulateNavigationStart(t0);
// Network is forever quiet for this test.
SetActiveConnections(1);
- SimulateDOMContentLoadedEnd(t0 + 5.0);
- SimulateFMPDetected(/* fmp_time */ t0 + 3.0, /* detection_time */ t0 + 10.0);
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(5));
+ SimulateFMPDetected(/* fmp_time */ t0 + TimeDelta::FromSeconds(3),
+ /* detection_time */ t0 + TimeDelta::FromSeconds(10));
// Although we just detected FMP, the FMP timestamp is more than
// kTimeToInteractiveWindowSeconds earlier. We should instantaneously
// detect that we reached TTI at DCL.
- EXPECT_EQ(GetInteractiveTime(), t0 + 5.0);
+ EXPECT_EQ(GetInteractiveTime(), t0 + TimeDelta::FromSeconds(5));
}
TEST_F(InteractiveDetectorTest, FmpDetectFiresAfterLateLongTask) {
- double t0 = CurrentTimeTicksInSeconds();
+ TimeTicks t0 = CurrentTimeTicks();
SimulateNavigationStart(t0);
// Network is forever quiet for this test.
SetActiveConnections(1);
- SimulateDOMContentLoadedEnd(t0 + 3.0);
- SimulateLongTask(t0 + 9.0, t0 + 9.1);
- SimulateFMPDetected(/* fmp_time */ t0 + 3.0, /* detection_time */ t0 + 10.0);
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(3));
+ SimulateLongTask(t0 + TimeDelta::FromSeconds(9),
+ t0 + TimeDelta::FromSecondsD(9.1));
+ SimulateFMPDetected(/* fmp_time */ t0 + TimeDelta::FromSeconds(3),
+ /* detection_time */ t0 + TimeDelta::FromSeconds(10));
// There is a 5 second quiet window after fmp_time - the long task is 6s
// seconds after fmp_time. We should instantly detect we reached TTI at FMP.
- EXPECT_EQ(GetInteractiveTime(), t0 + 3.0);
+ EXPECT_EQ(GetInteractiveTime(), t0 + TimeDelta::FromSeconds(3));
}
TEST_F(InteractiveDetectorTest, FMP_FmpDetect_DCL) {
- double t0 = CurrentTimeTicksInSeconds();
+ TimeTicks t0 = CurrentTimeTicks();
SimulateNavigationStart(t0);
// Network is forever quiet for this test.
SetActiveConnections(1);
- SimulateFMPDetected(/* fmp_time */ t0 + 3.0, /* detection_time */ t0 + 5.0);
- SimulateDOMContentLoadedEnd(t0 + 9.0);
+ SimulateFMPDetected(/* fmp_time */ t0 + TimeDelta::FromSeconds(3),
+ /* detection_time */ t0 + TimeDelta::FromSeconds(5));
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(9));
// TTI reached at DCL.
- EXPECT_EQ(GetInteractiveTime(), t0 + 9.0);
+ EXPECT_EQ(GetInteractiveTime(), t0 + TimeDelta::FromSeconds(9));
}
TEST_F(InteractiveDetectorTest, LongTaskBeforeFMPDoesNotAffectTTI) {
- double t0 = CurrentTimeTicksInSeconds();
+ TimeTicks t0 = CurrentTimeTicks();
SimulateNavigationStart(t0);
// Network is forever quiet for this test.
SetActiveConnections(1);
- SimulateDOMContentLoadedEnd(t0 + 3.0);
- SimulateLongTask(t0 + 5.1, t0 + 5.2);
- SimulateFMPDetected(/* fmp_time */ t0 + 8.0, /* detection_time */ t0 + 9.0);
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(3));
+ SimulateLongTask(t0 + TimeDelta::FromSecondsD(5.1),
+ t0 + TimeDelta::FromSecondsD(5.2));
+ SimulateFMPDetected(/* fmp_time */ t0 + TimeDelta::FromSeconds(8),
+ /* detection_time */ t0 + TimeDelta::FromSeconds(9));
// Run till 5 seconds after FMP.
- RunTillTimestamp((t0 + 8.0) + 5.0 + 0.1);
+ RunTillTimestamp((t0 + TimeDelta::FromSeconds(8)) +
+ TimeDelta::FromSecondsD(5.0 + 0.1));
// TTI reached at FMP.
- EXPECT_EQ(GetInteractiveTime(), t0 + 8.0);
+ EXPECT_EQ(GetInteractiveTime(), t0 + TimeDelta::FromSeconds(8));
}
TEST_F(InteractiveDetectorTest, DCLDoesNotResetTimer) {
- double t0 = CurrentTimeTicksInSeconds();
+ TimeTicks t0 = CurrentTimeTicks();
SimulateNavigationStart(t0);
// Network is forever quiet for this test.
SetActiveConnections(1);
- SimulateFMPDetected(/* fmp_time */ t0 + 3.0, /* detection_time */ t0 + 4.0);
- SimulateLongTask(t0 + 5.0, t0 + 5.1);
- SimulateDOMContentLoadedEnd(t0 + 8.0);
+ SimulateFMPDetected(/* fmp_time */ t0 + TimeDelta::FromSeconds(3),
+ /* detection_time */ t0 + TimeDelta::FromSeconds(4));
+ SimulateLongTask(t0 + TimeDelta::FromSeconds(5),
+ t0 + TimeDelta::FromSecondsD(5.1));
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(8));
// Run till 5 seconds after long task end.
- RunTillTimestamp((t0 + 5.1) + 5.0 + 0.1);
+ RunTillTimestamp((t0 + TimeDelta::FromSecondsD(5.1)) +
+ TimeDelta::FromSecondsD(5.0 + 0.1));
// TTI Reached at DCL.
- EXPECT_EQ(GetInteractiveTime(), t0 + 8.0);
+ EXPECT_EQ(GetInteractiveTime(), t0 + TimeDelta::FromSeconds(8));
}
TEST_F(InteractiveDetectorTest, DCL_FMP_FmpDetect_LT) {
- double t0 = CurrentTimeTicksInSeconds();
+ TimeTicks t0 = CurrentTimeTicks();
SimulateNavigationStart(t0);
// Network is forever quiet for this test.
SetActiveConnections(1);
- SimulateDOMContentLoadedEnd(t0 + 3.0);
- SimulateFMPDetected(/* fmp_time */ t0 + 4.0, /* detection_time */ t0 + 5.0);
- SimulateLongTask(t0 + 7.0, t0 + 7.1);
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(3));
+ SimulateFMPDetected(/* fmp_time */ t0 + TimeDelta::FromSeconds(4),
+ /* detection_time */ t0 + TimeDelta::FromSeconds(5));
+ SimulateLongTask(t0 + TimeDelta::FromSeconds(7),
+ t0 + TimeDelta::FromSecondsD(7.1));
// Run till 5 seconds after long task end.
- RunTillTimestamp((t0 + 7.1) + 5.0 + 0.1);
+ RunTillTimestamp((t0 + TimeDelta::FromSecondsD(7.1)) +
+ TimeDelta::FromSecondsD(5.0 + 0.1));
// TTI reached at long task end.
- EXPECT_EQ(GetInteractiveTime(), t0 + 7.1);
+ EXPECT_EQ(GetInteractiveTime(), t0 + TimeDelta::FromSecondsD(7.1));
}
TEST_F(InteractiveDetectorTest, DCL_FMP_LT_FmpDetect) {
- double t0 = CurrentTimeTicksInSeconds();
+ TimeTicks t0 = CurrentTimeTicks();
SimulateNavigationStart(t0);
// Network is forever quiet for this test.
SetActiveConnections(1);
- SimulateDOMContentLoadedEnd(t0 + 3.0);
- SimulateLongTask(t0 + 7.0, t0 + 7.1);
- SimulateFMPDetected(/* fmp_time */ t0 + 3.0, /* detection_time */ t0 + 5.0);
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(3));
+ SimulateLongTask(t0 + TimeDelta::FromSeconds(7),
+ t0 + TimeDelta::FromSecondsD(7.1));
+ SimulateFMPDetected(/* fmp_time */ t0 + TimeDelta::FromSeconds(3),
+ /* detection_time */ t0 + TimeDelta::FromSeconds(5));
// Run till 5 seconds after long task end.
- RunTillTimestamp((t0 + 7.1) + 5.0 + 0.1);
+ RunTillTimestamp((t0 + TimeDelta::FromSecondsD(7.1)) +
+ TimeDelta::FromSecondsD(5.0 + 0.1));
// TTI reached at long task end.
- EXPECT_EQ(GetInteractiveTime(), t0 + 7.1);
+ EXPECT_EQ(GetInteractiveTime(), t0 + TimeDelta::FromSecondsD(7.1));
}
TEST_F(InteractiveDetectorTest, FMP_FmpDetect_LT_DCL) {
- double t0 = CurrentTimeTicksInSeconds();
+ TimeTicks t0 = CurrentTimeTicks();
SimulateNavigationStart(t0);
// Network is forever quiet for this test.
SetActiveConnections(1);
- SimulateFMPDetected(/* fmp_time */ t0 + 3.0, /* detection_time */ t0 + 4.0);
- SimulateLongTask(t0 + 7.0, t0 + 7.1);
- SimulateDOMContentLoadedEnd(t0 + 8.0);
+ SimulateFMPDetected(/* fmp_time */ t0 + TimeDelta::FromSeconds(3),
+ /* detection_time */ t0 + TimeDelta::FromSeconds(4));
+ SimulateLongTask(t0 + TimeDelta::FromSeconds(7),
+ t0 + TimeDelta::FromSecondsD(7.1));
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(8));
// Run till 5 seconds after long task end.
- RunTillTimestamp((t0 + 7.1) + 5.0 + 0.1);
+ RunTillTimestamp((t0 + TimeDelta::FromSecondsD(7.1)) +
+ TimeDelta::FromSecondsD(5.0 + 0.1));
// TTI reached at DCL. Note that we do not need to wait for DCL + 5 seconds.
- EXPECT_EQ(GetInteractiveTime(), t0 + 8.0);
+ EXPECT_EQ(GetInteractiveTime(), t0 + TimeDelta::FromSeconds(8));
}
TEST_F(InteractiveDetectorTest, DclIsMoreThan5sAfterFMP) {
- double t0 = CurrentTimeTicksInSeconds();
+ TimeTicks t0 = CurrentTimeTicks();
SimulateNavigationStart(t0);
// Network is forever quiet for this test.
SetActiveConnections(1);
- SimulateFMPDetected(/* fmp_time */ t0 + 3.0, /* detection_time */ t0 + 4.0);
- SimulateLongTask(t0 + 7.0, t0 + 7.1); // Long task 1.
- SimulateDOMContentLoadedEnd(t0 + 10.0);
+ SimulateFMPDetected(/* fmp_time */ t0 + TimeDelta::FromSeconds(3),
+ /* detection_time */ t0 + TimeDelta::FromSeconds(4));
+ SimulateLongTask(t0 + TimeDelta::FromSeconds(7),
+ t0 + TimeDelta::FromSecondsD(7.1)); // Long task 1.
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(10));
// Have not reached TTI yet.
- EXPECT_EQ(GetInteractiveTime(), 0.0);
- SimulateLongTask(t0 + 11.0, t0 + 11.1); // Long task 2.
+ EXPECT_EQ(GetInteractiveTime(), TimeTicks());
+ SimulateLongTask(t0 + TimeDelta::FromSeconds(11),
+ t0 + TimeDelta::FromSecondsD(11.1)); // Long task 2.
// Run till long task 2 end + 5 seconds.
- RunTillTimestamp((t0 + 11.1) + 5.0 + 0.1);
+ RunTillTimestamp((t0 + TimeDelta::FromSecondsD(11.1)) +
+ TimeDelta::FromSecondsD(5.0 + 0.1));
// TTI reached at long task 2 end.
- EXPECT_EQ(GetInteractiveTime(), (t0 + 11.1));
+ EXPECT_EQ(GetInteractiveTime(), (t0 + TimeDelta::FromSecondsD(11.1)));
}
TEST_F(InteractiveDetectorTest, NetworkBusyBlocksTTIEvenWhenMainThreadQuiet) {
- double t0 = CurrentTimeTicksInSeconds();
+ TimeTicks t0 = CurrentTimeTicks();
SimulateNavigationStart(t0);
SetActiveConnections(1);
- SimulateDOMContentLoadedEnd(t0 + 2.0);
- SimulateResourceLoadBegin(t0 + 3.4); // Request 2 start.
- SimulateResourceLoadBegin(t0 + 3.5); // Request 3 start. Network busy.
- SimulateFMPDetected(/* fmp_time */ t0 + 3.0, /* detection_time */ t0 + 4.0);
- SimulateLongTask(t0 + 7.0, t0 + 7.1); // Long task 1.
- SimulateResourceLoadEnd(t0 + 12.2); // Network quiet.
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(2));
+ SimulateResourceLoadBegin(t0 +
+ TimeDelta::FromSecondsD(3.4)); // Request 2 start.
+ SimulateResourceLoadBegin(
+ t0 + TimeDelta::FromSecondsD(3.5)); // Request 3 start. Network busy.
+ SimulateFMPDetected(/* fmp_time */ t0 + TimeDelta::FromSeconds(3),
+ /* detection_time */ t0 + TimeDelta::FromSeconds(4));
+ SimulateLongTask(t0 + TimeDelta::FromSeconds(7),
+ t0 + TimeDelta::FromSecondsD(7.1)); // Long task 1.
+ SimulateResourceLoadEnd(t0 +
+ TimeDelta::FromSecondsD(12.2)); // Network quiet.
// Network busy kept page from reaching TTI..
- EXPECT_EQ(GetInteractiveTime(), 0.0);
- SimulateLongTask(t0 + 13.0, t0 + 13.1); // Long task 2.
+ EXPECT_EQ(GetInteractiveTime(), TimeTicks());
+ SimulateLongTask(t0 + TimeDelta::FromSeconds(13),
+ t0 + TimeDelta::FromSecondsD(13.1)); // Long task 2.
// Run till 5 seconds after long task 2 end.
- RunTillTimestamp((t0 + 13.1) + 5.0 + 0.1);
- EXPECT_EQ(GetInteractiveTime(), (t0 + 13.1));
+ RunTillTimestamp((t0 + TimeDelta::FromSecondsD(13.1)) +
+ TimeDelta::FromSecondsD(5.0 + 0.1));
+ EXPECT_EQ(GetInteractiveTime(), (t0 + TimeDelta::FromSecondsD(13.1)));
}
TEST_F(InteractiveDetectorTest, LongEnoughQuietWindowBetweenFMPAndFmpDetect) {
- double t0 = CurrentTimeTicksInSeconds();
+ TimeTicks t0 = CurrentTimeTicks();
SimulateNavigationStart(t0);
SetActiveConnections(1);
- SimulateDOMContentLoadedEnd(t0 + 2.0);
- SimulateLongTask(t0 + 2.1, t0 + 2.2); // Long task 1.
- SimulateLongTask(t0 + 8.2, t0 + 8.3); // Long task 2.
- SimulateResourceLoadBegin(t0 + 8.4); // Request 2 start.
- SimulateResourceLoadBegin(t0 + 8.5); // Request 3 start. Network busy.
- SimulateFMPDetected(/* fmp_time */ t0 + 3.0, /* detection_time */ t0 + 10.0);
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(2));
+ SimulateLongTask(t0 + TimeDelta::FromSecondsD(2.1),
+ t0 + TimeDelta::FromSecondsD(2.2)); // Long task 1.
+ SimulateLongTask(t0 + TimeDelta::FromSecondsD(8.2),
+ t0 + TimeDelta::FromSecondsD(8.3)); // Long task 2.
+ SimulateResourceLoadBegin(t0 +
+ TimeDelta::FromSecondsD(8.4)); // Request 2 start.
+ SimulateResourceLoadBegin(
+ t0 + TimeDelta::FromSecondsD(8.5)); // Request 3 start. Network busy.
+ SimulateFMPDetected(/* fmp_time */ t0 + TimeDelta::FromSeconds(3),
+ /* detection_time */ t0 + TimeDelta::FromSeconds(10));
// Even though network is currently busy and we have long task finishing
// recently, we should be able to detect that the page already achieved TTI at
// FMP.
- EXPECT_EQ(GetInteractiveTime(), t0 + 3.0);
+ EXPECT_EQ(GetInteractiveTime(), t0 + TimeDelta::FromSeconds(3));
}
TEST_F(InteractiveDetectorTest, NetworkBusyEndIsNotTTI) {
- double t0 = CurrentTimeTicksInSeconds();
+ TimeTicks t0 = CurrentTimeTicks();
SimulateNavigationStart(t0);
SetActiveConnections(1);
- SimulateDOMContentLoadedEnd(t0 + 2.0);
- SimulateResourceLoadBegin(t0 + 3.4); // Request 2 start.
- SimulateResourceLoadBegin(t0 + 3.5); // Request 3 start. Network busy.
- SimulateFMPDetected(/* fmp_time */ t0 + 3.0, /* detection_time */ t0 + 4.0);
- SimulateLongTask(t0 + 7.0, t0 + 7.1); // Long task 1.
- SimulateLongTask(t0 + 13.0, t0 + 13.1); // Long task 2.
- SimulateResourceLoadEnd(t0 + 14.0); // Network quiet.
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(2));
+ SimulateResourceLoadBegin(t0 +
+ TimeDelta::FromSecondsD(3.4)); // Request 2 start.
+ SimulateResourceLoadBegin(
+ t0 + TimeDelta::FromSecondsD(3.5)); // Request 3 start. Network busy.
+ SimulateFMPDetected(/* fmp_time */ t0 + TimeDelta::FromSeconds(3),
+ /* detection_time */ t0 + TimeDelta::FromSeconds(4));
+ SimulateLongTask(t0 + TimeDelta::FromSeconds(7),
+ t0 + TimeDelta::FromSecondsD(7.1)); // Long task 1.
+ SimulateLongTask(t0 + TimeDelta::FromSeconds(13),
+ t0 + TimeDelta::FromSecondsD(13.1)); // Long task 2.
+ SimulateResourceLoadEnd(t0 + TimeDelta::FromSeconds(14)); // Network quiet.
// Run till 5 seconds after network busy end.
- RunTillTimestamp((t0 + 14.0) + 5.0 + 0.1);
+ RunTillTimestamp((t0 + TimeDelta::FromSeconds(14)) +
+ TimeDelta::FromSecondsD(5.0 + 0.1));
// TTI reached at long task 2 end, NOT at network busy end.
- EXPECT_EQ(GetInteractiveTime(), t0 + 13.1);
+ EXPECT_EQ(GetInteractiveTime(), t0 + TimeDelta::FromSecondsD(13.1));
}
TEST_F(InteractiveDetectorTest, LateLongTaskWithLateFMPDetection) {
- double t0 = CurrentTimeTicksInSeconds();
+ TimeTicks t0 = CurrentTimeTicks();
SimulateNavigationStart(t0);
SetActiveConnections(1);
- SimulateDOMContentLoadedEnd(t0 + 2.0);
- SimulateResourceLoadBegin(t0 + 3.4); // Request 2 start.
- SimulateResourceLoadBegin(t0 + 3.5); // Request 3 start. Network busy.
- SimulateLongTask(t0 + 7.0, t0 + 7.1); // Long task 1.
- SimulateResourceLoadEnd(t0 + 8.0); // Network quiet.
- SimulateLongTask(t0 + 14.0, t0 + 14.1); // Long task 2.
- SimulateFMPDetected(/* fmp_time */ t0 + 3.0, /* detection_time */ t0 + 20.0);
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(2));
+ SimulateResourceLoadBegin(t0 +
+ TimeDelta::FromSecondsD(3.4)); // Request 2 start.
+ SimulateResourceLoadBegin(
+ t0 + TimeDelta::FromSecondsD(3.5)); // Request 3 start. Network busy.
+ SimulateLongTask(t0 + TimeDelta::FromSeconds(7),
+ t0 + TimeDelta::FromSecondsD(7.1)); // Long task 1.
+ SimulateResourceLoadEnd(t0 + TimeDelta::FromSeconds(8)); // Network quiet.
+ SimulateLongTask(t0 + TimeDelta::FromSeconds(14),
+ t0 + TimeDelta::FromSecondsD(14.1)); // Long task 2.
+ SimulateFMPDetected(/* fmp_time */ t0 + TimeDelta::FromSeconds(3),
+ /* detection_time */ t0 + TimeDelta::FromSeconds(20));
// TTI reached at long task 1 end, NOT at long task 2 end.
- EXPECT_EQ(GetInteractiveTime(), t0 + 7.1);
+ EXPECT_EQ(GetInteractiveTime(), t0 + TimeDelta::FromSecondsD(7.1));
}
TEST_F(InteractiveDetectorTest, IntermittentNetworkBusyBlocksTTI) {
- double t0 = CurrentTimeTicksInSeconds();
+ TimeTicks t0 = CurrentTimeTicks();
SimulateNavigationStart(t0);
SetActiveConnections(1);
- SimulateDOMContentLoadedEnd(t0 + 2.0);
- SimulateFMPDetected(/* fmp_time */ t0 + 3.0, /* detection_time */ t0 + 4.0);
- SimulateLongTask(t0 + 7.0, t0 + 7.1); // Long task 1.
- SimulateResourceLoadBegin(t0 + 7.9); // Active connections: 2
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(2));
+ SimulateFMPDetected(/* fmp_time */ t0 + TimeDelta::FromSeconds(3),
+ /* detection_time */ t0 + TimeDelta::FromSeconds(4));
+ SimulateLongTask(t0 + TimeDelta::FromSeconds(7),
+ t0 + TimeDelta::FromSecondsD(7.1)); // Long task 1.
+ SimulateResourceLoadBegin(
+ t0 + TimeDelta::FromSecondsD(7.9)); // Active connections: 2
// Network busy start.
- SimulateResourceLoadBegin(t0 + 8.0); // Active connections: 3.
+ SimulateResourceLoadBegin(
+ t0 + TimeDelta::FromSeconds(8)); // Active connections: 3.
// Network busy end.
- SimulateResourceLoadEnd(t0 + 8.5); // Active connections: 2.
+ SimulateResourceLoadEnd(
+ t0 + TimeDelta::FromSecondsD(8.5)); // Active connections: 2.
// Network busy start.
- SimulateResourceLoadBegin(t0 + 11.0); // Active connections: 3.
+ SimulateResourceLoadBegin(
+ t0 + TimeDelta::FromSeconds(11)); // Active connections: 3.
// Network busy end.
- SimulateResourceLoadEnd(t0 + 12.0); // Active connections: 2.
- SimulateLongTask(t0 + 14.0, t0 + 14.1); // Long task 2.
+ SimulateResourceLoadEnd(
+ t0 + TimeDelta::FromSeconds(12)); // Active connections: 2.
+ SimulateLongTask(t0 + TimeDelta::FromSeconds(14),
+ t0 + TimeDelta::FromSecondsD(14.1)); // Long task 2.
// Run till 5 seconds after long task 2 end.
- RunTillTimestamp((t0 + 14.1) + 5.0 + 0.1);
+ RunTillTimestamp((t0 + TimeDelta::FromSecondsD(14.1)) +
+ TimeDelta::FromSecondsD(5.0 + 0.1));
// TTI reached at long task 2 end.
- EXPECT_EQ(GetInteractiveTime(), t0 + 14.1);
+ EXPECT_EQ(GetInteractiveTime(), t0 + TimeDelta::FromSecondsD(14.1));
}
TEST_F(InteractiveDetectorTest, InvalidatingUserInput) {
- double t0 = CurrentTimeTicksInSeconds();
+ TimeTicks t0 = CurrentTimeTicks();
SimulateNavigationStart(t0);
// Network is forever quiet for this test.
SetActiveConnections(1);
- SimulateDOMContentLoadedEnd(t0 + 2.0);
- SimulateFMPDetected(/* fmp_time */ t0 + 3.0, /* detection_time */ t0 + 4.0);
- SimulateInteractiveInvalidatingInput(t0 + 5.0);
- SimulateLongTask(t0 + 7.0, t0 + 7.1); // Long task 1.
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(2));
+ SimulateFMPDetected(/* fmp_time */ t0 + TimeDelta::FromSeconds(3),
+ /* detection_time */ t0 + TimeDelta::FromSeconds(4));
+ SimulateInteractiveInvalidatingInput(t0 + TimeDelta::FromSeconds(5));
+ SimulateLongTask(t0 + TimeDelta::FromSeconds(7),
+ t0 + TimeDelta::FromSecondsD(7.1)); // Long task 1.
// Run till 5 seconds after long task 2 end.
- RunTillTimestamp((t0 + 7.1) + 5.0 + 0.1);
+ RunTillTimestamp((t0 + TimeDelta::FromSecondsD(7.1)) +
+ TimeDelta::FromSecondsD(5.0 + 0.1));
// We still detect interactive time on the blink side even if there is an
// invalidating user input. Page Load Metrics filters out this value in the
// browser process for UMA reporting.
- EXPECT_EQ(GetInteractiveTime(), t0 + 7.1);
- EXPECT_EQ(TimeTicksInSeconds(GetDetector()->GetFirstInvalidatingInputTime()),
- t0 + 5.0);
+ EXPECT_EQ(GetInteractiveTime(), t0 + TimeDelta::FromSecondsD(7.1));
+ EXPECT_EQ(GetDetector()->GetFirstInvalidatingInputTime(),
+ t0 + TimeDelta::FromSeconds(5));
}
TEST_F(InteractiveDetectorTest, InvalidatingUserInputClampedAtNavStart) {
- double t0 = CurrentTimeTicksInSeconds();
+ TimeTicks t0 = CurrentTimeTicks();
SimulateNavigationStart(t0);
// Network is forever quiet for this test.
SetActiveConnections(1);
- SimulateDOMContentLoadedEnd(t0 + 2.0);
- SimulateFMPDetected(/* fmp_time */ t0 + 3.0, /* detection_time */ t0 + 4.0);
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(2));
+ SimulateFMPDetected(/* fmp_time */ t0 + TimeDelta::FromSeconds(3),
+ /* detection_time */ t0 + TimeDelta::FromSeconds(4));
// Invalidating input timestamp is earlier than navigation start.
- SimulateInteractiveInvalidatingInput(t0 - 10.0);
+ SimulateInteractiveInvalidatingInput(t0 - TimeDelta::FromSeconds(10));
// Run till 5 seconds after FMP.
- RunTillTimestamp((t0 + 7.1) + 5.0 + 0.1);
- EXPECT_EQ(GetInteractiveTime(), t0 + 3.0); // TTI at FMP.
+ RunTillTimestamp((t0 + TimeDelta::FromSecondsD(7.1)) +
+ TimeDelta::FromSecondsD(5.0 + 0.1));
+ EXPECT_EQ(GetInteractiveTime(),
+ t0 + TimeDelta::FromSeconds(3)); // TTI at FMP.
// Invalidating input timestamp is clamped at navigation start.
- EXPECT_EQ(TimeTicksInSeconds(GetDetector()->GetFirstInvalidatingInputTime()),
- t0);
+ EXPECT_EQ(GetDetector()->GetFirstInvalidatingInputTime(), t0);
}
TEST_F(InteractiveDetectorTest, InvalidatedFMP) {
- double t0 = CurrentTimeTicksInSeconds();
+ TimeTicks t0 = CurrentTimeTicks();
SimulateNavigationStart(t0);
// Network is forever quiet for this test.
SetActiveConnections(1);
- SimulateInteractiveInvalidatingInput(t0 + 1.0);
- SimulateDOMContentLoadedEnd(t0 + 2.0);
- RunTillTimestamp(t0 + 4.0); // FMP Detection time.
+ SimulateInteractiveInvalidatingInput(t0 + TimeDelta::FromSeconds(1));
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(2));
+ RunTillTimestamp(t0 + TimeDelta::FromSeconds(4)); // FMP Detection time.
GetDetector()->OnFirstMeaningfulPaintDetected(
- TimeTicksFromSeconds(t0 + 3.0),
+ t0 + TimeDelta::FromSeconds(3),
FirstMeaningfulPaintDetector::kHadUserInput);
// Run till 5 seconds after FMP.
- RunTillTimestamp((t0 + 3.0) + 5.0 + 0.1);
+ RunTillTimestamp((t0 + TimeDelta::FromSeconds(3)) +
+ TimeDelta::FromSecondsD(5.0 + 0.1));
// Since FMP was invalidated, we do not have TTI or TTI Detection Time.
- EXPECT_EQ(GetInteractiveTime(), 0.0);
+ EXPECT_EQ(GetInteractiveTime(), TimeTicks());
EXPECT_EQ(TimeTicksInSeconds(GetDetector()->GetInteractiveDetectionTime()),
0.0);
// Invalidating input timestamp is available.
- EXPECT_EQ(TimeTicksInSeconds(GetDetector()->GetFirstInvalidatingInputTime()),
- t0 + 1.0);
+ EXPECT_EQ(GetDetector()->GetFirstInvalidatingInputTime(),
+ t0 + TimeDelta::FromSeconds(1));
}
TEST_F(InteractiveDetectorTest, TaskLongerThan5sBlocksTTI) {
- double t0 = CurrentTimeTicksInSeconds();
- GetDetector()->SetNavigationStartTime(TimeTicksFromSeconds(t0));
+ TimeTicks t0 = CurrentTimeTicks();
+ GetDetector()->SetNavigationStartTime(t0);
- SimulateDOMContentLoadedEnd(t0 + 2.0);
- SimulateFMPDetected(t0 + 3.0, t0 + 4.0);
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(2));
+ SimulateFMPDetected(t0 + TimeDelta::FromSeconds(3),
+ t0 + TimeDelta::FromSeconds(4));
// Post a task with 6 seconds duration.
PostCrossThreadTask(
@@ -473,16 +529,16 @@ TEST_F(InteractiveDetectorTest, TaskLongerThan5sBlocksTTI) {
// We should be able to detect TTI 5s after the end of long task.
platform_->RunForPeriodSeconds(5.1);
- EXPECT_EQ(TimeTicksInSeconds(GetDetector()->GetInteractiveTime()),
- GetDummyTaskEndTime());
+ EXPECT_EQ(GetDetector()->GetInteractiveTime(), GetDummyTaskEndTime());
}
TEST_F(InteractiveDetectorTest, LongTaskAfterTTIDoesNothing) {
- double t0 = CurrentTimeTicksInSeconds();
- GetDetector()->SetNavigationStartTime(TimeTicksFromSeconds(t0));
+ TimeTicks t0 = CurrentTimeTicks();
+ GetDetector()->SetNavigationStartTime(t0);
- SimulateDOMContentLoadedEnd(2.0);
- SimulateFMPDetected(t0 + 3.0, t0 + 4.0);
+ SimulateDOMContentLoadedEnd(t0 + TimeDelta::FromSeconds(2));
+ SimulateFMPDetected(t0 + TimeDelta::FromSeconds(3),
+ t0 + TimeDelta::FromSeconds(4));
// Long task 1.
PostCrossThreadTask(
@@ -492,11 +548,10 @@ TEST_F(InteractiveDetectorTest, LongTaskAfterTTIDoesNothing) {
platform_->RunUntilIdle();
- double long_task_1_end_time = GetDummyTaskEndTime();
+ TimeTicks long_task_1_end_time = GetDummyTaskEndTime();
// We should be able to detect TTI 5s after the end of long task.
platform_->RunForPeriodSeconds(5.1);
- EXPECT_EQ(TimeTicksInSeconds(GetDetector()->GetInteractiveTime()),
- long_task_1_end_time);
+ EXPECT_EQ(GetDetector()->GetInteractiveTime(), long_task_1_end_time);
// Long task 2.
PostCrossThreadTask(
@@ -508,8 +563,7 @@ TEST_F(InteractiveDetectorTest, LongTaskAfterTTIDoesNothing) {
// Wait 5 seconds to see if TTI time changes.
platform_->RunForPeriodSeconds(5.1);
// TTI time should not change.
- EXPECT_EQ(TimeTicksInSeconds(GetDetector()->GetInteractiveTime()),
- long_task_1_end_time);
+ EXPECT_EQ(GetDetector()->GetInteractiveTime(), long_task_1_end_time);
}
} // namespace blink
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 21fc2397f15..cd77dabebe5 100644
--- a/chromium/third_party/blink/renderer/core/loader/link_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/link_loader.cc
@@ -47,15 +47,17 @@
#include "third_party/blink/renderer/core/html/parser/html_srcset_parser.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
+#include "third_party/blink/renderer/core/loader/importance_attribute.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h"
#include "third_party/blink/renderer/core/loader/network_hints_interface.h"
#include "third_party/blink/renderer/core/loader/private/prerender_handle.h"
+#include "third_party/blink/renderer/core/loader/resource/css_style_sheet_resource.h"
#include "third_party/blink/renderer/core/loader/resource/link_fetch_resource.h"
#include "third_party/blink/renderer/core/loader/subresource_integrity_helper.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/core/script/module_script.h"
#include "third_party/blink/renderer/core/script/script_loader.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_client.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_finish_observer.h"
@@ -83,6 +85,11 @@ static unsigned PrerenderRelTypesFromRelAttribute(
return result;
}
+// TODO(domfarolino)
+// Eventually we'll want to support an |importance| value on
+// LinkHeaders. We can communicate a header's importance value
+// to LinkLoadParameters here, likely after modifying the LinkHeader
+// class. See https://crbug.com/821464 for info on Priority Hints.
LinkLoadParameters::LinkLoadParameters(const LinkHeader& header,
const KURL& base_url)
: rel(LinkRelAttribute(header.Rel())),
@@ -345,7 +352,8 @@ static Resource* PreloadIfNeeded(const LinkLoadParameters& params,
Document& document,
const KURL& base_url,
LinkCaller caller,
- ViewportDescription* viewport_description) {
+ ViewportDescription* viewport_description,
+ ParserDisposition parser_disposition) {
if (!document.Loader() || !params.rel.IsLinkPreload())
return nullptr;
@@ -408,8 +416,12 @@ static Resource* PreloadIfNeeded(const LinkLoadParameters& params,
params.referrer_policy, url, document.OutgoingReferrer()));
}
+ resource_request.SetFetchImportanceMode(
+ GetFetchImportanceAttributeValue(params.importance));
+
ResourceLoaderOptions options;
options.initiator_info.name = FetchInitiatorTypeNames::link;
+ options.parser_disposition = parser_disposition;
FetchParameters link_fetch_params(resource_request, options);
link_fetch_params.SetCharset(document.Encoding());
@@ -492,6 +504,8 @@ static void ModulePreloadIfNeeded(const LinkLoadParameters& params,
// |document| is the node document here, and its context document is the
// relevant settings object.
Document* context_document = document.ContextDocument();
+ auto* settings_object =
+ new FetchClientSettingsObjectSnapshot(*context_document);
Modulator* modulator =
Modulator::From(ToScriptStateForMainWorld(context_document->GetFrame()));
@@ -520,23 +534,29 @@ static void ModulePreloadIfNeeded(const LinkLoadParameters& params,
SubresourceIntegrityHelper::DoReport(document, report_info);
}
- // Step 9. "Let options be a script fetch options whose cryptographic nonce is
- // cryptographic nonce, integrity metadata is integrity metadata, parser
- // metadata is "not-parser-inserted", and credentials mode is credentials
- // mode." [spec text]
+ // Step 9. "Let referrer policy be the current state of the element's
+ // referrerpolicy attribute." [spec text]
+ // |referrer_policy| parameter is the value of the referrerpolicy attribute.
+
+ // Step 10. "Let options be a script fetch options whose cryptographic nonce
+ // is cryptographic nonce, integrity metadata is integrity metadata, parser
+ // metadata is "not-parser-inserted", credentials mode is credentials mode,
+ // and referrer policy is referrer policy." [spec text]
ModuleScriptFetchRequest request(
params.href, destination,
ScriptFetchOptions(params.nonce, integrity_metadata, params.integrity,
- kNotParserInserted, credentials_mode),
- Referrer::NoReferrer(), params.referrer_policy,
+ kNotParserInserted, credentials_mode,
+ params.referrer_policy),
+ Referrer(Referrer::NoReferrer(), params.referrer_policy),
TextPosition::MinimumPosition());
- // Step 10. "Fetch a single module script given url, settings object,
+ // Step 11. "Fetch a single module script given url, settings object,
// 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, ModuleGraphLevel::kDependentModuleFetch,
- link_loader);
+ modulator->FetchSingle(request, settings_object,
+ ModuleGraphLevel::kDependentModuleFetch,
+ ModuleScriptCustomFetchType::kNone, link_loader);
Settings* settings = document.GetSettings();
if (settings && settings->GetLogPreload()) {
@@ -562,16 +582,11 @@ static Resource* PrefetchIfNeeded(const LinkLoadParameters& params,
params.referrer_policy, params.href, document.OutgoingReferrer()));
}
+ resource_request.SetFetchImportanceMode(
+ GetFetchImportanceAttributeValue(params.importance));
+
ResourceLoaderOptions options;
options.initiator_info.name = FetchInitiatorTypeNames::link;
- auto* service = document.GetFrame()->PrefetchURLLoaderService();
- if (service) {
- network::mojom::blink::URLLoaderFactoryPtr prefetch_url_loader_factory;
- service->GetFactory(mojo::MakeRequest(&prefetch_url_loader_factory));
- options.url_loader_factory = base::MakeRefCounted<
- base::RefCountedData<network::mojom::blink::URLLoaderFactoryPtr>>(
- std::move(prefetch_url_loader_factory));
- }
FetchParameters link_fetch_params(resource_request, options);
if (params.cross_origin != kCrossOriginAttributeNotSet) {
@@ -624,7 +639,7 @@ void LinkLoader::LoadLinksFromHeader(
: nullptr;
PreloadIfNeeded(params, *document, base_url, kLinkCalledFromHeader,
- viewport_description);
+ viewport_description, kNotParserInserted);
PrefetchIfNeeded(params, *document);
ModulePreloadIfNeeded(params, *document, viewport_description, nullptr);
}
@@ -651,8 +666,9 @@ bool LinkLoader::LoadLink(
PreconnectIfNeeded(params, &document, document.GetFrame(),
network_hints_interface, kLinkCalledFromMarkup);
- Resource* resource = PreloadIfNeeded(params, document, NullURL(),
- kLinkCalledFromMarkup, nullptr);
+ Resource* resource = PreloadIfNeeded(
+ params, document, NullURL(), kLinkCalledFromMarkup, nullptr,
+ client_->IsLinkCreatedByParser() ? kParserInserted : kNotParserInserted);
if (!resource) {
resource = PrefetchIfNeeded(params, document);
}
@@ -679,6 +695,55 @@ bool LinkLoader::LoadLink(
return true;
}
+void LinkLoader::LoadStylesheet(const LinkLoadParameters& params,
+ const AtomicString& local_name,
+ const WTF::TextEncoding& charset,
+ FetchParameters::DeferOption defer_option,
+ Document& document,
+ ResourceClient* link_client) {
+ ResourceRequest resource_request(document.CompleteURL(params.href));
+ ReferrerPolicy referrer_policy = params.referrer_policy;
+ if (referrer_policy != kReferrerPolicyDefault) {
+ resource_request.SetHTTPReferrer(SecurityPolicy::GenerateReferrer(
+ referrer_policy, params.href, document.OutgoingReferrer()));
+ }
+
+ mojom::FetchImportanceMode importance_mode =
+ GetFetchImportanceAttributeValue(params.importance);
+ DCHECK(importance_mode == mojom::FetchImportanceMode::kImportanceAuto ||
+ RuntimeEnabledFeatures::PriorityHintsEnabled());
+ resource_request.SetFetchImportanceMode(importance_mode);
+
+ ResourceLoaderOptions options;
+ options.initiator_info.name = local_name;
+ FetchParameters link_fetch_params(resource_request, options);
+ link_fetch_params.SetCharset(charset);
+
+ link_fetch_params.SetDefer(defer_option);
+
+ link_fetch_params.SetContentSecurityPolicyNonce(params.nonce);
+
+ CrossOriginAttributeValue cross_origin = params.cross_origin;
+ if (cross_origin != kCrossOriginAttributeNotSet) {
+ link_fetch_params.SetCrossOriginAccessControl(document.GetSecurityOrigin(),
+ cross_origin);
+ }
+
+ String integrity_attr = params.integrity;
+ if (!integrity_attr.IsEmpty()) {
+ IntegrityMetadataSet metadata_set;
+ SubresourceIntegrity::ParseIntegrityAttribute(
+ integrity_attr, SubresourceIntegrityHelper::GetFeatures(&document),
+ metadata_set);
+ link_fetch_params.SetIntegrityMetadata(metadata_set);
+ link_fetch_params.MutableResourceRequest().SetFetchIntegrity(
+ integrity_attr);
+ }
+
+ CSSStyleSheetResource::Fetch(link_fetch_params, document.Fetcher(),
+ link_client);
+}
+
void LinkLoader::DispatchLinkLoadingErroredAsync() {
client_->GetLoadingTaskRunner()->PostTask(
FROM_HERE, WTF::Bind(&LinkLoaderClient::LinkLoadingErrored,
diff --git a/chromium/third_party/blink/renderer/core/loader/link_loader.h b/chromium/third_party/blink/renderer/core/loader/link_loader.h
index efc7836f127..338bc6cffa4 100644
--- a/chromium/third_party/blink/renderer/core/loader/link_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/link_loader.h
@@ -38,6 +38,7 @@
#include "third_party/blink/renderer/core/loader/link_loader_client.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/platform/cross_origin_attribute_value.h"
+#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/prerender_client.h"
@@ -59,6 +60,7 @@ struct LinkLoadParameters {
const String& media,
const String& nonce,
const String& integrity,
+ const String& importance,
const ReferrerPolicy& referrer_policy,
const KURL& href,
const String& srcset,
@@ -70,6 +72,7 @@ struct LinkLoadParameters {
media(media),
nonce(nonce),
integrity(integrity),
+ importance(importance),
referrer_policy(referrer_policy),
href(href),
srcset(srcset),
@@ -83,6 +86,7 @@ struct LinkLoadParameters {
String media;
String nonce;
String integrity;
+ String importance;
ReferrerPolicy referrer_policy;
KURL href;
String srcset;
@@ -111,6 +115,12 @@ class CORE_EXPORT LinkLoader final : public SingleModuleClient,
bool LoadLink(const LinkLoadParameters&,
Document&,
const NetworkHintsInterface&);
+ void LoadStylesheet(const LinkLoadParameters&,
+ const AtomicString&,
+ const WTF::TextEncoding&,
+ FetchParameters::DeferOption,
+ Document&,
+ ResourceClient*);
void DispatchLinkLoadingErroredAsync();
enum CanLoadResources {
diff --git a/chromium/third_party/blink/renderer/core/loader/link_loader_client.h b/chromium/third_party/blink/renderer/core/loader/link_loader_client.h
index c08098a08e8..28e042239dd 100644
--- a/chromium/third_party/blink/renderer/core/loader/link_loader_client.h
+++ b/chromium/third_party/blink/renderer/core/loader/link_loader_client.h
@@ -53,6 +53,7 @@ class CORE_EXPORT LinkLoaderClient : public GarbageCollectedMixin {
virtual void DidStopLinkPrerender() = 0;
virtual void DidSendLoadForLinkPrerender() = 0;
virtual void DidSendDOMContentLoadedForLinkPrerender() = 0;
+ virtual bool IsLinkCreatedByParser() = 0;
virtual scoped_refptr<base::SingleThreadTaskRunner>
GetLoadingTaskRunner() = 0;
diff --git a/chromium/third_party/blink/renderer/core/loader/link_loader_test.cc b/chromium/third_party/blink/renderer/core/loader/link_loader_test.cc
index e8fcedd35e3..a0d6e29b89c 100644
--- a/chromium/third_party/blink/renderer/core/loader/link_loader_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/link_loader_test.cc
@@ -43,6 +43,7 @@ class MockLinkLoaderClient final
}
bool ShouldLoadLink() override { return should_load_; }
+ bool IsLinkCreatedByParser() override { return true; }
void LinkLoaded() override {}
void LinkLoadingErrored() override {}
@@ -186,8 +187,9 @@ TEST_P(LinkLoaderPreloadTest, Preload) {
const auto& test_case = GetParam();
LinkLoadParameters params(
LinkRelAttribute("preload"), kCrossOriginAttributeNotSet, String(),
- test_case.as, String(), String(), String(), kReferrerPolicyDefault,
- KURL(NullURL(), test_case.href), String(), String());
+ test_case.as, String(), String(), String(), String(),
+ kReferrerPolicyDefault, KURL(NullURL(), test_case.href), String(),
+ String());
Expectations expectations = {
test_case.priority, test_case.context, test_case.expecting_load,
test_case.expecting_load ? params.href : NullURL(),
@@ -264,8 +266,9 @@ TEST_P(LinkLoaderPreloadMimeTypeTest, Preload) {
const auto& test_case = GetParam();
LinkLoadParameters params(
LinkRelAttribute("preload"), kCrossOriginAttributeNotSet, test_case.type,
- test_case.as, String(), String(), String(), kReferrerPolicyDefault,
- KURL(NullURL(), test_case.href), String(), String());
+ test_case.as, String(), String(), String(), String(),
+ kReferrerPolicyDefault, KURL(NullURL(), test_case.href), String(),
+ String());
Expectations expectations = {
test_case.priority, test_case.context, test_case.expecting_load,
test_case.expecting_load ? params.href : NullURL(),
@@ -297,8 +300,9 @@ TEST_P(LinkLoaderPreloadMediaTest, Preload) {
const auto& test_case = GetParam();
LinkLoadParameters params(
LinkRelAttribute("preload"), kCrossOriginAttributeNotSet, "image/gif",
- "image", test_case.media, String(), String(), kReferrerPolicyDefault,
- KURL(NullURL(), "http://example.test/cat.gif"), String(), String());
+ "image", test_case.media, String(), String(), String(),
+ kReferrerPolicyDefault, KURL(NullURL(), "http://example.test/cat.gif"),
+ String(), String());
Expectations expectations = {
test_case.priority, WebURLRequest::kRequestContextImage,
test_case.link_loader_should_load_value,
@@ -327,7 +331,7 @@ TEST_P(LinkLoaderPreloadReferrerPolicyTest, Preload) {
const ReferrerPolicy referrer_policy = GetParam();
LinkLoadParameters params(
LinkRelAttribute("preload"), kCrossOriginAttributeNotSet, "image/gif",
- "image", String(), String(), String(), referrer_policy,
+ "image", String(), String(), String(), String(), referrer_policy,
KURL(NullURL(), "http://example.test/cat.gif"), String(), String());
Expectations expectations = {ResourceLoadPriority::kLow,
WebURLRequest::kRequestContextImage, true,
@@ -364,8 +368,9 @@ TEST_P(LinkLoaderPreloadNonceTest, Preload) {
kContentSecurityPolicyHeaderSourceHTTP);
LinkLoadParameters params(
LinkRelAttribute("preload"), kCrossOriginAttributeNotSet, String(),
- "script", String(), test_case.nonce, String(), kReferrerPolicyDefault,
- KURL(NullURL(), "http://example.test/cat.js"), String(), String());
+ "script", String(), test_case.nonce, String(), String(),
+ kReferrerPolicyDefault, KURL(NullURL(), "http://example.test/cat.js"),
+ String(), String());
Expectations expectations = {
ResourceLoadPriority::kHigh, WebURLRequest::kRequestContextScript,
test_case.expecting_load,
@@ -416,7 +421,7 @@ TEST_P(LinkLoaderPreloadSrcsetTest, Preload) {
test_case.scale_factor);
LinkLoadParameters params(
LinkRelAttribute("preload"), kCrossOriginAttributeNotSet, "image/gif",
- "image", String(), String(), String(), kReferrerPolicyDefault,
+ "image", String(), String(), String(), String(), kReferrerPolicyDefault,
KURL(NullURL(), test_case.href), test_case.srcset, test_case.sizes);
Expectations expectations = {
ResourceLoadPriority::kLow, WebURLRequest::kRequestContextImage, true,
@@ -462,9 +467,12 @@ class ModulePreloadTestModulator final : public DummyModulator {
ModulePreloadTestModulator(const ModulePreloadTestParams* params)
: params_(params), fetched_(false) {}
- void FetchSingle(const ModuleScriptFetchRequest& request,
- ModuleGraphLevel,
- SingleModuleClient*) override {
+ void FetchSingle(
+ const ModuleScriptFetchRequest& request,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
+ ModuleGraphLevel,
+ ModuleScriptCustomFetchType custom_fetch_type,
+ SingleModuleClient*) override {
fetched_ = true;
EXPECT_EQ(KURL(NullURL(), params_->href), request.Url());
@@ -472,10 +480,10 @@ class ModulePreloadTestModulator final : public DummyModulator {
EXPECT_EQ(kNotParserInserted, request.Options().ParserState());
EXPECT_EQ(params_->expected_credentials_mode,
request.Options().CredentialsMode());
- EXPECT_EQ(AtomicString(), request.GetReferrer());
- EXPECT_EQ(params_->referrer_policy, request.GetReferrerPolicy());
+ EXPECT_EQ(Referrer::NoReferrer(), request.GetReferrer().referrer);
EXPECT_EQ(params_->integrity,
request.Options().GetIntegrityAttributeValue());
+ EXPECT_EQ(ModuleScriptCustomFetchType::kNone, custom_fetch_type);
}
bool fetched() const { return fetched_; }
@@ -501,8 +509,8 @@ TEST_P(LinkLoaderModulePreloadTest, ModulePreload) {
LinkLoadParameters params(
LinkRelAttribute("modulepreload"), test_case.cross_origin,
String() /* type */, String() /* as */, String() /* media */,
- test_case.nonce, test_case.integrity, test_case.referrer_policy, href_url,
- String() /* srcset */, String() /* sizes */);
+ test_case.nonce, test_case.integrity, String(), test_case.referrer_policy,
+ href_url, String() /* srcset */, String() /* sizes */);
loader->LoadLink(params, dummy_page_holder->GetDocument(),
NetworkHintsMock());
ASSERT_EQ(test_case.expecting_load, modulator->fetched());
@@ -543,10 +551,11 @@ TEST(LinkLoaderTest, Prefetch) {
LinkLoader* loader = LinkLoader::Create(loader_client.Get());
KURL href_url = KURL(NullURL(), test_case.href);
URLTestHelpers::RegisterMockedErrorURLLoad(href_url);
- LinkLoadParameters params(
- LinkRelAttribute("prefetch"), kCrossOriginAttributeNotSet,
- test_case.type, "", test_case.media, "", "", test_case.referrer_policy,
- href_url, String() /* srcset */, String() /* sizes */);
+ LinkLoadParameters params(LinkRelAttribute("prefetch"),
+ kCrossOriginAttributeNotSet, test_case.type, "",
+ test_case.media, "", "", String(),
+ test_case.referrer_policy, href_url,
+ String() /* srcset */, String() /* sizes */);
loader->LoadLink(params, dummy_page_holder->GetDocument(),
NetworkHintsMock());
ASSERT_TRUE(dummy_page_holder->GetDocument().Fetcher());
@@ -590,10 +599,11 @@ TEST(LinkLoaderTest, DNSPrefetch) {
LinkLoader* loader = LinkLoader::Create(loader_client.Get());
KURL href_url = KURL(KURL(String("http://example.com")), test_case.href);
NetworkHintsMock network_hints;
- LinkLoadParameters params(
- LinkRelAttribute("dns-prefetch"), kCrossOriginAttributeNotSet, String(),
- String(), String(), String(), String(), kReferrerPolicyDefault,
- href_url, String() /* srcset */, String() /* sizes */);
+ LinkLoadParameters params(LinkRelAttribute("dns-prefetch"),
+ kCrossOriginAttributeNotSet, String(), String(),
+ String(), String(), String(), String(),
+ kReferrerPolicyDefault, href_url,
+ String() /* srcset */, String() /* sizes */);
loader->LoadLink(params, dummy_page_holder->GetDocument(), network_hints);
EXPECT_FALSE(network_hints.DidPreconnect());
EXPECT_EQ(test_case.should_load, network_hints.DidDnsPrefetch());
@@ -625,10 +635,11 @@ TEST(LinkLoaderTest, Preconnect) {
LinkLoader* loader = LinkLoader::Create(loader_client.Get());
KURL href_url = KURL(KURL(String("http://example.com")), test_case.href);
NetworkHintsMock network_hints;
- LinkLoadParameters params(
- LinkRelAttribute("preconnect"), test_case.cross_origin, String(),
- String(), String(), String(), String(), kReferrerPolicyDefault,
- href_url, String() /* srcset */, String() /* sizes */);
+ LinkLoadParameters params(LinkRelAttribute("preconnect"),
+ test_case.cross_origin, String(), String(),
+ String(), String(), String(), String(),
+ kReferrerPolicyDefault, href_url,
+ String() /* srcset */, String() /* sizes */);
loader->LoadLink(params, dummy_page_holder->GetDocument(), network_hints);
EXPECT_EQ(test_case.should_load, network_hints.DidPreconnect());
EXPECT_EQ(test_case.is_https, network_hints.IsHTTPS());
@@ -647,10 +658,11 @@ TEST(LinkLoaderTest, PreloadAndPrefetch) {
LinkLoader* loader = LinkLoader::Create(loader_client.Get());
KURL href_url = KURL(KURL(), "https://www.example.com/");
URLTestHelpers::RegisterMockedErrorURLLoad(href_url);
- LinkLoadParameters params(
- LinkRelAttribute("preload prefetch"), kCrossOriginAttributeNotSet,
- "application/javascript", "script", "", "", "", kReferrerPolicyDefault,
- href_url, String() /* srcset */, String() /* sizes */);
+ LinkLoadParameters params(LinkRelAttribute("preload prefetch"),
+ kCrossOriginAttributeNotSet,
+ "application/javascript", "script", "", "", "",
+ String(), kReferrerPolicyDefault, href_url,
+ String() /* srcset */, String() /* sizes */);
loader->LoadLink(params, dummy_page_holder->GetDocument(),
NetworkHintsMock());
ASSERT_EQ(1, fetcher->CountPreloads());
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 0b0d7cf9272..37a297c5d15 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
@@ -43,6 +43,8 @@
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#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/workers/worker_content_settings_client.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"
@@ -147,14 +149,14 @@ const char* RequestContextName(WebURLRequest::RequestContext context) {
// ContentSettingsClient/WorkerContentSettingsClient to avoid using C++
// template.
template <typename SettingsType, typename SettingsClientType>
-bool IsWebSocketAllowedImpl(ExecutionContext* execution_context,
+bool IsWebSocketAllowedImpl(const BaseFetchContext& fetch_context,
SecurityContext* security_context,
const SecurityOrigin* security_origin,
SettingsType* settings,
SettingsClientType* settings_client,
const KURL& url) {
- UseCounter::Count(execution_context, WebFeature::kMixedContentPresent);
- UseCounter::Count(execution_context, WebFeature::kMixedContentWebSocket);
+ fetch_context.CountUsage(WebFeature::kMixedContentPresent);
+ fetch_context.CountUsage(WebFeature::kMixedContentWebSocket);
if (ContentSecurityPolicy* policy =
security_context->GetContentSecurityPolicy()) {
policy->ReportMixedContent(url,
@@ -253,8 +255,7 @@ Frame* MixedContentChecker::InWhichFrameIsContentMixed(
}
// static
-void MixedContentChecker::LogToConsoleAboutFetch(
- ExecutionContext* execution_context,
+ConsoleMessage* MixedContentChecker::CreateConsoleMessageAboutFetch(
const KURL& main_resource_url,
const KURL& url,
WebURLRequest::RequestContext request_context,
@@ -271,13 +272,10 @@ void MixedContentChecker::LogToConsoleAboutFetch(
MessageLevel message_level =
allowed ? kWarningMessageLevel : kErrorMessageLevel;
if (source_location) {
- execution_context->AddConsoleMessage(
- ConsoleMessage::Create(kSecurityMessageSource, message_level, message,
- std::move(source_location)));
- } else {
- execution_context->AddConsoleMessage(
- ConsoleMessage::Create(kSecurityMessageSource, message_level, message));
+ return ConsoleMessage::Create(kSecurityMessageSource, message_level,
+ message, std::move(source_location));
}
+ return ConsoleMessage::Create(kSecurityMessageSource, message_level, message);
}
// static
@@ -443,78 +441,76 @@ bool MixedContentChecker::ShouldBlockFetch(
};
if (reporting_policy == SecurityViolationReportingPolicy::kReport) {
- LogToConsoleAboutFetch(frame->GetDocument(),
- MainResourceUrlForFrame(mixed_frame), url,
- request_context, allowed, nullptr);
+ frame->GetDocument()->AddConsoleMessage(
+ CreateConsoleMessageAboutFetch(MainResourceUrlForFrame(mixed_frame),
+ url, request_context, allowed, nullptr));
}
return !allowed;
}
// static
bool MixedContentChecker::ShouldBlockFetchOnWorker(
- WorkerOrWorkletGlobalScope* global_scope,
- WebWorkerFetchContext* worker_fetch_context,
+ const WorkerFetchContext& worker_fetch_context,
WebURLRequest::RequestContext request_context,
- network::mojom::RequestContextFrameType frame_type,
ResourceRequest::RedirectStatus redirect_status,
const KURL& url,
- SecurityViolationReportingPolicy reporting_policy) {
- if (!MixedContentChecker::IsMixedContent(global_scope->GetSecurityOrigin(),
- url)) {
+ SecurityViolationReportingPolicy reporting_policy,
+ bool is_worklet_global_scope) {
+ if (!MixedContentChecker::IsMixedContent(
+ worker_fetch_context.GetSecurityOrigin(), url)) {
return false;
}
- UseCounter::Count(global_scope, WebFeature::kMixedContentPresent);
- UseCounter::Count(global_scope, WebFeature::kMixedContentBlockable);
- if (ContentSecurityPolicy* policy = global_scope->GetContentSecurityPolicy())
+ worker_fetch_context.CountUsage(WebFeature::kMixedContentPresent);
+ worker_fetch_context.CountUsage(WebFeature::kMixedContentBlockable);
+ if (auto* policy = worker_fetch_context.GetContentSecurityPolicy())
policy->ReportMixedContent(url, redirect_status);
// Blocks all mixed content request from worklets.
// TODO(horo): Revise this when the spec is updated.
// Worklets spec: https://www.w3.org/TR/worklets-1/#security-considerations
// Spec issue: https://github.com/w3c/css-houdini-drafts/issues/92
- if (!global_scope->IsWorkerGlobalScope())
+ if (is_worklet_global_scope)
return true;
- WorkerGlobalScope* worker_global_scope = ToWorkerGlobalScope(global_scope);
- WorkerSettings* settings = worker_global_scope->GetWorkerSettings();
+ WorkerSettings* settings = worker_fetch_context.GetWorkerSettings();
DCHECK(settings);
bool allowed = false;
if (!settings->GetAllowRunningOfInsecureContent() &&
- worker_fetch_context->IsOnSubframe()) {
- UseCounter::Count(global_scope,
- WebFeature::kBlockableMixedContentInSubframeBlocked);
+ worker_fetch_context.GetWebWorkerFetchContext()->IsOnSubframe()) {
+ worker_fetch_context.CountUsage(
+ WebFeature::kBlockableMixedContentInSubframeBlocked);
allowed = false;
} else {
- bool strict_mode = worker_global_scope->GetInsecureRequestPolicy() &
- kBlockAllMixedContent ||
- settings->GetStrictMixedContentChecking();
+ bool strict_mode =
+ worker_fetch_context.GetSecurityContext().GetInsecureRequestPolicy() &
+ kBlockAllMixedContent ||
+ settings->GetStrictMixedContentChecking();
bool should_ask_embedder =
!strict_mode && (!settings->GetStrictlyBlockBlockableMixedContent() ||
settings->GetAllowRunningOfInsecureContent());
allowed = should_ask_embedder &&
- WorkerContentSettingsClient::From(*global_scope)
+ worker_fetch_context.GetWorkerContentSettingsClient()
->AllowRunningInsecureContent(
settings->GetAllowRunningOfInsecureContent(),
- global_scope->GetSecurityOrigin(), url);
+ worker_fetch_context.GetSecurityOrigin(), url);
if (allowed) {
- worker_fetch_context->DidRunInsecureContent(
- WebSecurityOrigin(global_scope->GetSecurityOrigin()), url);
- UseCounter::Count(global_scope,
- WebFeature::kMixedContentBlockableAllowed);
+ worker_fetch_context.GetWebWorkerFetchContext()->DidRunInsecureContent(
+ WebSecurityOrigin(worker_fetch_context.GetSecurityOrigin()), url);
+ worker_fetch_context.CountUsage(
+ WebFeature::kMixedContentBlockableAllowed);
}
}
if (reporting_policy == SecurityViolationReportingPolicy::kReport) {
- LogToConsoleAboutFetch(global_scope, global_scope->Url(), url,
- request_context, allowed, nullptr);
+ worker_fetch_context.AddConsoleMessage(CreateConsoleMessageAboutFetch(
+ worker_fetch_context.Url(), url, request_context, allowed, nullptr));
}
return !allowed;
}
// static
-void MixedContentChecker::LogToConsoleAboutWebSocket(
- ExecutionContext* execution_context,
+ConsoleMessage* MixedContentChecker::CreateConsoleMessageAboutWebSocket(
const KURL& main_resource_url,
const KURL& url,
bool allowed) {
@@ -529,13 +525,14 @@ void MixedContentChecker::LogToConsoleAboutWebSocket(
"available over WSS.");
MessageLevel message_level =
allowed ? kWarningMessageLevel : kErrorMessageLevel;
- execution_context->AddConsoleMessage(
- ConsoleMessage::Create(kSecurityMessageSource, message_level, message));
+ return ConsoleMessage::Create(kSecurityMessageSource, message_level, message);
}
// static
-bool MixedContentChecker::IsWebSocketAllowed(LocalFrame* frame,
- const KURL& url) {
+bool MixedContentChecker::IsWebSocketAllowed(
+ const FrameFetchContext& frame_fetch_context,
+ LocalFrame* frame,
+ const KURL& url) {
Frame* mixed_frame = InWhichFrameIsContentMixed(
frame, network::mojom::RequestContextFrameType::kNone, url, frame);
if (!mixed_frame)
@@ -549,43 +546,45 @@ bool MixedContentChecker::IsWebSocketAllowed(LocalFrame* frame,
SecurityContext* security_context = mixed_frame->GetSecurityContext();
const SecurityOrigin* security_origin = security_context->GetSecurityOrigin();
- bool allowed = IsWebSocketAllowedImpl(frame->GetDocument(), security_context,
+ bool allowed = IsWebSocketAllowedImpl(frame_fetch_context, security_context,
security_origin, settings,
content_settings_client, url);
if (allowed)
frame->Client()->DidRunInsecureContent(security_origin, url);
- LogToConsoleAboutWebSocket(
- frame->GetDocument(), MainResourceUrlForFrame(mixed_frame), url, allowed);
+ frame->GetDocument()->AddConsoleMessage(CreateConsoleMessageAboutWebSocket(
+ MainResourceUrlForFrame(mixed_frame), url, allowed));
return allowed;
}
// static
bool MixedContentChecker::IsWebSocketAllowed(
- WorkerGlobalScope* global_scope,
- WebWorkerFetchContext* worker_fetch_context,
+ const WorkerFetchContext& worker_fetch_context,
const KURL& url) {
- if (!MixedContentChecker::IsMixedContent(global_scope->GetSecurityOrigin(),
- url)) {
+ if (!MixedContentChecker::IsMixedContent(
+ worker_fetch_context.GetSecurityOrigin(), url)) {
return true;
}
- WorkerSettings* settings = global_scope->GetWorkerSettings();
+ WorkerSettings* settings = worker_fetch_context.GetWorkerSettings();
WorkerContentSettingsClient* content_settings_client =
- WorkerContentSettingsClient::From(*global_scope);
- SecurityContext* security_context = &global_scope->GetSecurityContext();
- const SecurityOrigin* security_origin = global_scope->GetSecurityOrigin();
+ worker_fetch_context.GetWorkerContentSettingsClient();
+ SecurityContext* security_context =
+ &worker_fetch_context.GetSecurityContext();
+ const SecurityOrigin* security_origin =
+ worker_fetch_context.GetSecurityOrigin();
- bool allowed =
- IsWebSocketAllowedImpl(global_scope, security_context, security_origin,
- settings, content_settings_client, url);
+ bool allowed = IsWebSocketAllowedImpl(worker_fetch_context, security_context,
+ security_origin, settings,
+ content_settings_client, url);
if (allowed) {
- worker_fetch_context->DidRunInsecureContent(
+ worker_fetch_context.GetWebWorkerFetchContext()->DidRunInsecureContent(
WebSecurityOrigin(security_origin), url);
}
- LogToConsoleAboutWebSocket(global_scope, global_scope->Url(), url, allowed);
+ worker_fetch_context.AddConsoleMessage(CreateConsoleMessageAboutWebSocket(
+ worker_fetch_context.Url(), url, allowed));
return allowed;
}
@@ -702,9 +701,9 @@ void MixedContentChecker::MixedContentFound(
bool had_redirect,
std::unique_ptr<SourceLocation> source_location) {
// Logs to the frame console.
- LogToConsoleAboutFetch(frame->GetDocument(), main_resource_url,
- mixed_content_url, request_context, was_allowed,
- std::move(source_location));
+ frame->GetDocument()->AddConsoleMessage(CreateConsoleMessageAboutFetch(
+ main_resource_url, mixed_content_url, request_context, was_allowed,
+ std::move(source_location)));
// Reports to the CSP policy.
ContentSecurityPolicy* policy =
frame->GetSecurityContext()->GetContentSecurityPolicy();
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 879fa2fec89..2a0a300c78b 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
@@ -43,16 +43,15 @@
namespace blink {
-class ExecutionContext;
+class ConsoleMessage;
class Frame;
+class FrameFetchContext;
class LocalFrame;
class KURL;
class ResourceResponse;
class SecurityOrigin;
class SourceLocation;
-class WorkerGlobalScope;
-class WorkerOrWorkletGlobalScope;
-class WebWorkerFetchContext;
+class WorkerFetchContext;
// Checks resource loads for mixed content. If PlzNavigate is enabled then this
// class only checks for sub-resource loads while frame-level loads are
@@ -74,18 +73,17 @@ class CORE_EXPORT MixedContentChecker final {
SecurityViolationReportingPolicy =
SecurityViolationReportingPolicy::kReport);
- static bool ShouldBlockFetchOnWorker(WorkerOrWorkletGlobalScope*,
- WebWorkerFetchContext*,
+ static bool ShouldBlockFetchOnWorker(const WorkerFetchContext&,
WebURLRequest::RequestContext,
- network::mojom::RequestContextFrameType,
ResourceRequest::RedirectStatus,
const KURL&,
- SecurityViolationReportingPolicy);
+ SecurityViolationReportingPolicy,
+ bool is_worklet_global_scope);
- static bool IsWebSocketAllowed(LocalFrame*, const KURL&);
- static bool IsWebSocketAllowed(WorkerGlobalScope*,
- WebWorkerFetchContext*,
+ static bool IsWebSocketAllowed(const FrameFetchContext&,
+ LocalFrame*,
const KURL&);
+ static bool IsWebSocketAllowed(const WorkerFetchContext&, const KURL&);
static bool IsMixedContent(const SecurityOrigin*, const KURL&);
static bool IsMixedFormAction(LocalFrame*,
@@ -129,16 +127,15 @@ class CORE_EXPORT MixedContentChecker final {
const KURL&,
const LocalFrame*);
- static void LogToConsoleAboutFetch(ExecutionContext*,
- const KURL&,
- const KURL&,
- WebURLRequest::RequestContext,
- bool allowed,
- std::unique_ptr<SourceLocation>);
- static void LogToConsoleAboutWebSocket(ExecutionContext*,
- const KURL&,
- const KURL&,
- bool allowed);
+ static ConsoleMessage* CreateConsoleMessageAboutFetch(
+ const KURL&,
+ const KURL&,
+ WebURLRequest::RequestContext,
+ bool allowed,
+ std::unique_ptr<SourceLocation>);
+ static ConsoleMessage* CreateConsoleMessageAboutWebSocket(const KURL&,
+ const KURL&,
+ bool allowed);
static void Count(Frame*, WebURLRequest::RequestContext, const LocalFrame*);
DISALLOW_COPY_AND_ASSIGN(MixedContentChecker);
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc b/chromium/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc
index 7c8215a0b0e..81cbd3aba62 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc
@@ -1,74 +1,17 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// 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/loader/modulescript/document_module_script_fetcher.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/core/loader/subresource_integrity_helper.h"
#include "third_party/blink/renderer/core/script/layered_api.h"
-#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/mime/mime_type_registry.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/wtf/text/movable_string.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
-namespace {
-
-bool WasModuleLoadSuccessful(
- Resource* resource,
- HeapVector<Member<ConsoleMessage>>* error_messages) {
- // Implements conditions in Step 7 of
- // https://html.spec.whatwg.org/#fetch-a-single-module-script
-
- DCHECK(error_messages);
-
- if (resource) {
- SubresourceIntegrityHelper::GetConsoleMessages(
- resource->IntegrityReportInfo(), error_messages);
- }
-
- // - response's type is "error"
- if (!resource || resource->ErrorOccurred() ||
- resource->IntegrityDisposition() !=
- ResourceIntegrityDisposition::kPassed) {
- return false;
- }
-
- const auto& response = resource->GetResponse();
- // - response's status is not an ok status
- if (response.IsHTTP() && !CORS::IsOkStatus(response.HttpStatusCode())) {
- return false;
- }
-
- // The result of extracting a MIME type from response's header list
- // (ignoring parameters) is not a JavaScript MIME type
- // Note: For historical reasons, fetching a classic script does not include
- // MIME type checking. In contrast, module scripts will fail to load if they
- // are not of a correct MIME type.
- // We use ResourceResponse::HttpContentType() instead of MimeType(), as
- // MimeType() may be rewritten by mime sniffer.
- if (!MIMETypeRegistry::IsSupportedJavaScriptMIMEType(
- response.HttpContentType())) {
- String message =
- "Failed to load module script: The server responded with a "
- "non-JavaScript MIME type of \"" +
- response.HttpContentType() +
- "\". Strict MIME type checking is enforced for module scripts per "
- "HTML spec.";
- error_messages->push_back(ConsoleMessage::CreateForRequest(
- kJSMessageSource, kErrorMessageLevel, message,
- response.Url().GetString(), nullptr, resource->Identifier()));
- return false;
- }
-
- return true;
-}
-
-} // namespace
-
DocumentModuleScriptFetcher::DocumentModuleScriptFetcher(
ResourceFetcher* fetcher)
: fetcher_(fetcher) {
@@ -76,8 +19,10 @@ DocumentModuleScriptFetcher::DocumentModuleScriptFetcher(
}
void DocumentModuleScriptFetcher::Fetch(FetchParameters& fetch_params,
+ ModuleGraphLevel level,
ModuleScriptFetcher::Client* client) {
- SetClient(client);
+ DCHECK(!client_);
+ client_ = client;
if (FetchIfLayeredAPI(fetch_params))
return;
@@ -85,6 +30,31 @@ void DocumentModuleScriptFetcher::Fetch(FetchParameters& fetch_params,
ScriptResource::Fetch(fetch_params, fetcher_, this);
}
+void DocumentModuleScriptFetcher::NotifyFinished(Resource* resource) {
+ ClearResource();
+
+ ScriptResource* script_resource = ToScriptResource(resource);
+
+ HeapVector<Member<ConsoleMessage>> error_messages;
+ if (!WasModuleLoadSuccessful(script_resource, &error_messages)) {
+ client_->NotifyFetchFinished(base::nullopt, error_messages);
+ return;
+ }
+
+ ModuleScriptCreationParams params(
+ script_resource->GetResponse().Url(), script_resource->SourceText(),
+ script_resource->GetResourceRequest().GetFetchCredentialsMode(),
+ script_resource->CalculateAccessControlStatus(
+ fetcher_->Context().GetSecurityOrigin()));
+ client_->NotifyFetchFinished(params, error_messages);
+}
+
+void DocumentModuleScriptFetcher::Trace(blink::Visitor* visitor) {
+ visitor->Trace(fetcher_);
+ visitor->Trace(client_);
+ ResourceClient::Trace(visitor);
+}
+
bool DocumentModuleScriptFetcher::FetchIfLayeredAPI(
FetchParameters& fetch_params) {
if (!RuntimeEnabledFeatures::LayeredAPIEnabled())
@@ -95,54 +65,23 @@ bool DocumentModuleScriptFetcher::FetchIfLayeredAPI(
if (layered_api_url.IsNull())
return false;
- const String source_text = blink::layered_api::GetSourceText(layered_api_url);
+ String source_text = blink::layered_api::GetSourceText(layered_api_url);
if (source_text.IsNull()) {
HeapVector<Member<ConsoleMessage>> error_messages;
error_messages.push_back(ConsoleMessage::CreateForRequest(
kJSMessageSource, kErrorMessageLevel, "Unexpected data error",
fetch_params.Url().GetString(), nullptr, 0));
- Finalize(base::nullopt, error_messages);
+ client_->NotifyFetchFinished(base::nullopt, error_messages);
return true;
}
ModuleScriptCreationParams params(
- layered_api_url, source_text,
+ layered_api_url, MovableString(source_text.ReleaseImpl()),
fetch_params.GetResourceRequest().GetFetchCredentialsMode(),
kSharableCrossOrigin);
- Finalize(params, HeapVector<Member<ConsoleMessage>>());
+ client_->NotifyFetchFinished(params, HeapVector<Member<ConsoleMessage>>());
return true;
}
-void DocumentModuleScriptFetcher::NotifyFinished(Resource* resource) {
- ClearResource();
-
- ScriptResource* script_resource = ToScriptResource(resource);
-
- HeapVector<Member<ConsoleMessage>> error_messages;
- if (!WasModuleLoadSuccessful(script_resource, &error_messages)) {
- Finalize(base::nullopt, error_messages);
- return;
- }
-
- ModuleScriptCreationParams params(
- script_resource->GetResponse().Url(), script_resource->SourceText(),
- script_resource->GetResourceRequest().GetFetchCredentialsMode(),
- script_resource->CalculateAccessControlStatus(
- fetcher_->Context().GetSecurityOrigin()));
- Finalize(params, error_messages);
-}
-
-void DocumentModuleScriptFetcher::Finalize(
- const base::Optional<ModuleScriptCreationParams>& params,
- const HeapVector<Member<ConsoleMessage>>& error_messages) {
- NotifyFetchFinished(params, error_messages);
-}
-
-void DocumentModuleScriptFetcher::Trace(blink::Visitor* visitor) {
- visitor->Trace(fetcher_);
- ResourceClient::Trace(visitor);
- ModuleScriptFetcher::Trace(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.h b/chromium/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.h
index be860391b52..49fb6b6e04a 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.h
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.h
@@ -1,53 +1,43 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// 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_LOADER_MODULESCRIPT_DOCUMENT_MODULE_SCRIPT_FETCHER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_DOCUMENT_MODULE_SCRIPT_FETCHER_H_
-#include "base/optional.h"
-#include "third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.h"
-#include "third_party/blink/renderer/core/loader/resource/script_resource.h"
-#include "third_party/blink/renderer/core/script/modulator.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/weborigin/security_origin.h"
namespace blink {
-class ConsoleMessage;
-
-// DocumentModuleScriptFetcher is used to fetch module scripts used in main
-// documents and workers (but not worklets).
-//
-// DocumentModuleScriptFetcher emits FetchParameters to ResourceFetcher
-// (via ScriptResource::Fetch). Then, it keeps track of the fetch progress by
-// being a ResourceClient. Finally, it returns its client a fetched resource as
-// ModuleScriptCreationParams.
-class CORE_EXPORT DocumentModuleScriptFetcher : public ModuleScriptFetcher,
- public ResourceClient {
+// DocumentModuleScriptFetcher is an implmenetation of ModuleScriptFetcher
+// interface used for <script type='module'> on Document.
+// TODO(nhiroki): This class is also used for non-custom module script fetch on
+// workers. We should rename this to something like ModuleScriptFetcherImpl that
+// doesn't relate to Document.
+class CORE_EXPORT DocumentModuleScriptFetcher final
+ : public GarbageCollectedFinalized<DocumentModuleScriptFetcher>,
+ public ModuleScriptFetcher {
USING_GARBAGE_COLLECTED_MIXIN(DocumentModuleScriptFetcher);
public:
explicit DocumentModuleScriptFetcher(ResourceFetcher*);
+ ~DocumentModuleScriptFetcher() override = default;
- void Fetch(FetchParameters&, ModuleScriptFetcher::Client*) final;
+ // Implements ModuleScriptFetcher.
+ void Fetch(FetchParameters&, ModuleGraphLevel, Client*) override;
// Implements ResourceClient
- void NotifyFinished(Resource*) final;
- String DebugName() const final { return "DocumentModuleScriptFetcher"; }
+ void NotifyFinished(Resource*) override;
+ String DebugName() const override { return "DocumentModuleScriptFetcher"; }
void Trace(blink::Visitor*) override;
private:
- void Finalize(const base::Optional<ModuleScriptCreationParams>&,
- const HeapVector<Member<ConsoleMessage>>& error_messages);
-
- // Returns true if loaded as Layered API.
bool FetchIfLayeredAPI(FetchParameters&);
- Member<ResourceFetcher> fetcher_;
+ const Member<ResourceFetcher> fetcher_;
+ Member<Client> client_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h
index cdc39f58079..f9d9b548116 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/platform/cross_thread_copier.h"
#include "third_party/blink/renderer/platform/loader/fetch/access_control_status.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/text/movable_string.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -19,17 +20,34 @@ class ModuleScriptCreationParams {
public:
ModuleScriptCreationParams(
const KURL& response_url,
- const String& source_text,
+ const MovableString& source_text,
network::mojom::FetchCredentialsMode fetch_credentials_mode,
AccessControlStatus access_control_status)
: response_url_(response_url),
+ is_isolated_(false),
source_text_(source_text),
+ isolated_source_text_(),
fetch_credentials_mode_(fetch_credentials_mode),
access_control_status_(access_control_status) {}
+
~ModuleScriptCreationParams() = default;
+ ModuleScriptCreationParams IsolatedCopy() const {
+ String isolated_source_text = GetSourceText().ToString().IsolatedCopy();
+ return ModuleScriptCreationParams(
+ GetResponseUrl().Copy(), isolated_source_text,
+ GetFetchCredentialsMode(), GetAccessControlStatus());
+ }
+
const KURL& GetResponseUrl() const { return response_url_; };
- const String& GetSourceText() const { return source_text_; }
+ const MovableString& GetSourceText() const {
+ if (is_isolated_) {
+ source_text_ = MovableString(isolated_source_text_.ReleaseImpl());
+ isolated_source_text_ = String();
+ is_isolated_ = false;
+ }
+ return source_text_;
+ }
network::mojom::FetchCredentialsMode GetFetchCredentialsMode() const {
return fetch_credentials_mode_;
}
@@ -37,9 +55,32 @@ class ModuleScriptCreationParams {
return access_control_status_;
}
+ bool IsSafeToSendToAnotherThread() const {
+ return response_url_.IsSafeToSendToAnotherThread() && is_isolated_;
+ }
+
private:
+ // Creates an isolated copy.
+ ModuleScriptCreationParams(
+ const KURL& response_url,
+ const String& isolated_source_text,
+ network::mojom::FetchCredentialsMode fetch_credentials_mode,
+ AccessControlStatus access_control_status)
+ : response_url_(response_url),
+ is_isolated_(true),
+ source_text_(),
+ isolated_source_text_(isolated_source_text),
+ fetch_credentials_mode_(fetch_credentials_mode),
+ access_control_status_(access_control_status) {}
+
const KURL response_url_;
- const String source_text_;
+
+ // Mutable because an isolated copy can become bound to a thread when
+ // calling GetSourceText().
+ mutable bool is_isolated_;
+ mutable MovableString source_text_;
+ mutable String isolated_source_text_;
+
const network::mojom::FetchCredentialsMode fetch_credentials_mode_;
const AccessControlStatus access_control_status_;
};
@@ -50,9 +91,7 @@ template <>
struct CrossThreadCopier<ModuleScriptCreationParams> {
static ModuleScriptCreationParams Copy(
const ModuleScriptCreationParams& params) {
- return ModuleScriptCreationParams(
- params.GetResponseUrl().Copy(), params.GetSourceText().IsolatedCopy(),
- params.GetFetchCredentialsMode(), params.GetAccessControlStatus());
+ return params.IsolatedCopy();
}
};
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h
index 8b18476ae1b..687c8cfa85a 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h
@@ -24,37 +24,32 @@ class ModuleScriptFetchRequest final {
ModuleScriptFetchRequest(const KURL& url,
WebURLRequest::RequestContext destination,
const ScriptFetchOptions& options,
- const String& referrer,
- ReferrerPolicy referrer_policy,
+ const Referrer& referrer,
const TextPosition& referrer_position)
: url_(url),
destination_(destination),
options_(options),
referrer_(referrer),
- referrer_policy_(referrer_policy),
referrer_position_(referrer_position) {}
static ModuleScriptFetchRequest CreateForTest(const KURL& url) {
- return ModuleScriptFetchRequest(
- url, WebURLRequest::kRequestContextScript, ScriptFetchOptions(),
- Referrer::NoReferrer(), kReferrerPolicyDefault,
- TextPosition::MinimumPosition());
+ return ModuleScriptFetchRequest(url, WebURLRequest::kRequestContextScript,
+ ScriptFetchOptions(), Referrer(),
+ TextPosition::MinimumPosition());
}
~ModuleScriptFetchRequest() = default;
const KURL& Url() const { return url_; }
WebURLRequest::RequestContext Destination() const { return destination_; }
const ScriptFetchOptions& Options() const { return options_; }
- const AtomicString& GetReferrer() const { return referrer_; }
- ReferrerPolicy GetReferrerPolicy() const { return referrer_policy_; }
+ const Referrer& GetReferrer() const { return referrer_; }
const TextPosition& GetReferrerPosition() const { return referrer_position_; }
private:
const KURL url_;
const WebURLRequest::RequestContext destination_;
const ScriptFetchOptions options_;
- const AtomicString referrer_;
- const ReferrerPolicy referrer_policy_;
+ const Referrer referrer_;
const TextPosition referrer_position_;
};
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.cc b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.cc
index 85e2815a94e..10634797e8d 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.cc
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.cc
@@ -4,21 +4,71 @@
#include "third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.h"
+#include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/core/loader/subresource_integrity_helper.h"
+#include "third_party/blink/renderer/platform/loader/cors/cors.h"
+#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
namespace blink {
-void ModuleScriptFetcher::Trace(blink::Visitor* visitor) {
- visitor->Trace(client_);
+void ModuleScriptFetcher::Client::OnFetched(
+ const base::Optional<ModuleScriptCreationParams>& params) {
+ NotifyFetchFinished(params, HeapVector<Member<ConsoleMessage>>());
}
-void ModuleScriptFetcher::NotifyFetchFinished(
- const base::Optional<ModuleScriptCreationParams>& params,
- const HeapVector<Member<ConsoleMessage>>& error_messages) {
- client_->NotifyFetchFinished(params, error_messages);
+void ModuleScriptFetcher::Client::OnFailed() {
+ NotifyFetchFinished(base::nullopt, HeapVector<Member<ConsoleMessage>>());
}
-void ModuleScriptFetcher::SetClient(Client* client) {
- DCHECK(!client_);
- client_ = client;
+bool ModuleScriptFetcher::WasModuleLoadSuccessful(
+ Resource* resource,
+ HeapVector<Member<ConsoleMessage>>* error_messages) {
+ // Implements conditions in Step 7 of
+ // https://html.spec.whatwg.org/#fetch-a-single-module-script
+
+ DCHECK(error_messages);
+
+ if (resource) {
+ SubresourceIntegrityHelper::GetConsoleMessages(
+ resource->IntegrityReportInfo(), error_messages);
+ }
+
+ // - response's type is "error"
+ if (!resource || resource->ErrorOccurred() ||
+ resource->IntegrityDisposition() !=
+ ResourceIntegrityDisposition::kPassed) {
+ return false;
+ }
+
+ const auto& response = resource->GetResponse();
+ // - response's status is not an ok status
+ if (response.IsHTTP() && !CORS::IsOkStatus(response.HttpStatusCode())) {
+ return false;
+ }
+
+ // The result of extracting a MIME type from response's header list
+ // (ignoring parameters) is not a JavaScript MIME type
+ // Note: For historical reasons, fetching a classic script does not include
+ // MIME type checking. In contrast, module scripts will fail to load if they
+ // are not of a correct MIME type.
+ // We use ResourceResponse::HttpContentType() instead of MimeType(), as
+ // MimeType() may be rewritten by mime sniffer.
+ if (!MIMETypeRegistry::IsSupportedJavaScriptMIMEType(
+ response.HttpContentType())) {
+ String message =
+ "Failed to load module script: The server responded with a "
+ "non-JavaScript MIME type of \"" +
+ response.HttpContentType() +
+ "\". Strict MIME type checking is enforced for module scripts per "
+ "HTML spec.";
+ error_messages->push_back(ConsoleMessage::CreateForRequest(
+ kJSMessageSource, kErrorMessageLevel, message,
+ response.Url().GetString(), nullptr, resource->Identifier()));
+ return false;
+ }
+
+ return true;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.h b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.h
index 4131f5f9eca..077fe4bc430 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.h
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.h
@@ -8,6 +8,8 @@
#include "base/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h"
+#include "third_party/blink/renderer/core/loader/resource/script_resource.h"
+#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
@@ -18,33 +20,28 @@ class ConsoleMessage;
// ModuleScriptFetcher is an abstract class to fetch module scripts. Derived
// classes are expected to fetch a module script for the given FetchParameters
// and return its client a fetched resource as ModuleScriptCreationParams.
-class CORE_EXPORT ModuleScriptFetcher
- : public GarbageCollectedFinalized<ModuleScriptFetcher> {
+class CORE_EXPORT ModuleScriptFetcher : public ResourceClient {
public:
class CORE_EXPORT Client : public GarbageCollectedMixin {
public:
virtual void NotifyFetchFinished(
const base::Optional<ModuleScriptCreationParams>&,
const HeapVector<Member<ConsoleMessage>>& error_messages) = 0;
- };
- ModuleScriptFetcher() = default;
- virtual ~ModuleScriptFetcher() = default;
+ // These helpers are used only from WorkletModuleResponsesMap.
+ // TODO(nhiroki): Move these helpers to WorkletModuleResponsesMap.
+ void OnFetched(const base::Optional<ModuleScriptCreationParams>&);
+ void OnFailed();
+ };
// Takes a non-const reference to FetchParameters because
// ScriptResource::Fetch() requires it.
- virtual void Fetch(FetchParameters&, Client*) = 0;
-
- virtual void Trace(blink::Visitor*);
+ virtual void Fetch(FetchParameters&, ModuleGraphLevel, Client*) = 0;
protected:
- void NotifyFetchFinished(const base::Optional<ModuleScriptCreationParams>&,
- const HeapVector<Member<ConsoleMessage>>&);
-
- void SetClient(Client*);
-
- private:
- Member<Client> client_;
+ static bool WasModuleLoadSuccessful(
+ Resource*,
+ HeapVector<Member<ConsoleMessage>>* error_messages);
};
} // namespace blink
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 c608d657497..5b6548957fa 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
@@ -6,10 +6,10 @@
#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/core/loader/modulescript/document_module_script_fetcher.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_loader_client.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_loader_registry.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/script/module_script.h"
#include "third_party/blink/renderer/core/workers/main_thread_worklet_global_scope.h"
@@ -77,10 +77,27 @@ void ModuleScriptLoader::AdvanceState(ModuleScriptLoader::State new_state) {
}
}
-void ModuleScriptLoader::Fetch(const ModuleScriptFetchRequest& module_request,
- ModuleGraphLevel level) {
- // https://html.spec.whatwg.org/#fetch-a-single-module-script
+void ModuleScriptLoader::Fetch(
+ const ModuleScriptFetchRequest& module_request,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
+ ModuleGraphLevel level,
+ Modulator* module_map_settings_object,
+ ModuleScriptCustomFetchType custom_fetch_type,
+ ModuleScriptLoaderRegistry* registry,
+ ModuleScriptLoaderClient* client) {
+ ModuleScriptLoader* loader = new ModuleScriptLoader(
+ module_map_settings_object, module_request.Options(), registry, client);
+ registry->AddLoader(loader);
+ loader->FetchInternal(module_request, fetch_client_settings_object, level,
+ custom_fetch_type);
+}
+// https://html.spec.whatwg.org/#fetch-a-single-module-script
+void ModuleScriptLoader::FetchInternal(
+ const ModuleScriptFetchRequest& module_request,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
+ ModuleGraphLevel level,
+ ModuleScriptCustomFetchType custom_fetch_type) {
// Step 4. "Set moduleMap[url] to "fetching"." [spec text]
AdvanceState(State::kFetching);
@@ -111,7 +128,7 @@ void ModuleScriptLoader::Fetch(const ModuleScriptFetchRequest& module_request,
if (level == ModuleGraphLevel::kDependentModuleFetch) {
options.initiator_info.imported_module_referrer =
- module_request.GetReferrer();
+ module_request.GetReferrer().referrer;
options.initiator_info.position = module_request.GetReferrerPosition();
}
@@ -132,15 +149,12 @@ void ModuleScriptLoader::Fetch(const ModuleScriptFetchRequest& module_request,
// [SMSR] "... and its credentials mode to options's credentials mode."
// [spec text]
fetch_params.SetCrossOriginAccessControl(
- modulator_->GetSecurityOriginForFetch(), options_.CredentialsMode());
+ fetch_client_settings_object->GetSecurityOrigin(),
+ options_.CredentialsMode());
// Step 5. "... referrer is referrer, ..." [spec text]
- if (!module_request.GetReferrer().IsNull()) {
- fetch_params.MutableResourceRequest().SetHTTPReferrer(
- SecurityPolicy::GenerateReferrer(module_request.GetReferrerPolicy(),
- module_request.Url(),
- module_request.GetReferrer()));
- }
+ fetch_params.MutableResourceRequest().SetHTTPReferrer(
+ module_request.GetReferrer());
// Step 5. "... and client is fetch client settings object." [spec text]
// -> set by ResourceFetcher
@@ -171,8 +185,8 @@ void ModuleScriptLoader::Fetch(const ModuleScriptFetchRequest& module_request,
// Otherwise, fetch request. Return from this algorithm, and run the remaining
// steps as part of the fetch's process response for the response response."
// [spec text]
- module_fetcher_ = modulator_->CreateModuleScriptFetcher();
- module_fetcher_->Fetch(fetch_params, this);
+ module_fetcher_ = modulator_->CreateModuleScriptFetcher(custom_fetch_type);
+ module_fetcher_->Fetch(fetch_params, level, this);
}
void ModuleScriptLoader::NotifyFetchFinished(
@@ -185,7 +199,7 @@ void ModuleScriptLoader::NotifyFetchFinished(
}
// Note: "conditions" referred in Step 8 is implemented in
- // WasModuleLoadSuccessful() in DocumentModuleScriptFetcher.cpp.
+ // WasModuleLoadSuccessful() in module_script_fetcher.cc.
// Step 8. "If any of the following conditions are met, set moduleMap[url] to
// null, asynchronously complete this algorithm with null, and abort these
// steps." [spec text]
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.h b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.h
index e6e619b4ed0..c2e1d338a20 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.h
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader.h
@@ -16,6 +16,7 @@
namespace blink {
+class FetchClientSettingsObjectSnapshot;
class Modulator;
class ModuleScript;
class ModuleScriptLoaderClient;
@@ -44,17 +45,16 @@ class CORE_EXPORT ModuleScriptLoader final
};
public:
- static ModuleScriptLoader* Create(Modulator* modulator,
- const ScriptFetchOptions& options,
- ModuleScriptLoaderRegistry* registry,
- ModuleScriptLoaderClient* client) {
- return new ModuleScriptLoader(modulator, options, registry, client);
- }
-
~ModuleScriptLoader();
- void Fetch(const ModuleScriptFetchRequest&,
- ModuleGraphLevel);
+ static void Fetch(
+ const ModuleScriptFetchRequest&,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
+ ModuleGraphLevel,
+ Modulator* module_map_settings_object,
+ ModuleScriptCustomFetchType,
+ ModuleScriptLoaderRegistry*,
+ ModuleScriptLoaderClient*);
// Implements ModuleScriptFetcher::Client.
void NotifyFetchFinished(
@@ -72,6 +72,12 @@ class CORE_EXPORT ModuleScriptLoader final
ModuleScriptLoaderRegistry*,
ModuleScriptLoaderClient*);
+ void FetchInternal(
+ const ModuleScriptFetchRequest&,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
+ ModuleGraphLevel,
+ ModuleScriptCustomFetchType);
+
void AdvanceState(State new_state);
#if DCHECK_IS_ON()
static const char* StateToString(State);
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader_registry.cc b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader_registry.cc
index eb8b543ac4a..d52e6549707 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader_registry.cc
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader_registry.cc
@@ -12,17 +12,10 @@ void ModuleScriptLoaderRegistry::Trace(blink::Visitor* visitor) {
visitor->Trace(active_loaders_);
}
-ModuleScriptLoader* ModuleScriptLoaderRegistry::Fetch(
- const ModuleScriptFetchRequest& request,
- ModuleGraphLevel level,
- Modulator* modulator,
- ModuleScriptLoaderClient* client) {
- ModuleScriptLoader* loader =
- ModuleScriptLoader::Create(modulator, request.Options(), this, client);
+void ModuleScriptLoaderRegistry::AddLoader(ModuleScriptLoader* loader) {
DCHECK(loader->IsInitialState());
+ DCHECK(!active_loaders_.Contains(loader));
active_loaders_.insert(loader);
- loader->Fetch(request, level);
- return loader;
}
void ModuleScriptLoaderRegistry::ReleaseFinishedLoader(
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader_registry.h b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader_registry.h
index c3dd895bb65..8ca0faea242 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader_registry.h
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/module_script_loader_registry.h
@@ -7,16 +7,11 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
namespace blink {
-class Modulator;
-class ModuleScriptFetchRequest;
class ModuleScriptLoader;
-class ModuleScriptLoaderClient;
-enum class ModuleGraphLevel;
// ModuleScriptLoaderRegistry keeps active ModuleLoaders alive.
class CORE_EXPORT ModuleScriptLoaderRegistry final
@@ -27,15 +22,11 @@ class CORE_EXPORT ModuleScriptLoaderRegistry final
}
void Trace(blink::Visitor*);
- ModuleScriptLoader* Fetch(const ModuleScriptFetchRequest&,
- ModuleGraphLevel,
- Modulator*,
- ModuleScriptLoaderClient*);
-
private:
ModuleScriptLoaderRegistry() = default;
friend class ModuleScriptLoader;
+ void AddLoader(ModuleScriptLoader*);
void ReleaseFinishedLoader(ModuleScriptLoader*);
HeapHashSet<Member<ModuleScriptLoader>> active_loaders_;
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 bfe0b6f3793..0e9271fc523 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
@@ -15,8 +15,9 @@
#include "third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_loader_client.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_loader_registry.h"
-#include "third_party/blink/renderer/core/loader/modulescript/worker_or_worklet_module_script_fetcher.h"
+#include "third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/script/module_script.h"
#include "third_party/blink/renderer/core/script/script.h"
@@ -66,33 +67,22 @@ class TestModuleScriptLoaderClient final
class ModuleScriptLoaderTestModulator final : public DummyModulator {
public:
ModuleScriptLoaderTestModulator(
- scoped_refptr<ScriptState> script_state,
+ ScriptState* script_state,
scoped_refptr<const SecurityOrigin> security_origin,
ResourceFetcher* fetcher)
- : script_state_(std::move(script_state)),
+ : script_state_(script_state),
security_origin_(std::move(security_origin)),
fetcher_(fetcher) {}
~ModuleScriptLoaderTestModulator() override = default;
- const SecurityOrigin* GetSecurityOriginForFetch() override {
- return security_origin_.get();
+ KURL ResolveModuleSpecifier(const String& module_request,
+ const KURL& base_url,
+ String* failure_reason) final {
+ return KURL(base_url, module_request);
}
- ScriptState* GetScriptState() override { return script_state_.get(); }
-
- ScriptModule CompileModule(const String& script,
- const KURL& source_url,
- const KURL& base_url,
- const ScriptFetchOptions& options,
- AccessControlStatus access_control_status,
- const TextPosition& position,
- ExceptionState& exception_state) override {
- ScriptState::Scope scope(script_state_.get());
- return ScriptModule::Compile(
- script_state_->GetIsolate(), script, source_url, base_url, options,
- access_control_status, position, exception_state);
- }
+ ScriptState* GetScriptState() override { return script_state_; }
void SetModuleRequests(const Vector<String>& requests) {
requests_.clear();
@@ -104,13 +94,18 @@ class ModuleScriptLoaderTestModulator final : public DummyModulator {
return requests_;
}
- ModuleScriptFetcher* CreateModuleScriptFetcher() override {
- auto* execution_context = ExecutionContext::From(script_state_.get());
- if (execution_context->IsDocument())
- return new DocumentModuleScriptFetcher(Fetcher());
- auto* global_scope = ToWorkletGlobalScope(execution_context);
- return new WorkerOrWorkletModuleScriptFetcher(
- global_scope->ModuleFetchCoordinatorProxy());
+ ModuleScriptFetcher* CreateModuleScriptFetcher(
+ ModuleScriptCustomFetchType custom_fetch_type) override {
+ auto* execution_context = ExecutionContext::From(script_state_);
+ if (execution_context->IsWorkletGlobalScope()) {
+ EXPECT_EQ(ModuleScriptCustomFetchType::kWorkletAddModule,
+ custom_fetch_type);
+ auto* global_scope = ToWorkletGlobalScope(execution_context);
+ return new WorkletModuleScriptFetcher(
+ Fetcher(), global_scope->GetModuleResponsesMap());
+ }
+ EXPECT_EQ(ModuleScriptCustomFetchType::kNone, custom_fetch_type);
+ return new DocumentModuleScriptFetcher(Fetcher());
}
ResourceFetcher* Fetcher() const { return fetcher_.Get(); }
@@ -118,7 +113,7 @@ class ModuleScriptLoaderTestModulator final : public DummyModulator {
void Trace(blink::Visitor*) override;
private:
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
scoped_refptr<const SecurityOrigin> security_origin_;
Member<ResourceFetcher> fetcher_;
Vector<ModuleRequest> requests_;
@@ -126,6 +121,7 @@ class ModuleScriptLoaderTestModulator final : public DummyModulator {
void ModuleScriptLoaderTestModulator::Trace(blink::Visitor* visitor) {
visitor->Trace(fetcher_);
+ visitor->Trace(script_state_);
DummyModulator::Trace(visitor);
}
@@ -141,13 +137,22 @@ class ModuleScriptLoaderTest : public PageTestBase {
void InitializeForDocument();
void InitializeForWorklet();
- void TestFetchDataURL(TestModuleScriptLoaderClient*);
- void TestInvalidSpecifier(TestModuleScriptLoaderClient*);
- void TestFetchInvalidURL(TestModuleScriptLoaderClient*);
- void TestFetchURL(TestModuleScriptLoaderClient*);
+ void TestFetchDataURL(ModuleScriptCustomFetchType,
+ TestModuleScriptLoaderClient*);
+ void TestInvalidSpecifier(ModuleScriptCustomFetchType,
+ TestModuleScriptLoaderClient*);
+ void TestFetchInvalidURL(ModuleScriptCustomFetchType,
+ TestModuleScriptLoaderClient*);
+ void TestFetchURL(ModuleScriptCustomFetchType, TestModuleScriptLoaderClient*);
ModuleScriptLoaderTestModulator* GetModulator() { return modulator_.Get(); }
+ void RunUntilIdle() {
+ base::SingleThreadTaskRunner* runner =
+ GetModulator()->Fetcher()->Context().GetLoadingTaskRunner().get();
+ static_cast<scheduler::FakeTaskRunner*>(runner)->RunUntilIdle();
+ }
+
protected:
ScopedTestingPlatformSupport<FetchTestingPlatformSupport> platform_;
std::unique_ptr<MainThreadWorkletReportingProxy> reporting_proxy_;
@@ -179,13 +184,12 @@ void ModuleScriptLoaderTest::InitializeForWorklet() {
std::make_unique<MainThreadWorkletReportingProxy>(&GetDocument());
auto creation_params = std::make_unique<GlobalScopeCreationParams>(
GetDocument().Url(), ScriptType::kModule, GetDocument().UserAgent(),
- nullptr /* content_security_policy_parsed_headers */,
- GetDocument().GetReferrerPolicy(), GetDocument().GetSecurityOrigin(),
- GetDocument().IsSecureContext(), nullptr /* worker_clients */,
- GetDocument().AddressSpace(),
+ Vector<CSPHeaderAndType>(), GetDocument().GetReferrerPolicy(),
+ GetDocument().GetSecurityOrigin(), GetDocument().IsSecureContext(),
+ nullptr /* worker_clients */, GetDocument().AddressSpace(),
OriginTrialContext::GetTokens(&GetDocument()).get(),
base::UnguessableToken::Create(), nullptr /* worker_settings */,
- kV8CacheOptionsDefault, new WorkletModuleResponsesMap(fetcher));
+ kV8CacheOptionsDefault, new WorkletModuleResponsesMap);
global_scope_ = new MainThreadWorkletGlobalScope(
&GetFrame(), std::move(creation_params), *reporting_proxy_);
global_scope_->ScriptController()->InitializeContextIfNeeded("Dummy Context");
@@ -195,18 +199,22 @@ void ModuleScriptLoaderTest::InitializeForWorklet() {
}
void ModuleScriptLoaderTest::TestFetchDataURL(
+ ModuleScriptCustomFetchType custom_fetch_type,
TestModuleScriptLoaderClient* client) {
ModuleScriptLoaderRegistry* registry = ModuleScriptLoaderRegistry::Create();
KURL url("data:text/javascript,export default 'grapes';");
- registry->Fetch(ModuleScriptFetchRequest::CreateForTest(url),
- ModuleGraphLevel::kTopLevelModuleFetch, GetModulator(),
- client);
+ auto* fetch_client_settings_object =
+ new FetchClientSettingsObjectSnapshot(GetDocument());
+ ModuleScriptLoader::Fetch(
+ ModuleScriptFetchRequest::CreateForTest(url),
+ fetch_client_settings_object, ModuleGraphLevel::kTopLevelModuleFetch,
+ GetModulator(), custom_fetch_type, registry, client);
}
TEST_F(ModuleScriptLoaderTest, FetchDataURL) {
InitializeForDocument();
TestModuleScriptLoaderClient* client = new TestModuleScriptLoaderClient;
- TestFetchDataURL(client);
+ TestFetchDataURL(ModuleScriptCustomFetchType::kNone, client);
EXPECT_TRUE(client->WasNotifyFinished())
<< "ModuleScriptLoader should finish synchronously.";
@@ -218,11 +226,11 @@ TEST_F(ModuleScriptLoaderTest, FetchDataURL) {
TEST_F(ModuleScriptLoaderTest, FetchDataURL_OnWorklet) {
InitializeForWorklet();
TestModuleScriptLoaderClient* client1 = new TestModuleScriptLoaderClient;
- TestFetchDataURL(client1);
+ TestFetchDataURL(ModuleScriptCustomFetchType::kWorkletAddModule, client1);
EXPECT_FALSE(client1->WasNotifyFinished())
<< "ModuleScriptLoader should finish asynchronously.";
- platform_->RunUntilIdle();
+ RunUntilIdle();
EXPECT_TRUE(client1->WasNotifyFinished());
ASSERT_TRUE(client1->GetModuleScript());
@@ -232,11 +240,11 @@ TEST_F(ModuleScriptLoaderTest, FetchDataURL_OnWorklet) {
// Try to fetch the same URL again in order to verify the case where
// WorkletModuleResponsesMap serves a cache.
TestModuleScriptLoaderClient* client2 = new TestModuleScriptLoaderClient;
- TestFetchDataURL(client2);
+ TestFetchDataURL(ModuleScriptCustomFetchType::kWorkletAddModule, client2);
EXPECT_FALSE(client2->WasNotifyFinished())
<< "ModuleScriptLoader should finish asynchronously.";
- platform_->RunUntilIdle();
+ RunUntilIdle();
EXPECT_TRUE(client2->WasNotifyFinished());
ASSERT_TRUE(client2->GetModuleScript());
@@ -245,19 +253,23 @@ TEST_F(ModuleScriptLoaderTest, FetchDataURL_OnWorklet) {
}
void ModuleScriptLoaderTest::TestInvalidSpecifier(
+ ModuleScriptCustomFetchType custom_fetch_type,
TestModuleScriptLoaderClient* client) {
ModuleScriptLoaderRegistry* registry = ModuleScriptLoaderRegistry::Create();
KURL url("data:text/javascript,import 'invalid';export default 'grapes';");
+ auto* fetch_client_settings_object =
+ new FetchClientSettingsObjectSnapshot(GetDocument());
GetModulator()->SetModuleRequests({"invalid"});
- registry->Fetch(ModuleScriptFetchRequest::CreateForTest(url),
- ModuleGraphLevel::kTopLevelModuleFetch, GetModulator(),
- client);
+ ModuleScriptLoader::Fetch(
+ ModuleScriptFetchRequest::CreateForTest(url),
+ fetch_client_settings_object, ModuleGraphLevel::kTopLevelModuleFetch,
+ GetModulator(), custom_fetch_type, registry, client);
}
TEST_F(ModuleScriptLoaderTest, InvalidSpecifier) {
InitializeForDocument();
TestModuleScriptLoaderClient* client = new TestModuleScriptLoaderClient;
- TestInvalidSpecifier(client);
+ TestInvalidSpecifier(ModuleScriptCustomFetchType::kNone, client);
EXPECT_TRUE(client->WasNotifyFinished())
<< "ModuleScriptLoader should finish synchronously.";
@@ -269,11 +281,11 @@ TEST_F(ModuleScriptLoaderTest, InvalidSpecifier) {
TEST_F(ModuleScriptLoaderTest, InvalidSpecifier_OnWorklet) {
InitializeForWorklet();
TestModuleScriptLoaderClient* client = new TestModuleScriptLoaderClient;
- TestInvalidSpecifier(client);
+ TestInvalidSpecifier(ModuleScriptCustomFetchType::kWorkletAddModule, client);
EXPECT_FALSE(client->WasNotifyFinished())
<< "ModuleScriptLoader should finish asynchronously.";
- platform_->RunUntilIdle();
+ RunUntilIdle();
EXPECT_TRUE(client->WasNotifyFinished());
ASSERT_TRUE(client->GetModuleScript());
@@ -282,19 +294,23 @@ TEST_F(ModuleScriptLoaderTest, InvalidSpecifier_OnWorklet) {
}
void ModuleScriptLoaderTest::TestFetchInvalidURL(
+ ModuleScriptCustomFetchType custom_fetch_type,
TestModuleScriptLoaderClient* client) {
ModuleScriptLoaderRegistry* registry = ModuleScriptLoaderRegistry::Create();
KURL url;
EXPECT_FALSE(url.IsValid());
- registry->Fetch(ModuleScriptFetchRequest::CreateForTest(url),
- ModuleGraphLevel::kTopLevelModuleFetch, GetModulator(),
- client);
+ auto* fetch_client_settings_object =
+ new FetchClientSettingsObjectSnapshot(GetDocument());
+ ModuleScriptLoader::Fetch(
+ ModuleScriptFetchRequest::CreateForTest(url),
+ fetch_client_settings_object, ModuleGraphLevel::kTopLevelModuleFetch,
+ GetModulator(), custom_fetch_type, registry, client);
}
TEST_F(ModuleScriptLoaderTest, FetchInvalidURL) {
InitializeForDocument();
TestModuleScriptLoaderClient* client = new TestModuleScriptLoaderClient;
- TestFetchInvalidURL(client);
+ TestFetchInvalidURL(ModuleScriptCustomFetchType::kNone, client);
EXPECT_TRUE(client->WasNotifyFinished())
<< "ModuleScriptLoader should finish synchronously.";
@@ -304,32 +320,36 @@ TEST_F(ModuleScriptLoaderTest, FetchInvalidURL) {
TEST_F(ModuleScriptLoaderTest, FetchInvalidURL_OnWorklet) {
InitializeForWorklet();
TestModuleScriptLoaderClient* client = new TestModuleScriptLoaderClient;
- TestFetchInvalidURL(client);
+ TestFetchInvalidURL(ModuleScriptCustomFetchType::kWorkletAddModule, client);
EXPECT_FALSE(client->WasNotifyFinished())
<< "ModuleScriptLoader should finish asynchronously.";
- platform_->RunUntilIdle();
+ RunUntilIdle();
EXPECT_TRUE(client->WasNotifyFinished());
EXPECT_FALSE(client->GetModuleScript());
}
void ModuleScriptLoaderTest::TestFetchURL(
+ ModuleScriptCustomFetchType custom_fetch_type,
TestModuleScriptLoaderClient* client) {
KURL url("https://example.test/module.js");
URLTestHelpers::RegisterMockedURLLoad(
url, test::CoreTestDataPath("module.js"), "text/javascript");
+ auto* fetch_client_settings_object =
+ new FetchClientSettingsObjectSnapshot(GetDocument());
ModuleScriptLoaderRegistry* registry = ModuleScriptLoaderRegistry::Create();
- registry->Fetch(ModuleScriptFetchRequest::CreateForTest(url),
- ModuleGraphLevel::kTopLevelModuleFetch, GetModulator(),
- client);
+ ModuleScriptLoader::Fetch(
+ ModuleScriptFetchRequest::CreateForTest(url),
+ fetch_client_settings_object, ModuleGraphLevel::kTopLevelModuleFetch,
+ GetModulator(), custom_fetch_type, registry, client);
}
TEST_F(ModuleScriptLoaderTest, FetchURL) {
InitializeForDocument();
TestModuleScriptLoaderClient* client = new TestModuleScriptLoaderClient;
- TestFetchURL(client);
+ TestFetchURL(ModuleScriptCustomFetchType::kNone, client);
EXPECT_FALSE(client->WasNotifyFinished())
<< "ModuleScriptLoader unexpectedly finished synchronously.";
@@ -342,16 +362,12 @@ TEST_F(ModuleScriptLoaderTest, FetchURL) {
TEST_F(ModuleScriptLoaderTest, FetchURL_OnWorklet) {
InitializeForWorklet();
TestModuleScriptLoaderClient* client = new TestModuleScriptLoaderClient;
- TestFetchURL(client);
+ TestFetchURL(ModuleScriptCustomFetchType::kWorkletAddModule, client);
EXPECT_FALSE(client->WasNotifyFinished())
<< "ModuleScriptLoader unexpectedly finished synchronously.";
-
- // Advance until WorkerOrWorkletModuleScriptFetcher finishes looking up a
- // cache in WorkletModuleResponsesMap and issues a fetch request so that
- // ServeAsynchronousRequests() can serve for the pending request.
- platform_->RunUntilIdle();
platform_->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ RunUntilIdle();
EXPECT_TRUE(client->WasNotifyFinished());
EXPECT_TRUE(client->GetModuleScript());
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.cc b/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.cc
index f01712f84b6..67a0ecfa41a 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.cc
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.cc
@@ -12,44 +12,57 @@
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loading_log.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "v8/include/v8.h"
namespace blink {
-ModuleTreeLinker* ModuleTreeLinker::Fetch(
+void ModuleTreeLinker::Fetch(
const KURL& url,
- const KURL& base_url,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
WebURLRequest::RequestContext destination,
const ScriptFetchOptions& options,
Modulator* modulator,
+ ModuleScriptCustomFetchType custom_fetch_type,
ModuleTreeLinkerRegistry* registry,
ModuleTreeClient* client) {
ModuleTreeLinker* fetcher =
- new ModuleTreeLinker(destination, modulator, registry, client);
- fetcher->FetchRoot(url, base_url, options);
- return fetcher;
+ new ModuleTreeLinker(fetch_client_settings_object, destination, modulator,
+ custom_fetch_type, registry, client);
+ registry->AddFetcher(fetcher);
+ fetcher->FetchRoot(url, options);
+ DCHECK(fetcher->IsFetching());
}
-ModuleTreeLinker* ModuleTreeLinker::FetchDescendantsForInlineScript(
+void ModuleTreeLinker::FetchDescendantsForInlineScript(
ModuleScript* module_script,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
WebURLRequest::RequestContext destination,
Modulator* modulator,
+ ModuleScriptCustomFetchType custom_fetch_type,
ModuleTreeLinkerRegistry* registry,
ModuleTreeClient* client) {
DCHECK(module_script);
ModuleTreeLinker* fetcher =
- new ModuleTreeLinker(destination, modulator, registry, client);
+ new ModuleTreeLinker(fetch_client_settings_object, destination, modulator,
+ custom_fetch_type, registry, client);
+ registry->AddFetcher(fetcher);
fetcher->FetchRootInline(module_script);
- return fetcher;
+ DCHECK(fetcher->IsFetching());
}
-ModuleTreeLinker::ModuleTreeLinker(WebURLRequest::RequestContext destination,
- Modulator* modulator,
- ModuleTreeLinkerRegistry* registry,
- ModuleTreeClient* client)
- : destination_(destination),
+ModuleTreeLinker::ModuleTreeLinker(
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
+ WebURLRequest::RequestContext destination,
+ Modulator* modulator,
+ ModuleScriptCustomFetchType custom_fetch_type,
+ ModuleTreeLinkerRegistry* registry,
+ ModuleTreeClient* client)
+ : fetch_client_settings_object_(fetch_client_settings_object),
+ destination_(destination),
modulator_(modulator),
+ custom_fetch_type_(custom_fetch_type),
registry_(registry),
client_(client) {
CHECK(modulator);
@@ -58,6 +71,7 @@ ModuleTreeLinker::ModuleTreeLinker(WebURLRequest::RequestContext destination,
}
void ModuleTreeLinker::Trace(blink::Visitor* visitor) {
+ visitor->Trace(fetch_client_settings_object_);
visitor->Trace(modulator_);
visitor->Trace(registry_);
visitor->Trace(client_);
@@ -65,11 +79,6 @@ void ModuleTreeLinker::Trace(blink::Visitor* visitor) {
SingleModuleClient::Trace(visitor);
}
-void ModuleTreeLinker::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(result_);
- SingleModuleClient::TraceWrappers(visitor);
-}
-
#if DCHECK_IS_ON()
const char* ModuleTreeLinker::StateToString(ModuleTreeLinker::State state) {
switch (state) {
@@ -141,7 +150,6 @@ void ModuleTreeLinker::AdvanceState(State new_state) {
// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-module-script-tree
void ModuleTreeLinker::FetchRoot(const KURL& original_url,
- const KURL& base_url,
const ScriptFetchOptions& options) {
#if DCHECK_IS_ON()
original_url_ = original_url;
@@ -155,8 +163,10 @@ void ModuleTreeLinker::FetchRoot(const KURL& original_url,
// href="https://github.com/drufball/layered-apis/blob/master/spec.md#fetch-a-module-script-graph"
// step="1">Set url to the layered API fetching URL given url and the current
// settings object's API base URL.</spec>
- if (RuntimeEnabledFeatures::LayeredAPIEnabled())
- url = blink::layered_api::ResolveFetchingURL(url, base_url);
+ if (RuntimeEnabledFeatures::LayeredAPIEnabled()) {
+ url = blink::layered_api::ResolveFetchingURL(
+ url, fetch_client_settings_object_->BaseURL());
+ }
#if DCHECK_IS_ON()
url_ = url;
@@ -180,8 +190,11 @@ void ModuleTreeLinker::FetchRoot(const KURL& original_url,
// Step 2. Perform the internal module script graph fetching procedure given
// ... with the top-level module fetch flag set. ...
ModuleScriptFetchRequest request(
- url, destination_, options, Referrer::NoReferrer(),
- modulator_->GetReferrerPolicy(), TextPosition::MinimumPosition());
+ url, destination_, options,
+ SecurityPolicy::GenerateReferrer(
+ options.GetReferrerPolicy(), url,
+ fetch_client_settings_object_->GetOutgoingReferrer()),
+ TextPosition::MinimumPosition());
InitiateInternalModuleScriptGraphFetching(
request, ModuleGraphLevel::kTopLevelModuleFetch);
@@ -200,7 +213,7 @@ void ModuleTreeLinker::FetchRootInline(ModuleScript* module_script) {
// Store the |module_script| here which will be used as result of the
// algorithm when success. Also, this ensures that the |module_script| is
- // TraceWrappers()ed via ModuleTreeLinker.
+ // traced via ModuleTreeLinker.
result_ = module_script;
AdvanceState(State::kFetchingDependencies);
@@ -219,7 +232,8 @@ void ModuleTreeLinker::InitiateInternalModuleScriptGraphFetching(
++num_incomplete_fetches_;
// [IMSGF] Step 2. Fetch a single module script given ...
- modulator_->FetchSingle(request, level, this);
+ modulator_->FetchSingle(request, fetch_client_settings_object_.Get(), level,
+ custom_fetch_type_, this);
// [IMSGF] Step 3-- are executed when NotifyModuleLoadFinished() is called.
}
@@ -360,7 +374,8 @@ void ModuleTreeLinker::FetchDescendants(ModuleScript* module_script) {
ScriptFetchOptions options(module_script->FetchOptions().Nonce(),
IntegrityMetadataSet(), String(),
module_script->FetchOptions().ParserState(),
- module_script->FetchOptions().CredentialsMode());
+ module_script->FetchOptions().CredentialsMode(),
+ module_script->FetchOptions().GetReferrerPolicy());
// [FD] Step 7. For each url in urls, ...
//
@@ -368,10 +383,14 @@ void ModuleTreeLinker::FetchDescendants(ModuleScript* module_script) {
// procedure should be performed in parallel to each other.
for (size_t i = 0; i < urls.size(); ++i) {
// [FD] Step 7. ... perform the internal module script graph fetching
- // procedure given ... with the top-level module fetch flag unset. ...
+ // procedure given url, fetch client settings object, destination, options,
+ // module script's settings object, visited set, module script's base URL,
+ // and with the top-level module fetch flag unset. ...
ModuleScriptFetchRequest request(
- urls[i], destination_, options, module_script->BaseURL().GetString(),
- modulator_->GetReferrerPolicy(), positions[i]);
+ urls[i], destination_, options,
+ SecurityPolicy::GenerateReferrer(options.GetReferrerPolicy(), urls[i],
+ module_script->BaseURL().GetString()),
+ positions[i]);
InitiateInternalModuleScriptGraphFetching(
request, ModuleGraphLevel::kDependentModuleFetch);
}
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.h b/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.h
index 811d843ada7..bd67dd7d192 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.h
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.h
@@ -7,6 +7,7 @@
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
@@ -36,28 +37,28 @@ class ModuleTreeLinkerRegistry;
class CORE_EXPORT ModuleTreeLinker final : public SingleModuleClient {
public:
// https://html.spec.whatwg.org/#fetch-a-module-script-tree
- //
- // TODO(hiroshige): |base_url| is used only for Layered APIs and will be
- // removed soon once an upcoming spec change lands.
- static ModuleTreeLinker* Fetch(const KURL&,
- const KURL& base_url,
- WebURLRequest::RequestContext destination,
- const ScriptFetchOptions&,
- Modulator*,
- ModuleTreeLinkerRegistry*,
- ModuleTreeClient*);
+ static void Fetch(
+ const KURL&,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
+ WebURLRequest::RequestContext destination,
+ const ScriptFetchOptions&,
+ Modulator*,
+ ModuleScriptCustomFetchType,
+ ModuleTreeLinkerRegistry*,
+ ModuleTreeClient*);
// [FDaI] for an inline script.
- static ModuleTreeLinker* FetchDescendantsForInlineScript(
+ static void FetchDescendantsForInlineScript(
ModuleScript*,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
WebURLRequest::RequestContext destination,
Modulator*,
+ ModuleScriptCustomFetchType,
ModuleTreeLinkerRegistry*,
ModuleTreeClient*);
~ModuleTreeLinker() override = default;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
bool IsFetching() const {
return State::kFetchingSelf <= state_ && state_ < State::kFinished;
@@ -65,10 +66,13 @@ class CORE_EXPORT ModuleTreeLinker final : public SingleModuleClient {
bool HasFinished() const { return state_ == State::kFinished; }
private:
- ModuleTreeLinker(WebURLRequest::RequestContext destination,
- Modulator*,
- ModuleTreeLinkerRegistry*,
- ModuleTreeClient*);
+ ModuleTreeLinker(
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
+ WebURLRequest::RequestContext destination,
+ Modulator*,
+ ModuleScriptCustomFetchType,
+ ModuleTreeLinkerRegistry*,
+ ModuleTreeClient*);
enum class State {
kInitial,
@@ -85,7 +89,7 @@ class CORE_EXPORT ModuleTreeLinker final : public SingleModuleClient {
#endif
void AdvanceState(State);
- void FetchRoot(const KURL&, const KURL& base_url, const ScriptFetchOptions&);
+ void FetchRoot(const KURL&, const ScriptFetchOptions&);
void FetchRootInline(ModuleScript*);
// Steps 1--2 of [IMSGF].
@@ -108,8 +112,10 @@ class CORE_EXPORT ModuleTreeLinker final : public SingleModuleClient {
ScriptValue FindFirstParseError(ModuleScript*,
HeapHashSet<Member<ModuleScript>>*) const;
+ const Member<FetchClientSettingsObjectSnapshot> fetch_client_settings_object_;
const WebURLRequest::RequestContext destination_;
const Member<Modulator> modulator_;
+ const ModuleScriptCustomFetchType custom_fetch_type_;
HashSet<KURL> visited_set_;
const Member<ModuleTreeLinkerRegistry> registry_;
const Member<ModuleTreeClient> client_;
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.cc b/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.cc
index 0af9e592791..9e1ba283b8e 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.cc
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_tree_linker.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/kurl_hash.h"
@@ -14,36 +15,9 @@ void ModuleTreeLinkerRegistry::Trace(blink::Visitor* visitor) {
visitor->Trace(active_tree_linkers_);
}
-void ModuleTreeLinkerRegistry::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- for (const auto& member : active_tree_linkers_)
- visitor->TraceWrappers(member);
-}
-
-ModuleTreeLinker* ModuleTreeLinkerRegistry::Fetch(
- const KURL& url,
- const KURL& base_url,
- WebURLRequest::RequestContext destination,
- const ScriptFetchOptions& options,
- Modulator* modulator,
- ModuleTreeClient* client) {
- ModuleTreeLinker* fetcher = ModuleTreeLinker::Fetch(
- url, base_url, destination, options, modulator, this, client);
- DCHECK(fetcher->IsFetching());
- active_tree_linkers_.insert(fetcher);
- return fetcher;
-}
-
-ModuleTreeLinker* ModuleTreeLinkerRegistry::FetchDescendantsForInlineScript(
- ModuleScript* module_script,
- WebURLRequest::RequestContext destination,
- Modulator* modulator,
- ModuleTreeClient* client) {
- ModuleTreeLinker* fetcher = ModuleTreeLinker::FetchDescendantsForInlineScript(
- module_script, destination, modulator, this, client);
- DCHECK(fetcher->IsFetching());
+void ModuleTreeLinkerRegistry::AddFetcher(ModuleTreeLinker* fetcher) {
+ DCHECK(!active_tree_linkers_.Contains(fetcher));
active_tree_linkers_.insert(fetcher);
- return fetcher;
}
void ModuleTreeLinkerRegistry::ReleaseFinishedFetcher(
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.h b/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.h
index f50aa9e750d..b5f0b31ab5a 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.h
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.h
@@ -5,51 +5,33 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_MODULE_TREE_LINKER_REGISTRY_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_MODULE_TREE_LINKER_REGISTRY_H_
-#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
-class KURL;
-class Modulator;
-class ModuleTreeClient;
class ModuleTreeLinker;
-class ModuleScript;
-class ScriptFetchOptions;
// ModuleTreeLinkerRegistry keeps active ModuleTreeLinkers alive.
class CORE_EXPORT ModuleTreeLinkerRegistry
: public GarbageCollected<ModuleTreeLinkerRegistry>,
- public TraceWrapperBase {
+ public NameClient {
public:
static ModuleTreeLinkerRegistry* Create() {
return new ModuleTreeLinkerRegistry;
}
void Trace(blink::Visitor*);
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "ModuleTreeLinkerRegistry";
}
- ModuleTreeLinker* Fetch(const KURL&,
- const KURL& base_url,
- WebURLRequest::RequestContext destination,
- const ScriptFetchOptions&,
- Modulator*,
- ModuleTreeClient*);
- ModuleTreeLinker* FetchDescendantsForInlineScript(
- ModuleScript*,
- WebURLRequest::RequestContext destination,
- Modulator*,
- ModuleTreeClient*);
-
private:
ModuleTreeLinkerRegistry() = default;
friend class ModuleTreeLinker;
+ void AddFetcher(ModuleTreeLinker*);
void ReleaseFinishedFetcher(ModuleTreeLinker*);
HeapHashSet<TraceWrapperMember<ModuleTreeLinker>> active_tree_linkers_;
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc b/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc
index 29dc1fd1ee0..3c057f536c3 100644
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker_test.cc
@@ -6,13 +6,14 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/script_module.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/core/loader/modulescript/module_script_fetch_request.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/script/module_script.h"
#include "third_party/blink/renderer/core/testing/dummy_modulator.h"
@@ -54,8 +55,8 @@ class TestModuleTreeClient final : public ModuleTreeClient {
class ModuleTreeLinkerTestModulator final : public DummyModulator {
public:
- ModuleTreeLinkerTestModulator(scoped_refptr<ScriptState> script_state)
- : script_state_(std::move(script_state)) {}
+ ModuleTreeLinkerTestModulator(ScriptState* script_state)
+ : script_state_(script_state) {}
~ModuleTreeLinkerTestModulator() override = default;
void Trace(blink::Visitor*) override;
@@ -67,7 +68,7 @@ class ModuleTreeLinkerTestModulator final : public DummyModulator {
const KURL& url,
const Vector<String>& dependency_module_specifiers,
bool parse_error = false) {
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
StringBuilder source_text;
Vector<ModuleRequest> dependency_module_requests;
@@ -97,7 +98,7 @@ class ModuleTreeLinkerTestModulator final : public DummyModulator {
v8::Local<v8::Value> error = V8ThrowException::CreateError(
script_state_->GetIsolate(), "Parse failure.");
module_script->SetParseErrorAndClearRecord(
- ScriptValue(script_state_.get(), error));
+ ScriptValue(script_state_, error));
}
EXPECT_TRUE(pending_clients_.Contains(url));
@@ -120,12 +121,20 @@ class ModuleTreeLinkerTestModulator final : public DummyModulator {
private:
// Implements Modulator:
- ReferrerPolicy GetReferrerPolicy() override { return kReferrerPolicyDefault; }
- ScriptState* GetScriptState() override { return script_state_.get(); }
+ ScriptState* GetScriptState() override { return script_state_; }
- void FetchSingle(const ModuleScriptFetchRequest& request,
- ModuleGraphLevel,
- SingleModuleClient* client) override {
+ KURL ResolveModuleSpecifier(const String& module_request,
+ const KURL& base_url,
+ String* failure_reason) final {
+ return KURL(base_url, module_request);
+ }
+
+ void FetchSingle(
+ const ModuleScriptFetchRequest& request,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
+ ModuleGraphLevel,
+ ModuleScriptCustomFetchType,
+ SingleModuleClient* client) override {
EXPECT_FALSE(pending_clients_.Contains(request.Url()));
pending_clients_.Set(request.Url(), client);
}
@@ -140,10 +149,10 @@ class ModuleTreeLinkerTestModulator final : public DummyModulator {
ScriptValue InstantiateModule(ScriptModule record) override {
if (instantiate_should_fail_) {
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
v8::Local<v8::Value> error = V8ThrowException::CreateError(
script_state_->GetIsolate(), "Instantiation failure.");
- return ScriptValue(script_state_.get(), error);
+ return ScriptValue(script_state_, error);
}
instantiated_records_.insert(record);
return ScriptValue();
@@ -161,7 +170,7 @@ class ModuleTreeLinkerTestModulator final : public DummyModulator {
return it->value;
}
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
HeapHashMap<KURL, Member<SingleModuleClient>> pending_clients_;
HashMap<ScriptModule, Vector<ModuleRequest>> dependency_module_requests_map_;
HeapHashMap<KURL, Member<ModuleScript>> module_map_;
@@ -170,6 +179,7 @@ class ModuleTreeLinkerTestModulator final : public DummyModulator {
};
void ModuleTreeLinkerTestModulator::Trace(blink::Visitor* visitor) {
+ visitor->Trace(script_state_);
visitor->Trace(pending_clients_);
visitor->Trace(module_map_);
DummyModulator::Trace(visitor);
@@ -190,8 +200,7 @@ class ModuleTreeLinkerTest : public PageTestBase {
void ModuleTreeLinkerTest::SetUp() {
PageTestBase::SetUp(IntSize(500, 500));
- scoped_refptr<ScriptState> script_state =
- ToScriptStateForMainWorld(&GetFrame());
+ ScriptState* script_state = ToScriptStateForMainWorld(&GetFrame());
modulator_ = new ModuleTreeLinkerTestModulator(script_state);
}
@@ -200,8 +209,10 @@ TEST_F(ModuleTreeLinkerTest, FetchTreeNoDeps) {
KURL url("http://example.com/root.js");
TestModuleTreeClient* client = new TestModuleTreeClient;
- registry->Fetch(url, NullURL(), WebURLRequest::kRequestContextScript,
- ScriptFetchOptions(), GetModulator(), client);
+ ModuleTreeLinker::Fetch(
+ url, new FetchClientSettingsObjectSnapshot(GetDocument()),
+ WebURLRequest::kRequestContextScript, ScriptFetchOptions(),
+ GetModulator(), ModuleScriptCustomFetchType::kNone, registry, client);
EXPECT_FALSE(client->WasNotifyFinished())
<< "ModuleTreeLinker should always finish asynchronously.";
@@ -220,8 +231,10 @@ TEST_F(ModuleTreeLinkerTest, FetchTreeInstantiationFailure) {
KURL url("http://example.com/root.js");
TestModuleTreeClient* client = new TestModuleTreeClient;
- registry->Fetch(url, NullURL(), WebURLRequest::kRequestContextScript,
- ScriptFetchOptions(), GetModulator(), client);
+ ModuleTreeLinker::Fetch(
+ url, new FetchClientSettingsObjectSnapshot(GetDocument()),
+ WebURLRequest::kRequestContextScript, ScriptFetchOptions(),
+ GetModulator(), ModuleScriptCustomFetchType::kNone, registry, client);
EXPECT_FALSE(client->WasNotifyFinished())
<< "ModuleTreeLinker should always finish asynchronously.";
@@ -244,8 +257,10 @@ TEST_F(ModuleTreeLinkerTest, FetchTreeWithSingleDependency) {
KURL url("http://example.com/root.js");
TestModuleTreeClient* client = new TestModuleTreeClient;
- registry->Fetch(url, NullURL(), WebURLRequest::kRequestContextScript,
- ScriptFetchOptions(), GetModulator(), client);
+ ModuleTreeLinker::Fetch(
+ url, new FetchClientSettingsObjectSnapshot(GetDocument()),
+ WebURLRequest::kRequestContextScript, ScriptFetchOptions(),
+ GetModulator(), ModuleScriptCustomFetchType::kNone, registry, client);
EXPECT_FALSE(client->WasNotifyFinished())
<< "ModuleTreeLinker should always finish asynchronously.";
@@ -269,8 +284,10 @@ TEST_F(ModuleTreeLinkerTest, FetchTreeWith3Deps) {
KURL url("http://example.com/root.js");
TestModuleTreeClient* client = new TestModuleTreeClient;
- registry->Fetch(url, NullURL(), WebURLRequest::kRequestContextScript,
- ScriptFetchOptions(), GetModulator(), client);
+ ModuleTreeLinker::Fetch(
+ url, new FetchClientSettingsObjectSnapshot(GetDocument()),
+ WebURLRequest::kRequestContextScript, ScriptFetchOptions(),
+ GetModulator(), ModuleScriptCustomFetchType::kNone, registry, client);
EXPECT_FALSE(client->WasNotifyFinished())
<< "ModuleTreeLinker should always finish asynchronously.";
@@ -307,8 +324,10 @@ TEST_F(ModuleTreeLinkerTest, FetchTreeWith3Deps1Fail) {
KURL url("http://example.com/root.js");
TestModuleTreeClient* client = new TestModuleTreeClient;
- registry->Fetch(url, NullURL(), WebURLRequest::kRequestContextScript,
- ScriptFetchOptions(), GetModulator(), client);
+ ModuleTreeLinker::Fetch(
+ url, new FetchClientSettingsObjectSnapshot(GetDocument()),
+ WebURLRequest::kRequestContextScript, ScriptFetchOptions(),
+ GetModulator(), ModuleScriptCustomFetchType::kNone, registry, client);
EXPECT_FALSE(client->WasNotifyFinished())
<< "ModuleTreeLinker should always finish asynchronously.";
@@ -364,8 +383,10 @@ TEST_F(ModuleTreeLinkerTest, FetchDependencyTree) {
KURL url("http://example.com/depth1.js");
TestModuleTreeClient* client = new TestModuleTreeClient;
- registry->Fetch(url, NullURL(), WebURLRequest::kRequestContextScript,
- ScriptFetchOptions(), GetModulator(), client);
+ ModuleTreeLinker::Fetch(
+ url, new FetchClientSettingsObjectSnapshot(GetDocument()),
+ WebURLRequest::kRequestContextScript, ScriptFetchOptions(),
+ GetModulator(), ModuleScriptCustomFetchType::kNone, registry, client);
EXPECT_FALSE(client->WasNotifyFinished())
<< "ModuleTreeLinker should always finish asynchronously.";
@@ -388,8 +409,10 @@ TEST_F(ModuleTreeLinkerTest, FetchDependencyOfCyclicGraph) {
KURL url("http://example.com/a.js");
TestModuleTreeClient* client = new TestModuleTreeClient;
- registry->Fetch(url, NullURL(), WebURLRequest::kRequestContextScript,
- ScriptFetchOptions(), GetModulator(), client);
+ ModuleTreeLinker::Fetch(
+ url, new FetchClientSettingsObjectSnapshot(GetDocument()),
+ WebURLRequest::kRequestContextScript, ScriptFetchOptions(),
+ GetModulator(), ModuleScriptCustomFetchType::kNone, registry, client);
EXPECT_FALSE(client->WasNotifyFinished())
<< "ModuleTreeLinker should always finish asynchronously.";
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc b/chromium/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc
new file mode 100644
index 00000000000..54878e001e2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc
@@ -0,0 +1,96 @@
+// 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/loader/modulescript/worker_module_script_fetcher.h"
+
+#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
+#include "third_party/blink/renderer/platform/network/http_names.h"
+#include "third_party/blink/renderer/platform/weborigin/referrer_policy.h"
+#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
+
+namespace blink {
+
+WorkerModuleScriptFetcher::WorkerModuleScriptFetcher(
+ WorkerGlobalScope* global_scope)
+ : global_scope_(global_scope) {}
+
+// https://html.spec.whatwg.org/multipage/workers.html#worker-processing-model
+void WorkerModuleScriptFetcher::Fetch(FetchParameters& fetch_params,
+ ModuleGraphLevel level,
+ ModuleScriptFetcher::Client* client) {
+ DCHECK(global_scope_->IsContextThread());
+ client_ = client;
+ level_ = level;
+
+ // Step 13. "In both cases, to perform the fetch given request, perform the
+ // following steps if the is top-level flag is set:" [spec text]
+ // Step 13.1. "Set request's reserved client to inside settings." [spec text]
+ // This is implemented in the browser process.
+
+ // Step 13.2. "Fetch request, and asynchronously wait to run the remaining
+ // steps as part of fetch's process response for the response response." [spec
+ // text]
+ ScriptResource::Fetch(fetch_params, global_scope_->EnsureFetcher(), this);
+}
+
+void WorkerModuleScriptFetcher::Trace(blink::Visitor* visitor) {
+ ModuleScriptFetcher::Trace(visitor);
+ visitor->Trace(client_);
+ visitor->Trace(global_scope_);
+}
+
+// https://html.spec.whatwg.org/multipage/workers.html#worker-processing-model
+void WorkerModuleScriptFetcher::NotifyFinished(Resource* resource) {
+ DCHECK(global_scope_->IsContextThread());
+ ClearResource();
+
+ ScriptResource* script_resource = ToScriptResource(resource);
+ HeapVector<Member<ConsoleMessage>> error_messages;
+ if (!WasModuleLoadSuccessful(script_resource, &error_messages)) {
+ client_->NotifyFetchFinished(base::nullopt, error_messages);
+ return;
+ }
+
+ if (level_ == ModuleGraphLevel::kTopLevelModuleFetch) {
+ // TODO(nhiroki, hiroshige): Access to WorkerGlobalScope in module loaders
+ // is a layering violation. Also, updating WorkerGlobalScope ('module map
+ // settigns object') in flight can be dangerous because module loaders may
+ // refers to it. We should move these steps out of core/loader/modulescript/
+ // and run them after module loading. This may require the spec change.
+ // (https://crbug.com/845285)
+
+ // Step 13.3. "Set worker global scope's url to response's url." [spec text]
+ // Step 13.4. "Set worker global scope's HTTPS state to response's HTTPS
+ // state." [spec text]
+
+ // Step 13.5. "Set worker global scope's referrer policy to the result of
+ // parsing the `Referrer-Policy` header of response." [spec text]
+ const String referrer_policy_header =
+ resource->GetResponse().HttpHeaderField(HTTPNames::Referrer_Policy);
+ if (!referrer_policy_header.IsNull()) {
+ ReferrerPolicy referrer_policy = kReferrerPolicyDefault;
+ SecurityPolicy::ReferrerPolicyFromHeaderValue(
+ referrer_policy_header, kDoNotSupportReferrerPolicyLegacyKeywords,
+ &referrer_policy);
+ global_scope_->SetReferrerPolicy(referrer_policy);
+ }
+
+ // Step 13.6. "Execute the Initialize a global object's CSP list algorithm
+ // on worker global scope and response. [CSP]" [spec text]
+ // This is done in the constructor of WorkerGlobalScope.
+ }
+
+ ModuleScriptCreationParams params(
+ script_resource->GetResponse().Url(), script_resource->SourceText(),
+ script_resource->GetResourceRequest().GetFetchCredentialsMode(),
+ script_resource->CalculateAccessControlStatus(
+ global_scope_->EnsureFetcher()->Context().GetSecurityOrigin()));
+
+ // Step 13.7. "Asynchronously complete the perform the fetch steps with
+ // response." [spec text]
+ client_->NotifyFetchFinished(params, error_messages);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.h b/chromium/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.h
new file mode 100644
index 00000000000..f2fde549724
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.h
@@ -0,0 +1,47 @@
+// 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_LOADER_MODULESCRIPT_WORKER_MODULE_SCRIPT_FETCHER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_WORKER_MODULE_SCRIPT_FETCHER_H_
+
+#include "third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.h"
+
+namespace blink {
+
+class WorkerGlobalScope;
+
+// WorkerModuleScriptFetcher is an implementation of ModuleScriptFetcher
+// interface for WebWorkers. This implements the custom "perform the fetch" hook
+// defined in the HTML spec:
+// https://html.spec.whatwg.org/multipage/webappapis.html#fetching-scripts-perform-fetch
+// https://html.spec.whatwg.org/multipage/workers.html#worker-processing-model
+class CORE_EXPORT WorkerModuleScriptFetcher final
+ : public GarbageCollectedFinalized<WorkerModuleScriptFetcher>,
+ public ModuleScriptFetcher {
+ USING_GARBAGE_COLLECTED_MIXIN(WorkerModuleScriptFetcher);
+
+ public:
+ explicit WorkerModuleScriptFetcher(WorkerGlobalScope*);
+
+ // Implements ModuleScriptFetcher.
+ void Fetch(FetchParameters&,
+ ModuleGraphLevel,
+ ModuleScriptFetcher::Client*) override;
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ // Implements ResourceClient
+ void NotifyFinished(Resource*) override;
+ String DebugName() const override { return "WorkerModuleScriptFetcher"; }
+
+ const Member<WorkerGlobalScope> global_scope_;
+
+ Member<Client> client_;
+ ModuleGraphLevel level_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_WORKER_MODULE_SCRIPT_FETCHER_H_
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/worker_or_worklet_module_script_fetcher.cc b/chromium/third_party/blink/renderer/core/loader/modulescript/worker_or_worklet_module_script_fetcher.cc
deleted file mode 100644
index 6fc84657ead..00000000000
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/worker_or_worklet_module_script_fetcher.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/loader/modulescript/worker_or_worklet_module_script_fetcher.h"
-
-#include "third_party/blink/renderer/platform/cross_thread_functional.h"
-
-namespace blink {
-
-WorkerOrWorkletModuleScriptFetcher::WorkerOrWorkletModuleScriptFetcher(
- WorkerOrWorkletModuleFetchCoordinatorProxy* coordinator_proxy)
- : coordinator_proxy_(coordinator_proxy) {
- DCHECK(coordinator_proxy_);
-}
-
-void WorkerOrWorkletModuleScriptFetcher::Trace(blink::Visitor* visitor) {
- visitor->Trace(coordinator_proxy_);
- ModuleScriptFetcher::Trace(visitor);
-}
-
-void WorkerOrWorkletModuleScriptFetcher::Fetch(
- FetchParameters& fetch_params,
- ModuleScriptFetcher::Client* client) {
- SetClient(client);
- coordinator_proxy_->Fetch(fetch_params, this);
-}
-
-void WorkerOrWorkletModuleScriptFetcher::OnFetched(
- const ModuleScriptCreationParams& params) {
- HeapVector<Member<ConsoleMessage>> error_messages;
- Finalize(params, error_messages);
-}
-
-void WorkerOrWorkletModuleScriptFetcher::OnFailed() {
- HeapVector<Member<ConsoleMessage>> error_messages;
- Finalize(base::nullopt, error_messages);
-}
-
-void WorkerOrWorkletModuleScriptFetcher::Finalize(
- const base::Optional<ModuleScriptCreationParams>& params,
- const HeapVector<Member<ConsoleMessage>>& error_messages) {
- NotifyFetchFinished(params, error_messages);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/worker_or_worklet_module_script_fetcher.h b/chromium/third_party/blink/renderer/core/loader/modulescript/worker_or_worklet_module_script_fetcher.h
deleted file mode 100644
index 00d21e389b6..00000000000
--- a/chromium/third_party/blink/renderer/core/loader/modulescript/worker_or_worklet_module_script_fetcher.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_WORKER_OR_WORKLET_MODULE_SCRIPT_FETCHER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_WORKER_OR_WORKLET_MODULE_SCRIPT_FETCHER_H_
-
-#include "base/optional.h"
-#include "third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.h"
-#include "third_party/blink/renderer/core/workers/worker_or_worklet_module_fetch_coordinator_proxy.h"
-#include "third_party/blink/renderer/core/workers/worklet_module_responses_map.h"
-
-namespace blink {
-
-// WorkerOrWorkletModuleScriptFetcher does not initiate module fetch by itself.
-// Instead, this delegates it to WorkletModuleResponsesMap on the
-// main thread via WorkerOrWorkletModuleFetchCoordinatorProxy.
-// TODO(japhet): Rename to WorkletModuleScriptFetcher
-class CORE_EXPORT WorkerOrWorkletModuleScriptFetcher final
- : public ModuleScriptFetcher,
- public WorkletModuleResponsesMap::Client {
- USING_GARBAGE_COLLECTED_MIXIN(WorkerOrWorkletModuleScriptFetcher);
-
- public:
- explicit WorkerOrWorkletModuleScriptFetcher(
- WorkerOrWorkletModuleFetchCoordinatorProxy*);
-
- // Implements ModuleScriptFetcher.
- void Fetch(FetchParameters&, ModuleScriptFetcher::Client*) override;
-
- // Implements WorkletModuleResponsesMap::Client.
- void OnFetched(const ModuleScriptCreationParams&) override;
- void OnFailed() override;
-
- void Trace(blink::Visitor*) override;
-
- private:
- void Finalize(const base::Optional<ModuleScriptCreationParams>&,
- const HeapVector<Member<ConsoleMessage>>& error_messages);
-
- Member<WorkerOrWorkletModuleFetchCoordinatorProxy> coordinator_proxy_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_WORKER_OR_WORKLET_MODULE_SCRIPT_FETCHER_H_
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.cc b/chromium/third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.cc
new file mode 100644
index 00000000000..4edfaeadd2d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.cc
@@ -0,0 +1,63 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.h"
+
+#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
+
+namespace blink {
+
+WorkletModuleScriptFetcher::WorkletModuleScriptFetcher(
+ ResourceFetcher* fetcher,
+ WorkletModuleResponsesMap* module_responses_map)
+ : fetcher_(fetcher), module_responses_map_(module_responses_map) {}
+
+void WorkletModuleScriptFetcher::Trace(blink::Visitor* visitor) {
+ ModuleScriptFetcher::Trace(visitor);
+ visitor->Trace(fetcher_);
+}
+
+void WorkletModuleScriptFetcher::Fetch(FetchParameters& fetch_params,
+ ModuleGraphLevel level,
+ ModuleScriptFetcher::Client* client) {
+ if (module_responses_map_->GetEntry(
+ fetch_params.Url(), client,
+ fetcher_->Context().GetLoadingTaskRunner())) {
+ return;
+ }
+
+ // TODO(japhet): This worklet global scope will drive the fetch of this
+ // module. If another global scope requests the same module,
+ // module_responses_map_ will ensure that it is notified when this fetch
+ // completes. Currently, all worklet global scopes are destroyed when the
+ // Document is destroyed, so we won't end up in a situation where this global
+ // scope is being destroyed and needs to cancel the fetch, but some other
+ // global scope is still alive and still wants to complete the fetch. When we
+ // support worklet global scopes being created and destroyed flexibly, we'll
+ // need to handle that case, maybe by having a way to restart fetches in a
+ // different global scope?
+ url_ = fetch_params.Url();
+ ScriptResource::Fetch(fetch_params, fetcher_.Get(), this);
+}
+
+void WorkletModuleScriptFetcher::NotifyFinished(Resource* resource) {
+ ClearResource();
+
+ base::Optional<ModuleScriptCreationParams> params;
+ ScriptResource* script_resource = ToScriptResource(resource);
+ HeapVector<Member<ConsoleMessage>> error_messages;
+ if (WasModuleLoadSuccessful(script_resource, &error_messages)) {
+ params.emplace(
+ script_resource->GetResponse().Url(), script_resource->SourceText(),
+ script_resource->GetResourceRequest().GetFetchCredentialsMode(),
+ script_resource->CalculateAccessControlStatus(
+ fetcher_->Context().GetSecurityOrigin()));
+ }
+
+ // This will eventually notify |client| passed to
+ // WorkletModuleScriptFetcher::Fetch().
+ module_responses_map_->SetEntryParams(url_, params);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.h b/chromium/third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.h
new file mode 100644
index 00000000000..aa8f57baa2e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.h
@@ -0,0 +1,59 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_WORKLET_MODULE_SCRIPT_FETCHER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_WORKLET_MODULE_SCRIPT_FETCHER_H_
+
+#include "base/optional.h"
+#include "third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.h"
+#include "third_party/blink/renderer/core/workers/worklet_module_responses_map.h"
+
+namespace blink {
+
+class ResourceFetcher;
+
+// WorkletModuleScriptFetcher is an implementation of ModuleScriptFetcher
+// interface for Worklets. This implements the custom "perform the fetch" hook
+// defined in the Worklets spec:
+// https://html.spec.whatwg.org/multipage/webappapis.html#fetching-scripts-perform-fetch
+// https://drafts.css-houdini.org/worklets/#fetch-a-worklet-script
+//
+// WorkletModuleScriptFetcher either fetchs a cached result from
+// WorkletModuleResponsesMap, or defers to ModuleScriptFetcher and
+// stores the result in WorkletModuleResponsesMap on fetch completion.
+class CORE_EXPORT WorkletModuleScriptFetcher final
+ : public GarbageCollectedFinalized<WorkletModuleScriptFetcher>,
+ public ModuleScriptFetcher {
+ USING_GARBAGE_COLLECTED_MIXIN(WorkletModuleScriptFetcher);
+
+ public:
+ WorkletModuleScriptFetcher(ResourceFetcher*, WorkletModuleResponsesMap*);
+
+ // Implements ModuleScriptFetcher.
+ void Fetch(FetchParameters&,
+ ModuleGraphLevel,
+ ModuleScriptFetcher::Client*) override;
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ // Implements ResourceClient
+ void NotifyFinished(Resource*) override;
+ String DebugName() const override { return "WorkletModuleScriptFetcher"; }
+
+ const Member<ResourceFetcher> fetcher_;
+
+ // TODO(nhiroki): In general, CrossThreadPersistent is heavy and should not be
+ // owned by objects that can frequently be created like this class. Instead of
+ // retaining a reference to WorkletModuleResponsesMap, this class should
+ // access the map via WorkletGlobalScope::GetModuleResponsesMap().
+ // Bonus: WorkletGlobalScope can provide ResourceFetcher, too.
+ CrossThreadPersistent<WorkletModuleResponsesMap> module_responses_map_;
+
+ KURL url_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_WORKLET_MODULE_SCRIPT_FETCHER_H_
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 7d9f4fc7198..cb4fa0ff3fa 100644
--- a/chromium/third_party/blink/renderer/core/loader/navigation_policy.cc
+++ b/chromium/third_party/blink/renderer/core/loader/navigation_policy.cc
@@ -31,38 +31,167 @@
#include "third_party/blink/renderer/core/loader/navigation_policy.h"
#include "build/build_config.h"
+#include "third_party/blink/public/platform/web_keyboard_event.h"
+#include "third_party/blink/public/platform/web_mouse_event.h"
#include "third_party/blink/public/web/web_navigation_policy.h"
+#include "third_party/blink/public/web/web_window_features.h"
+#include "third_party/blink/renderer/core/events/current_input_event.h"
+#include "third_party/blink/renderer/core/events/gesture_event.h"
+#include "third_party/blink/renderer/core/events/keyboard_event.h"
+#include "third_party/blink/renderer/core/events/mouse_event.h"
+#include "third_party/blink/renderer/core/events/ui_event_with_key_state.h"
+#include "third_party/blink/renderer/platform/keyboard_codes.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink {
-bool NavigationPolicyFromMouseEvent(unsigned short button,
- bool ctrl,
- bool shift,
- bool alt,
- bool meta,
- NavigationPolicy* policy) {
+namespace {
+
+NavigationPolicy NavigationPolicyFromEventModifiers(unsigned short button,
+ bool ctrl,
+ bool shift,
+ bool alt,
+ bool meta) {
#if defined(OS_MACOSX)
const bool new_tab_modifier = (button == 1) || meta;
#else
const bool new_tab_modifier = (button == 1) || ctrl;
#endif
if (!new_tab_modifier && !shift && !alt)
- return false;
+ return kNavigationPolicyCurrentTab;
- DCHECK(policy);
if (new_tab_modifier) {
if (shift)
- *policy = kNavigationPolicyNewForegroundTab;
+ return kNavigationPolicyNewForegroundTab;
else
- *policy = kNavigationPolicyNewBackgroundTab;
+ return kNavigationPolicyNewBackgroundTab;
} else {
if (shift)
- *policy = kNavigationPolicyNewWindow;
+ return kNavigationPolicyNewWindow;
else
- *policy = kNavigationPolicyDownload;
+ return kNavigationPolicyDownload;
+ }
+ return kNavigationPolicyCurrentTab;
+}
+
+NavigationPolicy NavigationPolicyFromEventInternal(Event* event) {
+ if (!event)
+ return kNavigationPolicyCurrentTab;
+
+ if (event->IsMouseEvent()) {
+ MouseEvent* mouse_event = ToMouseEvent(event);
+ return NavigationPolicyFromEventModifiers(
+ mouse_event->button(), mouse_event->ctrlKey(), mouse_event->shiftKey(),
+ mouse_event->altKey(), mouse_event->metaKey());
+ } else if (event->IsKeyboardEvent()) {
+ // The click is simulated when triggering the keypress event.
+ KeyboardEvent* key_event = ToKeyboardEvent(event);
+ return NavigationPolicyFromEventModifiers(
+ 0, key_event->ctrlKey(), key_event->shiftKey(), key_event->altKey(),
+ key_event->metaKey());
+ } else if (event->IsGestureEvent()) {
+ // The click is simulated when triggering the gesture-tap event
+ GestureEvent* gesture_event = ToGestureEvent(event);
+ return NavigationPolicyFromEventModifiers(
+ 0, gesture_event->ctrlKey(), gesture_event->shiftKey(),
+ gesture_event->altKey(), gesture_event->metaKey());
}
- return true;
+ return kNavigationPolicyCurrentTab;
+}
+
+NavigationPolicy NavigationPolicyFromCurrentEvent() {
+ const WebInputEvent* event = CurrentInputEvent::Get();
+ if (!event)
+ return kNavigationPolicyCurrentTab;
+
+ unsigned short button = 0;
+ if (event->GetType() == WebInputEvent::kMouseUp) {
+ const WebMouseEvent* mouse_event = static_cast<const WebMouseEvent*>(event);
+
+ switch (mouse_event->button) {
+ case WebMouseEvent::Button::kLeft:
+ button = 0;
+ break;
+ case WebMouseEvent::Button::kMiddle:
+ button = 1;
+ break;
+ case WebMouseEvent::Button::kRight:
+ button = 2;
+ break;
+ default:
+ return kNavigationPolicyCurrentTab;
+ }
+ } else if ((WebInputEvent::IsKeyboardEventType(event->GetType()) &&
+ static_cast<const WebKeyboardEvent*>(event)->windows_key_code ==
+ VKEY_RETURN) ||
+ WebInputEvent::IsGestureEventType(event->GetType())) {
+ // Keyboard and gesture events can simulate mouse events.
+ button = 0;
+ } else {
+ return kNavigationPolicyCurrentTab;
+ }
+
+ return NavigationPolicyFromEventModifiers(
+ button, event->GetModifiers() & WebInputEvent::kControlKey,
+ event->GetModifiers() & WebInputEvent::kShiftKey,
+ event->GetModifiers() & WebInputEvent::kAltKey,
+ event->GetModifiers() & WebInputEvent::kMetaKey);
+}
+
+} // namespace
+
+NavigationPolicy NavigationPolicyFromEvent(Event* event) {
+ NavigationPolicy event_policy = NavigationPolicyFromEventInternal(event);
+ NavigationPolicy input_policy = NavigationPolicyFromCurrentEvent();
+
+ if (event_policy == kNavigationPolicyDownload &&
+ input_policy != kNavigationPolicyDownload) {
+ // No downloads from synthesized events without user intention.
+ return kNavigationPolicyCurrentTab;
+ }
+
+ if (event_policy == kNavigationPolicyNewBackgroundTab &&
+ input_policy != kNavigationPolicyNewBackgroundTab &&
+ !UIEventWithKeyState::NewTabModifierSetFromIsolatedWorld()) {
+ // No "tab-unders" from synthesized events without user intention.
+ // Events originating from an isolated world are exempt.
+ return kNavigationPolicyNewForegroundTab;
+ }
+
+ return event_policy;
+}
+
+NavigationPolicy NavigationPolicyForCreateWindow(
+ const WebWindowFeatures& features) {
+ // If our default configuration was modified by a script or wasn't
+ // created by a user gesture, then show as a popup. Else, let this
+ // new window be opened as a toplevel window.
+ bool as_popup = !features.tool_bar_visible || !features.status_bar_visible ||
+ !features.scrollbars_visible || !features.menu_bar_visible ||
+ !features.resizable;
+ NavigationPolicy app_policy =
+ as_popup ? kNavigationPolicyNewPopup : kNavigationPolicyNewForegroundTab;
+ NavigationPolicy user_policy = NavigationPolicyFromCurrentEvent();
+
+ if (user_policy == kNavigationPolicyNewWindow &&
+ app_policy == kNavigationPolicyNewPopup) {
+ // User and app agree that we want a new window; let the app override the
+ // decorations.
+ return app_policy;
+ }
+
+ if (user_policy == kNavigationPolicyCurrentTab) {
+ // User doesn't want a specific policy, use app policy instead.
+ return app_policy;
+ }
+
+ if (user_policy == kNavigationPolicyDownload) {
+ // When the input event suggests a download, but the navigation was
+ // initiated by script, we should not override it.
+ return app_policy;
+ }
+
+ return user_policy;
}
STATIC_ASSERT_ENUM(kWebNavigationPolicyIgnore, kNavigationPolicyIgnore);
diff --git a/chromium/third_party/blink/renderer/core/loader/navigation_policy.h b/chromium/third_party/blink/renderer/core/loader/navigation_policy.h
index 7aa9973dcdf..6be8416b62f 100644
--- a/chromium/third_party/blink/renderer/core/loader/navigation_policy.h
+++ b/chromium/third_party/blink/renderer/core/loader/navigation_policy.h
@@ -35,6 +35,9 @@
namespace blink {
+class Event;
+struct WebWindowFeatures;
+
enum NavigationPolicy {
kNavigationPolicyIgnore,
kNavigationPolicyDownload,
@@ -47,12 +50,17 @@ enum NavigationPolicy {
kNavigationPolicyHandledByClientForInitialHistory,
};
-CORE_EXPORT bool NavigationPolicyFromMouseEvent(unsigned short button,
- bool ctrl,
- bool shift,
- bool alt,
- bool meta,
- NavigationPolicy*);
+// Returns a NavigationPolicy to use for starting a navigation
+// based on the Event. This function takes care of some security checks,
+// ensuring that synthesized events cannot trigger arbitrary downloads
+// or new tabs without user intention coming from a real input event.
+CORE_EXPORT NavigationPolicy NavigationPolicyFromEvent(Event*);
+
+// Returns a NavigationPolicy to use for navigating a new window.
+// This function respects user intention coming from a real input event,
+// and ensures that we don't perform a download instead of navigation.
+CORE_EXPORT NavigationPolicy
+NavigationPolicyForCreateWindow(const WebWindowFeatures&);
} // namespace blink
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
new file mode 100644
index 00000000000..ee8e66d906a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/loader/navigation_policy_test.cc
@@ -0,0 +1,329 @@
+/*
+ * 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/loader/navigation_policy.h"
+#include "base/auto_reset.h"
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/web_input_event.h"
+#include "third_party/blink/public/platform/web_mouse_event.h"
+#include "third_party/blink/public/web/web_window_features.h"
+#include "third_party/blink/renderer/core/events/current_input_event.h"
+#include "third_party/blink/renderer/core/events/mouse_event.h"
+
+namespace blink {
+
+class NavigationPolicyTest : public testing::Test {
+ protected:
+ NavigationPolicy GetPolicyForCreateWindow(int modifiers,
+ WebMouseEvent::Button button,
+ bool as_popup) {
+ WebMouseEvent event(WebInputEvent::kMouseUp, modifiers,
+ WebInputEvent::GetStaticTimeStampForTests());
+ event.button = button;
+ if (as_popup)
+ features.tool_bar_visible = false;
+ base::AutoReset<const WebInputEvent*> current_event_change(
+ &CurrentInputEvent::current_input_event_, &event);
+ return NavigationPolicyForCreateWindow(features);
+ }
+
+ Event* GetEvent(int modifiers, WebMouseEvent::Button button) {
+ MouseEventInit mouse_initializer;
+ if (button == WebMouseEvent::Button::kLeft)
+ mouse_initializer.setButton(0);
+ if (button == WebMouseEvent::Button::kMiddle)
+ mouse_initializer.setButton(1);
+ if (button == WebMouseEvent::Button::kRight)
+ mouse_initializer.setButton(2);
+ if (modifiers & WebInputEvent::kShiftKey)
+ mouse_initializer.setShiftKey(true);
+ if (modifiers & WebInputEvent::kControlKey)
+ mouse_initializer.setCtrlKey(true);
+ if (modifiers & WebInputEvent::kAltKey)
+ mouse_initializer.setAltKey(true);
+ if (modifiers & WebInputEvent::kMetaKey)
+ mouse_initializer.setMetaKey(true);
+ return MouseEvent::Create(nullptr, EventTypeNames::click,
+ mouse_initializer);
+ }
+
+ NavigationPolicy GetPolicyFromEvent(int modifiers,
+ WebMouseEvent::Button button,
+ int user_modifiers,
+ WebMouseEvent::Button user_button) {
+ WebMouseEvent event(WebInputEvent::kMouseUp, user_modifiers,
+ WebInputEvent::GetStaticTimeStampForTests());
+ event.button = user_button;
+ base::AutoReset<const WebInputEvent*> current_event_change(
+ &CurrentInputEvent::current_input_event_, &event);
+ return NavigationPolicyFromEvent(GetEvent(modifiers, button));
+ }
+
+ WebWindowFeatures features;
+};
+
+TEST_F(NavigationPolicyTest, LeftClick) {
+ int modifiers = 0;
+ WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
+ bool as_popup = false;
+ EXPECT_EQ(kNavigationPolicyNewForegroundTab,
+ GetPolicyForCreateWindow(modifiers, button, as_popup));
+}
+
+TEST_F(NavigationPolicyTest, LeftClickPopup) {
+ int modifiers = 0;
+ WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
+ bool as_popup = true;
+ EXPECT_EQ(kNavigationPolicyNewPopup,
+ GetPolicyForCreateWindow(modifiers, button, as_popup));
+}
+
+TEST_F(NavigationPolicyTest, ShiftLeftClick) {
+ int modifiers = WebInputEvent::kShiftKey;
+ WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
+ bool as_popup = false;
+ EXPECT_EQ(kNavigationPolicyNewWindow,
+ GetPolicyForCreateWindow(modifiers, button, as_popup));
+}
+
+TEST_F(NavigationPolicyTest, ShiftLeftClickPopup) {
+ int modifiers = WebInputEvent::kShiftKey;
+ WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
+ bool as_popup = true;
+ EXPECT_EQ(kNavigationPolicyNewPopup,
+ GetPolicyForCreateWindow(modifiers, button, as_popup));
+}
+
+TEST_F(NavigationPolicyTest, ControlOrMetaLeftClick) {
+#if defined(OS_MACOSX)
+ int modifiers = WebInputEvent::kMetaKey;
+#else
+ int modifiers = WebInputEvent::kControlKey;
+#endif
+ WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
+ bool as_popup = false;
+ EXPECT_EQ(kNavigationPolicyNewBackgroundTab,
+ GetPolicyForCreateWindow(modifiers, button, as_popup));
+}
+
+TEST_F(NavigationPolicyTest, ControlOrMetaLeftClickPopup) {
+#if defined(OS_MACOSX)
+ int modifiers = WebInputEvent::kMetaKey;
+#else
+ int modifiers = WebInputEvent::kControlKey;
+#endif
+ WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
+ bool as_popup = true;
+ EXPECT_EQ(kNavigationPolicyNewBackgroundTab,
+ GetPolicyForCreateWindow(modifiers, button, as_popup));
+}
+
+TEST_F(NavigationPolicyTest, ControlOrMetaAndShiftLeftClick) {
+#if defined(OS_MACOSX)
+ int modifiers = WebInputEvent::kMetaKey;
+#else
+ int modifiers = WebInputEvent::kControlKey;
+#endif
+ modifiers |= WebInputEvent::kShiftKey;
+ WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
+ bool as_popup = false;
+ EXPECT_EQ(kNavigationPolicyNewForegroundTab,
+ GetPolicyForCreateWindow(modifiers, button, as_popup));
+}
+
+TEST_F(NavigationPolicyTest, ControlOrMetaAndShiftLeftClickPopup) {
+#if defined(OS_MACOSX)
+ int modifiers = WebInputEvent::kMetaKey;
+#else
+ int modifiers = WebInputEvent::kControlKey;
+#endif
+ modifiers |= WebInputEvent::kShiftKey;
+ WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
+ bool as_popup = true;
+ EXPECT_EQ(kNavigationPolicyNewForegroundTab,
+ GetPolicyForCreateWindow(modifiers, button, as_popup));
+}
+
+TEST_F(NavigationPolicyTest, MiddleClick) {
+ int modifiers = 0;
+ bool as_popup = false;
+ WebMouseEvent::Button button = WebMouseEvent::Button::kMiddle;
+ EXPECT_EQ(kNavigationPolicyNewBackgroundTab,
+ GetPolicyForCreateWindow(modifiers, button, as_popup));
+}
+
+TEST_F(NavigationPolicyTest, MiddleClickPopup) {
+ int modifiers = 0;
+ bool as_popup = true;
+ WebMouseEvent::Button button = WebMouseEvent::Button::kMiddle;
+ EXPECT_EQ(kNavigationPolicyNewBackgroundTab,
+ GetPolicyForCreateWindow(modifiers, button, as_popup));
+}
+
+TEST_F(NavigationPolicyTest, NoToolbarsForcesPopup) {
+ features.tool_bar_visible = false;
+ EXPECT_EQ(kNavigationPolicyNewPopup,
+ NavigationPolicyForCreateWindow(features));
+ features.tool_bar_visible = true;
+ EXPECT_EQ(kNavigationPolicyNewForegroundTab,
+ NavigationPolicyForCreateWindow(features));
+}
+
+TEST_F(NavigationPolicyTest, NoStatusBarForcesPopup) {
+ features.status_bar_visible = false;
+ EXPECT_EQ(kNavigationPolicyNewPopup,
+ NavigationPolicyForCreateWindow(features));
+ features.status_bar_visible = true;
+ EXPECT_EQ(kNavigationPolicyNewForegroundTab,
+ NavigationPolicyForCreateWindow(features));
+}
+
+TEST_F(NavigationPolicyTest, NoMenuBarForcesPopup) {
+ features.menu_bar_visible = false;
+ EXPECT_EQ(kNavigationPolicyNewPopup,
+ NavigationPolicyForCreateWindow(features));
+ features.menu_bar_visible = true;
+ EXPECT_EQ(kNavigationPolicyNewForegroundTab,
+ NavigationPolicyForCreateWindow(features));
+}
+
+TEST_F(NavigationPolicyTest, NotResizableForcesPopup) {
+ features.resizable = false;
+ EXPECT_EQ(kNavigationPolicyNewPopup,
+ NavigationPolicyForCreateWindow(features));
+ features.resizable = true;
+ EXPECT_EQ(kNavigationPolicyNewForegroundTab,
+ NavigationPolicyForCreateWindow(features));
+}
+
+TEST_F(NavigationPolicyTest, EventLeftClick) {
+ int modifiers = 0;
+ WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
+ EXPECT_EQ(kNavigationPolicyCurrentTab,
+ NavigationPolicyFromEvent(GetEvent(modifiers, button)));
+}
+
+TEST_F(NavigationPolicyTest, EventShiftLeftClick) {
+ int modifiers = WebInputEvent::kShiftKey;
+ WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
+ EXPECT_EQ(kNavigationPolicyNewWindow,
+ NavigationPolicyFromEvent(GetEvent(modifiers, button)));
+}
+
+TEST_F(NavigationPolicyTest, EventControlOrMetaLeftClick) {
+#if defined(OS_MACOSX)
+ int modifiers = WebInputEvent::kMetaKey;
+#else
+ int modifiers = WebInputEvent::kControlKey;
+#endif
+ WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
+ EXPECT_EQ(kNavigationPolicyNewForegroundTab,
+ NavigationPolicyFromEvent(GetEvent(modifiers, button)));
+}
+
+TEST_F(NavigationPolicyTest, EventControlOrMetaLeftClickWithUserEvent) {
+#if defined(OS_MACOSX)
+ int modifiers = WebInputEvent::kMetaKey;
+#else
+ int modifiers = WebInputEvent::kControlKey;
+#endif
+ WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
+ EXPECT_EQ(kNavigationPolicyNewBackgroundTab,
+ GetPolicyFromEvent(modifiers, button, modifiers, button));
+}
+
+TEST_F(NavigationPolicyTest,
+ EventControlOrMetaLeftClickWithDifferentUserEvent) {
+#if defined(OS_MACOSX)
+ int modifiers = WebInputEvent::kMetaKey;
+#else
+ int modifiers = WebInputEvent::kControlKey;
+#endif
+ WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
+ EXPECT_EQ(kNavigationPolicyNewForegroundTab,
+ GetPolicyFromEvent(modifiers, button, 0, button));
+}
+
+TEST_F(NavigationPolicyTest, EventShiftControlOrMetaLeftClick) {
+#if defined(OS_MACOSX)
+ int modifiers = WebInputEvent::kMetaKey | WebInputEvent::kShiftKey;
+#else
+ int modifiers = WebInputEvent::kControlKey | WebInputEvent::kShiftKey;
+#endif
+ WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
+ EXPECT_EQ(kNavigationPolicyNewForegroundTab,
+ NavigationPolicyFromEvent(GetEvent(modifiers, button)));
+}
+
+TEST_F(NavigationPolicyTest, EventMiddleClick) {
+ int modifiers = 0;
+ WebMouseEvent::Button button = WebMouseEvent::Button::kMiddle;
+ EXPECT_EQ(kNavigationPolicyNewForegroundTab,
+ NavigationPolicyFromEvent(GetEvent(modifiers, button)));
+}
+
+TEST_F(NavigationPolicyTest, EventMiddleClickWithUserEvent) {
+ int modifiers = 0;
+ WebMouseEvent::Button button = WebMouseEvent::Button::kMiddle;
+ EXPECT_EQ(kNavigationPolicyNewBackgroundTab,
+ GetPolicyFromEvent(modifiers, button, modifiers, button));
+}
+
+TEST_F(NavigationPolicyTest, EventMiddleClickWithDifferentUserEvent) {
+ int modifiers = 0;
+ WebMouseEvent::Button button = WebMouseEvent::Button::kMiddle;
+ WebMouseEvent::Button user_button = WebMouseEvent::Button::kLeft;
+ EXPECT_EQ(kNavigationPolicyNewForegroundTab,
+ GetPolicyFromEvent(modifiers, button, modifiers, user_button));
+}
+
+TEST_F(NavigationPolicyTest, EventAltClick) {
+ int modifiers = WebInputEvent::kAltKey;
+ WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
+ EXPECT_EQ(kNavigationPolicyCurrentTab,
+ NavigationPolicyFromEvent(GetEvent(modifiers, button)));
+}
+
+TEST_F(NavigationPolicyTest, EventAltClickWithUserEvent) {
+ int modifiers = WebInputEvent::kAltKey;
+ WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
+ EXPECT_EQ(kNavigationPolicyDownload,
+ GetPolicyFromEvent(modifiers, button, modifiers, button));
+}
+
+TEST_F(NavigationPolicyTest, EventAltClickWithDifferentUserEvent) {
+ int modifiers = WebInputEvent::kAltKey;
+ WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
+ EXPECT_EQ(kNavigationPolicyCurrentTab,
+ GetPolicyFromEvent(modifiers, button, 0, button));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/navigation_scheduler.cc b/chromium/third_party/blink/renderer/core/loader/navigation_scheduler.cc
index e15e5751165..44e517b77c4 100644
--- a/chromium/third_party/blink/renderer/core/loader/navigation_scheduler.cc
+++ b/chromium/third_party/blink/renderer/core/loader/navigation_scheduler.cc
@@ -33,6 +33,7 @@
#include "third_party/blink/renderer/core/loader/navigation_scheduler.h"
#include <memory>
+#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
@@ -132,7 +133,7 @@ class ScheduledURLNavigation : public ScheduledNavigation {
}
if (origin_document && url.ProtocolIs("blob") &&
- RuntimeEnabledFeatures::MojoBlobURLsEnabled()) {
+ BlobUtils::MojoBlobURLsEnabled()) {
origin_document->GetPublicURLManager().Resolve(
url_, MakeRequest(&blob_url_token_));
}
@@ -259,14 +260,14 @@ class ScheduledReload final : public ScheduledNavigation {
std::unique_ptr<UserGestureIndicator> gesture_indicator =
CreateUserGestureIndicator();
ResourceRequest resource_request = frame->Loader().ResourceRequestForReload(
- kFrameLoadTypeReload, ClientRedirectPolicy::kClientRedirect);
+ WebFrameLoadType::kReload, ClientRedirectPolicy::kClientRedirect);
if (resource_request.IsNull())
return;
FrameLoadRequest request = FrameLoadRequest(nullptr, resource_request);
request.SetClientRedirect(ClientRedirectPolicy::kClientRedirect);
MaybeLogScheduledNavigationClobber(
ScheduledNavigationType::kScheduledReload, frame);
- frame->Loader().StartNavigation(request, kFrameLoadTypeReload);
+ frame->Loader().StartNavigation(request, WebFrameLoadType::kReload);
}
KURL Url() const override { return frame_->GetDocument()->Url(); }
@@ -331,7 +332,8 @@ class ScheduledFormSubmission final : public ScheduledNavigation {
frame_request.SetReplacesCurrentItem(ReplacesCurrentItem());
MaybeLogScheduledNavigationClobber(
ScheduledNavigationType::kScheduledFormSubmission, frame);
- frame->Loader().StartNavigation(frame_request);
+ frame->Loader().StartNavigation(frame_request, WebFrameLoadType::kStandard,
+ submission_->GetNavigationPolicy());
}
KURL Url() const override { return submission_->RequestURL(); }
diff --git a/chromium/third_party/blink/renderer/core/loader/navigation_scheduler.h b/chromium/third_party/blink/renderer/core/loader/navigation_scheduler.h
index 8e8ae019cd8..67cd23e4ad5 100644
--- a/chromium/third_party/blink/renderer/core/loader/navigation_scheduler.h
+++ b/chromium/third_party/blink/renderer/core/loader/navigation_scheduler.h
@@ -36,7 +36,7 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.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"
diff --git a/chromium/third_party/blink/renderer/core/loader/ping_loader_test.cc b/chromium/third_party/blink/renderer/core/loader/ping_loader_test.cc
index e8eacea53a0..1eec52dd218 100644
--- a/chromium/third_party/blink/renderer/core/loader/ping_loader_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/ping_loader_test.cc
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/loader/frame_loader.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/loader/fetch/substitute_data.h"
+#include "third_party/blink/renderer/platform/network/encoded_form_data.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/weborigin/kurl.h"
diff --git a/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_receiver_impl.cc b/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_receiver_impl.cc
new file mode 100644
index 00000000000..6a1a5e43253
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_receiver_impl.cc
@@ -0,0 +1,28 @@
+// 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/loader/previews_resource_loading_hints_receiver_impl.h"
+
+#include "base/metrics/histogram_macros.h"
+
+namespace blink {
+
+PreviewsResourceLoadingHintsReceiverImpl::
+ PreviewsResourceLoadingHintsReceiverImpl(
+ mojom::blink::PreviewsResourceLoadingHintsReceiverRequest request)
+ : binding_(this, std::move(request)) {}
+
+PreviewsResourceLoadingHintsReceiverImpl::
+ ~PreviewsResourceLoadingHintsReceiverImpl() {}
+
+void PreviewsResourceLoadingHintsReceiverImpl::SetResourceLoadingHints(
+ mojom::blink::PreviewsResourceLoadingHintsPtr resource_loading_hints) {
+ // TODO(tbansal): https://crbug.com/856247. Block loading of resources based
+ // on |resource_loading_hints|.
+ UMA_HISTOGRAM_COUNTS_100(
+ "ResourceLoadingHints.CountBlockedSubresourcePatterns",
+ resource_loading_hints->subresources_to_block.size());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_receiver_impl.h b/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_receiver_impl.h
new file mode 100644
index 00000000000..d4a8daf02b2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/loader/previews_resource_loading_hints_receiver_impl.h
@@ -0,0 +1,35 @@
+// 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_LOADER_PREVIEWS_RESOURCE_LOADING_HINTS_RECEIVER_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_PREVIEWS_RESOURCE_LOADING_HINTS_RECEIVER_IMPL_H_
+
+#include "mojo/public/cpp/bindings/binding.h"
+#include "third_party/blink/public/mojom/loader/previews_resource_loading_hints.mojom-blink.h"
+
+namespace blink {
+
+// Created and attached to a LocalFrame when
+// PreviewsResourceLoadingHintsReceiverRequest is received by the frame from the
+// browser process.
+class PreviewsResourceLoadingHintsReceiverImpl
+ : public mojom::blink::PreviewsResourceLoadingHintsReceiver {
+ public:
+ explicit PreviewsResourceLoadingHintsReceiverImpl(
+ mojom::blink::PreviewsResourceLoadingHintsReceiverRequest request);
+ ~PreviewsResourceLoadingHintsReceiverImpl() override;
+
+ private:
+ void SetResourceLoadingHints(mojom::blink::PreviewsResourceLoadingHintsPtr
+ resource_loading_hints) override;
+
+ // TODO(tbansal): https://crbug.com/800641. Consider using a RevocableBinding.
+ mojo::Binding<mojom::blink::PreviewsResourceLoadingHintsReceiver> binding_;
+
+ DISALLOW_COPY_AND_ASSIGN(PreviewsResourceLoadingHintsReceiverImpl);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_PREVIEWS_RESOURCE_LOADING_HINTS_RECEIVER_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/core/loader/programmatic_scroll_test.cc b/chromium/third_party/blink/renderer/core/loader/programmatic_scroll_test.cc
index d31bd93d2b0..11807820218 100644
--- a/chromium/third_party/blink/renderer/core/loader/programmatic_scroll_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/programmatic_scroll_test.cc
@@ -7,8 +7,8 @@
#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/public/web/web_frame.h"
-#include "third_party/blink/public/web/web_frame_client.h"
#include "third_party/blink/public/web/web_history_item.h"
+#include "third_party/blink/public/web/web_local_frame_client.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_view.h"
@@ -18,6 +18,7 @@
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.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/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/testing/unit_test_helpers.h"
@@ -55,7 +56,7 @@ TEST_F(ProgrammaticScrollTest, RestoreScrollPositionAndViewStateWithScale) {
web_view->UpdateAllLifecyclePhases();
FrameLoader& loader = web_view->MainFrameImpl()->GetFrame()->Loader();
- loader.GetDocumentLoader()->SetLoadType(kFrameLoadTypeBackForward);
+ loader.GetDocumentLoader()->SetLoadType(WebFrameLoadType::kBackForward);
web_view->SetPageScaleFactor(3.0f);
web_view->MainFrameImpl()->SetScrollOffset(WebSize(0, 500));
@@ -87,7 +88,7 @@ TEST_F(ProgrammaticScrollTest, RestoreScrollPositionAndViewStateWithoutScale) {
web_view->UpdateAllLifecyclePhases();
FrameLoader& loader = web_view->MainFrameImpl()->GetFrame()->Loader();
- loader.GetDocumentLoader()->SetLoadType(kFrameLoadTypeBackForward);
+ loader.GetDocumentLoader()->SetLoadType(WebFrameLoadType::kBackForward);
web_view->SetPageScaleFactor(3.0f);
web_view->MainFrameImpl()->SetScrollOffset(WebSize(0, 500));
@@ -142,8 +143,7 @@ TEST_F(ProgrammaticScrollSimTest, NavigateToHash) {
// should cause the document to scroll to the hash.
test::RunPendingTasks();
- ScrollableArea* layout_viewport =
- GetDocument().View()->LayoutViewportScrollableArea();
+ ScrollableArea* layout_viewport = GetDocument().View()->LayoutViewport();
EXPECT_EQ(3001, layout_viewport->GetScrollOffset().Height());
}
diff --git a/chromium/third_party/blink/renderer/core/loader/progress_tracker.cc b/chromium/third_party/blink/renderer/core/loader/progress_tracker.cc
index ddfd169dddb..7d5ba73cb99 100644
--- a/chromium/third_party/blink/renderer/core/loader/progress_tracker.cc
+++ b/chromium/third_party/blink/renderer/core/loader/progress_tracker.cc
@@ -106,13 +106,13 @@ LocalFrameClient* ProgressTracker::GetLocalFrameClient() const {
return frame_->Client();
}
-void ProgressTracker::ProgressStarted(FrameLoadType type) {
+void ProgressTracker::ProgressStarted() {
Reset();
progress_value_ = kInitialProgressValue;
if (!frame_->IsLoading()) {
GetLocalFrameClient()->DidStartLoading(kNavigationToDifferentDocument);
frame_->SetIsLoading(true);
- probe::frameStartedLoading(frame_, type);
+ probe::frameStartedLoading(frame_);
}
}
diff --git a/chromium/third_party/blink/renderer/core/loader/progress_tracker.h b/chromium/third_party/blink/renderer/core/loader/progress_tracker.h
index 0a05bb35b8d..f5c64eed4c5 100644
--- a/chromium/third_party/blink/renderer/core/loader/progress_tracker.h
+++ b/chromium/third_party/blink/renderer/core/loader/progress_tracker.h
@@ -58,7 +58,7 @@ class CORE_EXPORT ProgressTracker final
double EstimatedProgress() const;
- void ProgressStarted(FrameLoadType);
+ void ProgressStarted();
void ProgressCompleted();
void FinishedParsing();
diff --git a/chromium/third_party/blink/renderer/core/loader/progress_tracker_test.cc b/chromium/third_party/blink/renderer/core/loader/progress_tracker_test.cc
index 04eca2b73e7..63bcfe8b246 100644
--- a/chromium/third_party/blink/renderer/core/loader/progress_tracker_test.cc
+++ b/chromium/third_party/blink/renderer/core/loader/progress_tracker_test.cc
@@ -44,7 +44,7 @@ class ProgressTrackerTest : public PageTestBase {
// to ProgressTracker with identifier 1, but tests are responsible for
// emulating payload and load completion.
void EmulateMainResourceRequestAndResponse() const {
- Progress().ProgressStarted(kFrameLoadTypeStandard);
+ Progress().ProgressStarted();
Progress().WillStartLoading(1ul, ResourceLoadPriority::kVeryHigh);
EXPECT_EQ(0.0, LastProgress());
Progress().IncrementProgress(1ul, ResponseHeaders());
@@ -57,7 +57,7 @@ class ProgressTrackerTest : public PageTestBase {
};
TEST_F(ProgressTrackerTest, Static) {
- Progress().ProgressStarted(kFrameLoadTypeStandard);
+ Progress().ProgressStarted();
EXPECT_EQ(0.0, LastProgress());
Progress().ProgressCompleted();
EXPECT_EQ(1.0, LastProgress());
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
index b10e13e7177..8ca4629e98f 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/document_resource.cc
+++ b/chromium/third_party/blink/renderer/core/loader/resource/document_resource.cc
@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/core/loader/resource/document_resource.h"
#include "services/network/public/mojom/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"
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 941af988447..1b2e6a28ecd 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
@@ -24,7 +24,6 @@
#include "third_party/blink/renderer/core/loader/resource/image_resource.h"
#include <stdint.h>
-#include <v8.h>
#include <memory>
#include "third_party/blink/public/platform/platform.h"
@@ -57,7 +56,7 @@ namespace {
// The amount of time to wait before informing the clients that the image has
// been updated (in seconds). This effectively throttles invalidations that
// result from new data arriving for this image.
-constexpr double kFlushDelaySeconds = 1.;
+constexpr auto kFlushDelay = TimeDelta::FromSeconds(1);
bool HasServerLoFiResponseHeaders(const ResourceResponse& response) {
return response.HttpHeaderField("chrome-proxy-content-transform")
@@ -331,26 +330,25 @@ void ImageResource::AppendData(const char* data, size_t length) {
return;
}
- // For other cases, only update at |kFlushDelaySeconds| intervals. This
+ // For other cases, only update at |kFlushDelay| intervals. This
// throttles how frequently we update |m_image| and how frequently we
// inform the clients which causes an invalidation of this image. In other
- // words, we only invalidate this image every |kFlushDelaySeconds| seconds
+ // words, we only invalidate this image every |kFlushDelay| seconds
// while loading.
if (Loader() && !is_pending_flushing_) {
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
Loader()->GetLoadingTaskRunner();
- double now = WTF::CurrentTimeTicksInSeconds();
- if (!last_flush_time_)
+ TimeTicks now = CurrentTimeTicks();
+ if (last_flush_time_.is_null())
last_flush_time_ = now;
DCHECK_LE(last_flush_time_, now);
- double flush_delay = last_flush_time_ - now + kFlushDelaySeconds;
- if (flush_delay < 0.)
- flush_delay = 0.;
+ TimeDelta flush_delay =
+ std::max(TimeDelta(), last_flush_time_ - now + kFlushDelay);
task_runner->PostDelayedTask(FROM_HERE,
WTF::Bind(&ImageResource::FlushImageIfNeeded,
WrapWeakPersistent(this)),
- TimeDelta::FromSecondsD(flush_delay));
+ flush_delay);
is_pending_flushing_ = true;
}
}
@@ -360,7 +358,7 @@ void ImageResource::FlushImageIfNeeded() {
// We might have already loaded the image fully, in which case we don't need
// to call |updateImage()|.
if (IsLoading()) {
- last_flush_time_ = WTF::CurrentTimeTicksInSeconds();
+ last_flush_time_ = CurrentTimeTicks();
UpdateImage(Data(), ImageResourceContent::kUpdateImage, false);
}
is_pending_flushing_ = false;
@@ -400,6 +398,7 @@ void ImageResource::UpdateImageAndClearBuffer() {
}
void ImageResource::NotifyStartLoad() {
+ Resource::NotifyStartLoad();
CHECK_EQ(GetStatus(), ResourceStatus::kPending);
GetContent()->NotifyStartLoad();
}
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 2fedb175215..db2a678ae20 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
@@ -31,6 +31,7 @@
#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/timer.h"
+#include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink {
@@ -176,7 +177,7 @@ class CORE_EXPORT ImageResource final
};
PlaceholderOption placeholder_option_;
- double last_flush_time_ = 0.;
+ 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 cea5599d458..73084594c9c 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
@@ -240,19 +240,6 @@ blink::Image* ImageResourceContent::GetImage() const {
return image_.get();
}
-std::pair<blink::Image*, float> ImageResourceContent::BrokenCanvas(
- float device_scale_factor) {
- if (device_scale_factor >= 2) {
- DEFINE_STATIC_REF(blink::Image, broken_canvas_hi_res,
- (blink::Image::LoadPlatformResource("brokenCanvas@2x")));
- return std::make_pair(broken_canvas_hi_res, 2);
- }
-
- DEFINE_STATIC_REF(blink::Image, broken_canvas_lo_res,
- (blink::Image::LoadPlatformResource("brokenCanvas")));
- return std::make_pair(broken_canvas_lo_res, 1);
-}
-
IntSize ImageResourceContent::IntrinsicSize(
RespectImageOrientationEnum should_respect_image_orientation) {
if (!image_)
@@ -358,25 +345,6 @@ void ImageResourceContent::UpdateToLoadedContentStatus(
break;
}
- // Checks ImageResourceContent's previous status.
- switch (GetContentStatus()) {
- case ResourceStatus::kPending:
- // A non-multipart image or the first part of a multipart image.
- break;
-
- case ResourceStatus::kCached:
- case ResourceStatus::kLoadError:
- case ResourceStatus::kDecodeError:
- // Second (or later) part of a multipart image.
- // TODO(hiroshige): Assert that this is actually a multipart image.
- break;
-
- case ResourceStatus::kNotStarted:
- // Should have updated to kPending via NotifyStartLoad().
- CHECK(false);
- break;
- }
-
// Updates the status.
content_status_ = new_status;
}
@@ -424,8 +392,6 @@ ImageResourceContent::UpdateImageResult ImageResourceContent::UpdateImage(
base::AutoReset<bool> scope(&is_update_image_being_called_, true);
#endif
- CHECK_NE(GetContentStatus(), ResourceStatus::kNotStarted);
-
// Clears the existing image, if instructed by |updateImageOption|.
switch (update_image_option) {
case kClearAndUpdateImage:
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 ab956561062..5df45ba3f96 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
@@ -61,10 +61,6 @@ class CORE_EXPORT ImageResourceContent final
blink::Image* GetImage() const;
bool HasImage() const { return image_.get(); }
- // Returns an image and the image's resolution scale factor.
- static std::pair<blink::Image*, float> BrokenCanvas(
- float device_scale_factor);
-
// The device pixel ratio we got from the server for this image, or 1.0.
float DevicePixelRatioHeaderValue() const;
bool HasDevicePixelRatioHeaderValue() const;
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 75553a8bfa9..3920612fe91 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
@@ -184,7 +184,6 @@ void ReceiveResponse(ImageResource* image_resource,
size_t data_size) {
ResourceResponse response(url, mime_type);
response.SetHTTPStatusCode(200);
- image_resource->SetStatus(ResourceStatus::kPending);
image_resource->NotifyStartLoad();
image_resource->ResponseReceived(response, nullptr);
image_resource->AppendData(data, data_size);
@@ -559,7 +558,6 @@ TEST(ImageResourceTest, CancelWithImageAndFinishObserver) {
TEST(ImageResourceTest, DecodedDataRemainsWhileHasClients) {
ImageResource* image_resource = ImageResource::CreateForTest(NullURL());
- image_resource->SetStatus(ResourceStatus::kPending);
image_resource->NotifyStartLoad();
std::unique_ptr<MockImageResourceObserver> observer =
@@ -600,7 +598,6 @@ TEST(ImageResourceTest, DecodedDataRemainsWhileHasClients) {
TEST(ImageResourceTest, UpdateBitmapImages) {
ImageResource* image_resource = ImageResource::CreateForTest(NullURL());
- image_resource->SetStatus(ResourceStatus::kPending);
image_resource->NotifyStartLoad();
std::unique_ptr<MockImageResourceObserver> observer =
@@ -638,7 +635,6 @@ TEST_P(ImageResourceReloadTest, ReloadIfLoFiOrPlaceholderAfterFinished) {
KURL test_url(kTestURL);
ScopedMockedURLLoad scoped_mocked_url_load(test_url, GetTestFilePath());
ImageResource* image_resource = ImageResource::CreateForTest(test_url);
- image_resource->SetStatus(ResourceStatus::kPending);
image_resource->NotifyStartLoad();
std::unique_ptr<MockImageResourceObserver> observer =
@@ -686,7 +682,6 @@ TEST_P(ImageResourceReloadTest,
KURL test_url(kTestURL);
ScopedMockedURLLoad scoped_mocked_url_load(test_url, GetTestFilePath());
ImageResource* image_resource = ImageResource::CreateForTest(test_url);
- image_resource->SetStatus(ResourceStatus::kPending);
image_resource->NotifyStartLoad();
std::unique_ptr<MockImageResourceObserver> observer =
@@ -736,7 +731,6 @@ TEST_P(ImageResourceReloadTest,
request.SetPreviewsState(WebURLRequest::kServerLoFiOn);
request.SetFetchCredentialsMode(network::mojom::FetchCredentialsMode::kOmit);
ImageResource* image_resource = ImageResource::Create(request);
- image_resource->SetStatus(ResourceStatus::kPending);
image_resource->NotifyStartLoad();
std::unique_ptr<MockImageResourceObserver> observer =
@@ -1835,7 +1829,6 @@ TEST(ImageResourceTest, PeriodicFlushTest) {
ResourceLoader::Create(fetcher, scheduler, image_resource);
ALLOW_UNUSED_LOCAL(loader);
- image_resource->SetStatus(ResourceStatus::kPending);
image_resource->NotifyStartLoad();
std::unique_ptr<MockImageResourceObserver> observer =
@@ -1910,8 +1903,6 @@ TEST(ImageResourceTest, PeriodicFlushTest) {
EXPECT_TRUE(image_resource->GetContent()->GetImage()->IsBitmapImage());
EXPECT_EQ(50, image_resource->GetContent()->GetImage()->width());
EXPECT_EQ(50, image_resource->GetContent()->GetImage()->height());
-
- WTF::SetTimeFunctionsForTesting(nullptr);
}
TEST(ImageResourceTest, DeferredInvalidation) {
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 8c9cab8de67..21f66864055 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
@@ -199,14 +199,14 @@ void ScriptResource::OnMemoryDump(WebMemoryDumpLevelOfDetail level_of_detail,
dump->Guid(), String(WTF::Partitions::kAllocatedObjectPoolName));
}
-const String& ScriptResource::SourceText() {
+const MovableString& ScriptResource::SourceText() {
DCHECK(IsLoaded());
if (source_text_.IsNull() && Data()) {
String source_text = DecodedText();
ClearData();
SetDecodedSize(source_text.CharactersSizeInBytes());
- source_text_ = AtomicString(source_text);
+ source_text_ = MovableString(source_text.ReleaseImpl());
}
return source_text_;
@@ -233,7 +233,7 @@ void ScriptResource::SetSerializedCachedMetadata(const char* data,
}
void ScriptResource::DestroyDecodedDataForFailedRevalidation() {
- source_text_ = AtomicString();
+ source_text_ = MovableString();
SetDecodedSize(0);
}
diff --git a/chromium/third_party/blink/renderer/core/loader/resource/script_resource.h b/chromium/third_party/blink/renderer/core/loader/resource/script_resource.h
index 9d838a06105..97dee5e861d 100644
--- a/chromium/third_party/blink/renderer/core/loader/resource/script_resource.h
+++ b/chromium/third_party/blink/renderer/core/loader/resource/script_resource.h
@@ -33,6 +33,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
#include "third_party/blink/renderer/platform/loader/fetch/text_resource_decoder_options.h"
+#include "third_party/blink/renderer/platform/wtf/text/movable_string.h"
namespace blink {
@@ -68,7 +69,7 @@ class CORE_EXPORT ScriptResource final : public TextResource {
void SetSerializedCachedMetadata(const char*, size_t) override;
- const String& SourceText();
+ const MovableString& SourceText();
AccessControlStatus CalculateAccessControlStatus(const SecurityOrigin*) const;
@@ -101,7 +102,7 @@ class CORE_EXPORT ScriptResource final : public TextResource {
bool CanUseCacheValidator() const override;
- AtomicString source_text_;
+ MovableString source_text_;
};
DEFINE_RESOURCE_TYPE_CASTS(Script);
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 1ce9c9e53f7..42354f8a31a 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
@@ -33,12 +33,8 @@ String TextResource::DecodedText() const {
DCHECK(Data());
StringBuilder builder;
- const char* segment;
- size_t position = 0;
- while (size_t length = Data()->GetSomeData(segment, position)) {
- builder.Append(decoder_->Decode(segment, length));
- position += length;
- }
+ for (const auto& span : *Data())
+ builder.Append(decoder_->Decode(span.data(), span.size()));
builder.Append(decoder_->Flush());
return builder.ToString();
}
diff --git a/chromium/third_party/blink/renderer/core/loader/scheduled_navigation.cc b/chromium/third_party/blink/renderer/core/loader/scheduled_navigation.cc
index 7b6bc822b3f..935da8d5ab3 100644
--- a/chromium/third_party/blink/renderer/core/loader/scheduled_navigation.cc
+++ b/chromium/third_party/blink/renderer/core/loader/scheduled_navigation.cc
@@ -6,6 +6,7 @@
#include <memory>
+#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_frame.h"
diff --git a/chromium/third_party/blink/renderer/core/loader/subresource_integrity_helper.cc b/chromium/third_party/blink/renderer/core/loader/subresource_integrity_helper.cc
index 6748289bb60..c8ab9c40012 100644
--- a/chromium/third_party/blink/renderer/core/loader/subresource_integrity_helper.cc
+++ b/chromium/third_party/blink/renderer/core/loader/subresource_integrity_helper.cc
@@ -65,7 +65,7 @@ SubresourceIntegrity::IntegrityFeatures SubresourceIntegrityHelper::GetFeatures(
ExecutionContext* execution_context) {
bool allow_signatures =
RuntimeEnabledFeatures::SignatureBasedIntegrityEnabledByRuntimeFlag() ||
- OriginTrials::signatureBasedIntegrityEnabled(execution_context);
+ OriginTrials::SignatureBasedIntegrityEnabled(execution_context);
return allow_signatures ? SubresourceIntegrity::IntegrityFeatures::kSignatures
: SubresourceIntegrity::IntegrityFeatures::kDefault;
}
diff --git a/chromium/third_party/blink/renderer/core/loader/text_track_loader.cc b/chromium/third_party/blink/renderer/core/loader/text_track_loader.cc
index 0e8c721654d..a2968adf1b4 100644
--- a/chromium/third_party/blink/renderer/core/loader/text_track_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/text_track_loader.cc
@@ -143,7 +143,7 @@ bool TextTrackLoader::Load(const KURL& url,
CancelLoad();
ResourceLoaderOptions options;
- options.initiator_info.name = FetchInitiatorTypeNames::texttrack;
+ options.initiator_info.name = FetchInitiatorTypeNames::track;
FetchParameters cue_fetch_params(ResourceRequest(url), options);
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 6e269ec2080..44b688f05be 100644
--- a/chromium/third_party/blink/renderer/core/loader/threadable_loader.cc
+++ b/chromium/third_party/blink/renderer/core/loader/threadable_loader.cc
@@ -33,7 +33,6 @@
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/loader/document_threadable_loader.h"
#include "third_party/blink/renderer/core/loader/threadable_loading_context.h"
-#include "third_party/blink/renderer/core/loader/worker_threadable_loader.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
namespace blink {
@@ -57,12 +56,6 @@ void ThreadableLoader::LoadResourceSynchronously(
ThreadableLoaderClient& client,
const ThreadableLoaderOptions& options,
const ResourceLoaderOptions& resource_loader_options) {
- if (context.IsWorkerGlobalScope()) {
- WorkerThreadableLoader::LoadResourceSynchronously(
- ToWorkerGlobalScope(context), request, client, options,
- resource_loader_options);
- return;
- }
DocumentThreadableLoader::LoadResourceSynchronously(
*ThreadableLoadingContext::Create(context), request, client, options,
resource_loader_options);
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 cb7050a33b0..0638411771e 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
@@ -135,7 +135,7 @@ void SetUpRedirectURL() {
response.SetHTTPStatusCode(301);
response.SetLoadTiming(timing);
response.AddHTTPHeaderField("Location", SuccessURL().GetString());
- response.AddHTTPHeaderField("Access-Control-Allow-Origin", "null");
+ response.AddHTTPHeaderField("Access-Control-Allow-Origin", "http://fake.url");
URLTestHelpers::RegisterMockedURLLoadWithCustomResponse(
url, test::CoreTestDataPath(kFileName), response);
@@ -152,7 +152,7 @@ void SetUpRedirectLoopURL() {
response.SetHTTPStatusCode(301);
response.SetLoadTiming(timing);
response.AddHTTPHeaderField("Location", RedirectLoopURL().GetString());
- response.AddHTTPHeaderField("Access-Control-Allow-Origin", "null");
+ response.AddHTTPHeaderField("Access-Control-Allow-Origin", "http://fake.url");
URLTestHelpers::RegisterMockedURLLoadWithCustomResponse(
url, test::CoreTestDataPath(kFileName), response);
@@ -189,7 +189,11 @@ class ThreadableLoaderTestHelper {
class DocumentThreadableLoaderTestHelper : public ThreadableLoaderTestHelper {
public:
DocumentThreadableLoaderTestHelper()
- : dummy_page_holder_(DummyPageHolder::Create(IntSize(1, 1))) {}
+ : dummy_page_holder_(DummyPageHolder::Create(IntSize(1, 1))) {
+ GetDocument().SetURL(KURL("http://fake.url/"));
+ GetDocument().SetSecurityOrigin(
+ SecurityOrigin::Create(KURL("http://fake.url/")));
+ }
void CreateLoader(ThreadableLoaderClient* client) override {
ThreadableLoaderOptions options;
@@ -250,7 +254,10 @@ class WebWorkerFetchContextForTest : public WebWorkerFetchContext {
}
void WillSendRequest(WebURLRequest&) override {}
- bool IsControlledByServiceWorker() const override { return false; }
+ blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker()
+ const override {
+ return blink::mojom::ControllerServiceWorkerMode::kNoController;
+ }
WebURL SiteForCookies() const override { return site_for_cookies_; }
private:
@@ -262,7 +269,9 @@ class WebWorkerFetchContextForTest : public WebWorkerFetchContext {
class WorkerThreadableLoaderTestHelper : public ThreadableLoaderTestHelper {
public:
WorkerThreadableLoaderTestHelper()
- : dummy_page_holder_(DummyPageHolder::Create(IntSize(1, 1))) {}
+ : dummy_page_holder_(DummyPageHolder::Create(IntSize(1, 1))) {
+ GetDocument().SetURL(KURL("http://fake.url/"));
+ }
void CreateLoader(ThreadableLoaderClient* client) override {
std::unique_ptr<WaitableEvent> completion_event =
@@ -770,7 +779,8 @@ TEST_P(ThreadableLoaderTest, DidFailAccessControlCheck) {
DidFail(ResourceError::CancelledDueToAccessCheckError(
SuccessURL(), ResourceRequestBlockedReason::kOther,
"No 'Access-Control-Allow-Origin' header is present on the requested "
- "resource. Origin 'null' is therefore not allowed access.")));
+ "resource. Origin 'http://fake.url' is therefore not allowed "
+ "access.")));
StartLoader(SuccessURL(), network::mojom::FetchRequestMode::kCORS);
CallCheckpoint(2);
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 bcc6a09b457..315409235c1 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/loader/worker_fetch_context.h"
#include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/common/blob/blob_utils.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_mixed_content.h"
@@ -76,7 +77,6 @@ WorkerFetchContext::~WorkerFetchContext() = default;
WorkerFetchContext* WorkerFetchContext::Create(
WorkerOrWorkletGlobalScope& global_scope) {
DCHECK(global_scope.IsContextThread());
- DCHECK(!global_scope.IsMainThreadWorkletGlobalScope());
WorkerClients* worker_clients = global_scope.Clients();
DCHECK(worker_clients);
WorkerFetchContextHolder* holder =
@@ -96,6 +96,8 @@ WorkerFetchContext::WorkerFetchContext(
web_context_(std::move(web_context)),
loading_task_runner_(
global_scope_->GetTaskRunner(TaskType::kInternalLoading)),
+ fetch_client_settings_object_(
+ new FetchClientSettingsObjectImpl(*global_scope_)),
save_data_enabled_(GetNetworkStateNotifier().SaveDataEnabled()) {
web_context_->InitializeOnWorkerThread();
std::unique_ptr<blink::WebDocumentSubresourceFilter> web_filter =
@@ -105,6 +107,10 @@ WorkerFetchContext::WorkerFetchContext(
SubresourceFilter::Create(global_scope, std::move(web_filter));
}
}
+const FetchClientSettingsObject*
+WorkerFetchContext::GetFetchClientSettingsObject() const {
+ return fetch_client_settings_object_.Get();
+}
KURL WorkerFetchContext::GetSiteForCookies() const {
return web_context_->SiteForCookies();
@@ -160,8 +166,7 @@ bool WorkerFetchContext::ShouldBlockWebSocketByMixedContentCheck(
const KURL& url) const {
// Worklets don't support WebSocket.
DCHECK(global_scope_->IsWorkerGlobalScope());
- return !MixedContentChecker::IsWebSocketAllowed(
- ToWorkerGlobalScope(global_scope_), web_context_.get(), url);
+ return !MixedContentChecker::IsWebSocketAllowed(*this, url);
}
std::unique_ptr<WebSocketHandshakeThrottle>
@@ -176,8 +181,8 @@ bool WorkerFetchContext::ShouldBlockFetchByMixedContentCheck(
const KURL& url,
SecurityViolationReportingPolicy reporting_policy) const {
return MixedContentChecker::ShouldBlockFetchOnWorker(
- global_scope_, web_context_.get(), request_context, frame_type,
- redirect_status, url, reporting_policy);
+ *this, request_context, redirect_status, url, reporting_policy,
+ global_scope_->IsWorkletGlobalScope());
}
bool WorkerFetchContext::ShouldBlockFetchAsCredentialedSubresource(
@@ -199,14 +204,6 @@ bool WorkerFetchContext::ShouldBlockFetchAsCredentialedSubresource(
return false;
}
-ReferrerPolicy WorkerFetchContext::GetReferrerPolicy() const {
- return global_scope_->GetReferrerPolicy();
-}
-
-String WorkerFetchContext::GetOutgoingReferrer() const {
- return global_scope_->OutgoingReferrer();
-}
-
const KURL& WorkerFetchContext::Url() const {
return global_scope_->Url();
}
@@ -221,8 +218,7 @@ const SecurityOrigin* WorkerFetchContext::GetParentSecurityOrigin() const {
base::Optional<mojom::IPAddressSpace> WorkerFetchContext::GetAddressSpace()
const {
- return base::make_optional(
- global_scope_->GetSecurityContext().AddressSpace());
+ return base::make_optional(GetSecurityContext().AddressSpace());
}
const ContentSecurityPolicy* WorkerFetchContext::GetContentSecurityPolicy()
@@ -235,12 +231,11 @@ void WorkerFetchContext::AddConsoleMessage(ConsoleMessage* message) const {
}
const SecurityOrigin* WorkerFetchContext::GetSecurityOrigin() const {
- return global_scope_->GetSecurityOrigin();
+ return GetFetchClientSettingsObject()->GetSecurityOrigin();
}
std::unique_ptr<WebURLLoader> WorkerFetchContext::CreateURLLoader(
const ResourceRequest& request,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
const ResourceLoaderOptions& options) {
CountUsage(WebFeature::kOffMainThreadFetch);
WrappedResourceRequest wrapped(request);
@@ -255,23 +250,34 @@ std::unique_ptr<WebURLLoader> WorkerFetchContext::CreateURLLoader(
// actually creating the URL loader here. Other subresource loading will
// immediately create the URL loader so resolving those blob URLs here is
// simplest.
- if (request.Url().ProtocolIs("blob") &&
- RuntimeEnabledFeatures::MojoBlobURLsEnabled() && !url_loader_factory) {
+ if (request.Url().ProtocolIs("blob") && BlobUtils::MojoBlobURLsEnabled() &&
+ !url_loader_factory) {
global_scope_->GetPublicURLManager().Resolve(
request.Url(), MakeRequest(&url_loader_factory));
}
if (url_loader_factory) {
return web_context_
->WrapURLLoaderFactory(url_loader_factory.PassInterface().PassHandle())
- ->CreateURLLoader(wrapped, task_runner);
+ ->CreateURLLoader(wrapped, CreateResourceLoadingTaskRunnerHandle());
+ }
+
+ if (request.GetRequestContext() == WebURLRequest::kRequestContextScript) {
+ if (!script_loader_factory_)
+ script_loader_factory_ = web_context_->CreateScriptLoaderFactory();
+ if (script_loader_factory_) {
+ return script_loader_factory_->CreateURLLoader(
+ wrapped, CreateResourceLoadingTaskRunnerHandle());
+ }
}
if (!url_loader_factory_)
url_loader_factory_ = web_context_->CreateURLLoaderFactory();
- return url_loader_factory_->CreateURLLoader(wrapped, task_runner);
+ return url_loader_factory_->CreateURLLoader(
+ wrapped, CreateResourceLoadingTaskRunnerHandle());
}
-bool WorkerFetchContext::IsControlledByServiceWorker() const {
+blink::mojom::ControllerServiceWorkerMode
+WorkerFetchContext::IsControlledByServiceWorker() const {
return web_context_->IsControlledByServiceWorker();
}
@@ -286,6 +292,8 @@ void WorkerFetchContext::PrepareRequest(ResourceRequest& request,
DCHECK(!user_agent.IsNull());
request.SetHTTPUserAgent(AtomicString(user_agent));
+ FrameLoader::UpgradeInsecureRequest(request, global_scope_);
+
WrappedResourceRequest webreq(request);
web_context_->WillSendRequest(webreq);
}
@@ -351,10 +359,10 @@ void WorkerFetchContext::DispatchDidFinishLoading(
TimeTicks finish_time,
int64_t encoded_data_length,
int64_t decoded_body_length,
- bool blocked_cross_site_document) {
+ bool should_report_corb_blocking) {
probe::didFinishLoading(global_scope_, identifier, nullptr, finish_time,
encoded_data_length, decoded_body_length,
- blocked_cross_site_document);
+ should_report_corb_blocking);
}
void WorkerFetchContext::DispatchDidFail(const KURL& url,
@@ -398,10 +406,31 @@ WorkerFetchContext::GetLoadingTaskRunner() {
return loading_task_runner_;
}
+std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
+WorkerFetchContext::CreateResourceLoadingTaskRunnerHandle() {
+ return scheduler::WebResourceLoadingTaskRunnerHandle::CreateUnprioritized(
+ GetLoadingTaskRunner());
+}
+
+SecurityContext& WorkerFetchContext::GetSecurityContext() const {
+ return global_scope_->GetSecurityContext();
+}
+
+WorkerSettings* WorkerFetchContext::GetWorkerSettings() const {
+ if (!global_scope_->IsWorkerGlobalScope())
+ return nullptr;
+ return ToWorkerGlobalScope(global_scope_)->GetWorkerSettings();
+}
+
+WorkerContentSettingsClient*
+WorkerFetchContext::GetWorkerContentSettingsClient() const {
+ return WorkerContentSettingsClient::From(*global_scope_);
+}
+
void WorkerFetchContext::Trace(blink::Visitor* visitor) {
visitor->Trace(global_scope_);
visitor->Trace(subresource_filter_);
- visitor->Trace(resource_fetcher_);
+ visitor->Trace(fetch_client_settings_object_);
BaseFetchContext::Trace(visitor);
}
@@ -409,6 +438,9 @@ void ProvideWorkerFetchContextToWorker(
WorkerClients* clients,
std::unique_ptr<WebWorkerFetchContext> web_context) {
DCHECK(clients);
+ // web_context should only be nullptr in unit tests.
+ if (!web_context)
+ return;
WorkerFetchContextHolder::ProvideTo(
*clients, new WorkerFetchContextHolder(std::move(web_context)));
}
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 5b97752a90a..f1ad8cbc146 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
@@ -8,18 +8,21 @@
#include <memory>
#include "base/single_thread_task_runner.h"
#include "services/network/public/mojom/request_context_frame_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-blink.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/core/script/fetch_client_settings_object_impl.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
namespace blink {
-class ResourceFetcher;
class SubresourceFilter;
class WebURLLoader;
class WebURLLoaderFactory;
class WebWorkerFetchContext;
class WorkerClients;
+class WorkerContentSettingsClient;
+class WorkerSettings;
class WorkerOrWorkletGlobalScope;
CORE_EXPORT void ProvideWorkerFetchContextToWorker(
@@ -34,6 +37,8 @@ class WorkerFetchContext final : public BaseFetchContext {
~WorkerFetchContext() override;
// BaseFetchContext implementation:
+ const FetchClientSettingsObject* GetFetchClientSettingsObject()
+ const override;
KURL GetSiteForCookies() const override;
SubresourceFilter* GetSubresourceFilter() const override;
bool AllowScriptFromSource(const KURL&) const override;
@@ -58,8 +63,6 @@ class WorkerFetchContext final : public BaseFetchContext {
bool ShouldBlockFetchAsCredentialedSubresource(const ResourceRequest&,
const KURL&) const override;
bool ShouldLoadNewResource(Resource::Type) const override { return true; }
- ReferrerPolicy GetReferrerPolicy() const override;
- String GetOutgoingReferrer() const override;
const KURL& Url() const override;
const SecurityOrigin* GetParentSecurityOrigin() const override;
base::Optional<mojom::IPAddressSpace> GetAddressSpace() const override;
@@ -70,10 +73,10 @@ class WorkerFetchContext final : public BaseFetchContext {
const SecurityOrigin* GetSecurityOrigin() const override;
std::unique_ptr<WebURLLoader> CreateURLLoader(
const ResourceRequest&,
- scoped_refptr<base::SingleThreadTaskRunner>,
const ResourceLoaderOptions&) override;
void PrepareRequest(ResourceRequest&, RedirectType) override;
- bool IsControlledByServiceWorker() const override;
+ blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker()
+ const override;
int ApplicationCacheHostID() const override;
void AddAdditionalRequestHeaders(ResourceRequest&,
FetchResourceType) override;
@@ -97,7 +100,7 @@ class WorkerFetchContext final : public BaseFetchContext {
TimeTicks finish_time,
int64_t encoded_data_length,
int64_t decoded_body_length,
- bool blocked_cross_site_document) override;
+ bool should_report_corb_blocking) override;
void DispatchDidFail(const KURL&,
unsigned long identifier,
const ResourceError&,
@@ -110,7 +113,13 @@ class WorkerFetchContext final : public BaseFetchContext {
ResourceRequest&) override;
scoped_refptr<base::SingleThreadTaskRunner> GetLoadingTaskRunner() override;
- WebWorkerFetchContext* GetWebWorkerFetchContext() {
+ std::unique_ptr<scheduler::WebResourceLoadingTaskRunnerHandle>
+ CreateResourceLoadingTaskRunnerHandle() override;
+
+ SecurityContext& GetSecurityContext() const;
+ WorkerSettings* GetWorkerSettings() const;
+ WorkerContentSettingsClient* GetWorkerContentSettingsClient() const;
+ WebWorkerFetchContext* GetWebWorkerFetchContext() const {
return web_context_.get();
}
@@ -122,12 +131,22 @@ class WorkerFetchContext final : public BaseFetchContext {
void SetFirstPartyCookieAndRequestorOrigin(ResourceRequest&);
- Member<WorkerOrWorkletGlobalScope> global_scope_;
- std::unique_ptr<WebWorkerFetchContext> web_context_;
+ const Member<WorkerOrWorkletGlobalScope> global_scope_;
+ const std::unique_ptr<WebWorkerFetchContext> web_context_;
+
+ // Responsible for regular loads from the worker (i.e., Fetch API).
std::unique_ptr<WebURLLoaderFactory> url_loader_factory_;
+
+ // Responsible for handling script loads in certian situations (i.e.,
+ // script import from service workers, which invole special processing
+ // to persist the script in storage). May be null, fallback to
+ // url_loader_factory_ in that case.
+ std::unique_ptr<WebURLLoaderFactory> script_loader_factory_;
+
Member<SubresourceFilter> subresource_filter_;
- Member<ResourceFetcher> resource_fetcher_;
- scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner_;
+ const scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner_;
+
+ const Member<FetchClientSettingsObjectImpl> fetch_client_settings_object_;
// 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/messaging/blink_transferable_message_struct_traits.cc b/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_struct_traits.cc
index de03fcbf04b..a223c52a098 100644
--- a/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_struct_traits.cc
+++ b/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_struct_traits.cc
@@ -26,8 +26,7 @@ scoped_refptr<blink::StaticBitmapImage> ToStaticBitmapImage(
SkImageInfo info = sk_bitmap.info();
if (!sk_bitmap.readPixels(info, array_buffer_contents.Data(),
- info.minRowBytes(), 0, 0,
- SkTransferFunctionBehavior::kIgnore))
+ info.minRowBytes(), 0, 0))
return nullptr;
return blink::StaticBitmapImage::Create(array_buffer_contents, info);
diff --git a/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_struct_traits_test.cc b/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_struct_traits_test.cc
index f2ad693005e..e7a491be03a 100644
--- a/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_struct_traits_test.cc
+++ b/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_struct_traits_test.cc
@@ -10,7 +10,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/message_port/message_port_channel.h"
#include "third_party/blink/public/mojom/message_port/message_port.mojom-blink.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_deserializer.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
@@ -19,6 +18,7 @@
#include "third_party/blink/renderer/core/messaging/blink_transferable_message.h"
#include "third_party/blink/renderer/core/messaging/message_port.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/skia/include/core/SkBitmap.h"
namespace blink {
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 bfdcf5beeec..ce45e3fdbea 100644
--- a/chromium/third_party/blink/renderer/core/messaging/message_port.cc
+++ b/chromium/third_party/blink/renderer/core/messaging/message_port.cc
@@ -31,10 +31,8 @@
#include "mojo/public/cpp/base/big_buffer_mojom_traits.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_factory.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#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"
@@ -42,9 +40,9 @@
#include "third_party/blink/renderer/core/inspector/thread_debugger.h"
#include "third_party/blink/renderer/core/messaging/blink_transferable_message_struct_traits.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.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/cross_thread_functional.h"
-#include "third_party/blink/renderer/platform/wtf/atomics.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
namespace blink {
@@ -80,7 +78,7 @@ void MessagePort::postMessage(ScriptState* script_state,
for (unsigned i = 0; i < ports.size(); ++i) {
if (ports[i] == this) {
exception_state.ThrowDOMException(
- kDataCloneError,
+ DOMExceptionCode::kDataCloneError,
"Port at index " + String::Number(i) + " contains the source port.");
return;
}
@@ -184,7 +182,7 @@ Vector<MessagePortChannel> MessagePort::DisentanglePorts(
else
type = "a duplicate";
exception_state.ThrowDOMException(
- kDataCloneError,
+ DOMExceptionCode::kDataCloneError,
"Port at index " + String::Number(i) + " is " + type + ".");
return Vector<MessagePortChannel>();
}
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 92e3ff775f0..f9406552582 100644
--- a/chromium/third_party/blink/renderer/core/messaging/message_port.h
+++ b/chromium/third_party/blink/renderer/core/messaging/message_port.h
@@ -30,6 +30,8 @@
#include <memory>
#include "base/memory/scoped_refptr.h"
#include "base/single_thread_task_runner.h"
+#include "mojo/public/cpp/bindings/connector.h"
+#include "mojo/public/cpp/bindings/message.h"
#include "third_party/blink/public/common/message_port/message_port_channel.h"
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
diff --git a/chromium/third_party/blink/renderer/core/mojo/mojo_watcher.cc b/chromium/third_party/blink/renderer/core/mojo/mojo_watcher.cc
index 5e080cb709a..b62ee148954 100644
--- a/chromium/third_party/blink/renderer/core/mojo/mojo_watcher.cc
+++ b/chromium/third_party/blink/renderer/core/mojo/mojo_watcher.cc
@@ -56,11 +56,6 @@ void MojoWatcher::Trace(blink::Visitor* visitor) {
ContextLifecycleObserver::Trace(visitor);
}
-void MojoWatcher::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- ScriptWrappable::TraceWrappers(visitor);
- visitor->TraceWrappers(callback_);
-}
-
bool MojoWatcher::HasPendingActivity() const {
return handle_.is_valid();
}
@@ -123,20 +118,18 @@ MojoResult MojoWatcher::Arm(MojoResult* ready_result) {
if (!handle_.is_valid())
return MOJO_RESULT_OK;
- uint32_t num_ready_contexts = 1;
- uintptr_t ready_context;
- MojoResult local_ready_result;
- MojoHandleSignalsState ready_signals;
- MojoResult result =
- MojoArmTrap(trap_handle_.get().value(), nullptr, &num_ready_contexts,
- &ready_context, &local_ready_result, &ready_signals);
+ uint32_t num_blocking_events = 1;
+ MojoTrapEvent blocking_event = {sizeof(blocking_event)};
+ MojoResult result = MojoArmTrap(trap_handle_.get().value(), nullptr,
+ &num_blocking_events, &blocking_event);
if (result == MOJO_RESULT_OK)
return MOJO_RESULT_OK;
if (result == MOJO_RESULT_FAILED_PRECONDITION) {
- DCHECK_EQ(1u, num_ready_contexts);
- DCHECK_EQ(reinterpret_cast<uintptr_t>(this), ready_context);
- *ready_result = local_ready_result;
+ DCHECK_EQ(1u, num_blocking_events);
+ DCHECK_EQ(reinterpret_cast<uintptr_t>(this),
+ blocking_event.trigger_context);
+ *ready_result = blocking_event.result;
return result;
}
diff --git a/chromium/third_party/blink/renderer/core/mojo/mojo_watcher.h b/chromium/third_party/blink/renderer/core/mojo/mojo_watcher.h
index a5a33871c33..816853b79e3 100644
--- a/chromium/third_party/blink/renderer/core/mojo/mojo_watcher.h
+++ b/chromium/third_party/blink/renderer/core/mojo/mojo_watcher.h
@@ -34,7 +34,6 @@ class MojoWatcher final : public ScriptWrappable,
MojoResult cancel();
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
// ActiveScriptWrappable
bool HasPendingActivity() const final;
diff --git a/chromium/third_party/blink/renderer/core/mojo/test/mojo_interface_interceptor.cc b/chromium/third_party/blink/renderer/core/mojo/test/mojo_interface_interceptor.cc
index 605cdae1e2a..6e7bd8fca53 100644
--- a/chromium/third_party/blink/renderer/core/mojo/test/mojo_interface_interceptor.cc
+++ b/chromium/third_party/blink/renderer/core/mojo/test/mojo_interface_interceptor.cc
@@ -8,7 +8,6 @@
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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"
@@ -18,6 +17,7 @@
#include "third_party/blink/renderer/core/mojo/test/mojo_interface_request_event.h"
#include "third_party/blink/renderer/core/workers/worker_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/wtf/text/string_utf8_adaptor.h"
@@ -32,7 +32,7 @@ MojoInterfaceInterceptor* MojoInterfaceInterceptor::Create(
bool process_scope = scope == "process";
if (process_scope && !context->IsDocument()) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"\"process\" scope interception is unavailable outside a Document.");
return nullptr;
}
@@ -49,7 +49,7 @@ void MojoInterfaceInterceptor::start(ExceptionState& exception_state) {
service_manager::InterfaceProvider* interface_provider =
GetInterfaceProvider();
if (!interface_provider) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The interface provider is unavailable.");
return;
}
@@ -64,7 +64,7 @@ void MojoInterfaceInterceptor::start(ExceptionState& exception_state) {
Platform::Current()->GetConnector());
if (test_api.HasBinderOverride(identity, interface_name)) {
exception_state.ThrowDOMException(
- kInvalidModificationError,
+ DOMExceptionCode::kInvalidModificationError,
"Interface " + interface_name_ +
" is already intercepted by another MojoInterfaceInterceptor.");
return;
@@ -81,7 +81,7 @@ void MojoInterfaceInterceptor::start(ExceptionState& exception_state) {
service_manager::InterfaceProvider::TestApi test_api(interface_provider);
if (test_api.HasBinderForName(interface_name)) {
exception_state.ThrowDOMException(
- kInvalidModificationError,
+ DOMExceptionCode::kInvalidModificationError,
"Interface " + interface_name_ +
" is already intercepted by another MojoInterfaceInterceptor.");
return;
diff --git a/chromium/third_party/blink/renderer/core/offscreencanvas/image_encode_options.idl b/chromium/third_party/blink/renderer/core/offscreencanvas/image_encode_options.idl
deleted file mode 100644
index 338adc7bb92..00000000000
--- a/chromium/third_party/blink/renderer/core/offscreencanvas/image_encode_options.idl
+++ /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.
-
-// https://html.spec.whatwg.org/multipage/scripting.html#the-offscreencanvas-interface
-
-dictionary ImageEncodeOptions {
- DOMString type = "image/png";
- unrestricted double quality = 1.0; // Defaults to 1.0 if value is outside 0:1 range
-};
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 5f5f797c44c..a96e0c03616 100644
--- a/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
+++ b/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
@@ -7,12 +7,10 @@
#include <memory>
#include <utility>
-#include "gpu/config/gpu_feature_info.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/core/css/css_font_selector.h"
#include "third_party/blink/renderer/core/css/offscreen_font_selector.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
-#include "third_party/blink/renderer/core/dom/exception_code.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/html/canvas/canvas_async_blob_creator.h"
@@ -23,10 +21,10 @@
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
+#include "third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
-#include "third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/blink/renderer/platform/image-encoders/image_encoder_utils.h"
@@ -45,15 +43,15 @@ OffscreenCanvas* OffscreenCanvas::Create(unsigned width, unsigned height) {
OffscreenCanvas::~OffscreenCanvas() = default;
-void OffscreenCanvas::Commit(scoped_refptr<StaticBitmapImage> bitmap_image,
+void OffscreenCanvas::Commit(scoped_refptr<CanvasResource> canvas_resource,
const SkIRect& damage_rect) {
- if (!HasPlaceholderCanvas())
+ if (!HasPlaceholderCanvas() || !canvas_resource)
return;
- double commit_start_time = WTF::CurrentTimeTicksInSeconds();
+ base::TimeTicks commit_start_time = WTF::CurrentTimeTicks();
current_frame_damage_rect_.join(damage_rect);
- GetOrCreateFrameDispatcher()->DispatchFrameSync(
- std::move(bitmap_image), commit_start_time, current_frame_damage_rect_);
+ GetOrCreateResourceDispatcher()->DispatchFrameSync(
+ canvas_resource->Bitmap(), commit_start_time, current_frame_damage_rect_);
current_frame_damage_rect_ = SkIRect::MakeEmpty();
}
@@ -62,6 +60,29 @@ void OffscreenCanvas::Dispose() {
context_->DetachHost();
context_ = nullptr;
}
+
+ if (HasPlaceholderCanvas() && GetTopExecutionContext() &&
+ GetTopExecutionContext()->IsWorkerGlobalScope()) {
+ WorkerAnimationFrameProvider* animation_frame_provider =
+ ToWorkerGlobalScope(GetTopExecutionContext())
+ ->GetAnimationFrameProvider();
+ if (animation_frame_provider) {
+ animation_frame_provider->DeregisterOffscreenCanvas(this);
+ }
+ }
+}
+
+void OffscreenCanvas::SetPlaceholderCanvasId(DOMNodeId canvas_id) {
+ placeholder_canvas_id_ = canvas_id;
+ if (GetTopExecutionContext() &&
+ GetTopExecutionContext()->IsWorkerGlobalScope()) {
+ WorkerAnimationFrameProvider* animation_frame_provider =
+ ToWorkerGlobalScope(GetTopExecutionContext())
+ ->GetAnimationFrameProvider();
+ if (animation_frame_provider) {
+ animation_frame_provider->RegisterOffscreenCanvas(this);
+ }
+ }
}
void OffscreenCanvas::setWidth(unsigned width) {
@@ -108,12 +129,12 @@ ImageBitmap* OffscreenCanvas::transferToImageBitmap(
ExceptionState& exception_state) {
if (is_neutered_) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Cannot transfer an ImageBitmap from a detached OffscreenCanvas");
return nullptr;
}
if (!context_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Cannot transfer an ImageBitmap from an "
"OffscreenCanvas with no context");
return nullptr;
@@ -121,7 +142,8 @@ ImageBitmap* OffscreenCanvas::transferToImageBitmap(
ImageBitmap* image = context_->TransferToImageBitmap(script_state);
if (!image) {
// Undocumented exception (not in spec)
- exception_state.ThrowDOMException(kV8Error, "Out of memory");
+ exception_state.ThrowDOMException(DOMExceptionCode::kUnknownError,
+ "Out of memory");
}
return image;
}
@@ -180,7 +202,7 @@ CanvasRenderingContext* OffscreenCanvas::GetCanvasRenderingContext(
// Unknown type.
if (context_type == CanvasRenderingContext::kContextTypeCount ||
(context_type == CanvasRenderingContext::kContextXRPresent &&
- !OriginTrials::webXREnabled(execution_context)))
+ !OriginTrials::WebXREnabled(execution_context)))
return nullptr;
CanvasRenderingContextFactory* factory =
@@ -231,68 +253,98 @@ bool OffscreenCanvas::IsAccelerated() const {
return context_ && context_->IsAccelerated();
}
-OffscreenCanvasFrameDispatcher* OffscreenCanvas::GetOrCreateFrameDispatcher() {
+bool OffscreenCanvas::HasPlaceholderCanvas() const {
+ return placeholder_canvas_id_ != kInvalidDOMNodeId;
+}
+
+CanvasResourceDispatcher* OffscreenCanvas::GetOrCreateResourceDispatcher() {
+ DCHECK(HasPlaceholderCanvas());
+ // If we don't have a valid placeholder_canvas_id_, then this is a standalone
+ // OffscreenCanvas, and it should not have a placeholder.
if (!frame_dispatcher_) {
// The frame dispatcher connects the current thread of OffscreenCanvas
// (either main or worker) to the browser process and remains unchanged
// throughout the lifetime of this OffscreenCanvas.
- frame_dispatcher_ = std::make_unique<OffscreenCanvasFrameDispatcher>(
+ frame_dispatcher_ = std::make_unique<CanvasResourceDispatcher>(
this, client_id_, sink_id_, placeholder_canvas_id_, size_);
}
return frame_dispatcher_.get();
}
void OffscreenCanvas::DiscardResourceProvider() {
- resource_provider_.reset();
+ CanvasResourceHost::DiscardResourceProvider();
needs_matrix_clip_restore_ = true;
}
CanvasResourceProvider* OffscreenCanvas::GetOrCreateResourceProvider() {
- if (!resource_provider_) {
- bool is_accelerated_2d_canvas_blacklisted = true;
- if (SharedGpuContext::IsGpuCompositingEnabled()) {
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>
- context_provider_wrapper = SharedGpuContext::ContextProviderWrapper();
- if (context_provider_wrapper) {
- const gpu::GpuFeatureInfo& gpu_feature_info =
- context_provider_wrapper->ContextProvider()->GetGpuFeatureInfo();
- if (gpu::kGpuFeatureStatusEnabled ==
- gpu_feature_info
- .status_values[gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS]) {
- is_accelerated_2d_canvas_blacklisted = false;
- }
+ if (!ResourceProvider()) {
+ bool can_use_gpu = false;
+ CanvasResourceProvider::PresentationMode presentation_mode =
+ CanvasResourceProvider::kDefaultPresentationMode;
+ if (Is2d()) {
+ if (RuntimeEnabledFeatures::Canvas2dImageChromiumEnabled()) {
+ presentation_mode =
+ CanvasResourceProvider::kAllowImageChromiumPresentationMode;
+ }
+ if (SharedGpuContext::IsGpuCompositingEnabled() &&
+ RuntimeEnabledFeatures::Accelerated2dCanvasEnabled()) {
+ can_use_gpu = true;
+ }
+ } else if (Is3d()) {
+ if (RuntimeEnabledFeatures::WebGLImageChromiumEnabled()) {
+ presentation_mode =
+ CanvasResourceProvider::kAllowImageChromiumPresentationMode;
}
+ can_use_gpu = SharedGpuContext::IsGpuCompositingEnabled();
}
IntSize surface_size(width(), height());
- if (RuntimeEnabledFeatures::Accelerated2dCanvasEnabled() &&
- !is_accelerated_2d_canvas_blacklisted) {
- resource_provider_ = CanvasResourceProvider::Create(
- surface_size, CanvasResourceProvider::kAcceleratedResourceUsage,
- SharedGpuContext::ContextProviderWrapper(), 0,
- context_->ColorParams());
- }
-
- if (!resource_provider_ || !resource_provider_->IsValid()) {
- resource_provider_ = CanvasResourceProvider::Create(
- surface_size, CanvasResourceProvider::kSoftwareResourceUsage, nullptr,
- 0, context_->ColorParams());
+ CanvasResourceProvider::ResourceUsage usage;
+ if (can_use_gpu) {
+ if (HasPlaceholderCanvas()) {
+ usage = CanvasResourceProvider::kAcceleratedCompositedResourceUsage;
+ } else {
+ usage = CanvasResourceProvider::kAcceleratedResourceUsage;
+ }
+ } else {
+ if (HasPlaceholderCanvas()) {
+ usage = CanvasResourceProvider::kSoftwareCompositedResourceUsage;
+ } else {
+ usage = CanvasResourceProvider::kSoftwareResourceUsage;
+ }
}
- if (resource_provider_ && resource_provider_->IsValid()) {
- resource_provider_->Clear();
+ base::WeakPtr<CanvasResourceDispatcher> dispatcher_weakptr =
+ HasPlaceholderCanvas() ? GetOrCreateResourceDispatcher()->GetWeakPtr()
+ : nullptr;
+
+ ReplaceResourceProvider(CanvasResourceProvider::Create(
+ surface_size, usage, SharedGpuContext::ContextProviderWrapper(), 0,
+ context_->ColorParams(), presentation_mode,
+ std::move(dispatcher_weakptr)));
+
+ // The fallback chain for k*CompositedResourceUsage should never fall
+ // all the way through to BitmapResourceProvider, except in unit tests.
+ // In non unit-test scenarios, it should always be possible to at least
+ // get a ResourceProviderSharedBitmap as a last resort.
+ // This CHECK verifies that we did indeed get a resource provider that
+ // supports compositing when one is required.
+ CHECK(!ResourceProvider() || !HasPlaceholderCanvas() ||
+ ResourceProvider()->SupportsDirectCompositing());
+
+ if (ResourceProvider() && ResourceProvider()->IsValid()) {
+ ResourceProvider()->Clear();
// Always save an initial frame, to support resetting the top level matrix
// and clip.
- resource_provider_->Canvas()->save();
- }
+ ResourceProvider()->Canvas()->save();
- if (resource_provider_ && needs_matrix_clip_restore_) {
- needs_matrix_clip_restore_ = false;
- context_->RestoreCanvasMatrixClipStack(resource_provider_->Canvas());
+ if (needs_matrix_clip_restore_) {
+ needs_matrix_clip_restore_ = false;
+ context_->RestoreCanvasMatrixClipStack(ResourceProvider()->Canvas());
+ }
}
}
-
- return resource_provider_.get();
+ return ResourceProvider();
}
void OffscreenCanvas::DidDraw() {
@@ -303,85 +355,44 @@ void OffscreenCanvas::DidDraw(const FloatRect& rect) {
if (rect.IsEmpty())
return;
- if (!HasPlaceholderCanvas())
- return;
-
- GetOrCreateFrameDispatcher()->SetNeedsBeginFrame(true);
+ if (HasPlaceholderCanvas()) {
+ needs_push_frame_ = true;
+ // TODO(fserb): perhaps we could avoid requesting begin frames here in cases
+ // where the draw is call from within a worker rAF?
+ GetOrCreateResourceDispatcher()->SetNeedsBeginFrame(true);
+ }
}
void OffscreenCanvas::BeginFrame() {
- context_->PushFrame();
- GetOrCreateFrameDispatcher()->SetNeedsBeginFrame(false);
-}
-
-void OffscreenCanvas::PushFrame(scoped_refptr<StaticBitmapImage> image,
- const SkIRect& damage_rect) {
- current_frame_damage_rect_.join(damage_rect);
- if (current_frame_damage_rect_.isEmpty())
- return;
- double commit_start_time = WTF::CurrentTimeTicksInSeconds();
- GetOrCreateFrameDispatcher()->DispatchFrame(
- std::move(image), commit_start_time, current_frame_damage_rect_);
- current_frame_damage_rect_ = SkIRect::MakeEmpty();
+ DCHECK(HasPlaceholderCanvas());
+ PushFrameIfNeeded();
+ GetOrCreateResourceDispatcher()->SetNeedsBeginFrame(false);
}
-ScriptPromise OffscreenCanvas::convertToBlob(ScriptState* script_state,
- const ImageEncodeOptions& options,
- ExceptionState& exception_state) {
- if (this->IsNeutered()) {
- exception_state.ThrowDOMException(kInvalidStateError,
- "OffscreenCanvas object is detached.");
- return exception_state.Reject(script_state);
- }
-
- if (!this->OriginClean()) {
- exception_state.ThrowSecurityError(
- "Tainted OffscreenCanvas may not be exported.");
- return exception_state.Reject(script_state);
- }
-
- if (!this->IsPaintable() || size_.IsEmpty()) {
- exception_state.ThrowDOMException(
- kIndexSizeError, "The size of the OffscreenCanvas is zero.");
- return exception_state.Reject(script_state);
- }
-
- if (!this->context_) {
- exception_state.ThrowDOMException(
- kInvalidStateError, "OffscreenCanvas object has no rendering contexts");
- return exception_state.Reject(script_state);
+void OffscreenCanvas::PushFrameIfNeeded() {
+ if (needs_push_frame_ && context_) {
+ context_->PushFrame();
}
+}
- double start_time = WTF::CurrentTimeTicksInSeconds();
- scoped_refptr<StaticBitmapImage> snapshot =
- context_->GetImage(kPreferNoAcceleration);
- if (snapshot) {
- ScriptPromiseResolver* resolver =
- ScriptPromiseResolver::Create(script_state);
- String encoding_mime_type = ImageEncoderUtils::ToEncodingMimeType(
- options.type(), ImageEncoderUtils::kEncodeReasonConvertToBlobPromise);
- CanvasAsyncBlobCreator* async_creator = CanvasAsyncBlobCreator::Create(
- snapshot, encoding_mime_type, start_time,
- ExecutionContext::From(script_state), resolver);
- async_creator->ScheduleAsyncBlobCreation(options.quality());
- return resolver->Promise();
- } else {
- exception_state.ThrowDOMException(
- kNotReadableError, "Readback of the source image has failed.");
- return exception_state.Reject(script_state);
- }
+bool OffscreenCanvas::ShouldAccelerate2dContext() const {
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper =
+ SharedGpuContext::ContextProviderWrapper();
+ return context_provider_wrapper &&
+ context_provider_wrapper->Utils()->Accelerated2DCanvasFeatureEnabled();
}
-void OffscreenCanvas::RegisterContextToDispatch(
- CanvasRenderingContext* context) {
- if (!HasPlaceholderCanvas())
+void OffscreenCanvas::PushFrame(scoped_refptr<CanvasResource> canvas_resource,
+ const SkIRect& damage_rect) {
+ DCHECK(needs_push_frame_);
+ needs_push_frame_ = false;
+ current_frame_damage_rect_.join(damage_rect);
+ if (current_frame_damage_rect_.isEmpty() || !canvas_resource)
return;
-
- if (GetExecutionContext()->IsWorkerGlobalScope()) {
- ToWorkerGlobalScope(GetExecutionContext())
- ->GetAnimationFrameProvider()
- ->AddContextToDispatch(context);
- }
+ base::TimeTicks commit_start_time = WTF::CurrentTimeTicks();
+ GetOrCreateResourceDispatcher()->DispatchFrame(
+ canvas_resource->Bitmap(), commit_start_time, current_frame_damage_rect_);
+ current_frame_damage_rect_ = SkIRect::MakeEmpty();
}
FontSelector* OffscreenCanvas::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 b1b6fd941cb..a1c67e02ee8 100644
--- a/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h
+++ b/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h
@@ -12,12 +12,12 @@
#include "third_party/blink/renderer/core/html/canvas/canvas_image_source.h"
#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h"
#include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
+#include "third_party/blink/renderer/core/html/canvas/image_encode_options.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap_source.h"
-#include "third_party/blink/renderer/core/offscreencanvas/image_encode_options.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
-#include "third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher.h"
+#include "third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
@@ -25,17 +25,24 @@ namespace blink {
class CanvasContextCreationAttributesCore;
class CanvasResourceProvider;
class ImageBitmap;
+#if defined(SUPPORT_WEBGL2_COMPUTE_CONTEXT)
+class
+ OffscreenCanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContext;
+typedef OffscreenCanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContextOrWebGL2ComputeRenderingContext
+ OffscreenRenderingContext;
+#else
class
OffscreenCanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContext;
typedef OffscreenCanvasRenderingContext2DOrWebGLRenderingContextOrWebGL2RenderingContext
OffscreenRenderingContext;
+#endif
class CORE_EXPORT OffscreenCanvas final
: public EventTargetWithInlineData,
public CanvasImageSource,
public ImageBitmapSource,
public CanvasRenderingContextHost,
- public OffscreenCanvasFrameDispatcherClient {
+ public CanvasResourceDispatcherClient {
DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(OffscreenCanvas);
USING_PRE_FINALIZER(OffscreenCanvas, Dispose);
@@ -52,26 +59,19 @@ class CORE_EXPORT OffscreenCanvas final
void setWidth(unsigned);
void setHeight(unsigned);
- // OffscreenCanvasFrameDispatcherClient
+ // CanvasResourceDispatcherClient
void BeginFrame() override;
// API Methods
ImageBitmap* transferToImageBitmap(ScriptState*, ExceptionState&);
- ScriptPromise convertToBlob(ScriptState*,
- const ImageEncodeOptions&,
- ExceptionState&);
const IntSize& Size() const override { return size_; }
void SetSize(const IntSize&);
- void SetPlaceholderCanvasId(DOMNodeId canvas_id) {
- placeholder_canvas_id_ = canvas_id;
- }
+ void SetPlaceholderCanvasId(DOMNodeId canvas_id);
DOMNodeId PlaceholderCanvasId() const { return placeholder_canvas_id_; }
- bool HasPlaceholderCanvas() {
- return placeholder_canvas_id_ != kInvalidDOMNodeId;
- }
- bool IsNeutered() const { return is_neutered_; }
+ bool HasPlaceholderCanvas() const;
+ bool IsNeutered() const override { return is_neutered_; }
void SetNeutered();
CanvasRenderingContext* GetCanvasRenderingContext(
ExecutionContext*,
@@ -88,11 +88,8 @@ class CORE_EXPORT OffscreenCanvas final
disable_reading_from_canvas_ = true;
}
- void DiscardResourceProvider() override;
- CanvasResourceProvider* GetResourceProvider() const {
- return resource_provider_.get();
- }
CanvasResourceProvider* GetOrCreateResourceProvider();
+ void DiscardResourceProvider() override;
void SetFrameSinkId(uint32_t client_id, uint32_t sink_id) {
client_id_ = client_id;
@@ -102,20 +99,27 @@ class CORE_EXPORT OffscreenCanvas final
uint32_t SinkId() const { return sink_id_; }
// CanvasRenderingContextHost implementation.
- void FinalizeFrame() override{};
+ void FinalizeFrame() override {}
void DetachContext() override { context_ = nullptr; }
CanvasRenderingContext* RenderingContext() const override { return context_; }
- void PushFrame(scoped_refptr<StaticBitmapImage> image,
+ void PushFrameIfNeeded();
+ void PushFrame(scoped_refptr<CanvasResource> frame,
const SkIRect& damage_rect) override;
void DidDraw(const FloatRect&) override;
void DidDraw() override;
- void Commit(scoped_refptr<StaticBitmapImage> bitmap_image,
+ void Commit(scoped_refptr<CanvasResource> bitmap_image,
const SkIRect& damage_rect) override;
+ bool ShouldAccelerate2dContext() const override;
+ unsigned GetMSAASampleCountFor2dContext() const override { return 0; }
+ CanvasResourceDispatcher* GetOrCreateResourceDispatcher() override;
// Partial CanvasResourceHost implementation
- void NotifyGpuContextLost() override{};
- void SetNeedsCompositingUpdate() override{};
- void UpdateMemoryUsage() override{/*TODO(crbug.com/842693): implement*/};
+ void NotifyGpuContextLost() override {}
+ void SetNeedsCompositingUpdate() override {}
+ void UpdateMemoryUsage() override {} // TODO(crbug.com/842693): implement
+ SkFilterQuality FilterQuality() const override {
+ return kLow_SkFilterQuality; // TODO(crbug.com/856654)
+ }
// EventTarget implementation
const AtomicString& InterfaceName() const final {
@@ -161,8 +165,6 @@ class CORE_EXPORT OffscreenCanvas final
bool IsWebGL2Enabled() const override { return true; }
bool IsWebGLBlocked() const override { return false; }
- void RegisterContextToDispatch(CanvasRenderingContext*) override;
-
FontSelector* GetFontSelector() override;
void Trace(blink::Visitor*) override;
@@ -170,7 +172,6 @@ class CORE_EXPORT OffscreenCanvas final
private:
friend class OffscreenCanvasTest;
explicit OffscreenCanvas(const IntSize&);
- OffscreenCanvasFrameDispatcher* GetOrCreateFrameDispatcher();
using ContextFactoryVector =
Vector<std::unique_ptr<CanvasRenderingContextFactory>>;
static ContextFactoryVector& RenderingContextFactories();
@@ -187,12 +188,12 @@ class CORE_EXPORT OffscreenCanvas final
bool origin_clean_ = true;
bool disable_reading_from_canvas_ = false;
- std::unique_ptr<OffscreenCanvasFrameDispatcher> frame_dispatcher_;
+ std::unique_ptr<CanvasResourceDispatcher> frame_dispatcher_;
SkIRect current_frame_damage_rect_;
- std::unique_ptr<CanvasResourceProvider> resource_provider_;
bool needs_matrix_clip_restore_ = false;
+ bool needs_push_frame_ = false;
// cc::FrameSinkId is broken into two integer components as this can be used
// in transfer of OffscreenCanvas across threads
diff --git a/chromium/third_party/blink/renderer/core/page/BUILD.gn b/chromium/third_party/blink/renderer/core/page/BUILD.gn
index 029ba5fdd69..ec5831d4deb 100644
--- a/chromium/third_party/blink/renderer/core/page/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/page/BUILD.gn
@@ -34,7 +34,6 @@ blink_core_sources("page") {
"page.h",
"page_animator.cc",
"page_animator.h",
- "page_lifecycle_state.h",
"page_overlay.cc",
"page_overlay.h",
"page_popup.h",
@@ -97,5 +96,7 @@ blink_core_sources("page") {
"validation_message_client_impl.h",
"validation_message_overlay_delegate.cc",
"validation_message_overlay_delegate.h",
+ "viewport_description.cc",
+ "viewport_description.h",
]
}
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 9030d957151..9849c205f65 100644
--- a/chromium/third_party/blink/renderer/core/page/chrome_client.cc
+++ b/chromium/third_party/blink/renderer/core/page/chrome_client.cc
@@ -165,6 +165,7 @@ bool ChromeClient::OpenJavaScriptPrompt(LocalFrame* frame,
}
void ChromeClient::MouseDidMoveOverElement(LocalFrame& frame,
+ const HitTestLocation& location,
const HitTestResult& result) {
if (!result.GetScrollbar() && result.InnerNode() &&
result.InnerNode()->GetDocument().IsDNSPrefetchEnabled())
@@ -175,10 +176,12 @@ void ChromeClient::MouseDidMoveOverElement(LocalFrame& frame,
if (result.GetScrollbar())
ClearToolTip(frame);
else
- SetToolTip(frame, result);
+ SetToolTip(frame, location, result);
}
-void ChromeClient::SetToolTip(LocalFrame& frame, const HitTestResult& result) {
+void ChromeClient::SetToolTip(LocalFrame& frame,
+ const HitTestLocation& location,
+ const HitTestResult& result) {
// First priority is a tooltip for element with "title" attribute.
TextDirection tool_tip_direction;
String tool_tip = result.Title(tool_tip_direction);
@@ -200,7 +203,7 @@ void ChromeClient::SetToolTip(LocalFrame& frame, const HitTestResult& result) {
}
}
- if (last_tool_tip_point_ == result.GetHitTestLocation().Point() &&
+ if (last_tool_tip_point_ == location.Point() &&
last_tool_tip_text_ == tool_tip)
return;
@@ -214,7 +217,7 @@ void ChromeClient::SetToolTip(LocalFrame& frame, const HitTestResult& result) {
!last_tool_tip_text_.IsEmpty() && tool_tip == last_tool_tip_text_)
ClearToolTip(frame);
- last_tool_tip_point_ = result.GetHitTestLocation().Point();
+ last_tool_tip_point_ = location.Point();
last_tool_tip_text_ = tool_tip;
last_mouse_over_node_ = result.InnerNodeOrImageMapImage();
SetToolTip(frame, tool_tip, tool_tip_direction);
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 38befcf26bb..a032cc6d181 100644
--- a/chromium/third_party/blink/renderer/core/page/chrome_client.h
+++ b/chromium/third_party/blink/renderer/core/page/chrome_client.h
@@ -26,13 +26,13 @@
#include <memory>
#include "base/gtest_prod_util.h"
#include "base/optional.h"
+#include "cc/input/event_listener_properties.h"
#include "third_party/blink/public/platform/blame_context.h"
#include "third_party/blink/public/platform/web_drag_operation.h"
-#include "third_party/blink/public/platform/web_event_listener_properties.h"
#include "third_party/blink/public/platform/web_focus_type.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/dom/animation_worklet_proxy_client.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
#include "third_party/blink/renderer/core/frame/sandbox_flags.h"
#include "third_party/blink/renderer/core/html/forms/popup_menu.h"
#include "third_party/blink/renderer/core/inspector/console_types.h"
@@ -71,6 +71,7 @@ class GraphicsLayer;
class HTMLFormControlElement;
class HTMLInputElement;
class HTMLSelectElement;
+class HitTestLocation;
class HitTestResult;
class IntRect;
class KeyboardEvent;
@@ -82,7 +83,6 @@ class PagePopup;
class PagePopupClient;
class PopupOpeningObserver;
class WebDragData;
-class WebImage;
class WebLayerTreeView;
class WebViewImpl;
@@ -130,7 +130,7 @@ class CORE_EXPORT ChromeClient : public PlatformChromeClient {
virtual void StartDragging(LocalFrame*,
const WebDragData&,
WebDragOperationsMask,
- const WebImage& drag_image,
+ const SkBitmap& drag_image,
const WebPoint& drag_image_offset) = 0;
virtual bool AcceptsLoadDrops() const = 0;
@@ -219,7 +219,9 @@ class CORE_EXPORT ChromeClient : public PlatformChromeClient {
virtual void ResizeAfterLayout() const {}
virtual void LayoutUpdated() const {}
- void MouseDidMoveOverElement(LocalFrame&, const HitTestResult&);
+ void MouseDidMoveOverElement(LocalFrame&,
+ const HitTestLocation&,
+ const HitTestResult&);
virtual void SetToolTip(LocalFrame&, const String&, TextDirection) = 0;
void ClearToolTip(LocalFrame&);
@@ -275,11 +277,11 @@ class CORE_EXPORT ChromeClient : public PlatformChromeClient {
const CompositedSelection&) {}
virtual void SetEventListenerProperties(LocalFrame*,
- WebEventListenerClass,
- WebEventListenerProperties) = 0;
- virtual WebEventListenerProperties EventListenerProperties(
+ cc::EventListenerClass,
+ cc::EventListenerProperties) = 0;
+ virtual cc::EventListenerProperties EventListenerProperties(
LocalFrame*,
- WebEventListenerClass) const = 0;
+ cc::EventListenerClass) const = 0;
virtual void SetHasScrollEventHandlers(LocalFrame*, bool) = 0;
virtual void SetNeedsLowLatencyInput(LocalFrame*, bool) = 0;
virtual void RequestUnbufferedInputEvents(LocalFrame*) = 0;
@@ -381,7 +383,7 @@ class CORE_EXPORT ChromeClient : public PlatformChromeClient {
bool CanOpenModalIfDuringPageDismissal(Frame& main_frame,
DialogType,
const String& message);
- void SetToolTip(LocalFrame&, const HitTestResult&);
+ void SetToolTip(LocalFrame&, const HitTestLocation&, const HitTestResult&);
WeakMember<Node> last_mouse_over_node_;
LayoutPoint last_tool_tip_point_;
@@ -390,6 +392,12 @@ class CORE_EXPORT ChromeClient : public PlatformChromeClient {
FRIEND_TEST_ALL_PREFIXES(ChromeClientTest, SetToolTipFlood);
};
+inline ChromeClient* ToChromeClient(PlatformChromeClient* client) {
+ // In production code, a PlatformChromeClient instance is always a
+ // ChromeClient instance.
+ return static_cast<ChromeClient*>(client);
+}
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_CHROME_CLIENT_H_
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 50350ccbc3f..5656f762955 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
@@ -36,6 +36,7 @@
#include "base/optional.h"
#include "build/build_config.h"
+#include "cc/layers/picture_layer.h"
#include "third_party/blink/public/platform/web_cursor_info.h"
#include "third_party/blink/public/platform/web_float_rect.h"
#include "third_party/blink/public/platform/web_rect.h"
@@ -43,12 +44,11 @@
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/public/web/web_autofill_client.h"
#include "third_party/blink/public/web/web_console_message.h"
-#include "third_party/blink/public/web/web_frame_client.h"
#include "third_party/blink/public/web/web_input_element.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_node.h"
#include "third_party/blink/public/web/web_plugin.h"
#include "third_party/blink/public/web/web_popup_menu_info.h"
-#include "third_party/blink/public/web/web_selection.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/public/web/web_text_direction.h"
#include "third_party/blink/public/web/web_view_client.h"
@@ -159,6 +159,11 @@ ChromeClientImpl* ChromeClientImpl::Create(WebViewImpl* web_view) {
return new ChromeClientImpl(web_view);
}
+void ChromeClientImpl::Trace(Visitor* visitor) {
+ visitor->Trace(popup_opening_observers_);
+ ChromeClient::Trace(visitor);
+}
+
WebViewImpl* ChromeClientImpl::GetWebView() const {
return web_view_;
}
@@ -238,7 +243,7 @@ bool ChromeClientImpl::HadFormInteraction() const {
void ChromeClientImpl::StartDragging(LocalFrame* frame,
const WebDragData& drag_data,
WebDragOperationsMask mask,
- const WebImage& drag_image,
+ const SkBitmap& drag_image,
const WebPoint& drag_image_offset) {
WebLocalFrameImpl* web_frame = WebLocalFrameImpl::FromFrame(frame);
WebReferrerPolicy policy = web_frame->GetDocument().GetReferrerPolicy();
@@ -261,6 +266,7 @@ Page* ChromeClientImpl::CreateWindow(LocalFrame* frame,
if (!frame->GetPage() || frame->GetPage()->Paused())
return nullptr;
+ NotifyPopupOpeningObservers();
const AtomicString& frame_name =
!EqualIgnoringASCIICase(r.FrameName(), "_blank") ? r.FrameName()
: g_empty_atom;
@@ -281,17 +287,17 @@ void ChromeClientImpl::DidOverscroll(const FloatSize& overscroll_delta,
const FloatPoint& position_in_viewport,
const FloatSize& velocity_in_viewport,
const cc::OverscrollBehavior& behavior) {
- if (!web_view_->Client())
+ if (!web_view_->WidgetClient())
return;
- web_view_->Client()->DidOverscroll(overscroll_delta, accumulated_overscroll,
- position_in_viewport, velocity_in_viewport,
- behavior);
+ web_view_->WidgetClient()->DidOverscroll(
+ overscroll_delta, accumulated_overscroll, position_in_viewport,
+ velocity_in_viewport, behavior);
}
void ChromeClientImpl::Show(NavigationPolicy navigation_policy) {
- if (web_view_->Client()) {
- web_view_->Client()->Show(
+ if (web_view_->WidgetClient()) {
+ web_view_->WidgetClient()->Show(
static_cast<WebNavigationPolicy>(navigation_policy));
}
}
@@ -334,8 +340,8 @@ bool ChromeClientImpl::OpenBeforeUnloadConfirmPanelDelegate(LocalFrame* frame,
}
void ChromeClientImpl::CloseWindowSoon() {
- if (web_view_->Client())
- web_view_->Client()->CloseWidgetSoon();
+ if (web_view_->WidgetClient())
+ web_view_->WidgetClient()->CloseWidgetSoon();
}
// Although a LocalFrame is passed in, we don't actually use it, since we
@@ -430,16 +436,17 @@ IntRect ChromeClientImpl::ViewportToScreen(
}
float ChromeClientImpl::WindowToViewportScalar(const float scalar_value) const {
- if (!web_view_->Client())
+ if (!web_view_->WidgetClient())
return scalar_value;
WebFloatRect viewport_rect(0, 0, scalar_value, 0);
- web_view_->Client()->ConvertWindowToViewport(&viewport_rect);
+ web_view_->WidgetClient()->ConvertWindowToViewport(&viewport_rect);
return viewport_rect.width;
}
WebScreenInfo ChromeClientImpl::GetScreenInfo() const {
- return web_view_->Client() ? web_view_->Client()->GetScreenInfo()
- : WebScreenInfo();
+ if (!web_view_->WidgetClient())
+ return {};
+ return web_view_->WidgetClient()->GetScreenInfo();
}
base::Optional<IntRect> ChromeClientImpl::VisibleContentRectForPainting()
@@ -576,7 +583,7 @@ void ChromeClientImpl::OpenFileChooser(
LocalFrame* frame,
scoped_refptr<FileChooser> file_chooser) {
NotifyPopupOpeningObservers();
- WebFrameClient* client = WebLocalFrameImpl::FromFrame(frame)->Client();
+ WebLocalFrameClient* client = WebLocalFrameImpl::FromFrame(frame)->Client();
if (!client)
return;
@@ -763,8 +770,36 @@ void ChromeClientImpl::UpdateCompositedSelection(
if (!client)
return;
- if (WebLayerTreeView* layer_tree_view = widget->GetLayerTreeView())
- layer_tree_view->RegisterSelection(WebSelection(selection));
+ if (WebLayerTreeView* layer_tree_view = widget->GetLayerTreeView()) {
+ DCHECK_NE(selection.type, kNoSelection);
+
+ cc::LayerSelection cc_selection;
+ if (selection.type == kRangeSelection) {
+ cc_selection.start.type = selection.start.is_text_direction_rtl
+ ? gfx::SelectionBound::Type::RIGHT
+ : gfx::SelectionBound::Type::LEFT;
+ cc_selection.end.type = selection.end.is_text_direction_rtl
+ ? gfx::SelectionBound::Type::LEFT
+ : gfx::SelectionBound::Type::RIGHT;
+ } else {
+ cc_selection.start.type = gfx::SelectionBound::Type::CENTER;
+ cc_selection.end.type = gfx::SelectionBound::Type::CENTER;
+ }
+ cc_selection.start.edge_top =
+ gfx::Point(RoundedIntPoint(selection.start.edge_top_in_layer));
+ cc_selection.start.edge_bottom =
+ gfx::Point(RoundedIntPoint(selection.start.edge_bottom_in_layer));
+ cc_selection.start.layer_id = selection.start.layer->CcLayer()->id();
+ cc_selection.start.hidden = selection.start.hidden;
+ cc_selection.end.edge_top =
+ gfx::Point(RoundedIntPoint(selection.end.edge_top_in_layer));
+ cc_selection.end.edge_bottom =
+ gfx::Point(RoundedIntPoint(selection.end.edge_bottom_in_layer));
+ cc_selection.end.layer_id = selection.end.layer->CcLayer()->id();
+ cc_selection.end.hidden = selection.end.hidden;
+
+ layer_tree_view->RegisterSelection(cc_selection);
+ }
}
bool ChromeClientImpl::HasOpenedPopup() const {
@@ -841,8 +876,8 @@ void ChromeClientImpl::RequestDecode(LocalFrame* frame,
void ChromeClientImpl::SetEventListenerProperties(
LocalFrame* frame,
- WebEventListenerClass event_class,
- WebEventListenerProperties properties) {
+ cc::EventListenerClass event_class,
+ cc::EventListenerProperties properties) {
// |frame| might be null if called via TreeScopeAdopter::
// moveNodeToNewDocument() and the new document has no frame attached.
// Since a document without a frame cannot attach one later, it is safe to
@@ -857,7 +892,7 @@ void ChromeClientImpl::SetEventListenerProperties(
if (web_frame->IsProvisional()) {
// If we hit a provisional frame, we expect it to be during initialization
// in which case the |properties| should be 'nothing'.
- DCHECK(properties == WebEventListenerProperties::kNothing);
+ DCHECK(properties == cc::EventListenerProperties::kNone);
return;
}
WebFrameWidgetBase* widget = web_frame->LocalRootFrameWidget();
@@ -874,18 +909,18 @@ void ChromeClientImpl::SetEventListenerProperties(
WebWidgetClient* client = widget->Client();
if (WebLayerTreeView* tree_view = widget->GetLayerTreeView()) {
tree_view->SetEventListenerProperties(event_class, properties);
- if (event_class == WebEventListenerClass::kTouchStartOrMove) {
+ if (event_class == cc::EventListenerClass::kTouchStartOrMove) {
client->HasTouchEventHandlers(
- properties != WebEventListenerProperties::kNothing ||
+ properties != cc::EventListenerProperties::kNone ||
tree_view->EventListenerProperties(
- WebEventListenerClass::kTouchEndOrCancel) !=
- WebEventListenerProperties::kNothing);
- } else if (event_class == WebEventListenerClass::kTouchEndOrCancel) {
+ cc::EventListenerClass::kTouchEndOrCancel) !=
+ cc::EventListenerProperties::kNone);
+ } else if (event_class == cc::EventListenerClass::kTouchEndOrCancel) {
client->HasTouchEventHandlers(
- properties != WebEventListenerProperties::kNothing ||
+ properties != cc::EventListenerProperties::kNone ||
tree_view->EventListenerProperties(
- WebEventListenerClass::kTouchStartOrMove) !=
- WebEventListenerProperties::kNothing);
+ cc::EventListenerClass::kTouchStartOrMove) !=
+ cc::EventListenerProperties::kNone);
}
} else {
client->HasTouchEventHandlers(true);
@@ -899,17 +934,17 @@ void ChromeClientImpl::BeginLifecycleUpdates() {
}
}
-WebEventListenerProperties ChromeClientImpl::EventListenerProperties(
+cc::EventListenerProperties ChromeClientImpl::EventListenerProperties(
LocalFrame* frame,
- WebEventListenerClass event_class) const {
+ cc::EventListenerClass event_class) const {
if (!frame)
- return WebEventListenerProperties::kNothing;
+ return cc::EventListenerProperties::kNone;
WebFrameWidgetBase* widget =
WebLocalFrameImpl::FromFrame(frame)->LocalRootFrameWidget();
if (!widget || !widget->GetLayerTreeView())
- return WebEventListenerProperties::kNothing;
+ return cc::EventListenerProperties::kNone;
return widget->GetLayerTreeView()->EventListenerProperties(event_class);
}
@@ -1086,19 +1121,19 @@ void ChromeClientImpl::SetOverscrollBehavior(
void ChromeClientImpl::RegisterPopupOpeningObserver(
PopupOpeningObserver* observer) {
DCHECK(observer);
- popup_opening_observers_.push_back(observer);
+ popup_opening_observers_.insert(observer);
}
void ChromeClientImpl::UnregisterPopupOpeningObserver(
PopupOpeningObserver* observer) {
- size_t index = popup_opening_observers_.Find(observer);
- DCHECK_NE(index, kNotFound);
- popup_opening_observers_.EraseAt(index);
+ DCHECK(popup_opening_observers_.Contains(observer));
+ popup_opening_observers_.erase(observer);
}
void ChromeClientImpl::NotifyPopupOpeningObservers() const {
- const Vector<PopupOpeningObserver*> observers(popup_opening_observers_);
- for (auto* const observer : observers)
+ const HeapHashSet<WeakMember<PopupOpeningObserver>> observers(
+ popup_opening_observers_);
+ for (const auto& observer : observers)
observer->WillOpenPopup();
}
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 9bac9a2695c..5b9a70911d0 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
@@ -52,6 +52,7 @@ class CORE_EXPORT ChromeClientImpl final : public ChromeClient {
public:
static ChromeClientImpl* Create(WebViewImpl*);
~ChromeClientImpl() override;
+ void Trace(Visitor* visitor) override;
WebViewImpl* GetWebView() const override;
@@ -69,7 +70,7 @@ class CORE_EXPORT ChromeClientImpl final : public ChromeClient {
void StartDragging(LocalFrame*,
const WebDragData&,
WebDragOperationsMask,
- const WebImage& drag_image,
+ const SkBitmap& drag_image,
const WebPoint& drag_image_offset) override;
bool AcceptsLoadDrops() const override;
Page* CreateWindow(LocalFrame*,
@@ -137,11 +138,11 @@ class CORE_EXPORT ChromeClientImpl final : public ChromeClient {
// allows the client to know which optimizations can be used for the
// associated event classes.
void SetEventListenerProperties(LocalFrame*,
- WebEventListenerClass,
- WebEventListenerProperties) override;
- WebEventListenerProperties EventListenerProperties(
+ cc::EventListenerClass,
+ cc::EventListenerProperties) override;
+ cc::EventListenerProperties EventListenerProperties(
LocalFrame*,
- WebEventListenerClass) const override;
+ cc::EventListenerClass) const override;
// Informs client about the existence of handlers for scroll events so
// appropriate scroll optimizations can be chosen.
void SetHasScrollEventHandlers(LocalFrame*, bool has_event_handlers) override;
@@ -243,7 +244,7 @@ class CORE_EXPORT ChromeClientImpl final : public ChromeClient {
WebAutofillClient* AutofillClientFromFrame(LocalFrame*);
WebViewImpl* web_view_; // Weak pointer.
- Vector<PopupOpeningObserver*> popup_opening_observers_;
+ HeapHashSet<WeakMember<PopupOpeningObserver>> popup_opening_observers_;
Cursor last_set_mouse_cursor_for_testing_;
bool cursor_overridden_;
bool did_request_non_empty_tool_tip_;
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 f2ed77c35a3..cff471e3ff2 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
@@ -28,10 +28,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "third_party/blink/renderer/core/page/chrome_client_impl.h"
+#include "cc/trees/layer_tree_host.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_input_event.h"
-#include "third_party/blink/public/web/web_frame_client.h"
#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_view.h"
#include "third_party/blink/public/web/web_view_client.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
@@ -42,10 +44,11 @@
#include "third_party/blink/renderer/core/html/forms/date_time_chooser_client.h"
#include "third_party/blink/renderer/core/html/forms/html_select_element.h"
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
-#include "third_party/blink/renderer/core/page/chrome_client_impl.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/scoped_page_pauser.h"
+#include "third_party/blink/renderer/core/paint/compositing/composited_selection.h"
#include "third_party/blink/renderer/platform/language.h"
+#include "third_party/blink/renderer/platform/testing/stub_graphics_layer_client.h"
namespace blink {
@@ -237,4 +240,97 @@ TEST_F(PagePopupSuppressionTest, SuppressDateTimeChooser) {
EXPECT_TRUE(CanOpenDateTimeChooser());
}
+TEST(ChromeClientImplTest, SelectionHandles) {
+ FrameTestHelpers::WebViewHelper helper;
+ WebViewImpl* web_view = helper.Initialize();
+ ChromeClientImpl* chrome_client_impl =
+ ToChromeClientImpl(&web_view->GetPage()->GetChromeClient());
+
+ content::LayerTreeView* layer_tree_view = helper.GetLayerTreeView();
+ LocalFrame* main_frame = helper.LocalMainFrame()->GetFrame();
+
+ auto set_and_get_selection = [&](const CompositedSelection& selection) {
+ // Sets the selection on the LayerTreeHost, then return what it set.
+ chrome_client_impl->UpdateCompositedSelection(main_frame, selection);
+ return layer_tree_view->layer_tree_host()->selection();
+ };
+
+ StubGraphicsLayerClient graphics_layer_client;
+ std::unique_ptr<GraphicsLayer> graphics_layer =
+ GraphicsLayer::Create(graphics_layer_client);
+
+ CompositedSelection selection;
+ cc::LayerSelection cc_selection;
+
+ selection.start.layer = graphics_layer.get();
+ selection.end.layer = graphics_layer.get();
+
+ // An LTR range selection.
+ selection.type = kRangeSelection;
+ selection.start.is_text_direction_rtl = false;
+ selection.end.is_text_direction_rtl = false;
+ selection.start.edge_top_in_layer = FloatPoint(1.1f, 2.8f);
+ selection.start.edge_bottom_in_layer = FloatPoint(2.9f, 3.2f);
+ selection.end.edge_top_in_layer = FloatPoint(4.1f, 5.8f);
+ selection.end.edge_bottom_in_layer = FloatPoint(5.9f, 6.2f);
+ selection.start.hidden = false;
+ selection.end.hidden = false;
+
+ cc_selection = set_and_get_selection(selection);
+ // LTR means the start is left and the end is right.
+ EXPECT_EQ(cc_selection.start.type, gfx::SelectionBound::Type::LEFT);
+ EXPECT_EQ(cc_selection.end.type, gfx::SelectionBound::Type::RIGHT);
+ EXPECT_EQ(cc_selection.start.hidden, false);
+ EXPECT_EQ(cc_selection.end.hidden, false);
+ // Points are rounded.
+ EXPECT_EQ(cc_selection.start.edge_top, gfx::Point(1, 3));
+ EXPECT_EQ(cc_selection.start.edge_bottom, gfx::Point(3, 3));
+ EXPECT_EQ(cc_selection.end.edge_top, gfx::Point(4, 6));
+ EXPECT_EQ(cc_selection.end.edge_bottom, gfx::Point(6, 6));
+
+ // An RTL range selection.
+ selection.start.is_text_direction_rtl = true;
+ selection.end.is_text_direction_rtl = true;
+
+ cc_selection = set_and_get_selection(selection);
+ // RTL means the start is right and the end is left.
+ EXPECT_EQ(cc_selection.start.type, gfx::SelectionBound::Type::RIGHT);
+ EXPECT_EQ(cc_selection.end.type, gfx::SelectionBound::Type::LEFT);
+ EXPECT_EQ(cc_selection.start.hidden, false);
+ EXPECT_EQ(cc_selection.end.hidden, false);
+ EXPECT_EQ(cc_selection.start.edge_top, gfx::Point(1, 3));
+ EXPECT_EQ(cc_selection.start.edge_bottom, gfx::Point(3, 3));
+ EXPECT_EQ(cc_selection.end.edge_top, gfx::Point(4, 6));
+ EXPECT_EQ(cc_selection.end.edge_bottom, gfx::Point(6, 6));
+
+ // A hidden range selection.
+ selection.start.hidden = true;
+ selection.end.hidden = true;
+
+ cc_selection = set_and_get_selection(selection);
+ EXPECT_EQ(cc_selection.start.type, gfx::SelectionBound::Type::RIGHT);
+ EXPECT_EQ(cc_selection.end.type, gfx::SelectionBound::Type::LEFT);
+ // The hidden flag is propogated.
+ EXPECT_EQ(cc_selection.start.hidden, true);
+ EXPECT_EQ(cc_selection.end.hidden, true);
+ EXPECT_EQ(cc_selection.start.edge_top, gfx::Point(1, 3));
+ EXPECT_EQ(cc_selection.start.edge_bottom, gfx::Point(3, 3));
+ EXPECT_EQ(cc_selection.end.edge_top, gfx::Point(4, 6));
+ EXPECT_EQ(cc_selection.end.edge_bottom, gfx::Point(6, 6));
+
+ // A caret selection.
+ selection.type = kCaretSelection;
+
+ cc_selection = set_and_get_selection(selection);
+ // Caret selections have no left/right, only center.
+ EXPECT_EQ(cc_selection.start.type, gfx::SelectionBound::Type::CENTER);
+ EXPECT_EQ(cc_selection.end.type, gfx::SelectionBound::Type::CENTER);
+ EXPECT_EQ(cc_selection.start.hidden, true);
+ EXPECT_EQ(cc_selection.end.hidden, true);
+ EXPECT_EQ(cc_selection.start.edge_top, gfx::Point(1, 3));
+ EXPECT_EQ(cc_selection.start.edge_bottom, gfx::Point(3, 3));
+ EXPECT_EQ(cc_selection.end.edge_top, gfx::Point(4, 6));
+ EXPECT_EQ(cc_selection.end.edge_bottom, gfx::Point(6, 6));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/chrome_client_test.cc b/chromium/third_party/blink/renderer/core/page/chrome_client_test.cc
index f30db3b35a4..d97a2f2c88e 100644
--- a/chromium/third_party/blink/renderer/core/page/chrome_client_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/chrome_client_test.cc
@@ -39,32 +39,32 @@ class ChromeClientTest : public testing::Test {};
TEST_F(ChromeClientTest, SetToolTipFlood) {
ChromeClientToolTipLogger logger;
ChromeClient* client = &logger;
- HitTestResult result(HitTestRequest(HitTestRequest::kMove),
- LayoutPoint(10, 20));
+ HitTestLocation location(LayoutPoint(10, 20));
+ HitTestResult result(HitTestRequest(HitTestRequest::kMove), location);
Document* doc = Document::CreateForTest();
Element* element = HTMLElement::Create(HTMLNames::divTag, *doc);
element->setAttribute(HTMLNames::titleAttr, "tooltip");
result.SetInnerNode(element);
- client->SetToolTip(*doc->GetFrame(), result);
+ client->SetToolTip(*doc->GetFrame(), location, result);
EXPECT_EQ("tooltip", logger.ToolTipForLastSetToolTip());
// seToolTip(HitTestResult) again in the same condition.
logger.ClearToolTipForLastSetToolTip();
- client->SetToolTip(*doc->GetFrame(), result);
+ client->SetToolTip(*doc->GetFrame(), location, result);
// setToolTip(String,TextDirection) should not be called.
EXPECT_EQ(String(), logger.ToolTipForLastSetToolTip());
// Cancel the tooltip, and setToolTip(HitTestResult) again.
client->ClearToolTip(*doc->GetFrame());
logger.ClearToolTipForLastSetToolTip();
- client->SetToolTip(*doc->GetFrame(), result);
+ client->SetToolTip(*doc->GetFrame(), location, result);
// setToolTip(String,TextDirection) should not be called.
EXPECT_EQ(String(), logger.ToolTipForLastSetToolTip());
logger.ClearToolTipForLastSetToolTip();
element->setAttribute(HTMLNames::titleAttr, "updated");
- client->SetToolTip(*doc->GetFrame(), result);
+ client->SetToolTip(*doc->GetFrame(), location, result);
// setToolTip(String,TextDirection) should be called because tooltip string
// is different from the last one.
EXPECT_EQ("updated", logger.ToolTipForLastSetToolTip());
diff --git a/chromium/third_party/blink/renderer/core/page/context_menu_controller.cc b/chromium/third_party/blink/renderer/core/page/context_menu_controller.cc
index a55f5c5d3ab..5af515b231b 100644
--- a/chromium/third_party/blink/renderer/core/page/context_menu_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/context_menu_controller.cc
@@ -32,7 +32,7 @@
#include "third_party/blink/public/platform/web_menu_source_type.h"
#include "third_party/blink/public/web/web_context_menu_data.h"
-#include "third_party/blink/public/web/web_frame_client.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_plugin.h"
#include "third_party/blink/public/web/web_text_check_client.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -46,6 +46,7 @@
#include "third_party/blink/renderer/core/events/mouse_event.h"
#include "third_party/blink/renderer/core/exported/web_plugin_container_impl.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/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/html/forms/html_form_element.h"
@@ -178,7 +179,7 @@ bool ContextMenuController::ShouldShowContextMenuFromTouch(
}
bool ContextMenuController::ShowContextMenu(LocalFrame* frame,
- const LayoutPoint& location,
+ const LayoutPoint& point,
WebMenuSourceType source_type) {
// Displaying the context menu in this function is a big hack as we don't
// have context, i.e. whether this is being invoked via a script or in
@@ -190,20 +191,21 @@ bool ContextMenuController::ShowContextMenu(LocalFrame* frame,
HitTestRequest::HitTestRequestType type =
HitTestRequest::kReadOnly | HitTestRequest::kActive;
- HitTestResult r(type, location);
+ HitTestLocation location(point);
+ HitTestResult result(type, location);
if (frame)
- r = frame->GetEventHandler().HitTestResultAtPoint(location, type);
- if (!r.InnerNodeOrImageMapImage())
+ result = frame->GetEventHandler().HitTestResultAtLocation(location, type);
+ if (!result.InnerNodeOrImageMapImage())
return false;
- hit_test_result_ = r;
- r.SetToShadowHostIfInRestrictedShadowRoot();
+ hit_test_result_ = result;
+ result.SetToShadowHostIfInRestrictedShadowRoot();
- LocalFrame* selected_frame = r.InnerNodeFrame();
+ LocalFrame* selected_frame = result.InnerNodeFrame();
WebContextMenuData data;
- data.mouse_position = selected_frame->View()->ContentsToViewport(
- r.RoundedPointInInnerNodeFrame());
+ data.mouse_position = selected_frame->View()->FrameToViewport(
+ result.RoundedPointInInnerNodeFrame());
data.edit_flags = ComputeEditFlags(
*selected_frame->GetDocument(),
@@ -212,10 +214,10 @@ bool ContextMenuController::ShowContextMenu(LocalFrame* frame,
// Links, Images, Media tags, and Image/Media-Links take preference over
// all else.
- data.link_url = r.AbsoluteLinkURL();
+ data.link_url = result.AbsoluteLinkURL();
- if (r.InnerNode()->IsHTMLElement()) {
- HTMLElement* html_element = ToHTMLElement(r.InnerNode());
+ if (result.InnerNode()->IsHTMLElement()) {
+ HTMLElement* html_element = ToHTMLElement(result.InnerNode());
if (!html_element->title().IsEmpty()) {
data.title_text = html_element->title();
} else {
@@ -223,38 +225,48 @@ bool ContextMenuController::ShowContextMenu(LocalFrame* frame,
}
}
- if (IsHTMLCanvasElement(r.InnerNode())) {
+ if (IsHTMLCanvasElement(result.InnerNode())) {
data.media_type = WebContextMenuData::kMediaTypeCanvas;
data.has_image_contents = true;
- } else if (!r.AbsoluteImageURL().IsEmpty()) {
- data.src_url = r.AbsoluteImageURL();
+ } else if (!result.AbsoluteImageURL().IsEmpty()) {
+ data.src_url = result.AbsoluteImageURL();
data.media_type = WebContextMenuData::kMediaTypeImage;
data.media_flags |= WebContextMenuData::kMediaCanPrint;
// An image can be null for many reasons, like being blocked, no image
// data received from server yet.
- data.has_image_contents = r.GetImage() && !r.GetImage()->IsNull();
+ data.has_image_contents = result.GetImage() && !result.GetImage()->IsNull();
data.is_placeholder_image =
- r.GetImage() && r.GetImage()->IsPlaceholderImage();
+ result.GetImage() && result.GetImage()->IsPlaceholderImage();
if (data.has_image_contents &&
- IsHTMLImageElement(r.InnerNodeOrImageMapImage())) {
+ IsHTMLImageElement(result.InnerNodeOrImageMapImage())) {
HTMLImageElement* image_element =
- ToHTMLImageElement(r.InnerNodeOrImageMapImage());
+ ToHTMLImageElement(result.InnerNodeOrImageMapImage());
if (image_element && image_element->CachedImage()) {
data.image_response = WrappedResourceResponse(
image_element->CachedImage()->GetResponse());
}
}
- } else if (!r.AbsoluteMediaURL().IsEmpty()) {
- data.src_url = r.AbsoluteMediaURL();
+ } else if (!result.AbsoluteMediaURL().IsEmpty()) {
+ data.src_url = result.AbsoluteMediaURL();
// We know that if absoluteMediaURL() is not empty, then this
// is a media element.
- HTMLMediaElement* media_element = ToHTMLMediaElement(r.InnerNode());
+ HTMLMediaElement* media_element = ToHTMLMediaElement(result.InnerNode());
if (IsHTMLVideoElement(*media_element)) {
- data.media_type = WebContextMenuData::kMediaTypeVideo;
- if (media_element->SupportsPictureInPicture())
+ // A video element should be presented as an audio element when it has an
+ // audio track but no video track.
+ if (media_element->HasAudio() && !media_element->HasVideo())
+ data.media_type = WebContextMenuData::kMediaTypeAudio;
+ else
+ data.media_type = WebContextMenuData::kMediaTypeVideo;
+ if (media_element->SupportsPictureInPicture()) {
data.media_flags |= WebContextMenuData::kMediaCanPictureInPicture;
+ if (PictureInPictureController::From(media_element->GetDocument())
+ .IsPictureInPictureElement(media_element)) {
+ data.media_flags |= WebContextMenuData::kMediaPictureInPicture;
+ }
+ }
} else if (IsHTMLAudioElement(*media_element))
data.media_type = WebContextMenuData::kMediaTypeAudio;
@@ -280,9 +292,9 @@ bool ContextMenuController::ShowContextMenu(LocalFrame* frame,
data.media_flags |= WebContextMenuData::kMediaCanToggleControls;
if (media_element->ShouldShowControls())
data.media_flags |= WebContextMenuData::kMediaControls;
- } else if (IsHTMLObjectElement(*r.InnerNode()) ||
- IsHTMLEmbedElement(*r.InnerNode())) {
- LayoutObject* object = r.InnerNode()->GetLayoutObject();
+ } else if (IsHTMLObjectElement(*result.InnerNode()) ||
+ IsHTMLEmbedElement(*result.InnerNode())) {
+ LayoutObject* object = result.InnerNode()->GetLayoutObject();
if (object && object->IsLayoutEmbeddedContent()) {
WebPluginContainerImpl* plugin_view =
ToLayoutEmbeddedContent(object)->Plugin();
@@ -292,7 +304,8 @@ bool ContextMenuController::ShowContextMenu(LocalFrame* frame,
WebPlugin* plugin = plugin_view->Plugin();
data.link_url = plugin->LinkAtPosition(data.mouse_position);
- HTMLPlugInElement* plugin_element = ToHTMLPlugInElement(r.InnerNode());
+ HTMLPlugInElement* plugin_element =
+ ToHTMLPlugInElement(result.InnerNode());
data.src_url =
plugin_element->GetDocument().CompleteURL(plugin_element->Url());
@@ -362,7 +375,8 @@ bool ContextMenuController::ShowContextMenu(LocalFrame* frame,
// If source_type is |kMenuSourceAdjustSelection| or
// |kMenuSourceAdjustSelectionReset| we know the original HitTestResult in
// SelectionController passed the inside check already, so let it pass.
- if (r.IsSelected() || source_type == kMenuSourceAdjustSelection ||
+ if (result.IsSelected(location) ||
+ source_type == kMenuSourceAdjustSelection ||
source_type == kMenuSourceAdjustSelectionReset) {
data.selected_text = selected_frame->SelectedText();
WebRange range =
@@ -370,7 +384,7 @@ bool ContextMenuController::ShowContextMenu(LocalFrame* frame,
data.selection_start_offset = range.StartOffset();
}
- if (r.IsContentEditable()) {
+ if (result.IsContentEditable()) {
data.is_editable = true;
SpellChecker& spell_checker = selected_frame->GetSpellChecker();
@@ -413,7 +427,7 @@ bool ContextMenuController::ShowContextMenu(LocalFrame* frame,
data.custom_items = menu_provider_->PopulateContextMenu();
}
- if (auto* anchor = ToHTMLAnchorElementOrNull(r.URLElement())) {
+ if (auto* anchor = ToHTMLAnchorElementOrNull(result.URLElement())) {
// Extract suggested filename for same-origin URLS for saving file.
const SecurityOrigin* origin =
selected_frame->GetSecurityContext()->GetSecurityOrigin();
@@ -431,9 +445,13 @@ bool ContextMenuController::ShowContextMenu(LocalFrame* frame,
}
// Find the input field type.
- if (auto* input = ToHTMLInputElementOrNull(r.InnerNode())) {
+ if (auto* input = ToHTMLInputElementOrNull(result.InnerNode())) {
if (input->type() == InputTypeNames::password)
data.input_field_type = WebContextMenuData::kInputFieldTypePassword;
+ else if (input->type() == InputTypeNames::number)
+ data.input_field_type = WebContextMenuData::kInputFieldTypeNumber;
+ else if (input->type() == InputTypeNames::tel)
+ data.input_field_type = WebContextMenuData::kInputFieldTypeTelephone;
else if (input->IsTextField())
data.input_field_type = WebContextMenuData::kInputFieldTypePlainText;
else
@@ -445,8 +463,8 @@ bool ContextMenuController::ShowContextMenu(LocalFrame* frame,
IntRect anchor;
IntRect focus;
selected_frame->Selection().ComputeAbsoluteBounds(anchor, focus);
- anchor = selected_frame->View()->ContentsToViewport(anchor);
- focus = selected_frame->View()->ContentsToViewport(focus);
+ anchor = selected_frame->View()->FrameToViewport(anchor);
+ focus = selected_frame->View()->FrameToViewport(focus);
int left = std::min(focus.X(), anchor.X());
int top = std::min(focus.Y(), anchor.Y());
int right = std::max(focus.X() + focus.Width(), anchor.X() + anchor.Width());
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 ee642f9b73d..65d7ad8173c 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
@@ -24,6 +24,7 @@ namespace {
class MockWebMediaPlayerForContextMenu : public EmptyWebMediaPlayer {
public:
+ MOCK_CONST_METHOD0(HasAudio, bool());
MOCK_CONST_METHOD0(HasVideo, bool());
};
@@ -116,7 +117,7 @@ TEST_F(ContextMenuControllerTest, VideoNotLoaded) {
(rect->top() + rect->bottom()) / 2);
EXPECT_TRUE(ShowContextMenu(location, kMenuSourceMouse));
- // Context menu info are sent to the WebFrameClient.
+ // Context menu info are sent to the WebLocalFrameClient.
WebContextMenuData context_menu_data =
GetWebFrameClient().GetContextMenuData();
EXPECT_EQ(WebContextMenuData::kMediaTypeVideo, context_menu_data.media_type);
@@ -135,6 +136,66 @@ TEST_F(ContextMenuControllerTest, VideoNotLoaded) {
{WebContextMenuData::kMediaCanPrint, false},
{WebContextMenuData::kMediaCanRotate, false},
{WebContextMenuData::kMediaCanPictureInPicture, false},
+ {WebContextMenuData::kMediaPictureInPicture, false},
+ };
+
+ for (const auto& expected_media_flag : expected_media_flags) {
+ EXPECT_EQ(expected_media_flag.second,
+ !!(context_menu_data.media_flags & expected_media_flag.first))
+ << "Flag 0x" << std::hex << expected_media_flag.first;
+ }
+}
+
+TEST_F(ContextMenuControllerTest, VideoWithAudioOnly) {
+ ContextMenuAllowedScope context_menu_allowed_scope;
+ HitTestResult hit_test_result;
+ const char video_url[] = "https://example.com/foo.webm";
+
+ // Make sure Picture-in-Picture is enabled.
+ GetDocument()->GetSettings()->SetPictureInPictureEnabled(true);
+
+ // Setup video element.
+ Persistent<HTMLVideoElement> video = HTMLVideoElement::Create(*GetDocument());
+ video->SetSrc(video_url);
+ GetDocument()->body()->AppendChild(video);
+ test::RunPendingTasks();
+ SetReadyState(video.Get(), HTMLMediaElement::kHaveNothing);
+ test::RunPendingTasks();
+
+ EXPECT_CALL(*static_cast<MockWebMediaPlayerForContextMenu*>(
+ video->GetWebMediaPlayer()),
+ HasVideo())
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(*static_cast<MockWebMediaPlayerForContextMenu*>(
+ video->GetWebMediaPlayer()),
+ HasAudio())
+ .WillRepeatedly(Return(true));
+
+ DOMRect* rect = video->getBoundingClientRect();
+ LayoutPoint location((rect->left() + rect->right()) / 2,
+ (rect->top() + rect->bottom()) / 2);
+ EXPECT_TRUE(ShowContextMenu(location, kMenuSourceMouse));
+
+ // Context menu info are sent to the WebLocalFrameClient.
+ WebContextMenuData context_menu_data =
+ GetWebFrameClient().GetContextMenuData();
+ EXPECT_EQ(WebContextMenuData::kMediaTypeAudio, context_menu_data.media_type);
+ EXPECT_EQ(video_url, context_menu_data.src_url.GetString());
+
+ const std::vector<std::pair<WebContextMenuData::MediaFlags, bool>>
+ expected_media_flags = {
+ {WebContextMenuData::kMediaInError, false},
+ {WebContextMenuData::kMediaPaused, true},
+ {WebContextMenuData::kMediaMuted, false},
+ {WebContextMenuData::kMediaLoop, false},
+ {WebContextMenuData::kMediaCanSave, true},
+ {WebContextMenuData::kMediaHasAudio, true},
+ {WebContextMenuData::kMediaCanToggleControls, false},
+ {WebContextMenuData::kMediaControls, false},
+ {WebContextMenuData::kMediaCanPrint, false},
+ {WebContextMenuData::kMediaCanRotate, false},
+ {WebContextMenuData::kMediaCanPictureInPicture, false},
+ {WebContextMenuData::kMediaPictureInPicture, false},
};
for (const auto& expected_media_flag : expected_media_flags) {
@@ -170,7 +231,7 @@ TEST_F(ContextMenuControllerTest, PictureInPictureEnabledVideoLoaded) {
(rect->top() + rect->bottom()) / 2);
EXPECT_TRUE(ShowContextMenu(location, kMenuSourceMouse));
- // Context menu info are sent to the WebFrameClient.
+ // Context menu info are sent to the WebLocalFrameClient.
WebContextMenuData context_menu_data =
GetWebFrameClient().GetContextMenuData();
EXPECT_EQ(WebContextMenuData::kMediaTypeVideo, context_menu_data.media_type);
@@ -189,6 +250,7 @@ TEST_F(ContextMenuControllerTest, PictureInPictureEnabledVideoLoaded) {
{WebContextMenuData::kMediaCanPrint, false},
{WebContextMenuData::kMediaCanRotate, false},
{WebContextMenuData::kMediaCanPictureInPicture, true},
+ {WebContextMenuData::kMediaPictureInPicture, false},
};
for (const auto& expected_media_flag : expected_media_flags) {
@@ -224,7 +286,7 @@ TEST_F(ContextMenuControllerTest, PictureInPictureDisabledVideoLoaded) {
(rect->top() + rect->bottom()) / 2);
EXPECT_TRUE(ShowContextMenu(location, kMenuSourceMouse));
- // Context menu info are sent to the WebFrameClient.
+ // Context menu info are sent to the WebLocalFrameClient.
WebContextMenuData context_menu_data =
GetWebFrameClient().GetContextMenuData();
EXPECT_EQ(WebContextMenuData::kMediaTypeVideo, context_menu_data.media_type);
@@ -243,6 +305,7 @@ TEST_F(ContextMenuControllerTest, PictureInPictureDisabledVideoLoaded) {
{WebContextMenuData::kMediaCanPrint, false},
{WebContextMenuData::kMediaCanRotate, false},
{WebContextMenuData::kMediaCanPictureInPicture, false},
+ {WebContextMenuData::kMediaPictureInPicture, false},
};
for (const auto& expected_media_flag : expected_media_flags) {
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 ffd35a27067..475a2ac3906 100644
--- a/chromium/third_party/blink/renderer/core/page/create_window.cc
+++ b/chromium/third_party/blink/renderer/core/page/create_window.cc
@@ -28,14 +28,9 @@
#include "services/network/public/mojom/request_context_frame_type.mojom-blink.h"
#include "third_party/blink/public/platform/web_input_event.h"
-#include "third_party/blink/public/platform/web_keyboard_event.h"
-#include "third_party/blink/public/platform/web_mouse_event.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/web/web_window_features.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/events/current_input_event.h"
-#include "third_party/blink/renderer/core/events/ui_event_with_key_state.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/frame_client.h"
@@ -46,7 +41,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/probe/core_probes.h"
-#include "third_party/blink/renderer/platform/keyboard_codes.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.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/weborigin/security_origin.h"
@@ -54,94 +49,6 @@
namespace blink {
-namespace {
-
-void UpdatePolicyForEvent(const WebInputEvent* input_event,
- NavigationPolicy* policy) {
- if (!input_event)
- return;
-
- unsigned short button_number = 0;
- if (input_event->GetType() == WebInputEvent::kMouseUp) {
- const WebMouseEvent* mouse_event =
- static_cast<const WebMouseEvent*>(input_event);
-
- switch (mouse_event->button) {
- case WebMouseEvent::Button::kLeft:
- button_number = 0;
- break;
- case WebMouseEvent::Button::kMiddle:
- button_number = 1;
- break;
- case WebMouseEvent::Button::kRight:
- button_number = 2;
- break;
- default:
- return;
- }
- } else if ((WebInputEvent::IsKeyboardEventType(input_event->GetType()) &&
- static_cast<const WebKeyboardEvent*>(input_event)
- ->windows_key_code == VKEY_RETURN) ||
- WebInputEvent::IsGestureEventType(input_event->GetType())) {
- // Keyboard and gesture events can simulate mouse events.
- button_number = 0;
- } else {
- return;
- }
-
- bool ctrl = input_event->GetModifiers() & WebInputEvent::kControlKey;
- bool shift = input_event->GetModifiers() & WebInputEvent::kShiftKey;
- bool alt = input_event->GetModifiers() & WebInputEvent::kAltKey;
- bool meta = input_event->GetModifiers() & WebInputEvent::kMetaKey;
-
- NavigationPolicy user_policy = *policy;
- NavigationPolicyFromMouseEvent(button_number, ctrl, shift, alt, meta,
- &user_policy);
-
- // When the input event suggests a download, but the navigation was initiated
- // by script, we should not override it.
- if (user_policy == kNavigationPolicyDownload &&
- *policy != kNavigationPolicyIgnore)
- return;
-
- // User and app agree that we want a new window; let the app override the
- // decorations.
- if (user_policy == kNavigationPolicyNewWindow &&
- *policy == kNavigationPolicyNewPopup)
- return;
- *policy = user_policy;
-}
-
-NavigationPolicy GetNavigationPolicy(const WebInputEvent* current_event,
- const WebWindowFeatures& features) {
- // If our default configuration was modified by a script or wasn't
- // created by a user gesture, then show as a popup. Else, let this
- // new window be opened as a toplevel window.
- bool as_popup = !features.tool_bar_visible || !features.status_bar_visible ||
- !features.scrollbars_visible || !features.menu_bar_visible ||
- !features.resizable;
- NavigationPolicy policy =
- as_popup ? kNavigationPolicyNewPopup : kNavigationPolicyNewForegroundTab;
- UpdatePolicyForEvent(current_event, &policy);
- return policy;
-}
-
-} // anonymous namespace
-
-NavigationPolicy EffectiveNavigationPolicy(NavigationPolicy policy,
- const WebInputEvent* current_event,
- const WebWindowFeatures& features) {
- if (policy == kNavigationPolicyIgnore)
- return GetNavigationPolicy(current_event, features);
- if (policy == kNavigationPolicyNewBackgroundTab &&
- GetNavigationPolicy(current_event, features) !=
- kNavigationPolicyNewBackgroundTab &&
- !UIEventWithKeyState::NewTabModifierSetFromIsolatedWorld()) {
- return kNavigationPolicyNewForegroundTab;
- }
- return policy;
-}
-
// Though isspace() considers \t and \v to be whitespace, Win IE doesn't when
// parsing window features.
static bool IsWindowFeaturesSeparator(UChar c) {
@@ -270,10 +177,8 @@ WebWindowFeatures GetWindowFeaturesFromString(const String& feature_string) {
static Frame* ReuseExistingWindow(LocalFrame& active_frame,
LocalFrame& lookup_frame,
const AtomicString& frame_name,
- NavigationPolicy policy,
const KURL& destination_url) {
- if (!frame_name.IsEmpty() && !EqualIgnoringASCIICase(frame_name, "_blank") &&
- policy == kNavigationPolicyIgnore) {
+ if (!frame_name.IsEmpty() && !EqualIgnoringASCIICase(frame_name, "_blank")) {
if (Frame* frame = lookup_frame.FindFrameForNavigation(
frame_name, active_frame, destination_url)) {
if (!EqualIgnoringASCIICase(frame_name, "_self")) {
@@ -293,14 +198,15 @@ static Frame* ReuseExistingWindow(LocalFrame& active_frame,
static Frame* CreateNewWindow(LocalFrame& opener_frame,
const FrameLoadRequest& request,
const WebWindowFeatures& features,
- NavigationPolicy policy,
+ bool force_new_foreground_tab,
bool& created) {
Page* old_page = opener_frame.GetPage();
if (!old_page)
return nullptr;
- policy =
- EffectiveNavigationPolicy(policy, CurrentInputEvent::Get(), features);
+ NavigationPolicy policy = force_new_foreground_tab
+ ? kNavigationPolicyNewForegroundTab
+ : NavigationPolicyForCreateWindow(features);
const SandboxFlags sandbox_flags =
opener_frame.GetDocument()->IsSandboxed(
@@ -315,6 +221,8 @@ static Frame* CreateNewWindow(LocalFrame& opener_frame,
if (page == old_page) {
Frame* frame = &opener_frame.Tree().Top();
+ if (!opener_frame.CanNavigate(*frame))
+ return nullptr;
if (request.GetShouldSetOpener() == kMaybeSetOpener)
frame->Client()->SetOpener(&opener_frame);
return frame;
@@ -357,7 +265,7 @@ static Frame* CreateWindowHelper(LocalFrame& opener_frame,
LocalFrame& lookup_frame,
const FrameLoadRequest& request,
const WebWindowFeatures& features,
- NavigationPolicy policy,
+ bool force_new_foreground_tab,
bool& created) {
DCHECK(request.GetResourceRequest().RequestorOrigin() ||
opener_frame.GetDocument()->Url().IsEmpty());
@@ -369,10 +277,10 @@ static Frame* CreateWindowHelper(LocalFrame& opener_frame,
created = false;
Frame* window =
- features.noopener
+ features.noopener || force_new_foreground_tab
? nullptr
: ReuseExistingWindow(active_frame, lookup_frame, request.FrameName(),
- policy, request.GetResourceRequest().Url());
+ request.GetResourceRequest().Url());
if (!window) {
// Sandboxed frames cannot open new auxiliary browsing contexts.
@@ -390,7 +298,7 @@ static Frame* CreateWindowHelper(LocalFrame& opener_frame,
}
if (window) {
- // JS can run inside reuseExistingWindow (via onblur), which can detach
+ // JS can run inside ReuseExistingWindow (via onblur), which can detach
// the target window.
if (!window->Client())
return nullptr;
@@ -399,7 +307,8 @@ static Frame* CreateWindowHelper(LocalFrame& opener_frame,
return window;
}
- return CreateNewWindow(opener_frame, request, features, policy, created);
+ return CreateNewWindow(opener_frame, request, features,
+ force_new_foreground_tab, created);
}
DOMWindow* CreateWindow(const String& url_string,
@@ -418,8 +327,9 @@ DOMWindow* CreateWindow(const String& url_string,
if (!completed_url.IsEmpty() && !completed_url.IsValid()) {
UseCounter::Count(active_frame, WebFeature::kWindowOpenWithInvalidURL);
exception_state.ThrowDOMException(
- kSyntaxError, "Unable to open a window with invalid URL '" +
- completed_url.GetString() + "'.\n");
+ DOMExceptionCode::kSyntaxError,
+ "Unable to open a window with invalid URL '" +
+ completed_url.GetString() + "'.\n");
return nullptr;
}
@@ -427,9 +337,7 @@ DOMWindow* CreateWindow(const String& url_string,
opener_frame.GetDocument()->GetContentSecurityPolicy() &&
!ContentSecurityPolicy::ShouldBypassMainWorld(
opener_frame.GetDocument())) {
- const int kJavascriptSchemeLength = sizeof("javascript:") - 1;
- String script_source = DecodeURLEscapeSequences(completed_url.GetString())
- .Substring(kJavascriptSchemeLength);
+ String script_source = DecodeURLEscapeSequences(completed_url.GetString());
if (!opener_frame.GetDocument()
->GetContentSecurityPolicy()
@@ -472,7 +380,7 @@ DOMWindow* CreateWindow(const String& url_string,
bool created;
Frame* new_frame = CreateWindowHelper(
opener_frame, *active_frame, opener_frame, frame_request, window_features,
- kNavigationPolicyIgnore, created);
+ false /* force_new_foreground_tab */, created);
if (!new_frame)
return nullptr;
if (new_frame->DomWindow()->IsInsecureScriptAccess(calling_window,
@@ -494,16 +402,16 @@ DOMWindow* CreateWindow(const String& url_string,
request.GetResourceRequest().SetHasUserGesture(has_user_gesture);
new_frame->Navigate(request);
} else if (!url_string.IsEmpty()) {
- new_frame->Navigate(*calling_window.document(), completed_url, false,
- has_user_gesture ? UserGestureStatus::kActive
- : UserGestureStatus::kNone);
+ new_frame->ScheduleNavigation(*calling_window.document(), completed_url,
+ false,
+ has_user_gesture ? UserGestureStatus::kActive
+ : UserGestureStatus::kNone);
}
return window_features.noopener ? nullptr : new_frame->DomWindow();
}
void CreateWindowForRequest(const FrameLoadRequest& request,
- LocalFrame& opener_frame,
- NavigationPolicy policy) {
+ LocalFrame& opener_frame) {
DCHECK(request.GetResourceRequest().RequestorOrigin() ||
(opener_frame.GetDocument() &&
opener_frame.GetDocument()->Url().IsEmpty()));
@@ -516,15 +424,12 @@ void CreateWindowForRequest(const FrameLoadRequest& request,
opener_frame.GetDocument()->IsSandboxed(kSandboxPopups))
return;
- if (policy == kNavigationPolicyCurrentTab)
- policy = kNavigationPolicyNewForegroundTab;
-
WebWindowFeatures features;
features.noopener = request.GetShouldSetOpener() == kNeverSetOpener;
bool created;
- Frame* new_frame =
- CreateWindowHelper(opener_frame, opener_frame, opener_frame, request,
- features, policy, created);
+ Frame* new_frame = CreateWindowHelper(
+ opener_frame, opener_frame, opener_frame, request, features,
+ true /* force_new_foreground_tab */, created);
if (!new_frame)
return;
if (request.GetShouldSendReferrer() == kMaybeSendReferrer) {
@@ -537,6 +442,9 @@ void CreateWindowForRequest(const FrameLoadRequest& request,
// TODO(japhet): Form submissions on RemoteFrames don't work yet.
FrameLoadRequest new_request(nullptr, request.GetResourceRequest());
new_request.SetForm(request.Form());
+ auto blob_url_token = request.GetBlobURLToken();
+ if (blob_url_token)
+ new_request.SetBlobURLToken(std::move(blob_url_token));
if (new_frame->IsLocalFrame())
ToLocalFrame(new_frame)->Loader().StartNavigation(new_request);
}
diff --git a/chromium/third_party/blink/renderer/core/page/create_window.h b/chromium/third_party/blink/renderer/core/page/create_window.h
index 36e8bb8806b..2d5afe1dc86 100644
--- a/chromium/third_party/blink/renderer/core/page/create_window.h
+++ b/chromium/third_party/blink/renderer/core/page/create_window.h
@@ -49,15 +49,7 @@ DOMWindow* CreateWindow(const String& url_string,
LocalFrame& opener_frame,
ExceptionState&);
-void CreateWindowForRequest(const FrameLoadRequest&,
- LocalFrame& opener_frame,
- NavigationPolicy);
-
-// Exposed for testing
-CORE_EXPORT NavigationPolicy
-EffectiveNavigationPolicy(NavigationPolicy,
- const WebInputEvent* current_event,
- const WebWindowFeatures&);
+void CreateWindowForRequest(const FrameLoadRequest&, LocalFrame& opener_frame);
// Exposed for testing
CORE_EXPORT WebWindowFeatures GetWindowFeaturesFromString(const String&);
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 0e5a2d63bc3..31d56851f54 100644
--- a/chromium/third_party/blink/renderer/core/page/drag_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/drag_controller.cc
@@ -36,7 +36,6 @@
#include "third_party/blink/public/platform/web_image.h"
#include "third_party/blink/public/platform/web_point.h"
#include "third_party/blink/public/platform/web_screen_info.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/clipboard/data_object.h"
#include "third_party/blink/renderer/core/clipboard/data_transfer.h"
#include "third_party/blink/renderer/core/clipboard/data_transfer_access_policy.h"
@@ -79,6 +78,7 @@
#include "third_party/blink/renderer/core/page/drag_state.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/drag_image.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
@@ -258,12 +258,13 @@ void DragController::PerformDrag(DragData* drag_data, LocalFrame& local_root) {
prevented_default = event_handler.PerformDragAndDrop(
CreateMouseEvent(drag_data), data_transfer) !=
WebInputEventResult::kNotHandled;
- if (!prevented_default) {
+ if (!prevented_default && document_under_mouse_) {
// When drop target is plugin element and it can process drag, we
// should prevent default behavior.
- const LayoutPoint point = local_root.View()->RootFrameToContents(
- LayoutPoint(drag_data->ClientPosition()));
- const HitTestResult result = event_handler.HitTestResultAtPoint(point);
+ const HitTestLocation location(local_root.View()->ConvertFromRootFrame(
+ LayoutPoint(drag_data->ClientPosition())));
+ const HitTestResult result =
+ event_handler.HitTestResultAtLocation(location);
prevented_default |=
IsHTMLPlugInElement(*result.InnerNode()) &&
ToHTMLPlugInElement(result.InnerNode())->CanProcessDrag();
@@ -355,8 +356,9 @@ static HTMLInputElement* AsFileInput(Node* node) {
static Element* ElementUnderMouse(Document* document_under_mouse,
const LayoutPoint& point) {
HitTestRequest request(HitTestRequest::kReadOnly | HitTestRequest::kActive);
- HitTestResult result(request, point);
- document_under_mouse->GetLayoutView()->HitTest(result);
+ HitTestLocation location(point);
+ HitTestResult result(request, location);
+ document_under_mouse->GetLayoutView()->HitTest(location, result);
Node* n = result.InnerNode();
while (n && !n->IsElementNode())
@@ -405,7 +407,7 @@ bool DragController::TryDocumentDrag(DragData* drag_data,
if ((action_mask & kDragDestinationActionEdit) &&
CanProcessDrag(drag_data, local_root)) {
- LayoutPoint point = frame_view->RootFrameToContents(
+ LayoutPoint point = frame_view->ConvertFromRootFrame(
LayoutPoint(drag_data->ClientPosition()));
Element* element = ElementUnderMouse(document_under_mouse_.Get(), point);
if (!element)
@@ -530,7 +532,7 @@ bool DragController::ConcludeEditDrag(DragData* drag_data) {
if (!document_under_mouse_)
return false;
- LayoutPoint point = document_under_mouse_->View()->RootFrameToContents(
+ LayoutPoint point = document_under_mouse_->View()->ConvertFromRootFrame(
LayoutPoint(drag_data->ClientPosition()));
Element* element = ElementUnderMouse(document_under_mouse_.Get(), point);
if (!element)
@@ -695,11 +697,12 @@ bool DragController::CanProcessDrag(DragData* drag_data,
if (!local_root.ContentLayoutObject())
return false;
- LayoutPoint point = local_root.View()->RootFrameToContents(
+ LayoutPoint point = local_root.View()->ConvertFromRootFrame(
LayoutPoint(drag_data->ClientPosition()));
+ HitTestLocation location(point);
HitTestResult result =
- local_root.GetEventHandler().HitTestResultAtPoint(point);
+ local_root.GetEventHandler().HitTestResultAtLocation(location);
if (!result.InnerNode())
return false;
@@ -716,7 +719,7 @@ bool DragController::CanProcessDrag(DragData* drag_data,
}
if (did_initiate_drag_ && document_under_mouse_ == drag_initiator_ &&
- result.IsSelected())
+ result.IsSelected(location))
return false;
return true;
@@ -921,8 +924,9 @@ bool DragController::PopulateDragDataTransfer(LocalFrame* src,
if (!src->View() || !src->ContentLayoutObject())
return false;
+ HitTestLocation location(drag_origin);
HitTestResult hit_test_result =
- src->GetEventHandler().HitTestResultAtPoint(drag_origin);
+ src->GetEventHandler().HitTestResultAtLocation(location);
// FIXME: Can this even happen? I guess it's possible, but should verify
// with a layout test.
if (!state.drag_src_->IsShadowIncludingInclusiveAncestorOf(
@@ -1138,14 +1142,8 @@ std::unique_ptr<DragImage> DragController::DragImageForSelection(
frame.View()->PaintContents(builder.Context(), paint_flags,
EnclosingIntRect(painting_rect));
- PropertyTreeState property_tree_state = PropertyTreeState::Root();
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- property_tree_state = frame.View()
- ->GetLayoutView()
- ->FirstFragment()
- .LocalBorderBoxProperties();
- }
-
+ PropertyTreeState property_tree_state =
+ frame.View()->GetLayoutView()->FirstFragment().LocalBorderBoxProperties();
return DataTransfer::CreateDragImageForFrame(
frame, opacity, kDoNotRespectImageOrientation, painting_rect.Size(),
painting_rect.Location(), builder, property_tree_state);
@@ -1162,8 +1160,9 @@ bool DragController::StartDrag(LocalFrame* src,
if (!src->View() || !src->ContentLayoutObject())
return false;
+ HitTestLocation location(drag_origin);
HitTestResult hit_test_result =
- src->GetEventHandler().HitTestResultAtPoint(drag_origin);
+ src->GetEventHandler().HitTestResultAtLocation(location);
if (!state.drag_src_->IsShadowIncludingInclusiveAncestorOf(
hit_test_result.InnerNode())) {
// The original node being dragged isn't under the drag origin anymore...
@@ -1177,7 +1176,7 @@ bool DragController::StartDrag(LocalFrame* src,
// TODO(pdr): This code shouldn't be necessary because drag_origin is already
// in the coordinate space of the view's contents.
- IntPoint mouse_dragged_point = src->View()->RootFrameToContents(
+ IntPoint mouse_dragged_point = src->View()->ConvertFromRootFrame(
FlooredIntPoint(drag_event.PositionInRootFrame()));
IntPoint drag_location;
@@ -1293,14 +1292,14 @@ void DragController::DoSystemDrag(DragImage* image,
// FloatPoints and we should calculate these adjusted values in floating
// point to avoid unnecessary rounding.
IntPoint adjusted_drag_location =
- frame->View()->ContentsToViewport(drag_location);
- IntPoint adjusted_event_pos = frame->View()->ContentsToViewport(event_pos);
+ frame->View()->FrameToViewport(drag_location);
+ IntPoint adjusted_event_pos = frame->View()->FrameToViewport(event_pos);
IntSize offset_size(adjusted_event_pos - adjusted_drag_location);
WebPoint offset_point(offset_size.Width(), offset_size.Height());
WebDragData drag_data = data_transfer->GetDataObject()->ToWebDragData();
WebDragOperationsMask drag_operation_mask =
static_cast<WebDragOperationsMask>(data_transfer->SourceOperation());
- WebImage drag_image;
+ SkBitmap drag_image;
if (image) {
float resolution_scale = image->ResolutionScale();
@@ -1315,7 +1314,7 @@ void DragController::DoSystemDrag(DragImage* image,
}
page_->GetChromeClient().StartDragging(frame, drag_data, drag_operation_mask,
- drag_image, offset_point);
+ std::move(drag_image), offset_point);
}
DragOperation DragController::GetDragOperation(DragData* drag_data) {
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 524abc8bb65..bdea264d4b1 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
@@ -12,9 +12,11 @@
#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/visual_viewport.h"
+#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/page/autoscroll_controller.h"
#include "third_party/blink/renderer/core/page/drag_data.h"
#include "third_party/blink/renderer/core/page/drag_state.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/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
@@ -29,9 +31,9 @@ class DragMockChromeClient : public EmptyChromeClient {
void StartDragging(LocalFrame*,
const WebDragData&,
WebDragOperationsMask,
- const WebImage& drag_image,
+ const SkBitmap& drag_image,
const WebPoint& drag_image_offset) override {
- last_drag_image_size = drag_image.Size();
+ last_drag_image_size = WebSize(drag_image.width(), drag_image.height());
last_drag_image_offset = drag_image_offset;
}
@@ -101,7 +103,7 @@ TEST_F(DragControllerSimTest, DropURLOnNonNavigatingClearsState) {
DataObject* object = DataObject::Create();
object->SetURLAndTitle("https://www.example.com/index.html", "index");
DragData data(
- object, IntPoint(10, 10), IntPoint(10, 10),
+ object, FloatPoint(10, 10), FloatPoint(10, 10),
static_cast<DragOperation>(kDragOperationCopy | kDragOperationLink |
kDragOperationMove));
@@ -121,6 +123,45 @@ TEST_F(DragControllerSimTest, DropURLOnNonNavigatingClearsState) {
WebView().GetPage()->GetAutoscrollController().AutoscrollInProgress());
}
+// Verify that conditions that prevent hit testing - such as throttled
+// lifecycle updates for frames - are accounted for in the DragController.
+// Regression test for https://crbug.com/685030
+TEST_F(DragControllerSimTest, ThrottledDocumentHandled) {
+ WebView().GetPage()->GetSettings().SetNavigateOnDragDrop(false);
+ WebView().Resize(WebSize(800, 600));
+ SimRequest main_resource("https://example.com/test.html", "text/html");
+
+ LoadURL("https://example.com/test.html");
+
+ // Intercept event to indicate that the document will be handling the drag.
+ main_resource.Complete(
+ "<!DOCTYPE html>"
+ "<script>"
+ " document.addEventListener('dragenter', e => e.preventDefault());"
+ "</script>");
+
+ DataObject* object = DataObject::Create();
+ object->SetURLAndTitle("https://www.example.com/index.html", "index");
+ DragData data(
+ object, FloatPoint(10, 10), FloatPoint(10, 10),
+ static_cast<DragOperation>(kDragOperationCopy | kDragOperationLink |
+ kDragOperationMove));
+
+ WebView().GetPage()->GetDragController().DragEnteredOrUpdated(
+ &data, *GetDocument().GetFrame());
+
+ // Throttle updates, which prevents hit testing from yielding a node.
+ WebView()
+ .MainFrameImpl()
+ ->GetFrameView()
+ ->SetLifecycleUpdatesThrottledForTesting();
+
+ WebView().GetPage()->GetDragController().PerformDrag(
+ &data, *GetDocument().GetFrame());
+
+ // Test passes if we don't crash.
+}
+
TEST_F(DragControllerTest, DragImageForSelectionClipsToViewport) {
SetBodyInnerHTML(R"HTML(
<style>
@@ -166,8 +207,8 @@ TEST_F(DragControllerTest, DragImageForSelectionClipsToViewport) {
// the entire viewport.
int scroll_offset = 500;
LocalFrameView* frame_view = GetDocument().View();
- frame_view->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, scroll_offset), kProgrammaticScroll);
+ frame_view->LayoutViewport()->SetScrollOffset(ScrollOffset(0, scroll_offset),
+ kProgrammaticScroll);
expected_selection = FloatRect(0, 0, node_width, viewport_height_css);
EXPECT_EQ(expected_selection, DragController::ClippedSelection(GetFrame()));
selection_image = DragController::DragImageForSelection(GetFrame(), 1);
@@ -178,8 +219,8 @@ TEST_F(DragControllerTest, DragImageForSelectionClipsToViewport) {
// Scroll 800 css px down so the top of the node is outside the viewport and
// the bottom of the node is now visible.
scroll_offset = 800;
- frame_view->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, scroll_offset), kProgrammaticScroll);
+ frame_view->LayoutViewport()->SetScrollOffset(ScrollOffset(0, scroll_offset),
+ kProgrammaticScroll);
expected_selection = FloatRect(0, 0, node_width,
node_height + node_margin_top - scroll_offset);
EXPECT_EQ(expected_selection, DragController::ClippedSelection(GetFrame()));
@@ -234,8 +275,8 @@ TEST_F(DragControllerTest, DragImageForSelectionClipsChildFrameToViewport) {
// not include scroll offset.
int scroll_offset = 50;
LocalFrameView* frame_view = GetDocument().View();
- frame_view->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, scroll_offset), kProgrammaticScroll);
+ frame_view->LayoutViewport()->SetScrollOffset(ScrollOffset(0, scroll_offset),
+ kProgrammaticScroll);
expected_selection = FloatRect(0, 5, 30, 20);
EXPECT_EQ(expected_selection, DragController::ClippedSelection(child_frame));
selection_image = DragController::DragImageForSelection(child_frame, 1);
@@ -246,8 +287,8 @@ TEST_F(DragControllerTest, DragImageForSelectionClipsChildFrameToViewport) {
// be shifted which should cause the iframe's selection rect to be clipped by
// the visual viewport.
scroll_offset = 210;
- frame_view->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, scroll_offset), kProgrammaticScroll);
+ frame_view->LayoutViewport()->SetScrollOffset(ScrollOffset(0, scroll_offset),
+ kProgrammaticScroll);
expected_selection = FloatRect(0, 10, 30, 15);
EXPECT_EQ(expected_selection, DragController::ClippedSelection(child_frame));
selection_image = DragController::DragImageForSelection(child_frame, 1);
@@ -257,7 +298,7 @@ TEST_F(DragControllerTest, DragImageForSelectionClipsChildFrameToViewport) {
// Scrolling the iframe should shift the content so it is further under the
// visual viewport clip.
int iframe_scroll_offset = 7;
- child_frame.View()->LayoutViewportScrollableArea()->SetScrollOffset(
+ child_frame.View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0, iframe_scroll_offset), kProgrammaticScroll);
expected_selection = FloatRect(0, 10, 30, 8);
EXPECT_EQ(expected_selection, DragController::ClippedSelection(child_frame));
@@ -315,8 +356,8 @@ TEST_F(DragControllerTest,
// not include the parent frame's scroll offset.
int scroll_offset = 50;
LocalFrameView* frame_view = GetDocument().View();
- frame_view->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, scroll_offset), kProgrammaticScroll);
+ frame_view->LayoutViewport()->SetScrollOffset(ScrollOffset(0, scroll_offset),
+ kProgrammaticScroll);
expected_selection = FloatRect(0, 5, 30, 20);
EXPECT_EQ(expected_selection, DragController::ClippedSelection(child_frame));
selection_image = DragController::DragImageForSelection(child_frame, 1);
@@ -328,8 +369,8 @@ TEST_F(DragControllerTest,
// be shifted which should cause the iframe's selection rect to be clipped by
// the visual viewport.
scroll_offset = 210;
- frame_view->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, scroll_offset), kProgrammaticScroll);
+ frame_view->LayoutViewport()->SetScrollOffset(ScrollOffset(0, scroll_offset),
+ kProgrammaticScroll);
expected_selection = FloatRect(0, 10, 30, 15);
EXPECT_EQ(expected_selection, DragController::ClippedSelection(child_frame));
selection_image = DragController::DragImageForSelection(child_frame, 1);
@@ -340,7 +381,7 @@ TEST_F(DragControllerTest,
// Scrolling the iframe should shift the content so it is further under the
// visual viewport clip.
int iframe_scroll_offset = 7;
- child_frame.View()->LayoutViewportScrollableArea()->SetScrollOffset(
+ child_frame.View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0, iframe_scroll_offset), kProgrammaticScroll);
expected_selection = FloatRect(0, 10, 30, 8);
EXPECT_EQ(expected_selection, DragController::ClippedSelection(child_frame));
diff --git a/chromium/third_party/blink/renderer/core/page/drag_data.cc b/chromium/third_party/blink/renderer/core/page/drag_data.cc
index 24f1449bc50..70ba50a5613 100644
--- a/chromium/third_party/blink/renderer/core/page/drag_data.cc
+++ b/chromium/third_party/blink/renderer/core/page/drag_data.cc
@@ -26,12 +26,12 @@
#include "third_party/blink/renderer/core/page/drag_data.h"
+#include "third_party/blink/renderer/core/clipboard/clipboard_mime_types.h"
#include "third_party/blink/renderer/core/clipboard/data_object.h"
#include "third_party/blink/renderer/core/dom/document_fragment.h"
#include "third_party/blink/renderer/core/dom/range.h"
#include "third_party/blink/renderer/core/editing/serializers/serialization.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/platform/clipboard/clipboard_mime_types.h"
#include "third_party/blink/renderer/platform/file_metadata.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/core/page/effective_navigation_policy_test.cc b/chromium/third_party/blink/renderer/core/page/effective_navigation_policy_test.cc
deleted file mode 100644
index 33e76a44c14..00000000000
--- a/chromium/third_party/blink/renderer/core/page/effective_navigation_policy_test.cc
+++ /dev/null
@@ -1,199 +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 "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/web_input_event.h"
-#include "third_party/blink/public/platform/web_mouse_event.h"
-#include "third_party/blink/public/web/web_window_features.h"
-#include "third_party/blink/renderer/core/page/create_window.h"
-
-namespace blink {
-
-class EffectiveNavigationPolicyTest : public testing::Test {
- protected:
- NavigationPolicy GetNavigationPolicyWithMouseEvent(
- int modifiers,
- WebMouseEvent::Button button,
- bool as_popup) {
- WebMouseEvent event(WebInputEvent::kMouseUp, modifiers,
- WebInputEvent::GetStaticTimeStampForTests());
- event.button = button;
- if (as_popup)
- features.tool_bar_visible = false;
- return EffectiveNavigationPolicy(kNavigationPolicyIgnore, &event, features);
- }
-
- WebWindowFeatures features;
-};
-
-TEST_F(EffectiveNavigationPolicyTest, LeftClick) {
- int modifiers = 0;
- WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
- bool as_popup = false;
- EXPECT_EQ(kNavigationPolicyNewForegroundTab,
- GetNavigationPolicyWithMouseEvent(modifiers, button, as_popup));
-}
-
-TEST_F(EffectiveNavigationPolicyTest, LeftClickPopup) {
- int modifiers = 0;
- WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
- bool as_popup = true;
- EXPECT_EQ(kNavigationPolicyNewPopup,
- GetNavigationPolicyWithMouseEvent(modifiers, button, as_popup));
-}
-
-TEST_F(EffectiveNavigationPolicyTest, ShiftLeftClick) {
- int modifiers = WebInputEvent::kShiftKey;
- WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
- bool as_popup = false;
- EXPECT_EQ(kNavigationPolicyNewWindow,
- GetNavigationPolicyWithMouseEvent(modifiers, button, as_popup));
-}
-
-TEST_F(EffectiveNavigationPolicyTest, ShiftLeftClickPopup) {
- int modifiers = WebInputEvent::kShiftKey;
- WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
- bool as_popup = true;
- EXPECT_EQ(kNavigationPolicyNewPopup,
- GetNavigationPolicyWithMouseEvent(modifiers, button, as_popup));
-}
-
-TEST_F(EffectiveNavigationPolicyTest, ControlOrMetaLeftClick) {
-#if defined(OS_MACOSX)
- int modifiers = WebInputEvent::kMetaKey;
-#else
- int modifiers = WebInputEvent::kControlKey;
-#endif
- WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
- bool as_popup = false;
- EXPECT_EQ(kNavigationPolicyNewBackgroundTab,
- GetNavigationPolicyWithMouseEvent(modifiers, button, as_popup));
-}
-
-TEST_F(EffectiveNavigationPolicyTest, ControlOrMetaLeftClickPopup) {
-#if defined(OS_MACOSX)
- int modifiers = WebInputEvent::kMetaKey;
-#else
- int modifiers = WebInputEvent::kControlKey;
-#endif
- WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
- bool as_popup = true;
- EXPECT_EQ(kNavigationPolicyNewBackgroundTab,
- GetNavigationPolicyWithMouseEvent(modifiers, button, as_popup));
-}
-
-TEST_F(EffectiveNavigationPolicyTest, ControlOrMetaAndShiftLeftClick) {
-#if defined(OS_MACOSX)
- int modifiers = WebInputEvent::kMetaKey;
-#else
- int modifiers = WebInputEvent::kControlKey;
-#endif
- modifiers |= WebInputEvent::kShiftKey;
- WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
- bool as_popup = false;
- EXPECT_EQ(kNavigationPolicyNewForegroundTab,
- GetNavigationPolicyWithMouseEvent(modifiers, button, as_popup));
-}
-
-TEST_F(EffectiveNavigationPolicyTest, ControlOrMetaAndShiftLeftClickPopup) {
-#if defined(OS_MACOSX)
- int modifiers = WebInputEvent::kMetaKey;
-#else
- int modifiers = WebInputEvent::kControlKey;
-#endif
- modifiers |= WebInputEvent::kShiftKey;
- WebMouseEvent::Button button = WebMouseEvent::Button::kLeft;
- bool as_popup = true;
- EXPECT_EQ(kNavigationPolicyNewForegroundTab,
- GetNavigationPolicyWithMouseEvent(modifiers, button, as_popup));
-}
-
-TEST_F(EffectiveNavigationPolicyTest, MiddleClick) {
- int modifiers = 0;
- bool as_popup = false;
- WebMouseEvent::Button button = WebMouseEvent::Button::kMiddle;
- EXPECT_EQ(kNavigationPolicyNewBackgroundTab,
- GetNavigationPolicyWithMouseEvent(modifiers, button, as_popup));
-}
-
-TEST_F(EffectiveNavigationPolicyTest, MiddleClickPopup) {
- int modifiers = 0;
- bool as_popup = true;
- WebMouseEvent::Button button = WebMouseEvent::Button::kMiddle;
- EXPECT_EQ(kNavigationPolicyNewBackgroundTab,
- GetNavigationPolicyWithMouseEvent(modifiers, button, as_popup));
-}
-
-TEST_F(EffectiveNavigationPolicyTest, NoToolbarsForcesPopup) {
- features.tool_bar_visible = false;
- EXPECT_EQ(
- kNavigationPolicyNewPopup,
- EffectiveNavigationPolicy(kNavigationPolicyIgnore, nullptr, features));
- features.tool_bar_visible = true;
- EXPECT_EQ(
- kNavigationPolicyNewForegroundTab,
- EffectiveNavigationPolicy(kNavigationPolicyIgnore, nullptr, features));
-}
-
-TEST_F(EffectiveNavigationPolicyTest, NoStatusBarForcesPopup) {
- features.status_bar_visible = false;
- EXPECT_EQ(
- kNavigationPolicyNewPopup,
- EffectiveNavigationPolicy(kNavigationPolicyIgnore, nullptr, features));
- features.status_bar_visible = true;
- EXPECT_EQ(
- kNavigationPolicyNewForegroundTab,
- EffectiveNavigationPolicy(kNavigationPolicyIgnore, nullptr, features));
-}
-
-TEST_F(EffectiveNavigationPolicyTest, NoMenuBarForcesPopup) {
- features.menu_bar_visible = false;
- EXPECT_EQ(
- kNavigationPolicyNewPopup,
- EffectiveNavigationPolicy(kNavigationPolicyIgnore, nullptr, features));
- features.menu_bar_visible = true;
- EXPECT_EQ(
- kNavigationPolicyNewForegroundTab,
- EffectiveNavigationPolicy(kNavigationPolicyIgnore, nullptr, features));
-}
-
-TEST_F(EffectiveNavigationPolicyTest, NotResizableForcesPopup) {
- features.resizable = false;
- EXPECT_EQ(
- kNavigationPolicyNewPopup,
- EffectiveNavigationPolicy(kNavigationPolicyIgnore, nullptr, features));
- features.resizable = true;
- EXPECT_EQ(
- kNavigationPolicyNewForegroundTab,
- EffectiveNavigationPolicy(kNavigationPolicyIgnore, nullptr, features));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/event_with_hit_test_results.h b/chromium/third_party/blink/renderer/core/page/event_with_hit_test_results.h
index 153bc8a4e14..e31396af8eb 100644
--- a/chromium/third_party/blink/renderer/core/page/event_with_hit_test_results.h
+++ b/chromium/third_party/blink/renderer/core/page/event_with_hit_test_results.h
@@ -35,8 +35,11 @@ class EventWithHitTestResults {
public:
EventWithHitTestResults(const EventType& event,
+ const HitTestLocation& location,
const HitTestResult& hit_test_result)
- : event_(event), hit_test_result_(hit_test_result) {}
+ : event_(event),
+ hit_test_result_(hit_test_result),
+ hit_test_location_(location) {}
const EventType& Event() const { return event_; }
const HitTestResult& GetHitTestResult() const { return hit_test_result_; }
@@ -52,9 +55,17 @@ class EventWithHitTestResults {
return hit_test_result_.CanvasRegionId();
}
+ const HitTestLocation& GetHitTestLocation() const {
+ return hit_test_location_;
+ }
+ void SetHitTestLocation(const HitTestLocation& new_location) {
+ hit_test_location_ = new_location;
+ }
+
private:
EventType event_;
HitTestResult hit_test_result_;
+ HitTestLocation hit_test_location_;
};
using MouseEventWithHitTestResults = EventWithHitTestResults<WebMouseEvent>;
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 da3d74c2190..e2e6d4af5fa 100644
--- a/chromium/third_party/blink/renderer/core/page/focus_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/focus_controller.cc
@@ -26,7 +26,7 @@
#include "third_party/blink/renderer/core/page/focus_controller.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/container_node.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
@@ -1292,15 +1292,15 @@ static void UpdateFocusCandidateIfNeeded(WebFocusType direction,
->MainFrame()
->IsLocalFrame())
return;
+ HitTestLocation location(IntPoint(x.ToInt(), y.ToInt()));
HitTestResult result =
candidate.visible_node->GetDocument()
.GetPage()
->DeprecatedLocalMainFrame()
->GetEventHandler()
- .HitTestResultAtPoint(IntPoint(x.ToInt(), y.ToInt()),
- HitTestRequest::kReadOnly |
- HitTestRequest::kActive |
- HitTestRequest::kIgnoreClipping);
+ .HitTestResultAtLocation(
+ location, HitTestRequest::kReadOnly | HitTestRequest::kActive |
+ HitTestRequest::kIgnoreClipping);
if (candidate.visible_node->contains(result.InnerNode())) {
closest = candidate;
return;
diff --git a/chromium/third_party/blink/renderer/core/page/page.cc b/chromium/third_party/blink/renderer/core/page/page.cc
index a6a36fb4b38..0f42c3e762d 100644
--- a/chromium/third_party/blink/renderer/core/page/page.cc
+++ b/chromium/third_party/blink/renderer/core/page/page.cc
@@ -21,7 +21,9 @@
#include "third_party/blink/renderer/core/page/page.h"
+#include "cc/layers/picture_layer.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_layer_tree_view.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
@@ -36,6 +38,7 @@
#include "third_party/blink/renderer/core/frame/dom_timer.h"
#include "third_party/blink/renderer/core/frame/event_handler_registry.h"
#include "third_party/blink/renderer/core/frame/frame_console.h"
+#include "third_party/blink/renderer/core/frame/link_highlights.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/page_scale_constraints.h"
@@ -43,6 +46,7 @@
#include "third_party/blink/renderer/core/frame/remote_frame.h"
#include "third_party/blink/renderer/core/frame/remote_frame_view.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"
#include "third_party/blink/renderer/core/geometry/dom_rect_list.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
@@ -62,7 +66,9 @@
#include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h"
#include "third_party/blink/renderer/core/page/validation_message_client.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/probe/core_probes.h"
+#include "third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/plugins/plugin_data.h"
@@ -75,8 +81,9 @@ namespace blink {
// Wrapper function defined in WebKit.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.
DCHECK(!reload_pages);
- Page::RefreshPlugins();
Page::ResetPluginData();
}
@@ -92,6 +99,10 @@ Page::PageSet& Page::OrdinaryPages() {
return pages;
}
+void Page::InsertOrdinaryPageForTesting(Page* page) {
+ OrdinaryPages().insert(page);
+}
+
HeapVector<Member<Page>> Page::RelatedPages() {
HeapVector<Member<Page>> result;
Page* ptr = this->next_related_page_;
@@ -135,6 +146,7 @@ Page* Page::CreateOrdinary(PageClients& page_clients, Page* opener) {
Page::Page(PageClients& page_clients)
: SettingsDelegate(Settings::Create()),
+ main_frame_(nullptr),
animator_(PageAnimator::Create(*this)),
autoscroll_controller_(AutoscrollController::Create(*this)),
chrome_client_(page_clients.chrome_client),
@@ -151,18 +163,14 @@ Page::Page(PageClients& page_clients)
visual_viewport_(VisualViewport::Create(*this)),
overscroll_controller_(
OverscrollController::Create(GetVisualViewport(), GetChromeClient())),
- main_frame_(nullptr),
+ link_highlights_(LinkHighlights::Create(*this)),
plugin_data_(nullptr),
- use_counter_(page_clients.chrome_client &&
- page_clients.chrome_client->IsSVGImageChromeClient()
- ? UseCounter::kSVGImageContext
- : UseCounter::kDefaultContext),
opened_by_dom_(false),
tab_key_cycles_through_elements_(true),
paused_(false),
device_scale_factor_(1),
visibility_state_(mojom::PageVisibilityState::kVisible),
- page_lifecycle_state_(PageLifecycleState::kUnknown),
+ page_lifecycle_state_(kDefaultPageLifecycleState),
is_cursor_visible_(true),
subframe_count_(0),
next_related_page_(this),
@@ -193,7 +201,8 @@ ViewportDescription Page::GetViewportDescription() const {
DeprecatedLocalMainFrame()->GetDocument()
? DeprecatedLocalMainFrame()
->GetDocument()
- ->GetViewportDescription()
+ ->GetViewportData()
+ .GetViewportDescription()
: ViewportDescription();
}
@@ -255,14 +264,17 @@ const OverscrollController& Page::GetOverscrollController() const {
return *overscroll_controller_;
}
-DOMRectList* Page::NonFastScrollableRects(const LocalFrame* frame) {
+LinkHighlights& Page::GetLinkHighlights() {
+ return *link_highlights_;
+}
+
+DOMRectList* Page::NonFastScrollableRectsForTesting(const LocalFrame* frame) {
// Update lifecycle to kPrePaintClean. This includes the compositing update
- // and ScrollingCoordinator::UpdateAfterCompositingChangeIfNeeded, which
- // computes the non-fast scrollable region.
- frame->View()->UpdateAllLifecyclePhasesExceptPaint();
+ // and ScrollingCoordinator::UpdateAfterPaint, which computes the non-fast
+ // scrollable region.
+ frame->View()->UpdateAllLifecyclePhases();
- GraphicsLayer* layer =
- frame->View()->LayoutViewportScrollableArea()->LayerForScrolling();
+ GraphicsLayer* layer = frame->View()->LayoutViewport()->LayerForScrolling();
if (!layer)
return DOMRectList::Create();
const cc::Region& region = layer->CcLayer()->non_fast_scrollable_region();
@@ -318,10 +330,6 @@ void Page::InitialStyleChanged() {
}
}
-void Page::RefreshPlugins() {
- PluginData::RefreshBrowserSidePluginCache();
-}
-
PluginData* Page::GetPluginData(const SecurityOrigin* main_frame_origin) {
if (!plugin_data_)
plugin_data_ = PluginData::Create();
@@ -342,6 +350,14 @@ void Page::ResetPluginData() {
}
}
+static void RestoreSVGImageAnimations() {
+ for (const Page* page : AllPages()) {
+ if (auto* svg_image_chrome_client =
+ ToSVGImageChromeClientOrNull(page->GetChromeClient()))
+ svg_image_chrome_client->RestoreAnimationIfNeeded();
+ }
+}
+
void Page::SetValidationMessageClient(ValidationMessageClient* client) {
validation_message_client_ = client;
}
@@ -453,11 +469,15 @@ void Page::SetVisibilityState(mojom::PageVisibilityState visibility_state,
return;
visibility_state_ = visibility_state;
- if (!is_initial_state)
- NotifyPageVisibilityChanged();
+ if (is_initial_state)
+ return;
+ NotifyPageVisibilityChanged();
- if (!is_initial_state && main_frame_)
+ if (main_frame_) {
+ if (IsPageVisible())
+ RestoreSVGImageAnimations();
main_frame_->DidChangeVisibilityState();
+ }
}
mojom::PageVisibilityState Page::VisibilityState() const {
@@ -471,6 +491,7 @@ bool Page::IsPageVisible() const {
void Page::SetLifecycleState(PageLifecycleState state) {
if (state == page_lifecycle_state_)
return;
+ DCHECK_NE(state, PageLifecycleState::kUnknown);
if (RuntimeEnabledFeatures::PageLifecycleEnabled()) {
if (state == PageLifecycleState::kFrozen) {
@@ -478,11 +499,12 @@ void Page::SetLifecycleState(PageLifecycleState state) {
frame = frame->Tree().TraverseNext()) {
frame->DidFreeze();
}
- } else if (state == PageLifecycleState::kActive ||
- state == PageLifecycleState::kHidden) {
+ } else if (page_lifecycle_state_ == PageLifecycleState::kFrozen) {
// TODO(fmeawad): Only resume the page that just became visible, blocked
// on task queues per frame.
- DCHECK(page_lifecycle_state_ == PageLifecycleState::kFrozen);
+ DCHECK(state == PageLifecycleState::kActive ||
+ state == PageLifecycleState::kHiddenBackgrounded ||
+ state == PageLifecycleState::kHiddenForegrounded);
for (Frame* frame = main_frame_.Get(); frame;
frame = frame->Tree().TraverseNext()) {
frame->DidResume();
@@ -526,7 +548,10 @@ void Page::SettingsChanged(SettingsDelegate::ChangeType change_type) {
break;
case SettingsDelegate::kViewportDescriptionChange:
if (MainFrame() && MainFrame()->IsLocalFrame()) {
- DeprecatedLocalMainFrame()->GetDocument()->UpdateViewportDescription();
+ DeprecatedLocalMainFrame()
+ ->GetDocument()
+ ->GetViewportData()
+ .UpdateViewportDescription();
// The text autosizer has dependencies on the viewport.
if (TextAutosizer* text_autosizer =
DeprecatedLocalMainFrame()->GetDocument()->GetTextAutosizer())
@@ -615,9 +640,9 @@ void Page::SettingsChanged(SettingsDelegate::ChangeType change_type) {
if (!frame->IsLocalFrame())
continue;
LocalFrame* local_frame = ToLocalFrame(frame);
- if (local_frame->Loader()
- .StateMachine()
- ->CommittedFirstRealDocumentLoad()) {
+ if (!local_frame->Loader()
+ .StateMachine()
+ ->CreatingInitialEmptyDocument()) {
// Forcibly instantiate WindowProxy.
local_frame->GetScriptController().WindowProxy(
DOMWrapperWorld::MainWorld());
@@ -662,9 +687,8 @@ void Page::UpdateAcceleratedCompositingSettings() {
void Page::DidCommitLoad(LocalFrame* frame) {
if (main_frame_ == frame) {
GetConsoleMessageStorage().Clear();
- GetUseCounter().DidCommitLoad(frame);
- // TODO(rbyers): Most of this doesn't appear to take into account that each
- // SVGImage gets it's own Page instance.
+ // TODO(loonybear): Most of this doesn't appear to take into account that
+ // each SVGImage gets it's own Page instance.
GetDeprecation().ClearSuppression();
GetVisualViewport().SendUMAMetrics();
// Need to reset visual viewport position here since before commit load we
@@ -707,10 +731,10 @@ void Page::Trace(blink::Visitor* visitor) {
visitor->Trace(global_root_scroller_controller_);
visitor->Trace(visual_viewport_);
visitor->Trace(overscroll_controller_);
+ visitor->Trace(link_highlights_);
visitor->Trace(main_frame_);
visitor->Trace(plugin_data_);
visitor->Trace(validation_message_client_);
- visitor->Trace(use_counter_);
visitor->Trace(plugins_changed_observers_);
visitor->Trace(next_related_page_);
visitor->Trace(prev_related_page_);
@@ -722,12 +746,14 @@ void Page::LayerTreeViewInitialized(WebLayerTreeView& layer_tree_view,
LocalFrameView* view) {
if (GetScrollingCoordinator())
GetScrollingCoordinator()->LayerTreeViewInitialized(layer_tree_view, view);
+ GetLinkHighlights().LayerTreeViewInitialized(layer_tree_view);
}
void Page::WillCloseLayerTreeView(WebLayerTreeView& layer_tree_view,
LocalFrameView* view) {
if (scrolling_coordinator_)
scrolling_coordinator_->WillCloseLayerTreeView(layer_tree_view, view);
+ GetLinkHighlights().WillCloseLayerTreeView(layer_tree_view);
}
void Page::WillBeDestroyed() {
@@ -793,9 +819,9 @@ void Page::ReportIntervention(const String& text) {
}
}
-void Page::RequestBeginMainFrameNotExpected(bool new_state) {
+bool Page::RequestBeginMainFrameNotExpected(bool new_state) {
if (!main_frame_ || !main_frame_->IsLocalFrame())
- return;
+ return false;
base::debug::StackTrace main_frame_created_trace =
main_frame_->CreateStackForDebugging();
@@ -808,14 +834,10 @@ void Page::RequestBeginMainFrameNotExpected(bool new_state) {
if (WebLayerTreeView* layer_tree_view =
chrome_client_->GetWebLayerTreeView(main_frame)) {
layer_tree_view->RequestBeginMainFrameNotExpected(new_state);
+ return true;
}
}
-}
-
-void Page::SetPageFrozen(bool frozen) {
- SetLifecycleState(frozen ? PageLifecycleState::kFrozen
- : IsPageVisible() ? PageLifecycleState::kActive
- : PageLifecycleState::kHidden);
+ return false;
}
ukm::UkmRecorder* Page::GetUkmRecorder() {
diff --git a/chromium/third_party/blink/renderer/core/page/page.h b/chromium/third_party/blink/renderer/core/page/page.h
index eba08dbfa10..1be040296b6 100644
--- a/chromium/third_party/blink/renderer/core/page/page.h
+++ b/chromium/third_party/blink/renderer/core/page/page.h
@@ -28,20 +28,19 @@
#include "base/macros.h"
#include "third_party/blink/public/web/web_window_features.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/dom/viewport_description.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/core/frame/hosts_using_features.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings_delegate.h"
-#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/page/page_animator.h"
-#include "third_party/blink/renderer/core/page/page_lifecycle_state.h"
#include "third_party/blink/renderer/core/page/page_visibility_notifier.h"
#include "third_party/blink/renderer/core/page/page_visibility_observer.h"
#include "third_party/blink/renderer/core/page/page_visibility_state.h"
+#include "third_party/blink/renderer/core/page/viewport_description.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/geometry/region.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#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/supplementable.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -60,6 +59,7 @@ class DragCaret;
class DragController;
class FocusController;
class Frame;
+class LinkHighlights;
class OverscrollController;
struct PageScaleConstraints;
class PageScaleConstraintsSet;
@@ -123,6 +123,7 @@ class CORE_EXPORT Page final : public GarbageCollectedFinalized<Page>,
// This set does not include Pages created for other, internal purposes
// (SVGImages, inspector overlays, page popups etc.)
static PageSet& OrdinaryPages();
+ static void InsertOrdinaryPageForTesting(Page*);
// Returns pages related to the current browsing context (excluding the
// current page). See also
@@ -139,9 +140,6 @@ class CORE_EXPORT Page final : public GarbageCollectedFinalized<Page>,
// Returns the plugin data associated with |main_frame_origin|.
PluginData* GetPluginData(const SecurityOrigin* main_frame_origin);
- // Refreshes the browser-side plugin cache.
- static void RefreshPlugins();
-
// Resets the plugin data for all pages in the renderer process and notifies
// PluginsChangedObservers.
static void ResetPluginData();
@@ -191,11 +189,10 @@ class CORE_EXPORT Page final : public GarbageCollectedFinalized<Page>,
SmoothScrollSequencer* GetSmoothScrollSequencer();
- DOMRectList* NonFastScrollableRects(const LocalFrame*);
+ DOMRectList* NonFastScrollableRectsForTesting(const LocalFrame*);
Settings& GetSettings() const { return *settings_; }
- UseCounter& GetUseCounter() { return use_counter_; }
Deprecation& GetDeprecation() { return deprecation_; }
HostsUsingFeatures& GetHostsUsingFeatures() { return hosts_using_features_; }
@@ -220,6 +217,8 @@ class CORE_EXPORT Page final : public GarbageCollectedFinalized<Page>,
VisualViewport& GetVisualViewport();
const VisualViewport& GetVisualViewport() const;
+ LinkHighlights& GetLinkHighlights();
+
OverscrollController& GetOverscrollController();
const OverscrollController& GetOverscrollController() const;
@@ -266,7 +265,6 @@ class CORE_EXPORT Page final : public GarbageCollectedFinalized<Page>,
mojom::PageVisibilityState VisibilityState() const;
bool IsPageVisible() const;
- void SetLifecycleState(PageLifecycleState);
PageLifecycleState LifecycleState() const;
bool IsCursorVisible() const;
@@ -312,8 +310,8 @@ class CORE_EXPORT Page final : public GarbageCollectedFinalized<Page>,
// PageScheduler::Delegate implementation.
void ReportIntervention(const String& message) override;
- void RequestBeginMainFrameNotExpected(bool new_state) override;
- void SetPageFrozen(bool frozen) override;
+ bool RequestBeginMainFrameNotExpected(bool new_state) override;
+ void SetLifecycleState(PageLifecycleState) override;
ukm::UkmRecorder* GetUkmRecorder() override;
int64_t GetUkmSourceId() override;
@@ -337,6 +335,20 @@ class CORE_EXPORT Page final : public GarbageCollectedFinalized<Page>,
void SetPageScheduler(std::unique_ptr<PageScheduler>);
+ // Typically, the main frame and Page should both be owned by the embedder,
+ // which must call Page::willBeDestroyed() prior to destroying Page. This
+ // call detaches the main frame and clears this pointer, thus ensuring that
+ // this field only references a live main frame.
+ //
+ // However, there are several locations (InspectorOverlay, SVGImage, and
+ // WebPagePopupImpl) which don't hold a reference to the main frame at all
+ // after creating it. These are still safe because they always create a
+ // Frame with a LocalFrameView. LocalFrameView and Frame hold references to
+ // each other, thus keeping each other alive. The call to willBeDestroyed()
+ // breaks this cycle, so the frame is still properly destroyed once no
+ // longer needed.
+ Member<Frame> main_frame_;
+
Member<PageAnimator> animator_;
const Member<AutoscrollController> autoscroll_controller_;
Member<ChromeClient> chrome_client_;
@@ -354,26 +366,12 @@ class CORE_EXPORT Page final : public GarbageCollectedFinalized<Page>,
global_root_scroller_controller_;
const Member<VisualViewport> visual_viewport_;
const Member<OverscrollController> overscroll_controller_;
-
- // Typically, the main frame and Page should both be owned by the embedder,
- // which must call Page::willBeDestroyed() prior to destroying Page. This
- // call detaches the main frame and clears this pointer, thus ensuring that
- // this field only references a live main frame.
- //
- // However, there are several locations (InspectorOverlay, SVGImage, and
- // WebPagePopupImpl) which don't hold a reference to the main frame at all
- // after creating it. These are still safe because they always create a
- // Frame with a LocalFrameView. LocalFrameView and Frame hold references to
- // each other, thus keeping each other alive. The call to willBeDestroyed()
- // breaks this cycle, so the frame is still properly destroyed once no
- // longer needed.
- Member<Frame> main_frame_;
+ const Member<LinkHighlights> link_highlights_;
Member<PluginData> plugin_data_;
Member<ValidationMessageClient> validation_message_client_;
- UseCounter use_counter_;
Deprecation deprecation_;
HostsUsingFeatures hosts_using_features_;
WebWindowFeatures window_features_;
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 818f208449d..8d5ad84758a 100644
--- a/chromium/third_party/blink/renderer/core/page/page_animator.cc
+++ b/chromium/third_party/blink/renderer/core/page/page_animator.cc
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.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/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/svg/svg_document_extensions.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -61,15 +62,17 @@ void PageAnimator::ServiceScriptedAnimations(
document->View()->AnimatingScrollableAreas()) {
// Iterate over a copy, since ScrollableAreas may deregister
// themselves during the iteration.
- HeapVector<Member<ScrollableArea>> animating_scrollable_areas_copy;
+ HeapVector<Member<PaintLayerScrollableArea>>
+ animating_scrollable_areas_copy;
CopyToVector(*animating_scrollable_areas,
animating_scrollable_areas_copy);
- for (ScrollableArea* scrollable_area :
+ for (PaintLayerScrollableArea* scrollable_area :
animating_scrollable_areas_copy) {
scrollable_area->ServiceScrollAnimations(
monotonic_animation_start_time.since_origin().InSecondsF());
}
}
+ document->GetFrame()->AnimateSnapFling(monotonic_animation_start_time);
SVGDocumentExtensions::ServiceOnAnimationFrame(*document);
}
// TODO(skyostil): This function should not run for documents without views.
@@ -104,11 +107,11 @@ void PageAnimator::UpdateAllLifecyclePhases(LocalFrame& root_frame) {
view->UpdateAllLifecyclePhases();
}
-void PageAnimator::UpdateLifecycleToPrePaintClean(LocalFrame& root_frame) {
+void PageAnimator::UpdateAllLifecyclePhasesExceptPaint(LocalFrame& root_frame) {
LocalFrameView* view = root_frame.View();
base::AutoReset<bool> servicing(&updating_layout_and_style_for_painting_,
true);
- view->UpdateLifecycleToPrePaintClean();
+ view->UpdateAllLifecyclePhasesExceptPaint();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/page_animator.h b/chromium/third_party/blink/renderer/core/page/page_animator.h
index 6e98a789a45..5d3531c2f3e 100644
--- a/chromium/third_party/blink/renderer/core/page/page_animator.h
+++ b/chromium/third_party/blink/renderer/core/page/page_animator.h
@@ -32,7 +32,7 @@ class CORE_EXPORT PageAnimator final : public GarbageCollected<PageAnimator> {
// See documents of methods with the same names in LocalFrameView class.
void UpdateAllLifecyclePhases(LocalFrame& root_frame);
- void UpdateLifecycleToPrePaintClean(LocalFrame& root_frame);
+ void UpdateAllLifecyclePhasesExceptPaint(LocalFrame& root_frame);
AnimationClock& Clock() { return animation_clock_; }
private:
diff --git a/chromium/third_party/blink/renderer/core/page/page_lifecycle_state.h b/chromium/third_party/blink/renderer/core/page/page_lifecycle_state.h
deleted file mode 100644
index 0f8169a934e..00000000000
--- a/chromium/third_party/blink/renderer/core/page/page_lifecycle_state.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_PAGE_LIFECYCLE_STATE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_PAGE_LIFECYCLE_STATE_H_
-
-namespace blink {
-
-enum class PageLifecycleState {
- kUnknown, // The page state is unknown.
- kActive, // The page is visible and active.
- kHidden, // The page is not visible but active.
- kFrozen, // The page is frozen.
-};
-
-} // namespace blink
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_PAGE_LIFECYCLE_STATE_H_
diff --git a/chromium/third_party/blink/renderer/core/page/page_overlay.cc b/chromium/third_party/blink/renderer/core/page/page_overlay.cc
index 55d5560604b..d7b281fcd5e 100644
--- a/chromium/third_party/blink/renderer/core/page/page_overlay.cc
+++ b/chromium/third_party/blink/renderer/core/page/page_overlay.cc
@@ -32,7 +32,7 @@
#include <utility>
#include "base/memory/ptr_util.h"
-#include "cc/layers/layer.h"
+#include "cc/layers/picture_layer.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/frame/web_frame_widget_base.h"
@@ -72,26 +72,25 @@ void PageOverlay::Update() {
return;
if (!layer_) {
+ GraphicsLayer* parent_layer =
+ frame->IsMainFrame()
+ ? frame->GetPage()->GetVisualViewport().ContainerLayer()
+ : frame_impl_->LocalRootFrameWidget()->RootGraphicsLayer();
+ if (!parent_layer)
+ return;
+
layer_ = GraphicsLayer::Create(*this);
layer_->SetDrawsContent(true);
+ parent_layer->AddChild(layer_.get());
// This is required for contents of overlay to stay in sync with the page
// while scrolling.
cc::Layer* cc_layer = layer_->CcLayer();
cc_layer->AddMainThreadScrollingReasons(
MainThreadScrollingReason::kPageOverlay);
- if (frame->IsMainFrame()) {
- frame->GetPage()->GetVisualViewport().ContainerLayer()->AddChild(
- layer_.get());
- } else {
- frame_impl_->LocalRootFrameWidget()->RootGraphicsLayer()->AddChild(
- layer_.get());
- }
-
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- layer_->SetLayerState(PropertyTreeState(PropertyTreeState::Root()),
- IntPoint());
- }
+
+ layer_->SetLayerState(PropertyTreeState(PropertyTreeState::Root()),
+ IntPoint());
}
IntSize size = frame->GetPage()->GetVisualViewport().Size();
@@ -104,12 +103,12 @@ void PageOverlay::Update() {
LayoutRect PageOverlay::VisualRect() const {
DCHECK(layer_.get());
- return LayoutRect(FloatPoint(), layer_->Size());
+ return LayoutRect(IntPoint(), layer_->Size());
}
IntRect PageOverlay::ComputeInterestRect(const GraphicsLayer* graphics_layer,
const IntRect&) const {
- return IntRect(IntPoint(), ExpandedIntSize(layer_->Size()));
+ return IntRect(IntPoint(), layer_->Size());
}
void PageOverlay::PaintContents(const GraphicsLayer* graphics_layer,
diff --git a/chromium/third_party/blink/renderer/core/page/page_overlay_test.cc b/chromium/third_party/blink/renderer/core/page/page_overlay_test.cc
index b47e7c38fb9..c483078197f 100644
--- a/chromium/third_party/blink/renderer/core/page/page_overlay_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/page_overlay_test.cc
@@ -5,10 +5,12 @@
#include "third_party/blink/renderer/core/page/page_overlay.h"
#include <memory>
+
+#include "cc/paint/paint_canvas.h"
+#include "cc/trees/layer_tree_host.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/web_canvas.h"
#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
@@ -70,9 +72,9 @@ class PageOverlayTest : public testing::Test {
enum CompositingMode { kAcceleratedCompositing, kUnacceleratedCompositing };
void Initialize(CompositingMode compositing_mode) {
- helper_.Initialize(nullptr /* webFrameClient */,
- nullptr /* webViewClient */,
- nullptr /* webWidgetClient */,
+ helper_.Initialize(nullptr /* web_frame_client */,
+ nullptr /* web_view_client */,
+ nullptr /* web_widget_client */,
compositing_mode == kAcceleratedCompositing
? EnableAcceleratedCompositing
: DisableAcceleratedCompositing);
@@ -90,7 +92,12 @@ class PageOverlayTest : public testing::Test {
std::make_unique<SolidColorOverlay>(SK_ColorYELLOW));
}
- void SetViewportSize(const WebSize& size) { helper_.SetViewportSize(size); }
+ void SetViewportSize(const WebSize& size) {
+ content::LayerTreeView* layer_tree_view = helper_.GetLayerTreeView();
+ layer_tree_view->SetViewportSizeAndScale(
+ static_cast<gfx::Size>(size), /*device_scale_factor=*/1.f,
+ layer_tree_view->layer_tree_host()->local_surface_id_from_parent());
+ }
template <typename OverlayType>
void RunPageOverlayTestWithAcceleratedCompositing();
diff --git a/chromium/third_party/blink/renderer/core/page/page_popup_client_test.cc b/chromium/third_party/blink/renderer/core/page/page_popup_client_test.cc
index 999d9b72406..4069b009f3d 100644
--- a/chromium/third_party/blink/renderer/core/page/page_popup_client_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/page_popup_client_test.cc
@@ -14,7 +14,7 @@ TEST(PagePopupClientTest, AddJavaScriptString) {
PagePopupClient::AddJavaScriptString(
String::FromUTF8("abc\r\n'\"</script>\t\f\v\xE2\x80\xA8\xE2\x80\xA9"),
buffer.get());
- const Vector<char> contiguous = buffer->Copy();
+ const Vector<char> contiguous = buffer->CopyAs<Vector<char>>();
EXPECT_EQ(
"\"abc\\r\\n'\\\"\\x3C/script>\\u0009\\u000C\\u000B\\u2028\\u2029\"",
std::string(contiguous.data(), contiguous.size()));
diff --git a/chromium/third_party/blink/renderer/core/page/page_visibility_notifier.cc b/chromium/third_party/blink/renderer/core/page/page_visibility_notifier.cc
index 531da3efce0..b497d34753a 100644
--- a/chromium/third_party/blink/renderer/core/page/page_visibility_notifier.cc
+++ b/chromium/third_party/blink/renderer/core/page/page_visibility_notifier.cc
@@ -31,9 +31,9 @@
namespace blink {
void PageVisibilityNotifier::NotifyPageVisibilityChanged() {
- base::AutoReset<IterationState> scope(&iteration_state_, kAllowingNone);
- for (PageVisibilityObserver* observer : observers_)
+ ForEachObserver([](PageVisibilityObserver* observer) {
observer->PageVisibilityChanged();
+ });
}
} // namespace blink
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 0f59076f1be..9a7c5ec8931 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
@@ -31,7 +31,7 @@
#include "third_party/blink/renderer/core/page/page_widget_delegate.h"
#include "third_party/blink/public/platform/web_input_event.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.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"
@@ -42,9 +42,7 @@
#include "third_party/blink/renderer/core/page/autoscroll_controller.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
@@ -64,17 +62,17 @@ void PageWidgetDelegate::UpdateLifecycle(
LocalFrame& root,
WebWidget::LifecycleUpdate requested_update) {
if (requested_update == WebWidget::LifecycleUpdate::kPrePaint) {
- page.Animator().UpdateLifecycleToPrePaintClean(root);
+ page.Animator().UpdateAllLifecyclePhasesExceptPaint(root);
} else {
page.Animator().UpdateAllLifecyclePhases(root);
}
}
-static void PaintInternal(Page& page,
- WebCanvas* canvas,
- const WebRect& rect,
- LocalFrame& root,
- const GlobalPaintFlags global_paint_flags) {
+static void PaintContentInternal(Page& page,
+ cc::PaintCanvas* canvas,
+ const WebRect& rect,
+ LocalFrame& root,
+ const GlobalPaintFlags global_paint_flags) {
if (rect.IsEmpty())
return;
@@ -95,7 +93,9 @@ static void PaintInternal(Page& page,
builder.Context().SetDeviceScaleFactor(scale_factor);
view->PaintWithLifecycleUpdate(builder.Context(), global_paint_flags,
CullRect(dirty_rect));
- builder.EndRecording(*canvas);
+ builder.EndRecording(
+ *canvas,
+ view->GetLayoutView()->FirstFragment().LocalBorderBoxProperties());
} else {
PaintFlags flags;
flags.setColor(SK_ColorWHITE);
@@ -105,18 +105,20 @@ static void PaintInternal(Page& page,
canvas->restore();
}
-void PageWidgetDelegate::Paint(Page& page,
- WebCanvas* canvas,
- const WebRect& rect,
- LocalFrame& root) {
- PaintInternal(page, canvas, rect, root, kGlobalPaintNormalPhase);
+void PageWidgetDelegate::PaintContent(Page& page,
+ cc::PaintCanvas* canvas,
+ const WebRect& rect,
+ LocalFrame& root) {
+ PaintContentInternal(page, canvas, rect, root, kGlobalPaintNormalPhase);
}
-void PageWidgetDelegate::PaintIgnoringCompositing(Page& page,
- WebCanvas* canvas,
- const WebRect& rect,
- LocalFrame& root) {
- PaintInternal(page, canvas, rect, root, kGlobalPaintFlattenCompositingLayers);
+void PageWidgetDelegate::PaintContentIgnoringCompositing(
+ Page& page,
+ cc::PaintCanvas* canvas,
+ const WebRect& rect,
+ LocalFrame& root) {
+ PaintContentInternal(page, canvas, rect, root,
+ kGlobalPaintFlattenCompositingLayers);
}
WebInputEventResult PageWidgetDelegate::HandleInputEvent(
@@ -134,7 +136,7 @@ WebInputEventResult PageWidgetDelegate::HandleInputEvent(
// interactive_detector is null in the OOPIF case.
// TODO(crbug.com/808089): report across OOPIFs.
if (interactive_detector)
- interactive_detector->HandleForFirstInputDelay(event);
+ interactive_detector->HandleForInputDelay(event);
}
if (event.GetModifiers() & WebInputEvent::kIsTouchAccessibility &&
@@ -142,10 +144,10 @@ WebInputEventResult PageWidgetDelegate::HandleInputEvent(
WebMouseEvent mouse_event = TransformWebMouseEvent(
root->View(), static_cast<const WebMouseEvent&>(event));
- IntPoint doc_point(root->View()->RootFrameToContents(
+ HitTestLocation location(root->View()->ConvertFromRootFrame(
FlooredIntPoint(mouse_event.PositionInRootFrame())));
- HitTestResult result = root->GetEventHandler().HitTestResultAtPoint(
- doc_point, HitTestRequest::kReadOnly | HitTestRequest::kActive);
+ HitTestResult result = root->GetEventHandler().HitTestResultAtLocation(
+ location, HitTestRequest::kReadOnly | HitTestRequest::kActive);
result.SetToShadowHostIfInRestrictedShadowRoot();
if (result.InnerNodeFrame()) {
Document* document = result.InnerNodeFrame()->GetDocument();
@@ -238,11 +240,11 @@ WebInputEventResult PageWidgetDelegate::HandleInputEvent(
return WebInputEventResult::kNotHandled;
case WebInputEvent::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:
- // Touchscreen pinch events are currently not handled in main thread.
- // Once they are, these should be passed to |handleGestureEvent| similar
- // to gesture scroll events.
return WebInputEventResult::kNotHandled;
default:
return WebInputEventResult::kNotHandled;
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 026fad1a236..778cff4de2e 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,13 +31,15 @@
#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_canvas.h"
#include "third_party/blink/public/platform/web_coalesced_input_event.h"
#include "third_party/blink/public/web/web_widget.h"
#include "third_party/blink/renderer/core/core_export.h"
-namespace blink {
+namespace cc {
+class PaintCanvas;
+}
+namespace blink {
class LocalFrame;
class Page;
class WebGestureEvent;
@@ -81,11 +83,14 @@ class CORE_EXPORT PageWidgetDelegate {
WebWidget::LifecycleUpdate requested_update);
// See documents of methods with the same names in FrameView class.
- static void Paint(Page&, WebCanvas*, const WebRect&, LocalFrame& root);
- static void PaintIgnoringCompositing(Page&,
- WebCanvas*,
- const WebRect&,
- LocalFrame& root);
+ static void PaintContent(Page&,
+ cc::PaintCanvas*,
+ const WebRect&,
+ LocalFrame& root);
+ static void PaintContentIgnoringCompositing(Page&,
+ cc::PaintCanvas*,
+ const WebRect&,
+ LocalFrame& root);
// See FIXME in the function body about nullptr |root|.
static WebInputEventResult HandleInputEvent(
PageWidgetEventHandler&,
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 5bd09e1c220..a4551c43128 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
@@ -165,8 +165,10 @@ void PointerLockController::EnqueueEvent(const AtomicString& type,
void PointerLockController::EnqueueEvent(const AtomicString& type,
Document* document) {
- if (document && document->domWindow())
- document->domWindow()->EnqueueDocumentEvent(Event::Create(type));
+ if (document && document->domWindow()) {
+ document->domWindow()->EnqueueDocumentEvent(Event::Create(type),
+ TaskType::kMiscPlatformAPI);
+ }
}
void PointerLockController::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/core/page/popup_opening_observer.h b/chromium/third_party/blink/renderer/core/page/popup_opening_observer.h
index 4686a5b1e3f..aa00e7b39b9 100644
--- a/chromium/third_party/blink/renderer/core/page/popup_opening_observer.h
+++ b/chromium/third_party/blink/renderer/core/page/popup_opening_observer.h
@@ -27,10 +27,11 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_POPUP_OPENING_OBSERVER_H_
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
-class CORE_EXPORT PopupOpeningObserver {
+class CORE_EXPORT PopupOpeningObserver : public GarbageCollectedMixin {
public:
virtual void WillOpenPopup() = 0;
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 3cf14cb80a3..27d5942d5e2 100644
--- a/chromium/third_party/blink/renderer/core/page/print_context.cc
+++ b/chromium/third_party/blink/renderer/core/page/print_context.cc
@@ -25,6 +25,7 @@
#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"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
namespace blink {
@@ -127,7 +128,7 @@ void PrintContext::ComputePageRectsWithPageSizeInternal(
? inline_direction_start
: inline_direction_start - page_logical_width;
- auto* scrollable_area = GetFrame()->View()->LayoutViewportScrollableArea();
+ auto* scrollable_area = GetFrame()->View()->LayoutViewport();
IntSize frame_scroll = scrollable_area->ScrollOffsetInt();
page_logical_left -= frame_scroll.Width();
page_logical_top -= frame_scroll.Height();
@@ -190,7 +191,7 @@ int PrintContext::PageNumberForElement(Element* element,
FloatSize scaled_page_size = page_size_in_pixels;
scaled_page_size.Scale(
- frame->View()->LayoutViewportScrollableArea()->ContentsSize().Width() /
+ frame->View()->LayoutViewport()->ContentsSize().Width() /
page_rect.Width());
print_context->ComputePageRectsWithPageSize(scaled_page_size);
@@ -309,7 +310,7 @@ int PrintContext::NumberOfPages(LocalFrame* frame,
// Account for shrink-to-fit.
FloatSize scaled_page_size = page_size_in_pixels;
scaled_page_size.Scale(
- frame->View()->LayoutViewportScrollableArea()->ContentsSize().Width() /
+ frame->View()->LayoutViewport()->ContentsSize().Width() /
page_rect.Width());
print_context->ComputePageRectsWithPageSize(scaled_page_size);
return print_context->PageCount();
diff --git a/chromium/third_party/blink/renderer/core/page/print_context_test.cc b/chromium/third_party/blink/renderer/core/page/print_context_test.cc
index f40c47b3994..0477c0deb73 100644
--- a/chromium/third_party/blink/renderer/core/page/print_context_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/print_context_test.cc
@@ -8,6 +8,7 @@
#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/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_controller.cc b/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_controller.cc
index 7c8b74cc44c..ce48fb1430c 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_controller.cc
@@ -85,8 +85,7 @@ PaintLayerScrollableArea* GetScrollableArea(const Element& element) {
if (!frame_view)
return nullptr;
- return ToPaintLayerScrollableArea(
- frame_view->LayoutViewportScrollableArea());
+ return frame_view->LayoutViewport();
}
DCHECK(element.GetLayoutObject()->IsBox());
@@ -197,6 +196,27 @@ void RootScrollerController::RecomputeEffectiveRootScroller() {
Node* old_effective_root_scroller = effective_root_scroller_;
effective_root_scroller_ = new_effective_root_scroller;
+ if (new_effective_root_scroller != old_effective_root_scroller) {
+ if (LayoutBoxModelObject* new_obj =
+ new_effective_root_scroller->GetLayoutBoxModelObject()) {
+ if (new_obj->Layer()) {
+ new_effective_root_scroller->GetLayoutBoxModelObject()
+ ->Layer()
+ ->SetNeedsCompositingInputsUpdate();
+ }
+ }
+ if (old_effective_root_scroller) {
+ if (LayoutBoxModelObject* old_obj =
+ old_effective_root_scroller->GetLayoutBoxModelObject()) {
+ if (old_obj->Layer()) {
+ old_effective_root_scroller->GetLayoutBoxModelObject()
+ ->Layer()
+ ->SetNeedsCompositingInputsUpdate();
+ }
+ }
+ }
+ }
+
ApplyRootScrollerProperties(*old_effective_root_scroller);
ApplyRootScrollerProperties(*effective_root_scroller_);
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 7a822fb6519..8af7d56aa16 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
@@ -276,7 +276,8 @@ TEST_F(RootScrollerTest, TestSetRootScroller) {
GetWebView()->HandleInputEvent(GenerateTouchGestureEvent(
WebInputEvent::kGestureScrollUpdate, 0, -100));
EXPECT_FLOAT_EQ(100, container->scrollTop());
- EXPECT_FLOAT_EQ(0, MainFrameView()->GetScrollOffset().Height());
+ EXPECT_FLOAT_EQ(
+ 0, MainFrameView()->LayoutViewport()->GetScrollOffset().Height());
}
{
@@ -288,7 +289,8 @@ TEST_F(RootScrollerTest, TestSetRootScroller) {
GetWebView()->HandleInputEvent(GenerateTouchGestureEvent(
WebInputEvent::kGestureScrollUpdate, 0, -500));
EXPECT_FLOAT_EQ(maximum_scroll, container->scrollTop());
- EXPECT_FLOAT_EQ(0, MainFrameView()->GetScrollOffset().Height());
+ EXPECT_FLOAT_EQ(
+ 0, MainFrameView()->LayoutViewport()->GetScrollOffset().Height());
Mock::VerifyAndClearExpectations(&client);
}
@@ -300,7 +302,8 @@ TEST_F(RootScrollerTest, TestSetRootScroller) {
GetWebView()->HandleInputEvent(
GenerateTouchGestureEvent(WebInputEvent::kGestureScrollUpdate, 0, -20));
EXPECT_FLOAT_EQ(maximum_scroll, container->scrollTop());
- EXPECT_FLOAT_EQ(0, MainFrameView()->GetScrollOffset().Height());
+ EXPECT_FLOAT_EQ(
+ 0, MainFrameView()->LayoutViewport()->GetScrollOffset().Height());
Mock::VerifyAndClearExpectations(&client);
}
@@ -319,7 +322,8 @@ TEST_F(RootScrollerTest, TestSetRootScroller) {
GetWebView()->HandleInputEvent(
GenerateTouchGestureEvent(WebInputEvent::kGestureScrollUpdate, 0, -30));
EXPECT_FLOAT_EQ(maximum_scroll, container->scrollTop());
- EXPECT_FLOAT_EQ(0, MainFrameView()->GetScrollOffset().Height());
+ EXPECT_FLOAT_EQ(
+ 0, MainFrameView()->LayoutViewport()->GetScrollOffset().Height());
Mock::VerifyAndClearExpectations(&client);
GetWebView()->HandleInputEvent(
@@ -538,9 +542,8 @@ TEST_F(RootScrollerTest, SetRootScrollerIframeUsesCorrectLayerAndCallback) {
// No root scroller set, the documentElement should be the effective root
// and the main LocalFrameView's scroll layer should be the layer to use.
{
- EXPECT_EQ(
- main_controller.RootScrollerLayer(),
- MainFrameView()->LayoutViewportScrollableArea()->LayerForScrolling());
+ EXPECT_EQ(main_controller.RootScrollerLayer(),
+ MainFrameView()->LayoutViewport()->LayerForScrolling());
EXPECT_TRUE(main_controller.IsViewportScrollCallback(
MainFrame()->GetDocument()->documentElement()->GetApplyScroll()));
}
@@ -550,9 +553,8 @@ TEST_F(RootScrollerTest, SetRootScrollerIframeUsesCorrectLayerAndCallback) {
{
SetAndSelectRootScroller(*iframe->contentDocument(), container);
- EXPECT_EQ(
- main_controller.RootScrollerLayer(),
- MainFrameView()->LayoutViewportScrollableArea()->LayerForScrolling());
+ EXPECT_EQ(main_controller.RootScrollerLayer(),
+ MainFrameView()->LayoutViewport()->LayerForScrolling());
EXPECT_TRUE(main_controller.IsViewportScrollCallback(
MainFrame()->GetDocument()->documentElement()->GetApplyScroll()));
}
@@ -564,9 +566,7 @@ TEST_F(RootScrollerTest, SetRootScrollerIframeUsesCorrectLayerAndCallback) {
SetAndSelectRootScroller(*MainFrame()->GetDocument(), iframe);
ScrollableArea* container_scroller =
- static_cast<PaintInvalidationCapableScrollableArea*>(
- ToLayoutBox(container->GetLayoutObject())->GetScrollableArea());
-
+ ToLayoutBox(container->GetLayoutObject())->GetScrollableArea();
EXPECT_EQ(main_controller.RootScrollerLayer(),
container_scroller->LayerForScrolling());
EXPECT_FALSE(main_controller.IsViewportScrollCallback(
@@ -580,11 +580,10 @@ TEST_F(RootScrollerTest, SetRootScrollerIframeUsesCorrectLayerAndCallback) {
// documentElement becomes the global root scroller.
{
SetAndSelectRootScroller(*iframe->contentDocument(), nullptr);
- EXPECT_EQ(main_controller.RootScrollerLayer(),
- iframe->contentDocument()
- ->View()
- ->LayoutViewportScrollableArea()
- ->LayerForScrolling());
+ EXPECT_EQ(main_controller.RootScrollerLayer(), iframe->contentDocument()
+ ->View()
+ ->LayoutViewport()
+ ->LayerForScrolling());
EXPECT_FALSE(
main_controller.IsViewportScrollCallback(container->GetApplyScroll()));
EXPECT_FALSE(main_controller.IsViewportScrollCallback(
@@ -597,9 +596,8 @@ TEST_F(RootScrollerTest, SetRootScrollerIframeUsesCorrectLayerAndCallback) {
// documentElement and corresponding layer.
{
SetAndSelectRootScroller(*MainFrame()->GetDocument(), nullptr);
- EXPECT_EQ(
- main_controller.RootScrollerLayer(),
- MainFrameView()->LayoutViewportScrollableArea()->LayerForScrolling());
+ EXPECT_EQ(main_controller.RootScrollerLayer(),
+ MainFrameView()->LayoutViewport()->LayerForScrolling());
EXPECT_TRUE(main_controller.IsViewportScrollCallback(
MainFrame()->GetDocument()->documentElement()->GetApplyScroll()));
EXPECT_FALSE(
@@ -800,7 +798,7 @@ TEST_F(RootScrollerTest, RemoteMainFrame) {
WebRemoteFrameImpl* remote_main_frame = FrameTestHelpers::CreateRemote();
helper_.LocalMainFrame()->Swap(remote_main_frame);
remote_main_frame->SetReplicatedOrigin(
- WebSecurityOrigin(SecurityOrigin::CreateUnique()), false);
+ WebSecurityOrigin(SecurityOrigin::CreateUniqueOpaque()), false);
local_frame = FrameTestHelpers::CreateLocalChild(*remote_main_frame);
FrameTestHelpers::LoadFrame(local_frame,
@@ -872,7 +870,7 @@ TEST_F(RootScrollerTest, NonMainLocalRootLifecycle) {
ToWebLocalFrameImpl(helper_.LocalMainFrame()->FirstChild());
child->Swap(remote_frame);
remote_frame->SetReplicatedOrigin(
- WebSecurityOrigin(SecurityOrigin::CreateUnique()), false);
+ WebSecurityOrigin(SecurityOrigin::CreateUniqueOpaque()), false);
non_main_local_root = FrameTestHelpers::CreateLocalChild(*remote_frame);
ASSERT_EQ(non_main_local_root->LocalRoot(), non_main_local_root);
@@ -948,9 +946,8 @@ TEST_F(RootScrollerTest, DocumentElementHasNoLayoutObject) {
EXPECT_EQ(MainFrame()->GetDocument()->documentElement(),
global_controller.GlobalRootScroller());
- EXPECT_EQ(
- MainFrameView()->LayoutViewportScrollableArea()->LayerForScrolling(),
- global_controller.RootScrollerLayer());
+ EXPECT_EQ(MainFrameView()->LayoutViewport()->LayerForScrolling(),
+ global_controller.RootScrollerLayer());
}
// On Android, the main scrollbars are owned by the visual viewport and the
@@ -963,9 +960,7 @@ TEST_F(RootScrollerTest, UseVisualViewportScrollbars) {
SetAndSelectRootScroller(*MainFrame()->GetDocument(), container);
ScrollableArea* container_scroller =
- static_cast<PaintInvalidationCapableScrollableArea*>(
- ToLayoutBox(container->GetLayoutObject())->GetScrollableArea());
-
+ ToLayoutBox(container->GetLayoutObject())->GetScrollableArea();
EXPECT_FALSE(container_scroller->HorizontalScrollbar());
EXPECT_FALSE(container_scroller->VerticalScrollbar());
EXPECT_GT(container_scroller->MaximumScrollOffset().Width(), 0);
@@ -993,8 +988,7 @@ TEST_F(RootScrollerTest, UseVisualViewportScrollbarsIframe) {
MainFrameView()->UpdateAllLifecyclePhases();
- ScrollableArea* container_scroller =
- child_frame->View()->LayoutViewportScrollableArea();
+ ScrollableArea* container_scroller = child_frame->View()->LayoutViewport();
EXPECT_FALSE(container_scroller->HorizontalScrollbar());
EXPECT_FALSE(container_scroller->VerticalScrollbar());
@@ -1032,8 +1026,7 @@ TEST_F(RootScrollerTest, TopControlsAdjustmentAppliedToRootScroller) {
SetAndSelectRootScroller(*MainFrame()->GetDocument(), container);
ScrollableArea* container_scroller =
- static_cast<PaintInvalidationCapableScrollableArea*>(
- ToLayoutBox(container->GetLayoutObject())->GetScrollableArea());
+ ToLayoutBox(container->GetLayoutObject())->GetScrollableArea();
// Hide the top controls and scroll down maximally. We should account for the
// change in maximum scroll offset due to the top controls hiding. That is,
@@ -1073,8 +1066,8 @@ TEST_F(RootScrollerTest, RotationAnchoring) {
MainFrame()->GetDocument()->getElementById("container");
SetAndSelectRootScroller(*MainFrame()->GetDocument(), container);
- container_scroller = static_cast<PaintInvalidationCapableScrollableArea*>(
- ToLayoutBox(container->GetLayoutObject())->GetScrollableArea());
+ container_scroller =
+ ToLayoutBox(container->GetLayoutObject())->GetScrollableArea();
}
Element* target = MainFrame()->GetDocument()->getElementById("target");
@@ -1220,14 +1213,14 @@ TEST_F(RootScrollerTest, ImmediateUpdateOfLayoutViewport) {
LocalFrame* iframe_local_frame = ToLocalFrame(iframe->ContentFrame());
EXPECT_EQ(iframe, &main_controller.EffectiveRootScroller());
- EXPECT_EQ(iframe_local_frame->View()->LayoutViewportScrollableArea(),
+ EXPECT_EQ(iframe_local_frame->View()->LayoutViewport(),
&MainFrameView()->GetRootFrameViewport()->LayoutViewport());
// Remove the <iframe> and make sure the layout viewport reverts to the
// LocalFrameView without a layout.
iframe->remove();
- EXPECT_EQ(MainFrameView()->LayoutViewportScrollableArea(),
+ EXPECT_EQ(MainFrameView()->LayoutViewport(),
&MainFrameView()->GetRootFrameViewport()->LayoutViewport());
}
@@ -2039,7 +2032,7 @@ TEST_F(ImplicitRootScrollerSimTest, NavigateToValidRemainsRootScroller) {
// the parent.
SimRequest child_request2("https://example.com/child-next.html", "text/html");
WebURLRequest request(KURL("https://example.com/child-next.html"));
- WebView().MainFrameImpl()->FirstChild()->ToWebLocalFrame()->LoadRequest(
+ WebView().MainFrameImpl()->FirstChild()->ToWebLocalFrame()->StartNavigation(
request);
child_request2.Start();
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_util.cc b/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_util.cc
index 4cf9b99c5e0..87b8a07185f 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_util.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/root_scroller_util.cc
@@ -33,7 +33,7 @@ ScrollableArea* ScrollableAreaForRootScroller(const Node* node) {
// getScrollableArea() since that could be the RootFrameViewport. The
// rootScroller's ScrollableArea will be swapped in as the layout viewport
// in RootFrameViewport so we need to ensure we get the layout viewport.
- return node->GetDocument().View()->LayoutViewportScrollableArea();
+ return node->GetDocument().View()->LayoutViewport();
}
DCHECK(node->IsElementNode());
@@ -42,8 +42,8 @@ ScrollableArea* ScrollableAreaForRootScroller(const Node* node) {
if (!element->GetLayoutObject() || !element->GetLayoutObject()->IsBox())
return nullptr;
- return static_cast<PaintInvalidationCapableScrollableArea*>(
- ToLayoutBoxModelObject(element->GetLayoutObject())->GetScrollableArea());
+ return ToLayoutBoxModelObject(element->GetLayoutObject())
+ ->GetScrollableArea();
}
PaintLayer* PaintLayerForRootScroller(const Node* node) {
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/scroll_state.cc b/chromium/third_party/blink/renderer/core/page/scrolling/scroll_state.cc
index 19205687480..93d56565eb7 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/scroll_state.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/scroll_state.cc
@@ -7,7 +7,6 @@
#include <memory>
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/dom/element.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
@@ -61,12 +60,13 @@ void ScrollState::consumeDelta(double x,
if ((data_->delta_x > 0 && 0 > x) || (data_->delta_x < 0 && 0 < x) ||
(data_->delta_y > 0 && 0 > y) || (data_->delta_y < 0 && 0 < y)) {
exception_state.ThrowDOMException(
- kInvalidModificationError, "Can't increase delta using consumeDelta");
+ DOMExceptionCode::kInvalidModificationError,
+ "Can't increase delta using consumeDelta");
return;
}
if (fabs(x) > fabs(data_->delta_x) || fabs(y) > fabs(data_->delta_y)) {
exception_state.ThrowDOMException(
- kInvalidModificationError,
+ DOMExceptionCode::kInvalidModificationError,
"Can't change direction of delta using consumeDelta");
return;
}
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/scroll_state.h b/chromium/third_party/blink/renderer/core/page/scrolling/scroll_state.h
index 364ac18adae..3fdcde684b0 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/scroll_state.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/scroll_state.h
@@ -7,10 +7,10 @@
#include <deque>
#include <memory>
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/page/scrolling/scroll_state_init.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/scroll/scroll_state_data.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
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 5f15853574b..191e2407ff1 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,6 +32,7 @@
#include "cc/layers/layer_position_constraint.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_interface.h"
#include "cc/layers/solid_color_scrollbar_layer.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -40,6 +41,7 @@
#include "third_party/blink/renderer/core/frame/event_handler_registry.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/page_scale_constraints_set.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/html/html_element.h"
@@ -52,6 +54,7 @@
#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_context.h"
#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/platform/animation/compositor_animation_host.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_timeline.h"
#include "third_party/blink/renderer/platform/geometry/region.h"
@@ -65,6 +68,7 @@
#endif
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_layer_tree_view.h"
+#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
#include "third_party/blink/renderer/platform/scroll/main_thread_scrolling_reason.h"
#include "third_party/blink/renderer/platform/scroll/scroll_animator_base.h"
#include "third_party/blink/renderer/platform/scroll/scrollbar_layer_delegate.h"
@@ -104,7 +108,7 @@ void ScrollingCoordinator::SetShouldHandleScrollGestureOnMainThreadRegion(
const Region& region,
LocalFrameView* frame_view) {
if (cc::Layer* scroll_layer = GraphicsLayerToCcLayer(
- frame_view->LayoutViewportScrollableArea()->LayerForScrolling())) {
+ frame_view->LayoutViewport()->LayerForScrolling())) {
scroll_layer->SetNonFastScrollableRegion(RegionToCCRegion(region));
}
}
@@ -124,6 +128,14 @@ void ScrollingCoordinator::NotifyTransformChanged(LocalFrame* frame,
if (frame->View()->NeedsLayout())
return;
+ if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()) {
+ // PaintTouchActionRects does not keep a list of layers with touch rects so
+ // just do an update if transforms change.
+ frame->View()->GetScrollingContext()->SetTouchEventTargetRectsAreDirty(
+ true);
+ return;
+ }
+
for (PaintLayer* layer = box.EnclosingLayer(); layer;
layer = layer->Parent()) {
if (frame->View()
@@ -151,7 +163,7 @@ void ScrollingCoordinator::DidScroll(const gfx::ScrollOffset& offset,
// VisualViewport::didScroll).
if (LocalFrameView* view = ToLocalFrame(frame)->View()) {
if (auto* scrollable = view->ScrollableAreaWithElementId(element_id)) {
- scrollable->DidScroll(offset);
+ scrollable->DidScroll(FloatPoint(offset.x(), offset.y()));
return;
}
}
@@ -160,8 +172,7 @@ void ScrollingCoordinator::DidScroll(const gfx::ScrollOffset& offset,
// safely ignore the DidScroll callback.
}
-void ScrollingCoordinator::UpdateAfterCompositingChangeIfNeeded(
- LocalFrameView* frame_view) {
+void ScrollingCoordinator::UpdateAfterPaint(LocalFrameView* frame_view) {
LocalFrame* frame = &frame_view->GetFrame();
DCHECK(frame->IsLocalRoot());
@@ -179,9 +190,10 @@ void ScrollingCoordinator::UpdateAfterCompositingChangeIfNeeded(
}
SCOPED_BLINK_UMA_HISTOGRAM_TIMER("Blink.ScrollingCoordinator.UpdateTime");
- TRACE_EVENT0("input",
- "ScrollingCoordinator::updateAfterCompositingChangeIfNeeded");
+ TRACE_EVENT0("input", "ScrollingCoordinator::UpdateAfterPaint");
+ // TODO(pdr): Move the scroll gesture region logic to use touch action rects.
+ // These features are similar and do not need independent implementations.
if (scroll_gesture_region_dirty) {
// Compute the region of the page where we can't handle scroll gestures and
// mousewheel events
@@ -209,6 +221,9 @@ void ScrollingCoordinator::UpdateAfterCompositingChangeIfNeeded(
frame_view->GetScrollingContext()->SetTouchEventTargetRectsAreDirty(false);
}
+ // TODO(pdr): Move the should_scroll_on_main_thread logic to use touch action
+ // rects. These features are similar and do not need independent
+ // implementations.
if (should_scroll_on_main_thread_dirty ||
frame_view->FrameIsScrollableDidChange()) {
SetShouldUpdateScrollLayerPositionOnMainThread(
@@ -226,6 +241,51 @@ void ScrollingCoordinator::UpdateAfterCompositingChangeIfNeeded(
UpdateUserInputScrollable(&page_->GetVisualViewport());
}
+template <typename Function>
+static void ForAllGraphicsLayers(GraphicsLayer& layer,
+ const Function& function) {
+ function(layer);
+ for (auto* child : layer.Children())
+ ForAllGraphicsLayers(*child, function);
+}
+
+// Set the touch action rects on the cc layer from the touch action data stored
+// on the GraphicsLayer's paint chunks.
+static void UpdateLayerTouchActionRects(GraphicsLayer& layer) {
+ DCHECK(RuntimeEnabledFeatures::PaintTouchActionRectsEnabled());
+
+ // TODO(pdr): This will need to be moved to PaintArtifactCompositor (or later)
+ // for SPV2 because composited layers are not known until then. The SPV2
+ // implementation will iterate over the paint chunks in each composited layer
+ // and will look almost the same as this function.
+ DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
+
+ if (!layer.DrawsContent())
+ return;
+
+ const auto& layer_state = layer.GetPropertyTreeState();
+ Vector<TouchActionRect> touch_action_rects_in_layer_space;
+ for (const auto& chunk : layer.GetPaintController().PaintChunks()) {
+ const auto* hit_test_data = chunk.GetHitTestData();
+ if (!hit_test_data || hit_test_data->touch_action_rects.IsEmpty())
+ continue;
+
+ const auto& chunk_state = chunk.properties.GetPropertyTreeState();
+ for (auto touch_action_rect : hit_test_data->touch_action_rects) {
+ auto rect =
+ FloatClipRect(FloatRect(PixelSnappedIntRect(touch_action_rect.rect)));
+ if (!GeometryMapper::LocalToAncestorVisualRect(chunk_state, layer_state,
+ rect)) {
+ continue;
+ }
+ touch_action_rects_in_layer_space.emplace_back(TouchActionRect(
+ LayoutRect(rect.Rect()), touch_action_rect.whitelisted_touch_action));
+ }
+ }
+ layer.CcLayer()->SetTouchActionRegion(
+ TouchActionRect::BuildRegion(touch_action_rects_in_layer_space));
+}
+
static void ClearPositionConstraintExceptForLayer(GraphicsLayer* layer,
GraphicsLayer* except) {
if (layer && layer != except && GraphicsLayerToCcLayer(layer)) {
@@ -306,15 +366,13 @@ CreateScrollbarLayer(Scrollbar& scrollbar, float device_scale_factor) {
if (theme.UsesOverlayScrollbars() && theme.UsesNinePatchThumbResource()) {
auto scrollbar_layer = cc::PaintedOverlayScrollbarLayer::Create(
std::move(scrollbar_delegate), /*scroll_element_id=*/cc::ElementId());
- scrollbar_layer->SetElementId(
- CompositorElementIdFromUniqueObjectId(NewUniqueObjectId()));
+ scrollbar_layer->SetElementId(scrollbar.GetElementId());
layer_group->scrollbar_layer = scrollbar_layer.get();
layer_group->layer = std::move(scrollbar_layer);
} else {
auto scrollbar_layer = cc::PaintedScrollbarLayer::Create(
std::move(scrollbar_delegate), /*scroll_element_id=*/cc::ElementId());
- scrollbar_layer->SetElementId(
- CompositorElementIdFromUniqueObjectId(NewUniqueObjectId()));
+ scrollbar_layer->SetElementId(scrollbar.GetElementId());
layer_group->scrollbar_layer = scrollbar_layer.get();
layer_group->layer = std::move(scrollbar_layer);
}
@@ -329,14 +387,14 @@ ScrollingCoordinator::CreateSolidColorScrollbarLayer(
ScrollbarOrientation orientation,
int thumb_thickness,
int track_start,
- bool is_left_side_vertical_scrollbar) {
+ 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, cc::ElementId());
- scrollbar_layer->SetElementId(
- CompositorElementIdFromUniqueObjectId(NewUniqueObjectId()));
+ scrollbar_layer->SetElementId(element_id);
auto layer_group = std::make_unique<ScrollbarLayerGroup>();
layer_group->scrollbar_layer = scrollbar_layer.get();
@@ -427,7 +485,8 @@ void ScrollingCoordinator::ScrollableAreaScrollbarLayerDidChange(
group = CreateSolidColorScrollbarLayer(
orientation, scrollbar.GetTheme().ThumbThickness(scrollbar),
scrollbar.GetTheme().TrackPosition(scrollbar),
- scrollable_area->ShouldPlaceVerticalScrollbarOnLeft());
+ scrollable_area->ShouldPlaceVerticalScrollbarOnLeft(),
+ scrollable_area->GetScrollbarElementId(orientation));
} else {
group = CreateScrollbarLayer(scrollbar,
page_->DeviceScaleFactorDeprecated());
@@ -455,7 +514,7 @@ void ScrollingCoordinator::ScrollableAreaScrollbarLayerDidChange(
bool ScrollingCoordinator::UpdateCompositedScrollOffset(
ScrollableArea* scrollable_area) {
GraphicsLayer* scroll_layer = scrollable_area->LayerForScrolling();
- if (!scroll_layer || scroll_layer->GetScrollableArea() != scrollable_area)
+ if (!scroll_layer)
return false;
cc::Layer* cc_layer =
@@ -473,10 +532,6 @@ bool ScrollingCoordinator::ScrollableAreaScrollLayerDidChange(
if (!page_ || !page_->MainFrame())
return false;
- GraphicsLayer* scroll_layer = scrollable_area->LayerForScrolling();
- if (scroll_layer)
- scroll_layer->SetScrollableArea(scrollable_area);
-
UpdateUserInputScrollable(scrollable_area);
cc::Layer* cc_layer =
@@ -485,8 +540,7 @@ bool ScrollingCoordinator::ScrollableAreaScrollLayerDidChange(
GraphicsLayerToCcLayer(scrollable_area->LayerForContainer());
if (cc_layer) {
cc_layer->SetScrollable(container_layer->bounds());
- FloatPoint scroll_position(scrollable_area->ScrollOrigin() +
- scrollable_area->GetScrollOffset());
+ FloatPoint scroll_position(scrollable_area->ScrollPosition());
cc_layer->SetScrollOffset(static_cast<gfx::ScrollOffset>(scroll_position));
// TODO(bokan): This method shouldn't be resizing the layer geometry. That
// happens in CompositedLayerMapping::UpdateScrollingLayerGeometry.
@@ -503,17 +557,24 @@ bool ScrollingCoordinator::ScrollableAreaScrollLayerDidChange(
PixelSnappedIntRect(
LayoutRect(LayoutPoint(subpixel_accumulation), contents_size))
.Size();
- // The scrolling contents layer must be at least as large as the clip.
- scroll_contents_size = scroll_contents_size.ExpandedTo(IntSize(
- container_layer->bounds().width(), container_layer->bounds().height()));
- cc_layer->SetBounds(static_cast<gfx::Size>(scroll_contents_size));
- // VisualViewport scrolling may involve pinch zoom and gets routed through
- // WebViewImpl explicitly rather than via ScrollingCoordinator::DidScroll
- // since it needs to be set in tandem with the page scale delta.
+
if (scrollable_area != &page_->GetVisualViewport()) {
+ // The scrolling contents layer must be at least as large as its clip.
+ // The visual viewport is special because the size of its scrolling
+ // content depends on the page scale factor. Its scrollable content is
+ // the layout viewport which is sized based on the minimum allowed page
+ // scale so it actually can be smaller than its clip.
+ scroll_contents_size =
+ scroll_contents_size.ExpandedTo(IntSize(container_layer->bounds()));
+
+ // VisualViewport scrolling may involve pinch zoom and gets routed through
+ // WebViewImpl explicitly rather than via ScrollingCoordinator::DidScroll
+ // since it needs to be set in tandem with the page scale delta.
cc_layer->set_did_scroll_callback(WTF::BindRepeating(
&ScrollingCoordinator::DidScroll, WrapWeakPersistent(this)));
}
+
+ cc_layer->SetBounds(static_cast<gfx::Size>(scroll_contents_size));
}
if (ScrollbarLayerGroup* scrollbar_layer_group =
GetScrollbarLayerGroup(scrollable_area, kHorizontalScrollbar)) {
@@ -544,10 +605,7 @@ bool ScrollingCoordinator::ScrollableAreaScrollLayerDidChange(
// LocalFrameView::CompositorAnimationTimeline() can indirectly return
// m_programmaticScrollAnimatorTimeline if it does not have its own
// timeline.
- if (scrollable_area->IsLocalFrameView()) {
- timeline =
- ToLocalFrameView(scrollable_area)->GetCompositorAnimationTimeline();
- } else if (scrollable_area->IsPaintLayerScrollableArea()) {
+ if (scrollable_area->IsPaintLayerScrollableArea()) {
timeline = ToPaintLayerScrollableArea(scrollable_area)
->GetCompositorAnimationTimeline();
} else {
@@ -739,9 +797,15 @@ void ScrollingCoordinator::UpdateTouchEventTargetRectsIfNeeded(
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
return;
- LayerHitTestRects touch_event_target_rects;
- ComputeTouchEventTargetRects(frame, touch_event_target_rects);
- SetTouchEventTargetRects(frame, touch_event_target_rects);
+ if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()) {
+ auto* view_layer = frame->View()->GetLayoutView()->Layer();
+ if (auto* root = view_layer->Compositor()->PaintRootGraphicsLayer())
+ ForAllGraphicsLayers(*root, UpdateLayerTouchActionRects);
+ } else {
+ LayerHitTestRects touch_event_target_rects;
+ ComputeTouchEventTargetRects(frame, touch_event_target_rects);
+ SetTouchEventTargetRects(frame, touch_event_target_rects);
+ }
}
void ScrollingCoordinator::UpdateUserInputScrollable(
@@ -777,6 +841,8 @@ void ScrollingCoordinator::SetTouchEventTargetRects(
LayerHitTestRects& layer_rects) {
TRACE_EVENT0("input", "ScrollingCoordinator::setTouchEventTargetRects");
+ DCHECK(!RuntimeEnabledFeatures::PaintTouchActionRectsEnabled());
+
// Ensure we have an entry for each composited layer that previously had rects
// (so that old ones will get cleared out). Note that ideally we'd track this
// on GraphicsLayer instead of Layer, but we have no good hook into the
@@ -887,30 +953,26 @@ void ScrollingCoordinator::WillDestroyLayer(PaintLayer* layer) {
void ScrollingCoordinator::SetShouldUpdateScrollLayerPositionOnMainThread(
LocalFrame* frame,
MainThreadScrollingReasons main_thread_scrolling_reasons) {
- GraphicsLayer* visual_viewport_layer =
- frame->GetPage()->GetVisualViewport().ScrollLayer();
+ VisualViewport& visual_viewport = frame->GetPage()->GetVisualViewport();
+ GraphicsLayer* visual_viewport_layer = visual_viewport.ScrollLayer();
cc::Layer* visual_viewport_scroll_layer =
GraphicsLayerToCcLayer(visual_viewport_layer);
- GraphicsLayer* layer =
- frame->View()->LayoutViewportScrollableArea()->LayerForScrolling();
+ ScrollableArea* scrollable_area = frame->View()->LayoutViewport();
+ GraphicsLayer* layer = scrollable_area->LayerForScrolling();
if (cc::Layer* scroll_layer = GraphicsLayerToCcLayer(layer)) {
if (main_thread_scrolling_reasons) {
- ScrollableArea* scrollable_area = layer->GetScrollableArea();
- if (scrollable_area) {
- if (ScrollAnimatorBase* scroll_animator =
- scrollable_area->ExistingScrollAnimator()) {
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled() ||
- frame->GetDocument()->Lifecycle().GetState() >=
- DocumentLifecycle::kCompositingClean);
- scroll_animator->TakeOverCompositorAnimation();
- }
+ if (ScrollAnimatorBase* scroll_animator =
+ scrollable_area->ExistingScrollAnimator()) {
+ DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled() ||
+ frame->GetDocument()->Lifecycle().GetState() >=
+ DocumentLifecycle::kCompositingClean);
+ scroll_animator->TakeOverCompositorAnimation();
}
scroll_layer->AddMainThreadScrollingReasons(
main_thread_scrolling_reasons);
if (visual_viewport_scroll_layer) {
if (ScrollAnimatorBase* scroll_animator =
- visual_viewport_layer->GetScrollableArea()
- ->ExistingScrollAnimator()) {
+ visual_viewport.ExistingScrollAnimator()) {
DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled() ||
frame->GetDocument()->Lifecycle().GetState() >=
DocumentLifecycle::kCompositingClean);
@@ -937,13 +999,11 @@ void ScrollingCoordinator::SetShouldUpdateScrollLayerPositionOnMainThread(
void ScrollingCoordinator::LayerTreeViewInitialized(
WebLayerTreeView& layer_tree_view,
LocalFrameView* view) {
- if (Platform::Current()->IsThreadedAnimationEnabled() &&
- layer_tree_view.CompositorAnimationHost()) {
+ if (Platform::Current()->IsThreadedAnimationEnabled()) {
std::unique_ptr<CompositorAnimationTimeline> timeline =
CompositorAnimationTimeline::Create();
- std::unique_ptr<CompositorAnimationHost> host =
- std::make_unique<CompositorAnimationHost>(
- layer_tree_view.CompositorAnimationHost());
+ auto host = std::make_unique<CompositorAnimationHost>(
+ layer_tree_view.CompositorAnimationHost());
if (view && view->GetFrame().LocalFrameRoot() != page_->MainFrame()) {
view->GetScrollingContext()->SetAnimationHost(std::move(host));
view->GetScrollingContext()->SetAnimationTimeline(std::move(timeline));
@@ -1008,10 +1068,6 @@ Region ScrollingCoordinator::ComputeShouldHandleScrollGestureOnMainThreadRegion(
if (const LocalFrameView::ScrollableAreaSet* scrollable_areas =
frame_view->ScrollableAreas()) {
for (const ScrollableArea* scrollable_area : *scrollable_areas) {
- if (scrollable_area->IsLocalFrameView() &&
- ToLocalFrameView(scrollable_area)->ShouldThrottleRendering()) {
- continue;
- }
// Composited scrollable areas can be scrolled off the main thread.
if (scrollable_area->UsesCompositedScrolling())
continue;
@@ -1170,6 +1226,8 @@ void ScrollingCoordinator::ComputeTouchEventTargetRects(
LayerHitTestRects& rects) {
TRACE_EVENT0("input", "ScrollingCoordinator::computeTouchEventTargetRects");
+ DCHECK(!RuntimeEnabledFeatures::PaintTouchActionRectsEnabled());
+
Document* document = frame->GetDocument();
if (!document || !document->View() || !document->GetFrame())
return;
@@ -1226,9 +1284,8 @@ bool ScrollingCoordinator::IsForMainFrame(
return false;
// FIXME(305811): Refactor for OOPI.
- return scrollable_area == page_->DeprecatedLocalMainFrame()
- ->View()
- ->LayoutViewportScrollableArea();
+ return scrollable_area ==
+ page_->DeprecatedLocalMainFrame()->View()->LayoutViewport();
}
void ScrollingCoordinator::FrameViewRootLayerDidChange(
@@ -1250,11 +1307,10 @@ bool ScrollingCoordinator::FrameScrollerIsDirty(
if (cc::Layer* scroll_layer =
frame_view ? GraphicsLayerToCcLayer(
- frame_view->LayoutViewportScrollableArea()
- ->LayerForScrolling())
+ frame_view->LayoutViewport()->LayerForScrolling())
: nullptr) {
return static_cast<gfx::Size>(
- frame_view->LayoutViewportScrollableArea()->ContentsSize()) !=
+ frame_view->LayoutViewport()->ContentsSize()) !=
scroll_layer->bounds();
}
return false;
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 bc0d2bd73bc..68c91535359 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
@@ -104,7 +104,10 @@ class CORE_EXPORT ScrollingCoordinator final
// Called when any layoutBox has transform changed
void NotifyTransformChanged(LocalFrame*, const LayoutBox&);
- void UpdateAfterCompositingChangeIfNeeded(LocalFrameView*);
+ // Update non-fast scrollable regions, touch event target rects, main thread
+ // scrolling reasons, and whether the visual viewport is user scrollable.
+ // TODO(pdr): Refactor this out of ScrollingCoordinator.
+ void UpdateAfterPaint(LocalFrameView*);
// Should be called whenever the slow repaint objects counter changes between
// zero and one.
@@ -120,7 +123,8 @@ class CORE_EXPORT ScrollingCoordinator final
ScrollbarOrientation,
int thumb_thickness,
int track_start,
- bool is_left_side_vertical_scrollbar);
+ bool is_left_side_vertical_scrollbar,
+ cc::ElementId);
void WillDestroyScrollableArea(ScrollableArea*);
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc b/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
index c4b14b65134..1e48ae9bb27 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_test.cc
@@ -26,6 +26,7 @@
#include "build/build_config.h"
#include "cc/layers/layer_sticky_position_constraint.h"
+#include "cc/layers/picture_layer.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_cache.h"
@@ -49,6 +50,7 @@
#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_context.h"
#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/platform/geometry/int_point.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
@@ -59,9 +61,13 @@
namespace blink {
-class ScrollingCoordinatorTest : public testing::Test {
+class ScrollingCoordinatorTest : public testing::Test,
+ public testing::WithParamInterface<bool>,
+ private ScopedPaintTouchActionRectsForTest {
public:
- ScrollingCoordinatorTest() : base_url_("http://www.test.com/") {
+ ScrollingCoordinatorTest()
+ : ScopedPaintTouchActionRectsForTest(GetParam()),
+ base_url_("http://www.test.com/") {
helper_.Initialize(nullptr, nullptr, nullptr, &ConfigureSettings);
GetWebView()->Resize(IntSize(320, 240));
@@ -106,7 +112,7 @@ class ScrollingCoordinatorTest : public testing::Test {
cc::Layer* GetRootScrollLayer() {
GraphicsLayer* layer =
- GetFrame()->View()->LayoutViewportScrollableArea()->LayerForScrolling();
+ GetFrame()->View()->LayoutViewport()->LayerForScrolling();
return layer ? layer->CcLayer() : nullptr;
}
@@ -117,6 +123,8 @@ class ScrollingCoordinatorTest : public testing::Test {
return GetWebView()->LayerTreeView();
}
+ void LoadAhem() { helper_.LoadAhem(); }
+
protected:
std::string base_url_;
@@ -128,7 +136,9 @@ class ScrollingCoordinatorTest : public testing::Test {
FrameTestHelpers::WebViewHelper helper_;
};
-TEST_F(ScrollingCoordinatorTest, fastScrollingByDefault) {
+INSTANTIATE_TEST_CASE_P(All, ScrollingCoordinatorTest, ::testing::Bool());
+
+TEST_P(ScrollingCoordinatorTest, fastScrollingByDefault) {
GetWebView()->Resize(WebSize(800, 600));
LoadHTML("<div id='spacer' style='height: 1000px'></div>");
ForceFullCompositingUpdate();
@@ -144,21 +154,21 @@ TEST_F(ScrollingCoordinatorTest, fastScrollingByDefault) {
cc::Layer* root_scroll_layer = GetRootScrollLayer();
ASSERT_TRUE(root_scroll_layer);
ASSERT_TRUE(root_scroll_layer->scrollable());
- ASSERT_FALSE(root_scroll_layer->should_scroll_on_main_thread());
- ASSERT_EQ(WebEventListenerProperties::kNothing,
+ ASSERT_FALSE(root_scroll_layer->main_thread_scrolling_reasons());
+ ASSERT_EQ(cc::EventListenerProperties::kNone,
GetWebLayerTreeView()->EventListenerProperties(
- WebEventListenerClass::kTouchStartOrMove));
- ASSERT_EQ(WebEventListenerProperties::kNothing,
+ cc::EventListenerClass::kTouchStartOrMove));
+ ASSERT_EQ(cc::EventListenerProperties::kNone,
GetWebLayerTreeView()->EventListenerProperties(
- WebEventListenerClass::kMouseWheel));
+ cc::EventListenerClass::kMouseWheel));
cc::Layer* inner_viewport_scroll_layer =
page->GetVisualViewport().ScrollLayer()->CcLayer();
ASSERT_TRUE(inner_viewport_scroll_layer->scrollable());
- ASSERT_FALSE(inner_viewport_scroll_layer->should_scroll_on_main_thread());
+ ASSERT_FALSE(inner_viewport_scroll_layer->main_thread_scrolling_reasons());
}
-TEST_F(ScrollingCoordinatorTest, fastScrollingCanBeDisabledWithSetting) {
+TEST_P(ScrollingCoordinatorTest, fastScrollingCanBeDisabledWithSetting) {
GetWebView()->Resize(WebSize(800, 600));
LoadHTML("<div id='spacer' style='height: 1000px'></div>");
GetWebView()->GetSettings()->SetThreadedScrollingEnabled(false);
@@ -175,16 +185,16 @@ TEST_F(ScrollingCoordinatorTest, fastScrollingCanBeDisabledWithSetting) {
cc::Layer* root_scroll_layer = GetRootScrollLayer();
ASSERT_TRUE(root_scroll_layer);
ASSERT_TRUE(root_scroll_layer->scrollable());
- ASSERT_TRUE(root_scroll_layer->should_scroll_on_main_thread());
+ ASSERT_TRUE(root_scroll_layer->main_thread_scrolling_reasons());
// Main scrolling should also propagate to inner viewport layer.
cc::Layer* inner_viewport_scroll_layer =
page->GetVisualViewport().ScrollLayer()->CcLayer();
ASSERT_TRUE(inner_viewport_scroll_layer->scrollable());
- ASSERT_TRUE(inner_viewport_scroll_layer->should_scroll_on_main_thread());
+ ASSERT_TRUE(inner_viewport_scroll_layer->main_thread_scrolling_reasons());
}
-TEST_F(ScrollingCoordinatorTest, fastFractionalScrollingDiv) {
+TEST_P(ScrollingCoordinatorTest, fastFractionalScrollingDiv) {
ScopedFractionalScrollOffsetsForTest fractional_scroll_offsets(true);
RegisterMockedHttpURLLoad("fractional-scroll-div.html");
@@ -216,8 +226,8 @@ TEST_F(ScrollingCoordinatorTest, fastFractionalScrollingDiv) {
cc::Layer* cc_scroll_layer =
composited_layer_mapping->ScrollingContentsLayer()->CcLayer();
ASSERT_TRUE(cc_scroll_layer);
- ASSERT_NEAR(1.2f, cc_scroll_layer->scroll_offset().x(), 0.01f);
- ASSERT_NEAR(1.2f, cc_scroll_layer->scroll_offset().y(), 0.01f);
+ ASSERT_NEAR(1.2f, cc_scroll_layer->CurrentScrollOffset().x(), 0.01f);
+ ASSERT_NEAR(1.2f, cc_scroll_layer->CurrentScrollOffset().y(), 0.01f);
}
static cc::Layer* CcLayerFromElement(Element* element) {
@@ -239,7 +249,7 @@ static cc::Layer* CcLayerFromElement(Element* element) {
return graphics_layer->CcLayer();
}
-TEST_F(ScrollingCoordinatorTest, fastScrollingForFixedPosition) {
+TEST_P(ScrollingCoordinatorTest, fastScrollingForFixedPosition) {
RegisterMockedHttpURLLoad("fixed-position.html");
NavigateTo(base_url_ + "fixed-position.html");
ForceFullCompositingUpdate();
@@ -247,7 +257,7 @@ TEST_F(ScrollingCoordinatorTest, fastScrollingForFixedPosition) {
// Fixed position should not fall back to main thread scrolling.
cc::Layer* root_scroll_layer = GetRootScrollLayer();
ASSERT_TRUE(root_scroll_layer);
- ASSERT_FALSE(root_scroll_layer->should_scroll_on_main_thread());
+ ASSERT_FALSE(root_scroll_layer->main_thread_scrolling_reasons());
Document* document = GetFrame()->GetDocument();
{
@@ -332,7 +342,7 @@ TEST_F(ScrollingCoordinatorTest, fastScrollingForFixedPosition) {
}
}
-TEST_F(ScrollingCoordinatorTest, fastScrollingForStickyPosition) {
+TEST_P(ScrollingCoordinatorTest, fastScrollingForStickyPosition) {
RegisterMockedHttpURLLoad("sticky-position.html");
NavigateTo(base_url_ + "sticky-position.html");
ForceFullCompositingUpdate();
@@ -340,7 +350,7 @@ TEST_F(ScrollingCoordinatorTest, fastScrollingForStickyPosition) {
// Sticky position should not fall back to main thread scrolling.
cc::Layer* root_scroll_layer = GetRootScrollLayer();
ASSERT_TRUE(root_scroll_layer);
- EXPECT_FALSE(root_scroll_layer->should_scroll_on_main_thread());
+ EXPECT_FALSE(root_scroll_layer->main_thread_scrolling_reasons());
Document* document = GetFrame()->GetDocument();
{
@@ -437,67 +447,127 @@ TEST_F(ScrollingCoordinatorTest, fastScrollingForStickyPosition) {
}
}
-TEST_F(ScrollingCoordinatorTest, touchEventHandler) {
+TEST_P(ScrollingCoordinatorTest, elementPointerEventHandler) {
+ LoadHTML(R"HTML(
+ <div id="pointer" style="width: 100px; height: 100px;"></div>
+ <script>
+ pointer.addEventListener('pointerdown', function(event) {
+ }, {blocking: false} );
+ </script>
+ )HTML");
+ ForceFullCompositingUpdate();
+
+ auto* layout_view = GetFrame()->View()->GetLayoutView();
+ auto* mapping = layout_view->Layer()->GetCompositedLayerMapping();
+ GraphicsLayer* graphics_layer = mapping->ScrollingContentsLayer();
+ cc::Layer* cc_layer = graphics_layer->CcLayer();
+
+ // Pointer event handlers should not generate blocking touch action regions.
+ cc::Region region = cc_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionNone);
+ EXPECT_TRUE(region.IsEmpty());
+}
+
+TEST_P(ScrollingCoordinatorTest, touchEventHandler) {
RegisterMockedHttpURLLoad("touch-event-handler.html");
NavigateTo(base_url_ + "touch-event-handler.html");
ForceFullCompositingUpdate();
- ASSERT_EQ(WebEventListenerProperties::kBlocking,
+ ASSERT_EQ(cc::EventListenerProperties::kBlocking,
GetWebLayerTreeView()->EventListenerProperties(
- WebEventListenerClass::kTouchStartOrMove));
+ cc::EventListenerClass::kTouchStartOrMove));
+}
+
+TEST_P(ScrollingCoordinatorTest, elementBlockingTouchEventHandler) {
+ LoadHTML(R"HTML(
+ <div id="blocking" style="width: 100px; height: 100px;"></div>
+ <script>
+ blocking.addEventListener('touchstart', function(event) {
+ }, {passive: false} );
+ </script>
+ )HTML");
+ ForceFullCompositingUpdate();
+
+ auto* layout_view = GetFrame()->View()->GetLayoutView();
+ auto* mapping = layout_view->Layer()->GetCompositedLayerMapping();
+ cc::Layer* cc_layer = mapping->ScrollingContentsLayer()->CcLayer();
+ cc::Region region = cc_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionNone);
+ EXPECT_EQ(region.bounds(), gfx::Rect(8, 8, 100, 100));
}
-TEST_F(ScrollingCoordinatorTest, touchEventHandlerPassive) {
+TEST_P(ScrollingCoordinatorTest, touchEventHandlerPassive) {
RegisterMockedHttpURLLoad("touch-event-handler-passive.html");
NavigateTo(base_url_ + "touch-event-handler-passive.html");
ForceFullCompositingUpdate();
- ASSERT_EQ(WebEventListenerProperties::kPassive,
+ ASSERT_EQ(cc::EventListenerProperties::kPassive,
GetWebLayerTreeView()->EventListenerProperties(
- WebEventListenerClass::kTouchStartOrMove));
+ cc::EventListenerClass::kTouchStartOrMove));
}
-TEST_F(ScrollingCoordinatorTest, touchEventHandlerBoth) {
+TEST_P(ScrollingCoordinatorTest, elementTouchEventHandlerPassive) {
+ LoadHTML(R"HTML(
+ <div id="passive" style="width: 100px; height: 100px;"></div>
+ <script>
+ passive.addEventListener('touchstart', function(event) {
+ }, {passive: true} );
+ </script>
+ )HTML");
+ ForceFullCompositingUpdate();
+
+ auto* layout_view = GetFrame()->View()->GetLayoutView();
+ auto* mapping = layout_view->Layer()->GetCompositedLayerMapping();
+ GraphicsLayer* graphics_layer = mapping->ScrollingContentsLayer();
+ cc::Layer* cc_layer = graphics_layer->CcLayer();
+
+ // Passive event handlers should not generate blocking touch action regions.
+ cc::Region region = cc_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionNone);
+ EXPECT_TRUE(region.IsEmpty());
+}
+
+TEST_P(ScrollingCoordinatorTest, touchEventHandlerBoth) {
RegisterMockedHttpURLLoad("touch-event-handler-both.html");
NavigateTo(base_url_ + "touch-event-handler-both.html");
ForceFullCompositingUpdate();
- ASSERT_EQ(WebEventListenerProperties::kBlockingAndPassive,
+ ASSERT_EQ(cc::EventListenerProperties::kBlockingAndPassive,
GetWebLayerTreeView()->EventListenerProperties(
- WebEventListenerClass::kTouchStartOrMove));
+ cc::EventListenerClass::kTouchStartOrMove));
}
-TEST_F(ScrollingCoordinatorTest, wheelEventHandler) {
+TEST_P(ScrollingCoordinatorTest, wheelEventHandler) {
RegisterMockedHttpURLLoad("wheel-event-handler.html");
NavigateTo(base_url_ + "wheel-event-handler.html");
ForceFullCompositingUpdate();
- ASSERT_EQ(WebEventListenerProperties::kBlocking,
+ ASSERT_EQ(cc::EventListenerProperties::kBlocking,
GetWebLayerTreeView()->EventListenerProperties(
- WebEventListenerClass::kMouseWheel));
+ cc::EventListenerClass::kMouseWheel));
}
-TEST_F(ScrollingCoordinatorTest, wheelEventHandlerPassive) {
+TEST_P(ScrollingCoordinatorTest, wheelEventHandlerPassive) {
RegisterMockedHttpURLLoad("wheel-event-handler-passive.html");
NavigateTo(base_url_ + "wheel-event-handler-passive.html");
ForceFullCompositingUpdate();
- ASSERT_EQ(WebEventListenerProperties::kPassive,
+ ASSERT_EQ(cc::EventListenerProperties::kPassive,
GetWebLayerTreeView()->EventListenerProperties(
- WebEventListenerClass::kMouseWheel));
+ cc::EventListenerClass::kMouseWheel));
}
-TEST_F(ScrollingCoordinatorTest, wheelEventHandlerBoth) {
+TEST_P(ScrollingCoordinatorTest, wheelEventHandlerBoth) {
RegisterMockedHttpURLLoad("wheel-event-handler-both.html");
NavigateTo(base_url_ + "wheel-event-handler-both.html");
ForceFullCompositingUpdate();
- ASSERT_EQ(WebEventListenerProperties::kBlockingAndPassive,
+ ASSERT_EQ(cc::EventListenerProperties::kBlockingAndPassive,
GetWebLayerTreeView()->EventListenerProperties(
- WebEventListenerClass::kMouseWheel));
+ cc::EventListenerClass::kMouseWheel));
}
-TEST_F(ScrollingCoordinatorTest, scrollEventHandler) {
+TEST_P(ScrollingCoordinatorTest, scrollEventHandler) {
RegisterMockedHttpURLLoad("scroll-event-handler.html");
NavigateTo(base_url_ + "scroll-event-handler.html");
ForceFullCompositingUpdate();
@@ -505,7 +575,7 @@ TEST_F(ScrollingCoordinatorTest, scrollEventHandler) {
ASSERT_TRUE(GetWebLayerTreeView()->HaveScrollEventHandlers());
}
-TEST_F(ScrollingCoordinatorTest, updateEventHandlersDuringTeardown) {
+TEST_P(ScrollingCoordinatorTest, updateEventHandlersDuringTeardown) {
RegisterMockedHttpURLLoad("scroll-event-handler-window.html");
NavigateTo(base_url_ + "scroll-event-handler-window.html");
ForceFullCompositingUpdate();
@@ -515,7 +585,7 @@ TEST_F(ScrollingCoordinatorTest, updateEventHandlersDuringTeardown) {
GetFrame()->GetDocument()->Shutdown();
}
-TEST_F(ScrollingCoordinatorTest, clippedBodyTest) {
+TEST_P(ScrollingCoordinatorTest, clippedBodyTest) {
RegisterMockedHttpURLLoad("clipped-body.html");
NavigateTo(base_url_ + "clipped-body.html");
ForceFullCompositingUpdate();
@@ -525,7 +595,7 @@ TEST_F(ScrollingCoordinatorTest, clippedBodyTest) {
EXPECT_TRUE(root_scroll_layer->non_fast_scrollable_region().IsEmpty());
}
-TEST_F(ScrollingCoordinatorTest, touchAction) {
+TEST_P(ScrollingCoordinatorTest, touchAction) {
RegisterMockedHttpURLLoad("touch-action.html");
NavigateTo(base_url_ + "touch-action.html");
ForceFullCompositingUpdate();
@@ -539,7 +609,12 @@ TEST_F(ScrollingCoordinatorTest, touchAction) {
CompositedLayerMapping* composited_layer_mapping =
box->Layer()->GetCompositedLayerMapping();
- GraphicsLayer* graphics_layer = composited_layer_mapping->MainGraphicsLayer();
+ // Without PaintTouchActionRects, rects are on the wrong graphics layer. See:
+ // https://crbug.com/826746.
+ auto* graphics_layer =
+ RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()
+ ? composited_layer_mapping->ScrollingContentsLayer()
+ : composited_layer_mapping->MainGraphicsLayer();
cc::Layer* cc_layer = graphics_layer->CcLayer();
cc::Region region = cc_layer->touch_action_region().GetRegionForTouchAction(
TouchAction::kTouchActionPanX | TouchAction::kTouchActionPanDown);
@@ -547,7 +622,7 @@ TEST_F(ScrollingCoordinatorTest, touchAction) {
EXPECT_EQ(region.bounds(), gfx::Rect(0, 0, 1000, 1000));
}
-TEST_F(ScrollingCoordinatorTest, touchActionRegions) {
+TEST_P(ScrollingCoordinatorTest, touchActionRegions) {
RegisterMockedHttpURLLoad("touch-action-regions.html");
NavigateTo(base_url_ + "touch-action-regions.html");
ForceFullCompositingUpdate();
@@ -561,7 +636,12 @@ TEST_F(ScrollingCoordinatorTest, touchActionRegions) {
CompositedLayerMapping* composited_layer_mapping =
box->Layer()->GetCompositedLayerMapping();
- GraphicsLayer* graphics_layer = composited_layer_mapping->MainGraphicsLayer();
+ // Without PaintTouchActionRects, rects are on the wrong graphics layer. See:
+ // https://crbug.com/826746.
+ auto* graphics_layer =
+ RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()
+ ? composited_layer_mapping->ScrollingContentsLayer()
+ : composited_layer_mapping->MainGraphicsLayer();
cc::Layer* cc_layer = graphics_layer->CcLayer();
cc::Region region = cc_layer->touch_action_region().GetRegionForTouchAction(
@@ -580,7 +660,216 @@ TEST_F(ScrollingCoordinatorTest, touchActionRegions) {
EXPECT_EQ(region.bounds(), gfx::Rect(0, 100, 100, 100));
}
-TEST_F(ScrollingCoordinatorTest, touchActionBlockingHandler) {
+TEST_P(ScrollingCoordinatorTest, touchActionNesting) {
+ LoadHTML(R"HTML(
+ <style>
+ #scrollable {
+ width: 200px;
+ height: 200px;
+ overflow: scroll;
+ }
+ #touchaction {
+ touch-action: pan-x;
+ width: 100px;
+ height: 100px;
+ margin: 5px;
+ }
+ #child {
+ width: 150px;
+ height: 50px;
+ }
+ </style>
+ <div id="scrollable">
+ <div id="touchaction">
+ <div id="child"></div>
+ </div>
+ <div id="forcescroll" style="width: 1000px; height: 1000px;"></div>
+ </div>
+ )HTML");
+ ForceFullCompositingUpdate();
+
+ auto* scrollable = GetFrame()->GetDocument()->getElementById("scrollable");
+ auto* box = ToLayoutBox(scrollable->GetLayoutObject());
+ auto* composited_layer_mapping = box->Layer()->GetCompositedLayerMapping();
+
+ // Without PaintTouchActionRects, rects are on the wrong graphics layer. See:
+ // https://crbug.com/826746.
+ auto* graphics_layer =
+ RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()
+ ? composited_layer_mapping->ScrollingContentsLayer()
+ : composited_layer_mapping->MainGraphicsLayer();
+ cc::Layer* cc_layer = graphics_layer->CcLayer();
+
+ cc::Region region = cc_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionPanX);
+ EXPECT_EQ(region.GetRegionComplexity(), 2);
+ EXPECT_EQ(region.bounds(), gfx::Rect(5, 5, 150, 100));
+}
+
+TEST_P(ScrollingCoordinatorTest, nestedTouchActionInvalidation) {
+ LoadHTML(R"HTML(
+ <style>
+ #scrollable {
+ width: 200px;
+ height: 200px;
+ overflow: scroll;
+ }
+ #touchaction {
+ touch-action: pan-x;
+ width: 100px;
+ height: 100px;
+ margin: 5px;
+ }
+ #child {
+ width: 150px;
+ height: 50px;
+ }
+ </style>
+ <div id="scrollable">
+ <div id="touchaction">
+ <div id="child"></div>
+ </div>
+ <div id="forcescroll" style="width: 1000px; height: 1000px;"></div>
+ </div>
+ )HTML");
+ ForceFullCompositingUpdate();
+
+ auto* scrollable = GetFrame()->GetDocument()->getElementById("scrollable");
+ auto* box = ToLayoutBox(scrollable->GetLayoutObject());
+ auto* composited_layer_mapping = box->Layer()->GetCompositedLayerMapping();
+
+ // Without PaintTouchActionRects, rects are on the wrong graphics layer. See:
+ // https://crbug.com/826746.
+ GraphicsLayer* graphics_layer =
+ RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()
+ ? composited_layer_mapping->ScrollingContentsLayer()
+ : composited_layer_mapping->MainGraphicsLayer();
+ cc::Layer* cc_layer = graphics_layer->CcLayer();
+
+ cc::Region region = cc_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionPanX);
+ EXPECT_EQ(region.GetRegionComplexity(), 2);
+ EXPECT_EQ(region.bounds(), gfx::Rect(5, 5, 150, 100));
+
+ scrollable->setAttribute("style", "touch-action: none", ASSERT_NO_EXCEPTION);
+ ForceFullCompositingUpdate();
+ region = cc_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionPanX);
+ EXPECT_TRUE(region.IsEmpty());
+}
+
+// Similar to nestedTouchActionInvalidation but tests that an ancestor with
+// touch-action: pan-x and a descendant with touch-action: pan-y results in a
+// touch-action rect of none for the descendant.
+TEST_P(ScrollingCoordinatorTest, nestedTouchActionChangesUnion) {
+ LoadHTML(R"HTML(
+ <style>
+ #ancestor {
+ width: 100px;
+ height: 100px;
+ }
+ #child {
+ touch-action: pan-x;
+ width: 150px;
+ height: 50px;
+ }
+ </style>
+ <div id="ancestor">
+ <div id="child"></div>
+ </div>
+ )HTML");
+ ForceFullCompositingUpdate();
+
+ auto* layout_view = GetFrame()->View()->GetLayoutView();
+ auto* mapping = layout_view->Layer()->GetCompositedLayerMapping();
+ GraphicsLayer* graphics_layer = mapping->ScrollingContentsLayer();
+ cc::Layer* cc_layer = graphics_layer->CcLayer();
+
+ cc::Region region = cc_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionPanX);
+ EXPECT_EQ(region.bounds(), gfx::Rect(8, 8, 150, 50));
+ region = cc_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionNone);
+ EXPECT_TRUE(region.IsEmpty());
+
+ Element* ancestor = GetFrame()->GetDocument()->getElementById("ancestor");
+ ancestor->setAttribute("style", "touch-action: pan-y", ASSERT_NO_EXCEPTION);
+ ForceFullCompositingUpdate();
+
+ region = cc_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionPanY);
+ EXPECT_EQ(region.bounds(), gfx::Rect(8, 8, 100, 100));
+ region = cc_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionPanX);
+ EXPECT_TRUE(region.IsEmpty());
+ region = cc_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionNone);
+ EXPECT_EQ(region.bounds(), gfx::Rect(8, 8, 150, 50));
+}
+
+// Box shadow is not hit testable and should not be included in touch action.
+TEST_P(ScrollingCoordinatorTest, touchActionExcludesBoxShadow) {
+ LoadHTML(R"HTML(
+ <style>
+ #shadow {
+ width: 100px;
+ height: 100px;
+ touch-action: none;
+ box-shadow: 10px 5px 5px red;
+ }
+ </style>
+ <div id="shadow"></div>
+ )HTML");
+ ForceFullCompositingUpdate();
+
+ auto* layout_view = GetFrame()->View()->GetLayoutView();
+ auto* mapping = layout_view->Layer()->GetCompositedLayerMapping();
+ GraphicsLayer* graphics_layer = mapping->ScrollingContentsLayer();
+ cc::Layer* cc_layer = graphics_layer->CcLayer();
+
+ cc::Region region = cc_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionNone);
+ EXPECT_EQ(region.bounds(), gfx::Rect(8, 8, 100, 100));
+}
+
+TEST_P(ScrollingCoordinatorTest, touchActionOnInline) {
+ RegisterMockedHttpURLLoad("touch-action-on-inline.html");
+ NavigateTo(base_url_ + "touch-action-on-inline.html");
+ LoadAhem();
+ ForceFullCompositingUpdate();
+
+ auto* layout_view = GetFrame()->View()->GetLayoutView();
+ auto* mapping = layout_view->Layer()->GetCompositedLayerMapping();
+ GraphicsLayer* graphics_layer = mapping->ScrollingContentsLayer();
+ cc::Layer* cc_layer = graphics_layer->CcLayer();
+
+ cc::Region region = cc_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionNone);
+ EXPECT_EQ(region.bounds(), gfx::Rect(8, 8, 80, 50));
+}
+
+TEST_P(ScrollingCoordinatorTest, touchActionWithVerticalRLWritingMode) {
+ // Touch action rects are incorrect with vertical-rl. See: crbug.com/852013.
+ // This is fixed with PaintTouchActionRects.
+ if (!RuntimeEnabledFeatures::PaintTouchActionRectsEnabled())
+ return;
+
+ RegisterMockedHttpURLLoad("touch-action-with-vertical-rl-writing-mode.html");
+ NavigateTo(base_url_ + "touch-action-with-vertical-rl-writing-mode.html");
+ LoadAhem();
+ ForceFullCompositingUpdate();
+
+ auto* layout_view = GetFrame()->View()->GetLayoutView();
+ auto* mapping = layout_view->Layer()->GetCompositedLayerMapping();
+ GraphicsLayer* graphics_layer = mapping->ScrollingContentsLayer();
+ cc::Layer* cc_layer = graphics_layer->CcLayer();
+
+ cc::Region region = cc_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionNone);
+ EXPECT_EQ(region.bounds(), gfx::Rect(292, 8, 20, 80));
+}
+
+TEST_P(ScrollingCoordinatorTest, touchActionBlockingHandler) {
RegisterMockedHttpURLLoad("touch-action-blocking-handler.html");
NavigateTo(base_url_ + "touch-action-blocking-handler.html");
ForceFullCompositingUpdate();
@@ -594,7 +883,12 @@ TEST_F(ScrollingCoordinatorTest, touchActionBlockingHandler) {
CompositedLayerMapping* composited_layer_mapping =
box->Layer()->GetCompositedLayerMapping();
- GraphicsLayer* graphics_layer = composited_layer_mapping->MainGraphicsLayer();
+ // Without PaintTouchActionRects, rects are on the wrong graphics layer. See:
+ // https://crbug.com/826746.
+ auto* graphics_layer =
+ RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()
+ ? composited_layer_mapping->ScrollingContentsLayer()
+ : composited_layer_mapping->MainGraphicsLayer();
cc::Layer* cc_layer = graphics_layer->CcLayer();
cc::Region region = cc_layer->touch_action_region().GetRegionForTouchAction(
@@ -604,34 +898,92 @@ TEST_F(ScrollingCoordinatorTest, touchActionBlockingHandler) {
region = cc_layer->touch_action_region().GetRegionForTouchAction(
TouchAction::kTouchActionPanY);
- EXPECT_EQ(region.GetRegionComplexity(), 1);
+ EXPECT_EQ(region.GetRegionComplexity(), 2);
EXPECT_EQ(region.bounds(), gfx::Rect(0, 0, 1000, 1000));
}
-TEST_F(ScrollingCoordinatorTest, IframeWindowTouchHandler) {
+TEST_P(ScrollingCoordinatorTest, touchActionOnScrollingElement) {
+ LoadHTML(R"HTML(
+ <style>
+ #scrollable {
+ width: 100px;
+ height: 100px;
+ overflow: scroll;
+ touch-action: pan-y;
+ }
+ #child {
+ width: 50px;
+ height: 150px;
+ }
+ </style>
+ <div id="scrollable">
+ <div id="child"></div>
+ </div>
+ )HTML");
+ ForceFullCompositingUpdate();
+
+ Element* scrollable_element =
+ GetFrame()->GetDocument()->getElementById("scrollable");
+ LayoutBox* box = ToLayoutBox(scrollable_element->GetLayoutObject());
+ auto* composited_layer_mapping = box->Layer()->GetCompositedLayerMapping();
+
+ if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()) {
+ // With PaintTouchActionRects the outer layer (not scrollable) will be fully
+ // marked as pan-y (100x100) and the scrollable layer will only have the
+ // contents marked as pan-y (50x150).
+ auto* scrolling_contents_layer =
+ composited_layer_mapping->ScrollingContentsLayer()->CcLayer();
+ cc::Region region =
+ scrolling_contents_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionPanY);
+ EXPECT_EQ(region.bounds(), gfx::Rect(0, 0, 50, 150));
+
+ auto* non_scrolling_layer =
+ composited_layer_mapping->MainGraphicsLayer()->CcLayer();
+ region = non_scrolling_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionPanY);
+ EXPECT_EQ(region.bounds(), gfx::Rect(0, 0, 100, 100));
+ } else {
+ // Without PaintTouchActionRects, the main graphics layer gets all touch
+ // action rects.
+ auto* main_graphics_layer =
+ composited_layer_mapping->MainGraphicsLayer()->CcLayer();
+ cc::Region region =
+ main_graphics_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionPanY);
+ EXPECT_EQ(region.bounds(), gfx::Rect(0, 0, 100, 150));
+ }
+}
+
+TEST_P(ScrollingCoordinatorTest, IframeWindowTouchHandler) {
LoadHTML(
R"(<iframe style="width: 275px; height: 250px;"></iframe>)");
WebLocalFrameImpl* child_frame =
ToWebLocalFrameImpl(GetWebView()->MainFrameImpl()->FirstChild());
- FrameTestHelpers::LoadHTMLString(child_frame,
- R"(<body>
- <p style="margin: 1000px"> Hello </p>
- <script>
- window.addEventListener('touchstart', (e) => {
- e.preventDefault();
- }, {passive: false});
- </script>
- </body>)",
+ FrameTestHelpers::LoadHTMLString(child_frame, R"HTML(
+ <p style="margin: 1000px"> Hello </p>
+ <script>
+ window.addEventListener('touchstart', (e) => {
+ e.preventDefault();
+ }, {passive: false});
+ </script>
+ )HTML",
URLTestHelpers::ToKURL("about:blank"));
ForceFullCompositingUpdate();
PaintLayer* paint_layer_child_frame =
child_frame->GetFrame()->GetDocument()->GetLayoutView()->Layer();
+ auto* child_mapping = paint_layer_child_frame->GetCompositedLayerMapping();
+ // With PaintTouchActionRects, touch action regions are stored on the layer
+ // that draws the background whereas without PaintTouchActionRects the main
+ // graphics layer is used.
+ auto* child_graphics_layer =
+ RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()
+ ? child_mapping->ScrollingContentsLayer()
+ : child_mapping->MainGraphicsLayer();
+
cc::Region region_child_frame =
- paint_layer_child_frame
- ->EnclosingLayerForPaintInvalidationCrossingFrameBoundaries()
- ->GraphicsLayerBacking(&paint_layer_child_frame->GetLayoutObject())
- ->CcLayer()
+ child_graphics_layer->CcLayer()
->touch_action_region()
.GetRegionForTouchAction(TouchAction::kTouchActionNone);
PaintLayer* paint_layer_main_frame = GetWebView()
@@ -651,11 +1003,105 @@ TEST_F(ScrollingCoordinatorTest, IframeWindowTouchHandler) {
EXPECT_FALSE(region_child_frame.bounds().IsEmpty());
// We only check for the content size for verification as the offset is 0x0
// due to child frame having its own composited layer.
- EXPECT_EQ(child_frame->GetFrameView()->ContentsSize(),
- IntRect(region_child_frame.bounds()).Size());
+ if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()) {
+ // Because PaintTouchActionRects is painting the touch action rects on the
+ // scrolling contents layer, the size of the rect should be equal to the
+ // entire scrolling contents area.
+ EXPECT_EQ(child_graphics_layer->Size(),
+ IntSize(region_child_frame.bounds().size()));
+ } else {
+ EXPECT_EQ(child_frame->GetFrameView()->Size(),
+ IntRect(region_child_frame.bounds()).Size());
+ }
+}
+
+TEST_P(ScrollingCoordinatorTest, WindowTouchEventHandler) {
+ LoadHTML(R"HTML(
+ <style>
+ html { width: 200px; height: 200px; }
+ body { width: 100px; height: 100px; }
+ </style>
+ <script>
+ window.addEventListener('touchstart', function(event) {
+ event.preventDefault();
+ }, {passive: false} );
+ </script>
+ )HTML");
+ ForceFullCompositingUpdate();
+
+ auto* layout_view = GetFrame()->View()->GetLayoutView();
+ auto* mapping = layout_view->Layer()->GetCompositedLayerMapping();
+ // With PaintTouchActionRects, touch action regions are stored on the layer
+ // that draws the background whereas without PaintTouchActionRects the main
+ // graphics layer is used.
+ auto* graphics_layer = RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()
+ ? mapping->ScrollingContentsLayer()
+ : mapping->MainGraphicsLayer();
+
+ // The touch action region should include the entire frame, even though the
+ // document is smaller than the frame.
+ cc::Region region =
+ graphics_layer->CcLayer()->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionNone);
+ EXPECT_EQ(region.bounds(), gfx::Rect(0, 0, 320, 240));
+}
+
+namespace {
+class ScrollingCoordinatorMockEventListener final : public EventListener {
+ public:
+ ScrollingCoordinatorMockEventListener()
+ : EventListener(kCPPEventListenerType) {}
+
+ bool operator==(const EventListener& other) const final {
+ return this == &other;
+ }
+
+ void handleEvent(ExecutionContext*, Event*) final {}
+};
+} // namespace
+
+TEST_P(ScrollingCoordinatorTest, WindowTouchEventHandlerInvalidation) {
+ LoadHTML("");
+ ForceFullCompositingUpdate();
+
+ auto* layout_view = GetFrame()->View()->GetLayoutView();
+ auto* mapping = layout_view->Layer()->GetCompositedLayerMapping();
+ // With PaintTouchActionRects, touch action regions are stored on the layer
+ // that draws the background whereas without PaintTouchActionRects the main
+ // graphics layer is used. Both approaches can implement correct behavior for
+ // window event handlers.
+ auto* graphics_layer = RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()
+ ? mapping->ScrollingContentsLayer()
+ : mapping->MainGraphicsLayer();
+ auto* cc_layer = graphics_layer->CcLayer();
+
+ // Initially there are no touch action regions.
+ auto region = cc_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionNone);
+ EXPECT_TRUE(region.IsEmpty());
+
+ // Adding a blocking window event handler should create a touch action region.
+ auto* listener = new ScrollingCoordinatorMockEventListener();
+ AddEventListenerOptions options;
+ options.setPassive(false);
+ AddEventListenerOptionsResolved resolved_options(options);
+ GetFrame()->DomWindow()->addEventListener(EventTypeNames::touchstart,
+ listener, resolved_options);
+ ForceFullCompositingUpdate();
+ region = cc_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionNone);
+ EXPECT_FALSE(region.IsEmpty());
+
+ // Removing the window event handler also removes the blocking touch action
+ // region.
+ GetFrame()->DomWindow()->RemoveAllEventListeners();
+ ForceFullCompositingUpdate();
+ region = cc_layer->touch_action_region().GetRegionForTouchAction(
+ TouchAction::kTouchActionNone);
+ EXPECT_TRUE(region.IsEmpty());
}
-TEST_F(ScrollingCoordinatorTest, overflowScrolling) {
+TEST_P(ScrollingCoordinatorTest, overflowScrolling) {
RegisterMockedHttpURLLoad("overflow-scrolling.html");
NavigateTo(base_url_ + "overflow-scrolling.html");
ForceFullCompositingUpdate();
@@ -679,11 +1125,6 @@ TEST_F(ScrollingCoordinatorTest, overflowScrolling) {
ASSERT_TRUE(composited_layer_mapping->HasScrollingLayer());
DCHECK(composited_layer_mapping->ScrollingContentsLayer());
- GraphicsLayer* graphics_layer =
- composited_layer_mapping->ScrollingContentsLayer();
- ASSERT_EQ(box->Layer()->GetScrollableArea(),
- graphics_layer->GetScrollableArea());
-
cc::Layer* cc_scroll_layer =
composited_layer_mapping->ScrollingContentsLayer()->CcLayer();
ASSERT_TRUE(cc_scroll_layer->scrollable());
@@ -701,7 +1142,7 @@ TEST_F(ScrollingCoordinatorTest, overflowScrolling) {
#endif
}
-TEST_F(ScrollingCoordinatorTest, overflowHidden) {
+TEST_P(ScrollingCoordinatorTest, overflowHidden) {
RegisterMockedHttpURLLoad("overflow-hidden.html");
NavigateTo(base_url_ + "overflow-hidden.html");
ForceFullCompositingUpdate();
@@ -725,11 +1166,6 @@ TEST_F(ScrollingCoordinatorTest, overflowHidden) {
ASSERT_TRUE(composited_layer_mapping->HasScrollingLayer());
DCHECK(composited_layer_mapping->ScrollingContentsLayer());
- GraphicsLayer* graphics_layer =
- composited_layer_mapping->ScrollingContentsLayer();
- ASSERT_EQ(box->Layer()->GetScrollableArea(),
- graphics_layer->GetScrollableArea());
-
cc::Layer* cc_scroll_layer =
composited_layer_mapping->ScrollingContentsLayer()->CcLayer();
ASSERT_TRUE(cc_scroll_layer->scrollable());
@@ -752,10 +1188,6 @@ TEST_F(ScrollingCoordinatorTest, overflowHidden) {
ASSERT_TRUE(composited_layer_mapping->HasScrollingLayer());
DCHECK(composited_layer_mapping->ScrollingContentsLayer());
- graphics_layer = composited_layer_mapping->ScrollingContentsLayer();
- ASSERT_EQ(box->Layer()->GetScrollableArea(),
- graphics_layer->GetScrollableArea());
-
cc_scroll_layer =
composited_layer_mapping->ScrollingContentsLayer()->CcLayer();
ASSERT_TRUE(cc_scroll_layer->scrollable());
@@ -763,7 +1195,7 @@ TEST_F(ScrollingCoordinatorTest, overflowHidden) {
ASSERT_TRUE(cc_scroll_layer->user_scrollable_vertical());
}
-TEST_F(ScrollingCoordinatorTest, iframeScrolling) {
+TEST_P(ScrollingCoordinatorTest, iframeScrolling) {
RegisterMockedHttpURLLoad("iframe-scrolling.html");
RegisterMockedHttpURLLoad("iframe-scrolling-inner.html");
NavigateTo(base_url_ + "iframe-scrolling.html");
@@ -794,10 +1226,8 @@ TEST_F(ScrollingCoordinatorTest, iframeScrolling) {
ASSERT_TRUE(inner_compositor->InCompositingMode());
GraphicsLayer* scroll_layer =
- inner_frame_view->LayoutViewportScrollableArea()->LayerForScrolling();
+ inner_frame_view->LayoutViewport()->LayerForScrolling();
ASSERT_TRUE(scroll_layer);
- ASSERT_EQ(inner_frame_view->LayoutViewportScrollableArea(),
- scroll_layer->GetScrollableArea());
cc::Layer* cc_scroll_layer = scroll_layer->CcLayer();
ASSERT_TRUE(cc_scroll_layer->scrollable());
@@ -805,19 +1235,17 @@ TEST_F(ScrollingCoordinatorTest, iframeScrolling) {
#if defined(OS_ANDROID)
// Now verify we've attached impl-side scrollbars onto the scrollbar layers
GraphicsLayer* horizontal_scrollbar_layer =
- inner_frame_view->LayoutViewportScrollableArea()
- ->LayerForHorizontalScrollbar();
+ inner_frame_view->LayoutViewport()->LayerForHorizontalScrollbar();
ASSERT_TRUE(horizontal_scrollbar_layer);
ASSERT_TRUE(horizontal_scrollbar_layer->HasContentsLayer());
GraphicsLayer* vertical_scrollbar_layer =
- inner_frame_view->LayoutViewportScrollableArea()
- ->LayerForVerticalScrollbar();
+ inner_frame_view->LayoutViewport()->LayerForVerticalScrollbar();
ASSERT_TRUE(vertical_scrollbar_layer);
ASSERT_TRUE(vertical_scrollbar_layer->HasContentsLayer());
#endif
}
-TEST_F(ScrollingCoordinatorTest, rtlIframe) {
+TEST_P(ScrollingCoordinatorTest, rtlIframe) {
RegisterMockedHttpURLLoad("rtl-iframe.html");
RegisterMockedHttpURLLoad("rtl-iframe-inner.html");
NavigateTo(base_url_ + "rtl-iframe.html");
@@ -848,24 +1276,22 @@ TEST_F(ScrollingCoordinatorTest, rtlIframe) {
ASSERT_TRUE(inner_compositor->InCompositingMode());
GraphicsLayer* scroll_layer =
- inner_frame_view->LayoutViewportScrollableArea()->LayerForScrolling();
+ inner_frame_view->LayoutViewport()->LayerForScrolling();
ASSERT_TRUE(scroll_layer);
- ASSERT_EQ(inner_frame_view->LayoutViewportScrollableArea(),
- scroll_layer->GetScrollableArea());
cc::Layer* cc_scroll_layer = scroll_layer->CcLayer();
ASSERT_TRUE(cc_scroll_layer->scrollable());
- int expected_scroll_position =
- 958 + (inner_frame_view->LayoutViewportScrollableArea()
- ->VerticalScrollbar()
- ->IsOverlayScrollbar()
- ? 0
- : 15);
- ASSERT_EQ(expected_scroll_position, cc_scroll_layer->scroll_offset().x());
+ int expected_scroll_position = 958 + (inner_frame_view->LayoutViewport()
+ ->VerticalScrollbar()
+ ->IsOverlayScrollbar()
+ ? 0
+ : 15);
+ ASSERT_EQ(expected_scroll_position,
+ cc_scroll_layer->CurrentScrollOffset().x());
}
-TEST_F(ScrollingCoordinatorTest, setupScrollbarLayerShouldNotCrash) {
+TEST_P(ScrollingCoordinatorTest, setupScrollbarLayerShouldNotCrash) {
RegisterMockedHttpURLLoad("setup_scrollbar_layer_crash.html");
NavigateTo(base_url_ + "setup_scrollbar_layer_crash.html");
ForceFullCompositingUpdate();
@@ -873,7 +1299,7 @@ TEST_F(ScrollingCoordinatorTest, setupScrollbarLayerShouldNotCrash) {
// an empty document by javascript.
}
-TEST_F(ScrollingCoordinatorTest,
+TEST_P(ScrollingCoordinatorTest,
ScrollbarsForceMainThreadOrHaveCompositorScrollbarLayer) {
RegisterMockedHttpURLLoad("trivial-scroller.html");
NavigateTo(base_url_ + "trivial-scroller.html");
@@ -896,14 +1322,14 @@ TEST_F(ScrollingCoordinatorTest,
bool has_cc_scrollbar_layer = !scrollbar_graphics_layer->DrawsContent();
ASSERT_TRUE(
has_cc_scrollbar_layer ||
- scrollbar_graphics_layer->CcLayer()->should_scroll_on_main_thread());
+ scrollbar_graphics_layer->CcLayer()->main_thread_scrolling_reasons());
}
#if defined(OS_MACOSX) || defined(OS_ANDROID)
-TEST_F(ScrollingCoordinatorTest,
+TEST_P(ScrollingCoordinatorTest,
DISABLED_setupScrollbarLayerShouldSetScrollLayerOpaque)
#else
-TEST_F(ScrollingCoordinatorTest, setupScrollbarLayerShouldSetScrollLayerOpaque)
+TEST_P(ScrollingCoordinatorTest, setupScrollbarLayerShouldSetScrollLayerOpaque)
#endif
{
RegisterMockedHttpURLLoad("wide_document.html");
@@ -914,7 +1340,7 @@ TEST_F(ScrollingCoordinatorTest, setupScrollbarLayerShouldSetScrollLayerOpaque)
ASSERT_TRUE(frame_view);
GraphicsLayer* scrollbar_graphics_layer =
- frame_view->LayoutViewportScrollableArea()->LayerForHorizontalScrollbar();
+ frame_view->LayoutViewport()->LayerForHorizontalScrollbar();
ASSERT_TRUE(scrollbar_graphics_layer);
cc::Layer* platform_layer = scrollbar_graphics_layer->CcLayer();
@@ -930,7 +1356,7 @@ TEST_F(ScrollingCoordinatorTest, setupScrollbarLayerShouldSetScrollLayerOpaque)
contents_layer->contents_opaque());
}
-TEST_F(ScrollingCoordinatorTest,
+TEST_P(ScrollingCoordinatorTest,
FixedPositionLosingBackingShouldTriggerMainThreadScroll) {
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false);
RegisterMockedHttpURLLoad("fixed-position-losing-backing.html");
@@ -946,7 +1372,7 @@ TEST_F(ScrollingCoordinatorTest,
EXPECT_TRUE(static_cast<LayoutBoxModelObject*>(fixed_pos->GetLayoutObject())
->Layer()
->HasCompositedLayerMapping());
- EXPECT_FALSE(scroll_layer->should_scroll_on_main_thread());
+ EXPECT_FALSE(scroll_layer->main_thread_scrolling_reasons());
fixed_pos->SetInlineStyleProperty(CSSPropertyTransform, CSSValueNone);
ForceFullCompositingUpdate();
@@ -954,10 +1380,10 @@ TEST_F(ScrollingCoordinatorTest,
EXPECT_FALSE(static_cast<LayoutBoxModelObject*>(fixed_pos->GetLayoutObject())
->Layer()
->HasCompositedLayerMapping());
- EXPECT_TRUE(scroll_layer->should_scroll_on_main_thread());
+ EXPECT_TRUE(scroll_layer->main_thread_scrolling_reasons());
}
-TEST_F(ScrollingCoordinatorTest, CustomScrollbarShouldTriggerMainThreadScroll) {
+TEST_P(ScrollingCoordinatorTest, CustomScrollbarShouldTriggerMainThreadScroll) {
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(true);
GetWebView()->SetDeviceScaleFactor(2.f);
RegisterMockedHttpURLLoad("custom_scrollbar.html");
@@ -981,7 +1407,7 @@ TEST_F(ScrollingCoordinatorTest, CustomScrollbarShouldTriggerMainThreadScroll) {
composited_layer_mapping->LayerForVerticalScrollbar();
ASSERT_TRUE(scrollbar_graphics_layer);
ASSERT_TRUE(
- scrollbar_graphics_layer->CcLayer()->should_scroll_on_main_thread());
+ scrollbar_graphics_layer->CcLayer()->main_thread_scrolling_reasons());
ASSERT_TRUE(
scrollbar_graphics_layer->CcLayer()->main_thread_scrolling_reasons() &
MainThreadScrollingReason::kCustomScrollbarScrolling);
@@ -993,13 +1419,13 @@ TEST_F(ScrollingCoordinatorTest, CustomScrollbarShouldTriggerMainThreadScroll) {
scrollbar_graphics_layer =
composited_layer_mapping->LayerForVerticalScrollbar();
ASSERT_FALSE(
- scrollbar_graphics_layer->CcLayer()->should_scroll_on_main_thread());
+ scrollbar_graphics_layer->CcLayer()->main_thread_scrolling_reasons());
ASSERT_FALSE(
scrollbar_graphics_layer->CcLayer()->main_thread_scrolling_reasons() &
MainThreadScrollingReason::kCustomScrollbarScrolling);
}
-TEST_F(ScrollingCoordinatorTest,
+TEST_P(ScrollingCoordinatorTest,
BackgroundAttachmentFixedShouldTriggerMainThreadScroll) {
RegisterMockedHttpURLLoad("iframe-background-attachment-fixed.html");
RegisterMockedHttpURLLoad("iframe-background-attachment-fixed-inner.html");
@@ -1029,10 +1455,8 @@ TEST_F(ScrollingCoordinatorTest,
ASSERT_TRUE(inner_compositor->InCompositingMode());
GraphicsLayer* scroll_layer =
- inner_frame_view->LayoutViewportScrollableArea()->LayerForScrolling();
+ inner_frame_view->LayoutViewport()->LayerForScrolling();
ASSERT_TRUE(scroll_layer);
- ASSERT_EQ(inner_frame_view->LayoutViewportScrollableArea(),
- scroll_layer->GetScrollableArea());
cc::Layer* cc_scroll_layer = scroll_layer->CcLayer();
ASSERT_TRUE(cc_scroll_layer->scrollable());
@@ -1051,9 +1475,8 @@ TEST_F(ScrollingCoordinatorTest,
layout_object = iframe->GetLayoutObject();
ASSERT_TRUE(layout_object);
- scroll_layer = layout_object->GetFrameView()
- ->LayoutViewportScrollableArea()
- ->LayerForScrolling();
+ scroll_layer =
+ layout_object->GetFrameView()->LayoutViewport()->LayerForScrolling();
ASSERT_TRUE(scroll_layer);
cc_scroll_layer = scroll_layer->CcLayer();
@@ -1074,9 +1497,8 @@ TEST_F(ScrollingCoordinatorTest,
layout_object = iframe->GetLayoutObject();
ASSERT_TRUE(layout_object);
- scroll_layer = layout_object->GetFrameView()
- ->LayoutViewportScrollableArea()
- ->LayerForScrolling();
+ scroll_layer =
+ layout_object->GetFrameView()->LayoutViewport()->LayerForScrolling();
ASSERT_TRUE(scroll_layer);
cc_scroll_layer = scroll_layer->CcLayer();
@@ -1087,7 +1509,7 @@ TEST_F(ScrollingCoordinatorTest,
// Upon resizing the content size, the main thread scrolling reason
// kHasNonLayerViewportConstrainedObject should be updated on all frames
-TEST_F(ScrollingCoordinatorTest,
+TEST_P(ScrollingCoordinatorTest,
RecalculateMainThreadScrollingReasonsUponResize) {
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false);
RegisterMockedHttpURLLoad("has-non-layer-viewport-constrained-objects.html");
@@ -1109,9 +1531,8 @@ TEST_F(ScrollingCoordinatorTest,
layout_object = element->GetLayoutObject();
ASSERT_TRUE(layout_object);
- GraphicsLayer* scroll_layer = layout_object->GetFrameView()
- ->LayoutViewportScrollableArea()
- ->LayerForScrolling();
+ GraphicsLayer* scroll_layer =
+ layout_object->GetFrameView()->LayoutViewport()->LayerForScrolling();
ASSERT_TRUE(scroll_layer);
cc::Layer* cc_scroll_layer = scroll_layer->CcLayer();
@@ -1130,22 +1551,22 @@ TEST_F(ScrollingCoordinatorTest,
ASSERT_TRUE(layout_object);
}
-TEST_F(ScrollingCoordinatorTest, StickyTriggersMainThreadScroll) {
+TEST_P(ScrollingCoordinatorTest, StickyTriggersMainThreadScroll) {
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false);
LoadHTML(
"<body style='height: 1200px'>"
"<div style='position: sticky; top: 0'>sticky</div>");
ForceFullCompositingUpdate();
- ScrollableArea* viewport = GetFrame()->View()->LayoutViewportScrollableArea();
+ ScrollableArea* viewport = GetFrame()->View()->LayoutViewport();
cc::Layer* scroll_layer = viewport->LayerForScrolling()->CcLayer();
ASSERT_EQ(MainThreadScrollingReason::kHasNonLayerViewportConstrainedObjects,
scroll_layer->main_thread_scrolling_reasons());
}
// LocalFrameView::FrameIsScrollableDidChange is used as a dirty bit and is
-// set to clean in ScrollingCoordinator::UpdateAfterCompositingChangeIfNeeded.
-// This test ensures that the dirty bit is set and unset properly.
-TEST_F(ScrollingCoordinatorTest, FrameIsScrollableDidChange) {
+// set to clean in ScrollingCoordinator::UpdateAfterPaint. This test ensures
+// that the dirty bit is set and unset properly.
+TEST_P(ScrollingCoordinatorTest, FrameIsScrollableDidChange) {
LoadHTML(R"HTML(
<div id='bg' style='background: red; width: 10px; height: 10px;'></div>
<div id='forcescroll' style='height: 5000px;'></div>
@@ -1173,7 +1594,7 @@ TEST_F(ScrollingCoordinatorTest, FrameIsScrollableDidChange) {
EXPECT_FALSE(GetFrame()->View()->FrameIsScrollableDidChange());
}
-TEST_F(ScrollingCoordinatorTest, UpdateUMAMetricUpdated) {
+TEST_P(ScrollingCoordinatorTest, UpdateUMAMetricUpdated) {
HistogramTester histogram_tester;
LoadHTML(R"HTML(
<div id='bg' style='background: blue;'></div>
@@ -1275,28 +1696,28 @@ class NonCompositedMainThreadScrollingReasonTest
}
};
-TEST_F(NonCompositedMainThreadScrollingReasonTest, TransparentTest) {
+TEST_P(NonCompositedMainThreadScrollingReasonTest, TransparentTest) {
TestNonCompositedReasons("transparent",
MainThreadScrollingReason::kHasOpacityAndLCDText);
}
-TEST_F(NonCompositedMainThreadScrollingReasonTest, TransformTest) {
+TEST_P(NonCompositedMainThreadScrollingReasonTest, TransformTest) {
TestNonCompositedReasons("transform",
MainThreadScrollingReason::kHasTransformAndLCDText);
}
-TEST_F(NonCompositedMainThreadScrollingReasonTest, BackgroundNotOpaqueTest) {
+TEST_P(NonCompositedMainThreadScrollingReasonTest, BackgroundNotOpaqueTest) {
TestNonCompositedReasons(
"background-not-opaque",
MainThreadScrollingReason::kBackgroundNotOpaqueInRectAndLCDText);
}
-TEST_F(NonCompositedMainThreadScrollingReasonTest, ClipTest) {
+TEST_P(NonCompositedMainThreadScrollingReasonTest, ClipTest) {
TestNonCompositedReasons("clip",
MainThreadScrollingReason::kHasClipRelatedProperty);
}
-TEST_F(NonCompositedMainThreadScrollingReasonTest, ClipPathTest) {
+TEST_P(NonCompositedMainThreadScrollingReasonTest, ClipPathTest) {
uint32_t clip_reason = MainThreadScrollingReason::kHasClipRelatedProperty;
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false);
Document* document = GetFrame()->GetDocument();
@@ -1345,17 +1766,17 @@ TEST_F(NonCompositedMainThreadScrollingReasonTest, ClipPathTest) {
EXPECT_FALSE(frame_view->GetMainThreadScrollingReasons() & clip_reason);
}
-TEST_F(NonCompositedMainThreadScrollingReasonTest, LCDTextEnabledTest) {
+TEST_P(NonCompositedMainThreadScrollingReasonTest, LCDTextEnabledTest) {
TestNonCompositedReasons("transparent",
MainThreadScrollingReason::kHasOpacityAndLCDText);
}
-TEST_F(NonCompositedMainThreadScrollingReasonTest, BoxShadowTest) {
+TEST_P(NonCompositedMainThreadScrollingReasonTest, BoxShadowTest) {
TestNonCompositedReasons(
"box-shadow", MainThreadScrollingReason::kHasBoxShadowFromNonRootLayer);
}
-TEST_F(NonCompositedMainThreadScrollingReasonTest, StackingContextTest) {
+TEST_P(NonCompositedMainThreadScrollingReasonTest, StackingContextTest) {
GetWebView()->GetSettings()->SetPreferCompositingToLCDTextEnabled(false);
Document* document = GetFrame()->GetDocument();
@@ -1384,7 +1805,7 @@ TEST_F(NonCompositedMainThreadScrollingReasonTest, StackingContextTest) {
EXPECT_FALSE(scrollable_area->GetNonCompositedMainThreadScrollingReasons());
}
-TEST_F(NonCompositedMainThreadScrollingReasonTest,
+TEST_P(NonCompositedMainThreadScrollingReasonTest,
CompositedWithLCDTextRelatedReasonsTest) {
// With "will-change:transform" we composite elements with
// LCDTextRelatedReasons only. For elements with other
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc b/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
index 74356de121e..ec73eb3807d 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/node.h"
+#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -114,8 +115,8 @@ void SnapCoordinator::UpdateSnapContainerData(const LayoutBox& snap_container) {
ScrollableArea* scrollable_area = ScrollableAreaForSnapping(snap_container);
if (!scrollable_area)
return;
- FloatPoint max_position = ScrollOffsetToPosition(
- scrollable_area->MaximumScrollOffset(), scrollable_area->ScrollOrigin());
+ FloatPoint max_position = scrollable_area->ScrollOffsetToPosition(
+ scrollable_area->MaximumScrollOffset());
snap_container_data.set_max_position(
gfx::ScrollOffset(max_position.X(), max_position.Y()));
@@ -151,6 +152,7 @@ void SnapCoordinator::UpdateSnapContainerData(const LayoutBox& snap_container) {
MinimumValueForLength(container_style->ScrollPaddingLeft(),
container_rect.Width()));
container_rect.Contract(container_padding);
+ snap_container_data.set_rect(FloatRect(container_rect));
if (snap_container_data.scroll_snap_type().strictness ==
SnapStrictness::kProximity) {
@@ -162,158 +164,13 @@ void SnapCoordinator::UpdateSnapContainerData(const LayoutBox& snap_container) {
if (SnapAreaSet* snap_areas = snap_container.SnapAreas()) {
for (const LayoutBox* snap_area : *snap_areas) {
- snap_container_data.AddSnapAreaData(CalculateSnapAreaData(
- *snap_area, snap_container, container_rect, max_position));
+ snap_container_data.AddSnapAreaData(
+ CalculateSnapAreaData(*snap_area, snap_container));
}
}
snap_container_map_.Set(&snap_container, snap_container_data);
}
-static float ClipInContainer(LayoutUnit unit, float max) {
- float value = unit.ClampNegativeToZero().ToFloat();
- return value > max ? max : value;
-}
-
-// Returns scroll offset at which the snap area and snap containers meet the
-// requested snapping alignment on the given axis.
-// If the scroll offset required for the alignment is outside the valid range
-// then it will be clamped.
-// alignment - The scroll-snap-align specified on the snap area.
-// https://www.w3.org/TR/css-scroll-snap-1/#scroll-snap-align
-// axis - The axis for which we consider alignment on. Should be either X or Y
-// container - The snap_container rect relative to the container_element's
-// boundary. Note that this rect is represented by the dotted box below,
-// which is contracted by the scroll-padding from the element's original
-// boundary.
-// max_position - The maximal scrollable offset of the container. The
-// calculated snap_position can not be larger than this value.
-// area - The snap area rect relative to the snap container's boundary. Note
-// that this rect is represented by the dotted box below, which is expanded
-// by the scroll-margin from the element's original boundary.
-static float CalculateSnapPosition(SnapAlignment alignment,
- SearchAxis axis,
- const LayoutRect& container,
- const FloatPoint& max_position,
- const LayoutRect& area) {
- if (alignment == SnapAlignment::kNone)
- return SnapAreaData::kInvalidScrollPosition;
- switch (alignment) {
- /* Start alignment aligns the area's start edge with container's start edge.
- https://www.w3.org/TR/css-scroll-snap-1/#valdef-scroll-snap-align-start
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- + ^ +
- + | +
- + |snap_position +
- + | +
- + v +
- + \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ +
- + \ scroll-padding \ +
- + \ . . . . . . . . . . . . . . . . . . . . . . . \ +
- + \ . . scroll-margin . . \ +
- + \ . . |=================| . . \ +
- + \ . . | | . . \ +
- + \ . . | snap_area | . . \ +
- + \ . . | | . . \ +
- + \ . . |=================| . . \ +
- + \ . . . . \ +
- + \ . . . . . . . . . . . . . . . \ +
- + \ . . \ +
- + \ . . \ +
- + \ . . \ +
- + \ . . . . . . .snap_container . . . . . . . . . \ +
- + \ \ +
- + \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ +
- + +
- + scrollable_content +
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
-
- */
- case SnapAlignment::kStart:
- if (axis == SearchAxis::kX) {
- return ClipInContainer(area.X() - container.X(), max_position.X());
- }
- return ClipInContainer(area.Y() - container.Y(), max_position.Y());
-
- /* Center alignment aligns the snap_area(with margin)'s center line with
- snap_container(without padding)'s center line.
- https://www.w3.org/TR/css-scroll-snap-1/#valdef-scroll-snap-align-center
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- + ^ +
- + | snap_position +
- + v +
- + \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ +
- + \ scroll-padding \ +
- + \ . . . . . . . . . . . . . . . . . . . . . . . \ +
- + \ . . \ +
- + \ . . . . . . . . . . . . . . . \ +
- + \ . . scroll-margin . . \ +
- + \ . . |=================| . . \ +
- + \ . . | snap_area | . . \ +
- + \* *.* * * *.* * * * * * * * * * * *.* * * * * * * * * * Center line
- + \ . . | | . . \ +
- + \ . . |=================| . . \ +
- + \ . . . . \ +
- + \ . . . . . . . . . . . . . . . \ +
- + \ . . \ +
- + \ . . . . . . snap_container. . . . . . . . . . \ +
- + \ \ +
- + \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ +
- + +
- + +
- + scrollable_content +
- + +
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
-
- */
- case SnapAlignment::kCenter:
- if (axis == SearchAxis::kX) {
- return ClipInContainer(area.Center().X() - container.Center().X(),
- max_position.X());
- }
- return ClipInContainer(area.Center().Y() - container.Center().Y(),
- max_position.Y());
-
- /* End alignment aligns the snap_area(with margin)'s end edge with
- snap_container(without padding)'s end edge.
- https://www.w3.org/TR/css-scroll-snap-1/#valdef-scroll-snap-align-end
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + . .
- + ^ +
- + | snap_position +
- + v +
- + \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ +
- + \ \ +
- + \ . . . . . . . . snap_container. . . . . . . . \ +
- + \ . . \ +
- + \ . . \ +
- + \ . . \ +
- + \ . . . . . . . . . . . . . . . \ +
- + \ . . scroll-margin . . \ +
- + \ . . |=================| . . \ +
- + \ . . | | . . \ +
- + \ . . | snap_area | . . \ +
- + \ . . | | . . \ +
- + \ . . |=================| . . \ +
- + \ . . . . \ +
- + \ . . . . . . . . . . . . . . . . . . . . . . . \ +
- + \ scroll-padding \ +
- + \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ +
- + +
- + scrollable_content +
- + +
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
-
- */
- case SnapAlignment::kEnd:
- if (axis == SearchAxis::kX) {
- return ClipInContainer(area.MaxX() - container.MaxX(),
- max_position.X());
- }
- return ClipInContainer(area.MaxY() - container.MaxY(), max_position.Y());
- default:
- return LayoutUnit(SnapAreaData::kInvalidScrollPosition);
- }
-}
-
static ScrollSnapAlign GetPhysicalAlignment(
const ComputedStyle& area_style,
const ComputedStyle& container_style) {
@@ -335,32 +192,9 @@ static ScrollSnapAlign GetPhysicalAlignment(
return align;
}
-static FloatRect GetVisibleRegion(const LayoutRect& container,
- const LayoutRect& area) {
- float left = area.X() - container.MaxX();
- float right = area.MaxX() - container.X();
- float top = area.Y() - container.MaxY();
- float bottom = area.MaxY() - container.Y();
- return FloatRect(left, top, right - left, bottom - top);
-}
-
-static SnapAxis ToSnapAxis(ScrollSnapAlign align) {
- if (align.alignment_inline != SnapAlignment::kNone &&
- align.alignment_block != SnapAlignment::kNone)
- return SnapAxis::kBoth;
-
- if (align.alignment_inline != SnapAlignment::kNone &&
- align.alignment_block == SnapAlignment::kNone)
- return SnapAxis::kX;
-
- return SnapAxis::kY;
-}
-
SnapAreaData SnapCoordinator::CalculateSnapAreaData(
const LayoutBox& snap_area,
- const LayoutBox& snap_container,
- const LayoutRect& container_rect,
- const FloatPoint& max_position) {
+ const LayoutBox& snap_container) {
const ComputedStyle* container_style = snap_container.Style();
const ComputedStyle* area_style = snap_area.Style();
SnapAreaData snap_area_data;
@@ -381,7 +215,7 @@ SnapAreaData SnapCoordinator::CalculateSnapAreaData(
ScrollableArea* scrollable_area = ScrollableAreaForSnapping(snap_container);
if (scrollable_area) {
if (snap_container.IsLayoutView())
- area_rect = snap_container.GetFrameView()->AbsoluteToDocument(area_rect);
+ area_rect = snap_container.GetFrameView()->FrameToDocument(area_rect);
else
area_rect.MoveBy(LayoutPoint(scrollable_area->ScrollPosition()));
}
@@ -390,44 +224,37 @@ SnapAreaData SnapCoordinator::CalculateSnapAreaData(
area_style->ScrollMarginTop(), area_style->ScrollMarginRight(),
area_style->ScrollMarginBottom(), area_style->ScrollMarginLeft());
area_rect.Expand(area_margin);
+ snap_area_data.rect = FloatRect(area_rect);
ScrollSnapAlign align = GetPhysicalAlignment(*area_style, *container_style);
+ snap_area_data.scroll_snap_align = align;
- snap_area_data.snap_position.set_x(
- CalculateSnapPosition(align.alignment_inline, SearchAxis::kX,
- container_rect, max_position, area_rect));
- snap_area_data.snap_position.set_y(
- CalculateSnapPosition(align.alignment_block, SearchAxis::kY,
- container_rect, max_position, area_rect));
-
- snap_area_data.snap_axis = ToSnapAxis(align);
-
- snap_area_data.visible_region = GetVisibleRegion(container_rect, area_rect);
snap_area_data.must_snap =
(area_style->ScrollSnapStop() == EScrollSnapStop::kAlways);
return snap_area_data;
}
-FloatPoint SnapCoordinator::GetSnapPositionForPoint(
+base::Optional<FloatPoint> SnapCoordinator::GetSnapPositionForPoint(
const LayoutBox& snap_container,
const FloatPoint& point,
bool did_scroll_x,
bool did_scroll_y) {
auto iter = snap_container_map_.find(&snap_container);
if (iter == snap_container_map_.end())
- return point;
+ return base::nullopt;
const SnapContainerData& data = iter->value;
if (!data.size())
- return point;
+ return base::nullopt;
gfx::ScrollOffset snap_position;
if (data.FindSnapPosition(gfx::ScrollOffset(point.X(), point.Y()),
did_scroll_x, did_scroll_y, &snap_position)) {
- return FloatPoint(snap_position.x(), snap_position.y());
+ FloatPoint snap_point(snap_position.x(), snap_position.y());
+ return snap_point;
}
- return point;
+ return base::nullopt;
}
void SnapCoordinator::PerformSnapping(const LayoutBox& snap_container,
@@ -438,12 +265,16 @@ void SnapCoordinator::PerformSnapping(const LayoutBox& snap_container,
return;
FloatPoint current_position = scrollable_area->ScrollPosition();
- FloatPoint snap_position = GetSnapPositionForPoint(
+ base::Optional<FloatPoint> snap_point = GetSnapPositionForPoint(
snap_container, current_position, did_scroll_x, did_scroll_y);
+ if (!snap_point.has_value())
+ return;
- if (snap_position != current_position) {
+ scrollable_area->CancelScrollAnimation();
+ scrollable_area->CancelProgrammaticScrollAnimation();
+ if (snap_point.value() != current_position) {
scrollable_area->SetScrollOffset(
- ScrollPositionToOffset(snap_position, scrollable_area->ScrollOrigin()),
+ scrollable_area->ScrollPositionToOffset(snap_point.value()),
kProgrammaticScroll, kScrollBehaviorSmooth);
}
}
@@ -476,6 +307,30 @@ base::Optional<SnapContainerData> SnapCoordinator::GetSnapContainerData(
return base::nullopt;
}
+bool SnapCoordinator::GetSnapFlingInfo(
+ const LayoutBox& snap_container,
+ const gfx::Vector2dF& natural_displacement,
+ gfx::Vector2dF* out_initial_offset,
+ gfx::Vector2dF* out_target_offset) {
+ ScrollableArea* scrollable_area = ScrollableAreaForSnapping(snap_container);
+ if (!scrollable_area)
+ return false;
+
+ FloatPoint current_position = scrollable_area->ScrollPosition();
+ *out_initial_offset = gfx::Vector2dF(current_position);
+ FloatPoint original_end =
+ current_position +
+ FloatPoint(natural_displacement.x(), natural_displacement.y());
+ bool did_scroll_x = natural_displacement.x() != 0;
+ bool did_scroll_y = natural_displacement.y() != 0;
+ base::Optional<FloatPoint> snap_end = GetSnapPositionForPoint(
+ snap_container, original_end, did_scroll_x, did_scroll_y);
+ if (!snap_end.has_value())
+ return false;
+ *out_target_offset = gfx::Vector2dF(snap_end.value());
+ return true;
+}
+
#ifndef NDEBUG
void SnapCoordinator::ShowSnapAreaMap() {
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.h b/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.h
index 64680f012e9..2c3ad76aba9 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.h
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.h
@@ -44,9 +44,7 @@ class CORE_EXPORT SnapCoordinator final
// Calculate the SnapAreaData for the specific snap area in its snap
// container.
SnapAreaData CalculateSnapAreaData(const LayoutBox& snap_area,
- const LayoutBox& snap_container,
- const LayoutRect& area_rect,
- const FloatPoint& max_position);
+ const LayoutBox& snap_container);
// Called by LocalFrameView::PerformPostLayoutTasks(), so that the snap data
// are updated whenever a layout happens.
@@ -59,10 +57,15 @@ class CORE_EXPORT SnapCoordinator final
void PerformSnapping(const LayoutBox& snap_container,
bool did_scroll_x,
bool did_scroll_y);
- FloatPoint GetSnapPositionForPoint(const LayoutBox& snap_container,
- const FloatPoint& natural_position,
- bool did_scroll_x,
- bool did_scroll_y);
+ base::Optional<FloatPoint> GetSnapPositionForPoint(
+ const LayoutBox& snap_container,
+ const FloatPoint& natural_position,
+ bool did_scroll_x,
+ bool did_scroll_y);
+ bool GetSnapFlingInfo(const LayoutBox& snap_container,
+ const gfx::Vector2dF& natural_displacement,
+ gfx::Vector2dF* out_initial_offset,
+ gfx::Vector2dF* out_target_offset);
#ifndef NDEBUG
void ShowSnapAreaMap();
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc b/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc
index 4e10acf80f2..119f7ba3c02 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator_test.cc
@@ -297,64 +297,54 @@ TEST_F(SnapCoordinatorTest,
#define EXPECT_EQ_CONTAINER(expected, actual) \
{ \
- EXPECT_EQ(expected.max_position().x(), actual.max_position().x()); \
- EXPECT_EQ(expected.max_position().y(), actual.max_position().y()); \
+ EXPECT_EQ(expected.max_position(), actual.max_position()); \
EXPECT_EQ(expected.scroll_snap_type(), actual.scroll_snap_type()); \
EXPECT_EQ(expected.proximity_range(), actual.proximity_range()); \
EXPECT_EQ(expected.size(), actual.size()); \
+ EXPECT_EQ(expected.rect(), actual.rect()); \
}
#define EXPECT_EQ_AREA(expected, actual) \
{ \
- EXPECT_EQ(expected.snap_axis, actual.snap_axis); \
- EXPECT_EQ(expected.snap_position.x(), actual.snap_position.x()); \
- EXPECT_EQ(expected.snap_position.y(), actual.snap_position.y()); \
- EXPECT_EQ(expected.visible_region, actual.visible_region); \
+ EXPECT_EQ(expected.scroll_snap_align, actual.scroll_snap_align); \
+ EXPECT_EQ(expected.rect, actual.rect); \
EXPECT_EQ(expected.must_snap, actual.must_snap); \
}
-// The following tests check the snap data are correctly calculated.
-TEST_F(SnapCoordinatorTest, StartAlignmentCalculation) {
+// The following tests check the SnapContainerData and SnapAreaData are
+// correctly calculated.
+TEST_F(SnapCoordinatorTest, SnapDataCalculation) {
SetUpSingleSnapArea();
+ Element* scroller_element = GetDocument().getElementById("scroller");
+ ScrollableArea* scrollable_area =
+ scroller_element->GetLayoutBox()->GetScrollableArea();
Element* area_element = GetDocument().getElementById("area");
area_element->setAttribute(styleAttr, "scroll-snap-align: start;");
GetDocument().UpdateStyleAndLayout();
- Element* scroller_element = GetDocument().getElementById("scroller");
SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
+
base::Optional<SnapContainerData> data =
snap_coordinator->GetSnapContainerData(*scroller_element->GetLayoutBox());
EXPECT_TRUE(data.has_value());
SnapContainerData actual_container = data.value();
-
- ScrollableArea* scrollable_area =
- scroller_element->GetLayoutBox()->GetScrollableArea();
- FloatPoint max_position = ScrollOffsetToPosition(
- scrollable_area->MaximumScrollOffset(), scrollable_area->ScrollOrigin());
-
- // (#area.left - #area.scroll-margin) - (#scroller.scroll-padding)
- double snap_position_x = (200 - 8) - 10;
- // (#area.top - #area.scroll-margin) - (#scroller.scroll-padding)
- double snap_position_y = (200 - 8) - 10;
+ FloatPoint max_position = scrollable_area->ScrollOffsetToPosition(
+ scrollable_area->MaximumScrollOffset());
double width = scroller_element->clientWidth();
double height = scroller_element->clientHeight();
- gfx::RectF visible_region(202 - width, 202 - height, 96 + width, 96 + height);
-
- bool must_snap = false;
-
SnapContainerData expected_container(
ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory),
+ gfx::RectF(10, 10, width - 20, height - 20),
gfx::ScrollOffset(max_position.X(), max_position.Y()));
- SnapAreaData expected_area(
- SnapAxis::kBoth, gfx::ScrollOffset(snap_position_x, snap_position_y),
- visible_region, must_snap);
+ SnapAreaData expected_area(ScrollSnapAlign(SnapAlignment::kStart),
+ gfx::RectF(192, 192, 116, 116), false);
expected_container.AddSnapAreaData(expected_area);
EXPECT_EQ_CONTAINER(expected_container, actual_container);
EXPECT_EQ_AREA(expected_area, actual_container.at(0));
}
-TEST_F(SnapCoordinatorTest, ScrolledStartAlignmentCalculation) {
+TEST_F(SnapCoordinatorTest, ScrolledSnapDataCalculation) {
SetUpSingleSnapArea();
Element* scroller_element = GetDocument().getElementById("scroller");
ScrollableArea* scrollable_area =
@@ -365,38 +355,29 @@ TEST_F(SnapCoordinatorTest, ScrolledStartAlignmentCalculation) {
area_element->setAttribute(styleAttr, "scroll-snap-align: start;");
GetDocument().UpdateStyleAndLayout();
SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
+
base::Optional<SnapContainerData> data =
snap_coordinator->GetSnapContainerData(*scroller_element->GetLayoutBox());
EXPECT_TRUE(data.has_value());
SnapContainerData actual_container = data.value();
-
- FloatPoint max_position = ScrollOffsetToPosition(
- scrollable_area->MaximumScrollOffset(), scrollable_area->ScrollOrigin());
-
- // (#area.left - #area.scroll-margin) - (#scroller.scroll-padding)
- double snap_position_x = (200 - 8) - 10;
- // (#area.top - #area.scroll-margin) - (#scroller.scroll-padding)
- double snap_position_y = (200 - 8) - 10;
+ FloatPoint max_position = scrollable_area->ScrollOffsetToPosition(
+ scrollable_area->MaximumScrollOffset());
double width = scroller_element->clientWidth();
double height = scroller_element->clientHeight();
- gfx::RectF visible_region(202 - width, 202 - height, 96 + width, 96 + height);
-
- bool must_snap = false;
-
SnapContainerData expected_container(
ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory),
+ gfx::RectF(10, 10, width - 20, height - 20),
gfx::ScrollOffset(max_position.X(), max_position.Y()));
- SnapAreaData expected_area(
- SnapAxis::kBoth, gfx::ScrollOffset(snap_position_x, snap_position_y),
- visible_region, must_snap);
+ SnapAreaData expected_area(ScrollSnapAlign(SnapAlignment::kStart),
+ gfx::RectF(192, 192, 116, 116), false);
expected_container.AddSnapAreaData(expected_area);
EXPECT_EQ_CONTAINER(expected_container, actual_container);
EXPECT_EQ_AREA(expected_area, actual_container.at(0));
}
-TEST_F(SnapCoordinatorTest, ScrolledStartAlignmentCalculationOnViewport) {
+TEST_F(SnapCoordinatorTest, ScrolledSnapDataCalculationOnViewport) {
SetHTML(R"HTML(
<style>
body {
@@ -424,8 +405,7 @@ TEST_F(SnapCoordinatorTest, ScrolledStartAlignmentCalculationOnViewport) {
Element* body = GetDocument().body();
EXPECT_EQ(body, GetDocument().ViewportDefiningElement());
- ScrollableArea* scrollable_area =
- GetDocument().View()->LayoutViewportScrollableArea();
+ ScrollableArea* scrollable_area = GetDocument().View()->LayoutViewport();
body->scrollBy(20, 20);
EXPECT_EQ(FloatPoint(20, 20), scrollable_area->ScrollPosition());
Element* area_element = GetDocument().getElementById("area");
@@ -437,26 +417,25 @@ TEST_F(SnapCoordinatorTest, ScrolledStartAlignmentCalculationOnViewport) {
EXPECT_TRUE(data.has_value());
SnapContainerData actual_container = data.value();
- FloatPoint max_position = ScrollOffsetToPosition(
- scrollable_area->MaximumScrollOffset(), scrollable_area->ScrollOrigin());
+ FloatPoint max_position = scrollable_area->ScrollOffsetToPosition(
+ scrollable_area->MaximumScrollOffset());
+ double width = body->clientWidth();
+ double height = body->clientHeight();
SnapContainerData expected_container(
ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory),
+ gfx::RectF(0, 0, width, height),
gfx::ScrollOffset(max_position.X(), max_position.Y()));
- double width = body->clientWidth();
- double height = body->clientHeight();
- gfx::RectF visible_region(200 - width, 200 - height, 100 + width,
- 100 + height);
- SnapAreaData expected_area(SnapAxis::kBoth, gfx::ScrollOffset(200, 200),
- visible_region, false);
+ SnapAreaData expected_area(ScrollSnapAlign(SnapAlignment::kStart),
+ gfx::RectF(200, 200, 100, 100), false);
expected_container.AddSnapAreaData(expected_area);
EXPECT_EQ_CONTAINER(expected_container, actual_container);
EXPECT_EQ_AREA(expected_area, actual_container.at(0));
}
-TEST_F(SnapCoordinatorTest, StartAlignmentCalculationWithBoxModel) {
+TEST_F(SnapCoordinatorTest, SnapDataCalculationWithBoxModel) {
SetUpSingleSnapArea();
Element* area_element = GetDocument().getElementById("area");
area_element->setAttribute(styleAttr,
@@ -474,36 +453,34 @@ TEST_F(SnapCoordinatorTest, StartAlignmentCalculationWithBoxModel) {
ScrollableArea* scrollable_area =
scroller_element->GetLayoutBox()->GetScrollableArea();
- FloatPoint max_position = ScrollOffsetToPosition(
- scrollable_area->MaximumScrollOffset(), scrollable_area->ScrollOrigin());
-
- // (#scroller.padding + #area.left + #area.margin - #area.scroll-margin)
- // - (#scroller.scroll-padding)
- double snap_position_x = (4 + 200 + 2 - 8) - 10;
- // (#scroller.padding + #area.top + #area.margin - #area.scroll-margin)
- // - (#scroller.scroll-padding)
- double snap_position_y = (4 + 200 + 2 - 8) - 10;
+ FloatPoint max_position = scrollable_area->ScrollOffsetToPosition(
+ scrollable_area->MaximumScrollOffset());
double width = scroller_element->clientWidth();
double height = scroller_element->clientHeight();
- gfx::RectF visible_region(208 - width, 208 - height, 124 + width,
- 124 + height);
-
- bool must_snap = false;
+ // rect.x = rect.y = scroller.border + scroller.scroll-padding
SnapContainerData expected_container(
ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory),
+ gfx::RectF(20, 20, width - 20, height - 20),
gfx::ScrollOffset(max_position.X(), max_position.Y()));
- SnapAreaData expected_area(
- SnapAxis::kBoth, gfx::ScrollOffset(snap_position_x, snap_position_y),
- visible_region, must_snap);
+ // rect.x = scroller.border + scroller.padding + area.left + area.margin
+ // - area.scroll-margin
+ // rect.y = scroller.border + scroller.padding + area.top + area.margin
+ // - area.scroll-margin
+ // rect.width = area.width +
+ // 2 * (area.padding + area.border + area.scroll-margin)
+ // rect.height = area.height +
+ // 2 * (area.padding + area.border + area.scroll-margin)
+ SnapAreaData expected_area(ScrollSnapAlign(SnapAlignment::kStart),
+ gfx::RectF(208, 208, 144, 144), false);
expected_container.AddSnapAreaData(expected_area);
EXPECT_EQ_CONTAINER(expected_container, actual_container);
EXPECT_EQ_AREA(expected_area, actual_container.at(0));
}
-TEST_F(SnapCoordinatorTest, NegativeMarginStartAlignmentCalculation) {
+TEST_F(SnapCoordinatorTest, NegativeMarginSnapDataCalculation) {
SetUpSingleSnapArea();
Element* area_element = GetDocument().getElementById("area");
area_element->setAttribute(styleAttr,
@@ -518,73 +495,25 @@ TEST_F(SnapCoordinatorTest, NegativeMarginStartAlignmentCalculation) {
ScrollableArea* scrollable_area =
scroller_element->GetLayoutBox()->GetScrollableArea();
- FloatPoint max_position = ScrollOffsetToPosition(
- scrollable_area->MaximumScrollOffset(), scrollable_area->ScrollOrigin());
-
- // (#area.left - #area.scroll-margin) - (#scroller.scroll-padding)
- double snap_position_x = (200 - (-8)) - 10;
- // (#area.top - #area.scroll-margin) - (#scroller.scroll-padding)
- double snap_position_y = (200 - (-8)) - 10;
+ FloatPoint max_position = scrollable_area->ScrollOffsetToPosition(
+ scrollable_area->MaximumScrollOffset());
double width = scroller_element->clientWidth();
double height = scroller_element->clientHeight();
- gfx::RectF visible_region(218 - width, 218 - height, 64 + width, 64 + height);
-
- bool must_snap = false;
SnapContainerData expected_container(
ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory),
+ gfx::RectF(10, 10, width - 20, height - 20),
gfx::ScrollOffset(max_position.X(), max_position.Y()));
- SnapAreaData expected_area(
- SnapAxis::kBoth, gfx::ScrollOffset(snap_position_x, snap_position_y),
- visible_region, must_snap);
+ SnapAreaData expected_area(ScrollSnapAlign(SnapAlignment::kStart),
+ gfx::RectF(208, 208, 84, 84), false);
expected_container.AddSnapAreaData(expected_area);
EXPECT_EQ_CONTAINER(expected_container, actual_container);
EXPECT_EQ_AREA(expected_area, actual_container.at(0));
}
-TEST_F(SnapCoordinatorTest, CenterAlignmentCalculation) {
- SetUpSingleSnapArea();
- Element* area_element = GetDocument().getElementById("area");
- area_element->setAttribute(styleAttr, "scroll-snap-align: center;");
- GetDocument().UpdateStyleAndLayout();
- Element* scroller_element = GetDocument().getElementById("scroller");
- SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
- base::Optional<SnapContainerData> data =
- snap_coordinator->GetSnapContainerData(*scroller_element->GetLayoutBox());
- EXPECT_TRUE(data.has_value());
- SnapContainerData actual_container = data.value();
-
- ScrollableArea* scrollable_area =
- scroller_element->GetLayoutBox()->GetScrollableArea();
- FloatPoint max_position = ScrollOffsetToPosition(
- scrollable_area->MaximumScrollOffset(), scrollable_area->ScrollOrigin());
-
- double width = scroller_element->clientWidth();
- double height = scroller_element->clientHeight();
- // (#area.left + #area.right) / 2 - #scroller.width / 2
- double snap_position_x = (200 + (200 + 100)) / 2 - width / 2;
- // (#area.top + #area.bottom) / 2 - #scroller.height / 2
- double snap_position_y = (200 + (200 + 100)) / 2 - height / 2;
-
- gfx::RectF visible_region(202 - width, 202 - height, 96 + width, 96 + height);
-
- bool must_snap = false;
-
- SnapContainerData expected_container(
- ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory),
- gfx::ScrollOffset(max_position.X(), max_position.Y()));
- SnapAreaData expected_area(
- SnapAxis::kBoth, gfx::ScrollOffset(snap_position_x, snap_position_y),
- visible_region, must_snap);
- expected_container.AddSnapAreaData(expected_area);
-
- EXPECT_EQ_CONTAINER(expected_container, actual_container);
- EXPECT_EQ_AREA(expected_area, actual_container.at(0));
-}
-
-TEST_F(SnapCoordinatorTest, AsymmetricalCenterAlignmentCalculation) {
+TEST_F(SnapCoordinatorTest, AsymmetricalSnapDataCalculation) {
SetUpSingleSnapArea();
Element* area_element = GetDocument().getElementById("area");
area_element->setAttribute(styleAttr,
@@ -612,45 +541,29 @@ TEST_F(SnapCoordinatorTest, AsymmetricalCenterAlignmentCalculation) {
ScrollableArea* scrollable_area =
scroller_element->GetLayoutBox()->GetScrollableArea();
- FloatPoint max_position = ScrollOffsetToPosition(
- scrollable_area->MaximumScrollOffset(), scrollable_area->ScrollOrigin());
+ FloatPoint max_position = scrollable_area->ScrollOffsetToPosition(
+ scrollable_area->MaximumScrollOffset());
double width = scroller_element->clientWidth();
double height = scroller_element->clientHeight();
- // (#area.left - #area.scroll-margin-left +
- // #area.right + #area.scroll-margin-right) / 2 -
- // (#scroller.left + #scroller.scroll-padding-left +
- // #scroller.right - #scroller.scroll-padding-right) / 2
- double snap_position_x =
- (200 - 8 + (200 + 100 + 4)) / 2 - (0 + 16 + width - 12) / 2;
-
- // (#area.top - #area.scroll-margin-top +
- // #area.bottom + #area.scroll-margin-bottom) / 2 -
- // (#scroller.top + #scroller.scroll-padding-top +
- // #scroller.bottom - #scroller.scroll-padding-bottom) / 2
- double snap_position_y =
- (200 - 2 + (200 + 100 + 6)) / 2 - (0 + 10 + height - 14) / 2;
-
- gfx::RectF visible_region(204 - width, 212 - height, 84 + width, 84 + height);
-
- bool must_snap = false;
SnapContainerData expected_container(
ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory),
+ gfx::RectF(16, 10, width - 28, height - 24),
gfx::ScrollOffset(max_position.X(), max_position.Y()));
- SnapAreaData expected_area(
- SnapAxis::kBoth, gfx::ScrollOffset(snap_position_x, snap_position_y),
- visible_region, must_snap);
+ SnapAreaData expected_area(ScrollSnapAlign(SnapAlignment::kCenter),
+ gfx::RectF(192, 198, 112, 108), false);
expected_container.AddSnapAreaData(expected_area);
EXPECT_EQ_CONTAINER(expected_container, actual_container);
EXPECT_EQ_AREA(expected_area, actual_container.at(0));
}
-TEST_F(SnapCoordinatorTest, EndAlignmentCalculation) {
+TEST_F(SnapCoordinatorTest, ScaledSnapDataCalculation) {
SetUpSingleSnapArea();
Element* area_element = GetDocument().getElementById("area");
- area_element->setAttribute(styleAttr, "scroll-snap-align: end;");
+ area_element->setAttribute(styleAttr,
+ "scroll-snap-align: end; transform: scale(4, 4);");
GetDocument().UpdateStyleAndLayout();
Element* scroller_element = GetDocument().getElementById("scroller");
SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
@@ -661,132 +574,27 @@ TEST_F(SnapCoordinatorTest, EndAlignmentCalculation) {
ScrollableArea* scrollable_area =
scroller_element->GetLayoutBox()->GetScrollableArea();
- FloatPoint max_position = ScrollOffsetToPosition(
- scrollable_area->MaximumScrollOffset(), scrollable_area->ScrollOrigin());
-
- double width = scroller_element->clientWidth();
- double height = scroller_element->clientHeight();
- // (#area.right + #area.scroll-margin)
- // - (#scroller.right - #scroller.scroll-padding)
- double snap_position_x = (200 + 100 + 8) - (width - 10);
-
- // (#area.bottom + #area.scroll-margin)
- // - (#scroller.bottom - #scroller.scroll-padding)
- double snap_position_y = (200 + 100 + 8) - (height - 10);
-
- gfx::RectF visible_region(202 - width, 202 - height, 96 + width, 96 + height);
-
- bool must_snap = false;
-
- SnapContainerData expected_container(
- ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory),
- gfx::ScrollOffset(max_position.X(), max_position.Y()));
- SnapAreaData expected_area(
- SnapAxis::kBoth, gfx::ScrollOffset(snap_position_x, snap_position_y),
- visible_region, must_snap);
- expected_container.AddSnapAreaData(expected_area);
-
- EXPECT_EQ_CONTAINER(expected_container, actual_container);
- EXPECT_EQ_AREA(expected_area, actual_container.at(0));
-}
-
-TEST_F(SnapCoordinatorTest, EndAlignmentCalculationWithBoxModel) {
- SetUpSingleSnapArea();
- Element* area_element = GetDocument().getElementById("area");
- area_element->setAttribute(
- styleAttr,
- "scroll-snap-align: end; margin: 2px; border: 9px solid; padding: 5px;");
- Element* scroller_element = GetDocument().getElementById("scroller");
- scroller_element->setAttribute(
- styleAttr, "margin: 3px; border: 10px solid; padding: 4px;");
- GetDocument().UpdateStyleAndLayout();
- SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
- base::Optional<SnapContainerData> data =
- snap_coordinator->GetSnapContainerData(*scroller_element->GetLayoutBox());
- EXPECT_TRUE(data.has_value());
- SnapContainerData actual_container = data.value();
-
- ScrollableArea* scrollable_area =
- scroller_element->GetLayoutBox()->GetScrollableArea();
- FloatPoint max_position = ScrollOffsetToPosition(
- scrollable_area->MaximumScrollOffset(), scrollable_area->ScrollOrigin());
+ FloatPoint max_position = scrollable_area->ScrollOffsetToPosition(
+ scrollable_area->MaximumScrollOffset());
double width = scroller_element->clientWidth();
double height = scroller_element->clientHeight();
- // (#scroller.padding + #area.left + #area.margin + #area.width
- // + 2 x (#area.border + #area.padding)) + #area.scroll-margin)
- // - (#scroller.width - #scroller.scroll-padding)
- double snap_position_x = (4 + 200 + 2 + 100 + 2 * (9 + 5) + 8) - (width - 10);
- // (#scroller.padding + #area.top + #area.height + #area.margin
- // + 2 x (#area.border + #area.padding)) + #area.scroll-margin)
- // - (#scroller.height - #scroller.scroll-padding)
- double snap_position_y =
- (4 + 200 + 2 + 100 + 2 * (9 + 5) + 8) - (height - 10);
-
- gfx::RectF visible_region(208 - width, 208 - height, 124 + width,
- 124 + height);
-
- bool must_snap = false;
-
SnapContainerData expected_container(
ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory),
+ gfx::RectF(10, 10, width - 20, height - 20),
gfx::ScrollOffset(max_position.X(), max_position.Y()));
- SnapAreaData expected_area(
- SnapAxis::kBoth, gfx::ScrollOffset(snap_position_x, snap_position_y),
- visible_region, must_snap);
- expected_container.AddSnapAreaData(expected_area);
- EXPECT_EQ_CONTAINER(expected_container, actual_container);
- EXPECT_EQ_AREA(expected_area, actual_container.at(0));
-}
-
-TEST_F(SnapCoordinatorTest, ScaledEndAlignmentCalculation) {
- SetUpSingleSnapArea();
- Element* area_element = GetDocument().getElementById("area");
- area_element->setAttribute(styleAttr,
- "scroll-snap-align: end; transform: scale(4, 4);");
- GetDocument().UpdateStyleAndLayout();
- Element* scroller_element = GetDocument().getElementById("scroller");
- SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
- base::Optional<SnapContainerData> data =
- snap_coordinator->GetSnapContainerData(*scroller_element->GetLayoutBox());
- EXPECT_TRUE(data.has_value());
- SnapContainerData actual_container = data.value();
-
- ScrollableArea* scrollable_area =
- scroller_element->GetLayoutBox()->GetScrollableArea();
- FloatPoint max_position = ScrollOffsetToPosition(
- scrollable_area->MaximumScrollOffset(), scrollable_area->ScrollOrigin());
-
- double width = scroller_element->clientWidth();
- double height = scroller_element->clientHeight();
// The area is scaled from center, so it pushes the area's top-left corner to
// (50, 50).
- // (#area.right + #area.scroll-margin)
- // - (#scroller.right - #scroller.scroll-padding)
- double snap_position_x = (50 + 400 + 8) - (width - 10);
-
- // (#area.bottom + #area.scroll-margin)
- // - (#scroller.bottom - #scroller.scroll-padding)
- double snap_position_y = (50 + 400 + 8) - (height - 10);
-
- gfx::RectF visible_region(52 - width, 52 - height, 396 + width, 396 + height);
-
- bool must_snap = false;
-
- SnapContainerData expected_container(
- ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory),
- gfx::ScrollOffset(max_position.X(), max_position.Y()));
- SnapAreaData expected_area(
- SnapAxis::kBoth, gfx::ScrollOffset(snap_position_x, snap_position_y),
- visible_region, must_snap);
+ SnapAreaData expected_area(ScrollSnapAlign(SnapAlignment::kEnd),
+ gfx::RectF(42, 42, 416, 416), false);
expected_container.AddSnapAreaData(expected_area);
EXPECT_EQ_CONTAINER(expected_container, actual_container);
EXPECT_EQ_AREA(expected_area, actual_container.at(0));
}
-TEST_F(SnapCoordinatorTest, VerticalRlStartAlignmentCalculation) {
+TEST_F(SnapCoordinatorTest, VerticalRlSnapDataCalculation) {
SetUpSingleSnapArea();
Element* area_element = GetDocument().getElementById("area");
area_element->setAttribute(styleAttr,
@@ -802,79 +610,21 @@ TEST_F(SnapCoordinatorTest, VerticalRlStartAlignmentCalculation) {
ScrollableArea* scrollable_area =
scroller_element->GetLayoutBox()->GetScrollableArea();
- FloatPoint max_position = ScrollOffsetToPosition(
- scrollable_area->MaximumScrollOffset(), scrollable_area->ScrollOrigin());
-
- double width = scroller_element->clientWidth();
- double height = scroller_element->clientHeight();
- // Under vertical-rl writing mode, 'start' should align to the right.
- // (#area.right + #area.scroll-margin)
- // - (#scroller.right - #scroller.scroll-padding)
- double snap_position_x = (200 + 100 + 8) - (width - 10);
-
- // (#area.top - #area.scroll-margin) - (#scroller.scroll-padding)
- double snap_position_y = (200 - 8) - 10;
-
- gfx::RectF visible_region(202 - width, 202 - height, 96 + width, 96 + height);
-
- bool must_snap = false;
-
- SnapContainerData expected_container(
- ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory),
- gfx::ScrollOffset(max_position.X(), max_position.Y()));
- SnapAreaData expected_area(
- SnapAxis::kBoth, gfx::ScrollOffset(snap_position_x, snap_position_y),
- visible_region, must_snap);
- expected_container.AddSnapAreaData(expected_area);
-
- EXPECT_EQ_CONTAINER(expected_container, actual_container);
- EXPECT_EQ_AREA(expected_area, actual_container.at(0));
-}
-
-// TODO(sunyunjia): Also add a test for vertical and rtl page.
-
-TEST_F(SnapCoordinatorTest, OverflowedSnapPositionCalculation) {
- SetUpSingleSnapArea();
- Element* area_element = GetDocument().getElementById("area");
- area_element->setAttribute(styleAttr,
- "left: 0px; top: 0px; scroll-snap-align: end;");
- GetDocument().UpdateStyleAndLayout();
- Element* scroller_element = GetDocument().getElementById("scroller");
- SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
- base::Optional<SnapContainerData> data =
- snap_coordinator->GetSnapContainerData(*scroller_element->GetLayoutBox());
- EXPECT_TRUE(data.has_value());
- SnapContainerData actual_container = data.value();
-
- ScrollableArea* scrollable_area =
- scroller_element->GetLayoutBox()->GetScrollableArea();
- FloatPoint max_position = ScrollOffsetToPosition(
- scrollable_area->MaximumScrollOffset(), scrollable_area->ScrollOrigin());
+ FloatPoint max_position = scrollable_area->ScrollOffsetToPosition(
+ scrollable_area->MaximumScrollOffset());
double width = scroller_element->clientWidth();
double height = scroller_element->clientHeight();
- // (#area.right + #area.scroll-margin)
- // - (#scroller.right - #scroller.scroll-padding)
- // = (100 + 8) - (clientWidth - 10) < 0
- // As scrollPosition cannot be set to a negative number, we set it to 0.
- double snap_position_x = 0;
-
- // (#area.bottom + #area.scroll-margin)
- // - (#scroller.bottom - #scroller.scroll-padding)
- // = (100 + 8) - (clientHeight - 10) < 0
- // As scrollPosition cannot be set to a negative number, we set it to 0.
- double snap_position_y = 0;
-
- gfx::RectF visible_region(2 - width, 2 - height, 96 + width, 96 + height);
-
- bool must_snap = false;
SnapContainerData expected_container(
ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory),
+ gfx::RectF(10, 10, width - 20, height - 20),
gfx::ScrollOffset(max_position.X(), max_position.Y()));
+ // Under vertical-rl writing mode, 'start' should align to the right, so the
+ // alignment on x should be reversed.
SnapAreaData expected_area(
- SnapAxis::kBoth, gfx::ScrollOffset(snap_position_x, snap_position_y),
- visible_region, must_snap);
+ ScrollSnapAlign(SnapAlignment::kEnd, SnapAlignment::kStart),
+ gfx::RectF(192, 192, 116, 116), false);
expected_container.AddSnapAreaData(expected_area);
EXPECT_EQ_CONTAINER(expected_container, actual_container);
@@ -892,10 +642,12 @@ TEST_F(SnapCoordinatorTest, SnapsIfScrolledAndSnappingAxesMatch) {
SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
LayoutBox* snap_container = scroller_element->GetLayoutBox();
- FloatPoint snap_position = snap_coordinator->GetSnapPositionForPoint(
- *snap_container, FloatPoint(150, 150), true, false);
- EXPECT_EQ(200 - 8 - 10, snap_position.X());
- EXPECT_EQ(150, snap_position.Y());
+ base::Optional<FloatPoint> snap_position =
+ snap_coordinator->GetSnapPositionForPoint(
+ *snap_container, FloatPoint(150, 150), true, false);
+ EXPECT_TRUE(snap_position.has_value());
+ EXPECT_EQ(200 - 8 - 10, snap_position.value().X());
+ EXPECT_EQ(150, snap_position.value().Y());
}
TEST_F(SnapCoordinatorTest, DoesNotSnapOnNonSnappingAxis) {
@@ -908,10 +660,10 @@ TEST_F(SnapCoordinatorTest, DoesNotSnapOnNonSnappingAxis) {
SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
LayoutBox* snap_container = scroller_element->GetLayoutBox();
- FloatPoint snap_position = snap_coordinator->GetSnapPositionForPoint(
- *snap_container, FloatPoint(150, 150), true, false);
- EXPECT_EQ(150, snap_position.X());
- EXPECT_EQ(150, snap_position.Y());
+ base::Optional<FloatPoint> snap_position =
+ snap_coordinator->GetSnapPositionForPoint(
+ *snap_container, FloatPoint(150, 150), true, false);
+ EXPECT_FALSE(snap_position.has_value());
}
TEST_F(SnapCoordinatorTest, DoesNotSnapOnEmptyContainer) {
@@ -924,10 +676,11 @@ TEST_F(SnapCoordinatorTest, DoesNotSnapOnEmptyContainer) {
SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
LayoutBox* snap_container = scroller_element->GetLayoutBox();
- FloatPoint snap_position = snap_coordinator->GetSnapPositionForPoint(
- *snap_container, FloatPoint(150, 150), true, false);
- EXPECT_EQ(150, snap_position.X());
- EXPECT_EQ(150, snap_position.Y());
+ base::Optional<FloatPoint> snap_position =
+ snap_coordinator->GetSnapPositionForPoint(
+ *snap_container, FloatPoint(150, 150), true, false);
+ ;
+ EXPECT_FALSE(snap_position.has_value());
}
TEST_F(SnapCoordinatorTest, DoesNotSnapOnNonSnapContainer) {
@@ -940,10 +693,10 @@ TEST_F(SnapCoordinatorTest, DoesNotSnapOnNonSnapContainer) {
SnapCoordinator* snap_coordinator = GetDocument().GetSnapCoordinator();
LayoutBox* snap_container = scroller_element->GetLayoutBox();
- FloatPoint snap_position = snap_coordinator->GetSnapPositionForPoint(
- *snap_container, FloatPoint(150, 150), true, false);
- EXPECT_EQ(150, snap_position.X());
- EXPECT_EQ(150, snap_position.Y());
+ base::Optional<FloatPoint> snap_position =
+ snap_coordinator->GetSnapPositionForPoint(
+ *snap_container, FloatPoint(150, 150), true, false);
+ EXPECT_FALSE(snap_position.has_value());
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.cc b/chromium/third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.cc
index c5b48b3f08d..380e5cc24d0 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.cc
@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/page_scale_constraints_set.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/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -18,6 +19,7 @@
#include "third_party/blink/renderer/core/page/scrolling/viewport_scroll_callback.h"
#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/platform/scroll/scrollable_area.h"
namespace blink {
@@ -69,7 +71,7 @@ IntSize TopDocumentRootScrollerController::RootScrollerVisibleArea() const {
return TopDocument()
->View()
- ->LayoutViewportScrollableArea()
+ ->LayoutViewport()
->VisibleContentRect(kExcludeScrollbars)
.Size() +
IntSize(0, browser_controls_adjustment);
@@ -210,8 +212,8 @@ void TopDocumentRootScrollerController::DidDisposeScrollableArea(
RootFrameViewport* rfv = frame_view->GetRootFrameViewport();
if (rfv && &area == &rfv->LayoutViewport()) {
- DCHECK(frame_view->LayoutViewportScrollableArea());
- rfv->SetLayoutViewport(*frame_view->LayoutViewportScrollableArea());
+ DCHECK(frame_view->LayoutViewport());
+ rfv->SetLayoutViewport(*frame_view->LayoutViewport());
}
}
diff --git a/chromium/third_party/blink/renderer/core/page/slot_scoped_traversal_test.cc b/chromium/third_party/blink/renderer/core/page/slot_scoped_traversal_test.cc
index 87a1ae520fe..f018a33ce26 100644
--- a/chromium/third_party/blink/renderer/core/page/slot_scoped_traversal_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/slot_scoped_traversal_test.cc
@@ -6,7 +6,6 @@
#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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.h"
@@ -15,6 +14,7 @@
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/html/html_slot_element.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/chromium/third_party/blink/renderer/core/page/spatial_navigation.cc b/chromium/third_party/blink/renderer/core/page/spatial_navigation.cc
index 37032e42f0a..3c21f9701e8 100644
--- a/chromium/third_party/blink/renderer/core/page/spatial_navigation.cc
+++ b/chromium/third_party/blink/renderer/core/page/spatial_navigation.cc
@@ -40,6 +40,7 @@
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/page/frame_tree.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_rect.h"
namespace blink {
@@ -154,7 +155,7 @@ bool HasOffscreenRect(const Node* node, WebFocusType direction) {
DCHECK(!frame_view->NeedsLayout());
LayoutRect container_viewport_rect(
- frame_view->LayoutViewportScrollableArea()->VisibleContentRect());
+ frame_view->LayoutViewport()->VisibleContentRect());
// We want to select a node if it is currently off screen, but will be
// exposed after we scroll. Adjust the viewport to post-scrolling position.
// If the container has overflow:hidden, we cannot scroll, so we do not pass
@@ -223,8 +224,8 @@ bool ScrollInDirection(LocalFrame* frame, WebFocusType direction) {
return false;
}
- frame->View()->LayoutViewportScrollableArea()->ScrollBy(
- ScrollOffset(dx, dy), kUserScroll);
+ frame->View()->LayoutViewport()->ScrollBy(ScrollOffset(dx, dy),
+ kUserScroll);
return true;
}
return false;
@@ -390,8 +391,7 @@ bool CanScrollInDirection(const LocalFrame* frame, WebFocusType direction) {
if ((direction == kWebFocusTypeUp || direction == kWebFocusTypeDown) &&
kScrollbarAlwaysOff == vertical_mode)
return false;
- ScrollableArea* scrollable_area =
- frame->View()->LayoutViewportScrollableArea();
+ ScrollableArea* scrollable_area = frame->View()->LayoutViewport();
LayoutSize size(scrollable_area->ContentsSize());
LayoutSize offset(scrollable_area->ScrollOffsetInt());
LayoutRect rect(scrollable_area->VisibleContentRect(kIncludeScrollbars));
@@ -416,7 +416,7 @@ LayoutRect NodeRectInRootFrame(const Node* node, bool ignore_border) {
DCHECK(node->GetLayoutObject());
DCHECK(!node->GetDocument().View()->NeedsLayout());
- LayoutRect rect = node->GetDocument().GetFrame()->View()->AbsoluteToRootFrame(
+ LayoutRect rect = node->GetDocument().GetFrame()->View()->ConvertToRootFrame(
node->BoundingBox());
// For authors that use border instead of outline in their CSS, we compensate
@@ -694,7 +694,7 @@ LayoutRect VirtualRectForAreaElementAndDirection(const HTMLAreaElement& area,
// areas.
LayoutRect rect = VirtualRectForDirection(
direction,
- area.GetDocument().GetFrame()->View()->AbsoluteToRootFrame(
+ area.GetDocument().GetFrame()->View()->ConvertToRootFrame(
area.ComputeAbsoluteRect(area.ImageElement()->GetLayoutObject())),
LayoutUnit(1));
return rect;
@@ -710,10 +710,8 @@ LayoutRect FindSearchStartPoint(const LocalFrame* frame,
WebFocusType direction) {
LayoutRect starting_rect = VirtualRectForDirection(
direction,
- frame->View()->AbsoluteToRootFrame(frame->View()->DocumentToAbsolute(
- LayoutRect(frame->View()
- ->LayoutViewportScrollableArea()
- ->VisibleContentRect()))));
+ frame->View()->ConvertToRootFrame(frame->View()->DocumentToFrame(
+ LayoutRect(frame->View()->LayoutViewport()->VisibleContentRect()))));
const Element* focused_element = frame->GetDocument()->FocusedElement();
if (focused_element) {
diff --git a/chromium/third_party/blink/renderer/core/page/touch_adjustment.cc b/chromium/third_party/blink/renderer/core/page/touch_adjustment.cc
index 81ea53c3605..83a8a7c36ea 100644
--- a/chromium/third_party/blink/renderer/core/page/touch_adjustment.cc
+++ b/chromium/third_party/blink/renderer/core/page/touch_adjustment.cc
@@ -44,7 +44,7 @@ namespace blink {
namespace TouchAdjustment {
const float kZeroTolerance = 1e-6f;
-constexpr float kMaxAdjustmentRadiusDips = 16.f;
+constexpr float kMaxAdjustmentSizeDips = 32.f;
// Class for remembering absolute quads of a target node and what node they
// represent.
@@ -337,7 +337,7 @@ void CompileSubtargetList(const HeapVector<Member<Node>>& intersected_nodes,
float ZoomableIntersectionQuotient(const IntPoint& touch_hotspot,
const IntRect& touch_area,
const SubtargetGeometry& subtarget) {
- IntRect rect = subtarget.GetNode()->GetDocument().View()->ContentsToRootFrame(
+ IntRect rect = subtarget.GetNode()->GetDocument().View()->ConvertToRootFrame(
subtarget.BoundingBox());
// Check the rectangle is meaningful zoom target. It should at least contain
@@ -361,7 +361,7 @@ float ZoomableIntersectionQuotient(const IntPoint& touch_hotspot,
float HybridDistanceFunction(const IntPoint& touch_hotspot,
const IntRect& touch_rect,
const SubtargetGeometry& subtarget) {
- IntRect rect = subtarget.GetNode()->GetDocument().View()->ContentsToRootFrame(
+ IntRect rect = subtarget.GetNode()->GetDocument().View()->ConvertToRootFrame(
subtarget.BoundingBox());
float radius_squared = 0.25f * (touch_rect.Size().DiagonalLengthSquared());
@@ -380,16 +380,16 @@ float HybridDistanceFunction(const IntPoint& touch_hotspot,
return hybrid_score;
}
-FloatPoint ContentsToRootFrame(LocalFrameView* view, FloatPoint pt) {
+FloatPoint ConvertToRootFrame(LocalFrameView* view, FloatPoint pt) {
int x = static_cast<int>(pt.X() + 0.5f);
int y = static_cast<int>(pt.Y() + 0.5f);
- IntPoint adjusted = view->ContentsToRootFrame(IntPoint(x, y));
+ IntPoint adjusted = view->ConvertToRootFrame(IntPoint(x, y));
return FloatPoint(adjusted.X(), adjusted.Y());
}
// Adjusts 'point' to the nearest point inside rect, and leaves it unchanged if
// already inside.
-void AdjustPointToRect(FloatPoint& point, const FloatRect& rect) {
+void AdjustPointToRect(FloatPoint& point, const IntRect& rect) {
if (point.X() < rect.X())
point.SetX(rect.X());
else if (point.X() > rect.MaxX())
@@ -409,7 +409,7 @@ bool SnapTo(const SubtargetGeometry& geom,
FloatQuad quad = geom.Quad();
if (quad.IsRectilinear()) {
- IntRect bounds = view->ContentsToRootFrame(geom.BoundingBox());
+ IntRect bounds = view->ConvertToRootFrame(geom.BoundingBox());
if (bounds.Contains(touch_point)) {
adjusted_point = touch_point;
return true;
@@ -429,13 +429,13 @@ bool SnapTo(const SubtargetGeometry& geom,
// the quad. Corner-cases exist where the quad will intersect but this will
// fail to adjust the point to somewhere in the intersection.
- FloatPoint p1 = ContentsToRootFrame(view, quad.P1());
- FloatPoint p2 = ContentsToRootFrame(view, quad.P2());
- FloatPoint p3 = ContentsToRootFrame(view, quad.P3());
- FloatPoint p4 = ContentsToRootFrame(view, quad.P4());
+ FloatPoint p1 = ConvertToRootFrame(view, quad.P1());
+ FloatPoint p2 = ConvertToRootFrame(view, quad.P2());
+ FloatPoint p3 = ConvertToRootFrame(view, quad.P3());
+ FloatPoint p4 = ConvertToRootFrame(view, quad.P4());
quad = FloatQuad(p1, p2, p3, p4);
- if (quad.ContainsPoint(touch_point)) {
+ if (quad.ContainsPoint(FloatPoint(touch_point))) {
adjusted_point = touch_point;
return true;
}
@@ -446,7 +446,7 @@ bool SnapTo(const SubtargetGeometry& geom,
AdjustPointToRect(center, touch_area);
adjusted_point = RoundedIntPoint(center);
- return quad.ContainsPoint(adjusted_point);
+ return quad.ContainsPoint(FloatPoint(adjusted_point));
}
// A generic function for finding the target node with the lowest distance
@@ -492,9 +492,10 @@ bool FindNodeWithLowestDistanceMetric(Node*& target_node,
if (target_node && target_node->IsPseudoElement())
target_node = target_node->ParentOrShadowHostNode();
- if (target_node)
+ if (target_node) {
target_area =
- target_node->GetDocument().View()->ContentsToRootFrame(target_area);
+ target_node->GetDocument().View()->ConvertToRootFrame(target_area);
+ }
return (target_node);
}
@@ -532,8 +533,8 @@ bool FindBestContextMenuCandidate(Node*& target_node,
}
LayoutSize GetHitTestRectForAdjustment(const LayoutSize& touch_area) {
- const LayoutSize max_size(TouchAdjustment::kMaxAdjustmentRadiusDips,
- TouchAdjustment::kMaxAdjustmentRadiusDips);
+ const LayoutSize max_size(TouchAdjustment::kMaxAdjustmentSizeDips,
+ TouchAdjustment::kMaxAdjustmentSizeDips);
return touch_area.ShrunkTo(max_size);
}
diff --git a/chromium/third_party/blink/renderer/core/page/touch_disambiguation.cc b/chromium/third_party/blink/renderer/core/page/touch_disambiguation.cc
index 9306fccd74c..f6678b7b9b8 100644
--- a/chromium/third_party/blink/renderer/core/page/touch_disambiguation.cc
+++ b/chromium/third_party/blink/renderer/core/page/touch_disambiguation.cc
@@ -59,23 +59,20 @@ static IntRect BoundingBoxForEventNodes(Node* event_node) {
result.Unite(node->PixelSnappedBoundingBox());
node = NodeTraversal::Next(*node, event_node);
}
- return event_node->GetDocument().View()->ContentsToRootFrame(result);
+ return event_node->GetDocument().View()->ConvertToRootFrame(result);
}
-static float ScoreTouchTarget(IntPoint touch_point,
- int padding,
- IntRect bounding_box) {
+static float ScoreTouchTarget(const IntRect& touch_rect, IntRect bounding_box) {
if (bounding_box.IsEmpty())
return 0;
- float reciprocal_padding = 1.f / padding;
+ float touch_radius =
+ ceil(std::max(touch_rect.Width(), touch_rect.Height()) * 0.5f);
float score = 1;
- IntSize distance = bounding_box.DifferenceToPoint(touch_point);
- score *=
- std::max((padding - abs(distance.Width())) * reciprocal_padding, 0.f);
- score *=
- std::max((padding - abs(distance.Height())) * reciprocal_padding, 0.f);
+ IntSize distance = bounding_box.DifferenceToPoint(touch_rect.Center());
+ score *= std::max(1 - (abs(distance.Width()) / touch_radius), 0.f);
+ score *= std::max(1 - (abs(distance.Height()) / touch_radius), 0.f);
return score;
}
@@ -90,21 +87,13 @@ void FindGoodTouchTargets(const IntRect& touch_box_in_root_frame,
Vector<IntRect>& good_targets,
HeapVector<Member<Node>>& highlight_nodes) {
good_targets.clear();
-
- int touch_point_padding = ceil(std::max(touch_box_in_root_frame.Width(),
- touch_box_in_root_frame.Height()) *
- 0.5);
-
- IntPoint touch_point = touch_box_in_root_frame.Center();
- IntPoint contents_point =
- main_frame->View()->RootFrameToContents(touch_point);
-
- HitTestResult result = main_frame->GetEventHandler().HitTestResultAtPoint(
- contents_point,
- HitTestRequest::kReadOnly | HitTestRequest::kActive |
- HitTestRequest::kListBased,
- LayoutRectOutsets(touch_point_padding, touch_point_padding,
- touch_point_padding, touch_point_padding));
+ LayoutPoint hit_point(main_frame->View()->ConvertFromRootFrame(
+ touch_box_in_root_frame.Location()));
+ HitTestLocation location(
+ LayoutRect(hit_point, LayoutSize(touch_box_in_root_frame.Size())));
+ HitTestResult result = main_frame->GetEventHandler().HitTestResultAtLocation(
+ location, HitTestRequest::kReadOnly | HitTestRequest::kActive |
+ HitTestRequest::kListBased);
const HeapListHashSet<Member<Node>>& hit_results =
result.ListBasedTestResult();
@@ -144,7 +133,7 @@ void FindGoodTouchTargets(const IntRect& touch_box_in_root_frame,
TouchTargetData& target_data =
touch_targets.insert(&node, TouchTargetData()).stored_value->value;
target_data.window_bounding_box = BoundingBoxForEventNodes(&node);
- target_data.score = ScoreTouchTarget(touch_point, touch_point_padding,
+ target_data.score = ScoreTouchTarget(touch_box_in_root_frame,
target_data.window_bounding_box);
best_score = std::max(best_score, target_data.score);
break;
diff --git a/chromium/third_party/blink/renderer/core/page/validation_message_client_impl.cc b/chromium/third_party/blink/renderer/core/page/validation_message_client_impl.cc
index 4a4bd439f1e..ad3d52a6ac3 100644
--- a/chromium/third_party/blink/renderer/core/page/validation_message_client_impl.cc
+++ b/chromium/third_party/blink/renderer/core/page/validation_message_client_impl.cc
@@ -43,9 +43,7 @@
namespace blink {
ValidationMessageClientImpl::ValidationMessageClientImpl(WebViewImpl& web_view)
- : web_view_(web_view),
- current_anchor_(nullptr),
- finish_time_(0) {}
+ : web_view_(web_view), current_anchor_(nullptr) {}
ValidationMessageClientImpl* ValidationMessageClientImpl::Create(
WebViewImpl& web_view) {
@@ -75,12 +73,13 @@ void ValidationMessageClientImpl::ShowValidationMessage(
current_anchor_ = &anchor;
message_ = message;
web_view_.GetChromeClient().RegisterPopupOpeningObserver(this);
- const double kMinimumSecondToShowValidationMessage = 5.0;
- const double kSecondPerCharacter = 0.05;
+ constexpr auto kMinimumTimeToShowValidationMessage =
+ TimeDelta::FromSeconds(5);
+ constexpr auto kTimePerCharacter = TimeDelta::FromMilliseconds(50);
finish_time_ =
- CurrentTimeTicksInSeconds() +
- std::max(kMinimumSecondToShowValidationMessage,
- (message.length() + sub_message.length()) * kSecondPerCharacter);
+ CurrentTimeTicks() +
+ std::max(kMinimumTimeToShowValidationMessage,
+ (message.length() + sub_message.length()) * kTimePerCharacter);
auto* target_frame =
web_view_.MainFrameImpl()
@@ -113,7 +112,7 @@ void ValidationMessageClientImpl::HideValidationMessage(const Element& anchor) {
&ValidationMessageClientImpl::Reset);
// This should be equal to or larger than transition duration of
// #container.hiding in validation_bubble.css.
- const double kHidingAnimationDuration = 0.13333;
+ const TimeDelta kHidingAnimationDuration = TimeDelta::FromSecondsD(0.13333);
timer_->StartOneShot(kHidingAnimationDuration, FROM_HERE);
}
@@ -128,7 +127,7 @@ void ValidationMessageClientImpl::Reset(TimerBase*) {
timer_ = nullptr;
current_anchor_ = nullptr;
message_ = String();
- finish_time_ = 0;
+ finish_time_ = TimeTicks();
overlay_ = nullptr;
overlay_delegate_ = nullptr;
web_view_.GetChromeClient().UnregisterPopupOpeningObserver(this);
@@ -147,7 +146,7 @@ void ValidationMessageClientImpl::DocumentDetached(const Document& document) {
void ValidationMessageClientImpl::CheckAnchorStatus(TimerBase*) {
DCHECK(current_anchor_);
if ((!LayoutTestSupport::IsRunningLayoutTest() &&
- CurrentTimeTicksInSeconds() >= finish_time_) ||
+ CurrentTimeTicks() >= finish_time_) ||
!CurrentView()) {
HideValidationMessage(*current_anchor_);
return;
diff --git a/chromium/third_party/blink/renderer/core/page/validation_message_client_impl.h b/chromium/third_party/blink/renderer/core/page/validation_message_client_impl.h
index e3a3ad60be4..5aaa1308b0c 100644
--- a/chromium/third_party/blink/renderer/core/page/validation_message_client_impl.h
+++ b/chromium/third_party/blink/renderer/core/page/validation_message_client_impl.h
@@ -78,7 +78,7 @@ class CORE_EXPORT ValidationMessageClientImpl final
WebViewImpl& web_view_;
Member<const Element> current_anchor_;
String message_;
- double finish_time_;
+ TimeTicks finish_time_;
std::unique_ptr<TimerBase> timer_;
std::unique_ptr<PageOverlay> overlay_;
// Raw pointer. This pointer is valid unless overlay_ is nullptr.
diff --git a/chromium/third_party/blink/renderer/core/page/viewport_description.cc b/chromium/third_party/blink/renderer/core/page/viewport_description.cc
new file mode 100644
index 00000000000..ee87f7d8daf
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/page/viewport_description.cc
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2001 Dirk Mueller (mueller@kde.org)
+ * (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights
+ * reserved.
+ * Copyright (C) 2008 Torch Mobile Inc. All rights reserved.
+ * (http://www.torchmobile.com/)
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
+ *
+ * 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/page/viewport_description.h"
+
+#include "build/build_config.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"
+#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/page/page.h"
+#include "third_party/blink/renderer/platform/histogram.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+
+namespace blink {
+
+static const float& CompareIgnoringAuto(const float& value1,
+ const float& value2,
+ const float& (*compare)(const float&,
+ const float&)) {
+ if (value1 == ViewportDescription::kValueAuto)
+ return value2;
+
+ if (value2 == ViewportDescription::kValueAuto)
+ return value1;
+
+ return compare(value1, value2);
+}
+
+float ViewportDescription::ResolveViewportLength(
+ const Length& length,
+ const FloatSize& initial_viewport_size,
+ Direction direction) {
+ if (length.IsAuto())
+ return ViewportDescription::kValueAuto;
+
+ if (length.IsFixed())
+ return length.GetFloatValue();
+
+ if (length.GetType() == kExtendToZoom)
+ return ViewportDescription::kValueExtendToZoom;
+
+ if (length.GetType() == kPercent && direction == kHorizontal)
+ return initial_viewport_size.Width() * length.GetFloatValue() / 100.0f;
+
+ if (length.GetType() == kPercent && direction == kVertical)
+ return initial_viewport_size.Height() * length.GetFloatValue() / 100.0f;
+
+ if (length.GetType() == kDeviceWidth)
+ return initial_viewport_size.Width();
+
+ if (length.GetType() == kDeviceHeight)
+ return initial_viewport_size.Height();
+
+ NOTREACHED();
+ return ViewportDescription::kValueAuto;
+}
+
+PageScaleConstraints ViewportDescription::Resolve(
+ const FloatSize& initial_viewport_size,
+ Length legacy_fallback_width) const {
+ float result_width = kValueAuto;
+
+ Length copy_max_width = max_width;
+ Length copy_min_width = min_width;
+ // In case the width (used for min- and max-width) is undefined.
+ if (IsLegacyViewportType() && max_width.IsAuto()) {
+ // The width viewport META property is translated into 'width' descriptors,
+ // setting the 'min' value to 'extend-to-zoom' and the 'max' value to the
+ // intended length. In case the UA-defines a min-width, use that as length.
+ if (zoom == ViewportDescription::kValueAuto) {
+ copy_min_width = Length(kExtendToZoom);
+ copy_max_width = legacy_fallback_width;
+ } else if (max_height.IsAuto()) {
+ copy_min_width = Length(kExtendToZoom);
+ copy_max_width = Length(kExtendToZoom);
+ }
+ }
+
+ float result_max_width =
+ ResolveViewportLength(copy_max_width, initial_viewport_size, kHorizontal);
+ float result_min_width =
+ ResolveViewportLength(copy_min_width, initial_viewport_size, kHorizontal);
+
+ float result_height = kValueAuto;
+ float result_max_height =
+ ResolveViewportLength(max_height, initial_viewport_size, kVertical);
+ float result_min_height =
+ ResolveViewportLength(min_height, initial_viewport_size, kVertical);
+
+ float result_zoom = zoom;
+ float result_min_zoom = min_zoom;
+ float result_max_zoom = max_zoom;
+ bool result_user_zoom = user_zoom;
+
+ // Resolve min-zoom and max-zoom values.
+ if (result_min_zoom != ViewportDescription::kValueAuto &&
+ result_max_zoom != ViewportDescription::kValueAuto)
+ result_max_zoom = std::max(result_min_zoom, result_max_zoom);
+
+ // Constrain zoom value to the [min-zoom, max-zoom] range.
+ if (result_zoom != ViewportDescription::kValueAuto)
+ result_zoom = CompareIgnoringAuto(
+ result_min_zoom,
+ CompareIgnoringAuto(result_max_zoom, result_zoom, std::min), std::max);
+
+ float extend_zoom =
+ CompareIgnoringAuto(result_zoom, result_max_zoom, std::min);
+
+ // Resolve non-"auto" lengths to pixel lengths.
+ if (extend_zoom == ViewportDescription::kValueAuto) {
+ if (result_max_width == ViewportDescription::kValueExtendToZoom)
+ result_max_width = ViewportDescription::kValueAuto;
+
+ if (result_max_height == ViewportDescription::kValueExtendToZoom)
+ result_max_height = ViewportDescription::kValueAuto;
+
+ if (result_min_width == ViewportDescription::kValueExtendToZoom)
+ result_min_width = result_max_width;
+
+ if (result_min_height == ViewportDescription::kValueExtendToZoom)
+ result_min_height = result_max_height;
+ } else {
+ float extend_width = initial_viewport_size.Width() / extend_zoom;
+ float extend_height = initial_viewport_size.Height() / extend_zoom;
+
+ if (result_max_width == ViewportDescription::kValueExtendToZoom)
+ result_max_width = extend_width;
+
+ if (result_max_height == ViewportDescription::kValueExtendToZoom)
+ result_max_height = extend_height;
+
+ if (result_min_width == ViewportDescription::kValueExtendToZoom)
+ result_min_width =
+ CompareIgnoringAuto(extend_width, result_max_width, std::max);
+
+ if (result_min_height == ViewportDescription::kValueExtendToZoom)
+ result_min_height =
+ CompareIgnoringAuto(extend_height, result_max_height, std::max);
+ }
+
+ // Resolve initial width from min/max descriptors.
+ if (result_min_width != ViewportDescription::kValueAuto ||
+ result_max_width != ViewportDescription::kValueAuto)
+ result_width = CompareIgnoringAuto(
+ result_min_width,
+ CompareIgnoringAuto(result_max_width, initial_viewport_size.Width(),
+ std::min),
+ std::max);
+
+ // Resolve initial height from min/max descriptors.
+ if (result_min_height != ViewportDescription::kValueAuto ||
+ result_max_height != ViewportDescription::kValueAuto)
+ result_height = CompareIgnoringAuto(
+ result_min_height,
+ CompareIgnoringAuto(result_max_height, initial_viewport_size.Height(),
+ std::min),
+ std::max);
+
+ // Resolve width value.
+ if (result_width == ViewportDescription::kValueAuto) {
+ if (result_height == ViewportDescription::kValueAuto ||
+ !initial_viewport_size.Height())
+ result_width = initial_viewport_size.Width();
+ else
+ result_width = result_height * (initial_viewport_size.Width() /
+ initial_viewport_size.Height());
+ }
+
+ // Resolve height value.
+ if (result_height == ViewportDescription::kValueAuto) {
+ if (!initial_viewport_size.Width())
+ result_height = initial_viewport_size.Height();
+ else
+ result_height = result_width * initial_viewport_size.Height() /
+ initial_viewport_size.Width();
+ }
+
+ // Resolve initial-scale value.
+ if (result_zoom == ViewportDescription::kValueAuto) {
+ if (result_width != ViewportDescription::kValueAuto && result_width > 0)
+ result_zoom = initial_viewport_size.Width() / result_width;
+ if (result_height != ViewportDescription::kValueAuto && result_height > 0) {
+ // if 'auto', the initial-scale will be negative here and thus ignored.
+ result_zoom = std::max<float>(
+ result_zoom, initial_viewport_size.Height() / result_height);
+ }
+
+ // Reconstrain zoom value to the [min-zoom, max-zoom] range.
+ result_zoom = CompareIgnoringAuto(
+ result_min_zoom,
+ CompareIgnoringAuto(result_max_zoom, result_zoom, std::min), std::max);
+ }
+
+ // If user-scalable = no, lock the min/max scale to the computed initial
+ // scale.
+ if (!result_user_zoom)
+ result_min_zoom = result_max_zoom = result_zoom;
+
+ // Only set initialScale to a value if it was explicitly set.
+ if (zoom == ViewportDescription::kValueAuto)
+ result_zoom = ViewportDescription::kValueAuto;
+
+ PageScaleConstraints result;
+ result.minimum_scale = result_min_zoom;
+ result.maximum_scale = result_max_zoom;
+ result.initial_scale = result_zoom;
+ result.layout_size.SetWidth(result_width);
+ result.layout_size.SetHeight(result_height);
+ return result;
+}
+
+void ViewportDescription::ReportMobilePageStats(
+ const LocalFrame* main_frame) const {
+ if (!main_frame || !main_frame->GetPage() || !main_frame->View() ||
+ !main_frame->GetDocument())
+ return;
+
+ if (!main_frame->GetSettings() ||
+ !main_frame->GetSettings()->GetViewportEnabled())
+ return;
+
+ // Avoid chrome:// pages like the new-tab page (on Android new tab is
+ // non-http).
+ if (!main_frame->GetDocument()->Url().ProtocolIsInHTTPFamily())
+ return;
+
+ DEFINE_STATIC_LOCAL(
+ EnumerationHistogram, meta_tag_type_histogram,
+ ("Viewport.MetaTagType", static_cast<int>(ViewportUMAType::kTypeCount)));
+ if (!IsSpecifiedByAuthor()) {
+ meta_tag_type_histogram.Count(
+ main_frame->GetDocument()->IsMobileDocument()
+ ? static_cast<int>(ViewportUMAType::kXhtmlMobileProfile)
+ : static_cast<int>(ViewportUMAType::kNoViewportTag));
+ return;
+ }
+
+ if (IsMetaViewportType()) {
+ if (max_width.GetType() == blink::kFixed) {
+ meta_tag_type_histogram.Count(
+ static_cast<int>(ViewportUMAType::kConstantWidth));
+
+ if (main_frame->View()) {
+ // To get an idea of how "far" the viewport is from the device's ideal
+ // width, we report the zoom level that we'd need to be at for the
+ // entire page to be visible.
+ int viewport_width = max_width.IntValue();
+ int window_width =
+ main_frame->GetPage()->GetVisualViewport().Size().Width();
+ int overview_zoom_percent =
+ 100 * window_width / static_cast<float>(viewport_width);
+ DEFINE_STATIC_LOCAL(SparseHistogram, overview_zoom_histogram,
+ ("Viewport.OverviewZoom"));
+ overview_zoom_histogram.Sample(overview_zoom_percent);
+ }
+
+ } else if (max_width.GetType() == blink::kDeviceWidth ||
+ max_width.GetType() == blink::kExtendToZoom) {
+ meta_tag_type_histogram.Count(
+ static_cast<int>(ViewportUMAType::kDeviceWidth));
+ } else {
+ // Overflow bucket for cases we may be unaware of.
+ meta_tag_type_histogram.Count(
+ static_cast<int>(ViewportUMAType::kMetaWidthOther));
+ }
+ } else if (type == ViewportDescription::kHandheldFriendlyMeta) {
+ meta_tag_type_histogram.Count(
+ static_cast<int>(ViewportUMAType::kMetaHandheldFriendly));
+ } else if (type == ViewportDescription::kMobileOptimizedMeta) {
+ meta_tag_type_histogram.Count(
+ static_cast<int>(ViewportUMAType::kMetaMobileOptimized));
+ }
+}
+
+bool ViewportDescription::MatchesHeuristicsForGpuRasterization() const {
+ return IsSpecifiedByAuthor();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/page/viewport_description.h b/chromium/third_party/blink/renderer/core/page/viewport_description.h
new file mode 100644
index 00000000000..a0ed23ad0be
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/page/viewport_description.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * (C) 2001 Dirk Mueller (mueller@kde.org)
+ * (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Torch Mobile Inc. All rights reserved.
+ * (http://www.torchmobile.com/)
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
+ *
+ * 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_PAGE_VIEWPORT_DESCRIPTION_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_VIEWPORT_DESCRIPTION_H_
+
+#include "base/optional.h"
+#include "third_party/blink/public/mojom/page/display_cutout.mojom-blink.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/frame/page_scale_constraints.h"
+#include "third_party/blink/renderer/platform/geometry/float_size.h"
+#include "third_party/blink/renderer/platform/length.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+
+namespace blink {
+
+class LocalFrame;
+
+struct CORE_EXPORT ViewportDescription {
+ DISALLOW_NEW();
+
+ enum Type {
+ // These are ordered in increasing importance.
+ kUserAgentStyleSheet,
+ kHandheldFriendlyMeta,
+ kMobileOptimizedMeta,
+ kViewportMeta,
+ kAuthorStyleSheet
+ } type;
+
+ // Enums used to record the kind of viewport in the Viewport.MetaTagType
+ // histogram. These must match the enums in histograms.xml and existing
+ // entries must not be changed.
+ enum class ViewportUMAType : int {
+ kNoViewportTag = 0,
+ kDeviceWidth = 1,
+ kConstantWidth = 2,
+ kMetaWidthOther = 3,
+ kMetaHandheldFriendly = 4,
+ kMetaMobileOptimized = 5,
+ kXhtmlMobileProfile = 6,
+
+ kTypeCount = 7
+ };
+
+ enum {
+ kValueAuto = -1,
+ kValueDeviceWidth = -2,
+ kValueDeviceHeight = -3,
+ kValuePortrait = -4,
+ kValueLandscape = -5,
+ kValueDeviceDPI = -6,
+ kValueLowDPI = -7,
+ kValueMediumDPI = -8,
+ kValueHighDPI = -9,
+ kValueExtendToZoom = -10
+ };
+
+ ViewportDescription(Type type = kUserAgentStyleSheet)
+ : type(type),
+ zoom(kValueAuto),
+ min_zoom(kValueAuto),
+ max_zoom(kValueAuto),
+ user_zoom(true),
+ orientation(kValueAuto),
+ deprecated_target_density_dpi(kValueAuto),
+ zoom_is_explicit(false),
+ min_zoom_is_explicit(false),
+ max_zoom_is_explicit(false),
+ user_zoom_is_explicit(false) {}
+
+ // All arguments are in CSS units.
+ PageScaleConstraints Resolve(const FloatSize& initial_viewport_size,
+ Length legacy_fallback_width) const;
+
+ // When --use-zoom-for-dsf is enabled, if the type is kFixed, these Length
+ // values (i.e., |min_width|, |max_width|, |min_height|, and |max_height|)
+ // must be in physical pixel scale. When --use-zoom-for-dsf is disabled, if
+ // the type is kFixed, these Length values must be in DIP scale.
+ Length min_width;
+ Length max_width;
+ Length min_height;
+ Length max_height;
+ float zoom;
+ float min_zoom;
+ float max_zoom;
+ bool user_zoom;
+ float orientation;
+ float deprecated_target_density_dpi; // Only used for Android WebView
+
+ // Whether the computed value was explicitly specified rather than being
+ // inferred.
+ bool zoom_is_explicit;
+ bool min_zoom_is_explicit;
+ bool max_zoom_is_explicit;
+ bool user_zoom_is_explicit;
+
+ mojom::ViewportFit GetViewportFit() const {
+ return viewport_fit_.value_or(mojom::ViewportFit::kAuto);
+ }
+ void SetViewportFit(mojom::ViewportFit value) { viewport_fit_ = value; }
+
+ bool operator==(const ViewportDescription& other) const {
+ // Used for figuring out whether to reset the viewport or not,
+ // thus we are not taking type into account.
+ return min_width == other.min_width && max_width == other.max_width &&
+ min_height == other.min_height && max_height == other.max_height &&
+ zoom == other.zoom && min_zoom == other.min_zoom &&
+ max_zoom == other.max_zoom && user_zoom == other.user_zoom &&
+ orientation == other.orientation &&
+ deprecated_target_density_dpi ==
+ other.deprecated_target_density_dpi &&
+ zoom_is_explicit == other.zoom_is_explicit &&
+ min_zoom_is_explicit == other.min_zoom_is_explicit &&
+ max_zoom_is_explicit == other.max_zoom_is_explicit &&
+ user_zoom_is_explicit == other.user_zoom_is_explicit &&
+ viewport_fit_ == other.viewport_fit_;
+ }
+
+ bool operator!=(const ViewportDescription& other) const {
+ return !(*this == other);
+ }
+
+ bool IsLegacyViewportType() const {
+ return type >= kHandheldFriendlyMeta && type <= kViewportMeta;
+ }
+ bool IsMetaViewportType() const { return type == kViewportMeta; }
+ bool IsSpecifiedByAuthor() const { return type != kUserAgentStyleSheet; }
+ bool MatchesHeuristicsForGpuRasterization() const;
+
+ // Reports UMA stat on whether the page is considered mobile or desktop and
+ // what kind of mobile it is. Applies only to Android, must only be called
+ // once per page load.
+ void ReportMobilePageStats(const LocalFrame*) const;
+
+ private:
+ enum Direction { kHorizontal, kVertical };
+ static float ResolveViewportLength(const Length&,
+ const FloatSize& initial_viewport_size,
+ Direction);
+
+ // Optional is used to identify if |viewport_fit_| has been explicitly set.
+ // This is because a Document will have multiple ViewportDescriptions are
+ // which one that will be used is dependent on whether any values have been
+ // explicitly set.
+ base::Optional<mojom::ViewportFit> viewport_fit_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAGE_VIEWPORT_DESCRIPTION_H_
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 b36669cba5e..fff7feaf4ac 100644
--- a/chromium/third_party/blink/renderer/core/page/viewport_test.cc
+++ b/chromium/third_party/blink/renderer/core/page/viewport_test.cc
@@ -37,7 +37,6 @@
#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_view_client.h"
-#include "third_party/blink/renderer/core/dom/viewport_description.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
@@ -45,6 +44,7 @@
#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/page/page.h"
+#include "third_party/blink/renderer/core/page/viewport_description.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"
diff --git a/chromium/third_party/blink/renderer/core/paint/BUILD.gn b/chromium/third_party/blink/renderer/core/paint/BUILD.gn
index 46f559f87f5..9b23bff71aa 100644
--- a/chromium/third_party/blink/renderer/core/paint/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/paint/BUILD.gn
@@ -63,6 +63,8 @@ blink_core_sources("paint") {
"compositing/compositing_requirements_updater.h",
"compositing/compositing_state.h",
"compositing/compositing_triggers.h",
+ "compositing/graphics_layer_tree_as_text.cc",
+ "compositing/graphics_layer_tree_as_text.h",
"compositing/graphics_layer_tree_builder.cc",
"compositing/graphics_layer_tree_builder.h",
"compositing/graphics_layer_updater.cc",
@@ -74,6 +76,8 @@ blink_core_sources("paint") {
"decoration_info.h",
"details_marker_painter.cc",
"details_marker_painter.h",
+ "document_marker_painter.cc",
+ "document_marker_painter.h",
"ellipsis_box_painter.cc",
"ellipsis_box_painter.h",
"embedded_content_painter.cc",
@@ -90,13 +94,9 @@ blink_core_sources("paint") {
"file_upload_control_painter.h",
"filter_effect_builder.cc",
"filter_effect_builder.h",
- "filter_painter.cc",
- "filter_painter.h",
"find_properties_needing_update.h",
"first_meaningful_paint_detector.cc",
"first_meaningful_paint_detector.h",
- "float_clip_recorder.cc",
- "float_clip_recorder.h",
"fragment_data.cc",
"fragment_data.h",
"frame_paint_timing.h",
@@ -118,8 +118,6 @@ blink_core_sources("paint") {
"inline_painter.h",
"inline_text_box_painter.cc",
"inline_text_box_painter.h",
- "layer_clip_recorder.cc",
- "layer_clip_recorder.h",
"line_box_list_painter.cc",
"line_box_list_painter.h",
"link_highlight_impl.cc",
@@ -159,8 +157,6 @@ blink_core_sources("paint") {
"object_painter_base.h",
"paint_event.h",
"paint_info.h",
- "paint_invalidation_capable_scrollable_area.cc",
- "paint_invalidation_capable_scrollable_area.h",
"paint_invalidator.cc",
"paint_invalidator.h",
"paint_layer.cc",
@@ -196,12 +192,8 @@ blink_core_sources("paint") {
"root_inline_box_painter.h",
"rounded_inner_rect_clipper.cc",
"rounded_inner_rect_clipper.h",
- "scroll_recorder.cc",
- "scroll_recorder.h",
"scrollable_area_painter.cc",
"scrollable_area_painter.h",
- "scrollbar_manager.cc",
- "scrollbar_manager.h",
"scrollbar_painter.cc",
"scrollbar_painter.h",
"selection_painting_utils.cc",
@@ -220,6 +212,8 @@ blink_core_sources("paint") {
"svg_inline_text_box_painter.h",
"svg_mask_painter.cc",
"svg_mask_painter.h",
+ "svg_model_object_painter.cc",
+ "svg_model_object_painter.h",
"svg_paint_context.cc",
"svg_paint_context.h",
"svg_root_inline_box_painter.cc",
@@ -242,6 +236,8 @@ blink_core_sources("paint") {
"table_row_painter.h",
"table_section_painter.cc",
"table_section_painter.h",
+ "text_control_single_line_painter.cc",
+ "text_control_single_line_painter.h",
"text_paint_style.h",
"text_painter.cc",
"text_painter.h",
@@ -253,10 +249,6 @@ blink_core_sources("paint") {
"theme_painter_default.h",
"theme_painter_mac.h",
"theme_painter_mac.mm",
- "transform_3d_recorder.cc",
- "transform_3d_recorder.h",
- "transform_recorder.cc",
- "transform_recorder.h",
"video_painter.cc",
"video_painter.h",
"view_painter.cc",
diff --git a/chromium/third_party/blink/renderer/core/paint/README.md b/chromium/third_party/blink/renderer/core/paint/README.md
index 0a3e2ed55b7..5402cf655e7 100644
--- a/chromium/third_party/blink/renderer/core/paint/README.md
+++ b/chromium/third_party/blink/renderer/core/paint/README.md
@@ -42,7 +42,7 @@ are treated in different ways during painting:
elements because `z-index:auto` and `z-index:0` are considered equal for
stacking context sorting and they may interleave by DOM order.
- The difference of a stacked element of this type from a real stacking
+ The difference of a stacked element of this type from a real stacking
context is that it doesn't manage z-ordering of stacked descendants.
These descendants are managed by the parent stacking context of this
stacked element.
@@ -113,52 +113,49 @@ and associated display items).
At the time of writing, there are three operation modes that are switched by
`RuntimeEnabledFeatures`.
-### SlimmingPaintV1 (a.k.a. SPv1, SPv1.5, old-world compositing)
-This is the default operation mode. In this mode, layerization runs before
-pre-paint and paint. `PaintLayerCompositor` and `CompositedLayerMapping` use
-layout and style information to determine which subtrees of the `PaintLayer`
-tree should be pulled out to paint in its own layer, this is also known as
-'being composited'. Transforms, clips, and effects enclosing the subtree are
-applied as `GraphicsLayer` parameters.
-
-Then during pre-paint, a property tree is generated for fast calculating
-paint location and visual rects of each `LayoutObject` on their backing layer,
-for invalidation purposes.
+### SlimmingPaintV175 (a.k.a. SPv1.75)
-During paint, the paint function of each `GraphicsLayer` created by
-`CompositedLayerMapping` will be invoked, which then calls into the painter
-of each `PaintLayer` subtree. The painter then outputs a list of display
-items which may be drawing, or meta display items that represents non-composited
-transforms, clips and effects.
+This mode is for incrementally shipping completed features from SPv2. SPv1.75
+reuses layerization from SPv1, but will cherrypick property-tree-based paint
+from SPv2. Meta display items are abandoned in favor of property tree. Each
+drawable GraphicsLayer's layer state will be computed by the property tree
+builder. During paint, each display item will be associated with a property
+tree state. At the end of paint, meta display items will be generated from
+the state differences between the chunk and the layer.
+```
+from layout
|
- | from layout
v
+------------------------------+
-| LayoutObject/PaintLayer tree |
-+------------------------------+
- |
- | PaintLayerCompositor::UpdateIfNeeded()
- | CompositingInputsUpdater::Update()
- | CompositingLayerAssigner::Assign()
- | GraphicsLayerUpdater::Update()
- | GraphicsLayerTreeBuilder::Rebuild()
- v
-+--------------------+
-| GraphicsLayer tree |
-+--------------------+
- | |
- | | LocalFrameView::PaintTree()
- | | LocalFrameView::PaintGraphicsLayerRecursively()
- | | GraphicsLayer::Paint()
- | | CompositedLayerMapping::PaintContents()
- | | PaintLayerPainter::PaintLayerContents()
- | | ObjectPainter::Paint()
- | v
- | +-----------------+
- | | DisplayItemList |
- | +-----------------+
+| LayoutObject/PaintLayer tree |-----------+
++------------------------------+ |
+ | |
+ | PaintLayerCompositor::UpdateIfNeeded() |
+ | CompositingInputsUpdater::Update() |
+ | CompositingLayerAssigner::Assign() |
+ | GraphicsLayerUpdater::Update() | PrePaintTreeWalk::Walk()
+ | GraphicsLayerTreeBuilder::Rebuild() | PaintPropertyTreeBuider::UpdatePropertiesForSelf()
+ v |
++--------------------+ +------------------+
+| GraphicsLayer tree |<------------------| Property trees |
++--------------------+ +------------------+
+ | | | |
+ | |<-----------------------------------+ |
+ | | LocalFrameView::PaintTree() |
+ | | LocalFrameView::PaintGraphicsLayerRecursively() |
+ | | GraphicsLayer::Paint() |
+ | | CompositedLayerMapping::PaintContents() |
+ | | PaintLayerPainter::PaintLayerContents() |
+ | | ObjectPainter::Paint() |
+ | v |
+ | +---------------------------------+ |
+ | | DisplayItemList/PaintChunk list | |
+ | +---------------------------------+ |
+ | | |
+ | |<--------------------------------------------------+
+ | | PaintChunksToCcLayer::Convert()
| |
| | WebContentLayer shim
v v
@@ -168,6 +165,139 @@ transforms, clips and effects.
|
| to compositor
v
+```
+
+#### SPv1 compositing algorithm
+
+The SPv1 compositing system chooses which `LayoutObject`s paint into their
+own composited backing texture. This is called "having a compositing trigger".
+These textures correspond to GraphicsLayers. There are also additional
+`GraphicsLayer`s which represent property tree-related effects.
+
+All elements which do not have a compositing trigger paint into the texture
+of the nearest `LayoutObject`with a compositing trigger on its
+*compositing container chain* (except for squashed layers; see below). For
+historical, practical and implementation detail reasons, only `LayoutObject`s
+with `PaintLayer`s can have a compositing trigger. See crbug.com/370604 for a
+bug tracking this limitation, which is often referred to as the "fundamental
+compositing bug".
+
+The various compositing triggers are listed
+[here](../../platform/graphics/compositing_reasons.h).
+They fall in to several categories:
+1. Direct reasons due to CSS style (see `CompositingReason::kComboAllDirectStyleDeterminedReasons`)
+2. Direct reasons due to other conditions (see `CompositingReason::kComboAllDirectNonStyleDeterminedReasons`)
+3. Composited scrolling-dependent reasons (see `CompositingReason::kComboAllCompositedScrollingDeterminedReasons`)
+4. Composited descendant-dependent reasons (see `CompositingReason::kComboCompositedDescendants`)
+5. Overlap-dependent reasons (See `CompositingReasons::kComboSquashableReasons`)
+
+The triggers have no effect unless `PaintLayerCompositor::CanBeComposited`
+returns true.
+
+Category (1) always triggers compositing of a `LayoutObject` based on its own
+style. Category (2) triggers based on the `LayoutObject`'s style, its DOM
+ancestors, and whether it is a certain kind of frame root. Category (3)
+triggers based on whether composited scrolling applies to the `LayoutObject`,
+or the `LayoutObject` moves relative to a composited scroller (position: fixed
+or position: sticky). Category (4) triggers if there are any stacking
+descendants of the `LayoutObject` that end up composited. Category 5 triggers
+if the `LayoutObject` paints after and overlaps (or may overlap) another
+composited layer.
+
+Note that composited scrolling is special. Several ways it is special:
+ * Composited descendants do _not_ necessarily cause composited scrolling of an
+ancestor.
+ * The presence of LCD text prevents composited scrolling in the
+absence of other overriding triggers.
+ * Local frame roots always use
+composited scrolling if they have overflow.
+ * Non-local frame roots use
+composited scrolling if they have overflow and any composited descendants.
+ * Composited scrolling is indicated by a bit on PaintLayerScrollableArea, not
+ a direct compositing reason. This bit is then transformed into a compositing
+ reason from category (3) during the CompositingRequirementsUpdater
+
+Note that overlap triggers have two special behaviors:
+ * Any `LayoutObject`
+which may overlap a `LayoutObject` that uses composited scrolling or a
+transform animation, paints after it, and scrolls with respect to it, receives
+an overlap trigger. In some cases this trigger is too aggressive.
+ * Inline CSS
+transform is treated as if it was a transform animation. (This is a heuristic
+to speed up the compositing step but leads to more composited layers.)
+
+The sequence of work during the `DocumentLifecycle` to compute these triggers
+is as follows:
+
+ * `kInStyleRecalc`: compute (1) and most of (4) by calling
+`CompositingReasonFinder::PotentialCompositingReasonsFromStyle` and caching
+the result on `PaintLayer`, accessible via
+`PaintLayer::PotentialCompositingReasonsFromStyle`. Dirty bits in
+`StyleDifference` determine whether this has to be re-computed on a particular
+lifecycle update.
+ * `kInCompositingUpdate`: compute (2) `CompositingInputsUpdater`. Also
+ set the composited scrolling bit on `PaintLayerScrollableArea` if applicable.
+ * `kCompositingInputsClean`: compute (3), the rest of (4), and (5), in
+`CompositingRequirementsUpdater`
+
+### BlinkGenPropertyTrees
+
+This mode is for incrementally shipping completed features from SPv2. It is
+based on SPv1.75 and starts sending a layer list and property trees directly to
+the compositor. BlinkGenPropertyTrees still uses the GraphicsLayers from SPv1.75
+and plugs them in as foreign layers to the SPv2 compositor
+(PaintArtifactCompositor).
+
+```
+from layout
+ |
+ v
++------------------------------+
+| LayoutObject/PaintLayer tree |-----------+
++------------------------------+ |
+ | |
+ | PaintLayerCompositor::UpdateIfNeeded() |
+ | CompositingInputsUpdater::Update() |
+ | CompositingLayerAssigner::Assign() |
+ | GraphicsLayerUpdater::Update() | PrePaintTreeWalk::Walk()
+ | GraphicsLayerTreeBuilder::Rebuild() | PaintPropertyTreeBuider::UpdatePropertiesForSelf()
+ v |
++--------------------+ +------------------+
+| GraphicsLayer tree |<------------------| Property trees |
++--------------------+ +------------------+
+ | | |
+ |<-----------------------------------+ |
+ | LocalFrameView::PaintTree() |
+ | LocalFrameView::PaintGraphicsLayerRecursively() |
+ | GraphicsLayer::Paint() |
+ | CompositedLayerMapping::PaintContents() |
+ | PaintLayerPainter::PaintLayerContents() |
+ | ObjectPainter::Paint() |
+ v |
+ +---------------------------------+ |
+ | DisplayItemList/PaintChunk list | |
+ +---------------------------------+ |
+ | |
+ |<--------------------------------------------------+
+ | PaintChunksToCcLayer::Convert() |
+ v |
++----------------+ |
+| Foreign layers | |
++----------------+ |
+ | |
+ | LocalFrameView::PushPaintArtifactToCompositor() |
+ | PaintArtifactCompositor::Update() |
+ +--------------------+ +--------------------------+
+ | |
+ v v
+ +----------------+ +-----------------------+
+ | cc::Layer list | | cc property trees |
+ +----------------+ +-----------------------+
+ | |
+ +-------------+--------------+
+ | to compositor
+ v
+```
### SlimmingPaintV2 (a.k.a. SPv2)
@@ -183,8 +313,9 @@ Adjacent display items having the same property tree state will be grouped as
composited are converted into cc property nodes, while non-composited property
nodes are converted into meta display items by `PaintChunksToCcLayer`.
+```
+from layout
|
- | from layout
v
+------------------------------+
| LayoutObject/PaintLayer tree |
@@ -225,72 +356,18 @@ nodes are converted into meta display items by `PaintChunksToCcLayer`.
+------------------+
| to compositor
v
-
-### SlimmingPaintV175 (a.k.a. SPv1.75)
-
-This mode is for incrementally shipping completed features from SPv2. It is
-numbered 1.75 because invalidation using property trees was called SPv1.5,
-which is now a part of SPv1. SPv1.75 will again replace SPv1 once completed.
-
-SPv1.75 reuses layerization from SPv1, but will cherrypick property-tree-based
-paint from SPv2. Meta display items are abandoned in favor of property tree.
-Each drawable GraphicsLayer's layer state will be computed by the property tree
-builder. During paint, each display item will be associated with a property
-tree state. At the end of paint, meta display items will be generated from
-the state differences between the chunk and the layer.
-
- |
- | from layout
- v
-+------------------------------+
-| LayoutObject/PaintLayer tree |-----------+
-+------------------------------+ |
- | |
- | PaintLayerCompositor::UpdateIfNeeded() |
- | CompositingInputsUpdater::Update() |
- | CompositingLayerAssigner::Assign() |
- | GraphicsLayerUpdater::Update() | PrePaintTreeWalk::Walk()
- | GraphicsLayerTreeBuilder::Rebuild() | PaintPropertyTreeBuider::UpdatePropertiesForSelf()
- v |
-+--------------------+ +------------------+
-| GraphicsLayer tree |<------------------| Property trees |
-+--------------------+ +------------------+
- | | | |
- | |<-----------------------------------+ |
- | | LocalFrameView::PaintTree() |
- | | LocalFrameView::PaintGraphicsLayerRecursively() |
- | | GraphicsLayer::Paint() |
- | | CompositedLayerMapping::PaintContents() |
- | | PaintLayerPainter::PaintLayerContents() |
- | | ObjectPainter::Paint() |
- | v |
- | +---------------------------------+ |
- | | DisplayItemList/PaintChunk list | |
- | +---------------------------------+ |
- | | |
- | |<--------------------------------------------------+
- | | PaintChunksToCcLayer::Convert()
- | |
- | | WebContentLayer shim
- v v
-+----------------+
-| cc::Layer tree |
-+----------------+
- |
- | to compositor
- v
+```
### Comparison of the three modes
- | SPv1 | SPv175 | SPv2
---------------------------+--------------------+--------------------+-------------
-REF::SPv175Enabled | false | true | true
-REF::SPv2Enabled | false | false | true
-Property tree | without effects | full | full
-Paint chunks | no | yes | yes
-Layerization | PLC/CLM | PLC/CLM | PAC
-Non-composited properties | meta items | PC2CL | PC2CL
-Raster invalidation | LayoutObject-based | LayoutObject-based | chunk-based
+```
+ | SPv175 | BlinkGenPropertyTrees | SPv2
+---------------------------------+--------------------+-----------------------+-------
+REF::BlinkGenPropertyTreesEnabled| false | true | false
+REF::SPv2Enabled | false | false | true
+Layerization | PLC/CLM | PLC/CLM | PAC
+cc property tree builder | on | off | off
+```
## PaintInvalidation (Deprecated by [PrePaint](#PrePaint))
@@ -321,7 +398,7 @@ is created for the root `LayoutView`. During the tree walk, one
information to provide O(1) complexity access to them if possible:
* Paint invalidation container: Since as indicated by the definitions in
- [Glossaries](#Other glossaries), the paint invalidation container for
+ [Glossaries](#other-glossaries), the paint invalidation container for
stacked objects can differ from normal objects, we have to track both
separately. Here is an example:
@@ -528,3 +605,32 @@ needs all paint phases that its container self-painting layer needs.
We could update the `NeedsPaintPhaseXXX` flags in a separate tree walk, but that
would regress performance of the first paint. For slimming paint v2, we can
update the flags during the pre-painting tree walk to simplify the logics.
+
+### Hit test painting
+
+Hit testing is done in paint-order. The |PaintTouchActionRects| flag enables a
+mode where hit test display items are emitted in the background phase of
+painting. Hit test display items are produced even if there is no painted
+content.
+
+### PaintNG
+
+[LayoutNG](../layout/ng/README.md]) is a project that will change how Layout
+generates geometry/style information for painting. Instead of modifying
+LayoutObjects, LayoutNG will generate an NGFragment tree.
+
+NGPaintFragments are:
+* immutable
+* all coordinates are physical. See
+[layout_box_model_object.h](../layout/layout_box_model_object.h).
+* instead of Location(), NGFragment has Offset(), a physical offset from parent
+fragment.
+
+The goal is for PaintNG to eventually paint from NGFragment tree,
+and not see LayoutObjects at all. Until this goal is reached,
+LegacyPaint, and NGPaint will coexist.
+
+When a particular LayoutObject subclass fully migrates to NG, its LayoutObject
+geometry information might no longer be updated\(\*\), and its
+painter needs to be rewritten to paint NGFragments.
+For example, see how BlockPainter is being rewritten as NGBoxFragmentPainter.
diff --git a/chromium/third_party/blink/renderer/core/paint/adjust_paint_offset_scope.cc b/chromium/third_party/blink/renderer/core/paint/adjust_paint_offset_scope.cc
index f0e438c5018..e0f8049d30d 100644
--- a/chromium/third_party/blink/renderer/core/paint/adjust_paint_offset_scope.cc
+++ b/chromium/third_party/blink/renderer/core/paint/adjust_paint_offset_scope.cc
@@ -4,71 +4,39 @@
#include "third_party/blink/renderer/core/paint/adjust_paint_offset_scope.h"
-#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
-#include "third_party/blink/renderer/core/layout/layout_table_section.h"
-
namespace blink {
-bool AdjustPaintOffsetScope::AdjustPaintOffset(const LayoutBox& box) {
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
-
- if (box.HasSelfPaintingLayer())
- return false;
-
- // TODO(wangxianzhu): Expose fragment so that the client doesn't need to
- // call FragmentToPaint() again when needed.
- const auto* fragment = old_paint_info_.FragmentToPaint(box);
- if (!fragment) {
- // TODO(wangxianzhu): The client should know the case and bail out of
- // painting of itself.
- return false;
- }
-
- const auto* paint_properties = fragment->PaintProperties();
- if (paint_properties && paint_properties->PaintOffsetTranslation()) {
- contents_properties_.emplace(
- old_paint_info_.context.GetPaintController(),
- fragment->LocalBorderBoxProperties(), box,
- DisplayItem::PaintPhaseToDrawingType(old_paint_info_.phase));
-
- new_paint_info_.emplace(old_paint_info_);
- new_paint_info_->UpdateCullRect(paint_properties->PaintOffsetTranslation()
- ->Matrix()
- .ToAffineTransform());
-
- adjusted_paint_offset_ = fragment->PaintOffset();
- return true;
+void AdjustPaintOffsetScope::AdjustForPaintOffsetTranslation(
+ const LayoutObject& object,
+ const TransformPaintPropertyNode* paint_offset_translation) {
+ if (input_paint_info_.context.InDrawingRecorder()) {
+ // If we are recording drawings, we should issue the translation as a raw
+ // paint operation instead of paint chunk properties. One case is that we
+ // are painting table row background behind a cell having paint offset
+ // translation.
+ input_paint_info_.context.Save();
+ FloatSize translation =
+ paint_offset_translation->Matrix().To2DTranslation();
+ input_paint_info_.context.Translate(translation.Width(),
+ translation.Height());
+ paint_offset_translation_as_drawing_ = true;
+ } else {
+ chunk_properties_.emplace(
+ input_paint_info_.context.GetPaintController(),
+ paint_offset_translation, object,
+ DisplayItem::PaintPhaseToDrawingType(input_paint_info_.phase));
}
- if (box.IsFixedPositionObjectInPagedMedia()) {
- adjusted_paint_offset_ = fragment->PaintOffset();
- return true;
- }
-
- if (box.IsTableSection()) {
- const auto& section = ToLayoutTableSection(box);
- if (section.IsRepeatingHeaderGroup() || section.IsRepeatingFooterGroup()) {
- adjusted_paint_offset_ = fragment->PaintOffset();
- return true;
- }
- }
-
- // TODO(wangxianzhu): Use fragment->PaintOffset() for all cases and eliminate
- // the paint_offset parameter of paint methods.
- return false;
+ adjusted_paint_info_.emplace(input_paint_info_);
+ adjusted_paint_info_->UpdateCullRect(
+ paint_offset_translation->Matrix().ToAffineTransform());
}
-bool AdjustPaintOffsetScope::WillUseLegacyLocation(const LayoutBox* child) {
- if (child->HasSelfPaintingLayer())
- return true;
- if (child->IsLayoutNGMixin()) {
- NGPaintFragment* paint_fragment = ToLayoutBlockFlow(child)->PaintFragment();
- if (!paint_fragment)
- return true;
- if (!paint_fragment->PhysicalFragment().IsPlacedByLayoutNG())
- return true;
- return false;
- }
- return true;
+void AdjustPaintOffsetScope::FinishPaintOffsetTranslationAsDrawing() {
+ // This scope should not interlace with scopes of DrawingRecorders.
+ DCHECK(paint_offset_translation_as_drawing_);
+ DCHECK(input_paint_info_.context.InDrawingRecorder());
+ input_paint_info_.context.Restore();
}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/adjust_paint_offset_scope.h b/chromium/third_party/blink/renderer/core/paint/adjust_paint_offset_scope.h
index 23e015402ff..b698402e038 100644
--- a/chromium/third_party/blink/renderer/core/paint/adjust_paint_offset_scope.h
+++ b/chromium/third_party/blink/renderer/core/paint/adjust_paint_offset_scope.h
@@ -5,68 +5,83 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_ADJUST_PAINT_OFFSET_SCOPE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_ADJUST_PAINT_OFFSET_SCOPE_H_
-#include "third_party/blink/renderer/core/layout/layout_box.h"
+#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
namespace blink {
+// Adjusts cull rect of the input PaintInfo and finds the paint offset for a
+// LayoutObject or an NGPaintFragment before painting. Normally a
+// Paint(const PaintInfo&) method creates an AdjustPaintOffsetScope and holds it
+// in the stack, and passes it to other PaintXXX() methods that paint different
+// parts of the object.
class AdjustPaintOffsetScope {
STACK_ALLOCATED();
public:
- AdjustPaintOffsetScope(const LayoutBox& box,
- const PaintInfo& paint_info,
- const LayoutPoint& paint_offset)
- : old_paint_info_(paint_info) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() ||
- !AdjustPaintOffset(box))
- adjusted_paint_offset_ = paint_offset + box.Location();
+ AdjustPaintOffsetScope(const LayoutObject& object,
+ const PaintInfo& paint_info)
+ : fragment_to_paint_(paint_info.FragmentToPaint(object)),
+ input_paint_info_(paint_info) {
+ if (!fragment_to_paint_) {
+ // The object has nothing to paint in the current fragment.
+ return;
+ }
+ if (&object == paint_info.PaintContainer()) {
+ // PaintLayerPainter already adjusted for PaintOffsetTranslation for
+ // PaintContainer. TODO(wangxianzhu): Can we combine the code?
+ return;
+ }
+ const auto* properties = fragment_to_paint_->PaintProperties();
+ if (properties && properties->PaintOffsetTranslation()) {
+ AdjustForPaintOffsetTranslation(object,
+ properties->PaintOffsetTranslation());
+ }
}
AdjustPaintOffsetScope(const NGPaintFragment& fragment,
- const PaintInfo& paint_info,
- const LayoutPoint& paint_offset)
- : old_paint_info_(paint_info) {
- DCHECK(fragment.GetLayoutObject());
- const LayoutBox& box = ToLayoutBox(*fragment.GetLayoutObject());
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- AdjustPaintOffset(box))
- return;
- if (UNLIKELY(box.HasSelfPaintingLayer())) {
- // There is no containing block here, we are painting from origin.
- // paint_offset is 0,0
- // box.Location is offset from Layer()
- adjusted_paint_offset_ = paint_offset + box.Location();
- } else {
- adjusted_paint_offset_ = paint_offset + fragment.Offset().ToLayoutPoint();
- }
+ const PaintInfo& paint_info)
+ : AdjustPaintOffsetScope(*fragment.GetLayoutObject(), paint_info) {}
+
+ ~AdjustPaintOffsetScope() {
+ if (paint_offset_translation_as_drawing_)
+ FinishPaintOffsetTranslationAsDrawing();
}
const PaintInfo& GetPaintInfo() const {
- return new_paint_info_ ? *new_paint_info_ : old_paint_info_;
+ return adjusted_paint_info_ ? *adjusted_paint_info_ : input_paint_info_;
}
PaintInfo& MutablePaintInfo() {
- if (!new_paint_info_)
- new_paint_info_.emplace(old_paint_info_);
- return *new_paint_info_;
+ if (!adjusted_paint_info_)
+ adjusted_paint_info_.emplace(input_paint_info_);
+ return *adjusted_paint_info_;
}
- LayoutPoint AdjustedPaintOffset() const { return adjusted_paint_offset_; }
+ LayoutPoint PaintOffset() const {
+ // TODO(wangxianzhu): Use DCHECK(fragment_to_paint_) when all painters
+ // check FragmentToPaint() before painting.
+ return fragment_to_paint_
+ ? fragment_to_paint_->PaintOffset()
+ : LayoutPoint(LayoutUnit::NearlyMax(), LayoutUnit::NearlyMax());
+ }
- // True if child will use LayoutObject::Location to compute adjusted_offset.
- static bool WillUseLegacyLocation(const LayoutBox* child);
+ const FragmentData* FragmentToPaint() const { return fragment_to_paint_; }
private:
- // Returns true if paint info and offset has been adjusted.
- bool AdjustPaintOffset(const LayoutBox&);
+ void AdjustForPaintOffsetTranslation(
+ const LayoutObject&,
+ const TransformPaintPropertyNode* paint_offset_translation);
+
+ void FinishPaintOffsetTranslationAsDrawing();
- const PaintInfo& old_paint_info_;
- LayoutPoint adjusted_paint_offset_;
- base::Optional<PaintInfo> new_paint_info_;
- base::Optional<ScopedPaintChunkProperties> contents_properties_;
+ const FragmentData* fragment_to_paint_;
+ const PaintInfo& input_paint_info_;
+ base::Optional<PaintInfo> adjusted_paint_info_;
+ base::Optional<ScopedPaintChunkProperties> chunk_properties_;
+ bool paint_offset_translation_as_drawing_ = false;
};
} // namespace blink
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 92d3fd49049..1c4c1db236e 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
@@ -12,6 +12,7 @@
#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"
#include "third_party/blink/renderer/core/style/border_edge.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/layout_unit.h"
@@ -26,7 +27,6 @@ inline LayoutUnit GetSpaceBetweenImageTiles(LayoutUnit area_size,
LayoutUnit tile_size) {
int number_of_tiles = (area_size / tile_size).ToInt();
LayoutUnit space(-1);
-
if (number_of_tiles > 1) {
// Spec doesn't specify rounding, so use the same method as for
// background-repeat: round.
@@ -55,122 +55,6 @@ bool FixedBackgroundPaintsInLocalCoordinates(
return !mapping->BackgroundPaintsOntoScrollingContentsLayer();
}
-LayoutSize CalculateFillTileSize(const LayoutBoxModelObject& obj,
- const FillLayer& fill_layer,
- const LayoutSize& positioning_area_size) {
- StyleImage* image = fill_layer.GetImage();
- EFillSizeType type = fill_layer.SizeType();
-
- LayoutSize image_intrinsic_size(image->ImageSize(
- obj.GetDocument(), obj.Style()->EffectiveZoom(), positioning_area_size));
- switch (type) {
- case EFillSizeType::kSizeLength: {
- LayoutSize tile_size(positioning_area_size);
-
- const Length& layer_width = fill_layer.SizeLength().Width();
- const Length& layer_height = fill_layer.SizeLength().Height();
-
- if (layer_width.IsFixed())
- tile_size.SetWidth(LayoutUnit(layer_width.Value()));
- else if (layer_width.IsPercentOrCalc())
- tile_size.SetWidth(
- ValueForLength(layer_width, positioning_area_size.Width()));
-
- if (layer_height.IsFixed())
- tile_size.SetHeight(LayoutUnit(layer_height.Value()));
- else if (layer_height.IsPercentOrCalc())
- tile_size.SetHeight(
- ValueForLength(layer_height, positioning_area_size.Height()));
-
- // If one of the values is auto we have to use the appropriate
- // scale to maintain our aspect ratio.
- if (layer_width.IsAuto() && !layer_height.IsAuto()) {
- if (image->ImageHasRelativeSize()) {
- // Spec says that auto should be 100% in the absence of
- // an intrinsic ratio or size.
- tile_size.SetWidth(positioning_area_size.Width());
- } else if (image_intrinsic_size.Height()) {
- LayoutUnit adjusted_width = image_intrinsic_size.Width() *
- tile_size.Height() /
- image_intrinsic_size.Height();
- if (image_intrinsic_size.Width() >= 1 && adjusted_width < 1)
- adjusted_width = LayoutUnit(1);
- tile_size.SetWidth(adjusted_width);
- }
- } else if (!layer_width.IsAuto() && layer_height.IsAuto()) {
- if (image->ImageHasRelativeSize()) {
- // Spec says that auto should be 100% in the absence of
- // an intrinsic ratio or size.
- tile_size.SetHeight(positioning_area_size.Height());
- } else if (image_intrinsic_size.Width()) {
- LayoutUnit adjusted_height = image_intrinsic_size.Height() *
- tile_size.Width() /
- image_intrinsic_size.Width();
- if (image_intrinsic_size.Height() >= 1 && adjusted_height < 1)
- adjusted_height = LayoutUnit(1);
- tile_size.SetHeight(adjusted_height);
- }
- } else if (layer_width.IsAuto() && layer_height.IsAuto()) {
- // If both width and height are auto, use the image's intrinsic size.
- tile_size = image_intrinsic_size;
- }
-
- tile_size.ClampNegativeToZero();
- return tile_size;
- }
- case EFillSizeType::kSizeNone: {
- // If both values are 'auto' then the intrinsic width and/or height of the
- // image should be used, if any.
- if (!image_intrinsic_size.IsEmpty())
- return image_intrinsic_size;
-
- // If the image has neither an intrinsic width nor an intrinsic height,
- // its size is determined as for 'contain'.
- type = EFillSizeType::kContain;
- FALLTHROUGH;
- }
- case EFillSizeType::kContain:
- case EFillSizeType::kCover: {
- float horizontal_scale_factor =
- image_intrinsic_size.Width()
- ? positioning_area_size.Width().ToFloat() /
- image_intrinsic_size.Width()
- : 1.0f;
- float vertical_scale_factor =
- image_intrinsic_size.Height()
- ? positioning_area_size.Height().ToFloat() /
- image_intrinsic_size.Height()
- : 1.0f;
- // Force the dimension that determines the size to exactly match the
- // positioningAreaSize in that dimension, so that rounding of floating
- // point approximation to LayoutUnit do not shrink the image to smaller
- // than the positioningAreaSize.
- if (type == EFillSizeType::kContain) {
- if (horizontal_scale_factor < vertical_scale_factor)
- return LayoutSize(
- positioning_area_size.Width(),
- LayoutUnit(std::max(1.0f, image_intrinsic_size.Height() *
- horizontal_scale_factor)));
- return LayoutSize(
- LayoutUnit(std::max(
- 1.0f, image_intrinsic_size.Width() * vertical_scale_factor)),
- positioning_area_size.Height());
- }
- if (horizontal_scale_factor > vertical_scale_factor)
- return LayoutSize(
- positioning_area_size.Width(),
- LayoutUnit(std::max(1.0f, image_intrinsic_size.Height() *
- horizontal_scale_factor)));
- return LayoutSize(LayoutUnit(std::max(1.0f, image_intrinsic_size.Width() *
- vertical_scale_factor)),
- positioning_area_size.Height());
- }
- }
-
- NOTREACHED();
- return LayoutSize();
-}
-
IntPoint AccumulatedScrollOffsetForFixedBackground(
const LayoutBoxModelObject& object,
const LayoutBoxModelObject* container) {
@@ -190,148 +74,176 @@ IntPoint AccumulatedScrollOffsetForFixedBackground(
return result;
}
-// When we match the sub-pixel fraction of the destination rect in a dimension,
-// we snap the same way. This commonly occurs when the background is meant to
-// fill the padding box but there's a border (which in Blink is always stored as
-// an integer). Otherwise we floor to avoid growing our tile size. Often these
-// tiles are from a sprite map, and bleeding adjacent sprites is visually worse
-// than clipping the intended one.
-LayoutSize ApplySubPixelHeuristicToImageSize(const LayoutSize& size,
- const LayoutRect& destination) {
- LayoutSize snapped_size =
- LayoutSize(size.Width().Fraction() == destination.Width().Fraction()
- ? SnapSizeToPixel(size.Width(), destination.X())
- : size.Width().Floor(),
- size.Height().Fraction() == destination.Height().Fraction()
- ? SnapSizeToPixel(size.Height(), destination.Y())
- : size.Height().Floor());
- return snapped_size;
-}
-
} // anonymous namespace
-void BackgroundImageGeometry::SetNoRepeatX(LayoutUnit x_offset) {
- int rounded_offset = RoundToInt(x_offset);
- dest_rect_.Move(std::max(rounded_offset, 0), 0);
- SetPhaseX(LayoutUnit(-std::min(rounded_offset, 0)));
- dest_rect_.SetWidth(tile_size_.Width() + std::min(rounded_offset, 0));
+void BackgroundImageGeometry::SetNoRepeatX(LayoutUnit x_offset,
+ LayoutUnit snapped_x_offset) {
+ // The snapped offset may not yet be snapped, so make sure it is an integer.
+ snapped_x_offset = LayoutUnit(RoundToInt(snapped_x_offset));
+
+ 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());
+ snapped_dest_rect_.Move(snapped_x_offset, LayoutUnit());
+
+ // 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,
+ // the dest rect will be clipped when intersected with the paint
+ // rect.
+ unsnapped_dest_rect_.SetWidth(tile_size_.Width());
+ snapped_dest_rect_.SetWidth(tile_size_.Width());
+
+ SetPhaseX(0);
+ } else {
+ // Otherwise, if the offset is negative use it to move the image under
+ // the dest rect (since we can't paint outside the paint_rect).
+ SetPhaseX(-x_offset.ToFloat());
+
+ // Reduce the width of the dest rect to draw only the portion of the
+ // tile that remains visible after offsetting the image.
+ unsnapped_dest_rect_.SetWidth(tile_size_.Width() + x_offset);
+ snapped_dest_rect_.SetWidth(tile_size_.Width() + snapped_x_offset);
+ }
+
+ // Force the horizontal space to zero, retaining vertical.
SetSpaceSize(LayoutSize(LayoutUnit(), SpaceSize().Height()));
}
-void BackgroundImageGeometry::SetNoRepeatY(LayoutUnit y_offset) {
- int rounded_offset = RoundToInt(y_offset);
- dest_rect_.Move(0, std::max(rounded_offset, 0));
- SetPhaseY(LayoutUnit(-std::min(rounded_offset, 0)));
- dest_rect_.SetHeight(tile_size_.Height() + std::min(rounded_offset, 0));
+void BackgroundImageGeometry::SetNoRepeatY(LayoutUnit y_offset,
+ LayoutUnit snapped_y_offset) {
+ // The snapped offset may not yet be snapped, so make sure it is an integer.
+ snapped_y_offset = LayoutUnit(RoundToInt(snapped_y_offset));
+
+ 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);
+ snapped_dest_rect_.Move(LayoutUnit(), snapped_y_offset);
+
+ // 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,
+ // the dest rect will be clipped when intersected with the paint
+ // rect.
+ unsnapped_dest_rect_.SetHeight(tile_size_.Height());
+ snapped_dest_rect_.SetHeight(tile_size_.Height());
+
+ SetPhaseY(0);
+ } else {
+ // Otherwise, if the offset is negative, use it to move the image under
+ // the dest rect (since we can't paint outside the paint_rect).
+ SetPhaseY(-y_offset.ToFloat());
+
+ // Reduce the height of the dest rect to draw only the portion of the
+ // tile that remains visible after offsetting the image.
+ unsnapped_dest_rect_.SetHeight(tile_size_.Height() + y_offset);
+ snapped_dest_rect_.SetHeight(tile_size_.Height() + snapped_y_offset);
+ }
+
+ // Force the vertical space to zero, retaining horizontal.
SetSpaceSize(LayoutSize(SpaceSize().Width(), LayoutUnit()));
}
void BackgroundImageGeometry::SetRepeatX(const FillLayer& fill_layer,
- LayoutUnit unsnapped_tile_width,
- LayoutUnit snapped_available_width,
- LayoutUnit unsnapped_available_width,
- LayoutUnit extra_offset,
- LayoutUnit offset_for_cell) {
- // We would like to identify the phase as a fraction of the image size in the
- // absence of snapping, then re-apply it to the snapped values. This is to
- // handle large positions.
- if (unsnapped_tile_width) {
- LayoutUnit computed_x_position =
- RoundedMinimumValueForLength(fill_layer.PositionX(),
- unsnapped_available_width) -
- offset_for_cell;
+ LayoutUnit available_width,
+ LayoutUnit extra_offset) {
+ // All values are unsnapped to accurately set phase in the presence of
+ // zoom and large values. That is, accurately render the
+ // background-position value.
+ if (tile_size_.Width()) {
+ // Recompute computed_position because here we need to resolve against
+ // unsnapped widths to correctly set the phase.
+ LayoutUnit computed_position =
+ MinimumValueForLength(fill_layer.PositionX(), available_width) -
+ offset_in_background_.X();
+
+ // Identify the number of tiles that fit within the computed
+ // position in the direction we should be moving.
float number_of_tiles_in_position;
if (fill_layer.BackgroundXOrigin() == BackgroundEdgeOrigin::kRight) {
number_of_tiles_in_position =
- (snapped_available_width - computed_x_position + extra_offset)
- .ToFloat() /
- unsnapped_tile_width.ToFloat();
+ (available_width - computed_position + extra_offset).ToFloat() /
+ tile_size_.Width().ToFloat();
} else {
number_of_tiles_in_position =
- (computed_x_position + extra_offset).ToFloat() /
- unsnapped_tile_width.ToFloat();
+ (computed_position + extra_offset).ToFloat() /
+ tile_size_.Width().ToFloat();
}
+ // Assuming a non-integral number of tiles, find out how much of the
+ // partial tile is visible. That is the phase.
float fractional_position_within_tile =
1.0f -
(number_of_tiles_in_position - truncf(number_of_tiles_in_position));
- SetPhaseX(LayoutUnit(
- roundf(fractional_position_within_tile * TileSize().Width())));
+ SetPhaseX(fractional_position_within_tile * tile_size_.Width());
} else {
- SetPhaseX(LayoutUnit());
+ SetPhaseX(0);
}
SetSpaceSize(LayoutSize(LayoutUnit(), SpaceSize().Height()));
}
void BackgroundImageGeometry::SetRepeatY(const FillLayer& fill_layer,
- LayoutUnit unsnapped_tile_height,
- LayoutUnit snapped_available_height,
- LayoutUnit unsnapped_available_height,
- LayoutUnit extra_offset,
- LayoutUnit offset_for_cell) {
- // We would like to identify the phase as a fraction of the image size in the
- // absence of snapping, then re-apply it to the snapped values. This is to
- // handle large positions.
- if (unsnapped_tile_height) {
- LayoutUnit computed_y_position =
- RoundedMinimumValueForLength(fill_layer.PositionY(),
- unsnapped_available_height) -
- offset_for_cell;
+ LayoutUnit available_height,
+ LayoutUnit extra_offset) {
+ // All values are unsnapped to accurately set phase in the presence of
+ // zoom and large values. That is, accurately render the
+ // background-position value.
+ if (tile_size_.Height()) {
+ // Recompute computed_position because here we need to resolve against
+ // unsnapped widths to correctly set the phase.
+ LayoutUnit computed_position =
+ MinimumValueForLength(fill_layer.PositionY(), available_height) -
+ offset_in_background_.Y();
+
+ // Identify the number of tiles that fit within the computed
+ // position in the direction we should be moving.
float number_of_tiles_in_position;
if (fill_layer.BackgroundYOrigin() == BackgroundEdgeOrigin::kBottom) {
number_of_tiles_in_position =
- (snapped_available_height - computed_y_position + extra_offset)
- .ToFloat() /
- unsnapped_tile_height.ToFloat();
+ (available_height - computed_position + extra_offset).ToFloat() /
+ tile_size_.Height().ToFloat();
} else {
number_of_tiles_in_position =
- (computed_y_position + extra_offset).ToFloat() /
- unsnapped_tile_height.ToFloat();
+ (computed_position + extra_offset).ToFloat() /
+ tile_size_.Height().ToFloat();
}
+ // Assuming a non-integral number of tiles, find out how much of the
+ // partial tile is visible. That is the phase.
float fractional_position_within_tile =
1.0f -
(number_of_tiles_in_position - truncf(number_of_tiles_in_position));
- SetPhaseY(LayoutUnit(
- roundf(fractional_position_within_tile * TileSize().Height())));
+ SetPhaseY(fractional_position_within_tile * tile_size_.Height());
} else {
- SetPhaseY(LayoutUnit());
+ SetPhaseY(0);
}
SetSpaceSize(LayoutSize(SpaceSize().Width(), LayoutUnit()));
}
void BackgroundImageGeometry::SetSpaceX(LayoutUnit space,
- LayoutUnit available_width,
LayoutUnit extra_offset) {
- LayoutUnit computed_x_position =
- RoundedMinimumValueForLength(Length(), available_width);
- SetSpaceSize(LayoutSize(space.Round(), SpaceSize().Height().ToInt()));
- LayoutUnit actual_width = TileSize().Width() + space;
- SetPhaseX(actual_width
- ? LayoutUnit(roundf(actual_width -
- fmodf((computed_x_position + extra_offset),
- actual_width)))
- : LayoutUnit());
+ SetSpaceSize(LayoutSize(space, SpaceSize().Height()));
+ // Modify the phase to start a full tile at the edge of the paint area
+ LayoutUnit actual_width = tile_size_.Width() + space;
+ SetPhaseX(actual_width ? actual_width - fmodf(extra_offset, actual_width)
+ : 0);
}
void BackgroundImageGeometry::SetSpaceY(LayoutUnit space,
- LayoutUnit available_height,
LayoutUnit extra_offset) {
- LayoutUnit computed_y_position =
- RoundedMinimumValueForLength(Length(), available_height);
- SetSpaceSize(LayoutSize(SpaceSize().Width().ToInt(), space.Round()));
- LayoutUnit actual_height = TileSize().Height() + space;
- SetPhaseY(actual_height
- ? LayoutUnit(roundf(actual_height -
- fmodf((computed_y_position + extra_offset),
- actual_height)))
- : LayoutUnit());
+ SetSpaceSize(LayoutSize(SpaceSize().Width(), space));
+ // Modify the phase to start a full tile at the edge of the paint area
+ LayoutUnit actual_height = tile_size_.Height() + space;
+ SetPhaseY(actual_height ? actual_height - fmodf(extra_offset, actual_height)
+ : 0);
}
void BackgroundImageGeometry::UseFixedAttachment(
const LayoutPoint& attachment_point) {
LayoutPoint aligned_point = attachment_point;
- phase_.Move(std::max(aligned_point.X() - dest_rect_.X(), LayoutUnit()),
- std::max(aligned_point.Y() - dest_rect_.Y(), LayoutUnit()));
- SetPhase(LayoutPoint(RoundedIntPoint(phase_)));
+ phase_.Move(
+ std::max((aligned_point.X() - unsnapped_dest_rect_.X()).ToFloat(), 0.f),
+ std::max((aligned_point.Y() - unsnapped_dest_rect_.Y()).ToFloat(), 0.f));
}
enum ColumnGroupDirection { kColumnGroupStart, kColumnGroupEnd };
@@ -444,7 +356,7 @@ LayoutRect FixedAttachmentPositioningArea(const LayoutBoxModelObject& obj,
if (!frame_view)
return LayoutRect();
- ScrollableArea* layout_viewport = frame_view->LayoutViewportScrollableArea();
+ ScrollableArea* layout_viewport = frame_view->LayoutViewport();
DCHECK(layout_viewport);
LayoutRect rect = LayoutRect(
@@ -466,20 +378,18 @@ LayoutRect FixedAttachmentPositioningArea(const LayoutBoxModelObject& obj,
if (container)
rect.MoveBy(LayoutPoint(-container->LocalToAbsolute(FloatPoint())));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- // By now we have converted the viewport rect to the border box space of
- // |container|, however |container| does not necessarily create a paint
- // offset translation node, thus its paint offset must be added to convert
- // the rect to the space of the transform node.
- // TODO(trchen): This function does only one simple thing -- mapping the
- // viewport rect from frame space to whatever space the current paint
- // context uses. However we can't always invoke geometry mapper because
- // there are at least one caller uses this before PrePaint phase.
- if (container) {
- DCHECK_GE(container->GetDocument().Lifecycle().GetState(),
- DocumentLifecycle::kPrePaintClean);
- rect.MoveBy(container->FirstFragment().PaintOffset());
- }
+ // By now we have converted the viewport rect to the border box space of
+ // |container|, however |container| does not necessarily create a paint
+ // offset translation node, thus its paint offset must be added to convert
+ // the rect to the space of the transform node.
+ // TODO(trchen): This function does only one simple thing -- mapping the
+ // viewport rect from frame space to whatever space the current paint
+ // context uses. However we can't always invoke geometry mapper because
+ // there are at least one caller uses this before PrePaint phase.
+ if (container) {
+ DCHECK_GE(container->GetDocument().Lifecycle().GetState(),
+ DocumentLifecycle::kPrePaintClean);
+ rect.MoveBy(container->FirstFragment().PaintOffset());
}
return rect;
@@ -491,18 +401,13 @@ BackgroundImageGeometry::BackgroundImageGeometry(const LayoutView& view)
: box_(view),
positioning_box_(view.RootBox()),
has_non_local_geometry_(false),
+ painting_view_(true),
painting_table_cell_(false),
cell_using_container_background_(false) {
// 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 input paint rect is specified in root element local coordinate
- // (i.e. a transform is applied on the context for painting), and is
- // expanded to cover the whole canvas. Since left/top is relative to the
- // paint rect, we need to offset them back.
- coordinate_offset_by_paint_rect_ = true;
}
BackgroundImageGeometry::BackgroundImageGeometry(
@@ -510,7 +415,7 @@ BackgroundImageGeometry::BackgroundImageGeometry(
: box_(obj),
positioning_box_(obj),
has_non_local_geometry_(false),
- coordinate_offset_by_paint_rect_(false),
+ painting_view_(false),
painting_table_cell_(false),
cell_using_container_background_(false) {
// Specialized constructor should be used for LayoutView.
@@ -525,7 +430,7 @@ BackgroundImageGeometry::BackgroundImageGeometry(
? ToLayoutBoxModelObject(*background_object)
: cell),
has_non_local_geometry_(false),
- coordinate_offset_by_paint_rect_(false),
+ painting_view_(false),
painting_table_cell_(true) {
cell_using_container_background_ =
background_object && !background_object->IsTableCell();
@@ -537,64 +442,156 @@ BackgroundImageGeometry::BackgroundImageGeometry(
}
}
-LayoutRectOutsets BackgroundImageGeometry::ComputeDestRectAdjustment(
+void BackgroundImageGeometry::ComputeDestRectAdjustments(
const FillLayer& fill_layer,
- PaintPhase paint_phase) const {
- LayoutRectOutsets dest_adjust;
-
- // Attempt to shrink the destination rect if possible while also ensuring that
- // it paints to the border:
- //
- // * for background-clip content-box/padding-box, we can restrict to the
- // respective box, but for padding-box we also try to force alignment
- // with the inner border.
- //
- // * for border-box, we can modify individual edges iff the border fully
- // obscures the background.
- //
- // It it unsafe to derive dest from border information when any of the
- // following is true:
- // * the layer is not painted as part of a regular background phase
- // (e.g.paint_phase == kMask)
- // * non-SrcOver compositing is active
- // * coordinate_offset_by_paint_rect_ is set, meaning we're dealing with a
- // LayoutView - for which dest_rect is overflowing (expanded to cover
- // the whole canvas).
- // * We are painting table cells using the table background
- // * There is a border image, because it may not be opaque or may be outset.
- bool disallow_border_derived_adjustment =
- !ShouldPaintSelfBlockBackground(paint_phase) ||
- fill_layer.Composite() != CompositeOperator::kCompositeSourceOver ||
- coordinate_offset_by_paint_rect_ || painting_table_cell_ ||
- positioning_box_.StyleRef().BorderImage().GetImage();
+ const LayoutRect& unsnapped_positioning_area,
+ bool disallow_border_derived_adjustment,
+ LayoutRectOutsets& unsnapped_dest_adjust,
+ LayoutRectOutsets& snapped_dest_adjust) const {
switch (fill_layer.Clip()) {
case EFillBox::kContent:
- dest_adjust += positioning_box_.PaddingOutsets();
+ // If the PaddingOutsets are zero then this is equivalent to
+ // kPadding and we should apply the snapping logic.
+ if (!positioning_box_.PaddingOutsets().IsZero()) {
+ unsnapped_dest_adjust = positioning_box_.PaddingOutsets();
+ unsnapped_dest_adjust += positioning_box_.BorderBoxOutsets();
+
+ // We're not trying to match a border position, so don't snap.
+ snapped_dest_adjust = unsnapped_dest_adjust;
+ return;
+ }
FALLTHROUGH;
case EFillBox::kPadding:
- dest_adjust += positioning_box_.BorderBoxOutsets();
- break;
+ unsnapped_dest_adjust = positioning_box_.BorderBoxOutsets();
+ if (disallow_border_derived_adjustment) {
+ // Nothing to drive snapping behavior, so don't snap.
+ snapped_dest_adjust = unsnapped_dest_adjust;
+ } else {
+ // Force the snapped dest rect to match the inner border to
+ // avoid gaps between the background and border.
+ // TODO(schenney) The LayoutUnit(float) constructor always
+ // rounds down. We should FromFloatFloor or FromFloatCeil to
+ // move toward the border.
+ FloatRect inner_border_rect =
+ positioning_box_.StyleRef()
+ .GetRoundedInnerBorderFor(unsnapped_positioning_area)
+ .Rect();
+ snapped_dest_adjust.SetLeft(LayoutUnit(inner_border_rect.X()) -
+ unsnapped_dest_rect_.X());
+ snapped_dest_adjust.SetTop(LayoutUnit(inner_border_rect.Y()) -
+ unsnapped_dest_rect_.Y());
+ snapped_dest_adjust.SetRight(unsnapped_dest_rect_.MaxX() -
+ LayoutUnit(inner_border_rect.MaxX()));
+ snapped_dest_adjust.SetBottom(unsnapped_dest_rect_.MaxY() -
+ LayoutUnit(inner_border_rect.MaxY()));
+ }
+ return;
case EFillBox::kBorder: {
- if (disallow_border_derived_adjustment)
- break;
+ if (disallow_border_derived_adjustment) {
+ // All adjustments remain 0.
+ return;
+ }
+ // The dest rects can be adjusted. The snapped dest rect is forced
+ // to match the inner border to avoid gaps between the background and
+ // border, while the unsnapped dest moves according to the
+ // border box outsets. This leaves the unsnapped dest accurately
+ // conveying the content creator's intent when used for determining
+ // the pixels to use from sprite maps and other size and positioning
+ // properties.
+ // Note that the snapped adjustments do not have the same effect as
+ // pixel snapping the unsnapped rectangle. Border snapping snaps both
+ // the size and position of the borders, sometimes adjusting the inner
+ // border by more than a pixel when done (particularly under magnifying
+ // zoom).
+ // TODO(schenney) The LayoutUnit(float) constructor always
+ // rounds down. We should FromFloatFloor or FromFloatCeil to
+ // move toward the border.
BorderEdge edges[4];
positioning_box_.StyleRef().GetBorderEdgeInfo(edges);
- const auto border_outsets = positioning_box_.BorderBoxOutsets();
- if (edges[static_cast<unsigned>(BoxSide::kTop)].ObscuresBackground())
- dest_adjust.SetTop(border_outsets.Top());
- if (edges[static_cast<unsigned>(BoxSide::kRight)].ObscuresBackground())
- dest_adjust.SetRight(border_outsets.Right());
- if (edges[static_cast<unsigned>(BoxSide::kBottom)].ObscuresBackground())
- dest_adjust.SetBottom(border_outsets.Bottom());
- if (edges[static_cast<unsigned>(BoxSide::kLeft)].ObscuresBackground())
- dest_adjust.SetLeft(border_outsets.Left());
- } break;
+ FloatRect inner_border_rect =
+ positioning_box_.StyleRef()
+ .GetRoundedInnerBorderFor(unsnapped_positioning_area)
+ .Rect();
+ LayoutRectOutsets box_outsets = positioning_box_.BorderBoxOutsets();
+ if (edges[static_cast<unsigned>(BoxSide::kTop)].ObscuresBackground()) {
+ snapped_dest_adjust.SetTop(LayoutUnit(inner_border_rect.Y()) -
+ unsnapped_dest_rect_.Y());
+ unsnapped_dest_adjust.SetTop(box_outsets.Top());
+ }
+ if (edges[static_cast<unsigned>(BoxSide::kRight)].ObscuresBackground()) {
+ snapped_dest_adjust.SetRight(unsnapped_dest_rect_.MaxX() -
+ LayoutUnit(inner_border_rect.MaxX()));
+ unsnapped_dest_adjust.SetRight(box_outsets.Right());
+ }
+ if (edges[static_cast<unsigned>(BoxSide::kBottom)].ObscuresBackground()) {
+ snapped_dest_adjust.SetBottom(unsnapped_dest_rect_.MaxY() -
+ LayoutUnit(inner_border_rect.MaxY()));
+ unsnapped_dest_adjust.SetBottom(box_outsets.Bottom());
+ }
+ if (edges[static_cast<unsigned>(BoxSide::kLeft)].ObscuresBackground()) {
+ snapped_dest_adjust.SetLeft(LayoutUnit(inner_border_rect.X()) -
+ unsnapped_dest_rect_.X());
+ unsnapped_dest_adjust.SetLeft(box_outsets.Left());
+ }
+ }
+ return;
case EFillBox::kText:
- break;
+ return;
}
+}
- return dest_adjust;
+void BackgroundImageGeometry::ComputePositioningAreaAdjustments(
+ const FillLayer& fill_layer,
+ const LayoutRect& unsnapped_positioning_area,
+ bool disallow_border_derived_adjustment,
+ LayoutRectOutsets& unsnapped_box_outset,
+ LayoutRectOutsets& snapped_box_outset) const {
+ switch (fill_layer.Origin()) {
+ case EFillBox::kContent:
+ // If the PaddingOutsets are zero then this is equivalent to
+ // kPadding and we should apply the snapping logic.
+ if (!positioning_box_.PaddingOutsets().IsZero()) {
+ unsnapped_box_outset = positioning_box_.PaddingOutsets();
+ unsnapped_box_outset += positioning_box_.BorderBoxOutsets();
+
+ // We're not trying to match a border position, so don't snap.
+ snapped_box_outset = unsnapped_box_outset;
+ return;
+ }
+ FALLTHROUGH;
+ case EFillBox::kPadding:
+ unsnapped_box_outset = positioning_box_.BorderBoxOutsets();
+ if (disallow_border_derived_adjustment) {
+ snapped_box_outset = unsnapped_box_outset;
+ } else {
+ // Force the snapped positioning area to fill to the borders.
+ // Note that the snapped adjustments do not have the same effect as
+ // pixel snapping the unsnapped rectangle. Border snapping snaps both
+ // the size and position of the borders, sometimes adjusting the inner
+ // border by more than a pixel when done (particularly under magnifying
+ // zoom).
+ FloatRect inner_border_rect =
+ positioning_box_.StyleRef()
+ .GetRoundedInnerBorderFor(unsnapped_positioning_area)
+ .Rect();
+ snapped_box_outset.SetLeft(LayoutUnit(inner_border_rect.X()) -
+ unsnapped_positioning_area.X());
+ snapped_box_outset.SetTop(LayoutUnit(inner_border_rect.Y()) -
+ unsnapped_positioning_area.Y());
+ snapped_box_outset.SetRight(unsnapped_positioning_area.MaxX() -
+ LayoutUnit(inner_border_rect.MaxX()));
+ snapped_box_outset.SetBottom(unsnapped_positioning_area.MaxY() -
+ LayoutUnit(inner_border_rect.MaxY()));
+ }
+ return;
+ case EFillBox::kBorder:
+ // All adjustments remain 0.
+ snapped_box_outset = unsnapped_box_outset = LayoutRectOutsets(0, 0, 0, 0);
+ return;
+ case EFillBox::kText:
+ return;
+ }
}
void BackgroundImageGeometry::ComputePositioningArea(
@@ -603,37 +600,235 @@ void BackgroundImageGeometry::ComputePositioningArea(
GlobalPaintFlags flags,
const FillLayer& fill_layer,
const LayoutRect& paint_rect,
- LayoutRect& positioning_area,
- LayoutPoint& box_offset) {
+ LayoutRect& unsnapped_positioning_area,
+ LayoutRect& snapped_positioning_area,
+ LayoutPoint& unsnapped_box_offset,
+ LayoutPoint& snapped_box_offset) {
if (ShouldUseFixedAttachment(fill_layer)) {
+ // No snapping for fixed attachment.
SetHasNonLocalGeometry();
offset_in_background_ = LayoutPoint();
- positioning_area = FixedAttachmentPositioningArea(box_, container, flags);
- SetDestRect(positioning_area);
+ unsnapped_positioning_area =
+ FixedAttachmentPositioningArea(box_, container, flags);
+ unsnapped_dest_rect_ = snapped_dest_rect_ = snapped_positioning_area =
+ unsnapped_positioning_area;
} else {
- if (coordinate_offset_by_paint_rect_ || cell_using_container_background_)
- positioning_area.SetSize(positioning_size_override_);
- else
- positioning_area = paint_rect;
+ unsnapped_dest_rect_ = paint_rect;
- LayoutRectOutsets box_outset;
- if (fill_layer.Origin() != EFillBox::kBorder) {
- box_outset = positioning_box_.BorderBoxOutsets();
- if (fill_layer.Origin() == EFillBox::kContent)
- box_outset += positioning_box_.PaddingOutsets();
+ if (painting_view_ || cell_using_container_background_)
+ unsnapped_positioning_area.SetSize(positioning_size_override_);
+ else
+ unsnapped_positioning_area = unsnapped_dest_rect_;
+
+ // Attempt to shrink the destination rect if possible while also ensuring
+ // that it paints to the border:
+ //
+ // * for background-clip content-box/padding-box, we can restrict to the
+ // respective box, but for padding-box we also try to force alignment
+ // with the inner border.
+ //
+ // * for border-box, we can modify individual edges iff the border fully
+ // obscures the background.
+ //
+ // It is unsafe to derive dest from border information when any of the
+ // following is true:
+ // * the layer is not painted as part of a regular background phase
+ // (e.g.paint_phase == kMask)
+ // * non-SrcOver compositing is active
+ // * painting_view_ is set, meaning we're dealing with a
+ // LayoutView - for which dest rect is overflowing (expanded to cover
+ // the whole canvas).
+ // * We are painting table cells using the table background, or the table
+ // has collapsed borders
+ // * There is a border image, because it may not be opaque or may be outset.
+ bool disallow_border_derived_adjustment =
+ !ShouldPaintSelfBlockBackground(paint_phase) ||
+ fill_layer.Composite() != CompositeOperator::kCompositeSourceOver ||
+ painting_view_ || painting_table_cell_ ||
+ positioning_box_.StyleRef().BorderImage().GetImage() ||
+ positioning_box_.StyleRef().BorderCollapse() ==
+ EBorderCollapse::kCollapse;
+
+ // Compute all the outsets we need to apply to the rectangles. These
+ // outsets also include the snapping behavior.
+ LayoutRectOutsets unsnapped_dest_adjust;
+ LayoutRectOutsets snapped_dest_adjust;
+ LayoutRectOutsets unsnapped_box_outset;
+ LayoutRectOutsets snapped_box_outset;
+ ComputeDestRectAdjustments(fill_layer, unsnapped_positioning_area,
+ disallow_border_derived_adjustment,
+ unsnapped_dest_adjust, snapped_dest_adjust);
+ ComputePositioningAreaAdjustments(fill_layer, unsnapped_positioning_area,
+ disallow_border_derived_adjustment,
+ unsnapped_box_outset, snapped_box_outset);
+
+ // Apply the adjustments.
+ snapped_dest_rect_ = unsnapped_dest_rect_;
+ snapped_dest_rect_.Contract(snapped_dest_adjust);
+ unsnapped_dest_rect_.Contract(unsnapped_dest_adjust);
+ snapped_positioning_area = unsnapped_positioning_area;
+ snapped_positioning_area.Contract(snapped_box_outset);
+ unsnapped_positioning_area.Contract(unsnapped_box_outset);
+
+ // Offset of the positioning area from the corner of the
+ // positioning_box_.
+ // TODO(schenney): Could we enable dest adjust for collapsed
+ // borders if we computed this based on the actual offset between
+ // the rects?
+ unsnapped_box_offset =
+ LayoutPoint(unsnapped_box_outset.Left() - unsnapped_dest_adjust.Left(),
+ unsnapped_box_outset.Top() - unsnapped_dest_adjust.Top());
+ snapped_box_offset =
+ LayoutPoint(snapped_box_outset.Left() - snapped_dest_adjust.Left(),
+ snapped_box_outset.Top() - snapped_dest_adjust.Top());
+
+ // For view backgrounds, the input paint rect is specified in root element
+ // local coordinate (i.e. a transform is applied on the context for
+ // painting), and is expanded to cover the whole canvas. Since left/top is
+ // relative to the paint rect, we need to offset them back.
+ if (painting_view_) {
+ unsnapped_box_offset -= paint_rect.Location();
+ snapped_box_offset -= paint_rect.Location();
}
- positioning_area.Contract(box_outset);
+ }
+}
+
+void BackgroundImageGeometry::CalculateFillTileSize(
+ const FillLayer& fill_layer,
+ const LayoutSize& unsnapped_positioning_area_size,
+ const LayoutSize& snapped_positioning_area_size) {
+ StyleImage* image = fill_layer.GetImage();
+ EFillSizeType type = fill_layer.SizeType();
- auto dest_rect = paint_rect;
- auto dest_adjust = ComputeDestRectAdjustment(fill_layer, paint_phase);
- dest_rect.Contract(dest_adjust);
- SetDestRect(dest_rect);
+ // Tile size is snapped for relative sized images (typically generated
+ // content) and unsnapped for intrinsically sized content. Once we choose
+ // here we stop tracking whether the tile size is snapped or unsnapped.
+ LayoutSize positioning_area_size = image->ImageHasRelativeSize()
+ ? snapped_positioning_area_size
+ : unsnapped_positioning_area_size;
+ LayoutSize image_intrinsic_size(image->ImageSize(
+ positioning_box_.GetDocument(),
+ positioning_box_.StyleRef().EffectiveZoom(), positioning_area_size));
+ switch (type) {
+ case EFillSizeType::kSizeLength: {
+ tile_size_ = positioning_area_size;
+
+ const Length& layer_width = fill_layer.SizeLength().Width();
+ const Length& layer_height = fill_layer.SizeLength().Height();
+
+ if (layer_width.IsFixed()) {
+ tile_size_.SetWidth(LayoutUnit(layer_width.Value()));
+ } else if (layer_width.IsPercentOrCalc()) {
+ tile_size_.SetWidth(
+ ValueForLength(layer_width, positioning_area_size.Width()));
+ }
+
+ if (layer_height.IsFixed()) {
+ tile_size_.SetHeight(LayoutUnit(layer_height.Value()));
+ } else if (layer_height.IsPercentOrCalc()) {
+ tile_size_.SetHeight(
+ ValueForLength(layer_height, positioning_area_size.Height()));
+ }
- box_offset = LayoutPoint(box_outset.Left() - dest_adjust.Left(),
- box_outset.Top() - dest_adjust.Top());
- if (coordinate_offset_by_paint_rect_)
- box_offset -= paint_rect.Location();
+ // If one of the values is auto we have to use the appropriate
+ // scale to maintain our aspect ratio.
+ if (layer_width.IsAuto() && !layer_height.IsAuto()) {
+ if (image->ImageHasRelativeSize()) {
+ // Spec says that auto should be 100% in the absence of
+ // an intrinsic ratio or size.
+ tile_size_.SetWidth(positioning_area_size.Width());
+ } else if (image_intrinsic_size.Height()) {
+ LayoutUnit adjusted_width = image_intrinsic_size.Width() *
+ tile_size_.Height() /
+ image_intrinsic_size.Height();
+ if (image_intrinsic_size.Width() >= 1 && adjusted_width < 1)
+ adjusted_width = LayoutUnit(1);
+ tile_size_.SetWidth(adjusted_width);
+ }
+ } else if (!layer_width.IsAuto() && layer_height.IsAuto()) {
+ if (image->ImageHasRelativeSize()) {
+ // Spec says that auto should be 100% in the absence of
+ // an intrinsic ratio or size.
+ tile_size_.SetHeight(positioning_area_size.Height());
+ } else if (image_intrinsic_size.Width()) {
+ LayoutUnit adjusted_height = image_intrinsic_size.Height() *
+ tile_size_.Width() /
+ image_intrinsic_size.Width();
+ if (image_intrinsic_size.Height() >= 1 && adjusted_height < 1)
+ adjusted_height = LayoutUnit(1);
+ tile_size_.SetHeight(adjusted_height);
+ }
+ } else if (layer_width.IsAuto() && layer_height.IsAuto()) {
+ // If both width and height are auto, use the image's intrinsic size.
+ tile_size_ = image_intrinsic_size;
+ }
+
+ tile_size_.ClampNegativeToZero();
+ return;
+ }
+ case EFillSizeType::kSizeNone: {
+ // If both values are 'auto' then the intrinsic width and/or height of the
+ // image should be used, if any.
+ if (!image_intrinsic_size.IsEmpty()) {
+ tile_size_ = image_intrinsic_size;
+ return;
+ }
+
+ // If the image has neither an intrinsic width nor an intrinsic height,
+ // its size is determined as for 'contain'.
+ type = EFillSizeType::kContain;
+ FALLTHROUGH;
+ }
+ case EFillSizeType::kContain:
+ case EFillSizeType::kCover: {
+ float horizontal_scale_factor =
+ image_intrinsic_size.Width()
+ ? positioning_area_size.Width().ToFloat() /
+ image_intrinsic_size.Width()
+ : 1.0f;
+ float vertical_scale_factor =
+ image_intrinsic_size.Height()
+ ? positioning_area_size.Height().ToFloat() /
+ image_intrinsic_size.Height()
+ : 1.0f;
+ // Force the dimension that determines the size to exactly match the
+ // positioning_area_size in that dimension, so that rounding of floating
+ // point approximation to LayoutUnit do not shrink the image to smaller
+ // than the positioning_area_size.
+ LayoutSize tile_size;
+ if (type == EFillSizeType::kContain) {
+ // Snap the dependent dimension to avoid bleeding/blending artifacts
+ // at the edge of the image when we paint it.
+ if (horizontal_scale_factor < vertical_scale_factor) {
+ tile_size_ = LayoutSize(
+ positioning_area_size.Width(),
+ LayoutUnit(std::max(1.0f, roundf(image_intrinsic_size.Height() *
+ horizontal_scale_factor))));
+ } else {
+ tile_size_ = LayoutSize(
+ LayoutUnit(std::max(1.0f, roundf(image_intrinsic_size.Width() *
+ vertical_scale_factor))),
+ positioning_area_size.Height());
+ }
+ return;
+ }
+ if (horizontal_scale_factor > vertical_scale_factor) {
+ tile_size_ =
+ LayoutSize(positioning_area_size.Width(),
+ LayoutUnit(std::max(1.0f, image_intrinsic_size.Height() *
+ horizontal_scale_factor)));
+ } else {
+ tile_size_ =
+ LayoutSize(LayoutUnit(std::max(1.0f, image_intrinsic_size.Width() *
+ vertical_scale_factor)),
+ positioning_area_size.Height());
+ }
+ return;
+ }
}
+
+ NOTREACHED();
+ return;
}
void BackgroundImageGeometry::Calculate(const LayoutBoxModelObject* container,
@@ -641,148 +836,175 @@ void BackgroundImageGeometry::Calculate(const LayoutBoxModelObject* container,
GlobalPaintFlags flags,
const FillLayer& fill_layer,
const LayoutRect& paint_rect) {
- LayoutRect positioning_area;
- LayoutPoint box_offset;
+ // Unsnapped positioning area is used to derive quantities
+ // that reference source image maps and define non-integer values, such
+ // as phase and position.
+ LayoutRect unsnapped_positioning_area;
+
+ // Snapped positioning area is used for sizing images based on the
+ // background area (like cover and contain), and for setting the repeat
+ // spacing.
+ LayoutRect snapped_positioning_area;
+
+ // Additional offset from the corner of the positioning_box_
+ LayoutPoint unsnapped_box_offset;
+ LayoutPoint snapped_box_offset;
+
+ // This method also sets the destination rects.
ComputePositioningArea(container, paint_phase, flags, fill_layer, paint_rect,
- positioning_area, box_offset);
+ unsnapped_positioning_area, snapped_positioning_area,
+ unsnapped_box_offset, snapped_box_offset);
- LayoutSize fill_tile_size(CalculateFillTileSize(positioning_box_, fill_layer,
- positioning_area.Size()));
- // It's necessary to apply the heuristic here prior to any further
- // calculations to avoid incorrectly using sub-pixel values that won't be
- // present in the painted tile.
- SetTileSize(
- ApplySubPixelHeuristicToImageSize(fill_tile_size, positioning_area));
+ // Sets the tile_size_.
+ CalculateFillTileSize(fill_layer, unsnapped_positioning_area.Size(),
+ snapped_positioning_area.Size());
EFillRepeat background_repeat_x = fill_layer.RepeatX();
EFillRepeat background_repeat_y = fill_layer.RepeatY();
+
+ // Maintain both snapped and unsnapped available widths and heights.
+ // Unsnapped values are used for most thing, but snapped are used
+ // to computed sizes that must fill the area, such as round and space.
LayoutUnit unsnapped_available_width =
- positioning_area.Width() - fill_tile_size.Width();
+ unsnapped_positioning_area.Width() - tile_size_.Width();
LayoutUnit unsnapped_available_height =
- positioning_area.Height() - fill_tile_size.Height();
- LayoutSize positioning_area_size =
- LayoutSize(SnapSizeToPixel(positioning_area.Width(), dest_rect_.X()),
- SnapSizeToPixel(positioning_area.Height(), dest_rect_.Y()));
- LayoutUnit available_width =
- positioning_area_size.Width() - TileSize().Width();
- LayoutUnit available_height =
- positioning_area_size.Height() - TileSize().Height();
-
+ unsnapped_positioning_area.Height() - tile_size_.Height();
+ LayoutUnit snapped_available_width =
+ snapped_positioning_area.Width() - tile_size_.Width();
+ LayoutUnit snapped_available_height =
+ snapped_positioning_area.Height() - tile_size_.Height();
+ LayoutSize snapped_positioning_area_size = snapped_positioning_area.Size();
+
+ // Computed position is for placing things within the destination, so use
+ // snapped values.
LayoutUnit computed_x_position =
- RoundedMinimumValueForLength(fill_layer.PositionX(), available_width) -
+ MinimumValueForLength(fill_layer.PositionX(), snapped_available_width) -
offset_in_background_.X();
+ LayoutUnit computed_y_position =
+ MinimumValueForLength(fill_layer.PositionY(), snapped_available_height) -
+ offset_in_background_.Y();
+
if (background_repeat_x == EFillRepeat::kRoundFill &&
- positioning_area_size.Width() > LayoutUnit() &&
- fill_tile_size.Width() > LayoutUnit()) {
+ snapped_positioning_area_size.Width() > LayoutUnit() &&
+ tile_size_.Width() > LayoutUnit()) {
int nr_tiles = std::max(
- 1, RoundToInt(positioning_area_size.Width() / fill_tile_size.Width()));
- LayoutUnit rounded_width = positioning_area_size.Width() / nr_tiles;
+ 1,
+ RoundToInt(snapped_positioning_area_size.Width() / tile_size_.Width()));
+ LayoutUnit rounded_width = snapped_positioning_area_size.Width() / nr_tiles;
// Maintain aspect ratio if background-size: auto is set
if (fill_layer.SizeLength().Height().IsAuto() &&
background_repeat_y != EFillRepeat::kRoundFill) {
- fill_tile_size.SetHeight(fill_tile_size.Height() * rounded_width /
- fill_tile_size.Width());
+ tile_size_.SetHeight(tile_size_.Height() * rounded_width /
+ tile_size_.Width());
}
- fill_tile_size.SetWidth(rounded_width);
-
- SetTileSize(
- ApplySubPixelHeuristicToImageSize(fill_tile_size, positioning_area));
- SetPhaseX(
- TileSize().Width()
- ? LayoutUnit(roundf(TileSize().Width() -
- fmodf((computed_x_position + box_offset.X()),
- TileSize().Width())))
- : LayoutUnit());
+ tile_size_.SetWidth(rounded_width);
+
+ // Force the first tile to line up with the edge of the positioning area.
+ SetPhaseX(tile_size_.Width()
+ ? tile_size_.Width() -
+ fmodf(computed_x_position + unsnapped_box_offset.X(),
+ tile_size_.Width())
+ : 0);
SetSpaceSize(LayoutSize());
}
- LayoutUnit computed_y_position =
- RoundedMinimumValueForLength(fill_layer.PositionY(), available_height) -
- offset_in_background_.Y();
if (background_repeat_y == EFillRepeat::kRoundFill &&
- positioning_area_size.Height() > LayoutUnit() &&
- fill_tile_size.Height() > LayoutUnit()) {
- int nr_tiles = std::max(1, RoundToInt(positioning_area_size.Height() /
- fill_tile_size.Height()));
- LayoutUnit rounded_height = positioning_area_size.Height() / nr_tiles;
+ snapped_positioning_area_size.Height() > LayoutUnit() &&
+ tile_size_.Height() > LayoutUnit()) {
+ int nr_tiles =
+ std::max(1, RoundToInt(snapped_positioning_area_size.Height() /
+ tile_size_.Height()));
+ LayoutUnit rounded_height =
+ snapped_positioning_area_size.Height() / nr_tiles;
// Maintain aspect ratio if background-size: auto is set
if (fill_layer.SizeLength().Width().IsAuto() &&
background_repeat_x != EFillRepeat::kRoundFill) {
- fill_tile_size.SetWidth(fill_tile_size.Width() * rounded_height /
- fill_tile_size.Height());
+ tile_size_.SetWidth(tile_size_.Width() * rounded_height /
+ tile_size_.Height());
}
- fill_tile_size.SetHeight(rounded_height);
-
- SetTileSize(
- ApplySubPixelHeuristicToImageSize(fill_tile_size, positioning_area));
- SetPhaseY(
- TileSize().Height()
- ? LayoutUnit(roundf(TileSize().Height() -
- fmodf((computed_y_position + box_offset.Y()),
- TileSize().Height())))
- : LayoutUnit());
+ tile_size_.SetHeight(rounded_height);
+
+ // Force the first tile to line up with the edge of the positioning area.
+ SetPhaseY(tile_size_.Height()
+ ? tile_size_.Height() -
+ fmodf(computed_y_position + unsnapped_box_offset.Y(),
+ tile_size_.Height())
+ : 0);
SetSpaceSize(LayoutSize());
}
if (background_repeat_x == EFillRepeat::kRepeatFill) {
- SetRepeatX(fill_layer, fill_tile_size.Width(), available_width,
- unsnapped_available_width, box_offset.X(),
- offset_in_background_.X());
+ // Repeat must set the phase accurately, so use unsnapped values.
+ SetRepeatX(fill_layer, unsnapped_available_width, unsnapped_box_offset.X());
} else if (background_repeat_x == EFillRepeat::kSpaceFill &&
- TileSize().Width() > LayoutUnit()) {
- LayoutUnit space = GetSpaceBetweenImageTiles(positioning_area_size.Width(),
- TileSize().Width());
+ tile_size_.Width() > LayoutUnit()) {
+ // SpaceFill uses snapped values to fill the painted area.
+ LayoutUnit space = GetSpaceBetweenImageTiles(
+ snapped_positioning_area_size.Width(), tile_size_.Width());
if (space >= LayoutUnit())
- SetSpaceX(space, available_width, box_offset.X());
+ SetSpaceX(space, snapped_box_offset.X());
else
background_repeat_x = EFillRepeat::kNoRepeatFill;
}
if (background_repeat_x == EFillRepeat::kNoRepeatFill) {
+ // NoRepeat moves the dest rects, so needs both snapped and
+ // unsnapped parameters.
LayoutUnit x_offset =
fill_layer.BackgroundXOrigin() == BackgroundEdgeOrigin::kRight
- ? available_width - computed_x_position
+ ? unsnapped_available_width - computed_x_position
+ : computed_x_position;
+ LayoutUnit snapped_x_offset =
+ fill_layer.BackgroundXOrigin() == BackgroundEdgeOrigin::kRight
+ ? snapped_available_width - computed_x_position
: computed_x_position;
- SetNoRepeatX(box_offset.X() + x_offset);
- if (offset_in_background_.X() > TileSize().Width())
- SetDestRect(LayoutRect());
+ SetNoRepeatX(unsnapped_box_offset.X() + x_offset,
+ snapped_box_offset.X() + snapped_x_offset);
+ if (offset_in_background_.X() > tile_size_.Width())
+ unsnapped_dest_rect_ = snapped_dest_rect_ = LayoutRect();
}
if (background_repeat_y == EFillRepeat::kRepeatFill) {
- SetRepeatY(fill_layer, fill_tile_size.Height(), available_height,
- unsnapped_available_height, box_offset.Y(),
- offset_in_background_.Y());
+ // Repeat must set the phase accurately, so use unsnapped values.
+ SetRepeatY(fill_layer, unsnapped_available_height,
+ unsnapped_box_offset.Y());
} else if (background_repeat_y == EFillRepeat::kSpaceFill &&
- TileSize().Height() > LayoutUnit()) {
- LayoutUnit space = GetSpaceBetweenImageTiles(positioning_area_size.Height(),
- TileSize().Height());
+ tile_size_.Height() > LayoutUnit()) {
+ // SpaceFill uses snapped values to fill the painted area.
+ LayoutUnit space = GetSpaceBetweenImageTiles(
+ snapped_positioning_area_size.Height(), tile_size_.Height());
if (space >= LayoutUnit())
- SetSpaceY(space, available_height, box_offset.Y());
+ SetSpaceY(space, snapped_box_offset.Y());
else
background_repeat_y = EFillRepeat::kNoRepeatFill;
}
if (background_repeat_y == EFillRepeat::kNoRepeatFill) {
+ // NoRepeat moves the dest rects, so needs both snapped and
+ // unsnapped parameters.
LayoutUnit y_offset =
fill_layer.BackgroundYOrigin() == BackgroundEdgeOrigin::kBottom
- ? available_height - computed_y_position
+ ? unsnapped_available_height - computed_y_position
: computed_y_position;
- SetNoRepeatY(box_offset.Y() + y_offset);
- if (offset_in_background_.Y() > TileSize().Height())
- SetDestRect(LayoutRect());
+ LayoutUnit snapped_y_offset =
+ fill_layer.BackgroundYOrigin() == BackgroundEdgeOrigin::kBottom
+ ? snapped_available_height - computed_y_position
+ : computed_y_position;
+ SetNoRepeatY(unsnapped_box_offset.Y() + y_offset,
+ snapped_box_offset.Y() + snapped_y_offset);
+ if (offset_in_background_.Y() > tile_size_.Height())
+ unsnapped_dest_rect_ = snapped_dest_rect_ = LayoutRect();
}
if (ShouldUseFixedAttachment(fill_layer))
UseFixedAttachment(paint_rect.Location());
- // Clip the final output rect to the paint rect
- dest_rect_.Intersect(paint_rect);
-
- // Snap as-yet unsnapped values.
- SetDestRect(LayoutRect(PixelSnappedIntRect(dest_rect_)));
+ // Clip the final output rect to the paint rect, maintaining snapping.
+ unsnapped_dest_rect_.Intersect(paint_rect);
+ snapped_dest_rect_.Intersect(LayoutRect(PixelSnappedIntRect(paint_rect)));
}
const ImageResourceObserver& BackgroundImageGeometry::ImageClient() const {
- return coordinate_offset_by_paint_rect_ ? box_ : positioning_box_;
+ return painting_view_ ? box_ : positioning_box_;
}
const Document& BackgroundImageGeometry::ImageDocument() const {
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 e1f519c917e..84d49b301ac 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
@@ -45,26 +45,39 @@ class BackgroundImageGeometry {
const FillLayer&,
const LayoutRect& paint_rect);
- // destRect() is the rect in the space of the containing box into which to
- // draw the image.
- const LayoutRect& DestRect() const { return dest_rect_; }
- // If the image is repeated via tiling, tileSize() is the size
- // in pixels of the area into which to draw the entire image once.
- //
- // tileSize() need not be the same as the intrinsic size of the image; if not,
- // it means the image will be resized (via an image filter) when painted into
+ // Destination rects define the area into which the image will paint.
+ // For cases where no explicit background size is requested, the destination
+ // also defines the subset of the image to be drawn. Both border-snapped
+ // and unsnapped rectangles are available. The snapped rectangle matches the
+ // inner border of the box when such information is available. This may
+ // may differ from the PixelSnappedIntRect of the unsnapped rectangle
+ // because both border widths and border locations are snapped. The
+ // unsnapped rectangle is the size and location intended by the content
+ // author, and is needed to correctly subset images when no background-size
+ // size is given.
+ const LayoutRect& UnsnappedDestRect() const { return unsnapped_dest_rect_; }
+ const LayoutRect& SnappedDestRect() const { return snapped_dest_rect_; }
+
+ // Tile size is the area into which to draw one copy of the image. It
+ // need not be the same as the intrinsic size of the image; if not,
+ // the image will be resized (via an image filter) when painted into
// that tile region. This may happen because of CSS background-size and
// background-repeat requirements.
const LayoutSize& TileSize() const { return tile_size_; }
- // phase() represents the point in the image that will appear at (0,0) in the
- // destination space. The point is defined in tileSize() coordinates.
- const LayoutPoint& Phase() const { return phase_; }
- // Space-size represents extra width and height that may be added to
+
+ // Phase() represents the point in the image that will appear at (0,0) in the
+ // destination space. The point is defined in TileSize() coordinates, that is,
+ // in the scaled image.
+ const FloatPoint& Phase() const { return phase_; }
+
+ // SpaceSize() represents extra width and height that may be added to
// the image if used as a pattern with background-repeat: space.
const LayoutSize& SpaceSize() const { return repeat_spacing_; }
+
// Has background-attachment: fixed. Implies that we can't always cheaply
- // compute destRect.
+ // compute the destination rects.
bool HasNonLocalGeometry() const { return has_non_local_geometry_; }
+
// Whether the background needs to be positioned relative to a container
// element. Only used for tables.
bool CellUsingContainerBackground() const {
@@ -76,31 +89,22 @@ class BackgroundImageGeometry {
const ComputedStyle& ImageStyle() const;
private:
- void SetDestRect(const LayoutRect& dest_rect) { dest_rect_ = dest_rect; }
- void SetPhase(const LayoutPoint& phase) { phase_ = phase; }
- void SetTileSize(const LayoutSize& tile_size) { tile_size_ = tile_size; }
void SetSpaceSize(const LayoutSize& repeat_spacing) {
repeat_spacing_ = repeat_spacing;
}
- void SetPhaseX(LayoutUnit x) { phase_.SetX(x); }
- void SetPhaseY(LayoutUnit y) { phase_.SetY(y); }
+ void SetPhaseX(float x) { phase_.SetX(x); }
+ void SetPhaseY(float y) { phase_.SetY(y); }
- void SetNoRepeatX(LayoutUnit x_offset);
- void SetNoRepeatY(LayoutUnit y_offset);
+ void SetNoRepeatX(LayoutUnit x_offset, LayoutUnit snapped_x_offset);
+ void SetNoRepeatY(LayoutUnit y_offset, LayoutUnit snapped_y_offset);
void SetRepeatX(const FillLayer&,
- LayoutUnit,
- LayoutUnit,
- LayoutUnit,
- LayoutUnit,
- LayoutUnit);
+ LayoutUnit available_width,
+ LayoutUnit extra_offset);
void SetRepeatY(const FillLayer&,
- LayoutUnit,
- LayoutUnit,
- LayoutUnit,
- LayoutUnit,
- LayoutUnit);
- void SetSpaceX(LayoutUnit, LayoutUnit, LayoutUnit);
- void SetSpaceY(LayoutUnit, LayoutUnit, LayoutUnit);
+ LayoutUnit available_height,
+ LayoutUnit extra_offset);
+ void SetSpaceX(LayoutUnit space, LayoutUnit extra_offset);
+ void SetSpaceY(LayoutUnit space, LayoutUnit extra_offset);
void UseFixedAttachment(const LayoutPoint& attachment_point);
void SetHasNonLocalGeometry() { has_non_local_geometry_ = true; }
@@ -108,28 +112,63 @@ class BackgroundImageGeometry {
LayoutSize GetBackgroundObjectDimensions(const LayoutTableCell&,
const LayoutBox&);
- LayoutRectOutsets ComputeDestRectAdjustment(const FillLayer&,
- PaintPhase) const;
+ // Compute adjustments for the destination rects. Adjustments
+ // both optimize painting when the background is obscured by a
+ // border, and snap the dest rect to the border. They also
+ // account for the background-clip property.
+ void ComputeDestRectAdjustments(const FillLayer&,
+ const LayoutRect&,
+ bool,
+ LayoutRectOutsets&,
+ LayoutRectOutsets&) const;
+
+ // Positioning area adjustments modify the size of the
+ // positioning area to snap values and apply the
+ // background-origin property.
+ void ComputePositioningAreaAdjustments(const FillLayer&,
+ const LayoutRect&,
+ bool,
+ LayoutRectOutsets&,
+ LayoutRectOutsets&) const;
+
void ComputePositioningArea(const LayoutBoxModelObject*,
PaintPhase,
GlobalPaintFlags,
const FillLayer&,
const LayoutRect&,
LayoutRect&,
+ LayoutRect&,
+ LayoutPoint&,
LayoutPoint&);
+ void CalculateFillTileSize(const FillLayer&,
+ const LayoutSize&,
+ const LayoutSize&);
+ // The box_ is the source for the Document and StyleRef for
+ // background properties. It also the image client unless
+ // painting the view background.
const LayoutBoxModelObject& box_;
+
+ // The positioning box is the source of geometric information
+ // for positioning and sizing the background. We have some problems here
+ // with currentColor. See crbug.com/848860.
const LayoutBoxModelObject& positioning_box_;
+
+ // When painting table cells or the view, the positioning area
+ // 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_;
- // TODO(schenney): Convert these to IntPoints for values that we snap
- LayoutRect dest_rect_;
- LayoutPoint phase_;
+ LayoutRect unsnapped_dest_rect_;
+ LayoutRect snapped_dest_rect_;
+ FloatPoint phase_;
LayoutSize tile_size_;
LayoutSize repeat_spacing_;
bool has_non_local_geometry_;
- bool coordinate_offset_by_paint_rect_;
+ bool painting_view_;
bool painting_table_cell_;
bool cell_using_container_background_;
};
diff --git a/chromium/third_party/blink/renderer/core/paint/block_flow_painter.cc b/chromium/third_party/blink/renderer/core/paint/block_flow_painter.cc
index b3802ba2b93..cc7810ab6d4 100644
--- a/chromium/third_party/blink/renderer/core/paint/block_flow_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/block_flow_painter.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/core/layout/floating_objects.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
+#include "third_party/blink/renderer/core/paint/adjust_paint_offset_scope.h"
#include "third_party/blink/renderer/core/paint/block_painter.h"
#include "third_party/blink/renderer/core/paint/line_box_list_painter.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
@@ -24,16 +25,15 @@ void BlockFlowPainter::PaintContents(const PaintInfo& paint_info,
BlockPainter(layout_block_flow_).PaintContents(paint_info, paint_offset);
return;
}
- if (ShouldPaintDescendantOutlines(paint_info.phase))
- ObjectPainter(layout_block_flow_)
- .PaintInlineChildrenOutlines(paint_info, paint_offset);
- else
+ if (ShouldPaintDescendantOutlines(paint_info.phase)) {
+ ObjectPainter(layout_block_flow_).PaintInlineChildrenOutlines(paint_info);
+ } else {
LineBoxListPainter(layout_block_flow_.LineBoxes())
.Paint(layout_block_flow_, paint_info, paint_offset);
+ }
}
-void BlockFlowPainter::PaintFloats(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void BlockFlowPainter::PaintFloats(const PaintInfo& paint_info) {
if (!layout_block_flow_.GetFloatingObjects())
return;
@@ -55,21 +55,8 @@ void BlockFlowPainter::PaintFloats(const PaintInfo& paint_info,
if (floating_layout_object->HasSelfPaintingLayer())
continue;
- // FIXME: LayoutPoint version of xPositionForFloatIncludingMargin would make
- // this much cleaner.
- LayoutPoint child_point =
- layout_block_flow_.FlipFloatForWritingModeForChild(
- *floating_object,
- LayoutPoint(paint_offset.X() +
- layout_block_flow_.XPositionForFloatIncludingMargin(
- *floating_object) -
- floating_layout_object->Location().X(),
- paint_offset.Y() +
- layout_block_flow_.YPositionForFloatIncludingMargin(
- *floating_object) -
- floating_layout_object->Location().Y()));
ObjectPainter(*floating_layout_object)
- .PaintAllPhasesAtomically(float_paint_info, child_point);
+ .PaintAllPhasesAtomically(float_paint_info);
}
}
diff --git a/chromium/third_party/blink/renderer/core/paint/block_flow_painter.h b/chromium/third_party/blink/renderer/core/paint/block_flow_painter.h
index 928099cf75f..8f8c8e45508 100644
--- a/chromium/third_party/blink/renderer/core/paint/block_flow_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/block_flow_painter.h
@@ -9,9 +9,9 @@
namespace blink {
-class LayoutPoint;
struct PaintInfo;
class LayoutBlockFlow;
+class LayoutPoint;
class BlockFlowPainter {
STACK_ALLOCATED();
@@ -19,8 +19,8 @@ class BlockFlowPainter {
public:
BlockFlowPainter(const LayoutBlockFlow& layout_block_flow)
: layout_block_flow_(layout_block_flow) {}
- void PaintContents(const PaintInfo&, const LayoutPoint&);
- void PaintFloats(const PaintInfo&, const LayoutPoint&);
+ void PaintContents(const PaintInfo&, const LayoutPoint& paint_offset);
+ void PaintFloats(const PaintInfo&);
private:
const LayoutBlockFlow& layout_block_flow_;
diff --git a/chromium/third_party/blink/renderer/core/paint/block_painter.cc b/chromium/third_party/blink/renderer/core/paint/block_painter.cc
index 1758d7585fc..3c688a1fe1a 100644
--- a/chromium/third_party/blink/renderer/core/paint/block_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/block_painter.cc
@@ -19,66 +19,55 @@
#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_layer.h"
-#include "third_party/blink/renderer/core/paint/scroll_recorder.h"
#include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h"
namespace blink {
DISABLE_CFI_PERF
-void BlockPainter::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
- AdjustPaintOffsetScope adjustment(layout_block_, paint_info, paint_offset);
- auto adjusted_paint_offset = adjustment.AdjustedPaintOffset();
+void BlockPainter::Paint(const PaintInfo& paint_info) {
+ AdjustPaintOffsetScope adjustment(layout_block_, paint_info);
+ auto paint_offset = adjustment.PaintOffset();
auto& local_paint_info = adjustment.MutablePaintInfo();
- if (!IntersectsPaintRect(local_paint_info, adjusted_paint_offset))
+ // We can't early return if there is no fragment to paint for this block,
+ // because there may be overflowing children that exist in the painting
+ // fragment. We also can't check IntersectsPaintRect() in the case because we
+ // don't have a meaningful paint offset. TODO(wangxianzhu): only paint
+ // children if !adjustment.FragmentToPaint().
+ if (adjustment.FragmentToPaint() &&
+ !IntersectsPaintRect(local_paint_info, paint_offset))
return;
PaintPhase original_phase = local_paint_info.phase;
- // There are some cases where not all clipped visual overflow is accounted
- // for.
- // FIXME: reduce the number of such cases.
- ContentsClipBehavior contents_clip_behavior = kForceContentsClip;
- if (layout_block_.ShouldClipOverflow() && !layout_block_.HasControlClip() &&
- !layout_block_.ShouldPaintCarets())
- contents_clip_behavior = kSkipContentsClipIfPossible;
-
if (original_phase == PaintPhase::kOutline) {
local_paint_info.phase = PaintPhase::kDescendantOutlinesOnly;
} else if (ShouldPaintSelfBlockBackground(original_phase)) {
local_paint_info.phase = PaintPhase::kSelfBlockBackgroundOnly;
- layout_block_.PaintObject(local_paint_info, adjusted_paint_offset);
+ layout_block_.PaintObject(local_paint_info, paint_offset);
if (ShouldPaintDescendantBlockBackgrounds(original_phase))
local_paint_info.phase = PaintPhase::kDescendantBlockBackgroundsOnly;
}
if (original_phase != PaintPhase::kSelfBlockBackgroundOnly &&
original_phase != PaintPhase::kSelfOutlineOnly) {
- base::Optional<BoxClipper> clipper;
- // We have already applied clip in SVGForeignObjectClipper.
- if (!layout_block_.IsSVGForeignObject() ||
- RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- clipper.emplace(layout_block_, local_paint_info, adjusted_paint_offset,
- contents_clip_behavior);
- }
- layout_block_.PaintObject(local_paint_info, adjusted_paint_offset);
+ BoxClipper clipper(layout_block_, local_paint_info);
+ layout_block_.PaintObject(local_paint_info, paint_offset);
}
if (ShouldPaintSelfOutline(original_phase)) {
local_paint_info.phase = PaintPhase::kSelfOutlineOnly;
- layout_block_.PaintObject(local_paint_info, adjusted_paint_offset);
+ layout_block_.PaintObject(local_paint_info, paint_offset);
}
// Our scrollbar widgets paint exactly when we tell them to, so that they work
// properly with z-index. We paint after we painted the background/border, so
// that the scrollbars will sit above the background/border.
local_paint_info.phase = original_phase;
- PaintOverflowControlsIfNeeded(local_paint_info, adjusted_paint_offset);
+ PaintOverflowControlsIfNeeded(local_paint_info, paint_offset);
}
void BlockPainter::PaintOverflowControlsIfNeeded(
@@ -87,60 +76,43 @@ void BlockPainter::PaintOverflowControlsIfNeeded(
if (layout_block_.HasOverflowClip() &&
layout_block_.Style()->Visibility() == EVisibility::kVisible &&
ShouldPaintSelfBlockBackground(paint_info.phase)) {
- base::Optional<ClipRecorder> clip_recorder;
- if (!layout_block_.Layer()->IsSelfPaintingLayer()) {
- LayoutRect clip_rect = layout_block_.BorderBoxRect();
- clip_rect.MoveBy(paint_offset);
- clip_recorder.emplace(paint_info.context, layout_block_,
- DisplayItem::kClipScrollbarsToBoxBounds,
- PixelSnappedIntRect(clip_rect));
- }
ScrollableAreaPainter(*layout_block_.Layer()->GetScrollableArea())
.PaintOverflowControls(paint_info, RoundedIntPoint(paint_offset),
false /* painting_overlay_controls */);
}
}
-void BlockPainter::PaintChildren(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void BlockPainter::PaintChildren(const PaintInfo& paint_info) {
for (LayoutBox* child = layout_block_.FirstChildBox(); child;
child = child->NextSiblingBox())
- PaintChild(*child, paint_info, paint_offset);
+ PaintChild(*child, paint_info);
}
void BlockPainter::PaintChild(const LayoutBox& child,
- const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
- LayoutPoint child_point =
- layout_block_.FlipForWritingModeForChildForPaint(&child, paint_offset);
+ const PaintInfo& paint_info) {
if (!child.HasSelfPaintingLayer() && !child.IsFloating() &&
!child.IsColumnSpanAll())
- child.Paint(paint_info, child_point);
+ child.Paint(paint_info);
}
void BlockPainter::PaintChildrenOfFlexibleBox(
const LayoutFlexibleBox& layout_flexible_box,
- const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+ const PaintInfo& paint_info) {
for (const LayoutBox* child = layout_flexible_box.GetOrderIterator().First();
- child; child = layout_flexible_box.GetOrderIterator().Next())
+ child; child = layout_flexible_box.GetOrderIterator().Next()) {
BlockPainter(layout_flexible_box)
- .PaintAllChildPhasesAtomically(*child, paint_info, paint_offset);
+ .PaintAllChildPhasesAtomically(*child, paint_info);
+ }
}
-void BlockPainter::PaintAllChildPhasesAtomically(
- const LayoutBox& child,
- const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
- LayoutPoint child_point =
- layout_block_.FlipForWritingModeForChildForPaint(&child, paint_offset);
+void BlockPainter::PaintAllChildPhasesAtomically(const LayoutBox& child,
+ const PaintInfo& paint_info) {
if (!child.HasSelfPaintingLayer() && !child.IsFloating())
- ObjectPainter(child).PaintAllPhasesAtomically(paint_info, child_point);
+ ObjectPainter(child).PaintAllPhasesAtomically(paint_info);
}
void BlockPainter::PaintInlineBox(const InlineBox& inline_box,
- const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+ const PaintInfo& paint_info) {
if (paint_info.phase != PaintPhase::kForeground &&
paint_info.phase != PaintPhase::kSelection)
return;
@@ -149,24 +121,9 @@ void BlockPainter::PaintInlineBox(const InlineBox& inline_box,
// that has a text clip style on it, not block children.
DCHECK(paint_info.phase != PaintPhase::kTextClip);
- LayoutPoint child_point = paint_offset;
- if (inline_box.Parent()
- ->GetLineLayoutItem()
- .Style()
- ->IsFlippedBlocksWritingMode()) {
- // Faster than calling containingBlock().
- child_point =
- LineLayoutAPIShim::LayoutObjectFrom(inline_box.GetLineLayoutItem())
- ->ContainingBlock()
- ->FlipForWritingModeForChildForPaint(
- ToLayoutBox(LineLayoutAPIShim::LayoutObjectFrom(
- inline_box.GetLineLayoutItem())),
- child_point);
- }
-
ObjectPainter(
*LineLayoutAPIShim::ConstLayoutObjectFrom(inline_box.GetLineLayoutItem()))
- .PaintAllPhasesAtomically(paint_info, child_point);
+ .PaintAllPhasesAtomically(paint_info);
}
void BlockPainter::PaintScrollHitTestDisplayItem(const PaintInfo& paint_info) {
@@ -195,11 +152,34 @@ void BlockPainter::PaintScrollHitTestDisplayItem(const PaintInfo& paint_info) {
fragment->LocalBorderBoxProperties(), layout_block_,
DisplayItem::kScrollHitTest);
ScrollHitTestDisplayItem::Record(paint_info.context, layout_block_,
- DisplayItem::kScrollHitTest,
- properties->ScrollTranslation());
+ *properties->ScrollTranslation());
}
}
+// TODO(pdr): Non-blocks also need to paint the hit test display item. Move this
+// to a more central place such as BoxPainter.
+void BlockPainter::RecordHitTestData(const PaintInfo& paint_info,
+ const LayoutPoint& paint_offset) {
+ // Hit test display items are only needed for compositing. This flag is used
+ // for for printing and drag images which do not need hit testing.
+ if (paint_info.GetGlobalPaintFlags() & kGlobalPaintFlattenCompositingLayers)
+ return;
+
+ auto touch_action = layout_block_.EffectiveWhitelistedTouchAction();
+ if (touch_action == TouchAction::kTouchActionAuto)
+ return;
+
+ // TODO(pdr): If we are painting the background into the scrolling contents
+ // layer, we need to use the overflow rect instead of the border box rect. We
+ // may want to move the call to RecordTouchActionRect into
+ // BoxPainter::PaintBoxDecorationBackgroundWithRect and share the logic
+ // the background painting code already uses.
+ auto rect = layout_block_.BorderBoxRect();
+ rect.MoveBy(paint_offset);
+ HitTestData::RecordTouchActionRect(paint_info.context, layout_block_,
+ TouchActionRect(rect, touch_action));
+}
+
DISABLE_CFI_PERF
void BlockPainter::PaintObject(const PaintInfo& paint_info,
const LayoutPoint& paint_offset) {
@@ -212,6 +192,8 @@ void BlockPainter::PaintObject(const PaintInfo& paint_info,
if (layout_block_.Style()->Visibility() == EVisibility::kVisible &&
layout_block_.HasBoxDecorationBackground())
layout_block_.PaintBoxDecorationBackground(paint_info, paint_offset);
+ if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled())
+ RecordHitTestData(paint_info, paint_offset);
// Record the scroll hit test after the background so background squashing
// is not affected. Hit test order would be equivalent if this were
// immediately before the background.
@@ -228,52 +210,30 @@ void BlockPainter::PaintObject(const PaintInfo& paint_info,
return;
}
- if (paint_phase == PaintPhase::kClippingMask &&
- layout_block_.Style()->Visibility() == EVisibility::kVisible) {
- // SPv175 always paints clipping mask in PaintLayerPainter.
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
- BoxPainter(layout_block_).PaintClippingMask(paint_info, paint_offset);
- return;
- }
-
if (paint_phase == PaintPhase::kForeground && paint_info.IsPrinting())
ObjectPainter(layout_block_)
.AddPDFURLRectIfNeeded(paint_info, paint_offset);
if (paint_phase != PaintPhase::kSelfOutlineOnly) {
base::Optional<ScopedPaintChunkProperties> scoped_scroll_property;
- base::Optional<ScrollRecorder> scroll_recorder;
base::Optional<PaintInfo> scrolled_paint_info;
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- if (const auto* fragment = paint_info.FragmentToPaint(layout_block_)) {
- const auto* object_properties = fragment->PaintProperties();
- auto* scroll_translation = object_properties
- ? object_properties->ScrollTranslation()
- : nullptr;
- if (scroll_translation) {
- scoped_scroll_property.emplace(
- paint_info.context.GetPaintController(), scroll_translation,
- layout_block_, DisplayItem::PaintPhaseToScrollType(paint_phase));
- scrolled_paint_info.emplace(paint_info);
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- scrolled_paint_info->UpdateCullRectForScrollingContents(
- EnclosingIntRect(layout_block_.OverflowClipRect(paint_offset)),
- scroll_translation->Matrix().ToAffineTransform());
- } else {
- scrolled_paint_info->UpdateCullRect(
- scroll_translation->Matrix().ToAffineTransform());
- }
- }
- }
- } else if (layout_block_.HasOverflowClip()) {
- IntSize scroll_offset = layout_block_.ScrolledContentOffset();
- if (layout_block_.Layer()->ScrollsOverflow() || !scroll_offset.IsZero()) {
- scroll_recorder.emplace(paint_info.context, layout_block_, paint_phase,
- scroll_offset);
+ if (const auto* fragment = paint_info.FragmentToPaint(layout_block_)) {
+ const auto* object_properties = fragment->PaintProperties();
+ auto* scroll_translation =
+ object_properties ? object_properties->ScrollTranslation() : nullptr;
+ if (scroll_translation) {
+ scoped_scroll_property.emplace(
+ paint_info.context.GetPaintController(), scroll_translation,
+ layout_block_, DisplayItem::PaintPhaseToScrollType(paint_phase));
scrolled_paint_info.emplace(paint_info);
- AffineTransform transform;
- transform.Translate(-scroll_offset.Width(), -scroll_offset.Height());
- scrolled_paint_info->UpdateCullRect(transform);
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ scrolled_paint_info->UpdateCullRectForScrollingContents(
+ EnclosingIntRect(layout_block_.OverflowClipRect(paint_offset)),
+ scroll_translation->Matrix().ToAffineTransform());
+ } else {
+ scrolled_paint_info->UpdateCullRect(
+ scroll_translation->Matrix().ToAffineTransform());
+ }
}
}
@@ -286,7 +246,7 @@ void BlockPainter::PaintObject(const PaintInfo& paint_info,
if (paint_phase == PaintPhase::kFloat ||
paint_phase == PaintPhase::kSelection ||
paint_phase == PaintPhase::kTextClip)
- block_flow_painter.PaintFloats(contents_paint_info, paint_offset);
+ block_flow_painter.PaintFloats(contents_paint_info);
} else {
PaintContents(contents_paint_info, paint_offset);
}
@@ -316,9 +276,8 @@ void BlockPainter::PaintCarets(const PaintInfo& paint_info,
}
DISABLE_CFI_PERF
-bool BlockPainter::IntersectsPaintRect(
- const PaintInfo& paint_info,
- const LayoutPoint& adjusted_paint_offset) const {
+bool BlockPainter::IntersectsPaintRect(const PaintInfo& paint_info,
+ const LayoutPoint& paint_offset) const {
LayoutRect overflow_rect;
if (paint_info.IsPrinting() && layout_block_.IsAnonymousBlock() &&
layout_block_.ChildrenInline()) {
@@ -348,7 +307,7 @@ bool BlockPainter::IntersectsPaintRect(
overflow_rect.Move(-layout_block_.ScrolledContentOffset());
}
- overflow_rect.MoveBy(adjusted_paint_offset);
+ overflow_rect.MoveBy(paint_offset);
return paint_info.GetCullRect().IntersectsCullRect(overflow_rect);
}
diff --git a/chromium/third_party/blink/renderer/core/paint/block_painter.h b/chromium/third_party/blink/renderer/core/paint/block_painter.h
index 6c3dffbe603..190d45eef13 100644
--- a/chromium/third_party/blink/renderer/core/paint/block_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/block_painter.h
@@ -22,34 +22,34 @@ class BlockPainter {
public:
BlockPainter(const LayoutBlock& block) : layout_block_(block) {}
- void Paint(const PaintInfo&, const LayoutPoint& paint_offset);
- void PaintObject(const PaintInfo&, const LayoutPoint&);
- void PaintContents(const PaintInfo&, const LayoutPoint&);
- void PaintChildren(const PaintInfo&, const LayoutPoint&);
- void PaintChild(const LayoutBox&, const PaintInfo&, const LayoutPoint&);
- void PaintOverflowControlsIfNeeded(const PaintInfo&, const LayoutPoint&);
+ void Paint(const PaintInfo&);
+ void PaintObject(const PaintInfo&, const LayoutPoint& paint_offset);
+ void PaintContents(const PaintInfo&, const LayoutPoint& paint_offset);
+ void PaintChildren(const PaintInfo&);
+ void PaintChild(const LayoutBox&, const PaintInfo&);
+ void PaintOverflowControlsIfNeeded(const PaintInfo&,
+ const LayoutPoint& paint_offset);
// See ObjectPainter::paintAllPhasesAtomically().
- void PaintAllChildPhasesAtomically(const LayoutBox&,
- const PaintInfo&,
- const LayoutPoint&);
+ void PaintAllChildPhasesAtomically(const LayoutBox&, const PaintInfo&);
static void PaintChildrenOfFlexibleBox(const LayoutFlexibleBox&,
- const PaintInfo&,
- const LayoutPoint& paint_offset);
- static void PaintInlineBox(const InlineBox&,
- const PaintInfo&,
- const LayoutPoint& paint_offset);
+ const PaintInfo&);
+ static void PaintInlineBox(const InlineBox&, const PaintInfo&);
// The adjustedPaintOffset should include the location (offset) of the object
// itself.
bool IntersectsPaintRect(const PaintInfo&,
- const LayoutPoint& adjusted_paint_offset) const;
+ const LayoutPoint& paint_offset) const;
private:
// Paint scroll hit test placeholders in the correct paint order (see:
// ScrollHitTestDisplayItem.h).
void PaintScrollHitTestDisplayItem(const PaintInfo&);
- void PaintCarets(const PaintInfo&, const LayoutPoint&);
+ // Paint a hit test display item and record hit test data. This should be
+ // called in the background paint phase even if there is no other painted
+ // content.
+ void RecordHitTestData(const PaintInfo&, const LayoutPoint& paint_offset);
+ void PaintCarets(const PaintInfo&, const LayoutPoint& paint_offset);
const LayoutBlock& layout_block_;
};
diff --git a/chromium/third_party/blink/renderer/core/paint/block_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/block_painter_test.cc
index bb9fea2f69c..779abf9fa7c 100644
--- a/chromium/third_party/blink/renderer/core/paint/block_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/block_painter_test.cc
@@ -133,7 +133,7 @@ TEST_P(BlockPainterTest, FrameScrollHitTestProperties) {
scroll_hit_test_chunk.properties.Transform();
EXPECT_EQ(nullptr, scroll_hit_test_transform->ScrollNode());
auto* scroll_hit_test_clip = scroll_hit_test_chunk.properties.Clip();
- EXPECT_EQ(LayoutRect::InfiniteIntRect(),
+ EXPECT_EQ(FloatRect(LayoutRect::InfiniteIntRect()),
scroll_hit_test_clip->ClipRect().Rect());
// The scrolled contents should be scrolled and clipped.
@@ -154,4 +154,199 @@ TEST_P(BlockPainterTest, FrameScrollHitTestProperties) {
&scroll_hit_test_display_item.scroll_offset_node());
}
+class BlockPainterTestWithPaintTouchAction
+ : public PaintControllerPaintTestBase,
+ private ScopedPaintTouchActionRectsForTest {
+ public:
+ BlockPainterTestWithPaintTouchAction()
+ : PaintControllerPaintTestBase(),
+ ScopedPaintTouchActionRectsForTest(true) {}
+};
+
+TEST_F(BlockPainterTestWithPaintTouchAction, TouchActionRectsWithoutPaint) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ ::-webkit-scrollbar { display: none; }
+ body { margin: 0; }
+ #parent { width: 100px; height: 100px; }
+ .touchActionNone { touch-action: none; }
+ #childVisible { width: 200px; height: 25px; }
+ #childHidden { width: 200px; height: 30px; visibility: hidden; }
+ </style>
+ <div id='parent'>
+ <div id='childVisible'></div>
+ <div id='childHidden'></div>
+ </div>
+ )HTML");
+
+ // Initially there should be no hit test display items because there is no
+ // touch action.
+ auto* scrolling_client = GetLayoutView().Layer()->GraphicsLayerBacking();
+ EXPECT_DISPLAY_LIST(
+ RootPaintController().GetDisplayItemList(), 1,
+ TestDisplayItem(*scrolling_client, kDocumentBackgroundType));
+
+ // Add a touch action to parent and ensure that hit test display items are
+ // created for both the parent and child.
+ auto* parent_element = GetElementById("parent");
+ parent_element->setAttribute(HTMLNames::classAttr, "touchActionNone");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ auto* parent = GetLayoutObjectByElementId("parent");
+ auto* childVisible = GetLayoutObjectByElementId("childVisible");
+ auto* childHidden = GetLayoutObjectByElementId("childHidden");
+ EXPECT_DISPLAY_LIST(
+ RootPaintController().GetDisplayItemList(), 4,
+ TestDisplayItem(*scrolling_client, kDocumentBackgroundType),
+ TestDisplayItem(*parent, DisplayItem::kHitTest),
+ TestDisplayItem(*childVisible, DisplayItem::kHitTest),
+ TestDisplayItem(*childHidden, DisplayItem::kHitTest));
+
+ // Remove the touch action from parent and ensure no hit test display items
+ // are left.
+ parent_element->removeAttribute(HTMLNames::classAttr);
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ EXPECT_DISPLAY_LIST(
+ RootPaintController().GetDisplayItemList(), 1,
+ TestDisplayItem(*scrolling_client, kDocumentBackgroundType));
+}
+
+namespace {
+class BlockPainterMockEventListener final : public EventListener {
+ public:
+ BlockPainterMockEventListener() : EventListener(kCPPEventListenerType) {}
+
+ bool operator==(const EventListener& other) const final {
+ return this == &other;
+ }
+
+ void handleEvent(ExecutionContext*, Event*) final {}
+};
+} // namespace
+
+TEST_F(BlockPainterTestWithPaintTouchAction, TouchHandlerRectsWithoutPaint) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ ::-webkit-scrollbar { display: none; }
+ body { margin: 0; }
+ #parent { width: 100px; height: 100px; }
+ #child { width: 200px; height: 50px; }
+ </style>
+ <div id='parent'>
+ <div id='child'></div>
+ </div>
+ )HTML");
+
+ // Initially there should be no hit test display items because there are no
+ // event handlers.
+ auto* scrolling_client = GetLayoutView().Layer()->GraphicsLayerBacking();
+ EXPECT_DISPLAY_LIST(
+ RootPaintController().GetDisplayItemList(), 1,
+ TestDisplayItem(*scrolling_client, kDocumentBackgroundType));
+
+ // Add an event listener to parent and ensure that hit test display items are
+ // created for both the parent and child.
+ BlockPainterMockEventListener* callback = new BlockPainterMockEventListener();
+ auto* parent_element = GetElementById("parent");
+ parent_element->addEventListener(EventTypeNames::touchstart, callback);
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ auto* parent = GetLayoutObjectByElementId("parent");
+ auto* child = GetLayoutObjectByElementId("child");
+ EXPECT_DISPLAY_LIST(
+ RootPaintController().GetDisplayItemList(), 3,
+ TestDisplayItem(*scrolling_client, kDocumentBackgroundType),
+ TestDisplayItem(*parent, DisplayItem::kHitTest),
+ TestDisplayItem(*child, DisplayItem::kHitTest));
+
+ // Remove the event handler from parent and ensure no hit test display items
+ // are left.
+ parent_element->RemoveAllEventListeners();
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ EXPECT_DISPLAY_LIST(
+ RootPaintController().GetDisplayItemList(), 1,
+ TestDisplayItem(*scrolling_client, kDocumentBackgroundType));
+}
+
+TEST_F(BlockPainterTestWithPaintTouchAction,
+ TouchActionRectsAcrossPaintChanges) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ ::-webkit-scrollbar { display: none; }
+ body { margin: 0; }
+ #parent { width: 100px; height: 100px; touch-action: none; }
+ #child { width: 200px; height: 50px; }
+ </style>
+ <div id='parent'>
+ <div id='child'></div>
+ </div>
+ )HTML");
+
+ auto* scrolling_client = GetLayoutView().Layer()->GraphicsLayerBacking();
+ auto* parent = GetLayoutObjectByElementId("parent");
+ auto* child = GetLayoutObjectByElementId("child");
+ EXPECT_DISPLAY_LIST(
+ RootPaintController().GetDisplayItemList(), 3,
+ TestDisplayItem(*scrolling_client, kDocumentBackgroundType),
+ TestDisplayItem(*parent, DisplayItem::kHitTest),
+ TestDisplayItem(*child, DisplayItem::kHitTest));
+
+ auto* child_element = GetElementById("parent");
+ child_element->setAttribute("style", "background: blue;");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ EXPECT_DISPLAY_LIST(
+ RootPaintController().GetDisplayItemList(), 4,
+ TestDisplayItem(*scrolling_client, kDocumentBackgroundType),
+ TestDisplayItem(*parent, kBackgroundType),
+ TestDisplayItem(*parent, DisplayItem::kHitTest),
+ TestDisplayItem(*child, DisplayItem::kHitTest));
+}
+
+TEST_F(BlockPainterTestWithPaintTouchAction, ScrolledHitTestChunkProperties) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ ::-webkit-scrollbar { display: none; }
+ body { margin: 0; }
+ #scroller {
+ width: 100px;
+ height: 100px;
+ overflow: scroll;
+ touch-action: none;
+ }
+ #child {
+ width: 200px;
+ height: 50px;
+ touch-action: none;
+ }
+ </style>
+ <div id='scroller'>
+ <div id='child'></div>
+ </div>
+ )HTML");
+
+ auto* scrolling_client = GetLayoutView().Layer()->GraphicsLayerBacking();
+ auto* scroller = GetLayoutObjectByElementId("scroller");
+ auto* child = GetLayoutObjectByElementId("child");
+ EXPECT_DISPLAY_LIST(
+ RootPaintController().GetDisplayItemList(), 3,
+ TestDisplayItem(*scrolling_client, kDocumentBackgroundType),
+ TestDisplayItem(*scroller, DisplayItem::kHitTest),
+ TestDisplayItem(*child, DisplayItem::kHitTest));
+
+ const auto& paint_chunks =
+ RootPaintController().GetPaintArtifact().PaintChunks();
+ EXPECT_EQ(3u, paint_chunks.size());
+
+ const auto& scroller_paint_chunk = RootPaintController().PaintChunks()[1];
+ EXPECT_EQ(ToLayoutBoxModelObject(scroller)->Layer(),
+ &scroller_paint_chunk.id.client);
+ EXPECT_EQ(FloatRect(0, 0, 100, 100), scroller_paint_chunk.bounds);
+ // The hit test rect for the scroller itself should not be scrolled.
+ EXPECT_FALSE(scroller_paint_chunk.properties.Transform()->ScrollNode());
+
+ const auto& scrolled_paint_chunk = RootPaintController().PaintChunks()[2];
+ EXPECT_EQ(scroller, &scrolled_paint_chunk.id.client);
+ EXPECT_EQ(FloatRect(0, 0, 200, 50), scrolled_paint_chunk.bounds);
+ // The hit test rect for the scrolled contents should be scrolled.
+ EXPECT_TRUE(scrolled_paint_chunk.properties.Transform()->ScrollNode());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/box_border_painter.cc b/chromium/third_party/blink/renderer/core/paint/box_border_painter.cc
index c2f035629ba..1e0eb065acf 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_border_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/box_border_painter.cc
@@ -517,21 +517,28 @@ void BoxBorderPainter::DrawDoubleBorder(GraphicsContext& context,
const Color color = FirstEdge().color;
+ // When painting outlines, we ignore outer/inner radii.
+ const auto force_rectangular = !outer_.IsRounded() && !inner_.IsRounded();
+
// outer stripe
const LayoutRectOutsets outer_third_insets =
DoubleStripeInsets(edges_, BorderEdge::kDoubleBorderStripeOuter);
- const FloatRoundedRect outer_third_rect = style_.GetRoundedInnerBorderFor(
+ FloatRoundedRect outer_third_rect = style_.GetRoundedInnerBorderFor(
border_rect, outer_third_insets, include_logical_left_edge_,
include_logical_right_edge_);
+ if (force_rectangular)
+ outer_third_rect.SetRadii(FloatRoundedRect::Radii());
DrawBleedAdjustedDRRect(context, bleed_avoidance_, outer_, outer_third_rect,
color);
// inner stripe
const LayoutRectOutsets inner_third_insets =
DoubleStripeInsets(edges_, BorderEdge::kDoubleBorderStripeInner);
- const FloatRoundedRect inner_third_rect = style_.GetRoundedInnerBorderFor(
+ FloatRoundedRect inner_third_rect = style_.GetRoundedInnerBorderFor(
border_rect, inner_third_insets, include_logical_left_edge_,
include_logical_right_edge_);
+ if (force_rectangular)
+ inner_third_rect.SetRadii(FloatRoundedRect::Radii());
context.FillDRRect(inner_third_rect, inner_, color);
}
diff --git a/chromium/third_party/blink/renderer/core/paint/box_clipper.cc b/chromium/third_party/blink/renderer/core/paint/box_clipper.cc
index 5edcc4e6c82..f00a3ca64b4 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_clipper.cc
+++ b/chromium/third_party/blink/renderer/core/paint/box_clipper.cc
@@ -10,93 +10,22 @@
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
-// Clips for boxes are applied by the box's PaintLayerClipper, if the box has
-// a self-painting PaintLayer. Otherwise the box clips itself.
-// Note that this method is very similar to
-// PaintLayerClipper::shouldClipOverflow for that reason.
-//
-// An exception is control clip, which is currently never applied by
-// PaintLayerClipper.
-static bool BoxNeedsClip(const LayoutBox& box) {
- if (box.HasLayer() && box.Layer()->IsSelfPaintingLayer())
- return false;
- return box.ShouldClipOverflow();
-}
-
DISABLE_CFI_PERF
-BoxClipper::BoxClipper(const LayoutBox& box,
- const PaintInfo& paint_info,
- const LayoutPoint& accumulated_offset,
- ContentsClipBehavior contents_clip_behavior)
- : box_(box),
- paint_info_(paint_info),
- clip_type_(DisplayItem::kUninitializedType) {
+BoxClipper::BoxClipper(const LayoutBox& box, const PaintInfo& paint_info)
+ : box_(box), paint_info_(paint_info) {
DCHECK(paint_info_.phase != PaintPhase::kSelfBlockBackgroundOnly &&
paint_info_.phase != PaintPhase::kSelfOutlineOnly);
if (paint_info_.phase == PaintPhase::kMask)
return;
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- InitializeScopedClipProperty(paint_info.FragmentToPaint(box_), box,
- paint_info);
- return;
- }
-
- if (!BoxNeedsClip(box_))
- return;
-
- LayoutRect clip_rect = box_.OverflowClipRect(accumulated_offset);
- FloatRoundedRect clip_rounded_rect(0, 0, 0, 0);
- bool has_border_radius = box_.Style()->HasBorderRadius();
- if (has_border_radius) {
- clip_rounded_rect = box_.Style()->GetRoundedInnerBorderFor(
- LayoutRect(accumulated_offset, box_.Size()));
- }
-
- // Selection may extend beyond visual overflow, so this optimization is
- // invalid if selection is present.
- if (contents_clip_behavior == kSkipContentsClipIfPossible &&
- box.GetSelectionState() == SelectionState::kNone) {
- LayoutRect contents_visual_overflow = box_.ContentsVisualOverflowRect();
- if (contents_visual_overflow.IsEmpty())
- return;
-
- LayoutRect conservative_clip_rect = clip_rect;
- if (has_border_radius)
- conservative_clip_rect.Intersect(
- LayoutRect(clip_rounded_rect.RadiusCenterRect()));
- conservative_clip_rect.MoveBy(-accumulated_offset);
- if (box_.HasLayer())
- conservative_clip_rect.Move(box_.ScrolledContentOffset());
- if (conservative_clip_rect.Contains(contents_visual_overflow))
- return;
- }
-
- if (!paint_info_.context.GetPaintController()
- .DisplayItemConstructionIsDisabled()) {
- clip_type_ = paint_info_.DisplayItemTypeForClipping();
- Vector<FloatRoundedRect> rounded_rects;
- if (has_border_radius)
- rounded_rects.push_back(clip_rounded_rect);
- paint_info_.context.GetPaintController().CreateAndAppend<ClipDisplayItem>(
- box_, clip_type_, PixelSnappedIntRect(clip_rect), rounded_rects);
- }
-}
-
-BoxClipper::~BoxClipper() {
- if (clip_type_ == DisplayItem::kUninitializedType)
- return;
-
- DCHECK(BoxNeedsClip(box_));
- paint_info_.context.GetPaintController().EndItem<EndClipDisplayItem>(
- box_, DisplayItem::ClipTypeToEndClipType(clip_type_));
+ InitializeScopedClipProperty(paint_info.FragmentToPaint(box_), box,
+ paint_info);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/box_clipper.h b/chromium/third_party/blink/renderer/core/paint/box_clipper.h
index b9c967d82ac..e6d49f2d126 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_clipper.h
+++ b/chromium/third_party/blink/renderer/core/paint/box_clipper.h
@@ -13,22 +13,15 @@ namespace blink {
class LayoutBox;
-enum ContentsClipBehavior { kForceContentsClip, kSkipContentsClipIfPossible };
-
class BoxClipper : public BoxClipperBase {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
public:
- BoxClipper(const LayoutBox&,
- const PaintInfo&,
- const LayoutPoint& accumulated_offset,
- ContentsClipBehavior);
- ~BoxClipper();
+ BoxClipper(const LayoutBox&, const PaintInfo&);
private:
const LayoutBox& box_;
const PaintInfo& paint_info_;
- DisplayItem::Type clip_type_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/box_clipper_base.cc b/chromium/third_party/blink/renderer/core/paint/box_clipper_base.cc
index 5b3acb31ded..39ade2308c4 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_clipper_base.cc
+++ b/chromium/third_party/blink/renderer/core/paint/box_clipper_base.cc
@@ -8,7 +8,6 @@
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -19,8 +18,6 @@ void BoxClipperBase::InitializeScopedClipProperty(
const FragmentData* fragment,
const DisplayItemClient& client,
const PaintInfo& paint_info) {
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
-
if (!fragment)
return;
const auto* properties = fragment->PaintProperties();
diff --git a/chromium/third_party/blink/renderer/core/paint/box_decoration_data.cc b/chromium/third_party/blink/renderer/core/paint/box_decoration_data.cc
index 8c2f7287f32..54c63393c0c 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_decoration_data.cc
+++ b/chromium/third_party/blink/renderer/core/paint/box_decoration_data.cc
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/core/paint/box_decoration_data.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
-#include "third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h"
+#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/paint/box_painter.h"
#include "third_party/blink/renderer/core/style/border_edge.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
@@ -18,7 +18,7 @@ BoxDecorationData::BoxDecorationData(const LayoutBox& layout_box)
bleed_avoidance = ComputeBleedAvoidance(&layout_box);
}
-BoxDecorationData::BoxDecorationData(const NGPhysicalFragment& fragment)
+BoxDecorationData::BoxDecorationData(const NGPhysicalBoxFragment& fragment)
: BoxDecorationData(fragment.Style()) {
bleed_avoidance = ComputeBleedAvoidance(fragment.GetLayoutObject());
}
diff --git a/chromium/third_party/blink/renderer/core/paint/box_decoration_data.h b/chromium/third_party/blink/renderer/core/paint/box_decoration_data.h
index c2e8c999855..e60159249d3 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_decoration_data.h
+++ b/chromium/third_party/blink/renderer/core/paint/box_decoration_data.h
@@ -13,7 +13,7 @@ namespace blink {
class LayoutBox;
class LayoutObject;
class Document;
-class NGPhysicalFragment;
+class NGPhysicalBoxFragment;
class ComputedStyle;
// Information extracted from ComputedStyle for box painting.
@@ -22,7 +22,7 @@ struct BoxDecorationData {
public:
BoxDecorationData(const LayoutBox&);
- BoxDecorationData(const NGPhysicalFragment&);
+ BoxDecorationData(const NGPhysicalBoxFragment&);
Color background_color;
BackgroundBleedAvoidance bleed_avoidance;
diff --git a/chromium/third_party/blink/renderer/core/paint/box_model_object_painter.cc b/chromium/third_party/blink/renderer/core/paint/box_model_object_painter.cc
index 977ac5cd08e..7cfd64eec43 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_model_object_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/box_model_object_painter.cc
@@ -50,13 +50,11 @@ LayoutSize LogicalOffsetOnLine(const InlineFlowBox& flow_box) {
BoxModelObjectPainter::BoxModelObjectPainter(const LayoutBoxModelObject& box,
const InlineFlowBox* flow_box)
- : BoxPainterBase(box,
- &box.GetDocument(),
+ : BoxPainterBase(&box.GetDocument(),
box.StyleRef(),
GeneratingNodeForObject(box),
box.BorderBoxOutsets(),
- box.PaddingOutsets(),
- box.Layer()),
+ box.PaddingOutsets()),
box_model_(box),
flow_box_(flow_box) {}
@@ -72,7 +70,8 @@ bool BoxModelObjectPainter::
void BoxModelObjectPainter::PaintTextClipMask(GraphicsContext& context,
const IntRect& mask_rect,
- const LayoutPoint& paint_offset) {
+ const LayoutPoint& paint_offset,
+ bool) {
PaintInfo paint_info(context, mask_rect, PaintPhase::kTextClip,
kGlobalPaintNormalPhase, 0);
if (flow_box_) {
@@ -87,32 +86,11 @@ void BoxModelObjectPainter::PaintTextClipMask(GraphicsContext& context,
} else {
// FIXME: this should only have an effect for the line box list within
// |box_model_|. Change this to create a LineBoxListPainter directly.
- LayoutSize local_offset = box_model_.IsBox()
- ? ToLayoutBox(&box_model_)->LocationOffset()
- : LayoutSize();
- box_model_.Paint(paint_info, paint_offset - local_offset);
+ box_model_.Paint(paint_info);
}
}
-FloatRoundedRect BoxModelObjectPainter::GetBackgroundRoundedRect(
- const LayoutRect& border_rect,
- const LayoutSize& flow_box_size,
- bool include_logical_left_edge,
- bool include_logical_right_edge) const {
- FloatRoundedRect border = BoxPainterBase::GetBackgroundRoundedRect(
- border_rect, flow_box_size, include_logical_left_edge,
- include_logical_right_edge);
- if (flow_box_ && (flow_box_->NextForSameLayoutObject() ||
- flow_box_->PrevForSameLayoutObject())) {
- FloatRoundedRect segment_border = box_model_.StyleRef().GetRoundedBorderFor(
- LayoutRect(LayoutPoint(), LayoutSize(FlooredIntSize(flow_box_size))),
- include_logical_left_edge, include_logical_right_edge);
- border.SetRadii(segment_border.GetRadii());
- }
- return border;
-}
-
-LayoutRect BoxModelObjectPainter::AdjustForScrolledContent(
+LayoutRect BoxModelObjectPainter::AdjustRectForScrolledContent(
const PaintInfo& paint_info,
const BoxPainterBase::FillLayerInfo& info,
const LayoutRect& rect) {
diff --git a/chromium/third_party/blink/renderer/core/paint/box_model_object_painter.h b/chromium/third_party/blink/renderer/core/paint/box_model_object_painter.h
index 220926d4329..8896cdbc546 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_model_object_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/box_model_object_painter.h
@@ -39,15 +39,11 @@ class BoxModelObjectPainter : public BoxPainterBase {
void PaintTextClipMask(GraphicsContext&,
const IntRect& mask_rect,
- const LayoutPoint& paint_offset) override;
- LayoutRect AdjustForScrolledContent(const PaintInfo&,
- const BoxPainterBase::FillLayerInfo&,
- const LayoutRect&) override;
- FloatRoundedRect GetBackgroundRoundedRect(
- const LayoutRect& border_rect,
- const LayoutSize& flow_box_size,
- bool include_logical_left_edge,
- bool include_logical_right_edge) const override;
+ const LayoutPoint& paint_offset,
+ bool object_has_multiple_boxes) override;
+ LayoutRect AdjustRectForScrolledContent(const PaintInfo&,
+ const BoxPainterBase::FillLayerInfo&,
+ const LayoutRect&) override;
private:
const LayoutBoxModelObject& box_model_;
diff --git a/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.cc b/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.cc
index f662b17173a..0a6727100a3 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.cc
+++ b/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.cc
@@ -15,64 +15,6 @@
namespace blink {
-static LayoutRect ComputeRightDelta(const LayoutPoint& location,
- const LayoutSize& old_size,
- const LayoutSize& new_size,
- const LayoutUnit& extra_width) {
- LayoutUnit delta = new_size.Width() - old_size.Width();
- if (delta > 0) {
- return LayoutRect(location.X() + old_size.Width() - extra_width,
- location.Y(), delta + extra_width, new_size.Height());
- }
- if (delta < 0) {
- return LayoutRect(location.X() + new_size.Width() - extra_width,
- location.Y(), -delta + extra_width, old_size.Height());
- }
- return LayoutRect();
-}
-
-static LayoutRect ComputeBottomDelta(const LayoutPoint& location,
- const LayoutSize& old_size,
- const LayoutSize& new_size,
- const LayoutUnit& extra_height) {
- LayoutUnit delta = new_size.Height() - old_size.Height();
- if (delta > 0) {
- return LayoutRect(location.X(),
- location.Y() + old_size.Height() - extra_height,
- new_size.Width(), delta + extra_height);
- }
- if (delta < 0) {
- return LayoutRect(location.X(),
- location.Y() + new_size.Height() - extra_height,
- old_size.Width(), -delta + extra_height);
- }
- return LayoutRect();
-}
-
-void BoxPaintInvalidator::IncrementallyInvalidatePaint(
- PaintInvalidationReason reason,
- const LayoutRect& old_rect,
- const LayoutRect& new_rect) {
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
- DCHECK(old_rect.Location() == new_rect.Location());
- DCHECK(old_rect.Size() != new_rect.Size());
- LayoutRect right_delta = ComputeRightDelta(
- new_rect.Location(), old_rect.Size(), new_rect.Size(),
- reason == PaintInvalidationReason::kIncremental ? box_.BorderRight()
- : LayoutUnit());
- LayoutRect bottom_delta = ComputeBottomDelta(
- new_rect.Location(), old_rect.Size(), new_rect.Size(),
- reason == PaintInvalidationReason::kIncremental ? box_.BorderBottom()
- : LayoutUnit());
-
- DCHECK(!right_delta.IsEmpty() || !bottom_delta.IsEmpty());
- ObjectPaintInvalidatorWithContext object_paint_invalidator(box_, context_);
- object_paint_invalidator.InvalidatePaintRectangleWithContext(right_delta,
- reason);
- object_paint_invalidator.InvalidatePaintRectangleWithContext(bottom_delta,
- reason);
-}
-
PaintInvalidationReason BoxPaintInvalidator::ComputePaintInvalidationReason() {
PaintInvalidationReason reason =
ObjectPaintInvalidatorWithContext(box_, context_)
@@ -99,26 +41,24 @@ PaintInvalidationReason BoxPaintInvalidator::ComputePaintInvalidationReason() {
// If either border box changed or bounds changed, and old or new border box
// doesn't equal old or new bounds, incremental invalidation is not
// applicable. This captures the following cases:
- // - pixel snapping of paint invalidation bounds,
+ // - pixel snapping, or not snapping e.g. for some visual overflowing effects,
// - scale, rotate, skew etc. transforms,
- // - visual overflows.
+ // - visual (ink) overflows.
if (context_.old_visual_rect !=
- LayoutRect(context_.old_location, old_border_box_size) ||
+ LayoutRect(context_.old_paint_offset, old_border_box_size) ||
context_.fragment_data->VisualRect() !=
- LayoutRect(context_.fragment_data->LocationInBacking(),
+ LayoutRect(context_.fragment_data->PaintOffset(),
new_border_box_size)) {
return PaintInvalidationReason::kGeometry;
}
DCHECK(border_box_changed);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- // Incremental invalidation is not applicable if there is border in the
- // direction of border box size change because we don't know the border
- // width when issuing incremental raster invalidations.
- if (box_.BorderRight() || box_.BorderBottom())
- return PaintInvalidationReason::kGeometry;
- }
+ // Incremental invalidation is not applicable if there is border in the
+ // direction of border box size change because we don't know the border
+ // width when issuing incremental raster invalidations.
+ if (box_.BorderRight() || box_.BorderBottom())
+ return PaintInvalidationReason::kGeometry;
if (style.HasVisualOverflowingEffect() || style.HasAppearance() ||
style.HasFilterInducingProperty() || style.HasMask() || style.ClipPath())
@@ -207,8 +147,7 @@ bool BoxPaintInvalidator::ShouldFullyInvalidateBackgroundOnLayoutOverflowChange(
bool BoxPaintInvalidator::ViewBackgroundShouldFullyInvalidate() const {
DCHECK(box_.IsLayoutView());
// Fixed attachment background is handled in LayoutView::layout().
- // TODO(wangxianzhu): Combine code for fixed-attachment background when we
- // enable rootLayerScrolling permanently.
+ // TODO(wangxianzhu): Combine code for fixed-attachment background.
if (box_.StyleRef().HasEntirelyFixedBackground())
return false;
@@ -263,64 +202,35 @@ BoxPaintInvalidator::ComputeBackgroundInvalidation() {
return BackgroundInvalidationType::kNone;
}
-void BoxPaintInvalidator::InvalidateScrollingContentsBackground(
- BackgroundInvalidationType background_invalidation_type) {
- if (!BackgroundPaintsOntoScrollingContentsLayer())
- return;
- if (background_invalidation_type == BackgroundInvalidationType::kNone)
- return;
-
- PaintInvalidationReason reason;
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- reason = background_invalidation_type == BackgroundInvalidationType::kFull
- ? PaintInvalidationReason::kBackgroundOnScrollingContentsLayer
- : PaintInvalidationReason::kIncremental;
- } else {
- // For SPv1 we need this reason for both full and incremental invalidation
- // to let ObjectPaintInvalidator::SetBackingNeedsPaintInvalidationInRect()
- // know we are invalidating on the scrolling contents backing.
- reason = PaintInvalidationReason::kBackgroundOnScrollingContentsLayer;
- const LayoutRect& old_layout_overflow =
- box_.PreviousPhysicalLayoutOverflowRect();
- LayoutRect new_layout_overflow = box_.PhysicalLayoutOverflowRect();
- if (background_invalidation_type == BackgroundInvalidationType::kFull) {
- ObjectPaintInvalidatorWithContext(box_, context_)
- .FullyInvalidatePaint(reason, old_layout_overflow,
- new_layout_overflow);
- } else {
- IncrementallyInvalidatePaint(reason, old_layout_overflow,
- new_layout_overflow);
- }
- }
-
- context_.painting_layer->SetNeedsRepaint();
- ObjectPaintInvalidator(box_).InvalidateDisplayItemClient(
- *box_.Layer()->GetCompositedLayerMapping()->ScrollingContentsLayer(),
- reason);
-}
-
-PaintInvalidationReason BoxPaintInvalidator::InvalidatePaint() {
- BackgroundInvalidationType backgroundInvalidationType =
+void BoxPaintInvalidator::InvalidateBackground() {
+ BackgroundInvalidationType background_invalidation_type =
ComputeBackgroundInvalidation();
- if (backgroundInvalidationType == BackgroundInvalidationType::kFull &&
- !BackgroundPaintsOntoScrollingContentsLayer()) {
+
+ if (BackgroundPaintsOntoScrollingContentsLayer()) {
+ if (background_invalidation_type != BackgroundInvalidationType::kNone) {
+ auto reason =
+ background_invalidation_type == BackgroundInvalidationType::kFull
+ ? PaintInvalidationReason::kBackgroundOnScrollingContentsLayer
+ : PaintInvalidationReason::kIncremental;
+ context_.painting_layer->SetNeedsRepaint();
+ ObjectPaintInvalidator(box_).InvalidateDisplayItemClient(
+ *box_.Layer()->GetCompositedLayerMapping()->ScrollingContentsLayer(),
+ reason);
+ }
+ } else if (background_invalidation_type ==
+ BackgroundInvalidationType::kFull) {
box_.GetMutableForPainting()
.SetShouldDoFullPaintInvalidationWithoutGeometryChange(
PaintInvalidationReason::kBackground);
}
- InvalidateScrollingContentsBackground(backgroundInvalidationType);
+}
+
+PaintInvalidationReason BoxPaintInvalidator::InvalidatePaint() {
+ InvalidateBackground();
PaintInvalidationReason reason = ComputePaintInvalidationReason();
if (reason == PaintInvalidationReason::kIncremental) {
- bool should_invalidate;
- should_invalidate = box_.PreviousSize() != box_.Size();
- if (should_invalidate &&
- !RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- IncrementallyInvalidatePaint(
- reason, LayoutRect(context_.old_location, box_.PreviousSize()),
- LayoutRect(context_.fragment_data->LocationInBacking(), box_.Size()));
- }
- if (should_invalidate) {
+ if (box_.PreviousSize() != box_.Size()) {
context_.painting_layer->SetNeedsRepaint();
box_.InvalidateDisplayItemClients(reason);
} else {
diff --git a/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.h b/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.h
index 3aa33ecb692..8f94dba2226 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.h
+++ b/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator.h
@@ -39,14 +39,10 @@ class CORE_EXPORT BoxPaintInvalidator {
enum BackgroundInvalidationType { kNone = 0, kIncremental, kFull };
BackgroundInvalidationType ComputeBackgroundInvalidation();
- void InvalidateScrollingContentsBackground(BackgroundInvalidationType);
+ void InvalidateBackground();
PaintInvalidationReason ComputePaintInvalidationReason();
- void IncrementallyInvalidatePaint(PaintInvalidationReason,
- const LayoutRect& old_rect,
- const LayoutRect& new_rect);
-
bool NeedsToSavePreviousContentBoxSizeOrLayoutOverflowRect();
void SavePreviousBoxGeometriesIfNeeded();
diff --git a/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator_test.cc b/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator_test.cc
index 73dacdb63ce..92c92a0ce07 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/box_paint_invalidator_test.cc
@@ -24,28 +24,16 @@ class BoxPaintInvalidatorTest : public PaintControllerPaintTest {
: PaintControllerPaintTest(SingleChildLocalFrameClient::Create()) {}
protected:
- const RasterInvalidationTracking* GetRasterInvalidationTracking() const {
- // TODO(wangxianzhu): Test SPv2.
- // TODO(wangxianzhu): For SPv175, XXXPaintInvalidator doesn't do raster
- // invalidation, so the test should be moved to somewhere else (or use
- // layout tests?).
- return GetLayoutView()
- .Layer()
- ->GraphicsLayerBacking()
- ->GetRasterInvalidationTracking();
- }
-
PaintInvalidationReason ComputePaintInvalidationReason(
const LayoutBox& box,
const LayoutRect& old_visual_rect,
- const LayoutPoint& old_location) {
+ const LayoutPoint& old_paint_offset) {
FragmentData fragment_data;
PaintInvalidatorContext context;
context.old_visual_rect = old_visual_rect;
- context.old_location = old_location;
+ context.old_paint_offset = old_paint_offset;
fragment_data_.SetVisualRect(box.FirstFragment().VisualRect());
- fragment_data_.SetLocationInBacking(
- box.FirstFragment().LocationInBacking());
+ fragment_data_.SetPaintOffset(box.FirstFragment().PaintOffset());
context.fragment_data = &fragment_data_;
return BoxPaintInvalidator(box, context).ComputePaintInvalidationReason();
}
@@ -60,11 +48,11 @@ class BoxPaintInvalidatorTest : public PaintControllerPaintTest {
auto& target = *GetDocument().getElementById("target");
const auto& box = *ToLayoutBox(target.GetLayoutObject());
LayoutRect visual_rect = box.FirstFragment().VisualRect();
- LayoutPoint location = box.FirstFragment().LocationInBacking();
+ LayoutPoint paint_offset = box.FirstFragment().PaintOffset();
// No geometry change.
EXPECT_EQ(PaintInvalidationReason::kNone,
- ComputePaintInvalidationReason(box, visual_rect, location));
+ ComputePaintInvalidationReason(box, visual_rect, paint_offset));
target.setAttribute(
HTMLNames::styleAttr,
@@ -75,13 +63,10 @@ class BoxPaintInvalidatorTest : public PaintControllerPaintTest {
LayoutRect(visual_rect.Location(), box.Size()));
EXPECT_EQ(PaintInvalidationReason::kGeometry,
- ComputePaintInvalidationReason(box, visual_rect, location));
+ ComputePaintInvalidationReason(box, visual_rect, paint_offset));
}
- private:
- void SetUp() override {
- RenderingTest::SetUp();
- EnableCompositing();
+ void SetUpHTML() {
SetBodyInnerHTML(R"HTML(
<style>
body {
@@ -99,62 +84,19 @@ class BoxPaintInvalidatorTest : public PaintControllerPaintTest {
border-style: solid;
border-color: red;
}
- .solid-composited-scroller {
- overflow: scroll;
- will-change: transform;
- background: #ccc;
- }
- .local-background {
- background-attachment: local;
- overflow: scroll;
- }
- .gradient {
- background-image: linear-gradient(blue, yellow)
- }
- .transform {
- transform: scale(2);
- }
</style>
<div id='target' class='border'></div>
)HTML");
}
+
+ private:
FragmentData fragment_data_;
};
INSTANTIATE_PAINT_TEST_CASE_P(BoxPaintInvalidatorTest);
-TEST_P(BoxPaintInvalidatorTest, SlowMapToVisualRectInAncestorSpaceLayoutView) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- SetBodyInnerHTML(
- "<!doctype html>"
- "<style>"
- "#parent {"
- " display: inline-block;"
- " width: 300px;"
- " height: 300px;"
- " margin-top: 200px;"
- " filter: blur(3px);" // Forces the slow path in
- // SlowMapToVisualRectInAncestorSpace.
- " border: 1px solid rebeccapurple;"
- "}"
- "</style>"
- "<div id=parent>"
- " <iframe id='target' src='data:text/html,<body style='background: "
- "blue;'></body>'></iframe>"
- "</div>");
-
- auto& target = *GetDocument().getElementById("target");
- EXPECT_EQ(IntRect(2, 202, 318, 168),
- EnclosingIntRect(ToHTMLFrameOwnerElement(target)
- .contentDocument()
- ->GetLayoutView()
- ->FirstFragment()
- .VisualRect()));
-}
-
TEST_P(BoxPaintInvalidatorTest, ComputePaintInvalidationReasonPaintingNothing) {
+ SetUpHTML();
auto& target = *GetDocument().getElementById("target");
auto& box = *ToLayoutBox(target.GetLayoutObject());
// Remove border.
@@ -170,7 +112,7 @@ TEST_P(BoxPaintInvalidatorTest, ComputePaintInvalidationReasonPaintingNothing) {
PaintInvalidationReason::kNone,
ComputePaintInvalidationReason(box, visual_rect, visual_rect.Location()));
- // Location change.
+ // Paint offset change.
EXPECT_EQ(PaintInvalidationReason::kNone,
ComputePaintInvalidationReason(
box, visual_rect, visual_rect.Location() + LayoutSize(10, 20)));
@@ -189,6 +131,7 @@ TEST_P(BoxPaintInvalidatorTest, ComputePaintInvalidationReasonPaintingNothing) {
}
TEST_P(BoxPaintInvalidatorTest, ComputePaintInvalidationReasonBasic) {
+ SetUpHTML();
auto& target = *GetDocument().getElementById("target");
auto& box = *ToLayoutBox(target.GetLayoutObject());
// Remove border.
@@ -205,14 +148,6 @@ TEST_P(BoxPaintInvalidatorTest, ComputePaintInvalidationReasonBasic) {
PaintInvalidationReason::kNone,
ComputePaintInvalidationReason(box, visual_rect, visual_rect.Location()));
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- // Location change.
- EXPECT_EQ(
- PaintInvalidationReason::kGeometry,
- ComputePaintInvalidationReason(
- box, visual_rect, visual_rect.Location() + LayoutSize(10, 20)));
- }
-
// Visual rect size change.
LayoutRect old_visual_rect = visual_rect;
target.setAttribute(HTMLNames::styleAttr, "background: blue; width: 200px");
@@ -225,14 +160,13 @@ TEST_P(BoxPaintInvalidatorTest, ComputePaintInvalidationReasonBasic) {
ComputePaintInvalidationReason(box, old_visual_rect,
old_visual_rect.Location()));
- // Visual rect size change, with location in backing different from location
- // of visual rect.
- LayoutPoint fake_location = visual_rect.Location() + LayoutSize(10, 20);
- box.GetMutableForPainting().FirstFragment().SetLocationInBacking(
- fake_location);
+ // Visual rect size change, with paint offset different from location of
+ // visual rect.
+ LayoutPoint fake_paint_offset = visual_rect.Location() + LayoutSize(10, 20);
+ box.GetMutableForPainting().FirstFragment().SetPaintOffset(fake_paint_offset);
EXPECT_EQ(
PaintInvalidationReason::kGeometry,
- ComputePaintInvalidationReason(box, old_visual_rect, fake_location));
+ ComputePaintInvalidationReason(box, old_visual_rect, fake_paint_offset));
// Should use the existing full paint invalidation reason regardless of
// geometry change.
@@ -246,11 +180,11 @@ TEST_P(BoxPaintInvalidatorTest, ComputePaintInvalidationReasonBasic) {
}
TEST_P(BoxPaintInvalidatorTest, ComputePaintInvalidationReasonOtherCases) {
+ SetUpHTML();
auto& target = *GetDocument().getElementById("target");
// The target initially has border.
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- ExpectFullPaintInvalidationOnGeometryChange("With border");
+ ExpectFullPaintInvalidationOnGeometryChange("With border");
// Clear border.
target.setAttribute(HTMLNames::classAttr, "");
@@ -276,595 +210,4 @@ TEST_P(BoxPaintInvalidatorTest, ComputePaintInvalidationReasonOtherCases) {
ExpectFullPaintInvalidationOnGeometryChange("With clip-path");
}
-TEST_P(BoxPaintInvalidatorTest, IncrementalInvalidationExpand) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- GetDocument().View()->SetTracksPaintInvalidations(true);
- Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::styleAttr, "width: 100px; height: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- const auto& raster_invalidations =
- GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations.size());
- EXPECT_EQ(IntRect(60, 0, 60, 240), raster_invalidations[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- raster_invalidations[0].reason);
- EXPECT_EQ(IntRect(0, 120, 120, 120), raster_invalidations[1].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- raster_invalidations[1].reason);
- GetDocument().View()->SetTracksPaintInvalidations(false);
-}
-
-TEST_P(BoxPaintInvalidatorTest, IncrementalInvalidationShrink) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- GetDocument().View()->SetTracksPaintInvalidations(true);
- Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::styleAttr, "width: 20px; height: 80px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- const auto& raster_invalidations =
- GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations.size());
- EXPECT_EQ(IntRect(30, 0, 40, 140), raster_invalidations[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- raster_invalidations[0].reason);
- EXPECT_EQ(IntRect(0, 100, 70, 40), raster_invalidations[1].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- raster_invalidations[1].reason);
- GetDocument().View()->SetTracksPaintInvalidations(false);
-}
-
-TEST_P(BoxPaintInvalidatorTest, IncrementalInvalidationMixed) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- GetDocument().View()->SetTracksPaintInvalidations(true);
- Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::styleAttr, "width: 100px; height: 80px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- const auto& raster_invalidations =
- GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations.size());
- EXPECT_EQ(IntRect(60, 0, 60, 120), raster_invalidations[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- raster_invalidations[0].reason);
- EXPECT_EQ(IntRect(0, 100, 70, 40), raster_invalidations[1].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- raster_invalidations[1].reason);
- GetDocument().View()->SetTracksPaintInvalidations(false);
-}
-
-TEST_P(BoxPaintInvalidatorTest, SubpixelVisualRectChagne) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- Element* target = GetDocument().getElementById("target");
-
- GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "width: 100.6px; height: 70.3px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- const auto* raster_invalidations =
- &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations->size());
- EXPECT_EQ(IntRect(60, 0, 61, 111), (*raster_invalidations)[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- (*raster_invalidations)[0].reason);
- EXPECT_EQ(IntRect(0, 90, 70, 50), (*raster_invalidations)[1].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- (*raster_invalidations)[1].reason);
- GetDocument().View()->SetTracksPaintInvalidations(false);
-
- GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "width: 50px; height: 100px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- raster_invalidations = &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations->size());
- EXPECT_EQ(IntRect(60, 0, 61, 111), (*raster_invalidations)[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- (*raster_invalidations)[0].reason);
- EXPECT_EQ(IntRect(0, 90, 70, 50), (*raster_invalidations)[1].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- (*raster_invalidations)[1].reason);
- GetDocument().View()->SetTracksPaintInvalidations(false);
-}
-
-TEST_P(BoxPaintInvalidatorTest, SubpixelVisualRectChangeWithTransform) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::classAttr, "border transform");
- GetDocument().View()->UpdateAllLifecyclePhases();
-
- GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "width: 100.6px; height: 70.3px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- const auto* raster_invalidations =
- &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations->size());
- EXPECT_EQ(IntRect(0, 0, 140, 280), (*raster_invalidations)[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- (*raster_invalidations)[0].reason);
- EXPECT_EQ(IntRect(0, 0, 242, 222), (*raster_invalidations)[1].rect);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- (*raster_invalidations)[1].reason);
- GetDocument().View()->SetTracksPaintInvalidations(false);
-
- GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "width: 50px; height: 100px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- raster_invalidations = &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations->size());
- EXPECT_EQ(IntRect(0, 0, 242, 222), (*raster_invalidations)[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- (*raster_invalidations)[0].reason);
- EXPECT_EQ(IntRect(0, 0, 140, 280), (*raster_invalidations)[1].rect);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- (*raster_invalidations)[1].reason);
- GetDocument().View()->SetTracksPaintInvalidations(false);
-}
-
-TEST_P(BoxPaintInvalidatorTest, SubpixelWithinPixelsChange) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- Element* target = GetDocument().getElementById("target");
- LayoutObject* target_object = target->GetLayoutObject();
- EXPECT_EQ(LayoutRect(0, 0, 70, 140),
- target_object->FirstFragment().VisualRect());
-
- GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr,
- "margin-top: 0.6px; width: 50px; height: 99.3px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_EQ(LayoutRect(LayoutUnit(), LayoutUnit(0.6), LayoutUnit(70),
- LayoutUnit(139.3)),
- target_object->FirstFragment().VisualRect());
- const auto* raster_invalidations =
- &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations->size());
- EXPECT_EQ(IntRect(0, 0, 70, 140), (*raster_invalidations)[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- (*raster_invalidations)[0].reason);
- GetDocument().View()->SetTracksPaintInvalidations(false);
-
- GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr,
- "margin-top: 0.6px; width: 49.3px; height: 98.5px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_EQ(LayoutRect(LayoutUnit(), LayoutUnit(0.6), LayoutUnit(69.3),
- LayoutUnit(138.5)),
- target_object->FirstFragment().VisualRect());
- raster_invalidations = &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations->size());
- EXPECT_EQ(IntRect(59, 0, 11, 140), (*raster_invalidations)[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- (*raster_invalidations)[0].reason);
- EXPECT_EQ(IntRect(0, 119, 70, 21), (*raster_invalidations)[1].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- (*raster_invalidations)[1].reason);
- GetDocument().View()->SetTracksPaintInvalidations(false);
-}
-
-TEST_P(BoxPaintInvalidatorTest, ResizeRotated) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::styleAttr, "transform: rotate(45deg)");
- GetDocument().View()->UpdateAllLifecyclePhases();
-
- // Should do full invalidation a rotated object is resized.
- GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr,
- "transform: rotate(45deg); width: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- const auto* raster_invalidations =
- &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations->size());
- EXPECT_EQ(IntRect(-99, 0, 255, 255), (*raster_invalidations)[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- (*raster_invalidations)[0].reason);
- GetDocument().View()->SetTracksPaintInvalidations(false);
-}
-
-TEST_P(BoxPaintInvalidatorTest, ResizeRotatedChild) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::styleAttr,
- "transform: rotate(45deg); width: 200px");
- target->SetInnerHTMLFromString(
- "<div id=child style='width: 50px; height: 50px; background: "
- "red'></div>");
- GetDocument().View()->UpdateAllLifecyclePhases();
- Element* child = GetDocument().getElementById("child");
-
- // Should do full invalidation a rotated object is resized.
- GetDocument().View()->SetTracksPaintInvalidations(true);
- child->setAttribute(HTMLNames::styleAttr,
- "width: 100px; height: 50px; background: red");
- GetDocument().View()->UpdateAllLifecyclePhases();
- const auto* raster_invalidations =
- &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations->size());
- EXPECT_EQ(IntRect(-43, 21, 107, 107), (*raster_invalidations)[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- (*raster_invalidations)[0].reason);
- GetDocument().View()->SetTracksPaintInvalidations(false);
-}
-
-TEST_P(BoxPaintInvalidatorTest, CompositedLayoutViewResize) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- EnableCompositing();
- Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::classAttr, "");
- target->setAttribute(HTMLNames::styleAttr, "height: 2000px");
- GetDocument().View()->UpdateAllLifecyclePhases();
-
- // Resize the content.
- GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "height: 3000px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- const auto& raster_invalidations =
- GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations.size());
- EXPECT_EQ(IntRect(0, 2000, 800, 1000), raster_invalidations[0].rect);
- EXPECT_EQ(static_cast<const DisplayItemClient*>(&GetLayoutView()),
- raster_invalidations[0].client);
- EXPECT_EQ(PaintInvalidationReason::kBackgroundOnScrollingContentsLayer,
- raster_invalidations[0].reason);
-
- GetDocument().View()->SetTracksPaintInvalidations(false);
-
- // Resize the viewport. No paint invalidation.
- GetDocument().View()->SetTracksPaintInvalidations(true);
- GetDocument().View()->Resize(800, 1000);
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_FALSE(GetRasterInvalidationTracking()->HasInvalidations());
- GetDocument().View()->SetTracksPaintInvalidations(false);
-}
-
-TEST_P(BoxPaintInvalidatorTest, CompositedLayoutViewGradientResize) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- EnableCompositing();
- GetDocument().body()->setAttribute(HTMLNames::classAttr, "gradient");
- Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::classAttr, "");
- target->setAttribute(HTMLNames::styleAttr, "height: 2000px");
- GetDocument().View()->UpdateAllLifecyclePhases();
-
- // Resize the content.
- GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "height: 3000px");
- GetDocument().View()->UpdateAllLifecyclePhases();
-
- const auto& raster_invalidations =
- GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations.size());
- EXPECT_EQ(IntRect(0, 0, 800, 3000), raster_invalidations[0].rect);
- EXPECT_EQ(static_cast<const DisplayItemClient*>(&GetLayoutView()),
- raster_invalidations[0].client);
- EXPECT_EQ(PaintInvalidationReason::kBackgroundOnScrollingContentsLayer,
- raster_invalidations[0].reason);
-
- GetDocument().View()->SetTracksPaintInvalidations(false);
-
- // Resize the viewport. No paint invalidation.
- GetDocument().View()->SetTracksPaintInvalidations(true);
- GetDocument().View()->Resize(800, 1000);
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_FALSE(GetRasterInvalidationTracking()->HasInvalidations());
- GetDocument().View()->SetTracksPaintInvalidations(false);
-}
-
-TEST_P(BoxPaintInvalidatorTest, NonCompositedLayoutViewResize) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- SetBodyInnerHTML(R"HTML(
- <style>
- body { margin: 0 }
- iframe { display: block; width: 100px; height: 100px; border: none; }
- </style>
- <iframe id='iframe'></iframe>
- )HTML");
- SetChildFrameHTML(R"HTML(
- <style>
- ::-webkit-scrollbar { display: none }
- body { margin: 0; background: green; height: 0 }
- </style>
- <div id='content' style='width: 200px; height: 200px'></div>
- )HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
- Element* iframe = GetDocument().getElementById("iframe");
- Element* content = ChildDocument().getElementById("content");
- EXPECT_EQ(GetLayoutView(),
- content->GetLayoutObject()->ContainerForPaintInvalidation());
-
- // Resize the content.
- GetDocument().View()->SetTracksPaintInvalidations(true);
- content->setAttribute(HTMLNames::styleAttr, "height: 500px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- // No invalidation because the changed part of layout overflow is clipped.
- EXPECT_FALSE(GetRasterInvalidationTracking()->HasInvalidations());
- GetDocument().View()->SetTracksPaintInvalidations(false);
-
- // Resize the iframe.
- GetDocument().View()->SetTracksPaintInvalidations(true);
- iframe->setAttribute(HTMLNames::styleAttr, "height: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- const auto& raster_invalidations =
- GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations.size());
- EXPECT_EQ(IntRect(0, 100, 100, 100), raster_invalidations[0].rect);
- EXPECT_EQ(static_cast<const DisplayItemClient*>(iframe->GetLayoutObject()),
- raster_invalidations[0].client);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- raster_invalidations[0].reason);
- EXPECT_EQ(
- static_cast<const DisplayItemClient*>(content->GetLayoutObject()->View()),
- raster_invalidations[1].client);
- EXPECT_EQ(IntRect(0, 100, 100, 100), raster_invalidations[1].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- raster_invalidations[1].reason);
- GetDocument().View()->SetTracksPaintInvalidations(false);
-}
-
-TEST_P(BoxPaintInvalidatorTest, NonCompositedLayoutViewGradientResize) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- SetBodyInnerHTML(R"HTML(
- <style>
- body { margin: 0 }
- iframe { display: block; width: 100px; height: 100px; border: none; }
- </style>
- <iframe id='iframe'></iframe>
- )HTML");
- SetChildFrameHTML(R"HTML(
- <style>
- ::-webkit-scrollbar { display: none }
- body {
- margin: 0;
- height: 0;
- background-image: linear-gradient(blue, yellow);
- }
- </style>
- <div id='content' style='width: 200px; height: 200px'></div>
- )HTML");
- GetDocument().View()->UpdateAllLifecyclePhases();
- Element* iframe = GetDocument().getElementById("iframe");
- Element* content = ChildDocument().getElementById("content");
- LayoutView* frame_layout_view = content->GetLayoutObject()->View();
- EXPECT_EQ(GetLayoutView(),
- content->GetLayoutObject()->ContainerForPaintInvalidation());
-
- // Resize the content.
- GetDocument().View()->SetTracksPaintInvalidations(true);
- content->setAttribute(HTMLNames::styleAttr, "height: 500px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- const auto* raster_invalidations =
- &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations->size());
- EXPECT_EQ(IntRect(0, 0, 100, 100), (*raster_invalidations)[0].rect);
- EXPECT_EQ(static_cast<const DisplayItemClient*>(frame_layout_view),
- (*raster_invalidations)[0].client);
- EXPECT_EQ(PaintInvalidationReason::kBackground,
- (*raster_invalidations)[0].reason);
- GetDocument().View()->SetTracksPaintInvalidations(false);
-
- // Resize the iframe.
- GetDocument().View()->SetTracksPaintInvalidations(true);
- iframe->setAttribute(HTMLNames::styleAttr, "height: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- raster_invalidations = &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations->size());
- EXPECT_EQ(IntRect(0, 100, 100, 100), (*raster_invalidations)[0].rect);
- EXPECT_EQ(static_cast<const DisplayItemClient*>(iframe->GetLayoutObject()),
- (*raster_invalidations)[0].client);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- (*raster_invalidations)[0].reason);
- EXPECT_EQ(static_cast<const DisplayItemClient*>(frame_layout_view),
- (*raster_invalidations)[1].client);
- EXPECT_EQ(IntRect(0, 0, 100, 200), (*raster_invalidations)[1].rect);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- (*raster_invalidations)[1].reason);
- GetDocument().View()->SetTracksPaintInvalidations(false);
-}
-
-TEST_P(BoxPaintInvalidatorTest, CompositedBackgroundAttachmentLocalResize) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- EnableCompositing();
-
- Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::classAttr, "border local-background");
- target->setAttribute(HTMLNames::styleAttr, "will-change: transform");
- target->SetInnerHTMLFromString(
- "<div id=child style='width: 500px; height: 500px'></div>",
- ASSERT_NO_EXCEPTION);
- Element* child = GetDocument().getElementById("child");
- GetDocument().View()->UpdateAllLifecyclePhases();
-
- // Resize the content.
- GetDocument().View()->SetTracksPaintInvalidations(true);
- child->setAttribute(HTMLNames::styleAttr, "width: 500px; height: 1000px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- LayoutBoxModelObject* target_obj =
- ToLayoutBoxModelObject(target->GetLayoutObject());
- GraphicsLayer* container_layer =
- target_obj->Layer()->GraphicsLayerBacking(target_obj);
- GraphicsLayer* contents_layer = target_obj->Layer()->GraphicsLayerBacking();
- // No invalidation on the container layer.
- EXPECT_FALSE(
- container_layer->GetRasterInvalidationTracking()->HasInvalidations());
- // Incremental invalidation of background on contents layer.
- const auto& contents_raster_invalidations =
- contents_layer->GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, contents_raster_invalidations.size());
- EXPECT_EQ(IntRect(0, 500, 500, 500), contents_raster_invalidations[0].rect);
- EXPECT_EQ(static_cast<const DisplayItemClient*>(target->GetLayoutObject()),
- contents_raster_invalidations[0].client);
- EXPECT_EQ(PaintInvalidationReason::kBackgroundOnScrollingContentsLayer,
- contents_raster_invalidations[0].reason);
- GetDocument().View()->SetTracksPaintInvalidations(false);
-
- // Resize the container.
- GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr,
- "will-change: transform; height: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- // No invalidation on the contents layer.
- EXPECT_FALSE(
- contents_layer->GetRasterInvalidationTracking()->HasInvalidations());
- // Incremental invalidation on the container layer.
- const auto& container_raster_invalidations =
- container_layer->GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, container_raster_invalidations.size());
- EXPECT_EQ(IntRect(0, 120, 70, 120), container_raster_invalidations[0].rect);
- EXPECT_EQ(static_cast<const DisplayItemClient*>(target->GetLayoutObject()),
- container_raster_invalidations[0].client);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- container_raster_invalidations[0].reason);
- GetDocument().View()->SetTracksPaintInvalidations(false);
-}
-
-TEST_P(BoxPaintInvalidatorTest,
- CompositedBackgroundAttachmentLocalGradientResize) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- EnableCompositing();
-
- Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::classAttr,
- "border local-background gradient");
- target->setAttribute(HTMLNames::styleAttr, "will-change: transform");
- target->SetInnerHTMLFromString(
- "<div id='child' style='width: 500px; height: 500px'></div>",
- ASSERT_NO_EXCEPTION);
- Element* child = GetDocument().getElementById("child");
- GetDocument().View()->UpdateAllLifecyclePhases();
-
- // Resize the content.
- GetDocument().View()->SetTracksPaintInvalidations(true);
- child->setAttribute(HTMLNames::styleAttr, "width: 500px; height: 1000px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- LayoutBoxModelObject* target_obj =
- ToLayoutBoxModelObject(target->GetLayoutObject());
- GraphicsLayer* container_layer =
- target_obj->Layer()->GraphicsLayerBacking(target_obj);
- GraphicsLayer* contents_layer = target_obj->Layer()->GraphicsLayerBacking();
- // No invalidation on the container layer.
- EXPECT_FALSE(
- container_layer->GetRasterInvalidationTracking()->HasInvalidations());
- // Full invalidation of background on contents layer because the gradient
- // background is resized.
- const auto& contents_raster_invalidations =
- contents_layer->GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, contents_raster_invalidations.size());
- EXPECT_EQ(IntRect(0, 0, 500, 1000), contents_raster_invalidations[0].rect);
- EXPECT_EQ(static_cast<const DisplayItemClient*>(target->GetLayoutObject()),
- contents_raster_invalidations[0].client);
- EXPECT_EQ(PaintInvalidationReason::kBackgroundOnScrollingContentsLayer,
- contents_raster_invalidations[0].reason);
- GetDocument().View()->SetTracksPaintInvalidations(false);
-
- // Resize the container.
- GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr,
- "will-change: transform; height: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_FALSE(
- contents_layer->GetRasterInvalidationTracking()->HasInvalidations());
- // Full invalidation on the container layer.
- const auto& container_raster_invalidations =
- container_layer->GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, container_raster_invalidations.size());
- EXPECT_EQ(IntRect(0, 0, 70, 240), container_raster_invalidations[0].rect);
- EXPECT_EQ(static_cast<const DisplayItemClient*>(target->GetLayoutObject()),
- container_raster_invalidations[0].client);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- container_raster_invalidations[0].reason);
- GetDocument().View()->SetTracksPaintInvalidations(false);
-}
-
-TEST_P(BoxPaintInvalidatorTest, NonCompositedBackgroundAttachmentLocalResize) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::classAttr, "border local-background");
- target->SetInnerHTMLFromString(
- "<div id=child style='width: 500px; height: 500px'></div>",
- ASSERT_NO_EXCEPTION);
- Element* child = GetDocument().getElementById("child");
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_EQ(&GetLayoutView(),
- &target->GetLayoutObject()->ContainerForPaintInvalidation());
-
- // Resize the content.
- GetDocument().View()->SetTracksPaintInvalidations(true);
- child->setAttribute(HTMLNames::styleAttr, "width: 500px; height: 1000px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- // No invalidation because the changed part is invisible.
- EXPECT_FALSE(GetRasterInvalidationTracking()->HasInvalidations());
-
- // Resize the container.
- GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "height: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- const auto& raster_invalidations =
- GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations.size());
- EXPECT_EQ(IntRect(0, 120, 70, 120), raster_invalidations[0].rect);
- EXPECT_EQ(static_cast<const DisplayItemClient*>(target->GetLayoutObject()),
- raster_invalidations[0].client);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- raster_invalidations[0].reason);
- GetDocument().View()->SetTracksPaintInvalidations(false);
-}
-
-TEST_P(BoxPaintInvalidatorTest, CompositedSolidBackgroundResize) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- EnableCompositing();
- Element* target = GetDocument().getElementById("target");
- target->setAttribute(HTMLNames::classAttr, "solid-composited-scroller");
- target->SetInnerHTMLFromString("<div style='height: 500px'></div>",
- ASSERT_NO_EXCEPTION);
- GetDocument().View()->UpdateAllLifecyclePhases();
-
- // Resize the scroller.
- GetDocument().View()->SetTracksPaintInvalidations(true);
- target->setAttribute(HTMLNames::styleAttr, "width: 100px");
- GetDocument().View()->UpdateAllLifecyclePhases();
-
- LayoutBoxModelObject* target_object =
- ToLayoutBoxModelObject(target->GetLayoutObject());
- GraphicsLayer* scrolling_contents_layer =
- target_object->Layer()->GraphicsLayerBacking();
- const auto& invalidations =
- scrolling_contents_layer->GetRasterInvalidationTracking()
- ->Invalidations();
-
- ASSERT_EQ(1u, invalidations.size());
- EXPECT_EQ(IntRect(50, 0, 50, 500), invalidations[0].rect);
- EXPECT_EQ(static_cast<const DisplayItemClient*>(target_object),
- invalidations[0].client);
- EXPECT_EQ(PaintInvalidationReason::kBackgroundOnScrollingContentsLayer,
- invalidations[0].reason);
- GetDocument().View()->SetTracksPaintInvalidations(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 f7782f3cc83..beea2b67302 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/box_painter.cc
@@ -20,7 +20,6 @@
#include "third_party/blink/renderer/core/paint/nine_piece_image_painter.h"
#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/scroll_recorder.h"
#include "third_party/blink/renderer/core/paint/svg_foreign_object_painter.h"
#include "third_party/blink/renderer/core/paint/theme_painter.h"
#include "third_party/blink/renderer/platform/geometry/layout_point.h"
@@ -32,24 +31,21 @@
namespace blink {
-void BoxPainter::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void BoxPainter::Paint(const PaintInfo& paint_info) {
// Default implementation. Just pass paint through to the children.
- AdjustPaintOffsetScope adjustment(layout_box_, paint_info, paint_offset);
- PaintChildren(adjustment.GetPaintInfo(), adjustment.AdjustedPaintOffset());
+ AdjustPaintOffsetScope adjustment(layout_box_, paint_info);
+ PaintChildren(adjustment.GetPaintInfo());
}
-void BoxPainter::PaintChildren(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void BoxPainter::PaintChildren(const PaintInfo& paint_info) {
PaintInfo child_info(paint_info);
for (LayoutObject* child = layout_box_.SlowFirstChild(); child;
child = child->NextSibling()) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- child->IsSVGForeignObject()) {
+ if (child->IsSVGForeignObject()) {
SVGForeignObjectPainter(ToLayoutSVGForeignObject(*child))
.PaintLayer(paint_info);
} else {
- child->Paint(child_info, paint_offset);
+ child->Paint(child_info);
}
}
}
@@ -57,7 +53,6 @@ void BoxPainter::PaintChildren(const PaintInfo& paint_info,
void BoxPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info,
const LayoutPoint& paint_offset) {
LayoutRect paint_rect;
- base::Optional<ScrollRecorder> scroll_recorder;
base::Optional<ScopedPaintChunkProperties> scoped_scroll_property;
if (BoxModelObjectPainter::
IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
@@ -67,15 +62,11 @@ void BoxPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info,
// overflow rect.
paint_rect = layout_box_.PhysicalLayoutOverflowRect();
- scroll_recorder.emplace(paint_info.context, layout_box_, paint_info.phase,
- layout_box_.ScrolledContentOffset());
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- if (const auto* fragment = paint_info.FragmentToPaint(layout_box_)) {
- scoped_scroll_property.emplace(
- paint_info.context.GetPaintController(),
- fragment->ContentsProperties(), layout_box_,
- DisplayItem::PaintPhaseToScrollType(paint_info.phase));
- }
+ if (const auto* fragment = paint_info.FragmentToPaint(layout_box_)) {
+ scoped_scroll_property.emplace(
+ paint_info.context.GetPaintController(),
+ fragment->ContentsProperties(), layout_box_,
+ DisplayItem::PaintPhaseToScrollType(paint_info.phase));
}
// The background painting code assumes that the borders are part of the
@@ -92,14 +83,14 @@ void BoxPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info,
LayoutRect BoxPainter::BoundsForDrawingRecorder(
const PaintInfo& paint_info,
- const LayoutPoint& adjusted_paint_offset) {
+ const LayoutPoint& paint_offset) {
LayoutRect bounds =
BoxModelObjectPainter::
IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
&layout_box_, paint_info)
? layout_box_.LayoutOverflowRect()
: layout_box_.SelfVisualOverflowRect();
- bounds.MoveBy(adjusted_paint_offset);
+ bounds.MoveBy(paint_offset);
return bounds;
}
@@ -264,27 +255,4 @@ void BoxPainter::PaintMaskImages(const PaintInfo& paint_info,
include_logical_right_edge);
}
-void BoxPainter::PaintClippingMask(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
- // SPv175 always paints clipping mask in PaintLayerPainter.
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
- DCHECK(paint_info.phase == PaintPhase::kClippingMask);
-
- if (layout_box_.Style()->Visibility() != EVisibility::kVisible)
- return;
-
- if (!layout_box_.Layer() ||
- layout_box_.Layer()->GetCompositingState() != kPaintsIntoOwnBacking)
- return;
-
- if (DrawingRecorder::UseCachedDrawingIfPossible(
- paint_info.context, layout_box_, paint_info.phase))
- return;
-
- IntRect paint_rect =
- PixelSnappedIntRect(LayoutRect(paint_offset, layout_box_.Size()));
- DrawingRecorder recorder(paint_info.context, layout_box_, paint_info.phase);
- paint_info.context.FillRect(paint_rect, Color::kBlack);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/box_painter.h b/chromium/third_party/blink/renderer/core/paint/box_painter.h
index c68e48beadc..1bfa1b2bdf1 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/box_painter.h
@@ -13,30 +13,30 @@
namespace blink {
-class LayoutPoint;
-class LayoutRect;
struct PaintInfo;
-class LayoutBox;
class Color;
+class LayoutBox;
+class LayoutPoint;
+class LayoutRect;
class BoxPainter {
STACK_ALLOCATED();
public:
BoxPainter(const LayoutBox& layout_box) : layout_box_(layout_box) {}
- void Paint(const PaintInfo&, const LayoutPoint&);
+ void Paint(const PaintInfo&);
- void PaintChildren(const PaintInfo&, const LayoutPoint&);
- void PaintBoxDecorationBackground(const PaintInfo&, const LayoutPoint&);
- void PaintMask(const PaintInfo&, const LayoutPoint&);
- void PaintClippingMask(const PaintInfo&, const LayoutPoint&);
+ void PaintChildren(const PaintInfo&);
+ void PaintBoxDecorationBackground(const PaintInfo&,
+ const LayoutPoint& paint_offset);
+ void PaintMask(const PaintInfo&, const LayoutPoint& paint_offset);
void PaintMaskImages(const PaintInfo&, const LayoutRect&);
void PaintBoxDecorationBackgroundWithRect(const PaintInfo&,
const LayoutPoint&,
const LayoutRect&);
LayoutRect BoundsForDrawingRecorder(const PaintInfo&,
- const LayoutPoint& adjusted_paint_offset);
+ const LayoutPoint& paint_offset);
private:
void PaintBackground(const PaintInfo&,
diff --git a/chromium/third_party/blink/renderer/core/paint/box_painter_base.cc b/chromium/third_party/blink/renderer/core/paint/box_painter_base.cc
index b4de4e3e137..441e273f7ee 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_painter_base.cc
+++ b/chromium/third_party/blink/renderer/core/paint/box_painter_base.cc
@@ -269,57 +269,6 @@ bool BoxPainterBase::CalculateFillLayerOcclusionCulling(
return is_non_associative;
}
-FloatRoundedRect BoxPainterBase::BackgroundRoundedRectAdjustedForBleedAvoidance(
- const LayoutRect& border_rect,
- const LayoutSize& flow_box_size,
- BackgroundBleedAvoidance bleed_avoidance,
- bool include_logical_left_edge,
- bool include_logical_right_edge) const {
- if (bleed_avoidance == kBackgroundBleedShrinkBackground) {
- // Inset the background rect by a "safe" amount: 1/2 border-width for opaque
- // border styles, 1/6 border-width for double borders.
-
- // TODO(fmalita): we should be able to fold these parameters into
- // BoxBorderInfo or BoxDecorationData and avoid calling getBorderEdgeInfo
- // redundantly here.
- BorderEdge edges[4];
- style_.GetBorderEdgeInfo(edges, include_logical_left_edge,
- include_logical_right_edge);
-
- // Use the most conservative inset to avoid mixed-style corner issues.
- float fractional_inset = 1.0f / 2;
- for (auto& edge : edges) {
- if (edge.BorderStyle() == EBorderStyle::kDouble) {
- fractional_inset = 1.0f / 6;
- break;
- }
- }
-
- FloatRectOutsets insets(
- -fractional_inset * edges[static_cast<unsigned>(BoxSide::kTop)].Width(),
- -fractional_inset *
- edges[static_cast<unsigned>(BoxSide::kRight)].Width(),
- -fractional_inset *
- edges[static_cast<unsigned>(BoxSide::kBottom)].Width(),
- -fractional_inset *
- edges[static_cast<unsigned>(BoxSide::kLeft)].Width());
-
- FloatRoundedRect background_rounded_rect = GetBackgroundRoundedRect(
- border_rect, flow_box_size, include_logical_left_edge,
- include_logical_right_edge);
- FloatRect inset_rect(background_rounded_rect.Rect());
- inset_rect.Expand(insets);
- FloatRoundedRect::Radii inset_radii(background_rounded_rect.GetRadii());
- inset_radii.Shrink(-insets.Top(), -insets.Bottom(), -insets.Left(),
- -insets.Right());
- return FloatRoundedRect(inset_rect, inset_radii);
- }
-
- return GetBackgroundRoundedRect(border_rect, flow_box_size,
- include_logical_left_edge,
- include_logical_right_edge);
-}
-
BoxPainterBase::FillLayerInfo::FillLayerInfo(
const Document& doc,
const ComputedStyle& style,
@@ -371,8 +320,7 @@ BoxPainterBase::FillLayerInfo::FillLayerInfo(
namespace {
-inline bool PaintFastBottomLayer(const DisplayItemClient& image_client,
- Node* node,
+inline bool PaintFastBottomLayer(Node* node,
const PaintInfo& paint_info,
const BoxPainterBase::FillLayerInfo& info,
const LayoutRect& rect,
@@ -391,27 +339,54 @@ inline bool PaintFastBottomLayer(const DisplayItemClient& image_client,
if (!info.should_paint_color && !info.should_paint_image)
return true;
+ // Compute the destination rect for painting the color here because we may
+ // need it for computing the image painting rect for optimization.
+ GraphicsContext& context = paint_info.context;
+ FloatRoundedRect color_border =
+ info.is_rounded_fill ? border_rect
+ : FloatRoundedRect(PixelSnappedIntRect(rect));
+
// When the layer has an image, figure out whether it is covered by a single
- // tile.
+ // tile. The border for painting images may not be the same as the color due
+ // to optimizations for the image painting destination that avoid painting
+ // under the border.
FloatRect image_tile;
+ FloatRoundedRect image_border;
if (info.should_paint_image) {
// Avoid image shaders when printing (poorly supported in PDF).
if (info.is_rounded_fill && paint_info.IsPrinting())
return false;
- if (!geometry.DestRect().IsEmpty()) {
- // The tile is too small.
- if (geometry.TileSize().Width() < rect.Width() ||
- geometry.TileSize().Height() < rect.Height())
+ // Compute the dest rect we will be using for images.
+ image_border =
+ info.is_rounded_fill
+ ? color_border
+ : FloatRoundedRect(FloatRect(geometry.SnappedDestRect()));
+
+ if (!image_border.Rect().IsEmpty()) {
+ // We cannot optimize if the tile is too small.
+ if (geometry.TileSize().Width() < image_border.Rect().Width() ||
+ geometry.TileSize().Height() < image_border.Rect().Height())
return false;
- image_tile = Image::ComputeTileContaining(
- FloatPoint(geometry.DestRect().Location()),
- FloatSize(geometry.TileSize()), FloatPoint(geometry.Phase()),
+ // Phase calculation uses the actual painted location, given by the
+ // border-snapped destination rect.
+ image_tile = Image::ComputePhaseForBackground(
+ FloatPoint(geometry.SnappedDestRect().Location()),
+ FloatSize(geometry.TileSize()), geometry.Phase(),
FloatSize(geometry.SpaceSize()));
- // The tile is misaligned.
- if (!image_tile.Contains(FloatRect(rect)))
+ // Force the image tile to LayoutUnit precision, which is the precision
+ // it was calcuated in. This avoids bleeding due to values very close to
+ // integers.
+ // The test images/sprite-no-bleed.html fails on two of the sub-cases
+ // due to this rounding still not being enough to make the Contains check
+ // pass. The best way to fix this would be to remove the paint rect offset
+ // from the tile computation, because we effectively add it in
+ // ComputePhaseForBackground then remove it in ComputeSubsetForBackground.
+ image_tile = FloatRect(LayoutRect(image_tile));
+ // We cannot optimize if the tile is misaligned.
+ if (!image_tile.Contains(image_border.Rect()))
return false;
}
}
@@ -419,56 +394,143 @@ inline bool PaintFastBottomLayer(const DisplayItemClient& image_client,
// At this point we're committed to the fast path: the destination (r)rect
// fits within a single tile, and we can paint it using direct draw(R)Rect()
// calls.
- GraphicsContext& context = paint_info.context;
- FloatRoundedRect border = info.is_rounded_fill
- ? border_rect
- : FloatRoundedRect(PixelSnappedIntRect(rect));
base::Optional<RoundedInnerRectClipper> clipper;
- if (info.is_rounded_fill && !border.IsRenderable()) {
+ if (info.is_rounded_fill && !color_border.IsRenderable()) {
// When the rrect is not renderable, we resort to clipping.
// RoundedInnerRectClipper handles this case via discrete, corner-wise
// clipping.
- clipper.emplace(image_client, paint_info, rect, border, kApplyToContext);
- border.SetRadii(FloatRoundedRect::Radii());
+ clipper.emplace(context, rect, color_border);
+ color_border.SetRadii(FloatRoundedRect::Radii());
}
// Paint the color if needed.
if (info.should_paint_color)
- context.FillRoundedRect(border, info.color);
+ context.FillRoundedRect(color_border, info.color);
// Paint the image if needed.
- if (!info.should_paint_image || image_tile.IsEmpty())
- return true;
-
- if (!image)
+ if (!info.should_paint_image || !image || image_tile.IsEmpty())
return true;
+ // Generated images will be created at the desired tile size, so assume their
+ // intrinsic size is the requested tile size.
const FloatSize intrinsic_tile_size =
image->HasRelativeSize() ? image_tile.Size() : FloatSize(image->Size());
- const FloatRect src_rect = Image::ComputeSubsetForTile(
- image_tile, border.Rect(), intrinsic_tile_size);
+ // Subset computation needs the same location as was used with
+ // ComputePhaseForBackground above, but needs the unsnapped destination
+ // size to correctly calculate sprite subsets in the presence of zoom.
+ FloatRect dest_rect_for_subset(
+ FloatPoint(geometry.SnappedDestRect().Location()),
+ FloatSize(geometry.UnsnappedDestRect().Size()));
+ // Content providers almost always choose source pixels at integer locations,
+ // so snap to integers. This is particuarly important for sprite maps.
+ // Calculation up to this point, in LayoutUnits, can lead to small variations
+ // from integer size, so it is safe to round without introducing major issues.
+ const FloatRect src_rect =
+ FloatRect(RoundedIntRect(Image::ComputeSubsetForBackground(
+ image_tile, dest_rect_for_subset, intrinsic_tile_size)));
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage",
"data",
- InspectorPaintImageEvent::Data(node, *info.image, image->Rect(),
- FloatRect(rect)));
+ InspectorPaintImageEvent::Data(node, *info.image,
+ FloatRect(image->Rect()),
+ FloatRect(image_border.Rect())));
+
// Since there is no way for the developer to specify decode behavior, use
// kSync by default.
- context.DrawImageRRect(image, Image::kSyncDecode, border, src_rect,
+ context.DrawImageRRect(image, Image::kSyncDecode, image_border, src_rect,
composite_op);
return true;
}
-} // anonymous namespace
+// Inset the background rect by a "safe" amount: 1/2 border-width for opaque
+// border styles, 1/6 border-width for double borders.
+FloatRoundedRect BackgroundRoundedRectAdjustedForBleedAvoidance(
+ const ComputedStyle& style,
+ const LayoutRect& border_rect,
+ bool object_has_multiple_boxes,
+ bool include_logical_left_edge,
+ bool include_logical_right_edge,
+ FloatRoundedRect background_rounded_rect) {
+ // TODO(fmalita): we should be able to fold these parameters into
+ // BoxBorderInfo or BoxDecorationData and avoid calling getBorderEdgeInfo
+ // redundantly here.
+ BorderEdge edges[4];
+ style.GetBorderEdgeInfo(edges, include_logical_left_edge,
+ include_logical_right_edge);
+
+ // Use the most conservative inset to avoid mixed-style corner issues.
+ float fractional_inset = 1.0f / 2;
+ for (auto& edge : edges) {
+ if (edge.BorderStyle() == EBorderStyle::kDouble) {
+ fractional_inset = 1.0f / 6;
+ break;
+ }
+ }
-void BoxPainterBase::PaintFillLayerBackground(
- GraphicsContext& context,
- const FillLayerInfo& info,
- Image* image,
- SkBlendMode composite_op,
- const BackgroundImageGeometry& geometry,
- LayoutRect scrolled_paint_rect) {
+ FloatRectOutsets insets(
+ -fractional_inset * edges[static_cast<unsigned>(BoxSide::kTop)].Width(),
+ -fractional_inset * edges[static_cast<unsigned>(BoxSide::kRight)].Width(),
+ -fractional_inset *
+ edges[static_cast<unsigned>(BoxSide::kBottom)].Width(),
+ -fractional_inset * edges[static_cast<unsigned>(BoxSide::kLeft)].Width());
+
+ FloatRect inset_rect(background_rounded_rect.Rect());
+ inset_rect.Expand(insets);
+ FloatRoundedRect::Radii inset_radii(background_rounded_rect.GetRadii());
+ inset_radii.Shrink(-insets.Top(), -insets.Bottom(), -insets.Left(),
+ -insets.Right());
+ return FloatRoundedRect(inset_rect, inset_radii);
+}
+
+FloatRoundedRect RoundedBorderRectForClip(
+ const ComputedStyle& style,
+ const BoxPainterBase::FillLayerInfo& info,
+ const FillLayer& bg_layer,
+ const LayoutRect& rect,
+ bool object_has_multiple_boxes,
+ const LayoutSize& flow_box_size,
+ BackgroundBleedAvoidance bleed_avoidance,
+ LayoutRectOutsets border_padding_insets) {
+ if (!info.is_rounded_fill)
+ return FloatRoundedRect();
+
+ FloatRoundedRect border = style.GetRoundedBorderFor(
+ rect, info.include_left_edge, info.include_right_edge);
+ if (object_has_multiple_boxes) {
+ FloatRoundedRect segment_border = style.GetRoundedBorderFor(
+ LayoutRect(LayoutPoint(), LayoutSize(FlooredIntSize(flow_box_size))),
+ info.include_left_edge, info.include_right_edge);
+ border.SetRadii(segment_border.GetRadii());
+ }
+
+ if (info.is_border_fill &&
+ bleed_avoidance == kBackgroundBleedShrinkBackground) {
+ border = BackgroundRoundedRectAdjustedForBleedAvoidance(
+ style, rect, object_has_multiple_boxes, info.include_left_edge,
+ info.include_right_edge, border);
+ }
+
+ // Clip to the padding or content boxes as necessary.
+ if (bg_layer.Clip() == EFillBox::kContent) {
+ border = style.GetRoundedInnerBorderFor(
+ LayoutRect(border.Rect()), border_padding_insets,
+ info.include_left_edge, info.include_right_edge);
+ } else if (bg_layer.Clip() == EFillBox::kPadding) {
+ border = style.GetRoundedInnerBorderFor(LayoutRect(border.Rect()),
+ info.include_left_edge,
+ info.include_right_edge);
+ }
+ return border;
+}
+
+void PaintFillLayerBackground(GraphicsContext& context,
+ const BoxPainterBase::FillLayerInfo& info,
+ Node* node,
+ Image* image,
+ SkBlendMode composite_op,
+ const BackgroundImageGeometry& geometry,
+ LayoutRect scrolled_paint_rect) {
// Paint the color first underneath all images, culled if background image
// occludes it.
// TODO(trchen): In the !bgLayer.hasRepeatXY() case, we could improve the
@@ -482,45 +544,37 @@ void BoxPainterBase::PaintFillLayerBackground(
// No progressive loading of the background image.
// NOTE: This method can be called with no image in situations when a bad
// resource locator is given such as "//:0", so still check for image.
- if (info.should_paint_image && !geometry.DestRect().IsEmpty() && image) {
- TRACE_EVENT1(
- TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage", "data",
- InspectorPaintImageEvent::Data(node_, *info.image, image->Rect(),
- FloatRect(scrolled_paint_rect)));
- context.DrawTiledImage(image, FloatRect(geometry.DestRect()),
- FloatPoint(geometry.Phase()),
- FloatSize(geometry.TileSize()), composite_op,
- FloatSize(geometry.SpaceSize()));
+ if (info.should_paint_image && !geometry.SnappedDestRect().IsEmpty() &&
+ image) {
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage",
+ "data",
+ InspectorPaintImageEvent::Data(
+ node, *info.image, FloatRect(image->Rect()),
+ FloatRect(scrolled_paint_rect)));
+ context.DrawTiledImage(image,
+ FloatSize(geometry.UnsnappedDestRect().Size()),
+ FloatRect(geometry.SnappedDestRect()),
+ geometry.Phase(), FloatSize(geometry.TileSize()),
+ composite_op, FloatSize(geometry.SpaceSize()));
}
}
-LayoutRectOutsets BoxPainterBase::BorderOutsets(
- const FillLayerInfo& info) const {
- LayoutRectOutsets borders = border_;
+LayoutRectOutsets AdjustOutsetsForEdgeInclusion(
+ const LayoutRectOutsets outsets,
+ const BoxPainterBase::FillLayerInfo& info) {
+ LayoutRectOutsets adjusted = outsets;
if (!info.include_right_edge)
- borders.SetRight(LayoutUnit());
+ adjusted.SetRight(LayoutUnit());
if (!info.include_left_edge)
- borders.SetLeft(LayoutUnit());
- return borders;
+ adjusted.SetLeft(LayoutUnit());
+ return adjusted;
}
-LayoutRectOutsets BoxPainterBase::PaddingOutsets(
- const FillLayerInfo& info) const {
- LayoutRectOutsets paddings = padding_;
- if (!info.include_right_edge)
- paddings.SetRight(LayoutUnit());
- if (!info.include_left_edge)
- paddings.SetLeft(LayoutUnit());
- return paddings;
-}
+} // anonymous namespace
-FloatRoundedRect BoxPainterBase::GetBackgroundRoundedRect(
- const LayoutRect& border_rect,
- const LayoutSize& flow_box_size,
- bool include_logical_left_edge,
- bool include_logical_right_edge) const {
- return style_.GetRoundedBorderFor(border_rect, include_logical_left_edge,
- include_logical_right_edge);
+LayoutRectOutsets BoxPainterBase::BorderOutsets(
+ const FillLayerInfo& info) const {
+ return AdjustOutsetsForEdgeInclusion(border_, info);
}
void BoxPainterBase::PaintFillLayer(const PaintInfo& paint_info,
@@ -530,6 +584,7 @@ void BoxPainterBase::PaintFillLayer(const PaintInfo& paint_info,
BackgroundBleedAvoidance bleed_avoidance,
BackgroundImageGeometry& geometry,
SkBlendMode op,
+ bool object_has_multiple_boxes,
const LayoutSize flow_box_size) {
GraphicsContext& context = paint_info.context;
if (rect.IsEmpty())
@@ -542,8 +597,9 @@ void BoxPainterBase::PaintFillLayer(const PaintInfo& paint_info,
GraphicsContextStateSaver clip_with_scrolling_state_saver(
context, info.is_clipped_with_local_scrolling);
- LayoutRect scrolled_paint_rect =
- AdjustForScrolledContent(paint_info, info, rect);
+ auto scrolled_paint_rect =
+ AdjustRectForScrolledContent(paint_info, info, rect);
+ const auto did_adjust_paint_rect = scrolled_paint_rect != rect;
scoped_refptr<Image> image;
SkBlendMode composite_op = op;
@@ -568,24 +624,29 @@ void BoxPainterBase::PaintFillLayer(const PaintInfo& paint_info,
}
LayoutRectOutsets border_padding_insets = -(border_ + padding_);
- FloatRoundedRect border_rect =
- RoundedBorderRectForClip(info, bg_layer, rect, flow_box_size,
- bleed_avoidance, border_padding_insets);
-
- // Fast path for drawing simple color backgrounds.
- if (PaintFastBottomLayer(display_item_, node_, paint_info, info, rect,
- border_rect, geometry, image.get(), composite_op)) {
+ FloatRoundedRect border_rect = RoundedBorderRectForClip(
+ style_, info, bg_layer, rect, object_has_multiple_boxes, flow_box_size,
+ bleed_avoidance, border_padding_insets);
+
+ // Fast path for drawing simple color backgrounds. Do not use the fast
+ // path if the dest rect has been adjusted for scrolling backgrounds
+ // because correcting the dest rect for this case reduces the accuracy of the
+ // destinations rects.
+ // TODO(schenney): Still use the fast path if not painting any images.
+ if (!did_adjust_paint_rect &&
+ PaintFastBottomLayer(node_, paint_info, info, rect, border_rect, geometry,
+ image.get(), composite_op)) {
return;
}
base::Optional<RoundedInnerRectClipper> clip_to_border;
- if (info.is_rounded_fill) {
- clip_to_border.emplace(display_item_, paint_info, rect, border_rect,
- kApplyToContext);
- }
+ if (info.is_rounded_fill)
+ clip_to_border.emplace(context, rect, border_rect);
+
if (bg_layer.Clip() == EFillBox::kText) {
PaintFillLayerTextFillBox(context, info, image.get(), composite_op,
- geometry, rect, scrolled_paint_rect);
+ geometry, rect, scrolled_paint_rect,
+ object_has_multiple_boxes);
return;
}
@@ -598,9 +659,9 @@ void BoxPainterBase::PaintFillLayer(const PaintInfo& paint_info,
// Clip to the padding or content boxes as necessary.
LayoutRect clip_rect = scrolled_paint_rect;
- clip_rect.Contract(BorderOutsets(info));
+ clip_rect.Contract(AdjustOutsetsForEdgeInclusion(border_, info));
if (bg_layer.Clip() == EFillBox::kContent)
- clip_rect.Contract(PaddingOutsets(info));
+ clip_rect.Contract(AdjustOutsetsForEdgeInclusion(padding_, info));
background_clip_state_saver.Save();
// TODO(chrishtr): this should be pixel-snapped.
context.Clip(FloatRect(clip_rect));
@@ -614,8 +675,8 @@ void BoxPainterBase::PaintFillLayer(const PaintInfo& paint_info,
break;
}
- PaintFillLayerBackground(context, info, image.get(), composite_op, geometry,
- scrolled_paint_rect);
+ PaintFillLayerBackground(context, info, node_, image.get(), composite_op,
+ geometry, scrolled_paint_rect);
}
void BoxPainterBase::PaintFillLayerTextFillBox(
@@ -625,7 +686,8 @@ void BoxPainterBase::PaintFillLayerTextFillBox(
SkBlendMode composite_op,
const BackgroundImageGeometry& geometry,
const LayoutRect& rect,
- const LayoutRect& scrolled_paint_rect) {
+ const LayoutRect& scrolled_paint_rect,
+ bool object_has_multiple_boxes) {
// First figure out how big the mask has to be. It should be no bigger
// than what we need to actually render, so we should intersect the dirty
// rect with the border box of the background.
@@ -638,7 +700,7 @@ void BoxPainterBase::PaintFillLayerTextFillBox(
context.Clip(mask_rect);
context.BeginLayer(1, composite_op);
- PaintFillLayerBackground(context, info, image, SkBlendMode::kSrcOver,
+ PaintFillLayerBackground(context, info, node_, image, SkBlendMode::kSrcOver,
geometry, scrolled_paint_rect);
// Create the text mask layer and draw the text into the mask. We do this by
@@ -646,43 +708,13 @@ void BoxPainterBase::PaintFillLayerTextFillBox(
// they should just add their contents to the clip.
context.BeginLayer(1, SkBlendMode::kDstIn);
- PaintTextClipMask(context, mask_rect, scrolled_paint_rect.Location());
+ PaintTextClipMask(context, mask_rect, scrolled_paint_rect.Location(),
+ object_has_multiple_boxes);
context.EndLayer(); // Text mask layer.
context.EndLayer(); // Background layer.
}
-FloatRoundedRect BoxPainterBase::RoundedBorderRectForClip(
- const BoxPainterBase::FillLayerInfo& info,
- const FillLayer& bg_layer,
- const LayoutRect& rect,
- const LayoutSize& flow_box_size,
- BackgroundBleedAvoidance bleed_avoidance,
- LayoutRectOutsets border_padding_insets) const {
- if (!info.is_rounded_fill)
- return FloatRoundedRect();
-
- FloatRoundedRect border =
- info.is_border_fill ? BackgroundRoundedRectAdjustedForBleedAvoidance(
- rect, flow_box_size, bleed_avoidance,
- info.include_left_edge, info.include_right_edge)
- : GetBackgroundRoundedRect(rect, flow_box_size,
- info.include_left_edge,
- info.include_right_edge);
-
- // Clip to the padding or content boxes as necessary.
- if (bg_layer.Clip() == EFillBox::kContent) {
- border = style_.GetRoundedInnerBorderFor(
- LayoutRect(border.Rect()), border_padding_insets,
- info.include_left_edge, info.include_right_edge);
- } else if (bg_layer.Clip() == EFillBox::kPadding) {
- border = style_.GetRoundedInnerBorderFor(LayoutRect(border.Rect()),
- info.include_left_edge,
- info.include_right_edge);
- }
- return border;
-}
-
void BoxPainterBase::PaintBorder(const ImageResourceObserver& obj,
const Document& document,
Node* node,
@@ -710,40 +742,15 @@ void BoxPainterBase::PaintMaskImages(const PaintInfo& paint_info,
BackgroundImageGeometry& geometry,
bool include_logical_left_edge,
bool include_logical_right_edge) {
- // Figure out if we need to push a transparency layer to render our mask.
- bool push_transparency_layer = false;
- bool all_mask_images_loaded = true;
-
if (!style_.HasMask() || style_.Visibility() != EVisibility::kVisible)
return;
- DCHECK(paint_layer_);
- if (!paint_layer_->MaskBlendingAppliedByCompositor(paint_info)) {
- push_transparency_layer = true;
- StyleImage* mask_box_image = style_.MaskBoxImage().GetImage();
- const FillLayer& mask_layers = style_.MaskLayers();
-
- // Don't render a masked element until all the mask images have loaded, to
- // prevent a flash of unmasked content.
- if (mask_box_image)
- all_mask_images_loaded &= mask_box_image->IsLoaded();
-
- all_mask_images_loaded &= mask_layers.ImagesAreLoaded();
-
- paint_info.context.BeginLayer(1, SkBlendMode::kDstIn);
- }
-
- if (all_mask_images_loaded) {
- PaintFillLayers(paint_info, Color::kTransparent, style_.MaskLayers(),
- paint_rect, geometry);
- NinePieceImagePainter::Paint(paint_info.context, obj, *document_, node_,
- paint_rect, style_, style_.MaskBoxImage(),
- include_logical_left_edge,
- include_logical_right_edge);
- }
-
- if (push_transparency_layer)
- paint_info.context.EndLayer();
+ PaintFillLayers(paint_info, Color::kTransparent, style_.MaskLayers(),
+ paint_rect, geometry);
+ NinePieceImagePainter::Paint(paint_info.context, obj, *document_, node_,
+ paint_rect, style_, style_.MaskBoxImage(),
+ include_logical_left_edge,
+ include_logical_right_edge);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/box_painter_base.h b/chromium/third_party/blink/renderer/core/paint/box_painter_base.h
index 93c618a38fe..9f4cb7909d3 100644
--- a/chromium/third_party/blink/renderer/core/paint/box_painter_base.h
+++ b/chromium/third_party/blink/renderer/core/paint/box_painter_base.h
@@ -18,13 +18,13 @@ namespace blink {
class BackgroundImageGeometry;
class ComputedStyle;
-class DisplayItemClient;
class Document;
class FillLayer;
class FloatRoundedRect;
+class GraphicsContext;
class ImageResourceObserver;
+class IntRect;
class LayoutRect;
-class PaintLayer;
struct PaintInfo;
// Base class for box painting. Has no dependencies on the layout tree and thus
@@ -34,20 +34,16 @@ class BoxPainterBase {
STACK_ALLOCATED();
public:
- BoxPainterBase(const DisplayItemClient& display_item,
- const Document* document,
+ BoxPainterBase(const Document* document,
const ComputedStyle& style,
Node* node,
LayoutRectOutsets border,
- LayoutRectOutsets padding,
- const PaintLayer* paint_layer)
- : display_item_(display_item),
- document_(document),
+ LayoutRectOutsets padding)
+ : document_(document),
style_(style),
node_(node),
border_(border),
- padding_(padding),
- paint_layer_(paint_layer) {}
+ padding_(padding) {}
void PaintFillLayers(const PaintInfo&,
const Color&,
@@ -64,6 +60,7 @@ class BoxPainterBase {
BackgroundBleedAvoidance,
BackgroundImageGeometry&,
SkBlendMode = SkBlendMode::kSrcOver,
+ bool object_has_multiple_boxes = false,
const LayoutSize flow_box_size = LayoutSize());
void PaintMaskImages(const PaintInfo&,
@@ -142,51 +139,26 @@ class BoxPainterBase {
};
protected:
- FloatRoundedRect BackgroundRoundedRectAdjustedForBleedAvoidance(
- const LayoutRect& border_rect,
- const LayoutSize& flow_box_size,
- BackgroundBleedAvoidance,
- bool include_logical_left_edge,
- bool include_logical_right_edge) const;
- FloatRoundedRect RoundedBorderRectForClip(
- const FillLayerInfo&,
- const FillLayer&,
- const LayoutRect&,
- const LayoutSize& flow_box_size,
- BackgroundBleedAvoidance,
- LayoutRectOutsets border_padding_insets) const;
-
- void PaintFillLayerBackground(GraphicsContext&,
- const FillLayerInfo&,
- Image*,
- SkBlendMode,
- const BackgroundImageGeometry&,
- LayoutRect scrolled_paint_rect);
LayoutRectOutsets BorderOutsets(const FillLayerInfo&) const;
- LayoutRectOutsets PaddingOutsets(const FillLayerInfo&) const;
-
void PaintFillLayerTextFillBox(GraphicsContext&,
const FillLayerInfo&,
Image*,
SkBlendMode composite_op,
const BackgroundImageGeometry&,
const LayoutRect&,
- const LayoutRect& scrolled_paint_rect);
+ const LayoutRect& scrolled_paint_rect,
+ bool object_has_multiple_boxes);
virtual void PaintTextClipMask(GraphicsContext&,
const IntRect& mask_rect,
- const LayoutPoint& paint_offset) = 0;
- virtual LayoutRect AdjustForScrolledContent(const PaintInfo&,
- const FillLayerInfo&,
- const LayoutRect&) = 0;
+ const LayoutPoint& paint_offset,
+ bool object_has_multiple_boxes) = 0;
+
+ virtual LayoutRect AdjustRectForScrolledContent(const PaintInfo&,
+ const FillLayerInfo&,
+ const LayoutRect&) = 0;
virtual FillLayerInfo GetFillLayerInfo(const Color&,
const FillLayer&,
BackgroundBleedAvoidance) const = 0;
- virtual FloatRoundedRect GetBackgroundRoundedRect(
- const LayoutRect& border_rect,
- const LayoutSize& flow_box_size,
- bool include_logical_left_edge,
- bool include_logical_right_edge) const;
-
static void PaintInsetBoxShadow(const PaintInfo&,
const FloatRoundedRect&,
const ComputedStyle&,
@@ -194,13 +166,11 @@ class BoxPainterBase {
bool include_logical_right_edge = true);
private:
- const DisplayItemClient& display_item_;
Member<const Document> document_;
const ComputedStyle& style_;
Member<Node> node_;
- LayoutRectOutsets border_;
- LayoutRectOutsets padding_;
- const PaintLayer* paint_layer_;
+ const LayoutRectOutsets border_;
+ const LayoutRectOutsets padding_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/clip_path_clipper.cc b/chromium/third_party/blink/renderer/core/paint/clip_path_clipper.cc
index 21b120ddccd..54e5ce3ae41 100644
--- a/chromium/third_party/blink/renderer/core/paint/clip_path_clipper.cc
+++ b/chromium/third_party/blink/renderer/core/paint/clip_path_clipper.cc
@@ -13,6 +13,8 @@
#include "third_party/blink/renderer/core/layout/svg/svg_resources_cache.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/style/clip_path_operation.h"
+#include "third_party/blink/renderer/core/style/reference_clip_path_operation.h"
+#include "third_party/blink/renderer/core/style/shape_clip_path_operation.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
@@ -145,35 +147,6 @@ ClipPathClipper::ClipPathClipper(GraphicsContext& context,
layout_object_(layout_object),
paint_offset_(paint_offset) {
DCHECK(layout_object.StyleRef().ClipPath());
-
- // Technically we should apply the mask clip and mask isolation property
- // nodes to match clip_recorder_ and mask_isolation_recorder_ below,
- // but we can safely omit those, because they will be applied in bundle
- // when the contents are painted.
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- base::Optional<FloatRect> bounding_box =
- LocalClipPathBoundingBox(layout_object);
- if (!bounding_box)
- return;
-
- FloatRect adjusted_bounding_box = *bounding_box;
- adjusted_bounding_box.MoveBy(FloatPoint(paint_offset));
- clip_recorder_.emplace(context, layout_object,
- DisplayItem::kFloatClipClipPathBounds,
- adjusted_bounding_box);
-
- bool is_valid = false;
- if (base::Optional<Path> as_path =
- PathBasedClip(layout_object, layout_object.IsSVGChild(),
- LocalReferenceBox(layout_object), is_valid)) {
- as_path->Translate(FloatSize(paint_offset.X(), paint_offset.Y()));
- clip_path_recorder_.emplace(context, layout_object, *as_path);
- } else if (is_valid) {
- mask_isolation_recorder_.emplace(context, layout_object,
- SkBlendMode::kSrcOver, 1.f);
- }
}
static AffineTransform MaskToContentTransform(
@@ -195,24 +168,17 @@ static AffineTransform MaskToContentTransform(
}
ClipPathClipper::~ClipPathClipper() {
- base::Optional<ScopedPaintChunkProperties> scoped_properties;
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- const auto* properties = layout_object_.FirstFragment().PaintProperties();
- if (!properties || !properties->ClipPath())
- return;
- scoped_properties.emplace(
- context_.GetPaintController(),
- layout_object_.FirstFragment().ClipPathProperties(), layout_object_,
- DisplayItem::kSVGClip);
- } else if (!mask_isolation_recorder_) {
+ const auto* properties = layout_object_.FirstFragment().PaintProperties();
+ if (!properties || !properties->ClipPath())
return;
- }
+ ScopedPaintChunkProperties scoped_properties(
+ context_.GetPaintController(),
+ layout_object_.FirstFragment().ClipPathProperties(), layout_object_,
+ DisplayItem::kSVGClip);
bool is_svg_child = layout_object_.IsSVGChild();
FloatRect reference_box = LocalReferenceBox(layout_object_);
- CompositingRecorder mask_recorder(context_, layout_object_,
- SkBlendMode::kDstIn, 1.f);
if (DrawingRecorder::UseCachedDrawingIfPossible(context_, layout_object_,
DisplayItem::kSVGClip))
return;
diff --git a/chromium/third_party/blink/renderer/core/paint/clip_path_clipper.h b/chromium/third_party/blink/renderer/core/paint/clip_path_clipper.h
index debbc7e1d33..9bea09e4182 100644
--- a/chromium/third_party/blink/renderer/core/paint/clip_path_clipper.h
+++ b/chromium/third_party/blink/renderer/core/paint/clip_path_clipper.h
@@ -7,10 +7,9 @@
#include "base/optional.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/paint/float_clip_recorder.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_path_recorder.h"
-#include "third_party/blink/renderer/platform/graphics/paint/compositing_recorder.h"
+#include "third_party/blink/renderer/platform/geometry/layout_point.h"
+#include "third_party/blink/renderer/platform/graphics/path.h"
namespace blink {
@@ -26,8 +25,6 @@ class CORE_EXPORT ClipPathClipper {
const LayoutPoint& paint_offset);
~ClipPathClipper();
- bool IsIsolationInstalled() const { return !!mask_isolation_recorder_; }
-
// Returns the reference box used by CSS clip-path. For HTML objects,
// this is the border box of the element. For SVG objects this is the
// object bounding box.
@@ -56,10 +53,6 @@ class CORE_EXPORT ClipPathClipper {
GraphicsContext& context_;
const LayoutObject& layout_object_;
LayoutPoint paint_offset_;
-
- base::Optional<FloatClipRecorder> clip_recorder_;
- base::Optional<ClipPathRecorder> clip_path_recorder_;
- base::Optional<CompositingRecorder> mask_isolation_recorder_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/clip_path_clipper_test.cc b/chromium/third_party/blink/renderer/core/paint/clip_path_clipper_test.cc
index 88530ea7bda..e89559d057c 100644
--- a/chromium/third_party/blink/renderer/core/paint/clip_path_clipper_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/clip_path_clipper_test.cc
@@ -23,7 +23,7 @@ TEST_F(ClipPathClipperTest, ClipPathBoundingBoxClamped) {
base::Optional<FloatRect> bounding_box =
ClipPathClipper::LocalClipPathBoundingBox(object);
ASSERT_TRUE(bounding_box.has_value());
- EXPECT_EQ(LayoutRect::InfiniteIntRect(), *bounding_box);
+ EXPECT_EQ(FloatRect(LayoutRect::InfiniteIntRect()), *bounding_box);
}
} // unnamed namespace
diff --git a/chromium/third_party/blink/renderer/core/paint/clip_rect.cc b/chromium/third_party/blink/renderer/core/paint/clip_rect.cc
index 9b610539100..dacca1a885e 100644
--- a/chromium/third_party/blink/renderer/core/paint/clip_rect.cc
+++ b/chromium/third_party/blink/renderer/core/paint/clip_rect.cc
@@ -27,16 +27,69 @@
#include "third_party/blink/renderer/core/paint/clip_rect.h"
#include "third_party/blink/renderer/core/layout/hit_test_location.h"
+#include "third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
+ClipRect::ClipRect()
+ : rect_(LayoutRect::InfiniteIntRect()),
+ has_radius_(false),
+ is_infinite_(true) {}
+
+ClipRect::ClipRect(const FloatClipRect& rect)
+ : rect_(rect.Rect()),
+ has_radius_(rect.HasRadius()),
+ is_infinite_(rect.IsInfinite()) {}
+
+void ClipRect::SetRect(const FloatClipRect& rect) {
+ if (rect.IsInfinite() && IsInfinite())
+ return;
+ rect_ = LayoutRect(rect.Rect());
+ has_radius_ = rect.HasRadius();
+ is_infinite_ = rect.IsInfinite();
+}
+
+void ClipRect::SetRect(const LayoutRect& rect) {
+ rect_ = rect;
+ has_radius_ = false;
+ is_infinite_ = false;
+}
+
+void ClipRect::Intersect(const LayoutRect& other) {
+ if (IsInfinite()) {
+ rect_ = other;
+ is_infinite_ = false;
+ } else {
+ rect_.Intersect(other);
+ }
+}
+
+void ClipRect::Intersect(const ClipRect& other) {
+ if (other.IsInfinite())
+ return;
+ Intersect(other.Rect());
+ if (other.HasRadius())
+ has_radius_ = true;
+}
+
bool ClipRect::Intersects(const HitTestLocation& hit_test_location) const {
+ if (is_infinite_)
+ return true;
return hit_test_location.Intersects(rect_);
}
+void ClipRect::Reset() {
+ if (is_infinite_)
+ return;
+ has_radius_ = true;
+ is_infinite_ = true;
+ rect_ = LayoutRect(LayoutRect::InfiniteIntRect());
+}
+
String ClipRect::ToString() const {
- return rect_.ToString() + (has_radius_ ? " hasRadius" : " noRadius");
+ return rect_.ToString() + (has_radius_ ? " hasRadius" : " noRadius") +
+ (is_infinite_ ? " isInfinite" : " notInfinite");
}
std::ostream& operator<<(std::ostream& ostream, const ClipRect& rect) {
diff --git a/chromium/third_party/blink/renderer/core/paint/clip_rect.h b/chromium/third_party/blink/renderer/core/paint/clip_rect.h
index 0fb23dda9f4..31d052062d8 100644
--- a/chromium/third_party/blink/renderer/core/paint/clip_rect.h
+++ b/chromium/third_party/blink/renderer/core/paint/clip_rect.h
@@ -28,33 +28,38 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
-#include "third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
namespace blink {
+class FloatClipRect;
class HitTestLocation;
-class ClipRect {
+class CORE_EXPORT ClipRect {
USING_FAST_MALLOC(ClipRect);
public:
- ClipRect() : has_radius_(false) {}
-
- ClipRect(const LayoutRect& rect) : rect_(rect), has_radius_(false) {}
-
- ClipRect(const FloatClipRect& rect)
- : rect_(rect.Rect()), has_radius_(rect.HasRadius()) {}
-
- void SetRect(const FloatClipRect& rect) {
- rect_ = LayoutRect(rect.Rect());
- has_radius_ = rect.HasRadius();
- }
+ ClipRect();
+ ClipRect(const LayoutRect& rect)
+ : rect_(rect), has_radius_(false), is_infinite_(false) {}
+ ClipRect(const FloatClipRect& rect);
+ void SetRect(const LayoutRect& rect);
const LayoutRect& Rect() const { return rect_; }
+ void SetRect(const FloatClipRect& rect);
+ // HasRadius is true if the clip this ClipRect has rounded corners.
+ // The ClipRect does not actually represent the rounded corners; those
+ // are computed as neeeded from the LayoutObject when actually applying the
+ // clip.
bool HasRadius() const { return has_radius_; }
- void SetHasRadius(bool has_radius) { has_radius_ = has_radius; }
+ void SetHasRadius(bool has_radius) {
+ if (IsInfinite())
+ return;
+ has_radius_ = has_radius;
+ }
+
+ bool IsInfinite() const { return is_infinite_; }
bool operator==(const ClipRect& other) const {
return Rect() == other.Rect() && HasRadius() == other.HasRadius();
@@ -66,12 +71,9 @@ class ClipRect {
return Rect() != other_rect;
}
- void Intersect(const LayoutRect& other) { rect_.Intersect(other); }
- void Intersect(const ClipRect& other) {
- rect_.Intersect(other.Rect());
- if (other.HasRadius())
- has_radius_ = true;
- }
+ void Intersect(const LayoutRect& other);
+ void Intersect(const ClipRect& other);
+
void Move(const LayoutSize& size) { rect_.Move(size); }
void Move(const IntSize& size) { rect_.Move(size); }
void MoveBy(const LayoutPoint& point) { rect_.MoveBy(point); }
@@ -79,11 +81,14 @@ class ClipRect {
bool IsEmpty() const { return rect_.IsEmpty(); }
bool Intersects(const HitTestLocation&) const;
+ void Reset();
+
String ToString() const;
private:
LayoutRect rect_;
- bool has_radius_;
+ bool has_radius_ : 1;
+ bool is_infinite_ : 1;
};
inline ClipRect Intersection(const ClipRect& a, const ClipRect& b) {
diff --git a/chromium/third_party/blink/renderer/core/paint/clip_rect_test.cc b/chromium/third_party/blink/renderer/core/paint/clip_rect_test.cc
new file mode 100644
index 00000000000..50111a4ec25
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/clip_rect_test.cc
@@ -0,0 +1,87 @@
+// 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/paint/clip_rect.h"
+#include "third_party/blink/renderer/core/layout/hit_test_location.h"
+#include "third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+class ClipRectTest : public testing::Test {};
+
+TEST_F(ClipRectTest, IsInfinite) {
+ ClipRect rect;
+ EXPECT_TRUE(rect.IsInfinite());
+
+ rect.SetRect(FloatClipRect());
+ EXPECT_TRUE(rect.IsInfinite());
+
+ rect.SetRect(LayoutRect());
+ EXPECT_FALSE(rect.IsInfinite());
+}
+
+TEST_F(ClipRectTest, HasRadius) {
+ ClipRect rect;
+ EXPECT_FALSE(rect.HasRadius());
+
+ rect.SetRect(FloatClipRect());
+ EXPECT_FALSE(rect.HasRadius());
+
+ FloatClipRect float_clip_rect;
+ float_clip_rect.SetHasRadius();
+ rect.SetRect(float_clip_rect);
+ EXPECT_TRUE(rect.HasRadius());
+
+ rect.SetRect(LayoutRect());
+ EXPECT_FALSE(rect.HasRadius());
+
+ rect.SetHasRadius(true);
+ EXPECT_TRUE(rect.HasRadius());
+
+ rect.SetRect(FloatClipRect());
+ EXPECT_FALSE(rect.HasRadius());
+ EXPECT_TRUE(rect.IsInfinite());
+}
+
+TEST_F(ClipRectTest, IntersectClipRect) {
+ ClipRect rect;
+ rect.SetRect(LayoutRect(100, 200, 300, 400));
+ EXPECT_FALSE(rect.HasRadius());
+
+ ClipRect rect2;
+ rect2.SetRect(LayoutRect(100, 100, 200, 300));
+ rect2.SetHasRadius(true);
+ rect.Intersect(rect2);
+ EXPECT_TRUE(rect.HasRadius());
+ EXPECT_FALSE(rect.IsInfinite());
+ EXPECT_EQ(LayoutRect(100, 200, 200, 200), rect.Rect());
+}
+
+TEST_F(ClipRectTest, IntersectLayoutRect) {
+ ClipRect rect;
+ LayoutRect layout_rect;
+
+ rect.Intersect(layout_rect);
+ EXPECT_FALSE(rect.IsInfinite());
+}
+
+TEST_F(ClipRectTest, IntersectsInfinite) {
+ ClipRect rect;
+
+ EXPECT_TRUE(rect.Intersects(HitTestLocation(FloatPoint(100000, -3333333))));
+}
+
+TEST_F(ClipRectTest, ToString) {
+ ClipRect rect;
+ rect.SetRect(LayoutRect(0, 0, 100, 100));
+ EXPECT_EQ(String("0,0 100x100 noRadius notInfinite"), rect.ToString());
+
+ rect.SetHasRadius(true);
+ EXPECT_EQ(String("0,0 100x100 hasRadius notInfinite"), rect.ToString());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/collapsed_border_painter.cc b/chromium/third_party/blink/renderer/core/paint/collapsed_border_painter.cc
index 447bf6eed49..66d874d8132 100644
--- a/chromium/third_party/blink/renderer/core/paint/collapsed_border_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/collapsed_border_painter.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/paint/collapsed_border_painter.h"
+#include "third_party/blink/renderer/core/paint/adjust_paint_offset_scope.h"
#include "third_party/blink/renderer/core/paint/block_painter.h"
#include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
@@ -333,8 +334,7 @@ static EBorderStyle CollapsedBorderStyle(EBorderStyle style) {
}
void CollapsedBorderPainter::PaintCollapsedBorders(
- const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+ const PaintInfo& paint_info) {
if (cell_.Style()->Visibility() != EVisibility::kVisible)
return;
@@ -350,9 +350,10 @@ void CollapsedBorderPainter::PaintCollapsedBorders(
// Now left=start_, right=end_, before_=top, after_=bottom.
// Collapsed borders are half inside and half outside of |rect|.
+ AdjustPaintOffsetScope adjustment(cell_, paint_info);
IntRect rect = PixelSnappedIntRect(
TableCellPainter(cell_).PaintRectNotIncludingVisualOverflow(
- paint_offset + cell_.Location()));
+ adjustment.PaintOffset()));
// |paint_rect| covers the whole collapsed borders.
IntRect paint_rect = rect;
paint_rect.Expand(IntRectOutsets(before_.outer_width, end_.outer_width,
diff --git a/chromium/third_party/blink/renderer/core/paint/collapsed_border_painter.h b/chromium/third_party/blink/renderer/core/paint/collapsed_border_painter.h
index fd6517f5655..3fccd0cfc3c 100644
--- a/chromium/third_party/blink/renderer/core/paint/collapsed_border_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/collapsed_border_painter.h
@@ -12,7 +12,6 @@
namespace blink {
struct PaintInfo;
-class LayoutPoint;
class CollapsedBorderPainter {
STACK_ALLOCATED();
@@ -21,7 +20,7 @@ class CollapsedBorderPainter {
CollapsedBorderPainter(const LayoutTableCell& cell)
: cell_(cell), table_(*cell.Table()) {}
- void PaintCollapsedBorders(const PaintInfo&, const LayoutPoint&);
+ void PaintCollapsedBorders(const PaintInfo&);
private:
void SetupBorders();
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 32861ebbc2c..c900e894b44 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
@@ -59,24 +59,20 @@
#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
#include "third_party/blink/renderer/core/paint/css_mask_painter.h"
#include "third_party/blink/renderer/core/paint/frame_paint_timing.h"
-#include "third_party/blink/renderer/core/paint/layer_clip_recorder.h"
#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer_painter.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h"
#include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
#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/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/clip_display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.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/transform_display_item.h"
#include "third_party/blink/renderer/platform/length_functions.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/transforms/transform_state.h"
@@ -178,9 +174,7 @@ static inline bool IsAcceleratedContents(LayoutObject& layout_object) {
// position offset for this composited layer.
static bool UsesCompositedStickyPosition(PaintLayer& layer) {
return layer.GetLayoutObject().Style()->HasStickyConstrainedPosition() &&
- (layer.AncestorOverflowLayer()->IsRootLayer()
- ? layer.GetLayoutObject().View()->GetFrameView()->IsScrollable()
- : layer.AncestorOverflowLayer()->NeedsCompositedScrolling());
+ layer.AncestorOverflowLayer()->NeedsCompositedScrolling();
}
// Returns the sticky position offset that should be removed from a given layer
@@ -398,7 +392,9 @@ void CompositedLayerMapping::UpdateIsRootForIsolatedGroup() {
bool isolate = owning_layer_.ShouldIsolateCompositedDescendants();
// non stacking context layers should never isolate
- DCHECK(owning_layer_.StackingNode()->IsStackingContext() || !isolate);
+ DCHECK((owning_layer_.StackingNode() &&
+ owning_layer_.GetLayoutObject().StyleRef().IsStackingContext()) ||
+ !isolate);
graphics_layer_->SetIsRootForIsolatedGroup(isolate);
}
@@ -558,8 +554,8 @@ void CompositedLayerMapping::UpdateAfterPartResize() {
FloatPoint parent_position = child_containment_layer_
? child_containment_layer_->GetPosition()
: FloatPoint();
- document_layer->SetPosition(FlooredIntPoint(
- FloatPoint(ContentsBox().Location()) - parent_position));
+ document_layer->SetPosition(FloatPoint(FlooredIntPoint(
+ FloatPoint(ContentsBox().Location()) - parent_position)));
}
}
}
@@ -572,27 +568,63 @@ void CompositedLayerMapping::UpdateCompositingReasons() {
owning_layer_.GetSquashingDisallowedReasons());
}
+static bool InContainingBlockChain(const PaintLayer* start_layer,
+ const PaintLayer* end_layer) {
+ if (start_layer == end_layer)
+ return true;
+
+ LayoutView* view = start_layer->GetLayoutObject().View();
+ for (const LayoutBlock* current_block =
+ start_layer->GetLayoutObject().ContainingBlock();
+ current_block && current_block != view;
+ current_block = current_block->ContainingBlock()) {
+ if (current_block->Layer() == end_layer)
+ return true;
+ }
+
+ return false;
+}
+
bool CompositedLayerMapping::AncestorRoundedCornersWillClip(
const FloatRect& bounds_in_ancestor_space) const {
- // Collect all border-radius clips between us and the state we inherited.
- LayoutPoint zero_offset;
- Vector<FloatRoundedRect> rounded_rect_clips;
- LayerClipRecorder::CollectRoundedRectClips(
- owning_layer_, clip_inheritance_ancestor_, zero_offset, true,
- LayerClipRecorder::kDoNotIncludeSelfForBorderRadius, rounded_rect_clips);
-
- for (auto clip_rect : rounded_rect_clips) {
- FloatRect inner_clip_rect = clip_rect.RadiusCenterRect();
- // The first condition catches cases where the child is certainly inside
- // the rounded corner portion of the border, and cannot be clipped by
- // the rounded portion. The second catches cases where the child is
- // entirely outside the rectangular border (ignoring rounded corners) so
- // is also unaffected by the rounded corners. In both cases the existing
- // rectangular clip is adequate and the mask is unnecessary.
- if (!inner_clip_rect.Contains(bounds_in_ancestor_space) &&
- bounds_in_ancestor_space.Intersects(clip_rect.Rect())) {
- return true;
+ // Check border-radius clips between us and the state we inherited.
+ for (const PaintLayer* layer = owning_layer_.Parent(); layer;
+ layer = layer->Parent()) {
+ // Check clips for embedded content despite their lack of overflow,
+ // because in practice they do need to clip. However, the clip is only
+ // used when painting child clipping masks to avoid clipping out border
+ // decorations.
+ if ((layer->GetLayoutObject().HasOverflowClip() ||
+ layer->GetLayoutObject().IsLayoutEmbeddedContent()) &&
+ layer->GetLayoutObject().Style()->HasBorderRadius() &&
+ InContainingBlockChain(&owning_layer_, layer)) {
+ LayoutPoint delta;
+ layer->ConvertToLayerCoords(clip_inheritance_ancestor_, delta);
+
+ // The PaintLayer's size is pixel-snapped if it is a LayoutBox. We can't
+ // use a pre-snapped border rect for clipping, since
+ // getRoundedInnerBorderFor assumes it has not been snapped yet.
+ LayoutSize size(layer->GetLayoutBox()
+ ? ToLayoutBox(layer->GetLayoutObject()).Size()
+ : LayoutSize(layer->Size()));
+ auto clip_rect =
+ layer->GetLayoutObject().StyleRef().GetRoundedInnerBorderFor(
+ LayoutRect(delta, size));
+ auto inner_clip_rect = clip_rect.RadiusCenterRect();
+
+ // The first condition catches cases where the child is certainly inside
+ // the rounded corner portion of the border, and cannot be clipped by
+ // the rounded portion. The second catches cases where the child is
+ // entirely outside the rectangular border (ignoring rounded corners) so
+ // is also unaffected by the rounded corners. In both cases the existing
+ // rectangular clip is adequate and the mask is unnecessary.
+ if (!inner_clip_rect.Contains(bounds_in_ancestor_space) &&
+ bounds_in_ancestor_space.Intersects(clip_rect.Rect())) {
+ return true;
+ }
}
+ if (layer == clip_inheritance_ancestor_)
+ break;
}
return false;
}
@@ -1008,10 +1040,10 @@ void CompositedLayerMapping::UpdateSquashingLayerGeometry(
} else if (compositing_container) {
common_transform_ancestor =
&compositing_container->TransformAncestorOrRoot();
+ } else {
+ common_transform_ancestor = owning_layer_.Root();
}
- // What about a null compositing container?
-
// FIXME: Cache these offsets.
LayoutPoint compositing_container_offset_from_transformed_ancestor;
if (compositing_container) {
@@ -1082,9 +1114,6 @@ void CompositedLayerMapping::UpdateSquashingLayerGeometry(
offset_from_squash_layer_origin + new_offset_from_layout_object;
if (layers[i].offset_from_layout_object_set &&
layers[i].offset_from_layout_object != new_offset_from_layout_object) {
- // It is ok to issue paint invalidation here, because all of the geometry
- // needed to correctly invalidate paint is computed by this point.
- DisablePaintInvalidationStateAsserts disabler;
ObjectPaintInvalidator(layers[i].paint_layer->GetLayoutObject())
.InvalidatePaintIncludingNonCompositingDescendants();
@@ -1099,12 +1128,12 @@ void CompositedLayerMapping::UpdateSquashingLayerGeometry(
layers[i].paint_layer->SetSubpixelAccumulation(subpixel_accumulation);
}
- squashing_layer_->SetPosition(squash_layer_bounds.Location());
+ squashing_layer_->SetPosition(FloatPoint(squash_layer_bounds.Location()));
squashing_layer_->SetSize(squash_layer_bounds.Size());
// We can't squashing_layer_->SetOffsetFromLayoutObject().
// Squashing layer has special paint and invalidation logic that already
// compensated for compositing bounds, setting it here would end up
- // double adjustment. The value is stored to be used by SPv175.
+ // double adjustment.
auto new_offset = squash_layer_bounds.Location() -
snapped_offset_from_composited_ancestor +
ToIntSize(graphics_layer_parent_location);
@@ -1501,7 +1530,7 @@ void CompositedLayerMapping::UpdateChildContainmentLayerGeometry() {
IntPoint parent_location(
child_containment_layer_->Parent()->OffsetFromLayoutObject());
child_containment_layer_->SetPosition(
- IntPoint(clipping_box.Location() - parent_location));
+ FloatPoint(clipping_box.Location() - parent_location));
} else {
IntRect clipping_box = PixelSnappedIntRect(
ToLayoutBox(GetLayoutObject())
@@ -1512,12 +1541,16 @@ void CompositedLayerMapping::UpdateChildContainmentLayerGeometry() {
IntPoint parent_location(
child_containment_layer_->Parent()->OffsetFromLayoutObject());
child_containment_layer_->SetPosition(
- IntPoint(clipping_box.Location() - parent_location));
+ FloatPoint(clipping_box.Location() - parent_location));
}
if (child_clipping_mask_layer_ && !scrolling_layer_ &&
!GetLayoutObject().Style()->ClipPath()) {
- child_clipping_mask_layer_->SetSize(child_containment_layer_->Size());
+ if (child_clipping_mask_layer_->Size() !=
+ child_containment_layer_->Size()) {
+ child_clipping_mask_layer_->SetSize(child_containment_layer_->Size());
+ child_clipping_mask_layer_->SetNeedsDisplay();
+ }
child_clipping_mask_layer_->SetOffsetFromLayoutObject(
child_containment_layer_->OffsetFromLayoutObject());
}
@@ -1608,21 +1641,19 @@ void CompositedLayerMapping::UpdateScrollingLayerGeometry(
bool scroll_container_size_changed =
old_scroll_container_size != scrolling_layer_->Size();
- IntSize old_scrolling_layer_offset =
- scrolling_layer_->OffsetFromLayoutObject();
scrolling_layer_->SetOffsetFromLayoutObject(
ToIntSize(overflow_clip_rect.Location()));
if (child_clipping_mask_layer_ && !GetLayoutObject().Style()->ClipPath()) {
child_clipping_mask_layer_->SetPosition(scrolling_layer_->GetPosition());
- child_clipping_mask_layer_->SetSize(scrolling_layer_->Size());
+ if (child_clipping_mask_layer_->Size() != scrolling_layer_->Size()) {
+ child_clipping_mask_layer_->SetSize(scrolling_layer_->Size());
+ child_clipping_mask_layer_->SetNeedsDisplay();
+ }
child_clipping_mask_layer_->SetOffsetFromLayoutObject(
ToIntSize(overflow_clip_rect.Location()));
}
- bool overflow_clip_rect_offset_changed =
- old_scrolling_layer_offset != scrolling_layer_->OffsetFromLayoutObject();
-
IntSize scroll_size =
PixelSnappedIntRect(
LayoutRect(
@@ -1632,9 +1663,6 @@ void CompositedLayerMapping::UpdateScrollingLayerGeometry(
// Ensure scrolling contents are at least as large as the scroll clip
scroll_size = scroll_size.ExpandedTo(overflow_clip_rect.Size());
- if (overflow_clip_rect_offset_changed)
- scrolling_contents_layer_->SetNeedsDisplay();
-
FloatPoint scroll_position =
owning_layer_.GetScrollableArea()->ScrollPosition();
DoubleSize scrolling_contents_offset(
@@ -1669,10 +1697,8 @@ void CompositedLayerMapping::UpdateScrollingLayerGeometry(
}
scrolling_contents_layer_offset_from_layout_object.MoveBy(
overflow_clip_rect.Location());
-
- scrolling_contents_layer_->SetOffsetDoubleFromLayoutObject(
- ToIntSize(scrolling_contents_layer_offset_from_layout_object),
- GraphicsLayer::kDontSetNeedsDisplay);
+ scrolling_contents_layer_->SetOffsetFromLayoutObject(
+ ToIntSize(scrolling_contents_layer_offset_from_layout_object));
}
void CompositedLayerMapping::UpdateChildClippingMaskLayerGeometry() {
@@ -1683,13 +1709,33 @@ void CompositedLayerMapping::UpdateChildClippingMaskLayerGeometry() {
IntRect padding_box = EnclosingIntRect(layout_box.PaddingBoxRect());
child_clipping_mask_layer_->SetPosition(graphics_layer_->GetPosition());
- child_clipping_mask_layer_->SetSize(graphics_layer_->Size());
+ if (child_clipping_mask_layer_->Size() != graphics_layer_->Size()) {
+ child_clipping_mask_layer_->SetSize(graphics_layer_->Size());
+ child_clipping_mask_layer_->SetNeedsDisplay();
+ }
child_clipping_mask_layer_->SetOffsetFromLayoutObject(
ToIntSize(padding_box.Location()));
// NOTE: also some stuff happening in updateChildContainmentLayerGeometry().
}
+bool CompositedLayerMapping::RequiresHorizontalScrollbarLayer() const {
+ return owning_layer_.GetScrollableArea() &&
+ owning_layer_.GetScrollableArea()->HorizontalScrollbar();
+}
+
+bool CompositedLayerMapping::RequiresVerticalScrollbarLayer() const {
+ return owning_layer_.GetScrollableArea() &&
+ owning_layer_.GetScrollableArea()->VerticalScrollbar();
+}
+
+bool CompositedLayerMapping::RequiresScrollCornerLayer() const {
+ return owning_layer_.GetScrollableArea() &&
+ !owning_layer_.GetScrollableArea()
+ ->ScrollCornerAndResizerRect()
+ .IsEmpty();
+}
+
void CompositedLayerMapping::UpdateForegroundLayerGeometry() {
if (!foreground_layer_)
return;
@@ -1697,13 +1743,13 @@ void CompositedLayerMapping::UpdateForegroundLayerGeometry() {
// Should be equivalent to local_compositing_bounds.
IntRect compositing_bounds(
IntPoint(graphics_layer_->OffsetFromLayoutObject()),
- FlooredIntSize(graphics_layer_->Size()));
+ graphics_layer_->Size());
if (scrolling_layer_) {
// Override compositing bounds to include full overflow if composited
// scrolling is used.
compositing_bounds =
IntRect(IntPoint(scrolling_contents_layer_->OffsetFromLayoutObject()),
- FlooredIntSize(scrolling_contents_layer_->Size()));
+ scrolling_contents_layer_->Size());
} else if (child_containment_layer_) {
// If we have a clipping layer, shrink compositing bounds to the clip rect.
// Note: this is technically incorrect because non-composited positive
@@ -1712,13 +1758,13 @@ void CompositedLayerMapping::UpdateForegroundLayerGeometry() {
// escape clips, thus shrinking the layer won't cause bug.
IntRect clipping_box(
IntPoint(child_containment_layer_->OffsetFromLayoutObject()),
- FlooredIntSize(child_containment_layer_->Size()));
+ child_containment_layer_->Size());
compositing_bounds.Intersect(clipping_box);
}
IntRect old_compositing_bounds(
IntPoint(foreground_layer_->OffsetFromLayoutObject()),
- FlooredIntSize(foreground_layer_->Size()));
+ foreground_layer_->Size());
if (compositing_bounds != old_compositing_bounds) {
foreground_layer_->SetOffsetFromLayoutObject(
ToIntSize(compositing_bounds.Location()));
@@ -1727,7 +1773,7 @@ void CompositedLayerMapping::UpdateForegroundLayerGeometry() {
}
IntPoint parent_location(ParentForSublayers()->OffsetFromLayoutObject());
foreground_layer_->SetPosition(
- IntPoint(compositing_bounds.Location() - parent_location));
+ FloatPoint(compositing_bounds.Location() - parent_location));
}
void CompositedLayerMapping::UpdateDecorationOutlineLayerGeometry(
@@ -2138,7 +2184,7 @@ void CompositedLayerMapping::PositionOverflowControlsLayers() {
Scrollbar* h_bar = owning_layer_.GetScrollableArea()->HorizontalScrollbar();
if (h_bar) {
IntRect frame_rect = h_bar->FrameRect();
- layer->SetPosition(frame_rect.Location());
+ layer->SetPosition(FloatPoint(frame_rect.Location()));
layer->SetOffsetFromLayoutObject(ToIntSize(frame_rect.Location()));
layer->SetSize(frame_rect.Size());
if (layer->HasContentsLayer())
@@ -2151,7 +2197,7 @@ void CompositedLayerMapping::PositionOverflowControlsLayers() {
Scrollbar* v_bar = owning_layer_.GetScrollableArea()->VerticalScrollbar();
if (v_bar) {
IntRect frame_rect = v_bar->FrameRect();
- layer->SetPosition(frame_rect.Location());
+ layer->SetPosition(FloatPoint(frame_rect.Location()));
layer->SetOffsetFromLayoutObject(ToIntSize(frame_rect.Location()));
layer->SetSize(frame_rect.Size());
if (layer->HasContentsLayer())
@@ -2648,7 +2694,7 @@ float CompositedLayerMapping::CompositingOpacity(
for (PaintLayer* curr = owning_layer_.Parent(); curr; curr = curr->Parent()) {
// We only care about parents that are stacking contexts.
// Recall that opacity creates stacking context.
- if (!curr->StackingNode()->IsStackingContext())
+ if (!curr->GetLayoutObject().StyleRef().IsStackingContext())
continue;
// If we found a composited layer, regardless of whether it actually
@@ -2707,8 +2753,8 @@ bool CompositedLayerMapping::HasVisibleNonCompositingDescendant(
if (!parent->HasVisibleDescendant())
return false;
- // FIXME: We shouldn't be called with a stale z-order lists. See bug 85512.
- parent->StackingNode()->UpdateLayerListsIfNeeded();
+ if (!parent->StackingNode())
+ return false;
#if DCHECK_IS_ON()
LayerListMutationDetector mutation_checker(parent->StackingNode());
@@ -2716,12 +2762,11 @@ bool CompositedLayerMapping::HasVisibleNonCompositingDescendant(
PaintLayerStackingNodeIterator normal_flow_iterator(*parent->StackingNode(),
kAllChildren);
- while (PaintLayerStackingNode* cur_node = normal_flow_iterator.Next()) {
- PaintLayer* cur_layer = cur_node->Layer();
- if (cur_layer->HasCompositedLayerMapping())
+ while (PaintLayer* child_layer = normal_flow_iterator.Next()) {
+ if (child_layer->HasCompositedLayerMapping())
continue;
- if (cur_layer->HasVisibleContent() ||
- HasVisibleNonCompositingDescendant(cur_layer))
+ if (child_layer->HasVisibleContent() ||
+ HasVisibleNonCompositingDescendant(child_layer))
return true;
}
@@ -2887,9 +2932,12 @@ LayoutRect CompositedLayerMapping::ContentsBox() const {
}
bool CompositedLayerMapping::NeedsToReparentOverflowControls() const {
+ const ComputedStyle& style = owning_layer_.GetLayoutObject().StyleRef();
return owning_layer_.GetScrollableArea() &&
owning_layer_.GetScrollableArea()->HasOverlayScrollbars() &&
- owning_layer_.GetScrollableArea()->TopmostScrollChild();
+ !style.IsStackingContext() &&
+ (style.IsStacked() ||
+ owning_layer_.IsNonStackedWithInFlowStackedDescendant());
}
GraphicsLayer* CompositedLayerMapping::DetachLayerForOverflowControls() {
@@ -2978,69 +3026,6 @@ void CompositedLayerMapping::SetContentsNeedDisplay() {
kApplyToContentLayers);
}
-struct SetContentsNeedsDisplayInRectFunctor {
- void operator()(GraphicsLayer* layer) const {
- if (layer->DrawsContent()) {
- IntRect layer_dirty_rect = r;
- layer_dirty_rect.Move(-layer->OffsetFromLayoutObject());
- layer->SetNeedsDisplayInRect(layer_dirty_rect, invalidation_reason,
- client);
- }
- }
-
- IntRect r;
- PaintInvalidationReason invalidation_reason;
- const DisplayItemClient& client;
-};
-
-void CompositedLayerMapping::SetContentsNeedDisplayInRect(
- const LayoutRect& r,
- PaintInvalidationReason invalidation_reason,
- const DisplayItemClient& client) {
- DCHECK(!owning_layer_.GetLayoutObject().UsesCompositedScrolling());
- // TODO(wangxianzhu): Enable the following assert after paint invalidation for
- // spv2 is ready.
- // DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
-
- SetContentsNeedsDisplayInRectFunctor functor = {
- EnclosingIntRect(LayoutRect(
- r.Location() + owning_layer_.SubpixelAccumulation(), r.Size())),
- invalidation_reason, client};
- ApplyToGraphicsLayers(this, functor, kApplyToContentLayers);
-}
-
-void CompositedLayerMapping::SetNonScrollingContentsNeedDisplayInRect(
- const LayoutRect& r,
- PaintInvalidationReason invalidation_reason,
- const DisplayItemClient& client) {
- DCHECK(owning_layer_.GetLayoutObject().UsesCompositedScrolling());
- // TODO(wangxianzhu): Enable the following assert after paint invalidation for
- // spv2 is ready.
- // DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
-
- SetContentsNeedsDisplayInRectFunctor functor = {
- EnclosingIntRect(LayoutRect(
- r.Location() + owning_layer_.SubpixelAccumulation(), r.Size())),
- invalidation_reason, client};
- ApplyToGraphicsLayers(this, functor, kApplyToNonScrollingContentLayers);
-}
-
-void CompositedLayerMapping::SetScrollingContentsNeedDisplayInRect(
- const LayoutRect& r,
- PaintInvalidationReason invalidation_reason,
- const DisplayItemClient& client) {
- DCHECK(owning_layer_.GetLayoutObject().UsesCompositedScrolling());
- // TODO(wangxianzhu): Enable the following assert after paint invalidation for
- // spv2 is ready.
- // DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
-
- SetContentsNeedsDisplayInRectFunctor functor = {
- EnclosingIntRect(LayoutRect(
- r.Location() + owning_layer_.SubpixelAccumulation(), r.Size())),
- invalidation_reason, client};
- ApplyToGraphicsLayers(this, functor, kApplyToScrollingContentLayers);
-}
-
void CompositedLayerMapping::SetNeedsCheckRasterInvalidation() {
ApplyToGraphicsLayers(this,
[](GraphicsLayer* graphics_layer) {
@@ -3122,10 +3107,6 @@ void CompositedLayerMapping::DoPaintTask(
FontCachePurgePreventer font_cache_purge_preventer;
IntSize offset = paint_info.offset_from_layout_object;
- AffineTransform translation;
- translation.Translate(-offset.Width(), -offset.Height());
- TransformRecorder transform_recorder(context, graphics_layer, translation);
-
// The dirtyRect is in the coords of the painting root.
IntRect dirty_rect(clip);
dirty_rect.Move(offset);
@@ -3177,22 +3158,6 @@ void CompositedLayerMapping::DoPaintTask(
PaintLayerPaintingInfo painting_info(
paint_info.paint_layer, LayoutRect(dirty_rect), kGlobalPaintNormalPhase,
paint_info.paint_layer->SubpixelAccumulation());
-
- // PaintLayer::paintLayer assumes that the caller clips to the passed rect.
- // Squashed layers need to do this clipping in software, since there is no
- // graphics layer to clip them precisely. Furthermore, in some cases we
- // squash layers that need clipping in software from clipping ancestors (see
- // CompositedLayerMapping::localClipRectForSquashedLayer()).
- // FIXME: Is it correct to clip to dirtyRect in slimming paint mode?
- ClipRect clip_rect = paint_info.local_clip_rect_for_squashed_layer;
- clip_rect.Intersect(LayoutRect(dirty_rect));
-
- LayerClipRecorder layer_clip_recorder(
- context, *paint_info.paint_layer,
- DisplayItem::kClipLayerOverflowControls, clip_rect,
- paint_info.local_clip_rect_root, paint_info.offset_from_clip_rect_root,
- paint_layer_flags, graphics_layer,
- LayerClipRecorder::kDoNotIncludeSelfForBorderRadius);
PaintLayerPainter(*paint_info.paint_layer)
.Paint(context, painting_info, paint_layer_flags);
}
@@ -3285,11 +3250,11 @@ IntRect CompositedLayerMapping::RecomputeInterestRect(
// If the visible content rect is empty, then it makes no sense to map it back
// since there is nothing to map.
if (!visible_content_rect.IsEmpty()) {
- local_interest_rect =
+ local_interest_rect = FloatRect(
anchor_layout_object
->AbsoluteToLocalQuad(visible_content_rect,
kUseTransforms | kTraverseDocumentBoundaries)
- .EnclosingBoundingBox();
+ .EnclosingBoundingBox());
local_interest_rect.Move(-offset_from_anchor_layout_object);
// TODO(chrishtr): the code below is a heuristic, instead we should detect
// and return whether the mapping failed. In some cases,
@@ -3365,8 +3330,7 @@ IntRect CompositedLayerMapping::ComputeInterestRect(
const GraphicsLayer* graphics_layer,
const IntRect& previous_interest_rect) const {
// Use the previous interest rect if it covers the whole layer.
- IntRect whole_layer_rect =
- IntRect(IntPoint(), ExpandedIntSize(graphics_layer->Size()));
+ IntRect whole_layer_rect = IntRect(IntPoint(), graphics_layer->Size());
if (!NeedsRepaint(*graphics_layer) &&
previous_interest_rect == whole_layer_rect)
return previous_interest_rect;
@@ -3379,8 +3343,7 @@ IntRect CompositedLayerMapping::ComputeInterestRect(
IntRect new_interest_rect = RecomputeInterestRect(graphics_layer);
if (NeedsRepaint(*graphics_layer) ||
InterestRectChangedEnoughToRepaint(
- previous_interest_rect, new_interest_rect,
- ExpandedIntSize(graphics_layer->Size())))
+ previous_interest_rect, new_interest_rect, graphics_layer->Size()))
return new_interest_rect;
return previous_interest_rect;
}
@@ -3511,19 +3474,10 @@ void CompositedLayerMapping::PaintScrollableArea(
const GraphicsLayer* graphics_layer,
GraphicsContext& context,
const IntRect& interest_rect) const {
- // Note the composited scrollable area painted here is never associated with a
- // frame. For painting frame ScrollableAreas, see
- // PaintLayerCompositor::paintContents.
-
- // Map context and cull_rect which are in the local space of the scrollbar
- // to the space of the containing scrollable area in which Scrollbar::Paint()
- // will paint the scrollbar.
- auto offset = graphics_layer->OffsetFromLayoutObject();
- CullRect cull_rect(CullRect(interest_rect), offset);
- TransformRecorder transform_recorder(
- context, *graphics_layer,
- AffineTransform::Translation(-offset.Width(), -offset.Height()));
-
+ // cull_rect is in the space of the containing scrollable area in which
+ // Scrollbar::Paint() will paint the scrollbar.
+ CullRect cull_rect(CullRect(interest_rect),
+ graphics_layer->OffsetFromLayoutObject());
PaintLayerScrollableArea* scrollable_area = owning_layer_.GetScrollableArea();
if (graphics_layer == LayerForHorizontalScrollbar()) {
if (const Scrollbar* scrollbar = scrollable_area->HorizontalScrollbar())
@@ -3556,6 +3510,11 @@ bool CompositedLayerMapping::IsTrackingRasterInvalidations() const {
->IsTrackingPaintInvalidations();
}
+void CompositedLayerMapping::SetOverlayScrollbarsHidden(bool hidden) {
+ if (ScrollableArea* scrollable_area = owning_layer_.GetScrollableArea())
+ scrollable_area->SetScrollbarsHiddenIfOverlay(hidden);
+}
+
#if DCHECK_IS_ON()
void CompositedLayerMapping::VerifyNotPainting() {
DCHECK(!GetLayoutObject().GetFrame()->GetPage() ||
@@ -3684,6 +3643,7 @@ void CompositedLayerMapping::FinishAccumulatingSquashingLayers(
if (InvalidateLayerIfNoPrecedingEntry(i)) {
squashed_layers_[i].paint_layer->SetGroupedMapping(
nullptr, PaintLayer::kDoNotInvalidateLayerAndRemoveFromMapping);
+ squashed_layers_[i].paint_layer->SetLostGroupedMapping(true);
}
layers_needing_paint_invalidation.push_back(
squashed_layers_[i].paint_layer);
@@ -3746,4 +3706,11 @@ String CompositedLayerMapping::DebugName(
return name;
}
+const ScrollableArea* CompositedLayerMapping::GetScrollableAreaForTesting(
+ const GraphicsLayer* layer) const {
+ if (layer == scrolling_contents_layer_.get())
+ return owning_layer_.GetScrollableArea();
+ return nullptr;
+}
+
} // namespace blink
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 5750216b8c6..36ca4fc651c 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
@@ -173,18 +173,6 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
void SetSquashingContentsNeedDisplay();
void SetContentsNeedDisplay();
- // LayoutRect is in the coordinate space of the layer's layout object.
- void SetContentsNeedDisplayInRect(const LayoutRect&,
- PaintInvalidationReason,
- const DisplayItemClient&);
- // Invalidates just the non-scrolling content layers.
- void SetNonScrollingContentsNeedDisplayInRect(const LayoutRect&,
- PaintInvalidationReason,
- const DisplayItemClient&);
- // Invalidates just scrolling content layers.
- void SetScrollingContentsNeedDisplayInRect(const LayoutRect&,
- PaintInvalidationReason,
- const DisplayItemClient&);
// Let all DrawsContent GraphicsLayers check raster invalidations after
// a no-change paint.
@@ -226,6 +214,7 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
const IntRect& interest_rect) const override;
bool ShouldThrottleRendering() const override;
bool IsTrackingRasterInvalidations() const override;
+ void SetOverlayScrollbarsHidden(bool) override;
#if DCHECK_IS_ON()
void VerifyNotPainting() override;
@@ -283,6 +272,9 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
String DebugName(const GraphicsLayer*) const override;
+ const ScrollableArea* GetScrollableAreaForTesting(
+ const GraphicsLayer*) const override;
+
LayoutSize ContentOffsetInCompositingLayer() const;
// Returned value does not include any composited scroll offset of
@@ -415,20 +407,9 @@ class CORE_EXPORT CompositedLayerMapping final : public GraphicsLayerClient {
bool UpdateDecorationOutlineLayer(bool needs_decoration_outline_layer);
bool UpdateMaskLayer(bool needs_mask_layer);
bool UpdateChildClippingMaskLayer(bool needs_child_clipping_mask_layer);
- bool RequiresHorizontalScrollbarLayer() const {
- return owning_layer_.GetScrollableArea() &&
- owning_layer_.GetScrollableArea()->HorizontalScrollbar();
- }
- bool RequiresVerticalScrollbarLayer() const {
- return owning_layer_.GetScrollableArea() &&
- owning_layer_.GetScrollableArea()->VerticalScrollbar();
- }
- bool RequiresScrollCornerLayer() const {
- return owning_layer_.GetScrollableArea() &&
- !owning_layer_.GetScrollableArea()
- ->ScrollCornerAndResizerRect()
- .IsEmpty();
- }
+ bool RequiresHorizontalScrollbarLayer() const;
+ bool RequiresVerticalScrollbarLayer() const;
+ bool RequiresScrollCornerLayer() const;
bool UpdateScrollingLayers(bool scrolling_layers);
void UpdateScrollParent(const PaintLayer*);
void UpdateClipParent(const PaintLayer* scroll_parent);
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc b/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
index da070be1bda..bc5f72982a3 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping_test.cc
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/layout/layout_image.h"
#include "third_party/blink/renderer/core/layout/layout_view.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"
namespace blink {
@@ -166,8 +167,8 @@ TEST_F(CompositedLayerMappingTest, TallCompositedScrolledLayerInterestRect) {
)HTML");
GetDocument().View()->UpdateAllLifecyclePhases();
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 8000), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 8000),
+ kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
Element* element = GetDocument().getElementById("target");
@@ -184,11 +185,11 @@ TEST_F(CompositedLayerMappingTest, TallNonCompositedScrolledLayerInterestRect) {
)HTML");
GetDocument().View()->UpdateAllLifecyclePhases();
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 8000), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 8000),
+ kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
- PaintLayer* paint_layer = GetDocument().View()->Layer();
+ PaintLayer* paint_layer = GetDocument().GetLayoutView()->Layer();
ASSERT_TRUE(paint_layer->GraphicsLayerBacking());
EXPECT_EQ(IntRect(0, 4000, 800, 7016),
RecomputeInterestRect(paint_layer->GraphicsLayerBacking()));
@@ -223,7 +224,7 @@ TEST_F(CompositedLayerMappingTest, VerticalRightLeftWritingModeDocument) {
)HTML");
GetDocument().View()->UpdateAllLifecyclePhases();
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(-5000, 0), kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
@@ -628,8 +629,8 @@ TEST_F(CompositedLayerMappingTest, InterestRectChangeOnViewportScroll) {
EXPECT_EQ(IntRect(0, 0, 800, 4600),
PreviousInterestRect(root_scrolling_layer));
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 300), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 300),
+ kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
// Still use the previous interest rect because the recomputed rect hasn't
// changed enough.
@@ -638,8 +639,8 @@ TEST_F(CompositedLayerMappingTest, InterestRectChangeOnViewportScroll) {
EXPECT_EQ(IntRect(0, 0, 800, 4600),
PreviousInterestRect(root_scrolling_layer));
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 600), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 600),
+ kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
// Use recomputed interest rect because it changed enough.
EXPECT_EQ(IntRect(0, 0, 800, 5200),
@@ -647,16 +648,16 @@ TEST_F(CompositedLayerMappingTest, InterestRectChangeOnViewportScroll) {
EXPECT_EQ(IntRect(0, 0, 800, 5200),
PreviousInterestRect(root_scrolling_layer));
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 5400), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 5400),
+ kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
EXPECT_EQ(IntRect(0, 1400, 800, 8600),
RecomputeInterestRect(root_scrolling_layer));
EXPECT_EQ(IntRect(0, 1400, 800, 8600),
PreviousInterestRect(root_scrolling_layer));
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 9000), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 9000),
+ kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
// Still use the previous interest rect because it contains the recomputed
// interest rect.
@@ -665,8 +666,8 @@ TEST_F(CompositedLayerMappingTest, InterestRectChangeOnViewportScroll) {
EXPECT_EQ(IntRect(0, 1400, 800, 8600),
PreviousInterestRect(root_scrolling_layer));
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(0, 2000), kProgrammaticScroll);
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(ScrollOffset(0, 2000),
+ kProgrammaticScroll);
// Use recomputed interest rect because it changed enough.
GetDocument().View()->UpdateAllLifecyclePhases();
EXPECT_EQ(IntRect(0, 0, 800, 6600),
@@ -865,7 +866,7 @@ TEST_F(CompositedLayerMappingTest, InterestRectOfIframeInScrolledDiv) {
"will-change: transform}</style><div id=target></div>");
// Scroll 8000 pixels down to move the iframe into view.
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0.0, 8000.0), kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
@@ -896,7 +897,7 @@ TEST_F(CompositedLayerMappingTest, InterestRectOfScrolledIframe) {
GetDocument().View()->UpdateAllLifecyclePhases();
// Scroll 7500 pixels down to bring the scrollable area to the bottom.
- ChildDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
+ ChildDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0.0, 7500.0), kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
@@ -930,7 +931,7 @@ TEST_F(CompositedLayerMappingTest, InterestRectOfIframeWithContentBoxOffset) {
// Scroll 3000 pixels down to bring the scrollable area to somewhere in the
// middle.
- ChildDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
+ ChildDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0.0, 3000.0), kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
@@ -972,7 +973,7 @@ TEST_F(CompositedLayerMappingTest, InterestRectOfIframeWithFixedContents) {
// this to the right-most 4000x4000 area.
EXPECT_EQ(IntRect(1000, 0, 4400, 300), RecomputeInterestRect(graphics_layer));
- ChildDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
+ ChildDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0.0, 3000.0), kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
@@ -998,7 +999,7 @@ TEST_F(CompositedLayerMappingTest, ScrolledFixedPositionInterestRect) {
auto* graphics_layer = fixed->EnclosingLayer()->GraphicsLayerBacking(fixed);
EXPECT_EQ(IntRect(0, 500, 100, 4030), RecomputeInterestRect(graphics_layer));
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(0.0, 200.0), kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
@@ -2470,20 +2471,20 @@ TEST_F(CompositedLayerMappingTest, ScrollingContainerBoundsChange) {
PaintLayerScrollableArea* scrollable_area = scroller->GetScrollableArea();
cc::Layer* scrolling_layer = scrollable_area->LayerForScrolling()->CcLayer();
- EXPECT_EQ(0, scrolling_layer->scroll_offset().y());
+ EXPECT_EQ(0, scrolling_layer->CurrentScrollOffset().y());
EXPECT_EQ(150, scrolling_layer->bounds().height());
EXPECT_EQ(100, scrolling_layer->scroll_container_bounds().height());
scrollerElement->setScrollTop(300);
scrollerElement->setAttribute(HTMLNames::styleAttr, "max-height: 25px;");
GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_EQ(50, scrolling_layer->scroll_offset().y());
+ EXPECT_EQ(50, scrolling_layer->CurrentScrollOffset().y());
EXPECT_EQ(150, scrolling_layer->bounds().height());
EXPECT_EQ(25, scrolling_layer->scroll_container_bounds().height());
scrollerElement->setAttribute(HTMLNames::styleAttr, "max-height: 300px;");
GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_EQ(50, scrolling_layer->scroll_offset().y());
+ EXPECT_EQ(50, scrolling_layer->CurrentScrollOffset().y());
EXPECT_EQ(150, scrolling_layer->bounds().height());
EXPECT_EQ(100, scrolling_layer->scroll_container_bounds().height());
}
@@ -2559,13 +2560,13 @@ TEST_F(CompositedLayerMappingTest, ForegroundLayerSizing) {
->Layer()
->GetCompositedLayerMapping();
ASSERT_TRUE(mapping);
- EXPECT_EQ(FloatSize(120, 120), mapping->MainGraphicsLayer()->Size());
+ EXPECT_EQ(IntSize(120, 120), mapping->MainGraphicsLayer()->Size());
ASSERT_TRUE(mapping->ClippingLayer());
EXPECT_EQ(FloatPoint(10, 10), mapping->ClippingLayer()->GetPosition());
- EXPECT_EQ(FloatSize(100, 100), mapping->ClippingLayer()->Size());
+ EXPECT_EQ(IntSize(100, 100), mapping->ClippingLayer()->Size());
ASSERT_TRUE(mapping->ForegroundLayer());
EXPECT_EQ(FloatPoint(0, 0), mapping->ForegroundLayer()->GetPosition());
- EXPECT_EQ(FloatSize(100, 100), mapping->ForegroundLayer()->Size());
+ EXPECT_EQ(IntSize(100, 100), mapping->ForegroundLayer()->Size());
}
TEST_F(CompositedLayerMappingTest, ScrollLayerSizingSubpixelAccumulation) {
@@ -2632,8 +2633,8 @@ TEST_F(CompositedLayerMappingTest, SquashingScroll) {
LayoutPoint(),
squashed->GroupedMapping()->SquashingOffsetFromTransformedAncestor());
- GetDocument().View()->LayoutViewportScrollableArea()->ScrollBy(
- ScrollOffset(0, 25), kUserScroll);
+ GetDocument().View()->LayoutViewport()->ScrollBy(ScrollOffset(0, 25),
+ kUserScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
EXPECT_EQ(
@@ -2658,8 +2659,8 @@ TEST_F(CompositedLayerMappingTest, SquashingScrollInterestRect) {
ToLayoutBoxModelObject(GetLayoutObjectByElementId("squashed"))->Layer();
EXPECT_EQ(kPaintsIntoGroupedBacking, squashed->GetCompositingState());
- GetDocument().View()->LayoutViewportScrollableArea()->ScrollBy(
- ScrollOffset(0, 5000), kUserScroll);
+ GetDocument().View()->LayoutViewport()->ScrollBy(ScrollOffset(0, 5000),
+ kUserScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
EXPECT_EQ(IntRect(0, 1000, 200, 5000),
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/composited_selection.h b/chromium/third_party/blink/renderer/core/paint/compositing/composited_selection.h
index efa1a24167f..808b2f50ea7 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/composited_selection.h
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/composited_selection.h
@@ -40,8 +40,8 @@
namespace blink {
// The active selection region, containing compositing data for the selection
-// end points as well as metadata for the selection region.
-// See |WebSelection|.
+// end points as well as metadata for the selection region. Maps to a
+// cc::LayerSelection when the |type| is not kNoSelection.
struct CompositedSelection {
STACK_ALLOCATED();
CompositedSelection() : type(kNoSelection) {}
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 d393de8bede..f7e9bdc5724 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
@@ -12,6 +12,7 @@
#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.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
namespace blink {
@@ -23,8 +24,12 @@ static const LayoutBoxModelObject* ClippingContainerFromClipChainParent(
: clip_chain_parent->ClippingContainer();
}
-CompositingInputsUpdater::CompositingInputsUpdater(PaintLayer* root_layer)
- : geometry_map_(kUseTransforms), root_layer_(root_layer) {}
+CompositingInputsUpdater::CompositingInputsUpdater(
+ PaintLayer* root_layer,
+ CompositingReasonFinder& compositing_reason_finder)
+ : geometry_map_(kUseTransforms),
+ root_layer_(root_layer),
+ compositing_reason_finder_(compositing_reason_finder) {}
CompositingInputsUpdater::~CompositingInputsUpdater() = default;
@@ -36,10 +41,6 @@ void CompositingInputsUpdater::Update() {
void CompositingInputsUpdater::UpdateRecursive(PaintLayer* layer,
UpdateType update_type,
AncestorInfo info) {
- if (!layer->ChildNeedsCompositingInputsUpdate() &&
- update_type != kForceUpdate)
- return;
-
LayoutBoxModelObject& layout_object = layer->GetLayoutObject();
const ComputedStyle& style = layout_object.StyleRef();
@@ -165,7 +166,7 @@ void CompositingInputsUpdater::UpdateRecursive(PaintLayer* layer,
? info.clip_chain_parent_for_fixed
: nullptr;
// Workaround crbug.com/817175
- // We can't escape clip to a layer that paints after us, because in SPv1*
+ // We can't escape clip to a layer that paints after us, because in SPv1
// cc needs to reverse engineer clip tree from the layer tree, and we
// can't refer to a clip node that hasn't been built yet.
// This will result in wrong clip in some rare cases, for example:
@@ -189,11 +190,59 @@ void CompositingInputsUpdater::UpdateRecursive(PaintLayer* layer,
info.needs_reparent_scroll_for_fixed = false;
}
+ PaintLayerCompositor* compositor =
+ layer->GetLayoutObject().View()->Compositor();
+
+ // The sequence of updates to compositing triggers goes like this:
+ // 1. Apply all triggers from kComboAllDirectNonStyleDeterminedReasons for
+ // |layer|. This may depend on ancestor composited scrolling (i.e. step
+ // 2 for an ancestor PaintLayer).
+ // 2. Put |layer| in composited scrolling mode if needed.
+ // 3. Reset DescendantHasDirectCompositingReason to false for |layer|.
+ // 4. Recurse into child PaintLayers.
+ // 5. Set DescendantHasDirectCompositingReason to true if it was for any
+ // child.
+ // 6. If |layer| is the root, composite if
+ // DescendantHasDirectCompositingReason is true for |layer|.
+ bool ignore_lcd_text =
+ (layer->AncestorScrollingLayer() &&
+ !layer->AncestorScrollingLayer()->IsRootLayer() &&
+ layer->AncestorScrollingLayer()->NeedsCompositedScrolling());
+
+ layer->SetPotentialCompositingReasonsFromNonStyle(
+ compositing_reason_finder_.NonStyleDeterminedDirectReasons(
+ layer, ignore_lcd_text));
+
+ if (layer->GetScrollableArea()) {
+ layer->GetScrollableArea()->UpdateNeedsCompositedScrolling(
+ compositor->CanBeComposited(layer) &&
+ layer->DirectCompositingReasons());
+ }
+
+ bool should_recurse =
+ layer->ChildNeedsCompositingInputsUpdate() || update_type == kForceUpdate;
+
+ layer->SetDescendantHasDirectOrScrollingCompositingReason(false);
+ bool descendant_has_direct_compositing_reason = false;
for (PaintLayer* child = layer->FirstChild(); child;
- child = child->NextSibling())
- UpdateRecursive(child, update_type, info);
+ child = child->NextSibling()) {
+ if (should_recurse)
+ UpdateRecursive(child, update_type, info);
+ descendant_has_direct_compositing_reason |=
+ child->DescendantHasDirectOrScrollingCompositingReason() ||
+ child->NeedsCompositedScrolling() ||
+ (compositor->CanBeComposited(child) &&
+ child->DirectCompositingReasons());
+ }
+ layer->SetDescendantHasDirectOrScrollingCompositingReason(
+ descendant_has_direct_compositing_reason);
+
+ if (layer->IsRootLayer() && layer->ScrollsOverflow() &&
+ layer->DescendantHasDirectOrScrollingCompositingReason() &&
+ !layer->NeedsCompositedScrolling())
+ layer->GetScrollableArea()->UpdateNeedsCompositedScrolling(true);
- layer->DidUpdateCompositingInputs();
+ layer->ClearChildNeedsCompositingInputsUpdate();
geometry_map_.PopMappingsToAncestor(layer->Parent());
@@ -288,7 +337,7 @@ void CompositingInputsUpdater::UpdateAncestorDependentCompositingInputs(
properties.clip_parent = info.escape_clip_to;
properties.ancestor_scrolling_layer = info.scrolling_ancestor;
- if (info.needs_reparent_scroll && layer->StackingNode()->IsStacked())
+ if (info.needs_reparent_scroll && layout_object.StyleRef().IsStacked())
properties.scroll_parent = info.scrolling_ancestor;
layer->UpdateAncestorDependentCompositingInputs(properties);
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h
index 0a432f62512..a7c07a1eac4 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h
@@ -11,12 +11,15 @@
namespace blink {
class PaintLayer;
+class CompositingReasonFinder;
class CompositingInputsUpdater {
STACK_ALLOCATED();
public:
- explicit CompositingInputsUpdater(PaintLayer* root_layer);
+ explicit CompositingInputsUpdater(
+ PaintLayer* root_layer,
+ CompositingReasonFinder& compositing_reason_finder);
~CompositingInputsUpdater();
void Update();
@@ -62,6 +65,7 @@ class CompositingInputsUpdater {
LayoutGeometryMap geometry_map_;
PaintLayer* root_layer_;
+ CompositingReasonFinder& compositing_reason_finder_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc
index d8d8986972e..c979b7949e5 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater_test.cc
@@ -2,9 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/paint/compositing/compositing_inputs_updater.h"
+#include "testing/gtest/include/gtest/gtest.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"
namespace blink {
@@ -98,8 +99,8 @@ TEST_F(CompositingInputsUpdaterTest, UnclippedAndClippedRectsUnderScroll) {
LayoutBoxModelObject* target =
ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"));
- GetDocument().View()->LayoutViewportScrollableArea()->ScrollBy(
- ScrollOffset(0, 25), kUserScroll);
+ GetDocument().View()->LayoutViewport()->ScrollBy(ScrollOffset(0, 25),
+ kUserScroll);
GetDocument()
.View()
->GetLayoutView()
@@ -124,8 +125,8 @@ TEST_F(CompositingInputsUpdaterTest,
LayoutBoxModelObject* target =
ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"));
- GetDocument().View()->LayoutViewportScrollableArea()->ScrollBy(
- ScrollOffset(0, 25), kUserScroll);
+ GetDocument().View()->LayoutViewport()->ScrollBy(ScrollOffset(0, 25),
+ kUserScroll);
GetDocument()
.View()
->GetLayoutView()
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 0539fec93e6..7c36d148bed 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
@@ -26,6 +26,8 @@
#include "third_party/blink/renderer/core/paint/compositing/compositing_layer_assigner.h"
+#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
+#include "third_party/blink/renderer/core/animation/worklet_animation_controller.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/page/page.h"
@@ -283,85 +285,108 @@ void CompositingLayerAssigner::AssignLayersToBackingsInternal(
PaintLayer* layer,
SquashingState& squashing_state,
Vector<PaintLayer*>& layers_needing_paint_invalidation) {
- if (RequiresSquashing(layer->GetCompositingReasons())) {
- SquashingDisallowedReasons reasons_preventing_squashing =
- GetReasonsPreventingSquashing(layer, squashing_state);
- if (reasons_preventing_squashing) {
- layer->SetCompositingReasons(layer->GetCompositingReasons() |
- CompositingReason::kSquashingDisallowed);
- layer->SetSquashingDisallowedReasons(reasons_preventing_squashing);
+ if (layer->NeedsCompositingLayerAssignment()) {
+ DCHECK(layer->GetCompositingReasons() ||
+ (layer->GetCompositingState() != kNotComposited) ||
+ layer->LostGroupedMapping());
+ if (RequiresSquashing(layer->GetCompositingReasons())) {
+ SquashingDisallowedReasons reasons_preventing_squashing =
+ GetReasonsPreventingSquashing(layer, squashing_state);
+ if (reasons_preventing_squashing) {
+ layer->SetCompositingReasons(layer->GetCompositingReasons() |
+ CompositingReason::kSquashingDisallowed);
+ layer->SetSquashingDisallowedReasons(reasons_preventing_squashing);
+ }
}
- }
- CompositingStateTransitionType composited_layer_update =
- ComputeCompositedLayerUpdate(layer);
+ CompositingStateTransitionType composited_layer_update =
+ ComputeCompositedLayerUpdate(layer);
+
+ if (compositor_->AllocateOrClearCompositedLayerMapping(
+ layer, composited_layer_update)) {
+ TRACE_LAYER_INVALIDATION(
+ layer, InspectorLayerInvalidationTrackingEvent::kNewCompositedLayer);
+ layers_needing_paint_invalidation.push_back(layer);
+ layers_changed_ = true;
+ if (ScrollingCoordinator* scrolling_coordinator =
+ layer->GetScrollingCoordinator()) {
+ if (layer->GetLayoutObject()
+ .Style()
+ ->HasViewportConstrainedPosition()) {
+ scrolling_coordinator->FrameViewFixedObjectsDidChange(
+ layer->GetLayoutObject().View()->GetFrameView());
+ }
+ }
+ }
- if (compositor_->AllocateOrClearCompositedLayerMapping(
- layer, composited_layer_update)) {
- TRACE_LAYER_INVALIDATION(
- layer, InspectorLayerInvalidationTrackingEvent::kNewCompositedLayer);
- layers_needing_paint_invalidation.push_back(layer);
- layers_changed_ = true;
- if (ScrollingCoordinator* scrolling_coordinator =
- layer->GetScrollingCoordinator()) {
- if (layer->GetLayoutObject().Style()->HasViewportConstrainedPosition()) {
- scrolling_coordinator->FrameViewFixedObjectsDidChange(
- layer->GetLayoutObject().View()->GetFrameView());
+ if (composited_layer_update != kNoCompositingStateChange) {
+ // A change in the compositing state of a ScrollTimeline's scroll source
+ // can cause the compositor's view of the scroll source to become out of
+ // date. We inform the WorkletAnimationController about any such changes
+ // so that it can schedule a compositing animations update.
+ Node* node = layer->GetLayoutObject().GetNode();
+ if (node && ScrollTimeline::HasActiveScrollTimeline(node)) {
+ node->GetDocument()
+ .GetWorkletAnimationController()
+ .ScrollSourceCompositingStateChanged(node);
}
}
- }
- // Add this layer to a squashing backing if needed.
- UpdateSquashingAssignment(layer, squashing_state, composited_layer_update,
- layers_needing_paint_invalidation);
-
- const bool layer_is_squashed =
- composited_layer_update == kPutInSquashingLayer ||
- (composited_layer_update == kNoCompositingStateChange &&
- layer->GroupedMapping());
- if (layer_is_squashed) {
- squashing_state.next_squashed_layer_index++;
- IntRect layer_bounds = layer->ClippedAbsoluteBoundingBox();
- squashing_state.total_area_of_squashed_rects += layer_bounds.Size().Area();
- squashing_state.bounding_rect.Unite(layer_bounds);
+ // Add this layer to a squashing backing if needed.
+ UpdateSquashingAssignment(layer, squashing_state, composited_layer_update,
+ layers_needing_paint_invalidation);
+
+ const bool layer_is_squashed =
+ composited_layer_update == kPutInSquashingLayer ||
+ (composited_layer_update == kNoCompositingStateChange &&
+ layer->GroupedMapping());
+ if (layer_is_squashed) {
+ squashing_state.next_squashed_layer_index++;
+ IntRect layer_bounds = layer->ClippedAbsoluteBoundingBox();
+ squashing_state.total_area_of_squashed_rects +=
+ layer_bounds.Size().Area();
+ squashing_state.bounding_rect.Unite(layer_bounds);
+ }
}
- if (layer->StackingNode()->IsStackingContext()) {
+ if (layer->StackingDescendantNeedsCompositingLayerAssignment() &&
+ layer->GetLayoutObject().StyleRef().IsStackingContext()) {
PaintLayerStackingNodeIterator iterator(*layer->StackingNode(),
kNegativeZOrderChildren);
- while (PaintLayerStackingNode* cur_node = iterator.Next()) {
- AssignLayersToBackingsInternal(cur_node->Layer(), squashing_state,
+ while (PaintLayer* child_node = iterator.Next()) {
+ AssignLayersToBackingsInternal(child_node, squashing_state,
layers_needing_paint_invalidation);
}
}
// At this point, if the layer is to be separately composited, then its
// backing becomes the most recent in paint-order.
- if (layer->GetCompositingState() == kPaintsIntoOwnBacking) {
+ if (layer->NeedsCompositingLayerAssignment() &&
+ layer->GetCompositingState() == kPaintsIntoOwnBacking) {
DCHECK(!RequiresSquashing(layer->GetCompositingReasons()));
squashing_state.UpdateSquashingStateForNewMapping(
layer->GetCompositedLayerMapping(), layer->HasCompositedLayerMapping(),
layers_needing_paint_invalidation);
}
- if (layer->ScrollParent())
- layer->ScrollParent()->GetScrollableArea()->SetTopmostScrollChild(layer);
-
- if (layer->NeedsCompositedScrolling())
- layer->GetScrollableArea()->SetTopmostScrollChild(nullptr);
-
- PaintLayerStackingNodeIterator iterator(
- *layer->StackingNode(), kNormalFlowChildren | kPositiveZOrderChildren);
- while (PaintLayerStackingNode* cur_node = iterator.Next()) {
- AssignLayersToBackingsInternal(cur_node->Layer(), squashing_state,
- layers_needing_paint_invalidation);
+ if (layer->StackingNode() &&
+ layer->StackingDescendantNeedsCompositingLayerAssignment()) {
+ PaintLayerStackingNodeIterator iterator(
+ *layer->StackingNode(), kNormalFlowChildren | kPositiveZOrderChildren);
+ while (PaintLayer* curr_layer = iterator.Next()) {
+ AssignLayersToBackingsInternal(curr_layer, squashing_state,
+ layers_needing_paint_invalidation);
+ }
}
- if (squashing_state.has_most_recent_mapping &&
- &squashing_state.most_recent_mapping->OwningLayer() == layer) {
- squashing_state.have_assigned_backings_to_entire_squashing_layer_subtree =
- true;
+ if (layer->NeedsCompositingLayerAssignment()) {
+ if (squashing_state.has_most_recent_mapping &&
+ &squashing_state.most_recent_mapping->OwningLayer() == layer) {
+ squashing_state.have_assigned_backings_to_entire_squashing_layer_subtree =
+ true;
+ }
}
+ layer->ClearNeedsCompositingLayerAssignment();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc
index 143d7486075..3d1acd5a14b 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.cc
@@ -9,11 +9,18 @@
#include "third_party/blink/renderer/core/paint/fragment_data.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+namespace {
+enum class ScrollbarOrCorner {
+ kHorizontalScrollbar,
+ kVerticalScrollbar,
+ kScrollbarCorner,
+};
+}
+
namespace blink {
void CompositingLayerPropertyUpdater::Update(const LayoutObject& object) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() ||
- RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
return;
if (!object.HasLayer())
@@ -26,7 +33,10 @@ void CompositingLayerPropertyUpdater::Update(const LayoutObject& object) {
const FragmentData& fragment_data = object.FirstFragment();
DCHECK(fragment_data.HasLocalBorderBoxProperties());
// SPv1 compositing forces single fragment for composited elements.
- DCHECK(!fragment_data.NextFragment());
+ DCHECK(!fragment_data.NextFragment() ||
+ // We create multiple fragments for composited repeating fixed-position
+ // during printing.
+ object.GetDocument().Printing());
LayoutPoint layout_snapped_paint_offset =
fragment_data.PaintOffset() - mapping->SubpixelAccumulation();
@@ -37,9 +47,12 @@ void CompositingLayerPropertyUpdater::Update(const LayoutObject& object) {
// that all of its ancestors have a visible subtree. An ancestor with no
// visible subtree can be non-composited despite we expected it to, this
// resulted in the paint offset used by CompositedLayerMapping to mismatch.
+#if 0
+ // TODO(crbug.com/838018): Re-enable this check.
bool subpixel_accumulation_may_be_bogus = paint_layer->SubtreeIsInvisible();
DCHECK(layout_snapped_paint_offset == snapped_paint_offset ||
subpixel_accumulation_may_be_bogus);
+#endif
base::Optional<PropertyTreeState> container_layer_state;
auto SetContainerLayerState =
@@ -63,38 +76,48 @@ void CompositingLayerPropertyUpdater::Update(const LayoutObject& object) {
SetContainerLayerState(mapping->DecorationOutlineLayer());
SetContainerLayerState(mapping->ChildClippingMaskLayer());
- base::Optional<PropertyTreeState> scrollbar_layer_state;
-
auto SetContainerLayerStateForScrollbars =
- [&fragment_data, &snapped_paint_offset, &container_layer_state,
- &scrollbar_layer_state](GraphicsLayer* graphics_layer) {
- if (graphics_layer) {
- if (!scrollbar_layer_state) {
- // OverflowControlsClip should be applied within the scrollbar
- // layers.
- if (container_layer_state) {
- scrollbar_layer_state = container_layer_state;
- } else {
- scrollbar_layer_state = fragment_data.LocalBorderBoxProperties();
- }
+ [&fragment_data, &snapped_paint_offset, &container_layer_state](
+ GraphicsLayer* graphics_layer,
+ ScrollbarOrCorner scrollbar_or_corner) {
+ if (!graphics_layer)
+ return;
+ PropertyTreeState scrollbar_layer_state =
+ container_layer_state.value_or(
+ fragment_data.LocalBorderBoxProperties());
+ // OverflowControlsClip should be applied within the scrollbar
+ // layers.
+ if (const auto* properties = fragment_data.PaintProperties()) {
+ if (const auto* clip = properties->OverflowControlsClip()) {
+ scrollbar_layer_state.SetClip(clip);
+ } else if (const auto* css_clip = properties->CssClip()) {
+ scrollbar_layer_state.SetClip(css_clip->Parent());
+ }
+ }
- if (const auto* properties = fragment_data.PaintProperties()) {
- if (const auto* clip = properties->OverflowControlsClip()) {
- scrollbar_layer_state->SetClip(clip);
- } else if (const auto* css_clip = properties->CssClip()) {
- scrollbar_layer_state->SetClip(css_clip->Parent());
- }
+ if (const auto* properties = fragment_data.PaintProperties()) {
+ if (scrollbar_or_corner == ScrollbarOrCorner::kHorizontalScrollbar) {
+ if (const auto* effect = properties->HorizontalScrollbarEffect()) {
+ scrollbar_layer_state.SetEffect(effect);
}
}
- graphics_layer->SetLayerState(
- *scrollbar_layer_state,
- snapped_paint_offset + graphics_layer->OffsetFromLayoutObject());
+
+ if (scrollbar_or_corner == ScrollbarOrCorner::kVerticalScrollbar) {
+ if (const auto* effect = properties->VerticalScrollbarEffect())
+ scrollbar_layer_state.SetEffect(effect);
+ }
}
+ graphics_layer->SetLayerState(
+ scrollbar_layer_state,
+ snapped_paint_offset + graphics_layer->OffsetFromLayoutObject());
};
- SetContainerLayerStateForScrollbars(mapping->LayerForHorizontalScrollbar());
- SetContainerLayerStateForScrollbars(mapping->LayerForVerticalScrollbar());
- SetContainerLayerStateForScrollbars(mapping->LayerForScrollCorner());
+ SetContainerLayerStateForScrollbars(mapping->LayerForHorizontalScrollbar(),
+ ScrollbarOrCorner::kHorizontalScrollbar);
+ SetContainerLayerStateForScrollbars(mapping->LayerForVerticalScrollbar(),
+ ScrollbarOrCorner::kVerticalScrollbar);
+ SetContainerLayerStateForScrollbars(mapping->LayerForScrollCorner(),
+ ScrollbarOrCorner::kScrollbarCorner);
if (mapping->ScrollingContentsLayer()) {
auto paint_offset = snapped_paint_offset;
@@ -120,6 +143,15 @@ void CompositingLayerPropertyUpdater::Update(const LayoutObject& object) {
SetContainerLayerState(mapping->ForegroundLayer());
}
+ auto* main_graphics_layer = mapping->MainGraphicsLayer();
+ if (const auto* contents_layer = main_graphics_layer->ContentsLayer()) {
+ auto position = contents_layer->position();
+ main_graphics_layer->SetContentsLayerState(
+ fragment_data.ContentsProperties(),
+ snapped_paint_offset + main_graphics_layer->OffsetFromLayoutObject() +
+ IntSize(position.x(), position.y()));
+ }
+
if (auto* squashing_layer = mapping->SquashingLayer()) {
auto state = fragment_data.PreEffectProperties();
// The squashing layer's ClippingContainer is the common ancestor of clip
@@ -130,7 +162,7 @@ void CompositingLayerPropertyUpdater::Update(const LayoutObject& object) {
state.SetClip(
clipping_container
? clipping_container->FirstFragment().ContentsProperties().Clip()
- : ClipPaintPropertyNode::Root());
+ : &ClipPaintPropertyNode::Root());
squashing_layer->SetLayerState(
state,
snapped_paint_offset + mapping->SquashingLayerOffsetFromLayoutObject());
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater_test.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater_test.cc
index a00370c98bb..3e99fbd948a 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater_test.cc
@@ -2,11 +2,15 @@
// 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/compositing/compositing_layer_property_updater.h"
+
+#include "cc/layers/picture_layer.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
-#include "third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.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"
+#include "third_party/blink/renderer/core/testing/use_mock_scrollbar_settings.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
namespace blink {
@@ -41,4 +45,68 @@ TEST_F(CompositingLayerPropertyUpdaterTest, MaskLayerState) {
mask_layer->layer_state_->state.Clip());
}
+TEST_F(CompositingLayerPropertyUpdaterTest,
+ EnsureOverlayScrollbarLayerHasEffectNode) {
+ GetDocument().GetFrame()->GetSettings()->SetPreferCompositingToLCDTextEnabled(
+ true);
+ UseMockScrollbarSettings mock_scrollbar(false, true);
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #scroller {
+ width: 100px;
+ height: 100px;
+ overflow: scroll;
+ }
+ #big {
+ width: 200px;
+ height: 200px;
+ }
+ </style>
+ <div id='scroller'>
+ <div id='big'></div>
+ </div>
+ )HTML");
+
+ ASSERT_TRUE(
+ GetDocument().GetPage()->GetScrollbarTheme().UsesOverlayScrollbars());
+
+ PaintLayer* scroller_layer =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("scroller"))->Layer();
+ PaintLayerScrollableArea* scrollable_area =
+ scroller_layer->GetScrollableArea();
+ ASSERT_TRUE(scrollable_area);
+
+ auto* horizontal_scrollbar_layer =
+ scrollable_area->LayerForHorizontalScrollbar();
+ auto* vertical_scrollbar_layer = scrollable_area->LayerForVerticalScrollbar();
+ ASSERT_TRUE(horizontal_scrollbar_layer);
+ ASSERT_TRUE(vertical_scrollbar_layer);
+
+ auto* paint_properties =
+ scroller_layer->GetLayoutObject().FirstFragment().PaintProperties();
+
+ // Ensure each overlay scrollbar has its own effect node and effect node has
+ // correct element_id.
+ EXPECT_EQ(paint_properties->HorizontalScrollbarEffect(),
+ horizontal_scrollbar_layer->GetPropertyTreeState().Effect());
+ EXPECT_EQ(paint_properties->VerticalScrollbarEffect(),
+ vertical_scrollbar_layer->GetPropertyTreeState().Effect());
+ EXPECT_NE(horizontal_scrollbar_layer->GetPropertyTreeState().Effect(),
+ vertical_scrollbar_layer->GetPropertyTreeState().Effect());
+ EXPECT_NE(horizontal_scrollbar_layer->GetPropertyTreeState()
+ .Effect()
+ ->GetCompositorElementId(),
+ vertical_scrollbar_layer->GetPropertyTreeState()
+ .Effect()
+ ->GetCompositorElementId());
+ EXPECT_EQ(horizontal_scrollbar_layer->GetPropertyTreeState()
+ .Effect()
+ ->GetCompositorElementId(),
+ horizontal_scrollbar_layer->ContentsLayer()->element_id());
+ EXPECT_EQ(vertical_scrollbar_layer->GetPropertyTreeState()
+ .Effect()
+ ->GetCompositorElementId(),
+ vertical_scrollbar_layer->ContentsLayer()->element_id());
+}
+
} // namespace blink
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 2a9e0762483..690b49674b0 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
@@ -13,6 +13,7 @@
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/scrolling/root_scroller_util.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/public/platform/platform.h"
@@ -56,7 +57,6 @@ CompositingReasons CompositingReasonFinder::DirectReasons(
NonStyleDeterminedDirectReasons(layer, ignore_lcd_text);
}
-// This information doesn't appear to be incorporated into CompositingReasons.
bool CompositingReasonFinder::RequiresCompositingForScrollableFrame() const {
// Need this done first to determine overflow.
DCHECK(!layout_view_.NeedsLayout());
@@ -66,10 +66,10 @@ bool CompositingReasonFinder::RequiresCompositingForScrollableFrame() const {
if (!(compositing_triggers_ & kScrollableInnerFrameTrigger))
return false;
- if (layout_view_.GetFrameView()->VisibleContentSize().IsEmpty())
+ if (layout_view_.GetFrameView()->Size().IsEmpty())
return false;
- return layout_view_.GetFrameView()->IsScrollable();
+ return layout_view_.GetFrameView()->LayoutViewport()->ScrollsOverflow();
}
CompositingReasons
@@ -132,6 +132,9 @@ CompositingReasonFinder::PotentialCompositingReasonsFromStyle(
if (layout_object.HasReflection())
reasons |= CompositingReason::kReflectionWithCompositedDescendants;
+ if (layout_object.HasClipRelatedProperty())
+ reasons |= CompositingReason::kClipsCompositingDescendants;
+
DCHECK(!(reasons & ~CompositingReason::kComboAllStyleDeterminedReasons));
return reasons;
}
@@ -161,9 +164,6 @@ CompositingReasons CompositingReasonFinder::NonStyleDeterminedDirectReasons(
if (layer->ClipParent() && layer->GetLayoutObject().IsOutOfFlowPositioned())
direct_reasons |= CompositingReason::kOutOfFlowClipping;
- if (layer->NeedsCompositedScrolling())
- direct_reasons |= CompositingReason::kOverflowScrollingTouch;
-
if (RequiresCompositingForRootScroller(*layer))
direct_reasons |= CompositingReason::kRootScroller;
@@ -186,6 +186,19 @@ CompositingReasons CompositingReasonFinder::NonStyleDeterminedDirectReasons(
direct_reasons |= CompositingReason::kScrollTimelineTarget;
}
+ // Video is special. It's the only PaintLayer type that can both have
+ // PaintLayer children and whose children can't use its backing to render
+ // into. These children (the controls) always need to be promoted into their
+ // own layers to draw on top of the accelerated video.
+ if (layer->CompositingContainer() &&
+ layer->CompositingContainer()->GetLayoutObject().IsVideo())
+ direct_reasons |= CompositingReason::kVideoOverlay;
+
+ if (layer->IsRootLayer() && (RequiresCompositingForScrollableFrame() ||
+ layout_view_.GetFrame()->IsLocalRoot())) {
+ direct_reasons |= CompositingReason::kRoot;
+ }
+
direct_reasons |= layout_object.AdditionalCompositingReasons();
DCHECK(
@@ -268,15 +281,13 @@ bool CompositingReasonFinder::RequiresCompositingForScrollDependentPosition(
EPosition position = layer->GetLayoutObject().Style()->GetPosition();
if (position == EPosition::kFixed) {
return layer->FixedToViewport() &&
- layout_view_.GetFrameView()->IsScrollable();
+ layout_view_.GetFrameView()->LayoutViewport()->ScrollsOverflow();
}
DCHECK_EQ(position, EPosition::kSticky);
// Don't promote sticky position elements that cannot move with scrolls.
if (!layer->SticksToScroller())
return false;
- if (layer->AncestorOverflowLayer()->IsRootLayer())
- return layout_view_.GetFrameView()->IsScrollable();
return layer->AncestorOverflowLayer()->ScrollsOverflow();
}
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h
index bca501219a2..0bf467bf6cb 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_reason_finder.h
@@ -26,6 +26,13 @@ class CORE_EXPORT CompositingReasonFinder {
CompositingReasons PotentialCompositingReasonsFromStyle(LayoutObject&) const;
+ CompositingReasons NonStyleDeterminedDirectReasons(
+ const PaintLayer*,
+ bool ignore_lcd_text) const;
+ LayoutView& layout_view_;
+ CompositingTriggerFlags compositing_triggers_;
+ DISALLOW_COPY_AND_ASSIGN(CompositingReasonFinder);
+
// Returns the direct reasons for compositing the given layer. If
// |ignoreLCDText| is true promotion will not try to preserve subpixel text
// rendering (i.e. partially transparent layers will be promoted).
@@ -51,13 +58,6 @@ class CORE_EXPORT CompositingReasonFinder {
private:
bool IsMainFrame() const;
-
- CompositingReasons NonStyleDeterminedDirectReasons(
- const PaintLayer*,
- bool ignore_lcd_text) const;
- LayoutView& layout_view_;
- CompositingTriggerFlags compositing_triggers_;
- DISALLOW_COPY_AND_ASSIGN(CompositingReasonFinder);
};
} // namespace blink
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 563dc66f438..b32df08233c 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
@@ -32,6 +32,16 @@ class CompositingReasonFinderTestPlatform : public TestingPlatformSupport {
bool IsLowEndDevice() override { return true; }
};
+TEST_F(CompositingReasonFinderTest, CompositingReasonDependencies) {
+ EXPECT_FALSE(CompositingReason::kComboAllDirectNonStyleDeterminedReasons &
+ (~CompositingReason::kComboAllDirectReasons));
+ EXPECT_EQ(CompositingReason::kComboAllDirectReasons,
+ CompositingReason::kComboAllDirectStyleDeterminedReasons |
+ CompositingReason::kComboAllDirectNonStyleDeterminedReasons);
+ EXPECT_FALSE(CompositingReason::kComboAllDirectNonStyleDeterminedReasons &
+ CompositingReason::kComboAllStyleDeterminedReasons);
+}
+
TEST_F(CompositingReasonFinderTest, DontPromoteTrivial3DLowEnd) {
ScopedTestingPlatformSupport<CompositingReasonFinderTestPlatform> platform;
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 7de149c1489..f4d972924de 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
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/core/layout/layout_view.h"
#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/paint/paint_layer_stacking_node.h"
#include "third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -148,14 +149,12 @@ class CompositingRequirementsUpdater::RecursionData {
: compositing_ancestor_(compositing_ancestor),
subtree_is_compositing_(false),
has_unisolated_composited_blending_descendant_(false),
- testing_overlap_(true),
- has_composited_scrolling_ancestor_(false) {}
+ testing_overlap_(true) {}
PaintLayer* compositing_ancestor_;
bool subtree_is_compositing_;
bool has_unisolated_composited_blending_descendant_;
bool testing_overlap_;
- bool has_composited_scrolling_ancestor_;
};
static bool RequiresCompositingOrSquashing(CompositingReasons reasons) {
@@ -183,17 +182,10 @@ static CompositingReasons SubtreeReasonsForCompositing(
CompositingReason::kComboCompositedDescendants;
if (layer->ShouldIsolateCompositedDescendants()) {
- DCHECK(layer->StackingNode()->IsStackingContext());
+ DCHECK(layer->GetLayoutObject().StyleRef().IsStackingContext());
subtree_reasons |= CompositingReason::kIsolateCompositedDescendants;
}
- // FIXME: This should move into
- // CompositingReasonFinder::potentialCompositingReasonsFromStyle, but theres
- // a poor interaction with LayoutTextControlSingleLine, which sets this
- // hasOverflowClip directly.
- if (layer->GetLayoutObject().HasClipRelatedProperty())
- subtree_reasons |= CompositingReason::kClipsCompositingDescendants;
-
// We ignore LCD text here because we are required to composite
// scroll-dependant fixed position elements with composited descendants for
// correctness - even if we lose LCD.
@@ -250,28 +242,21 @@ void CompositingRequirementsUpdater::Update(
absolute_descendant_bounding_box, compositing_reasons_stats);
}
-void CompositingRequirementsUpdater::MaybeEnableCompositedScrolling(
- PaintLayer* layer,
- CompositingReasons& reasons) {
- // Add CompositingReasonOverflowScrollingTouch for layers that do not
- // already have it but need it.
- // Note that m_compositingReasonFinder.directReasons(layer) already includes
- // CompositingReasonOverflowScrollingTouch for anything that has
- // layer->needsCompositedScrolling() true. That is, for cases where we
- // explicitly decide not to have LCD text or cases where the layer will
- // still support LCD text even if the layer is composited.
- if (reasons && layer->ScrollsOverflow() &&
- !layer->NeedsCompositedScrolling()) {
- // We can get here for a scroller that will be composited for some other
- // reason and hence will already use grayscale AA text. We recheck for
- // needsCompositedScrolling ignoring LCD to correctly add the
- // CompositingReasonOverflowScrollingTouch reason to layers that can
- // support it with grayscale AA text.
- layer->GetScrollableArea()->UpdateNeedsCompositedScrolling(true);
- if (layer->NeedsCompositedScrolling())
- reasons |= CompositingReason::kOverflowScrollingTouch;
+#if DCHECK_IS_ON()
+static void CheckSubtreeHasNoCompositing(PaintLayer* layer) {
+ if (!layer->StackingNode())
+ return;
+ PaintLayerStackingNodeIterator iterator(
+ *layer->StackingNode(),
+ kNegativeZOrderChildren | kNormalFlowChildren | kPositiveZOrderChildren);
+ while (PaintLayer* cur_layer = iterator.Next()) {
+ DCHECK(cur_layer->GetCompositingState() == kNotComposited);
+ DCHECK(!cur_layer->DirectCompositingReasons() ||
+ !layer->Compositor()->CanBeComposited(cur_layer));
+ CheckSubtreeHasNoCompositing(cur_layer);
}
}
+#endif
void CompositingRequirementsUpdater::UpdateRecursive(
PaintLayer* ancestor_layer,
@@ -284,28 +269,16 @@ void CompositingRequirementsUpdater::UpdateRecursive(
CompositingReasonsStats& compositing_reasons_stats) {
PaintLayerCompositor* compositor = layout_view_.Compositor();
- layer->StackingNode()->UpdateLayerListsIfNeeded();
-
CompositingReasons reasons_to_composite = CompositingReason::kNone;
CompositingReasons direct_reasons = CompositingReason::kNone;
- // Video is special. It's the only PaintLayer type that can both have
- // PaintLayer children and whose children can't use its backing to render
- // into. These children (the controls) always need to be promoted into their
- // own layers to draw on top of the accelerated video.
- if (current_recursion_data.compositing_ancestor_ &&
- current_recursion_data.compositing_ancestor_->GetLayoutObject().IsVideo())
- direct_reasons |= CompositingReason::kVideoOverlay;
-
- bool has_composited_scrolling_ancestor =
+ bool has_non_root_composited_scrolling_ancestor =
layer->AncestorScrollingLayer() &&
- (compositing_reason_finder_.DirectReasons(layer->AncestorScrollingLayer(),
- false) &
- CompositingReason::kOverflowScrollingTouch);
+ layer->AncestorScrollingLayer()->GetScrollableArea() &&
+ layer->AncestorScrollingLayer()->DirectCompositingReasons() &&
+ !layer->AncestorScrollingLayer()->IsRootLayer();
- bool use_clipped_bounding_rect =
- !has_composited_scrolling_ancestor ||
- layer->AncestorScrollingLayer()->IsRootLayer();
+ bool use_clipped_bounding_rect = !has_non_root_composited_scrolling_ancestor;
// We have to promote the sticky element to work around the bug
// (https://crbug.com/698358) of not being able to invalidate the ancestor
@@ -316,38 +289,54 @@ void CompositingRequirementsUpdater::UpdateRecursive(
const bool moves_with_respect_to_compositing_ancestor =
layer->SticksToScroller() &&
!current_recursion_data.compositing_ancestor_->IsRootLayer();
- // TODO(chrishtr): use |hasCompositedScrollingAncestor| instead.
- const bool ignore_lcd_text =
- current_recursion_data.has_composited_scrolling_ancestor_ ||
- moves_with_respect_to_compositing_ancestor;
- direct_reasons |=
- compositing_reason_finder_.DirectReasons(layer, ignore_lcd_text);
+ const bool ignore_lcd_text = has_non_root_composited_scrolling_ancestor;
- bool can_be_composited = compositor->CanBeComposited(layer);
- if (can_be_composited) {
- reasons_to_composite |= direct_reasons;
+ const bool layer_can_be_composited = compositor->CanBeComposited(layer);
- if (layer->IsRootLayer() && compositor->RootShouldAlwaysComposite())
- reasons_to_composite |= CompositingReason::kRoot;
+ CompositingReasons direct_from_paint_layer = 0;
+ if (layer_can_be_composited)
+ direct_from_paint_layer = layer->DirectCompositingReasons();
+
+ if (compositing_reason_finder_.RequiresCompositingForScrollDependentPosition(
+ layer,
+ ignore_lcd_text || moves_with_respect_to_compositing_ancestor)) {
+ direct_from_paint_layer |= CompositingReason::kScrollDependentPosition;
+ }
- MaybeEnableCompositedScrolling(layer, reasons_to_composite);
+#if DCHECK_IS_ON()
+ if (layer_can_be_composited) {
+ DCHECK(direct_from_paint_layer ==
+ compositing_reason_finder_.DirectReasons(
+ layer,
+ ignore_lcd_text || moves_with_respect_to_compositing_ancestor))
+ << " Expected: "
+ << CompositingReason::ToString(
+ compositing_reason_finder_.DirectReasons(layer, ignore_lcd_text))
+ << " Actual: " << CompositingReason::ToString(direct_from_paint_layer);
}
+#endif
- if ((reasons_to_composite & CompositingReason::kOverflowScrollingTouch) &&
- !layer->IsRootLayer())
- current_recursion_data.has_composited_scrolling_ancestor_ = true;
+ direct_reasons |= direct_from_paint_layer;
+
+ if (layer->GetScrollableArea() &&
+ layer->GetScrollableArea()->NeedsCompositedScrolling())
+ direct_reasons |= CompositingReason::kOverflowScrollingTouch;
+
+ bool can_be_composited = compositor->CanBeComposited(layer);
+ if (can_be_composited)
+ reasons_to_composite |= direct_reasons;
// Next, accumulate reasons related to overlap.
// If overlap testing is used, this reason will be overridden. If overlap
// testing is not used, we must assume we overlap if there is anything
// composited behind us in paint-order.
CompositingReasons overlap_compositing_reason =
- current_recursion_data.subtree_is_compositing_
+ (layer_can_be_composited &&
+ current_recursion_data.subtree_is_compositing_)
? CompositingReason::kAssumedOverlap
: CompositingReason::kNone;
- // TODO(chrishtr): use |hasCompositedScrollingAncestor| instead.
- if (current_recursion_data.has_composited_scrolling_ancestor_) {
+ if (has_non_root_composited_scrolling_ancestor) {
Vector<size_t> unclipped_descendants_to_remove;
for (size_t i = 0; i < unclipped_descendants.size(); i++) {
PaintLayer* unclipped_descendant = unclipped_descendants.at(i);
@@ -360,7 +349,8 @@ void CompositingRequirementsUpdater::UpdateRecursive(
unclipped_descendants_to_remove.push_back(i);
continue;
}
- if (layer->ScrollsWithRespectTo(unclipped_descendant))
+ if (layer_can_be_composited &&
+ layer->ScrollsWithRespectTo(unclipped_descendant))
reasons_to_composite |= CompositingReason::kAssumedOverlap;
}
@@ -395,7 +385,7 @@ void CompositingRequirementsUpdater::UpdateRecursive(
}
absolute_descendant_bounding_box = abs_bounds;
- if (current_recursion_data.testing_overlap_ &&
+ if (layer_can_be_composited && current_recursion_data.testing_overlap_ &&
!RequiresCompositingOrSquashing(direct_reasons)) {
bool overlaps =
overlap_map.OverlapsLayers(abs_bounds, use_clipped_bounding_rect);
@@ -428,21 +418,47 @@ void CompositingRequirementsUpdater::UpdateRecursive(
}
#if DCHECK_IS_ON()
- LayerListMutationDetector mutation_checker(layer->StackingNode());
+ base::Optional<LayerListMutationDetector> mutation_checker;
+ if (layer->StackingNode())
+ mutation_checker.emplace(layer->StackingNode());
#endif
bool any_descendant_has3d_transform = false;
bool will_have_foreground_layer = false;
- if (layer->StackingNode()->IsStackingContext()) {
+ bool needs_recursion_for_composited_scrolling_plus_fixed_or_sticky =
+ layer->HasDescendantWithStickyOrFixed() &&
+ (has_non_root_composited_scrolling_ancestor ||
+ (layer->GetScrollableArea() &&
+ layer->GetScrollableArea()->NeedsCompositedScrolling()));
+
+ bool needs_recursion_for_out_of_flow_descendant =
+ layer->HasNonContainedAbsolutePositionDescendant();
+
+ // Skip recursion if there are no descendants which:
+ // * may have their own reason for compositing,
+ // * have compositing already from the previous frame, or
+ // * may escape |layer|'s clip.
+ // * may need compositing requirements update for another reason (
+ // e.g. change of stacking order)
+ bool skip_children =
+ !layer->DescendantHasDirectOrScrollingCompositingReason() &&
+ !needs_recursion_for_composited_scrolling_plus_fixed_or_sticky &&
+ !needs_recursion_for_out_of_flow_descendant &&
+ layer->GetLayoutObject().HasOverflowClip() &&
+ !layer->HasCompositingDescendant() &&
+ !layer->DescendantMayNeedCompositingRequirementsUpdate();
+
+ if (!skip_children &&
+ layer->GetLayoutObject().StyleRef().IsStackingContext()) {
PaintLayerStackingNodeIterator iterator(*layer->StackingNode(),
kNegativeZOrderChildren);
- while (PaintLayerStackingNode* cur_node = iterator.Next()) {
+ while (PaintLayer* child_layer = iterator.Next()) {
IntRect absolute_child_descendant_bounding_box;
- UpdateRecursive(
- layer, cur_node->Layer(), overlap_map, child_recursion_data,
- any_descendant_has3d_transform, unclipped_descendants,
- absolute_child_descendant_bounding_box, compositing_reasons_stats);
+ UpdateRecursive(layer, child_layer, overlap_map, child_recursion_data,
+ any_descendant_has3d_transform, unclipped_descendants,
+ absolute_child_descendant_bounding_box,
+ compositing_reasons_stats);
absolute_descendant_bounding_box.Unite(
absolute_child_descendant_bounding_box);
@@ -463,9 +479,8 @@ void CompositingRequirementsUpdater::UpdateRecursive(
// child: re-compute the absBounds for the child so that we can add
// the negative z-index child's bounds to the new overlap context.
overlap_map.BeginNewOverlapTestingContext();
- overlap_map.Add(cur_node->Layer(),
- cur_node->Layer()->ClippedAbsoluteBoundingBox(),
- true);
+ overlap_map.Add(child_layer,
+ child_layer->ClippedAbsoluteBoundingBox(), true);
overlap_map.FinishCurrentOverlapTestingContext();
}
}
@@ -486,22 +501,29 @@ void CompositingRequirementsUpdater::UpdateRecursive(
child_recursion_data.testing_overlap_ = true;
}
- PaintLayerStackingNodeIterator iterator(
- *layer->StackingNode(), kNormalFlowChildren | kPositiveZOrderChildren);
- while (PaintLayerStackingNode* cur_node = iterator.Next()) {
- IntRect absolute_child_descendant_bounding_box;
- UpdateRecursive(layer, cur_node->Layer(), overlap_map, child_recursion_data,
- any_descendant_has3d_transform, unclipped_descendants,
- absolute_child_descendant_bounding_box,
- compositing_reasons_stats);
- absolute_descendant_bounding_box.Unite(
- absolute_child_descendant_bounding_box);
+ if (!skip_children && layer->StackingNode()) {
+ PaintLayerStackingNodeIterator iterator(
+ *layer->StackingNode(), kNormalFlowChildren | kPositiveZOrderChildren);
+ while (PaintLayer* child_layer = iterator.Next()) {
+ IntRect absolute_child_descendant_bounding_box;
+ UpdateRecursive(layer, child_layer, overlap_map, child_recursion_data,
+ any_descendant_has3d_transform, unclipped_descendants,
+ absolute_child_descendant_bounding_box,
+ compositing_reasons_stats);
+ absolute_descendant_bounding_box.Unite(
+ absolute_child_descendant_bounding_box);
+ }
}
+#if DCHECK_IS_ON()
+ if (skip_children)
+ CheckSubtreeHasNoCompositing(layer);
+#endif
+
// Now that the subtree has been traversed, we can check for compositing
// reasons that depended on the state of the subtree.
- if (layer->StackingNode()->IsStackingContext()) {
+ if (layer->GetLayoutObject().StyleRef().IsStackingContext()) {
layer->SetShouldIsolateCompositedDescendants(
child_recursion_data.has_unisolated_composited_blending_descendant_);
} else {
@@ -534,15 +556,16 @@ void CompositingRequirementsUpdater::UpdateRecursive(
if (child_recursion_data.subtree_is_compositing_ ||
RequiresCompositingOrSquashing(reasons_to_composite) ||
compositor->RootShouldAlwaysComposite()) {
+#if DCHECK_IS_ON()
+ // The reason for compositing should not be due to composited scrolling.
+ // It should only be compositing in order to represent composited content
+ // within a composited subframe.
+ bool was = layer->NeedsCompositedScrolling();
+ layer->GetScrollableArea()->UpdateNeedsCompositedScrolling(true);
+ DCHECK(was == layer->NeedsCompositedScrolling());
+#endif
+
reasons_to_composite |= CompositingReason::kRoot;
- current_recursion_data.subtree_is_compositing_ = true;
- // Try again to enable composited scrolling if root became composited due
- // to subtree_is_compositing_ or overlap.
- // TODO(skobes): At this point we've already done recursion to descendant
- // layers, possibly with has_composited_scrolling_ancestor_ == false.
- // We should refactor overlap testing etc. to be independent of having
- // composited scrolling ancestors. See crbug.com/777672, crbug.com/782991.
- MaybeEnableCompositedScrolling(layer, reasons_to_composite);
} else {
compositor->SetCompositingModeEnabled(false);
reasons_to_composite = CompositingReason::kNone;
@@ -563,7 +586,8 @@ void CompositingRequirementsUpdater::UpdateRecursive(
compositing_reason_finder_, layer,
child_recursion_data.subtree_is_compositing_,
any_descendant_has3d_transform);
- reasons_to_composite |= subtree_compositing_reasons;
+ if (layer_can_be_composited)
+ reasons_to_composite |= subtree_compositing_reasons;
if (!will_be_composited_or_squashed && can_be_composited &&
RequiresCompositingOrSquashing(subtree_compositing_reasons)) {
child_recursion_data.compositing_ancestor_ = layer;
@@ -614,9 +638,16 @@ void CompositingRequirementsUpdater::UpdateRecursive(
any_descendant_has3d_transform || layer->Has3DTransform();
}
+ // Layer assignment is needed for allocating or removing composited
+ // layers related to this PaintLayer; hence the below conditions.
+ if (reasons_to_composite || layer->GetCompositingState() != kNotComposited ||
+ layer->LostGroupedMapping())
+ layer->SetNeedsCompositingLayerAssignment();
+
// At this point we have finished collecting all reasons to composite this
// layer.
layer->SetCompositingReasons(reasons_to_composite);
+ layer->ClearNeedsCompositingRequirementsUpdate();
if (reasons_to_composite & CompositingReason::kOverlap)
compositing_reasons_stats.overlap_layers++;
if (reasons_to_composite & CompositingReason::kComboActiveAnimation)
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.h b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.h
index 289eaf12436..9419f90c76e 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.h
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.h
@@ -71,8 +71,6 @@ class CompositingRequirementsUpdater {
IntRect& absolute_descendant_bounding_box,
CompositingReasonsStats&);
- void MaybeEnableCompositedScrolling(PaintLayer*, CompositingReasons&);
-
LayoutView& layout_view_;
CompositingReasonFinder& compositing_reason_finder_;
};
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc
index 6d6e589a7b4..db1715411de 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater_test.cc
@@ -5,7 +5,9 @@
#include "third_party/blink/renderer/core/paint/compositing/compositing_requirements_updater.h"
#include "testing/gtest/include/gtest/gtest.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"
+#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
namespace blink {
@@ -38,12 +40,140 @@ TEST_F(CompositingRequirementsUpdaterTest, FixedPosOverlap) {
CompositingReason::kOverlap | CompositingReason::kSquashingDisallowed,
fixed->Layer()->GetCompositingReasons());
- GetDocument().View()->LayoutViewportScrollableArea()->ScrollBy(
- ScrollOffset(0, 100), kUserScroll);
+ GetDocument().View()->LayoutViewport()->ScrollBy(ScrollOffset(0, 100),
+ kUserScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
// No longer overlaps the first div.
EXPECT_EQ(CompositingReason::kNone, fixed->Layer()->GetCompositingReasons());
}
+TEST_F(CompositingRequirementsUpdaterTest,
+ NoOverlapReasonForNonSelfPaintingLayer) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #target {
+ overflow: auto;
+ width: 100px;
+ height: 100px;
+ margin-top: -50px;
+ }
+ </style>
+ <div style="position: relative; width: 500px; height: 300px;
+ will-change: transform"></div>
+ <div id=target></div>
+ )HTML");
+
+ PaintLayer* target =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer();
+ EXPECT_FALSE(target->GetCompositingReasons());
+
+ // Now make |target| self-painting.
+ GetDocument().getElementById("target")->setAttribute(HTMLNames::styleAttr,
+ "position: relative");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ EXPECT_EQ(CompositingReason::kOverlap, target->GetCompositingReasons());
+}
+
+TEST_F(CompositingRequirementsUpdaterTest,
+ NoAssumedOverlapReasonForNonSelfPaintingLayer) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #target {
+ overflow: auto;
+ width: 100px;
+ height: 100px;
+ }
+ </style>
+ <div style="position: relative; width: 500px; height: 300px;
+ transform: translateZ(0)"></div>
+ <div id=target></div>
+ )HTML");
+
+ PaintLayer* target =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer();
+ EXPECT_FALSE(target->GetCompositingReasons());
+
+ // Now make |target| self-painting.
+ GetDocument().getElementById("target")->setAttribute(HTMLNames::styleAttr,
+ "position: relative");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ EXPECT_EQ(CompositingReason::kAssumedOverlap,
+ target->GetCompositingReasons());
+}
+
+TEST_F(CompositingRequirementsUpdaterTest,
+ NoDescendantReasonForNonSelfPaintingLayer) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #target {
+ overflow: auto;
+ width: 100px;
+ height: 100px;
+ }
+ </style>
+ <div id=target>
+ <div style="backface-visibility: hidden"></div>
+ </div>
+ )HTML");
+
+ PaintLayer* target =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer();
+ EXPECT_FALSE(target->GetCompositingReasons());
+
+ // Now make |target| self-painting.
+ GetDocument().getElementById("target")->setAttribute(HTMLNames::styleAttr,
+ "position: relative");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ EXPECT_EQ(CompositingReason::kClipsCompositingDescendants,
+ target->GetCompositingReasons());
+}
+
+// This test sets up a situation where a squashed PaintLayer loses its
+// backing, but does not change visual rect. Therefore the compositing system
+// must invalidate it because of change of backing.
+TEST_F(CompositingRequirementsUpdaterTest,
+ NeedsLayerAssignmentAfterSquashingRemoval) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ * {
+ margin: 0
+ }
+ #target {
+ width: 100px; height: 100px; backface-visibility: hidden
+ }
+ div {
+ width: 100px; height: 100px;
+ position: absolute;
+ background: lightblue;
+ top: 0px;
+ }
+ </style>
+ <div id=target></div>
+ <div id=squashed></div>
+ )HTML");
+
+ PaintLayer* squashed =
+ ToLayoutBoxModelObject(GetLayoutObjectByElementId("squashed"))->Layer();
+ EXPECT_EQ(kPaintsIntoGroupedBacking, squashed->GetCompositingState());
+
+ GetDocument().View()->SetTracksPaintInvalidations(true);
+
+ GetDocument().getElementById("target")->setAttribute(HTMLNames::styleAttr,
+ "display: none");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ EXPECT_EQ(kNotComposited, squashed->GetCompositingState());
+ auto* tracking = GetDocument()
+ .View()
+ ->GetLayoutView()
+ ->Layer()
+ ->GraphicsLayerBacking()
+ ->GetRasterInvalidationTracking();
+ EXPECT_TRUE(tracking->HasInvalidations());
+
+ EXPECT_EQ(IntRect(0, 0, 100, 100), tracking->Invalidations()[0].rect);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc b/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc
new file mode 100644
index 00000000000..ee6e7881dd5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.cc
@@ -0,0 +1,378 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.h"
+
+#include "third_party/blink/renderer/platform/geometry/geometry_as_json.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
+#include "third_party/blink/renderer/platform/graphics/logging_canvas.h"
+#include "third_party/blink/renderer/platform/json/json_values.h"
+#include "third_party/blink/renderer/platform/scroll/scrollable_area.h"
+#include "third_party/blink/renderer/platform/wtf/text/text_stream.h"
+
+namespace blink {
+
+namespace {
+
+typedef HashMap<int, int> RenderingContextMap;
+
+String PointerAsString(const void* ptr) {
+ WTF::TextStream ts;
+ ts << ptr;
+ return ts.Release();
+}
+
+FloatPoint ScrollPosition(const GraphicsLayer& layer) {
+ if (const auto* scrollable_area =
+ layer.Client().GetScrollableAreaForTesting(&layer)) {
+ return scrollable_area->ScrollPosition();
+ }
+ return FloatPoint();
+}
+
+void AddFlattenInheritedTransformJSON(const GraphicsLayer* layer,
+ JSONObject& json) {
+ if (layer->Parent() && !layer->Parent()->ShouldFlattenTransform())
+ json.SetBoolean("flattenInheritedTransform", false);
+}
+
+void AddTransformJSONProperties(const GraphicsLayer* layer,
+ JSONObject& json,
+ RenderingContextMap& rendering_context_map) {
+ const TransformationMatrix& transform = layer->Transform();
+ if (!transform.IsIdentity())
+ json.SetArray("transform", TransformAsJSONArray(transform));
+
+ if (!transform.IsIdentityOrTranslation())
+ json.SetArray("origin", PointAsJSONArray(layer->TransformOrigin()));
+
+ AddFlattenInheritedTransformJSON(layer, json);
+
+ if (int rendering_context3d = layer->GetRenderingContext3D()) {
+ auto it = rendering_context_map.find(rendering_context3d);
+ int context_id = rendering_context_map.size() + 1;
+ if (it == rendering_context_map.end())
+ rendering_context_map.Set(rendering_context3d, context_id);
+ else
+ context_id = it->value;
+
+ json.SetInteger("renderingContext", context_id);
+ }
+}
+
+std::unique_ptr<JSONObject> GraphicsLayerAsJSON(
+ const GraphicsLayer* layer,
+ LayerTreeFlags flags,
+ RenderingContextMap& rendering_context_map,
+ const FloatPoint& position) {
+ std::unique_ptr<JSONObject> json = JSONObject::Create();
+
+ if (flags & kLayerTreeIncludesDebugInfo)
+ json->SetString("this", PointerAsString(layer));
+
+ json->SetString("name", layer->DebugName());
+
+ if (position != FloatPoint())
+ json->SetArray("position", PointAsJSONArray(position));
+
+ if (flags & kLayerTreeIncludesDebugInfo &&
+ layer->OffsetFromLayoutObject() != IntSize()) {
+ json->SetArray("offsetFromLayoutObject",
+ SizeAsJSONArray(layer->OffsetFromLayoutObject()));
+ }
+
+ if (layer->Size() != IntSize())
+ json->SetArray("bounds", SizeAsJSONArray(layer->Size()));
+
+ if (layer->Opacity() != 1)
+ json->SetDouble("opacity", layer->Opacity());
+
+ if (layer->GetBlendMode() != BlendMode::kNormal) {
+ json->SetString("blendMode", CompositeOperatorName(kCompositeSourceOver,
+ layer->GetBlendMode()));
+ }
+
+ if (layer->IsRootForIsolatedGroup())
+ json->SetBoolean("isolate", true);
+
+ if (layer->ContentsOpaque())
+ json->SetBoolean("contentsOpaque", true);
+
+ if (!layer->DrawsContent())
+ json->SetBoolean("drawsContent", false);
+
+ if (!layer->ContentsAreVisible())
+ json->SetBoolean("contentsVisible", false);
+
+ if (!layer->BackfaceVisibility())
+ json->SetString("backfaceVisibility", "hidden");
+
+ if (flags & kLayerTreeIncludesDebugInfo)
+ json->SetString("client", PointerAsString(&layer->Client()));
+
+ if (layer->BackgroundColor().Alpha()) {
+ json->SetString("backgroundColor",
+ layer->BackgroundColor().NameForLayoutTreeAsText());
+ }
+
+ if (flags & kOutputAsLayerTree) {
+ AddTransformJSONProperties(layer, *json, rendering_context_map);
+ if (!layer->ShouldFlattenTransform())
+ json->SetBoolean("shouldFlattenTransform", false);
+ FloatPoint scroll_position(ScrollPosition(*layer));
+ if (scroll_position != FloatPoint())
+ json->SetArray("scrollPosition", PointAsJSONArray(scroll_position));
+ }
+
+ if ((flags & kLayerTreeIncludesPaintInvalidations) &&
+ layer->Client().IsTrackingRasterInvalidations() &&
+ layer->GetRasterInvalidationTracking()) {
+ layer->GetRasterInvalidationTracking()->AsJSON(json.get());
+ }
+
+ GraphicsLayerPaintingPhase painting_phase = layer->PaintingPhase();
+ if ((flags & kLayerTreeIncludesPaintingPhases) && painting_phase) {
+ std::unique_ptr<JSONArray> painting_phases_json = JSONArray::Create();
+ if (painting_phase & kGraphicsLayerPaintBackground)
+ painting_phases_json->PushString("GraphicsLayerPaintBackground");
+ if (painting_phase & kGraphicsLayerPaintForeground)
+ painting_phases_json->PushString("GraphicsLayerPaintForeground");
+ if (painting_phase & kGraphicsLayerPaintMask)
+ painting_phases_json->PushString("GraphicsLayerPaintMask");
+ if (painting_phase & kGraphicsLayerPaintChildClippingMask)
+ painting_phases_json->PushString("GraphicsLayerPaintChildClippingMask");
+ if (painting_phase & kGraphicsLayerPaintAncestorClippingMask) {
+ painting_phases_json->PushString(
+ "GraphicsLayerPaintAncestorClippingMask");
+ }
+ if (painting_phase & kGraphicsLayerPaintOverflowContents)
+ painting_phases_json->PushString("GraphicsLayerPaintOverflowContents");
+ if (painting_phase & kGraphicsLayerPaintCompositedScroll)
+ painting_phases_json->PushString("GraphicsLayerPaintCompositedScroll");
+ if (painting_phase & kGraphicsLayerPaintDecoration)
+ painting_phases_json->PushString("GraphicsLayerPaintDecoration");
+ json->SetArray("paintingPhases", std::move(painting_phases_json));
+ }
+
+ if (flags & kLayerTreeIncludesClipAndScrollParents) {
+ if (layer->HasScrollParent())
+ json->SetBoolean("hasScrollParent", true);
+ if (layer->HasClipParent())
+ json->SetBoolean("hasClipParent", true);
+ }
+
+ if (flags &
+ (kLayerTreeIncludesDebugInfo | kLayerTreeIncludesCompositingReasons)) {
+ bool debug = flags & kLayerTreeIncludesDebugInfo;
+ {
+ std::unique_ptr<JSONArray> compositing_reasons_json = JSONArray::Create();
+ CompositingReasons compositing_reasons = layer->GetCompositingReasons();
+ auto names = debug ? CompositingReason::Descriptions(compositing_reasons)
+ : CompositingReason::ShortNames(compositing_reasons);
+ for (const char* name : names)
+ compositing_reasons_json->PushString(name);
+ json->SetArray("compositingReasons", std::move(compositing_reasons_json));
+ }
+ {
+ std::unique_ptr<JSONArray> squashing_disallowed_reasons_json =
+ JSONArray::Create();
+ SquashingDisallowedReasons squashing_disallowed_reasons =
+ layer->GetSquashingDisallowedReasons();
+ auto names = debug ? SquashingDisallowedReason::Descriptions(
+ squashing_disallowed_reasons)
+ : SquashingDisallowedReason::ShortNames(
+ squashing_disallowed_reasons);
+ for (const char* name : names)
+ squashing_disallowed_reasons_json->PushString(name);
+ json->SetArray("squashingDisallowedReasons",
+ std::move(squashing_disallowed_reasons_json));
+ }
+ }
+
+ if (layer->MaskLayer()) {
+ std::unique_ptr<JSONArray> mask_layer_json = JSONArray::Create();
+ mask_layer_json->PushObject(
+ GraphicsLayerAsJSON(layer->MaskLayer(), flags, rendering_context_map,
+ layer->MaskLayer()->GetPosition()));
+ json->SetArray("maskLayer", std::move(mask_layer_json));
+ }
+
+ if (layer->ContentsClippingMaskLayer()) {
+ std::unique_ptr<JSONArray> contents_clipping_mask_layer_json =
+ JSONArray::Create();
+ contents_clipping_mask_layer_json->PushObject(GraphicsLayerAsJSON(
+ layer->ContentsClippingMaskLayer(), flags, rendering_context_map,
+ layer->ContentsClippingMaskLayer()->GetPosition()));
+ json->SetArray("contentsClippingMaskLayer",
+ std::move(contents_clipping_mask_layer_json));
+ }
+
+ if (layer->HasLayerState() && (flags & (kLayerTreeIncludesDebugInfo |
+ kLayerTreeIncludesPaintRecords))) {
+ json->SetString("layerState", layer->GetPropertyTreeState().ToString());
+ json->SetValue("layerOffset",
+ PointAsJSONArray(layer->GetOffsetFromTransformNode()));
+ }
+
+#if DCHECK_IS_ON()
+ if (layer->DrawsContent() && (flags & kLayerTreeIncludesPaintRecords))
+ json->SetValue("paintRecord", RecordAsJSON(*layer->CapturePaintRecord()));
+#endif
+
+ return json;
+}
+
+class LayersAsJSONArray {
+ public:
+ LayersAsJSONArray(LayerTreeFlags flags)
+ : flags_(flags),
+ next_transform_id_(1),
+ layers_json_(JSONArray::Create()),
+ transforms_json_(JSONArray::Create()) {}
+
+ // Outputs the layer tree rooted at |layer| as a JSON array, in paint order,
+ // and the transform tree also as a JSON array.
+ std::unique_ptr<JSONObject> operator()(const GraphicsLayer& layer) {
+ auto json = JSONObject::Create();
+ Walk(layer, 0, FloatPoint());
+ json->SetArray("layers", std::move(layers_json_));
+ if (transforms_json_->size())
+ json->SetArray("transforms", std::move(transforms_json_));
+ return json;
+ }
+
+ JSONObject* AddTransformJSON(int& transform_id) {
+ auto transform_json = JSONObject::Create();
+ int parent_transform_id = transform_id;
+ transform_id = next_transform_id_++;
+ transform_json->SetInteger("id", transform_id);
+ if (parent_transform_id)
+ transform_json->SetInteger("parent", parent_transform_id);
+ auto* result = transform_json.get();
+ transforms_json_->PushObject(std::move(transform_json));
+ return result;
+ }
+
+ void AddLayer(const GraphicsLayer& layer,
+ int& transform_id,
+ FloatPoint& position) {
+ FloatPoint scroll_position = ScrollPosition(layer);
+ if (scroll_position != FloatPoint()) {
+ // Output scroll position as a transform.
+ auto* scroll_translate_json = AddTransformJSON(transform_id);
+ scroll_translate_json->SetArray(
+ "transform", TransformAsJSONArray(TransformationMatrix().Translate(
+ -scroll_position.X(), -scroll_position.Y())));
+ AddFlattenInheritedTransformJSON(&layer, *scroll_translate_json);
+ }
+
+ if (!layer.Transform().IsIdentity() || layer.GetRenderingContext3D() ||
+ layer.GetCompositingReasons() & CompositingReason::k3DTransform) {
+ if (position != FloatPoint()) {
+ // Output position offset as a transform.
+ auto* position_translate_json = AddTransformJSON(transform_id);
+ position_translate_json->SetArray(
+ "transform", TransformAsJSONArray(TransformationMatrix().Translate(
+ position.X(), position.Y())));
+ AddFlattenInheritedTransformJSON(&layer, *position_translate_json);
+ if (layer.Parent() && !layer.Parent()->ShouldFlattenTransform()) {
+ position_translate_json->SetBoolean("flattenInheritedTransform",
+ false);
+ }
+ position = FloatPoint();
+ }
+
+ if (!layer.Transform().IsIdentity() || layer.GetRenderingContext3D()) {
+ auto* transform_json = AddTransformJSON(transform_id);
+ AddTransformJSONProperties(&layer, *transform_json,
+ rendering_context_map_);
+ }
+ }
+
+ auto json =
+ GraphicsLayerAsJSON(&layer, flags_, rendering_context_map_, position);
+ if (transform_id)
+ json->SetInteger("transform", transform_id);
+ layers_json_->PushObject(std::move(json));
+ }
+
+ void Walk(const GraphicsLayer& layer,
+ int parent_transform_id,
+ const FloatPoint& parent_position) {
+ FloatPoint position = parent_position + layer.GetPosition();
+ int transform_id = parent_transform_id;
+ AddLayer(layer, transform_id, position);
+ for (auto* const child : layer.Children())
+ Walk(*child, transform_id, position);
+ }
+
+ private:
+ LayerTreeFlags flags_;
+ int next_transform_id_;
+ RenderingContextMap rendering_context_map_;
+ std::unique_ptr<JSONArray> layers_json_;
+ std::unique_ptr<JSONArray> transforms_json_;
+};
+
+// This is the SPv1 version of ContentLayerClientImpl::LayerAsJSON().
+std::unique_ptr<JSONObject> GraphicsLayerTreeAsJSON(
+ const GraphicsLayer* layer,
+ LayerTreeFlags flags,
+ RenderingContextMap& rendering_context_map) {
+ std::unique_ptr<JSONObject> json = GraphicsLayerAsJSON(
+ layer, flags, rendering_context_map, layer->GetPosition());
+
+ if (layer->Children().size()) {
+ std::unique_ptr<JSONArray> children_json = JSONArray::Create();
+ for (size_t i = 0; i < layer->Children().size(); i++) {
+ children_json->PushObject(GraphicsLayerTreeAsJSON(
+ layer->Children()[i], flags, rendering_context_map));
+ }
+ json->SetArray("children", std::move(children_json));
+ }
+
+ return json;
+}
+
+} // namespace
+
+std::unique_ptr<JSONObject> GraphicsLayerTreeAsJSON(const GraphicsLayer* layer,
+ LayerTreeFlags flags) {
+ if (flags & kOutputAsLayerTree) {
+ RenderingContextMap rendering_context_map;
+ return GraphicsLayerTreeAsJSON(layer, flags, rendering_context_map);
+ }
+
+ return LayersAsJSONArray(flags)(*layer);
+}
+
+String GraphicsLayerTreeAsTextForTesting(const GraphicsLayer* layer,
+ LayerTreeFlags flags) {
+ return GraphicsLayerTreeAsJSON(layer, flags)->ToPrettyJSONString();
+}
+
+} // namespace blink
+
+#if DCHECK_IS_ON()
+void showGraphicsLayerTree(const blink::GraphicsLayer* layer) {
+ if (!layer) {
+ LOG(ERROR) << "Cannot showGraphicsLayerTree for (nil).";
+ return;
+ }
+
+ String output = blink::GraphicsLayerTreeAsTextForTesting(layer, 0xffffffff);
+ LOG(ERROR) << output.Utf8().data();
+}
+
+void showGraphicsLayers(const blink::GraphicsLayer* layer) {
+ if (!layer) {
+ LOG(ERROR) << "Cannot showGraphicsLayers for (nil).";
+ return;
+ }
+
+ String output = blink::GraphicsLayerTreeAsTextForTesting(
+ layer, 0xffffffff & ~blink::kOutputAsLayerTree);
+ LOG(ERROR) << output.Utf8().data();
+}
+#endif
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.h b/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.h
new file mode 100644
index 00000000000..ac28082114d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.h
@@ -0,0 +1,32 @@
+// 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_PAINT_COMPOSITING_GRAPHICS_LAYER_TREE_AS_TEXT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_COMPOSITING_GRAPHICS_LAYER_TREE_AS_TEXT_H_
+
+#include <memory>
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_layer_client.h"
+
+namespace blink {
+
+class GraphicsLayer;
+class JSONObject;
+
+std::unique_ptr<JSONObject> GraphicsLayerTreeAsJSON(const GraphicsLayer*,
+ LayerTreeFlags);
+
+String CORE_EXPORT GraphicsLayerTreeAsTextForTesting(const GraphicsLayer*,
+ LayerTreeFlags);
+
+} // namespace blink
+
+#if DCHECK_IS_ON()
+// Outside the blink namespace for ease of invocation from gdb.
+void CORE_EXPORT showGraphicsLayerTree(const blink::GraphicsLayer*);
+void CORE_EXPORT showGraphicsLayers(const blink::GraphicsLayer*);
+#endif
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_COMPOSITING_GRAPHICS_LAYER_TREE_AS_TEXT_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_builder.cc b/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_builder.cc
index 61ec93bebb7..bd00dbd583d 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_builder.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_builder.cc
@@ -51,13 +51,23 @@ static bool ShouldAppendLayer(const PaintLayer& layer) {
void GraphicsLayerTreeBuilder::Rebuild(PaintLayer& layer,
GraphicsLayerVector& child_layers) {
+ PendingOverflowControlReparents ignored;
+ RebuildRecursive(layer, child_layers, ignored);
+}
+
+using PendingPair = std::pair<const PaintLayer*, size_t>;
+
+void GraphicsLayerTreeBuilder::RebuildRecursive(
+ PaintLayer& layer,
+ GraphicsLayerVector& child_layers,
+ PendingOverflowControlReparents& pending_reparents) {
+ const ComputedStyle& style = layer.GetLayoutObject().StyleRef();
+
// Make the layer compositing if necessary, and set up clipping and content
// layers. Note that we can only do work here that is independent of whether
// the descendant layers have been processed. computeCompositingRequirements()
// will already have done the paint invalidation if necessary.
- layer.StackingNode()->UpdateLayerListsIfNeeded();
-
const bool has_composited_layer_mapping = layer.HasCompositedLayerMapping();
CompositedLayerMapping* current_composited_layer_mapping =
layer.GetCompositedLayerMapping();
@@ -69,15 +79,24 @@ void GraphicsLayerTreeBuilder::Rebuild(PaintLayer& layer,
GraphicsLayerVector* layer_vector_for_children =
has_composited_layer_mapping ? &this_layer_children : &child_layers;
+ PendingOverflowControlReparents this_pending_reparents_children;
+ PendingOverflowControlReparents* pending_reparents_for_children =
+ has_composited_layer_mapping ? &this_pending_reparents_children
+ : &pending_reparents;
+
#if DCHECK_IS_ON()
- LayerListMutationDetector mutation_checker(layer.StackingNode());
+ base::Optional<LayerListMutationDetector> mutation_checker;
+ if (layer.StackingNode())
+ mutation_checker.emplace(layer.StackingNode());
#endif
- if (layer.StackingNode()->IsStackingContext()) {
+ if (style.IsStackingContext()) {
PaintLayerStackingNodeIterator iterator(*layer.StackingNode(),
kNegativeZOrderChildren);
- while (PaintLayerStackingNode* cur_node = iterator.Next())
- Rebuild(*cur_node->Layer(), *layer_vector_for_children);
+ while (PaintLayer* child_layer = iterator.Next()) {
+ RebuildRecursive(*child_layer, *layer_vector_for_children,
+ *pending_reparents_for_children);
+ }
// If a negative z-order child is compositing, we get a foreground layer
// which needs to get parented.
@@ -88,10 +107,14 @@ void GraphicsLayerTreeBuilder::Rebuild(PaintLayer& layer,
}
}
- PaintLayerStackingNodeIterator iterator(
- *layer.StackingNode(), kNormalFlowChildren | kPositiveZOrderChildren);
- while (PaintLayerStackingNode* cur_node = iterator.Next())
- Rebuild(*cur_node->Layer(), *layer_vector_for_children);
+ if (layer.StackingNode()) {
+ PaintLayerStackingNodeIterator iterator(
+ *layer.StackingNode(), kNormalFlowChildren | kPositiveZOrderChildren);
+ while (PaintLayer* child_layer = iterator.Next()) {
+ RebuildRecursive(*child_layer, *layer_vector_for_children,
+ *pending_reparents_for_children);
+ }
+ }
if (has_composited_layer_mapping) {
bool parented = false;
@@ -100,6 +123,28 @@ void GraphicsLayerTreeBuilder::Rebuild(PaintLayer& layer,
ToLayoutEmbeddedContent(layer.GetLayoutObject()));
}
+ // Apply all pending reparents by inserting the overflow controls
+ // root layers into |this_layer_children|. To do this, first sort
+ // them by index. Then insert them one-by-one into the array,
+ // incrementing |offset| by one each time to account for previous
+ // insertions.
+ size_t offset = 0;
+ Vector<PendingPair> pending;
+ for (auto& item : *pending_reparents_for_children)
+ pending.push_back(std::make_pair(item.key, item.value));
+ pending_reparents_for_children->clear();
+
+ std::sort(pending.begin(), pending.end(),
+ [](const PendingPair& a, const PendingPair& b) {
+ return a.second < b.second;
+ });
+ for (auto& item : pending) {
+ this_layer_children.insert(item.second + offset,
+ item.first->GetCompositedLayerMapping()
+ ->DetachLayerForOverflowControls());
+ offset++;
+ }
+
if (!parented)
current_composited_layer_mapping->SetSublayers(this_layer_children);
@@ -109,17 +154,23 @@ void GraphicsLayerTreeBuilder::Rebuild(PaintLayer& layer,
}
}
- if (layer.ScrollParent() &&
- layer.ScrollParent()->HasCompositedLayerMapping() &&
- layer.ScrollParent()
- ->GetCompositedLayerMapping()
- ->NeedsToReparentOverflowControls() &&
- layer.ScrollParent()->GetScrollableArea()->TopmostScrollChild() ==
- &layer) {
- child_layers.push_back(layer.ScrollParent()
- ->GetCompositedLayerMapping()
- ->DetachLayerForOverflowControls());
- }
+ // Also insert for self, to handle the case of scrollers with negative
+ // z-index children (the scrolbars should still paint on top of the
+ // scroller itself).
+ if (style.IsStacked() && has_composited_layer_mapping &&
+ layer.GetCompositedLayerMapping()->NeedsToReparentOverflowControls())
+ pending_reparents.Set(&layer, child_layers.size());
+
+ // Set or overwrite the entry in |pending_reparents| for this scroller.
+ // Overlay controls need to paint on top of all content under the
+ // scroller, so keep overwriting if we find a PaintLayer that is
+ // later in paint order.
+ const PaintLayer* scroll_parent = layer.ScrollParent();
+ if (style.IsStacked() && scroll_parent &&
+ scroll_parent->HasCompositedLayerMapping() &&
+ scroll_parent->GetCompositedLayerMapping()
+ ->NeedsToReparentOverflowControls())
+ pending_reparents.Set(layer.ScrollParent(), child_layers.size());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_builder.h b/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_builder.h
index 4ac85fb3d08..944933c0a1e 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_builder.h
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_builder.h
@@ -42,6 +42,16 @@ class GraphicsLayerTreeBuilder {
~GraphicsLayerTreeBuilder();
void Rebuild(PaintLayer&, GraphicsLayerVector&);
+
+ private:
+ // Maps from PaintLayer::ScrollParent to index into |child_layers| (see below
+ // for child_layers parameter) at which to insert the overflow controls
+ // graphics layers for ScrollParent when reparenting them.
+ using PendingOverflowControlReparents = HashMap<const PaintLayer*, size_t>;
+
+ void RebuildRecursive(PaintLayer&,
+ GraphicsLayerVector& child_layers,
+ PendingOverflowControlReparents& pending_reparents);
};
} // namespace blink
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 0a5827be12b..2479cadb9b3 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
@@ -32,6 +32,7 @@
#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.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
namespace blink {
@@ -49,14 +50,15 @@ class GraphicsLayerUpdater::UpdateContext {
if (compositing_state != kNotComposited &&
compositing_state != kPaintsIntoGroupedBacking) {
compositing_ancestor_ = &layer;
- if (layer.StackingNode()->IsStackingContext())
+ if (layer.GetLayoutObject().StyleRef().IsStackingContext())
compositing_stacking_context_ = &layer;
}
}
const PaintLayer* CompositingContainer(const PaintLayer& layer) const {
const PaintLayer* compositing_container;
- if (layer.StackingNode()->IsStacked()) {
+ if (layer.GetLayoutObject().StyleRef().IsStacked() &&
+ !layer.IsReplacedNormalFlowStacking()) {
compositing_container = compositing_stacking_context_;
} else if ((layer.Parent() &&
!layer.Parent()->GetLayoutObject().IsLayoutBlock()) ||
diff --git a/chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc b/chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc
index 79e2b648d97..e50a69a5f2e 100644
--- a/chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc
+++ b/chromium/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc
@@ -53,6 +53,7 @@
#include "third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_builder.h"
#include "third_party/blink/renderer/core/paint/compositing/graphics_layer_updater.h"
#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
@@ -103,10 +104,6 @@ void PaintLayerCompositor::SetCompositingModeEnabled(bool enable) {
else
DestroyRootLayer();
- LocalFrameView* view = layout_view_.GetFrameView();
- view->SetUsesCompositedScrolling(
- view->GetFrame().GetSettings()->GetPreferCompositingToLCDTextEnabled());
-
// Schedule an update in the parent frame so the <iframe>'s layer in the owner
// document matches the compositing state here.
if (HTMLFrameOwnerElement* owner_element =
@@ -272,8 +269,10 @@ void PaintLayerCompositor::UpdateIfNeededRecursiveInternal(
->UpdateCompositorScrollAnimations();
if (const LocalFrameView::ScrollableAreaSet* animating_scrollable_areas =
layout_view_.GetFrameView()->AnimatingScrollableAreas()) {
- for (ScrollableArea* scrollable_area : *animating_scrollable_areas)
+ for (PaintLayerScrollableArea* scrollable_area :
+ *animating_scrollable_areas) {
scrollable_area->UpdateCompositorScrollAnimations();
+ }
}
}
@@ -347,7 +346,7 @@ void PaintLayerCompositor::ApplyOverlayFullscreenVideoAdjustmentIfNeeded() {
// scroll position because fullscreen container is fixed-positioned.
// We should reset layer position here since we are going to reattach the
// layer at the very top level.
- video_layer->SetPosition(IntPoint());
+ video_layer->SetPosition(FloatPoint());
// Only steal fullscreen video layer and clear all other layers if we are the
// main frame.
@@ -365,7 +364,7 @@ void PaintLayerCompositor::UpdateWithoutAcceleratedCompositing(
DCHECK(!HasAcceleratedCompositing());
if (update_type >= kCompositingUpdateAfterCompositingInputChange)
- CompositingInputsUpdater(RootLayer()).Update();
+ CompositingInputsUpdater(RootLayer(), compositing_reason_finder_).Update();
#if DCHECK_IS_ON()
CompositingInputsUpdater::AssertNeedsCompositingInputsUpdateBitsCleared(
@@ -441,7 +440,7 @@ void PaintLayerCompositor::UpdateIfNeeded(
Vector<PaintLayer*> layers_needing_paint_invalidation;
if (update_type >= kCompositingUpdateAfterCompositingInputChange) {
- CompositingInputsUpdater(update_root).Update();
+ CompositingInputsUpdater(update_root, compositing_reason_finder_).Update();
#if DCHECK_IS_ON()
// FIXME: Move this check to the end of the compositing update.
@@ -465,21 +464,17 @@ void PaintLayerCompositor::UpdateIfNeeded(
CompositingLayerAssigner layer_assigner(this);
layer_assigner.Assign(update_root, layers_needing_paint_invalidation);
- bool layers_changed = layer_assigner.LayersChanged();
-
{
TRACE_EVENT0("blink",
"PaintLayerCompositor::updateAfterCompositingChange");
if (const LocalFrameView::ScrollableAreaSet* scrollable_areas =
layout_view_.GetFrameView()->ScrollableAreas()) {
- for (ScrollableArea* scrollable_area : *scrollable_areas)
- layers_changed |= scrollable_area->UpdateAfterCompositingChange();
+ for (PaintLayerScrollableArea* scrollable_area : *scrollable_areas)
+ scrollable_area->UpdateAfterCompositingChange();
}
- layers_changed |=
- layout_view_.GetFrameView()->UpdateAfterCompositingChange();
}
- if (layers_changed) {
+ if (layer_assigner.LayersChanged()) {
update_type = std::max(update_type, kCompositingUpdateRebuildTree);
if (ScrollingCoordinator* scrolling_coordinator =
GetScrollingCoordinator()) {
@@ -663,9 +658,6 @@ void PaintLayerCompositor::PaintInvalidationOnCompositingChange(
// to the previous frame's compositing state when changing the compositing
// backing of the layer.
DisableCompositingQueryAsserts disabler;
- // We have to do immediate paint invalidation because compositing will change.
- DisablePaintInvalidationStateAsserts paint_invalidation_assertisabler;
-
ObjectPaintInvalidator(layer->GetLayoutObject())
.InvalidatePaintIncludingNonCompositingDescendants();
}
@@ -734,6 +726,9 @@ GraphicsLayer* PaintLayerCompositor::RootGraphicsLayer() const {
GraphicsLayer* PaintLayerCompositor::PaintRootGraphicsLayer() const {
if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
+ if (layout_view_.GetDocument().GetPage()->GetChromeClient().IsPopup())
+ return RootGraphicsLayer();
+
// Start painting at the inner viewport container layer which is an ancestor
// of both the main contents layers and the scrollbar layers.
if (IsMainFrame() && GetVisualViewport().ContainerLayer())
@@ -824,7 +819,8 @@ bool PaintLayerCompositor::NeedsContentsCompositingLayer(
const PaintLayer* layer) const {
if (!layer->HasCompositingDescendant())
return false;
- return layer->StackingNode()->HasNegativeZOrderList();
+ return layer->StackingNode() &&
+ layer->StackingNode()->HasNegativeZOrderList();
}
static void UpdateTrackingRasterInvalidationsRecursive(
@@ -886,6 +882,11 @@ void PaintLayerCompositor::AttachRootLayer() {
// CompositedLayerMapping::updateGraphicsLayerConfiguration() for the
// frame's layoutObject in the parent document.
owner_element->SetNeedsCompositingUpdate();
+ if (owner_element->GetLayoutObject()) {
+ ToLayoutBoxModelObject(owner_element->GetLayoutObject())
+ ->Layer()
+ ->SetNeedsCompositingInputsUpdate();
+ }
root_layer_attachment_ = kRootLayerAttachedViaEnclosingFrame;
}
}
diff --git a/chromium/third_party/blink/renderer/core/paint/details_marker_painter.cc b/chromium/third_party/blink/renderer/core/paint/details_marker_painter.cc
index 795443bba7e..7f1868f9870 100644
--- a/chromium/third_party/blink/renderer/core/paint/details_marker_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/details_marker_painter.cc
@@ -14,11 +14,10 @@
namespace blink {
-void DetailsMarkerPainter::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void DetailsMarkerPainter::Paint(const PaintInfo& paint_info) {
if (paint_info.phase != PaintPhase::kForeground ||
layout_details_marker_.Style()->Visibility() != EVisibility::kVisible) {
- BlockPainter(layout_details_marker_).Paint(paint_info, paint_offset);
+ BlockPainter(layout_details_marker_).Paint(paint_info);
return;
}
@@ -26,10 +25,9 @@ void DetailsMarkerPainter::Paint(const PaintInfo& paint_info,
paint_info.context, layout_details_marker_, paint_info.phase))
return;
- AdjustPaintOffsetScope adjustment(layout_details_marker_, paint_info,
- paint_offset);
+ AdjustPaintOffsetScope adjustment(layout_details_marker_, paint_info);
const auto& local_paint_info = adjustment.GetPaintInfo();
- auto box_origin = adjustment.AdjustedPaintOffset();
+ auto box_origin = adjustment.PaintOffset();
LayoutRect overflow_rect(layout_details_marker_.VisualOverflowRect());
overflow_rect.MoveBy(box_origin);
diff --git a/chromium/third_party/blink/renderer/core/paint/details_marker_painter.h b/chromium/third_party/blink/renderer/core/paint/details_marker_painter.h
index 5dc7b7db030..a681ac33f01 100644
--- a/chromium/third_party/blink/renderer/core/paint/details_marker_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/details_marker_painter.h
@@ -21,7 +21,7 @@ class DetailsMarkerPainter {
DetailsMarkerPainter(const LayoutDetailsMarker& layout_details_marker)
: layout_details_marker_(layout_details_marker) {}
- void Paint(const PaintInfo&, const LayoutPoint& paint_offset);
+ void Paint(const PaintInfo&);
private:
Path GetCanonicalPath() const;
diff --git a/chromium/third_party/blink/renderer/core/paint/document_marker_painter.cc b/chromium/third_party/blink/renderer/core/paint/document_marker_painter.cc
new file mode 100644
index 00000000000..40624d469f5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/document_marker_painter.cc
@@ -0,0 +1,247 @@
+// 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/paint/document_marker_painter.h"
+
+#include "build/build_config.h"
+#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
+#include "third_party/blink/renderer/core/layout/layout_theme.h"
+#include "third_party/blink/renderer/core/paint/text_paint_style.h"
+#include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
+#include "third_party/blink/renderer/platform/layout_unit.h"
+
+namespace blink {
+
+namespace {
+
+#if !defined(OS_MACOSX)
+
+static const float kMarkerWidth = 4;
+static const float kMarkerHeight = 2;
+
+sk_sp<PaintRecord> RecordMarker(Color blink_color) {
+ const SkColor color = blink_color.Rgb();
+
+ // Record the path equivalent to this legacy pattern:
+ // X o o X o o X
+ // o X o o X o
+
+ // Adjust the phase such that f' == 0 is "pixel"-centered
+ // (for optimal rasterization at native rez).
+ SkPath path;
+ path.moveTo(kMarkerWidth * -3 / 8, kMarkerHeight * 3 / 4);
+ path.cubicTo(kMarkerWidth * -1 / 8, kMarkerHeight * 3 / 4,
+ kMarkerWidth * -1 / 8, kMarkerHeight * 1 / 4,
+ kMarkerWidth * 1 / 8, kMarkerHeight * 1 / 4);
+ path.cubicTo(kMarkerWidth * 3 / 8, kMarkerHeight * 1 / 4,
+ kMarkerWidth * 3 / 8, kMarkerHeight * 3 / 4,
+ kMarkerWidth * 5 / 8, kMarkerHeight * 3 / 4);
+ path.cubicTo(kMarkerWidth * 7 / 8, kMarkerHeight * 3 / 4,
+ kMarkerWidth * 7 / 8, kMarkerHeight * 1 / 4,
+ kMarkerWidth * 9 / 8, kMarkerHeight * 1 / 4);
+
+ PaintFlags flags;
+ flags.setAntiAlias(true);
+ flags.setColor(color);
+ flags.setStyle(PaintFlags::kStroke_Style);
+ flags.setStrokeWidth(kMarkerHeight * 1 / 2);
+
+ PaintRecorder recorder;
+ recorder.beginRecording(kMarkerWidth, kMarkerHeight);
+ recorder.getRecordingCanvas()->drawPath(path, flags);
+
+ return recorder.finishRecordingAsPicture();
+}
+
+#else // defined(OS_MACOSX)
+
+static const float kMarkerWidth = 4;
+static const float kMarkerHeight = 3;
+
+sk_sp<PaintRecord> RecordMarker(Color blink_color) {
+ const SkColor color = blink_color.Rgb();
+
+ // Match the artwork used by the Mac.
+ static const float kR = 1.5f;
+
+ // top->bottom translucent gradient.
+ const SkColor colors[2] = {
+ SkColorSetARGB(0x48, SkColorGetR(color), SkColorGetG(color),
+ SkColorGetB(color)),
+ color};
+ const SkPoint pts[2] = {SkPoint::Make(0, 0), SkPoint::Make(0, 2 * kR)};
+
+ PaintFlags flags;
+ flags.setAntiAlias(true);
+ flags.setColor(color);
+ flags.setShader(PaintShader::MakeLinearGradient(
+ pts, colors, nullptr, ARRAY_SIZE(colors), SkShader::kClamp_TileMode));
+ PaintRecorder recorder;
+ recorder.beginRecording(kMarkerWidth, kMarkerHeight);
+ recorder.getRecordingCanvas()->drawOval(SkRect::MakeWH(2 * kR, 2 * kR),
+ flags);
+ return recorder.finishRecordingAsPicture();
+}
+
+#endif // defined(OS_MACOSX)
+
+void DrawDocumentMarker(GraphicsContext& context,
+ const FloatPoint& pt,
+ float width,
+ DocumentMarker::MarkerType marker_type,
+ float zoom) {
+ DCHECK(marker_type == DocumentMarker::kSpelling ||
+ marker_type == DocumentMarker::kGrammar);
+
+ DEFINE_STATIC_LOCAL(
+ PaintRecord*, spelling_marker,
+ (RecordMarker(
+ LayoutTheme::GetTheme().PlatformSpellingMarkerUnderlineColor())
+ .release()));
+ DEFINE_STATIC_LOCAL(
+ PaintRecord*, grammar_marker,
+ (RecordMarker(
+ LayoutTheme::GetTheme().PlatformGrammarMarkerUnderlineColor())
+ .release()));
+ auto* const marker = marker_type == DocumentMarker::kSpelling
+ ? spelling_marker
+ : grammar_marker;
+
+ // Position already includes zoom and device scale factor.
+ SkScalar origin_x = WebCoreFloatToSkScalar(pt.X());
+ SkScalar origin_y = WebCoreFloatToSkScalar(pt.Y());
+
+#if defined(OS_MACOSX)
+ // Make sure to draw only complete dots, and finish inside the marked text.
+ width -= fmodf(width, kMarkerWidth * zoom);
+#else
+ // Offset it vertically by 1 so that there's some space under the text.
+ origin_y += 1;
+#endif
+
+ const auto rect = SkRect::MakeWH(width, kMarkerHeight * zoom);
+ const auto local_matrix = SkMatrix::MakeScale(zoom, zoom);
+
+ PaintFlags flags;
+ flags.setAntiAlias(true);
+ flags.setShader(PaintShader::MakePaintRecord(
+ sk_ref_sp(marker), FloatRect(0, 0, kMarkerWidth, kMarkerHeight),
+ SkShader::kRepeat_TileMode, SkShader::kClamp_TileMode, &local_matrix));
+
+ // Apply the origin translation as a global transform. This ensures that the
+ // shader local matrix depends solely on zoom => Skia can reuse the same
+ // cached tile for all markers at a given zoom level.
+ GraphicsContextStateSaver saver(context);
+ context.Translate(origin_x, origin_y);
+ context.DrawRect(rect, flags);
+}
+
+} // anonymous ns
+
+// TODO(yoichio) : Move this to document_marker_painter.cc
+void DocumentMarkerPainter::PaintStyleableMarkerUnderline(
+ GraphicsContext& context,
+ const LayoutPoint& box_origin,
+ const StyleableMarker& marker,
+ const ComputedStyle& style,
+ const FloatRect& marker_rect,
+ LayoutUnit logical_height) {
+ if (marker.HasThicknessNone() ||
+ (marker.UnderlineColor() == Color::kTransparent &&
+ !marker.UseTextColor()))
+ return;
+
+ // start of line to draw, relative to box_origin.X()
+ LayoutUnit start = LayoutUnit(marker_rect.X());
+ LayoutUnit width = LayoutUnit(marker_rect.Width());
+
+ // We need to have some space between underlines of subsequent clauses,
+ // because some input methods do not use different underline styles for those.
+ // We make each line shorter, which has a harmless side effect of shortening
+ // the first and last clauses, too.
+ start += 1;
+ width -= 2;
+
+ // Thick marked text underlines are 2px thick as long as there is room for the
+ // 2px line under the baseline. All other marked text underlines are 1px
+ // thick. If there's not enough space the underline will touch or overlap
+ // characters.
+ int line_thickness = 1;
+ const SimpleFontData* font_data = style.GetFont().PrimaryFont();
+ DCHECK(font_data);
+ int baseline = font_data ? font_data->GetFontMetrics().Ascent() : 0;
+ if (marker.HasThicknessThick() && logical_height.ToInt() - baseline >= 2)
+ line_thickness = 2;
+
+ Color marker_color =
+ marker.UseTextColor()
+ ? style.VisitedDependentColor(GetCSSPropertyWebkitTextFillColor())
+ : marker.UnderlineColor();
+ context.SetStrokeColor(marker_color);
+
+ context.SetStrokeThickness(line_thickness);
+ context.DrawLineForText(
+ FloatPoint(
+ box_origin.X() + start,
+ (box_origin.Y() + logical_height.ToInt() - line_thickness).ToFloat()),
+ width);
+}
+
+static const int kMisspellingLineThickness = 3;
+
+// TODO(yoichio): Move this to document_marker_painter.cc
+void DocumentMarkerPainter::PaintDocumentMarker(
+ GraphicsContext& context,
+ const LayoutPoint& box_origin,
+ const ComputedStyle& style,
+ DocumentMarker::MarkerType marker_type,
+ const LayoutRect& local_rect) {
+ // IMPORTANT: The misspelling underline is not considered when calculating the
+ // text bounds, so we have to make sure to fit within those bounds. This
+ // means the top pixel(s) of the underline will overlap the bottom pixel(s) of
+ // the glyphs in smaller font sizes. The alternatives are to increase the
+ // line spacing (bad!!) or decrease the underline thickness. The overlap is
+ // actually the most useful, and matches what AppKit does. So, we generally
+ // place the underline at the bottom of the text, but in larger fonts that's
+ // not so good so we pin to two pixels under the baseline.
+ int line_thickness = kMisspellingLineThickness;
+
+ const SimpleFontData* font_data = style.GetFont().PrimaryFont();
+ DCHECK(font_data);
+ int baseline = font_data->GetFontMetrics().Ascent();
+ int descent = (local_rect.Height() - baseline).ToInt();
+ int underline_offset;
+ if (descent <= (line_thickness + 2)) {
+ // Place the underline at the very bottom of the text in small/medium fonts.
+ underline_offset = (local_rect.Height() - line_thickness).ToInt();
+ } else {
+ // In larger fonts, though, place the underline up near the baseline to
+ // prevent a big gap.
+ underline_offset = baseline + 2;
+ }
+ DrawDocumentMarker(context,
+ FloatPoint((box_origin.X() + local_rect.X()).ToFloat(),
+ (box_origin.Y() + underline_offset).ToFloat()),
+ local_rect.Width().ToFloat(), marker_type,
+ style.EffectiveZoom());
+}
+
+TextPaintStyle DocumentMarkerPainter::ComputeTextPaintStyleFrom(
+ const ComputedStyle& style,
+ const TextMatchMarker& marker) {
+ const Color text_color =
+ LayoutTheme::GetTheme().PlatformTextSearchColor(marker.IsActiveMatch());
+ if (style.VisitedDependentColor(GetCSSPropertyColor()) == text_color)
+ return {};
+
+ TextPaintStyle text_style;
+ text_style.current_color = text_style.fill_color = text_style.stroke_color =
+ text_style.emphasis_mark_color = text_color;
+ text_style.stroke_width = style.TextStrokeWidth();
+ text_style.shadow = nullptr;
+ return text_style;
+}
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/document_marker_painter.h b/chromium/third_party/blink/renderer/core/paint/document_marker_painter.h
new file mode 100644
index 00000000000..928baad29a3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/document_marker_painter.h
@@ -0,0 +1,48 @@
+// 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_PAINT_DOCUMENT_MARKER_PAINTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_DOCUMENT_MARKER_PAINTER_H_
+
+#include "third_party/blink/renderer/core/editing/markers/document_marker.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+
+namespace blink {
+
+class ComputedStyle;
+class FloatRect;
+class GraphicsContext;
+class LayoutPoint;
+class LayoutRect;
+class LayoutUnit;
+class StyleableMarker;
+class TextMatchMarker;
+struct TextPaintStyle;
+
+// Document marker painter for both LayoutNG and legacy layout.
+// This paints text decorations for spell/grammer check, find-in-page, and
+// input method.
+class DocumentMarkerPainter {
+ STATIC_ONLY(DocumentMarkerPainter);
+
+ public:
+ static void PaintStyleableMarkerUnderline(GraphicsContext& context,
+ const LayoutPoint& box_origin,
+ const StyleableMarker& marker,
+ const ComputedStyle& style,
+ const FloatRect& marker_rect,
+ LayoutUnit logical_height);
+ static void PaintDocumentMarker(GraphicsContext& context,
+ const LayoutPoint& box_origin,
+ const ComputedStyle& style,
+ DocumentMarker::MarkerType marker_type,
+ const LayoutRect& local_rect);
+ static TextPaintStyle ComputeTextPaintStyleFrom(
+ const ComputedStyle& style,
+ const TextMatchMarker& marker);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_DOCUMENT_MARKER_PAINTER_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/embedded_content_painter.cc b/chromium/third_party/blink/renderer/core/paint/embedded_content_painter.cc
index 95500c3ff98..6945ceba555 100644
--- a/chromium/third_party/blink/renderer/core/paint/embedded_content_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/embedded_content_painter.cc
@@ -13,10 +13,8 @@
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/replaced_painter.h"
-#include "third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.h"
#include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
#include "third_party/blink/renderer/core/paint/selection_painting_utils.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.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"
@@ -30,8 +28,7 @@ bool EmbeddedContentPainter::IsSelected() const {
return true;
}
-void EmbeddedContentPainter::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void EmbeddedContentPainter::Paint(const PaintInfo& paint_info) {
// TODO(crbug.com/797779): For now embedded contents don't know whether
// they are painted in a fragmented context and may do something bad in a
// fragmented context, e.g. creating subsequences. Skip cache to avoid that.
@@ -41,33 +38,31 @@ void EmbeddedContentPainter::Paint(const PaintInfo& paint_info,
if (layout_embedded_content_.Layer()->EnclosingPaginationLayer())
cache_skipper.emplace(paint_info.context);
- AdjustPaintOffsetScope adjustment(layout_embedded_content_, paint_info,
- paint_offset);
+ AdjustPaintOffsetScope adjustment(layout_embedded_content_, paint_info);
const auto& local_paint_info = adjustment.GetPaintInfo();
- auto adjusted_paint_offset = adjustment.AdjustedPaintOffset();
+ auto paint_offset = adjustment.PaintOffset();
if (!ReplacedPainter(layout_embedded_content_)
- .ShouldPaint(local_paint_info, adjusted_paint_offset))
+ .ShouldPaint(local_paint_info, paint_offset))
return;
- LayoutRect border_rect(adjusted_paint_offset,
- layout_embedded_content_.Size());
+ LayoutRect border_rect(paint_offset, layout_embedded_content_.Size());
if (layout_embedded_content_.HasBoxDecorationBackground() &&
(local_paint_info.phase == PaintPhase::kForeground ||
local_paint_info.phase == PaintPhase::kSelection)) {
BoxPainter(layout_embedded_content_)
- .PaintBoxDecorationBackground(local_paint_info, adjusted_paint_offset);
+ .PaintBoxDecorationBackground(local_paint_info, paint_offset);
}
if (local_paint_info.phase == PaintPhase::kMask) {
BoxPainter(layout_embedded_content_)
- .PaintMask(local_paint_info, adjusted_paint_offset);
+ .PaintMask(local_paint_info, paint_offset);
return;
}
if (ShouldPaintSelfOutline(local_paint_info.phase)) {
ObjectPainter(layout_embedded_content_)
- .PaintOutline(local_paint_info, adjusted_paint_offset);
+ .PaintOutline(local_paint_info, paint_offset);
}
if (local_paint_info.phase != PaintPhase::kForeground)
@@ -75,38 +70,20 @@ void EmbeddedContentPainter::Paint(const PaintInfo& paint_info,
if (layout_embedded_content_.GetEmbeddedContentView()) {
base::Optional<ScopedPaintChunkProperties> scoped_paint_chunk_properties;
- base::Optional<RoundedInnerRectClipper> clipper;
if (layout_embedded_content_.Style()->HasBorderRadius()) {
if (border_rect.IsEmpty())
return;
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- const auto* fragment =
- local_paint_info.FragmentToPaint(layout_embedded_content_);
- if (!fragment)
- return;
- const auto* properties = fragment->PaintProperties();
- DCHECK(properties && properties->InnerBorderRadiusClip());
- scoped_paint_chunk_properties.emplace(
- local_paint_info.context.GetPaintController(),
- properties->InnerBorderRadiusClip(), layout_embedded_content_,
- DisplayItem::PaintPhaseToDrawingType(local_paint_info.phase));
- } else {
- FloatRoundedRect rounded_inner_rect =
- layout_embedded_content_.Style()->GetRoundedInnerBorderFor(
- border_rect,
- LayoutRectOutsets(-(layout_embedded_content_.PaddingTop() +
- layout_embedded_content_.BorderTop()),
- -(layout_embedded_content_.PaddingRight() +
- layout_embedded_content_.BorderRight()),
- -(layout_embedded_content_.PaddingBottom() +
- layout_embedded_content_.BorderBottom()),
- -(layout_embedded_content_.PaddingLeft() +
- layout_embedded_content_.BorderLeft())),
- true, true);
- clipper.emplace(layout_embedded_content_, local_paint_info, border_rect,
- rounded_inner_rect, kApplyToDisplayList);
- }
+ const auto* fragment =
+ local_paint_info.FragmentToPaint(layout_embedded_content_);
+ if (!fragment)
+ return;
+ const auto* properties = fragment->PaintProperties();
+ DCHECK(properties && properties->InnerBorderRadiusClip());
+ scoped_paint_chunk_properties.emplace(
+ local_paint_info.context.GetPaintController(),
+ properties->InnerBorderRadiusClip(), layout_embedded_content_,
+ DisplayItem::PaintPhaseToDrawingType(local_paint_info.phase));
}
layout_embedded_content_.PaintContents(local_paint_info, paint_offset);
@@ -118,7 +95,7 @@ void EmbeddedContentPainter::Paint(const PaintInfo& paint_info,
layout_embedded_content_,
local_paint_info.phase)) {
LayoutRect rect = layout_embedded_content_.LocalSelectionRect();
- rect.MoveBy(adjusted_paint_offset);
+ rect.MoveBy(paint_offset);
IntRect selection_rect = PixelSnappedIntRect(rect);
DrawingRecorder recorder(local_paint_info.context, layout_embedded_content_,
local_paint_info.phase);
@@ -132,25 +109,19 @@ void EmbeddedContentPainter::Paint(const PaintInfo& paint_info,
if (layout_embedded_content_.CanResize()) {
ScrollableAreaPainter(
*layout_embedded_content_.Layer()->GetScrollableArea())
- .PaintResizer(local_paint_info.context,
- RoundedIntPoint(adjusted_paint_offset),
+ .PaintResizer(local_paint_info.context, RoundedIntPoint(paint_offset),
local_paint_info.GetCullRect());
}
}
void EmbeddedContentPainter::PaintContents(const PaintInfo& paint_info,
const LayoutPoint& paint_offset) {
- AdjustPaintOffsetScope adjustment(layout_embedded_content_, paint_info,
- paint_offset);
- const auto& local_paint_info = adjustment.GetPaintInfo();
- auto adjusted_paint_offset = adjustment.AdjustedPaintOffset();
-
EmbeddedContentView* embedded_content_view =
layout_embedded_content_.GetEmbeddedContentView();
CHECK(embedded_content_view);
IntPoint paint_location(RoundedIntPoint(
- adjusted_paint_offset +
+ paint_offset +
layout_embedded_content_.ReplacedContentRect().Location()));
// Views don't support painting with a paint offset, but instead
@@ -159,18 +130,10 @@ void EmbeddedContentPainter::PaintContents(const PaintInfo& paint_info,
// the frame rect neutralized.
IntSize view_paint_offset =
paint_location - embedded_content_view->FrameRect().Location();
- TransformRecorder transform(
- local_paint_info.context, layout_embedded_content_,
- AffineTransform::Translation(view_paint_offset.Width(),
- view_paint_offset.Height()));
- CullRect adjusted_cull_rect(local_paint_info.GetCullRect(),
- -view_paint_offset);
- embedded_content_view->Paint(
- local_paint_info.context, local_paint_info.GetGlobalPaintFlags(),
- adjusted_cull_rect,
- // For SPv175 we need to apply the transform during painting.
- RuntimeEnabledFeatures::SlimmingPaintV175Enabled() ? view_paint_offset
- : IntSize());
+ CullRect adjusted_cull_rect(paint_info.GetCullRect(), -view_paint_offset);
+ embedded_content_view->Paint(paint_info.context,
+ paint_info.GetGlobalPaintFlags(),
+ adjusted_cull_rect, view_paint_offset);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/embedded_content_painter.h b/chromium/third_party/blink/renderer/core/paint/embedded_content_painter.h
index 89e1a16e2e3..ea101cd1d3e 100644
--- a/chromium/third_party/blink/renderer/core/paint/embedded_content_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/embedded_content_painter.h
@@ -20,8 +20,8 @@ class EmbeddedContentPainter {
EmbeddedContentPainter(const LayoutEmbeddedContent& layout_embedded_content)
: layout_embedded_content_(layout_embedded_content) {}
- void Paint(const PaintInfo&, const LayoutPoint&);
- void PaintContents(const PaintInfo&, const LayoutPoint&);
+ void Paint(const PaintInfo&);
+ void PaintContents(const PaintInfo&, const LayoutPoint& paint_offset);
private:
bool IsSelected() const;
diff --git a/chromium/third_party/blink/renderer/core/paint/fieldset_painter.h b/chromium/third_party/blink/renderer/core/paint/fieldset_painter.h
index dabfdd76198..66195e03fe2 100644
--- a/chromium/third_party/blink/renderer/core/paint/fieldset_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/fieldset_painter.h
@@ -20,8 +20,9 @@ class FieldsetPainter {
FieldsetPainter(const LayoutFieldset& layout_fieldset)
: layout_fieldset_(layout_fieldset) {}
- void PaintBoxDecorationBackground(const PaintInfo&, const LayoutPoint&);
- void PaintMask(const PaintInfo&, const LayoutPoint&);
+ void PaintBoxDecorationBackground(const PaintInfo&,
+ const LayoutPoint& paint_offset);
+ void PaintMask(const PaintInfo&, const LayoutPoint& paint_offset);
private:
const LayoutFieldset& layout_fieldset_;
diff --git a/chromium/third_party/blink/renderer/core/paint/file_upload_control_painter.cc b/chromium/third_party/blink/renderer/core/paint/file_upload_control_painter.cc
index 68b5b46070d..8f207775a1d 100644
--- a/chromium/third_party/blink/renderer/core/paint/file_upload_control_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/file_upload_control_painter.cc
@@ -10,36 +10,16 @@
#include "third_party/blink/renderer/core/layout/text_run_constructor.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/platform/fonts/text_run_paint_info.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
namespace blink {
-const int kButtonShadowHeight = 2;
-
void FileUploadControlPainter::PaintObject(const PaintInfo& paint_info,
const LayoutPoint& paint_offset) {
if (layout_file_upload_control_.Style()->Visibility() !=
EVisibility::kVisible)
return;
- // Push a clip.
- base::Optional<ClipRecorder> clip_recorder;
- if (paint_info.phase == PaintPhase::kForeground ||
- paint_info.phase == PaintPhase::kDescendantBlockBackgroundsOnly) {
- IntRect clip_rect = EnclosingIntRect(LayoutRect(
- LayoutPoint(paint_offset.X() + layout_file_upload_control_.BorderLeft(),
- paint_offset.Y() + layout_file_upload_control_.BorderTop()),
- layout_file_upload_control_.Size() +
- LayoutSize(LayoutUnit(),
- -layout_file_upload_control_.BorderWidth() +
- kButtonShadowHeight)));
- if (clip_rect.IsEmpty())
- return;
- clip_recorder.emplace(paint_info.context, layout_file_upload_control_,
- DisplayItem::kClipFileUploadControlRect, clip_rect);
- }
-
if (paint_info.phase == PaintPhase::kForeground &&
!DrawingRecorder::UseCachedDrawingIfPossible(
paint_info.context, layout_file_upload_control_, paint_info.phase)) {
diff --git a/chromium/third_party/blink/renderer/core/paint/file_upload_control_painter.h b/chromium/third_party/blink/renderer/core/paint/file_upload_control_painter.h
index 33f9f8c6cc4..2935b6f8daa 100644
--- a/chromium/third_party/blink/renderer/core/paint/file_upload_control_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/file_upload_control_painter.h
@@ -21,7 +21,7 @@ class FileUploadControlPainter {
const LayoutFileUploadControl& layout_file_upload_control)
: layout_file_upload_control_(layout_file_upload_control) {}
- void PaintObject(const PaintInfo&, const LayoutPoint&);
+ void PaintObject(const PaintInfo&, const LayoutPoint& paint_offset);
private:
const LayoutFileUploadControl& layout_file_upload_control_;
diff --git a/chromium/third_party/blink/renderer/core/paint/filter_painter.cc b/chromium/third_party/blink/renderer/core/paint/filter_painter.cc
deleted file mode 100644
index 6613a0aa50d..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/filter_painter.cc
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/paint/filter_painter.h"
-
-#include <memory>
-#include <utility>
-
-#include "third_party/blink/renderer/core/paint/filter_effect_builder.h"
-#include "third_party/blink/renderer/core/paint/layer_clip_recorder.h"
-#include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/platform/graphics/compositor_filter_operations.h"
-#include "third_party/blink/renderer/platform/graphics/filters/filter_effect.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/filter_display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-
-namespace blink {
-
-sk_sp<PaintFilter> FilterPainter::GetImageFilter(PaintLayer& layer) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return nullptr;
-
- if (!layer.PaintsWithFilters())
- return nullptr;
-
- FilterEffect* last_effect = layer.LastFilterEffect();
- if (!last_effect)
- return nullptr;
-
- return PaintFilterBuilder::Build(last_effect, kInterpolationSpaceSRGB);
-}
-
-FilterPainter::FilterPainter(PaintLayer& layer,
- GraphicsContext& context,
- const LayoutPoint& offset_from_root,
- const ClipRect& clip_rect,
- PaintLayerPaintingInfo& painting_info,
- PaintLayerFlags paint_flags)
- : filter_in_progress_(false),
- context_(context),
- layout_object_(layer.GetLayoutObject()) {
- sk_sp<PaintFilter> image_filter = GetImageFilter(layer);
- if (!image_filter)
- return;
-
- if (clip_rect.Rect() != painting_info.paint_dirty_rect ||
- clip_rect.HasRadius()) {
- // Apply clips outside the filter. See discussion about these clips
- // in PaintLayerPainter regarding "clipping in the presence of filters".
- clip_recorder_ = std::make_unique<LayerClipRecorder>(
- context, layer, DisplayItem::kClipLayerFilter, clip_rect,
- painting_info.root_layer, LayoutPoint(), paint_flags,
- layer.GetLayoutObject());
- }
-
- if (!context.GetPaintController().DisplayItemConstructionIsDisabled()) {
- CompositorFilterOperations compositor_filter_operations;
- layer.UpdateCompositorFilterOperationsForFilter(
- compositor_filter_operations);
- // FIXME: It's possible to have empty CompositorFilterOperations here even
- // though the PaintFilter produced above is non-null, since the
- // layer's FilterEffectBuilder can have a stale representation of
- // the layer's filter. See crbug.com/502026.
- if (compositor_filter_operations.IsEmpty())
- return;
- LayoutRect visual_bounds(
- layer.PhysicalBoundingBoxIncludingStackingChildren(offset_from_root));
- if (layer.EnclosingPaginationLayer()) {
- // Filters are set up before pagination, so we need to make the bounding
- // box visual on our own.
- visual_bounds.MoveBy(-offset_from_root);
- layer.ConvertFromFlowThreadToVisualBoundingBoxInAncestor(
- painting_info.root_layer, visual_bounds);
- }
- FloatPoint origin(offset_from_root);
- context.GetPaintController().CreateAndAppend<BeginFilterDisplayItem>(
- layout_object_, std::move(image_filter), FloatRect(visual_bounds),
- origin, std::move(compositor_filter_operations));
- }
-
- filter_in_progress_ = true;
-}
-
-FilterPainter::~FilterPainter() {
- if (!filter_in_progress_)
- return;
-
- context_.GetPaintController().EndItem<EndFilterDisplayItem>(layout_object_);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/filter_painter.h b/chromium/third_party/blink/renderer/core/paint/filter_painter.h
deleted file mode 100644
index 97c4ea3373d..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/filter_painter.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_FILTER_PAINTER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_FILTER_PAINTER_H_
-
-#include <memory>
-#include "third_party/blink/renderer/core/paint/paint_layer_painting_info.h"
-#include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class ClipRect;
-class GraphicsContext;
-class PaintLayer;
-class LayerClipRecorder;
-class LayoutObject;
-
-class FilterPainter {
- public:
- FilterPainter(PaintLayer&,
- GraphicsContext&,
- const LayoutPoint& offset_from_root,
- const ClipRect&,
- PaintLayerPaintingInfo&,
- PaintLayerFlags paint_flags);
- ~FilterPainter();
-
- // Returns whether it's ok to clip this PaintLayer's painted outputs
- // the dirty rect. Some filters require input from outside this rect, in
- // which case this method would return true.
- static sk_sp<PaintFilter> GetImageFilter(PaintLayer&);
-
- private:
- bool filter_in_progress_;
- GraphicsContext& context_;
- std::unique_ptr<LayerClipRecorder> clip_recorder_;
- LayoutObject& layout_object_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_FILTER_PAINTER_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/find_paint_offset_and_visual_rect_needing_update.h b/chromium/third_party/blink/renderer/core/paint/find_paint_offset_and_visual_rect_needing_update.h
index b75179c759a..4df507f5195 100644
--- a/chromium/third_party/blink/renderer/core/paint/find_paint_offset_and_visual_rect_needing_update.h
+++ b/chromium/third_party/blink/renderer/core/paint/find_paint_offset_and_visual_rect_needing_update.h
@@ -56,21 +56,20 @@ class FindPaintOffsetNeedingUpdateScope {
const FragmentData& fragment_data_;
const bool& is_actually_needed_;
LayoutPoint old_paint_offset_;
- scoped_refptr<const TransformPaintPropertyNode> old_paint_offset_translation_;
+ scoped_refptr<TransformPaintPropertyNode> old_paint_offset_translation_;
};
class FindVisualRectNeedingUpdateScopeBase {
protected:
FindVisualRectNeedingUpdateScopeBase(const LayoutObject& object,
const PaintInvalidatorContext& context,
- const LayoutRect& old_visual_rect,
- bool is_actually_needed)
+ const LayoutRect& old_visual_rect)
: object_(object),
context_(context),
old_visual_rect_(old_visual_rect),
needed_visual_rect_update_(context.NeedsVisualRectUpdate(object)) {
if (needed_visual_rect_update_) {
- DCHECK(is_actually_needed);
+ DCHECK(context.tree_builder_context_actually_needed_);
return;
}
context.force_visual_rect_update_for_checking_ = true;
@@ -125,11 +124,7 @@ class FindVisualRectNeedingUpdateScope : FindVisualRectNeedingUpdateScopeBase {
// Must be a reference to a rect that
// outlives this scope.
const LayoutRect& new_visual_rect)
- : FindVisualRectNeedingUpdateScopeBase(
- object,
- context,
- old_visual_rect,
- context.tree_builder_context_actually_needed_),
+ : FindVisualRectNeedingUpdateScopeBase(object, context, old_visual_rect),
new_visual_rect_ref_(new_visual_rect) {}
~FindVisualRectNeedingUpdateScope() { CheckVisualRect(new_visual_rect_ref_); }
@@ -144,42 +139,18 @@ class FindObjectVisualRectNeedingUpdateScope
public:
FindObjectVisualRectNeedingUpdateScope(const LayoutObject& object,
const FragmentData& fragment_data,
- const PaintInvalidatorContext& context,
- bool is_actually_needed)
+ const PaintInvalidatorContext& context)
: FindVisualRectNeedingUpdateScopeBase(object,
context,
- fragment_data.VisualRect(),
- is_actually_needed),
- fragment_data_(fragment_data),
- old_location_(context.old_location) {}
+ fragment_data.VisualRect()),
+ fragment_data_(fragment_data) {}
~FindObjectVisualRectNeedingUpdateScope() {
CheckVisualRect(fragment_data_.VisualRect());
- CheckLocation();
- }
-
- void CheckLocation() {
- if (needed_visual_rect_update_)
- return;
- LayoutPoint new_location = fragment_data_.LocationInBacking();
- // Location of LayoutText and non-root SVG is location of the visual rect
- // which have been checked above.
- DCHECK(object_.IsText() || object_.IsSVGChild() ||
- new_location == old_location_ ||
- object_.EnclosingLayer()->SubtreeIsInvisible() ||
- // See checkVisualRect for the issue of approximation.
- LayoutRect(-1, -1, 2, 2)
- .Contains(LayoutRect(LayoutPoint(new_location - old_location_),
- LayoutSize())))
- << "Location changed without needing update"
- << " object=" << object_.DebugName()
- << " old=" << old_location_.ToString()
- << " new=" << new_location.ToString();
}
private:
const FragmentData& fragment_data_;
- LayoutPoint old_location_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/find_properties_needing_update.h b/chromium/third_party/blink/renderer/core/paint/find_properties_needing_update.h
index 2caa8892310..f27d8d9823d 100644
--- a/chromium/third_party/blink/renderer/core/paint/find_properties_needing_update.h
+++ b/chromium/third_party/blink/renderer/core/paint/find_properties_needing_update.h
@@ -107,6 +107,12 @@ class FindObjectPropertiesNeedingUpdateScope {
object_properties->Effect());
DCHECK_OBJECT_PROPERTY_EQ(object_, original_properties_->Filter(),
object_properties->Filter());
+ DCHECK_OBJECT_PROPERTY_EQ(object_,
+ original_properties_->VerticalScrollbarEffect(),
+ object_properties->VerticalScrollbarEffect());
+ DCHECK_OBJECT_PROPERTY_EQ(
+ object_, original_properties_->HorizontalScrollbarEffect(),
+ object_properties->HorizontalScrollbarEffect());
DCHECK_OBJECT_PROPERTY_EQ(object_, original_properties_->Mask(),
object_properties->Mask());
DCHECK_OBJECT_PROPERTY_EQ(object_, original_properties_->ClipPath(),
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 9fa4b224de2..472ac46a524 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
@@ -7,6 +7,7 @@
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_layer_tree_view.h"
#include "third_party/blink/renderer/core/css/font_face_set_document.h"
+#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/paint/paint_timing.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
@@ -24,6 +25,9 @@ const int kBlankCharactersThreshold = 200;
} // namespace
+constexpr TimeDelta FirstMeaningfulPaintDetector::kNetwork2QuietWindowTimeout;
+constexpr TimeDelta FirstMeaningfulPaintDetector::kNetwork0QuietWindowTimeout;
+
FirstMeaningfulPaintDetector& FirstMeaningfulPaintDetector::From(
Document& document) {
return PaintTiming::From(document).GetFirstMeaningfulPaintDetector();
@@ -40,7 +44,13 @@ FirstMeaningfulPaintDetector::FirstMeaningfulPaintDetector(
network2_quiet_timer_(
document.GetTaskRunner(TaskType::kInternalDefault),
this,
- &FirstMeaningfulPaintDetector::Network2QuietTimerFired) {}
+ &FirstMeaningfulPaintDetector::Network2QuietTimerFired) {
+ if (GetDocument() && GetDocument()->GetSettings()) {
+ network2_quiet_window_timeout_ = TimeDelta::FromSecondsD(
+ GetDocument()->GetSettings()->GetFMPNetworkQuietTimeout());
+ network0_quiet_window_timeout_ = network2_quiet_window_timeout_;
+ }
+}
Document* FirstMeaningfulPaintDetector::GetDocument() {
return paint_timing_->GetSupplementable();
@@ -135,13 +145,14 @@ void FirstMeaningfulPaintDetector::SetNetworkQuietTimers(
// If activeConnections < 2 and the timer is already running, current
// 2-quiet window continues; the timer shouldn't be restarted.
if (active_connections == 2 || !network2_quiet_timer_.IsActive()) {
- network2_quiet_timer_.StartOneShot(kNetwork2QuietWindowSeconds,
+ network2_quiet_timer_.StartOneShot(network2_quiet_window_timeout_,
FROM_HERE);
}
}
if (!network0_quiet_reached_ && active_connections == 0) {
// This restarts 0-quiet timer if it's already running.
- network0_quiet_timer_.StartOneShot(kNetwork0QuietWindowSeconds, FROM_HERE);
+ network0_quiet_timer_.StartOneShot(network0_quiet_window_timeout_,
+ FROM_HERE);
}
}
@@ -306,7 +317,6 @@ void FirstMeaningfulPaintDetector::SetFirstMeaningfulPaint(
TimeTicks stamp,
TimeTicks swap_stamp) {
DCHECK(paint_timing_->FirstMeaningfulPaint().is_null());
- DCHECK_GE(swap_stamp, stamp);
DCHECK(!swap_stamp.is_null());
DCHECK(network2_quiet_reached_);
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 0ad6f50003e..ff6f60d8951 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
@@ -16,28 +16,17 @@
namespace blink {
class Document;
+class LayoutObjectCounter;
class PaintTiming;
// FirstMeaningfulPaintDetector observes layout operations during page load
-// until network stable (2 seconds of no network activity), and computes the
+// until network stable (0.5 seconds of no network activity), and computes the
// layout-based First Meaningful Paint.
// See https://goo.gl/vpaxv6 and http://goo.gl/TEiMi4 for more details.
class CORE_EXPORT FirstMeaningfulPaintDetector
: public GarbageCollectedFinalized<FirstMeaningfulPaintDetector> {
public:
- // Used by FrameView to keep track of the number of layout objects created
- // in the frame.
- class LayoutObjectCounter {
- public:
- void Reset() { count_ = 0; }
- void Increment() { count_++; }
- unsigned Count() const { return count_; }
-
- private:
- unsigned count_ = 0;
- };
-
static FirstMeaningfulPaintDetector& From(Document&);
FirstMeaningfulPaintDetector(PaintTiming*, Document&);
@@ -70,8 +59,10 @@ class CORE_EXPORT FirstMeaningfulPaintDetector
// The page is n-quiet if there are no more than n active network requests for
// this duration of time.
- static constexpr double kNetwork2QuietWindowSeconds = 0.5;
- static constexpr double kNetwork0QuietWindowSeconds = 0.5;
+ static constexpr TimeDelta kNetwork2QuietWindowTimeout =
+ TimeDelta::FromSecondsD(0.5);
+ static constexpr TimeDelta kNetwork0QuietWindowTimeout =
+ TimeDelta::FromSecondsD(0.5);
Document* GetDocument();
int ActiveConnections();
@@ -92,6 +83,8 @@ class CORE_EXPORT FirstMeaningfulPaintDetector
TimeTicks provisional_first_meaningful_paint_swap_;
double max_significance_so_far_ = 0.0;
double accumulated_significance_while_having_blank_text_ = 0.0;
+ TimeDelta network2_quiet_window_timeout_ = kNetwork2QuietWindowTimeout;
+ TimeDelta network0_quiet_window_timeout_ = kNetwork0QuietWindowTimeout;
unsigned prev_layout_object_count_ = 0;
bool seen_first_meaningful_paint_candidate_ = false;
bool network0_quiet_reached_ = false;
diff --git a/chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector_test.cc b/chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector_test.cc
index f9414e495eb..756ad3f1124 100644
--- a/chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/first_meaningful_paint_detector_test.cc
@@ -18,7 +18,7 @@ namespace blink {
class FirstMeaningfulPaintDetectorTest : public PageTestBase {
protected:
void SetUp() override {
- platform_->AdvanceClockSeconds(1);
+ platform_->AdvanceClock(TimeDelta::FromSeconds(1));
PageTestBase::SetUp();
ResetNetworkQuietTimer();
}
@@ -32,7 +32,7 @@ class FirstMeaningfulPaintDetectorTest : public PageTestBase {
}
TimeTicks AdvanceClockAndGetTime() {
- platform_->AdvanceClockSeconds(1);
+ platform_->AdvanceClock(TimeDelta::FromSeconds(1));
return CurrentTimeTicks();
}
@@ -42,7 +42,7 @@ class FirstMeaningfulPaintDetectorTest : public PageTestBase {
}
void SimulateLayoutAndPaint(int new_elements) {
- platform_->AdvanceClockSeconds(0.001);
+ platform_->AdvanceClock(TimeDelta::FromMilliseconds(1));
StringBuilder builder;
for (int i = 0; i < new_elements; i++)
builder.Append("<span>a</span>");
@@ -85,21 +85,21 @@ class FirstMeaningfulPaintDetectorTest : public PageTestBase {
bool HadNetwork2Quiet() { return Detector().network2_quiet_reached_; }
void ClearFirstPaintSwapPromise() {
- platform_->AdvanceClockSeconds(0.001);
+ platform_->AdvanceClock(TimeDelta::FromMilliseconds(1));
GetPaintTiming().ReportSwapTime(PaintEvent::kFirstPaint,
WebLayerTreeView::SwapResult::kDidSwap,
CurrentTimeTicks());
}
void ClearFirstContentfulPaintSwapPromise() {
- platform_->AdvanceClockSeconds(0.001);
+ platform_->AdvanceClock(TimeDelta::FromMilliseconds(1));
GetPaintTiming().ReportSwapTime(PaintEvent::kFirstContentfulPaint,
WebLayerTreeView::SwapResult::kDidSwap,
CurrentTimeTicks());
}
void ClearProvisionalFirstMeaningfulPaintSwapPromise() {
- platform_->AdvanceClockSeconds(0.001);
+ platform_->AdvanceClock(TimeDelta::FromMilliseconds(1));
ClearProvisionalFirstMeaningfulPaintSwapPromise(CurrentTimeTicks());
}
@@ -128,10 +128,12 @@ class FirstMeaningfulPaintDetectorTest : public PageTestBase {
ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
platform_;
- static constexpr double kNetwork0QuietWindowSeconds =
- FirstMeaningfulPaintDetector::kNetwork0QuietWindowSeconds;
- static constexpr double kNetwork2QuietWindowSeconds =
- FirstMeaningfulPaintDetector::kNetwork2QuietWindowSeconds;
+ TimeDelta GetNetwork0QuietWindowTimeout() {
+ return FirstMeaningfulPaintDetector::kNetwork0QuietWindowTimeout;
+ }
+ TimeDelta GetNetwork2QuietWindowTimeout() {
+ return FirstMeaningfulPaintDetector::kNetwork2QuietWindowTimeout;
+ }
};
TEST_F(FirstMeaningfulPaintDetectorTest, NoFirstPaint) {
@@ -260,7 +262,7 @@ TEST_F(FirstMeaningfulPaintDetectorTest,
SimulateLayoutAndPaint(10);
EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 1U);
ClearProvisionalFirstMeaningfulPaintSwapPromise();
- platform_->AdvanceClockSeconds(0.001);
+ platform_->AdvanceClock(TimeDelta::FromMilliseconds(1));
MarkFirstContentfulPaintAndClearSwapPromise();
SimulateNetworkStable();
EXPECT_GE(GetPaintTiming().FirstMeaningfulPaintRendered(),
@@ -329,16 +331,18 @@ TEST_F(FirstMeaningfulPaintDetectorTest, Network0QuietTimer) {
EXPECT_FALSE(IsNetwork0QuietTimerActive());
SetActiveConnections(0);
- platform_->RunForPeriodSeconds(kNetwork0QuietWindowSeconds - 0.1);
+ platform_->RunForPeriod(GetNetwork0QuietWindowTimeout() -
+ TimeDelta::FromMilliseconds(100));
EXPECT_TRUE(IsNetwork0QuietTimerActive());
EXPECT_FALSE(HadNetwork0Quiet());
SetActiveConnections(0); // This should reset the 0-quiet timer.
- platform_->RunForPeriodSeconds(kNetwork0QuietWindowSeconds - 0.1);
+ platform_->RunForPeriod(GetNetwork0QuietWindowTimeout() -
+ TimeDelta::FromMilliseconds(100));
EXPECT_TRUE(IsNetwork0QuietTimerActive());
EXPECT_FALSE(HadNetwork0Quiet());
- platform_->RunForPeriodSeconds(0.1001);
+ platform_->RunForPeriod(TimeDelta::FromMicroseconds(100100));
EXPECT_TRUE(HadNetwork0Quiet());
}
@@ -349,17 +353,19 @@ TEST_F(FirstMeaningfulPaintDetectorTest, Network2QuietTimer) {
EXPECT_FALSE(IsNetwork2QuietTimerActive());
SetActiveConnections(2);
- platform_->RunForPeriodSeconds(kNetwork2QuietWindowSeconds - 0.1);
+ platform_->RunForPeriod(GetNetwork2QuietWindowTimeout() -
+ TimeDelta::FromMilliseconds(100));
EXPECT_TRUE(IsNetwork2QuietTimerActive());
EXPECT_FALSE(HadNetwork2Quiet());
SetActiveConnections(2); // This should reset the 2-quiet timer.
- platform_->RunForPeriodSeconds(kNetwork2QuietWindowSeconds - 0.1);
+ platform_->RunForPeriod(GetNetwork2QuietWindowTimeout() -
+ TimeDelta::FromMilliseconds(100));
EXPECT_TRUE(IsNetwork2QuietTimerActive());
EXPECT_FALSE(HadNetwork2Quiet());
SetActiveConnections(1); // This should not reset the 2-quiet timer.
- platform_->RunForPeriodSeconds(0.1001);
+ platform_->RunForPeriod(TimeDelta::FromMicroseconds(100100));
EXPECT_TRUE(HadNetwork2Quiet());
}
@@ -408,7 +414,7 @@ TEST_F(FirstMeaningfulPaintDetectorTest,
MarkFirstContentfulPaintAndClearSwapPromise();
SimulateLayoutAndPaint(1);
EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 1U);
- platform_->AdvanceClockSeconds(0.001);
+ platform_->AdvanceClock(TimeDelta::FromMilliseconds(1));
SimulateLayoutAndPaint(10);
EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 2U);
// Having outstanding swap promises should defer setting FMP.
@@ -438,7 +444,7 @@ TEST_F(FirstMeaningfulPaintDetectorTest,
EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 1U);
ClearProvisionalFirstMeaningfulPaintSwapPromise();
TimeTicks after_first_meaningful_paint_candidate = AdvanceClockAndGetTime();
- platform_->AdvanceClockSeconds(0.001);
+ platform_->AdvanceClock(TimeDelta::FromMilliseconds(1));
GetPaintTiming().MarkFirstContentfulPaint();
// FCP > FMP candidate, but still waiting for FCP swap.
SimulateNetworkStable();
@@ -467,14 +473,14 @@ TEST_F(FirstMeaningfulPaintDetectorTest,
// Simulate only network 2-quiet so provisional FMP will be set on next
// layout.
TimeTicks pre_stable_timestamp = AdvanceClockAndGetTime();
- platform_->AdvanceClockSeconds(0.001);
+ platform_->AdvanceClock(TimeDelta::FromMilliseconds(1));
SimulateNetwork2Quiet();
EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaintRendered(), TimeTicks());
EXPECT_EQ(GetPaintTiming().FirstMeaningfulPaint(), TimeTicks());
// Force another FMP candidate while there is a pending swap promise and the
// network 2-quiet FMP non-swap timestamp is set.
- platform_->AdvanceClockSeconds(0.001);
+ platform_->AdvanceClock(TimeDelta::FromMilliseconds(1));
SimulateLayoutAndPaint(10);
EXPECT_EQ(OutstandingDetectorSwapPromiseCount(), 1U);
diff --git a/chromium/third_party/blink/renderer/core/paint/float_clip_recorder.cc b/chromium/third_party/blink/renderer/core/paint/float_clip_recorder.cc
deleted file mode 100644
index 4d79a42883c..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/float_clip_recorder.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/paint/float_clip_recorder.h"
-
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/float_clip_display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-
-namespace blink {
-
-FloatClipRecorder::FloatClipRecorder(GraphicsContext& context,
- const DisplayItemClient& client,
- PaintPhase paint_phase,
- const FloatRect& clip_rect)
- : FloatClipRecorder(context,
- client,
- DisplayItem::PaintPhaseToFloatClipType(paint_phase),
- clip_rect) {}
-
-FloatClipRecorder::FloatClipRecorder(GraphicsContext& context,
- const DisplayItemClient& client,
- DisplayItem::Type clip_type,
- const FloatRect& clip_rect)
- : context_(context), client_(client), clip_type_(clip_type) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
- context_.GetPaintController().CreateAndAppend<FloatClipDisplayItem>(
- client_, clip_type_, clip_rect);
-}
-
-FloatClipRecorder::~FloatClipRecorder() {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
- DisplayItem::Type end_type =
- DisplayItem::FloatClipTypeToEndFloatClipType(clip_type_);
- context_.GetPaintController().EndItem<EndFloatClipDisplayItem>(client_,
- end_type);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/float_clip_recorder.h b/chromium/third_party/blink/renderer/core/paint/float_clip_recorder.h
deleted file mode 100644
index 0700c565b12..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/float_clip_recorder.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_FLOAT_CLIP_RECORDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_FLOAT_CLIP_RECORDER_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/core/paint/paint_phase.h"
-#include "third_party/blink/renderer/platform/geometry/float_rect.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class FloatClipRecorder {
- USING_FAST_MALLOC(FloatClipRecorder);
-
- public:
- FloatClipRecorder(GraphicsContext&,
- const DisplayItemClient&,
- PaintPhase,
- const FloatRect&);
- FloatClipRecorder(GraphicsContext&,
- const DisplayItemClient&,
- DisplayItem::Type,
- const FloatRect&);
-
- ~FloatClipRecorder();
-
- private:
- GraphicsContext& context_;
- const DisplayItemClient& client_;
- DisplayItem::Type clip_type_;
- DISALLOW_COPY_AND_ASSIGN(FloatClipRecorder);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_FLOAT_CLIP_RECORDER_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/fragment_data.cc b/chromium/third_party/blink/renderer/core/paint/fragment_data.cc
index 3c2ddafd306..77d262bef5d 100644
--- a/chromium/third_party/blink/renderer/core/paint/fragment_data.cc
+++ b/chromium/third_party/blink/renderer/core/paint/fragment_data.cc
@@ -11,9 +11,7 @@ namespace blink {
// These are defined here because of PaintLayer dependency.
-FragmentData::RareData::RareData(const LayoutPoint& location_in_backing)
- : unique_id(NewUniqueObjectId()),
- location_in_backing(location_in_backing) {}
+FragmentData::RareData::RareData() : unique_id(NewUniqueObjectId()) {}
FragmentData::RareData::~RareData() = default;
@@ -25,7 +23,7 @@ FragmentData& FragmentData::EnsureNextFragment() {
FragmentData::RareData& FragmentData::EnsureRareData() {
if (!rare_data_)
- rare_data_ = std::make_unique<RareData>(visual_rect_.Location());
+ rare_data_ = std::make_unique<RareData>();
return *rare_data_;
}
diff --git a/chromium/third_party/blink/renderer/core/paint/fragment_data.h b/chromium/third_party/blink/renderer/core/paint/fragment_data.h
index 0d848d7c3ab..4bd3b3198d2 100644
--- a/chromium/third_party/blink/renderer/core/paint/fragment_data.h
+++ b/chromium/third_party/blink/renderer/core/paint/fragment_data.h
@@ -24,13 +24,9 @@ class CORE_EXPORT FragmentData {
void ClearNextFragment() { next_fragment_.reset(); }
// Visual offset of this fragment's top-left position from the
- // "paint offset root":
- // - In SPv1 mode, this is the containing composited PaintLayer, or
- // PaintLayer with a transform, whichever is nearer along the containing
- // block chain.
- // - In SPv2 mode, this is the containing root PaintLayer of the
- // root LocalFrameView, or PaintLayer with a transform, whichever is nearer
- // along the containing block chain.
+ // "paint offset root" which is the containing root PaintLayer of the root
+ // LocalFrameView, or PaintLayer with a transform, whichever is nearer along
+ // the containing block chain.
LayoutPoint PaintOffset() const { return paint_offset_; }
void SetPaintOffset(const LayoutPoint& paint_offset) {
paint_offset_ = paint_offset;
@@ -39,6 +35,8 @@ class CORE_EXPORT FragmentData {
// The visual rect computed by the latest paint invalidation.
// This rect does *not* account for composited scrolling. See LayoutObject::
// AdjustVisualRectForCompositedScrolling().
+ // It's location may be different from PaintOffset when there is visual (ink)
+ // overflow to the top and/or the left.
LayoutRect VisualRect() const { return visual_rect_; }
void SetVisualRect(const LayoutRect& rect) { visual_rect_ = rect; }
@@ -54,17 +52,6 @@ class CORE_EXPORT FragmentData {
}
void SetLayer(std::unique_ptr<PaintLayer>);
- // See PaintInvalidatorContext::old_location for details. This will be removed
- // for SPv2.
- LayoutPoint LocationInBacking() const {
- return rare_data_ ? rare_data_->location_in_backing
- : visual_rect_.Location();
- }
- void SetLocationInBacking(const LayoutPoint& location) {
- if (rare_data_ || location != visual_rect_.Location())
- EnsureRareData().location_in_backing = location;
- }
-
// Visual rect of the selection on this object, in the same coordinate space
// as DisplayItemClient::VisualRect().
LayoutRect SelectionVisualRect() const {
@@ -75,12 +62,31 @@ class CORE_EXPORT FragmentData {
EnsureRareData().selection_visual_rect = r;
}
- LayoutRect PartialInvalidationRect() const {
- return rare_data_ ? rare_data_->partial_invalidation_rect : LayoutRect();
+ // Covers the sub-rectangles of the object that need to be re-rastered, in the
+ // object's local coordinate space. During PrePaint, the rect mapped into
+ // visual rect space will be added into PartialInvalidationVisualRect(), and
+ // cleared.
+ LayoutRect PartialInvalidationLocalRect() const {
+ return rare_data_ ? rare_data_->partial_invalidation_local_rect
+ : LayoutRect();
+ }
+ // LayoutObject::InvalidatePaintRectangle() calls this method to accumulate
+ // the sub-rectangles needing re-rasterization.
+ void SetPartialInvalidationLocalRect(const LayoutRect& r) {
+ if (rare_data_ || !r.IsEmpty())
+ EnsureRareData().partial_invalidation_local_rect = r;
+ }
+
+ // Covers the sub-rectangles of the object that need to be re-rastered, in
+ // visual rect space (see VisualRect()). It will be cleared after the raster
+ // invalidation is issued after paint.
+ LayoutRect PartialInvalidationVisualRect() const {
+ return rare_data_ ? rare_data_->partial_invalidation_visual_rect
+ : LayoutRect();
}
- void SetPartialInvalidationRect(const LayoutRect& r) {
+ void SetPartialInvalidationVisualRect(const LayoutRect& r) {
if (rare_data_ || !r.IsEmpty())
- EnsureRareData().partial_invalidation_rect = r;
+ EnsureRareData().partial_invalidation_visual_rect = r;
}
LayoutUnit LogicalTopInFlowThread() const {
@@ -164,7 +170,7 @@ class CORE_EXPORT FragmentData {
rare_data_->local_border_box_properties =
std::make_unique<RefCountedPropertyTreeState>(state);
} else {
- *rare_data_->local_border_box_properties = std::move(state);
+ *rare_data_->local_border_box_properties = state;
}
}
@@ -211,16 +217,16 @@ class CORE_EXPORT FragmentData {
USING_FAST_MALLOC(RareData);
public:
- RareData(const LayoutPoint& location_in_backing);
+ RareData();
~RareData();
// The following data fields are not fragment specific. Placed here just to
// avoid separate data structure for them.
std::unique_ptr<PaintLayer> layer;
UniqueObjectId unique_id;
- LayoutPoint location_in_backing;
LayoutRect selection_visual_rect;
- LayoutRect partial_invalidation_rect;
+ LayoutRect partial_invalidation_local_rect;
+ LayoutRect partial_invalidation_visual_rect;
// Fragment specific data.
LayoutPoint pagination_offset;
diff --git a/chromium/third_party/blink/renderer/core/paint/fragment_data_test.cc b/chromium/third_party/blink/renderer/core/paint/fragment_data_test.cc
index bef2197d3f8..87822ad0a54 100644
--- a/chromium/third_party/blink/renderer/core/paint/fragment_data_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/fragment_data_test.cc
@@ -12,31 +12,23 @@ class FragmentDataTest : public RenderingTest {
bool HasRareData(const FragmentData& data) { return !!data.rare_data_; }
};
-TEST_F(FragmentDataTest, LocationInBackingAndSelectionVisualRect) {
+TEST_F(FragmentDataTest, SelectionVisualRect) {
FragmentData fragment;
- // Default LocationInBacking and SelectionVisualRect should not create
- // RareData.
+ // Default SelectionVisualRect should not create RareData.
fragment.SetVisualRect(LayoutRect(10, 20, 30, 400));
- fragment.SetLocationInBacking(LayoutPoint(10, 20));
fragment.SetSelectionVisualRect(LayoutRect());
EXPECT_FALSE(HasRareData(fragment));
- EXPECT_EQ(LayoutPoint(10, 20), fragment.LocationInBacking());
EXPECT_EQ(LayoutRect(), fragment.SelectionVisualRect());
- // Non-Default LocationInBacking and SelectionVisualRect create RareData.
- fragment.SetLocationInBacking(LayoutPoint(20, 30));
+ // Non-Default SelectionVisualRect creates RareData.
fragment.SetSelectionVisualRect(LayoutRect(1, 2, 3, 4));
EXPECT_TRUE(HasRareData(fragment));
- EXPECT_EQ(LayoutPoint(20, 30), fragment.LocationInBacking());
EXPECT_EQ(LayoutRect(1, 2, 3, 4), fragment.SelectionVisualRect());
- // PaintProperties should store default LocationInBacking and
- // SelectionVisualRect once it's created.
- fragment.SetLocationInBacking(LayoutPoint(10, 20));
+ // PaintProperties should store default SelectionVisualRect once it's created.
fragment.SetSelectionVisualRect(LayoutRect());
EXPECT_TRUE(HasRareData(fragment));
- EXPECT_EQ(LayoutPoint(10, 20), fragment.LocationInBacking());
EXPECT_EQ(LayoutRect(), fragment.SelectionVisualRect());
}
diff --git a/chromium/third_party/blink/renderer/core/paint/frame_painter.cc b/chromium/third_party/blink/renderer/core/paint/frame_painter.cc
index dcf5389d761..12b6df67135 100644
--- a/chromium/third_party/blink/renderer/core/paint/frame_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/frame_painter.cc
@@ -4,26 +4,20 @@
#include "third_party/blink/renderer/core/paint/frame_painter.h"
-#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
-#include "third_party/blink/renderer/core/layout/layout_scrollbar_part.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/frame_paint_timing.h"
-#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_painter.h"
#include "third_party/blink/renderer/core/paint/scrollbar_painter.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
#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/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
+#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
-#include "third_party/blink/renderer/platform/scroll/scrollbar_theme.h"
namespace blink {
@@ -37,35 +31,14 @@ void FramePainter::Paint(GraphicsContext& context,
GetFrameView().NotifyPageThatContentAreaWillPaint();
- IntRect document_dirty_rect;
- IntPoint frame_view_location(GetFrameView().Location());
- IntRect visible_area_without_scrollbars(frame_view_location,
- GetFrameView().VisibleContentSize());
- IntPoint content_offset =
- -frame_view_location + GetFrameView().ScrollOffsetInt();
- document_dirty_rect = rect.rect_;
- document_dirty_rect.Intersect(visible_area_without_scrollbars);
- document_dirty_rect.MoveBy(content_offset);
-
- bool should_paint_contents = !document_dirty_rect.IsEmpty();
- bool should_paint_scrollbars = !GetFrameView().ScrollbarsSuppressed() &&
- (GetFrameView().HorizontalScrollbar() ||
- GetFrameView().VerticalScrollbar());
- if (!should_paint_contents && !should_paint_scrollbars)
+ IntRect document_dirty_rect(rect.Rect());
+ document_dirty_rect.Intersect(GetFrameView().FrameRect());
+ document_dirty_rect.MoveBy(-GetFrameView().Location());
+
+ if (document_dirty_rect.IsEmpty())
return;
- if (should_paint_contents) {
- TransformRecorder transform_recorder(
- context, *GetFrameView().GetLayoutView(),
- AffineTransform::Translation(
- frame_view_location.X() - GetFrameView().ScrollX(),
- frame_view_location.Y() - GetFrameView().ScrollY()));
-
- ClipRecorder clip_recorder(context, *GetFrameView().GetLayoutView(),
- DisplayItem::kClipFrameToVisibleContentRect,
- GetFrameView().VisibleContentRect());
- PaintContents(context, global_paint_flags, document_dirty_rect);
- }
+ PaintContents(context, global_paint_flags, document_dirty_rect);
}
void FramePainter::PaintContents(GraphicsContext& context,
@@ -151,75 +124,6 @@ void FramePainter::PaintContents(GraphicsContext& context,
probe::didPaint(layout_view->GetFrame(), nullptr, context, LayoutRect(rect));
}
-void FramePainter::PaintScrollbars(GraphicsContext& context,
- const IntRect& rect) {
- if (GetFrameView().HorizontalScrollbar() &&
- !GetFrameView().LayerForHorizontalScrollbar())
- PaintScrollbar(context, *GetFrameView().HorizontalScrollbar(), rect);
-
- if (GetFrameView().VerticalScrollbar() &&
- !GetFrameView().LayerForVerticalScrollbar())
- PaintScrollbar(context, *GetFrameView().VerticalScrollbar(), rect);
-
- if (!GetFrameView().LayerForScrollCorner() &&
- GetFrameView().IsScrollCornerVisible())
- PaintScrollCorner(context, GetFrameView().ScrollCornerRect());
-}
-
-void FramePainter::PaintScrollCorner(GraphicsContext& context,
- const IntRect& corner_rect) {
- if (const auto* scroll_corner = GetFrameView().ScrollCorner()) {
- bool needs_background = GetFrameView().GetFrame().IsMainFrame();
- if (needs_background &&
- !DrawingRecorder::UseCachedDrawingIfPossible(
- context, *scroll_corner, DisplayItem::kScrollbarBackground)) {
- DrawingRecorder recorder(context, *scroll_corner,
- DisplayItem::kScrollbarBackground);
- context.FillRect(corner_rect, GetFrameView().BaseBackgroundColor());
- }
- ScrollbarPainter::PaintIntoRect(*scroll_corner, context,
- corner_rect.Location(),
- LayoutRect(corner_rect));
- return;
- }
-
- ScrollbarTheme* theme = nullptr;
-
- if (GetFrameView().HorizontalScrollbar()) {
- theme = &GetFrameView().HorizontalScrollbar()->GetTheme();
- } else if (GetFrameView().VerticalScrollbar()) {
- theme = &GetFrameView().VerticalScrollbar()->GetTheme();
- } else {
- NOTREACHED();
- }
-
- const DisplayItemClient* client;
- if (auto* graphics_layer = GetFrameView().LayerForScrollCorner())
- client = graphics_layer;
- else
- client = GetFrameView().GetLayoutView();
- theme->PaintScrollCorner(context, *client, corner_rect);
-}
-
-void FramePainter::PaintScrollbar(GraphicsContext& context,
- Scrollbar& bar,
- const IntRect& rect) {
- bool needs_background =
- bar.IsCustomScrollbar() && GetFrameView().GetFrame().IsMainFrame();
- if (needs_background) {
- IntRect to_fill = bar.FrameRect();
- to_fill.Intersect(rect);
- if (!to_fill.IsEmpty() &&
- !DrawingRecorder::UseCachedDrawingIfPossible(
- context, bar, DisplayItem::kScrollbarBackground)) {
- DrawingRecorder recorder(context, bar, DisplayItem::kScrollbarBackground);
- context.FillRect(to_fill, GetFrameView().BaseBackgroundColor());
- }
- }
-
- bar.Paint(context, CullRect(rect));
-}
-
const LocalFrameView& FramePainter::GetFrameView() {
DCHECK(frame_view_);
return *frame_view_;
diff --git a/chromium/third_party/blink/renderer/core/paint/frame_painter.h b/chromium/third_party/blink/renderer/core/paint/frame_painter.h
index 798f3a6d443..cf756c96740 100644
--- a/chromium/third_party/blink/renderer/core/paint/frame_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/frame_painter.h
@@ -15,7 +15,6 @@ class CullRect;
class GraphicsContext;
class IntRect;
class LocalFrameView;
-class Scrollbar;
class FramePainter {
STACK_ALLOCATED();
@@ -25,13 +24,9 @@ class FramePainter {
: frame_view_(&frame_view) {}
void Paint(GraphicsContext&, const GlobalPaintFlags, const CullRect&);
- void PaintScrollbars(GraphicsContext&, const IntRect&);
void PaintContents(GraphicsContext&, const GlobalPaintFlags, const IntRect&);
- void PaintScrollCorner(GraphicsContext&, const IntRect& corner_rect);
private:
- void PaintScrollbar(GraphicsContext&, Scrollbar&, const IntRect&);
-
const LocalFrameView& GetFrameView();
Member<const LocalFrameView> frame_view_;
diff --git a/chromium/third_party/blink/renderer/core/paint/frame_set_painter.cc b/chromium/third_party/blink/renderer/core/paint/frame_set_painter.cc
index 18b01b4aa5f..ac119bf960a 100644
--- a/chromium/third_party/blink/renderer/core/paint/frame_set_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/frame_set_painter.cc
@@ -82,7 +82,7 @@ static bool ShouldPaintBorderAfter(const LayoutFrameSet::GridAxis& axis,
}
void FrameSetPainter::PaintBorders(const PaintInfo& paint_info,
- const LayoutPoint& adjusted_paint_offset) {
+ const LayoutPoint& paint_offset) {
if (DrawingRecorder::UseCachedDrawingIfPossible(
paint_info.context, layout_frame_set_, paint_info.phase))
return;
@@ -104,10 +104,10 @@ void FrameSetPainter::PaintBorders(const PaintInfo& paint_info,
x_pos += layout_frame_set_.Columns().sizes_[c];
if (ShouldPaintBorderAfter(layout_frame_set_.Columns(), c)) {
PaintColumnBorder(
- paint_info, PixelSnappedIntRect(LayoutRect(
- adjusted_paint_offset.X() + x_pos,
- adjusted_paint_offset.Y() + y_pos, border_thickness,
- layout_frame_set_.Size().Height() - y_pos)));
+ paint_info,
+ PixelSnappedIntRect(LayoutRect(
+ paint_offset.X() + x_pos, paint_offset.Y() + y_pos,
+ border_thickness, layout_frame_set_.Size().Height() - y_pos)));
x_pos += border_thickness;
}
child = child->NextSibling();
@@ -116,18 +116,16 @@ void FrameSetPainter::PaintBorders(const PaintInfo& paint_info,
}
y_pos += layout_frame_set_.Rows().sizes_[r];
if (ShouldPaintBorderAfter(layout_frame_set_.Rows(), r)) {
- PaintRowBorder(
- paint_info,
- PixelSnappedIntRect(LayoutRect(
- adjusted_paint_offset.X(), adjusted_paint_offset.Y() + y_pos,
- layout_frame_set_.Size().Width(), border_thickness)));
+ PaintRowBorder(paint_info,
+ PixelSnappedIntRect(LayoutRect(
+ paint_offset.X(), paint_offset.Y() + y_pos,
+ layout_frame_set_.Size().Width(), border_thickness)));
y_pos += border_thickness;
}
}
}
-void FrameSetPainter::PaintChildren(const PaintInfo& paint_info,
- const LayoutPoint& adjusted_paint_offset) {
+void FrameSetPainter::PaintChildren(const PaintInfo& paint_info) {
// Paint only those children that fit in the grid.
// Remaining frames are "hidden".
// See also LayoutFrameSet::positionFrames.
@@ -140,7 +138,7 @@ void FrameSetPainter::PaintChildren(const PaintInfo& paint_info,
// not LayoutObject.
if (!child->IsBoxModelObject() ||
!ToLayoutBoxModelObject(child)->HasSelfPaintingLayer())
- child->Paint(paint_info, adjusted_paint_offset);
+ child->Paint(paint_info);
child = child->NextSibling();
if (!child)
return;
@@ -148,8 +146,7 @@ void FrameSetPainter::PaintChildren(const PaintInfo& paint_info,
}
}
-void FrameSetPainter::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void FrameSetPainter::Paint(const PaintInfo& paint_info) {
if (paint_info.phase != PaintPhase::kForeground)
return;
@@ -157,12 +154,10 @@ void FrameSetPainter::Paint(const PaintInfo& paint_info,
if (!child)
return;
- AdjustPaintOffsetScope adjustment(layout_frame_set_, paint_info,
- paint_offset);
+ AdjustPaintOffsetScope adjustment(layout_frame_set_, paint_info);
const auto& local_paint_info = adjustment.GetPaintInfo();
- auto adjusted_paint_offset = adjustment.AdjustedPaintOffset();
- PaintChildren(local_paint_info, adjusted_paint_offset);
- PaintBorders(local_paint_info, adjusted_paint_offset);
+ PaintChildren(local_paint_info);
+ PaintBorders(local_paint_info, adjustment.PaintOffset());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/frame_set_painter.h b/chromium/third_party/blink/renderer/core/paint/frame_set_painter.h
index d8bc17c9de2..126f26d4639 100644
--- a/chromium/third_party/blink/renderer/core/paint/frame_set_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/frame_set_painter.h
@@ -9,8 +9,8 @@
namespace blink {
-class IntRect;
struct PaintInfo;
+class IntRect;
class LayoutFrameSet;
class LayoutPoint;
@@ -21,12 +21,11 @@ class FrameSetPainter {
FrameSetPainter(const LayoutFrameSet& layout_frame_set)
: layout_frame_set_(layout_frame_set) {}
- void Paint(const PaintInfo&, const LayoutPoint& paint_offset);
+ void Paint(const PaintInfo&);
private:
- void PaintBorders(const PaintInfo&, const LayoutPoint& adjusted_paint_offset);
- void PaintChildren(const PaintInfo&,
- const LayoutPoint& adjusted_paint_offset);
+ void PaintBorders(const PaintInfo&, const LayoutPoint& paint_offset);
+ void PaintChildren(const PaintInfo&);
void PaintRowBorder(const PaintInfo&, const IntRect&);
void PaintColumnBorder(const PaintInfo&, const IntRect&);
diff --git a/chromium/third_party/blink/renderer/core/paint/grid_painter.cc b/chromium/third_party/blink/renderer/core/paint/grid_painter.cc
index c54424f86df..74bad9d6943 100644
--- a/chromium/third_party/blink/renderer/core/paint/grid_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/grid_painter.cc
@@ -48,7 +48,7 @@ void GridPainter::PaintChildren(const PaintInfo& paint_info,
const LayoutPoint& paint_offset) {
DCHECK(!layout_grid_.NeedsLayout());
- LayoutRect local_visual_rect = LayoutRect(paint_info.GetCullRect().rect_);
+ LayoutRect local_visual_rect = LayoutRect(paint_info.GetCullRect().Rect());
local_visual_rect.MoveBy(-paint_offset);
Vector<LayoutUnit> column_positions = layout_grid_.ColumnPositions();
@@ -111,7 +111,7 @@ void GridPainter::PaintChildren(const PaintInfo& paint_info,
continue;
BlockPainter(layout_grid_)
- .PaintAllChildPhasesAtomically(*current, paint_info, paint_offset);
+ .PaintAllChildPhasesAtomically(*current, paint_info);
previous = current;
}
}
diff --git a/chromium/third_party/blink/renderer/core/paint/grid_painter.h b/chromium/third_party/blink/renderer/core/paint/grid_painter.h
index fb47f82898d..41d70b99745 100644
--- a/chromium/third_party/blink/renderer/core/paint/grid_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/grid_painter.h
@@ -19,7 +19,7 @@ class GridPainter {
public:
GridPainter(const LayoutGrid& layout_grid) : layout_grid_(layout_grid) {}
- void PaintChildren(const PaintInfo&, const LayoutPoint&);
+ void PaintChildren(const PaintInfo&, const LayoutPoint& paint_offset);
private:
const LayoutGrid& layout_grid_;
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 6827099754b..be38ebb0e88 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
@@ -50,7 +50,7 @@ void HTMLCanvasPainter::PaintReplaced(const PaintInfo& paint_info,
layer->SetIsDrawable(true);
RecordForeignLayer(
context, layout_html_canvas_, DisplayItem::kForeignLayerCanvas, layer,
- pixel_snapped_rect.Location(), pixel_snapped_rect.Size());
+ FloatPoint(pixel_snapped_rect.Location()), pixel_snapped_rect.Size());
return;
}
}
diff --git a/chromium/third_party/blink/renderer/core/paint/html_canvas_painter.h b/chromium/third_party/blink/renderer/core/paint/html_canvas_painter.h
index 56ef797dbf1..764dd346d53 100644
--- a/chromium/third_party/blink/renderer/core/paint/html_canvas_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/html_canvas_painter.h
@@ -19,7 +19,7 @@ class HTMLCanvasPainter {
public:
HTMLCanvasPainter(const LayoutHTMLCanvas& layout_html_canvas)
: layout_html_canvas_(layout_html_canvas) {}
- void PaintReplaced(const PaintInfo&, const LayoutPoint&);
+ void PaintReplaced(const PaintInfo&, const LayoutPoint& paint_offset);
private:
const LayoutHTMLCanvas& layout_html_canvas_;
diff --git a/chromium/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc
index 717d87697ce..34c5b8d0e00 100644
--- a/chromium/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/html_canvas_painter_test.cc
@@ -67,7 +67,7 @@ class HTMLCanvasPainterTestForSPv2 : public PaintControllerPaintTest {
std::unique_ptr<Canvas2DLayerBridge> MakeCanvas2DLayerBridge(
const IntSize& size) {
return std::make_unique<Canvas2DLayerBridge>(
- size, 0, Canvas2DLayerBridge::kForceAccelerationForTesting,
+ size, Canvas2DLayerBridge::kForceAccelerationForTesting,
CanvasColorParams());
}
@@ -91,7 +91,7 @@ TEST_P(HTMLCanvasPainterTestForSPv2, Canvas2DLayerAppearsInLayerTree) {
element->GetCanvasRenderingContext("2d", attributes);
IntSize size(300, 200);
std::unique_ptr<Canvas2DLayerBridge> bridge = MakeCanvas2DLayerBridge(size);
- element->CreateCanvas2DLayerBridgeForTesting(std::move(bridge), size);
+ element->SetCanvas2DLayerBridgeForTesting(std::move(bridge), size);
ASSERT_EQ(context, element->RenderingContext());
ASSERT_TRUE(context->IsComposited());
ASSERT_TRUE(element->IsAccelerated());
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 0f326b41b44..43ba924decd 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/image_painter.cc
@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/core/layout/text_run_constructor.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/paint/adjust_paint_offset_scope.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/platform/geometry/layout_point.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h"
@@ -24,16 +25,14 @@
namespace blink {
-void ImagePainter::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
- layout_image_.LayoutReplaced::Paint(paint_info, paint_offset);
+void ImagePainter::Paint(const PaintInfo& paint_info) {
+ layout_image_.LayoutReplaced::Paint(paint_info);
if (paint_info.phase == PaintPhase::kOutline)
- PaintAreaElementFocusRing(paint_info, paint_offset);
+ PaintAreaElementFocusRing(paint_info);
}
-void ImagePainter::PaintAreaElementFocusRing(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void ImagePainter::PaintAreaElementFocusRing(const PaintInfo& paint_info) {
Document& document = layout_image_.GetDocument();
if (paint_info.IsPrinting() ||
@@ -62,10 +61,9 @@ void ImagePainter::PaintAreaElementFocusRing(const PaintInfo& paint_info,
if (path.IsEmpty())
return;
- LayoutPoint adjusted_paint_offset = paint_offset;
- adjusted_paint_offset.MoveBy(layout_image_.Location());
- path.Translate(
- FloatSize(adjusted_paint_offset.X(), adjusted_paint_offset.Y()));
+ AdjustPaintOffsetScope adjustment(layout_image_, paint_info);
+ auto paint_offset = adjustment.PaintOffset();
+ path.Translate(FloatSize(paint_offset.X(), paint_offset.Y()));
if (DrawingRecorder::UseCachedDrawingIfPossible(
paint_info.context, layout_image_, DisplayItem::kImageAreaFocusRing))
@@ -79,7 +77,7 @@ void ImagePainter::PaintAreaElementFocusRing(const PaintInfo& paint_info,
paint_info.context.Save();
LayoutRect focus_rect = layout_image_.ContentBoxRect();
- focus_rect.MoveBy(adjusted_paint_offset);
+ focus_rect.MoveBy(paint_offset);
paint_info.context.Clip(PixelSnappedIntRect(focus_rect));
paint_info.context.DrawFocusRing(
path, area_element_style.GetOutlineStrokeWidthForFocusRing(),
@@ -155,7 +153,7 @@ void ImagePainter::PaintIntoRect(GraphicsContext& context,
if (!image || image->IsNull())
return;
- FloatRect src_rect = image->Rect();
+ FloatRect src_rect = FloatRect(image->Rect());
// If the content rect requires clipping, adjust |srcRect| and
// |pixelSnappedDestRect| over using a clip.
if (!content_rect.Contains(dest_rect)) {
@@ -163,8 +161,8 @@ void ImagePainter::PaintIntoRect(GraphicsContext& context,
pixel_snapped_content_rect.Intersect(pixel_snapped_dest_rect);
if (pixel_snapped_content_rect.IsEmpty())
return;
- src_rect =
- MapRect(pixel_snapped_content_rect, pixel_snapped_dest_rect, src_rect);
+ src_rect = MapRect(FloatRect(pixel_snapped_content_rect),
+ FloatRect(pixel_snapped_dest_rect), src_rect);
pixel_snapped_dest_rect = pixel_snapped_content_rect;
}
@@ -183,7 +181,7 @@ void ImagePainter::PaintIntoRect(GraphicsContext& context,
image->paint_image_id())
: Image::kUnspecifiedDecode;
context.DrawImage(
- image.get(), decode_mode, pixel_snapped_dest_rect, &src_rect,
+ image.get(), decode_mode, FloatRect(pixel_snapped_dest_rect), &src_rect,
SkBlendMode::kSrcOver,
LayoutObject::ShouldRespectImageOrientation(&layout_image_));
}
diff --git a/chromium/third_party/blink/renderer/core/paint/image_painter.h b/chromium/third_party/blink/renderer/core/paint/image_painter.h
index 538db44e052..fb08ac9c331 100644
--- a/chromium/third_party/blink/renderer/core/paint/image_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/image_painter.h
@@ -9,8 +9,8 @@
namespace blink {
-class GraphicsContext;
struct PaintInfo;
+class GraphicsContext;
class LayoutPoint;
class LayoutRect;
class LayoutImage;
@@ -21,7 +21,7 @@ class ImagePainter {
public:
ImagePainter(const LayoutImage& layout_image) : layout_image_(layout_image) {}
- void Paint(const PaintInfo&, const LayoutPoint& paint_offset);
+ void Paint(const PaintInfo&);
void PaintReplaced(const PaintInfo&, const LayoutPoint& paint_offset);
// Paint the image into |destRect|, after clipping by |contentRect|. Both
@@ -32,8 +32,7 @@ class ImagePainter {
const LayoutRect& content_rect);
private:
- void PaintAreaElementFocusRing(const PaintInfo&,
- const LayoutPoint& paint_offset);
+ void PaintAreaElementFocusRing(const PaintInfo&);
const LayoutImage& layout_image_;
};
diff --git a/chromium/third_party/blink/renderer/core/paint/inline_flow_box_painter.cc b/chromium/third_party/blink/renderer/core/paint/inline_flow_box_painter.cc
index d7107d75b67..004830e5a87 100644
--- a/chromium/third_party/blink/renderer/core/paint/inline_flow_box_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/inline_flow_box_painter.cc
@@ -11,7 +11,6 @@
#include "third_party/blink/renderer/core/paint/box_painter_base.h"
#include "third_party/blink/renderer/core/paint/nine_piece_image_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
-#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
@@ -80,17 +79,19 @@ void InlineFlowBoxPainter::PaintFillLayer(const PaintInfo& paint_info,
(!inline_flow_box_.PrevForSameLayoutObject() &&
!inline_flow_box_.NextForSameLayoutObject()) ||
!inline_flow_box_.Parent()) {
+ bool object_has_multiple_boxes = false;
box_model_painter.PaintFillLayer(paint_info, c, fill_layer, rect,
kBackgroundBleedNone, geometry, op,
- rect.Size());
+ object_has_multiple_boxes);
} else if (inline_flow_box_.GetLineLayoutItem()
.Style()
->BoxDecorationBreak() == EBoxDecorationBreak::kClone) {
GraphicsContextStateSaver state_saver(paint_info.context);
paint_info.context.Clip(PixelSnappedIntRect(rect));
+ bool object_has_multiple_boxes = false;
box_model_painter.PaintFillLayer(paint_info, c, fill_layer, rect,
kBackgroundBleedNone, geometry, op,
- rect.Size());
+ object_has_multiple_boxes);
} else {
// We have a fill image that spans multiple lines.
// FIXME: frameSize ought to be the same as rect.size().
@@ -101,9 +102,10 @@ void InlineFlowBoxPainter::PaintFillLayer(const PaintInfo& paint_info,
GraphicsContextStateSaver state_saver(paint_info.context);
// TODO(chrishtr): this should likely be pixel-snapped.
paint_info.context.Clip(PixelSnappedIntRect(rect));
+ bool object_has_multiple_boxes = true;
box_model_painter.PaintFillLayer(
paint_info, c, fill_layer, image_strip_paint_rect, kBackgroundBleedNone,
- geometry, op, rect.Size());
+ geometry, op, object_has_multiple_boxes, rect.Size());
}
}
@@ -251,6 +253,10 @@ void InlineFlowBoxPainter::PaintBoxDecorationBackground(
const PaintInfo& paint_info,
const LayoutPoint& paint_offset) {
DCHECK(paint_info.phase == PaintPhase::kForeground);
+
+ if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled())
+ RecordHitTestData(paint_info, paint_offset);
+
if (inline_flow_box_.GetLineLayoutItem().Style()->Visibility() !=
EVisibility::kVisible)
return;
@@ -282,28 +288,20 @@ void InlineFlowBoxPainter::PaintBoxDecorationBackground(
DrawingRecorder recorder(paint_info.context, inline_flow_box_,
DisplayItem::kBoxDecorationBackground);
- LayoutRect frame_rect = FrameRectClampedToLineTopAndBottomIfNeeded();
-
- // Move x/y to our coordinates.
- LayoutRect local_rect(frame_rect);
- inline_flow_box_.FlipForWritingMode(local_rect);
- LayoutPoint adjusted_paint_offset = paint_offset + local_rect.Location();
-
- LayoutRect adjusted_frame_rect =
- LayoutRect(adjusted_paint_offset, frame_rect.Size());
+ LayoutRect paint_rect = AdjustedPaintRect(paint_offset);
IntRect adjusted_clip_rect;
BorderPaintingType border_painting_type =
- GetBorderPaintType(adjusted_frame_rect, adjusted_clip_rect);
+ GetBorderPaintType(paint_rect, adjusted_clip_rect);
// Shadow comes first and is behind the background and border.
- PaintNormalBoxShadow(paint_info, *style_to_use, adjusted_frame_rect);
+ PaintNormalBoxShadow(paint_info, *style_to_use, paint_rect);
Color background_color = inline_flow_box_layout_object->ResolveColor(
*style_to_use, GetCSSPropertyBackgroundColor());
PaintFillLayers(paint_info, background_color,
- style_to_use->BackgroundLayers(), adjusted_frame_rect);
- PaintInsetBoxShadow(paint_info, *style_to_use, adjusted_frame_rect);
+ style_to_use->BackgroundLayers(), paint_rect);
+ PaintInsetBoxShadow(paint_info, *style_to_use, paint_rect);
const LayoutObject* box_model = ToLayoutBoxModelObject(
LineLayoutAPIShim::LayoutObjectFrom(inline_flow_box_.BoxModelObject()));
@@ -312,20 +310,20 @@ void InlineFlowBoxPainter::PaintBoxDecorationBackground(
case kDontPaintBorders:
break;
case kPaintBordersWithoutClip:
- BoxPainterBase::PaintBorder(
- *box_model, box_model->GetDocument(), GetNode(box_model), paint_info,
- adjusted_frame_rect,
- inline_flow_box_.GetLineLayoutItem().StyleRef(
- inline_flow_box_.IsFirstLineStyle()),
- kBackgroundBleedNone, inline_flow_box_.IncludeLogicalLeftEdge(),
- inline_flow_box_.IncludeLogicalRightEdge());
+ BoxPainterBase::PaintBorder(*box_model, box_model->GetDocument(),
+ GetNode(box_model), paint_info, paint_rect,
+ inline_flow_box_.GetLineLayoutItem().StyleRef(
+ inline_flow_box_.IsFirstLineStyle()),
+ kBackgroundBleedNone,
+ inline_flow_box_.IncludeLogicalLeftEdge(),
+ inline_flow_box_.IncludeLogicalRightEdge());
break;
case kPaintBordersWithClip:
// FIXME: What the heck do we do with RTL here? The math we're using is
// obviously not right, but it isn't even clear how this should work at
// all.
LayoutRect image_strip_paint_rect = PaintRectForImageStrip(
- adjusted_paint_offset, frame_rect.Size(), TextDirection::kLtr);
+ paint_rect.Location(), paint_rect.Size(), TextDirection::kLtr);
GraphicsContextStateSaver state_saver(paint_info.context);
paint_info.context.Clip(adjusted_clip_rect);
BoxPainterBase::PaintBorder(*box_model, box_model->GetDocument(),
@@ -354,34 +352,19 @@ void InlineFlowBoxPainter::PaintMask(const PaintInfo& paint_info,
paint_info.context, inline_flow_box_,
DisplayItem::PaintPhaseToDrawingType(paint_info.phase));
- LayoutRect frame_rect = FrameRectClampedToLineTopAndBottomIfNeeded();
-
- // Move x/y to our coordinates.
- LayoutRect local_rect(frame_rect);
- inline_flow_box_.FlipForWritingMode(local_rect);
- LayoutPoint adjusted_paint_offset = paint_offset + local_rect.Location();
+ LayoutRect paint_rect = AdjustedPaintRect(paint_offset);
const auto& mask_nine_piece_image = box_model.StyleRef().MaskBoxImage();
const auto* mask_box_image = mask_nine_piece_image.GetImage();
// Figure out if we need to push a transparency layer to render our mask.
- bool push_transparency_layer = false;
- LayoutRect paint_rect = LayoutRect(adjusted_paint_offset, frame_rect.Size());
- DCHECK(box_model.HasLayer());
- if (!box_model.Layer()->MaskBlendingAppliedByCompositor(paint_info)) {
- push_transparency_layer = true;
- FloatRect bounds(paint_rect);
- paint_info.context.BeginLayer(1.0f, SkBlendMode::kDstIn, &bounds);
- }
-
PaintFillLayers(paint_info, Color::kTransparent,
box_model.StyleRef().MaskLayers(), paint_rect);
bool has_box_image = mask_box_image && mask_box_image->CanRender();
if (!has_box_image || !mask_box_image->IsLoaded()) {
- if (push_transparency_layer)
- paint_info.context.EndLayer();
- return; // Don't paint anything while we wait for the image to load.
+ // Don't paint anything while we wait for the image to load.
+ return;
}
// The simple case is where we are the only box for this object. In those
@@ -397,7 +380,7 @@ void InlineFlowBoxPainter::PaintMask(const PaintInfo& paint_info,
// FIXME: What the heck do we do with RTL here? The math we're using is
// obviously not right, but it isn't even clear how this should work at all.
LayoutRect image_strip_paint_rect = PaintRectForImageStrip(
- adjusted_paint_offset, frame_rect.Size(), TextDirection::kLtr);
+ paint_rect.Location(), paint_rect.Size(), TextDirection::kLtr);
FloatRect clip_rect(ClipRectForNinePieceImageStrip(
inline_flow_box_, mask_nine_piece_image, paint_rect));
GraphicsContextStateSaver state_saver(paint_info.context);
@@ -408,9 +391,6 @@ void InlineFlowBoxPainter::PaintMask(const PaintInfo& paint_info,
image_strip_paint_rect, box_model.StyleRef(),
mask_nine_piece_image);
}
-
- if (push_transparency_layer)
- paint_info.context.EndLayer();
}
// This method should not be needed. See crbug.com/530659.
@@ -443,4 +423,27 @@ LayoutRect InlineFlowBoxPainter::FrameRectClampedToLineTopAndBottomIfNeeded()
return rect;
}
+LayoutRect InlineFlowBoxPainter::AdjustedPaintRect(
+ const LayoutPoint& paint_offset) const {
+ LayoutRect frame_rect = FrameRectClampedToLineTopAndBottomIfNeeded();
+ LayoutRect local_rect(frame_rect);
+ inline_flow_box_.FlipForWritingMode(local_rect);
+ LayoutPoint adjusted_paint_offset = paint_offset + local_rect.Location();
+ return LayoutRect(adjusted_paint_offset, frame_rect.Size());
+}
+
+void InlineFlowBoxPainter::RecordHitTestData(const PaintInfo& paint_info,
+ const LayoutPoint& paint_offset) {
+ LayoutObject* layout_object =
+ LineLayoutAPIShim::LayoutObjectFrom(inline_flow_box_.GetLineLayoutItem());
+
+ auto touch_action = layout_object->EffectiveWhitelistedTouchAction();
+ if (touch_action == TouchAction::kTouchActionAuto)
+ return;
+
+ HitTestData::RecordTouchActionRect(
+ paint_info.context, inline_flow_box_,
+ TouchActionRect(AdjustedPaintRect(paint_offset), touch_action));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/inline_flow_box_painter.h b/chromium/third_party/blink/renderer/core/paint/inline_flow_box_painter.h
index 33b64f5f373..f3a6ccd1113 100644
--- a/chromium/third_party/blink/renderer/core/paint/inline_flow_box_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/inline_flow_box_painter.h
@@ -71,6 +71,13 @@ class InlineFlowBoxPainter {
BorderPaintingType GetBorderPaintType(const LayoutRect& adjusted_frame_rect,
IntRect& adjusted_clip_rect) const;
+ LayoutRect AdjustedPaintRect(const LayoutPoint& paint_offset) const;
+
+ // Paint a hit test display item and record hit test data. This should be
+ // called when painting the background even if there is no other painted
+ // content.
+ void RecordHitTestData(const PaintInfo&, const LayoutPoint& paint_offset);
+
const InlineFlowBox& inline_flow_box_;
};
diff --git a/chromium/third_party/blink/renderer/core/paint/inline_painter.cc b/chromium/third_party/blink/renderer/core/paint/inline_painter.cc
index 8cb222ec020..f40a16ff8cd 100644
--- a/chromium/third_party/blink/renderer/core/paint/inline_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/inline_painter.cc
@@ -4,33 +4,52 @@
#include "third_party/blink/renderer/core/paint/inline_painter.h"
+#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
+#include "third_party/blink/renderer/core/paint/adjust_paint_offset_scope.h"
#include "third_party/blink/renderer/core/paint/line_box_list_painter.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#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/platform/geometry/layout_point.h"
namespace blink {
-void InlinePainter::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
- if (paint_info.phase == PaintPhase::kForeground && paint_info.IsPrinting())
+void InlinePainter::Paint(const PaintInfo& paint_info) {
+ AdjustPaintOffsetScope adjustment(layout_inline_, paint_info);
+ auto paint_offset = adjustment.PaintOffset();
+ const auto& local_paint_info = adjustment.GetPaintInfo();
+
+ if (RuntimeEnabledFeatures::LayoutNGEnabled()) {
+ // Inline box with self painting layer is painted in this code path.
+ if (auto* block_flow = layout_inline_.EnclosingNGBlockFlow()) {
+ if (auto* block_flow_fragment = block_flow->PaintFragment()) {
+ block_flow_fragment->PaintInlineBoxForDescendants(
+ local_paint_info, paint_offset, &layout_inline_);
+ return;
+ }
+ }
+ }
+
+ if (local_paint_info.phase == PaintPhase::kForeground &&
+ local_paint_info.IsPrinting()) {
ObjectPainter(layout_inline_)
- .AddPDFURLRectIfNeeded(paint_info, paint_offset);
+ .AddPDFURLRectIfNeeded(local_paint_info, paint_offset);
+ }
- if (ShouldPaintSelfOutline(paint_info.phase) ||
- ShouldPaintDescendantOutlines(paint_info.phase)) {
+ if (ShouldPaintSelfOutline(local_paint_info.phase) ||
+ ShouldPaintDescendantOutlines(local_paint_info.phase)) {
ObjectPainter painter(layout_inline_);
- if (ShouldPaintDescendantOutlines(paint_info.phase))
- painter.PaintInlineChildrenOutlines(paint_info, paint_offset);
- if (ShouldPaintSelfOutline(paint_info.phase) &&
+ if (ShouldPaintDescendantOutlines(local_paint_info.phase))
+ painter.PaintInlineChildrenOutlines(local_paint_info);
+ if (ShouldPaintSelfOutline(local_paint_info.phase) &&
!layout_inline_.IsElementContinuation())
- painter.PaintOutline(paint_info, paint_offset);
+ painter.PaintOutline(local_paint_info, paint_offset);
return;
}
LineBoxListPainter(*layout_inline_.LineBoxes())
- .Paint(layout_inline_, paint_info, paint_offset);
+ .Paint(layout_inline_, local_paint_info, paint_offset);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/inline_painter.h b/chromium/third_party/blink/renderer/core/paint/inline_painter.h
index da0b1cdbe65..5f8020ad9eb 100644
--- a/chromium/third_party/blink/renderer/core/paint/inline_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/inline_painter.h
@@ -10,7 +10,6 @@
namespace blink {
-class LayoutPoint;
struct PaintInfo;
class LayoutInline;
@@ -21,7 +20,7 @@ class InlinePainter {
InlinePainter(const LayoutInline& layout_inline)
: layout_inline_(layout_inline) {}
- void Paint(const PaintInfo&, const LayoutPoint& paint_offset);
+ void Paint(const PaintInfo&);
private:
const LayoutInline& layout_inline_;
diff --git a/chromium/third_party/blink/renderer/core/paint/inline_text_box_painter.cc b/chromium/third_party/blink/renderer/core/paint/inline_text_box_painter.cc
index 7a4d0820875..4e03b11e1ae 100644
--- a/chromium/third_party/blink/renderer/core/paint/inline_text_box_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/inline_text_box_painter.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/core/paint/inline_text_box_painter.h"
#include "base/optional.h"
-#include "build/build_config.h"
#include "third_party/blink/renderer/core/editing/editor.h"
#include "third_party/blink/renderer/core/editing/markers/composition_marker.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
@@ -19,6 +18,7 @@
#include "third_party/blink/renderer/core/layout/text_decoration_offset.h"
#include "third_party/blink/renderer/core/paint/applied_decoration_painter.h"
#include "third_party/blink/renderer/core/paint/decoration_info.h"
+#include "third_party/blink/renderer/core/paint/document_marker_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/selection_painting_utils.h"
#include "third_party/blink/renderer/core/paint/text_painter.h"
@@ -83,8 +83,6 @@ static LineLayoutItem EnclosingUnderlineObject(
}
}
-static const int kMisspellingLineThickness = 3;
-
LayoutObject& InlineTextBoxPainter::InlineLayoutObject() const {
return *LineLayoutAPIShim::LayoutObjectFrom(
inline_text_box_.GetLineLayoutItem());
@@ -129,16 +127,11 @@ void InlineTextBoxPainter::Paint(const PaintInfo& paint_info,
(inline_text_box_.IsHorizontal() ? paint_offset.X() : paint_offset.Y());
LayoutUnit logical_extent = logical_visual_overflow.Width();
- // We round the y-axis to ensure consistent line heights.
- LayoutPoint adjusted_paint_offset(paint_offset);
-
if (inline_text_box_.IsHorizontal()) {
- adjusted_paint_offset.SetY(LayoutUnit(adjusted_paint_offset.Y().Round()));
if (!paint_info.GetCullRect().IntersectsHorizontalRange(
logical_start, logical_start + logical_extent))
return;
} else {
- adjusted_paint_offset.SetX(LayoutUnit(adjusted_paint_offset.X().Round()));
if (!paint_info.GetCullRect().IntersectsVerticalRange(
logical_start, logical_start + logical_extent))
return;
@@ -175,6 +168,7 @@ void InlineTextBoxPainter::Paint(const PaintInfo& paint_info,
LayoutPoint box_origin(inline_text_box_.PhysicalLocation() + paint_offset);
+ // We round the y-axis to ensure consistent line heights.
if (inline_text_box_.IsHorizontal()) {
box_origin.SetY(LayoutUnit(box_origin.Y().Round()));
} else {
@@ -316,6 +310,11 @@ void InlineTextBoxPainter::Paint(const PaintInfo& paint_info,
static_cast<unsigned>(selection_end)});
selection_start = selection_offsets.start;
selection_end = selection_offsets.end;
+ if (have_selection) {
+ font.ExpandRangeToIncludePartialGlyphs(text_run, &selection_start,
+ &selection_end);
+ }
+
if (inline_text_box_.Truncation() != kCNoTruncation) {
// In a mixed-direction flow the ellipsis is at the start of the text
// rather than at the end of it.
@@ -375,7 +374,6 @@ void InlineTextBoxPainter::Paint(const PaintInfo& paint_info,
start_offset = selection_end;
end_offset = selection_start;
}
-
text_painter.Paint(start_offset, end_offset, length, text_style);
// Paint line-through decoration if needed.
@@ -388,8 +386,28 @@ void InlineTextBoxPainter::Paint(const PaintInfo& paint_info,
if ((paint_selected_text_only || paint_selected_text_separately) &&
selection_start < selection_end) {
- // paint only the text that is selected
- text_painter.Paint(selection_start, selection_end, length, selection_style);
+ // paint only the text that is selected.
+ // Because only a part of the text glyph can be selected, we need to draw
+ // the selection twice:
+ LayoutRect selection_rect =
+ GetSelectionRect<InlineTextBoxPainter::PaintOptions::kNormal>(
+ context, box_rect, style_to_use, font);
+
+ // the first time, we draw the glyphs outside the selection area, with
+ // the original style.
+ {
+ GraphicsContextStateSaver state_saver(context);
+ context.ClipOut(FloatRect(selection_rect));
+ text_painter.Paint(selection_start, selection_end, length, text_style);
+ }
+ // the second time, we draw the glyphs inside the selection area, with
+ // the selection style.
+ {
+ GraphicsContextStateSaver state_saver(context);
+ context.Clip(FloatRect(selection_rect));
+ text_painter.Paint(selection_start, selection_end, length,
+ selection_style);
+ }
}
if (paint_info.phase == PaintPhase::kForeground) {
@@ -511,87 +529,13 @@ void InlineTextBoxPainter::PaintSingleMarkerBackgroundRun(
}
DocumentMarkerVector InlineTextBoxPainter::ComputeMarkersToPaint() const {
- // We don't render composition or spelling markers that overlap suggestion
- // markers.
-
Node* const node = inline_text_box_.GetLineLayoutItem().GetNode();
if (!node)
return DocumentMarkerVector();
DocumentMarkerController& document_marker_controller =
inline_text_box_.GetLineLayoutItem().GetDocument().Markers();
-
- // Note: DocumentMarkerController::MarkersFor() returns markers sorted by
- // start offset.
- const DocumentMarkerVector& suggestion_markers =
- document_marker_controller.MarkersFor(node, DocumentMarker::kSuggestion);
- if (suggestion_markers.IsEmpty()) {
- // If there are no suggestion markers, we can return early as a minor
- // performance optimization.
- DocumentMarker::MarkerTypes remaining_types = DocumentMarker::AllMarkers();
- remaining_types.Remove(DocumentMarker::kSuggestion);
- return document_marker_controller.MarkersFor(node, remaining_types);
- }
-
- const DocumentMarkerVector& markers_overridden_by_suggestion_markers =
- document_marker_controller.MarkersFor(
- node, DocumentMarker::kComposition | DocumentMarker::kSpelling);
-
- Vector<unsigned> suggestion_starts;
- Vector<unsigned> suggestion_ends;
- for (const DocumentMarker* suggestion_marker : suggestion_markers) {
- suggestion_starts.push_back(suggestion_marker->StartOffset());
- suggestion_ends.push_back(suggestion_marker->EndOffset());
- }
-
- std::sort(suggestion_starts.begin(), suggestion_starts.end());
- std::sort(suggestion_ends.begin(), suggestion_ends.end());
-
- unsigned suggestion_starts_index = 0;
- unsigned suggestion_ends_index = 0;
- unsigned number_suggestions_currently_inside = 0;
-
- DocumentMarkerVector markers_to_paint;
- for (DocumentMarker* marker : markers_overridden_by_suggestion_markers) {
- while (suggestion_starts_index < suggestion_starts.size() &&
- suggestion_starts[suggestion_starts_index] <=
- marker->StartOffset()) {
- ++suggestion_starts_index;
- ++number_suggestions_currently_inside;
- }
- while (suggestion_ends_index < suggestion_ends.size() &&
- suggestion_ends[suggestion_ends_index] <= marker->StartOffset()) {
- ++suggestion_ends_index;
- --number_suggestions_currently_inside;
- }
-
- // At this point, number_suggestions_currently_inside should be equal to the
- // number of suggestion markers overlapping the point marker->StartOffset()
- // (marker endpoints don't count as overlapping).
-
- // Marker is overlapped by a suggestion marker, do not paint.
- if (number_suggestions_currently_inside)
- continue;
-
- // Verify that no suggestion marker starts before the current marker ends.
- if (suggestion_starts_index < suggestion_starts.size() &&
- suggestion_starts[suggestion_starts_index] < marker->EndOffset())
- continue;
-
- markers_to_paint.push_back(marker);
- }
-
- markers_to_paint.AppendVector(suggestion_markers);
-
- DocumentMarker::MarkerTypes remaining_types = DocumentMarker::AllMarkers();
- remaining_types.Remove(DocumentMarker::kComposition |
- DocumentMarker::kSpelling |
- DocumentMarker::kSuggestion);
-
- markers_to_paint.AppendVector(
- document_marker_controller.MarkersFor(node, remaining_types));
-
- return markers_to_paint;
+ return document_marker_controller.ComputeMarkersToPaint(*node);
}
void InlineTextBoxPainter::PaintDocumentMarkers(
@@ -672,149 +616,12 @@ void InlineTextBoxPainter::PaintDocumentMarkers(
}
}
-namespace {
-
-#if !defined(OS_MACOSX)
-
-static const float kMarkerWidth = 4;
-static const float kMarkerHeight = 2;
-
-sk_sp<PaintRecord> RecordMarker(DocumentMarker::MarkerType marker_type) {
- SkColor color =
- (marker_type == DocumentMarker::kGrammar)
- ? LayoutTheme::GetTheme().PlatformGrammarMarkerUnderlineColor().Rgb()
- : LayoutTheme::GetTheme()
- .PlatformSpellingMarkerUnderlineColor()
- .Rgb();
-
- // Record the path equivalent to this legacy pattern:
- // X o o X o o X
- // o X o o X o
-
- // Adjust the phase such that f' == 0 is "pixel"-centered
- // (for optimal rasterization at native rez).
- SkPath path;
- path.moveTo(kMarkerWidth * -3 / 8, kMarkerHeight * 3 / 4);
- path.cubicTo(kMarkerWidth * -1 / 8, kMarkerHeight * 3 / 4,
- kMarkerWidth * -1 / 8, kMarkerHeight * 1 / 4,
- kMarkerWidth * 1 / 8, kMarkerHeight * 1 / 4);
- path.cubicTo(kMarkerWidth * 3 / 8, kMarkerHeight * 1 / 4,
- kMarkerWidth * 3 / 8, kMarkerHeight * 3 / 4,
- kMarkerWidth * 5 / 8, kMarkerHeight * 3 / 4);
- path.cubicTo(kMarkerWidth * 7 / 8, kMarkerHeight * 3 / 4,
- kMarkerWidth * 7 / 8, kMarkerHeight * 1 / 4,
- kMarkerWidth * 9 / 8, kMarkerHeight * 1 / 4);
-
- PaintFlags flags;
- flags.setAntiAlias(true);
- flags.setColor(color);
- flags.setStyle(PaintFlags::kStroke_Style);
- flags.setStrokeWidth(kMarkerHeight * 1 / 2);
-
- PaintRecorder recorder;
- recorder.beginRecording(kMarkerWidth, kMarkerHeight);
- recorder.getRecordingCanvas()->drawPath(path, flags);
-
- return recorder.finishRecordingAsPicture();
-}
-
-#else // defined(OS_MACOSX)
-
-static const float kMarkerWidth = 4;
-static const float kMarkerHeight = 3;
-
-sk_sp<PaintRecord> RecordMarker(DocumentMarker::MarkerType marker_type) {
- SkColor color =
- (marker_type == DocumentMarker::kGrammar)
- ? LayoutTheme::GetTheme().PlatformGrammarMarkerUnderlineColor().Rgb()
- : LayoutTheme::GetTheme()
- .PlatformSpellingMarkerUnderlineColor()
- .Rgb();
-
- // Match the artwork used by the Mac.
- static const float kR = 1.5f;
-
- // top->bottom translucent gradient.
- const SkColor colors[2] = {
- SkColorSetARGB(0x48,
- SkColorGetR(color),
- SkColorGetG(color),
- SkColorGetB(color)),
- color
- };
- const SkPoint pts[2] = {
- SkPoint::Make(0, 0),
- SkPoint::Make(0, 2 * kR)
- };
-
- PaintFlags flags;
- flags.setAntiAlias(true);
- flags.setColor(color);
- flags.setShader(PaintShader::MakeLinearGradient(
- pts, colors, nullptr, ARRAY_SIZE(colors), SkShader::kClamp_TileMode));
- PaintRecorder recorder;
- recorder.beginRecording(kMarkerWidth, kMarkerHeight);
- recorder.getRecordingCanvas()->drawOval(SkRect::MakeWH(2 * kR, 2 * kR),
- flags);
- return recorder.finishRecordingAsPicture();
-}
-
-#endif // defined(OS_MACOSX)
-
-void DrawDocumentMarker(GraphicsContext& context,
- const FloatPoint& pt,
- float width,
- DocumentMarker::MarkerType marker_type,
- float zoom) {
- DCHECK(marker_type == DocumentMarker::kSpelling ||
- marker_type == DocumentMarker::kGrammar);
-
- DEFINE_STATIC_LOCAL(PaintRecord*, spelling_marker,
- (RecordMarker(DocumentMarker::kSpelling).release()));
- DEFINE_STATIC_LOCAL(PaintRecord*, grammar_marker,
- (RecordMarker(DocumentMarker::kGrammar).release()));
- auto* const marker = marker_type == DocumentMarker::kSpelling
- ? spelling_marker
- : grammar_marker;
-
- // Position already includes zoom and device scale factor.
- SkScalar origin_x = WebCoreFloatToSkScalar(pt.X());
- SkScalar origin_y = WebCoreFloatToSkScalar(pt.Y());
-
-#if defined(OS_MACOSX)
- // Make sure to draw only complete dots, and finish inside the marked text.
- width -= fmodf(width, kMarkerWidth * zoom);
-#else
- // Offset it vertically by 1 so that there's some space under the text.
- origin_y += 1;
-#endif
-
- const auto rect = SkRect::MakeWH(width, kMarkerHeight * zoom);
- const auto local_matrix = SkMatrix::MakeScale(zoom, zoom);
-
- PaintFlags flags;
- flags.setAntiAlias(true);
- flags.setShader(PaintShader::MakePaintRecord(
- sk_ref_sp(marker), FloatRect(0, 0, kMarkerWidth, kMarkerHeight),
- SkShader::kRepeat_TileMode, SkShader::kClamp_TileMode, &local_matrix));
-
- // Apply the origin translation as a global transform. This ensures that the
- // shader local matrix depends solely on zoom => Skia can reuse the same
- // cached tile for all markers at a given zoom level.
- GraphicsContextStateSaver saver(context);
- context.Translate(origin_x, origin_y);
- context.DrawRect(rect, flags);
-}
-
-} // anonymous ns
-
void InlineTextBoxPainter::PaintDocumentMarker(GraphicsContext& context,
const LayoutPoint& box_origin,
const DocumentMarker& marker,
const ComputedStyle& style,
const Font& font,
bool grammar) {
- // Never print spelling/grammar markers (5327887)
if (inline_text_box_.GetLineLayoutItem().GetDocument().Printing())
return;
@@ -857,64 +664,23 @@ void InlineTextBoxPainter::PaintDocumentMarker(GraphicsContext& context,
start = marker_rect.X() - start_point.X();
width = LayoutUnit(marker_rect.Width());
}
-
- // IMPORTANT: The misspelling underline is not considered when calculating the
- // text bounds, so we have to make sure to fit within those bounds. This
- // means the top pixel(s) of the underline will overlap the bottom pixel(s) of
- // the glyphs in smaller font sizes. The alternatives are to increase the
- // line spacing (bad!!) or decrease the underline thickness. The overlap is
- // actually the most useful, and matches what AppKit does. So, we generally
- // place the underline at the bottom of the text, but in larger fonts that's
- // not so good so we pin to two pixels under the baseline.
- int line_thickness = kMisspellingLineThickness;
-
- const SimpleFontData* font_data =
- inline_text_box_.GetLineLayoutItem()
- .Style(inline_text_box_.IsFirstLineStyle())
- ->GetFont()
- .PrimaryFont();
- DCHECK(font_data);
- int baseline = font_data ? font_data->GetFontMetrics().Ascent() : 0;
- int descent = (inline_text_box_.LogicalHeight() - baseline).ToInt();
- int underline_offset;
- if (descent <= (line_thickness + 2)) {
- // Place the underline at the very bottom of the text in small/medium fonts.
- underline_offset =
- (inline_text_box_.LogicalHeight() - line_thickness).ToInt();
- } else {
- // In larger fonts, though, place the underline up near the baseline to
- // prevent a big gap.
- underline_offset = baseline + 2;
- }
- DrawDocumentMarker(context,
- FloatPoint((box_origin.X() + start).ToFloat(),
- (box_origin.Y() + underline_offset).ToFloat()),
- width.ToFloat(), marker.GetType(), style.EffectiveZoom());
+ DocumentMarkerPainter::PaintDocumentMarker(
+ context, box_origin, style, marker.GetType(),
+ LayoutRect(start, LayoutUnit(), width, inline_text_box_.LogicalHeight()));
}
template <InlineTextBoxPainter::PaintOptions options>
-void InlineTextBoxPainter::PaintSelection(GraphicsContext& context,
- const LayoutRect& box_rect,
- const ComputedStyle& style,
- const Font& font,
- Color text_color,
- LayoutTextCombine* combined_text) {
+LayoutRect InlineTextBoxPainter::GetSelectionRect(
+ GraphicsContext& context,
+ const LayoutRect& box_rect,
+ const ComputedStyle& style,
+ const Font& font,
+ LayoutTextCombine* combined_text) {
// See if we have a selection to paint at all.
- int s_pos, e_pos;
- inline_text_box_.SelectionStartEnd(s_pos, e_pos);
- if (s_pos >= e_pos)
- return;
-
- auto layout_item = inline_text_box_.GetLineLayoutItem();
- Color c = SelectionPaintingUtils::SelectionBackgroundColor(
- layout_item.GetDocument(), layout_item.StyleRef(), layout_item.GetNode());
- if (!c.Alpha())
- return;
-
- // If the text color ends up being the same as the selection background,
- // invert the selection background.
- if (text_color == c)
- c = Color(0xff - c.Red(), 0xff - c.Green(), 0xff - c.Blue());
+ int start_pos, end_pos;
+ inline_text_box_.SelectionStartEnd(start_pos, end_pos);
+ if (start_pos >= end_pos)
+ return LayoutRect();
// If the text is truncated, let the thing being painted in the truncation
// draw its own highlight.
@@ -930,7 +696,7 @@ void InlineTextBoxPainter::PaintSelection(GraphicsContext& context,
// so we need to start after it. Otherwise we just need to make sure
// the end of the text is where the ellipsis starts.
if (ltr != flow_is_ltr)
- s_pos = std::max<int>(s_pos, inline_text_box_.Truncation());
+ start_pos = std::max<int>(start_pos, inline_text_box_.Truncation());
else
length = inline_text_box_.Truncation();
}
@@ -938,26 +704,20 @@ void InlineTextBoxPainter::PaintSelection(GraphicsContext& context,
static_cast<unsigned>(length));
StringBuilder characters_with_hyphen;
- bool respect_hyphen = e_pos == length && inline_text_box_.HasHyphen();
+ bool respect_hyphen = end_pos == length && inline_text_box_.HasHyphen();
TextRun text_run = inline_text_box_.ConstructTextRun(
style, string,
inline_text_box_.GetLineLayoutItem().TextLength() -
inline_text_box_.Start(),
respect_hyphen ? &characters_with_hyphen : nullptr);
if (respect_hyphen)
- e_pos = text_run.length();
-
- GraphicsContextStateSaver state_saver(context);
+ end_pos = text_run.length();
if (options == InlineTextBoxPainter::PaintOptions::kCombinedText) {
DCHECK(combined_text);
// We can't use the height of m_inlineTextBox because LayoutTextCombine's
// inlineTextBox is horizontal within vertical flow
combined_text->TransformToInlineCoordinates(context, box_rect, true);
- context.DrawHighlightForText(font, text_run,
- FloatPoint(box_rect.Location()),
- box_rect.Height().ToInt(), c, s_pos, e_pos);
- return;
}
LayoutUnit selection_bottom = inline_text_box_.Root().SelectionBottom();
@@ -972,7 +732,7 @@ void InlineTextBoxPainter::PaintSelection(GraphicsContext& context,
FloatPoint local_origin(box_rect.X().ToFloat(),
(box_rect.Y() - delta_y).ToFloat());
LayoutRect selection_rect = LayoutRect(font.SelectionRectForText(
- text_run, local_origin, sel_height, s_pos, e_pos));
+ text_run, local_origin, sel_height, start_pos, end_pos));
// For line breaks, just painting a selection where the line break itself
// is rendered is sufficient. Don't select it if there's an ellipsis
// there.
@@ -988,9 +748,36 @@ void InlineTextBoxPainter::PaintSelection(GraphicsContext& context,
if (!inline_text_box_.IsLeftToRightDirection() &&
inline_text_box_.IsLineBreak())
selection_rect.Move(-selection_rect.Width(), LayoutUnit());
- if (!flow_is_ltr && !ltr && inline_text_box_.Truncation() != kCNoTruncation)
+ if (!flow_is_ltr && !ltr && inline_text_box_.Truncation() != kCNoTruncation) {
selection_rect.Move(
inline_text_box_.LogicalWidth() - selection_rect.Width(), LayoutUnit());
+ }
+
+ return selection_rect;
+}
+
+template <InlineTextBoxPainter::PaintOptions options>
+void InlineTextBoxPainter::PaintSelection(GraphicsContext& context,
+ const LayoutRect& box_rect,
+ const ComputedStyle& style,
+ const Font& font,
+ Color text_color,
+ LayoutTextCombine* combined_text) {
+ auto layout_item = inline_text_box_.GetLineLayoutItem();
+ Color c = SelectionPaintingUtils::SelectionBackgroundColor(
+ layout_item.GetDocument(), layout_item.StyleRef(), layout_item.GetNode());
+ if (!c.Alpha())
+ return;
+
+ LayoutRect selection_rect =
+ GetSelectionRect<options>(context, box_rect, style, font, combined_text);
+
+ // If the text color ends up being the same as the selection background,
+ // invert the selection background.
+ if (text_color == c)
+ c = Color(0xff - c.Red(), 0xff - c.Green(), 0xff - c.Blue());
+
+ GraphicsContextStateSaver state_saver(context);
context.FillRect(FloatRect(selection_rect), c);
}
@@ -1012,61 +799,17 @@ void InlineTextBoxPainter::PaintStyleableMarkerUnderline(
const StyleableMarker& marker,
const ComputedStyle& style,
const Font& font) {
- if (marker.HasThicknessNone() ||
- (marker.UnderlineColor() == Color::kTransparent &&
- !marker.UseTextColor()))
- return;
-
if (inline_text_box_.Truncation() == kCFullTruncation)
return;
const PaintOffsets marker_offsets = MarkerPaintStartAndEnd(marker);
-
const TextRun& run = inline_text_box_.ConstructTextRun(style);
// Pass 0 for height since we only care about the width
const FloatRect& marker_rect = font.SelectionRectForText(
run, FloatPoint(), 0, marker_offsets.start, marker_offsets.end);
- // start of line to draw, relative to box_origin.X()
- LayoutUnit start = LayoutUnit(marker_rect.X());
- LayoutUnit width = LayoutUnit(marker_rect.Width());
-
- // We need to have some space between underlines of subsequent clauses,
- // because some input methods do not use different underline styles for those.
- // We make each line shorter, which has a harmless side effect of shortening
- // the first and last clauses, too.
- start += 1;
- width -= 2;
-
- // Thick marked text underlines are 2px thick as long as there is room for the
- // 2px line under the baseline. All other marked text underlines are 1px
- // thick. If there's not enough space the underline will touch or overlap
- // characters.
- int line_thickness = 1;
- const SimpleFontData* font_data =
- inline_text_box_.GetLineLayoutItem()
- .Style(inline_text_box_.IsFirstLineStyle())
- ->GetFont()
- .PrimaryFont();
- DCHECK(font_data);
- int baseline = font_data ? font_data->GetFontMetrics().Ascent() : 0;
- if (marker.HasThicknessThick() &&
- inline_text_box_.LogicalHeight() - baseline >= 2)
- line_thickness = 2;
-
- Color marker_color =
- marker.UseTextColor()
- ? inline_text_box_.GetLineLayoutItem().Style()->VisitedDependentColor(
- GetCSSPropertyWebkitTextFillColor())
- : marker.UnderlineColor();
- context.SetStrokeColor(marker_color);
-
- context.SetStrokeThickness(line_thickness);
- context.DrawLineForText(
- FloatPoint(
- box_origin.X() + start,
- (box_origin.Y() + inline_text_box_.LogicalHeight() - line_thickness)
- .ToFloat()),
- width);
+ DocumentMarkerPainter::PaintStyleableMarkerUnderline(
+ context, box_origin, marker, style, marker_rect,
+ inline_text_box_.LogicalHeight());
}
void InlineTextBoxPainter::PaintTextMatchMarkerForeground(
@@ -1085,21 +828,15 @@ void InlineTextBoxPainter::PaintTextMatchMarkerForeground(
GetTextMatchMarkerPaintOffsets(marker, inline_text_box_);
TextRun run = inline_text_box_.ConstructTextRun(style);
- Color text_color =
- LayoutTheme::GetTheme().PlatformTextSearchColor(marker.IsActiveMatch());
- if (style.VisitedDependentColor(GetCSSPropertyColor()) == text_color)
- return;
-
const SimpleFontData* font_data = font.PrimaryFont();
DCHECK(font_data);
if (!font_data)
return;
- TextPaintStyle text_style;
- text_style.current_color = text_style.fill_color = text_style.stroke_color =
- text_style.emphasis_mark_color = text_color;
- text_style.stroke_width = style.TextStrokeWidth();
- text_style.shadow = nullptr;
+ const TextPaintStyle text_style =
+ DocumentMarkerPainter::ComputeTextPaintStyleFrom(style, marker);
+ if (text_style.current_color == Color::kTransparent)
+ return;
LayoutRect box_rect(box_origin, LayoutSize(inline_text_box_.LogicalWidth(),
inline_text_box_.LogicalHeight()));
diff --git a/chromium/third_party/blink/renderer/core/paint/inline_text_box_painter.h b/chromium/third_party/blink/renderer/core/paint/inline_text_box_painter.h
index 4e93acbc97a..1749188428f 100644
--- a/chromium/third_party/blink/renderer/core/paint/inline_text_box_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/inline_text_box_painter.h
@@ -34,7 +34,7 @@ class InlineTextBoxPainter {
InlineTextBoxPainter(const InlineTextBox& inline_text_box)
: inline_text_box_(inline_text_box) {}
- void Paint(const PaintInfo&, const LayoutPoint&);
+ void Paint(const PaintInfo&, const LayoutPoint& paint_offset);
// We don't paint composition or spelling markers that overlap a suggestion
// marker (to match the native Android behavior). This method lets us throw
@@ -85,6 +85,13 @@ class InlineTextBoxPainter {
Color text_color,
LayoutTextCombine* = nullptr);
+ template <PaintOptions>
+ LayoutRect GetSelectionRect(GraphicsContext&,
+ const LayoutRect& box_rect,
+ const ComputedStyle&,
+ const Font&,
+ LayoutTextCombine* = nullptr);
+
void PaintStyleableMarkerUnderline(GraphicsContext&,
const LayoutPoint& box_origin,
const StyleableMarker&,
diff --git a/chromium/third_party/blink/renderer/core/paint/layer_clip_recorder.cc b/chromium/third_party/blink/renderer/core/paint/layer_clip_recorder.cc
deleted file mode 100644
index b40763867f2..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/layer_clip_recorder.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/paint/layer_clip_recorder.h"
-
-#include "third_party/blink/renderer/core/layout/layout_view.h"
-#include "third_party/blink/renderer/core/paint/clip_rect.h"
-#include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/platform/geometry/int_rect.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-
-namespace blink {
-
-LayerClipRecorder::LayerClipRecorder(GraphicsContext& graphics_context,
- const PaintLayer& paint_layer,
- DisplayItem::Type clip_type,
- const ClipRect& clip_rect,
- const PaintLayer* clip_root,
- const LayoutPoint& fragment_offset,
- PaintLayerFlags paint_flags,
- const DisplayItemClient& client,
- BorderRadiusClippingRule rule)
- : graphics_context_(graphics_context),
- client_(client),
- clip_type_(clip_type) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
- IntRect snapped_clip_rect = PixelSnappedIntRect(clip_rect.Rect());
-#if DCHECK_IS_ON
- // In SPv175+ mode, clip rects are pre-snapped.
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- DCHECK(FloatRect(snapped_clip_rect) == clip_rect.Rect());
-#endif
- bool painting_masks =
- (paint_flags & kPaintLayerPaintingChildClippingMaskPhase ||
- paint_flags & kPaintLayerPaintingAncestorClippingMaskPhase);
- Vector<FloatRoundedRect> rounded_rects;
- if (clip_root && (clip_rect.HasRadius() || painting_masks)) {
- CollectRoundedRectClips(paint_layer, clip_root, fragment_offset,
- painting_masks, rule, rounded_rects);
- }
-
- graphics_context_.GetPaintController().CreateAndAppend<ClipDisplayItem>(
- client_, clip_type_, snapped_clip_rect, rounded_rects);
-}
-
-static bool InContainingBlockChain(const PaintLayer* start_layer,
- const PaintLayer* end_layer) {
- if (start_layer == end_layer)
- return true;
-
- LayoutView* view = start_layer->GetLayoutObject().View();
- for (const LayoutBlock* current_block =
- start_layer->GetLayoutObject().ContainingBlock();
- current_block && current_block != view;
- current_block = current_block->ContainingBlock()) {
- if (current_block->Layer() == end_layer)
- return true;
- }
-
- return false;
-}
-
-void LayerClipRecorder::CollectRoundedRectClips(
- const PaintLayer& paint_layer,
- const PaintLayer* clip_root,
- const LayoutPoint& fragment_offset,
- bool cross_composited_scrollers,
- BorderRadiusClippingRule rule,
- Vector<FloatRoundedRect>& rounded_rect_clips) {
- // If the clip rect has been tainted by a border radius, then we have to walk
- // up our layer chain applying the clips from any layers with overflow. The
- // condition for being able to apply these clips is that the overflow object
- // be in our containing block chain so we check that also.
- for (const PaintLayer* layer = rule == kIncludeSelfForBorderRadius
- ? &paint_layer
- : paint_layer.Parent();
- layer; layer = layer->Parent()) {
- // Composited scrolling layers handle border-radius clip in the compositor
- // via a mask layer. We do not want to apply a border-radius clip to the
- // layer contents itself, because that would require re-rastering every
- // frame to update the clip. We only want to make sure that the mask layer
- // is properly clipped so that it can in turn clip the scrolled contents in
- // the compositor.
- if (!cross_composited_scrollers && layer->NeedsCompositedScrolling())
- break;
-
- // Collect clips for embedded content despite their lack of overflow,
- // because in practice they do need to clip. However, the clip is only
- // used when painting child clipping masks to avoid clipping out border
- // decorations.
- if ((layer->GetLayoutObject().HasOverflowClip() ||
- layer->GetLayoutObject().IsLayoutEmbeddedContent()) &&
- layer->GetLayoutObject().Style()->HasBorderRadius() &&
- InContainingBlockChain(&paint_layer, layer)) {
- LayoutPoint delta;
- if (layer->EnclosingPaginationLayer() ==
- paint_layer.EnclosingPaginationLayer())
- delta.MoveBy(fragment_offset);
- layer->ConvertToLayerCoords(clip_root, delta);
-
- // The PaintLayer's size is pixel-snapped if it is a LayoutBox. We can't
- // use a pre-snapped border rect for clipping, since
- // getRoundedInnerBorderFor assumes it has not been snapped yet.
- LayoutSize size(layer->GetLayoutBox()
- ? ToLayoutBox(layer->GetLayoutObject()).Size()
- : LayoutSize(layer->Size()));
- rounded_rect_clips.push_back(
- layer->GetLayoutObject().Style()->GetRoundedInnerBorderFor(
- LayoutRect(delta, size)));
- }
-
- if (layer == clip_root)
- break;
- }
-}
-
-LayerClipRecorder::~LayerClipRecorder() {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
- graphics_context_.GetPaintController().EndItem<EndClipDisplayItem>(
- client_, DisplayItem::ClipTypeToEndClipType(clip_type_));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/layer_clip_recorder.h b/chromium/third_party/blink/renderer/core/paint/layer_clip_recorder.h
deleted file mode 100644
index 5da20f489ef..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/layer_clip_recorder.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_LAYER_CLIP_RECORDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_LAYER_CLIP_RECORDER_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/paint/paint_layer_painting_info.h"
-#include "third_party/blink/renderer/core/paint/paint_phase.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-class ClipRect;
-class GraphicsContext;
-
-class CORE_EXPORT LayerClipRecorder {
- USING_FAST_MALLOC(LayerClipRecorder);
-
- public:
- enum BorderRadiusClippingRule {
- kIncludeSelfForBorderRadius,
- kDoNotIncludeSelfForBorderRadius
- };
-
- // Set rounded clip rectangles defined by border radii all the way from the
- // PaintLayerPaintingInfo "root" layer down to the specified layer (or the
- // parent of said layer, in case BorderRadiusClippingRule says to skip self).
- // fragmentOffset is used for multicol, to specify the translation required to
- // get from flow thread coordinates to visual coordinates for a certain
- // column.
- // FIXME: The BorderRadiusClippingRule parameter is really useless now. If we
- // want to skip self,
- // why not just supply the parent layer as the first parameter instead?
- // FIXME: The ClipRect passed is in visual coordinates (not flow thread
- // coordinates), but at the same time we pass a fragmentOffset, so that we can
- // translate from flow thread coordinates to visual coordinates. This may look
- // rather confusing/redundant, but it is needed for rounded border clipping.
- // Would be nice to clean up this.
- explicit LayerClipRecorder(
- GraphicsContext&,
- const PaintLayer&,
- DisplayItem::Type,
- const ClipRect&,
- const PaintLayer* clip_root,
- const LayoutPoint& fragment_offset,
- PaintLayerFlags,
- const DisplayItemClient&,
- BorderRadiusClippingRule = kIncludeSelfForBorderRadius);
-
- ~LayerClipRecorder();
-
- // Build a vector of the border radius clips that should be applied to
- // the given PaintLayer, walking up the paint layer tree to the clip_root.
- // The fragment_offset is an offset to apply to the clip to position it
- // in the required clipping coordinates (for cases when the painting
- // coordinate system is offset from the layer coordinate system).
- // cross_composited_scrollers should be true when the search for clips should
- // continue even if the clipping layer is painting into a composited scrolling
- // layer, as when painting a mask for a child of the scroller.
- // The BorderRadiusClippingRule defines whether clips on the PaintLayer itself
- // are included. Output is appended to rounded_rect_clips.
- static void CollectRoundedRectClips(
- const PaintLayer&,
- const PaintLayer* clip_root,
- const LayoutPoint& fragment_offset,
- bool cross_composited_scrollers,
- BorderRadiusClippingRule,
- Vector<FloatRoundedRect>& rounded_rect_clips);
-
- private:
- GraphicsContext& graphics_context_;
- const DisplayItemClient& client_;
- DisplayItem::Type clip_type_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_LAYER_CLIP_RECORDER_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/layer_clip_recorder_test.cc b/chromium/third_party/blink/renderer/core/paint/layer_clip_recorder_test.cc
deleted file mode 100644
index 93566326029..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/layer_clip_recorder_test.cc
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/paint/layer_clip_recorder.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/core/layout/layout_view.h"
-#include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
-#include "third_party/blink/renderer/core/paint/paint_controller_paint_test.h"
-#include "third_party/blink/renderer/core/paint/paint_layer.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"
-
-namespace blink {
-namespace {
-
-class LayerClipRecorderTest : public PaintControllerPaintTestBase {
- private:
- void SetUp() override {
- PaintControllerPaintTestBase::SetUp();
- EnableCompositing();
- }
-};
-
-void DrawEmptyClip(GraphicsContext& context,
- LayoutView& layout_view,
- PaintPhase phase) {
- LayoutRect rect(1, 1, 9, 9);
- ClipRect clip_rect(rect);
- LayerClipRecorder layer_clip_recorder(
- context, *layout_view.Compositor()->RootLayer(),
- DisplayItem::kClipLayerForeground, clip_rect, nullptr, LayoutPoint(),
- PaintLayerFlags(),
- layout_view.Compositor()->RootLayer()->GetLayoutObject());
-}
-
-void DrawRectInClip(GraphicsContext& context,
- LayoutView& layout_view,
- PaintPhase phase) {
- IntRect rect(1, 1, 9, 9);
- ClipRect clip_rect((LayoutRect(rect)));
- LayerClipRecorder layer_clip_recorder(
- context, *layout_view.Compositor()->RootLayer(),
- DisplayItem::kClipLayerForeground, clip_rect, nullptr, LayoutPoint(),
- PaintLayerFlags(),
- layout_view.Compositor()->RootLayer()->GetLayoutObject());
- if (!DrawingRecorder::UseCachedDrawingIfPossible(context, layout_view,
- phase)) {
- DrawingRecorder recorder(context, layout_view, phase);
- context.DrawRect(rect);
- }
-}
-
-TEST_F(LayerClipRecorderTest, Single) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- RootPaintController().InvalidateAll();
- GraphicsContext context(RootPaintController());
- EXPECT_EQ((size_t)0, RootPaintController().GetDisplayItemList().size());
-
- DrawRectInClip(context, GetLayoutView(), PaintPhase::kForeground);
- RootPaintController().CommitNewDisplayItems();
- EXPECT_EQ((size_t)3, RootPaintController().GetDisplayItemList().size());
- EXPECT_TRUE(DisplayItem::IsClipType(
- RootPaintController().GetDisplayItemList()[0].GetType()));
- EXPECT_TRUE(DisplayItem::IsDrawingType(
- RootPaintController().GetDisplayItemList()[1].GetType()));
- EXPECT_TRUE(DisplayItem::IsEndClipType(
- RootPaintController().GetDisplayItemList()[2].GetType()));
-}
-
-TEST_F(LayerClipRecorderTest, Empty) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- RootPaintController().InvalidateAll();
- GraphicsContext context(RootPaintController());
- EXPECT_EQ((size_t)0, RootPaintController().GetDisplayItemList().size());
-
- DrawEmptyClip(context, GetLayoutView(), PaintPhase::kForeground);
- RootPaintController().CommitNewDisplayItems();
- EXPECT_EQ((size_t)0, RootPaintController().GetDisplayItemList().size());
-}
-
-} // namespace
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/layout_object_counter.h b/chromium/third_party/blink/renderer/core/paint/layout_object_counter.h
new file mode 100644
index 00000000000..139c7ce9bb1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/layout_object_counter.h
@@ -0,0 +1,24 @@
+// 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_PAINT_LAYOUT_OBJECT_COUNTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_LAYOUT_OBJECT_COUNTER_H_
+
+namespace blink {
+
+// Used by LocalFrameView and FirstMeaningfulPaintDetector to keep track of
+// the number of layout objects created in the frame.
+class LayoutObjectCounter {
+ public:
+ void Reset() { count_ = 0; }
+ void Increment() { count_++; }
+ unsigned Count() const { return count_; }
+
+ private:
+ unsigned count_ = 0;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_FIRST_MEANINGFUL_PAINT_DETECTOR_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/line_box_list_painter.h b/chromium/third_party/blink/renderer/core/paint/line_box_list_painter.h
index 12426623ee2..d2d4b46f4fd 100644
--- a/chromium/third_party/blink/renderer/core/paint/line_box_list_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/line_box_list_painter.h
@@ -24,7 +24,7 @@ class LineBoxListPainter {
void Paint(const LayoutBoxModelObject&,
const PaintInfo&,
- const LayoutPoint&) const;
+ const LayoutPoint& paint_offset) const;
private:
const LineBoxList& line_box_list_;
diff --git a/chromium/third_party/blink/renderer/core/paint/link_highlight_impl.cc b/chromium/third_party/blink/renderer/core/paint/link_highlight_impl.cc
index cbc6115b688..683971be2ce 100644
--- a/chromium/third_party/blink/renderer/core/paint/link_highlight_impl.cc
+++ b/chromium/third_party/blink/renderer/core/paint/link_highlight_impl.cc
@@ -29,7 +29,6 @@
#include <utility>
#include "base/memory/ptr_util.h"
-#include "cc/layers/layer.h"
#include "cc/layers/picture_layer.h"
#include "cc/paint/display_item_list.h"
#include "third_party/blink/public/platform/platform.h"
@@ -39,16 +38,17 @@
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/renderer/core/dom/layout_tree_builder_traversal.h"
#include "third_party/blink/renderer/core/dom/node.h"
-#include "third_party/blink/renderer/core/exported/web_settings_impl.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/settings.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/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/layout/layout_object.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"
#include "third_party/blink/renderer/platform/animation/compositor_animation_curve.h"
#include "third_party/blink/renderer/platform/animation/compositor_float_animation_curve.h"
#include "third_party/blink/renderer/platform/animation/compositor_keyframe_model.h"
@@ -60,7 +60,6 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.h"
#include "third_party/blink/renderer/platform/layout_test_support.h"
-#include "third_party/blink/renderer/platform/wtf/time.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/skia/include/core/SkMatrix44.h"
#include "ui/gfx/geometry/rect.h"
@@ -69,33 +68,25 @@
namespace blink {
-std::unique_ptr<LinkHighlightImpl> LinkHighlightImpl::Create(
- Node* node,
- WebViewImpl* owning_web_view) {
- return base::WrapUnique(new LinkHighlightImpl(node, owning_web_view));
+std::unique_ptr<LinkHighlightImpl> LinkHighlightImpl::Create(Node* node) {
+ return base::WrapUnique(new LinkHighlightImpl(node));
}
-LinkHighlightImpl::LinkHighlightImpl(Node* node, WebViewImpl* owning_web_view)
+LinkHighlightImpl::LinkHighlightImpl(Node* node)
: node_(node),
- owning_web_view_(owning_web_view),
current_graphics_layer_(nullptr),
is_scrolling_graphics_layer_(false),
geometry_needs_update_(false),
is_animating_(false),
- start_time_(CurrentTimeTicksInSeconds()),
+ start_time_(CurrentTimeTicks()),
unique_id_(NewUniqueObjectId()) {
DCHECK(node_);
- DCHECK(owning_web_view);
content_layer_ = cc::PictureLayer::Create(this);
- clip_layer_ = cc::Layer::Create();
- clip_layer_->SetTransformOrigin(FloatPoint3D());
- clip_layer_->AddChild(content_layer_);
+ content_layer_->SetTransformOrigin(FloatPoint3D());
compositor_animation_ = CompositorAnimation::Create();
DCHECK(compositor_animation_);
compositor_animation_->SetAnimationDelegate(this);
- if (owning_web_view_->LinkHighlightsTimeline())
- owning_web_view_->LinkHighlightsTimeline()->AnimationAttached(*this);
CompositorElementId element_id =
CompositorElementIdFromUniqueObjectId(unique_id_);
@@ -109,8 +100,6 @@ LinkHighlightImpl::LinkHighlightImpl(Node* node, WebViewImpl* owning_web_view)
LinkHighlightImpl::~LinkHighlightImpl() {
if (compositor_animation_->IsElementAttached())
compositor_animation_->DetachElement();
- if (owning_web_view_->LinkHighlightsTimeline())
- owning_web_view_->LinkHighlightsTimeline()->AnimationDestroyed(*this);
compositor_animation_->SetAnimationDelegate(nullptr);
compositor_animation_.reset();
@@ -118,14 +107,6 @@ LinkHighlightImpl::~LinkHighlightImpl() {
ReleaseResources();
}
-cc::PictureLayer* LinkHighlightImpl::ContentLayer() {
- return content_layer_.get();
-}
-
-cc::Layer* LinkHighlightImpl::ClipLayer() {
- return clip_layer_.get();
-}
-
void LinkHighlightImpl::ReleaseResources() {
node_.Clear();
}
@@ -144,8 +125,6 @@ void LinkHighlightImpl::AttachLinkHighlightToCompositingLayer(
if (!new_graphics_layer)
return;
- clip_layer_->SetTransform(gfx::Transform());
-
if (current_graphics_layer_ != new_graphics_layer) {
if (current_graphics_layer_)
ClearGraphicsLayerLinkHighlightPointer();
@@ -218,10 +197,10 @@ bool LinkHighlightImpl::ComputeHighlightLayerPathAndPosition(
absolute_quad.Move(ToScrollOffset(scroll_position));
}
- absolute_quad.SetP1(RoundedIntPoint(absolute_quad.P1()));
- absolute_quad.SetP2(RoundedIntPoint(absolute_quad.P2()));
- absolute_quad.SetP3(RoundedIntPoint(absolute_quad.P3()));
- absolute_quad.SetP4(RoundedIntPoint(absolute_quad.P4()));
+ absolute_quad.SetP1(FloatPoint(RoundedIntPoint(absolute_quad.P1())));
+ absolute_quad.SetP2(FloatPoint(RoundedIntPoint(absolute_quad.P2())));
+ absolute_quad.SetP3(FloatPoint(RoundedIntPoint(absolute_quad.P3())));
+ absolute_quad.SetP4(FloatPoint(RoundedIntPoint(absolute_quad.P4())));
FloatQuad transformed_quad =
paint_invalidation_container.AbsoluteToLocalQuad(
absolute_quad, kUseTransforms | kTraverseDocumentBoundaries);
@@ -241,7 +220,9 @@ bool LinkHighlightImpl::ComputeHighlightLayerPathAndPosition(
// links: these should ideally be merged into a single rect before creating
// the path, but that's another CL.
if (quads.size() == 1 && transformed_quad.IsRectilinear() &&
- !owning_web_view_->SettingsImpl()->MockGestureTapHighlightsEnabled()) {
+ !node_->GetDocument()
+ .GetSettings()
+ ->GetMockGestureTapHighlightsEnabled()) {
FloatSize rect_rounding_radii(3, 3);
new_path.AddRoundedRect(transformed_quad.BoundingBox(),
rect_rounding_radii);
@@ -280,7 +261,7 @@ LinkHighlightImpl::PaintContentsToDisplayList(
PaintRecorder recorder;
gfx::Rect record_bounds = PaintableRegion();
- PaintCanvas* canvas =
+ cc::PaintCanvas* canvas =
recorder.beginRecording(record_bounds.width(), record_bounds.height());
PaintFlags flags;
@@ -304,8 +285,8 @@ void LinkHighlightImpl::StartHighlightAnimationIfNeeded() {
is_animating_ = true;
const float kStartOpacity = 1;
// FIXME: Should duration be configurable?
- const float kFadeDuration = 0.1f;
- const float kMinPreFadeDuration = 0.1f;
+ constexpr auto kFadeDuration = TimeDelta::FromMilliseconds(100);
+ constexpr auto kMinPreFadeDuration = TimeDelta::FromMilliseconds(100);
content_layer_->SetOpacity(kStartOpacity);
@@ -319,16 +300,15 @@ void LinkHighlightImpl::StartHighlightAnimationIfNeeded() {
CompositorFloatKeyframe(0, kStartOpacity, timing_function));
// Make sure we have displayed for at least minPreFadeDuration before starting
// to fade out.
- float extra_duration_required = std::max(
- 0.f, kMinPreFadeDuration -
- static_cast<float>(CurrentTimeTicksInSeconds() - start_time_));
- if (extra_duration_required) {
- curve->AddKeyframe(CompositorFloatKeyframe(extra_duration_required,
- kStartOpacity, timing_function));
+ TimeDelta extra_duration_required = std::max(
+ TimeDelta(), kMinPreFadeDuration - (CurrentTimeTicks() - start_time_));
+ if (!extra_duration_required.is_zero()) {
+ curve->AddKeyframe(CompositorFloatKeyframe(
+ extra_duration_required.InSecondsF(), kStartOpacity, timing_function));
}
// For layout tests we don't fade out.
curve->AddKeyframe(CompositorFloatKeyframe(
- kFadeDuration + extra_duration_required,
+ (kFadeDuration + extra_duration_required).InSecondsF(),
LayoutTestSupport::IsRunningLayoutTest() ? kStartOpacity : 0,
timing_function));
@@ -340,7 +320,6 @@ void LinkHighlightImpl::StartHighlightAnimationIfNeeded() {
compositor_animation_->AddKeyframeModel(std::move(keyframe_model));
Invalidate();
- owning_web_view_->MainFrameImpl()->FrameWidgetImpl()->ScheduleAnimation();
}
void LinkHighlightImpl::ClearGraphicsLayerLinkHighlightPointer() {
@@ -388,7 +367,7 @@ void LinkHighlightImpl::UpdateGeometry() {
gfx::RectF(Layer()->position(), gfx::SizeF(Layer()->bounds())));
current_graphics_layer_->TrackRasterInvalidation(
LinkHighlightDisplayItemClientForTracking(), IntRect(rect),
- PaintInvalidationReason::kFull);
+ PaintInvalidationReason::kFullLayer);
}
}
} else {
@@ -409,7 +388,7 @@ void LinkHighlightImpl::Invalidate() {
}
cc::Layer* LinkHighlightImpl::Layer() {
- return ClipLayer();
+ return content_layer_.get();
}
CompositorAnimation* LinkHighlightImpl::GetCompositorAnimation() const {
diff --git a/chromium/third_party/blink/renderer/core/paint/link_highlight_impl.h b/chromium/third_party/blink/renderer/core/paint/link_highlight_impl.h
index f0c631dd5c5..2158cf774e1 100644
--- a/chromium/third_party/blink/renderer/core/paint/link_highlight_impl.h
+++ b/chromium/third_party/blink/renderer/core/paint/link_highlight_impl.h
@@ -38,6 +38,7 @@
#include "third_party/blink/renderer/platform/graphics/path.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/time.h"
namespace cc {
class Layer;
@@ -49,18 +50,15 @@ namespace blink {
class GraphicsLayer;
class LayoutBoxModelObject;
class Node;
-class WebViewImpl;
class CORE_EXPORT LinkHighlightImpl final : public LinkHighlight,
public cc::ContentLayerClient,
public CompositorAnimationDelegate,
public CompositorAnimationClient {
public:
- static std::unique_ptr<LinkHighlightImpl> Create(Node*, WebViewImpl*);
+ static std::unique_ptr<LinkHighlightImpl> Create(Node*);
~LinkHighlightImpl() override;
- cc::PictureLayer* ContentLayer();
- cc::Layer* ClipLayer();
void StartHighlightAnimationIfNeeded();
void UpdateGeometry();
@@ -89,7 +87,7 @@ class CORE_EXPORT LinkHighlightImpl final : public LinkHighlight,
}
private:
- LinkHighlightImpl(Node*, WebViewImpl*);
+ LinkHighlightImpl(Node*);
void ReleaseResources();
void ComputeQuads(const Node&, Vector<FloatQuad>&) const;
@@ -102,18 +100,16 @@ class CORE_EXPORT LinkHighlightImpl final : public LinkHighlight,
bool ComputeHighlightLayerPathAndPosition(const LayoutBoxModelObject&);
scoped_refptr<cc::PictureLayer> content_layer_;
- scoped_refptr<cc::Layer> clip_layer_;
Path path_;
Persistent<Node> node_;
- WebViewImpl* owning_web_view_;
GraphicsLayer* current_graphics_layer_;
bool is_scrolling_graphics_layer_;
std::unique_ptr<CompositorAnimation> compositor_animation_;
bool geometry_needs_update_;
bool is_animating_;
- double start_time_;
+ TimeTicks start_time_;
UniqueObjectId unique_id_;
};
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 4ae95d4c3f4..1739a05d66b 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
@@ -34,18 +34,20 @@
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/public/web/web_frame.h"
-#include "third_party/blink/public/web/web_frame_client.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_view_client.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
+#include "third_party/blink/renderer/core/frame/link_highlights.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/core/input/event_handler.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/page/touch_disambiguation.h"
+#include "third_party/blink/renderer/platform/animation/compositor_animation_timeline.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
@@ -104,27 +106,34 @@ TEST(LinkHighlightImplTest, verifyWebViewImplIntegration) {
web_view_impl->EnableTapHighlightAtPoint(
GetTargetedEvent(web_view_impl, touch_event));
- EXPECT_TRUE(web_view_impl->GetLinkHighlight(0));
- EXPECT_TRUE(web_view_impl->GetLinkHighlight(0)->ContentLayer());
- EXPECT_TRUE(web_view_impl->GetLinkHighlight(0)->ClipLayer());
+ const auto& highlights =
+ web_view_impl->GetPage()->GetLinkHighlights().link_highlights_;
+ EXPECT_TRUE(highlights.at(0));
+ EXPECT_TRUE(highlights.at(0)->Layer());
// Find a target inside a scrollable div
touch_event.SetPositionInWidget(WebFloatPoint(20, 100));
web_view_impl->EnableTapHighlightAtPoint(
GetTargetedEvent(web_view_impl, touch_event));
- ASSERT_TRUE(web_view_impl->GetLinkHighlight(0));
+ ASSERT_TRUE(highlights.at(0));
+
+ // Enesure the timeline was added to a host.
+ EXPECT_TRUE(!!web_view_impl->GetPage()
+ ->GetLinkHighlights()
+ .timeline_->GetAnimationTimeline()
+ ->animation_host());
// Don't highlight if no "hand cursor"
touch_event.SetPositionInWidget(
WebFloatPoint(20, 220)); // An A-link with cross-hair cursor.
web_view_impl->EnableTapHighlightAtPoint(
GetTargetedEvent(web_view_impl, touch_event));
- ASSERT_EQ(0U, web_view_impl->NumLinkHighlights());
+ ASSERT_EQ(0U, highlights.size());
touch_event.SetPositionInWidget(WebFloatPoint(20, 260)); // A text input box.
web_view_impl->EnableTapHighlightAtPoint(
GetTargetedEvent(web_view_impl, touch_event));
- ASSERT_EQ(0U, web_view_impl->NumLinkHighlights());
+ ASSERT_EQ(0U, highlights.size());
Platform::Current()
->GetURLLoaderMockFactory()
@@ -153,16 +162,17 @@ TEST(LinkHighlightImplTest, resetDuringNodeRemoval) {
ASSERT_TRUE(touch_node);
web_view_impl->EnableTapHighlightAtPoint(targeted_event);
- ASSERT_TRUE(web_view_impl->GetLinkHighlight(0));
+ const auto& highlights = web_view_impl->GetPage()->GetLinkHighlights();
+ ASSERT_TRUE(highlights.link_highlights_.at(0));
GraphicsLayer* highlight_layer =
- web_view_impl->GetLinkHighlight(0)->CurrentGraphicsLayerForTesting();
+ highlights.link_highlights_.at(0)->CurrentGraphicsLayerForTesting();
ASSERT_TRUE(highlight_layer);
EXPECT_TRUE(highlight_layer->GetLinkHighlight(0));
touch_node->remove(IGNORE_EXCEPTION_FOR_TESTING);
web_view_impl->UpdateAllLifecyclePhases();
- ASSERT_EQ(0U, highlight_layer->NumLinkHighlights());
+ EXPECT_EQ(0U, highlight_layer->NumLinkHighlights());
Platform::Current()
->GetURLLoaderMockFactory()
@@ -192,10 +202,12 @@ TEST(LinkHighlightImplTest, resetLayerTreeView) {
ASSERT_TRUE(touch_node);
web_view_impl->EnableTapHighlightAtPoint(targeted_event);
- ASSERT_TRUE(web_view_impl->GetLinkHighlight(0));
+ const auto& highlights =
+ web_view_impl->GetPage()->GetLinkHighlights().link_highlights_;
+ ASSERT_TRUE(highlights.at(0));
GraphicsLayer* highlight_layer =
- web_view_impl->GetLinkHighlight(0)->CurrentGraphicsLayerForTesting();
+ highlights.at(0)->CurrentGraphicsLayerForTesting();
ASSERT_TRUE(highlight_layer);
EXPECT_TRUE(highlight_layer->GetLinkHighlight(0));
@@ -229,7 +241,9 @@ TEST(LinkHighlightImplTest, multipleHighlights) {
good_targets, highlight_nodes);
web_view_impl->EnableTapHighlights(highlight_nodes);
- EXPECT_EQ(2U, web_view_impl->NumLinkHighlights());
+ const auto& highlights =
+ web_view_impl->GetPage()->GetLinkHighlights().link_highlights_;
+ EXPECT_EQ(2U, highlights.size());
Platform::Current()
->GetURLLoaderMockFactory()
diff --git a/chromium/third_party/blink/renderer/core/paint/list_item_painter.cc b/chromium/third_party/blink/renderer/core/paint/list_item_painter.cc
index 39b74ed9119..e9c8395e765 100644
--- a/chromium/third_party/blink/renderer/core/paint/list_item_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/list_item_painter.cc
@@ -10,12 +10,11 @@
namespace blink {
-void ListItemPainter::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void ListItemPainter::Paint(const PaintInfo& paint_info) {
if (!layout_list_item_.LogicalHeight() && layout_list_item_.HasOverflowClip())
return;
- BlockPainter(layout_list_item_).Paint(paint_info, paint_offset);
+ BlockPainter(layout_list_item_).Paint(paint_info);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/list_item_painter.h b/chromium/third_party/blink/renderer/core/paint/list_item_painter.h
index fa4e4184617..8264747c009 100644
--- a/chromium/third_party/blink/renderer/core/paint/list_item_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/list_item_painter.h
@@ -11,7 +11,6 @@ namespace blink {
struct PaintInfo;
class LayoutListItem;
-class LayoutPoint;
class ListItemPainter {
STACK_ALLOCATED();
@@ -20,7 +19,7 @@ class ListItemPainter {
ListItemPainter(const LayoutListItem& layout_list_item)
: layout_list_item_(layout_list_item) {}
- void Paint(const PaintInfo&, const LayoutPoint& paint_offset);
+ void Paint(const PaintInfo&);
private:
const LayoutListItem& layout_list_item_;
diff --git a/chromium/third_party/blink/renderer/core/paint/list_marker_painter.cc b/chromium/third_party/blink/renderer/core/paint/list_marker_painter.cc
index 36f2d0c19e7..a591be96a34 100644
--- a/chromium/third_party/blink/renderer/core/paint/list_marker_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/list_marker_painter.cc
@@ -20,19 +20,27 @@
namespace blink {
-static inline void PaintSymbol(GraphicsContext& context,
- const Color& color,
- const IntRect& marker,
- EListStyleType list_style) {
+void ListMarkerPainter::PaintSymbol(const PaintInfo& paint_info,
+ const LayoutObject* object,
+ const ComputedStyle& style,
+ const IntRect& marker) {
+ DCHECK(object);
+ GraphicsContext& context = paint_info.context;
+ Color color(object->ResolveColor(GetCSSPropertyColor()));
+ if (BoxModelObjectPainter::ShouldForceWhiteBackgroundForPrintEconomy(
+ object->GetDocument(), style))
+ color = TextPainter::TextColorForWhiteBackground(color);
+ // Apply the color to the list marker text.
+ context.SetFillColor(color);
context.SetStrokeColor(color);
context.SetStrokeStyle(kSolidStroke);
context.SetStrokeThickness(1.0f);
- switch (list_style) {
+ switch (style.ListStyleType()) {
case EListStyleType::kDisc:
- context.FillEllipse(marker);
+ context.FillEllipse(FloatRect(marker));
break;
case EListStyleType::kCircle:
- context.StrokeEllipse(marker);
+ context.StrokeEllipse(FloatRect(marker));
break;
case EListStyleType::kSquare:
context.FillRect(marker);
@@ -43,8 +51,7 @@ static inline void PaintSymbol(GraphicsContext& context,
}
}
-void ListMarkerPainter::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void ListMarkerPainter::Paint(const PaintInfo& paint_info) {
if (paint_info.phase != PaintPhase::kForeground)
return;
@@ -55,10 +62,9 @@ void ListMarkerPainter::Paint(const PaintInfo& paint_info,
paint_info.context, layout_list_marker_, paint_info.phase))
return;
- AdjustPaintOffsetScope adjustment(layout_list_marker_, paint_info,
- paint_offset);
+ AdjustPaintOffsetScope adjustment(layout_list_marker_, paint_info);
const auto& local_paint_info = adjustment.GetPaintInfo();
- auto box_origin = adjustment.AdjustedPaintOffset();
+ auto box_origin = adjustment.PaintOffset();
LayoutRect overflow_rect(layout_list_marker_.VisualOverflowRect());
overflow_rect.MoveBy(box_origin);
@@ -101,6 +107,15 @@ void ListMarkerPainter::Paint(const PaintInfo& paint_info,
if (style_category == LayoutListMarker::ListStyleCategory::kNone)
return;
+ if (style_category == LayoutListMarker::ListStyleCategory::kSymbol) {
+ PaintSymbol(paint_info, &layout_list_marker_,
+ layout_list_marker_.StyleRef(), PixelSnappedIntRect(marker));
+ return;
+ }
+
+ if (layout_list_marker_.GetText().IsEmpty())
+ return;
+
Color color(layout_list_marker_.ResolveColor(GetCSSPropertyColor()));
if (BoxModelObjectPainter::ShouldForceWhiteBackgroundForPrintEconomy(
@@ -111,16 +126,6 @@ void ListMarkerPainter::Paint(const PaintInfo& paint_info,
// Apply the color to the list marker text.
context.SetFillColor(color);
- const EListStyleType list_style =
- layout_list_marker_.Style()->ListStyleType();
- if (style_category == LayoutListMarker::ListStyleCategory::kSymbol) {
- PaintSymbol(context, color, PixelSnappedIntRect(marker), list_style);
- return;
- }
-
- if (layout_list_marker_.GetText().IsEmpty())
- return;
-
const Font& font = layout_list_marker_.Style()->GetFont();
TextRun text_run = ConstructTextRun(font, layout_list_marker_.GetText(),
layout_list_marker_.StyleRef());
@@ -139,13 +144,13 @@ void ListMarkerPainter::Paint(const PaintInfo& paint_info,
}
TextRunPaintInfo text_run_paint_info(text_run);
- text_run_paint_info.bounds = EnclosingIntRect(marker);
+ text_run_paint_info.bounds = FloatRect(EnclosingIntRect(marker));
const SimpleFontData* font_data =
layout_list_marker_.Style()->GetFont().PrimaryFont();
- IntPoint text_origin =
- IntPoint(marker.X().Round(),
- marker.Y().Round() +
- (font_data ? font_data->GetFontMetrics().Ascent() : 0));
+ FloatPoint text_origin =
+ FloatPoint(marker.X().Round(),
+ marker.Y().Round() +
+ (font_data ? font_data->GetFontMetrics().Ascent() : 0));
// Text is not arbitrary. We can judge whether it's RTL from the first
// character, and we only need to handle the direction RightToLeft for now.
@@ -162,23 +167,26 @@ void ListMarkerPainter::Paint(const PaintInfo& paint_info,
text_run.SetText(reversed_text.ToString());
}
- const UChar suffix = ListMarkerText::Suffix(
- list_style, layout_list_marker_.ListItem()->Value());
+ const UChar suffix =
+ ListMarkerText::Suffix(layout_list_marker_.Style()->ListStyleType(),
+ layout_list_marker_.ListItem()->Value());
UChar suffix_str[2] = {suffix, static_cast<UChar>(' ')};
TextRun suffix_run =
ConstructTextRun(font, suffix_str, 2, layout_list_marker_.StyleRef(),
layout_list_marker_.Style()->Direction());
TextRunPaintInfo suffix_run_info(suffix_run);
- suffix_run_info.bounds = EnclosingIntRect(marker);
+ suffix_run_info.bounds = FloatRect(EnclosingIntRect(marker));
if (layout_list_marker_.Style()->IsLeftToRightDirection()) {
context.DrawText(font, text_run_paint_info, text_origin);
context.DrawText(font, suffix_run_info,
- text_origin + IntSize(font.Width(text_run), 0));
+ text_origin + FloatSize(IntSize(font.Width(text_run), 0)));
} else {
context.DrawText(font, suffix_run_info, text_origin);
- context.DrawText(font, text_run_paint_info,
- text_origin + IntSize(font.Width(suffix_run), 0));
+ // Is the truncation to IntSize below meaningful or a bug?
+ context.DrawText(
+ font, text_run_paint_info,
+ text_origin + FloatSize(IntSize(font.Width(suffix_run), 0)));
}
// TODO(npm): Check that there are non-whitespace characters. See
// crbug.com/788444.
diff --git a/chromium/third_party/blink/renderer/core/paint/list_marker_painter.h b/chromium/third_party/blink/renderer/core/paint/list_marker_painter.h
index ab8b0b8af7f..fb39379adad 100644
--- a/chromium/third_party/blink/renderer/core/paint/list_marker_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/list_marker_painter.h
@@ -10,8 +10,10 @@
namespace blink {
struct PaintInfo;
+class ComputedStyle;
+class IntRect;
class LayoutListMarker;
-class LayoutPoint;
+class LayoutObject;
class ListMarkerPainter {
STACK_ALLOCATED();
@@ -20,7 +22,12 @@ class ListMarkerPainter {
ListMarkerPainter(const LayoutListMarker& layout_list_marker)
: layout_list_marker_(layout_list_marker) {}
- void Paint(const PaintInfo&, const LayoutPoint& paint_offset);
+ void Paint(const PaintInfo&);
+
+ static void PaintSymbol(const PaintInfo&,
+ const LayoutObject*,
+ const ComputedStyle&,
+ const IntRect&);
private:
const LayoutListMarker& layout_list_marker_;
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_block_flow_painter.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_block_flow_painter.cc
index 335971b445e..0f48339ac26 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_block_flow_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_block_flow_painter.cc
@@ -11,30 +11,26 @@
namespace blink {
-void NGBlockFlowPainter::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void NGBlockFlowPainter::Paint(const PaintInfo& paint_info) {
const NGPaintFragment* paint_fragment = block_.PaintFragment();
DCHECK(paint_fragment);
- PaintBoxFragment(*paint_fragment, paint_info, paint_offset);
+ PaintBoxFragment(*paint_fragment, paint_info);
}
void NGBlockFlowPainter::PaintBoxFragment(const NGPaintFragment& fragment,
- const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+ const PaintInfo& paint_info) {
PaintInfo ng_paint_info(paint_info);
- NGBoxFragmentPainter(fragment).Paint(ng_paint_info, paint_offset);
+ NGBoxFragmentPainter(fragment).Paint(ng_paint_info);
}
bool NGBlockFlowPainter::NodeAtPoint(
HitTestResult& result,
const HitTestLocation& location_in_container,
- const LayoutPoint& accumulated_offset,
- const LayoutPoint& accumulated_offset_for_legacy,
+ const LayoutPoint& physical_offset,
HitTestAction action) {
if (const NGPaintFragment* paint_fragment = block_.PaintFragment()) {
return NGBoxFragmentPainter(*paint_fragment)
- .NodeAtPoint(result, location_in_container, accumulated_offset,
- accumulated_offset_for_legacy, action);
+ .NodeAtPoint(result, location_in_container, physical_offset, action);
}
return false;
}
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_block_flow_painter.h b/chromium/third_party/blink/renderer/core/paint/ng/ng_block_flow_painter.h
index bc73ba986d9..7c9af2576d4 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_block_flow_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_block_flow_painter.h
@@ -27,18 +27,17 @@ class NGBlockFlowPainter {
public:
NGBlockFlowPainter(const LayoutBlockFlow& layout_block_flow)
: block_(layout_block_flow) {}
- void Paint(const PaintInfo&, const LayoutPoint&);
+ void Paint(const PaintInfo&);
+ // Hit tests this block flow
+ // @param physical_offset Physical offset of this block flow in paint layer.
bool NodeAtPoint(HitTestResult&,
const HitTestLocation& location_in_container,
- const LayoutPoint& accumulated_offset,
- const LayoutPoint& accumulated_offset_for_legacy,
+ const LayoutPoint& physical_offset,
HitTestAction);
private:
- void PaintBoxFragment(const NGPaintFragment&,
- const PaintInfo&,
- const LayoutPoint&);
+ void PaintBoxFragment(const NGPaintFragment&, const PaintInfo&);
const LayoutBlockFlow& block_;
};
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_box_clipper.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_box_clipper.cc
index b8ab6d7dba1..78b60daf91c 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_box_clipper.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_box_clipper.cc
@@ -18,7 +18,6 @@ NGBoxClipper::NGBoxClipper(const NGPaintFragment& fragment,
if (paint_info.phase == PaintPhase::kMask)
return;
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
DCHECK(fragment.GetLayoutObject());
InitializeScopedClipProperty(
paint_info.FragmentToPaint(*fragment.GetLayoutObject()), fragment,
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 15b4b358e00..67dc662e244 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
@@ -7,6 +7,8 @@
#include "third_party/blink/renderer/core/layout/background_bleed_avoidance.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_inline.h"
+#include "third_party/blink/renderer/core/layout/layout_list_marker.h"
#include "third_party/blink/renderer/core/layout/layout_table.h"
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_border_edges.h"
@@ -18,6 +20,7 @@
#include "third_party/blink/renderer/core/paint/adjust_paint_offset_scope.h"
#include "third_party/blink/renderer/core/paint/background_image_geometry.h"
#include "third_party/blink/renderer/core/paint/box_decoration_data.h"
+#include "third_party/blink/renderer/core/paint/list_marker_painter.h"
#include "third_party/blink/renderer/core/paint/ng/ng_box_clipper.h"
#include "third_party/blink/renderer/core/paint/ng/ng_fragment_painter.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
@@ -26,11 +29,9 @@
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_phase.h"
-#include "third_party/blink/renderer/core/paint/scroll_recorder.h"
#include "third_party/blink/renderer/core/paint/scrollable_area_painter.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/clip_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/scroll/scroll_types.h"
@@ -53,18 +54,77 @@ bool ShouldPaintBoxFragmentBorders(const LayoutObject& object) {
return !ToLayoutTableCell(object).Table()->ShouldCollapseBorders();
}
+bool FragmentVisibleToHitTestRequest(const NGPaintFragment& fragment,
+ const HitTestRequest& request) {
+ return fragment.Style().Visibility() == EVisibility::kVisible &&
+ (request.IgnorePointerEventsNone() ||
+ fragment.Style().PointerEvents() != EPointerEvents::kNone) &&
+ !(fragment.GetNode() && fragment.GetNode()->IsInert());
+}
+
+// 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& location_in_container,
+ const LayoutPoint& 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 LayoutPoint fallback_accumulated_offset =
+ physical_offset - fragment.InlineOffsetToContainerBox().ToLayoutSize();
+ const LayoutObject* limit_layout_object =
+ parent.PhysicalFragment().IsLineBox() ? parent.Parent()->GetLayoutObject()
+ : parent.GetLayoutObject();
+
+ 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()) {
+ // |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.
+ // To ensure the correct hit test ordering, |culled_parent| must be hit
+ // tested only once after all of its descendants are hit tested:
+ // - Shortcut: when |current_layout_object| is the only child (of
+ // |culled_parent|), since it's just hit tested, we can safely hit test its
+ // parent;
+ // - General case: we hit test |culled_parent| only when it is not an
+ // 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();
+ if (has_sibling && previous_sibling &&
+ previous_sibling->GetLayoutObject()->IsDescendantOf(culled_parent))
+ break;
+
+ if (culled_parent->IsLayoutInline() &&
+ ToLayoutInline(culled_parent)
+ ->HitTestCulledInline(result, location_in_container,
+ fallback_accumulated_offset, &parent))
+ return true;
+
+ current_layout_object = culled_parent;
+ }
+
+ return false;
+}
+
} // anonymous namespace
NGBoxFragmentPainter::NGBoxFragmentPainter(const NGPaintFragment& box)
: BoxPainterBase(
- box,
&box.GetLayoutObject()->GetDocument(),
box.Style(),
box.GetLayoutObject()->GeneratingNode(),
BoxStrutToLayoutRectOutsets(box.PhysicalFragment().BorderWidths()),
BoxStrutToLayoutRectOutsets(
- ToNGPhysicalBoxFragment(box.PhysicalFragment()).Padding()),
- box.PhysicalFragment().Layer()),
+ ToNGPhysicalBoxFragment(box.PhysicalFragment()).Padding())),
box_fragment_(box),
border_edges_(
NGBorderEdges::FromPhysical(box.PhysicalFragment().BorderEdges(),
@@ -72,44 +132,16 @@ NGBoxFragmentPainter::NGBoxFragmentPainter(const NGPaintFragment& box)
DCHECK(box.PhysicalFragment().IsBox());
}
-void NGBoxFragmentPainter::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
- const LayoutObject* layout_object = PhysicalFragment().GetLayoutObject();
- DCHECK(layout_object && layout_object->IsBox());
- if (!PhysicalFragment().IsPlacedByLayoutNG()) {
- // |fragment.Offset()| is valid only when it is placed by LayoutNG parent.
- // Use LayoutBox::Location() if not. crbug.com/788590
- AdjustPaintOffsetScope adjustment(ToLayoutBox(*layout_object), paint_info,
- paint_offset);
- PaintWithAdjustedOffset(adjustment.MutablePaintInfo(),
- adjustment.AdjustedPaintOffset());
- return;
- }
- DCHECK_EQ(layout_object->Style(PhysicalFragment().UsesFirstLineStyle()),
- &PhysicalFragment().Style());
- AdjustPaintOffsetScope adjustment(box_fragment_, paint_info, paint_offset);
- PaintWithAdjustedOffset(adjustment.MutablePaintInfo(),
- adjustment.AdjustedPaintOffset());
-}
-
-void NGBoxFragmentPainter::PaintInlineBox(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
- const LayoutPoint adjusted_paint_offset =
- paint_offset + box_fragment_.Offset().ToLayoutPoint();
- if (paint_info.phase == PaintPhase::kForeground)
- PaintBoxDecorationBackground(paint_info, adjusted_paint_offset);
+void NGBoxFragmentPainter::Paint(const PaintInfo& paint_info) {
+ AdjustPaintOffsetScope adjustment(box_fragment_, paint_info);
+ auto& info = adjustment.MutablePaintInfo();
+ auto paint_offset = adjustment.PaintOffset();
- PaintObject(paint_info, adjusted_paint_offset, true);
-}
-
-void NGBoxFragmentPainter::PaintWithAdjustedOffset(
- PaintInfo& info,
- const LayoutPoint& paint_offset) {
if (!IntersectsPaintRect(info, paint_offset))
return;
if (PhysicalFragment().IsAtomicInline())
- return PaintAtomicInline(info, paint_offset);
+ return PaintAtomicInline(info);
PaintPhase original_phase = info.phase;
@@ -124,7 +156,11 @@ void NGBoxFragmentPainter::PaintWithAdjustedOffset(
if (original_phase != PaintPhase::kSelfBlockBackgroundOnly &&
original_phase != PaintPhase::kSelfOutlineOnly) {
- NGBoxClipper box_clipper(box_fragment_, info);
+ base::Optional<NGBoxClipper> box_clipper;
+ if (original_phase == PaintPhase::kForeground ||
+ original_phase == PaintPhase::kFloat ||
+ original_phase == PaintPhase::kDescendantOutlinesOnly)
+ box_clipper.emplace(box_fragment_, info);
PaintObject(info, paint_offset);
}
@@ -140,6 +176,17 @@ void NGBoxFragmentPainter::PaintWithAdjustedOffset(
PaintOverflowControlsIfNeeded(info, paint_offset);
}
+void NGBoxFragmentPainter::PaintInlineBox(const PaintInfo& paint_info,
+ const LayoutPoint& paint_offset) {
+ const LayoutPoint adjusted_paint_offset =
+ paint_offset + box_fragment_.Offset().ToLayoutPoint();
+ if (paint_info.phase == PaintPhase::kForeground &&
+ box_fragment_.Style().Visibility() == EVisibility::kVisible)
+ PaintBoxDecorationBackground(paint_info, adjusted_paint_offset);
+
+ PaintObject(paint_info, adjusted_paint_offset, true);
+}
+
void NGBoxFragmentPainter::PaintObject(
const PaintInfo& paint_info,
const LayoutPoint& paint_offset,
@@ -152,7 +199,7 @@ void NGBoxFragmentPainter::PaintObject(
// TODO(eae): style.HasBoxDecorationBackground isn't good enough, it needs
// to check the object as some objects may have box decoration background
// other than from their own style.
- // TODO(eae): This should not be needed both here and in PaintInlineBox.
+ // TODO(eae): We can probably get rid of suppress_box_decoration_background.
if (!suppress_box_decoration_background && is_visible &&
style.HasBoxDecorationBackground())
PaintBoxDecorationBackground(paint_info, paint_offset);
@@ -171,9 +218,6 @@ void NGBoxFragmentPainter::PaintObject(
if (paint_phase == PaintPhase::kMask && is_visible)
return PaintMask(paint_info, paint_offset);
- if (paint_phase == PaintPhase::kClippingMask && is_visible)
- return PaintClippingMask(paint_info, paint_offset);
-
if (paint_phase == PaintPhase::kForeground && paint_info.IsPrinting()) {
NGFragmentPainter(box_fragment_)
.AddPDFURLRectIfNeeded(paint_info, paint_offset);
@@ -185,7 +229,6 @@ void NGBoxFragmentPainter::PaintObject(
base::Optional<ScopedPaintChunkProperties> scoped_scroll_property;
base::Optional<PaintInfo> scrolled_paint_info;
if (const auto* fragment = paint_info.FragmentToPaint(layout_object)) {
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
const auto* object_properties = fragment->PaintProperties();
auto* scroll_translation =
object_properties ? object_properties->ScrollTranslation() : nullptr;
@@ -215,21 +258,22 @@ void NGBoxFragmentPainter::PaintObject(
if (paint_phase == PaintPhase::kFloat ||
paint_phase == PaintPhase::kSelection ||
paint_phase == PaintPhase::kTextClip)
- PaintFloats(contents_paint_info, paint_offset);
+ PaintFloats(contents_paint_info);
} else {
PaintInlineChildren(box_fragment_.Children(), contents_paint_info,
paint_offset);
}
} else {
- PaintBlockChildren(contents_paint_info, paint_offset);
+ PaintBlockChildren(contents_paint_info);
+ }
+ if (ShouldPaintDescendantOutlines(paint_phase)) {
+ NGFragmentPainter(box_fragment_)
+ .PaintDescendantOutlines(paint_info, paint_offset);
}
}
if (ShouldPaintSelfOutline(paint_phase))
NGFragmentPainter(box_fragment_).PaintOutline(paint_info, paint_offset);
- if (ShouldPaintDescendantOutlines(paint_phase))
- NGFragmentPainter(box_fragment_)
- .PaintDescendantOutlines(paint_info, paint_offset);
// TODO(layout-dev): Implement once we have selections in LayoutNG.
// If the caret's node's layout object's containing block is this block, and
// the paint action is PaintPhaseForeground, then paint the caret.
@@ -254,7 +298,7 @@ void NGBoxFragmentPainter::PaintBlockFlowContents(
DCHECK(PhysicalFragment().ChildrenInline());
- LayoutRect overflow_rect(box_fragment_.VisualOverflowRect());
+ LayoutRect overflow_rect(box_fragment_.ChildrenInkOverflow());
overflow_rect.MoveBy(paint_offset);
if (!paint_info.GetCullRect().IntersectsCullRect(overflow_rect))
return;
@@ -310,8 +354,7 @@ bool FragmentRequiresLegacyFallback(const NGPhysicalFragment& fragment) {
}
} // anonymous namespace
-void NGBoxFragmentPainter::PaintBlockChildren(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void NGBoxFragmentPainter::PaintBlockChildren(const PaintInfo& paint_info) {
for (const auto& child : box_fragment_.Children()) {
const NGPhysicalFragment& fragment = child->PhysicalFragment();
if (child->HasSelfPaintingLayer() || fragment.IsFloating())
@@ -319,9 +362,9 @@ void NGBoxFragmentPainter::PaintBlockChildren(const PaintInfo& paint_info,
if (fragment.Type() == NGPhysicalFragment::kFragmentBox) {
if (FragmentRequiresLegacyFallback(fragment))
- fragment.GetLayoutObject()->Paint(paint_info, paint_offset);
+ fragment.GetLayoutObject()->Paint(paint_info);
else
- NGBoxFragmentPainter(*child).Paint(paint_info, paint_offset);
+ NGBoxFragmentPainter(*child).Paint(paint_info);
} else {
NOTREACHED() << fragment.ToString();
}
@@ -330,8 +373,7 @@ void NGBoxFragmentPainter::PaintBlockChildren(const PaintInfo& paint_info,
void NGBoxFragmentPainter::PaintFloatingChildren(
const Vector<std::unique_ptr<NGPaintFragment>>& children,
- const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+ const PaintInfo& paint_info) {
for (const auto& child : children) {
const NGPhysicalFragment& fragment = child->PhysicalFragment();
if (child->HasSelfPaintingLayer())
@@ -345,15 +387,14 @@ void NGBoxFragmentPainter::PaintFloatingChildren(
// NGBoxFragmentPainter. We can shortcut this for the first case when
// we're more stable.
ObjectPainter(*child->GetLayoutObject())
- .PaintAllPhasesAtomically(paint_info, paint_offset);
+ .PaintAllPhasesAtomically(paint_info);
} else {
- PaintFloatingChildren(child->Children(), paint_info, paint_offset);
+ PaintFloatingChildren(child->Children(), paint_info);
}
}
}
-void NGBoxFragmentPainter::PaintFloats(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void NGBoxFragmentPainter::PaintFloats(const PaintInfo& paint_info) {
// TODO(eae): The legacy paint code currently handles most floats, if they can
// be painted by PaintNG BlockFlowPainter::PaintFloats will then call
// NGBlockFlowPainter::Paint on each float.
@@ -362,8 +403,7 @@ void NGBoxFragmentPainter::PaintFloats(const PaintInfo& paint_info,
PaintInfo float_paint_info(paint_info);
if (paint_info.phase == PaintPhase::kFloat)
float_paint_info.phase = PaintPhase::kForeground;
- PaintFloatingChildren(box_fragment_.Children(), float_paint_info,
- paint_offset);
+ PaintFloatingChildren(box_fragment_.Children(), float_paint_info);
}
void NGBoxFragmentPainter::PaintMask(const PaintInfo& paint_info,
@@ -388,11 +428,6 @@ void NGBoxFragmentPainter::PaintMask(const PaintInfo& paint_info,
border_edges_.line_left, border_edges_.line_right);
}
-void NGBoxFragmentPainter::PaintClippingMask(const PaintInfo&,
- const LayoutPoint&) {
- // TODO(eae): Implement.
-}
-
void NGBoxFragmentPainter::PaintBoxDecorationBackground(
const PaintInfo& paint_info,
const LayoutPoint& paint_offset) {
@@ -443,10 +478,14 @@ void NGBoxFragmentPainter::PaintBoxDecorationBackground(
// TODO(layout-dev): Support theme painting.
bool theme_painted = false;
+ // TODO(mstensho): Break dependency on LayoutObject functionality.
+ const LayoutObject& layout_object = *box_fragment_.GetLayoutObject();
bool should_paint_background =
!theme_painted &&
(!paint_info.SkipRootBackground() ||
- paint_info.PaintContainer() != box_fragment_.GetLayoutObject());
+ paint_info.PaintContainer() != layout_object) &&
+ (!layout_object.IsBoxModelObject() ||
+ !ToLayoutBoxModelObject(layout_object).BackgroundStolenForBeingBody());
if (should_paint_background) {
PaintBackground(paint_info, paint_rect,
box_decoration_data.background_color,
@@ -459,9 +498,9 @@ void NGBoxFragmentPainter::PaintBoxDecorationBackground(
border_edges_.line_right);
if (box_decoration_data.has_border_decoration &&
- ShouldPaintBoxFragmentBorders(*box_fragment_.GetLayoutObject())) {
- Node* generating_node = box_fragment_.GetLayoutObject()->GeneratingNode();
- const Document& document = box_fragment_.GetLayoutObject()->GetDocument();
+ ShouldPaintBoxFragmentBorders(layout_object)) {
+ Node* generating_node = layout_object.GeneratingNode();
+ const Document& document = layout_object.GetDocument();
PaintBorder(box_fragment_, document, generating_node, paint_info,
paint_rect, style, box_decoration_data.bleed_avoidance,
border_edges_.line_left, border_edges_.line_right);
@@ -474,64 +513,63 @@ void NGBoxFragmentPainter::PaintBoxDecorationBackground(
void NGBoxFragmentPainter::PaintInlineChildBoxUsingLegacyFallback(
const NGPhysicalFragment& fragment,
- const PaintInfo& paint_info,
- const LayoutPoint& paint_offset,
- const LayoutPoint& legacy_paint_offset) {
+ const PaintInfo& paint_info) {
LayoutObject* child_layout_object = fragment.GetLayoutObject();
DCHECK(child_layout_object);
if (child_layout_object->IsLayoutNGMixin() &&
ToLayoutBlockFlow(child_layout_object)->PaintFragment()) {
- // This object will use NGBoxFragmentPainter. NGBoxFragmentPainter expects
- // |paint_offset| relative to the parent, even when in inline context.
- LayoutPoint child_point =
- FlipForWritingModeForChild(fragment, paint_offset);
- child_layout_object->Paint(paint_info, child_point);
+ // This object will use NGBoxFragmentPainter.
+ child_layout_object->Paint(paint_info);
return;
}
- // When in inline context, pre-NG painters expect |paint_offset| of their
- // block container.
if (child_layout_object->IsAtomicInlineLevel()) {
// Pre-NG painters also expect callers to use |PaintAllPhasesAtomically()|
// for atomic inlines.
- LayoutPoint child_point =
- FlipForWritingModeForChild(fragment, legacy_paint_offset);
- ObjectPainter(*child_layout_object)
- .PaintAllPhasesAtomically(paint_info, child_point);
+ ObjectPainter(*child_layout_object).PaintAllPhasesAtomically(paint_info);
return;
}
- child_layout_object->Paint(paint_info, paint_offset);
+ child_layout_object->Paint(paint_info);
}
void NGBoxFragmentPainter::PaintAllPhasesAtomically(
const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+ bool is_self_painting) {
+ AdjustPaintOffsetScope adjustment(box_fragment_, paint_info);
+ auto paint_offset = adjustment.PaintOffset();
+ PaintInfo local_paint_info = adjustment.MutablePaintInfo();
+
// Pass PaintPhaseSelection and PaintPhaseTextClip is handled by the regular
// foreground paint implementation. We don't need complete painting for these
// phases.
PaintPhase phase = paint_info.phase;
if (phase == PaintPhase::kSelection || phase == PaintPhase::kTextClip)
- return PaintObject(paint_info, paint_offset);
+ return PaintObject(local_paint_info, paint_offset);
+
+ if (paint_info.phase == PaintPhase::kSelfBlockBackgroundOnly &&
+ is_self_painting)
+ return PaintObject(local_paint_info, paint_offset);
if (phase != PaintPhase::kForeground)
return;
- PaintInfo info(paint_info);
-
- NGBoxClipper box_clipper(box_fragment_, info);
-
- info.phase = PaintPhase::kBlockBackground;
- PaintObject(info, paint_offset);
-
- info.phase = PaintPhase::kFloat;
- PaintObject(info, paint_offset);
-
- info.phase = PaintPhase::kForeground;
- PaintObject(info, paint_offset);
+ if (!is_self_painting) {
+ local_paint_info.phase = PaintPhase::kBlockBackground;
+ PaintObject(local_paint_info, paint_offset);
+ }
+ local_paint_info.phase = PaintPhase::kFloat;
+ PaintObject(local_paint_info, paint_offset);
+ {
+ NGBoxClipper box_clipper(box_fragment_, local_paint_info);
+ local_paint_info.phase = PaintPhase::kForeground;
+ PaintObject(local_paint_info, paint_offset);
+ }
+ local_paint_info.phase = PaintPhase::kOutline;
+ PaintObject(local_paint_info, paint_offset);
- info.phase = PaintPhase::kOutline;
- PaintObject(info, paint_offset);
+ local_paint_info.phase = PaintPhase::kBlockBackground;
+ PaintOverflowControlsIfNeeded(local_paint_info, paint_offset);
}
void NGBoxFragmentPainter::PaintLineBoxChildren(
@@ -568,7 +606,7 @@ void NGBoxFragmentPainter::PaintLineBoxChildren(
const LayoutPoint child_offset =
paint_offset + line->Offset().ToLayoutPoint();
if (line->PhysicalFragment().IsListMarker()) {
- PaintAtomicInlineChild(*line, paint_info, paint_offset, paint_offset);
+ PaintAtomicInlineChild(*line, paint_info);
continue;
}
DCHECK(line->PhysicalFragment().IsLineBox())
@@ -597,8 +635,7 @@ void NGBoxFragmentPainter::PaintInlineChildren(
parent = parent->Parent();
}
- PaintAtomicInlineChild(*child, paint_info, paint_offset,
- legacy_paint_offset);
+ PaintAtomicInlineChild(*child, paint_info);
} else {
PaintInlineChild(*child, paint_info, paint_offset);
}
@@ -612,11 +649,8 @@ void NGBoxFragmentPainter::PaintInlineChildrenOutlines(
// TODO(layout-dev): Implement.
}
-void NGBoxFragmentPainter::PaintAtomicInlineChild(
- const NGPaintFragment& child,
- const PaintInfo& paint_info,
- const LayoutPoint& paint_offset,
- const LayoutPoint& legacy_paint_offset) {
+void NGBoxFragmentPainter::PaintAtomicInlineChild(const NGPaintFragment& child,
+ const PaintInfo& paint_info) {
// Inline children should be painted by PaintInlineChild.
DCHECK(child.PhysicalFragment().IsAtomicInline());
@@ -625,11 +659,9 @@ void NGBoxFragmentPainter::PaintAtomicInlineChild(
return;
if (fragment.Type() == NGPhysicalFragment::kFragmentBox &&
FragmentRequiresLegacyFallback(fragment)) {
- PaintInlineChildBoxUsingLegacyFallback(fragment, paint_info, paint_offset,
- legacy_paint_offset);
+ PaintInlineChildBoxUsingLegacyFallback(fragment, paint_info);
} else {
- NGBoxFragmentPainter(child).PaintAllPhasesAtomically(
- paint_info, paint_offset + fragment.Offset().ToLayoutPoint());
+ NGBoxFragmentPainter(child).PaintAllPhasesAtomically(paint_info, false);
}
}
@@ -639,6 +671,13 @@ void NGBoxFragmentPainter::PaintTextChild(const NGPaintFragment& text_fragment,
// Inline blocks should be painted by PaintAtomicInlineChild.
DCHECK(!text_fragment.PhysicalFragment().IsAtomicInline());
+ // Only paint during the foreground/selection phases.
+ if (paint_info.phase != PaintPhase::kForeground &&
+ paint_info.phase != PaintPhase::kSelection &&
+ paint_info.phase != PaintPhase::kTextClip &&
+ paint_info.phase != PaintPhase::kMask)
+ return;
+
// The text clip phase already has a DrawingRecorder. Text clips are initiated
// only in BoxPainterBase::PaintFillLayer, which is already within a
// DrawingRecorder.
@@ -652,21 +691,48 @@ void NGBoxFragmentPainter::PaintTextChild(const NGPaintFragment& text_fragment,
DisplayItem::PaintPhaseToDrawingType(paint_info.phase));
}
- NGTextFragmentPainter text_painter(text_fragment);
- text_painter.Paint(paint_info, paint_offset);
+ const NGPhysicalTextFragment& physical_text_fragment =
+ ToNGPhysicalTextFragment(text_fragment.PhysicalFragment());
+ if (physical_text_fragment.TextType() ==
+ NGPhysicalTextFragment::kSymbolMarker) {
+ // The NGInlineItem of marker might be Split(). So PaintSymbol only if the
+ // StartOffset is 0, or it might be painted several times.
+ if (!physical_text_fragment.StartOffset())
+ PaintSymbol(text_fragment, paint_info, paint_offset);
+ } else {
+ NGTextFragmentPainter text_painter(text_fragment);
+ text_painter.Paint(paint_info, paint_offset);
+ }
+}
+
+void NGBoxFragmentPainter::PaintSymbol(const NGPaintFragment& fragment,
+ const PaintInfo& paint_info,
+ const LayoutPoint& paint_offset) {
+ const ComputedStyle& style = fragment.Style();
+ LayoutRect marker_rect =
+ LayoutListMarker::RelativeSymbolMarkerRect(style, fragment.Size().width);
+ marker_rect.MoveBy(fragment.Offset().ToLayoutPoint());
+ marker_rect.MoveBy(paint_offset);
+ IntRect rect = PixelSnappedIntRect(marker_rect);
+
+ ListMarkerPainter::PaintSymbol(paint_info, fragment.GetLayoutObject(), style,
+ rect);
}
-void NGBoxFragmentPainter::PaintAtomicInline(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+// Follows BlockPainter::PaintInlineBox
+void NGBoxFragmentPainter::PaintAtomicInline(const PaintInfo& paint_info) {
if (paint_info.phase != PaintPhase::kForeground &&
- paint_info.phase != PaintPhase::kSelection)
+ paint_info.phase != PaintPhase::kSelection &&
+ paint_info.phase != PaintPhase::kSelfBlockBackgroundOnly)
return;
// Text clips are painted only for the direct inline children of the object
// that has a text clip style on it, not block children.
DCHECK(paint_info.phase != PaintPhase::kTextClip);
- PaintAllPhasesAtomically(paint_info, paint_offset);
+ bool is_self_painting = PhysicalFragment().Layer() &&
+ PhysicalFragment().Layer()->IsSelfPaintingLayer();
+ PaintAllPhasesAtomically(paint_info, is_self_painting);
}
bool NGBoxFragmentPainter::
@@ -688,17 +754,7 @@ void NGBoxFragmentPainter::PaintOverflowControlsIfNeeded(
if (box_fragment_.HasOverflowClip() &&
box_fragment_.Style().Visibility() == EVisibility::kVisible &&
ShouldPaintSelfBlockBackground(paint_info.phase)) {
- const NGPhysicalBoxFragment& fragment = PhysicalFragment();
- base::Optional<ClipRecorder> clip_recorder;
- if (!fragment.Layer()->IsSelfPaintingLayer()) {
- LayoutRect clip_rect =
- LayoutRect(LayoutPoint(), fragment.Size().ToLayoutSize());
- clip_rect.MoveBy(paint_offset);
- clip_recorder.emplace(paint_info.context, box_fragment_,
- DisplayItem::kClipScrollbarsToBoxBounds,
- PixelSnappedIntRect(clip_rect));
- }
- ScrollableAreaPainter(*fragment.Layer()->GetScrollableArea())
+ ScrollableAreaPainter(*PhysicalFragment().Layer()->GetScrollableArea())
.PaintOverflowControls(paint_info, RoundedIntPoint(paint_offset),
false /* painting_overlay_controls */);
}
@@ -706,17 +762,18 @@ void NGBoxFragmentPainter::PaintOverflowControlsIfNeeded(
bool NGBoxFragmentPainter::IntersectsPaintRect(
const PaintInfo& paint_info,
- const LayoutPoint& adjusted_paint_offset) const {
+ const LayoutPoint& paint_offset) const {
// TODO(layout-dev): Add support for scrolling, see
// BlockPainter::IntersectsPaintRect.
- LayoutRect overflow_rect(box_fragment_.VisualOverflowRect());
- overflow_rect.MoveBy(adjusted_paint_offset);
+ LayoutRect overflow_rect(box_fragment_.SelfInkOverflow());
+ overflow_rect.MoveBy(paint_offset);
return paint_info.GetCullRect().IntersectsCullRect(overflow_rect);
}
void NGBoxFragmentPainter::PaintTextClipMask(GraphicsContext& context,
const IntRect& mask_rect,
- const LayoutPoint& paint_offset) {
+ const LayoutPoint& paint_offset,
+ bool object_has_multiple_boxes) {
PaintInfo paint_info(context, mask_rect, PaintPhase::kTextClip,
kGlobalPaintNormalPhase, 0);
const LayoutSize local_offset = box_fragment_.Offset().ToLayoutSize();
@@ -733,7 +790,7 @@ void NGBoxFragmentPainter::PaintTextClipMask(GraphicsContext& context,
}
}
-LayoutRect NGBoxFragmentPainter::AdjustForScrolledContent(
+LayoutRect NGBoxFragmentPainter::AdjustRectForScrolledContent(
const PaintInfo& paint_info,
const BoxPainterBase::FillLayerInfo& info,
const LayoutRect& rect) {
@@ -792,21 +849,9 @@ bool NGBoxFragmentPainter::IsInSelfHitTestingPhase(HitTestAction action) const {
bool NGBoxFragmentPainter::NodeAtPoint(
HitTestResult& result,
const HitTestLocation& location_in_container,
- const LayoutPoint& accumulated_offset,
- const LayoutPoint& accumulated_offset_for_legacy,
+ const LayoutPoint& physical_offset,
HitTestAction action) {
// TODO(eae): Switch to using NG geometry types.
- LayoutSize offset;
- if (box_fragment_.PhysicalFragment().IsPlacedByLayoutNG()) {
- offset =
- LayoutSize(box_fragment_.Offset().left, box_fragment_.Offset().top);
- } else {
- LayoutPoint location =
- ToLayoutBox(box_fragment_.PhysicalFragment().GetLayoutObject())
- ->Location();
- offset = LayoutSize(location.X(), location.Y());
- }
- LayoutPoint adjusted_location = accumulated_offset + offset;
LayoutSize size(box_fragment_.Size().width, box_fragment_.Size().height);
const ComputedStyle& style = box_fragment_.Style();
@@ -815,7 +860,7 @@ bool NGBoxFragmentPainter::NodeAtPoint(
// TODO(layout-dev): Add support for hit testing overflow controls once we
// overflow has been implemented.
// if (hit_test_self && HasOverflowClip() &&
- // HitTestOverflowControl(result, location_in_container, adjusted_location))
+ // HitTestOverflowControl(result, location_in_container, physical_offset))
// return true;
bool skip_children = false;
@@ -825,38 +870,39 @@ bool NGBoxFragmentPainter::NodeAtPoint(
// so only do the overflow clip check here for non-self-painting layers.
if (!box_fragment_.HasSelfPaintingLayer() &&
!location_in_container.Intersects(PhysicalFragment().OverflowClipRect(
- adjusted_location, kExcludeOverlayScrollbarSizeForHitTesting))) {
+ physical_offset, kExcludeOverlayScrollbarSizeForHitTesting))) {
skip_children = true;
}
if (!skip_children && style.HasBorderRadius()) {
- LayoutRect bounds_rect(adjusted_location, size);
+ LayoutRect bounds_rect(physical_offset, size);
skip_children = !location_in_container.Intersects(
style.GetRoundedInnerBorderFor(bounds_rect));
}
}
- // TODO(layout-dev): Accumulate |accumulated_offset_for_legacy| properly.
- LayoutPoint adjusted_location_for_legacy =
- accumulated_offset_for_legacy + offset;
- if (!skip_children &&
- HitTestChildren(result, box_fragment_.Children(), location_in_container,
- adjusted_location, adjusted_location_for_legacy,
- action)) {
- return true;
+ if (!skip_children) {
+ const IntSize scrolled_offset =
+ box_fragment_.HasOverflowClip()
+ ? PhysicalFragment().ScrolledContentOffset()
+ : IntSize();
+ if (HitTestChildren(result, box_fragment_.Children(), location_in_container,
+ physical_offset - scrolled_offset, action)) {
+ return true;
+ }
}
if (style.HasBorderRadius() &&
- HitTestClippedOutByBorder(location_in_container, adjusted_location))
+ HitTestClippedOutByBorder(location_in_container, physical_offset))
return false;
// Now hit test ourselves.
if (hit_test_self && VisibleToHitTestRequest(result.GetHitTestRequest())) {
- LayoutRect bounds_rect(adjusted_location, size);
+ LayoutRect bounds_rect(physical_offset, size);
if (location_in_container.Intersects(bounds_rect)) {
- Node* node = box_fragment_.GetNode();
+ Node* node = box_fragment_.NodeForHitTest();
if (!result.InnerNode() && node) {
LayoutPoint point =
- location_in_container.Point() - ToLayoutSize(adjusted_location);
+ location_in_container.Point() - ToLayoutSize(physical_offset);
result.SetNodeAndPosition(node, point);
}
if (result.AddNodeToListBasedTestResult(node, location_in_container,
@@ -871,23 +917,18 @@ bool NGBoxFragmentPainter::NodeAtPoint(
bool NGBoxFragmentPainter::VisibleToHitTestRequest(
const HitTestRequest& request) const {
- return box_fragment_.Style().Visibility() == EVisibility::kVisible &&
- (request.IgnorePointerEventsNone() ||
- box_fragment_.Style().PointerEvents() != EPointerEvents::kNone) &&
- !(box_fragment_.GetNode() && box_fragment_.GetNode()->IsInert());
+ return FragmentVisibleToHitTestRequest(box_fragment_, request);
}
bool NGBoxFragmentPainter::HitTestTextFragment(
HitTestResult& result,
const NGPaintFragment& text_paint_fragment,
const HitTestLocation& location_in_container,
- const LayoutPoint& accumulated_offset) {
+ const LayoutPoint& physical_offset) {
const NGPhysicalFragment& text_fragment =
text_paint_fragment.PhysicalFragment();
- LayoutSize offset(text_fragment.Offset().left, text_fragment.Offset().top);
- LayoutPoint adjusted_location = accumulated_offset + offset;
LayoutSize size(text_fragment.Size().width, text_fragment.Size().height);
- LayoutRect border_rect(adjusted_location, size);
+ LayoutRect border_rect(physical_offset, size);
const ComputedStyle& style = text_fragment.Style();
if (style.HasBorderRadius()) {
@@ -901,13 +942,13 @@ bool NGBoxFragmentPainter::HitTestTextFragment(
// TODO(layout-dev): Clip to line-top/bottom.
LayoutRect rect = LayoutRect(PixelSnappedIntRect(border_rect));
- if (VisibleToHitTestRequest(result.GetHitTestRequest()) &&
+ if (FragmentVisibleToHitTestRequest(text_paint_fragment,
+ result.GetHitTestRequest()) &&
location_in_container.Intersects(rect)) {
- Node* node = text_fragment.GetNode();
+ Node* node = text_paint_fragment.NodeForHitTest();
if (!result.InnerNode() && node) {
LayoutPoint point =
- location_in_container.Point() - ToLayoutSize(accumulated_offset) -
- offset +
+ location_in_container.Point() - ToLayoutSize(physical_offset) +
text_paint_fragment.InlineOffsetToContainerBox().ToLayoutPoint();
result.SetNodeAndPosition(node, point);
}
@@ -921,12 +962,60 @@ bool NGBoxFragmentPainter::HitTestTextFragment(
return false;
}
+// Replicates logic in legacy InlineFlowBox::NodeAtPoint().
+bool NGBoxFragmentPainter::HitTestLineBoxFragment(
+ HitTestResult& result,
+ const NGPaintFragment& fragment,
+ const HitTestLocation& location_in_container,
+ const LayoutPoint& physical_offset,
+ HitTestAction action) {
+ if (action != kHitTestForeground)
+ return false;
+
+ const LayoutSize size = fragment.Size().ToLayoutSize();
+
+ // TODO(xiaochengh): Hit test ellipsis box.
+
+ if (HitTestChildren(result, fragment.Children(), location_in_container,
+ physical_offset, action))
+ return true;
+
+ if (!VisibleToHitTestRequest(result.GetHitTestRequest()))
+ return false;
+
+ const LayoutPoint overflow_location =
+ fragment.SelfInkOverflow().Location() + physical_offset;
+ if (HitTestClippedOutByBorder(location_in_container, overflow_location))
+ return false;
+
+ const LayoutRect bounds_rect(physical_offset, size);
+ const ComputedStyle& containing_box_style = box_fragment_.Style();
+ if (containing_box_style.HasBorderRadius() &&
+ !location_in_container.Intersects(
+ containing_box_style.GetRoundedBorderFor(bounds_rect))) {
+ return false;
+ }
+
+ // Now hit test ourselves.
+ if (!location_in_container.Intersects(bounds_rect))
+ return false;
+
+ Node* node = fragment.NodeForHitTest();
+ if (!result.InnerNode() && node) {
+ const LayoutPoint point =
+ location_in_container.Point() - ToLayoutSize(physical_offset) +
+ fragment.InlineOffsetToContainerBox().ToLayoutPoint();
+ result.SetNodeAndPosition(node, point);
+ }
+ return result.AddNodeToListBasedTestResult(node, location_in_container,
+ bounds_rect) == kStopHitTesting;
+}
+
bool NGBoxFragmentPainter::HitTestChildren(
HitTestResult& result,
const Vector<std::unique_ptr<NGPaintFragment>>& children,
const HitTestLocation& location_in_container,
const LayoutPoint& accumulated_offset,
- const LayoutPoint& accumulated_offset_for_legacy,
HitTestAction action) {
for (auto iter = children.rbegin(); iter != children.rend(); iter++) {
const std::unique_ptr<NGPaintFragment>& child = *iter;
@@ -934,37 +1023,60 @@ bool NGBoxFragmentPainter::HitTestChildren(
continue;
const NGPhysicalFragment& fragment = child->PhysicalFragment();
+ const LayoutPoint child_physical_offset =
+ accumulated_offset + fragment.Offset().ToLayoutPoint();
+
bool stop_hit_testing = false;
if (fragment.Type() == NGPhysicalFragment::kFragmentBox) {
if (FragmentRequiresLegacyFallback(fragment)) {
- stop_hit_testing = fragment.GetLayoutObject()->NodeAtPoint(
- result, location_in_container, accumulated_offset_for_legacy,
- action);
+ // Hit test all phases of an inline-block/table or replaced element
+ // atomically, as if it created its own stacking context. (See Appendix
+ // E.2, section 7.4 on inline block/table elements in CSS2.2 spec)
+ bool should_hit_test_all_phases = fragment.IsAtomicInline();
+ // To be passed as |accumulated_offset| to legacy hit test functions of
+ // LayoutBox or subclass overrides, where it isn't in any well-defined
+ // coordinate space, but only equals the difference below.
+ LayoutPoint fallback_accumulated_offset =
+ child_physical_offset -
+ ToLayoutSize(ToLayoutBox(fragment.GetLayoutObject())->Location());
+ if (should_hit_test_all_phases) {
+ stop_hit_testing = fragment.GetLayoutObject()->HitTestAllPhases(
+ result, location_in_container, fallback_accumulated_offset);
+ } else {
+ stop_hit_testing = fragment.GetLayoutObject()->NodeAtPoint(
+ result, location_in_container, fallback_accumulated_offset,
+ action);
+ }
} else {
- // TODO(layout-dev): Accumulate |accumulated_offset_for_legacy|
- // properly.
+ // TODO(layout-dev): Implement HitTestAllPhases in NG after we stop
+ // falling back to legacy for atomic inlines.
stop_hit_testing = NGBoxFragmentPainter(*child).NodeAtPoint(
- result, location_in_container, accumulated_offset,
- accumulated_offset_for_legacy, action);
+ result, location_in_container, child_physical_offset, action);
}
} else if (fragment.Type() == NGPhysicalFragment::kFragmentLineBox) {
- const LayoutSize line_box_offset(fragment.Offset().left,
- fragment.Offset().top);
- const LayoutPoint adjusted_offset = accumulated_offset + line_box_offset;
- // TODO(layout-dev): Accumulate |accumulated_offset_for_legacy| properly.
- stop_hit_testing = HitTestChildren(result, child->Children(),
- location_in_container, adjusted_offset,
- accumulated_offset_for_legacy, action);
+ stop_hit_testing = HitTestLineBoxFragment(
+ result, *child, location_in_container, child_physical_offset, action);
} else if (fragment.Type() == NGPhysicalFragment::kFragmentText) {
// TODO(eae): Should this hit test on the text itself or the containing
// node?
stop_hit_testing = HitTestTextFragment(
- result, *child, location_in_container, accumulated_offset);
+ result, *child, location_in_container, child_physical_offset);
}
if (stop_hit_testing)
return true;
+
+ if (!fragment.IsInline())
+ continue;
+
+ // Hit test culled inline boxes between |fragment| and its parent fragment.
+ const NGPaintFragment* previous_sibling =
+ std::next(iter) == children.rend() ? nullptr : std::next(iter)->get();
+ if (HitTestCulledInlineAncestors(result, *child, previous_sibling,
+ location_in_container,
+ child_physical_offset))
+ return true;
}
return false;
@@ -977,38 +1089,8 @@ bool NGBoxFragmentPainter::HitTestClippedOutByBorder(
LayoutRect rect =
LayoutRect(LayoutPoint(), PhysicalFragment().Size().ToLayoutSize());
rect.MoveBy(border_box_location);
- return !location_in_container.Intersects(style.GetRoundedBorderFor(rect));
-}
-
-LayoutPoint NGBoxFragmentPainter::FlipForWritingModeForChild(
- const NGPhysicalFragment& child_fragment,
- const LayoutPoint& offset) {
- if (!PhysicalFragment().Style().IsFlippedBlocksWritingMode())
- return offset;
-
- LayoutPoint flipped_offset;
- LayoutObject* child_layout_object = child_fragment.GetLayoutObject();
- if (!AdjustPaintOffsetScope::WillUseLegacyLocation(
- ToLayoutBox(child_layout_object)))
- return offset;
- LayoutObject* container_layout_object = box_fragment_.GetLayoutObject();
- DCHECK(child_layout_object->IsBox());
- if (container_layout_object->IsLayoutBlock()) {
- flipped_offset = ToLayoutBlock(container_layout_object)
- ->FlipForWritingModeForChild(
- ToLayoutBox(child_layout_object), offset);
- } else if (container_layout_object->IsInline()) {
- // Reimplementation of LayoutBox::FlipForWritingModeForChild because
- // LayoutInline cannot be an argument to FlipForWritingModeForChild
- NGPhysicalSize container_size = PhysicalFragment().Size();
- LayoutSize child_size = ToLayoutBox(child_layout_object)->Size();
- LayoutPoint child_location = ToLayoutBox(child_layout_object)->Location();
- flipped_offset =
- LayoutPoint(offset.X() + container_size.width - child_size.Width() -
- (2 * child_location.X()),
- offset.Y());
- }
- return flipped_offset;
+ return !location_in_container.Intersects(style.GetRoundedBorderFor(
+ rect, border_edges_.line_left, border_edges_.line_right));
}
const NGPhysicalBoxFragment& NGBoxFragmentPainter::PhysicalFragment() const {
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 c8389f0cb48..fcd0338c8ca 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
@@ -33,14 +33,15 @@ class NGBoxFragmentPainter : public BoxPainterBase {
public:
NGBoxFragmentPainter(const NGPaintFragment&);
- void Paint(const PaintInfo&, const LayoutPoint& paint_offset);
+ void Paint(const PaintInfo&);
void PaintInlineBox(const PaintInfo&, const LayoutPoint& paint_offset);
+ // Hit tests this box fragment.
+ // @param physical_offset Physical offset of this box fragment in paint layer.
// TODO(eae): Change to take a HitTestResult pointer instead as it mutates.
bool NodeAtPoint(HitTestResult&,
const HitTestLocation& location_in_container,
- const LayoutPoint& accumulated_offset,
- const LayoutPoint& accumulated_offset_for_legacy,
+ const LayoutPoint& physical_offset,
HitTestAction);
protected:
@@ -51,24 +52,27 @@ class NGBoxFragmentPainter : public BoxPainterBase {
void PaintTextClipMask(GraphicsContext&,
const IntRect& mask_rect,
- const LayoutPoint& paint_offset) override;
- LayoutRect AdjustForScrolledContent(const PaintInfo&,
- const BoxPainterBase::FillLayerInfo&,
- const LayoutRect&) override;
+ const LayoutPoint& paint_offset,
+ bool object_has_multiple_boxes) override;
+ LayoutRect AdjustRectForScrolledContent(const PaintInfo&,
+ const BoxPainterBase::FillLayerInfo&,
+ const LayoutRect&) override;
private:
bool IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
const NGPaintFragment&,
const PaintInfo&);
- bool IntersectsPaintRect(const PaintInfo&, const LayoutPoint&) const;
-
- void PaintWithAdjustedOffset(PaintInfo&, const LayoutPoint&);
- void PaintBoxDecorationBackground(const PaintInfo&, const LayoutPoint&);
- void PaintAllPhasesAtomically(const PaintInfo&, const LayoutPoint&);
- void PaintBlockChildren(const PaintInfo&, const LayoutPoint&);
+ bool IntersectsPaintRect(const PaintInfo&,
+ const LayoutPoint& paint_offset) const;
+
+ void PaintBoxDecorationBackground(const PaintInfo&,
+ const LayoutPoint& paint_offset);
+ void PaintAllPhasesAtomically(const PaintInfo&,
+ bool is_self_painting);
+ void PaintBlockChildren(const PaintInfo&);
void PaintLineBoxChildren(const Vector<std::unique_ptr<NGPaintFragment>>&,
const PaintInfo&,
- const LayoutPoint&);
+ const LayoutPoint& paint_offset);
void PaintInlineChildren(const Vector<std::unique_ptr<NGPaintFragment>>&,
const PaintInfo&,
const LayoutPoint& paint_offset);
@@ -76,52 +80,70 @@ class NGBoxFragmentPainter : public BoxPainterBase {
const Vector<std::unique_ptr<NGPaintFragment>>&,
const PaintInfo&,
const LayoutPoint& paint_offset);
- void PaintInlineChildBoxUsingLegacyFallback(
- const NGPhysicalFragment&,
- const PaintInfo&,
- const LayoutPoint& paint_offset,
- const LayoutPoint& legacy_paint_offset);
+ void PaintInlineChildBoxUsingLegacyFallback(const NGPhysicalFragment&,
+ const PaintInfo&);
void PaintObject(const PaintInfo&,
const LayoutPoint&,
bool suppress_box_decoration_background = false);
- void PaintBlockFlowContents(const PaintInfo&, const LayoutPoint&);
+ void PaintBlockFlowContents(const PaintInfo&,
+ const LayoutPoint& paint_offset);
void PaintInlineChild(const NGPaintFragment&,
const PaintInfo&,
const LayoutPoint& paint_offset);
- void PaintAtomicInlineChild(const NGPaintFragment&,
- const PaintInfo&,
- const LayoutPoint& paint_offset,
- const LayoutPoint& legacy_paint_offset);
+ void PaintAtomicInlineChild(const NGPaintFragment&, const PaintInfo&);
void PaintTextChild(const NGPaintFragment&,
const PaintInfo&,
const LayoutPoint& paint_offset);
void PaintFloatingChildren(const Vector<std::unique_ptr<NGPaintFragment>>&,
- const PaintInfo&,
- const LayoutPoint& paint_offset);
- void PaintFloats(const PaintInfo&, const LayoutPoint&);
- void PaintMask(const PaintInfo&, const LayoutPoint&);
- void PaintClippingMask(const PaintInfo&, const LayoutPoint&);
- void PaintOverflowControlsIfNeeded(const PaintInfo&, const LayoutPoint&);
- void PaintAtomicInline(const PaintInfo&, const LayoutPoint& paint_offset);
+ const PaintInfo&);
+ void PaintFloats(const PaintInfo&);
+ void PaintMask(const PaintInfo&, const LayoutPoint& paint_offset);
+ void PaintOverflowControlsIfNeeded(const PaintInfo&,
+ const LayoutPoint& paint_offset);
+ void PaintAtomicInline(const PaintInfo&);
void PaintBackground(const PaintInfo&,
const LayoutRect&,
const Color& background_color,
BackgroundBleedAvoidance = kBackgroundBleedNone);
+ void PaintSymbol(const NGPaintFragment&,
+ const PaintInfo&,
+ const LayoutPoint& paint_offset);
bool IsInSelfHitTestingPhase(HitTestAction) const;
bool VisibleToHitTestRequest(const HitTestRequest&) const;
+
+ // Hit tests the children of a container fragment, which is either
+ // |box_fragment_|, or one of its child line box fragments.
+ // @param physical_offset Physical offset of the container fragment's content
+ // box in paint layer. Note that this includes scrolling offset when the
+ // container has 'overflow: scroll'.
bool HitTestChildren(HitTestResult&,
const Vector<std::unique_ptr<NGPaintFragment>>&,
const HitTestLocation& location_in_container,
- const LayoutPoint& accumulated_offset,
- const LayoutPoint& accumulated_offset_for_legacy,
+ const LayoutPoint& physical_offset,
HitTestAction);
+
+ // Hit tests the given text fragment.
+ // @param physical_offset Physical offset of the text fragment in paint layer.
bool HitTestTextFragment(HitTestResult&,
const NGPaintFragment&,
const HitTestLocation& location_in_container,
- const LayoutPoint& accumulated_offset);
+ const LayoutPoint& physical_offset);
+
+ // Hit tests the given line box fragment.
+ // @param physical_offset Physical offset of the line box fragment in paint
+ // layer.
+ bool HitTestLineBoxFragment(HitTestResult&,
+ const NGPaintFragment&,
+ const HitTestLocation& location_in_container,
+ const LayoutPoint& physical_offset,
+ HitTestAction);
+
+ // Returns whether the hit test location is completely outside the border box,
+ // which possibly has rounded corners.
bool HitTestClippedOutByBorder(const HitTestLocation&,
const LayoutPoint& border_box_location) const;
+
LayoutPoint FlipForWritingModeForChild(
const NGPhysicalFragment& child_fragment,
const LayoutPoint& offset);
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 ecc4e71ed9e..25d6ac1a8d6 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
@@ -4,20 +4,23 @@
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
+#include "third_party/blink/renderer/core/dom/pseudo_element.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/inline_box_traversal.h"
#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
#include "third_party/blink/renderer/core/editing/text_affinity.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
-#include "third_party/blink/renderer/core/layout/ng/geometry/ng_logical_offset.h"
-#include "third_party/blink/renderer/core/layout/ng/geometry/ng_logical_size.h"
+#include "third_party/blink/renderer/core/layout/ng/geometry/ng_logical_rect.h"
#include "third_party/blink/renderer/core/layout/ng/geometry/ng_physical_offset_rect.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_caret_position.h"
#include "third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.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_physical_text_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.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_list_marker.h"
#include "third_party/blink/renderer/core/layout/ng/ng_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h"
@@ -28,33 +31,67 @@ namespace blink {
namespace {
-NGPhysicalOffsetRect ExpandedSelectionRectForLineBreakIfNeeded(
- const NGPhysicalOffsetRect& rect,
+NGLogicalRect ComputeLogicalRectFor(const NGPhysicalOffsetRect& physical_rect,
+ const NGPaintFragment& paint_fragment) {
+ const WritingMode writing_mode = paint_fragment.Style().GetWritingMode();
+ const TextDirection text_direction =
+ paint_fragment.PhysicalFragment().ResolvedDirection();
+ const NGPhysicalSize outer_size = paint_fragment.Size();
+ const NGLogicalOffset logical_offset = physical_rect.offset.ConvertToLogical(
+ writing_mode, text_direction, outer_size, physical_rect.size);
+ const NGLogicalSize logical_size =
+ physical_rect.size.ConvertToLogical(writing_mode);
+ return {logical_offset, logical_size};
+}
+
+NGPhysicalOffsetRect ComputePhysicalRectFor(
+ const NGLogicalRect& logical_rect,
+ const NGPaintFragment& paint_fragment) {
+ const WritingMode writing_mode = paint_fragment.Style().GetWritingMode();
+ const TextDirection text_direction =
+ paint_fragment.PhysicalFragment().ResolvedDirection();
+ const NGPhysicalSize outer_size = paint_fragment.Size();
+ const NGPhysicalSize physical_size =
+ logical_rect.size.ConvertToPhysical(writing_mode);
+ const NGPhysicalOffset physical_offset =
+ logical_rect.offset.ConvertToPhysical(writing_mode, text_direction,
+ outer_size, physical_size);
+
+ return {physical_offset, physical_size};
+}
+
+NGLogicalRect ExpandedSelectionRectForSoftLineBreakIfNeeded(
+ const NGLogicalRect& rect,
const NGPaintFragment& paint_fragment,
const LayoutSelectionStatus& selection_status) {
// Expand paint rect if selection covers multiple lines and
// this fragment is at the end of line.
- if (selection_status.line_break == SelectLineBreak::kNotSelected)
+ if (selection_status.line_break == SelectSoftLineBreak::kNotSelected)
return rect;
if (paint_fragment.GetLayoutObject()
->EnclosingNGBlockFlow()
->ShouldTruncateOverflowingText())
return rect;
- // Copy from InlineTextBoxPainter.
- const NGPaintFragment* container_line_box = paint_fragment.ContainerLineBox();
- DCHECK(container_line_box);
- const NGPhysicalLineBoxFragment& physical_line_box =
- ToNGPhysicalLineBoxFragment(container_line_box->PhysicalFragment());
+ // Copy from InlineTextBoxPainter::PaintSelection.
const LayoutUnit space_width(paint_fragment.Style().GetFont().SpaceWidth());
- const NGPhysicalSize expanded_size(rect.size.width + space_width,
- rect.size.height);
- // TODO(yoichio): Support vertical writing mode.
- // Consider sharing physical directional algorithm with ng_caret_rect.cc.
- if (IsLtr(physical_line_box.BaseDirection()))
- return NGPhysicalOffsetRect(rect.offset, expanded_size);
- return NGPhysicalOffsetRect(
- NGPhysicalOffset(rect.offset.left - space_width, rect.offset.top),
- expanded_size);
+ return {rect.offset,
+ {rect.size.inline_size + space_width, rect.size.block_size}};
+}
+
+// Expands selection height so that the selection rect fills entire line.
+NGLogicalRect ExpandSelectionRectToLineHeight(
+ const NGLogicalRect& rect,
+ const NGPaintFragment& paint_fragment) {
+ const NGPaintFragment* current_line = paint_fragment.ContainerLineBox();
+ DCHECK(current_line);
+ const NGPhysicalOffsetRect line_physical_rect(
+ current_line->InlineOffsetToContainerBox() -
+ paint_fragment.InlineOffsetToContainerBox(),
+ current_line->Size());
+ const NGLogicalRect line_logical_rect =
+ ComputeLogicalRectFor(line_physical_rect, paint_fragment);
+ return {{rect.offset.inline_offset, line_logical_rect.offset.block_offset},
+ {rect.size.inline_size, line_logical_rect.size.block_size}};
}
NGLogicalOffset ChildLogicalOffsetInParent(const NGPaintFragment& child) {
@@ -92,6 +129,25 @@ base::Optional<PositionWithAffinity> PositionForPointInChild(
return base::nullopt;
}
+// ::before, ::after and ::first-letter can be hit test targets.
+bool CanBeHitTestTargetPseudoNode(const Node& node) {
+ if (!node.IsPseudoElement())
+ return false;
+ switch (ToPseudoElement(node).GetPseudoId()) {
+ case kPseudoIdBefore:
+ case kPseudoIdAfter:
+ case kPseudoIdFirstLetter:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool IsLastBRInPage(const NGPhysicalTextFragment& text_fragment) {
+ return text_fragment.GetLayoutObject()->IsBR() &&
+ !text_fragment.GetLayoutObject()->NextInPreOrder();
+}
+
} // namespace
NGPaintFragment::NGPaintFragment(
@@ -101,6 +157,10 @@ NGPaintFragment::NGPaintFragment(
DCHECK(physical_fragment_);
}
+NGPaintFragment::~NGPaintFragment() {
+ NGAbstractInlineTextBox::WillDestroy(this);
+}
+
std::unique_ptr<NGPaintFragment> NGPaintFragment::Create(
scoped_refptr<const NGPhysicalFragment> fragment) {
std::unique_ptr<NGPaintFragment> paint_fragment =
@@ -114,6 +174,16 @@ std::unique_ptr<NGPaintFragment> NGPaintFragment::Create(
return paint_fragment;
}
+bool NGPaintFragment::IsDescendantOfNotSelf(
+ const NGPaintFragment& ancestor) const {
+ for (const NGPaintFragment* fragment = Parent(); fragment;
+ fragment = fragment->Parent()) {
+ if (fragment == &ancestor)
+ return true;
+ }
+ return false;
+}
+
bool NGPaintFragment::HasSelfPaintingLayer() const {
return physical_fragment_->IsBox() &&
ToNGPhysicalBoxFragment(*physical_fragment_).HasSelfPaintingLayer();
@@ -129,8 +199,12 @@ bool NGPaintFragment::ShouldClipOverflow() const {
ToNGPhysicalBoxFragment(*physical_fragment_).ShouldClipOverflow();
}
-LayoutRect NGPaintFragment::VisualOverflowRect() const {
- return physical_fragment_->VisualRectWithContents().ToLayoutRect();
+LayoutRect NGPaintFragment::SelfInkOverflow() const {
+ return physical_fragment_->InkOverflow().ToLayoutRect();
+}
+
+LayoutRect NGPaintFragment::ChildrenInkOverflow() const {
+ return physical_fragment_->InkOverflow(false).ToLayoutRect();
}
// Populate descendants from NGPhysicalFragment tree.
@@ -227,7 +301,7 @@ bool NGPaintFragment::FlippedLocalVisualRectFor(
for (NGPaintFragment* fragment : fragments) {
NGPhysicalOffsetRect child_visual_rect =
- fragment->PhysicalFragment().SelfVisualRect();
+ fragment->PhysicalFragment().SelfInkOverflow();
child_visual_rect.offset += fragment->InlineOffsetToContainerBox();
visual_rect->Unite(child_visual_rect.ToLayoutRect());
}
@@ -268,6 +342,7 @@ void NGPaintFragment::PaintInlineBoxForDescendants(
const LayoutPoint& paint_offset,
const LayoutInline* layout_object,
NGPhysicalOffset offset) const {
+ DCHECK(layout_object);
for (const auto& child : Children()) {
if (child->GetLayoutObject() == layout_object) {
NGBoxFragmentPainter(*child).PaintInlineBox(
@@ -280,18 +355,6 @@ void NGPaintFragment::PaintInlineBoxForDescendants(
}
}
-LayoutRect NGPaintFragment::PartialInvalidationRect() const {
- // TODO(yochio): On SlimmingPaintV175, this function is used to invalidate old selected rect in
- // this fragment by PaintController::GenerateRasterInvalidation.
- // So far we just return enclosing block flow's visual rect to pass layout test
- // but this makes performance worse. We should return LayoutRect on that
- // ng_text_fragment_painter::PaintSelection paints selection.
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
- const NGPaintFragment* block_fragment =
- GetLayoutObject()->EnclosingNGBlockFlow()->PaintFragment();
- return block_fragment->VisualRect();
-}
-
const NGPaintFragment* NGPaintFragment::ContainerLineBox() const {
DCHECK(PhysicalFragment().IsInline());
for (const NGPaintFragment* runner = this; runner;
@@ -327,15 +390,44 @@ void NGPaintFragment::SetShouldDoFullPaintInvalidationForFirstLine() {
line_box->SetShouldDoFullPaintInvalidationRecursively();
}
-NGPhysicalOffsetRect NGPaintFragment::ComputeLocalSelectionRect(
+NGPhysicalOffsetRect NGPaintFragment::ComputeLocalSelectionRectForText(
const LayoutSelectionStatus& selection_status) const {
- const NGPhysicalOffsetRect& selection_rect =
- ToNGPhysicalTextFragmentOrDie(PhysicalFragment())
- .LocalRect(selection_status.start, selection_status.end);
- const NGPhysicalOffsetRect line_break_extended_rect =
- ExpandedSelectionRectForLineBreakIfNeeded(selection_rect, *this,
- selection_status);
- return line_break_extended_rect;
+ const NGPhysicalTextFragment& text_fragment =
+ ToNGPhysicalTextFragmentOrDie(PhysicalFragment());
+ NGPhysicalOffsetRect selection_rect =
+ text_fragment.LocalRect(selection_status.start, selection_status.end);
+ NGLogicalRect logical_rect = ComputeLogicalRectFor(selection_rect, *this);
+ // Let LocalRect for line break have a space width to paint line break
+ // when it is only character in a line or only selected in a line.
+ if (text_fragment.IsLineBreak() &&
+ selection_status.start != selection_status.end &&
+ // This is for old compatible that old doesn't paint last br in a page.
+ !IsLastBRInPage(text_fragment)) {
+ DCHECK(!logical_rect.size.inline_size);
+ logical_rect.size.inline_size = LayoutUnit(Style().GetFont().SpaceWidth());
+ }
+ const NGLogicalRect line_break_extended_rect =
+ text_fragment.IsLineBreak()
+ ? logical_rect
+ : ExpandedSelectionRectForSoftLineBreakIfNeeded(logical_rect, *this,
+ selection_status);
+ const NGLogicalRect line_height_expanded_rect =
+ ExpandSelectionRectToLineHeight(line_break_extended_rect, *this);
+ const NGPhysicalOffsetRect physical_rect =
+ ComputePhysicalRectFor(line_height_expanded_rect, *this);
+ return physical_rect;
+}
+
+NGPhysicalOffsetRect NGPaintFragment::ComputeLocalSelectionRectForReplaced()
+ const {
+ DCHECK(GetLayoutObject()->IsLayoutReplaced());
+ const NGPhysicalOffsetRect selection_rect = PhysicalFragment().LocalRect();
+ NGLogicalRect logical_rect = ComputeLogicalRectFor(selection_rect, *this);
+ const NGLogicalRect line_height_expanded_rect =
+ ExpandSelectionRectToLineHeight(logical_rect, *this);
+ const NGPhysicalOffsetRect physical_rect =
+ ComputePhysicalRectFor(line_height_expanded_rect, *this);
+ return physical_rect;
}
PositionWithAffinity NGPaintFragment::PositionForPointInText(
@@ -350,16 +442,12 @@ PositionWithAffinity NGPaintFragment::PositionForPointInText(
text_offset < text_fragment.EndOffset()) {
const Position position = NGOffsetMapping::GetFor(GetLayoutObject())
->GetFirstPosition(text_offset);
- // TODO(xiaochengh): Adjust TextAffinity.
return PositionWithAffinity(position, TextAffinity::kDownstream);
}
const NGCaretPosition unadjusted_position{
this, NGCaretPositionType::kAtTextOffset, text_offset};
- const Position adjusted_position =
- BidiAdjustment::AdjustForHitTest(unadjusted_position)
- .ToPositionInDOMTree();
- // TODO(xiaochengh): Adjust TextAffinity.
- return PositionWithAffinity(adjusted_position, TextAffinity::kDownstream);
+ return BidiAdjustment::AdjustForHitTest(unadjusted_position)
+ .ToPositionInDOMTreeWithAffinity();
}
PositionWithAffinity NGPaintFragment::PositionForPointInInlineLevelBox(
@@ -525,4 +613,75 @@ PositionWithAffinity NGPaintFragment::PositionForPoint(
return PositionForPointInInlineLevelBox(point);
}
+Node* NGPaintFragment::NodeForHitTest() const {
+ if (GetNode())
+ return GetNode();
+
+ if (PhysicalFragment().IsLineBox())
+ return Parent()->NodeForHitTest();
+
+ // When the fragment is a list marker, return the list item.
+ if (GetLayoutObject() && GetLayoutObject()->IsLayoutNGListMarker())
+ return ToLayoutNGListMarker(GetLayoutObject())->ListItem()->GetNode();
+
+ for (const NGPaintFragment* runner = Parent(); runner;
+ runner = runner->Parent()) {
+ // When the fragment is inside a ::first-letter, ::before or ::after pseudo
+ // node, return the pseudo node.
+ if (Node* node = runner->GetNode()) {
+ if (CanBeHitTestTargetPseudoNode(*node))
+ return node;
+ return nullptr;
+ }
+
+ // When the fragment is inside a list marker, return the list item.
+ if (runner->GetLayoutObject() &&
+ runner->GetLayoutObject()->IsLayoutNGListMarker()) {
+ return runner->NodeForHitTest();
+ }
+ }
+
+ return nullptr;
+}
+
+// ----
+
+NGPaintFragment& NGPaintFragment::FragmentRange::front() const {
+ DCHECK(first_);
+ return *first_;
+}
+
+NGPaintFragment& NGPaintFragment::FragmentRange::back() const {
+ DCHECK(first_);
+ NGPaintFragment* last = first_;
+ for (NGPaintFragment* fragment : *this)
+ last = fragment;
+ return *last;
+}
+
+String NGPaintFragment::DebugName() const {
+ StringBuilder name;
+
+ DCHECK(physical_fragment_);
+ const NGPhysicalFragment& physical_fragment = *physical_fragment_;
+ if (physical_fragment.IsBox()) {
+ name.Append("NGPhysicalBoxFragment");
+ if (LayoutObject* layout_object = physical_fragment.GetLayoutObject()) {
+ DCHECK(physical_fragment.IsBox());
+ name.Append(' ');
+ name.Append(layout_object->DebugName());
+ }
+ } else if (physical_fragment.IsText()) {
+ name.Append("NGPhysicalTextFragment '");
+ name.Append(ToNGPhysicalTextFragment(physical_fragment).Text());
+ name.Append('\'');
+ } else if (physical_fragment.IsLineBox()) {
+ name.Append("NGPhysicalLineBoxFragment");
+ } else {
+ NOTREACHED();
+ }
+
+ return name.ToString();
+}
+
} // namespace blink
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 faea365419e..370ad8cd32e 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
@@ -5,6 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_PAINT_FRAGMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_NG_NG_PAINT_FRAGMENT_H_
+#include <iterator>
+
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h"
#include "third_party/blink/renderer/core/loader/resource/image_resource_observer.h"
@@ -36,6 +38,7 @@ class CORE_EXPORT NGPaintFragment : public DisplayItemClient,
public ImageResourceObserver {
public:
NGPaintFragment(scoped_refptr<const NGPhysicalFragment>, NGPaintFragment*);
+ ~NGPaintFragment() override;
static std::unique_ptr<NGPaintFragment> Create(
scoped_refptr<const NGPhysicalFragment>);
@@ -50,6 +53,10 @@ class CORE_EXPORT NGPaintFragment : public DisplayItemClient,
const Vector<std::unique_ptr<NGPaintFragment>>& Children() const {
return children_;
}
+ // Note, as the name implies, |IsDescendantOfNotSelf| returns false for the
+ // same object. This is different from |LayoutObject::IsDescendant| but is
+ // same as |Node::IsDescendant|.
+ bool IsDescendantOfNotSelf(const NGPaintFragment&) const;
// Returns the first line box for a block-level container.
NGPaintFragment* FirstLineBox() const;
@@ -74,14 +81,24 @@ class CORE_EXPORT NGPaintFragment : public DisplayItemClient,
bool HasOverflowClip() const;
bool ShouldClipOverflow() const;
bool HasSelfPaintingLayer() const;
+ // This is equivalent to LayoutObject::VisualRect
LayoutRect VisualRect() const override { return visual_rect_; }
void SetVisualRect(const LayoutRect& rect) { visual_rect_ = rect; }
- LayoutRect VisualOverflowRect() const;
- LayoutRect PartialInvalidationRect() const override;
+ LayoutRect SelectionVisualRect() const { return selection_visual_rect_; }
+ void SetSelectionVisualRect(const LayoutRect& rect) {
+ selection_visual_rect_ = rect;
+ }
+
+ // CSS ink overflow https://www.w3.org/TR/css-overflow-3/#ink
+ // Encloses all pixels painted by self + children.
+ LayoutRect SelfInkOverflow() const;
+ // Union of children's ink overflows.
+ LayoutRect ChildrenInkOverflow() const;
- NGPhysicalOffsetRect ComputeLocalSelectionRect(
+ NGPhysicalOffsetRect ComputeLocalSelectionRectForText(
const LayoutSelectionStatus&) const;
+ NGPhysicalOffsetRect ComputeLocalSelectionRectForReplaced() const;
// Set ShouldDoFullPaintInvalidation flag in the corresponding LayoutObject
// recursively.
@@ -99,7 +116,7 @@ class CORE_EXPORT NGPaintFragment : public DisplayItemClient,
NGPhysicalOffset = {}) const;
// DisplayItemClient methods.
- String DebugName() const override { return "NGPaintFragment"; }
+ String DebugName() const override;
// Commonly used functions for NGPhysicalFragment.
Node* GetNode() const { return PhysicalFragment().GetNode(); }
@@ -114,8 +131,12 @@ class CORE_EXPORT NGPaintFragment : public DisplayItemClient,
// in DOM tree.
PositionWithAffinity PositionForPoint(const NGPhysicalOffset&) const;
+ // The node to return when hit-testing on this fragment. This can be different
+ // from GetNode() when this fragment is content of a pseudo node.
+ Node* NodeForHitTest() const;
+
// A range of fragments for |FragmentsFor()|.
- class FragmentRange {
+ class CORE_EXPORT FragmentRange {
public:
explicit FragmentRange(
NGPaintFragment* first,
@@ -130,15 +151,17 @@ class CORE_EXPORT NGPaintFragment : public DisplayItemClient,
bool IsEmpty() const { return !first_; }
- class iterator {
+ class iterator final
+ : public std::iterator<std::forward_iterator_tag, NGPaintFragment*> {
public:
explicit iterator(NGPaintFragment* first) : current_(first) {}
NGPaintFragment* operator*() const { return current_; }
NGPaintFragment* operator->() const { return current_; }
- void operator++() {
+ iterator& operator++() {
CHECK(current_);
current_ = current_->next_fragment_;
+ return *this;
}
bool operator==(const iterator& other) const {
return current_ == other.current_;
@@ -154,6 +177,16 @@ class CORE_EXPORT NGPaintFragment : public DisplayItemClient,
iterator begin() const { return iterator(first_); }
iterator end() const { return iterator(nullptr); }
+ // Returns the first |NGPaintFragment| in |FragmentRange| as STL container.
+ // It is error to call |front()| for empty range.
+ NGPaintFragment& front() const;
+
+ // Returns the last |NGPaintFragment| in |FragmentRange| as STL container.
+ // It is error to call |back()| for empty range.
+ // Note: The complicity of |back()| is O(n) where n is number of elements
+ // in this |FragmentRange|.
+ NGPaintFragment& back() const;
+
private:
NGPaintFragment* first_;
bool is_in_layout_ng_inline_formatting_context_;
@@ -221,6 +254,7 @@ class CORE_EXPORT NGPaintFragment : public DisplayItemClient,
//
LayoutRect visual_rect_;
+ LayoutRect selection_visual_rect_;
};
} // namespace blink
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 be8d9fdc6c3..1710a6c5185 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
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/editing/frame_selection.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_physical_text_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/layout_ng_block_flow.h"
@@ -190,6 +191,7 @@ TEST_F(NGPaintFragmentTest, InlineBlock) {
<span id="box1">X</span><span id="box2">Y</span></div>
</body>
)HTML");
+
const NGPaintFragment* container = GetPaintFragmentByElementId("container");
EXPECT_TRUE(container);
EXPECT_EQ(1u, container->Children().size());
@@ -205,6 +207,7 @@ TEST_F(NGPaintFragmentTest, InlineBlock) {
.ToString());
// TODO(kojii): This is still incorrect.
EXPECT_EQ(LayoutRect(0, 0, 60, 10), outer_text.VisualRect());
+ EXPECT_EQ(LayoutRect(), outer_text.SelectionVisualRect());
// Test |InlineFragmentsFor| can find the outer text.
LayoutObject* layout_outer_text =
@@ -221,6 +224,7 @@ TEST_F(NGPaintFragmentTest, InlineBlock) {
EXPECT_EQ(NGPhysicalFragment::kAtomicInline,
box1.PhysicalFragment().BoxType());
EXPECT_EQ(LayoutRect(60, 0, 10, 10), box1.VisualRect());
+ EXPECT_EQ(LayoutRect(), box1.SelectionVisualRect());
// Test |InlineFragmentsFor| can find "box1".
LayoutObject* layout_box1 = GetLayoutObjectByElementId("box1");
@@ -241,6 +245,7 @@ TEST_F(NGPaintFragmentTest, InlineBlock) {
EXPECT_EQ(NGPhysicalFragment::kFragmentText,
inner_text.PhysicalFragment().Type());
EXPECT_EQ(LayoutRect(60, 0, 10, 10), inner_text.VisualRect());
+ EXPECT_EQ(LayoutRect(), inner_text.SelectionVisualRect());
// Test |InlineFragmentsFor| can find the inner text of "box1".
LayoutObject* layout_inner_text = layout_box1->SlowFirstChild();
@@ -256,6 +261,18 @@ TEST_F(NGPaintFragmentTest, InlineBlock) {
EXPECT_EQ(NGPhysicalFragment::kAtomicInline,
box2.PhysicalFragment().BoxType());
EXPECT_EQ(LayoutRect(70, 10, 10, 10), box2.VisualRect());
+ EXPECT_EQ(LayoutRect(), box2.SelectionVisualRect());
+
+ GetDocument().GetFrame()->Selection().SelectAll();
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ EXPECT_EQ(LayoutRect(0, 0, 60, 10), outer_text.VisualRect());
+ EXPECT_EQ(LayoutRect(0, 0, 60, 10), outer_text.SelectionVisualRect());
+ EXPECT_EQ(LayoutRect(60, 0, 10, 10), box1.VisualRect());
+ EXPECT_EQ(LayoutRect(), box1.SelectionVisualRect());
+ EXPECT_EQ(LayoutRect(60, 0, 10, 10), inner_text.VisualRect());
+ EXPECT_EQ(LayoutRect(60, 0, 10, 10), inner_text.SelectionVisualRect());
+ EXPECT_EQ(LayoutRect(70, 10, 10, 10), box2.VisualRect());
+ EXPECT_EQ(LayoutRect(), box2.SelectionVisualRect());
}
TEST_F(NGPaintFragmentTest, RelativeBlock) {
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.cc
index 614854c6238..aad88b113e8 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.cc
@@ -143,8 +143,113 @@ NGPaintFragmentTraversalContext NextSiblingOf(
return {fragment.parent, fragment.index + 1};
}
+unsigned IndexOfChild(const NGPaintFragment& parent,
+ const NGPaintFragment& fragment) {
+ const auto& children = parent.Children();
+ const auto* it = std::find_if(
+ children.begin(), children.end(),
+ [&fragment](const auto& child) { return &fragment == child.get(); });
+ DCHECK(it != children.end());
+ return std::distance(children.begin(), it);
+}
+
} // namespace
+NGPaintFragmentTraversal::NGPaintFragmentTraversal(const NGPaintFragment& root)
+ : root_(root) {
+ Push(root, 0);
+}
+
+NGPaintFragmentTraversal::NGPaintFragmentTraversal(const NGPaintFragment& root,
+ const NGPaintFragment& start)
+ : root_(root) {
+ MoveTo(start);
+}
+
+void NGPaintFragmentTraversal::Push(const NGPaintFragment& parent,
+ unsigned index) {
+ stack_.push_back(ParentAndIndex{&parent, index});
+ current_ = parent.Children()[index].get();
+}
+
+void NGPaintFragmentTraversal::Push(const NGPaintFragment& fragment) {
+ const NGPaintFragment* parent = fragment.Parent();
+ DCHECK(parent);
+ Push(*parent, IndexOfChild(*parent, fragment));
+}
+
+void NGPaintFragmentTraversal::MoveTo(const NGPaintFragment& fragment) {
+ DCHECK(fragment.IsDescendantOfNotSelf(root_));
+
+ // Because we may not traverse all descendants of |root_|, just push the
+ // specified fragment. Computing its ancestors up to |root_| is deferred to
+ // |MoveToNextSiblingOrAncestor()|.
+ stack_.resize(0);
+ Push(fragment);
+}
+
+void NGPaintFragmentTraversal::MoveToNext() {
+ if (IsAtEnd())
+ return;
+
+ if (!current_->Children().IsEmpty()) {
+ Push(*current_, 0);
+ return;
+ }
+
+ MoveToNextSiblingOrAncestor();
+}
+
+void NGPaintFragmentTraversal::MoveToNextSiblingOrAncestor() {
+ while (!IsAtEnd()) {
+ // Check if we have a next sibling.
+ auto& stack_top = stack_.back();
+ if (++stack_top.index < stack_top.parent->Children().size()) {
+ current_ = stack_top.parent->Children()[stack_top.index].get();
+ return;
+ }
+ MoveToParent();
+ }
+}
+
+void NGPaintFragmentTraversal::MoveToParent() {
+ if (IsAtEnd())
+ return;
+ DCHECK(!stack_.IsEmpty());
+ const NGPaintFragment& parent = *stack_.back().parent;
+ stack_.pop_back();
+ if (&parent == &root_) {
+ DCHECK(stack_.IsEmpty());
+ current_ = nullptr;
+ return;
+ }
+ if (stack_.IsEmpty()) {
+ // We might have started with |MoveTo()|, and thus computing parent stack
+ // was deferred.
+ Push(parent);
+ return;
+ }
+ DCHECK_EQ(&parent,
+ stack_.back().parent->Children()[stack_.back().index].get());
+ current_ = &parent;
+}
+
+void NGPaintFragmentTraversal::MoveToPrevious() {
+ if (IsAtEnd())
+ return;
+ DCHECK(!stack_.IsEmpty());
+ auto& stack_top = stack_.back();
+ if (stack_top.index == 0) {
+ // There is no previous sibling of |current_|. We move to parent.
+ MoveToParent();
+ return;
+ }
+ --stack_top.index;
+ current_ = stack_top.parent->Children()[stack_top.index].get();
+ while (!current_->Children().IsEmpty())
+ Push(*current_, current_->Children().size() - 1);
+}
+
Vector<NGPaintFragmentWithContainerOffset>
NGPaintFragmentTraversal::DescendantsOf(const NGPaintFragment& container) {
Vector<NGPaintFragmentWithContainerOffset> result;
@@ -198,14 +303,7 @@ NGPaintFragmentTraversalContext NGPaintFragmentTraversalContext::Create(
const NGPaintFragment* fragment) {
if (!fragment)
return NGPaintFragmentTraversalContext();
-
- DCHECK(fragment->Parent());
- const auto& siblings = fragment->Parent()->Children();
- const auto* self_iter = std::find_if(
- siblings.begin(), siblings.end(),
- [&fragment](const auto& sibling) { return fragment == sibling.get(); });
- DCHECK_NE(self_iter, siblings.end());
- return {fragment->Parent(), self_iter - siblings.begin()};
+ return {fragment->Parent(), IndexOfChild(*fragment->Parent(), *fragment)};
}
NGPaintFragmentTraversalContext NGPaintFragmentTraversal::PreviousInlineLeafOf(
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h
index cd42ac44fc4..e1de32a0e64 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h
@@ -24,7 +24,7 @@ struct CORE_EXPORT NGPaintFragmentWithContainerOffset {
// Represents an NGPaintFragment by its parent and its index in the parent's
// |Children()| vector.
-struct NGPaintFragmentTraversalContext {
+struct CORE_EXPORT NGPaintFragmentTraversalContext {
STACK_ALLOCATED();
static NGPaintFragmentTraversalContext Create(const NGPaintFragment*);
@@ -41,10 +41,63 @@ struct NGPaintFragmentTraversalContext {
};
// Utility class for traversing the paint fragment tree.
+//
+// This class has two groups of functions; one is a traversing cursor, by
+// instantiating and using instance functions. The other is a set of static
+// functions that are similar to DOM traversal functions.
class CORE_EXPORT NGPaintFragmentTraversal {
- STATIC_ONLY(NGPaintFragmentTraversal);
+ STACK_ALLOCATED();
public:
+ // Create an instance to traverse descendants of |root|.
+ explicit NGPaintFragmentTraversal(const NGPaintFragment& root);
+
+ // Create an instance to traverse descendants of |root|, starting at |start|.
+ // Same as constructing with |root| and then |MoveTo()|.
+ NGPaintFragmentTraversal(const NGPaintFragment& root,
+ const NGPaintFragment& start);
+
+ bool IsAtEnd() const { return !current_; }
+ explicit operator bool() const { return !IsAtEnd(); }
+
+ const NGPaintFragment* get() const {
+ DCHECK(current_);
+ return current_;
+ }
+ const NGPaintFragment& operator*() const { return *get(); }
+ const NGPaintFragment* operator->() const { return get(); }
+
+ // Move to the specified fragment. The fragment must be a descendant of
+ // |root|. This function is O(n) where |n| is the number of senior siblings
+ // before |fragment|.
+ void MoveTo(const NGPaintFragment& fragment);
+
+ // Move to the next node using the pre-order depth-first-search.
+ // Note: When |IsAtEnd()| is true, this function does nothing.
+ void MoveToNext();
+
+ // Move to the next sibling, or next ancestor node using the pre-order
+ // depth-first-search, skipping children of the current node.
+ void MoveToNextSiblingOrAncestor();
+
+ // Move to the parent of current fragment. When |current_| is a child of
+ // |root_|, this function makes |IsAtEnd()| to true.
+ // Note: When |IsAtEnd()| is true, this function does nothing.
+ void MoveToParent();
+
+ // Move to the previous node using the pre-order depth-first-search. When
+ // |current_| is the first child of |root_|, this function makes |IsAtEnd()|
+ // to true.
+ // Note: When |IsAtEnd()| is true, this function does nothing.
+ void MoveToPrevious();
+
+ //
+ // Following functions are static, similar to DOM traversal utilities.
+ //
+ // Because fragments have children as a vector, not a two-way list, static
+ // functions are not as cheap as their DOM versions. When traversing more than
+ // once, instace functions are recommended.
+
// Returns descendants without paint layer in preorder.
static Vector<NGPaintFragmentWithContainerOffset> DescendantsOf(
const NGPaintFragment&);
@@ -73,6 +126,33 @@ class CORE_EXPORT NGPaintFragmentTraversal {
const NGPaintFragmentTraversalContext&);
static NGPaintFragmentTraversalContext NextInlineLeafOfIgnoringLineBreak(
const NGPaintFragmentTraversalContext&);
+
+ private:
+ void Push(const NGPaintFragment& parent, unsigned index);
+ void Push(const NGPaintFragment& fragment);
+
+ // |current_| holds a |NGPaintFragment| specified by |index|th child of
+ // |parent| of the last element of |stack_|.
+ const NGPaintFragment* current_ = nullptr;
+
+ // The root of subtree where traversing is taken place. |root_| is excluded
+ // from traversal. |current_| can't |root_|.
+ const NGPaintFragment& root_;
+
+ // The stack of parent and its child index up to the root. Each stack entry
+ // represents the current node, and thus
+ // |stack_.back().parent->Children()[stack_.back().index] == current_|.
+ //
+ // Computing ancestors maybe deferred until |MoveToNextSiblingOrAncestor()|
+ // when |Moveto()| is used. In that case, the |stack_| does not contain all
+ // fragments to the |root_|.
+ struct ParentAndIndex {
+ const NGPaintFragment* parent;
+ unsigned index;
+ };
+ Vector<ParentAndIndex, 4> stack_;
+
+ DISALLOW_COPY_AND_ASSIGN(NGPaintFragmentTraversal);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal_test.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal_test.cc
index 6482613fb70..fcf2c77a241 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal_test.cc
@@ -4,12 +4,15 @@
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/blink/renderer/core/layout/layout_block_flow.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
namespace blink {
+using testing::ElementsAreArray;
+
class NGPaintFragmentTraversalTest : public RenderingTest,
private ScopedLayoutNGForTest {
public:
@@ -28,10 +31,148 @@ class NGPaintFragmentTraversalTest : public RenderingTest,
return root_fragment_->Children();
}
+ Vector<const NGPaintFragment*> ToDepthFirstList(
+ NGPaintFragmentTraversal* traversal) const {
+ Vector<const NGPaintFragment*> results;
+ for (; *traversal; traversal->MoveToNext()) {
+ const NGPaintFragment& fragment = **traversal;
+ results.push_back(&fragment);
+ }
+ return results;
+ }
+
+ Vector<const NGPaintFragment*> ToReverseDepthFirstList(
+ NGPaintFragmentTraversal* traversal) const {
+ Vector<const NGPaintFragment*> results;
+ for (; *traversal; traversal->MoveToPrevious()) {
+ const NGPaintFragment& fragment = **traversal;
+ results.push_back(&fragment);
+ }
+ return results;
+ }
+
LayoutBlockFlow* layout_block_flow_;
NGPaintFragment* root_fragment_;
};
+TEST_F(NGPaintFragmentTraversalTest, MoveToNext) {
+ SetUpHtml("t", R"HTML(
+ <div id=t>
+ line0
+ <span style="background: red">red</span>
+ <br>
+ line1
+ </div>
+ )HTML");
+ NGPaintFragmentTraversal traversal(*root_fragment_);
+ NGPaintFragment* line0 = root_fragment_->Children()[0].get();
+ NGPaintFragment* line1 = root_fragment_->Children()[1].get();
+ NGPaintFragment* span = line0->Children()[1].get();
+ NGPaintFragment* br = line0->Children()[2].get();
+ EXPECT_THAT(ToDepthFirstList(&traversal),
+ ElementsAreArray({line0, line0->Children()[0].get(), span,
+ span->Children()[0].get(), br, line1,
+ line1->Children()[0].get()}));
+}
+
+TEST_F(NGPaintFragmentTraversalTest, MoveToNextWithRoot) {
+ SetUpHtml("t", R"HTML(
+ <div id=t>
+ line0
+ <span style="background: red">red</span>
+ <br>
+ line1
+ </div>
+ )HTML");
+ NGPaintFragment* line0 = root_fragment_->Children()[0].get();
+ NGPaintFragment* span = line0->Children()[1].get();
+ NGPaintFragment* br = line0->Children()[2].get();
+ NGPaintFragmentTraversal traversal(*line0);
+ EXPECT_THAT(ToDepthFirstList(&traversal),
+ ElementsAreArray({line0->Children()[0].get(), span,
+ span->Children()[0].get(), br}));
+}
+
+TEST_F(NGPaintFragmentTraversalTest, MoveToPrevious) {
+ SetUpHtml("t", R"HTML(
+ <div id=t>
+ line0
+ <span style="background: red">red</span>
+ <br>
+ line1
+ </div>
+ )HTML");
+ NGPaintFragmentTraversal traversal(*root_fragment_);
+ NGPaintFragment* line0 = root_fragment_->Children()[0].get();
+ NGPaintFragment* line1 = root_fragment_->Children()[1].get();
+ NGPaintFragment* span = line0->Children()[1].get();
+ NGPaintFragment* br = line0->Children()[2].get();
+ traversal.MoveTo(*line1->Children()[0].get());
+ EXPECT_THAT(ToReverseDepthFirstList(&traversal),
+ ElementsAreArray({line1->Children()[0].get(), line1, br,
+ span->Children()[0].get(), span,
+ line0->Children()[0].get(), line0}));
+}
+
+TEST_F(NGPaintFragmentTraversalTest, MoveToPreviousWithRoot) {
+ SetUpHtml("t", R"HTML(
+ <div id=t>
+ line0
+ <span style="background: red">red</span>
+ <br>
+ line1
+ </div>
+ )HTML");
+ NGPaintFragment* line0 = root_fragment_->Children()[0].get();
+ NGPaintFragment* span = line0->Children()[1].get();
+ NGPaintFragment* br = line0->Children()[2].get();
+ NGPaintFragmentTraversal traversal(*line0);
+ traversal.MoveTo(*br);
+ EXPECT_THAT(ToReverseDepthFirstList(&traversal),
+ ElementsAreArray({br, span->Children()[0].get(), span,
+ line0->Children()[0].get()}));
+}
+
+TEST_F(NGPaintFragmentTraversalTest, MoveTo) {
+ SetUpHtml("t", R"HTML(
+ <div id=t>
+ line0
+ <span style="background: red">red</span>
+ <br>
+ line1
+ </div>
+ )HTML");
+ NGPaintFragmentTraversal traversal(*root_fragment_);
+ NGPaintFragment* line0 = root_fragment_->Children()[0].get();
+ NGPaintFragment* line1 = root_fragment_->Children()[1].get();
+ NGPaintFragment* span = line0->Children()[1].get();
+ NGPaintFragment* br = line0->Children()[2].get();
+ traversal.MoveTo(*span);
+ EXPECT_EQ(span, &*traversal);
+ EXPECT_THAT(ToDepthFirstList(&traversal),
+ ElementsAreArray({span, span->Children()[0].get(), br, line1,
+ line1->Children()[0].get()}));
+}
+
+TEST_F(NGPaintFragmentTraversalTest, MoveToWithRoot) {
+ SetUpHtml("t", R"HTML(
+ <div id=t>
+ line0
+ <span style="background: red">red</span>
+ <br>
+ line1
+ </div>
+ )HTML");
+ NGPaintFragment* line0 = root_fragment_->Children()[0].get();
+ NGPaintFragment* span = line0->Children()[1].get();
+ NGPaintFragment* br = line0->Children()[2].get();
+ NGPaintFragmentTraversal traversal(*line0);
+ traversal.MoveTo(*span);
+ EXPECT_EQ(span, &*traversal);
+ EXPECT_THAT(ToDepthFirstList(&traversal),
+ ElementsAreArray({span, span->Children()[0].get(), br}));
+}
+
TEST_F(NGPaintFragmentTraversalTest, PreviousLineOf) {
SetUpHtml("t", "<div id=t>foo<br>bar</div>");
ASSERT_EQ(2u, RootChildren().size());
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc b/chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc
index 2b2fa38ac1d..ac5b860c2f5 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc
@@ -4,11 +4,20 @@
#include "third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.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/markers/composition_marker.h"
+#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
+#include "third_party/blink/renderer/core/editing/markers/text_match_marker.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/layout/ng/geometry/ng_logical_rect.h"
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping.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_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h"
#include "third_party/blink/renderer/core/layout/ng/ng_text_decoration_offset.h"
+#include "third_party/blink/renderer/core/paint/document_marker_painter.h"
+#include "third_party/blink/renderer/core/paint/inline_text_box_painter.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/ng/ng_text_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
@@ -36,6 +45,8 @@ inline bool ShouldPaintTextFragment(const NGPhysicalTextFragment& text_fragment,
// This code path is only called in PaintPhaseForeground whereas we would
// expect PaintPhaseSelection. The existing haveSelection logic in paint()
// tests for != PaintPhaseTextClip.
+ if (text_fragment.IsLineBreak())
+ return true;
if (!text_fragment.Length() || !text_fragment.TextShapeResult())
return false;
@@ -58,6 +69,171 @@ Color SelectionBackgroundColor(const Document& document,
return color;
}
+DocumentMarkerVector ComputeMarkersToPaint(
+ const NGPaintFragment& paint_fragment) {
+ // TODO(yoichio): Handle first-letter
+ Node* const node = paint_fragment.GetNode();
+ if (!node)
+ return DocumentMarkerVector();
+ // We don't paint any marker on ellipsis.
+ if (paint_fragment.PhysicalFragment().StyleVariant() ==
+ NGStyleVariant::kEllipsis)
+ return DocumentMarkerVector();
+
+ DocumentMarkerController& document_marker_controller =
+ node->GetDocument().Markers();
+ return document_marker_controller.ComputeMarkersToPaint(*node);
+}
+
+unsigned GetTextContentOffset(const Text& text, unsigned offset) {
+ const Position position(text, offset);
+ const NGOffsetMapping* const offset_mapping =
+ NGOffsetMapping::GetFor(position);
+ DCHECK(offset_mapping);
+ const base::Optional<unsigned>& ng_offset =
+ offset_mapping->GetTextContentOffset(position);
+ DCHECK(ng_offset.has_value());
+ return ng_offset.value();
+}
+
+// ClampOffset modifies |offset| fixed in a range of |text_fragment| start/end
+// offsets.
+// |offset| points not each character but each span between character.
+// With that concept, we can clear catch what is inside start / end.
+// Suppose we have "foo_bar"('_' is a space).
+// There are 8 offsets for that:
+// f o o _ b a r
+// 0 1 2 3 4 5 6 7
+// If "bar" is a TextFragment. That start(), end() {4, 7} correspond this
+// offset. If a marker has StartOffset / EndOffset as {2, 6},
+// ClampOffset returns{ 4,6 }, which represents "ba" on "foo_bar".
+unsigned ClampOffset(unsigned offset,
+ const NGPhysicalTextFragment& text_fragment) {
+ return std::min(std::max(offset, text_fragment.StartOffset()),
+ text_fragment.EndOffset());
+}
+
+void PaintRect(GraphicsContext& context,
+ const NGPhysicalOffset& location,
+ const NGPhysicalOffsetRect& rect,
+ const Color color) {
+ if (!color.Alpha())
+ return;
+ if (rect.size.IsEmpty())
+ return;
+ const NGPhysicalOffsetRect global_rect(rect.offset + location, rect.size);
+ context.FillRect(global_rect.ToFloatRect(), color);
+}
+
+LayoutRect MarkerRectForForeground(const NGPhysicalTextFragment& text_fragment,
+ unsigned start_offset,
+ unsigned end_offset) {
+ LayoutUnit start_position, end_position;
+ std::tie(start_position, end_position) =
+ text_fragment.LineLeftAndRightForOffsets(start_offset, end_offset);
+
+ const LayoutUnit height = text_fragment.Size()
+ .ConvertToLogical(static_cast<WritingMode>(
+ text_fragment.Style().GetWritingMode()))
+ .block_size;
+ return {start_position, LayoutUnit(), end_position - start_position, height};
+}
+
+// Copied from InlineTextBoxPainter
+void PaintDocumentMarkers(GraphicsContext& context,
+ const NGPaintFragment& paint_fragment,
+ const DocumentMarkerVector& markers_to_paint,
+ const LayoutPoint& box_origin,
+ const ComputedStyle& style,
+ DocumentMarkerPaintPhase marker_paint_phase,
+ NGTextPainter* text_painter) {
+ if (markers_to_paint.IsEmpty())
+ return;
+
+ const NGPhysicalTextFragment& text_fragment =
+ ToNGPhysicalTextFragmentOrDie(paint_fragment.PhysicalFragment());
+ DCHECK(text_fragment.GetNode());
+ const Text& text = ToTextOrDie(*text_fragment.GetNode());
+ for (const DocumentMarker* marker : markers_to_paint) {
+ const unsigned marker_start_offset =
+ GetTextContentOffset(text, marker->StartOffset());
+ const unsigned marker_end_offset =
+ GetTextContentOffset(text, marker->EndOffset());
+ const unsigned paint_start_offset =
+ ClampOffset(marker_start_offset, text_fragment);
+ const unsigned paint_end_offset =
+ ClampOffset(marker_end_offset, text_fragment);
+ if (paint_start_offset == paint_end_offset)
+ continue;
+
+ switch (marker->GetType()) {
+ case DocumentMarker::kSpelling:
+ case DocumentMarker::kGrammar: {
+ if (context.Printing())
+ break;
+ if (marker_paint_phase == DocumentMarkerPaintPhase::kBackground)
+ continue;
+ DocumentMarkerPainter::PaintDocumentMarker(
+ context, box_origin, style, marker->GetType(),
+ MarkerRectForForeground(text_fragment, paint_start_offset,
+ paint_end_offset));
+ } break;
+
+ case DocumentMarker::kTextMatch: {
+ if (!text_fragment.GetNode()
+ ->GetDocument()
+ .GetFrame()
+ ->GetEditor()
+ .MarkedTextMatchesAreHighlighted())
+ break;
+ const TextMatchMarker& text_match_marker =
+ ToTextMatchMarkerOrDie(*marker);
+ if (marker_paint_phase == DocumentMarkerPaintPhase::kBackground) {
+ const Color color =
+ LayoutTheme::GetTheme().PlatformTextSearchHighlightColor(
+ text_match_marker.IsActiveMatch());
+ PaintRect(
+ context, NGPhysicalOffset(box_origin),
+ text_fragment.LocalRect(paint_start_offset, paint_end_offset),
+ color);
+ break;
+ }
+
+ const TextPaintStyle text_style =
+ DocumentMarkerPainter::ComputeTextPaintStyleFrom(style,
+ text_match_marker);
+ if (text_style.current_color == Color::kTransparent)
+ break;
+ text_painter->Paint(paint_start_offset, paint_end_offset,
+ paint_end_offset - paint_start_offset, text_style);
+ } break;
+
+ case DocumentMarker::kComposition:
+ case DocumentMarker::kActiveSuggestion:
+ case DocumentMarker::kSuggestion: {
+ const StyleableMarker& styleable_marker = ToStyleableMarker(*marker);
+ if (marker_paint_phase == DocumentMarkerPaintPhase::kBackground) {
+ PaintRect(
+ context, NGPhysicalOffset(box_origin),
+ text_fragment.LocalRect(paint_start_offset, paint_end_offset),
+ styleable_marker.BackgroundColor());
+ break;
+ }
+ const SimpleFontData* font_data = style.GetFont().PrimaryFont();
+ DocumentMarkerPainter::PaintStyleableMarkerUnderline(
+ context, box_origin, styleable_marker, style,
+ FloatRect(MarkerRectForForeground(text_fragment, paint_start_offset,
+ paint_end_offset)),
+ LayoutUnit(font_data->GetFontMetrics().Height()));
+ } break;
+
+ default:
+ NOTREACHED();
+ break;
+ }
+ }
+}
+
} // namespace
NGTextFragmentPainter::NGTextFragmentPainter(
@@ -80,16 +256,10 @@ static void PaintSelection(GraphicsContext& context,
ToNGPhysicalTextFragment(paint_fragment.PhysicalFragment());
const Color color =
SelectionBackgroundColor(document, style, text_fragment, text_color);
- if (!color.Alpha())
- return;
-
- GraphicsContextStateSaver state_saver(context);
const NGPhysicalOffsetRect selection_rect =
- paint_fragment.ComputeLocalSelectionRect(selection_status);
- const NGPhysicalOffsetRect global_rect(
- selection_rect.offset + NGPhysicalOffset(box_rect.Location()),
- selection_rect.size);
- context.FillRect(global_rect.ToFloatRect(), color);
+ paint_fragment.ComputeLocalSelectionRectForText(selection_status);
+ PaintRect(context, NGPhysicalOffset(box_rect.Location()), selection_rect,
+ color);
}
// This is copied from InlineTextBoxPainter::PaintSelection() but lacks of
@@ -146,7 +316,33 @@ void NGTextFragmentPainter::Paint(const PaintInfo& paint_info,
LayoutRect box_rect(box_origin, fragment_.Size().ToLayoutSize());
base::Optional<GraphicsContextStateSaver> state_saver;
- NGLineOrientation orientation = text_fragment.LineOrientation();
+
+ // 1. Paint backgrounds behind text if needed. Examples of such backgrounds
+ // include selection and composition highlights.
+ // Since NGPaintFragment::ComputeLocalSelectionRectForText() returns
+ // NGPhysicalOffsetRect rather than NGLogicalRect, we should paint selection
+ // before GraphicsContext flip.
+ // TODO(yoichio): Make NGPhysicalTextFragment::LocalRect and
+ // NGPaintFragment::ComputeLocalSelectionRectForText logical so that we can
+ // paint selection in same fliped dimention as NGTextPainter.
+ const DocumentMarkerVector& markers_to_paint =
+ ComputeMarkersToPaint(fragment_);
+ if (paint_info.phase != PaintPhase::kSelection &&
+ paint_info.phase != PaintPhase::kTextClip && !is_printing) {
+ PaintDocumentMarkers(context, fragment_, markers_to_paint, box_origin,
+ style, DocumentMarkerPaintPhase::kBackground, nullptr);
+
+ if (have_selection) {
+ PaintSelection(context, fragment_, document, style,
+ selection_style.fill_color, box_rect, selection_status);
+ }
+ }
+
+ // Line break needs only selection painting.
+ if (text_fragment.IsLineBreak())
+ return;
+
+ const NGLineOrientation orientation = text_fragment.LineOrientation();
if (orientation != NGLineOrientation::kHorizontal) {
state_saver.emplace(context);
// Because we rotate the GraphicsContext to be logical, flip the
@@ -159,15 +355,6 @@ void NGTextFragmentPainter::Paint(const PaintInfo& paint_info,
: TextPainterBase::kCounterclockwise));
}
- // 1. Paint backgrounds behind text if needed. Examples of such backgrounds
- // include selection and composition highlights.
- if (have_selection && paint_info.phase != PaintPhase::kSelection &&
- paint_info.phase != PaintPhase::kTextClip && !is_printing) {
- // TODO(yoichio): Implement composition highlights.
- PaintSelection(context, fragment_, document, style,
- selection_style.fill_color, box_rect, selection_status);
- }
-
// 2. Now paint the foreground, including text and decorations.
int ascent = font_data ? font_data->GetFontMetrics().Ascent() : 0;
LayoutPoint text_origin(box_origin.X(), box_origin.Y() + ascent);
@@ -234,6 +421,11 @@ void NGTextFragmentPainter::Paint(const PaintInfo& paint_info,
text_painter.Paint(selection_status.start, selection_status.end, length,
selection_style);
}
+
+ if (paint_info.phase != PaintPhase::kForeground)
+ return;
+ PaintDocumentMarkers(context, fragment_, markers_to_paint, box_origin, style,
+ DocumentMarkerPaintPhase::kForeground, &text_painter);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.h b/chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.h
index 67434d2dcc9..dbb160cc20f 100644
--- a/chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.h
@@ -24,7 +24,7 @@ class NGTextFragmentPainter {
public:
explicit NGTextFragmentPainter(const NGPaintFragment&);
- void Paint(const PaintInfo&, const LayoutPoint&);
+ void Paint(const PaintInfo&, const LayoutPoint& paint_offset);
private:
const NGPaintFragment& fragment_;
diff --git a/chromium/third_party/blink/renderer/core/paint/nine_piece_image_painter.cc b/chromium/third_party/blink/renderer/core/paint/nine_piece_image_painter.cc
index 2b7998e3248..aa56f62ea47 100644
--- a/chromium/third_party/blink/renderer/core/paint/nine_piece_image_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/nine_piece_image_painter.cc
@@ -100,7 +100,8 @@ bool NinePieceImagePainter::Paint(GraphicsContext& graphics_context,
TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "PaintImage",
"data",
- InspectorPaintImageEvent::Data(node, *style_image, image->Rect(),
+ InspectorPaintImageEvent::Data(node, *style_image,
+ FloatRect(image->Rect()),
FloatRect(border_image_rect)));
ScopedInterpolationQuality interpolation_quality_scope(
diff --git a/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator.cc b/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
index fbfdbd4e8ee..88f1a5c66ed 100644
--- a/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
+++ b/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
@@ -11,14 +11,13 @@
#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/find_paint_offset_and_visual_rect_needing_update.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
#include "third_party/blink/renderer/core/paint/paint_invalidator.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
namespace blink {
-static bool g_disable_paint_invalidation_state_asserts = false;
-
using LayoutObjectTraversalFunctor = std::function<void(const LayoutObject&)>;
static void TraverseNonCompositingDescendantsInPaintOrder(
@@ -137,82 +136,48 @@ void ObjectPaintInvalidator::
});
}
-DISABLE_CFI_PERF
-void ObjectPaintInvalidator::InvalidatePaintOfPreviousVisualRect(
- const LayoutBoxModelObject& paint_invalidation_container,
- PaintInvalidationReason reason) {
- // It's caller's responsibility to ensure enclosingSelfPaintingLayer's
- // needsRepaint is set. Don't set the flag here because getting
- // enclosingSelfPaintLayer has cost and the caller can use various ways (e.g.
- // PaintInvalidatinState::enclosingSelfPaintingLayer()) to reduce the cost.
- DCHECK(!object_.PaintingLayer() || object_.PaintingLayer()->NeedsRepaint());
-
- // For SPv175, raster invalidation will be issued after painting.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- // These disablers are valid because we want to use the current
- // compositing/invalidation status.
- DisablePaintInvalidationStateAsserts invalidation_disabler;
- DisableCompositingQueryAsserts compositing_disabler;
-
- LayoutRect invalidation_rect = object_.FragmentsVisualRectBoundingBox();
- InvalidatePaintUsingContainer(paint_invalidation_container,
- invalidation_rect, reason);
- object_.InvalidateDisplayItemClients(reason);
- }
-
- // This method may be used to invalidate paint of an object changing paint
- // invalidation container. Clear previous visual rect on the original paint
- // invalidation container to avoid under-invalidation if the visual rect on
- // the new paint invalidation container happens to be the same as the old one.
- object_.GetMutableForPainting().ClearPreviousVisualRects();
-}
-
void ObjectPaintInvalidator::
InvalidatePaintIncludingNonCompositingDescendants() {
DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
- // Since we're only painting non-composited layers, we know that they all
- // share the same paintInvalidationContainer.
- const LayoutBoxModelObject& paint_invalidation_container =
- object_.ContainerForPaintInvalidation();
SlowSetPaintingLayerNeedsRepaint();
+ // This method may be used to invalidate paint of objects changing paint
+ // invalidation container. Clear previous visual rects on the original paint
+ // invalidation container to avoid under-invalidation if the visual rect on
+ // the new paint invalidation container happens to be the same as the old one.
TraverseNonCompositingDescendantsInPaintOrder(
- object_, [&paint_invalidation_container](const LayoutObject& object) {
+ object_, [](const LayoutObject& object) {
SetPaintingLayerNeedsRepaintDuringTraverse(object);
- ObjectPaintInvalidator(object).InvalidatePaintOfPreviousVisualRect(
- paint_invalidation_container, PaintInvalidationReason::kSubtree);
+ object.GetMutableForPainting().ClearPreviousVisualRects();
});
}
void ObjectPaintInvalidator::
- InvalidatePaintIncludingNonSelfPaintingLayerDescendantsInternal(
- const LayoutBoxModelObject& paint_invalidation_container) {
- InvalidatePaintOfPreviousVisualRect(paint_invalidation_container,
- PaintInvalidationReason::kSubtree);
- for (LayoutObject* child = object_.SlowFirstChild(); child;
- child = child->NextSibling()) {
- if (!child->HasLayer() ||
- !ToLayoutBoxModelObject(child)->Layer()->IsSelfPaintingLayer())
- ObjectPaintInvalidator(*child)
- .InvalidatePaintIncludingNonSelfPaintingLayerDescendantsInternal(
- paint_invalidation_container);
- }
-}
-
-void ObjectPaintInvalidator::
- InvalidatePaintIncludingNonSelfPaintingLayerDescendants(
- const LayoutBoxModelObject& paint_invalidation_container) {
+ InvalidatePaintIncludingNonSelfPaintingLayerDescendants() {
SlowSetPaintingLayerNeedsRepaint();
- InvalidatePaintIncludingNonSelfPaintingLayerDescendantsInternal(
- paint_invalidation_container);
+ // This method may be used to invalidate paint of objects changing paint
+ // invalidation container. Clear previous visual rect on the original paint
+ // invalidation container to avoid under-invalidation if the visual rect on
+ // the new paint invalidation container happens to be the same as the old one.
+ std::function<void(const LayoutObject&)> traverse =
+ [&traverse](const LayoutObject& object) {
+ object.GetMutableForPainting().ClearPreviousVisualRects();
+ for (LayoutObject* child = object.SlowFirstChild(); child;
+ child = child->NextSibling()) {
+ if (!child->HasLayer() ||
+ !ToLayoutBoxModelObject(child)->Layer()->IsSelfPaintingLayer())
+ traverse(*child);
+ }
+ };
+ traverse(object_);
}
void ObjectPaintInvalidator::InvalidateDisplayItemClient(
const DisplayItemClient& client,
PaintInvalidationReason reason) {
- // It's caller's responsibility to ensure enclosingSelfPaintingLayer's
- // needsRepaint is set. Don't set the flag here because getting
- // enclosingSelfPaintLayer has cost and the caller can use various ways (e.g.
- // PaintInvalidatinState::enclosingSelfPaintingLayer()) to reduce the cost.
+ // It's caller's responsibility to ensure PaintingLayer's NeedsRepaint is set.
+ // Don't set the flag here because getting PaintLayer has cost and the caller
+ // can use various ways (e.g. PaintInvalidatinContext::painting_layer) to
+ // reduce the cost.
DCHECK(!object_.PaintingLayer() || object_.PaintingLayer()->NeedsRepaint());
if (&client == &object_) {
@@ -222,203 +187,17 @@ void ObjectPaintInvalidator::InvalidateDisplayItemClient(
InspectorPaintInvalidationTrackingEvent::Data(object_));
}
- client.SetDisplayItemsUncached(reason);
+ client.Invalidate(reason);
if (LocalFrameView* frame_view = object_.GetFrameView())
frame_view->TrackObjectPaintInvalidation(client, reason);
}
-template <typename T>
-void AddJsonObjectForRect(TracedValue* value, const char* name, const T& rect) {
- value->BeginDictionary(name);
- value->SetDouble("x", rect.X());
- value->SetDouble("y", rect.Y());
- value->SetDouble("width", rect.Width());
- value->SetDouble("height", rect.Height());
- value->EndDictionary();
-}
-
-static std::unique_ptr<TracedValue> JsonObjectForPaintInvalidationInfo(
- const LayoutRect& rect,
- const String& invalidation_reason) {
- std::unique_ptr<TracedValue> value = TracedValue::Create();
- AddJsonObjectForRect(value.get(), "rect", rect);
- value->SetString("invalidation_reason", invalidation_reason);
- return value;
-}
-
-static void InvalidatePaintRectangleOnWindow(
- const LayoutBoxModelObject& paint_invalidation_container,
- const IntRect& dirty_rect) {
- LocalFrameView* frame_view = paint_invalidation_container.GetFrameView();
- DCHECK(paint_invalidation_container.IsLayoutView() &&
- paint_invalidation_container.Layer()->GetCompositingState() ==
- kNotComposited);
-
- if (!frame_view)
- return;
-
- if (paint_invalidation_container.GetDocument().Printing() &&
- !RuntimeEnabledFeatures::PrintBrowserEnabled())
- return;
-
- DCHECK(!frame_view->GetFrame().OwnerLayoutObject());
-
- IntRect paint_rect = dirty_rect;
- paint_rect.Intersect(frame_view->VisibleContentRect());
- if (paint_rect.IsEmpty())
- return;
-
- if (ChromeClient* client = frame_view->GetChromeClient())
- client->InvalidateRect(frame_view->ContentsToRootFrame(paint_rect));
-}
-
-void ObjectPaintInvalidator::SetBackingNeedsPaintInvalidationInRect(
- const LayoutBoxModelObject& paint_invalidation_container,
- const LayoutRect& rect,
- PaintInvalidationReason reason) {
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
- // https://bugs.webkit.org/show_bug.cgi?id=61159 describes an unreproducible
- // crash here, so assert but check that the layer is composited.
- DCHECK(paint_invalidation_container.GetCompositingState() != kNotComposited);
-
- PaintLayer& layer = *paint_invalidation_container.Layer();
- if (layer.GroupedMapping()) {
- if (GraphicsLayer* squashing_layer =
- layer.GroupedMapping()->SquashingLayer()) {
- // Note: the subpixel accumulation of layer() does not need to be added
- // here. It is already taken into account.
- squashing_layer->SetNeedsDisplayInRect(EnclosingIntRect(rect), reason,
- object_);
- }
- } else if (paint_invalidation_container.UsesCompositedScrolling()) {
- // If object_ is not paint_invalidation_container, then it scrolls.
- if (&object_ != paint_invalidation_container ||
- reason ==
- PaintInvalidationReason::kBackgroundOnScrollingContentsLayer ||
- reason == PaintInvalidationReason::kCaret) {
- layer.GetCompositedLayerMapping()->SetScrollingContentsNeedDisplayInRect(
- rect, reason, object_);
- } else {
- layer.GetCompositedLayerMapping()
- ->SetNonScrollingContentsNeedDisplayInRect(rect, reason, object_);
- }
- } else {
- // Otherwise invalidate everything.
- layer.GetCompositedLayerMapping()->SetContentsNeedDisplayInRect(
- rect, reason, object_);
- }
-}
-
-void ObjectPaintInvalidator::InvalidatePaintUsingContainer(
- const LayoutBoxModelObject& paint_invalidation_container,
- const LayoutRect& dirty_rect,
- PaintInvalidationReason invalidation_reason) {
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
-
- if (paint_invalidation_container.GetFrameView()->ShouldThrottleRendering())
- return;
-
- DCHECK(g_disable_paint_invalidation_state_asserts ||
- object_.GetDocument().Lifecycle().GetState() ==
- DocumentLifecycle::kInPrePaint);
-
- if (dirty_rect.IsEmpty())
- return;
-
- CHECK(object_.IsRooted());
-
- TRACE_EVENT2(
- TRACE_DISABLED_BY_DEFAULT("blink.invalidation"),
- "LayoutObject::invalidatePaintUsingContainer()", "object",
- object_.DebugName().Ascii(), "info",
- JsonObjectForPaintInvalidationInfo(
- dirty_rect, PaintInvalidationReasonToString(invalidation_reason)));
-
- // This conditional handles situations where non-rooted (and hence
- // non-composited) frames are painted, such as SVG images.
- if (!paint_invalidation_container.IsPaintInvalidationContainer()) {
- InvalidatePaintRectangleOnWindow(paint_invalidation_container,
- EnclosingIntRect(dirty_rect));
- } else {
- SetBackingNeedsPaintInvalidationInRect(paint_invalidation_container,
- dirty_rect, invalidation_reason);
- }
-}
-
void ObjectPaintInvalidator::SlowSetPaintingLayerNeedsRepaint() {
if (PaintLayer* painting_layer = object_.PaintingLayer())
painting_layer->SetNeedsRepaint();
}
-void ObjectPaintInvalidatorWithContext::FullyInvalidatePaint(
- PaintInvalidationReason reason,
- const LayoutRect& old_visual_rect,
- const LayoutRect& new_visual_rect) {
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
- // The following logic avoids invalidating twice if one set of bounds contains
- // the other.
- if (!new_visual_rect.Contains(old_visual_rect)) {
- LayoutRect invalidation_rect = old_visual_rect;
- InvalidatePaintRectangleWithContext(invalidation_rect, reason);
-
- if (invalidation_rect.Contains(new_visual_rect))
- return;
- }
-
- InvalidatePaintRectangleWithContext(new_visual_rect, reason);
-}
-
-bool ObjectPaintInvalidatorWithContext::ParentFullyInvalidatedOnSameBacking() {
- if (!object_.Parent() || !context_.ParentContext())
- return false;
-
- if (!IsImmediateFullPaintInvalidationReason(
- object_.Parent()->FullPaintInvalidationReason()))
- return false;
-
- // Parent and child should have the same paint invalidation container.
- if (context_.ParentContext()->paint_invalidation_container !=
- context_.paint_invalidation_container)
- return false;
-
- // Both parent and child are contents of the paint invalidation container,
- // so they are on the same backing.
- if (object_.Parent() != context_.paint_invalidation_container)
- return true;
-
- // If the paint invalidation container (i.e. parent) uses composited
- // scrolling, parent and child might be on different backing (scrolling
- // container vs scrolling contents).
- return !context_.paint_invalidation_container->UsesCompositedScrolling();
-}
-
-void ObjectPaintInvalidatorWithContext::InvalidatePaintRectangleWithContext(
- const LayoutRect& rect,
- PaintInvalidationReason reason) {
- if (rect.IsEmpty())
- return;
-
- base::Optional<ScopedSetNeedsDisplayInRectForTrackingOnly> scope;
- // If the parent has fully invalidated and its visual rect covers this object
- // on the same backing, skip the invalidation.
- if (ParentFullyInvalidatedOnSameBacking() &&
- (context_.ParentContext()->old_visual_rect.Contains(rect) ||
- object_.Parent()->FirstFragment().VisualRect().Contains(rect))) {
- if (!object_.GetFrameView()->IsTrackingPaintInvalidations())
- return;
- // If we are tracking paint invalidations (e.g. when running a text-based-
- // repaint layout test), still track the rectangle but the rectangle
- // won't affect any other functionality including raster-under-invalidation
- // checking. This is to reduce differences between layout test results of
- // SPv1 and SPv2, to reduce rebaselines and chance of errors.
- scope.emplace();
- }
-
- InvalidatePaintUsingContainer(*context_.paint_invalidation_container, rect,
- reason);
-}
-
DISABLE_CFI_PERF
PaintInvalidationReason
ObjectPaintInvalidatorWithContext::ComputePaintInvalidationReason() {
@@ -485,8 +264,10 @@ ObjectPaintInvalidatorWithContext::ComputePaintInvalidationReason() {
context_.old_visual_rect.Location())
return PaintInvalidationReason::kGeometry;
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- context_.fragment_data->LocationInBacking() != context_.old_location)
+ // Most paintings are pixel-snapped so subpixel change of paint offset doesn't
+ // directly cause full raster invalidation.
+ if (RoundedIntPoint(context_.fragment_data->PaintOffset()) !=
+ RoundedIntPoint(context_.old_paint_offset))
return PaintInvalidationReason::kGeometry;
// Incremental invalidation is only applicable to LayoutBoxes. Return
@@ -506,6 +287,15 @@ ObjectPaintInvalidatorWithContext::ComputePaintInvalidationReason() {
DISABLE_CFI_PERF
void ObjectPaintInvalidatorWithContext::InvalidateSelection(
PaintInvalidationReason reason) {
+ // In LayoutNG, if NGPaintFragment paints the selection, we invalidate for
+ // selection change in PaintInvalidator.
+ if (RuntimeEnabledFeatures::LayoutNGEnabled() && object_.IsInline() &&
+ // LayoutReplaced still paints selection tint by itself.
+ !object_.IsLayoutReplaced() &&
+ NGPaintFragment::InlineFragmentsFor(&object_)
+ .IsInLayoutNGInlineFormattingContext())
+ return;
+
// Update selection rect when we are doing full invalidation with geometry
// change (in case that the object is moved, composite status changed, etc.)
// or shouldInvalidationSelection is set (in case that the selection itself
@@ -522,7 +312,7 @@ void ObjectPaintInvalidatorWithContext::InvalidateSelection(
#endif
if (context_.NeedsVisualRectUpdate(object_)) {
new_selection_rect = object_.LocalSelectionRect();
- context_.MapLocalRectToVisualRectInBacking(object_, new_selection_rect);
+ context_.MapLocalRectToVisualRect(object_, new_selection_rect);
} else {
new_selection_rect = old_selection_rect;
}
@@ -532,17 +322,9 @@ void ObjectPaintInvalidatorWithContext::InvalidateSelection(
if (full_invalidation)
return;
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- if (RuntimeEnabledFeatures::PartialRasterInvalidationEnabled()) {
- // PaintController will handle raster invalidation of the partial rect.
- object_.GetMutableForPainting().SetPartialInvalidationRect(
- UnionRect(object_.PartialInvalidationRect(),
- UnionRect(new_selection_rect, old_selection_rect)));
- }
- } else {
- FullyInvalidatePaint(PaintInvalidationReason::kSelection,
- old_selection_rect, new_selection_rect);
- }
+ object_.GetMutableForPainting().SetPartialInvalidationVisualRect(
+ UnionRect(object_.PartialInvalidationVisualRect(),
+ UnionRect(new_selection_rect, old_selection_rect)));
context_.painting_layer->SetNeedsRepaint();
object_.InvalidateDisplayItemClients(PaintInvalidationReason::kSelection);
}
@@ -553,26 +335,16 @@ void ObjectPaintInvalidatorWithContext::InvalidatePartialRect(
if (IsImmediateFullPaintInvalidationReason(reason))
return;
- auto rect = object_.PartialInvalidationRect();
+ auto rect = object_.PartialInvalidationLocalRect();
if (rect.IsEmpty())
return;
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() ||
- RuntimeEnabledFeatures::PartialRasterInvalidationEnabled()) {
- context_.MapLocalRectToVisualRectInBacking(object_, rect);
- if (rect.IsEmpty())
- return;
- }
+ context_.MapLocalRectToVisualRect(object_, rect);
+ if (rect.IsEmpty())
+ return;
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- if (RuntimeEnabledFeatures::PartialRasterInvalidationEnabled()) {
- // PaintController will handle raster invalidation of the partial rect.
- object_.GetMutableForPainting().SetPartialInvalidationRect(rect);
- }
- } else {
- InvalidatePaintRectangleWithContext(rect,
- PaintInvalidationReason::kRectangle);
- }
+ object_.GetMutableForPainting().SetPartialInvalidationVisualRect(
+ UnionRect(object_.PartialInvalidationVisualRect(), rect));
context_.painting_layer->SetNeedsRepaint();
object_.InvalidateDisplayItemClients(PaintInvalidationReason::kRectangle);
@@ -596,20 +368,6 @@ ObjectPaintInvalidatorWithContext::InvalidatePaintWithComputedReason(
switch (reason) {
case PaintInvalidationReason::kNone:
- // There are corner cases that the display items need to be invalidated
- // for paint offset mutation, but incurs no pixel difference (i.e. bounds
- // stay the same) so no rect-based invalidation is issued. See
- // crbug.com/508383 and crbug.com/515977.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- (context_.subtree_flags &
- PaintInvalidatorContext::kSubtreeInvalidationChecking) &&
- !object_.IsSVGChild()) {
- // For SPv1, we conservatively assume the object changed paint offset
- // except for non-root SVG whose paint offset is always zero.
- reason = PaintInvalidationReason::kGeometry;
- break;
- }
-
if (object_.IsSVG() &&
(context_.subtree_flags &
PaintInvalidatorContext::kSubtreeSVGResourceChange)) {
@@ -621,14 +379,6 @@ ObjectPaintInvalidatorWithContext::InvalidatePaintWithComputedReason(
return PaintInvalidationReason::kDelayedFull;
default:
DCHECK(IsImmediateFullPaintInvalidationReason(reason));
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- // This allows descendants to know the computed reason if it's different
- // from the original reason before paint invalidation.
- object_.GetMutableForPainting()
- .SetShouldDoFullPaintInvalidationWithoutGeometryChange(reason);
- FullyInvalidatePaint(reason, context_.old_visual_rect,
- context_.fragment_data->VisualRect());
- }
}
context_.painting_layer->SetNeedsRepaint();
@@ -636,7 +386,4 @@ ObjectPaintInvalidatorWithContext::InvalidatePaintWithComputedReason(
return reason;
}
-DisablePaintInvalidationStateAsserts::DisablePaintInvalidationStateAsserts()
- : disabler_(&g_disable_paint_invalidation_state_asserts, true) {}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator.h b/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator.h
index a8541b21d8c..af5aad1808c 100644
--- a/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator.h
+++ b/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator.h
@@ -14,9 +14,7 @@
namespace blink {
class DisplayItemClient;
-class LayoutBoxModelObject;
class LayoutObject;
-class LayoutRect;
struct PaintInvalidatorContext;
class CORE_EXPORT ObjectPaintInvalidator {
@@ -25,13 +23,11 @@ class CORE_EXPORT ObjectPaintInvalidator {
public:
ObjectPaintInvalidator(const LayoutObject& object) : object_(object) {}
- // This calls paintingLayer() which walks up the tree.
+ // This calls LayoutObject::PaintingLayer() which walks up the tree.
// If possible, use the faster
- // PaintInvalidatorContext.paintingLayer.setNeedsRepaint().
+ // PaintInvalidatorContext.painting_layer.SetNeedsRepaint() instead.
void SlowSetPaintingLayerNeedsRepaint();
- // TODO(wangxianzhu): Change the call sites to use the faster version if
- // possible.
void SlowSetPaintingLayerNeedsRepaintAndInvalidateDisplayItemClient(
const DisplayItemClient& client,
PaintInvalidationReason reason) {
@@ -42,36 +38,13 @@ class CORE_EXPORT ObjectPaintInvalidator {
void InvalidateDisplayItemClientsIncludingNonCompositingDescendants(
PaintInvalidationReason);
- void InvalidatePaintOfPreviousVisualRect(
- const LayoutBoxModelObject& paint_invalidation_container,
- PaintInvalidationReason);
-
- // The caller should ensure the painting layer has been setNeedsRepaint before
+ // The caller should ensure the painting layer has been SetNeedsRepaint before
// calling this function.
void InvalidateDisplayItemClient(const DisplayItemClient&,
PaintInvalidationReason);
- // Actually do the paint invalidate of rect r for this object which has been
- // computed in the coordinate space of the GraphicsLayer backing of
- // |paintInvalidationContainer|. Note that this coordinate space is not the
- // same as the local coordinate space of |paintInvalidationContainer| in the
- // presence of layer squashing.
- void InvalidatePaintUsingContainer(
- const LayoutBoxModelObject& paint_invalidation_container,
- const LayoutRect&,
- PaintInvalidationReason);
-
void InvalidatePaintIncludingNonCompositingDescendants();
- void InvalidatePaintIncludingNonSelfPaintingLayerDescendants(
- const LayoutBoxModelObject& paint_invalidation_container);
-
- private:
- void InvalidatePaintIncludingNonSelfPaintingLayerDescendantsInternal(
- const LayoutBoxModelObject& paint_invalidation_container);
- void SetBackingNeedsPaintInvalidationInRect(
- const LayoutBoxModelObject& paint_invalidation_container,
- const LayoutRect&,
- PaintInvalidationReason);
+ void InvalidatePaintIncludingNonSelfPaintingLayerDescendants();
protected:
const LayoutObject& object_;
@@ -91,39 +64,13 @@ class ObjectPaintInvalidatorWithContext : public ObjectPaintInvalidator {
PaintInvalidationReason InvalidatePaintWithComputedReason(
PaintInvalidationReason);
- // This function generates a full invalidation, which means invalidating both
- // |oldVisualRect| and |newVisualRect|. This is the default choice when
- // generating an invalidation, as it is always correct, albeit it may force
- // some extra painting.
- void FullyInvalidatePaint(PaintInvalidationReason,
- const LayoutRect& old_visual_rect,
- const LayoutRect& new_visual_rect);
-
- void InvalidatePaintRectangleWithContext(const LayoutRect&,
- PaintInvalidationReason);
-
private:
void InvalidateSelection(PaintInvalidationReason);
void InvalidatePartialRect(PaintInvalidationReason);
- bool ParentFullyInvalidatedOnSameBacking();
const PaintInvalidatorContext& context_;
};
-// Use this for cases that compositing will change and we have to do immediate
-// paint invalidation. TODO(wangxianzhu): Remove this for SPv2 and SPv175 which
-// will always invalidate raster after paint.
-class DisablePaintInvalidationStateAsserts {
- STACK_ALLOCATED();
- DISALLOW_COPY_AND_ASSIGN(DisablePaintInvalidationStateAsserts);
-
- public:
- DisablePaintInvalidationStateAsserts();
-
- private:
- base::AutoReset<bool> disabler_;
-};
-
} // namespace blink
#endif
diff --git a/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc b/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc
index aec9c0e1930..30701f663e6 100644
--- a/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/object_paint_invalidator_test.cc
@@ -276,29 +276,40 @@ TEST_F(ObjectPaintInvalidatorTest, InvalidatePaintRectangle) {
auto* target = GetLayoutObjectByElementId("target");
target->InvalidatePaintRectangle(LayoutRect(10, 10, 50, 50));
- EXPECT_EQ(LayoutRect(10, 10, 50, 50), target->PartialInvalidationRect());
+ EXPECT_EQ(LayoutRect(10, 10, 50, 50), target->PartialInvalidationLocalRect());
target->InvalidatePaintRectangle(LayoutRect(30, 30, 60, 60));
- EXPECT_EQ(LayoutRect(10, 10, 80, 80), target->PartialInvalidationRect());
+ EXPECT_EQ(LayoutRect(10, 10, 80, 80), target->PartialInvalidationLocalRect());
EXPECT_TRUE(target->MayNeedPaintInvalidation());
- GetDocument().View()->UpdateLifecycleToPrePaintClean();
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() ||
- !RuntimeEnabledFeatures::PartialRasterInvalidationEnabled())
- EXPECT_EQ(LayoutRect(), target->PartialInvalidationRect());
+ GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
+ EXPECT_EQ(LayoutRect(), target->PartialInvalidationLocalRect());
+ EXPECT_EQ(LayoutRect(18, 18, 80, 80),
+ target->PartialInvalidationVisualRect());
+
+ target->InvalidatePaintRectangle(LayoutRect(30, 30, 50, 80));
+ EXPECT_EQ(LayoutRect(30, 30, 50, 80), target->PartialInvalidationLocalRect());
+ GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
+ // PartialInvalidationVisualRect should accumulate until painting.
+ EXPECT_EQ(LayoutRect(18, 18, 80, 100),
+ target->PartialInvalidationVisualRect());
+
GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_EQ(LayoutRect(), target->PartialInvalidationRect());
+ EXPECT_EQ(LayoutRect(), target->PartialInvalidationLocalRect());
+ EXPECT_EQ(LayoutRect(), target->PartialInvalidationVisualRect());
auto object_invalidations =
GetDocument().View()->TrackedObjectPaintInvalidationsAsJSON();
- ASSERT_EQ(1u, object_invalidations->size());
- String s;
- const auto* entry = JSONObject::Cast(object_invalidations->at(0));
- entry->Get("reason")->AsString(&s);
- EXPECT_EQ(String(PaintInvalidationReasonToString(
- PaintInvalidationReason::kRectangle)),
- s);
- entry->Get("object")->AsString(&s);
- EXPECT_EQ(target->DebugName(), s);
+ ASSERT_EQ(2u, object_invalidations->size());
+ for (int i = 0; i < 2; i++) {
+ String s;
+ const auto* entry = JSONObject::Cast(object_invalidations->at(i));
+ entry->Get("reason")->AsString(&s);
+ EXPECT_EQ(String(PaintInvalidationReasonToString(
+ PaintInvalidationReason::kRectangle)),
+ s);
+ entry->Get("object")->AsString(&s);
+ EXPECT_EQ(target->DebugName(), s);
+ }
const auto& raster_invalidations = GetLayoutView()
.Layer()
@@ -306,10 +317,7 @@ TEST_F(ObjectPaintInvalidatorTest, InvalidatePaintRectangle) {
->GetRasterInvalidationTracking()
->Invalidations();
ASSERT_EQ(1u, raster_invalidations.size());
- if (RuntimeEnabledFeatures::PartialRasterInvalidationEnabled())
- EXPECT_EQ(IntRect(18, 18, 80, 80), raster_invalidations[0].rect);
- else
- EXPECT_EQ(IntRect(8, 8, 200, 200), raster_invalidations[0].rect);
+ EXPECT_EQ(IntRect(18, 18, 80, 100), raster_invalidations[0].rect);
EXPECT_EQ(PaintInvalidationReason::kRectangle,
raster_invalidations[0].reason);
diff --git a/chromium/third_party/blink/renderer/core/paint/object_paint_properties.h b/chromium/third_party/blink/renderer/core/paint/object_paint_properties.h
index 016233a20b4..736b174648d 100644
--- a/chromium/third_party/blink/renderer/core/paint/object_paint_properties.h
+++ b/chromium/third_party/blink/renderer/core/paint/object_paint_properties.h
@@ -81,6 +81,9 @@ class CORE_EXPORT ObjectPaintProperties {
// | backdrop-dependent children are present.
// +-[ filter ]
// | Isolated group for CSS filter.
+ // +-[ vertical/horizontal scrollbar effect ]
+ // | Overlay Scrollbars on Aura and Android need effect node for fade
+ // | animation.
// +-[ mask ]
// | Isolated group for painting the CSS mask. This node will have
// | SkBlendMode::kDstIn and shall paint last, i.e. after masked contents.
@@ -90,20 +93,25 @@ class CORE_EXPORT ObjectPaintProperties {
// contents.
const EffectPaintPropertyNode* Effect() const { return effect_.get(); }
const EffectPaintPropertyNode* Filter() const { return filter_.get(); }
+ const EffectPaintPropertyNode* VerticalScrollbarEffect() const {
+ return vertical_scrollbar_effect_.get();
+ }
+ const EffectPaintPropertyNode* HorizontalScrollbarEffect() const {
+ return horizontal_scrollbar_effect_.get();
+ }
const EffectPaintPropertyNode* Mask() const { return mask_.get(); }
const EffectPaintPropertyNode* ClipPath() const { return clip_path_.get(); }
// The hierarchy of the clip subtree created by a LayoutObject is as follows:
// [ fragment clip ]
// | Clips to a fragment's bounds.
- // | This is only present for content under a fragmentation
- // | container.
- // | NOTE: for composited SPv1/SPv175 clip path clips, we move clip path clip
- // | below mask.
+ // | This is only present for content under a fragmentation container.
// +-[ clip path clip ]
// | Clip created by path-based CSS clip-path. Only exists if the
// / clip-path is "simple" that can be applied geometrically. This and
// / the clip path effect node are mutually exclusive.
+ // | NOTE: for composited SPv1 clip path clips, we move clip path clip
+ // | below mask.
// +-[ mask clip ]
// | Clip created by CSS mask or CSS clip-path. It serves two purposes:
// | 1. Cull painting of the masked subtree. Because anything outside of
@@ -158,6 +166,12 @@ class CORE_EXPORT ObjectPaintProperties {
bool ClearTransform() { return Clear(transform_); }
bool ClearEffect() { return Clear(effect_); }
bool ClearFilter() { return Clear(filter_); }
+ bool ClearVerticalScrollbarEffect() {
+ return Clear(vertical_scrollbar_effect_);
+ }
+ bool ClearHorizontalScrollbarEffect() {
+ return Clear(horizontal_scrollbar_effect_);
+ }
bool ClearMask() { return Clear(mask_); }
bool ClearClipPath() { return Clear(clip_path_); }
bool ClearFragmentClip() { return Clear(fragment_clip_); }
@@ -188,98 +202,98 @@ class CORE_EXPORT ObjectPaintProperties {
};
UpdateResult UpdatePaintOffsetTranslation(
- scoped_refptr<const TransformPaintPropertyNode> parent,
+ const TransformPaintPropertyNode& parent,
TransformPaintPropertyNode::State&& state) {
- return Update(paint_offset_translation_, std::move(parent),
- std::move(state));
+ return Update(paint_offset_translation_, parent, std::move(state));
}
- UpdateResult UpdateTransform(
- scoped_refptr<const TransformPaintPropertyNode> parent,
- TransformPaintPropertyNode::State&& state) {
- return Update(transform_, std::move(parent), std::move(state));
+ UpdateResult UpdateTransform(const TransformPaintPropertyNode& parent,
+ TransformPaintPropertyNode::State&& state) {
+ return Update(transform_, parent, std::move(state));
}
- UpdateResult UpdatePerspective(
- scoped_refptr<const TransformPaintPropertyNode> parent,
- TransformPaintPropertyNode::State&& state) {
- return Update(perspective_, std::move(parent), std::move(state));
+ UpdateResult UpdatePerspective(const TransformPaintPropertyNode& parent,
+ TransformPaintPropertyNode::State&& state) {
+ return Update(perspective_, parent, std::move(state));
}
UpdateResult UpdateSvgLocalToBorderBoxTransform(
- scoped_refptr<const TransformPaintPropertyNode> parent,
+ const TransformPaintPropertyNode& parent,
TransformPaintPropertyNode::State&& state) {
DCHECK(!ScrollTranslation()) << "SVG elements cannot scroll so there "
"should never be both a scroll translation "
"and an SVG local to border box transform.";
- return Update(svg_local_to_border_box_transform_, std::move(parent),
- std::move(state));
+ return Update(svg_local_to_border_box_transform_, parent, std::move(state));
}
- UpdateResult UpdateScroll(scoped_refptr<const ScrollPaintPropertyNode> parent,
+ UpdateResult UpdateScroll(const ScrollPaintPropertyNode& parent,
ScrollPaintPropertyNode::State&& state) {
- return Update(scroll_, std::move(parent), std::move(state));
+ return Update(scroll_, parent, std::move(state));
}
UpdateResult UpdateScrollTranslation(
- scoped_refptr<const TransformPaintPropertyNode> parent,
+ const TransformPaintPropertyNode& parent,
TransformPaintPropertyNode::State&& state) {
DCHECK(!SvgLocalToBorderBoxTransform())
<< "SVG elements cannot scroll so there should never be both a scroll "
"translation and an SVG local to border box transform.";
- return Update(scroll_translation_, std::move(parent), std::move(state));
+ return Update(scroll_translation_, parent, std::move(state));
}
- UpdateResult UpdateEffect(scoped_refptr<const EffectPaintPropertyNode> parent,
+ UpdateResult UpdateEffect(const EffectPaintPropertyNode& parent,
EffectPaintPropertyNode::State&& state) {
- return Update(effect_, std::move(parent), std::move(state));
+ return Update(effect_, parent, std::move(state));
}
- UpdateResult UpdateFilter(scoped_refptr<const EffectPaintPropertyNode> parent,
+ UpdateResult UpdateFilter(const EffectPaintPropertyNode& parent,
EffectPaintPropertyNode::State&& state) {
- return Update(filter_, std::move(parent), std::move(state));
+ return Update(filter_, parent, std::move(state));
}
- UpdateResult UpdateMask(scoped_refptr<const EffectPaintPropertyNode> parent,
- EffectPaintPropertyNode::State&& state) {
- return Update(mask_, std::move(parent), std::move(state));
+ UpdateResult UpdateVerticalScrollbarEffect(
+ const EffectPaintPropertyNode& parent,
+ EffectPaintPropertyNode::State&& state) {
+ return Update(vertical_scrollbar_effect_, parent, std::move(state));
}
- UpdateResult UpdateClipPath(
- scoped_refptr<const EffectPaintPropertyNode> parent,
+ UpdateResult UpdateHorizontalScrollbarEffect(
+ const EffectPaintPropertyNode& parent,
EffectPaintPropertyNode::State&& state) {
- return Update(clip_path_, std::move(parent), std::move(state));
+ return Update(horizontal_scrollbar_effect_, parent, std::move(state));
}
- UpdateResult UpdateFragmentClip(
- scoped_refptr<const ClipPaintPropertyNode> parent,
- ClipPaintPropertyNode::State&& state) {
- return Update(fragment_clip_, std::move(parent), std::move(state));
+ UpdateResult UpdateMask(const EffectPaintPropertyNode& parent,
+ EffectPaintPropertyNode::State&& state) {
+ return Update(mask_, parent, std::move(state));
}
- UpdateResult UpdateClipPathClip(
- scoped_refptr<const ClipPaintPropertyNode> parent,
- ClipPaintPropertyNode::State&& state) {
- return Update(clip_path_clip_, std::move(parent), std::move(state));
+ UpdateResult UpdateClipPath(const EffectPaintPropertyNode& parent,
+ EffectPaintPropertyNode::State&& state) {
+ return Update(clip_path_, parent, std::move(state));
}
- UpdateResult UpdateMaskClip(scoped_refptr<const ClipPaintPropertyNode> parent,
+ UpdateResult UpdateFragmentClip(const ClipPaintPropertyNode& parent,
+ ClipPaintPropertyNode::State&& state) {
+ return Update(fragment_clip_, parent, std::move(state));
+ }
+ UpdateResult UpdateClipPathClip(const ClipPaintPropertyNode& parent,
+ ClipPaintPropertyNode::State&& state) {
+ return Update(clip_path_clip_, parent, std::move(state));
+ }
+ UpdateResult UpdateMaskClip(const ClipPaintPropertyNode& parent,
ClipPaintPropertyNode::State&& state) {
- return Update(mask_clip_, std::move(parent), std::move(state));
+ return Update(mask_clip_, parent, std::move(state));
}
- UpdateResult UpdateCssClip(scoped_refptr<const ClipPaintPropertyNode> parent,
+ UpdateResult UpdateCssClip(const ClipPaintPropertyNode& parent,
ClipPaintPropertyNode::State&& state) {
- return Update(css_clip_, std::move(parent), std::move(state));
+ return Update(css_clip_, parent, std::move(state));
}
UpdateResult UpdateCssClipFixedPosition(
- scoped_refptr<const ClipPaintPropertyNode> parent,
+ const ClipPaintPropertyNode& parent,
ClipPaintPropertyNode::State&& state) {
- return Update(css_clip_fixed_position_, std::move(parent),
- std::move(state));
+ return Update(css_clip_fixed_position_, parent, std::move(state));
}
UpdateResult UpdateOverflowControlsClip(
- scoped_refptr<const ClipPaintPropertyNode> parent,
+ const ClipPaintPropertyNode& parent,
ClipPaintPropertyNode::State&& state) {
- return Update(overflow_controls_clip_, std::move(parent), std::move(state));
+ return Update(overflow_controls_clip_, parent, std::move(state));
}
UpdateResult UpdateInnerBorderRadiusClip(
- scoped_refptr<const ClipPaintPropertyNode> parent,
+ const ClipPaintPropertyNode& parent,
ClipPaintPropertyNode::State&& state) {
- return Update(inner_border_radius_clip_, std::move(parent),
- std::move(state));
+ return Update(inner_border_radius_clip_, parent, std::move(state));
}
- UpdateResult UpdateOverflowClip(
- scoped_refptr<const ClipPaintPropertyNode> parent,
- ClipPaintPropertyNode::State&& state) {
- return Update(overflow_clip_, std::move(parent), std::move(state));
+ UpdateResult UpdateOverflowClip(const ClipPaintPropertyNode& parent,
+ ClipPaintPropertyNode::State&& state) {
+ return Update(overflow_clip_, parent, std::move(state));
}
#if DCHECK_IS_ON()
@@ -294,6 +308,12 @@ class CORE_EXPORT ObjectPaintProperties {
cloned->effect_ = effect_->Clone();
if (filter_)
cloned->filter_ = filter_->Clone();
+ if (vertical_scrollbar_effect_)
+ cloned->vertical_scrollbar_effect_ = vertical_scrollbar_effect_->Clone();
+ if (horizontal_scrollbar_effect_) {
+ cloned->horizontal_scrollbar_effect_ =
+ horizontal_scrollbar_effect_->Clone();
+ }
if (mask_)
cloned->mask_ = mask_->Clone();
if (clip_path_)
@@ -348,14 +368,14 @@ class CORE_EXPORT ObjectPaintProperties {
// implementation note") for details about why this is needed for efficiency.
template <typename PaintPropertyNode>
UpdateResult Update(scoped_refptr<PaintPropertyNode>& field,
- scoped_refptr<const PaintPropertyNode> parent,
+ const PaintPropertyNode& parent,
typename PaintPropertyNode::State&& state) {
if (field) {
- return field->Update(std::move(parent), std::move(state))
+ return field->Update(parent, std::move(state))
? UpdateResult::kValueChanged
: UpdateResult::kUnchanged;
}
- field = PaintPropertyNode::Create(std::move(parent), std::move(state));
+ field = PaintPropertyNode::Create(parent, std::move(state));
return UpdateResult::kNewNodeCreated;
}
@@ -365,6 +385,8 @@ class CORE_EXPORT ObjectPaintProperties {
scoped_refptr<TransformPaintPropertyNode> transform_;
scoped_refptr<EffectPaintPropertyNode> effect_;
scoped_refptr<EffectPaintPropertyNode> filter_;
+ scoped_refptr<EffectPaintPropertyNode> vertical_scrollbar_effect_;
+ scoped_refptr<EffectPaintPropertyNode> horizontal_scrollbar_effect_;
scoped_refptr<EffectPaintPropertyNode> mask_;
scoped_refptr<EffectPaintPropertyNode> clip_path_;
scoped_refptr<ClipPaintPropertyNode> fragment_clip_;
diff --git a/chromium/third_party/blink/renderer/core/paint/object_painter.cc b/chromium/third_party/blink/renderer/core/paint/object_painter.cc
index 04e9ea9e295..f5ac9b23465 100644
--- a/chromium/third_party/blink/renderer/core/paint/object_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/object_painter.cc
@@ -63,9 +63,7 @@ void ObjectPainter::PaintOutline(const PaintInfo& paint_info,
PaintOutlineRects(paint_info, outline_rects, style_to_use);
}
-void ObjectPainter::PaintInlineChildrenOutlines(
- const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void ObjectPainter::PaintInlineChildrenOutlines(const PaintInfo& paint_info) {
DCHECK(ShouldPaintDescendantOutlines(paint_info.phase));
PaintInfo paint_info_for_descendants = paint_info.ForDescendants();
@@ -73,7 +71,7 @@ void ObjectPainter::PaintInlineChildrenOutlines(
child = child->NextSibling()) {
if (child->IsLayoutInline() &&
!ToLayoutInline(child)->HasSelfPaintingLayer())
- child->Paint(paint_info_for_descendants, paint_offset);
+ child->Paint(paint_info_for_descendants);
}
}
@@ -114,14 +112,13 @@ void ObjectPainter::AddPDFURLRectIfNeeded(const PaintInfo& paint_info,
paint_info.context.SetURLForRect(url, rect);
}
-void ObjectPainter::PaintAllPhasesAtomically(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void ObjectPainter::PaintAllPhasesAtomically(const PaintInfo& paint_info) {
// Pass PaintPhaseSelection and PaintPhaseTextClip to the descendants so that
// they will paint for selection and text clip respectively. We don't need
// complete painting for these phases.
if (paint_info.phase == PaintPhase::kSelection ||
paint_info.phase == PaintPhase::kTextClip) {
- layout_object_.Paint(paint_info, paint_offset);
+ layout_object_.Paint(paint_info);
return;
}
@@ -130,13 +127,13 @@ void ObjectPainter::PaintAllPhasesAtomically(const PaintInfo& paint_info,
PaintInfo info(paint_info);
info.phase = PaintPhase::kBlockBackground;
- layout_object_.Paint(info, paint_offset);
+ layout_object_.Paint(info);
info.phase = PaintPhase::kFloat;
- layout_object_.Paint(info, paint_offset);
+ layout_object_.Paint(info);
info.phase = PaintPhase::kForeground;
- layout_object_.Paint(info, paint_offset);
+ layout_object_.Paint(info);
info.phase = PaintPhase::kOutline;
- layout_object_.Paint(info, paint_offset);
+ layout_object_.Paint(info);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/object_painter.h b/chromium/third_party/blink/renderer/core/paint/object_painter.h
index fa961f99fda..be00a3352c5 100644
--- a/chromium/third_party/blink/renderer/core/paint/object_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/object_painter.h
@@ -12,9 +12,9 @@
namespace blink {
-class LayoutPoint;
struct PaintInfo;
class LayoutObject;
+class LayoutPoint;
class ObjectPainter : public ObjectPainterBase {
STACK_ALLOCATED();
@@ -24,8 +24,7 @@ class ObjectPainter : public ObjectPainterBase {
: layout_object_(layout_object) {}
void PaintOutline(const PaintInfo&, const LayoutPoint& paint_offset);
- void PaintInlineChildrenOutlines(const PaintInfo&,
- const LayoutPoint& paint_offset);
+ void PaintInlineChildrenOutlines(const PaintInfo&);
void AddPDFURLRectIfNeeded(const PaintInfo&, const LayoutPoint& paint_offset);
// Paints the object atomically as if it created a new stacking context, for:
@@ -43,8 +42,7 @@ class ObjectPainter : public ObjectPainterBase {
// PaintPhaseForeground), normal paint (for PaintPhaseSelection and
// PaintPhaseTextClip) or nothing (other paint phases) according to
// paintInfo.phase.
- void PaintAllPhasesAtomically(const PaintInfo&,
- const LayoutPoint& paint_offset);
+ void PaintAllPhasesAtomically(const PaintInfo&);
const LayoutObject& layout_object_;
};
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 5559f902850..b4e59a12038 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
@@ -5,9 +5,13 @@
#include "third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
namespace blink {
+using ::testing::MatchesRegex;
+using ::testing::UnorderedElementsAre;
+
void SetUpHTML(PaintAndRasterInvalidationTest& test) {
test.SetBodyInnerHTML(R"HTML(
<style>
@@ -61,7 +65,7 @@ TEST_P(PaintAndRasterInvalidationTest, TrackingForTracing) {
target->setAttribute(HTMLNames::styleAttr, "height: 200px");
GetDocument().View()->UpdateAllLifecyclePhases();
EXPECT_THAT(GetCcLayerClient()->TakeDebugInfo(GetCcLayer())->ToString(),
- testing::MatchesRegex(
+ MatchesRegex(
"\\{\"layer_name\":.*\"annotated_invalidation_rects\":\\["
"\\{\"geometry_rect\":\\[8,108,100,100\\],"
"\"reason\":\"incremental\","
@@ -70,7 +74,7 @@ TEST_P(PaintAndRasterInvalidationTest, TrackingForTracing) {
target->setAttribute(HTMLNames::styleAttr, "height: 200px; width: 200px");
GetDocument().View()->UpdateAllLifecyclePhases();
EXPECT_THAT(GetCcLayerClient()->TakeDebugInfo(GetCcLayer())->ToString(),
- testing::MatchesRegex(
+ MatchesRegex(
"\\{\"layer_name\":.*\"annotated_invalidation_rects\":\\["
"\\{\"geometry_rect\":\\[108,8,100,200\\],"
"\"reason\":\"incremental\","
@@ -88,164 +92,159 @@ TEST_P(PaintAndRasterInvalidationTest, TrackingForTracing) {
TEST_P(PaintAndRasterInvalidationTest, IncrementalInvalidationExpand) {
SetUpHTML(*this);
Element* target = GetDocument().getElementById("target");
+ auto* object = target->GetLayoutObject();
GetDocument().View()->SetTracksPaintInvalidations(true);
target->setAttribute(HTMLNames::styleAttr, "width: 100px; height: 200px");
GetDocument().View()->UpdateAllLifecyclePhases();
- const auto& raster_invalidations =
- GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations.size());
- EXPECT_EQ(IntRect(50, 0, 50, 200), raster_invalidations[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- raster_invalidations[0].reason);
- EXPECT_EQ(IntRect(0, 100, 100, 100), raster_invalidations[1].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- raster_invalidations[1].reason);
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{object, object->DebugName(),
+ IntRect(50, 0, 50, 200),
+ PaintInvalidationReason::kIncremental},
+ RasterInvalidationInfo{
+ object, object->DebugName(), IntRect(0, 100, 100, 100),
+ PaintInvalidationReason::kIncremental}));
GetDocument().View()->SetTracksPaintInvalidations(false);
}
TEST_P(PaintAndRasterInvalidationTest, IncrementalInvalidationShrink) {
SetUpHTML(*this);
Element* target = GetDocument().getElementById("target");
+ auto* object = target->GetLayoutObject();
GetDocument().View()->SetTracksPaintInvalidations(true);
target->setAttribute(HTMLNames::styleAttr, "width: 20px; height: 80px");
GetDocument().View()->UpdateAllLifecyclePhases();
- const auto& raster_invalidations =
- GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations.size());
- EXPECT_EQ(IntRect(20, 0, 30, 100), raster_invalidations[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- raster_invalidations[0].reason);
- EXPECT_EQ(IntRect(0, 80, 50, 20), raster_invalidations[1].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- raster_invalidations[1].reason);
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{object, object->DebugName(),
+ IntRect(20, 0, 30, 100),
+ PaintInvalidationReason::kIncremental},
+ RasterInvalidationInfo{
+ object, object->DebugName(), IntRect(0, 80, 50, 20),
+ PaintInvalidationReason::kIncremental}));
GetDocument().View()->SetTracksPaintInvalidations(false);
}
TEST_P(PaintAndRasterInvalidationTest, IncrementalInvalidationMixed) {
SetUpHTML(*this);
Element* target = GetDocument().getElementById("target");
+ auto* object = target->GetLayoutObject();
GetDocument().View()->SetTracksPaintInvalidations(true);
target->setAttribute(HTMLNames::styleAttr, "width: 100px; height: 80px");
GetDocument().View()->UpdateAllLifecyclePhases();
- const auto& raster_invalidations =
- GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations.size());
- EXPECT_EQ(IntRect(50, 0, 50, 80), raster_invalidations[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- raster_invalidations[0].reason);
- EXPECT_EQ(IntRect(0, 80, 50, 20), raster_invalidations[1].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- raster_invalidations[1].reason);
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{object, object->DebugName(),
+ IntRect(50, 0, 50, 80),
+ PaintInvalidationReason::kIncremental},
+ RasterInvalidationInfo{
+ object, object->DebugName(), IntRect(0, 80, 50, 20),
+ PaintInvalidationReason::kIncremental}));
GetDocument().View()->SetTracksPaintInvalidations(false);
}
TEST_P(PaintAndRasterInvalidationTest, SubpixelVisualRectChagne) {
SetUpHTML(*this);
Element* target = GetDocument().getElementById("target");
+ auto* object = target->GetLayoutObject();
GetDocument().View()->SetTracksPaintInvalidations(true);
target->setAttribute(HTMLNames::styleAttr, "width: 100.6px; height: 70.3px");
GetDocument().View()->UpdateAllLifecyclePhases();
- const auto* raster_invalidations =
- &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations->size());
- EXPECT_EQ(IntRect(0, 0, 50, 100), (*raster_invalidations)[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- (*raster_invalidations)[0].reason);
- EXPECT_EQ(IntRect(0, 0, 101, 71), (*raster_invalidations)[1].rect);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- (*raster_invalidations)[1].reason);
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{object, object->DebugName(),
+ IntRect(0, 0, 50, 100),
+ PaintInvalidationReason::kGeometry},
+ RasterInvalidationInfo{object, object->DebugName(),
+ IntRect(0, 0, 101, 71),
+ PaintInvalidationReason::kGeometry}));
GetDocument().View()->SetTracksPaintInvalidations(false);
GetDocument().View()->SetTracksPaintInvalidations(true);
target->setAttribute(HTMLNames::styleAttr, "width: 50px; height: 100px");
GetDocument().View()->UpdateAllLifecyclePhases();
- raster_invalidations = &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations->size());
- EXPECT_EQ(IntRect(0, 0, 101, 71), (*raster_invalidations)[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- (*raster_invalidations)[0].reason);
- EXPECT_EQ(IntRect(0, 0, 50, 100), (*raster_invalidations)[1].rect);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- (*raster_invalidations)[1].reason);
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{object, object->DebugName(),
+ IntRect(0, 0, 50, 100),
+ PaintInvalidationReason::kGeometry},
+ RasterInvalidationInfo{object, object->DebugName(),
+ IntRect(0, 0, 101, 71),
+ PaintInvalidationReason::kGeometry}));
GetDocument().View()->SetTracksPaintInvalidations(false);
}
TEST_P(PaintAndRasterInvalidationTest, SubpixelVisualRectChangeWithTransform) {
SetUpHTML(*this);
Element* target = GetDocument().getElementById("target");
+ auto* object = target->GetLayoutObject();
target->setAttribute(HTMLNames::classAttr, "background transform");
GetDocument().View()->UpdateAllLifecyclePhases();
GetDocument().View()->SetTracksPaintInvalidations(true);
target->setAttribute(HTMLNames::styleAttr, "width: 100.6px; height: 70.3px");
GetDocument().View()->UpdateAllLifecyclePhases();
- const auto* raster_invalidations =
- &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations->size());
- EXPECT_EQ(IntRect(0, 0, 100, 200), (*raster_invalidations)[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- (*raster_invalidations)[0].reason);
- EXPECT_EQ(IntRect(0, 0, 202, 142), (*raster_invalidations)[1].rect);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- (*raster_invalidations)[1].reason);
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{object, object->DebugName(),
+ IntRect(0, 0, 100, 200),
+ PaintInvalidationReason::kGeometry},
+ RasterInvalidationInfo{object, object->DebugName(),
+ IntRect(0, 0, 202, 142),
+ PaintInvalidationReason::kGeometry}));
GetDocument().View()->SetTracksPaintInvalidations(false);
GetDocument().View()->SetTracksPaintInvalidations(true);
target->setAttribute(HTMLNames::styleAttr, "width: 50px; height: 100px");
GetDocument().View()->UpdateAllLifecyclePhases();
- raster_invalidations = &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(2u, raster_invalidations->size());
- EXPECT_EQ(IntRect(0, 0, 202, 142), (*raster_invalidations)[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- (*raster_invalidations)[0].reason);
- EXPECT_EQ(IntRect(0, 0, 100, 200), (*raster_invalidations)[1].rect);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- (*raster_invalidations)[1].reason);
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{object, object->DebugName(),
+ IntRect(0, 0, 100, 200),
+ PaintInvalidationReason::kGeometry},
+ RasterInvalidationInfo{object, object->DebugName(),
+ IntRect(0, 0, 202, 142),
+ PaintInvalidationReason::kGeometry}));
GetDocument().View()->SetTracksPaintInvalidations(false);
}
TEST_P(PaintAndRasterInvalidationTest, SubpixelWithinPixelsChange) {
SetUpHTML(*this);
Element* target = GetDocument().getElementById("target");
- LayoutObject* target_object = target->GetLayoutObject();
- EXPECT_EQ(LayoutRect(0, 0, 50, 100),
- target_object->FirstFragment().VisualRect());
+ LayoutObject* object = target->GetLayoutObject();
+ EXPECT_EQ(LayoutRect(0, 0, 50, 100), object->FirstFragment().VisualRect());
GetDocument().View()->SetTracksPaintInvalidations(true);
target->setAttribute(HTMLNames::styleAttr,
"margin-top: 0.6px; width: 50px; height: 99.3px");
GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_EQ(LayoutRect(0, 0, 50, 100),
- target_object->FirstFragment().VisualRect());
- const auto* raster_invalidations =
- &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations->size());
- EXPECT_EQ(IntRect(0, 0, 50, 100), (*raster_invalidations)[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- (*raster_invalidations)[0].reason);
+ EXPECT_EQ(LayoutRect(0, 0, 50, 100), object->FirstFragment().VisualRect());
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ object, object->DebugName(), IntRect(0, 0, 50, 100),
+ PaintInvalidationReason::kGeometry}));
GetDocument().View()->SetTracksPaintInvalidations(false);
GetDocument().View()->SetTracksPaintInvalidations(true);
target->setAttribute(HTMLNames::styleAttr,
"margin-top: 0.6px; width: 49.3px; height: 98.5px");
GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_EQ(LayoutRect(0, 0, 50, 100),
- target_object->FirstFragment().VisualRect());
- raster_invalidations = &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations->size());
- EXPECT_EQ(IntRect(0, 0, 50, 100), (*raster_invalidations)[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- (*raster_invalidations)[0].reason);
+ EXPECT_EQ(LayoutRect(0, 0, 50, 100), object->FirstFragment().VisualRect());
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ object, object->DebugName(), IntRect(0, 0, 50, 100),
+ PaintInvalidationReason::kGeometry}));
GetDocument().View()->SetTracksPaintInvalidations(false);
}
TEST_P(PaintAndRasterInvalidationTest, ResizeRotated) {
SetUpHTML(*this);
Element* target = GetDocument().getElementById("target");
+ auto* object = target->GetLayoutObject();
target->setAttribute(HTMLNames::styleAttr, "transform: rotate(45deg)");
GetDocument().View()->UpdateAllLifecyclePhases();
@@ -253,15 +252,13 @@ TEST_P(PaintAndRasterInvalidationTest, ResizeRotated) {
target->setAttribute(HTMLNames::styleAttr,
"transform: rotate(45deg); width: 200px");
GetDocument().View()->UpdateAllLifecyclePhases();
- const auto* raster_invalidations =
- &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations->size());
auto expected_rect = EnclosingIntRect(
TransformationMatrix().Rotate(45).MapRect(FloatRect(50, 0, 150, 100)));
expected_rect.Intersect(IntRect(0, 0, 800, 600));
- EXPECT_EQ(expected_rect, (*raster_invalidations)[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- (*raster_invalidations)[0].reason);
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ object, object->DebugName(), expected_rect,
+ PaintInvalidationReason::kIncremental}));
GetDocument().View()->SetTracksPaintInvalidations(false);
}
@@ -275,20 +272,19 @@ TEST_P(PaintAndRasterInvalidationTest, ResizeRotatedChild) {
"red'></div>");
GetDocument().View()->UpdateAllLifecyclePhases();
Element* child = GetDocument().getElementById("child");
+ auto* child_object = child->GetLayoutObject();
GetDocument().View()->SetTracksPaintInvalidations(true);
child->setAttribute(HTMLNames::styleAttr,
"width: 100px; height: 50px; background: red");
GetDocument().View()->UpdateAllLifecyclePhases();
- const auto* raster_invalidations =
- &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations->size());
auto expected_rect = EnclosingIntRect(
TransformationMatrix().Rotate(45).MapRect(FloatRect(50, 0, 50, 50)));
expected_rect.Intersect(IntRect(0, 0, 800, 600));
- EXPECT_EQ(expected_rect, (*raster_invalidations)[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- (*raster_invalidations)[0].reason);
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ child_object, child_object->DebugName(), expected_rect,
+ PaintInvalidationReason::kIncremental}));
GetDocument().View()->SetTracksPaintInvalidations(false);
}
@@ -307,16 +303,12 @@ TEST_P(PaintAndRasterInvalidationTest, CompositedLayoutViewResize) {
GetDocument().View()->SetTracksPaintInvalidations(true);
target->setAttribute(HTMLNames::styleAttr, "height: 3000px");
GetDocument().View()->UpdateAllLifecyclePhases();
- const auto& raster_invalidations =
- GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations.size());
- EXPECT_EQ(IntRect(0, 2000, 800, 1000), raster_invalidations[0].rect);
- EXPECT_EQ(static_cast<const DisplayItemClient*>(
- ViewScrollingContentsDisplayItemClient()),
- raster_invalidations[0].client);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- raster_invalidations[0].reason);
-
+ EXPECT_THAT(
+ GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ ViewScrollingContentsDisplayItemClient(),
+ ViewScrollingContentsDisplayItemClient()->DebugName(),
+ IntRect(0, 2000, 800, 1000), PaintInvalidationReason::kIncremental}));
GetDocument().View()->SetTracksPaintInvalidations(false);
// Resize the viewport. No paint invalidation.
@@ -344,16 +336,13 @@ TEST_P(PaintAndRasterInvalidationTest, CompositedLayoutViewGradientResize) {
target->setAttribute(HTMLNames::styleAttr, "height: 3000px");
GetDocument().View()->UpdateAllLifecyclePhases();
- const auto& raster_invalidations =
- GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations.size());
- EXPECT_EQ(IntRect(0, 0, 800, 3000), raster_invalidations[0].rect);
- EXPECT_EQ(static_cast<const DisplayItemClient*>(
- ViewScrollingContentsDisplayItemClient()),
- raster_invalidations[0].client);
- EXPECT_EQ(PaintInvalidationReason::kBackgroundOnScrollingContentsLayer,
- raster_invalidations[0].reason);
-
+ EXPECT_THAT(
+ GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ ViewScrollingContentsDisplayItemClient(),
+ ViewScrollingContentsDisplayItemClient()->DebugName(),
+ IntRect(0, 0, 800, 3000),
+ PaintInvalidationReason::kBackgroundOnScrollingContentsLayer}));
GetDocument().View()->SetTracksPaintInvalidations(false);
// Resize the viewport. No paint invalidation.
@@ -399,15 +388,12 @@ TEST_P(PaintAndRasterInvalidationTest, NonCompositedLayoutViewResize) {
GetDocument().View()->UpdateAllLifecyclePhases();
// The iframe doesn't have anything visible by itself, so we only issue raster
// invalidation for the frame contents.
- const auto& raster_invalidations =
- GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations.size());
- EXPECT_EQ(
- static_cast<const DisplayItemClient*>(content->GetLayoutObject()->View()),
- raster_invalidations[0].client);
- EXPECT_EQ(IntRect(0, 100, 100, 100), raster_invalidations[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- raster_invalidations[0].reason);
+ EXPECT_THAT(
+ GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ content->GetLayoutObject()->View(),
+ content->GetLayoutObject()->View()->DebugName(),
+ IntRect(0, 100, 100, 100), PaintInvalidationReason::kIncremental}));
GetDocument().View()->SetTracksPaintInvalidations(false);
}
@@ -441,29 +427,24 @@ TEST_P(PaintAndRasterInvalidationTest, NonCompositedLayoutViewGradientResize) {
GetDocument().View()->SetTracksPaintInvalidations(true);
content->setAttribute(HTMLNames::styleAttr, "height: 500px");
GetDocument().View()->UpdateAllLifecyclePhases();
- const auto* raster_invalidations =
- &GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations->size());
- EXPECT_EQ(IntRect(0, 0, 100, 100), (*raster_invalidations)[0].rect);
- EXPECT_EQ(static_cast<const DisplayItemClient*>(frame_layout_view),
- (*raster_invalidations)[0].client);
- EXPECT_EQ(PaintInvalidationReason::kBackground,
- (*raster_invalidations)[0].reason);
+ EXPECT_THAT(
+ GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ frame_layout_view, frame_layout_view->DebugName(),
+ IntRect(0, 0, 100, 100), PaintInvalidationReason::kBackground}));
GetDocument().View()->SetTracksPaintInvalidations(false);
// Resize the iframe.
GetDocument().View()->SetTracksPaintInvalidations(true);
iframe->setAttribute(HTMLNames::styleAttr, "height: 200px");
GetDocument().View()->UpdateAllLifecyclePhases();
- raster_invalidations = &GetRasterInvalidationTracking()->Invalidations();
// The iframe doesn't have anything visible by itself, so we only issue raster
// invalidation for the frame contents.
- ASSERT_EQ(1u, raster_invalidations->size());
- EXPECT_EQ(static_cast<const DisplayItemClient*>(frame_layout_view),
- (*raster_invalidations)[0].client);
- EXPECT_EQ(IntRect(0, 0, 100, 200), (*raster_invalidations)[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kGeometry,
- (*raster_invalidations)[0].reason);
+ EXPECT_THAT(
+ GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ frame_layout_view, frame_layout_view->DebugName(),
+ IntRect(0, 0, 100, 200), PaintInvalidationReason::kGeometry}));
GetDocument().View()->SetTracksPaintInvalidations(false);
}
@@ -508,15 +489,11 @@ TEST_P(PaintAndRasterInvalidationTest,
// No invalidation on the container layer.
EXPECT_FALSE(container_raster_invalidation_tracking()->HasInvalidations());
// Incremental invalidation of background on contents layer.
- const auto& contents_raster_invalidations =
- contents_raster_invalidation_tracking()->Invalidations();
- ASSERT_EQ(1u, contents_raster_invalidations.size());
- EXPECT_EQ(IntRect(0, 500, 500, 500), contents_raster_invalidations[0].rect);
- EXPECT_EQ(static_cast<const DisplayItemClient*>(
- target_obj->Layer()->GraphicsLayerBacking()),
- contents_raster_invalidations[0].client);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- contents_raster_invalidations[0].reason);
+ const auto* client = target_obj->Layer()->GraphicsLayerBacking();
+ EXPECT_THAT(contents_raster_invalidation_tracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ client, client->DebugName(), IntRect(0, 500, 500, 500),
+ PaintInvalidationReason::kIncremental}));
GetDocument().View()->SetTracksPaintInvalidations(false);
// Resize the container.
@@ -560,14 +537,11 @@ TEST_P(PaintAndRasterInvalidationTest,
container_layer->GetRasterInvalidationTracking()->HasInvalidations());
// Full invalidation of background on contents layer because the gradient
// background is resized.
- const auto& contents_raster_invalidations =
- contents_layer->GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, contents_raster_invalidations.size());
- EXPECT_EQ(IntRect(0, 0, 500, 1000), contents_raster_invalidations[0].rect);
- EXPECT_EQ(static_cast<const DisplayItemClient*>(contents_layer),
- contents_raster_invalidations[0].client);
- EXPECT_EQ(PaintInvalidationReason::kBackgroundOnScrollingContentsLayer,
- contents_raster_invalidations[0].reason);
+ EXPECT_THAT(
+ contents_layer->GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ contents_layer, contents_layer->DebugName(), IntRect(0, 0, 500, 1000),
+ PaintInvalidationReason::kBackgroundOnScrollingContentsLayer}));
GetDocument().View()->SetTracksPaintInvalidations(false);
// Resize the container.
@@ -587,6 +561,7 @@ TEST_P(PaintAndRasterInvalidationTest,
NonCompositedBackgroundAttachmentLocalResize) {
SetUpHTML(*this);
Element* target = GetDocument().getElementById("target");
+ auto* object = target->GetLayoutObject();
target->setAttribute(HTMLNames::classAttr, "background local-background");
target->SetInnerHTMLFromString(
"<div id=child style='width: 500px; height: 500px'></div>",
@@ -607,14 +582,10 @@ TEST_P(PaintAndRasterInvalidationTest,
GetDocument().View()->SetTracksPaintInvalidations(true);
target->setAttribute(HTMLNames::styleAttr, "height: 200px");
GetDocument().View()->UpdateAllLifecyclePhases();
- const auto& raster_invalidations =
- GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations.size());
- EXPECT_EQ(IntRect(0, 100, 50, 100), raster_invalidations[0].rect);
- EXPECT_EQ(static_cast<const DisplayItemClient*>(target->GetLayoutObject()),
- raster_invalidations[0].client);
- EXPECT_EQ(PaintInvalidationReason::kIncremental,
- raster_invalidations[0].reason);
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ object, object->DebugName(), IntRect(0, 100, 50, 100),
+ PaintInvalidationReason::kIncremental}));
GetDocument().View()->SetTracksPaintInvalidations(false);
}
@@ -639,15 +610,12 @@ TEST_P(PaintAndRasterInvalidationTest, CompositedSolidBackgroundResize) {
ToLayoutBoxModelObject(target->GetLayoutObject());
GraphicsLayer* scrolling_contents_layer =
target_object->Layer()->GraphicsLayerBacking();
- const auto& invalidations =
+ EXPECT_THAT(
scrolling_contents_layer->GetRasterInvalidationTracking()
- ->Invalidations();
-
- ASSERT_EQ(1u, invalidations.size());
- EXPECT_EQ(IntRect(50, 0, 50, 500), invalidations[0].rect);
- EXPECT_EQ(static_cast<const DisplayItemClient*>(scrolling_contents_layer),
- invalidations[0].client);
- EXPECT_EQ(PaintInvalidationReason::kIncremental, invalidations[0].reason);
+ ->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ scrolling_contents_layer, scrolling_contents_layer->DebugName(),
+ IntRect(50, 0, 50, 500), PaintInvalidationReason::kIncremental}));
GetDocument().View()->SetTracksPaintInvalidations(false);
}
@@ -675,8 +643,7 @@ TEST_P(PaintAndRasterInvalidationTest, RecalcOverflowInvalidatesBackground) {
GetDocument().View()->UpdateAllLifecyclePhases();
- ScrollableArea* scrollable_area =
- GetDocument().View()->LayoutViewportScrollableArea();
+ ScrollableArea* scrollable_area = GetDocument().View()->LayoutViewport();
ASSERT_EQ(scrollable_area->MaximumScrollOffset().Height(), 0);
EXPECT_FALSE(GetDocument().GetLayoutView()->MayNeedPaintInvalidation());
@@ -746,13 +713,12 @@ TEST_P(PaintAndRasterInvalidationTest, DelayedFullPaintInvalidation) {
// Scroll target into view.
GetDocument().domWindow()->scrollTo(0, 4000);
GetDocument().View()->UpdateAllLifecyclePhases();
- const auto& raster_invalidations =
- GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations.size());
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ target, target->DebugName(), IntRect(0, 4000, 100, 100),
+ PaintInvalidationReason::kFull}));
EXPECT_EQ(PaintInvalidationReason::kNone,
target->FullPaintInvalidationReason());
- EXPECT_EQ(IntRect(0, 4000, 100, 100), raster_invalidations[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kFull, raster_invalidations[0].reason);
EXPECT_FALSE(target->NeedsPaintOffsetAndVisualRectUpdate());
GetDocument().View()->SetTracksPaintInvalidations(false);
};
@@ -786,9 +752,8 @@ TEST_P(PaintAndRasterInvalidationTest, SVGHiddenContainer) {
EXPECT_EQ(PaintInvalidationReason::kFull,
real_rect->GetPaintInvalidationReason());
- // mask_rect has PaintInvalidationReason::kFull because it is not cached by
- // any PaintController.
- EXPECT_EQ(PaintInvalidationReason::kFull,
+ // mask_rect is not cached and validated by any PaintController.
+ EXPECT_EQ(PaintInvalidationReason::kJustCreated,
mask_rect->GetPaintInvalidationReason());
GetDocument().View()->UpdateAllLifecyclePhases();
@@ -799,27 +764,23 @@ TEST_P(PaintAndRasterInvalidationTest, SVGHiddenContainer) {
// Should invalidate raster for real_rect only.
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
// SPv2 creates composited layers for the rect and its mask.
- const auto& rect_raster_invalidations =
- GetRasterInvalidationTracking(1)->Invalidations();
- ASSERT_EQ(1u, rect_raster_invalidations.size());
- EXPECT_EQ(IntRect(0, 0, 7, 8), rect_raster_invalidations[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kFull,
- rect_raster_invalidations[0].reason);
- const auto& mask_raster_invalidations =
- GetRasterInvalidationTracking(2)->Invalidations();
- ASSERT_EQ(1u, mask_raster_invalidations.size());
- EXPECT_EQ(IntRect(0, 0, 7, 8), mask_raster_invalidations[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kFull,
- mask_raster_invalidations[0].reason);
+ EXPECT_THAT(GetRasterInvalidationTracking(1)->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ real_rect, real_rect->DebugName(), IntRect(0, 0, 7, 8),
+ PaintInvalidationReason::kFull}));
+ EXPECT_THAT(GetRasterInvalidationTracking(2)->Invalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ real_rect, real_rect->DebugName(), IntRect(0, 0, 7, 8),
+ PaintInvalidationReason::kFull}));
} else {
- const auto& raster_invalidations =
- GetRasterInvalidationTracking()->Invalidations();
- // The first is for the rect itself, the second is for its mask.
- ASSERT_EQ(2u, raster_invalidations.size());
- EXPECT_EQ(IntRect(155, 166, 7, 8), raster_invalidations[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kFull, raster_invalidations[0].reason);
- EXPECT_EQ(IntRect(155, 166, 7, 8), raster_invalidations[1].rect);
- EXPECT_EQ(PaintInvalidationReason::kFull, raster_invalidations[1].reason);
+ EXPECT_THAT(GetRasterInvalidationTracking(1)->Invalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{real_rect, real_rect->DebugName(),
+ IntRect(155, 166, 7, 8),
+ PaintInvalidationReason::kFull},
+ RasterInvalidationInfo{real_rect, real_rect->DebugName(),
+ IntRect(155, 166, 7, 8),
+ PaintInvalidationReason::kFull}));
}
GetDocument().View()->SetTracksPaintInvalidations(false);
@@ -864,6 +825,35 @@ TEST_P(PaintAndRasterInvalidationTest, UpdateVisualRectWhenPrinting) {
EXPECT_EQ(LayoutRect(300, 0, 150, 20), c->FirstFragment().VisualRect());
};
+TEST_P(PaintAndRasterInvalidationTest, PaintPropertyChange) {
+ SetUpHTML(*this);
+ Element* target = GetDocument().getElementById("target");
+ auto* object = target->GetLayoutObject();
+ target->setAttribute(HTMLNames::classAttr, "background transform");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ auto* layer = ToLayoutBoxModelObject(object)->Layer();
+ GetDocument().View()->SetTracksPaintInvalidations(true);
+ target->setAttribute(HTMLNames::styleAttr, "transform: scale(3)");
+ GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
+ EXPECT_FALSE(layer->NeedsRepaint());
+ const auto* transform =
+ object->FirstFragment().PaintProperties()->Transform();
+ EXPECT_TRUE(transform->Changed(*transform->Parent()));
+
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ EXPECT_THAT(GetRasterInvalidationTracking()->Invalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{
+ layer, layer->DebugName(), IntRect(0, 0, 100, 200),
+ PaintInvalidationReason::kPaintProperty},
+ RasterInvalidationInfo{
+ layer, layer->DebugName(), IntRect(0, 0, 150, 300),
+ PaintInvalidationReason::kPaintProperty}));
+ EXPECT_FALSE(transform->Changed(*transform->Parent()));
+ GetDocument().View()->SetTracksPaintInvalidations(false);
+}
+
class PaintInvalidatorTestClient : public EmptyChromeClient {
public:
void InvalidateRect(const IntRect&) override {
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.h b/chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.h
new file mode 100644
index 00000000000..c5ba86ed439
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.h
@@ -0,0 +1,74 @@
+// 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_PAINT_AND_RASTER_INVALIDATION_TEST_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_AND_RASTER_INVALIDATION_TEST_H_
+
+#include "cc/layers/picture_layer.h"
+#include "third_party/blink/renderer/core/paint/paint_controller_paint_test.h"
+#include "third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h"
+#include "third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h"
+#include "third_party/blink/renderer/platform/testing/layer_tree_host_embedder.h"
+
+namespace blink {
+
+class PaintAndRasterInvalidationTest : public PaintControllerPaintTest {
+ public:
+ PaintAndRasterInvalidationTest()
+ : PaintControllerPaintTest(SingleChildLocalFrameClient::Create()) {}
+
+ protected:
+ cc::Layer* GetCcLayer(size_t index = 0) const {
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ return GetDocument()
+ .View()
+ ->GetPaintArtifactCompositorForTesting()
+ ->RootLayer()
+ ->children()[index]
+ .get();
+ }
+ return GetLayoutView().Layer()->GraphicsLayerBacking()->ContentLayer();
+ }
+
+ cc::LayerClient* GetCcLayerClient(size_t index = 0) const {
+ return GetCcLayer(index)->GetLayerClientForTesting();
+ }
+
+ const RasterInvalidationTracking* GetRasterInvalidationTracking(
+ size_t index = 0) const {
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ return static_cast<ContentLayerClientImpl*>(GetCcLayerClient(index))
+ ->GetRasterInvalidator()
+ .GetTracking();
+ }
+ return GetLayoutView()
+ .Layer()
+ ->GraphicsLayerBacking()
+ ->GetRasterInvalidationTracking();
+ }
+
+ void SetUp() override {
+ PaintControllerPaintTest::SetUp();
+
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ layer_tree_ = std::make_unique<LayerTreeHostEmbedder>();
+ layer_tree_->layer_tree_host()->SetRootLayer(
+ GetDocument()
+ .View()
+ ->GetPaintArtifactCompositorForTesting()
+ ->RootLayer());
+ }
+ }
+
+ const DisplayItemClient* ViewScrollingContentsDisplayItemClient() const {
+ return GetLayoutView().Layer()->GraphicsLayerBacking();
+ }
+
+ private:
+ std::unique_ptr<LayerTreeHostEmbedder> layer_tree_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_AND_RASTER_INVALIDATION_TEST_H_
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 84a50e34f53..7de9c6fa26c 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
@@ -77,9 +77,6 @@ TEST_P(PaintControllerPaintTest, InlineRelayout) {
}
TEST_P(PaintControllerPaintTest, ChunkIdClientCacheFlag) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<div id='div' style='width: 200px; height: 200px; opacity: 0.5'>
<div style='width: 100px; height: 100px; background-color:
@@ -120,9 +117,6 @@ TEST_P(PaintControllerPaintTest, ChunkIdClientCacheFlag) {
}
TEST_P(PaintControllerPaintTest, CompositingNoFold) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<div id='div' style='width: 200px; height: 200px; opacity: 0.5'>
<div style='width: 100px; height: 100px; background-color:
@@ -161,7 +155,7 @@ TEST_P(PaintControllerPaintTestForSPv2, FrameScrollingContents) {
TestDisplayItem(GetLayoutView(), kScrollHitTestType),
TestDisplayItem(div1, kBackgroundType));
- GetDocument().View()->LayoutViewportScrollableArea()->SetScrollOffset(
+ GetDocument().View()->LayoutViewport()->SetScrollOffset(
ScrollOffset(5000, 5000), kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.h b/chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.h
index d590d26deee..9b284a22450 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_controller_paint_test.h
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/layout/layout_view.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"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
@@ -66,23 +67,24 @@ class PaintControllerPaintTestBase : public RenderingTest {
const DisplayItemClient& ViewBackgroundClient() {
if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- // With SPv1*, the document background uses the scrolling contents
+ // With SPv1, the document background uses the scrolling contents
// layer as its DisplayItemClient.
return *GetLayoutView().Layer()->GraphicsLayerBacking();
}
return GetLayoutView();
}
- void Commit() {
+ void CommitAndFinishCycle() {
// Only root graphics layer is supported.
RootPaintController().CommitNewDisplayItems();
+ RootPaintController().FinishCycle();
GetDocument().View()->Lifecycle().AdvanceTo(DocumentLifecycle::kPaintClean);
}
void Paint(const IntRect* interest_rect = nullptr) {
// Only root graphics layer is supported.
if (PaintWithoutCommit(interest_rect))
- Commit();
+ CommitAndFinishCycle();
}
bool DisplayItemListContains(const DisplayItemList& display_item_list,
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_info.h b/chromium/third_party/blink/renderer/core/paint/paint_info.h
index 57bfcf9f3aa..b8f42f22f23 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_info.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_info.h
@@ -115,7 +115,7 @@ struct CORE_EXPORT PaintInfo {
}
DisplayItem::Type DisplayItemTypeForClipping() const {
- return DisplayItem::PaintPhaseToClipBoxType(phase);
+ return DisplayItem::PaintPhaseToClipType(phase);
}
const LayoutBoxModelObject* PaintContainer() const {
@@ -128,6 +128,10 @@ struct CORE_EXPORT PaintInfo {
const CullRect& GetCullRect() const { return cull_rect_; }
+ void ApplyInfiniteCullRect() {
+ cull_rect_ = CullRect(LayoutRect::InfiniteIntRect());
+ }
+
void UpdateCullRect(const AffineTransform& local_to_parent_transform) {
cull_rect_.UpdateCullRect(local_to_parent_transform);
}
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_invalidation_capable_scrollable_area.cc b/chromium/third_party/blink/renderer/core/paint/paint_invalidation_capable_scrollable_area.cc
deleted file mode 100644
index bb693b4536c..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/paint_invalidation_capable_scrollable_area.cc
+++ /dev/null
@@ -1,282 +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/paint_invalidation_capable_scrollable_area.h"
-
-#include "third_party/blink/renderer/core/frame/settings.h"
-#include "third_party/blink/renderer/core/frame/use_counter.h"
-#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
-#include "third_party/blink/renderer/core/layout/layout_box.h"
-#include "third_party/blink/renderer/core/layout/layout_scrollbar.h"
-#include "third_party/blink/renderer/core/layout/layout_scrollbar_part.h"
-#include "third_party/blink/renderer/core/paint/find_paint_offset_and_visual_rect_needing_update.h"
-#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
-#include "third_party/blink/renderer/core/paint/paint_invalidator.h"
-#include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-
-namespace blink {
-
-void PaintInvalidationCapableScrollableArea::WillRemoveScrollbar(
- Scrollbar& scrollbar,
- ScrollbarOrientation orientation) {
- if (!scrollbar.IsCustomScrollbar() &&
- !(orientation == kHorizontalScrollbar ? LayerForHorizontalScrollbar()
- : LayerForVerticalScrollbar())) {
- ObjectPaintInvalidator(*GetLayoutBox())
- .SlowSetPaintingLayerNeedsRepaintAndInvalidateDisplayItemClient(
- scrollbar, PaintInvalidationReason::kScrollControl);
- }
-
- ScrollableArea::WillRemoveScrollbar(scrollbar, orientation);
-}
-
-static LayoutRect ScrollControlVisualRect(
- const IntRect& scroll_control_rect,
- const LayoutBox& box,
- const PaintInvalidatorContext& context,
- const LayoutRect& previous_visual_rect) {
- LayoutRect visual_rect(scroll_control_rect);
-#if DCHECK_IS_ON()
- FindVisualRectNeedingUpdateScope finder(box, context, previous_visual_rect,
- visual_rect);
-#endif
- if (!context.NeedsVisualRectUpdate(box))
- return previous_visual_rect;
-
- // No need to apply any paint offset. Scroll controls paint in a different
- // transform space than their contained box (the scrollbarPaintOffset
- // transform node).
- if (!visual_rect.IsEmpty() &&
- !RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- // PaintInvalidatorContext::mapLocalRectToPaintInvalidationBacking() treats
- // the rect as in flipped block direction, but scrollbar controls don't
- // flip for block direction, so flip here to undo the flip in the function.
- box.FlipForWritingMode(visual_rect);
- context.MapLocalRectToVisualRectInBacking(box, visual_rect);
- }
- return visual_rect;
-}
-
-// Returns true if the scroll control is invalidated.
-static bool InvalidatePaintOfScrollControlIfNeeded(
- const LayoutRect& new_visual_rect,
- const LayoutRect& previous_visual_rect,
- bool needs_paint_invalidation,
- LayoutBox& box,
- const LayoutBoxModelObject& paint_invalidation_container) {
- bool should_invalidate_new_rect = needs_paint_invalidation;
- if (new_visual_rect != previous_visual_rect) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- ObjectPaintInvalidator(box).InvalidatePaintUsingContainer(
- paint_invalidation_container, previous_visual_rect,
- PaintInvalidationReason::kScrollControl);
- }
- should_invalidate_new_rect = true;
- } else if (previous_visual_rect.IsEmpty()) {
- DCHECK(new_visual_rect.IsEmpty());
- // Do not issue an empty invalidation.
- should_invalidate_new_rect = false;
- }
-
- if (should_invalidate_new_rect) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- ObjectPaintInvalidator(box).InvalidatePaintUsingContainer(
- paint_invalidation_container, new_visual_rect,
- PaintInvalidationReason::kScrollControl);
- }
- return true;
- }
- return false;
-}
-
-static LayoutRect InvalidatePaintOfScrollbarIfNeeded(
- Scrollbar* scrollbar,
- GraphicsLayer* graphics_layer,
- bool& previously_was_overlay,
- const LayoutRect& previous_visual_rect,
- bool needs_paint_invalidation_arg,
- LayoutBox& box,
- const PaintInvalidatorContext& context) {
- bool is_overlay = scrollbar && scrollbar->IsOverlayScrollbar();
-
- LayoutRect new_visual_rect;
- // Calculate visual rect of the scrollbar, except overlay composited
- // scrollbars because we invalidate the graphics layer only.
- if (scrollbar && !(graphics_layer && is_overlay)) {
- new_visual_rect = ScrollControlVisualRect(scrollbar->FrameRect(), box,
- context, previous_visual_rect);
- }
-
- bool needs_paint_invalidation = needs_paint_invalidation_arg;
- if (needs_paint_invalidation && graphics_layer) {
- // If the scrollbar needs paint invalidation but didn't change location/size
- // or the scrollbar is an overlay scrollbar (visual rect is empty),
- // invalidating the graphics layer is enough (which has been done in
- // ScrollableArea::setScrollbarNeedsPaintInvalidation()).
- // Otherwise invalidatePaintOfScrollControlIfNeeded() below will invalidate
- // the old and new location of the scrollbar on the box's paint invalidation
- // container to ensure newly expanded/shrunk areas of the box to be
- // invalidated.
- needs_paint_invalidation = false;
- DCHECK(!graphics_layer->DrawsContent() ||
- graphics_layer->GetPaintController().GetPaintArtifact().IsEmpty());
- }
-
- // Invalidate the box's display item client if the box's padding box size is
- // affected by change of the non-overlay scrollbar width. We detect change of
- // visual rect size instead of change of scrollbar width change, which may
- // have some false-positives (e.g. the scrollbar changed length but not width)
- // but won't invalidate more than expected because in the false-positive case
- // the box must have changed size and have been invalidated.
- const LayoutBoxModelObject& paint_invalidation_container =
- *context.paint_invalidation_container;
- LayoutSize new_scrollbar_used_space_in_box;
- if (!is_overlay)
- new_scrollbar_used_space_in_box = new_visual_rect.Size();
- LayoutSize previous_scrollbar_used_space_in_box;
- if (!previously_was_overlay)
- previous_scrollbar_used_space_in_box = previous_visual_rect.Size();
- if (new_scrollbar_used_space_in_box != previous_scrollbar_used_space_in_box) {
- context.painting_layer->SetNeedsRepaint();
- ObjectPaintInvalidator(box).InvalidateDisplayItemClient(
- box, PaintInvalidationReason::kGeometry);
- }
-
- bool invalidated = InvalidatePaintOfScrollControlIfNeeded(
- new_visual_rect, previous_visual_rect, needs_paint_invalidation, box,
- paint_invalidation_container);
-
- previously_was_overlay = is_overlay;
-
- if (!invalidated || !scrollbar || graphics_layer)
- return new_visual_rect;
-
- context.painting_layer->SetNeedsRepaint();
- ObjectPaintInvalidator(box).InvalidateDisplayItemClient(
- *scrollbar, PaintInvalidationReason::kScrollControl);
- if (scrollbar->IsCustomScrollbar()) {
- ToLayoutScrollbar(scrollbar)
- ->InvalidateDisplayItemClientsOfScrollbarParts();
- }
-
- return new_visual_rect;
-}
-
-void PaintInvalidationCapableScrollableArea::
- InvalidatePaintOfScrollControlsIfNeeded(
- const PaintInvalidatorContext& context) {
- LayoutBox& box = *GetLayoutBox();
- SetHorizontalScrollbarVisualRect(InvalidatePaintOfScrollbarIfNeeded(
- HorizontalScrollbar(), LayerForHorizontalScrollbar(),
- horizontal_scrollbar_previously_was_overlay_,
- horizontal_scrollbar_visual_rect_,
- HorizontalScrollbarNeedsPaintInvalidation(), box, context));
- SetVerticalScrollbarVisualRect(InvalidatePaintOfScrollbarIfNeeded(
- VerticalScrollbar(), LayerForVerticalScrollbar(),
- vertical_scrollbar_previously_was_overlay_,
- vertical_scrollbar_visual_rect_,
- VerticalScrollbarNeedsPaintInvalidation(), box, context));
-
- LayoutRect scroll_corner_and_resizer_visual_rect =
- ScrollControlVisualRect(ScrollCornerAndResizerRect(), box, context,
- scroll_corner_and_resizer_visual_rect_);
- const LayoutBoxModelObject& paint_invalidation_container =
- *context.paint_invalidation_container;
- if (InvalidatePaintOfScrollControlIfNeeded(
- scroll_corner_and_resizer_visual_rect,
- scroll_corner_and_resizer_visual_rect_,
- ScrollCornerNeedsPaintInvalidation(), box,
- paint_invalidation_container)) {
- SetScrollCornerAndResizerVisualRect(scroll_corner_and_resizer_visual_rect);
- if (LayoutScrollbarPart* scroll_corner = ScrollCorner()) {
- ObjectPaintInvalidator(*scroll_corner)
- .InvalidateDisplayItemClientsIncludingNonCompositingDescendants(
- PaintInvalidationReason::kScrollControl);
- }
- if (LayoutScrollbarPart* resizer = Resizer()) {
- ObjectPaintInvalidator(*resizer)
- .InvalidateDisplayItemClientsIncludingNonCompositingDescendants(
- PaintInvalidationReason::kScrollControl);
- }
- }
-
- ClearNeedsPaintInvalidationForScrollControls();
-}
-
-void PaintInvalidationCapableScrollableArea::ClearPreviousVisualRects() {
- SetHorizontalScrollbarVisualRect(LayoutRect());
- SetVerticalScrollbarVisualRect(LayoutRect());
- SetScrollCornerAndResizerVisualRect(LayoutRect());
-}
-
-void PaintInvalidationCapableScrollableArea::SetHorizontalScrollbarVisualRect(
- const LayoutRect& rect) {
- horizontal_scrollbar_visual_rect_ = rect;
- if (Scrollbar* scrollbar = HorizontalScrollbar())
- scrollbar->SetVisualRect(rect);
-}
-
-void PaintInvalidationCapableScrollableArea::SetVerticalScrollbarVisualRect(
- const LayoutRect& rect) {
- vertical_scrollbar_visual_rect_ = rect;
- if (Scrollbar* scrollbar = VerticalScrollbar())
- scrollbar->SetVisualRect(rect);
-}
-
-void PaintInvalidationCapableScrollableArea::
- SetScrollCornerAndResizerVisualRect(const LayoutRect& rect) {
- scroll_corner_and_resizer_visual_rect_ = rect;
- if (LayoutScrollbarPart* scroll_corner = ScrollCorner())
- scroll_corner->GetMutableForPainting().FirstFragment().SetVisualRect(rect);
- if (LayoutScrollbarPart* resizer = Resizer())
- resizer->GetMutableForPainting().FirstFragment().SetVisualRect(rect);
-}
-
-void PaintInvalidationCapableScrollableArea::
- ScrollControlWasSetNeedsPaintInvalidation() {
- GetLayoutBox()->SetMayNeedPaintInvalidation();
-}
-
-void PaintInvalidationCapableScrollableArea::DidScrollWithScrollbar(
- ScrollbarPart part,
- ScrollbarOrientation orientation) {
- WebFeature scrollbar_use_uma;
- switch (part) {
- case kBackButtonStartPart:
- case kForwardButtonStartPart:
- case kBackButtonEndPart:
- case kForwardButtonEndPart:
- scrollbar_use_uma =
- (orientation == kVerticalScrollbar
- ? WebFeature::kScrollbarUseVerticalScrollbarButton
- : WebFeature::kScrollbarUseHorizontalScrollbarButton);
- break;
- case kThumbPart:
- scrollbar_use_uma =
- (orientation == kVerticalScrollbar
- ? WebFeature::kScrollbarUseVerticalScrollbarThumb
- : WebFeature::kScrollbarUseHorizontalScrollbarThumb);
- break;
- case kBackTrackPart:
- case kForwardTrackPart:
- scrollbar_use_uma =
- (orientation == kVerticalScrollbar
- ? WebFeature::kScrollbarUseVerticalScrollbarTrack
- : WebFeature::kScrollbarUseHorizontalScrollbarTrack);
- break;
- default:
- return;
- }
-
- UseCounter::Count(GetLayoutBox()->GetDocument(), scrollbar_use_uma);
-}
-
-CompositorElementId
-PaintInvalidationCapableScrollableArea::GetCompositorElementId() const {
- return CompositorElementIdFromUniqueObjectId(
- GetLayoutBox()->UniqueId(), CompositorElementIdNamespace::kScroll);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_invalidation_capable_scrollable_area.h b/chromium/third_party/blink/renderer/core/paint/paint_invalidation_capable_scrollable_area.h
deleted file mode 100644
index 19eaa0c44f2..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/paint_invalidation_capable_scrollable_area.h
+++ /dev/null
@@ -1,61 +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_PAINT_INVALIDATION_CAPABLE_SCROLLABLE_AREA_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_INVALIDATION_CAPABLE_SCROLLABLE_AREA_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
-#include "third_party/blink/renderer/platform/scroll/scrollable_area.h"
-
-namespace blink {
-
-class LayoutScrollbarPart;
-struct PaintInvalidatorContext;
-
-// Base class of LocalFrameView and PaintLayerScrollableArea to share paint
-// invalidation code.
-// TODO(wangxianzhu): Combine this into PaintLayerScrollableArea when
-// root-layer-scrolls launches.
-class CORE_EXPORT PaintInvalidationCapableScrollableArea
- : public ScrollableArea {
- public:
- PaintInvalidationCapableScrollableArea()
- : horizontal_scrollbar_previously_was_overlay_(false),
- vertical_scrollbar_previously_was_overlay_(false) {}
-
- void WillRemoveScrollbar(Scrollbar&, ScrollbarOrientation) override;
-
- void InvalidatePaintOfScrollControlsIfNeeded(const PaintInvalidatorContext&);
-
- // Should be called when the previous visual rects are no longer valid.
- void ClearPreviousVisualRects();
-
- virtual IntRect ScrollCornerAndResizerRect() const {
- return ScrollCornerRect();
- }
-
- void DidScrollWithScrollbar(ScrollbarPart, ScrollbarOrientation) override;
- CompositorElementId GetCompositorElementId() const override;
-
- private:
- virtual LayoutScrollbarPart* ScrollCorner() const = 0;
- virtual LayoutScrollbarPart* Resizer() const = 0;
-
- void ScrollControlWasSetNeedsPaintInvalidation() override;
-
- void SetHorizontalScrollbarVisualRect(const LayoutRect&);
- void SetVerticalScrollbarVisualRect(const LayoutRect&);
- void SetScrollCornerAndResizerVisualRect(const LayoutRect&);
-
- bool horizontal_scrollbar_previously_was_overlay_;
- bool vertical_scrollbar_previously_was_overlay_;
- LayoutRect horizontal_scrollbar_visual_rect_;
- LayoutRect vertical_scrollbar_visual_rect_;
- LayoutRect scroll_corner_and_resizer_visual_rect_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_INVALIDATION_CAPABLE_SCROLLABLE_AREA_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_invalidation_test.cc b/chromium/third_party/blink/renderer/core/paint/paint_invalidation_test.cc
deleted file mode 100644
index 2412648cbab..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/paint_invalidation_test.cc
+++ /dev/null
@@ -1,345 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/core/frame/local_frame_view.h"
-#include "third_party/blink/renderer/core/layout/layout_view.h"
-#include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
-#include "third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h"
-#include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
-
-namespace blink {
-
-namespace {
-
-class PaintInvalidationTest : public PaintTestConfigurations,
- public RenderingTest {
- public:
- PaintInvalidationTest()
- : RenderingTest(SingleChildLocalFrameClient::Create()) {}
-
- protected:
- const RasterInvalidationTracking* GetRasterInvalidationTracking() const {
- // TODO(wangxianzhu): Test raster invalidation for SPv2 (in this test suite
- // or elsewhere for the applicable cases in this test suite).
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
- return GetLayoutView()
- .Layer()
- ->GraphicsLayerBacking()
- ->GetRasterInvalidationTracking();
- }
-};
-
-INSTANTIATE_PAINT_TEST_CASE_P(PaintInvalidationTest);
-
-// Changing style in a way that changes overflow without layout should cause
-// the layout view to possibly need a paint invalidation since we may have
-// revealed additional background that can be scrolled into view.
-TEST_P(PaintInvalidationTest, RecalcOverflowInvalidatesBackground) {
- GetDocument().GetPage()->GetSettings().SetViewportEnabled(true);
- SetBodyInnerHTML(R"HTML(
- <!DOCTYPE html>
- <style type='text/css'>
- body, html {
- width: 100%;
- height: 100%;
- margin: 0px;
- }
- #container {
- will-change: transform;
- width: 100%;
- height: 100%;
- }
- </style>
- <div id='container'></div>
- )HTML");
-
- GetDocument().View()->UpdateAllLifecyclePhases();
-
- ScrollableArea* scrollable_area =
- GetDocument().View()->LayoutViewportScrollableArea();
- ASSERT_EQ(scrollable_area->MaximumScrollOffset().Height(), 0);
- EXPECT_FALSE(GetDocument().GetLayoutView()->MayNeedPaintInvalidation());
-
- Element* container = GetDocument().getElementById("container");
- container->setAttribute(HTMLNames::styleAttr,
- "transform: translateY(1000px);");
- GetDocument().UpdateStyleAndLayoutTree();
-
- EXPECT_EQ(scrollable_area->MaximumScrollOffset().Height(), 1000);
- EXPECT_TRUE(GetDocument().GetLayoutView()->MayNeedPaintInvalidation());
-}
-
-TEST_P(PaintInvalidationTest, UpdateVisualRectOnFrameBorderWidthChange) {
- // TODO(wangxianzhu): enable for SPv2.
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- return;
-
- SetBodyInnerHTML(R"HTML(
- <style>
- body { margin: 10px }
- iframe { width: 100px; height: 100px; border: none; }
- </style>
- <iframe id='iframe'></iframe>
- )HTML");
-
- Element* iframe = GetDocument().getElementById("iframe");
- LayoutView* child_layout_view = ChildDocument().GetLayoutView();
- EXPECT_EQ(GetDocument().GetLayoutView(),
- &child_layout_view->ContainerForPaintInvalidation());
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(LayoutRect(0, 0, 100, 100),
- child_layout_view->FirstFragment().VisualRect());
- } else {
- EXPECT_EQ(LayoutRect(10, 10, 100, 100),
- child_layout_view->FirstFragment().VisualRect());
- }
-
- iframe->setAttribute(HTMLNames::styleAttr, "border: 20px solid blue");
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_EQ(GetDocument().GetLayoutView(),
- &child_layout_view->ContainerForPaintInvalidation());
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(LayoutRect(0, 0, 100, 100),
- child_layout_view->FirstFragment().VisualRect());
- } else {
- EXPECT_EQ(LayoutRect(30, 30, 100, 100),
- child_layout_view->FirstFragment().VisualRect());
- }
-};
-
-// This is a simplified test case for crbug.com/704182. It ensures no repaint
-// on transform change causing no visual change.
-TEST_P(PaintInvalidationTest, InvisibleTransformUnderFixedOnScroll) {
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- return;
-
- EnableCompositing();
- SetBodyInnerHTML(R"HTML(
- <style>
- #fixed {
- position: fixed;
- top: 0;
- left: 0;
- width: 100px;
- height: 100px;
- background-color: blue;
- }
- #transform {
- width: 100px;
- height: 100px;
- background-color: yellow;
- will-change: transform;
- transform: translate(10px, 20px);
- }
- </style>
- <div style='height: 2000px'></div>
- <div id='fixed' style='visibility: hidden'>
- <div id='transform'></div>
- </div>
- )HTML");
-
- auto& fixed = *GetDocument().getElementById("fixed");
- const auto& fixed_object = ToLayoutBox(*fixed.GetLayoutObject());
- const auto& fixed_layer = *fixed_object.Layer();
- auto& transform = *GetDocument().getElementById("transform");
- EXPECT_TRUE(fixed_layer.SubtreeIsInvisible());
- EXPECT_EQ(LayoutRect(0, 0, 110, 120), fixed_object.LayoutOverflowRect());
-
- GetDocument().domWindow()->scrollTo(0, 100);
- transform.setAttribute(HTMLNames::styleAttr,
- "transform: translate(20px, 30px)");
- GetDocument().View()->UpdateLifecycleToCompositingCleanPlusScrolling();
-
- EXPECT_TRUE(fixed_layer.SubtreeIsInvisible());
- // We skip invisible layers when setting non-composited fixed-position
- // needing paint invalidation when the frame is scrolled.
- EXPECT_FALSE(fixed_object.ShouldDoFullPaintInvalidation());
- // This was set when fixedObject is marked needsOverflowRecaldAfterStyleChange
- // when child changed transform.
- EXPECT_TRUE(fixed_object.MayNeedPaintInvalidation());
- EXPECT_EQ(LayoutRect(0, 0, 120, 130), fixed_object.LayoutOverflowRect());
-
- GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
- // Invalidation is still needed for invisible transformed content, because it
- // may end up composited (in SPv2 mode) and move on screen.
- EXPECT_TRUE(fixed_layer.NeedsRepaint());
- GetDocument().View()->UpdateAllLifecyclePhases();
-
- // The following ensures normal paint invalidation still works.
- transform.setAttribute(
- HTMLNames::styleAttr,
- "visibility: visible; transform: translate(20px, 30px)");
- GetDocument().View()->UpdateLifecycleToCompositingCleanPlusScrolling();
- EXPECT_FALSE(fixed_layer.SubtreeIsInvisible());
- GetDocument().View()->UpdateAllLifecyclePhases();
- fixed.setAttribute(HTMLNames::styleAttr, "top: 50px");
- GetDocument().View()->UpdateLifecycleToCompositingCleanPlusScrolling();
- EXPECT_TRUE(fixed_object.MayNeedPaintInvalidation());
- EXPECT_FALSE(fixed_layer.SubtreeIsInvisible());
- GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
- EXPECT_TRUE(fixed_layer.NeedsRepaint());
- GetDocument().View()->UpdateAllLifecyclePhases();
-}
-
-TEST_P(PaintInvalidationTest, DelayedFullPaintInvalidation) {
- EnableCompositing();
- SetBodyInnerHTML(R"HTML(
- <style>body { margin: 0 }</style>
- <div style='height: 4000px'></div>
- <div id='target' style='width: 100px; height: 100px; background: blue'>
- </div>
- )HTML");
-
- auto* target = GetLayoutObjectByElementId("target");
- target->SetShouldDoFullPaintInvalidationWithoutGeometryChange(
- PaintInvalidationReason::kDelayedFull);
- EXPECT_EQ(PaintInvalidationReason::kDelayedFull,
- target->FullPaintInvalidationReason());
- EXPECT_FALSE(target->NeedsPaintOffsetAndVisualRectUpdate());
-
- GetDocument().View()->SetTracksPaintInvalidations(true);
- GetDocument().View()->UpdateAllLifecyclePhases();
- if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
- EXPECT_FALSE(GetRasterInvalidationTracking()->HasInvalidations());
- EXPECT_EQ(PaintInvalidationReason::kDelayedFull,
- target->FullPaintInvalidationReason());
- EXPECT_FALSE(target->NeedsPaintOffsetAndVisualRectUpdate());
- GetDocument().View()->SetTracksPaintInvalidations(false);
-
- GetDocument().View()->SetTracksPaintInvalidations(true);
- // Scroll target into view.
- GetDocument().domWindow()->scrollTo(0, 4000);
- GetDocument().View()->UpdateAllLifecyclePhases();
- if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- const auto& raster_invalidations =
- GetRasterInvalidationTracking()->Invalidations();
- ASSERT_EQ(1u, raster_invalidations.size());
- EXPECT_EQ(PaintInvalidationReason::kNone,
- target->FullPaintInvalidationReason());
- EXPECT_EQ(IntRect(0, 4000, 100, 100), raster_invalidations[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kFull, raster_invalidations[0].reason);
- }
- EXPECT_FALSE(target->NeedsPaintOffsetAndVisualRectUpdate());
- GetDocument().View()->SetTracksPaintInvalidations(false);
-};
-
-TEST_P(PaintInvalidationTest, SVGHiddenContainer) {
- EnableCompositing();
- SetBodyInnerHTML(R"HTML(
- <svg style='position: absolute; top: 100px; left: 100px'>
- <mask id='mask'>
- <g transform='scale(2)'>
- <rect id='mask-rect' x='11' y='22' width='33' height='44'/>
- </g>
- </mask>
- <rect id='real-rect' x='55' y='66' width='7' height='8'
- mask='url(#mask)'/>
- </svg>
- )HTML");
-
- // mask_rect's visual rect is in coordinates of the mask.
- auto* mask_rect = GetLayoutObjectByElementId("mask-rect");
- EXPECT_EQ(LayoutRect(), mask_rect->FirstFragment().VisualRect());
-
- // real_rect's visual rect is in coordinates of its paint invalidation
- // container (the view).
- auto* real_rect = GetLayoutObjectByElementId("real-rect");
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(LayoutRect(55, 66, 7, 8),
- real_rect->FirstFragment().VisualRect());
- } else {
- EXPECT_EQ(LayoutRect(155, 166, 7, 8),
- real_rect->FirstFragment().VisualRect());
- }
-
- GetDocument().View()->SetTracksPaintInvalidations(true);
- ToElement(mask_rect->GetNode())->setAttribute("x", "20");
- GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
-
- EXPECT_EQ(PaintInvalidationReason::kFull,
- real_rect->GetPaintInvalidationReason());
- // mask_rect has PaintInvalidationReason::kFull because it is not cached by
- // any PaintController.
- EXPECT_EQ(PaintInvalidationReason::kFull,
- mask_rect->GetPaintInvalidationReason());
-
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- GetDocument().View()->UpdateAllLifecyclePhases();
-
- EXPECT_EQ(LayoutRect(), mask_rect->FirstFragment().VisualRect());
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(LayoutRect(55, 66, 7, 8),
- real_rect->FirstFragment().VisualRect());
- } else {
- EXPECT_EQ(LayoutRect(155, 166, 7, 8),
- real_rect->FirstFragment().VisualRect());
- }
-
- // Should invalidate raster for real_rect only.
- if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- const auto& raster_invalidations =
- GetRasterInvalidationTracking()->Invalidations();
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- // The first is for the rect itself, the second is for its mask.
- ASSERT_EQ(2u, raster_invalidations.size());
- EXPECT_EQ(IntRect(155, 166, 7, 8), raster_invalidations[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kFull, raster_invalidations[0].reason);
- EXPECT_EQ(IntRect(155, 166, 7, 8), raster_invalidations[1].rect);
- EXPECT_EQ(PaintInvalidationReason::kFull, raster_invalidations[1].reason);
- } else {
- ASSERT_EQ(1u, raster_invalidations.size());
- EXPECT_EQ(IntRect(155, 166, 7, 8), raster_invalidations[0].rect);
- EXPECT_EQ(PaintInvalidationReason::kFull, raster_invalidations[0].reason);
- }
- }
-
- GetDocument().View()->SetTracksPaintInvalidations(false);
-}
-
-TEST_P(PaintInvalidationTest, UpdateVisualRectWhenPrinting) {
- SetBodyInnerHTML(R"HTML(
- <style>
- * { margin: 0;}
- span {
- display: inline-block;
- width: 150px;
- height: 20px;
- background: rebeccapurple;
- }
- </style>
- <div><span id="a"></span><span id="b"></span><span id="c"></div>
- )HTML");
-
- auto* a = GetDocument().getElementById("a")->GetLayoutObject();
- EXPECT_EQ(LayoutRect(0, 0, 150, 20), a->FirstFragment().VisualRect());
- auto* b = GetDocument().getElementById("b")->GetLayoutObject();
- EXPECT_EQ(LayoutRect(150, 0, 150, 20), b->FirstFragment().VisualRect());
- auto* c = GetDocument().getElementById("c")->GetLayoutObject();
- EXPECT_EQ(LayoutRect(300, 0, 150, 20), c->FirstFragment().VisualRect());
-
- // Print the page with a width of 400px which will require wrapping 'c'.
- FloatSize page_size(400, 200);
- GetFrame().StartPrinting(page_size, page_size, 1);
- GetDocument().View()->UpdateLifecyclePhasesForPrinting();
-
- EXPECT_EQ(LayoutRect(0, 0, 150, 20), a->FirstFragment().VisualRect());
- EXPECT_EQ(LayoutRect(150, 0, 150, 20), b->FirstFragment().VisualRect());
- // 'c' should be on the next line.
- EXPECT_EQ(LayoutRect(0, 20, 150, 20), c->FirstFragment().VisualRect());
-
- GetFrame().EndPrinting();
- GetDocument().View()->UpdateLifecyclePhasesForPrinting();
-
- EXPECT_EQ(LayoutRect(0, 0, 150, 20), a->FirstFragment().VisualRect());
- EXPECT_EQ(LayoutRect(150, 0, 150, 20), b->FirstFragment().VisualRect());
- EXPECT_EQ(LayoutRect(300, 0, 150, 20), c->FirstFragment().VisualRect());
-};
-
-} // namespace
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_invalidator.cc b/chromium/third_party/blink/renderer/core/paint/paint_invalidator.cc
index 3c582ee139e..5ac372b76b0 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_invalidator.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_invalidator.cc
@@ -40,12 +40,7 @@ static LayoutRect SlowMapToVisualRectInAncestorSpace(
}
LayoutRect result(rect);
- if (object.IsLayoutView()) {
- ToLayoutView(object).MapToVisualRectInAncestorSpace(
- &ancestor, result, kInputIsInFrameCoordinates, kDefaultVisualRectFlags);
- } else {
- object.MapToVisualRectInAncestorSpace(&ancestor, result);
- }
+ object.MapToVisualRectInAncestorSpace(&ancestor, result);
return result;
}
@@ -92,13 +87,10 @@ void PaintInvalidator::ExcludeCompositedLayerSubpixelAccumulation(
-context.paint_invalidation_container->Layer()->SubpixelAccumulation())));
}
-// TODO(wangxianzhu): Combine this into
-// PaintInvalidator::mapLocalRectToBacking() when removing
-// PaintInvalidationState.
// This function is templatized to avoid FloatRect<->LayoutRect conversions
// which affect performance.
template <typename Rect, typename Point>
-LayoutRect PaintInvalidator::MapLocalRectToVisualRectInBacking(
+LayoutRect PaintInvalidator::MapLocalRectToVisualRect(
const LayoutObject& object,
const Rect& local_rect,
const PaintInvalidatorContext& context,
@@ -147,91 +139,21 @@ LayoutRect PaintInvalidator::MapLocalRectToVisualRectInBacking(
}
}
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- // In SPv175, visual rects are in the space of their local transform node.
- // For SVG, the input rect is in local SVG coordinates in which paint
- // offset doesn't apply.
- if (!is_svg_child)
- rect.MoveBy(Point(context.fragment_data->PaintOffset()));
- ExcludeCompositedLayerSubpixelAccumulation<Rect, Point>(object, context,
- rect);
- // Use EnclosingIntRect to ensure the final visual rect will cover the rect
- // in source coordinates no matter if the painting will snap to pixels.
- return LayoutRect(EnclosingIntRect(rect));
- }
-
- LayoutRect result;
- if (context.subtree_flags & PaintInvalidatorContext::kSubtreeSlowPathRect) {
- result = SlowMapToVisualRectInAncestorSpace(
- object, *context.paint_invalidation_container, rect);
- } else if (object == context.paint_invalidation_container) {
- result = LayoutRect(rect);
- } else {
- // For non-root SVG, the input rect is in local SVG coordinates in which
- // paint offset doesn't apply.
- if (!is_svg_child)
- rect.MoveBy(Point(context.fragment_data->PaintOffset()));
-
- auto container_contents_properties =
- context.paint_invalidation_container->FirstFragment()
- .ContentsProperties();
- DCHECK(
- !context.paint_invalidation_container->FirstFragment().NextFragment());
- if (context.tree_builder_context_->current.transform ==
- container_contents_properties.Transform() &&
- context.tree_builder_context_->current.clip ==
- container_contents_properties.Clip() &&
- context.tree_builder_context_->current_effect ==
- container_contents_properties.Effect()) {
- result = LayoutRect(rect);
- } else {
- // Use enclosingIntRect to ensure the final visual rect will cover the
- // rect in source coordinates no matter if the painting will use pixel
- // snapping, when transforms are applied. If there is no transform,
- // enclosingIntRect is applied in the last step of paint invalidation
- // (see CompositedLayerMapping::setContentsNeedDisplayInRect()).
- if (!is_svg_child && context.tree_builder_context_->current.transform !=
- container_contents_properties.Transform())
- rect = Rect(EnclosingIntRect(rect));
-
- PropertyTreeState current_tree_state(
- context.tree_builder_context_->current.transform,
- context.tree_builder_context_->current.clip,
- context.tree_builder_context_->current_effect);
-
- FloatClipRect float_rect((FloatRect(rect)));
-
- GeometryMapper::LocalToAncestorVisualRect(
- current_tree_state, container_contents_properties, float_rect);
- result = LayoutRect(float_rect.Rect());
- }
-
- // Convert the result to the paint invalidation container's contents space.
- // If the paint invalidation container has a transform node associated
- // with it (due to scroll or transform), then its PaintOffset
- // must be zero or equal to its subpixel accumulation, since in all
- // such cases we allocate a paint offset translation transform.
- result.MoveBy(
- -context.paint_invalidation_container->FirstFragment().PaintOffset());
- }
-
- if (!result.IsEmpty())
- result.Inflate(object.VisualRectOutsetForRasterEffects());
-
- PaintLayer::MapRectInPaintInvalidationContainerToBacking(
- *context.paint_invalidation_container, result);
-
- result.Move(object.ScrollAdjustmentForPaintInvalidation(
- *context.paint_invalidation_container));
-
- return result;
+ // Visual rects are in the space of their local transform node. For SVG, the
+ // input rect is in local SVG coordinates in which paint offset doesn't apply.
+ if (!is_svg_child)
+ rect.MoveBy(Point(context.fragment_data->PaintOffset()));
+ ExcludeCompositedLayerSubpixelAccumulation<Rect, Point>(object, context,
+ rect);
+ // Use EnclosingIntRect to ensure the final visual rect will cover the rect
+ // in source coordinates no matter if the painting will snap to pixels.
+ return LayoutRect(EnclosingIntRect(rect));
}
-void PaintInvalidatorContext::MapLocalRectToVisualRectInBacking(
+void PaintInvalidatorContext::MapLocalRectToVisualRect(
const LayoutObject& object,
LayoutRect& rect) const {
- rect = PaintInvalidator::MapLocalRectToVisualRectInBacking<LayoutRect,
- LayoutPoint>(
+ rect = PaintInvalidator::MapLocalRectToVisualRect<LayoutRect, LayoutPoint>(
object, rect, *this);
}
@@ -242,79 +164,43 @@ PaintInvalidatorContext::ParentContextAccessor::ParentContext() const {
: nullptr;
}
-LayoutRect PaintInvalidator::ComputeVisualRectInBacking(
+LayoutRect PaintInvalidator::ComputeVisualRect(
const LayoutObject& object,
const PaintInvalidatorContext& context) {
if (object.IsSVGChild()) {
FloatRect local_rect = SVGLayoutSupport::LocalVisualRect(object);
- return MapLocalRectToVisualRectInBacking<FloatRect, FloatPoint>(
- object, local_rect, context);
+ return MapLocalRectToVisualRect<FloatRect, FloatPoint>(object, local_rect,
+ context);
}
LayoutRect local_rect = object.LocalVisualRect();
- return MapLocalRectToVisualRectInBacking<LayoutRect, LayoutPoint>(
- object, local_rect, context);
+ return MapLocalRectToVisualRect<LayoutRect, LayoutPoint>(object, local_rect,
+ context);
}
-LayoutRect PaintInvalidator::ComputeVisualRectInBacking(
- const NGPaintFragment& fragment,
- const LayoutObject& object,
- const PaintInvalidatorContext& context) {
- const NGPhysicalFragment& physical_fragment = fragment.PhysicalFragment();
- LayoutRect local_rect =
- physical_fragment.VisualRectWithContents().ToLayoutRect();
- bool disable_flip = true;
- LayoutRect backing_rect =
- MapLocalRectToVisualRectInBacking<LayoutRect, LayoutPoint>(
- object, local_rect, context, disable_flip);
- if (!object.IsBox())
- backing_rect.Move(fragment.InlineOffsetToContainerBox().ToLayoutSize());
- return backing_rect;
+static LayoutRect ComputeFragmentLocalSelectionRect(
+ const NGPaintFragment& fragment) {
+ if (!fragment.PhysicalFragment().IsText())
+ return LayoutRect();
+ const FrameSelection& frame_selection =
+ fragment.GetLayoutObject()->GetFrame()->Selection();
+ const LayoutSelectionStatus status =
+ frame_selection.ComputeLayoutSelectionStatus(fragment);
+ if (status.start == status.end)
+ return LayoutRect();
+ return fragment.ComputeLocalSelectionRectForText(status).ToLayoutRect();
}
-LayoutPoint PaintInvalidator::ComputeLocationInBacking(
+LayoutRect PaintInvalidator::MapFragmentLocalRectToVisualRect(
+ const LayoutRect& local_rect,
const LayoutObject& object,
+ const NGPaintFragment& fragment,
const PaintInvalidatorContext& context) {
- // In SPv2, locationInBacking is in the space of their local transform node.
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return object.FirstFragment().PaintOffset();
-
- LayoutPoint point;
- if (object != context.paint_invalidation_container) {
- point.MoveBy(context.fragment_data->PaintOffset());
-
- const auto* container_transform =
- context.paint_invalidation_container->FirstFragment()
- .ContentsProperties()
- .Transform();
- if (context.tree_builder_context_->current.transform !=
- container_transform) {
- FloatRect rect = FloatRect(FloatPoint(point), FloatSize());
- GeometryMapper::SourceToDestinationRect(
- context.tree_builder_context_->current.transform, container_transform,
- rect);
- point = LayoutPoint(rect.Location());
- }
-
- // Convert the result to the paint invalidation container's contents space.
- // If the paint invalidation container has a transform node associated
- // with it (due to scroll or transform), then its PaintOffset
- // must be zero or equal to its subpixel accumulation, since in all
- // such cases we allocate a paint offset translation transform.
- point.MoveBy(
- -context.paint_invalidation_container->FirstFragment().PaintOffset());
- }
-
- if (context.paint_invalidation_container->Layer()->GroupedMapping()) {
- FloatPoint float_point(point);
- PaintLayer::MapPointInPaintInvalidationContainerToBacking(
- *context.paint_invalidation_container, float_point);
- point = LayoutPoint(float_point);
- }
-
- point.Move(object.ScrollAdjustmentForPaintInvalidation(
- *context.paint_invalidation_container));
-
- return point;
+ LayoutRect rect = local_rect;
+ if (!object.IsBox())
+ rect.Move(fragment.InlineOffsetToContainerBox().ToLayoutSize());
+ bool disable_flip = true;
+ return MapLocalRectToVisualRect<LayoutRect, LayoutPoint>(
+ object, rect, context, disable_flip);
}
void PaintInvalidator::UpdatePaintingLayer(const LayoutObject& object,
@@ -355,6 +241,12 @@ void PaintInvalidator::UpdatePaintingLayer(const LayoutObject& object,
|| (object.HasOverflowClip() &&
ToLayoutBox(object).GetScrollableArea()->HasOverflowControls())) {
context.painting_layer->SetNeedsPaintPhaseDescendantBlockBackgrounds();
+ } else if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()) {
+ // Hit testing rects for touch action paint in the background phase.
+ if (object.EffectiveWhitelistedTouchAction() !=
+ TouchAction::kTouchActionAuto) {
+ context.painting_layer->SetNeedsPaintPhaseDescendantBlockBackgrounds();
+ }
}
}
@@ -384,6 +276,9 @@ void PaintInvalidator::UpdatePaintInvalidationContainer(
// This is to exclude some objects (e.g. LayoutText) inheriting
// stacked style from parent but aren't actually stacked.
object.HasLayer() &&
+ !ToLayoutBoxModelObject(object)
+ .Layer()
+ ->IsReplacedNormalFlowStacking() &&
context.paint_invalidation_container !=
context.paint_invalidation_container_for_stacked_contents) {
// The current object is stacked, so we should use
@@ -430,23 +325,11 @@ void PaintInvalidator::UpdateVisualRect(const LayoutObject& object,
DCHECK(context.tree_builder_context_->current.paint_offset ==
fragment_data.PaintOffset());
- LayoutRect new_visual_rect = ComputeVisualRectInBacking(object, context);
- LayoutPoint new_location;
- if (object.IsBoxModelObject()) {
- new_location = ComputeLocationInBacking(object, context);
- // Location of empty visual rect doesn't affect paint invalidation. Set it
- // to newLocation to avoid saving the previous location separately in
- // ObjectPaintInvalidator.
- if (new_visual_rect.IsEmpty())
- new_visual_rect.SetLocation(new_location);
- } else {
- // Use visual rect location for non-LayoutBoxModelObject because it suffices
- // to check whether a visual rect changes for layout caused invalidation.
- new_location = new_visual_rect.Location();
- }
-
+ LayoutRect new_visual_rect = ComputeVisualRect(object, context);
+ // Make the empty visual rect more meaningful for debugging and testing.
+ if (new_visual_rect.IsEmpty())
+ new_visual_rect.SetLocation(fragment_data.PaintOffset());
fragment_data.SetVisualRect(new_visual_rect);
- fragment_data.SetLocationInBacking(new_location);
// For LayoutNG, update NGPaintFragments.
if (!RuntimeEnabledFeatures::LayoutNGEnabled())
@@ -468,9 +351,26 @@ void PaintInvalidator::UpdateVisualRect(const LayoutObject& object,
auto fragments = NGPaintFragment::InlineFragmentsFor(&object);
if (fragments.IsInLayoutNGInlineFormattingContext()) {
for (NGPaintFragment* fragment : fragments) {
- LayoutRect fragment_visual_rect =
- ComputeVisualRectInBacking(*fragment, object, context);
- fragment->SetVisualRect(fragment_visual_rect);
+ LayoutRect local_selection_rect =
+ ComputeFragmentLocalSelectionRect(*fragment);
+ LayoutRect local_visual_rect =
+ UnionRect(fragment->SelfInkOverflow(), local_selection_rect);
+ fragment->SetVisualRect(MapFragmentLocalRectToVisualRect(
+ local_visual_rect, object, *fragment, context));
+
+ LayoutRect selection_visual_rect = MapFragmentLocalRectToVisualRect(
+ local_selection_rect, object, *fragment, context);
+ const bool should_invalidate =
+ object.ShouldInvalidateSelection() ||
+ selection_visual_rect != fragment->SelectionVisualRect();
+ const bool rect_exists = !selection_visual_rect.IsEmpty() ||
+ !fragment->SelectionVisualRect().IsEmpty();
+ if (should_invalidate && rect_exists) {
+ context.painting_layer->SetNeedsRepaint();
+ ObjectPaintInvalidator(object).InvalidateDisplayItemClient(
+ *fragment, PaintInvalidationReason::kSelection);
+ fragment->SetSelectionVisualRect(selection_visual_rect);
+ }
}
}
}
@@ -509,9 +409,8 @@ static void InvalidateChromeClient(
auto* frame_view = paint_invalidation_container.GetFrameView();
DCHECK(!frame_view->GetFrame().OwnerLayoutObject());
- if (auto* client = frame_view->GetChromeClient()) {
- client->InvalidateRect(
- frame_view->ContentsToFrame(frame_view->VisibleContentRect()));
+ if (auto* client = ToChromeClient(frame_view->GetChromeClient())) {
+ client->InvalidateRect(IntRect(IntPoint(), frame_view->Size()));
}
}
@@ -568,7 +467,7 @@ void PaintInvalidator::InvalidatePaint(
UpdatePaintInvalidationContainer(object, context);
UpdateEmptyVisualRectFlag(object, context);
- if (!object.ShouldCheckForPaintInvalidation() && !context.subtree_flags)
+ if (!object.ShouldCheckForPaintInvalidation() && !context.NeedsSubtreeWalk())
return;
unsigned tree_builder_index = 0;
@@ -577,7 +476,6 @@ void PaintInvalidator::InvalidatePaint(
fragment_data;
fragment_data = fragment_data->NextFragment(), tree_builder_index++) {
context.old_visual_rect = fragment_data->VisualRect();
- context.old_location = fragment_data->LocationInBacking();
context.fragment_data = fragment_data;
DCHECK(!tree_builder_context ||
@@ -585,18 +483,19 @@ void PaintInvalidator::InvalidatePaint(
{
#if DCHECK_IS_ON()
- bool is_actually_needed =
+ context.tree_builder_context_actually_needed_ =
tree_builder_context && tree_builder_context->is_actually_needed;
- FindObjectVisualRectNeedingUpdateScope finder(
- object, *fragment_data, context, is_actually_needed);
-
- context.tree_builder_context_actually_needed_ = is_actually_needed;
+ FindObjectVisualRectNeedingUpdateScope finder(object, *fragment_data,
+ context);
#endif
if (tree_builder_context) {
context.tree_builder_context_ =
&tree_builder_context->fragments[tree_builder_index];
+ context.old_paint_offset =
+ context.tree_builder_context_->old_paint_offset;
} else {
context.tree_builder_context_ = nullptr;
+ context.old_paint_offset = fragment_data->PaintOffset();
}
UpdateVisualRect(object, *fragment_data, context);
@@ -620,12 +519,6 @@ void PaintInvalidator::InvalidatePaint(
default:
break;
}
-
- if (context.old_location != fragment_data->LocationInBacking() &&
- !context.painting_layer->SubtreeIsInvisible()) {
- context.subtree_flags |=
- PaintInvalidatorContext::kSubtreeInvalidationChecking;
- }
}
if (object.MayNeedPaintInvalidationSubtree()) {
@@ -650,11 +543,9 @@ void PaintInvalidator::InvalidatePaint(
// The object is under a frame for WebViewPlugin, SVG images etc. Need to
// inform the chrome client of the invalidation so that the client will
- // initiate painting of the contents. For SPv1 this is done by
- // ObjectPaintInvalidator::InvalidatePaintUsingContainer().
+ // initiate painting of the contents.
// TODO(wangxianzhu): Do we need this for SPv2?
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- !RuntimeEnabledFeatures::SlimmingPaintV2Enabled() &&
+ if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled() &&
!context.paint_invalidation_container->IsPaintInvalidationContainer() &&
object.GetPaintInvalidationReason() != PaintInvalidationReason::kNone)
InvalidateChromeClient(*context.paint_invalidation_container);
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_invalidator.h b/chromium/third_party/blink/renderer/core/paint/paint_invalidator.h
index fa6c5748537..7cb3e82dde0 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_invalidator.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_invalidator.h
@@ -14,6 +14,7 @@ namespace blink {
class NGPaintFragment;
class PrePaintTreeWalk;
+
struct CORE_EXPORT PaintInvalidatorContext {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
@@ -42,8 +43,7 @@ struct CORE_EXPORT PaintInvalidatorContext {
ParentContext()->paint_invalidation_container_for_stacked_contents),
painting_layer(ParentContext()->painting_layer) {}
- void MapLocalRectToVisualRectInBacking(const LayoutObject&,
- LayoutRect&) const;
+ void MapLocalRectToVisualRect(const LayoutObject&, LayoutRect&) const;
bool NeedsVisualRectUpdate(const LayoutObject& object) const {
#if DCHECK_IS_ON()
@@ -54,6 +54,14 @@ struct CORE_EXPORT PaintInvalidatorContext {
(subtree_flags & PaintInvalidatorContext::kSubtreeVisualRectUpdate);
}
+ bool NeedsSubtreeWalk() const {
+ return subtree_flags &
+ (kSubtreeInvalidationChecking | kSubtreeVisualRectUpdate |
+ kSubtreeFullInvalidation |
+ kSubtreeFullInvalidationForStackedContents |
+ kSubtreeSVGResourceChange);
+ }
+
const PaintInvalidatorContext* ParentContext() const {
return parent_context_accessor_.ParentContext();
}
@@ -64,6 +72,7 @@ struct CORE_EXPORT PaintInvalidatorContext {
ParentContextAccessor parent_context_accessor_;
public:
+ // When adding new subtree flags, ensure |NeedsSubtreeWalk| is updated.
enum SubtreeFlag {
kSubtreeInvalidationChecking = 1 << 0,
kSubtreeVisualRectUpdate = 1 << 1,
@@ -107,21 +116,9 @@ struct CORE_EXPORT PaintInvalidatorContext {
PaintLayer* painting_layer = nullptr;
- // Store the old visual rect in the paint invalidation backing's coordinates.
- // It does *not* account for composited scrolling.
- // See LayoutObject::AdjustVisualRectForCompositedScrolling().
+ // The previous VisualRect and PaintOffset of FragmentData.
LayoutRect old_visual_rect;
- // Use LayoutObject::VisualRect() to get the new visual rect.
-
- // This field and LayoutObject::LocationInBacking() store the old and new
- // origins of the object's local coordinates in the paint invalidation
- // backing's coordinates. They are used to detect layoutObject shifts that
- // force a full invalidation and invalidation check in subtree.
- // The points do *not* account for composited scrolling. See
- // LayoutObject::adjustVisualRectForCompositedScrolling().
- // This field will be removed for SPv175.
- LayoutPoint old_location;
- // Use LayoutObject::LocationInBacking() to get the new location.
+ LayoutPoint old_paint_offset;
const FragmentData* fragment_data;
@@ -133,7 +130,6 @@ struct CORE_EXPORT PaintInvalidatorContext {
#if DCHECK_IS_ON()
bool tree_builder_context_actually_needed_ = false;
- friend class FindVisualRectNeedingUpdateScope;
friend class FindVisualRectNeedingUpdateScopeBase;
mutable bool force_visual_rect_update_for_checking_ = false;
#endif
@@ -162,21 +158,18 @@ class PaintInvalidator {
const PaintInvalidatorContext&,
Rect&);
template <typename Rect, typename Point>
- static LayoutRect MapLocalRectToVisualRectInBacking(
- const LayoutObject&,
- const Rect&,
- const PaintInvalidatorContext&,
- bool disable_flip = false);
+ static LayoutRect MapLocalRectToVisualRect(const LayoutObject&,
+ const Rect&,
+ const PaintInvalidatorContext&,
+ bool disable_flip = false);
+ ALWAYS_INLINE LayoutRect ComputeVisualRect(const LayoutObject&,
+ const PaintInvalidatorContext&);
ALWAYS_INLINE LayoutRect
- ComputeVisualRectInBacking(const LayoutObject&,
- const PaintInvalidatorContext&);
- ALWAYS_INLINE LayoutRect
- ComputeVisualRectInBacking(const NGPaintFragment&,
- const LayoutObject&,
- const PaintInvalidatorContext&);
- ALWAYS_INLINE LayoutPoint
- ComputeLocationInBacking(const LayoutObject&, const PaintInvalidatorContext&);
+ MapFragmentLocalRectToVisualRect(const LayoutRect&,
+ const LayoutObject&,
+ const NGPaintFragment&,
+ const PaintInvalidatorContext&);
ALWAYS_INLINE void UpdatePaintingLayer(const LayoutObject&,
PaintInvalidatorContext&);
ALWAYS_INLINE void UpdatePaintInvalidationContainer(const LayoutObject&,
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 e537bf47792..c3c2671146b 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -47,6 +47,7 @@
#include <limits>
#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/pseudo_style_request.h"
#include "third_party/blink/renderer/core/css_property_names.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -78,6 +79,9 @@
#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer_painter.h"
+#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
+#include "third_party/blink/renderer/core/style/reference_clip_path_operation.h"
+#include "third_party/blink/renderer/core/style/shape_clip_path_operation.h"
#include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/geometry/float_point_3d.h"
@@ -102,15 +106,18 @@ static CompositingQueryMode g_compositing_query_mode =
kCompositingQueriesAreOnlyAllowedInCertainDocumentLifecyclePhases;
struct SameSizeAsPaintLayer : DisplayItemClient {
- int bit_fields;
+ // The bit fields may fit into the machine word of DisplayItemClient which
+ // has only 8-bit data.
+ unsigned bit_fields1 : 24;
+ unsigned bit_fields2;
void* pointers[11];
+#if DCHECK_IS_ON()
+ void* pointer;
+#endif
LayoutUnit layout_units[4];
IntSize size;
Persistent<PaintLayerScrollableArea> scrollable_area;
- struct {
- IntSize size;
- LayoutRect rect;
- } previous_paint_status;
+ LayoutRect previous_dirty_rect;
};
static_assert(sizeof(PaintLayer) == sizeof(SameSizeAsPaintLayer),
@@ -123,6 +130,7 @@ using namespace HTMLNames;
PaintLayerRareData::PaintLayerRareData()
: enclosing_pagination_layer(nullptr),
potential_compositing_reasons_from_style(CompositingReason::kNone),
+ potential_compositing_reasons_from_non_style(CompositingReason::kNone),
compositing_reasons(CompositingReason::kNone),
squashing_disallowed_reasons(SquashingDisallowedReason::kNone),
grouped_mapping(nullptr) {}
@@ -130,9 +138,7 @@ PaintLayerRareData::PaintLayerRareData()
PaintLayerRareData::~PaintLayerRareData() = default;
PaintLayer::PaintLayer(LayoutBoxModelObject& layout_object)
- : has_self_painting_layer_descendant_(false),
- has_self_painting_layer_descendant_dirty_(false),
- is_root_layer_(layout_object.IsLayoutView()),
+ : is_root_layer_(layout_object.IsLayoutView()),
has_visible_content_(false),
needs_descendant_dependent_flags_update_(true),
has_visible_descendant_(false),
@@ -159,9 +165,18 @@ PaintLayer::PaintLayer(LayoutBoxModelObject& layout_object)
previous_paint_phase_descendant_block_backgrounds_was_empty_(false),
has_descendant_with_clip_path_(false),
has_non_isolated_descendant_with_blend_mode_(false),
+ has_descendant_with_sticky_or_fixed_(false),
+ has_non_contained_absolute_position_descendant_(false),
self_painting_status_changed_(false),
filter_on_effect_node_dirty_(false),
is_under_svg_hidden_container_(false),
+ descendant_has_direct_or_scrolling_compositing_reason_(false),
+ needs_compositing_reasons_update_(true),
+ descendant_may_need_compositing_requirements_update_(false),
+ needs_compositing_layer_assignment_(false),
+ descendant_needs_compositing_layer_assignment_(false),
+ has_self_painting_layer_descendant_(false),
+ is_non_stacked_with_in_flow_stacked_descendant_(false),
layout_object_(layout_object),
parent_(nullptr),
previous_(nullptr),
@@ -170,9 +185,12 @@ PaintLayer::PaintLayer(LayoutBoxModelObject& layout_object)
last_(nullptr),
static_inline_position_(0),
static_block_position_(0),
- ancestor_overflow_layer_(nullptr) {
- UpdateStackingNode();
-
+ ancestor_overflow_layer_(nullptr)
+#if DCHECK_IS_ON()
+ ,
+ stacking_parent_(nullptr)
+#endif
+{
is_self_painting_layer_ = ShouldBeSelfPaintingLayer();
UpdateScrollableArea();
@@ -205,6 +223,13 @@ PaintLayer::~PaintLayer() {
if (scrollable_area_)
scrollable_area_->Dispose();
+
+#if DCHECK_IS_ON()
+ // stacking_parent_ should be cleared because DirtyStackingContextZOrderLists
+ // should have been called.
+ if (!GetLayoutObject().DocumentBeingDestroyed())
+ DCHECK(!stacking_parent_);
+#endif
}
String PaintLayer::DebugName() const {
@@ -228,14 +253,11 @@ void PaintLayer::ContentChanged(ContentChangeType change_type) {
DisableCompositingQueryAsserts disabler;
if (Compositor()) {
- if (change_type == kCanvasChanged) {
- Compositor()->SetNeedsCompositingUpdate(
- kCompositingUpdateAfterCompositingInputChange);
- }
+ if (change_type == kCanvasChanged)
+ SetNeedsCompositingInputsUpdate();
if (change_type == kCanvasContextChanged) {
- Compositor()->SetNeedsCompositingUpdate(
- kCompositingUpdateAfterCompositingInputChange);
+ SetNeedsCompositingInputsUpdate();
// Although we're missing test coverage, we need to call
// GraphicsLayer::SetContentsToCcLayer with the new cc::Layer for this
@@ -325,36 +347,6 @@ void PaintLayer::UpdateLayerPositionRecursive(
child->UpdateLayerPositionRecursive(behavior);
}
-void PaintLayer::UpdateHasSelfPaintingLayerDescendant() const {
- DCHECK(has_self_painting_layer_descendant_dirty_);
-
- has_self_painting_layer_descendant_ = false;
-
- for (PaintLayer* child = FirstChild(); child; child = child->NextSibling()) {
- if (child->IsSelfPaintingLayer() ||
- child->HasSelfPaintingLayerDescendant()) {
- has_self_painting_layer_descendant_ = true;
- break;
- }
- }
-
- has_self_painting_layer_descendant_dirty_ = false;
-}
-
-void PaintLayer::DirtyAncestorChainHasSelfPaintingLayerDescendantStatus() {
- for (PaintLayer* layer = this; layer; layer = layer->Parent()) {
- layer->has_self_painting_layer_descendant_dirty_ = true;
- // If we have reached a self-painting layer, we know our parent should have
- // a self-painting descendant in this case, there is no need to dirty our
- // ancestors further.
- if (layer->IsSelfPaintingLayer()) {
- DCHECK(!Parent() || Parent()->has_self_painting_layer_descendant_dirty_ ||
- Parent()->has_self_painting_layer_descendant_);
- break;
- }
- }
-}
-
bool PaintLayer::SticksToScroller() const {
if (GetLayoutObject().Style()->GetPosition() != EPosition::kSticky)
return false;
@@ -732,7 +724,7 @@ void PaintLayer::UpdateScrollingStateAfterCompositingChange() {
if (child->GetCompositingState() == kNotComposited) {
is_all_scrolling_content_composited_ = false;
return;
- } else if (!child->StackingNode()->IsStackingContext()) {
+ } else if (!child->GetLayoutObject().StyleRef().IsStackingContext()) {
// If the child is composited, but not a stacking context, it may paint
// negative z-index descendants into an ancestor's GraphicsLayer.
is_all_scrolling_content_composited_ = false;
@@ -748,23 +740,64 @@ void PaintLayer::UpdateDescendantDependentFlags() {
has_visible_descendant_ = false;
has_non_isolated_descendant_with_blend_mode_ = false;
has_descendant_with_clip_path_ = false;
+ has_descendant_with_sticky_or_fixed_ = false;
+ has_non_contained_absolute_position_descendant_ = false;
+ has_self_painting_layer_descendant_ = false;
+ is_non_stacked_with_in_flow_stacked_descendant_ = false;
+
+ bool can_contain_abs =
+ GetLayoutObject().CanContainAbsolutePositionObjects();
+
+ const ComputedStyle& style = GetLayoutObject().StyleRef();
+ bool needs_stacking_node = style.IsStackingContext();
+ bool is_stacked = style.IsStacked();
for (PaintLayer* child = FirstChild(); child;
child = child->NextSibling()) {
+ const ComputedStyle& child_style = child->GetLayoutObject().StyleRef();
+
child->UpdateDescendantDependentFlags();
if (child->has_visible_content_ || child->has_visible_descendant_)
has_visible_descendant_ = true;
has_non_isolated_descendant_with_blend_mode_ |=
- (!child->StackingNode()->IsStackingContext() &&
+ (!child->GetLayoutObject().StyleRef().IsStackingContext() &&
child->HasNonIsolatedDescendantWithBlendMode()) ||
child->GetLayoutObject().StyleRef().HasBlendMode();
has_descendant_with_clip_path_ |= child->HasDescendantWithClipPath() ||
child->GetLayoutObject().HasClipPath();
+
+ has_descendant_with_sticky_or_fixed_ |=
+ child->HasDescendantWithStickyOrFixed() ||
+ child_style.GetPosition() == EPosition::kSticky ||
+ child_style.GetPosition() == EPosition::kFixed;
+
+ if (!can_contain_abs) {
+ has_non_contained_absolute_position_descendant_ |=
+ (child->HasNonContainedAbsolutePositionDescendant() ||
+ child_style.GetPosition() == EPosition::kAbsolute);
+ }
+
+ needs_stacking_node = needs_stacking_node || !child_style.IsStacked();
+
+ has_self_painting_layer_descendant_ =
+ has_self_painting_layer_descendant_ ||
+ child->HasSelfPaintingLayerDescendant() ||
+ child->IsSelfPaintingLayer();
+
+ if (!is_stacked) {
+ if (child->IsNonStackedWithInFlowStackedDescendant())
+ is_non_stacked_with_in_flow_stacked_descendant_ = true;
+ else if (child_style.IsStacked() &&
+ !child->GetLayoutObject().IsOutOfFlowPositioned())
+ is_non_stacked_with_in_flow_stacked_descendant_ = true;
+ }
}
+ UpdateStackingNode(needs_stacking_node);
+
if (old_has_non_isolated_descendant_with_blend_mode !=
static_cast<bool>(has_non_isolated_descendant_with_blend_mode_))
GetLayoutObject().SetNeedsPaintPropertyUpdate();
@@ -817,21 +850,22 @@ void PaintLayer::UpdateDescendantDependentFlags() {
void PaintLayer::Update3DTransformedDescendantStatus() {
has3d_transformed_descendant_ = false;
- stacking_node_->UpdateZOrderLists();
+ if (!stacking_node_)
+ return;
// Transformed or preserve-3d descendants can only be in the z-order lists,
// not in the normal flow list, so we only need to check those.
PaintLayerStackingNodeIterator iterator(
*stacking_node_.get(), kPositiveZOrderChildren | kNegativeZOrderChildren);
- while (PaintLayerStackingNode* node = iterator.Next()) {
- const PaintLayer& child_layer = *node->Layer();
+ while (PaintLayer* child_layer = iterator.Next()) {
bool child_has3d = false;
// If the child lives in a 3d hierarchy, then the layer at the root of
// that hierarchy needs the m_has3DTransformedDescendant set.
- if (child_layer.Preserves3D() && (child_layer.Has3DTransform() ||
- child_layer.Has3DTransformedDescendant()))
+ if (child_layer->Preserves3D() &&
+ (child_layer->Has3DTransform() ||
+ child_layer->Has3DTransformedDescendant()))
child_has3d = true;
- else if (child_layer.Has3DTransform())
+ else if (child_layer->Has3DTransform())
child_has3d = true;
if (child_has3d) {
@@ -1022,10 +1056,12 @@ LayoutPoint PaintLayer::ComputeOffsetFromAncestor(
}
PaintLayer* PaintLayer::CompositingContainer() const {
- if (!StackingNode()->IsStacked())
+ if (IsReplacedNormalFlowStacking())
+ return Parent();
+ if (!GetLayoutObject().StyleRef().IsStacked())
return IsSelfPaintingLayer() ? Parent() : ContainingLayer();
if (PaintLayerStackingNode* ancestor_stacking_node =
- StackingNode()->AncestorStackingContextNode())
+ PaintLayerStackingNode::AncestorStackingContextNode(this))
return ancestor_stacking_node->Layer();
return nullptr;
}
@@ -1121,14 +1157,13 @@ void PaintLayer::UpdateAncestorDependentCompositingInputs(
needs_ancestor_dependent_compositing_inputs_update_ = false;
}
-void PaintLayer::DidUpdateCompositingInputs() {
+void PaintLayer::ClearChildNeedsCompositingInputsUpdate() {
DCHECK(!NeedsCompositingInputsUpdate());
child_needs_compositing_inputs_update_ = false;
- if (scrollable_area_)
- scrollable_area_->UpdateNeedsCompositedScrolling();
}
bool PaintLayer::HasNonIsolatedDescendantWithBlendMode() const {
+ DCHECK(!needs_descendant_dependent_flags_update_);
if (has_non_isolated_descendant_with_blend_mode_)
return true;
if (GetLayoutObject().IsSVGRoot())
@@ -1306,7 +1341,7 @@ void* PaintLayer::operator new(size_t sz) {
}
void PaintLayer::operator delete(void* ptr) {
- WTF::PartitionFree(ptr);
+ base::PartitionFree(ptr);
}
void PaintLayer::AddChild(PaintLayer* child, PaintLayer* before_child) {
@@ -1336,18 +1371,20 @@ void PaintLayer::AddChild(PaintLayer* child, PaintLayer* before_child) {
SetNeedsCompositingInputsUpdate();
+ const ComputedStyle& child_style = child->GetLayoutObject().StyleRef();
+
if (Compositor()) {
- if (!child->StackingNode()->IsStacked() &&
- !GetLayoutObject().DocumentBeingDestroyed())
+ if (!child_style.IsStacked() && !GetLayoutObject().DocumentBeingDestroyed())
Compositor()->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
}
- if (child->StackingNode()->IsStacked() || child->FirstChild()) {
+ if (child_style.IsStacked() || child->FirstChild()) {
// Dirty the z-order list in which we are contained. The
// ancestorStackingContextNode() can be null in the case where we're
// building up generated content layers. This is ok, since the lists will
// start off dirty in that case anyway.
- child->StackingNode()->DirtyStackingContextZOrderLists();
+ PaintLayerStackingNode::DirtyStackingContextZOrderLists(child);
+ MarkAncestorChainForDescendantDependentFlagsUpdate();
}
// Non-self-painting children paint into this layer, so the visible contents
@@ -1356,7 +1393,9 @@ void PaintLayer::AddChild(PaintLayer* child, PaintLayer* before_child) {
DirtyVisibleContentStatus();
MarkAncestorChainForDescendantDependentFlagsUpdate();
- DirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
+
+ // Need to force requirements update, due to change of stacking order.
+ SetNeedsCompositingRequirementsUpdate();
child->SetNeedsRepaint();
}
@@ -1374,19 +1413,17 @@ PaintLayer* PaintLayer::RemoveChild(PaintLayer* old_child) {
if (last_ == old_child)
last_ = old_child->PreviousSibling();
+ const ComputedStyle& old_child_style =
+ old_child->GetLayoutObject().StyleRef();
+
if (!GetLayoutObject().DocumentBeingDestroyed()) {
if (Compositor()) {
- if (!old_child->StackingNode()->IsStacked())
+ if (!old_child_style.IsStacked())
Compositor()->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
}
-
- if (old_child->StackingNode()->IsStacked() || old_child->FirstChild()) {
- // Dirty the z-order list in which we are contained. When called via the
- // reattachment process in removeOnlyThisLayer, the layer may already be
- // disconnected from the main layer tree, so we need to null-check the
- // |stackingContext| value.
- old_child->StackingNode()->DirtyStackingContextZOrderLists();
- }
+ // Dirty the z-order list in which we are contained.
+ PaintLayerStackingNode::DirtyStackingContextZOrderLists(old_child);
+ MarkAncestorChainForDescendantDependentFlagsUpdate();
}
if (GetLayoutObject().Style()->Visibility() != EVisibility::kVisible)
@@ -1400,8 +1437,6 @@ PaintLayer* PaintLayer::RemoveChild(PaintLayer* old_child) {
if (old_child->AncestorOverflowLayer())
old_child->RemoveAncestorOverflowLayer(old_child->AncestorOverflowLayer());
- DirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
-
if (old_child->has_visible_content_ || old_child->has_visible_descendant_)
MarkAncestorChainForDescendantDependentFlagsUpdate();
@@ -1416,25 +1451,31 @@ void PaintLayer::ClearClipRects(ClipRectsCacheSlot cache_slot) {
.ClearClipRectsIncludingDescendants(cache_slot);
}
-void PaintLayer::RemoveOnlyThisLayerAfterStyleChange() {
+void PaintLayer::RemoveOnlyThisLayerAfterStyleChange(
+ const ComputedStyle* old_style) {
if (!parent_)
return;
- // Destructing PaintLayer would cause CompositedLayerMapping and composited
- // layers to be destructed and detach from layer tree immediately. Layers
- // could have dangling scroll/clip parent if compositing update were omitted.
- if (LocalFrameView* frame_view = layout_object_.GetDocument().View())
- frame_view->SetNeedsForcedCompositingUpdate();
+ if (old_style && old_style->IsStacked()) {
+ PaintLayerStackingNode::DirtyStackingContextZOrderLists(this);
+ MarkAncestorChainForDescendantDependentFlagsUpdate();
+ }
bool did_set_paint_invalidation = false;
if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ // Destructing PaintLayer would cause CompositedLayerMapping and composited
+ // layers to be destructed and detach from layer tree immediately. Layers
+ // could have dangling scroll/clip parent if compositing update were
+ // omitted.
+ if (LocalFrameView* frame_view = layout_object_.GetDocument().View())
+ frame_view->SetNeedsForcedCompositingUpdate();
+
// We need the current compositing status.
DisableCompositingQueryAsserts disabler;
if (IsPaintInvalidationContainer()) {
// Our children will be reparented and contained by a new paint
// invalidation container, so need paint invalidation. CompositingUpdate
// can't see this layer (which has been removed) so won't do this for us.
- DisablePaintInvalidationStateAsserts disabler;
ObjectPaintInvalidator(GetLayoutObject())
.InvalidatePaintIncludingNonCompositingDescendants();
GetLayoutObject()
@@ -1498,8 +1539,7 @@ void PaintLayer::InsertOnlyThisLayerAfterStyleChange() {
GetLayoutObject().Parent()->ContainerForPaintInvalidation();
if (!previous_paint_invalidation_container.StyleRef().IsStackingContext()) {
ObjectPaintInvalidator(GetLayoutObject())
- .InvalidatePaintIncludingNonSelfPaintingLayerDescendants(
- previous_paint_invalidation_container);
+ .InvalidatePaintIncludingNonSelfPaintingLayerDescendants();
// Set needsRepaint along the original compositingContainer chain.
GetLayoutObject().Parent()->EnclosingLayer()->SetNeedsRepaint();
did_set_paint_invalidation = true;
@@ -1611,12 +1651,16 @@ void PaintLayer::DidUpdateScrollsOverflow() {
UpdateSelfPaintingLayer();
}
-void PaintLayer::UpdateStackingNode() {
- DCHECK(!stacking_node_);
- if (RequiresStackingNode())
- stacking_node_ = std::make_unique<PaintLayerStackingNode>(this);
- else
- stacking_node_ = nullptr;
+void PaintLayer::UpdateStackingNode(bool needs_stacking_node) {
+ if (needs_stacking_node != !!stacking_node_) {
+ if (needs_stacking_node)
+ stacking_node_ = std::make_unique<PaintLayerStackingNode>(this);
+ else
+ stacking_node_ = nullptr;
+ }
+
+ if (stacking_node_)
+ stacking_node_->UpdateZOrderLists();
}
bool PaintLayer::RequiresScrollableArea() const {
@@ -1653,7 +1697,7 @@ bool PaintLayer::HasOverflowControls() const {
void PaintLayer::AppendSingleFragmentIgnoringPagination(
PaintLayerFragments& fragments,
const PaintLayer* root_layer,
- const LayoutRect& dirty_rect,
+ const LayoutRect* dirty_rect,
OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior,
ShouldRespectOverflowClipType respect_overflow_clip,
const LayoutPoint* offset_from_root,
@@ -1692,7 +1736,7 @@ bool PaintLayer::ShouldFragmentCompositedBounds(
void PaintLayer::CollectFragments(
PaintLayerFragments& fragments,
const PaintLayer* root_layer,
- const LayoutRect& dirty_rect,
+ const LayoutRect* dirty_rect,
OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior,
ShouldRespectOverflowClipType respect_overflow_clip,
const LayoutPoint* offset_from_root,
@@ -1707,7 +1751,7 @@ void PaintLayer::CollectFragments(
// create fragments when ShouldFragmentCompositedBounds() is false, e.g. for
// fixed-position objects in paged media.
bool offset_from_root_can_be_used =
- !ShouldFragmentCompositedBounds(root_layer) &&
+ offset_from_root && !ShouldFragmentCompositedBounds(root_layer) &&
!GetLayoutObject().FirstFragment().NextFragment();
for (auto* fragment_data = &GetLayoutObject().FirstFragment(); fragment_data;
fragment_data = fragment_data->NextFragment()) {
@@ -1725,15 +1769,18 @@ void PaintLayer::CollectFragments(
}
}
-static inline LayoutRect FrameVisibleRect(LayoutObject& layout_object) {
- LocalFrameView* frame_view = layout_object.GetDocument().View();
- if (!frame_view)
- return LayoutRect();
-
- return LayoutRect(frame_view->VisibleContentRect());
-}
+PaintLayer::HitTestRecursionData::HitTestRecursionData(
+ const LayoutRect& rect_arg,
+ const HitTestLocation& location_arg,
+ const HitTestLocation& original_location_arg)
+ : rect(rect_arg),
+ location(location_arg),
+ original_location(original_location_arg),
+ intersects_location(location_arg.Intersects(rect_arg)) {}
-bool PaintLayer::HitTest(HitTestResult& result) {
+bool PaintLayer::HitTest(const HitTestLocation& hit_test_location,
+ HitTestResult& result,
+ const LayoutRect& hit_test_area) {
DCHECK(IsSelfPaintingLayer() || HasSelfPaintingLayerDescendant());
// LayoutView should make sure to update layout before entering hit testing
@@ -1741,19 +1788,11 @@ bool PaintLayer::HitTest(HitTestResult& result) {
DCHECK(!GetLayoutObject().GetDocument().GetLayoutView()->NeedsLayout());
const HitTestRequest& request = result.GetHitTestRequest();
- const HitTestLocation& hit_test_location = result.GetHitTestLocation();
-
- // Start with frameVisibleRect to ensure we include the scrollbars.
- LayoutRect hit_test_area = FrameVisibleRect(GetLayoutObject());
- if (request.IgnoreClipping()) {
- if (LocalFrameView* frame_view = GetLayoutObject().GetDocument().View()) {
- hit_test_area.Unite(frame_view->DocumentToAbsolute(
- LayoutRect(GetLayoutObject().View()->DocumentRect())));
- }
- }
- PaintLayer* inside_layer = HitTestLayer(this, nullptr, result, hit_test_area,
- hit_test_location, false);
+ HitTestRecursionData recursion_data(hit_test_area, hit_test_location,
+ hit_test_location);
+ PaintLayer* inside_layer =
+ HitTestLayer(this, nullptr, result, recursion_data, false);
if (!inside_layer && IsRootLayer()) {
bool fallback = false;
// If we didn't hit any layers but are still inside the document
@@ -1832,8 +1871,7 @@ static double ComputeZOffset(const HitTestingTransformState& transform_state) {
scoped_refptr<HitTestingTransformState> PaintLayer::CreateLocalTransformState(
PaintLayer* root_layer,
PaintLayer* container_layer,
- const LayoutRect& hit_test_rect,
- const HitTestLocation& hit_test_location,
+ const HitTestRecursionData& recursion_data,
const HitTestingTransformState* container_transform_state,
const LayoutPoint& translation_offset) const {
scoped_refptr<HitTestingTransformState> transform_state;
@@ -1847,10 +1885,10 @@ scoped_refptr<HitTestingTransformState> PaintLayer::CreateLocalTransformState(
} else {
// If this is the first time we need to make transform state, then base it
// off of hitTestLocation, which is relative to rootLayer.
- transform_state =
- HitTestingTransformState::Create(hit_test_location.TransformedPoint(),
- hit_test_location.TransformedRect(),
- FloatQuad(FloatRect(hit_test_rect)));
+ transform_state = HitTestingTransformState::Create(
+ recursion_data.location.TransformedPoint(),
+ recursion_data.location.TransformedRect(),
+ FloatQuad(FloatRect(recursion_data.rect)));
ConvertToLayerCoords(root_layer, offset);
}
offset.MoveBy(translation_offset);
@@ -1916,12 +1954,12 @@ PaintLayer* PaintLayer::HitTestLayer(
PaintLayer* root_layer,
PaintLayer* container_layer,
HitTestResult& result,
- const LayoutRect& hit_test_rect,
- const HitTestLocation& hit_test_location,
+ const HitTestRecursionData& recursion_data,
bool applied_transform,
const HitTestingTransformState* transform_state,
double* z_offset) {
- DCHECK_GE(GetLayoutObject().GetDocument().Lifecycle().GetState(),
+ const LayoutObject& layout_object = GetLayoutObject();
+ DCHECK_GE(layout_object.GetDocument().Lifecycle().GetState(),
DocumentLifecycle::kCompositingClean);
if (!IsSelfPaintingLayer() && !HasSelfPaintingLayerDescendant())
@@ -1935,14 +1973,14 @@ PaintLayer* PaintLayer::HitTestLayer(
// LayoutSVGForeignObject::NodeAtFloatPoint (because
// IsReplacedNormalFlowStacking() true for LayoutSVGForeignObject),
// where the hit_test_rect has already been transformed to local coordinates.
- bool use_transform = Transform() && !GetLayoutObject().IsSVGForeignObject();
+ bool use_transform = Transform() && !layout_object.IsSVGForeignObject();
// Apply a transform if we have one.
if (use_transform && !applied_transform) {
if (EnclosingPaginationLayer()) {
return HitTestTransformedLayerInFragments(
- root_layer, container_layer, result, hit_test_rect, hit_test_location,
- transform_state, z_offset, clip_behavior);
+ root_layer, container_layer, result, recursion_data, transform_state,
+ z_offset, clip_behavior);
}
// Make sure the parent's clip rects have been calculated.
@@ -1955,16 +1993,17 @@ PaintLayer* PaintLayer::HitTestLayer(
clip_behavior),
clip_rect);
// Go ahead and test the enclosing clip now.
- if (!clip_rect.Intersects(hit_test_location))
+ if (!clip_rect.Intersects(recursion_data.location))
return nullptr;
}
return HitTestLayerByApplyingTransform(root_layer, container_layer, result,
- hit_test_rect, hit_test_location,
- transform_state, z_offset);
+ recursion_data, transform_state,
+ z_offset);
}
- if (HitTestClippedOutByClipPath(root_layer, hit_test_location))
+ if (layout_object.HasClipPath() &&
+ HitTestClippedOutByClipPath(root_layer, recursion_data.location))
return nullptr;
// The natural thing would be to keep HitTestingTransformState on the stack,
@@ -1980,15 +2019,13 @@ PaintLayer* PaintLayer::HitTestLayer(
Preserves3D()) {
// We need transform state for the first time, or to offset the container
// state, so create it here.
- local_transform_state =
- CreateLocalTransformState(root_layer, container_layer, hit_test_rect,
- hit_test_location, transform_state);
+ local_transform_state = CreateLocalTransformState(
+ root_layer, container_layer, recursion_data, transform_state);
}
// Check for hit test on backface if backface-visibility is 'hidden'
- if (local_transform_state &&
- GetLayoutObject().Style()->BackfaceVisibility() ==
- EBackfaceVisibility::kHidden) {
+ if (local_transform_state && layout_object.StyleRef().BackfaceVisibility() ==
+ EBackfaceVisibility::kHidden) {
TransformationMatrix inverted_matrix =
local_transform_state->accumulated_transform_.Inverse();
// If the z-vector of the matrix is negative, the back is facing towards the
@@ -2033,10 +2070,9 @@ PaintLayer* PaintLayer::HitTestLayer(
// Begin by walking our list of positive layers from highest z-index down to
// the lowest z-index.
PaintLayer* hit_layer = HitTestChildren(
- kPositiveZOrderChildren, root_layer, result, hit_test_rect,
- hit_test_location, local_transform_state.get(),
- z_offset_for_descendants_ptr, z_offset, unflattened_transform_state.get(),
- depth_sort_descendants);
+ kPositiveZOrderChildren, root_layer, result, recursion_data,
+ local_transform_state.get(), z_offset_for_descendants_ptr, z_offset,
+ unflattened_transform_state.get(), depth_sort_descendants);
if (hit_layer) {
if (!depth_sort_descendants)
return hit_layer;
@@ -2045,7 +2081,7 @@ PaintLayer* PaintLayer::HitTestLayer(
// Now check our overflow objects.
hit_layer = HitTestChildren(
- kNormalFlowChildren, root_layer, result, hit_test_rect, hit_test_location,
+ kNormalFlowChildren, root_layer, result, recursion_data,
local_transform_state.get(), z_offset_for_descendants_ptr, z_offset,
unflattened_transform_state.get(), depth_sort_descendants);
if (hit_layer) {
@@ -2056,82 +2092,86 @@ PaintLayer* PaintLayer::HitTestLayer(
// Collect the fragments. This will compute the clip rectangles for each layer
// fragment.
- PaintLayerFragments layer_fragments;
- if (applied_transform) {
- DCHECK(root_layer == this);
- LayoutPoint offset;
- AppendSingleFragmentIgnoringPagination(
- layer_fragments, root_layer, hit_test_rect,
- kExcludeOverlayScrollbarSizeForHitTesting, clip_behavior, &offset);
- } else {
- CollectFragments(layer_fragments, root_layer, hit_test_rect,
- kExcludeOverlayScrollbarSizeForHitTesting, clip_behavior);
- }
-
- if (scrollable_area_ && scrollable_area_->HitTestResizerInFragments(
- layer_fragments, hit_test_location)) {
- GetLayoutObject().UpdateHitTestResult(result, hit_test_location.Point());
- return this;
- }
-
- LayoutPoint offset = -LayoutBoxLocation();
+ base::Optional<PaintLayerFragments> layer_fragments;
+ LayoutPoint offset;
+ if (recursion_data.intersects_location) {
+ layer_fragments.emplace();
+ if (applied_transform) {
+ DCHECK(root_layer == this);
+ LayoutPoint ignored;
+ AppendSingleFragmentIgnoringPagination(
+ *layer_fragments, root_layer, nullptr,
+ kExcludeOverlayScrollbarSizeForHitTesting, clip_behavior, &ignored);
+ } else {
+ CollectFragments(*layer_fragments, root_layer, nullptr,
+ kExcludeOverlayScrollbarSizeForHitTesting,
+ clip_behavior);
+ }
- // Next we want to see if the mouse pos is inside the child LayoutObjects of
- // the layer. Check every fragment in reverse order.
- if (IsSelfPaintingLayer()) {
- // Hit test with a temporary HitTestResult, because we only want to commit
- // to 'result' if we know we're frontmost.
- HitTestResult temp_result(result.GetHitTestRequest(),
- result.GetHitTestLocation());
- bool inside_fragment_foreground_rect = false;
+ if (scrollable_area_ && scrollable_area_->HitTestResizerInFragments(
+ *layer_fragments, recursion_data.location)) {
+ layout_object.UpdateHitTestResult(result,
+ recursion_data.location.Point());
+ return this;
+ }
- if (HitTestContentsForFragments(layer_fragments, offset, temp_result,
- hit_test_location, kHitTestDescendants,
- inside_fragment_foreground_rect) &&
- IsHitCandidate(this, false, z_offset_for_contents_ptr,
- unflattened_transform_state.get())) {
- if (result.GetHitTestRequest().ListBased())
+ // Next we want to see if the mouse pos is inside the child LayoutObjects of
+ // the layer. Check every fragment in reverse order.
+ if (IsSelfPaintingLayer()) {
+ offset = -LayoutBoxLocation();
+ // Hit test with a temporary HitTestResult, because we only want to commit
+ // to 'result' if we know we're frontmost.
+ HitTestResult temp_result(result.GetHitTestRequest(),
+ recursion_data.original_location);
+ bool inside_fragment_foreground_rect = false;
+
+ if (HitTestContentsForFragments(
+ *layer_fragments, offset, temp_result, recursion_data.location,
+ kHitTestDescendants, inside_fragment_foreground_rect) &&
+ IsHitCandidate(this, false, z_offset_for_contents_ptr,
+ unflattened_transform_state.get())) {
+ if (result.GetHitTestRequest().ListBased())
+ result.Append(temp_result);
+ else
+ result = temp_result;
+ if (!depth_sort_descendants)
+ return this;
+ // Foreground can depth-sort with descendant layers, so keep this as a
+ // candidate.
+ candidate_layer = this;
+ } else if (inside_fragment_foreground_rect &&
+ result.GetHitTestRequest().ListBased()) {
result.Append(temp_result);
- else
- result = temp_result;
- if (!depth_sort_descendants)
- return this;
- // Foreground can depth-sort with descendant layers, so keep this as a
- // candidate.
- candidate_layer = this;
- } else if (inside_fragment_foreground_rect &&
- result.GetHitTestRequest().ListBased()) {
- result.Append(temp_result);
+ }
}
}
// Now check our negative z-index children.
hit_layer = HitTestChildren(
- kNegativeZOrderChildren, root_layer, result, hit_test_rect,
- hit_test_location, local_transform_state.get(),
- z_offset_for_descendants_ptr, z_offset, unflattened_transform_state.get(),
- depth_sort_descendants);
+ kNegativeZOrderChildren, root_layer, result, recursion_data,
+ local_transform_state.get(), z_offset_for_descendants_ptr, z_offset,
+ unflattened_transform_state.get(), depth_sort_descendants);
if (hit_layer) {
if (!depth_sort_descendants)
return hit_layer;
candidate_layer = hit_layer;
}
- // If we found a layer, return. Child layers, and foreground always render in
- // front of background.
+ // If we found a layer, return. Child layers, and foreground always render
+ // in front of background.
if (candidate_layer)
return candidate_layer;
- if (IsSelfPaintingLayer()) {
+ if (recursion_data.intersects_location && IsSelfPaintingLayer()) {
HitTestResult temp_result(result.GetHitTestRequest(),
- result.GetHitTestLocation());
+ recursion_data.original_location);
bool inside_fragment_background_rect = false;
- if (HitTestContentsForFragments(layer_fragments, offset, temp_result,
- hit_test_location, kHitTestSelf,
+ if (HitTestContentsForFragments(*layer_fragments, offset, temp_result,
+ recursion_data.location, kHitTestSelf,
inside_fragment_background_rect) &&
IsHitCandidate(this, false, z_offset_for_contents_ptr,
unflattened_transform_state.get())) {
- if (result.IsRectBasedTest())
+ if (recursion_data.original_location.IsRectBasedTest())
result.Append(temp_result);
else
result = temp_result;
@@ -2177,8 +2217,7 @@ PaintLayer* PaintLayer::HitTestTransformedLayerInFragments(
PaintLayer* root_layer,
PaintLayer* container_layer,
HitTestResult& result,
- const LayoutRect& hit_test_rect,
- const HitTestLocation& hit_test_location,
+ const HitTestRecursionData& recursion_data,
const HitTestingTransformState* transform_state,
double* z_offset,
ShouldRespectOverflowClipType clip_behavior) {
@@ -2186,7 +2225,7 @@ PaintLayer* PaintLayer::HitTestTransformedLayerInFragments(
// FIXME: We're missing a sub-pixel offset here crbug.com/348728
EnclosingPaginationLayer()->CollectFragments(
- enclosing_pagination_fragments, root_layer, hit_test_rect,
+ enclosing_pagination_fragments, root_layer, nullptr,
kExcludeOverlayScrollbarSizeForHitTesting, clip_behavior, nullptr,
LayoutSize());
@@ -2194,12 +2233,12 @@ PaintLayer* PaintLayer::HitTestTransformedLayerInFragments(
// Apply the page/column clip for this fragment, as well as any clips
// established by layers in between us and the enclosing pagination layer.
LayoutRect clip_rect = fragment.background_rect.Rect();
- if (!hit_test_location.Intersects(clip_rect))
+ if (!recursion_data.location.Intersects(clip_rect))
continue;
PaintLayer* hit_layer = HitTestLayerByApplyingTransform(
- root_layer, container_layer, result, hit_test_rect, hit_test_location,
- transform_state, z_offset, fragment.pagination_offset);
+ root_layer, container_layer, result, recursion_data, transform_state,
+ z_offset, fragment.pagination_offset);
if (hit_layer)
return hit_layer;
}
@@ -2211,16 +2250,14 @@ PaintLayer* PaintLayer::HitTestLayerByApplyingTransform(
PaintLayer* root_layer,
PaintLayer* container_layer,
HitTestResult& result,
- const LayoutRect& hit_test_rect,
- const HitTestLocation& hit_test_location,
+ const HitTestRecursionData& recursion_data,
const HitTestingTransformState* transform_state,
double* z_offset,
const LayoutPoint& translation_offset) {
// Create a transform state to accumulate this transform.
scoped_refptr<HitTestingTransformState> new_transform_state =
- CreateLocalTransformState(root_layer, container_layer, hit_test_rect,
- hit_test_location, transform_state,
- translation_offset);
+ CreateLocalTransformState(root_layer, container_layer, recursion_data,
+ transform_state, translation_offset);
// If the transform can't be inverted, then don't hit test this layer at all.
if (!new_transform_state->accumulated_transform_.IsInvertible())
@@ -2235,17 +2272,18 @@ PaintLayer* PaintLayer::HitTestLayerByApplyingTransform(
// been flattened (losing z) by our container.
FloatPoint local_point = new_transform_state->MappedPoint();
FloatQuad local_point_quad = new_transform_state->MappedQuad();
- LayoutRect local_hit_test_rect = new_transform_state->BoundsOfMappedArea();
- HitTestLocation new_hit_test_location;
- if (hit_test_location.IsRectBasedTest())
- new_hit_test_location = HitTestLocation(local_point, local_point_quad);
+ LayoutRect bounds_of_mapped_area = new_transform_state->BoundsOfMappedArea();
+ base::Optional<HitTestLocation> new_location;
+ if (recursion_data.location.IsRectBasedTest())
+ new_location.emplace(local_point, local_point_quad);
else
- new_hit_test_location = HitTestLocation(local_point);
+ new_location.emplace(local_point);
+ HitTestRecursionData new_recursion_data(bounds_of_mapped_area, *new_location,
+ recursion_data.original_location);
// Now do a hit test with the root layer shifted to be us.
- return HitTestLayer(this, container_layer, result, local_hit_test_rect,
- new_hit_test_location, true, new_transform_state.get(),
- z_offset);
+ return HitTestLayer(this, container_layer, result, new_recursion_data, true,
+ new_transform_state.get(), z_offset);
}
bool PaintLayer::HitTestContents(HitTestResult& result,
@@ -2288,20 +2326,38 @@ bool PaintLayer::HitTestContents(HitTestResult& result,
return true;
}
-bool PaintLayer::IsReplacedNormalFlowStacking() {
- if (!GetLayoutObject().IsSVGForeignObject())
- return false;
- if (!GetLayoutObject().StyleRef().HasAutoZIndex())
- return false;
- return true;
+bool PaintLayer::IsReplacedNormalFlowStacking() const {
+ return GetLayoutObject().IsSVGForeignObject();
+}
+
+void PaintLayer::SetNeedsCompositingLayerAssignment() {
+ needs_compositing_layer_assignment_ = true;
+
+ for (PaintLayer* curr = CompositingContainer();
+ curr && !curr->StackingDescendantNeedsCompositingLayerAssignment();
+ curr = curr->CompositingContainer()) {
+ curr->descendant_needs_compositing_layer_assignment_ = true;
+ }
+}
+
+void PaintLayer::ClearNeedsCompositingLayerAssignment() {
+ needs_compositing_layer_assignment_ = false;
+ descendant_needs_compositing_layer_assignment_ = false;
+}
+
+void PaintLayer::SetNeedsCompositingRequirementsUpdate() {
+ for (PaintLayer* curr = this;
+ curr && !curr->DescendantMayNeedCompositingRequirementsUpdate();
+ curr = curr->Parent()) {
+ curr->descendant_may_need_compositing_requirements_update_ = true;
+ }
}
PaintLayer* PaintLayer::HitTestChildren(
ChildrenIteration childrento_visit,
PaintLayer* root_layer,
HitTestResult& result,
- const LayoutRect& hit_test_rect,
- const HitTestLocation& hit_test_location,
+ const HitTestRecursionData& recursion_data,
const HitTestingTransformState* transform_state,
double* z_offset_for_descendants,
double* z_offset,
@@ -2310,15 +2366,16 @@ PaintLayer* PaintLayer::HitTestChildren(
if (!HasSelfPaintingLayerDescendant())
return nullptr;
+ if (!stacking_node_)
+ return nullptr;
+
const LayoutObject* stop_node = result.GetHitTestRequest().GetStopNode();
PaintLayer* stop_layer = stop_node ? stop_node->PaintingLayer() : nullptr;
PaintLayer* result_layer = nullptr;
PaintLayerStackingNodeReverseIterator iterator(*stacking_node_,
childrento_visit);
- while (PaintLayerStackingNode* child = iterator.Next()) {
- PaintLayer* child_layer = child->Layer();
-
+ while (PaintLayer* child_layer = iterator.Next()) {
if (child_layer->IsReplacedNormalFlowStacking())
continue;
@@ -2331,14 +2388,15 @@ PaintLayer* PaintLayer::HitTestChildren(
PaintLayer* hit_layer = nullptr;
HitTestResult temp_result(result.GetHitTestRequest(),
- result.GetHitTestLocation());
+ recursion_data.original_location);
hit_layer = child_layer->HitTestLayer(
- root_layer, this, temp_result, hit_test_rect, hit_test_location, false,
- transform_state, z_offset_for_descendants);
+ root_layer, this, temp_result, recursion_data, false, transform_state,
+ z_offset_for_descendants);
// If it is a list-based test, we can safely append the temporary result
// since it might had hit nodes but not necesserily had hitLayer set.
- DCHECK(!result.IsRectBasedTest() || result.GetHitTestRequest().ListBased());
+ DCHECK(!recursion_data.original_location.IsRectBasedTest() ||
+ result.GetHitTestRequest().ListBased());
if (result.GetHitTestRequest().ListBased())
result.Append(temp_result);
@@ -2371,8 +2429,7 @@ FloatRect PaintLayer::FilterReferenceBox(const FilterOperations& filter,
bool PaintLayer::HitTestClippedOutByClipPath(
PaintLayer* root_layer,
const HitTestLocation& hit_test_location) const {
- if (!GetLayoutObject().HasClipPath())
- return false;
+ DCHECK(GetLayoutObject().HasClipPath());
DCHECK(IsSelfPaintingLayer());
DCHECK(root_layer);
@@ -2509,7 +2566,10 @@ void PaintLayer::ExpandRectForStackingChildren(
const PaintLayer& composited_layer,
LayoutRect& result,
PaintLayer::CalculateBoundsOptions options) const {
- DCHECK(StackingNode()->IsStackingContext() ||
+ if (!StackingNode())
+ return;
+
+ DCHECK(GetLayoutObject().StyleRef().IsStackingContext() ||
!StackingNode()->HasPositiveZOrderList());
#if DCHECK_IS_ON()
@@ -2518,7 +2578,7 @@ void PaintLayer::ExpandRectForStackingChildren(
#endif
PaintLayerStackingNodeIterator iterator(*StackingNode(), kAllChildren);
- while (PaintLayerStackingNode* node = iterator.Next()) {
+ while (PaintLayer* child_layer = iterator.Next()) {
// Here we exclude both directly composited layers and squashing layers
// because those Layers don't paint into the graphics layer
// for this Layer. For example, the bounds of squashed Layers
@@ -2526,9 +2586,9 @@ void PaintLayer::ExpandRectForStackingChildren(
// GraphicsLayer.
if (options != PaintLayer::CalculateBoundsOptions::
kIncludeTransformsAndCompositedChildLayers &&
- node->Layer()->GetCompositingState() != kNotComposited)
+ child_layer->GetCompositingState() != kNotComposited)
continue;
- result.Unite(node->Layer()->BoundingBoxForCompositingInternal(
+ result.Unite(child_layer->BoundingBoxForCompositingInternal(
composited_layer, this, options));
}
}
@@ -2537,9 +2597,6 @@ LayoutRect PaintLayer::PhysicalBoundingBoxIncludingStackingChildren(
const LayoutPoint& offset_from_root,
CalculateBoundsOptions options) const {
LayoutRect result = PhysicalBoundingBox(LayoutPoint());
-
- const_cast<PaintLayer*>(this)->StackingNode()->UpdateLayerListsIfNeeded();
-
ExpandRectForStackingChildren(*this, result, options);
result.MoveBy(offset_from_root);
@@ -2570,7 +2627,7 @@ LayoutRect PaintLayer::BoundingBoxForCompositingInternal(
// and the document's layout overflow rect.
IntRect result = IntRect();
if (LocalFrameView* frame_view = GetLayoutObject().GetFrameView())
- result = IntRect(IntPoint(), frame_view->VisibleContentSize());
+ result = IntRect(IntPoint(), frame_view->Size());
return LayoutRect(result);
}
@@ -2581,8 +2638,6 @@ LayoutRect PaintLayer::BoundingBoxForCompositingInternal(
if (GetLayoutObject().IsLayoutFlowThread())
return LayoutRect();
- const_cast<PaintLayer*>(this)->StackingNode()->UpdateLayerListsIfNeeded();
-
// If there is a clip applied by an ancestor to this PaintLayer but below or
// equal to |ancestorLayer|, apply that clip.
LayoutRect result = Clipper(PaintLayer::kDoNotUseGeometryMapper)
@@ -2677,9 +2732,8 @@ BackgroundPaintLocation PaintLayer::GetBackgroundPaintLocation(
else
location = GetLayoutObject().GetBackgroundPaintLocation(reasons);
}
- if (!IsRootLayer()) {
- stacking_node_->UpdateLayerListsIfNeeded();
- if (stacking_node_->HasNegativeZOrderList())
+ if (!IsRootLayer() && stacking_node_) {
+ if (StackingNode()->HasNegativeZOrderList())
location = kBackgroundPaintInGraphicsLayer;
}
return location;
@@ -2741,22 +2795,8 @@ void PaintLayer::SetGroupedMapping(CompositedLayerMapping* grouped_mapping,
grouped_mapping->SetNeedsGraphicsLayerUpdate(kGraphicsLayerUpdateSubtree);
}
-bool PaintLayer::MaskBlendingAppliedByCompositor(
- const PaintInfo& paint_info) const {
- DCHECK(layout_object_.HasMask());
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return true;
-
- if (paint_info.GetGlobalPaintFlags() & kGlobalPaintFlattenCompositingLayers)
- return false;
-
- return rare_data_ && rare_data_->composited_layer_mapping &&
- rare_data_->composited_layer_mapping->HasMaskLayer();
-}
-
-bool PaintLayer::HasCompositedClippingMask() const {
- return rare_data_ && rare_data_->composited_layer_mapping &&
- rare_data_->composited_layer_mapping->HasChildClippingMaskLayer();
+bool PaintLayer::NeedsCompositedScrolling() const {
+ return scrollable_area_ && scrollable_area_->NeedsCompositedScrolling();
}
bool PaintLayer::PaintsWithTransform(
@@ -2780,13 +2820,12 @@ bool PaintLayer::SupportsSubsequenceCaching() const {
if (EnclosingPaginationLayer())
return false;
- // SVG documents paint atomically.
- if (GetLayoutObject().IsSVGRoot() &&
- GetLayoutObject().GetDocument().IsSVGDocument())
+ // SVG paints atomically.
+ if (GetLayoutObject().IsSVGRoot())
return true;
// Create subsequence for only stacking contexts whose painting are atomic.
- return StackingNode()->IsStackingContext();
+ return GetLayoutObject().StyleRef().IsStackingContext();
}
ScrollingCoordinator* PaintLayer::GetScrollingCoordinator() {
@@ -2829,13 +2868,6 @@ bool PaintLayer::BackgroundIsKnownToBeOpaqueInRect(
GetCompositingState() != kPaintsIntoOwnBacking)
return false;
- // This function should not be called when layer-lists are dirty.
- // TODO(schenney) This check never hits in layout tests or most platforms, but
- // does hit in PopupBlockerBrowserTest.AllowPopupThroughContentSetting on
- // Win 7 Test Builder.
- if (stacking_node_->ZOrderListsDirty())
- return false;
-
// FIXME: We currently only check the immediate layoutObject,
// which will miss many cases where additional layout objects paint
// into this layer.
@@ -2856,11 +2888,13 @@ bool PaintLayer::BackgroundIsKnownToBeOpaqueInRect(
bool PaintLayer::ChildBackgroundIsKnownToBeOpaqueInRect(
const LayoutRect& local_rect) const {
+ if (!stacking_node_)
+ return false;
+
PaintLayerStackingNodeReverseIterator reverse_iterator(
*stacking_node_,
kPositiveZOrderChildren | kNormalFlowChildren | kNegativeZOrderChildren);
- while (PaintLayerStackingNode* child = reverse_iterator.Next()) {
- const PaintLayer* child_layer = child->Layer();
+ while (PaintLayer* child_layer = reverse_iterator.Next()) {
// Stop at composited paint boundaries and non-self-painting layers.
if (child_layer->IsPaintInvalidationContainer())
continue;
@@ -2880,14 +2914,12 @@ bool PaintLayer::ChildBackgroundIsKnownToBeOpaqueInRect(
}
bool PaintLayer::ShouldBeSelfPaintingLayer() const {
- if (GetLayoutObject().IsLayoutEmbeddedContent() &&
- ToLayoutEmbeddedContent(GetLayoutObject())
- .RequiresAcceleratedCompositing())
- return true;
-
+ // TODO(crbug.com/839341): Remove ScrollTimeline check once we support
+ // main-thread AnimationWorklet and don't need to promote the scroll-source.
return GetLayoutObject().LayerTypeRequired() == kNormalPaintLayer ||
(scrollable_area_ && scrollable_area_->HasOverlayScrollbars()) ||
- ScrollsOverflow();
+ ScrollsOverflow() ||
+ ScrollTimeline::HasActiveScrollTimeline(GetLayoutObject().GetNode());
}
void PaintLayer::UpdateSelfPaintingLayer() {
@@ -2903,7 +2935,7 @@ void PaintLayer::UpdateSelfPaintingLayer() {
SetNeedsRepaint();
if (PaintLayer* parent = Parent()) {
- parent->DirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
+ parent->MarkAncestorChainForDescendantDependentFlagsUpdate();
if (PaintLayer* enclosing_self_painting_layer =
parent->EnclosingSelfPaintingLayer()) {
@@ -2996,8 +3028,10 @@ bool PaintLayer::AttemptDirectCompositingUpdate(
const ComputedStyle* old_style) {
CompositingReasons old_potential_compositing_reasons_from_style =
PotentialCompositingReasonsFromStyle();
- if (Compositor() && diff.HasDifference())
+ if (Compositor() &&
+ (diff.HasDifference() || needs_compositing_reasons_update_))
Compositor()->UpdatePotentialCompositingReasonsFromStyle(*this);
+ needs_compositing_reasons_update_ = false;
// This function implements an optimization for transforms and opacity.
// A common pattern is for a touchmove handler to update the transform
@@ -3070,7 +3104,8 @@ void PaintLayer::StyleDidChange(StyleDifference diff,
if (AttemptDirectCompositingUpdate(diff, old_style))
return;
- stacking_node_->StyleDidChange(old_style);
+ if (PaintLayerStackingNode::StyleDidChange(this, old_style))
+ MarkAncestorChainForDescendantDependentFlagsUpdate();
if (RequiresScrollableArea()) {
DCHECK(scrollable_area_);
@@ -3081,16 +3116,18 @@ void PaintLayer::StyleDidChange(StyleDifference diff,
// to recompute the bit once scrollbars have been updated.
UpdateSelfPaintingLayer();
- UpdateTransform(old_style, GetLayoutObject().StyleRef());
- UpdateFilters(old_style, GetLayoutObject().StyleRef());
- UpdateClipPath(old_style, GetLayoutObject().StyleRef());
+ const ComputedStyle& new_style = GetLayoutObject().StyleRef();
+
+ UpdateTransform(old_style, new_style);
+ UpdateFilters(old_style, new_style);
+ UpdateClipPath(old_style, new_style);
SetNeedsCompositingInputsUpdate();
GetLayoutObject().SetNeedsPaintPropertyUpdate();
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() && !NeedsRepaint()) {
+ if (!NeedsRepaint()) {
if (diff.ZIndexChanged()) {
- // We don't need to invalidate paint of objects on SPv175 when paint order
+ // We don't need to invalidate paint of objects when paint order
// changes. However, we do need to repaint the containing stacking
// context, in order to generate new paint chunks in the correct order.
// Raster invalidation will be issued if needed during paint.
@@ -3103,7 +3140,7 @@ void PaintLayer::StyleDidChange(StyleDifference diff,
// compositing state.
DisableCompositingQueryAsserts disable;
if (painter.PaintedOutputInvisible(*old_style) !=
- painter.PaintedOutputInvisible(GetLayoutObject().StyleRef()))
+ painter.PaintedOutputInvisible(new_style))
SetNeedsRepaint();
}
}
@@ -3310,7 +3347,7 @@ void PaintLayer::SetNeedsRepaint() {
void PaintLayer::SetNeedsRepaintInternal() {
needs_repaint_ = true;
// Invalidate as a display item client.
- SetDisplayItemsUncached();
+ static_cast<DisplayItemClient*>(this)->Invalidate();
}
void PaintLayer::MarkCompositingContainerChainForNeedsRepaint() {
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 8ef3ef63ce7..2b6736933d7 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer.h
@@ -54,7 +54,6 @@
#include "third_party/blink/renderer/core/paint/paint_layer_clipper.h"
#include "third_party/blink/renderer/core/paint/paint_layer_fragment.h"
#include "third_party/blink/renderer/core/paint/paint_layer_resource_info.h"
-#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
#include "third_party/blink/renderer/core/paint/paint_layer_stacking_node.h"
#include "third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h"
#include "third_party/blink/renderer/core/paint/paint_result.h"
@@ -72,6 +71,8 @@ class FilterOperations;
class HitTestResult;
class HitTestingTransformState;
class PaintLayerCompositor;
+class PaintLayerScrollableArea;
+class ScrollingCoordinator;
class TransformationMatrix;
using PaintLayerId = uint64_t;
@@ -124,6 +125,8 @@ struct PaintLayerRareData {
// compositing state of this layer.
CompositingReasons potential_compositing_reasons_from_style;
+ CompositingReasons potential_compositing_reasons_from_non_style;
+
// Once computed, indicates all that a layer needs to become composited using
// the CompositingReasons enum bitfield.
CompositingReasons compositing_reasons;
@@ -248,7 +251,7 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
void ClearClipRects(ClipRectsCacheSlot = kNumberOfClipRectsCacheSlots);
- void RemoveOnlyThisLayerAfterStyleChange();
+ void RemoveOnlyThisLayerAfterStyleChange(const ComputedStyle* old_style);
void InsertOnlyThisLayerAfterStyleChange();
void StyleDidChange(StyleDifference, const ComputedStyle* old_style);
@@ -419,7 +422,11 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
// The hitTest() method looks for mouse events by walking layers that
// intersect the point from front to back.
- bool HitTest(HitTestResult&);
+ // |hit_test_area| is the rect in the space of this PaintLayer's
+ // LayoutObject to consider for hit testing.
+ bool HitTest(const HitTestLocation& location,
+ HitTestResult&,
+ const LayoutRect& hit_test_area);
bool IntersectsDamageRect(const LayoutRect& layer_bounds,
const LayoutRect& damage_rect,
@@ -551,11 +558,7 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
};
void SetGroupedMapping(CompositedLayerMapping*, SetGroupMappingOptions);
- bool MaskBlendingAppliedByCompositor(const PaintInfo&) const;
- bool HasCompositedClippingMask() const;
- bool NeedsCompositedScrolling() const {
- return scrollable_area_ && scrollable_area_->NeedsCompositedScrolling();
- }
+ bool NeedsCompositedScrolling() const;
// Paint invalidation containers can be self-composited or squashed.
// In the former case, these methods do nothing.
@@ -686,6 +689,14 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
bool ScrollsOverflow() const;
+ CompositingReasons DirectCompositingReasons() const {
+ return rare_data_
+ ? ((rare_data_->potential_compositing_reasons_from_style |
+ rare_data_->potential_compositing_reasons_from_non_style) &
+ CompositingReason::kComboAllDirectReasons)
+ : CompositingReason::kNone;
+ }
+
CompositingReasons PotentialCompositingReasonsFromStyle() const {
return rare_data_ ? rare_data_->potential_compositing_reasons_from_style
: CompositingReason::kNone;
@@ -696,6 +707,17 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
if (rare_data_ || reasons != CompositingReason::kNone)
EnsureRareData().potential_compositing_reasons_from_style = reasons;
}
+ CompositingReasons PotentialCompositingReasonsFromNonStyle() const {
+ return rare_data_ ? rare_data_->potential_compositing_reasons_from_non_style
+ : CompositingReason::kNone;
+ }
+ void SetPotentialCompositingReasonsFromNonStyle(CompositingReasons reasons) {
+ DCHECK(reasons ==
+ (reasons &
+ CompositingReason::kComboAllDirectNonStyleDeterminedReasons));
+ if (rare_data_ || reasons != CompositingReason::kNone)
+ EnsureRareData().potential_compositing_reasons_from_non_style = reasons;
+ }
bool HasStyleDeterminedDirectCompositingReasons() const {
return PotentialCompositingReasonsFromStyle() &
@@ -752,7 +774,7 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
}
void UpdateAncestorDependentCompositingInputs(
const AncestorDependentCompositingInputs&);
- void DidUpdateCompositingInputs();
+ void ClearChildNeedsCompositingInputsUpdate();
const AncestorDependentCompositingInputs&
GetAncestorDependentCompositingInputs() const {
@@ -806,8 +828,25 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
return GetAncestorDependentCompositingInputs().mask_ancestor;
}
bool HasDescendantWithClipPath() const {
+ DCHECK(!needs_descendant_dependent_flags_update_);
return has_descendant_with_clip_path_;
}
+ bool HasDescendantWithStickyOrFixed() const {
+ DCHECK(!needs_descendant_dependent_flags_update_);
+ return has_descendant_with_sticky_or_fixed_;
+ }
+ bool HasNonContainedAbsolutePositionDescendant() const {
+ DCHECK(!needs_descendant_dependent_flags_update_);
+ return has_non_contained_absolute_position_descendant_;
+ }
+ bool HasSelfPaintingLayerDescendant() const {
+ DCHECK(!needs_descendant_dependent_flags_update_);
+ return has_self_painting_layer_descendant_;
+ }
+ bool IsNonStackedWithInFlowStackedDescendant() const {
+ DCHECK(!needs_descendant_dependent_flags_update_);
+ return is_non_stacked_with_in_flow_stacked_descendant_;
+ }
// Returns true if there is a descendant with blend-mode that is
// not contained within another enclosing stacking context other
@@ -822,7 +861,11 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
DCHECK(IsAllowedToQueryCompositingState());
return lost_grouped_mapping_;
}
- void SetLostGroupedMapping(bool b) { lost_grouped_mapping_ = b; }
+ void SetLostGroupedMapping(bool b) {
+ lost_grouped_mapping_ = b;
+ needs_compositing_layer_assignment_ =
+ needs_compositing_layer_assignment_ || b;
+ }
CompositingReasons GetCompositingReasons() const {
DCHECK(IsAllowedToQueryCompositingState());
@@ -864,12 +907,6 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
void DidUpdateScrollsOverflow();
- bool HasSelfPaintingLayerDescendant() const {
- if (has_self_painting_layer_descendant_dirty_)
- UpdateHasSelfPaintingLayerDescendant();
- DCHECK(!has_self_painting_layer_descendant_dirty_);
- return has_self_painting_layer_descendant_;
- }
LayoutRect PaintingExtent(const PaintLayer* root_layer,
const LayoutSize& sub_pixel_accumulation,
GlobalPaintFlags);
@@ -877,7 +914,7 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
void AppendSingleFragmentIgnoringPagination(
PaintLayerFragments&,
const PaintLayer* root_layer,
- const LayoutRect& dirty_rect,
+ const LayoutRect* dirty_rect,
OverlayScrollbarClipBehavior = kIgnorePlatformOverlayScrollbarSize,
ShouldRespectOverflowClipType = kRespectOverflowClip,
const LayoutPoint* offset_from_root = nullptr,
@@ -886,7 +923,7 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
void CollectFragments(
PaintLayerFragments&,
const PaintLayer* root_layer,
- const LayoutRect& dirty_rect,
+ const LayoutRect* dirty_rect,
OverlayScrollbarClipBehavior = kIgnorePlatformOverlayScrollbarSize,
ShouldRespectOverflowClipType = kRespectOverflowClip,
const LayoutPoint* offset_from_root = nullptr,
@@ -925,13 +962,6 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
// shouldCreateSubsequence() in PaintLayerPainter.cpp for the cases we use
// subsequence when painting a PaintLayer.
- IntSize PreviousScrollOffsetAccumulationForPainting() const {
- return previous_scroll_offset_accumulation_for_painting_;
- }
- void SetPreviousScrollOffsetAccumulationForPainting(const IntSize& s) {
- previous_scroll_offset_accumulation_for_painting_ = s;
- }
-
LayoutRect PreviousPaintDirtyRect() const {
return previous_paint_dirty_rect_;
}
@@ -992,6 +1022,21 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
previous_paint_phase_descendant_block_backgrounds_was_empty_ = is_empty;
}
+ bool DescendantHasDirectOrScrollingCompositingReason() const {
+ return descendant_has_direct_or_scrolling_compositing_reason_;
+ }
+ void SetDescendantHasDirectOrScrollingCompositingReason(bool value) {
+ descendant_has_direct_or_scrolling_compositing_reason_ = value;
+ }
+
+ void SetNeedsCompositingRequirementsUpdate();
+ void ClearNeedsCompositingRequirementsUpdate() {
+ descendant_may_need_compositing_requirements_update_ = false;
+ }
+ bool DescendantMayNeedCompositingRequirementsUpdate() const {
+ return descendant_may_need_compositing_requirements_update_;
+ }
+
ClipRectsCache* GetClipRectsCache() const { return clip_rects_cache_.get(); }
ClipRectsCache& EnsureClipRectsCache() const {
if (!clip_rects_cache_)
@@ -1027,7 +1072,29 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
// See
// https://chromium.googlesource.com/chromium/src.git/+/master/third_party/blink/renderer/core/paint/README.md
// for the definition of a replaced normal-flow stacking element.
- bool IsReplacedNormalFlowStacking();
+ bool IsReplacedNormalFlowStacking() const;
+
+ void SetNeeedsCompositingReasonsUpdate() {
+ needs_compositing_reasons_update_ = true;
+ }
+
+#if DCHECK_IS_ON()
+ void SetStackingParent(PaintLayerStackingNode* stacking_parent) {
+ stacking_parent_ = stacking_parent;
+ }
+ PaintLayerStackingNode* StackingParent() { return stacking_parent_; }
+ bool IsInStackingParentZOrderLists() const;
+#endif
+
+ void SetNeedsCompositingLayerAssignment();
+ void ClearNeedsCompositingLayerAssignment();
+
+ bool NeedsCompositingLayerAssignment() const {
+ return needs_compositing_layer_assignment_;
+ }
+ bool StackingDescendantNeedsCompositingLayerAssignment() const {
+ return descendant_needs_compositing_layer_assignment_;
+ }
private:
void SetNeedsCompositingInputsUpdateInternal();
@@ -1039,8 +1106,6 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
bool HasOverflowControls() const;
- void DirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
-
enum UpdateLayerPositionBehavior { AllLayers, OnlyStickyLayers };
void UpdateLayerPositionRecursive(UpdateLayerPositionBehavior = AllLayers);
@@ -1050,11 +1115,22 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
void SetLastChild(PaintLayer* last) { last_ = last; }
void UpdateHasSelfPaintingLayerDescendant() const;
+
+ struct HitTestRecursionData {
+ const LayoutRect& rect;
+ // Whether location.Intersects(rect) returns true.
+ const HitTestLocation& location;
+ const HitTestLocation& original_location;
+ const bool intersects_location;
+ HitTestRecursionData(const LayoutRect& rect_arg,
+ const HitTestLocation& location_arg,
+ const HitTestLocation& original_location_arg);
+ };
+
PaintLayer* HitTestLayer(PaintLayer* root_layer,
PaintLayer* container_layer,
HitTestResult&,
- const LayoutRect& hit_test_rect,
- const HitTestLocation&,
+ const HitTestRecursionData& recursion_data,
bool applied_transform,
const HitTestingTransformState* = nullptr,
double* z_offset = nullptr);
@@ -1062,8 +1138,7 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
PaintLayer* root_layer,
PaintLayer* container_layer,
HitTestResult&,
- const LayoutRect& hit_test_rect,
- const HitTestLocation&,
+ const HitTestRecursionData& recursion_data,
const HitTestingTransformState* = nullptr,
double* z_offset = nullptr,
const LayoutPoint& translation_offset = LayoutPoint());
@@ -1071,8 +1146,7 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
ChildrenIteration,
PaintLayer* root_layer,
HitTestResult&,
- const LayoutRect& hit_test_rect,
- const HitTestLocation&,
+ const HitTestRecursionData& recursion_data,
const HitTestingTransformState*,
double* z_offset_for_descendants,
double* z_offset,
@@ -1082,8 +1156,7 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
scoped_refptr<HitTestingTransformState> CreateLocalTransformState(
PaintLayer* root_layer,
PaintLayer* container_layer,
- const LayoutRect& hit_test_rect,
- const HitTestLocation&,
+ const HitTestRecursionData& recursion_data,
const HitTestingTransformState* container_transform_state,
const LayoutPoint& translation_offset = LayoutPoint()) const;
@@ -1101,8 +1174,7 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
PaintLayer* root_layer,
PaintLayer* container_layer,
HitTestResult&,
- const LayoutRect& hit_test_rect,
- const HitTestLocation&,
+ const HitTestRecursionData&,
const HitTestingTransformState*,
double* z_offset,
ShouldRespectOverflowClipType);
@@ -1113,9 +1185,7 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
bool ShouldBeSelfPaintingLayer() const;
- // FIXME: We should only create the stacking node if needed.
- bool RequiresStackingNode() const { return true; }
- void UpdateStackingNode();
+ void UpdateStackingNode(bool needs_stacking_node);
FilterOperations FilterOperationsIncludingReflection() const;
@@ -1182,13 +1252,6 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
// overflow-only concept.
unsigned is_self_painting_layer_ : 1;
- // If have no self-painting descendants, we don't have to walk our children
- // during painting. This can lead to significant savings, especially if the
- // tree has lots of non-self-painting layers grouped together (e.g. table
- // cells).
- mutable unsigned has_self_painting_layer_descendant_ : 1;
- mutable unsigned has_self_painting_layer_descendant_dirty_ : 1;
-
const unsigned is_root_layer_ : 1;
unsigned has_visible_content_ : 1;
@@ -1241,6 +1304,8 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
// inputs.
unsigned has_descendant_with_clip_path_ : 1;
unsigned has_non_isolated_descendant_with_blend_mode_ : 1;
+ unsigned has_descendant_with_sticky_or_fixed_ : 1;
+ unsigned has_non_contained_absolute_position_descendant_ : 1;
unsigned self_painting_status_changed_ : 1;
@@ -1253,6 +1318,16 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
// ancestor.
unsigned is_under_svg_hidden_container_ : 1;
+ unsigned descendant_has_direct_or_scrolling_compositing_reason_ : 1;
+ unsigned needs_compositing_reasons_update_ : 1;
+
+ unsigned descendant_may_need_compositing_requirements_update_ : 1;
+ unsigned needs_compositing_layer_assignment_ : 1;
+ unsigned descendant_needs_compositing_layer_assignment_ : 1;
+
+ unsigned has_self_painting_layer_descendant_ : 1;
+ unsigned is_non_stacked_with_in_flow_stacked_descendant_ : 1;
+
LayoutBoxModelObject& layout_object_;
PaintLayer* parent_;
@@ -1287,11 +1362,14 @@ class CORE_EXPORT PaintLayer : public DisplayItemClient {
std::unique_ptr<PaintLayerStackingNode> stacking_node_;
- IntSize previous_scroll_offset_accumulation_for_painting_;
LayoutRect previous_paint_dirty_rect_;
std::unique_ptr<PaintLayerRareData> rare_data_;
+#if DCHECK_IS_ON()
+ PaintLayerStackingNode* stacking_parent_;
+#endif
+
FRIEND_TEST_ALL_PREFIXES(PaintLayerTest,
DescendantDependentFlagsStopsAtThrottledFrames);
FRIEND_TEST_ALL_PREFIXES(PaintLayerTest,
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.cc
index 44be51dd06d..7d3d6388cca 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.cc
@@ -50,6 +50,7 @@
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/paint/object_paint_properties.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/graphics/paint/geometry_mapper.h"
namespace blink {
@@ -94,8 +95,6 @@ static void ApplyClipRects(const ClipRectsContext& context,
DCHECK(box.ShouldClipOverflow() || box.HasClip());
LayoutView* view = box.View();
DCHECK(view);
- if (clip_rects.Fixed() && &context.root_layer->GetLayoutObject() == view)
- offset -= LayoutSize(view->GetFrameView()->GetScrollOffset());
if (box.ShouldClipOverflow()) {
ClipRect new_overflow_clip =
@@ -109,7 +108,7 @@ static void ApplyClipRects(const ClipRectsContext& context,
if (box.CanContainFixedPositionObjects())
clip_rects.SetFixedClipRect(
Intersection(new_overflow_clip, clip_rects.FixedClipRect()));
- if (box.StyleRef().ContainsPaint())
+ if (box.ShouldApplyPaintContainment())
clip_rects.SetPosClipRect(
Intersection(new_overflow_clip, clip_rects.PosClipRect()));
}
@@ -221,8 +220,11 @@ LayoutRect PaintLayerClipper::LocalClipRect(
CalculateBackgroundClipRectWithGeometryMapper(
context, layer_.GetLayoutObject().FirstFragment(), kRespectOverflowClip,
clip_rect);
- LayoutRect premapped_rect = clip_rect.Rect();
+ if (clip_rect.IsInfinite())
+ return clip_rect.Rect();
+
+ LayoutRect premapped_rect = clip_rect.Rect();
// The rect now needs to be transformed to the local space of this
// PaintLayer.
// TODO(chrishtr): not correct for fragmentation.
@@ -251,14 +253,13 @@ LayoutRect PaintLayerClipper::LocalClipRect(
LayoutRect layer_bounds;
ClipRect background_rect, foreground_rect;
- CalculateRects(context, nullptr, LayoutRect(LayoutRect::InfiniteIntRect()),
- layer_bounds, background_rect, foreground_rect);
+ CalculateRects(context, nullptr, nullptr, layer_bounds, background_rect,
+ foreground_rect);
- LayoutRect clip_rect = background_rect.Rect();
- // TODO(chrishtr): avoid converting to IntRect and back.
- if (clip_rect == LayoutRect(LayoutRect::InfiniteIntRect()))
- return clip_rect;
+ if (background_rect.IsInfinite())
+ return background_rect.Rect();
+ LayoutRect clip_rect = background_rect.Rect();
LayoutPoint clipping_root_offset;
layer_.ConvertToLayerCoords(&clipping_root_layer, clipping_root_offset);
clip_rect.MoveBy(-clipping_root_offset);
@@ -269,7 +270,7 @@ LayoutRect PaintLayerClipper::LocalClipRect(
void PaintLayerClipper::CalculateRectsWithGeometryMapper(
const ClipRectsContext& context,
const FragmentData& fragment_data,
- const LayoutRect& paint_dirty_rect,
+ const LayoutRect* paint_dirty_rect,
LayoutRect& layer_bounds,
ClipRect& background_rect,
ClipRect& foreground_rect,
@@ -329,7 +330,10 @@ void PaintLayerClipper::CalculateRectsWithGeometryMapper(
CalculateBackgroundClipRectWithGeometryMapper(
context, fragment_data, kRespectOverflowClip, background_rect);
- background_rect.Intersect(paint_dirty_rect);
+
+ foreground_rect.Reset();
+ if (paint_dirty_rect)
+ background_rect.Intersect(*paint_dirty_rect);
if (ShouldClipOverflow(context)) {
LayoutBoxModelObject& layout_object = layer_.GetLayoutObject();
@@ -348,7 +352,7 @@ void PaintLayerClipper::CalculateRectsWithGeometryMapper(
void PaintLayerClipper::CalculateRects(
const ClipRectsContext& context,
const FragmentData* fragment_data,
- const LayoutRect& paint_dirty_rect,
+ const LayoutRect* paint_dirty_rect,
LayoutRect& layer_bounds,
ClipRect& background_rect,
ClipRect& foreground_rect,
@@ -374,10 +378,9 @@ void PaintLayerClipper::CalculateRects(
if (!is_clipping_root && layer_.Parent()) {
CalculateBackgroundClipRect(context, background_rect);
background_rect.Move(context.sub_pixel_accumulation);
- background_rect.Intersect(paint_dirty_rect);
- } else {
- background_rect = paint_dirty_rect;
}
+ if (paint_dirty_rect)
+ background_rect.Intersect(*paint_dirty_rect);
foreground_rect = background_rect;
@@ -480,11 +483,10 @@ void PaintLayerClipper::CalculateBackgroundClipRectWithGeometryMapper(
ClipRect& output) const {
DCHECK(use_geometry_mapper_);
+ output.Reset();
bool is_clipping_root = &layer_ == context.root_layer;
- if (is_clipping_root && !context.ShouldRespectRootLayerClip()) {
- output.SetRect(FloatClipRect());
+ if (is_clipping_root && !context.ShouldRespectRootLayerClip())
return;
- }
PropertyTreeState source_property_tree_state(nullptr, nullptr, nullptr);
PropertyTreeState destination_property_tree_state(nullptr, nullptr, nullptr);
@@ -522,7 +524,8 @@ void PaintLayerClipper::CalculateBackgroundClipRectWithGeometryMapper(
destination_property_tree_state,
clip_rect, clip_behavior);
output.SetRect(clip_rect);
- } else {
+ } else if (source_property_tree_state.Clip() !=
+ destination_property_tree_state.Clip()) {
const FloatClipRect& clipped_rect_in_root_layer_space =
GeometryMapper::LocalToAncestorClipRect(
source_property_tree_state, destination_property_tree_state,
@@ -530,10 +533,12 @@ void PaintLayerClipper::CalculateBackgroundClipRectWithGeometryMapper(
output.SetRect(clipped_rect_in_root_layer_space);
}
- // TODO(chrishtr): generalize to multiple fragments.
- output.MoveBy(
- -context.root_layer->GetLayoutObject().FirstFragment().PaintOffset());
- output.Move(context.sub_pixel_accumulation);
+ if (!output.IsInfinite()) {
+ // TODO(chrishtr): generalize to multiple fragments.
+ output.MoveBy(
+ -context.root_layer->GetLayoutObject().FirstFragment().PaintOffset());
+ output.Move(context.sub_pixel_accumulation);
+ }
}
void PaintLayerClipper::InitializeCommonClipRectState(
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.h b/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.h
index 3f830db57d6..9df1f85fb59 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper.h
@@ -188,9 +188,11 @@ class CORE_EXPORT PaintLayerClipper {
// include subpixel accumualation. Otherwise it is set to the offset from
// |layer_| to |root_layer|, plus |context.sub_pixel_accumuation|.
// |fragment_data| is only used in kUseGeometryMapper mode.
+ // If |paint_dirty_rect| is provided, intersects |background_rect|
+ // and |foreground_rect| with it.
void CalculateRects(const ClipRectsContext&,
const FragmentData*,
- const LayoutRect& paint_dirty_rect,
+ const LayoutRect* paint_dirty_rect,
LayoutRect& layer_bounds,
ClipRect& background_rect,
ClipRect& foreground_rect,
@@ -227,7 +229,7 @@ class CORE_EXPORT PaintLayerClipper {
ALWAYS_INLINE void CalculateRectsWithGeometryMapper(
const ClipRectsContext&,
const FragmentData&,
- const LayoutRect& paint_dirty_rect,
+ const LayoutRect* paint_dirty_rect,
LayoutRect& layer_bounds,
ClipRect& background_rect,
ClipRect& foreground_rect,
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc
index 09da860785d..aadfe40237e 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_clipper_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/core/paint/paint_layer_clipper.h"
#include "build/build_config.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
@@ -143,8 +144,7 @@ TEST_F(PaintLayerClipperTest, LayoutSVGRoot) {
target_paint_layer->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context,
&target_paint_layer->GetLayoutObject().FirstFragment(),
- LayoutRect(LayoutRect::InfiniteIntRect()), layer_bounds,
- background_rect, foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
EXPECT_EQ(LayoutRect(FloatRect(8.25, 8.35, 200, 300)),
background_rect.Rect());
@@ -173,8 +173,7 @@ TEST_F(PaintLayerClipperTest, ControlClip) {
target_paint_layer->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context,
&target_paint_layer->GetLayoutObject().FirstFragment(),
- LayoutRect(LayoutRect::InfiniteIntRect()), layer_bounds,
- background_rect, foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
#if defined(OS_MACOSX)
// If the PaintLayer clips overflow, the background rect is intersected with
// the PaintLayer bounds...
@@ -213,8 +212,7 @@ TEST_F(PaintLayerClipperTest, RoundedClip) {
target_paint_layer->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context,
&target_paint_layer->GetLayoutObject().FirstFragment(),
- LayoutRect(LayoutRect::InfiniteIntRect()), layer_bounds,
- background_rect, foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
// Only the foreground rect gets hasRadius set for overflow clipping
// of descendants.
@@ -252,8 +250,7 @@ TEST_F(PaintLayerClipperTest, RoundedClipNested) {
child_paint_layer->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context,
&child_paint_layer->GetLayoutObject().FirstFragment(),
- LayoutRect(LayoutRect::InfiniteIntRect()), layer_bounds,
- background_rect, foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
EXPECT_EQ(LayoutRect(0, 0, 200, 300), background_rect.Rect());
EXPECT_TRUE(background_rect.HasRadius());
@@ -289,8 +286,7 @@ TEST_F(PaintLayerClipperTest, ControlClipSelect) {
target_paint_layer->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context,
&target_paint_layer->GetLayoutObject().FirstFragment(),
- LayoutRect(LayoutRect::InfiniteIntRect()), layer_bounds,
- background_rect, foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
// The control clip for a select excludes the area for the down arrow.
#if defined(OS_MACOSX)
EXPECT_EQ(LayoutRect(16, 9, 79, 13), foreground_rect.Rect());
@@ -322,8 +318,7 @@ TEST_F(PaintLayerClipperTest, LayoutSVGRootChild) {
target_paint_layer->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context,
&target_paint_layer->GetLayoutObject().FirstFragment(),
- LayoutRect(LayoutRect::InfiniteIntRect()), layer_bounds,
- background_rect, foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
EXPECT_EQ(LayoutRect(8, 8, 200, 300), background_rect.Rect());
EXPECT_EQ(LayoutRect(8, 8, 200, 300), foreground_rect.Rect());
EXPECT_EQ(LayoutRect(8, 8, 400, 0), layer_bounds);
@@ -337,7 +332,6 @@ TEST_F(PaintLayerClipperTest, ContainPaintClip) {
</div>
)HTML");
- LayoutRect infinite_rect(LayoutRect::InfiniteIntRect());
PaintLayer* layer =
ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer();
ClipRectsContext context(layer, kPaintingClipRectsIgnoringOverflowClip,
@@ -348,8 +342,7 @@ TEST_F(PaintLayerClipperTest, ContainPaintClip) {
layer->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context, &layer->GetLayoutObject().FirstFragment(),
- infinite_rect, layer_bounds, background_rect,
- foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
EXPECT_GE(background_rect.Rect().Size().Width().ToInt(), 33554422);
EXPECT_GE(background_rect.Rect().Size().Height().ToInt(), 33554422);
EXPECT_EQ(background_rect.Rect(), foreground_rect.Rect());
@@ -359,8 +352,7 @@ TEST_F(PaintLayerClipperTest, ContainPaintClip) {
layer->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context_clip, &layer->GetLayoutObject().FirstFragment(),
- infinite_rect, layer_bounds, background_rect,
- foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
EXPECT_EQ(LayoutRect(0, 0, 200, 200), background_rect.Rect());
EXPECT_EQ(LayoutRect(0, 0, 200, 200), foreground_rect.Rect());
EXPECT_EQ(LayoutRect(0, 0, 200, 200), layer_bounds);
@@ -375,7 +367,6 @@ TEST_F(PaintLayerClipperTest, NestedContainPaintClip) {
</div>
)HTML");
- LayoutRect infinite_rect(LayoutRect::InfiniteIntRect());
PaintLayer* layer =
ToLayoutBoxModelObject(GetLayoutObjectByElementId("target"))->Layer();
ClipRectsContext context(
@@ -386,8 +377,7 @@ TEST_F(PaintLayerClipperTest, NestedContainPaintClip) {
layer->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context, &layer->GetLayoutObject().FirstFragment(),
- infinite_rect, layer_bounds, background_rect,
- foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
EXPECT_EQ(LayoutRect(0, 0, 200, 400), background_rect.Rect());
EXPECT_EQ(LayoutRect(0, 0, 200, 400), foreground_rect.Rect());
EXPECT_EQ(LayoutRect(0, 0, 200, 400), layer_bounds);
@@ -396,8 +386,7 @@ TEST_F(PaintLayerClipperTest, NestedContainPaintClip) {
layer->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context_clip, &layer->GetLayoutObject().FirstFragment(),
- infinite_rect, layer_bounds, background_rect,
- foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
EXPECT_EQ(LayoutRect(0, 0, 200, 200), background_rect.Rect());
EXPECT_EQ(LayoutRect(0, 0, 200, 200), foreground_rect.Rect());
EXPECT_EQ(LayoutRect(0, 0, 200, 400), layer_bounds);
@@ -415,7 +404,6 @@ TEST_F(PaintLayerClipperTest, LocalClipRectFixedUnderTransform) {
</div>
)HTML");
- LayoutRect infinite_rect(LayoutRect::InfiniteIntRect());
PaintLayer* transformed =
ToLayoutBoxModelObject(GetLayoutObjectByElementId("transformed"))
->Layer();
@@ -521,8 +509,7 @@ TEST_F(PaintLayerClipperTest, CSSClip) {
ClipRect foreground_rect(infinite_rect);
target->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context, &target->GetLayoutObject().FirstFragment(),
- infinite_rect, layer_bounds, background_rect,
- foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
EXPECT_EQ(LayoutRect(0, 0, 50, 100), background_rect.Rect());
EXPECT_EQ(LayoutRect(0, 0, 50, 100), foreground_rect.Rect());
@@ -551,8 +538,7 @@ TEST_F(PaintLayerClipperTest, Filter) {
ClipRect foreground_rect(infinite_rect);
target->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context, &target->GetLayoutObject().FirstFragment(),
- infinite_rect, layer_bounds, background_rect,
- foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
// The background rect is used to clip stacking context (layer) output.
// In this case, nothing is above us, thus the infinite rect. However we do
@@ -566,8 +552,8 @@ TEST_F(PaintLayerClipperTest, Filter) {
background_rect = infinite_rect;
foreground_rect = infinite_rect;
target->Clipper(PaintLayer::kDoNotUseGeometryMapper)
- .CalculateRects(context, nullptr, infinite_rect, layer_bounds,
- background_rect, foreground_rect);
+ .CalculateRects(context, nullptr, nullptr, layer_bounds, background_rect,
+ foreground_rect);
// The non-GeometryMapper path applies the immediate filter effect in
// background rect.
EXPECT_EQ(LayoutRect(-12, -9, 204, 304), background_rect.Rect());
@@ -579,8 +565,7 @@ TEST_F(PaintLayerClipperTest, Filter) {
foreground_rect = infinite_rect;
target->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(root_context, &target->GetLayoutObject().FirstFragment(),
- infinite_rect, layer_bounds, background_rect,
- foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
// This includes the filter effect because it's applied before mapping the
// background rect to the root layer.
EXPECT_EQ(LayoutRect(38, 41, 204, 304), background_rect.Rect());
@@ -590,7 +575,7 @@ TEST_F(PaintLayerClipperTest, Filter) {
background_rect = infinite_rect;
foreground_rect = infinite_rect;
target->Clipper(PaintLayer::kDoNotUseGeometryMapper)
- .CalculateRects(root_context, nullptr, infinite_rect, layer_bounds,
+ .CalculateRects(root_context, nullptr, nullptr, layer_bounds,
background_rect, foreground_rect);
EXPECT_EQ(LayoutRect(38, 41, 204, 304), background_rect.Rect());
EXPECT_EQ(LayoutRect(90, 90, 100, 200), foreground_rect.Rect());
@@ -632,8 +617,7 @@ TEST_F(PaintLayerClipperTest, IgnoreRootLayerClipWithCSSClip) {
ClipRect foreground_rect(infinite_rect);
target->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context, &target->GetLayoutObject().FirstFragment(),
- infinite_rect, layer_bounds, background_rect,
- foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
EXPECT_TRUE(IsInfinite(background_rect.Rect()));
EXPECT_TRUE(IsInfinite(foreground_rect.Rect()));
@@ -668,8 +652,7 @@ TEST_F(PaintLayerClipperTest, IgnoreRootLayerClipWithOverflowClip) {
ClipRect foreground_rect(infinite_rect);
target->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context, &target->GetLayoutObject().FirstFragment(),
- infinite_rect, layer_bounds, background_rect,
- foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
EXPECT_TRUE(IsInfinite(background_rect.Rect()));
EXPECT_TRUE(IsInfinite(foreground_rect.Rect()));
@@ -705,8 +688,7 @@ TEST_F(PaintLayerClipperTest, IgnoreRootLayerClipWithBothClip) {
ClipRect foreground_rect(infinite_rect);
target->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context, &target->GetLayoutObject().FirstFragment(),
- infinite_rect, layer_bounds, background_rect,
- foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
EXPECT_TRUE(IsInfinite(background_rect.Rect()));
EXPECT_TRUE(IsInfinite(foreground_rect.Rect()));
@@ -744,8 +726,7 @@ TEST_F(PaintLayerClipperTest, Fragmentation) {
target_paint_layer->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context,
&target_paint_layer->GetLayoutObject().FirstFragment(),
- LayoutRect(LayoutRect::InfiniteIntRect()), layer_bounds,
- background_rect, foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
EXPECT_EQ(LayoutRect(FloatRect(-1.0e6, -1.0e6, 1.0001e6, 1.0001e6)),
background_rect.Rect());
@@ -757,8 +738,7 @@ TEST_F(PaintLayerClipperTest, Fragmentation) {
.CalculateRects(
context,
target_paint_layer->GetLayoutObject().FirstFragment().NextFragment(),
- LayoutRect(LayoutRect::InfiniteIntRect()), layer_bounds,
- background_rect, foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
EXPECT_EQ(LayoutRect(FloatRect(100, 0, 1000000, 999900)),
background_rect.Rect());
@@ -795,8 +775,7 @@ TEST_F(PaintLayerClipperTest, ScrollbarClipBehaviorChild) {
child_paint_layer->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context,
&child_paint_layer->GetLayoutObject().FirstFragment(),
- LayoutRect(LayoutRect::InfiniteIntRect()), layer_bounds,
- background_rect, foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
// The background and foreground rect are clipped by the scrollbar size.
EXPECT_EQ(LayoutRect(0, 0, 193, 293), background_rect.Rect());
@@ -804,9 +783,8 @@ TEST_F(PaintLayerClipperTest, ScrollbarClipBehaviorChild) {
EXPECT_EQ(LayoutRect(0, 0, 500, 500), layer_bounds);
child_paint_layer->Clipper(PaintLayer::kDoNotUseGeometryMapper)
- .CalculateRects(context, nullptr,
- LayoutRect(LayoutRect::InfiniteIntRect()), layer_bounds,
- background_rect, foreground_rect);
+ .CalculateRects(context, nullptr, nullptr, layer_bounds, background_rect,
+ foreground_rect);
// The background and foreground rect are clipped by the scrollbar size.
EXPECT_EQ(LayoutRect(0, 0, 193, 293), background_rect.Rect());
@@ -840,8 +818,7 @@ TEST_F(PaintLayerClipperTest, ScrollbarClipBehaviorChildScrollBetween) {
child_paint_layer->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context,
&child_paint_layer->GetLayoutObject().FirstFragment(),
- LayoutRect(LayoutRect::InfiniteIntRect()), layer_bounds,
- background_rect, foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
// The background and foreground rect are clipped by the scrollbar size.
EXPECT_EQ(LayoutRect(8, 8, 193, 293), background_rect.Rect());
@@ -849,9 +826,8 @@ TEST_F(PaintLayerClipperTest, ScrollbarClipBehaviorChildScrollBetween) {
EXPECT_EQ(LayoutRect(8, 8, 500, 500), layer_bounds);
child_paint_layer->Clipper(PaintLayer::kDoNotUseGeometryMapper)
- .CalculateRects(context, nullptr,
- LayoutRect(LayoutRect::InfiniteIntRect()), layer_bounds,
- background_rect, foreground_rect);
+ .CalculateRects(context, nullptr, nullptr, layer_bounds, background_rect,
+ foreground_rect);
// The background and foreground rect are clipped by the scrollbar size.
EXPECT_EQ(LayoutRect(8, 8, 193, 293), background_rect.Rect());
@@ -886,8 +862,7 @@ TEST_F(PaintLayerClipperTest, ScrollbarClipBehaviorParent) {
parent_paint_layer->Clipper(PaintLayer::kUseGeometryMapper)
.CalculateRects(context,
&child_paint_layer->GetLayoutObject().FirstFragment(),
- LayoutRect(LayoutRect::InfiniteIntRect()), layer_bounds,
- background_rect, foreground_rect);
+ nullptr, layer_bounds, background_rect, foreground_rect);
// Only the foreground is clipped by the scrollbar size, because we
// called CalculateRects on the root layer.
@@ -896,9 +871,8 @@ TEST_F(PaintLayerClipperTest, ScrollbarClipBehaviorParent) {
EXPECT_EQ(LayoutRect(0, 0, 200, 300), layer_bounds);
parent_paint_layer->Clipper(PaintLayer::kDoNotUseGeometryMapper)
- .CalculateRects(context, nullptr,
- LayoutRect(LayoutRect::InfiniteIntRect()), layer_bounds,
- background_rect, foreground_rect);
+ .CalculateRects(context, nullptr, nullptr, layer_bounds, background_rect,
+ foreground_rect);
// Only the foreground is clipped by the scrollbar size, because we
// called CalculateRects on the root layer.
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 362435d4420..dcf00696a24 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
@@ -9,24 +9,18 @@
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/paint/clip_path_clipper.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
-#include "third_party/blink/renderer/core/paint/filter_painter.h"
-#include "third_party/blink/renderer/core/paint/layer_clip_recorder.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/paint_layer.h"
-#include "third_party/blink/renderer/core/paint/scroll_recorder.h"
#include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
-#include "third_party/blink/renderer/core/paint/transform_3d_recorder.h"
#include "third_party/blink/renderer/platform/geometry/float_point_3d.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/compositing_recorder.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/geometry_mapper.h"
#include "third_party/blink/renderer/platform/graphics/paint/scoped_display_item_fragment.h"
#include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
#include "third_party/blink/renderer/platform/graphics/paint/subsequence_recorder.h"
-#include "third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
@@ -115,8 +109,7 @@ bool PaintLayerPainter::ShouldAdjustPaintingRoot(
// Cull rects and clips can't be propagated across a filter which moves
// pixels, since the input of the filter may be outside the cull rect/clips
// yet still result in painted output.
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- paint_layer_.HasFilterThatMovesPixels())
+ if (paint_layer_.HasFilterThatMovesPixels())
return true;
return false;
@@ -268,28 +261,16 @@ static bool ShouldRepaintSubsequence(
}
paint_layer.SetPreviousPaintDirtyRect(painting_info.paint_dirty_rect);
- // TODO(wangxianzhu): Get rid of scroll_offset_accumulation for SPv175.
- // Repaint if scroll offset accumulation changes.
- if (painting_info.scroll_offset_accumulation !=
- paint_layer.PreviousScrollOffsetAccumulationForPainting()) {
- needs_repaint = true;
- should_clear_empty_paint_phase_flags = true;
- }
- paint_layer.SetPreviousScrollOffsetAccumulationForPainting(
- painting_info.scroll_offset_accumulation);
-
return needs_repaint;
}
void PaintLayerPainter::AdjustForPaintProperties(
PaintLayerPaintingInfo& painting_info,
PaintLayerFlags& paint_flags) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
// Paint properties for transforms, composited layers or LayoutView is already
// taken care of.
// TODO(wangxianzhu): Also use this for PaintsWithTransform() and remove
- // PaintLayerWithTransform() for SPv175.
+ // PaintLayerWithTransform().
if (&paint_layer_ == painting_info.root_layer ||
paint_layer_.PaintsWithTransform(painting_info.GetGlobalPaintFlags()) ||
paint_layer_.PaintsIntoOwnOrGroupedBacking(
@@ -389,9 +370,6 @@ PaintResult PaintLayerPainter::PaintLayerContents(
(!is_painting_scrolling_content && !is_painting_mask)) &&
paint_layer_.GetLayoutObject().StyleRef().HasOutline();
- // Ensure our lists are up to date.
- paint_layer_.StackingNode()->UpdateLayerListsIfNeeded();
-
LayoutSize subpixel_accumulation =
paint_layer_.GetCompositingState() == kPaintsIntoOwnBacking
? paint_layer_.SubpixelAccumulation()
@@ -450,35 +428,9 @@ PaintResult PaintLayerPainter::PaintLayerContents(
visual_offset_from_root);
}
- base::Optional<CompositingRecorder> compositing_recorder;
- // FIXME: this should be unified further into
- // PaintLayer::paintsWithTransparency().
- bool compositing_already_applied =
- painting_info.root_layer == &paint_layer_ &&
- is_painting_overflow_contents;
- bool should_composite_for_blend_mode =
- paint_layer_.StackingNode()->IsStackingContext() &&
- paint_layer_.HasNonIsolatedDescendantWithBlendMode();
- if (!compositing_already_applied &&
- (should_composite_for_blend_mode ||
- paint_layer_.PaintsWithTransparency(
- painting_info.GetGlobalPaintFlags()))) {
- FloatRect compositing_bounds = EnclosingIntRect(paint_layer_.PaintingExtent(
- painting_info.root_layer, painting_info.sub_pixel_accumulation,
- painting_info.GetGlobalPaintFlags()));
- compositing_recorder.emplace(
- context, paint_layer_.GetLayoutObject(),
- WebCoreCompositeToSkiaComposite(
- kCompositeSourceOver,
- paint_layer_.GetLayoutObject().Style()->GetBlendMode()),
- paint_layer_.GetLayoutObject().Opacity(), &compositing_bounds);
- }
-
PaintLayerPaintingInfo local_painting_info(painting_info);
local_painting_info.sub_pixel_accumulation = subpixel_accumulation;
- sk_sp<PaintFilter> image_filter = FilterPainter::GetImageFilter(paint_layer_);
-
bool should_paint_content =
paint_layer_.HasVisibleContent() &&
// Content under a LayoutSVGHiddenContainer is auxiliary resources for
@@ -523,50 +475,14 @@ PaintResult PaintLayerPainter::PaintLayerContents(
// PaintLayerWithTransform() path.
paint_layer_for_fragments->AppendSingleFragmentIgnoringPagination(
layer_fragments, local_painting_info.root_layer,
- local_painting_info.paint_dirty_rect,
+ &local_painting_info.paint_dirty_rect,
kIgnorePlatformOverlayScrollbarSize, respect_overflow_clip,
&offset_from_root, local_painting_info.sub_pixel_accumulation);
layer_fragments[0].fragment_data = fragment->fragment_data;
- } else if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- paint_layer_.GetLayoutObject()
- .IsFixedPositionObjectInPagedMedia()) {
- PaintLayerFragments single_fragment;
- paint_layer_for_fragments->AppendSingleFragmentIgnoringPagination(
- single_fragment, local_painting_info.root_layer,
- local_painting_info.paint_dirty_rect,
- kIgnorePlatformOverlayScrollbarSize, respect_overflow_clip,
- &offset_from_root, local_painting_info.sub_pixel_accumulation);
- RepeatFixedPositionObjectInPages(single_fragment[0], painting_info,
- layer_fragments);
- } else if (image_filter && !paint_layer_.EnclosingPaginationLayer()) {
- // Clipping in the presence of filters needs to happen in two phases.
- // It proceeds like this:
- // 1. Apply overflow clip to normal-flow contents.
- // 2. Paint layer contents into the filter.
- // 3. Apply all inherited clips (including dirty rect) plus CSS clip
- // of the current layer to the filter output.
- //
- // It is critical to avoid clipping to the dirty rect or any clips
- // above the filter before applying the filter, because content which
- // appears to be clipped may affect visual output if the filter moves
- // pixels.
- //
- // #1 is applied in the lines below. #3 is applied in FilterPainter,
- // and computed just before construction of the FilterPainter.
- LayoutRect foreground_clip(LayoutRect::InfiniteIntRect());
- if (paint_layer_.GetLayoutObject().IsBox()) {
- const LayoutBox& box = ToLayoutBox(paint_layer_.GetLayoutObject());
- if (box.ShouldClipOverflow())
- foreground_clip = box.OverflowClipRect(offset_from_root);
- }
- PaintLayerFragment& fragment = layer_fragments.emplace_back();
- fragment.SetRects(
- LayoutRect(offset_from_root, LayoutSize(paint_layer_.Size())),
- LayoutRect(LayoutRect::InfiniteIntRect()), foreground_clip);
} else {
paint_layer_for_fragments->CollectFragments(
layer_fragments, local_painting_info.root_layer,
- local_painting_info.paint_dirty_rect,
+ &local_painting_info.paint_dirty_rect,
kIgnorePlatformOverlayScrollbarSize, respect_overflow_clip,
&offset_from_root, local_painting_info.sub_pixel_accumulation);
@@ -604,24 +520,6 @@ PaintResult PaintLayerPainter::PaintLayerContents(
size_t display_item_list_size_before_painting =
context.GetPaintController().NewDisplayItemList().size();
- base::Optional<FilterPainter> filter_painter;
- if (image_filter) {
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
- // Compute clips outside the filter (#3, see above for discussion).
- PaintLayerFragments filter_fragments;
- paint_layer_.AppendSingleFragmentIgnoringPagination(
- filter_fragments, local_painting_info.root_layer,
- local_painting_info.paint_dirty_rect,
- kIgnorePlatformOverlayScrollbarSize, respect_overflow_clip,
- &offset_from_root, local_painting_info.sub_pixel_accumulation);
-
- filter_painter.emplace(paint_layer_, context, offset_from_root,
- filter_fragments.IsEmpty()
- ? ClipRect()
- : filter_fragments[0].background_rect,
- local_painting_info, paint_flags);
- }
-
bool is_painting_root_layer = (&paint_layer_) == painting_info.root_layer;
bool should_paint_background =
should_paint_content && !selection_only &&
@@ -639,8 +537,7 @@ PaintResult PaintLayerPainter::PaintLayerContents(
base::Optional<ScopedPaintChunkProperties>
subsequence_forced_chunk_properties;
- if (subsequence_recorder && paint_layer_.HasSelfPaintingLayerDescendant() &&
- RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
+ if (subsequence_recorder && paint_layer_.HasSelfPaintingLayerDescendant()) {
// Prepare for forced paint chunks to ensure chunk id stability to avoid
// unnecessary full chunk raster invalidations on changed chunk ids.
// TODO(crbug.com/834606): This may be unnecessary after we refactor
@@ -700,8 +597,7 @@ PaintResult PaintLayerPainter::PaintLayerContents(
local_painting_info, paint_flags);
}
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- !is_painting_overlay_scrollbars && paint_layer_.PaintsWithFilters() &&
+ if (!is_painting_overlay_scrollbars && paint_layer_.PaintsWithFilters() &&
display_item_list_size_before_painting ==
context.GetPaintController().NewDisplayItemList().size()) {
// If a layer with filters painted nothing, we need to issue a no-op
@@ -726,24 +622,20 @@ PaintResult PaintLayerPainter::PaintLayerContents(
// for just CSS clip-path but without a CSS mask. In that case we need to
// paint a fully filled mask (which will subsequently clipped by the
// clip-path), otherwise the mask layer will be empty.
-
- base::Optional<ScopedPaintChunkProperties> path_based_clip_path_scope;
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- const auto& fragment_data =
- paint_layer_.GetLayoutObject().FirstFragment();
- auto state = fragment_data.LocalBorderBoxProperties();
- const auto* properties = fragment_data.PaintProperties();
- DCHECK(properties && properties->Mask());
- state.SetEffect(properties->Mask());
- if (properties && properties->ClipPathClip()) {
- DCHECK_EQ(properties->ClipPathClip()->Parent(), properties->MaskClip());
- state.SetClip(properties->ClipPathClip());
- }
- path_based_clip_path_scope.emplace(
- context.GetPaintController(), state,
- *paint_layer_.GetCompositedLayerMapping()->MaskLayer(),
- DisplayItem::PaintPhaseToDrawingType(PaintPhase::kClippingMask));
+ const auto& fragment_data = paint_layer_.GetLayoutObject().FirstFragment();
+ auto state = fragment_data.LocalBorderBoxProperties();
+ const auto* properties = fragment_data.PaintProperties();
+ DCHECK(properties && properties->Mask());
+ state.SetEffect(properties->Mask());
+ if (properties && properties->ClipPathClip()) {
+ DCHECK_EQ(properties->ClipPathClip()->Parent(), properties->MaskClip());
+ state.SetClip(properties->ClipPathClip());
}
+ ScopedPaintChunkProperties path_based_clip_path_scope(
+ context.GetPaintController(), state,
+ *paint_layer_.GetCompositedLayerMapping()->MaskLayer(),
+ DisplayItem::kClippingMask);
+
const GraphicsLayer* mask_layer =
paint_layer_.GetCompositedLayerMapping()->MaskLayer();
ClipRect layer_rect = LayoutRect(
@@ -774,33 +666,6 @@ PaintResult PaintLayerPainter::PaintLayerContents(
return result;
}
-bool PaintLayerPainter::NeedsToClip(
- const PaintLayerPaintingInfo& local_painting_info,
- const ClipRect& clip_rect,
- const PaintLayerFlags& paint_flags,
- const LayoutBoxModelObject& layout_object) {
- // Other clipping will be applied by property nodes directly for SPv175+.
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return false;
-
- // Always clip if painting an ancestor clipping mask layer.
- if (paint_flags & kPaintLayerPaintingAncestorClippingMaskPhase)
- return true;
-
- // Embedded objects have a clip rect when border radius is present
- // because we need it for the border radius mask with composited
- // chidren. However, we do not want to apply the clip when painting
- // the embedded content itself. Doing so would clip out the
- // border because LayoutEmbeddedObject does not obey the painting phases
- // of a normal box object.
- if (layout_object.IsLayoutEmbeddedContent() &&
- layout_object.GetCompositingState() == kPaintsIntoOwnBacking)
- return paint_flags & kPaintLayerPaintingChildClippingMaskPhase;
-
- return clip_rect.Rect() != local_painting_info.paint_dirty_rect ||
- clip_rect.HasRadius();
-}
-
bool PaintLayerPainter::AtLeastOneFragmentIntersectsDamageRect(
PaintLayerFragments& fragments,
const PaintLayerPaintingInfo& local_painting_info,
@@ -831,35 +696,6 @@ bool PaintLayerPainter::AtLeastOneFragmentIntersectsDamageRect(
return false;
}
-void PaintLayerPainter::RepeatFixedPositionObjectInPages(
- const PaintLayerFragment& single_fragment_ignored_pagination,
- const PaintLayerPaintingInfo& painting_info,
- PaintLayerFragments& layer_fragments) {
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
- DCHECK(paint_layer_.GetLayoutObject().IsFixedPositionObjectInPagedMedia());
-
- LayoutView* view = paint_layer_.GetLayoutObject().View();
- unsigned pages =
- ceilf(view->DocumentRect().Height() / view->PageLogicalHeight());
-
- // The fixed position object is offset from the top of the page, so remove
- // any scroll offset.
- LayoutPoint offset_from_root;
- paint_layer_.ConvertToLayerCoords(painting_info.root_layer, offset_from_root);
- LayoutSize offset_adjustment = paint_layer_.Location() - offset_from_root;
- layer_fragments.push_back(single_fragment_ignored_pagination);
- layer_fragments[0].pagination_offset += offset_adjustment;
- layer_fragments[0].layer_bounds.Move(offset_adjustment);
-
- LayoutPoint page_offset(LayoutUnit(), view->PageLogicalHeight());
- for (unsigned i = 1; i < pages; i++) {
- PaintLayerFragment fragment = layer_fragments[i - 1];
- fragment.pagination_offset += page_offset;
- fragment.layer_bounds.MoveBy(page_offset);
- layer_fragments.push_back(fragment);
- }
-}
-
template <typename Function>
static void ForAllFragments(GraphicsContext& context,
const PaintLayerFragments& fragments,
@@ -889,9 +725,6 @@ PaintResult PaintLayerPainter::PaintLayerWithAdjustedRoot(
PaintResult result = kFullyPainted;
PaintLayerFragments layer_fragments;
- bool is_fixed_position_object_in_paged_media =
- !RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- paint_layer_.GetLayoutObject().IsFixedPositionObjectInPagedMedia();
// This works around a bug in squashed-layer painting.
// Squashed layers paint into a backing in its compositing container's
@@ -902,7 +735,7 @@ PaintResult PaintLayerPainter::PaintLayerWithAdjustedRoot(
// appropriate ancestor clip for us, so we can simply skip it.
bool is_squashed_layer = painting_info.root_layer == &paint_layer_;
- if (is_squashed_layer || is_fixed_position_object_in_paged_media) {
+ if (is_squashed_layer) {
// We don't need to collect any fragments in the regular way here. We have
// already calculated a clip rectangle for the ancestry if it was needed,
// and clipping this layer is something that can be done further down the
@@ -910,18 +743,13 @@ PaintResult PaintLayerPainter::PaintLayerWithAdjustedRoot(
PaintLayerFragment fragment;
fragment.background_rect = painting_info.paint_dirty_rect;
fragment.fragment_data = &paint_layer_.GetLayoutObject().FirstFragment();
- if (is_fixed_position_object_in_paged_media) {
- RepeatFixedPositionObjectInPages(fragment, painting_info,
- layer_fragments);
- } else {
- layer_fragments.push_back(fragment);
- }
+ layer_fragments.push_back(fragment);
} else if (parent_layer) {
ShouldRespectOverflowClipType respect_overflow_clip =
ShouldRespectOverflowClip(paint_flags, paint_layer_.GetLayoutObject());
paint_layer_.CollectFragments(
layer_fragments, painting_info.root_layer,
- painting_info.paint_dirty_rect, kIgnorePlatformOverlayScrollbarSize,
+ &painting_info.paint_dirty_rect, kIgnorePlatformOverlayScrollbarSize,
respect_overflow_clip, nullptr, painting_info.sub_pixel_accumulation);
// PaintLayer::CollectFragments depends on the paint dirty rect in
// complicated ways. For now, always assume a partially painted output
@@ -940,18 +768,6 @@ PaintResult PaintLayerPainter::PaintLayerWithAdjustedRoot(
ForAllFragments(
context, layer_fragments, [&](const PaintLayerFragment& fragment) {
- base::Optional<LayerClipRecorder> clip_recorder;
- if (parent_layer &&
- !RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- if (NeedsToClip(painting_info, fragment.background_rect, paint_flags,
- paint_layer_.GetLayoutObject())) {
- clip_recorder.emplace(
- context, *parent_layer, DisplayItem::kClipLayerParent,
- fragment.background_rect, painting_info.root_layer,
- fragment.pagination_offset, paint_flags,
- paint_layer_.GetLayoutObject());
- }
- }
if (paint_layer_.PaintsWithTransform(
painting_info.GetGlobalPaintFlags())) {
if (PaintFragmentByApplyingTransform(context, painting_info,
@@ -991,14 +807,6 @@ PaintResult PaintLayerPainter::PaintFragmentByApplyingTransform(
new_sub_pixel_accumulation += delta - rounded_delta;
// Otherwise discard the sub-pixel remainder because paint offset can't be
// transformed by a non-translation transform.
-
- // TODO(jbroman): Put the real transform origin here, instead of using a
- // matrix with the origin baked in.
- FloatPoint3D transform_origin;
- Transform3DRecorder transform3d_recorder(
- context, paint_layer_.GetLayoutObject(),
- DisplayItem::kTransform3DElementTransform, transform, transform_origin);
-
return PaintSingleFragment(context, painting_info, paint_flags, fragment,
new_sub_pixel_accumulation);
}
@@ -1010,6 +818,11 @@ PaintResult PaintLayerPainter::PaintSingleFragment(
const PaintLayerFragment& fragment,
const LayoutSize& subpixel_accumulation) {
// Now do a paint with the root layer shifted to be us.
+
+ // We do not apply cull rect optimizations across transforms for two reasons:
+ // 1) Performance: We can optimize transform changes by not repainting.
+ // 2) Complexity: Difficulty updating clips when ancestor transforms change.
+ // For these reasons, we use an infinite dirty rect here.
PaintLayerPaintingInfo new_paint_info(
&paint_layer_, LayoutRect(LayoutRect::InfiniteIntRect()),
painting_info.GetGlobalPaintFlags(), subpixel_accumulation);
@@ -1034,54 +847,30 @@ PaintResult PaintLayerPainter::PaintChildren(
PaintResult result = kFullyPainted;
if (!paint_layer_.HasSelfPaintingLayerDescendant())
return result;
-
+ if (!paint_layer_.StackingNode())
+ return result;
#if DCHECK_IS_ON()
LayerListMutationDetector mutation_checker(paint_layer_.StackingNode());
#endif
PaintLayerStackingNodeIterator iterator(*paint_layer_.StackingNode(),
children_to_visit);
- PaintLayerStackingNode* child = iterator.Next();
+ PaintLayer* child = iterator.Next();
if (!child)
return result;
- IntSize scroll_offset_accumulation_for_children =
- painting_info.scroll_offset_accumulation;
- if (paint_layer_.GetLayoutObject().HasOverflowClip()) {
- scroll_offset_accumulation_for_children +=
- paint_layer_.GetLayoutBox()->ScrolledContentOffset();
- }
-
for (; child; child = iterator.Next()) {
// If this Layer should paint into its own backing or a grouped backing,
// that will be done via CompositedLayerMapping::PaintContents() and
// CompositedLayerMapping::DoPaintTask().
- if (child->Layer()->PaintsIntoOwnOrGroupedBacking(
+ if (child->PaintsIntoOwnOrGroupedBacking(
painting_info.GetGlobalPaintFlags()))
continue;
- if (child->Layer()->IsReplacedNormalFlowStacking())
+ if (child->IsReplacedNormalFlowStacking())
continue;
- PaintLayerPaintingInfo child_painting_info = painting_info;
- child_painting_info.scroll_offset_accumulation =
- scroll_offset_accumulation_for_children;
- // Rare case: accumulate scroll offset of non-stacking-context ancestors up
- // to m_paintLayer.
- Vector<PaintLayer*> scroll_parents;
- for (PaintLayer* parent_layer = child->Layer()->Parent();
- parent_layer != &paint_layer_; parent_layer = parent_layer->Parent()) {
- if (parent_layer->GetLayoutObject().HasOverflowClip())
- scroll_parents.push_back(parent_layer);
- }
-
- for (const auto* scroller : scroll_parents) {
- child_painting_info.scroll_offset_accumulation +=
- scroller->GetLayoutBox()->ScrolledContentOffset();
- }
-
- if (PaintLayerPainter(*child->Layer())
- .Paint(context, child_painting_info, paint_flags) ==
+ if (PaintLayerPainter(*child).Paint(context, painting_info, paint_flags) ==
kMayBeClippedByPaintDirtyRect)
result = kMayBeClippedByPaintDirtyRect;
}
@@ -1100,38 +889,14 @@ void PaintLayerPainter::PaintOverflowControlsForFragments(
ForAllFragments(
context, layer_fragments, [&](const PaintLayerFragment& fragment) {
- base::Optional<ScopedPaintChunkProperties>
- fragment_paint_chunk_properties;
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- fragment_paint_chunk_properties.emplace(
- context.GetPaintController(),
- fragment.fragment_data->LocalBorderBoxProperties(), paint_layer_,
- DisplayItem::kScrollOverflowControls);
- }
+ ScopedPaintChunkProperties fragment_paint_chunk_properties(
+ context.GetPaintController(),
+ fragment.fragment_data->LocalBorderBoxProperties(), paint_layer_,
+ DisplayItem::kOverflowControls);
// We need to apply the same clips and transforms that
// paintFragmentWithPhase would have.
LayoutRect cull_rect = fragment.background_rect.Rect();
-
- base::Optional<LayerClipRecorder> clip_recorder;
- if (NeedsToClip(painting_info, fragment.background_rect, paint_flags,
- paint_layer_.GetLayoutObject())) {
- clip_recorder.emplace(
- context, paint_layer_, DisplayItem::kClipLayerOverflowControls,
- fragment.background_rect, painting_info.root_layer,
- fragment.pagination_offset, paint_flags,
- paint_layer_.GetLayoutObject());
- }
-
- base::Optional<ScrollRecorder> scroll_recorder;
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- !painting_info.scroll_offset_accumulation.IsZero()) {
- cull_rect.Move(painting_info.scroll_offset_accumulation);
- scroll_recorder.emplace(context, paint_layer_.GetLayoutObject(),
- DisplayItem::kScrollOverflowControls,
- painting_info.scroll_offset_accumulation);
- }
-
PaintInfo paint_info(
context, PixelSnappedIntRect(cull_rect),
PaintPhase::kSelfBlockBackgroundOnly,
@@ -1155,106 +920,35 @@ void PaintLayerPainter::PaintFragmentWithPhase(
GraphicsContext& context,
const ClipRect& clip_rect,
const PaintLayerPaintingInfo& painting_info,
- PaintLayerFlags paint_flags,
- ClipState clip_state) {
+ PaintLayerFlags paint_flags) {
DCHECK(paint_layer_.IsSelfPaintingLayer());
- base::Optional<ScopedPaintChunkProperties> fragment_paint_chunk_properties;
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- DCHECK(phase != PaintPhase::kClippingMask);
- auto chunk_properties = fragment.fragment_data->LocalBorderBoxProperties();
- if (phase == PaintPhase::kMask) {
- const auto* properties = fragment.fragment_data->PaintProperties();
- DCHECK(properties && properties->Mask());
- chunk_properties.SetEffect(properties->Mask());
- // Special case for SPv1 composited mask layer. Path-based clip-path
- // is only applies to the mask chunk, but not to the layer property
- // or local box box property.
- if (properties->ClipPathClip() &&
- properties->ClipPathClip()->Parent() == properties->MaskClip()) {
- chunk_properties.SetClip(properties->ClipPathClip());
- }
+ auto chunk_properties = fragment.fragment_data->LocalBorderBoxProperties();
+ if (phase == PaintPhase::kMask) {
+ const auto* properties = fragment.fragment_data->PaintProperties();
+ DCHECK(properties && properties->Mask());
+ chunk_properties.SetEffect(properties->Mask());
+ // Special case for SPv1 composited mask layer. Path-based clip-path
+ // is only applies to the mask chunk, but not to the layer property
+ // or local box box property.
+ if (properties->ClipPathClip() &&
+ properties->ClipPathClip()->Parent() == properties->MaskClip()) {
+ chunk_properties.SetClip(properties->ClipPathClip());
}
- fragment_paint_chunk_properties.emplace(
- context.GetPaintController(), chunk_properties, paint_layer_,
- DisplayItem::PaintPhaseToDrawingType(phase));
- }
-
- DisplayItemClient* client = &paint_layer_.GetLayoutObject();
- base::Optional<LayerClipRecorder> clip_recorder;
- if (clip_state != kHasClipped &&
- NeedsToClip(painting_info, clip_rect, paint_flags,
- paint_layer_.GetLayoutObject())) {
- DisplayItem::Type clip_type =
- DisplayItem::PaintPhaseToClipLayerFragmentType(phase);
- LayerClipRecorder::BorderRadiusClippingRule clipping_rule;
- switch (phase) {
- case PaintPhase::kSelfBlockBackgroundOnly: // Background painting will
- // handle clipping to self.
- case PaintPhase::kSelfOutlineOnly:
- case PaintPhase::kMask: // Mask painting will handle clipping to self.
- clipping_rule = LayerClipRecorder::kDoNotIncludeSelfForBorderRadius;
- break;
- case PaintPhase::kClippingMask:
- if (paint_flags & kPaintLayerPaintingAncestorClippingMaskPhase) {
- // The ancestor is the thing that needs to clip, so do not include
- // this layer's clips.
- clipping_rule = LayerClipRecorder::kDoNotIncludeSelfForBorderRadius;
- // The ancestor clipping mask may have a larger visual rect than
- // paint_layer_, since it includes ancestor clips.
- client = paint_layer_.GetCompositedLayerMapping()
- ->AncestorClippingMaskLayer();
- break;
- }
- FALLTHROUGH;
- default:
- clipping_rule = LayerClipRecorder::kIncludeSelfForBorderRadius;
- break;
- }
- clip_recorder.emplace(context, paint_layer_, clip_type, clip_rect,
- painting_info.root_layer, fragment.pagination_offset,
- paint_flags, *client, clipping_rule);
- }
-
- // If we are painting a mask for any reason and we have already processed the
- // clips, there is no need to go through the remaining painting pipeline.
- // We know that the mask just needs the area bounded by the clip rects to be
- // filled with black.
- if (clip_recorder && phase == PaintPhase::kClippingMask) {
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
- FillMaskingFragment(context, clip_rect, *client);
- return;
}
+ ScopedPaintChunkProperties fragment_paint_chunk_properties(
+ context.GetPaintController(), chunk_properties, paint_layer_,
+ DisplayItem::PaintPhaseToDrawingType(phase));
LayoutRect new_cull_rect(clip_rect.Rect());
- base::Optional<ScrollRecorder> scroll_recorder;
- LayoutPoint paint_offset = -paint_layer_.LayoutBoxLocation();
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- paint_offset += fragment.fragment_data->PaintOffset();
- // For SPv175+, we paint in the containing transform node's space. Now
- // |new_cull_rect| is in the pixel-snapped border box space of
- // |painting_info.root_layer|. Adjust it to the correct space.
- // |paint_offset| is already in the correct space.
- new_cull_rect.MoveBy(
- RoundedIntPoint(painting_info.root_layer->GetLayoutObject()
- .FirstFragment()
- .PaintOffset()));
- } else {
- paint_offset += ToSize(fragment.layer_bounds.Location());
- if (!painting_info.scroll_offset_accumulation.IsZero()) {
- // As a descendant of the root layer, m_paintLayer's painting is not
- // controlled by the ScrollRecorders created by BlockPainter of the
- // ancestor layers up to the root layer, so we need to issue
- // ScrollRecorder for this layer seperately, with the scroll offset
- // accumulated from the root layer to the parent of this layer, to get the
- // same result as ScrollRecorder in BlockPainter.
- paint_offset += painting_info.scroll_offset_accumulation;
-
- new_cull_rect.Move(painting_info.scroll_offset_accumulation);
- scroll_recorder.emplace(context, paint_layer_.GetLayoutObject(), phase,
- painting_info.scroll_offset_accumulation);
- }
- }
+ // We paint in the containing transform node's space. Now |new_cull_rect| is
+ // in the pixel-snapped border box space of |painting_info.root_layer|.
+ // Adjust it to the correct space. |paint_offset| is already in the correct
+ // space.
+ new_cull_rect.MoveBy(
+ RoundedIntPoint(painting_info.root_layer->GetLayoutObject()
+ .FirstFragment()
+ .PaintOffset()));
PaintInfo paint_info(context, PixelSnappedIntRect(new_cull_rect), phase,
painting_info.GetGlobalPaintFlags(), paint_flags,
&painting_info.root_layer->GetLayoutObject(),
@@ -1267,7 +961,7 @@ void PaintLayerPainter::PaintFragmentWithPhase(
.GetDocument()
.DidLayoutWithPendingStylesheets());
- paint_layer_.GetLayoutObject().Paint(paint_info, paint_offset);
+ paint_layer_.GetLayoutObject().Paint(paint_info);
}
void PaintLayerPainter::PaintBackgroundForFragments(
@@ -1279,8 +973,7 @@ void PaintLayerPainter::PaintBackgroundForFragments(
context, layer_fragments, [&](const PaintLayerFragment& fragment) {
PaintFragmentWithPhase(PaintPhase::kSelfBlockBackgroundOnly, fragment,
context, fragment.background_rect,
- local_painting_info, paint_flags,
- kHasNotClipped);
+ local_painting_info, paint_flags);
});
}
@@ -1291,26 +984,10 @@ void PaintLayerPainter::PaintForegroundForFragments(
bool selection_only,
bool force_paint_chunks,
PaintLayerFlags paint_flags) {
- // Optimize clipping for the single fragment case.
- bool should_clip = layer_fragments.size() == 1 &&
- !layer_fragments[0].foreground_rect.IsEmpty();
- ClipState clip_state = kHasNotClipped;
- base::Optional<LayerClipRecorder> clip_recorder;
- if (should_clip &&
- NeedsToClip(local_painting_info, layer_fragments[0].foreground_rect,
- paint_flags, paint_layer_.GetLayoutObject())) {
- clip_recorder.emplace(
- context, paint_layer_, DisplayItem::kClipLayerForeground,
- layer_fragments[0].foreground_rect, local_painting_info.root_layer,
- layer_fragments[0].pagination_offset, paint_flags,
- paint_layer_.GetLayoutObject());
- clip_state = kHasClipped;
- }
-
if (selection_only) {
- PaintForegroundForFragmentsWithPhase(
- PaintPhase::kSelection, layer_fragments, context, local_painting_info,
- paint_flags, clip_state);
+ PaintForegroundForFragmentsWithPhase(PaintPhase::kSelection,
+ layer_fragments, context,
+ local_painting_info, paint_flags);
} else {
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() ||
paint_layer_.NeedsPaintPhaseDescendantBlockBackgrounds()) {
@@ -1322,7 +999,7 @@ void PaintLayerPainter::PaintForegroundForFragments(
context.GetPaintController().NewDisplayItemList().size();
PaintForegroundForFragmentsWithPhase(
PaintPhase::kDescendantBlockBackgroundsOnly, layer_fragments, context,
- local_painting_info, paint_flags, clip_state);
+ local_painting_info, paint_flags);
// Don't set the empty flag if we are not painting the whole background.
if (!(paint_flags & kPaintLayerPaintingSkipRootBackground)) {
bool phase_is_empty =
@@ -1345,7 +1022,7 @@ void PaintLayerPainter::PaintForegroundForFragments(
context.GetPaintController().NewDisplayItemList().size();
PaintForegroundForFragmentsWithPhase(PaintPhase::kFloat, layer_fragments,
context, local_painting_info,
- paint_flags, clip_state);
+ paint_flags);
bool phase_is_empty =
context.GetPaintController().NewDisplayItemList().size() ==
size_before;
@@ -1358,17 +1035,17 @@ void PaintLayerPainter::PaintForegroundForFragments(
paint_layer_, DisplayItem::kLayerChunkForeground);
}
- PaintForegroundForFragmentsWithPhase(
- PaintPhase::kForeground, layer_fragments, context, local_painting_info,
- paint_flags, clip_state);
+ PaintForegroundForFragmentsWithPhase(PaintPhase::kForeground,
+ layer_fragments, context,
+ local_painting_info, paint_flags);
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() ||
paint_layer_.NeedsPaintPhaseDescendantOutlines()) {
size_t size_before =
context.GetPaintController().NewDisplayItemList().size();
- PaintForegroundForFragmentsWithPhase(
- PaintPhase::kDescendantOutlinesOnly, layer_fragments, context,
- local_painting_info, paint_flags, clip_state);
+ PaintForegroundForFragmentsWithPhase(PaintPhase::kDescendantOutlinesOnly,
+ layer_fragments, context,
+ local_painting_info, paint_flags);
bool phase_is_empty =
context.GetPaintController().NewDisplayItemList().size() ==
size_before;
@@ -1384,14 +1061,13 @@ void PaintLayerPainter::PaintForegroundForFragmentsWithPhase(
const PaintLayerFragments& layer_fragments,
GraphicsContext& context,
const PaintLayerPaintingInfo& local_painting_info,
- PaintLayerFlags paint_flags,
- ClipState clip_state) {
+ PaintLayerFlags paint_flags) {
ForAllFragments(
context, layer_fragments, [&](const PaintLayerFragment& fragment) {
if (!fragment.foreground_rect.IsEmpty()) {
PaintFragmentWithPhase(phase, fragment, context,
fragment.foreground_rect, local_painting_info,
- paint_flags, clip_state);
+ paint_flags);
}
});
}
@@ -1406,8 +1082,7 @@ void PaintLayerPainter::PaintSelfOutlineForFragments(
if (!fragment.background_rect.IsEmpty()) {
PaintFragmentWithPhase(PaintPhase::kSelfOutlineOnly, fragment,
context, fragment.background_rect,
- local_painting_info, paint_flags,
- kHasNotClipped);
+ local_painting_info, paint_flags);
}
});
}
@@ -1417,12 +1092,12 @@ void PaintLayerPainter::PaintMaskForFragments(
GraphicsContext& context,
const PaintLayerPaintingInfo& local_painting_info,
PaintLayerFlags paint_flags) {
- ForAllFragments(
- context, layer_fragments, [&](const PaintLayerFragment& fragment) {
- PaintFragmentWithPhase(PaintPhase::kMask, fragment, context,
- fragment.background_rect, local_painting_info,
- paint_flags, kHasNotClipped);
- });
+ ForAllFragments(context, layer_fragments,
+ [&](const PaintLayerFragment& fragment) {
+ PaintFragmentWithPhase(PaintPhase::kMask, fragment, context,
+ fragment.background_rect,
+ local_painting_info, paint_flags);
+ });
}
void PaintLayerPainter::PaintAncestorClippingMask(
@@ -1430,26 +1105,18 @@ void PaintLayerPainter::PaintAncestorClippingMask(
GraphicsContext& context,
const PaintLayerPaintingInfo& local_painting_info,
PaintLayerFlags paint_flags) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- const DisplayItemClient& client =
- *paint_layer_.GetCompositedLayerMapping()->AncestorClippingMaskLayer();
- const auto& layer_fragment = paint_layer_.GetLayoutObject().FirstFragment();
- auto state = layer_fragment.PreEffectProperties();
- // This is a hack to incorporate mask-based clip-path.
- // See CompositingLayerPropertyUpdater.cpp about AncestorClippingMaskLayer.
- state.SetEffect(layer_fragment.PreFilter());
- ScopedPaintChunkProperties properties(
- context.GetPaintController(), state, client,
- DisplayItem::PaintPhaseToDrawingType(PaintPhase::kClippingMask));
- ClipRect mask_rect = fragment.background_rect;
- mask_rect.MoveBy(layer_fragment.PaintOffset());
- FillMaskingFragment(context, mask_rect, client);
- return;
- }
-
- PaintFragmentWithPhase(PaintPhase::kClippingMask, fragment, context,
- fragment.background_rect, local_painting_info,
- paint_flags, kHasNotClipped);
+ const DisplayItemClient& client =
+ *paint_layer_.GetCompositedLayerMapping()->AncestorClippingMaskLayer();
+ const auto& layer_fragment = paint_layer_.GetLayoutObject().FirstFragment();
+ auto state = layer_fragment.PreEffectProperties();
+ // This is a hack to incorporate mask-based clip-path.
+ // See CompositingLayerPropertyUpdater.cpp about AncestorClippingMaskLayer.
+ state.SetEffect(layer_fragment.PreFilter());
+ ScopedPaintChunkProperties properties(context.GetPaintController(), state,
+ client, DisplayItem::kClippingMask);
+ ClipRect mask_rect = fragment.background_rect;
+ mask_rect.MoveBy(layer_fragment.PaintOffset());
+ FillMaskingFragment(context, mask_rect, client);
}
void PaintLayerPainter::PaintChildClippingMaskForFragments(
@@ -1457,35 +1124,25 @@ void PaintLayerPainter::PaintChildClippingMaskForFragments(
GraphicsContext& context,
const PaintLayerPaintingInfo& local_painting_info,
PaintLayerFlags paint_flags) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- const DisplayItemClient& client =
- *paint_layer_.GetCompositedLayerMapping()->ChildClippingMaskLayer();
- ForAllFragments(
- context, layer_fragments, [&](const PaintLayerFragment& fragment) {
- // Use the LocalBorderboxProperties as a starting point to ensure that
- // we don't include the scroll offset when painting the mask layer.
- auto state = fragment.fragment_data->LocalBorderBoxProperties();
- // This is a hack to incorporate mask-based clip-path.
- // See CompositingLayerPropertyUpdater.cpp about
- // ChildClippingMaskLayer.
- state.SetEffect(fragment.fragment_data->PreFilter());
- // Update the clip to be the ContentsProperties clip, since it
- // includes the InnerBorderRadiusClip.
- state.SetClip(fragment.fragment_data->ContentsProperties().Clip());
- ScopedPaintChunkProperties fragment_paint_chunk_properties(
- context.GetPaintController(), state, client,
- DisplayItem::PaintPhaseToDrawingType(PaintPhase::kClippingMask));
- ClipRect mask_rect = fragment.background_rect;
- FillMaskingFragment(context, mask_rect, client);
- });
- return;
- }
-
+ const DisplayItemClient& client =
+ *paint_layer_.GetCompositedLayerMapping()->ChildClippingMaskLayer();
ForAllFragments(
context, layer_fragments, [&](const PaintLayerFragment& fragment) {
- PaintFragmentWithPhase(PaintPhase::kClippingMask, fragment, context,
- fragment.foreground_rect, local_painting_info,
- paint_flags, kHasNotClipped);
+ // Use the LocalBorderboxProperties as a starting point to ensure that
+ // we don't include the scroll offset when painting the mask layer.
+ auto state = fragment.fragment_data->LocalBorderBoxProperties();
+ // This is a hack to incorporate mask-based clip-path.
+ // See CompositingLayerPropertyUpdater.cpp about
+ // ChildClippingMaskLayer.
+ state.SetEffect(fragment.fragment_data->PreFilter());
+ // Update the clip to be the ContentsProperties clip, since it
+ // includes the InnerBorderRadiusClip.
+ state.SetClip(fragment.fragment_data->ContentsProperties().Clip());
+ ScopedPaintChunkProperties fragment_paint_chunk_properties(
+ context.GetPaintController(), state, client,
+ DisplayItem::kClippingMask);
+ ClipRect mask_rect = fragment.background_rect;
+ FillMaskingFragment(context, mask_rect, client);
});
}
@@ -1507,12 +1164,11 @@ void PaintLayerPainter::PaintOverlayScrollbars(
void PaintLayerPainter::FillMaskingFragment(GraphicsContext& context,
const ClipRect& clip_rect,
const DisplayItemClient& client) {
- DisplayItem::Type type =
- DisplayItem::PaintPhaseToDrawingType(PaintPhase::kClippingMask);
- if (DrawingRecorder::UseCachedDrawingIfPossible(context, client, type))
+ if (DrawingRecorder::UseCachedDrawingIfPossible(context, client,
+ DisplayItem::kClippingMask))
return;
- DrawingRecorder recorder(context, client, type);
+ DrawingRecorder recorder(context, client, DisplayItem::kClippingMask);
IntRect snapped_clip_rect = PixelSnappedIntRect(clip_rect.Rect());
context.FillRect(snapped_clip_rect, Color::kBlack);
}
@@ -1520,7 +1176,6 @@ void PaintLayerPainter::FillMaskingFragment(GraphicsContext& context,
// Generate a no-op DrawingDisplayItem to ensure a non-empty chunk for the
// filter without content.
void PaintLayerPainter::PaintEmptyContentForFilters(GraphicsContext& context) {
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
DCHECK(paint_layer_.PaintsWithFilters());
ScopedPaintChunkProperties paint_chunk_properties(
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.h b/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.h
index fe3cd61a6a8..7b7c47fc956 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_painter.h
@@ -18,7 +18,6 @@ class ComputedStyle;
class DisplayItemClient;
class PaintLayer;
class GraphicsContext;
-class LayoutBoxModelObject;
class LayoutPoint;
// This class is responsible for painting self-painting PaintLayer.
@@ -63,21 +62,9 @@ class CORE_EXPORT PaintLayerPainter {
private:
friend class PaintLayerPainterTest;
- enum ClipState { kHasNotClipped, kHasClipped };
-
bool ShouldAdjustPaintingRoot(const PaintLayerPaintingInfo& painting_info,
PaintLayerFlags paint_flags);
- // "For paged media, boxes with fixed positions are repeated on every page."
- // https://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#fixed-positioning
- // Repeats singleFragmentIgnoredPagination of the fixed-position object in
- // each page, with paginationOffset and layerBounds adjusted for each page.
- // TODO(wangxianzhu): Fold this into PaintLayer::collectFragments().
- void RepeatFixedPositionObjectInPages(
- const PaintLayerFragment& single_fragment_ignored_pagination,
- const PaintLayerPaintingInfo&,
- PaintLayerFragments&);
-
PaintResult PaintLayerContentsCompositingAllPhases(
GraphicsContext&,
const PaintLayerPaintingInfo&,
@@ -110,8 +97,7 @@ class CORE_EXPORT PaintLayerPainter {
GraphicsContext&,
const ClipRect&,
const PaintLayerPaintingInfo&,
- PaintLayerFlags,
- ClipState);
+ PaintLayerFlags);
void PaintBackgroundForFragments(
const PaintLayerFragments&,
GraphicsContext&,
@@ -127,8 +113,7 @@ class CORE_EXPORT PaintLayerPainter {
const PaintLayerFragments&,
GraphicsContext&,
const PaintLayerPaintingInfo&,
- PaintLayerFlags,
- ClipState);
+ PaintLayerFlags);
void PaintSelfOutlineForFragments(const PaintLayerFragments&,
GraphicsContext&,
const PaintLayerPaintingInfo&,
@@ -156,11 +141,6 @@ class CORE_EXPORT PaintLayerPainter {
void PaintEmptyContentForFilters(GraphicsContext&);
- static bool NeedsToClip(const PaintLayerPaintingInfo& local_painting_info,
- const ClipRect&,
- const PaintLayerFlags&,
- const LayoutBoxModelObject&);
-
void AdjustForPaintProperties(PaintLayerPaintingInfo&, PaintLayerFlags&);
PaintLayer& paint_layer_;
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 7e3db2578e4..1890a0da8a1 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
@@ -22,8 +22,8 @@ class PaintLayerPainterTest : public PaintControllerPaintTest {
void ExpectPaintedOutputInvisible(const char* element_name,
bool expected_value) {
// The optimization to skip painting for effectively-invisible content is
- // limited to SPv1.
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
+ // limited to pre-SPv2.
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
return;
PaintLayer* target_layer =
@@ -35,9 +35,8 @@ class PaintLayerPainterTest : public PaintControllerPaintTest {
.PaintedOutputInvisible(target_layer->GetLayoutObject().StyleRef(),
painting_info.GetGlobalPaintFlags());
EXPECT_EQ(expected_value, invisible)
- << "Failed painted output visibility [spv175_enabled="
- << RuntimeEnabledFeatures::SlimmingPaintV175Enabled()
- << ", expected=" << expected_value << ", actual=" << invisible << "].";
+ << "Failed painted output visibility, expected=" << expected_value
+ << ", actual=" << invisible << "].";
}
PaintController& MainGraphicsLayerPaintController() {
@@ -153,8 +152,7 @@ TEST_P(PaintLayerPainterTest, CachedSubsequence) {
other_chunk_state));
};
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- check_chunks();
+ check_chunks();
ToHTMLElement(content1.GetNode())
->setAttribute(HTMLNames::styleAttr,
@@ -164,7 +162,7 @@ TEST_P(PaintLayerPainterTest, CachedSubsequence) {
EXPECT_TRUE(PaintWithoutCommit());
EXPECT_EQ(6, NumCachedNewItems());
- Commit();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(
RootPaintController().GetDisplayItemList(), 7,
@@ -177,8 +175,7 @@ TEST_P(PaintLayerPainterTest, CachedSubsequence) {
TestDisplayItem(filler2, kBackgroundType));
// We should still have the paint chunks forced by the cached subsequences.
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- check_chunks();
+ check_chunks();
}
TEST_P(PaintLayerPainterTest, CachedSubsequenceOnInterestRectChange) {
@@ -256,7 +253,7 @@ TEST_P(PaintLayerPainterTest, CachedSubsequenceOnInterestRectChange) {
// pair.
EXPECT_EQ(5, NumCachedNewItems());
- Commit();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(
RootPaintController().GetDisplayItemList(), 6,
@@ -337,7 +334,7 @@ TEST_P(PaintLayerPainterTest,
EXPECT_TRUE(PaintWithoutCommit(&interest_rect));
EXPECT_EQ(4, NumCachedNewItems());
- Commit();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(
RootPaintController().GetDisplayItemList(), 5,
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_painting_info.h b/chromium/third_party/blink/renderer/core/paint/paint_layer_painting_info.h
index ea5a9d683dc..1adbacd3d11 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_painting_info.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_painting_info.h
@@ -96,7 +96,6 @@ struct PaintLayerPaintingInfo {
const PaintLayer* root_layer;
LayoutRect paint_dirty_rect; // relative to rootLayer;
LayoutSize sub_pixel_accumulation;
- IntSize scroll_offset_accumulation;
private:
const GlobalPaintFlags global_paint_flags_;
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 ec6d6ca5d58..ee72a82c200 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
@@ -44,12 +44,14 @@
#include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
+#include "base/numerics/checked_math.h"
#include "base/single_thread_task_runner.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_scroll_into_view_params.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
+#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
#include "third_party/blink/renderer/core/css/pseudo_style_request.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
@@ -84,13 +86,15 @@
#include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h"
#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/find_paint_offset_and_visual_rect_needing_update.h"
+#include "third_party/blink/renderer/core/paint/paint_invalidator.h"
#include "third_party/blink/renderer/core/paint/paint_layer_fragment.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/scroll/scroll_alignment.h"
#include "third_party/blink/renderer/platform/scroll/scroll_animator_base.h"
#include "third_party/blink/renderer/platform/scroll/scrollbar_theme.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
+#include "third_party/blink/renderer/platform/scroll/smooth_scroll_sequencer.h"
namespace blink {
@@ -121,8 +125,6 @@ const int kResizerControlExpandRatioForTouch = 2;
PaintLayerScrollableArea::PaintLayerScrollableArea(PaintLayer& layer)
: layer_(&layer),
- next_topmost_scroll_child_(nullptr),
- topmost_scroll_child_(nullptr),
in_resize_mode_(false),
scrolls_overflow_(false),
in_overflow_relayout_(false),
@@ -134,11 +136,14 @@ PaintLayerScrollableArea::PaintLayerScrollableArea(PaintLayer& layer)
needs_relayout_(false),
had_horizontal_scrollbar_before_relayout_(false),
had_vertical_scrollbar_before_relayout_(false),
+ scroll_origin_changed_(false),
scrollbar_manager_(*this),
scroll_corner_(nullptr),
resizer_(nullptr),
scroll_anchor_(this),
- non_composited_main_thread_scrolling_reasons_(0) {
+ non_composited_main_thread_scrolling_reasons_(0),
+ horizontal_scrollbar_previously_was_overlay_(false),
+ vertical_scrollbar_previously_was_overlay_(false) {
Node* node = GetLayoutBox()->GetNode();
if (node && node->IsElementNode()) {
// We save and restore only the scrollOffset as the other scroll values are
@@ -156,8 +161,8 @@ PaintLayerScrollableArea::~PaintLayerScrollableArea() {
DCHECK(HasBeenDisposed());
}
-void PaintLayerScrollableArea::DidScroll(const gfx::ScrollOffset& offset) {
- ScrollableArea::DidScroll(offset);
+void PaintLayerScrollableArea::DidScroll(const FloatPoint& position) {
+ ScrollableArea::DidScroll(position);
// This should be alive if it receives composited scroll callbacks.
CHECK(!HasBeenDisposed());
}
@@ -216,16 +221,6 @@ void PaintLayerScrollableArea::Dispose() {
if (SmoothScrollSequencer* sequencer = GetSmoothScrollSequencer())
sequencer->DidDisposeScrollableArea(*this);
- {
- // Here using the stale compositing data is in fact what we want to do
- // because the graphics layer which hasn't been removed yet may be used in
- // the meantime to try to deliver scroll related updates.
- DisableCompositingQueryAsserts disabler;
- GraphicsLayer* graphics_layer = LayerForScrolling();
- if (graphics_layer)
- graphics_layer->ScrollableAreaDisposed();
- }
-
layer_ = nullptr;
}
@@ -239,24 +234,11 @@ void PaintLayerScrollableArea::Trace(blink::Visitor* visitor) {
ScrollableArea::Trace(visitor);
}
-void PaintLayerScrollableArea::CalculateScrollbarModes(
- ScrollbarMode& h_mode,
- ScrollbarMode& v_mode) const {
- DCHECK(GetLayoutBox()->IsLayoutView());
-
- // FrameViewAutoSizeInfo manually controls the appearance of the main frame's
- // scrollbars so defer to those if we're in AutoSize mode.
- if (AutosizeVerticalScrollbarMode() != kScrollbarAuto ||
- AutosizeHorizontalScrollbarMode() != kScrollbarAuto) {
- h_mode = AutosizeHorizontalScrollbarMode();
- v_mode = AutosizeVerticalScrollbarMode();
- return;
- }
-
- ToLayoutView(GetLayoutBox())->CalculateScrollbarModes(h_mode, v_mode);
+bool PaintLayerScrollableArea::IsThrottled() const {
+ return GetLayoutBox()->GetFrame()->ShouldThrottleRendering();
}
-ChromeClient* PaintLayerScrollableArea::GetChromeClient() const {
+PlatformChromeClient* PaintLayerScrollableArea::GetChromeClient() const {
if (HasBeenDisposed())
return nullptr;
if (Page* page = GetLayoutBox()->GetFrame()->GetPage())
@@ -681,9 +663,10 @@ IntRect PaintLayerScrollableArea::VisibleContentRect(
GetLayoutBox()->Location()));
}
-LayoutRect PaintLayerScrollableArea::VisibleScrollSnapportRect() const {
+LayoutRect PaintLayerScrollableArea::VisibleScrollSnapportRect(
+ IncludeScrollbarsInRect scrollbar_inclusion) const {
const ComputedStyle* style = GetLayoutBox()->Style();
- LayoutRect layout_content_rect(LayoutContentRect(kExcludeScrollbars));
+ LayoutRect layout_content_rect(LayoutContentRect(scrollbar_inclusion));
layout_content_rect.MoveBy(LayoutPoint(-ScrollOrigin()));
LayoutRectOutsets padding(MinimumValueForLength(style->ScrollPaddingTop(),
layout_content_rect.Height()),
@@ -707,10 +690,6 @@ void PaintLayerScrollableArea::ContentsResized() {
GetLayoutBox()->SetNeedsPaintPropertyUpdate();
}
-bool PaintLayerScrollableArea::IsScrollable() const {
- return ScrollsOverflow();
-}
-
IntPoint PaintLayerScrollableArea::LastKnownMousePosition() const {
return GetLayoutBox()->GetFrame() ? GetLayoutBox()
->GetFrame()
@@ -733,7 +712,7 @@ bool PaintLayerScrollableArea::ShouldSuspendScrollAnimations() const {
LayoutView* view = GetLayoutBox()->View();
if (!view)
return true;
- return view->GetFrameView()->ShouldSuspendScrollAnimations();
+ return !GetLayoutBox()->GetDocument().LoadEventFinished();
}
void PaintLayerScrollableArea::ScrollbarVisibilityChanged() {
@@ -760,13 +739,20 @@ bool PaintLayerScrollableArea::ScrollbarsCanBeActive() const {
LayoutView* view = GetLayoutBox()->View();
if (!view)
return false;
- return view->GetFrameView()->ScrollbarsCanBeActive();
+
+ // TODO(szager): This conditional is weird and likely obsolete. Originally
+ // added in commit eb0d49caaee2b275ff524d3945a74e8d9180eb7d.
+ LocalFrameView* frame_view = view->GetFrameView();
+ if (frame_view != frame_view->GetFrame().View())
+ return false;
+
+ return !!frame_view->GetFrame().GetDocument();
}
IntRect PaintLayerScrollableArea::ScrollableAreaBoundingBox() const {
if (LocalFrame* frame = GetLayoutBox()->GetFrame()) {
if (LocalFrameView* local_root = frame->LocalFrameRoot().View()) {
- return local_root->RootFrameToDocument(frame->View()->AbsoluteToRootFrame(
+ return local_root->RootFrameToDocument(frame->View()->ConvertToRootFrame(
GetLayoutBox()->AbsoluteBoundingBoxRect(0)));
}
}
@@ -804,7 +790,7 @@ bool PaintLayerScrollableArea::UserInputScrollable(
ScrollbarMode h_mode;
ScrollbarMode v_mode;
- CalculateScrollbarModes(h_mode, v_mode);
+ ToLayoutView(GetLayoutBox())->CalculateScrollbarModes(h_mode, v_mode);
ScrollbarMode mode =
(orientation == kHorizontalScrollbar) ? h_mode : v_mode;
return mode == kScrollbarAuto || mode == kScrollbarAlwaysOn;
@@ -823,12 +809,16 @@ bool PaintLayerScrollableArea::ShouldPlaceVerticalScrollbarOnLeft() const {
}
int PaintLayerScrollableArea::PageStep(ScrollbarOrientation orientation) const {
- int length =
- (orientation == kHorizontalScrollbar) ? VisibleWidth() : VisibleHeight();
+ // Paging scroll operations should take scroll-padding into account [1]. So we
+ // use the snapport rect to calculate the page step instead of the visible
+ // rect.
+ // [1] https://drafts.csswg.org/css-scroll-snap/#scroll-padding
+ IntSize snapport_size = VisibleScrollSnapportRect().PixelSnappedSize();
+ int length = (orientation == kHorizontalScrollbar) ? snapport_size.Width()
+ : snapport_size.Height();
int min_page_step = static_cast<float>(length) *
ScrollableArea::MinFractionToStepWhenPaging();
int page_step = max(min_page_step, length - MaxOverlapBetweenPages());
-
return max(page_step, 1);
}
@@ -866,8 +856,11 @@ void PaintLayerScrollableArea::UpdateScrollOrigin() {
LayoutRect scrollable_overflow(overflow_rect_);
scrollable_overflow.Move(-GetLayoutBox()->BorderLeft(),
-GetLayoutBox()->BorderTop());
- SetScrollOrigin(-scrollable_overflow.PixelSnappedLocation() +
- GetLayoutBox()->OriginAdjustmentForScrollbars());
+ IntPoint new_origin(-scrollable_overflow.PixelSnappedLocation() +
+ GetLayoutBox()->OriginAdjustmentForScrollbars());
+ if (new_origin != scroll_origin_)
+ scroll_origin_changed_ = true;
+ scroll_origin_ = new_origin;
}
void PaintLayerScrollableArea::UpdateScrollDimensions() {
@@ -1039,6 +1032,9 @@ void PaintLayerScrollableArea::UpdateAfterLayout() {
}
void PaintLayerScrollableArea::ClampScrollOffsetAfterOverflowChange() {
+ if (HasBeenDisposed())
+ return;
+
// If a vertical scrollbar was removed, the min/max scroll offsets may have
// changed, so the scroll offsets needs to be clamped. If the scroll offset
// did not change, but the scroll origin *did* change, we still need to notify
@@ -1229,13 +1225,8 @@ void PaintLayerScrollableArea::UpdateAfterStyleChange(
UpdateResizerStyle(old_style);
}
-bool PaintLayerScrollableArea::UpdateAfterCompositingChange() {
+void PaintLayerScrollableArea::UpdateAfterCompositingChange() {
Layer()->UpdateScrollingStateAfterCompositingChange();
- const bool layers_changed =
- topmost_scroll_child_ != next_topmost_scroll_child_;
- topmost_scroll_child_ = next_topmost_scroll_child_;
- next_topmost_scroll_child_ = nullptr;
- return layers_changed;
}
void PaintLayerScrollableArea::UpdateAfterOverflowRecalc() {
@@ -1340,43 +1331,63 @@ IntSize PaintLayerScrollableArea::ScrollbarOffset(
}
static inline const LayoutObject& ScrollbarStyleSource(
- const LayoutObject& layout_object) {
- if (Node* node = layout_object.GetNode()) {
- if (layout_object.IsLayoutView()) {
- Document& doc = node->GetDocument();
- if (Settings* settings = doc.GetSettings()) {
- if (!settings->GetAllowCustomScrollbarInMainFrame() &&
- layout_object.GetFrame() && layout_object.GetFrame()->IsMainFrame())
- return layout_object;
- }
-
- // Try the <body> element first as a scrollbar source.
- Element* body = doc.body();
- if (body && body->GetLayoutObject() &&
- body->GetLayoutObject()->Style()->HasPseudoStyle(kPseudoIdScrollbar))
- return *body->GetLayoutObject();
-
- // If the <body> didn't have a custom style, then the root element might.
- Element* doc_element = doc.documentElement();
- if (doc_element && doc_element->GetLayoutObject() &&
- doc_element->GetLayoutObject()->Style()->HasPseudoStyle(
- kPseudoIdScrollbar))
- return *doc_element->GetLayoutObject();
+ const LayoutBox& layout_box) {
+ if (layout_box.IsLayoutView()) {
+ Document& doc = layout_box.GetDocument();
+ if (Settings* settings = doc.GetSettings()) {
+ if (!settings->GetAllowCustomScrollbarInMainFrame() &&
+ layout_box.GetFrame() && layout_box.GetFrame()->IsMainFrame())
+ return layout_box;
}
- if (layout_object.StyleRef().HasPseudoStyle(kPseudoIdScrollbar))
- return layout_object;
+ // Try the <body> element first as a scrollbar source, but only if the body
+ // can scroll.
+ Element* body = doc.body();
+ if (body && body->GetLayoutObject() && body->GetLayoutObject()->IsBox() &&
+ body->GetLayoutObject()->Style()->HasPseudoStyle(kPseudoIdScrollbar))
+ return *body->GetLayoutObject();
- if (ShadowRoot* shadow_root = node->ContainingShadowRoot()) {
- if (shadow_root->IsUserAgent()) {
- if (LayoutObject* host_layout_object =
- shadow_root->host().GetLayoutObject())
- return *host_layout_object;
- }
- }
+ // If the <body> didn't have a custom style, then the root element might.
+ Element* doc_element = doc.documentElement();
+ if (doc_element && doc_element->GetLayoutObject() &&
+ doc_element->GetLayoutObject()->Style()->HasPseudoStyle(
+ kPseudoIdScrollbar))
+ return *doc_element->GetLayoutObject();
+ }
+
+ return layout_box;
+}
+
+int PaintLayerScrollableArea::HypotheticalScrollbarThickness(
+ ScrollbarOrientation orientation) const {
+ Scrollbar* scrollbar = orientation == kHorizontalScrollbar
+ ? HorizontalScrollbar()
+ : VerticalScrollbar();
+ if (scrollbar)
+ return scrollbar->ScrollbarThickness();
+
+ const LayoutObject& style_source = ScrollbarStyleSource(*GetLayoutBox());
+ bool has_custom_scrollbar_style =
+ style_source.StyleRef().HasPseudoStyle(kPseudoIdScrollbar);
+ if (has_custom_scrollbar_style) {
+ return LayoutScrollbar::HypotheticalScrollbarThickness(
+ orientation, *GetLayoutBox(), style_source);
}
- return layout_object;
+ ScrollbarControlSize scrollbar_size = kRegularScrollbar;
+ if (style_source.StyleRef().HasAppearance()) {
+ scrollbar_size = LayoutTheme::GetTheme().ScrollbarControlSizeForPart(
+ style_source.StyleRef().Appearance());
+ }
+ ScrollbarTheme& theme = GetPageScrollbarTheme();
+ if (theme.UsesOverlayScrollbars())
+ return 0;
+ int thickness = theme.ScrollbarThickness(scrollbar_size);
+ return GetLayoutBox()
+ ->GetDocument()
+ .GetPage()
+ ->GetChromeClient()
+ .WindowToViewportScalar(thickness);
}
bool PaintLayerScrollableArea::NeedsScrollbarReconstruction() const {
@@ -1401,8 +1412,10 @@ bool PaintLayerScrollableArea::NeedsScrollbarReconstruction() const {
if (needs_custom) {
DCHECK(scrollbar->IsCustomScrollbar());
// We have a custom scrollbar with a stale m_owner.
- if (ToLayoutScrollbar(scrollbar)->StyleSource() != style_source)
+ if (ToLayoutScrollbar(scrollbar)->StyleSource()->GetLayoutObject() !=
+ style_source) {
return true;
+ }
// Should use custom scrollbar and nothing should change.
continue;
@@ -1456,7 +1469,7 @@ void PaintLayerScrollableArea::ComputeScrollbarExistence(
if (GetLayoutBox()->IsLayoutView()) {
ScrollbarMode h_mode;
ScrollbarMode v_mode;
- CalculateScrollbarModes(h_mode, v_mode);
+ ToLayoutView(GetLayoutBox())->CalculateScrollbarModes(h_mode, v_mode);
// Look for the scrollbarModes and reset the needs Horizontal & vertical
// Scrollbar values based on scrollbarModes, as during force style change
@@ -1488,7 +1501,7 @@ bool PaintLayerScrollableArea::TryRemovingAutoScrollbars(
if (GetLayoutBox()->IsLayoutView()) {
ScrollbarMode h_mode;
ScrollbarMode v_mode;
- CalculateScrollbarModes(h_mode, v_mode);
+ ToLayoutView(GetLayoutBox())->CalculateScrollbarModes(h_mode, v_mode);
if (h_mode != kScrollbarAuto || v_mode != kScrollbarAuto)
return false;
@@ -1608,7 +1621,7 @@ int PaintLayerScrollableArea::HorizontalScrollbarHeight(
return HorizontalScrollbar()->ScrollbarThickness();
}
-void PaintLayerScrollableArea::SnapAfterScrollbarDragging(
+void PaintLayerScrollableArea::SnapAfterScrollbarScrolling(
ScrollbarOrientation orientation) {
SnapCoordinator* snap_coordinator =
GetLayoutBox()->GetDocument().GetSnapCoordinator();
@@ -1772,8 +1785,8 @@ bool PaintLayerScrollableArea::IsPointInResizeControl(
if (!GetLayoutBox()->CanResize())
return false;
- IntPoint local_point = RoundedIntPoint(
- GetLayoutBox()->AbsoluteToLocal(absolute_point, kUseTransforms));
+ IntPoint local_point = RoundedIntPoint(GetLayoutBox()->AbsoluteToLocal(
+ FloatPoint(absolute_point), kUseTransforms));
IntRect local_bounds(IntPoint(), Layer()->PixelSnappedSize());
return ResizerCornerRect(local_bounds, resizer_hit_test_type)
.Contains(local_point);
@@ -1901,8 +1914,8 @@ IntSize PaintLayerScrollableArea::OffsetFromResizeCorner(
if (GetLayoutBox()->ShouldPlaceBlockDirectionScrollbarOnLogicalLeft())
element_size.SetWidth(0);
IntPoint resizer_point = IntPoint(element_size);
- IntPoint local_point = RoundedIntPoint(
- GetLayoutBox()->AbsoluteToLocal(absolute_point, kUseTransforms));
+ IntPoint local_point = RoundedIntPoint(GetLayoutBox()->AbsoluteToLocal(
+ FloatPoint(absolute_point), kUseTransforms));
return local_point - resizer_point;
}
@@ -1935,7 +1948,7 @@ void PaintLayerScrollableArea::Resize(const IntPoint& pos,
float zoom_factor = GetLayoutBox()->Style()->EffectiveZoom();
IntSize new_offset =
- OffsetFromResizeCorner(document.View()->RootFrameToContents(pos));
+ OffsetFromResizeCorner(document.View()->ConvertFromRootFrame(pos));
new_offset.SetWidth(new_offset.Width() / zoom_factor);
new_offset.SetHeight(new_offset.Height() / zoom_factor);
@@ -2081,7 +2094,7 @@ void PaintLayerScrollableArea::UpdateScrollableAreaSet() {
if (GetLayoutBox()->IsLayoutView()) {
ScrollbarMode h_mode;
ScrollbarMode v_mode;
- CalculateScrollbarModes(h_mode, v_mode);
+ ToLayoutView(GetLayoutBox())->CalculateScrollbarModes(h_mode, v_mode);
if (h_mode == kScrollbarAlwaysOff && v_mode == kScrollbarAlwaysOff)
has_overflow = false;
}
@@ -2204,8 +2217,13 @@ bool PaintLayerScrollableArea::ComputeNeedsCompositedScrolling(
if (CompositingReasonFinder::RequiresCompositingForRootScroller(*layer))
return true;
- if (!layer->ScrollsOverflow())
+ // TODO(crbug.com/839341): Remove ScrollTimeline check once we support
+ // main-thread AnimationWorklet and don't need to promote the scroll-source.
+ Node* node = layer->GetLayoutObject().GetNode();
+ if (!layer->ScrollsOverflow() &&
+ !ScrollTimeline::HasActiveScrollTimeline(node)) {
return false;
+ }
if (layer->Size().IsEmpty())
return false;
@@ -2229,7 +2247,10 @@ bool PaintLayerScrollableArea::ComputeNeedsCompositedScrolling(
ToLayoutBox(layer->GetLayoutObject()).PaddingBoxRect()) &&
!layer->CompositesWithTransform() && !layer->CompositesWithOpacity();
- if (!layer_has_been_composited &&
+ // TODO(crbug.com/839341): Remove ScrollTimeline check once we support
+ // main-thread AnimationWorklet and don't need to promote the scroll-source.
+ if (!ScrollTimeline::HasActiveScrollTimeline(node) &&
+ !layer_has_been_composited &&
!layer->Compositor()->PreferCompositingToLCDTextEnabled() &&
!background_supports_lcd_text) {
if (layer->CompositesWithOpacity()) {
@@ -2276,14 +2297,6 @@ void PaintLayerScrollableArea::UpdateNeedsCompositedScrolling(
}
}
-void PaintLayerScrollableArea::SetTopmostScrollChild(PaintLayer* scroll_child) {
- // We only want to track the topmost scroll child for scrollable areas with
- // overlay scrollbars.
- if (!HasOverlayScrollbars())
- return;
- next_topmost_scroll_child_ = scroll_child;
-}
-
bool PaintLayerScrollableArea::VisualViewportSuppliesScrollbars() const {
LocalFrame* frame = GetLayoutBox()->GetFrame();
if (!frame || !frame->GetSettings())
@@ -2301,7 +2314,7 @@ bool PaintLayerScrollableArea::VisualViewportSuppliesScrollbars() const {
}
bool PaintLayerScrollableArea::ScheduleAnimation() {
- if (ChromeClient* client = GetChromeClient()) {
+ if (ChromeClient* client = ToChromeClient(GetChromeClient())) {
client->ScheduleAnimation(GetLayoutBox()->GetFrame()->View());
return true;
}
@@ -2326,26 +2339,8 @@ PaintLayerScrollableArea::GetCompositorAnimationTimeline() const {
}
void PaintLayerScrollableArea::GetTickmarks(Vector<IntRect>& tickmarks) const {
- if (layer_->IsRootLayer()) {
- tickmarks = GetLayoutBox()
- ->GetDocument()
- .Markers()
- .LayoutRectsForTextMatchMarkers();
- }
-}
-
-PaintLayerScrollableArea*
-PaintLayerScrollableArea::ScrollbarManager::ScrollableArea() {
- return ToPaintLayerScrollableArea(scrollable_area_.Get());
-}
-
-void PaintLayerScrollableArea::ScrollbarManager::DestroyDetachedScrollbars() {
- DCHECK(!h_bar_is_attached_ || h_bar_);
- DCHECK(!v_bar_is_attached_ || v_bar_);
- if (h_bar_ && !h_bar_is_attached_)
- DestroyScrollbar(kHorizontalScrollbar);
- if (v_bar_ && !v_bar_is_attached_)
- DestroyScrollbar(kVerticalScrollbar);
+ if (layer_->IsRootLayer())
+ tickmarks = ToLayoutView(GetLayoutBox())->GetTickmarks();
}
void PaintLayerScrollableArea::ScrollbarManager::SetHasHorizontalScrollbar(
@@ -2396,7 +2391,6 @@ Scrollbar* PaintLayerScrollableArea::ScrollbarManager::CreateScrollbar(
const LayoutObject& style_source =
ScrollbarStyleSource(*ScrollableArea()->GetLayoutBox());
bool has_custom_scrollbar_style =
- style_source.IsBox() &&
style_source.StyleRef().HasPseudoStyle(kPseudoIdScrollbar);
if (has_custom_scrollbar_style) {
DCHECK(style_source.GetNode() && style_source.GetNode()->IsElementNode());
@@ -2444,6 +2438,28 @@ void PaintLayerScrollableArea::ScrollbarManager::DestroyScrollbar(
scrollbar = nullptr;
}
+void PaintLayerScrollableArea::ScrollbarManager::DestroyDetachedScrollbars() {
+ DCHECK(!h_bar_is_attached_ || h_bar_);
+ DCHECK(!v_bar_is_attached_ || v_bar_);
+ if (h_bar_ && !h_bar_is_attached_)
+ DestroyScrollbar(kHorizontalScrollbar);
+ if (v_bar_ && !v_bar_is_attached_)
+ DestroyScrollbar(kVerticalScrollbar);
+}
+
+void PaintLayerScrollableArea::ScrollbarManager::Dispose() {
+ h_bar_is_attached_ = v_bar_is_attached_ = 0;
+ DestroyScrollbar(kHorizontalScrollbar);
+ DestroyScrollbar(kVerticalScrollbar);
+}
+
+void PaintLayerScrollableArea::ScrollbarManager::Trace(
+ blink::Visitor* visitor) {
+ visitor->Trace(scrollable_area_);
+ visitor->Trace(h_bar_);
+ visitor->Trace(v_bar_);
+}
+
uint64_t PaintLayerScrollableArea::Id() const {
return DOMNodeIds::IdForNode(GetLayoutBox()->GetNode());
}
@@ -2568,4 +2584,246 @@ ScrollbarTheme& PaintLayerScrollableArea::GetPageScrollbarTheme() const {
return page->GetScrollbarTheme();
}
+void PaintLayerScrollableArea::WillRemoveScrollbar(
+ Scrollbar& scrollbar,
+ ScrollbarOrientation orientation) {
+ if (!scrollbar.IsCustomScrollbar() &&
+ !(orientation == kHorizontalScrollbar ? LayerForHorizontalScrollbar()
+ : LayerForVerticalScrollbar())) {
+ ObjectPaintInvalidator(*GetLayoutBox())
+ .SlowSetPaintingLayerNeedsRepaintAndInvalidateDisplayItemClient(
+ scrollbar, PaintInvalidationReason::kScrollControl);
+ }
+
+ ScrollableArea::WillRemoveScrollbar(scrollbar, orientation);
+}
+
+static LayoutRect ScrollControlVisualRect(
+ const IntRect& scroll_control_rect,
+ const LayoutBox& box,
+ const PaintInvalidatorContext& context,
+ const LayoutRect& previous_visual_rect) {
+ LayoutRect visual_rect(scroll_control_rect);
+#if DCHECK_IS_ON()
+ FindVisualRectNeedingUpdateScope finder(box, context, previous_visual_rect,
+ visual_rect);
+#endif
+ if (!context.NeedsVisualRectUpdate(box))
+ return previous_visual_rect;
+
+ // No need to apply any paint offset. Scroll controls paint in a different
+ // transform space than their contained box (the scrollbarPaintOffset
+ // transform node).
+ return visual_rect;
+}
+
+// Returns true if the scroll control is invalidated.
+static bool InvalidatePaintOfScrollControlIfNeeded(
+ const LayoutRect& new_visual_rect,
+ const LayoutRect& previous_visual_rect,
+ bool needs_paint_invalidation,
+ LayoutBox& box,
+ const LayoutBoxModelObject& paint_invalidation_container) {
+ bool should_invalidate_new_rect = needs_paint_invalidation;
+ if (new_visual_rect != previous_visual_rect) {
+ should_invalidate_new_rect = true;
+ } else if (previous_visual_rect.IsEmpty()) {
+ DCHECK(new_visual_rect.IsEmpty());
+ // Do not issue an empty invalidation.
+ should_invalidate_new_rect = false;
+ }
+
+ return should_invalidate_new_rect;
+}
+
+static LayoutRect InvalidatePaintOfScrollbarIfNeeded(
+ Scrollbar* scrollbar,
+ GraphicsLayer* graphics_layer,
+ bool& previously_was_overlay,
+ const LayoutRect& previous_visual_rect,
+ bool needs_paint_invalidation_arg,
+ LayoutBox& box,
+ const PaintInvalidatorContext& context) {
+ bool is_overlay = scrollbar && scrollbar->IsOverlayScrollbar();
+
+ LayoutRect new_visual_rect;
+ // Calculate visual rect of the scrollbar, except overlay composited
+ // scrollbars because we invalidate the graphics layer only.
+ if (scrollbar && !(graphics_layer && is_overlay)) {
+ new_visual_rect = ScrollControlVisualRect(scrollbar->FrameRect(), box,
+ context, previous_visual_rect);
+ }
+
+ bool needs_paint_invalidation = needs_paint_invalidation_arg;
+ if (needs_paint_invalidation && graphics_layer) {
+ // If the scrollbar needs paint invalidation but didn't change location/size
+ // or the scrollbar is an overlay scrollbar (visual rect is empty),
+ // invalidating the graphics layer is enough (which has been done in
+ // ScrollableArea::setScrollbarNeedsPaintInvalidation()).
+ // Otherwise invalidatePaintOfScrollControlIfNeeded() below will invalidate
+ // the old and new location of the scrollbar on the box's paint invalidation
+ // container to ensure newly expanded/shrunk areas of the box to be
+ // invalidated.
+ needs_paint_invalidation = false;
+ DCHECK(!graphics_layer->DrawsContent() ||
+ graphics_layer->GetPaintController().GetPaintArtifact().IsEmpty());
+ }
+
+ // Invalidate the box's display item client if the box's padding box size is
+ // affected by change of the non-overlay scrollbar width. We detect change of
+ // visual rect size instead of change of scrollbar width change, which may
+ // have some false-positives (e.g. the scrollbar changed length but not width)
+ // but won't invalidate more than expected because in the false-positive case
+ // the box must have changed size and have been invalidated.
+ const LayoutBoxModelObject& paint_invalidation_container =
+ *context.paint_invalidation_container;
+ LayoutSize new_scrollbar_used_space_in_box;
+ if (!is_overlay)
+ new_scrollbar_used_space_in_box = new_visual_rect.Size();
+ LayoutSize previous_scrollbar_used_space_in_box;
+ if (!previously_was_overlay)
+ previous_scrollbar_used_space_in_box = previous_visual_rect.Size();
+
+ // The IsEmpty() check avoids invalidaiton in cases when the visual rect
+ // changes from (0,0 0x0) to (0,0 0x100).
+ if (!(new_scrollbar_used_space_in_box.IsEmpty() &&
+ previous_scrollbar_used_space_in_box.IsEmpty()) &&
+ new_scrollbar_used_space_in_box != previous_scrollbar_used_space_in_box) {
+ context.painting_layer->SetNeedsRepaint();
+ ObjectPaintInvalidator(box).InvalidateDisplayItemClient(
+ box, PaintInvalidationReason::kGeometry);
+ }
+
+ bool invalidated = InvalidatePaintOfScrollControlIfNeeded(
+ new_visual_rect, previous_visual_rect, needs_paint_invalidation, box,
+ paint_invalidation_container);
+
+ previously_was_overlay = is_overlay;
+
+ if (!invalidated || !scrollbar || graphics_layer)
+ return new_visual_rect;
+
+ context.painting_layer->SetNeedsRepaint();
+ ObjectPaintInvalidator(box).InvalidateDisplayItemClient(
+ *scrollbar, PaintInvalidationReason::kScrollControl);
+ if (scrollbar->IsCustomScrollbar()) {
+ ToLayoutScrollbar(scrollbar)
+ ->InvalidateDisplayItemClientsOfScrollbarParts();
+ }
+
+ return new_visual_rect;
+}
+
+void PaintLayerScrollableArea::InvalidatePaintOfScrollControlsIfNeeded(
+ const PaintInvalidatorContext& context) {
+ LayoutBox& box = *GetLayoutBox();
+ SetHorizontalScrollbarVisualRect(InvalidatePaintOfScrollbarIfNeeded(
+ HorizontalScrollbar(), LayerForHorizontalScrollbar(),
+ horizontal_scrollbar_previously_was_overlay_,
+ horizontal_scrollbar_visual_rect_,
+ HorizontalScrollbarNeedsPaintInvalidation(), box, context));
+ SetVerticalScrollbarVisualRect(InvalidatePaintOfScrollbarIfNeeded(
+ VerticalScrollbar(), LayerForVerticalScrollbar(),
+ vertical_scrollbar_previously_was_overlay_,
+ vertical_scrollbar_visual_rect_,
+ VerticalScrollbarNeedsPaintInvalidation(), box, context));
+
+ LayoutRect scroll_corner_and_resizer_visual_rect =
+ ScrollControlVisualRect(ScrollCornerAndResizerRect(), box, context,
+ scroll_corner_and_resizer_visual_rect_);
+ const LayoutBoxModelObject& paint_invalidation_container =
+ *context.paint_invalidation_container;
+ if (InvalidatePaintOfScrollControlIfNeeded(
+ scroll_corner_and_resizer_visual_rect,
+ scroll_corner_and_resizer_visual_rect_,
+ ScrollCornerNeedsPaintInvalidation(), box,
+ paint_invalidation_container)) {
+ SetScrollCornerAndResizerVisualRect(scroll_corner_and_resizer_visual_rect);
+ if (LayoutScrollbarPart* scroll_corner = ScrollCorner()) {
+ ObjectPaintInvalidator(*scroll_corner)
+ .InvalidateDisplayItemClientsIncludingNonCompositingDescendants(
+ PaintInvalidationReason::kScrollControl);
+ }
+ if (LayoutScrollbarPart* resizer = Resizer()) {
+ ObjectPaintInvalidator(*resizer)
+ .InvalidateDisplayItemClientsIncludingNonCompositingDescendants(
+ PaintInvalidationReason::kScrollControl);
+ }
+ }
+
+ ClearNeedsPaintInvalidationForScrollControls();
+}
+
+void PaintLayerScrollableArea::ClearPreviousVisualRects() {
+ SetHorizontalScrollbarVisualRect(LayoutRect());
+ SetVerticalScrollbarVisualRect(LayoutRect());
+ SetScrollCornerAndResizerVisualRect(LayoutRect());
+}
+
+void PaintLayerScrollableArea::SetHorizontalScrollbarVisualRect(
+ const LayoutRect& rect) {
+ horizontal_scrollbar_visual_rect_ = rect;
+ if (Scrollbar* scrollbar = HorizontalScrollbar())
+ scrollbar->SetVisualRect(rect);
+}
+
+void PaintLayerScrollableArea::SetVerticalScrollbarVisualRect(
+ const LayoutRect& rect) {
+ vertical_scrollbar_visual_rect_ = rect;
+ if (Scrollbar* scrollbar = VerticalScrollbar())
+ scrollbar->SetVisualRect(rect);
+}
+
+void PaintLayerScrollableArea::SetScrollCornerAndResizerVisualRect(
+ const LayoutRect& rect) {
+ scroll_corner_and_resizer_visual_rect_ = rect;
+ if (LayoutScrollbarPart* scroll_corner = ScrollCorner())
+ scroll_corner->GetMutableForPainting().FirstFragment().SetVisualRect(rect);
+ if (LayoutScrollbarPart* resizer = Resizer())
+ resizer->GetMutableForPainting().FirstFragment().SetVisualRect(rect);
+}
+
+void PaintLayerScrollableArea::ScrollControlWasSetNeedsPaintInvalidation() {
+ GetLayoutBox()->SetMayNeedPaintInvalidation();
+}
+
+void PaintLayerScrollableArea::DidScrollWithScrollbar(
+ ScrollbarPart part,
+ ScrollbarOrientation orientation) {
+ WebFeature scrollbar_use_uma;
+ switch (part) {
+ case kBackButtonStartPart:
+ case kForwardButtonStartPart:
+ case kBackButtonEndPart:
+ case kForwardButtonEndPart:
+ scrollbar_use_uma =
+ (orientation == kVerticalScrollbar
+ ? WebFeature::kScrollbarUseVerticalScrollbarButton
+ : WebFeature::kScrollbarUseHorizontalScrollbarButton);
+ break;
+ case kThumbPart:
+ scrollbar_use_uma =
+ (orientation == kVerticalScrollbar
+ ? WebFeature::kScrollbarUseVerticalScrollbarThumb
+ : WebFeature::kScrollbarUseHorizontalScrollbarThumb);
+ break;
+ case kBackTrackPart:
+ case kForwardTrackPart:
+ scrollbar_use_uma =
+ (orientation == kVerticalScrollbar
+ ? WebFeature::kScrollbarUseVerticalScrollbarTrack
+ : WebFeature::kScrollbarUseHorizontalScrollbarTrack);
+ break;
+ default:
+ return;
+ }
+
+ UseCounter::Count(GetLayoutBox()->GetDocument(), scrollbar_use_uma);
+}
+
+CompositorElementId PaintLayerScrollableArea::GetCompositorElementId() const {
+ return CompositorElementIdFromUniqueObjectId(
+ GetLayoutBox()->UniqueId(), CompositorElementIdNamespace::kScroll);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h b/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
index 5486d222524..e0190ee92a5 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
@@ -48,13 +48,11 @@
#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/layout/scroll_anchor.h"
-#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h"
-#include "third_party/blink/renderer/core/paint/paint_invalidation_capable_scrollable_area.h"
#include "third_party/blink/renderer/core/paint/paint_layer_fragment.h"
-#include "third_party/blink/renderer/core/paint/scrollbar_manager.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/scroll/scroll_types.h"
+#include "third_party/blink/renderer/platform/scroll/scrollable_area.h"
namespace blink {
@@ -64,6 +62,7 @@ class ComputedStyle;
class HitTestResult;
class LayoutBox;
class LayoutScrollbarPart;
+struct PaintInvalidatorContext;
class PaintLayer;
class ScrollingCoordinator;
class StickyPositionScrollingConstraints;
@@ -116,12 +115,12 @@ struct CORE_EXPORT PaintLayerScrollableAreaRareData {
// PaintLayerPaintingOverlayScrollbars.
class CORE_EXPORT PaintLayerScrollableArea final
: public GarbageCollectedFinalized<PaintLayerScrollableArea>,
- public PaintInvalidationCapableScrollableArea {
+ public ScrollableArea {
USING_GARBAGE_COLLECTED_MIXIN(PaintLayerScrollableArea);
friend class Internals;
private:
- class ScrollbarManager : public blink::ScrollbarManager {
+ class ScrollbarManager {
DISALLOW_NEW();
// Helper class to manage the life cycle of Scrollbar objects. Some layout
@@ -137,19 +136,43 @@ class CORE_EXPORT PaintLayerScrollableArea final
// previously "deleted" scrollbar will be restored, rather than constructing
// a new one.
public:
- ScrollbarManager(PaintLayerScrollableArea& scroller)
- : blink::ScrollbarManager(scroller) {}
-
- void SetHasHorizontalScrollbar(bool has_scrollbar) override;
- void SetHasVerticalScrollbar(bool has_scrollbar) override;
+ ScrollbarManager(PaintLayerScrollableArea& scrollable_area)
+ : scrollable_area_(scrollable_area),
+ h_bar_is_attached_(0),
+ v_bar_is_attached_(0) {}
+
+ PaintLayerScrollableArea* ScrollableArea() const {
+ return scrollable_area_.Get();
+ }
+ Scrollbar* HorizontalScrollbar() const {
+ return h_bar_is_attached_ ? h_bar_.Get() : nullptr;
+ }
+ Scrollbar* VerticalScrollbar() const {
+ return v_bar_is_attached_ ? v_bar_.Get() : nullptr;
+ }
+ bool HasHorizontalScrollbar() const { return HorizontalScrollbar(); }
+ bool HasVerticalScrollbar() const { return VerticalScrollbar(); }
+
+ void SetHasHorizontalScrollbar(bool has_scrollbar);
+ void SetHasVerticalScrollbar(bool has_scrollbar);
void DestroyDetachedScrollbars();
- Scrollbar* CreateScrollbar(ScrollbarOrientation) override;
+ void Dispose();
+
+ void Trace(blink::Visitor*);
+
+ private:
+ Scrollbar* CreateScrollbar(ScrollbarOrientation);
+ void DestroyScrollbar(ScrollbarOrientation);
- protected:
- void DestroyScrollbar(ScrollbarOrientation) override;
+ Member<PaintLayerScrollableArea> scrollable_area_;
- PaintLayerScrollableArea* ScrollableArea();
+ // The scrollbars associated with scrollable_area_. Both can nullptr.
+ Member<Scrollbar> h_bar_;
+ Member<Scrollbar> v_bar_;
+
+ unsigned h_bar_is_attached_ : 1;
+ unsigned v_bar_is_attached_ : 1;
};
public:
@@ -201,7 +224,7 @@ class CORE_EXPORT PaintLayerScrollableArea final
// last DelayScrollOffsetClampScope object is destructed, all
// PaintLayerScrollableArea's that delayed clamping their offsets will
// immediately clamp them.
- class DelayScrollOffsetClampScope {
+ class CORE_EXPORT DelayScrollOffsetClampScope {
STACK_ALLOCATED();
public:
@@ -238,14 +261,9 @@ class CORE_EXPORT PaintLayerScrollableArea final
Scrollbar* VerticalScrollbar() const override {
return scrollbar_manager_.VerticalScrollbar();
}
- Scrollbar* CreateScrollbar(ScrollbarOrientation orientation) override {
- return scrollbar_manager_.CreateScrollbar(orientation);
- }
-
- void CalculateScrollbarModes(ScrollbarMode& h_mode,
- ScrollbarMode& v_mode) const;
- ChromeClient* GetChromeClient() const override;
+ bool IsThrottled() const override;
+ PlatformChromeClient* GetChromeClient() const override;
SmoothScrollSequencer* GetSmoothScrollSequencer() const override;
@@ -256,7 +274,7 @@ class CORE_EXPORT PaintLayerScrollableArea final
// only a helper.
GraphicsLayer* LayerForScrolling() const override;
- void DidScroll(const gfx::ScrollOffset&) override;
+ void DidScroll(const FloatPoint&) override;
// GraphicsLayers for the scrolling components.
//
@@ -281,16 +299,26 @@ class CORE_EXPORT PaintLayerScrollableArea final
const IntPoint&) const override;
IntPoint ConvertFromRootFrame(const IntPoint&) const override;
int ScrollSize(ScrollbarOrientation) const override;
+ FloatPoint ScrollPosition() const override {
+ return FloatPoint(ScrollOrigin()) + GetScrollOffset();
+ }
+ FloatPoint ScrollOffsetToPosition(const ScrollOffset& offset) const override {
+ return FloatPoint(ScrollOrigin()) + offset;
+ }
+ ScrollOffset ScrollPositionToOffset(
+ const FloatPoint& position) const override {
+ return position - ScrollOrigin();
+ }
IntSize ScrollOffsetInt() const override;
ScrollOffset GetScrollOffset() const override;
IntSize MinimumScrollOffsetInt() const override;
IntSize MaximumScrollOffsetInt() const override;
IntRect VisibleContentRect(
IncludeScrollbarsInRect = kExcludeScrollbars) const override;
- LayoutRect VisibleScrollSnapportRect() const override;
+ LayoutRect VisibleScrollSnapportRect(
+ IncludeScrollbarsInRect = kExcludeScrollbars) const override;
IntSize ContentsSize() const override;
void ContentsResized() override;
- bool IsScrollable() const override;
IntPoint LastKnownMousePosition() const override;
bool ScrollAnimatorEnabled() const override;
bool ShouldSuspendScrollAnimations() const override;
@@ -310,6 +338,10 @@ class CORE_EXPORT PaintLayerScrollableArea final
void VisibleSizeChanged();
+ // See renderer/core/layout/README.md for an explanation of scroll origin.
+ IntPoint ScrollOrigin() const { return scroll_origin_; }
+ bool ScrollOriginChanged() const { return scroll_origin_changed_; }
+
// FIXME: We shouldn't allow access to m_overflowRect outside this class.
LayoutRect OverflowRect() const { return overflow_rect_; }
@@ -341,7 +373,7 @@ class CORE_EXPORT PaintLayerScrollableArea final
void UpdateAfterStyleChange(const ComputedStyle*);
void UpdateAfterOverflowRecalc();
- bool UpdateAfterCompositingChange() override;
+ void UpdateAfterCompositingChange();
bool HasScrollbar() const {
return HasHorizontalScrollbar() || HasVerticalScrollbar();
@@ -349,8 +381,11 @@ class CORE_EXPORT PaintLayerScrollableArea final
bool HasOverflowControls() const {
return HasScrollbar() || ScrollCorner() || Resizer();
}
+ bool HasOverflow() const {
+ return HasHorizontalOverflow() || HasVerticalOverflow();
+ }
- LayoutScrollbarPart* ScrollCorner() const override { return scroll_corner_; }
+ LayoutScrollbarPart* ScrollCorner() const { return scroll_corner_; }
void Resize(const IntPoint& pos, const LayoutSize& old_offset);
IntSize OffsetFromResizeCorner(const IntPoint& absolute_point) const;
@@ -400,24 +435,16 @@ class CORE_EXPORT PaintLayerScrollableArea final
bool ScrollsOverflow() const { return scrolls_overflow_; }
// Rectangle encompassing the scroll corner and resizer rect.
- IntRect ScrollCornerAndResizerRect() const final;
+ IntRect ScrollCornerAndResizerRect() const;
void UpdateNeedsCompositedScrolling(bool layer_has_been_composited = false);
bool NeedsCompositedScrolling() const { return needs_composited_scrolling_; }
- // These are used during compositing updates to determine if the overflow
- // controls need to be repositioned in the GraphicsLayer tree.
- void SetTopmostScrollChild(PaintLayer*);
- PaintLayer* TopmostScrollChild() const {
- DCHECK(!next_topmost_scroll_child_);
- return topmost_scroll_child_;
- }
-
IntRect ResizerCornerRect(const IntRect&, ResizerHitTestType) const;
PaintLayer* Layer() const override;
- LayoutScrollbarPart* Resizer() const override { return resizer_; }
+ LayoutScrollbarPart* Resizer() const { return resizer_; }
const IntPoint& CachedOverlayScrollbarOffset() {
return cached_overlay_scrollbar_offset_;
@@ -497,6 +524,24 @@ class CORE_EXPORT PaintLayerScrollableArea final
ScrollbarTheme& GetPageScrollbarTheme() const override;
+ // Return the thickness of the existing scrollbar; or, if there is no
+ // existing scrollbar, then calculate the thickness it would have if it
+ // existed. Returns zero if the (real or hypothetical) scrollbar is an overlay
+ // scrollbar.
+ int HypotheticalScrollbarThickness(ScrollbarOrientation) const;
+
+ void WillRemoveScrollbar(Scrollbar&, ScrollbarOrientation) override;
+
+ void InvalidatePaintOfScrollControlsIfNeeded(const PaintInvalidatorContext&);
+
+ // Should be called when the previous visual rects are no longer valid.
+ void ClearPreviousVisualRects();
+
+ void DidScrollWithScrollbar(ScrollbarPart, ScrollbarOrientation) override;
+ CompositorElementId GetCompositorElementId() const override;
+
+ bool VisualViewportSuppliesScrollbars() const override;
+
void Trace(blink::Visitor*) override;
private:
@@ -504,10 +549,10 @@ class CORE_EXPORT PaintLayerScrollableArea final
bool HasHorizontalOverflow() const;
bool HasVerticalOverflow() const;
- bool VisualViewportSuppliesScrollbars() const;
bool NeedsScrollbarReconstruction() const;
+ void ResetScrollOriginChanged() { scroll_origin_changed_ = false; }
void UpdateScrollOrigin();
void UpdateScrollDimensions();
void UpdateScrollbarEnabledState();
@@ -538,7 +583,7 @@ class CORE_EXPORT PaintLayerScrollableArea final
bool SetHasHorizontalScrollbar(bool has_scrollbar);
bool SetHasVerticalScrollbar(bool has_scrollbar);
- void SnapAfterScrollbarDragging(ScrollbarOrientation) override;
+ void SnapAfterScrollbarScrolling(ScrollbarOrientation) override;
void UpdateScrollCornerStyle();
LayoutSize MinimumSizeForResizing(float zoom_factor);
@@ -569,14 +614,17 @@ class CORE_EXPORT PaintLayerScrollableArea final
IntRect CornerRect(const IntRect& bounds) const;
+ void ScrollControlWasSetNeedsPaintInvalidation() override;
+
+ void SetHorizontalScrollbarVisualRect(const LayoutRect&);
+ void SetVerticalScrollbarVisualRect(const LayoutRect&);
+ void SetScrollCornerAndResizerVisualRect(const LayoutRect&);
+
// PaintLayer is destructed before PaintLayerScrollable area, during this
// time before PaintLayerScrollableArea has been collected layer_ will
// be set to nullptr by the Dispose method.
PaintLayer* layer_;
- PaintLayer* next_topmost_scroll_child_;
- PaintLayer* topmost_scroll_child_;
-
// Keeps track of whether the layer is currently resizing, so events can cause
// resizing to start and stop.
unsigned in_resize_mode_ : 1;
@@ -602,6 +650,19 @@ class CORE_EXPORT PaintLayerScrollableArea final
unsigned needs_relayout_ : 1;
unsigned had_horizontal_scrollbar_before_relayout_ : 1;
unsigned had_vertical_scrollbar_before_relayout_ : 1;
+ unsigned scroll_origin_changed_ : 1;
+
+ // There are 6 possible combinations of writing mode and direction. Scroll
+ // origin will be non-zero in the x or y axis if there is any reversed
+ // direction or writing-mode. The combinations are:
+ // writing-mode / direction scrollOrigin.x() set scrollOrigin.y() set
+ // horizontal-tb / ltr NO NO
+ // horizontal-tb / rtl YES NO
+ // vertical-lr / ltr NO NO
+ // vertical-lr / rtl NO YES
+ // vertical-rl / ltr YES NO
+ // vertical-rl / rtl YES YES
+ IntPoint scroll_origin_;
// The width/height of our scrolled area.
// This is OverflowModel's layout overflow translated to physical
@@ -629,6 +690,12 @@ class CORE_EXPORT PaintLayerScrollableArea final
// MainThreadScrollingReason due to the properties of the LayoutObject
uint32_t non_composited_main_thread_scrolling_reasons_;
+
+ bool horizontal_scrollbar_previously_was_overlay_;
+ bool vertical_scrollbar_previously_was_overlay_;
+ LayoutRect horizontal_scrollbar_visual_rect_;
+ LayoutRect vertical_scrollbar_visual_rect_;
+ LayoutRect scroll_corner_and_resizer_visual_rect_;
};
DEFINE_TYPE_CASTS(PaintLayerScrollableArea,
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 f4ea4c3fbb4..4d989ee50b1 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
@@ -730,6 +730,34 @@ TEST_F(PaintLayerScrollableAreaTest, FloatOverflowInRtlContainer) {
EXPECT_FALSE(scrollable_area->HasHorizontalScrollbar());
}
+TEST_F(PaintLayerScrollableAreaTest, ScrollOriginInRtlContainer) {
+ SetBodyInnerHTML(R"HTML(
+ <!DOCTYPE html>
+ <style>
+ #container {
+ width: 200px;
+ overflow: auto;
+ direction: rtl;
+ }
+ #content {
+ width: 300px;
+ }
+ </style>
+ <div id='container'>
+ <div id='content'>
+ lorem ipsum
+ <div>
+ </div>
+ )HTML");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ Element* container = GetDocument().getElementById("container");
+ ASSERT_TRUE(container);
+ PaintLayerScrollableArea* scrollable_area =
+ ToLayoutBoxModelObject(container->GetLayoutObject())->GetScrollableArea();
+ ASSERT_TRUE(scrollable_area);
+ EXPECT_EQ(scrollable_area->ScrollOrigin().X(), 100);
+}
+
TEST_F(PaintLayerScrollableAreaTest,
SlimmingPaintV2OverflowHiddenScrollOffsetInvalidation) {
ScopedSlimmingPaintV2ForTest enabler(true);
@@ -883,20 +911,24 @@ TEST_F(PaintLayerScrollableAreaTest, HitTestOverlayScrollbars) {
scrollable_area->SetScrollbarsHiddenIfOverlay(true);
HitTestRequest hit_request(HitTestRequest::kMove | HitTestRequest::kReadOnly);
- HitTestResult hit_result(hit_request, LayoutPoint(95, 5));
- GetDocument().GetLayoutView()->HitTest(hit_result);
+ HitTestLocation location(LayoutPoint(95, 5));
+ HitTestResult hit_result(hit_request, location);
+ GetDocument().GetLayoutView()->HitTest(location, hit_result);
EXPECT_EQ(hit_result.GetScrollbar(), nullptr);
- hit_result = HitTestResult(hit_request, LayoutPoint(5, 95));
- GetDocument().GetLayoutView()->HitTest(hit_result);
+ location = HitTestLocation(LayoutPoint(5, 95));
+ hit_result = HitTestResult(hit_request, location);
+ GetDocument().GetLayoutView()->HitTest(location, hit_result);
EXPECT_EQ(hit_result.GetScrollbar(), nullptr);
scrollable_area->SetScrollbarsHiddenIfOverlay(false);
- hit_result = HitTestResult(hit_request, LayoutPoint(95, 5));
- GetDocument().GetLayoutView()->HitTest(hit_result);
+ location = HitTestLocation(LayoutPoint(95, 5));
+ hit_result = HitTestResult(hit_request, location);
+ GetDocument().GetLayoutView()->HitTest(location, hit_result);
EXPECT_EQ(hit_result.GetScrollbar(), scrollable_area->VerticalScrollbar());
- hit_result = HitTestResult(hit_request, LayoutPoint(5, 95));
- GetDocument().GetLayoutView()->HitTest(hit_result);
+ location = HitTestLocation(LayoutPoint(5, 95));
+ hit_result = HitTestResult(hit_request, location);
+ GetDocument().GetLayoutView()->HitTest(location, hit_result);
EXPECT_EQ(hit_result.GetScrollbar(), scrollable_area->HorizontalScrollbar());
}
@@ -931,4 +963,21 @@ TEST_F(PaintLayerScrollableAreaTest, CompositedStickyDescendant) {
.To2DTranslation());
}
+// Delayed scroll offset clamping should not crash. https://crbug.com/842495
+TEST_F(PaintLayerScrollableAreaTest, IgnoreDelayedScrollOnDestroyedLayer) {
+ SetBodyInnerHTML(R"HTML(
+ <div id=scroller style="overflow: scroll; width: 200px; height: 200px;">
+ <div style="height: 1000px;"></div>
+ </div>
+ )HTML");
+ Element* scroller = GetDocument().getElementById("scroller");
+ {
+ PaintLayerScrollableArea::DelayScrollOffsetClampScope scope;
+ PaintLayerScrollableArea::DelayScrollOffsetClampScope::SetNeedsClamp(
+ scroller->GetLayoutBox()->GetScrollableArea());
+ scroller->SetInlineStyleProperty(CSSPropertyDisplay, CSSValueNone);
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node.cc
index a73760261e9..e61e03b2bdb 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node.cc
@@ -62,45 +62,55 @@ PaintLayerStackingNode::PaintLayerStackingNode(PaintLayer* layer)
: layer_(layer)
#if DCHECK_IS_ON()
,
- layer_list_mutation_allowed_(true),
- stacking_parent_(nullptr)
+ layer_list_mutation_allowed_(true)
#endif
{
- is_stacked_ = GetLayoutObject().StyleRef().IsStacked();
-
// Non-stacking contexts should have empty z-order lists. As this is already
// the case, there is no need to dirty / recompute these lists.
- z_order_lists_dirty_ = IsStackingContext();
+ z_order_lists_dirty_ =
+ layer->GetLayoutObject().StyleRef().IsStackingContext();
}
PaintLayerStackingNode::~PaintLayerStackingNode() {
#if DCHECK_IS_ON()
- if (!GetLayoutObject().DocumentBeingDestroyed()) {
- DCHECK(!IsInStackingParentZOrderLists());
-
+ if (!Layer()->GetLayoutObject().DocumentBeingDestroyed())
UpdateStackingParentForZOrderLists(nullptr);
- }
#endif
}
-// Helper for the sorting of layers by z-index.
-static inline bool CompareZIndex(PaintLayerStackingNode* first,
- PaintLayerStackingNode* second) {
- return first->ZIndex() < second->ZIndex();
+PaintLayerStackingNode::PaintLayers* PaintLayerStackingNode::PosZOrderList()
+ const {
+ DCHECK(!z_order_lists_dirty_);
+ DCHECK(Layer()->GetLayoutObject().StyleRef().IsStackingContext() ||
+ !pos_z_order_list_);
+ return pos_z_order_list_.get();
+}
+
+PaintLayerStackingNode::PaintLayers* PaintLayerStackingNode::NegZOrderList()
+ const {
+ DCHECK(!z_order_lists_dirty_);
+ DCHECK(Layer()->GetLayoutObject().StyleRef().IsStackingContext() ||
+ !neg_z_order_list_);
+ return neg_z_order_list_.get();
+}
+
+bool PaintLayerStackingNode::IsDirtyStackingContext() const {
+ return z_order_lists_dirty_ &&
+ Layer()->GetLayoutObject().StyleRef().IsStackingContext();
}
PaintLayerCompositor* PaintLayerStackingNode::Compositor() const {
- DCHECK(GetLayoutObject().View());
- if (!GetLayoutObject().View())
+ DCHECK(Layer()->GetLayoutObject().View());
+ if (!Layer()->GetLayoutObject().View())
return nullptr;
- return GetLayoutObject().View()->Compositor();
+ return Layer()->GetLayoutObject().View()->Compositor();
}
void PaintLayerStackingNode::DirtyZOrderLists() {
#if DCHECK_IS_ON()
DCHECK(layer_list_mutation_allowed_);
#endif
- DCHECK(IsStackingContext());
+ DCHECK(Layer()->GetLayoutObject().StyleRef().IsStackingContext());
#if DCHECK_IS_ON()
UpdateStackingParentForZOrderLists(nullptr);
@@ -112,12 +122,14 @@ void PaintLayerStackingNode::DirtyZOrderLists() {
neg_z_order_list_->clear();
z_order_lists_dirty_ = true;
- if (!GetLayoutObject().DocumentBeingDestroyed() && Compositor())
+ if (!Layer()->GetLayoutObject().DocumentBeingDestroyed() && Compositor())
Compositor()->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
}
-void PaintLayerStackingNode::DirtyStackingContextZOrderLists() {
- if (PaintLayerStackingNode* stacking_node = AncestorStackingContextNode())
+void PaintLayerStackingNode::DirtyStackingContextZOrderLists(
+ PaintLayer* layer) {
+ if (PaintLayerStackingNode* stacking_node =
+ AncestorStackingContextNode(layer))
stacking_node->DirtyZOrderLists();
}
@@ -129,7 +141,12 @@ void PaintLayerStackingNode::RebuildZOrderLists() {
for (PaintLayer* child = Layer()->FirstChild(); child;
child = child->NextSibling())
- child->StackingNode()->CollectLayers(pos_z_order_list_, neg_z_order_list_);
+ CollectLayers(child, pos_z_order_list_, neg_z_order_list_);
+
+ auto CompareZIndex = [](PaintLayer* first, PaintLayer* second) {
+ return first->GetLayoutObject().StyleRef().ZIndex() <
+ second->GetLayoutObject().StyleRef().ZIndex();
+ };
// Sort the two lists.
if (pos_z_order_list_)
@@ -145,7 +162,7 @@ void PaintLayerStackingNode::RebuildZOrderLists() {
// layer elements are children of the view, sorted in top layer stacking
// order.
if (Layer()->IsRootLayer()) {
- LayoutBlockFlow* root_block = GetLayoutObject().View();
+ LayoutBlockFlow* root_block = Layer()->GetLayoutObject().View();
// If the viewport is paginated, everything (including "top-layer" elements)
// gets redirected to the flow thread. So that's where we have to look, in
// that case.
@@ -160,12 +177,13 @@ void PaintLayerStackingNode::RebuildZOrderLists() {
: nullptr;
if (child_element && child_element->IsInTopLayer()) {
PaintLayer* layer = ToLayoutBoxModelObject(child)->Layer();
- // Create the buffer if it doesn't exist yet.
- if (!pos_z_order_list_) {
- pos_z_order_list_ =
- std::make_unique<Vector<PaintLayerStackingNode*>>();
+ if (layer->StackingNode()) {
+ // Create the buffer if it doesn't exist yet.
+ if (!pos_z_order_list_) {
+ pos_z_order_list_ = std::make_unique<PaintLayers>();
+ }
+ pos_z_order_list_->push_back(layer);
}
- pos_z_order_list_->push_back(layer->StackingNode());
}
}
}
@@ -178,42 +196,31 @@ void PaintLayerStackingNode::RebuildZOrderLists() {
}
void PaintLayerStackingNode::CollectLayers(
- std::unique_ptr<Vector<PaintLayerStackingNode*>>& pos_buffer,
- std::unique_ptr<Vector<PaintLayerStackingNode*>>& neg_buffer) {
- if (Layer()->IsInTopLayer())
+ PaintLayer* paint_layer,
+ std::unique_ptr<PaintLayers>& pos_buffer,
+ std::unique_ptr<PaintLayers>& neg_buffer) {
+ if (paint_layer->IsInTopLayer())
return;
- if (IsStacked()) {
- std::unique_ptr<Vector<PaintLayerStackingNode*>>& buffer =
- (ZIndex() >= 0) ? pos_buffer : neg_buffer;
+ const ComputedStyle& style = paint_layer->GetLayoutObject().StyleRef();
+
+ if (style.IsStacked()) {
+ std::unique_ptr<PaintLayers>& buffer =
+ (style.ZIndex() >= 0) ? pos_buffer : neg_buffer;
if (!buffer)
- buffer = std::make_unique<Vector<PaintLayerStackingNode*>>();
- buffer->push_back(this);
+ buffer = std::make_unique<PaintLayers>();
+ buffer->push_back(paint_layer);
}
- if (!IsStackingContext()) {
- for (PaintLayer* child = Layer()->FirstChild(); child;
- child = child->NextSibling())
- child->StackingNode()->CollectLayers(pos_buffer, neg_buffer);
+ if (!style.IsStackingContext()) {
+ for (PaintLayer* child = paint_layer->FirstChild(); child;
+ child = child->NextSibling()) {
+ CollectLayers(child, pos_buffer, neg_buffer);
+ }
}
}
#if DCHECK_IS_ON()
-bool PaintLayerStackingNode::IsInStackingParentZOrderLists() const {
- if (!stacking_parent_ || stacking_parent_->ZOrderListsDirty())
- return false;
-
- if (stacking_parent_->PosZOrderList() &&
- stacking_parent_->PosZOrderList()->Find(this) != kNotFound)
- return true;
-
- if (stacking_parent_->NegZOrderList() &&
- stacking_parent_->NegZOrderList()->Find(this) != kNotFound)
- return true;
-
- return false;
-}
-
void PaintLayerStackingNode::UpdateStackingParentForZOrderLists(
PaintLayerStackingNode* stacking_parent) {
if (pos_z_order_list_) {
@@ -229,49 +236,78 @@ void PaintLayerStackingNode::UpdateStackingParentForZOrderLists(
#endif
-void PaintLayerStackingNode::UpdateLayerListsIfNeeded() {
- UpdateZOrderLists();
-}
+bool PaintLayerStackingNode::StyleDidChange(PaintLayer* paint_layer,
+ const ComputedStyle* old_style) {
+ bool was_stacking_context = false;
+ bool was_stacked = false;
+ bool old_z_index = 0;
+ if (old_style) {
+ was_stacking_context = old_style->IsStackingContext();
+ old_z_index = old_style->ZIndex();
+ was_stacked = old_style->IsStacked();
+ }
-void PaintLayerStackingNode::StyleDidChange(const ComputedStyle* old_style) {
- bool was_stacking_context =
- old_style ? old_style->IsStackingContext() : false;
- int old_z_index = old_style ? old_style->ZIndex() : 0;
+ const ComputedStyle& new_style = paint_layer->GetLayoutObject().StyleRef();
- bool is_stacking_context = IsStackingContext();
- bool should_be_stacked = GetLayoutObject().StyleRef().IsStacked();
- if (is_stacking_context == was_stacking_context &&
- is_stacked_ == should_be_stacked && old_z_index == ZIndex())
- return;
+ bool should_be_stacking_context = new_style.IsStackingContext();
+ bool should_be_stacked = new_style.IsStacked();
+ if (should_be_stacking_context == was_stacking_context &&
+ was_stacked == should_be_stacked && old_z_index == new_style.ZIndex())
+ return false;
- DirtyStackingContextZOrderLists();
+ // Need to force requirements update, due to change of stacking order.
+ paint_layer->SetNeedsCompositingRequirementsUpdate();
+ DirtyStackingContextZOrderLists(paint_layer);
- if (is_stacking_context)
- DirtyZOrderLists();
- else
- ClearZOrderLists();
+ if (paint_layer->StackingNode()) {
+ if (should_be_stacking_context)
+ paint_layer->StackingNode()->DirtyZOrderLists();
+ else
+ paint_layer->StackingNode()->ClearZOrderLists();
+ }
- if (is_stacked_ != should_be_stacked) {
- is_stacked_ = should_be_stacked;
- if (!GetLayoutObject().DocumentBeingDestroyed() &&
- !Layer()->IsRootLayer() && Compositor())
- Compositor()->SetNeedsCompositingUpdate(kCompositingUpdateRebuildTree);
+ if (was_stacked != should_be_stacked) {
+ if (!paint_layer->GetLayoutObject().DocumentBeingDestroyed() &&
+ !paint_layer->IsRootLayer() && paint_layer->Compositor()) {
+ paint_layer->Compositor()->SetNeedsCompositingUpdate(
+ kCompositingUpdateRebuildTree);
+ }
}
+ return true;
}
-PaintLayerStackingNode* PaintLayerStackingNode::AncestorStackingContextNode()
- const {
- for (PaintLayer* ancestor = Layer()->Parent(); ancestor;
+PaintLayerStackingNode* PaintLayerStackingNode::AncestorStackingContextNode(
+ const PaintLayer* layer) {
+ for (PaintLayer* ancestor = layer->Parent(); ancestor;
ancestor = ancestor->Parent()) {
- PaintLayerStackingNode* stacking_node = ancestor->StackingNode();
- if (stacking_node->IsStackingContext())
- return stacking_node;
+ if (ancestor->GetLayoutObject().StyleRef().IsStackingContext())
+ return ancestor->StackingNode();
}
return nullptr;
}
-LayoutBoxModelObject& PaintLayerStackingNode::GetLayoutObject() const {
- return layer_->GetLayoutObject();
+void PaintLayerStackingNode::ClearZOrderLists() {
+ DCHECK(!Layer()->GetLayoutObject().StyleRef().IsStackingContext());
+
+#if DCHECK_IS_ON()
+ UpdateStackingParentForZOrderLists(nullptr);
+#endif
+
+ pos_z_order_list_.reset();
+ neg_z_order_list_.reset();
+}
+
+void PaintLayerStackingNode::UpdateZOrderLists() {
+ if (!z_order_lists_dirty_)
+ return;
+
+ if (!Layer()->GetLayoutObject().StyleRef().IsStackingContext()) {
+ ClearZOrderLists();
+ z_order_lists_dirty_ = false;
+ return;
+ }
+
+ RebuildZOrderLists();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node.h b/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node.h
index 075fd7fab01..3452619760f 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node.h
@@ -56,7 +56,6 @@ namespace blink {
class PaintLayer;
class PaintLayerCompositor;
class ComputedStyle;
-class LayoutBoxModelObject;
// PaintLayerStackingNode represents a stacked element which is either a
// stacking context or a positioned element.
@@ -97,26 +96,11 @@ class CORE_EXPORT PaintLayerStackingNode {
explicit PaintLayerStackingNode(PaintLayer*);
~PaintLayerStackingNode();
- int ZIndex() const { return GetLayoutObject().Style()->ZIndex(); }
-
- bool IsStackingContext() const {
- return GetLayoutObject().Style()->IsStackingContext();
- }
-
- // Whether the node is stacked. See documentation for the class about
- // "stacked". For now every PaintLayer has a PaintLayerStackingNode, even if
- // the layer is not stacked (e.g. a scrollable layer which is statically
- // positioned and is not a stacking context).
- bool IsStacked() const { return is_stacked_; }
-
- // Update our normal and z-index lists.
- void UpdateLayerListsIfNeeded();
-
bool ZOrderListsDirty() const { return z_order_lists_dirty_; }
void DirtyZOrderLists();
void UpdateZOrderLists();
void ClearZOrderLists();
- void DirtyStackingContextZOrderLists();
+ static void DirtyStackingContextZOrderLists(PaintLayer*);
bool HasPositiveZOrderList() const {
return PosZOrderList() && PosZOrderList()->size();
@@ -125,9 +109,9 @@ class CORE_EXPORT PaintLayerStackingNode {
return NegZOrderList() && NegZOrderList()->size();
}
- void StyleDidChange(const ComputedStyle* old_style);
-
- PaintLayerStackingNode* AncestorStackingContextNode() const;
+ // Returns whether a relevant style changed.
+ static bool StyleDidChange(PaintLayer* paint_layer,
+ const ComputedStyle* old_style);
PaintLayer* Layer() const { return layer_; }
@@ -138,54 +122,46 @@ class CORE_EXPORT PaintLayerStackingNode {
}
#endif
+ static PaintLayerStackingNode* AncestorStackingContextNode(const PaintLayer*);
+ using PaintLayers = Vector<PaintLayer*>;
+
private:
friend class PaintLayerStackingNodeIterator;
friend class PaintLayerStackingNodeReverseIterator;
friend class LayoutTreeAsText;
- Vector<PaintLayerStackingNode*>* PosZOrderList() const {
- DCHECK(!z_order_lists_dirty_);
- DCHECK(IsStackingContext() || !pos_z_order_list_);
- return pos_z_order_list_.get();
- }
+#if DCHECK_IS_ON()
+ friend class PaintLayer;
+#endif
- Vector<PaintLayerStackingNode*>* NegZOrderList() const {
- DCHECK(!z_order_lists_dirty_);
- DCHECK(IsStackingContext() || !neg_z_order_list_);
- return neg_z_order_list_.get();
- }
+ PaintLayers* PosZOrderList() const;
+
+ PaintLayers* NegZOrderList() const;
void RebuildZOrderLists();
- void CollectLayers(
- std::unique_ptr<Vector<PaintLayerStackingNode*>>& pos_z_order_list,
- std::unique_ptr<Vector<PaintLayerStackingNode*>>& neg_z_order_list);
+
+ static void CollectLayers(PaintLayer*,
+ std::unique_ptr<PaintLayers>& pos_z_order_list,
+ std::unique_ptr<PaintLayers>& neg_z_order_list);
#if DCHECK_IS_ON()
- bool IsInStackingParentZOrderLists() const;
void UpdateStackingParentForZOrderLists(
PaintLayerStackingNode* stacking_parent);
- void SetStackingParent(PaintLayerStackingNode* stacking_parent) {
- stacking_parent_ = stacking_parent;
- }
#endif
- bool IsDirtyStackingContext() const {
- return z_order_lists_dirty_ && IsStackingContext();
- }
+ bool IsDirtyStackingContext() const;
PaintLayerCompositor* Compositor() const;
- // We can't return a LayoutBox as LayoutInline can be a stacking context.
- LayoutBoxModelObject& GetLayoutObject() const;
PaintLayer* layer_;
// m_posZOrderList holds a sorted list of all the descendant nodes within
// that have z-indices of 0 (or is treated as 0 for positioned objects) or
// greater.
- std::unique_ptr<Vector<PaintLayerStackingNode*>> pos_z_order_list_;
+ std::unique_ptr<PaintLayers> pos_z_order_list_;
// m_negZOrderList holds descendants within our stacking context with
// negative z-indices.
- std::unique_ptr<Vector<PaintLayerStackingNode*>> neg_z_order_list_;
+ std::unique_ptr<PaintLayers> neg_z_order_list_;
// This boolean caches whether the z-order lists above are dirty.
// It is only ever set for stacking contexts, as no other element can
@@ -200,36 +176,11 @@ class CORE_EXPORT PaintLayerStackingNode {
#if DCHECK_IS_ON()
bool layer_list_mutation_allowed_ : 1;
- PaintLayerStackingNode* stacking_parent_;
#endif
DISALLOW_COPY_AND_ASSIGN(PaintLayerStackingNode);
};
-inline void PaintLayerStackingNode::ClearZOrderLists() {
- DCHECK(!IsStackingContext());
-
-#if DCHECK_IS_ON()
- UpdateStackingParentForZOrderLists(nullptr);
-#endif
-
- pos_z_order_list_.reset();
- neg_z_order_list_.reset();
-}
-
-inline void PaintLayerStackingNode::UpdateZOrderLists() {
- if (!z_order_lists_dirty_)
- return;
-
- if (!IsStackingContext()) {
- ClearZOrderLists();
- z_order_lists_dirty_ = false;
- return;
- }
-
- RebuildZOrderLists();
-}
-
#if DCHECK_IS_ON()
class LayerListMutationDetector {
public:
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.cc b/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.cc
index 267d312ac16..076e289a1a3 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.cc
@@ -44,9 +44,10 @@ PaintLayerStackingNodeIterator::PaintLayerStackingNodeIterator(
current_normal_flow_child_ = root.Layer()->FirstChild();
}
-PaintLayerStackingNode* PaintLayerStackingNodeIterator::Next() {
+PaintLayer* PaintLayerStackingNodeIterator::Next() {
if (remaining_children_ & kNegativeZOrderChildren) {
- Vector<PaintLayerStackingNode*>* neg_z_order_list = root_.NegZOrderList();
+ PaintLayerStackingNode::PaintLayers* neg_z_order_list =
+ root_.NegZOrderList();
if (neg_z_order_list && index_ < neg_z_order_list->size())
return neg_z_order_list->at(index_++);
@@ -58,10 +59,12 @@ PaintLayerStackingNode* PaintLayerStackingNodeIterator::Next() {
for (; current_normal_flow_child_;
current_normal_flow_child_ =
current_normal_flow_child_->NextSibling()) {
- if (!current_normal_flow_child_->StackingNode()->IsStacked()) {
+ if (!current_normal_flow_child_->GetLayoutObject()
+ .StyleRef()
+ .IsStacked()) {
PaintLayer* normal_flow_child = current_normal_flow_child_;
current_normal_flow_child_ = current_normal_flow_child_->NextSibling();
- return normal_flow_child->StackingNode();
+ return normal_flow_child;
}
}
@@ -71,7 +74,8 @@ PaintLayerStackingNode* PaintLayerStackingNodeIterator::Next() {
}
if (remaining_children_ & kPositiveZOrderChildren) {
- Vector<PaintLayerStackingNode*>* pos_z_order_list = root_.PosZOrderList();
+ PaintLayerStackingNode::PaintLayers* pos_z_order_list =
+ root_.PosZOrderList();
if (pos_z_order_list && index_ < pos_z_order_list->size())
return pos_z_order_list->at(index_++);
@@ -82,9 +86,10 @@ PaintLayerStackingNode* PaintLayerStackingNodeIterator::Next() {
return nullptr;
}
-PaintLayerStackingNode* PaintLayerStackingNodeReverseIterator::Next() {
+PaintLayer* PaintLayerStackingNodeReverseIterator::Next() {
if (remaining_children_ & kNegativeZOrderChildren) {
- Vector<PaintLayerStackingNode*>* neg_z_order_list = root_.NegZOrderList();
+ PaintLayerStackingNode::PaintLayers* neg_z_order_list =
+ root_.NegZOrderList();
if (neg_z_order_list && index_ >= 0)
return neg_z_order_list->at(index_--);
@@ -96,11 +101,13 @@ PaintLayerStackingNode* PaintLayerStackingNodeReverseIterator::Next() {
for (; current_normal_flow_child_;
current_normal_flow_child_ =
current_normal_flow_child_->PreviousSibling()) {
- if (!current_normal_flow_child_->StackingNode()->IsStacked()) {
+ if (!current_normal_flow_child_->GetLayoutObject()
+ .StyleRef()
+ .IsStacked()) {
PaintLayer* normal_flow_child = current_normal_flow_child_;
current_normal_flow_child_ =
current_normal_flow_child_->PreviousSibling();
- return normal_flow_child->StackingNode();
+ return normal_flow_child;
}
}
@@ -109,7 +116,8 @@ PaintLayerStackingNode* PaintLayerStackingNodeReverseIterator::Next() {
}
if (remaining_children_ & kPositiveZOrderChildren) {
- Vector<PaintLayerStackingNode*>* pos_z_order_list = root_.PosZOrderList();
+ PaintLayerStackingNode::PaintLayers* pos_z_order_list =
+ root_.PosZOrderList();
if (pos_z_order_list && index_ >= 0)
return pos_z_order_list->at(index_--);
@@ -122,7 +130,8 @@ PaintLayerStackingNode* PaintLayerStackingNodeReverseIterator::Next() {
void PaintLayerStackingNodeReverseIterator::SetIndexToLastItem() {
if (remaining_children_ & kNegativeZOrderChildren) {
- Vector<PaintLayerStackingNode*>* neg_z_order_list = root_.NegZOrderList();
+ PaintLayerStackingNode::PaintLayers* neg_z_order_list =
+ root_.NegZOrderList();
if (neg_z_order_list) {
index_ = neg_z_order_list->size() - 1;
return;
@@ -137,7 +146,8 @@ void PaintLayerStackingNodeReverseIterator::SetIndexToLastItem() {
}
if (remaining_children_ & kPositiveZOrderChildren) {
- Vector<PaintLayerStackingNode*>* pos_z_order_list = root_.PosZOrderList();
+ PaintLayerStackingNode::PaintLayers* pos_z_order_list =
+ root_.PosZOrderList();
if (pos_z_order_list) {
index_ = pos_z_order_list->size() - 1;
return;
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h b/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h
index 52b5f66f3fe..40136836cad 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h
@@ -60,7 +60,7 @@ class PaintLayerStackingNodeIterator {
PaintLayerStackingNodeIterator(const PaintLayerStackingNode& root,
unsigned which_children);
- PaintLayerStackingNode* Next();
+ PaintLayer* Next();
private:
const PaintLayerStackingNode& root_;
@@ -82,7 +82,7 @@ class PaintLayerStackingNodeReverseIterator {
SetIndexToLastItem();
}
- PaintLayerStackingNode* Next();
+ PaintLayer* Next();
private:
void SetIndexToLastItem();
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 19628a9b623..c404de1f3b1 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
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
#include "third_party/blink/renderer/core/layout/layout_box_model_object.h"
#include "third_party/blink/renderer/core/layout/layout_view.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/paint_test_configurations.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
@@ -232,7 +233,6 @@ TEST_P(PaintLayerTest, CompositedScrollingNoNeedsRepaint) {
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
return;
- EnableCompositing();
SetBodyInnerHTML(R"HTML(
<div id='scroll' style='width: 100px; height: 100px; overflow: scroll;
will-change: transform'>
@@ -283,10 +283,7 @@ TEST_P(PaintLayerTest, NonCompositedScrollingNeedsRepaint) {
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
EXPECT_EQ(LayoutPoint(-1000, -1000), content_layer->Location());
EXPECT_TRUE(scroll_layer->NeedsRepaint());
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- EXPECT_FALSE(content_layer->NeedsRepaint());
- else
- EXPECT_TRUE(content_layer->NeedsRepaint());
+ EXPECT_FALSE(content_layer->NeedsRepaint());
GetDocument().View()->UpdateAllLifecyclePhases();
}
@@ -314,6 +311,225 @@ TEST_P(PaintLayerTest, HasNonIsolatedDescendantWithBlendMode) {
EXPECT_TRUE(parent->HasVisibleDescendant());
}
+TEST_P(PaintLayerTest, HasDescendantWithSticky) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='parent' style='isolation: isolate'>
+ <div id='child' style='position: sticky'>
+ </div>
+ </div>
+ )HTML");
+ PaintLayer* parent = GetPaintLayerByElementId("parent");
+ PaintLayer* child = GetPaintLayerByElementId("child");
+ EXPECT_TRUE(parent->HasDescendantWithStickyOrFixed());
+ EXPECT_FALSE(child->HasDescendantWithStickyOrFixed());
+
+ GetDocument().getElementById("child")->setAttribute(HTMLNames::styleAttr,
+ "position: relative");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ EXPECT_FALSE(parent->HasDescendantWithStickyOrFixed());
+ EXPECT_FALSE(child->HasDescendantWithStickyOrFixed());
+}
+
+TEST_P(PaintLayerTest, HasDescendantWithFixed) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='parent' style='isolation: isolate'>
+ <div id='child' style='position: fixed'>
+ </div>
+ </div>
+ )HTML");
+ PaintLayer* parent = GetPaintLayerByElementId("parent");
+ PaintLayer* child = GetPaintLayerByElementId("child");
+ EXPECT_TRUE(parent->HasDescendantWithStickyOrFixed());
+ EXPECT_FALSE(child->HasDescendantWithStickyOrFixed());
+
+ GetDocument().getElementById("child")->setAttribute(HTMLNames::styleAttr,
+ "position: relative");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ EXPECT_FALSE(parent->HasDescendantWithStickyOrFixed());
+ EXPECT_FALSE(child->HasDescendantWithStickyOrFixed());
+}
+
+TEST_P(PaintLayerTest, HasDescendantWithFixedAndSticky) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='parent' style='isolation: isolate'>
+ <div id='child1' style='position: sticky'>
+ </div>
+ <div id='child2' style='position: fixed'>
+ </div>
+ </div>
+ )HTML");
+ PaintLayer* parent = GetPaintLayerByElementId("parent");
+ PaintLayer* child1 = GetPaintLayerByElementId("child1");
+ PaintLayer* child2 = GetPaintLayerByElementId("child2");
+ EXPECT_TRUE(parent->HasDescendantWithStickyOrFixed());
+ EXPECT_FALSE(child1->HasDescendantWithStickyOrFixed());
+ EXPECT_FALSE(child2->HasDescendantWithStickyOrFixed());
+
+ GetDocument().getElementById("child1")->setAttribute(HTMLNames::styleAttr,
+ "position: relative");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ EXPECT_TRUE(parent->HasDescendantWithStickyOrFixed());
+ EXPECT_FALSE(child1->HasDescendantWithStickyOrFixed());
+ EXPECT_FALSE(child2->HasDescendantWithStickyOrFixed());
+
+ GetDocument().getElementById("child2")->setAttribute(HTMLNames::styleAttr,
+ "position: relative");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ EXPECT_FALSE(parent->HasDescendantWithStickyOrFixed());
+ EXPECT_FALSE(child1->HasDescendantWithStickyOrFixed());
+ EXPECT_FALSE(child2->HasDescendantWithStickyOrFixed());
+}
+
+TEST_P(PaintLayerTest, HasNonContainedAbsolutePositionDescendant) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='parent' style='isolation: isolate'>
+ <div id='child' style='position: relative'>
+ </div>
+ </div>
+ )HTML");
+ PaintLayer* parent = GetPaintLayerByElementId("parent");
+ PaintLayer* child = GetPaintLayerByElementId("child");
+ EXPECT_FALSE(parent->HasNonContainedAbsolutePositionDescendant());
+ EXPECT_FALSE(child->HasNonContainedAbsolutePositionDescendant());
+
+ GetDocument().getElementById("child")->setAttribute(HTMLNames::styleAttr,
+ "position: absolute");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ EXPECT_TRUE(parent->HasNonContainedAbsolutePositionDescendant());
+ EXPECT_FALSE(child->HasNonContainedAbsolutePositionDescendant());
+
+ GetDocument().getElementById("parent")->setAttribute(HTMLNames::styleAttr,
+ "position: relative");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ EXPECT_FALSE(parent->HasNonContainedAbsolutePositionDescendant());
+ EXPECT_FALSE(child->HasNonContainedAbsolutePositionDescendant());
+}
+
+TEST_P(PaintLayerTest, HasSelfPaintingDescendant) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='parent' style='position: relative'>
+ <div id='child' style='position: relative'>
+ <div></div>
+ </div>
+ </div>
+ )HTML");
+ PaintLayer* parent = GetPaintLayerByElementId("parent");
+ PaintLayer* child = GetPaintLayerByElementId("child");
+
+ EXPECT_TRUE(parent->HasSelfPaintingLayerDescendant());
+ EXPECT_FALSE(child->HasSelfPaintingLayerDescendant());
+}
+
+TEST_P(PaintLayerTest, HasSelfPaintingDescendantNotSelfPainting) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='parent' style='position: relative'>
+ <div id='child' style='overflow: auto'>
+ <div></div>
+ </div>
+ </div>
+ )HTML");
+ PaintLayer* parent = GetPaintLayerByElementId("parent");
+ PaintLayer* child = GetPaintLayerByElementId("child");
+
+ EXPECT_FALSE(parent->HasSelfPaintingLayerDescendant());
+ EXPECT_FALSE(child->HasSelfPaintingLayerDescendant());
+}
+
+TEST_P(PaintLayerTest, HasSelfPaintingParentNotSelfPainting) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='parent' style='overflow: auto'>
+ <div id='child' style='position: relative'>
+ <div></div>
+ </div>
+ </div>
+ )HTML");
+ PaintLayer* parent = GetPaintLayerByElementId("parent");
+ PaintLayer* child = GetPaintLayerByElementId("child");
+
+ EXPECT_TRUE(parent->HasSelfPaintingLayerDescendant());
+ EXPECT_FALSE(child->HasSelfPaintingLayerDescendant());
+}
+
+TEST_P(PaintLayerTest, NonStackedWithInFlowDescendant) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='parent' style='overflow: auto'>
+ <div id='child' style='position: relative'>
+ <div></div>
+ </div>
+ </div>
+ )HTML");
+ PaintLayer* parent = GetPaintLayerByElementId("parent");
+ PaintLayer* child = GetPaintLayerByElementId("child");
+
+ EXPECT_TRUE(parent->IsNonStackedWithInFlowStackedDescendant());
+ EXPECT_FALSE(child->IsNonStackedWithInFlowStackedDescendant());
+}
+
+TEST_P(PaintLayerTest, NonStackedWithOutOfFlowDescendant) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='parent' style='overflow: auto'>
+ <div id='child' style='position: absolute'>
+ <div></div>
+ </div>
+ </div>
+ )HTML");
+ PaintLayer* parent = GetPaintLayerByElementId("parent");
+ PaintLayer* child = GetPaintLayerByElementId("child");
+
+ EXPECT_FALSE(parent->IsNonStackedWithInFlowStackedDescendant());
+ EXPECT_FALSE(child->IsNonStackedWithInFlowStackedDescendant());
+}
+
+TEST_P(PaintLayerTest, NonStackedWithNonStackedDescendant) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='parent' style='overflow: auto'>
+ <div id='child' style='overflow: auto'>
+ <div></div>
+ </div>
+ </div>
+ )HTML");
+ PaintLayer* parent = GetPaintLayerByElementId("parent");
+ PaintLayer* child = GetPaintLayerByElementId("child");
+
+ EXPECT_FALSE(parent->IsNonStackedWithInFlowStackedDescendant());
+ EXPECT_FALSE(child->IsNonStackedWithInFlowStackedDescendant());
+}
+
+TEST_P(PaintLayerTest, NonStackedWithInFlowStackedGrandchild) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='parent' style='overflow: auto'>
+ <div id='child' style='overflow: auto'>
+ <div style='position: relative'></div>
+ </div>
+ </div>
+ )HTML");
+ PaintLayer* parent = GetPaintLayerByElementId("parent");
+ PaintLayer* child = GetPaintLayerByElementId("child");
+
+ EXPECT_TRUE(parent->IsNonStackedWithInFlowStackedDescendant());
+ EXPECT_TRUE(child->IsNonStackedWithInFlowStackedDescendant());
+}
+
+TEST_P(PaintLayerTest, NonStackedWithOutOfFlowStackedGrandchild) {
+ SetBodyInnerHTML(R"HTML(
+ <div id='parent' style='overflow: auto'>
+ <div id='child' style='overflow: auto'>
+ <div style='position: absolute'></div>
+ </div>
+ </div>
+ )HTML");
+ PaintLayer* parent = GetPaintLayerByElementId("parent");
+ PaintLayer* child = GetPaintLayerByElementId("child");
+
+ EXPECT_FALSE(parent->IsNonStackedWithInFlowStackedDescendant());
+ EXPECT_FALSE(child->IsNonStackedWithInFlowStackedDescendant());
+}
+
TEST_P(PaintLayerTest, SubsequenceCachingStackingContexts) {
SetBodyInnerHTML(R"HTML(
<div id='parent' style='position:relative'>
@@ -357,7 +573,7 @@ TEST_P(PaintLayerTest, SubsequenceCachingSVGRoot) {
)HTML");
PaintLayer* svgroot = GetPaintLayerByElementId("svgroot");
- EXPECT_FALSE(svgroot->SupportsSubsequenceCaching());
+ EXPECT_TRUE(svgroot->SupportsSubsequenceCaching());
}
TEST_P(PaintLayerTest, SubsequenceCachingMuticol) {
@@ -389,7 +605,6 @@ TEST_P(PaintLayerTest, HasDescendantWithClipPath) {
}
TEST_P(PaintLayerTest, HasVisibleDescendant) {
- EnableCompositing();
SetBodyInnerHTML(R"HTML(
<div id='invisible' style='position:relative'>
<div id='visible' style='visibility: visible; position: relative'>
@@ -407,7 +622,6 @@ TEST_P(PaintLayerTest, HasVisibleDescendant) {
}
TEST_P(PaintLayerTest, Has3DTransformedDescendant) {
- EnableCompositing();
SetBodyInnerHTML(R"HTML(
<div id='parent' style='position:relative; z-index: 0'>
<div id='child' style='transform: translateZ(1px)'>
@@ -422,7 +636,6 @@ TEST_P(PaintLayerTest, Has3DTransformedDescendant) {
}
TEST_P(PaintLayerTest, Has3DTransformedDescendantChangeStyle) {
- EnableCompositing();
SetBodyInnerHTML(R"HTML(
<div id='parent' style='position:relative; z-index: 0'>
<div id='child' style='position:relative '>
@@ -444,7 +657,6 @@ TEST_P(PaintLayerTest, Has3DTransformedDescendantChangeStyle) {
}
TEST_P(PaintLayerTest, Has3DTransformedDescendantNotStacking) {
- EnableCompositing();
SetBodyInnerHTML(R"HTML(
<div id='parent' style='position:relative;'>
<div id='child' style='transform: translateZ(1px)'>
@@ -461,7 +673,6 @@ TEST_P(PaintLayerTest, Has3DTransformedDescendantNotStacking) {
}
TEST_P(PaintLayerTest, Has3DTransformedGrandchildWithPreserve3d) {
- EnableCompositing();
SetBodyInnerHTML(R"HTML(
<div id='parent' style='position:relative; z-index: 0'>
<div id='child' style='transform-style: preserve-3d'>
@@ -480,7 +691,6 @@ TEST_P(PaintLayerTest, Has3DTransformedGrandchildWithPreserve3d) {
}
TEST_P(PaintLayerTest, DescendantDependentFlagsStopsAtThrottledFrames) {
- EnableCompositing();
SetBodyInnerHTML(R"HTML(
<style>body { margin: 0; }</style>
<div id='transform' style='transform: translate3d(4px, 5px, 6px);'>
@@ -566,19 +776,12 @@ TEST_P(PaintLayerTest, PaintInvalidationOnNonCompositedScroll) {
scroller->GetScrollableArea()->SetScrollOffset(ScrollOffset(0, 20),
kProgrammaticScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(LayoutRect(0, 30, 50, 10),
- content_layer->FirstFragment().VisualRect());
- EXPECT_EQ(LayoutRect(0, 30, 50, 5), content->FirstFragment().VisualRect());
- } else {
- EXPECT_EQ(LayoutRect(0, 10, 50, 10),
- content_layer->FirstFragment().VisualRect());
- EXPECT_EQ(LayoutRect(0, 10, 50, 5), content->FirstFragment().VisualRect());
- }
+ EXPECT_EQ(LayoutRect(0, 30, 50, 10),
+ content_layer->FirstFragment().VisualRect());
+ EXPECT_EQ(LayoutRect(0, 30, 50, 5), content->FirstFragment().VisualRect());
}
TEST_P(PaintLayerTest, PaintInvalidationOnCompositedScroll) {
- EnableCompositing();
SetBodyInnerHTML(R"HTML(
<style>* { margin: 0 } ::-webkit-scrollbar { display: none }</style>
<div id='scroller' style='overflow: scroll; width: 50px; height: 50px;
@@ -608,7 +811,6 @@ TEST_P(PaintLayerTest, PaintInvalidationOnCompositedScroll) {
}
TEST_P(PaintLayerTest, CompositingContainerStackedFloatUnderStackingInline) {
- EnableCompositing();
SetBodyInnerHTML(R"HTML(
<div id='compositedContainer' style='position: relative;
will-change: transform'>
@@ -633,7 +835,6 @@ TEST_P(PaintLayerTest, CompositingContainerStackedFloatUnderStackingInline) {
TEST_P(PaintLayerTest,
CompositingContainerStackedFloatUnderStackingCompositedInline) {
- EnableCompositing();
SetBodyInnerHTML(R"HTML(
<div id='compositedContainer' style='position: relative;
will-change: transform'>
@@ -658,7 +859,6 @@ TEST_P(PaintLayerTest,
}
TEST_P(PaintLayerTest, CompositingContainerNonStackedFloatUnderStackingInline) {
- EnableCompositing();
SetBodyInnerHTML(R"HTML(
<div id='compositedContainer' style='position: relative;
will-change: transform'>
@@ -684,7 +884,6 @@ TEST_P(PaintLayerTest, CompositingContainerNonStackedFloatUnderStackingInline) {
TEST_P(PaintLayerTest,
CompositingContainerNonStackedFloatUnderStackingCompositedInline) {
- EnableCompositing();
SetBodyInnerHTML(R"HTML(
<div id='compositedContainer' style='position: relative;
will-change: transform'>
@@ -710,7 +909,6 @@ TEST_P(PaintLayerTest,
TEST_P(PaintLayerTest,
CompositingContainerStackedUnderFloatUnderStackingInline) {
- EnableCompositing();
SetBodyInnerHTML(R"HTML(
<div id='compositedContainer' style='position: relative;
will-change: transform'>
@@ -737,7 +935,6 @@ TEST_P(PaintLayerTest,
TEST_P(PaintLayerTest,
CompositingContainerStackedUnderFloatUnderStackingCompositedInline) {
- EnableCompositing();
SetBodyInnerHTML(R"HTML(
<div id='compositedContainer' style='position: relative;
will-change: transform'>
@@ -765,7 +962,6 @@ TEST_P(PaintLayerTest,
TEST_P(PaintLayerTest,
CompositingContainerNonStackedUnderFloatUnderStackingInline) {
- EnableCompositing();
SetBodyInnerHTML(R"HTML(
<div id='compositedContainer' style='position: relative;
will-change: transform'>
@@ -793,7 +989,6 @@ TEST_P(PaintLayerTest,
TEST_P(PaintLayerTest,
CompositingContainerNonStackedUnderFloatUnderStackingCompositedInline) {
- EnableCompositing();
SetBodyInnerHTML(R"HTML(
<div id='compositedContainer' style='position: relative;
will-change: transform'>
@@ -999,7 +1194,6 @@ TEST_P(PaintLayerTest, LayerUnderFloatUnderInlineLayer) {
}
TEST_P(PaintLayerTest, CompositingContainerFloatingIframe) {
- EnableCompositing();
SetBodyInnerHTML(R"HTML(
<div id='compositedContainer' style='position: relative;
will-change: transform'>
@@ -1043,7 +1237,7 @@ TEST_P(PaintLayerTest, CompositingContainerSelfPaintingNonStackedFloat) {
// The target layer is self-painting, but not stacked.
PaintLayer* target = GetPaintLayerByElementId("target");
EXPECT_TRUE(target->IsSelfPaintingLayer());
- EXPECT_FALSE(target->StackingNode()->IsStacked());
+ EXPECT_FALSE(target->GetLayoutObject().StyleRef().IsStacked());
PaintLayer* container = GetPaintLayerByElementId("container");
PaintLayer* span = GetPaintLayerByElementId("span");
@@ -1138,7 +1332,6 @@ TEST_P(PaintLayerTest, NeedsRepaintOnSelfPaintingStatusChange) {
}
TEST_P(PaintLayerTest, NeedsRepaintOnRemovingStackedLayer) {
- EnableCompositing();
SetBodyInnerHTML(
"<style>body {margin-top: 200px; backface-visibility: hidden}</style>"
"<div id='target' style='position: absolute; top: 0'>Text</div>");
@@ -1151,7 +1344,7 @@ TEST_P(PaintLayerTest, NeedsRepaintOnRemovingStackedLayer) {
// |container| is not the CompositingContainer of |target| because |target|
// is stacked but |container| is not a stacking context.
- EXPECT_TRUE(target_layer->StackingNode()->IsStacked());
+ EXPECT_TRUE(target_layer->GetLayoutObject().StyleRef().IsStacked());
EXPECT_NE(body_layer, target_layer->CompositingContainer());
auto* old_compositing_container = target_layer->CompositingContainer();
@@ -1169,7 +1362,7 @@ TEST_P(PaintLayerTest, NeedsRepaintOnRemovingStackedLayer) {
TEST_P(PaintLayerTest, FrameViewContentSize) {
SetBodyInnerHTML(
"<style> body { width: 1200px; height: 900px; margin: 0 } </style>");
- EXPECT_EQ(IntSize(800, 600), GetDocument().View()->ContentsSize());
+ EXPECT_EQ(IntSize(800, 600), GetDocument().View()->Size());
}
TEST_P(PaintLayerTest, ReferenceClipPathWithPageZoom) {
@@ -1260,8 +1453,8 @@ TEST_P(PaintLayerTest, SquashingOffsets) {
EXPECT_EQ(LayoutPoint(0, 0), squashed->ComputeOffsetFromAncestor(
squashed->TransformAncestorOrRoot()));
- GetDocument().View()->LayoutViewportScrollableArea()->ScrollBy(
- ScrollOffset(0, 25), kUserScroll);
+ GetDocument().View()->LayoutViewport()->ScrollBy(ScrollOffset(0, 25),
+ kUserScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
PaintLayer::MapPointInPaintInvalidationContainerToBacking(
@@ -1281,8 +1474,9 @@ TEST_P(PaintLayerTest, HitTestWithIgnoreClipping) {
HitTestRequest request(HitTestRequest::kIgnoreClipping);
// (10, 900) is outside the viewport clip of 800x600.
- HitTestResult result(request, IntPoint(10, 900));
- GetDocument().GetLayoutView()->HitTest(result);
+ HitTestLocation location((IntPoint(10, 900)));
+ HitTestResult result(request, location);
+ GetDocument().GetLayoutView()->HitTest(location, result);
EXPECT_EQ(GetDocument().getElementById("hit"), result.InnerNode());
}
@@ -1299,38 +1493,40 @@ TEST_P(PaintLayerTest, HitTestWithStopNode) {
// Regular hit test over 'child'
HitTestRequest request(HitTestRequest::kReadOnly | HitTestRequest::kActive);
- HitTestResult result(request, LayoutPoint(50, 25));
- GetDocument().GetLayoutView()->Layer()->HitTest(result);
+ HitTestLocation location((LayoutPoint(50, 25)));
+ HitTestResult result(request, location);
+ GetDocument().GetLayoutView()->HitTest(location, result);
EXPECT_EQ(child, result.InnerNode());
// Same hit test, with stop node.
request = HitTestRequest(HitTestRequest::kReadOnly | HitTestRequest::kActive,
hit->GetLayoutObject());
- result = HitTestResult(request, LayoutPoint(50, 25));
- GetDocument().GetLayoutView()->Layer()->HitTest(result);
+ result = HitTestResult(request, location);
+ GetDocument().GetLayoutView()->HitTest(location, result);
EXPECT_EQ(hit, result.InnerNode());
// Regular hit test over 'overlap'
request = HitTestRequest(HitTestRequest::kReadOnly | HitTestRequest::kActive);
- result = HitTestResult(request, LayoutPoint(50, 75));
- GetDocument().GetLayoutView()->Layer()->HitTest(result);
+ location = HitTestLocation((LayoutPoint(50, 75)));
+ result = HitTestResult(request, location);
+ GetDocument().GetLayoutView()->HitTest(location, result);
EXPECT_EQ(overlap, result.InnerNode());
// Same hit test, with stop node, should still hit 'overlap' because it's not
// a descendant of 'hit'.
request = HitTestRequest(HitTestRequest::kReadOnly | HitTestRequest::kActive,
hit->GetLayoutObject());
- result = HitTestResult(request, LayoutPoint(50, 75));
- GetDocument().GetLayoutView()->Layer()->HitTest(result);
+ result = HitTestResult(request, location);
+ GetDocument().GetLayoutView()->HitTest(location, result);
EXPECT_EQ(overlap, result.InnerNode());
// List-based hit test with stop node
request = HitTestRequest(HitTestRequest::kReadOnly | HitTestRequest::kActive |
HitTestRequest::kListBased,
hit->GetLayoutObject());
- result = HitTestResult(request, LayoutPoint(50, 25),
- LayoutRectOutsets(10, 10, 10, 10));
- GetDocument().GetLayoutView()->Layer()->HitTest(result);
+ location = HitTestLocation((LayoutRect(40, 15, 20, 20)));
+ result = HitTestResult(request, location);
+ GetDocument().GetLayoutView()->HitTest(location, result);
EXPECT_EQ(1u, result.ListBasedTestResult().size());
EXPECT_EQ(hit, *result.ListBasedTestResult().begin());
}
@@ -1357,14 +1553,15 @@ TEST_P(PaintLayerTest, HitTestTableWithStopNode) {
Element* table = GetDocument().getElementById("table");
Element* cell11 = GetDocument().getElementById("cell11");
HitTestRequest request(HitTestRequest::kReadOnly | HitTestRequest::kActive);
- HitTestResult result(request, LayoutPoint(50, 50));
- GetDocument().GetLayoutView()->Layer()->HitTest(result);
+ HitTestLocation location((LayoutPoint(50, 50)));
+ HitTestResult result(request, location);
+ GetDocument().GetLayoutView()->HitTest(location, result);
EXPECT_EQ(cell11, result.InnerNode());
request = HitTestRequest(HitTestRequest::kReadOnly | HitTestRequest::kActive,
table->GetLayoutObject());
- result = HitTestResult(request, LayoutPoint(50, 50));
- GetDocument().GetLayoutView()->Layer()->HitTest(result);
+ result = HitTestResult(request, location);
+ GetDocument().GetLayoutView()->HitTest(location, result);
EXPECT_EQ(table, result.InnerNode());
}
@@ -1377,14 +1574,15 @@ TEST_P(PaintLayerTest, HitTestSVGWithStopNode) {
Element* svg = GetDocument().getElementById("svg");
Element* circle = GetDocument().getElementById("circle");
HitTestRequest request(HitTestRequest::kReadOnly | HitTestRequest::kActive);
- HitTestResult result(request, LayoutPoint(50, 50));
- GetDocument().GetLayoutView()->Layer()->HitTest(result);
+ HitTestLocation location((LayoutPoint(50, 50)));
+ HitTestResult result(request, location);
+ GetDocument().GetLayoutView()->HitTest(location, result);
EXPECT_EQ(circle, result.InnerNode());
request = HitTestRequest(HitTestRequest::kReadOnly | HitTestRequest::kActive,
svg->GetLayoutObject());
- result = HitTestResult(request, LayoutPoint(50, 50));
- GetDocument().GetLayoutView()->Layer()->HitTest(result);
+ result = HitTestResult(request, location);
+ GetDocument().GetLayoutView()->HitTest(location, result);
EXPECT_EQ(svg, result.InnerNode());
}
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_phase.h b/chromium/third_party/blink/renderer/core/paint/paint_phase.h
index c086e081074..a4e23b70397 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_phase.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_phase.h
@@ -33,6 +33,8 @@ namespace blink {
// descent into the layer's layout objects in painting order:
// 1. Background phase: backgrounds and borders of all blocks are painted.
// Inlines are not painted at all.
+// With |PaintTouchActionRects|, hit testing is "painted" during the
+// background phase (see: paint/README.md#hit-test-painting).
// 2. Float phase: floating objects are painted above block backgrounds but
// entirely below inline content that can overlap them.
// 3. Foreground phase: all inlines are fully painted. Atomic inline elements
@@ -85,11 +87,8 @@ enum class PaintPhase {
kSelection = 8,
kTextClip = 9,
kMask = 10,
- // TODO(wangxianzhu): Remove this phase for SPv175+. Use a dedicated display
- // item type for the drawings.
- kClippingMask = 11,
- kMax = kClippingMask,
+ kMax = kMask,
// These values must be kept in sync with DisplayItem::Type and
// DisplayItem::typeAsDebugString().
};
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 bdf35a040a9..b1a44f09e08 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
@@ -5,10 +5,12 @@
#include "third_party/blink/renderer/core/paint/paint_property_tree_builder.h"
#include <memory>
+#include "third_party/blink/renderer/core/animation/scroll_timeline.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/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/layout/fragmentainer_iterator.h"
#include "third_party/blink/renderer/core/layout/layout_image.h"
#include "third_party/blink/renderer/core/layout/layout_inline.h"
@@ -30,6 +32,7 @@
#include "third_party/blink/renderer/core/paint/find_properties_needing_update.h"
#include "third_party/blink/renderer/core/paint/object_paint_properties.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/paint/paint_property_tree_printer.h"
#include "third_party/blink/renderer/core/paint/svg_root_painter.h"
#include "third_party/blink/renderer/platform/transforms/transform_state.h"
@@ -39,13 +42,38 @@ namespace blink {
PaintPropertyTreeBuilderFragmentContext::
PaintPropertyTreeBuilderFragmentContext()
- : current_effect(EffectPaintPropertyNode::Root()) {
+ : current_effect(&EffectPaintPropertyNode::Root()) {
current.clip = absolute_position.clip = fixed_position.clip =
- ClipPaintPropertyNode::Root();
+ &ClipPaintPropertyNode::Root();
current.transform = absolute_position.transform = fixed_position.transform =
- TransformPaintPropertyNode::Root();
+ &TransformPaintPropertyNode::Root();
current.scroll = absolute_position.scroll = fixed_position.scroll =
- ScrollPaintPropertyNode::Root();
+ &ScrollPaintPropertyNode::Root();
+}
+
+void VisualViewportPaintPropertyTreeBuilder::Update(
+ VisualViewport& visual_viewport,
+ PaintPropertyTreeBuilderContext& full_context) {
+ if (full_context.fragments.IsEmpty())
+ full_context.fragments.push_back(PaintPropertyTreeBuilderFragmentContext());
+
+ PaintPropertyTreeBuilderFragmentContext& context = full_context.fragments[0];
+
+ visual_viewport.UpdatePaintPropertyNodes(context.current.transform,
+ context.current.scroll);
+
+ context.current.transform = visual_viewport.GetScrollTranslationNode();
+ context.absolute_position.transform =
+ visual_viewport.GetScrollTranslationNode();
+ context.fixed_position.transform = visual_viewport.GetScrollTranslationNode();
+
+ context.current.scroll = visual_viewport.GetScrollNode();
+ context.absolute_position.scroll = visual_viewport.GetScrollNode();
+ context.fixed_position.scroll = visual_viewport.GetScrollNode();
+
+#if DCHECK_IS_ON()
+ PaintPropertyTreePrinter::UpdateDebugNames(visual_viewport);
+#endif
}
void PaintPropertyTreeBuilder::SetupContextForFrame(
@@ -160,7 +188,10 @@ class FragmentPaintPropertyTreeBuilder {
static bool NeedsScrollNode(const LayoutObject& object) {
if (!object.HasOverflowClip())
return false;
- return ToLayoutBox(object).GetScrollableArea()->ScrollsOverflow();
+ // TODO(crbug.com/839341): Remove ScrollTimeline check once we support
+ // main-thread AnimationWorklet and don't need to promote the scroll-source.
+ return ToLayoutBox(object).GetScrollableArea()->ScrollsOverflow() ||
+ ScrollTimeline::HasActiveScrollTimeline(object.GetNode());
}
static CompositingReasons CompositingReasonsForScroll(const LayoutBox& box) {
@@ -252,8 +283,11 @@ static bool NeedsPaintOffsetTranslation(const LayoutObject& object) {
return false;
}
-IntPoint ApplyPaintOffsetTranslation(const LayoutObject& object,
- LayoutPoint& paint_offset) {
+void FragmentPaintPropertyTreeBuilder::UpdateForPaintOffsetTranslation(
+ base::Optional<IntPoint>& paint_offset_translation) {
+ if (!NeedsPaintOffsetTranslation(object_))
+ return;
+
// We should use the same subpixel paint offset values for snapping
// regardless of whether a transform is present. If there is a transform
// we round the paint offset but keep around the residual fractional
@@ -261,35 +295,21 @@ IntPoint ApplyPaintOffsetTranslation(const LayoutObject& object,
// called "subpixel accumulation". For more information, see
// PaintLayer::subpixelAccumulation() and
// PaintLayerPainter::paintFragmentByApplyingTransform.
- IntPoint paint_offset_translation = RoundedIntPoint(paint_offset);
+ paint_offset_translation = RoundedIntPoint(context_.current.paint_offset);
LayoutPoint fractional_paint_offset =
- LayoutPoint(paint_offset - paint_offset_translation);
+ LayoutPoint(context_.current.paint_offset - *paint_offset_translation);
if (fractional_paint_offset != LayoutPoint()) {
// If the object has a non-translation transform, discard the fractional
// paint offset which can't be transformed by the transform.
TransformationMatrix matrix;
- object.StyleRef().ApplyTransform(
+ object_.StyleRef().ApplyTransform(
matrix, LayoutSize(), ComputedStyle::kExcludeTransformOrigin,
ComputedStyle::kIncludeMotionPath,
ComputedStyle::kIncludeIndependentTransformProperties);
if (!matrix.IsIdentityOrTranslation())
fractional_paint_offset = LayoutPoint();
}
- paint_offset = fractional_paint_offset;
- return paint_offset_translation;
-}
-
-void FragmentPaintPropertyTreeBuilder::UpdateForPaintOffsetTranslation(
- base::Optional<IntPoint>& paint_offset_translation) {
- if (!NeedsPaintOffsetTranslation(object_))
- return;
-
- paint_offset_translation =
- ApplyPaintOffsetTranslation(object_, context_.current.paint_offset);
- if (object_.IsLayoutView()) {
- context_.absolute_position.paint_offset = context_.current.paint_offset;
- context_.fixed_position.paint_offset = context_.current.paint_offset;
- }
+ context_.current.paint_offset = fractional_paint_offset;
}
void FragmentPaintPropertyTreeBuilder::UpdatePaintOffsetTranslation(
@@ -306,7 +326,7 @@ void FragmentPaintPropertyTreeBuilder::UpdatePaintOffsetTranslation(
RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled())
state.rendering_context_id = context_.current.rendering_context_id;
OnUpdate(properties_->UpdatePaintOffsetTranslation(
- context_.current.transform, std::move(state)));
+ *context_.current.transform, std::move(state)));
context_.current.transform = properties_->PaintOffsetTranslation();
if (object_.IsLayoutView()) {
context_.absolute_position.transform =
@@ -342,7 +362,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateTransformForNonRootSVG() {
if (NeedsTransformForNonRootSVG(object_)) {
// The origin is included in the local transform, so leave origin empty.
OnUpdate(properties_->UpdateTransform(
- context_.current.transform,
+ *context_.current.transform,
TransformPaintPropertyNode::State{transform}));
} else {
OnClear(properties_->ClearTransform());
@@ -460,7 +480,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateTransform() {
object_.UniqueId(), CompositorElementIdNamespace::kPrimary);
}
- OnUpdate(properties_->UpdateTransform(context_.current.transform,
+ OnUpdate(properties_->UpdateTransform(*context_.current.transform,
std::move(state)));
} else {
OnClear(properties_->ClearTransform());
@@ -579,17 +599,13 @@ void FragmentPaintPropertyTreeBuilder::UpdateEffect() {
if (has_spv1_composited_clip_path || has_mask_based_clip_path) {
clip_path_clip = fragment_data_.ClipPathBoundingBox();
}
- if ((mask_clip || clip_path_clip) &&
- // TODO(crbug.com/768691): Remove the following condition after mask
- // clip doesn't fail fast/borders/inline-mask-overlay-image-outset-
- // vertical-rl.html.
- RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
+ if (mask_clip || clip_path_clip) {
IntRect combined_clip = mask_clip ? *mask_clip : *clip_path_clip;
if (mask_clip && clip_path_clip)
combined_clip.Intersect(*clip_path_clip);
OnUpdateClip(properties_->UpdateMaskClip(
- context_.current.clip,
+ *context_.current.clip,
ClipPaintPropertyNode::State{context_.current.transform,
FloatRoundedRect(combined_clip)}));
output_clip = properties_->MaskClip();
@@ -618,8 +634,8 @@ void FragmentPaintPropertyTreeBuilder::UpdateEffect() {
state.compositor_element_id = CompositorElementIdFromUniqueObjectId(
object_.UniqueId(), CompositorElementIdNamespace::kPrimary);
}
- OnUpdate(
- properties_->UpdateEffect(context_.current_effect, std::move(state)));
+ OnUpdate(properties_->UpdateEffect(*context_.current_effect,
+ std::move(state)));
if (mask_clip || has_spv1_composited_clip_path) {
EffectPaintPropertyNode::State mask_state;
@@ -634,16 +650,16 @@ void FragmentPaintPropertyTreeBuilder::UpdateEffect() {
object_.UniqueId(),
CompositorElementIdNamespace::kEffectMask);
}
- OnUpdate(properties_->UpdateMask(properties_->Effect(),
+ OnUpdate(properties_->UpdateMask(*properties_->Effect(),
std::move(mask_state)));
} else {
OnClear(properties_->ClearMask());
}
if (has_mask_based_clip_path) {
- const EffectPaintPropertyNode* parent = has_spv1_composited_clip_path
- ? properties_->Mask()
- : properties_->Effect();
+ const EffectPaintPropertyNode& parent = has_spv1_composited_clip_path
+ ? *properties_->Mask()
+ : *properties_->Effect();
EffectPaintPropertyNode::State clip_path_state;
clip_path_state.local_transform_space = context_.current.transform;
clip_path_state.output_clip = output_clip;
@@ -757,8 +773,8 @@ void FragmentPaintPropertyTreeBuilder::UpdateFilter() {
object_.UniqueId(), CompositorElementIdNamespace::kEffectFilter);
}
- OnUpdate(
- properties_->UpdateFilter(context_.current_effect, std::move(state)));
+ OnUpdate(properties_->UpdateFilter(*context_.current_effect,
+ std::move(state)));
} else {
OnClear(properties_->ClearFilter());
}
@@ -775,9 +791,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateFilter() {
}
static FloatRoundedRect ToClipRect(const LayoutRect& rect) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return FloatRoundedRect(FloatRect(PixelSnappedIntRect(rect)));
- return FloatRoundedRect(FloatRect(rect));
+ return FloatRoundedRect(FloatRect(PixelSnappedIntRect(rect)));
}
void FragmentPaintPropertyTreeBuilder::UpdateFragmentClip() {
@@ -786,7 +800,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateFragmentClip() {
if (NeedsPaintPropertyUpdate()) {
if (context_.fragment_clip) {
OnUpdateClip(properties_->UpdateFragmentClip(
- context_.current.clip,
+ *context_.current.clip,
ClipPaintPropertyNode::State{context_.current.transform,
ToClipRect(*context_.fragment_clip)}));
} else {
@@ -813,7 +827,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateCssClip() {
// copy from in-flow context later at updateOutOfFlowContext() step.
DCHECK(object_.CanContainAbsolutePositionObjects());
OnUpdateClip(properties_->UpdateCssClip(
- context_.current.clip,
+ *context_.current.clip,
ClipPaintPropertyNode::State{context_.current.transform,
ToClipRect(ToLayoutBox(object_).ClipRect(
context_.current.paint_offset))}));
@@ -846,7 +860,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateClipPathClip(
state.clip_rect =
FloatRoundedRect(FloatRect(*fragment_data_.ClipPathBoundingBox()));
state.clip_path = fragment_data_.ClipPathPath();
- OnUpdateClip(properties_->UpdateClipPathClip(context_.current.clip,
+ OnUpdateClip(properties_->UpdateClipPathClip(*context_.current.clip,
std::move(state)));
}
}
@@ -869,9 +883,8 @@ void FragmentPaintPropertyTreeBuilder::UpdateLocalBorderBoxContext() {
PropertyTreeState(context_.current.transform, context_.current.clip,
context_.current_effect);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- (!fragment_data_.HasLocalBorderBoxProperties() ||
- local_border_box != fragment_data_.LocalBorderBoxProperties()))
+ if (!fragment_data_.HasLocalBorderBoxProperties() ||
+ local_border_box != fragment_data_.LocalBorderBoxProperties())
property_added_or_removed_ = true;
fragment_data_.SetLocalBorderBoxProperties(std::move(local_border_box));
@@ -903,11 +916,7 @@ static bool IsPrintingRootLayoutView(const LayoutObject& object) {
}
static bool NeedsOverflowClip(const LayoutObject& object) {
- // Though a SVGForeignObject is a LayoutBox, its overflow clip logic is
- // special because it doesn't create a PaintLayer.
- // See LayoutSVGBlock::AllowsOverflowClip().
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- object.IsSVGViewportContainer() &&
+ if (object.IsSVGViewportContainer() &&
SVGLayoutSupport::IsOverflowHidden(object))
return true;
@@ -975,7 +984,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateOverflowControlsClip() {
// Clip overflow controls to the border box rect. Not wrapped with
// OnUpdateClip() because this clip doesn't affect descendants.
properties_->UpdateOverflowControlsClip(
- context_.current.clip,
+ *context_.current.clip,
ClipPaintPropertyNode::State{
context_.current.transform,
ToClipRect(LayoutRect(context_.current.paint_offset,
@@ -1011,7 +1020,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateInnerBorderRadiusClip() {
LayoutRect(context_.current.paint_offset, box.Size()));
}
OnUpdateClip(properties_->UpdateInnerBorderRadiusClip(
- context_.current.clip, std::move(state)));
+ *context_.current.clip, std::move(state)));
} else {
OnClearClip(properties_->ClearInnerBorderRadiusClip());
}
@@ -1060,10 +1069,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateOverflowClip() {
ClipPaintPropertyNode::State state;
state.local_transform_space = context_.current.transform;
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- object_.IsSVGForeignObject()) {
- state.clip_rect = ToClipRect(ToLayoutBox(object_).FrameRect());
- } else if (object_.IsBox()) {
+ if (object_.IsBox()) {
state.clip_rect = ToClipRect(ToLayoutBox(object_).OverflowClipRect(
context_.current.paint_offset));
state.clip_rect_excluding_overlay_scrollbars =
@@ -1082,7 +1088,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateOverflowClip() {
bool equal_ignoring_hit_test_rects =
!!existing &&
existing->EqualIgnoringHitTestRects(context_.current.clip, state);
- OnUpdateClip(properties_->UpdateOverflowClip(context_.current.clip,
+ OnUpdateClip(properties_->UpdateOverflowClip(*context_.current.clip,
std::move(state)),
equal_ignoring_hit_test_rects);
} else {
@@ -1124,7 +1130,7 @@ void FragmentPaintPropertyTreeBuilder::UpdatePerspective() {
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled() ||
RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled())
state.rendering_context_id = context_.current.rendering_context_id;
- OnUpdate(properties_->UpdatePerspective(context_.current.transform,
+ OnUpdate(properties_->UpdatePerspective(*context_.current.transform,
std::move(state)));
} else {
OnClear(properties_->ClearPerspective());
@@ -1149,7 +1155,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateSvgLocalToBorderBoxTransform() {
if (!transform_to_border_box.IsIdentity() &&
NeedsSVGLocalToBorderBoxTransform(object_)) {
OnUpdate(properties_->UpdateSvgLocalToBorderBoxTransform(
- context_.current.transform,
+ *context_.current.transform,
TransformPaintPropertyNode::State{transform_to_border_box}));
} else {
OnClear(properties_->ClearSvgLocalToBorderBoxTransform());
@@ -1190,7 +1196,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateScrollAndScrollTranslation() {
if (NeedsPaintPropertyUpdate()) {
if (NeedsScrollNode(object_)) {
const LayoutBox& box = ToLayoutBox(object_);
- auto* scrollable_area = box.GetScrollableArea();
+ PaintLayerScrollableArea* scrollable_area = box.GetScrollableArea();
ScrollPaintPropertyNode::State state;
// The container bounds are snapped to integers to match the equivalent
@@ -1231,10 +1237,40 @@ void FragmentPaintPropertyTreeBuilder::UpdateScrollAndScrollTranslation() {
RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled())
state.compositor_element_id = scrollable_area->GetCompositorElementId();
- OnUpdate(
- properties_->UpdateScroll(context_.current.scroll, std::move(state)));
+ OnUpdate(properties_->UpdateScroll(*context_.current.scroll,
+ std::move(state)));
+
+ if (scrollable_area->VerticalScrollbar() ||
+ scrollable_area->HasLayerForVerticalScrollbar()) {
+ EffectPaintPropertyNode::State state;
+ state.local_transform_space = context_.current.transform;
+ state.direct_compositing_reasons =
+ CompositingReason::kActiveOpacityAnimation;
+ state.compositor_element_id = scrollable_area->GetScrollbarElementId(
+ ScrollbarOrientation::kVerticalScrollbar);
+ OnUpdate(properties_->UpdateVerticalScrollbarEffect(
+ *context_.current_effect, std::move(state)));
+ } else {
+ OnClear(properties_->ClearVerticalScrollbarEffect());
+ }
+
+ if (scrollable_area->HorizontalScrollbar() ||
+ scrollable_area->HasLayerForHorizontalScrollbar()) {
+ EffectPaintPropertyNode::State state;
+ state.local_transform_space = context_.current.transform;
+ state.direct_compositing_reasons =
+ CompositingReason::kActiveOpacityAnimation;
+ state.compositor_element_id = scrollable_area->GetScrollbarElementId(
+ ScrollbarOrientation::kHorizontalScrollbar);
+ OnUpdate(properties_->UpdateHorizontalScrollbarEffect(
+ *context_.current_effect, std::move(state)));
+ } else {
+ OnClear(properties_->ClearHorizontalScrollbarEffect());
+ }
} else {
OnClear(properties_->ClearScroll());
+ OnClear(properties_->ClearVerticalScrollbarEffect());
+ OnClear(properties_->ClearHorizontalScrollbarEffect());
}
// A scroll translation node is created for static offset (e.g., overflow
@@ -1252,7 +1288,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateScrollAndScrollTranslation() {
state.rendering_context_id = context_.current.rendering_context_id;
}
state.scroll = properties_->Scroll();
- OnUpdate(properties_->UpdateScrollTranslation(context_.current.transform,
+ OnUpdate(properties_->UpdateScrollTranslation(*context_.current.transform,
std::move(state)));
} else {
OnClear(properties_->ClearScrollTranslation());
@@ -1271,8 +1307,15 @@ void FragmentPaintPropertyTreeBuilder::UpdateOutOfFlowContext() {
if (!object_.IsBoxModelObject() && !properties_)
return;
- if (object_.IsLayoutBlock())
+ if (object_.IsLayoutBlockFlow()) {
context_.paint_offset_for_float = context_.current.paint_offset;
+ // TODO(crbug.com/858843): For now floating object's PhysicalLocation() is
+ // in the scrolling contents space, so if there is scrollbar on the left,
+ // we adjust the paint offset origin.
+ const auto& box = ToLayoutBox(object_);
+ if (box.ShouldPlaceBlockDirectionScrollbarOnLogicalLeft())
+ context_.paint_offset_for_float.Move(box.VerticalScrollbarWidth(), 0);
+ }
if (object_.CanContainAbsolutePositionObjects()) {
context_.absolute_position = context_.current;
@@ -1307,7 +1350,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateOutOfFlowContext() {
} else {
if (NeedsPaintPropertyUpdate()) {
OnUpdate(properties_->UpdateCssClipFixedPosition(
- context_.fixed_position.clip,
+ *context_.fixed_position.clip,
ClipPaintPropertyNode::State{css_clip->LocalTransformSpace(),
css_clip->ClipRect()}));
}
@@ -1575,8 +1618,7 @@ void FragmentPaintPropertyTreeBuilder::SetNeedsPaintPropertyUpdateIfNeeded() {
// CSS mask and clip-path comes with an implicit clip to the border box.
// Currently only SPv2 generate and take advantage of those.
const bool box_generates_property_nodes_for_mask_and_clip_path =
- RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- (box.HasMask() || box.HasClipPath());
+ box.HasMask() || box.HasClipPath();
// The overflow clip paint property depends on the border box rect through
// overflowClipRect(). The border box rect's size equals the frame rect's
// size so we trigger a paint property update when the frame rect changes.
@@ -1611,6 +1653,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateForObjectLocationAndSize(
object_, fragment_data_, full_context_.is_actually_needed);
#endif
+ context_.old_paint_offset = fragment_data_.PaintOffset();
UpdatePaintOffset();
UpdateForPaintOffsetTranslation(paint_offset_translation);
@@ -1619,20 +1662,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateForObjectLocationAndSize(
// the entire subtree on paint offset changes.
full_context_.force_subtree_update = true;
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- // TODO(wangxianzhu): Move this logic into PaintInvalidator.
- if (RoundedIntPoint(fragment_data_.PaintOffset()) ==
- RoundedIntPoint(context_.current.paint_offset)) {
- // Most paintings are pixel-snapped so subpixel change of paint offset
- // is unlikely to cause full invalidation. Let the object's paint
- // invalidator determine the right invalidation.
- object_.GetMutableForPainting().SetMayNeedPaintInvalidation();
- } else {
- object_.GetMutableForPainting().SetShouldDoFullPaintInvalidation(
- PaintInvalidationReason::kGeometry);
- }
- }
-
+ object_.GetMutableForPainting().SetMayNeedPaintInvalidation();
fragment_data_.SetPaintOffset(context_.current.paint_offset);
fragment_data_.InvalidateClipPathCache();
}
@@ -1691,8 +1721,7 @@ void FragmentPaintPropertyTreeBuilder::UpdateForSelf() {
if (properties_) {
UpdateTransform();
UpdateClipPathClip(false);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- UpdateEffect();
+ UpdateEffect();
UpdateClipPathClip(true); // Special pass for SPv1 composited clip-path.
UpdateCssClip();
UpdateFilter();
@@ -2194,20 +2223,27 @@ void PaintPropertyTreeBuilder::CreateFragmentContextsInFlowThread(
new_fragment_contexts.push_back(
ContextForFragment(fragment_clip, logical_top_in_flow_thread));
- base::Optional<LayoutUnit> old_logical_top_in_flow_thread;
if (current_fragment_data) {
- if (const auto* old_fragment = current_fragment_data->NextFragment())
- old_logical_top_in_flow_thread = old_fragment->LogicalTopInFlowThread();
+ if (!current_fragment_data->NextFragment())
+ fragments_changed = true;
current_fragment_data = &current_fragment_data->EnsureNextFragment();
} else {
current_fragment_data = &object_.GetMutableForPainting().FirstFragment();
- old_logical_top_in_flow_thread =
- current_fragment_data->LogicalTopInFlowThread();
}
- if (!old_logical_top_in_flow_thread ||
- *old_logical_top_in_flow_thread != logical_top_in_flow_thread)
- fragments_changed = true;
+ fragments_changed |= logical_top_in_flow_thread !=
+ current_fragment_data->LogicalTopInFlowThread();
+ if (!fragments_changed) {
+ const ClipPaintPropertyNode* old_fragment_clip = nullptr;
+ if (const auto* properties = current_fragment_data->PaintProperties())
+ old_fragment_clip = properties->FragmentClip();
+ const base::Optional<LayoutRect>& new_fragment_clip =
+ new_fragment_contexts.back().fragment_clip;
+ fragments_changed =
+ !!old_fragment_clip != !!new_fragment_clip ||
+ (old_fragment_clip && new_fragment_clip &&
+ old_fragment_clip->ClipRect() != ToClipRect(*new_fragment_clip));
+ }
InitFragmentPaintProperties(
*current_fragment_data,
@@ -2429,12 +2465,10 @@ bool PaintPropertyTreeBuilder::UpdateForSelf() {
DCHECK(!fragment_data);
// We need to update property tree states of paint chunks.
- if (property_added_or_removed &&
- RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
+ if (property_added_or_removed)
context_.painting_layer->SetNeedsRepaint();
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- !context_.supports_composited_raster_invalidation)
+ if (!context_.supports_composited_raster_invalidation)
return property_changed || property_added_or_removed;
return property_changed;
@@ -2464,8 +2498,7 @@ bool PaintPropertyTreeBuilder::UpdateForChildren() {
context_.container_for_fixed_position = &object_;
// We need to update property tree states of paint chunks.
- if (property_added_or_removed &&
- RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
+ if (property_added_or_removed)
context_.painting_layer->SetNeedsRepaint();
return property_changed;
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.h b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.h
index 5ae019dbc8f..4248108a7c9 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder.h
@@ -20,6 +20,7 @@ class LayoutObject;
class LayoutTableSection;
class LocalFrameView;
class PaintLayer;
+class VisualViewport;
// The context for PaintPropertyTreeBuilder.
// It's responsible for bookkeeping tree state in other order, for example, the
@@ -106,6 +107,8 @@ struct PaintPropertyTreeBuilderFragmentContext {
// The repeated paintings need to add an adjustment to the calculated paint
// offset to paint at the desired place.
LayoutSize repeating_paint_offset_adjustment;
+
+ LayoutPoint old_paint_offset;
};
struct PaintPropertyTreeBuilderContext {
@@ -160,6 +163,13 @@ struct PaintPropertyTreeBuilderContext {
bool supports_composited_raster_invalidation = true;
};
+class VisualViewportPaintPropertyTreeBuilder {
+ public:
+ // Update the paint properties for the visual viewport and ensure the context
+ // is up to date.
+ static void Update(VisualViewport&, PaintPropertyTreeBuilderContext&);
+};
+
// Creates paint property tree nodes for non-local effects in the layout tree.
// Non-local effects include but are not limited to: overflow clip, transform,
// fixed-pos, animation, mask, filters, etc. It expects to be invoked for each
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 5fa39212eb3..07e48113cb5 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
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/core/paint/paint_property_tree_builder_test.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
#include "third_party/blink/renderer/core/layout/layout_image.h"
#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
@@ -20,7 +22,8 @@ void PaintPropertyTreeBuilderTest::LoadTestData(const char* file_name) {
String full_path = test::BlinkRootDir();
full_path.append("/renderer/core/paint/test_data/");
full_path.append(file_name);
- const Vector<char> input_buffer = test::ReadFromFile(full_path)->Copy();
+ const Vector<char> input_buffer =
+ test::ReadFromFile(full_path)->CopyAs<Vector<char>>();
SetBodyInnerHTML(String(input_buffer.data(), input_buffer.size()));
}
@@ -77,8 +80,7 @@ void PaintPropertyTreeBuilderTest::SetUp() {
#define CHECK_VISUAL_RECT(expected, source_object, ancestor, slop_factor) \
do { \
- if ((source_object)->HasLayer() && (ancestor)->HasLayer() && \
- RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) { \
+ if ((source_object)->HasLayer() && (ancestor)->HasLayer()) { \
LayoutRect actual((source_object)->LocalVisualRect()); \
(source_object) \
->MapToVisualRectInAncestorSpace(ancestor, actual, \
@@ -143,7 +145,18 @@ TEST_P(PaintPropertyTreeBuilderTest, FixedPosition) {
auto* positioned_scroll_translation =
positioned_scroll_properties->ScrollTranslation();
auto* positioned_scroll_node = positioned_scroll_translation->ScrollNode();
- EXPECT_TRUE(positioned_scroll_node->Parent()->IsRoot());
+ // TODO(bokan): Viewport property node generation has been disabled
+ // temporarily with the flag off to diagnose https//crbug.com/868927.
+ if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
+ EXPECT_EQ(GetDocument()
+ .GetPage()
+ ->GetVisualViewport()
+ .GetScrollTranslationNode()
+ ->ScrollNode(),
+ positioned_scroll_node->Parent());
+ } else {
+ EXPECT_TRUE(positioned_scroll_node->Parent()->IsRoot());
+ }
EXPECT_EQ(TransformationMatrix().Translate(0, -3),
positioned_scroll_translation->Matrix());
EXPECT_EQ(nullptr, target1_properties->ScrollTranslation());
@@ -170,7 +183,18 @@ TEST_P(PaintPropertyTreeBuilderTest, FixedPosition) {
auto* transformed_scroll_translation =
transformed_scroll_properties->ScrollTranslation();
auto* transformed_scroll_node = transformed_scroll_translation->ScrollNode();
- EXPECT_TRUE(transformed_scroll_node->Parent()->IsRoot());
+ // TODO(bokan): Viewport property node generation has been disabled
+ // temporarily with the flag off to diagnose https//crbug.com/868927.
+ if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
+ EXPECT_EQ(GetDocument()
+ .GetPage()
+ ->GetVisualViewport()
+ .GetScrollTranslationNode()
+ ->ScrollNode(),
+ transformed_scroll_node->Parent());
+ } else {
+ EXPECT_TRUE(transformed_scroll_node->Parent()->IsRoot());
+ }
EXPECT_EQ(TransformationMatrix().Translate(0, -5),
transformed_scroll_translation->Matrix());
EXPECT_EQ(nullptr, target2_properties->ScrollTranslation());
@@ -295,10 +319,7 @@ TEST_P(PaintPropertyTreeBuilderTest, OverflowScrollExcludeScrollbarsSubpixel) {
EXPECT_EQ(DocContentClip(), overflow_clip->Parent());
EXPECT_EQ(properties->PaintOffsetTranslation(),
overflow_clip->LocalTransformSpace());
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- EXPECT_EQ(FloatRoundedRect(10, 10, 101, 100), overflow_clip->ClipRect());
- else
- EXPECT_EQ(FloatRoundedRect(10, 10, 100.5, 100), overflow_clip->ClipRect());
+ EXPECT_EQ(FloatRoundedRect(10, 10, 101, 100), overflow_clip->ClipRect());
PaintLayer* paint_layer =
ToLayoutBoxModelObject(GetLayoutObjectByElementId("scroller"))->Layer();
@@ -306,13 +327,8 @@ TEST_P(PaintPropertyTreeBuilderTest, OverflowScrollExcludeScrollbarsSubpixel) {
->VerticalScrollbar()
->IsOverlayScrollbar());
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(FloatRoundedRect(10, 10, 94, 93),
- overflow_clip->ClipRectExcludingOverlayScrollbars());
- } else {
- EXPECT_EQ(FloatRoundedRect(10, 10, 93.5, 93),
- overflow_clip->ClipRectExcludingOverlayScrollbars());
- }
+ EXPECT_EQ(FloatRoundedRect(10, 10, 94, 93),
+ overflow_clip->ClipRectExcludingOverlayScrollbars());
}
TEST_P(PaintPropertyTreeBuilderTest, OverflowScrollVerticalRL) {
@@ -382,7 +398,15 @@ TEST_P(PaintPropertyTreeBuilderTest, DocScrollingTraditional) {
LocalFrameView* frame_view = GetDocument().View();
frame_view->UpdateAllLifecyclePhases();
EXPECT_EQ(TransformationMatrix(), DocPreTranslation()->Matrix());
- EXPECT_TRUE(DocPreTranslation()->Parent()->IsRoot());
+ // TODO(bokan): Viewport property node generation has been disabled
+ // temporarily with the flag off to diagnose https//crbug.com/868927.
+ if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
+ EXPECT_EQ(
+ GetDocument().GetPage()->GetVisualViewport().GetScrollTranslationNode(),
+ DocPreTranslation()->Parent());
+ } else {
+ EXPECT_TRUE(DocPreTranslation()->Parent()->IsRoot());
+ }
EXPECT_EQ(TransformationMatrix().Translate(0, -100),
DocScrollTranslation()->Matrix());
EXPECT_EQ(DocPreTranslation(), DocScrollTranslation()->Parent());
@@ -607,7 +631,7 @@ TEST_P(PaintPropertyTreeBuilderTest, WillChangeTransform) {
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
EXPECT_EQ(nullptr, transform_properties->PaintOffsetTranslation());
} else {
- // SPv175 creates PaintOffsetTranslation for composited layers.
+ // SPv1 creates PaintOffsetTranslation for composited layers.
EXPECT_EQ(TransformationMatrix().Translate(50, 100),
transform_properties->PaintOffsetTranslation()->Matrix());
}
@@ -672,10 +696,6 @@ TEST_P(PaintPropertyTreeBuilderTest, RelativePositionInline) {
}
TEST_P(PaintPropertyTreeBuilderTest, NestedOpacityEffect) {
- // SPv1 has no effect tree.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<div id='nodeWithoutOpacity' style='width: 100px; height: 200px'>
<div id='childWithOpacity'
@@ -732,10 +752,6 @@ TEST_P(PaintPropertyTreeBuilderTest, NestedOpacityEffect) {
}
TEST_P(PaintPropertyTreeBuilderTest, TransformNodeDoesNotAffectEffectNodes) {
- // SPv1 has no effect tree.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<style>
#nodeWithOpacity {
@@ -797,9 +813,6 @@ TEST_P(PaintPropertyTreeBuilderTest, TransformNodeDoesNotAffectEffectNodes) {
}
TEST_P(PaintPropertyTreeBuilderTest, EffectNodesAcrossStackingContext) {
- // SPv1 has no effect tree.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
SetBodyInnerHTML(R"HTML(
<div id='nodeWithOpacity'
style='opacity: 0.6; width: 100px; height: 200px'>
@@ -847,10 +860,6 @@ TEST_P(PaintPropertyTreeBuilderTest, EffectNodesAcrossStackingContext) {
}
TEST_P(PaintPropertyTreeBuilderTest, EffectNodesInSVG) {
- // SPv1 has no effect tree.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<svg id='svgRoot'>
<g id='groupWithOpacity' opacity='0.6'>
@@ -869,7 +878,7 @@ TEST_P(PaintPropertyTreeBuilderTest, EffectNodesInSVG) {
PaintPropertiesForElement("groupWithOpacity");
EXPECT_EQ(0.6f, group_with_opacity_properties->Effect()->Opacity());
EXPECT_EQ(svg_clip, group_with_opacity_properties->Effect()->OutputClip());
- EXPECT_EQ(EffectPaintPropertyNode::Root(),
+ EXPECT_EQ(&EffectPaintPropertyNode::Root(),
group_with_opacity_properties->Effect()->Parent());
EXPECT_EQ(nullptr, PaintPropertiesForElement("rectWithoutOpacity"));
@@ -901,10 +910,6 @@ TEST_P(PaintPropertyTreeBuilderTest, EffectNodesInSVG) {
}
TEST_P(PaintPropertyTreeBuilderTest, EffectNodesAcrossHTMLSVGBoundary) {
- // SPv1 has no effect tree.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<div id='divWithOpacity' style='opacity: 0.2;'>
<svg id='svgRootWithOpacity' style='opacity: 0.3;'>
@@ -936,10 +941,6 @@ TEST_P(PaintPropertyTreeBuilderTest, EffectNodesAcrossHTMLSVGBoundary) {
}
TEST_P(PaintPropertyTreeBuilderTest, EffectNodesAcrossSVGHTMLBoundary) {
- // SPv1 has no effect tree.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<svg id='svgRootWithOpacity' style='opacity: 0.3;'>
<foreignObject id='foreignObjectWithOpacity' opacity='0.4'>
@@ -1236,10 +1237,6 @@ TEST_P(PaintPropertyTreeBuilderTest, ForeignObjectWithTransformAndOffset) {
}
TEST_P(PaintPropertyTreeBuilderTest, ForeignObjectWithMask) {
- // SPV1 has no effect tree.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<style> body { margin: 0px; } </style>
<svg id='svg' style='position; relative'>
@@ -1296,9 +1293,6 @@ TEST_P(PaintPropertyTreeBuilderTest, PaintOffsetTranslationSVGHTMLBoundary) {
}
TEST_P(PaintPropertyTreeBuilderTest, SVGViewportContainer) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<!-- border radius of inner svg elemnents should be ignored. -->
<style>svg { border-radius: 10px }</style>
@@ -1359,9 +1353,6 @@ TEST_P(PaintPropertyTreeBuilderTest, SVGViewportContainer) {
}
TEST_P(PaintPropertyTreeBuilderTest, SVGForeignObjectOverflowClip) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<svg id='svg'>
<foreignObject id='object1' x='10' y='20' width='30' height='40'
@@ -1805,15 +1796,12 @@ TEST_P(PaintPropertyTreeBuilderTest,
EXPECT_EQ(DocScrollTranslation(),
child.FirstFragment().LocalBorderBoxProperties().Transform());
} else {
- // For SPv1*, |child| is composited so we created PaintOffsetTranslation.
+ // For SPv1, |child| is composited so we created PaintOffsetTranslation.
EXPECT_EQ(child.FirstFragment().PaintProperties()->PaintOffsetTranslation(),
child.FirstFragment().LocalBorderBoxProperties().Transform());
}
- // SPv1 has no effect tree.
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(scroller_properties->Effect(),
- child.FirstFragment().LocalBorderBoxProperties().Effect());
- }
+ EXPECT_EQ(scroller_properties->Effect(),
+ child.FirstFragment().LocalBorderBoxProperties().Effect());
CHECK_EXACT_VISUAL_RECT(LayoutRect(0, 0, 800, 10000), &scroller,
GetDocument().View()->GetLayoutView());
CHECK_EXACT_VISUAL_RECT(LayoutRect(0, 0, 100, 200), &child,
@@ -1995,10 +1983,7 @@ TEST_P(PaintPropertyTreeBuilderTest, CSSClipSubpixel) {
LayoutRect local_clip_rect(40, 10, 40, 60);
LayoutRect absolute_clip_rect = local_clip_rect;
// Moved by 124 pixels due to pixel-snapping.
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- absolute_clip_rect.Move(124, 456);
- else
- absolute_clip_rect.Move(LayoutUnit(123.5f), LayoutUnit(456));
+ absolute_clip_rect.Move(124, 456);
auto* clip = GetLayoutObjectByElementId("clip");
const ObjectPaintProperties* clip_properties =
@@ -3342,7 +3327,18 @@ TEST_P(PaintPropertyTreeBuilderTest, NestedScrollProperties) {
auto* scroll_a_translation =
overflow_a_scroll_properties->ScrollTranslation();
auto* overflow_a_scroll_node = scroll_a_translation->ScrollNode();
- EXPECT_TRUE(overflow_a_scroll_node->Parent()->IsRoot());
+ // TODO(bokan): Viewport property node generation has been disabled
+ // temporarily with the flag off to diagnose https//crbug.com/868927.
+ if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
+ EXPECT_EQ(GetDocument()
+ .GetPage()
+ ->GetVisualViewport()
+ .GetScrollTranslationNode()
+ ->ScrollNode(),
+ overflow_a_scroll_node->Parent());
+ } else {
+ EXPECT_TRUE(overflow_a_scroll_node->Parent()->IsRoot());
+ }
EXPECT_EQ(TransformationMatrix().Translate(0, -37),
scroll_a_translation->Matrix());
EXPECT_EQ(IntRect(0, 0, 5, 3), overflow_a_scroll_node->ContainerRect());
@@ -3459,7 +3455,16 @@ TEST_P(PaintPropertyTreeBuilderTest, PositionedScrollerIsNotNested) {
auto* fixed_overflow_scroll_node = fixed_scroll_translation->ScrollNode();
// The fixed position overflow scroll node is parented under the root, not the
// dom-order parent or frame's scroll.
- EXPECT_TRUE(fixed_overflow_scroll_node->Parent()->IsRoot());
+ if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
+ EXPECT_EQ(GetDocument()
+ .GetPage()
+ ->GetVisualViewport()
+ .GetScrollTranslationNode()
+ ->ScrollNode(),
+ fixed_overflow_scroll_node->Parent());
+ } else {
+ EXPECT_TRUE(fixed_overflow_scroll_node->Parent()->IsRoot());
+ }
EXPECT_EQ(TransformationMatrix().Translate(0, -43),
fixed_scroll_translation->Matrix());
EXPECT_EQ(IntRect(0, 0, 13, 11), fixed_overflow_scroll_node->ContainerRect());
@@ -3515,7 +3520,18 @@ TEST_P(PaintPropertyTreeBuilderTest, NestedPositionedScrollProperties) {
auto* scroll_a_translation =
overflow_a_scroll_properties->ScrollTranslation();
auto* overflow_a_scroll_node = scroll_a_translation->ScrollNode();
- EXPECT_TRUE(overflow_a_scroll_node->Parent()->IsRoot());
+ // TODO(bokan): Viewport property node generation has been disabled
+ // temporarily with the flag off to diagnose https//crbug.com/868927.
+ if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
+ EXPECT_EQ(GetDocument()
+ .GetPage()
+ ->GetVisualViewport()
+ .GetScrollTranslationNode()
+ ->ScrollNode(),
+ overflow_a_scroll_node->Parent());
+ } else {
+ EXPECT_TRUE(overflow_a_scroll_node->Parent()->IsRoot());
+ }
EXPECT_EQ(TransformationMatrix().Translate(0, -37),
scroll_a_translation->Matrix());
EXPECT_EQ(IntRect(0, 0, 20, 20), overflow_a_scroll_node->ContainerRect());
@@ -3609,25 +3625,6 @@ TEST_P(PaintPropertyTreeBuilderTest, MainThreadScrollReasonsWithoutScrolling) {
nullptr);
}
-static unsigned NumFragments(const LayoutObject* obj) {
- unsigned count = 0;
- auto* fragment = &obj->FirstFragment();
- while (fragment) {
- count++;
- fragment = fragment->NextFragment();
- }
- return count;
-}
-
-static const FragmentData& FragmentAt(const LayoutObject* obj, unsigned count) {
- auto* fragment = &obj->FirstFragment();
- while (count > 0) {
- count--;
- fragment = fragment->NextFragment();
- }
- return *fragment;
-}
-
TEST_P(PaintPropertyTreeBuilderTest, PaintOffsetsUnderMultiColumnScrolled) {
SetBodyInnerHTML(R"HTML(
<!doctype HTML>
@@ -3651,9 +3648,10 @@ TEST_P(PaintPropertyTreeBuilderTest, PaintOffsetsUnderMultiColumnScrolled) {
.To2DTranslation());
}
-TEST_P(PaintPropertyTreeBuilderTest, PaintOffsetsUnderMultiColumnWithOutline) {
+TEST_P(PaintPropertyTreeBuilderTest,
+ PaintOffsetsUnderMultiColumnWithVisualOverflow) {
SetBodyInnerHTML(R"HTML(
- <div style='columns: 2; height: 100px'>
+ <div style='columns: 2; width: 300px; column-gap: 0; height: 100px'>
<div id=target1 style='outline: 2px solid black; width: 100px;
height: 100px'></div>
<div id=target2 style='outline: 2px solid black; width: 100px;
@@ -3670,12 +3668,33 @@ TEST_P(PaintPropertyTreeBuilderTest, PaintOffsetsUnderMultiColumnWithOutline) {
EXPECT_FALSE(target1->FirstFragment().NextFragment());
LayoutObject* target2 = GetLayoutObjectByElementId("target2");
- EXPECT_EQ(LayoutPoint(LayoutUnit(400.5f), LayoutUnit(8.0f)),
- target2->FirstFragment().PaintOffset());
+ EXPECT_EQ(LayoutPoint(158, 8), target2->FirstFragment().PaintOffset());
// |target2| is only in the second column.
EXPECT_FALSE(target2->FirstFragment().NextFragment());
}
+TEST_P(PaintPropertyTreeBuilderTest,
+ PaintOffsetsUnderMultiColumnWithLayoutOverflow) {
+ SetBodyInnerHTML(R"HTML(
+ <div style='columns: 2; width: 300px; column-gap: 0; height: 100px'>
+ <div id='parent' style='outline: 2px solid black;
+ width: 100px; height: 100px'>
+ <div id='child' style='width: 100px; height: 200px'></div>
+ </div>
+ </div>
+ )HTML");
+
+ LayoutObject* parent = GetLayoutObjectByElementId("parent");
+ // Parent has 1 fragment regardless of the overflowing child.
+ ASSERT_EQ(1u, NumFragments(parent));
+ EXPECT_EQ(LayoutPoint(8, 8), FragmentAt(parent, 0).PaintOffset());
+
+ LayoutObject* child = GetLayoutObjectByElementId("child");
+ ASSERT_EQ(2u, NumFragments(child));
+ EXPECT_EQ(LayoutPoint(8, 8), FragmentAt(child, 0).PaintOffset());
+ EXPECT_EQ(LayoutPoint(158, -92), FragmentAt(child, 1).PaintOffset());
+}
+
TEST_P(PaintPropertyTreeBuilderTest, SpanFragmentsLimitedToSize) {
SetBodyInnerHTML(R"HTML(
<div style='columns: 10; height: 100px; width: 5000px'>
@@ -3709,8 +3728,8 @@ TEST_P(PaintPropertyTreeBuilderTest,
EXPECT_EQ(LayoutPoint(59, -12),
multicol_container->FirstFragment().NextFragment()->PaintOffset());
- GetDocument().View()->LayoutViewportScrollableArea()->ScrollBy(
- ScrollOffset(0, 25), kUserScroll);
+ GetDocument().View()->LayoutViewport()->ScrollBy(ScrollOffset(0, 25),
+ kUserScroll);
GetDocument().View()->UpdateAllLifecyclePhases();
ASSERT_TRUE(multicol_container->FirstFragment().NextFragment());
@@ -3965,7 +3984,7 @@ TEST_P(PaintPropertyTreeBuilderTest, CompositedUnderMultiColumn) {
EXPECT_EQ(LayoutUnit(),
FragmentAt(composited_child, 0).LogicalTopInFlowThread());
} else {
- // SPv1* forces single fragment for composited layers.
+ // SPv1 forces single fragment for composited layers.
EXPECT_EQ(1u, NumFragments(composited));
EXPECT_EQ(LayoutPoint(100, 100), FragmentAt(composited, 0).PaintOffset());
EXPECT_EQ(LayoutPoint(100, -200),
@@ -4415,10 +4434,6 @@ TEST_P(PaintPropertyTreeBuilderTest, EffectNodeAnimatedHasCompositorElementId) {
}
TEST_P(PaintPropertyTreeBuilderTest, FloatUnderInline) {
- // SPv1 has no effect tree.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<div style='position: absolute; top: 55px; left: 66px'>
<span id='span'
@@ -4477,21 +4492,12 @@ TEST_P(PaintPropertyTreeBuilderTest, OverflowClipSubpixelPosition) {
EXPECT_EQ(LayoutPoint(FloatPoint(31.5, 20)),
clipper->FirstFragment().PaintOffset());
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- // Result is pixel-snapped.
- EXPECT_EQ(FloatRect(32, 20, 400, 300),
- clip_properties->OverflowClip()->ClipRect().Rect());
- } else {
- EXPECT_EQ(FloatRect(31.5, 20, 400, 300),
- clip_properties->OverflowClip()->ClipRect().Rect());
- }
+ // Result is pixel-snapped.
+ EXPECT_EQ(FloatRect(32, 20, 400, 300),
+ clip_properties->OverflowClip()->ClipRect().Rect());
}
TEST_P(PaintPropertyTreeBuilderTest, MaskSimple) {
- // SPv1 has no effect tree.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<div id='target' style='width:300px; height:200px;
-webkit-mask:linear-gradient(red,red)'>
@@ -4520,10 +4526,6 @@ TEST_P(PaintPropertyTreeBuilderTest, MaskSimple) {
}
TEST_P(PaintPropertyTreeBuilderTest, MaskWithOutset) {
- // SPv1 has no effect tree.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<div id='target' style='width:300px; height:200px;
-webkit-mask-box-image-source:linear-gradient(red,red);
@@ -4553,10 +4555,6 @@ TEST_P(PaintPropertyTreeBuilderTest, MaskWithOutset) {
}
TEST_P(PaintPropertyTreeBuilderTest, MaskEscapeClip) {
- // SPv1 has no effect tree.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
// This test verifies an abs-pos element still escape the scroll of a
// static-pos ancestor, but gets clipped due to the presence of a mask.
SetBodyInnerHTML(R"HTML(
@@ -4615,7 +4613,7 @@ TEST_P(PaintPropertyTreeBuilderTest, MaskEscapeClip) {
EXPECT_EQ(DocPreTranslation(),
absolute->FirstFragment().LocalBorderBoxProperties().Transform());
} else {
- // For SPv1*, |absolute| is composited so we created PaintOffsetTranslation.
+ // For SPv1, |absolute| is composited so we created PaintOffsetTranslation.
EXPECT_EQ(
absolute->FirstFragment().PaintProperties()->PaintOffsetTranslation(),
absolute->FirstFragment().LocalBorderBoxProperties().Transform());
@@ -4625,10 +4623,6 @@ TEST_P(PaintPropertyTreeBuilderTest, MaskEscapeClip) {
}
TEST_P(PaintPropertyTreeBuilderTest, MaskInline) {
- // SPv1 has no effect tree.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
LoadAhem();
// This test verifies CSS mask applied on an inline element is clipped to
// the line box of the said element. In this test the masked element has
@@ -4699,7 +4693,7 @@ TEST_P(PaintPropertyTreeBuilderTest, SVGResource) {
// The <marker> object resets to a new paint property tree, so the
// transform within it should have the root as parent.
- EXPECT_EQ(TransformPaintPropertyNode::Root(),
+ EXPECT_EQ(&TransformPaintPropertyNode::Root(),
transform_inside_marker_properties->Transform()->Parent());
// Whereas this is not true of the transform above the path.
@@ -4732,7 +4726,7 @@ TEST_P(PaintPropertyTreeBuilderTest, SVGHiddenResource) {
// The <marker> object resets to a new paint property tree, so the
// transform within it should have the root as parent.
- EXPECT_EQ(TransformPaintPropertyNode::Root(),
+ EXPECT_EQ(&TransformPaintPropertyNode::Root(),
transform_inside_symbol_properties->Transform()->Parent());
// Whereas this is not true of the transform above the path.
@@ -4741,10 +4735,6 @@ TEST_P(PaintPropertyTreeBuilderTest, SVGHiddenResource) {
}
TEST_P(PaintPropertyTreeBuilderTest, SVGRootBlending) {
- // SPv1 has no effect tree.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<svg id='svgroot' 'width=100' height='100'
style='position: relative; z-index: 0'>
@@ -4757,7 +4747,7 @@ TEST_P(PaintPropertyTreeBuilderTest, SVGRootBlending) {
const ObjectPaintProperties* svg_root_properties =
svg_root.FirstFragment().PaintProperties();
EXPECT_TRUE(svg_root_properties->Effect());
- EXPECT_EQ(EffectPaintPropertyNode::Root(),
+ EXPECT_EQ(&EffectPaintPropertyNode::Root(),
svg_root_properties->Effect()->Parent());
}
@@ -4795,7 +4785,18 @@ TEST_P(PaintPropertyTreeBuilderTest, ScrollBoundsOffset) {
auto* scroll_translation = scroll_properties->ScrollTranslation();
auto* paint_offset_translation = scroll_properties->PaintOffsetTranslation();
auto* scroll_node = scroll_translation->ScrollNode();
- EXPECT_TRUE(scroll_node->Parent()->IsRoot());
+ // TODO(bokan): Viewport property node generation has been disabled
+ // temporarily with the flag off to diagnose https//crbug.com/868927.
+ if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
+ EXPECT_EQ(GetDocument()
+ .GetPage()
+ ->GetVisualViewport()
+ .GetScrollTranslationNode()
+ ->ScrollNode(),
+ scroll_node->Parent());
+ } else {
+ EXPECT_TRUE(scroll_node->Parent()->IsRoot());
+ }
EXPECT_EQ(TransformationMatrix().Translate(0, -42),
scroll_translation->Matrix());
// The paint offset node should be offset by the margin.
@@ -4839,7 +4840,7 @@ TEST_P(PaintPropertyTreeBuilderTest, BackfaceHidden) {
EXPECT_EQ(nullptr, paint_offset_translation);
EXPECT_EQ(LayoutPoint(60, 50), target->FirstFragment().PaintOffset());
} else {
- // For SPv1*, |target| is composited so we created PaintOffsetTranslation.
+ // For SPv1, |target| is composited so we created PaintOffsetTranslation.
ASSERT_NE(nullptr, paint_offset_translation);
EXPECT_EQ(TransformationMatrix().Translate(60, 50),
paint_offset_translation->Matrix());
@@ -4980,13 +4981,7 @@ TEST_P(PaintPropertyTreeBuilderTest, OverflowControlsClipSubpixel) {
const auto* properties1 = PaintPropertiesForElement("div1");
ASSERT_NE(nullptr, properties1);
const auto* overflow_controls_clip = properties1->OverflowControlsClip();
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(FloatRect(0, 0, 6, 50),
- overflow_controls_clip->ClipRect().Rect());
- } else {
- EXPECT_EQ(FloatRect(0, 0, 5.5, 50),
- overflow_controls_clip->ClipRect().Rect());
- }
+ EXPECT_EQ(FloatRect(0, 0, 6, 50), overflow_controls_clip->ClipRect().Rect());
const auto* properties2 = PaintPropertiesForElement("div2");
ASSERT_NE(nullptr, properties2);
@@ -5017,13 +5012,8 @@ TEST_P(PaintPropertyTreeBuilderTest, FragmentPaintOffsetUnderOverflowScroll) {
EXPECT_EQ(LayoutPoint(), first_fragment.PaintOffset());
EXPECT_EQ(LayoutPoint(390, -10), second_fragment->PaintOffset());
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(LayoutRect(0, 0, 20, 20), first_fragment.VisualRect());
- EXPECT_EQ(LayoutRect(390, -10, 20, 20), second_fragment->VisualRect());
- } else {
- EXPECT_EQ(LayoutRect(0, 50, 20, 10), first_fragment.VisualRect());
- EXPECT_EQ(LayoutRect(390, 50, 20, 10), second_fragment->VisualRect());
- }
+ EXPECT_EQ(LayoutRect(0, 0, 20, 20), first_fragment.VisualRect());
+ EXPECT_EQ(LayoutRect(390, -10, 20, 20), second_fragment->VisualRect());
}
// The following test tests that we restrict actual column count, to not run
@@ -5058,24 +5048,13 @@ TEST_P(PaintPropertyTreeBuilderTest, FragmentClipPixelSnapped) {
const auto* second_clip =
FragmentAt(flow_thread, 1).PaintProperties()->FragmentClip();
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(FloatRect(-999992, -999992, 1000025, 1000050),
- first_clip->ClipRect().Rect());
- EXPECT_EQ(FloatRect(33, 8, 1000000, 999951),
- second_clip->ClipRect().Rect());
- } else {
- EXPECT_EQ(FloatRect(-999992, -999992, 1000024.75, 1000049.5),
- first_clip->ClipRect().Rect());
- EXPECT_EQ(FloatRect(32.75, 8, 1000000, 999950.5),
- second_clip->ClipRect().Rect());
- }
+ EXPECT_EQ(FloatRect(-999992, -999992, 1000025, 1000050),
+ first_clip->ClipRect().Rect());
+ EXPECT_EQ(FloatRect(33, 8, 1000000, 999951), second_clip->ClipRect().Rect());
}
TEST_P(PaintPropertyTreeBuilderTest,
UpdateUnderChangedEffectUnderCompositedLayer) {
- // SPv1 has no effect tree.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
SetBodyInnerHTML(R"HTML(
<div id="opacity" style="isolation: isolate; width: 100px: height: 100px">
<div id="target"
@@ -5092,15 +5071,12 @@ TEST_P(PaintPropertyTreeBuilderTest,
opacity_element->setAttribute(HTMLNames::styleAttr, "opacity: 0.5");
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
- // In SPv175 mode, all paint chunks contained by the new opacity effect
- // node need to be re-painted.
+ // All paint chunks contained by the new opacity effect node need to be
+ // re-painted.
EXPECT_TRUE(ToLayoutBoxModelObject(target)->Layer()->NeedsRepaint());
}
TEST_P(PaintPropertyTreeBuilderTest, SVGRootWithMask) {
- // SPv1 has no effect tree.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
SetBodyInnerHTML(R"HTML(
<svg id="svg" width="16" height="16" mask="url(#test)">
<rect width="100%" height="16" fill="#fff"></rect>
@@ -5120,9 +5096,6 @@ TEST_P(PaintPropertyTreeBuilderTest, SVGRootWithMask) {
}
TEST_P(PaintPropertyTreeBuilderTest, SVGRootWithCSSMask) {
- // SPv1 has no effect tree.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
SetBodyInnerHTML(R"HTML(
<svg id="svg" width="16" height="16" style="-webkit-mask-image: url(fake);">
</svg>
@@ -5136,10 +5109,6 @@ TEST_P(PaintPropertyTreeBuilderTest, SVGRootWithCSSMask) {
TEST_P(PaintPropertyTreeBuilderTest, ClearClipPathEffectNode) {
// This test makes sure ClipPath effect node is cleared properly upon
// removal of a clip-path.
-
- // SPv1 has no effect tree.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
SetBodyInnerHTML(R"HTML(
<svg>
<clipPath clip-path="circle()" id="clip"></clipPath>
@@ -5611,4 +5580,58 @@ TEST_P(PaintPropertyTreeBuilderTest, LayeredImageWithInvertFilterUpdated) {
EXPECT_EQ(nullptr, PaintPropertiesForElement("img"));
}
+TEST_P(PaintPropertyTreeBuilderTest,
+ FloatPaintOffsetInContainerWithScrollbars) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ ::-webkit-scrollbar {width: 15px; height: 15px}
+ .container {
+ position: absolute; width: 200px; height: 200px; overflow: scroll;
+ }
+ .float-left {float: left; width: 100px; height: 100px;}
+ .float-right {float: right; width: 100px; height: 100px;}
+ </style>
+ <div class="container">
+ <div id="float-left" class="float-left"></div>
+ <div id="float-right" class="float-right"></div>
+ </div>
+ <div class="container" style="direction: rtl">
+ <div id="float-left-rtl" class="float-left"></div>
+ <div id="float-right-rtl" class="float-right"></div>
+ </div>
+ <div class="container" style="writing-mode: vertical-rl">
+ <div id="float-left-vrl" class="float-left"></div>
+ <div id="float-right-vrl" class="float-right"></div>
+ </div>
+ <div class="container" style="writing-mode: vertical-rl; direction: rtl">
+ <div id="float-left-rtl-vrl" class="float-left"></div>
+ <div id="float-right-rtl-vrl" class="float-right"></div>
+ </div>
+ <div class="container" style="writing-mode: vertical-lr">
+ <div id="float-left-vlr" class="float-left"></div>
+ <div id="float-right-vlr" class="float-right"></div>
+ </div>
+ <div class="container" style="writing-mode: vertical-lr; direction: rtl">
+ <div id="float-left-rtl-vlr" class="float-left"></div>
+ <div id="float-right-rtl-vlr" class="float-right"></div>
+ </div>
+ )HTML");
+
+ auto paint_offset = [this](const char* id) {
+ return GetLayoutObjectByElementId(id)->FirstFragment().PaintOffset();
+ };
+ EXPECT_EQ(LayoutPoint(0, 0), paint_offset("float-left"));
+ EXPECT_EQ(LayoutPoint(85, 100), paint_offset("float-right"));
+ EXPECT_EQ(LayoutPoint(15, 0), paint_offset("float-left-rtl"));
+ EXPECT_EQ(LayoutPoint(100, 100), paint_offset("float-right-rtl"));
+ EXPECT_EQ(LayoutPoint(100, 0), paint_offset("float-left-vrl"));
+ EXPECT_EQ(LayoutPoint(0, 85), paint_offset("float-right-vrl"));
+ EXPECT_EQ(LayoutPoint(100, 0), paint_offset("float-left-rtl-vrl"));
+ EXPECT_EQ(LayoutPoint(0, 85), paint_offset("float-right-rtl-vrl"));
+ EXPECT_EQ(LayoutPoint(0, 0), paint_offset("float-left-vlr"));
+ EXPECT_EQ(LayoutPoint(100, 85), paint_offset("float-right-vlr"));
+ EXPECT_EQ(LayoutPoint(0, 0), paint_offset("float-left-rtl-vlr"));
+ EXPECT_EQ(LayoutPoint(100, 85), paint_offset("float-right-rtl-vlr"));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.h b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.h
index b5c290c8749..0166f288bcb 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.h
@@ -40,6 +40,26 @@ class PaintPropertyTreeBuilderTest : public PaintControllerPaintTest {
const ObjectPaintProperties* PaintPropertiesForElement(const char* name);
+ static unsigned NumFragments(const LayoutObject* obj) {
+ unsigned count = 0;
+ auto* fragment = &obj->FirstFragment();
+ while (fragment) {
+ count++;
+ fragment = fragment->NextFragment();
+ }
+ return count;
+ }
+
+ static const FragmentData& FragmentAt(const LayoutObject* obj,
+ unsigned count) {
+ auto* fragment = &obj->FirstFragment();
+ while (count > 0) {
+ count--;
+ fragment = fragment->NextFragment();
+ }
+ return *fragment;
+ }
+
private:
void SetUp() override;
};
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.cc b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.cc
index a92005318c3..e407f3d2d33 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.cc
@@ -6,8 +6,10 @@
#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/visual_viewport.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/page/page.h"
#include "third_party/blink/renderer/core/paint/object_paint_properties.h"
#include <iomanip>
@@ -34,6 +36,8 @@ class FrameViewPropertyTreePrinter
using Traits = PropertyTreePrinterTraits<PropertyTreeNode>;
void CollectNodes(const LocalFrameView& frame_view) {
+ Traits::AddVisualViewportProperties(
+ frame_view.GetPage()->GetVisualViewport(), *this);
if (LayoutView* layout_view = frame_view.GetLayoutView())
CollectNodes(*layout_view);
for (Frame* child = frame_view.GetFrame().Tree().FirstChild(); child;
@@ -61,6 +65,12 @@ class FrameViewPropertyTreePrinter
template <>
class PropertyTreePrinterTraits<TransformPaintPropertyNode> {
public:
+ static void AddVisualViewportProperties(
+ const VisualViewport& visual_viewport,
+ PropertyTreePrinter<TransformPaintPropertyNode>& printer) {
+ printer.AddNode(visual_viewport.GetPageScaleNode());
+ printer.AddNode(visual_viewport.GetScrollTranslationNode());
+ }
static void AddObjectPaintProperties(
const LayoutObject& object,
const ObjectPaintProperties& properties,
@@ -76,6 +86,9 @@ class PropertyTreePrinterTraits<TransformPaintPropertyNode> {
template <>
class PropertyTreePrinterTraits<ClipPaintPropertyNode> {
public:
+ static void AddVisualViewportProperties(
+ const VisualViewport& visual_viewport,
+ PropertyTreePrinter<ClipPaintPropertyNode>& printer) {}
static void AddObjectPaintProperties(
const LayoutObject& object,
const ObjectPaintProperties& properties,
@@ -94,6 +107,10 @@ class PropertyTreePrinterTraits<ClipPaintPropertyNode> {
template <>
class PropertyTreePrinterTraits<EffectPaintPropertyNode> {
public:
+ static void AddVisualViewportProperties(
+ const VisualViewport& visual_viewport,
+ PropertyTreePrinter<EffectPaintPropertyNode>& printer) {}
+
static void AddObjectPaintProperties(
const LayoutObject& object,
const ObjectPaintProperties& properties,
@@ -108,6 +125,12 @@ class PropertyTreePrinterTraits<EffectPaintPropertyNode> {
template <>
class PropertyTreePrinterTraits<ScrollPaintPropertyNode> {
public:
+ static void AddVisualViewportProperties(
+ const VisualViewport& visual_viewport,
+ PropertyTreePrinter<ScrollPaintPropertyNode>& printer) {
+ printer.AddNode(visual_viewport.GetScrollNode());
+ }
+
static void AddObjectPaintProperties(
const LayoutObject& object,
const ObjectPaintProperties& properties,
@@ -134,6 +157,13 @@ void SetDebugName(const PropertyTreeNode* node,
namespace PaintPropertyTreePrinter {
+void UpdateDebugNames(const VisualViewport& viewport) {
+ viewport.GetPageScaleNode()->SetDebugName("VisualViewport Scale Node");
+ viewport.GetScrollTranslationNode()->SetDebugName(
+ "VisualViewport Translate Node");
+ viewport.GetScrollNode()->SetDebugName("VisualViewport Scroll Node");
+}
+
void UpdateDebugNames(const LayoutObject& object,
ObjectPaintProperties& properties) {
SetDebugName(properties.PaintOffsetTranslation(), "PaintOffsetTranslation",
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.h b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.h
index 53e936da3da..e7341612aa2 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.h
+++ b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer.h
@@ -15,9 +15,11 @@ namespace blink {
class LocalFrameView;
class LayoutObject;
class ObjectPaintProperties;
+class VisualViewport;
namespace PaintPropertyTreePrinter {
+void UpdateDebugNames(const VisualViewport&);
void UpdateDebugNames(const LayoutObject&, ObjectPaintProperties&);
} // namespace PaintPropertyTreePrinter
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer_test.cc b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer_test.cc
index 533f038cffd..190f7f4743e 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_printer_test.cc
@@ -46,9 +46,6 @@ TEST_P(PaintPropertyTreePrinterTest, SimpleClipTree) {
}
TEST_P(PaintPropertyTreePrinterTest, SimpleEffectTree) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML("<div style='opacity: 0.9;'>hello world</div>");
String effect_tree_as_string =
effectPropertyTreeAsString(*GetDocument().View());
@@ -100,9 +97,6 @@ TEST_P(PaintPropertyTreePrinterTest, SimpleClipTreePath) {
}
TEST_P(PaintPropertyTreePrinterTest, SimpleEffectTreePath) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML("<div id='effect' style='opacity: 0.9;'></div>");
LayoutObject* effect_object =
GetDocument().getElementById("effect")->GetLayoutObject();
diff --git a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc
index d878e97a3f5..9c0248b1125 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "third_party/blink/renderer/core/frame/visual_viewport.h"
#include "third_party/blink/renderer/core/html/forms/html_select_element.h"
#include "third_party/blink/renderer/core/html/html_iframe_element.h"
#include "third_party/blink/renderer/core/page/focus_controller.h"
@@ -250,6 +251,8 @@ TEST_P(PaintPropertyTreeUpdateTest,
)HTML");
Element* overflow_a = GetDocument().getElementById("overflowA");
Element* overflow_b = GetDocument().getElementById("overflowB");
+ VisualViewport& visual_viewport =
+ GetDocument().GetPage()->GetVisualViewport();
// This should be false. We are not as strict about main thread scrolling
// reasons as we could be.
@@ -265,13 +268,25 @@ TEST_P(PaintPropertyTreeUpdateTest,
->ScrollTranslation()
->ScrollNode()
->HasBackgroundAttachmentFixedDescendants());
- EXPECT_TRUE(overflow_b->GetLayoutObject()
+
+ // TODO(bokan): Viewport property node generation has been disabled
+ // temporarily with the flag off to diagnose https//crbug.com/868927.
+ if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
+ EXPECT_EQ(visual_viewport.GetScrollNode(), overflow_b->GetLayoutObject()
+ ->FirstFragment()
+ .PaintProperties()
+ ->ScrollTranslation()
+ ->ScrollNode()
+ ->Parent());
+ } else {
+ EXPECT_TRUE(overflow_b->GetLayoutObject()
->FirstFragment()
.PaintProperties()
->ScrollTranslation()
->ScrollNode()
->Parent()
->IsRoot());
+ }
// Removing a main thread scrolling reason should update the entire tree.
overflow_b->removeAttribute("class");
@@ -848,9 +863,6 @@ TEST_P(PaintPropertyTreeUpdateTest, MenuListControlClipChange) {
}
TEST_P(PaintPropertyTreeUpdateTest, BoxAddRemoveMask) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<style>#target {width: 100px; height: 100px}</style>
<div id='target'>
@@ -879,9 +891,6 @@ TEST_P(PaintPropertyTreeUpdateTest, BoxAddRemoveMask) {
}
TEST_P(PaintPropertyTreeUpdateTest, MaskClipNodeBoxSizeChange) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<style>
#target {
@@ -910,9 +919,6 @@ TEST_P(PaintPropertyTreeUpdateTest, MaskClipNodeBoxSizeChange) {
}
TEST_P(PaintPropertyTreeUpdateTest, InlineAddRemoveMask) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(
"<span id='target'><img id='img' style='width: 50px'></span>");
@@ -937,9 +943,6 @@ TEST_P(PaintPropertyTreeUpdateTest, InlineAddRemoveMask) {
}
TEST_P(PaintPropertyTreeUpdateTest, MaskClipNodeInlineBoundsChange) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<span id='target' style='-webkit-mask: linear-gradient(red, blue)'>
<img id='img' style='width: 50px'>
@@ -961,9 +964,6 @@ TEST_P(PaintPropertyTreeUpdateTest, MaskClipNodeInlineBoundsChange) {
}
TEST_P(PaintPropertyTreeUpdateTest, AddRemoveSVGMask) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<svg width='200' height='200'>
<rect id='rect' x='0' y='100' width='100' height='100' fill='blue'/>
@@ -993,9 +993,6 @@ TEST_P(PaintPropertyTreeUpdateTest, AddRemoveSVGMask) {
}
TEST_P(PaintPropertyTreeUpdateTest, SVGMaskTargetBoundsChange) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<svg width='500' height='500'>
<g id='target' mask='url(#mask)'>
@@ -1103,9 +1100,6 @@ TEST_P(PaintPropertyTreeUpdateTest, CompositingReasonForAnimation) {
}
TEST_P(PaintPropertyTreeUpdateTest, SVGViewportContainerOverflowChange) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<svg>
<svg id='target' width='30' height='40'></svg>
@@ -1130,9 +1124,6 @@ TEST_P(PaintPropertyTreeUpdateTest, SVGViewportContainerOverflowChange) {
}
TEST_P(PaintPropertyTreeUpdateTest, SVGForeignObjectOverflowChange) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
SetBodyInnerHTML(R"HTML(
<svg>
<foreignObject id='target' x='10' y='20' width='30' height='40'
@@ -1197,4 +1188,80 @@ TEST_P(PaintPropertyTreeBuilderTest, OmitOverflowClipOnCaretChange) {
EXPECT_FALSE(PaintPropertiesForElement("target")->OverflowClip());
}
+TEST_P(PaintPropertyTreeUpdateTest,
+ FragmentClipUpdateOnMulticolContainerWidthChange) {
+ SetBodyInnerHTML(R"HTML(
+ <style>body {margin: 0}</style>
+ <div id="container" style="width: 100px">
+ <div id="multicol" style="columns: 2; column-gap: 0; line-height: 500px">
+ <div><br></div>
+ <div><br></div>
+ </div>
+ </div>
+ )HTML");
+
+ auto* flow_thread = GetLayoutObjectByElementId("multicol")->SlowFirstChild();
+ ASSERT_EQ(2u, NumFragments(flow_thread));
+ EXPECT_EQ(50, FragmentAt(flow_thread, 0)
+ .PaintProperties()
+ ->FragmentClip()
+ ->ClipRect()
+ .Rect()
+ .MaxX());
+ EXPECT_EQ(50, FragmentAt(flow_thread, 1)
+ .PaintProperties()
+ ->FragmentClip()
+ ->ClipRect()
+ .Rect()
+ .X());
+
+ GetDocument()
+ .getElementById("container")
+ ->setAttribute(HTMLNames::styleAttr, "width: 500px");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ ASSERT_EQ(2u, NumFragments(flow_thread));
+ EXPECT_EQ(250, FragmentAt(flow_thread, 0)
+ .PaintProperties()
+ ->FragmentClip()
+ ->ClipRect()
+ .Rect()
+ .MaxX());
+ EXPECT_EQ(250, FragmentAt(flow_thread, 1)
+ .PaintProperties()
+ ->FragmentClip()
+ ->ClipRect()
+ .Rect()
+ .X());
+}
+
+TEST_P(PaintPropertyTreeUpdateTest,
+ PropertyTreesRebuiltAfterSVGBlendModeChange) {
+ SetBodyInnerHTML(R"HTML(
+ <style>
+ #blended {
+ mix-blend-mode: darken;
+ fill: red;
+ }
+ </style>
+ <svg width="100" height="100">
+ <rect id="blended" x="0" y="0" width="100" height="100"></rect>
+ </svg>
+ )HTML");
+
+ auto* blended_element = GetDocument().getElementById("blended");
+ ASSERT_TRUE(blended_element);
+ const auto* props =
+ blended_element->GetLayoutObject()->FirstFragment().PaintProperties();
+ ASSERT_TRUE(props->Effect());
+ EXPECT_EQ(props->Effect()->BlendMode(), SkBlendMode::kDarken);
+
+ blended_element->setAttribute(HTMLNames::styleAttr,
+ "mix-blend-mode: lighten;");
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ props = blended_element->GetLayoutObject()->FirstFragment().PaintProperties();
+ ASSERT_TRUE(props->Effect());
+ EXPECT_EQ(props->Effect()->BlendMode(), SkBlendMode::kLighten);
+}
+
} // 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 51d31b3c9e6..950858001dd 100644
--- a/chromium/third_party/blink/renderer/core/paint/paint_timing.cc
+++ b/chromium/third_party/blink/renderer/core/paint/paint_timing.cc
@@ -24,6 +24,7 @@
#include "third_party/blink/renderer/platform/histogram.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/wtf.h"
namespace blink {
@@ -204,6 +205,7 @@ void PaintTiming::RegisterNotifySwapTime(PaintEvent event,
void PaintTiming::ReportSwapTime(PaintEvent event,
WebLayerTreeView::SwapResult result,
base::TimeTicks timestamp) {
+ DCHECK(IsMainThread());
// If the swap fails for any reason, we use the timestamp when the SwapPromise
// was broken. |result| == WebLayerTreeView::SwapResult::kDidNotSwapSwapFails
// usually means the compositor decided not swap because there was no actual
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 59c20860f89..78fa2485612 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
@@ -6,12 +6,15 @@
#include "base/auto_reset.h"
#include "third_party/blink/renderer/core/dom/document_lifecycle.h"
+#include "third_party/blink/renderer/core/frame/event_handler_registry.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"
#include "third_party/blink/renderer/core/layout/layout_embedded_content.h"
#include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/compositing/compositing_layer_property_updater.h"
#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
@@ -43,6 +46,12 @@ void PrePaintTreeWalk::WalkTree(LocalFrameView& root_frame_view) {
if (needs_tree_builder_context_update)
GeometryMapper::ClearCache();
+ if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
+ VisualViewportPaintPropertyTreeBuilder::Update(
+ root_frame_view.GetPage()->GetVisualViewport(),
+ *context_storage_.back().tree_builder_context);
+ }
+
Walk(root_frame_view);
paint_invalidator_.ProcessPendingDelayedPaintInvalidations();
context_storage_.pop_back();
@@ -92,7 +101,7 @@ void PrePaintTreeWalk::Walk(LocalFrameView& frame_view) {
return context_storage_.back();
};
- // ancestorOverflowLayer does not cross frame boundaries.
+ // ancestor_overflow_paint_layer does not cross frame boundaries.
context().ancestor_overflow_paint_layer = nullptr;
if (context().tree_builder_context) {
PaintPropertyTreeBuilder::SetupContextForFrame(
@@ -121,12 +130,90 @@ void PrePaintTreeWalk::Walk(LocalFrameView& frame_view) {
#endif
}
- frame_view.ClearNeedsPaintPropertyUpdate();
if (RuntimeEnabledFeatures::JankTrackingEnabled())
frame_view.GetJankTracker().NotifyPrePaintFinished();
+
context_storage_.pop_back();
}
+bool PrePaintTreeWalk::NeedsEffectiveWhitelistedTouchActionUpdate(
+ const LayoutObject& object,
+ PrePaintTreeWalk::PrePaintTreeWalkContext& context) const {
+ if (!RuntimeEnabledFeatures::PaintTouchActionRectsEnabled())
+ return false;
+ return context.effective_whitelisted_touch_action_changed ||
+ object.EffectiveWhitelistedTouchActionChanged() ||
+ object.DescendantEffectiveWhitelistedTouchActionChanged();
+}
+
+namespace {
+bool HasBlockingTouchEventHandler(const LocalFrame& frame,
+ EventTarget& target) {
+ if (!target.HasEventListeners())
+ return false;
+ const auto& registry = frame.GetEventHandlerRegistry();
+ const auto* blocking = registry.EventHandlerTargets(
+ EventHandlerRegistry::kTouchStartOrMoveEventBlocking);
+ const auto* blocking_low_latency = registry.EventHandlerTargets(
+ EventHandlerRegistry::kTouchStartOrMoveEventBlocking);
+ return blocking->Contains(&target) || blocking_low_latency->Contains(&target);
+}
+
+bool HasBlockingTouchEventHandler(const LayoutObject& object) {
+ if (object.IsLayoutView()) {
+ auto* frame = object.GetFrame();
+ if (HasBlockingTouchEventHandler(*frame, *frame->DomWindow()))
+ return true;
+ }
+
+ auto* node = object.GetNode();
+ if (!node)
+ return false;
+ return HasBlockingTouchEventHandler(*object.GetFrame(), *node);
+}
+} // namespace
+
+void PrePaintTreeWalk::UpdateEffectiveWhitelistedTouchAction(
+ const LayoutObject& object,
+ PrePaintTreeWalk::PrePaintTreeWalkContext& context) {
+ if (!RuntimeEnabledFeatures::PaintTouchActionRectsEnabled())
+ return;
+
+ if (object.EffectiveWhitelistedTouchActionChanged())
+ context.effective_whitelisted_touch_action_changed = true;
+
+ if (context.effective_whitelisted_touch_action_changed) {
+ object.GetMutableForPainting().UpdateInsideBlockingTouchEventHandler(
+ context.inside_blocking_touch_event_handler ||
+ HasBlockingTouchEventHandler(object));
+ }
+
+ if (object.InsideBlockingTouchEventHandler())
+ context.inside_blocking_touch_event_handler = true;
+}
+
+bool PrePaintTreeWalk::NeedsHitTestingPaintInvalidation(
+ const LayoutObject& object,
+ const PrePaintTreeWalk::PrePaintTreeWalkContext& context) const {
+ if (!RuntimeEnabledFeatures::PaintTouchActionRectsEnabled())
+ return false;
+ return context.effective_whitelisted_touch_action_changed;
+}
+
+void PrePaintTreeWalk::InvalidatePaintForHitTesting(
+ const LayoutObject& object,
+ PrePaintTreeWalk::PrePaintTreeWalkContext& context) {
+ if (!RuntimeEnabledFeatures::PaintTouchActionRectsEnabled())
+ return;
+
+ if (context.effective_whitelisted_touch_action_changed) {
+ if (auto* paint_layer = context.paint_invalidator_context.painting_layer)
+ paint_layer->SetNeedsRepaint();
+ ObjectPaintInvalidator(object).InvalidateDisplayItemClient(
+ object, PaintInvalidationReason::kHitTest);
+ }
+}
+
void PrePaintTreeWalk::UpdateAuxiliaryObjectProperties(
const LayoutObject& object,
PrePaintTreeWalk::PrePaintTreeWalkContext& context) {
@@ -175,9 +262,8 @@ void PrePaintTreeWalk::InvalidatePaintLayerOptimizationsIfNeeded(
bool PrePaintTreeWalk::NeedsTreeBuilderContextUpdate(
const LocalFrameView& frame_view,
const PrePaintTreeWalkContext& context) {
- return frame_view.NeedsPaintPropertyUpdate() ||
- (frame_view.GetLayoutView() &&
- NeedsTreeBuilderContextUpdate(*frame_view.GetLayoutView(), context));
+ return frame_view.GetLayoutView() &&
+ NeedsTreeBuilderContextUpdate(*frame_view.GetLayoutView(), context);
}
bool PrePaintTreeWalk::NeedsTreeBuilderContextUpdate(
@@ -232,7 +318,6 @@ void PrePaintTreeWalk::WalkInternal(const LayoutObject& object,
}
if (property_changed &&
- RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
!context.tree_builder_context
->supports_composited_raster_invalidation) {
paint_invalidator_context.subtree_flags |=
@@ -240,16 +325,21 @@ void PrePaintTreeWalk::WalkInternal(const LayoutObject& object,
}
}
+ // This must happen before paint invalidation because background painting
+ // depends on the effective whitelisted touch action.
+ UpdateEffectiveWhitelistedTouchAction(object, context);
+
paint_invalidator_.InvalidatePaint(
object, base::OptionalOrNullptr(context.tree_builder_context),
paint_invalidator_context);
+ InvalidatePaintForHitTesting(object, context);
+
if (context.tree_builder_context) {
property_changed |= property_tree_builder->UpdateForChildren();
InvalidatePaintLayerOptimizationsIfNeeded(object, context);
- if (property_changed &&
- RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
+ if (property_changed) {
if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
const auto* paint_invalidation_layer =
paint_invalidator_context.paint_invalidation_container->Layer();
@@ -291,7 +381,10 @@ void PrePaintTreeWalk::Walk(const LayoutObject& object) {
NeedsTreeBuilderContextUpdate(object, parent_context());
// Early out from the tree walk if possible.
if (!needs_tree_builder_context_update &&
- !object.ShouldCheckForPaintInvalidation()) {
+ !object.ShouldCheckForPaintInvalidation() &&
+ !parent_context().paint_invalidator_context.NeedsSubtreeWalk() &&
+ !NeedsEffectiveWhitelistedTouchActionUpdate(object, parent_context()) &&
+ !NeedsHitTestingPaintInvalidation(object, parent_context())) {
return;
}
diff --git a/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h b/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h
index 84477b28814..3d51b061229 100644
--- a/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h
+++ b/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk.h
@@ -38,7 +38,11 @@ class CORE_EXPORT PrePaintTreeWalk {
bool needs_tree_builder_context)
: paint_invalidator_context(parent_context_accessor),
ancestor_overflow_paint_layer(
- parent_context.ancestor_overflow_paint_layer) {
+ parent_context.ancestor_overflow_paint_layer),
+ inside_blocking_touch_event_handler(
+ parent_context.inside_blocking_touch_event_handler),
+ effective_whitelisted_touch_action_changed(
+ parent_context.effective_whitelisted_touch_action_changed) {
if (needs_tree_builder_context || DCHECK_IS_ON()) {
DCHECK(parent_context.tree_builder_context);
tree_builder_context.emplace(*parent_context.tree_builder_context);
@@ -57,6 +61,13 @@ class CORE_EXPORT PrePaintTreeWalk {
// is the root layer. Note that it is tree ancestor, not containing
// block or stacking ancestor.
PaintLayer* ancestor_overflow_paint_layer = nullptr;
+
+ // Whether there is a blocking touch event handler on any ancestor.
+ bool inside_blocking_touch_event_handler = false;
+
+ // When the effective whitelisted touch action changes on an ancestor, the
+ // entire subtree may need to update.
+ bool effective_whitelisted_touch_action_changed = false;
};
const PrePaintTreeWalkContext& ContextAt(size_t index) {
@@ -86,6 +97,19 @@ class CORE_EXPORT PrePaintTreeWalk {
void UpdateAuxiliaryObjectProperties(const LayoutObject&,
PrePaintTreeWalkContext&);
+ bool NeedsEffectiveWhitelistedTouchActionUpdate(
+ const LayoutObject&,
+ PrePaintTreeWalkContext&) const;
+ // Updates |LayoutObject::InsideBlockingTouchEventHandler|. Also ensures
+ // |PrePaintTreeWalkContext.effective_whitelisted_touch_action_changed| is set
+ // which will ensure the subtree is updated too.
+ void UpdateEffectiveWhitelistedTouchAction(const LayoutObject&,
+ PrePaintTreeWalkContext&);
+ bool NeedsHitTestingPaintInvalidation(const LayoutObject&,
+ const PrePaintTreeWalkContext&) const;
+ void InvalidatePaintForHitTesting(const LayoutObject&,
+ PrePaintTreeWalkContext&);
+
void ResizeContextStorageIfNeeded();
PaintInvalidator paint_invalidator_;
diff --git a/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk_test.cc b/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk_test.cc
index 9198deef352..7ba16801482 100644
--- a/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/pre_paint_tree_walk_test.cc
@@ -2,14 +2,15 @@
// 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/pre_paint_tree_walk.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/layout/layout_tree_as_text.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/paint/object_paint_properties.h"
#include "third_party/blink/renderer/core/paint/paint_controller_paint_test.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/paint/paint_property_tree_printer.h"
-#include "third_party/blink/renderer/core/paint/pre_paint_tree_walk.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
#include "third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.h"
@@ -122,9 +123,6 @@ TEST_P(PrePaintTreeWalkTest, PropertyTreesRebuiltWithCSSTransformInvalidation) {
}
TEST_P(PrePaintTreeWalkTest, PropertyTreesRebuiltWithOpacityInvalidation) {
- // In SPv1 mode, we don't need or store property tree nodes for effects.
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
SetBodyInnerHTML(R"HTML(
<style>
.opacityA { opacity: 0.9; }
@@ -277,12 +275,7 @@ TEST_P(PrePaintTreeWalkTest, VisualRectClipForceSubtree) {
GetDocument().getElementById("parent")->removeAttribute("style");
GetDocument().View()->UpdateAllLifecyclePhases();
- // In SPv175 mode, VisualRects are in the space of the containing transform
- // node without applying any ancestor property nodes, including clip.
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- EXPECT_EQ(200, grandchild->FirstFragment().VisualRect().Height());
- else
- EXPECT_EQ(75, grandchild->FirstFragment().VisualRect().Height());
+ EXPECT_EQ(200, grandchild->FirstFragment().VisualRect().Height());
}
TEST_P(PrePaintTreeWalkTest, ClipChangeHasRadius) {
@@ -308,4 +301,116 @@ TEST_P(PrePaintTreeWalkTest, ClipChangeHasRadius) {
GetDocument().View()->UpdateAllLifecyclePhases();
}
+namespace {
+class PrePaintTreeWalkMockEventListener final : public EventListener {
+ public:
+ PrePaintTreeWalkMockEventListener() : EventListener(kCPPEventListenerType) {}
+
+ bool operator==(const EventListener& other) const final {
+ return this == &other;
+ }
+
+ void handleEvent(ExecutionContext*, Event*) final {}
+};
+} // namespace
+
+TEST_P(PrePaintTreeWalkTest, InsideBlockingTouchEventHandlerUpdate) {
+ ScopedPaintTouchActionRectsForTest enable_paint_touch_action_rects(true);
+ SetBodyInnerHTML(R"HTML(
+ <div id='ancestor' style='width: 100px; height: 100px;'>
+ <div id='handler' style='width: 100px; height: 100px;'>
+ <div id='descendant' style='width: 100px; height: 100px;'>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ auto& ancestor = *GetLayoutObjectByElementId("ancestor");
+ auto& handler = *GetLayoutObjectByElementId("handler");
+ auto& descendant = *GetLayoutObjectByElementId("descendant");
+
+ EXPECT_FALSE(ancestor.EffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(handler.EffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(descendant.EffectiveWhitelistedTouchActionChanged());
+
+ EXPECT_FALSE(ancestor.DescendantEffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(handler.DescendantEffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(descendant.DescendantEffectiveWhitelistedTouchActionChanged());
+
+ EXPECT_FALSE(ancestor.InsideBlockingTouchEventHandler());
+ EXPECT_FALSE(handler.InsideBlockingTouchEventHandler());
+ EXPECT_FALSE(descendant.InsideBlockingTouchEventHandler());
+
+ PrePaintTreeWalkMockEventListener* callback =
+ new PrePaintTreeWalkMockEventListener();
+ auto* handler_element = GetDocument().getElementById("handler");
+ handler_element->addEventListener(EventTypeNames::touchstart, callback);
+
+ EXPECT_FALSE(ancestor.EffectiveWhitelistedTouchActionChanged());
+ EXPECT_TRUE(handler.EffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(descendant.EffectiveWhitelistedTouchActionChanged());
+
+ EXPECT_TRUE(ancestor.DescendantEffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(handler.DescendantEffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(descendant.DescendantEffectiveWhitelistedTouchActionChanged());
+
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ EXPECT_FALSE(ancestor.EffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(handler.EffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(descendant.EffectiveWhitelistedTouchActionChanged());
+
+ EXPECT_FALSE(ancestor.DescendantEffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(handler.DescendantEffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(descendant.DescendantEffectiveWhitelistedTouchActionChanged());
+
+ EXPECT_FALSE(ancestor.InsideBlockingTouchEventHandler());
+ EXPECT_TRUE(handler.InsideBlockingTouchEventHandler());
+ EXPECT_TRUE(descendant.InsideBlockingTouchEventHandler());
+}
+
+TEST_P(PrePaintTreeWalkTest, EffectiveTouchActionStyleUpdate) {
+ ScopedPaintTouchActionRectsForTest enable_paint_touch_action_rects(true);
+ SetBodyInnerHTML(R"HTML(
+ <style> .touchaction { touch-action: none; } </style>
+ <div id='ancestor' style='width: 100px; height: 100px;'>
+ <div id='touchaction' style='width: 100px; height: 100px;'>
+ <div id='descendant' style='width: 100px; height: 100px;'>
+ </div>
+ </div>
+ </div>
+ )HTML");
+
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ auto& ancestor = *GetLayoutObjectByElementId("ancestor");
+ auto& touchaction = *GetLayoutObjectByElementId("touchaction");
+ auto& descendant = *GetLayoutObjectByElementId("descendant");
+
+ EXPECT_FALSE(ancestor.EffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(touchaction.EffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(descendant.EffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(ancestor.DescendantEffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(touchaction.DescendantEffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(descendant.DescendantEffectiveWhitelistedTouchActionChanged());
+
+ GetDocument()
+ .getElementById("touchaction")
+ ->setAttribute(HTMLNames::classAttr, "touchaction");
+ GetDocument().View()->UpdateLifecycleToLayoutClean();
+ EXPECT_FALSE(ancestor.EffectiveWhitelistedTouchActionChanged());
+ EXPECT_TRUE(touchaction.EffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(descendant.EffectiveWhitelistedTouchActionChanged());
+ EXPECT_TRUE(ancestor.DescendantEffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(touchaction.DescendantEffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(descendant.DescendantEffectiveWhitelistedTouchActionChanged());
+
+ GetDocument().View()->UpdateAllLifecyclePhases();
+ EXPECT_FALSE(ancestor.EffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(touchaction.EffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(descendant.EffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(ancestor.DescendantEffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(touchaction.DescendantEffectiveWhitelistedTouchActionChanged());
+ EXPECT_FALSE(descendant.DescendantEffectiveWhitelistedTouchActionChanged());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/raster_invalidation_test.cc b/chromium/third_party/blink/renderer/core/paint/raster_invalidation_test.cc
deleted file mode 100644
index 55a09c6801e..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/raster_invalidation_test.cc
+++ /dev/null
@@ -1,90 +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/paint/paint_controller_paint_test.h"
-
-#include "cc/layers/picture_layer.h"
-#include "testing/gmock/include/gmock/gmock-matchers.h"
-#include "third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h"
-#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
-#include "third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.h"
-
-namespace blink {
-
-class RasterInvalidationTest : public PaintControllerPaintTest {
- protected:
- cc::Layer* GetCcLayer() const {
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- return GetDocument()
- .View()
- ->GetPaintArtifactCompositorForTesting()
- ->RootLayer()
- ->child_at(0);
- }
- return GetLayoutView().Layer()->GraphicsLayerBacking()->ContentLayer();
- }
-
- cc::LayerClient* GetCcLayerClient() const {
- return GetCcLayer()->GetLayerClientForTesting();
- }
-
- void SetUp() override {
- PaintControllerPaintTest::SetUp();
-
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- web_layer_tree_view_ = std::make_unique<WebLayerTreeViewImplForTesting>();
- web_layer_tree_view_->SetRootLayer(
- GetDocument()
- .View()
- ->GetPaintArtifactCompositorForTesting()
- ->RootLayer());
- }
- }
-
- private:
- std::unique_ptr<WebLayerTreeViewImplForTesting> web_layer_tree_view_;
-};
-
-INSTANTIATE_PAINT_TEST_CASE_P(RasterInvalidationTest);
-
-TEST_P(RasterInvalidationTest, TrackingForTracing) {
- SetBodyInnerHTML(R"HTML(
- <style>#target { width: 100px; height: 100px; background: blue }</style>
- <div id="target"></div>
- )HTML");
- auto* target = GetDocument().getElementById("target");
-
- {
- // This is equivalent to enabling disabled-by-default-blink.invalidation
- // for tracing.
- ScopedPaintUnderInvalidationCheckingForTest checking(true);
-
- target->setAttribute(HTMLNames::styleAttr, "height: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_THAT(GetCcLayerClient()->TakeDebugInfo(GetCcLayer())->ToString(),
- testing::MatchesRegex(
- "\\{\"layer_name\":.*\"annotated_invalidation_rects\":\\["
- "\\{\"geometry_rect\":\\[8,108,100,100\\],"
- "\"reason\":\"incremental\","
- "\"client\":\"LayoutBlockFlow DIV id='target'\"\\}\\]\\}"));
-
- target->setAttribute(HTMLNames::styleAttr, "height: 200px; width: 200px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_THAT(GetCcLayerClient()->TakeDebugInfo(GetCcLayer())->ToString(),
- testing::MatchesRegex(
- "\\{\"layer_name\":.*\"annotated_invalidation_rects\":\\["
- "\\{\"geometry_rect\":\\[108,8,100,200\\],"
- "\"reason\":\"incremental\","
- "\"client\":\"LayoutBlockFlow DIV id='target'\"\\}\\]\\}"));
- }
-
- target->setAttribute(HTMLNames::styleAttr, "height: 300px; width: 300px");
- GetDocument().View()->UpdateAllLifecyclePhases();
- EXPECT_EQ(std::string::npos, GetCcLayerClient()
- ->TakeDebugInfo(GetCcLayer())
- ->ToString()
- .find("invalidation_rects"));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/replaced_painter.cc b/chromium/third_party/blink/renderer/core/paint/replaced_painter.cc
index 0d50e82766b..b6219caf7b1 100644
--- a/chromium/third_party/blink/renderer/core/paint/replaced_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/replaced_painter.cc
@@ -21,21 +21,15 @@
namespace blink {
-static bool ShouldApplyViewportClip(const LayoutReplaced& layout_replaced) {
- return !layout_replaced.IsSVGRoot() ||
- ToLayoutSVGRoot(&layout_replaced)->ShouldApplyViewportClip();
-}
-
-void ReplacedPainter::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
- AdjustPaintOffsetScope adjustment(layout_replaced_, paint_info, paint_offset);
+void ReplacedPainter::Paint(const PaintInfo& paint_info) {
+ AdjustPaintOffsetScope adjustment(layout_replaced_, paint_info);
const auto& local_paint_info = adjustment.GetPaintInfo();
- auto adjusted_paint_offset = adjustment.AdjustedPaintOffset();
+ auto paint_offset = adjustment.PaintOffset();
- if (!ShouldPaint(local_paint_info, adjusted_paint_offset))
+ if (!ShouldPaint(local_paint_info, paint_offset))
return;
- LayoutRect border_rect(adjusted_paint_offset, layout_replaced_.Size());
+ LayoutRect border_rect(paint_offset, layout_replaced_.Size());
if (ShouldPaintSelfBlockBackground(local_paint_info.phase)) {
if (layout_replaced_.Style()->Visibility() == EVisibility::kVisible &&
@@ -49,7 +43,7 @@ void ReplacedPainter::Paint(const PaintInfo& paint_info,
return;
layout_replaced_.PaintBoxDecorationBackground(local_paint_info,
- adjusted_paint_offset);
+ paint_offset);
}
// We're done. We don't bother painting any children.
if (local_paint_info.phase == PaintPhase::kSelfBlockBackgroundOnly)
@@ -57,25 +51,19 @@ void ReplacedPainter::Paint(const PaintInfo& paint_info,
}
if (local_paint_info.phase == PaintPhase::kMask) {
- layout_replaced_.PaintMask(local_paint_info, adjusted_paint_offset);
+ layout_replaced_.PaintMask(local_paint_info, paint_offset);
return;
}
- if (local_paint_info.phase == PaintPhase::kClippingMask &&
- (!layout_replaced_.HasLayer() ||
- !layout_replaced_.Layer()->HasCompositedClippingMask()))
- return;
-
if (ShouldPaintSelfOutline(local_paint_info.phase)) {
ObjectPainter(layout_replaced_)
- .PaintOutline(local_paint_info, adjusted_paint_offset);
+ .PaintOutline(local_paint_info, paint_offset);
return;
}
if (local_paint_info.phase != PaintPhase::kForeground &&
local_paint_info.phase != PaintPhase::kSelection &&
- !layout_replaced_.CanHaveChildren() &&
- local_paint_info.phase != PaintPhase::kClippingMask)
+ !layout_replaced_.CanHaveChildren())
return;
if (local_paint_info.phase == PaintPhase::kSelection &&
@@ -83,69 +71,37 @@ void ReplacedPainter::Paint(const PaintInfo& paint_info,
return;
{
- base::Optional<RoundedInnerRectClipper> clipper;
base::Optional<ScopedPaintChunkProperties> chunk_properties;
bool completely_clipped_out = false;
if (layout_replaced_.Style()->HasBorderRadius() && border_rect.IsEmpty())
completely_clipped_out = true;
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- if (!layout_replaced_.IsSVGRoot()) {
- if (layout_replaced_.Style()->HasBorderRadius()) {
- if (const auto* fragment =
- paint_info.FragmentToPaint(layout_replaced_)) {
- const auto* paint_properties = fragment->PaintProperties();
- DCHECK(paint_properties &&
- paint_properties->InnerBorderRadiusClip());
+ if (!layout_replaced_.IsSVGRoot()) {
+ if (const auto* fragment = paint_info.FragmentToPaint(layout_replaced_)) {
+ if (const auto* paint_properties = fragment->PaintProperties()) {
+ // Check filter for optimized image policy violation highlights, which
+ // may be applied locally.
+ if (paint_properties->Filter() &&
+ (!layout_replaced_.HasLayer() ||
+ !layout_replaced_.Layer()->IsSelfPaintingLayer())) {
chunk_properties.emplace(
local_paint_info.context.GetPaintController(),
- paint_properties->InnerBorderRadiusClip(), layout_replaced_,
+ fragment->ContentsProperties(), layout_replaced_,
DisplayItem::PaintPhaseToDrawingType(local_paint_info.phase));
- }
- } else if (!layout_replaced_.HasLayer() ||
- !layout_replaced_.Layer()->IsSelfPaintingLayer()) {
- // The only use case of this is to apply color-inversion filter for
- // images violating feature policy optimized image policies.
- if (layout_replaced_.FirstFragment().HasLocalBorderBoxProperties()) {
+ } else if (layout_replaced_.Style()->HasBorderRadius()) {
+ DCHECK(paint_properties->InnerBorderRadiusClip());
chunk_properties.emplace(
local_paint_info.context.GetPaintController(),
- layout_replaced_.FirstFragment().LocalBorderBoxProperties(),
- layout_replaced_,
+ paint_properties->InnerBorderRadiusClip(), layout_replaced_,
DisplayItem::PaintPhaseToDrawingType(local_paint_info.phase));
}
}
}
- } else if (!completely_clipped_out &&
- layout_replaced_.Style()->HasBorderRadius() &&
- ShouldApplyViewportClip(layout_replaced_)) {
- // Push a clip if we have a border radius, since we want to round the
- // foreground content that gets painted.
- FloatRoundedRect rounded_inner_rect =
- layout_replaced_.Style()->GetRoundedInnerBorderFor(
- border_rect,
- LayoutRectOutsets(-(layout_replaced_.PaddingTop() +
- layout_replaced_.BorderTop()),
- -(layout_replaced_.PaddingRight() +
- layout_replaced_.BorderRight()),
- -(layout_replaced_.PaddingBottom() +
- layout_replaced_.BorderBottom()),
- -(layout_replaced_.PaddingLeft() +
- layout_replaced_.BorderLeft())),
- true, true);
-
- clipper.emplace(layout_replaced_, local_paint_info, border_rect,
- rounded_inner_rect, kApplyToDisplayList);
}
- if (!completely_clipped_out) {
- if (local_paint_info.phase == PaintPhase::kClippingMask) {
- BoxPainter(layout_replaced_)
- .PaintClippingMask(local_paint_info, adjusted_paint_offset);
- } else {
- layout_replaced_.PaintReplaced(local_paint_info, adjusted_paint_offset);
- }
- }
+ if (!completely_clipped_out)
+ layout_replaced_.PaintReplaced(local_paint_info, paint_offset);
}
// The selection tint never gets clipped by border-radius rounding, since we
@@ -158,7 +114,7 @@ void ReplacedPainter::Paint(const PaintInfo& paint_info,
local_paint_info.context, layout_replaced_,
DisplayItem::kSelectionTint)) {
LayoutRect selection_painting_rect = layout_replaced_.LocalSelectionRect();
- selection_painting_rect.MoveBy(adjusted_paint_offset);
+ selection_painting_rect.MoveBy(paint_offset);
IntRect selection_painting_int_rect =
PixelSnappedIntRect(selection_painting_rect);
@@ -172,14 +128,12 @@ void ReplacedPainter::Paint(const PaintInfo& paint_info,
}
}
-bool ReplacedPainter::ShouldPaint(
- const PaintInfo& paint_info,
- const LayoutPoint& adjusted_paint_offset) const {
+bool ReplacedPainter::ShouldPaint(const PaintInfo& paint_info,
+ const LayoutPoint& paint_offset) const {
if (paint_info.phase != PaintPhase::kForeground &&
!ShouldPaintSelfOutline(paint_info.phase) &&
paint_info.phase != PaintPhase::kSelection &&
paint_info.phase != PaintPhase::kMask &&
- paint_info.phase != PaintPhase::kClippingMask &&
!ShouldPaintSelfBlockBackground(paint_info.phase))
return false;
@@ -195,7 +149,7 @@ bool ReplacedPainter::ShouldPaint(
LayoutRect paint_rect(layout_replaced_.VisualOverflowRect());
paint_rect.Unite(layout_replaced_.LocalSelectionRect());
- paint_rect.MoveBy(adjusted_paint_offset);
+ paint_rect.MoveBy(paint_offset);
if (!paint_info.GetCullRect().IntersectsCullRect(paint_rect))
return false;
diff --git a/chromium/third_party/blink/renderer/core/paint/replaced_painter.h b/chromium/third_party/blink/renderer/core/paint/replaced_painter.h
index 1f717ecb125..6cbc1381215 100644
--- a/chromium/third_party/blink/renderer/core/paint/replaced_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/replaced_painter.h
@@ -20,12 +20,9 @@ class ReplacedPainter {
ReplacedPainter(const LayoutReplaced& layout_replaced)
: layout_replaced_(layout_replaced) {}
- void Paint(const PaintInfo&, const LayoutPoint&);
+ void Paint(const PaintInfo&);
- // The adjustedPaintOffset should include the location (offset) of the object
- // itself.
- bool ShouldPaint(const PaintInfo&,
- const LayoutPoint& adjusted_paint_offset) const;
+ bool ShouldPaint(const PaintInfo&, const LayoutPoint& paint_offset) const;
private:
const LayoutReplaced& layout_replaced_;
diff --git a/chromium/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.cc b/chromium/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.cc
index 9ea756703ae..a4d21f2ea11 100644
--- a/chromium/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.cc
+++ b/chromium/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.cc
@@ -4,29 +4,17 @@
#include "third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.h"
-#include "third_party/blink/renderer/core/paint/paint_info.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item_client.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
+#include "third_party/blink/renderer/platform/geometry/float_rounded_rect.h"
+#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
namespace blink {
RoundedInnerRectClipper::RoundedInnerRectClipper(
- const DisplayItemClient& display_item,
- const PaintInfo& paint_info,
+ GraphicsContext& context,
const LayoutRect& rect,
- const FloatRoundedRect& clip_rect,
- RoundedInnerRectClipperBehavior behavior)
- : display_item_(display_item),
- paint_info_(paint_info),
- use_paint_controller_(behavior == kApplyToDisplayList),
- clip_type_(use_paint_controller_
- ? paint_info_.DisplayItemTypeForClipping()
- : DisplayItem::kClipBoxPaintPhaseFirst) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- use_paint_controller_)
- return;
-
+ const FloatRoundedRect& clip_rect)
+ : context_(context) {
Vector<FloatRoundedRect> rounded_rect_clips;
if (clip_rect.IsRenderable()) {
rounded_rect_clips.push_back(clip_rect);
@@ -72,29 +60,13 @@ RoundedInnerRectClipper::RoundedInnerRectClipper(
}
}
- if (use_paint_controller_) {
- paint_info_.context.GetPaintController().CreateAndAppend<ClipDisplayItem>(
- display_item, clip_type_, LayoutRect::InfiniteIntRect(),
- rounded_rect_clips);
- } else {
- paint_info.context.Save();
- for (const auto& rrect : rounded_rect_clips)
- paint_info.context.ClipRoundedRect(rrect);
- }
+ context.Save();
+ for (const auto& rrect : rounded_rect_clips)
+ context.ClipRoundedRect(rrect);
}
RoundedInnerRectClipper::~RoundedInnerRectClipper() {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- use_paint_controller_)
- return;
-
- DisplayItem::Type end_type = DisplayItem::ClipTypeToEndClipType(clip_type_);
- if (use_paint_controller_) {
- paint_info_.context.GetPaintController().EndItem<EndClipDisplayItem>(
- display_item_, end_type);
- } else {
- paint_info_.context.Restore();
- }
+ context_.Restore();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.h b/chromium/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.h
index 25fd36bbe06..6022058c97c 100644
--- a/chromium/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.h
+++ b/chromium/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.h
@@ -5,34 +5,25 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_ROUNDED_INNER_RECT_CLIPPER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_ROUNDED_INNER_RECT_CLIPPER_H_
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
namespace blink {
class FloatRoundedRect;
+class GraphicsContext;
class LayoutRect;
-class DisplayItemClient;
-struct PaintInfo;
-
-enum RoundedInnerRectClipperBehavior { kApplyToDisplayList, kApplyToContext };
class RoundedInnerRectClipper {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
public:
- RoundedInnerRectClipper(const DisplayItemClient&,
- const PaintInfo&,
+ RoundedInnerRectClipper(GraphicsContext&,
const LayoutRect&,
- const FloatRoundedRect& clip_rect,
- RoundedInnerRectClipperBehavior);
+ const FloatRoundedRect& clip_rect);
~RoundedInnerRectClipper();
private:
- const DisplayItemClient& display_item_;
- const PaintInfo& paint_info_;
- bool use_paint_controller_;
- DisplayItem::Type clip_type_;
+ GraphicsContext& context_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/scroll_recorder.cc b/chromium/third_party/blink/renderer/core/paint/scroll_recorder.cc
deleted file mode 100644
index b0890f1ba93..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/scroll_recorder.cc
+++ /dev/null
@@ -1,40 +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/scroll_recorder.h"
-
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-#include "third_party/blink/renderer/platform/graphics/paint/scroll_display_item.h"
-
-namespace blink {
-
-ScrollRecorder::ScrollRecorder(GraphicsContext& context,
- const DisplayItemClient& client,
- DisplayItem::Type type,
- const IntSize& current_offset)
- : client_(client), begin_item_type_(type), context_(context) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
- context_.GetPaintController().CreateAndAppend<BeginScrollDisplayItem>(
- client_, begin_item_type_, current_offset);
-}
-
-ScrollRecorder::ScrollRecorder(GraphicsContext& context,
- const DisplayItemClient& client,
- PaintPhase phase,
- const IntSize& current_offset)
- : ScrollRecorder(context,
- client,
- DisplayItem::PaintPhaseToScrollType(phase),
- current_offset) {}
-
-ScrollRecorder::~ScrollRecorder() {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
- context_.GetPaintController().EndItem<EndScrollDisplayItem>(
- client_, DisplayItem::ScrollTypeToEndScrollType(begin_item_type_));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/scroll_recorder.h b/chromium/third_party/blink/renderer/core/paint/scroll_recorder.h
deleted file mode 100644
index 81273393d89..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/scroll_recorder.h
+++ /dev/null
@@ -1,42 +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_SCROLL_RECORDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCROLL_RECORDER_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/paint/paint_phase.h"
-#include "third_party/blink/renderer/platform/geometry/int_size.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class GraphicsContext;
-
-// Emits display items which represent a region which is scrollable, so that it
-// can be translated by the scroll offset.
-class CORE_EXPORT ScrollRecorder {
- USING_FAST_MALLOC(ScrollRecorder);
-
- public:
- ScrollRecorder(GraphicsContext&,
- const DisplayItemClient&,
- DisplayItem::Type,
- const IntSize& current_offset);
- ScrollRecorder(GraphicsContext&,
- const DisplayItemClient&,
- PaintPhase,
- const IntSize& current_offset);
- ~ScrollRecorder();
-
- private:
- const DisplayItemClient& client_;
- DisplayItem::Type begin_item_type_;
- GraphicsContext& context_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCROLL_RECORDER_H_
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 d7071a6c83d..e466c1d7666 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
@@ -11,11 +11,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/paint/scrollbar_painter.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
#include "third_party/blink/renderer/platform/platform_chrome_client.h"
@@ -173,46 +171,31 @@ void ScrollableAreaPainter::PaintOverflowControls(
return;
GraphicsContext& context = paint_info.context;
+ const auto& box = *GetScrollableArea().GetLayoutBox();
+ const auto* fragment = paint_info.FragmentToPaint(box);
+ if (!fragment)
+ return;
- base::Optional<ClipRecorder> clip_recorder;
base::Optional<ScopedPaintChunkProperties> scoped_paint_chunk_properties;
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- const auto& box = *GetScrollableArea().GetLayoutBox();
- if (const auto* fragment = paint_info.FragmentToPaint(box)) {
- const auto* properties = fragment->PaintProperties();
- // TODO(crbug.com/849278): Remove either the DCHECK or the if condition
- // when we figure out in what cases that the box doesn't have properties.
- DCHECK(properties);
- if (properties) {
- if (const auto* clip = properties->OverflowControlsClip()) {
- scoped_paint_chunk_properties.emplace(
- context.GetPaintController(), clip, box,
- DisplayItem::kClipLayerOverflowControls);
- }
- }
+ const auto* properties = fragment->PaintProperties();
+ // TODO(crbug.com/849278): Remove either the DCHECK or the if condition
+ // when we figure out in what cases that the box doesn't have properties.
+ DCHECK(properties);
+ if (properties) {
+ if (const auto* clip = properties->OverflowControlsClip()) {
+ scoped_paint_chunk_properties.emplace(context.GetPaintController(), clip,
+ box,
+ DisplayItem::kOverflowControls);
}
- } else {
- IntRect clip_rect(adjusted_paint_offset,
- GetScrollableArea().Layer()->PixelSnappedSize());
- clip_recorder.emplace(context, *GetScrollableArea().GetLayoutBox(),
- DisplayItem::kClipLayerOverflowControls, clip_rect);
}
if (GetScrollableArea().HorizontalScrollbar() &&
!GetScrollableArea().LayerForHorizontalScrollbar()) {
- TransformRecorder translate_recorder(
- context, *GetScrollableArea().HorizontalScrollbar(),
- AffineTransform::Translation(adjusted_paint_offset.X(),
- adjusted_paint_offset.Y()));
GetScrollableArea().HorizontalScrollbar()->Paint(context,
adjusted_cull_rect);
}
if (GetScrollableArea().VerticalScrollbar() &&
!GetScrollableArea().LayerForVerticalScrollbar()) {
- TransformRecorder translate_recorder(
- context, *GetScrollableArea().VerticalScrollbar(),
- AffineTransform::Translation(adjusted_paint_offset.X(),
- adjusted_paint_offset.Y()));
GetScrollableArea().VerticalScrollbar()->Paint(context, adjusted_cull_rect);
}
if (!GetScrollableArea().LayerForScrollCorner()) {
diff --git a/chromium/third_party/blink/renderer/core/paint/scrollbar_manager.cc b/chromium/third_party/blink/renderer/core/paint/scrollbar_manager.cc
deleted file mode 100644
index 0dc78ec411a..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/scrollbar_manager.cc
+++ /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.
-
-#include "third_party/blink/renderer/core/paint/scrollbar_manager.h"
-
-namespace blink {
-
-ScrollbarManager::ScrollbarManager(ScrollableArea& scrollable_area)
- : scrollable_area_(&scrollable_area),
- h_bar_is_attached_(0),
- v_bar_is_attached_(0) {}
-
-void ScrollbarManager::Trace(blink::Visitor* visitor) {
- visitor->Trace(scrollable_area_);
- visitor->Trace(h_bar_);
- visitor->Trace(v_bar_);
-}
-
-void ScrollbarManager::Dispose() {
- h_bar_is_attached_ = v_bar_is_attached_ = 0;
- DestroyScrollbar(kHorizontalScrollbar);
- DestroyScrollbar(kVerticalScrollbar);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/scrollbar_manager.h b/chromium/third_party/blink/renderer/core/paint/scrollbar_manager.h
deleted file mode 100644
index fdf90a63f8c..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/scrollbar_manager.h
+++ /dev/null
@@ -1,56 +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_PAINT_SCROLLBAR_MANAGER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCROLLBAR_MANAGER_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/scroll/scrollable_area.h"
-
-namespace blink {
-
-class CORE_EXPORT ScrollbarManager {
- DISALLOW_NEW();
-
- // Helper class to manage the life cycle of Scrollbar objects.
- public:
- ScrollbarManager(ScrollableArea&);
-
- void Dispose();
-
- Scrollbar* HorizontalScrollbar() const {
- return h_bar_is_attached_ ? h_bar_.Get() : nullptr;
- }
- Scrollbar* VerticalScrollbar() const {
- return v_bar_is_attached_ ? v_bar_.Get() : nullptr;
- }
- bool HasHorizontalScrollbar() const { return HorizontalScrollbar(); }
- bool HasVerticalScrollbar() const { return VerticalScrollbar(); }
-
- // These functions are used to create/destroy scrollbars.
- virtual void SetHasHorizontalScrollbar(bool has_scrollbar) = 0;
- virtual void SetHasVerticalScrollbar(bool has_scrollbar) = 0;
-
- virtual void Trace(blink::Visitor*);
-
- protected:
- // TODO(ymalik): This can be made non-virtual since there's a lot of
- // common code in subclasses.
- virtual Scrollbar* CreateScrollbar(ScrollbarOrientation) = 0;
- virtual void DestroyScrollbar(ScrollbarOrientation) = 0;
-
- protected:
- Member<ScrollableArea> scrollable_area_;
-
- // The scrollbars associated with m_scrollableArea. Both can nullptr.
- Member<Scrollbar> h_bar_;
- Member<Scrollbar> v_bar_;
-
- unsigned h_bar_is_attached_ : 1;
- unsigned v_bar_is_attached_ : 1;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCROLLBAR_MANAGER_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/scrollbar_painter.cc b/chromium/third_party/blink/renderer/core/paint/scrollbar_painter.cc
index 49cf80a4427..62cc0af434f 100644
--- a/chromium/third_party/blink/renderer/core/paint/scrollbar_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/scrollbar_painter.cc
@@ -20,28 +20,34 @@ void ScrollbarPainter::PaintPart(GraphicsContext& graphics_context,
if (!part_layout_object)
return;
PaintIntoRect(*part_layout_object, graphics_context,
- layout_scrollbar_->Location(), LayoutRect(rect));
+ layout_scrollbar_->Location(), LayoutRect(rect),
+ layout_scrollbar_.Get());
}
void ScrollbarPainter::PaintIntoRect(
const LayoutScrollbarPart& layout_scrollbar_part,
GraphicsContext& graphics_context,
const LayoutPoint& paint_offset,
- const LayoutRect& rect) {
+ const LayoutRect& rect,
+ const LayoutScrollbar* scrollbar) {
// Make sure our dimensions match the rect.
- // FIXME: Setting these is a bad layering violation!
+ // TODO(crbug.com/856802): Setting these is a bad layering violation!
+ // Move these into layout stage.
const_cast<LayoutScrollbarPart&>(layout_scrollbar_part)
.SetLocation(rect.Location() - ToSize(paint_offset));
const_cast<LayoutScrollbarPart&>(layout_scrollbar_part)
.SetWidth(rect.Width());
const_cast<LayoutScrollbarPart&>(layout_scrollbar_part)
.SetHeight(rect.Height());
+ // TODO(crbug.com/856802): Move this into PaintPropertyTreeBuilder.
+ layout_scrollbar_part.GetMutableForPainting().FirstFragment().SetPaintOffset(
+ (scrollbar ? scrollbar->Location() : LayoutPoint()) +
+ layout_scrollbar_part.PhysicalLocation());
PaintInfo paint_info(graphics_context, PixelSnappedIntRect(rect),
PaintPhase::kForeground, kGlobalPaintNormalPhase,
kPaintLayerNoFlag);
- ObjectPainter(layout_scrollbar_part)
- .PaintAllPhasesAtomically(paint_info, paint_offset);
+ ObjectPainter(layout_scrollbar_part).PaintAllPhasesAtomically(paint_info);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/scrollbar_painter.h b/chromium/third_party/blink/renderer/core/paint/scrollbar_painter.h
index 4e6f1757880..e73f507251f 100644
--- a/chromium/third_party/blink/renderer/core/paint/scrollbar_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/scrollbar_painter.h
@@ -29,7 +29,8 @@ class ScrollbarPainter {
static void PaintIntoRect(const LayoutScrollbarPart&,
GraphicsContext&,
const LayoutPoint& paint_offset,
- const LayoutRect&);
+ const LayoutRect&,
+ const LayoutScrollbar* = nullptr);
private:
Member<const LayoutScrollbar> layout_scrollbar_;
diff --git a/chromium/third_party/blink/renderer/core/paint/selection_painting_utils.cc b/chromium/third_party/blink/renderer/core/paint/selection_painting_utils.cc
index 1c70e26c3a0..5426d6fb347 100644
--- a/chromium/third_party/blink/renderer/core/paint/selection_painting_utils.cc
+++ b/chromium/third_party/blink/renderer/core/paint/selection_painting_utils.cc
@@ -38,7 +38,7 @@ scoped_refptr<ComputedStyle> GetUncachedSelectionStyle(Node* node) {
if (ShadowRoot* root = node->ContainingShadowRoot()) {
if (root->IsUserAgent()) {
if (Element* shadow_host = node->OwnerShadowHost()) {
- return shadow_host->GetUncachedPseudoStyle(
+ return shadow_host->StyleForPseudoElement(
PseudoStyleRequest(kPseudoIdSelection));
}
}
@@ -51,8 +51,7 @@ scoped_refptr<ComputedStyle> GetUncachedSelectionStyle(Node* node) {
if (!element || element->IsPseudoElement())
return nullptr;
- return element->GetUncachedPseudoStyle(
- PseudoStyleRequest(kPseudoIdSelection));
+ return element->StyleForPseudoElement(PseudoStyleRequest(kPseudoIdSelection));
}
Color SelectionColor(const Document& document,
@@ -80,8 +79,10 @@ const ComputedStyle* SelectionPseudoStyle(Node* node) {
if (!node)
return nullptr;
Element* element = Traversal<Element>::FirstAncestorOrSelf(*node);
- return element ? element->PseudoStyle(PseudoStyleRequest(kPseudoIdSelection))
- : nullptr;
+ if (!element)
+ return nullptr;
+ return element->CachedStyleForPseudoElement(
+ PseudoStyleRequest(kPseudoIdSelection));
}
} // anonymous namespace
diff --git a/chromium/third_party/blink/renderer/core/paint/stub_chrome_client_for_spv2.h b/chromium/third_party/blink/renderer/core/paint/stub_chrome_client_for_spv2.h
index e47a32daac2..f16792d620f 100644
--- a/chromium/third_party/blink/renderer/core/paint/stub_chrome_client_for_spv2.h
+++ b/chromium/third_party/blink/renderer/core/paint/stub_chrome_client_for_spv2.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_STUB_CHROME_CLIENT_FOR_SPV2_H_
#include "third_party/blink/renderer/core/loader/empty_clients.h"
-#include "third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.h"
+#include "third_party/blink/renderer/platform/testing/layer_tree_host_embedder.h"
namespace cc {
class Layer;
@@ -15,23 +15,21 @@ class Layer;
namespace blink {
// A simple ChromeClient implementation which forwards painted artifacts to a
-// PaintArtifactCompositor attached to a testing WebLayerTreeView, and permits
+// PaintArtifactCompositor attached to a testing cc::LayerTreeHost, and permits
// simple analysis of the results.
class StubChromeClientForSPv2 : public EmptyChromeClient {
public:
- StubChromeClientForSPv2() : layer_tree_view_() {}
-
bool HasLayer(const cc::Layer& layer) {
- return layer_tree_view_.HasLayer(layer);
+ return layer.layer_tree_host() == layer_tree_.layer_tree_host();
}
void AttachRootLayer(scoped_refptr<cc::Layer> layer,
LocalFrame* local_root) override {
- layer_tree_view_.SetRootLayer(std::move(layer));
+ layer_tree_.layer_tree_host()->SetRootLayer(std::move(layer));
}
private:
- WebLayerTreeViewImplForTesting layer_tree_view_;
+ LayerTreeHostEmbedder layer_tree_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_container_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_container_painter.cc
index ede56819beb..58e7b810648 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_container_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_container_painter.cc
@@ -10,10 +10,10 @@
#include "third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h"
#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
-#include "third_party/blink/renderer/core/paint/float_clip_recorder.h"
#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/svg_foreign_object_painter.h"
+#include "third_party/blink/renderer/core/paint/svg_model_object_painter.h"
#include "third_party/blink/renderer/core/paint/svg_paint_context.h"
#include "third_party/blink/renderer/core/svg/svg_svg_element.h"
@@ -25,15 +25,6 @@ void SVGContainerPainter::Paint(const PaintInfo& paint_info) {
!layout_svg_container_.SelfWillPaint())
return;
- FloatRect bounding_box =
- layout_svg_container_.VisualRectInLocalSVGCoordinates();
- // LayoutSVGHiddenContainer's visual rect is always empty but we need to
- // paint its descendants.
- if (!layout_svg_container_.IsSVGHiddenContainer() &&
- !paint_info.GetCullRect().IntersectsCullRect(
- layout_svg_container_.LocalToSVGParentTransform(), bounding_box))
- return;
-
// Spec: An empty viewBox on the <svg> element disables rendering.
DCHECK(layout_svg_container_.GetElement());
if (IsSVGSVGElement(*layout_svg_container_.GetElement()) &&
@@ -41,17 +32,31 @@ void SVGContainerPainter::Paint(const PaintInfo& paint_info) {
return;
PaintInfo paint_info_before_filtering(paint_info);
- paint_info_before_filtering.UpdateCullRect(
- layout_svg_container_.LocalToSVGParentTransform());
+
+ if (SVGModelObjectPainter(layout_svg_container_)
+ .CullRectSkipsPainting(paint_info_before_filtering)) {
+ return;
+ }
+
+ // We do not apply cull rect optimizations across transforms for two reasons:
+ // 1) Performance: We can optimize transform changes by not repainting.
+ // 2) Complexity: Difficulty updating clips when ancestor transforms change.
+ // This is why we use an infinite cull rect if there is a transform. Non-svg
+ // content, does this in PaintLayerPainter::PaintSingleFragment.
+ if (layout_svg_container_.StyleRef().HasTransform()) {
+ paint_info_before_filtering.ApplyInfiniteCullRect();
+ } else {
+ paint_info_before_filtering.UpdateCullRect(
+ layout_svg_container_.LocalToSVGParentTransform());
+ }
+
SVGTransformContext transform_context(
paint_info_before_filtering, layout_svg_container_,
layout_svg_container_.LocalToSVGParentTransform());
{
- base::Optional<FloatClipRecorder> clip_recorder;
base::Optional<ScopedPaintChunkProperties> scoped_paint_chunk_properties;
if (layout_svg_container_.IsSVGViewportContainer() &&
SVGLayoutSupport::IsOverflowHidden(layout_svg_container_)) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
const auto* fragment =
paint_info.FragmentToPaint(layout_svg_container_);
if (!fragment)
@@ -66,14 +71,6 @@ void SVGContainerPainter::Paint(const PaintInfo& paint_info) {
properties->OverflowClip(), layout_svg_container_,
paint_info.DisplayItemTypeForClipping());
}
- } else {
- FloatRect viewport =
- layout_svg_container_.LocalToSVGParentTransform().Inverse().MapRect(
- ToLayoutSVGViewportContainer(layout_svg_container_).Viewport());
- clip_recorder.emplace(paint_info_before_filtering.context,
- layout_svg_container_,
- paint_info_before_filtering.phase, viewport);
- }
}
SVGPaintContext paint_context(layout_svg_container_,
@@ -85,31 +82,24 @@ void SVGContainerPainter::Paint(const PaintInfo& paint_info) {
if (continue_rendering) {
for (LayoutObject* child = layout_svg_container_.FirstChild(); child;
child = child->NextSibling()) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- child->IsSVGForeignObject()) {
+ if (child->IsSVGForeignObject()) {
SVGForeignObjectPainter(ToLayoutSVGForeignObject(*child))
.PaintLayer(paint_context.GetPaintInfo());
} else {
- child->Paint(paint_context.GetPaintInfo(), IntPoint());
+ child->Paint(paint_context.GetPaintInfo());
}
}
}
}
- if (paint_info_before_filtering.phase != PaintPhase::kForeground)
- return;
+ SVGModelObjectPainter(layout_svg_container_)
+ .PaintOutline(paint_info_before_filtering);
- if (layout_svg_container_.Style()->OutlineWidth() &&
- layout_svg_container_.Style()->Visibility() == EVisibility::kVisible) {
- PaintInfo outline_paint_info(paint_info_before_filtering);
- outline_paint_info.phase = PaintPhase::kSelfOutlineOnly;
- ObjectPainter(layout_svg_container_)
- .PaintOutline(outline_paint_info, LayoutPoint(bounding_box.Location()));
- }
-
- if (paint_info_before_filtering.IsPrinting())
+ if (paint_info_before_filtering.IsPrinting() &&
+ paint_info_before_filtering.phase == PaintPhase::kForeground) {
ObjectPainter(layout_svg_container_)
.AddPDFURLRectIfNeeded(paint_info_before_filtering, LayoutPoint());
+ }
}
} // namespace blink
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
index f35b674b3ed..738109459c7 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_filter_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_filter_painter.cc
@@ -23,13 +23,12 @@ GraphicsContext* SVGFilterRecordingContext::BeginContent() {
paint_controller_ = PaintController::Create();
context_ = std::make_unique<GraphicsContext>(*paint_controller_);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- // Use initial_context_'s current paint chunk properties so that any new
- // chunk created during painting the content will be in the correct state.
- paint_controller_->UpdateCurrentPaintChunkProperties(
- base::nullopt,
- initial_context_.GetPaintController().CurrentPaintChunkProperties());
- }
+ // Use initial_context_'s current paint chunk properties so that any new
+ // chunk created during painting the content will be in the correct state.
+ paint_controller_->UpdateCurrentPaintChunkProperties(
+ base::nullopt,
+ initial_context_.GetPaintController().CurrentPaintChunkProperties());
+
return context_.get();
}
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc
index d2734756906..6cdc7fc8705 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc
@@ -8,36 +8,16 @@
#include "third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h"
#include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
#include "third_party/blink/renderer/core/paint/block_painter.h"
-#include "third_party/blink/renderer/core/paint/float_clip_recorder.h"
#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_layer.h"
#include "third_party/blink/renderer/core/paint/paint_layer_painter.h"
#include "third_party/blink/renderer/core/paint/svg_paint_context.h"
+#include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h"
namespace blink {
-namespace {
-
-class BlockPainterDelegate : public LayoutBlock {
- public:
- BlockPainterDelegate(const LayoutSVGForeignObject& layout_svg_foreign_object)
- : LayoutBlock(nullptr),
- layout_svg_foreign_object_(layout_svg_foreign_object) {}
-
- private:
- void Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) const final {
- BlockPainter(layout_svg_foreign_object_).Paint(paint_info, paint_offset);
- }
- const LayoutSVGForeignObject& layout_svg_foreign_object_;
-};
-
-} // namespace
-
void SVGForeignObjectPainter::PaintLayer(const PaintInfo& paint_info) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
if (paint_info.phase != PaintPhase::kForeground &&
paint_info.phase != PaintPhase::kSelection)
return;
@@ -47,6 +27,14 @@ void SVGForeignObjectPainter::PaintLayer(const PaintInfo& paint_info) {
if (!layout_svg_foreign_object_.FirstFragment().HasLocalBorderBoxProperties())
return;
+ // TODO(crbug.com/797779): For now foreign object contents don't know whether
+ // they are painted in a fragmented context and may do something bad in a
+ // fragmented context, e.g. creating subsequences. Skip cache to avoid that.
+ // This will be unnecessary when the contents are fragment aware.
+ base::Optional<DisplayItemCacheSkipper> cache_skipper;
+ if (layout_svg_foreign_object_.Layer()->Parent()->EnclosingPaginationLayer())
+ cache_skipper.emplace(paint_info.context);
+
// <foreignObject> is a replaced normal-flow stacking element.
// See IsReplacedNormalFlowStacking in paint_layer_painter.cc.
PaintLayerPaintingInfo layer_painting_info(
@@ -64,54 +52,14 @@ void SVGForeignObjectPainter::PaintLayer(const PaintInfo& paint_info) {
}
void SVGForeignObjectPainter::Paint(const PaintInfo& paint_info) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- if (paint_info.phase != PaintPhase::kForeground &&
- paint_info.phase != PaintPhase::kSelection)
- return;
- }
-
PaintInfo paint_info_before_filtering(paint_info);
- base::Optional<SVGTransformContext> transform_context;
-
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- paint_info_before_filtering.UpdateCullRect(
- layout_svg_foreign_object_.LocalSVGTransform());
- transform_context.emplace(paint_info_before_filtering,
- layout_svg_foreign_object_,
- layout_svg_foreign_object_.LocalSVGTransform());
-
- // In theory we should just let BlockPainter::paint() handle the clip, but
- // for now we don't allow normal overflow clip for LayoutSVGBlock, so we
- // have to apply clip manually. See LayoutSVGBlock::allowsOverflowClip() for
- // details.
- base::Optional<FloatClipRecorder> clip_recorder;
- base::Optional<ScopedPaintChunkProperties> scoped_paint_chunk_properties;
- if (SVGLayoutSupport::IsOverflowHidden(layout_svg_foreign_object_)) {
- clip_recorder.emplace(paint_info_before_filtering.context,
- layout_svg_foreign_object_,
- paint_info_before_filtering.phase,
- FloatRect(layout_svg_foreign_object_.FrameRect()));
- }
- }
-
SVGPaintContext paint_context(layout_svg_foreign_object_,
paint_info_before_filtering);
if (paint_context.GetPaintInfo().phase == PaintPhase::kForeground &&
!paint_context.ApplyClipMaskAndFilterIfNecessary())
return;
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- BlockPainter(layout_svg_foreign_object_).Paint(paint_info, LayoutPoint());
- } else {
- // Paint all phases of FO elements atomically as though the FO element
- // established its own stacking context. The delegate forwards calls to
- // paint() in LayoutObject::paintAllPhasesAtomically() to
- // BlockPainter::paint(), instead of m_layoutSVGForeignObject.paint() (which
- // would call this method again).
- BlockPainterDelegate delegate(layout_svg_foreign_object_);
- ObjectPainter(delegate).PaintAllPhasesAtomically(
- paint_context.GetPaintInfo(), LayoutPoint());
- }
+ BlockPainter(layout_svg_foreign_object_).Paint(paint_info);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_image_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_image_painter.cc
index ddac9665bdc..93d3611f8ac 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_image_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_image_painter.cc
@@ -4,20 +4,15 @@
#include "third_party/blink/renderer/core/paint/svg_image_painter.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_image_resource.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_image.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/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
+#include "third_party/blink/renderer/core/paint/svg_model_object_painter.h"
#include "third_party/blink/renderer/core/paint/svg_paint_context.h"
#include "third_party/blink/renderer/core/svg/graphics/svg_image.h"
#include "third_party/blink/renderer/core/svg/svg_image_element.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_record.h"
#include "third_party/blink/renderer/platform/graphics/scoped_interpolation_quality.h"
namespace blink {
@@ -28,13 +23,14 @@ void SVGImagePainter::Paint(const PaintInfo& paint_info) {
!layout_svg_image_.ImageResource()->HasImage())
return;
- FloatRect bounding_box = layout_svg_image_.VisualRectInLocalSVGCoordinates();
- if (!paint_info.GetCullRect().IntersectsCullRect(
- layout_svg_image_.LocalToSVGParentTransform(), bounding_box))
+ PaintInfo paint_info_before_filtering(paint_info);
+
+ if (SVGModelObjectPainter(layout_svg_image_)
+ .CullRectSkipsPainting(paint_info_before_filtering)) {
return;
+ }
+ // Images cannot have children so do not call UpdateCullRect.
- PaintInfo paint_info_before_filtering(paint_info);
- // Images cannot have children so do not call updateCullRect.
SVGTransformContext transform_context(
paint_info_before_filtering, layout_svg_image_,
layout_svg_image_.LocalToSVGParentTransform());
@@ -52,17 +48,17 @@ void SVGImagePainter::Paint(const PaintInfo& paint_info) {
}
}
- if (layout_svg_image_.Style()->OutlineWidth()) {
- PaintInfo outline_paint_info(paint_info_before_filtering);
- outline_paint_info.phase = PaintPhase::kSelfOutlineOnly;
- ObjectPainter(layout_svg_image_)
- .PaintOutline(outline_paint_info, LayoutPoint(bounding_box.Location()));
- }
+ SVGModelObjectPainter(layout_svg_image_)
+ .PaintOutline(paint_info_before_filtering);
}
void SVGImagePainter::PaintForeground(const PaintInfo& paint_info) {
const LayoutImageResource* image_resource = layout_svg_image_.ImageResource();
- IntSize image_viewport_size = ExpandedIntSize(ComputeImageViewportSize());
+ // TODO(fs): Reduce the number of conversions.
+ // (FloatSize -> IntSize -> LayoutSize currently.)
+ FloatSize float_image_viewport_size = ComputeImageViewportSize();
+ float_image_viewport_size.Scale(layout_svg_image_.StyleRef().EffectiveZoom());
+ IntSize image_viewport_size = ExpandedIntSize(float_image_viewport_size);
if (image_viewport_size.IsEmpty())
return;
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_inline_flow_box_painter.h b/chromium/third_party/blink/renderer/core/paint/svg_inline_flow_box_painter.h
index fed617ddf95..53adfa63184 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_inline_flow_box_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/svg_inline_flow_box_painter.h
@@ -21,7 +21,7 @@ class SVGInlineFlowBoxPainter {
: svg_inline_flow_box_(svg_inline_flow_box) {}
void PaintSelectionBackground(const PaintInfo&);
- void Paint(const PaintInfo&, const LayoutPoint&);
+ void Paint(const PaintInfo&, const LayoutPoint& paint_offset);
private:
const SVGInlineFlowBox& svg_inline_flow_box_;
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.h b/chromium/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.h
index bca6b009c8c..2fd216fce31 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/svg_inline_text_box_painter.h
@@ -41,7 +41,7 @@ class SVGInlineTextBoxPainter {
public:
SVGInlineTextBoxPainter(const SVGInlineTextBox& svg_inline_text_box)
: svg_inline_text_box_(svg_inline_text_box) {}
- void Paint(const PaintInfo&, const LayoutPoint&);
+ void Paint(const PaintInfo&, const LayoutPoint& paint_offset);
void PaintSelectionBackground(const PaintInfo&);
void PaintTextMatchMarkerForeground(const PaintInfo&,
const LayoutPoint&,
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_mask_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_mask_painter.cc
index 0d369f86e32..9e2863a4bd9 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_mask_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_mask_painter.cc
@@ -7,8 +7,6 @@
#include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.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/platform/graphics/paint/compositing_display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/compositing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
@@ -27,10 +25,6 @@ bool SVGMaskPainter::PrepareEffect(const LayoutObject& object,
if (visual_rect.IsEmpty() || !mask_.GetElement()->HasChildren())
return false;
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- context.GetPaintController().CreateAndAppend<BeginCompositingDisplayItem>(
- object, SkBlendMode::kSrcOver, 1, &visual_rect);
- }
return true;
}
@@ -39,47 +33,26 @@ void SVGMaskPainter::FinishEffect(const LayoutObject& object,
DCHECK(mask_.Style());
SECURITY_DCHECK(!mask_.NeedsLayout());
- FloatRect visual_rect = object.VisualRectInLocalSVGCoordinates();
- {
- ColorFilter mask_layer_filter =
- mask_.Style()->SvgStyle().MaskType() == MT_LUMINANCE
- ? kColorFilterLuminanceToAlpha
- : kColorFilterNone;
- CompositingRecorder mask_compositing(context, object, SkBlendMode::kDstIn,
- 1, &visual_rect, mask_layer_filter);
- base::Optional<ScopedPaintChunkProperties> scoped_paint_chunk_properties;
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- const auto* properties = object.FirstFragment().PaintProperties();
- // TODO(crbug.com/814815): This condition should be a DCHECK, but for now
- // we may paint the object for filters during PrePaint before the
- // properties are ready.
- if (properties && properties->Mask()) {
- scoped_paint_chunk_properties.emplace(context.GetPaintController(),
- properties->Mask(), object,
- DisplayItem::kSVGMask);
- }
- }
-
- DrawMaskForLayoutObject(context, object, object.ObjectBoundingBox());
+ base::Optional<ScopedPaintChunkProperties> scoped_paint_chunk_properties;
+ const auto* properties = object.FirstFragment().PaintProperties();
+ // TODO(crbug.com/814815): This condition should be a DCHECK, but for now
+ // we may paint the object for filters during PrePaint before the
+ // properties are ready.
+ if (properties && properties->Mask()) {
+ scoped_paint_chunk_properties.emplace(context.GetPaintController(),
+ properties->Mask(), object,
+ DisplayItem::kSVGMask);
}
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- context.GetPaintController().EndItem<EndCompositingDisplayItem>(object);
-}
-
-void SVGMaskPainter::DrawMaskForLayoutObject(
- GraphicsContext& context,
- const LayoutObject& layout_object,
- const FloatRect& target_bounding_box) {
AffineTransform content_transformation;
sk_sp<const PaintRecord> record = mask_.CreatePaintRecord(
- content_transformation, target_bounding_box, context);
+ content_transformation, object.ObjectBoundingBox(), context);
- if (DrawingRecorder::UseCachedDrawingIfPossible(context, layout_object,
+ if (DrawingRecorder::UseCachedDrawingIfPossible(context, object,
DisplayItem::kSVGMask))
return;
- DrawingRecorder recorder(context, layout_object, DisplayItem::kSVGMask);
+ DrawingRecorder recorder(context, object, DisplayItem::kSVGMask);
context.Save();
context.ConcatCTM(content_transformation);
context.DrawRecord(std::move(record));
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_mask_painter.h b/chromium/third_party/blink/renderer/core/paint/svg_mask_painter.h
index ff1ac3fe270..3e854ad3e9b 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_mask_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/svg_mask_painter.h
@@ -24,10 +24,6 @@ class SVGMaskPainter {
void FinishEffect(const LayoutObject&, GraphicsContext&);
private:
- void DrawMaskForLayoutObject(GraphicsContext&,
- const LayoutObject&,
- const FloatRect& target_bounding_box);
-
LayoutSVGResourceMasker& mask_;
};
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_model_object_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_model_object_painter.cc
new file mode 100644
index 00000000000..956f01cec5d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/svg_model_object_painter.cc
@@ -0,0 +1,46 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/paint/svg_model_object_painter.h"
+
+#include "third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h"
+#include "third_party/blink/renderer/core/paint/object_painter.h"
+#include "third_party/blink/renderer/core/paint/paint_info.h"
+
+namespace blink {
+
+bool SVGModelObjectPainter::CullRectSkipsPainting(const PaintInfo& paint_info) {
+ // We do not apply cull rect optimizations across transforms for two reasons:
+ // 1) Performance: We can optimize transform changes by not repainting.
+ // 2) Complexity: Difficulty updating clips when ancestor transforms change.
+ // For these reasons, we do not cull painting if there is a transform.
+ if (layout_svg_model_object_.StyleRef().HasTransform())
+ return false;
+
+ // LayoutSVGHiddenContainer's visual rect is always empty but we need to
+ // paint its descendants so we cannot skip painting.
+ if (layout_svg_model_object_.IsSVGHiddenContainer())
+ return false;
+
+ return !paint_info.GetCullRect().IntersectsCullRect(
+ layout_svg_model_object_.LocalToSVGParentTransform(),
+ layout_svg_model_object_.VisualRectInLocalSVGCoordinates());
+}
+
+void SVGModelObjectPainter::PaintOutline(const PaintInfo& paint_info) {
+ if (paint_info.phase != PaintPhase::kForeground)
+ return;
+ if (layout_svg_model_object_.Style()->Visibility() != EVisibility::kVisible)
+ return;
+ if (!layout_svg_model_object_.Style()->OutlineWidth())
+ return;
+
+ PaintInfo outline_paint_info(paint_info);
+ outline_paint_info.phase = PaintPhase::kSelfOutlineOnly;
+ auto visual_rect = layout_svg_model_object_.VisualRectInLocalSVGCoordinates();
+ ObjectPainter(layout_svg_model_object_)
+ .PaintOutline(outline_paint_info, LayoutPoint(visual_rect.Location()));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_model_object_painter.h b/chromium/third_party/blink/renderer/core/paint/svg_model_object_painter.h
new file mode 100644
index 00000000000..6f3df6d6c43
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/svg_model_object_painter.h
@@ -0,0 +1,35 @@
+// 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_PAINT_SVG_MODEL_OBJECT_PAINTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SVG_MODEL_OBJECT_PAINTER_H_
+
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+
+namespace blink {
+
+struct PaintInfo;
+class LayoutSVGModelObject;
+
+class SVGModelObjectPainter {
+ STACK_ALLOCATED();
+
+ public:
+ SVGModelObjectPainter(const LayoutSVGModelObject& layout_svg_model_object)
+ : layout_svg_model_object_(layout_svg_model_object) {}
+
+ // If the object is outside the cull rect, painting can be skipped in most
+ // cases. An important exception is when there is a transform style: see the
+ // comment in the implementation.
+ bool CullRectSkipsPainting(const PaintInfo&);
+
+ void PaintOutline(const PaintInfo&);
+
+ private:
+ const LayoutSVGModelObject& layout_svg_model_object_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SVG_MODEL_OBJECT_PAINTER_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_paint_context.cc b/chromium/third_party/blink/renderer/core/paint/svg_paint_context.cc
index e2645a5f462..e0f2fd23885 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_paint_context.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_paint_context.cc
@@ -78,17 +78,11 @@ bool SVGPaintContext::ApplyClipMaskAndFilterIfNecessary() {
}
bool is_svg_root = object_.IsSVGRoot();
-
- // Layer takes care of root opacity and blend mode.
- if (is_svg_root) {
- DCHECK(!(object_.IsTransparent() || object_.StyleRef().HasBlendMode()) ||
- object_.HasLayer());
- } else {
- ApplyCompositingIfNecessary();
- }
-
if (is_svg_root) {
- DCHECK(!object_.StyleRef().ClipPath() || object_.HasLayer());
+ // Layer takes care of root opacity and blend mode.
+ DCHECK(object_.HasLayer() ||
+ !(object_.IsTransparent() || object_.StyleRef().HasBlendMode() ||
+ object_.StyleRef().ClipPath()));
} else {
ApplyClipIfNecessary();
}
@@ -100,24 +94,16 @@ bool SVGPaintContext::ApplyClipMaskAndFilterIfNecessary() {
return false;
if (is_svg_root) {
- DCHECK(!object_.StyleRef().HasFilter() || object_.HasLayer());
+ // Layer takes care of root filter.
+ DCHECK(object_.HasLayer() || !object_.StyleRef().HasFilter());
} else if (!ApplyFilterIfNecessary(resources)) {
return false;
}
- if (!IsIsolationInstalled() &&
- SVGLayoutSupport::IsIsolationRequired(&object_)) {
- compositing_recorder_ = std::make_unique<CompositingRecorder>(
- GetPaintInfo().context, object_, SkBlendMode::kSrcOver, 1);
- }
-
return true;
}
void SVGPaintContext::ApplyPaintPropertyState() {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
// SVGRoot works like normal CSS replaced element and its effects are
// applied as stacking context effect by PaintLayerPainter.
if (object_.IsSVGRoot())
@@ -144,24 +130,6 @@ void SVGPaintContext::ApplyPaintPropertyState() {
DisplayItem::PaintPhaseToSVGEffectType(GetPaintInfo().phase));
}
-void SVGPaintContext::ApplyCompositingIfNecessary() {
- DCHECK(!GetPaintInfo().IsRenderingClipPathAsMaskImage());
-
- const ComputedStyle& style = object_.StyleRef();
- float opacity = style.Opacity();
- BlendMode blend_mode = style.HasBlendMode() && object_.IsBlendingAllowed()
- ? style.GetBlendMode()
- : BlendMode::kNormal;
- if (opacity < 1 || blend_mode != BlendMode::kNormal) {
- const FloatRect compositing_bounds =
- object_.VisualRectInLocalSVGCoordinates();
- compositing_recorder_ = std::make_unique<CompositingRecorder>(
- GetPaintInfo().context, object_,
- WebCoreCompositeToSkiaComposite(kCompositeSourceOver, blend_mode),
- opacity, &compositing_bounds);
- }
-}
-
void SVGPaintContext::ApplyClipIfNecessary() {
if (object_.StyleRef().ClipPath())
clip_path_clipper_.emplace(GetPaintInfo().context, object_, LayoutPoint());
@@ -209,25 +177,10 @@ bool SVGPaintContext::ApplyFilterIfNecessary(SVGResources* resources) {
// 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.
- filter_paint_info_->cull_rect_.rect_ = LayoutRect::InfiniteIntRect();
+ filter_paint_info_->cull_rect_ = CullRect(LayoutRect::InfiniteIntRect());
return true;
}
-bool SVGPaintContext::IsIsolationInstalled() const {
- // In SPv175+ isolation is modeled by effect nodes, and will be applied by
- // PaintArtifactCompositor or PaintChunksToCcLayer depends on compositing
- // state.
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return true;
- if (compositing_recorder_)
- return true;
- if (masker_ || filter_)
- return true;
- if (clip_path_clipper_ && clip_path_clipper_->IsIsolationInstalled())
- return true;
- return false;
-}
-
void SVGPaintContext::PaintResourceSubtree(GraphicsContext& context,
const LayoutObject* item) {
DCHECK(item);
@@ -236,7 +189,7 @@ void SVGPaintContext::PaintResourceSubtree(GraphicsContext& context,
PaintInfo info(context, LayoutRect::InfiniteIntRect(),
PaintPhase::kForeground, kGlobalPaintNormalPhase,
kPaintLayerPaintingRenderingResourceSubtree);
- item->Paint(info, IntPoint());
+ item->Paint(info);
}
bool SVGPaintContext::PaintForLayoutObject(
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_paint_context.h b/chromium/third_party/blink/renderer/core/paint/svg_paint_context.h
index 8a60c272fab..261639650c5 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_paint_context.h
+++ b/chromium/third_party/blink/renderer/core/paint/svg_paint_context.h
@@ -31,8 +31,6 @@
#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/transform_recorder.h"
-#include "third_party/blink/renderer/platform/graphics/paint/compositing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
@@ -43,43 +41,38 @@ class LayoutSVGResourceFilter;
class LayoutSVGResourceMasker;
class SVGResources;
-// This class hooks up the correct paint property transform node when spv2 is
-// enabled, and otherwise works like a TransformRecorder which emits Transform
-// display items for spv1.
-class SVGTransformContext : public TransformRecorder {
+// Hooks up the correct paint property transform node.
+class SVGTransformContext {
STACK_ALLOCATED();
public:
SVGTransformContext(const PaintInfo& paint_info,
const LayoutObject& object,
- const AffineTransform& transform)
- : TransformRecorder(paint_info.context, object, transform) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- const auto* fragment = paint_info.FragmentToPaint(object);
- if (!fragment)
- return;
- const auto* properties = fragment->PaintProperties();
- if (!properties)
- return;
-
- const TransformPaintPropertyNode* transform_node;
- if (object.IsSVGRoot()) {
- // If a transform exists, we can rely on a layer existing to apply it.
- DCHECK(!properties || !properties->Transform() || object.HasLayer());
- transform_node = properties->SvgLocalToBorderBoxTransform();
- } else {
- DCHECK(object.IsSVG());
- // Should only be used by LayoutSVGRoot.
- DCHECK(!properties->SvgLocalToBorderBoxTransform());
- transform_node = properties->Transform();
- }
-
- if (transform_node) {
- DCHECK(transform_node->Matrix() == transform.ToTransformationMatrix());
- transform_property_scope_.emplace(
- paint_info.context.GetPaintController(), transform_node, object,
- DisplayItem::PaintPhaseToSVGTransformType(paint_info.phase));
- }
+ const AffineTransform& transform) {
+ const auto* fragment = paint_info.FragmentToPaint(object);
+ if (!fragment)
+ return;
+ const auto* properties = fragment->PaintProperties();
+ if (!properties)
+ return;
+
+ const TransformPaintPropertyNode* transform_node;
+ if (object.IsSVGRoot()) {
+ // If a transform exists, we can rely on a layer existing to apply it.
+ DCHECK(!properties || !properties->Transform() || object.HasLayer());
+ transform_node = properties->SvgLocalToBorderBoxTransform();
+ } else {
+ DCHECK(object.IsSVG());
+ // Should only be used by LayoutSVGRoot.
+ DCHECK(!properties->SvgLocalToBorderBoxTransform());
+ transform_node = properties->Transform();
+ }
+
+ if (transform_node) {
+ DCHECK(transform_node->Matrix() == transform.ToTransformationMatrix());
+ transform_property_scope_.emplace(
+ paint_info.context.GetPaintController(), transform_node, object,
+ DisplayItem::PaintPhaseToSVGTransformType(paint_info.phase));
}
}
@@ -120,7 +113,6 @@ class SVGPaintContext {
const AffineTransform* additional_paint_server_transform = nullptr);
private:
- void ApplyCompositingIfNecessary();
void ApplyPaintPropertyState();
void ApplyClipIfNecessary();
@@ -132,14 +124,11 @@ class SVGPaintContext {
// applied.
bool ApplyFilterIfNecessary(SVGResources*);
- bool IsIsolationInstalled() const;
-
const LayoutObject& object_;
PaintInfo paint_info_;
std::unique_ptr<PaintInfo> filter_paint_info_;
LayoutSVGResourceFilter* filter_;
LayoutSVGResourceMasker* masker_;
- std::unique_ptr<CompositingRecorder> compositing_recorder_;
base::Optional<ClipPathClipper> clip_path_clipper_;
std::unique_ptr<SVGFilterRecordingContext> filter_recording_context_;
base::Optional<ScopedPaintChunkProperties> scoped_paint_chunk_properties_;
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_root_inline_box_painter.h b/chromium/third_party/blink/renderer/core/paint/svg_root_inline_box_painter.h
index ce08bbcaead..a84b66fb116 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_root_inline_box_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/svg_root_inline_box_painter.h
@@ -20,7 +20,7 @@ class SVGRootInlineBoxPainter {
SVGRootInlineBoxPainter(const SVGRootInlineBox& svg_root_inline_box)
: svg_root_inline_box_(svg_root_inline_box) {}
- void Paint(const PaintInfo&, const LayoutPoint&);
+ void Paint(const PaintInfo&, const LayoutPoint& paint_offset);
private:
const SVGRootInlineBox& svg_root_inline_box_;
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_root_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_root_painter.cc
index 62fd531b902..448e42aed97 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_root_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_root_painter.cc
@@ -55,8 +55,7 @@ void SVGRootPainter::PaintReplaced(const PaintInfo& paint_info,
base::Optional<BoxClipper> box_clipper;
if (layout_svg_root_.ShouldApplyViewportClip()) {
// TODO(pdr): Clip the paint info cull rect here.
- box_clipper.emplace(layout_svg_root_, paint_info, paint_offset,
- kForceContentsClip);
+ box_clipper.emplace(layout_svg_root_, paint_info);
}
PaintInfo paint_info_before_filtering(paint_info);
@@ -71,8 +70,7 @@ void SVGRootPainter::PaintReplaced(const PaintInfo& paint_info,
!paint_context.ApplyClipMaskAndFilterIfNecessary())
return;
- BoxPainter(layout_svg_root_)
- .PaintChildren(paint_context.GetPaintInfo(), LayoutPoint());
+ BoxPainter(layout_svg_root_).PaintChildren(paint_context.GetPaintInfo());
PaintTiming& timing = PaintTiming::From(
layout_svg_root_.GetNode()->GetDocument().TopDocument());
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_root_painter.h b/chromium/third_party/blink/renderer/core/paint/svg_root_painter.h
index dd5c1d4bceb..f267c2e69a4 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_root_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/svg_root_painter.h
@@ -22,7 +22,7 @@ class SVGRootPainter {
SVGRootPainter(const LayoutSVGRoot& layout_svg_root)
: layout_svg_root_(layout_svg_root) {}
- void PaintReplaced(const PaintInfo&, const LayoutPoint&);
+ void PaintReplaced(const PaintInfo&, const LayoutPoint& paint_offset);
// The embedded SVG document uses an unsnapped viewport box for layout, while
// SVG root's border box ultimately gets snapped during paint. This
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_shape_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_shape_painter.cc
index 2d33acd3488..2c8ed987c4a 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_shape_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_shape_painter.cc
@@ -11,9 +11,9 @@
#include "third_party/blink/renderer/core/layout/svg/svg_marker_data.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/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/svg_container_painter.h"
+#include "third_party/blink/renderer/core/paint/svg_model_object_painter.h"
#include "third_party/blink/renderer/core/paint/svg_paint_context.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
@@ -46,13 +46,14 @@ void SVGShapePainter::Paint(const PaintInfo& paint_info) {
layout_svg_shape_.IsShapeEmpty())
return;
- FloatRect bounding_box = layout_svg_shape_.VisualRectInLocalSVGCoordinates();
- if (!paint_info.GetCullRect().IntersectsCullRect(
- layout_svg_shape_.LocalSVGTransform(), bounding_box))
+ PaintInfo paint_info_before_filtering(paint_info);
+
+ if (SVGModelObjectPainter(layout_svg_shape_)
+ .CullRectSkipsPainting(paint_info_before_filtering)) {
return;
+ }
+ // Shapes cannot have children so do not call UpdateCullRect.
- PaintInfo paint_info_before_filtering(paint_info);
- // Shapes cannot have children so do not call updateCullRect.
SVGTransformContext transform_context(paint_info_before_filtering,
layout_svg_shape_,
layout_svg_shape_.LocalSVGTransform());
@@ -124,7 +125,8 @@ void SVGShapePainter::Paint(const PaintInfo& paint_info) {
}
break;
case PT_MARKERS:
- PaintMarkers(paint_context.GetPaintInfo(), bounding_box);
+ PaintMarkers(paint_context.GetPaintInfo(),
+ layout_svg_shape_.VisualRectInLocalSVGCoordinates());
break;
default:
NOTREACHED();
@@ -134,12 +136,8 @@ void SVGShapePainter::Paint(const PaintInfo& paint_info) {
}
}
- if (layout_svg_shape_.Style()->OutlineWidth()) {
- PaintInfo outline_paint_info(paint_info_before_filtering);
- outline_paint_info.phase = PaintPhase::kSelfOutlineOnly;
- ObjectPainter(layout_svg_shape_)
- .PaintOutline(outline_paint_info, LayoutPoint(bounding_box.Location()));
- }
+ SVGModelObjectPainter(layout_svg_shape_)
+ .PaintOutline(paint_info_before_filtering);
}
class PathWithTemporaryWindingRule {
@@ -235,7 +233,7 @@ void SVGShapePainter::PaintMarker(const PaintInfo& paint_info,
AffineTransform transform = marker.MarkerTransformation(
position.origin, position.angle, stroke_width);
- PaintCanvas* canvas = paint_info.context.Canvas();
+ cc::PaintCanvas* canvas = paint_info.context.Canvas();
canvas->save();
canvas->concat(AffineTransformToSkMatrix(transform));
@@ -247,7 +245,7 @@ void SVGShapePainter::PaintMarker(const PaintInfo& paint_info,
// It's expensive to track the transformed paint cull rect for each
// marker so just disable culling. The shape paint call will already
// be culled if it is outside the paint info cull rect.
- marker_paint_info.cull_rect_.rect_ = LayoutRect::InfiniteIntRect();
+ marker_paint_info.cull_rect_ = CullRect(LayoutRect::InfiniteIntRect());
SVGContainerPainter(marker).Paint(marker_paint_info);
builder.EndRecording(*canvas);
diff --git a/chromium/third_party/blink/renderer/core/paint/svg_text_painter.cc b/chromium/third_party/blink/renderer/core/paint/svg_text_painter.cc
index c369fa0fa10..ece2cac98d8 100644
--- a/chromium/third_party/blink/renderer/core/paint/svg_text_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/svg_text_painter.cc
@@ -22,12 +22,12 @@ void SVGTextPainter::Paint(const PaintInfo& paint_info) {
block_info, layout_svg_text_,
layout_svg_text_.LocalToSVGParentTransform());
- BlockPainter(layout_svg_text_).Paint(block_info, LayoutPoint());
+ BlockPainter(layout_svg_text_).Paint(block_info);
// Paint the outlines, if any
if (paint_info.phase == PaintPhase::kForeground) {
block_info.phase = PaintPhase::kOutline;
- BlockPainter(layout_svg_text_).Paint(block_info, LayoutPoint());
+ BlockPainter(layout_svg_text_).Paint(block_info);
}
}
diff --git a/chromium/third_party/blink/renderer/core/paint/table_cell_paint_invalidator.cc b/chromium/third_party/blink/renderer/core/paint/table_cell_paint_invalidator.cc
index 30f82f28ec6..db26d502637 100644
--- a/chromium/third_party/blink/renderer/core/paint/table_cell_paint_invalidator.cc
+++ b/chromium/third_party/blink/renderer/core/paint/table_cell_paint_invalidator.cc
@@ -26,18 +26,8 @@ void TableCellPaintInvalidator::InvalidateContainerForCellGeometryChange(
// At this time we have already walked the container for paint invalidation,
// so we should invalidate the container immediately here instead of setting
// paint invalidation flags.
- ObjectPaintInvalidator invalidator(container);
container_context.painting_layer->SetNeedsRepaint();
container.InvalidateDisplayItemClients(PaintInvalidationReason::kGeometry);
-
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- context_.paint_invalidation_container !=
- container_context.paint_invalidation_container) {
- ObjectPaintInvalidatorWithContext(container, container_context)
- .InvalidatePaintRectangleWithContext(
- container.FirstFragment().VisualRect(),
- PaintInvalidationReason::kGeometry);
- }
}
PaintInvalidationReason TableCellPaintInvalidator::InvalidatePaint() {
@@ -45,7 +35,7 @@ PaintInvalidationReason TableCellPaintInvalidator::InvalidatePaint() {
// and the row or table paints collapsed borders. If the cell's geometry
// changed and the containers which will paint backgrounds and/or collapsed
// borders haven't been full invalidated, invalidate the containers.
- if (context_.old_location != context_.fragment_data->LocationInBacking() ||
+ if (context_.old_paint_offset != context_.fragment_data->PaintOffset() ||
cell_.Size() != cell_.PreviousSize()) {
const auto& row = *cell_.Row();
const auto& section = *row.Section();
diff --git a/chromium/third_party/blink/renderer/core/paint/table_cell_painter.cc b/chromium/third_party/blink/renderer/core/paint/table_cell_painter.cc
index 44c9df9baf8..226d0345c22 100644
--- a/chromium/third_party/blink/renderer/core/paint/table_cell_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/table_cell_painter.cc
@@ -18,14 +18,8 @@
namespace blink {
-void TableCellPainter::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
- BlockPainter(layout_table_cell_).Paint(paint_info, paint_offset);
-}
-
void TableCellPainter::PaintContainerBackgroundBehindCell(
const PaintInfo& paint_info,
- const LayoutPoint& paint_offset,
const LayoutObject& background_object) {
DCHECK(background_object != layout_table_cell_);
@@ -38,10 +32,9 @@ void TableCellPainter::PaintContainerBackgroundBehindCell(
!layout_table_cell_.FirstChild())
return;
- AdjustPaintOffsetScope adjustment(layout_table_cell_, paint_info,
- paint_offset);
+ AdjustPaintOffsetScope adjustment(layout_table_cell_, paint_info);
auto paint_rect =
- PaintRectNotIncludingVisualOverflow(adjustment.AdjustedPaintOffset());
+ PaintRectNotIncludingVisualOverflow(adjustment.PaintOffset());
PaintBackground(adjustment.GetPaintInfo(), paint_rect, background_object);
}
diff --git a/chromium/third_party/blink/renderer/core/paint/table_cell_painter.h b/chromium/third_party/blink/renderer/core/paint/table_cell_painter.h
index 410be8c42a3..bfa57163443 100644
--- a/chromium/third_party/blink/renderer/core/paint/table_cell_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/table_cell_painter.h
@@ -23,11 +23,8 @@ class TableCellPainter {
TableCellPainter(const LayoutTableCell& layout_table_cell)
: layout_table_cell_(layout_table_cell) {}
- void Paint(const PaintInfo&, const LayoutPoint&);
-
void PaintContainerBackgroundBehindCell(
const PaintInfo&,
- const LayoutPoint&,
const LayoutObject& background_object);
void PaintBoxDecorationBackground(const PaintInfo&,
const LayoutPoint& paint_offset);
diff --git a/chromium/third_party/blink/renderer/core/paint/table_painter.cc b/chromium/third_party/blink/renderer/core/paint/table_painter.cc
index a9209760465..8b84ce98f07 100644
--- a/chromium/third_party/blink/renderer/core/paint/table_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/table_painter.cc
@@ -38,17 +38,14 @@ void TablePainter::PaintObject(const PaintInfo& paint_info,
child = child->NextSibling()) {
if (child->IsBox() && !ToLayoutBox(child)->HasSelfPaintingLayer() &&
(child->IsTableSection() || child->IsTableCaption())) {
- LayoutPoint child_point =
- layout_table_.FlipForWritingModeForChildForPaint(ToLayoutBox(child),
- paint_offset);
- child->Paint(paint_info_for_descendants, child_point);
+ child->Paint(paint_info_for_descendants);
}
}
if (layout_table_.HasCollapsedBorders() &&
ShouldPaintDescendantBlockBackgrounds(paint_phase) &&
layout_table_.Style()->Visibility() == EVisibility::kVisible) {
- PaintCollapsedBorders(paint_info_for_descendants, paint_offset);
+ PaintCollapsedBorders(paint_info_for_descendants);
}
}
@@ -86,8 +83,7 @@ void TablePainter::PaintMask(const PaintInfo& paint_info,
BoxPainter(layout_table_).PaintMaskImages(paint_info, rect);
}
-void TablePainter::PaintCollapsedBorders(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void TablePainter::PaintCollapsedBorders(const PaintInfo& paint_info) {
base::Optional<DrawingRecorder> recorder;
if (UNLIKELY(layout_table_.ShouldPaintAllCollapsedBorders())) {
if (DrawingRecorder::UseCachedDrawingIfPossible(
@@ -101,10 +97,7 @@ void TablePainter::PaintCollapsedBorders(const PaintInfo& paint_info,
for (LayoutTableSection* section = layout_table_.BottomSection(); section;
section = layout_table_.SectionAbove(section)) {
- LayoutPoint child_point =
- layout_table_.FlipForWritingModeForChildForPaint(section, paint_offset);
- TableSectionPainter(*section).PaintCollapsedBorders(paint_info,
- child_point);
+ TableSectionPainter(*section).PaintCollapsedBorders(paint_info);
}
}
diff --git a/chromium/third_party/blink/renderer/core/paint/table_painter.h b/chromium/third_party/blink/renderer/core/paint/table_painter.h
index bc22d687b4f..3cea620b7dc 100644
--- a/chromium/third_party/blink/renderer/core/paint/table_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/table_painter.h
@@ -19,12 +19,13 @@ class TablePainter {
public:
TablePainter(const LayoutTable& layout_table) : layout_table_(layout_table) {}
- void PaintObject(const PaintInfo&, const LayoutPoint&);
- void PaintBoxDecorationBackground(const PaintInfo&, const LayoutPoint&);
- void PaintMask(const PaintInfo&, const LayoutPoint&);
+ void PaintObject(const PaintInfo&, const LayoutPoint& paint_offset);
+ void PaintBoxDecorationBackground(const PaintInfo&,
+ const LayoutPoint& paint_offset);
+ void PaintMask(const PaintInfo&, const LayoutPoint& paint_offset);
private:
- void PaintCollapsedBorders(const PaintInfo&, const LayoutPoint&);
+ void PaintCollapsedBorders(const PaintInfo&);
const LayoutTable& layout_table_;
};
diff --git a/chromium/third_party/blink/renderer/core/paint/table_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/table_painter_test.cc
index b25740427a7..7075a87248b 100644
--- a/chromium/third_party/blink/renderer/core/paint/table_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/table_painter_test.cc
@@ -133,23 +133,11 @@ TEST_P(TablePainterTest, BackgroundInSelfPaintingRow) {
IntRect interest_rect(200, 0, 200, 200);
Paint(&interest_rect);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 3,
- TestDisplayItem(ViewBackgroundClient(),
- DisplayItem::kDocumentBackground),
- TestDisplayItem(row, DisplayItem::kBoxDecorationBackground),
- TestDisplayItem(cell1, DisplayItem::kBoxDecorationBackground));
- } else {
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 5,
- TestDisplayItem(ViewBackgroundClient(),
- DisplayItem::kDocumentBackground),
- TestDisplayItem(row, DisplayItem::kBeginCompositing),
- TestDisplayItem(row, DisplayItem::kBoxDecorationBackground),
- TestDisplayItem(cell1, DisplayItem::kBoxDecorationBackground),
- TestDisplayItem(row, DisplayItem::kEndCompositing));
- }
+ EXPECT_DISPLAY_LIST(
+ RootPaintController().GetDisplayItemList(), 3,
+ TestDisplayItem(ViewBackgroundClient(), DisplayItem::kDocumentBackground),
+ TestDisplayItem(row, DisplayItem::kBoxDecorationBackground),
+ TestDisplayItem(cell1, DisplayItem::kBoxDecorationBackground));
GetDocument().View()->UpdateAllLifecyclePhasesExceptPaint();
// Intersects the spacing only.
@@ -165,23 +153,12 @@ TEST_P(TablePainterTest, BackgroundInSelfPaintingRow) {
interest_rect = IntRect(450, 0, 200, 200);
Paint(&interest_rect);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
EXPECT_DISPLAY_LIST(
RootPaintController().GetDisplayItemList(), 3,
TestDisplayItem(ViewBackgroundClient(),
DisplayItem::kDocumentBackground),
TestDisplayItem(row, DisplayItem::kBoxDecorationBackground),
TestDisplayItem(cell2, DisplayItem::kBoxDecorationBackground));
- } else {
- EXPECT_DISPLAY_LIST(
- RootPaintController().GetDisplayItemList(), 5,
- TestDisplayItem(ViewBackgroundClient(),
- DisplayItem::kDocumentBackground),
- TestDisplayItem(row, DisplayItem::kBeginCompositing),
- TestDisplayItem(row, DisplayItem::kBoxDecorationBackground),
- TestDisplayItem(cell2, DisplayItem::kBoxDecorationBackground),
- TestDisplayItem(row, DisplayItem::kEndCompositing));
- }
}
TEST_P(TablePainterTest, CollapsedBorderAndOverflow) {
diff --git a/chromium/third_party/blink/renderer/core/paint/table_row_painter.cc b/chromium/third_party/blink/renderer/core/paint/table_row_painter.cc
index e30a6be0de2..e7e29a96740 100644
--- a/chromium/third_party/blink/renderer/core/paint/table_row_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/table_row_painter.cc
@@ -17,8 +17,7 @@
namespace blink {
-void TableRowPainter::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void TableRowPainter::Paint(const PaintInfo& paint_info) {
DCHECK(layout_table_row_.HasSelfPaintingLayer());
// TODO(crbug.com/805514): Paint mask for table row.
@@ -28,13 +27,13 @@ void TableRowPainter::Paint(const PaintInfo& paint_info,
// TODO(crbug.com/577282): This painting order is inconsistent with other
// outlines.
if (ShouldPaintSelfOutline(paint_info.phase))
- PaintOutline(paint_info, paint_offset);
+ PaintOutline(paint_info);
if (paint_info.phase == PaintPhase::kSelfOutlineOnly)
return;
if (ShouldPaintSelfBlockBackground(paint_info.phase)) {
PaintBoxDecorationBackground(
- paint_info, paint_offset,
+ paint_info,
layout_table_row_.Section()->FullTableEffectiveColumnSpan());
}
@@ -45,18 +44,15 @@ void TableRowPainter::Paint(const PaintInfo& paint_info,
for (LayoutTableCell* cell = layout_table_row_.FirstCell(); cell;
cell = cell->NextCell()) {
if (!cell->HasSelfPaintingLayer())
- cell->Paint(paint_info_for_cells, paint_offset);
+ cell->Paint(paint_info_for_cells);
}
}
-void TableRowPainter::PaintOutline(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void TableRowPainter::PaintOutline(const PaintInfo& paint_info) {
DCHECK(ShouldPaintSelfOutline(paint_info.phase));
- AdjustPaintOffsetScope adjustment(layout_table_row_, paint_info,
- paint_offset);
+ AdjustPaintOffsetScope adjustment(layout_table_row_, paint_info);
ObjectPainter(layout_table_row_)
- .PaintOutline(adjustment.GetPaintInfo(),
- adjustment.AdjustedPaintOffset());
+ .PaintOutline(adjustment.GetPaintInfo(), adjustment.PaintOffset());
}
void TableRowPainter::HandleChangedPartialPaint(
@@ -73,7 +69,6 @@ void TableRowPainter::HandleChangedPartialPaint(
void TableRowPainter::PaintBoxDecorationBackground(
const PaintInfo& paint_info,
- const LayoutPoint& paint_offset,
const CellSpan& dirtied_columns) {
bool has_background = layout_table_row_.StyleRef().HasBackground();
bool has_box_shadow = layout_table_row_.StyleRef().BoxShadow();
@@ -87,13 +82,12 @@ void TableRowPainter::PaintBoxDecorationBackground(
DisplayItem::kBoxDecorationBackground))
return;
- AdjustPaintOffsetScope adjustment(layout_table_row_, paint_info,
- paint_offset);
+ AdjustPaintOffsetScope adjustment(layout_table_row_, paint_info);
const auto& local_paint_info = adjustment.GetPaintInfo();
- auto adjusted_paint_offset = adjustment.AdjustedPaintOffset();
+ auto paint_offset = adjustment.PaintOffset();
DrawingRecorder recorder(local_paint_info.context, layout_table_row_,
DisplayItem::kBoxDecorationBackground);
- LayoutRect paint_rect(adjusted_paint_offset, layout_table_row_.Size());
+ LayoutRect paint_rect(paint_offset, layout_table_row_.Size());
if (has_box_shadow) {
BoxPainterBase::PaintNormalBoxShadow(local_paint_info, paint_rect,
@@ -105,8 +99,10 @@ void TableRowPainter::PaintBoxDecorationBackground(
PaintInfo paint_info_for_cells = local_paint_info.ForDescendants();
for (auto c = dirtied_columns.Start(); c < dirtied_columns.End(); c++) {
if (const auto* cell =
- section->OriginatingCellAt(layout_table_row_.RowIndex(), c))
- PaintBackgroundBehindCell(*cell, paint_info_for_cells, paint_offset);
+ section->OriginatingCellAt(layout_table_row_.RowIndex(), c)) {
+ TableCellPainter(*cell).PaintContainerBackgroundBehindCell(
+ paint_info_for_cells, layout_table_row_);
+ }
}
}
@@ -116,26 +112,7 @@ void TableRowPainter::PaintBoxDecorationBackground(
}
}
-void TableRowPainter::PaintBackgroundBehindCell(
- const LayoutTableCell& cell,
- const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
- DCHECK(layout_table_row_.StyleRef().HasBackground());
- LayoutPoint cell_point = paint_offset;
- // If the row is self painting, paintOffset is in row's coordinates, so
- // doesn't need to flip in section's blocks direction. A row doesn't have
- // flipped blocks direction.
- if (!layout_table_row_.HasSelfPaintingLayer()) {
- cell_point =
- layout_table_row_.Section()->FlipForWritingModeForChildForPaint(
- &cell, cell_point);
- }
- TableCellPainter(cell).PaintContainerBackgroundBehindCell(
- paint_info, cell_point, layout_table_row_);
-}
-
void TableRowPainter::PaintCollapsedBorders(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset,
const CellSpan& dirtied_columns) {
base::Optional<DrawingRecorder> recorder;
@@ -156,12 +133,8 @@ void TableRowPainter::PaintCollapsedBorders(const PaintInfo& paint_info,
unsigned row = layout_table_row_.RowIndex();
for (unsigned c = std::min(dirtied_columns.End(), section->NumCols(row));
c > dirtied_columns.Start(); c--) {
- if (const auto* cell = section->OriginatingCellAt(row, c - 1)) {
- LayoutPoint cell_point =
- section->FlipForWritingModeForChildForPaint(cell, paint_offset);
- CollapsedBorderPainter(*cell).PaintCollapsedBorders(paint_info,
- cell_point);
- }
+ if (const auto* cell = section->OriginatingCellAt(row, c - 1))
+ CollapsedBorderPainter(*cell).PaintCollapsedBorders(paint_info);
}
}
diff --git a/chromium/third_party/blink/renderer/core/paint/table_row_painter.h b/chromium/third_party/blink/renderer/core/paint/table_row_painter.h
index 7af41d79b19..7c512ff139a 100644
--- a/chromium/third_party/blink/renderer/core/paint/table_row_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/table_row_painter.h
@@ -10,11 +10,9 @@
namespace blink {
+struct PaintInfo;
class CellSpan;
-class LayoutPoint;
-class LayoutTableCell;
class LayoutTableRow;
-struct PaintInfo;
class TableRowPainter {
STACK_ALLOCATED();
@@ -23,20 +21,14 @@ class TableRowPainter {
TableRowPainter(const LayoutTableRow& layout_table_row)
: layout_table_row_(layout_table_row) {}
- void Paint(const PaintInfo&, const LayoutPoint&);
- void PaintOutline(const PaintInfo&, const LayoutPoint&);
+ void Paint(const PaintInfo&);
+ void PaintOutline(const PaintInfo&);
void PaintBoxDecorationBackground(const PaintInfo&,
- const LayoutPoint&,
const CellSpan& dirtied_columns);
void PaintCollapsedBorders(const PaintInfo&,
- const LayoutPoint&,
const CellSpan& dirtied_columns);
private:
- void PaintBackgroundBehindCell(const LayoutTableCell&,
- const PaintInfo&,
- const LayoutPoint&);
-
void HandleChangedPartialPaint(const PaintInfo&,
const CellSpan& dirtied_columns);
diff --git a/chromium/third_party/blink/renderer/core/paint/table_section_painter.cc b/chromium/third_party/blink/renderer/core/paint/table_section_painter.cc
index dbc15bda69e..85d6a08aae0 100644
--- a/chromium/third_party/blink/renderer/core/paint/table_section_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/table_section_painter.cc
@@ -23,197 +23,37 @@
namespace blink {
-void TableSectionPainter::PaintRepeatingHeaderGroup(
- const PaintInfo& paint_info,
- const LayoutPoint& paint_offset,
- ItemToPaint item_to_paint) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- if (!layout_table_section_.IsRepeatingHeaderGroup())
- return;
-
- LayoutTable* table = layout_table_section_.Table();
- // TODO(crbug.com/757947): This shouldn't be possible but happens to
- // column-spanners in nested multi-col contexts.
- if (!table->IsPageLogicalHeightKnown())
- return;
-
- // We may paint the header multiple times so can't uniquely identify each
- // display item.
- DisplayItemCacheSkipper cache_skipper(paint_info.context);
-
- LayoutPoint pagination_offset = paint_offset;
- LayoutUnit page_height = table->PageLogicalHeightForOffset(LayoutUnit());
-
- LayoutUnit header_group_offset = table->BlockOffsetToFirstRepeatableHeader();
- // The header may have a pagination strut before it so we need to account for
- // that when establishing its position.
- LayoutUnit strut_on_first_row;
- if (LayoutTableRow* row = layout_table_section_.FirstRow())
- strut_on_first_row = row->PaginationStrut();
- header_group_offset += strut_on_first_row;
- LayoutUnit offset_to_next_page =
- page_height - IntMod(header_group_offset, page_height);
- // Move pagination_offset to the top of the next page.
- pagination_offset.Move(LayoutUnit(), offset_to_next_page);
- // Now move pagination_offset to the top of the page the cull rect starts on.
- if (paint_info.GetCullRect().rect_.Y() > pagination_offset.Y()) {
- pagination_offset.Move(LayoutUnit(),
- page_height * ((paint_info.GetCullRect().rect_.Y() -
- pagination_offset.Y()) /
- page_height)
- .ToInt());
- }
-
- // We only want to consider pages where we going to paint a row, so exclude
- // captions and border spacing from the table.
- LayoutRect sections_rect(LayoutPoint(), table->Size());
- table->SubtractCaptionRect(sections_rect);
- LayoutUnit total_height_of_rows =
- sections_rect.Height() - table->VBorderSpacing();
- LayoutUnit bottom_bound =
- std::min(LayoutUnit(paint_info.GetCullRect().rect_.MaxY()),
- paint_offset.Y() + total_height_of_rows);
-
- while (pagination_offset.Y() < bottom_bound) {
- LayoutPoint nested_offset = pagination_offset;
- LayoutUnit height_of_previous_headers =
- table->RowOffsetFromRepeatingHeader() -
- layout_table_section_.LogicalHeight() + strut_on_first_row;
- nested_offset.Move(LayoutUnit(), height_of_previous_headers);
- if (item_to_paint == kPaintCollapsedBorders) {
- PaintCollapsedSectionBorders(paint_info, nested_offset);
- } else {
- PaintSection(paint_info, nested_offset);
- }
- pagination_offset.Move(0, page_height.ToInt());
- }
-}
-
-void TableSectionPainter::PaintRepeatingFooterGroup(
- const PaintInfo& paint_info,
- const LayoutPoint& paint_offset,
- ItemToPaint item_to_paint) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- if (!layout_table_section_.IsRepeatingFooterGroup())
- return;
-
- // Work out the top position of the table so we can decide
- // which page to paint the first footer on.
- LayoutTable* table = layout_table_section_.Table();
- // TODO(crbug.com/757947): This shouldn't be possible but happens to
- // column-spanners in nested multi-col contexts.
- if (!table->IsPageLogicalHeightKnown())
- return;
-
- // We may paint the footer multiple times so can't uniquely identify each
- // display item.
- DisplayItemCacheSkipper cache_skipper(paint_info.context);
-
- LayoutRect sections_rect(LayoutPoint(), table->Size());
- table->SubtractCaptionRect(sections_rect);
- LayoutUnit page_height = table->PageLogicalHeightForOffset(LayoutUnit());
- LayoutUnit height_of_previous_footers = table->RowOffsetFromRepeatingFooter();
- LayoutUnit offset_for_footer = page_height - height_of_previous_footers;
- // TODO: Accounting for the border-spacing here is wrong.
- LayoutUnit header_group_offset =
- table->BlockOffsetToFirstRepeatableHeader() + table->VBorderSpacing();
- // The first row in the table may have a pagination strut before it so we need
- // to account for that when establishing its position.
- LayoutUnit strut_on_first_row;
- LayoutTableSection* top_section = table->TopSection();
- if (top_section) {
- if (LayoutTableRow* row = top_section->FirstRow())
- strut_on_first_row = row->PaginationStrut();
- }
- header_group_offset += strut_on_first_row;
- LayoutUnit total_height_of_rows =
- sections_rect.Height() + IntMod(header_group_offset, page_height);
- LayoutUnit first_row_strut =
- layout_table_section_.FirstRow()
- ? layout_table_section_.FirstRow()->PaginationStrut()
- : LayoutUnit();
- total_height_of_rows -=
- layout_table_section_.LogicalHeight() - first_row_strut;
-
- // Move the offset to the top of the page the table starts on.
- LayoutPoint pagination_offset = paint_offset;
- pagination_offset.Move(LayoutUnit(), -total_height_of_rows);
-
- // Paint up to the last page that needs painting.
- LayoutUnit bottom_bound =
- std::min(LayoutUnit(paint_info.GetCullRect().rect_.MaxY()),
- pagination_offset.Y() + total_height_of_rows - page_height);
-
- // If the first row in the table would overlap with the footer on the first
- // page then don't repeat the footer there.
- if (top_section && top_section->FirstRow() &&
- IntMod(header_group_offset, page_height) +
- top_section->FirstRow()->LogicalHeight() >
- offset_for_footer) {
- pagination_offset.Move(LayoutUnit(), page_height);
- }
-
- // Paint a footer on each page from first to next-to-last.
- while (pagination_offset.Y() < bottom_bound) {
- LayoutPoint nested_offset = pagination_offset;
- nested_offset.Move(LayoutUnit(), offset_for_footer);
- if (item_to_paint == kPaintCollapsedBorders) {
- PaintCollapsedSectionBorders(paint_info, nested_offset);
- } else {
- PaintSection(paint_info, nested_offset);
- }
- pagination_offset.Move(0, page_height.ToInt());
- }
-}
-
-void TableSectionPainter::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void TableSectionPainter::Paint(const PaintInfo& paint_info) {
// TODO(crbug.com/805514): Paint mask for table section.
if (paint_info.phase == PaintPhase::kMask)
return;
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- // If the section has multiple fragments, it should repeatedly paint the
- // fragments by itself if:
- // - It's not a self-painting layer (otherwise PaintLayerPainter should
- // initiate painting of the multiple fragments);
- // - the table doesn't have multiple fragments (otherwise the table's
- // containing painting layer should initiate painting of the fragments).
- bool should_paint_fragments_by_itself =
- layout_table_section_.FirstFragment().NextFragment() &&
- !layout_table_section_.HasSelfPaintingLayer() &&
- !layout_table_section_.Table()->FirstFragment().NextFragment();
-
- if (!should_paint_fragments_by_itself) {
- PaintSection(paint_info, paint_offset);
- return;
- }
-
- for (const auto* fragment = &layout_table_section_.FirstFragment();
- fragment; fragment = fragment->NextFragment()) {
- PaintInfo fragment_paint_info = paint_info;
- fragment_paint_info.SetFragmentLogicalTopInFlowThread(
- fragment->LogicalTopInFlowThread());
- PaintSection(fragment_paint_info, paint_offset);
- }
+ // If the section has multiple fragments, it should repeatedly paint the
+ // fragments by itself if:
+ // - It's not a self-painting layer (otherwise PaintLayerPainter should
+ // initiate painting of the multiple fragments);
+ // - the table doesn't have multiple fragments (otherwise the table's
+ // containing painting layer should initiate painting of the fragments).
+ bool should_paint_fragments_by_itself =
+ layout_table_section_.FirstFragment().NextFragment() &&
+ !layout_table_section_.HasSelfPaintingLayer() &&
+ !layout_table_section_.Table()->FirstFragment().NextFragment();
+
+ if (!should_paint_fragments_by_itself) {
+ PaintSection(paint_info);
return;
}
- PaintSection(paint_info, paint_offset);
- LayoutTable* table = layout_table_section_.Table();
- if (table->Header() == layout_table_section_) {
- PaintRepeatingHeaderGroup(paint_info, paint_offset, kPaintSection);
- } else if (table->Footer() == layout_table_section_) {
- PaintRepeatingFooterGroup(paint_info, paint_offset, kPaintSection);
+ for (const auto* fragment = &layout_table_section_.FirstFragment(); fragment;
+ fragment = fragment->NextFragment()) {
+ PaintInfo fragment_paint_info = paint_info;
+ fragment_paint_info.SetFragmentLogicalTopInFlowThread(
+ fragment->LogicalTopInFlowThread());
+ PaintSection(fragment_paint_info);
}
}
-void TableSectionPainter::PaintSection(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void TableSectionPainter::PaintSection(const PaintInfo& paint_info) {
DCHECK(!layout_table_section_.NeedsLayout());
// avoid crashing on bugs that cause us to paint with dirty layout
if (layout_table_section_.NeedsLayout())
@@ -225,85 +65,70 @@ void TableSectionPainter::PaintSection(const PaintInfo& paint_info,
if (!total_rows || !total_cols)
return;
- AdjustPaintOffsetScope adjustment(layout_table_section_, paint_info,
- paint_offset);
+ AdjustPaintOffsetScope adjustment(layout_table_section_, paint_info);
const auto& local_paint_info = adjustment.GetPaintInfo();
- auto adjusted_paint_offset = adjustment.AdjustedPaintOffset();
+ auto paint_offset = adjustment.PaintOffset();
if (local_paint_info.phase != PaintPhase::kSelfOutlineOnly) {
base::Optional<BoxClipper> box_clipper;
- if (local_paint_info.phase != PaintPhase::kSelfBlockBackgroundOnly) {
- box_clipper.emplace(layout_table_section_, local_paint_info,
- adjusted_paint_offset, kForceContentsClip);
- }
- PaintObject(local_paint_info, adjusted_paint_offset);
+ if (local_paint_info.phase != PaintPhase::kSelfBlockBackgroundOnly)
+ box_clipper.emplace(layout_table_section_, local_paint_info);
+ PaintObject(local_paint_info, paint_offset);
}
if (ShouldPaintSelfOutline(local_paint_info.phase)) {
ObjectPainter(layout_table_section_)
- .PaintOutline(local_paint_info, adjusted_paint_offset);
+ .PaintOutline(local_paint_info, paint_offset);
}
}
-void TableSectionPainter::PaintCollapsedBorders(
- const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- // If the section has multiple fragments, it should repeatedly paint the
- // fragments for collapsed borders by itself if the table doesn't have
- // multiple fragments (otherwise the table's containing painting layer
- // should initiate painting of the fragments). The condition here is
- // different from that in Paint() because the table always initiate painting
- // of collapsed borders regardless of self-painting status of the section.
- bool should_paint_fragments_by_itself =
- layout_table_section_.FirstFragment().NextFragment() &&
- !layout_table_section_.Table()->FirstFragment().NextFragment();
-
- if (!should_paint_fragments_by_itself) {
- PaintCollapsedSectionBorders(paint_info, paint_offset);
- return;
- }
-
- for (const auto* fragment = &layout_table_section_.FirstFragment();
- fragment; fragment = fragment->NextFragment()) {
- PaintInfo fragment_paint_info = paint_info;
- fragment_paint_info.SetFragmentLogicalTopInFlowThread(
- fragment->LogicalTopInFlowThread());
- PaintCollapsedSectionBorders(fragment_paint_info, paint_offset);
- }
+void TableSectionPainter::PaintCollapsedBorders(const PaintInfo& paint_info) {
+ // If the section has multiple fragments, it should repeatedly paint the
+ // fragments for collapsed borders by itself if the table doesn't have
+ // multiple fragments (otherwise the table's containing painting layer
+ // should initiate painting of the fragments). The condition here is
+ // different from that in Paint() because the table always initiate painting
+ // of collapsed borders regardless of self-painting status of the section.
+ bool should_paint_fragments_by_itself =
+ layout_table_section_.FirstFragment().NextFragment() &&
+ !layout_table_section_.Table()->FirstFragment().NextFragment();
+
+ if (!should_paint_fragments_by_itself) {
+ PaintCollapsedSectionBorders(paint_info);
return;
}
- PaintCollapsedSectionBorders(paint_info, paint_offset);
- LayoutTable* table = layout_table_section_.Table();
- if (table->Header() == layout_table_section_) {
- PaintRepeatingHeaderGroup(paint_info, paint_offset, kPaintCollapsedBorders);
- } else if (table->Footer() == layout_table_section_) {
- PaintRepeatingFooterGroup(paint_info, paint_offset, kPaintCollapsedBorders);
+ for (const auto* fragment = &layout_table_section_.FirstFragment(); fragment;
+ fragment = fragment->NextFragment()) {
+ PaintInfo fragment_paint_info = paint_info;
+ fragment_paint_info.SetFragmentLogicalTopInFlowThread(
+ fragment->LogicalTopInFlowThread());
+ PaintCollapsedSectionBorders(fragment_paint_info);
}
}
-void TableSectionPainter::PaintCollapsedSectionBorders(
+LayoutRect TableSectionPainter::TableAlignedRect(
const PaintInfo& paint_info,
const LayoutPoint& paint_offset) {
+ LayoutRect local_cull_rect = LayoutRect(paint_info.GetCullRect().Rect());
+ local_cull_rect.MoveBy(-paint_offset);
+
+ LayoutRect table_aligned_rect =
+ layout_table_section_.LogicalRectForWritingModeAndDirection(
+ local_cull_rect);
+ return table_aligned_rect;
+}
+
+void TableSectionPainter::PaintCollapsedSectionBorders(
+ const PaintInfo& paint_info) {
if (!layout_table_section_.NumRows() ||
!layout_table_section_.Table()->EffectiveColumns().size())
return;
- AdjustPaintOffsetScope adjustment(layout_table_section_, paint_info,
- paint_offset);
+ AdjustPaintOffsetScope adjustment(layout_table_section_, paint_info);
const auto& local_paint_info = adjustment.GetPaintInfo();
- auto adjusted_paint_offset = adjustment.AdjustedPaintOffset();
- BoxClipper box_clipper(layout_table_section_, local_paint_info,
- adjusted_paint_offset, kForceContentsClip);
-
- LayoutRect local_visual_rect =
- LayoutRect(local_paint_info.GetCullRect().rect_);
- local_visual_rect.MoveBy(-adjusted_paint_offset);
-
- LayoutRect table_aligned_rect =
- layout_table_section_.LogicalRectForWritingModeAndDirection(
- local_visual_rect);
+ auto paint_offset = adjustment.PaintOffset();
+ BoxClipper box_clipper(layout_table_section_, local_paint_info);
CellSpan dirtied_rows;
CellSpan dirtied_columns;
@@ -314,7 +139,8 @@ void TableSectionPainter::PaintCollapsedSectionBorders(
dirtied_columns = layout_table_section_.FullTableEffectiveColumnSpan();
} else {
layout_table_section_.DirtiedRowsAndEffectiveColumns(
- table_aligned_rect, dirtied_rows, dirtied_columns);
+ TableAlignedRect(paint_info, paint_offset), dirtied_rows,
+ dirtied_columns);
}
if (dirtied_columns.Start() >= dirtied_columns.End())
@@ -324,25 +150,19 @@ void TableSectionPainter::PaintCollapsedSectionBorders(
// precedence due to cell position is respected.
for (unsigned r = dirtied_rows.End(); r > dirtied_rows.Start(); r--) {
if (const auto* row = layout_table_section_.RowLayoutObjectAt(r - 1)) {
- TableRowPainter(*row).PaintCollapsedBorders(
- local_paint_info, adjusted_paint_offset, dirtied_columns);
+ TableRowPainter(*row).PaintCollapsedBorders(local_paint_info,
+ dirtied_columns);
}
}
}
void TableSectionPainter::PaintObject(const PaintInfo& paint_info,
const LayoutPoint& paint_offset) {
- LayoutRect local_visual_rect = LayoutRect(paint_info.GetCullRect().rect_);
- local_visual_rect.MoveBy(-paint_offset);
-
- LayoutRect table_aligned_rect =
- layout_table_section_.LogicalRectForWritingModeAndDirection(
- local_visual_rect);
-
CellSpan dirtied_rows;
CellSpan dirtied_columns;
layout_table_section_.DirtiedRowsAndEffectiveColumns(
- table_aligned_rect, dirtied_rows, dirtied_columns);
+ TableAlignedRect(paint_info, paint_offset), dirtied_rows,
+ dirtied_columns);
PaintInfo paint_info_for_descendants = paint_info.ForDescendants();
@@ -362,7 +182,7 @@ void TableSectionPainter::PaintObject(const PaintInfo& paint_info,
if (!row || row->HasSelfPaintingLayer())
continue;
TableRowPainter(*row).PaintBoxDecorationBackground(
- paint_info_for_descendants, paint_offset, dirtied_columns);
+ paint_info_for_descendants, dirtied_columns);
}
}
@@ -392,14 +212,13 @@ void TableSectionPainter::PaintObject(const PaintInfo& paint_info,
// outlines.
if (row && !row->HasSelfPaintingLayer() &&
ShouldPaintSelfOutline(paint_info_for_descendants.phase)) {
- TableRowPainter(*row).PaintOutline(paint_info_for_descendants,
- paint_offset);
+ TableRowPainter(*row).PaintOutline(paint_info_for_descendants);
}
for (unsigned c = dirtied_columns.Start(); c < dirtied_columns.End();
c++) {
if (const LayoutTableCell* cell =
layout_table_section_.OriginatingCellAt(r, c))
- PaintCell(*cell, paint_info_for_descendants, paint_offset);
+ PaintCell(*cell, paint_info_for_descendants);
}
}
} else {
@@ -416,8 +235,7 @@ void TableSectionPainter::PaintObject(const PaintInfo& paint_info,
// outlines.
if (row && !row->HasSelfPaintingLayer() &&
ShouldPaintSelfOutline(paint_info_for_descendants.phase)) {
- TableRowPainter(*row).PaintOutline(paint_info_for_descendants,
- paint_offset);
+ TableRowPainter(*row).PaintOutline(paint_info_for_descendants);
}
unsigned n_cols = layout_table_section_.NumCols(r);
for (unsigned c = dirtied_columns.Start();
@@ -432,7 +250,7 @@ void TableSectionPainter::PaintObject(const PaintInfo& paint_info,
// Sort the dirty cells by paint order.
std::sort(cells.begin(), cells.end(), LayoutTableCell::CompareInDOMOrder);
for (const auto* cell : cells)
- PaintCell(*cell, paint_info_for_descendants, paint_offset);
+ PaintCell(*cell, paint_info_for_descendants);
}
}
@@ -473,9 +291,8 @@ void TableSectionPainter::PaintBoxDecorationBackground(
PaintInfo paint_info_for_cells = paint_info.ForDescendants();
for (auto r = dirtied_rows.Start(); r < dirtied_rows.End(); r++) {
for (auto c = dirtied_columns.Start(); c < dirtied_columns.End(); c++) {
- if (const auto* cell = layout_table_section_.OriginatingCellAt(r, c)) {
- PaintBackgroundsBehindCell(*cell, paint_info_for_cells, paint_offset);
- }
+ if (const auto* cell = layout_table_section_.OriginatingCellAt(r, c))
+ PaintBackgroundsBehindCell(*cell, paint_info_for_cells);
}
}
}
@@ -488,12 +305,7 @@ void TableSectionPainter::PaintBoxDecorationBackground(
void TableSectionPainter::PaintBackgroundsBehindCell(
const LayoutTableCell& cell,
- const PaintInfo& paint_info_for_cells,
- const LayoutPoint& paint_offset) {
- LayoutPoint cell_point =
- layout_table_section_.FlipForWritingModeForChildForPaint(&cell,
- paint_offset);
-
+ const PaintInfo& paint_info_for_cells) {
// We need to handle painting a stack of backgrounds. This stack (from bottom
// to top) consists of the column group, column, row group, row, and then the
// cell.
@@ -512,30 +324,25 @@ void TableSectionPainter::PaintBackgroundsBehindCell(
// deliberately ignore whether or not the cell has a layer, since these
// backgrounds paint "behind" the cell.
if (column_group && column_group->StyleRef().HasBackground()) {
- table_cell_painter.PaintContainerBackgroundBehindCell(
- paint_info_for_cells, cell_point, *column_group);
+ table_cell_painter.PaintContainerBackgroundBehindCell(paint_info_for_cells,
+ *column_group);
}
if (column && column->StyleRef().HasBackground()) {
table_cell_painter.PaintContainerBackgroundBehindCell(paint_info_for_cells,
- cell_point, *column);
+ *column);
}
// Paint the row group next.
if (layout_table_section_.StyleRef().HasBackground()) {
table_cell_painter.PaintContainerBackgroundBehindCell(
- paint_info_for_cells, cell_point, layout_table_section_);
+ paint_info_for_cells, layout_table_section_);
}
}
void TableSectionPainter::PaintCell(const LayoutTableCell& cell,
- const PaintInfo& paint_info_for_cells,
- const LayoutPoint& paint_offset) {
- if (!cell.HasSelfPaintingLayer() && !cell.Row()->HasSelfPaintingLayer()) {
- LayoutPoint cell_point =
- layout_table_section_.FlipForWritingModeForChildForPaint(&cell,
- paint_offset);
- cell.Paint(paint_info_for_cells, cell_point);
- }
+ const PaintInfo& paint_info_for_cells) {
+ if (!cell.HasSelfPaintingLayer() && !cell.Row()->HasSelfPaintingLayer())
+ cell.Paint(paint_info_for_cells);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/table_section_painter.h b/chromium/third_party/blink/renderer/core/paint/table_section_painter.h
index 0965d31756e..eabff481f90 100644
--- a/chromium/third_party/blink/renderer/core/paint/table_section_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/table_section_painter.h
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/paint/paint_phase.h"
#include "third_party/blink/renderer/core/style/shadow_data.h"
+#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
namespace blink {
@@ -24,30 +25,24 @@ class TableSectionPainter {
TableSectionPainter(const LayoutTableSection& layout_table_section)
: layout_table_section_(layout_table_section) {}
- void Paint(const PaintInfo&, const LayoutPoint&);
- void PaintCollapsedBorders(const PaintInfo&, const LayoutPoint&);
+ void Paint(const PaintInfo&);
+ void PaintCollapsedBorders(const PaintInfo&);
private:
- void PaintObject(const PaintInfo&, const LayoutPoint&);
+ void PaintObject(const PaintInfo&, const LayoutPoint& paint_offset);
void PaintBoxDecorationBackground(const PaintInfo&,
const LayoutPoint&,
const CellSpan& dirtied_rows,
const CellSpan& dirtied_columns);
- void PaintBackgroundsBehindCell(const LayoutTableCell&,
- const PaintInfo&,
- const LayoutPoint&);
- void PaintCell(const LayoutTableCell&, const PaintInfo&, const LayoutPoint&);
-
- enum ItemToPaint { kPaintCollapsedBorders, kPaintSection };
- void PaintRepeatingHeaderGroup(const PaintInfo&,
- const LayoutPoint&,
- ItemToPaint);
- void PaintRepeatingFooterGroup(const PaintInfo&,
- const LayoutPoint&,
- ItemToPaint);
- void PaintSection(const PaintInfo&, const LayoutPoint&);
- void PaintCollapsedSectionBorders(const PaintInfo&, const LayoutPoint&);
+ void PaintBackgroundsBehindCell(const LayoutTableCell&, const PaintInfo&);
+ void PaintCell(const LayoutTableCell&, const PaintInfo&);
+
+ void PaintSection(const PaintInfo&);
+ void PaintCollapsedSectionBorders(const PaintInfo&);
+
+ LayoutRect TableAlignedRect(const PaintInfo& paint_info,
+ const LayoutPoint& paint_offset);
const LayoutTableSection& layout_table_section_;
};
diff --git a/chromium/third_party/blink/renderer/core/paint/text_control_single_line_painter.cc b/chromium/third_party/blink/renderer/core/paint/text_control_single_line_painter.cc
new file mode 100644
index 00000000000..b63136d1b29
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/text_control_single_line_painter.cc
@@ -0,0 +1,49 @@
+// 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/paint/text_control_single_line_painter.h"
+
+#include "third_party/blink/renderer/core/layout/layout_text_control_single_line.h"
+#include "third_party/blink/renderer/core/layout/layout_theme.h"
+#include "third_party/blink/renderer/core/paint/adjust_paint_offset_scope.h"
+#include "third_party/blink/renderer/core/paint/block_painter.h"
+#include "third_party/blink/renderer/core/paint/theme_painter.h"
+#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
+
+namespace blink {
+
+void TextControlSingleLinePainter::Paint(const PaintInfo& paint_info) {
+ BlockPainter(text_control_).Paint(paint_info);
+
+ if (!ShouldPaintSelfBlockBackground(paint_info.phase) ||
+ !text_control_.ShouldDrawCapsLockIndicator())
+ return;
+
+ if (DrawingRecorder::UseCachedDrawingIfPossible(
+ paint_info.context, text_control_, DisplayItem::kCapsLockIndicator))
+ return;
+ DrawingRecorder recorder(paint_info.context, text_control_,
+ DisplayItem::kCapsLockIndicator);
+
+ LayoutRect contents_rect = text_control_.ContentBoxRect();
+
+ // Center in the block progression direction.
+ if (text_control_.IsHorizontalWritingMode()) {
+ contents_rect.SetY(
+ (text_control_.Size().Height() - contents_rect.Height()) / 2);
+ } else {
+ contents_rect.SetX((text_control_.Size().Width() - contents_rect.Width()) /
+ 2);
+ }
+
+ // Convert the rect into the coords used for painting the content.
+ AdjustPaintOffsetScope adjustment(text_control_, paint_info);
+ const auto& local_paint_info = adjustment.GetPaintInfo();
+ contents_rect.MoveBy(adjustment.PaintOffset());
+ IntRect snapped_rect = PixelSnappedIntRect(contents_rect);
+ LayoutTheme::GetTheme().Painter().PaintCapsLockIndicator(
+ text_control_, local_paint_info, snapped_rect);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/text_control_single_line_painter.h b/chromium/third_party/blink/renderer/core/paint/text_control_single_line_painter.h
new file mode 100644
index 00000000000..8c9f898fef5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/paint/text_control_single_line_painter.h
@@ -0,0 +1,29 @@
+// 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_PAINT_TEXT_CONTROL_SINGLE_LINE_PAINTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TEXT_CONTROL_SINGLE_LINE_PAINTER_H_
+
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+
+namespace blink {
+
+class LayoutTextControlSingleLine;
+struct PaintInfo;
+
+class TextControlSingleLinePainter {
+ STACK_ALLOCATED();
+
+ public:
+ TextControlSingleLinePainter(const LayoutTextControlSingleLine& text_control)
+ : text_control_(text_control) {}
+ void Paint(const PaintInfo&);
+
+ private:
+ const LayoutTextControlSingleLine& text_control_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TEXT_CONTROL_SINGLE_LINE_PAINTER_H_
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 965ced591a9..80a5e078a5a 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
@@ -288,13 +288,11 @@ static ResolvedUnderlinePosition ResolveUnderlinePosition(
// vertical text.
switch (baseline_type) {
case kAlphabeticBaseline:
- switch (style.GetTextUnderlinePosition()) {
- case TextUnderlinePosition::kAuto:
- return ResolvedUnderlinePosition::kRoman;
- case TextUnderlinePosition::kUnder:
- return ResolvedUnderlinePosition::kUnder;
+ if (style.TextUnderlinePosition() == kTextUnderlinePositionAuto) {
+ return ResolvedUnderlinePosition::kRoman;
}
- break;
+ // TODO(https://crbug.com/313888) Support left, right.
+ return ResolvedUnderlinePosition::kUnder;
case kIdeographicBaseline:
// Compute language-appropriate default underline position.
// https://drafts.csswg.org/css-text-decor-3/#default-stylesheet
diff --git a/chromium/third_party/blink/renderer/core/paint/theme_painter_default.cc b/chromium/third_party/blink/renderer/core/paint/theme_painter_default.cc
index 4c7169e0fc2..7e32057cc7c 100644
--- a/chromium/third_party/blink/renderer/core/paint/theme_painter_default.cc
+++ b/chromium/third_party/blink/renderer/core/paint/theme_painter_default.cc
@@ -148,7 +148,7 @@ bool ThemePainterDefault::PaintCheckbox(const Node* node,
const PaintInfo& paint_info,
const IntRect& rect) {
WebThemeEngine::ExtraParams extra_params;
- WebCanvas* canvas = paint_info.context.Canvas();
+ cc::PaintCanvas* canvas = paint_info.context.Canvas();
extra_params.button.checked = LayoutTheme::IsChecked(node);
extra_params.button.indeterminate = LayoutTheme::IsIndeterminate(node);
@@ -176,7 +176,7 @@ bool ThemePainterDefault::PaintRadio(const Node* node,
const PaintInfo& paint_info,
const IntRect& rect) {
WebThemeEngine::ExtraParams extra_params;
- WebCanvas* canvas = paint_info.context.Canvas();
+ cc::PaintCanvas* canvas = paint_info.context.Canvas();
extra_params.button.checked = LayoutTheme::IsChecked(node);
Platform::Current()->ThemeEngine()->Paint(canvas, WebThemeEngine::kPartRadio,
@@ -191,7 +191,7 @@ bool ThemePainterDefault::PaintButton(const Node* node,
const PaintInfo& paint_info,
const IntRect& rect) {
WebThemeEngine::ExtraParams extra_params;
- WebCanvas* canvas = paint_info.context.Canvas();
+ cc::PaintCanvas* canvas = paint_info.context.Canvas();
extra_params.button.has_border = true;
extra_params.button.background_color =
UseMockTheme() ? 0xffc0c0c0 : kDefaultButtonBackgroundColor;
@@ -220,7 +220,7 @@ bool ThemePainterDefault::PaintTextField(const Node* node,
extra_params.text_field.is_text_area = part == kTextAreaPart;
extra_params.text_field.is_listbox = part == kListboxPart;
- WebCanvas* canvas = paint_info.context.Canvas();
+ cc::PaintCanvas* canvas = paint_info.context.Canvas();
Color background_color =
style.VisitedDependentColor(GetCSSPropertyBackgroundColor());
@@ -259,7 +259,7 @@ bool ThemePainterDefault::PaintMenuList(const Node* node,
SetupMenuListArrow(document, style, rect, extra_params);
- WebCanvas* canvas = i.context.Canvas();
+ cc::PaintCanvas* canvas = i.context.Canvas();
Platform::Current()->ThemeEngine()->Paint(
canvas, WebThemeEngine::kPartMenuList, GetWebThemeState(node),
WebRect(rect), &extra_params);
@@ -278,7 +278,7 @@ bool ThemePainterDefault::PaintMenuListButton(const Node* node,
extra_params.menu_list.fill_content_area = false;
SetupMenuListArrow(document, style, rect, extra_params);
- WebCanvas* canvas = paint_info.context.Canvas();
+ cc::PaintCanvas* canvas = paint_info.context.Canvas();
Platform::Current()->ThemeEngine()->Paint(
canvas, WebThemeEngine::kPartMenuList, GetWebThemeState(node),
WebRect(rect), &extra_params);
@@ -334,7 +334,7 @@ bool ThemePainterDefault::PaintSliderTrack(const LayoutObject& o,
const PaintInfo& i,
const IntRect& rect) {
WebThemeEngine::ExtraParams extra_params;
- WebCanvas* canvas = i.context.Canvas();
+ cc::PaintCanvas* canvas = i.context.Canvas();
extra_params.slider.vertical =
o.StyleRef().Appearance() == kSliderVerticalPart;
@@ -364,7 +364,7 @@ bool ThemePainterDefault::PaintSliderThumb(const Node* node,
const PaintInfo& paint_info,
const IntRect& rect) {
WebThemeEngine::ExtraParams extra_params;
- WebCanvas* canvas = paint_info.context.Canvas();
+ cc::PaintCanvas* canvas = paint_info.context.Canvas();
extra_params.slider.vertical = style.Appearance() == kSliderThumbVerticalPart;
extra_params.slider.in_drag = LayoutTheme::IsPressed(node);
@@ -392,7 +392,7 @@ bool ThemePainterDefault::PaintInnerSpinButton(const Node* node,
const PaintInfo& paint_info,
const IntRect& rect) {
WebThemeEngine::ExtraParams extra_params;
- WebCanvas* canvas = paint_info.context.Canvas();
+ cc::PaintCanvas* canvas = paint_info.context.Canvas();
extra_params.inner_spin.spin_up =
(LayoutTheme::ControlStatesForNode(node, style) & kSpinUpControlState);
extra_params.inner_spin.read_only = LayoutTheme::IsReadOnlyControl(node);
@@ -420,7 +420,7 @@ bool ThemePainterDefault::PaintProgressBar(const LayoutObject& o,
extra_params.progress_bar.value_rect_height = value_rect.Height();
DirectionFlippingScope scope(o, i, rect);
- WebCanvas* canvas = i.context.Canvas();
+ cc::PaintCanvas* canvas = i.context.Canvas();
Platform::Current()->ThemeEngine()->Paint(
canvas, WebThemeEngine::kPartProgressBar, GetWebThemeState(o.GetNode()),
WebRect(rect), &extra_params);
@@ -482,7 +482,7 @@ bool ThemePainterDefault::PaintSearchFieldCancelButton(
LayoutTheme::IsPressed(cancel_button_object.GetNode())
? cancel_pressed_image
: cancel_image,
- Image::kSyncDecode, painting_rect);
+ Image::kSyncDecode, FloatRect(painting_rect));
return false;
}
diff --git a/chromium/third_party/blink/renderer/core/paint/theme_painter_mac.mm b/chromium/third_party/blink/renderer/core/paint/theme_painter_mac.mm
index dc115581a0e..7a1260db0a1 100644
--- a/chromium/third_party/blink/renderer/core/paint/theme_painter_mac.mm
+++ b/chromium/third_party/blink/renderer/core/paint/theme_painter_mac.mm
@@ -325,7 +325,7 @@ bool ThemePainterMac::PaintSliderTrack(const LayoutObject& o,
PaintSliderTicks(o, paint_info, r);
float zoom_level = o.StyleRef().EffectiveZoom();
- FloatRect unzoomed_rect = r;
+ FloatRect unzoomed_rect(r);
if (o.StyleRef().Appearance() == kSliderHorizontalPart ||
o.StyleRef().Appearance() == kMediaSliderPart) {
@@ -473,7 +473,7 @@ bool ThemePainterMac::PaintSliderThumb(const Node* node,
paint_info.context.FillEllipse(border_bounds);
paint_info.context.SetDrawLooper(nullptr);
- IntRect fill_bounds = EnclosedIntRect(unzoomed_rect);
+ FloatRect fill_bounds = FloatRect(EnclosedIntRect(unzoomed_rect));
scoped_refptr<Gradient> fill_gradient = Gradient::CreateLinear(
fill_bounds.MinXMinYCorner(), fill_bounds.MinXMaxYCorner());
fill_gradient->AddColorStop(0.0, fill_gradient_top_color);
@@ -642,7 +642,7 @@ bool ThemePainterMac::PaintCheckbox(const Node* node,
LocalCurrentGraphicsContext local_context(
paint_info.context, ThemeMac::InflateRectForFocusRing(inflated_rect));
- NSView* view = ThemeMac::EnsuredView(document.View());
+ NSView* view = ThemeMac::EnsuredView(document.View()->Size());
[checkbox_cell drawWithFrame:NSRect(inflated_rect) inView:view];
if (states & kFocusControlState)
[checkbox_cell cr_drawFocusRingWithFrame:NSRect(inflated_rect) inView:view];
@@ -684,7 +684,7 @@ bool ThemePainterMac::PaintRadio(const Node* node,
LocalCurrentGraphicsContext local_context(
paint_info.context, ThemeMac::InflateRectForFocusRing(inflated_rect));
BEGIN_BLOCK_OBJC_EXCEPTIONS
- NSView* view = ThemeMac::EnsuredView(document.View());
+ NSView* view = ThemeMac::EnsuredView(document.View()->Size());
[radio_cell drawWithFrame:NSRect(inflated_rect) inView:view];
if (states & kFocusControlState)
[radio_cell cr_drawFocusRingWithFrame:NSRect(inflated_rect) inView:view];
@@ -741,7 +741,7 @@ bool ThemePainterMac::PaintButton(const Node* node,
LocalCurrentGraphicsContext local_context(
paint_info.context, ThemeMac::InflateRectForFocusRing(inflated_rect));
- NSView* view = ThemeMac::EnsuredView(document.View());
+ NSView* view = ThemeMac::EnsuredView(document.View()->Size());
[button_cell drawWithFrame:NSRect(inflated_rect) inView:view];
if (states & kFocusControlState)
diff --git a/chromium/third_party/blink/renderer/core/paint/transform_3d_recorder.cc b/chromium/third_party/blink/renderer/core/paint/transform_3d_recorder.cc
deleted file mode 100644
index 0807fc6254a..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/transform_3d_recorder.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/paint/transform_3d_recorder.h"
-
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-#include "third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.h"
-
-namespace blink {
-
-Transform3DRecorder::Transform3DRecorder(GraphicsContext& context,
- const DisplayItemClient& client,
- DisplayItem::Type type,
- const TransformationMatrix& transform,
- const FloatPoint3D& transform_origin)
- : context_(context), client_(client), type_(type) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
- DCHECK(DisplayItem::IsTransform3DType(type));
- skip_recording_for_identity_transform_ = transform.IsIdentity();
-
- if (skip_recording_for_identity_transform_)
- return;
-
- context_.GetPaintController().CreateAndAppend<BeginTransform3DDisplayItem>(
- client_, type_, transform, transform_origin);
-}
-
-Transform3DRecorder::~Transform3DRecorder() {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
- if (skip_recording_for_identity_transform_)
- return;
-
- context_.GetPaintController().EndItem<EndTransform3DDisplayItem>(
- client_, DisplayItem::Transform3DTypeToEndTransform3DType(type_));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/transform_3d_recorder.h b/chromium/third_party/blink/renderer/core/paint/transform_3d_recorder.h
deleted file mode 100644
index ecf11f2de87..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/transform_3d_recorder.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TRANSFORM_3D_RECORDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TRANSFORM_3D_RECORDER_H_
-
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class FloatPoint3D;
-class GraphicsContext;
-class TransformationMatrix;
-
-class Transform3DRecorder {
- STACK_ALLOCATED();
-
- public:
- Transform3DRecorder(GraphicsContext&,
- const DisplayItemClient&,
- DisplayItem::Type,
- const TransformationMatrix&,
- const FloatPoint3D& transform_origin);
- ~Transform3DRecorder();
-
- private:
- GraphicsContext& context_;
- const DisplayItemClient& client_;
- DisplayItem::Type type_;
- bool skip_recording_for_identity_transform_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TRANSFORM_3D_RECORDER_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/transform_recorder.cc b/chromium/third_party/blink/renderer/core/paint/transform_recorder.cc
deleted file mode 100644
index c2652734aee..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/transform_recorder.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
-
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-#include "third_party/blink/renderer/platform/graphics/paint/transform_display_item.h"
-
-namespace blink {
-
-TransformRecorder::TransformRecorder(GraphicsContext& context,
- const DisplayItemClient& client,
- const AffineTransform& transform)
- : context_(context), client_(client) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
- skip_recording_for_identity_transform_ = transform.IsIdentity();
-
- if (skip_recording_for_identity_transform_)
- return;
-
- context_.GetPaintController().CreateAndAppend<BeginTransformDisplayItem>(
- client_, transform);
-}
-
-TransformRecorder::~TransformRecorder() {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
- if (skip_recording_for_identity_transform_)
- return;
-
- context_.GetPaintController().EndItem<EndTransformDisplayItem>(client_);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/paint/transform_recorder.h b/chromium/third_party/blink/renderer/core/paint/transform_recorder.h
deleted file mode 100644
index 28955f759f0..00000000000
--- a/chromium/third_party/blink/renderer/core/paint/transform_recorder.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TRANSFORM_RECORDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TRANSFORM_RECORDER_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class GraphicsContext;
-class AffineTransform;
-
-class CORE_EXPORT TransformRecorder {
- STACK_ALLOCATED();
-
- public:
- TransformRecorder(GraphicsContext&,
- const DisplayItemClient&,
- const AffineTransform&);
- ~TransformRecorder();
-
- private:
- GraphicsContext& context_;
- const DisplayItemClient& client_;
- bool skip_recording_for_identity_transform_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TRANSFORM_RECORDER_H_
diff --git a/chromium/third_party/blink/renderer/core/paint/video_painter.cc b/chromium/third_party/blink/renderer/core/paint/video_painter.cc
index 80b6f2eb161..f3badfd3a61 100644
--- a/chromium/third_party/blink/renderer/core/paint/video_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/video_painter.cc
@@ -56,7 +56,7 @@ void VideoPainter::PaintReplaced(const PaintInfo& paint_info,
layer->SetIsDrawable(true);
RecordForeignLayer(
context, layout_video_, DisplayItem::kForeignLayerVideo, layer,
- pixel_snapped_rect.Location(), pixel_snapped_rect.Size());
+ FloatPoint(pixel_snapped_rect.Location()), pixel_snapped_rect.Size());
return;
}
}
diff --git a/chromium/third_party/blink/renderer/core/paint/video_painter.h b/chromium/third_party/blink/renderer/core/paint/video_painter.h
index 47ce5606662..bac0cbecdac 100644
--- a/chromium/third_party/blink/renderer/core/paint/video_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/video_painter.h
@@ -19,7 +19,7 @@ class VideoPainter {
public:
VideoPainter(const LayoutVideo& layout_video) : layout_video_(layout_video) {}
- void PaintReplaced(const PaintInfo&, const LayoutPoint&);
+ void PaintReplaced(const PaintInfo&, const LayoutPoint& paint_offset);
private:
const LayoutVideo& layout_video_;
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 2730807b29e..998110e4ae1 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
@@ -26,7 +26,7 @@ class StubWebMediaPlayer : public EmptyWebMediaPlayer {
const cc::Layer* GetCcLayer() { return layer_.get(); }
// WebMediaPlayer
- void Load(LoadType, const WebMediaPlayerSource&, CORSMode) override {
+ LoadTiming Load(LoadType, const WebMediaPlayerSource&, CORSMode) override {
network_state_ = kNetworkStateLoaded;
client_->NetworkStateChanged();
ready_state_ = kReadyStateHaveEnoughData;
@@ -34,6 +34,7 @@ class StubWebMediaPlayer : public EmptyWebMediaPlayer {
layer_ = cc::Layer::Create();
layer_->SetIsDrawable(true);
client_->SetCcLayer(layer_.get());
+ return LoadTiming::kImmediate;
}
NetworkState GetNetworkState() const override { return network_state_; }
ReadyState GetReadyState() const override { return ready_state_; }
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 6a2380a9ad2..7b9edc2b0e4 100644
--- a/chromium/third_party/blink/renderer/core/paint/view_painter.cc
+++ b/chromium/third_party/blink/renderer/core/paint/view_painter.cc
@@ -15,26 +15,19 @@
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
#include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/core/paint/scroll_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
-void ViewPainter::Paint(const PaintInfo& paint_info,
- const LayoutPoint& paint_offset) {
+void ViewPainter::Paint(const PaintInfo& paint_info) {
// If we ever require layout but receive a paint anyway, something has gone
// horribly wrong.
DCHECK(!layout_view_.NeedsLayout());
- // LayoutViews should never be called to paint with an offset not on device
- // pixels.
- DCHECK(LayoutPoint(IntPoint(paint_offset.X().ToInt(),
- paint_offset.Y().ToInt())) == paint_offset);
-
DCHECK(!layout_view_.GetFrameView()->ShouldThrottleRendering());
- BlockPainter(layout_view_).Paint(paint_info, paint_offset);
+ BlockPainter(layout_view_).Paint(paint_info);
}
void ViewPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info) {
@@ -67,24 +60,16 @@ void ViewPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info) {
const DisplayItemClient* display_item_client = &layout_view_;
base::Optional<ScopedPaintChunkProperties> scoped_scroll_property;
- base::Optional<ScrollRecorder> scroll_recorder;
if (BoxModelObjectPainter::
IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
&layout_view_, paint_info)) {
// Layout overflow, combined with the visible content size.
background_rect.Unite(layout_view_.DocumentRect());
display_item_client = layout_view_.Layer()->GraphicsLayerBacking();
- if (!layout_view_.ScrolledContentOffset().IsZero()) {
- scroll_recorder.emplace(paint_info.context, layout_view_,
- paint_info.phase,
- layout_view_.ScrolledContentOffset());
- }
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- scoped_scroll_property.emplace(
- paint_info.context.GetPaintController(),
- layout_view_.FirstFragment().ContentsProperties(),
- *display_item_client, DisplayItem::kDocumentBackground);
- }
+ scoped_scroll_property.emplace(
+ paint_info.context.GetPaintController(),
+ layout_view_.FirstFragment().ContentsProperties(), *display_item_client,
+ DisplayItem::kDocumentBackground);
}
if (DrawingRecorder::UseCachedDrawingIfPossible(
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 d4006bdc44e..a5fcfbe03b1 100644
--- a/chromium/third_party/blink/renderer/core/paint/view_painter.h
+++ b/chromium/third_party/blink/renderer/core/paint/view_painter.h
@@ -9,7 +9,6 @@
namespace blink {
-class LayoutPoint;
struct PaintInfo;
class LayoutView;
@@ -19,7 +18,7 @@ class ViewPainter {
public:
ViewPainter(const LayoutView& layout_view) : layout_view_(layout_view) {}
- void Paint(const PaintInfo&, const LayoutPoint& paint_offset);
+ void Paint(const PaintInfo&);
void PaintBoxDecorationBackground(const PaintInfo&);
private:
diff --git a/chromium/third_party/blink/renderer/core/paint/view_painter_test.cc b/chromium/third_party/blink/renderer/core/paint/view_painter_test.cc
index 33f180fd6af..ce4b14e41ab 100644
--- a/chromium/third_party/blink/renderer/core/paint/view_painter_test.cc
+++ b/chromium/third_party/blink/renderer/core/paint/view_painter_test.cc
@@ -43,13 +43,12 @@ void ViewPainterTest::RunFixedBackgroundTest(
)HTML");
LocalFrameView* frame_view = GetDocument().View();
- ScrollableArea* layout_viewport = frame_view->LayoutViewportScrollableArea();
+ ScrollableArea* layout_viewport = frame_view->LayoutViewport();
ScrollOffset scroll_offset(200, 150);
layout_viewport->SetScrollOffset(scroll_offset, kUserScroll);
frame_view->UpdateAllLifecyclePhases();
- bool v175 = RuntimeEnabledFeatures::SlimmingPaintV175Enabled();
CompositedLayerMapping* clm =
GetLayoutView().Layer()->GetCompositedLayerMapping();
@@ -64,8 +63,7 @@ void ViewPainterTest::RunFixedBackgroundTest(
}
const DisplayItemList& display_items =
layer_for_background->GetPaintController().GetDisplayItemList();
- const DisplayItem& background =
- display_items[!prefer_compositing_to_lcd_text && !v175 ? 2 : 0];
+ const DisplayItem& background = display_items[0];
EXPECT_EQ(background.GetType(), kDocumentBackgroundType);
DisplayItemClient* expected_client;
if (!prefer_compositing_to_lcd_text)
@@ -112,16 +110,13 @@ TEST_P(ViewPainterTest, DocumentBackgroundWithScroll) {
RootPaintController().GetDisplayItemList(), 1,
TestDisplayItem(*background_item_client, kDocumentBackgroundType));
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
const auto& chunks = RootPaintController().GetPaintArtifact().PaintChunks();
EXPECT_EQ(1u, chunks.size());
const auto& chunk = chunks[0];
EXPECT_EQ(background_chunk_client, &chunk.id.client);
const auto& tree_state = chunk.properties;
- EXPECT_EQ(EffectPaintPropertyNode::Root(), tree_state.Effect());
+ EXPECT_EQ(&EffectPaintPropertyNode::Root(), tree_state.Effect());
const auto* properties = GetLayoutView().FirstFragment().PaintProperties();
EXPECT_EQ(properties->ScrollTranslation(), tree_state.Transform());
EXPECT_EQ(properties->OverflowClip(), tree_state.Clip());
diff --git a/chromium/third_party/blink/renderer/core/policy/policy.cc b/chromium/third_party/blink/renderer/core/policy/policy.cc
index b00ce70e490..83e300686fb 100644
--- a/chromium/third_party/blink/renderer/core/policy/policy.cc
+++ b/chromium/third_party/blink/renderer/core/policy/policy.cc
@@ -25,7 +25,7 @@ bool Policy::allowsFeature(const String& feature) const {
bool Policy::allowsFeature(const String& feature, const String& url) const {
scoped_refptr<const SecurityOrigin> origin =
SecurityOrigin::CreateFromString(url);
- if (!origin || origin->IsUnique()) {
+ if (!origin || origin->IsOpaque()) {
GetDocument()->AddConsoleMessage(ConsoleMessage::Create(
kOtherMessageSource, kWarningMessageLevel,
"Invalid origin url for feature '" + feature + "': " + url + "."));
@@ -78,4 +78,8 @@ void Policy::Trace(blink::Visitor* visitor) {
ScriptWrappable::Trace(visitor);
}
+void Policy::UpdateContainerPolicy(
+ const ParsedFeaturePolicy& container_policy,
+ scoped_refptr<const SecurityOrigin> src_origin) {}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/policy/policy.h b/chromium/third_party/blink/renderer/core/policy/policy.h
index 7c8efed1b44..5e0fccd3ed4 100644
--- a/chromium/third_party/blink/renderer/core/policy/policy.h
+++ b/chromium/third_party/blink/renderer/core/policy/policy.h
@@ -40,7 +40,7 @@ class CORE_EXPORT Policy : public ScriptWrappable {
// changed.
virtual void UpdateContainerPolicy(
const ParsedFeaturePolicy& container_policy = {},
- scoped_refptr<const SecurityOrigin> src_origin = nullptr) {}
+ scoped_refptr<const SecurityOrigin> src_origin = nullptr);
void Trace(blink::Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/core/policy/policy.idl b/chromium/third_party/blink/renderer/core/policy/policy.idl
index ab6fda8d491..d2d5ad3169d 100644
--- a/chromium/third_party/blink/renderer/core/policy/policy.idl
+++ b/chromium/third_party/blink/renderer/core/policy/policy.idl
@@ -8,9 +8,9 @@
// https://docs.google.com/a/chromium.org/document/d/1wvk3cXkblNnbkMcsKayseK-k0SMGiP9b9fQFgfpqQpc/edit?usp=sharing
[
NoInterfaceObject,
- RuntimeEnabled=FeaturePolicyJavaScriptInterface
+ OriginTrialEnabled=FeaturePolicyJavaScriptInterface
] interface Policy {
- boolean allowsFeature(DOMString feature, optional DOMString url);
- sequence<DOMString> allowedFeatures();
- sequence<DOMString> getAllowlistForFeature(DOMString feature);
+ [MeasureAs=FeaturePolicyJSAPI] boolean allowsFeature(DOMString feature, optional DOMString url);
+ [MeasureAs=FeaturePolicyJSAPI] sequence<DOMString> allowedFeatures();
+ [MeasureAs=FeaturePolicyJSAPI] sequence<DOMString> getAllowlistForFeature(DOMString feature);
};
diff --git a/chromium/third_party/blink/renderer/core/policy/policy_test.cc b/chromium/third_party/blink/renderer/core/policy/policy_test.cc
index 4e785fbb903..c218d63ad2d 100644
--- a/chromium/third_party/blink/renderer/core/policy/policy_test.cc
+++ b/chromium/third_party/blink/renderer/core/policy/policy_test.cc
@@ -69,6 +69,8 @@ TEST_F(DocumentPolicyTest, TestAllowsFeature) {
EXPECT_TRUE(GetPolicy()->allowsFeature("camera", kOriginB));
EXPECT_FALSE(GetPolicy()->allowsFeature("camera", "https://badorigin.com"));
EXPECT_TRUE(GetPolicy()->allowsFeature("geolocation", kSelfOrigin));
+ EXPECT_TRUE(GetPolicy()->allowsFeature("sync-xhr"));
+ EXPECT_TRUE(GetPolicy()->allowsFeature("sync-xhr", kOriginA));
}
TEST_F(DocumentPolicyTest, TestGetAllowList) {
@@ -82,6 +84,8 @@ TEST_F(DocumentPolicyTest, TestGetAllowList) {
UnorderedElementsAre("*"));
EXPECT_TRUE(GetPolicy()->getAllowlistForFeature("badfeature").IsEmpty());
EXPECT_TRUE(GetPolicy()->getAllowlistForFeature("midi").IsEmpty());
+ EXPECT_THAT(GetPolicy()->getAllowlistForFeature("sync-xhr"),
+ UnorderedElementsAre("*"));
}
TEST_F(DocumentPolicyTest, TestAllowedFeatures) {
@@ -93,6 +97,8 @@ TEST_F(DocumentPolicyTest, TestAllowedFeatures) {
EXPECT_TRUE(allowed_features.Contains("geolocation"));
EXPECT_FALSE(allowed_features.Contains("badfeature"));
EXPECT_FALSE(allowed_features.Contains("midi"));
+ // "sync-xhr" is allowed on all origins
+ EXPECT_TRUE(allowed_features.Contains("sync-xhr"));
}
TEST_F(IFramePolicyTest, TestAllowsFeature) {
@@ -110,6 +116,8 @@ TEST_F(IFramePolicyTest, TestAllowsFeature) {
EXPECT_FALSE(GetPolicy()->allowsFeature("camera", kOriginB));
EXPECT_FALSE(GetPolicy()->allowsFeature("camera", "https://badorigin.com"));
EXPECT_TRUE(GetPolicy()->allowsFeature("geolocation", kSelfOrigin));
+ EXPECT_TRUE(GetPolicy()->allowsFeature("sync-xhr"));
+ EXPECT_TRUE(GetPolicy()->allowsFeature("sync-xhr", kOriginA));
}
TEST_F(IFramePolicyTest, TestGetAllowList) {
@@ -123,6 +131,8 @@ TEST_F(IFramePolicyTest, TestGetAllowList) {
UnorderedElementsAre(kSelfOrigin));
EXPECT_TRUE(GetPolicy()->getAllowlistForFeature("badfeature").IsEmpty());
EXPECT_TRUE(GetPolicy()->getAllowlistForFeature("midi").IsEmpty());
+ EXPECT_THAT(GetPolicy()->getAllowlistForFeature("sync-xhr"),
+ UnorderedElementsAre("*"));
}
TEST_F(IFramePolicyTest, TestAllowedFeatures) {
@@ -134,6 +144,8 @@ TEST_F(IFramePolicyTest, TestAllowedFeatures) {
EXPECT_TRUE(allowed_features.Contains("geolocation"));
EXPECT_FALSE(allowed_features.Contains("badfeature"));
EXPECT_FALSE(allowed_features.Contains("midi"));
+ // "sync-xhr" is allowed on all origins
+ EXPECT_TRUE(allowed_features.Contains("sync-xhr"));
}
TEST_F(IFramePolicyTest, TestCombinedPolicy) {
@@ -151,6 +163,8 @@ TEST_F(IFramePolicyTest, TestCombinedPolicy) {
EXPECT_TRUE(allowed_features.Contains("camera"));
// "geolocation" has default policy as allowed on self origin.
EXPECT_FALSE(allowed_features.Contains("badfeature"));
+ // "sync-xhr" is still implicitly allowed on all origins
+ EXPECT_TRUE(allowed_features.Contains("sync-xhr"));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/probe/CoreProbes.json5 b/chromium/third_party/blink/renderer/core/probe/CoreProbes.json5
index bee9e5f1153..cfd2cb8a94f 100644
--- a/chromium/third_party/blink/renderer/core/probe/CoreProbes.json5
+++ b/chromium/third_party/blink/renderer/core/probe/CoreProbes.json5
@@ -5,6 +5,11 @@
include_path: "third_party/blink/renderer/core/inspector",
includes: [
"third_party/blink/renderer/core/CoreProbeSink.h",
+ "third_party/blink/renderer/core/animation/animation.h",
+ "third_party/blink/renderer/core/dom/character_data.h",
+ "third_party/blink/renderer/core/dom/pseudo_element.h",
+ "third_party/blink/renderer/core/html/html_slot_element.h",
+ "third_party/blink/renderer/core/page/chrome_client.h",
"third_party/blink/renderer/core/probe/core_probes.h",
],
},
@@ -77,6 +82,10 @@
"willModifyDOMAttr",
"willRemoveDOMNode",
"willSendXMLHttpOrFetchNetworkRequest",
+ "didCreateAudioContext",
+ "didCloseAudioContext",
+ "didResumeAudioContext",
+ "didSuspendAudioContext",
]
},
InspectorDOMSnapshotAgent: {
@@ -87,7 +96,10 @@
},
InspectorEmulationAgent: {
probes: [
+ "applyAcceptLanguageOverride",
+ "applyUserAgentOverride",
"frameStartedLoading",
+ "willSendRequest",
]
},
InspectorLayerTreeAgent: {
@@ -103,18 +115,14 @@
},
InspectorNetworkAgent: {
probes: [
- "applyUserAgentOverride",
- "detachClientRequest",
"didBlockRequest",
"didChangeResourcePriority",
"didCloseWebSocket",
"didCommitLoad",
"didCreateWebSocket",
"didFailLoading",
- "didFailXHRLoading",
- "didFinishEventSourceRequest",
"didFinishLoading",
- "didFinishXHRLoading",
+ "didFinishXHR",
"didReceiveCORSRedirectResponse",
"didReceiveData",
"didReceiveBlob",
@@ -125,8 +133,6 @@
"didReceiveWebSocketFrameError",
"didReceiveWebSocketHandshakeResponse",
"didSendWebSocketFrame",
- "documentThreadableLoaderFailedToStartLoadingForClient",
- "documentThreadableLoaderStartedLoadingForClient",
"frameClearedScheduledClientNavigation",
"frameClearedScheduledNavigation",
"frameScheduledClientNavigation",
@@ -146,6 +152,7 @@
},
InspectorPageAgent: {
probes: [
+ "consumeCompilationCache",
"didChangeViewport",
"didClearDocumentOfWindowObject",
"didNavigateWithinDocument",
@@ -162,6 +169,7 @@
"lifecycleEvent",
"loadEventFired",
"paintTiming",
+ "produceCompilationCache",
"RecalculateStyle",
"UpdateLayout",
"willRunJavaScriptDialog",
diff --git a/chromium/third_party/blink/renderer/core/probe/CoreProbes.pidl b/chromium/third_party/blink/renderer/core/probe/CoreProbes.pidl
index f2c19accddf..719c98ad8c4 100644
--- a/chromium/third_party/blink/renderer/core/probe/CoreProbes.pidl
+++ b/chromium/third_party/blink/renderer/core/probe/CoreProbes.pidl
@@ -59,8 +59,6 @@ interface CoreProbes {
class HTMLDocumentParser;
class ScheduledNavigation;
class ThreadableLoaderClient;
- class WebSocketHandshakeRequest;
- class WebSocketHandshakeResponse;
class WorkerInspectorProxy;
class XMLHttpRequest;
@@ -89,6 +87,7 @@ interface CoreProbes {
void didFireWebGLErrorOrWarning(Element*, const String& message);
void didResizeMainFrame(LocalFrame*);
void didPaint(LocalFrame*, const GraphicsLayer*, GraphicsContext&, const LayoutRect&);
+ void applyAcceptLanguageOverride(LocalFrame*, String* acceptLanguage);
void applyUserAgentOverride(ExecutionContext*, String* userAgent);
void didBlockRequest([Keep] ExecutionContext*, const ResourceRequest&, DocumentLoader*, const FetchInitiatorInfo&, ResourceRequestBlockedReason, Resource::Type);
void didChangeResourcePriority(LocalFrame*, DocumentLoader*, unsigned long identifier, ResourceLoadPriority loadPriority);
@@ -98,20 +97,14 @@ interface CoreProbes {
void didReceiveData(ExecutionContext*, unsigned long identifier, DocumentLoader*, const char* data, int dataLength);
void didReceiveBlob(ExecutionContext*, unsigned long identifier, DocumentLoader*, BlobDataHandle*);
void didReceiveEncodedDataLength(ExecutionContext*, DocumentLoader* loader, unsigned long identifier, int encodedDataLength);
- void didFinishLoading(ExecutionContext*, unsigned long identifier, DocumentLoader*, TimeTicks finishTime, int64_t encoded_data_length, int64_t decodedBodyLength, bool blocked_cross_site_document);
+ void didFinishLoading(ExecutionContext*, unsigned long identifier, DocumentLoader*, TimeTicks finishTime, int64_t encoded_data_length, int64_t decodedBodyLength, bool should_report_corb_blocking);
void didReceiveCORSRedirectResponse(ExecutionContext*, unsigned long identifier, DocumentLoader*, const ResourceResponse&, Resource*);
void didFailLoading(ExecutionContext*, unsigned long identifier, DocumentLoader*, const ResourceError&);
- void documentThreadableLoaderStartedLoadingForClient(ExecutionContext*, unsigned long identifier, ThreadableLoaderClient* client);
- void documentThreadableLoaderFailedToStartLoadingForClient(ExecutionContext*, ThreadableLoaderClient* client);
void willSendEventSourceRequest(ExecutionContext*, ThreadableLoaderClient* eventSource);
void willDispatchEventSourceEvent(ExecutionContext*, unsigned long identifier, const AtomicString& eventName, const AtomicString& eventId, const String& data);
- void didFinishEventSourceRequest(ExecutionContext*, ThreadableLoaderClient* eventSource);
void willLoadXHR(ExecutionContext*, XMLHttpRequest* xhr, ThreadableLoaderClient* client, const AtomicString& method, const KURL& url, bool async, const HTTPHeaderMap& headers, bool includeCredentials);
- void didFailXHRLoading([Keep] ExecutionContext*, XMLHttpRequest* xhr, ThreadableLoaderClient* client, const AtomicString& method, const String& url);
- void didFinishXHRLoading([Keep] ExecutionContext*, XMLHttpRequest* xhr, ThreadableLoaderClient* client, const AtomicString& method, const String& url);
+ void didFinishXHR(ExecutionContext*, XMLHttpRequest* xhr);
void willStartFetch(ExecutionContext*, ThreadableLoaderClient*);
- // Detach and remove all references to the given client.
- void detachClientRequest(ExecutionContext*, ThreadableLoaderClient*);
void scriptImported(ExecutionContext*, unsigned long identifier, const String& sourceString);
void scriptExecutionBlockedByCSP(ExecutionContext*, const String& directiveText);
void didReceiveScriptResponse(ExecutionContext*, unsigned long identifier);
@@ -124,7 +117,7 @@ interface CoreProbes {
void didNavigateWithinDocument([Keep] LocalFrame*);
void frameDocumentUpdated([Keep] LocalFrame*);
void frameOwnerContentUpdated([Keep] LocalFrame*, HTMLFrameOwnerElement*);
- void frameStartedLoading([Keep] LocalFrame*, FrameLoadType);
+ void frameStartedLoading([Keep] LocalFrame*);
void frameStoppedLoading([Keep] LocalFrame*);
void frameScheduledNavigation([Keep] LocalFrame*, ScheduledNavigation*);
void frameClearedScheduledNavigation([Keep] LocalFrame*);
@@ -133,8 +126,8 @@ interface CoreProbes {
void didStartWorker(ExecutionContext*, WorkerInspectorProxy* proxy, bool waitingForDebugger);
void workerTerminated(ExecutionContext*, WorkerInspectorProxy* proxy);
void didCreateWebSocket([Keep] ExecutionContext*, unsigned long identifier, const KURL& requestURL, const String& protocol);
- void willSendWebSocketHandshakeRequest([Keep] ExecutionContext*, unsigned long identifier, const WebSocketHandshakeRequest* request);
- void didReceiveWebSocketHandshakeResponse([Keep] ExecutionContext*, unsigned long identifier, const WebSocketHandshakeRequest* request, const WebSocketHandshakeResponse* response);
+ void willSendWebSocketHandshakeRequest([Keep] ExecutionContext*, unsigned long identifier, network::mojom::blink::WebSocketHandshakeRequest* request);
+ void didReceiveWebSocketHandshakeResponse([Keep] ExecutionContext*, unsigned long identifier, network::mojom::blink::WebSocketHandshakeRequest* request, network::mojom::blink::WebSocketHandshakeResponse* response);
void didCloseWebSocket([Keep] ExecutionContext*, unsigned long identifier);
void didReceiveWebSocketFrame(ExecutionContext*, unsigned long identifier, int opCode, bool masked, const char* payload, size_t payloadLength);
void didSendWebSocketFrame(ExecutionContext*, unsigned long identifier, int opCode, bool masked, const char* payload, size_t payloadLength);
@@ -168,4 +161,10 @@ interface CoreProbes {
void consoleTimeStamp(ExecutionContext*, const String& title);
void lifecycleEvent([Keep] LocalFrame*, DocumentLoader*, const char* name, double timestamp);
void paintTiming([Keep] Document*, const char* name, double timestamp);
+ void didCreateAudioContext(Document*);
+ void didCloseAudioContext(Document*);
+ void didResumeAudioContext(Document*);
+ void didSuspendAudioContext(Document*);
+ void produceCompilationCache(LocalFrame*, const ScriptSourceCode& source, v8::Local<v8::Script> script);
+ void consumeCompilationCache(ExecutionContext*, const ScriptSourceCode& source, v8::ScriptCompiler::CachedData** cached_data);
}
diff --git a/chromium/third_party/blink/renderer/core/probe/core_probes.cc b/chromium/third_party/blink/renderer/core/probe/core_probes.cc
index e838eeb91fc..c45771cf2a9 100644
--- a/chromium/third_party/blink/renderer/core/probe/core_probes.cc
+++ b/chromium/third_party/blink/renderer/core/probe/core_probes.cc
@@ -31,21 +31,9 @@
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
-#include "third_party/blink/renderer/core/CoreProbeSink.h"
-#include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/core/dom/events/event_target.h"
-#include "third_party/blink/renderer/core/inspector/inspector_css_agent.h"
-#include "third_party/blink/renderer/core/inspector/inspector_dom_debugger_agent.h"
-#include "third_party/blink/renderer/core/inspector/inspector_network_agent.h"
-#include "third_party/blink/renderer/core/inspector/inspector_page_agent.h"
-#include "third_party/blink/renderer/core/inspector/inspector_session.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
-#include "third_party/blink/renderer/core/inspector/main_thread_debugger.h"
#include "third_party/blink/renderer/core/inspector/thread_debugger.h"
-#include "third_party/blink/renderer/core/page/page.h"
-#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
-#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_info.h"
namespace blink {
namespace probe {
@@ -126,30 +114,5 @@ void AllAsyncTasksCanceled(ExecutionContext* context) {
debugger->AllAsyncTasksCanceled();
}
-void DidReceiveResourceResponseButCanceled(LocalFrame* frame,
- DocumentLoader* loader,
- unsigned long identifier,
- const ResourceResponse& r,
- Resource* resource) {
- didReceiveResourceResponse(frame->GetDocument(), identifier, loader, r,
- resource);
-}
-
-void CanceledAfterReceivedResourceResponse(LocalFrame* frame,
- DocumentLoader* loader,
- unsigned long identifier,
- const ResourceResponse& r,
- Resource* resource) {
- DidReceiveResourceResponseButCanceled(frame, loader, identifier, r, resource);
-}
-
-void ContinueWithPolicyIgnore(LocalFrame* frame,
- DocumentLoader* loader,
- unsigned long identifier,
- const ResourceResponse& r,
- Resource* resource) {
- DidReceiveResourceResponseButCanceled(frame, loader, identifier, r, resource);
-}
-
} // namespace probe
} // namespace blink
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 7107ee4c97d..8ae705f66c5 100644
--- a/chromium/third_party/blink/renderer/core/probe/core_probes.h
+++ b/chromium/third_party/blink/renderer/core/probe/core_probes.h
@@ -31,19 +31,23 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PROBE_CORE_PROBES_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_PROBE_CORE_PROBES_H_
-#include "third_party/blink/renderer/core/animation/animation.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/dom/pseudo_element.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/core/html/html_slot_element.h"
-#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/platform/probe/platform_probes.h"
+namespace network {
+namespace mojom {
+namespace blink {
+class WebSocketHandshakeResponse;
+class WebSocketHandshakeRequest;
+} // namespace blink
+} // namespace mojom
+} // namespace network
+
namespace blink {
class CoreProbeSink;
-class Resource;
class ThreadDebugger;
namespace probe {
@@ -101,18 +105,7 @@ CORE_EXPORT void AsyncTaskCanceled(v8::Isolate*, void*);
CORE_EXPORT void AsyncTaskCanceledBreakable(ExecutionContext*,
const char* name,
void*);
-
CORE_EXPORT void AllAsyncTasksCanceled(ExecutionContext*);
-CORE_EXPORT void CanceledAfterReceivedResourceResponse(LocalFrame*,
- DocumentLoader*,
- unsigned long identifier,
- const ResourceResponse&,
- Resource*);
-CORE_EXPORT void ContinueWithPolicyIgnore(LocalFrame*,
- DocumentLoader*,
- unsigned long identifier,
- const ResourceResponse&,
- Resource*);
} // namespace probe
} // namespace blink
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 af227168578..33acd56e78e 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
@@ -187,9 +187,4 @@ void ResizeObserver::Trace(blink::Visitor* visitor) {
ContextClient::Trace(visitor);
}
-void ResizeObserver::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(callback_);
- ScriptWrappable::TraceWrappers(visitor);
-}
-
} // namespace blink
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 d90caa2785d..1aaea12270c 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
@@ -62,7 +62,6 @@ class CORE_EXPORT ResizeObserver final
bool HasPendingActivity() const override;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
ResizeObserver(V8ResizeObserverCallback*, Document&);
diff --git a/chromium/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc b/chromium/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc
index 547bfbf2e1b..f73992413f1 100644
--- a/chromium/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc
+++ b/chromium/third_party/blink/renderer/core/scheduler/frame_throttling_test.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "cc/layers/picture_layer.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/web/web_frame_content_dumper.h"
#include "third_party/blink/public/web/web_hit_test_result.h"
@@ -20,6 +21,7 @@
#include "third_party/blink/renderer/core/page/page.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"
#include "third_party/blink/renderer/core/testing/sim/sim_compositor.h"
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
@@ -36,7 +38,7 @@ using namespace HTMLNames;
// NOTE: This test uses <iframe sandbox> to create cross origin iframes.
-class FrameThrottlingTest : public SimTest, public PaintTestConfigurations {
+class FrameThrottlingTest : public PaintTestConfigurations, public SimTest {
protected:
void SetUp() override {
SimTest::SetUp();
@@ -189,7 +191,8 @@ TEST_P(FrameThrottlingTest, IntersectionObservationOverridesThrottling) {
EXPECT_TRUE(inner_frame_document->View()->ShouldThrottleRendering());
// An intersection observation overrides...
- inner_frame_document->View()->SetNeedsIntersectionObservation();
+ inner_frame_document->View()->SetNeedsIntersectionObservation(
+ LocalFrameView::kRequired);
EXPECT_FALSE(inner_frame_document->View()->ShouldThrottleRendering());
inner_frame_document->View()->ScheduleAnimation();
@@ -394,11 +397,8 @@ TEST_P(FrameThrottlingTest, UnthrottlingTriggersRepaint) {
// Scroll down to unthrottle the frame. The first frame we composite after
// scrolling won't contain the frame yet, but will schedule another repaint.
- WebView()
- .MainFrameImpl()
- ->GetFrameView()
- ->LayoutViewportScrollableArea()
- ->SetScrollOffset(ScrollOffset(0, 480), kProgrammaticScroll);
+ WebView().MainFrameImpl()->GetFrameView()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(0, 480), kProgrammaticScroll);
auto commands = CompositeFrame();
EXPECT_FALSE(commands.Contains(SimCanvas::kRect, "green"));
@@ -436,11 +436,8 @@ TEST_P(FrameThrottlingTest, UnthrottlingTriggersRepaintInCompositedChild) {
// Scroll down to unthrottle the frame. The first frame we composite after
// scrolling won't contain the frame yet, but will schedule another repaint.
- WebView()
- .MainFrameImpl()
- ->GetFrameView()
- ->LayoutViewportScrollableArea()
- ->SetScrollOffset(ScrollOffset(0, 480), kProgrammaticScroll);
+ WebView().MainFrameImpl()->GetFrameView()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(0, 480), kProgrammaticScroll);
auto commands = CompositeFrame();
EXPECT_FALSE(commands.Contains(SimCanvas::kRect, "green"));
@@ -472,11 +469,8 @@ TEST_P(FrameThrottlingTest, ChangeStyleInThrottledFrame) {
"background: green");
// Scroll down to unthrottle the frame.
- WebView()
- .MainFrameImpl()
- ->GetFrameView()
- ->LayoutViewportScrollableArea()
- ->SetScrollOffset(ScrollOffset(0, 480), kProgrammaticScroll);
+ WebView().MainFrameImpl()->GetFrameView()->LayoutViewport()->SetScrollOffset(
+ ScrollOffset(0, 480), kProgrammaticScroll);
auto commands = CompositeFrame();
EXPECT_FALSE(commands.Contains(SimCanvas::kRect, "red"));
EXPECT_FALSE(commands.Contains(SimCanvas::kRect, "green"));
@@ -593,26 +587,24 @@ TEST_P(FrameThrottlingTest, ScrollingCoordinatorShouldSkipThrottledFrame) {
frame_element->contentDocument()->body()->setAttribute(styleAttr,
"background: green");
// Change root frame's layout so that the next lifecycle update will call
- // ScrollingCoordinator::updateAfterCompositingChangeIfNeeded().
+ // ScrollingCoordinator::UpdateAfterPaint().
GetDocument().body()->setAttribute(styleAttr, "margin: 20px");
EXPECT_EQ(DocumentLifecycle::kVisualUpdatePending,
frame_element->contentDocument()->Lifecycle().GetState());
DocumentLifecycle::AllowThrottlingScope throttling_scope(
GetDocument().Lifecycle());
- // This will call ScrollingCoordinator::updateAfterCompositingChangeIfNeeded()
- // and should not cause assert failure about
- // isAllowedToQueryCompositingState() in the throttled frame.
+ // This will call ScrollingCoordinator::UpdateAfterPaint() and should not
+ // cause assert failure about isAllowedToQueryCompositingState() in the
+ // throttled frame.
GetDocument().View()->UpdateAllLifecyclePhases();
test::RunPendingTasks();
EXPECT_EQ(DocumentLifecycle::kVisualUpdatePending,
frame_element->contentDocument()->Lifecycle().GetState());
// The fixed background in the throttled sub frame should not cause main
// thread scrolling.
- EXPECT_FALSE(GetDocument()
- .View()
- ->LayoutViewportScrollableArea()
- ->ShouldScrollOnMainThread());
+ EXPECT_FALSE(
+ GetDocument().View()->LayoutViewport()->ShouldScrollOnMainThread());
// Make the frame visible by changing its transform. This doesn't cause a
// layout, but should still unthrottle the frame.
@@ -623,12 +615,10 @@ TEST_P(FrameThrottlingTest, ScrollingCoordinatorShouldSkipThrottledFrame) {
// The fixed background in the throttled sub frame should be considered.
EXPECT_TRUE(frame_element->contentDocument()
->View()
- ->LayoutViewportScrollableArea()
+ ->LayoutViewport()
->ShouldScrollOnMainThread());
- EXPECT_FALSE(GetDocument()
- .View()
- ->LayoutViewportScrollableArea()
- ->ShouldScrollOnMainThread());
+ EXPECT_FALSE(
+ GetDocument().View()->LayoutViewport()->ShouldScrollOnMainThread());
}
TEST_P(FrameThrottlingTest, ScrollingCoordinatorShouldSkipThrottledLayer) {
@@ -661,16 +651,16 @@ TEST_P(FrameThrottlingTest, ScrollingCoordinatorShouldSkipThrottledLayer) {
frame_element->contentDocument()->body()->setAttribute(styleAttr,
"background: green");
// Change root frame's layout so that the next lifecycle update will call
- // ScrollingCoordinator::updateAfterCompositingChangeIfNeeded().
+ // ScrollingCoordinator::UpdateAfterPaint().
GetDocument().body()->setAttribute(styleAttr, "margin: 20px");
EXPECT_EQ(DocumentLifecycle::kVisualUpdatePending,
frame_element->contentDocument()->Lifecycle().GetState());
DocumentLifecycle::AllowThrottlingScope throttling_scope(
GetDocument().Lifecycle());
- // This will call ScrollingCoordinator::updateAfterCompositingChangeIfNeeded()
- // and should not cause assert failure about
- // isAllowedToQueryCompositingState() in the throttled frame.
+ // This will call ScrollingCoordinator::UpdateAfterPaint() and should not
+ // cause an assert failure about isAllowedToQueryCompositingState() in the
+ // throttled frame.
GetDocument().View()->UpdateAllLifecyclePhases();
test::RunPendingTasks();
EXPECT_EQ(DocumentLifecycle::kVisualUpdatePending,
@@ -703,16 +693,16 @@ TEST_P(FrameThrottlingTest,
frame_element->contentDocument()->body()->setAttribute(styleAttr,
"background: green");
// Change root frame's layout so that the next lifecycle update will call
- // ScrollingCoordinator::updateAfterCompositingChangeIfNeeded().
+ // ScrollingCoordinator::UpdateAfterPaint().
GetDocument().body()->setAttribute(styleAttr, "margin: 20px");
EXPECT_EQ(DocumentLifecycle::kVisualUpdatePending,
frame_element->contentDocument()->Lifecycle().GetState());
DocumentLifecycle::AllowThrottlingScope throttling_scope(
GetDocument().Lifecycle());
- // This will call ScrollingCoordinator::updateAfterCompositingChangeIfNeeded()
- // and should not cause assert failure about
- // isAllowedToQueryCompositingState() in the throttled frame.
+ // This will call ScrollingCoordinator::UpdateAfterPaint() and should not
+ // cause an assert failure about isAllowedToQueryCompositingState() in the
+ // throttled frame.
CompositeFrame();
EXPECT_EQ(DocumentLifecycle::kVisualUpdatePending,
frame_element->contentDocument()->Lifecycle().GetState());
@@ -721,12 +711,21 @@ TEST_P(FrameThrottlingTest,
// layout, but should still unthrottle the frame.
frame_element->setAttribute(styleAttr, "transform: translateY(0px)");
CompositeFrame(); // Unthrottle the frame.
+
+ EXPECT_FALSE(
+ frame_element->contentDocument()->View()->ShouldThrottleRendering());
CompositeFrame(); // Handle the pending visual update of the unthrottled
// frame.
EXPECT_EQ(DocumentLifecycle::kPaintClean,
frame_element->contentDocument()->Lifecycle().GetState());
- EXPECT_TRUE(
- frame_element->contentDocument()->View()->UsesCompositedScrolling());
+ // TODO(szager): Re-enable this check for SPv2 when it properly sets the
+ // bits for composited scrolling.
+ if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+ EXPECT_TRUE(frame_element->contentDocument()
+ ->View()
+ ->LayoutViewport()
+ ->UsesCompositedScrolling());
+ }
}
TEST_P(FrameThrottlingTest, UnthrottleByTransformingWithoutLayout) {
diff --git a/chromium/third_party/blink/renderer/core/scheduler/throttling_test.cc b/chromium/third_party/blink/renderer/core/scheduler/throttling_test.cc
index 5b345376b6a..0dd5b4bb449 100644
--- a/chromium/third_party/blink/renderer/core/scheduler/throttling_test.cc
+++ b/chromium/third_party/blink/renderer/core/scheduler/throttling_test.cc
@@ -4,7 +4,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
diff --git a/chromium/third_party/blink/renderer/core/script/BUILD.gn b/chromium/third_party/blink/renderer/core/script/BUILD.gn
index 952d7798233..cd40d444633 100644
--- a/chromium/third_party/blink/renderer/core/script/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/script/BUILD.gn
@@ -18,6 +18,11 @@ blink_core_sources("script") {
"document_write_intervention.h",
"dynamic_module_resolver.cc",
"dynamic_module_resolver.h",
+ "fetch_client_settings_object.h",
+ "fetch_client_settings_object_impl.cc",
+ "fetch_client_settings_object_impl.h",
+ "fetch_client_settings_object_snapshot.cc",
+ "fetch_client_settings_object_snapshot.h",
"html_parser_script_runner.cc",
"html_parser_script_runner.h",
"html_parser_script_runner_host.h",
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 7849261a30b..9ead234760b 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
@@ -81,6 +81,8 @@ ClassicPendingScript::ClassicPendingScript(
options_(options),
base_url_for_inline_script_(
is_external ? KURL() : element->GetDocument().BaseURL()),
+ source_text_for_inline_script_(is_external ? String()
+ : element->TextFromChildren()),
source_location_type_(source_location_type),
is_external_(is_external),
ready_state_(is_external ? kWaitingForResource : kReady),
@@ -252,7 +254,6 @@ ClassicScript* ClassicPendingScript::GetSource(const KURL& document_url,
error_occurred = ErrorOccurred();
if (!is_external_) {
SingleCachedMetadataHandler* cache_handler = nullptr;
- String source = GetElement()->TextFromChildren();
// We only create an inline cache handler for html-embedded scripts, not
// for scripts produced by document.write, or not parser-inserted. This is
// because we expect those to be too dynamic to benefit from caching.
@@ -262,10 +263,11 @@ ClassicScript* ClassicPendingScript::GetSource(const KURL& document_url,
// used for behavioural changes (and if yes, update its documentation), or
// otherwise trigger this behaviour differently.
if (source_location_type_ == ScriptSourceLocationType::kInline) {
- cache_handler =
- GetInlineCacheHandler(source, GetElement()->GetDocument());
+ cache_handler = GetInlineCacheHandler(source_text_for_inline_script_,
+ GetElement()->GetDocument());
}
- ScriptSourceCode source_code(source, source_location_type_, cache_handler,
+ ScriptSourceCode source_code(source_text_for_inline_script_,
+ source_location_type_, cache_handler,
document_url, StartingPosition());
return ClassicScript::Create(source_code, base_url_for_inline_script_,
options_, kSharableCrossOrigin);
@@ -347,7 +349,7 @@ void ClassicPendingScript::AdvanceReadyState(ReadyState new_ready_state) {
// Did we transition into a 'ready' state?
if (IsReady() && !old_is_ready && IsWatchingForLoad())
- Client()->PendingScriptFinished(this);
+ PendingScriptFinished();
// Did we finish streaming?
if (IsCurrentlyStreaming()) {
diff --git a/chromium/third_party/blink/renderer/core/script/classic_pending_script.h b/chromium/third_party/blink/renderer/core/script/classic_pending_script.h
index 41c456ba30c..677b2f9a390 100644
--- a/chromium/third_party/blink/renderer/core/script/classic_pending_script.h
+++ b/chromium/third_party/blink/renderer/core/script/classic_pending_script.h
@@ -119,6 +119,10 @@ class CORE_EXPORT ClassicPendingScript final : public PendingScript,
// https://html.spec.whatwg.org/multipage/webappapis.html#concept-script-base-url
const KURL base_url_for_inline_script_;
+ // "element's child text content" snapshot taken at
+ // #prepare-a-script (Step 4).
+ const String source_text_for_inline_script_;
+
const ScriptSourceLocationType source_location_type_;
const bool is_external_;
ReadyState ready_state_;
diff --git a/chromium/third_party/blink/renderer/core/script/classic_script.h b/chromium/third_party/blink/renderer/core/script/classic_script.h
index 13f2f7cf846..873272c0d98 100644
--- a/chromium/third_party/blink/renderer/core/script/classic_script.h
+++ b/chromium/third_party/blink/renderer/core/script/classic_script.h
@@ -42,7 +42,7 @@ class CORE_EXPORT ClassicScript final : public Script {
ScriptType GetScriptType() const override { return ScriptType::kClassic; }
void RunScript(LocalFrame*, const SecurityOrigin*) const override;
String InlineSourceTextForCSP() const override {
- return script_source_code_.Source();
+ return script_source_code_.Source().ToString();
}
const ScriptSourceCode script_source_code_;
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 a9ff83afe0b..5adaf1b7705 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
@@ -5,16 +5,19 @@
#include "third_party/blink/renderer/core/script/document_modulator_impl.h"
#include "third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
ModulatorImplBase* DocumentModulatorImpl::Create(
- scoped_refptr<ScriptState> script_state,
+ ScriptState* script_state,
ResourceFetcher* resource_fetcher) {
- return new DocumentModulatorImpl(std::move(script_state), resource_fetcher);
+ return new DocumentModulatorImpl(script_state, resource_fetcher);
}
-ModuleScriptFetcher* DocumentModulatorImpl::CreateModuleScriptFetcher() {
+ModuleScriptFetcher* DocumentModulatorImpl::CreateModuleScriptFetcher(
+ ModuleScriptCustomFetchType custom_fetch_type) {
+ DCHECK_EQ(ModuleScriptCustomFetchType::kNone, custom_fetch_type);
return new DocumentModuleScriptFetcher(fetcher_);
}
@@ -23,10 +26,9 @@ void DocumentModulatorImpl::Trace(blink::Visitor* visitor) {
ModulatorImplBase::Trace(visitor);
}
-DocumentModulatorImpl::DocumentModulatorImpl(
- scoped_refptr<ScriptState> script_state,
- ResourceFetcher* resource_fetcher)
- : ModulatorImplBase(std::move(script_state)), fetcher_(resource_fetcher) {
+DocumentModulatorImpl::DocumentModulatorImpl(ScriptState* script_state,
+ ResourceFetcher* resource_fetcher)
+ : ModulatorImplBase(script_state), fetcher_(resource_fetcher) {
DCHECK(fetcher_);
}
diff --git a/chromium/third_party/blink/renderer/core/script/document_modulator_impl.h b/chromium/third_party/blink/renderer/core/script/document_modulator_impl.h
index ea1ed96cf1b..ebadc196ca0 100644
--- a/chromium/third_party/blink/renderer/core/script/document_modulator_impl.h
+++ b/chromium/third_party/blink/renderer/core/script/document_modulator_impl.h
@@ -21,11 +21,11 @@ class ScriptState;
// ModulatorImplBase.
class DocumentModulatorImpl final : public ModulatorImplBase {
public:
- static ModulatorImplBase* Create(scoped_refptr<ScriptState>,
- ResourceFetcher*);
+ static ModulatorImplBase* Create(ScriptState*, ResourceFetcher*);
// Implements Modulator.
- ModuleScriptFetcher* CreateModuleScriptFetcher() override;
+ ModuleScriptFetcher* CreateModuleScriptFetcher(
+ ModuleScriptCustomFetchType) override;
void Trace(blink::Visitor*) override;
@@ -33,7 +33,7 @@ class DocumentModulatorImpl final : public ModulatorImplBase {
// Implements ModulatorImplBase.
bool IsDynamicImportForbidden(String* reason) override;
- DocumentModulatorImpl(scoped_refptr<ScriptState>, ResourceFetcher*);
+ DocumentModulatorImpl(ScriptState*, ResourceFetcher*);
Member<ResourceFetcher> fetcher_;
};
diff --git a/chromium/third_party/blink/renderer/core/script/document_modulator_impl_test.cc b/chromium/third_party/blink/renderer/core/script/document_modulator_impl_test.cc
new file mode 100644
index 00000000000..49d89066d21
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/document_modulator_impl_test.cc
@@ -0,0 +1,98 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/core/script/modulator.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
+
+namespace blink {
+
+class DocumentModulatorImplTest : public PageTestBase {
+ DISALLOW_COPY_AND_ASSIGN(DocumentModulatorImplTest);
+
+ public:
+ DocumentModulatorImplTest() = default;
+ void SetUp() override;
+
+ protected:
+ Persistent<Modulator> modulator_;
+};
+
+void DocumentModulatorImplTest::SetUp() {
+ PageTestBase::SetUp(IntSize(500, 500));
+ ScriptState* script_state = ToScriptStateForMainWorld(&GetFrame());
+ modulator_ = Modulator::From(script_state);
+}
+
+TEST_F(DocumentModulatorImplTest, ResolveModuleSpecifier) {
+ // Taken from examples listed in
+ // https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier
+
+ // "The following are valid module specifiers according to the above
+ // algorithm:"
+ EXPECT_TRUE(
+ modulator_
+ ->ResolveModuleSpecifier("https://example.com/apples.js", NullURL())
+ .IsValid());
+
+ KURL resolved = modulator_->ResolveModuleSpecifier(
+ "http:example.com\\pears.mjs", NullURL());
+ EXPECT_TRUE(resolved.IsValid());
+ EXPECT_EQ("http://example.com/pears.mjs", resolved.GetString());
+
+ KURL base_url(NullURL(), "https://example.com");
+ EXPECT_TRUE(
+ modulator_->ResolveModuleSpecifier("//example.com/", base_url).IsValid());
+ EXPECT_TRUE(
+ modulator_->ResolveModuleSpecifier("./strawberries.js.cgi", base_url)
+ .IsValid());
+ EXPECT_TRUE(
+ modulator_->ResolveModuleSpecifier("../lychees", base_url).IsValid());
+ EXPECT_TRUE(
+ modulator_->ResolveModuleSpecifier("/limes.jsx", base_url).IsValid());
+ EXPECT_TRUE(
+ modulator_
+ ->ResolveModuleSpecifier(
+ "data:text/javascript,export default 'grapes';", NullURL())
+ .IsValid());
+ EXPECT_TRUE(
+ modulator_
+ ->ResolveModuleSpecifier(
+ "blob:https://whatwg.org/d0360e2f-caee-469f-9a2f-87d5b0456f6f",
+ KURL())
+ .IsValid());
+
+ // "The following are valid module specifiers according to the above
+ // algorithm, but will invariably cause failures when they are fetched:"
+ EXPECT_TRUE(modulator_
+ ->ResolveModuleSpecifier(
+ "javascript:export default 'artichokes';", NullURL())
+ .IsValid());
+ EXPECT_TRUE(modulator_
+ ->ResolveModuleSpecifier(
+ "data:text/plain,export default 'kale';", NullURL())
+ .IsValid());
+ EXPECT_TRUE(
+ modulator_->ResolveModuleSpecifier("about:legumes", NullURL()).IsValid());
+ EXPECT_TRUE(
+ modulator_->ResolveModuleSpecifier("wss://example.com/celery", NullURL())
+ .IsValid());
+
+ // "The following are not valid module specifiers according to the above
+ // algorithm:"
+ EXPECT_FALSE(
+ modulator_->ResolveModuleSpecifier("https://f:b/c", NullURL()).IsValid());
+ EXPECT_FALSE(
+ modulator_->ResolveModuleSpecifier("pumpkins.js", NullURL()).IsValid());
+
+ // Unprefixed module specifiers should still fail w/ a valid baseURL.
+ EXPECT_FALSE(
+ modulator_->ResolveModuleSpecifier("avocados.js", base_url).IsValid());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/script/document_write_intervention.cc b/chromium/third_party/blink/renderer/core/script/document_write_intervention.cc
index ff23cea0b9b..69277a5e13d 100644
--- a/chromium/third_party/blink/renderer/core/script/document_write_intervention.cc
+++ b/chromium/third_party/blink/renderer/core/script/document_write_intervention.cc
@@ -168,7 +168,7 @@ bool MaybeDisallowFetchForDocWrittenScript(FetchParameters& params,
// Do not block scripts if it is a page reload. This is to enable pages to
// recover if blocking of a script is leading to a page break and the user
// reloads the page.
- const FrameLoadType load_type = document.Loader()->LoadType();
+ const WebFrameLoadType load_type = document.Loader()->LoadType();
if (IsReloadLoadType(load_type)) {
// Recording this metric since an increase in number of reloads for pages
// where a script was blocked could be indicative of a page break.
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 b6fa9c62c5e..6a1f8285495 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
@@ -5,12 +5,13 @@
#include "third_party/blink/renderer/core/script/dynamic_module_resolver.h"
#include "third_party/blink/public/platform/web_url_request.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/referrer_script_info.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/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/script/module_script.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
#include "v8/include/v8.h"
@@ -174,7 +175,7 @@ void DynamicModuleResolver::ResolveDynamically(
}
DCHECK(!base_url.IsNull());
- KURL url = Modulator::ResolveModuleSpecifier(specifier, base_url);
+ KURL url = modulator_->ResolveModuleSpecifier(specifier, base_url);
if (!url.IsValid()) {
// Step 2.2.1. "If the result is failure, then:" [spec text]
// Step 2.2.2.1. "Let completion be Completion { [[Type]]: throw, [[Value]]:
@@ -206,15 +207,22 @@ void DynamicModuleResolver::ResolveDynamically(
// string.</spec>
ScriptFetchOptions options(referrer_info.Nonce(), IntegrityMetadataSet(),
String(), referrer_info.ParserState(),
- referrer_info.CredentialsMode());
+ referrer_info.CredentialsMode(),
+ referrer_info.GetReferrerPolicy());
// Step 2.4. "Fetch a module script graph given url, settings object,
// "script", and options. Wait until the algorithm asynchronously completes
// with result."
auto* tree_client =
DynamicImportTreeClient::Create(url, modulator_.Get(), promise_resolver);
- modulator_->FetchTree(url, WebURLRequest::kRequestContextScript, options,
- tree_client);
+ // TODO(kouhei): ExecutionContext::From(modulator_->GetScriptState()) is
+ // highly discouraged since it breaks layering. Rewrite this.
+ auto* execution_context =
+ ExecutionContext::From(modulator_->GetScriptState());
+ modulator_->FetchTree(
+ url, new FetchClientSettingsObjectSnapshot(*execution_context),
+ WebURLRequest::kRequestContextScript, options,
+ ModuleScriptCustomFetchType::kNone, tree_client);
// Steps 2.[5-8] are implemented at
// DynamicImportTreeClient::NotifyModuleLoadFinished.
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 dc92c1f3849..555574abd02 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
@@ -51,8 +51,7 @@ class DynamicModuleResolverTestModulator final : public DummyModulator {
private:
// Implements Modulator:
- ReferrerPolicy GetReferrerPolicy() override { return kReferrerPolicyDefault; }
- ScriptState* GetScriptState() final { return script_state_.get(); }
+ ScriptState* GetScriptState() final { return script_state_; }
ModuleScript* GetFetchedModuleScript(const KURL& url) final {
EXPECT_EQ(TestReferrerURL(), url);
@@ -61,12 +60,27 @@ class DynamicModuleResolverTestModulator final : public DummyModulator {
return module_script;
}
+ KURL ResolveModuleSpecifier(const String& module_request,
+ const KURL& base_url,
+ String* failure_reason) final {
+ if (module_request == "invalid-specifier")
+ return KURL();
+
+ return KURL(base_url, module_request);
+ }
+
void FetchTree(const KURL& url,
+ FetchClientSettingsObjectSnapshot*,
WebURLRequest::RequestContext,
const ScriptFetchOptions&,
+ ModuleScriptCustomFetchType custom_fetch_type,
ModuleTreeClient* client) final {
EXPECT_EQ(expected_fetch_tree_url_, url);
+ // Currently there are no usage of custom fetch hooks for dynamic import in
+ // web specifications.
+ EXPECT_EQ(ModuleScriptCustomFetchType::kNone, custom_fetch_type);
+
pending_client_ = client;
fetch_tree_was_called_ = true;
}
@@ -75,17 +89,18 @@ class DynamicModuleResolverTestModulator final : public DummyModulator {
CaptureEvalErrorFlag capture_error) final {
EXPECT_EQ(CaptureEvalErrorFlag::kCapture, capture_error);
- ScriptState::Scope scope(script_state_.get());
- return module_script->Record().Evaluate(script_state_.get());
+ ScriptState::Scope scope(script_state_);
+ return module_script->Record().Evaluate(script_state_);
}
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
Member<ModuleTreeClient> pending_client_;
KURL expected_fetch_tree_url_;
bool fetch_tree_was_called_ = false;
};
void DynamicModuleResolverTestModulator::Trace(blink::Visitor* visitor) {
+ visitor->Trace(script_state_);
visitor->Trace(pending_client_);
DummyModulator::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object.h b/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object.h
new file mode 100644
index 00000000000..7bd44067b25
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object.h
@@ -0,0 +1,55 @@
+// 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_SCRIPT_FETCH_CLIENT_SETTINGS_OBJECT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_FETCH_CLIENT_SETTINGS_OBJECT_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/cross_thread_copier.h"
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/weborigin/referrer_policy.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+
+namespace blink {
+
+// This is a partial interface of the "settings object" concept defined in the
+// HTML spec:
+// https://html.spec.whatwg.org/multipage/webappapis.html#settings-object
+//
+// This is also a partial interface of the "fetch client settings object" used
+// in module script fetch. Other part of the "fetch client settings object" is
+// currently implemented by ResourceFetcher and FetchContext, and this class is
+// used together with them.
+// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-module-worker-script-tree
+class CORE_EXPORT FetchClientSettingsObject
+ : public GarbageCollectedFinalized<FetchClientSettingsObject> {
+ public:
+ virtual ~FetchClientSettingsObject() = default;
+
+ // "A URL used by APIs called by scripts that use this environment settings
+ // object to parse URLs."
+ // https://html.spec.whatwg.org/multipage/webappapis.html#api-base-url
+ virtual const KURL& BaseURL() const = 0;
+
+ // "An origin used in security checks."
+ // https://html.spec.whatwg.org/multipage/webappapis.html#concept-settings-object-origin
+ virtual const SecurityOrigin* GetSecurityOrigin() const = 0;
+
+ // "The default referrer policy for fetches performed using this environment
+ // settings object as a request client."
+ // https://html.spec.whatwg.org/multipage/webappapis.html#concept-settings-object-referrer-policy
+ virtual ReferrerPolicy GetReferrerPolicy() const = 0;
+
+ // "referrerURL" used in the "Determine request's Referrer" algorithm:
+ // https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer
+ virtual const String GetOutgoingReferrer() const = 0;
+
+ virtual void Trace(Visitor*) {}
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_FETCH_CLIENT_SETTINGS_OBJECT_H_
diff --git a/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.cc b/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.cc
new file mode 100644
index 00000000000..36257cd0a42
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.cc
@@ -0,0 +1,42 @@
+// 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/script/fetch_client_settings_object_impl.h"
+
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+
+namespace blink {
+
+FetchClientSettingsObjectImpl::FetchClientSettingsObjectImpl(
+ ExecutionContext& execution_context)
+ : execution_context_(execution_context) {
+ DCHECK(execution_context_->IsContextThread());
+}
+
+const KURL& FetchClientSettingsObjectImpl::BaseURL() const {
+ DCHECK(execution_context_->IsContextThread());
+ return execution_context_->BaseURL();
+}
+
+const SecurityOrigin* FetchClientSettingsObjectImpl::GetSecurityOrigin() const {
+ DCHECK(execution_context_->IsContextThread());
+ return execution_context_->GetSecurityOrigin();
+}
+
+ReferrerPolicy FetchClientSettingsObjectImpl::GetReferrerPolicy() const {
+ DCHECK(execution_context_->IsContextThread());
+ return execution_context_->GetReferrerPolicy();
+}
+
+const String FetchClientSettingsObjectImpl::GetOutgoingReferrer() const {
+ DCHECK(execution_context_->IsContextThread());
+ return execution_context_->OutgoingReferrer();
+}
+
+void FetchClientSettingsObjectImpl::Trace(Visitor* visitor) {
+ visitor->Trace(execution_context_);
+ FetchClientSettingsObject::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h b/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h
new file mode 100644
index 00000000000..7f1e29c1ceb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h
@@ -0,0 +1,46 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_FETCH_CLIENT_SETTINGS_OBJECT_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_FETCH_CLIENT_SETTINGS_OBJECT_IMPL_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object.h"
+#include "third_party/blink/renderer/platform/cross_thread_copier.h"
+#include "third_party/blink/renderer/platform/heap/member.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/weborigin/referrer_policy.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+
+namespace blink {
+
+class ExecutionContext;
+
+// This is an implementation of FetchClientSettingsObject. As opposed to
+// FetchClientSettingsObjectSnapshot, this refers to up-to-date values of the
+// settings object.
+//
+// This class should be used for resource loading other than main worker
+// (worklet) scripts. For the main scripts, FetchClientSettingsObjectSnapshot
+// should be used. See the class level comments on that class.
+class CORE_EXPORT FetchClientSettingsObjectImpl final
+ : public FetchClientSettingsObject {
+ public:
+ explicit FetchClientSettingsObjectImpl(ExecutionContext&);
+ ~FetchClientSettingsObjectImpl() override = default;
+
+ const KURL& BaseURL() const override;
+ const SecurityOrigin* GetSecurityOrigin() const override;
+ ReferrerPolicy GetReferrerPolicy() const override;
+ const String GetOutgoingReferrer() const override;
+
+ void Trace(Visitor* visitor) override;
+
+ private:
+ Member<ExecutionContext> execution_context_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_FETCH_CLIENT_SETTINGS_OBJECT_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.cc b/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.cc
new file mode 100644
index 00000000000..707dde6e9cb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.cc
@@ -0,0 +1,35 @@
+// 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/script/fetch_client_settings_object_snapshot.h"
+
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+
+namespace blink {
+
+FetchClientSettingsObjectSnapshot::FetchClientSettingsObjectSnapshot(
+ ExecutionContext& execution_context)
+ : FetchClientSettingsObjectSnapshot(execution_context.BaseURL(),
+ execution_context.GetSecurityOrigin(),
+ execution_context.GetReferrerPolicy(),
+ execution_context.OutgoingReferrer()) {}
+
+FetchClientSettingsObjectSnapshot::FetchClientSettingsObjectSnapshot(
+ std::unique_ptr<CrossThreadFetchClientSettingsObjectData> data)
+ : FetchClientSettingsObjectSnapshot(data->base_url,
+ data->security_origin,
+ data->referrer_policy,
+ data->outgoing_referrer) {}
+
+FetchClientSettingsObjectSnapshot::FetchClientSettingsObjectSnapshot(
+ const KURL& base_url,
+ const scoped_refptr<const SecurityOrigin> security_origin,
+ ReferrerPolicy referrer_policy,
+ const String& outgoing_referrer)
+ : base_url_(base_url),
+ security_origin_(std::move(security_origin)),
+ referrer_policy_(referrer_policy),
+ outgoing_referrer_(outgoing_referrer) {}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h b/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h
new file mode 100644
index 00000000000..a38cfd7b342
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h
@@ -0,0 +1,97 @@
+// 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_SCRIPT_FETCH_CLIENT_SETTINGS_OBJECT_SNAPSHOT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_FETCH_CLIENT_SETTINGS_OBJECT_SNAPSHOT_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object.h"
+#include "third_party/blink/renderer/platform/cross_thread_copier.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/weborigin/referrer_policy.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+
+namespace blink {
+
+class ExecutionContext;
+
+// This class is needed to copy a FetchClientSettingsObjectSnapshot across
+// threads, because it has some members which cannot be transferred across
+// threads (AtomicString for example).
+// There are some rules / restrictions:
+// - This struct cannot contain an object that cannot be transferred across
+// threads (e.g., AtomicString)
+// - Non-simple members need explicit copying (e.g., String::IsolatedCopy,
+// KURL::Copy) rather than the copy constructor or the assignment operator.
+struct CrossThreadFetchClientSettingsObjectData {
+ WTF_MAKE_NONCOPYABLE(CrossThreadFetchClientSettingsObjectData);
+ USING_FAST_MALLOC(CrossThreadFetchClientSettingsObjectData);
+
+ public:
+ CrossThreadFetchClientSettingsObjectData(
+ KURL base_url,
+ scoped_refptr<const SecurityOrigin> security_origin,
+ ReferrerPolicy referrer_policy,
+ String outgoing_referrer)
+ : base_url(std::move(base_url)),
+ security_origin(std::move(security_origin)),
+ referrer_policy(referrer_policy),
+ outgoing_referrer(std::move(outgoing_referrer)) {}
+
+ KURL base_url;
+ scoped_refptr<const SecurityOrigin> security_origin;
+ ReferrerPolicy referrer_policy;
+ String outgoing_referrer;
+};
+
+// This takes a partial snapshot of the execution context's states so that an
+// instance of this class can be passed to another thread without cross-thread
+// synchronization. Don't keep this object persistently, instead create a new
+// instance per each "fetch a module script graph" algorithm:
+// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-module-script-tree
+// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-module-worker-script-tree
+//
+// This class should be used only for main worker (worklet) script loading. For
+// other resources, FetchClientSettingsObjectImpl should be used. See the class
+// level comments on that class.
+class CORE_EXPORT FetchClientSettingsObjectSnapshot final
+ : public FetchClientSettingsObject {
+ public:
+ explicit FetchClientSettingsObjectSnapshot(ExecutionContext&);
+ explicit FetchClientSettingsObjectSnapshot(
+ std::unique_ptr<CrossThreadFetchClientSettingsObjectData>);
+ FetchClientSettingsObjectSnapshot(
+ const KURL& base_url,
+ const scoped_refptr<const SecurityOrigin> security_origin,
+ ReferrerPolicy referrer_policy,
+ const String& outgoing_referrer);
+
+ ~FetchClientSettingsObjectSnapshot() override = default;
+
+ const KURL& BaseURL() const override { return base_url_; }
+ const SecurityOrigin* GetSecurityOrigin() const override {
+ return security_origin_.get();
+ }
+ ReferrerPolicy GetReferrerPolicy() const override { return referrer_policy_; }
+ const String GetOutgoingReferrer() const override {
+ return outgoing_referrer_;
+ }
+
+ // Gets a copy of the data suitable for passing to another thread.
+ std::unique_ptr<CrossThreadFetchClientSettingsObjectData> CopyData() const {
+ return std::make_unique<CrossThreadFetchClientSettingsObjectData>(
+ base_url_.Copy(), security_origin_->IsolatedCopy(), referrer_policy_,
+ outgoing_referrer_.IsolatedCopy());
+ }
+
+ private:
+ const KURL base_url_;
+ const scoped_refptr<const SecurityOrigin> security_origin_;
+ const ReferrerPolicy referrer_policy_;
+ const String outgoing_referrer_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_FETCH_CLIENT_SETTINGS_OBJECT_SNAPSHOT_H_
diff --git a/chromium/third_party/blink/renderer/core/script/html_parser_script_runner.cc b/chromium/third_party/blink/renderer/core/script/html_parser_script_runner.cc
index e93f3e8ccff..8fa3c5aa45a 100644
--- a/chromium/third_party/blink/renderer/core/script/html_parser_script_runner.cc
+++ b/chromium/third_party/blink/renderer/core/script/html_parser_script_runner.cc
@@ -563,11 +563,5 @@ void HTMLParserScriptRunner::Trace(blink::Visitor* visitor) {
visitor->Trace(scripts_to_execute_after_parsing_);
PendingScriptClient::Trace(visitor);
}
-void HTMLParserScriptRunner::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(parser_blocking_script_);
- for (const auto& member : scripts_to_execute_after_parsing_)
- visitor->TraceWrappers(member);
-}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/script/html_parser_script_runner.h b/chromium/third_party/blink/renderer/core/script/html_parser_script_runner.h
index 5a2935c31f1..a5e1596e083 100644
--- a/chromium/third_party/blink/renderer/core/script/html_parser_script_runner.h
+++ b/chromium/third_party/blink/renderer/core/script/html_parser_script_runner.h
@@ -31,7 +31,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_streamer.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_reentry_permit.h"
#include "third_party/blink/renderer/core/script/pending_script.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
@@ -57,7 +57,7 @@ class ScriptLoader;
class HTMLParserScriptRunner final
: public GarbageCollectedFinalized<HTMLParserScriptRunner>,
public PendingScriptClient,
- public TraceWrapperBase {
+ public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(HTMLParserScriptRunner);
public:
@@ -98,7 +98,6 @@ class HTMLParserScriptRunner final
}
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "HTMLParserScriptRunner";
}
diff --git a/chromium/third_party/blink/renderer/core/script/layered_api.cc b/chromium/third_party/blink/renderer/core/script/layered_api.cc
index 55b3c54c8f2..9460bb6fc00 100644
--- a/chromium/third_party/blink/renderer/core/script/layered_api.cc
+++ b/chromium/third_party/blink/renderer/core/script/layered_api.cc
@@ -29,17 +29,19 @@ const LayeredAPIResource kLayeredAPIResources[] = {
{"async-local-storage/index.js",
IDR_LAYERED_API_ASYNC_LOCAL_STORAGE_INDEX_JS},
- {"virtual-list/index.js", IDR_LAYERED_API_VIRTUAL_LIST_INDEX_JS},
- {"virtual-list/layouts/layout-1d-base.js",
- IDR_LAYERED_API_VIRTUAL_LIST_LAYOUTS_LAYOUT_1D_BASE_JS},
- {"virtual-list/layouts/layout-1d-grid.js",
- IDR_LAYERED_API_VIRTUAL_LIST_LAYOUTS_LAYOUT_1D_GRID_JS},
- {"virtual-list/layouts/layout-1d.js",
- IDR_LAYERED_API_VIRTUAL_LIST_LAYOUTS_LAYOUT_1D_JS},
- {"virtual-list/virtual-list.js",
- IDR_LAYERED_API_VIRTUAL_LIST_VIRTUAL_LIST_JS},
- {"virtual-list/virtual-repeater.js",
- IDR_LAYERED_API_VIRTUAL_LIST_VIRTUAL_REPEATER_JS},
+ {"virtual-scroller/index.js", IDR_LAYERED_API_VIRTUAL_SCROLLER_INDEX_JS},
+ {"virtual-scroller/item-source.js",
+ IDR_LAYERED_API_VIRTUAL_SCROLLER_ITEM_SOURCE_JS},
+ {"virtual-scroller/layouts/layout-1d-base.js",
+ IDR_LAYERED_API_VIRTUAL_SCROLLER_LAYOUTS_LAYOUT_1D_BASE_JS},
+ {"virtual-scroller/layouts/layout-1d-grid.js",
+ IDR_LAYERED_API_VIRTUAL_SCROLLER_LAYOUTS_LAYOUT_1D_GRID_JS},
+ {"virtual-scroller/layouts/layout-1d.js",
+ IDR_LAYERED_API_VIRTUAL_SCROLLER_LAYOUTS_LAYOUT_1D_JS},
+ {"virtual-scroller/virtual-scroller.js",
+ IDR_LAYERED_API_VIRTUAL_SCROLLER_VIRTUAL_SCROLLER_JS},
+ {"virtual-scroller/virtual-repeater.js",
+ IDR_LAYERED_API_VIRTUAL_SCROLLER_VIRTUAL_REPEATER_JS},
};
int GetResourceIDFromPath(const String& path) {
diff --git a/chromium/third_party/blink/renderer/core/script/modulator.cc b/chromium/third_party/blink/renderer/core/script/modulator.cc
index ab4eca33c47..ee333a718a5 100644
--- a/chromium/third_party/blink/renderer/core/script/modulator.cc
+++ b/chromium/third_party/blink/renderer/core/script/modulator.cc
@@ -9,7 +9,6 @@
#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/document_modulator_impl.h"
-#include "third_party/blink/renderer/core/script/layered_api.h"
#include "third_party/blink/renderer/core/script/worker_modulator_impl.h"
#include "third_party/blink/renderer/core/script/worklet_modulator_impl.h"
#include "third_party/blink/renderer/core/workers/worklet_global_scope.h"
@@ -80,52 +79,4 @@ void Modulator::ClearModulator(ScriptState* script_state) {
per_context_data->ClearData(kPerContextDataKey);
}
-// https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier
-KURL Modulator::ResolveModuleSpecifier(const String& module_request,
- const KURL& base_url,
- String* failure_reason) {
- // <spec step="1">Apply the URL parser to specifier. If the result is not
- // failure, return the result.</spec>
- KURL url(NullURL(), module_request);
- if (url.IsValid()) {
- // <spec
- // href="https://github.com/drufball/layered-apis/blob/master/spec.md#resolve-a-module-specifier"
- // step="1">Let parsed be the result of applying the URL parser to
- // specifier. If parsed is not failure, then return the layered API fetching
- // URL given parsed and script's base URL.</spec>
- if (RuntimeEnabledFeatures::LayeredAPIEnabled())
- return blink::layered_api::ResolveFetchingURL(url, base_url);
-
- return url;
- }
-
- // <spec step="2">If specifier does not start with the character U+002F
- // SOLIDUS (/), the two-character sequence U+002E FULL STOP, U+002F SOLIDUS
- // (./), or the three-character sequence U+002E FULL STOP, U+002E FULL STOP,
- // U+002F SOLIDUS (../), return failure.</spec>
- //
- // (../), return failure and abort these steps." [spec text]
- if (!module_request.StartsWith("/") && !module_request.StartsWith("./") &&
- !module_request.StartsWith("../")) {
- if (failure_reason) {
- *failure_reason =
- "Relative references must start with either \"/\", \"./\", or "
- "\"../\".";
- }
- return KURL();
- }
-
- // <spec step="3">Return the result of applying the URL parser to specifier
- // with script's base URL as the base URL.</spec>
- DCHECK(base_url.IsValid());
- KURL absolute_url(base_url, module_request);
- if (absolute_url.IsValid())
- return absolute_url;
-
- if (failure_reason) {
- *failure_reason = "Invalid relative url or base scheme isn't hierarchical.";
- }
- return KURL();
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/script/modulator.h b/chromium/third_party/blink/renderer/core/script/modulator.h
index 57824d39067..9e4ab29af45 100644
--- a/chromium/third_party/blink/renderer/core/script/modulator.h
+++ b/chromium/third_party/blink/renderer/core/script/modulator.h
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_module.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/script/module_import_meta.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -22,28 +23,25 @@
namespace blink {
-class ExceptionState;
+class FetchClientSettingsObjectSnapshot;
class ModuleScript;
class ModuleScriptFetchRequest;
class ModuleScriptFetcher;
-class ModuleScriptLoaderClient;
class ReferrerScriptInfo;
class ScriptModuleResolver;
class ScriptPromiseResolver;
class ScriptState;
class ScriptValue;
-class SecurityOrigin;
// A SingleModuleClient is notified when single module script node (node as in a
// module tree graph) load is complete and its corresponding entry is created in
// module map.
class CORE_EXPORT SingleModuleClient
: public GarbageCollectedFinalized<SingleModuleClient>,
- public TraceWrapperBase {
+ public NameClient {
public:
virtual ~SingleModuleClient() = default;
virtual void Trace(blink::Visitor* visitor) {}
- void TraceWrappers(ScriptWrappableVisitor*) const override {}
const char* NameInHeapSnapshot() const override {
return "SingleModuleClient";
}
@@ -55,11 +53,10 @@ class CORE_EXPORT SingleModuleClient
// tree load is complete.
class CORE_EXPORT ModuleTreeClient
: public GarbageCollectedFinalized<ModuleTreeClient>,
- public TraceWrapperBase {
+ public NameClient {
public:
virtual ~ModuleTreeClient() = default;
virtual void Trace(blink::Visitor* visitor) {}
- void TraceWrappers(ScriptWrappableVisitor*) const override {}
const char* NameInHeapSnapshot() const override { return "ModuleTreeClient"; }
virtual void NotifyModuleTreeLoadFinished(ModuleScript*) = 0;
@@ -69,6 +66,23 @@ class CORE_EXPORT ModuleTreeClient
// https://html.spec.whatwg.org/multipage/webappapis.html#fetching-scripts-is-top-level
enum class ModuleGraphLevel { kTopLevelModuleFetch, kDependentModuleFetch };
+// spec: "custom peform the fetch hook"
+// https://html.spec.whatwg.org/multipage/webappapis.html#fetching-scripts-perform-fetch
+enum class ModuleScriptCustomFetchType {
+ // Fetch module scripts without invoking custom fetch steps.
+ kNone,
+
+ // Perform custom fetch steps for worker's constructor defined in the HTML
+ // spec:
+ // https://html.spec.whatwg.org/multipage/workers.html#worker-processing-model
+ kWorkerConstructor,
+
+ // Perform custom fetch steps for Worklet's addModule() function defined in
+ // the Worklet spec:
+ // https://drafts.css-houdini.org/worklets/#fetch-a-worklet-script
+ kWorkletAddModule
+};
+
// A Modulator is an interface for "environment settings object" concept for
// module scripts.
// https://html.spec.whatwg.org/multipage/webappapis.html#environment-settings-object
@@ -76,7 +90,7 @@ enum class ModuleGraphLevel { kTopLevelModuleFetch, kDependentModuleFetch };
// A Modulator also serves as an entry point for various module spec algorithms.
class CORE_EXPORT Modulator : public GarbageCollectedFinalized<Modulator>,
public V8PerContextData::Data,
- public TraceWrapperBase {
+ public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(Modulator);
public:
@@ -87,35 +101,43 @@ class CORE_EXPORT Modulator : public GarbageCollectedFinalized<Modulator>,
static void ClearModulator(ScriptState*);
void Trace(blink::Visitor* visitor) override {}
- void TraceWrappers(ScriptWrappableVisitor*) const override {}
const char* NameInHeapSnapshot() const override { return "Modulator"; }
virtual ScriptModuleResolver* GetScriptModuleResolver() = 0;
virtual base::SingleThreadTaskRunner* TaskRunner() = 0;
- virtual ReferrerPolicy GetReferrerPolicy() = 0;
-
- // Returns the security origin of the "fetch client settings object".
- // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-module-worker-script-tree
- // This should be called only from ModuleScriptLoader.
- virtual const SecurityOrigin* GetSecurityOriginForFetch() = 0;
virtual ScriptState* GetScriptState() = 0;
+ // https://html.spec.whatwg.org/multipage/webappapis.html#concept-bc-noscript
+ // "scripting is disabled for settings's responsible browsing context"
+ virtual bool IsScriptingDisabled() const = 0;
+
// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-module-script-tree
- virtual void FetchTree(const KURL&,
- WebURLRequest::RequestContext destination,
- const ScriptFetchOptions&,
- ModuleTreeClient*) = 0;
+ // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-module-worker-script-tree
+ // Note that |this| is the "module map settings object" used in the "fetch a
+ // module worker script graph" algorithm.
+ virtual void FetchTree(
+ const KURL&,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
+ WebURLRequest::RequestContext destination,
+ const ScriptFetchOptions&,
+ ModuleScriptCustomFetchType,
+ ModuleTreeClient*) = 0;
// Asynchronously retrieve a module script from the module map, or fetch it
// and put it in the map if it's not there already.
// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script
- virtual void FetchSingle(const ModuleScriptFetchRequest&,
- ModuleGraphLevel,
- SingleModuleClient*) = 0;
+ // Note that |this| is the "module map settings object".
+ virtual void FetchSingle(
+ const ModuleScriptFetchRequest&,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
+ ModuleGraphLevel,
+ ModuleScriptCustomFetchType,
+ SingleModuleClient*) = 0;
virtual void FetchDescendantsForInlineScript(
ModuleScript*,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
WebURLRequest::RequestContext destination,
ModuleTreeClient*) = 0;
@@ -126,9 +148,9 @@ class CORE_EXPORT Modulator : public GarbageCollectedFinalized<Modulator>,
virtual ModuleScript* GetFetchedModuleScript(const KURL&) = 0;
// https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier
- static KURL ResolveModuleSpecifier(const String& module_request,
- const KURL& base_url,
- String* failure_reason = nullptr);
+ virtual KURL ResolveModuleSpecifier(const String& module_request,
+ const KURL& base_url,
+ String* failure_reason = nullptr) = 0;
// https://tc39.github.io/proposal-dynamic-import/#sec-hostimportmoduledynamically
virtual void ResolveDynamically(const String& specifier,
@@ -141,14 +163,6 @@ class CORE_EXPORT Modulator : public GarbageCollectedFinalized<Modulator>,
virtual bool HasValidContext() = 0;
- virtual ScriptModule CompileModule(const String& script,
- const KURL& source_url,
- const KURL& base_url,
- const ScriptFetchOptions&,
- AccessControlStatus,
- const TextPosition&,
- ExceptionState&) = 0;
-
virtual ScriptValue InstantiateModule(ScriptModule) = 0;
struct ModuleRequest {
@@ -174,18 +188,8 @@ class CORE_EXPORT Modulator : public GarbageCollectedFinalized<Modulator>,
virtual ScriptValue ExecuteModule(const ModuleScript*,
CaptureEvalErrorFlag) = 0;
- virtual ModuleScriptFetcher* CreateModuleScriptFetcher() = 0;
-
- private:
- friend class ModuleMap;
-
- // Fetches a single module script.
- // This is triggered from fetchSingle() implementation (which is in ModuleMap)
- // if the cached entry doesn't exist.
- // The client can be notified either synchronously or asynchronously.
- virtual void FetchNewSingleModule(const ModuleScriptFetchRequest&,
- ModuleGraphLevel,
- ModuleScriptLoaderClient*) = 0;
+ virtual ModuleScriptFetcher* CreateModuleScriptFetcher(
+ ModuleScriptCustomFetchType) = 0;
};
} // namespace blink
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 cbb276012fb..13915b3d97e 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
@@ -8,9 +8,11 @@
#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/loader/modulescript/module_script_fetch_request.h"
-#include "third_party/blink/renderer/core/loader/modulescript/module_script_loader_registry.h"
+#include "third_party/blink/renderer/core/loader/modulescript/module_tree_linker.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_tree_linker_registry.h"
#include "third_party/blink/renderer/core/script/dynamic_module_resolver.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h"
+#include "third_party/blink/renderer/core/script/layered_api.h"
#include "third_party/blink/renderer/core/script/module_map.h"
#include "third_party/blink/renderer/core/script/module_script.h"
#include "third_party/blink/renderer/core/script/script_module_resolver_impl.h"
@@ -19,19 +21,18 @@
namespace blink {
ExecutionContext* ModulatorImplBase::GetExecutionContext() const {
- return ExecutionContext::From(script_state_.get());
+ return ExecutionContext::From(script_state_);
}
-ModulatorImplBase::ModulatorImplBase(scoped_refptr<ScriptState> script_state)
- : script_state_(std::move(script_state)),
- task_runner_(ExecutionContext::From(script_state_.get())
+ModulatorImplBase::ModulatorImplBase(ScriptState* script_state)
+ : script_state_(script_state),
+ task_runner_(ExecutionContext::From(script_state_)
->GetTaskRunner(TaskType::kNetworking)),
map_(ModuleMap::Create(this)),
- loader_registry_(ModuleScriptLoaderRegistry::Create()),
tree_linker_registry_(ModuleTreeLinkerRegistry::Create()),
script_module_resolver_(ScriptModuleResolverImpl::Create(
this,
- ExecutionContext::From(script_state_.get()))),
+ ExecutionContext::From(script_state_))),
dynamic_module_resolver_(DynamicModuleResolver::Create(this)) {
DCHECK(script_state_);
DCHECK(task_runner_);
@@ -39,22 +40,21 @@ ModulatorImplBase::ModulatorImplBase(scoped_refptr<ScriptState> script_state)
ModulatorImplBase::~ModulatorImplBase() {}
-ReferrerPolicy ModulatorImplBase::GetReferrerPolicy() {
- return GetExecutionContext()->GetReferrerPolicy();
-}
-
-const SecurityOrigin* ModulatorImplBase::GetSecurityOriginForFetch() {
- return GetExecutionContext()->GetSecurityOrigin();
+bool ModulatorImplBase::IsScriptingDisabled() const {
+ return !GetExecutionContext()->CanExecuteScripts(kAboutToExecuteScript);
}
// [fetch-a-module-script-tree]
// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-module-script-tree
// [fetch-a-module-worker-script-tree]
// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-module-worker-script-tree
-void ModulatorImplBase::FetchTree(const KURL& url,
- WebURLRequest::RequestContext destination,
- const ScriptFetchOptions& options,
- ModuleTreeClient* client) {
+void ModulatorImplBase::FetchTree(
+ const KURL& url,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
+ WebURLRequest::RequestContext destination,
+ const ScriptFetchOptions& options,
+ ModuleScriptCustomFetchType custom_fetch_type,
+ ModuleTreeClient* client) {
// <spec label="fetch-a-module-script-tree" step="2">Perform the internal
// module script graph fetching procedure given url, settings object,
// destination, options, settings object, visited set, "client", and with the
@@ -68,8 +68,9 @@ void ModulatorImplBase::FetchTree(const KURL& url,
// of this algorithm specified custom perform the fetch steps, pass those
// along as well.</spec>
- tree_linker_registry_->Fetch(url, GetExecutionContext()->BaseURL(),
- destination, options, this, client);
+ ModuleTreeLinker::Fetch(url, fetch_client_settings_object, destination,
+ options, this, custom_fetch_type,
+ tree_linker_registry_, client);
// <spec label="fetch-a-module-script-tree" step="3">When the internal module
// script graph fetching procedure asynchronously completes with result,
@@ -84,29 +85,76 @@ void ModulatorImplBase::FetchTree(const KURL& url,
void ModulatorImplBase::FetchDescendantsForInlineScript(
ModuleScript* module_script,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
WebURLRequest::RequestContext destination,
ModuleTreeClient* client) {
- tree_linker_registry_->FetchDescendantsForInlineScript(
- module_script, destination, this, client);
+ ModuleTreeLinker::FetchDescendantsForInlineScript(
+ module_script, fetch_client_settings_object, destination, this,
+ ModuleScriptCustomFetchType::kNone, tree_linker_registry_, client);
}
-void ModulatorImplBase::FetchSingle(const ModuleScriptFetchRequest& request,
- ModuleGraphLevel level,
- SingleModuleClient* client) {
- map_->FetchSingleModuleScript(request, level, client);
-}
-
-void ModulatorImplBase::FetchNewSingleModule(
+void ModulatorImplBase::FetchSingle(
const ModuleScriptFetchRequest& request,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
ModuleGraphLevel level,
- ModuleScriptLoaderClient* client) {
- loader_registry_->Fetch(request, level, this, client);
+ ModuleScriptCustomFetchType custom_fetch_type,
+ SingleModuleClient* client) {
+ map_->FetchSingleModuleScript(request, fetch_client_settings_object, level,
+ custom_fetch_type, client);
}
ModuleScript* ModulatorImplBase::GetFetchedModuleScript(const KURL& url) {
return map_->GetFetchedModuleScript(url);
}
+// https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier
+KURL ModulatorImplBase::ResolveModuleSpecifier(const String& module_request,
+ const KURL& base_url,
+ String* failure_reason) {
+ // <spec step="1">Apply the URL parser to specifier. If the result is not
+ // failure, return the result.</spec>
+ KURL url(NullURL(), module_request);
+ if (url.IsValid()) {
+ // <spec
+ // href="https://github.com/drufball/layered-apis/blob/master/spec.md#resolve-a-module-specifier"
+ // step="1">Let parsed be the result of applying the URL parser to
+ // specifier. If parsed is not failure, then return the layered API fetching
+ // URL given parsed and script's base URL.</spec>
+ if (RuntimeEnabledFeatures::LayeredAPIEnabled())
+ return blink::layered_api::ResolveFetchingURL(url, base_url);
+
+ return url;
+ }
+
+ // <spec step="2">If specifier does not start with the character U+002F
+ // SOLIDUS (/), the two-character sequence U+002E FULL STOP, U+002F SOLIDUS
+ // (./), or the three-character sequence U+002E FULL STOP, U+002E FULL STOP,
+ // U+002F SOLIDUS (../), return failure.</spec>
+ //
+ // (../), return failure and abort these steps." [spec text]
+ if (!module_request.StartsWith("/") && !module_request.StartsWith("./") &&
+ !module_request.StartsWith("../")) {
+ if (failure_reason) {
+ *failure_reason =
+ "Relative references must start with either \"/\", \"./\", or "
+ "\"../\".";
+ }
+ return KURL();
+ }
+
+ // <spec step="3">Return the result of applying the URL parser to specifier
+ // with script's base URL as the base URL.</spec>
+ DCHECK(base_url.IsValid());
+ KURL absolute_url(base_url, module_request);
+ if (absolute_url.IsValid())
+ return absolute_url;
+
+ if (failure_reason) {
+ *failure_reason = "Invalid relative url or base scheme isn't hierarchical.";
+ }
+ return KURL();
+}
+
bool ModulatorImplBase::HasValidContext() {
return script_state_->ContextIsValid();
}
@@ -140,45 +188,17 @@ ModuleImportMeta ModulatorImplBase::HostGetImportMetaProperties(
return ModuleImportMeta(url_string);
}
-ScriptModule ModulatorImplBase::CompileModule(
- const String& provided_source,
- const KURL& source_url,
- const KURL& base_url,
- const ScriptFetchOptions& options,
- AccessControlStatus access_control_status,
- const TextPosition& position,
- ExceptionState& exception_state) {
- // Implements Steps 3-5 of
- // https://html.spec.whatwg.org/multipage/webappapis.html#creating-a-module-script
-
- // Step 3. Let realm be the provided environment settings object's Realm.
- // Note: Realm is v8::Context.
-
- // Step 4. If scripting is disabled for the given environment settings
- // object's responsible browsing context, then let script source be the empty
- // string. Otherwise, let script source be the provided script source.
- String script_source;
- if (GetExecutionContext()->CanExecuteScripts(kAboutToExecuteScript))
- script_source = provided_source;
-
- // Step 5. Let result be ParseModule(script source, realm, script).
- ScriptState::Scope scope(script_state_.get());
- return ScriptModule::Compile(
- script_state_->GetIsolate(), script_source, source_url, base_url, options,
- access_control_status, position, exception_state);
-}
-
ScriptValue ModulatorImplBase::InstantiateModule(ScriptModule script_module) {
- ScriptState::Scope scope(script_state_.get());
- return script_module.Instantiate(script_state_.get());
+ ScriptState::Scope scope(script_state_);
+ return script_module.Instantiate(script_state_);
}
Vector<Modulator::ModuleRequest>
ModulatorImplBase::ModuleRequestsFromScriptModule(ScriptModule script_module) {
- ScriptState::Scope scope(script_state_.get());
- Vector<String> specifiers = script_module.ModuleRequests(script_state_.get());
+ ScriptState::Scope scope(script_state_);
+ Vector<String> specifiers = script_module.ModuleRequests(script_state_);
Vector<TextPosition> positions =
- script_module.ModuleRequestPositions(script_state_.get());
+ script_module.ModuleRequestPositions(script_state_);
DCHECK_EQ(specifiers.size(), positions.size());
Vector<ModuleRequest> requests;
requests.ReserveInitialCapacity(specifiers.size());
@@ -200,12 +220,12 @@ ScriptValue ModulatorImplBase::ExecuteModule(
// Step 3. "Check if we can run script with settings.
// If this returns "do not run" then return." [spec text]
- if (!GetExecutionContext()->CanExecuteScripts(kAboutToExecuteScript))
+ if (IsScriptingDisabled())
return ScriptValue();
// Step 4. "Prepare to run script given settings." [spec text]
// This is placed here to also cover ScriptModule::ReportException().
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
// Step 5. "Let evaluationStatus be null." [spec text]
// |error| corresponds to "evaluationStatus of [[Type]]: throw".
@@ -224,7 +244,7 @@ ScriptValue ModulatorImplBase::ExecuteModule(
CHECK(!record.IsNull());
// Step 7.2. "Set evaluationStatus to record.Evaluate()." [spec text]
- error = record.Evaluate(script_state_.get());
+ error = record.Evaluate(script_state_);
// "If Evaluate fails to complete as a result of the user agent aborting the
// running script, then set evaluationStatus to Completion { [[Type]]:
@@ -241,7 +261,7 @@ ScriptValue ModulatorImplBase::ExecuteModule(
// Step 8.2. "Otherwise, report the exception given by
// evaluationStatus.[[Value]] for script." [spec text]
- ScriptModule::ReportException(script_state_.get(), error.V8Value());
+ ScriptModule::ReportException(script_state_, error.V8Value());
}
// Step 9. "Clean up after running script with settings." [spec text]
@@ -250,18 +270,13 @@ ScriptValue ModulatorImplBase::ExecuteModule(
}
void ModulatorImplBase::Trace(blink::Visitor* visitor) {
- Modulator::Trace(visitor);
+ visitor->Trace(script_state_);
visitor->Trace(map_);
- visitor->Trace(loader_registry_);
visitor->Trace(tree_linker_registry_);
visitor->Trace(script_module_resolver_);
visitor->Trace(dynamic_module_resolver_);
-}
-void ModulatorImplBase::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(map_);
- visitor->TraceWrappers(tree_linker_registry_);
- Modulator::TraceWrappers(visitor);
+ Modulator::Trace(visitor);
}
} // namespace blink
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 382ab46cb31..3fbdf5d9367 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
@@ -18,7 +18,6 @@ namespace blink {
class DynamicModuleResolver;
class ExecutionContext;
class ModuleMap;
-class ModuleScriptLoaderRegistry;
class ModuleTreeLinkerRegistry;
class ScriptState;
@@ -30,55 +29,54 @@ class ModulatorImplBase : public Modulator {
public:
~ModulatorImplBase() override;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
protected:
- explicit ModulatorImplBase(scoped_refptr<ScriptState>);
+ explicit ModulatorImplBase(ScriptState*);
ExecutionContext* GetExecutionContext() const;
- ScriptState* GetScriptState() override { return script_state_.get(); }
+ ScriptState* GetScriptState() override { return script_state_; }
private:
// Implements Modulator
+ bool IsScriptingDisabled() const override;
+
ScriptModuleResolver* GetScriptModuleResolver() override {
return script_module_resolver_.Get();
}
base::SingleThreadTaskRunner* TaskRunner() override {
return task_runner_.get();
}
- ReferrerPolicy GetReferrerPolicy() override;
- const SecurityOrigin* GetSecurityOriginForFetch() override;
- void FetchTree(const KURL&,
- WebURLRequest::RequestContext destination,
- const ScriptFetchOptions&,
- ModuleTreeClient*) override;
+ void FetchTree(
+ const KURL&,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
+ WebURLRequest::RequestContext destination,
+ const ScriptFetchOptions&,
+ ModuleScriptCustomFetchType,
+ ModuleTreeClient*) override;
void FetchDescendantsForInlineScript(
ModuleScript*,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
WebURLRequest::RequestContext destination,
ModuleTreeClient*) override;
- void FetchSingle(const ModuleScriptFetchRequest&,
- ModuleGraphLevel,
- SingleModuleClient*) override;
+ void FetchSingle(
+ const ModuleScriptFetchRequest&,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
+ ModuleGraphLevel,
+ ModuleScriptCustomFetchType,
+ SingleModuleClient*) override;
ModuleScript* GetFetchedModuleScript(const KURL&) override;
bool HasValidContext() override;
- void FetchNewSingleModule(const ModuleScriptFetchRequest&,
- ModuleGraphLevel,
- ModuleScriptLoaderClient*) override;
+ KURL ResolveModuleSpecifier(const String& module_request,
+ const KURL& base_url,
+ String* failure_reason) final;
void ResolveDynamically(const String& specifier,
const KURL&,
const ReferrerScriptInfo&,
ScriptPromiseResolver*) override;
ModuleImportMeta HostGetImportMetaProperties(ScriptModule) const override;
- ScriptModule CompileModule(const String& script,
- const KURL& source_url,
- const KURL& base_url,
- const ScriptFetchOptions&,
- AccessControlStatus,
- const TextPosition&,
- ExceptionState&) override;
ScriptValue InstantiateModule(ScriptModule) override;
Vector<ModuleRequest> ModuleRequestsFromScriptModule(ScriptModule) override;
ScriptValue ExecuteModule(const ModuleScript*, CaptureEvalErrorFlag) override;
@@ -90,10 +88,9 @@ class ModulatorImplBase : public Modulator {
// modification of |reason|.
virtual bool IsDynamicImportForbidden(String* reason) = 0;
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
TraceWrapperMember<ModuleMap> map_;
- Member<ModuleScriptLoaderRegistry> loader_registry_;
TraceWrapperMember<ModuleTreeLinkerRegistry> tree_linker_registry_;
Member<ScriptModuleResolver> script_module_resolver_;
Member<DynamicModuleResolver> dynamic_module_resolver_;
diff --git a/chromium/third_party/blink/renderer/core/script/modulator_test.cc b/chromium/third_party/blink/renderer/core/script/modulator_test.cc
deleted file mode 100644
index 2308e07d75b..00000000000
--- a/chromium/third_party/blink/renderer/core/script/modulator_test.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/script/modulator.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
-
-namespace blink {
-
-TEST(ModulatorTest, resolveModuleSpecifier) {
- // Taken from examples listed in
- // https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier
-
- // "The following are valid module specifiers according to the above
- // algorithm:"
- EXPECT_TRUE(Modulator::ResolveModuleSpecifier("https://example.com/apples.js",
- NullURL())
- .IsValid());
-
- KURL resolved = Modulator::ResolveModuleSpecifier(
- "http:example.com\\pears.mjs", NullURL());
- EXPECT_TRUE(resolved.IsValid());
- EXPECT_EQ("http://example.com/pears.mjs", resolved.GetString());
-
- KURL base_url(NullURL(), "https://example.com");
- EXPECT_TRUE(
- Modulator::ResolveModuleSpecifier("//example.com/", base_url).IsValid());
- EXPECT_TRUE(
- Modulator::ResolveModuleSpecifier("./strawberries.js.cgi", base_url)
- .IsValid());
- EXPECT_TRUE(
- Modulator::ResolveModuleSpecifier("../lychees", base_url).IsValid());
- EXPECT_TRUE(
- Modulator::ResolveModuleSpecifier("/limes.jsx", base_url).IsValid());
- EXPECT_TRUE(Modulator::ResolveModuleSpecifier(
- "data:text/javascript,export default 'grapes';", NullURL())
- .IsValid());
- EXPECT_TRUE(
- Modulator::ResolveModuleSpecifier(
- "blob:https://whatwg.org/d0360e2f-caee-469f-9a2f-87d5b0456f6f",
- KURL())
- .IsValid());
-
- // "The following are valid module specifiers according to the above
- // algorithm, but will invariably cause failures when they are fetched:"
- EXPECT_TRUE(Modulator::ResolveModuleSpecifier(
- "javascript:export default 'artichokes';", NullURL())
- .IsValid());
- EXPECT_TRUE(Modulator::ResolveModuleSpecifier(
- "data:text/plain,export default 'kale';", NullURL())
- .IsValid());
- EXPECT_TRUE(
- Modulator::ResolveModuleSpecifier("about:legumes", NullURL()).IsValid());
- EXPECT_TRUE(
- Modulator::ResolveModuleSpecifier("wss://example.com/celery", NullURL())
- .IsValid());
-
- // "The following are not valid module specifiers according to the above
- // algorithm:"
- EXPECT_FALSE(
- Modulator::ResolveModuleSpecifier("https://f:b/c", NullURL()).IsValid());
- EXPECT_FALSE(
- Modulator::ResolveModuleSpecifier("pumpkins.js", NullURL()).IsValid());
-
- // Unprefixed module specifiers should still fail w/ a valid baseURL.
- EXPECT_FALSE(
- Modulator::ResolveModuleSpecifier("avocados.js", base_url).IsValid());
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/script/module_map.cc b/chromium/third_party/blink/renderer/core/script/module_map.cc
index dc8e944e888..c33f7fa0a48 100644
--- a/chromium/third_party/blink/renderer/core/script/module_map.cc
+++ b/chromium/third_party/blink/renderer/core/script/module_map.cc
@@ -5,16 +5,19 @@
#include "third_party/blink/renderer/core/script/module_map.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h"
+#include "third_party/blink/renderer/core/loader/modulescript/module_script_loader.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_loader_client.h"
+#include "third_party/blink/renderer/core/loader/modulescript/module_script_loader_registry.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/script/module_script.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
namespace blink {
// Entry struct represents a value in "module map" spec object.
// https://html.spec.whatwg.org/multipage/webappapis.html#module-map
class ModuleMap::Entry final : public GarbageCollectedFinalized<Entry>,
- public TraceWrapperBase,
+ public NameClient,
public ModuleScriptLoaderClient {
USING_GARBAGE_COLLECTED_MIXIN(ModuleMap::Entry);
@@ -23,7 +26,6 @@ class ModuleMap::Entry final : public GarbageCollectedFinalized<Entry>,
~Entry() override {}
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override { return "ModuleMap::Entry"; }
// Notify fetched |m_moduleScript| to the client asynchronously.
@@ -59,10 +61,6 @@ void ModuleMap::Entry::Trace(blink::Visitor* visitor) {
visitor->Trace(clients_);
}
-void ModuleMap::Entry::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(module_script_);
-}
-
void ModuleMap::Entry::DispatchFinishedNotificationAsync(
SingleModuleClient* client) {
map_->GetModulator()->TaskRunner()->PostTask(
@@ -98,24 +96,25 @@ ModuleScript* ModuleMap::Entry::GetModuleScript() const {
return module_script_.Get();
}
-ModuleMap::ModuleMap(Modulator* modulator) : modulator_(modulator) {
+ModuleMap::ModuleMap(Modulator* modulator)
+ : modulator_(modulator),
+ loader_registry_(ModuleScriptLoaderRegistry::Create()) {
DCHECK(modulator);
}
void ModuleMap::Trace(blink::Visitor* visitor) {
visitor->Trace(map_);
visitor->Trace(modulator_);
-}
-
-void ModuleMap::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- for (const auto& it : map_)
- visitor->TraceWrappers(it.value);
+ visitor->Trace(loader_registry_);
}
// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script
-void ModuleMap::FetchSingleModuleScript(const ModuleScriptFetchRequest& request,
- ModuleGraphLevel level,
- SingleModuleClient* client) {
+void ModuleMap::FetchSingleModuleScript(
+ const ModuleScriptFetchRequest& request,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
+ ModuleGraphLevel level,
+ ModuleScriptCustomFetchType custom_fetch_type,
+ SingleModuleClient* client) {
// <spec step="1">Let moduleMap be module map settings object's module
// map.</spec>
//
@@ -131,7 +130,9 @@ void ModuleMap::FetchSingleModuleScript(const ModuleScriptFetchRequest& request,
// Steps 4-9 loads a new single module script.
// Delegates to ModuleScriptLoader via Modulator.
- modulator_->FetchNewSingleModule(request, level, entry);
+ ModuleScriptLoader::Fetch(request, fetch_client_settings_object, level,
+ modulator_, custom_fetch_type, loader_registry_,
+ entry);
}
DCHECK(entry);
diff --git a/chromium/third_party/blink/renderer/core/script/module_map.h b/chromium/third_party/blink/renderer/core/script/module_map.h
index 1f87c0712da..ebf4a229cd9 100644
--- a/chromium/third_party/blink/renderer/core/script/module_map.h
+++ b/chromium/third_party/blink/renderer/core/script/module_map.h
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -16,16 +16,19 @@
namespace blink {
+class FetchClientSettingsObjectSnapshot;
class Modulator;
class ModuleScript;
class ModuleScriptFetchRequest;
+class ModuleScriptLoaderRegistry;
class SingleModuleClient;
enum class ModuleGraphLevel;
+enum class ModuleScriptCustomFetchType;
// A ModuleMap implements "module map" spec.
// https://html.spec.whatwg.org/multipage/webappapis.html#module-map
class CORE_EXPORT ModuleMap final : public GarbageCollected<ModuleMap>,
- public TraceWrapperBase {
+ public NameClient {
class Entry;
public:
@@ -33,13 +36,15 @@ class CORE_EXPORT ModuleMap final : public GarbageCollected<ModuleMap>,
return new ModuleMap(modulator);
}
void Trace(blink::Visitor*);
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override { return "ModuleMap"; }
// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script
- void FetchSingleModuleScript(const ModuleScriptFetchRequest&,
- ModuleGraphLevel,
- SingleModuleClient*);
+ void FetchSingleModuleScript(
+ const ModuleScriptFetchRequest&,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
+ ModuleGraphLevel,
+ ModuleScriptCustomFetchType,
+ SingleModuleClient*);
// Synchronously get the ModuleScript for a given URL.
// If the URL wasn't fetched, or is currently being fetched, this returns a
@@ -57,6 +62,7 @@ class CORE_EXPORT ModuleMap final : public GarbageCollected<ModuleMap>,
MapImpl map_;
Member<Modulator> modulator_;
+ Member<ModuleScriptLoaderRegistry> loader_registry_;
DISALLOW_COPY_AND_ASSIGN(ModuleMap);
};
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 a8c368e4ea3..0432bb25c02 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
@@ -6,14 +6,18 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.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/loader/modulescript/module_script_fetch_request.h"
+#include "third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_loader_client.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/script/module_script.h"
#include "third_party/blink/renderer/core/script/script_module_resolver.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/page_test_base.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h"
@@ -80,7 +84,7 @@ class TestScriptModuleResolver final : public ScriptModuleResolver {
class ModuleMapTestModulator final : public DummyModulator {
public:
- ModuleMapTestModulator();
+ explicit ModuleMapTestModulator(ScriptState*);
~ModuleMapTestModulator() override {}
void Trace(blink::Visitor*) override;
@@ -92,67 +96,93 @@ class ModuleMapTestModulator final : public DummyModulator {
private:
// Implements Modulator:
-
ScriptModuleResolver* GetScriptModuleResolver() override {
return resolver_.Get();
}
+ ScriptState* GetScriptState() override { return script_state_; }
+
+ class TestModuleScriptFetcher final
+ : public GarbageCollectedFinalized<TestModuleScriptFetcher>,
+ public ModuleScriptFetcher {
+ USING_GARBAGE_COLLECTED_MIXIN(TestModuleScriptFetcher);
+
+ public:
+ TestModuleScriptFetcher(ModuleMapTestModulator* modulator)
+ : modulator_(modulator) {}
+ void Fetch(FetchParameters& request,
+ ModuleGraphLevel,
+ ModuleScriptFetcher::Client* client) override {
+ TestRequest* test_request = new TestRequest(
+ ModuleScriptCreationParams(
+ request.Url(), MovableString(String("").ReleaseImpl()),
+ request.GetResourceRequest().GetFetchCredentialsMode(),
+ kSharableCrossOrigin),
+ client);
+ modulator_->test_requests_.push_back(test_request);
+ }
+ String DebugName() const override { return "TestModuleScriptFetcher"; }
+ void Trace(blink::Visitor* visitor) override {
+ ModuleScriptFetcher::Trace(visitor);
+ visitor->Trace(modulator_);
+ }
+
+ private:
+ Member<ModuleMapTestModulator> modulator_;
+ };
+
+ ModuleScriptFetcher* CreateModuleScriptFetcher(
+ ModuleScriptCustomFetchType) override {
+ return new TestModuleScriptFetcher(this);
+ }
+
+ Vector<ModuleRequest> ModuleRequestsFromScriptModule(ScriptModule) override {
+ return Vector<ModuleRequest>();
+ }
base::SingleThreadTaskRunner* TaskRunner() override {
return Platform::Current()->CurrentThread()->GetTaskRunner().get();
};
- void FetchNewSingleModule(const ModuleScriptFetchRequest&,
- ModuleGraphLevel,
- ModuleScriptLoaderClient*) override;
-
struct TestRequest final : public GarbageCollectedFinalized<TestRequest> {
- TestRequest(const KURL& in_url,
- const ScriptFetchOptions& in_options,
- ModuleScriptLoaderClient* in_client)
- : url(in_url), options(in_options), client(in_client) {}
- KURL url;
- ScriptFetchOptions options;
- Member<ModuleScriptLoaderClient> client;
-
- void Trace(blink::Visitor* visitor) { visitor->Trace(client); }
+ TestRequest(const ModuleScriptCreationParams& params,
+ ModuleScriptFetcher::Client* client)
+ : params_(params), client_(client) {}
+ void NotifyFetchFinished() {
+ client_->NotifyFetchFinished(params_,
+ HeapVector<Member<ConsoleMessage>>());
+ }
+ void Trace(blink::Visitor* visitor) { visitor->Trace(client_); }
+
+ private:
+ ModuleScriptCreationParams params_;
+ Member<ModuleScriptFetcher::Client> client_;
};
HeapVector<Member<TestRequest>> test_requests_;
+ Member<ScriptState> script_state_;
Member<TestScriptModuleResolver> resolver_;
};
-ModuleMapTestModulator::ModuleMapTestModulator()
- : resolver_(new TestScriptModuleResolver) {}
+ModuleMapTestModulator::ModuleMapTestModulator(ScriptState* script_state)
+ : script_state_(script_state), resolver_(new TestScriptModuleResolver) {}
void ModuleMapTestModulator::Trace(blink::Visitor* visitor) {
visitor->Trace(test_requests_);
+ visitor->Trace(script_state_);
visitor->Trace(resolver_);
DummyModulator::Trace(visitor);
}
-void ModuleMapTestModulator::FetchNewSingleModule(
- const ModuleScriptFetchRequest& request,
- ModuleGraphLevel,
- ModuleScriptLoaderClient* client) {
- TestRequest* test_request =
- new TestRequest(request.Url(), request.Options(), client);
- test_requests_.push_back(test_request);
-}
-
void ModuleMapTestModulator::ResolveFetches() {
for (const auto& test_request : test_requests_) {
- auto* module_script = ModuleScript::CreateForTest(
- this, ScriptModule(), test_request->url, test_request->options);
- TaskRunner()->PostTask(
- FROM_HERE,
- WTF::Bind(&ModuleScriptLoaderClient::NotifyNewSingleModuleFinished,
- WrapPersistent(test_request->client.Get()),
- WrapPersistent(module_script)));
+ TaskRunner()->PostTask(FROM_HERE,
+ WTF::Bind(&TestRequest::NotifyFetchFinished,
+ WrapPersistent(test_request.Get())));
}
test_requests_.clear();
}
-class ModuleMapTest : public testing::Test {
+class ModuleMapTest : public PageTestBase {
public:
void SetUp() override;
@@ -165,8 +195,12 @@ class ModuleMapTest : public testing::Test {
};
void ModuleMapTest::SetUp() {
- modulator_ = new ModuleMapTestModulator();
- map_ = ModuleMap::Create(modulator_.Get());
+ PageTestBase::SetUp(IntSize(500, 500));
+ GetDocument().SetURL(KURL("https://example.com"));
+ GetDocument().SetSecurityOrigin(SecurityOrigin::Create(GetDocument().Url()));
+ modulator_ =
+ new ModuleMapTestModulator(ToScriptStateForMainWorld(&GetFrame()));
+ map_ = ModuleMap::Create(modulator_);
}
TEST_F(ModuleMapTest, sequentialRequests) {
@@ -175,12 +209,14 @@ TEST_F(ModuleMapTest, sequentialRequests) {
platform->AdvanceClockSeconds(1.); // For non-zero DocumentParserTimings
KURL url(NullURL(), "https://example.com/foo.js");
+ auto* settings_object = new FetchClientSettingsObjectSnapshot(GetDocument());
// First request
TestSingleModuleClient* client = new TestSingleModuleClient;
Map()->FetchSingleModuleScript(ModuleScriptFetchRequest::CreateForTest(url),
+ settings_object,
ModuleGraphLevel::kTopLevelModuleFetch,
- client);
+ ModuleScriptCustomFetchType::kNone, client);
Modulator()->ResolveFetches();
EXPECT_FALSE(client->WasNotifyFinished())
<< "fetchSingleModuleScript shouldn't complete synchronously";
@@ -196,8 +232,9 @@ TEST_F(ModuleMapTest, sequentialRequests) {
// Secondary request
TestSingleModuleClient* client2 = new TestSingleModuleClient;
Map()->FetchSingleModuleScript(ModuleScriptFetchRequest::CreateForTest(url),
+ settings_object,
ModuleGraphLevel::kTopLevelModuleFetch,
- client2);
+ ModuleScriptCustomFetchType::kNone, client2);
Modulator()->ResolveFetches();
EXPECT_FALSE(client2->WasNotifyFinished())
<< "fetchSingleModuleScript shouldn't complete synchronously";
@@ -218,18 +255,21 @@ TEST_F(ModuleMapTest, concurrentRequestsShouldJoin) {
platform->AdvanceClockSeconds(1.); // For non-zero DocumentParserTimings
KURL url(NullURL(), "https://example.com/foo.js");
+ auto* settings_object = new FetchClientSettingsObjectSnapshot(GetDocument());
// First request
TestSingleModuleClient* client = new TestSingleModuleClient;
Map()->FetchSingleModuleScript(ModuleScriptFetchRequest::CreateForTest(url),
+ settings_object,
ModuleGraphLevel::kTopLevelModuleFetch,
- client);
+ ModuleScriptCustomFetchType::kNone, client);
// Secondary request (which should join the first request)
TestSingleModuleClient* client2 = new TestSingleModuleClient;
Map()->FetchSingleModuleScript(ModuleScriptFetchRequest::CreateForTest(url),
+ settings_object,
ModuleGraphLevel::kTopLevelModuleFetch,
- client2);
+ ModuleScriptCustomFetchType::kNone, client2);
Modulator()->ResolveFetches();
EXPECT_FALSE(client->WasNotifyFinished())
diff --git a/chromium/third_party/blink/renderer/core/script/module_pending_script.cc b/chromium/third_party/blink/renderer/core/script/module_pending_script.cc
index 70df1c8ae23..8ad0afe2431 100644
--- a/chromium/third_party/blink/renderer/core/script/module_pending_script.cc
+++ b/chromium/third_party/blink/renderer/core/script/module_pending_script.cc
@@ -37,13 +37,6 @@ void ModulePendingScriptTreeClient::Trace(blink::Visitor* visitor) {
ModuleTreeClient::Trace(visitor);
}
-void ModulePendingScriptTreeClient::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(module_script_);
- visitor->TraceWrappers(pending_script_);
- ModuleTreeClient::TraceWrappers(visitor);
-}
-
ModulePendingScript::ModulePendingScript(ScriptElementBase* element,
ModulePendingScriptTreeClient* client,
bool is_external)
@@ -66,17 +59,10 @@ void ModulePendingScript::Trace(blink::Visitor* visitor) {
PendingScript::Trace(visitor);
}
-void ModulePendingScript::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(module_tree_client_);
- PendingScript::TraceWrappers(visitor);
-}
-
void ModulePendingScript::NotifyModuleTreeLoadFinished() {
CHECK(!IsReady());
ready_ = true;
-
- if (Client())
- Client()->PendingScriptFinished(this);
+ PendingScriptFinished();
}
Script* ModulePendingScript::GetSource(const KURL& document_url,
diff --git a/chromium/third_party/blink/renderer/core/script/module_pending_script.h b/chromium/third_party/blink/renderer/core/script/module_pending_script.h
index f934b5fca2d..15be60e0760 100644
--- a/chromium/third_party/blink/renderer/core/script/module_pending_script.h
+++ b/chromium/third_party/blink/renderer/core/script/module_pending_script.h
@@ -33,7 +33,6 @@ class ModulePendingScriptTreeClient final : public ModuleTreeClient {
ModuleScript* GetModuleScript() const { return module_script_; }
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
ModulePendingScriptTreeClient();
@@ -65,7 +64,6 @@ class CORE_EXPORT ModulePendingScript : public PendingScript {
}
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
ModulePendingScript(ScriptElementBase*,
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 b31d077d497..513b8de9641 100644
--- a/chromium/third_party/blink/renderer/core/script/module_script.cc
+++ b/chromium/third_party/blink/renderer/core/script/module_script.cc
@@ -12,7 +12,7 @@
namespace blink {
// https://html.spec.whatwg.org/multipage/webappapis.html#creating-a-module-script
-ModuleScript* ModuleScript::Create(const String& source_text,
+ModuleScript* ModuleScript::Create(const MovableString& original_source_text,
Modulator* modulator,
const KURL& source_url,
const KURL& base_url,
@@ -21,8 +21,9 @@ ModuleScript* ModuleScript::Create(const String& source_text,
const TextPosition& start_position) {
// <spec step="1">If scripting is disabled for settings's responsible browsing
// context, then set source to the empty string.</spec>
- //
- // TODO(hiroshige): Implement this.
+ MovableString source_text;
+ if (!modulator->IsScriptingDisabled())
+ source_text = original_source_text;
// <spec step="2">Let script be a new module script that this algorithm will
// subsequently initialize.</spec>
@@ -39,10 +40,9 @@ ModuleScript* ModuleScript::Create(const String& source_text,
ExceptionState exception_state(isolate, ExceptionState::kExecutionContext,
"ModuleScript", "Create");
- // Delegate to Modulator::CompileModule to process Steps 3-5.
- ScriptModule result = modulator->CompileModule(
- source_text, source_url, base_url, options, access_control_status,
- start_position, exception_state);
+ ScriptModule result = ScriptModule::Compile(
+ isolate, source_text.ToString(), source_url, base_url, options,
+ access_control_status, start_position, exception_state);
// CreateInternal processes Steps 4 and 8-10.
//
@@ -101,14 +101,14 @@ ModuleScript* ModuleScript::CreateForTest(Modulator* modulator,
ScriptModule record,
const KURL& base_url,
const ScriptFetchOptions& options) {
- String dummy_source_text = "";
+ MovableString dummy_source_text(String("").ReleaseImpl());
KURL dummy_source_url;
return CreateInternal(dummy_source_text, modulator, record, dummy_source_url,
base_url, options, TextPosition::MinimumPosition());
}
// https://html.spec.whatwg.org/multipage/webappapis.html#creating-a-module-script
-ModuleScript* ModuleScript::CreateInternal(const String& source_text,
+ModuleScript* ModuleScript::CreateInternal(const MovableString& source_text,
Modulator* modulator,
ScriptModule result,
const KURL& source_url,
@@ -141,7 +141,7 @@ ModuleScript::ModuleScript(Modulator* settings_object,
const KURL& source_url,
const KURL& base_url,
const ScriptFetchOptions& fetch_options,
- const String& source_text,
+ const MovableString& source_text,
const TextPosition& start_position)
: Script(fetch_options, base_url),
settings_object_(settings_object),
@@ -210,8 +210,8 @@ KURL ModuleScript::ResolveModuleSpecifier(const String& module_request,
if (found != specifier_to_url_cache_.end())
return found->value;
- KURL url = Modulator::ResolveModuleSpecifier(module_request, BaseURL(),
- failure_reason);
+ KURL url = settings_object_->ResolveModuleSpecifier(module_request, BaseURL(),
+ failure_reason);
// Cache the result only on success, so that failure_reason is set for
// subsequent calls too.
if (url.IsValid())
@@ -221,15 +221,11 @@ KURL ModuleScript::ResolveModuleSpecifier(const String& module_request,
void ModuleScript::Trace(blink::Visitor* visitor) {
visitor->Trace(settings_object_);
+ visitor->Trace(record_.UnsafeCast<v8::Value>());
+ visitor->Trace(parse_error_);
+ visitor->Trace(error_to_rethrow_);
Script::Trace(visitor);
}
-void ModuleScript::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- // TODO(mlippautz): Support TraceWrappers(const
- // TraceWrapperV8Reference<v8::Module>&) to remove the cast.
- visitor->TraceWrappers(record_.UnsafeCast<v8::Value>());
- visitor->TraceWrappers(parse_error_);
- visitor->TraceWrappers(error_to_rethrow_);
-}
void ModuleScript::RunScript(LocalFrame* frame, const SecurityOrigin*) const {
DVLOG(1) << *this << "::RunScript()";
@@ -238,7 +234,7 @@ void ModuleScript::RunScript(LocalFrame* frame, const SecurityOrigin*) const {
}
String ModuleScript::InlineSourceTextForCSP() const {
- return source_text_;
+ return source_text_.ToString();
}
std::ostream& operator<<(std::ostream& stream,
diff --git a/chromium/third_party/blink/renderer/core/script/module_script.h b/chromium/third_party/blink/renderer/core/script/module_script.h
index 0fd6df8ed6e..eb1c6efb967 100644
--- a/chromium/third_party/blink/renderer/core/script/module_script.h
+++ b/chromium/third_party/blink/renderer/core/script/module_script.h
@@ -10,23 +10,24 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/script/script.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/kurl_hash.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/text/movable_string.h"
#include "third_party/blink/renderer/platform/wtf/text/text_position.h"
namespace blink {
// ModuleScript is a model object for the "module script" spec concept.
// https://html.spec.whatwg.org/multipage/webappapis.html#module-script
-class CORE_EXPORT ModuleScript final : public Script, public TraceWrapperBase {
+class CORE_EXPORT ModuleScript final : public Script, public NameClient {
public:
// https://html.spec.whatwg.org/multipage/webappapis.html#creating-a-module-script
static ModuleScript* Create(
- const String& source_text,
+ const MovableString& source_text,
Modulator*,
const KURL& source_url,
const KURL& base_url,
@@ -62,7 +63,6 @@ class CORE_EXPORT ModuleScript final : public Script, public TraceWrapperBase {
String* failure_reason = nullptr);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override { return "ModuleScript"; }
private:
@@ -71,10 +71,10 @@ class CORE_EXPORT ModuleScript final : public Script, public TraceWrapperBase {
const KURL& source_url,
const KURL& base_url,
const ScriptFetchOptions&,
- const String& source_text,
+ const MovableString& source_text,
const TextPosition& start_position);
- static ModuleScript* CreateInternal(const String& source_text,
+ static ModuleScript* CreateInternal(const MovableString& source_text,
Modulator*,
ScriptModule,
const KURL& source_url,
@@ -97,7 +97,7 @@ class CORE_EXPORT ModuleScript final : public Script, public TraceWrapperBase {
// https://html.spec.whatwg.org/multipage/webappapis.html#concept-script-parse-error
//
- // |record_|, |parse_error_| and |error_to_rethrow_| are TraceWrappers()ed and
+ // |record_|, |parse_error_| and |error_to_rethrow_| are wrapper traced and
// kept alive via one or more of following reference graphs:
// * non-inline module script case
// DOMWindow -> Modulator/ModulatorImpl -> ModuleMap -> ModuleMap::Entry
@@ -117,7 +117,7 @@ class CORE_EXPORT ModuleScript final : public Script, public TraceWrapperBase {
// Document -> ScriptRunner -> ScriptLoader -> ModulePendingScript
// -> ModulePendingScriptTreeClient -> ModuleScript.
// All the classes/references on the graphs above should be
- // TraceWrapperBase/TraceWrapperMember<>/etc.,
+ // TraceWrapperMember<>/etc.,
//
// A parse error and an error to rethrow belong to a script, not to a
// |parse_error_| and |error_to_rethrow_| should belong to a script (i.e.
@@ -136,7 +136,7 @@ class CORE_EXPORT ModuleScript final : public Script, public TraceWrapperBase {
TraceWrapperV8Reference<v8::Value> error_to_rethrow_;
// For CSP check.
- const String source_text_;
+ const MovableString source_text_;
const TextPosition start_position_;
HashMap<String, KURL> specifier_to_url_cache_;
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 96842d75dc1..fbca3f9d4e8 100644
--- a/chromium/third_party/blink/renderer/core/script/pending_script.cc
+++ b/chromium/third_party/blink/renderer/core/script/pending_script.cc
@@ -34,7 +34,6 @@
#include "third_party/blink/renderer/core/script/ignore_destructive_write_count_incrementer.h"
#include "third_party/blink/renderer/core/script/script_element_base.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
-#include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink {
@@ -58,7 +57,6 @@ PendingScript::PendingScript(ScriptElementBase* element,
const TextPosition& starting_position)
: element_(element),
starting_position_(starting_position),
- parser_blocking_load_start_time_(0),
virtual_time_pauser_(CreateWebScopedVirtualTimePauser(element)),
client_(nullptr),
original_context_document_(element->GetDocument().ContextDocument()),
@@ -73,7 +71,7 @@ void PendingScript::Dispose() {
DCHECK(!IsWatchingForLoad());
starting_position_ = TextPosition::BelowRangePosition();
- parser_blocking_load_start_time_ = 0;
+ parser_blocking_load_start_time_ = TimeTicks();
DisposeInternal();
element_ = nullptr;
@@ -91,7 +89,7 @@ void PendingScript::WatchForLoad(PendingScriptClient* client) {
// notifyFinished and further stopWatchingForLoad().
client_ = client;
if (IsReady()) {
- client_->PendingScriptFinished(this);
+ PendingScriptFinished();
} else {
virtual_time_pauser_.PauseVirtualTime();
}
@@ -106,6 +104,13 @@ void PendingScript::StopWatchingForLoad() {
virtual_time_pauser_.UnpauseVirtualTime();
}
+void PendingScript::PendingScriptFinished() {
+ virtual_time_pauser_.UnpauseVirtualTime();
+ if (client_) {
+ client_->PendingScriptFinished(this);
+ }
+}
+
ScriptElementBase* PendingScript::GetElement() const {
// As mentioned in the comment at |m_element| declaration,
// |m_element| must point to the corresponding ScriptLoader's
@@ -115,8 +120,8 @@ ScriptElementBase* PendingScript::GetElement() const {
}
void PendingScript::MarkParserBlockingLoadStartTime() {
- DCHECK_EQ(parser_blocking_load_start_time_, 0.0);
- parser_blocking_load_start_time_ = CurrentTimeTicksInSeconds();
+ DCHECK(parser_blocking_load_start_time_.is_null());
+ parser_blocking_load_start_time_ = CurrentTimeTicks();
}
// https://html.spec.whatwg.org/multipage/scripting.html#execute-the-script-block
@@ -162,7 +167,8 @@ void PendingScript::ExecuteScriptBlock(const KURL& document_url) {
const bool was_canceled = WasCanceled();
const bool is_external = IsExternal();
const bool created_during_document_write = WasCreatedDuringDocumentWrite();
- const double parser_blocking_load_start_time = ParserBlockingLoadStartTime();
+ const TimeTicks parser_blocking_load_start_time =
+ ParserBlockingLoadStartTime();
const bool is_controlled_by_script_runner = IsControlledByScriptRunner();
ScriptElementBase* element = element_;
Dispose();
@@ -182,7 +188,7 @@ void PendingScript::ExecuteScriptBlockInternal(
bool was_canceled,
bool is_external,
bool created_during_document_write,
- double parser_blocking_load_start_time,
+ TimeTicks parser_blocking_load_start_time,
bool is_controlled_by_script_runner) {
Document& element_document = element->GetDocument();
Document* context_document = element_document.ContextDocument();
@@ -194,17 +200,17 @@ void PendingScript::ExecuteScriptBlockInternal(
return;
}
- if (parser_blocking_load_start_time > 0.0) {
+ if (parser_blocking_load_start_time > TimeTicks()) {
DocumentParserTiming::From(element_document)
.RecordParserBlockedOnScriptLoadDuration(
- CurrentTimeTicksInSeconds() - parser_blocking_load_start_time,
+ CurrentTimeTicks() - parser_blocking_load_start_time,
created_during_document_write);
}
if (was_canceled)
return;
- double script_exec_start_time = CurrentTimeTicksInSeconds();
+ TimeTicks script_exec_start_time = CurrentTimeTicks();
{
if (element->ElementHasDuplicateAttributes()) {
@@ -279,7 +285,7 @@ void PendingScript::ExecuteScriptBlockInternal(
if (!is_controlled_by_script_runner) {
DocumentParserTiming::From(element_document)
.RecordParserBlockedOnScriptExecutionDuration(
- CurrentTimeTicksInSeconds() - script_exec_start_time,
+ CurrentTimeTicks() - script_exec_start_time,
created_during_document_write);
}
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 5fb3f0d9932..3f641b695c0 100644
--- a/chromium/third_party/blink/renderer/core/script/pending_script.h
+++ b/chromium/third_party/blink/renderer/core/script/pending_script.h
@@ -33,10 +33,11 @@
#include "third_party/blink/renderer/core/script/script.h"
#include "third_party/blink/renderer/core/script/script_element_base.h"
#include "third_party/blink/renderer/core/script/script_scheduling_type.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/text_position.h"
+#include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink {
@@ -63,7 +64,7 @@ class CORE_EXPORT PendingScriptClient : public GarbageCollectedMixin {
// PendingScriptClient is notified.
class CORE_EXPORT PendingScript
: public GarbageCollectedFinalized<PendingScript>,
- public TraceWrapperBase {
+ public NameClient {
public:
virtual ~PendingScript();
@@ -72,19 +73,19 @@ class CORE_EXPORT PendingScript
// Returns the time the load of this script started blocking the parser, or
// zero if this script hasn't yet blocked the parser, in
// monotonicallyIncreasingTime.
- double ParserBlockingLoadStartTime() const {
+ TimeTicks ParserBlockingLoadStartTime() const {
return parser_blocking_load_start_time_;
}
void WatchForLoad(PendingScriptClient*);
void StopWatchingForLoad();
+ void PendingScriptFinished();
ScriptElementBase* GetElement() const;
virtual ScriptType GetScriptType() const = 0;
virtual void Trace(blink::Visitor*);
- void TraceWrappers(ScriptWrappableVisitor*) const override {}
const char* NameInHeapSnapshot() const override { return "PendingScript"; }
virtual Script* GetSource(const KURL& document_url,
@@ -149,14 +150,15 @@ class CORE_EXPORT PendingScript
virtual void CheckState() const = 0;
private:
- static void ExecuteScriptBlockInternal(Script*,
- bool error_occurred,
- ScriptElementBase*,
- bool was_canceled,
- bool is_external,
- bool created_during_document_write,
- double parser_blocking_load_start_time,
- bool is_controlled_by_script_runner);
+ static void ExecuteScriptBlockInternal(
+ Script*,
+ bool error_occurred,
+ ScriptElementBase*,
+ bool was_canceled,
+ bool is_external,
+ bool created_during_document_write,
+ TimeTicks parser_blocking_load_start_time,
+ bool is_controlled_by_script_runner);
// |m_element| must points to the corresponding ScriptLoader's
// ScriptElementBase and thus must be non-null before dispose() is called
@@ -164,7 +166,7 @@ class CORE_EXPORT PendingScript
Member<ScriptElementBase> element_;
TextPosition starting_position_; // Only used for inline script tags.
- double parser_blocking_load_start_time_;
+ TimeTicks parser_blocking_load_start_time_;
ScriptSchedulingType scheduling_type_ = ScriptSchedulingType::kNotSet;
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/README.chromium b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/README.chromium
deleted file mode 100644
index 0660333c855..00000000000
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/README.chromium
+++ /dev/null
@@ -1,12 +0,0 @@
-Name: virtual-list Layered API
-URL: https://github.com/valdrinkoshi/virtual-list
-Version: 4bbc08999515cdf3ce944a150bc6d9949add8978
-Security Critical: no
-
-Description:
-Temporarily, the files under this directory are authored by Chromium Authors
-on a github repository, and then imported to Chromium repository directly here,
-until a long-term Layered API development plan is settled.
-
-Local Modifications:
-None (except for renaming virtual-list-element.js to index.js)
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/index.js b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/index.js
deleted file mode 100644
index 3dfbb62eb26..00000000000
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/index.js
+++ /dev/null
@@ -1,163 +0,0 @@
-import {VirtualList} from './virtual-list.js';
-
-/** Properties */
-const _items = Symbol();
-const _list = Symbol();
-const _newChild = Symbol();
-const _updateChild = Symbol();
-const _recycleChild = Symbol();
-const _itemKey = Symbol();
-const _grid = Symbol();
-const _horizontal = Symbol();
-const _pendingRender = Symbol();
-/** Functions */
-const _render = Symbol();
-const _scheduleRender = Symbol();
-
-// Lazily loaded Layout classes.
-const dynamicImports = {};
-const importLayoutClass = async (url) => {
- if (!dynamicImports[url]) {
- dynamicImports[url] = import(url).then(module => module.default);
- }
- return await dynamicImports[url];
-};
-
-export class VirtualListElement extends HTMLElement {
- constructor() {
- super();
- this[_items] = null;
- this[_list] = null;
- this[_newChild] = null;
- this[_updateChild] = null;
- this[_recycleChild] = null;
- this[_itemKey] = null;
- this[_grid] = false;
- this[_horizontal] = false;
- this[_pendingRender] = null;
- }
-
- connectedCallback() {
- if (!this.shadowRoot) {
- this.attachShadow({mode: 'open'}).innerHTML = `
-<style>
- :host {
- display: block;
- position: relative;
- contain: strict;
- }
- ::slotted(*) {
- box-sizing: border-box;
- max-width: 100%;
- max-height: 100%;
- }
-</style>
-<slot></slot>`;
- }
- this[_scheduleRender]();
- }
-
- static get observedAttributes() {
- return ['layout'];
- }
-
- attributeChangedCallback(name, oldVal, newVal) {
- if (name === 'layout') {
- this.layout = newVal;
- }
- }
-
- get newChild() {
- return this[_newChild];
- }
- set newChild(fn) {
- this[_newChild] = fn;
- this[_scheduleRender]();
- }
-
- get updateChild() {
- return this[_updateChild];
- }
- set updateChild(fn) {
- this[_updateChild] = fn;
- this[_scheduleRender]();
- }
-
- get recycleChild() {
- return this[_recycleChild];
- }
- set recycleChild(fn) {
- this[_recycleChild] = fn;
- this[_scheduleRender]();
- }
-
- get itemKey() {
- return this[_itemKey];
- }
- set itemKey(fn) {
- this[_itemKey] = fn;
- this[_scheduleRender]();
- }
-
- get layout() {
- const prefix = this[_horizontal] ? 'horizontal' : 'vertical';
- const suffix = this[_grid] ? '-grid' : '';
- return prefix + suffix;
- }
- set layout(layout) {
- this[_horizontal] = layout && layout.startsWith('horizontal');
- this[_grid] = layout && layout.endsWith('-grid');
- this[_scheduleRender]();
- }
-
- get items() {
- return this[_items];
- }
- set items(items) {
- this[_items] = items;
- this[_scheduleRender]();
- }
-
- requestReset() {
- if (this[_list]) {
- this[_list].requestReset();
- }
- }
-
- [_scheduleRender]() {
- if (!this[_pendingRender]) {
- this[_pendingRender] = Promise.resolve().then(() => {
- this[_pendingRender] = null;
- this[_render]();
- });
- }
- }
-
- async[_render]() {
- if (!this.newChild) {
- return;
- }
- // Delay init to first connected as list needs to measure
- // sizes of container and children.
- if (!this[_list] && !this.isConnected) {
- return;
- }
-
- if (!this[_list]) {
- this[_list] = new VirtualList({container: this});
- }
- const list = this[_list];
-
- const {newChild, updateChild, recycleChild, itemKey, items} = this;
- Object.assign(list, {newChild, updateChild, recycleChild, itemKey, items});
-
- const Layout = await importLayoutClass(
- this[_grid] ? './layouts/layout-1d-grid.js' : './layouts/layout-1d.js');
- const direction = this[_horizontal] ? 'horizontal' : 'vertical';
- if (list.layout instanceof Layout === false ||
- list.layout.direction !== direction) {
- list.layout = new Layout({direction});
- }
- }
-}
-customElements.define('virtual-list', VirtualListElement); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/layouts/layout-1d-base.js b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/layouts/layout-1d-base.js
deleted file mode 100644
index df58584ecf3..00000000000
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/layouts/layout-1d-base.js
+++ /dev/null
@@ -1,264 +0,0 @@
-export default class Layout extends EventTarget {
- constructor(config) {
- super();
-
- this._physicalMin = 0;
- this._physicalMax = 0;
-
- this._first = -1;
- this._last = -1;
-
- this._latestCoords = {left: 0, top: 0};
-
- this._itemSize = {width: 100, height: 100};
- this._spacing = 0;
-
- this._virtualScroll = false;
-
- this._sizeDim = 'height';
- this._secondarySizeDim = 'width';
- this._positionDim = 'top';
- this._secondaryPositionDim = 'left';
- this._direction = 'vertical';
-
- this._scrollPosition = 0;
- this._viewportSize = {width: 0, height: 0};
- this._totalItems = 0;
-
- this._scrollSize = 1;
-
- this._overhang = 150;
-
- Object.assign(this, config);
- }
-
- // public properties
-
- set virtualScroll(bool) {
- this._virtualScroll = bool;
- }
-
- get virtualScroll() {
- return this._virtualScroll;
- }
-
- set spacing(px) {
- if (px !== this._spacing) {
- this._spacing = px;
- this._scheduleReflow();
- }
- }
-
- get spacing() {
- return this._spacing;
- }
-
- set itemSize(dims) {
- const {_itemDim1, _itemDim2} = this;
- Object.assign(this._itemSize, dims);
- if (_itemDim1 !== this._itemDim1 || _itemDim2 !== this._itemDim2) {
- if (_itemDim2 !== this._itemDim2) {
- this._itemDim2Changed();
- } else {
- this._scheduleReflow();
- }
- }
- }
-
- _itemDim2Changed() {
- // Override
- }
-
- get _delta() {
- return this._itemDim1 + this._spacing;
- }
-
- get _itemDim1() {
- return this._itemSize[this._sizeDim];
- }
-
- get _itemDim2() {
- return this._itemSize[this._secondarySizeDim];
- }
-
- get itemSize() {
- return this._itemSize;
- }
-
- set direction(dir) {
- // Force it to be either horizontal or vertical.
- dir = (dir === 'horizontal') ? dir : 'vertical';
- if (dir !== this._direction) {
- this._direction = dir;
- this._sizeDim = (dir === 'horizontal') ? 'width' : 'height';
- this._secondarySizeDim = (dir === 'horizontal') ? 'height' : 'width';
- this._positionDim = (dir === 'horizontal') ? 'left' : 'top';
- this._secondaryPositionDim = (dir === 'horizontal') ? 'top' : 'left';
- this._scheduleReflow();
- }
- }
-
- get direction() {
- return this._direction;
- }
-
- set viewportSize(dims) {
- const {_viewDim1, _viewDim2} = this;
- Object.assign(this._viewportSize, dims);
- if (_viewDim1 !== this._viewDim1 || _viewDim2 !== this._viewDim2) {
- if (_viewDim2 !== this._viewDim2) {
- this._viewDim2Changed();
- } else {
- this._checkThresholds();
- }
- }
- }
-
- _viewDim2Changed() {
- // Override
- }
-
- get _viewDim1() {
- return this._viewportSize[this._sizeDim];
- }
-
- get _viewDim2() {
- return this._viewportSize[this._secondarySizeDim];
- }
-
- get viewportSize() {
- return this._viewportSize;
- }
-
- set totalItems(num) {
- if (num !== this._totalItems) {
- this._totalItems = num;
- this._maxIdx = num - 1;
- this._scheduleReflow();
- }
- }
-
- get totalItems() {
- return this._totalItems;
- }
-
- // private properties
-
- get _num() {
- if (this._first === -1 || this._last === -1) {
- return 0;
- }
- return this._last - this._first + 1;
- }
-
- // public methods
-
- scrollTo(coords) {
- this._latestCoords = coords;
- this._scroll();
- }
-
- //
-
- _scroll() {
- this._scrollPosition = this._latestCoords[this._positionDim];
-
- this._checkThresholds();
- }
-
- _getActiveItems() {
- // Override
- }
-
- // TODO: Does this need to be public?
- _reflow() {
- const {_first, _last, _scrollSize} = this;
-
- this._updateScrollSize();
- this._getActiveItems();
-
- if (this._scrollSize !== _scrollSize) {
- this._emitScrollSize();
- }
-
- if (this._first === -1 && this._last === -1) {
- this._emitRange();
- } else if (
- this._first !== _first || this._last !== _last ||
- this._spacingChanged) {
- this._emitRange();
- this._emitChildPositions();
- }
- this._pendingReflow = null;
- }
-
- _scheduleReflow() {
- if (!this._pendingReflow) {
- this._pendingReflow = Promise.resolve().then(() => this._reflow());
- }
- }
-
- _updateScrollSize() {
- // Ensure we have at least 1px - this allows getting at least 1 item to be
- // rendered.
- this._scrollSize = Math.max(1, this._totalItems * this._delta);
- }
-
- _checkThresholds() {
- if (this._viewDim1 === 0 && this._num > 0) {
- this._scheduleReflow();
- } else {
- const min = Math.max(0, this._scrollPosition - this._overhang);
- const max = Math.min(
- this._scrollSize,
- this._scrollPosition + this._viewDim1 + this._overhang);
- if (this._physicalMin > min || this._physicalMax < max) {
- this._scheduleReflow();
- }
- }
- }
-
- ///
-
- _emitRange(inProps) {
- const detail = Object.assign(
- {
- first: this._first,
- last: this._last,
- num: this._num,
- stable: true,
- },
- inProps);
- this.dispatchEvent(new CustomEvent('rangechange', {detail}));
- }
-
- _emitScrollSize() {
- const detail = {
- [this._sizeDim]: this._scrollSize,
- };
- this.dispatchEvent(new CustomEvent('scrollsizechange', {detail}));
- }
-
- _emitScrollError() {
- if (this._scrollError) {
- const detail = {
- [this._positionDim]: this._scrollError,
- [this._secondaryPositionDim]: 0,
- };
- this.dispatchEvent(new CustomEvent('scrollerrorchange', {detail}));
- this._scrollError = 0;
- }
- }
-
- _emitChildPositions() {
- const detail = {};
- for (let idx = this._first; idx <= this._last; idx++) {
- detail[idx] = this._getItemPosition(idx);
- }
- this.dispatchEvent(new CustomEvent('itempositionchange', {detail}));
- }
-
- _getItemPosition(idx) {
- // Override.
- }
-} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/layouts/layout-1d-grid.js b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/layouts/layout-1d-grid.js
deleted file mode 100644
index f2b208d656f..00000000000
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/layouts/layout-1d-grid.js
+++ /dev/null
@@ -1,66 +0,0 @@
-import Layout1dBase from './layout-1d-base.js';
-
-export default class Layout extends Layout1dBase {
- constructor(config) {
- super(config);
- this._rolumns = 1;
- }
-
- updateItemSizes(sizes) {
- // Assume all items have the same size.
- const size = Object.values(sizes)[0];
- if (size) {
- this.itemSize = size;
- }
- }
-
- _viewDim2Changed() {
- this._defineGrid();
- }
-
- _itemDim2Changed() {
- this._defineGrid();
- }
-
- _getActiveItems() {
- const {_scrollPosition, _scrollSize} = this;
-
- const min = Math.max(0, this._scrollPosition - this._overhang);
- const max = Math.min(
- this._scrollSize,
- this._scrollPosition + this._viewDim1 + this._overhang);
- const firstCow = Math.floor(min / this._delta);
- const lastCow = Math.ceil(max / this._delta) - 1;
-
- this._first = firstCow * this._rolumns;
- this._last =
- Math.min(((lastCow + 1) * this._rolumns) - 1, this._totalItems);
- this._physicalMin = this._delta * firstCow;
- this._physicalMax = this._delta * (lastCow + 1);
- }
-
- _getItemPosition(idx) {
- return {
- [this._positionDim]: Math.floor(idx / this._rolumns) * this._delta,
- [this._secondaryPositionDim]: this._spacing +
- ((idx % this._rolumns) * (this._spacing + this._itemDim2))
- }
- }
-
-
- _defineGrid() {
- const {_spacing} = this;
- this._rolumns = Math.max(1, Math.floor(this._viewDim2 / this._itemDim2));
- if (this._rolumns > 1) {
- this._spacing = (this._viewDim2 % (this._rolumns * this._itemDim2)) /
- (this._rolumns + 1);
- }
- this._spacingChanged = !(_spacing === this._spacing);
- this._scheduleReflow();
- }
-
- _updateScrollSize() {
- this._scrollSize =
- Math.max(1, Math.ceil(this._totalItems / this._rolumns) * this._delta);
- }
-} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/layouts/layout-1d.js b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/layouts/layout-1d.js
deleted file mode 100644
index 38447806f29..00000000000
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/layouts/layout-1d.js
+++ /dev/null
@@ -1,329 +0,0 @@
-import Layout1dBase from './layout-1d-base.js';
-
-export default class Layout extends Layout1dBase {
- constructor(config) {
- super(config);
- this._physicalItems = new Map();
- this._newPhysicalItems = new Map();
-
- this._metrics = new Map();
-
- this._anchorIdx = null;
- this._anchorPos = null;
- this._scrollError = 0;
- this._stable = true;
-
- this._needsRemeasure = false;
-
- this._nMeasured = 0;
- this._tMeasured = 0;
-
- this._estimate = true;
- }
-
- updateItemSizes(sizes) {
- Object.keys(sizes).forEach((key) => {
- const metrics = sizes[key], mi = this._getMetrics(key),
- prevSize = mi[this._sizeDim];
-
- // TODO(valdrin) Handle margin collapsing.
- // https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing
- mi.width = metrics.width + (metrics.marginLeft || 0) +
- (metrics.marginRight || 0);
- mi.height = metrics.height + (metrics.marginTop || 0) +
- (metrics.marginBottom || 0);
-
- const size = mi[this._sizeDim];
- const item = this._getPhysicalItem(Number(key));
- if (item) {
- let delta;
-
- if (size !== undefined) {
- item.size = size;
- if (prevSize === undefined) {
- delta = size;
- this._nMeasured++;
- } else {
- delta = size - prevSize;
- }
- }
- this._tMeasured = this._tMeasured + delta;
- } else {
- // console.debug(`Could not find physical item for key ${key}`);
- }
- });
- if (!this._nMeasured) {
- console.warn(`No items measured yet.`);
- } else {
- this._updateItemSize();
- this._scheduleReflow();
- }
- }
-
- _updateItemSize() {
- this._itemSize[this._sizeDim] = this._tMeasured / this._nMeasured;
- }
-
- //
-
- _getMetrics(idx) {
- return (this._metrics[idx] = this._metrics[idx] || {});
- }
-
- _getPhysicalItem(idx) {
- return this._newPhysicalItems.get(idx) || this._physicalItems.get(idx);
- }
-
- _getSize(idx) {
- const item = this._getPhysicalItem(idx);
- return item && item.size;
- }
-
- _getPosition(idx) {
- const item = this._physicalItems.get(idx);
- return item ? item.pos : (idx * (this._delta)) + this._spacing;
- }
-
- _calculateAnchor(lower, upper) {
- if (lower === 0) {
- return 0;
- }
- if (upper > this._scrollSize - this._viewDim1) {
- return this._maxIdx;
- }
- return Math.max(
- 0,
- Math.min(
- this._maxIdx, Math.floor(((lower + upper) / 2) / this._delta)));
- }
-
- _setAnchor(lower, upper) {
- if (this._physicalItems.size === 0) {
- return this._calculateAnchor(lower, upper);
- }
- if (this._first < 0) {
- console.error('_setAnchor: negative _first');
- return this._calculateAnchor(lower, upper);
- }
- if (this._last < 0) {
- console.error('_setAnchor: negative _last');
- return this._calculateAnchor(lower, upper);
- }
-
- const firstItem = this._getPhysicalItem(this._first),
- lastItem = this._getPhysicalItem(this._last),
- firstMin = firstItem.pos, firstMax = firstMin + firstItem.size,
- lastMin = lastItem.pos, lastMax = lastMin + lastItem.size;
-
- if (lastMax < lower) {
- // Window is entirely past physical items, calculate new anchor
- return this._calculateAnchor(lower, upper);
- }
- if (firstMin > upper) {
- // Window is entirely before physical items, calculate new anchor
- return this._calculateAnchor(lower, upper);
- }
- if (firstMin >= lower || firstMax >= lower) {
- // First physical item overlaps window, choose it
- return this._first;
- }
- if (lastMax <= upper || lastMin <= upper) {
- // Last physical overlaps window, choose it
- return this._last;
- }
- // Window contains a physical item, but not the first or last
- let maxIdx = this._last, minIdx = this._first;
-
- while (true) {
- let candidateIdx = Math.round((maxIdx + minIdx) / 2),
- candidate = this._physicalItems.get(candidateIdx),
- cMin = candidate.pos, cMax = cMin + candidate.size;
-
- if ((cMin >= lower && cMin <= upper) ||
- (cMax >= lower && cMax <= upper)) {
- return candidateIdx;
- } else if (cMax < lower) {
- minIdx = candidateIdx + 1;
- } else if (cMin > upper) {
- maxIdx = candidateIdx - 1;
- }
- }
- }
-
- _getActiveItems() {
- if (this._viewDim1 === 0 || this._totalItems === 0) {
- this._clearItems();
- } else {
- const upper = Math.min(
- this._scrollSize,
- this._scrollPosition + this._viewDim1 + this._overhang),
- lower = Math.max(0, upper - this._viewDim1 - (2 * this._overhang));
-
- this._getItems(lower, upper);
- }
- }
-
- _clearItems() {
- this._first = -1;
- this._last = -1;
- this._physicalMin = 0;
- this._physicalMax = 0;
- const items = this._newPhysicalItems;
- this._newPhysicalItems = this._physicalItems;
- this._newPhysicalItems.clear();
- this._physicalItems = items;
- this._stable = true;
- }
-
- _getItems(lower, upper) {
- const items = this._newPhysicalItems;
-
- if (this._anchorIdx === null || this._anchorPos === null) {
- this._anchorIdx = this._setAnchor(lower, upper);
- this._anchorPos = this._getPosition(this._anchorIdx);
- }
-
- let anchorSize = this._getSize(this._anchorIdx);
- if (anchorSize === undefined) {
- anchorSize = this._itemDim1;
- }
-
- let anchorErr = 0;
-
- if (this._anchorPos + anchorSize + this._spacing < lower) {
- anchorErr = lower - (this._anchorPos + anchorSize + this._spacing);
- }
-
- if (this._anchorPos > upper) {
- anchorErr = upper - this._anchorPos;
- }
-
- if (anchorErr) {
- this._scrollPosition -= anchorErr;
- lower -= anchorErr;
- upper -= anchorErr;
- this._scrollError += anchorErr;
- }
-
- items.set(this._anchorIdx, {pos: this._anchorPos, size: anchorSize});
-
- this._first = (this._last = this._anchorIdx);
- this._physicalMin = (this._physicalMax = this._anchorPos);
-
- this._stable = true;
-
- while (this._physicalMin > lower && this._first > 0) {
- let size = this._getSize(--this._first);
- if (size === undefined) {
- this._stable = false;
- size = this._itemDim1;
- }
- const pos = (this._physicalMin -= size + this._spacing);
- items.set(this._first, {pos, size});
- if (this._stable === false && this._estimate === false) {
- break;
- }
- }
-
- while (this._physicalMax < upper && this._last < this._totalItems) {
- let size = this._getSize(this._last);
- if (size === undefined) {
- this._stable = false;
- size = this._itemDim1;
- }
- items.set(this._last++, {pos: this._physicalMax, size});
- if (this._stable === false && this._estimate === false) {
- break;
- } else {
- this._physicalMax += size + this._spacing;
- }
- }
-
- this._last--;
-
- const extentErr = this._calculateError();
- if (extentErr) {
- this._physicalMin -= extentErr;
- this._physicalMax -= extentErr;
- this._anchorPos -= extentErr;
- this._scrollPosition -= extentErr;
- items.forEach(item => item.pos -= extentErr);
- this._scrollError += extentErr;
- }
-
- if (this._stable) {
- this._newPhysicalItems = this._physicalItems;
- this._newPhysicalItems.clear();
- this._physicalItems = items;
- }
- }
-
- _calculateError() {
- if (this._first === 0) {
- return this._physicalMin;
- } else if (this._physicalMin <= 0) {
- return this._physicalMin - (this._first * this._delta);
- } else if (this._last === this._maxIdx) {
- return this._physicalMax - this._scrollSize;
- } else if (this._physicalMax >= this._scrollSize) {
- return (
- (this._physicalMax - this._scrollSize) +
- ((this._maxIdx - this._last) * this._delta));
- }
- return 0;
- }
-
- // TODO: Can this be made to inherit from base, with proper hooks?
- _reflow() {
- const {_first, _last, _scrollSize} = this;
-
- this._updateScrollSize();
- this._getActiveItems();
-
- if (this._scrollSize !== _scrollSize) {
- this._emitScrollSize();
- }
-
- if (this._first === -1 && this._last === -1) {
- this._emitRange();
- this._resetReflowState();
- } else if (
- this._first !== _first || this._last !== _last ||
- this._needsRemeasure) {
- this._emitRange();
- this._emitScrollError();
- this._emitChildPositions();
- } else {
- this._emitRange();
- this._emitScrollError();
- this._emitChildPositions();
- this._resetReflowState();
- }
- this._pendingReflow = null;
- }
-
- _resetReflowState() {
- this._anchorIdx = null;
- this._anchorPos = null;
- this._stable = true;
- }
-
- _getItemPosition(idx) {
- return {
- [this._positionDim]: this._getPosition(idx),
- [this._secondaryPositionDim]: 0
- }
- }
-
- _viewDim2Changed() {
- this._needsRemeasure = true;
- this._scheduleReflow();
- }
-
- _emitRange() {
- const remeasure = this._needsRemeasure;
- const stable = this._stable;
- this._needsRemeasure = false;
- super._emitRange({remeasure, stable});
- }
-}
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/virtual-list.js b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/virtual-list.js
deleted file mode 100644
index 22050869249..00000000000
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/virtual-list.js
+++ /dev/null
@@ -1,255 +0,0 @@
-import {Repeats} from './virtual-repeater.js';
-
-export class RangeChangeEvent extends Event {
- constructor(type, init) {
- super(type, init);
- this._first = Math.floor(init.first || 0);
- this._last = Math.floor(init.last || 0);
- }
- get first() {
- return this._first;
- }
- get last() {
- return this._last;
- }
-}
-
-export const RepeatsAndScrolls = Superclass => class extends Repeats
-(Superclass) {
- constructor(config) {
- super();
- this._num = 0;
- this._first = -1;
- this._last = -1;
- this._prevFirst = -1;
- this._prevLast = -1;
-
- this._pendingUpdateView = null;
- this._isContainerVisible = false;
- this._containerElement = null;
-
- if (config) {
- Object.assign(this, config);
- }
- }
-
- get container() {
- return this._container;
- }
- set container(container) {
- if (container === this._container) {
- return;
- }
-
- removeEventListener('scroll', this);
- removeEventListener('resize', this);
-
- super.container = container;
-
- if (container) {
- addEventListener('scroll', this);
- addEventListener('resize', this);
- this._scheduleUpdateView();
- }
-
- // Update the containerElement, copy min-width/height styles to new
- // container.
- let containerStyle = null;
- if (this._containerElement) {
- containerStyle = this._containerElement.getAttribute('style');
- this._containerElement.removeAttribute('style');
- }
- // Consider document fragments as shadowRoots.
- this._containerElement =
- (container && container.nodeType === Node.DOCUMENT_FRAGMENT_NODE) ?
- container.host :
- container;
-
- if (this._containerElement && containerStyle) {
- this._containerElement.setAttribute('style', containerStyle);
- }
- }
-
- get layout() {
- return this._layout;
- }
- set layout(layout) {
- if (layout === this._layout) {
- return;
- }
-
- if (this._layout) {
- this._measureCallback = null;
- this._layout.removeEventListener('scrollsizechange', this);
- this._layout.removeEventListener('scrollerrorchange', this);
- this._layout.removeEventListener('itempositionchange', this);
- this._layout.removeEventListener('rangechange', this);
- // Remove min-width/height from containerElement so
- // layout can get correct viewport size.
- if (this._containerElement) {
- this._containerElement.removeAttribute('style');
- this.requestRemeasure();
- }
- }
-
- this._layout = layout;
-
- if (this._layout) {
- if (typeof this._layout.updateItemSizes === 'function') {
- this._measureCallback = this._layout.updateItemSizes.bind(this._layout);
- }
- this._layout.addEventListener('scrollsizechange', this);
- this._layout.addEventListener('scrollerrorchange', this);
- this._layout.addEventListener('itempositionchange', this);
- this._layout.addEventListener('rangechange', this);
- this._scheduleUpdateView();
- }
- }
-
- requestReset() {
- super.requestReset();
- this._scheduleUpdateView();
- }
-
- /**
- * @param {!Event} event
- * @private
- */
- handleEvent(event) {
- switch (event.type) {
- case 'scroll':
- case 'resize':
- this._scheduleUpdateView();
- break;
- case 'scrollsizechange':
- this._sizeContainer(event.detail);
- break;
- case 'scrollerrorchange':
- this._correctScrollError(event.detail);
- break;
- case 'itempositionchange':
- this._positionChildren(event.detail);
- break;
- case 'rangechange':
- this._adjustRange(event.detail);
- break;
- default:
- console.warn('event not handled', event);
- }
- }
-
- // Rename _ordered to _kids?
- /**
- * @protected
- */
- get _kids() {
- return this._ordered;
- }
- /**
- * @private
- */
- _scheduleUpdateView() {
- if (!this._pendingUpdateView && this._container && this._layout) {
- this._pendingUpdateView =
- Promise.resolve().then(() => this._updateView());
- }
- }
- /**
- * @private
- */
- _updateView() {
- this._pendingUpdateView = null;
-
- this._layout.totalItems = this._items ? this._items.length : 0;
-
- const listBounds = this._containerElement.getBoundingClientRect();
- // Avoid updating viewport if container is not visible.
- this._isContainerVisible = Boolean(
- listBounds.width || listBounds.height || listBounds.top ||
- listBounds.left);
- if (!this._isContainerVisible) {
- return;
- }
-
- const scrollerWidth = window.innerWidth;
- const scrollerHeight = window.innerHeight;
- const xMin = Math.max(0, Math.min(scrollerWidth, listBounds.left));
- const yMin = Math.max(0, Math.min(scrollerHeight, listBounds.top));
- const xMax = this._layout.direction === 'vertical' ?
- Math.max(0, Math.min(scrollerWidth, listBounds.right)) :
- scrollerWidth;
- const yMax = this._layout.direction === 'vertical' ?
- scrollerHeight :
- Math.max(0, Math.min(scrollerHeight, listBounds.bottom));
- const width = xMax - xMin;
- const height = yMax - yMin;
- this._layout.viewportSize = {width, height};
-
- const left = Math.max(0, -listBounds.x);
- const top = Math.max(0, -listBounds.y);
- this._layout.scrollTo({top, left});
- }
- /**
- * @private
- */
- _sizeContainer(size) {
- const style = this._containerElement.style;
- style.minWidth = size.width ? size.width + 'px' : null;
- style.minHeight = size.height ? size.height + 'px' : null;
- }
- /**
- * @private
- */
- async _positionChildren(pos) {
- await Promise.resolve();
- const kids = this._kids;
- Object.keys(pos).forEach(key => {
- const idx = key - this._first;
- const child = kids[idx];
- if (child) {
- const {top, left} = pos[key];
- // console.debug(`_positionChild #${this._container.id} > #${child.id}:
- // top ${top}`);
- child.style.position = 'absolute';
- child.style.transform = `translate(${left}px, ${top}px)`;
- }
- });
- }
- /**
- * @private
- */
- _adjustRange(range) {
- this.num = range.num;
- this.first = range.first;
- this._incremental = !(range.stable);
- if (range.remeasure) {
- this.requestRemeasure();
- } else if (range.stable) {
- this._notifyStable();
- }
- }
- /**
- * @protected
- */
- _shouldRender() {
- return Boolean(
- this._isContainerVisible && this._layout && super._shouldRender());
- }
- /**
- * @private
- */
- _correctScrollError(err) {
- window.scroll(window.scrollX - err.left, window.scrollY - err.top);
- }
- /**
- * @protected
- */
- _notifyStable() {
- const {first, num} = this;
- const last = first + num;
- this._container.dispatchEvent(
- new RangeChangeEvent('rangechange', {first, last}));
- }
-};
-
-export const VirtualList = RepeatsAndScrolls(class {});
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/virtual-repeater.js b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/virtual-repeater.js
deleted file mode 100644
index ccc46b1b9e0..00000000000
--- a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-list/virtual-repeater.js
+++ /dev/null
@@ -1,522 +0,0 @@
-export const Repeats = Superclass => class extends Superclass {
- constructor(config) {
- super();
-
- this._newChildFn = null;
- this._updateChildFn = null;
- this._recycleChildFn = null;
- this._itemKeyFn = null;
-
- this._measureCallback = null;
-
- this._items = null;
- // Consider renaming this. firstVisibleIndex?
- this._first = 0;
- // Consider renaming this. count? visibleElements?
- this._num = Infinity;
-
- this.__incremental = false;
-
- // used only internally..
- // legacy from 1st approach to preact integration
- this._manageDom = true;
- // used to check if it is more perf if you don't care of dom order?
- this._maintainDomOrder = true;
-
- this._last = 0;
- this._prevFirst = 0;
- this._prevLast = 0;
-
- this._needsReset = false;
- this._needsRemeasure = false;
- this._pendingRender = null;
-
- // Contains child nodes in the rendered order.
- this._ordered = [];
- // this._pool = [];
- this._active = new Map();
- this._prevActive = new Map();
- // Both used for recycling purposes.
- this._keyToChild = new Map();
- this._childToKey = new WeakMap();
- // Used to keep track of measures by index.
- this._indexToMeasure = {};
-
- if (config) {
- Object.assign(this, config);
- }
- }
-
- // API
-
- get container() {
- return this._container;
- }
- set container(container) {
- if (container === this._container) {
- return;
- }
- if (this._container) {
- // Remove children from old container.
- this._ordered.forEach((child) => this._removeChild(child));
- }
-
- this._container = container;
-
- if (container) {
- // Insert children in new container.
- this._ordered.forEach((child) => this._insertBefore(child, null));
- } else {
- this._ordered.length = 0;
- this._active.clear();
- this._prevActive.clear();
- }
- this.requestReset();
- }
-
- get newChild() {
- return this._newChildFn;
- }
- set newChild(fn) {
- if (fn !== this._newChildFn) {
- this._newChildFn = fn;
- this._keyToChild.clear();
- this.requestReset();
- }
- }
-
- get updateChild() {
- return this._updateChildFn;
- }
- set updateChild(fn) {
- if (fn !== this._updateChildFn) {
- this._updateChildFn = fn;
- this.requestReset();
- }
- }
-
- get recycleChild() {
- return this._recycleChildFn;
- }
- set recycleChild(fn) {
- if (fn !== this._recycleChildFn) {
- this._recycleChildFn = fn;
- this.requestReset();
- }
- }
-
- get itemKey() {
- return this._itemKeyFn;
- }
- set itemKey(fn) {
- if (fn !== this._itemKeyFn) {
- this._itemKeyFn = fn;
- this._keyToChild.clear();
- this.requestReset();
- }
- }
-
- get first() {
- return this._first;
- }
-
- set first(idx) {
- if (typeof idx === 'number') {
- const len = this._items ? this._items.length : 0;
- const newFirst = Math.max(0, Math.min(idx, len - this._num));
- if (newFirst !== this._first) {
- this._first = newFirst;
- this._scheduleRender();
- }
- }
- }
-
- get num() {
- return this._num;
- }
-
- set num(n) {
- if (typeof n === 'number') {
- if (n !== this._num) {
- this._num = n;
- this.first = this._first;
- this._scheduleRender();
- }
- }
- }
-
- get items() {
- return this._items;
- }
-
- set items(arr) {
- if (arr !== this._items) {
- this._items = arr;
- this.first = this._first;
- this.requestReset();
- }
- }
-
- get _incremental() {
- return this.__incremental;
- }
-
- set _incremental(inc) {
- if (inc !== this.__incremental) {
- this.__incremental = inc;
- this._scheduleRender();
- }
- }
-
- requestReset() {
- this._needsReset = true;
- this._scheduleRender();
- }
-
- requestRemeasure() {
- this._needsRemeasure = true;
- this._scheduleRender();
- }
-
- // Core functionality
-
- /**
- * @protected
- */
- _shouldRender() {
- return Boolean(this.items && this.container && this.newChild);
- }
-
- /**
- * @private
- */
- _scheduleRender() {
- if (!this._pendingRender && this._shouldRender()) {
- this._pendingRender = Promise.resolve().then(() => this._render());
- }
- }
-
- /**
- * Returns those children that are about to be displayed and that
- * require to be positioned. If reset or remeasure has been triggered,
- * all children are returned.
- * @return {{indices:Array<number>,children:Array<Element>}}
- * @private
- */
- get _toMeasure() {
- return this._ordered.reduce((toMeasure, c, i) => {
- const idx = this._first + i;
- if (this._needsReset || this._needsRemeasure || idx < this._prevFirst ||
- idx > this._prevLast) {
- toMeasure.indices.push(idx);
- toMeasure.children.push(c);
- }
- return toMeasure;
- }, {indices: [], children: []});
- }
-
- /**
- * Measures each child bounds and builds a map of index/bounds to be passed to
- * the `_measureCallback`
- * @private
- */
- async _measureChildren() {
- if (this._ordered.length > 0) {
- const {indices, children} = this._toMeasure;
- await Promise.resolve();
- const pm = await Promise.all(children.map(
- (c, i) => this._indexToMeasure[indices[i]] || this._measureChild(c)));
- const mm = /** @type {{ number: { width: number, height: number } }} */
- (pm.reduce((out, cur, i) => {
- out[indices[i]] = this._indexToMeasure[indices[i]] = cur;
- return out;
- }, {}));
- this._measureCallback(mm);
- }
- }
-
- /**
- * @protected
- */
- _render() {
- // 1. create DOM
- // 2. measure DOM
- // 3. recycle DOM
- const rangeChanged =
- this._first !== this._prevFirst || this._num !== this._prevNum;
- if (rangeChanged || this._needsReset) {
- this._last = this._first +
- Math.min(this._num, this._items.length - this._first) - 1;
- if (this._num || this._prevNum) {
- if (this._needsReset) {
- this._reset(this._first, this._last);
- } else {
- this._discardHead();
- this._discardTail();
- this._addHead();
- this._addTail();
- }
- }
- }
- if (this._needsRemeasure || this._needsReset) {
- this._indexToMeasure = {};
- }
- const shouldMeasure = this._num > 0 && this._measureCallback &&
- (rangeChanged || this._needsRemeasure || this._needsReset);
- // console.debug(`#${this._container.id} _render: ${this._num}/${
- // this._items.length} ${this._first} -> ${this._last}
- // (${this._prevNum}/${this._items.length} ${this._prevFirst} ->
- // ${this._prevLast}) measure=${shouldMeasure}`);
- if (shouldMeasure) {
- this._measureChildren();
- }
-
- // Cleanup
- if (!this._incremental) {
- this._prevActive.forEach((idx, child) => this._unassignChild(child, idx));
- this._prevActive.clear();
- }
-
- this._prevFirst = this._first;
- this._prevLast = this._last;
- this._prevNum = this._num;
- this._needsReset = false;
- this._needsRemeasure = false;
- this._pendingRender = null;
- }
-
- /**
- * @private
- */
- _discardHead() {
- const o = this._ordered;
- for (let idx = this._prevFirst; o.length && idx < this._first; idx++) {
- this._unassignChild(o.shift(), idx);
- }
- }
-
- /**
- * @private
- */
- _discardTail() {
- const o = this._ordered;
- for (let idx = this._prevLast; o.length && idx > this._last; idx--) {
- this._unassignChild(o.pop(), idx);
- }
- }
-
- /**
- * @private
- */
- _addHead() {
- const start = this._first;
- const end = Math.min(this._last, this._prevFirst - 1);
- for (let idx = end; idx >= start; idx--) {
- const child = this._assignChild(idx);
- const item = this._items[idx];
- if (this._manageDom) {
- if (this._maintainDomOrder || !this._childIsAttached(child)) {
- this._insertBefore(child, this._firstChild);
- }
- }
- if (this.updateChild) {
- this.updateChild(child, item, idx);
- }
- this._ordered.unshift(child);
- }
- }
-
- /**
- * @private
- */
- _addTail() {
- const start = Math.max(this._first, this._prevLast + 1);
- const end = this._last;
- for (let idx = start; idx <= end; idx++) {
- const child = this._assignChild(idx);
- const item = this._items[idx];
- if (this._manageDom) {
- if (this._maintainDomOrder || !this._childIsAttached(child)) {
- this._insertBefore(child, null);
- }
- }
- if (this.updateChild) {
- this.updateChild(child, item, idx);
- }
- this._ordered.push(child);
- }
- }
-
- /**
- * @param {number} first
- * @param {number} last
- * @private
- */
- _reset(first, last) {
- const len = last - first + 1;
- // Explain why swap prevActive with active - affects _assignChild.
- const prevActive = this._active;
- this._active = this._prevActive;
- this._prevActive = prevActive;
- let currentMarker = this._manageDom && this._firstChild;
- this._ordered.length = 0;
- for (let n = 0; n < len; n++) {
- const idx = first + n;
- const item = this._items[idx];
- const child = this._assignChild(idx);
- this._ordered.push(child);
- if (this._manageDom) {
- if (currentMarker && this._maintainDomOrder) {
- if (currentMarker === this._node(child)) {
- currentMarker = this._nextSibling(child);
- } else {
- this._insertBefore(child, currentMarker);
- }
- } else if (!this._childIsAttached(child)) {
- this._insertBefore(child, null);
- }
- }
- if (this.updateChild) {
- this.updateChild(child, item, idx);
- }
- }
- }
-
- /**
- * @param {number} idx
- * @private
- */
- _assignChild(idx) {
- const item = this._items[idx];
- const key = this.itemKey ? this.itemKey(item) : idx;
- let child;
- if (child = this._keyToChild.get(key)) {
- this._prevActive.delete(child);
- } else {
- child = this.newChild(item, idx);
- this._keyToChild.set(key, child);
- this._childToKey.set(child, key);
- }
- this._showChild(child);
- this._active.set(child, idx);
- return child;
- }
-
- /**
- * @param {*} child
- * @param {number} idx
- * @private
- */
- _unassignChild(child, idx) {
- this._hideChild(child);
- if (this._incremental) {
- this._active.delete(child);
- this._prevActive.set(child, idx);
- } else {
- const key = this._childToKey.get(child);
- this._childToKey.delete(child);
- this._keyToChild.delete(key);
- this._active.delete(child);
- if (this.recycleChild) {
- this.recycleChild(child, this._items[idx], idx);
- } else {
- this._removeChild(child);
- }
- }
- }
-
- // TODO: Is this the right name?
- /**
- * @private
- */
- get _firstChild() {
- return this._ordered.length ? this._node(this._ordered[0]) : null;
- }
-
- // Overridable abstractions for child manipulation
- /**
- * @protected
- */
- _node(child) {
- return child;
- }
- /**
- * @protected
- */
- _nextSibling(child) {
- return child.nextSibling;
- }
- /**
- * @protected
- */
- _insertBefore(child, referenceNode) {
- this._container.insertBefore(child, referenceNode);
- }
- /**
- * @protected
- */
- _childIsAttached(child) {
- const node = this._node(child);
- return node && node.parentNode === this._container;
- }
- /**
- * @protected
- */
- _hideChild(child) {
- if (child.style) {
- child.style.display = 'none';
- }
- }
- /**
- * @protected
- */
- _showChild(child) {
- if (child.style) {
- child.style.display = null;
- }
- }
-
- /**
- *
- * @param {!Element} child
- * @return {{width: number, height: number, marginTop: number, marginBottom: number, marginLeft: number, marginRight: number}} childMeasures
- * @protected
- */
- _measureChild(child) {
- // offsetWidth doesn't take transforms in consideration,
- // so we use getBoundingClientRect which does.
- const {width, height} = child.getBoundingClientRect();
- // console.debug(`_measureChild #${this._container.id} > #${
- // child.id}: height: ${height}px`);
- return Object.assign({width, height}, getMargins(child));
- }
-
- /**
- * Remove child.
- * Override to control child removal.
- *
- * @param {*} child
- * @protected
- */
- _removeChild(child) {
- child.parentNode.removeChild(child);
- }
-}
-
-function getMargins(el) {
- const style = window.getComputedStyle(el);
- // console.log(el.id, style.position);
- return {
- marginLeft: getMarginValue(style.marginLeft),
- marginRight: getMarginValue(style.marginRight),
- marginTop: getMarginValue(style.marginTop),
- marginBottom: getMarginValue(style.marginBottom),
- };
-}
-
-function getMarginValue(value) {
- value = value ? parseFloat(value) : NaN;
- return value !== value ? 0 : value;
-}
-
-export const VirtualRepeater = Repeats(class {}); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/README.chromium b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/README.chromium
new file mode 100644
index 00000000000..4b0028ae557
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/README.chromium
@@ -0,0 +1,12 @@
+Name: virtual-scroller Layered API
+URL: https://github.com/valdrinkoshi/virtual-scroller
+Version: 58659cee10c5d9237821d5c475dac89720bd995d
+Security Critical: no
+
+Description:
+Temporarily, the files under this directory are authored by Chromium Authors
+on a github repository, and then imported to Chromium repository directly here,
+until a long-term Layered API development plan is settled.
+
+Local Modifications:
+None (except for renaming virtual-scroller-element.js to index.js)
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/index.js b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/index.js
new file mode 100644
index 00000000000..d6ddb091791
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/index.js
@@ -0,0 +1,213 @@
+import {_item, _key, ItemSource} from './item-source.js';
+import {default as Layout1dGrid} from './layouts/layout-1d-grid.js';
+import {default as Layout1d} from './layouts/layout-1d.js';
+import {VirtualScroller} from './virtual-scroller.js';
+
+export {ItemSource};
+
+/** Properties */
+const _scroller = Symbol();
+const _createElement = Symbol();
+const _updateElement = Symbol();
+const _recycleElement = Symbol();
+const _nodePool = Symbol();
+const _rawItemSource = Symbol();
+const _itemSource = Symbol();
+const _elementSource = Symbol();
+const _firstConnected = Symbol();
+/** Functions */
+const _render = Symbol();
+
+export class VirtualScrollerElement extends HTMLElement {
+ constructor() {
+ super();
+ this[_scroller] = null;
+ // Default create/update/recycleElement.
+ this[_nodePool] = [];
+ let childTemplate = null;
+ this[_createElement] = () => {
+ if (this[_nodePool] && this[_nodePool].length) {
+ return this[_nodePool].pop();
+ }
+ if (!childTemplate) {
+ const template = this.querySelector('template');
+ childTemplate = template && template.content.firstElementChild ?
+ template.content.firstElementChild :
+ document.createElement('div');
+ }
+ return childTemplate.cloneNode(true);
+ };
+ this[_updateElement] = (element, item) => element.textContent =
+ item.toString();
+ this[_recycleElement] = (element) => this[_nodePool].push(element);
+
+ this[_itemSource] = this[_rawItemSource] = null;
+ this[_elementSource] = {};
+
+ this[_firstConnected] = false;
+ }
+
+ connectedCallback() {
+ if (!this[_firstConnected]) {
+ this.attachShadow({mode: 'open'}).innerHTML = `
+<style>
+ :host {
+ display: block;
+ position: relative;
+ contain: strict;
+ height: 150px;
+ overflow: auto;
+ }
+ :host([hidden]) {
+ display: none;
+ }
+ ::slotted(*) {
+ box-sizing: border-box;
+ }
+ :host([layout=vertical]) ::slotted(*) {
+ width: 100%;
+ }
+ :host([layout=horizontal]) ::slotted(*) {
+ height: 100%;
+ }
+</style>
+<slot></slot>`;
+ // Set default values.
+ if (!this.layout) {
+ this.layout = 'vertical';
+ }
+ // Enables rendering.
+ this[_firstConnected] = true;
+ }
+ this[_render]();
+ }
+
+ static get observedAttributes() {
+ return ['layout'];
+ }
+
+ attributeChangedCallback(name, oldVal, newVal) {
+ this[_render]();
+ }
+
+ get layout() {
+ return this.getAttribute('layout');
+ }
+ set layout(layout) {
+ this.setAttribute('layout', layout);
+ }
+
+ get itemSource() {
+ return this[_itemSource];
+ }
+ set itemSource(itemSource) {
+ // No Change.
+ if (this[_rawItemSource] === itemSource) {
+ return;
+ }
+ this[_rawItemSource] = itemSource;
+ this[_itemSource] = Array.isArray(itemSource) ?
+ ItemSource.fromArray(itemSource) :
+ itemSource;
+ this[_render]();
+ }
+
+ get createElement() {
+ return this[_createElement];
+ }
+ set createElement(fn) {
+ // Resets default recycling.
+ if (this[_nodePool]) {
+ this.recycleElement = null;
+ }
+ this[_createElement] = fn;
+ // Invalidate wrapped function.
+ this[_elementSource].createElement = null;
+ this[_render]();
+ }
+
+ get updateElement() {
+ return this[_updateElement];
+ }
+ set updateElement(fn) {
+ this[_updateElement] = fn;
+ // Invalidate wrapped function.
+ this[_elementSource].updateElement = null;
+ this[_render]();
+ }
+
+ get recycleElement() {
+ return this[_recycleElement];
+ }
+ set recycleElement(fn) {
+ // Marks default recycling changed.
+ this[_nodePool] = null;
+ this[_recycleElement] = fn;
+ // Invalidate wrapped function.
+ this[_elementSource].recycleElement = null;
+ this[_render]();
+ }
+
+ itemsChanged() {
+ if (this[_scroller]) {
+ // Render because length might have changed.
+ this[_render]();
+ // Request reset because items might have changed.
+ this[_scroller].requestReset();
+ }
+ }
+
+ scrollToIndex(index, { position = 'start' } = {}) {
+ if (this[_scroller]) {
+ this[_scroller].layout.scrollToIndex(index, position);
+ }
+ }
+
+ [_render]() {
+ // Wait first connected as scroller needs to measure
+ // sizes of container and children.
+ if (!this[_firstConnected] || !this.createElement) {
+ return;
+ }
+ if (!this[_scroller]) {
+ this[_scroller] =
+ new VirtualScroller({container: this, scrollTarget: this});
+ }
+ const scroller = this[_scroller];
+
+ const layoutAttr = this.layout;
+ const Layout = layoutAttr.endsWith('-grid') ? Layout1dGrid : Layout1d;
+ const direction =
+ layoutAttr.startsWith('horizontal') ? 'horizontal' : 'vertical';
+ const layout = scroller.layout instanceof Layout &&
+ scroller.layout.direction === direction ?
+ scroller.layout :
+ new Layout({direction});
+
+ let {createElement, updateElement, recycleElement} = this[_elementSource];
+ if (!createElement) {
+ createElement = this[_elementSource].createElement = (index) =>
+ this.createElement(this.itemSource[_item](index), index);
+ }
+ if (this.updateElement && !updateElement) {
+ updateElement = this[_elementSource].updateElement = (element, index) =>
+ this.updateElement(element, this.itemSource[_item](index), index);
+ }
+ if (this.recycleElement && !recycleElement) {
+ recycleElement = this[_elementSource].recycleElement = (element, index) =>
+ this.recycleElement(element, this.itemSource[_item](index), index);
+ }
+
+ const elementKey = this.itemSource ? this.itemSource[_key] : null;
+ const totalItems = this.itemSource ? this.itemSource.length : 0;
+ Object.assign(scroller, {
+ layout,
+ createElement,
+ updateElement,
+ recycleElement,
+ elementKey,
+ totalItems
+ });
+ }
+}
+customElements.define('virtual-scroller', VirtualScrollerElement);
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/item-source.js b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/item-source.js
new file mode 100644
index 00000000000..255e97b245c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/item-source.js
@@ -0,0 +1,47 @@
+export const _getLength = Symbol();
+export const _item = Symbol();
+export const _key = Symbol();
+
+export class ItemSource {
+ constructor({getLength, item, key}) {
+ if (typeof getLength !== 'function') {
+ throw new TypeError('getLength option must be a function');
+ }
+ if (typeof item !== 'function') {
+ throw new TypeError('item option must be a function');
+ }
+ if (typeof key !== 'function') {
+ throw new TypeError('key option must be a function');
+ }
+
+ this[_getLength] = getLength;
+ this[_item] = item;
+ this[_key] = key;
+ }
+
+ static fromArray(array, key) {
+ if (!Array.isArray(array)) {
+ throw new TypeError('First argument to fromArray() must be an array');
+ }
+ if (typeof key !== 'function' && key !== undefined) {
+ throw new TypeError(
+ 'Second argument to fromArray() must be a function or undefined');
+ }
+
+ return new this({
+ getLength() {
+ return array.length;
+ },
+ item(index) {
+ return array[index];
+ },
+ key(index) {
+ return key ? key(array[index], index) : array[index];
+ }
+ });
+ }
+
+ get length() {
+ return this[_getLength]();
+ }
+}
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d-base.js b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d-base.js
new file mode 100644
index 00000000000..89a9a9e8106
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d-base.js
@@ -0,0 +1,320 @@
+export default class Layout extends EventTarget {
+ constructor(config) {
+ super();
+
+ this._physicalMin = 0;
+ this._physicalMax = 0;
+
+ this._first = -1;
+ this._last = -1;
+
+ this._latestCoords = {left: 0, top: 0};
+
+ this._itemSize = {width: 100, height: 100};
+ this._spacing = 0;
+
+ this._sizeDim = 'height';
+ this._secondarySizeDim = 'width';
+ this._positionDim = 'top';
+ this._secondaryPositionDim = 'left';
+ this._direction = 'vertical';
+
+ this._scrollPosition = 0;
+ this._scrollError = 0;
+ this._viewportSize = {width: 0, height: 0};
+ this._totalItems = 0;
+
+ this._scrollSize = 1;
+
+ this._overhang = 150;
+
+ this._pendingReflow = false;
+
+ this._scrollToIndex = -1;
+ this._scrollToAnchor = 0;
+
+ Object.assign(this, config);
+ }
+
+ // public properties
+
+ get totalItems() {
+ return this._totalItems;
+ }
+ set totalItems(num) {
+ if (num !== this._totalItems) {
+ this._totalItems = num;
+ this._maxIdx = num - 1;
+ this._scheduleReflow();
+ }
+ }
+
+ get direction() {
+ return this._direction;
+ }
+ set direction(dir) {
+ // Force it to be either horizontal or vertical.
+ dir = (dir === 'horizontal') ? dir : 'vertical';
+ if (dir !== this._direction) {
+ this._direction = dir;
+ this._sizeDim = (dir === 'horizontal') ? 'width' : 'height';
+ this._secondarySizeDim = (dir === 'horizontal') ? 'height' : 'width';
+ this._positionDim = (dir === 'horizontal') ? 'left' : 'top';
+ this._secondaryPositionDim = (dir === 'horizontal') ? 'top' : 'left';
+ this._scheduleReflow();
+ }
+ }
+
+ get itemSize() {
+ return this._itemSize;
+ }
+ set itemSize(dims) {
+ const {_itemDim1, _itemDim2} = this;
+ Object.assign(this._itemSize, dims);
+ if (_itemDim1 !== this._itemDim1 || _itemDim2 !== this._itemDim2) {
+ if (_itemDim2 !== this._itemDim2) {
+ this._itemDim2Changed();
+ } else {
+ this._scheduleReflow();
+ }
+ }
+ }
+
+ get spacing() {
+ return this._spacing;
+ }
+ set spacing(px) {
+ if (px !== this._spacing) {
+ this._spacing = px;
+ this._scheduleReflow();
+ }
+ }
+
+ get viewportSize() {
+ return this._viewportSize;
+ }
+ set viewportSize(dims) {
+ const {_viewDim1, _viewDim2} = this;
+ Object.assign(this._viewportSize, dims);
+ if (_viewDim2 !== this._viewDim2) {
+ this._viewDim2Changed();
+ } else if (_viewDim1 !== this._viewDim1) {
+ this._checkThresholds();
+ }
+ }
+
+ get viewportScroll() {
+ return this._latestCoords;
+ }
+ set viewportScroll(coords) {
+ Object.assign(this._latestCoords, coords);
+ const oldPos = this._scrollPosition;
+ this._scrollPosition = this._latestCoords[this._positionDim];
+ if (oldPos !== this._scrollPosition) {
+ this._scrollPositionChanged(oldPos, this._scrollPosition);
+ }
+ this._checkThresholds();
+ }
+
+ // private properties
+
+ get _delta() {
+ return this._itemDim1 + this._spacing;
+ }
+
+ get _itemDim1() {
+ return this._itemSize[this._sizeDim];
+ }
+
+ get _itemDim2() {
+ return this._itemSize[this._secondarySizeDim];
+ }
+
+ get _viewDim1() {
+ return this._viewportSize[this._sizeDim];
+ }
+
+ get _viewDim2() {
+ return this._viewportSize[this._secondarySizeDim];
+ }
+
+ get _num() {
+ if (this._first === -1 || this._last === -1) {
+ return 0;
+ }
+ return this._last - this._first + 1;
+ }
+
+ // public methods
+
+ reflowIfNeeded() {
+ if (this._pendingReflow) {
+ this._pendingReflow = false;
+ this._reflow();
+ }
+ }
+
+ scrollToIndex(index, position = 'start') {
+ if (!Number.isFinite(index))
+ return;
+ index = Math.min(this.totalItems, Math.max(0, index));
+ this._scrollToIndex = index;
+ if (position === 'nearest') {
+ position = index > this._first + this._num / 2 ? 'end' : 'start';
+ }
+ switch (position) {
+ case 'start':
+ this._scrollToAnchor = 0;
+ break;
+ case 'center':
+ this._scrollToAnchor = 0.5;
+ break;
+ case 'end':
+ this._scrollToAnchor = 1;
+ break;
+ default:
+ throw new TypeError(
+ 'position must be one of: start, center, end, nearest');
+ }
+ this._scheduleReflow();
+ this.reflowIfNeeded();
+ }
+
+ ///
+
+ _scheduleReflow() {
+ this._pendingReflow = true;
+ }
+
+ _reflow() {
+ const {_first, _last, _scrollSize} = this;
+
+ this._updateScrollSize();
+ this._getActiveItems();
+ this._scrollIfNeeded();
+
+ if (this._scrollSize !== _scrollSize) {
+ this._emitScrollSize();
+ }
+
+ if (this._first === -1 && this._last === -1) {
+ this._emitRange();
+ } else if (
+ this._first !== _first || this._last !== _last ||
+ this._spacingChanged) {
+ this._emitRange();
+ this._emitChildPositions();
+ }
+ this._emitScrollError();
+ }
+
+ _updateScrollSize() {
+ // Ensure we have at least 1px - this allows getting at least 1 item to be
+ // rendered.
+ this._scrollSize = Math.max(1, this._totalItems * this._delta);
+ }
+
+ _checkThresholds() {
+ if (this._viewDim1 === 0 && this._num > 0) {
+ this._scheduleReflow();
+ } else {
+ const min = Math.max(0, this._scrollPosition - this._overhang);
+ const max = Math.min(
+ this._scrollSize,
+ this._scrollPosition + this._viewDim1 + this._overhang);
+ if (this._physicalMin > min || this._physicalMax < max) {
+ this._scheduleReflow();
+ }
+ }
+ }
+
+ _scrollIfNeeded() {
+ if (this._scrollToIndex === -1) {
+ return;
+ }
+ const index = this._scrollToIndex;
+ const anchor = this._scrollToAnchor;
+ const pos = this._getItemPosition(index)[this._positionDim];
+ const size = this._getItemSize(index)[this._sizeDim];
+
+ const curAnchorPos = this._scrollPosition + this._viewDim1 * anchor;
+ const newAnchorPos = pos + size * anchor;
+ // Ensure scroll position is an integer within scroll bounds.
+ const scrollPosition = Math.floor(Math.min(
+ this._scrollSize - this._viewDim1,
+ Math.max(0, this._scrollPosition - curAnchorPos + newAnchorPos)));
+ this._scrollError += this._scrollPosition - scrollPosition;
+ this._scrollPosition = scrollPosition;
+ }
+
+ _emitRange(inProps) {
+ const detail = Object.assign(
+ {
+ first: this._first,
+ last: this._last,
+ num: this._num,
+ stable: true,
+ },
+ inProps);
+ this.dispatchEvent(new CustomEvent('rangechange', {detail}));
+ }
+
+ _emitScrollSize() {
+ const detail = {
+ [this._sizeDim]: this._scrollSize,
+ };
+ this.dispatchEvent(new CustomEvent('scrollsizechange', {detail}));
+ }
+
+ _emitScrollError() {
+ if (this._scrollError) {
+ const detail = {
+ [this._positionDim]: this._scrollError,
+ [this._secondaryPositionDim]: 0,
+ };
+ this.dispatchEvent(new CustomEvent('scrollerrorchange', {detail}));
+ this._scrollError = 0;
+ }
+ }
+
+ _emitChildPositions() {
+ const detail = {};
+ for (let idx = this._first; idx <= this._last; idx++) {
+ detail[idx] = this._getItemPosition(idx);
+ }
+ this.dispatchEvent(new CustomEvent('itempositionchange', {detail}));
+ }
+
+ _itemDim2Changed() {
+ // Override
+ }
+
+ _viewDim2Changed() {
+ // Override
+ }
+
+ _scrollPositionChanged(oldPos, newPos) {
+ // When both values are bigger than the max scroll position, keep the
+ // current _scrollToIndexx, otherwise invalidate it.
+ const maxPos = this._scrollSize - this._viewDim1;
+ if (oldPos < maxPos || newPos < maxPos) {
+ this._scrollToIndex = -1;
+ }
+ }
+
+ _getActiveItems() {
+ // Override
+ }
+
+ _getItemPosition(idx) {
+ // Override.
+ }
+
+ _getItemSize(idx) {
+ // Override.
+ return {
+ [this._sizeDim]: this._itemDim1,
+ [this._secondarySizeDim]: this._itemDim2,
+ };
+ }
+} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d-grid.js b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d-grid.js
new file mode 100644
index 00000000000..4d49707004f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d-grid.js
@@ -0,0 +1,64 @@
+import Layout1dBase from './layout-1d-base.js';
+
+export default class Layout extends Layout1dBase {
+ constructor(config) {
+ super(config);
+ this._rolumns = 1;
+ }
+
+ updateItemSizes(sizes) {
+ // Assume all items have the same size.
+ const size = Object.values(sizes)[0];
+ if (size) {
+ this.itemSize = size;
+ }
+ }
+
+ _viewDim2Changed() {
+ this._defineGrid();
+ }
+
+ _itemDim2Changed() {
+ this._defineGrid();
+ }
+
+ _getActiveItems() {
+ const min = Math.max(0, this._scrollPosition - this._overhang);
+ const max = Math.min(
+ this._scrollSize,
+ this._scrollPosition + this._viewDim1 + this._overhang);
+ const firstCow = Math.floor(min / this._delta);
+ const lastCow = Math.ceil(max / this._delta) - 1;
+
+ this._first = firstCow * this._rolumns;
+ this._last =
+ Math.min(((lastCow + 1) * this._rolumns) - 1, this._totalItems);
+ this._physicalMin = this._delta * firstCow;
+ this._physicalMax = this._delta * (lastCow + 1);
+ }
+
+ _getItemPosition(idx) {
+ return {
+ [this._positionDim]: Math.floor(idx / this._rolumns) * this._delta,
+ [this._secondaryPositionDim]: this._spacing +
+ ((idx % this._rolumns) * (this._spacing + this._itemDim2))
+ }
+ }
+
+
+ _defineGrid() {
+ const {_spacing} = this;
+ this._rolumns = Math.max(1, Math.floor(this._viewDim2 / this._itemDim2));
+ if (this._rolumns > 1) {
+ this._spacing = (this._viewDim2 % (this._rolumns * this._itemDim2)) /
+ (this._rolumns + 1);
+ }
+ this._spacingChanged = !(_spacing === this._spacing);
+ this._scheduleReflow();
+ }
+
+ _updateScrollSize() {
+ this._scrollSize =
+ Math.max(1, Math.ceil(this._totalItems / this._rolumns) * this._delta);
+ }
+} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d.js b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d.js
new file mode 100644
index 00000000000..bbd262d8e86
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/layouts/layout-1d.js
@@ -0,0 +1,349 @@
+import Layout1dBase from './layout-1d-base.js';
+
+export default class Layout extends Layout1dBase {
+ constructor(config) {
+ super(config);
+ this._physicalItems = new Map();
+ this._newPhysicalItems = new Map();
+
+ this._metrics = new Map();
+
+ this._anchorIdx = null;
+ this._anchorPos = null;
+ this._stable = true;
+
+ this._needsRemeasure = false;
+
+ this._nMeasured = 0;
+ this._tMeasured = 0;
+
+ this._estimate = true;
+ }
+
+ updateItemSizes(sizes) {
+ Object.keys(sizes).forEach((key) => {
+ const metrics = sizes[key], mi = this._getMetrics(key),
+ prevSize = mi[this._sizeDim];
+
+ // TODO(valdrin) Handle margin collapsing.
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing
+ mi.width = metrics.width + (metrics.marginLeft || 0) +
+ (metrics.marginRight || 0);
+ mi.height = metrics.height + (metrics.marginTop || 0) +
+ (metrics.marginBottom || 0);
+
+ const size = mi[this._sizeDim];
+ const item = this._getPhysicalItem(Number(key));
+ if (item) {
+ let delta;
+
+ if (size !== undefined) {
+ item.size = size;
+ if (prevSize === undefined) {
+ delta = size;
+ this._nMeasured++;
+ } else {
+ delta = size - prevSize;
+ }
+ }
+ this._tMeasured = this._tMeasured + delta;
+ } else {
+ // console.debug(`Could not find physical item for key ${key}`);
+ }
+ });
+ if (!this._nMeasured) {
+ console.warn(`No items measured yet.`);
+ } else {
+ this._updateItemSize();
+ this._scheduleReflow();
+ }
+ }
+
+ _updateItemSize() {
+ // Keep integer values.
+ this._itemSize[this._sizeDim] =
+ Math.round(this._tMeasured / this._nMeasured);
+ }
+
+ //
+
+ _getMetrics(idx) {
+ return (this._metrics[idx] = this._metrics[idx] || {});
+ }
+
+ _getPhysicalItem(idx) {
+ return this._newPhysicalItems.get(idx) || this._physicalItems.get(idx);
+ }
+
+ _getSize(idx) {
+ const item = this._getPhysicalItem(idx);
+ return item && item.size;
+ }
+
+ _getPosition(idx) {
+ const item = this._physicalItems.get(idx);
+ return item ? item.pos : (idx * (this._delta)) + this._spacing;
+ }
+
+ _calculateAnchor(lower, upper) {
+ if (lower === 0) {
+ return 0;
+ }
+ if (upper > this._scrollSize - this._viewDim1) {
+ return this._maxIdx;
+ }
+ return Math.max(
+ 0,
+ Math.min(
+ this._maxIdx, Math.floor(((lower + upper) / 2) / this._delta)));
+ }
+
+ _getAnchor(lower, upper) {
+ if (this._physicalItems.size === 0) {
+ return this._calculateAnchor(lower, upper);
+ }
+ if (this._first < 0) {
+ console.error('_getAnchor: negative _first');
+ return this._calculateAnchor(lower, upper);
+ }
+ if (this._last < 0) {
+ console.error('_getAnchor: negative _last');
+ return this._calculateAnchor(lower, upper);
+ }
+
+ const firstItem = this._getPhysicalItem(this._first),
+ lastItem = this._getPhysicalItem(this._last),
+ firstMin = firstItem.pos, firstMax = firstMin + firstItem.size,
+ lastMin = lastItem.pos, lastMax = lastMin + lastItem.size;
+
+ if (lastMax < lower) {
+ // Window is entirely past physical items, calculate new anchor
+ return this._calculateAnchor(lower, upper);
+ }
+ if (firstMin > upper) {
+ // Window is entirely before physical items, calculate new anchor
+ return this._calculateAnchor(lower, upper);
+ }
+ if (firstMin >= lower || firstMax >= lower) {
+ // First physical item overlaps window, choose it
+ return this._first;
+ }
+ if (lastMax <= upper || lastMin <= upper) {
+ // Last physical overlaps window, choose it
+ return this._last;
+ }
+ // Window contains a physical item, but not the first or last
+ let maxIdx = this._last, minIdx = this._first;
+
+ while (true) {
+ let candidateIdx = Math.round((maxIdx + minIdx) / 2),
+ candidate = this._physicalItems.get(candidateIdx),
+ cMin = candidate.pos, cMax = cMin + candidate.size;
+
+ if ((cMin >= lower && cMin <= upper) ||
+ (cMax >= lower && cMax <= upper)) {
+ return candidateIdx;
+ } else if (cMax < lower) {
+ minIdx = candidateIdx + 1;
+ } else if (cMin > upper) {
+ maxIdx = candidateIdx - 1;
+ }
+ }
+ }
+
+ _getActiveItems() {
+ if (this._viewDim1 === 0 || this._totalItems === 0) {
+ this._clearItems();
+ } else {
+ const upper = Math.min(
+ this._scrollSize,
+ this._scrollPosition + this._viewDim1 + this._overhang),
+ lower = Math.max(0, upper - this._viewDim1 - (2 * this._overhang));
+
+ this._getItems(lower, upper);
+ }
+ }
+
+ _clearItems() {
+ this._first = -1;
+ this._last = -1;
+ this._physicalMin = 0;
+ this._physicalMax = 0;
+ const items = this._newPhysicalItems;
+ this._newPhysicalItems = this._physicalItems;
+ this._newPhysicalItems.clear();
+ this._physicalItems = items;
+ this._stable = true;
+ }
+
+ _getItems(lower, upper) {
+ const items = this._newPhysicalItems;
+
+ // The anchorIdx is the anchor around which we reflow.
+ // It is designed to allow jumping to any point of the scroll size.
+ // We choose it once and stick with it until stable. first and last are
+ // deduced around it.
+ if (this._anchorIdx === null || this._anchorPos === null) {
+ this._anchorIdx = this._getAnchor(lower, upper);
+ this._anchorPos = this._getPosition(this._anchorIdx);
+ }
+
+ let anchorSize = this._getSize(this._anchorIdx);
+ if (anchorSize === undefined) {
+ anchorSize = this._itemDim1;
+ }
+
+ // Anchor might be outside bounds, so prefer correcting the error and keep
+ // that anchorIdx.
+ let anchorErr = 0;
+
+ if (this._anchorPos + anchorSize + this._spacing < lower) {
+ anchorErr = lower - (this._anchorPos + anchorSize + this._spacing);
+ }
+
+ if (this._anchorPos > upper) {
+ anchorErr = upper - this._anchorPos;
+ }
+
+ if (anchorErr) {
+ this._scrollPosition -= anchorErr;
+ lower -= anchorErr;
+ upper -= anchorErr;
+ this._scrollError += anchorErr;
+ }
+
+ items.set(this._anchorIdx, {pos: this._anchorPos, size: anchorSize});
+
+ this._first = (this._last = this._anchorIdx);
+ this._physicalMin = (this._physicalMax = this._anchorPos);
+
+ this._stable = true;
+
+ while (this._physicalMin > lower && this._first > 0) {
+ let size = this._getSize(--this._first);
+ if (size === undefined) {
+ this._stable = false;
+ size = this._itemDim1;
+ }
+ const pos = (this._physicalMin -= size + this._spacing);
+ items.set(this._first, {pos, size});
+ if (this._stable === false && this._estimate === false) {
+ break;
+ }
+ }
+
+ while (this._physicalMax < upper && this._last < this._totalItems) {
+ let size = this._getSize(this._last);
+ if (size === undefined) {
+ this._stable = false;
+ size = this._itemDim1;
+ }
+ items.set(this._last++, {pos: this._physicalMax, size});
+ if (this._stable === false && this._estimate === false) {
+ break;
+ } else {
+ this._physicalMax += size + this._spacing;
+ }
+ }
+
+ this._last--;
+
+ // This handles the cases where we were relying on estimated sizes.
+ const extentErr = this._calculateError();
+ if (extentErr) {
+ this._physicalMin -= extentErr;
+ this._physicalMax -= extentErr;
+ this._anchorPos -= extentErr;
+ this._scrollPosition -= extentErr;
+ items.forEach(item => item.pos -= extentErr);
+ this._scrollError += extentErr;
+ }
+
+ if (this._stable) {
+ this._newPhysicalItems = this._physicalItems;
+ this._newPhysicalItems.clear();
+ this._physicalItems = items;
+ }
+ }
+
+ _calculateError() {
+ if (this._first === 0) {
+ return this._physicalMin;
+ } else if (this._physicalMin <= 0) {
+ return this._physicalMin - (this._first * this._delta);
+ } else if (this._last === this._maxIdx) {
+ return this._physicalMax - this._scrollSize;
+ } else if (this._physicalMax >= this._scrollSize) {
+ return (
+ (this._physicalMax - this._scrollSize) +
+ ((this._maxIdx - this._last) * this._delta));
+ }
+ return 0;
+ }
+
+ _updateScrollSize() {
+ // Reuse previously calculated physical max, as it might be
+ // higher than the estimated size.
+ super._updateScrollSize();
+ this._scrollSize = Math.max(this._physicalMax, this._scrollSize);
+ }
+
+ // TODO: Can this be made to inherit from base, with proper hooks?
+ _reflow() {
+ const {_first, _last, _scrollSize} = this;
+
+ this._updateScrollSize();
+ this._getActiveItems();
+ this._scrollIfNeeded();
+
+ if (this._scrollSize !== _scrollSize) {
+ this._emitScrollSize();
+ }
+
+ this._emitRange();
+ if (this._first === -1 && this._last === -1) {
+ this._resetReflowState();
+ } else if (
+ this._first !== _first || this._last !== _last ||
+ this._needsRemeasure) {
+ this._emitChildPositions();
+ this._emitScrollError();
+ } else {
+ this._emitChildPositions();
+ this._emitScrollError();
+ this._resetReflowState();
+ }
+ }
+
+ _resetReflowState() {
+ this._anchorIdx = null;
+ this._anchorPos = null;
+ this._stable = true;
+ }
+
+ _getItemPosition(idx) {
+ return {
+ [this._positionDim]: this._getPosition(idx),
+ [this._secondaryPositionDim]: 0
+ }
+ }
+
+ _getItemSize(idx) {
+ return {
+ [this._sizeDim]: this._getSize(idx) || this._itemDim1,
+ [this._secondarySizeDim]: this._itemDim2,
+ };
+ }
+
+ _viewDim2Changed() {
+ this._needsRemeasure = true;
+ this._scheduleReflow();
+ }
+
+ _emitRange() {
+ const remeasure = this._needsRemeasure;
+ const stable = this._stable;
+ this._needsRemeasure = false;
+ super._emitRange({remeasure, stable});
+ }
+}
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/virtual-repeater.js b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/virtual-repeater.js
new file mode 100644
index 00000000000..3d3cb6aa7c1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/virtual-repeater.js
@@ -0,0 +1,531 @@
+export const Repeats = Superclass => class extends Superclass {
+ constructor(config) {
+ super();
+
+ this._createElementFn = null;
+ this._updateElementFn = null;
+ this._recycleElementFn = null;
+ this._elementKeyFn = null;
+
+ this._measureCallback = null;
+
+ this._totalItems = 0;
+ // Consider renaming this. firstVisibleIndex?
+ this._first = 0;
+ // Consider renaming this. count? visibleElements?
+ this._num = Infinity;
+
+ this.__incremental = false;
+
+ // used only internally..
+ // legacy from 1st approach to preact integration
+ this._manageDom = true;
+ // used to check if it is more perf if you don't care of dom order?
+ this._maintainDomOrder = true;
+
+ this._last = 0;
+ this._prevFirst = 0;
+ this._prevLast = 0;
+
+ this._needsReset = false;
+ this._needsRemeasure = false;
+ this._pendingRender = null;
+
+ // Contains child nodes in the rendered order.
+ this._ordered = [];
+ // this._pool = [];
+ this._active = new Map();
+ this._prevActive = new Map();
+ // Both used for recycling purposes.
+ this._keyToChild = new Map();
+ this._childToKey = new WeakMap();
+ // Used to keep track of measures by index.
+ this._indexToMeasure = {};
+ // Used to debounce _measureChildren calls.
+ this._measuringId = -1;
+
+ if (config) {
+ Object.assign(this, config);
+ }
+ }
+
+ // API
+
+ get container() {
+ return this._container;
+ }
+ set container(container) {
+ if (container === this._container) {
+ return;
+ }
+ if (this._container) {
+ // Remove children from old container.
+ this._ordered.forEach((child) => this._removeChild(child));
+ }
+
+ this._container = container;
+
+ if (container) {
+ // Insert children in new container.
+ this._ordered.forEach((child) => this._insertBefore(child, null));
+ } else {
+ this._ordered.length = 0;
+ this._active.clear();
+ this._prevActive.clear();
+ }
+ this.requestReset();
+ }
+
+ get createElement() {
+ return this._createElementFn;
+ }
+ set createElement(fn) {
+ if (fn !== this._createElementFn) {
+ this._createElementFn = fn;
+ this._keyToChild.clear();
+ this.requestReset();
+ }
+ }
+
+ get updateElement() {
+ return this._updateElementFn;
+ }
+ set updateElement(fn) {
+ if (fn !== this._updateElementFn) {
+ this._updateElementFn = fn;
+ this.requestReset();
+ }
+ }
+
+ get recycleElement() {
+ return this._recycleElementFn;
+ }
+ set recycleElement(fn) {
+ if (fn !== this._recycleElementFn) {
+ this._recycleElementFn = fn;
+ this.requestReset();
+ }
+ }
+
+ get elementKey() {
+ return this._elementKeyFn;
+ }
+ set elementKey(fn) {
+ if (fn !== this._elementKeyFn) {
+ this._elementKeyFn = fn;
+ this._keyToChild.clear();
+ this.requestReset();
+ }
+ }
+
+ get first() {
+ return this._first;
+ }
+
+ set first(idx) {
+ if (typeof idx === 'number') {
+ const newFirst = Math.max(0, Math.min(idx, this._totalItems - this._num));
+ if (newFirst !== this._first) {
+ this._first = newFirst;
+ this._scheduleRender();
+ }
+ }
+ }
+
+ get num() {
+ return this._num;
+ }
+
+ set num(n) {
+ if (typeof n === 'number') {
+ if (n !== this._num) {
+ this._num = n;
+ this.first = this._first;
+ this._scheduleRender();
+ }
+ }
+ }
+
+ get totalItems() {
+ return this._totalItems;
+ }
+
+ set totalItems(num) {
+ // TODO(valdrin) should we check if it is a finite number?
+ // Technically, Infinity would break Layout, not VirtualRepeater.
+ if (typeof num === 'number' && num !== this._totalItems) {
+ this._totalItems = num;
+ this.first = this._first;
+ this.requestReset();
+ }
+ }
+
+ get _incremental() {
+ return this.__incremental;
+ }
+
+ set _incremental(inc) {
+ if (inc !== this.__incremental) {
+ this.__incremental = inc;
+ this._scheduleRender();
+ }
+ }
+
+ requestReset() {
+ this._needsReset = true;
+ this._scheduleRender();
+ }
+
+ requestRemeasure() {
+ this._needsRemeasure = true;
+ this._scheduleRender();
+ }
+
+ // Core functionality
+
+ /**
+ * @protected
+ */
+ _shouldRender() {
+ return Boolean(this.container && this.createElement);
+ }
+
+ /**
+ * @private
+ */
+ _scheduleRender() {
+ if (!this._pendingRender) {
+ this._pendingRender = requestAnimationFrame(() => {
+ this._pendingRender = null;
+ if (this._shouldRender()) {
+ this._render();
+ }
+ });
+ }
+ }
+
+ /**
+ * Returns those children that are about to be displayed and that
+ * require to be positioned. If reset or remeasure has been triggered,
+ * all children are returned.
+ * @return {{indices:Array<number>,children:Array<Element>}}
+ * @private
+ */
+ get _toMeasure() {
+ return this._ordered.reduce((toMeasure, c, i) => {
+ const idx = this._first + i;
+ if (this._needsReset || this._needsRemeasure || idx < this._prevFirst ||
+ idx > this._prevLast) {
+ toMeasure.indices.push(idx);
+ toMeasure.children.push(c);
+ }
+ return toMeasure;
+ }, {indices: [], children: []});
+ }
+
+ /**
+ * Measures each child bounds and builds a map of index/bounds to be passed to
+ * the `_measureCallback`
+ * @private
+ */
+ _measureChildren({indices, children}) {
+ let pm = children.map(
+ (c, i) => this._indexToMeasure[indices[i]] || this._measureChild(c));
+ const mm = /** @type {{ number: { width: number, height: number } }} */
+ (pm.reduce((out, cur, i) => {
+ out[indices[i]] = this._indexToMeasure[indices[i]] = cur;
+ return out;
+ }, {}));
+ this._measureCallback(mm);
+ }
+
+ /**
+ * @protected
+ */
+ _render() {
+ const rangeChanged =
+ this._first !== this._prevFirst || this._num !== this._prevNum;
+ // Create/update/recycle DOM.
+ if (rangeChanged || this._needsReset) {
+ this._last =
+ this._first + Math.min(this._num, this._totalItems - this._first) - 1;
+ if (this._num || this._prevNum) {
+ if (this._needsReset) {
+ this._reset(this._first, this._last);
+ } else {
+ this._discardHead();
+ this._discardTail();
+ this._addHead();
+ this._addTail();
+ }
+ }
+ }
+ if (this._needsRemeasure || this._needsReset) {
+ this._indexToMeasure = {};
+ }
+ // Retrieve DOM to be measured.
+ // Do it right before cleanup and reset of properties.
+ const shouldMeasure = this._num > 0 && this._measureCallback &&
+ (rangeChanged || this._needsRemeasure || this._needsReset);
+ const toMeasure = shouldMeasure ? this._toMeasure : null;
+
+ // Cleanup.
+ if (!this._incremental) {
+ this._prevActive.forEach((idx, child) => this._unassignChild(child, idx));
+ this._prevActive.clear();
+ }
+ // Reset internal properties.
+ this._prevFirst = this._first;
+ this._prevLast = this._last;
+ this._prevNum = this._num;
+ this._needsReset = false;
+ this._needsRemeasure = false;
+
+ // Notify render completed.
+ this._didRender();
+ // Measure DOM.
+ if (toMeasure) {
+ this._measureChildren(toMeasure);
+ }
+ }
+
+ /**
+ * Invoked after DOM is updated, and before it gets measured.
+ * @protected
+ */
+ _didRender() {
+ }
+
+ /**
+ * @private
+ */
+ _discardHead() {
+ const o = this._ordered;
+ for (let idx = this._prevFirst; o.length && idx < this._first; idx++) {
+ this._unassignChild(o.shift(), idx);
+ }
+ }
+
+ /**
+ * @private
+ */
+ _discardTail() {
+ const o = this._ordered;
+ for (let idx = this._prevLast; o.length && idx > this._last; idx--) {
+ this._unassignChild(o.pop(), idx);
+ }
+ }
+
+ /**
+ * @private
+ */
+ _addHead() {
+ const start = this._first;
+ const end = Math.min(this._last, this._prevFirst - 1);
+ for (let idx = end; idx >= start; idx--) {
+ const child = this._assignChild(idx);
+ if (this._manageDom) {
+ if (this._maintainDomOrder || !this._childIsAttached(child)) {
+ this._insertBefore(child, this._firstChild);
+ }
+ }
+ if (this.updateElement) {
+ this.updateElement(child, idx);
+ }
+ this._ordered.unshift(child);
+ }
+ }
+
+ /**
+ * @private
+ */
+ _addTail() {
+ const start = Math.max(this._first, this._prevLast + 1);
+ const end = this._last;
+ for (let idx = start; idx <= end; idx++) {
+ const child = this._assignChild(idx);
+ if (this._manageDom) {
+ if (this._maintainDomOrder || !this._childIsAttached(child)) {
+ this._insertBefore(child, null);
+ }
+ }
+ if (this.updateElement) {
+ this.updateElement(child, idx);
+ }
+ this._ordered.push(child);
+ }
+ }
+
+ /**
+ * @param {number} first
+ * @param {number} last
+ * @private
+ */
+ _reset(first, last) {
+ const len = last - first + 1;
+ // Explain why swap prevActive with active - affects _assignChild.
+ const prevActive = this._active;
+ this._active = this._prevActive;
+ this._prevActive = prevActive;
+ let currentMarker = this._manageDom && this._firstChild;
+ this._ordered.length = 0;
+ for (let n = 0; n < len; n++) {
+ const idx = first + n;
+ const child = this._assignChild(idx);
+ this._ordered.push(child);
+ if (this._manageDom) {
+ if (currentMarker && this._maintainDomOrder) {
+ if (currentMarker === this._node(child)) {
+ currentMarker = this._nextSibling(child);
+ } else {
+ this._insertBefore(child, currentMarker);
+ }
+ } else if (!this._childIsAttached(child)) {
+ this._insertBefore(child, null);
+ }
+ }
+ if (this.updateElement) {
+ this.updateElement(child, idx);
+ }
+ }
+ }
+
+ /**
+ * @param {number} idx
+ * @private
+ */
+ _assignChild(idx) {
+ const key = this.elementKey ? this.elementKey(idx) : idx;
+ let child;
+ if (child = this._keyToChild.get(key)) {
+ this._prevActive.delete(child);
+ } else {
+ child = this.createElement(idx);
+ this._keyToChild.set(key, child);
+ this._childToKey.set(child, key);
+ }
+ this._showChild(child);
+ this._active.set(child, idx);
+ return child;
+ }
+
+ /**
+ * @param {*} child
+ * @param {number} idx
+ * @private
+ */
+ _unassignChild(child, idx) {
+ this._hideChild(child);
+ if (this._incremental) {
+ this._active.delete(child);
+ this._prevActive.set(child, idx);
+ } else {
+ const key = this._childToKey.get(child);
+ this._childToKey.delete(child);
+ this._keyToChild.delete(key);
+ this._active.delete(child);
+ if (this.recycleElement) {
+ this.recycleElement(child, idx);
+ } else if (this._node(child).parentNode) {
+ this._removeChild(child);
+ }
+ }
+ }
+
+ // TODO: Is this the right name?
+ /**
+ * @private
+ */
+ get _firstChild() {
+ return this._ordered.length && this._childIsAttached(this._ordered[0]) ?
+ this._node(this._ordered[0]) :
+ null;
+ }
+
+ // Overridable abstractions for child manipulation
+ /**
+ * @protected
+ */
+ _node(child) {
+ return child;
+ }
+ /**
+ * @protected
+ */
+ _nextSibling(child) {
+ return child.nextSibling;
+ }
+ /**
+ * @protected
+ */
+ _insertBefore(child, referenceNode) {
+ this._container.insertBefore(child, referenceNode);
+ }
+ /**
+ * @protected
+ */
+ _childIsAttached(child) {
+ const node = this._node(child);
+ return node && node.parentNode === this._container;
+ }
+ /**
+ * @protected
+ */
+ _hideChild(child) {
+ if (child.style) {
+ child.style.display = 'none';
+ }
+ }
+ /**
+ * @protected
+ */
+ _showChild(child) {
+ if (child.style) {
+ child.style.display = null;
+ }
+ }
+
+ /**
+ *
+ * @param {!Element} child
+ * @return {{width: number, height: number, marginTop: number, marginBottom: number, marginLeft: number, marginRight: number}} childMeasures
+ * @protected
+ */
+ _measureChild(child) {
+ // offsetWidth doesn't take transforms in consideration,
+ // so we use getBoundingClientRect which does.
+ const {width, height} = child.getBoundingClientRect();
+ // console.debug(`_measureChild #${this._container.id} > #${
+ // child.id}: height: ${height}px`);
+ return Object.assign({width, height}, getMargins(child));
+ }
+
+ /**
+ * Remove child.
+ * Override to control child removal.
+ *
+ * @param {*} child
+ * @protected
+ */
+ _removeChild(child) {
+ child.parentNode.removeChild(child);
+ }
+}
+
+function getMargins(el) {
+ const style = window.getComputedStyle(el);
+ // console.log(el.id, style.position);
+ return {
+ marginLeft: getMarginValue(style.marginLeft),
+ marginRight: getMarginValue(style.marginRight),
+ marginTop: getMarginValue(style.marginTop),
+ marginBottom: getMarginValue(style.marginBottom),
+ };
+}
+
+function getMarginValue(value) {
+ value = value ? parseFloat(value) : NaN;
+ return value !== value ? 0 : value;
+}
+
+export const VirtualRepeater = Repeats(class {}); \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/virtual-scroller.js b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/virtual-scroller.js
new file mode 100644
index 00000000000..b0d240498c9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/script/resources/layered_api/virtual-scroller/virtual-scroller.js
@@ -0,0 +1,444 @@
+import {Repeats} from './virtual-repeater.js';
+
+export class RangeChangeEvent extends Event {
+ constructor(type, init) {
+ super(type, init);
+ this._first = Math.floor(init.first || 0);
+ this._last = Math.floor(init.last || 0);
+ }
+ get first() {
+ return this._first;
+ }
+ get last() {
+ return this._last;
+ }
+}
+
+export const RepeatsAndScrolls = Superclass => class extends Repeats
+(Superclass) {
+ constructor(config) {
+ super();
+ this._num = 0;
+ this._first = -1;
+ this._last = -1;
+ this._prevFirst = -1;
+ this._prevLast = -1;
+
+ this._needsUpdateView = false;
+ this._containerElement = null;
+ this._layout = null;
+ this._scrollTarget = null;
+ // Keep track of original inline style of the container,
+ // so it can be restored when container is changed.
+ this._containerInlineStyle = null;
+ // A sentinel element that sizes the container when
+ // it is a scrolling element.
+ this._sizer = null;
+ // Layout provides these values, we set them on _render().
+ this._scrollSize = null;
+ this._scrollErr = null;
+ this._childrenPos = null;
+
+ this._containerSize = null;
+ this._containerRO = new ResizeObserver(
+ (entries) => this._containerSizeChanged(entries[0].contentRect));
+
+ this._skipNextChildrenSizeChanged = false;
+ this._childrenRO =
+ new ResizeObserver((entries) => this._childrenSizeChanged(entries));
+
+ if (config) {
+ Object.assign(this, config);
+ }
+ }
+
+ get container() {
+ return this._container;
+ }
+ set container(container) {
+ super.container = container;
+
+ const oldEl = this._containerElement;
+ // Consider document fragments as shadowRoots.
+ const newEl =
+ (container && container.nodeType === Node.DOCUMENT_FRAGMENT_NODE) ?
+ container.host :
+ container;
+ if (oldEl === newEl) {
+ return;
+ }
+
+ this._containerRO.disconnect();
+ this._containerSize = null;
+
+ if (oldEl) {
+ if (this._containerInlineStyle) {
+ oldEl.setAttribute('style', this._containerInlineStyle);
+ } else {
+ oldEl.removeAttribute('style');
+ }
+ this._containerInlineStyle = null;
+ if (oldEl === this._scrollTarget) {
+ oldEl.removeEventListener('scroll', this, {passive: true});
+ this._sizer && this._sizer.remove();
+ }
+ } else {
+ // First time container was setup, add listeners only now.
+ addEventListener('scroll', this, {passive: true});
+ }
+
+ this._containerElement = newEl;
+
+ if (newEl) {
+ this._containerInlineStyle = newEl.getAttribute('style') || null;
+ if (newEl === this._scrollTarget) {
+ this._sizer = this._sizer || this._createContainerSizer();
+ this._container.prepend(this._sizer);
+ }
+ this._scheduleUpdateView();
+ this._containerRO.observe(newEl);
+ }
+ }
+
+ get layout() {
+ return this._layout;
+ }
+ set layout(layout) {
+ if (layout === this._layout) {
+ return;
+ }
+
+ if (this._layout) {
+ this._measureCallback = null;
+ this._layout.removeEventListener('scrollsizechange', this);
+ this._layout.removeEventListener('scrollerrorchange', this);
+ this._layout.removeEventListener('itempositionchange', this);
+ this._layout.removeEventListener('rangechange', this);
+ // Reset container size so layout can get correct viewport size.
+ if (this._containerElement) {
+ this._sizeContainer();
+ }
+ }
+
+ this._layout = layout;
+
+ if (this._layout) {
+ if (typeof this._layout.updateItemSizes === 'function') {
+ this._measureCallback = this._layout.updateItemSizes.bind(this._layout);
+ this.requestRemeasure();
+ }
+ this._layout.addEventListener('scrollsizechange', this);
+ this._layout.addEventListener('scrollerrorchange', this);
+ this._layout.addEventListener('itempositionchange', this);
+ this._layout.addEventListener('rangechange', this);
+ this._scheduleUpdateView();
+ }
+ }
+
+ /**
+ * The element that generates scroll events and defines the container
+ * viewport. The value `null` (default) corresponds to `window` as scroll
+ * target.
+ * @type {Element|null}
+ */
+ get scrollTarget() {
+ return this._scrollTarget;
+ }
+ /**
+ * @param {Element|null} target
+ */
+ set scrollTarget(target) {
+ // Consider window as null.
+ if (target === window) {
+ target = null;
+ }
+ if (this._scrollTarget === target) {
+ return;
+ }
+ if (this._scrollTarget) {
+ this._scrollTarget.removeEventListener('scroll', this, {passive: true});
+ if (this._sizer && this._scrollTarget === this._containerElement) {
+ this._sizer.remove();
+ }
+ }
+
+ this._scrollTarget = target;
+
+ if (target) {
+ target.addEventListener('scroll', this, {passive: true});
+ if (target === this._containerElement) {
+ this._sizer = this._sizer || this._createContainerSizer();
+ this._container.prepend(this._sizer);
+ }
+ }
+ }
+
+ /**
+ * @protected
+ */
+ _render() {
+ // console.time(`render ${this._containerElement.localName}#${
+ // this._containerElement.id}`);
+
+ this._childrenRO.disconnect();
+
+ // Update layout properties before rendering to have correct
+ // first, num, scroll size, children positions.
+ this._layout.totalItems = this.totalItems;
+ if (this._needsUpdateView) {
+ this._needsUpdateView = false;
+ this._updateView();
+ }
+ this._layout.reflowIfNeeded();
+ // Keep rendering until there is no more scheduled renders.
+ while (true) {
+ if (this._pendingRender) {
+ cancelAnimationFrame(this._pendingRender);
+ this._pendingRender = null;
+ }
+ // Update scroll size and correct scroll error before rendering.
+ this._sizeContainer(this._scrollSize);
+ if (this._scrollErr) {
+ // This triggers a 'scroll' event (async) which triggers another
+ // _updateView().
+ this._correctScrollError(this._scrollErr);
+ this._scrollErr = null;
+ }
+ // Position children (_didRender()), and provide their measures to layout.
+ super._render();
+ this._layout.reflowIfNeeded();
+ // If layout reflow did not provoke another render, we're done.
+ if (!this._pendingRender) {
+ break;
+ }
+ }
+ // We want to skip the first ResizeObserver callback call as we already
+ // measured the children.
+ this._skipNextChildrenSizeChanged = true;
+ this._kids.forEach(child => this._childrenRO.observe(child));
+
+ // console.timeEnd(`render ${this._containerElement.localName}#${
+ // this._containerElement.id}`);
+ }
+
+ /**
+ * Position children before they get measured.
+ * Measuring will force relayout, so by positioning
+ * them first, we reduce computations.
+ * @protected
+ */
+ _didRender() {
+ if (this._childrenPos) {
+ this._positionChildren(this._childrenPos);
+ this._childrenPos = null;
+ }
+ }
+
+ /**
+ * @param {!Event} event
+ * @private
+ */
+ handleEvent(event) {
+ switch (event.type) {
+ case 'scroll':
+ if (!this._scrollTarget || event.target === this._scrollTarget) {
+ this._scheduleUpdateView();
+ }
+ break;
+ case 'scrollsizechange':
+ this._scrollSize = event.detail;
+ this._scheduleRender();
+ break;
+ case 'scrollerrorchange':
+ this._scrollErr = event.detail;
+ this._scheduleRender();
+ break;
+ case 'itempositionchange':
+ this._childrenPos = event.detail;
+ this._scheduleRender();
+ break;
+ case 'rangechange':
+ this._adjustRange(event.detail);
+ break;
+ default:
+ console.warn('event not handled', event);
+ }
+ }
+ /**
+ * @return {!Element}
+ * @private
+ */
+ _createContainerSizer() {
+ const sizer = document.createElement('div');
+ // When the scrollHeight is large, the height
+ // of this element might be ignored.
+ // Setting content and font-size ensures the element
+ // has a size.
+ Object.assign(sizer.style, {
+ position: 'absolute',
+ margin: '-2px 0 0 0',
+ padding: 0,
+ visibility: 'hidden',
+ fontSize: '2px',
+ });
+ sizer.innerHTML = '&nbsp;';
+ return sizer;
+ }
+
+ // Rename _ordered to _kids?
+ /**
+ * @protected
+ */
+ get _kids() {
+ return this._ordered;
+ }
+ /**
+ * @private
+ */
+ _scheduleUpdateView() {
+ this._needsUpdateView = true;
+ this._scheduleRender();
+ }
+ /**
+ * @private
+ */
+ _updateView() {
+ let width, height, top, left;
+ if (this._scrollTarget === this._containerElement) {
+ width = this._containerSize.width;
+ height = this._containerSize.height;
+ left = this._containerElement.scrollLeft;
+ top = this._containerElement.scrollTop;
+ } else {
+ const containerBounds = this._containerElement.getBoundingClientRect();
+ const scrollBounds = this._scrollTarget ?
+ this._scrollTarget.getBoundingClientRect() :
+ {top: 0, left: 0, width: innerWidth, height: innerHeight};
+ const scrollerWidth = scrollBounds.width;
+ const scrollerHeight = scrollBounds.height;
+ const xMin = Math.max(
+ 0, Math.min(scrollerWidth, containerBounds.left - scrollBounds.left));
+ const yMin = Math.max(
+ 0, Math.min(scrollerHeight, containerBounds.top - scrollBounds.top));
+ const xMax = this._layout.direction === 'vertical' ?
+ Math.max(
+ 0,
+ Math.min(
+ scrollerWidth, containerBounds.right - scrollBounds.left)) :
+ scrollerWidth;
+ const yMax = this._layout.direction === 'vertical' ?
+ scrollerHeight :
+ Math.max(
+ 0,
+ Math.min(
+ scrollerHeight, containerBounds.bottom - scrollBounds.top));
+ width = xMax - xMin;
+ height = yMax - yMin;
+ left = Math.max(0, -(containerBounds.x - scrollBounds.left));
+ top = Math.max(0, -(containerBounds.y - scrollBounds.top));
+ }
+ this._layout.viewportSize = {width, height};
+ this._layout.viewportScroll = {top, left};
+ }
+ /**
+ * @private
+ */
+ _sizeContainer(size) {
+ if (this._scrollTarget === this._containerElement) {
+ const left = size && size.width ? size.width - 1 : 0;
+ const top = size && size.height ? size.height - 1 : 0;
+ this._sizer.style.transform = `translate(${left}px, ${top}px)`;
+ } else {
+ const style = this._containerElement.style;
+ style.minWidth = size && size.width ? size.width + 'px' : null;
+ style.minHeight = size && size.height ? size.height + 'px' : null;
+ }
+ }
+ /**
+ * @private
+ */
+ _positionChildren(pos) {
+ const kids = this._kids;
+ Object.keys(pos).forEach(key => {
+ const idx = key - this._first;
+ const child = kids[idx];
+ if (child) {
+ const {top, left} = pos[key];
+ // console.debug(`_positionChild #${this._container.id} >
+ // #${child.id}: top ${top}`);
+ child.style.position = 'absolute';
+ child.style.transform = `translate(${left}px, ${top}px)`;
+ }
+ });
+ }
+ /**
+ * @private
+ */
+ _adjustRange(range) {
+ this.num = range.num;
+ this.first = range.first;
+ this._incremental = !(range.stable);
+ if (range.remeasure) {
+ this.requestRemeasure();
+ } else if (range.stable) {
+ this._notifyStable();
+ }
+ }
+ /**
+ * @protected
+ */
+ _shouldRender() {
+ if (!super._shouldRender() || !this._layout) {
+ return false;
+ }
+ // NOTE: we're about to render, but the ResizeObserver didn't execute yet.
+ // Since we want to keep rAF timing, we compute _containerSize now.
+ // Would be nice to have a way to flush ResizeObservers
+ if (this._containerSize === null) {
+ const {width, height} = this._containerElement.getBoundingClientRect();
+ this._containerSize = {width, height};
+ }
+ return this._containerSize.width > 0 || this._containerSize.height > 0;
+ }
+ /**
+ * @private
+ */
+ _correctScrollError(err) {
+ if (this._scrollTarget) {
+ this._scrollTarget.scrollTop -= err.top;
+ this._scrollTarget.scrollLeft -= err.left;
+ } else {
+ window.scroll(window.scrollX - err.left, window.scrollY - err.top);
+ }
+ }
+ /**
+ * @protected
+ */
+ _notifyStable() {
+ const {first, num} = this;
+ const last = first + num - 1;
+ this._container.dispatchEvent(
+ new RangeChangeEvent('rangechange', {first, last}));
+ }
+ /**
+ * @private
+ */
+ _containerSizeChanged(size) {
+ const {width, height} = size;
+ this._containerSize = {width, height};
+ // console.debug('container changed size', this._containerSize);
+ this._scheduleUpdateView();
+ }
+ /**
+ * @private
+ */
+ _childrenSizeChanged() {
+ if (this._skipNextChildrenSizeChanged) {
+ this._skipNextChildrenSizeChanged = false;
+ } else {
+ this.requestRemeasure();
+ }
+ }
+};
+
+export const VirtualScroller = RepeatsAndScrolls(class {});
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 23d2f28ac55..a413f0f0ae8 100644
--- a/chromium/third_party/blink/renderer/core/script/script_loader.cc
+++ b/chromium/third_party/blink/renderer/core/script/script_loader.cc
@@ -40,12 +40,15 @@
#include "third_party/blink/renderer/core/loader/subresource_integrity_helper.h"
#include "third_party/blink/renderer/core/script/classic_pending_script.h"
#include "third_party/blink/renderer/core/script/classic_script.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/script/module_pending_script.h"
#include "third_party/blink/renderer/core/script/script.h"
#include "third_party/blink/renderer/core/script/script_element_base.h"
#include "third_party/blink/renderer/core/script/script_runner.h"
#include "third_party/blink/renderer/core/svg_names.h"
+#include "third_party/blink/renderer/platform/feature_policy/feature_policy.h"
+#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/loader/fetch/access_control_status.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
@@ -53,6 +56,7 @@
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
+#include "third_party/blink/renderer/platform/wtf/text/movable_string.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
@@ -100,11 +104,6 @@ void ScriptLoader::Trace(blink::Visitor* visitor) {
PendingScriptClient::Trace(visitor);
}
-void ScriptLoader::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(pending_script_);
- visitor->TraceWrappers(prepared_pending_script_);
-}
-
void ScriptLoader::DidNotifySubtreeInsertionsToDocument() {
if (!parser_inserted_)
PrepareScript(); // FIXME: Provide a real starting line number here.
@@ -218,6 +217,24 @@ network::mojom::FetchCredentialsMode ScriptLoader::ModuleScriptCredentialsMode(
return network::mojom::FetchCredentialsMode::kOmit;
}
+// https://github.com/WICG/feature-policy/issues/135
+bool ShouldBlockSyncScriptForFeaturePolicy(const ScriptElementBase* element,
+ ScriptType script_type,
+ bool parser_inserted) {
+ if (element->GetDocument().GetFeaturePolicy()->IsFeatureEnabled(
+ mojom::FeaturePolicyFeature::kSyncScript)) {
+ return false;
+ }
+
+ // Module scripts never block parsing.
+ if (script_type == ScriptType::kModule || !parser_inserted)
+ return false;
+
+ if (!element->HasSourceAttribute())
+ return true;
+ return !element->DeferAttributeValue() && !element->AsyncAttributeValue();
+}
+
// https://html.spec.whatwg.org/multipage/scripting.html#prepare-a-script
bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
LegacyTypeSupport support_legacy_types) {
@@ -244,12 +261,11 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
non_blocking_ = true;
// <spec step="4">Let source text be the element's child text content.</spec>
- //
+ const String source_text = element_->TextFromChildren();
+
// <spec step="5">If the element has no src attribute, and source text is the
// empty string, then return. The script is not executed.</spec>
- //
- // TODO(hiroshige): Update the behavior according to the spec.
- if (!element_->HasSourceAttribute() && !element_->HasChildren())
+ if (!element_->HasSourceAttribute() && source_text.IsEmpty())
return false;
// <spec step="6">If the element is not connected, then return. The script is
@@ -306,6 +322,15 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
if (!IsScriptForEventSupported())
return false;
+ // This FeaturePolicy is still in the process of being added to the spec.
+ if (ShouldBlockSyncScriptForFeaturePolicy(element_.Get(), GetScriptType(),
+ parser_inserted_)) {
+ element_document.AddConsoleMessage(ConsoleMessage::Create(
+ kJSMessageSource, kErrorMessageLevel,
+ "Synchronous script execution is disabled by Feature Policy"));
+ return false;
+ }
+
// 14. is handled below.
// <spec step="16">Let classic script CORS setting be the current state of the
@@ -336,7 +361,14 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
SubresourceIntegrityHelper::DoReport(element_document, report_info);
}
- // <spec step="20">Let parser metadata be "parser-inserted" if the script
+ // <spec step="20">Let referrer policy be the current state of the element's
+ // referrerpolicy content attribute.</spec>
+ // TODO(domfarolino): Implement referrerpolicy attribute on script elements.
+ // As a stopgap, we set |referrer_policy| to document's referrer policy to
+ // keep the backward compatibility (https://crbug.com/841673).
+ ReferrerPolicy referrer_policy = element_document.GetReferrerPolicy();
+
+ // <spec step="21">Let parser metadata be "parser-inserted" if the script
// element has been flagged as "parser-inserted", and "not-parser-inserted"
// otherwise.</spec>
ParserDisposition parser_state =
@@ -360,52 +392,56 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
TextPosition position =
is_in_document_write ? TextPosition() : script_start_position;
- // <spec step="21">Let options be a script fetch options whose cryptographic
+ // <spec step="22">Let options be a script fetch options whose cryptographic
// nonce is cryptographic nonce, integrity metadata is integrity metadata,
// parser metadata is parser metadata, credentials mode is module script
- // credentials mode, and referrer policy is the empty string.</spec>
+ // credentials mode, and referrer policy is referrer_policy.</spec>
ScriptFetchOptions options(nonce, integrity_metadata, integrity_attr,
- parser_state, credentials_mode);
+ parser_state, credentials_mode, referrer_policy);
- // <spec step="22">Let settings object be the element's node document's Window
+ // <spec step="23">Let settings object be the element's node document's Window
// object's environment settings object.</spec>
//
// Note: We use |element_document| as "settings object" in the steps below.
+ auto* settings_object =
+ new FetchClientSettingsObjectSnapshot(element_document);
- // <spec step="23">If the element has a src content attribute, then:</spec>
+ // <spec step="24">If the element has a src content attribute, then:</spec>
if (element_->HasSourceAttribute()) {
- // <spec step="23.1">Let src be the value of the element's src
+ // <spec step="24.1">Let src be the value of the element's src
// attribute.</spec>
String src =
StripLeadingAndTrailingHTMLSpaces(element_->SourceAttributeValue());
- // <spec step="23.2">If src is the empty string, queue a task to fire an
+ // <spec step="24.2">If src is the empty string, queue a task to fire an
// event named error at the element, and return.</spec>
if (src.IsEmpty()) {
- // TODO(hiroshige): Make this asynchronous. Currently we fire the error
- // event synchronously to keep the existing behavior.
- element_->DispatchErrorEvent();
+ element_document.GetTaskRunner(TaskType::kDOMManipulation)
+ ->PostTask(FROM_HERE,
+ WTF::Bind(&ScriptElementBase::DispatchErrorEvent,
+ WrapPersistent(element_.Get())));
return false;
}
- // <spec step="23.3">Set the element's from an external file flag.</spec>
+ // <spec step="24.3">Set the element's from an external file flag.</spec>
is_external_script_ = true;
- // <spec step="23.4">Parse src relative to the element's node
+ // <spec step="24.4">Parse src relative to the element's node
// document.</spec>
KURL url = element_document.CompleteURL(src);
- // <spec step="23.5">If the previous step failed, queue a task to fire an
+ // <spec step="24.5">If the previous step failed, queue a task to fire an
// event named error at the element, and return. Otherwise, let url be the
// resulting URL record.</spec>
if (!url.IsValid()) {
- // TODO(hiroshige): Make this asynchronous. Currently we fire the error
- // event synchronously to keep the existing behavior.
- element_->DispatchErrorEvent();
+ element_document.GetTaskRunner(TaskType::kDOMManipulation)
+ ->PostTask(FROM_HERE,
+ WTF::Bind(&ScriptElementBase::DispatchErrorEvent,
+ WrapPersistent(element_.Get())));
return false;
}
- // <spec step="23.6">Switch on the script's type:</spec>
+ // <spec step="24.6">Switch on the script's type:</spec>
if (GetScriptType() == ScriptType::kClassic) {
// - "classic":
@@ -422,7 +458,7 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
else
encoding = element_document.Encoding();
- // <spec step="23.6.A">"classic"
+ // <spec step="24.6.A">"classic"
//
// Fetch a classic script given url, settings object, options, classic
// script CORS setting, and encoding.</spec>
@@ -433,15 +469,15 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
// Step 15 is skipped because they are not used in module
// scripts.
- // <spec step="23.6.B">"module"
+ // <spec step="24.6.B">"module"
//
// Fetch a module script graph given url, settings object, "script", and
// options.</spec>
Modulator* modulator = Modulator::From(
ToScriptStateForMainWorld(context_document->GetFrame()));
- FetchModuleScriptTree(url, modulator, options);
+ FetchModuleScriptTree(url, settings_object, modulator, options);
}
- // <spec step="23.6">When the chosen algorithm asynchronously completes, set
+ // <spec step="24.6">When the chosen algorithm asynchronously completes, set
// the script's script to the result. At that time, the script is ready.
// ...</spec>
//
@@ -453,30 +489,30 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
// depending on the conditions in Step 25 of "prepare a script".
}
- // <spec step="24">If the element does not have a src content attribute, run
+ // <spec step="25">If the element does not have a src content attribute, run
// these substeps:</spec>
if (!element_->HasSourceAttribute()) {
- // <spec step="23.1">Let src be the value of the element's src
+ // <spec step="25.1">Let src be the value of the element's src
// attribute.</spec>
//
// This step is done later as ScriptElementBase::TextFromChildren():
- // - in ScriptLoader::PrepareScript() (Step 25, 6th Clause),
+ // - in ScriptLoader::PrepareScript() (Step 26, 6th Clause),
// - in HTMLParserScriptRunner::ProcessScriptElementInternal()
- // (Duplicated code of Step 25, 6th Clause),
- // - in XMLDocumentParser::EndElementNs() (Step 25, 5th Clause), or
+ // (Duplicated code of Step 26, 6th Clause),
+ // - in XMLDocumentParser::EndElementNs() (Step 26, 5th Clause), or
// - in PendingScript::GetSource() (Indirectly used via
// HTMLParserScriptRunner::ProcessScriptElementInternal(),
- // Step 25, 5th Clause).
+ // Step 26, 5th Clause).
- // <spec step="24.1">Let base URL be the script element's node document's
+ // <spec step="25.1">Let base URL be the script element's node document's
// document base URL.</spec>
KURL base_url = element_document.BaseURL();
- // <spec step="24.2">Switch on the script's type:</spec>
+ // <spec step="25.2">Switch on the script's type:</spec>
switch (GetScriptType()) {
- // Step 24.2.A. "classic" [spec text]
+ // Step 25.2.A. "classic" [spec text]
case ScriptType::kClassic: {
- // <spec step="24.2.A.1">Let script be the result of creating a classic
+ // <spec step="25.2.A.1">Let script be the result of creating a classic
// script using source text, settings object, base URL, and
// options.</spec>
@@ -493,39 +529,39 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
prepared_pending_script_ = ClassicPendingScript::CreateInline(
element_, position, script_location_type, options);
- // <spec step="24.2.A.2">Set the script's script to script.</spec>
+ // <spec step="25.2.A.2">Set the script's script to script.</spec>
//
- // <spec step="24.2.A.3">The script is ready.</spec>
+ // <spec step="25.2.A.3">The script is ready.</spec>
//
// Implemented by ClassicPendingScript.
break;
}
- // Step 24.2.B. "module" [spec text]
+ // Step 25.2.B. "module" [spec text]
case ScriptType::kModule: {
- // <spec step="24.2.B.1">Let script be the result of creating a module
+ // <spec step="25.2.B.1">Let script be the result of creating a module
// script using source text, settings object, base URL, and
// options.</spec>
const KURL& source_url = element_document.Url();
Modulator* modulator = Modulator::From(
ToScriptStateForMainWorld(context_document->GetFrame()));
ModuleScript* module_script = ModuleScript::Create(
- element_->TextFromChildren(), modulator, source_url, base_url,
- options, kSharableCrossOrigin, position);
+ MovableString(element_->TextFromChildren().Impl()), modulator,
+ source_url, base_url, options, kSharableCrossOrigin, position);
- // <spec step="24.2.B.2">If this returns null, set the script's script
+ // <spec step="25.2.B.2">If this returns null, set the script's script
// to null and return; the script is ready.</spec>
if (!module_script)
return false;
- // <spec step="24.2.B.3">Fetch the descendants of and instantiate
+ // <spec step="25.2.B.3">Fetch the descendants of and instantiate
// script, given the destination "script". When this asynchronously
// completes, set the script's script to the result. At that time, the
// script is ready.</spec>
auto* module_tree_client = ModulePendingScriptTreeClient::Create();
modulator->FetchDescendantsForInlineScript(
- module_script, WebURLRequest::kRequestContextScript,
- module_tree_client);
+ module_script, settings_object,
+ WebURLRequest::kRequestContextScript, module_tree_client);
prepared_pending_script_ = ModulePendingScript::Create(
element_, module_tree_client, is_external_script_);
break;
@@ -535,17 +571,17 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
DCHECK(prepared_pending_script_);
- // <spec step="25">Then, follow the first of the following options that
+ // <spec step="26">Then, follow the first of the following options that
// describes the situation:</spec>
// Three flags are used to instruct the caller of prepareScript() to execute
- // a part of Step 24, when |m_willBeParserExecuted| is true:
+ // a part of Step 25, when |m_willBeParserExecuted| is true:
// - |m_willBeParserExecuted|
// - |m_willExecuteWhenDocumentFinishedParsing|
// - |m_readyToBeParserExecuted|
// TODO(hiroshige): Clean up the dependency.
- // <spec step="25.A">If the script's type is "classic", and the element has a
+ // <spec step="26.A">If the script's type is "classic", and the element has a
// src attribute, and the element has a defer attribute, and the element has
// been flagged as "parser-inserted", and the element does not have an async
// attribute
@@ -567,7 +603,7 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
return true;
}
- // <spec step="25.B">If the script's type is "classic", and the element has a
+ // <spec step="26.B">If the script's type is "classic", and the element has a
// src attribute, and the element has been flagged as "parser-inserted", and
// the element does not have an async attribute ...</spec>
if (GetScriptType() == ScriptType::kClassic &&
@@ -581,7 +617,7 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
return true;
}
- // <spec step="25.C">If the script's type is "classic", and the element has a
+ // <spec step="26.C">If the script's type is "classic", and the element has a
// src attribute, and the element does not have an async attribute, and the
// element does not have the "non-blocking" flag set
//
@@ -593,7 +629,7 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
!non_blocking_) ||
(GetScriptType() == ScriptType::kModule &&
!element_->AsyncAttributeValue() && !non_blocking_)) {
- // <spec step="25.C">... Add the element to the end of the list of scripts
+ // <spec step="26.C">... Add the element to the end of the list of scripts
// that will execute in order as soon as possible associated with the node
// document of the script element at the time the prepare a script algorithm
// started. ...</spec>
@@ -611,14 +647,14 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
return true;
}
- // <spec step="25.D">If the script's type is "classic", and the element has a
+ // <spec step="26.D">If the script's type is "classic", and the element has a
// src attribute
//
// If the script's type is "module" ...</spec>
if ((GetScriptType() == ScriptType::kClassic &&
element_->HasSourceAttribute()) ||
GetScriptType() == ScriptType::kModule) {
- // <spec step="25.D">... The element must be added to the set of scripts
+ // <spec step="26.D">... The element must be added to the set of scripts
// that will execute as soon as possible of the node document of the script
// element at the time the prepare a script algorithm started. When the
// script is ready, execute the script block and then remove the element
@@ -642,7 +678,7 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
DCHECK_EQ(GetScriptType(), ScriptType::kClassic);
DCHECK(!is_external_script_);
- // <spec step="25.E">If the element does not have a src attribute, and the
+ // <spec step="26.E">If the element does not have a src attribute, and the
// element has been flagged as "parser-inserted", and either the parser that
// created the script is an XML parser or it's an HTML parser whose script
// nesting level is not greater than one, and the Document of the HTML parser
@@ -661,14 +697,14 @@ bool ScriptLoader::PrepareScript(const TextPosition& script_start_position,
// - HTMLParserScriptRunner::requestParsingBlockingScript()
// - TODO(hiroshige): Investigate XMLDocumentParser::endElementNs()
will_be_parser_executed_ = true;
- // <spec step="25.E">... Set the element's "ready to be parser-executed"
+ // <spec step="26.E">... Set the element's "ready to be parser-executed"
// flag. ...</spec>
ready_to_be_parser_executed_ = true;
return true;
}
- // <spec step="25.F">Otherwise
+ // <spec step="26.F">Otherwise
//
// Immediately execute the script block, even if other scripts are already
// executing.</spec>
@@ -700,9 +736,11 @@ void ScriptLoader::FetchClassicScript(const KURL& url,
resource_keep_alive_ = pending_script->GetResource();
}
-void ScriptLoader::FetchModuleScriptTree(const KURL& url,
- Modulator* modulator,
- const ScriptFetchOptions& options) {
+void ScriptLoader::FetchModuleScriptTree(
+ const KURL& url,
+ FetchClientSettingsObjectSnapshot* settings_object,
+ Modulator* modulator,
+ const ScriptFetchOptions& options) {
// <spec
// href="https://html.spec.whatwg.org/multipage/scripting.html#prepare-a-script"
// step="23.6.B">"module"
@@ -710,8 +748,9 @@ void ScriptLoader::FetchModuleScriptTree(const KURL& url,
// Fetch a module script graph given url, settings object, "script", and
// options.</spec>
auto* module_tree_client = ModulePendingScriptTreeClient::Create();
- modulator->FetchTree(url, WebURLRequest::kRequestContextScript, options,
- module_tree_client);
+ modulator->FetchTree(url, settings_object,
+ WebURLRequest::kRequestContextScript, options,
+ ModuleScriptCustomFetchType::kNone, module_tree_client);
prepared_pending_script_ = ModulePendingScript::Create(
element_, module_tree_client, is_external_script_);
}
@@ -720,6 +759,11 @@ PendingScript* ScriptLoader::TakePendingScript(
ScriptSchedulingType scheduling_type) {
CHECK(prepared_pending_script_);
+ DEFINE_STATIC_LOCAL(
+ EnumerationHistogram, scheduling_type_histogram,
+ ("Blink.Script.SchedulingType", kLastScriptSchedulingType + 1));
+ scheduling_type_histogram.Count(static_cast<int>(scheduling_type));
+
switch (scheduling_type) {
case ScriptSchedulingType::kAsync:
case ScriptSchedulingType::kInOrder:
diff --git a/chromium/third_party/blink/renderer/core/script/script_loader.h b/chromium/third_party/blink/renderer/core/script/script_loader.h
index 4eecf66e214..4a04c488630 100644
--- a/chromium/third_party/blink/renderer/core/script/script_loader.h
+++ b/chromium/third_party/blink/renderer/core/script/script_loader.h
@@ -29,7 +29,7 @@
#include "third_party/blink/renderer/core/script/script.h"
#include "third_party/blink/renderer/core/script/script_runner.h"
#include "third_party/blink/renderer/core/script/script_scheduling_type.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/loader/fetch/integrity_metadata.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
@@ -40,17 +40,16 @@
namespace blink {
+class FetchClientSettingsObjectSnapshot;
class ScriptElementBase;
class Script;
-
class ScriptResource;
-
class Modulator;
class CORE_EXPORT ScriptLoader final
: public GarbageCollectedFinalized<ScriptLoader>,
public PendingScriptClient,
- public TraceWrapperBase {
+ public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(ScriptLoader);
public:
@@ -62,7 +61,6 @@ class CORE_EXPORT ScriptLoader final
~ScriptLoader() override;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override { return "ScriptLoader"; }
enum LegacyTypeSupport {
@@ -131,6 +129,7 @@ class CORE_EXPORT ScriptLoader final
const WTF::TextEncoding&);
// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-module-script-tree
void FetchModuleScriptTree(const KURL&,
+ FetchClientSettingsObjectSnapshot*,
Modulator*,
const ScriptFetchOptions&);
diff --git a/chromium/third_party/blink/renderer/core/script/script_module_resolver.h b/chromium/third_party/blink/renderer/core/script/script_module_resolver.h
index a9245fdd85f..56c83bfc852 100644
--- a/chromium/third_party/blink/renderer/core/script/script_module_resolver.h
+++ b/chromium/third_party/blink/renderer/core/script/script_module_resolver.h
@@ -5,8 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_MODULE_RESOLVER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_SCRIPT_MODULE_RESOLVER_H_
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/core/script/script_module_resolver_impl_test.cc b/chromium/third_party/blink/renderer/core/script/script_module_resolver_impl_test.cc
index 72990269655..911117b1705 100644
--- a/chromium/third_party/blink/renderer/core/script/script_module_resolver_impl_test.cc
+++ b/chromium/third_party/blink/renderer/core/script/script_module_resolver_impl_test.cc
@@ -7,7 +7,6 @@
#include "testing/gtest/include/gtest/gtest.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/dom/exception_code.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/script/module_script.h"
#include "third_party/blink/renderer/core/testing/dummy_modulator.h"
@@ -42,17 +41,24 @@ class ScriptModuleResolverImplTestModulator final : public DummyModulator {
private:
// Implements Modulator:
- ScriptState* GetScriptState() override { return script_state_.get(); }
+ ScriptState* GetScriptState() override { return script_state_; }
+
+ KURL ResolveModuleSpecifier(const String& module_request,
+ const KURL& base_url,
+ String* failure_reason) final {
+ return KURL(base_url, module_request);
+ }
ModuleScript* GetFetchedModuleScript(const KURL&) override;
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
int get_fetched_module_script_called_ = 0;
KURL fetched_url_;
Member<ModuleScript> module_script_;
};
void ScriptModuleResolverImplTestModulator::Trace(blink::Visitor* visitor) {
+ visitor->Trace(script_state_);
visitor->Trace(module_script_);
DummyModulator::Trace(visitor);
}
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 8d524497be6..1490a3ccdb7 100644
--- a/chromium/third_party/blink/renderer/core/script/script_runner.cc
+++ b/chromium/third_party/blink/renderer/core/script/script_runner.cc
@@ -330,15 +330,4 @@ void ScriptRunner::Trace(blink::Visitor* visitor) {
visitor->Trace(in_order_scripts_to_execute_soon_);
}
-void ScriptRunner::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- for (const auto& loader : pending_in_order_scripts_)
- visitor->TraceWrappers(loader);
- for (const auto& loader : pending_async_scripts_)
- visitor->TraceWrappers(loader);
- for (const auto& loader : async_scripts_to_execute_soon_)
- visitor->TraceWrappers(loader);
- for (const auto& loader : in_order_scripts_to_execute_soon_)
- visitor->TraceWrappers(loader);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/script/script_runner.h b/chromium/third_party/blink/renderer/core/script/script_runner.h
index 0b7c016b128..e64c99b4dde 100644
--- a/chromium/third_party/blink/renderer/core/script/script_runner.h
+++ b/chromium/third_party/blink/renderer/core/script/script_runner.h
@@ -30,7 +30,7 @@
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
@@ -44,7 +44,7 @@ class ScriptLoader;
class CORE_EXPORT ScriptRunner final
: public GarbageCollectedFinalized<ScriptRunner>,
- public TraceWrapperBase {
+ public NameClient {
public:
static ScriptRunner* Create(Document* document) {
return new ScriptRunner(document);
@@ -63,7 +63,6 @@ class CORE_EXPORT ScriptRunner final
static void MovePendingScript(Document&, Document&, ScriptLoader*);
void Trace(blink::Visitor*);
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override { return "ScriptRunner"; }
private:
diff --git a/chromium/third_party/blink/renderer/core/script/script_scheduling_type.h b/chromium/third_party/blink/renderer/core/script/script_scheduling_type.h
index 31a188740a0..869e28575bc 100644
--- a/chromium/third_party/blink/renderer/core/script/script_scheduling_type.h
+++ b/chromium/third_party/blink/renderer/core/script/script_scheduling_type.h
@@ -12,6 +12,9 @@ namespace blink {
// In the spec, this is determined which clause of Step 25 of
// https://html.spec.whatwg.org/multipage/scripting.html#prepare-a-script
// is taken.
+//
+// The enum values are used in histograms and thus do not change existing
+// enum values when modifying.
enum class ScriptSchedulingType {
// Because the sheduling type is determined slightly after PendingScript
// creation, it is set to kNotSet before ScriptLoader::TakePendingScript()
@@ -62,6 +65,9 @@ enum class ScriptSchedulingType {
kImmediate
};
+static const int kLastScriptSchedulingType =
+ static_cast<int>(ScriptSchedulingType::kImmediate);
+
} // namespace blink
#endif
diff --git a/chromium/third_party/blink/renderer/core/script/worker_modulator_impl.cc b/chromium/third_party/blink/renderer/core/script/worker_modulator_impl.cc
index a2c6e7fe739..3cba1547df4 100644
--- a/chromium/third_party/blink/renderer/core/script/worker_modulator_impl.cc
+++ b/chromium/third_party/blink/renderer/core/script/worker_modulator_impl.cc
@@ -6,24 +6,33 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.h"
+#include "third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
-ModulatorImplBase* WorkerModulatorImpl::Create(
- scoped_refptr<ScriptState> script_state) {
- return new WorkerModulatorImpl(std::move(script_state));
+ModulatorImplBase* WorkerModulatorImpl::Create(ScriptState* script_state) {
+ return new WorkerModulatorImpl(script_state);
}
-WorkerModulatorImpl::WorkerModulatorImpl(
- scoped_refptr<ScriptState> script_state)
- : ModulatorImplBase(std::move(script_state)) {}
-
-ModuleScriptFetcher* WorkerModulatorImpl::CreateModuleScriptFetcher() {
- ToWorkerGlobalScope(GetExecutionContext())->EnsureFetcher();
- return new DocumentModuleScriptFetcher(GetExecutionContext()->Fetcher());
+WorkerModulatorImpl::WorkerModulatorImpl(ScriptState* script_state)
+ : ModulatorImplBase(script_state) {}
+
+ModuleScriptFetcher* WorkerModulatorImpl::CreateModuleScriptFetcher(
+ ModuleScriptCustomFetchType custom_fetch_type) {
+ auto* global_scope = ToWorkerGlobalScope(GetExecutionContext());
+ switch (custom_fetch_type) {
+ case ModuleScriptCustomFetchType::kNone:
+ return new DocumentModuleScriptFetcher(global_scope->EnsureFetcher());
+ case ModuleScriptCustomFetchType::kWorkerConstructor:
+ return new WorkerModuleScriptFetcher(global_scope);
+ case ModuleScriptCustomFetchType::kWorkletAddModule:
+ break;
+ }
+ NOTREACHED();
+ return nullptr;
}
bool WorkerModulatorImpl::IsDynamicImportForbidden(String* reason) {
diff --git a/chromium/third_party/blink/renderer/core/script/worker_modulator_impl.h b/chromium/third_party/blink/renderer/core/script/worker_modulator_impl.h
index 37a2e58baab..4a6f361064b 100644
--- a/chromium/third_party/blink/renderer/core/script/worker_modulator_impl.h
+++ b/chromium/third_party/blink/renderer/core/script/worker_modulator_impl.h
@@ -17,13 +17,14 @@ class ScriptState;
// context should be implemented in this class, not in ModulatorImplBase.
class WorkerModulatorImpl final : public ModulatorImplBase {
public:
- static ModulatorImplBase* Create(scoped_refptr<ScriptState>);
+ static ModulatorImplBase* Create(ScriptState*);
// Implements ModulatorImplBase.
- ModuleScriptFetcher* CreateModuleScriptFetcher() override;
+ ModuleScriptFetcher* CreateModuleScriptFetcher(
+ ModuleScriptCustomFetchType) override;
private:
- explicit WorkerModulatorImpl(scoped_refptr<ScriptState>);
+ explicit WorkerModulatorImpl(ScriptState*);
// Implements ModulatorImplBase.
bool IsDynamicImportForbidden(String* reason) override;
diff --git a/chromium/third_party/blink/renderer/core/script/worklet_modulator_impl.cc b/chromium/third_party/blink/renderer/core/script/worklet_modulator_impl.cc
index 772f386ce27..bc678d809b6 100644
--- a/chromium/third_party/blink/renderer/core/script/worklet_modulator_impl.cc
+++ b/chromium/third_party/blink/renderer/core/script/worklet_modulator_impl.cc
@@ -4,28 +4,25 @@
#include "third_party/blink/renderer/core/script/worklet_modulator_impl.h"
-#include "third_party/blink/renderer/core/loader/modulescript/worker_or_worklet_module_script_fetcher.h"
+#include "third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.h"
#include "third_party/blink/renderer/core/workers/worklet_global_scope.h"
namespace blink {
-ModulatorImplBase* WorkletModulatorImpl::Create(
- scoped_refptr<ScriptState> script_state) {
- return new WorkletModulatorImpl(std::move(script_state));
+ModulatorImplBase* WorkletModulatorImpl::Create(ScriptState* script_state) {
+ return new WorkletModulatorImpl(script_state);
}
-WorkletModulatorImpl::WorkletModulatorImpl(
- scoped_refptr<ScriptState> script_state)
- : ModulatorImplBase(std::move(script_state)) {}
+WorkletModulatorImpl::WorkletModulatorImpl(ScriptState* script_state)
+ : ModulatorImplBase(script_state) {}
-const SecurityOrigin* WorkletModulatorImpl::GetSecurityOriginForFetch() {
- return ToWorkletGlobalScope(GetExecutionContext())->DocumentSecurityOrigin();
-}
-
-ModuleScriptFetcher* WorkletModulatorImpl::CreateModuleScriptFetcher() {
- auto* global_scope = ToWorkletGlobalScope(GetExecutionContext());
- return new WorkerOrWorkletModuleScriptFetcher(
- global_scope->ModuleFetchCoordinatorProxy());
+ModuleScriptFetcher* WorkletModulatorImpl::CreateModuleScriptFetcher(
+ ModuleScriptCustomFetchType custom_fetch_type) {
+ DCHECK_EQ(ModuleScriptCustomFetchType::kWorkletAddModule, custom_fetch_type);
+ WorkletGlobalScope* global_scope =
+ ToWorkletGlobalScope(GetExecutionContext());
+ return new WorkletModuleScriptFetcher(global_scope->EnsureFetcher(),
+ global_scope->GetModuleResponsesMap());
}
bool WorkletModulatorImpl::IsDynamicImportForbidden(String* reason) {
diff --git a/chromium/third_party/blink/renderer/core/script/worklet_modulator_impl.h b/chromium/third_party/blink/renderer/core/script/worklet_modulator_impl.h
index 569ba2b350e..de313d80988 100644
--- a/chromium/third_party/blink/renderer/core/script/worklet_modulator_impl.h
+++ b/chromium/third_party/blink/renderer/core/script/worklet_modulator_impl.h
@@ -19,14 +19,14 @@ class ScriptState;
// context should be implemented in this class, not in ModulatorImplBase.
class WorkletModulatorImpl final : public ModulatorImplBase {
public:
- static ModulatorImplBase* Create(scoped_refptr<ScriptState>);
+ static ModulatorImplBase* Create(ScriptState*);
// Implements ModulatorImplBase.
- const SecurityOrigin* GetSecurityOriginForFetch() override;
- ModuleScriptFetcher* CreateModuleScriptFetcher() override;
+ ModuleScriptFetcher* CreateModuleScriptFetcher(
+ ModuleScriptCustomFetchType) override;
private:
- explicit WorkletModulatorImpl(scoped_refptr<ScriptState>);
+ explicit WorkletModulatorImpl(ScriptState*);
// Implements ModulatorImplBase.
bool IsDynamicImportForbidden(String* reason) override;
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_wrapper.h b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_wrapper.h
index 949d409a098..8f448ce0067 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_wrapper.h
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_default_controller_wrapper.h
@@ -19,7 +19,7 @@ namespace blink {
class CORE_EXPORT ReadableStreamDefaultControllerWrapper final
: public GarbageCollectedFinalized<ReadableStreamDefaultControllerWrapper> {
public:
- void Trace(blink::Visitor* visitor) {}
+ void Trace(blink::Visitor* visitor) { visitor->Trace(script_state_); }
explicit ReadableStreamDefaultControllerWrapper(ScriptValue controller)
: script_state_(controller.GetScriptState()),
@@ -36,7 +36,7 @@ class CORE_EXPORT ReadableStreamDefaultControllerWrapper final
bool IsActive() const { return !js_controller_.IsEmpty(); }
void Close() {
- ScriptState* script_state = script_state_.get();
+ ScriptState* script_state = script_state_;
// This will assert that the context is valid; do not call this method when
// the context is invalidated.
ScriptState::Scope scope(script_state);
@@ -54,7 +54,7 @@ class CORE_EXPORT ReadableStreamDefaultControllerWrapper final
}
double DesiredSize() const {
- ScriptState* script_state = script_state_.get();
+ ScriptState* script_state = script_state_;
// This will assert that the context is valid; do not call this method when
// the context is invalidated.
ScriptState::Scope scope(script_state);
@@ -73,7 +73,7 @@ class CORE_EXPORT ReadableStreamDefaultControllerWrapper final
template <typename ChunkType>
void Enqueue(ChunkType chunk) const {
- ScriptState* script_state = script_state_.get();
+ ScriptState* script_state = script_state_;
// This will assert that the context is valid; do not call this method when
// the context is invalidated.
ScriptState::Scope scope(script_state);
@@ -92,7 +92,7 @@ class CORE_EXPORT ReadableStreamDefaultControllerWrapper final
template <typename ErrorType>
void GetError(ErrorType error) {
- ScriptState* script_state = script_state_.get();
+ ScriptState* script_state = script_state_;
// This will assert that the context is valid; do not call this method when
// the context is invalidated.
ScriptState::Scope scope(script_state);
@@ -111,7 +111,7 @@ class CORE_EXPORT ReadableStreamDefaultControllerWrapper final
}
private:
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
ScopedPersistent<v8::Value> js_controller_;
};
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_operations.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_operations.cc
index c1d3dd6ca85..4efc26b28e8 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_operations.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_operations.cc
@@ -4,14 +4,77 @@
#include "third_party/blink/renderer/core/streams/readable_stream_operations.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include <utility>
+
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
#include "third_party/blink/renderer/core/streams/underlying_source_base.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/wtf/assertions.h"
namespace blink {
+namespace {
+
+base::Optional<bool> BooleanOperationWithRethrow(
+ ScriptState* script_state,
+ ScriptValue value,
+ const char* operation,
+ ExceptionState& exception_state) {
+ DCHECK(!value.IsEmpty());
+
+ if (!value.IsObject())
+ return false;
+
+ v8::TryCatch block(script_state->GetIsolate());
+ v8::Local<v8::Value> args[] = {value.V8Value()};
+ v8::Local<v8::Value> local_value;
+ bool result_bool = false;
+
+ if (!V8ScriptRunner::CallExtra(script_state, operation, args)
+ .ToLocal(&local_value) ||
+ !local_value->BooleanValue(script_state->GetContext()).To(&result_bool)) {
+ DCHECK(block.HasCaught());
+ exception_state.RethrowV8Exception(block.Exception());
+ return base::nullopt;
+ }
+
+ DCHECK(!block.HasCaught());
+ return result_bool;
+}
+
+// Performs |operation| on |value|, catching any exceptions. This is for use in
+// DCHECK(). It is unsafe for general use because it ignores errors. Returns
+// |fallback_value|, which must be chosen so that the DCHECK() passed if an
+// exception was thrown, so that the behaviour matches a release build.
+bool BooleanOperationForDCheck(ScriptState* script_state,
+ ScriptValue value,
+ const char* operation,
+ bool fallback_value) {
+ v8::Local<v8::Value> args[] = {value.V8Value()};
+ v8::Local<v8::Value> result_value;
+ bool result_bool = false;
+ v8::TryCatch block(script_state->GetIsolate());
+ if (V8ScriptRunner::CallExtra(script_state, operation, args)
+ .ToLocal(&result_value) &&
+ result_value->BooleanValue(script_state->GetContext()).To(&result_bool)) {
+ DCHECK(!block.HasCaught());
+ return result_bool;
+ }
+ DCHECK(block.HasCaught());
+ return fallback_value;
+}
+
+// Performs IsReadableStreamDefaultReader(value), catching exceptions. Should
+// only be used in DCHECK(). Returns true on exception.
+bool IsDefaultReaderForDCheck(ScriptState* script_state, ScriptValue value) {
+ return BooleanOperationForDCheck(script_state, value,
+ "IsReadableStreamDefaultReader", true);
+}
+
+} // namespace
+
ScriptValue ReadableStreamOperations::CreateReadableStream(
ScriptState* script_state,
UnderlyingSourceBase* underlying_source,
@@ -24,7 +87,7 @@ ScriptValue ReadableStreamOperations::CreateReadableStream(
v8::Local<v8::Value> args[] = {js_underlying_source, js_strategy};
return ScriptValue(
script_state,
- V8ScriptRunner::CallExtraOrCrash(
+ V8ScriptRunner::CallExtra(
script_state, "createReadableStreamWithExternalController", args));
}
@@ -37,14 +100,15 @@ ScriptValue ReadableStreamOperations::CreateCountQueuingStrategy(
v8::Number::New(script_state->GetIsolate(), high_water_mark)};
return ScriptValue(
script_state,
- V8ScriptRunner::CallExtraOrCrash(
- script_state, "createBuiltInCountQueuingStrategy", args));
+ V8ScriptRunner::CallExtra(script_state,
+ "createBuiltInCountQueuingStrategy", args));
}
-ScriptValue ReadableStreamOperations::GetReader(ScriptState* script_state,
- ScriptValue stream,
- ExceptionState& es) {
- DCHECK(IsReadableStream(script_state, stream));
+ScriptValue ReadableStreamOperations::GetReader(
+ ScriptState* script_state,
+ ScriptValue stream,
+ ExceptionState& exception_state) {
+ DCHECK(IsReadableStreamForDCheck(script_state, stream));
v8::TryCatch block(script_state->GetIsolate());
v8::Local<v8::Value> args[] = {stream.V8Value()};
@@ -52,131 +116,147 @@ ScriptValue ReadableStreamOperations::GetReader(ScriptState* script_state,
script_state,
V8ScriptRunner::CallExtra(script_state,
"AcquireReadableStreamDefaultReader", args));
- if (block.HasCaught())
- es.RethrowV8Exception(block.Exception());
+ if (block.HasCaught()) {
+ exception_state.RethrowV8Exception(block.Exception());
+ return ScriptValue();
+ }
+ DCHECK(!result.IsEmpty());
return result;
}
-bool ReadableStreamOperations::IsReadableStream(ScriptState* script_state,
- ScriptValue value) {
- DCHECK(!value.IsEmpty());
-
- if (!value.IsObject())
- return false;
-
- v8::Local<v8::Value> args[] = {value.V8Value()};
- return V8ScriptRunner::CallExtraOrCrash(script_state, "IsReadableStream",
- args)
- ->ToBoolean()
- ->Value();
+base::Optional<bool> ReadableStreamOperations::IsReadableStream(
+ ScriptState* script_state,
+ ScriptValue value,
+ ExceptionState& exception_state) {
+ return BooleanOperationWithRethrow(script_state, value, "IsReadableStream",
+ exception_state);
}
-bool ReadableStreamOperations::IsDisturbed(ScriptState* script_state,
- ScriptValue stream) {
- DCHECK(IsReadableStream(script_state, stream));
-
- v8::Local<v8::Value> args[] = {stream.V8Value()};
- return V8ScriptRunner::CallExtraOrCrash(script_state,
- "IsReadableStreamDisturbed", args)
- ->ToBoolean()
- ->Value();
+bool ReadableStreamOperations::IsReadableStreamForDCheck(
+ ScriptState* script_state,
+ ScriptValue value) {
+ return BooleanOperationForDCheck(script_state, value, "IsReadableStream",
+ true);
}
-bool ReadableStreamOperations::IsLocked(ScriptState* script_state,
- ScriptValue stream) {
- DCHECK(IsReadableStream(script_state, stream));
-
- v8::Local<v8::Value> args[] = {stream.V8Value()};
- return V8ScriptRunner::CallExtraOrCrash(script_state,
- "IsReadableStreamLocked", args)
- ->ToBoolean()
- ->Value();
+base::Optional<bool> ReadableStreamOperations::IsDisturbed(
+ ScriptState* script_state,
+ ScriptValue stream,
+ ExceptionState& exception_state) {
+ DCHECK(IsReadableStreamForDCheck(script_state, stream));
+ return BooleanOperationWithRethrow(
+ script_state, stream, "IsReadableStreamDisturbed", exception_state);
}
-bool ReadableStreamOperations::IsReadable(ScriptState* script_state,
- ScriptValue stream) {
- DCHECK(IsReadableStream(script_state, stream));
-
- v8::Local<v8::Value> args[] = {stream.V8Value()};
- return V8ScriptRunner::CallExtraOrCrash(script_state,
- "IsReadableStreamReadable", args)
- ->ToBoolean()
- ->Value();
+bool ReadableStreamOperations::IsDisturbedForDCheck(ScriptState* script_state,
+ ScriptValue stream) {
+ DCHECK(IsReadableStreamForDCheck(script_state, stream));
+ return BooleanOperationForDCheck(script_state, stream,
+ "IsReadableStreamDisturbed", false);
}
-bool ReadableStreamOperations::IsClosed(ScriptState* script_state,
- ScriptValue stream) {
- DCHECK(IsReadableStream(script_state, stream));
-
- v8::Local<v8::Value> args[] = {stream.V8Value()};
- return V8ScriptRunner::CallExtraOrCrash(script_state,
- "IsReadableStreamClosed", args)
- ->ToBoolean()
- ->Value();
+base::Optional<bool> ReadableStreamOperations::IsLocked(
+ ScriptState* script_state,
+ ScriptValue stream,
+ ExceptionState& exception_state) {
+ DCHECK(IsReadableStreamForDCheck(script_state, stream));
+ return BooleanOperationWithRethrow(script_state, stream,
+ "IsReadableStreamLocked", exception_state);
}
-bool ReadableStreamOperations::IsErrored(ScriptState* script_state,
- ScriptValue stream) {
- DCHECK(IsReadableStream(script_state, stream));
+bool ReadableStreamOperations::IsLockedForDCheck(ScriptState* script_state,
+ ScriptValue stream) {
+ DCHECK(IsReadableStreamForDCheck(script_state, stream));
+ return BooleanOperationForDCheck(script_state, stream,
+ "IsReadableStreamLocked", false);
+}
- v8::Local<v8::Value> args[] = {stream.V8Value()};
- return V8ScriptRunner::CallExtraOrCrash(script_state,
- "IsReadableStreamErrored", args)
- ->ToBoolean()
- ->Value();
+base::Optional<bool> ReadableStreamOperations::IsReadable(
+ ScriptState* script_state,
+ ScriptValue stream,
+ ExceptionState& exception_state) {
+ DCHECK(IsReadableStreamForDCheck(script_state, stream));
+ return BooleanOperationWithRethrow(
+ script_state, stream, "IsReadableStreamReadable", exception_state);
}
-bool ReadableStreamOperations::IsReadableStreamDefaultReader(
+base::Optional<bool> ReadableStreamOperations::IsClosed(
ScriptState* script_state,
- ScriptValue value) {
- DCHECK(!value.IsEmpty());
+ ScriptValue stream,
+ ExceptionState& exception_state) {
+ DCHECK(IsReadableStreamForDCheck(script_state, stream));
+ return BooleanOperationWithRethrow(script_state, stream,
+ "IsReadableStreamClosed", exception_state);
+}
- if (!value.IsObject())
- return false;
+base::Optional<bool> ReadableStreamOperations::IsErrored(
+ ScriptState* script_state,
+ ScriptValue stream,
+ ExceptionState& exception_state) {
+ DCHECK(IsReadableStreamForDCheck(script_state, stream));
+ return BooleanOperationWithRethrow(
+ script_state, stream, "IsReadableStreamErrored", exception_state);
+}
- v8::Local<v8::Value> args[] = {value.V8Value()};
- return V8ScriptRunner::CallExtraOrCrash(script_state,
- "IsReadableStreamDefaultReader", args)
- ->ToBoolean()
- ->Value();
+base::Optional<bool> ReadableStreamOperations::IsReadableStreamDefaultReader(
+ ScriptState* script_state,
+ ScriptValue value,
+ ExceptionState& exception_state) {
+ return BooleanOperationWithRethrow(
+ script_state, value, "IsReadableStreamDefaultReader", exception_state);
}
ScriptPromise ReadableStreamOperations::DefaultReaderRead(
ScriptState* script_state,
ScriptValue reader) {
- DCHECK(IsReadableStreamDefaultReader(script_state, reader));
+ DCHECK(IsDefaultReaderForDCheck(script_state, reader));
+ v8::TryCatch block(script_state->GetIsolate());
v8::Local<v8::Value> args[] = {reader.V8Value()};
- return ScriptPromise::Cast(
- script_state, V8ScriptRunner::CallExtraOrCrash(
- script_state, "ReadableStreamDefaultReaderRead", args));
+ v8::MaybeLocal<v8::Value> maybe_result = V8ScriptRunner::CallExtra(
+ script_state, "ReadableStreamDefaultReaderRead", args);
+ if (maybe_result.IsEmpty()) {
+ DCHECK(block.HasCaught());
+ return ScriptPromise::Reject(script_state, block.Exception());
+ }
+ return ScriptPromise::Cast(script_state, maybe_result.ToLocalChecked());
}
void ReadableStreamOperations::Tee(ScriptState* script_state,
ScriptValue stream,
ScriptValue* new_stream1,
- ScriptValue* new_stream2) {
- DCHECK(IsReadableStream(script_state, stream));
- DCHECK(!IsLocked(script_state, stream));
+ ScriptValue* new_stream2,
+ ExceptionState& exception_state) {
+ DCHECK(IsReadableStreamForDCheck(script_state, stream));
+ DCHECK(!IsLockedForDCheck(script_state, stream));
v8::Local<v8::Value> args[] = {stream.V8Value()};
- ScriptValue result(script_state,
- V8ScriptRunner::CallExtraOrCrash(
- script_state, "ReadableStreamTee", args));
- DCHECK(result.V8Value()->IsArray());
- v8::Local<v8::Array> branches = result.V8Value().As<v8::Array>();
+ v8::TryCatch block(script_state->GetIsolate());
+ v8::Local<v8::Value> result;
+ if (!V8ScriptRunner::CallExtra(script_state, "ReadableStreamTee", args)
+ .ToLocal(&result)) {
+ DCHECK(block.HasCaught());
+ exception_state.RethrowV8Exception(block.Exception());
+ return;
+ }
+
+ DCHECK(result->IsArray());
+ v8::Local<v8::Array> branches = result.As<v8::Array>();
DCHECK_EQ(2u, branches->Length());
- *new_stream1 = ScriptValue(
- script_state,
- branches->Get(script_state->GetContext(), 0).ToLocalChecked());
- *new_stream2 = ScriptValue(
- script_state,
- branches->Get(script_state->GetContext(), 1).ToLocalChecked());
+ ScriptValue result1(script_state,
+ branches->Get(script_state->GetContext(), 0));
+ DCHECK(!result1.IsEmpty());
+ DCHECK(IsReadableStreamForDCheck(script_state, result1));
+
+ ScriptValue result2(script_state,
+ branches->Get(script_state->GetContext(), 1));
+ DCHECK(!result2.IsEmpty());
+ DCHECK(IsReadableStreamForDCheck(script_state, result2));
- DCHECK(IsReadableStream(script_state, *new_stream1));
- DCHECK(IsReadableStream(script_state, *new_stream2));
+ *new_stream1 = std::move(result1);
+ *new_stream2 = std::move(result2);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_operations.h b/chromium/third_party/blink/renderer/core/streams/readable_stream_operations.h
index 278ffa72981..d3665109766 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_operations.h
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_operations.h
@@ -5,10 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_READABLE_STREAM_OPERATIONS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_READABLE_STREAM_OPERATIONS_H_
+#include "base/optional.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/core_export.h"
-#include "v8/include/v8.h"
namespace blink {
@@ -20,65 +20,114 @@ class ScriptState;
// V8 Extras.
// All methods should be called in an appropriate V8 context. All ScriptValue
// arguments must not be empty.
+//
+// Boolean methods return an optional bool, where an empty value indicates that
+// Javascript failed to return a value (ie. an exception occurred). Exceptions
+// are not caught, so that they can be handled by user Javascript. This implicit
+// exception passing is error-prone and bad.
+//
+// In methods which take an ExceptionState& parameter, exception passing is
+// explicit. Callers must check exception_state.HadException() on
+// return. Although these methods return base::nullopt if and only if an
+// exception was thrown, outside of unit tests exception_state should always be
+// used to determine failure.
+//
+// TODO(ricea): Add ExceptionState arguments to the rest of the non-Promise
+// methods to make exception passing explicit. https://crbug.com/853189.
class CORE_EXPORT ReadableStreamOperations {
STATIC_ONLY(ReadableStreamOperations);
public:
// createReadableStreamWithExternalController
// If the caller supplies an invalid strategy (e.g. one that returns
- // negative sizes, or doesn't have appropriate properties), this will crash.
+ // negative sizes, or doesn't have appropriate properties), or an exception
+ // occurs for another reason, this will return an empty value.
static ScriptValue CreateReadableStream(ScriptState*,
UnderlyingSourceBase*,
ScriptValue strategy);
// createBuiltInCountQueuingStrategy
+ // If the constructor throws, this will return an empty value.
static ScriptValue CreateCountQueuingStrategy(ScriptState*,
size_t high_water_mark);
// AcquireReadableStreamDefaultReader
- // This function assumes |isReadableStream(stream)|.
- // Returns an empty value and throws an error via the ExceptionState when
- // errored.
+ // This function assumes |IsReadableStream(stream)|.
static ScriptValue GetReader(ScriptState*,
ScriptValue stream,
ExceptionState&);
- // IsReadableStream
- static bool IsReadableStream(ScriptState*, ScriptValue);
-
- // IsReadableStreamDisturbed
- // This function assumes |isReadableStream(stream)|.
- static bool IsDisturbed(ScriptState*, ScriptValue stream);
-
- // IsReadableStreamLocked
- // This function assumes |isReadableStream(stream)|.
- static bool IsLocked(ScriptState*, ScriptValue stream);
-
- // IsReadableStreamReadable
- // This function assumes |isReadableStream(stream)|.
- static bool IsReadable(ScriptState*, ScriptValue stream);
-
- // IsReadableStreamClosed
- // This function assumes |isReadableStream(stream)|.
- static bool IsClosed(ScriptState*, ScriptValue stream);
-
- // IsReadableStreamErrored
- // This function assumes |isReadableStream(stream)|.
- static bool IsErrored(ScriptState*, ScriptValue stream);
-
- // IsReadableStreamDefaultReader
- static bool IsReadableStreamDefaultReader(ScriptState*, ScriptValue);
+ // IsReadableStream, exception-catching version. Exceptions will be passed to
+ // |exception_state|.
+ static base::Optional<bool> IsReadableStream(ScriptState*,
+ ScriptValue,
+ ExceptionState& exception_state);
+
+ // Performs IsReadableStream.
+ // Catches exceptions, and returns false if there are any. Should only be used
+ // in a DCHECK statement that passes when the return value is true.
+ static bool IsReadableStreamForDCheck(ScriptState*, ScriptValue);
+
+ // IsReadableStreamDisturbed.
+ // This function assumes |IsReadableStream(stream)|.
+ static base::Optional<bool> IsDisturbed(ScriptState*,
+ ScriptValue stream,
+ ExceptionState& exception_state);
+
+ // Performs IsReadableStreamDisturbed.
+ // Catches exceptions, and returns false if there are any. Should only be used
+ // in a DCHECK statement that passes when the return value is false.
+ static bool IsDisturbedForDCheck(ScriptState*, ScriptValue stream);
+
+ // IsReadableStreamLocked.
+ // This function assumes |IsReadableStream(stream)|.
+ static base::Optional<bool> IsLocked(ScriptState*,
+ ScriptValue stream,
+ ExceptionState&);
+
+ // Performs IsReadableStreamLocked.
+ // Catches exceptions, and returns false if there are any. Should only be used
+ // in a DCHECK statement that passes when the return value is false.
+ static bool IsLockedForDCheck(ScriptState*, ScriptValue stream);
+
+ // IsReadableStreamReadable.
+ // This function assumes |IsReadableStream(stream)|.
+ static base::Optional<bool> IsReadable(ScriptState*,
+ ScriptValue stream,
+ ExceptionState& exception_state);
+
+ // IsReadableStreamClosed.
+ // This function assumes |IsReadableStream(stream)|.
+ static base::Optional<bool> IsClosed(ScriptState*,
+ ScriptValue stream,
+ ExceptionState& exception_state);
+
+ // IsReadableStreamErrored.
+ // This function assumes |IsReadableStream(stream)|.
+ static base::Optional<bool> IsErrored(ScriptState*,
+ ScriptValue stream,
+ ExceptionState& exception_state);
+
+ // IsReadableStreamDefaultReader.
+ static base::Optional<bool> IsReadableStreamDefaultReader(
+ ScriptState*,
+ ScriptValue,
+ ExceptionState& exception_state);
// ReadableStreamDefaultReaderRead
- // This function assumes |isReadableStreamDefaultReader(reader)|.
+ // This function assumes |IsReadableStreamDefaultReader(reader)|.
+ // If an exception occurs, returns a rejected promise.
static ScriptPromise DefaultReaderRead(ScriptState*, ScriptValue reader);
// ReadableStreamTee
- // This function assumes |isReadableStream(stream)| and |!isLocked(stream)|
+ // This function assumes |IsReadableStream(stream)| and |!IsLocked(stream)|
+ // Returns without setting new_stream1 or new_stream2 if an error occurs.
+ // Exceptions are caught and rethrown on |exception_state|.
static void Tee(ScriptState*,
ScriptValue stream,
ScriptValue* new_stream1,
- ScriptValue* new_stream2);
+ ScriptValue* new_stream2,
+ ExceptionState&);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/streams/readable_stream_operations_test.cc b/chromium/third_party/blink/renderer/core/streams/readable_stream_operations_test.cc
index df4bd261688..33154781e83 100644
--- a/chromium/third_party/blink/renderer/core/streams/readable_stream_operations_test.cc
+++ b/chromium/third_party/blink/renderer/core/streams/readable_stream_operations_test.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/core/streams/readable_stream_operations.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
@@ -15,6 +14,7 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/streams/readable_stream_default_controller_wrapper.h"
#include "third_party/blink/renderer/core/streams/underlying_source_base.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/bindings/v8_binding_macros.h"
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
@@ -120,37 +120,55 @@ TEST(ReadableStreamOperationsTest, IsReadableStream) {
V8TestingScope scope;
TryCatchScope try_catch_scope(scope.GetIsolate());
EXPECT_FALSE(ReadableStreamOperations::IsReadableStream(
- scope.GetScriptState(),
- ScriptValue(scope.GetScriptState(), v8::Undefined(scope.GetIsolate()))));
+ scope.GetScriptState(),
+ ScriptValue(scope.GetScriptState(),
+ v8::Undefined(scope.GetIsolate())),
+ ASSERT_NO_EXCEPTION)
+ .value_or(true));
EXPECT_FALSE(ReadableStreamOperations::IsReadableStream(
- scope.GetScriptState(), ScriptValue::CreateNull(scope.GetScriptState())));
+ scope.GetScriptState(),
+ ScriptValue::CreateNull(scope.GetScriptState()),
+ ASSERT_NO_EXCEPTION)
+ .value_or(true));
EXPECT_FALSE(ReadableStreamOperations::IsReadableStream(
- scope.GetScriptState(),
- ScriptValue(scope.GetScriptState(),
- v8::Object::New(scope.GetIsolate()))));
+ scope.GetScriptState(),
+ ScriptValue(scope.GetScriptState(),
+ v8::Object::New(scope.GetIsolate())),
+ ASSERT_NO_EXCEPTION)
+ .value_or(true));
ScriptValue stream = EvalWithPrintingError(&scope, "new ReadableStream()");
EXPECT_FALSE(stream.IsEmpty());
- EXPECT_TRUE(ReadableStreamOperations::IsReadableStream(scope.GetScriptState(),
- stream));
+ EXPECT_TRUE(ReadableStreamOperations::IsReadableStream(
+ scope.GetScriptState(), stream, ASSERT_NO_EXCEPTION)
+ .value_or(false));
}
TEST(ReadableStreamOperationsTest, IsReadableStreamDefaultReaderInvalid) {
V8TestingScope scope;
TryCatchScope try_catch_scope(scope.GetIsolate());
EXPECT_FALSE(ReadableStreamOperations::IsReadableStreamDefaultReader(
- scope.GetScriptState(),
- ScriptValue(scope.GetScriptState(), v8::Undefined(scope.GetIsolate()))));
+ scope.GetScriptState(),
+ ScriptValue(scope.GetScriptState(),
+ v8::Undefined(scope.GetIsolate())),
+ ASSERT_NO_EXCEPTION)
+ .value_or(true));
EXPECT_FALSE(ReadableStreamOperations::IsReadableStreamDefaultReader(
- scope.GetScriptState(), ScriptValue::CreateNull(scope.GetScriptState())));
+ scope.GetScriptState(),
+ ScriptValue::CreateNull(scope.GetScriptState()),
+ ASSERT_NO_EXCEPTION)
+ .value_or(true));
EXPECT_FALSE(ReadableStreamOperations::IsReadableStreamDefaultReader(
- scope.GetScriptState(),
- ScriptValue(scope.GetScriptState(),
- v8::Object::New(scope.GetIsolate()))));
+ scope.GetScriptState(),
+ ScriptValue(scope.GetScriptState(),
+ v8::Object::New(scope.GetIsolate())),
+ ASSERT_NO_EXCEPTION)
+ .value_or(true));
ScriptValue stream = EvalWithPrintingError(&scope, "new ReadableStream()");
- EXPECT_FALSE(stream.IsEmpty());
+ ASSERT_FALSE(stream.IsEmpty());
EXPECT_FALSE(ReadableStreamOperations::IsReadableStreamDefaultReader(
- scope.GetScriptState(), stream));
+ scope.GetScriptState(), stream, ASSERT_NO_EXCEPTION)
+ .value_or(true));
}
TEST(ReadableStreamOperationsTest, GetReader) {
@@ -159,32 +177,30 @@ TEST(ReadableStreamOperationsTest, GetReader) {
ScriptValue stream = EvalWithPrintingError(&scope, "new ReadableStream()");
EXPECT_FALSE(stream.IsEmpty());
- EXPECT_FALSE(
- ReadableStreamOperations::IsLocked(scope.GetScriptState(), stream));
+ EXPECT_FALSE(ReadableStreamOperations::IsLocked(scope.GetScriptState(),
+ stream, ASSERT_NO_EXCEPTION)
+ .value_or(true));
ScriptValue reader;
- {
- DummyExceptionStateForTesting es;
- reader =
- ReadableStreamOperations::GetReader(scope.GetScriptState(), stream, es);
- ASSERT_FALSE(es.HadException());
- }
- EXPECT_TRUE(
- ReadableStreamOperations::IsLocked(scope.GetScriptState(), stream));
+ reader = ReadableStreamOperations::GetReader(scope.GetScriptState(), stream,
+ ASSERT_NO_EXCEPTION);
+ EXPECT_TRUE(ReadableStreamOperations::IsLocked(scope.GetScriptState(), stream,
+ ASSERT_NO_EXCEPTION)
+ .value_or(false));
ASSERT_FALSE(reader.IsEmpty());
EXPECT_FALSE(ReadableStreamOperations::IsReadableStream(
- scope.GetScriptState(), reader));
+ scope.GetScriptState(), reader, ASSERT_NO_EXCEPTION)
+ .value_or(true));
EXPECT_TRUE(ReadableStreamOperations::IsReadableStreamDefaultReader(
- scope.GetScriptState(), reader));
+ scope.GetScriptState(), reader, ASSERT_NO_EXCEPTION)
+ .value_or(false));
// Already locked!
- {
- DummyExceptionStateForTesting es;
- reader =
- ReadableStreamOperations::GetReader(scope.GetScriptState(), stream, es);
- ASSERT_TRUE(es.HadException());
- }
- ASSERT_TRUE(reader.IsEmpty());
+ DummyExceptionStateForTesting exception_state;
+ reader = ReadableStreamOperations::GetReader(scope.GetScriptState(), stream,
+ exception_state);
+ EXPECT_TRUE(exception_state.HadException());
+ EXPECT_TRUE(reader.IsEmpty());
}
TEST(ReadableStreamOperationsTest, IsDisturbed) {
@@ -194,13 +210,15 @@ TEST(ReadableStreamOperationsTest, IsDisturbed) {
EvalWithPrintingError(&scope, "stream = new ReadableStream()");
EXPECT_FALSE(stream.IsEmpty());
- EXPECT_FALSE(
- ReadableStreamOperations::IsDisturbed(scope.GetScriptState(), stream));
+ EXPECT_FALSE(ReadableStreamOperations::IsDisturbed(
+ scope.GetScriptState(), stream, ASSERT_NO_EXCEPTION)
+ .value_or(true));
ASSERT_FALSE(EvalWithPrintingError(&scope, "stream.cancel()").IsEmpty());
- EXPECT_TRUE(
- ReadableStreamOperations::IsDisturbed(scope.GetScriptState(), stream));
+ EXPECT_TRUE(ReadableStreamOperations::IsDisturbed(scope.GetScriptState(),
+ stream, ASSERT_NO_EXCEPTION)
+ .value_or(false));
}
TEST(ReadableStreamOperationsTest, Read) {
@@ -213,7 +231,8 @@ TEST(ReadableStreamOperationsTest, Read) {
"new ReadableStream({start}).getReader()");
EXPECT_FALSE(reader.IsEmpty());
ASSERT_TRUE(ReadableStreamOperations::IsReadableStreamDefaultReader(
- scope.GetScriptState(), reader));
+ scope.GetScriptState(), reader, ASSERT_NO_EXCEPTION)
+ .value_or(false));
Iteration* it1 = new Iteration();
Iteration* it2 = new Iteration();
@@ -273,12 +292,8 @@ TEST(ReadableStreamOperationsTest,
EXPECT_EQ(8, underlying_source->DesiredSize());
ScriptValue reader;
- {
- DummyExceptionStateForTesting es;
- reader =
- ReadableStreamOperations::GetReader(scope.GetScriptState(), stream, es);
- ASSERT_FALSE(es.HadException());
- }
+ reader = ReadableStreamOperations::GetReader(scope.GetScriptState(), stream,
+ ASSERT_NO_EXCEPTION);
ASSERT_FALSE(reader.IsEmpty());
Iteration* it1 = new Iteration();
@@ -367,12 +382,15 @@ TEST(ReadableStreamOperationsTest, IsReadable) {
ASSERT_FALSE(closed.IsEmpty());
ASSERT_FALSE(errored.IsEmpty());
- EXPECT_TRUE(
- ReadableStreamOperations::IsReadable(scope.GetScriptState(), readable));
- EXPECT_FALSE(
- ReadableStreamOperations::IsReadable(scope.GetScriptState(), closed));
- EXPECT_FALSE(
- ReadableStreamOperations::IsReadable(scope.GetScriptState(), errored));
+ EXPECT_TRUE(ReadableStreamOperations::IsReadable(
+ scope.GetScriptState(), readable, ASSERT_NO_EXCEPTION)
+ .value_or(false));
+ EXPECT_FALSE(ReadableStreamOperations::IsReadable(scope.GetScriptState(),
+ closed, ASSERT_NO_EXCEPTION)
+ .value_or(true));
+ EXPECT_FALSE(ReadableStreamOperations::IsReadable(
+ scope.GetScriptState(), errored, ASSERT_NO_EXCEPTION)
+ .value_or(true));
}
TEST(ReadableStreamOperationsTest, IsClosed) {
@@ -387,12 +405,15 @@ TEST(ReadableStreamOperationsTest, IsClosed) {
ASSERT_FALSE(closed.IsEmpty());
ASSERT_FALSE(errored.IsEmpty());
- EXPECT_FALSE(
- ReadableStreamOperations::IsClosed(scope.GetScriptState(), readable));
- EXPECT_TRUE(
- ReadableStreamOperations::IsClosed(scope.GetScriptState(), closed));
- EXPECT_FALSE(
- ReadableStreamOperations::IsClosed(scope.GetScriptState(), errored));
+ EXPECT_FALSE(ReadableStreamOperations::IsClosed(scope.GetScriptState(),
+ readable, ASSERT_NO_EXCEPTION)
+ .value_or(true));
+ EXPECT_TRUE(ReadableStreamOperations::IsClosed(scope.GetScriptState(), closed,
+ ASSERT_NO_EXCEPTION)
+ .value_or(false));
+ EXPECT_FALSE(ReadableStreamOperations::IsClosed(scope.GetScriptState(),
+ errored, ASSERT_NO_EXCEPTION)
+ .value_or(true));
}
TEST(ReadableStreamOperationsTest, IsErrored) {
@@ -407,30 +428,40 @@ TEST(ReadableStreamOperationsTest, IsErrored) {
ASSERT_FALSE(closed.IsEmpty());
ASSERT_FALSE(errored.IsEmpty());
- EXPECT_FALSE(
- ReadableStreamOperations::IsErrored(scope.GetScriptState(), readable));
- EXPECT_FALSE(
- ReadableStreamOperations::IsErrored(scope.GetScriptState(), closed));
- EXPECT_TRUE(
- ReadableStreamOperations::IsErrored(scope.GetScriptState(), errored));
+ EXPECT_FALSE(ReadableStreamOperations::IsErrored(
+ scope.GetScriptState(), readable, ASSERT_NO_EXCEPTION)
+ .value_or(true));
+ EXPECT_FALSE(ReadableStreamOperations::IsErrored(scope.GetScriptState(),
+ closed, ASSERT_NO_EXCEPTION)
+ .value_or(true));
+ EXPECT_TRUE(ReadableStreamOperations::IsErrored(scope.GetScriptState(),
+ errored, ASSERT_NO_EXCEPTION)
+ .value_or(false));
}
TEST(ReadableStreamOperationsTest, Tee) {
V8TestingScope scope;
TryCatchScope try_catch_scope(scope.GetIsolate());
+ NonThrowableExceptionState exception_state;
ScriptValue original =
EvalWithPrintingError(&scope,
"var controller;"
"new ReadableStream({start: c => controller = c})");
ASSERT_FALSE(original.IsEmpty());
ScriptValue new1, new2;
- ReadableStreamOperations::Tee(scope.GetScriptState(), original, &new1, &new2);
+ ReadableStreamOperations::Tee(scope.GetScriptState(), original, &new1, &new2,
+ exception_state);
+
+ ASSERT_FALSE(new1.IsEmpty());
+ ASSERT_FALSE(new2.IsEmpty());
+
+ ScriptValue reader1 = ReadableStreamOperations::GetReader(
+ scope.GetScriptState(), new1, exception_state);
+ ScriptValue reader2 = ReadableStreamOperations::GetReader(
+ scope.GetScriptState(), new2, exception_state);
- NonThrowableExceptionState ec;
- ScriptValue reader1 =
- ReadableStreamOperations::GetReader(scope.GetScriptState(), new1, ec);
- ScriptValue reader2 =
- ReadableStreamOperations::GetReader(scope.GetScriptState(), new2, ec);
+ ASSERT_FALSE(reader1.IsEmpty());
+ ASSERT_FALSE(reader2.IsEmpty());
Iteration* it1 = new Iteration();
Iteration* it2 = new Iteration();
diff --git a/chromium/third_party/blink/renderer/core/style/BUILD.gn b/chromium/third_party/blink/renderer/core/style/BUILD.gn
index 7830abd1947..5906f097d40 100644
--- a/chromium/third_party/blink/renderer/core/style/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/style/BUILD.gn
@@ -21,7 +21,6 @@ blink_core_sources("rendering") {
"border_value.h",
"cached_ua_style.cc",
"cached_ua_style.h",
- "clip_path_operation.cc",
"clip_path_operation.h",
"computed_style.cc",
"computed_style.h",
@@ -57,10 +56,15 @@ blink_core_sources("rendering") {
"quad_length_value.h",
"quotes_data.cc",
"quotes_data.h",
+ "reference_clip_path_operation.cc",
+ "reference_clip_path_operation.h",
"shadow_data.cc",
"shadow_data.h",
"shadow_list.cc",
"shadow_list.h",
+ "shape_clip_path_operation.h",
+ "shape_value.cc",
+ "shape_value.h",
"style_content_alignment_data.h",
"style_difference.cc",
"style_difference.h",
diff --git a/chromium/third_party/blink/renderer/core/style/OWNERS b/chromium/third_party/blink/renderer/core/style/OWNERS
index ebb863967ba..7d528afeb3b 100644
--- a/chromium/third_party/blink/renderer/core/style/OWNERS
+++ b/chromium/third_party/blink/renderer/core/style/OWNERS
@@ -1,8 +1,9 @@
+andruud@chromium.org
ericwilligers@chromium.org
shend@chromium.org
# Also core owners
alancutter@chromium.org
-nainar@chromium.org
+futhark@chromium.org
# COMPONENT: Blink>CSS
diff --git a/chromium/third_party/blink/renderer/core/style/clip_path_operation.cc b/chromium/third_party/blink/renderer/core/style/clip_path_operation.cc
deleted file mode 100644
index 0710d667902..00000000000
--- a/chromium/third_party/blink/renderer/core/style/clip_path_operation.cc
+++ /dev/null
@@ -1,30 +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/style/clip_path_operation.h"
-
-namespace blink {
-
-void ReferenceClipPathOperation::AddClient(SVGResourceClient& client) {
- if (resource_)
- resource_->AddClient(client);
-}
-
-void ReferenceClipPathOperation::RemoveClient(SVGResourceClient& client) {
- if (resource_)
- resource_->RemoveClient(client);
-}
-
-SVGResource* ReferenceClipPathOperation::Resource() const {
- return resource_;
-}
-
-bool ReferenceClipPathOperation::operator==(const ClipPathOperation& o) const {
- if (!IsSameType(o))
- return false;
- const ReferenceClipPathOperation& other = ToReferenceClipPathOperation(o);
- return resource_ == other.resource_ && url_ == other.url_;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/clip_path_operation.h b/chromium/third_party/blink/renderer/core/style/clip_path_operation.h
index c23bbb6932b..761c65a0836 100644
--- a/chromium/third_party/blink/renderer/core/style/clip_path_operation.h
+++ b/chromium/third_party/blink/renderer/core/style/clip_path_operation.h
@@ -30,17 +30,11 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_CLIP_PATH_OPERATION_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_CLIP_PATH_OPERATION_H_
-#include <memory>
-#include "third_party/blink/renderer/core/style/basic_shapes.h"
-#include "third_party/blink/renderer/core/svg/svg_resource.h"
-#include "third_party/blink/renderer/platform/graphics/path.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
-class SVGResourceClient;
-
class ClipPathOperation : public RefCounted<ClipPathOperation> {
public:
enum OperationType { REFERENCE, SHAPE };
@@ -59,80 +53,6 @@ class ClipPathOperation : public RefCounted<ClipPathOperation> {
ClipPathOperation() = default;
};
-class ReferenceClipPathOperation final : public ClipPathOperation {
- public:
- static scoped_refptr<ReferenceClipPathOperation> Create(
- const String& url,
- SVGResource* resource) {
- return base::AdoptRef(new ReferenceClipPathOperation(url, resource));
- }
-
- void AddClient(SVGResourceClient&);
- void RemoveClient(SVGResourceClient&);
-
- SVGResource* Resource() const;
- const String& Url() const { return url_; }
-
- private:
- bool operator==(const ClipPathOperation&) const override;
- OperationType GetType() const override { return REFERENCE; }
-
- ReferenceClipPathOperation(const String& url, SVGResource* resource)
- : resource_(resource), url_(url) {}
-
- Persistent<SVGResource> resource_;
- String url_;
-};
-
-DEFINE_TYPE_CASTS(ReferenceClipPathOperation,
- ClipPathOperation,
- op,
- op->GetType() == ClipPathOperation::REFERENCE,
- op.GetType() == ClipPathOperation::REFERENCE);
-
-class ShapeClipPathOperation final : public ClipPathOperation {
- public:
- static scoped_refptr<ShapeClipPathOperation> Create(
- scoped_refptr<BasicShape> shape) {
- return base::AdoptRef(new ShapeClipPathOperation(std::move(shape)));
- }
-
- const BasicShape* GetBasicShape() const { return shape_.get(); }
- bool IsValid() const { return shape_.get(); }
- Path GetPath(const FloatRect& bounding_rect) const {
- DCHECK(shape_);
- Path path;
- shape_->GetPath(path, bounding_rect);
- path.SetWindRule(shape_->GetWindRule());
- return path;
- }
-
- private:
- bool operator==(const ClipPathOperation&) const override;
- OperationType GetType() const override { return SHAPE; }
-
- ShapeClipPathOperation(scoped_refptr<BasicShape> shape)
- : shape_(std::move(shape)) {}
-
- scoped_refptr<BasicShape> shape_;
-};
-
-DEFINE_TYPE_CASTS(ShapeClipPathOperation,
- ClipPathOperation,
- op,
- op->GetType() == ClipPathOperation::SHAPE,
- op.GetType() == ClipPathOperation::SHAPE);
-
-inline bool ShapeClipPathOperation::operator==(
- const ClipPathOperation& o) const {
- if (!IsSameType(o))
- return false;
- BasicShape* other_shape = ToShapeClipPathOperation(o).shape_.get();
- if (!shape_.get() || !other_shape)
- return static_cast<bool>(shape_.get()) == static_cast<bool>(other_shape);
- return *shape_ == *other_shape;
-}
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_CLIP_PATH_OPERATION_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 86ea6f525f6..c6aa9af2492 100644
--- a/chromium/third_party/blink/renderer/core/style/computed_style.cc
+++ b/chromium/third_party/blink/renderer/core/style/computed_style.cc
@@ -60,6 +60,7 @@
#include "third_party/blink/renderer/platform/fonts/font_selector.h"
#include "third_party/blink/renderer/platform/geometry/float_rounded_rect.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
+#include "third_party/blink/renderer/platform/graphics/path.h"
#include "third_party/blink/renderer/platform/length_functions.h"
#include "third_party/blink/renderer/platform/text/capitalize.h"
#include "third_party/blink/renderer/platform/transforms/rotate_transform_operation.h"
@@ -426,9 +427,7 @@ ComputedStyle* ComputedStyle::GetCachedPseudoStyle(PseudoId pid) const {
ComputedStyle* ComputedStyle::AddCachedPseudoStyle(
scoped_refptr<ComputedStyle> pseudo) {
- if (!pseudo)
- return nullptr;
-
+ DCHECK(pseudo);
DCHECK_GT(pseudo->StyleType(), kPseudoIdNone);
ComputedStyle* result = pseudo.get();
@@ -821,6 +820,9 @@ void ComputedStyle::UpdatePropertySpecificDifferences(
(has_clip && Clip() != other.Clip()))
diff.SetCSSClipChanged();
+ if (GetBlendMode() != other.GetBlendMode())
+ diff.SetBlendModeChanged();
+
if (HasCurrentTransformAnimation() != other.HasCurrentTransformAnimation() ||
HasCurrentOpacityAnimation() != other.HasCurrentOpacityAnimation() ||
HasCurrentFilterAnimation() != other.HasCurrentFilterAnimation() ||
@@ -829,7 +831,9 @@ void ComputedStyle::UpdatePropertySpecificDifferences(
HasInlineTransform() != other.HasInlineTransform() ||
BackfaceVisibility() != other.BackfaceVisibility() ||
HasWillChangeCompositingHint() != other.HasWillChangeCompositingHint() ||
- UsedTransformStyle3D() != other.UsedTransformStyle3D()) {
+ UsedTransformStyle3D() != other.UsedTransformStyle3D() ||
+ ContainsPaint() != other.ContainsPaint() ||
+ IsOverflowVisible() != other.IsOverflowVisible()) {
diff.SetCompositingReasonsChanged();
}
}
@@ -916,7 +920,7 @@ void ComputedStyle::UpdateIsStackingContext(bool is_document_element,
return;
}
- if (is_document_element || is_in_top_layer ||
+ if (is_document_element || is_in_top_layer || is_svg_stacking ||
StyleType() == kPseudoIdBackdrop || HasOpacity() ||
HasTransformRelatedProperty() || HasMask() || ClipPath() ||
BoxReflect() || HasFilterInducingProperty() || HasBackdropFilter() ||
@@ -926,9 +930,6 @@ void ComputedStyle::UpdateIsStackingContext(bool is_document_element,
ContainsPaint()) {
SetIsStackingContext(true);
}
-
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() && is_svg_stacking)
- SetIsStackingContext(true);
}
void ComputedStyle::AddCallbackSelector(const String& selector) {
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 8a3621f8b51..2847c7d7e0e 100644
--- a/chromium/third_party/blink/renderer/core/style/computed_style.h
+++ b/chromium/third_party/blink/renderer/core/style/computed_style.h
@@ -72,6 +72,7 @@ class CSSTransitionData;
class CSSVariableData;
class FilterOperations;
class Font;
+class FloatRoundedRect;
class Hyphenation;
class NinePieceImage;
class ShadowList;
@@ -1869,9 +1870,9 @@ class ComputedStyle : public ComputedStyleBase,
// Cursor utility functions.
CursorList* Cursors() const { return CursorDataInternal().Get(); }
- void AddCursor(StyleImage*,
- bool hot_spot_specified,
- const IntPoint& hot_spot = IntPoint());
+ CORE_EXPORT void AddCursor(StyleImage*,
+ bool hot_spot_specified,
+ const IntPoint& hot_spot = IntPoint());
void SetCursorList(CursorList*);
void ClearCursorList();
@@ -2088,7 +2089,7 @@ class ComputedStyle : public ComputedStyleBase,
return GetPosition() != EPosition::kStatic;
}
bool CanContainFixedPositionObjects(bool is_document_element) const {
- return HasTransformRelatedProperty() || ContainsPaint() ||
+ return HasTransformRelatedProperty() ||
// Filter establishes containing block for non-document elements:
// https://drafts.fxtf.org/filter-effects-1/#FilterProperty
(!is_document_element && HasFilter());
@@ -2218,6 +2219,21 @@ class ComputedStyle : public ComputedStyleBase,
InterpolationQuality GetInterpolationQuality() const;
+ bool CanGeneratePseudoElement(PseudoId pseudo) const {
+ // The first letter pseudo element has to look up the tree and see if any
+ // of the ancestors are first letter.
+ if (pseudo != kPseudoIdFirstLetter && !HasPseudoStyle(pseudo))
+ return false;
+ if (Display() == EDisplay::kNone)
+ return false;
+ if (Display() != EDisplay::kContents)
+ return true;
+ // For display: contents elements, we still need to generate ::before and
+ // ::after, but the rest of the pseudo-elements should only be used for
+ // elements with an actual layout object.
+ return pseudo == kPseudoIdBefore || pseudo == kPseudoIdAfter;
+ }
+
private:
void SetVisitedLinkBackgroundColor(const StyleColor& v) {
SetVisitedLinkBackgroundColorInternal(v);
@@ -2543,6 +2559,12 @@ class ComputedStyle : public ComputedStyleBase,
FRIEND_TEST_ALL_PREFIXES(
ComputedStyleTest,
UpdatePropertySpecificDifferencesCompositingReasonsUsedStylePreserve3D);
+ FRIEND_TEST_ALL_PREFIXES(
+ ComputedStyleTest,
+ UpdatePropertySpecificDifferencesCompositingReasonsOverflow);
+ FRIEND_TEST_ALL_PREFIXES(
+ ComputedStyleTest,
+ UpdatePropertySpecificDifferencesCompositingReasonsContainsPaint);
};
inline bool ComputedStyle::SetEffectiveZoom(float f) {
diff --git a/chromium/third_party/blink/renderer/core/style/computed_style_constants.h b/chromium/third_party/blink/renderer/core/style/computed_style_constants.h
index 69060c9bf64..c9ea1e21f41 100644
--- a/chromium/third_party/blink/renderer/core/style/computed_style_constants.h
+++ b/chromium/third_party/blink/renderer/core/style/computed_style_constants.h
@@ -192,6 +192,22 @@ inline Containment& operator|=(Containment& a, Containment b) {
return a = a | b;
}
+static const size_t kTextUnderlinePositionBits = 3;
+enum TextUnderlinePosition {
+ kTextUnderlinePositionAuto = 0x0,
+ kTextUnderlinePositionUnder = 0x1,
+ kTextUnderlinePositionLeft = 0x2,
+ kTextUnderlinePositionRight = 0x4
+};
+inline TextUnderlinePosition operator|(TextUnderlinePosition a,
+ TextUnderlinePosition b) {
+ return TextUnderlinePosition(int(a) | int(b));
+}
+inline TextUnderlinePosition& operator|=(TextUnderlinePosition& a,
+ TextUnderlinePosition b) {
+ return a = a | b;
+}
+
enum class ItemPosition : unsigned {
kLegacy,
kAuto,
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 b4639b1cc8b..db7bb165995 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
@@ -6,10 +6,12 @@
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/css/css_gradient_value.h"
#include "third_party/blink/renderer/core/style/clip_path_operation.h"
+#include "third_party/blink/renderer/core/style/shape_clip_path_operation.h"
#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/platform/testing/runtime_enabled_features_test_helpers.h"
+#include "third_party/blink/renderer/core/style/style_generated_image.h"
namespace blink {
@@ -20,7 +22,7 @@ TEST(ComputedStyleTest, ShapeOutsideBoxEqual) {
scoped_refptr<ComputedStyle> style2 = ComputedStyle::Create();
style1->SetShapeOutside(shape1);
style2->SetShapeOutside(shape2);
- ASSERT_EQ(*style1, *style2);
+ EXPECT_EQ(*style1, *style2);
}
TEST(ComputedStyleTest, ShapeOutsideCircleEqual) {
@@ -34,7 +36,7 @@ TEST(ComputedStyleTest, ShapeOutsideCircleEqual) {
scoped_refptr<ComputedStyle> style2 = ComputedStyle::Create();
style1->SetShapeOutside(shape1);
style2->SetShapeOutside(shape2);
- ASSERT_EQ(*style1, *style2);
+ EXPECT_EQ(*style1, *style2);
}
TEST(ComputedStyleTest, ClipPathEqual) {
@@ -47,7 +49,7 @@ TEST(ComputedStyleTest, ClipPathEqual) {
scoped_refptr<ComputedStyle> style2 = ComputedStyle::Create();
style1->SetClipPath(path1);
style2->SetClipPath(path2);
- ASSERT_EQ(*style1, *style2);
+ EXPECT_EQ(*style1, *style2);
}
TEST(ComputedStyleTest, FocusRingWidth) {
@@ -55,11 +57,11 @@ TEST(ComputedStyleTest, FocusRingWidth) {
style->SetEffectiveZoom(3.5);
#if defined(OS_MACOSX)
style->SetOutlineStyle(EBorderStyle::kSolid);
- ASSERT_EQ(3, style->GetOutlineStrokeWidthForFocusRing());
+ EXPECT_EQ(3, style->GetOutlineStrokeWidthForFocusRing());
#else
- ASSERT_EQ(3.5, style->GetOutlineStrokeWidthForFocusRing());
+ EXPECT_EQ(3.5, style->GetOutlineStrokeWidthForFocusRing());
style->SetEffectiveZoom(0.5);
- ASSERT_EQ(1, style->GetOutlineStrokeWidthForFocusRing());
+ EXPECT_EQ(1, style->GetOutlineStrokeWidthForFocusRing());
#endif
}
@@ -69,9 +71,9 @@ TEST(ComputedStyleTest, FocusRingOutset) {
style->SetOutlineStyleIsAuto(static_cast<bool>(OutlineIsAuto::kOn));
style->SetEffectiveZoom(4.75);
#if defined(OS_MACOSX)
- ASSERT_EQ(4, style->OutlineOutsetExtent());
+ EXPECT_EQ(4, style->OutlineOutsetExtent());
#else
- ASSERT_EQ(3, style->OutlineOutsetExtent());
+ EXPECT_EQ(3, style->OutlineOutsetExtent());
#endif
}
@@ -81,13 +83,6 @@ TEST(ComputedStyleTest, SVGStackingContext) {
EXPECT_TRUE(style->IsStackingContext());
}
-TEST(ComputedStyleTest, SVGStackingContextSPv1) {
- ScopedSlimmingPaintV175ForTest spv175(false);
- scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
- style->UpdateIsStackingContext(false, false, true);
- EXPECT_FALSE(style->IsStackingContext());
-}
-
TEST(ComputedStyleTest, Preserve3dForceStackingContext) {
scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
style->SetTransformStyle3D(ETransformStyle3D::kPreserve3d);
@@ -217,6 +212,29 @@ TEST(ComputedStyleTest,
EXPECT_TRUE(diff.CompositingReasonsChanged());
}
+TEST(ComputedStyleTest,
+ UpdatePropertySpecificDifferencesCompositingReasonsOverflow) {
+ scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
+ scoped_refptr<ComputedStyle> other = ComputedStyle::Clone(*style);
+
+ other->SetOverflowX(EOverflow::kHidden);
+ StyleDifference diff;
+ style->UpdatePropertySpecificDifferences(*other, diff);
+ EXPECT_TRUE(diff.CompositingReasonsChanged());
+}
+
+TEST(ComputedStyleTest,
+ UpdatePropertySpecificDifferencesCompositingReasonsContainsPaint) {
+ scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
+ scoped_refptr<ComputedStyle> other = ComputedStyle::Clone(*style);
+
+ // This induces a flat used transform style.
+ other->SetContain(kContainsPaint);
+ StyleDifference diff;
+ style->UpdatePropertySpecificDifferences(*other, diff);
+ EXPECT_TRUE(diff.CompositingReasonsChanged());
+}
+
TEST(ComputedStyleTest, HasOutlineWithCurrentColor) {
scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
EXPECT_FALSE(style->HasOutline());
@@ -250,4 +268,22 @@ TEST(ComputedStyleTest, BorderWidth) {
EXPECT_EQ(style->BorderBottom().Width(), 5);
}
+TEST(ComputedStyleTest, CursorList) {
+ scoped_refptr<ComputedStyle> style = ComputedStyle::Create();
+ scoped_refptr<ComputedStyle> other = ComputedStyle::Create();
+
+ cssvalue::CSSGradientValue* gradient =
+ cssvalue::CSSLinearGradientValue::Create(
+ nullptr, nullptr, nullptr, nullptr, nullptr, cssvalue::kRepeating);
+
+ StyleImage* image_value = StyleGeneratedImage::Create(*gradient);
+ StyleImage* other_image_value = StyleGeneratedImage::Create(*gradient);
+
+ EXPECT_TRUE(DataEquivalent(image_value, other_image_value));
+
+ style->AddCursor(image_value, false);
+ other->AddCursor(other_image_value, false);
+ EXPECT_EQ(*style, *other);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/counter_directives.h b/chromium/third_party/blink/renderer/core/style/counter_directives.h
index 8e0841268e1..8f62ffa02e2 100644
--- a/chromium/third_party/blink/renderer/core/style/counter_directives.h
+++ b/chromium/third_party/blink/renderer/core/style/counter_directives.h
@@ -29,8 +29,8 @@
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
+#include "base/numerics/checked_math.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -89,7 +89,7 @@ class CounterDirectives {
// According to the spec, if an increment would overflow or underflow the
// counter, we are allowed to ignore the increment.
// https://drafts.csswg.org/css-lists-3/#valdef-counter-reset-custom-ident-integer
- return WTF::CheckAdd(reset_value_, increment_value_)
+ return base::CheckAdd(reset_value_, increment_value_)
.ValueOrDefault(reset_value_);
}
diff --git a/chromium/third_party/blink/renderer/core/style/cursor_data.h b/chromium/third_party/blink/renderer/core/style/cursor_data.h
index 6f6431779a8..bf4392e2501 100644
--- a/chromium/third_party/blink/renderer/core/style/cursor_data.h
+++ b/chromium/third_party/blink/renderer/core/style/cursor_data.h
@@ -25,6 +25,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_CURSOR_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_CURSOR_DATA_H_
+#include "third_party/blink/renderer/core/style/data_equivalency.h"
#include "third_party/blink/renderer/core/style/style_image.h"
#include "third_party/blink/renderer/platform/geometry/int_point.h"
@@ -42,7 +43,7 @@ class CursorData {
hot_spot_(hot_spot) {}
bool operator==(const CursorData& o) const {
- return hot_spot_ == o.hot_spot_ && image_ == o.image_;
+ return hot_spot_ == o.hot_spot_ && DataEquivalent(image_, o.image_);
}
bool operator!=(const CursorData& o) const { return !(*this == o); }
diff --git a/chromium/third_party/blink/renderer/core/style/fill_layer.cc b/chromium/third_party/blink/renderer/core/style/fill_layer.cc
index 7c0a92d6742..16d68469f02 100644
--- a/chromium/third_party/blink/renderer/core/style/fill_layer.cc
+++ b/chromium/third_party/blink/renderer/core/style/fill_layer.cc
@@ -364,16 +364,6 @@ bool FillLayer::ClipOccludesNextLayers() const {
return Clip() == ThisOrNextLayersClipMax();
}
-bool FillLayer::ContainsImage(StyleImage* s) const {
- if (!s)
- return false;
- if (image_ && *s == *image_)
- return true;
- if (next_)
- return next_->ContainsImage(s);
- return false;
-}
-
bool FillLayer::ImagesAreLoaded() const {
const FillLayer* curr;
for (curr = this; curr; curr = curr->Next()) {
diff --git a/chromium/third_party/blink/renderer/core/style/fill_layer.h b/chromium/third_party/blink/renderer/core/style/fill_layer.h
index 1d68e66b88d..d5bed9d2073 100644
--- a/chromium/third_party/blink/renderer/core/style/fill_layer.h
+++ b/chromium/third_party/blink/renderer/core/style/fill_layer.h
@@ -214,7 +214,6 @@ class CORE_EXPORT FillLayer {
bool VisuallyEqual(const FillLayer&) const;
- bool ContainsImage(StyleImage*) const;
bool ImagesAreLoaded() const;
bool HasImage() const {
diff --git a/chromium/third_party/blink/renderer/core/style/filter_operations.h b/chromium/third_party/blink/renderer/core/style/filter_operations.h
index 79b7c8610b6..090103b2a19 100644
--- a/chromium/third_party/blink/renderer/core/style/filter_operations.h
+++ b/chromium/third_party/blink/renderer/core/style/filter_operations.h
@@ -32,6 +32,7 @@
namespace blink {
+class FloatRect;
class SVGResourceClient;
class CORE_EXPORT FilterOperations {
diff --git a/chromium/third_party/blink/renderer/core/style/reference_clip_path_operation.cc b/chromium/third_party/blink/renderer/core/style/reference_clip_path_operation.cc
new file mode 100644
index 00000000000..b713e54f902
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/style/reference_clip_path_operation.cc
@@ -0,0 +1,30 @@
+// 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/style/reference_clip_path_operation.h"
+
+namespace blink {
+
+void ReferenceClipPathOperation::AddClient(SVGResourceClient& client) {
+ if (resource_)
+ resource_->AddClient(client);
+}
+
+void ReferenceClipPathOperation::RemoveClient(SVGResourceClient& client) {
+ if (resource_)
+ resource_->RemoveClient(client);
+}
+
+SVGResource* ReferenceClipPathOperation::Resource() const {
+ return resource_;
+}
+
+bool ReferenceClipPathOperation::operator==(const ClipPathOperation& o) const {
+ if (!IsSameType(o))
+ return false;
+ const ReferenceClipPathOperation& other = ToReferenceClipPathOperation(o);
+ return resource_ == other.resource_ && url_ == other.url_;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/reference_clip_path_operation.h b/chromium/third_party/blink/renderer/core/style/reference_clip_path_operation.h
new file mode 100644
index 00000000000..633fa73c490
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/style/reference_clip_path_operation.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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_STYLE_REFERENCE_CLIP_PATH_OPERATION_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_REFERENCE_CLIP_PATH_OPERATION_H_
+
+#include <memory>
+
+#include "third_party/blink/renderer/core/style/clip_path_operation.h"
+#include "third_party/blink/renderer/core/svg/svg_resource.h"
+
+namespace blink {
+
+class SVGResourceClient;
+
+class ReferenceClipPathOperation final : public ClipPathOperation {
+ public:
+ static scoped_refptr<ReferenceClipPathOperation> Create(
+ const String& url,
+ SVGResource* resource) {
+ return base::AdoptRef(new ReferenceClipPathOperation(url, resource));
+ }
+
+ void AddClient(SVGResourceClient&);
+ void RemoveClient(SVGResourceClient&);
+
+ SVGResource* Resource() const;
+ const String& Url() const { return url_; }
+
+ private:
+ bool operator==(const ClipPathOperation&) const override;
+ OperationType GetType() const override { return REFERENCE; }
+
+ ReferenceClipPathOperation(const String& url, SVGResource* resource)
+ : resource_(resource), url_(url) {}
+
+ Persistent<SVGResource> resource_;
+ String url_;
+};
+
+DEFINE_TYPE_CASTS(ReferenceClipPathOperation,
+ ClipPathOperation,
+ op,
+ op->GetType() == ClipPathOperation::REFERENCE,
+ op.GetType() == ClipPathOperation::REFERENCE);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_REFERENCE_CLIP_PATH_OPERATION_H_
diff --git a/chromium/third_party/blink/renderer/core/style/shadow_data.cc b/chromium/third_party/blink/renderer/core/style/shadow_data.cc
index c3ecdf57efb..acb6c057697 100644
--- a/chromium/third_party/blink/renderer/core/style/shadow_data.cc
+++ b/chromium/third_party/blink/renderer/core/style/shadow_data.cc
@@ -24,6 +24,7 @@
#include "third_party/blink/renderer/platform/animation/animation_utilities.h"
#include "third_party/blink/renderer/platform/graphics/color_blend.h"
+#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
namespace blink {
@@ -48,4 +49,13 @@ ShadowData ShadowData::NeutralValue() {
StyleColor(Color::kTransparent));
}
+FloatRectOutsets ShadowData::RectOutsets() const {
+ // 3 * skBlurRadiusToSigma(blur()) is how Skia implements the radius of a
+ // blur. See also https://crbug.com/624175.
+ float blur_and_spread = ceil(3 * SkBlurRadiusToSigma(Blur())) + Spread();
+ return FloatRectOutsets(
+ blur_and_spread - Y() /* top */, blur_and_spread + X() /* right */,
+ blur_and_spread + Y() /* bottom */, blur_and_spread - X() /* left */);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/shadow_data.h b/chromium/third_party/blink/renderer/core/style/shadow_data.h
index ae63fe1f8d1..e29d0975fde 100644
--- a/chromium/third_party/blink/renderer/core/style/shadow_data.h
+++ b/chromium/third_party/blink/renderer/core/style/shadow_data.h
@@ -29,7 +29,6 @@
#include "third_party/blink/renderer/core/css/style_color.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
#include "third_party/blink/renderer/platform/geometry/float_rect_outsets.h"
-#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
namespace blink {
@@ -72,14 +71,7 @@ class ShadowData {
// Outsets needed to adjust a source rectangle to the one cast by this
// shadow.
- FloatRectOutsets RectOutsets() const {
- // 3 * skBlurRadiusToSigma(blur()) is how Skia implements the radius of a
- // blur. See also https://crbug.com/624175.
- float blur_and_spread = ceil(3 * SkBlurRadiusToSigma(Blur())) + Spread();
- return FloatRectOutsets(
- blur_and_spread - Y() /* top */, blur_and_spread + X() /* right */,
- blur_and_spread + Y() /* bottom */, blur_and_spread - X() /* left */);
- }
+ FloatRectOutsets RectOutsets() const;
private:
FloatPoint location_;
diff --git a/chromium/third_party/blink/renderer/core/style/shape_clip_path_operation.h b/chromium/third_party/blink/renderer/core/style/shape_clip_path_operation.h
new file mode 100644
index 00000000000..bb7b6a76d4f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/style/shape_clip_path_operation.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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_STYLE_SHAPE_CLIP_PATH_OPERATION_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_SHAPE_CLIP_PATH_OPERATION_H_
+
+#include "third_party/blink/renderer/core/style/basic_shapes.h"
+#include "third_party/blink/renderer/core/style/clip_path_operation.h"
+#include "third_party/blink/renderer/platform/graphics/path.h"
+
+namespace blink {
+
+class ShapeClipPathOperation final : public ClipPathOperation {
+ public:
+ static scoped_refptr<ShapeClipPathOperation> Create(
+ scoped_refptr<BasicShape> shape) {
+ return base::AdoptRef(new ShapeClipPathOperation(std::move(shape)));
+ }
+
+ const BasicShape* GetBasicShape() const { return shape_.get(); }
+ bool IsValid() const { return shape_.get(); }
+ Path GetPath(const FloatRect& bounding_rect) const {
+ DCHECK(shape_);
+ Path path;
+ shape_->GetPath(path, bounding_rect);
+ path.SetWindRule(shape_->GetWindRule());
+ return path;
+ }
+
+ private:
+ bool operator==(const ClipPathOperation&) const override;
+ OperationType GetType() const override { return SHAPE; }
+
+ ShapeClipPathOperation(scoped_refptr<BasicShape> shape)
+ : shape_(std::move(shape)) {}
+
+ scoped_refptr<BasicShape> shape_;
+};
+
+DEFINE_TYPE_CASTS(ShapeClipPathOperation,
+ ClipPathOperation,
+ op,
+ op->GetType() == ClipPathOperation::SHAPE,
+ op.GetType() == ClipPathOperation::SHAPE);
+
+inline bool ShapeClipPathOperation::operator==(
+ const ClipPathOperation& o) const {
+ if (!IsSameType(o))
+ return false;
+ BasicShape* other_shape = ToShapeClipPathOperation(o).shape_.get();
+ if (!shape_.get() || !other_shape)
+ return static_cast<bool>(shape_.get()) == static_cast<bool>(other_shape);
+ return *shape_ == *other_shape;
+}
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_SHAPE_CLIP_PATH_OPERATION_H_
diff --git a/chromium/third_party/blink/renderer/core/style/shape_value.cc b/chromium/third_party/blink/renderer/core/style/shape_value.cc
new file mode 100644
index 00000000000..8ead9fd3f94
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/style/shape_value.cc
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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/style/shape_value.h"
+
+#include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
+
+namespace blink {
+
+bool ShapeValue::IsImageValid() const {
+ if (!GetImage())
+ return false;
+ if (GetImage()->IsImageResource() || GetImage()->IsImageResourceSet())
+ return GetImage()->CachedImage() && GetImage()->CachedImage()->HasImage();
+ return GetImage()->IsGeneratedImage();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/shape_value.h b/chromium/third_party/blink/renderer/core/style/shape_value.h
index fbd64108316..c89b50f5cf0 100644
--- a/chromium/third_party/blink/renderer/core/style/shape_value.h
+++ b/chromium/third_party/blink/renderer/core/style/shape_value.h
@@ -31,7 +31,6 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_SHAPE_VALUE_H_
#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
#include "third_party/blink/renderer/core/style/basic_shapes.h"
#include "third_party/blink/renderer/core/style/computed_style_constants.h"
#include "third_party/blink/renderer/core/style/data_equivalency.h"
@@ -65,13 +64,7 @@ class ShapeValue final : public GarbageCollectedFinalized<ShapeValue> {
BasicShape* Shape() const { return shape_.get(); }
StyleImage* GetImage() const { return image_.Get(); }
- bool IsImageValid() const {
- if (!GetImage())
- return false;
- if (GetImage()->IsImageResource() || GetImage()->IsImageResourceSet())
- return GetImage()->CachedImage() && GetImage()->CachedImage()->HasImage();
- return GetImage()->IsGeneratedImage();
- }
+ bool IsImageValid() const;
void SetImage(StyleImage* image) {
DCHECK_EQ(GetType(), kImage);
if (image_ != image)
diff --git a/chromium/third_party/blink/renderer/core/style/style_difference.cc b/chromium/third_party/blink/renderer/core/style/style_difference.cc
index b59d8437249..a4869fa5a9d 100644
--- a/chromium/third_party/blink/renderer/core/style/style_difference.cc
+++ b/chromium/third_party/blink/renderer/core/style/style_difference.cc
@@ -72,6 +72,9 @@ std::ostream& operator<<(std::ostream& out, const StyleDifference& diff) {
case StyleDifference::kTextDecorationOrColorChanged:
out << "TextDecorationOrColorChanged";
break;
+ case StyleDifference::kBlendModeChanged:
+ out << "BlendModeChanged";
+ break;
default:
NOTREACHED();
break;
diff --git a/chromium/third_party/blink/renderer/core/style/style_difference.h b/chromium/third_party/blink/renderer/core/style/style_difference.h
index a327caef938..356d681070d 100644
--- a/chromium/third_party/blink/renderer/core/style/style_difference.h
+++ b/chromium/third_party/blink/renderer/core/style/style_difference.h
@@ -26,6 +26,7 @@ class StyleDifference {
// The object needs to issue paint invalidations if it is affected by text
// decorations or properties dependent on color (e.g., border or outline).
kTextDecorationOrColorChanged = 1 << 6,
+ kBlendModeChanged = 1 << 7,
// If you add a value here, be sure to update kPropertyDifferenceCount.
};
@@ -131,6 +132,13 @@ class StyleDifference {
property_specific_differences_ |= kCSSClipChanged;
}
+ bool BlendModeChanged() const {
+ return property_specific_differences_ & kBlendModeChanged;
+ }
+ void SetBlendModeChanged() {
+ property_specific_differences_ |= kBlendModeChanged;
+ }
+
bool TextDecorationOrColorChanged() const {
return property_specific_differences_ & kTextDecorationOrColorChanged;
}
@@ -148,7 +156,7 @@ class StyleDifference {
void SetCompositingReasonsChanged() { composited_reasons_changed_ = true; }
private:
- static constexpr int kPropertyDifferenceCount = 7;
+ static constexpr int kPropertyDifferenceCount = 8;
friend CORE_EXPORT std::ostream& operator<<(std::ostream&,
const StyleDifference&);
diff --git a/chromium/third_party/blink/renderer/core/style/style_difference_test.cc b/chromium/third_party/blink/renderer/core/style/style_difference_test.cc
index 669a39becfc..349b8632e03 100644
--- a/chromium/third_party/blink/renderer/core/style/style_difference_test.cc
+++ b/chromium/third_party/blink/renderer/core/style/style_difference_test.cc
@@ -49,6 +49,7 @@ TEST(StyleDifferenceTest, StreamOutputSetAllProperties) {
diff.SetBackdropFilterChanged();
diff.SetCSSClipChanged();
diff.SetTextDecorationOrColorChanged();
+ diff.SetBlendModeChanged();
string_stream << diff;
EXPECT_EQ(
"StyleDifference{layoutType=NoLayout, "
@@ -56,7 +57,8 @@ TEST(StyleDifferenceTest, StreamOutputSetAllProperties) {
"visualRectUpdate=0, "
"propertySpecificDifferences=TransformChanged|OpacityChanged|"
"ZIndexChanged|FilterChanged|BackdropFilterChanged|CSSClipChanged|"
- "TextDecorationOrColorChanged, scrollAnchorDisablingPropertyChanged=0}",
+ "TextDecorationOrColorChanged|BlendModeChanged, "
+ "scrollAnchorDisablingPropertyChanged=0}",
string_stream.str());
}
diff --git a/chromium/third_party/blink/renderer/core/style/style_generated_image.cc b/chromium/third_party/blink/renderer/core/style/style_generated_image.cc
index 30d23a32334..adaad592c10 100644
--- a/chromium/third_party/blink/renderer/core/style/style_generated_image.cc
+++ b/chromium/third_party/blink/renderer/core/style/style_generated_image.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/core/css/css_image_generator_value.h"
#include "third_party/blink/renderer/platform/geometry/float_size.h"
#include "third_party/blink/renderer/platform/geometry/layout_size.h"
+#include "third_party/blink/renderer/platform/graphics/image.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/style/style_image.h b/chromium/third_party/blink/renderer/core/style/style_image.h
index b2905294d96..6aa247dc28c 100644
--- a/chromium/third_party/blink/renderer/core/style/style_image.h
+++ b/chromium/third_party/blink/renderer/core/style/style_image.h
@@ -25,12 +25,14 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_STYLE_STYLE_IMAGE_H_
#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/graphics/image.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
namespace blink {
class CSSValue;
+class FloatSize;
+class Image;
class ImageResourceContent;
class LayoutSize;
class SVGImage;
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 d1401dea903..8678a01c3f0 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
@@ -74,19 +74,15 @@ void StyleInheritedVariables::RemoveVariable(const AtomicString& name) {
iterator->value = nullptr;
}
-std::unique_ptr<HashMap<AtomicString, scoped_refptr<CSSVariableData>>>
-StyleInheritedVariables::GetVariables() const {
- std::unique_ptr<HashMap<AtomicString, scoped_refptr<CSSVariableData>>> result;
+HashSet<AtomicString> StyleInheritedVariables::GetCustomPropertyNames() const {
+ HashSet<AtomicString> names;
if (root_) {
- result.reset(new HashMap<AtomicString, scoped_refptr<CSSVariableData>>(
- root_->data_));
- for (auto it = data_.begin(); it != data_.end(); ++it)
- result->Set(it->key, it->value);
- } else {
- result.reset(
- new HashMap<AtomicString, scoped_refptr<CSSVariableData>>(data_));
+ for (const auto& pair : root_->data_)
+ names.insert(pair.key);
}
- return result;
+ 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 b52e0b63f31..faadb12d7c0 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
@@ -39,11 +39,10 @@ class StyleInheritedVariables : public RefCounted<StyleInheritedVariables> {
void SetRegisteredVariable(const AtomicString&, const CSSValue*);
const CSSValue* RegisteredVariable(const AtomicString&) const;
- // This map will contain null pointers if variables are invalid due to
- // cycles or referencing invalid variables without using a fallback.
- // Note that this method is slow as a new map is constructed.
- std::unique_ptr<HashMap<AtomicString, scoped_refptr<CSSVariableData>>>
- GetVariables() const;
+ // 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;
private:
StyleInheritedVariables() : root_(nullptr) {}
@@ -52,7 +51,7 @@ class StyleInheritedVariables : public RefCounted<StyleInheritedVariables> {
friend class CSSVariableResolver;
HashMap<AtomicString, scoped_refptr<CSSVariableData>> data_;
- HashMap<AtomicString, Persistent<CSSValue>> registered_data_;
+ PersistentHeapHashMap<AtomicString, Member<CSSValue>> registered_data_;
scoped_refptr<StyleInheritedVariables> root_;
};
diff --git a/chromium/third_party/blink/renderer/core/style/style_non_inherited_variables.cc b/chromium/third_party/blink/renderer/core/style/style_non_inherited_variables.cc
index 92aa7ee5a2f..7496efd1488 100644
--- a/chromium/third_party/blink/renderer/core/style/style_non_inherited_variables.cc
+++ b/chromium/third_party/blink/renderer/core/style/style_non_inherited_variables.cc
@@ -44,4 +44,12 @@ StyleNonInheritedVariables::StyleNonInheritedVariables(
registered_data_ = other.registered_data_;
}
+HashSet<AtomicString> StyleNonInheritedVariables::GetCustomPropertyNames()
+ const {
+ HashSet<AtomicString> names;
+ for (const auto& pair : data_)
+ names.insert(pair.key);
+ return names;
+}
+
} // namespace blink
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 f23a3b95349..926fe199530 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
@@ -44,6 +44,8 @@ class StyleNonInheritedVariables {
return registered_data_.at(name);
}
+ HashSet<AtomicString> GetCustomPropertyNames() const;
+
private:
StyleNonInheritedVariables() = default;
StyleNonInheritedVariables(StyleNonInheritedVariables&);
@@ -51,7 +53,7 @@ class StyleNonInheritedVariables {
friend class CSSVariableResolver;
HashMap<AtomicString, scoped_refptr<CSSVariableData>> data_;
- HashMap<AtomicString, Persistent<CSSValue>> registered_data_;
+ PersistentHeapHashMap<AtomicString, Member<CSSValue>> registered_data_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/svg_computed_style.cc b/chromium/third_party/blink/renderer/core/style/svg_computed_style.cc
index 92da18a4d98..9cc17a6c432 100644
--- a/chromium/third_party/blink/renderer/core/style/svg_computed_style.cc
+++ b/chromium/third_party/blink/renderer/core/style/svg_computed_style.cc
@@ -28,6 +28,7 @@
#include "third_party/blink/renderer/core/style/svg_computed_style.h"
#include "third_party/blink/renderer/core/style/style_difference.h"
+#include "third_party/blink/renderer/core/style/style_svg_resource.h"
namespace blink {
@@ -273,4 +274,28 @@ EPaintOrderType SVGComputedStyle::PaintOrderType(unsigned index) const {
return (EPaintOrderType)pt;
}
+void SVGComputedStyle::SetMaskerResource(
+ scoped_refptr<StyleSVGResource> resource) {
+ if (!(resources->masker == resource))
+ resources.Access()->masker = std::move(resource);
+}
+
+void SVGComputedStyle::SetMarkerStartResource(
+ scoped_refptr<StyleSVGResource> resource) {
+ if (!(inherited_resources->marker_start == resource))
+ inherited_resources.Access()->marker_start = std::move(resource);
+}
+
+void SVGComputedStyle::SetMarkerMidResource(
+ scoped_refptr<StyleSVGResource> resource) {
+ if (!(inherited_resources->marker_mid == resource))
+ inherited_resources.Access()->marker_mid = std::move(resource);
+}
+
+void SVGComputedStyle::SetMarkerEndResource(
+ scoped_refptr<StyleSVGResource> resource) {
+ if (!(inherited_resources->marker_end == resource))
+ inherited_resources.Access()->marker_end = std::move(resource);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/style/svg_computed_style.h b/chromium/third_party/blink/renderer/core/style/svg_computed_style.h
index 2be43fbdfab..729933aaea5 100644
--- a/chromium/third_party/blink/renderer/core/style/svg_computed_style.h
+++ b/chromium/third_party/blink/renderer/core/style/svg_computed_style.h
@@ -257,26 +257,14 @@ class SVGComputedStyle : public RefCounted<SVGComputedStyle> {
}
// Setters for non-inherited resources
- void SetMaskerResource(scoped_refptr<StyleSVGResource> resource) {
- if (!(resources->masker == resource))
- resources.Access()->masker = std::move(resource);
- }
+ void SetMaskerResource(scoped_refptr<StyleSVGResource> resource);
// Setters for inherited resources
- void SetMarkerStartResource(scoped_refptr<StyleSVGResource> resource) {
- if (!(inherited_resources->marker_start == resource))
- inherited_resources.Access()->marker_start = std::move(resource);
- }
+ void SetMarkerStartResource(scoped_refptr<StyleSVGResource> resource);
- void SetMarkerMidResource(scoped_refptr<StyleSVGResource> resource) {
- if (!(inherited_resources->marker_mid == resource))
- inherited_resources.Access()->marker_mid = std::move(resource);
- }
+ void SetMarkerMidResource(scoped_refptr<StyleSVGResource> resource);
- void SetMarkerEndResource(scoped_refptr<StyleSVGResource> resource) {
- if (!(inherited_resources->marker_end == resource))
- inherited_resources.Access()->marker_end = std::move(resource);
- }
+ void SetMarkerEndResource(scoped_refptr<StyleSVGResource> resource);
// Read accessors for all the properties
EAlignmentBaseline AlignmentBaseline() const {
diff --git a/chromium/third_party/blink/renderer/core/style/svg_computed_style_defs.cc b/chromium/third_party/blink/renderer/core/style/svg_computed_style_defs.cc
index 91e1f4e21ed..0c3083921c1 100644
--- a/chromium/third_party/blink/renderer/core/style/svg_computed_style_defs.cc
+++ b/chromium/third_party/blink/renderer/core/style/svg_computed_style_defs.cc
@@ -28,13 +28,26 @@
#include "third_party/blink/renderer/core/style/svg_computed_style_defs.h"
#include "third_party/blink/renderer/core/style/data_equivalency.h"
+#include "third_party/blink/renderer/core/style/style_svg_resource.h"
#include "third_party/blink/renderer/core/style/svg_computed_style.h"
namespace blink {
+SVGPaint::SVGPaint() : type(SVG_PAINTTYPE_NONE) {}
+SVGPaint::SVGPaint(Color color) : color(color), type(SVG_PAINTTYPE_RGBCOLOR) {}
+SVGPaint::SVGPaint(const SVGPaint& paint) = default;
+
+SVGPaint::~SVGPaint() = default;
+
+SVGPaint& SVGPaint::operator=(const SVGPaint& paint) = default;
+
bool SVGPaint::operator==(const SVGPaint& other) const {
return type == other.type && color == other.color &&
- resource == other.resource;
+ DataEquivalent(resource, other.resource);
+}
+
+const String& SVGPaint::GetUrl() const {
+ return Resource()->Url();
}
StyleFillData::StyleFillData()
@@ -116,8 +129,10 @@ StyleResourceData::StyleResourceData()
StyleResourceData::StyleResourceData(const StyleResourceData& other)
: RefCounted<StyleResourceData>(), masker(other.masker) {}
+StyleResourceData::~StyleResourceData() = default;
+
bool StyleResourceData::operator==(const StyleResourceData& other) const {
- return masker == other.masker;
+ return DataEquivalent(masker, other.masker);
}
StyleInheritedResourceData::StyleInheritedResourceData()
@@ -132,10 +147,13 @@ StyleInheritedResourceData::StyleInheritedResourceData(
marker_mid(other.marker_mid),
marker_end(other.marker_end) {}
+StyleInheritedResourceData::~StyleInheritedResourceData() = default;
+
bool StyleInheritedResourceData::operator==(
const StyleInheritedResourceData& other) const {
- return marker_start == other.marker_start && marker_mid == other.marker_mid &&
- marker_end == other.marker_end;
+ return DataEquivalent(marker_start, other.marker_start) &&
+ DataEquivalent(marker_mid, other.marker_mid) &&
+ DataEquivalent(marker_end, other.marker_end);
}
StyleGeometryData::StyleGeometryData()
diff --git a/chromium/third_party/blink/renderer/core/style/svg_computed_style_defs.h b/chromium/third_party/blink/renderer/core/style/svg_computed_style_defs.h
index 40b845c919c..95d00bb6547 100644
--- a/chromium/third_party/blink/renderer/core/style/svg_computed_style_defs.h
+++ b/chromium/third_party/blink/renderer/core/style/svg_computed_style_defs.h
@@ -31,7 +31,6 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/style/style_path.h"
-#include "third_party/blink/renderer/core/style/style_svg_resource.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/length.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
@@ -41,6 +40,8 @@
namespace blink {
+class StyleSVGResource;
+
typedef RefVector<Length> SVGDashArray;
enum SVGPaintType {
@@ -121,8 +122,11 @@ enum EPaintOrder {
};
struct SVGPaint {
- SVGPaint() : type(SVG_PAINTTYPE_NONE) {}
- SVGPaint(Color color) : color(color), type(SVG_PAINTTYPE_RGBCOLOR) {}
+ CORE_EXPORT SVGPaint();
+ SVGPaint(Color color);
+ SVGPaint(const SVGPaint& paint);
+ CORE_EXPORT ~SVGPaint();
+ CORE_EXPORT SVGPaint& operator=(const SVGPaint& paint);
CORE_EXPORT bool operator==(const SVGPaint&) const;
bool operator!=(const SVGPaint& other) const { return !(*this == other); }
@@ -149,7 +153,7 @@ struct SVGPaint {
StyleSVGResource* Resource() const { return resource.get(); }
const Color& GetColor() const { return color; }
- const String& GetUrl() const { return Resource()->Url(); }
+ const String& GetUrl() const;
scoped_refptr<StyleSVGResource> resource;
Color color;
@@ -285,6 +289,7 @@ class StyleResourceData : public RefCounted<StyleResourceData> {
static scoped_refptr<StyleResourceData> Create() {
return base::AdoptRef(new StyleResourceData);
}
+ ~StyleResourceData();
scoped_refptr<StyleResourceData> Copy() const {
return base::AdoptRef(new StyleResourceData(*this));
}
@@ -308,6 +313,7 @@ class StyleInheritedResourceData
static scoped_refptr<StyleInheritedResourceData> Create() {
return base::AdoptRef(new StyleInheritedResourceData);
}
+ ~StyleInheritedResourceData();
scoped_refptr<StyleInheritedResourceData> Copy() const {
return base::AdoptRef(new StyleInheritedResourceData(*this));
}
diff --git a/chromium/third_party/blink/renderer/core/svg/animation/smil_time_container.cc b/chromium/third_party/blink/renderer/core/svg/animation/smil_time_container.cc
index 06e30f22c53..f53feeb9419 100644
--- a/chromium/third_party/blink/renderer/core/svg/animation/smil_time_container.cc
+++ b/chromium/third_party/blink/renderer/core/svg/animation/smil_time_container.cc
@@ -39,7 +39,8 @@
namespace blink {
-static const double kAnimationPolicyOnceDuration = 3.000;
+static constexpr TimeDelta kAnimationPolicyOnceDuration =
+ TimeDelta::FromSeconds(3);
SMILTimeContainer::SMILTimeContainer(SVGSVGElement& owner)
: presentation_time_(0),
@@ -119,7 +120,7 @@ bool SMILTimeContainer::HasAnimations() const {
bool SMILTimeContainer::HasPendingSynchronization() const {
return frame_scheduling_state_ == kSynchronizeAnimations &&
- wakeup_timer_.IsActive() && !wakeup_timer_.NextFireInterval();
+ wakeup_timer_.IsActive() && wakeup_timer_.NextFireInterval().is_zero();
}
void SMILTimeContainer::NotifyIntervalsChanged() {
@@ -266,7 +267,7 @@ void SMILTimeContainer::ScheduleWakeUp(
FrameSchedulingState frame_scheduling_state) {
DCHECK(frame_scheduling_state == kSynchronizeAnimations ||
frame_scheduling_state == kFutureAnimationFrame);
- wakeup_timer_.StartOneShot(delay_time, FROM_HERE);
+ wakeup_timer_.StartOneShot(TimeDelta::FromSecondsD(delay_time), FROM_HERE);
frame_scheduling_state_ = frame_scheduling_state;
}
diff --git a/chromium/third_party/blink/renderer/core/svg/graphics/filters/svg_fe_image.cc b/chromium/third_party/blink/renderer/core/svg/graphics/filters/svg_fe_image.cc
index 9acbfde2084..fd1f73105a9 100644
--- a/chromium/third_party/blink/renderer/core/svg/graphics/filters/svg_fe_image.cc
+++ b/chromium/third_party/blink/renderer/core/svg/graphics/filters/svg_fe_image.cc
@@ -25,7 +25,6 @@
#include "third_party/blink/renderer/core/layout/layout_object.h"
#include "third_party/blink/renderer/core/paint/svg_paint_context.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/core/svg/svg_length_context.h"
#include "third_party/blink/renderer/core/svg/svg_uri_reference.h"
@@ -183,7 +182,7 @@ sk_sp<PaintFilter> FEImage::CreateImageFilterForLayoutObject(
SVGPaintContext::PaintResourceSubtree(builder.Context(), &layout_object);
PaintRecorder paint_recorder;
- PaintCanvas* canvas = paint_recorder.beginRecording(dst_rect);
+ cc::PaintCanvas* canvas = paint_recorder.beginRecording(dst_rect);
canvas->concat(AffineTransformToSkMatrix(transform));
builder.EndRecording(*canvas);
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 60ccc695588..cfbb9f3b0ab 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
@@ -31,18 +31,19 @@
#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/dom/document_parser.h"
+#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/dom/node_traversal.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/settings.h"
+#include "third_party/blink/renderer/core/frame/visual_viewport.h"
+#include "third_party/blink/renderer/core/layout/intrinsic_sizing_info.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
#include "third_party/blink/renderer/core/loader/frame_load_request.h"
-#include "third_party/blink/renderer/core/paint/float_clip_recorder.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/core/svg/animation/smil_time_container.h"
#include "third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h"
@@ -51,14 +52,13 @@
#include "third_party/blink/renderer/core/svg/svg_image_element.h"
#include "third_party/blink/renderer/core/svg/svg_svg_element.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
-#include "third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.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/image_observer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -303,7 +303,7 @@ void SVGImage::ForContainer(const FloatSize& container_size, Func&& func) {
rounded_container_size.Height() / container_size.Height()));
}
-void SVGImage::DrawForContainer(PaintCanvas* canvas,
+void SVGImage::DrawForContainer(cc::PaintCanvas* canvas,
const PaintFlags& flags,
const FloatSize& container_size,
float zoom,
@@ -392,13 +392,13 @@ sk_sp<PaintRecord> SVGImage::PaintRecordForContainer(
return nullptr;
PaintRecorder recorder;
- PaintCanvas* canvas = recorder.beginRecording(draw_src_rect);
+ cc::PaintCanvas* canvas = recorder.beginRecording(draw_src_rect);
if (flip_y) {
canvas->translate(0, draw_dst_rect.Height());
canvas->scale(1, -1);
}
DrawForContainer(canvas, PaintFlags(), FloatSize(container_size), 1,
- draw_dst_rect, draw_src_rect, url);
+ FloatRect(draw_dst_rect), FloatRect(draw_src_rect), url);
return recorder.finishRecordingAsPicture();
}
@@ -412,9 +412,9 @@ void SVGImage::PopulatePaintRecordForCurrentFrameForContainer(
const IntRect container_rect(IntPoint(), container_size);
PaintRecorder recorder;
- PaintCanvas* canvas = recorder.beginRecording(container_rect);
+ cc::PaintCanvas* canvas = recorder.beginRecording(container_rect);
DrawForContainer(canvas, PaintFlags(), FloatSize(container_rect.Size()), 1,
- container_rect, container_rect, url);
+ FloatRect(container_rect), FloatRect(container_rect), url);
builder.set_paint_record(recorder.finishRecordingAsPicture(), container_rect,
PaintImage::GetNextContentId());
}
@@ -469,7 +469,7 @@ bool SVGImage::ApplyShaderForContainer(const FloatSize& container_size,
}
void SVGImage::Draw(
- PaintCanvas* canvas,
+ cc::PaintCanvas* canvas,
const PaintFlags& flags,
const FloatRect& dst_rect,
const FloatRect& src_rect,
@@ -483,12 +483,14 @@ void SVGImage::Draw(
should_respect_image_orientation, clamp_mode, NullURL());
}
-sk_sp<PaintRecord> SVGImage::PaintRecordForCurrentFrame(const IntRect& bounds,
- const KURL& url,
- PaintCanvas* canvas) {
+sk_sp<PaintRecord> SVGImage::PaintRecordForCurrentFrame(
+ const IntRect& bounds,
+ const KURL& url,
+ cc::PaintCanvas* canvas) {
DCHECK(page_);
LocalFrameView* view = ToLocalFrame(page_->MainFrame())->View();
view->Resize(ContainerSize());
+ page_->GetVisualViewport().SetSize(ContainerSize());
// Always call processUrlFragment, even if the url is empty, because
// there may have been a previous url/fragment that needs to be reset.
@@ -515,7 +517,7 @@ sk_sp<PaintRecord> SVGImage::PaintRecordForCurrentFrame(const IntRect& bounds,
return builder.EndRecording();
}
-void SVGImage::DrawInternal(PaintCanvas* canvas,
+void SVGImage::DrawInternal(cc::PaintCanvas* canvas,
const PaintFlags& flags,
const FloatRect& dst_rect,
const FloatRect& src_rect,
@@ -591,6 +593,17 @@ void SVGImage::ResetAnimation() {
ScheduleTimelineRewind();
}
+void SVGImage::RestoreAnimation() {
+ // If the image has no animations then do nothing.
+ if (!MaybeAnimated())
+ return;
+ // If there are no clients, or no client is going to render, then do nothing.
+ ImageObserver* image_observer = GetImageObserver();
+ if (!image_observer || image_observer->ShouldPauseAnimation(this))
+ return;
+ StartAnimation();
+}
+
bool SVGImage::MaybeAnimated() {
SVGSVGElement* root_element = SvgRootElement(page_.Get());
if (!root_element)
@@ -633,11 +646,12 @@ void SVGImage::ServiceAnimations(
LocalFrameView* frame_view = ToLocalFrame(page_->MainFrame())->View();
frame_view->UpdateAllLifecyclePhasesExceptPaint();
- if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- // For SPv2 we run UpdateAnimations after the paint phase, but per above
- // comment we don't want to run lifecycle through to paint for SVG images.
- // Since we know SVG images never have composited animations we can update
- // animations directly without worrying about including
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled() ||
+ RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled()) {
+ // For SPv2/BGPT we run UpdateAnimations after the paint phase, but per the
+ // above comment, we don't want to run lifecycle through to paint for SVG
+ // images. Since we know SVG images never have composited animations we can
+ // update animations directly without worrying about including
// PaintArtifactCompositor analysis of whether animations should be
// composited.
base::Optional<CompositorElementIdSet> composited_element_ids;
@@ -787,7 +801,6 @@ Image::SizeAvailability SVGImage::DataChanged(bool all_data_received) {
FrameLoader& loader = frame->Loader();
loader.ForceSandboxFlags(kSandboxAll);
- frame->View()->SetScrollbarsSuppressed(true);
// SVG Images will always synthesize a viewBox, if it's not available, and
// thus never see scrollbars.
frame->View()->SetCanHaveScrollbars(false);
diff --git a/chromium/third_party/blink/renderer/core/svg/graphics/svg_image.h b/chromium/third_party/blink/renderer/core/svg/graphics/svg_image.h
index 40ff71b5cfa..ad74de97b1a 100644
--- a/chromium/third_party/blink/renderer/core/svg/graphics/svg_image.h
+++ b/chromium/third_party/blink/renderer/core/svg/graphics/svg_image.h
@@ -73,6 +73,7 @@ class CORE_EXPORT SVGImage final : public Image {
void StartAnimation() override;
void ResetAnimation() override;
+ void RestoreAnimation();
PaintImage::CompletionState completion_state() const {
return load_state_ == LoadState::kLoadCompleted
@@ -151,15 +152,15 @@ class CORE_EXPORT SVGImage final : public Image {
// FIXME: Implement this to be less conservative.
bool CurrentFrameKnownToBeOpaque() override { return false; }
- void Draw(PaintCanvas*,
- const PaintFlags&,
+ void Draw(cc::PaintCanvas*,
+ const cc::PaintFlags&,
const FloatRect& from_rect,
const FloatRect& to_rect,
RespectImageOrientationEnum,
ImageClampingMode,
ImageDecodingMode) override;
- void DrawForContainer(PaintCanvas*,
- const PaintFlags&,
+ void DrawForContainer(cc::PaintCanvas*,
+ const cc::PaintFlags&,
const FloatSize&,
float,
const FloatRect&,
@@ -185,10 +186,10 @@ class CORE_EXPORT SVGImage final : public Image {
// Otherwise returns a pointer to the new PaintRecord.
sk_sp<PaintRecord> PaintRecordForCurrentFrame(const IntRect& bounds,
const KURL&,
- PaintCanvas* = nullptr);
+ cc::PaintCanvas* = nullptr);
- void DrawInternal(PaintCanvas*,
- const PaintFlags&,
+ void DrawInternal(cc::PaintCanvas*,
+ const cc::PaintFlags&,
const FloatRect& from_rect,
const FloatRect& to_rect,
RespectImageOrientationEnum,
@@ -198,13 +199,13 @@ class CORE_EXPORT SVGImage final : public Image {
template <typename Func>
void ForContainer(const FloatSize&, Func&&);
- bool ApplyShader(PaintFlags&, const SkMatrix& local_matrix) override;
+ bool ApplyShader(cc::PaintFlags&, const SkMatrix& local_matrix) override;
bool ApplyShaderForContainer(const FloatSize&,
float zoom,
const KURL&,
- PaintFlags&,
+ cc::PaintFlags&,
const SkMatrix& local_matrix);
- bool ApplyShaderInternal(PaintFlags&,
+ bool ApplyShaderInternal(cc::PaintFlags&,
const SkMatrix& local_matrix,
const KURL&);
@@ -242,6 +243,7 @@ class CORE_EXPORT SVGImage final : public Image {
Persistent<SVGImageLocalFrameClient> frame_client_;
FRIEND_TEST_ALL_PREFIXES(SVGImageTest, SupportsSubsequenceCaching);
FRIEND_TEST_ALL_PREFIXES(SVGImageTest, JankTrackerDisabled);
+ FRIEND_TEST_ALL_PREFIXES(SVGImageTest, SetSizeOnVisualViewport);
};
DEFINE_IMAGE_TYPE_CASTS(SVGImage);
diff --git a/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc b/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc
index 710433e1e51..a3a240ddc42 100644
--- a/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc
+++ b/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc
@@ -38,7 +38,8 @@
namespace blink {
-static const double kAnimationFrameDelay = 1.0 / 60;
+static constexpr TimeDelta kAnimationFrameDelay =
+ TimeDelta::FromSecondsD(1.0 / 60);
SVGImageChromeClient::SVGImageChromeClient(SVGImage* image)
: image_(image),
@@ -91,6 +92,13 @@ void SVGImageChromeClient::ResumeAnimation() {
ScheduleAnimation(nullptr);
}
+void SVGImageChromeClient::RestoreAnimationIfNeeded() {
+ // If the timeline is not suspended we needn't attempt to restore.
+ if (!IsSuspended())
+ return;
+ image_->RestoreAnimation();
+}
+
void SVGImageChromeClient::ScheduleAnimation(const LocalFrameView*) {
// Because a single SVGImage can be shared by multiple pages, we can't key
// our svg image layout on the page's real animation frame. Therefore, we
@@ -103,9 +111,9 @@ void SVGImageChromeClient::ScheduleAnimation(const LocalFrameView*) {
// animations, but prefer a fixed, jittery, frame-delay if there're any
// animations. Checking for pending/active animations could be more
// stringent.
- double fire_time = 0;
+ TimeDelta fire_time;
if (image_->MaybeAnimated()) {
- if (timeline_state_ >= kSuspended)
+ if (IsSuspended())
return;
fire_time = kAnimationFrameDelay;
}
diff --git a/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h b/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h
index 736dafd01d1..059446061e1 100644
--- a/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h
+++ b/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h
@@ -49,6 +49,8 @@ class CORE_EXPORT SVGImageChromeClient final : public EmptyChromeClient {
void SuspendAnimation();
void ResumeAnimation();
+ void RestoreAnimationIfNeeded();
+
bool IsSuspended() const { return timeline_state_ >= kSuspended; }
private:
@@ -59,6 +61,7 @@ class CORE_EXPORT SVGImageChromeClient final : public EmptyChromeClient {
void ScheduleAnimation(const LocalFrameView*) override;
void SetTimer(std::unique_ptr<TimerBase>);
+ TimerBase* GetTimerForTesting() const { return animation_timer_.get(); }
void AnimationTimerFired(TimerBase*);
SVGImage* image_;
@@ -71,6 +74,8 @@ class CORE_EXPORT SVGImageChromeClient final : public EmptyChromeClient {
FRIEND_TEST_ALL_PREFIXES(SVGImageTest, TimelineSuspendAndResume);
FRIEND_TEST_ALL_PREFIXES(SVGImageTest, ResetAnimation);
+ FRIEND_TEST_ALL_PREFIXES(SVGImagePageVisibilityTest,
+ PageVisibilityHiddenToVisible);
};
DEFINE_TYPE_CASTS(SVGImageChromeClient,
diff --git a/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.cc b/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.cc
index 243c5115c46..9745ea45053 100644
--- a/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.cc
+++ b/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.cc
@@ -33,8 +33,8 @@ IntSize SVGImageForContainer::Size() const {
return RoundedIntSize(scaled_container_size);
}
-void SVGImageForContainer::Draw(PaintCanvas* canvas,
- const PaintFlags& flags,
+void SVGImageForContainer::Draw(cc::PaintCanvas* canvas,
+ const cc::PaintFlags& flags,
const FloatRect& dst_rect,
const FloatRect& src_rect,
RespectImageOrientationEnum,
@@ -56,7 +56,7 @@ void SVGImageForContainer::DrawPattern(GraphicsContext& context,
url_);
}
-bool SVGImageForContainer::ApplyShader(PaintFlags& flags,
+bool SVGImageForContainer::ApplyShader(cc::PaintFlags& flags,
const SkMatrix& local_matrix) {
return image_->ApplyShaderForContainer(container_size_, zoom_, url_, flags,
local_matrix);
diff --git a/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h b/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h
index a7d3e7531ce..bf81d1c3b66 100644
--- a/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h
+++ b/chromium/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h
@@ -76,10 +76,10 @@ class SVGImageForContainer final : public Image {
}
bool HasRelativeSize() const override { return image_->HasRelativeSize(); }
- bool ApplyShader(PaintFlags&, const SkMatrix& local_matrix) override;
+ bool ApplyShader(cc::PaintFlags&, const SkMatrix& local_matrix) override;
- void Draw(PaintCanvas*,
- const PaintFlags&,
+ void Draw(cc::PaintCanvas*,
+ const cc::PaintFlags&,
const FloatRect&,
const FloatRect&,
RespectImageOrientationEnum,
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 15bbb9ff155..31c2365e760 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
@@ -10,9 +10,13 @@
#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_view.h"
+#include "third_party/blink/renderer/core/frame/visual_viewport.h"
+#include "third_party/blink/renderer/core/html/html_image_element.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/paint/paint_layer.h"
#include "third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.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/float_rect.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_flags.h"
@@ -111,7 +115,7 @@ TEST_F(SVGImageTest, TimelineSuspendAndResume) {
// true for shouldPauseAnimation, this will result in the timeline being
// suspended.
test::RunDelayedTasks(TimeDelta::FromMilliseconds(1) +
- TimeDelta::FromSecondsD(timer->NextFireInterval()));
+ timer->NextFireInterval());
EXPECT_TRUE(chrome_client.IsSuspended());
EXPECT_FALSE(timer->IsActive());
@@ -145,7 +149,7 @@ TEST_F(SVGImageTest, ResetAnimation) {
// Fire the timer/trigger a frame update. The timeline will remain
// suspended and no frame will be scheduled.
test::RunDelayedTasks(TimeDelta::FromMillisecondsD(1) +
- TimeDelta::FromSecondsD(timer->NextFireInterval()));
+ timer->NextFireInterval());
EXPECT_TRUE(chrome_client.IsSuspended());
EXPECT_FALSE(timer->IsActive());
@@ -178,4 +182,72 @@ TEST_F(SVGImageTest, JankTrackerDisabled) {
EXPECT_FALSE(jank_tracker.IsActive());
}
+TEST_F(SVGImageTest, SetSizeOnVisualViewport) {
+ const bool kDontPause = false;
+ Load(
+ "<svg xmlns='http://www.w3.org/2000/svg'>"
+ " <rect id='green' width='100%' height='100%' fill='green' />"
+ "</svg>",
+ kDontPause);
+ PumpFrame();
+ LocalFrame* local_frame =
+ ToLocalFrame(GetImage().GetPageForTesting()->MainFrame());
+ ASSERT_FALSE(local_frame->View()->Size().IsEmpty());
+ EXPECT_EQ(local_frame->View()->Size(),
+ GetImage().GetPageForTesting()->GetVisualViewport().Size());
+}
+
+class SVGImagePageVisibilityTest : public SimTest {};
+
+TEST_F(SVGImagePageVisibilityTest, PageVisibilityHiddenToVisible) {
+ SimRequest main_resource("https://example.com/", "text/html");
+ SimRequest image_resource("https://example.com/image.svg", "image/svg+xml");
+ LoadURL("https://example.com/");
+ main_resource.Complete("<img src='image.svg' width='100' id='image'>");
+ image_resource.Complete(kAnimatedDocument);
+
+ Compositor().BeginFrame();
+ test::RunPendingTasks();
+
+ Element* element = GetDocument().getElementById("image");
+ ASSERT_TRUE(IsHTMLImageElement(element));
+
+ ImageResourceContent* image_content =
+ ToHTMLImageElement(*element).CachedImage();
+ ASSERT_TRUE(image_content);
+ ASSERT_TRUE(image_content->IsLoaded());
+ ASSERT_TRUE(image_content->HasImage());
+ Image* image = image_content->GetImage();
+ ASSERT_TRUE(image->IsSVGImage());
+ SVGImageChromeClient& svg_image_chrome_client =
+ ToSVGImage(*image).ChromeClientForTesting();
+ TimerBase* timer = svg_image_chrome_client.GetTimerForTesting();
+
+ // Wait for the next animation frame to be triggered, and then trigger a new
+ // frame. The image animation timeline should be running.
+ test::RunDelayedTasks(TimeDelta::FromMilliseconds(1) +
+ timer->NextFireInterval());
+ Compositor().BeginFrame();
+
+ EXPECT_FALSE(svg_image_chrome_client.IsSuspended());
+
+ // 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(mojom::PageVisibilityState::kHidden, false);
+ test::RunDelayedTasks(TimeDelta::FromMilliseconds(1) +
+ timer->NextFireInterval());
+
+ EXPECT_TRUE(svg_image_chrome_client.IsSuspended());
+
+ // Set page visibility to 'visible' - this should schedule a new animation
+ // frame and resume the image animation.
+ WebView().SetVisibilityState(mojom::PageVisibilityState::kVisible, false);
+ test::RunDelayedTasks(TimeDelta::FromMilliseconds(1) +
+ timer->NextFireInterval());
+ Compositor().BeginFrame();
+
+ EXPECT_FALSE(svg_image_chrome_client.IsSuspended());
+}
+
} // namespace blink
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 48c579f0aff..4032183191d 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
@@ -79,9 +79,6 @@ class SVGAnimatedPropertyBase : public GarbageCollectedMixin {
void Trace(blink::Visitor* visitor) override {
visitor->Trace(context_element_);
}
- virtual void TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(context_element_);
- }
protected:
SVGAnimatedPropertyBase(AnimatedPropertyType,
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 a427849003c..8bb717a88e0 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
@@ -31,11 +31,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SVG_PROPERTIES_SVG_LIST_PROPERTY_HELPER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SVG_PROPERTIES_SVG_LIST_PROPERTY_HELPER_H_
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/svg/properties/svg_property_helper.h"
#include "third_party/blink/renderer/core/svg/svg_animation_element.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -230,7 +229,7 @@ ItemProperty* SVGListPropertyHelper<Derived, ItemProperty>::ReplaceItem(
// which means there's nothing to replace.
// TODO(fs): This should not cause us to throw an exception.
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
String::Format("Failed to replace the provided item at index %zu.",
index));
return nullptr;
@@ -251,8 +250,9 @@ bool SVGListPropertyHelper<Derived, ItemProperty>::CheckIndexBound(
ExceptionState& exception_state) {
if (index >= values_.size()) {
exception_state.ThrowDOMException(
- kIndexSizeError, ExceptionMessages::IndexExceedsMaximumBound(
- "index", index, values_.size()));
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexExceedsMaximumBound("index", index,
+ values_.size()));
return false;
}
return true;
diff --git a/chromium/third_party/blink/renderer/core/svg/properties/svg_list_property_tear_off_helper.h b/chromium/third_party/blink/renderer/core/svg/properties/svg_list_property_tear_off_helper.h
index fde742a9cb2..78aa5bab91b 100644
--- a/chromium/third_party/blink/renderer/core/svg/properties/svg_list_property_tear_off_helper.h
+++ b/chromium/third_party/blink/renderer/core/svg/properties/svg_list_property_tear_off_helper.h
@@ -182,10 +182,6 @@ class SVGListPropertyTearOffHelper : public SVGPropertyTearOff<ListProperty> {
return CreateItemTearOff(value);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- SVGPropertyTearOff<ListProperty>::TraceWrappers(visitor);
- }
-
protected:
SVGListPropertyTearOffHelper(
ListPropertyType* target,
diff --git a/chromium/third_party/blink/renderer/core/svg/properties/svg_property_tear_off.cc b/chromium/third_party/blink/renderer/core/svg/properties/svg_property_tear_off.cc
index c20574ba46c..d3a40e45d37 100644
--- a/chromium/third_party/blink/renderer/core/svg/properties/svg_property_tear_off.cc
+++ b/chromium/third_party/blink/renderer/core/svg/properties/svg_property_tear_off.cc
@@ -30,16 +30,16 @@
#include "third_party/blink/renderer/core/svg/properties/svg_property_tear_off.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
void SVGPropertyTearOffBase::ThrowReadOnly(ExceptionState& exception_state) {
- exception_state.ThrowDOMException(kNoModificationAllowedError,
- ExceptionMessages::ReadOnly());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNoModificationAllowedError,
+ ExceptionMessages::ReadOnly());
}
void SVGPropertyTearOffBase::CommitChange() {
diff --git a/chromium/third_party/blink/renderer/core/svg/properties/svg_property_tear_off.h b/chromium/third_party/blink/renderer/core/svg/properties/svg_property_tear_off.h
index ac72e94774a..d1107a4a36e 100644
--- a/chromium/third_party/blink/renderer/core/svg/properties/svg_property_tear_off.h
+++ b/chromium/third_party/blink/renderer/core/svg/properties/svg_property_tear_off.h
@@ -77,11 +77,6 @@ class SVGPropertyTearOffBase : public ScriptWrappable {
ScriptWrappable::Trace(visitor);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- visitor->TraceWrappers(context_element_);
- ScriptWrappable::TraceWrappers(visitor);
- }
-
static void ThrowReadOnly(ExceptionState&);
protected:
@@ -116,10 +111,6 @@ class SVGPropertyTearOff : public SVGPropertyTearOffBase {
SVGPropertyTearOffBase::Trace(visitor);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- SVGPropertyTearOffBase::TraceWrappers(visitor);
- }
-
protected:
SVGPropertyTearOff(Property* target,
SVGElement* context_element,
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_a_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_a_element.cc
index 42b8fd46225..a6328c0ec3d 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_a_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_a_element.cc
@@ -136,8 +136,12 @@ void SVGAElement::DefaultEventHandler(Event* event) {
FrameLoadRequest frame_request(
&GetDocument(), ResourceRequest(GetDocument().CompleteURL(url)),
target);
- frame_request.SetTriggeringEvent(event);
- frame->Loader().StartNavigation(frame_request);
+ frame_request.SetTriggeringEventInfo(
+ event->isTrusted() ? WebTriggeringEventInfo::kFromTrustedEvent
+ : WebTriggeringEventInfo::kFromUntrustedEvent);
+ frame->Loader().StartNavigation(frame_request,
+ WebFrameLoadType::kStandard,
+ NavigationPolicyFromEvent(event));
return;
}
}
@@ -163,7 +167,8 @@ bool SVGAElement::SupportsFocus() const {
}
bool SVGAElement::ShouldHaveFocusAppearance() const {
- return !WasFocusedByMouse() || SVGGraphicsElement::SupportsFocus();
+ return (GetDocument().LastFocusType() != kWebFocusTypeMouse) ||
+ SVGGraphicsElement::SupportsFocus();
}
bool SVGAElement::IsURLAttribute(const Attribute& attribute) const {
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_angle_tear_off.cc b/chromium/third_party/blink/renderer/core/svg/svg_angle_tear_off.cc
index 427a00337ea..c518e19eb2c 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_angle_tear_off.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_angle_tear_off.cc
@@ -30,9 +30,8 @@
#include "third_party/blink/renderer/core/svg/svg_angle_tear_off.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -77,8 +76,9 @@ void SVGAngleTearOff::newValueSpecifiedUnits(unsigned short unit_type,
if (unit_type == SVGAngle::kSvgAngletypeUnknown ||
unit_type > SVGAngle::kSvgAngletypeGrad) {
exception_state.ThrowDOMException(
- kNotSupportedError, "Cannot set value with unknown or invalid units (" +
- String::Number(unit_type) + ").");
+ DOMExceptionCode::kNotSupportedError,
+ "Cannot set value with unknown or invalid units (" +
+ String::Number(unit_type) + ").");
return;
}
Target()->NewValueSpecifiedUnits(
@@ -95,13 +95,15 @@ void SVGAngleTearOff::convertToSpecifiedUnits(unsigned short unit_type,
if (unit_type == SVGAngle::kSvgAngletypeUnknown ||
unit_type > SVGAngle::kSvgAngletypeGrad) {
exception_state.ThrowDOMException(
- kNotSupportedError, "Cannot convert to unknown or invalid units (" +
- String::Number(unit_type) + ").");
+ DOMExceptionCode::kNotSupportedError,
+ "Cannot convert to unknown or invalid units (" +
+ String::Number(unit_type) + ").");
return;
}
if (Target()->UnitType() == SVGAngle::kSvgAngletypeUnknown) {
exception_state.ThrowDOMException(
- kNotSupportedError, "Cannot convert from unknown or invalid units.");
+ DOMExceptionCode::kNotSupportedError,
+ "Cannot convert from unknown or invalid units.");
return;
}
Target()->ConvertToSpecifiedUnits(
@@ -123,7 +125,8 @@ void SVGAngleTearOff::setValueAsString(const String& value,
}
if (status != SVGParseStatus::kNoError) {
exception_state.ThrowDOMException(
- kSyntaxError, "The value provided ('" + value + "') is invalid.");
+ DOMExceptionCode::kSyntaxError,
+ "The value provided ('" + value + "') is invalid.");
return;
}
CommitChange();
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_angle.cc b/chromium/third_party/blink/renderer/core/svg/svg_animated_angle.cc
index 8a39ac1b8dc..9769ff07fe3 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_angle.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_angle.cc
@@ -51,11 +51,6 @@ void SVGAnimatedAngle::Trace(blink::Visitor* visitor) {
ScriptWrappable::Trace(visitor);
}
-void SVGAnimatedAngle::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- SVGAnimatedProperty<SVGAngle>::TraceWrappers(visitor);
- ScriptWrappable::TraceWrappers(visitor);
-}
-
bool SVGAnimatedAngle::NeedsSynchronizeAttribute() {
return orient_type_->NeedsSynchronizeAttribute() ||
SVGAnimatedProperty<SVGAngle>::NeedsSynchronizeAttribute();
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_angle.h b/chromium/third_party/blink/renderer/core/svg/svg_animated_angle.h
index e711b0190a4..4015b78b385 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_angle.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_angle.h
@@ -63,8 +63,6 @@ class SVGAnimatedAngle final : public ScriptWrappable,
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
protected:
explicit SVGAnimatedAngle(SVGElement* context_element);
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_boolean.h b/chromium/third_party/blink/renderer/core/svg/svg_animated_boolean.h
index 81580b218ba..1220c930907 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_boolean.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_boolean.h
@@ -53,11 +53,6 @@ class SVGAnimatedBoolean final : public ScriptWrappable,
ScriptWrappable::Trace(visitor);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- SVGAnimatedProperty<SVGBoolean>::TraceWrappers(visitor);
- ScriptWrappable::TraceWrappers(visitor);
- }
-
protected:
SVGAnimatedBoolean(SVGElement* context_element,
const QualifiedName& attribute_name)
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_enumeration_base.cc b/chromium/third_party/blink/renderer/core/svg/svg_animated_enumeration_base.cc
index a11abc5be3b..525251a00a7 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_enumeration_base.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_enumeration_base.cc
@@ -30,8 +30,8 @@
#include "third_party/blink/renderer/core/svg/svg_animated_enumeration_base.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_enumeration_base.h b/chromium/third_party/blink/renderer/core/svg/svg_animated_enumeration_base.h
index cb8168507a5..0ada0b5efef 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_enumeration_base.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_enumeration_base.h
@@ -53,11 +53,6 @@ class SVGAnimatedEnumerationBase
ScriptWrappable::Trace(visitor);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- SVGAnimatedProperty<SVGEnumerationBase>::TraceWrappers(visitor);
- ScriptWrappable::TraceWrappers(visitor);
- }
-
protected:
SVGAnimatedEnumerationBase(SVGElement* context_element,
const QualifiedName& attribute_name,
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_integer.cc b/chromium/third_party/blink/renderer/core/svg/svg_animated_integer.cc
index 2c489d3706a..fd690d339ab 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_integer.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_integer.cc
@@ -50,9 +50,4 @@ void SVGAnimatedInteger::Trace(blink::Visitor* visitor) {
ScriptWrappable::Trace(visitor);
}
-void SVGAnimatedInteger::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- SVGAnimatedProperty<SVGInteger>::TraceWrappers(visitor);
- ScriptWrappable::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_integer.h b/chromium/third_party/blink/renderer/core/svg/svg_animated_integer.h
index 697e09c6bd5..4c9ad63921d 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_integer.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_integer.h
@@ -63,8 +63,6 @@ class SVGAnimatedInteger : public ScriptWrappable,
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
protected:
SVGAnimatedInteger(SVGElement* context_element,
const QualifiedName& attribute_name,
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_length.cc b/chromium/third_party/blink/renderer/core/svg/svg_animated_length.cc
index e2b1e37fc63..b44a605ebd1 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_length.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_length.cc
@@ -57,9 +57,4 @@ void SVGAnimatedLength::Trace(blink::Visitor* visitor) {
ScriptWrappable::Trace(visitor);
}
-void SVGAnimatedLength::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- SVGAnimatedProperty<SVGLength>::TraceWrappers(visitor);
- ScriptWrappable::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_length.h b/chromium/third_party/blink/renderer/core/svg/svg_animated_length.h
index 8d5a7742bf6..eab3f978005 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_length.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_length.h
@@ -60,7 +60,6 @@ class SVGAnimatedLength : public ScriptWrappable,
}
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
protected:
SVGAnimatedLength(SVGElement* context_element,
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_length_list.h b/chromium/third_party/blink/renderer/core/svg/svg_animated_length_list.h
index e168c994215..3738a2012b8 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_length_list.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_length_list.h
@@ -57,11 +57,6 @@ class SVGAnimatedLengthList final : public ScriptWrappable,
ScriptWrappable::Trace(visitor);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- SVGAnimatedProperty<SVGLengthList>::TraceWrappers(visitor);
- ScriptWrappable::TraceWrappers(visitor);
- }
-
protected:
SVGAnimatedLengthList(SVGElement* context_element,
const QualifiedName& attribute_name,
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_number.cc b/chromium/third_party/blink/renderer/core/svg/svg_animated_number.cc
index 695abff7391..c712644904f 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_number.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_number.cc
@@ -50,9 +50,4 @@ void SVGAnimatedNumber::Trace(blink::Visitor* visitor) {
ScriptWrappable::Trace(visitor);
}
-void SVGAnimatedNumber::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- SVGAnimatedProperty<SVGNumber>::TraceWrappers(visitor);
- ScriptWrappable::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_number.h b/chromium/third_party/blink/renderer/core/svg/svg_animated_number.h
index e3f6366a502..074c747aca4 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_number.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_number.h
@@ -63,8 +63,6 @@ class SVGAnimatedNumber : public ScriptWrappable,
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
protected:
SVGAnimatedNumber(SVGElement* context_element,
const QualifiedName& attribute_name,
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_number_list.h b/chromium/third_party/blink/renderer/core/svg/svg_animated_number_list.h
index 5daeacb2ddf..e06f6ac5a78 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_number_list.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_number_list.h
@@ -55,11 +55,6 @@ class SVGAnimatedNumberList final : public ScriptWrappable,
ScriptWrappable::Trace(visitor);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- SVGAnimatedProperty<SVGNumberList>::TraceWrappers(visitor);
- ScriptWrappable::TraceWrappers(visitor);
- }
-
protected:
SVGAnimatedNumberList(SVGElement* context_element,
const QualifiedName& attribute_name)
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_preserve_aspect_ratio.h b/chromium/third_party/blink/renderer/core/svg/svg_animated_preserve_aspect_ratio.h
index a048a2ee587..9a5a2708c06 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_preserve_aspect_ratio.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_preserve_aspect_ratio.h
@@ -55,11 +55,6 @@ class SVGAnimatedPreserveAspectRatio
ScriptWrappable::Trace(visitor);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- SVGAnimatedProperty<SVGPreserveAspectRatio>::TraceWrappers(visitor);
- ScriptWrappable::TraceWrappers(visitor);
- }
-
protected:
SVGAnimatedPreserveAspectRatio(SVGElement* context_element,
const QualifiedName& attribute_name)
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_rect.h b/chromium/third_party/blink/renderer/core/svg/svg_animated_rect.h
index 9b63ffa9dcc..c400d9c3840 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_rect.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_rect.h
@@ -53,11 +53,6 @@ class SVGAnimatedRect : public ScriptWrappable,
ScriptWrappable::Trace(visitor);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- SVGAnimatedProperty<SVGRect>::TraceWrappers(visitor);
- ScriptWrappable::TraceWrappers(visitor);
- }
-
protected:
SVGAnimatedRect(SVGElement* context_element,
const QualifiedName& attribute_name)
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_string.cc b/chromium/third_party/blink/renderer/core/svg/svg_animated_string.cc
index b3b108ad9ec..8804faf0356 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_string.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_string.cc
@@ -24,9 +24,4 @@ void SVGAnimatedString::Trace(blink::Visitor* visitor) {
ScriptWrappable::Trace(visitor);
}
-void SVGAnimatedString::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- SVGAnimatedProperty<SVGString>::TraceWrappers(visitor);
- ScriptWrappable::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_string.h b/chromium/third_party/blink/renderer/core/svg/svg_animated_string.h
index 930f66f64db..13b213d5b6a 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_string.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_string.h
@@ -53,7 +53,6 @@ class SVGAnimatedString : public ScriptWrappable,
virtual String animVal();
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
protected:
SVGAnimatedString(SVGElement* context_element,
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animated_transform_list.h b/chromium/third_party/blink/renderer/core/svg/svg_animated_transform_list.h
index 64be226c754..e40b3dc092b 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animated_transform_list.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animated_transform_list.h
@@ -59,11 +59,6 @@ class SVGAnimatedTransformList final
ScriptWrappable::Trace(visitor);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- SVGAnimatedProperty<SVGTransformList>::TraceWrappers(visitor);
- ScriptWrappable::TraceWrappers(visitor);
- }
-
protected:
SVGAnimatedTransformList(SVGElement* context_element,
const QualifiedName& attribute_name,
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_animation_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_animation_element.cc
index 86514e68176..1c8e310b5b1 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_animation_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_animation_element.cc
@@ -24,12 +24,12 @@
#include "third_party/blink/renderer/core/svg/svg_animation_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/svg/svg_animate_element.h"
#include "third_party/blink/renderer/core/svg/svg_parser_utilities.h"
#include "third_party/blink/renderer/core/svg_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
namespace blink {
@@ -237,7 +237,7 @@ void SVGAnimationElement::AnimationAttributeChanged() {
float SVGAnimationElement::getStartTime(ExceptionState& exception_state) const {
SMILTime start_time = IntervalBegin();
if (!start_time.IsFinite()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"No current interval.");
return 0;
}
@@ -252,7 +252,7 @@ float SVGAnimationElement::getSimpleDuration(
ExceptionState& exception_state) const {
SMILTime duration = SimpleDuration();
if (!duration.IsFinite()) {
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"No simple duration defined.");
return 0;
}
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_ellipse_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_ellipse_element.cc
index a49b4ca7098..2f2dfa882d6 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_ellipse_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_ellipse_element.cc
@@ -69,6 +69,10 @@ Path SVGEllipseElement::AsPath() const {
FloatSize radii(ToFloatSize(
length_context.ResolveLengthPair(svg_style.Rx(), svg_style.Ry(), style)));
+ if (svg_style.Rx().IsAuto())
+ radii.SetWidth(radii.Height());
+ else if (svg_style.Ry().IsAuto())
+ radii.SetHeight(radii.Width());
if (radii.Width() < 0 || radii.Height() < 0 ||
(!radii.Width() && !radii.Height()))
return path;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fit_to_view_box.cc b/chromium/third_party/blink/renderer/core/svg/svg_fit_to_view_box.cc
index 0ea483c3893..7328b6ef3a7 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fit_to_view_box.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fit_to_view_box.cc
@@ -71,7 +71,7 @@ void SVGFitToViewBox::Trace(blink::Visitor* visitor) {
AffineTransform SVGFitToViewBox::ViewBoxToViewTransform(
const FloatRect& view_box_rect,
- SVGPreserveAspectRatio* preserve_aspect_ratio,
+ const SVGPreserveAspectRatio* preserve_aspect_ratio,
float view_width,
float view_height) {
if (!view_box_rect.Width() || !view_box_rect.Height() || !view_width ||
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_fit_to_view_box.h b/chromium/third_party/blink/renderer/core/svg/svg_fit_to_view_box.h
index bbef21ac340..58d6af310fa 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_fit_to_view_box.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_fit_to_view_box.h
@@ -36,7 +36,7 @@ class QualifiedName;
class SVGFitToViewBox : public GarbageCollectedMixin {
public:
static AffineTransform ViewBoxToViewTransform(const FloatRect& view_box_rect,
- SVGPreserveAspectRatio*,
+ const SVGPreserveAspectRatio*,
float view_width,
float view_height);
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_foreign_object_element.h b/chromium/third_party/blink/renderer/core/svg/svg_foreign_object_element.h
index 914185aa19e..481cd953954 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_foreign_object_element.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_foreign_object_element.h
@@ -50,6 +50,12 @@ class SVGForeignObjectElement final : public SVGGraphicsElement {
LayoutObject* CreateLayoutObject(const ComputedStyle&) override;
+ // As long as the foreignObject element itself creates a legacy layout object,
+ // we need to use legacy layout for the entire block formatting context
+ // established by the foreignObject. For simplicity, just force legacy for the
+ // entire subtree.
+ bool ShouldForceLegacyLayout() const override { return true; }
+
bool SelfHasRelativeLengths() const override;
Member<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 1e46cbab025..97ee5aae7aa 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
@@ -141,8 +141,17 @@ SVGPointTearOff* SVGGeometryElement::getPointAtLength(float length) {
GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();
FloatPoint point;
- if (GetLayoutObject())
- point = AsPath().PointAtLength(length);
+ if (GetLayoutObject()) {
+ const Path& path = AsPath();
+ if (length < 0) {
+ length = 0;
+ } else {
+ float computed_length = path.length();
+ if (length > computed_length)
+ length = computed_length;
+ }
+ point = path.PointAtLength(length);
+ }
return SVGPointTearOff::CreateDetached(point);
}
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_length_tear_off.cc b/chromium/third_party/blink/renderer/core/svg/svg_length_tear_off.cc
index ffb2a810509..43aec9b463a 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_length_tear_off.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_length_tear_off.cc
@@ -30,9 +30,8 @@
#include "third_party/blink/renderer/core/svg/svg_length_tear_off.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -119,7 +118,7 @@ SVGLengthMode SVGLengthTearOff::UnitMode() {
float SVGLengthTearOff::value(ExceptionState& exception_state) {
if (Target()->IsRelative() && !CanResolveRelativeUnits(contextElement())) {
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"Could not resolve relative length.");
return 0;
}
@@ -133,7 +132,7 @@ void SVGLengthTearOff::setValue(float value, ExceptionState& exception_state) {
return;
}
if (Target()->IsRelative() && !CanResolveRelativeUnits(contextElement())) {
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"Could not resolve relative length.");
return;
}
@@ -186,7 +185,8 @@ void SVGLengthTearOff::setValueAsString(const String& str,
}
if (status != SVGParseStatus::kNoError) {
exception_state.ThrowDOMException(
- kSyntaxError, "The value provided ('" + str + "') is invalid.");
+ DOMExceptionCode::kSyntaxError,
+ "The value provided ('" + str + "') is invalid.");
return;
}
CommitChange();
@@ -201,8 +201,9 @@ void SVGLengthTearOff::newValueSpecifiedUnits(unsigned short unit_type,
}
if (!IsValidLengthUnit(unit_type)) {
exception_state.ThrowDOMException(
- kNotSupportedError, "Cannot set value with unknown or invalid units (" +
- String::Number(unit_type) + ").");
+ DOMExceptionCode::kNotSupportedError,
+ "Cannot set value with unknown or invalid units (" +
+ String::Number(unit_type) + ").");
return;
}
Target()->NewValueSpecifiedUnits(ToCSSUnitType(unit_type),
@@ -219,14 +220,15 @@ void SVGLengthTearOff::convertToSpecifiedUnits(
}
if (!IsValidLengthUnit(unit_type)) {
exception_state.ThrowDOMException(
- kNotSupportedError, "Cannot convert to unknown or invalid units (" +
- String::Number(unit_type) + ").");
+ DOMExceptionCode::kNotSupportedError,
+ "Cannot convert to unknown or invalid units (" +
+ String::Number(unit_type) + ").");
return;
}
if ((Target()->IsRelative() ||
CSSPrimitiveValue::IsRelativeUnit(ToCSSUnitType(unit_type))) &&
!CanResolveRelativeUnits(contextElement())) {
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"Could not resolve relative length.");
return;
}
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_matrix_tear_off.cc b/chromium/third_party/blink/renderer/core/svg/svg_matrix_tear_off.cc
index b6083085f6d..606a1cfc3a4 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_matrix_tear_off.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_matrix_tear_off.cc
@@ -30,10 +30,9 @@
#include "third_party/blink/renderer/core/svg/svg_matrix_tear_off.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/core/svg/svg_transform_tear_off.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -50,11 +49,6 @@ void SVGMatrixTearOff::Trace(blink::Visitor* visitor) {
ScriptWrappable::Trace(visitor);
}
-void SVGMatrixTearOff::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(context_transform_);
- ScriptWrappable::TraceWrappers(visitor);
-}
-
const AffineTransform& SVGMatrixTearOff::Value() const {
return context_transform_ ? context_transform_->Target()->Matrix()
: static_value_;
@@ -149,7 +143,7 @@ SVGMatrixTearOff* SVGMatrixTearOff::multiply(SVGMatrixTearOff* other) {
SVGMatrixTearOff* SVGMatrixTearOff::inverse(ExceptionState& exception_state) {
if (!Value().IsInvertible()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The matrix is not invertible.");
return nullptr;
}
@@ -161,7 +155,7 @@ SVGMatrixTearOff* SVGMatrixTearOff::rotateFromVector(
double y,
ExceptionState& exception_state) {
if (!x || !y) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"Arguments cannot be zero.");
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_matrix_tear_off.h b/chromium/third_party/blink/renderer/core/svg/svg_matrix_tear_off.h
index bdee2ce33d7..aa78ee20ee0 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_matrix_tear_off.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_matrix_tear_off.h
@@ -89,7 +89,6 @@ class CORE_EXPORT SVGMatrixTearOff final : public ScriptWrappable {
const AffineTransform& Value() const;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
explicit SVGMatrixTearOff(const AffineTransform&);
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_parser_utilities.cc b/chromium/third_party/blink/renderer/core/svg/svg_parser_utilities.cc
index b9815dc7f7e..c7b613fd34c 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_parser_utilities.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_parser_utilities.cc
@@ -33,12 +33,6 @@ static inline bool IsValidRange(const FloatType x) {
return x >= -kMax && x <= kMax;
}
-template <typename FloatType>
-static inline bool IsValidExponent(const FloatType x) {
- return x >= std::numeric_limits<FloatType>::min_exponent10 &&
- x <= std::numeric_limits<FloatType>::max_exponent10;
-}
-
// We use this generic parseNumber function to allow the Path parsing code to
// work at a higher precision internally, without any unnecessary runtime cost
// or code complexity.
@@ -129,13 +123,19 @@ static bool GenericParseNumber(const CharType*& cursor,
exponent += *ptr - '0';
ptr++;
}
+ // TODO(fs): This is unnecessarily strict - the position of the decimal
+ // point is not taken into account when limiting |exponent|.
if (exponent_is_negative)
exponent = -exponent;
- // Make sure exponent is valid.
- if (!IsValidExponent(exponent))
+ // Fail if the exponent is greater than the largest positive power
+ // of ten (that would yield a representable float.)
+ if (exponent > std::numeric_limits<FloatType>::max_exponent10)
return false;
+ // If the exponent is smaller than smallest negative power of 10 (that
+ // would yield a representable float), then rely on the pow()+rounding to
+ // produce a reasonable result (likely zero.)
if (exponent)
- number *= static_cast<FloatType>(pow(10.0, static_cast<int>(exponent)));
+ number *= static_cast<FloatType>(std::pow(10.0, exponent));
}
// Don't return Infinity() or NaN().
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_path_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_path_element.cc
index 582dbe0e0ed..241cdadf3bf 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_path_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_path_element.cc
@@ -70,7 +70,15 @@ float SVGPathElement::getTotalLength() {
SVGPointTearOff* SVGPathElement::getPointAtLength(float length) {
GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets();
- FloatPoint point = SVGPathQuery(PathByteStream()).GetPointAtLength(length);
+ SVGPathQuery path_query(PathByteStream());
+ if (length < 0) {
+ length = 0;
+ } else {
+ float computed_length = path_query.GetTotalLength();
+ if (length > computed_length)
+ length = computed_length;
+ }
+ FloatPoint point = path_query.GetPointAtLength(length);
return SVGPointTearOff::CreateDetached(point);
}
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_path_parser.cc b/chromium/third_party/blink/renderer/core/svg/svg_path_parser.cc
index 0c842666cfb..447adfb8c25 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_path_parser.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_path_parser.cc
@@ -234,9 +234,9 @@ bool SVGPathNormalizer::DecomposeArcToCubic(
float theta_arc = theta2 - theta1;
if (theta_arc < 0 && arc_segment.arc_sweep)
- theta_arc += twoPiFloat;
+ theta_arc += kTwoPiFloat;
else if (theta_arc > 0 && !arc_segment.arc_sweep)
- theta_arc -= twoPiFloat;
+ theta_arc -= kTwoPiFloat;
point_transform.MakeIdentity();
point_transform.Rotate(angle);
@@ -245,7 +245,7 @@ bool SVGPathNormalizer::DecomposeArcToCubic(
// Some results of atan2 on some platform implementations are not exact
// enough. So that we get more cubic curves than expected here. Adding 0.001f
// reduces the count of sgements to the correct count.
- int segments = ceilf(fabsf(theta_arc / (piOverTwoFloat + 0.001f)));
+ int segments = ceilf(fabsf(theta_arc / (kPiOverTwoFloat + 0.001f)));
for (int i = 0; i < segments; ++i) {
float start_theta = theta1 + i * theta_arc / segments;
float end_theta = theta1 + (i + 1) * theta_arc / segments;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_path_parser_test.cc b/chromium/third_party/blink/renderer/core/svg/svg_path_parser_test.cc
index bd0ba0461ee..f4c64252802 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_path_parser_test.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_path_parser_test.cc
@@ -138,6 +138,19 @@ TEST(SVGPathParserTest, Simple) {
MALFORMED("M1,1A2,3,4,0,0,5,6 7", "M 1 1 A 2 3 4 0 0 5 6");
VALID("M1,1A2,3,4,0,0,5,6 7,8,9,0,0,10,11",
"M 1 1 A 2 3 4 0 0 5 6 A 7 8 9 0 0 10 11");
+
+ // Scientific notation.
+ VALID("M1e2,10e1", "M 100 100");
+ VALID("M100e0,100", "M 100 100");
+ VALID("M1e+2,1000e-1", "M 100 100");
+ VALID("M1e2.5", "M 100 0.5");
+ VALID("M0.00000001e10 100", "M 100 100");
+ VALID("M1e-46,50 h1e38", "M 0 50 h 1.00000e+38");
+ VALID("M0,50 h1e-123456789123456789123", "M 0 50 h 0");
+ MALFORMED("M0,50 h1e39", "M 0 50");
+ MALFORMED("M0,50 h1e123456789123456789123", "M 0 50");
+ MALFORMED("M0,50 h1e-.5", "M 0 50");
+ MALFORMED("M0,50 h1e+.5", "M 0 50");
}
#undef MALFORMED
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_preserve_aspect_ratio_tear_off.cc b/chromium/third_party/blink/renderer/core/svg/svg_preserve_aspect_ratio_tear_off.cc
index 816e5659455..643e441c637 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_preserve_aspect_ratio_tear_off.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_preserve_aspect_ratio_tear_off.cc
@@ -30,9 +30,8 @@
#include "third_party/blink/renderer/core/svg/svg_preserve_aspect_ratio_tear_off.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -44,7 +43,7 @@ void SVGPreserveAspectRatioTearOff::setAlign(unsigned short align,
}
if (align == kSvgPreserveaspectratioUnknown ||
align > kSvgPreserveaspectratioXmaxymax) {
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"The alignment provided is invalid.");
return;
}
@@ -62,7 +61,7 @@ void SVGPreserveAspectRatioTearOff::setMeetOrSlice(
}
if (meet_or_slice == kSvgMeetorsliceUnknown ||
meet_or_slice > kSvgMeetorsliceSlice) {
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"The meetOrSlice provided is invalid.");
return;
}
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 3a099f992eb..12bee5bfbc3 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
@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/bindings/core/v8/html_script_element_or_svg_script_element.h"
#include "third_party/blink/renderer/bindings/core/v8/script_event_listener.h"
#include "third_party/blink/renderer/core/dom/attribute.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/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/html_names.h"
@@ -184,9 +185,4 @@ void SVGScriptElement::Trace(blink::Visitor* visitor) {
ScriptElementBase::Trace(visitor);
}
-void SVGScriptElement::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(loader_);
- SVGElement::TraceWrappers(visitor);
-}
-
} // namespace blink
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 3363f8123c9..350c0859dc8 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
@@ -50,7 +50,6 @@ class SVGScriptElement final : public SVGElement,
bool IsScriptElement() const override { return true; }
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
SVGScriptElement(Document&, const CreateElementFlags);
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_string_list.cc b/chromium/third_party/blink/renderer/core/svg/svg_string_list.cc
index 4b2922a5233..aeb1453f482 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_string_list.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_string_list.cc
@@ -20,11 +20,10 @@
#include "third_party/blink/renderer/core/svg/svg_string_list.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/svg/svg_element.h"
#include "third_party/blink/renderer/core/svg/svg_parser_utilities.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -138,8 +137,9 @@ bool SVGStringList::CheckIndexBound(size_t index,
ExceptionState& exception_state) {
if (index >= values_.size()) {
exception_state.ThrowDOMException(
- kIndexSizeError, ExceptionMessages::IndexExceedsMaximumBound(
- "index", index, values_.size()));
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexExceedsMaximumBound("index", index,
+ values_.size()));
return false;
}
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_style_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_style_element.cc
index ec0c3cdbded..df0dd356ebc 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_style_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_style_element.cc
@@ -105,14 +105,14 @@ void SVGStyleElement::FinishParsingChildren() {
Node::InsertionNotificationRequest SVGStyleElement::InsertedInto(
ContainerNode* insertion_point) {
SVGElement::InsertedInto(insertion_point);
- return kInsertionShouldCallDidNotifySubtreeInsertions;
-}
-
-void SVGStyleElement::DidNotifySubtreeInsertionsToDocument() {
- if (StyleElement::ProcessStyleSheet(GetDocument(), *this) ==
- StyleElement::kProcessingFatalError)
- NotifyLoadedSheetAndAllCriticalSubresources(
- kErrorOccurredLoadingSubresource);
+ if (isConnected()) {
+ if (StyleElement::ProcessStyleSheet(GetDocument(), *this) ==
+ StyleElement::kProcessingFatalError) {
+ NotifyLoadedSheetAndAllCriticalSubresources(
+ kErrorOccurredLoadingSubresource);
+ }
+ }
+ return kInsertionDone;
}
void SVGStyleElement::RemovedFrom(ContainerNode* insertion_point) {
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_style_element.h b/chromium/third_party/blink/renderer/core/svg/svg_style_element.h
index c76d749016c..477c72042e2 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_style_element.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_style_element.h
@@ -58,7 +58,6 @@ class SVGStyleElement final : public SVGElement, public StyleElement {
void ParseAttribute(const AttributeModificationParams&) override;
InsertionNotificationRequest InsertedInto(ContainerNode*) override;
- void DidNotifySubtreeInsertionsToDocument() override;
void RemovedFrom(ContainerNode*) override;
void ChildrenChanged(const ChildrenChange&) 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 3644fdae905..3402a3c1831 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
@@ -151,8 +151,8 @@ void SVGSVGElement::UpdateUserTransform() {
bool SVGSVGElement::ZoomAndPanEnabled() const {
SVGZoomAndPanType zoom_and_pan = this->zoomAndPan();
- if (view_spec_)
- zoom_and_pan = view_spec_->zoomAndPan();
+ if (view_spec_ && view_spec_->ZoomAndPan() != kSVGZoomAndPanUnknown)
+ zoom_and_pan = view_spec_->ZoomAndPan();
return zoom_and_pan == kSVGZoomAndPanMagnify;
}
@@ -473,16 +473,6 @@ AffineTransform SVGSVGElement::LocalCoordinateSpaceTransform(
// #96361).
transform.Scale(1.0 / layout_object->StyleRef().EffectiveZoom());
- // Origin in the document. (This, together with the inverse-scale above,
- // performs the same operation as
- // Document::adjustFloatRectForScrollAndAbsoluteZoom, but in
- // transformation matrix form.)
- if (LocalFrameView* view = GetDocument().View()) {
- LayoutRect visible_content_rect(view->VisibleContentRect());
- transform.Translate(-visible_content_rect.X(),
- -visible_content_rect.Y());
- }
-
// Apply transforms from our ancestor coordinate space, including any
// non-SVG ancestor transforms.
transform.Multiply(layout_object->LocalToAbsoluteTransform());
@@ -600,7 +590,7 @@ bool SVGSVGElement::ShouldSynthesizeViewBox() const {
}
FloatRect SVGSVGElement::CurrentViewBoxRect() const {
- if (view_spec_)
+ if (view_spec_ && view_spec_->ViewBox())
return view_spec_->ViewBox()->Value();
FloatRect use_view_box = viewBox()->CurrentValue()->Value();
@@ -623,8 +613,9 @@ FloatRect SVGSVGElement::CurrentViewBoxRect() const {
return FloatRect(FloatPoint(), synthesized_view_box_size);
}
-SVGPreserveAspectRatio* SVGSVGElement::CurrentPreserveAspectRatio() const {
- if (view_spec_)
+const SVGPreserveAspectRatio* SVGSVGElement::CurrentPreserveAspectRatio()
+ const {
+ if (view_spec_ && view_spec_->PreserveAspectRatio())
return view_spec_->PreserveAspectRatio();
if (!HasValidViewBox() && ShouldSynthesizeViewBox()) {
@@ -687,10 +678,10 @@ AffineTransform SVGSVGElement::ViewBoxToViewTransform(float view_width,
AffineTransform ctm = SVGFitToViewBox::ViewBoxToViewTransform(
CurrentViewBoxRect(), CurrentPreserveAspectRatio(), view_width,
view_height);
- if (!view_spec_)
+ if (!view_spec_ || !view_spec_->Transform())
return ctm;
- SVGTransformList* transform_list = view_spec_->Transform();
+ const SVGTransformList* transform_list = view_spec_->Transform();
if (transform_list->IsEmpty())
return ctm;
@@ -701,7 +692,7 @@ AffineTransform SVGSVGElement::ViewBoxToViewTransform(float view_width,
return ctm;
}
-void SVGSVGElement::SetViewSpec(SVGViewSpec* view_spec) {
+void SVGSVGElement::SetViewSpec(const SVGViewSpec* view_spec) {
// Even if the viewspec object itself doesn't change, it could still
// have been mutated, so only treat a "no viewspec" -> "no viewspec"
// transition as a no-op.
@@ -715,41 +706,29 @@ void SVGSVGElement::SetViewSpec(SVGViewSpec* view_spec) {
void SVGSVGElement::SetupInitialView(const String& fragment_identifier,
Element* anchor_node) {
if (fragment_identifier.StartsWith("svgView(")) {
- SVGViewSpec* view_spec = SVGViewSpec::CreateForElement(*this);
- if (view_spec->ParseViewSpec(fragment_identifier)) {
+ SVGViewSpec* view_spec =
+ SVGViewSpec::CreateFromFragment(fragment_identifier);
+ if (view_spec) {
UseCounter::Count(GetDocument(),
WebFeature::kSVGSVGElementFragmentSVGView);
SetViewSpec(view_spec);
return;
}
}
-
- SetViewSpec(nullptr);
-
- if (!IsSVGViewElement(anchor_node))
+ if (IsSVGViewElement(anchor_node)) {
+ // Spec: If the SVG fragment identifier addresses a 'view' element within an
+ // SVG document (e.g., MyDrawing.svg#MyView) then the root 'svg' element is
+ // displayed in the SVG viewport. Any view specification attributes included
+ // on the given 'view' element override the corresponding view specification
+ // attributes on the root 'svg' element.
+ SVGViewSpec* view_spec =
+ SVGViewSpec::CreateForViewElement(ToSVGViewElement(*anchor_node));
+ UseCounter::Count(GetDocument(),
+ WebFeature::kSVGSVGElementFragmentSVGViewElement);
+ SetViewSpec(view_spec);
return;
-
- SVGViewElement& view_element = ToSVGViewElement(*anchor_node);
-
- // Spec: If the SVG fragment identifier addresses a 'view' element
- // within an SVG document (e.g., MyDrawing.svg#MyView) then the
- // closest ancestor 'svg' element is displayed in the
- // viewport. Any view specification attributes included on the
- // given 'view' element override the corresponding view
- // specification attributes on the closest ancestor 'svg' element.
- // TODO(ed): The spec text above is a bit unclear.
- // Should the transform from outermost svg to nested svg be applied to
- // "display" the inner svg in the viewport, then let the view element
- // override the inner svg's view specification attributes. Should it
- // fill/override the outer viewport?
- SVGSVGElement* svg = view_element.ownerSVGElement();
- if (!svg)
- return;
- SVGViewSpec* view_spec = SVGViewSpec::CreateForElement(*svg);
- view_spec->InheritViewAttributesFromElement(view_element);
- UseCounter::Count(svg->GetDocument(),
- WebFeature::kSVGSVGElementFragmentSVGViewElement);
- svg->SetViewSpec(view_spec);
+ }
+ SetViewSpec(nullptr);
}
void SVGSVGElement::FinishParsingChildren() {
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_svg_element.h b/chromium/third_party/blink/renderer/core/svg/svg_svg_element.h
index a91910f667f..f843f67f7c5 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_svg_element.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_svg_element.h
@@ -53,7 +53,7 @@ class SVGSVGElement final : public SVGGraphicsElement,
float IntrinsicHeight() const;
FloatSize CurrentViewportSize() const;
FloatRect CurrentViewBoxRect() const;
- SVGPreserveAspectRatio* CurrentPreserveAspectRatio() const;
+ const SVGPreserveAspectRatio* CurrentPreserveAspectRatio() const;
float currentScale() const;
void setCurrentScale(float scale);
@@ -111,14 +111,11 @@ class SVGSVGElement final : public SVGGraphicsElement,
void Trace(blink::Visitor*) override;
- SVGViewSpec* ViewSpec() const { return view_spec_; }
- void SetViewSpec(SVGViewSpec*);
-
private:
explicit SVGSVGElement(Document&);
~SVGSVGElement() override;
- SVGViewSpec& EnsureViewSpec();
+ void SetViewSpec(const SVGViewSpec*);
void ParseAttribute(const AttributeModificationParams&) override;
bool IsPresentationAttribute(const QualifiedName&) const override;
@@ -163,7 +160,7 @@ class SVGSVGElement final : public SVGGraphicsElement,
Member<SMILTimeContainer> time_container_;
Member<SVGPoint> translation_;
- Member<SVGViewSpec> view_spec_;
+ Member<const SVGViewSpec> view_spec_;
float current_scale_;
friend class SVGCurrentTranslateTearOff;
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_text_content_element.cc b/chromium/third_party/blink/renderer/core/svg/svg_text_content_element.cc
index b73e2237c32..42871653d94 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_text_content_element.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_text_content_element.cc
@@ -20,8 +20,6 @@
#include "third_party/blink/renderer/core/svg/svg_text_content_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/css_property_names.h"
#include "third_party/blink/renderer/core/css_value_keywords.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
@@ -33,6 +31,8 @@
#include "third_party/blink/renderer/core/svg/svg_rect_tear_off.h"
#include "third_party/blink/renderer/core/svg_names.h"
#include "third_party/blink/renderer/core/xml_names.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -113,8 +113,9 @@ float SVGTextContentElement::getSubStringLength(
unsigned number_of_chars = getNumberOfChars();
if (charnum >= number_of_chars) {
exception_state.ThrowDOMException(
- kIndexSizeError, ExceptionMessages::IndexExceedsMaximumBound(
- "charnum", charnum, getNumberOfChars()));
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexExceedsMaximumBound("charnum", charnum,
+ getNumberOfChars()));
return 0.0f;
}
@@ -131,8 +132,9 @@ SVGPointTearOff* SVGTextContentElement::getStartPositionOfChar(
if (charnum >= getNumberOfChars()) {
exception_state.ThrowDOMException(
- kIndexSizeError, ExceptionMessages::IndexExceedsMaximumBound(
- "charnum", charnum, getNumberOfChars()));
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexExceedsMaximumBound("charnum", charnum,
+ getNumberOfChars()));
return nullptr;
}
@@ -148,8 +150,9 @@ SVGPointTearOff* SVGTextContentElement::getEndPositionOfChar(
if (charnum >= getNumberOfChars()) {
exception_state.ThrowDOMException(
- kIndexSizeError, ExceptionMessages::IndexExceedsMaximumBound(
- "charnum", charnum, getNumberOfChars()));
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexExceedsMaximumBound("charnum", charnum,
+ getNumberOfChars()));
return nullptr;
}
@@ -165,8 +168,9 @@ SVGRectTearOff* SVGTextContentElement::getExtentOfChar(
if (charnum >= getNumberOfChars()) {
exception_state.ThrowDOMException(
- kIndexSizeError, ExceptionMessages::IndexExceedsMaximumBound(
- "charnum", charnum, getNumberOfChars()));
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexExceedsMaximumBound("charnum", charnum,
+ getNumberOfChars()));
return nullptr;
}
@@ -181,8 +185,9 @@ float SVGTextContentElement::getRotationOfChar(
if (charnum >= getNumberOfChars()) {
exception_state.ThrowDOMException(
- kIndexSizeError, ExceptionMessages::IndexExceedsMaximumBound(
- "charnum", charnum, getNumberOfChars()));
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexExceedsMaximumBound("charnum", charnum,
+ getNumberOfChars()));
return 0.0f;
}
@@ -203,8 +208,9 @@ void SVGTextContentElement::selectSubString(unsigned charnum,
unsigned number_of_chars = getNumberOfChars();
if (charnum >= number_of_chars) {
exception_state.ThrowDOMException(
- kIndexSizeError, ExceptionMessages::IndexExceedsMaximumBound(
- "charnum", charnum, getNumberOfChars()));
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexExceedsMaximumBound("charnum", charnum,
+ getNumberOfChars()));
return;
}
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_view_spec.cc b/chromium/third_party/blink/renderer/core/svg/svg_view_spec.cc
index 71032306f2f..3fff52025ff 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_view_spec.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_view_spec.cc
@@ -22,30 +22,37 @@
#include "third_party/blink/renderer/core/svg/svg_parser_utilities.h"
#include "third_party/blink/renderer/core/svg/svg_preserve_aspect_ratio.h"
#include "third_party/blink/renderer/core/svg/svg_rect.h"
-#include "third_party/blink/renderer/core/svg/svg_svg_element.h"
#include "third_party/blink/renderer/core/svg/svg_transform_list.h"
+#include "third_party/blink/renderer/core/svg/svg_view_element.h"
#include "third_party/blink/renderer/platform/wtf/text/parsing_utilities.h"
namespace blink {
-SVGViewSpec::SVGViewSpec()
- : view_box_(SVGRect::CreateInvalid()),
- preserve_aspect_ratio_(SVGPreserveAspectRatio::Create()),
- transform_(SVGTransformList::Create()) {}
+SVGViewSpec::SVGViewSpec() : zoom_and_pan_(kSVGZoomAndPanUnknown) {}
-void SVGViewSpec::Trace(blink::Visitor* visitor) {
+void SVGViewSpec::Trace(Visitor* visitor) {
visitor->Trace(view_box_);
visitor->Trace(preserve_aspect_ratio_);
visitor->Trace(transform_);
}
-SVGViewSpec* SVGViewSpec::CreateForElement(SVGSVGElement& root_element) {
- SVGViewSpec* view_spec = root_element.ViewSpec();
- if (!view_spec)
- view_spec = new SVGViewSpec();
- else
- view_spec->Reset();
- view_spec->InheritViewAttributesFromElement(root_element);
+SVGViewSpec* SVGViewSpec::CreateFromFragment(const String& fragment) {
+ SVGViewSpec* view_spec = new SVGViewSpec();
+ if (!view_spec->ParseViewSpec(fragment))
+ return nullptr;
+ return view_spec;
+}
+
+SVGViewSpec* SVGViewSpec::CreateForViewElement(const SVGViewElement& view) {
+ SVGViewSpec* view_spec = new SVGViewSpec();
+ if (view.HasValidViewBox())
+ view_spec->view_box_ = view.viewBox()->CurrentValue()->Clone();
+ if (view.preserveAspectRatio()->IsSpecified()) {
+ view_spec->preserve_aspect_ratio_ =
+ view.preserveAspectRatio()->CurrentValue()->Clone();
+ }
+ if (view.hasAttribute(SVGNames::zoomAndPanAttr))
+ view_spec->zoom_and_pan_ = view.zoomAndPan();
return view_spec;
}
@@ -62,22 +69,6 @@ bool SVGViewSpec::ParseViewSpec(const String& spec) {
return ParseViewSpecInternal(ptr, end);
}
-void SVGViewSpec::SetViewBox(const FloatRect& rect) {
- ViewBox()->SetValue(rect);
-}
-
-void SVGViewSpec::SetPreserveAspectRatio(const SVGPreserveAspectRatio& other) {
- PreserveAspectRatio()->SetAlign(other.Align());
- PreserveAspectRatio()->SetMeetOrSlice(other.MeetOrSlice());
-}
-
-void SVGViewSpec::Reset() {
- ResetZoomAndPan();
- transform_->Clear();
- SetViewBox(FloatRect());
- PreserveAspectRatio()->SetDefault();
-}
-
namespace {
enum ViewSpecFunctionType {
@@ -145,7 +136,7 @@ bool SVGViewSpec::ParseViewSpecInternal(const CharType* ptr,
ParseNumber(ptr, end, width) &&
ParseNumber(ptr, end, height, kDisallowWhitespace)))
return false;
- SetViewBox(FloatRect(x, y, width, height));
+ view_box_ = SVGRect::Create(FloatRect(x, y, width, height));
break;
}
case kViewTarget: {
@@ -154,14 +145,17 @@ bool SVGViewSpec::ParseViewSpecInternal(const CharType* ptr,
break;
}
case kZoomAndPan:
- if (!ParseZoomAndPan(ptr, end))
+ zoom_and_pan_ = SVGZoomAndPan::Parse(ptr, end);
+ if (zoom_and_pan_ == kSVGZoomAndPanUnknown)
return false;
break;
case kPreserveAspectRatio:
- if (!PreserveAspectRatio()->Parse(ptr, end, false))
+ preserve_aspect_ratio_ = SVGPreserveAspectRatio::Create();
+ if (!preserve_aspect_ratio_->Parse(ptr, end, false))
return false;
break;
case kTransform:
+ transform_ = SVGTransformList::Create();
transform_->Parse(ptr, end);
break;
default:
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_view_spec.h b/chromium/third_party/blink/renderer/core/svg/svg_view_spec.h
index 7c82fa4a0c7..ff9fa2a4b77 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_view_spec.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_view_spec.h
@@ -25,58 +25,38 @@
namespace blink {
-class FloatRect;
class SVGPreserveAspectRatio;
class SVGRect;
-class SVGSVGElement;
class SVGTransformList;
+class SVGViewElement;
-class SVGViewSpec final : public GarbageCollectedFinalized<SVGViewSpec>,
- public SVGZoomAndPan {
+class SVGViewSpec final : public GarbageCollectedFinalized<SVGViewSpec> {
public:
- static SVGViewSpec* CreateForElement(SVGSVGElement&);
+ static SVGViewSpec* CreateFromFragment(const String&);
+ static SVGViewSpec* CreateForViewElement(const SVGViewElement&);
- bool ParseViewSpec(const String&);
- void Reset();
- template <typename T>
- void InheritViewAttributesFromElement(T&);
-
- SVGRect* ViewBox() { return view_box_; }
- SVGPreserveAspectRatio* PreserveAspectRatio() {
+ const SVGRect* ViewBox() const { return view_box_; }
+ const SVGPreserveAspectRatio* PreserveAspectRatio() const {
return preserve_aspect_ratio_;
}
- SVGTransformList* Transform() { return transform_; }
+ const SVGTransformList* Transform() const { return transform_; }
+ SVGZoomAndPanType ZoomAndPan() const { return zoom_and_pan_; }
- virtual void Trace(blink::Visitor*);
+ void Trace(Visitor*);
private:
SVGViewSpec();
+ bool ParseViewSpec(const String&);
template <typename CharType>
bool ParseViewSpecInternal(const CharType* ptr, const CharType* end);
- void SetViewBox(const FloatRect&);
- void SetPreserveAspectRatio(const SVGPreserveAspectRatio&);
-
Member<SVGRect> view_box_;
Member<SVGPreserveAspectRatio> preserve_aspect_ratio_;
Member<SVGTransformList> transform_;
+ SVGZoomAndPanType zoom_and_pan_;
};
-template <typename T>
-void SVGViewSpec::InheritViewAttributesFromElement(T& inherit_from_element) {
- if (inherit_from_element.HasValidViewBox())
- SetViewBox(inherit_from_element.viewBox()->CurrentValue()->Value());
-
- if (inherit_from_element.preserveAspectRatio()->IsSpecified()) {
- SetPreserveAspectRatio(
- *inherit_from_element.preserveAspectRatio()->CurrentValue());
- }
-
- if (inherit_from_element.hasAttribute(SVGNames::zoomAndPanAttr))
- setZoomAndPan(inherit_from_element.zoomAndPan());
-}
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_SVG_SVG_VIEW_SPEC_H_
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_zoom_and_pan.cc b/chromium/third_party/blink/renderer/core/svg/svg_zoom_and_pan.cc
index 5837aadf7ee..5ae806fc7ea 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_zoom_and_pan.cc
+++ b/chromium/third_party/blink/renderer/core/svg/svg_zoom_and_pan.cc
@@ -27,35 +27,43 @@ namespace blink {
SVGZoomAndPan::SVGZoomAndPan() : zoom_and_pan_(kSVGZoomAndPanMagnify) {}
-void SVGZoomAndPan::ResetZoomAndPan() {
- zoom_and_pan_ = kSVGZoomAndPanMagnify;
-}
-
bool SVGZoomAndPan::IsKnownAttribute(const QualifiedName& attr_name) {
return attr_name == SVGNames::zoomAndPanAttr;
}
-template <typename CharType>
-static bool ParseZoomAndPanInternal(const CharType*& start,
- const CharType* end,
- SVGZoomAndPanType& zoom_and_pan) {
- if (SkipToken(start, end, "disable")) {
- zoom_and_pan = kSVGZoomAndPanDisable;
- return true;
- }
- if (SkipToken(start, end, "magnify")) {
- zoom_and_pan = kSVGZoomAndPanMagnify;
- return true;
+bool SVGZoomAndPan::ParseAttribute(const QualifiedName& name,
+ const AtomicString& value) {
+ if (name != SVGNames::zoomAndPanAttr)
+ return false;
+ zoom_and_pan_ = kSVGZoomAndPanUnknown;
+ if (!value.IsEmpty()) {
+ if (value.Is8Bit()) {
+ const LChar* start = value.Characters8();
+ zoom_and_pan_ = Parse(start, start + value.length());
+ } else {
+ const UChar* start = value.Characters16();
+ zoom_and_pan_ = Parse(start, start + value.length());
+ }
}
- return false;
+ return true;
+}
+
+template <typename CharType>
+static SVGZoomAndPanType ParseZoomAndPanInternal(const CharType*& start,
+ const CharType* end) {
+ if (SkipToken(start, end, "disable"))
+ return kSVGZoomAndPanDisable;
+ if (SkipToken(start, end, "magnify"))
+ return kSVGZoomAndPanMagnify;
+ return kSVGZoomAndPanUnknown;
}
-bool SVGZoomAndPan::ParseZoomAndPan(const LChar*& start, const LChar* end) {
- return ParseZoomAndPanInternal(start, end, zoom_and_pan_);
+SVGZoomAndPanType SVGZoomAndPan::Parse(const LChar*& start, const LChar* end) {
+ return ParseZoomAndPanInternal(start, end);
}
-bool SVGZoomAndPan::ParseZoomAndPan(const UChar*& start, const UChar* end) {
- return ParseZoomAndPanInternal(start, end, zoom_and_pan_);
+SVGZoomAndPanType SVGZoomAndPan::Parse(const UChar*& start, const UChar* end) {
+ return ParseZoomAndPanInternal(start, end);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/svg/svg_zoom_and_pan.h b/chromium/third_party/blink/renderer/core/svg/svg_zoom_and_pan.h
index 4276248bae1..c31fe7ed1fb 100644
--- a/chromium/third_party/blink/renderer/core/svg/svg_zoom_and_pan.h
+++ b/chromium/third_party/blink/renderer/core/svg/svg_zoom_and_pan.h
@@ -54,26 +54,10 @@ class SVGZoomAndPan {
return static_cast<SVGZoomAndPanType>(number);
}
- bool ParseZoomAndPan(const LChar*& start, const LChar* end);
- bool ParseZoomAndPan(const UChar*& start, const UChar* end);
-
- bool ParseAttribute(const QualifiedName& name, const AtomicString& value) {
- if (name == SVGNames::zoomAndPanAttr) {
- zoom_and_pan_ = kSVGZoomAndPanUnknown;
- if (!value.IsEmpty()) {
- if (value.Is8Bit()) {
- const LChar* start = value.Characters8();
- ParseZoomAndPan(start, start + value.length());
- } else {
- const UChar* start = value.Characters16();
- ParseZoomAndPan(start, start + value.length());
- }
- }
- return true;
- }
-
- return false;
- }
+ static SVGZoomAndPanType Parse(const LChar*& start, const LChar* end);
+ static SVGZoomAndPanType Parse(const UChar*& start, const UChar* end);
+
+ bool ParseAttribute(const QualifiedName& name, const AtomicString& value);
// JS API
SVGZoomAndPanType zoomAndPan() const { return zoom_and_pan_; }
@@ -86,7 +70,6 @@ class SVGZoomAndPan {
protected:
SVGZoomAndPan();
- void ResetZoomAndPan();
private:
SVGZoomAndPanType zoom_and_pan_;
diff --git a/chromium/third_party/blink/renderer/core/testing/DEPS b/chromium/third_party/blink/renderer/core/testing/DEPS
index 8109dc0a0d1..1cd6cecba86 100644
--- a/chromium/third_party/blink/renderer/core/testing/DEPS
+++ b/chromium/third_party/blink/renderer/core/testing/DEPS
@@ -1,3 +1,9 @@
include_rules = [
+ "+cc",
+ # TODO(crbug.com/838693): Test harnesses use LayerTreeView
+ # from content instead of a fake WebLayerTreeView implementation, so
+ # that the Web abstraction can go away.
+ "+content/renderer/gpu",
+ "+content/test",
"+gpu/command_buffer/client/gles2_interface.h",
]
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 a9261a3a029..b86cc174ffe 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
@@ -42,11 +42,12 @@ RenderingTest::RenderingTest(LocalFrameClient* local_frame_client)
: UseMockScrollbarSettings(), local_frame_client_(local_frame_client) {}
const Node* RenderingTest::HitTest(int x, int y) {
+ HitTestLocation location(LayoutPoint(x, y));
HitTestResult result(
HitTestRequest(HitTestRequest::kReadOnly | HitTestRequest::kActive |
HitTestRequest::kAllowChildFrameContent),
- IntPoint(x, y));
- GetLayoutView().HitTest(result);
+ location);
+ GetLayoutView().HitTest(location, result);
return result.InnerNode();
}
@@ -80,6 +81,14 @@ void RenderingTest::TearDown() {
void RenderingTest::SetChildFrameHTML(const String& html) {
ChildDocument().SetBaseURLOverride(KURL("http://test.com"));
ChildDocument().body()->SetInnerHTMLFromString(html, ASSERT_NO_EXCEPTION);
+
+ // Setting HTML implies the frame loads contents, so we need to advance the
+ // state machine to leave the initial empty document state.
+ auto* state_machine = ChildDocument().GetFrame()->Loader().StateMachine();
+ if (state_machine->IsDisplayingInitialEmptyDocument())
+ state_machine->AdvanceTo(FrameLoaderStateMachine::kCommittedFirstRealLoad);
+ // And let the frame view exit the initial throttled state.
+ ChildDocument().View()->BeginLifecycleUpdates();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/testing/core_unit_test_helper.h b/chromium/third_party/blink/renderer/core/testing/core_unit_test_helper.h
index b7359bd5af1..1708ced4b9b 100644
--- a/chromium/third_party/blink/renderer/core/testing/core_unit_test_helper.h
+++ b/chromium/third_party/blink/renderer/core/testing/core_unit_test_helper.h
@@ -16,7 +16,7 @@
#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/core/loader/empty_clients.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
-#include "third_party/blink/renderer/platform/testing/use_mock_scrollbar_settings.h"
+#include "third_party/blink/renderer/core/testing/use_mock_scrollbar_settings.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
namespace blink {
@@ -59,6 +59,7 @@ class LocalFrameClientWithParent final : public EmptyLocalFrameClient {
// FrameClient overrides:
void Detached(FrameDetachType) override;
LocalFrame* Parent() const override { return parent_.Get(); }
+ LocalFrame* Top() const override { return parent_.Get(); }
private:
explicit LocalFrameClientWithParent(LocalFrame* parent) : parent_(parent) {}
diff --git a/chromium/third_party/blink/renderer/core/testing/data/95-vh.html b/chromium/third_party/blink/renderer/core/testing/data/95-vh.html
new file mode 100644
index 00000000000..9026953f8ef
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/testing/data/95-vh.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<div style="background: linear-gradient(#e66465, #9198e5); height: 95vh; width: 10px;"></div>
diff --git a/chromium/third_party/blink/renderer/core/testing/data/frameserialization/beautifull.css b/chromium/third_party/blink/renderer/core/testing/data/frameserialization/beautifull.css
index 545eb347ee4..c8b49ccd15c 100644
--- a/chromium/third_party/blink/renderer/core/testing/data/frameserialization/beautifull.css
+++ b/chromium/third_party/blink/renderer/core/testing/data/frameserialization/beautifull.css
@@ -1 +1,4 @@
/* placeholder */
+.placeholder {
+ color: black;
+}
diff --git a/chromium/third_party/blink/renderer/core/testing/data/frameserialization/integrityfail.css b/chromium/third_party/blink/renderer/core/testing/data/frameserialization/integrityfail.css
new file mode 100644
index 00000000000..e8f24f94a36
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/testing/data/frameserialization/integrityfail.css
@@ -0,0 +1,3 @@
+body {
+ background-color: red;
+}
diff --git a/chromium/third_party/blink/renderer/core/testing/data/frameserialization/link_integrity.html b/chromium/third_party/blink/renderer/core/testing/data/frameserialization/link_integrity.html
new file mode 100644
index 00000000000..393cfbb3cf9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/testing/data/frameserialization/link_integrity.html
@@ -0,0 +1,10 @@
+<html>
+<meta charset="utf8">
+<head>
+<link rel="stylesheet" href="beautifull.css" integrity="sha256-Y7+RP0LZ3EKKy3OwZSuGNpG1C+PZ9fofRh+n9uuMeQ8=">
+<link rel="stylesheet" href="integrityfail.css" integrity="sha256-Y7+RP0LZ3EKKy3OwZSuGNpG1C+PZ9fofRh+n9uuMeQ8=">
+<body>
+beautifull.css should load because the integrity is provided correctly.
+integrityfail.css will not load.
+</body>
+</html>
diff --git a/chromium/third_party/blink/renderer/core/testing/data/link-manifest-change.html b/chromium/third_party/blink/renderer/core/testing/data/link-manifest-change.html
index fabec0c5453..0f214665f42 100644
--- a/chromium/third_party/blink/renderer/core/testing/data/link-manifest-change.html
+++ b/chromium/third_party/blink/renderer/core/testing/data/link-manifest-change.html
@@ -1,5 +1,5 @@
<!DOCTYPE html>
-<!-- This file is meant to test how many times the WebFrameClient will be
+<!-- This file is meant to test how many times the WebLocalFrameClient will be
notified of a change in the current manifest URL associated with the document. -->
<html>
<head>
diff --git a/chromium/third_party/blink/renderer/core/testing/data/origin-trial-dummy.html b/chromium/third_party/blink/renderer/core/testing/data/origin-trial-dummy.html
new file mode 100644
index 00000000000..3f09fe3a878
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/testing/data/origin-trial-dummy.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Origin Trial Test</title>
+<!-- TODO(iclelland): Generate this sample token during the build. The token
+ below will expire in 2033, but it would be better to always have a token which
+ is guaranteed to be valid when the tests are run.
+ Generate this token with the command:
+ generate_token.py https://example.test Frobulate -expire-timestamp=2000000000 -->
+<meta http-equiv="origin-trial" content="AlrgXVXDH5RSr6sDZiO6/8Hejv3BIhODCSS/0zD8VmDDLNPn463JzEq/Cv/wqt8cRHacGD3cUhKkibGIGQbaXAMAAABUeyJvcmlnaW4iOiAiaHR0cHM6Ly9leGFtcGxlLnRlc3Q6NDQzIiwgImZlYXR1cmUiOiAiRnJvYnVsYXRlIiwgImV4cGlyeSI6IDIwMDAwMDAwMDB9">
+</head>
+</html>
diff --git a/chromium/third_party/blink/renderer/core/testing/data/touch-action-blocking-handler.html b/chromium/third_party/blink/renderer/core/testing/data/touch-action-blocking-handler.html
index a7efd7d69e4..018e9421648 100644
--- a/chromium/third_party/blink/renderer/core/testing/data/touch-action-blocking-handler.html
+++ b/chromium/third_party/blink/renderer/core/testing/data/touch-action-blocking-handler.html
@@ -8,6 +8,8 @@
width: 200px;
height: 200px;
overflow: scroll;
+ }
+ #touchaction {
touch-action: pan-y;
}
.content {
@@ -23,8 +25,10 @@
<body>
<div id="scrollable">
- <div id="handler"></div>
- <div class="content"></div>
+ <div id="touchaction">
+ <div id="handler"></div>
+ <div class="content"></div>
+ </div>
</div>
<script>
// A blocking touch handler should prevent scrolling in that region.
diff --git a/chromium/third_party/blink/renderer/core/testing/data/touch-action-on-inline.html b/chromium/third_party/blink/renderer/core/testing/data/touch-action-on-inline.html
new file mode 100644
index 00000000000..b6a923fe9fb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/testing/data/touch-action-on-inline.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<style>
+ div { width: 10px; height: 50px; touch-action: none; font: 10px Ahem; }
+</style>
+<div>aaaaaaaa</div>
diff --git a/chromium/third_party/blink/renderer/core/testing/data/touch-action-with-vertical-rl-writing-mode.html b/chromium/third_party/blink/renderer/core/testing/data/touch-action-with-vertical-rl-writing-mode.html
new file mode 100644
index 00000000000..1721e27bfca
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/testing/data/touch-action-with-vertical-rl-writing-mode.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<style>
+ html { writing-mode: vertical-rl; }
+ div { width: 20px; height: 20px; touch-action: none; font: 10px Ahem; }
+</style>
+<div>aaaaaaaa</div>
diff --git a/chromium/third_party/blink/renderer/core/testing/death_aware_script_wrappable.h b/chromium/third_party/blink/renderer/core/testing/death_aware_script_wrappable.h
index 519529d8833..043efbd980f 100644
--- a/chromium/third_party/blink/renderer/core/testing/death_aware_script_wrappable.h
+++ b/chromium/third_party/blink/renderer/core/testing/death_aware_script_wrappable.h
@@ -9,10 +9,33 @@
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
+class DeathAwareScriptWrappable;
+
+namespace internal {
+
+class InObjectContainer {
+ DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
+
+ public:
+ explicit InObjectContainer(DeathAwareScriptWrappable* dependency)
+ : dependency_(dependency) {}
+
+ virtual ~InObjectContainer() {}
+
+ virtual void Trace(Visitor* visitor) { visitor->Trace(dependency_); }
+
+ private:
+ TraceWrapperMember<DeathAwareScriptWrappable> dependency_;
+};
+
+} // namespace internal
+
+// ScriptWrappable that can be used to
+// (a) build a graph of ScriptWrappables, and
+// (b) observe a single DeathAwareScriptWrappable for being garbage collected.
class DeathAwareScriptWrappable : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
static DeathAwareScriptWrappable* instance_;
@@ -21,12 +44,6 @@ class DeathAwareScriptWrappable : public ScriptWrappable {
public:
typedef TraceWrapperMember<DeathAwareScriptWrappable> Wrapper;
- ~DeathAwareScriptWrappable() override {
- if (this == instance_) {
- has_died_ = true;
- }
- }
-
static DeathAwareScriptWrappable* Create() {
return new DeathAwareScriptWrappable();
}
@@ -37,25 +54,20 @@ class DeathAwareScriptWrappable : public ScriptWrappable {
instance_ = instance;
}
+ ~DeathAwareScriptWrappable() override {
+ if (this == instance_) {
+ has_died_ = true;
+ }
+ }
+
void Trace(blink::Visitor* visitor) override {
visitor->Trace(wrapped_dependency_);
visitor->Trace(wrapped_vector_dependency_);
visitor->Trace(wrapped_hash_map_dependency_);
+ visitor->Trace(in_object_dependency_);
ScriptWrappable::Trace(visitor);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- visitor->TraceWrappers(wrapped_dependency_);
- for (auto dep : wrapped_vector_dependency_) {
- visitor->TraceWrappers(dep);
- }
- for (auto pair : wrapped_hash_map_dependency_) {
- visitor->TraceWrappers(pair.key);
- visitor->TraceWrappers(pair.value);
- }
- ScriptWrappable::TraceWrappers(visitor);
- }
-
void SetWrappedDependency(DeathAwareScriptWrappable* dependency) {
wrapped_dependency_ = dependency;
}
@@ -69,12 +81,17 @@ class DeathAwareScriptWrappable : public ScriptWrappable {
wrapped_hash_map_dependency_.insert(key, value);
}
+ void AddInObjectDependency(DeathAwareScriptWrappable* dependency) {
+ in_object_dependency_.push_back(internal::InObjectContainer(dependency));
+ }
+
private:
DeathAwareScriptWrappable() = default;
Wrapper wrapped_dependency_;
HeapVector<Wrapper> wrapped_vector_dependency_;
HeapHashMap<Wrapper, Wrapper> wrapped_hash_map_dependency_;
+ HeapVector<internal::InObjectContainer> in_object_dependency_;
};
} // namespace blink
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 f926075ef9d..0c3275090d6 100644
--- a/chromium/third_party/blink/renderer/core/testing/dictionary_test.cc
+++ b/chromium/third_party/blink/renderer/core/testing/dictionary_test.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/testing/internal_dictionary_derived.h"
#include "third_party/blink/renderer/core/testing/internal_dictionary_derived_derived.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
namespace {
@@ -140,8 +141,8 @@ void DictionaryTest::get(InternalDictionary& result) {
result.setEnumOrNullMember(enum_or_null_member_);
if (element_member_)
result.setElementMember(element_member_);
- if (element_or_null_member_)
- result.setElementOrNullMember(element_or_null_member_);
+ if (element_or_null_member_.has_value())
+ result.setElementOrNullMember(element_or_null_member_.value());
result.setObjectMember(object_member_);
result.setObjectOrNullMemberWithDefault(object_or_null_member_with_default_);
if (!double_or_string_member_.IsNull())
@@ -245,7 +246,7 @@ void DictionaryTest::Reset() {
enum_member_with_default_ = String();
enum_or_null_member_ = String();
element_member_ = nullptr;
- element_or_null_member_ = nullptr;
+ element_or_null_member_.reset();
object_member_ = ScriptValue();
object_or_null_member_with_default_ = ScriptValue();
double_or_string_member_ = DoubleOrString();
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 98da87dec77..34157aa4058 100644
--- a/chromium/third_party/blink/renderer/core/testing/dictionary_test.h
+++ b/chromium/third_party/blink/renderer/core/testing/dictionary_test.h
@@ -79,7 +79,7 @@ class DictionaryTest : public ScriptWrappable {
String enum_member_with_default_;
String enum_or_null_member_;
Member<Element> element_member_;
- Member<Element> element_or_null_member_;
+ base::Optional<Member<Element>> element_or_null_member_;
ScriptValue object_member_;
ScriptValue object_or_null_member_with_default_;
DoubleOrString double_or_string_member_;
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 46a969bc753..193a998c745 100644
--- a/chromium/third_party/blink/renderer/core/testing/dummy_modulator.cc
+++ b/chromium/third_party/blink/renderer/core/testing/dummy_modulator.cc
@@ -44,19 +44,13 @@ void DummyModulator::Trace(blink::Visitor* visitor) {
Modulator::Trace(visitor);
}
-ReferrerPolicy DummyModulator::GetReferrerPolicy() {
- NOTREACHED();
- return kReferrerPolicyDefault;
-}
-
-const SecurityOrigin* DummyModulator::GetSecurityOriginForFetch() {
+ScriptState* DummyModulator::GetScriptState() {
NOTREACHED();
return nullptr;
}
-ScriptState* DummyModulator::GetScriptState() {
- NOTREACHED();
- return nullptr;
+bool DummyModulator::IsScriptingDisabled() const {
+ return false;
}
ScriptModuleResolver* DummyModulator::GetScriptModuleResolver() {
@@ -69,20 +63,25 @@ base::SingleThreadTaskRunner* DummyModulator::TaskRunner() {
};
void DummyModulator::FetchTree(const KURL&,
+ FetchClientSettingsObjectSnapshot*,
WebURLRequest::RequestContext,
const ScriptFetchOptions&,
+ ModuleScriptCustomFetchType,
ModuleTreeClient*) {
NOTREACHED();
}
void DummyModulator::FetchSingle(const ModuleScriptFetchRequest&,
+ FetchClientSettingsObjectSnapshot*,
ModuleGraphLevel,
+ ModuleScriptCustomFetchType,
SingleModuleClient*) {
NOTREACHED();
}
void DummyModulator::FetchDescendantsForInlineScript(
ModuleScript*,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
WebURLRequest::RequestContext,
ModuleTreeClient*) {
NOTREACHED();
@@ -93,10 +92,11 @@ ModuleScript* DummyModulator::GetFetchedModuleScript(const KURL&) {
return nullptr;
}
-void DummyModulator::FetchNewSingleModule(const ModuleScriptFetchRequest&,
- ModuleGraphLevel,
- ModuleScriptLoaderClient*) {
+KURL DummyModulator::ResolveModuleSpecifier(const String&,
+ const KURL&,
+ String*) {
NOTREACHED();
+ return KURL();
}
bool DummyModulator::HasValidContext() {
@@ -116,17 +116,6 @@ ModuleImportMeta DummyModulator::HostGetImportMetaProperties(
return ModuleImportMeta(String());
}
-ScriptModule DummyModulator::CompileModule(const String& script,
- const KURL& source_url,
- const KURL& base_url,
- const ScriptFetchOptions&,
- AccessControlStatus,
- const TextPosition&,
- ExceptionState&) {
- NOTREACHED();
- return ScriptModule();
-}
-
ScriptValue DummyModulator::InstantiateModule(ScriptModule) {
NOTREACHED();
return ScriptValue();
@@ -144,7 +133,8 @@ ScriptValue DummyModulator::ExecuteModule(const ModuleScript*,
return ScriptValue();
}
-ModuleScriptFetcher* DummyModulator::CreateModuleScriptFetcher() {
+ModuleScriptFetcher* DummyModulator::CreateModuleScriptFetcher(
+ ModuleScriptCustomFetchType) {
NOTREACHED();
return nullptr;
}
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 0b26440fdf6..300f7cb2c35 100644
--- a/chromium/third_party/blink/renderer/core/testing/dummy_modulator.h
+++ b/chromium/third_party/blink/renderer/core/testing/dummy_modulator.h
@@ -12,9 +12,7 @@
namespace blink {
-class ModuleScriptLoaderClient;
class ScriptModuleResolver;
-class ModuleScriptFetchRequest;
// DummyModulator provides empty Modulator interface implementation w/
// NOTREACHED().
@@ -33,42 +31,40 @@ class DummyModulator : public Modulator {
ScriptModuleResolver* GetScriptModuleResolver() override;
base::SingleThreadTaskRunner* TaskRunner() override;
- ReferrerPolicy GetReferrerPolicy() override;
- const SecurityOrigin* GetSecurityOriginForFetch() override;
ScriptState* GetScriptState() override;
+ bool IsScriptingDisabled() const override;
- void FetchTree(const KURL&,
- WebURLRequest::RequestContext destination,
- const ScriptFetchOptions&,
- ModuleTreeClient*) override;
- void FetchSingle(const ModuleScriptFetchRequest&,
- ModuleGraphLevel,
- SingleModuleClient*) override;
+ void FetchTree(
+ const KURL&,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
+ WebURLRequest::RequestContext destination,
+ const ScriptFetchOptions&,
+ ModuleScriptCustomFetchType,
+ ModuleTreeClient*) override;
+ void FetchSingle(
+ const ModuleScriptFetchRequest&,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
+ ModuleGraphLevel,
+ ModuleScriptCustomFetchType,
+ SingleModuleClient*) override;
void FetchDescendantsForInlineScript(
ModuleScript*,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
WebURLRequest::RequestContext destination,
ModuleTreeClient*) override;
ModuleScript* GetFetchedModuleScript(const KURL&) override;
- void FetchNewSingleModule(const ModuleScriptFetchRequest&,
- ModuleGraphLevel,
- ModuleScriptLoaderClient*) override;
+ KURL ResolveModuleSpecifier(const String&, const KURL&, String*) override;
bool HasValidContext() override;
void ResolveDynamically(const String& specifier,
const KURL&,
const ReferrerScriptInfo&,
ScriptPromiseResolver*) override;
ModuleImportMeta HostGetImportMetaProperties(ScriptModule) const override;
- ScriptModule CompileModule(const String& script,
- const KURL& source_url,
- const KURL& base_url,
- const ScriptFetchOptions&,
- AccessControlStatus,
- const TextPosition&,
- ExceptionState&) override;
ScriptValue InstantiateModule(ScriptModule) override;
Vector<ModuleRequest> ModuleRequestsFromScriptModule(ScriptModule) override;
ScriptValue ExecuteModule(const ModuleScript*, CaptureEvalErrorFlag) override;
- ModuleScriptFetcher* CreateModuleScriptFetcher() override;
+ ModuleScriptFetcher* CreateModuleScriptFetcher(
+ ModuleScriptCustomFetchType) override;
Member<ScriptModuleResolver> resolver_;
};
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 01e9c2bea90..86938f58a2e 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
@@ -63,9 +63,6 @@ DummyPageHolder::DummyPageHolder(
else
page_clients.chrome_client = page_clients_argument->chrome_client;
page_ = Page::Create(page_clients);
- // TODO(loonybear): Don't insert dummy pages to OrdinaryPages once UseCounter
- // is moved to the browser side PageLoadMetricsObserver (crbug.com/845986).
- Page::OrdinaryPages().insert(page_);
Settings& settings = page_->GetSettings();
// FIXME: http://crbug.com/363843. This needs to find a better way to
// not create graphics layers.
diff --git a/chromium/third_party/blink/renderer/core/testing/internal_settings.cc b/chromium/third_party/blink/renderer/core/testing/internal_settings.cc
index 8e5d1526de4..73ab56660cb 100644
--- a/chromium/third_party/blink/renderer/core/testing/internal_settings.cc
+++ b/chromium/third_party/blink/renderer/core/testing/internal_settings.cc
@@ -26,10 +26,9 @@
#include "third_party/blink/renderer/core/testing/internal_settings.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/supplementable.h"
#include "third_party/blink/renderer/platform/text/locale_to_script_mapping.h"
@@ -41,11 +40,12 @@
return returnValue; \
}
-#define InternalSettingsGuardForSettings() \
- if (!GetSettings()) { \
- exception_state.ThrowDOMException( \
- kInvalidAccessError, "The settings object cannot be obtained."); \
- return; \
+#define InternalSettingsGuardForSettings() \
+ if (!GetSettings()) { \
+ exception_state.ThrowDOMException( \
+ DOMExceptionCode::kInvalidAccessError, \
+ "The settings object cannot be obtained."); \
+ return; \
}
#define InternalSettingsGuardForPage() \
@@ -188,7 +188,7 @@ void InternalSettings::setViewportStyle(const String& style,
GetSettings()->SetViewportStyle(WebViewportStyle::kTelevision);
else
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"The viewport style type provided ('" + style + "') is invalid.");
}
@@ -295,16 +295,19 @@ void InternalSettings::setTextTrackKindUserPreference(
String token = preference.StripWhiteSpace();
TextTrackKindUserPreference user_preference =
TextTrackKindUserPreference::kDefault;
- if (token == "default")
+ if (token == "default") {
user_preference = TextTrackKindUserPreference::kDefault;
- else if (token == "captions")
+ } else if (token == "captions") {
user_preference = TextTrackKindUserPreference::kCaptions;
- else if (token == "subtitles")
+ } else if (token == "subtitles") {
user_preference = TextTrackKindUserPreference::kSubtitles;
- else
+ } else {
exception_state.ThrowDOMException(
- kSyntaxError, "The user preference for text track kind " + preference +
- ")' is invalid.");
+ DOMExceptionCode::kSyntaxError,
+ "The user preference for text track kind " + preference +
+ ")' is invalid.");
+ return;
+ }
GetSettings()->SetTextTrackKindUserPreference(user_preference);
}
@@ -334,7 +337,7 @@ void InternalSettings::setEditingBehavior(const String& editing_behavior,
else if (DeprecatedEqualIgnoringCase(editing_behavior, "android"))
GetSettings()->SetEditingBehaviorType(kEditingAndroidBehavior);
else
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"The editing behavior type provided ('" +
editing_behavior + "') is invalid.");
}
@@ -375,15 +378,18 @@ void InternalSettings::setAvailablePointerTypes(
for (size_t i = 0; i < tokens.size(); ++i) {
String token = tokens[i].StripWhiteSpace();
- if (token == "coarse")
+ if (token == "coarse") {
pointer_types |= kPointerTypeCoarse;
- else if (token == "fine")
+ } else if (token == "fine") {
pointer_types |= kPointerTypeFine;
- else if (token == "none")
+ } else if (token == "none") {
pointer_types |= kPointerTypeNone;
- else
+ } else {
exception_state.ThrowDOMException(
- kSyntaxError, "The pointer type token ('" + token + ")' is invalid.");
+ DOMExceptionCode::kSyntaxError,
+ "The pointer type token ('" + token + ")' is invalid.");
+ return;
+ }
}
GetSettings()->SetAvailablePointerTypes(pointer_types);
@@ -395,17 +401,20 @@ void InternalSettings::setDisplayModeOverride(const String& display_mode,
String token = display_mode.StripWhiteSpace();
WebDisplayMode mode = kWebDisplayModeBrowser;
- if (token == "browser")
+ if (token == "browser") {
mode = kWebDisplayModeBrowser;
- else if (token == "minimal-ui")
+ } else if (token == "minimal-ui") {
mode = kWebDisplayModeMinimalUi;
- else if (token == "standalone")
+ } else if (token == "standalone") {
mode = kWebDisplayModeStandalone;
- else if (token == "fullscreen")
+ } else if (token == "fullscreen") {
mode = kWebDisplayModeFullscreen;
- else
+ } else {
exception_state.ThrowDOMException(
- kSyntaxError, "The display-mode token ('" + token + ")' is invalid.");
+ DOMExceptionCode::kSyntaxError,
+ "The display-mode token ('" + token + ")' is invalid.");
+ return;
+ }
GetSettings()->SetDisplayModeOverride(mode);
}
@@ -416,15 +425,18 @@ void InternalSettings::setPrimaryPointerType(const String& pointer,
String token = pointer.StripWhiteSpace();
PointerType type = kPointerTypeNone;
- if (token == "coarse")
+ if (token == "coarse") {
type = kPointerTypeCoarse;
- else if (token == "fine")
+ } else if (token == "fine") {
type = kPointerTypeFine;
- else if (token == "none")
+ } else if (token == "none") {
type = kPointerTypeNone;
- else
+ } else {
exception_state.ThrowDOMException(
- kSyntaxError, "The pointer type token ('" + token + ")' is invalid.");
+ DOMExceptionCode::kSyntaxError,
+ "The pointer type token ('" + token + ")' is invalid.");
+ return;
+ }
GetSettings()->SetPrimaryPointerType(type);
}
@@ -442,13 +454,16 @@ void InternalSettings::setAvailableHoverTypes(const String& types,
for (size_t i = 0; i < tokens.size(); ++i) {
String token = tokens[i].StripWhiteSpace();
- if (token == "none")
+ if (token == "none") {
hover_types |= kHoverTypeNone;
- else if (token == "hover")
+ } else if (token == "hover") {
hover_types |= kHoverTypeHover;
- else
+ } else {
exception_state.ThrowDOMException(
- kSyntaxError, "The hover type token ('" + token + ")' is invalid.");
+ DOMExceptionCode::kSyntaxError,
+ "The hover type token ('" + token + ")' is invalid.");
+ return;
+ }
}
GetSettings()->SetAvailableHoverTypes(hover_types);
@@ -460,13 +475,16 @@ void InternalSettings::setPrimaryHoverType(const String& type,
String token = type.StripWhiteSpace();
HoverType hover_type = kHoverTypeNone;
- if (token == "none")
+ if (token == "none") {
hover_type = kHoverTypeNone;
- else if (token == "hover")
+ } else if (token == "hover") {
hover_type = kHoverTypeHover;
- else
+ } else {
exception_state.ThrowDOMException(
- kSyntaxError, "The hover type token ('" + token + ")' is invalid.");
+ DOMExceptionCode::kSyntaxError,
+ "The hover type token ('" + token + ")' is invalid.");
+ return;
+ }
GetSettings()->SetPrimaryHoverType(hover_type);
}
@@ -475,16 +493,18 @@ void InternalSettings::setImageAnimationPolicy(
const String& policy,
ExceptionState& exception_state) {
InternalSettingsGuardForSettings();
- if (DeprecatedEqualIgnoringCase(policy, "allowed"))
+ if (DeprecatedEqualIgnoringCase(policy, "allowed")) {
GetSettings()->SetImageAnimationPolicy(kImageAnimationPolicyAllowed);
- else if (DeprecatedEqualIgnoringCase(policy, "once"))
+ } else if (DeprecatedEqualIgnoringCase(policy, "once")) {
GetSettings()->SetImageAnimationPolicy(kImageAnimationPolicyAnimateOnce);
- else if (DeprecatedEqualIgnoringCase(policy, "none"))
+ } else if (DeprecatedEqualIgnoringCase(policy, "none")) {
GetSettings()->SetImageAnimationPolicy(kImageAnimationPolicyNoAnimation);
- else
+ } else {
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"The image animation policy provided ('" + policy + "') is invalid.");
+ return;
+ }
}
void InternalSettings::setScrollTopLeftInteropEnabled(bool enabled) {
@@ -525,7 +545,8 @@ void InternalSettings::setAutoplayPolicy(const String& policy_str,
policy = AutoplayPolicy::Type::kDocumentUserActivationRequired;
} else {
exception_state.ThrowDOMException(
- kSyntaxError, "The autoplay policy ('" + policy_str + ")' is invalid.");
+ DOMExceptionCode::kSyntaxError,
+ "The autoplay policy ('" + policy_str + ")' is invalid.");
}
GetSettings()->SetAutoplayPolicy(policy);
diff --git a/chromium/third_party/blink/renderer/core/testing/internals.cc b/chromium/third_party/blink/renderer/core/testing/internals.cc
index a277e9754f3..37cab2836be 100644
--- a/chromium/third_party/blink/renderer/core/testing/internals.cc
+++ b/chromium/third_party/blink/renderer/core/testing/internals.cc
@@ -31,14 +31,13 @@
#include "base/macros.h"
#include "base/optional.h"
+#include "cc/layers/picture_layer.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/blink/public/platform/modules/remoteplayback/web_remote_playback_availability.h"
#include "third_party/blink/public/platform/modules/remoteplayback/web_remote_playback_client.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_connection_type.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
@@ -52,7 +51,6 @@
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/dom/dom_string_list.h"
#include "third_party/blink/renderer/core/dom/element.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
#include "third_party/blink/renderer/core/dom/iterator.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
@@ -62,7 +60,6 @@
#include "third_party/blink/renderer/core/dom/shadow_root_v0.h"
#include "third_party/blink/renderer/core/dom/static_node_list.h"
#include "third_party/blink/renderer/core/dom/tree_scope.h"
-#include "third_party/blink/renderer/core/dom/viewport_description.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/frame_selection.h"
@@ -121,9 +118,12 @@
#include "third_party/blink/renderer/core/page/scrolling/root_scroller_controller.h"
#include "third_party/blink/renderer/core/page/scrolling/scroll_state.h"
#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator_context.h"
+#include "third_party/blink/renderer/core/page/viewport_description.h"
#include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
+#include "third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.h"
#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/probe/core_probes.h"
#include "third_party/blink/renderer/core/style_property_shorthand.h"
#include "third_party/blink/renderer/core/svg/svg_image_element.h"
@@ -144,6 +144,8 @@
#include "third_party/blink/renderer/core/testing/union_types_test.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
#include "third_party/blink/renderer/platform/cursor.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
@@ -154,15 +156,16 @@
#include "third_party/blink/renderer/platform/instance_counters.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/language.h"
-#include "third_party/blink/renderer/platform/layout_locale.h"
#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_priority.h"
#include "third_party/blink/renderer/platform/network/network_state_notifier.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scroll/programmatic_scroll_animator.h"
+#include "third_party/blink/renderer/platform/scroll/scroll_animator_base.h"
#include "third_party/blink/renderer/platform/scroll/scrollbar_theme.h"
#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
+#include "third_party/blink/renderer/platform/text/layout_locale.h"
#include "third_party/blink/renderer/platform/weborigin/scheme_registry.h"
#include "third_party/blink/renderer/platform/wtf/dtoa.h"
#include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
@@ -242,7 +245,7 @@ static ScrollableArea* ScrollableAreaForNode(Node* node) {
if (node->IsDocumentNode()) {
// This can be removed after root layer scrolling is enabled.
if (LocalFrameView* frame_view = ToDocument(node)->View())
- return frame_view->LayoutViewportScrollableArea();
+ return frame_view->LayoutViewport();
}
LayoutObject* layout_object = node->GetLayoutObject();
@@ -268,8 +271,8 @@ void Internals::ResetToConsistentState(Page* page) {
page->SetDefaultPageScaleLimits(1, 4);
page->SetPageScaleFactor(1);
LocalFrame* frame = page->DeprecatedLocalMainFrame();
- frame->View()->LayoutViewportScrollableArea()->SetScrollOffset(
- ScrollOffset(), kProgrammaticScroll);
+ frame->View()->LayoutViewport()->SetScrollOffset(ScrollOffset(),
+ kProgrammaticScroll);
OverrideUserPreferredLanguagesForTesting(Vector<AtomicString>());
if (page->DeprecatedLocalMainFrame()->GetEditor().IsOverwriteModeEnabled())
page->DeprecatedLocalMainFrame()->GetEditor().ToggleOverwriteModeEnabled();
@@ -327,7 +330,7 @@ GCObservation* Internals::observeGC(ScriptValue script_value) {
unsigned Internals::updateStyleAndReturnAffectedElementCount(
ExceptionState& exception_state) const {
if (!document_) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"No context document is available.");
return 0;
}
@@ -340,7 +343,7 @@ unsigned Internals::updateStyleAndReturnAffectedElementCount(
unsigned Internals::needsLayoutCount(ExceptionState& exception_state) const {
LocalFrame* context_frame = GetFrame();
if (!context_frame) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"No context frame is available.");
return 0;
}
@@ -356,7 +359,7 @@ unsigned Internals::needsLayoutCount(ExceptionState& exception_state) const {
unsigned Internals::hitTestCount(Document* doc,
ExceptionState& exception_state) const {
if (!doc) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"Must supply document to check");
return 0;
}
@@ -367,7 +370,7 @@ unsigned Internals::hitTestCount(Document* doc,
unsigned Internals::hitTestCacheHits(Document* doc,
ExceptionState& exception_state) const {
if (!doc) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"Must supply document to check");
return 0;
}
@@ -382,7 +385,7 @@ Element* Internals::elementFromPoint(Document* doc,
bool allow_child_frame_content,
ExceptionState& exception_state) const {
if (!doc) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"Must supply document to check");
return nullptr;
}
@@ -405,7 +408,7 @@ Element* Internals::elementFromPoint(Document* doc,
void Internals::clearHitTestCache(Document* doc,
ExceptionState& exception_state) const {
if (!doc) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"Must supply document to check");
return;
}
@@ -421,7 +424,7 @@ Element* Internals::innerEditorElement(Element* container,
if (auto* control = ToTextControlOrNull(container))
return control->InnerEditorElement();
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"Not a text control element.");
return nullptr;
}
@@ -485,7 +488,7 @@ bool Internals::isValidContentSelect(Element* insertion_point,
ExceptionState& exception_state) {
DCHECK(insertion_point);
if (!insertion_point->IsV0InsertionPoint()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The element is not an insertion point.");
return false;
}
@@ -524,7 +527,7 @@ unsigned short Internals::compareTreeScopePosition(
: nullptr;
if (!tree_scope1 || !tree_scope2) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
String::Format(
"The %s node is neither a document node, nor a shadow root.",
tree_scope1 ? "second" : "first"));
@@ -537,8 +540,9 @@ void Internals::pauseAnimations(double pause_time,
ExceptionState& exception_state) {
if (pause_time < 0) {
exception_state.ThrowDOMException(
- kInvalidAccessError, ExceptionMessages::IndexExceedsMinimumBound(
- "pauseTime", pause_time, 0.0));
+ DOMExceptionCode::kInvalidAccessError,
+ ExceptionMessages::IndexExceedsMinimumBound("pauseTime", pause_time,
+ 0.0));
return;
}
@@ -572,12 +576,13 @@ void Internals::advanceImageAnimation(Element* image,
resource = svg_image->CachedImage();
} else {
exception_state.ThrowDOMException(
- kInvalidAccessError, "The element provided is not a image element.");
+ DOMExceptionCode::kInvalidAccessError,
+ "The element provided is not a image element.");
return;
}
if (!resource || !resource->HasImage()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The image resource is not available.");
return;
}
@@ -591,7 +596,8 @@ bool Internals::hasShadowInsertionPoint(const Node* root,
DCHECK(root);
if (!root->IsShadowRoot()) {
exception_state.ThrowDOMException(
- kInvalidAccessError, "The node argument is not a shadow root.");
+ DOMExceptionCode::kInvalidAccessError,
+ "The node argument is not a shadow root.");
return false;
}
return ToShadowRoot(root)->V0().ContainsShadowElements();
@@ -602,7 +608,8 @@ bool Internals::hasContentElement(const Node* root,
DCHECK(root);
if (!root->IsShadowRoot()) {
exception_state.ThrowDOMException(
- kInvalidAccessError, "The node argument is not a shadow root.");
+ DOMExceptionCode::kInvalidAccessError,
+ "The node argument is not a shadow root.");
return false;
}
return ToShadowRoot(root)->V0().ContainsContentElements();
@@ -613,7 +620,8 @@ size_t Internals::countElementShadow(const Node* root,
DCHECK(root);
if (!root->IsShadowRoot()) {
exception_state.ThrowDOMException(
- kInvalidAccessError, "The node argument is not a shadow root.");
+ DOMExceptionCode::kInvalidAccessError,
+ "The node argument is not a shadow root.");
return 0;
}
return ToShadowRoot(root)->ChildShadowRootCount();
@@ -624,7 +632,7 @@ Node* Internals::nextSiblingInFlatTree(Node* node,
DCHECK(node);
if (!node->CanParticipateInFlatTree()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"The node argument doesn't particite in the flat tree.");
return nullptr;
}
@@ -636,7 +644,7 @@ Node* Internals::firstChildInFlatTree(Node* node,
DCHECK(node);
if (!node->CanParticipateInFlatTree()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"The node argument doesn't particite in the flat tree");
return nullptr;
}
@@ -648,7 +656,7 @@ Node* Internals::lastChildInFlatTree(Node* node,
DCHECK(node);
if (!node->CanParticipateInFlatTree()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"The node argument doesn't particite in the flat tree.");
return nullptr;
}
@@ -659,7 +667,7 @@ Node* Internals::nextInFlatTree(Node* node, ExceptionState& exception_state) {
DCHECK(node);
if (!node->CanParticipateInFlatTree()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"The node argument doesn't particite in the flat tree.");
return nullptr;
}
@@ -671,7 +679,7 @@ Node* Internals::previousInFlatTree(Node* node,
DCHECK(node);
if (!node->CanParticipateInFlatTree()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"The node argument doesn't particite in the flat tree.");
return nullptr;
}
@@ -686,7 +694,7 @@ String Internals::elementLayoutTreeAsText(Element* element,
String representation = ExternalRepresentation(element);
if (representation.IsEmpty()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"The element provided has no external representation.");
return String();
}
@@ -734,7 +742,8 @@ String Internals::shadowRootType(const Node* root,
DCHECK(root);
if (!root->IsShadowRoot()) {
exception_state.ThrowDOMException(
- kInvalidAccessError, "The node provided is not a shadow root.");
+ DOMExceptionCode::kInvalidAccessError,
+ "The node provided is not a shadow root.");
return String();
}
@@ -808,7 +817,7 @@ Vector<String> Internals::formControlStateOfHistoryItem(
if (GetFrame())
main_item = GetFrame()->Loader().GetDocumentLoader()->GetHistoryItem();
if (!main_item) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"No history item is available.");
return Vector<String>();
}
@@ -822,7 +831,7 @@ void Internals::setFormControlStateOfHistoryItem(
if (GetFrame())
main_item = GetFrame()->Loader().GetDocumentLoader()->GetHistoryItem();
if (!main_item) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"No history item is available.");
return;
}
@@ -850,7 +859,8 @@ DOMRectReadOnly* Internals::absoluteCaretBounds(
ExceptionState& exception_state) {
if (!GetFrame()) {
exception_state.ThrowDOMException(
- kInvalidAccessError, "The document's frame cannot be retrieved.");
+ DOMExceptionCode::kInvalidAccessError,
+ "The document's frame cannot be retrieved.");
return nullptr;
}
@@ -888,7 +898,7 @@ void Internals::setMarker(Document* document,
const String& marker_type,
ExceptionState& exception_state) {
if (!document) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"No context document is available.");
return;
}
@@ -896,13 +906,13 @@ void Internals::setMarker(Document* document,
base::Optional<DocumentMarker::MarkerType> type = MarkerTypeFrom(marker_type);
if (!type) {
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"The marker type provided ('" + marker_type + "') is invalid.");
return;
}
if (type != DocumentMarker::kSpelling && type != DocumentMarker::kGrammar) {
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"internals.setMarker() currently only "
"supports spelling and grammar markers; "
"attempted to add marker of type '" +
@@ -925,7 +935,7 @@ unsigned Internals::markerCountForNode(Node* node,
MarkerTypesFrom(marker_type);
if (!marker_types) {
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"The marker type provided ('" + marker_type + "') is invalid.");
return 0;
}
@@ -962,7 +972,7 @@ DocumentMarker* Internals::MarkerAt(Node* node,
MarkerTypesFrom(marker_type);
if (!marker_types) {
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"The marker type provided ('" + marker_type + "') is invalid.");
return nullptr;
}
@@ -1038,7 +1048,7 @@ void Internals::addTextMatchMarker(const Range* range,
MatchStatusFrom(match_status);
if (!match_status_enum) {
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"The match status provided ('" + match_status + "') is invalid.");
return;
}
@@ -1049,7 +1059,7 @@ void Internals::addTextMatchMarker(const Range* range,
// This simulates what the production code does after
// DocumentMarkerController::addTextMatchMarker().
- range->OwnerDocument().View()->InvalidatePaintForTickmarks();
+ range->OwnerDocument().GetLayoutView()->InvalidatePaintForTickmarks();
}
static bool ParseColor(const String& value,
@@ -1057,7 +1067,8 @@ static bool ParseColor(const String& value,
ExceptionState& exception_state,
String error_message) {
if (!color.SetFromString(value)) {
- exception_state.ThrowDOMException(kInvalidAccessError, error_message);
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
+ error_message);
return false;
}
return true;
@@ -1092,7 +1103,7 @@ void addStyleableMarkerHelper(
ThicknessFrom(thickness_value);
if (!thickness) {
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"The thickness provided ('" + thickness_value + "') is invalid.");
return;
}
@@ -1198,25 +1209,6 @@ void Internals::setMarkedTextMatchesAreHighlighted(Document* document,
highlight);
}
-void Internals::setFrameViewPosition(Document* document,
- long x,
- long y,
- ExceptionState& exception_state) {
- DCHECK(document);
- if (!document->View()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
- "The document provided is invalid.");
- return;
- }
-
- LocalFrameView* frame_view = document->View();
- bool scrollbars_suppressed_old_value = frame_view->ScrollbarsSuppressed();
-
- frame_view->SetScrollbarsSuppressed(false);
- frame_view->UpdateScrollOffsetFromInternals(IntSize(x, y));
- frame_view->SetScrollbarsSuppressed(scrollbars_suppressed_old_value);
-}
-
String Internals::viewportAsText(Document* document,
float,
int available_width,
@@ -1224,7 +1216,7 @@ String Internals::viewportAsText(Document* document,
ExceptionState& exception_state) {
DCHECK(document);
if (!document->GetPage()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The document provided is invalid.");
return String();
}
@@ -1272,7 +1264,7 @@ bool Internals::elementShouldAutoComplete(Element* element,
if (auto* input = ToHTMLInputElementOrNull(*element))
return input->ShouldAutocomplete();
- exception_state.ThrowDOMException(kInvalidNodeTypeError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidNodeTypeError,
"The element provided is not an INPUT.");
return false;
}
@@ -1282,7 +1274,7 @@ String Internals::suggestedValue(Element* element,
DCHECK(element);
if (!element->IsFormControlElement()) {
exception_state.ThrowDOMException(
- kInvalidNodeTypeError,
+ DOMExceptionCode::kInvalidNodeTypeError,
"The element provided is not a form control element.");
return String();
}
@@ -1306,7 +1298,7 @@ void Internals::setSuggestedValue(Element* element,
DCHECK(element);
if (!element->IsFormControlElement()) {
exception_state.ThrowDOMException(
- kInvalidNodeTypeError,
+ DOMExceptionCode::kInvalidNodeTypeError,
"The element provided is not a form control element.");
return;
}
@@ -1327,7 +1319,7 @@ void Internals::setAutofilledValue(Element* element,
DCHECK(element);
if (!element->IsFormControlElement()) {
exception_state.ThrowDOMException(
- kInvalidNodeTypeError,
+ DOMExceptionCode::kInvalidNodeTypeError,
"The element provided is not a form control element.");
return;
}
@@ -1347,7 +1339,8 @@ void Internals::setAutofilledValue(Element* element,
if (auto* select = ToHTMLSelectElementOrNull(*element))
select->setValue(value, kDispatchInputAndChangeEvent);
- ToHTMLFormControlElement(element)->SetAutofilled(true);
+ ToHTMLFormControlElement(element)->SetAutofillState(
+ blink::WebAutofillState::kAutofilled);
}
void Internals::setEditingValue(Element* element,
@@ -1355,7 +1348,7 @@ void Internals::setEditingValue(Element* element,
ExceptionState& exception_state) {
DCHECK(element);
if (!IsHTMLInputElement(*element)) {
- exception_state.ThrowDOMException(kInvalidNodeTypeError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidNodeTypeError,
"The element provided is not an INPUT.");
return;
}
@@ -1369,11 +1362,17 @@ void Internals::setAutofilled(Element* element,
DCHECK(element);
if (!element->IsFormControlElement()) {
exception_state.ThrowDOMException(
- kInvalidNodeTypeError,
+ DOMExceptionCode::kInvalidNodeTypeError,
"The element provided is not a form control element.");
return;
}
- ToHTMLFormControlElement(element)->SetAutofilled(enabled);
+ if (enabled) {
+ ToHTMLFormControlElement(element)->SetAutofillState(
+ WebAutofillState::kAutofilled);
+ } else {
+ ToHTMLFormControlElement(element)->SetAutofillState(
+ WebAutofillState::kNotFilled);
+ }
}
Range* Internals::rangeFromLocationAndLength(Element* scope,
@@ -1418,6 +1417,24 @@ String Internals::rangeAsText(const Range* range) {
// FIXME: The next four functions are very similar - combine them once
// bestClickableNode/bestContextMenuNode have been combined..
+void Internals::HitTestRect(HitTestLocation& location,
+ HitTestResult& result,
+ long x,
+ long y,
+ long width,
+ long height,
+ Document* document) {
+ document->UpdateStyleAndLayout();
+ EventHandler& event_handler = document->GetFrame()->GetEventHandler();
+ LayoutPoint hit_test_point(
+ document->GetFrame()->View()->ConvertFromRootFrame(LayoutPoint(x, y)));
+ location = HitTestLocation(
+ (LayoutRect(hit_test_point, LayoutSize((int)width, (int)height))));
+ result = event_handler.HitTestResultAtLocation(
+ location, HitTestRequest::kReadOnly | HitTestRequest::kActive |
+ HitTestRequest::kListBased);
+}
+
DOMPoint* Internals::touchPositionAdjustedToBestClickableNode(
long x,
long y,
@@ -1427,31 +1444,20 @@ DOMPoint* Internals::touchPositionAdjustedToBestClickableNode(
ExceptionState& exception_state) {
DCHECK(document);
if (!document->GetFrame()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The document provided is invalid.");
return nullptr;
}
- document->UpdateStyleAndLayout();
-
- IntSize radius(width / 2, height / 2);
- IntPoint point(x + radius.Width(), y + radius.Height());
-
- EventHandler& event_handler = document->GetFrame()->GetEventHandler();
- IntPoint hit_test_point =
- document->GetFrame()->View()->RootFrameToContents(point);
- HitTestResult result = event_handler.HitTestResultAtPoint(
- hit_test_point,
- HitTestRequest::kReadOnly | HitTestRequest::kActive |
- HitTestRequest::kListBased,
- LayoutRectOutsets(radius.Height(), radius.Width(), radius.Height(),
- radius.Width()));
-
+ HitTestLocation location;
+ HitTestResult result;
+ HitTestRect(location, result, x, y, width, height, document);
Node* target_node = nullptr;
IntPoint adjusted_point;
+ EventHandler& event_handler = document->GetFrame()->GetEventHandler();
bool found_node = event_handler.BestClickableNodeForHitTestResult(
- result, adjusted_point, target_node);
+ location, result, adjusted_point, target_node);
if (found_node)
return DOMPoint::Create(adjusted_point.X(), adjusted_point.Y());
@@ -1467,30 +1473,18 @@ Node* Internals::touchNodeAdjustedToBestClickableNode(
ExceptionState& exception_state) {
DCHECK(document);
if (!document->GetFrame()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The document provided is invalid.");
return nullptr;
}
- document->UpdateStyleAndLayout();
-
- IntSize radius(width / 2, height / 2);
- IntPoint point(x + radius.Width(), y + radius.Height());
-
- EventHandler& event_handler = document->GetFrame()->GetEventHandler();
- IntPoint hit_test_point =
- document->GetFrame()->View()->RootFrameToContents(point);
- HitTestResult result = event_handler.HitTestResultAtPoint(
- hit_test_point,
- HitTestRequest::kReadOnly | HitTestRequest::kActive |
- HitTestRequest::kListBased,
- LayoutRectOutsets(radius.Height(), radius.Width(), radius.Height(),
- radius.Width()));
-
+ HitTestLocation location;
+ HitTestResult result;
+ HitTestRect(location, result, x, y, width, height, document);
Node* target_node = nullptr;
IntPoint adjusted_point;
document->GetFrame()->GetEventHandler().BestClickableNodeForHitTestResult(
- result, adjusted_point, target_node);
+ location, result, adjusted_point, target_node);
return target_node;
}
@@ -1503,31 +1497,20 @@ DOMPoint* Internals::touchPositionAdjustedToBestContextMenuNode(
ExceptionState& exception_state) {
DCHECK(document);
if (!document->GetFrame()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The document provided is invalid.");
return nullptr;
}
- document->UpdateStyleAndLayout();
-
- IntSize radius(width / 2, height / 2);
- IntPoint point(x + radius.Width(), y + radius.Height());
-
- EventHandler& event_handler = document->GetFrame()->GetEventHandler();
- IntPoint hit_test_point =
- document->GetFrame()->View()->RootFrameToContents(point);
- HitTestResult result = event_handler.HitTestResultAtPoint(
- hit_test_point,
- HitTestRequest::kReadOnly | HitTestRequest::kActive |
- HitTestRequest::kListBased,
- LayoutRectOutsets(radius.Height(), radius.Width(), radius.Height(),
- radius.Width()));
-
+ HitTestLocation location;
+ HitTestResult result;
+ HitTestRect(location, result, x, y, width, height, document);
Node* target_node = nullptr;
IntPoint adjusted_point;
+ EventHandler& event_handler = document->GetFrame()->GetEventHandler();
bool found_node = event_handler.BestContextMenuNodeForHitTestResult(
- result, adjusted_point, target_node);
+ location, result, adjusted_point, target_node);
if (found_node)
return DOMPoint::Create(adjusted_point.X(), adjusted_point.Y());
@@ -1543,30 +1526,18 @@ Node* Internals::touchNodeAdjustedToBestContextMenuNode(
ExceptionState& exception_state) {
DCHECK(document);
if (!document->GetFrame()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The document provided is invalid.");
return nullptr;
}
- document->UpdateStyleAndLayout();
-
- IntSize radius(width / 2, height / 2);
- IntPoint point(x + radius.Width(), y + radius.Height());
-
- EventHandler& event_handler = document->GetFrame()->GetEventHandler();
- IntPoint hit_test_point =
- document->GetFrame()->View()->RootFrameToContents(point);
- HitTestResult result = event_handler.HitTestResultAtPoint(
- hit_test_point,
- HitTestRequest::kReadOnly | HitTestRequest::kActive |
- HitTestRequest::kListBased,
- LayoutRectOutsets(radius.Height(), radius.Width(), radius.Height(),
- radius.Width()));
-
+ HitTestLocation location;
+ HitTestResult result;
+ HitTestRect(location, result, x, y, width, height, document);
Node* target_node = nullptr;
IntPoint adjusted_point;
- event_handler.BestContextMenuNodeForHitTestResult(result, adjusted_point,
- target_node);
+ document->GetFrame()->GetEventHandler().BestContextMenuNodeForHitTestResult(
+ location, result, adjusted_point, target_node);
return target_node;
}
@@ -1576,7 +1547,7 @@ int Internals::lastSpellCheckRequestSequence(Document* document,
if (!requester) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"No spell check requestor can be obtained for the provided document.");
return -1;
}
@@ -1591,7 +1562,7 @@ int Internals::lastSpellCheckProcessedSequence(
if (!requester) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"No spell check requestor can be obtained for the provided document.");
return -1;
}
@@ -1606,7 +1577,7 @@ void Internals::cancelCurrentSpellCheckRequest(
if (!requester) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"No spell check requestor can be obtained for the provided document.");
return;
}
@@ -1624,7 +1595,7 @@ String Internals::idleTimeSpellCheckerState(Document* document,
if (!document || !document->GetFrame()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"No frame can be obtained from the provided document.");
return String();
}
@@ -1643,7 +1614,7 @@ void Internals::runIdleTimeSpellChecker(Document* document,
ExceptionState& exception_state) {
if (!document || !document->GetFrame()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"No frame can be obtained from the provided document.");
return;
}
@@ -1927,7 +1898,7 @@ LayerRectList* Internals::touchEventTargetLayerRects(
ExceptionState& exception_state) {
DCHECK(document);
if (!document->View() || !document->GetPage() || document != document_) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The document provided is invalid.");
return nullptr;
}
@@ -1936,7 +1907,7 @@ LayerRectList* Internals::touchEventTargetLayerRects(
document->GetPage()->GetScrollingCoordinator()) {
FrameView* view = document->GetPage()->MainFrame()->View();
if (view->IsLocalFrameView()) {
- scrolling_coordinator->UpdateAfterCompositingChangeIfNeeded(
+ scrolling_coordinator->UpdateAfterPaint(
static_cast<LocalFrameView*>(view));
} else {
NOTREACHED();
@@ -1965,7 +1936,7 @@ bool Internals::executeCommand(Document* document,
ExceptionState& exception_state) {
DCHECK(document);
if (!document->GetFrame()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The document provided is invalid.");
return false;
}
@@ -2002,57 +1973,40 @@ Vector<AtomicString> Internals::svgTags() {
StaticNodeList* Internals::nodesFromRect(
Document* document,
- int center_x,
- int center_y,
- unsigned top_padding,
- unsigned right_padding,
- unsigned bottom_padding,
- unsigned left_padding,
+ int x,
+ int y,
+ int width,
+ int height,
bool ignore_clipping,
bool allow_child_frame_content,
ExceptionState& exception_state) const {
DCHECK(document);
if (!document->GetFrame() || !document->GetFrame()->View()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"No view can be obtained from the provided document.");
return nullptr;
}
- LocalFrame* frame = document->GetFrame();
- LocalFrameView* frame_view = document->View();
- auto* layout_view = document->GetLayoutView();
-
- if (!layout_view)
- return nullptr;
-
- float zoom_factor = frame->PageZoomFactor();
- LayoutPoint point =
- LayoutPoint(FloatPoint(center_x * zoom_factor + frame_view->ScrollX(),
- center_y * zoom_factor + frame_view->ScrollY()));
-
HitTestRequest::HitTestRequestType hit_type = HitTestRequest::kReadOnly |
HitTestRequest::kActive |
HitTestRequest::kListBased;
- if (ignore_clipping)
+ LocalFrame* frame = document->GetFrame();
+ LayoutRect rect(x, y, width, height);
+ if (ignore_clipping) {
hit_type |= HitTestRequest::kIgnoreClipping;
+ } else if (!IntRect(IntPoint(), frame->View()->Size())
+ .Intersects(EnclosingIntRect(rect))) {
+ return nullptr;
+ }
if (allow_child_frame_content)
hit_type |= HitTestRequest::kAllowChildFrameContent;
- HitTestRequest request(hit_type);
-
- // When ignoreClipping is false, this method returns null for coordinates
- // outside of the viewport.
- LayoutRectOutsets padding(top_padding, right_padding, bottom_padding,
- left_padding);
- LayoutRect rect = HitTestLocation::RectForPoint(point, padding);
- if (!request.IgnoreClipping() &&
- !frame_view->VisibleContentRect().Intersects(EnclosingIntRect(rect)))
- return nullptr;
-
HeapVector<Member<Node>> matches;
- HitTestResult result(request, point, padding);
- layout_view->HitTest(result);
+ HitTestRequest request(hit_type);
+ HitTestLocation location(rect);
+ HitTestResult result(request, location);
+ frame->ContentLayoutObject()->HitTest(location, result);
CopyToVector(result.ListBasedTestResult(), matches);
return StaticNodeList::Adopt(matches);
@@ -2064,7 +2018,7 @@ bool Internals::hasSpellingMarker(Document* document,
ExceptionState& exception_state) {
if (!document || !document->GetFrame()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"No frame can be obtained from the provided document.");
return false;
}
@@ -2079,7 +2033,7 @@ void Internals::replaceMisspelled(Document* document,
ExceptionState& exception_state) {
if (!document || !document->GetFrame()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"No frame can be obtained from the provided document.");
return;
}
@@ -2128,7 +2082,7 @@ bool Internals::hasGrammarMarker(Document* document,
ExceptionState& exception_state) {
if (!document || !document->GetFrame()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"No frame can be obtained from the provided document.");
return false;
}
@@ -2188,7 +2142,7 @@ bool Internals::scrollsWithRespectTo(Element* element1,
LayoutObject* layout_object2 = element2->GetLayoutObject();
if (!layout_object1 || !layout_object1->IsBox()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
layout_object1
? "The first provided element's layoutObject is not a box."
: "The first provided element has no layoutObject.");
@@ -2196,7 +2150,7 @@ bool Internals::scrollsWithRespectTo(Element* element1,
}
if (!layout_object2 || !layout_object2->IsBox()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
layout_object2
? "The second provided element's layoutObject is not a box."
: "The second provided element has no layoutObject.");
@@ -2207,7 +2161,7 @@ bool Internals::scrollsWithRespectTo(Element* element1,
PaintLayer* layer2 = ToLayoutBox(layout_object2)->Layer();
if (!layer1 || !layer2) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
String::Format(
"No PaintLayer can be obtained from the %s provided element.",
layer1 ? "second" : "first"));
@@ -2222,7 +2176,7 @@ String Internals::layerTreeAsText(Document* document,
ExceptionState& exception_state) const {
DCHECK(document);
if (!document->GetFrame()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The document provided is invalid.");
return String();
}
@@ -2242,7 +2196,7 @@ String Internals::elementLayerTreeAsText(
LayoutObject* layout_object = element->GetLayoutObject();
if (!layout_object || !layout_object->IsBox()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
layout_object ? "The provided element's layoutObject is not a box."
: "The provided element has no layoutObject.");
return String();
@@ -2255,9 +2209,8 @@ String Internals::elementLayerTreeAsText(
return String();
}
- return layer->GetCompositedLayerMapping()
- ->MainGraphicsLayer()
- ->GetLayerTreeAsTextForTesting(flags);
+ return GraphicsLayerTreeAsTextForTesting(
+ layer->GetCompositedLayerMapping()->MainGraphicsLayer(), flags);
}
String Internals::scrollingStateTreeAsText(Document*) const {
@@ -2269,7 +2222,7 @@ String Internals::mainThreadScrollingReasons(
ExceptionState& exception_state) const {
DCHECK(document);
if (!document->GetFrame()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The document provided is invalid.");
return String();
}
@@ -2294,7 +2247,7 @@ DOMRectList* Internals::nonFastScrollableRects(
ExceptionState& exception_state) const {
DCHECK(document);
if (!document->GetFrame()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The document provided is invalid.");
return nullptr;
}
@@ -2303,7 +2256,7 @@ DOMRectList* Internals::nonFastScrollableRects(
if (!page)
return nullptr;
- return page->NonFastScrollableRects(document->GetFrame());
+ return page->NonFastScrollableRectsForTesting(document->GetFrame());
}
void Internals::evictAllResources() const {
@@ -2325,8 +2278,8 @@ int Internals::pageNumber(Element* element,
return 0;
if (page_width <= 0 || page_height <= 0) {
- exception_state.ThrowDOMException(
- kV8TypeError, "Page width and height must be larger than 0.");
+ exception_state.ThrowTypeError(
+ "Page width and height must be larger than 0.");
return 0;
}
@@ -2360,8 +2313,8 @@ int Internals::numberOfPages(float page_width,
return -1;
if (page_width <= 0 || page_height <= 0) {
- exception_state.ThrowDOMException(
- kV8TypeError, "Page width and height must be larger than 0.");
+ exception_state.ThrowTypeError(
+ "Page width and height must be larger than 0.");
return -1;
}
@@ -2373,7 +2326,7 @@ String Internals::pageProperty(String property_name,
int page_number,
ExceptionState& exception_state) const {
if (!GetFrame()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"No frame is available.");
return String();
}
@@ -2392,7 +2345,7 @@ String Internals::pageSizeAndMarginsInPixels(
int margin_left,
ExceptionState& exception_state) const {
if (!GetFrame()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"No frame is available.");
return String();
}
@@ -2405,7 +2358,8 @@ String Internals::pageSizeAndMarginsInPixels(
float Internals::pageScaleFactor(ExceptionState& exception_state) {
if (!document_->GetPage()) {
exception_state.ThrowDOMException(
- kInvalidAccessError, "The document's page cannot be retrieved.");
+ DOMExceptionCode::kInvalidAccessError,
+ "The document's page cannot be retrieved.");
return 0;
}
Page* page = document_->GetPage();
@@ -2418,7 +2372,8 @@ void Internals::setPageScaleFactor(float scale_factor,
return;
if (!document_->GetPage()) {
exception_state.ThrowDOMException(
- kInvalidAccessError, "The document's page cannot be retrieved.");
+ DOMExceptionCode::kInvalidAccessError,
+ "The document's page cannot be retrieved.");
return;
}
Page* page = document_->GetPage();
@@ -2430,7 +2385,8 @@ void Internals::setPageScaleFactorLimits(float min_scale_factor,
ExceptionState& exception_state) {
if (!document_->GetPage()) {
exception_state.ThrowDOMException(
- kInvalidAccessError, "The document's page cannot be retrieved.");
+ DOMExceptionCode::kInvalidAccessError,
+ "The document's page cannot be retrieved.");
return;
}
@@ -2451,7 +2407,7 @@ void Internals::setIsCursorVisible(Document* document,
ExceptionState& exception_state) {
DCHECK(document);
if (!document->GetPage()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"No context document can be obtained.");
return;
}
@@ -2589,7 +2545,7 @@ void Internals::startTrackingRepaints(Document* document,
ExceptionState& exception_state) {
DCHECK(document);
if (!document->View()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The document provided is invalid.");
return;
}
@@ -2603,7 +2559,7 @@ void Internals::stopTrackingRepaints(Document* document,
ExceptionState& exception_state) {
DCHECK(document);
if (!document->View()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The document provided is invalid.");
return;
}
@@ -2638,7 +2594,7 @@ void Internals::forceFullRepaint(Document* document,
ExceptionState& exception_state) {
DCHECK(document);
if (!document->View()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The document provided is invalid.");
return;
}
@@ -2663,7 +2619,7 @@ DOMRectList* Internals::AnnotatedRegions(Document* document,
ExceptionState& exception_state) {
DCHECK(document);
if (!document->View()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The document provided is invalid.");
return DOMRectList::Create();
}
@@ -2863,9 +2819,9 @@ void Internals::forceReload(bool bypass_cache) {
if (!GetFrame())
return;
- GetFrame()->Reload(
- bypass_cache ? kFrameLoadTypeReloadBypassingCache : kFrameLoadTypeReload,
- ClientRedirectPolicy::kNotClientRedirect);
+ GetFrame()->Reload(bypass_cache ? WebFrameLoadType::kReloadBypassingCache
+ : WebFrameLoadType::kReload,
+ ClientRedirectPolicy::kNotClientRedirect);
}
StaticSelection* Internals::getSelectionInFlatTree(
@@ -2873,7 +2829,7 @@ StaticSelection* Internals::getSelectionInFlatTree(
ExceptionState& exception_state) {
Frame* const frame = window->GetFrame();
if (!frame || !frame->IsLocalFrame()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"Must supply local window");
return nullptr;
}
@@ -2924,7 +2880,8 @@ unsigned Internals::visibleSelectionFocusOffset() {
DOMRect* Internals::selectionBounds(ExceptionState& exception_state) {
if (!GetFrame()) {
exception_state.ThrowDOMException(
- kInvalidAccessError, "The document's frame cannot be retrieved.");
+ DOMExceptionCode::kInvalidAccessError,
+ "The document's frame cannot be retrieved.");
return nullptr;
}
@@ -2946,7 +2903,8 @@ void Internals::forceImageReload(Element* element,
ExceptionState& exception_state) {
if (!element || !IsHTMLImageElement(*element)) {
exception_state.ThrowDOMException(
- kInvalidAccessError, "The element should be HTMLImageElement.");
+ DOMExceptionCode::kInvalidAccessError,
+ "The element should be HTMLImageElement.");
}
ToHTMLImageElement(*element).ForceReload();
@@ -3025,7 +2983,7 @@ void Internals::forceCompositingUpdate(Document* document,
ExceptionState& exception_state) {
DCHECK(document);
if (!document->GetLayoutView()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The document provided is invalid.");
return;
}
@@ -3045,7 +3003,7 @@ void Internals::setShouldRevealPassword(Element* element,
ExceptionState& exception_state) {
DCHECK(element);
if (!IsHTMLInputElement(element)) {
- exception_state.ThrowDOMException(kInvalidNodeTypeError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidNodeTypeError,
"The element provided is not an INPUT.");
return;
}
@@ -3109,7 +3067,7 @@ ScriptPromise Internals::promiseCheck(ScriptState* script_state,
if (arg2)
return ScriptPromise::Cast(script_state,
V8String(script_state->GetIsolate(), "done"));
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Thrown from the native implementation.");
return ScriptPromise();
}
@@ -3211,7 +3169,7 @@ void Internals::setNetworkConnectionInfoOverride(
webtype = kWebConnectionTypeUnknown;
} else {
exception_state.ThrowDOMException(
- kNotFoundError,
+ DOMExceptionCode::kNotFoundError,
ExceptionMessages::FailedToEnumerate("connection type", type));
return;
}
@@ -3229,8 +3187,9 @@ void Internals::setNetworkConnectionInfoOverride(
web_effective_type = WebEffectiveConnectionType::kType4G;
} else if (effective_type != "unknown") {
exception_state.ThrowDOMException(
- kNotFoundError, ExceptionMessages::FailedToEnumerate(
- "effective connection type", effective_type));
+ DOMExceptionCode::kNotFoundError,
+ ExceptionMessages::FailedToEnumerate("effective connection type",
+ effective_type));
return;
}
GetNetworkStateNotifier().SetNetworkConnectionInfoOverride(
@@ -3270,7 +3229,7 @@ void Internals::setScrollChain(ScrollState* scroll_state,
}
void Internals::forceBlinkGCWithoutV8GC() {
- ThreadState::Current()->SetGCState(ThreadState::kFullGCScheduled);
+ ThreadState::Current()->ScheduleFullGC();
}
String Internals::selectedHTMLForClipboard() {
@@ -3300,38 +3259,6 @@ void Internals::setVisualViewportOffset(int x, int y) {
GetFrame()->GetPage()->GetVisualViewport().SetLocation(FloatPoint(x, y));
}
-int Internals::visualViewportHeight() {
- if (!GetFrame())
- return 0;
-
- return ExpandedIntSize(
- GetFrame()->GetPage()->GetVisualViewport().VisibleRect().Size())
- .Height();
-}
-
-int Internals::visualViewportWidth() {
- if (!GetFrame())
- return 0;
-
- return ExpandedIntSize(
- GetFrame()->GetPage()->GetVisualViewport().VisibleRect().Size())
- .Width();
-}
-
-float Internals::visualViewportScrollX() {
- if (!GetFrame())
- return 0;
-
- return GetFrame()->View()->GetScrollableArea()->GetScrollOffset().Width();
-}
-
-float Internals::visualViewportScrollY() {
- if (!GetFrame())
- return 0;
-
- return GetFrame()->View()->GetScrollableArea()->GetScrollOffset().Height();
-}
-
bool Internals::isUseCounted(Document* document, uint32_t feature) {
if (feature >= static_cast<int32_t>(WebFeature::kNumberOfFeatures))
return false;
@@ -3348,6 +3275,12 @@ bool Internals::isAnimatedCSSPropertyUseCounted(Document* document,
return UseCounter::IsCountedAnimatedCSS(*document, property_name);
}
+void Internals::clearUseCounter(Document* document, uint32_t feature) {
+ if (feature >= static_cast<int32_t>(WebFeature::kNumberOfFeatures))
+ return;
+ UseCounter::ClearCountForTesting(*document, static_cast<WebFeature>(feature));
+}
+
Vector<String> Internals::getCSSPropertyLonghands() const {
Vector<String> result;
for (int id = firstCSSProperty; id <= lastCSSProperty; ++id) {
@@ -3398,13 +3331,13 @@ ScriptPromise Internals::observeUseCounter(ScriptState* script_state,
return promise;
}
- Page* page = document->GetPage();
- if (!page) {
+ DocumentLoader* loader = document->Loader();
+ if (!loader) {
resolver->Reject();
return promise;
}
- page->GetUseCounter().AddObserver(new UseCounterObserverImpl(
+ loader->GetUseCounter().AddObserver(new UseCounterObserverImpl(
resolver, static_cast<WebFeature>(use_counter_feature)));
return promise;
}
@@ -3452,8 +3385,10 @@ bool Internals::setScrollbarVisibilityInScrollableArea(Node* node,
double Internals::monotonicTimeToZeroBasedDocumentTime(
double platform_time,
ExceptionState& exception_state) {
- return document_->Loader()->GetTiming().MonotonicTimeToZeroBasedDocumentTime(
- TimeTicksFromSeconds(platform_time));
+ return document_->Loader()
+ ->GetTiming()
+ .MonotonicTimeToZeroBasedDocumentTime(TimeTicksFromSeconds(platform_time))
+ .InSecondsF();
}
String Internals::getScrollAnimationState(Node* node) const {
@@ -3510,7 +3445,7 @@ void Internals::BypassLongCompileThresholdOnce(
PerformanceMonitor* performance_monitor = frame->GetPerformanceMonitor();
if (!performance_monitor) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"PerformanceObserver should be observing 'longtask' while "
"calling BypassLongCompileThresholdOnce.");
return;
diff --git a/chromium/third_party/blink/renderer/core/testing/internals.h b/chromium/third_party/blink/renderer/core/testing/internals.h
index 2b234520aa1..0a744c0afba 100644
--- a/chromium/third_party/blink/renderer/core/testing/internals.h
+++ b/chromium/third_party/blink/renderer/core/testing/internals.h
@@ -27,11 +27,11 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_INTERNALS_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_INTERNALS_H_
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/css/css_computed_style_declaration.h"
#include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.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/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -57,6 +57,8 @@ class Element;
class ExceptionState;
class ExecutionContext;
class GCObservation;
+class HitTestLocation;
+class HitTestResult;
class HTMLInputElement;
class HTMLMediaElement;
class HTMLSelectElement;
@@ -219,7 +221,6 @@ class Internals final : public ScriptWrappable {
bool);
void setMarkedTextMatchesAreHighlighted(Document*, bool);
- void setFrameViewPosition(Document*, long x, long y, ExceptionState&);
String viewportAsText(Document*,
float device_pixel_ratio,
int available_width,
@@ -300,10 +301,8 @@ class Internals final : public ScriptWrappable {
StaticNodeList* nodesFromRect(Document*,
int x,
int y,
- unsigned top_padding,
- unsigned right_padding,
- unsigned bottom_padding,
- unsigned left_padding,
+ int width,
+ int height,
bool ignore_clipping,
bool allow_child_frame_content,
ExceptionState&) const;
@@ -521,17 +520,13 @@ class Internals final : public ScriptWrappable {
String selectedTextForClipboard();
void setVisualViewportOffset(int x, int y);
- int visualViewportHeight();
- int visualViewportWidth();
- // The scroll position of the visual viewport relative to the document origin.
- float visualViewportScrollX();
- float visualViewportScrollY();
// Return true if the given use counter exists for the given document.
// |feature| must be one of the values from the WebFeature enum.
bool isUseCounted(Document*, uint32_t feature);
bool isCSSPropertyUseCounted(Document*, const String&);
bool isAnimatedCSSPropertyUseCounted(Document*, const String&);
+ void clearUseCounter(Document*, uint32_t feature);
Vector<String> getCSSPropertyLonghands() const;
Vector<String> getCSSPropertyShorthands() const;
@@ -599,6 +594,13 @@ class Internals final : public ScriptWrappable {
LocalFrame* GetFrame() const;
Vector<String> IconURLs(Document*, int icon_types_mask) const;
DOMRectList* AnnotatedRegions(Document*, bool draggable, ExceptionState&);
+ void HitTestRect(HitTestLocation&,
+ HitTestResult&,
+ long x,
+ long y,
+ long width,
+ long height,
+ Document*);
DocumentMarker* MarkerAt(Node*,
const String& marker_type,
diff --git a/chromium/third_party/blink/renderer/core/testing/internals.idl b/chromium/third_party/blink/renderer/core/testing/internals.idl
index e30ae7dfb9f..aaec0fa87a1 100644
--- a/chromium/third_party/blink/renderer/core/testing/internals.idl
+++ b/chromium/third_party/blink/renderer/core/testing/internals.idl
@@ -120,8 +120,6 @@ enum EffectiveConnectionType {
void setTextMatchMarkersActive(Node node, unsigned long startOffset, unsigned long endOffset, boolean active);
void setMarkedTextMatchesAreHighlighted(Document document, boolean highlight);
- [RaisesException] void setFrameViewPosition(Document document, long x, long y);
-
[RaisesException] DOMString viewportAsText(Document document,
float devicePixelRatio,
long availableWidth,
@@ -171,8 +169,8 @@ enum EffectiveConnectionType {
sequence<DOMString> svgTags();
[RaisesException] NodeList nodesFromRect(Document document, long x, long y,
- unsigned long topPadding, unsigned long rightPadding, unsigned long bottomPadding, unsigned long leftPadding,
- boolean ignoreClipping, boolean allowChildFrameContent);
+ unsigned long width, unsigned long height, boolean ignoreClipping,
+ boolean allowChildFrameContent);
[RaisesException] boolean hasSpellingMarker(Document document, long from, long length);
[RaisesException] boolean hasGrammarMarker(Document document, long from, long length);
@@ -349,16 +347,13 @@ enum EffectiveConnectionType {
DOMString selectedTextForClipboard();
void setVisualViewportOffset(long x, long y);
- long visualViewportHeight();
- long visualViewportWidth();
- double visualViewportScrollX();
- double visualViewportScrollY();
boolean magnifyScaleAroundAnchor(float offset, float x, float y);
boolean isUseCounted(Document document, unsigned long feature);
boolean isCSSPropertyUseCounted(Document document, DOMString propertyName);
boolean isAnimatedCSSPropertyUseCounted(Document document, DOMString propertyName);
+ void clearUseCounter(Document document, unsigned long feature);
sequence<DOMString> getCSSPropertyLonghands();
sequence<DOMString> getCSSPropertyShorthands();
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 2a61cc4ba72..e9584b586b7 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
@@ -11,23 +11,8 @@
namespace blink {
-namespace {
-
-class NullEventQueue final : public EventQueue {
- public:
- NullEventQueue() = default;
- ~NullEventQueue() override = default;
- bool EnqueueEvent(const base::Location&, Event*) override { return true; }
- bool CancelEvent(Event*) override { return true; }
- void Close() override {}
-};
-
-} // namespace
-
NullExecutionContext::NullExecutionContext()
- : tasks_need_pause_(false),
- is_secure_context_(true),
- queue_(new NullEventQueue()) {}
+ : tasks_need_pause_(false), is_secure_context_(true) {}
void NullExecutionContext::SetIsSecureContext(bool is_secure_context) {
is_secure_context_ = is_secure_context;
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 55acdcd13da..d642abe7c61 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
@@ -8,7 +8,6 @@
#include <memory>
#include "base/single_thread_task_runner.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
-#include "third_party/blink/renderer/core/dom/events/event_queue.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/execution_context/security_context.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
@@ -36,7 +35,6 @@ class NullExecutionContext
String UserAgent() const override { return String(); }
EventTarget* ErrorEventTarget() override { return nullptr; }
- EventQueue* GetEventQueue() const override { return queue_.Get(); }
bool TasksNeedPause() override { return tasks_need_pause_; }
void SetTasksNeedPause(bool flag) { tasks_need_pause_ = flag; }
@@ -62,7 +60,6 @@ class NullExecutionContext
using SecurityContext::GetContentSecurityPolicy;
void Trace(blink::Visitor* visitor) override {
- visitor->Trace(queue_);
SecurityContext::Trace(visitor);
ExecutionContext::Trace(visitor);
}
@@ -70,7 +67,6 @@ class NullExecutionContext
private:
bool tasks_need_pause_;
bool is_secure_context_;
- Member<EventQueue> queue_;
KURL url_;
};
diff --git a/chromium/third_party/blink/renderer/core/testing/origin_trials_test.cc b/chromium/third_party/blink/renderer/core/testing/origin_trials_test.cc
index 7297f47b4b9..856d93947e5 100644
--- a/chromium/third_party/blink/renderer/core/testing/origin_trials_test.cc
+++ b/chromium/third_party/blink/renderer/core/testing/origin_trials_test.cc
@@ -4,20 +4,19 @@
#include "third_party/blink/renderer/core/testing/origin_trials_test.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
bool OriginTrialsTest::throwingAttribute(ScriptState* script_state,
ExceptionState& exception_state) {
String error_message;
- if (!OriginTrials::originTrialsSampleAPIEnabled(
+ if (!OriginTrials::OriginTrialsSampleAPIEnabled(
ExecutionContext::From(script_state))) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"The Origin Trials Sample API has not been enabled in this context");
return false;
}
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 2d3da9f76ed..b48519564bd 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
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/testing/sim/sim_compositor.h"
+#include "cc/test/fake_layer_tree_frame_sink.h"
#include "third_party/blink/public/platform/web_rect.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -20,12 +21,17 @@
namespace blink {
-SimCompositor::SimCompositor()
- : needs_begin_frame_(false),
- defer_commits_(true),
- has_selection_(false),
- web_view_(nullptr) {
+SimCompositor::SimCompositor() {
LocalFrameView::SetInitialTracksPaintInvalidationsForTesting(true);
+
+ // SimCompositor overrides the LayerTreeViewDelegate to respond to
+ // BeginMainFrame(), which will update and paint the WebViewImpl given to
+ // SetWebView().
+ layer_tree_view_ = layer_tree_view_factory_.Initialize(this);
+ // SimCompositor starts with defer commits enabled, but uses synchronous
+ // compositing which does not use defer commits anyhow, it only uses it for
+ // reading defered state in tests.
+ layer_tree_view_->SetDeferCommits(true);
}
SimCompositor::~SimCompositor() {
@@ -36,35 +42,22 @@ void SimCompositor::SetWebView(WebViewImpl& web_view) {
web_view_ = &web_view;
}
-void SimCompositor::SetNeedsBeginFrame() {
- needs_begin_frame_ = true;
-}
-
-void SimCompositor::SetDeferCommits(bool defer_commits) {
- defer_commits_ = defer_commits;
-}
-
-void SimCompositor::RegisterSelection(const WebSelection&) {
- has_selection_ = true;
-}
-
-void SimCompositor::ClearSelection() {
- has_selection_ = false;
-}
-
SimCanvas::Commands SimCompositor::BeginFrame(double time_delta_in_seconds) {
DCHECK(web_view_);
- DCHECK(!defer_commits_);
- DCHECK(needs_begin_frame_);
+ DCHECK(!layer_tree_view_->layer_tree_host()->defer_commits());
+ DCHECK(layer_tree_view_->layer_tree_host()->RequestedMainFramePending());
DCHECK_GT(time_delta_in_seconds, 0);
- needs_begin_frame_ = false;
last_frame_time_ += base::TimeDelta::FromSecondsD(time_delta_in_seconds);
- web_view_->BeginFrame(last_frame_time_);
- web_view_->UpdateAllLifecyclePhases();
+ SimCanvas::Commands commands;
+ paint_commands_ = &commands;
+
+ layer_tree_view_->layer_tree_host()->Composite(last_frame_time_,
+ /*raster=*/false);
- return PaintFrame();
+ paint_commands_ = nullptr;
+ return commands;
}
SimCanvas::Commands SimCompositor::PaintFrame() {
@@ -83,4 +76,19 @@ SimCanvas::Commands SimCompositor::PaintFrame() {
return canvas.GetCommands();
}
+void SimCompositor::RequestNewLayerTreeFrameSink(
+ LayerTreeFrameSinkCallback callback) {
+ // Make a valid LayerTreeFrameSink so the compositor will generate begin main
+ // frames.
+ std::move(callback).Run(cc::FakeLayerTreeFrameSink::Create3d());
+}
+
+void SimCompositor::BeginMainFrame(base::TimeTicks frame_time) {
+ // There is no WebWidget like RenderWidget would have..? So go right to the
+ // WebViewImpl.
+ web_view_->BeginFrame(last_frame_time_);
+ web_view_->UpdateAllLifecyclePhases();
+ *paint_commands_ = PaintFrame();
+}
+
} // namespace blink
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 41a560cd2ab..1a5a93a64a4 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
@@ -6,7 +6,10 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_SIM_SIM_COMPOSITOR_H_
#include "base/time/time.h"
-#include "third_party/blink/public/platform/web_layer_tree_view.h"
+#include "cc/trees/layer_tree_host.h"
+#include "content/renderer/gpu/layer_tree_view.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"
namespace blink {
@@ -22,11 +25,18 @@ class WebViewImpl;
// only part of the layer was invalid.
//
// Note: This also does not support compositor driven animations.
-class SimCompositor final : public WebLayerTreeView {
+class SimCompositor final : public content::StubLayerTreeViewDelegate {
public:
explicit SimCompositor();
~SimCompositor() override;
+ // This compositor should be given to the WebViewImpl passed to SetWebView.
+ content::LayerTreeView& layer_tree_view() { return *layer_tree_view_; }
+
+ // When the compositor asks for a main frame, this WebViewImpl will have its
+ // lifecycle updated and be painted. The compositor() should have also been
+ // given to the WebViewImpl so that its using the same compositor() for its
+ // layer tree.
void SetWebView(WebViewImpl&);
// Executes the BeginMainFrame processing steps, an approximation of what
@@ -42,29 +52,44 @@ class SimCompositor final : public WebLayerTreeView {
// we don't schedule a BeginFrame).
SimCanvas::Commands PaintFrame();
- bool NeedsBeginFrame() const { return needs_begin_frame_; }
- bool DeferCommits() const { return defer_commits_; }
-
- bool HasSelection() const { return has_selection_; }
-
- void SetBackgroundColor(SkColor background_color) override {
- background_color_ = background_color;
+ // Helpers to query the state of the compositor from tests.
+ //
+ // Returns true if a main frame has been requested from blink, until the
+ // BeginFrame() step occurs.
+ bool NeedsBeginFrame() const {
+ return layer_tree_view_->layer_tree_host()->RequestedMainFramePending();
+ }
+ // Returns true if commits are deferred in the compositor. Since these tests
+ // use synchronous compositing through BeginFrame(), the deferred state has no
+ // real effect.
+ bool DeferCommits() const {
+ return layer_tree_view_->layer_tree_host()->defer_commits();
+ }
+ // Returns true if a selection is set on the compositor.
+ bool HasSelection() const {
+ return layer_tree_view_->layer_tree_host()->selection() !=
+ cc::LayerSelection();
+ }
+ // Returns the background color set on the compositor.
+ SkColor background_color() {
+ return layer_tree_view_->layer_tree_host()->background_color();
}
-
- SkColor background_color() { return background_color_; }
private:
- void SetNeedsBeginFrame() override;
- void SetDeferCommits(bool) override;
- void RegisterSelection(const WebSelection&) override;
- void ClearSelection() override;
-
- bool needs_begin_frame_;
- bool defer_commits_;
- bool has_selection_;
- WebViewImpl* web_view_;
+ // content::LayerTreeViewDelegate implementation.
+ void RequestNewLayerTreeFrameSink(
+ LayerTreeFrameSinkCallback callback) override;
+ void BeginMainFrame(base::TimeTicks frame_time) override;
+
+ WebViewImpl* web_view_ = nullptr;
base::TimeTicks last_frame_time_;
- SkColor background_color_;
+
+ // During BeginFrame(), painting is done, and the result is stored here to
+ // be returned from BeginFrame().
+ SimCanvas::Commands* paint_commands_;
+
+ content::LayerTreeView* layer_tree_view_ = nullptr;
+ FrameTestHelpers::LayerTreeViewFactory layer_tree_view_factory_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/testing/sim/sim_request.cc b/chromium/third_party/blink/renderer/core/testing/sim/sim_request.cc
index 1ae9d249b41..e6ff8a79153 100644
--- a/chromium/third_party/blink/renderer/core/testing/sim/sim_request.cc
+++ b/chromium/third_party/blink/renderer/core/testing/sim/sim_request.cc
@@ -92,6 +92,8 @@ void SimRequest::Complete(const Vector<char>& data) {
void SimRequest::Reset() {
is_ready_ = false;
client_ = nullptr;
+ Platform::Current()->GetURLLoaderMockFactory()->UnregisterURL(KURL(url_));
+
SimNetwork::Current().RemoveRequest(*this);
}
diff --git a/chromium/third_party/blink/renderer/core/testing/sim/sim_test.cc b/chromium/third_party/blink/renderer/core/testing/sim/sim_test.cc
index c80387d53cd..b816ca7ff90 100644
--- a/chromium/third_party/blink/renderer/core/testing/sim/sim_test.cc
+++ b/chromium/third_party/blink/renderer/core/testing/sim/sim_test.cc
@@ -4,7 +4,9 @@
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
+#include "content/test/test_blink_web_unit_test_support.h"
#include "third_party/blink/public/platform/web_cache.h"
+#include "third_party/blink/public/web/web_navigation_timings.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/exported/web_view_impl.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
@@ -15,7 +17,9 @@
namespace blink {
-SimTest::SimTest() : web_view_client_(compositor_), web_frame_client_(*this) {
+SimTest::SimTest()
+ : web_view_client_(compositor_.layer_tree_view()),
+ web_frame_client_(*this) {
Document::SetThreadedParsingEnabledForTesting(false);
// Use the mock theme to get more predictable code paths, this also avoids
// the OS callbacks in ScrollAnimatorMac which can schedule frames
@@ -25,6 +29,13 @@ SimTest::SimTest() : web_view_client_(compositor_), web_frame_client_(*this) {
// in the middle of a test.
LayoutTestSupport::SetMockThemeEnabledForTest(true);
ScrollbarTheme::SetMockScrollbarsEnabled(true);
+ // Threaded animations are usually enabled for blink. However these tests use
+ // synchronous compositing, which can not run threaded animations.
+ bool was_threaded_animation_enabled =
+ content::TestBlinkWebUnitTestSupport::SetThreadedAnimationEnabled(false);
+ // If this fails, we'd be resetting IsThreadedAnimationEnabled() to the wrong
+ // thing in the destructor.
+ DCHECK(was_threaded_animation_enabled);
}
SimTest::~SimTest() {
@@ -34,6 +45,7 @@ SimTest::~SimTest() {
Document::SetThreadedParsingEnabledForTesting(true);
LayoutTestSupport::SetMockThemeEnabledForTest(false);
ScrollbarTheme::SetMockScrollbarsEnabled(false);
+ content::TestBlinkWebUnitTestSupport::SetThreadedAnimationEnabled(true);
WebCache::Clear();
}
@@ -47,7 +59,9 @@ void SimTest::SetUp() {
void SimTest::LoadURL(const String& url) {
WebURLRequest request{KURL(url)};
- WebView().MainFrameImpl()->LoadRequest(request);
+ WebView().MainFrameImpl()->CommitNavigation(
+ request, WebFrameLoadType::kStandard, WebHistoryItem(), false,
+ base::UnguessableToken::Create(), nullptr, WebNavigationTimings());
}
LocalDOMWindow& SimTest::Window() {
@@ -78,6 +92,12 @@ SimCompositor& SimTest::Compositor() {
return compositor_;
}
+void SimTest::SetEffectiveConnectionTypeForTesting(
+ WebEffectiveConnectionType effective_connection_type) {
+ web_frame_client_.SetEffectiveConnectionTypeForTesting(
+ effective_connection_type);
+}
+
void SimTest::AddConsoleMessage(const String& message) {
console_messages_.push_back(message);
}
diff --git a/chromium/third_party/blink/renderer/core/testing/sim/sim_test.h b/chromium/third_party/blink/renderer/core/testing/sim/sim_test.h
index 125a4a9318c..ed38facd7ee 100644
--- a/chromium/third_party/blink/renderer/core/testing/sim/sim_test.h
+++ b/chromium/third_party/blink/renderer/core/testing/sim/sim_test.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_SIM_SIM_TEST_H_
#include <gtest/gtest.h>
+#include "third_party/blink/public/platform/web_effective_connection_type.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
#include "third_party/blink/renderer/core/testing/sim/sim_compositor.h"
#include "third_party/blink/renderer/core/testing/sim/sim_network.h"
@@ -42,6 +43,8 @@ class SimTest : public testing::Test {
Vector<String>& ConsoleMessages() { return console_messages_; }
+ void SetEffectiveConnectionTypeForTesting(WebEffectiveConnectionType);
+
private:
friend class SimWebFrameClient;
diff --git a/chromium/third_party/blink/renderer/core/testing/sim/sim_web_frame_client.cc b/chromium/third_party/blink/renderer/core/testing/sim/sim_web_frame_client.cc
index 987844c7bc3..9ede2eb44a9 100644
--- a/chromium/third_party/blink/renderer/core/testing/sim/sim_web_frame_client.cc
+++ b/chromium/third_party/blink/renderer/core/testing/sim/sim_web_frame_client.cc
@@ -9,7 +9,9 @@
namespace blink {
-SimWebFrameClient::SimWebFrameClient(SimTest& test) : test_(&test) {}
+SimWebFrameClient::SimWebFrameClient(SimTest& test)
+ : test_(&test),
+ effective_connection_type_(WebEffectiveConnectionType::kTypeUnknown) {}
void SimWebFrameClient::DidAddMessageToConsole(const WebConsoleMessage& message,
const WebString& source_name,
@@ -18,4 +20,13 @@ void SimWebFrameClient::DidAddMessageToConsole(const WebConsoleMessage& message,
test_->AddConsoleMessage(message.text);
}
+WebEffectiveConnectionType SimWebFrameClient::GetEffectiveConnectionType() {
+ return effective_connection_type_;
+}
+
+void SimWebFrameClient::SetEffectiveConnectionTypeForTesting(
+ WebEffectiveConnectionType effective_connection_type) {
+ effective_connection_type_ = effective_connection_type;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/testing/sim/sim_web_frame_client.h b/chromium/third_party/blink/renderer/core/testing/sim/sim_web_frame_client.h
index 5eba2c0c8b2..bc29eb3cbdb 100644
--- a/chromium/third_party/blink/renderer/core/testing/sim/sim_web_frame_client.h
+++ b/chromium/third_party/blink/renderer/core/testing/sim/sim_web_frame_client.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_SIM_SIM_WEB_FRAME_CLIENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_SIM_SIM_WEB_FRAME_CLIENT_H_
+#include "third_party/blink/public/platform/web_effective_connection_type.h"
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
namespace blink {
@@ -15,14 +16,19 @@ class SimWebFrameClient final : public FrameTestHelpers::TestWebFrameClient {
public:
explicit SimWebFrameClient(SimTest&);
- // WebFrameClient overrides:
+ // WebLocalFrameClient overrides:
void DidAddMessageToConsole(const WebConsoleMessage&,
const WebString& source_name,
unsigned source_line,
const WebString& stack_trace) override;
+ WebEffectiveConnectionType GetEffectiveConnectionType() override;
+ void SetEffectiveConnectionTypeForTesting(
+ WebEffectiveConnectionType) override;
+
private:
SimTest* test_;
+ WebEffectiveConnectionType effective_connection_type_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/testing/sim/sim_web_view_client.cc b/chromium/third_party/blink/renderer/core/testing/sim/sim_web_view_client.cc
index 902accfb708..8194c40ecd0 100644
--- a/chromium/third_party/blink/renderer/core/testing/sim/sim_web_view_client.cc
+++ b/chromium/third_party/blink/renderer/core/testing/sim/sim_web_view_client.cc
@@ -4,12 +4,11 @@
#include "third_party/blink/renderer/core/testing/sim/sim_web_view_client.h"
-#include "third_party/blink/public/platform/web_layer_tree_view.h"
#include "third_party/blink/public/web/web_local_frame.h"
namespace blink {
-SimWebViewClient::SimWebViewClient(WebLayerTreeView& layer_tree_view)
+SimWebViewClient::SimWebViewClient(content::LayerTreeView& layer_tree_view)
: visually_non_empty_layout_count_(0),
finished_parsing_layout_count_(0),
finished_loading_layout_count_(0),
@@ -30,6 +29,10 @@ void SimWebViewClient::DidMeaningfulLayout(
}
}
+WebLayerTreeView* SimWebViewClient::InitializeLayerTreeView() {
+ return layer_tree_view_;
+}
+
WebView* SimWebViewClient::CreateView(WebLocalFrame* opener,
const WebURLRequest&,
const WebWindowFeatures&,
diff --git a/chromium/third_party/blink/renderer/core/testing/sim/sim_web_view_client.h b/chromium/third_party/blink/renderer/core/testing/sim/sim_web_view_client.h
index 4296908b964..2fa564688a4 100644
--- a/chromium/third_party/blink/renderer/core/testing/sim/sim_web_view_client.h
+++ b/chromium/third_party/blink/renderer/core/testing/sim/sim_web_view_client.h
@@ -7,17 +7,17 @@
#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
-namespace blink {
+namespace content {
+class LayerTreeView;
+}
-class WebLayerTreeView;
+namespace blink {
class SimWebViewClient final : public FrameTestHelpers::TestWebViewClient {
public:
- explicit SimWebViewClient(WebLayerTreeView&);
-
- WebLayerTreeView* InitializeLayerTreeView() override {
- return layer_tree_view_;
- }
+ // The LayerTreeView to be returned from InitializeLayerTreeView()
+ // must be constructed before this class, and given to it.
+ explicit SimWebViewClient(content::LayerTreeView&);
int VisuallyNonEmptyLayoutCount() const {
return visually_non_empty_layout_count_;
@@ -29,6 +29,8 @@ class SimWebViewClient final : public FrameTestHelpers::TestWebViewClient {
return finished_loading_layout_count_;
}
+ // WebViewClient implementation.
+ WebLayerTreeView* InitializeLayerTreeView() override;
WebView* CreateView(WebLocalFrame* opener,
const WebURLRequest&,
const WebWindowFeatures&,
@@ -45,7 +47,7 @@ class SimWebViewClient final : public FrameTestHelpers::TestWebViewClient {
int finished_parsing_layout_count_;
int finished_loading_layout_count_;
- WebLayerTreeView* layer_tree_view_;
+ content::LayerTreeView* layer_tree_view_;
FrameTestHelpers::WebViewHelper web_view_helper_;
};
diff --git a/chromium/third_party/blink/renderer/core/testing/use_mock_scrollbar_settings.h b/chromium/third_party/blink/renderer/core/testing/use_mock_scrollbar_settings.h
new file mode 100644
index 00000000000..45e00a5cde9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/testing/use_mock_scrollbar_settings.h
@@ -0,0 +1,51 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_USE_MOCK_SCROLLBAR_SETTINGS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_USE_MOCK_SCROLLBAR_SETTINGS_H_
+
+#include "third_party/blink/renderer/platform/scroll/scrollbar_theme.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+
+namespace blink {
+
+// Forces to use mocked overlay scrollbars instead of the default native theme
+// scrollbars to avoid crash in Chromium code when it tries to load UI
+// resources that are not available when running blink unit tests, and to
+// ensure consistent layout regardless of differences between scrollbar themes.
+// WebViewHelper includes this, so this is only needed if a test doesn't use
+// WebViewHelper or the test needs a bigger scope of mock scrollbar settings
+// than the scope of WebViewHelper.
+class UseMockScrollbarSettings : private ScopedOverlayScrollbarsForTest {
+ public:
+ UseMockScrollbarSettings()
+ : ScopedOverlayScrollbarsForTest(true),
+ original_mock_scrollbar_enabled_(
+ ScrollbarTheme::MockScrollbarsEnabled()),
+ original_overlay_scrollbars_enabled_(
+ RuntimeEnabledFeatures::OverlayScrollbarsEnabled()) {
+ ScrollbarTheme::SetMockScrollbarsEnabled(true);
+ }
+
+ UseMockScrollbarSettings(bool use_mock, bool use_overlay)
+ : ScopedOverlayScrollbarsForTest(use_overlay),
+ original_mock_scrollbar_enabled_(
+ ScrollbarTheme::MockScrollbarsEnabled()),
+ original_overlay_scrollbars_enabled_(
+ RuntimeEnabledFeatures::OverlayScrollbarsEnabled()) {
+ ScrollbarTheme::SetMockScrollbarsEnabled(use_mock);
+ }
+
+ ~UseMockScrollbarSettings() {
+ ScrollbarTheme::SetMockScrollbarsEnabled(original_mock_scrollbar_enabled_);
+ }
+
+ private:
+ bool original_mock_scrollbar_enabled_;
+ bool original_overlay_scrollbars_enabled_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_USE_MOCK_SCROLLBAR_SETTINGS_H_
diff --git a/chromium/third_party/blink/renderer/core/testing/v8/web_core_test_support.cc b/chromium/third_party/blink/renderer/core/testing/v8/web_core_test_support.cc
index d6d86754231..d614f532822 100644
--- a/chromium/third_party/blink/renderer/core/testing/v8/web_core_test_support.cc
+++ b/chromium/third_party/blink/renderer/core/testing/v8/web_core_test_support.cc
@@ -36,6 +36,7 @@
#include "third_party/blink/renderer/core/testing/worker_internals.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
#include "third_party/blink/renderer/platform/bindings/origin_trial_features.h"
+#include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h"
namespace WebCoreTestSupport {
@@ -94,12 +95,12 @@ void InstallOriginTrialFeaturesForTesting(
blink::ExecutionContext::From(script_state);
if (type == &blink::V8OriginTrialsTest::wrapperTypeInfo) {
- if (blink::OriginTrials::originTrialsSampleAPIEnabled(execution_context)) {
+ if (blink::OriginTrials::OriginTrialsSampleAPIEnabled(execution_context)) {
blink::V8OriginTrialsTest::installOriginTrialsSampleAPI(
script_state->GetIsolate(), script_state->World(),
v8::Local<v8::Object>(), prototype_object, interface_object);
}
- if (blink::OriginTrials::originTrialsSampleAPIImpliedEnabled(
+ if (blink::OriginTrials::OriginTrialsSampleAPIImpliedEnabled(
execution_context)) {
blink::V8OriginTrialsTest::installOriginTrialsSampleAPIImplied(
script_state->GetIsolate(), script_state->World(),
diff --git a/chromium/third_party/blink/renderer/core/testing/worker_internals.cc b/chromium/third_party/blink/renderer/core/testing/worker_internals.cc
index c0ebe4fbff3..ef227ba8337 100644
--- a/chromium/third_party/blink/renderer/core/testing/worker_internals.cc
+++ b/chromium/third_party/blink/renderer/core/testing/worker_internals.cc
@@ -4,11 +4,11 @@
#include "third_party/blink/renderer/core/testing/worker_internals.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/testing/origin_trials_test.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/timing/dom_window_performance.cc b/chromium/third_party/blink/renderer/core/timing/dom_window_performance.cc
index 4f48d193376..1ffdf75af51 100644
--- a/chromium/third_party/blink/renderer/core/timing/dom_window_performance.cc
+++ b/chromium/third_party/blink/renderer/core/timing/dom_window_performance.cc
@@ -17,12 +17,6 @@ void DOMWindowPerformance::Trace(blink::Visitor* visitor) {
Supplement<LocalDOMWindow>::Trace(visitor);
}
-void DOMWindowPerformance::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(performance_);
- Supplement<LocalDOMWindow>::TraceWrappers(visitor);
-}
-
// static
const char DOMWindowPerformance::kSupplementName[] = "DOMWindowPerformance";
diff --git a/chromium/third_party/blink/renderer/core/timing/dom_window_performance.h b/chromium/third_party/blink/renderer/core/timing/dom_window_performance.h
index 18648dd1bbb..3712328d68a 100644
--- a/chromium/third_party/blink/renderer/core/timing/dom_window_performance.h
+++ b/chromium/third_party/blink/renderer/core/timing/dom_window_performance.h
@@ -27,7 +27,6 @@ class CORE_EXPORT DOMWindowPerformance final
static WindowPerformance* performance(LocalDOMWindow&);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
explicit DOMWindowPerformance(LocalDOMWindow&);
diff --git a/chromium/third_party/blink/renderer/core/timing/memory_info.cc b/chromium/third_party/blink/renderer/core/timing/memory_info.cc
index 0a478b023e4..fd257d682a6 100644
--- a/chromium/third_party/blink/renderer/core/timing/memory_info.cc
+++ b/chromium/third_party/blink/renderer/core/timing/memory_info.cc
@@ -43,7 +43,8 @@
namespace blink {
-static const double kTwentyMinutesInSeconds = 20 * 60;
+static constexpr TimeDelta kTwentyMinutes = TimeDelta::FromMinutes(20);
+static constexpr TimeDelta kFiftyMs = TimeDelta::FromMilliseconds(50);
static void GetHeapSize(HeapInfo& info) {
v8::HeapStatistics heap_statistics;
@@ -57,12 +58,10 @@ class HeapSizeCache {
USING_FAST_MALLOC(HeapSizeCache);
public:
- HeapSizeCache()
- : last_update_time_(CurrentTimeTicksInSeconds() -
- kTwentyMinutesInSeconds) {}
+ HeapSizeCache() {}
- void GetCachedHeapSize(HeapInfo& info) {
- MaybeUpdate();
+ void GetCachedHeapSize(HeapInfo& info, MemoryInfo::Precision precision) {
+ MaybeUpdate(precision);
info = info_;
}
@@ -73,25 +72,32 @@ class HeapSizeCache {
}
private:
- void MaybeUpdate() {
- // We rate-limit queries to once every twenty minutes to make it more
- // difficult for attackers to compare memory usage before and after some
- // event.
- double now = CurrentTimeTicksInSeconds();
- if (now - last_update_time_ >= kTwentyMinutesInSeconds) {
- Update();
+ void MaybeUpdate(MemoryInfo::Precision precision) {
+ // We rate-limit queries to once every twenty minutes in the Bucketized case
+ // to make it more difficult for attackers to compare memory usage before
+ // and after some event. We limit to once every 50 ms in the Precise case to
+ // avoid exposing precise GC timings.
+ TimeTicks now = CurrentTimeTicks();
+ TimeDelta delta_allowed = precision == MemoryInfo::Precision::Bucketized
+ ? kTwentyMinutes
+ : kFiftyMs;
+ if (now - last_update_time_ >= delta_allowed) {
+ Update(precision);
last_update_time_ = now;
}
}
- void Update() {
+ void Update(MemoryInfo::Precision precision) {
GetHeapSize(info_);
+ if (precision == MemoryInfo::Precision::Precise)
+ return;
+
info_.used_js_heap_size = QuantizeMemorySize(info_.used_js_heap_size);
info_.total_js_heap_size = QuantizeMemorySize(info_.total_js_heap_size);
info_.js_heap_size_limit = QuantizeMemorySize(info_.js_heap_size_limit);
}
- double last_update_time_;
+ TimeTicks last_update_time_;
HeapInfo info_;
DISALLOW_COPY_AND_ASSIGN(HeapSizeCache);
@@ -149,11 +155,12 @@ size_t QuantizeMemorySize(size_t size) {
return bucket_size_list[kNumberOfBuckets - 1];
}
-MemoryInfo::MemoryInfo() {
+MemoryInfo::MemoryInfo(Precision precision) {
+ // With the experimental PreciseMemoryInfoEnabled flag on, we will not
+ // bucketize or cache values.
if (RuntimeEnabledFeatures::PreciseMemoryInfoEnabled())
GetHeapSize(info_);
- else
- HeapSizeCache::ForCurrentThread().GetCachedHeapSize(info_);
+ HeapSizeCache::ForCurrentThread().GetCachedHeapSize(info_, precision);
}
} // namespace blink
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 5ad4195181d..06ae8afd8cc 100644
--- a/chromium/third_party/blink/renderer/core/timing/memory_info.h
+++ b/chromium/third_party/blink/renderer/core/timing/memory_info.h
@@ -52,14 +52,21 @@ class CORE_EXPORT MemoryInfo final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- static MemoryInfo* Create() { return new MemoryInfo(); }
+ // Precision of the performance.memory() attribute. A Precise value means that
+ // the numbers will not be bucketized and only cached for a small amount of
+ // time (50 ms). A Bucketized value means that the numbers will be bucketized
+ // and cached for a long period of time (20 minutes).
+ enum class Precision { Precise, Bucketized };
+ static MemoryInfo* Create(Precision precision) {
+ return new MemoryInfo(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; }
private:
- MemoryInfo();
+ explicit MemoryInfo(Precision precision);
HeapInfo info_;
};
diff --git a/chromium/third_party/blink/renderer/core/timing/memory_info_test.cc b/chromium/third_party/blink/renderer/core/timing/memory_info_test.cc
index d5680b39ebc..90b1e3da954 100644
--- a/chromium/third_party/blink/renderer/core/timing/memory_info_test.cc
+++ b/chromium/third_party/blink/renderer/core/timing/memory_info_test.cc
@@ -31,6 +31,8 @@
#include "third_party/blink/renderer/core/timing/memory_info.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink {
@@ -53,4 +55,153 @@ TEST(MemoryInfo, quantizeMemorySize) {
EXPECT_EQ(10000000u, QuantizeMemorySize(0));
}
+static constexpr int kModForBucketizationCheck = 100000;
+
+// The current time per the MemoryInfo Tests.
+// Use a large value as a start so that when subtracting twenty minutes it does
+// not become negative.
+static double current_time_ = 60 * 60;
+
+class MemoryInfoTest : public testing::Test {
+ protected:
+ void SetUp() override {
+ // Use a large value so that when subtracting twenty minutes it does not
+ // become negative. current_time_ = 60 * 60;
+ original_time_function_ = SetTimeFunctionsForTesting(MockTimeFunction);
+ // Advance clock by a large amount so that if there were previous MemoryInfo
+ // values, then they are no longer cached.
+ AdvanceClock(300 * 60);
+ }
+
+ void TearDown() override {
+ SetTimeFunctionsForTesting(original_time_function_);
+ }
+
+ void AdvanceClock(double seconds) { current_time_ += seconds; }
+
+ void CheckValues(MemoryInfo* info, MemoryInfo::Precision precision) {
+ // Check that used <= total <= limit.
+
+ // TODO(npm): add a check usedJSHeapSize <= totalJSHeapSize once it always
+ // holds. See https://crbug.com/849322
+ EXPECT_LE(info->totalJSHeapSize(), info->jsHeapSizeLimit());
+ if (precision == MemoryInfo::Precision::Bucketized) {
+ // Check that the bucketized values are heavily rounded.
+ EXPECT_EQ(0u, info->totalJSHeapSize() % kModForBucketizationCheck);
+ EXPECT_EQ(0u, info->usedJSHeapSize() % kModForBucketizationCheck);
+ EXPECT_EQ(0u, info->jsHeapSizeLimit() % kModForBucketizationCheck);
+ } else {
+ // Check that the precise values are not heavily rounded.
+ // Note: these checks are potentially flaky but in practice probably never
+ // flaky. If this is noticed to be flaky, disable test and assign bug to
+ // npm@.
+ EXPECT_NE(0u, info->totalJSHeapSize() % kModForBucketizationCheck);
+ EXPECT_NE(0u, info->usedJSHeapSize() % kModForBucketizationCheck);
+ EXPECT_NE(0u, info->jsHeapSizeLimit() % kModForBucketizationCheck);
+ }
+ }
+
+ void CheckEqual(MemoryInfo* info, MemoryInfo* info2) {
+ EXPECT_EQ(info2->totalJSHeapSize(), info->totalJSHeapSize());
+ EXPECT_EQ(info2->usedJSHeapSize(), info->usedJSHeapSize());
+ EXPECT_EQ(info2->jsHeapSizeLimit(), info->jsHeapSizeLimit());
+ }
+
+ private:
+ static double MockTimeFunction() { return current_time_; }
+
+ TimeFunction original_time_function_;
+};
+
+TEST_F(MemoryInfoTest, Bucketized) {
+ V8TestingScope scope;
+ v8::Isolate* isolate = scope.GetIsolate();
+ // The vector is used to keep the objects
+ // allocated alive even if GC happens. In practice, the objects only get GC'd
+ // after we go out of V8TestingScope. But having them in a vector makes it
+ // impossible for GC to clear them up unexpectedly early.
+ std::vector<v8::Local<v8::ArrayBuffer>> objects;
+
+ MemoryInfo* bucketized_memory =
+ MemoryInfo::Create(MemoryInfo::Precision::Bucketized);
+
+ // Check that the values are monotone and rounded.
+ CheckValues(bucketized_memory, MemoryInfo::Precision::Bucketized);
+
+ // Advance the clock for a minute. Not enough to make bucketized value
+ // recalculate. Also allocate some memory.
+ AdvanceClock(60);
+ objects.push_back(v8::ArrayBuffer::New(isolate, 100));
+
+ MemoryInfo* bucketized_memory2 =
+ MemoryInfo::Create(MemoryInfo::Precision::Bucketized);
+ // The old bucketized values must be equal to the new bucketized values.
+ CheckEqual(bucketized_memory, bucketized_memory2);
+
+ // TODO(npm): The bucketized MemoryInfo is very hard to change reliably. One
+ // option is to do something such as:
+ // for (int i = 0; i < kNumArrayBuffersForLargeAlloc; i++)
+ // objects.push_back(v8::ArrayBuffer::New(isolate, 1));
+ // Here, kNumArrayBuffersForLargeAlloc should be strictly greater than 200000
+ // (test failed on Windows with this value). Creating a single giant
+ // ArrayBuffer does not seem to work, so instead a lot of small ArrayBuffers
+ // are used. For now we only test that values are still rounded after adding
+ // some memory.
+ for (int i = 0; i < 10; i++) {
+ // Advance the clock for another thirty minutes, enough to make the
+ // bucketized value recalculate.
+ AdvanceClock(60 * 30);
+ objects.push_back(v8::ArrayBuffer::New(isolate, 100));
+ MemoryInfo* bucketized_memory3 =
+ MemoryInfo::Create(MemoryInfo::Precision::Bucketized);
+ CheckValues(bucketized_memory3, MemoryInfo::Precision::Bucketized);
+ // The limit should remain unchanged.
+ EXPECT_EQ(bucketized_memory3->jsHeapSizeLimit(),
+ bucketized_memory->jsHeapSizeLimit());
+ }
+}
+
+TEST_F(MemoryInfoTest, Precise) {
+ V8TestingScope scope;
+ v8::Isolate* isolate = scope.GetIsolate();
+ std::vector<v8::Local<v8::ArrayBuffer>> objects;
+
+ MemoryInfo* precise_memory =
+ MemoryInfo::Create(MemoryInfo::Precision::Precise);
+ // Check that the precise values are monotone and not heavily rounded.
+ CheckValues(precise_memory, MemoryInfo::Precision::Precise);
+
+ // Advance the clock for a nanosecond, which should not be enough to make the
+ // precise value recalculate.
+ AdvanceClock(1e-9);
+ // Allocate an object in heap and keep it in a vector to make sure that it
+ // does not get accidentally GC'd. This single ArrayBuffer should be enough to
+ // be noticed by the used heap size in the precise MemoryInfo case.
+ objects.push_back(v8::ArrayBuffer::New(isolate, 100));
+ MemoryInfo* precise_memory2 =
+ MemoryInfo::Create(MemoryInfo::Precision::Precise);
+ // The old precise values must be equal to the new precise values.
+ CheckEqual(precise_memory, precise_memory2);
+
+ for (int i = 0; i < 10; i++) {
+ // Advance the clock for another thirty seconds, enough to make the precise
+ // values be recalculated. Also allocate another object.
+ AdvanceClock(30);
+ objects.push_back(v8::ArrayBuffer::New(isolate, 100));
+
+ MemoryInfo* new_precise_memory =
+ MemoryInfo::Create(MemoryInfo::Precision::Precise);
+
+ CheckValues(new_precise_memory, MemoryInfo::Precision::Precise);
+ // The old precise used heap size must be different from the new one.
+ EXPECT_NE(new_precise_memory->usedJSHeapSize(),
+ precise_memory->usedJSHeapSize());
+ // The limit should remain unchanged.
+ EXPECT_EQ(new_precise_memory->jsHeapSizeLimit(),
+ precise_memory->jsHeapSizeLimit());
+ // Update |precise_memory| to be the newest MemoryInfo thus far.
+ precise_memory = new_precise_memory;
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/performance.cc b/chromium/third_party/blink/renderer/core/timing/performance.cc
index 9f09da89bf0..99375ad1b0e 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance.cc
@@ -84,7 +84,7 @@ DOMHighResTimeStamp GetUnixAtZeroMonotonic() {
using PerformanceObserverVector = HeapVector<Member<PerformanceObserver>>;
-static const size_t kDefaultResourceTimingBufferSize = 150;
+static const size_t kDefaultResourceTimingBufferSize = 250;
static const size_t kDefaultFrameTimingBufferSize = 150;
constexpr size_t kDefaultEventTimingBufferSize = 150;
@@ -120,6 +120,10 @@ MemoryInfo* Performance::memory() const {
return nullptr;
}
+bool Performance::shouldYield() const {
+ return false;
+}
+
DOMHighResTimeStamp Performance::timeOrigin() const {
DCHECK(!time_origin_.is_null());
return GetUnixAtZeroMonotonic() +
@@ -156,7 +160,8 @@ PerformanceEntryVector Performance::getEntries() {
return entries;
}
-PerformanceEntryVector Performance::getEntriesByType(const String& entry_type) {
+PerformanceEntryVector Performance::getEntriesByType(
+ const AtomicString& entry_type) {
PerformanceEntryVector entries;
PerformanceEntry::EntryType type =
PerformanceEntry::ToEntryTypeEnum(entry_type);
@@ -224,8 +229,9 @@ PerformanceEntryVector Performance::getEntriesByType(const String& entry_type) {
return entries;
}
-PerformanceEntryVector Performance::getEntriesByName(const String& name,
- const String& entry_type) {
+PerformanceEntryVector Performance::getEntriesByName(
+ const String& name,
+ const AtomicString& entry_type) {
PerformanceEntryVector entries;
PerformanceEntry::EntryType type =
PerformanceEntry::ToEntryTypeEnum(entry_type);
@@ -668,7 +674,7 @@ PerformanceMeasure* Performance::measureInternal(
if (start_or_options.IsPerformanceMeasureOptions()) {
if (!end.IsNull()) {
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"If a PerformanceMeasureOptions object was passed, |end| must be "
"null.");
return nullptr;
@@ -896,10 +902,4 @@ void Performance::Trace(blink::Visitor* visitor) {
EventTargetWithInlineData::Trace(visitor);
}
-void Performance::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- for (const auto& observer : observers_)
- visitor->TraceWrappers(observer);
- EventTargetWithInlineData::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/performance.h b/chromium/third_party/blink/renderer/core/timing/performance.h
index 44006484fb7..9126b86b62a 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance.h
@@ -48,6 +48,7 @@
#include "third_party/blink/renderer/platform/wtf/forward.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/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -85,6 +86,7 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
virtual PerformanceTiming* timing() const;
virtual PerformanceNavigation* navigation() const;
virtual MemoryInfo* memory() const;
+ virtual bool shouldYield() const;
virtual void UpdateLongTaskInstrumentation() {}
@@ -112,9 +114,9 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
double GetTimeOrigin() const { return TimeTicksInSeconds(time_origin_); }
PerformanceEntryVector getEntries();
- PerformanceEntryVector getEntriesByType(const String& entry_type);
+ PerformanceEntryVector getEntriesByType(const AtomicString& entry_type);
PerformanceEntryVector getEntriesByName(const String& name,
- const String& entry_type);
+ const AtomicString& entry_type);
void clearResourceTimings();
void setResourceTimingBufferSize(unsigned);
@@ -202,7 +204,6 @@ class CORE_EXPORT Performance : public EventTargetWithInlineData {
ScriptValue toJSONForBinding(ScriptState*) const;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
static bool PassesTimingAllowCheck(const ResourceResponse&,
diff --git a/chromium/third_party/blink/renderer/core/timing/performance.idl b/chromium/third_party/blink/renderer/core/timing/performance.idl
index 945edd8afff..58cc3685b19 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance.idl
+++ b/chromium/third_party/blink/renderer/core/timing/performance.idl
@@ -80,5 +80,8 @@ interface Performance : EventTarget {
// https://groups.google.com/a/chromium.org/d/msg/blink-dev/g5YRCGpC9vs/b4OJz71NmPwJ
[Exposed=Window, Measure] readonly attribute MemoryInfo memory;
+ // TODO(npm): This is an experimental attribute with no current plan to standardize. Remove once experiment has concluded. Only exposed to Window because we do not consider worker threads to contain high priority work.
+ [Exposed=Window, RuntimeEnabled=ExperimentalShouldYield] readonly attribute boolean shouldYield;
+
serializer = {attribute};
};
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_entry.cc b/chromium/third_party/blink/renderer/core/timing/performance_entry.cc
index 8d867d35e25..2ad3ed885c5 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_entry.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_entry.cc
@@ -41,14 +41,11 @@ static base::AtomicSequenceNumber index_seq;
}
PerformanceEntry::PerformanceEntry(const String& name,
- const String& entry_type,
double start_time,
double finish_time)
: duration_(finish_time - start_time),
name_(name),
- entry_type_(entry_type),
start_time_(start_time),
- entry_type_enum_(ToEntryTypeEnum(entry_type)),
index_(index_seq.GetNext()) {}
PerformanceEntry::~PerformanceEntry() = default;
@@ -57,10 +54,6 @@ String PerformanceEntry::name() const {
return name_;
}
-String PerformanceEntry::entryType() const {
- return entry_type_;
-}
-
DOMHighResTimeStamp PerformanceEntry::startTime() const {
return start_time_;
}
@@ -69,29 +62,107 @@ DOMHighResTimeStamp PerformanceEntry::duration() const {
return duration_;
}
+const AtomicString& PerformanceEntry::CompositeKeyword() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<AtomicString>, composite, ());
+ if (!composite.IsSet())
+ *composite = "composite";
+ return *composite;
+}
+
+const AtomicString& PerformanceEntry::EventKeyword() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<AtomicString>, event, ());
+ if (!event.IsSet())
+ *event = "event";
+ return *event;
+}
+
+const AtomicString& PerformanceEntry::FirstInputKeyword() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<AtomicString>, firstInput, ());
+ if (!firstInput.IsSet())
+ *firstInput = "firstInput";
+ return *firstInput;
+}
+
+const AtomicString& PerformanceEntry::LongtaskKeyword() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<AtomicString>, longtask, ());
+ if (!longtask.IsSet())
+ *longtask = "longtask";
+ return *longtask;
+}
+
+const AtomicString& PerformanceEntry::MarkKeyword() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<AtomicString>, mark, ());
+ if (!mark.IsSet())
+ *mark = "mark";
+ return *mark;
+}
+
+const AtomicString& PerformanceEntry::MeasureKeyword() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<AtomicString>, measure, ());
+ if (!measure.IsSet())
+ *measure = "measure";
+ return *measure;
+}
+
+const AtomicString& PerformanceEntry::NavigationKeyword() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<AtomicString>, navigation, ());
+ if (!navigation.IsSet())
+ *navigation = "navigation";
+ return *navigation;
+}
+
+const AtomicString& PerformanceEntry::PaintKeyword() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<AtomicString>, paint, ());
+ if (!paint.IsSet())
+ *paint = "paint";
+ return *paint;
+}
+
+const AtomicString& PerformanceEntry::RenderKeyword() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<AtomicString>, render, ());
+ if (!render.IsSet())
+ *render = "render";
+ return *render;
+}
+
+const AtomicString& PerformanceEntry::ResourceKeyword() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<AtomicString>, resource, ());
+ if (!resource.IsSet())
+ *resource = "resource";
+ return *resource;
+}
+
+const AtomicString& PerformanceEntry::TaskattributionKeyword() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<AtomicString>, taskattribution,
+ ());
+ if (!taskattribution.IsSet())
+ *taskattribution = "taskattribution";
+ return *taskattribution;
+}
+
PerformanceEntry::EntryType PerformanceEntry::ToEntryTypeEnum(
- const String& entry_type) {
- if (entry_type == "composite")
+ const AtomicString& entry_type) {
+ if (entry_type == CompositeKeyword())
return kComposite;
- if (entry_type == "longtask")
+ if (entry_type == LongtaskKeyword())
return kLongTask;
- if (entry_type == "mark")
+ if (entry_type == MarkKeyword())
return kMark;
- if (entry_type == "measure")
+ if (entry_type == MeasureKeyword())
return kMeasure;
- if (entry_type == "render")
+ if (entry_type == RenderKeyword())
return kRender;
- if (entry_type == "resource")
+ if (entry_type == ResourceKeyword())
return kResource;
- if (entry_type == "navigation")
+ if (entry_type == NavigationKeyword())
return kNavigation;
- if (entry_type == "taskattribution")
+ if (entry_type == TaskattributionKeyword())
return kTaskAttribution;
- if (entry_type == "paint")
+ if (entry_type == PaintKeyword())
return kPaint;
- if (entry_type == "event")
+ if (entry_type == EventKeyword())
return kEvent;
- if (entry_type == "firstInput")
+ if (entry_type == FirstInputKeyword())
return kFirstInput;
return kInvalid;
}
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_entry.h b/chromium/third_party/blink/renderer/core/timing/performance_entry.h
index 664134153e7..286b860cb77 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_entry.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance_entry.h
@@ -69,8 +69,9 @@ class CORE_EXPORT PerformanceEntry : public ScriptWrappable {
};
String name() const;
- String entryType() const;
DOMHighResTimeStamp startTime() const;
+ virtual AtomicString entryType() const = 0;
+ virtual PerformanceEntryType EntryTypeEnum() const = 0;
// PerformanceNavigationTiming will override this due to
// the nature of reporting it early, which means not having a
// finish time available at construction time.
@@ -79,13 +80,11 @@ class CORE_EXPORT PerformanceEntry : public ScriptWrappable {
ScriptValue toJSONForBinding(ScriptState*) const;
- PerformanceEntryType EntryTypeEnum() const { return entry_type_enum_; }
-
- bool IsResource() const { return entry_type_enum_ == kResource; }
- bool IsRender() const { return entry_type_enum_ == kRender; }
- bool IsComposite() const { return entry_type_enum_ == kComposite; }
- bool IsMark() const { return entry_type_enum_ == kMark; }
- bool IsMeasure() const { return entry_type_enum_ == kMeasure; }
+ bool IsResource() const { return EntryTypeEnum() == kResource; }
+ bool IsRender() const { return EntryTypeEnum() == kRender; }
+ bool IsComposite() const { return EntryTypeEnum() == kComposite; }
+ bool IsMark() const { return EntryTypeEnum() == kMark; }
+ bool IsMeasure() const { return EntryTypeEnum() == kMeasure; }
static bool StartTimeCompareLessThan(PerformanceEntry* a,
PerformanceEntry* b) {
@@ -94,11 +93,22 @@ class CORE_EXPORT PerformanceEntry : public ScriptWrappable {
return a->startTime() < b->startTime();
}
- static PerformanceEntry::EntryType ToEntryTypeEnum(const String& entry_type);
+ static const AtomicString& CompositeKeyword();
+ static const AtomicString& EventKeyword();
+ static const AtomicString& FirstInputKeyword();
+ static const AtomicString& LongtaskKeyword();
+ static const AtomicString& MarkKeyword();
+ static const AtomicString& MeasureKeyword();
+ static const AtomicString& NavigationKeyword();
+ static const AtomicString& PaintKeyword();
+ static const AtomicString& RenderKeyword();
+ static const AtomicString& ResourceKeyword();
+ static const AtomicString& TaskattributionKeyword();
+ static PerformanceEntry::EntryType ToEntryTypeEnum(
+ const AtomicString& entry_type);
protected:
PerformanceEntry(const String& name,
- const String& entry_type,
double start_time,
double finish_time);
virtual void BuildJSONValue(V8ObjectBuilder&) const;
@@ -108,9 +118,7 @@ class CORE_EXPORT PerformanceEntry : public ScriptWrappable {
private:
const String name_;
- const String entry_type_;
const double start_time_;
- const PerformanceEntryType entry_type_enum_;
const int index_;
};
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 be23bd0fd13..5fe4adc18a3 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
@@ -18,35 +18,42 @@ PerformanceEventTiming* PerformanceEventTiming::Create(
// 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 new PerformanceEventTiming(event_type, "event", start_time,
- processing_start, processing_end,
- cancelable);
+ return new PerformanceEventTiming(
+ event_type, PerformanceEntry::EventKeyword(), start_time,
+ processing_start, processing_end, cancelable);
}
// static
PerformanceEventTiming* PerformanceEventTiming::CreateFirstInputTiming(
PerformanceEventTiming* entry) {
PerformanceEventTiming* first_input = new PerformanceEventTiming(
- entry->name(), "firstInput", entry->startTime(), entry->processingStart(),
- entry->processingEnd(), entry->cancelable());
+ entry->name(), PerformanceEntry::FirstInputKeyword(), entry->startTime(),
+ entry->processingStart(), entry->processingEnd(), entry->cancelable());
first_input->SetDuration(entry->duration());
return first_input;
}
PerformanceEventTiming::PerformanceEventTiming(
const String& event_type,
- const String& entry_type,
+ const AtomicString& entry_type,
DOMHighResTimeStamp start_time,
DOMHighResTimeStamp processing_start,
DOMHighResTimeStamp processing_end,
bool cancelable)
- : PerformanceEntry(event_type, entry_type, start_time, 0.0),
+ : PerformanceEntry(event_type, start_time, 0.0),
+ entry_type_(entry_type),
processing_start_(processing_start),
processing_end_(processing_end),
cancelable_(cancelable) {}
PerformanceEventTiming::~PerformanceEventTiming() = default;
+PerformanceEntryType PerformanceEventTiming::EntryTypeEnum() const {
+ return entry_type_ == PerformanceEntry::EventKeyword()
+ ? PerformanceEntry::EntryType::kEvent
+ : PerformanceEntry::EntryType::kFirstInput;
+}
+
DOMHighResTimeStamp PerformanceEventTiming::processingStart() const {
return processing_start_;
}
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 2386f041854..3337b234aa7 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
@@ -27,6 +27,9 @@ class CORE_EXPORT PerformanceEventTiming final : public PerformanceEntry {
~PerformanceEventTiming() override;
+ AtomicString entryType() const override { return entry_type_; }
+ PerformanceEntryType EntryTypeEnum() const override;
+
bool cancelable() const { return cancelable_; }
DOMHighResTimeStamp processingStart() const;
@@ -40,11 +43,12 @@ class CORE_EXPORT PerformanceEventTiming final : public PerformanceEntry {
private:
PerformanceEventTiming(const String& event_type,
- const String& entry_type,
+ const AtomicString& entry_type,
DOMHighResTimeStamp start_time,
DOMHighResTimeStamp processing_start,
DOMHighResTimeStamp processing_end,
bool cancelable);
+ AtomicString entry_type_;
DOMHighResTimeStamp processing_start_;
DOMHighResTimeStamp processing_end_;
bool cancelable_;
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_long_task_timing.cc b/chromium/third_party/blink/renderer/core/timing/performance_long_task_timing.cc
index edc7cca4ccf..ba90d25a0ff 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_long_task_timing.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_long_task_timing.cc
@@ -34,7 +34,7 @@ PerformanceLongTaskTiming::PerformanceLongTaskTiming(
String culprit_frame_id,
String culprit_frame_name,
const SubTaskAttribution::EntriesVector& sub_task_attributions)
- : PerformanceEntry(name, "longtask", start_time, end_time) {
+ : PerformanceEntry(name, start_time, end_time) {
// Only one possible container type exists currently: "iframe".
if (RuntimeEnabledFeatures::LongTaskV2Enabled()) {
for (auto&& it : sub_task_attributions) {
@@ -55,6 +55,14 @@ PerformanceLongTaskTiming::PerformanceLongTaskTiming(
PerformanceLongTaskTiming::~PerformanceLongTaskTiming() = default;
+AtomicString PerformanceLongTaskTiming::entryType() const {
+ return PerformanceEntry::LongtaskKeyword();
+}
+
+PerformanceEntryType PerformanceLongTaskTiming::EntryTypeEnum() const {
+ return PerformanceEntry::EntryType::kLongTask;
+}
+
TaskAttributionVector PerformanceLongTaskTiming::attribution() const {
return attribution_;
}
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_long_task_timing.h b/chromium/third_party/blink/renderer/core/timing/performance_long_task_timing.h
index a2311123d54..cb9fd59559c 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_long_task_timing.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance_long_task_timing.h
@@ -29,6 +29,9 @@ class PerformanceLongTaskTiming final : public PerformanceEntry {
String frame_name,
const SubTaskAttribution::EntriesVector& sub_task_attributions);
+ AtomicString entryType() const override;
+ PerformanceEntryType EntryTypeEnum() const override;
+
TaskAttributionVector attribution() const;
void Trace(blink::Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_mark.cc b/chromium/third_party/blink/renderer/core/timing/performance_mark.cc
index 787169e1604..8c5d0b606e3 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_mark.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_mark.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/timing/performance_mark.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_factory.h"
@@ -12,7 +13,7 @@ PerformanceMark::PerformanceMark(ScriptState* script_state,
const String& name,
double start_time,
const ScriptValue& detail)
- : PerformanceEntry(name, "mark", start_time, start_time) {
+ : PerformanceEntry(name, start_time, start_time) {
world_ = WrapRefCounted(&script_state->World());
if (detail.IsEmpty() || detail.IsNull() || detail.IsUndefined()) {
return;
@@ -20,6 +21,14 @@ PerformanceMark::PerformanceMark(ScriptState* script_state,
detail_.Set(detail.GetIsolate(), detail.V8Value());
}
+AtomicString PerformanceMark::entryType() const {
+ return PerformanceEntry::MarkKeyword();
+}
+
+PerformanceEntryType PerformanceMark::EntryTypeEnum() const {
+ return PerformanceEntry::EntryType::kMark;
+}
+
ScriptValue PerformanceMark::detail(ScriptState* script_state) const {
v8::Isolate* isolate = script_state->GetIsolate();
if (detail_.IsEmpty()) {
@@ -36,12 +45,8 @@ ScriptValue PerformanceMark::detail(ScriptState* script_state) const {
}
void PerformanceMark::Trace(blink::Visitor* visitor) {
+ visitor->Trace(detail_);
PerformanceEntry::Trace(visitor);
}
-void PerformanceMark::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(detail_);
- PerformanceEntry::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_mark.h b/chromium/third_party/blink/renderer/core/timing/performance_mark.h
index b2e30e7ff7b..9af17a7beca 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_mark.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance_mark.h
@@ -33,8 +33,6 @@
namespace blink {
-class ScriptWrappableVisitor;
-
class CORE_EXPORT PerformanceMark final : public PerformanceEntry {
DEFINE_WRAPPERTYPEINFO();
@@ -46,12 +44,13 @@ class CORE_EXPORT PerformanceMark final : public PerformanceEntry {
return new PerformanceMark(script_state, name, start_time, detail);
}
+ AtomicString entryType() const override;
+ PerformanceEntryType EntryTypeEnum() const override;
+
ScriptValue detail(ScriptState*) const;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
private:
PerformanceMark(ScriptState*,
const String& name,
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_measure.cc b/chromium/third_party/blink/renderer/core/timing/performance_measure.cc
index 2fcb78c64bf..ab06293a79b 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_measure.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_measure.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/timing/performance_measure.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
namespace blink {
@@ -13,7 +14,7 @@ PerformanceMeasure::PerformanceMeasure(ScriptState* script_state,
double start_time,
double end_time,
const ScriptValue& detail)
- : PerformanceEntry(name, "measure", start_time, end_time) {
+ : PerformanceEntry(name, start_time, end_time) {
if (detail.IsEmpty()) {
detail_ = SerializedScriptValue::NullValue();
} else {
@@ -28,4 +29,12 @@ ScriptValue PerformanceMeasure::detail(ScriptState* script_state) const {
return ScriptValue(script_state, detail);
}
+AtomicString PerformanceMeasure::entryType() const {
+ return PerformanceEntry::MeasureKeyword();
+}
+
+PerformanceEntryType PerformanceMeasure::EntryTypeEnum() const {
+ return PerformanceEntry::EntryType::kMeasure;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_measure.h b/chromium/third_party/blink/renderer/core/timing/performance_measure.h
index e73e87e85b9..86b17ba2ac2 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_measure.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance_measure.h
@@ -48,6 +48,9 @@ class PerformanceMeasure final : public PerformanceEntry {
}
ScriptValue detail(ScriptState*) const;
+ AtomicString entryType() const override;
+ PerformanceEntryType EntryTypeEnum() const override;
+
void Trace(blink::Visitor* visitor) override {
PerformanceEntry::Trace(visitor);
}
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 3d94a31bfe6..ab305f33d05 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_navigation.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_navigation.cc
@@ -51,9 +51,9 @@ unsigned short PerformanceNavigation::type() const {
return kTypeNavigate;
switch (document_loader->GetNavigationType()) {
- case kNavigationTypeReload:
+ case kWebNavigationTypeReload:
return kTypeReload;
- case kNavigationTypeBackForward:
+ case kWebNavigationTypeBackForward:
return kTypeBackForward;
default:
return kTypeNavigate;
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 3f5217f821a..26859323bd6 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
@@ -23,7 +23,6 @@ PerformanceNavigationTiming::PerformanceNavigationTiming(
const WebVector<WebServerTimingInfo>& server_timing)
: PerformanceResourceTiming(
info ? info->FinalResponse().Url().GetString() : "",
- "navigation",
time_origin,
server_timing),
ContextClient(frame),
@@ -34,6 +33,14 @@ PerformanceNavigationTiming::PerformanceNavigationTiming(
PerformanceNavigationTiming::~PerformanceNavigationTiming() = default;
+AtomicString PerformanceNavigationTiming::entryType() const {
+ return PerformanceEntry::NavigationKeyword();
+}
+
+PerformanceEntryType PerformanceNavigationTiming::EntryTypeEnum() const {
+ return PerformanceEntry::EntryType::kNavigation;
+}
+
void PerformanceNavigationTiming::Trace(blink::Visitor* visitor) {
ContextClient::Trace(visitor);
PerformanceResourceTiming::Trace(visitor);
@@ -88,21 +95,21 @@ unsigned long long PerformanceNavigationTiming::GetDecodedBodySize() const {
}
AtomicString PerformanceNavigationTiming::GetNavigationType(
- NavigationType type,
+ WebNavigationType type,
const Document* document) {
if (document && document->GetPageVisibilityState() ==
mojom::PageVisibilityState::kPrerender) {
return "prerender";
}
switch (type) {
- case kNavigationTypeReload:
+ case kWebNavigationTypeReload:
return "reload";
- case kNavigationTypeBackForward:
+ case kWebNavigationTypeBackForward:
return "back_forward";
- case kNavigationTypeLinkClicked:
- case kNavigationTypeFormSubmitted:
- case kNavigationTypeFormResubmitted:
- case kNavigationTypeOther:
+ case kWebNavigationTypeLinkClicked:
+ case kWebNavigationTypeFormSubmitted:
+ case kWebNavigationTypeFormResubmitted:
+ case kWebNavigationTypeOther:
return "navigate";
}
NOTREACHED();
@@ -110,7 +117,7 @@ AtomicString PerformanceNavigationTiming::GetNavigationType(
}
AtomicString PerformanceNavigationTiming::initiatorType() const {
- return "navigation";
+ return PerformanceEntry::NavigationKeyword();
}
bool PerformanceNavigationTiming::GetAllowRedirectDetails() const {
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing.h b/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing.h
index eb71ba761f7..389358949c3 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance_navigation_timing.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_PERFORMANCE_NAVIGATION_TIMING_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_PERFORMANCE_NAVIGATION_TIMING_H_
+#include "third_party/blink/public/web/web_navigation_type.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/dom/dom_high_res_time_stamp.h"
@@ -37,6 +38,8 @@ class CORE_EXPORT PerformanceNavigationTiming final
// Attributes inheritted from PerformanceEntry.
DOMHighResTimeStamp duration() const override;
+ AtomicString entryType() const override;
+ PerformanceEntryType EntryTypeEnum() const override;
AtomicString initiatorType() const override;
@@ -66,7 +69,7 @@ class CORE_EXPORT PerformanceNavigationTiming final
private:
~PerformanceNavigationTiming() override;
- static AtomicString GetNavigationType(NavigationType, const Document*);
+ static AtomicString GetNavigationType(WebNavigationType, const Document*);
const DocumentTiming* GetDocumentTiming() const;
DocumentLoader* GetDocumentLoader() const;
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 517f9993202..686ab54bfb4 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
@@ -12,7 +12,7 @@ namespace blink {
class PerformanceNavigationTimingTest : public PageTestBase {
protected:
- AtomicString GetNavigationType(NavigationType type, Document* document) {
+ AtomicString GetNavigationType(WebNavigationType type, Document* document) {
return PerformanceNavigationTiming::GetNavigationType(type, document);
}
};
@@ -20,16 +20,17 @@ class PerformanceNavigationTimingTest : public PageTestBase {
TEST_F(PerformanceNavigationTimingTest, GetNavigationType) {
GetPage().SetVisibilityState(mojom::PageVisibilityState::kPrerender, false);
AtomicString returned_type =
- GetNavigationType(kNavigationTypeBackForward, &GetDocument());
+ GetNavigationType(kWebNavigationTypeBackForward, &GetDocument());
EXPECT_EQ(returned_type, "prerender");
GetPage().SetVisibilityState(mojom::PageVisibilityState::kHidden, false);
- returned_type = GetNavigationType(kNavigationTypeBackForward, &GetDocument());
+ returned_type =
+ GetNavigationType(kWebNavigationTypeBackForward, &GetDocument());
EXPECT_EQ(returned_type, "back_forward");
GetPage().SetVisibilityState(mojom::PageVisibilityState::kVisible, false);
returned_type =
- GetNavigationType(kNavigationTypeFormResubmitted, &GetDocument());
+ GetNavigationType(kWebNavigationTypeFormResubmitted, &GetDocument());
EXPECT_EQ(returned_type, "navigate");
}
} // namespace blink
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 64639d33800..9df0dbb3857 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_observer.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_observer.cc
@@ -5,8 +5,7 @@
#include "third_party/blink/renderer/core/timing/performance_observer.h"
#include <algorithm>
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_performance_observer_callback.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -19,6 +18,8 @@
#include "third_party/blink/renderer/core/timing/window_performance.h"
#include "third_party/blink/renderer/core/timing/worker_global_scope_performance.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/timer.h"
namespace blink {
@@ -72,8 +73,10 @@ void PerformanceObserver::observe(const PerformanceObserverInit& observer_init,
PerformanceEntryTypeMask entry_types = PerformanceEntry::kInvalid;
if (observer_init.hasEntryTypes() && observer_init.entryTypes().size()) {
const Vector<String>& sequence = observer_init.entryTypes();
- for (const auto& entry_type_string : sequence)
- entry_types |= PerformanceEntry::ToEntryTypeEnum(entry_type_string);
+ for (const auto& entry_type_string : sequence) {
+ entry_types |=
+ PerformanceEntry::ToEntryTypeEnum(AtomicString(entry_type_string));
+ }
}
if (entry_types == PerformanceEntry::kInvalid) {
exception_state.ThrowTypeError(
@@ -141,9 +144,4 @@ void PerformanceObserver::Trace(blink::Visitor* visitor) {
ContextClient::Trace(visitor);
}
-void PerformanceObserver::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(callback_);
- ScriptWrappable::TraceWrappers(visitor);
-}
-
} // namespace blink
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 eab006f2831..6d884e91215 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_observer.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance_observer.h
@@ -49,7 +49,6 @@ class CORE_EXPORT PerformanceObserver final
bool HasPendingActivity() const final;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
PerformanceObserver(ExecutionContext*,
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_observer_entry_list.cc b/chromium/third_party/blink/renderer/core/timing/performance_observer_entry_list.cc
index 4a24ab6ff68..61a622316c3 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_observer_entry_list.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_observer_entry_list.cc
@@ -27,7 +27,7 @@ PerformanceEntryVector PerformanceObserverEntryList::getEntries() const {
}
PerformanceEntryVector PerformanceObserverEntryList::getEntriesByType(
- const String& entry_type) {
+ const AtomicString& entry_type) {
PerformanceEntryVector entries;
PerformanceEntry::EntryType type =
PerformanceEntry::ToEntryTypeEnum(entry_type);
@@ -48,7 +48,7 @@ PerformanceEntryVector PerformanceObserverEntryList::getEntriesByType(
PerformanceEntryVector PerformanceObserverEntryList::getEntriesByName(
const String& name,
- const String& entry_type) {
+ const AtomicString& entry_type) {
PerformanceEntryVector entries;
PerformanceEntry::EntryType type =
PerformanceEntry::ToEntryTypeEnum(entry_type);
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_observer_entry_list.h b/chromium/third_party/blink/renderer/core/timing/performance_observer_entry_list.h
index 2225c16f74b..f7b6a54b484 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_observer_entry_list.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance_observer_entry_list.h
@@ -8,6 +8,7 @@
#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/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
namespace blink {
@@ -23,9 +24,9 @@ class PerformanceObserverEntryList : public ScriptWrappable {
~PerformanceObserverEntryList() override;
PerformanceEntryVector getEntries() const;
- PerformanceEntryVector getEntriesByType(const String& entry_type);
+ PerformanceEntryVector getEntriesByType(const AtomicString& entry_type);
PerformanceEntryVector getEntriesByName(const String& name,
- const String& entry_type);
+ const AtomicString& entry_type);
void Trace(blink::Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_paint_timing.cc b/chromium/third_party/blink/renderer/core/timing/performance_paint_timing.cc
index a0c6ea4bb20..1342c50ed28 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_paint_timing.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_paint_timing.cc
@@ -11,12 +11,19 @@ namespace blink {
PerformancePaintTiming::PerformancePaintTiming(PaintType type,
double start_time)
: PerformanceEntry(FromPaintTypeToString(type),
- "paint",
start_time,
start_time) {}
PerformancePaintTiming::~PerformancePaintTiming() = default;
+AtomicString PerformancePaintTiming::entryType() const {
+ return PerformanceEntry::PaintKeyword();
+}
+
+PerformanceEntryType PerformancePaintTiming::EntryTypeEnum() const {
+ return PerformanceEntry::EntryType::kPaint;
+}
+
String PerformancePaintTiming::FromPaintTypeToString(PaintType type) {
switch (type) {
case PaintType::kFirstPaint:
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_paint_timing.h b/chromium/third_party/blink/renderer/core/timing/performance_paint_timing.h
index 1fc2f48c564..c67d510cbb6 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_paint_timing.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance_paint_timing.h
@@ -19,6 +19,9 @@ class CORE_EXPORT PerformancePaintTiming final : public PerformanceEntry {
PerformancePaintTiming(PaintType, double start_time);
~PerformancePaintTiming() override;
+ AtomicString entryType() const override;
+ PerformanceEntryType EntryTypeEnum() const override;
+
static String FromPaintTypeToString(PaintType);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_resource_timing.cc b/chromium/third_party/blink/renderer/core/timing/performance_resource_timing.cc
index 9bff318837c..385b4c12cd5 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_resource_timing.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_resource_timing.cc
@@ -34,6 +34,7 @@
#include "third_party/blink/public/platform/web_resource_timing_info.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/core/timing/performance.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/loader/fetch/resource_response.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
@@ -45,7 +46,6 @@ PerformanceResourceTiming::PerformanceResourceTiming(
TimeTicks time_origin,
const AtomicString& initiator_type)
: PerformanceEntry(info.name,
- "resource",
Performance::MonotonicTimeToDOMHighResTimeStamp(
time_origin,
info.start_time,
@@ -54,7 +54,8 @@ PerformanceResourceTiming::PerformanceResourceTiming(
time_origin,
info.finish_time,
info.allow_negative_values)),
- initiator_type_(initiator_type),
+ initiator_type_(initiator_type.IsEmpty() ? FetchInitiatorTypeNames::other
+ : initiator_type),
alpn_negotiated_protocol_(
static_cast<String>(info.alpn_negotiated_protocol)),
connection_info_(static_cast<String>(info.connection_info)),
@@ -76,16 +77,23 @@ PerformanceResourceTiming::PerformanceResourceTiming(
// This constructor is for PerformanceNavigationTiming.
PerformanceResourceTiming::PerformanceResourceTiming(
const String& name,
- const String& entry_type,
TimeTicks time_origin,
const WebVector<WebServerTimingInfo>& server_timing)
- : PerformanceEntry(name, entry_type, 0.0, 0.0),
+ : PerformanceEntry(name, 0.0, 0.0),
time_origin_(time_origin),
server_timing_(
PerformanceServerTiming::FromParsedServerTiming(server_timing)) {}
PerformanceResourceTiming::~PerformanceResourceTiming() = default;
+AtomicString PerformanceResourceTiming::entryType() const {
+ return PerformanceEntry::ResourceKeyword();
+}
+
+PerformanceEntryType PerformanceResourceTiming::EntryTypeEnum() const {
+ return PerformanceEntry::EntryType::kResource;
+}
+
ResourceLoadTiming* PerformanceResourceTiming::GetResourceLoadTiming() const {
return timing_.get();
}
diff --git a/chromium/third_party/blink/renderer/core/timing/performance_resource_timing.h b/chromium/third_party/blink/renderer/core/timing/performance_resource_timing.h
index 6a352ec2a87..5c8d447816e 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_resource_timing.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance_resource_timing.h
@@ -57,6 +57,9 @@ class CORE_EXPORT PerformanceResourceTiming : public PerformanceEntry {
return new PerformanceResourceTiming(info, time_origin, initiator_type);
}
+ AtomicString entryType() const override;
+ PerformanceEntryType EntryTypeEnum() const override;
+
// Related doc: https://goo.gl/uNecAj.
virtual AtomicString initiatorType() const;
AtomicString nextHopProtocol() const;
@@ -85,7 +88,6 @@ class CORE_EXPORT PerformanceResourceTiming : public PerformanceEntry {
// This constructor is for PerformanceNavigationTiming.
// Related doc: https://goo.gl/uNecAj.
PerformanceResourceTiming(const String& name,
- const String& entry_type,
TimeTicks time_origin,
const WebVector<WebServerTimingInfo>&);
virtual AtomicString AlpnNegotiatedProtocol() const;
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 87cc3e51a4e..19a80e7a71f 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_timing.cc
+++ b/chromium/third_party/blink/renderer/core/timing/performance_timing.cc
@@ -32,7 +32,6 @@
#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/css/css_timing.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/dom/document_timing.h"
@@ -49,16 +48,13 @@
// Legacy support for NT1(https://www.w3.org/TR/navigation-timing/).
namespace blink {
-static unsigned long long ToIntegerMilliseconds(double seconds) {
- DCHECK_GE(seconds, 0);
- double clamped_seconds = Performance::ClampTimeResolution(seconds);
+static unsigned long long ToIntegerMilliseconds(TimeDelta duration) {
+ DCHECK_GE(duration, TimeDelta());
+ double clamped_seconds =
+ Performance::ClampTimeResolution(duration.InSecondsF());
return static_cast<unsigned long long>(clamped_seconds * 1000.0);
}
-static double ToDoubleSeconds(unsigned long long integer_milliseconds) {
- return integer_milliseconds / 1000.0;
-}
-
PerformanceTiming::PerformanceTiming(LocalFrame* frame)
: DOMWindowClient(frame) {}
@@ -350,6 +346,15 @@ unsigned long long PerformanceTiming::FirstMeaningfulPaint() const {
return MonotonicTimeToIntegerMilliseconds(timing->FirstMeaningfulPaint());
}
+unsigned long long PerformanceTiming::FirstMeaningfulPaintCandidate() const {
+ const PaintTiming* timing = GetPaintTiming();
+ if (!timing)
+ return 0;
+
+ return MonotonicTimeToIntegerMilliseconds(
+ timing->FirstMeaningfulPaintCandidate());
+}
+
unsigned long long PerformanceTiming::PageInteractive() const {
InteractiveDetector* interactive_detector = GetInteractiveDetector();
if (!interactive_detector)
@@ -383,8 +388,7 @@ unsigned long long PerformanceTiming::FirstInputDelay() const {
if (!interactive_detector)
return 0;
- return ToIntegerMilliseconds(
- interactive_detector->GetFirstInputDelay().InSecondsF());
+ return ToIntegerMilliseconds(interactive_detector->GetFirstInputDelay());
}
unsigned long long PerformanceTiming::FirstInputTimestamp() const {
@@ -396,6 +400,23 @@ unsigned long long PerformanceTiming::FirstInputTimestamp() const {
interactive_detector->GetFirstInputTimestamp());
}
+unsigned long long PerformanceTiming::LongestInputDelay() const {
+ const InteractiveDetector* interactive_detector = GetInteractiveDetector();
+ if (!interactive_detector)
+ return 0;
+
+ return ToIntegerMilliseconds(interactive_detector->GetLongestInputDelay());
+}
+
+unsigned long long PerformanceTiming::LongestInputTimestamp() const {
+ const InteractiveDetector* interactive_detector = GetInteractiveDetector();
+ if (!interactive_detector)
+ return 0;
+
+ return MonotonicTimeToIntegerMilliseconds(
+ interactive_detector->GetLongestInputTimestamp());
+}
+
unsigned long long PerformanceTiming::ParseStart() const {
const DocumentParserTiming* timing = GetDocumentParserTiming();
if (!timing)
@@ -451,24 +472,6 @@ PerformanceTiming::ParseBlockedOnScriptExecutionFromDocumentWriteDuration()
timing->ParserBlockedOnScriptExecutionFromDocumentWriteDuration());
}
-unsigned long long PerformanceTiming::AuthorStyleSheetParseDurationBeforeFCP()
- const {
- const CSSTiming* timing = CssTiming();
- if (!timing)
- return 0;
-
- return ToIntegerMilliseconds(
- timing->AuthorStyleSheetParseDurationBeforeFCP());
-}
-
-unsigned long long PerformanceTiming::UpdateStyleDurationBeforeFCP() const {
- const CSSTiming* timing = CssTiming();
- if (!timing)
- return 0;
-
- return ToIntegerMilliseconds(timing->UpdateDurationBeforeFCP());
-}
-
DocumentLoader* PerformanceTiming::GetDocumentLoader() const {
if (!GetFrame())
return nullptr;
@@ -498,17 +501,6 @@ const PaintTiming* PerformanceTiming::GetPaintTiming() const {
return &PaintTiming::From(*document);
}
-const CSSTiming* PerformanceTiming::CssTiming() const {
- if (!GetFrame())
- return nullptr;
-
- Document* document = GetFrame()->GetDocument();
- if (!document)
- return nullptr;
-
- return &CSSTiming::From(*document);
-}
-
const DocumentParserTiming* PerformanceTiming::GetDocumentParserTiming() const {
if (!GetFrame())
return nullptr;
@@ -583,16 +575,6 @@ unsigned long long PerformanceTiming::MonotonicTimeToIntegerMilliseconds(
return ToIntegerMilliseconds(timing->MonotonicTimeToPseudoWallTime(time));
}
-TimeTicks PerformanceTiming::IntegerMillisecondsToMonotonicTime(
- unsigned long long integer_milliseconds) const {
- const DocumentLoadTiming* timing = GetDocumentLoadTiming();
- if (!timing)
- return TimeTicks();
-
- return timing->PseudoWallTimeToMonotonicTime(
- ToDoubleSeconds(integer_milliseconds));
-}
-
void PerformanceTiming::Trace(blink::Visitor* visitor) {
ScriptWrappable::Trace(visitor);
DOMWindowClient::Trace(visitor);
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 35b020306c0..1564890b224 100644
--- a/chromium/third_party/blink/renderer/core/timing/performance_timing.h
+++ b/chromium/third_party/blink/renderer/core/timing/performance_timing.h
@@ -100,6 +100,13 @@ class CORE_EXPORT PerformanceTiming final : public ScriptWrappable,
// The time of the first 'meaningful' paint, A meaningful paint is a paint
// where the page's primary content is visible.
unsigned long long FirstMeaningfulPaint() const;
+ // The time of the candidate of first 'meaningful' paint, A meaningful paint
+ // candidate indicates the first time we considered a paint to qualify as the
+ // potential first meaningful paint. But, be careful that it may be an
+ // optimistic (i.e., too early) estimate.
+ // TODO(crbug.com/848639): This function is exposed as an experiment, and if
+ // not useful, this function can be removed.
+ unsigned long long FirstMeaningfulPaintCandidate() const;
// The first time the page is considered 'interactive'. This is determined
// using heuristics based on main thread and network activity.
unsigned long long PageInteractive() const;
@@ -115,6 +122,12 @@ class CORE_EXPORT PerformanceTiming final : public ScriptWrappable,
unsigned long long FirstInputDelay() const;
// The timestamp of the event whose delay is reported by FirstInputDelay().
unsigned long long FirstInputTimestamp() const;
+ // The longest duration between the hardware timestamp and being queued on the
+ // main thread for the click, tap, key press, cancellable touchstart, or
+ // pointer down followed by a pointer up.
+ unsigned long long LongestInputDelay() const;
+ // The timestamp of the event whose delay is reported by LongestInputDelay().
+ unsigned long long LongestInputTimestamp() const;
unsigned long long ParseStart() const;
unsigned long long ParseStop() const;
@@ -123,15 +136,12 @@ class CORE_EXPORT PerformanceTiming final : public ScriptWrappable,
unsigned long long ParseBlockedOnScriptExecutionDuration() const;
unsigned long long ParseBlockedOnScriptExecutionFromDocumentWriteDuration()
const;
- unsigned long long AuthorStyleSheetParseDurationBeforeFCP() const;
- unsigned long long UpdateStyleDurationBeforeFCP() const;
ScriptValue toJSONForBinding(ScriptState*) const;
void Trace(blink::Visitor*) override;
unsigned long long MonotonicTimeToIntegerMilliseconds(TimeTicks) const;
- TimeTicks IntegerMillisecondsToMonotonicTime(unsigned long long) const;
private:
explicit PerformanceTiming(LocalFrame*);
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 68a478c0df0..50db0c4d6ae 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
@@ -26,11 +26,10 @@
#include "third_party/blink/renderer/core/timing/performance_user_timing.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/timing/performance.h"
#include "third_party/blink/renderer/core/timing/performance_mark.h"
#include "third_party/blink/renderer/core/timing/performance_measure.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
@@ -106,9 +105,10 @@ PerformanceMark* UserTiming::Mark(ScriptState* script_state,
ExceptionState& exception_state) {
if (GetRestrictedKeyMap().Contains(mark_name)) {
exception_state.ThrowDOMException(
- kSyntaxError, "'" + mark_name +
- "' is part of the PerformanceTiming interface, and "
- "cannot be used as a mark name.");
+ DOMExceptionCode::kSyntaxError,
+ "'" + mark_name +
+ "' is part of the PerformanceTiming interface, and "
+ "cannot be used as a mark name.");
return nullptr;
}
@@ -137,17 +137,19 @@ double UserTiming::FindExistingMarkStartTime(const String& mark_name,
(performance_->timing()->*(GetRestrictedKeyMap().at(mark_name)))());
if (!value) {
exception_state.ThrowDOMException(
- kInvalidAccessError, "'" + mark_name +
- "' is empty: either the event hasn't "
- "happened yet, or it would provide "
- "cross-origin timing information.");
+ DOMExceptionCode::kInvalidAccessError,
+ "'" + mark_name +
+ "' is empty: either the event hasn't "
+ "happened yet, or it would provide "
+ "cross-origin timing information.");
return 0.0;
}
return value - performance_->timing()->navigationStart();
}
exception_state.ThrowDOMException(
- kSyntaxError, "The mark '" + mark_name + "' does not exist.");
+ DOMExceptionCode::kSyntaxError,
+ "The mark '" + mark_name + "' does not exist.");
return 0.0;
}
diff --git a/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.cc b/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.cc
index 78a26f8804f..1308fd60626 100644
--- a/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.cc
+++ b/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.cc
@@ -17,7 +17,7 @@ TaskAttributionTiming::TaskAttributionTiming(String name,
double start_time,
double finish_time,
String script_url)
- : PerformanceEntry(name, "taskattribution", start_time, finish_time),
+ : PerformanceEntry(name, start_time, finish_time),
container_type_(container_type),
container_src_(container_src),
container_id_(container_id),
@@ -26,6 +26,14 @@ TaskAttributionTiming::TaskAttributionTiming(String name,
TaskAttributionTiming::~TaskAttributionTiming() = default;
+AtomicString TaskAttributionTiming::entryType() const {
+ return PerformanceEntry::TaskattributionKeyword();
+}
+
+PerformanceEntryType TaskAttributionTiming::EntryTypeEnum() const {
+ return PerformanceEntry::EntryType::kTaskAttribution;
+}
+
String TaskAttributionTiming::scriptURL() const {
return script_url_;
}
diff --git a/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.h b/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.h
index 59c2d79ef3d..875a306da22 100644
--- a/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.h
+++ b/chromium/third_party/blink/renderer/core/timing/task_attribution_timing.h
@@ -40,6 +40,10 @@ class TaskAttributionTiming final : public PerformanceEntry {
container_id, container_name, 0.0, 0.0,
g_empty_string);
}
+
+ AtomicString entryType() const override;
+ PerformanceEntryType EntryTypeEnum() const override;
+
String containerType() const;
String containerSrc() const;
String containerId() const;
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 d35340aa6c3..8e24fd6ef25 100644
--- a/chromium/third_party/blink/renderer/core/timing/window_performance.cc
+++ b/chromium/third_party/blink/renderer/core/timing/window_performance.cc
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/core/timing/window_performance.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_layer_tree_view.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
@@ -43,13 +44,16 @@
#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
+#include "third_party/blink/renderer/core/page/chrome_client.h"
#include "third_party/blink/renderer/core/timing/performance_event_timing.h"
#include "third_party/blink/renderer/core/timing/performance_timing.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
-static const double kLongTaskObserverThreshold = 0.05;
+static constexpr base::TimeDelta kLongTaskObserverThreshold =
+ base::TimeDelta::FromMilliseconds(50);
static const char kUnknownAttribution[] = "unknown";
static const char kAmbiguousAttribution[] = "multiple-contexts";
@@ -143,7 +147,21 @@ PerformanceNavigation* WindowPerformance::navigation() const {
}
MemoryInfo* WindowPerformance::memory() const {
- return MemoryInfo::Create();
+ // The performance.memory() API has been improved so that we report precise
+ // values when the process is locked to a site. The intent (which changed
+ // course over time about what changes would be implemented) can be found at
+ // https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/no00RdMnGio,
+ // and the relevant bug is https://crbug.com/807651.
+ return MemoryInfo::Create(Platform::Current()->IsLockedToSite()
+ ? MemoryInfo::Precision::Precise
+ : MemoryInfo::Precision::Bucketized);
+}
+
+bool WindowPerformance::shouldYield() const {
+ return Platform::Current()
+ ->CurrentThread()
+ ->Scheduler()
+ ->ShouldYieldForHighPriorityWork();
}
PerformanceNavigationTiming*
@@ -258,8 +276,8 @@ std::pair<String, DOMWindow*> WindowPerformance::SanitizedAttribution(
}
void WindowPerformance::ReportLongTask(
- double start_time,
- double end_time,
+ base::TimeTicks start_time,
+ base::TimeTicks end_time,
ExecutionContext* task_context,
bool has_multiple_contexts,
const SubTaskAttribution::EntriesVector& sub_task_attributions) {
@@ -273,15 +291,14 @@ void WindowPerformance::ReportLongTask(
if (!culprit_dom_window || !culprit_dom_window->GetFrame() ||
!culprit_dom_window->GetFrame()->DeprecatedLocalOwner()) {
AddLongTaskTiming(
- TimeTicksFromSeconds(start_time), TimeTicksFromSeconds(end_time),
- attribution.first, g_empty_string, g_empty_string, g_empty_string,
+ start_time, end_time, attribution.first, g_empty_string, g_empty_string,
+ g_empty_string,
IsSameOrigin(attribution.first) ? sub_task_attributions : empty_vector);
} else {
HTMLFrameOwnerElement* frame_owner =
culprit_dom_window->GetFrame()->DeprecatedLocalOwner();
AddLongTaskTiming(
- TimeTicksFromSeconds(start_time), TimeTicksFromSeconds(end_time),
- attribution.first,
+ start_time, end_time, attribution.first,
GetFrameAttribute(frame_owner, HTMLNames::srcAttr, false),
GetFrameAttribute(frame_owner, HTMLNames::idAttr, false),
GetFrameAttribute(frame_owner, HTMLNames::nameAttr, true),
@@ -304,7 +321,7 @@ void WindowPerformance::RegisterEventTiming(String event_type,
TimeTicks processing_start,
TimeTicks processing_end,
bool cancelable) {
- DCHECK(OriginTrials::eventTimingEnabled(GetExecutionContext()));
+ DCHECK(OriginTrials::EventTimingEnabled(GetExecutionContext()));
DCHECK(!start_time.is_null());
DCHECK(!processing_start.is_null());
@@ -334,7 +351,7 @@ void WindowPerformance::RegisterEventTiming(String event_type,
void WindowPerformance::ReportEventTimings(WebLayerTreeView::SwapResult result,
TimeTicks timestamp) {
- DCHECK(OriginTrials::eventTimingEnabled(GetExecutionContext()));
+ DCHECK(OriginTrials::EventTimingEnabled(GetExecutionContext()));
DOMHighResTimeStamp end_time = MonotonicTimeToDOMHighResTimeStamp(timestamp);
for (const auto& entry : event_timings_) {
@@ -369,7 +386,7 @@ void WindowPerformance::ReportEventTimings(WebLayerTreeView::SwapResult result,
void WindowPerformance::DispatchFirstInputTiming(
PerformanceEventTiming* entry) {
- DCHECK(OriginTrials::eventTimingEnabled(GetExecutionContext()));
+ DCHECK(OriginTrials::EventTimingEnabled(GetExecutionContext()));
first_input_detected_ = true;
if (!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 977e12b521d..6cb0beb5b32 100644
--- a/chromium/third_party/blink/renderer/core/timing/window_performance.h
+++ b/chromium/third_party/blink/renderer/core/timing/window_performance.h
@@ -32,6 +32,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_WINDOW_PERFORMANCE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_WINDOW_PERFORMANCE_H_
+#include "third_party/blink/public/platform/web_layer_tree_view.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/frame/performance_monitor.h"
@@ -62,6 +63,8 @@ class CORE_EXPORT WindowPerformance final : public Performance,
MemoryInfo* memory() const override;
+ bool shouldYield() const override;
+
void UpdateLongTaskInstrumentation() override;
bool ObservingEventTimingEntries();
@@ -77,7 +80,6 @@ class CORE_EXPORT WindowPerformance final : public Performance,
bool cancelable);
void Trace(blink::Visitor*) override;
- using Performance::TraceWrappers;
private:
explicit WindowPerformance(LocalDOMWindow*);
@@ -91,8 +93,8 @@ class CORE_EXPORT WindowPerformance final : public Performance,
// PerformanceMonitor::Client implementation.
void ReportLongTask(
- double start_time,
- double end_time,
+ base::TimeTicks start_time,
+ base::TimeTicks end_time,
ExecutionContext* task_context,
bool has_multiple_contexts,
const SubTaskAttribution::EntriesVector& sub_task_attributions) override;
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 192509f50cb..181b469ecc1 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
@@ -3,50 +3,31 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/timing/window_performance.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_double.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_double_or_performance_measure_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/core/dom/document_init.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/performance_monitor.h"
#include "third_party/blink/renderer/core/loader/document_load_timing.h"
#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
#include "third_party/blink/renderer/core/timing/dom_window_performance.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/wtf/scoped_mock_clock.h"
namespace blink {
-static const int kTimeOrigin = 500;
+namespace {
TimeTicks GetTimeOrigin() {
- return TimeTicks() + TimeDelta::FromSeconds(kTimeOrigin);
+ return TimeTicks() + TimeDelta::FromSeconds(500);
}
-namespace {
-
-class FakeTimer {
- public:
- FakeTimer(double init_time) {
- g_mock_time = init_time;
- original_time_function_ =
- WTF::SetTimeFunctionsForTesting(GetMockTimeInSeconds);
- }
-
- ~FakeTimer() { WTF::SetTimeFunctionsForTesting(original_time_function_); }
-
- static double GetMockTimeInSeconds() { return g_mock_time; }
-
- void AdvanceTimer(double duration) { g_mock_time += duration; }
-
- private:
- TimeFunction original_time_function_;
- static double g_mock_time;
-};
-
-double FakeTimer::g_mock_time = 1000.;
-
} // namespace
class WindowPerformanceTest : public testing::Test {
@@ -78,7 +59,8 @@ class WindowPerformanceTest : public testing::Test {
auto* monitor = GetFrame()->GetPerformanceMonitor();
monitor->WillExecuteScript(GetDocument());
monitor->DidExecuteScript();
- monitor->DidProcessTask(0, 1);
+ monitor->DidProcessTask(
+ base::TimeTicks(), base::TimeTicks() + base::TimeDelta::FromSeconds(1));
}
void SimulateSwapPromise(TimeTicks timestamp) {
@@ -210,15 +192,16 @@ TEST(PerformanceLifetimeTest, SurviveContextSwitch) {
// order. (http://crbug.com/767560)
TEST_F(WindowPerformanceTest, EnsureEntryListOrder) {
V8TestingScope scope;
- FakeTimer timer(kTimeOrigin);
+ WTF::ScopedMockClock clock;
+ clock.Advance(GetTimeOrigin() - TimeTicks());
DummyExceptionStateForTesting exception_state;
- timer.AdvanceTimer(2);
+ clock.Advance(TimeDelta::FromSeconds(2));
for (int i = 0; i < 8; i++) {
performance_->mark(scope.GetScriptState(), String::Number(i),
exception_state);
}
- timer.AdvanceTimer(2);
+ clock.Advance(TimeDelta::FromSeconds(2));
for (int i = 8; i < 17; i++) {
performance_->mark(scope.GetScriptState(), String::Number(i),
exception_state);
@@ -239,12 +222,12 @@ TEST_F(WindowPerformanceTest, EventTimingBeforeOnLoad) {
ScopedEventTimingForTest event_timing(true);
EXPECT_TRUE(page_holder_->GetFrame().Loader().GetDocumentLoader());
- TimeTicks start_time = TimeTicksFromSeconds(kTimeOrigin + 1.1);
- TimeTicks processing_start = TimeTicksFromSeconds(kTimeOrigin + 3.3);
- TimeTicks processing_end = TimeTicksFromSeconds(kTimeOrigin + 3.8);
+ TimeTicks start_time = GetTimeOrigin() + TimeDelta::FromSecondsD(1.1);
+ TimeTicks processing_start = GetTimeOrigin() + TimeDelta::FromSecondsD(3.3);
+ TimeTicks processing_end = GetTimeOrigin() + TimeDelta::FromSecondsD(3.8);
performance_->RegisterEventTiming("click", start_time, processing_start,
processing_end, false);
- TimeTicks swap_time = TimeTicksFromSeconds(kTimeOrigin + 6.0);
+ TimeTicks swap_time = GetTimeOrigin() + TimeDelta::FromSecondsD(6.0);
SimulateSwapPromise(swap_time);
EXPECT_EQ(1u, performance_->getEntriesByName("click", "event").size());
performance_->clearEventTimings();
@@ -273,18 +256,22 @@ TEST_F(WindowPerformanceTest, EventTimingBeforeOnLoad) {
TEST_F(WindowPerformanceTest, EventTimingDuration) {
ScopedEventTimingForTest event_timing(true);
- TimeTicks start_time = TimeTicksFromSeconds(kTimeOrigin + 1.0);
- TimeTicks processing_start = TimeTicksFromSeconds(kTimeOrigin + 1.001);
- TimeTicks processing_end = TimeTicksFromSeconds(kTimeOrigin + 1.002);
+ TimeTicks start_time = GetTimeOrigin() + TimeDelta::FromMilliseconds(1000);
+ TimeTicks processing_start =
+ GetTimeOrigin() + TimeDelta::FromMilliseconds(1001);
+ TimeTicks processing_end =
+ GetTimeOrigin() + TimeDelta::FromMilliseconds(1002);
performance_->RegisterEventTiming("click", start_time, processing_start,
processing_end, false);
- TimeTicks short_swap_time = TimeTicksFromSeconds(kTimeOrigin + 1.003);
+ TimeTicks short_swap_time =
+ GetTimeOrigin() + TimeDelta::FromMilliseconds(1003);
SimulateSwapPromise(short_swap_time);
EXPECT_EQ(0u, performance_->getEntriesByName("click", "event").size());
performance_->RegisterEventTiming("click", start_time, processing_start,
processing_end, true);
- TimeTicks long_swap_time = TimeTicksFromSeconds(kTimeOrigin + 1.1);
+ TimeTicks long_swap_time =
+ GetTimeOrigin() + TimeDelta::FromMilliseconds(1100);
SimulateSwapPromise(long_swap_time);
EXPECT_EQ(1u, performance_->getEntriesByName("click", "event").size());
@@ -302,14 +289,14 @@ TEST_F(WindowPerformanceTest, MultipleEventsSameSwap) {
size_t num_events = 10;
for (size_t i = 0; i < num_events; ++i) {
- TimeTicks start_time = TimeTicksFromSeconds(kTimeOrigin + i);
- TimeTicks processing_start = TimeTicksFromSeconds(kTimeOrigin + i + 0.1);
- TimeTicks processing_end = TimeTicksFromSeconds(kTimeOrigin + i + 0.2);
+ TimeTicks start_time = GetTimeOrigin() + TimeDelta::FromSeconds(i);
+ TimeTicks processing_start = start_time + TimeDelta::FromMilliseconds(100);
+ TimeTicks processing_end = start_time + TimeDelta::FromMilliseconds(200);
performance_->RegisterEventTiming("click", start_time, processing_start,
processing_end, false);
EXPECT_EQ(0u, performance_->getEntriesByName("click", "event").size());
}
- TimeTicks swap_time = TimeTicksFromSeconds(kTimeOrigin + num_events);
+ TimeTicks swap_time = GetTimeOrigin() + TimeDelta::FromSeconds(num_events);
SimulateSwapPromise(swap_time);
EXPECT_EQ(num_events,
performance_->getEntriesByName("click", "event").size());
diff --git a/chromium/third_party/blink/renderer/core/timing/worker_global_scope_performance.cc b/chromium/third_party/blink/renderer/core/timing/worker_global_scope_performance.cc
index 0a0344a52d2..e62c1995c95 100644
--- a/chromium/third_party/blink/renderer/core/timing/worker_global_scope_performance.cc
+++ b/chromium/third_party/blink/renderer/core/timing/worker_global_scope_performance.cc
@@ -71,10 +71,4 @@ void WorkerGlobalScopePerformance::Trace(blink::Visitor* visitor) {
Supplement<WorkerGlobalScope>::Trace(visitor);
}
-void WorkerGlobalScopePerformance::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(performance_);
- Supplement<WorkerGlobalScope>::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/timing/worker_global_scope_performance.h b/chromium/third_party/blink/renderer/core/timing/worker_global_scope_performance.h
index 06ce8e348ae..ee297ebab9a 100644
--- a/chromium/third_party/blink/renderer/core/timing/worker_global_scope_performance.h
+++ b/chromium/third_party/blink/renderer/core/timing/worker_global_scope_performance.h
@@ -54,7 +54,6 @@ class CORE_EXPORT WorkerGlobalScopePerformance final
static WorkerPerformance* performance(WorkerGlobalScope&);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
explicit WorkerGlobalScopePerformance(WorkerGlobalScope&);
diff --git a/chromium/third_party/blink/renderer/core/timing/worker_performance.cc b/chromium/third_party/blink/renderer/core/timing/worker_performance.cc
index e953de5c5fc..2d3968f10b0 100644
--- a/chromium/third_party/blink/renderer/core/timing/worker_performance.cc
+++ b/chromium/third_party/blink/renderer/core/timing/worker_performance.cc
@@ -41,7 +41,7 @@
namespace blink {
WorkerPerformance::WorkerPerformance(WorkerGlobalScope* context)
- : Performance(TimeTicksFromSeconds(context->TimeOrigin()),
+ : Performance(context->TimeOrigin(),
context->GetTaskRunner(TaskType::kPerformanceTimeline)),
execution_context_(context) {}
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/BUILD.gn b/chromium/third_party/blink/renderer/core/trustedtypes/BUILD.gn
new file mode 100644
index 00000000000..36b86dcfbd9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/BUILD.gn
@@ -0,0 +1,16 @@
+# Copyright 2017 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/blink/renderer/core/core.gni")
+
+blink_core_sources("trustedtypes") {
+ sources = [
+ "trusted_html.cc",
+ "trusted_html.h",
+ "trusted_script_url.cc",
+ "trusted_script_url.h",
+ "trusted_url.cc",
+ "trusted_url.h",
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.cc b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.cc
new file mode 100644
index 00000000000..2b1cf3fa061
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.cc
@@ -0,0 +1,37 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/trustedtypes/trusted_html.h"
+
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+
+namespace blink {
+
+TrustedHTML::TrustedHTML(const String& html) : html_(html) {}
+
+TrustedHTML* TrustedHTML::escape(ScriptState* script_state,
+ const String& html) {
+ // TODO(mkwst): This could be hugely optimized by scanning the string for any
+ // of the interesting characters to see whether we need to do any replacement
+ // at all, and by replacing all the characters in a single pass.
+ String escapedHTML(html);
+ escapedHTML.Replace("&", "&amp;")
+ .Replace("<", "&lt;")
+ .Replace(">", "&gt;")
+ .Replace("\"", "&quot;")
+ .Replace("'", "&#39;");
+
+ return TrustedHTML::unsafelyCreate(script_state, escapedHTML);
+}
+
+TrustedHTML* TrustedHTML::unsafelyCreate(ScriptState* script_state,
+ const String& html) {
+ return TrustedHTML::Create(html);
+}
+
+String TrustedHTML::toString() const {
+ return html_;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.h b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.h
new file mode 100644
index 00000000000..f9cf7a8b22d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.h
@@ -0,0 +1,38 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_HTML_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_HTML_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#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/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class ScriptState;
+
+class CORE_EXPORT TrustedHTML final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static TrustedHTML* Create(const String& html) {
+ return new TrustedHTML(html);
+ }
+
+ // CredentialsContainer.idl
+ String toString() const;
+ static TrustedHTML* escape(ScriptState*, const String& html);
+ static TrustedHTML* unsafelyCreate(ScriptState*, const String& html);
+
+ private:
+ TrustedHTML(const String& html);
+
+ const String html_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_HTML_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_html.idl b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.idl
index 6ddc306a698..6ddc306a698 100644
--- a/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_html.idl
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_html.idl
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.cc b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.cc
new file mode 100644
index 00000000000..bfc4cd9fa80
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.cc
@@ -0,0 +1,24 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/trustedtypes/trusted_script_url.h"
+
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+
+namespace blink {
+
+TrustedScriptURL::TrustedScriptURL(const KURL& url) : url_(url) {}
+
+TrustedScriptURL* TrustedScriptURL::unsafelyCreate(ScriptState* script_state,
+ const String& url) {
+ return TrustedScriptURL::Create(
+ ExecutionContext::From(script_state)->CompleteURL(url));
+}
+
+String TrustedScriptURL::toString() const {
+ return url_.GetString();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.h b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.h
new file mode 100644
index 00000000000..708400da697
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.h
@@ -0,0 +1,38 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_SCRIPT_URL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_SCRIPT_URL_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#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/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class ScriptState;
+
+class CORE_EXPORT TrustedScriptURL final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static TrustedScriptURL* Create(const KURL& url) {
+ return new TrustedScriptURL(url);
+ }
+
+ // TrustedScriptURL.idl
+ String toString() const;
+ static TrustedScriptURL* unsafelyCreate(ScriptState*, const String& url);
+
+ private:
+ TrustedScriptURL(const KURL&);
+
+ KURL url_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_SCRIPT_URL_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.idl b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.idl
index 67fff8671ea..67fff8671ea 100644
--- a/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_script_url.idl
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_script_url.idl
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_url.cc b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_url.cc
new file mode 100644
index 00000000000..aca934aa777
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_url.cc
@@ -0,0 +1,33 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/trustedtypes/trusted_url.h"
+
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+
+namespace blink {
+
+TrustedURL::TrustedURL(const KURL& url) : url_(url) {}
+
+TrustedURL* TrustedURL::create(ScriptState* script_state, const String& url) {
+ KURL result(ExecutionContext::From(script_state)->CompleteURL(url));
+
+ if (!result.IsValid() || !result.ProtocolIsInHTTPFamily())
+ result = KURL("about:invalid");
+
+ return TrustedURL::Create(result);
+}
+
+TrustedURL* TrustedURL::unsafelyCreate(ScriptState* script_state,
+ const String& url) {
+ return TrustedURL::Create(
+ ExecutionContext::From(script_state)->CompleteURL(url));
+}
+
+String TrustedURL::toString() const {
+ return url_.GetString();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/trustedtypes/trusted_url.h b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_url.h
new file mode 100644
index 00000000000..09fcec5de6e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_url.h
@@ -0,0 +1,37 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_URL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_URL_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#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/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class ScriptState;
+
+class CORE_EXPORT TrustedURL final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static TrustedURL* Create(const KURL& url) { return new TrustedURL(url); }
+
+ // TrustedURL.idl
+ String toString() const;
+ static TrustedURL* create(ScriptState*, const String& url);
+ static TrustedURL* unsafelyCreate(ScriptState*, const String& url);
+
+ private:
+ TrustedURL(const KURL&);
+
+ KURL url_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_CORE_TRUSTEDTYPES_TRUSTED_URL_H_
diff --git a/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_url.idl b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_url.idl
index d2f24eff594..d2f24eff594 100644
--- a/chromium/third_party/blink/renderer/core/dom/trustedtypes/trusted_url.idl
+++ b/chromium/third_party/blink/renderer/core/trustedtypes/trusted_url.idl
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.cc b/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.cc
index 3693d886573..e4e9c0a05eb 100644
--- a/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.cc
+++ b/chromium/third_party/blink/renderer/core/typed_arrays/dom_array_buffer.cc
@@ -90,12 +90,10 @@ DOMArrayBuffer* DOMArrayBuffer::Create(
if (UNLIKELY(!data))
OOM_CRASH();
- shared_buffer->ForEachSegment([&data](const char* segment,
- size_t segment_size,
- size_t segment_offset) -> bool {
- memcpy(data + segment_offset, segment, segment_size);
- return true;
- });
+ for (const auto& span : *shared_buffer) {
+ memcpy(data, span.data(), span.size());
+ data += span.size();
+ }
return Create(ArrayBuffer::Create(contents));
}
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/dom_data_view.cc b/chromium/third_party/blink/renderer/core/typed_arrays/dom_data_view.cc
index 23070b76899..ab73dabef99 100644
--- a/chromium/third_party/blink/renderer/core/typed_arrays/dom_data_view.cc
+++ b/chromium/third_party/blink/renderer/core/typed_arrays/dom_data_view.cc
@@ -4,9 +4,9 @@
#include "third_party/blink/renderer/core/typed_arrays/dom_data_view.h"
+#include "base/numerics/checked_math.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
#include "third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_view.h"
namespace blink {
@@ -18,7 +18,7 @@ class DataView final : public ArrayBufferView {
static scoped_refptr<DataView> Create(ArrayBuffer* buffer,
unsigned byte_offset,
unsigned byte_length) {
- CheckedNumeric<uint32_t> checked_max = byte_offset;
+ base::CheckedNumeric<uint32_t> checked_max = byte_offset;
checked_max += byte_length;
CHECK_LE(checked_max.ValueOrDie(), buffer->ByteLength());
return base::AdoptRef(new DataView(buffer, byte_offset, byte_length));
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/dom_typed_array.h b/chromium/third_party/blink/renderer/core/typed_arrays/dom_typed_array.h
index 56384ecb124..8b720409f99 100644
--- a/chromium/third_party/blink/renderer/core/typed_arrays/dom_typed_array.h
+++ b/chromium/third_party/blink/renderer/core/typed_arrays/dom_typed_array.h
@@ -25,8 +25,7 @@
namespace blink {
template <typename WTFTypedArray, typename V8TypedArray>
-class CORE_TEMPLATE_CLASS_EXPORT DOMTypedArray final
- : public DOMArrayBufferView {
+class DOMTypedArray final : public DOMArrayBufferView {
typedef DOMTypedArray<WTFTypedArray, V8TypedArray> ThisType;
DECLARE_WRAPPERTYPEINFO();
diff --git a/chromium/third_party/blink/renderer/core/typed_arrays/typed_flexible_array_buffer_view.h b/chromium/third_party/blink/renderer/core/typed_arrays/typed_flexible_array_buffer_view.h
index 79ddfe6e7bc..cf0fd532e00 100644
--- a/chromium/third_party/blink/renderer/core/typed_arrays/typed_flexible_array_buffer_view.h
+++ b/chromium/third_party/blink/renderer/core/typed_arrays/typed_flexible_array_buffer_view.h
@@ -12,8 +12,7 @@
namespace blink {
template <typename WTFTypedArray>
-class CORE_TEMPLATE_CLASS_EXPORT TypedFlexibleArrayBufferView final
- : public FlexibleArrayBufferView {
+class TypedFlexibleArrayBufferView final : public FlexibleArrayBufferView {
STACK_ALLOCATED();
public:
diff --git a/chromium/third_party/blink/renderer/core/url/dom_url.cc b/chromium/third_party/blink/renderer/core/url/dom_url.cc
index b83d652f165..23defdf7bc9 100644
--- a/chromium/third_party/blink/renderer/core/url/dom_url.cc
+++ b/chromium/third_party/blink/renderer/core/url/dom_url.cc
@@ -27,12 +27,10 @@
#include "third_party/blink/renderer/core/url/dom_url.h"
#include "base/auto_reset.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fileapi/public_url_manager.h"
#include "third_party/blink/renderer/core/url/url_search_params.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
namespace blink {
@@ -57,6 +55,10 @@ void DOMURL::Trace(blink::Visitor* visitor) {
ScriptWrappable::Trace(visitor);
}
+void DOMURL::setHref(const String& value) {
+ SetInput(value);
+}
+
void DOMURL::SetInput(const String& value) {
KURL url(BlankURL(), value);
if (url.IsValid()) {
diff --git a/chromium/third_party/blink/renderer/core/url/dom_url.h b/chromium/third_party/blink/renderer/core/url/dom_url.h
index 3a7d578c6b1..56d52e56cba 100644
--- a/chromium/third_party/blink/renderer/core/url/dom_url.h
+++ b/chromium/third_party/blink/renderer/core/url/dom_url.h
@@ -70,6 +70,8 @@ class DOMURL final : public ScriptWrappable, public DOMURLUtils {
void Trace(blink::Visitor*) override;
+ void setHref(const String&);
+
private:
friend class URLSearchParams;
DOMURL(const String& url, const KURL& base, ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/core/url/dom_url_utils.cc b/chromium/third_party/blink/renderer/core/url/dom_url_utils.cc
index e597624e9fe..928053a4236 100644
--- a/chromium/third_party/blink/renderer/core/url/dom_url_utils.cc
+++ b/chromium/third_party/blink/renderer/core/url/dom_url_utils.cc
@@ -26,14 +26,35 @@
#include "third_party/blink/renderer/core/url/dom_url_utils.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/bindings/core/v8/usv_string_or_trusted_url.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_url.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/weborigin/known_ports.h"
namespace blink {
DOMURLUtils::~DOMURLUtils() = default;
-void DOMURLUtils::setHref(const String& value) {
+void DOMURLUtils::setHref(ScriptState* script_state,
+ const USVStringOrTrustedURL& stringOrUrl,
+ ExceptionState& exception_state) {
+ DCHECK(stringOrUrl.IsUSVString() ||
+ RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
+ DCHECK(!stringOrUrl.IsNull());
+
+ if (ExecutionContext::From(script_state)->IsDocument()) {
+ Document* document = ToDocument((ExecutionContext::From(script_state)));
+ if (!stringOrUrl.IsTrustedURL() && document->RequireTrustedTypes()) {
+ exception_state.ThrowTypeError(
+ "This document requires `TrustedURL` assignment.");
+ return;
+ }
+ }
+
+ String value = stringOrUrl.IsUSVString()
+ ? stringOrUrl.GetAsUSVString()
+ : stringOrUrl.GetAsTrustedURL()->toString();
SetInput(value);
}
diff --git a/chromium/third_party/blink/renderer/core/url/dom_url_utils.h b/chromium/third_party/blink/renderer/core/url/dom_url_utils.h
index 75f00cea919..2432755144a 100644
--- a/chromium/third_party/blink/renderer/core/url/dom_url_utils.h
+++ b/chromium/third_party/blink/renderer/core/url/dom_url_utils.h
@@ -33,7 +33,10 @@
namespace blink {
+class ExceptionState;
+class ScriptState;
class KURL;
+class USVStringOrTrustedURL;
class CORE_EXPORT DOMURLUtils : public DOMURLUtilsReadOnly {
public:
@@ -41,7 +44,7 @@ class CORE_EXPORT DOMURLUtils : public DOMURLUtilsReadOnly {
virtual void SetInput(const String&) = 0;
~DOMURLUtils() override;
- void setHref(const String&);
+ void setHref(ScriptState*, const USVStringOrTrustedURL&, ExceptionState&);
void setProtocol(const String&);
void setUsername(const String&);
diff --git a/chromium/third_party/blink/renderer/core/url/dom_url_utils_read_only.cc b/chromium/third_party/blink/renderer/core/url/dom_url_utils_read_only.cc
index 5a08967f494..fdb51e4aaf9 100644
--- a/chromium/third_party/blink/renderer/core/url/dom_url_utils_read_only.cc
+++ b/chromium/third_party/blink/renderer/core/url/dom_url_utils_read_only.cc
@@ -26,18 +26,24 @@
#include "third_party/blink/renderer/core/url/dom_url_utils_read_only.h"
+#include "third_party/blink/renderer/bindings/core/v8/usv_string_or_trusted_url.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_url.h"
#include "third_party/blink/renderer/platform/weborigin/known_ports.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
namespace blink {
-String DOMURLUtilsReadOnly::href() {
+String DOMURLUtilsReadOnly::href(ScriptState*, ExceptionState&) {
const KURL& kurl = Url();
if (kurl.IsNull())
return Input();
return kurl.GetString();
}
+void DOMURLUtilsReadOnly::href(ScriptState*, USVStringOrTrustedURL& result) {
+ result.SetUSVString(href());
+}
+
String DOMURLUtilsReadOnly::origin(const KURL& kurl) {
if (kurl.IsNull())
return "";
diff --git a/chromium/third_party/blink/renderer/core/url/dom_url_utils_read_only.h b/chromium/third_party/blink/renderer/core/url/dom_url_utils_read_only.h
index 7ca57a573a6..6544b7186d8 100644
--- a/chromium/third_party/blink/renderer/core/url/dom_url_utils_read_only.h
+++ b/chromium/third_party/blink/renderer/core/url/dom_url_utils_read_only.h
@@ -28,18 +28,24 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_URL_DOM_URL_UTILS_READ_ONLY_H_
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
namespace blink {
+class ExceptionState;
+class ScriptState;
+class USVStringOrTrustedURL;
+
class CORE_EXPORT DOMURLUtilsReadOnly {
public:
virtual KURL Url() const = 0;
virtual String Input() const = 0;
virtual ~DOMURLUtilsReadOnly() = default;
- String href();
+ void href(ScriptState*, USVStringOrTrustedURL&);
+ String href(ScriptState* = nullptr, ExceptionState& = ASSERT_NO_EXCEPTION);
static String origin(const KURL&);
String origin() { return origin(Url()); }
diff --git a/chromium/third_party/blink/renderer/core/url/url_search_params.cc b/chromium/third_party/blink/renderer/core/url/url_search_params.cc
index 363ed4ae87b..799fcd463f8 100644
--- a/chromium/third_party/blink/renderer/core/url/url_search_params.cc
+++ b/chromium/third_party/blink/renderer/core/url/url_search_params.cc
@@ -6,7 +6,9 @@
#include <algorithm>
#include <utility>
+
#include "third_party/blink/renderer/core/url/dom_url.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
#include "third_party/blink/renderer/platform/network/form_data_encoder.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
diff --git a/chromium/third_party/blink/renderer/core/workers/BUILD.gn b/chromium/third_party/blink/renderer/core/workers/BUILD.gn
index be6581749d7..57a956328fd 100644
--- a/chromium/third_party/blink/renderer/core/workers/BUILD.gn
+++ b/chromium/third_party/blink/renderer/core/workers/BUILD.gn
@@ -62,8 +62,6 @@ blink_core_sources("workers") {
"worker_clients.h",
"worker_content_settings_client.cc",
"worker_content_settings_client.h",
- "worker_event_queue.cc",
- "worker_event_queue.h",
"worker_global_scope.cc",
"worker_global_scope.h",
"worker_inspector_proxy.cc",
@@ -75,8 +73,6 @@ blink_core_sources("workers") {
"worker_navigator.h",
"worker_or_worklet_global_scope.cc",
"worker_or_worklet_global_scope.h",
- "worker_or_worklet_module_fetch_coordinator_proxy.cc",
- "worker_or_worklet_module_fetch_coordinator_proxy.h",
"worker_reporting_proxy.h",
"worker_settings.cc",
"worker_settings.h",
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 ba89191cb7c..9ca539e4faf 100644
--- a/chromium/third_party/blink/renderer/core/workers/abstract_worker.cc
+++ b/chromium/third_party/blink/renderer/core/workers/abstract_worker.cc
@@ -30,10 +30,9 @@
#include "third_party/blink/renderer/core/workers/abstract_worker.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.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/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
namespace blink {
@@ -50,7 +49,7 @@ KURL AbstractWorker::ResolveURL(ExecutionContext* execution_context,
WebURLRequest::RequestContext request_context) {
KURL script_url = execution_context->CompleteURL(url);
if (!script_url.IsValid()) {
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"'" + url + "' is not a valid URL.");
return KURL();
}
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 30bff6756a8..a7ddbf3cee1 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 "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
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 7168deb5562..a403a854b17 100644
--- a/chromium/third_party/blink/renderer/core/workers/dedicated_worker.cc
+++ b/chromium/third_party/blink/renderer/core/workers/dedicated_worker.cc
@@ -10,11 +10,10 @@
#include "services/service_manager/public/mojom/interface_provider.mojom-blink.h"
#include "third_party/blink/public/platform/dedicated_worker_factory.mojom-blink.h"
#include "third_party/blink/public/platform/web_content_settings_client.h"
-#include "third_party/blink/public/web/web_frame_client.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/public/platform/web_layer_tree_view.h"
+#include "third_party/blink/public/web/web_local_frame_client.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/exception_code.h"
#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/use_counter.h"
@@ -23,12 +22,14 @@
#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/probe/core_probes.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/core/script/script.h"
#include "third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h"
#include "third_party/blink/renderer/core/workers/worker_classic_script_loader.h"
#include "third_party/blink/renderer/core/workers/worker_clients.h"
#include "third_party/blink/renderer/core/workers/worker_content_settings_client.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.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/weborigin/security_policy.h"
@@ -58,7 +59,7 @@ DedicatedWorker* DedicatedWorker::Create(ExecutionContext* context,
DCHECK(context->IsContextThread());
UseCounter::Count(context, WebFeature::kWorkerStart);
if (context->IsContextDestroyed()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The context provided is invalid.");
return nullptr;
}
@@ -83,7 +84,7 @@ DedicatedWorker* DedicatedWorker::Create(ExecutionContext* context,
}
if (context->IsWorkerGlobalScope())
- ToWorkerGlobalScope(context)->EnsureFetcher();
+ UseCounter::Count(context, WebFeature::kNestedDedicatedWorker);
DedicatedWorker* worker = new DedicatedWorker(context, script_url, options);
worker->Start();
@@ -124,6 +125,7 @@ void DedicatedWorker::postMessage(ScriptState* script_state,
std::move(channels), stack_id);
}
+// https://html.spec.whatwg.org/multipage/workers.html#worker-processing-model
void DedicatedWorker::Start() {
DCHECK(GetExecutionContext()->IsContextThread());
@@ -131,7 +133,11 @@ void DedicatedWorker::Start() {
ThreadDebugger::From(ToIsolate(GetExecutionContext()))
->StoreCurrentStackTrace("Worker Created");
+ // Step 13: "Obtain script by switching on the value of options's type
+ // member:"
if (options_.type() == "classic") {
+ // "classic: Fetch a classic worker script given url, outside settings,
+ // destination, and inside settings."
network::mojom::FetchRequestMode fetch_request_mode =
network::mojom::FetchRequestMode::kSameOrigin;
network::mojom::FetchCredentialsMode fetch_credentials_mode =
@@ -152,12 +158,18 @@ void DedicatedWorker::Start() {
return;
}
if (options_.type() == "module") {
+ // "module: Fetch a module worker script graph given url, outside settings,
+ // destination, the value of the credentials member of options, and inside
+ // settings."
+ //
// Specify empty source code here because module scripts will be fetched on
// the worker thread as opposed to classic scripts that are fetched on the
// main thread.
- context_proxy_->StartWorkerGlobalScope(CreateGlobalScopeCreationParams(),
- options_, script_url_, stack_id,
- String() /* source_code */);
+ auto* outside_settings_object =
+ new FetchClientSettingsObjectSnapshot(*GetExecutionContext());
+ context_proxy_->StartWorkerGlobalScope(
+ CreateGlobalScopeCreationParams(), options_, script_url_,
+ outside_settings_object, stack_id, String() /* source_code */);
return;
}
NOTREACHED() << "Invalid type: " << options_.type();
@@ -174,14 +186,16 @@ BeginFrameProviderParams DedicatedWorker::CreateBeginFrameProviderParams() {
// won't be initialized. If that's the case, the Worker will initialize it by
// itself later.
BeginFrameProviderParams begin_frame_provider_params;
- if (GetExecutionContext()->IsDocument()) {
+ if (GetExecutionContext() && GetExecutionContext()->IsDocument()) {
LocalFrame* frame = ToDocument(GetExecutionContext())->GetFrame();
WebLayerTreeView* layer_tree_view = nullptr;
- if (frame) {
+ if (frame && frame->GetPage()) {
layer_tree_view =
frame->GetPage()->GetChromeClient().GetWebLayerTreeView(frame);
- begin_frame_provider_params.parent_frame_sink_id =
- layer_tree_view->GetFrameSinkId();
+ if (layer_tree_view) {
+ begin_frame_provider_params.parent_frame_sink_id =
+ layer_tree_view->GetFrameSinkId();
+ }
}
begin_frame_provider_params.frame_sink_id =
Platform::Current()->GenerateFrameSinkId();
@@ -249,8 +263,11 @@ void DedicatedWorker::OnFinished(const v8_inspector::V8StackTraceId& stack_id) {
std::unique_ptr<GlobalScopeCreationParams> creation_params =
CreateGlobalScopeCreationParams();
creation_params->referrer_policy = referrer_policy;
+ auto* outside_settings_object =
+ new FetchClientSettingsObjectSnapshot(*GetExecutionContext());
context_proxy_->StartWorkerGlobalScope(
- std::move(creation_params), options_, script_url_, stack_id,
+ std::move(creation_params), options_, script_url_,
+ outside_settings_object, stack_id,
classic_script_loader_->SourceText());
probe::scriptImported(GetExecutionContext(),
classic_script_loader_->Identifier(),
@@ -280,7 +297,7 @@ DedicatedWorker::CreateGlobalScopeCreationParams() {
: ScriptType::kModule;
return std::make_unique<GlobalScopeCreationParams>(
script_url_, script_type, GetExecutionContext()->UserAgent(),
- GetExecutionContext()->GetContentSecurityPolicy()->Headers().get(),
+ GetExecutionContext()->GetContentSecurityPolicy()->Headers(),
kReferrerPolicyDefault, GetExecutionContext()->GetSecurityOrigin(),
GetExecutionContext()->IsSecureContext(), CreateWorkerClients(),
GetExecutionContext()->GetSecurityContext().AddressSpace(),
@@ -289,7 +306,8 @@ DedicatedWorker::CreateGlobalScopeCreationParams() {
nullptr /* worklet_module_responses_map */,
ConnectToWorkerInterfaceProvider(GetExecutionContext(),
SecurityOrigin::Create(script_url_)),
- CreateBeginFrameProviderParams());
+ CreateBeginFrameProviderParams(),
+ GetExecutionContext()->GetSecurityContext().GetFeaturePolicy());
}
const AtomicString& DedicatedWorker::InterfaceName() const {
diff --git a/chromium/third_party/blink/renderer/core/workers/dedicated_worker.h b/chromium/third_party/blink/renderer/core/workers/dedicated_worker.h
index 1971d80c61f..4e7dea55c4d 100644
--- a/chromium/third_party/blink/renderer/core/workers/dedicated_worker.h
+++ b/chromium/third_party/blink/renderer/core/workers/dedicated_worker.h
@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/core/workers/abstract_worker.h"
#include "third_party/blink/renderer/core/workers/worker_options.h"
#include "third_party/blink/renderer/platform/graphics/begin_frame_provider.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
namespace v8_inspector {
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 4702f033006..58166d3552e 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
@@ -31,19 +31,20 @@
#include "third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h"
#include <memory>
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.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/thread_debugger.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h"
#include "third_party/blink/renderer/core/workers/dedicated_worker_thread.h"
#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_module_tree_client.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
@@ -51,7 +52,7 @@ namespace blink {
DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope(
std::unique_ptr<GlobalScopeCreationParams> creation_params,
DedicatedWorkerThread* thread,
- double time_origin)
+ base::TimeTicks time_origin)
: WorkerGlobalScope(std::move(creation_params), thread, time_origin) {}
DedicatedWorkerGlobalScope::~DedicatedWorkerGlobalScope() = default;
@@ -63,16 +64,21 @@ const AtomicString& DedicatedWorkerGlobalScope::InterfaceName() const {
// https://html.spec.whatwg.org/multipage/workers.html#worker-processing-model
void DedicatedWorkerGlobalScope::ImportModuleScript(
const KURL& module_url_record,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
network::mojom::FetchCredentialsMode credentials_mode) {
// Step 12: "Let destination be "sharedworker" if is shared is true, and
// "worker" otherwise."
WebURLRequest::RequestContext destination =
WebURLRequest::kRequestContextWorker;
+
Modulator* modulator = Modulator::From(ScriptController()->GetScriptState());
+
// Step 13: "... Fetch a module worker script graph given url, outside
// settings, destination, the value of the credentials member of options, and
// inside settings."
- FetchModuleScript(module_url_record, destination, credentials_mode,
+ FetchModuleScript(module_url_record, outside_settings_object, destination,
+ credentials_mode,
+ ModuleScriptCustomFetchType::kWorkerConstructor,
new WorkerModuleTreeClient(modulator));
}
diff --git a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h
index 472221dc2c3..645565126ed 100644
--- a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h
+++ b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h
@@ -50,7 +50,7 @@ class CORE_EXPORT DedicatedWorkerGlobalScope final : public WorkerGlobalScope {
public:
DedicatedWorkerGlobalScope(std::unique_ptr<GlobalScopeCreationParams>,
DedicatedWorkerThread*,
- double time_origin);
+ base::TimeTicks time_origin);
~DedicatedWorkerGlobalScope() override;
bool IsDedicatedWorkerGlobalScope() const override { return true; }
@@ -59,8 +59,10 @@ class CORE_EXPORT DedicatedWorkerGlobalScope final : public WorkerGlobalScope {
const AtomicString& InterfaceName() const override;
// WorkerGlobalScope
- void ImportModuleScript(const KURL& module_url_record,
- network::mojom::FetchCredentialsMode) override;
+ void ImportModuleScript(
+ const KURL& module_url_record,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
+ network::mojom::FetchCredentialsMode) override;
void postMessage(ScriptState*,
scoped_refptr<SerializedScriptValue>,
diff --git a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc
index bd2f74ad691..4e5a9048649 100644
--- a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc
+++ b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc
@@ -46,6 +46,7 @@ void DedicatedWorkerMessagingProxy::StartWorkerGlobalScope(
std::unique_ptr<GlobalScopeCreationParams> creation_params,
const WorkerOptions& options,
const KURL& script_url,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
const v8_inspector::V8StackTraceId& stack_id,
const String& source_code) {
DCHECK(IsParentContextThread());
@@ -67,7 +68,8 @@ void DedicatedWorkerMessagingProxy::StartWorkerGlobalScope(
bool result =
Request::ParseCredentialsMode(options.credentials(), &credentials_mode);
DCHECK(result);
- GetWorkerThread()->ImportModuleScript(script_url, credentials_mode);
+ GetWorkerThread()->ImportModuleScript(script_url, outside_settings_object,
+ credentials_mode);
} else {
NOTREACHED();
}
diff --git a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h
index 0a639b8a528..7fcb3fd5eeb 100644
--- a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h
+++ b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h
@@ -25,6 +25,7 @@ namespace blink {
class DedicatedWorker;
class DedicatedWorkerObjectProxy;
+class FetchClientSettingsObjectSnapshot;
class SerializedScriptValue;
class WorkerOptions;
@@ -38,11 +39,13 @@ class CORE_EXPORT DedicatedWorkerMessagingProxy
~DedicatedWorkerMessagingProxy() override;
// These methods should only be used on the parent context thread.
- void StartWorkerGlobalScope(std::unique_ptr<GlobalScopeCreationParams>,
- const WorkerOptions&,
- const KURL& script_url,
- const v8_inspector::V8StackTraceId&,
- const String& source_code);
+ void StartWorkerGlobalScope(
+ std::unique_ptr<GlobalScopeCreationParams>,
+ const WorkerOptions&,
+ const KURL& script_url,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
+ const v8_inspector::V8StackTraceId&,
+ const String& source_code);
void PostMessageToWorkerGlobalScope(scoped_refptr<SerializedScriptValue>,
Vector<MessagePortChannel>,
const v8_inspector::V8StackTraceId&);
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 0f6e231978f..424710beba0 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
@@ -32,7 +32,7 @@ class DedicatedWorkerThreadForTest final : public DedicatedWorkerThread {
DedicatedWorkerThreadForTest(DedicatedWorkerObjectProxy& worker_object_proxy)
: DedicatedWorkerThread(nullptr /* ThreadableLoadingContext */,
worker_object_proxy) {
- worker_backing_thread_ = WorkerBackingThread::CreateForTest(
+ worker_backing_thread_ = WorkerBackingThread::Create(
WebThreadCreationParams(WebThreadType::kTestThread));
}
@@ -125,15 +125,13 @@ class DedicatedWorkerMessagingProxyForTest
void StartWithSourceCode(const String& source) {
KURL script_url("http://fake.url/");
security_origin_ = SecurityOrigin::Create(script_url);
- auto headers = std::make_unique<Vector<CSPHeaderAndType>>();
- CSPHeaderAndType header_and_type("contentSecurityPolicy",
- kContentSecurityPolicyHeaderTypeReport);
- headers->push_back(header_and_type);
+ Vector<CSPHeaderAndType> headers{
+ {"contentSecurityPolicy", kContentSecurityPolicyHeaderTypeReport}};
auto worker_settings = std::make_unique<WorkerSettings>(
ToDocument(GetExecutionContext())->GetSettings());
InitializeWorkerThread(
std::make_unique<GlobalScopeCreationParams>(
- script_url, ScriptType::kClassic, "fake user agent", headers.get(),
+ script_url, ScriptType::kClassic, "fake user agent", headers,
kReferrerPolicyDefault, security_origin_.get(),
false /* starter_secure_context */, nullptr /* worker_clients */,
mojom::IPAddressSpace::kLocal, nullptr /* origin_trial_tokens */,
@@ -219,6 +217,7 @@ TEST_F(DedicatedWorkerTest, PendingActivity_NoActivityAfterContextDestroyed) {
}
TEST_F(DedicatedWorkerTest, UseCounter) {
+ Page::InsertOrdinaryPageForTesting(&GetPage());
const String source_code = "// Do nothing";
WorkerMessagingProxy()->StartWithSourceCode(source_code);
diff --git a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_thread.cc b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_thread.cc
index 44f3bc11493..595cb4f3085 100644
--- a/chromium/third_party/blink/renderer/core/workers/dedicated_worker_thread.cc
+++ b/chromium/third_party/blink/renderer/core/workers/dedicated_worker_thread.cc
@@ -41,20 +41,18 @@
#include "third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h"
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
#include "third_party/blink/renderer/core/workers/worker_backing_thread.h"
+#include "third_party/blink/renderer/platform/web_thread_supporting_gc.h"
namespace blink {
namespace {
-FrameScheduler* GetFrameScheduler(ThreadableLoadingContext* loading_context) {
+FrameOrWorkerScheduler* GetFrameOrWorkerScheduler(
+ ThreadableLoadingContext* loading_context) {
// |loading_context| can be null in unittests.
if (!loading_context)
return nullptr;
- if (!loading_context->GetExecutionContext()->IsDocument())
- return nullptr;
- return ToDocument(loading_context->GetExecutionContext())
- ->GetFrame()
- ->GetFrameScheduler();
+ return loading_context->GetExecutionContext()->GetScheduler();
}
} // namespace
@@ -72,7 +70,8 @@ DedicatedWorkerThread::DedicatedWorkerThread(
: WorkerThread(loading_context, worker_object_proxy),
worker_backing_thread_(WorkerBackingThread::Create(
WebThreadCreationParams(GetThreadType())
- .SetFrameScheduler(GetFrameScheduler(loading_context)))),
+ .SetFrameOrWorkerScheduler(
+ GetFrameOrWorkerScheduler(loading_context)))),
worker_object_proxy_(worker_object_proxy) {}
DedicatedWorkerThread::~DedicatedWorkerThread() = default;
diff --git a/chromium/third_party/blink/renderer/core/workers/execution_context_worker_registry.cc b/chromium/third_party/blink/renderer/core/workers/execution_context_worker_registry.cc
index ceb667f15fb..ad7da07b350 100644
--- a/chromium/third_party/blink/renderer/core/workers/execution_context_worker_registry.cc
+++ b/chromium/third_party/blink/renderer/core/workers/execution_context_worker_registry.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/core/workers/execution_context_worker_registry.h"
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/core/workers/global_scope_creation_params.cc b/chromium/third_party/blink/renderer/core/workers/global_scope_creation_params.cc
index 590bf269c83..e95d125e0db 100644
--- a/chromium/third_party/blink/renderer/core/workers/global_scope_creation_params.cc
+++ b/chromium/third_party/blink/renderer/core/workers/global_scope_creation_params.cc
@@ -13,7 +13,7 @@ GlobalScopeCreationParams::GlobalScopeCreationParams(
const KURL& script_url,
ScriptType script_type,
const String& user_agent,
- const Vector<CSPHeaderAndType>* content_security_policy_parsed_headers,
+ const Vector<CSPHeaderAndType>& content_security_policy_parsed_headers,
ReferrerPolicy referrer_policy,
const SecurityOrigin* starter_origin,
bool starter_secure_context,
@@ -26,7 +26,8 @@ GlobalScopeCreationParams::GlobalScopeCreationParams(
WorkletModuleResponsesMap* module_responses_map,
service_manager::mojom::blink::InterfaceProviderPtrInfo
interface_provider_info,
- BeginFrameProviderParams begin_frame_provider_params)
+ BeginFrameProviderParams begin_frame_provider_params,
+ const FeaturePolicy* parent_feature_policy)
: script_url(script_url.Copy()),
script_type(script_type),
user_agent(user_agent.IsolatedCopy()),
@@ -40,15 +41,18 @@ GlobalScopeCreationParams::GlobalScopeCreationParams(
v8_cache_options(v8_cache_options),
module_responses_map(module_responses_map),
interface_provider(std::move(interface_provider_info)),
- begin_frame_provider_params(std::move(begin_frame_provider_params)) {
- this->content_security_policy_parsed_headers =
- std::make_unique<Vector<CSPHeaderAndType>>();
- if (content_security_policy_parsed_headers) {
- for (const auto& header : *content_security_policy_parsed_headers) {
- CSPHeaderAndType copied_header(header.first.IsolatedCopy(),
- header.second);
- this->content_security_policy_parsed_headers->push_back(copied_header);
- }
+ begin_frame_provider_params(std::move(begin_frame_provider_params)),
+ // At the moment, workers do not support their container policy being set,
+ // so it will just be an empty ParsedFeaturePolicy for now.
+ worker_feature_policy(FeaturePolicy::CreateFromParentPolicy(
+ parent_feature_policy,
+ ParsedFeaturePolicy() /* container_policy */,
+ starter_origin->ToUrlOrigin())) {
+ this->content_security_policy_parsed_headers.ReserveInitialCapacity(
+ content_security_policy_parsed_headers.size());
+ for (const auto& header : content_security_policy_parsed_headers) {
+ this->content_security_policy_parsed_headers.emplace_back(
+ header.first.IsolatedCopy(), header.second);
}
this->origin_trial_tokens = std::make_unique<Vector<String>>();
diff --git a/chromium/third_party/blink/renderer/core/workers/global_scope_creation_params.h b/chromium/third_party/blink/renderer/core/workers/global_scope_creation_params.h
index 47320bd7741..8a1c3c8bec9 100644
--- a/chromium/third_party/blink/renderer/core/workers/global_scope_creation_params.h
+++ b/chromium/third_party/blink/renderer/core/workers/global_scope_creation_params.h
@@ -10,6 +10,7 @@
#include "base/optional.h"
#include "base/unguessable_token.h"
#include "services/service_manager/public/mojom/interface_provider.mojom-blink.h"
+#include "third_party/blink/public/common/feature_policy/feature_policy.h"
#include "third_party/blink/public/mojom/net/ip_address_space.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_cache_options.h"
#include "third_party/blink/renderer/core/core_export.h"
@@ -39,7 +40,7 @@ struct CORE_EXPORT GlobalScopeCreationParams final {
const KURL& script_url,
ScriptType script_type,
const String& user_agent,
- const Vector<CSPHeaderAndType>* content_security_policy_parsed_headers,
+ const Vector<CSPHeaderAndType>& content_security_policy_parsed_headers,
ReferrerPolicy referrer_policy,
const SecurityOrigin*,
bool starter_secure_context,
@@ -51,7 +52,8 @@ struct CORE_EXPORT GlobalScopeCreationParams final {
V8CacheOptions,
WorkletModuleResponsesMap*,
service_manager::mojom::blink::InterfaceProviderPtrInfo = {},
- BeginFrameProviderParams begin_frame_provider_params = {});
+ BeginFrameProviderParams begin_frame_provider_params = {},
+ const FeaturePolicy* parent_feature_policy = nullptr);
~GlobalScopeCreationParams() = default;
@@ -63,8 +65,7 @@ struct CORE_EXPORT GlobalScopeCreationParams final {
// |content_security_policy_raw_headers| are mutually exclusive.
// |content_security_policy_parsed_headers| is an empty vector
// when |content_security_policy_raw_headers| is set.
- std::unique_ptr<Vector<CSPHeaderAndType>>
- content_security_policy_parsed_headers;
+ Vector<CSPHeaderAndType> content_security_policy_parsed_headers;
base::Optional<ContentSecurityPolicyResponseHeaders>
content_security_policy_raw_headers;
@@ -119,6 +120,8 @@ struct CORE_EXPORT GlobalScopeCreationParams final {
BeginFrameProviderParams begin_frame_provider_params;
+ std::unique_ptr<FeaturePolicy> worker_feature_policy;
+
DISALLOW_COPY_AND_ASSIGN(GlobalScopeCreationParams);
};
diff --git a/chromium/third_party/blink/renderer/core/workers/main_thread_worklet_global_scope.cc b/chromium/third_party/blink/renderer/core/workers/main_thread_worklet_global_scope.cc
index 6d4c202ba62..9ba18f0db64 100644
--- a/chromium/third_party/blink/renderer/core/workers/main_thread_worklet_global_scope.cc
+++ b/chromium/third_party/blink/renderer/core/workers/main_thread_worklet_global_scope.cc
@@ -29,7 +29,9 @@ MainThreadWorkletGlobalScope::MainThreadWorkletGlobalScope(
frame->GetFrameScheduler()->GetTaskRunner(TaskType::kInternalLoading),
frame->GetFrameScheduler()->GetTaskRunner(
TaskType::kInternalLoading)),
- ContextClient(frame) {}
+ ContextClient(frame) {
+ BindContentSecurityPolicyToExecutionContext();
+}
MainThreadWorkletGlobalScope::~MainThreadWorkletGlobalScope() = default;
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 13650e540fd..12ede974d2e 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
@@ -46,6 +46,9 @@ class MainThreadWorkletReportingProxyForTest final
class MainThreadWorkletTest : public PageTestBase {
public:
void SetUp() override {
+ SetUpScope("script-src 'self' https://allowed.example.com");
+ }
+ void SetUpScope(const String& csp_header) {
PageTestBase::SetUp(IntSize());
Document* document = &GetDocument();
document->SetURL(KURL("https://example.com/"));
@@ -54,8 +57,7 @@ class MainThreadWorkletTest : public PageTestBase {
// Set up the CSP for Document before starting MainThreadWorklet because
// MainThreadWorklet inherits the owner Document's CSP.
ContentSecurityPolicy* csp = ContentSecurityPolicy::Create();
- csp->DidReceiveHeader("script-src 'self' https://allowed.example.com",
- kContentSecurityPolicyHeaderTypeEnforce,
+ csp->DidReceiveHeader(csp_header, kContentSecurityPolicyHeaderTypeEnforce,
kContentSecurityPolicyHeaderSourceHTTP);
document->InitContentSecurityPolicy(csp);
@@ -63,13 +65,12 @@ class MainThreadWorkletTest : public PageTestBase {
std::make_unique<MainThreadWorkletReportingProxyForTest>(document);
auto creation_params = std::make_unique<GlobalScopeCreationParams>(
document->Url(), ScriptType::kModule, document->UserAgent(),
- document->GetContentSecurityPolicy()->Headers().get(),
+ document->GetContentSecurityPolicy()->Headers(),
document->GetReferrerPolicy(), document->GetSecurityOrigin(),
document->IsSecureContext(), nullptr /* worker_clients */,
document->AddressSpace(), OriginTrialContext::GetTokens(document).get(),
base::UnguessableToken::Create(), nullptr /* worker_settings */,
- kV8CacheOptionsDefault,
- new WorkletModuleResponsesMap(document->Fetcher()));
+ kV8CacheOptionsDefault, new WorkletModuleResponsesMap);
global_scope_ = new MainThreadWorkletGlobalScope(
&GetFrame(), std::move(creation_params), *reporting_proxy_);
}
@@ -81,19 +82,23 @@ class MainThreadWorkletTest : public PageTestBase {
Persistent<MainThreadWorkletGlobalScope> global_scope_;
};
+class MainThreadWorkletInvalidCSPTest : public MainThreadWorkletTest {
+ public:
+ void SetUp() override { SetUpScope("invalid-csp"); }
+};
+
TEST_F(MainThreadWorkletTest, SecurityOrigin) {
// The SecurityOrigin for a worklet should be a unique opaque origin, while
// the owner Document's SecurityOrigin shouldn't.
- EXPECT_TRUE(global_scope_->GetSecurityOrigin()->IsUnique());
- EXPECT_FALSE(global_scope_->DocumentSecurityOrigin()->IsUnique());
+ EXPECT_TRUE(global_scope_->GetSecurityOrigin()->IsOpaque());
+ EXPECT_FALSE(global_scope_->DocumentSecurityOrigin()->IsOpaque());
}
TEST_F(MainThreadWorkletTest, ContentSecurityPolicy) {
ContentSecurityPolicy* csp = global_scope_->GetContentSecurityPolicy();
- // The "script-src 'self'" directive is specified but the Worklet has a
- // unique opaque origin, so this should not be allowed.
- EXPECT_FALSE(csp->AllowScriptFromSource(
+ // The "script-src 'self'" directive allows this.
+ EXPECT_TRUE(csp->AllowScriptFromSource(
global_scope_->Url(), String(), IntegrityMetadataSet(), kParserInserted));
// The "script-src https://allowed.example.com" should allow this.
@@ -107,6 +112,7 @@ TEST_F(MainThreadWorkletTest, ContentSecurityPolicy) {
}
TEST_F(MainThreadWorkletTest, UseCounter) {
+ Page::InsertOrdinaryPageForTesting(&GetPage());
// This feature is randomly selected.
const WebFeature kFeature1 = WebFeature::kRequestFileSystem;
@@ -140,4 +146,16 @@ TEST_F(MainThreadWorkletTest, TaskRunner) {
EXPECT_TRUE(task_runner->RunsTasksInCurrentSequence());
}
+// Test that having an invalid CSP does not result in an exception.
+// See bugs: 844383,844317
+TEST_F(MainThreadWorkletInvalidCSPTest, InvalidContentSecurityPolicy) {
+ ContentSecurityPolicy* csp = global_scope_->GetContentSecurityPolicy();
+
+ // At this point check that the CSP that was set is indeed invalid.
+ EXPECT_EQ(1ul, csp->Headers().size());
+ EXPECT_EQ("invalid-csp", csp->Headers().at(0).first);
+ EXPECT_EQ(kContentSecurityPolicyHeaderTypeEnforce,
+ csp->Headers().at(0).second);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/workers/parent_execution_context_task_runners.cc b/chromium/third_party/blink/renderer/core/workers/parent_execution_context_task_runners.cc
index 8c1c6e4036c..55b9ed99733 100644
--- a/chromium/third_party/blink/renderer/core/workers/parent_execution_context_task_runners.cc
+++ b/chromium/third_party/blink/renderer/core/workers/parent_execution_context_task_runners.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
@@ -29,10 +30,10 @@ ParentExecutionContextTaskRunners::ParentExecutionContextTaskRunners(
// For now we only support very limited task types. Sort in the TaskType enum
// value order.
for (auto type : {TaskType::kNetworking, TaskType::kPostedMessage,
- TaskType::kInternalDefault, TaskType::kInternalLoading,
- TaskType::kInternalTest, TaskType::kInternalMedia,
- TaskType::kInternalInspector, TaskType::kInternalWorker,
- TaskType::kUnthrottled}) {
+ TaskType::kWorkerAnimation, TaskType::kInternalDefault,
+ TaskType::kInternalLoading, TaskType::kInternalTest,
+ TaskType::kInternalMedia, TaskType::kInternalInspector,
+ TaskType::kInternalWorker}) {
auto task_runner =
context ? context->GetTaskRunner(type)
: Platform::Current()->CurrentThread()->GetTaskRunner();
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 ef16e0b69a9..17614f03dd9 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker.cc
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker.cc
@@ -31,8 +31,9 @@
#include "third_party/blink/renderer/core/workers/shared_worker.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#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/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
@@ -40,6 +41,7 @@
#include "third_party/blink/renderer/core/messaging/message_port.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/core/workers/shared_worker_repository_client.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -80,9 +82,16 @@ SharedWorker* SharedWorker::Create(ExecutionContext* context,
if (script_url.IsEmpty())
return nullptr;
+ mojom::blink::BlobURLTokenPtr blob_url_token;
+ if (script_url.ProtocolIs("blob") && BlobUtils::MojoBlobURLsEnabled()) {
+ document->GetPublicURLManager().Resolve(script_url,
+ MakeRequest(&blob_url_token));
+ }
+
if (document->GetFrame()->Client()->GetSharedWorkerRepositoryClient()) {
document->GetFrame()->Client()->GetSharedWorkerRepositoryClient()->Connect(
- worker, std::move(remote_port), script_url, name);
+ worker, std::move(remote_port), script_url, std::move(blob_url_token),
+ name);
}
return worker;
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 5abae313a2d..553c01a237d 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
@@ -52,7 +52,7 @@ SharedWorkerGlobalScope::SharedWorkerGlobalScope(
const String& name,
std::unique_ptr<GlobalScopeCreationParams> creation_params,
SharedWorkerThread* thread,
- double time_origin)
+ base::TimeTicks time_origin)
: WorkerGlobalScope(std::move(creation_params), thread, time_origin),
name_(name) {}
@@ -65,6 +65,7 @@ const AtomicString& SharedWorkerGlobalScope::InterfaceName() const {
// https://html.spec.whatwg.org/multipage/workers.html#worker-processing-model
void SharedWorkerGlobalScope::ImportModuleScript(
const KURL& module_url_record,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
network::mojom::FetchCredentialsMode credentials_mode) {
// Step 12: "Let destination be "sharedworker" if is shared is true, and
// "worker" otherwise."
diff --git a/chromium/third_party/blink/renderer/core/workers/shared_worker_global_scope.h b/chromium/third_party/blink/renderer/core/workers/shared_worker_global_scope.h
index 372277d576c..da59f4c05fc 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker_global_scope.h
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker_global_scope.h
@@ -49,7 +49,7 @@ class SharedWorkerGlobalScope final : public WorkerGlobalScope {
SharedWorkerGlobalScope(const String& name,
std::unique_ptr<GlobalScopeCreationParams>,
SharedWorkerThread*,
- double time_origin);
+ base::TimeTicks time_origin);
~SharedWorkerGlobalScope() override;
bool IsSharedWorkerGlobalScope() const override { return true; }
@@ -58,8 +58,10 @@ class SharedWorkerGlobalScope final : public WorkerGlobalScope {
const AtomicString& InterfaceName() const override;
// WorkerGlobalScope
- void ImportModuleScript(const KURL& module_url_record,
- network::mojom::FetchCredentialsMode) override;
+ void ImportModuleScript(
+ const KURL& module_url_record,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
+ network::mojom::FetchCredentialsMode) override;
// Setters/Getters for attributes in SharedWorkerGlobalScope.idl
DEFINE_ATTRIBUTE_EVENT_LISTENER(connect);
diff --git a/chromium/third_party/blink/renderer/core/workers/shared_worker_repository_client.h b/chromium/third_party/blink/renderer/core/workers/shared_worker_repository_client.h
index 9219d270215..16f7c62d1a8 100644
--- a/chromium/third_party/blink/renderer/core/workers/shared_worker_repository_client.h
+++ b/chromium/third_party/blink/renderer/core/workers/shared_worker_repository_client.h
@@ -32,6 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_SHARED_WORKER_REPOSITORY_CLIENT_H_
#include "base/macros.h"
+#include "third_party/blink/public/mojom/blob/blob_url_store.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/wtf/forward.h"
@@ -53,6 +54,7 @@ class CORE_EXPORT SharedWorkerRepositoryClient {
virtual void Connect(SharedWorker*,
MessagePortChannel,
const KURL&,
+ mojom::blink::BlobURLTokenPtr,
const String& name) = 0;
virtual void DocumentDetached(Document*) = 0;
diff --git a/chromium/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.cc b/chromium/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.cc
index 6dcbd6fb1d3..f77c4affa4d 100644
--- a/chromium/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.cc
+++ b/chromium/third_party/blink/renderer/core/workers/threaded_messaging_proxy_base.cc
@@ -7,7 +7,7 @@
#include "base/synchronization/waitable_event.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_worker_fetch_context.h"
-#include "third_party/blink/public/web/web_frame_client.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
diff --git a/chromium/third_party/blink/renderer/core/workers/threaded_worklet_global_scope.cc b/chromium/third_party/blink/renderer/core/workers/threaded_worklet_global_scope.cc
index edec77d9543..f00aca81556 100644
--- a/chromium/third_party/blink/renderer/core/workers/threaded_worklet_global_scope.cc
+++ b/chromium/third_party/blink/renderer/core/workers/threaded_worklet_global_scope.cc
@@ -31,7 +31,9 @@ ThreadedWorkletGlobalScope::ThreadedWorkletGlobalScope(
thread->GetParentExecutionContextTaskRunners()->Get(
TaskType::kInternalLoading),
thread->GetTaskRunner(TaskType::kInternalLoading)),
- thread_(thread) {}
+ thread_(thread) {
+ BindContentSecurityPolicyToExecutionContext();
+}
ThreadedWorkletGlobalScope::~ThreadedWorkletGlobalScope() {
DCHECK(!thread_);
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 eb3614cd0f0..260f497dba5 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
@@ -10,12 +10,16 @@
#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_frame_client.h"
#include "third_party/blink/renderer/core/inspector/thread_debugger.h"
+#include "third_party/blink/renderer/core/loader/worker_fetch_context.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/core/script/script.h"
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
#include "third_party/blink/renderer/core/workers/threaded_worklet_object_proxy.h"
#include "third_party/blink/renderer/core/workers/worker_clients.h"
+#include "third_party/blink/renderer/core/workers/worker_content_settings_client.h"
#include "third_party/blink/renderer/core/workers/worker_inspector_proxy.h"
#include "third_party/blink/renderer/core/workers/worklet_global_scope.h"
#include "third_party/blink/renderer/core/workers/worklet_module_responses_map.h"
@@ -43,10 +47,17 @@ void ThreadedWorkletMessagingProxy::Initialize(
ContentSecurityPolicy* csp = document->GetContentSecurityPolicy();
DCHECK(csp);
+ ProvideWorkerFetchContextToWorker(
+ worker_clients,
+ document->GetFrame()->Client()->CreateWorkerFetchContext());
+ ProvideContentSettingsClientToWorker(
+ worker_clients,
+ document->GetFrame()->Client()->CreateWorkerContentSettingsClient());
+
auto global_scope_creation_params =
std::make_unique<GlobalScopeCreationParams>(
document->Url(), ScriptType::kModule, document->UserAgent(),
- csp->Headers().get(), document->GetReferrerPolicy(),
+ csp->Headers(), document->GetReferrerPolicy(),
document->GetSecurityOrigin(), document->IsSecureContext(),
worker_clients, document->AddressSpace(),
OriginTrialContext::GetTokens(document).get(),
@@ -67,6 +78,7 @@ void ThreadedWorkletMessagingProxy::Trace(blink::Visitor* visitor) {
void ThreadedWorkletMessagingProxy::FetchAndInvokeScript(
const KURL& module_url_record,
network::mojom::FetchCredentialsMode credentials_mode,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
WorkletPendingTasks* pending_tasks) {
DCHECK(IsMainThread());
@@ -75,6 +87,7 @@ void ThreadedWorkletMessagingProxy::FetchAndInvokeScript(
CrossThreadBind(&ThreadedWorkletObjectProxy::FetchAndInvokeScript,
CrossThreadUnretained(worklet_object_proxy_.get()),
module_url_record, credentials_mode,
+ WTF::Passed(outside_settings_object->CopyData()),
std::move(outside_settings_task_runner),
WrapCrossThreadPersistent(pending_tasks),
CrossThreadUnretained(GetWorkerThread())));
diff --git a/chromium/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.h b/chromium/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.h
index af0638207fd..caad225d996 100644
--- a/chromium/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.h
+++ b/chromium/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.h
@@ -26,6 +26,7 @@ class CORE_EXPORT ThreadedWorkletMessagingProxy
void FetchAndInvokeScript(
const KURL& module_url_record,
network::mojom::FetchCredentialsMode,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
WorkletPendingTasks*) final;
void WorkletObjectDestroyed() final;
diff --git a/chromium/third_party/blink/renderer/core/workers/threaded_worklet_object_proxy.cc b/chromium/third_party/blink/renderer/core/workers/threaded_worklet_object_proxy.cc
index e1b6347276a..cd380d77bbf 100644
--- a/chromium/third_party/blink/renderer/core/workers/threaded_worklet_object_proxy.cc
+++ b/chromium/third_party/blink/renderer/core/workers/threaded_worklet_object_proxy.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/memory/ptr_util.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/core/workers/threaded_worklet_global_scope.h"
#include "third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h"
@@ -27,14 +28,17 @@ ThreadedWorkletObjectProxy::~ThreadedWorkletObjectProxy() = default;
void ThreadedWorkletObjectProxy::FetchAndInvokeScript(
const KURL& module_url_record,
network::mojom::FetchCredentialsMode credentials_mode,
+ std::unique_ptr<CrossThreadFetchClientSettingsObjectData>
+ outside_settings_object,
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
WorkletPendingTasks* pending_tasks,
WorkerThread* worker_thread) {
ThreadedWorkletGlobalScope* global_scope =
ToThreadedWorkletGlobalScope(worker_thread->GlobalScope());
- global_scope->FetchAndInvokeScript(module_url_record, credentials_mode,
- std::move(outside_settings_task_runner),
- pending_tasks);
+ global_scope->FetchAndInvokeScript(
+ module_url_record, credentials_mode,
+ new FetchClientSettingsObjectSnapshot(std::move(outside_settings_object)),
+ std::move(outside_settings_task_runner), pending_tasks);
}
ThreadedWorkletObjectProxy::ThreadedWorkletObjectProxy(
diff --git a/chromium/third_party/blink/renderer/core/workers/threaded_worklet_object_proxy.h b/chromium/third_party/blink/renderer/core/workers/threaded_worklet_object_proxy.h
index e3744930e53..0e900e27171 100644
--- a/chromium/third_party/blink/renderer/core/workers/threaded_worklet_object_proxy.h
+++ b/chromium/third_party/blink/renderer/core/workers/threaded_worklet_object_proxy.h
@@ -17,6 +17,7 @@ namespace blink {
class ThreadedWorkletMessagingProxy;
class WorkletPendingTasks;
class WorkerThread;
+struct CrossThreadFetchClientSettingsObjectData;
// A proxy to talk to the parent worker object. See class comments on
// ThreadedObjectProxyBase.h for lifetime of this class etc.
@@ -35,6 +36,8 @@ class CORE_EXPORT ThreadedWorkletObjectProxy : public ThreadedObjectProxyBase {
void FetchAndInvokeScript(
const KURL& module_url_record,
network::mojom::FetchCredentialsMode,
+ std::unique_ptr<CrossThreadFetchClientSettingsObjectData>
+ outside_settings_object,
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
WorkletPendingTasks*,
WorkerThread*);
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 a253f0ca8f2..28a13f09d22 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
@@ -86,8 +86,8 @@ class ThreadedWorkletThreadForTest : public WorkerThread {
WorkletGlobalScope* global_scope = ToWorkletGlobalScope(GlobalScope());
// The SecurityOrigin for a worklet should be a unique opaque origin, while
// the owner Document's SecurityOrigin shouldn't.
- EXPECT_TRUE(global_scope->GetSecurityOrigin()->IsUnique());
- EXPECT_FALSE(global_scope->DocumentSecurityOrigin()->IsUnique());
+ EXPECT_TRUE(global_scope->GetSecurityOrigin()->IsOpaque());
+ EXPECT_FALSE(global_scope->DocumentSecurityOrigin()->IsOpaque());
PostCrossThreadTask(
*GetParentExecutionContextTaskRunners()->Get(TaskType::kInternalTest),
FROM_HERE, CrossThreadBind(&test::ExitRunLoop));
@@ -97,11 +97,10 @@ class ThreadedWorkletThreadForTest : public WorkerThread {
EXPECT_TRUE(IsCurrentThread());
ContentSecurityPolicy* csp = GlobalScope()->GetContentSecurityPolicy();
- // The "script-src 'self'" directive is specified but the Worklet has a
- // unique opaque origin, so this should not be allowed.
- EXPECT_FALSE(csp->AllowScriptFromSource(GlobalScope()->Url(), String(),
- IntegrityMetadataSet(),
- kParserInserted));
+ // The "script-src 'self'" directive allows this.
+ EXPECT_TRUE(csp->AllowScriptFromSource(GlobalScope()->Url(), String(),
+ IntegrityMetadataSet(),
+ kParserInserted));
// The "script-src https://allowed.example.com" should allow this.
EXPECT_TRUE(csp->AllowScriptFromSource(KURL("https://allowed.example.com"),
@@ -117,6 +116,23 @@ class ThreadedWorkletThreadForTest : public WorkerThread {
FROM_HERE, CrossThreadBind(&test::ExitRunLoop));
}
+ // Test that having an invalid CSP does not result in an exception.
+ // See bugs: 844383,844317
+ void TestInvalidContentSecurityPolicy() {
+ EXPECT_TRUE(IsCurrentThread());
+
+ // At this point check that the CSP that was set is indeed invalid.
+ ContentSecurityPolicy* csp = GlobalScope()->GetContentSecurityPolicy();
+ EXPECT_EQ(1ul, csp->Headers().size());
+ EXPECT_EQ("invalid-csp", csp->Headers().at(0).first);
+ EXPECT_EQ(kContentSecurityPolicyHeaderTypeEnforce,
+ csp->Headers().at(0).second);
+
+ PostCrossThreadTask(
+ *GetParentExecutionContextTaskRunners()->Get(TaskType::kInternalTest),
+ FROM_HERE, CrossThreadBind(&test::ExitRunLoop));
+ }
+
// Emulates API use on ThreadedWorkletGlobalScope.
void CountFeature(WebFeature feature) {
EXPECT_TRUE(IsCurrentThread());
@@ -185,14 +201,13 @@ class ThreadedWorkletMessagingProxyForTest
InitializeWorkerThread(
std::make_unique<GlobalScopeCreationParams>(
document->Url(), ScriptType::kModule, document->UserAgent(),
- document->GetContentSecurityPolicy()->Headers().get(),
+ document->GetContentSecurityPolicy()->Headers(),
document->GetReferrerPolicy(), document->GetSecurityOrigin(),
document->IsSecureContext(), worker_clients,
document->AddressSpace(),
OriginTrialContext::GetTokens(document).get(),
base::UnguessableToken::Create(), std::move(worker_settings),
- kV8CacheOptionsDefault,
- new WorkletModuleResponsesMap(document->Fetcher())),
+ kV8CacheOptionsDefault, new WorkletModuleResponsesMap),
base::nullopt);
}
@@ -268,7 +283,24 @@ TEST_F(ThreadedWorkletTest, ContentSecurityPolicy) {
test::EnterRunLoop();
}
+TEST_F(ThreadedWorkletTest, InvalidContentSecurityPolicy) {
+ ContentSecurityPolicy* csp = ContentSecurityPolicy::Create();
+ csp->DidReceiveHeader("invalid-csp", kContentSecurityPolicyHeaderTypeEnforce,
+ kContentSecurityPolicyHeaderSourceHTTP);
+ GetDocument().InitContentSecurityPolicy(csp);
+
+ MessagingProxy()->Start();
+
+ PostCrossThreadTask(
+ *GetWorkerThread()->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+ CrossThreadBind(
+ &ThreadedWorkletThreadForTest::TestInvalidContentSecurityPolicy,
+ CrossThreadUnretained(GetWorkerThread())));
+ test::EnterRunLoop();
+}
+
TEST_F(ThreadedWorkletTest, UseCounter) {
+ Page::InsertOrdinaryPageForTesting(GetDocument().GetPage());
MessagingProxy()->Start();
// This feature is randomly selected.
diff --git a/chromium/third_party/blink/renderer/core/workers/worker.idl b/chromium/third_party/blink/renderer/core/workers/worker.idl
index 90f0f890a7a..7cd1f5cd43c 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker.idl
+++ b/chromium/third_party/blink/renderer/core/workers/worker.idl
@@ -31,7 +31,7 @@
ActiveScriptWrappable,
Constructor(DOMString scriptURL, optional WorkerOptions options),
ConstructorCallWith=ExecutionContext,
- // TODO(foolip): Exposed=(Window,Worker),
+ Exposed(Window StableBlinkFeatures,DedicatedWorker NestedWorkers),
RaisesException=Constructor,
ImplementedAs=DedicatedWorker
] interface Worker : EventTarget {
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_animation_frame_provider.cc b/chromium/third_party/blink/renderer/core/workers/worker_animation_frame_provider.cc
index ea583f23da8..bdbf04b6888 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_animation_frame_provider.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worker_animation_frame_provider.cc
@@ -3,6 +3,9 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/workers/worker_animation_frame_provider.h"
+
+#include "third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h"
+#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink {
@@ -13,7 +16,9 @@ WorkerAnimationFrameProvider::WorkerAnimationFrameProvider(
: begin_frame_provider_(
std::make_unique<BeginFrameProvider>(begin_frame_provider_params,
this)),
- callback_collection_(context) {}
+ callback_collection_(context),
+ context_(context),
+ weak_factory_(this) {}
int WorkerAnimationFrameProvider::RegisterCallback(
FrameRequestCallbackCollection::FrameCallback* callback) {
@@ -28,29 +33,42 @@ void WorkerAnimationFrameProvider::CancelCallback(int id) {
}
void WorkerAnimationFrameProvider::BeginFrame() {
- double time = WTF::CurrentTimeTicksInMilliseconds();
- // We don't want to expose microseconds residues to users.
- time = round(time * 60) / 60;
+ // TODO(fserb): Remove this once the Mojo changes for scheduling are in.
+ context_->GetTaskRunner(TaskType::kWorkerAnimation)
+ ->PostTask(
+ FROM_HERE,
+ WTF::Bind(
+ [](base::WeakPtr<WorkerAnimationFrameProvider> provider) {
+ double time = WTF::CurrentTimeTicksInMilliseconds();
+ // We don't want to expose microseconds residues to users.
+ time = round(time * 60) / 60;
- callback_collection_.ExecuteCallbacks(time, time);
+ provider->callback_collection_.ExecuteCallbacks(time, time);
- for (auto& ctx : rendering_contexts_) {
- ctx->PushFrame();
- }
+ for (auto& offscreen_canvas : provider->offscreen_canvases_) {
+ offscreen_canvas->PushFrameIfNeeded();
+ }
+ },
+ weak_factory_.GetWeakPtr()));
}
-void WorkerAnimationFrameProvider::AddContextToDispatch(
- CanvasRenderingContext* context) {
- DCHECK(rendering_contexts_.Find(context) == kNotFound);
- rendering_contexts_.push_back(context);
+void WorkerAnimationFrameProvider::RegisterOffscreenCanvas(
+ OffscreenCanvas* context) {
+ DCHECK(offscreen_canvases_.Find(context) == kNotFound);
+ offscreen_canvases_.push_back(context);
}
-void WorkerAnimationFrameProvider::RemoveContextToDispatch(
- CanvasRenderingContext* context) {
- size_t pos = rendering_contexts_.Find(context);
+void WorkerAnimationFrameProvider::DeregisterOffscreenCanvas(
+ OffscreenCanvas* offscreen_canvas) {
+ size_t pos = offscreen_canvases_.Find(offscreen_canvas);
if (pos != kNotFound) {
- rendering_contexts_.EraseAt(pos);
+ offscreen_canvases_.EraseAt(pos);
}
}
+void WorkerAnimationFrameProvider::Trace(blink::Visitor* visitor) {
+ visitor->Trace(callback_collection_);
+ visitor->Trace(context_);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_animation_frame_provider.h b/chromium/third_party/blink/renderer/core/workers/worker_animation_frame_provider.h
index 91a86a55082..d7759cb33f3 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_animation_frame_provider.h
+++ b/chromium/third_party/blink/renderer/core/workers/worker_animation_frame_provider.h
@@ -8,13 +8,12 @@
#include "base/macros.h"
#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/core/html/canvas/canvas_rendering_context.h"
#include "third_party/blink/renderer/platform/graphics/begin_frame_provider.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
-class CanvasRenderingContext;
+class OffscreenCanvas;
// WorkerAnimationFrameProvider is a member of WorkerGlobalScope and it provides
// RequestAnimationFrame capabilities to Workers.
@@ -40,20 +39,14 @@ class CORE_EXPORT WorkerAnimationFrameProvider
int RegisterCallback(FrameRequestCallbackCollection::FrameCallback* callback);
void CancelCallback(int id);
- void Trace(blink::Visitor* visitor) {
- visitor->Trace(callback_collection_);
- visitor->Trace(rendering_contexts_);
- }
-
- void TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(callback_collection_);
- }
+ void Trace(blink::Visitor* visitor);
// BeginFrameProviderClient
void BeginFrame() override;
+ bool InBeginFrame() const;
- void AddContextToDispatch(CanvasRenderingContext*);
- void RemoveContextToDispatch(CanvasRenderingContext*);
+ void RegisterOffscreenCanvas(OffscreenCanvas*);
+ void DeregisterOffscreenCanvas(OffscreenCanvas*);
protected:
WorkerAnimationFrameProvider(
@@ -65,7 +58,14 @@ class CORE_EXPORT WorkerAnimationFrameProvider
DISALLOW_COPY_AND_ASSIGN(WorkerAnimationFrameProvider);
FrameRequestCallbackCollection callback_collection_;
- HeapVector<Member<CanvasRenderingContext>> rendering_contexts_;
+ // To avoid leaking OffscreenCanvas objects, the following vector must
+ // not hold strong references.
+ Vector<UntracedMember<OffscreenCanvas>> offscreen_canvases_;
+ bool in_begin_frame_;
+
+ Member<ExecutionContext> context_;
+
+ base::WeakPtrFactory<WorkerAnimationFrameProvider> weak_factory_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_backing_thread.cc b/chromium/third_party/blink/renderer/core/workers/worker_backing_thread.cc
index 08706a54fa5..21d16b4c20b 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_backing_thread.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worker_backing_thread.cc
@@ -23,22 +23,14 @@
namespace blink {
-// Wrapper functions defined in WebKit.h
-void MemoryPressureNotificationToWorkerThreadIsolates(
- v8::MemoryPressureLevel level) {
- WorkerBackingThread::MemoryPressureNotificationToWorkerThreadIsolates(level);
-}
-
-void SetRAILModeOnWorkerThreadIsolates(v8::RAILMode rail_mode) {
- WorkerBackingThread::SetRAILModeOnWorkerThreadIsolates(rail_mode);
-}
+namespace {
-static Mutex& IsolatesMutex() {
+Mutex& IsolatesMutex() {
DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, mutex, ());
return mutex;
}
-static HashSet<v8::Isolate*>& Isolates() {
+HashSet<v8::Isolate*>& Isolates() {
#if DCHECK_IS_ON()
DCHECK(IsolatesMutex().Locked());
#endif
@@ -46,27 +38,35 @@ static HashSet<v8::Isolate*>& Isolates() {
return isolates;
}
-static void AddWorkerIsolate(v8::Isolate* isolate) {
+void AddWorkerIsolate(v8::Isolate* isolate) {
MutexLocker lock(IsolatesMutex());
Isolates().insert(isolate);
}
-static void RemoveWorkerIsolate(v8::Isolate* isolate) {
+void RemoveWorkerIsolate(v8::Isolate* isolate) {
MutexLocker lock(IsolatesMutex());
Isolates().erase(isolate);
}
-WorkerBackingThread::WorkerBackingThread(const WebThreadCreationParams& params,
- bool should_call_gc_on_shutdown)
+} // namespace
+
+// Wrapper functions defined in third_party/blink/public/web/blink.h
+void MemoryPressureNotificationToWorkerThreadIsolates(
+ v8::MemoryPressureLevel level) {
+ WorkerBackingThread::MemoryPressureNotificationToWorkerThreadIsolates(level);
+}
+
+void SetRAILModeOnWorkerThreadIsolates(v8::RAILMode rail_mode) {
+ WorkerBackingThread::SetRAILModeOnWorkerThreadIsolates(rail_mode);
+}
+
+WorkerBackingThread::WorkerBackingThread(const WebThreadCreationParams& params)
: backing_thread_(WebThreadSupportingGC::Create(params)),
- is_owning_thread_(true),
- should_call_gc_on_shutdown_(should_call_gc_on_shutdown) {}
+ is_owning_thread_(true) {}
-WorkerBackingThread::WorkerBackingThread(WebThread* thread,
- bool should_call_gc_on_shutdown)
+WorkerBackingThread::WorkerBackingThread(WebThread* thread)
: backing_thread_(WebThreadSupportingGC::CreateForThread(thread)),
- is_owning_thread_(false),
- should_call_gc_on_shutdown_(should_call_gc_on_shutdown) {}
+ is_owning_thread_(false) {}
WorkerBackingThread::~WorkerBackingThread() = default;
@@ -77,7 +77,7 @@ void WorkerBackingThread::InitializeOnBackingThread(
DCHECK(!isolate_);
isolate_ = V8PerIsolateData::Initialize(
- backing_thread_->PlatformThread().GetTaskRunner(),
+ backing_thread_->PlatformThread().Scheduler()->V8TaskRunner(),
V8PerIsolateData::V8ContextSnapshotMode::kDontUseSnapshot);
AddWorkerIsolate(isolate_);
V8Initializer::InitializeWorker(isolate_);
@@ -116,11 +116,6 @@ void WorkerBackingThread::ShutdownOnBackingThread() {
V8PerIsolateData::WillBeDestroyed(isolate_);
V8GCController::ClearDOMWrappers(isolate_);
- // TODO(yhirano): Remove this when https://crbug.com/v8/1428 is fixed.
- if (should_call_gc_on_shutdown_) {
- // This statement runs only in tests.
- V8GCController::CollectAllGarbageForTesting(isolate_);
- }
backing_thread_->ShutdownOnThread();
RemoveWorkerIsolate(isolate_);
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_backing_thread.h b/chromium/third_party/blink/renderer/core/workers/worker_backing_thread.h
index 10470d3e43b..72f80cf23e3 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_backing_thread.h
+++ b/chromium/third_party/blink/renderer/core/workers/worker_backing_thread.h
@@ -18,6 +18,7 @@ namespace blink {
class WebThread;
class WebThreadSupportingGC;
+struct WebThreadCreationParams;
struct WorkerBackingThreadStartupData;
// WorkerBackingThread represents a WebThread with Oilpan and V8. A client of
@@ -28,20 +29,10 @@ class CORE_EXPORT WorkerBackingThread final {
public:
static std::unique_ptr<WorkerBackingThread> Create(
const WebThreadCreationParams& params) {
- return base::WrapUnique(new WorkerBackingThread(params, false));
+ return base::WrapUnique(new WorkerBackingThread(params));
}
static std::unique_ptr<WorkerBackingThread> Create(WebThread* thread) {
- return base::WrapUnique(new WorkerBackingThread(thread, false));
- }
-
- // These are needed to suppress leak reports. See
- // https://crbug.com/590802 and https://crbug.com/v8/1428.
- static std::unique_ptr<WorkerBackingThread> CreateForTest(
- const WebThreadCreationParams& params) {
- return base::WrapUnique(new WorkerBackingThread(params, true));
- }
- static std::unique_ptr<WorkerBackingThread> CreateForTest(WebThread* thread) {
- return base::WrapUnique(new WorkerBackingThread(thread, true));
+ return base::WrapUnique(new WorkerBackingThread(thread));
}
~WorkerBackingThread();
@@ -66,14 +57,12 @@ class CORE_EXPORT WorkerBackingThread final {
static void SetRAILModeOnWorkerThreadIsolates(v8::RAILMode);
private:
- WorkerBackingThread(const WebThreadCreationParams&,
- bool should_call_gc_on_shutdown);
- WorkerBackingThread(WebThread*, bool should_call_gc_on_s_hutdown);
+ explicit WorkerBackingThread(const WebThreadCreationParams&);
+ explicit WorkerBackingThread(WebThread*);
std::unique_ptr<WebThreadSupportingGC> backing_thread_;
v8::Isolate* isolate_ = nullptr;
bool is_owning_thread_;
- bool should_call_gc_on_shutdown_;
};
} // namespace blink
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 4b47f551f36..6e803af108f 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
@@ -35,7 +35,6 @@
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/loader/allowed_by_nosniff.h"
#include "third_party/blink/renderer/core/loader/resource/script_resource.h"
-#include "third_party/blink/renderer/core/loader/worker_threadable_loader.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
@@ -82,9 +81,8 @@ void WorkerClassicScriptLoader::LoadSynchronously(
resource_loader_options.parser_disposition =
ParserDisposition::kNotParserInserted;
- WorkerThreadableLoader::LoadResourceSynchronously(
- ToWorkerGlobalScope(execution_context), request, *this, options,
- resource_loader_options);
+ ThreadableLoader::LoadResourceSynchronously(execution_context, request, *this,
+ options, resource_loader_options);
}
void WorkerClassicScriptLoader::LoadAsynchronously(
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_event_queue.cc b/chromium/third_party/blink/renderer/core/workers/worker_event_queue.cc
deleted file mode 100644
index a9dfe08d540..00000000000
--- a/chromium/third_party/blink/renderer/core/workers/worker_event_queue.cc
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "third_party/blink/renderer/core/workers/worker_event_queue.h"
-
-#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/core/probe/core_probes.h"
-#include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
-#include "third_party/blink/renderer/core/workers/worker_thread.h"
-
-namespace blink {
-
-WorkerEventQueue* WorkerEventQueue::Create(
- WorkerOrWorkletGlobalScope* global_scope) {
- return new WorkerEventQueue(global_scope);
-}
-
-WorkerEventQueue::WorkerEventQueue(WorkerOrWorkletGlobalScope* global_scope)
- : global_scope_(global_scope) {}
-
-WorkerEventQueue::~WorkerEventQueue() {
- DCHECK(pending_events_.IsEmpty());
-}
-
-void WorkerEventQueue::Trace(blink::Visitor* visitor) {
- visitor->Trace(global_scope_);
- visitor->Trace(pending_events_);
- EventQueue::Trace(visitor);
-}
-
-bool WorkerEventQueue::EnqueueEvent(const base::Location& from_here,
- Event* event) {
- if (is_closed_)
- return false;
- probe::AsyncTaskScheduled(event->target()->GetExecutionContext(),
- event->type(), event);
- pending_events_.insert(event);
- // This queue is unthrottled because throttling event tasks may break existing
- // web pages. For example, throttling IndexedDB events may break scenarios
- // where several tabs, some of which are backgrounded, access the same
- // database concurrently. See also comments in the ctor of
- // DOMWindowEventQueueTimer.
- // TODO(nhiroki): Callers of enqueueEvent() should specify the task type.
- global_scope_->GetTaskRunner(TaskType::kInternalWorker)
- ->PostTask(from_here,
- WTF::Bind(&WorkerEventQueue::DispatchEvent,
- WrapPersistent(this), WrapWeakPersistent(event)));
- return true;
-}
-
-bool WorkerEventQueue::CancelEvent(Event* event) {
- if (!RemoveEvent(event))
- return false;
- probe::AsyncTaskCanceled(event->target()->GetExecutionContext(), event);
- return true;
-}
-
-void WorkerEventQueue::Close() {
- is_closed_ = true;
- for (const auto& event : pending_events_)
- probe::AsyncTaskCanceled(event->target()->GetExecutionContext(), event);
- pending_events_.clear();
-}
-
-bool WorkerEventQueue::RemoveEvent(Event* event) {
- auto found = pending_events_.find(event);
- if (found == pending_events_.end())
- return false;
- pending_events_.erase(found);
- return true;
-}
-
-void WorkerEventQueue::DispatchEvent(Event* event) {
- if (!event || !RemoveEvent(event))
- return;
-
- probe::AsyncTask async_task(global_scope_, event);
- event->target()->DispatchEvent(event);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_event_queue.h b/chromium/third_party/blink/renderer/core/workers/worker_event_queue.h
deleted file mode 100644
index 23b1664bc50..00000000000
--- a/chromium/third_party/blink/renderer/core/workers/worker_event_queue.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_EVENT_QUEUE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_EVENT_QUEUE_H_
-
-#include "third_party/blink/renderer/core/dom/events/event_queue.h"
-#include "third_party/blink/renderer/platform/wtf/hash_set.h"
-
-namespace blink {
-
-class Event;
-class WorkerOrWorkletGlobalScope;
-
-// TODO(nhiroki): Rename this class to WorkerOrWorkletEventQueue and add
-// class-level comments.
-class WorkerEventQueue final : public EventQueue {
- public:
- static WorkerEventQueue* Create(WorkerOrWorkletGlobalScope*);
- ~WorkerEventQueue() override;
- void Trace(blink::Visitor*) override;
-
- // EventQueue
- bool EnqueueEvent(const base::Location&, Event*) override;
- bool CancelEvent(Event*) override;
- void Close() override;
-
- private:
- explicit WorkerEventQueue(WorkerOrWorkletGlobalScope*);
- bool RemoveEvent(Event*);
- void DispatchEvent(Event*);
-
- Member<WorkerOrWorkletGlobalScope> global_scope_;
- bool is_closed_ = false;
-
- HeapHashSet<Member<Event>> pending_events_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_EVENT_QUEUE_H_
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_fetch_test_helper.h b/chromium/third_party/blink/renderer/core/workers/worker_fetch_test_helper.h
index 1231518c3c9..3eb6d845757 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_fetch_test_helper.h
+++ b/chromium/third_party/blink/renderer/core/workers/worker_fetch_test_helper.h
@@ -8,7 +8,7 @@
#include "base/optional.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h"
-#include "third_party/blink/renderer/core/workers/worklet_module_responses_map.h"
+#include "third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/loader/testing/fetch_testing_platform_support.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
@@ -17,21 +17,22 @@
namespace blink {
class ClientImpl final : public GarbageCollectedFinalized<ClientImpl>,
- public WorkletModuleResponsesMap::Client {
+ public ModuleScriptFetcher::Client {
USING_GARBAGE_COLLECTED_MIXIN(ClientImpl);
public:
enum class Result { kInitial, kOK, kFailed };
- void OnFetched(const ModuleScriptCreationParams& params) override {
+ void NotifyFetchFinished(
+ const base::Optional<ModuleScriptCreationParams>& params,
+ const HeapVector<Member<ConsoleMessage>>&) override {
ASSERT_EQ(Result::kInitial, result_);
- result_ = Result::kOK;
- params_.emplace(params);
- }
-
- void OnFailed() override {
- ASSERT_EQ(Result::kInitial, result_);
- result_ = Result::kFailed;
+ if (params) {
+ result_ = Result::kOK;
+ params_.emplace(*params);
+ } else {
+ result_ = Result::kFailed;
+ }
}
Result GetResult() const { return result_; }
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 8773b861fc2..e5fe2f5574e 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
@@ -30,7 +30,6 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_url_request.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#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"
@@ -38,7 +37,6 @@
#include "third_party/blink/renderer/core/css/offscreen_font_selector.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_notifier.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/pausable_object.h"
#include "third_party/blink/renderer/core/events/error_event.h"
#include "third_party/blink/renderer/core/frame/dom_timer_coordinator.h"
@@ -56,6 +54,7 @@
#include "third_party/blink/renderer/core/workers/worker_navigator.h"
#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.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/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/instance_counters.h"
#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
@@ -151,13 +150,14 @@ void WorkerGlobalScope::importScripts(const Vector<String>& urls,
const KURL& url = execution_context.CompleteURL(url_string);
if (!url.IsValid()) {
exception_state.ThrowDOMException(
- kSyntaxError, "The URL '" + url_string + "' is invalid.");
+ DOMExceptionCode::kSyntaxError,
+ "The URL '" + url_string + "' is invalid.");
return;
}
if (!GetContentSecurityPolicy()->AllowScriptFromSource(
url, AtomicString(), IntegrityMetadataSet(), kNotParserInserted)) {
exception_state.ThrowDOMException(
- kNetworkError,
+ DOMExceptionCode::kNetworkError,
"The script at '" + url.ElidedString() + "' failed to load.");
return;
}
@@ -181,11 +181,12 @@ void WorkerGlobalScope::importScripts(const Vector<String>& urls,
if (result != LoadResult::kSuccess) {
// TODO(vogelheim): In case of certain types of failure - e.g. 'nosniff'
- // block - this ought to be a kSecurityError, but that information
- // presently gets lost on the way.
- exception_state.ThrowDOMException(
- kNetworkError, "The script at '" + complete_url.ElidedString() +
- "' failed to load.");
+ // block - this ought to be a DOMExceptionCode::kSecurityError, but that
+ // information presently gets lost on the way.
+ exception_state.ThrowDOMException(DOMExceptionCode::kNetworkError,
+ "The script at '" +
+ complete_url.ElidedString() +
+ "' failed to load.");
return;
}
@@ -328,7 +329,7 @@ void WorkerGlobalScope::EvaluateClassicScript(
WorkerGlobalScope::WorkerGlobalScope(
std::unique_ptr<GlobalScopeCreationParams> creation_params,
WorkerThread* thread,
- double time_origin)
+ base::TimeTicks time_origin)
: WorkerOrWorkletGlobalScope(thread->GetIsolate(),
creation_params->worker_clients,
thread->GetWorkerReportingProxy()),
@@ -352,10 +353,16 @@ WorkerGlobalScope::WorkerGlobalScope(
creation_params->starter_origin->CreatePrivilegeData());
}
SetSecurityOrigin(std::move(security_origin));
- ApplyContentSecurityPolicyFromVector(
- *creation_params->content_security_policy_parsed_headers);
+ InitContentSecurityPolicyFromVector(
+ creation_params->content_security_policy_parsed_headers);
+ BindContentSecurityPolicyToExecutionContext();
SetWorkerSettings(std::move(creation_params->worker_settings));
- SetReferrerPolicy(creation_params->referrer_policy);
+
+ // For module scripts, referrer policy will be set after the top-level module
+ // script is fetched.
+ if (creation_params->script_type == ScriptType::kClassic)
+ SetReferrerPolicy(creation_params->referrer_policy);
+
SetAddressSpace(creation_params->address_space);
OriginTrialContext::AddTokens(this,
creation_params->origin_trial_tokens.get());
@@ -367,6 +374,11 @@ WorkerGlobalScope::WorkerGlobalScope(
creation_params->interface_provider.PassHandle(),
service_manager::mojom::InterfaceProvider::Version_)));
}
+
+ // A FeaturePolicy is created by FeaturePolicy::CreateFromParentPolicy, even
+ // if the parent policy is null.
+ DCHECK(creation_params->worker_feature_policy);
+ SetFeaturePolicy(std::move(creation_params->worker_feature_policy));
}
void WorkerGlobalScope::ApplyContentSecurityPolicyFromHeaders(
@@ -424,10 +436,4 @@ void WorkerGlobalScope::Trace(blink::Visitor* visitor) {
Supplementable<WorkerGlobalScope>::Trace(visitor);
}
-void WorkerGlobalScope::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- Supplementable<WorkerGlobalScope>::TraceWrappers(visitor);
- WorkerOrWorkletGlobalScope::TraceWrappers(visitor);
- visitor->TraceWrappers(navigator_);
-}
-
} // namespace blink
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 4ad5fdc534c..41432025041 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
@@ -42,7 +42,6 @@
#include "third_party/blink/renderer/core/script/script.h"
#include "third_party/blink/renderer/core/workers/worker_animation_frame_provider.h"
#include "third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h"
-#include "third_party/blink/renderer/core/workers/worker_or_worklet_module_fetch_coordinator_proxy.h"
#include "third_party/blink/renderer/core/workers/worker_settings.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
@@ -53,9 +52,10 @@ class InterfaceProvider;
namespace blink {
-class FontFaceSet;
class ConsoleMessage;
class ExceptionState;
+class FetchClientSettingsObjectSnapshot;
+class FontFaceSet;
class OffscreenFontSelector;
class WorkerLocation;
class WorkerNavigator;
@@ -136,14 +136,15 @@ class CORE_EXPORT WorkerGlobalScope
std::unique_ptr<Vector<char>> cached_meta_data);
// Imports the top-level module script for |module_url_record|.
- virtual void ImportModuleScript(const KURL& module_url_record,
- network::mojom::FetchCredentialsMode) = 0;
+ virtual void ImportModuleScript(
+ const KURL& module_url_record,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
+ network::mojom::FetchCredentialsMode) = 0;
- double TimeOrigin() const { return time_origin_; }
+ base::TimeTicks TimeOrigin() const { return time_origin_; }
WorkerSettings* GetWorkerSettings() const { return worker_settings_.get(); }
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
// TODO(fserb): This can be removed once we WorkerGlobalScope implements
// FontFaceSource on the IDL.
@@ -159,7 +160,7 @@ class CORE_EXPORT WorkerGlobalScope
protected:
WorkerGlobalScope(std::unique_ptr<GlobalScopeCreationParams>,
WorkerThread*,
- double time_origin);
+ base::TimeTicks time_origin);
void ApplyContentSecurityPolicyFromHeaders(
const ContentSecurityPolicyResponseHeaders&);
@@ -216,7 +217,7 @@ class CORE_EXPORT WorkerGlobalScope
DOMTimerCoordinator timers_;
- const double time_origin_;
+ const base::TimeTicks time_origin_;
HeapHashMap<int, Member<ErrorEvent>> pending_error_events_;
int last_pending_error_event_id_ = 0;
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_navigator.cc b/chromium/third_party/blink/renderer/core/workers/worker_navigator.cc
index e670cb5dad5..166d2fdf592 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_navigator.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worker_navigator.cc
@@ -42,9 +42,4 @@ void WorkerNavigator::Trace(blink::Visitor* visitor) {
Supplementable<WorkerNavigator>::Trace(visitor);
}
-void WorkerNavigator::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- ScriptWrappable::TraceWrappers(visitor);
- Supplementable<WorkerNavigator>::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_navigator.h b/chromium/third_party/blink/renderer/core/workers/worker_navigator.h
index 53196e76c7b..203f006ce40 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_navigator.h
+++ b/chromium/third_party/blink/renderer/core/workers/worker_navigator.h
@@ -57,7 +57,6 @@ class CORE_EXPORT WorkerNavigator final
String userAgent() const override;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
explicit WorkerNavigator(const String&);
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_options.idl b/chromium/third_party/blink/renderer/core/workers/worker_options.idl
index 7c0a63d6393..5a96bbaa58b 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_options.idl
+++ b/chromium/third_party/blink/renderer/core/workers/worker_options.idl
@@ -5,7 +5,7 @@
// https://html.spec.whatwg.org/multipage/workers.html#workeroptions
dictionary WorkerOptions {
WorkerType type = "classic";
- RequestCredentials credentials = "omit";
+ RequestCredentials credentials = "same-origin";
// TODO(nhiroki): Implement "name" option (https://crbug.com/721219)
// DOMString name = "";
};
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 d99355c4040..c006e6490f1 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
@@ -7,12 +7,12 @@
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_abstract_event_listener.h"
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
+#include "third_party/blink/renderer/core/dom/events/event_queue.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.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/script/modulator.h"
#include "third_party/blink/renderer/core/workers/main_thread_worklet_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
#include "third_party/blink/renderer/core/workers/worker_thread.h"
@@ -29,7 +29,6 @@ WorkerOrWorkletGlobalScope::WorkerOrWorkletGlobalScope(
: worker_clients_(worker_clients),
script_controller_(
WorkerOrWorkletScriptController::Create(this, isolate)),
- event_queue_(WorkerEventQueue::Create(this)),
reporting_proxy_(reporting_proxy),
used_features_(static_cast<int>(WebFeature::kNumberOfFeatures)) {
if (worker_clients_)
@@ -97,7 +96,7 @@ void WorkerOrWorkletGlobalScope::CountDeprecation(WebFeature feature) {
}
ResourceFetcher* WorkerOrWorkletGlobalScope::EnsureFetcher() {
- DCHECK(!IsMainThreadWorkletGlobalScope());
+ DCHECK(IsContextThread());
if (resource_fetcher_)
return resource_fetcher_;
WorkerFetchContext* fetch_context = WorkerFetchContext::Create(*this);
@@ -106,7 +105,7 @@ ResourceFetcher* WorkerOrWorkletGlobalScope::EnsureFetcher() {
return resource_fetcher_;
}
ResourceFetcher* WorkerOrWorkletGlobalScope::Fetcher() const {
- DCHECK(!IsMainThreadWorkletGlobalScope());
+ DCHECK(IsContextThread());
DCHECK(resource_fetcher_);
return resource_fetcher_;
}
@@ -124,10 +123,6 @@ bool WorkerOrWorkletGlobalScope::CanExecuteScripts(
return !IsJSExecutionForbidden();
}
-EventQueue* WorkerOrWorkletGlobalScope::GetEventQueue() const {
- return event_queue_.Get();
-}
-
void WorkerOrWorkletGlobalScope::Dispose() {
DCHECK(script_controller_);
@@ -145,8 +140,6 @@ void WorkerOrWorkletGlobalScope::Dispose() {
}
RemoveAllEventListeners();
- event_queue_->Close();
-
script_controller_->Dispose();
script_controller_.Clear();
@@ -187,7 +180,7 @@ WorkerOrWorkletGlobalScope::GetTaskRunner(TaskType type) {
return GetThread()->GetTaskRunner(type);
}
-void WorkerOrWorkletGlobalScope::ApplyContentSecurityPolicyFromVector(
+void WorkerOrWorkletGlobalScope::InitContentSecurityPolicyFromVector(
const Vector<CSPHeaderAndType>& headers) {
if (!GetContentSecurityPolicy()) {
ContentSecurityPolicy* csp = ContentSecurityPolicy::Create();
@@ -198,34 +191,45 @@ void WorkerOrWorkletGlobalScope::ApplyContentSecurityPolicyFromVector(
policy_and_type.first, policy_and_type.second,
kContentSecurityPolicyHeaderSourceHTTP);
}
+}
+
+void WorkerOrWorkletGlobalScope::BindContentSecurityPolicyToExecutionContext() {
+ DCHECK(IsContextThread());
GetContentSecurityPolicy()->BindToExecutionContext(GetExecutionContext());
}
+// Implementation of the "fetch a module worker script graph" algorithm in the
+// HTML spec:
+// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-module-worker-script-tree
void WorkerOrWorkletGlobalScope::FetchModuleScript(
const KURL& module_url_record,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
WebURLRequest::RequestContext destination,
network::mojom::FetchCredentialsMode credentials_mode,
+ ModuleScriptCustomFetchType custom_fetch_type,
ModuleTreeClient* client) {
// Step 2: "Let options be a script fetch options whose cryptographic nonce is
// the empty string,
String nonce;
// integrity metadata is the empty string,
String integrity_attribute;
- // parser metadata is "not-parser-inserted",
+ // parser metadata is "not-parser-inserted,
ParserDisposition parser_state = kNotParserInserted;
- // and credentials mode is credentials mode."
+ // credentials mode is credentials mode, and referrer policy is the empty
+ // string."
ScriptFetchOptions options(nonce, IntegrityMetadataSet(), integrity_attribute,
- parser_state, credentials_mode);
+ parser_state, credentials_mode,
+ kReferrerPolicyDefault);
Modulator* modulator = Modulator::From(ScriptController()->GetScriptState());
// Step 3. "Perform the internal module script graph fetching procedure ..."
- modulator->FetchTree(module_url_record, destination, options, client);
+ modulator->FetchTree(module_url_record, fetch_client_settings_object,
+ destination, options, custom_fetch_type, client);
}
void WorkerOrWorkletGlobalScope::Trace(blink::Visitor* visitor) {
visitor->Trace(resource_fetcher_);
visitor->Trace(script_controller_);
- visitor->Trace(event_queue_);
visitor->Trace(event_listeners_);
visitor->Trace(modulator_);
EventTargetWithInlineData::Trace(visitor);
@@ -233,11 +237,4 @@ void WorkerOrWorkletGlobalScope::Trace(blink::Visitor* visitor) {
SecurityContext::Trace(visitor);
}
-void WorkerOrWorkletGlobalScope::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(modulator_);
- EventTargetWithInlineData::TraceWrappers(visitor);
- ExecutionContext::TraceWrappers(visitor);
-}
-
} // namespace blink
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 b38152e995f..bf40a501a2d 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
@@ -14,13 +14,14 @@
#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/web_feature_forward.h"
+#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/workers/worker_clients.h"
-#include "third_party/blink/renderer/core/workers/worker_event_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/bit_vector.h"
namespace blink {
+class FetchClientSettingsObjectSnapshot;
class Modulator;
class ModuleTreeClient;
class ResourceFetcher;
@@ -58,7 +59,6 @@ class CORE_EXPORT WorkerOrWorkletGlobalScope : public EventTargetWithInlineData,
bool IsJSExecutionForbidden() const final;
void DisableEval(const String& error_message) final;
bool CanExecuteScripts(ReasonForCallingCanExecuteScripts) final;
- EventQueue* GetEventQueue() const final;
// SecurityContext
void DidUpdateSecurityOrigin() final {}
@@ -101,28 +101,27 @@ class CORE_EXPORT WorkerOrWorkletGlobalScope : public EventTargetWithInlineData,
WorkerReportingProxy& ReportingProxy() { return reporting_proxy_; }
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
scheduler::WorkerScheduler* GetScheduler() override;
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) override;
protected:
- void ApplyContentSecurityPolicyFromVector(
+ void InitContentSecurityPolicyFromVector(
const Vector<CSPHeaderAndType>& headers);
+ virtual void BindContentSecurityPolicyToExecutionContext();
- // Implementation of the "fetch a module worker script graph" algorithm in the
- // HTML spec:
- // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-module-worker-script-tree
- void FetchModuleScript(const KURL& module_url_record,
- WebURLRequest::RequestContext destination,
- network::mojom::FetchCredentialsMode,
- ModuleTreeClient*);
+ void FetchModuleScript(
+ const KURL& module_url_record,
+ FetchClientSettingsObjectSnapshot* fetch_client_settings_object,
+ WebURLRequest::RequestContext destination,
+ network::mojom::FetchCredentialsMode,
+ ModuleScriptCustomFetchType,
+ ModuleTreeClient*);
private:
CrossThreadPersistent<WorkerClients> worker_clients_;
Member<ResourceFetcher> resource_fetcher_;
Member<WorkerOrWorkletScriptController> script_controller_;
- Member<WorkerEventQueue> event_queue_;
WorkerReportingProxy& reporting_proxy_;
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_or_worklet_module_fetch_coordinator_proxy.cc b/chromium/third_party/blink/renderer/core/workers/worker_or_worklet_module_fetch_coordinator_proxy.cc
deleted file mode 100644
index 7669cd98461..00000000000
--- a/chromium/third_party/blink/renderer/core/workers/worker_or_worklet_module_fetch_coordinator_proxy.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/workers/worker_or_worklet_module_fetch_coordinator_proxy.h"
-
-#include "third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h"
-#include "third_party/blink/renderer/platform/cross_thread_functional.h"
-#include "third_party/blink/renderer/platform/web_task_runner.h"
-
-namespace blink {
-
-namespace {
-
-// ClientAdapter mediates WorkletModuleResponsesMap on the main
-// thread and WorkletModuleResponsesMap::Client implementation on
-// the worker or worklet context thread as follows.
-//
-// CoordinatorProxy (context thread) --> Coordinator (main thread)
-// Coordinator::Client (context thread) <-- ClientAdapter (main thread)
-//
-// This lives on the main thread.
-class ClientAdapter final : public GarbageCollectedFinalized<ClientAdapter>,
- public WorkletModuleResponsesMap::Client {
- USING_GARBAGE_COLLECTED_MIXIN(ClientAdapter);
-
- public:
- static ClientAdapter* Create(
- WorkletModuleResponsesMap::Client* client,
- scoped_refptr<base::SingleThreadTaskRunner> inside_settings_task_runner) {
- return new ClientAdapter(client, std::move(inside_settings_task_runner));
- }
-
- ~ClientAdapter() override = default;
-
- void OnFetched(const ModuleScriptCreationParams& params) override {
- DCHECK(IsMainThread());
- PostCrossThreadTask(
- *inside_settings_task_runner_, FROM_HERE,
- CrossThreadBind(&WorkletModuleResponsesMap::Client::OnFetched, client_,
- params));
- }
-
- void OnFailed() override {
- DCHECK(IsMainThread());
- PostCrossThreadTask(
- *inside_settings_task_runner_, FROM_HERE,
- CrossThreadBind(&WorkletModuleResponsesMap::Client::OnFailed, client_));
- }
-
- void Trace(blink::Visitor* visitor) override {}
-
- private:
- ClientAdapter(
- WorkletModuleResponsesMap::Client* client,
- scoped_refptr<base::SingleThreadTaskRunner> inside_settings_task_runner)
- : client_(client),
- inside_settings_task_runner_(std::move(inside_settings_task_runner)) {}
-
- CrossThreadPersistent<WorkletModuleResponsesMap::Client> client_;
- scoped_refptr<base::SingleThreadTaskRunner> inside_settings_task_runner_;
-};
-
-} // namespace
-
-WorkerOrWorkletModuleFetchCoordinatorProxy*
-WorkerOrWorkletModuleFetchCoordinatorProxy::Create(
- WorkletModuleResponsesMap* module_responses_map,
- scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> inside_settings_task_runner) {
- return new WorkerOrWorkletModuleFetchCoordinatorProxy(
- module_responses_map, std::move(outside_settings_task_runner),
- std::move(inside_settings_task_runner));
-}
-
-void WorkerOrWorkletModuleFetchCoordinatorProxy::Fetch(
- const FetchParameters& fetch_params,
- Client* client) {
- DCHECK(inside_settings_task_runner_->RunsTasksInCurrentSequence());
- PostCrossThreadTask(
- *outside_settings_task_runner_, FROM_HERE,
- CrossThreadBind(
- &WorkerOrWorkletModuleFetchCoordinatorProxy::FetchOnMainThread,
- WrapCrossThreadPersistent(this), fetch_params,
- WrapCrossThreadPersistent(client)));
-}
-
-void WorkerOrWorkletModuleFetchCoordinatorProxy::Trace(
- blink::Visitor* visitor) {}
-
-WorkerOrWorkletModuleFetchCoordinatorProxy::
- WorkerOrWorkletModuleFetchCoordinatorProxy(
- WorkletModuleResponsesMap* module_responses_map,
- scoped_refptr<base::SingleThreadTaskRunner>
- outside_settings_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> inside_settings_task_runner)
- : module_responses_map_(module_responses_map),
- outside_settings_task_runner_(outside_settings_task_runner),
- inside_settings_task_runner_(inside_settings_task_runner) {
- DCHECK(module_responses_map_);
- DCHECK(outside_settings_task_runner_);
- DCHECK(inside_settings_task_runner_);
- DCHECK(inside_settings_task_runner_->RunsTasksInCurrentSequence());
-}
-
-void WorkerOrWorkletModuleFetchCoordinatorProxy::FetchOnMainThread(
- std::unique_ptr<CrossThreadFetchParametersData> cross_thread_fetch_params,
- Client* client) {
- DCHECK(IsMainThread());
- FetchParameters fetch_params(std::move(cross_thread_fetch_params));
- ClientAdapter* wrapper =
- ClientAdapter::Create(client, inside_settings_task_runner_);
- module_responses_map_->Fetch(fetch_params, wrapper);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_or_worklet_module_fetch_coordinator_proxy.h b/chromium/third_party/blink/renderer/core/workers/worker_or_worklet_module_fetch_coordinator_proxy.h
deleted file mode 100644
index e9f96f73d23..00000000000
--- a/chromium/third_party/blink/renderer/core/workers/worker_or_worklet_module_fetch_coordinator_proxy.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_OR_WORKLET_MODULE_FETCH_COORDINATOR_PROXY_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_OR_WORKLET_MODULE_FETCH_COORDINATOR_PROXY_H_
-
-#include "base/single_thread_task_runner.h"
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/workers/worklet_module_responses_map.h"
-#include "third_party/blink/renderer/platform/heap/heap.h"
-
-namespace blink {
-
-// WorkerOrWorkletModuleFetchCoordinatorProxy serves as a proxy to talk to
-// WorkletModuleResponsesMap on the main thread
-// (outside_settings) from the worker or worklet context thread
-// (inside_settings). The constructor and all public functions must be called on
-// the context thread.
-// TODO(japhet): Rename to WorkletModuleFetchCoordinatorProxy
-class CORE_EXPORT WorkerOrWorkletModuleFetchCoordinatorProxy
- : public GarbageCollectedFinalized<
- WorkerOrWorkletModuleFetchCoordinatorProxy> {
- public:
- using Client = WorkletModuleResponsesMap::Client;
-
- static WorkerOrWorkletModuleFetchCoordinatorProxy* Create(
- WorkletModuleResponsesMap*,
- scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> inside_settings_task_runner);
-
- void Fetch(const FetchParameters&, Client*);
-
- void Trace(blink::Visitor*);
-
- private:
- WorkerOrWorkletModuleFetchCoordinatorProxy(
- WorkletModuleResponsesMap*,
- scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> inside_settings_task_runner);
-
- void FetchOnMainThread(std::unique_ptr<CrossThreadFetchParametersData>,
- Client*);
-
- CrossThreadPersistent<WorkletModuleResponsesMap> module_responses_map_;
- scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner_;
- scoped_refptr<base::SingleThreadTaskRunner> inside_settings_task_runner_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_CORE_WORKERS_WORKER_OR_WORKLET_MODULE_FETCH_COORDINATOR_PROXY_H_
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 7cf818b56c1..6b4a2ce0552 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_thread.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worker_thread.cc
@@ -39,6 +39,7 @@
#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/probe/core_probes.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
#include "third_party/blink/renderer/core/workers/threaded_worklet_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_backing_thread.h"
@@ -52,8 +53,8 @@
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.h"
-#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler.h"
-#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
#include "third_party/blink/renderer/platform/waitable_event.h"
#include "third_party/blink/renderer/platform/web_thread_supporting_gc.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -145,22 +146,17 @@ void WorkerThread::EvaluateClassicScript(
void WorkerThread::ImportModuleScript(
const KURL& script_url,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
network::mojom::FetchCredentialsMode credentials_mode) {
DCHECK_CALLED_ON_VALID_THREAD(parent_thread_checker_);
PostCrossThreadTask(
*GetTaskRunner(TaskType::kInternalWorker), FROM_HERE,
CrossThreadBind(&WorkerThread::ImportModuleScriptOnWorkerThread,
CrossThreadUnretained(this), script_url,
+ WTF::Passed(outside_settings_object->CopyData()),
credentials_mode));
}
-void WorkerThread::TerminateChildThreadsOnWorkerThread() {
- DCHECK(IsCurrentThread());
- PrepareForShutdownOnWorkerThread();
- for (WorkerThread* child : child_threads_)
- child->Terminate();
-}
-
void WorkerThread::Terminate() {
DCHECK_CALLED_ON_VALID_THREAD(parent_thread_checker_);
{
@@ -178,18 +174,6 @@ void WorkerThread::Terminate() {
worker_thread_lifecycle_context_->NotifyContextDestroyed();
inspector_task_runner_->Dispose();
- if (!child_threads_.IsEmpty()) {
- // When child workers are present, wait for them to shutdown before shutting
- // down this thread. ChildThreadTerminatedOnWorkerThread() is responsible
- // for completing shutdown on the worker thread after the last child shuts
- // down.
- GetWorkerBackingThread().BackingThread().PostTask(
- FROM_HERE,
- CrossThreadBind(&WorkerThread::TerminateChildThreadsOnWorkerThread,
- CrossThreadUnretained(this)));
- return;
- }
-
GetWorkerBackingThread().BackingThread().PostTask(
FROM_HERE,
CrossThreadBind(&WorkerThread::PrepareForShutdownOnWorkerThread,
@@ -339,6 +323,12 @@ scheduler::WorkerScheduler* WorkerThread::GetScheduler() {
void WorkerThread::ChildThreadStartedOnWorkerThread(WorkerThread* child) {
DCHECK(IsCurrentThread());
+#if DCHECK_IS_ON()
+ {
+ MutexLocker lock(mutex_);
+ DCHECK_EQ(ThreadState::kRunning, thread_state_);
+ }
+#endif
child_threads_.insert(child);
}
@@ -351,7 +341,7 @@ void WorkerThread::ChildThreadTerminatedOnWorkerThread(WorkerThread* child) {
WorkerThread::WorkerThread(ThreadableLoadingContext* loading_context,
WorkerReportingProxy& worker_reporting_proxy)
- : time_origin_(CurrentTimeTicksInSeconds()),
+ : time_origin_(CurrentTimeTicks()),
worker_thread_id_(GetNextWorkerThreadId()),
forcible_termination_delay_(kForcibleTerminationDelay),
devtools_worker_token_(base::UnguessableToken::Create()),
@@ -418,7 +408,9 @@ void WorkerThread::InitializeSchedulerOnWorkerThread(
static_cast<scheduler::WebThreadImplForWorkerScheduler&>(
GetWorkerBackingThread().BackingThread().PlatformThread());
worker_scheduler_ = std::make_unique<scheduler::WorkerScheduler>(
- web_thread_for_worker.GetNonMainThreadScheduler());
+ static_cast<scheduler::WorkerThreadScheduler*>(
+ web_thread_for_worker.GetNonMainThreadScheduler()),
+ web_thread_for_worker.worker_scheduler_proxy());
waitable_event->Signal();
}
@@ -498,12 +490,17 @@ void WorkerThread::EvaluateClassicScriptOnWorkerThread(
void WorkerThread::ImportModuleScriptOnWorkerThread(
const KURL& script_url,
+ std::unique_ptr<CrossThreadFetchClientSettingsObjectData>
+ outside_settings_object,
network::mojom::FetchCredentialsMode credentials_mode) {
// Worklets have a different code path to import module scripts.
// TODO(nhiroki): Consider excluding this code path from WorkerThread like
// Worklets.
ToWorkerGlobalScope(GlobalScope())
- ->ImportModuleScript(script_url, credentials_mode);
+ ->ImportModuleScript(script_url,
+ new FetchClientSettingsObjectSnapshot(
+ std::move(outside_settings_object)),
+ credentials_mode);
}
void WorkerThread::PrepareForShutdownOnWorkerThread() {
@@ -517,25 +514,17 @@ void WorkerThread::PrepareForShutdownOnWorkerThread() {
SetExitCode(ExitCode::kGracefullyTerminated);
}
- inspector_task_runner_->Dispose();
GetWorkerReportingProxy().WillDestroyWorkerGlobalScope();
- probe::AllAsyncTasksCanceled(GlobalScope());
+ probe::AllAsyncTasksCanceled(GlobalScope());
GlobalScope()->NotifyContextDestroyed();
- if (worker_inspector_controller_) {
- worker_inspector_controller_->Dispose();
- worker_inspector_controller_.Clear();
- }
worker_scheduler_->Dispose();
- GlobalScope()->Dispose();
- global_scope_ = nullptr;
- if (WorkerThreadDebugger* debugger = WorkerThreadDebugger::From(GetIsolate()))
- debugger->WorkerThreadDestroyed(this);
-
- console_message_storage_.Clear();
- loading_context_.Clear();
+ // No V8 microtasks should get executed after shutdown is requested.
GetWorkerBackingThread().BackingThread().RemoveTaskObserver(this);
+
+ for (WorkerThread* child : child_threads_)
+ child->Terminate();
}
void WorkerThread::PerformShutdownOnWorkerThread() {
@@ -548,6 +537,28 @@ void WorkerThread::PerformShutdownOnWorkerThread() {
}
#endif
+ // When child workers are present, wait for them to shutdown before shutting
+ // down this thread. ChildThreadTerminatedOnWorkerThread() is responsible
+ // for completing shutdown on the worker thread after the last child shuts
+ // down.
+ if (!child_threads_.IsEmpty())
+ return;
+
+ inspector_task_runner_->Dispose();
+ if (worker_inspector_controller_) {
+ worker_inspector_controller_->Dispose();
+ worker_inspector_controller_.Clear();
+ }
+
+ GlobalScope()->Dispose();
+ global_scope_ = nullptr;
+
+ if (WorkerThreadDebugger* debugger = WorkerThreadDebugger::From(GetIsolate()))
+ debugger->WorkerThreadDestroyed(this);
+
+ console_message_storage_.Clear();
+ loading_context_.Clear();
+
if (IsOwningBackingThread())
GetWorkerBackingThread().ShutdownOnBackingThread();
// We must not touch workerBackingThread() from now on.
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 96c465c4e56..b87706015e4 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_thread.h
+++ b/chromium/third_party/blink/renderer/core/workers/worker_thread.h
@@ -45,7 +45,7 @@
#include "third_party/blink/renderer/core/workers/worker_inspector_proxy.h"
#include "third_party/blink/renderer/core/workers/worker_thread_lifecycle_context.h"
#include "third_party/blink/renderer/core/workers/worker_thread_lifecycle_observer.h"
-#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h"
#include "third_party/blink/renderer/platform/waitable_event.h"
#include "third_party/blink/renderer/platform/web_task_runner.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
@@ -55,12 +55,14 @@
namespace blink {
class ConsoleMessageStorage;
+class FetchClientSettingsObjectSnapshot;
class InspectorTaskRunner;
class InstalledScriptsManager;
class WorkerBackingThread;
class WorkerInspectorController;
class WorkerOrWorkletGlobalScope;
class WorkerReportingProxy;
+struct CrossThreadFetchClientSettingsObjectData;
struct GlobalScopeCreationParams;
// WorkerThread is a kind of WorkerBackingThread client. Each worker mechanism
@@ -112,8 +114,10 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver {
// Posts a task to import a top-level module script on the worker thread.
// Called on the main thread after start().
- void ImportModuleScript(const KURL& script_url,
- network::mojom::FetchCredentialsMode);
+ void ImportModuleScript(
+ const KURL& script_url,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
+ network::mojom::FetchCredentialsMode);
// Posts a task to the worker thread to close the global scope and terminate
// the underlying thread. This task may be blocked by JavaScript execution on
@@ -224,7 +228,7 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver {
// Official moment of creation of worker: when the worker thread is created.
// (https://w3c.github.io/hr-time/#time-origin)
- const double time_origin_;
+ const base::TimeTicks time_origin_;
private:
friend class WorkerThreadTest;
@@ -281,10 +285,11 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver {
String source_code,
std::unique_ptr<Vector<char>> cached_meta_data,
const v8_inspector::V8StackTraceId& stack_id);
- void ImportModuleScriptOnWorkerThread(const KURL& script_url,
- network::mojom::FetchCredentialsMode);
-
- void TerminateChildThreadsOnWorkerThread();
+ void ImportModuleScriptOnWorkerThread(
+ const KURL& script_url,
+ std::unique_ptr<CrossThreadFetchClientSettingsObjectData>
+ outside_settings_object,
+ network::mojom::FetchCredentialsMode);
// These are called in this order during worker thread termination.
void PrepareForShutdownOnWorkerThread() LOCKS_EXCLUDED(mutex_);
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 1693753d32e..719b92186f1 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
@@ -16,6 +16,7 @@
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
#include "third_party/blink/renderer/core/workers/worker_thread_test_helper.h"
+#include "third_party/blink/renderer/platform/scheduler/test/fake_task_runner.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
#include "third_party/blink/renderer/platform/waitable_event.h"
@@ -67,6 +68,98 @@ void WaitForSignalTask(WorkerThread* worker_thread,
waitable_event->Wait();
}
+void TerminateParentOfNestedWorker(WorkerThread* parent_thread,
+ WaitableEvent* waitable_event) {
+ EXPECT_TRUE(IsMainThread());
+ parent_thread->Terminate();
+ waitable_event->Signal();
+}
+
+// This helper managers a child worker thread and a reporting proxy
+// and ensures they stay alive for the duration of the test. The struct
+// is created on the main thread, but its members are created and
+// destroyed on the parent worker thread.
+struct NestedWorkerHelper {
+ public:
+ NestedWorkerHelper() = default;
+ ~NestedWorkerHelper() = default;
+
+ std::unique_ptr<MockWorkerReportingProxy> reporting_proxy;
+ std::unique_ptr<WorkerThreadForTest> worker_thread;
+};
+
+void CreateNestedWorkerThenTerminateParent(
+ WorkerThread* parent_thread,
+ NestedWorkerHelper* nested_worker_helper) {
+ EXPECT_TRUE(parent_thread->IsCurrentThread());
+
+ nested_worker_helper->reporting_proxy =
+ std::make_unique<MockWorkerReportingProxy>();
+ EXPECT_CALL(*nested_worker_helper->reporting_proxy,
+ DidCreateWorkerGlobalScope(_))
+ .Times(1);
+ EXPECT_CALL(*nested_worker_helper->reporting_proxy,
+ DidInitializeWorkerContext())
+ .Times(1);
+ EXPECT_CALL(*nested_worker_helper->reporting_proxy,
+ WillEvaluateClassicScriptMock(_, _))
+ .Times(1);
+ EXPECT_CALL(*nested_worker_helper->reporting_proxy,
+ DidEvaluateClassicScript(true))
+ .Times(1);
+ EXPECT_CALL(*nested_worker_helper->reporting_proxy,
+ WillDestroyWorkerGlobalScope())
+ .Times(1);
+ EXPECT_CALL(*nested_worker_helper->reporting_proxy,
+ DidTerminateWorkerThread())
+ .Times(1);
+
+ nested_worker_helper->worker_thread = std::make_unique<WorkerThreadForTest>(
+ nullptr, *nested_worker_helper->reporting_proxy);
+ nested_worker_helper->worker_thread->StartWithSourceCode(
+ SecurityOrigin::Create(KURL("http://fake.url/")).get(),
+ "//fake source code", ParentExecutionContextTaskRunners::Create());
+ nested_worker_helper->worker_thread->WaitForInit();
+
+ // Ask the main threat to terminate this parent thread.
+ WaitableEvent child_waitable;
+ PostCrossThreadTask(
+ *parent_thread->GetParentExecutionContextTaskRunners()->Get(
+ TaskType::kInternalTest),
+ FROM_HERE,
+ CrossThreadBind(&TerminateParentOfNestedWorker,
+ CrossThreadUnretained(parent_thread),
+ CrossThreadUnretained(&child_waitable)));
+ child_waitable.Wait();
+ EXPECT_EQ(ExitCode::kNotTerminated, parent_thread->GetExitCodeForTesting());
+
+ parent_thread->ChildThreadStartedOnWorkerThread(
+ nested_worker_helper->worker_thread.get());
+ PostCrossThreadTask(
+ *parent_thread->GetParentExecutionContextTaskRunners()->Get(
+ TaskType::kInternalTest),
+ FROM_HERE, CrossThreadBind(&test::ExitRunLoop));
+}
+
+void VerifyParentAndChildAreTerminated(WorkerThread* parent_thread,
+ NestedWorkerHelper* nested_worker_helper,
+ WaitableEvent* waitable_event) {
+ EXPECT_TRUE(parent_thread->IsCurrentThread());
+ EXPECT_EQ(ExitCode::kGracefullyTerminated,
+ parent_thread->GetExitCodeForTesting());
+ EXPECT_EQ(ExitCode::kGracefullyTerminated,
+ nested_worker_helper->worker_thread->GetExitCodeForTesting());
+ EXPECT_NE(nullptr, parent_thread->GlobalScope());
+
+ parent_thread->ChildThreadTerminatedOnWorkerThread(
+ nested_worker_helper->worker_thread.get());
+ EXPECT_EQ(nullptr, parent_thread->GlobalScope());
+
+ nested_worker_helper->worker_thread = nullptr;
+ nested_worker_helper->reporting_proxy = nullptr;
+ waitable_event->Signal();
+}
+
} // namespace
class WorkerThreadTest : public testing::Test {
@@ -298,15 +391,13 @@ TEST_F(WorkerThreadTest, Terminate_WhileDebuggerTaskIsRunningOnInitialization) {
EXPECT_CALL(*reporting_proxy_, DidTerminateWorkerThread()).Times(1);
EXPECT_CALL(*lifecycle_observer_, ContextDestroyed(_)).Times(1);
- auto headers = std::make_unique<Vector<CSPHeaderAndType>>();
- CSPHeaderAndType header_and_type("contentSecurityPolicy",
- kContentSecurityPolicyHeaderTypeReport);
- headers->push_back(header_and_type);
+ Vector<CSPHeaderAndType> headers{
+ {"contentSecurityPolicy", kContentSecurityPolicyHeaderTypeReport}};
auto global_scope_creation_params =
std::make_unique<GlobalScopeCreationParams>(
KURL("http://fake.url/"), ScriptType::kClassic, "fake user agent",
- headers.get(), kReferrerPolicyDefault, security_origin_.get(),
+ headers, kReferrerPolicyDefault, security_origin_.get(),
false /* starter_secure_context */, nullptr /* workerClients */,
mojom::IPAddressSpace::kLocal, nullptr /* originTrialToken */,
base::UnguessableToken::Create(),
@@ -396,4 +487,27 @@ TEST_F(WorkerThreadTest, Terminate_WhileDebuggerTaskIsRunning) {
EXPECT_EQ(ExitCode::kGracefullyTerminated, GetExitCode());
}
+TEST_F(WorkerThreadTest, TerminateWorkerWhileChildIsLoading) {
+ ExpectReportingCalls();
+ Start();
+ worker_thread_->WaitForInit();
+
+ NestedWorkerHelper nested_worker_helper;
+ // Create a nested worker from the worker thread.
+ PostCrossThreadTask(
+ *worker_thread_->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
+ CrossThreadBind(&CreateNestedWorkerThenTerminateParent,
+ CrossThreadUnretained(worker_thread_.get()),
+ CrossThreadUnretained(&nested_worker_helper)));
+ test::EnterRunLoop();
+
+ WaitableEvent waitable_event;
+ worker_thread_->GetWorkerBackingThread().BackingThread().PostTask(
+ FROM_HERE, CrossThreadBind(&VerifyParentAndChildAreTerminated,
+ CrossThreadUnretained(worker_thread_.get()),
+ CrossThreadUnretained(&nested_worker_helper),
+ CrossThreadUnretained(&waitable_event)));
+ waitable_event.Wait();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/workers/worker_thread_test_helper.h b/chromium/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
index e8f00b2a25b..4e6c5b3b294 100644
--- a/chromium/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
+++ b/chromium/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
@@ -63,7 +63,7 @@ class FakeWorkerGlobalScope : public WorkerGlobalScope {
WorkerThread* thread)
: WorkerGlobalScope(std::move(creation_params),
thread,
- CurrentTimeTicksInSeconds()) {}
+ CurrentTimeTicks()) {}
~FakeWorkerGlobalScope() override = default;
@@ -73,8 +73,10 @@ class FakeWorkerGlobalScope : public WorkerGlobalScope {
}
// WorkerGlobalScope
- void ImportModuleScript(const KURL& module_url_record,
- network::mojom::FetchCredentialsMode) override {
+ void ImportModuleScript(
+ const KURL& module_url_record,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
+ network::mojom::FetchCredentialsMode) override {
NOTREACHED();
}
@@ -86,7 +88,7 @@ class WorkerThreadForTest : public WorkerThread {
WorkerThreadForTest(ThreadableLoadingContext* loading_context,
WorkerReportingProxy& mock_worker_reporting_proxy)
: WorkerThread(loading_context, mock_worker_reporting_proxy),
- worker_backing_thread_(WorkerBackingThread::CreateForTest(
+ worker_backing_thread_(WorkerBackingThread::Create(
WebThreadCreationParams(WebThreadType::kTestThread))) {}
~WorkerThreadForTest() override = default;
@@ -102,13 +104,10 @@ class WorkerThreadForTest : public WorkerThread {
ParentExecutionContextTaskRunners* parent_execution_context_task_runners,
const KURL& script_url = KURL("http://fake.url/"),
WorkerClients* worker_clients = nullptr) {
- auto headers = std::make_unique<Vector<CSPHeaderAndType>>();
- CSPHeaderAndType header_and_type("contentSecurityPolicy",
- kContentSecurityPolicyHeaderTypeReport);
- headers->push_back(header_and_type);
-
+ Vector<CSPHeaderAndType> headers{
+ {"contentSecurityPolicy", kContentSecurityPolicyHeaderTypeReport}};
auto creation_params = std::make_unique<GlobalScopeCreationParams>(
- script_url, ScriptType::kClassic, "fake user agent", headers.get(),
+ script_url, ScriptType::kClassic, "fake user agent", headers,
kReferrerPolicyDefault, security_origin,
false /* starter_secure_context */, worker_clients,
mojom::IPAddressSpace::kLocal, nullptr,
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet.cc b/chromium/third_party/blink/renderer/core/workers/worklet.cc
index 0bd81a62e84..4eabae2562d 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worklet.cc
@@ -14,6 +14,7 @@
#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/use_counter.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/core/workers/worklet_pending_tasks.h"
#include "third_party/blink/renderer/platform/wtf/wtf.h"
@@ -21,8 +22,7 @@ namespace blink {
Worklet::Worklet(Document* document)
: ContextLifecycleObserver(document),
- module_responses_map_(
- new WorkletModuleResponsesMap(document->Fetcher())) {
+ module_responses_map_(new WorkletModuleResponsesMap) {
DCHECK(IsMainThread());
}
@@ -41,7 +41,7 @@ ScriptPromise Worklet::addModule(ScriptState* script_state,
DCHECK(IsMainThread());
if (!GetExecutionContext()) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kInvalidStateError,
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
"This frame is already detached"));
}
UseCounter::Count(GetExecutionContext(),
@@ -61,8 +61,9 @@ ScriptPromise Worklet::addModule(ScriptState* script_state,
// Step 4: "If moduleURLRecord is failure, then reject promise with a
// "SyntaxError" DOMException and return promise."
if (!module_url_record.IsValid()) {
- resolver->Reject(DOMException::Create(
- kSyntaxError, "'" + module_url + "' is not a valid URL."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kSyntaxError,
+ "'" + module_url + "' is not a valid URL."));
return promise;
}
@@ -73,7 +74,7 @@ ScriptPromise Worklet::addModule(ScriptState* script_state,
// parallel."
// |kInternalLoading| is used here because this is a part of script module
// loading.
- ExecutionContext::From(script_state)
+ GetExecutionContext()
->GetTaskRunner(TaskType::kInternalLoading)
->PostTask(FROM_HERE, WTF::Bind(&Worklet::FetchAndInvokeScript,
WrapPersistent(this), module_url_record,
@@ -120,10 +121,10 @@ void Worklet::FetchAndInvokeScript(const KURL& module_url_record,
DCHECK(result);
// Step 7: "Let outsideSettings be the relevant settings object of this."
- // In the specification, outsideSettings is used for posting a task to the
- // document's responsible event loop. In our implementation, we use the
- // document's UnspecedLoading task runner as that is what we commonly use for
- // module loading.
+ auto* outside_settings_object =
+ new FetchClientSettingsObjectSnapshot(*GetExecutionContext());
+ // Specify TaskType::kInternalLoading because it's commonly used for module
+ // loading.
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner =
GetExecutionContext()->GetTaskRunner(TaskType::kInternalLoading);
@@ -158,6 +159,7 @@ void Worklet::FetchAndInvokeScript(const KURL& module_url_record,
// TODO(nhiroki): Queue a task instead of executing this here.
for (const auto& proxy : proxies_) {
proxy->FetchAndInvokeScript(module_url_record, credentials_mode,
+ outside_settings_object,
outside_settings_task_runner, pending_tasks);
}
}
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet.idl b/chromium/third_party/blink/renderer/core/workers/worklet.idl
index bc6590c29fb..018d604f8ac 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet.idl
+++ b/chromium/third_party/blink/renderer/core/workers/worklet.idl
@@ -5,7 +5,6 @@
// https://drafts.css-houdini.org/worklets/#worklet
[
- RuntimeEnabled=Worklet,
SecureContext
] interface Worklet {
[CallWith=ScriptState] 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 75e7809c354..5135d01f291 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
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/inspector/main_thread_debugger.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
+#include "third_party/blink/renderer/core/script/fetch_client_settings_object_snapshot.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
@@ -38,16 +39,12 @@ WorkletGlobalScope::WorkletGlobalScope(
user_agent_(creation_params->user_agent),
document_security_origin_(creation_params->starter_origin),
document_secure_context_(creation_params->starter_secure_context),
- fetch_coordinator_proxy_(
- WorkerOrWorkletModuleFetchCoordinatorProxy::Create(
- creation_params->module_responses_map,
- std::move(document_loading_task_runner),
- std::move(worklet_loading_task_runner))) {
+ module_responses_map_(creation_params->module_responses_map) {
// Step 2: "Let inheritedAPIBaseURL be outsideSettings's API base URL."
// |url_| is the inheritedAPIBaseURL passed from the parent Document.
// Step 3: "Let origin be a unique opaque origin."
- SetSecurityOrigin(SecurityOrigin::CreateUnique());
+ SetSecurityOrigin(SecurityOrigin::CreateUniqueOpaque());
// Step 5: "Let inheritedReferrerPolicy be outsideSettings's referrer policy."
SetReferrerPolicy(creation_params->referrer_policy);
@@ -55,8 +52,8 @@ WorkletGlobalScope::WorkletGlobalScope(
// https://drafts.css-houdini.org/worklets/#creating-a-workletglobalscope
// Step 6: "Invoke the initialize a global object's CSP list algorithm given
// workletGlobalScope."
- ApplyContentSecurityPolicyFromVector(
- *creation_params->content_security_policy_parsed_headers);
+ InitContentSecurityPolicyFromVector(
+ creation_params->content_security_policy_parsed_headers);
OriginTrialContext::AddTokens(this,
creation_params->origin_trial_tokens.get());
@@ -84,6 +81,7 @@ bool WorkletGlobalScope::IsSecureContext(String& error_message) const {
void WorkletGlobalScope::FetchAndInvokeScript(
const KURL& module_url_record,
network::mojom::FetchCredentialsMode credentials_mode,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
WorkletPendingTasks* pending_tasks) {
DCHECK(IsContextThread());
@@ -105,14 +103,9 @@ void WorkletGlobalScope::FetchAndInvokeScript(
// spec (e.g., "paint worklet", "audio worklet").
WebURLRequest::RequestContext destination =
WebURLRequest::kRequestContextScript;
- FetchModuleScript(module_url_record, destination, credentials_mode, client);
-}
-
-WorkerOrWorkletModuleFetchCoordinatorProxy*
-WorkletGlobalScope::ModuleFetchCoordinatorProxy() const {
- DCHECK(IsContextThread());
- DCHECK(fetch_coordinator_proxy_);
- return fetch_coordinator_proxy_;
+ FetchModuleScript(module_url_record, outside_settings_object, destination,
+ credentials_mode,
+ ModuleScriptCustomFetchType::kWorkletAddModule, client);
}
KURL WorkletGlobalScope::CompleteURL(const String& url) const {
@@ -125,13 +118,22 @@ KURL WorkletGlobalScope::CompleteURL(const String& url) const {
return KURL(BaseURL(), url);
}
-void WorkletGlobalScope::Trace(blink::Visitor* visitor) {
- visitor->Trace(fetch_coordinator_proxy_);
- WorkerOrWorkletGlobalScope::Trace(visitor);
+void WorkletGlobalScope::BindContentSecurityPolicyToExecutionContext() {
+ WorkerOrWorkletGlobalScope::BindContentSecurityPolicyToExecutionContext();
+
+ // CSP checks should resolve self based on the 'fetch client settings object'
+ // (i.e., the document's origin), not the 'module map settings object' (i.e.,
+ // the opaque origin of this worklet global scope). The current implementation
+ // doesn't have separate CSP objects for these two contexts. Therefore,
+ // we initialize the worklet global scope's CSP object (which would naively
+ // appear to be a CSP object for the 'module map settings object') entirely
+ // based on state from the document (the origin and CSP headers it passed
+ // here), and use the document's origin for 'self' CSP checks.
+ GetContentSecurityPolicy()->SetupSelf(*document_security_origin_);
}
-void WorkletGlobalScope::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- WorkerOrWorkletGlobalScope::TraceWrappers(visitor);
+void WorkletGlobalScope::Trace(blink::Visitor* visitor) {
+ WorkerOrWorkletGlobalScope::Trace(visitor);
}
} // namespace blink
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 ea64ab0e472..c19ef393d82 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
@@ -13,13 +13,14 @@
#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/core/workers/worker_or_worklet_global_scope.h"
-#include "third_party/blink/renderer/core/workers/worker_or_worklet_module_fetch_coordinator_proxy.h"
+#include "third_party/blink/renderer/core/workers/worklet_module_responses_map.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
+class FetchClientSettingsObjectSnapshot;
class WorkletPendingTasks;
class WorkerReportingProxy;
struct GlobalScopeCreationParams;
@@ -64,11 +65,13 @@ class CORE_EXPORT WorkletGlobalScope
void FetchAndInvokeScript(
const KURL& module_url_record,
network::mojom::FetchCredentialsMode,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
WorkletPendingTasks*);
- WorkerOrWorkletModuleFetchCoordinatorProxy* ModuleFetchCoordinatorProxy()
- const;
+ WorkletModuleResponsesMap* GetModuleResponsesMap() const {
+ return module_responses_map_.Get();
+ }
const SecurityOrigin* DocumentSecurityOrigin() const {
return document_security_origin_.get();
@@ -84,7 +87,6 @@ class CORE_EXPORT WorkletGlobalScope
bool DocumentSecureContext() const { return document_secure_context_; }
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
protected:
// Partial implementation of the "set up a worklet environment settings
@@ -97,6 +99,8 @@ class CORE_EXPORT WorkletGlobalScope
scoped_refptr<base::SingleThreadTaskRunner> document_loading_task_runner,
scoped_refptr<base::SingleThreadTaskRunner> worklet_loading_task_runner);
+ void BindContentSecurityPolicyToExecutionContext() override;
+
private:
EventTarget* ErrorEventTarget() final { return nullptr; }
@@ -111,7 +115,7 @@ class CORE_EXPORT WorkletGlobalScope
// Used for origin trials, inherited from the parent Document.
const bool document_secure_context_;
- Member<WorkerOrWorkletModuleFetchCoordinatorProxy> fetch_coordinator_proxy_;
+ CrossThreadPersistent<WorkletModuleResponsesMap> module_responses_map_;
};
DEFINE_TYPE_CASTS(WorkletGlobalScope,
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet_global_scope.idl b/chromium/third_party/blink/renderer/core/workers/worklet_global_scope.idl
index 376b33013a6..c641fe88610 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet_global_scope.idl
+++ b/chromium/third_party/blink/renderer/core/workers/worklet_global_scope.idl
@@ -7,7 +7,6 @@
[
ActiveScriptWrappable,
Exposed=Worklet,
- RuntimeEnabled=Worklet,
ImmutablePrototype
] interface WorkletGlobalScope {
};
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet_global_scope_proxy.h b/chromium/third_party/blink/renderer/core/workers/worklet_global_scope_proxy.h
index 67bed86dfff..f9a9a351310 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet_global_scope_proxy.h
+++ b/chromium/third_party/blink/renderer/core/workers/worklet_global_scope_proxy.h
@@ -13,6 +13,7 @@
namespace blink {
+class FetchClientSettingsObjectSnapshot;
class WorkletPendingTasks;
// Abstracts communication from (Main/Threaded)Worklet on the main thread to
@@ -27,6 +28,7 @@ class CORE_EXPORT WorkletGlobalScopeProxy : public GarbageCollectedMixin {
virtual void FetchAndInvokeScript(
const KURL& module_url_record,
network::mojom::FetchCredentialsMode,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
WorkletPendingTasks*) = 0;
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet_module_responses_map.cc b/chromium/third_party/blink/renderer/core/workers/worklet_module_responses_map.cc
index 4e52f9e18f7..17152f5e186 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet_module_responses_map.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worklet_module_responses_map.cc
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/core/workers/worklet_module_responses_map.h"
#include "base/optional.h"
-#include "third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.h"
+#include "third_party/blink/renderer/platform/cross_thread_functional.h"
namespace blink {
@@ -17,103 +17,48 @@ bool IsValidURL(const KURL& url) {
} // namespace
-class WorkletModuleResponsesMap::Entry final
- : public GarbageCollectedFinalized<Entry>,
- public ModuleScriptFetcher::Client {
- USING_GARBAGE_COLLECTED_MIXIN(WorkletModuleResponsesMap::Entry);
-
- public:
- enum class State { kInitial, kFetching, kFetched, kFailed };
-
- Entry() = default;
- ~Entry() = default;
-
- void Fetch(FetchParameters& fetch_params, ResourceFetcher* fetcher) {
- AdvanceState(State::kFetching);
- module_fetcher_ = new DocumentModuleScriptFetcher(fetcher);
- module_fetcher_->Fetch(fetch_params, this);
- }
-
- State GetState() const { return state_; }
- const ModuleScriptCreationParams& GetParams() const { return *params_; }
-
- void AddClient(WorkletModuleResponsesMap::Client* client) {
- // Clients can be added only while a module script is being fetched.
- DCHECK(state_ == State::kInitial || state_ == State::kFetching);
- clients_.push_back(client);
- }
+void WorkletModuleResponsesMap::Entry::AddClient(
+ ModuleScriptFetcher::Client* client,
+ scoped_refptr<base::SingleThreadTaskRunner> client_task_runner) {
+ // Clients can be added only while a module script is being fetched.
+ DCHECK_EQ(state_, State::kFetching);
+ clients_.insert(client, client_task_runner);
+}
- // Implements ModuleScriptFetcher::Client.
- //
- // Implementation of the second half of the custom fetch defined in the
- // "fetch a worklet script" algorithm:
- // https://drafts.css-houdini.org/worklets/#fetch-a-worklet-script
- void NotifyFetchFinished(
- const base::Optional<ModuleScriptCreationParams>& params,
- const HeapVector<Member<ConsoleMessage>>& error_messages) override {
- // The entry can be disposed of during the resource fetch.
- if (state_ == State::kFailed)
- return;
-
- if (!params) {
- // TODO(nhiroki): Add |error_messages| to the context's message storage.
- NotifyFailure();
- return;
- }
+// Implementation of the second half of the custom fetch defined in the
+// "fetch a worklet script" algorithm:
+// https://drafts.css-houdini.org/worklets/#fetch-a-worklet-script
+void WorkletModuleResponsesMap::Entry::SetParams(
+ const base::Optional<ModuleScriptCreationParams>& params) {
+ DCHECK_EQ(state_, State::kFetching);
- AdvanceState(State::kFetched);
+ if (params) {
+ state_ = State::kFetched;
// Step 7: "Let response be the result of fetch when it asynchronously
// completes."
// Step 8: "Set the value of the entry in cache whose key is url to
// response, and asynchronously complete this algorithm with response."
- params_.emplace(*params);
- for (WorkletModuleResponsesMap::Client* client : clients_)
- client->OnFetched(*params);
- clients_.clear();
- module_fetcher_.Clear();
- }
-
- void NotifyFailure() {
- AdvanceState(State::kFailed);
- for (WorkletModuleResponsesMap::Client* client : clients_)
- client->OnFailed();
- clients_.clear();
- module_fetcher_.Clear();
- }
-
- void Trace(blink::Visitor* visitor) override {
- visitor->Trace(module_fetcher_);
- visitor->Trace(clients_);
- }
-
- private:
- void AdvanceState(State new_state) {
- switch (state_) {
- case State::kInitial:
- DCHECK_EQ(new_state, State::kFetching);
- break;
- case State::kFetching:
- DCHECK(new_state == State::kFetched || new_state == State::kFailed);
- break;
- case State::kFetched:
- case State::kFailed:
- NOTREACHED();
- break;
+ params_.emplace(params->IsolatedCopy());
+ DCHECK(params_->IsSafeToSendToAnotherThread());
+ for (auto& it : clients_) {
+ PostCrossThreadTask(
+ *it.value, FROM_HERE,
+ CrossThreadBind(&ModuleScriptFetcher::Client::OnFetched, it.key,
+ *params));
+ }
+ } else {
+ state_ = State::kFailed;
+ // TODO(nhiroki): Add |error_messages| to the context's message storage.
+ for (auto& it : clients_) {
+ PostCrossThreadTask(
+ *it.value, FROM_HERE,
+ CrossThreadBind(&ModuleScriptFetcher::Client::OnFailed, it.key));
}
- state_ = new_state;
}
- State state_ = State::kInitial;
-
- Member<DocumentModuleScriptFetcher> module_fetcher_;
-
- base::Optional<ModuleScriptCreationParams> params_;
- HeapVector<Member<WorkletModuleResponsesMap::Client>> clients_;
-};
-
-WorkletModuleResponsesMap::WorkletModuleResponsesMap(ResourceFetcher* fetcher)
- : fetcher_(fetcher) {}
+ clients_.clear();
+}
// Implementation of the first half of the custom fetch defined in the
// "fetch a worklet script" algorithm:
@@ -122,73 +67,78 @@ WorkletModuleResponsesMap::WorkletModuleResponsesMap(ResourceFetcher* fetcher)
// "To perform the fetch given request, perform the following steps:"
// Step 1: "Let cache be the moduleResponsesMap."
// Step 2: "Let url be request's url."
-void WorkletModuleResponsesMap::Fetch(FetchParameters& fetch_params,
- Client* client) {
- DCHECK(IsMainThread());
- if (!is_available_ || !IsValidURL(fetch_params.Url())) {
- client->OnFailed();
- return;
+bool WorkletModuleResponsesMap::GetEntry(
+ const KURL& url,
+ ModuleScriptFetcher::Client* client,
+ scoped_refptr<base::SingleThreadTaskRunner> client_task_runner) {
+ MutexLocker lock(mutex_);
+ if (!is_available_ || !IsValidURL(url)) {
+ client_task_runner->PostTask(
+ FROM_HERE, WTF::Bind(&ModuleScriptFetcher::Client::OnFailed,
+ WrapPersistent(client)));
+ return true;
}
- auto it = entries_.find(fetch_params.Url());
+ auto it = entries_.find(url);
if (it != entries_.end()) {
- Entry* entry = it->value;
+ Entry* entry = it->value.get();
switch (entry->GetState()) {
- case Entry::State::kInitial:
- NOTREACHED();
- return;
case Entry::State::kFetching:
// Step 3: "If cache contains an entry with key url whose value is
// "fetching", wait until that entry's value changes, then proceed to
// the next step."
- entry->AddClient(client);
- return;
+ entry->AddClient(client, client_task_runner);
+ return true;
case Entry::State::kFetched:
// Step 4: "If cache contains an entry with key url, asynchronously
// complete this algorithm with that entry's value, and abort these
// steps."
- client->OnFetched(entry->GetParams());
- return;
+ client_task_runner->PostTask(
+ FROM_HERE, WTF::Bind(&ModuleScriptFetcher::Client::OnFetched,
+ WrapPersistent(client), entry->GetParams()));
+ return true;
case Entry::State::kFailed:
// Module fetching failed before. Abort following steps.
- client->OnFailed();
- return;
+ client_task_runner->PostTask(
+ FROM_HERE, WTF::Bind(&ModuleScriptFetcher::Client::OnFailed,
+ WrapPersistent(client)));
+ return true;
}
NOTREACHED();
}
// Step 5: "Create an entry in cache with key url and value "fetching"."
- Entry* entry = new Entry;
- entry->AddClient(client);
- entries_.insert(fetch_params.Url(), entry);
+ std::unique_ptr<Entry> entry = std::make_unique<Entry>();
+ entry->AddClient(client, client_task_runner);
+ entries_.insert(url.Copy(), std::move(entry));
// Step 6: "Fetch request."
// Running the callback with an empty params will make the fetcher to fallback
// to regular module loading and Write() will be called once the fetch is
// complete.
- entry->Fetch(fetch_params, fetcher_.Get());
+ return false;
}
-void WorkletModuleResponsesMap::Invalidate(const KURL& url) {
- DCHECK(IsMainThread());
- DCHECK(IsValidURL(url));
+void WorkletModuleResponsesMap::SetEntryParams(
+ const KURL& url,
+ const base::Optional<ModuleScriptCreationParams>& params) {
+ MutexLocker lock(mutex_);
if (!is_available_)
return;
DCHECK(entries_.Contains(url));
- Entry* entry = entries_.find(url)->value;
- entry->NotifyFailure();
+ Entry* entry = entries_.find(url)->value.get();
+ entry->SetParams(params);
}
void WorkletModuleResponsesMap::Dispose() {
+ DCHECK(IsMainThread());
+ MutexLocker lock(mutex_);
is_available_ = false;
- for (auto it : entries_) {
+ for (auto& it : entries_) {
switch (it.value->GetState()) {
- case Entry::State::kInitial:
- NOTREACHED();
- break;
case Entry::State::kFetching:
- it.value->NotifyFailure();
+ it.value->SetParams(base::nullopt);
break;
case Entry::State::kFetched:
case Entry::State::kFailed:
@@ -198,9 +148,4 @@ void WorkletModuleResponsesMap::Dispose() {
entries_.clear();
}
-void WorkletModuleResponsesMap::Trace(blink::Visitor* visitor) {
- visitor->Trace(fetcher_);
- visitor->Trace(entries_);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet_module_responses_map.h b/chromium/third_party/blink/renderer/core/workers/worklet_module_responses_map.h
index 9bb9d91e2f2..27af4a7df66 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet_module_responses_map.h
+++ b/chromium/third_party/blink/renderer/core/workers/worklet_module_responses_map.h
@@ -7,12 +7,12 @@
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h"
+#include "third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.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_parameters.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/kurl_hash.h"
+#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
namespace blink {
@@ -22,54 +22,76 @@ namespace blink {
// https://drafts.css-houdini.org/worklets/#fetch-a-worklet-script
//
// This acts as a cache for creation params (including source code) of module
-// scripts, but also performs fetch when needed. The creation params are added
-// and retrieved using Fetch(). If a module script for a given URL has already
-// been fetched, Fetch() returns the cached creation params. Otherwise, Fetch()
-// internally creates DocumentModuleScriptFetcher with thie ResourceFetcher that
-// is given to its ctor. Once the module script is fetched, its creation params
-// are cached and Fetch() returns it.
-//
-// TODO(nhiroki): Rename this to WorkletModuleFetchCoordinator, and revise the
-// class-level comment.
+// scripts. The creation params are added using SetEntryParams(), and retrieved
+// using GetEntry(). If a module script for a given URL has already been
+// fetched, GetEntry() returns the cached creation params. Otherwise, GetEntry()
+// returns false and defers to WorkletModuleScriptFetcher to perform the fetch.
+// Once the module script is fetched, its creation params are cached and
+// GetEntry() returns it. This class is created on the main thread and shared
+// across worklet threads. All access to this class should be mutex-guarded,
+// and any data passed in or read out is copied to ensure that this object's
+// internal state can be safely destructed from the main thread.
class CORE_EXPORT WorkletModuleResponsesMap
: public GarbageCollectedFinalized<WorkletModuleResponsesMap> {
public:
- // Used for notifying results of Fetch().
- class CORE_EXPORT Client : public GarbageCollectedMixin {
- public:
- virtual ~Client() = default;
- virtual void OnFetched(const ModuleScriptCreationParams&) = 0;
- virtual void OnFailed() = 0;
- };
-
- explicit WorkletModuleResponsesMap(ResourceFetcher*);
+ WorkletModuleResponsesMap() = default;
- // Fetches a module script. If the script is already fetched, synchronously
- // calls Client::OnFetched(). Otherwise, it's called on the completion of the
- // fetch. See also the class-level comment.
- void Fetch(FetchParameters&, Client*);
+ // If |url| is already fetched, synchronously calls Client::OnFetched().
+ // Otherwise, it's called on the completion of the fetch. See also the
+ // class-level comment.
+ // Called on worklet threads.
+ bool GetEntry(const KURL&,
+ ModuleScriptFetcher::Client*,
+ scoped_refptr<base::SingleThreadTaskRunner> client_task_runner)
+ LOCKS_EXCLUDED(mutex_);
- // Invalidates an inflight module script fetch, and calls OnFailed() for
- // waiting clients.
- void Invalidate(const KURL&);
+ // Called on worklet threads.
+ void SetEntryParams(const KURL&,
+ const base::Optional<ModuleScriptCreationParams>&)
+ LOCKS_EXCLUDED(mutex_);
- // Called when the associated document is destroyed. Aborts all waiting
- // clients and clears the map. Following Fetch() calls are simply ignored.
- void Dispose();
+ // Called when the associated document is destroyed and clears the map.
+ // Following GetEntry() calls synchronously call Client::OnFailed().
+ // Called on main thread.
+ void Dispose() LOCKS_EXCLUDED(mutex_);
- void Trace(blink::Visitor*);
+ void Trace(blink::Visitor*) {}
private:
- class Entry;
+ class Entry final {
+ public:
+ enum class State { kFetching, kFetched, kFailed };
+ Entry() = default;
+ ~Entry() = default;
+
+ State GetState() const { return state_; }
+ ModuleScriptCreationParams GetParams() const {
+ return params_->IsolatedCopy();
+ }
+ void AddClient(
+ ModuleScriptFetcher::Client* client,
+ scoped_refptr<base::SingleThreadTaskRunner> client_task_runner);
+ void SetParams(const base::Optional<ModuleScriptCreationParams>& params);
- bool is_available_ = true;
+ private:
+ State state_ = State::kFetching;
+ base::Optional<ModuleScriptCreationParams> params_;
+ HashMap<CrossThreadPersistent<ModuleScriptFetcher::Client>,
+ scoped_refptr<base::SingleThreadTaskRunner>>
+ clients_;
+ };
- Member<ResourceFetcher> fetcher_;
+ // |is_available_| is written to false by the main thread on disposal, and
+ // read by any thread.
+ bool is_available_ GUARDED_BY(mutex_) = true;
// TODO(nhiroki): Keep the insertion order of top-level modules to replay
// addModule() calls for a newly created global scope.
// See https://drafts.css-houdini.org/worklets/#creating-a-workletglobalscope
- HeapHashMap<KURL, Member<Entry>> entries_;
+ // Can be read/written by any thread.
+ HashMap<KURL, std::unique_ptr<Entry>> entries_ GUARDED_BY(mutex_);
+
+ Mutex mutex_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet_module_responses_map_test.cc b/chromium/third_party/blink/renderer/core/workers/worklet_module_responses_map_test.cc
index a73010ade48..973d86c4b3d 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet_module_responses_map_test.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worklet_module_responses_map_test.cc
@@ -7,6 +7,8 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h"
+#include "third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.h"
+#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/core/workers/worker_fetch_test_helper.h"
#include "third_party/blink/renderer/platform/loader/testing/fetch_testing_platform_support.h"
#include "third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h"
@@ -27,7 +29,7 @@ class WorkletModuleResponsesMapTest : public testing::Test {
auto* context =
MockFetchContext::Create(MockFetchContext::kShouldLoadNewResource);
fetcher_ = ResourceFetcher::Create(context);
- map_ = new WorkletModuleResponsesMap(fetcher_);
+ map_ = new WorkletModuleResponsesMap;
}
void Fetch(const KURL& url, ClientImpl* client) {
@@ -36,7 +38,16 @@ class WorkletModuleResponsesMapTest : public testing::Test {
// "paintworklet").
resource_request.SetRequestContext(WebURLRequest::kRequestContextScript);
FetchParameters fetch_params(resource_request);
- map_->Fetch(fetch_params, client);
+ WorkletModuleScriptFetcher* module_fetcher =
+ new WorkletModuleScriptFetcher(fetcher_.Get(), map_.Get());
+ module_fetcher->Fetch(fetch_params, ModuleGraphLevel::kTopLevelModuleFetch,
+ client);
+ }
+
+ void RunUntilIdle() {
+ base::SingleThreadTaskRunner* runner =
+ fetcher_->Context().GetLoadingTaskRunner().get();
+ static_cast<scheduler::FakeTaskRunner*>(runner)->RunUntilIdle();
}
protected:
@@ -69,6 +80,7 @@ TEST_F(WorkletModuleResponsesMapTest, Basic) {
// Serve the fetch request. This should notify the waiting clients.
platform_->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ RunUntilIdle();
for (auto client : clients) {
EXPECT_EQ(ClientImpl::Result::kOK, client->GetResult());
EXPECT_TRUE(client->GetParams().has_value());
@@ -98,6 +110,7 @@ TEST_F(WorkletModuleResponsesMapTest, Failure) {
// Serve the fetch request with 404. This should fail the waiting clients.
platform_->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ RunUntilIdle();
for (auto client : clients) {
EXPECT_EQ(ClientImpl::Result::kFailed, client->GetResult());
EXPECT_FALSE(client->GetParams().has_value());
@@ -141,6 +154,7 @@ TEST_F(WorkletModuleResponsesMapTest, Isolation) {
// Serve the fetch requests.
platform_->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ RunUntilIdle();
EXPECT_EQ(ClientImpl::Result::kFailed, clients[0]->GetResult());
EXPECT_FALSE(clients[0]->GetParams().has_value());
EXPECT_EQ(ClientImpl::Result::kFailed, clients[1]->GetResult());
@@ -156,6 +170,7 @@ TEST_F(WorkletModuleResponsesMapTest, InvalidURL) {
ASSERT_TRUE(kEmptyURL.IsEmpty());
ClientImpl* client1 = new ClientImpl;
Fetch(kEmptyURL, client1);
+ RunUntilIdle();
EXPECT_EQ(ClientImpl::Result::kFailed, client1->GetResult());
EXPECT_FALSE(client1->GetParams().has_value());
@@ -163,6 +178,7 @@ TEST_F(WorkletModuleResponsesMapTest, InvalidURL) {
ASSERT_TRUE(kNullURL.IsNull());
ClientImpl* client2 = new ClientImpl;
Fetch(kNullURL, client2);
+ RunUntilIdle();
EXPECT_EQ(ClientImpl::Result::kFailed, client2->GetResult());
EXPECT_FALSE(client2->GetParams().has_value());
@@ -170,6 +186,7 @@ TEST_F(WorkletModuleResponsesMapTest, InvalidURL) {
ASSERT_FALSE(kInvalidURL.IsValid());
ClientImpl* client3 = new ClientImpl;
Fetch(kInvalidURL, client3);
+ RunUntilIdle();
EXPECT_EQ(ClientImpl::Result::kFailed, client3->GetResult());
EXPECT_FALSE(client3->GetParams().has_value());
}
@@ -211,6 +228,7 @@ TEST_F(WorkletModuleResponsesMapTest, Dispose) {
// Dispose() should notify to all waiting clients.
map_->Dispose();
+ RunUntilIdle();
for (auto client : clients) {
EXPECT_EQ(ClientImpl::Result::kFailed, client->GetResult());
EXPECT_FALSE(client->GetParams().has_value());
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet_pending_tasks.cc b/chromium/third_party/blink/renderer/core/workers/worklet_pending_tasks.cc
index c87d0beccee..6ee7b4e5cd8 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet_pending_tasks.cc
+++ b/chromium/third_party/blink/renderer/core/workers/worklet_pending_tasks.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/core/workers/worklet_pending_tasks.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/workers/worklet.h"
#include "third_party/blink/renderer/platform/wtf/wtf.h"
@@ -32,7 +31,7 @@ void WorkletPendingTasks::Abort() {
if (counter_ != -1) {
counter_ = -1;
worklet_->FinishPendingTasks(this);
- resolver_->Reject(DOMException::Create(kAbortError));
+ resolver_->Reject(DOMException::Create(DOMExceptionCode::kAbortError));
}
}
diff --git a/chromium/third_party/blink/renderer/core/workers/worklet_thread_holder.h b/chromium/third_party/blink/renderer/core/workers/worklet_thread_holder.h
index 7a982e03fb1..2c783faca90 100644
--- a/chromium/third_party/blink/renderer/core/workers/worklet_thread_holder.h
+++ b/chromium/third_party/blink/renderer/core/workers/worklet_thread_holder.h
@@ -46,16 +46,14 @@ class WorkletThreadHolder {
MutexLocker locker(HolderInstanceMutex());
DCHECK(!thread_holder_instance_);
thread_holder_instance_ = new WorkletThreadHolder<DerivedWorkletThread>;
- thread_holder_instance_->Initialize(
- WorkerBackingThread::CreateForTest(params));
+ thread_holder_instance_->Initialize(WorkerBackingThread::Create(params));
}
static void CreateForTest(WebThread* thread) {
MutexLocker locker(HolderInstanceMutex());
DCHECK(!thread_holder_instance_);
thread_holder_instance_ = new WorkletThreadHolder<DerivedWorkletThread>;
- thread_holder_instance_->Initialize(
- WorkerBackingThread::CreateForTest(thread));
+ thread_holder_instance_->Initialize(WorkerBackingThread::Create(thread));
}
static void ClearInstance() {
diff --git a/chromium/third_party/blink/renderer/core/xml/document_xml_tree_viewer.cc b/chromium/third_party/blink/renderer/core/xml/document_xml_tree_viewer.cc
index bb60c92233c..773262b5379 100644
--- a/chromium/third_party/blink/renderer/core/xml/document_xml_tree_viewer.cc
+++ b/chromium/third_party/blink/renderer/core/xml/document_xml_tree_viewer.cc
@@ -20,13 +20,11 @@ void TransformDocumentToXMLTreeView(Document& document) {
GetDataResourceAsASCIIString("DocumentXMLTreeViewer.js");
String css_string = GetDataResourceAsASCIIString("DocumentXMLTreeViewer.css");
- HeapVector<ScriptSourceCode> sources;
- sources.push_back(
- ScriptSourceCode(script_string, ScriptSourceLocationType::kInternal));
v8::HandleScope handle_scope(V8PerIsolateData::MainThreadIsolate());
document.GetFrame()->GetScriptController().ExecuteScriptInIsolatedWorld(
- IsolatedWorldId::kDocumentXMLTreeViewerWorldId, sources, nullptr);
+ IsolatedWorldId::kDocumentXMLTreeViewerWorldId,
+ ScriptSourceCode(script_string, ScriptSourceLocationType::kInternal));
Element* element = document.getElementById("xml-viewer-style");
if (element) {
diff --git a/chromium/third_party/blink/renderer/core/xml/document_xpath_evaluator.cc b/chromium/third_party/blink/renderer/core/xml/document_xpath_evaluator.cc
index 467bb0bc3e3..e1a1491106c 100644
--- a/chromium/third_party/blink/renderer/core/xml/document_xpath_evaluator.cc
+++ b/chromium/third_party/blink/renderer/core/xml/document_xpath_evaluator.cc
@@ -25,9 +25,10 @@
#include "third_party/blink/renderer/core/xml/document_xpath_evaluator.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/xml/xpath_expression.h"
#include "third_party/blink/renderer/core/xml/xpath_result.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
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 7189bb27b63..b322ad3ac99 100644
--- a/chromium/third_party/blink/renderer/core/xml/dom_parser.cc
+++ b/chromium/third_party/blink/renderer/core/xml/dom_parser.cc
@@ -18,14 +18,39 @@
*/
#include "third_party/blink/renderer/core/xml/dom_parser.h"
-
+#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html.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/dom_implementation.h"
+#include "third_party/blink/renderer/core/trustedtypes/trusted_html.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"
namespace blink {
-Document* DOMParser::parseFromString(const String& str, const String& type) {
+Document* DOMParser::parseFromString(const StringOrTrustedHTML& stringOrHTML,
+ const String& type,
+ ExceptionState& exception_state) {
+ DCHECK(stringOrHTML.IsString() ||
+ RuntimeEnabledFeatures::TrustedDOMTypesEnabled());
+ DCHECK(!stringOrHTML.IsNull());
+ if (context_document_ && stringOrHTML.IsString() &&
+ context_document_->RequireTrustedTypes()) {
+ exception_state.ThrowTypeError(
+ "This document requires `TrustedHTML` assignment.");
+ return nullptr;
+ }
+
+ String valueString = stringOrHTML.IsString()
+ ? stringOrHTML.GetAsString()
+ : stringOrHTML.GetAsTrustedHTML()->toString();
+
+ return parseFromStringInternal(valueString, type);
+}
+
+Document* DOMParser::parseFromStringInternal(const String& str,
+ const String& type) {
Document* doc = DOMImplementation::createDocument(
type, DocumentInit::Create().WithContextDocument(context_document_),
false);
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 cea414f96b5..868e1f9b4ec 100644
--- a/chromium/third_party/blink/renderer/core/xml/dom_parser.h
+++ b/chromium/third_party/blink/renderer/core/xml/dom_parser.h
@@ -27,6 +27,8 @@
namespace blink {
class Document;
+class StringOrTrustedHTML;
+class ExceptionState;
class DOMParser final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
@@ -35,12 +37,15 @@ class DOMParser final : public ScriptWrappable {
static DOMParser* Create(Document& document) {
return new DOMParser(document);
}
-
- Document* parseFromString(const String&, const String& type);
+ Document* parseFromString(const StringOrTrustedHTML&,
+ const String& type,
+ ExceptionState& exception_state);
+ Document* parseFromString(const StringOrTrustedHTML&, const String& type);
void Trace(blink::Visitor*) override;
private:
+ Document* parseFromStringInternal(const String&, const String& type);
explicit DOMParser(Document&);
WeakMember<Document> context_document_;
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 110d1ee1e58..b478df5d8e8 100644
--- a/chromium/third_party/blink/renderer/core/xml/dom_parser.idl
+++ b/chromium/third_party/blink/renderer/core/xml/dom_parser.idl
@@ -18,6 +18,9 @@
*/
// https://w3c.github.io/DOM-Parsing/#the-domparser-interface
+// The `HTMLString` reference below is from Trusted Types:
+// https://github.com/WICG/trusted-types/, which is still WIP.
+// https://crbug.com/739170.
enum SupportedType {
"text/html",
@@ -32,5 +35,5 @@ enum SupportedType {
ConstructorCallWith=Document,
Exposed=Window
] interface DOMParser {
- [NewObject] Document parseFromString(DOMString str, SupportedType type);
+ [NewObject, RaisesException] Document parseFromString(HTMLString str, SupportedType type);
};
diff --git a/chromium/third_party/blink/renderer/core/xml/parser/shared_buffer_reader.cc b/chromium/third_party/blink/renderer/core/xml/parser/shared_buffer_reader.cc
index 36f485bbaab..e9e9477a097 100644
--- a/chromium/third_party/blink/renderer/core/xml/parser/shared_buffer_reader.cc
+++ b/chromium/third_party/blink/renderer/core/xml/parser/shared_buffer_reader.cc
@@ -48,21 +48,19 @@ int SharedBufferReader::ReadData(char* output_buffer, int asked_to_read) {
return 0;
size_t bytes_copied = 0;
- size_t bytes_left = buffer_->size() - current_offset_;
- size_t len_to_copy = std::min(SafeCast<size_t>(asked_to_read), bytes_left);
-
- while (bytes_copied < len_to_copy) {
- const char* data;
- size_t segment_size = buffer_->GetSomeData(data, current_offset_);
- if (!segment_size)
+ size_t len_to_copy = std::min(SafeCast<size_t>(asked_to_read),
+ buffer_->size() - current_offset_);
+ for (auto it = buffer_->GetIteratorAt(current_offset_); it != buffer_->cend();
+ ++it) {
+ if (bytes_copied >= len_to_copy)
break;
+ size_t to_be_written = std::min(it->size(), len_to_copy - bytes_copied);
- segment_size = std::min(segment_size, len_to_copy - bytes_copied);
- memcpy(output_buffer + bytes_copied, data, segment_size);
- bytes_copied += segment_size;
- current_offset_ += segment_size;
+ memcpy(output_buffer + bytes_copied, it->data(), to_be_written);
+ bytes_copied += to_be_written;
}
+ current_offset_ += bytes_copied;
return SafeCast<int>(bytes_copied);
}
diff --git a/chromium/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc b/chromium/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc
index 9744de383d9..d0539f61e4b 100644
--- a/chromium/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc
+++ b/chromium/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc
@@ -28,6 +28,10 @@
#include <libxml/parser.h>
#include <libxml/parserInternals.h>
+#include <libxml/xmlversion.h>
+#if defined(LIBXML_CATALOG_ENABLED)
+#include <libxml/catalog.h>
+#endif
#include <libxslt/xslt.h>
#include <memory>
@@ -648,6 +652,9 @@ static void InitializeLibXMLIfNecessary() {
if (did_init)
return;
+#if defined(LIBXML_CATALOG_ENABLED)
+ xmlCatalogSetDefaults(XML_CATA_ALLOW_NONE);
+#endif
xmlInitParser();
xmlRegisterInputCallbacks(MatchFunc, OpenFunc, ReadFunc, CloseFunc);
xmlRegisterOutputCallbacks(MatchFunc, OpenFunc, WriteFunc, CloseFunc);
diff --git a/chromium/third_party/blink/renderer/core/xml/xpath_evaluator.cc b/chromium/third_party/blink/renderer/core/xml/xpath_evaluator.cc
index 280c034fa36..7aff10329b3 100644
--- a/chromium/third_party/blink/renderer/core/xml/xpath_evaluator.cc
+++ b/chromium/third_party/blink/renderer/core/xml/xpath_evaluator.cc
@@ -26,13 +26,13 @@
#include "third_party/blink/renderer/core/xml/xpath_evaluator.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/xml/native_xpath_ns_resolver.h"
#include "third_party/blink/renderer/core/xml/xpath_expression.h"
#include "third_party/blink/renderer/core/xml/xpath_result.h"
#include "third_party/blink/renderer/core/xml/xpath_util.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -58,9 +58,9 @@ XPathResult* XPathEvaluator::evaluate(const String& expression,
ExceptionState& exception_state) {
if (!IsValidContextNode(context_node)) {
exception_state.ThrowDOMException(
- kNotSupportedError, "The node provided is '" +
- context_node->nodeName() +
- "', which is not a valid context node type.");
+ DOMExceptionCode::kNotSupportedError,
+ "The node provided is '" + context_node->nodeName() +
+ "', which is not a valid context node type.");
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/xml/xpath_expression.cc b/chromium/third_party/blink/renderer/core/xml/xpath_expression.cc
index 68054d6e431..7476499914a 100644
--- a/chromium/third_party/blink/renderer/core/xml/xpath_expression.cc
+++ b/chromium/third_party/blink/renderer/core/xml/xpath_expression.cc
@@ -26,13 +26,12 @@
#include "third_party/blink/renderer/core/xml/xpath_expression.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/xml/xpath_expression_node.h"
#include "third_party/blink/renderer/core/xml/xpath_ns_resolver.h"
#include "third_party/blink/renderer/core/xml/xpath_parser.h"
#include "third_party/blink/renderer/core/xml/xpath_result.h"
#include "third_party/blink/renderer/core/xml/xpath_util.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -67,9 +66,9 @@ XPathResult* XPathExpression::evaluate(Node* context_node,
ExceptionState& exception_state) {
if (!IsValidContextNode(context_node)) {
exception_state.ThrowDOMException(
- kNotSupportedError, "The node provided is '" +
- context_node->nodeName() +
- "', which is not a valid context node type.");
+ DOMExceptionCode::kNotSupportedError,
+ "The node provided is '" + context_node->nodeName() +
+ "', which is not a valid context node type.");
return nullptr;
}
@@ -81,7 +80,7 @@ XPathResult* XPathExpression::evaluate(Node* context_node,
// It is not specified what to do if type conversion fails while evaluating
// an expression.
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"Type conversion failed while evaluating the expression.");
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/xml/xpath_parser.cc b/chromium/third_party/blink/renderer/core/xml/xpath_parser.cc
index ac7baffc52c..12ed5132ae3 100644
--- a/chromium/third_party/blink/renderer/core/xml/xpath_parser.cc
+++ b/chromium/third_party/blink/renderer/core/xml/xpath_parser.cc
@@ -28,12 +28,11 @@
#include "third_party/blink/renderer/core/xml/xpath_parser.h"
#include "base/memory/ptr_util.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/xml/xpath_evaluator.h"
#include "third_party/blink/renderer/core/xml/xpath_ns_resolver.h"
#include "third_party/blink/renderer/core/xml/xpath_path.h"
#include "third_party/blink/renderer/core/xpath_grammar.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
@@ -490,11 +489,11 @@ Expression* Parser::ParseStatement(const String& statement,
if (got_namespace_error_)
exception_state.ThrowDOMException(
- kNamespaceError,
+ DOMExceptionCode::kNamespaceError,
"The string '" + statement + "' contains unresolvable namespaces.");
else
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"The string '" + statement + "' is not a valid XPath expression.");
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/core/xml/xpath_result.cc b/chromium/third_party/blink/renderer/core/xml/xpath_result.cc
index 96cd090cc1b..60da3f148e1 100644
--- a/chromium/third_party/blink/renderer/core/xml/xpath_result.cc
+++ b/chromium/third_party/blink/renderer/core/xml/xpath_result.cc
@@ -26,11 +26,10 @@
#include "third_party/blink/renderer/core/xml/xpath_result.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/xml/xpath_evaluator.h"
#include "third_party/blink/renderer/core/xml/xpath_expression_node.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -188,7 +187,7 @@ Node* XPathResult::iterateNext(ExceptionState& exception_state) {
if (invalidIteratorState()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"The document has mutated since the result was returned.");
return nullptr;
}
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 9e74930b253..b59f7fc0cff 100644
--- a/chromium/third_party/blink/renderer/core/xml/xslt_processor.cc
+++ b/chromium/third_party/blink/renderer/core/xml/xslt_processor.cc
@@ -24,6 +24,7 @@
#include "third_party/blink/renderer/core/dom/document_encoding_data.h"
#include "third_party/blink/renderer/core/dom/document_fragment.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/editing/serializers/serialization.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
diff --git a/chromium/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc b/chromium/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc
index 1605256724d..bb879481ed5 100644
--- a/chromium/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc
+++ b/chromium/third_party/blink/renderer/core/xml/xslt_processor_libxslt.cc
@@ -26,6 +26,7 @@
#include <libxslt/security.h>
#include <libxslt/variables.h>
#include <libxslt/xsltutils.h>
+#include "base/numerics/checked_math.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/transform_source.h"
@@ -134,12 +135,13 @@ static xmlDocPtr DocLoaderFunc(const xmlChar* uri,
xmlParserCtxtPtr ctx = xmlCreatePushParserCtxt(
nullptr, nullptr, nullptr, 0, reinterpret_cast<const char*>(uri));
if (ctx && !xmlCtxtUseOptions(ctx, options)) {
- data->ForEachSegment([&data, &ctx](const char* segment,
- size_t segment_size,
- size_t segment_offset) -> bool {
- bool final_chunk = segment_offset + segment_size == data->size();
- return !xmlParseChunk(ctx, segment, segment_size, final_chunk);
- });
+ size_t offset = 0;
+ for (const auto& span : *data) {
+ bool final_chunk = offset + span.size() == data->size();
+ if (!xmlParseChunk(ctx, span.data(), span.size(), final_chunk))
+ break;
+ offset += span.size();
+ }
if (ctx->wellFormed)
doc = ctx->myDoc;
@@ -233,7 +235,7 @@ static const char** XsltParamArrayFromParameterMap(
if (parameters.IsEmpty())
return nullptr;
- WTF::CheckedSizeT size = parameters.size();
+ base::CheckedNumeric<size_t> size = parameters.size();
size *= 2;
++size;
size *= sizeof(char*);
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 d9f6ad5f813..bebe41442b7 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
@@ -24,19 +24,19 @@
#include "third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h"
#include <memory>
+
#include "base/auto_reset.h"
+#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/public/platform/web_cors.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view_or_blob_or_document_or_string_or_form_data_or_url_search_params.h"
#include "third_party/blink/renderer/bindings/core/v8/array_buffer_or_array_buffer_view_or_blob_or_usv_string.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/document_init.h"
#include "third_party/blink/renderer/core/dom/document_parser.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/dom/dom_implementation.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/xml_document.h"
#include "third_party/blink/renderer/core/editing/serializers/serialization.h"
#include "third_party/blink/renderer/core/events/progress_event.h"
@@ -66,6 +66,7 @@
#include "third_party/blink/renderer/core/url/url_search_params.h"
#include "third_party/blink/renderer/core/xmlhttprequest/xml_http_request_upload.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.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/blob/blob_data.h"
#include "third_party/blink/renderer/platform/exported/wrapped_resource_response.h"
@@ -90,6 +91,7 @@
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/cstring.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -202,7 +204,8 @@ bool ValidateOpenArguments(const AtomicString& method,
ExceptionState& exception_state) {
if (!IsValidHTTPToken(method)) {
exception_state.ThrowDOMException(
- kSyntaxError, "'" + method + "' is not a valid HTTP method.");
+ DOMExceptionCode::kSyntaxError,
+ "'" + method + "' is not a valid HTTP method.");
return false;
}
@@ -213,7 +216,8 @@ bool ValidateOpenArguments(const AtomicString& method,
}
if (!url.IsValid()) {
- exception_state.ThrowDOMException(kSyntaxError, "Invalid URL");
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
+ "Invalid URL");
return false;
}
@@ -326,7 +330,7 @@ v8::Local<v8::String> XMLHttpRequest::responseText(
ExceptionState& exception_state) {
if (response_type_code_ != kResponseTypeDefault &&
response_type_code_ != kResponseTypeText) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The value is only accessible if the "
"object's 'responseType' is '' or 'text' "
"(was '" +
@@ -375,7 +379,7 @@ void XMLHttpRequest::InitResponseDocument() {
Document* XMLHttpRequest::responseXML(ExceptionState& exception_state) {
if (response_type_code_ != kResponseTypeDefault &&
response_type_code_ != kResponseTypeDocument) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The value is only accessible if the "
"object's 'responseType' is '' or "
"'document' (was '" +
@@ -413,12 +417,8 @@ Blob* XMLHttpRequest::ResponseBlob() {
blob_data->SetContentType(FinalResponseMIMETypeWithFallback().LowerASCII());
size_t size = 0;
if (binary_response_builder_ && binary_response_builder_->size()) {
- binary_response_builder_->ForEachSegment(
- [&blob_data](const char* segment, size_t segment_size,
- size_t segment_offset) -> bool {
- blob_data->AppendBytes(segment, segment_size);
- return true;
- });
+ for (const auto& span : *binary_response_builder_)
+ blob_data->AppendBytes(span.data(), span.size());
size = binary_response_builder_->size();
binary_response_builder_ = nullptr;
ReportMemoryUsageToV8();
@@ -471,7 +471,7 @@ void XMLHttpRequest::setTimeout(unsigned timeout,
// fetching is in progress. If that occurs it will still be measured relative
// to the start of fetching."
if (GetExecutionContext() && GetExecutionContext()->IsDocument() && !async_) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"Timeouts cannot be set for synchronous "
"requests made from a document.");
return;
@@ -492,7 +492,7 @@ void XMLHttpRequest::setTimeout(unsigned timeout,
void XMLHttpRequest::setResponseType(const String& response_type,
ExceptionState& exception_state) {
if (state_ >= kLoading) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The response type cannot be set if the "
"object's state is LOADING or DONE.");
return;
@@ -502,7 +502,7 @@ void XMLHttpRequest::setResponseType(const String& response_type,
// contexts, as a spec-mandated attempt to discourage synchronous XHR use.
// responseType is one such piece of functionality.
if (GetExecutionContext() && GetExecutionContext()->IsDocument() && !async_) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The response type cannot be changed for "
"synchronous requests made from a "
"document.");
@@ -607,7 +607,7 @@ void XMLHttpRequest::setWithCredentials(bool value,
ExceptionState& exception_state) {
if (state_ > kOpened || send_flag_) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"The value may only be set if the object's state is UNSENT or OPENED.");
return;
}
@@ -670,7 +670,7 @@ void XMLHttpRequest::open(const AtomicString& method,
if (GetDocument()->GetSettings() &&
!GetDocument()->GetSettings()->GetSyncXHRInDocumentsEnabled()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"Synchronous requests are disabled for this page.");
return;
}
@@ -680,7 +680,7 @@ void XMLHttpRequest::open(const AtomicString& method,
// responseType is one such piece of functionality.
if (response_type_code_ != kResponseTypeDefault) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"Synchronous requests from a document must not set a response type.");
return;
}
@@ -688,7 +688,8 @@ void XMLHttpRequest::open(const AtomicString& method,
// Similarly, timeouts are disabled for synchronous requests as well.
if (timeout_milliseconds_ > 0) {
exception_state.ThrowDOMException(
- kInvalidAccessError, "Synchronous requests must not set a timeout.");
+ DOMExceptionCode::kInvalidAccessError,
+ "Synchronous requests must not set a timeout.");
return;
}
@@ -708,8 +709,7 @@ void XMLHttpRequest::open(const AtomicString& method,
url_ = url;
- if (url_.ProtocolIs("blob") &&
- RuntimeEnabledFeatures::MojoBlobURLsEnabled()) {
+ if (url_.ProtocolIs("blob") && BlobUtils::MojoBlobURLsEnabled()) {
GetExecutionContext()->GetPublicURLManager().Resolve(
url_, MakeRequest(&blob_url_loader_factory_));
}
@@ -739,14 +739,13 @@ bool XMLHttpRequest::InitSend(ExceptionState& exception_state) {
}
if (state_ != kOpened || send_flag_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The object's state must be OPENED.");
return false;
}
if (!async_) {
if (GetExecutionContext()->IsDocument() &&
- IsSupportedInFeaturePolicy(mojom::FeaturePolicyFeature::kSyncXHR) &&
!GetDocument()->GetFrame()->IsFeatureEnabled(
mojom::FeaturePolicyFeature::kSyncXHR)) {
LogConsoleError(GetExecutionContext(),
@@ -969,16 +968,19 @@ void XMLHttpRequest::SendForInspectorXHRReplay(
scoped_refptr<EncodedFormData> form_data,
ExceptionState& exception_state) {
CreateRequest(form_data ? form_data->DeepCopy() : nullptr, exception_state);
- exception_code_ = exception_state.Code();
+ if (exception_state.HadException()) {
+ CHECK(IsDOMExceptionCode(exception_state.Code()));
+ exception_code_ = exception_state.CodeAs<DOMExceptionCode>();
+ }
}
void XMLHttpRequest::ThrowForLoadFailureIfNeeded(
ExceptionState& exception_state,
const String& reason) {
- if (error_ && !exception_code_)
- exception_code_ = kNetworkError;
+ if (error_ && exception_code_ == DOMExceptionCode::kNoError)
+ exception_code_ = DOMExceptionCode::kNetworkError;
- if (!exception_code_)
+ if (exception_code_ == DOMExceptionCode::kNoError)
return;
String message = "Failed to load '" + url_.ElidedString() + "'";
@@ -1099,7 +1101,7 @@ void XMLHttpRequest::CreateRequest(scoped_refptr<EncodedFormData> http_body,
resource_loader_options.data_buffering_policy = kDoNotBufferData;
}
- exception_code_ = 0;
+ exception_code_ = DOMExceptionCode::kNoError;
error_ = false;
if (async_) {
@@ -1171,8 +1173,8 @@ void XMLHttpRequest::abort() {
if ((state_ == kOpened && send_flag_) || state_ == kHeadersReceived ||
state_ == kLoading) {
DCHECK(!loader_);
- HandleRequestError(0, EventTypeNames::abort, received_length,
- expected_length);
+ HandleRequestError(DOMExceptionCode::kNoError, EventTypeNames::abort,
+ received_length, expected_length);
}
}
if (state_ == kDone)
@@ -1180,7 +1182,6 @@ void XMLHttpRequest::abort() {
}
void XMLHttpRequest::Dispose() {
- probe::detachClientRequest(GetExecutionContext(), this);
progress_event_throttle_->Stop();
InternalAbort();
// TODO(yhirano): Remove this CHECK: see https://crbug.com/570946.
@@ -1307,8 +1308,8 @@ void XMLHttpRequest::HandleNetworkError() {
if (!InternalAbort())
return;
- HandleRequestError(kNetworkError, EventTypeNames::error, received_length,
- expected_length);
+ HandleRequestError(DOMExceptionCode::kNetworkError, EventTypeNames::error,
+ received_length, expected_length);
}
void XMLHttpRequest::HandleDidCancel() {
@@ -1321,21 +1322,21 @@ void XMLHttpRequest::HandleDidCancel() {
if (!InternalAbort())
return;
- HandleRequestError(kAbortError, EventTypeNames::abort, received_length,
- expected_length);
+ HandleRequestError(DOMExceptionCode::kAbortError, EventTypeNames::abort,
+ received_length, expected_length);
}
-void XMLHttpRequest::HandleRequestError(ExceptionCode exception_code,
+void XMLHttpRequest::HandleRequestError(DOMExceptionCode exception_code,
const AtomicString& type,
long long received_length,
long long expected_length) {
NETWORK_DVLOG(1) << this << " handleRequestError()";
- probe::didFailXHRLoading(GetExecutionContext(), this, this, method_, url_);
+ probe::didFinishXHR(GetExecutionContext(), this);
send_flag_ = false;
if (!async_) {
- DCHECK(exception_code);
+ DCHECK_NE(exception_code, DOMExceptionCode::kNoError);
state_ = kDone;
exception_code_ = exception_code;
return;
@@ -1370,7 +1371,7 @@ void XMLHttpRequest::overrideMimeType(const AtomicString& mime_type,
ExceptionState& exception_state) {
if (state_ == kLoading || state_ == kDone) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"MimeType cannot be overridden when the state is LOADING or DONE.");
return;
}
@@ -1387,7 +1388,7 @@ void XMLHttpRequest::setRequestHeader(const AtomicString& name,
// "1. If |state| is not "opened", throw an InvalidStateError exception.
// 2. If the send() flag is set, throw an InvalidStateError exception."
if (state_ != kOpened || send_flag_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The object's state must be OPENED.");
return;
}
@@ -1399,12 +1400,13 @@ void XMLHttpRequest::setRequestHeader(const AtomicString& name,
// exception."
if (!IsValidHTTPToken(name)) {
exception_state.ThrowDOMException(
- kSyntaxError, "'" + name + "' is not a valid HTTP header field name.");
+ DOMExceptionCode::kSyntaxError,
+ "'" + name + "' is not a valid HTTP header field name.");
return;
}
if (!IsValidHTTPHeaderValue(normalized_value)) {
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"'" + normalized_value + "' is not a valid HTTP header field value.");
return;
}
@@ -1706,7 +1708,7 @@ void XMLHttpRequest::NotifyParserStopped() {
}
void XMLHttpRequest::EndLoading() {
- probe::didFinishXHRLoading(GetExecutionContext(), this, this, method_, url_);
+ probe::didFinishXHR(GetExecutionContext(), this);
if (loader_) {
// Set |m_error| in order to suppress the cancel notification (see
@@ -1751,6 +1753,9 @@ void XMLHttpRequest::DidReceiveResponse(
unsigned long identifier,
const ResourceResponse& response,
std::unique_ptr<WebDataConsumerHandle> handle) {
+ // TODO(yhirano): Remove this CHECK: see https://crbug.com/570946.
+ CHECK(&response);
+
ALLOW_UNUSED_LOCAL(handle);
DCHECK(!handle);
NETWORK_DVLOG(1) << this << " didReceiveResponse(" << identifier << ")";
@@ -1939,8 +1944,8 @@ void XMLHttpRequest::HandleDidTimeout() {
if (!InternalAbort())
return;
- HandleRequestError(kTimeoutError, EventTypeNames::timeout, received_length,
- expected_length);
+ HandleRequestError(DOMExceptionCode::kTimeoutError, EventTypeNames::timeout,
+ received_length, expected_length);
}
void XMLHttpRequest::Pause() {
@@ -2005,19 +2010,12 @@ void XMLHttpRequest::Trace(blink::Visitor* visitor) {
visitor->Trace(progress_event_throttle_);
visitor->Trace(upload_);
visitor->Trace(blob_loader_);
+ visitor->Trace(response_text_);
XMLHttpRequestEventTarget::Trace(visitor);
DocumentParserClient::Trace(visitor);
PausableObject::Trace(visitor);
}
-void XMLHttpRequest::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(response_blob_);
- visitor->TraceWrappers(response_document_);
- visitor->TraceWrappers(response_array_buffer_);
- visitor->TraceWrappers(response_text_);
- XMLHttpRequestEventTarget::TraceWrappers(visitor);
-}
-
std::ostream& operator<<(std::ostream& ostream, const XMLHttpRequest* xhr) {
return ostream << "XMLHttpRequest " << static_cast<const void*>(xhr);
}
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 6780e581789..479cac9f6c3 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
@@ -24,15 +24,16 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_XMLHTTPREQUEST_XML_HTTP_REQUEST_H_
#include <memory>
+
#include "base/memory/scoped_refptr.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/core/dom/document_parser_client.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/pausable_object.h"
#include "third_party/blink/renderer/core/loader/threadable_loader_client.h"
#include "third_party/blink/renderer/core/xmlhttprequest/xml_http_request_event_target.h"
#include "third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.h"
+#include "third_party/blink/renderer/platform/bindings/exception_code.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_string.h"
@@ -167,7 +168,6 @@ class XMLHttpRequest final : public XMLHttpRequestEventTarget,
DEFINE_ATTRIBUTE_EVENT_LISTENER(readystatechange);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override { return "XMLHttpRequest"; }
private:
@@ -281,7 +281,7 @@ class XMLHttpRequest final : public XMLHttpRequestEventTarget,
// Handles didFail() call for timeout.
void HandleDidTimeout();
- void HandleRequestError(ExceptionCode,
+ void HandleRequestError(DOMExceptionCode,
const AtomicString&,
long long,
long long);
@@ -323,7 +323,7 @@ class XMLHttpRequest final : public XMLHttpRequestEventTarget,
// Avoid using a flat WTF::String here and rather use a traced v8::String
// which internally builds a string rope.
- TraceWrapperV8String response_text_;
+ GC_PLUGIN_IGNORE("crbug.com/841830") TraceWrapperV8String response_text_;
TraceWrapperMember<Document> response_document_;
Member<DocumentParser> response_document_parser_;
@@ -340,7 +340,7 @@ class XMLHttpRequest final : public XMLHttpRequestEventTarget,
// An exception to throw in synchronous mode. It's set when failure
// notification is received from m_loader and thrown at the end of send() if
// any.
- ExceptionCode exception_code_ = 0;
+ DOMExceptionCode exception_code_ = DOMExceptionCode::kNoError;
Member<XMLHttpRequestProgressEventThrottle> progress_event_throttle_;
diff --git a/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.cc b/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.cc
index 24b6b31e147..c4ccc751976 100644
--- a/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.cc
+++ b/chromium/third_party/blink/renderer/core/xmlhttprequest/xml_http_request_progress_event_throttle.cc
@@ -40,8 +40,8 @@
namespace blink {
-static const double kMinimumProgressEventDispatchingIntervalInSeconds =
- .05; // 50 ms per specification.
+static constexpr TimeDelta kMinimumProgressEventDispatchingInterval =
+ TimeDelta::FromMilliseconds(50); // 50 ms per specification.
XMLHttpRequestProgressEventThrottle::DeferredEvent::DeferredEvent() {
Clear();
@@ -105,7 +105,7 @@ void XMLHttpRequestProgressEventThrottle::DispatchProgressEvent(
} else {
DispatchProgressProgressEvent(ProgressEvent::Create(
EventTypeNames::progress, length_computable, loaded, total));
- StartOneShot(kMinimumProgressEventDispatchingIntervalInSeconds, FROM_HERE);
+ StartOneShot(kMinimumProgressEventDispatchingInterval, FROM_HERE);
}
}
@@ -169,7 +169,7 @@ void XMLHttpRequestProgressEventThrottle::Fired() {
DispatchProgressProgressEvent(deferred_.Take());
// Watch if another "progress" ProgressEvent arrives in the next 50ms.
- StartOneShot(kMinimumProgressEventDispatchingIntervalInSeconds, FROM_HERE);
+ StartOneShot(kMinimumProgressEventDispatchingInterval, FROM_HERE);
}
void XMLHttpRequestProgressEventThrottle::Pause() {
diff --git a/chromium/third_party/blink/renderer/devtools/BUILD.gn b/chromium/third_party/blink/renderer/devtools/BUILD.gn
index bd71028a610..e21a157ae92 100644
--- a/chromium/third_party/blink/renderer/devtools/BUILD.gn
+++ b/chromium/third_party/blink/renderer/devtools/BUILD.gn
@@ -174,9 +174,11 @@ all_devtools_files = [
"front_end/console/ConsoleFilter.js",
"front_end/console/ConsoleSidebar.js",
"front_end/console/ConsolePanel.js",
+ "front_end/console/ConsolePinPane.js",
"front_end/console/ConsolePrompt.js",
"front_end/console/consoleView.css",
"front_end/console/consoleContextSelector.css",
+ "front_end/console/consolePinPane.css",
"front_end/console/consoleSidebar.css",
"front_end/console/ConsoleView.js",
"front_end/console/ConsoleViewMessage.js",
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/Runtime.js b/chromium/third_party/blink/renderer/devtools/front_end/Runtime.js
index cee223667e5..f48f9e4c6cf 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/Runtime.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/Runtime.js
@@ -43,6 +43,8 @@ const baseUrl = self.location ? self.location.origin + self.location.pathname :
self._importScriptPathPrefix = baseUrl.substring(0, baseUrl.lastIndexOf('/') + 1);
})();
+const REMOTE_MODULE_FALLBACK_REVISION = '@010ddcfda246975d194964ccf20038ebbdec6084';
+
/**
* @unrestricted
*/
@@ -91,8 +93,11 @@ var Runtime = class { // eslint-disable-line
if (xhr.readyState !== XMLHttpRequest.DONE)
return;
- if ([0, 200, 304].indexOf(xhr.status) === -1) // Testing harness file:/// results in 0.
- reject(new Error('While loading from url ' + url + ' server responded with a status of ' + xhr.status));
+ // DevTools Proxy server can mask 404s as 200s, check the body to be sure
+ const status = /^HTTP\/1.1 404/.test(e.target.response) ? 404 : xhr.status;
+
+ if ([0, 200, 304].indexOf(status) === -1) // Testing harness file:/// results in 0.
+ reject(new Error('While loading from url ' + url + ' server responded with a status of ' + status));
else
fulfill(e.target.response);
}
@@ -101,6 +106,20 @@ var Runtime = class { // eslint-disable-line
}
/**
+ * @param {string} url
+ * @return {!Promise.<string>}
+ */
+ static loadResourcePromiseWithFallback(url) {
+ return Runtime.loadResourcePromise(url).catch(err => {
+ const urlWithFallbackVersion = url.replace(/@[0-9a-f]{40}/, REMOTE_MODULE_FALLBACK_REVISION);
+ // TODO(phulce): mark fallbacks in module.json and modify build script instead
+ if (urlWithFallbackVersion === url || !url.includes('audits2_worker_module'))
+ throw err;
+ return Runtime.loadResourcePromise(urlWithFallbackVersion);
+ });
+ }
+
+ /**
* http://tools.ietf.org/html/rfc3986#section-5.2.4
* @param {string} path
* @return {string}
@@ -157,8 +176,10 @@ var Runtime = class { // eslint-disable-line
if (_loadedScripts[sourceURL])
continue;
urls.push(sourceURL);
- promises.push(Runtime.loadResourcePromise(sourceURL).then(
- scriptSourceLoaded.bind(null, i), scriptSourceLoaded.bind(null, i, undefined)));
+ const loadResourcePromise =
+ base ? Runtime.loadResourcePromiseWithFallback(sourceURL) : Runtime.loadResourcePromise(sourceURL);
+ promises.push(
+ loadResourcePromise.then(scriptSourceLoaded.bind(null, i), scriptSourceLoaded.bind(null, i, undefined)));
}
return Promise.all(promises).then(undefined);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2Controller.js b/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2Controller.js
index 2adb2987c5d..843e716241f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2Controller.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2Controller.js
@@ -255,16 +255,16 @@ Audits2.RuntimeSettings = [
{
setting: Common.settings.createSetting('audits2.throttling', 'default'),
setFlags: (flags, value) => {
- switch (value) {
- case 'devtools':
- flags.throttlingMethod = 'devtools';
- break;
- case 'off':
- flags.throttlingMethod = 'provided';
- break;
- default:
- flags.throttlingMethod = 'simulate';
- }
+ switch (value) {
+ case 'devtools':
+ flags.throttlingMethod = 'devtools';
+ break;
+ case 'off':
+ flags.throttlingMethod = 'provided';
+ break;
+ default:
+ flags.throttlingMethod = 'simulate';
+ }
},
options: [
{
@@ -287,17 +287,16 @@ Audits2.RuntimeSettings = [
{
setting: Common.settings.createSetting('audits2.clear_storage', true),
title: ls`Clear storage`,
- description: ls
- `Reset storage (localStorage, IndexedDB, etc) before auditing. (Recommended for performance & PWA testing)`,
+ description: ls`Reset storage (localStorage, IndexedDB, etc) before auditing. (Good for performance & PWA testing)`,
setFlags: (flags, value) => {
flags.disableStorageReset = !value;
},
},
];
- Audits2.Events = {
- PageAuditabilityChanged: Symbol('PageAuditabilityChanged'),
- AuditProgressChanged: Symbol('AuditProgressChanged'),
- RequestAuditStart: Symbol('RequestAuditStart'),
- RequestAuditCancel: Symbol('RequestAuditCancel'),
- };
+Audits2.Events = {
+ PageAuditabilityChanged: Symbol('PageAuditabilityChanged'),
+ AuditProgressChanged: Symbol('AuditProgressChanged'),
+ RequestAuditStart: Symbol('RequestAuditStart'),
+ RequestAuditCancel: Symbol('RequestAuditCancel'),
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2ReportSelector.js b/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2ReportSelector.js
index 59261aa33ae..eb5aef7a389 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2ReportSelector.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2/Audits2ReportSelector.js
@@ -7,6 +7,7 @@ Audits2.ReportSelector = class {
this._renderNewAuditView = renderNewAuditView;
this._newAuditItem = createElement('option');
this._comboBox = new UI.ToolbarComboBox(this._handleChange.bind(this), 'audits2-report');
+ this._comboBox.setTitle(ls`Reports`);
this._comboBox.setMaxWidth(180);
this._comboBox.setMinWidth(140);
this._itemByOptionElement = new Map();
@@ -135,9 +136,10 @@ Audits2.ReportSelector.Item = class {
}
download() {
- const url = new Common.ParsedURL(this._lighthouseResult.finalUrl).domain();
+ const domain = new Common.ParsedURL(this._lighthouseResult.finalUrl).domain();
+ const sanitizedDomain = domain.replace(/[^a-z0-9.-]+/gi, '_');
const timestamp = this._lighthouseResult.fetchTime;
- const fileName = `${url}-${new Date(timestamp).toISO8601Compact()}.json`;
+ const fileName = `${sanitizedDomain}-${new Date(timestamp).toISO8601Compact()}.json`;
Workspace.fileManager.save(fileName, JSON.stringify(this._lighthouseResult), true);
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2/audits2Panel.css b/chromium/third_party/blink/renderer/devtools/front_end/audits2/audits2Panel.css
index b1e84b9316a..92ee823f463 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits2/audits2Panel.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2/audits2Panel.css
@@ -11,12 +11,18 @@
.lh-root {
--report-menu-width: 0;
- user-select: initial;
+ user-select: text;
--lh-bg-color: #fff;
background-color: var(--lh-bg-color);
}
.-theme-with-dark-background .lh-root {
+ --header-bg-color: hsl(0, 0%, 20%);
+ --lh-table-header-bg: hsl(0, 0%, 20%);
+ --display-value-gray: hsl(0, 0%, 66%);
+ --medium-75-gray: hsl(0, 0%, 66%);
+
+ --subheader-color: hsl(210, 15%, 80%);
--lh-bg-color: hsl(0, 0%, 14%);
--secondary-text-color: hsl(0, 0%, 66%);
--report-secondary-border-color: hsl(0, 0%, 8%);
@@ -47,3 +53,30 @@ button.view-trace {
overflow-y: scroll;
position: relative;
}
+
+/* TODO(phulce): remove the below on next LH roll */
+
+.-theme-with-dark-background .lh-scores-wrapper__background, .-theme-with-dark-background .lh-scores-wrapper__shadow {
+ background: var(--lh-bg-color) !important;
+}
+
+.-theme-with-dark-background .lh-gauge__label {
+ color: hsl(210, 15%, 80%);
+}
+
+.-theme-with-dark-background .lh-root .lh-audit a, .-theme-with-dark-background .lh-footer a {
+ color: hsl(210, 90%, 60%);
+}
+
+.-theme-with-dark-background .lh-load-opportunity__header .lh-load-opportunity__col {
+ background: hsl(0, 0%, 20%);
+}
+
+.-theme-with-dark-background .lh-crc .crc-node__tree-hostname {
+ color: hsl(0, 0%, 66%);
+}
+
+.-theme-with-dark-background .lh-audit-group__header::before {
+ background-color: hsl(0, 0%, 80%);
+ filter: invert(1);
+} \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/category-renderer.js b/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/category-renderer.js
index 1646e6ee6ba..4daf750cb07 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/category-renderer.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/category-renderer.js
@@ -9,9 +9,6 @@
/** @typedef {import('./dom.js')} DOM */
/** @typedef {import('./report-renderer.js')} ReportRenderer */
-/** @typedef {import('./report-renderer.js').AuditJSON} AuditJSON */
-/** @typedef {import('./report-renderer.js').CategoryJSON} CategoryJSON */
-/** @typedef {import('./report-renderer.js').GroupJSON} GroupJSON */
/** @typedef {import('./details-renderer.js')} DetailsRenderer */
/** @typedef {import('./util.js')} Util */
@@ -32,7 +29,7 @@ class CategoryRenderer {
}
/**
- * @param {AuditJSON} audit
+ * @param {LH.ReportResult.AuditRef} audit
* @param {number} index
* @return {Element}
*/
@@ -43,7 +40,7 @@ class CategoryRenderer {
/**
* Populate an DOM tree with audit details. Used by renderAudit and renderOpportunity
- * @param {AuditJSON} audit
+ * @param {LH.ReportResult.AuditRef} audit
* @param {number} index
* @param {DocumentFragment} tmpl
* @return {Element}
@@ -105,7 +102,7 @@ class CategoryRenderer {
}
/**
- * @return {!HTMLElement}
+ * @return {HTMLElement}
*/
_createChevron() {
const chevronTmpl = this.dom.cloneTemplate('#tmpl-lh-chevron', this.templateContext);
@@ -114,7 +111,7 @@ class CategoryRenderer {
}
/**
- * @param {!Element} element DOM node to populate with values.
+ * @param {Element} element DOM node to populate with values.
* @param {number|null} score
* @param {string} scoreDisplayMode
* @return {Element}
@@ -126,7 +123,7 @@ class CategoryRenderer {
}
/**
- * @param {CategoryJSON} category
+ * @param {LH.ReportResult.Category} category
* @return {Element}
*/
renderCategoryHeader(category) {
@@ -149,7 +146,7 @@ class CategoryRenderer {
/**
* Renders the group container for a group of audits. Individual audit elements can be added
* directly to the returned element.
- * @param {GroupJSON} group
+ * @param {LH.Result.ReportGroup} group
* @param {{expandable: boolean, itemCount?: number}} opts
* @return {Element}
*/
@@ -235,8 +232,8 @@ class CategoryRenderer {
}
/**
- * @param {Array<AuditJSON>} manualAudits
- * @param {string} manualDescription
+ * @param {Array<LH.ReportResult.AuditRef>} manualAudits
+ * @param {string} [manualDescription]
* @return {Element}
*/
_renderManualAudits(manualAudits, manualDescription) {
@@ -259,7 +256,7 @@ class CategoryRenderer {
}
/**
- * @param {CategoryJSON} category
+ * @param {LH.ReportResult.Category} category
* @return {DocumentFragment}
*/
renderScoreGauge(category) {
@@ -293,8 +290,8 @@ class CategoryRenderer {
}
/**
- * @param {CategoryJSON} category
- * @param {Object<string, GroupJSON>} groupDefinitions
+ * @param {LH.ReportResult.Category} category
+ * @param {Object<string, LH.Result.ReportGroup>} [groupDefinitions]
* @return {Element}
*/
render(category, groupDefinitions) {
@@ -306,7 +303,7 @@ class CategoryRenderer {
const manualAudits = auditRefs.filter(audit => audit.result.scoreDisplayMode === 'manual');
const nonManualAudits = auditRefs.filter(audit => !manualAudits.includes(audit));
- /** @type {Object<string, {passed: Array<AuditJSON>, failed: Array<AuditJSON>, notApplicable: Array<AuditJSON>}>} */
+ /** @type {Object<string, {passed: Array<LH.ReportResult.AuditRef>, failed: Array<LH.ReportResult.AuditRef>, notApplicable: Array<LH.ReportResult.AuditRef>}>} */
const auditsGroupedByGroup = {};
const auditsUngrouped = {passed: [], failed: [], notApplicable: []};
@@ -339,14 +336,14 @@ class CategoryRenderer {
const passedElements = /** @type {Array<Element>} */ ([]);
const notApplicableElements = /** @type {Array<Element>} */ ([]);
- auditsUngrouped.failed.forEach((/** @type {AuditJSON} */ audit, i) =>
- failedElements.push(this.renderAudit(audit, i)));
- auditsUngrouped.passed.forEach((/** @type {AuditJSON} */ audit, i) =>
- passedElements.push(this.renderAudit(audit, i)));
- auditsUngrouped.notApplicable.forEach((/** @type {AuditJSON} */ audit, i) =>
- notApplicableElements.push(this.renderAudit(audit, i)));
+ auditsUngrouped.failed.forEach((audit, i) => failedElements.push(this.renderAudit(audit, i)));
+ auditsUngrouped.passed.forEach((audit, i) => passedElements.push(this.renderAudit(audit, i)));
+ auditsUngrouped.notApplicable.forEach((audit, i) => notApplicableElements.push(
+ this.renderAudit(audit, i)));
Object.keys(auditsGroupedByGroup).forEach(groupId => {
+ if (!groupDefinitions) return; // We never reach here if there aren't groups, but TSC needs convincing
+
const group = groupDefinitions[groupId];
const groups = auditsGroupedByGroup[groupId];
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/details-renderer.js b/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/details-renderer.js
index b9082090c0d..9f48a3ef329 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/details-renderer.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/details-renderer.js
@@ -9,6 +9,10 @@
/** @typedef {import('./dom.js')} DOM */
/** @typedef {import('./crc-details-renderer.js')} CRCDetailsJSON */
+/** @typedef {LH.Result.Audit.OpportunityDetails} OpportunityDetails */
+
+/** @type {Array<string>} */
+const URL_PREFIXES = ['http://', 'https://', 'data:'];
class DetailsRenderer {
/**
@@ -29,7 +33,7 @@ class DetailsRenderer {
}
/**
- * @param {DetailsJSON} details
+ * @param {DetailsJSON|OpportunityDetails} details
* @return {Element}
*/
render(details) {
@@ -55,13 +59,16 @@ class DetailsRenderer {
// @ts-ignore - TODO(bckenny): Fix type hierarchy
return this._renderTable(/** @type {TableDetailsJSON} */ (details));
case 'code':
- return this._renderCode(details);
+ return this._renderCode(/** @type {DetailsJSON} */ (details));
case 'node':
return this.renderNode(/** @type {NodeDetailsJSON} */(details));
case 'criticalrequestchain':
return CriticalRequestChainRenderer.render(this._dom, this._templateContext,
// @ts-ignore - TODO(bckenny): Fix type hierarchy
/** @type {CRCDetailsJSON} */ (details));
+ case 'opportunity':
+ // @ts-ignore - TODO(bckenny): Fix type hierarchy
+ return this._renderOpportunityTable(details);
default: {
throw new Error(`Unknown type: ${details.type}`);
}
@@ -69,17 +76,17 @@ class DetailsRenderer {
}
/**
- * @param {NumericUnitDetailsJSON} details
+ * @param {{value: number, granularity?: number}} details
* @return {Element}
*/
_renderBytes(details) {
// TODO: handle displayUnit once we have something other than 'kb'
const value = Util.formatBytesToKB(details.value, details.granularity);
- return this._renderText({type: 'text', value});
+ return this._renderText({value});
}
/**
- * @param {NumericUnitDetailsJSON} details
+ * @param {{value: number, granularity?: number, displayUnit?: string}} details
* @return {Element}
*/
_renderMilliseconds(details) {
@@ -88,11 +95,11 @@ class DetailsRenderer {
value = Util.formatDuration(details.value);
}
- return this._renderText({type: 'text', value});
+ return this._renderText({value});
}
/**
- * @param {StringDetailsJSON} text
+ * @param {{value: string}} text
* @return {HTMLElement}
*/
_renderTextURL(text) {
@@ -107,7 +114,7 @@ class DetailsRenderer {
displayedHost = parsed.file === '/' ? '' : `(${parsed.hostname})`;
title = url;
} catch (/** @type {!Error} */ e) {
- if (!(e instanceof TypeError)) {
+ if (!e.name.startsWith('TypeError')) {
throw e;
}
displayedPath = url;
@@ -116,13 +123,11 @@ class DetailsRenderer {
const element = /** @type {HTMLElement} */ (this._dom.createElement('div', 'lh-text__url'));
element.appendChild(this._renderText({
value: displayedPath,
- type: 'text',
}));
if (displayedHost) {
const hostElem = this._renderText({
value: displayedHost,
- type: 'text',
});
hostElem.classList.add('lh-text__url-host');
element.appendChild(hostElem);
@@ -142,7 +147,6 @@ class DetailsRenderer {
if (!allowedProtocols.includes(url.protocol)) {
// Fall back to just the link text if protocol not allowed.
return this._renderText({
- type: 'text',
value: details.text,
});
}
@@ -157,7 +161,7 @@ class DetailsRenderer {
}
/**
- * @param {StringDetailsJSON} text
+ * @param {{value: string}} text
* @return {Element}
*/
_renderText(text) {
@@ -169,13 +173,11 @@ class DetailsRenderer {
/**
* Create small thumbnail with scaled down image asset.
* If the supplied details doesn't have an image/* mimeType, then an empty span is returned.
- * @param {ThumbnailDetails} details
+ * @param {{value: string}} details
* @return {Element}
*/
_renderThumbnail(details) {
const element = /** @type {HTMLImageElement}*/ (this._dom.createElement('img', 'lh-thumbnail'));
- /** @type {string} */
- // @ts-ignore - type should have a value if we get here.
const strValue = details.value;
element.src = strValue;
element.title = strValue;
@@ -243,6 +245,82 @@ class DetailsRenderer {
}
/**
+ * TODO(bckenny): migrate remaining table rendering to this function, then rename
+ * back to _renderTable and replace the original.
+ * @param {OpportunityDetails} details
+ * @return {Element}
+ */
+ _renderOpportunityTable(details) {
+ if (!details.items.length) return this._dom.createElement('span');
+
+ const tableElem = this._dom.createElement('table', 'lh-table');
+ const theadElem = this._dom.createChildOf(tableElem, 'thead');
+ const theadTrElem = this._dom.createChildOf(theadElem, 'tr');
+
+ for (const heading of details.headings) {
+ const valueType = heading.valueType || 'text';
+ const classes = `lh-table-column--${valueType}`;
+ const labelEl = this._dom.createElement('div', 'lh-text');
+ labelEl.textContent = heading.label;
+ this._dom.createChildOf(theadTrElem, 'th', classes).appendChild(labelEl);
+ }
+
+ const tbodyElem = this._dom.createChildOf(tableElem, 'tbody');
+ for (const row of details.items) {
+ const rowElem = this._dom.createChildOf(tbodyElem, 'tr');
+ for (const heading of details.headings) {
+ const key = /** @type {keyof LH.Result.Audit.OpportunityDetailsItem} */ (heading.key);
+ const value = row[key];
+
+ if (typeof value === 'undefined' || value === null) {
+ this._dom.createChildOf(rowElem, 'td', 'lh-table-column--empty');
+ continue;
+ }
+
+ const valueType = heading.valueType;
+ let itemElement;
+
+ // TODO(bckenny): as we add more table types, split out into _renderTableItem fn.
+ switch (valueType) {
+ case 'url': {
+ // Fall back to <pre> rendering if not actually a URL.
+ const strValue = /** @type {string} */ (value);
+ if (URL_PREFIXES.some(prefix => strValue.startsWith(prefix))) {
+ itemElement = this._renderTextURL({value: strValue});
+ } else {
+ const codeValue = /** @type {(number|string|undefined)} */ (value);
+ itemElement = this._renderCode({value: codeValue});
+ }
+ break;
+ }
+ case 'timespanMs': {
+ const numValue = /** @type {number} */ (value);
+ itemElement = this._renderMilliseconds({value: numValue});
+ break;
+ }
+ case 'bytes': {
+ const numValue = /** @type {number} */ (value);
+ itemElement = this._renderBytes({value: numValue, granularity: 1});
+ break;
+ }
+ case 'thumbnail': {
+ const strValue = /** @type {string} */ (value);
+ itemElement = this._renderThumbnail({value: strValue});
+ break;
+ }
+ default: {
+ throw new Error(`Unknown valueType: ${valueType}`);
+ }
+ }
+
+ const classes = `lh-table-column--${valueType}`;
+ this._dom.createChildOf(rowElem, 'td', classes).appendChild(itemElement);
+ }
+ }
+ return tableElem;
+ }
+
+ /**
* @param {NodeDetailsJSON} item
* @return {Element}
* @protected
@@ -279,7 +357,7 @@ class DetailsRenderer {
}
/**
- * @param {DetailsJSON} details
+ * @param {{value?: string|number}} details
* @return {Element}
*/
_renderCode(details) {
@@ -300,7 +378,6 @@ if (typeof module !== 'undefined' && module.exports) {
* @typedef {{
type: string,
value: (string|number|undefined),
- summary?: OpportunitySummary,
granularity?: number,
displayUnit?: string
}} DetailsJSON
@@ -352,7 +429,7 @@ if (typeof module !== 'undefined' && module.exports) {
/** @typedef {{
type: string,
- value?: string,
+ value: string,
}} ThumbnailDetails
*/
@@ -369,10 +446,3 @@ if (typeof module !== 'undefined' && module.exports) {
items: Array<{timing: number, timestamp: number, data: string}>,
}} FilmstripDetails
*/
-
-
-/** @typedef {{
- wastedMs?: number,
- wastedBytes?: number
- }} OpportunitySummary
- */
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/performance-category-renderer.js b/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/performance-category-renderer.js
index 71b16678cb0..3b25314a097 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/performance-category-renderer.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/performance-category-renderer.js
@@ -8,15 +8,12 @@
/* globals self, Util, CategoryRenderer */
/** @typedef {import('./dom.js')} DOM */
-/** @typedef {import('./report-renderer.js').CategoryJSON} CategoryJSON */
-/** @typedef {import('./report-renderer.js').GroupJSON} GroupJSON */
-/** @typedef {import('./report-renderer.js').AuditJSON} AuditJSON */
-/** @typedef {import('./details-renderer.js').OpportunitySummary} OpportunitySummary */
/** @typedef {import('./details-renderer.js').FilmstripDetails} FilmstripDetails */
+/** @typedef {LH.Result.Audit.OpportunityDetails} OpportunityDetails */
class PerformanceCategoryRenderer extends CategoryRenderer {
/**
- * @param {AuditJSON} audit
+ * @param {LH.ReportResult.AuditRef} audit
* @return {Element}
*/
_renderMetric(audit) {
@@ -46,7 +43,7 @@ class PerformanceCategoryRenderer extends CategoryRenderer {
}
/**
- * @param {AuditJSON} audit
+ * @param {LH.ReportResult.AuditRef} audit
* @param {number} index
* @param {number} scale
* @return {Element}
@@ -56,20 +53,20 @@ class PerformanceCategoryRenderer extends CategoryRenderer {
const element = this.populateAuditValues(audit, index, oppTmpl);
element.id = audit.result.id;
- const details = audit.result.details;
- if (!details) {
+ if (!audit.result.details || audit.result.scoreDisplayMode === 'error') {
return element;
}
- const summaryInfo = /** @type {OpportunitySummary} */ (details.summary);
- if (!summaryInfo || !summaryInfo.wastedMs || audit.result.scoreDisplayMode === 'error') {
+ // TODO(bckenny): remove cast when details is fully discriminated based on `type`.
+ const details = /** @type {OpportunityDetails} */ (audit.result.details);
+ if (details.type !== 'opportunity') {
return element;
}
// Overwrite the displayValue with opportunity's wastedMs
const displayEl = this.dom.find('.lh-audit__display-text', element);
- const sparklineWidthPct = `${summaryInfo.wastedMs / scale * 100}%`;
+ const sparklineWidthPct = `${details.overallSavingsMs / scale * 100}%`;
this.dom.find('.lh-sparkline__bar', element).style.width = sparklineWidthPct;
- displayEl.textContent = Util.formatSeconds(summaryInfo.wastedMs, 0.01);
+ displayEl.textContent = Util.formatSeconds(details.overallSavingsMs, 0.01);
// Set [title] tooltips
if (audit.result.displayValue) {
@@ -83,26 +80,27 @@ class PerformanceCategoryRenderer extends CategoryRenderer {
/**
* Get an audit's wastedMs to sort the opportunity by, and scale the sparkline width
- * Opportunties with an error won't have a summary object, so MIN_VALUE is returned to keep any
+ * Opportunties with an error won't have a details object, so MIN_VALUE is returned to keep any
* erroring opportunities last in sort order.
- * @param {AuditJSON} audit
+ * @param {LH.ReportResult.AuditRef} audit
* @return {number}
*/
_getWastedMs(audit) {
- if (
- audit.result.details &&
- audit.result.details.summary &&
- typeof audit.result.details.summary.wastedMs === 'number'
- ) {
- return audit.result.details.summary.wastedMs;
+ if (audit.result.details && audit.result.details.type === 'opportunity') {
+ // TODO(bckenny): remove cast when details is fully discriminated based on `type`.
+ const details = /** @type {OpportunityDetails} */ (audit.result.details);
+ if (typeof details.overallSavingsMs !== 'number') {
+ throw new Error('non-opportunity details passed to _getWastedMs');
+ }
+ return details.overallSavingsMs;
} else {
return Number.MIN_VALUE;
}
}
/**
- * @param {CategoryJSON} category
- * @param {Object<string, GroupJSON>} groups
+ * @param {LH.ReportResult.Category} category
+ * @param {Object<string, LH.Result.ReportGroup>} groups
* @return {Element}
* @override
*/
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/report-renderer.js b/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/report-renderer.js
index 011dfe869c2..de990d25994 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/report-renderer.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/renderer/report-renderer.js
@@ -29,12 +29,12 @@ class ReportRenderer {
}
/**
- * @param {ReportJSON} report
+ * @param {LH.ReportResult} report
* @param {Element} container Parent element to render the report into.
*/
renderReport(report, container) {
// If any mutations happen to the report within the renderers, we want the original object untouched
- const clone = /** @type {ReportJSON} */ (JSON.parse(JSON.stringify(report)));
+ const clone = /** @type {LH.ReportResult} */ (JSON.parse(JSON.stringify(report)));
// TODO(phulce): we all agree this is technical debt we should fix
if (typeof clone.categories !== 'object') throw new Error('No categories provided.');
@@ -56,7 +56,7 @@ class ReportRenderer {
}
/**
- * @param {ReportJSON} report
+ * @param {LH.ReportResult} report
* @return {DocumentFragment}
*/
_renderReportHeader(report) {
@@ -90,7 +90,7 @@ class ReportRenderer {
/**
- * @param {ReportJSON} report
+ * @param {LH.ReportResult} report
* @return {DocumentFragment}
*/
_renderReportFooter(report) {
@@ -117,7 +117,7 @@ class ReportRenderer {
/**
* Returns a div with a list of top-level warnings, or an empty div if no warnings.
- * @param {ReportJSON} report
+ * @param {LH.ReportResult} report
* @return {Node}
*/
_renderReportWarnings(report) {
@@ -136,7 +136,7 @@ class ReportRenderer {
}
/**
- * @param {ReportJSON} report
+ * @param {LH.ReportResult} report
* @return {DocumentFragment}
*/
_renderReport(report) {
@@ -203,7 +203,7 @@ class ReportRenderer {
/**
* Place the AuditResult into the auditDfn (which has just weight & group)
* @param {Object<string, LH.Audit.Result>} audits
- * @param {Array<CategoryJSON>} reportCategories
+ * @param {Array<LH.ReportResult.Category>} reportCategories
*/
static smooshAuditResultsIntoCategories(audits, reportCategories) {
for (const category of reportCategories) {
@@ -220,49 +220,3 @@ if (typeof module !== 'undefined' && module.exports) {
} else {
self.ReportRenderer = ReportRenderer;
}
-
-/**
- * @typedef {{
- id: string,
- score: (number|null),
- weight: number,
- group?: string,
- result: LH.Audit.Result
- }} AuditJSON
- */
-
-/**
- * @typedef {{
- title: string,
- id: string,
- score: (number|null),
- description?: string,
- manualDescription: string,
- auditRefs: Array<AuditJSON>
- }} CategoryJSON
- */
-
-/**
- * @typedef {{
- title: string,
- description?: string,
- }} GroupJSON
- */
-
-/**
- * @typedef {{
- lighthouseVersion: string,
- userAgent: string,
- fetchTime: string,
- timing: {total: number},
- requestedUrl: string,
- finalUrl: string,
- runWarnings?: Array<string>,
- artifacts: {traces: {defaultPass: {traceEvents: Array}}},
- audits: Object<string, LH.Audit.Result>,
- categories: Object<string, CategoryJSON>,
- reportCategories: Array<CategoryJSON>,
- categoryGroups: Object<string, GroupJSON>,
- configSettings: LH.Config.Settings,
- }} ReportJSON
- */
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/report-styles.css b/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/report-styles.css
index c3c9a43cc25..d175f729792 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/report-styles.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2/lighthouse/report-styles.css
@@ -864,6 +864,7 @@ summary.lh-passed-audits-summary {
.lh-table-column--text,
.lh-table-column--bytes,
+.lh-table-column--timespanMs,
.lh-table-column--ms {
text-align: right;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/audits2_worker/lighthouse/lighthouse-background.js b/chromium/third_party/blink/renderer/devtools/front_end/audits2_worker/lighthouse/lighthouse-background.js
index 21f7dcab7fe..ff346f15e37 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/audits2_worker/lighthouse/lighthouse-background.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/audits2_worker/lighthouse/lighthouse-background.js
@@ -1,4 +1,4 @@
-// lighthouse, browserified. 3.0.0-beta.0 (a194e972771bcf85071a796142d50d5bfbe3cc7b)
+// lighthouse, browserified. 3.0.3.1 (bf652a9fd8c04f445d820203960a905d6461277b)
require=function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a;}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r);},p,p.exports,r,e,n,t);}return n[i].exports;}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o;}return r;}()({"../audits/accessibility/accesskeys":[function(require,module,exports){
@@ -20,10 +20,10 @@ class Accesskeys extends AxeAudit{
static get meta(){
return{
-name:'accesskeys',
-description:'`[accesskey]` values are unique',
-failureDescription:'`[accesskey]` values are not unique',
-helpText:'Access keys let users quickly focus a part of the page. For proper '+
+id:'accesskeys',
+title:'`[accesskey]` values are unique',
+failureTitle:'`[accesskey]` values are not unique',
+description:'Access keys let users quickly focus a part of the page. For proper '+
'navigation, each access key must be unique. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/accesskeys?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -54,10 +54,10 @@ class ARIAAllowedAttr extends AxeAudit{
static get meta(){
return{
-name:'aria-allowed-attr',
-description:'`[aria-*]` attributes match their roles',
-failureDescription:'`[aria-*]` attributes do not match their roles',
-helpText:'Each ARIA `role` supports a specific subset of `aria-*` attributes. '+
+id:'aria-allowed-attr',
+title:'`[aria-*]` attributes match their roles',
+failureTitle:'`[aria-*]` attributes do not match their roles',
+description:'Each ARIA `role` supports a specific subset of `aria-*` attributes. '+
'Mismatching these invalidates the `aria-*` attributes. [Learn '+
'more](https://dequeuniversity.com/rules/axe/2.2/aria-allowed-attr?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -88,10 +88,10 @@ class ARIARequiredAttr extends AxeAudit{
static get meta(){
return{
-name:'aria-required-attr',
-description:'`[role]`s have all required `[aria-*]` attributes',
-failureDescription:'`[role]`s do not have all required `[aria-*]` attributes',
-helpText:'Some ARIA roles have required attributes that describe the state '+
+id:'aria-required-attr',
+title:'`[role]`s have all required `[aria-*]` attributes',
+failureTitle:'`[role]`s do not have all required `[aria-*]` attributes',
+description:'Some ARIA roles have required attributes that describe the state '+
'of the element to screen readers. [Learn more](https://dequeuniversity.com/rules/axe/2.2/aria-required-attr?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -122,11 +122,11 @@ class AriaRequiredChildren extends AxeAudit{
static get meta(){
return{
-name:'aria-required-children',
-description:'Elements with `[role]` that require specific children `[role]`s, are present',
-failureDescription:'Elements with `[role]` that require specific children `[role]`s, '+
+id:'aria-required-children',
+title:'Elements with `[role]` that require specific children `[role]`s, are present',
+failureTitle:'Elements with `[role]` that require specific children `[role]`s, '+
'are missing.',
-helpText:'Some ARIA parent roles must contain specific child roles to perform '+
+description:'Some ARIA parent roles must contain specific child roles to perform '+
'their intended accessibility functions. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/aria-required-children?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -158,10 +158,10 @@ class AriaRequiredParent extends AxeAudit{
static get meta(){
return{
-name:'aria-required-parent',
-description:'`[role]`s are contained by their required parent element',
-failureDescription:'`[role]`s are not contained by their required parent element',
-helpText:'Some ARIA child roles must be contained by specific parent roles to '+
+id:'aria-required-parent',
+title:'`[role]`s are contained by their required parent element',
+failureTitle:'`[role]`s are not contained by their required parent element',
+description:'Some ARIA child roles must be contained by specific parent roles to '+
'properly perform their intended accessibility functions. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/aria-required-parent?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -192,10 +192,10 @@ class AriaRoles extends AxeAudit{
static get meta(){
return{
-name:'aria-roles',
-description:'`[role]` values are valid',
-failureDescription:'`[role]` values are not valid',
-helpText:'ARIA roles must have valid values in order to perform their '+
+id:'aria-roles',
+title:'`[role]` values are valid',
+failureTitle:'`[role]` values are not valid',
+description:'ARIA roles must have valid values in order to perform their '+
'intended accessibility functions. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/aria-roles?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -226,10 +226,10 @@ class ARIAValidAttr extends AxeAudit{
static get meta(){
return{
-name:'aria-valid-attr-value',
-description:'`[aria-*]` attributes have valid values',
-failureDescription:'`[aria-*]` attributes do not have valid values',
-helpText:'Assistive technologies, like screen readers, can\'t interpret ARIA '+
+id:'aria-valid-attr-value',
+title:'`[aria-*]` attributes have valid values',
+failureTitle:'`[aria-*]` attributes do not have valid values',
+description:'Assistive technologies, like screen readers, can\'t interpret ARIA '+
'attributes with invalid values. [Learn '+
'more](https://dequeuniversity.com/rules/axe/2.2/aria-valid-attr-value?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -260,10 +260,10 @@ class ARIAValidAttr extends AxeAudit{
static get meta(){
return{
-name:'aria-valid-attr',
-description:'`[aria-*]` attributes are valid and not misspelled',
-failureDescription:'`[aria-*]` attributes are not valid or misspelled',
-helpText:'Assistive technologies, like screen readers, can\'t interpret ARIA '+
+id:'aria-valid-attr',
+title:'`[aria-*]` attributes are valid and not misspelled',
+failureTitle:'`[aria-*]` attributes are not valid or misspelled',
+description:'Assistive technologies, like screen readers, can\'t interpret ARIA '+
'attributes with invalid names. [Learn '+
'more](https://dequeuniversity.com/rules/axe/2.2/aria-valid-attr?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -294,11 +294,11 @@ class AudioCaption extends AxeAudit{
static get meta(){
return{
-name:'audio-caption',
-description:'`<audio>` elements contain a `<track>` element with `[kind="captions"]`',
-failureDescription:'`<audio>` elements are missing a `<track>` element with '+
+id:'audio-caption',
+title:'`<audio>` elements contain a `<track>` element with `[kind="captions"]`',
+failureTitle:'`<audio>` elements are missing a `<track>` element with '+
'`[kind="captions"]`.',
-helpText:'Captions make audio elements usable for deaf or hearing-impaired users, '+
+description:'Captions make audio elements usable for deaf or hearing-impaired users, '+
'providing critical information such as who is talking, what they\'re saying, '+
'and other non-speech information. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/audio-caption?application=lighthouse).',
@@ -330,11 +330,11 @@ class ButtonName extends AxeAudit{
static get meta(){
return{
-name:'button-name',
-description:'Buttons have an accessible name',
-failureDescription:'Buttons do not have an accessible name',
-helpText:'When a button doesn\'t have an accessible name, screen readers announce it as '+
-'"button", making it unusable for users who rely on screen readers. '+
+id:'button-name',
+title:'Buttons have an accessible name',
+failureTitle:'Buttons do not have an accessible name',
+description:'When a button doesn\'t have an accessible name, screen readers announce it '+
+'as "button", making it unusable for users who rely on screen readers. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/button-name?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -365,11 +365,11 @@ class Bypass extends AxeAudit{
static get meta(){
return{
-name:'bypass',
-description:'The page contains a heading, skip link, or landmark region',
-failureDescription:'The page does not contain a heading, skip link, or landmark region',
-helpText:'Adding ways to bypass repetitive content lets keyboard users navigate the page '+
-'more efficiently. '+
+id:'bypass',
+title:'The page contains a heading, skip link, or landmark region',
+failureTitle:'The page does not contain a heading, skip link, or landmark region',
+description:'Adding ways to bypass repetitive content lets keyboard users navigate the '+
+'page more efficiently. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/bypass?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -400,11 +400,11 @@ class ColorContrast extends AxeAudit{
static get meta(){
return{
-name:'color-contrast',
-description:'Background and foreground colors have a sufficient contrast ratio',
-failureDescription:'Background and foreground colors do not have a '+
+id:'color-contrast',
+title:'Background and foreground colors have a sufficient contrast ratio',
+failureTitle:'Background and foreground colors do not have a '+
'sufficient contrast ratio.',
-helpText:'Low-contrast text is difficult or impossible for many users to read. '+
+description:'Low-contrast text is difficult or impossible for many users to read. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/color-contrast?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -434,12 +434,12 @@ class DefinitionList extends AxeAudit{
static get meta(){
return{
-name:'definition-list',
-description:'`<dl>`\'s contain only properly-ordered `<dt>` and `<dd>` groups, `<script>` '+
+id:'definition-list',
+title:'`<dl>`\'s contain only properly-ordered `<dt>` and `<dd>` groups, `<script>` '+
'or `<template>` elements.',
-failureDescription:'`<dl>`\'s do not contain only properly-ordered `<dt>` and `<dd>` '+
+failureTitle:'`<dl>`\'s do not contain only properly-ordered `<dt>` and `<dd>` '+
'groups, `<script>` or `<template>` elements.',
-helpText:'When definition lists are not properly marked up, screen readers may produce '+
+description:'When definition lists are not properly marked up, screen readers may produce '+
'confusing or inaccurate output. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/definition-list?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -470,10 +470,10 @@ class DLItem extends AxeAudit{
static get meta(){
return{
-name:'dlitem',
-description:'Definition list items are wrapped in `<dl>` elements',
-failureDescription:'Definition list items are not wrapped in `<dl>` elements',
-helpText:'Definition list items (`<dt>` and `<dd>`) must be wrapped in a '+
+id:'dlitem',
+title:'Definition list items are wrapped in `<dl>` elements',
+failureTitle:'Definition list items are not wrapped in `<dl>` elements',
+description:'Definition list items (`<dt>` and `<dd>`) must be wrapped in a '+
'parent `<dl>` element to ensure that screen readers can properly announce them. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/dlitem?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -504,10 +504,10 @@ class DocumentTitle extends AxeAudit{
static get meta(){
return{
-name:'document-title',
-description:'Document has a `<title>` element',
-failureDescription:'Document doesn\'t have a `<title>` element',
-helpText:'The title gives screen reader users an overview of the page, and search '+
+id:'document-title',
+title:'Document has a `<title>` element',
+failureTitle:'Document doesn\'t have a `<title>` element',
+description:'The title gives screen reader users an overview of the page, and search '+
'engine users rely on it heavily to determine if a page is relevant to their search. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/title).',
requiredArtifacts:['Accessibility']};
@@ -538,10 +538,10 @@ class DuplicateId extends AxeAudit{
static get meta(){
return{
-name:'duplicate-id',
-description:'`[id]` attributes on the page are unique',
-failureDescription:'`[id]` attributes on the page are not unique',
-helpText:'The value of an id attribute must be unique to prevent '+
+id:'duplicate-id',
+title:'`[id]` attributes on the page are unique',
+failureTitle:'`[id]` attributes on the page are not unique',
+description:'The value of an id attribute must be unique to prevent '+
'other instances from being overlooked by assistive technologies. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/duplicate-id?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -572,10 +572,10 @@ class FrameTitle extends AxeAudit{
static get meta(){
return{
-name:'frame-title',
-description:'`<frame>` or `<iframe>` elements have a title',
-failureDescription:'`<frame>` or `<iframe>` elements do not have a title',
-helpText:'Screen reader users rely on frame titles to describe the contents of frames. '+
+id:'frame-title',
+title:'`<frame>` or `<iframe>` elements have a title',
+failureTitle:'`<frame>` or `<iframe>` elements do not have a title',
+description:'Screen reader users rely on frame titles to describe the contents of frames. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/frame-title?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -605,10 +605,10 @@ class HTMLHasLang extends AxeAudit{
static get meta(){
return{
-name:'html-has-lang',
-description:'`<html>` element has a `[lang]` attribute',
-failureDescription:'`<html>` element does not have a `[lang]` attribute',
-helpText:'If a page doesn\'t specify a lang attribute, a screen reader assumes '+
+id:'html-has-lang',
+title:'`<html>` element has a `[lang]` attribute',
+failureTitle:'`<html>` element does not have a `[lang]` attribute',
+description:'If a page doesn\'t specify a lang attribute, a screen reader assumes '+
'that the page is in the default language that the user chose when setting up the '+
'screen reader. If the page isn\'t actually in the default language, then the screen '+
'reader might not announce the page\'s text correctly. '+
@@ -641,11 +641,11 @@ class HTMLLangValid extends AxeAudit{
static get meta(){
return{
-name:'html-lang-valid',
-description:'`<html>` element has a valid value for its `[lang]` attribute',
-failureDescription:'`<html>` element does not have a valid value for '+
+id:'html-lang-valid',
+title:'`<html>` element has a valid value for its `[lang]` attribute',
+failureTitle:'`<html>` element does not have a valid value for '+
'its `[lang]` attribute.',
-helpText:'Specifying a valid [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) '+
+description:'Specifying a valid [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) '+
'helps screen readers announce text properly. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/valid-lang?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -676,10 +676,10 @@ class ImageAlt extends AxeAudit{
static get meta(){
return{
-name:'image-alt',
-description:'Image elements have `[alt]` attributes',
-failureDescription:'Image elements do not have `[alt]` attributes',
-helpText:'Informative elements should aim for short, descriptive alternate text. '+
+id:'image-alt',
+title:'Image elements have `[alt]` attributes',
+failureTitle:'Image elements do not have `[alt]` attributes',
+description:'Informative elements should aim for short, descriptive alternate text. '+
'Decorative elements can be ignored with an empty alt attribute. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/image-alt?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -710,11 +710,11 @@ class InputImageAlt extends AxeAudit{
static get meta(){
return{
-name:'input-image-alt',
-description:'`<input type="image">` elements have `[alt]` text',
-failureDescription:'`<input type="image">` elements do not have `[alt]` text',
-helpText:'When an image is being used as an `<input>` button, providing alternative text '+
-'can help screen reader users understand the purpose of the button. '+
+id:'input-image-alt',
+title:'`<input type="image">` elements have `[alt]` text',
+failureTitle:'`<input type="image">` elements do not have `[alt]` text',
+description:'When an image is being used as an `<input>` button, providing alternative '+
+'text can help screen reader users understand the purpose of the button. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/input-image-alt?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -744,10 +744,10 @@ class Label extends AxeAudit{
static get meta(){
return{
-name:'label',
-description:'Form elements have associated labels',
-failureDescription:'Form elements do not have associated labels',
-helpText:'Labels ensure that form controls are announced properly by assistive '+
+id:'label',
+title:'Form elements have associated labels',
+failureTitle:'Form elements do not have associated labels',
+description:'Labels ensure that form controls are announced properly by assistive '+
'technologies, like screen readers. [Learn '+
'more](https://dequeuniversity.com/rules/axe/2.2/label?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -779,12 +779,12 @@ class LayoutTable extends AxeAudit{
static get meta(){
return{
-name:'layout-table',
-description:'Presentational `<table>` elements avoid using `<th>`, `<caption>` or the '+
+id:'layout-table',
+title:'Presentational `<table>` elements avoid using `<th>`, `<caption>` or the '+
'`[summary]` attribute.',
-failureDescription:'Presentational `<table>` elements do not avoid using `<th>`, '+
+failureTitle:'Presentational `<table>` elements do not avoid using `<th>`, '+
'`<caption>` or the `[summary]` attribute.',
-helpText:'A table being used for layout purposes should not include data elements, '+
+description:'A table being used for layout purposes should not include data elements, '+
'such as the th or caption elements or the summary attribute, because this can '+
'create a confusing experience for screen reader users. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/layout-table?application=lighthouse).',
@@ -816,10 +816,10 @@ class LinkName extends AxeAudit{
static get meta(){
return{
-name:'link-name',
-description:'Links have a discernible name',
-failureDescription:'Links do not have a discernible name',
-helpText:'Link text (and alternate text for images, when used as links) that is '+
+id:'link-name',
+title:'Links have a discernible name',
+failureTitle:'Links do not have a discernible name',
+description:'Link text (and alternate text for images, when used as links) that is '+
'discernible, unique, and focusable improves the navigation experience for '+
'screen reader users. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/link-name?application=lighthouse).',
@@ -851,11 +851,11 @@ class ListItem extends AxeAudit{
static get meta(){
return{
-name:'listitem',
-description:'List items (`<li>`) are contained within `<ul>` or `<ol>` parent elements',
-failureDescription:'List items (`<li>`) are not contained within `<ul>` '+
+id:'listitem',
+title:'List items (`<li>`) are contained within `<ul>` or `<ol>` parent elements',
+failureTitle:'List items (`<li>`) are not contained within `<ul>` '+
'or `<ol>` parent elements.',
-helpText:'Screen readers require list items (`<li>`) to be contained within a '+
+description:'Screen readers require list items (`<li>`) to be contained within a '+
'parent `<ul>` or `<ol>` to be announced properly. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/listitem?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -886,12 +886,12 @@ class List extends AxeAudit{
static get meta(){
return{
-name:'list',
-description:'Lists contain only `<li>` elements and script supporting elements '+
+id:'list',
+title:'Lists contain only `<li>` elements and script supporting elements '+
'(`<script>` and `<template>`).',
-failureDescription:'Lists do not contain only `<li>` elements and script '+
+failureTitle:'Lists do not contain only `<li>` elements and script '+
'supporting elements (`<script>` and `<template>`).',
-helpText:'Screen readers have a specific way of announcing lists. Ensuring proper list '+
+description:'Screen readers have a specific way of announcing lists. Ensuring proper list '+
'structure aids screen reader output. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/list?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -922,9 +922,9 @@ class CustomControlsLabels extends ManualAudit{
static get meta(){
return Object.assign({
-name:'custom-controls-labels',
-helpText:'Custom interactive controls have associated labels, provided by aria-label or aria-labelledby. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#try_it_with_a_screen_reader).',
-description:'Custom controls have associated labels'},
+id:'custom-controls-labels',
+description:'Custom interactive controls have associated labels, provided by aria-label or aria-labelledby. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#try_it_with_a_screen_reader).',
+title:'Custom controls have associated labels'},
super.partialMeta);
}}
@@ -952,9 +952,9 @@ class CustomControlsRoles extends ManualAudit{
static get meta(){
return Object.assign({
-name:'custom-controls-roles',
-helpText:'Custom interactive controls have appropriate ARIA roles. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#try_it_with_a_screen_reader).',
-description:'Custom controls have ARIA roles'},
+id:'custom-controls-roles',
+description:'Custom interactive controls have appropriate ARIA roles. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#try_it_with_a_screen_reader).',
+title:'Custom controls have ARIA roles'},
super.partialMeta);
}}
@@ -982,9 +982,9 @@ class FocusTraps extends ManualAudit{
static get meta(){
return Object.assign({
-name:'focus-traps',
-helpText:'A user can tab into and out of any control or region without accidentally trapping their focus. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#start_with_the_keyboard).',
-description:'User focus is not accidentally trapped in a region'},
+id:'focus-traps',
+description:'A user can tab into and out of any control or region without accidentally trapping their focus. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#start_with_the_keyboard).',
+title:'User focus is not accidentally trapped in a region'},
super.partialMeta);
}}
@@ -1012,9 +1012,9 @@ class FocusableControls extends ManualAudit{
static get meta(){
return Object.assign({
-name:'focusable-controls',
-helpText:'Custom interactive controls are keyboard focusable and display a focus indicator. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#start_with_the_keyboard).',
-description:'Interactive controls are keyboard focusable'},
+id:'focusable-controls',
+description:'Custom interactive controls are keyboard focusable and display a focus indicator. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#start_with_the_keyboard).',
+title:'Interactive controls are keyboard focusable'},
super.partialMeta);
}}
@@ -1042,9 +1042,9 @@ class HeadingLevels extends ManualAudit{
static get meta(){
return Object.assign({
-name:'heading-levels',
-helpText:'Headings are used to create an outline for the page and heading levels are not skipped. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#take_advantage_of_headings_and_landmarks).',
-description:'Headings don\'t skip levels'},
+id:'heading-levels',
+description:'Headings are used to create an outline for the page and heading levels are not skipped. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#take_advantage_of_headings_and_landmarks).',
+title:'Headings don\'t skip levels'},
super.partialMeta);
}}
@@ -1072,9 +1072,9 @@ class LogicalTabOrder extends ManualAudit{
static get meta(){
return Object.assign({
-name:'logical-tab-order',
-helpText:'Tabbing through the page follows the visual layout. Users cannot focus elements that are offscreen. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#start_with_the_keyboard).',
-description:'The page has a logical tab order'},
+id:'logical-tab-order',
+description:'Tabbing through the page follows the visual layout. Users cannot focus elements that are offscreen. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#start_with_the_keyboard).',
+title:'The page has a logical tab order'},
super.partialMeta);
}}
@@ -1102,9 +1102,9 @@ class ManagedFocus extends ManualAudit{
static get meta(){
return Object.assign({
-name:'managed-focus',
-helpText:'If new content, such as a dialog, is added to the page, the user\'s focus is directed to it. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#start_with_the_keyboard).',
-description:'The user\'s focus is directed to new content added to the page'},
+id:'managed-focus',
+description:'If new content, such as a dialog, is added to the page, the user\'s focus is directed to it. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#start_with_the_keyboard).',
+title:'The user\'s focus is directed to new content added to the page'},
super.partialMeta);
}}
@@ -1133,9 +1133,9 @@ class OffscreenContentHidden extends ManualAudit{
static get meta(){
return Object.assign({
-name:'offscreen-content-hidden',
-helpText:'Offscreen content is hidden with display: none or aria-hidden=true. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#try_it_with_a_screen_reader).',
-description:'Offscreen content is hidden from assistive technology'},
+id:'offscreen-content-hidden',
+description:'Offscreen content is hidden with display: none or aria-hidden=true. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#try_it_with_a_screen_reader).',
+title:'Offscreen content is hidden from assistive technology'},
super.partialMeta);
}}
@@ -1163,9 +1163,9 @@ class UseLandmarks extends ManualAudit{
static get meta(){
return Object.assign({
-name:'use-landmarks',
-helpText:'Landmark elements (<main>, <nav>, etc.) are used to improve the keyboard navigation of the page for assistive technology. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#take_advantage_of_headings_and_landmarks).',
-description:'HTML5 landmark elements are used to improve navigation'},
+id:'use-landmarks',
+description:'Landmark elements (<main>, <nav>, etc.) are used to improve the keyboard navigation of the page for assistive technology. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#take_advantage_of_headings_and_landmarks).',
+title:'HTML5 landmark elements are used to improve navigation'},
super.partialMeta);
}}
@@ -1193,9 +1193,9 @@ class VisualOrderFollowsDOM extends ManualAudit{
static get meta(){
return Object.assign({
-name:'visual-order-follows-dom',
-helpText:'DOM order matches the visual order, improving navigation for assistive technology. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#try_it_with_a_screen_reader).',
-description:'Visual order on the page follows DOM order'},
+id:'visual-order-follows-dom',
+description:'DOM order matches the visual order, improving navigation for assistive technology. [Learn more](https://developers.google.com/web/fundamentals/accessibility/how-to-review#try_it_with_a_screen_reader).',
+title:'Visual order on the page follows DOM order'},
super.partialMeta);
}}
@@ -1223,10 +1223,10 @@ class MetaRefresh extends AxeAudit{
static get meta(){
return{
-name:'meta-refresh',
-description:'The document does not use `<meta http-equiv="refresh">`',
-failureDescription:'The document uses `<meta http-equiv="refresh">`',
-helpText:'Users do not expect a page to refresh automatically, and doing so will move '+
+id:'meta-refresh',
+title:'The document does not use `<meta http-equiv="refresh">`',
+failureTitle:'The document uses `<meta http-equiv="refresh">`',
+description:'Users do not expect a page to refresh automatically, and doing so will move '+
'focus back to the top of the page. This may create a frustrating or '+
'confusing experience. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/meta-refresh?application=lighthouse).',
@@ -1258,13 +1258,13 @@ class MetaViewport extends AxeAudit{
static get meta(){
return{
-name:'meta-viewport',
-description:'`[user-scalable="no"]` is not used in the `<meta name="viewport">` '+
+id:'meta-viewport',
+title:'`[user-scalable="no"]` is not used in the `<meta name="viewport">` '+
'element and the `[maximum-scale]` attribute is not less than 5.',
-failureDescription:'`[user-scalable="no"]` is used in the `<meta name="viewport">` '+
+failureTitle:'`[user-scalable="no"]` is used in the `<meta name="viewport">` '+
'element or the `[maximum-scale]` attribute is less than 5.',
-helpText:'Disabling zooming is problematic for users with low vision who rely on screen '+
-'magnification to properly see the contents of a web page. '+
+description:'Disabling zooming is problematic for users with low vision who rely on '+
+'screen magnification to properly see the contents of a web page. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/meta-viewport?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -1294,11 +1294,11 @@ class ObjectAlt extends AxeAudit{
static get meta(){
return{
-name:'object-alt',
-description:'`<object>` elements have `[alt]` text',
-failureDescription:'`<object>` elements do not have `[alt]` text',
-helpText:'Screen readers cannot translate non-text content. Adding alt text to `<object>` '+
-'elements helps screen readers convey meaning to users. '+
+id:'object-alt',
+title:'`<object>` elements have `[alt]` text',
+failureTitle:'`<object>` elements do not have `[alt]` text',
+description:'Screen readers cannot translate non-text content. Adding alt text to '+
+'`<object>` elements helps screen readers convey meaning to users. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/object-alt?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -1328,10 +1328,10 @@ class TabIndex extends AxeAudit{
static get meta(){
return{
-name:'tabindex',
-description:'No element has a `[tabindex]` value greater than 0',
-failureDescription:'Some elements have a `[tabindex]` value greater than 0',
-helpText:'A value greater than 0 implies an explicit navigation ordering. '+
+id:'tabindex',
+title:'No element has a `[tabindex]` value greater than 0',
+failureTitle:'Some elements have a `[tabindex]` value greater than 0',
+description:'A value greater than 0 implies an explicit navigation ordering. '+
'Although technically valid, this often creates frustrating experiences '+
'for users who rely on assistive technologies. [Learn more](https://dequeuniversity.com/rules/axe/2.2/tabindex?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -1363,14 +1363,14 @@ class TDHeadersAttr extends AxeAudit{
static get meta(){
return{
-name:'td-headers-attr',
-description:'Cells in a `<table>` element that use the `[headers]` attribute only refer '+
+id:'td-headers-attr',
+title:'Cells in a `<table>` element that use the `[headers]` attribute only refer '+
'to other cells of that same table.',
-failureDescription:'Cells in a `<table>` element that use the `[headers]` '+
+failureTitle:'Cells in a `<table>` element that use the `[headers]` '+
'attribute refers to other cells of that same table.',
-helpText:'Screen readers have features to make navigating tables easier. Ensuring `<td>` '+
-'cells using the `[headers]` attribute only refer to other cells in the same table may '+
-'improve the experience for screen reader users. '+
+description:'Screen readers have features to make navigating tables easier. Ensuring '+
+'`<td>` cells using the `[headers]` attribute only refer to other cells in the same '+
+'table may improve the experience for screen reader users. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/td-headers-attr?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -1400,13 +1400,13 @@ class THHasDataCells extends AxeAudit{
static get meta(){
return{
-name:'th-has-data-cells',
-description:'`<th>` elements and elements with `[role="columnheader"/"rowheader"]` have '+
+id:'th-has-data-cells',
+title:'`<th>` elements and elements with `[role="columnheader"/"rowheader"]` have '+
'data cells they describe.',
-failureDescription:'`<th>` elements and elements with '+
+failureTitle:'`<th>` elements and elements with '+
'`[role="columnheader"/"rowheader"]` do not have data cells they describe.',
-helpText:'Screen readers have features to make navigating tables easier. Ensuring table '+
-'headers always refer to some set of cells may improve the experience for screen '+
+description:'Screen readers have features to make navigating tables easier. Ensuring '+
+'table headers always refer to some set of cells may improve the experience for screen '+
'reader users. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/th-has-data-cells?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -1437,10 +1437,10 @@ class ValidLang extends AxeAudit{
static get meta(){
return{
-name:'valid-lang',
-description:'`[lang]` attributes have a valid value',
-failureDescription:'`[lang]` attributes do not have a valid value',
-helpText:'Specifying a valid [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) '+
+id:'valid-lang',
+title:'`[lang]` attributes have a valid value',
+failureTitle:'`[lang]` attributes do not have a valid value',
+description:'Specifying a valid [BCP 47 language](https://www.w3.org/International/questions/qa-choosing-language-tags#question) '+
'on elements helps ensure that text is pronounced correctly by a screen reader. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/valid-lang?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -1471,11 +1471,11 @@ class VideoCaption extends AxeAudit{
static get meta(){
return{
-name:'video-caption',
-description:'`<video>` elements contain a `<track>` element with `[kind="captions"]`',
-failureDescription:'`<video>` elements do not contain a `<track>` element '+
+id:'video-caption',
+title:'`<video>` elements contain a `<track>` element with `[kind="captions"]`',
+failureTitle:'`<video>` elements do not contain a `<track>` element '+
'with `[kind="captions"]`.',
-helpText:'When a video provides a caption it is easier for deaf and hearing impaired '+
+description:'When a video provides a caption it is easier for deaf and hearing impaired '+
'users to access its information. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/video-caption?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -1506,11 +1506,11 @@ class VideoDescription extends AxeAudit{
static get meta(){
return{
-name:'video-description',
-description:'`<video>` elements contain a `<track>` element with `[kind="description"]`',
-failureDescription:'`<video>` elements do not contain a `<track>` element with '+
+id:'video-description',
+title:'`<video>` elements contain a `<track>` element with `[kind="description"]`',
+failureTitle:'`<video>` elements do not contain a `<track>` element with '+
'`[kind="description"]`.',
-helpText:'Audio descriptions provide relevant information for videos that dialogue '+
+description:'Audio descriptions provide relevant information for videos that dialogue '+
'cannot, such as facial expressions and scenes. '+
'[Learn more](https://dequeuniversity.com/rules/axe/2.2/video-description?application=lighthouse).',
requiredArtifacts:['Accessibility']};
@@ -1529,9 +1529,9 @@ module.exports=VideoDescription;
'use strict';
const Audit=require('./audit');
-const WebInspector=require('../lib/web-inspector');
const Util=require('../report/html/renderer/util');
-const{groupIdToName,taskToGroup}=require('../lib/task-groups');
+const NetworkRequest=require('../lib/network-request');
+const{taskGroups}=require('../lib/task-groups');
class BootupTime extends Audit{
@@ -1539,11 +1539,11 @@ class BootupTime extends Audit{
static get meta(){
return{
-name:'bootup-time',
-description:'JavaScript boot-up time',
-failureDescription:'JavaScript boot-up time is too high',
+id:'bootup-time',
+title:'JavaScript boot-up time',
+failureTitle:'JavaScript boot-up time is too high',
scoreDisplayMode:Audit.SCORING_MODES.NUMERIC,
-helpText:'Consider reducing the time spent parsing, compiling, and executing JS. '+
+description:'Consider reducing the time spent parsing, compiling, and executing JS. '+
'You may find delivering smaller JS payloads helps with this. [Learn '+
'more](https://developers.google.com/web/tools/lighthouse/audits/bootup).',
requiredArtifacts:['traces']};
@@ -1566,31 +1566,38 @@ thresholdInMs:50};
+static getJavaScriptURLs(records){
+const urls=new Set();
+for(const record of records){
+if(record.resourceType===NetworkRequest.TYPES.Script){
+urls.add(record.url);
+}
+}
-static getExecutionTimingsByURL(timelineModel){
-const bottomUpByURL=timelineModel.bottomUpGroupBy('URL');
+return urls;
+}
-const result=new Map();
-bottomUpByURL.children.forEach((perUrlNode,url)=>{
-if(!url||url==='about:blank'){
-return;
-}
-const taskGroups={};
-perUrlNode.children.forEach(perTaskPerUrlNode=>{
-const task=WebInspector.TimelineUIUtils.eventStyle(perTaskPerUrlNode.event);
+static getExecutionTimingsByURL(tasks,jsURLs){
-const groupName=taskToGroup[task.title]||groupIdToName.other;
-const groupTotal=taskGroups[groupName]||0;
-taskGroups[groupName]=groupTotal+(perTaskPerUrlNode.selfTime||0);
-});
-result.set(url,taskGroups);
-});
+const result=new Map();
+
+for(const task of tasks){
+const jsURL=task.attributableURLs.find(url=>jsURLs.has(url));
+const fallbackURL=task.attributableURLs[0];
+const attributableURL=jsURL||fallbackURL;
+if(!attributableURL||attributableURL==='about:blank')continue;
+
+const timingByGroupId=result.get(attributableURL)||{};
+const originalTime=timingByGroupId[task.group.id]||0;
+timingByGroupId[task.group.id]=originalTime+task.selfTime;
+result.set(attributableURL,timingByGroupId);
+}
return result;
}
@@ -1603,47 +1610,54 @@ return result;
static async audit(artifacts,context){
const settings=context.settings||{};
const trace=artifacts.traces[BootupTime.DEFAULT_PASS];
-const devtoolsTimelineModel=await artifacts.requestDevtoolsTimelineModel(trace);
-const executionTimings=BootupTime.getExecutionTimingsByURL(devtoolsTimelineModel);
-let totalBootupTime=0;
-
-const extendedInfo={};
-
-const headings=[
-{key:'url',itemType:'url',text:'URL'},
-{key:'scripting',granularity:1,itemType:'ms',text:groupIdToName.scripting},
-{key:'scriptParseCompile',granularity:1,itemType:'ms',
-text:groupIdToName.scriptParseCompile}];
-
-
+const devtoolsLog=artifacts.devtoolsLogs[BootupTime.DEFAULT_PASS];
+const networkRecords=await artifacts.requestNetworkRecords(devtoolsLog);
+const tasks=await artifacts.requestMainThreadTasks(trace);
const multiplier=settings.throttlingMethod==='simulate'?
settings.throttling.cpuSlowdownMultiplier:1;
+const jsURLs=BootupTime.getJavaScriptURLs(networkRecords);
+const executionTimings=BootupTime.getExecutionTimingsByURL(tasks,jsURLs);
+
+let totalBootupTime=0;
const results=Array.from(executionTimings).
-map(([url,groups])=>{
+map(([url,timingByGroupId])=>{
+
+let bootupTimeForURL=0;
+for(const[groupId,timespanMs]of Object.entries(timingByGroupId)){
+timingByGroupId[groupId]=timespanMs*multiplier;
+bootupTimeForURL+=timespanMs*multiplier;
+}
+
-for(const[name,value]of Object.entries(groups)){
-groups[name]=value*multiplier;
-totalBootupTime+=value*multiplier;
+if(bootupTimeForURL>=context.options.thresholdInMs){
+totalBootupTime+=bootupTimeForURL;
}
-extendedInfo[url]=groups;
+const scriptingTotal=timingByGroupId[taskGroups.scriptEvaluation.id]||0;
+const parseCompileTotal=timingByGroupId[taskGroups.scriptParseCompile.id]||0;
-const scriptingTotal=groups[groupIdToName.scripting]||0;
-const parseCompileTotal=groups[groupIdToName.scriptParseCompile]||0;
return{
url:url,
-sum:scriptingTotal+parseCompileTotal,
-
+total:bootupTimeForURL,
scripting:scriptingTotal,
scriptParseCompile:parseCompileTotal};
}).
-filter(result=>result.sum>=context.options.thresholdInMs).
-sort((a,b)=>b.sum-a.sum);
+filter(result=>result.total>=context.options.thresholdInMs).
+sort((a,b)=>b.total-a.total);
const summary={wastedMs:totalBootupTime};
+
+const headings=[
+{key:'url',itemType:'url',text:'URL'},
+{key:'total',granularity:1,itemType:'ms',text:'Total'},
+{key:'scripting',granularity:1,itemType:'ms',text:taskGroups.scriptEvaluation.label},
+{key:'scriptParseCompile',granularity:1,itemType:'ms',
+text:taskGroups.scriptParseCompile.label}];
+
+
const details=BootupTime.makeTableDetails(headings,results,summary);
const score=Audit.computeLogNormalScore(
@@ -1656,17 +1670,14 @@ return{
score,
rawValue:totalBootupTime,
displayValue:[Util.MS_DISPLAY_VALUE,totalBootupTime],
-details,
-extendedInfo:{
-value:extendedInfo}};
-
+details};
}}
module.exports=BootupTime;
-},{"../lib/task-groups":42,"../lib/web-inspector":47,"../report/html/renderer/util":48,"./audit":2}],"../audits/byte-efficiency/efficient-animated-content":[function(require,module,exports){
+},{"../lib/network-request":38,"../lib/task-groups":43,"../report/html/renderer/util":48,"./audit":2}],"../audits/byte-efficiency/efficient-animated-content":[function(require,module,exports){
@@ -1677,7 +1688,7 @@ module.exports=BootupTime;
'use strict';
-const WebInspector=require('../../lib/web-inspector');
+const NetworkRequest=require('../../lib/network-request');
const ByteEfficiencyAudit=require('./byte-efficiency-audit');
@@ -1690,10 +1701,10 @@ class EfficientAnimatedContent extends ByteEfficiencyAudit{
static get meta(){
return{
-name:'efficient-animated-content',
+id:'efficient-animated-content',
scoreDisplayMode:ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
-description:'Use video formats for animated content',
-helpText:'Large GIFs are inefficient for delivering animated content. Consider using '+
+title:'Use video formats for animated content',
+description:'Large GIFs are inefficient for delivering animated content. Consider using '+
'MPEG4/WebM videos for animations and PNG/WebP for static images instead of GIF to save '+
'network bytes. [Learn more](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/replace-animated-gifs-with-video/)',
requiredArtifacts:['devtoolsLogs']};
@@ -1717,14 +1728,14 @@ return Math.round(29.1*Math.log10(bytes)-100.7)/100;
static audit_(artifacts,networkRecords){
const unoptimizedContent=networkRecords.filter(
-record=>record._mimeType==='image/gif'&&
-record._resourceType===WebInspector.resourceTypes.Image&&
-(record._resourceSize||0)>GIF_BYTE_THRESHOLD);
+record=>record.mimeType==='image/gif'&&
+record.resourceType===NetworkRequest.TYPES.Image&&
+(record.resourceSize||0)>GIF_BYTE_THRESHOLD);
-const results=unoptimizedContent.map(record=>{
-const resourceSize=record._resourceSize||0;
+const items=unoptimizedContent.map(record=>{
+const resourceSize=record.resourceSize||0;
return{
url:record.url,
totalBytes:resourceSize,
@@ -1733,26 +1744,15 @@ EfficientAnimatedContent.getPercentSavings(resourceSize))};
});
-const headings=[
-{key:'url',itemType:'url',text:'URL'},
-{
-key:'totalBytes',
-itemType:'bytes',
-displayUnit:'kb',
-granularity:1,
-text:'Transfer Size'},
-
-{
-key:'wastedBytes',
-itemType:'bytes',
-displayUnit:'kb',
-granularity:1,
-text:'Byte Savings'}];
+const headings=[
+{key:'url',valueType:'url',label:'URL'},
+{key:'totalBytes',valueType:'bytes',label:'Transfer Size'},
+{key:'wastedBytes',valueType:'bytes',label:'Byte Savings'}];
return{
-results,
+items,
headings};
}}
@@ -1760,7 +1760,7 @@ headings};
module.exports=EfficientAnimatedContent;
-},{"../../lib/web-inspector":47,"./byte-efficiency-audit":3}],"../audits/byte-efficiency/offscreen-images":[function(require,module,exports){
+},{"../../lib/network-request":38,"./byte-efficiency-audit":3}],"../audits/byte-efficiency/offscreen-images":[function(require,module,exports){
@@ -1781,6 +1781,7 @@ const ALLOWABLE_OFFSCREEN_Y=200;
const IGNORE_THRESHOLD_IN_BYTES=2048;
const IGNORE_THRESHOLD_IN_PERCENT=75;
+const IGNORE_THRESHOLD_IN_MS=50;
@@ -1790,10 +1791,10 @@ class OffscreenImages extends ByteEfficiencyAudit{
static get meta(){
return{
-name:'offscreen-images',
-description:'Defer offscreen images',
+id:'offscreen-images',
+title:'Defer offscreen images',
scoreDisplayMode:ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
-helpText:
+description:
'Consider lazy-loading offscreen and hidden images after all critical resources have '+
'finished loading to lower time to interactive. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/offscreen-images).',
@@ -1855,12 +1856,59 @@ wastedPercent:100*wastedRatio};
+static filterLanternResults(images,lanternMetricData){
+const nodeTimings=lanternMetricData.pessimisticEstimate.nodeTimings;
+
+
+let lastLongTaskStartTime=0;
+
+
+const startTimesByURL=new Map();
+for(const[node,timing]of nodeTimings){
+if(node.type==='cpu'&&timing.duration>=50){
+lastLongTaskStartTime=Math.max(lastLongTaskStartTime,timing.startTime);
+}else if(node.type==='network'){
+const networkNode=node;
+startTimesByURL.set(networkNode.record.url,timing.startTime);
+}
+}
+
+return images.filter(image=>{
+
+if(image.wastedBytes<IGNORE_THRESHOLD_IN_BYTES)return false;
+if(image.wastedPercent<IGNORE_THRESHOLD_IN_PERCENT)return false;
+
+const imageRequestStartTime=startTimesByURL.get(image.url)||0;
+return imageRequestStartTime<lastLongTaskStartTime-IGNORE_THRESHOLD_IN_MS;
+});
+}
+
+
+
+
+
+
+
+static filterObservedResults(images,interactiveTimestamp){
+return images.filter(image=>{
+if(image.wastedBytes<IGNORE_THRESHOLD_IN_BYTES)return false;
+if(image.wastedPercent<IGNORE_THRESHOLD_IN_PERCENT)return false;
+return image.requestStartTime<interactiveTimestamp/1e6-IGNORE_THRESHOLD_IN_MS/1000;
+});
+}
+
+
+
+
+
+
+
static computeWasteWithTTIGraph(results,graph,simulator){
-return ByteEfficiencyAudit.computeWasteWithTTIGraph(results,graph,simulator,
+return super.computeWasteWithTTIGraph(results,graph,simulator,
{includeLoad:false});
}
@@ -1887,7 +1935,7 @@ return results;
if(processed instanceof Error){
warnings.push(processed.message);
-Sentry.captureException(processed,{tags:{audit:this.meta.name},level:'warning'});
+Sentry.captureException(processed,{tags:{audit:this.meta.id},level:'warning'});
return results;
}
@@ -1901,36 +1949,26 @@ return results;
},new Map());
const settings=context.settings;
-return artifacts.requestFirstCPUIdle({trace,devtoolsLog,settings}).then(firstInteractive=>{
-
+return artifacts.requestInteractive({trace,devtoolsLog,settings}).then(interactive=>{
+const unfilteredResults=Array.from(resultsMap.values());
+const lanternInteractive=interactive;
+const items=context.settings.throttlingMethod==='simulate'?
+OffscreenImages.filterLanternResults(unfilteredResults,lanternInteractive):
-const ttiTimestamp=firstInteractive.timestamp?firstInteractive.timestamp/1e6:Infinity;
+OffscreenImages.filterObservedResults(unfilteredResults,interactive.timestamp);
-const results=Array.from(resultsMap.values()).filter(item=>{
-const isWasteful=
-item.wastedBytes>IGNORE_THRESHOLD_IN_BYTES&&
-item.wastedPercent>IGNORE_THRESHOLD_IN_PERCENT;
-const loadedEarly=item.requestStartTime<ttiTimestamp;
-return isWasteful&&loadedEarly;
-});
const headings=[
-{key:'url',itemType:'thumbnail',text:''},
-{key:'url',itemType:'url',text:'URL'},
-{key:'totalBytes',itemType:'bytes',displayUnit:'kb',granularity:1,text:'Original'},
-{
-key:'wastedBytes',
-itemType:'bytes',
-displayUnit:'kb',
-granularity:1,
-text:'Potential Savings'}];
-
+{key:'url',valueType:'thumbnail',label:''},
+{key:'url',valueType:'url',label:'URL'},
+{key:'totalBytes',valueType:'bytes',label:'Original'},
+{key:'wastedBytes',valueType:'bytes',label:'Potential Savings'}];
return{
warnings,
-results,
+items,
headings};
});
@@ -1939,7 +1977,7 @@ headings};
module.exports=OffscreenImages;
-},{"../../lib/sentry":39,"../../lib/url-shim":"url","./byte-efficiency-audit":3}],"../audits/byte-efficiency/render-blocking-resources":[function(require,module,exports){
+},{"../../lib/sentry":40,"../../lib/url-shim":"url","./byte-efficiency-audit":3}],"../audits/byte-efficiency/render-blocking-resources":[function(require,module,exports){
@@ -1952,13 +1990,14 @@ module.exports=OffscreenImages;
'use strict';
const Audit=require('../audit');
-const Node=require('../../lib/dependency-graph/node');
+const BaseNode=require('../../lib/dependency-graph/base-node');
const ByteEfficiencyAudit=require('./byte-efficiency-audit');
const UnusedCSS=require('./unused-css-rules');
-const WebInspector=require('../../lib/web-inspector');
+const NetworkRequest=require('../../lib/network-request');
+
+
+
-const Simulator=require('../../lib/dependency-graph/simulator/simulator');
-const NetworkNode=require('../../lib/dependency-graph/network-node.js');
@@ -1977,11 +2016,10 @@ const urlMap={};
const nodes=Array.from(nodeTimings.keys());
nodes.forEach(node=>{
if(node.type!=='network')return;
-const networkNode=node;
const nodeTiming=nodeTimings.get(node);
if(!nodeTiming)return;
-urlMap[networkNode.record.url]={node,nodeTiming};
+urlMap[node.record.url]={node,nodeTiming};
});
return urlMap;
@@ -1993,10 +2031,10 @@ class RenderBlockingResources extends Audit{
static get meta(){
return{
-name:'render-blocking-resources',
-description:'Eliminate render-blocking resources',
+id:'render-blocking-resources',
+title:'Eliminate render-blocking resources',
scoreDisplayMode:Audit.SCORING_MODES.NUMERIC,
-helpText:
+description:
'Resources are blocking the first paint of your page. Consider '+
'delivering critical JS/CSS inline and deferring all non-critical '+
'JS/styles. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/blocking-resources).',
@@ -2044,8 +2082,7 @@ const{node,nodeTiming}=nodesByUrl[resource.tag.url];
node.traverse(node=>deferredNodeIds.add(node.id));
-
-const wastedMs=Math.round(nodeTiming.endTime-nodeTiming.startTime);
+const wastedMs=Math.round(nodeTiming.duration);
if(wastedMs<MINIMUM_WASTED_MS)continue;
results.push({
@@ -2092,26 +2129,24 @@ let totalChildNetworkBytes=0;
const minimalFCPGraph=fcpGraph.cloneWithRelationships(node=>{
const canDeferRequest=deferredIds.has(node.id);
-if(node.type!==Node.TYPES.NETWORK)return!canDeferRequest;
-
-const networkNode=node;
+if(node.type!==BaseNode.TYPES.NETWORK)return!canDeferRequest;
const isStylesheet=
-networkNode.record._resourceType===WebInspector.resourceTypes.Stylesheet;
+node.record.resourceType===NetworkRequest.TYPES.Stylesheet;
if(canDeferRequest&&isStylesheet){
-const wastedBytes=wastedCssBytesByUrl.get(networkNode.record.url)||0;
-totalChildNetworkBytes+=(networkNode.record._transferSize||0)-wastedBytes;
+const wastedBytes=wastedCssBytesByUrl.get(node.record.url)||0;
+totalChildNetworkBytes+=(node.record.transferSize||0)-wastedBytes;
}
return!canDeferRequest;
});
-const originalTransferSize=minimalFCPGraph.record._transferSize;
+const originalTransferSize=minimalFCPGraph.record.transferSize;
const safeTransferSize=originalTransferSize||0;
-minimalFCPGraph.record._transferSize=safeTransferSize+totalChildNetworkBytes;
+minimalFCPGraph.record.transferSize=safeTransferSize+totalChildNetworkBytes;
const estimateAfterInline=simulator.simulate(minimalFCPGraph).timeInMs;
-minimalFCPGraph.record._transferSize=originalTransferSize;
+minimalFCPGraph.record.transferSize=originalTransferSize;
return Math.round(Math.max(originalEstimate-estimateAfterInline,0));
}
@@ -2149,20 +2184,14 @@ displayValue=`${results.length} resources delayed first paint by ${wastedMs}ms`;
displayValue=`${results.length} resource delayed first paint by ${wastedMs}ms`;
}
-const headings=[
-{key:'url',itemType:'url',text:'URL'},
-{
-key:'totalBytes',
-itemType:'bytes',
-displayUnit:'kb',
-granularity:0.01,
-text:'Size (KB)'},
-{key:'wastedMs',itemType:'ms',text:'Download Time (ms)',granularity:1}];
+const headings=[
+{key:'url',valueType:'url',label:'URL'},
+{key:'totalBytes',valueType:'bytes',label:'Size (KB)'},
+{key:'wastedMs',valueType:'timespanMs',label:'Download Time (ms)'}];
-const summary={wastedMs};
-const details=Audit.makeTableDetails(headings,results,summary);
+const details=Audit.makeOpportunityDetails(headings,results,wastedMs);
return{
displayValue,
@@ -2175,7 +2204,7 @@ details};
module.exports=RenderBlockingResources;
-},{"../../lib/dependency-graph/network-node.js":24,"../../lib/dependency-graph/node":25,"../../lib/dependency-graph/simulator/simulator":28,"../../lib/web-inspector":47,"../audit":2,"./byte-efficiency-audit":3,"./unused-css-rules":"../audits/byte-efficiency/unused-css-rules"}],"../audits/byte-efficiency/total-byte-weight":[function(require,module,exports){
+},{"../../lib/dependency-graph/base-node":22,"../../lib/network-request":38,"../audit":2,"./byte-efficiency-audit":3,"./unused-css-rules":"../audits/byte-efficiency/unused-css-rules"}],"../audits/byte-efficiency/total-byte-weight":[function(require,module,exports){
@@ -2191,11 +2220,11 @@ class TotalByteWeight extends ByteEfficiencyAudit{
static get meta(){
return{
-name:'total-byte-weight',
-description:'Avoids enormous network payloads',
-failureDescription:'Has enormous network payloads',
+id:'total-byte-weight',
+title:'Avoids enormous network payloads',
+failureTitle:'Has enormous network payloads',
scoreDisplayMode:ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
-helpText:
+description:
'Large network payloads cost users real money and are highly correlated with '+
'long load times. [Learn '+
'more](https://developers.google.com/web/tools/lighthouse/audits/network-payloads).',
@@ -2310,11 +2339,11 @@ class UnminifiedCSS extends ByteEfficiencyAudit{
static get meta(){
return{
-name:'unminified-css',
-description:'Minify CSS',
+id:'unminified-css',
+title:'Minify CSS',
scoreDisplayMode:ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
-helpText:'Minifying CSS files can reduce network payload sizes. '+
-'[Learn more](https://developers.google.com/speed/docs/insights/MinifyResources).',
+description:'Minifying CSS files can reduce network payload sizes. '+
+'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/minify-css).',
requiredArtifacts:['CSSUsage','devtoolsLogs']};
}
@@ -2390,15 +2419,14 @@ static computeWaste(stylesheet,networkRecord,pageUrl){
const content=stylesheet.content;
const totalTokenLength=UnminifiedCSS.computeTokenLength(content);
-
let url=stylesheet.header.sourceURL;
if(!url||url===pageUrl){
const contentPreview=UnusedCSSRules.determineContentPreview(stylesheet.content);
-url={type:'code',value:contentPreview};
+url=contentPreview;
}
const totalBytes=ByteEfficiencyAudit.estimateTransferSize(networkRecord,content.length,
-'stylesheet');
+'Stylesheet');
const wastedRatio=1-totalTokenLength/content.length;
const wastedBytes=Math.round(totalBytes*wastedRatio);
@@ -2417,7 +2445,7 @@ wastedPercent:100*wastedRatio};
static audit_(artifacts,networkRecords){
const pageUrl=artifacts.URL.finalUrl;
-const results=[];
+const items=[];
for(const stylesheet of artifacts.CSSUsage.stylesheets){
const networkRecord=networkRecords.
find(record=>record.url===stylesheet.header.sourceURL);
@@ -2430,16 +2458,15 @@ const result=UnminifiedCSS.computeWaste(stylesheet,networkRecord,pageUrl);
if(result.wastedPercent<IGNORE_THRESHOLD_IN_PERCENT||
result.wastedBytes<IGNORE_THRESHOLD_IN_BYTES||
!Number.isFinite(result.wastedBytes))continue;
-results.push(result);
+items.push(result);
}
return{
-results,
+items,
headings:[
-{key:'url',itemType:'url',text:'URL'},
-{key:'totalBytes',itemType:'bytes',displayUnit:'kb',granularity:1,text:'Original'},
-{key:'wastedBytes',itemType:'bytes',displayUnit:'kb',granularity:1,
-text:'Potential Savings'}]};
+{key:'url',valueType:'url',label:'URL'},
+{key:'totalBytes',valueType:'bytes',label:'Original'},
+{key:'wastedBytes',valueType:'bytes',label:'Potential Savings'}]};
}}
@@ -2478,11 +2505,11 @@ class UnminifiedJavaScript extends ByteEfficiencyAudit{
static get meta(){
return{
-name:'unminified-javascript',
-description:'Minify JavaScript',
+id:'unminified-javascript',
+title:'Minify JavaScript',
scoreDisplayMode:ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
-helpText:'Minifying JavaScript files can reduce payload sizes and script parse time. '+
+description:'Minifying JavaScript files can reduce payload sizes and script parse time. '+
'[Learn more](https://developers.google.com/speed/docs/insights/MinifyResources).',
requiredArtifacts:['Scripts','devtoolsLogs']};
@@ -2507,7 +2534,7 @@ totalTokenLength+=token.value.length;
}
const totalBytes=ByteEfficiencyAudit.estimateTransferSize(networkRecord,contentLength,
-'script');
+'Script');
const wastedRatio=1-totalTokenLength/contentLength;
const wastedBytes=Math.round(totalBytes*wastedRatio);
@@ -2526,7 +2553,7 @@ wastedPercent:100*wastedRatio};
static audit_(artifacts,networkRecords){
-const results=[];
+const items=[];
const warnings=[];
for(const requestId of Object.keys(artifacts.Scripts)){
const scriptContent=artifacts.Scripts[requestId];
@@ -2540,20 +2567,19 @@ const result=UnminifiedJavaScript.computeWaste(scriptContent,networkRecord);
if(result.wastedPercent<IGNORE_THRESHOLD_IN_PERCENT||
result.wastedBytes<IGNORE_THRESHOLD_IN_BYTES||
!Number.isFinite(result.wastedBytes))continue;
-results.push(result);
+items.push(result);
}catch(err){
-warnings.push(`Unable to process ${networkRecord._url}: ${err.message}`);
+warnings.push(`Unable to process ${networkRecord.url}: ${err.message}`);
}
}
return{
-results,
+items,
warnings,
headings:[
-{key:'url',itemType:'url',text:'URL'},
-{key:'totalBytes',itemType:'bytes',displayUnit:'kb',granularity:1,text:'Original'},
-{key:'wastedBytes',itemType:'bytes',displayUnit:'kb',granularity:1,
-text:'Potential Savings'}]};
+{key:'url',valueType:'url',label:'URL'},
+{key:'totalBytes',valueType:'bytes',label:'Original'},
+{key:'wastedBytes',valueType:'bytes',label:'Potential Savings'}]};
}}
@@ -2561,7 +2587,7 @@ text:'Potential Savings'}]};
module.exports=UnminifiedJavaScript;
-},{"./byte-efficiency-audit":3,"esprima":136}],"../audits/byte-efficiency/unused-css-rules":[function(require,module,exports){
+},{"./byte-efficiency-audit":3,"esprima":118}],"../audits/byte-efficiency/unused-css-rules":[function(require,module,exports){
@@ -2582,10 +2608,10 @@ class UnusedCSSRules extends ByteEfficiencyAudit{
static get meta(){
return{
-name:'unused-css-rules',
-description:'Defer unused CSS',
+id:'unused-css-rules',
+title:'Defer unused CSS',
scoreDisplayMode:ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
-helpText:'Remove unused rules from stylesheets to reduce unnecessary '+
+description:'Remove unused rules from stylesheets to reduce unnecessary '+
'bytes consumed by network activity. '+
'[Learn more](https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery).',
requiredArtifacts:['CSSUsage','URL','devtoolsLogs']};
@@ -2645,7 +2671,7 @@ usedUncompressedBytes+=usedRule.endOffset-usedRule.startOffset;
}
const totalTransferredBytes=ByteEfficiencyAudit.estimateTransferSize(
-stylesheetInfo.networkRecord,totalUncompressedBytes,'stylesheet');
+stylesheetInfo.networkRecord,totalUncompressedBytes,'Stylesheet');
const percentUnused=(totalUncompressedBytes-usedUncompressedBytes)/totalUncompressedBytes;
const wastedBytes=Math.round(percentUnused*totalTransferredBytes);
@@ -2698,15 +2724,15 @@ return preview;
static mapSheetToResult(stylesheetInfo,pageUrl){
-
let url=stylesheetInfo.header.sourceURL;
if(!url||url===pageUrl){
const contentPreview=UnusedCSSRules.determineContentPreview(stylesheetInfo.content);
-url={type:'code',value:contentPreview};
+url=contentPreview;
}
const usage=UnusedCSSRules.computeUsage(stylesheetInfo);
-return Object.assign({url},usage);
+const result={url};
+return Object.assign(result,usage);
}
@@ -2723,19 +2749,19 @@ return artifacts.requestNetworkRecords(devtoolsLogs).then(networkRecords=>{
const indexedSheets=UnusedCSSRules.indexStylesheetsById(styles,networkRecords);
UnusedCSSRules.indexUsedRules(usage,indexedSheets);
-const results=Object.keys(indexedSheets).
+const items=Object.keys(indexedSheets).
map(sheetId=>UnusedCSSRules.mapSheetToResult(indexedSheets[sheetId],pageUrl)).
filter(sheet=>sheet&&sheet.wastedBytes>IGNORE_THRESHOLD_IN_BYTES);
+
const headings=[
-{key:'url',itemType:'url',text:'URL'},
-{key:'totalBytes',itemType:'bytes',displayUnit:'kb',granularity:1,text:'Original'},
-{key:'wastedBytes',itemType:'bytes',displayUnit:'kb',granularity:1,
-text:'Potential Savings'}];
+{key:'url',valueType:'url',label:'URL'},
+{key:'totalBytes',valueType:'bytes',label:'Original'},
+{key:'wastedBytes',valueType:'bytes',label:'Potential Savings'}];
return{
-results,
+items,
headings};
});
@@ -2762,10 +2788,10 @@ class UnusedJavaScript extends ByteEfficiencyAudit{
static get meta(){
return{
-name:'unused-javascript',
-description:'Unused JavaScript',
+id:'unused-javascript',
+title:'Unused JavaScript',
scoreDisplayMode:ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
-helpText:'Remove unused JavaScript to reduce bytes consumed by network activity.',
+description:'Remove unused JavaScript to reduce bytes consumed by network activity.',
requiredArtifacts:['JsUsage','devtoolsLogs']};
}
@@ -2820,7 +2846,7 @@ contentLength+=usage.contentLength;
}
const totalBytes=ByteEfficiencyAudit.estimateTransferSize(networkRecord,contentLength,
-'script');
+'Script');
const wastedRatio=unusedLength/contentLength||0;
const wastedBytes=Math.round(totalBytes*wastedRatio);
@@ -2846,24 +2872,22 @@ scripts.push(script);
scriptsByUrl.set(script.url,scripts);
}
-
-const results=[];
+const items=[];
for(const[url,scripts]of scriptsByUrl.entries()){
const networkRecord=networkRecords.find(record=>record.url===url);
if(!networkRecord)continue;
const wasteData=scripts.map(UnusedJavaScript.computeWaste);
-const result=UnusedJavaScript.mergeWaste(wasteData,networkRecord);
-if(result.wastedBytes<=IGNORE_THRESHOLD_IN_BYTES)continue;
-results.push(result);
+const item=UnusedJavaScript.mergeWaste(wasteData,networkRecord);
+if(item.wastedBytes<=IGNORE_THRESHOLD_IN_BYTES)continue;
+items.push(item);
}
return{
-results,
+items,
headings:[
-{key:'url',itemType:'url',text:'URL'},
-{key:'totalBytes',itemType:'bytes',displayUnit:'kb',granularity:1,text:'Original'},
-{key:'wastedBytes',itemType:'bytes',displayUnit:'kb',granularity:1,
-text:'Potential Savings'}]};
+{key:'url',valueType:'url',label:'URL'},
+{key:'totalBytes',valueType:'bytes',label:'Original'},
+{key:'wastedBytes',valueType:'bytes',label:'Potential Savings'}]};
}}
@@ -2883,8 +2907,9 @@ const assert=require('assert');
const parseCacheControl=require('parse-cache-control');
const Audit=require('../audit');
-const WebInspector=require('../../lib/web-inspector');
+const NetworkRequest=require('../../lib/network-request');
const URL=require('../../lib/url-shim');
+const linearInterpolation=require('../../lib/statistics').linearInterpolation;
const IGNORE_THRESHOLD_IN_PERCENT=0.925;
@@ -2895,12 +2920,12 @@ class CacheHeaders extends Audit{
static get meta(){
return{
-name:'uses-long-cache-ttl',
-description:'Uses efficient cache policy on static assets',
-failureDescription:'Uses inefficient cache policy on static assets',
-helpText:
+id:'uses-long-cache-ttl',
+title:'Uses efficient cache policy on static assets',
+failureTitle:'Uses inefficient cache policy on static assets',
+description:
'A long cache lifetime can speed up repeat visits to your page. '+
-'[Learn more](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching#cache-control).',
+'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/cache-policy).',
scoreDisplayMode:Audit.SCORING_MODES.NUMERIC,
requiredArtifacts:['devtoolsLogs']};
@@ -2925,20 +2950,6 @@ scoreMedian:128*1024};
-
-
-
-static linearInterpolation(x0,y0,x1,y1,x){
-const slope=(y1-y0)/(x1-x0);
-return y0+(x-x0)*slope;
-}
-
-
-
-
-
-
-
static getCacheHitProbability(maxAgeInSeconds){
@@ -2964,7 +2975,7 @@ const upperDecile=upperDecileIndex/10;
const lowerDecile=(upperDecileIndex-1)/10;
-return CacheHeaders.linearInterpolation(
+return linearInterpolation(
lowerDecileValue,
lowerDecile,
upperDecileValue,
@@ -3022,17 +3033,17 @@ static isCacheableAsset(record){
const CACHEABLE_STATUS_CODES=new Set([200,203,206]);
const STATIC_RESOURCE_TYPES=new Set([
-WebInspector.resourceTypes.Font,
-WebInspector.resourceTypes.Image,
-WebInspector.resourceTypes.Media,
-WebInspector.resourceTypes.Script,
-WebInspector.resourceTypes.Stylesheet]);
+NetworkRequest.TYPES.Font,
+NetworkRequest.TYPES.Image,
+NetworkRequest.TYPES.Media,
+NetworkRequest.TYPES.Script,
+NetworkRequest.TYPES.Stylesheet]);
-const resourceUrl=record._url;
+const resourceUrl=record.url;
return(
CACHEABLE_STATUS_CODES.has(record.statusCode)&&
-STATIC_RESOURCE_TYPES.has(record._resourceType)&&
+STATIC_RESOURCE_TYPES.has(record.resourceType||'Other')&&
!resourceUrl.includes('data:'));
}
@@ -3054,7 +3065,7 @@ if(!CacheHeaders.isCacheableAsset(record))continue;
const headers=new Map();
-for(const header of record._responseHeaders||[]){
+for(const header of record.responseHeaders||[]){
headers.set(header.name.toLowerCase(),header.value);
}
@@ -3071,8 +3082,8 @@ cacheLifetimeInSeconds=cacheLifetimeInSeconds||0;
const cacheHitProbability=CacheHeaders.getCacheHitProbability(cacheLifetimeInSeconds);
if(cacheHitProbability>IGNORE_THRESHOLD_IN_PERCENT)continue;
-const url=URL.elideDataURI(record._url);
-const totalBytes=record._transferSize||0;
+const url=URL.elideDataURI(record.url);
+const totalBytes=record.transferSize||0;
const wastedBytes=(1-cacheHitProbability)*totalBytes;
totalWastedBytes+=wastedBytes;
@@ -3126,7 +3137,7 @@ details};
module.exports=CacheHeaders;
-},{"../../lib/url-shim":"url","../../lib/web-inspector":47,"../audit":2,"assert":53,"parse-cache-control":147}],"../audits/byte-efficiency/uses-optimized-images":[function(require,module,exports){
+},{"../../lib/network-request":38,"../../lib/statistics":41,"../../lib/url-shim":"url","../audit":2,"assert":53,"parse-cache-control":129}],"../audits/byte-efficiency/uses-optimized-images":[function(require,module,exports){
@@ -3149,10 +3160,10 @@ class UsesOptimizedImages extends ByteEfficiencyAudit{
static get meta(){
return{
-name:'uses-optimized-images',
-description:'Efficiently encode images',
+id:'uses-optimized-images',
+title:'Efficiently encode images',
scoreDisplayMode:ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
-helpText:'Optimized images load faster and consume less cellular data. '+
+description:'Optimized images load faster and consume less cellular data. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/optimize-images).',
requiredArtifacts:['OptimizedImages','devtoolsLogs']};
@@ -3176,7 +3187,7 @@ static audit_(artifacts){
const images=artifacts.OptimizedImages;
-const results=[];
+const items=[];
const warnings=[];
for(const image of images){
if(image.failed){
@@ -3190,7 +3201,7 @@ continue;
const url=URL.elideDataURI(image.url);
const jpegSavings=UsesOptimizedImages.computeSavings(image);
-results.push({
+items.push({
url,
fromProtocol:image.fromProtocol,
isCrossOrigin:!image.isSameOrigin,
@@ -3199,17 +3210,17 @@ wastedBytes:jpegSavings.bytes});
}
+
const headings=[
-{key:'url',itemType:'thumbnail',text:''},
-{key:'url',itemType:'url',text:'URL'},
-{key:'totalBytes',itemType:'bytes',displayUnit:'kb',granularity:1,text:'Original'},
-{key:'wastedBytes',itemType:'bytes',displayUnit:'kb',granularity:1,
-text:'Potential Savings'}];
+{key:'url',valueType:'thumbnail',label:''},
+{key:'url',valueType:'url',label:'URL'},
+{key:'totalBytes',valueType:'bytes',label:'Original'},
+{key:'wastedBytes',valueType:'bytes',label:'Potential Savings'}];
return{
warnings,
-results,
+items,
headings};
}}
@@ -3245,10 +3256,10 @@ class UsesResponsiveImages extends ByteEfficiencyAudit{
static get meta(){
return{
-name:'uses-responsive-images',
-description:'Properly size images',
+id:'uses-responsive-images',
+title:'Properly size images',
scoreDisplayMode:ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
-helpText:
+description:
'Serve images that are appropriately-sized to save cellular data '+
'and improve load time. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/oversized-images).',
@@ -3316,7 +3327,7 @@ if(!processed)return;
if(processed instanceof Error){
warnings.push(processed.message);
-Sentry.captureException(processed,{tags:{audit:this.meta.name},level:'warning'});
+Sentry.captureException(processed,{tags:{audit:this.meta.id},level:'warning'});
return;
}
@@ -3327,20 +3338,20 @@ resultsMap.set(processed.url,processed);
}
});
-const results=Array.from(resultsMap.values()).
+const items=Array.from(resultsMap.values()).
filter(item=>item.wastedBytes>IGNORE_THRESHOLD_IN_BYTES);
+
const headings=[
-{key:'url',itemType:'thumbnail',text:''},
-{key:'url',itemType:'url',text:'URL'},
-{key:'totalBytes',itemType:'bytes',displayUnit:'kb',granularity:1,text:'Original'},
-{key:'wastedBytes',itemType:'bytes',displayUnit:'kb',granularity:1,
-text:'Potential Savings'}];
+{key:'url',valueType:'thumbnail',label:''},
+{key:'url',valueType:'url',label:'URL'},
+{key:'totalBytes',valueType:'bytes',label:'Original'},
+{key:'wastedBytes',valueType:'bytes',label:'Potential Savings'}];
return{
warnings,
-results,
+items,
headings};
}}
@@ -3348,7 +3359,7 @@ headings};
module.exports=UsesResponsiveImages;
-},{"../../lib/sentry":39,"../../lib/url-shim":"url","./byte-efficiency-audit":3}],"../audits/byte-efficiency/uses-text-compression":[function(require,module,exports){
+},{"../../lib/sentry":40,"../../lib/url-shim":"url","./byte-efficiency-audit":3}],"../audits/byte-efficiency/uses-text-compression":[function(require,module,exports){
@@ -3372,12 +3383,12 @@ class ResponsesAreCompressed extends ByteEfficiencyAudit{
static get meta(){
return{
-name:'uses-text-compression',
+id:'uses-text-compression',
scoreDisplayMode:ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
-description:'Enable text compression',
-helpText:'Text-based responses should be served with compression (gzip, deflate or brotli)'+
-' to minimize total network bytes.'+
-' [Learn more](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/optimize-encoding-and-transfer).',
+title:'Enable text compression',
+description:'Text-based responses should be served with compression (gzip, deflate or'+
+' brotli) to minimize total network bytes.'+
+' [Learn more](https://developers.google.com/web/tools/lighthouse/audits/text-compression).',
requiredArtifacts:['ResponseCompression','devtoolsLogs']};
}
@@ -3390,8 +3401,11 @@ static audit_(artifacts){
const uncompressedResponses=artifacts.ResponseCompression;
-const results=[];
+const items=[];
uncompressedResponses.forEach(record=>{
+
+if(!record.gzipSize||record.gzipSize<0)return;
+
const originalSize=record.resourceSize;
const gzipSize=record.gzipSize;
const gzipSavings=originalSize-gzipSize;
@@ -3407,28 +3421,28 @@ return;
const url=URL.elideDataURI(record.url);
-const isDuplicate=results.find(res=>res.url===url&&
-res.totalBytes===record.resourceSize);
+const isDuplicate=items.find(item=>item.url===url&&
+item.totalBytes===record.resourceSize);
if(isDuplicate){
return;
}
-results.push({
+items.push({
url,
totalBytes:originalSize,
wastedBytes:gzipSavings});
});
+
const headings=[
-{key:'url',itemType:'url',text:'Uncompressed resource URL'},
-{key:'totalBytes',itemType:'bytes',displayUnit:'kb',granularity:1,text:'Original'},
-{key:'wastedBytes',itemType:'bytes',displayUnit:'kb',granularity:1,
-text:'GZIP Savings'}];
+{key:'url',valueType:'url',label:'Uncompressed resource URL'},
+{key:'totalBytes',valueType:'bytes',label:'Original'},
+{key:'wastedBytes',valueType:'bytes',label:'GZIP Savings'}];
return{
-results,
+items,
headings};
}}
@@ -3458,10 +3472,10 @@ class UsesWebPImages extends ByteEfficiencyAudit{
static get meta(){
return{
-name:'uses-webp-images',
-description:'Serve images in next-gen formats',
+id:'uses-webp-images',
+title:'Serve images in next-gen formats',
scoreDisplayMode:ByteEfficiencyAudit.SCORING_MODES.NUMERIC,
-helpText:'Image formats like JPEG 2000, JPEG XR, and WebP often provide better '+
+description:'Image formats like JPEG 2000, JPEG XR, and WebP often provide better '+
'compression than PNG or JPEG, which means faster downloads and less data consumption. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/webp).',
requiredArtifacts:['OptimizedImages','devtoolsLogs']};
@@ -3486,7 +3500,7 @@ static audit_(artifacts){
const images=artifacts.OptimizedImages;
-const results=[];
+const items=[];
const warnings=[];
for(const image of images){
if(image.failed){
@@ -3499,7 +3513,7 @@ continue;
const url=URL.elideDataURI(image.url);
const webpSavings=UsesWebPImages.computeSavings(image);
-results.push({
+items.push({
url,
fromProtocol:image.fromProtocol,
isCrossOrigin:!image.isSameOrigin,
@@ -3508,17 +3522,17 @@ wastedBytes:webpSavings.bytes});
}
+
const headings=[
-{key:'url',itemType:'thumbnail',text:''},
-{key:'url',itemType:'url',text:'URL'},
-{key:'totalBytes',itemType:'bytes',displayUnit:'kb',granularity:1,text:'Original'},
-{key:'wastedBytes',itemType:'bytes',displayUnit:'kb',granularity:1,
-text:'Potential Savings'}];
+{key:'url',valueType:'thumbnail',label:''},
+{key:'url',valueType:'url',label:'URL'},
+{key:'totalBytes',valueType:'bytes',label:'Original'},
+{key:'wastedBytes',valueType:'bytes',label:'Potential Savings'}];
return{
warnings,
-results,
+items,
headings};
}}
@@ -3542,10 +3556,10 @@ class ContentWidth extends Audit{
static get meta(){
return{
-name:'content-width',
-description:'Content is sized correctly for the viewport',
-failureDescription:'Content is not sized correctly for the viewport',
-helpText:'If the width of your app\'s content doesn\'t match the width '+
+id:'content-width',
+title:'Content is sized correctly for the viewport',
+failureTitle:'Content is not sized correctly for the viewport',
+description:'If the width of your app\'s content doesn\'t match the width '+
'of the viewport, your app might not be optimized for mobile screens. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/content-sized-correctly-for-viewport).',
requiredArtifacts:['ViewportDimensions']};
@@ -3601,10 +3615,10 @@ class CriticalRequestChains extends Audit{
static get meta(){
return{
-name:'critical-request-chains',
-description:'Critical Request Chains',
+id:'critical-request-chains',
+title:'Critical Request Chains',
scoreDisplayMode:Audit.SCORING_MODES.INFORMATIVE,
-helpText:'The Critical Request Chains below show you what resources are '+
+description:'The Critical Request Chains below show you what resources are '+
'issued with a high priority. Consider reducing '+
'the length of chains, reducing the download size of resources, or '+
'deferring the download of unnecessary resources to improve page load. '+
@@ -3695,7 +3709,7 @@ const simpleRequest={
url:request.url,
startTime:request.startTime,
endTime:request.endTime,
-_responseReceivedTime:request._responseReceivedTime,
+responseReceivedTime:request.responseReceivedTime,
transferSize:request.transferSize};
@@ -3814,10 +3828,10 @@ class Deprecations extends Audit{
static get meta(){
return{
-name:'deprecations',
-description:'Avoids deprecated APIs',
-failureDescription:'Uses deprecated API\'s',
-helpText:'Deprecated APIs will eventually be removed from the browser. '+
+id:'deprecations',
+title:'Avoids deprecated APIs',
+failureTitle:'Uses deprecated API\'s',
+description:'Deprecated APIs will eventually be removed from the browser. '+
'[Learn more](https://www.chromestatus.com/features#deprecated).',
requiredArtifacts:['ChromeConsoleMessages']};
@@ -3887,10 +3901,10 @@ class AppCacheManifestAttr extends Audit{
static get meta(){
return{
-name:'appcache-manifest',
-description:'Avoids Application Cache',
-failureDescription:'Uses Application Cache',
-helpText:'Application Cache is deprecated. '+
+id:'appcache-manifest',
+title:'Avoids Application Cache',
+failureTitle:'Uses Application Cache',
+description:'Application Cache is deprecated. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/appcache).',
requiredArtifacts:['AppCacheManifest']};
@@ -3913,6 +3927,81 @@ displayValue};
module.exports=AppCacheManifestAttr;
+},{"../audit":2}],"../audits/dobetterweb/doctype":[function(require,module,exports){
+
+
+
+
+
+'use strict';
+
+const Audit=require('../audit');
+
+class Doctype extends Audit{
+
+
+
+static get meta(){
+return{
+id:'doctype',
+title:'Page has the HTML doctype',
+failureTitle:'Page is missing the HTML doctype',
+description:'Specifying a doctype prevents the browser from switching to quirks-mode.'+
+'Read more on the '+
+'[MDN Web Docs page](https://developer.mozilla.org/en-US/docs/Glossary/Doctype)',
+requiredArtifacts:['Doctype']};
+
+}
+
+
+
+
+
+static audit(artifacts){
+if(!artifacts.Doctype){
+return{
+rawValue:false,
+explanation:'Document must contain a doctype'};
+
+}
+
+
+const doctypeName=artifacts.Doctype.name.trim();
+const doctypePublicId=artifacts.Doctype.publicId;
+const doctypeSystemId=artifacts.Doctype.systemId;
+
+if(doctypePublicId!==''){
+return{
+rawValue:false,
+explanation:'Expected publicId to be an empty string'};
+
+}
+
+if(doctypeSystemId!==''){
+return{
+rawValue:false,
+explanation:'Expected systemId to be an empty string'};
+
+}
+
+
+
+
+if(doctypeName==='html'){
+return{
+rawValue:true};
+
+}else{
+return{
+rawValue:false,
+explanation:'Doctype name must be the lowercase string `html`'};
+
+}
+}}
+
+
+module.exports=Doctype;
+
},{"../audit":2}],"../audits/dobetterweb/dom-size":[function(require,module,exports){
@@ -3945,10 +4034,10 @@ return MAX_DOM_NODES;
static get meta(){
return{
-name:'dom-size',
-description:'Avoids an excessive DOM size',
-failureDescription:'Uses an excessive DOM size',
-helpText:'Browser engineers recommend pages contain fewer than '+
+id:'dom-size',
+title:'Avoids an excessive DOM size',
+failureTitle:'Uses an excessive DOM size',
+description:'Browser engineers recommend pages contain fewer than '+
`~${Util.formatNumber(DOMSize.MAX_DOM_NODES)} DOM nodes. The sweet spot is a tree `+
`depth < ${MAX_DOM_TREE_DEPTH} elements and fewer than ${MAX_DOM_TREE_WIDTH} `+
'children/parent element. A large DOM can increase memory usage, cause longer '+
@@ -4043,10 +4132,10 @@ class ExternalAnchorsUseRelNoopenerAudit extends Audit{
static get meta(){
return{
-name:'external-anchors-use-rel-noopener',
-description:'Links to cross-origin destinations are safe',
-failureDescription:'Links to cross-origin destinations are unsafe',
-helpText:'Add `rel="noopener"` or `rel="noreferrer"` to any external links to improve '+
+id:'external-anchors-use-rel-noopener',
+title:'Links to cross-origin destinations are safe',
+failureTitle:'Links to cross-origin destinations are unsafe',
+description:'Add `rel="noopener"` or `rel="noreferrer"` to any external links to improve '+
'performance and prevent security vulnerabilities. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/noopener).',
requiredArtifacts:['URL','AnchorsWithNoRelNoopener']};
@@ -4134,10 +4223,10 @@ class GeolocationOnStart extends ViolationAudit{
static get meta(){
return{
-name:'geolocation-on-start',
-description:'Avoids requesting the geolocation permission on page load',
-failureDescription:'Requests the geolocation permission on page load',
-helpText:'Users are mistrustful of or confused by sites that request their '+
+id:'geolocation-on-start',
+title:'Avoids requesting the geolocation permission on page load',
+failureTitle:'Requests the geolocation permission on page load',
+description:'Users are mistrustful of or confused by sites that request their '+
'location without context. Consider tying the request to user gestures instead. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/geolocation-on-load).',
requiredArtifacts:['ChromeConsoleMessages']};
@@ -4193,10 +4282,10 @@ class NoDocWriteAudit extends ViolationAudit{
static get meta(){
return{
-name:'no-document-write',
-description:'Avoids `document.write()`',
-failureDescription:'Uses `document.write()`',
-helpText:'For users on slow connections, external scripts dynamically injected via '+
+id:'no-document-write',
+title:'Avoids `document.write()`',
+failureTitle:'Uses `document.write()`',
+description:'For users on slow connections, external scripts dynamically injected via '+
'`document.write()` can delay page load by tens of seconds. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/document-write).',
requiredArtifacts:['ChromeConsoleMessages']};
@@ -4229,101 +4318,7 @@ details};
module.exports=NoDocWriteAudit;
-},{"../violation-audit":6}],"../audits/dobetterweb/no-mutation-events":[function(require,module,exports){
-
-
-
-
-
-
-
-
-
-
-
-'use strict';
-
-const URL=require('../../lib/url-shim');
-const Audit=require('../audit');
-const EventHelpers=require('../../lib/event-helpers');
-
-class NoMutationEventsAudit extends Audit{
-static get MUTATION_EVENTS(){
-return[
-'DOMAttrModified',
-'DOMAttributeNameChanged',
-'DOMCharacterDataModified',
-'DOMElementNameChanged',
-'DOMNodeInserted',
-'DOMNodeInsertedIntoDocument',
-'DOMNodeRemoved',
-'DOMNodeRemovedFromDocument',
-'DOMSubtreeModified'];
-
-}
-
-
-
-
-static get meta(){
-return{
-name:'no-mutation-events',
-description:'Avoids Mutation Events in its own scripts',
-failureDescription:'Uses Mutation Events in its own scripts',
-helpText:'Mutation Events are deprecated and harm performance. Consider using Mutation '+
-'Observers instead. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/mutation-events).',
-requiredArtifacts:['URL','EventListeners']};
-
-}
-
-
-
-
-
-static audit(artifacts){
-
-const warnings=[];
-const listeners=artifacts.EventListeners;
-
-const results=listeners.filter(loc=>{
-const isMutationEvent=this.MUTATION_EVENTS.includes(loc.type);
-let sameHost=URL.hostsMatch(artifacts.URL.finalUrl,loc.url);
-
-if(!URL.isValid(loc.url)&&isMutationEvent){
-sameHost=true;
-warnings.push(URL.INVALID_URL_DEBUG_STRING);
-}
-
-return sameHost&&isMutationEvent;
-}).map(EventHelpers.addFormattedCodeSnippet);
-
-const groupedResults=EventHelpers.groupCodeSnippetsByLocation(results);
-
-const headings=[
-{key:'url',itemType:'url',text:'URL'},
-{key:'type',itemType:'code',text:'Event'},
-{key:'line',itemType:'text',text:'Line'},
-{key:'col',itemType:'text',text:'Col'},
-{key:'pre',itemType:'code',text:'Snippet'}];
-
-const details=NoMutationEventsAudit.makeTableDetails(headings,groupedResults);
-
-return{
-rawValue:groupedResults.length===0,
-extendedInfo:{
-value:{
-results:groupedResults}},
-
-
-details,
-warnings};
-
-}}
-
-
-module.exports=NoMutationEventsAudit;
-
-},{"../../lib/event-helpers":34,"../../lib/url-shim":"url","../audit":2}],"../audits/dobetterweb/no-vulnerable-libraries":[function(require,module,exports){
+},{"../violation-audit":6}],"../audits/dobetterweb/no-vulnerable-libraries":[function(require,module,exports){
@@ -4355,13 +4350,14 @@ class NoVulnerableLibrariesAudit extends Audit{
static get meta(){
return{
-name:'no-vulnerable-libraries',
-description:'Avoids front-end JavaScript libraries'+
+id:'no-vulnerable-libraries',
+title:'Avoids front-end JavaScript libraries'+
' with known security vulnerabilities',
-failureDescription:'Includes front-end JavaScript libraries'+
+failureTitle:'Includes front-end JavaScript libraries'+
' with known security vulnerabilities',
-helpText:'Some third-party scripts may contain known security vulnerabilities '+
-' that are easily identified and exploited by attackers.',
+description:'Some third-party scripts may contain known security vulnerabilities '+
+'that are easily identified and exploited by attackers. '+
+'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/vulnerabilities).',
requiredArtifacts:['JSLibraries']};
}
@@ -4523,7 +4519,7 @@ details};
module.exports=NoVulnerableLibrariesAudit;
-},{"../../../third-party/snyk/snapshot.json":155,"../../lib/sentry":39,"../audit":2,"semver":150}],"../audits/dobetterweb/no-websql":[function(require,module,exports){
+},{"../../../third-party/snyk/snapshot.json":137,"../../lib/sentry":40,"../audit":2,"semver":132}],"../audits/dobetterweb/no-websql":[function(require,module,exports){
@@ -4545,10 +4541,10 @@ class NoWebSQLAudit extends Audit{
static get meta(){
return{
-name:'no-websql',
-description:'Avoids WebSQL DB',
-failureDescription:'Uses WebSQL DB',
-helpText:'Web SQL is deprecated. Consider using IndexedDB instead. '+
+id:'no-websql',
+title:'Avoids WebSQL DB',
+failureTitle:'Uses WebSQL DB',
+description:'Web SQL is deprecated. Consider using IndexedDB instead. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/web-sql).',
requiredArtifacts:['WebSQL']};
@@ -4594,10 +4590,10 @@ class NotificationOnStart extends ViolationAudit{
static get meta(){
return{
-name:'notification-on-start',
-description:'Avoids requesting the notification permission on page load',
-failureDescription:'Requests the notification permission on page load',
-helpText:'Users are mistrustful of or confused by sites that request to send '+
+id:'notification-on-start',
+title:'Avoids requesting the notification permission on page load',
+failureTitle:'Requests the notification permission on page load',
+description:'Users are mistrustful of or confused by sites that request to send '+
'notifications without context. Consider tying the request to user gestures '+
'instead. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/notifications-on-load).',
requiredArtifacts:['ChromeConsoleMessages']};
@@ -4646,11 +4642,11 @@ class PasswordInputsCanBePastedIntoAudit extends Audit{
static get meta(){
return{
-name:'password-inputs-can-be-pasted-into',
-description:'Allows users to paste into password fields',
-failureDescription:'Prevents users to paste into password fields',
-helpText:'Preventing password pasting undermines good security policy. '+
-'[Learn more](https://www.ncsc.gov.uk/blog-post/let-them-paste-passwords).',
+id:'password-inputs-can-be-pasted-into',
+title:'Allows users to paste into password fields',
+failureTitle:'Prevents users to paste into password fields',
+description:'Preventing password pasting undermines good security policy. '+
+'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/password-pasting).',
requiredArtifacts:['PasswordInputsWithPreventedPaste']};
}
@@ -4710,10 +4706,10 @@ class UsesHTTP2Audit extends Audit{
static get meta(){
return{
-name:'uses-http2',
-description:'Uses HTTP/2 for its own resources',
-failureDescription:'Does not use HTTP/2 for all of its resources',
-helpText:'HTTP/2 offers many benefits over HTTP/1.1, including binary headers, '+
+id:'uses-http2',
+title:'Uses HTTP/2 for its own resources',
+failureTitle:'Does not use HTTP/2 for all of its resources',
+description:'HTTP/2 offers many benefits over HTTP/1.1, including binary headers, '+
'multiplexing, and server push. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/http2).',
requiredArtifacts:['URL','devtoolsLogs']};
@@ -4734,12 +4730,12 @@ const resources=networkRecords.filter(record=>{
const isOldHttp=/HTTP\/[01][.\d]?/i.test(record.protocol);
if(!isOldHttp)return false;
-const requestHost=new URL(record._url).host;
+const requestHost=new URL(record.url).host;
return requestHost===finalHost;
}).map(record=>{
return{
protocol:record.protocol,
-url:record._url};
+url:record.url};
}).filter(record=>{
if(seenURLs.has(record.url))return false;
@@ -4799,10 +4795,10 @@ class PassiveEventsAudit extends ViolationAudit{
static get meta(){
return{
-name:'uses-passive-event-listeners',
-description:'Uses passive listeners to improve scrolling performance',
-failureDescription:'Does not use passive listeners to improve scrolling performance',
-helpText:'Consider marking your touch and wheel event listeners as `passive` '+
+id:'uses-passive-event-listeners',
+title:'Uses passive listeners to improve scrolling performance',
+failureTitle:'Does not use passive listeners to improve scrolling performance',
+description:'Consider marking your touch and wheel event listeners as `passive` '+
'to improve your page\'s scroll performance. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/passive-event-listeners).',
requiredArtifacts:['ChromeConsoleMessages']};
@@ -4856,11 +4852,11 @@ class ErrorLogs extends Audit{
static get meta(){
return{
-name:'errors-in-console',
-description:'No browser errors logged to the console',
-helpText:'Errors logged to the console indicate unresolved problems. '+
+id:'errors-in-console',
+title:'No browser errors logged to the console',
+description:'Errors logged to the console indicate unresolved problems. '+
'They can come from network request failures and other browser concerns.',
-failureDescription:'Browser errors were logged to the console',
+failureTitle:'Browser errors were logged to the console',
requiredArtifacts:['ChromeConsoleMessages','RuntimeExceptions']};
}
@@ -4916,272 +4912,7 @@ details};
module.exports=ErrorLogs;
-},{"./audit":2}],"../audits/estimated-input-latency":[function(require,module,exports){
-
-
-
-
-
-'use strict';
-
-const Audit=require('./audit');
-
-class EstimatedInputLatency extends Audit{
-
-
-
-static get meta(){
-return{
-name:'estimated-input-latency',
-description:'Estimated Input Latency',
-helpText:'The score above is an estimate of how long your app takes to respond to user '+
-'input, in milliseconds, during the busiest 5s window of page load. If your '+
-'latency is higher than 50 ms, users may perceive your app as laggy. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/estimated-input-latency).',
-scoreDisplayMode:Audit.SCORING_MODES.NUMERIC,
-requiredArtifacts:['traces']};
-
-}
-
-
-
-
-static get defaultOptions(){
-return{
-
-scorePODR:50,
-scoreMedian:100};
-
-}
-
-
-
-
-
-
-
-
-
-static async audit(artifacts,context){
-const trace=artifacts.traces[Audit.DEFAULT_PASS];
-const devtoolsLog=artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
-const metricComputationData={trace,devtoolsLog,settings:context.settings};
-const metricResult=await artifacts.requestEstimatedInputLatency(metricComputationData);
-
-return{
-score:Audit.computeLogNormalScore(
-metricResult.timing,
-context.options.scorePODR,
-context.options.scoreMedian),
-
-rawValue:metricResult.timing,
-displayValue:['%d\xa0ms',metricResult.timing]};
-
-}}
-
-
-module.exports=EstimatedInputLatency;
-
-},{"./audit":2}],"../audits/first-contentful-paint":[function(require,module,exports){
-
-
-
-
-
-'use strict';
-
-const Audit=require('./audit');
-const Util=require('../report/html/renderer/util.js');
-
-class FirstContentfulPaint extends Audit{
-
-
-
-static get meta(){
-return{
-name:'first-contentful-paint',
-description:'First Contentful Paint',
-helpText:'First contentful paint marks the time at which the first text/image is painted. '+
-`[Learn more](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#first_paint_and_first_contentful_paint).`,
-scoreDisplayMode:Audit.SCORING_MODES.NUMERIC,
-requiredArtifacts:['traces','devtoolsLogs']};
-
-}
-
-
-
-
-static get defaultOptions(){
-return{
-
-
-
-scorePODR:2900,
-scoreMedian:4000};
-
-}
-
-
-
-
-
-
-static async audit(artifacts,context){
-const trace=artifacts.traces[Audit.DEFAULT_PASS];
-const devtoolsLog=artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
-const metricComputationData={trace,devtoolsLog,settings:context.settings};
-const metricResult=await artifacts.requestFirstContentfulPaint(metricComputationData);
-
-return{
-score:Audit.computeLogNormalScore(
-metricResult.timing,
-context.options.scorePODR,
-context.options.scoreMedian),
-
-rawValue:metricResult.timing,
-displayValue:[Util.MS_DISPLAY_VALUE,metricResult.timing]};
-
-}}
-
-
-module.exports=FirstContentfulPaint;
-
-},{"../report/html/renderer/util.js":48,"./audit":2}],"../audits/first-cpu-idle":[function(require,module,exports){
-
-
-
-
-
-'use strict';
-
-const Audit=require('./audit');
-const Util=require('../report/html/renderer/util.js');
-
-class FirstCPUIdle extends Audit{
-
-
-
-static get meta(){
-return{
-name:'first-cpu-idle',
-description:'First CPU Idle',
-helpText:'First CPU Idle marks the first time at which the page\'s main thread is '+
-'quiet enough to handle input. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/first-interactive).',
-scoreDisplayMode:Audit.SCORING_MODES.NUMERIC,
-requiredArtifacts:['traces']};
-
-}
-
-
-
-
-static get defaultOptions(){
-return{
-
-
-
-scorePODR:2900,
-scoreMedian:6500};
-
-}
-
-
-
-
-
-
-
-
-
-static async audit(artifacts,context){
-const trace=artifacts.traces[Audit.DEFAULT_PASS];
-const devtoolsLog=artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
-const metricComputationData={trace,devtoolsLog,settings:context.settings};
-const metricResult=await artifacts.requestFirstCPUIdle(metricComputationData);
-
-return{
-score:Audit.computeLogNormalScore(
-metricResult.timing,
-context.options.scorePODR,
-context.options.scoreMedian),
-
-rawValue:metricResult.timing,
-displayValue:[Util.MS_DISPLAY_VALUE,metricResult.timing]};
-
-}}
-
-
-module.exports=FirstCPUIdle;
-
-},{"../report/html/renderer/util.js":48,"./audit":2}],"../audits/first-meaningful-paint":[function(require,module,exports){
-
-
-
-
-
-'use strict';
-
-const Audit=require('./audit');
-const Util=require('../report/html/renderer/util');
-
-class FirstMeaningfulPaint extends Audit{
-
-
-
-static get meta(){
-return{
-name:'first-meaningful-paint',
-description:'First Meaningful Paint',
-helpText:'First Meaningful Paint measures when the primary content of a page is visible. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/first-meaningful-paint).',
-scoreDisplayMode:Audit.SCORING_MODES.NUMERIC,
-requiredArtifacts:['traces']};
-
-}
-
-
-
-
-static get defaultOptions(){
-return{
-
-
-
-scorePODR:2000,
-scoreMedian:4000};
-
-}
-
-
-
-
-
-
-
-
-
-static async audit(artifacts,context){
-const trace=artifacts.traces[Audit.DEFAULT_PASS];
-const devtoolsLog=artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
-const metricComputationData={trace,devtoolsLog,settings:context.settings};
-const metricResult=await artifacts.requestFirstMeaningfulPaint(metricComputationData);
-
-return{
-score:Audit.computeLogNormalScore(
-metricResult.timing,
-context.options.scorePODR,
-context.options.scoreMedian),
-
-rawValue:metricResult.timing,
-displayValue:[Util.MS_DISPLAY_VALUE,metricResult.timing]};
-
-}}
-
-
-module.exports=FirstMeaningfulPaint;
-
-},{"../report/html/renderer/util":48,"./audit":2}],"../audits/font-display":[function(require,module,exports){
+},{"./audit":2}],"../audits/font-display":[function(require,module,exports){
@@ -5190,7 +4921,7 @@ module.exports=FirstMeaningfulPaint;
'use strict';
const Audit=require('./audit');
-const WebInspector=require('../lib/web-inspector');
+const NetworkRequest=require('../lib/network-request');
const allowedFontFaceDisplays=['block','fallback','optional','swap'];
class FontDisplay extends Audit{
@@ -5199,10 +4930,10 @@ class FontDisplay extends Audit{
static get meta(){
return{
-name:'font-display',
-description:'All text remains visible during webfont loads',
-failureDescription:'Text is invisible while webfonts are loading',
-helpText:'Leverage the font-display CSS feature to ensure text is user-visible while '+
+id:'font-display',
+title:'All text remains visible during webfont loads',
+failureTitle:'Text is invisible while webfonts are loading',
+description:'Leverage the font-display CSS feature to ensure text is user-visible while '+
'webfonts are loading. '+
'[Learn more](https://developers.google.com/web/updates/2016/02/font-display).',
requiredArtifacts:['devtoolsLogs','Fonts']};
@@ -5224,7 +4955,7 @@ const fontsWithoutProperDisplay=fontFaces.filter(fontFace=>
return artifacts.requestNetworkRecords(devtoolsLogs).then(networkRecords=>{
const results=networkRecords.filter(record=>{
-const isFont=record._resourceType===WebInspector.resourceTypes.Font;
+const isFont=record.resourceType===NetworkRequest.TYPES.Font;
return isFont;
}).
@@ -5263,7 +4994,7 @@ details};
module.exports=FontDisplay;
-},{"../lib/web-inspector":47,"./audit":2}],"../audits/image-aspect-ratio":[function(require,module,exports){
+},{"../lib/network-request":38,"./audit":2}],"../audits/image-aspect-ratio":[function(require,module,exports){
@@ -5280,7 +5011,7 @@ module.exports=FontDisplay;
const Audit=require('./audit');
const URL=require('../lib/url-shim');
-const THRESHOLD=0.05;
+const THRESHOLD_PX=2;
@@ -5290,10 +5021,11 @@ class ImageAspectRatio extends Audit{
static get meta(){
return{
-name:'image-aspect-ratio',
-description:'Displays images with correct aspect ratio',
-failureDescription:'Displays images with incorrect aspect ratio',
-helpText:'Image display dimensions should match natural aspect ratio.',
+id:'image-aspect-ratio',
+title:'Displays images with correct aspect ratio',
+failureTitle:'Displays images with incorrect aspect ratio',
+description:'Image display dimensions should match natural aspect ratio. '+
+'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/aspect-ratio).',
requiredArtifacts:['ImageUsage']};
}
@@ -5306,7 +5038,9 @@ static computeAspectRatios(image){
const url=URL.elideDataURI(image.src);
const actualAspectRatio=image.naturalWidth/image.naturalHeight;
const displayedAspectRatio=image.width/image.height;
-const doRatiosMatch=Math.abs(actualAspectRatio-displayedAspectRatio)<THRESHOLD;
+
+const targetDisplayHeight=image.width/actualAspectRatio;
+const doRatiosMatch=Math.abs(targetDisplayHeight-image.height)<THRESHOLD_PX;
if(!Number.isFinite(actualAspectRatio)||
!Number.isFinite(displayedAspectRatio)){
@@ -5371,89 +5105,7 @@ details:Audit.makeTableDetails(headings,results)};
module.exports=ImageAspectRatio;
-},{"../lib/url-shim":"url","./audit":2}],"../audits/interactive":[function(require,module,exports){
-
-
-
-
-
-'use strict';
-
-const Audit=require('./audit');
-const Util=require('../report/html/renderer/util');
-
-
-
-
-
-
-
-class InteractiveMetric extends Audit{
-
-
-
-static get meta(){
-return{
-name:'interactive',
-description:'Time to Interactive',
-helpText:'Interactive marks the time at which the page is fully interactive. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/consistently-interactive).',
-scoreDisplayMode:Audit.SCORING_MODES.NUMERIC,
-requiredArtifacts:['traces','devtoolsLogs']};
-
-}
-
-
-
-
-static get defaultOptions(){
-return{
-
-
-
-scorePODR:2900,
-scoreMedian:7300};
-
-}
-
-
-
-
-
-
-static async audit(artifacts,context){
-const trace=artifacts.traces[Audit.DEFAULT_PASS];
-const devtoolsLog=artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
-const metricComputationData={trace,devtoolsLog,settings:context.settings};
-const metricResult=await artifacts.requestInteractive(metricComputationData);
-const timeInMs=metricResult.timing;
-const extendedInfo={
-timeInMs,
-timestamp:metricResult.timestamp,
-
-optimistic:metricResult.optimisticEstimate&&metricResult.optimisticEstimate.timeInMs,
-
-pessimistic:metricResult.pessimisticEstimate&&metricResult.pessimisticEstimate.timeInMs};
-
-
-return{
-score:Audit.computeLogNormalScore(
-timeInMs,
-context.options.scorePODR,
-context.options.scoreMedian),
-
-rawValue:timeInMs,
-displayValue:[Util.MS_DISPLAY_VALUE,timeInMs],
-extendedInfo:{
-value:extendedInfo}};
-
-
-}}
-
-
-module.exports=InteractiveMetric;
-
-},{"../report/html/renderer/util":48,"./audit":2}],"../audits/is-on-https":[function(require,module,exports){
+},{"../lib/url-shim":"url","./audit":2}],"../audits/is-on-https":[function(require,module,exports){
@@ -5474,10 +5126,10 @@ class HTTPS extends Audit{
static get meta(){
return{
-name:'is-on-https',
-description:'Uses HTTPS',
-failureDescription:'Does not use HTTPS',
-helpText:'All sites should be protected with HTTPS, even ones that don\'t handle '+
+id:'is-on-https',
+title:'Uses HTTPS',
+failureTitle:'Does not use HTTPS',
+description:'All sites should be protected with HTTPS, even ones that don\'t handle '+
'sensitive data. HTTPS prevents intruders from tampering with or passively listening '+
'in on the communications between your app and your users, and is a prerequisite for '+
'HTTP/2 and many new web platform APIs. '+
@@ -5562,10 +5214,10 @@ class LoadFastEnough4Pwa extends Audit{
static get meta(){
return{
-name:'load-fast-enough-for-pwa',
-description:'Page load is fast enough on 3G',
-failureDescription:'Page load is not fast enough on 3G',
-helpText:
+id:'load-fast-enough-for-pwa',
+title:'Page load is fast enough on 3G',
+failureTitle:'Page load is not fast enough on 3G',
+description:
'A fast page load over a 3G network ensures a good mobile user experience. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/fast-3g).',
requiredArtifacts:['traces','devtoolsLogs']};
@@ -5617,7 +5269,7 @@ rawValue:tti.timing};
module.exports=LoadFastEnough4Pwa;
-},{"../config/constants":8,"./audit":2,"lodash.isequal":144}],"../audits/mainthread-work-breakdown":[function(require,module,exports){
+},{"../config/constants":8,"./audit":2,"lodash.isequal":126}],"../audits/mainthread-work-breakdown":[function(require,module,exports){
@@ -5632,8 +5284,7 @@ module.exports=LoadFastEnough4Pwa;
const Audit=require('./audit');
const Util=require('../report/html/renderer/util');
-
-const{taskToGroup}=require('../lib/task-groups');
+const{taskGroups}=require('../lib/task-groups');
class MainThreadWorkBreakdown extends Audit{
@@ -5641,11 +5292,11 @@ class MainThreadWorkBreakdown extends Audit{
static get meta(){
return{
-name:'mainthread-work-breakdown',
-description:'Minimizes main thread work',
-failureDescription:'Has significant main thread work',
+id:'mainthread-work-breakdown',
+title:'Minimizes main thread work',
+failureTitle:'Has significant main thread work',
scoreDisplayMode:Audit.SCORING_MODES.NUMERIC,
-helpText:'Consider reducing the time spent parsing, compiling and executing JS. '+
+description:'Consider reducing the time spent parsing, compiling and executing JS. '+
'You may find delivering smaller JS payloads helps with this.',
requiredArtifacts:['traces']};
@@ -5666,12 +5317,14 @@ scoreMedian:4000};
-static getExecutionTimingsByCategory(timelineModel){
-const bottomUpByName=timelineModel.bottomUpGroupBy('EventName');
+static getExecutionTimingsByGroup(tasks){
const result=new Map();
-bottomUpByName.children.forEach((event,eventName)=>
-result.set(eventName,event.selfTime));
+
+for(const task of tasks){
+const originalTime=result.get(task.group.id)||0;
+result.set(task.group.id,originalTime+task.selfTime);
+}
return result;
}
@@ -5685,40 +5338,34 @@ static async audit(artifacts,context){
const settings=context.settings||{};
const trace=artifacts.traces[MainThreadWorkBreakdown.DEFAULT_PASS];
-const devtoolsTimelineModel=await artifacts.requestDevtoolsTimelineModel(trace);
-const executionTimings=MainThreadWorkBreakdown.getExecutionTimingsByCategory(
-devtoolsTimelineModel);
-
-let totalExecutionTime=0;
-
+const tasks=await artifacts.requestMainThreadTasks(trace);
const multiplier=settings.throttlingMethod==='simulate'?
settings.throttling.cpuSlowdownMultiplier:1;
-const extendedInfo={};
+const executionTimings=MainThreadWorkBreakdown.getExecutionTimingsByGroup(tasks);
+
+let totalExecutionTime=0;
const categoryTotals={};
-const results=Array.from(executionTimings).map(([eventName,duration])=>{
-duration*=multiplier;
+const results=Array.from(executionTimings).map(([groupId,rawDuration])=>{
+const duration=rawDuration*multiplier;
totalExecutionTime+=duration;
-extendedInfo[eventName]=duration;
-const groupName=taskToGroup[eventName];
-const categoryTotal=categoryTotals[groupName]||0;
-categoryTotals[groupName]=categoryTotal+duration;
+const categoryTotal=categoryTotals[groupId]||0;
+categoryTotals[groupId]=categoryTotal+duration;
return{
-category:eventName,
-group:groupName,
+group:groupId,
+groupLabel:taskGroups[groupId].label,
duration:duration};
});
const headings=[
-{key:'group',itemType:'text',text:'Category'},
-{key:'category',itemType:'text',text:'Work'},
-{key:'duration',itemType:'ms',granularity:1,text:'Time spent'}];
+{key:'groupLabel',itemType:'text',text:'Category'},
+{key:'duration',itemType:'ms',granularity:1,text:'Time Spent'}];
-results.stableSort((a,b)=>categoryTotals[b.group]-categoryTotals[a.group]);
+results.sort((a,b)=>categoryTotals[b.group]-categoryTotals[a.group]);
const tableDetails=MainThreadWorkBreakdown.makeTableDetails(headings,results);
const score=Audit.computeLogNormalScore(
@@ -5731,17 +5378,14 @@ return{
score,
rawValue:totalExecutionTime,
displayValue:[Util.MS_DISPLAY_VALUE,totalExecutionTime],
-details:tableDetails,
-extendedInfo:{
-value:extendedInfo}};
-
+details:tableDetails};
}}
module.exports=MainThreadWorkBreakdown;
-},{"../lib/task-groups":42,"../report/html/renderer/util":48,"./audit":2}],"../audits/manifest-short-name-length":[function(require,module,exports){
+},{"../lib/task-groups":43,"../report/html/renderer/util":48,"./audit":2}],"../audits/manifest-short-name-length":[function(require,module,exports){
@@ -5757,11 +5401,10 @@ class ManifestShortNameLength extends Audit{
static get meta(){
return{
-name:'manifest-short-name-length',
-description:'Manifest\'s `short_name` won\'t be truncated when displayed on homescreen',
-failureDescription:'Manifest\'s `short_name` will be truncated when displayed '+
-'on homescreen',
-helpText:'Make your app\'s `short_name` fewer than 12 characters to '+
+id:'manifest-short-name-length',
+title:'The `short_name` won\'t be truncated on the homescreen',
+failureTitle:'The `short_name` will be truncated on the homescreen',
+description:'Make your app\'s `short_name` fewer than 12 characters to '+
'ensure that it\'s not truncated on homescreens. [Learn '+
'more](https://developers.google.com/web/tools/lighthouse/audits/manifest-short_name-is-not-truncated).',
requiredArtifacts:['Manifest']};
@@ -5772,27 +5415,37 @@ requiredArtifacts:['Manifest']};
-static audit(artifacts){
-return artifacts.requestManifestValues(artifacts.Manifest).then(manifestValues=>{
+static async audit(artifacts){
+const manifestValues=await artifacts.requestManifestValues(artifacts.Manifest);
+
if(manifestValues.isParseFailure){
return{
-rawValue:false};
+rawValue:true,
+notApplicable:true};
+
+}
+
+const shortNameCheck=manifestValues.allChecks.find(i=>i.id==='hasShortName');
+const shortNameLengthCheck=manifestValues.allChecks.find(i=>i.id==='shortNameLength');
+
+
+if(shortNameCheck&&!shortNameCheck.passing){
+return{
+rawValue:true,
+notApplicable:true};
}
-const hasShortName=manifestValues.allChecks.find(i=>i.id==='hasShortName');
-if(!hasShortName||!hasShortName.passing){
+if(shortNameLengthCheck&&!shortNameLengthCheck.passing){
return{
rawValue:false,
-explanation:'No short_name found in manifest.'};
+explanation:`Failure: ${shortNameLengthCheck.failureText}.`};
}
-const isShortEnough=manifestValues.allChecks.find(i=>i.id==='shortNameLength');
return{
-rawValue:!!isShortEnough&&isShortEnough.passing};
+rawValue:true};
-});
}}
@@ -5819,10 +5472,10 @@ class PWACrossBrowser extends ManualAudit{
static get meta(){
return Object.assign({
-name:'pwa-cross-browser',
-helpText:'To reach the most number of users, sites should work across '+
+id:'pwa-cross-browser',
+description:'To reach the most number of users, sites should work across '+
'every major browser. [Learn more](https://developers.google.com/web/progressive-web-apps/checklist#site-works-cross-browser).',
-description:'Site works cross-browser'},
+title:'Site works cross-browser'},
super.partialMeta);
}}
@@ -5849,10 +5502,10 @@ class PWAEachPageHasURL extends ManualAudit{
static get meta(){
return Object.assign({
-name:'pwa-each-page-has-url',
-helpText:'Ensure individual pages are deep linkable via the URLs and that URLs are '+
+id:'pwa-each-page-has-url',
+description:'Ensure individual pages are deep linkable via the URLs and that URLs are '+
'unique for the purpose of shareability on social media. [Learn more](https://developers.google.com/web/progressive-web-apps/checklist#each-page-has-a-url).',
-description:'Each page has a URL'},
+title:'Each page has a URL'},
super.partialMeta);
}}
@@ -5879,17 +5532,430 @@ class PWAPageTransitions extends ManualAudit{
static get meta(){
return Object.assign({
-name:'pwa-page-transitions',
-helpText:'Transitions should feel snappy as you tap around, even on a slow network, a key '+
-'to perceived performance. [Learn more](https://developers.google.com/web/progressive-web-apps/checklist#page-transitions-dont-feel-like-they-block-on-the-network).',
-description:'Page transitions don\'t feel like they block on the network'},
+id:'pwa-page-transitions',
+description:'Transitions should feel snappy as you tap around, even on a slow network, a '+
+'key to perceived performance. [Learn more](https://developers.google.com/web/progressive-web-apps/checklist#page-transitions-dont-feel-like-they-block-on-the-network).',
+title:'Page transitions don\'t feel like they block on the network'},
super.partialMeta);
}}
module.exports=PWAPageTransitions;
-},{"./manual-audit":4}],"../audits/metrics":[function(require,module,exports){
+},{"./manual-audit":4}],"../audits/metrics/estimated-input-latency":[function(require,module,exports){
+
+
+
+
+
+'use strict';
+
+const Audit=require('../audit');
+
+class EstimatedInputLatency extends Audit{
+
+
+
+static get meta(){
+return{
+id:'estimated-input-latency',
+title:'Estimated Input Latency',
+description:'The score above is an estimate of how long your app takes to respond to user '+
+'input, in milliseconds, during the busiest 5s window of page load. If your '+
+'latency is higher than 50 ms, users may perceive your app as laggy. '+
+'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/estimated-input-latency).',
+scoreDisplayMode:Audit.SCORING_MODES.NUMERIC,
+requiredArtifacts:['traces']};
+
+}
+
+
+
+
+static get defaultOptions(){
+return{
+
+scorePODR:50,
+scoreMedian:100};
+
+}
+
+
+
+
+
+
+
+
+
+static async audit(artifacts,context){
+const trace=artifacts.traces[Audit.DEFAULT_PASS];
+const devtoolsLog=artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
+const metricComputationData={trace,devtoolsLog,settings:context.settings};
+const metricResult=await artifacts.requestEstimatedInputLatency(metricComputationData);
+
+return{
+score:Audit.computeLogNormalScore(
+metricResult.timing,
+context.options.scorePODR,
+context.options.scoreMedian),
+
+rawValue:metricResult.timing,
+displayValue:['%d\xa0ms',metricResult.timing]};
+
+}}
+
+
+module.exports=EstimatedInputLatency;
+
+},{"../audit":2}],"../audits/metrics/first-contentful-paint":[function(require,module,exports){
+
+
+
+
+
+'use strict';
+
+const Audit=require('../audit');
+const Util=require('../../report/html/renderer/util.js');
+
+class FirstContentfulPaint extends Audit{
+
+
+
+static get meta(){
+return{
+id:'first-contentful-paint',
+title:'First Contentful Paint',
+description:'First contentful paint marks the time at which the first text/image is '+
+`painted. [Learn more](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics#first_paint_and_first_contentful_paint).`,
+scoreDisplayMode:Audit.SCORING_MODES.NUMERIC,
+requiredArtifacts:['traces','devtoolsLogs']};
+
+}
+
+
+
+
+static get defaultOptions(){
+return{
+
+
+
+scorePODR:2000,
+scoreMedian:4000};
+
+}
+
+
+
+
+
+
+static async audit(artifacts,context){
+const trace=artifacts.traces[Audit.DEFAULT_PASS];
+const devtoolsLog=artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
+const metricComputationData={trace,devtoolsLog,settings:context.settings};
+const metricResult=await artifacts.requestFirstContentfulPaint(metricComputationData);
+
+return{
+score:Audit.computeLogNormalScore(
+metricResult.timing,
+context.options.scorePODR,
+context.options.scoreMedian),
+
+rawValue:metricResult.timing,
+displayValue:[Util.MS_DISPLAY_VALUE,metricResult.timing]};
+
+}}
+
+
+module.exports=FirstContentfulPaint;
+
+},{"../../report/html/renderer/util.js":48,"../audit":2}],"../audits/metrics/first-cpu-idle":[function(require,module,exports){
+
+
+
+
+
+'use strict';
+
+const Audit=require('../audit');
+const Util=require('../../report/html/renderer/util.js');
+
+class FirstCPUIdle extends Audit{
+
+
+
+static get meta(){
+return{
+id:'first-cpu-idle',
+title:'First CPU Idle',
+description:'First CPU Idle marks the first time at which the page\'s main thread is '+
+'quiet enough to handle input. '+
+'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/first-interactive).',
+scoreDisplayMode:Audit.SCORING_MODES.NUMERIC,
+requiredArtifacts:['traces']};
+
+}
+
+
+
+
+static get defaultOptions(){
+return{
+
+
+
+scorePODR:2900,
+scoreMedian:6500};
+
+}
+
+
+
+
+
+
+
+
+
+static async audit(artifacts,context){
+const trace=artifacts.traces[Audit.DEFAULT_PASS];
+const devtoolsLog=artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
+const metricComputationData={trace,devtoolsLog,settings:context.settings};
+const metricResult=await artifacts.requestFirstCPUIdle(metricComputationData);
+
+return{
+score:Audit.computeLogNormalScore(
+metricResult.timing,
+context.options.scorePODR,
+context.options.scoreMedian),
+
+rawValue:metricResult.timing,
+displayValue:[Util.MS_DISPLAY_VALUE,metricResult.timing]};
+
+}}
+
+
+module.exports=FirstCPUIdle;
+
+},{"../../report/html/renderer/util.js":48,"../audit":2}],"../audits/metrics/first-meaningful-paint":[function(require,module,exports){
+
+
+
+
+
+'use strict';
+
+const Audit=require('../audit');
+const Util=require('../../report/html/renderer/util');
+
+class FirstMeaningfulPaint extends Audit{
+
+
+
+static get meta(){
+return{
+id:'first-meaningful-paint',
+title:'First Meaningful Paint',
+description:'First Meaningful Paint measures when the primary content of a page is '+
+'visible. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/first-meaningful-paint).',
+scoreDisplayMode:Audit.SCORING_MODES.NUMERIC,
+requiredArtifacts:['traces']};
+
+}
+
+
+
+
+static get defaultOptions(){
+return{
+
+
+
+scorePODR:2000,
+scoreMedian:4000};
+
+}
+
+
+
+
+
+
+
+
+
+static async audit(artifacts,context){
+const trace=artifacts.traces[Audit.DEFAULT_PASS];
+const devtoolsLog=artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
+const metricComputationData={trace,devtoolsLog,settings:context.settings};
+const metricResult=await artifacts.requestFirstMeaningfulPaint(metricComputationData);
+
+return{
+score:Audit.computeLogNormalScore(
+metricResult.timing,
+context.options.scorePODR,
+context.options.scoreMedian),
+
+rawValue:metricResult.timing,
+displayValue:[Util.MS_DISPLAY_VALUE,metricResult.timing]};
+
+}}
+
+
+module.exports=FirstMeaningfulPaint;
+
+},{"../../report/html/renderer/util":48,"../audit":2}],"../audits/metrics/interactive":[function(require,module,exports){
+
+
+
+
+
+'use strict';
+
+const Audit=require('../audit');
+const Util=require('../../report/html/renderer/util');
+
+
+
+
+
+
+
+class InteractiveMetric extends Audit{
+
+
+
+static get meta(){
+return{
+id:'interactive',
+title:'Time to Interactive',
+description:'Interactive marks the time at which the page is fully interactive. '+
+'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/consistently-interactive).',
+scoreDisplayMode:Audit.SCORING_MODES.NUMERIC,
+requiredArtifacts:['traces','devtoolsLogs']};
+
+}
+
+
+
+
+static get defaultOptions(){
+return{
+
+
+
+scorePODR:2900,
+scoreMedian:7300};
+
+}
+
+
+
+
+
+
+static async audit(artifacts,context){
+const trace=artifacts.traces[Audit.DEFAULT_PASS];
+const devtoolsLog=artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
+const metricComputationData={trace,devtoolsLog,settings:context.settings};
+const metricResult=await artifacts.requestInteractive(metricComputationData);
+const timeInMs=metricResult.timing;
+const extendedInfo={
+timeInMs,
+timestamp:metricResult.timestamp,
+
+optimistic:metricResult.optimisticEstimate&&metricResult.optimisticEstimate.timeInMs,
+
+pessimistic:metricResult.pessimisticEstimate&&metricResult.pessimisticEstimate.timeInMs};
+
+
+return{
+score:Audit.computeLogNormalScore(
+timeInMs,
+context.options.scorePODR,
+context.options.scoreMedian),
+
+rawValue:timeInMs,
+displayValue:[Util.MS_DISPLAY_VALUE,timeInMs],
+extendedInfo:{
+value:extendedInfo}};
+
+
+}}
+
+
+module.exports=InteractiveMetric;
+
+},{"../../report/html/renderer/util":48,"../audit":2}],"../audits/metrics/speed-index":[function(require,module,exports){
+
+
+
+
+
+'use strict';
+
+const Audit=require('../audit');
+const Util=require('../../report/html/renderer/util');
+
+class SpeedIndex extends Audit{
+
+
+
+static get meta(){
+return{
+id:'speed-index',
+title:'Speed Index',
+description:'Speed Index shows how quickly the contents of a page are visibly populated. '+
+'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/speed-index).',
+scoreDisplayMode:Audit.SCORING_MODES.NUMERIC,
+requiredArtifacts:['traces','devtoolsLogs']};
+
+}
+
+
+
+
+static get defaultOptions(){
+return{
+
+
+
+scorePODR:2900,
+scoreMedian:5800};
+
+}
+
+
+
+
+
+
+
+
+static async audit(artifacts,context){
+const trace=artifacts.traces[Audit.DEFAULT_PASS];
+const devtoolsLog=artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
+const metricComputationData={trace,devtoolsLog,settings:context.settings};
+const metricResult=await artifacts.requestSpeedIndex(metricComputationData);
+
+return{
+score:Audit.computeLogNormalScore(
+metricResult.timing,
+context.options.scorePODR,
+context.options.scoreMedian),
+
+rawValue:metricResult.timing,
+displayValue:[Util.MS_DISPLAY_VALUE,metricResult.timing]};
+
+}}
+
+
+module.exports=SpeedIndex;
+
+},{"../../report/html/renderer/util":48,"../audit":2}],"../audits/metrics":[function(require,module,exports){
@@ -5905,10 +5971,10 @@ class Metrics extends Audit{
static get meta(){
return{
-name:'metrics',
+id:'metrics',
scoreDisplayMode:Audit.SCORING_MODES.INFORMATIVE,
-description:'Metrics',
-helpText:'Collects all available metrics.',
+title:'Metrics',
+description:'Collects all available metrics.',
requiredArtifacts:['traces','devtoolsLogs']};
}
@@ -6037,7 +6103,6 @@ module.exports=Metrics;
-
'use strict';
const Audit=require('./audit');
@@ -6056,10 +6121,10 @@ class MixedContent extends Audit{
static get meta(){
return{
-name:'mixed-content',
-description:'All resources loaded are secure',
-failureDescription:'Some insecure resources can be upgraded to HTTPS',
-helpText:`Mixed content warnings can prevent you from upgrading to HTTPS.
+id:'mixed-content',
+title:'All resources loaded are secure',
+failureTitle:'Some insecure resources can be upgraded to HTTPS',
+description:`Mixed content warnings can prevent you from upgrading to HTTPS.
This audit shows which insecure resources this page uses that can be
upgraded to HTTPS. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/mixed-content)`,
requiredArtifacts:['devtoolsLogs','MixedContent']};
@@ -6072,18 +6137,6 @@ requiredArtifacts:['devtoolsLogs','MixedContent']};
-
-
-static isSecureRecord(record){
-return record.securityState()==='secure'||record.protocol==='data';
-}
-
-
-
-
-
-
-
static upgradeURL(url){
const parsedURL=new URL(url);
parsedURL.protocol='https:';
@@ -6109,7 +6162,7 @@ return parsedURL.href;
-static displayURL(url){
+static displayURL(url=''){
const displayOptions={
numPathParts:4,
preserveQuery:false,
@@ -6134,15 +6187,15 @@ artifacts.requestNetworkRecords(upgradeLogs)];
return Promise.all(computedArtifacts).then(([defaultRecords,upgradedRecords])=>{
const insecureRecords=defaultRecords.filter(
-record=>!MixedContent.isSecureRecord(record));
+record=>!record.isSecure);
const secureRecords=defaultRecords.filter(
-record=>MixedContent.isSecureRecord(record));
+record=>record.isSecure);
const upgradePassHosts=new Set();
const upgradePassSecureHosts=new Set();
upgradedRecords.forEach(record=>{
upgradePassHosts.add(new URL(record.url).hostname);
-if(MixedContent.isSecureRecord(record)&&record.finished&&!record.failed){
+if(record.isSecure&&record.finished&&!record.failed){
upgradePassSecureHosts.add(new URL(record.url).hostname);
}
});
@@ -6161,7 +6214,7 @@ seen.add(simpleUrl);
const resource={
host:new URL(record.url).hostname,
fullUrl:record.url,
-referrerDocUrl:this.displayURL(record._documentURL)};
+referrerDocUrl:this.displayURL(record.documentURL)};
if(!upgradePassSecureHosts.has(resource.host))continue;
@@ -6211,10 +6264,10 @@ class NetworkRequests extends Audit{
static get meta(){
return{
-name:'network-requests',
+id:'network-requests',
scoreDisplayMode:Audit.SCORING_MODES.INFORMATIVE,
-description:'Network Requests',
-helpText:'Lists the network requests that were made during page load.',
+title:'Network Requests',
+description:'Lists the network requests that were made during page load.',
requiredArtifacts:['devtoolsLogs']};
}
@@ -6231,15 +6284,19 @@ const earliestStartTime=records.reduce(
Infinity);
+
+const timeToMs=time=>time<earliestStartTime||!Number.isFinite(time)?
+undefined:(time-earliestStartTime)*1000;
+
const results=records.map(record=>{
return{
url:URL.elideDataURI(record.url),
-startTime:(record.startTime-earliestStartTime)*1000,
-endTime:(record.endTime-earliestStartTime)*1000,
+startTime:timeToMs(record.startTime),
+endTime:timeToMs(record.endTime),
transferSize:record.transferSize,
statusCode:record.statusCode,
-mimeType:record._mimeType,
-resourceType:record._resourceType&&record._resourceType._name};
+mimeType:record.mimeType,
+resourceType:record.resourceType};
});
@@ -6264,7 +6321,6 @@ const tableDetails=Audit.makeTableDetails(headings,results);
return{
score:1,
rawValue:results.length,
-extendedInfo:{value:results},
details:tableDetails};
});
@@ -6295,9 +6351,9 @@ class PredictivePerf extends Audit{
static get meta(){
return{
-name:'predictive-perf',
-description:'Predicted Performance (beta)',
-helpText:
+id:'predictive-perf',
+title:'Predicted Performance (beta)',
+description:
'Predicted performance evaluates how your site will perform under '+
'a 3G connection on a mobile device.',
scoreDisplayMode:Audit.SCORING_MODES.NUMERIC,
@@ -6381,11 +6437,11 @@ class RedirectsHTTP extends Audit{
static get meta(){
return{
-name:'redirects-http',
-description:'Redirects HTTP traffic to HTTPS',
-failureDescription:'Does not redirect HTTP traffic to HTTPS',
-helpText:'If you\'ve already set up HTTPS, make sure that you redirect all HTTP traffic '+
-'to HTTPS. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/http-redirects-to-https).',
+id:'redirects-http',
+title:'Redirects HTTP traffic to HTTPS',
+failureTitle:'Does not redirect HTTP traffic to HTTPS',
+description:'If you\'ve already set up HTTPS, make sure that you redirect all HTTP '+
+'traffic to HTTPS. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/http-redirects-to-https).',
requiredArtifacts:['HTTPRedirect']};
}
@@ -6420,10 +6476,10 @@ class Redirects extends Audit{
static get meta(){
return{
-name:'redirects',
-description:'Avoid multiple page redirects',
+id:'redirects',
+title:'Avoid multiple page redirects',
scoreDisplayMode:Audit.SCORING_MODES.NUMERIC,
-helpText:'Redirects introduce additional delays before the page can be loaded. [Learn more](https://developers.google.com/speed/docs/insights/AvoidRedirects).',
+description:'Redirects introduce additional delays before the page can be loaded. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/redirects).',
requiredArtifacts:['URL','devtoolsLogs','traces']};
}
@@ -6481,7 +6537,6 @@ if(!initialTiming||!redirectedTiming){
throw new Error('Could not find redirects in graph');
}
-
const wastedMs=redirectedTiming.startTime-initialTiming.startTime;
totalWastedMs+=wastedMs;
@@ -6538,10 +6593,10 @@ class ScreenshotThumbnails extends Audit{
static get meta(){
return{
-name:'screenshot-thumbnails',
+id:'screenshot-thumbnails',
scoreDisplayMode:Audit.SCORING_MODES.INFORMATIVE,
-description:'Screenshot Thumbnails',
-helpText:'This is what the load of your site looked like.',
+title:'Screenshot Thumbnails',
+description:'This is what the load of your site looked like.',
requiredArtifacts:['traces','devtoolsLogs']};
}
@@ -6661,7 +6716,7 @@ items:thumbnails}};
module.exports=ScreenshotThumbnails;
-},{"../lib/errors":33,"./audit":2,"jpeg-js":140}],"../audits/seo/canonical":[function(require,module,exports){
+},{"../lib/errors":33,"./audit":2,"jpeg-js":122}],"../audits/seo/canonical":[function(require,module,exports){
@@ -6724,10 +6779,10 @@ class Canonical extends Audit{
static get meta(){
return{
-name:'canonical',
-description:'Document has a valid `rel=canonical`',
-failureDescription:'Document does not have a valid `rel=canonical`',
-helpText:'Canonical links suggest which URL to show in search results. '+
+id:'canonical',
+title:'Document has a valid `rel=canonical`',
+failureTitle:'Document does not have a valid `rel=canonical`',
+description:'Canonical links suggest which URL to show in search results. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/canonical).',
requiredArtifacts:['Canonical','Hreflang','URL']};
@@ -6748,7 +6803,7 @@ let canonicals=[];
let hreflangs=[];
-mainResource._responseHeaders&&mainResource._responseHeaders.
+mainResource.responseHeaders&&mainResource.responseHeaders.
filter(h=>h.name.toLowerCase()===LINK_HEADER).
forEach(h=>{
canonicals=canonicals.concat(getCanonicalLinksFromHeader(h.value));
@@ -6838,7 +6893,7 @@ rawValue:true};
module.exports=Canonical;
-},{"../../lib/url-shim":"url","../audit":2,"http-link-header":137}],"../audits/seo/font-size":[function(require,module,exports){
+},{"../../lib/url-shim":"url","../audit":2,"http-link-header":119}],"../audits/seo/font-size":[function(require,module,exports){
@@ -7025,10 +7080,10 @@ class FontSize extends Audit{
static get meta(){
return{
-name:'font-size',
-description:'Document uses legible font sizes',
-failureDescription:'Document doesn\'t use legible font sizes',
-helpText:'Font sizes less than 12px are too small to be legible and require mobile '+
+id:'font-size',
+title:'Document uses legible font sizes',
+failureTitle:'Document doesn\'t use legible font sizes',
+description:'Font sizes less than 12px are too small to be legible and require mobile '+
'visitors to “pinch to zoom” in order to read. Strive to have >60% of page text ≥12px. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/font-sizes).',
requiredArtifacts:['FontSize','URL','Viewport']};
@@ -7206,10 +7261,10 @@ class Hreflang extends Audit{
static get meta(){
return{
-name:'hreflang',
-description:'Document has a valid `hreflang`',
-failureDescription:'Document doesn\'t have a valid `hreflang`',
-helpText:'hreflang links tell search engines what version of a page they should '+
+id:'hreflang',
+title:'Document has a valid `hreflang`',
+failureTitle:'Document doesn\'t have a valid `hreflang`',
+description:'hreflang links tell search engines what version of a page they should '+
'list in search results for a given language or region. [Learn more]'+
'(https://developers.google.com/web/tools/lighthouse/audits/hreflang).',
requiredArtifacts:['Hreflang','URL']};
@@ -7242,7 +7297,7 @@ snippet:`<link name="alternate" hreflang="${hreflang}" href="${href}" />`}});
});
}
-mainResource._responseHeaders&&mainResource._responseHeaders.
+mainResource.responseHeaders&&mainResource.responseHeaders.
filter(h=>h.name.toLowerCase()===LINK_HEADER&&!headerHasValidHreflangs(h.value)).
forEach(h=>invalidHreflangs.push({source:`${h.name}: ${h.value}`}));
@@ -7262,7 +7317,7 @@ details};
module.exports=Hreflang;
}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{});
-},{"../audit":2,"axe-core/lib/commons/utils/valid-langs.js":98,"http-link-header":137}],"../audits/seo/http-status-code":[function(require,module,exports){
+},{"../audit":2,"axe-core/lib/commons/utils/valid-langs.js":98,"http-link-header":119}],"../audits/seo/http-status-code":[function(require,module,exports){
@@ -7280,10 +7335,10 @@ class HTTPStatusCode extends Audit{
static get meta(){
return{
-name:'http-status-code',
-description:'Page has successful HTTP status code',
-failureDescription:'Page has unsuccessful HTTP status code',
-helpText:'Pages with unsuccessful HTTP status codes may not be indexed properly. '+
+id:'http-status-code',
+title:'Page has successful HTTP status code',
+failureTitle:'Page has unsuccessful HTTP status code',
+description:'Pages with unsuccessful HTTP status codes may not be indexed properly. '+
'[Learn more]'+
'(https://developers.google.com/web/tools/lighthouse/audits/successful-http-code).',
requiredArtifacts:['devtoolsLogs','URL']};
@@ -7384,10 +7439,10 @@ class IsCrawlable extends Audit{
static get meta(){
return{
-name:'is-crawlable',
-description:'Page isn’t blocked from indexing',
-failureDescription:'Page is blocked from indexing',
-helpText:'Search engines are unable to include your pages in search results '+
+id:'is-crawlable',
+title:'Page isn’t blocked from indexing',
+failureTitle:'Page is blocked from indexing',
+description:'Search engines are unable to include your pages in search results '+
'if they don\'t have permission to crawl them. [Learn '+
'more](https://developers.google.com/web/tools/lighthouse/audits/indexing).',
requiredArtifacts:['MetaRobots','RobotsTxt','URL']};
@@ -7419,7 +7474,7 @@ snippet:`<meta name="robots" content="${artifacts.MetaRobots}" />`}});
}
}
-mainResource._responseHeaders&&mainResource._responseHeaders.
+mainResource.responseHeaders&&mainResource.responseHeaders.
filter(h=>h.name.toLowerCase()===ROBOTS_HEADER&&!hasUserAgent(h.value)&&
hasBlockingDirective(h.value)).
forEach(h=>blockingDirectives.push({source:`${h.name}: ${h.value}`}));
@@ -7453,7 +7508,7 @@ details};
module.exports=IsCrawlable;
-},{"../../lib/url-shim":"url","../audit":2,"robots-parser":149}],"../audits/seo/link-text":[function(require,module,exports){
+},{"../../lib/url-shim":"url","../audit":2,"robots-parser":131}],"../audits/seo/link-text":[function(require,module,exports){
@@ -7481,10 +7536,10 @@ class LinkText extends Audit{
static get meta(){
return{
-name:'link-text',
-description:'Links have descriptive text',
-failureDescription:'Links do not have descriptive text',
-helpText:'Descriptive link text helps search engines understand your content. '+
+id:'link-text',
+title:'Links have descriptive text',
+failureTitle:'Links do not have descriptive text',
+description:'Descriptive link text helps search engines understand your content. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/descriptive-link-text).',
requiredArtifacts:['URL','CrawlableLinks']};
@@ -7550,9 +7605,9 @@ class MobileFriendly extends ManualAudit{
static get meta(){
return Object.assign({
-name:'mobile-friendly',
-helpText:'Take the [Mobile-Friendly Test](https://search.google.com/test/mobile-friendly) to check for audits not covered by Lighthouse, like sizing tap targets appropriately. [Learn more](https://developers.google.com/search/mobile-sites/).',
-description:'Page is mobile friendly'},
+id:'mobile-friendly',
+description:'Take the [Mobile-Friendly Test](https://search.google.com/test/mobile-friendly) to check for audits not covered by Lighthouse, like sizing tap targets appropriately. [Learn more](https://developers.google.com/search/mobile-sites/).',
+title:'Page is mobile friendly'},
super.partialMeta);
}}
@@ -7579,9 +7634,9 @@ class StructuredData extends ManualAudit{
static get meta(){
return Object.assign({
-name:'structured-data',
-helpText:'Run the [Structured Data Testing Tool](https://search.google.com/structured-data/testing-tool/) and the [Structured Data Linter](http://linter.structured-data.org/) to validate structured data. [Learn more](https://developers.google.com/search/docs/guides/mark-up-content).',
-description:'Structured data is valid'},
+id:'structured-data',
+description:'Run the [Structured Data Testing Tool](https://search.google.com/structured-data/testing-tool/) and the [Structured Data Linter](http://linter.structured-data.org/) to validate structured data. [Learn more](https://developers.google.com/search/docs/guides/mark-up-content).',
+title:'Structured data is valid'},
super.partialMeta);
}}
@@ -7604,10 +7659,10 @@ class Description extends Audit{
static get meta(){
return{
-name:'meta-description',
-description:'Document has a meta description',
-failureDescription:'Document does not have a meta description',
-helpText:'Meta descriptions may be included in search results to concisely summarize '+
+id:'meta-description',
+title:'Document has a meta description',
+failureTitle:'Document does not have a meta description',
+description:'Meta descriptions may be included in search results to concisely summarize '+
'page content. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/description).',
requiredArtifacts:['MetaDescription']};
@@ -7715,10 +7770,10 @@ class Plugins extends Audit{
static get meta(){
return{
-name:'plugins',
-description:'Document avoids plugins',
-failureDescription:'Document uses plugins',
-helpText:'Search engines can\'t index plugin content, and '+
+id:'plugins',
+title:'Document avoids plugins',
+failureTitle:'Document uses plugins',
+description:'Search engines can\'t index plugin content, and '+
'many devices restrict plugins or don\'t support them. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/plugins).',
requiredArtifacts:['EmbeddedContent']};
@@ -7961,10 +8016,10 @@ class RobotsTxt extends Audit{
static get meta(){
return{
-name:'robots-txt',
-description:'robots.txt is valid',
-failureDescription:'robots.txt is not valid',
-helpText:'If your robots.txt file is malformed, crawlers may not be able to understand '+
+id:'robots-txt',
+title:'robots.txt is valid',
+failureTitle:'robots.txt is not valid',
+description:'If your robots.txt file is malformed, crawlers may not be able to understand '+
'how you want your website to be crawled or indexed.',
requiredArtifacts:['RobotsTxt']};
@@ -8047,10 +8102,10 @@ class ServiceWorker extends Audit{
static get meta(){
return{
-name:'service-worker',
-description:'Registers a service worker',
-failureDescription:'Does not register a service worker',
-helpText:'The service worker is the technology that enables your app to use many '+
+id:'service-worker',
+title:'Registers a service worker',
+failureTitle:'Does not register a service worker',
+description:'The service worker is the technology that enables your app to use many '+
'Progressive Web App features, such as offline, add to homescreen, and push '+
'notifications. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/registered-service-worker).',
requiredArtifacts:['URL','ServiceWorker']};
@@ -8079,73 +8134,7 @@ rawValue:!!matchingSW};
module.exports=ServiceWorker;
-},{"../lib/url-shim":"url","./audit":2}],"../audits/speed-index":[function(require,module,exports){
-
-
-
-
-
-'use strict';
-
-const Audit=require('./audit');
-const Util=require('../report/html/renderer/util');
-
-class SpeedIndex extends Audit{
-
-
-
-static get meta(){
-return{
-name:'speed-index',
-description:'Speed Index',
-helpText:'Speed Index shows how quickly the contents of a page are visibly populated. '+
-'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/speed-index).',
-scoreDisplayMode:Audit.SCORING_MODES.NUMERIC,
-requiredArtifacts:['traces','devtoolsLogs']};
-
-}
-
-
-
-
-static get defaultOptions(){
-return{
-
-
-
-scorePODR:2900,
-scoreMedian:5800};
-
-}
-
-
-
-
-
-
-
-
-static async audit(artifacts,context){
-const trace=artifacts.traces[Audit.DEFAULT_PASS];
-const devtoolsLog=artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
-const metricComputationData={trace,devtoolsLog,settings:context.settings};
-const metricResult=await artifacts.requestSpeedIndex(metricComputationData);
-
-return{
-score:Audit.computeLogNormalScore(
-metricResult.timing,
-context.options.scorePODR,
-context.options.scoreMedian),
-
-rawValue:metricResult.timing,
-displayValue:[Util.MS_DISPLAY_VALUE,metricResult.timing]};
-
-}}
-
-
-module.exports=SpeedIndex;
-
-},{"../report/html/renderer/util":48,"./audit":2}],"../audits/splash-screen":[function(require,module,exports){
+},{"../lib/url-shim":"url","./audit":2}],"../audits/splash-screen":[function(require,module,exports){
@@ -8174,10 +8163,10 @@ class SplashScreen extends MultiCheckAudit{
static get meta(){
return{
-name:'splash-screen',
-description:'Configured for a custom splash screen',
-failureDescription:'Is not configured for a custom splash screen',
-helpText:'A themed splash screen ensures a high-quality experience when '+
+id:'splash-screen',
+title:'Configured for a custom splash screen',
+failureTitle:'Is not configured for a custom splash screen',
+description:'A themed splash screen ensures a high-quality experience when '+
'users launch your app from their homescreens. [Learn '+
'more](https://developers.google.com/web/tools/lighthouse/audits/custom-splash-screen).',
requiredArtifacts:['Manifest']};
@@ -8258,10 +8247,10 @@ class ThemedOmnibox extends MultiCheckAudit{
static get meta(){
return{
-name:'themed-omnibox',
-description:'Address bar matches brand colors',
-failureDescription:'Address bar does not match brand colors',
-helpText:'The browser address bar can be themed to match your site. '+
+id:'themed-omnibox',
+title:'Address bar matches brand colors',
+failureTitle:'Address bar does not match brand colors',
+description:'The browser address bar can be themed to match your site. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/address-bar).',
requiredArtifacts:['Manifest','ThemeColor']};
@@ -8327,7 +8316,6 @@ module.exports=ThemedOmnibox;
'use strict';
const Audit=require('./audit');
-const Util=require('../report/html/renderer/util');
const TTFB_THRESHOLD=600;
@@ -8337,10 +8325,10 @@ class TTFBMetric extends Audit{
static get meta(){
return{
-name:'time-to-first-byte',
-description:'Keep server response times low (TTFB)',
-helpText:'Time To First Byte identifies the time at which your server sends a response.'+
-' [Learn more](https://developers.google.com/web/tools/chrome-devtools/network-performance/issues).',
+id:'time-to-first-byte',
+title:'Keep server response times low (TTFB)',
+description:'Time To First Byte identifies the time at which your server sends a response.'+
+' [Learn more](https://developers.google.com/web/tools/lighthouse/audits/ttfb).',
requiredArtifacts:['devtoolsLogs','URL']};
}
@@ -8349,9 +8337,8 @@ requiredArtifacts:['devtoolsLogs','URL']};
static caclulateTTFB(record){
-const timing=record._timing;
-
-return timing.receiveHeadersEnd-timing.sendEnd;
+const timing=record.timing;
+return timing?timing.receiveHeadersEnd-timing.sendEnd:0;
}
@@ -8363,10 +8350,11 @@ const devtoolsLogs=artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
return artifacts.requestNetworkRecords(devtoolsLogs).
then(networkRecords=>{
+
let displayValue='';
const finalUrl=artifacts.URL.finalUrl;
-const finalUrlRequest=networkRecords.find(record=>record._url===finalUrl);
+const finalUrlRequest=networkRecords.find(record=>record.url===finalUrl);
if(!finalUrlRequest){
throw new Error(`finalUrl '${finalUrl} not found in network records.`);
}
@@ -8374,18 +8362,22 @@ const ttfb=TTFBMetric.caclulateTTFB(finalUrlRequest);
const passed=ttfb<TTFB_THRESHOLD;
if(!passed){
-displayValue=`Root document took ${Util.formatMilliseconds(ttfb,1)} `;
+displayValue=['Root document took %10d',ttfb];
}
+
+const details={
+type:'opportunity',
+overallSavingsMs:ttfb-TTFB_THRESHOLD,
+headings:[],
+items:[]};
+
+
return{
rawValue:ttfb,
score:Number(passed),
displayValue,
-details:{
-summary:{
-wastedMs:ttfb-TTFB_THRESHOLD}},
-
-
+details,
extendedInfo:{
value:{
wastedMs:ttfb-TTFB_THRESHOLD}}};
@@ -8398,7 +8390,7 @@ wastedMs:ttfb-TTFB_THRESHOLD}}};
module.exports=TTFBMetric;
-},{"../report/html/renderer/util":48,"./audit":2}],"../audits/user-timings":[function(require,module,exports){
+},{"./audit":2}],"../audits/user-timings":[function(require,module,exports){
@@ -8417,10 +8409,10 @@ class UserTimings extends Audit{
static get meta(){
return{
-name:'user-timings',
+id:'user-timings',
scoreDisplayMode:Audit.SCORING_MODES.INFORMATIVE,
-description:'User Timing marks and measures',
-helpText:'Consider instrumenting your app with the User Timing API to create custom, '+
+title:'User Timing marks and measures',
+description:'Consider instrumenting your app with the User Timing API to create custom, '+
'real-world measurements of key user experiences. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/user-timing).',
requiredArtifacts:['traces']};
@@ -8516,16 +8508,16 @@ const trace=artifacts.traces[Audit.DEFAULT_PASS];
return artifacts.requestTraceOfTab(trace).then(tabTrace=>{
const userTimings=this.filterTrace(tabTrace).filter(UserTimings.excludeBlacklisted);
const tableRows=userTimings.map(item=>{
-const time=item.isMark?item.startTime:item.duration;
return{
name:item.name,
-timingType:item.isMark?'Mark':'Measure',
-time};
+startTime:item.startTime,
+duration:item.isMark?undefined:item.duration,
+timingType:item.isMark?'Mark':'Measure'};
}).sort((itemA,itemB)=>{
if(itemA.timingType===itemB.timingType){
-return itemA.time-itemB.time;
+return itemA.startTime-itemB.startTime;
}else if(itemA.timingType==='Measure'){
return-1;
@@ -8537,16 +8529,26 @@ return 1;
const headings=[
{key:'name',itemType:'text',text:'Name'},
{key:'timingType',itemType:'text',text:'Type'},
-{key:'time',itemType:'ms',granularity:0.01,text:'Time'}];
+{key:'startTime',itemType:'ms',granularity:0.01,text:'Start Time'},
+{key:'duration',itemType:'ms',granularity:0.01,text:'Duration'}];
const details=Audit.makeTableDetails(headings,tableRows);
+
+let displayValue;
+if(userTimings.length){
+displayValue=[
+userTimings.length===1?'%d user timing':'%d user timings',
+userTimings.length];
+
+}
+
return{
rawValue:userTimings.length===0,
notApplicable:userTimings.length===0,
-displayValue:userTimings.length?`${userTimings.length}`:'',
+displayValue,
extendedInfo:{
value:userTimings},
@@ -8583,9 +8585,9 @@ class UsesRelPreconnectAudit extends Audit{
static get meta(){
return{
-name:'uses-rel-preconnect',
-description:'Avoid multiple, costly round trips to any origin',
-helpText:
+id:'uses-rel-preconnect',
+title:'Avoid multiple, costly round trips to any origin',
+description:
'Consider adding preconnect or dns-prefetch resource hints to establish early '+
`connections to important third-party origins. [Learn more](https://developers.google.com/web/fundamentals/performance/resource-prioritization#preconnect).`,
requiredArtifacts:['devtoolsLogs','URL'],
@@ -8599,7 +8601,7 @@ scoreDisplayMode:Audit.SCORING_MODES.NUMERIC};
static hasValidTiming(record){
-return record._timing&&record._timing.connectEnd>0&&record._timing.connectStart>0;
+return!!record.timing&&record.timing.connectEnd>0&&record.timing.connectStart>0;
}
@@ -8609,8 +8611,9 @@ return record._timing&&record._timing.connectEnd>0&&record._timing.connectStart>
static hasAlreadyConnectedToOrigin(record){
return(
-record._timing.dnsEnd-record._timing.dnsStart===0&&
-record._timing.connectEnd-record._timing.connectStart===0);
+!!record.timing&&
+record.timing.dnsEnd-record.timing.dnsStart===0&&
+record.timing.connectEnd-record.timing.connectStart===0);
}
@@ -8651,11 +8654,11 @@ if(
!UsesRelPreconnectAudit.hasValidTiming(record)||
-record.initiatorRequest()===mainResource||
+record.initiator.url===mainResource.url||
-!record.parsedURL||!record.parsedURL.securityOrigin()||
+!record.parsedURL||!record.parsedURL.securityOrigin||
-mainResource.parsedURL.securityOrigin()===record.parsedURL.securityOrigin()||
+mainResource.parsedURL.securityOrigin===record.parsedURL.securityOrigin||
UsesRelPreconnectAudit.hasAlreadyConnectedToOrigin(record)||
@@ -8664,7 +8667,7 @@ UsesRelPreconnectAudit.hasAlreadyConnectedToOrigin(record)||
return;
}
-const securityOrigin=record.parsedURL.securityOrigin();
+const securityOrigin=record.parsedURL.securityOrigin;
const records=origins.get(securityOrigin)||[];
records.push(record);
origins.set(securityOrigin,records);
@@ -8679,7 +8682,10 @@ const firstRecordOfOrigin=records.reduce((firstRecord,record)=>{
return record.startTime<firstRecord.startTime?record:firstRecord;
});
-const securityOrigin=firstRecordOfOrigin.parsedURL.securityOrigin();
+
+if(!firstRecordOfOrigin.timing)return;
+
+const securityOrigin=firstRecordOfOrigin.parsedURL.securityOrigin;
@@ -8692,7 +8698,7 @@ if(firstRecordOfOrigin.parsedURL.scheme==='https')connectionTime=connectionTime*
const timeBetweenMainResourceAndDnsStart=
firstRecordOfOrigin.startTime*1000-
mainResource.endTime*1000+
-firstRecordOfOrigin._timing.dnsStart;
+firstRecordOfOrigin.timing.dnsStart;
const wastedMs=Math.min(connectionTime,timeBetweenMainResourceAndDnsStart);
if(wastedMs<IGNORE_THRESHOLD_IN_MS)return;
@@ -8707,12 +8713,12 @@ wastedMs:wastedMs});
results=results.
sort((a,b)=>b.wastedMs-a.wastedMs);
+
const headings=[
-{key:'url',itemType:'url',text:'Origin'},
-{key:'wastedMs',itemType:'ms',text:'Potential Savings'}];
+{key:'url',valueType:'url',label:'Origin'},
+{key:'wastedMs',valueType:'timespanMs',label:'Potential Savings'}];
-const summary={wastedMs:maxWasted};
-const details=Audit.makeTableDetails(headings,results,summary);
+const details=Audit.makeOpportunityDetails(headings,results,maxWasted);
return{
score:UnusedBytes.scoreForWastedMs(maxWasted),
@@ -8736,6 +8742,7 @@ module.exports=UsesRelPreconnectAudit;
'use strict';
+const URL=require('../lib/url-shim');
const Audit=require('./audit');
const UnusedBytes=require('./byte-efficiency/byte-efficiency-audit');
const THRESHOLD_IN_MS=100;
@@ -8746,10 +8753,10 @@ class UsesRelPreloadAudit extends Audit{
static get meta(){
return{
-name:'uses-rel-preload',
-description:'Preload key requests',
-helpText:'Consider using <link rel=preload> to prioritize fetching late-discovered '+
-'resources sooner. [Learn more](https://developers.google.com/web/updates/2016/03/link-rel-preload).',
+id:'uses-rel-preload',
+title:'Preload key requests',
+description:'Consider using <link rel=preload> to prioritize fetching late-discovered '+
+'resources sooner. [Learn more](https://developers.google.com/web/tools/lighthouse/audits/preload).',
requiredArtifacts:['devtoolsLogs','traces','URL'],
scoreDisplayMode:Audit.SCORING_MODES.NUMERIC};
@@ -8794,6 +8801,20 @@ return requests;
+static shouldPreload(request,mainResource){
+if(request.isLinkPreload||URL.NON_NETWORK_PROTOCOLS.includes(request.protocol)){
+return false;
+}
+
+return URL.rootDomainsMatch(request.url,mainResource.url);
+}
+
+
+
+
+
+
+
static computeWasteWithGraph(urls,graph,simulator){
if(!urls.size){
@@ -8843,6 +8864,7 @@ for(const node of nodesToPreload){
const originalNode=originalNodesByRecord.get(node.record);
const timingAfter=simulationAfterChanges.nodeTimings.get(node);
const timingBefore=simulationBeforeChanges.nodeTimings.get(originalNode);
+if(!timingBefore||!timingAfter)throw new Error('Missing preload node');
const wastedMs=Math.round(timingBefore.endTime-timingAfter.endTime);
if(wastedMs<THRESHOLD_IN_MS)continue;
@@ -8889,8 +8911,8 @@ const criticalRequests=UsesRelPreloadAudit._flattenRequests(critChains,
const urls=new Set();
for(const networkRecord of criticalRequests){
-if(!networkRecord._isLinkPreload&&networkRecord.protocol!=='data'){
-urls.add(networkRecord._url);
+if(UsesRelPreloadAudit.shouldPreload(networkRecord,mainResource)){
+urls.add(networkRecord.url);
}
}
@@ -8898,12 +8920,12 @@ const{results,wastedMs}=UsesRelPreloadAudit.computeWasteWithGraph(urls,graph,sim
results.sort((a,b)=>b.wastedMs-a.wastedMs);
+
const headings=[
-{key:'url',itemType:'url',text:'URL'},
-{key:'wastedMs',itemType:'ms',text:'Potential Savings',granularity:10}];
+{key:'url',valueType:'url',label:'URL'},
+{key:'wastedMs',valueType:'timespanMs',label:'Potential Savings'}];
-const summary={wastedMs};
-const details=Audit.makeTableDetails(headings,results,summary);
+const details=Audit.makeOpportunityDetails(headings,results,wastedMs);
return{
score:UnusedBytes.scoreForWastedMs(wastedMs),
@@ -8919,7 +8941,7 @@ details};
module.exports=UsesRelPreloadAudit;
-},{"./audit":2,"./byte-efficiency/byte-efficiency-audit":3}],"../audits/viewport":[function(require,module,exports){
+},{"../lib/url-shim":"url","./audit":2,"./byte-efficiency/byte-efficiency-audit":3}],"../audits/viewport":[function(require,module,exports){
@@ -8936,11 +8958,11 @@ class Viewport extends Audit{
static get meta(){
return{
-name:'viewport',
-description:'Has a `<meta name="viewport">` tag with `width` or `initial-scale`',
-failureDescription:'Does not have a `<meta name="viewport">` tag with `width` '+
+id:'viewport',
+title:'Has a `<meta name="viewport">` tag with `width` or `initial-scale`',
+failureTitle:'Does not have a `<meta name="viewport">` tag with `width` '+
'or `initial-scale`',
-helpText:'Add a viewport meta tag to optimize your app for mobile screens. '+
+description:'Add a viewport meta tag to optimize your app for mobile screens. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/has-viewport-meta-tag).',
requiredArtifacts:['Viewport']};
@@ -8980,7 +9002,7 @@ warnings};
module.exports=Viewport;
-},{"./audit":2,"metaviewport-parser":145}],"../audits/webapp-install-banner":[function(require,module,exports){
+},{"./audit":2,"metaviewport-parser":127}],"../audits/webapp-install-banner":[function(require,module,exports){
@@ -9017,10 +9039,10 @@ class WebappInstallBanner extends MultiCheckAudit{
static get meta(){
return{
-name:'webapp-install-banner',
-description:'User can be prompted to Install the Web App',
-failureDescription:'User will not be prompted to Install the Web App',
-helpText:'Browsers can proactively prompt users to add your app to their homescreen, '+
+id:'webapp-install-banner',
+title:'User can be prompted to Install the Web App',
+failureTitle:'User will not be prompted to Install the Web App',
+description:'Browsers can proactively prompt users to add your app to their homescreen, '+
'which can lead to higher engagement. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/install-prompt).',
requiredArtifacts:['URL','ServiceWorker','Manifest','StartUrl']};
@@ -9040,6 +9062,12 @@ return[manifestValues.parseFailureReason];
const failures=[];
const bannerCheckIds=[
'hasName',
+
+
+
+
+
+
'hasShortName',
'hasStartUrl',
'hasPWADisplayValue',
@@ -9144,11 +9172,11 @@ class WithoutJavaScript extends Audit{
static get meta(){
return{
-name:'without-javascript',
-description:'Contains some content when JavaScript is not available',
-failureDescription:'Does not provide fallback content when JavaScript is not available',
-helpText:'Your app should display some content when JavaScript is disabled, even if it\'s '+
-'just a warning to the user that JavaScript is required to use the app. '+
+id:'without-javascript',
+title:'Contains some content when JavaScript is not available',
+failureTitle:'Does not provide fallback content when JavaScript is not available',
+description:'Your app should display some content when JavaScript is disabled, even if '+
+'it\'s just a warning to the user that JavaScript is required to use the app. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/no-js).',
requiredArtifacts:['HTMLWithoutJavaScript']};
@@ -9161,7 +9189,8 @@ requiredArtifacts:['HTMLWithoutJavaScript']};
static audit(artifacts){
const artifact=artifacts.HTMLWithoutJavaScript;
-if(artifact.value.trim()===''){
+
+if(artifact.bodyText.trim()===''&&!artifact.hasNoScript){
return{
rawValue:false,
explanation:'The page body should render some content if its scripts are not available.'};
@@ -9193,11 +9222,11 @@ class WorksOffline extends Audit{
static get meta(){
return{
-name:'works-offline',
-description:'Responds with a 200 when offline',
-failureDescription:'Does not respond with a 200 when offline',
-helpText:'If you\'re building a Progressive Web App, consider using a service worker so '+
-'that your app can work offline. '+
+id:'works-offline',
+title:'Responds with a 200 when offline',
+failureTitle:'Does not respond with a 200 when offline',
+description:'If you\'re building a Progressive Web App, consider using a service worker '+
+'so that your app can work offline. '+
'[Learn more](https://developers.google.com/web/tools/lighthouse/audits/http-200-when-offline).',
requiredArtifacts:['Offline','URL']};
@@ -9531,12 +9560,7 @@ stylesheets:Array.from(dedupedStylesheets.values())};
module.exports=CSSUsage;
-},{"./gatherer":19}],"../gather/gatherers/dobetterweb/all-event-listeners":[function(require,module,exports){
-
-
-
-
-
+},{"./gatherer":19}],"../gather/gatherers/dobetterweb/anchors-with-no-rel-noopener":[function(require,module,exports){
@@ -9545,142 +9569,59 @@ module.exports=CSSUsage;
'use strict';
const Gatherer=require('../gatherer');
-const Driver=require('../../driver.js');
-const Element=require('../../../lib/element.js');
-
-class EventListeners extends Gatherer{
-
-
-
-async listenForScriptParsedEvents(driver){
-
-const parsedScripts=new Map();
-
-const scriptListener=script=>{
-parsedScripts.set(script.scriptId,script);
-};
-
-
-driver.on('Debugger.scriptParsed',scriptListener);
-await driver.sendCommand('Debugger.enable');
-await driver.sendCommand('Debugger.disable');
-driver.off('Debugger.scriptParsed',scriptListener);
-
-return parsedScripts;
-}
-
-
-
-
-
-
-
-
-_listEventListeners(driver,nodeIdOrObject){
-let promise;
-
-if(typeof nodeIdOrObject==='string'){
-promise=driver.sendCommand('Runtime.evaluate',{
-expression:nodeIdOrObject,
-objectGroup:'event-listeners-gatherer'}).
-then(result=>result.result);
-}else{
-promise=driver.sendCommand('DOM.resolveNode',{
-nodeId:nodeIdOrObject,
-objectGroup:'event-listeners-gatherer'}).
-then(result=>result.object);
-}
-
-return promise.then(obj=>{
-const objectId=obj.objectId;
-const description=obj.description;
-if(!objectId||!description){
-return{listeners:[],tagName:''};
-}
-
-return driver.sendCommand('DOMDebugger.getEventListeners',{
-objectId}).
-then(results=>{
-return{listeners:results.listeners,tagName:description};
-});
-});
-}
-
-
-
-
-
-
-
-
-
-
-
-getEventListeners(driver,parsedScripts,nodeId){
-
-const matchedListeners=[];
-
-return this._listEventListeners(driver,nodeId).then(results=>{
-results.listeners.forEach(listener=>{
-
-
-const script=parsedScripts.get(listener.scriptId);
-if(script){
+const DOMHelpers=require('../../../lib/dom-helpers.js');
+class AnchorsWithNoRelNoopener extends Gatherer{
-matchedListeners.push({
-url:script.url,
-type:listener.type,
-handler:listener.handler,
-objectName:results.tagName,
-line:listener.lineNumber+1,
-col:listener.columnNumber+1});
+afterPass(passContext){
+const expression=`(function() {
+ ${DOMHelpers.getElementsInDocumentFnString}; // define function on page
+ const selector = 'a[target="_blank"]:not([rel~="noopener"]):not([rel~="noreferrer"])';
+ const elements = getElementsInDocument(selector);
+ return elements.map(node => ({
+ href: node.href,
+ rel: node.getAttribute('rel'),
+ target: node.getAttribute('target')
+ }));
+ })()`;
-}
-});
+return passContext.driver.evaluateAsync(expression);
+}}
-return matchedListeners;
-});
-}
+module.exports=AnchorsWithNoRelNoopener;
+},{"../../../lib/dom-helpers.js":30,"../gatherer":19}],"../gather/gatherers/dobetterweb/appcache":[function(require,module,exports){
+'use strict';
+const Gatherer=require('../gatherer');
-collectListeners(driver,parsedScripts,nodeIds){
+class AppCacheManifest extends Gatherer{
-return Promise.all(nodeIds.map(node=>this.getEventListeners(driver,parsedScripts,node))).
-then(nestedListeners=>nestedListeners.reduce((prev,curr)=>prev.concat(curr)));
-}
-async afterPass(passContext){
+afterPass(passContext){
const driver=passContext.driver;
-await passContext.driver.sendCommand('DOM.enable');
-const parsedScripts=await this.listenForScriptParsedEvents(driver);
-const elements=await passContext.driver.getElementsInDocument();
-const elementIds=[...elements.map(el=>el.getNodeId()),'document','window'];
-
-const listeners=await this.collectListeners(driver,parsedScripts,elementIds);
-await passContext.driver.sendCommand('DOM.disable');
-return listeners;
+return driver.querySelector('html').
+then(node=>node&&node.getAttribute('manifest'));
}}
-module.exports=EventListeners;
+module.exports=AppCacheManifest;
-},{"../../../lib/element.js":31,"../../driver.js":17,"../gatherer":19}],"../gather/gatherers/dobetterweb/anchors-with-no-rel-noopener":[function(require,module,exports){
+},{"../gatherer":19}],"../gather/gatherers/dobetterweb/doctype":[function(require,module,exports){
@@ -9689,57 +9630,34 @@ module.exports=EventListeners;
'use strict';
const Gatherer=require('../gatherer');
-const DOMHelpers=require('../../../lib/dom-helpers.js');
-
-class AnchorsWithNoRelNoopener extends Gatherer{
-
-
-
-
-afterPass(passContext){
-const expression=`(function() {
- ${DOMHelpers.getElementsInDocumentFnString}; // define function on page
- const selector = 'a[target="_blank"]:not([rel~="noopener"]):not([rel~="noreferrer"])';
- const elements = getElementsInDocument(selector);
- return elements.map(node => ({
- href: node.href,
- rel: node.getAttribute('rel'),
- target: node.getAttribute('target')
- }));
- })()`;
-return passContext.driver.evaluateAsync(expression);
-}}
-
-
-module.exports=AnchorsWithNoRelNoopener;
-
-},{"../../../lib/dom-helpers.js":30,"../gatherer":19}],"../gather/gatherers/dobetterweb/appcache":[function(require,module,exports){
-'use strict';
-
-const Gatherer=require('../gatherer');
+function getDoctype(){
-class AppCacheManifest extends Gatherer{
+if(!document.doctype){
+return null;
+}
+const{name,publicId,systemId}=document.doctype;
+return{name,publicId,systemId};
+}
+class Doctype extends Gatherer{
afterPass(passContext){
const driver=passContext.driver;
-
-return driver.querySelector('html').
-then(node=>node&&node.getAttribute('manifest'));
+return driver.evaluateAsync(`(${getDoctype.toString()}())`);
}}
-module.exports=AppCacheManifest;
+module.exports=Doctype;
},{"../gatherer":19}],"../gather/gatherers/dobetterweb/domstats":[function(require,module,exports){
@@ -9990,6 +9908,7 @@ module.exports=JSLibraries;
const Gatherer=require('../gatherer');
const URL=require('../../../lib/url-shim');
+const NetworkRequest=require('../../../lib/network-request');
const Sentry=require('../../../lib/sentry');
const Driver=require('../../driver.js');
@@ -10058,25 +9977,24 @@ static filterImageRequests(pageUrl,networkRecords){
const seenUrls=new Set();
return networkRecords.reduce((prev,record)=>{
-if(seenUrls.has(record._url)||!record.finished){
+if(seenUrls.has(record.url)||!record.finished){
return prev;
}
-seenUrls.add(record._url);
-const isOptimizableImage=record._resourceType&&
-record._resourceType._name==='image'&&
-/image\/(png|bmp|jpeg)/.test(record._mimeType);
-const isSameOrigin=URL.originsMatch(pageUrl,record._url);
-const isBase64DataUri=/^data:.{2,40}base64\s*,/.test(record._url);
+seenUrls.add(record.url);
+const isOptimizableImage=record.resourceType===NetworkRequest.TYPES.Image&&
+/image\/(png|bmp|jpeg)/.test(record.mimeType);
+const isSameOrigin=URL.originsMatch(pageUrl,record.url);
+const isBase64DataUri=/^data:.{2,40}base64\s*,/.test(record.url);
-const actualResourceSize=Math.min(record._resourceSize||0,record._transferSize||0);
+const actualResourceSize=Math.min(record.resourceSize||0,record.transferSize||0);
if(isOptimizableImage&&actualResourceSize>MINIMUM_IMAGE_SIZE){
prev.push({
isSameOrigin,
isBase64DataUri,
-requestId:record._requestId,
-url:record._url,
-mimeType:record._mimeType,
+requestId:record.requestId,
+url:record.url,
+mimeType:record.mimeType,
resourceSize:actualResourceSize});
}
@@ -10092,6 +10010,8 @@ return prev;
_getEncodedResponse(driver,requestId,encoding){
+requestId=NetworkRequest.getRequestIdForBackend(requestId);
+
const quality=encoding==='jpeg'?JPEG_QUALITY:WEBP_QUALITY;
const params={requestId,encoding,quality,sizeOnly:true};
return driver.sendCommand('Audits.getEncodedResponse',params);
@@ -10163,8 +10083,7 @@ continue;
}
-
-const image=Object.assign({failed:false},stats,record);
+const image={failed:false,...stats,...record};
results.push(image);
}catch(err){
@@ -10177,8 +10096,7 @@ level:'warning'});
-
-const imageError=Object.assign({failed:true,errMsg:err.message},record);
+const imageError={failed:true,errMsg:err.message,...record};
results.push(imageError);
}
}
@@ -10210,7 +10128,7 @@ return results;
module.exports=OptimizedImages;
-},{"../../../lib/sentry":39,"../../../lib/url-shim":"url","../../driver.js":17,"../gatherer":19}],"../gather/gatherers/dobetterweb/password-inputs-with-prevented-paste":[function(require,module,exports){
+},{"../../../lib/network-request":38,"../../../lib/sentry":40,"../../../lib/url-shim":"url","../../driver.js":17,"../gatherer":19}],"../gather/gatherers/dobetterweb/password-inputs-with-prevented-paste":[function(require,module,exports){
@@ -10281,12 +10199,23 @@ module.exports=PasswordInputsWithPreventedPaste;
'use strict';
const Gatherer=require('../gatherer');
+const URL=require('../../../lib/url-shim');
+const Sentry=require('../../../lib/sentry');
+const NetworkRequest=require('../../../lib/network-request');
const gzip=require('zlib').gzip;
+const CHROME_EXTENSION_PROTOCOL='chrome-extension:';
const compressionHeaders=['content-encoding','x-original-content-encoding'];
const compressionTypes=['gzip','br','deflate'];
const binaryMimeTypes=['image','audio','video'];
-const CHROME_EXTENSION_PROTOCOL='chrome-extension:';
+const textResourceTypes=[
+NetworkRequest.TYPES.Document,
+NetworkRequest.TYPES.Script,
+NetworkRequest.TYPES.Stylesheet,
+NetworkRequest.TYPES.XHR,
+NetworkRequest.TYPES.Fetch,
+NetworkRequest.TYPES.EventSource];
+
class ResponseCompression extends Gatherer{
@@ -10298,20 +10227,20 @@ static filterUnoptimizedResponses(networkRecords){
const unoptimizedResponses=[];
networkRecords.forEach(record=>{
-const mimeType=record._mimeType;
-const resourceType=record._resourceType;
-const resourceSize=record._resourceSize;
+const mimeType=record.mimeType;
+const resourceType=record.resourceType||NetworkRequest.TYPES.Other;
+const resourceSize=record.resourceSize;
const isBinaryResource=mimeType&&binaryMimeTypes.some(type=>mimeType.startsWith(type));
-const isTextBasedResource=!isBinaryResource&&resourceType&&resourceType.isTextType();
+const isTextResource=!isBinaryResource&&textResourceTypes.includes(resourceType);
const isChromeExtensionResource=record.url.startsWith(CHROME_EXTENSION_PROTOCOL);
-if(!isTextBasedResource||!resourceSize||!record.finished||
+if(!isTextResource||!resourceSize||!record.finished||
isChromeExtensionResource||!record.transferSize||record.statusCode===304){
return;
}
-const isContentEncoded=(record._responseHeaders||[]).find(header=>
+const isContentEncoded=(record.responseHeaders||[]).find(header=>
compressionHeaders.includes(header.name.toLowerCase())&&
compressionTypes.includes(header.value));
@@ -10360,6 +10289,16 @@ record.gzipSize=Buffer.byteLength(res,'utf8');
resolve(record);
});
});
+}).catch(err=>{
+
+Sentry.captureException(err,{
+tags:{gatherer:'ResponseCompression'},
+extra:{url:URL.elideDataURI(record.url)},
+level:'warning'});
+
+
+record.gzipSize=undefined;
+return record;
});
}));
}}
@@ -10368,7 +10307,7 @@ resolve(record);
module.exports=ResponseCompression;
}).call(this,require("buffer").Buffer);
-},{"../gatherer":19,"buffer":60,"zlib":57}],"../gather/gatherers/dobetterweb/tags-blocking-first-paint":[function(require,module,exports){
+},{"../../../lib/network-request":38,"../../../lib/sentry":40,"../../../lib/url-shim":"url","../gatherer":19,"buffer":60,"zlib":57}],"../gather/gatherers/dobetterweb/tags-blocking-first-paint":[function(require,module,exports){
@@ -10475,21 +10414,21 @@ if(!record.finished){
return prev;
}
-const isParserGenerated=record._initiator.type==='parser';
+const isParserGenerated=record.initiator.type==='parser';
-const isParserScriptOrStyle=/(css|script)/.test(record._mimeType)&&isParserGenerated;
+const isParserScriptOrStyle=/(css|script)/.test(record.mimeType)&&isParserGenerated;
const isFailedRequest=record._failed;
-const isHtml=record._mimeType&&record._mimeType.includes('html');
+const isHtml=record.mimeType&&record.mimeType.includes('html');
if(isHtml||isParserScriptOrStyle||isFailedRequest&&isParserGenerated){
-prev[record._url]={
-isLinkPreload:record.isLinkPreload,
-transferSize:record._transferSize,
-startTime:record._startTime,
-endTime:record._endTime};
+prev[record.url]={
+isLinkPreload:!!record.isLinkPreload,
+transferSize:record.transferSize,
+startTime:record.startTime,
+endTime:record.endTime};
}
@@ -10504,7 +10443,7 @@ return prev;
static findBlockingTags(driver,networkRecords){
const scriptSrc=`(${collectTagsThatBlockFirstPaint.toString()}())`;
const firstRequestEndTime=networkRecords.reduce(
-(min,record)=>Math.min(min,record._endTime),
+(min,record)=>Math.min(min,record.endTime),
Infinity);
return driver.evaluateAsync(scriptSrc).then(tags=>{
@@ -10545,7 +10484,7 @@ return prev;
beforePass(passContext){
-return passContext.driver.evaluteScriptOnNewDocument(`(${installMediaListener.toString()})()`);
+return passContext.driver.evaluateScriptOnNewDocument(`(${installMediaListener.toString()})()`);
}
@@ -10741,11 +10680,24 @@ const newNode=oldNode.cloneNode(true);
return new Promise(resolve=>{
newNode.addEventListener('load',function onload(){
newNode.removeEventListener('load',onload);
-resolve(getFontFaceFromStylesheets());
+try{
+const stylesheet=Array.from(document.styleSheets).find(s=>s.ownerNode===newNode);
+if(stylesheet){
+const cssStylesheet=stylesheet;
+resolve(getSheetsFontFaces(cssStylesheet));
+}else{
+resolve([{err:{message:'Could not load stylesheet with CORS'}}]);
+}
+}catch(err){
+resolve([{err:{message:err.message,stack:err.stack}}]);
+}
});
newNode.crossOrigin='anonymous';
oldNode.parentNode&&oldNode.parentNode.insertBefore(newNode,oldNode);
oldNode.remove();
+
+
+setTimeout(()=>resolve([{err:{message:'Could not load stylesheet (timeout)'}}]),5000);
});
}
@@ -10755,21 +10707,30 @@ const data=[];
const corsDataPromises=[];
for(const stylesheet of Array.from(document.styleSheets)){
-try{
const cssStylesheet=stylesheet;
-if(cssStylesheet.cssRules===null&&cssStylesheet.href&&cssStylesheet.ownerNode&&
+try{
+
+if(!cssStylesheet.cssRules){
+throw new Error('Failed to read cssRules');
+}
+
+data.push(...getSheetsFontFaces(cssStylesheet));
+}catch(err){
+const failedToReadRules=/Failed to read.*cssRules/.test(err.message);
+
+const alreadyCORS=!cssStylesheet.ownerNode||!!cssStylesheet.ownerNode.crossOrigin;
+
+if(failedToReadRules&&!alreadyCORS&&cssStylesheet.href){
-!cssStylesheet.ownerNode.crossOrigin){
const ownerLinkEl=cssStylesheet.ownerNode;
corsDataPromises.push(loadStylesheetWithCORS(ownerLinkEl));
}else{
-data.push(...getSheetsFontFaces(cssStylesheet));
-}
-}catch(err){
+
data.push({err:{message:err.message,stack:err.stack}});
}
}
+}
return Promise.all(corsDataPromises).then(corsFontFaces=>data.concat(...corsFontFaces));
}
@@ -10811,7 +10772,7 @@ fontOrError=>{
const dataError=fontOrError;
if(dataError.err){
const err=new Error(dataError.err.message);
-err.stack=dataError.err.stack;
+err.stack=dataError.err.stack||err.stack;
Sentry.captureException(err,{tags:{gatherer:'Fonts'},level:'warning'});
return false;
@@ -10831,7 +10792,7 @@ return loadedFont;
module.exports=Fonts;
-},{"../../lib/sentry":39,"./gatherer":19}],"../gather/gatherers/html-without-javascript":[function(require,module,exports){
+},{"../../lib/sentry":40,"./gatherer":19}],"../gather/gatherers/html-without-javascript":[function(require,module,exports){
@@ -10852,7 +10813,10 @@ const Gatherer=require('./gatherer');
function getBodyText(){
const body=document.querySelector('body');
-return Promise.resolve(body?body.innerText:'');
+return Promise.resolve({
+bodyText:body?body.innerText:'',
+hasNoScript:!!document.querySelector('noscript')});
+
}
class HTMLWithoutJavaScript extends Gatherer{
@@ -10871,13 +10835,15 @@ async afterPass(passContext){
passContext.disableJavaScript=false;
-const bodyText=await passContext.driver.evaluateAsync(`(${getBodyText.toString()}())`);
+const expression=`(${getBodyText.toString()}())`;
+const{bodyText,hasNoScript}=await passContext.driver.evaluateAsync(expression);
if(typeof bodyText!=='string'){
throw new Error('document body innerText returned by protocol was not a string');
}
return{
-value:bodyText};
+bodyText,
+hasNoScript};
}}
@@ -11080,14 +11046,14 @@ return Object.assign(element,{naturalWidth:0,naturalHeight:0});
async afterPass(passContext,loadData){
const driver=passContext.driver;
const indexedNetworkRecords=loadData.networkRecords.reduce((map,record)=>{
-if(/^image/.test(record._mimeType)&&record.finished){
-map[record._url]={
+if(/^image/.test(record.mimeType)&&record.finished){
+map[record.url]={
url:record.url,
-resourceSize:Math.min(record._resourceSize||0,record.transferSize),
+resourceSize:Math.min(record.resourceSize||0,record.transferSize),
startTime:record.startTime,
endTime:record.endTime,
-responseReceivedTime:record._responseReceivedTime,
-mimeType:record._mimeType};
+responseReceivedTime:record.responseReceivedTime,
+mimeType:record.mimeType};
}
@@ -11361,8 +11327,8 @@ return passContext.driver.goOffline();
afterPass(passContext,loadData){
const navigationRecord=loadData.networkRecords.filter(record=>{
-return URL.equalWithExcludedFragments(record._url,passContext.url)&&
-record._fetchedViaServiceWorker;
+return URL.equalWithExcludedFragments(record.url,passContext.url)&&
+record.fetchedViaServiceWorker;
}).pop();
return passContext.driver.goOnline(passContext).
@@ -11431,7 +11397,7 @@ module.exports=RuntimeExceptions;
'use strict';
const Gatherer=require('./gatherer');
-const WebInspector=require('../../lib/web-inspector');
+const NetworkRequest=require('../../lib/network-request');
@@ -11448,7 +11414,7 @@ const driver=passContext.driver;
const scriptContentMap={};
const scriptRecords=loadData.networkRecords.
-filter(record=>record._resourceType===WebInspector.resourceTypes.Script);
+filter(record=>record.resourceType===NetworkRequest.TYPES.Script);
for(const record of scriptRecords){
try{
@@ -11465,7 +11431,7 @@ return scriptContentMap;
module.exports=Scripts;
-},{"../../lib/web-inspector":47,"./gatherer":19}],"../gather/gatherers/seo/canonical":[function(require,module,exports){
+},{"../../lib/network-request":38,"./gatherer":19}],"../gather/gatherers/seo/canonical":[function(require,module,exports){
@@ -11823,7 +11789,7 @@ module.exports=FontSize;
}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{});
-},{"../../../lib/sentry.js":39,"../../../lib/web-inspector":47,"../../driver.js":17,"../gatherer":19}],"../gather/gatherers/seo/hreflang":[function(require,module,exports){
+},{"../../../lib/sentry.js":40,"../../../lib/web-inspector":47,"../../driver.js":17,"../gatherer":19}],"../gather/gatherers/seo/hreflang":[function(require,module,exports){
@@ -12196,7 +12162,7 @@ module.exports=Viewport;
'use strict';
const ComputedArtifact=require('./computed-artifact');
-const WebInspector=require('../../lib/web-inspector');
+const NetworkRequest=require('../../lib/network-request');
const assert=require('assert');
class CriticalRequestChains extends ComputedArtifact{
@@ -12216,29 +12182,29 @@ static isCritical(request,mainResource){
assert.ok(mainResource,'mainResource not provided');
-if(request._isLinkPreload){
+if(request.isLinkPreload){
return false;
}
-const resourceTypeCategory=request._resourceType&&request._resourceType._category;
-
-const isIframe=request._resourceType===WebInspector.resourceTypes.Document&&
-request._frameId!==mainResource._frameId;
+const isIframe=request.resourceType===NetworkRequest.TYPES.Document&&
+request.frameId!==mainResource.frameId;
const nonCriticalResourceTypes=[
-WebInspector.resourceTypes.Image._category,
-WebInspector.resourceTypes.XHR._category];
+NetworkRequest.TYPES.Image,
+NetworkRequest.TYPES.XHR,
+NetworkRequest.TYPES.Fetch,
+NetworkRequest.TYPES.EventSource];
-if(nonCriticalResourceTypes.includes(resourceTypeCategory)||
+if(nonCriticalResourceTypes.includes(request.resourceType||'Other')||
isIframe||
-request._mimeType&&request._mimeType.startsWith('image/')){
+request.mimeType&&request.mimeType.startsWith('image/')){
return false;
}
-return['VeryHigh','High','Medium'].includes(request.priority());
+return['VeryHigh','High','Medium'].includes(request.priority);
}
@@ -12270,7 +12236,7 @@ for(const request of criticalRequests){
const ancestors=[];
-let ancestorRequest=request.initiatorRequest();
+let ancestorRequest=request.initiatorRequest;
let node=criticalRequestChains;
while(ancestorRequest){
@@ -12288,7 +12254,7 @@ node=undefined;
break;
}
ancestors.push(ancestorRequest.requestId);
-ancestorRequest=ancestorRequest.initiatorRequest();
+ancestorRequest=ancestorRequest.initiatorRequest;
}
@@ -12349,34 +12315,7 @@ return CriticalRequestChains.extractChain(networkRecords,mainResource);
module.exports=CriticalRequestChains;
-},{"../../lib/web-inspector":47,"./computed-artifact":11,"assert":53}],"./gather/computed/dtm-model":[function(require,module,exports){
-
-
-
-
-
-'use strict';
-
-const ComputedArtifact=require('./computed-artifact');
-const DTM=require('../../lib/traces/devtools-timeline-model');
-
-class DevtoolsTimelineModel extends ComputedArtifact{
-get name(){
-return'DevtoolsTimelineModel';
-}
-
-
-
-
-
-async compute_(trace){
-return new DTM(trace);
-}}
-
-
-module.exports=DevtoolsTimelineModel;
-
-},{"../../lib/traces/devtools-timeline-model":43,"./computed-artifact":11}],"./gather/computed/load-simulator":[function(require,module,exports){
+},{"../../lib/network-request":38,"./computed-artifact":11,"assert":53}],"./gather/computed/load-simulator":[function(require,module,exports){
@@ -12453,6 +12392,7 @@ module.exports=LoadSimulatorArtifact;
'use strict';
const ComputedArtifact=require('./computed-artifact');
+const URL=require('../../lib/url-shim');
@@ -12468,24 +12408,267 @@ return'MainResource';
-compute_(data,artifacts){
-const{URL,devtoolsLog}=data;
-return artifacts.requestNetworkRecords(devtoolsLog).
-then(requests=>{
-const mainResource=requests.find(request=>request.url===URL.finalUrl);
+async compute_(data,artifacts){
+const finalUrl=data.URL.finalUrl;
+const requests=await artifacts.requestNetworkRecords(data.devtoolsLog);
+
+const mainResource=requests.find(request=>finalUrl.startsWith(request.url)&&
+URL.equalWithExcludedFragments(request.url,finalUrl));
if(!mainResource){
throw new Error('Unable to identify the main resource');
}
return mainResource;
-});
}}
module.exports=MainResource;
-},{"./computed-artifact":11}],"./gather/computed/manifest-values":[function(require,module,exports){
+},{"../../lib/url-shim":"url","./computed-artifact":11}],"./gather/computed/main-thread-tasks":[function(require,module,exports){
+
+
+
+
+
+'use strict';
+
+const ComputedArtifact=require('./computed-artifact');
+const{taskGroups,taskNameToGroup}=require('../../lib/task-groups');
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+class MainThreadTasks extends ComputedArtifact{
+get name(){
+return'MainThreadTasks';
+}
+
+
+
+
+
+
+static _createNewTaskNode(event,parent){
+const newTask={
+event,
+startTime:event.ts,
+endTime:event.ph==='X'?event.ts+Number(event.dur||0):NaN,
+parent:parent,
+children:[],
+
+
+attributableURLs:[],
+group:taskGroups.other,
+duration:NaN,
+selfTime:NaN};
+
+
+if(parent){
+parent.children.push(newTask);
+}
+
+return newTask;
+}
+
+
+
+
+
+static _createTasksFromEvents(mainThreadEvents){
+
+const tasks=[];
+
+let currentTask;
+
+for(const event of mainThreadEvents){
+
+if(event.ph!=='X'&&event.ph!=='B'&&event.ph!=='E')continue;
+
+
+
+while(
+currentTask&&
+Number.isFinite(currentTask.endTime)&&
+currentTask.endTime<=event.ts)
+{
+currentTask=currentTask.parent;
+}
+
+
+if(!currentTask){
+
+if(event.ph==='E'){
+throw new Error('Fatal trace logic error');
+}
+
+currentTask=MainThreadTasks._createNewTaskNode(event);
+tasks.push(currentTask);
+
+continue;
+}
+
+if(event.ph==='X'||event.ph==='B'){
+
+const newTask=MainThreadTasks._createNewTaskNode(event,currentTask);
+tasks.push(newTask);
+currentTask=newTask;
+}else{
+if(currentTask.event.ph!=='B'){
+throw new Error('Fatal trace logic error');
+}
+
+
+currentTask.endTime=event.ts;
+currentTask=currentTask.parent;
+}
+}
+
+return tasks;
+}
+
+
+
+
+
+static _computeRecursiveSelfTime(task){
+const childTime=task.children.
+map(MainThreadTasks._computeRecursiveSelfTime).
+reduce((sum,child)=>sum+child,0);
+task.duration=task.endTime-task.startTime;
+task.selfTime=task.duration-childTime;
+return task.duration;
+}
+
+
+
+
+
+static _computeRecursiveAttributableURLs(task,parentURLs){
+const argsData=task.event.args.data||{};
+const stackFrameURLs=(argsData.stackTrace||[]).map(entry=>entry.url);
+
+let taskURLs=[];
+switch(task.event.name){
+
+
+
+
+
+case'v8.compile':
+case'EvaluateScript':
+case'FunctionCall':
+taskURLs=[argsData.url].concat(stackFrameURLs);
+break;
+case'v8.compileModule':
+taskURLs=[task.event.args.fileName].concat(stackFrameURLs);
+break;
+default:
+taskURLs=stackFrameURLs;
+break;}
+
+
+
+const attributableURLs=Array.from(parentURLs);
+for(const url of taskURLs){
+
+if(!url)continue;
+
+if(attributableURLs[attributableURLs.length-1]===url)continue;
+attributableURLs.push(url);
+}
+
+task.attributableURLs=attributableURLs;
+task.children.forEach(child=>
+MainThreadTasks._computeRecursiveAttributableURLs(child,attributableURLs));
+}
+
+
+
+
+
+static _computeRecursiveTaskGroup(task,parentGroup){
+const group=taskNameToGroup[task.event.name];
+task.group=group||parentGroup||taskGroups.other;
+task.children.forEach(child=>MainThreadTasks._computeRecursiveTaskGroup(child,task.group));
+}
+
+
+
+
+
+static getMainThreadTasks(traceEvents){
+const tasks=MainThreadTasks._createTasksFromEvents(traceEvents);
+
+
+for(const task of tasks){
+if(task.parent)continue;
+
+MainThreadTasks._computeRecursiveSelfTime(task);
+MainThreadTasks._computeRecursiveAttributableURLs(task,[]);
+MainThreadTasks._computeRecursiveTaskGroup(task);
+}
+
+
+const firstTs=(tasks[0]||{startTime:0}).startTime;
+for(const task of tasks){
+task.startTime=(task.startTime-firstTs)/1000;
+task.endTime=(task.endTime-firstTs)/1000;
+task.duration/=1000;
+task.selfTime/=1000;
+
+
+if(!Number.isFinite(task.selfTime)){
+throw new Error('Invalid task timing data');
+}
+}
+
+return tasks;
+}
+
+
+
+
+
+
+async compute_(trace,artifacts){
+const{mainThreadEvents}=await artifacts.requestTraceOfTab(trace);
+return MainThreadTasks.getMainThreadTasks(mainThreadEvents);
+}}
+
+
+module.exports=MainThreadTasks;
+
+},{"../../lib/task-groups":43,"./computed-artifact":11}],"./gather/computed/manifest-values":[function(require,module,exports){
@@ -12557,7 +12740,9 @@ validate:manifestValue=>!!manifestValue.short_name.value},
{
id:'shortNameLength',
-failureText:'Manifest `short_name` will be truncated when displayed on the homescreen',
+failureText:`Manifest's \`short_name\` is too long (>${SUGGESTED_SHORTNAME_LENGTH} `+
+`characters) to be displayed on a homescreen without truncation`,
+
validate:manifestValue=>!!manifestValue.short_name.value&&
manifestValue.short_name.value.length<=SUGGESTED_SHORTNAME_LENGTH},
@@ -12613,7 +12798,7 @@ allChecks:remainingChecks};
module.exports=ManifestValues;
-},{"../../lib/icons":35,"./computed-artifact":11}],"./gather/computed/metrics/estimated-input-latency":[function(require,module,exports){
+},{"../../lib/icons":34,"./computed-artifact":11}],"./gather/computed/metrics/estimated-input-latency":[function(require,module,exports){
@@ -13156,9 +13341,11 @@ module.exports=Interactive;
'use strict';
const LanternMetricArtifact=require('./lantern-metric');
-const Node=require('../../../lib/dependency-graph/node');
+const BaseNode=require('../../../lib/dependency-graph/base-node');
const EstimatedInputLatency=require('./estimated-input-latency');
+
+
class LanternEstimatedInputLatency extends LanternMetricArtifact{
get name(){
return'LanternEstimatedInputLatency';
@@ -13232,14 +13419,13 @@ static getEventsAfterFMP(nodeTimings,fmpTimeInMs){
const events=[];
for(const[node,timing]of nodeTimings.entries()){
-if(node.type!==Node.TYPES.CPU)continue;
-if(!timing.endTime||!timing.startTime)continue;
+if(node.type!==BaseNode.TYPES.CPU)continue;
if(timing.endTime<fmpTimeInMs)continue;
events.push({
start:timing.startTime,
end:timing.endTime,
-duration:timing.endTime-timing.startTime});
+duration:timing.duration});
}
@@ -13249,7 +13435,7 @@ return events;
module.exports=LanternEstimatedInputLatency;
-},{"../../../lib/dependency-graph/node":25,"./estimated-input-latency":"./gather/computed/metrics/estimated-input-latency","./lantern-metric":12}],"./gather/computed/metrics/lantern-first-contentful-paint":[function(require,module,exports){
+},{"../../../lib/dependency-graph/base-node":22,"./estimated-input-latency":"./gather/computed/metrics/estimated-input-latency","./lantern-metric":12}],"./gather/computed/metrics/lantern-first-contentful-paint":[function(require,module,exports){
@@ -13258,9 +13444,9 @@ module.exports=LanternEstimatedInputLatency;
'use strict';
const MetricArtifact=require('./lantern-metric');
-const Node=require('../../../lib/dependency-graph/node');
-const CPUNode=require('../../../lib/dependency-graph/cpu-node');
-const NetworkNode=require('../../../lib/dependency-graph/network-node');
+const BaseNode=require('../../../lib/dependency-graph/base-node');
+
+
class FirstContentfulPaint extends MetricArtifact{
get name(){
@@ -13272,8 +13458,8 @@ return'LanternFirstContentfulPaint';
get COEFFICIENTS(){
return{
-intercept:600,
-optimistic:0.6,
+intercept:0,
+optimistic:0.5,
pessimistic:0.5};
}
@@ -13294,13 +13480,12 @@ node.endTime<=fcp&&node.hasRenderBlockingPriority()&&node.initiatorType!=='scrip
return dependencyGraph.cloneWithRelationships(node=>{
if(node.endTime>fcp&&!node.isMainDocument())return false;
-if(node.type===Node.TYPES.CPU){
+if(node.type===BaseNode.TYPES.CPU){
return node.isEvaluateScriptFor(blockingScriptUrls);
}
-const asNetworkNode=node;
-return asNetworkNode.hasRenderBlockingPriority()&&asNetworkNode.initiatorType!=='script';
+return node.hasRenderBlockingPriority()&&node.initiatorType!=='script';
});
}
@@ -13318,7 +13503,7 @@ return node.endTime<=fcp&&node.hasRenderBlockingPriority();
return dependencyGraph.cloneWithRelationships(node=>{
if(node.endTime>fcp&&!node.isMainDocument())return false;
-if(node.type===Node.TYPES.CPU){
+if(node.type===BaseNode.TYPES.CPU){
return node.isEvaluateScriptFor(blockingScriptUrls);
}
@@ -13330,7 +13515,7 @@ return node.hasRenderBlockingPriority();
module.exports=FirstContentfulPaint;
-},{"../../../lib/dependency-graph/cpu-node":23,"../../../lib/dependency-graph/network-node":24,"../../../lib/dependency-graph/node":25,"./lantern-metric":12}],"./gather/computed/metrics/lantern-first-cpu-idle":[function(require,module,exports){
+},{"../../../lib/dependency-graph/base-node":22,"./lantern-metric":12}],"./gather/computed/metrics/lantern-first-cpu-idle":[function(require,module,exports){
@@ -13338,10 +13523,7 @@ module.exports=FirstContentfulPaint;
'use strict';
-const Node=require('../../../lib/dependency-graph/node');
-const CPUNode=require('../../../lib/dependency-graph/cpu-node');
-const NetworkNode=require('../../../lib/dependency-graph/network-node');
-
+const BaseNode=require('../../../lib/dependency-graph/base-node');
const FirstCPUIdle=require('./first-cpu-idle');
const LanternInteractive=require('./lantern-interactive');
@@ -13353,6 +13535,18 @@ return'LanternFirstCPUIdle';
+get COEFFICIENTS(){
+return{
+intercept:0,
+optimistic:1,
+pessimistic:0};
+
+}
+
+
+
+
+
getEstimateFromSimulation(simulation,extras){
@@ -13375,9 +13569,8 @@ static getFirstCPUIdleWindowStart(nodeTimings,fmpTimeInMs,longTaskLength=50){
const longTasks=[];
for(const[node,timing]of nodeTimings.entries()){
-if(node.type!==Node.TYPES.CPU)continue;
-if(!timing.endTime||!timing.startTime)continue;
-if(timing.endTime-timing.startTime<longTaskLength)continue;
+if(node.type!==BaseNode.TYPES.CPU)continue;
+if(timing.duration<longTaskLength)continue;
longTasks.push({start:timing.startTime,end:timing.endTime});
}
@@ -13387,7 +13580,7 @@ return FirstCPUIdle.findQuietWindow(fmpTimeInMs,Infinity,longTasks);
module.exports=LanternFirstCPUIdle;
-},{"../../../lib/dependency-graph/cpu-node":23,"../../../lib/dependency-graph/network-node":24,"../../../lib/dependency-graph/node":25,"./first-cpu-idle":"./gather/computed/metrics/first-cpu-idle","./lantern-interactive":"./gather/computed/metrics/lantern-interactive"}],"./gather/computed/metrics/lantern-first-meaningful-paint":[function(require,module,exports){
+},{"../../../lib/dependency-graph/base-node":22,"./first-cpu-idle":"./gather/computed/metrics/first-cpu-idle","./lantern-interactive":"./gather/computed/metrics/lantern-interactive"}],"./gather/computed/metrics/lantern-first-meaningful-paint":[function(require,module,exports){
@@ -13396,9 +13589,9 @@ module.exports=LanternFirstCPUIdle;
'use strict';
const MetricArtifact=require('./lantern-metric');
-const Node=require('../../../lib/dependency-graph/node');
-const CPUNode=require('../../../lib/dependency-graph/cpu-node');
-const NetworkNode=require('../../../lib/dependency-graph/network-node');
+const BaseNode=require('../../../lib/dependency-graph/base-node');
+
+
class FirstMeaningfulPaint extends MetricArtifact{
get name(){
@@ -13410,9 +13603,9 @@ return'LanternFirstMeaningfulPaint';
get COEFFICIENTS(){
return{
-intercept:900,
-optimistic:0.45,
-pessimistic:0.6};
+intercept:0,
+optimistic:0.5,
+pessimistic:0.5};
}
@@ -13432,13 +13625,12 @@ node.endTime<=fmp&&node.hasRenderBlockingPriority()&&node.initiatorType!=='scrip
return dependencyGraph.cloneWithRelationships(node=>{
if(node.endTime>fmp&&!node.isMainDocument())return false;
-if(node.type===Node.TYPES.CPU){
+if(node.type===BaseNode.TYPES.CPU){
return node.isEvaluateScriptFor(blockingScriptUrls);
}
-const asNetworkNode=node;
-return asNetworkNode.hasRenderBlockingPriority()&&asNetworkNode.initiatorType!=='script';
+return node.hasRenderBlockingPriority()&&node.initiatorType!=='script';
});
}
@@ -13457,9 +13649,8 @@ return dependencyGraph.cloneWithRelationships(node=>{
if(node.endTime>fmp&&!node.isMainDocument())return false;
-if(node.type===Node.TYPES.CPU){
-const asCpuNode=node;
-return asCpuNode.didPerformLayout()||asCpuNode.isEvaluateScriptFor(requiredScriptUrls);
+if(node.type===BaseNode.TYPES.CPU){
+return node.didPerformLayout()||node.isEvaluateScriptFor(requiredScriptUrls);
}
@@ -13482,7 +13673,7 @@ return metricResult;
module.exports=FirstMeaningfulPaint;
-},{"../../../lib/dependency-graph/cpu-node":23,"../../../lib/dependency-graph/network-node":24,"../../../lib/dependency-graph/node":25,"./lantern-metric":12}],"./gather/computed/metrics/lantern-interactive":[function(require,module,exports){
+},{"../../../lib/dependency-graph/base-node":22,"./lantern-metric":12}],"./gather/computed/metrics/lantern-interactive":[function(require,module,exports){
@@ -13491,10 +13682,10 @@ module.exports=FirstMeaningfulPaint;
'use strict';
const MetricArtifact=require('./lantern-metric');
-const Node=require('../../../lib/dependency-graph/node');
-const CPUNode=require('../../../lib/dependency-graph/cpu-node');
-const NetworkNode=require('../../../lib/dependency-graph/network-node');
-const WebInspector=require('../../../lib/web-inspector');
+const BaseNode=require('../../../lib/dependency-graph/base-node');
+const NetworkRequest=require('../../../lib/network-request');
+
+
const CRITICAL_LONG_TASK_THRESHOLD=20;
@@ -13509,9 +13700,9 @@ return'LanternInteractive';
get COEFFICIENTS(){
return{
-intercept:1600,
-optimistic:0.6,
-pessimistic:0.45};
+intercept:0,
+optimistic:0.5,
+pessimistic:0.5};
}
@@ -13525,19 +13716,18 @@ const minimumCpuTaskDuration=CRITICAL_LONG_TASK_THRESHOLD*1000;
return dependencyGraph.cloneWithRelationships(node=>{
-if(node.type===Node.TYPES.CPU){
+if(node.type===BaseNode.TYPES.CPU){
return node.event.dur>minimumCpuTaskDuration;
}
-const asNetworkNode=node;
-const isImage=asNetworkNode.record._resourceType===WebInspector.resourceTypes.Image;
-const isScript=asNetworkNode.record._resourceType===WebInspector.resourceTypes.Script;
+const isImage=node.record.resourceType===NetworkRequest.TYPES.Image;
+const isScript=node.record.resourceType===NetworkRequest.TYPES.Script;
return(
!isImage&&(
isScript||
-asNetworkNode.record.priority()==='High'||
-asNetworkNode.record.priority()==='VeryHigh'));
+node.record.priority==='High'||
+node.record.priority==='VeryHigh'));
});
}
@@ -13586,9 +13776,8 @@ static getLastLongTaskEndTime(nodeTimings,duration=50){
return Array.from(nodeTimings.entries()).
filter(([node,timing])=>{
-if(node.type!==Node.TYPES.CPU)return false;
-if(!timing.endTime||!timing.startTime)return false;
-return timing.endTime-timing.startTime>duration;
+if(node.type!==BaseNode.TYPES.CPU)return false;
+return timing.duration>duration;
}).
map(([_,timing])=>timing.endTime).
reduce((max,x)=>Math.max(max||0,x||0),0);
@@ -13597,7 +13786,7 @@ reduce((max,x)=>Math.max(max||0,x||0),0);
module.exports=Interactive;
-},{"../../../lib/dependency-graph/cpu-node":23,"../../../lib/dependency-graph/network-node":24,"../../../lib/dependency-graph/node":25,"../../../lib/web-inspector":47,"./lantern-metric":12}],"./gather/computed/metrics/lantern-speed-index":[function(require,module,exports){
+},{"../../../lib/dependency-graph/base-node":22,"../../../lib/network-request":38,"./lantern-metric":12}],"./gather/computed/metrics/lantern-speed-index":[function(require,module,exports){
@@ -13606,8 +13795,9 @@ module.exports=Interactive;
'use strict';
const MetricArtifact=require('./lantern-metric');
-const Node=require('../../../lib/dependency-graph/node');
-const CPUNode=require('../../../lib/dependency-graph/cpu-node');
+const BaseNode=require('../../../lib/dependency-graph/base-node');
+
+
class SpeedIndex extends MetricArtifact{
get name(){
@@ -13695,11 +13885,9 @@ static computeLayoutBasedSpeedIndex(nodeTimings,fcpTimeInMs){
const layoutWeights=[];
for(const[node,timing]of nodeTimings.entries()){
-if(node.type!==Node.TYPES.CPU)continue;
-if(!timing.startTime||!timing.endTime)continue;
+if(node.type!==BaseNode.TYPES.CPU)continue;
-const cpuNode=node;
-if(cpuNode.childEvents.some(x=>x.name==='Layout')){
+if(node.childEvents.some(x=>x.name==='Layout')){
const timingWeight=Math.max(Math.log2(timing.endTime-timing.startTime),0);
layoutWeights.push({time:timing.endTime,weight:timingWeight});
}
@@ -13719,7 +13907,7 @@ return totalWeightedTime/totalWeight;
module.exports=SpeedIndex;
-},{"../../../lib/dependency-graph/cpu-node":23,"../../../lib/dependency-graph/node":25,"./lantern-metric":12}],"./gather/computed/metrics/speed-index":[function(require,module,exports){
+},{"../../../lib/dependency-graph/base-node":22,"./lantern-metric":12}],"./gather/computed/metrics/speed-index":[function(require,module,exports){
@@ -13876,7 +14064,7 @@ return boundaries;
}
totalBytes+=record.transferSize;
-boundaries.push({time:record._responseReceivedTime,isStart:true});
+boundaries.push({time:record.responseReceivedTime,isStart:true});
boundaries.push({time:record.endTime,isStart:false});
return boundaries;
},[]).sort((a,b)=>a.time-b.time);
@@ -13932,9 +14120,9 @@ const NetworkNode=require('../../lib/dependency-graph/network-node');
const CPUNode=require('../../lib/dependency-graph/cpu-node');
const NetworkAnalyzer=require('../../lib/dependency-graph/simulator/network-analyzer');
const TracingProcessor=require('../../lib/traces/tracing-processor');
-const WebInspector=require('../../lib/web-inspector');
+const NetworkRequest=require('../../lib/network-request');
+
-const Node=require('../../lib/dependency-graph/node.js');
const MINIMUM_TASK_DURATION_OF_INTEREST=10;
@@ -13952,10 +14140,10 @@ return'PageDependencyGraph';
static getNetworkInitiators(record){
-if(!record._initiator)return[];
-if(record._initiator.url)return[record._initiator.url];
-if(record._initiator.type==='script'&&record._initiator.stack){
-const frames=record._initiator.stack.callFrames;
+if(!record.initiator)return[];
+if(record.initiator.url)return[record.initiator.url];
+if(record.initiator.type==='script'&&record.initiator.stack){
+const frames=record.initiator.stack.callFrames;
return Array.from(new Set(frames.map(frame=>frame.url))).filter(Boolean);
}
@@ -13973,12 +14161,14 @@ const idToNodeMap=new Map();
const urlToNodeMap=new Map();
networkRecords.forEach(record=>{
-if(IGNORED_MIME_TYPES_REGEX.test(record._mimeType))return;
+if(IGNORED_MIME_TYPES_REGEX.test(record.mimeType))return;
+
+
while(idToNodeMap.has(record.requestId)){
-record._requestId+=':duplicate';
+record.requestId+=':duplicate';
}
const node=new NetworkNode(record);
@@ -14077,7 +14267,7 @@ function addDependentNetworkRequest(cpuNode,reqId){
const networkNode=networkNodeOutput.idToNodeMap.get(reqId);
if(!networkNode||
-networkNode.record._resourceType!==WebInspector.resourceTypes.XHR||
+networkNode.record.resourceType!==NetworkRequest.TYPES.XHR||
networkNode.startTime<=cpuNode.startTime)return;
@@ -14236,7 +14426,7 @@ const length=Math.ceil((node.endTime-node.startTime)/timePerCharacter);
const bar=padRight('',offset)+padRight('',length,'=');
-const displayName=node.record?node.record._url:node.type;
+const displayName=node.record?node.record.url:node.type;
console.log(padRight(bar,widthInCharacters),`| ${displayName.slice(0,30)}`);
});
@@ -14268,7 +14458,7 @@ module.exports=PageDependencyGraphArtifact;
-},{"../../lib/dependency-graph/cpu-node":23,"../../lib/dependency-graph/network-node":24,"../../lib/dependency-graph/node.js":25,"../../lib/dependency-graph/simulator/network-analyzer":27,"../../lib/traces/tracing-processor":46,"../../lib/web-inspector":47,"./computed-artifact":11}],"./gather/computed/pushed-requests":[function(require,module,exports){
+},{"../../lib/dependency-graph/cpu-node":23,"../../lib/dependency-graph/network-node":24,"../../lib/dependency-graph/simulator/network-analyzer":27,"../../lib/network-request":38,"../../lib/traces/tracing-processor":46,"./computed-artifact":11}],"./gather/computed/pushed-requests":[function(require,module,exports){
@@ -14291,7 +14481,7 @@ return'PushedRequests';
compute_(devtoolsLog,artifacts){
return artifacts.requestNetworkRecords(devtoolsLog).then(records=>{
-const pushedRecords=records.filter(r=>r._timing&&!!r._timing.pushStart);
+const pushedRecords=records.filter(r=>r.timing&&!!r.timing.pushStart);
return pushedRecords;
});
}}
@@ -14309,6 +14499,8 @@ module.exports=PushedRequests;
const ComputedArtifact=require('./computed-artifact');
+const SCREENSHOT_TRACE_NAME='Screenshot';
+
class ScreenshotFilmstrip extends ComputedArtifact{
get name(){
return'Screenshots';
@@ -14318,29 +14510,14 @@ return'Screenshots';
-fetchScreenshot(frame){
-return frame.
-imageDataPromise().
-then(data=>'data:image/jpg;base64,'+data);
-}
-
-
-
-
-
-
-compute_(trace,computedArtifacts){
-return computedArtifacts.requestDevtoolsTimelineModel(trace).then(model=>{
-const filmStripFrames=model.filmStripModel().frames();
-const frameFetches=filmStripFrames.map(frame=>this.fetchScreenshot(frame));
-
-return Promise.all(frameFetches).then(images=>{
-const result=filmStripFrames.map((frame,i)=>({
-timestamp:frame.timestamp,
-datauri:images[i]}));
+async compute_(trace){
+return trace.traceEvents.
+filter(evt=>evt.name===SCREENSHOT_TRACE_NAME).
+map(evt=>{
+return{
+timestamp:evt.ts/1000,
+datauri:`data:image/jpg;base64,${evt.args.snapshot}`};
-return result;
-});
});
}}
@@ -14406,7 +14583,7 @@ return speedline;
module.exports=Speedline;
-},{"../../lib/errors":33,"./computed-artifact":11,"speedline":152}],"./gather/computed/trace-of-tab":[function(require,module,exports){
+},{"../../lib/errors":33,"./computed-artifact":11,"speedline":134}],"./gather/computed/trace-of-tab":[function(require,module,exports){
@@ -14427,13 +14604,14 @@ module.exports=Speedline;
const ComputedArtifact=require('./computed-artifact');
const log=require('lighthouse-logger');
+const TracingProcessor=require('../../lib/traces/tracing-processor');
const LHError=require('../../lib/errors');
const Sentry=require('../../lib/sentry');
-const WebInspector=require('../../lib/web-inspector');
+const NetworkRequest=require('../../lib/network-request');
class TraceOfTab extends ComputedArtifact{
get name(){
@@ -14444,28 +14622,50 @@ return'TraceOfTab';
+static filteredStableSort(traceEvents,filter){
+const indices=[];
+for(let srcIndex=0;srcIndex<traceEvents.length;srcIndex++){
+if(filter(traceEvents[srcIndex])){
+indices.push(srcIndex);
+}
+}
-async compute_(trace){
+
+indices.sort((indexA,indexB)=>{
+const result=traceEvents[indexA].ts-traceEvents[indexB].ts;
+return result?result:indexA-indexB;
+});
+
+
+const sorted=[];
+for(let i=0;i<indices.length;i++){
+sorted.push(traceEvents[indices[i]]);
+}
+
+return sorted;
+}
-const keyEvents=trace.traceEvents.
-filter(e=>{
+
+
+
+
+
+async compute_(trace){
+
+
+const keyEvents=TraceOfTab.filteredStableSort(trace.traceEvents,e=>{
return e.cat.includes('blink.user_timing')||
e.cat.includes('loading')||
e.cat.includes('devtools.timeline')||
-e.name==='TracingStartedInPage';
-}).
-
-stableSort((event0,event1)=>event0.ts-event1.ts);
+e.cat==='__metadata';
+});
+const{startedInPageEvt,frameId}=TracingProcessor.findTracingStartedEvt(keyEvents);
-const startedInPageEvt=keyEvents.find(e=>e.name==='TracingStartedInPage');
-if(!startedInPageEvt)throw new LHError(LHError.errors.NO_TRACING_STARTED);
-
-const frameId=startedInPageEvt.args.data.page;
const frameEvents=keyEvents.filter(e=>e.args.frame===frameId);
@@ -14513,11 +14713,8 @@ e=>e.name==='domContentLoadedEventEnd'&&e.ts>navigationStart.ts);
-
-const processEvents=trace.traceEvents.
-filter(e=>e.pid===startedInPageEvt.pid).
-
-stableSort((event0,event1)=>event0.ts-event1.ts);
+const processEvents=TraceOfTab.
+filteredStableSort(trace.traceEvents,e=>e.pid===startedInPageEvt.pid);
const mainThreadEvents=processEvents.
filter(e=>e.tid===startedInPageEvt.tid);
@@ -14566,7 +14763,7 @@ fmpFellBack};
module.exports=TraceOfTab;
-},{"../../lib/errors":33,"../../lib/sentry":39,"../../lib/web-inspector":47,"./computed-artifact":11,"lighthouse-logger":143}],1:[function(require,module,exports){
+},{"../../lib/errors":33,"../../lib/network-request":38,"../../lib/sentry":40,"../../lib/traces/tracing-processor":46,"./computed-artifact":11,"lighthouse-logger":125}],1:[function(require,module,exports){
@@ -14592,7 +14789,7 @@ static audit(artifacts){
const notApplicables=artifacts.Accessibility.notApplicable||[];
-const isNotApplicable=notApplicables.find(result=>result.id===this.meta.name);
+const isNotApplicable=notApplicables.find(result=>result.id===this.meta.id);
if(isNotApplicable){
return{
rawValue:true,
@@ -14601,7 +14798,9 @@ notApplicable:true};
}
const violations=artifacts.Accessibility.violations||[];
-const rule=violations.find(result=>result.id===this.meta.name);
+const rule=violations.find(result=>result.id===this.meta.id);
+const impact=rule&&rule.impact;
+const tags=rule&&rule.tags;
let items=[];
@@ -14611,7 +14810,8 @@ node:{
type:'node',
selector:Array.isArray(node.target)?node.target.join(' '):'',
path:node.path,
-snippet:node.snippet}}));
+snippet:node.html||node.snippet,
+explanation:node.failureSummary}}));
}
@@ -14625,7 +14825,7 @@ rawValue:typeof rule==='undefined',
extendedInfo:{
value:rule},
-details:Audit.makeTableDetails(headings,items)};
+details:{...Audit.makeTableDetails(headings,items),impact,tags}};
}}
@@ -14765,13 +14965,30 @@ summary};
+
+
+static makeOpportunityDetails(headings,items,overallSavingsMs,overallSavingsBytes){
+return{
+type:'opportunity',
+headings:items.length===0?[]:headings,
+items,
+overallSavingsMs,
+overallSavingsBytes};
+
+}
+
+
+
+
+
+
static _normalizeAuditScore(audit,result){
let score=result.score===undefined?Number(result.rawValue):result.score;
if(!Number.isFinite(score))throw new Error(`Invalid score: ${score}`);
-if(score>1)throw new Error(`Audit score for ${audit.meta.name} is > 1`);
-if(score<0)throw new Error(`Audit score for ${audit.meta.name} is < 0`);
+if(score>1)throw new Error(`Audit score for ${audit.meta.id} is > 1`);
+if(score<0)throw new Error(`Audit score for ${audit.meta.id} is < 0`);
score=clampTo2Decimals(score);
@@ -14806,10 +15023,10 @@ if(result.errorMessage){
scoreDisplayMode=Audit.SCORING_MODES.ERROR;
}
-let auditDescription=audit.meta.description;
-if(audit.meta.failureDescription){
+let auditTitle=audit.meta.title;
+if(audit.meta.failureTitle){
if(Number(score)<Util.PASS_THRESHOLD){
-auditDescription=audit.meta.failureDescription;
+auditTitle=audit.meta.failureTitle;
}
}
@@ -14819,9 +15036,9 @@ score=null;
}
return{
-id:audit.meta.name,
-title:auditDescription,
-description:audit.meta.helpText,
+id:audit.meta.id,
+title:auditTitle,
+description:audit.meta.description,
score,
scoreDisplayMode,
@@ -14839,7 +15056,7 @@ details:result.details};
module.exports=Audit;
-},{"../lib/statistics":40,"../report/html/renderer/util":48}],3:[function(require,module,exports){
+},{"../lib/statistics":41,"../report/html/renderer/util":48}],3:[function(require,module,exports){
@@ -14848,16 +15065,26 @@ module.exports=Audit;
'use strict';
const Audit=require('../audit');
+const linearInterpolation=require('../../lib/statistics').linearInterpolation;
const Interactive=require('../../gather/computed/metrics/lantern-interactive');
-const Simulator=require('../../lib/dependency-graph/simulator/simulator');
-const Node=require('../../lib/dependency-graph/node.js');
-const NetworkNode=require('../../lib/dependency-graph/network-node.js');
+
+
const KB_IN_BYTES=1024;
const WASTED_MS_FOR_AVERAGE=300;
const WASTED_MS_FOR_POOR=750;
+const WASTED_MS_FOR_SCORE_OF_ZERO=5000;
+
+
+
+
+
+
+
+
+
@@ -14868,11 +15095,21 @@ class UnusedBytes extends Audit{
+
+
static scoreForWastedMs(wastedMs){
-if(wastedMs===0)return 1;else
-if(wastedMs<WASTED_MS_FOR_AVERAGE)return 0.9;else
-if(wastedMs<WASTED_MS_FOR_POOR)return 0.65;else
-return 0;
+if(wastedMs===0){
+return 1;
+}else if(wastedMs<WASTED_MS_FOR_AVERAGE){
+return linearInterpolation(0,1,WASTED_MS_FOR_AVERAGE,0.75,wastedMs);
+}else if(wastedMs<WASTED_MS_FOR_POOR){
+return linearInterpolation(WASTED_MS_FOR_AVERAGE,0.75,WASTED_MS_FOR_POOR,0.5,wastedMs);
+}else{
+return Math.max(
+0,
+linearInterpolation(WASTED_MS_FOR_POOR,0.5,WASTED_MS_FOR_SCORE_OF_ZERO,0,wastedMs));
+
+}
}
@@ -14901,14 +15138,14 @@ if(!networkRecord){
return Math.round(totalBytes*compressionRatio);
-}else if(networkRecord._resourceType&&networkRecord._resourceType._name===resourceType){
+}else if(networkRecord.resourceType===resourceType){
-return networkRecord._transferSize||0;
+return networkRecord.transferSize||0;
}else{
-const transferSize=networkRecord._transferSize||0;
-const resourceSize=networkRecord._resourceSize;
+const transferSize=networkRecord.transferSize||0;
+const resourceSize=networkRecord.resourceSize;
const compressionRatio=resourceSize!==undefined?transferSize/resourceSize:1;
return Math.round(totalBytes*compressionRatio);
}
@@ -14953,9 +15190,11 @@ then(([result,graph,simulator])=>this.createAuditProduct(result,graph,simulator)
static computeWasteWithTTIGraph(results,graph,simulator,options){
-options=Object.assign({includeLoad:true},options);
+options=Object.assign({includeLoad:true,label:this.meta.id},options);
+const beforeLabel=`${options.label}-before`;
+const afterLabel=`${options.label}-after`;
-const simulationBeforeChanges=simulator.simulate(graph);
+const simulationBeforeChanges=simulator.simulate(graph,{label:beforeLabel});
const resultsByUrl=new Map();
for(const result of results){
@@ -14967,26 +15206,24 @@ resultsByUrl.set(result.url,result);
const originalTransferSizes=new Map();
graph.traverse(node=>{
if(node.type!=='network')return;
-const networkNode=node;
-const result=resultsByUrl.get(networkNode.record.url);
+const result=resultsByUrl.get(node.record.url);
if(!result)return;
-const original=networkNode.record.transferSize;
-originalTransferSizes.set(networkNode.record.requestId,original);
+const original=node.record.transferSize;
+originalTransferSizes.set(node.record.requestId,original);
const wastedBytes=result.wastedBytes;
-networkNode.record._transferSize=Math.max(original-wastedBytes,0);
+node.record.transferSize=Math.max(original-wastedBytes,0);
});
-const simulationAfterChanges=simulator.simulate(graph);
+const simulationAfterChanges=simulator.simulate(graph,{label:afterLabel});
graph.traverse(node=>{
if(node.type!=='network')return;
-const networkNode=node;
-const originalTransferSize=originalTransferSizes.get(networkNode.record.requestId);
+const originalTransferSize=originalTransferSizes.get(node.record.requestId);
if(originalTransferSize===undefined)return;
-networkNode.record._transferSize=originalTransferSize;
+node.record.transferSize=originalTransferSize;
});
const savingsOnOverallLoad=simulationBeforeChanges.timeInMs-simulationAfterChanges.timeInMs;
@@ -15007,7 +15244,7 @@ return Math.round(Math.max(savings,0)/10)*10;
static createAuditProduct(result,graph,simulator){
-const results=result.results.sort((itemA,itemB)=>itemB.wastedBytes-itemA.wastedBytes);
+const results=result.items.sort((itemA,itemB)=>itemB.wastedBytes-itemA.wastedBytes);
const wastedBytes=results.reduce((sum,item)=>sum+item.wastedBytes,0);
const wastedKb=Math.round(wastedBytes/KB_IN_BYTES);
@@ -15019,13 +15256,7 @@ if(typeof result.displayValue==='undefined'&&wastedKb){
displayValue=['Potential savings of %d\xa0KB',wastedKb];
}
-const summary={
-wastedMs,
-wastedBytes};
-
-
-
-const details=Audit.makeTableDetails(result.headings,results,summary);
+const details=Audit.makeOpportunityDetails(result.headings,results,wastedMs,wastedBytes);
return{
explanation:result.explanation,
@@ -15061,7 +15292,7 @@ throw new Error('audit_ unimplemented');
module.exports=UnusedBytes;
-},{"../../gather/computed/metrics/lantern-interactive":"./gather/computed/metrics/lantern-interactive","../../lib/dependency-graph/network-node.js":24,"../../lib/dependency-graph/node.js":25,"../../lib/dependency-graph/simulator/simulator":28,"../audit":2}],4:[function(require,module,exports){
+},{"../../gather/computed/metrics/lantern-interactive":"./gather/computed/metrics/lantern-interactive","../../lib/statistics":41,"../audit":2}],4:[function(require,module,exports){
@@ -15128,23 +15359,36 @@ return Promise.resolve(this.audit_(artifacts)).then(result=>this.createAuditProd
static createAuditProduct(result){
-const extendedInfo={
-value:result};
+const detailsItem={
+...result,
+...result.manifestValues,
+manifestValues:undefined,
+warnings:undefined,
+allChecks:undefined};
+
+
+if(result.manifestValues&&result.manifestValues.allChecks){
+result.manifestValues.allChecks.forEach(check=>{
+detailsItem[check.id]=check.passing;
+});
+}
+
+const details={items:[detailsItem]};
if(result.failures.length>0){
return{
rawValue:false,
explanation:`Failures: ${result.failures.join(',\n')}.`,
-extendedInfo};
+details};
}
return{
rawValue:true,
-extendedInfo,
+details,
warnings:result.warnings};
}
@@ -15206,7 +15450,6 @@ module.exports=ViolationAudit;
-
'use strict';
const defaultConfigPath='./default-config.js';
@@ -15217,21 +15460,29 @@ const constants=require('./constants');
const isDeepEqual=require('lodash.isequal');
const log=require('lighthouse-logger');
const path=require('path');
-const Audit=require('../audits/audit');
-const Runner=require('../runner');
+const Audit=require('../audits/audit.js');
+const Runner=require('../runner.js');
+
+
+
+
+
+
+
function validatePasses(passes,audits){
if(!Array.isArray(passes)){
return;
}
+
const requiredGatherers=Config.getGatherersNeededByAudits(audits);
passes.forEach(pass=>{
pass.gatherers.forEach(gathererDefn=>{
-const gatherer=gathererDefn.instance||gathererDefn.implementation;
+const gatherer=gathererDefn.instance;
const isGatherRequiredByAudits=requiredGatherers.has(gatherer.name);
-if(isGatherRequiredByAudits===false){
+if(!isGatherRequiredByAudits){
const msg=`${gatherer.name} gatherer requested, however no audit requires it.`;
log.warn('config',msg);
}
@@ -15249,6 +15500,11 @@ usedNames.add(passName);
});
}
+
+
+
+
+
function validateCategories(categories,audits,groups){
if(!categories){
return;
@@ -15260,7 +15516,7 @@ if(!auditRef.id){
throw new Error(`missing an audit id at ${categoryId}[${index}]`);
}
-const audit=audits.find(a=>a.implementation.meta.name===auditRef.id);
+const audit=audits&&audits.find(a=>a.implementation.meta.id===auditRef.id);
if(!audit){
throw new Error(`could not find ${auditRef.id} audit for category ${categoryId}`);
}
@@ -15275,44 +15531,48 @@ if(auditRef.weight>0&&isManual){
throw new Error(`${auditRef.id} is manual but has a positive weight`);
}
-if(auditRef.group&&!groups[auditRef.group]){
+if(auditRef.group&&(!groups||!groups[auditRef.group])){
throw new Error(`${auditRef.id} references unknown group ${auditRef.group}`);
}
});
});
}
+
+
+
+
function assertValidAudit(auditDefinition,auditPath){
const auditName=auditPath||
-auditDefinition&&auditDefinition.meta&&auditDefinition.meta.name;
+auditDefinition&&auditDefinition.meta&&auditDefinition.meta.id;
if(typeof auditDefinition.audit!=='function'||auditDefinition.audit===Audit.audit){
throw new Error(`${auditName} has no audit() method.`);
}
-if(typeof auditDefinition.meta.name!=='string'){
-throw new Error(`${auditName} has no meta.name property, or the property is not a string.`);
+if(typeof auditDefinition.meta.id!=='string'){
+throw new Error(`${auditName} has no meta.id property, or the property is not a string.`);
}
-if(typeof auditDefinition.meta.description!=='string'){
+if(typeof auditDefinition.meta.title!=='string'){
throw new Error(
-`${auditName} has no meta.description property, or the property is not a string.`);
+`${auditName} has no meta.title property, or the property is not a string.`);
}
-if(typeof auditDefinition.meta.failureDescription!=='string'&&
+if(typeof auditDefinition.meta.failureTitle!=='string'&&
auditDefinition.meta.scoreDisplayMode===Audit.SCORING_MODES.BINARY){
-throw new Error(`${auditName} has no failureDescription and should.`);
+throw new Error(`${auditName} has no failureTitle and should.`);
}
-if(typeof auditDefinition.meta.helpText!=='string'){
+if(typeof auditDefinition.meta.description!=='string'){
throw new Error(
-`${auditName} has no meta.helpText property, or the property is not a string.`);
+`${auditName} has no meta.description property, or the property is not a string.`);
-}else if(auditDefinition.meta.helpText===''){
+}else if(auditDefinition.meta.description===''){
throw new Error(
-`${auditName} has an empty meta.helpText string. Please add a description for the UI.`);
+`${auditName} has an empty meta.description string. Please add a description for the UI.`);
}
@@ -15323,6 +15583,10 @@ throw new Error(
}
}
+
+
+
+
function assertValidGatherer(gathererInstance,gathererName){
gathererName=gathererName||gathererInstance.name||'gatherer';
@@ -15347,10 +15611,14 @@ throw new Error(`${gathererName} has no afterPass() method.`);
function cleanFlagsForSettings(flags={}){
+
const settings={};
+
for(const key of Object.keys(flags)){
+
if(typeof constants.defaultSettings[key]!=='undefined'){
-settings[key]=flags[key];
+const safekey=key;
+settings[safekey]=flags[safekey];
}
}
@@ -15358,7 +15626,13 @@ return settings;
}
-function merge(base,extension,overwriteArrays=false){
+
+
+
+
+
+
+function _merge(base,extension,overwriteArrays=false){
if(typeof base==='undefined'||base===null){
return extension;
@@ -15375,10 +15649,11 @@ if(!merged.some(candidate=>isDeepEqual(candidate,item)))merged.push(item);
return merged;
}else if(typeof extension==='object'){
if(typeof base!=='object')throw new TypeError(`Expected object but got ${typeof base}`);
+if(Array.isArray(base))throw new TypeError('Expected object but got Array');
Object.keys(extension).forEach(key=>{
const localOverwriteArrays=overwriteArrays||
key==='settings'&&typeof base[key]==='object';
-base[key]=merge(base[key],extension[key],localOverwriteArrays);
+base[key]=_merge(base[key],extension[key],localOverwriteArrays);
});
return base;
}
@@ -15386,21 +15661,61 @@ return base;
return extension;
}
+
+
+
+
+
+const merge=_merge;
+
+
+
+
+
+
function cloneArrayWithPluginSafety(array){
return array.map(item=>{
-return typeof item==='object'?Object.assign({},item):item;
+if(typeof item==='object'){
+
+return Object.assign(
+Object.create(
+Object.getPrototypeOf(item)),
+
+item);
+
+}
+
+return item;
});
}
+
+
+
+
+
+
+
function deepClone(json){
-const cloned=JSON.parse(JSON.stringify(json));
+return JSON.parse(JSON.stringify(json));
+}
+
+
+
-if(Array.isArray(json.passes)){
-cloned.passes.forEach((pass,i)=>{
+
+function deepCloneConfigJson(json){
+const cloned=deepClone(json);
+
+
+
+if(Array.isArray(cloned.passes)&&Array.isArray(json.passes)){
+for(let i=0;i<cloned.passes.length;i++){
+const pass=cloned.passes[i];
pass.gatherers=cloneArrayWithPluginSafety(json.passes[i].gatherers||[]);
-});
+}
}
if(Array.isArray(json.audits)){
@@ -15410,12 +15725,35 @@ cloned.audits=cloneArrayWithPluginSafety(json.audits);
return cloned;
}
+
+
+
+
+
+const mergeOptionsOfItems=function(items){
+
+const mergedItems=[];
+
+for(const item of items){
+const existingItem=item.path&&mergedItems.find(candidate=>candidate.path===item.path);
+if(!existingItem){
+mergedItems.push(item);
+continue;
+}
+
+existingItem.options=Object.assign({},existingItem.options,item.options);
+}
+
+return mergedItems;
+};
+
class Config{
+
constructor(configJSON,flags){
let configPath=flags&&flags.configPath;
@@ -15429,52 +15767,46 @@ throw new Error('configPath must be an absolute path.');
}
-configJSON=deepClone(configJSON);
+configJSON=deepCloneConfigJson(configJSON);
if(configJSON.extends==='lighthouse:full'){
-const explodedFullConfig=Config.extendConfigJSON(deepClone(defaultConfig),
-deepClone(fullConfig));
+const explodedFullConfig=Config.extendConfigJSON(deepCloneConfigJson(defaultConfig),
+deepCloneConfigJson(fullConfig));
configJSON=Config.extendConfigJSON(explodedFullConfig,configJSON);
}else if(configJSON.extends){
-configJSON=Config.extendConfigJSON(deepClone(defaultConfig),configJSON);
+configJSON=Config.extendConfigJSON(deepCloneConfigJson(defaultConfig),configJSON);
}
-configJSON=Config.augmentWithDefaults(configJSON);
+const configDir=configPath?path.dirname(configPath):undefined;
+const settings=Config.initSettings(configJSON.settings,flags);
-configJSON.audits=Config.expandAuditShorthandAndMergeOptions(configJSON.audits);
-configJSON.passes=Config.expandGathererShorthandAndMergeOptions(configJSON.passes);
+const passesWithDefaults=Config.augmentPassesWithDefaults(configJSON.passes);
+Config.adjustDefaultPassForThrottling(settings,passesWithDefaults);
+const passes=Config.requireGatherers(passesWithDefaults,configDir);
-configJSON.settings=merge(configJSON.settings||{},cleanFlagsForSettings(flags),true);
+this.settings=settings;
-if(Array.isArray(configJSON.settings.onlyCategories)||
-Array.isArray(configJSON.settings.onlyAudits)||
-Array.isArray(configJSON.settings.skipAudits)){
-const categoryIds=configJSON.settings.onlyCategories;
-const auditIds=configJSON.settings.onlyAudits;
-const skipAuditIds=configJSON.settings.skipAudits;
-configJSON=Config.generateNewFilteredConfig(configJSON,categoryIds,auditIds,
-skipAuditIds);
-}
+this.passes=passes;
+
+this.audits=Config.requireAudits(configJSON.audits,configDir);
-Config.adjustDefaultPassForThrottling(configJSON);
+this.categories=configJSON.categories||null;
+this.groups=configJSON.groups||null;
-this._configDir=configPath?path.dirname(configPath):undefined;
+Config.filterConfigIfNeeded(this);
-this._passes=Config.requireGatherers(configJSON.passes,this._configDir);
-this._audits=Config.requireAudits(configJSON.audits,this._configDir);
-this._categories=configJSON.categories;
-this._groups=configJSON.groups;
-this._settings=configJSON.settings||{};
+validatePasses(this.passes,this.audits);
+validateCategories(this.categories,this.audits,this.groups);
-validatePasses(configJSON.passes,this._audits);
-validateCategories(configJSON.categories,this._audits,this._groups);
+
+const configJson=this;
}
@@ -15483,8 +15815,8 @@ validateCategories(configJSON.categories,this._audits,this._groups);
static extendConfigJSON(baseJSON,extendJSON){
-if(extendJSON.passes){
-extendJSON.passes.forEach(pass=>{
+if(extendJSON.passes&&baseJSON.passes){
+for(const pass of extendJSON.passes){
const passName=pass.passName||constants.defaultPassConfig.passName;
const basePass=baseJSON.passes.find(candidate=>candidate.passName===passName);
@@ -15494,7 +15826,7 @@ baseJSON.passes.push(pass);
}else{
merge(basePass,pass);
}
-});
+}
delete extendJSON.passes;
}
@@ -15506,14 +15838,13 @@ return merge(baseJSON,extendJSON);
-static augmentWithDefaults(config){
-const{defaultSettings,defaultPassConfig}=constants;
-config.settings=merge(deepClone(defaultSettings),config.settings,true);
-if(config.passes){
-config.passes=config.passes.map(pass=>merge(deepClone(defaultPassConfig),pass));
+static augmentPassesWithDefaults(passes){
+if(!passes){
+return null;
}
-return config;
+const{defaultPassConfig}=constants;
+return passes.map(pass=>merge(deepClone(defaultPassConfig),pass));
}
@@ -15521,23 +15852,46 @@ return config;
+static initSettings(settings={},flags){
-static expandAuditShorthandAndMergeOptions(audits){
+const{defaultSettings}=constants;
+const settingWithDefaults=merge(deepClone(defaultSettings),settings,true);
+
+
+const settingsWithFlags=merge(settingWithDefaults||{},cleanFlagsForSettings(flags),true);
+
+return settingsWithFlags;
+}
+
+
+
+
+
+
+static expandAuditShorthand(audits){
if(!audits){
-return audits;
+return null;
}
const newAudits=audits.map(audit=>{
if(typeof audit==='string'){
+
return{path:audit,options:{}};
-}else if(audit&&typeof audit.audit==='function'){
+}else if('implementation'in audit&&typeof audit.implementation.audit==='function'){
+
+return audit;
+}else if('path'in audit&&typeof audit.path==='string'){
+
+return audit;
+}else if('audit'in audit&&typeof audit.audit==='function'){
+
return{implementation:audit,options:{}};
}else{
-return audit;
+throw new Error('Invalid Audit type '+JSON.stringify(audit));
}
});
-return Config._mergeOptionsOfItems(newAudits);
+return newAudits;
}
@@ -15551,48 +15905,32 @@ return Config._mergeOptionsOfItems(newAudits);
-static expandGathererShorthandAndMergeOptions(passes){
-if(!passes){
-return passes;
-}
-
-passes.forEach(pass=>{
-pass.gatherers=pass.gatherers.map(gatherer=>{
+static expandGathererShorthand(gatherers){
+const expanded=gatherers.map(gatherer=>{
if(typeof gatherer==='string'){
+
return{path:gatherer,options:{}};
+}else if('implementation'in gatherer||'instance'in gatherer){
+
+return gatherer;
+}else if('path'in gatherer){
+
+if(typeof gatherer.path!=='string'){
+throw new Error('Invalid Gatherer type '+JSON.stringify(gatherer));
+}
+return gatherer;
}else if(typeof gatherer==='function'){
+
return{implementation:gatherer,options:{}};
}else if(gatherer&&typeof gatherer.beforePass==='function'){
+
return{instance:gatherer,options:{}};
}else{
-return gatherer;
+throw new Error('Invalid Gatherer type '+JSON.stringify(gatherer));
}
});
-pass.gatherers=Config._mergeOptionsOfItems(pass.gatherers);
-});
-
-return passes;
-}
-
-
-
-
-
-static _mergeOptionsOfItems(items){
-const mergedItems=[];
-
-for(const item of items){
-const existingItem=item.path&&mergedItems.find(candidate=>candidate.path===item.path);
-if(!existingItem){
-mergedItems.push(item);
-continue;
-}
-
-existingItem.options=Object.assign({},existingItem.options,item.options);
-}
-
-return mergedItems;
+return expanded;
}
@@ -15601,15 +15939,14 @@ return mergedItems;
-static adjustDefaultPassForThrottling(config){
-if(config.settings.throttlingMethod!=='devtools'&&
-config.settings.throttlingMethod!=='provided'){
+static adjustDefaultPassForThrottling(settings,passes){
+if(!passes||
+settings.throttlingMethod!=='devtools'&&settings.throttlingMethod!=='provided'){
return;
}
-const defaultPass=config.passes.find(pass=>pass.passName==='defaultPass');
+const defaultPass=passes.find(pass=>pass.passName==='defaultPass');
if(!defaultPass)return;
-
const overrides=constants.nonSimulatedPassConfigOverrides;
defaultPass.pauseAfterLoadMs=
Math.max(overrides.pauseAfterLoadMs,defaultPass.pauseAfterLoadMs);
@@ -15623,42 +15960,29 @@ Math.max(overrides.networkQuietThresholdMs,defaultPass.networkQuietThresholdMs);
+static filterConfigIfNeeded(config){
+const settings=config.settings;
+if(!settings.onlyCategories&&!settings.onlyAudits&&!settings.skipAudits){
+return;
+}
+const{categories,requestedAuditNames}=Config.filterCategoriesAndAudits(config.categories,
+settings);
-static generateNewFilteredConfig(oldConfig,categoryIds,auditIds,skipAuditIds){
+const audits=config.audits&&config.audits.filter(auditDefn=>
+requestedAuditNames.has(auditDefn.implementation.meta.id));
-const config=deepClone(oldConfig);
-config.audits=Config.expandAuditShorthandAndMergeOptions(config.audits);
-config.passes=Config.expandGathererShorthandAndMergeOptions(config.passes);
-config.passes=Config.requireGatherers(config.passes);
+const requiredGathererIds=Config.getGatherersNeededByAudits(audits);
-const{categories,audits:requestedAuditNames}=Config.filterCategoriesAndAudits(
-config.categories,
-categoryIds,
-auditIds,
-skipAuditIds);
+const passes=Config.generatePassesNeededByGatherers(config.passes,requiredGathererIds);
config.categories=categories;
-
-
-const auditPathToNameMap=Config.getMapOfAuditPathToName(config);
-const getAuditName=auditDefn=>auditDefn.implementation?
-auditDefn.implementation.meta.name:
-auditPathToNameMap.get(auditDefn.path);
-config.audits=config.audits.filter(auditDefn=>
-requestedAuditNames.has(getAuditName(auditDefn)));
-
-
-const auditObjectsSelected=Config.requireAudits(config.audits);
-const requiredGatherers=Config.getGatherersNeededByAudits(auditObjectsSelected);
-
-
-config.passes=Config.generatePassesNeededByGatherers(config.passes,requiredGatherers);
-return config;
+config.audits=audits;
+config.passes=passes;
}
@@ -15667,19 +15991,22 @@ return config;
+static filterCategoriesAndAudits(oldCategories,settings){
+if(!oldCategories){
+return{categories:null,requestedAuditNames:new Set()};
+}
-
-static filterCategoriesAndAudits(oldCategories,categoryIds,auditIds,skipAuditIds){
-if(auditIds&&skipAuditIds){
+if(settings.onlyAudits&&settings.skipAudits){
throw new Error('Cannot set both skipAudits and onlyAudits');
}
+
const categories={};
-const filterByIncludedCategory=!!categoryIds;
-const filterByIncludedAudit=!!auditIds;
-categoryIds=categoryIds||[];
-auditIds=auditIds||[];
-skipAuditIds=skipAuditIds||[];
+const filterByIncludedCategory=!!settings.onlyCategories;
+const filterByIncludedAudit=!!settings.onlyAudits;
+const categoryIds=settings.onlyCategories||[];
+const auditIds=settings.onlyAudits||[];
+const skipAuditIds=settings.skipAudits||[];
categoryIds.forEach(categoryId=>{
@@ -15693,15 +16020,13 @@ const auditsToValidate=new Set(auditIds.concat(skipAuditIds));
for(const auditId of auditsToValidate){
const foundCategory=Object.keys(oldCategories).find(categoryId=>{
const auditRefs=oldCategories[categoryId].auditRefs;
-return auditRefs.find(candidate=>candidate.id===auditId);
+return!!auditRefs.find(candidate=>candidate.id===auditId);
});
if(!foundCategory){
const parentKeyName=skipAuditIds.includes(auditId)?'skipAudits':'onlyAudits';
log.warn('config',`unrecognized audit in '${parentKeyName}': ${auditId}`);
-}
-
-if(auditIds.includes(auditId)&&categoryIds.includes(foundCategory)){
+}else if(auditIds.includes(auditId)&&categoryIds.includes(foundCategory)){
log.warn('config',`${auditId} in 'onlyAudits' is already included by `+
`${foundCategory} in 'onlyCategories'`);
}
@@ -15736,7 +16061,7 @@ category.auditRefs.forEach(audit=>includedAudits.add(audit.id));
}
});
-return{categories,audits:includedAudits};
+return{categories,requestedAuditNames:includedAudits};
}
@@ -15744,26 +16069,15 @@ return{categories,audits:includedAudits};
static getCategories(config){
-return Object.keys(config.categories).map(id=>{
-const title=config.categories[id].title;
-return{id,title};
-});
+const categories=config.categories;
+if(!categories){
+return[];
}
-
-
-
-
-
-static getMapOfAuditPathToName(config){
-const auditObjectsAll=Config.requireAudits(config.audits);
-const auditPathToName=new Map(auditObjectsAll.map((auditDefn,index)=>{
-const AuditClass=auditDefn.implementation;
-const auditPath=config.audits[index];
-const auditName=AuditClass.meta.name;
-return[auditPath,auditName];
-}));
-return auditPathToName;
+return Object.keys(categories).map(id=>{
+const title=categories[id].title;
+return{id,title};
+});
}
@@ -15791,11 +16105,15 @@ return list;
static generatePassesNeededByGatherers(passes,requiredGatherers){
+if(!passes){
+return null;
+}
+
const auditsNeedTrace=requiredGatherers.has('traces');
const filteredPasses=passes.map(pass=>{
pass.gatherers=pass.gatherers.filter(gathererDefn=>{
-const gatherer=gathererDefn.instance||gathererDefn.implementation;
+const gatherer=gathererDefn.instance;
return requiredGatherers.has(gatherer.name);
});
@@ -15826,121 +16144,120 @@ return filteredPasses;
static requireAudits(audits,configPath){
-if(!audits){
+const expandedAudits=Config.expandAuditShorthand(audits);
+if(!expandedAudits){
return null;
}
const coreList=Runner.getAuditList();
-return audits.map(auditDefn=>{
-if(!auditDefn.implementation){
-const path=auditDefn.path;
+const auditDefns=expandedAudits.map(audit=>{
+let implementation;
+if('implementation'in audit){
+implementation=audit.implementation;
+}else{
-const coreAudit=coreList.find(a=>a===`${path}.js`);
-let requirePath=`../audits/${path}`;
+const auditPathJs=`${audit.path}.js`;
+const coreAudit=coreList.find(a=>a===auditPathJs);
+let requirePath=`../audits/${audit.path}`;
if(!coreAudit){
-requirePath=Runner.resolvePlugin(path,configPath,'audit');
+requirePath=Runner.resolvePlugin(audit.path,configPath,'audit');
}
-
-auditDefn.implementation=require(requirePath);
+implementation=require(requirePath);
}
-assertValidAudit(auditDefn.implementation,auditDefn.path);
-return auditDefn;
+return{
+implementation,
+path:audit.path,
+options:audit.options||{}};
+
});
-}
+const mergedAuditDefns=mergeOptionsOfItems(auditDefns);
+mergedAuditDefns.forEach(audit=>assertValidAudit(audit.implementation,audit.path));
+return mergedAuditDefns;
+}
-static requireGatherers(passes,configPath){
-if(!passes){
-return null;
-}
-const coreList=Runner.getGathererList();
-passes.forEach(pass=>{
-pass.gatherers.forEach(gathererDefn=>{
-if(!gathererDefn.instance){
-let GathererClass=gathererDefn.implementation;
-if(!GathererClass){
-const name=gathererDefn.path;
-const coreGatherer=coreList.find(a=>a===`${name}.js`);
+static requireGathererFromPath(path,options,coreAuditList,configPath){
+const coreGatherer=coreAuditList.find(a=>a===`${path}.js`);
-let requirePath=`../gather/gatherers/${name}`;
+let requirePath=`../gather/gatherers/${path}`;
if(!coreGatherer){
-requirePath=Runner.resolvePlugin(name,configPath,'gatherer');
+requirePath=Runner.resolvePlugin(path,configPath,'gatherer');
}
-GathererClass=require(requirePath);
-}
+const GathererClass=require(requirePath);
-gathererDefn.implementation=GathererClass;
-gathererDefn.instance=new GathererClass();
-}
-
-assertValidGatherer(gathererDefn.instance,gathererDefn.path);
-});
-});
+return{
+instance:new GathererClass(),
+implementation:GathererClass,
+path,
+options:options||{}};
-return passes;
}
-get configDir(){
-return this._configDir;
-}
-get passes(){
-return this._passes;
-}
-
-get audits(){
-return this._audits;
-}
-get categories(){
-return this._categories;
-}
-get groups(){
-return this._groups;
+static requireGatherers(passes,configPath){
+if(!passes){
+return null;
}
+const coreList=Runner.getGathererList();
+const fullPasses=passes.map(pass=>{
+const gathererDefns=Config.expandGathererShorthand(pass.gatherers).map(gathererDefn=>{
+if(gathererDefn.instance){
+return{
+instance:gathererDefn.instance,
+implementation:gathererDefn.implementation,
+path:gathererDefn.path,
+options:gathererDefn.options||{}};
-get settings(){
-return this._settings;
-}}
-
-
-
-
-
-
-
-
-
-
-
-
+}else if(gathererDefn.implementation){
+const GathererClass=gathererDefn.implementation;
+return{
+instance:new GathererClass(),
+implementation:gathererDefn.implementation,
+path:gathererDefn.path,
+options:gathererDefn.options||{}};
+
+}else if(gathererDefn.path){
+const path=gathererDefn.path;
+const options=gathererDefn.options;
+return Config.requireGathererFromPath(path,options,coreList,configPath);
+}else{
+throw new Error('Invalid expanded Gatherer: '+JSON.stringify(gathererDefn));
+}
+});
+const mergedDefns=mergeOptionsOfItems(gathererDefns);
+mergedDefns.forEach(gatherer=>assertValidGatherer(gatherer.instance,gatherer.path));
+return Object.assign(pass,{gatherers:mergedDefns});
+});
+return fullPasses;
+}}
module.exports=Config;
}).call(this,"/../lighthouse-core/config");
-},{"../audits/audit":2,"../runner":50,"./constants":8,"./default-config.js":9,"./full-config.js":10,"lighthouse-logger":143,"lodash.isequal":144,"path":75}],8:[function(require,module,exports){
+},{"../audits/audit.js":2,"../runner.js":50,"./constants":8,"./default-config.js":9,"./full-config.js":10,"lighthouse-logger":125,"lodash.isequal":126,"path":75}],8:[function(require,module,exports){
@@ -15990,6 +16307,7 @@ onlyCategories:null,
skipAudits:null};
+
const defaultPassConfig={
passName:'defaultPass',
recordTrace:false,
@@ -16048,9 +16366,9 @@ gatherers:[
'chrome-console-messages',
'image-usage',
'accessibility',
-'dobetterweb/all-event-listeners',
'dobetterweb/anchors-with-no-rel-noopener',
'dobetterweb/appcache',
+'dobetterweb/doctype',
'dobetterweb/domstats',
'dobetterweb/js-libraries',
'dobetterweb/optimized-images',
@@ -16093,16 +16411,16 @@ audits:[
'works-offline',
'viewport',
'without-javascript',
-'first-contentful-paint',
-'first-meaningful-paint',
+'metrics/first-contentful-paint',
+'metrics/first-meaningful-paint',
'load-fast-enough-for-pwa',
-'speed-index',
+'metrics/speed-index',
'screenshot-thumbnails',
-'estimated-input-latency',
+'metrics/estimated-input-latency',
'errors-in-console',
'time-to-first-byte',
-'first-cpu-idle',
-'interactive',
+'metrics/first-cpu-idle',
+'metrics/interactive',
'user-timings',
'critical-request-chains',
'redirects',
@@ -16181,11 +16499,11 @@ audits:[
'byte-efficiency/uses-responsive-images',
'byte-efficiency/efficient-animated-content',
'dobetterweb/appcache-manifest',
+'dobetterweb/doctype',
'dobetterweb/dom-size',
'dobetterweb/external-anchors-use-rel-noopener',
'dobetterweb/geolocation-on-start',
'dobetterweb/no-document-write',
-'dobetterweb/no-mutation-events',
'dobetterweb/no-vulnerable-libraries',
'dobetterweb/no-websql',
'dobetterweb/notification-on-start',
@@ -16308,17 +16626,22 @@ manualDescription:'These checks are required by the baseline '+
'[PWA Checklist](https://developers.google.com/web/progressive-web-apps/checklist) but are '+
'not automatically checked by Lighthouse. They do not affect your score but it\'s important that you verify them manually.',
auditRefs:[
+
+{id:'load-fast-enough-for-pwa',weight:7},
+{id:'works-offline',weight:5},
+
+{id:'webapp-install-banner',weight:3},
+
+{id:'is-on-https',weight:2},
+{id:'redirects-http',weight:2},
+{id:'viewport',weight:2},
+
{id:'service-worker',weight:1},
-{id:'works-offline',weight:1},
{id:'without-javascript',weight:1},
-{id:'is-on-https',weight:1},
-{id:'redirects-http',weight:1},
-{id:'load-fast-enough-for-pwa',weight:1},
-{id:'webapp-install-banner',weight:1},
{id:'splash-screen',weight:1},
{id:'themed-omnibox',weight:1},
-{id:'viewport',weight:1},
{id:'content-width',weight:1},
+{id:'manifest-short-name-length',weight:0},
{id:'pwa-cross-browser',weight:0},
{id:'pwa-page-transitions',weight:0},
@@ -16386,14 +16709,13 @@ auditRefs:[
{id:'is-on-https',weight:1},
{id:'uses-http2',weight:1},
{id:'uses-passive-event-listeners',weight:1},
-{id:'no-mutation-events',weight:1},
{id:'no-document-write',weight:1},
{id:'external-anchors-use-rel-noopener',weight:1},
{id:'geolocation-on-start',weight:1},
+{id:'doctype',weight:1},
{id:'no-vulnerable-libraries',weight:1},
{id:'notification-on-start',weight:1},
{id:'deprecations',weight:1},
-{id:'manifest-short-name-length',weight:1},
{id:'password-inputs-can-be-pasted-into',weight:1},
{id:'errors-in-console',weight:1},
{id:'image-aspect-ratio',weight:1}]},
@@ -16539,10 +16861,12 @@ module.exports=ComputedArtifact;
'use strict';
const ComputedArtifact=require('../computed-artifact');
-const Node=require('../../../lib/dependency-graph/node');
-const NetworkNode=require('../../../lib/dependency-graph/network-node');
-const Simulator=require('../../../lib/dependency-graph/simulator/simulator');
-const WebInspector=require('../../../lib/web-inspector');
+const BaseNode=require('../../../lib/dependency-graph/base-node');
+const NetworkRequest=require('../../../lib/network-request');
+
+
+
+
class LanternMetricArtifact extends ComputedArtifact{
@@ -16551,14 +16875,14 @@ class LanternMetricArtifact extends ComputedArtifact{
static getScriptUrls(dependencyGraph,condition){
+
const scriptUrls=new Set();
dependencyGraph.traverse(node=>{
-if(node.type===Node.TYPES.CPU)return;
-const asNetworkNode=node;
-if(asNetworkNode.record._resourceType!==WebInspector.resourceTypes.Script)return;
-if(condition&&!condition(asNetworkNode))return;
-scriptUrls.add(asNetworkNode.record.url);
+if(node.type===BaseNode.TYPES.CPU)return;
+if(node.record.resourceType!==NetworkRequest.TYPES.Script)return;
+if(condition&&!condition(node))return;
+scriptUrls.add(node.record.url);
});
return scriptUrls;
@@ -16606,6 +16930,7 @@ return simulationResult;
async computeMetricWithGraphs(data,artifacts,extras){
const{trace,devtoolsLog,settings}=data;
+const metricName=this.name.replace('Lantern','');
const graph=await artifacts.requestPageDependencyGraph({trace,devtoolsLog});
const traceOfTab=await artifacts.requestTraceOfTab(trace);
@@ -16615,9 +16940,14 @@ await artifacts.requestLoadSimulator({devtoolsLog,settings}));
const optimisticGraph=this.getOptimisticGraph(graph,traceOfTab);
const pessimisticGraph=this.getPessimisticGraph(graph,traceOfTab);
-const optimisticSimulation=simulator.simulate(optimisticGraph);
-const optimisticFlexSimulation=simulator.simulate(optimisticGraph,{flexibleOrdering:true});
-const pessimisticSimulation=simulator.simulate(pessimisticGraph);
+let simulateOptions={label:`optimistic${metricName}`};
+const optimisticSimulation=simulator.simulate(optimisticGraph,simulateOptions);
+
+simulateOptions={label:`optimisticFlex${metricName}`,flexibleOrdering:true};
+const optimisticFlexSimulation=simulator.simulate(optimisticGraph,simulateOptions);
+
+simulateOptions={label:`pessimistic${metricName}`};
+const pessimisticSimulation=simulator.simulate(pessimisticGraph,simulateOptions);
const optimisticEstimate=this.getEstimateFromSimulation(
optimisticSimulation.timeInMs<optimisticFlexSimulation.timeInMs?
@@ -16659,7 +16989,7 @@ return this.computeMetricWithGraphs(data,computedArtifacts);
module.exports=LanternMetricArtifact;
-},{"../../../lib/dependency-graph/network-node":24,"../../../lib/dependency-graph/node":25,"../../../lib/dependency-graph/simulator/simulator":28,"../../../lib/web-inspector":47,"../computed-artifact":11}],13:[function(require,module,exports){
+},{"../../../lib/dependency-graph/base-node":22,"../../../lib/network-request":38,"../computed-artifact":11}],13:[function(require,module,exports){
@@ -16903,7 +17233,7 @@ Connection.prototype.sendCommand=_sendCommand;
module.exports=Connection;
-},{"../../lib/errors":33,"events":62,"lighthouse-logger":143}],15:[function(require,module,exports){
+},{"../../lib/errors":33,"events":62,"lighthouse-logger":125}],15:[function(require,module,exports){
@@ -16918,19 +17248,8 @@ const Connection=require('./connection.js');
-class Port{
-
-
-
-
-on(eventName,cb){}
-
-
-send(message){}
-
-close(){}}
@@ -17043,6 +17362,7 @@ const NetworkRecorder=require('../lib/network-recorder');
const emulation=require('../lib/emulation');
const Element=require('../lib/element');
const LHError=require('../lib/errors');
+const NetworkRequest=require('../lib/network-request');
const EventEmitter=require('events').EventEmitter;
const URL=require('../lib/url-shim');
const TraceParser=require('../lib/traces/trace-parser');
@@ -17207,7 +17527,7 @@ return!!this._domainEnabledCounts.get(domain);
-evaluteScriptOnNewDocument(scriptSource){
+evaluateScriptOnNewDocument(scriptSource){
return this.sendCommand('Page.addScriptToEvaluateOnLoad',{
scriptSource});
@@ -17620,7 +17940,7 @@ cleanupFn();
_beginNetworkStatusMonitoring(startingUrl){
-this._networkStatusMonitor=new NetworkRecorder([]);
+this._networkStatusMonitor=new NetworkRecorder();
this._monitoredUrl=startingUrl;
@@ -17761,6 +18081,8 @@ return null;
getRequestContent(requestId,timeout=1000){
+requestId=NetworkRequest.getRequestIdForBackend(requestId);
+
return new Promise((resolve,reject)=>{
@@ -18098,7 +18420,7 @@ storageTypes:typesToClear});
async cacheNatives(){
-await this.evaluteScriptOnNewDocument(`window.__nativePromise = Promise;
+await this.evaluateScriptOnNewDocument(`window.__nativePromise = Promise;
window.__nativeError = Error;`);
}
@@ -18108,39 +18430,7 @@ await this.evaluteScriptOnNewDocument(`window.__nativePromise = Promise;
async registerPerformanceObserver(){
const scriptStr=`(${pageFunctions.registerPerformanceObserverInPage.toString()})()`;
-await this.evaluteScriptOnNewDocument(scriptStr);
-}
-
-
-
-
-
-
-
-
-captureFunctionCallSites(funcName){
-const globalVarToPopulate=`window['__${funcName}StackTraces']`;
-const collectUsage=()=>{
-return this.evaluateAsync(
-`Array.from(${globalVarToPopulate}).map(item => JSON.parse(item))`).
-then(result=>{
-if(!Array.isArray(result)){
-throw new Error(
-'Driver failure: Expected evaluateAsync results to be an array '+
-`but got "${JSON.stringify(result)}" instead.`);
-}
-
-return result.filter(item=>!item.isExtension);
-});
-};
-
-const funcBody=pageFunctions.captureJSCallUsage.toString();
-
-this.evaluteScriptOnNewDocument(`
- ${globalVarToPopulate} = new Set();
- (${funcName} = ${funcBody}(${funcName}, ${globalVarToPopulate}))`);
-
-return collectUsage;
+await this.evaluateScriptOnNewDocument(scriptStr);
}
@@ -18252,7 +18542,7 @@ Driver.prototype.sendCommand=_sendCommand;
module.exports=Driver;
-},{"../config/constants":8,"../lib/element":31,"../lib/emulation":32,"../lib/errors":33,"../lib/network-recorder":37,"../lib/page-functions.js":38,"../lib/traces/trace-parser":45,"../lib/url-shim":"url","./connections/connection.js":14,"./devtools-log":16,"events":62,"lighthouse-logger":143}],18:[function(require,module,exports){
+},{"../config/constants":8,"../lib/element":31,"../lib/emulation":32,"../lib/errors":33,"../lib/network-recorder":37,"../lib/network-request":38,"../lib/page-functions.js":39,"../lib/traces/trace-parser":45,"../lib/url-shim":"url","./connections/connection.js":14,"./devtools-log":16,"events":62,"lighthouse-logger":125}],18:[function(require,module,exports){
@@ -18325,12 +18615,13 @@ class GatherRunner{
-static loadBlank(
+static async loadBlank(
driver,
url=constants.defaultPassConfig.blankPage,
duration=constants.defaultPassConfig.blankDuration)
{
-return driver.gotoURL(url).then(_=>new Promise(resolve=>setTimeout(resolve,duration)));
+await driver.gotoURL(url);
+await new Promise(resolve=>setTimeout(resolve,duration));
}
@@ -18342,13 +18633,12 @@ return driver.gotoURL(url).then(_=>new Promise(resolve=>setTimeout(resolve,durat
-static loadPage(driver,passContext){
-return driver.gotoURL(passContext.url,{
+static async loadPage(driver,passContext){
+const finalUrl=await driver.gotoURL(passContext.url,{
waitForLoad:true,
-passContext}).
-then(finalUrl=>{
+passContext});
+
passContext.url=finalUrl;
-});
}
@@ -18356,25 +18646,17 @@ passContext.url=finalUrl;
-
-static setupDriver(driver,gathererResults,options){
+static async setupDriver(driver,options){
log.log('status','Initializing…');
const resetStorage=!options.settings.disableStorageReset;
-return driver.assertNoSameOriginServiceWorkerClients(options.requestedUrl).
-then(_=>driver.getUserAgent()).
-then(userAgent=>{
-gathererResults.UserAgent=[userAgent];
-GatherRunner.warnOnHeadless(userAgent,gathererResults);
-}).
-then(_=>driver.beginEmulation(options.settings)).
-then(_=>driver.enableRuntimeEvents()).
-then(_=>driver.cacheNatives()).
-then(_=>driver.registerPerformanceObserver()).
-then(_=>driver.dismissJavaScriptDialogs()).
-then(_=>{
-if(resetStorage)return driver.clearDataForOrigin(options.requestedUrl);
-});
+await driver.assertNoSameOriginServiceWorkerClients(options.requestedUrl);
+await driver.beginEmulation(options.settings);
+await driver.enableRuntimeEvents();
+await driver.cacheNatives();
+await driver.registerPerformanceObserver();
+await driver.dismissJavaScriptDialogs();
+if(resetStorage)await driver.clearDataForOrigin(options.requestedUrl);
}
@@ -18439,48 +18721,28 @@ return error;
-static warnOnHeadless(userAgent,gathererResults){
-const chromeVersion=userAgent.split(/HeadlessChrome\/(.*) /)[1];
-
-
-const minVersion='63.0.3239.0';
-if(chromeVersion&&chromeVersion<minVersion){
-gathererResults.LighthouseRunWarnings.push('Your site\'s mobile performance may be '+
-'worse than the numbers presented in this report. Lighthouse could not test on a '+
-'mobile connection because Headless Chrome does not support network throttling '+
-'prior to version '+minVersion+'. The version used was '+chromeVersion);
-}
-}
-
-
-
-
-
-
-static beforePass(passContext,gathererResults){
+static async beforePass(passContext,gathererResults){
const blockedUrls=(passContext.passConfig.blockedUrlPatterns||[]).
concat(passContext.settings.blockedUrlPatterns||[]);
const blankPage=passContext.passConfig.blankPage;
const blankDuration=passContext.passConfig.blankDuration;
-const pass=GatherRunner.loadBlank(passContext.driver,blankPage,blankDuration).
+await GatherRunner.loadBlank(passContext.driver,blankPage,blankDuration);
-then(()=>passContext.driver.blockUrlPatterns(blockedUrls)).
-then(()=>passContext.driver.setExtraHTTPHeaders(passContext.settings.extraHeaders));
+await passContext.driver.blockUrlPatterns(blockedUrls);
+await passContext.driver.setExtraHTTPHeaders(passContext.settings.extraHeaders);
-return passContext.passConfig.gatherers.reduce((chain,gathererDefn)=>{
-return chain.then(_=>{
+for(const gathererDefn of passContext.passConfig.gatherers){
const gatherer=gathererDefn.instance;
passContext.options=gathererDefn.options||{};
const artifactPromise=Promise.resolve().then(_=>gatherer.beforePass(passContext));
gathererResults[gatherer.name]=[artifactPromise];
-return GatherRunner.recoverOrThrow(artifactPromise);
-});
-},pass);
+await GatherRunner.recoverOrThrow(artifactPromise);
+}
}
@@ -18490,7 +18752,7 @@ return GatherRunner.recoverOrThrow(artifactPromise);
-static pass(passContext,gathererResults){
+static async pass(passContext,gathererResults){
const driver=passContext.driver;
const config=passContext.passConfig;
const settings=passContext.settings;
@@ -18503,31 +18765,28 @@ const gatherernames=gatherers.map(g=>g.instance.name).join(', ');
const status='Loading page & waiting for onload';
log.log('status',status,gatherernames);
-const pass=Promise.resolve().
-then(_=>{
-if(isPerfRun)driver.cleanBrowserCaches();
-}).
+if(isPerfRun)await driver.cleanBrowserCaches();
-then(_=>driver.beginDevtoolsLog()).
+await driver.beginDevtoolsLog();
-then(_=>{
-if(recordTrace)driver.beginTrace(settings);
-}).
+if(recordTrace)await driver.beginTrace(settings);
-then(_=>GatherRunner.loadPage(driver,passContext)).
-then(_=>log.log('statusEnd',status));
-return gatherers.reduce((chain,gathererDefn)=>{
-return chain.then(_=>{
+await GatherRunner.loadPage(driver,passContext);
+log.log('statusEnd',status);
+
+for(const gathererDefn of gatherers){
const gatherer=gathererDefn.instance;
passContext.options=gathererDefn.options||{};
const artifactPromise=Promise.resolve().then(_=>gatherer.pass(passContext));
-gathererResults[gatherer.name].push(artifactPromise);
-return GatherRunner.recoverOrThrow(artifactPromise);
-});
-},pass);
+
+const gathererResult=gathererResults[gatherer.name]||[];
+gathererResult.push(artifactPromise);
+gathererResults[gatherer.name]=gathererResult;
+await GatherRunner.recoverOrThrow(artifactPromise);
+}
}
@@ -18561,7 +18820,7 @@ let pageLoadError=GatherRunner.getPageLoadError(passContext.url,networkRecords);
if(!driver.online)pageLoadError=undefined;
if(pageLoadError){
-gathererResults.LighthouseRunWarnings.push('Lighthouse was unable to reliably load the '+
+passContext.LighthouseRunWarnings.push('Lighthouse was unable to reliably load the '+
'page you requested. Make sure you are testing the correct URL and that the server is '+
'properly responding to all requests.');
}
@@ -18590,7 +18849,10 @@ const artifactPromise=pageLoadError?
Promise.reject(pageLoadError):
Promise.resolve().then(_=>gatherer.afterPass(passContext,passData));
-gathererResults[gatherer.name].push(artifactPromise);
+
+const gathererResult=gathererResults[gatherer.name]||[];
+gathererResult.push(artifactPromise);
+gathererResults[gatherer.name]=gathererResult;
await GatherRunner.recoverOrThrow(artifactPromise);
log.verbose('statusEnd',status);
}
@@ -18608,120 +18870,125 @@ return passData;
+static async collectArtifacts(gathererResults,baseArtifacts){
-static async collectArtifacts(gathererResults,tracingData,settings){
-
-
-
-const artifacts={
-traces:tracingData.traces,
-devtoolsLogs:tracingData.devtoolsLogs,
-settings,
-
-LighthouseRunWarnings:Array.from(new Set(gathererResults.LighthouseRunWarnings))};
-
+const gathererArtifacts={};
const pageLoadFailures=[];
-for(const[gathererName,phaseResultsPromises]of Object.entries(gathererResults)){
-if(artifacts[gathererName]!==undefined)continue;
+const resultsEntries=Object.entries(gathererResults);
+for(const[gathererName,phaseResultsPromises]of resultsEntries){
+if(gathererArtifacts[gathererName]!==undefined)continue;
try{
const phaseResults=await Promise.all(phaseResultsPromises);
const definedResults=phaseResults.filter(element=>element!==undefined);
const artifact=definedResults[definedResults.length-1];
-artifacts[gathererName]=artifact;
+
+gathererArtifacts[gathererName]=artifact;
}catch(err){
-artifacts[gathererName]=err;
+gathererArtifacts[gathererName]=err;
if(LHError.isPageLoadError(err))pageLoadFailures.push(err);
}
-if(artifacts[gathererName]===undefined){
+if(gathererArtifacts[gathererName]===undefined){
throw new Error(`${gathererName} failed to provide an artifact.`);
}
-if(pageLoadFailures.length>Object.keys(artifacts).length*0.5){
+if(pageLoadFailures.length>Object.keys(gathererArtifacts).length*0.5){
throw pageLoadFailures[0];
}
}
-return artifacts;
-}
+baseArtifacts.LighthouseRunWarnings=Array.from(new Set(baseArtifacts.LighthouseRunWarnings));
+return{...baseArtifacts,...gathererArtifacts};
+}
+
-static run(passes,options){
-const driver=options.driver;
-const tracingData={
+static async getBaseArtifacts(options){
+return{
+fetchTime:new Date().toJSON(),
+LighthouseRunWarnings:[],
+UserAgent:await options.driver.getUserAgent(),
traces:{},
-devtoolsLogs:{}};
+devtoolsLogs:{},
+settings:options.settings,
+URL:{requestedUrl:options.requestedUrl,finalUrl:''}};
+
+}
+
-const gathererResults={
-LighthouseRunWarnings:[],
-fetchTime:[new Date().toJSON()],
-URL:[{requestedUrl:options.requestedUrl,finalUrl:''}]};
-return driver.connect().
-then(_=>GatherRunner.loadBlank(driver)).
-then(_=>GatherRunner.setupDriver(driver,gathererResults,options)).
+static async run(passes,options){
+const driver=options.driver;
+
+
+const gathererResults={};
+
+try{
+await driver.connect();
+const baseArtifacts=await GatherRunner.getBaseArtifacts(options);
+await GatherRunner.loadBlank(driver);
+await GatherRunner.setupDriver(driver,options);
-then(_=>{
-return passes.reduce((chain,passConfig,passIndex)=>{
+let firstPass=true;
+for(const passConfig of passes){
const passContext={
driver:options.driver,
url:options.requestedUrl,
settings:options.settings,
-passConfig};
+passConfig,
+LighthouseRunWarnings:baseArtifacts.LighthouseRunWarnings};
-return chain.
-then(_=>driver.setThrottling(options.settings,passConfig)).
-then(_=>GatherRunner.beforePass(passContext,gathererResults)).
-then(_=>GatherRunner.pass(passContext,gathererResults)).
-then(_=>GatherRunner.afterPass(passContext,gathererResults)).
-then(passData=>{
-tracingData.devtoolsLogs[passConfig.passName]=passData.devtoolsLog;
+await driver.setThrottling(options.settings,passConfig);
+await GatherRunner.beforePass(passContext,gathererResults);
+await GatherRunner.pass(passContext,gathererResults);
+const passData=await GatherRunner.afterPass(passContext,gathererResults);
+
+
+baseArtifacts.devtoolsLogs[passConfig.passName]=passData.devtoolsLog;
if(passData.trace){
-tracingData.traces[passConfig.passName]=passData.trace;
+baseArtifacts.traces[passConfig.passName]=passData.trace;
}
-if(passIndex===0){
+if(firstPass){
-gathererResults.URL[0].finalUrl=passContext.url;
+baseArtifacts.URL.finalUrl=passContext.url;
+firstPass=false;
}
-});
-},Promise.resolve());
-}).
-then(_=>GatherRunner.disposeDriver(driver)).
-then(_=>GatherRunner.collectArtifacts(gathererResults,tracingData,options.settings)).
+}
+await GatherRunner.disposeDriver(driver);
+return GatherRunner.collectArtifacts(gathererResults,baseArtifacts);
+}catch(err){
-catch(err=>{
GatherRunner.disposeDriver(driver);
-
throw err;
-});
+}
}}
module.exports=GatherRunner;
-},{"../config/constants":8,"../gather/driver.js":17,"../lib/errors":33,"../lib/network-recorder.js":37,"../lib/url-shim":"url","lighthouse-logger":143}],19:[function(require,module,exports){
+},{"../config/constants":8,"../gather/driver.js":17,"../lib/errors":33,"../lib/network-recorder.js":37,"../lib/url-shim":"url","lighthouse-logger":125}],19:[function(require,module,exports){
@@ -18740,11 +19007,14 @@ module.exports=GatherRunner;
+
+
class Gatherer{
get name(){
+
return this.constructor.name;
}
@@ -18862,7 +19132,8 @@ return isEqual(objA,objB);
}};
-},{"lodash.isequal":144}],21:[function(require,module,exports){
+},{"lodash.isequal":126}],21:[function(require,module,exports){
+(function(process){
@@ -18874,6 +19145,8 @@ return isEqual(objA,objB);
const path=require('path');
const log=require('lighthouse-logger');
const stream=require('stream');
+const Simulator=require('./dependency-graph/simulator/simulator');
+const lanternTraceSaver=require('./lantern-trace-saver');
const Metrics=require('./traces/pwmetrics-events');
const TraceParser=require('./traces/trace-parser');
const rimraf=require('rimraf');
@@ -19064,7 +19337,9 @@ return assets;
+
function*traceJsonGenerator(traceData){
+const EVENTS_PER_ITERATION=500;
const keys=Object.keys(traceData);
yield'{\n';
@@ -19076,10 +19351,20 @@ const eventsIterator=traceData.traceEvents[Symbol.iterator]();
const firstEvent=eventsIterator.next().value;
yield` ${JSON.stringify(firstEvent)}`;
+
+let eventsRemaining=EVENTS_PER_ITERATION;
+let eventsJSON='';
for(const event of eventsIterator){
-yield`,\n ${JSON.stringify(event)}`;
+eventsJSON+=`,\n ${JSON.stringify(event)}`;
+eventsRemaining--;
+if(eventsRemaining===0){
+yield eventsJSON;
+eventsRemaining=EVENTS_PER_ITERATION;
+eventsJSON='';
}
}
+yield eventsJSON;
+}
yield'\n]';
@@ -19124,6 +19409,22 @@ traceStream.pipe(writeStream);
+async function saveLanternDebugTraces(pathWithBasename){
+if(!process.env.LANTERN_DEBUG)return;
+
+for(const[label,nodeTimings]of Simulator.ALL_NODE_TIMINGS){
+if(lanternTraceSaver.simulationNamesToIgnore.includes(label))continue;
+
+const traceFilename=`${pathWithBasename}-${label}${traceSuffix}`;
+await saveTrace(lanternTraceSaver.convertNodeTimingsToTrace(nodeTimings),traceFilename);
+log.log('saveAssets',`${label} lantern trace file streamed to disk: ${traceFilename}`);
+}
+}
+
+
+
+
+
@@ -19149,6 +19450,7 @@ log.log('saveAssets','trace file streamed to disk: '+streamTraceFilename);
});
await Promise.all(saveAll);
+await saveLanternDebugTraces(pathWithBasename);
}
@@ -19179,148 +19481,8 @@ saveTrace,
logAssets};
-},{"../runner.js":50,"./traces/pwmetrics-events":44,"./traces/trace-parser":45,"lighthouse-logger":143,"mkdirp":58,"path":75,"rimraf":58,"stream":92}],22:[function(require,module,exports){
-
-
-
-
-
-'use strict';
-
-
-
-const log=require('lighthouse-logger');
-
-
-let _logs=[];
-
-class ConsoleQuieter{
-
-static mute(opts){
-_logs=_logs||[];
-
-
-console.log=function(...args){
-_logs.push({type:'log',args,prefix:opts.prefix});
-};
-
-console.warn=function(...args){
-_logs.push({type:'warn',args,prefix:opts.prefix});
-};
-
-console.error=function(...args){
-_logs.push({type:'error',args,prefix:opts.prefix});
-};
-}
-
-static unmuteAndFlush(){
-console.log=ConsoleQuieter._consolelog;
-console.warn=ConsoleQuieter._consolewarn;
-console.error=ConsoleQuieter._consoleerror;
-
-_logs.forEach(entry=>{
-log.verbose(`${entry.prefix}-${entry.type}`,...entry.args);
-});
-_logs=[];
-}}
-
-
-ConsoleQuieter._consolelog=console.log.bind(console);
-ConsoleQuieter._consolewarn=console.warn.bind(console);
-ConsoleQuieter._consoleerror=console.error.bind(console);
-
-module.exports=ConsoleQuieter;
-
-},{"lighthouse-logger":143}],23:[function(require,module,exports){
-
-
-
-
-
-'use strict';
-
-const Node=require('./node');
-
-class CPUNode extends Node{
-
-
-
-
-constructor(parentEvent,childEvents=[]){
-const nodeId=`${parentEvent.tid}.${parentEvent.ts}`;
-super(nodeId);
-
-this._event=parentEvent;
-this._childEvents=childEvents;
-}
-
-
-
-
-get type(){
-return Node.TYPES.CPU;
-}
-
-
-
-
-get startTime(){
-return this._event.ts;
-}
-
-
-
-
-get endTime(){
-return this._event.ts+this._event.dur;
-}
-
-
-
-
-get event(){
-return this._event;
-}
-
-
-
-
-get childEvents(){
-return this._childEvents;
-}
-
-
-
-
-
-didPerformLayout(){
-return this._childEvents.some(evt=>evt.name==='Layout');
-}
-
-
-
-
-
-
-isEvaluateScriptFor(urls){
-return this._childEvents.some(evt=>{
-return evt.name==='EvaluateScript'&&
-!!evt.args.data&&!!evt.args.data.url&&
-urls.has(evt.args.data.url);
-});
-}
-
-
-
-
-cloneWithoutRelationships(){
-return new CPUNode(this._event,this._childEvents);
-}}
-
-
-module.exports=CPUNode;
-
-},{"./node":25}],24:[function(require,module,exports){
+}).call(this,require('_process'));
+},{"../runner.js":50,"./dependency-graph/simulator/simulator":28,"./lantern-trace-saver":35,"./traces/pwmetrics-events":44,"./traces/trace-parser":45,"_process":77,"lighthouse-logger":125,"mkdirp":58,"path":75,"rimraf":58,"stream":92}],22:[function(require,module,exports){
@@ -19328,105 +19490,25 @@ module.exports=CPUNode;
'use strict';
-const Node=require('./node');
-const WebInspector=require('../web-inspector');
-
-class NetworkNode extends Node{
-
-
-
-constructor(networkRecord){
-super(networkRecord.requestId);
-this._record=networkRecord;
-}
-
-
-
-
-get type(){
-return Node.TYPES.NETWORK;
-}
-
-
-
-
-get startTime(){
-return this._record.startTime*1000*1000;
-}
-get endTime(){
-return this._record.endTime*1000*1000;
-}
-get record(){
-return this._record;
-}
-get initiatorType(){
-return this._record._initiator&&this._record._initiator.type;
-}
-get fromDiskCache(){
-return!!this._record._fromDiskCache;
-}
-
-
-
-
-hasRenderBlockingPriority(){
-const priority=this._record.priority();
-const isScript=this._record._resourceType===WebInspector.resourceTypes.Script;
-const isDocument=this._record._resourceType===WebInspector.resourceTypes.Document;
-const isBlockingScript=priority==='High'&&isScript;
-const isBlockingHtmlImport=priority==='High'&&isDocument;
-return priority==='VeryHigh'||isBlockingScript||isBlockingHtmlImport;
-}
-
-
-
-
-cloneWithoutRelationships(){
-const node=new NetworkNode(this._record);
-node.setIsMainDocument(this._isMainDocument);
-return node;
-}}
-
-
-module.exports=NetworkNode;
-
-},{"../web-inspector":47,"./node":25}],25:[function(require,module,exports){
-
-
-
-
-
-'use strict';
-
-
-
-
-
-
-
-
-
-
-
-class Node{
+class BaseNode{
@@ -19506,7 +19588,6 @@ return this._dependencies.length;
getRootNode(){
-
let rootNode=this;
while(rootNode._dependencies.length){
rootNode=rootNode._dependencies[0];
@@ -19549,7 +19630,8 @@ if(!this._dependencies.includes(node)){
return;
}
-node._dependents.splice(node._dependents.indexOf(this),1);
+const thisIndex=node._dependents.indexOf(this);
+node._dependents.splice(thisIndex,1);
this._dependencies.splice(this._dependencies.indexOf(node),1);
}
@@ -19564,7 +19646,7 @@ this.removeDependency(node);
cloneWithoutRelationships(){
-const node=new Node(this.id);
+const node=new BaseNode(this.id);
node.setIsMainDocument(this._isMainDocument);
return node;
}
@@ -19623,7 +19705,6 @@ return idToNodeMap.get(this.id);
_traversePaths(iterator,getNext){
-
const stack=[[this]];
while(stack.length){
@@ -19673,7 +19754,7 @@ this._traversePaths(iterator,getNext);
static hasCycle(node,direction='both'){
if(direction==='both'){
-return Node.hasCycle(node,'dependents')||Node.hasCycle(node,'dependencies');
+return BaseNode.hasCycle(node,'dependents')||BaseNode.hasCycle(node,'dependencies');
}
const visited=new Set();
@@ -19717,14 +19798,184 @@ return false;
}}
-Node.TYPES={
+BaseNode.TYPES={
NETWORK:'network',
CPU:'cpu'};
-module.exports=Node;
+module.exports=BaseNode;
-},{}],26:[function(require,module,exports){
+},{}],23:[function(require,module,exports){
+
+
+
+
+
+'use strict';
+
+const BaseNode=require('./base-node');
+
+class CPUNode extends BaseNode{
+
+
+
+
+constructor(parentEvent,childEvents=[]){
+const nodeId=`${parentEvent.tid}.${parentEvent.ts}`;
+super(nodeId);
+
+this._event=parentEvent;
+this._childEvents=childEvents;
+}
+
+get type(){
+return BaseNode.TYPES.CPU;
+}
+
+
+
+
+get startTime(){
+return this._event.ts;
+}
+
+
+
+
+get endTime(){
+return this._event.ts+this._event.dur;
+}
+
+
+
+
+get event(){
+return this._event;
+}
+
+
+
+
+get childEvents(){
+return this._childEvents;
+}
+
+
+
+
+
+didPerformLayout(){
+return this._childEvents.some(evt=>evt.name==='Layout');
+}
+
+
+
+
+
+
+isEvaluateScriptFor(urls){
+return this._childEvents.some(evt=>{
+return evt.name==='EvaluateScript'&&
+!!evt.args.data&&!!evt.args.data.url&&
+urls.has(evt.args.data.url);
+});
+}
+
+
+
+
+cloneWithoutRelationships(){
+return new CPUNode(this._event,this._childEvents);
+}}
+
+
+module.exports=CPUNode;
+
+},{"./base-node":22}],24:[function(require,module,exports){
+
+
+
+
+
+'use strict';
+
+const BaseNode=require('./base-node');
+const NetworkRequest=require('../network-request');
+
+class NetworkNode extends BaseNode{
+
+
+
+constructor(networkRecord){
+super(networkRecord.requestId);
+
+this._record=networkRecord;
+}
+
+get type(){
+return BaseNode.TYPES.NETWORK;
+}
+
+
+
+
+get startTime(){
+return this._record.startTime*1000*1000;
+}
+
+
+
+
+get endTime(){
+return this._record.endTime*1000*1000;
+}
+
+
+
+
+get record(){
+return this._record;
+}
+
+
+
+
+get initiatorType(){
+return this._record.initiator&&this._record.initiator.type;
+}
+
+
+
+
+get fromDiskCache(){
+return!!this._record.fromDiskCache;
+}
+
+
+
+
+hasRenderBlockingPriority(){
+const priority=this._record.priority;
+const isScript=this._record.resourceType===NetworkRequest.TYPES.Script;
+const isDocument=this._record.resourceType===NetworkRequest.TYPES.Document;
+const isBlockingScript=priority==='High'&&isScript;
+const isBlockingHtmlImport=priority==='High'&&isDocument;
+return priority==='VeryHigh'||isBlockingScript||isBlockingHtmlImport;
+}
+
+
+
+
+cloneWithoutRelationships(){
+const node=new NetworkNode(this._record);
+node.setIsMainDocument(this._isMainDocument);
+return node;
+}}
+
+
+module.exports=NetworkNode;
+
+},{"../network-request":38,"./base-node":22}],25:[function(require,module,exports){
@@ -19838,7 +20089,7 @@ if(this._connectionsByRecord.has(record)){
return this._connectionsByRecord.get(record);
}
-const origin=String(record.parsedURL.securityOrigin());
+const origin=String(record.parsedURL.securityOrigin);
const connections=this._connectionsByOrigin.get(origin)||[];
@@ -19873,7 +20124,92 @@ this._connectionsInUse.delete(connection);
}};
-},{"./network-analyzer":27,"./tcp-connection":29}],27:[function(require,module,exports){
+},{"./network-analyzer":27,"./tcp-connection":29}],26:[function(require,module,exports){
+
+
+
+
+
+'use strict';
+
+
+
+
+
+
+const DNS_RESOLUTION_RTT_MULTIPLIER=2;
+
+class DNSCache{
+
+
+
+constructor(options){
+this._options=Object.assign(
+{
+rtt:undefined},
+
+options);
+
+
+if(!this._options.rtt){
+throw new Error('Cannot create DNS cache with no rtt');
+}
+
+this._rtt=this._options.rtt;
+
+this._resolvedDomainNames=new Map();
+}
+
+
+
+
+
+
+getTimeUntilResolution(request,options){
+const{requestedAt=0,shouldUpdateCache=false}=options||{};
+
+const domain=request.parsedURL.host;
+const cacheEntry=this._resolvedDomainNames.get(domain);
+let timeUntilResolved=this._rtt*DNSCache.RTT_MULTIPLIER;
+if(cacheEntry){
+const timeUntilCachedIsResolved=Math.max(cacheEntry.resolvedAt-requestedAt,0);
+timeUntilResolved=Math.min(timeUntilCachedIsResolved,timeUntilResolved);
+}
+
+const resolvedAt=requestedAt+timeUntilResolved;
+if(shouldUpdateCache)this._updateCacheResolvedAtIfNeeded(request,resolvedAt);
+
+return timeUntilResolved;
+}
+
+
+
+
+
+_updateCacheResolvedAtIfNeeded(request,resolvedAt){
+const domain=request.parsedURL.host;
+const cacheEntry=this._resolvedDomainNames.get(domain)||{resolvedAt};
+cacheEntry.resolvedAt=Math.min(cacheEntry.resolvedAt,resolvedAt);
+this._resolvedDomainNames.set(domain,cacheEntry);
+}
+
+
+
+
+
+
+
+
+setResolvedAt(domain,resolvedAt){
+this._resolvedDomainNames.set(domain,{resolvedAt});
+}}
+
+
+DNSCache.RTT_MULTIPLIER=DNS_RESOLUTION_RTT_MULTIPLIER;
+
+module.exports=DNSCache;
+
+},{}],27:[function(require,module,exports){
@@ -19882,7 +20218,7 @@ this._connectionsInUse.delete(connection);
'use strict';
const INITIAL_CWD=14*1024;
-const WebInspector=require('../../web-inspector');
+const NetworkRequest=require('../../network-request');
class NetworkAnalyzer{
@@ -19899,7 +20235,7 @@ return'__SUMMARY__';
static groupByOrigin(records){
const grouped=new Map();
records.forEach(item=>{
-const key=item.parsedURL.securityOrigin();
+const key=item.parsedURL.securityOrigin;
const group=grouped.get(key)||[];
group.push(item);
grouped.set(key,group);
@@ -19953,7 +20289,7 @@ for(const[origin,originRecords]of groupedByOrigin.entries()){
let originEstimates=[];
for(const record of originRecords){
-const timing=record._timing;
+const timing=record.timing;
if(!timing)continue;
const value=iteratee({
@@ -20056,7 +20392,7 @@ if(!Number.isFinite(timing.receiveHeadersEnd)||timing.receiveHeadersEnd<0)return
if(!Number.isFinite(timing.sendEnd)||timing.sendEnd<0)return;
const ttfb=timing.receiveHeadersEnd-timing.sendEnd;
-const origin=record.parsedURL.securityOrigin();
+const origin=record.parsedURL.securityOrigin;
const rtt=rttByOrigin.get(origin)||rttByOrigin.get(NetworkAnalyzer.SUMMARY)||0;
return Math.max(ttfb-rtt,0);
});
@@ -20203,8 +20539,8 @@ return NetworkAnalyzer.summarize(estimatesByOrigin);
static findMainDocument(records){
-const documentRequests=records.filter(record=>record._resourceType===
-WebInspector.resourceTypes.Document);
+const documentRequests=records.filter(record=>record.resourceType===
+NetworkRequest.TYPES.Document);
return documentRequests.sort((a,b)=>a.startTime-b.startTime)[0];
}}
@@ -20219,7 +20555,7 @@ module.exports=NetworkAnalyzer;
-},{"../../web-inspector":47}],28:[function(require,module,exports){
+},{"../../network-request":38}],28:[function(require,module,exports){
@@ -20227,14 +20563,17 @@ module.exports=NetworkAnalyzer;
'use strict';
-const Node=require('../node');
-const NetworkNode=require('../network-node');
-const CpuNode=require('../cpu-node');
+const BaseNode=require('../base-node');
const TcpConnection=require('./tcp-connection');
const ConnectionPool=require('./connection-pool');
+const DNSCache=require('./dns-cache');
const mobile3G=require('../../../config/constants').throttling.mobile3G;
+
+
+
+
const DEFAULT_MAXIMUM_CONCURRENT_REQUESTS=10;
const DEFAULT_LAYOUT_TASK_MULTIPLIER=0.5;
@@ -20248,6 +20587,9 @@ InProgress:2,
Complete:3};
+
+const ALL_SIMULATION_NODE_TIMINGS=new Map();
+
class Simulator{
@@ -20278,9 +20620,12 @@ this._layoutTaskMultiplier=this._cpuSlowdownMultiplier*this._options.layoutTaskM
this._flexibleOrdering=false;
+
this._nodeTimings=new Map();
+
this._numberInProgressByType=new Map();
this._nodes={};
+this._dns=new DNSCache({rtt:this._rtt});
this._connectionPool=null;
}
@@ -20292,7 +20637,7 @@ _initializeConnectionPool(graph){
const records=[];
graph.getRootNode().traverse(node=>{
-if(node.type===Node.TYPES.NETWORK){
+if(node.type===BaseNode.TYPES.NETWORK){
records.push(node.record);
}
});
@@ -20335,6 +20680,16 @@ this._nodeTimings.set(node,timingData);
+_getTimingData(node){
+const timingData=this._nodeTimings.get(node);
+if(!timingData)throw new Error(`Unable to get timing data for node ${node.id}`);
+return timingData;
+}
+
+
+
+
+
_markNodeAsReadyToStart(node,queuedTime){
this._nodes[NodeState.ReadyToStart].add(node);
this._nodes[NodeState.NotReadyToStart].delete(node);
@@ -20388,7 +20743,7 @@ ignoreConnectionReused:this._flexibleOrdering});
_startNodeIfPossible(node,totalElapsedTime){
-if(node.type===Node.TYPES.CPU){
+if(node.type===BaseNode.TYPES.CPU){
if(this._numberInProgress(node.type)===0){
this._markNodeAsInProgress(node,totalElapsedTime);
@@ -20398,15 +20753,14 @@ this._setTimingData(node,{timeElapsed:0});
return;
}
-if(node.type!==Node.TYPES.NETWORK)throw new Error('Unsupported');
+if(node.type!==BaseNode.TYPES.NETWORK)throw new Error('Unsupported');
-const networkNode=node;
-if(!networkNode.fromDiskCache){
+if(!node.fromDiskCache){
const numberOfActiveRequests=this._numberInProgress(node.type);
if(numberOfActiveRequests>=this._maximumConcurrentRequests)return;
-const connection=this._acquireConnection(networkNode.record);
+const connection=this._acquireConnection(node.record);
if(!connection)return;
}
@@ -20434,9 +20788,9 @@ connection.setThroughput(this._throughput/this._nodes[NodeState.InProgress].size
_estimateTimeRemaining(node){
-if(node.type===Node.TYPES.CPU){
+if(node.type===BaseNode.TYPES.CPU){
return this._estimateCPUTimeRemaining(node);
-}else if(node.type===Node.TYPES.NETWORK){
+}else if(node.type===BaseNode.TYPES.NETWORK){
return this._estimateNetworkTimeRemaining(node);
}else{
throw new Error('Unsupported');
@@ -20448,7 +20802,7 @@ throw new Error('Unsupported');
_estimateCPUTimeRemaining(cpuNode){
-const timingData=this._nodeTimings.get(cpuNode);
+const timingData=this._getTimingData(cpuNode);
const multiplier=cpuNode.didPerformLayout()?
this._layoutTaskMultiplier:
this._cpuSlowdownMultiplier;
@@ -20466,20 +20820,26 @@ return estimatedTimeElapsed;
_estimateNetworkTimeRemaining(networkNode){
-const timingData=this._nodeTimings.get(networkNode);
+const record=networkNode.record;
+const timingData=this._getTimingData(networkNode);
let timeElapsed=0;
if(networkNode.fromDiskCache){
-const sizeInMb=(networkNode.record._resourceSize||0)/1024/1024;
+const sizeInMb=(record.resourceSize||0)/1024/1024;
timeElapsed=8+20*sizeInMb-timingData.timeElapsed;
}else{
-const connection=this._acquireConnection(networkNode.record);
+const connection=this._acquireConnection(record);
+const dnsResolutionTime=this._dns.getTimeUntilResolution(record,{
+requestedAt:timingData.startTime,
+shouldUpdateCache:true});
+
+const timeAlreadyElapsed=timingData.timeElapsed;
const calculation=connection.simulateDownloadUntil(
-networkNode.record.transferSize-timingData.bytesDownloaded,
-{timeAlreadyElapsed:timingData.timeElapsed,maximumTimeToElapse:Infinity});
+record.transferSize-timingData.bytesDownloaded,
+{timeAlreadyElapsed,dnsResolutionTime,maximumTimeToElapse:Infinity});
timeElapsed=calculation.timeElapsed;
@@ -20510,25 +20870,28 @@ return minimumTime;
_updateProgressMadeInTimePeriod(node,timePeriodLength,totalElapsedTime){
-const timingData=this._nodeTimings.get(node);
+const timingData=this._getTimingData(node);
const isFinished=timingData.estimatedTimeElapsed===timePeriodLength;
-const networkNode=node;
-
-if(node.type===Node.TYPES.CPU||networkNode.fromDiskCache){
+if(node.type===BaseNode.TYPES.CPU||node.fromDiskCache){
return isFinished?
this._markNodeAsComplete(node,totalElapsedTime):
timingData.timeElapsed+=timePeriodLength;
}
-if(node.type!==Node.TYPES.NETWORK)throw new Error('Unsupported');
+if(node.type!==BaseNode.TYPES.NETWORK)throw new Error('Unsupported');
-const record=networkNode.record;
+const record=node.record;
const connection=this._acquireConnection(record);
+const dnsResolutionTime=this._dns.getTimeUntilResolution(record,{
+requestedAt:timingData.startTime,
+shouldUpdateCache:true});
+
const calculation=connection.simulateDownloadUntil(
record.transferSize-timingData.bytesDownloaded,
{
+dnsResolutionTime,
timeAlreadyElapsed:timingData.timeElapsed,
maximumTimeToElapse:timePeriodLength-timingData.timeElapsedOvershoot});
@@ -20548,6 +20911,20 @@ timingData.bytesDownloaded+=calculation.bytesDownloaded;
}
}
+_computeFinalNodeTimings(){
+
+const nodeTimings=new Map();
+for(const[node,timing]of this._nodeTimings){
+nodeTimings.set(node,{
+startTime:timing.startTime,
+endTime:timing.endTime,
+duration:timing.endTime-timing.startTime});
+
+}
+
+return nodeTimings;
+}
+
@@ -20569,13 +20946,18 @@ return this._options;
simulate(graph,options){
-if(Node.hasCycle(graph)){
+if(BaseNode.hasCycle(graph)){
throw new Error('Cannot simulate graph with cycle');
}
-options=Object.assign({flexibleOrdering:false},options);
+options=Object.assign({
+label:undefined,
+flexibleOrdering:false},
+options);
+
this._flexibleOrdering=!!options.flexibleOrdering;
+this._dns=new DNSCache({rtt:this._rtt});
this._initializeConnectionPool(graph);
this._initializeAuxiliaryData();
@@ -20625,16 +21007,35 @@ this._updateProgressMadeInTimePeriod(node,minimumTime,totalElapsedTime);
}
}
+const nodeTimings=this._computeFinalNodeTimings();
+ALL_SIMULATION_NODE_TIMINGS.set(options.label||'unlabeled',nodeTimings);
+
return{
timeInMs:totalElapsedTime,
-nodeTimings:this._nodeTimings};
+nodeTimings};
+
+}
+
+static get ALL_NODE_TIMINGS(){
+return ALL_SIMULATION_NODE_TIMINGS;
}}
module.exports=Simulator;
-},{"../../../config/constants":8,"../cpu-node":23,"../network-node":24,"../node":25,"./connection-pool":26,"./tcp-connection":29}],29:[function(require,module,exports){
+
+
+
+
+
+
+
+
+
+
+
+},{"../../../config/constants":8,"../base-node":22,"./connection-pool":25,"./dns-cache":26,"./tcp-connection":29}],29:[function(require,module,exports){
@@ -20758,7 +21159,8 @@ return Object.assign(new TcpConnection(this._rtt,this._throughput),this);
simulateDownloadUntil(bytesToDownload,options){
-const{timeAlreadyElapsed=0,maximumTimeToElapse=Infinity}=options||{};
+const{timeAlreadyElapsed=0,maximumTimeToElapse=Infinity,dnsResolutionTime=0}=
+options||{};
if(this._warmed&&this._h2){
bytesToDownload-=this._h2OverflowBytesDownloaded;
@@ -20771,6 +21173,8 @@ let handshakeAndRequest=oneWayLatency;
if(!this._warmed){
handshakeAndRequest=
+dnsResolutionTime+
+
oneWayLatency+
oneWayLatency+
@@ -20838,6 +21242,7 @@ module.exports=TcpConnection;
+
},{}],30:[function(require,module,exports){
@@ -20952,7 +21357,8 @@ if(!resp.object.objectId){
return null;
}
return this.driver.getObjectProperty(resp.object.objectId,propName);
-});
+}).
+catch(()=>null);
}}
@@ -21025,10 +21431,7 @@ driver.sendCommand('Emulation.setDeviceMetricsOverride',NEXUS5X_EMULATION_METRIC
driver.sendCommand('Network.enable'),
driver.sendCommand('Network.setUserAgentOverride',NEXUS5X_USERAGENT),
-driver.sendCommand('Emulation.setEmitTouchEventsForMouse',{
-enabled:true,
-configuration:'mobile'})]);
-
+driver.sendCommand('Emulation.setTouchEmulationEnabled',{enabled:true})]);
}
@@ -21203,7 +21606,7 @@ LighthouseError.errors=ERRORS;
module.exports=LighthouseError;
-},{"./strings":41}],34:[function(require,module,exports){
+},{"./strings":42}],34:[function(require,module,exports){
@@ -21215,81 +21618,174 @@ module.exports=LighthouseError;
+function doExist(manifest){
+if(!manifest||!manifest.icons){
+return false;
+}
+if(manifest.icons.value.length===0){
+return false;
+}
+return true;
+}
+function sizeAtLeast(sizeRequirement,manifest){
+const iconValues=manifest.icons.value;
-function addFormattedCodeSnippet(listener){
-const handler=listener.handler?listener.handler.description:'...';
-const objectName=listener.objectName.toLowerCase().replace('#document','document');
-return Object.assign({
-pre:`${objectName}.addEventListener('${listener.type}', ${handler})`},
-listener);
+const flattenedSizes=[];
+iconValues.forEach(icon=>{
+if(icon.value.sizes.value){
+flattenedSizes.push(...icon.value.sizes.value);
}
+});
+
+return flattenedSizes.
+
+filter(size=>/\d+x\d+/.test(size)).
+filter(size=>{
+
+const sizeStrs=size.split(/x/i);
+
+const sizeNums=[parseFloat(sizeStrs[0]),parseFloat(sizeStrs[1])];
+
+const areIconsBigEnough=sizeNums[0]>=sizeRequirement&&sizeNums[1]>=sizeRequirement;
+const areIconsSquare=sizeNums[0]===sizeNums[1];
+return areIconsBigEnough&&areIconsSquare;
+});
+}
+module.exports={
+doExist,
+sizeAtLeast};
+},{}],35:[function(require,module,exports){
+'use strict';
+function convertNodeTimingsToTrace(nodeTimings){
+const traceEvents=[];
+const baseTs=1e9;
+const baseEvent={pid:1,tid:1,cat:'devtools.timeline'};
+const frame='A00001';
-function groupCodeSnippetsByLocation(listeners){
+const toMicroseconds=ms=>baseTs+ms*1000;
-const locToListenerMap=new Map();
+traceEvents.push(createFakeTracingStartedEvent());
+traceEvents.push({...createFakeTracingStartedEvent(),name:'TracingStartedInBrowser'});
-listeners.forEach(loc=>{
-const accPre=loc.pre.trim()+'\n\n';
-const simplifiedLoc={line:loc.line,col:loc.col,url:loc.url,type:loc.type,pre:''};
+let requestId=1;
+let lastEventEndTime=0;
+for(const[node,timing]of nodeTimings.entries()){
+lastEventEndTime=Math.max(lastEventEndTime,timing.endTime);
+if(node.type==='cpu'){
-const key=JSON.stringify(simplifiedLoc);
-const accListener=locToListenerMap.get(key)||simplifiedLoc;
-accListener.pre+=accPre;
-locToListenerMap.set(key,accListener);
-});
+const cpuNode=node;
+traceEvents.push(...createFakeTaskEvents(cpuNode,timing));
+}else{
+const networkNode=node;
-return[...locToListenerMap.values()];
+if(/^data/.test(networkNode.record.url))continue;
+traceEvents.push(...createFakeNetworkEvents(networkNode.record,timing));
+}
}
-module.exports={
-addFormattedCodeSnippet,
-groupCodeSnippetsByLocation};
+traceEvents.push(
+...createFakeTaskEvents(
-},{}],35:[function(require,module,exports){
+{childEvents:[],event:{}},
+{
+startTime:lastEventEndTime+1000,
+endTime:lastEventEndTime+1001}));
+return{traceEvents};
-'use strict';
+function createFakeTracingStartedEvent(){
+const argsData={
+frameTreeNodeId:1,
+sessionId:'1.1',
+page:frame,
+persistentIds:true,
+frames:[{frame,url:'about:blank',name:'',processId:1}]};
-function doExist(manifest){
-if(!manifest||!manifest.icons){
-return false;
+return{
+...baseEvent,
+ts:baseTs-1e5,
+ph:'I',
+s:'t',
+cat:'disabled-by-default-devtools.timeline',
+name:'TracingStartedInPage',
+args:{data:argsData},
+dur:0};
+
}
-if(manifest.icons.value.length===0){
-return false;
+
+
+
+
+
+
+function createFakeTaskEvents(cpuNode,timing){
+const argsData={
+url:'',
+frame,
+lineNumber:0,
+columnNumber:0};
+
+
+const eventTs=toMicroseconds(timing.startTime);
+
+
+const events=[
+{
+...baseEvent,
+ph:'X',
+name:'Task',
+ts:eventTs,
+dur:(timing.endTime-timing.startTime)*1000,
+args:{data:argsData}}];
+
+
+
+const nestedBaseTs=cpuNode.event.ts||0;
+const multiplier=(timing.endTime-timing.startTime)*1000/cpuNode.event.dur;
+
+const netReqEvents=new Set(['ResourceSendRequest','ResourceFinish',
+'ResourceReceiveResponse','ResourceReceivedData']);
+for(const event of cpuNode.childEvents){
+if(netReqEvents.has(event.name))continue;
+const ts=eventTs+(event.ts-nestedBaseTs)*multiplier;
+const newEvent={...event,...{pid:baseEvent.pid,tid:baseEvent.tid},ts};
+if(event.dur)newEvent.dur=event.dur*multiplier;
+events.push(newEvent);
}
-return true;
+
+return events;
}
@@ -21297,37 +21793,85 @@ return true;
-function sizeAtLeast(sizeRequirement,manifest){
+function createFakeNetworkEvents(record,timing){
+requestId++;
-const iconValues=manifest.icons.value;
-const flattenedSizes=[];
-iconValues.forEach(icon=>{
-if(icon.value.sizes.value){
-flattenedSizes.push(...icon.value.sizes.value);
-}
-});
+let{startTime,endTime}=timing;
+if(startTime===endTime)endTime+=0.3;
-return flattenedSizes.
+const requestData={requestId:requestId.toString(),frame};
-filter(size=>/\d+x\d+/.test(size)).
-filter(size=>{
+const baseRequestEvent={...baseEvent,ph:'I',s:'t',dur:0};
-const sizeStrs=size.split(/x/i);
+const sendRequestData={
+...requestData,
+requestMethod:record.requestMethod,
+url:record.url,
+priority:record.priority};
-const sizeNums=[parseFloat(sizeStrs[0]),parseFloat(sizeStrs[1])];
-const areIconsBigEnough=sizeNums[0]>=sizeRequirement&&sizeNums[1]>=sizeRequirement;
+const receiveResponseData={
+...requestData,
+statusCode:record.statusCode,
+mimeType:record.mimeType,
+encodedDataLength:record.transferSize,
+fromCache:record.fromDiskCache,
+fromServiceWorker:record.fetchedViaServiceWorker};
-const areIconsSquare=sizeNums[0]===sizeNums[1];
-return areIconsBigEnough&&areIconsSquare;
-});
+
+const resourceFinishData={
+...requestData,
+decodedBodyLength:record.resourceSize,
+didFail:!!record.failed,
+finishTime:endTime};
+
+
+
+const events=[
+{
+...baseRequestEvent,
+name:'ResourceSendRequest',
+ts:toMicroseconds(startTime),
+args:{data:sendRequestData}},
+
+{
+...baseRequestEvent,
+name:'ResourceFinish',
+ts:toMicroseconds(endTime),
+args:{data:resourceFinishData}}];
+
+
+
+if(!record.failed){
+events.push({
+...baseRequestEvent,
+name:'ResourceReceiveResponse',
+ts:toMicroseconds((startTime+endTime)/2),
+args:{data:receiveResponseData}});
+
+}
+
+return events;
+}
}
module.exports={
-doExist,
-sizeAtLeast};
+simulationNamesToIgnore:[
+'unlabeled',
+
+'optimisticFirstCPUIdle',
+'optimisticFlexFirstCPUIdle',
+'pessimisticFirstCPUIdle',
+'optimisticSpeedIndex',
+'optimisticFlexSpeedIndex',
+'pessimisticSpeedIndex',
+'optimisticEstimatedInputLatency',
+'optimisticFlexEstimatedInputLatency',
+'pessimisticEstimatedInputLatency'],
+
+convertNodeTimingsToTrace};
},{}],36:[function(require,module,exports){
@@ -21795,6 +22339,7 @@ module.exports=parse;
'use strict';
const NetworkManager=require('./web-inspector').NetworkManager;
+const NetworkRequest=require('./network-request');
const EventEmitter=require('events').EventEmitter;
const log=require('lighthouse-logger');
@@ -21806,21 +22351,17 @@ class NetworkRecorder extends EventEmitter{
-
-constructor(recordArray){
+constructor(){
super();
-this._records=recordArray;
-this.networkManager=NetworkManager.createWithFakeTarget();
-this.networkManager.addEventListener(
-this.EventTypes.RequestStarted,
-this.onRequestStarted.bind(this));
+this._records=[];
-this.networkManager.addEventListener(
-this.EventTypes.RequestFinished,
-this.onRequestFinished.bind(this));
+this._recordsById=new Map();
+}
+getRecords(){
+return Array.from(this._records);
}
@@ -21885,9 +22426,9 @@ this.emit('networkbusy');
static _isQUICAndFinished(record){
-const isQUIC=record._responseHeaders&&record._responseHeaders.
+const isQUIC=record.responseHeaders&&record.responseHeaders.
some(header=>header.name.toLowerCase()==='alt-svc'&&/quic/.test(header.value));
-const receivedHeaders=record._timing&&record._timing.receiveHeadersEnd>0;
+const receivedHeaders=record.timing&&record.timing.receiveHeadersEnd>0;
return!!(isQUIC&&receivedHeaders&&record.endTime);
}
@@ -21955,7 +22496,9 @@ return quietPeriods.filter(period=>period.start!==period.end);
onRequestStarted(request){
-this._records.push(request.data);
+this._records.push(request);
+this._recordsById.set(request.requestId,request);
+
this._emitNetworkStatus();
}
@@ -21966,7 +22509,7 @@ this._emitNetworkStatus();
onRequestFinished(request){
-this.emit('requestloaded',request.data);
+this.emit('requestloaded',request);
this._emitNetworkStatus();
}
@@ -21976,66 +22519,97 @@ this._emitNetworkStatus();
-
onRequestWillBeSent(data){
+const originalRequest=this._findRealRequest(data.requestId);
+
+if(!originalRequest){
+const request=new NetworkRequest();
+request.onRequestWillBeSent(data);
+this.onRequestStarted(request);
+return;
+}
-this.networkManager._dispatcher.requestWillBeSent(data.requestId,
-data.frameId,data.loaderId,data.documentURL,data.request,
-data.timestamp,data.wallTime,data.initiator,data.redirectResponse,
-data.type);
+
+if(!data.redirectResponse){
+return;
+}
+
+
+
+const modifiedData={
+...data,
+
+
+initiator:originalRequest.initiator,
+requestId:`${originalRequest.requestId}:redirect`};
+
+const redirectedRequest=new NetworkRequest();
+
+redirectedRequest.onRequestWillBeSent(modifiedData);
+originalRequest.onRedirectResponse(data);
+
+originalRequest.redirectDestination=redirectedRequest;
+redirectedRequest.redirectSource=originalRequest;
+
+
+this.onRequestStarted(redirectedRequest);
+this.onRequestFinished(originalRequest);
}
onRequestServedFromCache(data){
-this.networkManager._dispatcher.requestServedFromCache(data.requestId);
+const request=this._findRealRequest(data.requestId);
+if(!request)return;
+request.onRequestServedFromCache();
}
onResponseReceived(data){
-
-this.networkManager._dispatcher.responseReceived(data.requestId,
-data.frameId,data.loaderId,data.timestamp,data.type,data.response);
+const request=this._findRealRequest(data.requestId);
+if(!request)return;
+request.onResponseReceived(data);
}
onDataReceived(data){
-
-this.networkManager._dispatcher.dataReceived(data.requestId,data.timestamp,
-data.dataLength,data.encodedDataLength);
+const request=this._findRealRequest(data.requestId);
+if(!request)return;
+request.onDataReceived(data);
}
onLoadingFinished(data){
-
-this.networkManager._dispatcher.loadingFinished(data.requestId,
-data.timestamp,data.encodedDataLength);
+const request=this._findRealRequest(data.requestId);
+if(!request)return;
+request.onLoadingFinished(data);
+this.onRequestFinished(request);
}
onLoadingFailed(data){
-
-
-this.networkManager._dispatcher.loadingFailed(data.requestId,
-data.timestamp,data.type,data.errorText,data.canceled,
-data.blockedReason);
+const request=this._findRealRequest(data.requestId);
+if(!request)return;
+request.onLoadingFailed(data);
+this.onRequestFinished(request);
}
onResourceChangedPriority(data){
-this.networkManager._dispatcher.resourceChangedPriority(data.requestId,
-data.newPriority,data.timestamp);
+const request=this._findRealRequest(data.requestId);
+if(!request)return;
+request.onResourceChangedPriority(data);
}
@@ -22064,21 +22638,73 @@ default:return;}
+
+
+
+
+_findRealRequest(requestId){
+let request=this._recordsById.get(requestId);
+if(!request)return undefined;
+
+while(request.redirectDestination){
+request=request.redirectDestination;
+}
+
+return request;
+}
+
+
+
+
+
+
static recordsFromLogs(devtoolsLog){
+const networkRecorder=new NetworkRecorder();
+
+devtoolsLog.forEach(message=>networkRecorder.dispatch(message));
+
+
+const records=networkRecorder.getRecords();
+
+
+const recordsByURL=new Map();
+for(const record of records){
+if(recordsByURL.has(record.url))continue;
+recordsByURL.set(record.url,record);
+}
+
+
+for(const record of records){
+const stackFrames=record.initiator.stack&&record.initiator.stack.callFrames||[];
+const initiatorURL=record.initiator.url||stackFrames[0]&&stackFrames[0].url;
+const initiator=recordsByURL.get(initiatorURL)||record.redirectSource;
+if(initiator){
+record.setInitiatorRequest(initiator);
+}
+
+let finalRecord=record;
+while(finalRecord.redirectDestination)finalRecord=finalRecord.redirectDestination;
+if(finalRecord===record||finalRecord.redirects)continue;
+
+const redirects=[];
+for(
+let redirect=finalRecord.redirectSource;
+redirect;
+redirect=redirect.redirectSource)
+{
+redirects.unshift(redirect);
+}
+
+finalRecord.redirects=redirects;
+}
-const records=[];
-const nr=new NetworkRecorder(records);
-devtoolsLog.forEach(message=>{
-nr.dispatch(message);
-});
return records;
}}
module.exports=NetworkRecorder;
-},{"./web-inspector":47,"events":62,"lighthouse-logger":143}],38:[function(require,module,exports){
-
+},{"./network-request":38,"./web-inspector":47,"events":62,"lighthouse-logger":125}],38:[function(require,module,exports){
@@ -22092,72 +22718,314 @@ module.exports=NetworkRecorder;
+const URL=require('./url-shim');
+
+const SECURE_SCHEMES=['data','https','wss','blob','chrome','chrome-extension','about'];
+
+
+
-function captureJSCallUsage(funcRef,set){
-const __nativeError=window.__nativeError||Error;
-const originalFunc=funcRef;
-const originalPrepareStackTrace=__nativeError.prepareStackTrace;
-return function(...args){
-__nativeError.prepareStackTrace=function(error,structStackTrace){
+const RESOURCE_TYPES={
+XHR:'XHR',
+Fetch:'Fetch',
+EventSource:'EventSource',
+Script:'Script',
+Stylesheet:'Stylesheet',
+Image:'Image',
+Media:'Media',
+Font:'Font',
+Document:'Document',
+TextTrack:'TextTrack',
+WebSocket:'WebSocket',
+Other:'Other',
+Manifest:'Manifest'};
-const callFrame=structStackTrace[1];
-let url=callFrame.getFileName()||callFrame.getEvalOrigin();
-const line=callFrame.getLineNumber();
-const col=callFrame.getColumnNumber();
-const isEval=callFrame.isEval();
-let isExtension=false;
-const stackTrace=structStackTrace.slice(1).map(callsite=>callsite.toString());
+module.exports=class NetworkRequest{
+constructor(){
+this.requestId='';
+
+this.connectionId='0';
+this.connectionReused=false;
+this.url='';
+this.protocol='';
+this.isSecure=false;
+this.parsedURL={scheme:''};
+this.documentURL='';
+this.startTime=-1;
+this.endTime=-1;
-if(isEval){
-url=stackTrace[1];
+this.responseReceivedTime=-1;
+
+this.transferSize=0;
+this.resourceSize=0;
+this.fromDiskCache=false;
+this.fromMemoryCache=false;
+
+this.finished=false;
+this.requestMethod='';
+this.statusCode=-1;
+
+this.redirectSource=undefined;
+
+this.redirectDestination=undefined;
+
+this.redirects=undefined;
+this.failed=false;
+this.localizedFailDescription='';
+
+this.initiator={type:'other'};
+
+this.timing=undefined;
+
+this.resourceType=undefined;
+this.mimeType='';
+
+this.priority='Low';
+
+this.initiatorRequest=undefined;
+
+this.responseHeaders=[];
+
+this.fetchedViaServiceWorker=false;
+
+this.frameId='';
+this.isLinkPreload=false;
+}
+
+
+
+
+setInitiatorRequest(initiator){
+this.initiatorRequest=initiator;
}
-if(stackTrace[0].startsWith('<anonymous>')){
+onRequestWillBeSent(data){
+this.requestId=data.requestId;
+const url=new URL(data.request.url);
+this.url=data.request.url;
+this.documentURL=data.documentURL;
+this.parsedURL={
+scheme:url.protocol.split(':')[0],
-url=stackTrace[0];
-isExtension=true;
+host:url.hostname,
+securityOrigin:url.origin};
+
+this.isSecure=SECURE_SCHEMES.includes(this.parsedURL.scheme);
+
+this.startTime=data.timestamp;
+
+this.requestMethod=data.request.method;
+
+this.initiator=data.initiator;
+this.resourceType=data.type&&RESOURCE_TYPES[data.type];
+this.priority=data.request.initialPriority;
+
+this.frameId=data.frameId;
+this.isLinkPreload=data.initiator.type==='preload'||!!data.request.isLinkPreload;
}
+onRequestServedFromCache(){
+this.fromMemoryCache=true;
+}
-return{url,args,line,col,isEval,isExtension};
-};
-const e=new __nativeError(`__called ${funcRef.name}__`);
-set.add(JSON.stringify(e.stack));
+onResponseReceived(data){
+this._onResponse(data.response,data.timestamp,data.type);
+this.frameId=data.frameId;
+}
+
-__nativeError.prepareStackTrace=originalPrepareStackTrace;
+onDataReceived(data){
+this.resourceSize+=data.dataLength;
+if(data.encodedDataLength!==-1){
+this.transferSize+=data.encodedDataLength;
+}
+}
-return originalFunc.apply(this,args);
-};
+
+
+onLoadingFinished(data){
+
+if(this.finished)return;
+
+this.finished=true;
+this.endTime=data.timestamp;
+if(data.encodedDataLength>=0){
+this.transferSize=data.encodedDataLength;
+}
+
+this._updateResponseReceivedTimeIfNecessary();
+}
+
+
+
+
+onLoadingFailed(data){
+
+if(this.finished)return;
+
+this.finished=true;
+this.endTime=data.timestamp;
+
+this.failed=true;
+this.resourceType=data.type&&RESOURCE_TYPES[data.type];
+this.localizedFailDescription=data.errorText;
+
+this._updateResponseReceivedTimeIfNecessary();
+}
+
+
+
+
+onResourceChangedPriority(data){
+this.priority=data.newPriority;
}
+onRedirectResponse(data){
+if(!data.redirectResponse)throw new Error('Missing redirectResponse data');
+this._onResponse(data.redirectResponse,data.timestamp,data.type);
+this.resourceType=undefined;
+this.finished=true;
+this.endTime=data.timestamp;
+
+this._updateResponseReceivedTimeIfNecessary();
+}
+
+
+
+
+
+
+_onResponse(response,timestamp,resourceType){
+this.url=response.url;
+
+this.connectionId=String(response.connectionId);
+this.connectionReused=response.connectionReused;
+
+if(response.protocol)this.protocol=response.protocol;
+
+this.responseReceivedTime=timestamp;
+
+this.transferSize=response.encodedDataLength;
+if(typeof response.fromDiskCache==='boolean')this.fromDiskCache=response.fromDiskCache;
+
+this.statusCode=response.status;
+
+this.timing=response.timing;
+if(resourceType)this.resourceType=RESOURCE_TYPES[resourceType];
+this.mimeType=response.mimeType;
+this.responseHeaders=NetworkRequest._headersDictToHeadersArray(response.headers);
+
+this.fetchedViaServiceWorker=!!response.fromServiceWorker;
+
+if(this.fromMemoryCache)this.timing=undefined;
+if(this.timing)this._recomputeTimesWithResourceTiming(this.timing);
+}
+
+
+
+
+
+
+_recomputeTimesWithResourceTiming(timing){
+
+
+this.startTime=timing.requestTime;
+const headersReceivedTime=timing.requestTime+timing.receiveHeadersEnd/1000;
+if(!this.responseReceivedTime||this.responseReceivedTime<0){
+this.responseReceivedTime=headersReceivedTime;
+}
+
+this.responseReceivedTime=Math.min(this.responseReceivedTime,headersReceivedTime);
+this.responseReceivedTime=Math.max(this.responseReceivedTime,this.startTime);
+this.endTime=Math.max(this.endTime,this.responseReceivedTime);
+}
+
+
+
+
+
+_updateResponseReceivedTimeIfNecessary(){
+this.responseReceivedTime=Math.min(this.endTime,this.responseReceivedTime);
+}
+
+
+
+
+
+
+
+static getRequestIdForBackend(requestId){
+return requestId.replace(/(:redirect)+$/,'');
+}
+
+
+
+
+
+
+
+static _headersDictToHeadersArray(headersDict){
+const result=[];
+for(const name of Object.keys(headersDict)){
+const values=headersDict[name].split('\n');
+for(let i=0;i<values.length;++i){
+result.push({name:name,value:values[i]});
+}
+}
+return result;
+}
+
+static get TYPES(){
+return RESOURCE_TYPES;
+}};
+
+
+},{"./url-shim":"url"}],39:[function(require,module,exports){
+
+
+
+
+
+
+'use strict';
+
+
+
+
+
+
+
+
+
+
@@ -22222,13 +23090,12 @@ resolve(timeSinceLongTask);
}
module.exports={
-captureJSCallUsage,
wrapRuntimeEvalErrorInBrowser,
registerPerformanceObserverInPage,
checkTimeSinceLastLongTask};
-},{}],39:[function(require,module,exports){
+},{}],40:[function(require,module,exports){
@@ -22257,6 +23124,7 @@ const SAMPLED_ERRORS=[
{pattern:/(IDLE_PERIOD|FMP_TOO_LATE)/,rate:0.1},
{pattern:/^NO_.*/,rate:0.1},
+{pattern:/Could not load stylesheet/,rate:0.01},
{pattern:/Failed to decode/,rate:0.1},
{pattern:/All image optimizations failed/,rate:0.1},
{pattern:/No.*resource with given/,rate:0.01},
@@ -22325,7 +23193,7 @@ return context;
module.exports=sentryDelegate;
-},{"lighthouse-logger":143,"raven":58}],40:[function(require,module,exports){
+},{"lighthouse-logger":125,"raven":58}],41:[function(require,module,exports){
@@ -22387,26 +23255,23 @@ return(1-erf(standardizedX))/2;
}
-module.exports={
-getLogNormalDistribution};
-},{}],41:[function(require,module,exports){
-'use strict';
+function linearInterpolation(x0,y0,x1,y1,x){
+const slope=(y1-y0)/(x1-x0);
+return y0+(x-x0)*slope;
+}
+
module.exports={
-didntCollectScreenshots:`Chrome didn't collect any screenshots during the page load. Please make sure there is content visible on the page, and then try re-running Lighthouse.`,
-badTraceRecording:`Something went wrong with recording the trace over your page load. Please run Lighthouse again.`,
-pageLoadTookTooLong:`Your page took too long to load. Please follow the opportunities in the report to reduce your page load time, and then try re-running Lighthouse.`,
-pageLoadFailed:`Your page failed to load. Verify that the URL is valid and re-run Lighthouse.`,
-internalChromeError:`An internal Chrome error occurred. Please restart Chrome and try re-running Lighthouse.`,
-requestContentTimeout:'Fetching resource content has exceeded the allotted time'};
+linearInterpolation,
+getLogNormalDistribution};
},{}],42:[function(require,module,exports){
@@ -22417,92 +23282,14 @@ requestContentTimeout:'Fetching resource content has exceeded the allotted time'
'use strict';
-const groupIdToName={
-loading:'Network request loading',
-parseHTML:'Parsing HTML & CSS',
-styleLayout:'Style & Layout',
-compositing:'Compositing',
-painting:'Paint',
-gpu:'GPU',
-scripting:'Script Evaluation',
-scriptParseCompile:'Script Parsing & Compile',
-scriptGC:'Garbage collection',
-other:'Other',
-images:'Images'};
-
-
-const taskToGroup={
-'Animation':groupIdToName.painting,
-'Async Task':groupIdToName.other,
-'Frame Start':groupIdToName.painting,
-'Frame Start (main thread)':groupIdToName.painting,
-'Cancel Animation Frame':groupIdToName.scripting,
-'Cancel Idle Callback':groupIdToName.scripting,
-'Compile Script':groupIdToName.scriptParseCompile,
-'Composite Layers':groupIdToName.compositing,
-'Console Time':groupIdToName.scripting,
-'Image Decode':groupIdToName.images,
-'Draw Frame':groupIdToName.painting,
-'Embedder Callback':groupIdToName.scripting,
-'Evaluate Script':groupIdToName.scripting,
-'Event':groupIdToName.scripting,
-'Animation Frame Fired':groupIdToName.scripting,
-'Fire Idle Callback':groupIdToName.scripting,
-'Function Call':groupIdToName.scripting,
-'DOM GC':groupIdToName.scriptGC,
-'GC Event':groupIdToName.scriptGC,
-'GPU':groupIdToName.gpu,
-'Hit Test':groupIdToName.compositing,
-'Invalidate Layout':groupIdToName.styleLayout,
-'JS Frame':groupIdToName.scripting,
-'Input Latency':groupIdToName.scripting,
-'Layout':groupIdToName.styleLayout,
-'Major GC':groupIdToName.scriptGC,
-'DOMContentLoaded event':groupIdToName.scripting,
-'First paint':groupIdToName.painting,
-'FMP':groupIdToName.painting,
-'FMP candidate':groupIdToName.painting,
-'Load event':groupIdToName.scripting,
-'Minor GC':groupIdToName.scriptGC,
-'Paint':groupIdToName.painting,
-'Paint Image':groupIdToName.images,
-'Paint Setup':groupIdToName.painting,
-'Parse Stylesheet':groupIdToName.parseHTML,
-'Parse HTML':groupIdToName.parseHTML,
-'Parse Script':groupIdToName.scriptParseCompile,
-'Other':groupIdToName.other,
-'Rasterize Paint':groupIdToName.painting,
-'Recalculate Style':groupIdToName.styleLayout,
-'Request Animation Frame':groupIdToName.scripting,
-'Request Idle Callback':groupIdToName.scripting,
-'Request Main Thread Frame':groupIdToName.painting,
-'Image Resize':groupIdToName.images,
-'Finish Loading':groupIdToName.loading,
-'Receive Data':groupIdToName.loading,
-'Receive Response':groupIdToName.loading,
-'Send Request':groupIdToName.loading,
-'Run Microtasks':groupIdToName.scripting,
-'Schedule Style Recalculation':groupIdToName.styleLayout,
-'Scroll':groupIdToName.compositing,
-'Task':groupIdToName.other,
-'Timer Fired':groupIdToName.scripting,
-'Install Timer':groupIdToName.scripting,
-'Remove Timer':groupIdToName.scripting,
-'Timestamp':groupIdToName.scripting,
-'Update Layer':groupIdToName.compositing,
-'Update Layer Tree':groupIdToName.compositing,
-'User Timing':groupIdToName.scripting,
-'Create WebSocket':groupIdToName.scripting,
-'Destroy WebSocket':groupIdToName.scripting,
-'Receive WebSocket Handshake':groupIdToName.scripting,
-'Send WebSocket Handshake':groupIdToName.scripting,
-'XHR Load':groupIdToName.scripting,
-'XHR Ready State Change':groupIdToName.scripting};
-
module.exports={
-groupIdToName,
-taskToGroup};
+didntCollectScreenshots:`Chrome didn't collect any screenshots during the page load. Please make sure there is content visible on the page, and then try re-running Lighthouse.`,
+badTraceRecording:`Something went wrong with recording the trace over your page load. Please run Lighthouse again.`,
+pageLoadTookTooLong:`Your page took too long to load. Please follow the opportunities in the report to reduce your page load time, and then try re-running Lighthouse.`,
+pageLoadFailed:`Your page failed to load. Verify that the URL is valid and re-run Lighthouse.`,
+internalChromeError:`An internal Chrome error occurred. Please restart Chrome and try re-running Lighthouse.`,
+requestContentTimeout:'Fetching resource content has exceeded the allotted time'};
},{}],43:[function(require,module,exports){
@@ -22513,132 +23300,113 @@ taskToGroup};
'use strict';
-const WebInspector=require('../web-inspector');
-const ConsoleQuieter=require('../console-quieter');
-const TimelineModelTreeView=
-require('devtools-timeline-model/lib/timeline-model-treeview.js')(WebInspector);
-class TimelineModel{
-constructor(events){
-this.init(events);
-}
-init(trace){
-this._tracingModel=
-new WebInspector.TracingModel(new WebInspector.TempFileBackingStorage('tracing'));
-this._timelineModel=
-new WebInspector.TimelineModel(WebInspector.TimelineUIUtils.visibleEventsFilter());
-let events;
-if(Array.isArray(trace)){
-events=trace;
-}
-if(typeof trace==='string'){
-events=JSON.parse(trace);
-}
-if(trace.hasOwnProperty('traceEvents')){
-events=trace.traceEvents;
-}
-this._tracingModel.reset();
+const taskGroups={
+parseHTML:{
+id:'',
+label:'Parse HTML & CSS',
+traceEventNames:['ParseHTML','ParseAuthorStyleSheet']},
-try{
-ConsoleQuieter.mute({prefix:'timelineModel'});
-this._tracingModel.addEvents(events);
-this._tracingModel.tracingComplete();
-this._timelineModel.setEvents(this._tracingModel);
-}finally{
-ConsoleQuieter.unmuteAndFlush();
-}
+styleLayout:{
+id:'',
+label:'Style & Layout',
+traceEventNames:[
+'ScheduleStyleRecalculation',
+'RecalculateStyles',
+'UpdateLayoutTree',
+'InvalidateLayout',
+'Layout']},
-return this;
-}
-
-_createAggregator(){
-return WebInspector.AggregatedTimelineTreeView.prototype._createAggregator();
-}
-
-timelineModel(){
-return this._timelineModel;
-}
-tracingModel(){
-return this._tracingModel;
-}
+paintCompositeRender:{
+id:'',
+label:'Rendering',
+traceEventNames:[
+'Animation',
+'RequestMainThreadFrame',
+'ActivateLayerTree',
+'DrawFrame',
+'HitTest',
+'PaintSetup',
+'Paint',
+'PaintImage',
+'Rasterize',
+'RasterTask',
+'ScrollLayer',
+'UpdateLayer',
+'UpdateLayerTree',
+'CompositeLayers']},
-topDown(){
-const filters=[];
-filters.push(WebInspector.TimelineUIUtils.visibleEventsFilter());
-filters.push(new WebInspector.ExcludeTopLevelFilter());
-const nonessentialEvents=[
-WebInspector.TimelineModel.RecordType.EventDispatch,
-WebInspector.TimelineModel.RecordType.FunctionCall,
-WebInspector.TimelineModel.RecordType.TimerFire];
-filters.push(new WebInspector.ExclusiveNameFilter(nonessentialEvents));
+scriptParseCompile:{
+id:'',
+label:'Script Parsing & Compilation',
+traceEventNames:['v8.compile','v8.compileModule','v8.parseOnBackground']},
-const topDown=WebInspector.TimelineProfileTree.buildTopDown(
-this._timelineModel.mainThreadEvents(),
-filters,0,Infinity,
-WebInspector.TimelineAggregator.eventId);
-return topDown;
-}
+scriptEvaluation:{
+id:'',
+label:'Script Evaluation',
+traceEventNames:[
+'EventDispatch',
+'EvaluateScript',
+'v8.evaluateModule',
+'FunctionCall',
+'TimerFire',
+'FireIdleCallback',
+'FireAnimationFrame',
+'RunMicrotasks',
+'V8.Execute']},
-bottomUp(){
-const topDown=this.topDown();
-const noGrouping=WebInspector.TimelineAggregator.GroupBy.None;
-const noGroupAggregator=this._createAggregator().groupFunction(noGrouping);
-return WebInspector.TimelineProfileTree.buildBottomUp(topDown,noGroupAggregator);
-}
+garbageCollection:{
+id:'',
+label:'Garbage Collection',
+traceEventNames:[
+'GCEvent',
+'MinorGC',
+'MajorGC',
+'ThreadState::performIdleLazySweep',
+'ThreadState::completeSweep',
+'BlinkGCMarking']},
+other:{
+id:'',
+label:'Other',
+traceEventNames:[
+'MessageLoop::RunTask',
+'TaskQueueManager::ProcessTaskFromWorkQueue',
+'ThreadControllerImpl::DoWork']}};
-bottomUpGroupBy(grouping){
-const topDown=this.topDown();
-const groupSetting=WebInspector.TimelineAggregator.GroupBy[grouping];
-const groupingAggregator=this._createAggregator().groupFunction(groupSetting);
-const bottomUpGrouped=
-WebInspector.TimelineProfileTree.buildBottomUp(topDown,groupingAggregator);
-new TimelineModelTreeView(bottomUpGrouped).sortingChanged('self','desc');
-return bottomUpGrouped;
-}
-
-frameModel(){
-const mapper=event=>WebInspector.TimelineUIUtils.eventStyle(event).category.name;
-const frameModel=new WebInspector.TimelineFrameModel(mapper);
-frameModel.addTraceEvents({},
-this._timelineModel.inspectedTargetEvents(),this._timelineModel.sessionId()||'');
-return frameModel;
+const taskNameToGroup={};
+for(const[groupId,group]of Object.entries(taskGroups)){
+group.id=groupId;
+for(const traceEventName of group.traceEventNames){
+taskNameToGroup[traceEventName]=group;
}
-
-
-filmStripModel(){
-return new WebInspector.FilmStripModel(this._tracingModel);
}
-interactionModel(){
-const irModel=new WebInspector.TimelineIRModel();
-irModel.populate(this._timelineModel);
-return irModel;
-}}
-
+module.exports={
+taskGroups,
+taskNameToGroup};
-module.exports=TimelineModel;
-},{"../console-quieter":22,"../web-inspector":47,"devtools-timeline-model/lib/timeline-model-treeview.js":135}],44:[function(require,module,exports){
+},{}],44:[function(require,module,exports){
@@ -22839,7 +23607,7 @@ return fakeEvents;
module.exports=Metrics;
-},{"lighthouse-logger":143}],45:[function(require,module,exports){
+},{"lighthouse-logger":125}],45:[function(require,module,exports){
@@ -22926,8 +23694,13 @@ module.exports=TraceParser;
const BASE_RESPONSE_LATENCY=16;
+
const SCHEDULABLE_TASK_TITLE='TaskQueueManager::ProcessTaskFromWorkQueue';
-const SCHEDULABLE_TASK_TITLE_ALT='ThreadControllerImpl::DoWork';
+
+const SCHEDULABLE_TASK_TITLE_ALT1='ThreadControllerImpl::DoWork';
+
+const SCHEDULABLE_TASK_TITLE_ALT2='ThreadControllerImpl::RunTask';
+const LHError=require('../errors');
class TraceProcessor{
@@ -23101,8 +23874,47 @@ return topLevelEvents;
+static findTracingStartedEvt(events){
+
+let startedInPageEvt;
+
+
+const startedInBrowserEvt=events.find(e=>e.name==='TracingStartedInBrowser');
+if(startedInBrowserEvt&&startedInBrowserEvt.args.data&&
+startedInBrowserEvt.args.data.frames){
+const mainFrame=startedInBrowserEvt.args.data.frames.find(frame=>!frame.parent);
+const pid=mainFrame&&mainFrame.processId;
+const threadNameEvt=events.find(e=>e.pid===pid&&e.ph==='M'&&
+e.cat==='__metadata'&&e.name==='thread_name'&&e.args.name==='CrRendererMain');
+startedInPageEvt=mainFrame&&threadNameEvt?
+Object.assign({},startedInBrowserEvt,{
+pid,tid:threadNameEvt.tid,name:'TracingStartedInPage',
+args:{data:{page:mainFrame.frame}}}):
+undefined;
+}
+
+
+if(!startedInPageEvt){
+
+
+startedInPageEvt=events.find(e=>e.name==='TracingStartedInPage');
+}
+
+if(!startedInPageEvt)throw new LHError(LHError.errors.NO_TRACING_STARTED);
+
+
+const frameId=startedInPageEvt.args.data.page;
+return{startedInPageEvt,frameId};
+}
+
+
+
+
+
static isScheduleableTask(evt){
-return evt.name===SCHEDULABLE_TASK_TITLE||evt.name===SCHEDULABLE_TASK_TITLE_ALT;
+return evt.name===SCHEDULABLE_TASK_TITLE||
+evt.name===SCHEDULABLE_TASK_TITLE_ALT1||
+evt.name===SCHEDULABLE_TASK_TITLE_ALT2;
}}
@@ -23115,7 +23927,7 @@ return evt.name===SCHEDULABLE_TASK_TITLE||evt.name===SCHEDULABLE_TASK_TITLE_ALT;
module.exports=TraceProcessor;
-},{}],47:[function(require,module,exports){
+},{"../errors":33}],47:[function(require,module,exports){
(function(global){
@@ -23220,66 +24032,13 @@ return this._moduleSettings[settingName];
};
-global.NetworkAgent={
-RequestMixedContentType:{
-Blockable:'blockable',
-OptionallyBlockable:'optionally-blockable',
-None:'none'},
-
-BlockedReason:{
-CSP:'csp',
-MixedContent:'mixed-content',
-Origin:'origin',
-Inspector:'inspector',
-Other:'other'},
-
-InitiatorType:{
-Other:'other',
-Parser:'parser',
-Redirect:'redirect',
-Script:'script'}};
-
-
-
-
-global.SecurityAgent={
-SecurityState:{
-Unknown:'unknown',
-Neutral:'neutral',
-Insecure:'insecure',
-Warning:'warning',
-Secure:'secure',
-Info:'info'}};
-
-
-
-global.PageAgent={
-ResourceType:{
-Document:'document',
-Stylesheet:'stylesheet',
-Image:'image',
-Media:'media',
-Font:'font',
-Script:'script',
-TextTrack:'texttrack',
-XHR:'xhr',
-Fetch:'fetch',
-EventSource:'eventsource',
-WebSocket:'websocket',
-Manifest:'manifest',
-Other:'other'}};
-
-
-
require('chrome-devtools-frontend/front_end/common/Object.js');
require('chrome-devtools-frontend/front_end/common/ParsedURL.js');
-require('chrome-devtools-frontend/front_end/common/ResourceType.js');
require('chrome-devtools-frontend/front_end/common/UIString.js');
+require('chrome-devtools-frontend/front_end/common/SegmentedRange.js');
require('chrome-devtools-frontend/front_end/platform/utilities.js');
require('chrome-devtools-frontend/front_end/sdk/Target.js');
require('chrome-devtools-frontend/front_end/sdk/TargetManager.js');
-require('chrome-devtools-frontend/front_end/sdk/NetworkManager.js');
-require('chrome-devtools-frontend/front_end/sdk/NetworkRequest.js');
WebInspector.targetManager={
@@ -23305,34 +24064,10 @@ WebInspector.ViewportDataGrid=function(){};
WebInspector.ViewportDataGridNode=function(){};
global.WorkerRuntime.Worker=function(){};
-require('chrome-devtools-frontend/front_end/common/SegmentedRange.js');
-require('chrome-devtools-frontend/front_end/bindings/TempFile.js');
-require('chrome-devtools-frontend/front_end/sdk/TracingModel.js');
-require('chrome-devtools-frontend/front_end/sdk/ProfileTreeModel.js');
-require('chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js');
-require('chrome-devtools-frontend/front_end/timeline_model/TimelineJSProfile.js');
-require('chrome-devtools-frontend/front_end/sdk/CPUProfileDataModel.js');
-require('chrome-devtools-frontend/front_end/timeline_model/LayerTreeModel.js');
-require('chrome-devtools-frontend/front_end/timeline_model/TimelineModel.js');
-require('chrome-devtools-frontend/front_end/ui_lazy/SortableDataGrid.js');
-require('chrome-devtools-frontend/front_end/timeline/TimelineTreeView.js');
-
require('chrome-devtools-frontend/front_end/common/TextUtils.js');
require('chrome-devtools-frontend/front_end/timeline/TimelineLoader.js');
-require('chrome-devtools-frontend/front_end/timeline_model/TimelineProfileTree.js');
-require('chrome-devtools-frontend/front_end/components_lazy/FilmStripModel.js');
-require('chrome-devtools-frontend/front_end/timeline_model/TimelineIRModel.js');
-require('chrome-devtools-frontend/front_end/timeline_model/TimelineFrameModel.js');
-
-
-WebInspector.DeferredTempFile=function(){};
-WebInspector.DeferredTempFile.prototype={
-write:function(){},
-finishWriting:function(){}};
-
-
WebInspector.ConsoleMessage=function(){};
WebInspector.ConsoleMessage.MessageSource={
@@ -23346,78 +24081,9 @@ Log:'log'};
-WebInspector.NetworkLog=function(target){
-this._requests=new Map();
-target.networkManager.addEventListener(
-WebInspector.NetworkManager.Events.RequestStarted,this._onRequestStarted,this);
-};
-
-WebInspector.NetworkLog.prototype={
-requestForURL:function(url){
-return this._requests.get(url)||null;
-},
-
-_onRequestStarted:function(event){
-const request=event.data;
-if(this._requests.has(request.url)){
-return;
-}
-this._requests.set(request.url,request);
-}};
-
-
-
require('chrome-devtools-frontend/front_end/common/Color.js');
-
-const Dispatcher=WebInspector.NetworkDispatcher;
-const origUpdateRequest=Dispatcher.prototype._updateNetworkRequestWithRequest;
-Dispatcher.prototype._updateNetworkRequestWithRequest=function(netRecord,request){
-origUpdateRequest.apply(this,arguments);
-netRecord.isLinkPreload=Boolean(request.isLinkPreload);
-netRecord._isLinkPreload=Boolean(request.isLinkPreload);
-};
-
-
-
-
-
-WebInspector.NetworkManager.createWithFakeTarget=function(){
-
-const fakeNetworkAgent={
-enable(){},
-getResponseBody(){
-throw new Error('Use driver.getRequestContent() for network request content');
-}};
-
-const fakeConsoleModel={
-addMessage(){},
-target(){}};
-
-const fakeTarget={
-_modelByConstructor:new Map(),
-get consoleModel(){
-return fakeConsoleModel;
-},
-networkAgent(){
-return fakeNetworkAgent;
-},
-registerNetworkDispatcher(){},
-model(){}};
-
-
-fakeTarget.networkManager=new WebInspector.NetworkManager(fakeTarget);
-fakeTarget.networkLog=new WebInspector.NetworkLog(fakeTarget);
-
-WebInspector.NetworkLog.fromTarget=()=>{
-return fakeTarget.networkLog;
-};
-
-return fakeTarget.networkManager;
-};
-
-
require('chrome-devtools-frontend/front_end/common/TextRange.js');
require('chrome-devtools-frontend/front_end/sdk/CSSMatchedStyles.js');
require('chrome-devtools-frontend/front_end/sdk/CSSMedia.js');
@@ -23440,7 +24106,7 @@ return WebInspector;
}();
}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{});
-},{"chrome-devtools-frontend/front_end/bindings/TempFile.js":99,"chrome-devtools-frontend/front_end/common/Color.js":100,"chrome-devtools-frontend/front_end/common/Object.js":101,"chrome-devtools-frontend/front_end/common/ParsedURL.js":102,"chrome-devtools-frontend/front_end/common/ResourceType.js":103,"chrome-devtools-frontend/front_end/common/SegmentedRange.js":104,"chrome-devtools-frontend/front_end/common/TextRange.js":105,"chrome-devtools-frontend/front_end/common/TextUtils.js":106,"chrome-devtools-frontend/front_end/common/UIString.js":107,"chrome-devtools-frontend/front_end/components_lazy/FilmStripModel.js":108,"chrome-devtools-frontend/front_end/platform/utilities.js":109,"chrome-devtools-frontend/front_end/sdk/CPUProfileDataModel.js":110,"chrome-devtools-frontend/front_end/sdk/CSSMatchedStyles.js":111,"chrome-devtools-frontend/front_end/sdk/CSSMedia.js":112,"chrome-devtools-frontend/front_end/sdk/CSSMetadata.js":113,"chrome-devtools-frontend/front_end/sdk/CSSProperty.js":114,"chrome-devtools-frontend/front_end/sdk/CSSRule.js":115,"chrome-devtools-frontend/front_end/sdk/CSSStyleDeclaration.js":116,"chrome-devtools-frontend/front_end/sdk/NetworkManager.js":117,"chrome-devtools-frontend/front_end/sdk/NetworkRequest.js":118,"chrome-devtools-frontend/front_end/sdk/ProfileTreeModel.js":119,"chrome-devtools-frontend/front_end/sdk/Target.js":120,"chrome-devtools-frontend/front_end/sdk/TargetManager.js":121,"chrome-devtools-frontend/front_end/sdk/TracingModel.js":122,"chrome-devtools-frontend/front_end/timeline/TimelineLoader.js":123,"chrome-devtools-frontend/front_end/timeline/TimelineTreeView.js":124,"chrome-devtools-frontend/front_end/timeline/TimelineUIUtils.js":125,"chrome-devtools-frontend/front_end/timeline_model/LayerTreeModel.js":126,"chrome-devtools-frontend/front_end/timeline_model/TimelineFrameModel.js":127,"chrome-devtools-frontend/front_end/timeline_model/TimelineIRModel.js":128,"chrome-devtools-frontend/front_end/timeline_model/TimelineJSProfile.js":129,"chrome-devtools-frontend/front_end/timeline_model/TimelineModel.js":130,"chrome-devtools-frontend/front_end/timeline_model/TimelineProfileTree.js":131,"chrome-devtools-frontend/front_end/ui_lazy/SortableDataGrid.js":132}],48:[function(require,module,exports){
+},{"chrome-devtools-frontend/front_end/common/Color.js":99,"chrome-devtools-frontend/front_end/common/Object.js":100,"chrome-devtools-frontend/front_end/common/ParsedURL.js":101,"chrome-devtools-frontend/front_end/common/SegmentedRange.js":102,"chrome-devtools-frontend/front_end/common/TextRange.js":103,"chrome-devtools-frontend/front_end/common/TextUtils.js":104,"chrome-devtools-frontend/front_end/common/UIString.js":105,"chrome-devtools-frontend/front_end/platform/utilities.js":106,"chrome-devtools-frontend/front_end/sdk/CSSMatchedStyles.js":107,"chrome-devtools-frontend/front_end/sdk/CSSMedia.js":108,"chrome-devtools-frontend/front_end/sdk/CSSMetadata.js":109,"chrome-devtools-frontend/front_end/sdk/CSSProperty.js":110,"chrome-devtools-frontend/front_end/sdk/CSSRule.js":111,"chrome-devtools-frontend/front_end/sdk/CSSStyleDeclaration.js":112,"chrome-devtools-frontend/front_end/sdk/Target.js":113,"chrome-devtools-frontend/front_end/sdk/TargetManager.js":114,"chrome-devtools-frontend/front_end/timeline/TimelineLoader.js":115}],48:[function(require,module,exports){
@@ -23970,7 +24636,8 @@ const URL=require('./lib/url-shim');
const Sentry=require('./lib/sentry');
const generateReport=require('./report/report-generator').generateReport;
-const Connection=require('./gather/connections/connection.js');
+
+
class Runner{
@@ -23989,19 +24656,6 @@ const settings=opts.config.settings;
const lighthouseRunWarnings=[];
-
-const rawRequestedUrl=opts.url;
-if(typeof rawRequestedUrl!=='string'||rawRequestedUrl.length===0){
-throw new Error(`You must provide a url to the runner. '${rawRequestedUrl}' provided.`);
-}
-
-let parsedURL;
-try{
-parsedURL=new URL(opts.url);
-}catch(e){
-throw new Error('The url provided should have a proper protocol and hostname.');
-}
-
const sentryContext=Sentry.getContext();
Sentry.captureBreadcrumb({
@@ -24012,26 +24666,37 @@ data:sentryContext&&sentryContext.extra});
-if(parsedURL.protocol!=='https:'&&parsedURL.hostname!=='localhost'){
-log.warn('Lighthouse','The URL provided should be on HTTPS');
-log.warn('Lighthouse','Performance stats will be skewed redirecting from HTTP to HTTPS.');
-}
-
-
-const requestedUrl=parsedURL.href;
-
-
let artifacts;
+let requestedUrl;
if(settings.auditMode&&!settings.gatherMode){
const path=Runner._getArtifactsPath(settings);
artifacts=await assetSaver.loadArtifacts(path);
+requestedUrl=artifacts.URL.requestedUrl;
+
+if(!requestedUrl){
+throw new Error('Cannot run audit mode on empty URL');
+}
+if(opts.url&&opts.url!==requestedUrl){
+throw new Error('Cannot run audit mode on different URL');
+}
}else{
+if(typeof opts.url!=='string'||opts.url.length===0){
+throw new Error(`You must provide a url to the runner. '${opts.url}' provided.`);
+}
+
+try{
+
+requestedUrl=new URL(opts.url).href;
+}catch(e){
+throw new Error('The url provided should have a proper protocol and hostname.');
+}
+
artifacts=await Runner._gatherArtifactsFromBrowser(requestedUrl,opts,connection);
if(settings.gatherMode){
@@ -24083,7 +24748,7 @@ runWarnings:lighthouseRunWarnings,
audits:resultsById,
configSettings:settings,
categories,
-categoryGroups:opts.config.groups,
+categoryGroups:opts.config.groups||undefined,
timing:{total:Date.now()-startTime}};
@@ -24161,7 +24826,7 @@ return auditResults;
static async _runAudit(auditDefn,artifacts,settings){
const audit=auditDefn.implementation;
-const status=`Evaluating: ${audit.meta.description}`;
+const status=`Evaluating: ${audit.meta.title}`;
log.log('status',status);
let auditResult;
@@ -24176,7 +24841,7 @@ const noTrace=artifactName==='traces'&&!artifacts.traces[Audit.DEFAULT_PASS];
if(noArtifact||noTrace){
log.warn('Runner',
-`${artifactName} gatherer, required by audit ${audit.meta.name}, did not run.`);
+`${artifactName} gatherer, required by audit ${audit.meta.id}, did not run.`);
throw new Error(`Required ${artifactName} gatherer did not run.`);
}
@@ -24193,7 +24858,7 @@ tags:{gatherer:artifactName},
level:'error'});
-log.warn('Runner',`${artifactName} gatherer, required by audit ${audit.meta.name},`+
+log.warn('Runner',`${artifactName} gatherer, required by audit ${audit.meta.id},`+
` encountered an error: ${artifactError.message}`);
@@ -24210,13 +24875,13 @@ const auditOptions=Object.assign({},audit.defaultOptions,auditDefn.options);
const product=await audit.audit(artifacts,{options:auditOptions,settings:settings});
auditResult=Audit.generateAuditResult(audit,product);
}catch(err){
-log.warn(audit.meta.name,`Caught exception: ${err.message}`);
+log.warn(audit.meta.id,`Caught exception: ${err.message}`);
if(err.fatal){
throw err;
}
-Sentry.captureException(err,{tags:{audit:audit.meta.name},level:'error'});
+Sentry.captureException(err,{tags:{audit:audit.meta.id},level:'error'});
const errorMessage=err.friendlyMessage?
`${err.friendlyMessage} (${err.message})`:
@@ -24243,8 +24908,9 @@ const ignoredFiles=[
const fileList=[
-...["accessibility","audit.js","bootup-time.js","byte-efficiency","content-width.js","critical-request-chains.js","deprecations.js","dobetterweb","errors-in-console.js","estimated-input-latency.js","first-contentful-paint.js","first-cpu-idle.js","first-meaningful-paint.js","font-display.js","image-aspect-ratio.js","interactive.js","is-on-https.js","load-fast-enough-for-pwa.js","mainthread-work-breakdown.js","manifest-short-name-length.js","manual","metrics.js","mixed-content.js","multi-check-audit.js","network-requests.js","predictive-perf.js","redirects-http.js","redirects.js","screenshot-thumbnails.js","seo","service-worker.js","speed-index.js","splash-screen.js","themed-omnibox.js","time-to-first-byte.js","user-timings.js","uses-rel-preconnect.js","uses-rel-preload.js","viewport.js","violation-audit.js","webapp-install-banner.js","without-javascript.js","works-offline.js"],
-...["appcache-manifest.js","dom-size.js","external-anchors-use-rel-noopener.js","geolocation-on-start.js","no-document-write.js","no-mutation-events.js","no-vulnerable-libraries.js","no-websql.js","notification-on-start.js","password-inputs-can-be-pasted-into.js","uses-http2.js","uses-passive-event-listeners.js"].map(f=>`dobetterweb/${f}`),
+...["accessibility","audit.js","bootup-time.js","byte-efficiency","content-width.js","critical-request-chains.js","deprecations.js","dobetterweb","errors-in-console.js","font-display.js","image-aspect-ratio.js","is-on-https.js","load-fast-enough-for-pwa.js","mainthread-work-breakdown.js","manifest-short-name-length.js","manual","metrics","metrics.js","mixed-content.js","multi-check-audit.js","network-requests.js","predictive-perf.js","redirects-http.js","redirects.js","screenshot-thumbnails.js","seo","service-worker.js","splash-screen.js","themed-omnibox.js","time-to-first-byte.js","user-timings.js","uses-rel-preconnect.js","uses-rel-preload.js","viewport.js","violation-audit.js","webapp-install-banner.js","without-javascript.js","works-offline.js"],
+...["appcache-manifest.js","doctype.js","dom-size.js","external-anchors-use-rel-noopener.js","geolocation-on-start.js","no-document-write.js","no-vulnerable-libraries.js","no-websql.js","notification-on-start.js","password-inputs-can-be-pasted-into.js","uses-http2.js","uses-passive-event-listeners.js"].map(f=>`dobetterweb/${f}`),
+...["estimated-input-latency.js","first-contentful-paint.js","first-cpu-idle.js","first-meaningful-paint.js","interactive.js","speed-index.js"].map(f=>`metrics/${f}`),
...["canonical.js","font-size.js","hreflang.js","http-status-code.js","is-crawlable.js","link-text.js","manual","meta-description.js","plugins.js","robots-txt.js"].map(f=>`seo/${f}`),
...["mobile-friendly.js","structured-data.js"].map(f=>`seo/manual/${f}`),
...["accesskeys.js","aria-allowed-attr.js","aria-required-attr.js","aria-required-children.js","aria-required-parent.js","aria-roles.js","aria-valid-attr-value.js","aria-valid-attr.js","audio-caption.js","axe-audit.js","button-name.js","bypass.js","color-contrast.js","definition-list.js","dlitem.js","document-title.js","duplicate-id.js","frame-title.js","html-has-lang.js","html-lang-valid.js","image-alt.js","input-image-alt.js","label.js","layout-table.js","link-name.js","list.js","listitem.js","manual","meta-refresh.js","meta-viewport.js","object-alt.js","tabindex.js","td-headers-attr.js","th-has-data-cells.js","valid-lang.js","video-caption.js","video-description.js"].
@@ -24268,7 +24934,7 @@ static getGathererList(){
const fileList=[
...["accessibility.js","cache-contents.js","chrome-console-messages.js","css-usage.js","dobetterweb","fonts.js","gatherer.js","html-without-javascript.js","http-redirect.js","image-usage.js","js-usage.js","manifest.js","mixed-content.js","offline.js","runtime-exceptions.js","scripts.js","seo","service-worker.js","start-url.js","theme-color.js","viewport-dimensions.js","viewport.js"],
...["canonical.js","crawlable-links.js","embedded-content.js","font-size.js","hreflang.js","meta-description.js","meta-robots.js","robots-txt.js"].map(f=>`seo/${f}`),
-...["all-event-listeners.js","anchors-with-no-rel-noopener.js","appcache.js","domstats.js","js-libraries.js","optimized-images.js","password-inputs-with-prevented-paste.js","response-compression.js","tags-blocking-first-paint.js","websql.js"].
+...["anchors-with-no-rel-noopener.js","appcache.js","doctype.js","domstats.js","js-libraries.js","optimized-images.js","password-inputs-with-prevented-paste.js","response-compression.js","tags-blocking-first-paint.js","websql.js"].
map(f=>`dobetterweb/${f}`)];
return fileList.filter(f=>/\.js$/.test(f)&&f!=='gatherer.js').sort();
@@ -24287,7 +24953,7 @@ const filenamesToSkip=[
const fileList=[
-...["computed-artifact.js","critical-request-chains.js","dtm-model.js","load-simulator.js","main-resource.js","manifest-values.js","metrics","network-analysis.js","network-records.js","network-throughput.js","page-dependency-graph.js","pushed-requests.js","screenshots.js","speedline.js","trace-of-tab.js"],
+...["computed-artifact.js","critical-request-chains.js","load-simulator.js","main-resource.js","main-thread-tasks.js","manifest-values.js","metrics","network-analysis.js","network-records.js","network-throughput.js","page-dependency-graph.js","pushed-requests.js","screenshots.js","speedline.js","trace-of-tab.js"],
...["estimated-input-latency.js","first-contentful-paint.js","first-cpu-idle.js","first-meaningful-paint.js","interactive.js","lantern-estimated-input-latency.js","lantern-first-contentful-paint.js","lantern-first-cpu-idle.js","lantern-first-meaningful-paint.js","lantern-interactive.js","lantern-metric.js","lantern-speed-index.js","metric.js","speed-index.js"].map(f=>`metrics/${f}`)];
@@ -24377,7 +25043,7 @@ return path.join(process.cwd(),'latest-run');
module.exports=Runner;
}).call(this,require('_process'),"/../lighthouse-core");
-},{"../package.json":154,"./audits/audit":2,"./gather/connections/connection.js":14,"./gather/driver.js":17,"./gather/gather-runner":18,"./lib/asset-saver":21,"./lib/sentry":39,"./lib/url-shim":"url","./report/report-generator":49,"./scoring":51,"_process":77,"lighthouse-logger":143,"lodash.isequal":144,"path":75}],51:[function(require,module,exports){
+},{"../package.json":136,"./audits/audit":2,"./gather/driver.js":17,"./gather/gather-runner":18,"./lib/asset-saver":21,"./lib/sentry":40,"./lib/url-shim":"url","./report/report-generator":49,"./scoring":51,"_process":77,"lighthouse-logger":125,"lodash.isequal":126,"path":75}],51:[function(require,module,exports){
@@ -24492,7 +25158,10 @@ const log=require('lighthouse-logger');
-window.runLighthouseForConnection=function(
+
+
+
+function runLighthouseForConnection(
connection,url,options,categoryIDs,
updateBadgeFn=function(){}){
const config=new Config({
@@ -24513,7 +25182,7 @@ catch(err=>{
updateBadgeFn();
throw err;
});
-};
+}
@@ -24522,26 +25191,45 @@ throw err;
-window.runLighthouseInWorker=function(port,url,options,categoryIDs){
+function runLighthouseInWorker(port,url,options,categoryIDs){
log.setLevel('info');
const connection=new RawProtocol(port);
-return window.runLighthouseForConnection(connection,url,options,categoryIDs);
-};
+return runLighthouseForConnection(connection,url,options,categoryIDs);
+}
-window.getDefaultCategories=function(){
+function getDefaultCategories(){
return Config.getCategories(defaultConfig);
-};
+}
-window.listenForStatus=function(listenCallback){
+
+function listenForStatus(listenCallback){
log.events.addListener('status',listenCallback);
-};
+}
+
+if(typeof module!=='undefined'&&module.exports){
+
+module.exports={
+runLighthouseForConnection,
+runLighthouseInWorker,
+getDefaultCategories,
+listenForStatus};
-},{"../../../lighthouse-core/config/config":7,"../../../lighthouse-core/config/default-config.js":9,"../../../lighthouse-core/gather/connections/raw":15,"../../../lighthouse-core/runner":50,"lighthouse-logger":143}],53:[function(require,module,exports){
+}
+
+if(typeof window!=='undefined'){
+
+
+window.runLighthouseInWorker=runLighthouseInWorker;
+
+window.listenForStatus=listenForStatus;
+}
+
+},{"../../../lighthouse-core/config/config":7,"../../../lighthouse-core/config/default-config.js":9,"../../../lighthouse-core/gather/connections/raw":15,"../../../lighthouse-core/runner":50,"lighthouse-logger":125}],53:[function(require,module,exports){
(function(global){
'use strict';
@@ -44032,600 +44720,6 @@ return langs;
-window.requestFileSystem=window.requestFileSystem||window.webkitRequestFileSystem;
-
-
-
-
-WebInspector.TempFile=function()
-{
-this._fileEntry=null;
-this._writer=null;
-};
-
-
-
-
-
-
-WebInspector.TempFile.create=function(dirPath,name)
-{
-var file=new WebInspector.TempFile();
-
-function requestTempFileSystem()
-{
-return new Promise(window.requestFileSystem.bind(window,window.TEMPORARY,10));
-}
-
-
-
-
-function getDirectoryEntry(fs)
-{
-return new Promise(fs.root.getDirectory.bind(fs.root,dirPath,{create:true}));
-}
-
-
-
-
-function getFileEntry(dir)
-{
-return new Promise(dir.getFile.bind(dir,name,{create:true}));
-}
-
-
-
-
-function createFileWriter(fileEntry)
-{
-file._fileEntry=fileEntry;
-return new Promise(fileEntry.createWriter.bind(fileEntry));
-}
-
-
-
-
-function truncateFile(writer)
-{
-if(!writer.length){
-file._writer=writer;
-return Promise.resolve(file);
-}
-
-
-
-
-
-function truncate(fulfill,reject)
-{
-writer.onwriteend=fulfill;
-writer.onerror=reject;
-writer.truncate(0);
-}
-
-function didTruncate()
-{
-file._writer=writer;
-writer.onwriteend=null;
-writer.onerror=null;
-return Promise.resolve(file);
-}
-
-function onTruncateError(e)
-{
-writer.onwriteend=null;
-writer.onerror=null;
-throw e;
-}
-
-return new Promise(truncate).then(didTruncate,onTruncateError);
-}
-
-return WebInspector.TempFile.ensureTempStorageCleared().
-then(requestTempFileSystem).
-then(getDirectoryEntry).
-then(getFileEntry).
-then(createFileWriter).
-then(truncateFile);
-};
-
-WebInspector.TempFile.prototype={
-
-
-
-
-write:function(strings,callback)
-{
-var blob=new Blob(strings,{type:"text/plain"});
-this._writer.onerror=function(e)
-{
-WebInspector.console.error("Failed to write into a temp file: "+e.target.error.message);
-callback(-1);
-};
-this._writer.onwriteend=function(e)
-{
-callback(e.target.length);
-};
-this._writer.write(blob);
-},
-
-finishWriting:function()
-{
-this._writer=null;
-},
-
-
-
-
-read:function(callback)
-{
-this.readRange(undefined,undefined,callback);
-},
-
-
-
-
-
-
-readRange:function(startOffset,endOffset,callback)
-{
-
-
-
-function didGetFile(file)
-{
-var reader=new FileReader();
-
-if(typeof startOffset==="number"||typeof endOffset==="number")
-file=file.slice(startOffset,endOffset);
-
-
-
-reader.onloadend=function(e)
-{
-callback(this.result);
-};
-reader.onerror=function(error)
-{
-WebInspector.console.error("Failed to read from temp file: "+error.message);
-};
-reader.readAsText(file);
-}
-function didFailToGetFile(error)
-{
-WebInspector.console.error("Failed to load temp file: "+error.message);
-callback(null);
-}
-this._fileEntry.file(didGetFile,didFailToGetFile);
-},
-
-
-
-
-
-copyToOutputStream:function(outputStream,delegate)
-{
-
-
-
-function didGetFile(file)
-{
-var reader=new WebInspector.ChunkedFileReader(file,10*1000*1000,delegate);
-reader.start(outputStream);
-}
-
-function didFailToGetFile(error)
-{
-WebInspector.console.error("Failed to load temp file: "+error.message);
-outputStream.close();
-}
-
-this._fileEntry.file(didGetFile,didFailToGetFile);
-},
-
-remove:function()
-{
-if(this._fileEntry)
-this._fileEntry.remove(function(){});
-}};
-
-
-
-
-
-
-
-WebInspector.DeferredTempFile=function(dirPath,name)
-{
-
-this._chunks=[];
-this._tempFile=null;
-this._isWriting=false;
-this._finishCallback=null;
-this._finishedWriting=false;
-this._callsPendingOpen=[];
-this._pendingReads=[];
-WebInspector.TempFile.create(dirPath,name).
-then(this._didCreateTempFile.bind(this),this._failedToCreateTempFile.bind(this));
-};
-
-WebInspector.DeferredTempFile.prototype={
-
-
-
-
-write:function(strings,callback)
-{
-if(this._finishCallback)
-throw new Error("No writes are allowed after close.");
-this._chunks.push({strings:strings,callback:callback||null});
-if(this._tempFile&&!this._isWriting)
-this._writeNextChunk();
-},
-
-
-
-
-finishWriting:function(callback)
-{
-this._finishCallback=callback;
-if(this._finishedWriting)
-callback(this._tempFile);else
-if(!this._isWriting&&!this._chunks.length)
-this._notifyFinished();
-},
-
-
-
-
-_failedToCreateTempFile:function(e)
-{
-WebInspector.console.error("Failed to create temp file "+e.code+" : "+e.message);
-this._notifyFinished();
-},
-
-
-
-
-_didCreateTempFile:function(tempFile)
-{
-this._tempFile=tempFile;
-var callsPendingOpen=this._callsPendingOpen;
-this._callsPendingOpen=null;
-for(var i=0;i<callsPendingOpen.length;++i)
-callsPendingOpen[i]();
-if(this._chunks.length)
-this._writeNextChunk();
-},
-
-_writeNextChunk:function()
-{
-
-if(!this._tempFile)
-return;
-var chunk=this._chunks.shift();
-this._isWriting=true;
-this._tempFile.write(chunk.strings,this._didWriteChunk.bind(this,chunk.callback));
-},
-
-
-
-
-
-_didWriteChunk:function(callback,size)
-{
-this._isWriting=false;
-if(size===-1){
-this._tempFile=null;
-this._notifyFinished();
-return;
-}
-if(callback)
-callback(size);
-if(this._chunks.length)
-this._writeNextChunk();else
-if(this._finishCallback)
-this._notifyFinished();
-},
-
-_notifyFinished:function()
-{
-this._finishedWriting=true;
-if(this._tempFile)
-this._tempFile.finishWriting();
-var chunks=this._chunks;
-this._chunks=[];
-for(var i=0;i<chunks.length;++i){
-if(chunks[i].callback)
-chunks[i].callback(-1);
-}
-if(this._finishCallback)
-this._finishCallback(this._tempFile);
-var pendingReads=this._pendingReads;
-this._pendingReads=[];
-for(var i=0;i<pendingReads.length;++i)
-pendingReads[i]();
-},
-
-
-
-
-
-
-readRange:function(startOffset,endOffset,callback)
-{
-if(!this._finishedWriting){
-this._pendingReads.push(this.readRange.bind(this,startOffset,endOffset,callback));
-return;
-}
-if(!this._tempFile){
-callback(null);
-return;
-}
-this._tempFile.readRange(startOffset,endOffset,callback);
-},
-
-
-
-
-
-copyToOutputStream:function(outputStream,delegate)
-{
-if(!this._finishedWriting){
-this._pendingReads.push(this.copyToOutputStream.bind(this,outputStream,delegate));
-return;
-}
-if(this._tempFile)
-this._tempFile.copyToOutputStream(outputStream,delegate);
-},
-
-remove:function()
-{
-if(this._callsPendingOpen){
-this._callsPendingOpen.push(this.remove.bind(this));
-return;
-}
-if(this._tempFile)
-this._tempFile.remove();
-this._tempFile=null;
-}};
-
-
-
-
-
-
-WebInspector.TempFile._clearTempStorage=function(fulfill,reject)
-{
-
-
-
-function handleError(event)
-{
-WebInspector.console.error(WebInspector.UIString("Failed to clear temp storage: %s",event.data));
-reject(event.data);
-}
-
-
-
-
-function handleMessage(event)
-{
-if(event.data.type==="tempStorageCleared"){
-if(event.data.error)
-WebInspector.console.error(event.data.error);else
-
-fulfill(undefined);
-return;
-}
-reject(event.data);
-}
-
-try{
-var worker=new WebInspector.Worker("temp_storage_shared_worker","TempStorageCleaner");
-worker.onerror=handleError;
-worker.onmessage=handleMessage;
-}catch(e){
-if(e.name==="URLMismatchError")
-console.log("Shared worker wasn't started due to url difference. "+e);else
-
-throw e;
-}
-};
-
-
-
-
-WebInspector.TempFile.ensureTempStorageCleared=function()
-{
-if(!WebInspector.TempFile._storageCleanerPromise)
-WebInspector.TempFile._storageCleanerPromise=new Promise(WebInspector.TempFile._clearTempStorage);
-return WebInspector.TempFile._storageCleanerPromise;
-};
-
-
-
-
-
-
-WebInspector.TempFileBackingStorage=function(dirName)
-{
-this._dirName=dirName;
-this.reset();
-};
-
-
-
-
-
-
-
-
-WebInspector.TempFileBackingStorage.Chunk;
-
-WebInspector.TempFileBackingStorage.prototype={
-
-
-
-
-appendString:function(string)
-{
-this._strings.push(string);
-this._stringsLength+=string.length;
-var flushStringLength=10*1024*1024;
-if(this._stringsLength>flushStringLength)
-this._flush(false);
-},
-
-
-
-
-
-
-appendAccessibleString:function(string)
-{
-this._flush(false);
-this._strings.push(string);
-var chunk=this._flush(true);
-
-
-
-
-
-
-function readString(chunk,file)
-{
-if(chunk.string)
-return Promise.resolve(chunk.string);
-
-console.assert(chunk.endOffset);
-if(!chunk.endOffset)
-return Promise.reject("Nor string nor offset to the string in the file were found.");
-
-
-
-
-
-function readRange(fulfill,reject)
-{
-
-file.readRange(chunk.startOffset,chunk.endOffset,fulfill);
-}
-
-return new Promise(readRange);
-}
-
-return readString.bind(null,chunk,this._file);
-},
-
-
-
-
-
-_flush:function(createChunk)
-{
-if(!this._strings.length)
-return null;
-
-var chunk=null;
-if(createChunk){
-console.assert(this._strings.length===1);
-chunk={
-string:this._strings[0],
-startOffset:0,
-endOffset:0};
-
-}
-
-
-
-
-
-
-function didWrite(chunk,fileSize)
-{
-if(fileSize===-1)
-return;
-if(chunk){
-chunk.startOffset=this._fileSize;
-chunk.endOffset=fileSize;
-chunk.string=null;
-}
-this._fileSize=fileSize;
-}
-
-this._file.write(this._strings,didWrite.bind(this,chunk));
-this._strings=[];
-this._stringsLength=0;
-return chunk;
-},
-
-
-
-
-finishWriting:function()
-{
-this._flush(false);
-this._file.finishWriting(function(){});
-},
-
-
-
-
-reset:function()
-{
-if(this._file)
-this._file.remove();
-this._file=new WebInspector.DeferredTempFile(this._dirName,String(Date.now()));
-
-
-
-this._strings=[];
-this._stringsLength=0;
-this._fileSize=0;
-},
-
-
-
-
-
-writeToStream:function(outputStream,delegate)
-{
-this._file.copyToOutputStream(outputStream,delegate);
-}};
-
-
-},{}],100:[function(require,module,exports){
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -45422,7 +45516,7 @@ format=cf.RGBA;
return format;
};
-},{}],101:[function(require,module,exports){
+},{}],100:[function(require,module,exports){
@@ -45643,7 +45737,7 @@ this.receiver=receiver;
this.method=method;
};
-},{}],102:[function(require,module,exports){
+},{}],101:[function(require,module,exports){
@@ -46006,317 +46100,7 @@ return parsedURL;
return null;
};
-},{}],103:[function(require,module,exports){
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-WebInspector.ResourceType=function(name,title,category,isTextType)
-{
-this._name=name;
-this._title=title;
-this._category=category;
-this._isTextType=isTextType;
-};
-
-WebInspector.ResourceType.prototype={
-
-
-
-name:function()
-{
-return this._name;
-},
-
-
-
-
-title:function()
-{
-return this._title;
-},
-
-
-
-
-category:function()
-{
-return this._category;
-},
-
-
-
-
-isTextType:function()
-{
-return this._isTextType;
-},
-
-
-
-
-isScript:function()
-{
-return this._name==="script"||this._name==="sm-script";
-},
-
-
-
-
-hasScripts:function()
-{
-return this.isScript()||this.isDocument();
-},
-
-
-
-
-isStyleSheet:function()
-{
-return this._name==="stylesheet"||this._name==="sm-stylesheet";
-},
-
-
-
-
-isDocument:function()
-{
-return this._name==="document";
-},
-
-
-
-
-isDocumentOrScriptOrStyleSheet:function()
-{
-return this.isDocument()||this.isScript()||this.isStyleSheet();
-},
-
-
-
-
-isFromSourceMap:function()
-{
-return this._name.startsWith("sm-");
-},
-
-
-
-
-
-toString:function()
-{
-return this._name;
-},
-
-
-
-
-canonicalMimeType:function()
-{
-if(this.isDocument())
-return"text/html";
-if(this.isScript())
-return"text/javascript";
-if(this.isStyleSheet())
-return"text/css";
-return"";
-}};
-
-
-
-
-
-
-
-WebInspector.ResourceCategory=function(title,shortTitle)
-{
-this.title=title;
-this.shortTitle=shortTitle;
-};
-
-WebInspector.resourceCategories={
-XHR:new WebInspector.ResourceCategory("XHR and Fetch","XHR"),
-Script:new WebInspector.ResourceCategory("Scripts","JS"),
-Stylesheet:new WebInspector.ResourceCategory("Stylesheets","CSS"),
-Image:new WebInspector.ResourceCategory("Images","Img"),
-Media:new WebInspector.ResourceCategory("Media","Media"),
-Font:new WebInspector.ResourceCategory("Fonts","Font"),
-Document:new WebInspector.ResourceCategory("Documents","Doc"),
-WebSocket:new WebInspector.ResourceCategory("WebSockets","WS"),
-Manifest:new WebInspector.ResourceCategory("Manifest","Manifest"),
-Other:new WebInspector.ResourceCategory("Other","Other")};
-
-
-
-
-
-
-WebInspector.resourceTypes={
-XHR:new WebInspector.ResourceType("xhr","XHR",WebInspector.resourceCategories.XHR,true),
-Fetch:new WebInspector.ResourceType("fetch","Fetch",WebInspector.resourceCategories.XHR,true),
-EventSource:new WebInspector.ResourceType("eventsource","EventSource",WebInspector.resourceCategories.XHR,true),
-Script:new WebInspector.ResourceType("script","Script",WebInspector.resourceCategories.Script,true),
-Stylesheet:new WebInspector.ResourceType("stylesheet","Stylesheet",WebInspector.resourceCategories.Stylesheet,true),
-Image:new WebInspector.ResourceType("image","Image",WebInspector.resourceCategories.Image,false),
-Media:new WebInspector.ResourceType("media","Media",WebInspector.resourceCategories.Media,false),
-Font:new WebInspector.ResourceType("font","Font",WebInspector.resourceCategories.Font,false),
-Document:new WebInspector.ResourceType("document","Document",WebInspector.resourceCategories.Document,true),
-TextTrack:new WebInspector.ResourceType("texttrack","TextTrack",WebInspector.resourceCategories.Other,true),
-WebSocket:new WebInspector.ResourceType("websocket","WebSocket",WebInspector.resourceCategories.WebSocket,false),
-Other:new WebInspector.ResourceType("other","Other",WebInspector.resourceCategories.Other,false),
-SourceMapScript:new WebInspector.ResourceType("sm-script","Script",WebInspector.resourceCategories.Script,false),
-SourceMapStyleSheet:new WebInspector.ResourceType("sm-stylesheet","Stylesheet",WebInspector.resourceCategories.Stylesheet,false),
-Manifest:new WebInspector.ResourceType("manifest","Manifest",WebInspector.resourceCategories.Manifest,true)};
-
-
-
-
-
-
-WebInspector.ResourceType.mimeFromURL=function(url)
-{
-var name=WebInspector.ParsedURL.extractName(url);
-if(WebInspector.ResourceType._mimeTypeByName.has(name)){
-return WebInspector.ResourceType._mimeTypeByName.get(name);
-}
-var ext=WebInspector.ParsedURL.extractExtension(url).toLowerCase();
-return WebInspector.ResourceType._mimeTypeByExtension.get(ext);
-};
-
-WebInspector.ResourceType._mimeTypeByName=new Map([
-
-["Cakefile","text/x-coffeescript"]]);
-
-
-WebInspector.ResourceType._mimeTypeByExtension=new Map([
-
-["js","text/javascript"],
-["css","text/css"],
-["html","text/html"],
-["htm","text/html"],
-["xml","application/xml"],
-["xsl","application/xml"],
-
-
-["asp","application/x-aspx"],
-["aspx","application/x-aspx"],
-["jsp","application/x-jsp"],
-
-
-["c","text/x-c++src"],
-["cc","text/x-c++src"],
-["cpp","text/x-c++src"],
-["h","text/x-c++src"],
-["m","text/x-c++src"],
-["mm","text/x-c++src"],
-
-
-["coffee","text/x-coffeescript"],
-
-
-["dart","text/javascript"],
-
-
-["ts","text/typescript"],
-["tsx","text/typescript"],
-
-
-["json","application/json"],
-["gyp","application/json"],
-["gypi","application/json"],
-
-
-["cs","text/x-csharp"],
-
-
-["java","text/x-java"],
-
-
-["less","text/x-less"],
-
-
-["php","text/x-php"],
-["phtml","application/x-httpd-php"],
-
-
-["py","text/x-python"],
-
-
-["sh","text/x-sh"],
-
-
-["scss","text/x-scss"],
-
-
-["vtt","text/vtt"],
-
-
-["ls","text/x-livescript"],
-
-
-["cljs","text/x-clojure"],
-["cljc","text/x-clojure"],
-["cljx","text/x-clojure"],
-
-
-["styl","text/x-styl"],
-
-
-["jsx","text/jsx"],
-
-
-["jpeg","image/jpeg"],
-["jpg","image/jpeg"],
-["svg","image/svg"],
-["gif","image/gif"],
-["webp","image/webp"],
-["png","image/png"],
-["ico","image/ico"],
-["tiff","image/tiff"],
-["tif","image/tif"],
-["bmp","image/bmp"],
-
-
-["ttf","font/opentype"],
-["otf","font/opentype"],
-["ttc","font/opentype"],
-["woff","application/font-woff"]]);
-
-
-},{}],104:[function(require,module,exports){
+},{}],102:[function(require,module,exports){
@@ -46430,7 +46214,7 @@ return merged;
}};
-},{}],105:[function(require,module,exports){
+},{}],103:[function(require,module,exports){
@@ -46777,7 +46561,7 @@ WebInspector.SourceEdit.comparator=function(edit1,edit2)
return WebInspector.TextRange.comparator(edit1.oldRange,edit2.oldRange);
};
-},{}],106:[function(require,module,exports){
+},{}],104:[function(require,module,exports){
@@ -47087,7 +46871,7 @@ WebInspector.TokenizerFactory.prototype={
createTokenizer:function(mimeType){}};
-},{}],107:[function(require,module,exports){
+},{}],105:[function(require,module,exports){
@@ -47199,163 +46983,7 @@ String.standardFormatters,"",WebInspector.UIStringFormat._append,this._tokenized
}};
-},{}],108:[function(require,module,exports){
-
-
-
-
-
-
-
-
-
-
-
-WebInspector.FilmStripModel=function(tracingModel,zeroTime)
-{
-this.reset(tracingModel,zeroTime);
-};
-
-WebInspector.FilmStripModel._category="disabled-by-default-devtools.screenshot";
-
-WebInspector.FilmStripModel.TraceEvents={
-CaptureFrame:"CaptureFrame",
-Screenshot:"Screenshot"};
-
-
-WebInspector.FilmStripModel.prototype={
-
-
-
-
-reset:function(tracingModel,zeroTime)
-{
-this._zeroTime=zeroTime||tracingModel.minimumRecordTime();
-this._spanTime=tracingModel.maximumRecordTime()-this._zeroTime;
-
-
-this._frames=[];
-var browserMain=WebInspector.TracingModel.browserMainThread(tracingModel);
-if(!browserMain)
-return;
-
-var events=browserMain.events();
-for(var i=0;i<events.length;++i){
-var event=events[i];
-if(event.startTime<this._zeroTime)
-continue;
-if(!event.hasCategory(WebInspector.FilmStripModel._category))
-continue;
-if(event.name===WebInspector.FilmStripModel.TraceEvents.CaptureFrame){
-var data=event.args["data"];
-if(data)
-this._frames.push(WebInspector.FilmStripModel.Frame._fromEvent(this,event,this._frames.length));
-}else if(event.name===WebInspector.FilmStripModel.TraceEvents.Screenshot){
-this._frames.push(WebInspector.FilmStripModel.Frame._fromSnapshot(this,event,this._frames.length));
-}
-}
-},
-
-
-
-
-frames:function()
-{
-return this._frames;
-},
-
-
-
-
-zeroTime:function()
-{
-return this._zeroTime;
-},
-
-
-
-
-spanTime:function()
-{
-return this._spanTime;
-},
-
-
-
-
-
-frameByTimestamp:function(timestamp)
-{
-var index=this._frames.upperBound(timestamp,(timestamp,frame)=>timestamp-frame.timestamp)-1;
-return index>=0?this._frames[index]:null;
-}};
-
-
-
-
-
-
-
-
-WebInspector.FilmStripModel.Frame=function(model,timestamp,index)
-{
-this._model=model;
-this.timestamp=timestamp;
-this.index=index;
-
-this._imageData=null;
-
-this._snapshot=null;
-};
-
-
-
-
-
-
-
-WebInspector.FilmStripModel.Frame._fromEvent=function(model,event,index)
-{
-var frame=new WebInspector.FilmStripModel.Frame(model,event.startTime,index);
-frame._imageData=event.args["data"];
-return frame;
-};
-
-
-
-
-
-
-
-WebInspector.FilmStripModel.Frame._fromSnapshot=function(model,snapshot,index)
-{
-var frame=new WebInspector.FilmStripModel.Frame(model,snapshot.startTime,index);
-frame._snapshot=snapshot;
-return frame;
-};
-
-WebInspector.FilmStripModel.Frame.prototype={
-
-
-
-model:function()
-{
-return this._model;
-},
-
-
-
-
-imageDataPromise:function()
-{
-if(this._imageData||!this._snapshot)
-return Promise.resolve(this._imageData);
-
-return this._snapshot.objectPromise();
-}};
-
-
-},{}],109:[function(require,module,exports){
+},{}],106:[function(require,module,exports){
@@ -48897,386 +48525,7 @@ equal:equal};
};
-},{}],110:[function(require,module,exports){
-
-
-
-
-
-
-
-
-
-
-WebInspector.CPUProfileNode=function(node,sampleTime)
-{
-var callFrame=node.callFrame||{
-
-functionName:node["functionName"],
-scriptId:node["scriptId"],
-url:node["url"],
-lineNumber:node["lineNumber"]-1,
-columnNumber:node["columnNumber"]-1};
-
-WebInspector.ProfileNode.call(this,callFrame);
-this.id=node.id;
-this.self=node.hitCount*sampleTime;
-this.positionTicks=node.positionTicks;
-
-this.deoptReason=node.deoptReason&&node.deoptReason!=="no reason"?node.deoptReason:null;
-};
-
-WebInspector.CPUProfileNode.prototype={
-__proto__:WebInspector.ProfileNode.prototype};
-
-
-
-
-
-
-
-WebInspector.CPUProfileDataModel=function(profile)
-{
-var isLegacyFormat=!!profile["head"];
-if(isLegacyFormat){
-
-this.profileStartTime=profile.startTime*1000;
-this.profileEndTime=profile.endTime*1000;
-this.timestamps=profile.timestamps;
-this._compatibilityConversionHeadToNodes(profile);
-}else{
-
-this.profileStartTime=profile.startTime/1000;
-this.profileEndTime=profile.endTime/1000;
-this.timestamps=this._convertTimeDeltas(profile);
-}
-this.samples=profile.samples;
-this.totalHitCount=0;
-this.profileHead=this._translateProfileTree(profile.nodes);
-WebInspector.ProfileTreeModel.call(this,this.profileHead);
-this._extractMetaNodes();
-if(this.samples){
-this._buildIdToNodeMap();
-this._sortSamples();
-this._normalizeTimestamps();
-}
-};
-
-WebInspector.CPUProfileDataModel.prototype={
-
-
-
-_compatibilityConversionHeadToNodes:function(profile)
-{
-if(!profile.head||profile.nodes)
-return;
-
-var nodes=[];
-convertNodesTree(profile.head);
-profile.nodes=nodes;
-delete profile.head;
-
-
-
-
-function convertNodesTree(node)
-{
-nodes.push(node);
-node.children=node.children.map(convertNodesTree);
-return node.id;
-}
-},
-
-
-
-
-
-_convertTimeDeltas:function(profile)
-{
-if(!profile.timeDeltas)
-return null;
-var lastTimeUsec=profile.startTime;
-var timestamps=new Array(profile.timeDeltas.length);
-for(var i=0;i<timestamps.length;++i){
-lastTimeUsec+=profile.timeDeltas[i];
-timestamps[i]=lastTimeUsec;
-}
-return timestamps;
-},
-
-
-
-
-
-_translateProfileTree:function(nodes)
-{
-
-
-
-
-function isNativeNode(node)
-{
-if(node.callFrame)
-return!!node.callFrame.url&&node.callFrame.url.startsWith("native ");
-return!!node.url&&node.url.startsWith("native ");
-}
-
-
-
-function buildChildrenFromParents(nodes)
-{
-if(nodes[0].children)
-return;
-nodes[0].children=[];
-for(var i=1;i<nodes.length;++i){
-var node=nodes[i];
-var parentNode=nodeByIdMap.get(node.parent);
-if(parentNode.children)
-parentNode.children.push(node.id);else
-
-parentNode.children=[node.id];
-}
-}
-
-var nodeByIdMap=new Map();
-for(var i=0;i<nodes.length;++i){
-var node=nodes[i];
-nodeByIdMap.set(node.id,node);
-}
-buildChildrenFromParents(nodes);
-this.totalHitCount=nodes.reduce((acc,node)=>acc+node.hitCount,0);
-var sampleTime=(this.profileEndTime-this.profileStartTime)/this.totalHitCount;
-var keepNatives=!!WebInspector.moduleSetting("showNativeFunctionsInJSProfile").get();
-var root=nodes[0];
-
-var idMap=new Map([[root.id,root.id]]);
-var resultRoot=new WebInspector.CPUProfileNode(root,sampleTime);
-var parentNodeStack=root.children.map(()=>resultRoot);
-var sourceNodeStack=root.children.map(id=>nodeByIdMap.get(id));
-while(sourceNodeStack.length){
-var parentNode=parentNodeStack.pop();
-var sourceNode=sourceNodeStack.pop();
-if(!sourceNode.children)
-sourceNode.children=[];
-var targetNode=new WebInspector.CPUProfileNode(sourceNode,sampleTime);
-if(keepNatives||!isNativeNode(sourceNode)){
-parentNode.children.push(targetNode);
-parentNode=targetNode;
-}else{
-parentNode.self+=targetNode.self;
-}
-idMap.set(sourceNode.id,parentNode.id);
-parentNodeStack.push.apply(parentNodeStack,sourceNode.children.map(()=>parentNode));
-sourceNodeStack.push.apply(sourceNodeStack,sourceNode.children.map(id=>nodeByIdMap.get(id)));
-}
-if(this.samples)
-this.samples=this.samples.map(id=>idMap.get(id));
-return resultRoot;
-},
-
-_sortSamples:function()
-{
-var timestamps=this.timestamps;
-if(!timestamps)
-return;
-var samples=this.samples;
-var indices=timestamps.map((x,index)=>index);
-indices.sort((a,b)=>timestamps[a]-timestamps[b]);
-for(var i=0;i<timestamps.length;++i){
-var index=indices[i];
-if(index===i)
-continue;
-
-var savedTimestamp=timestamps[i];
-var savedSample=samples[i];
-var currentIndex=i;
-while(index!==i){
-samples[currentIndex]=samples[index];
-timestamps[currentIndex]=timestamps[index];
-currentIndex=index;
-index=indices[index];
-indices[currentIndex]=currentIndex;
-}
-samples[currentIndex]=savedSample;
-timestamps[currentIndex]=savedTimestamp;
-}
-},
-
-_normalizeTimestamps:function()
-{
-var timestamps=this.timestamps;
-if(!timestamps){
-
-
-var profileStartTime=this.profileStartTime;
-var interval=(this.profileEndTime-profileStartTime)/this.samples.length;
-timestamps=new Float64Array(this.samples.length+1);
-for(var i=0;i<timestamps.length;++i)
-timestamps[i]=profileStartTime+i*interval;
-this.timestamps=timestamps;
-return;
-}
-
-
-for(var i=0;i<timestamps.length;++i)
-timestamps[i]/=1000;
-var averageSample=(timestamps.peekLast()-timestamps[0])/(timestamps.length-1);
-
-this.timestamps.push(timestamps.peekLast()+averageSample);
-this.profileStartTime=timestamps[0];
-this.profileEndTime=timestamps.peekLast();
-},
-
-_buildIdToNodeMap:function()
-{
-
-this._idToNode=new Map();
-var idToNode=this._idToNode;
-var stack=[this.profileHead];
-while(stack.length){
-var node=stack.pop();
-idToNode.set(node.id,node);
-stack.push.apply(stack,node.children);
-}
-},
-
-_extractMetaNodes:function()
-{
-var topLevelNodes=this.profileHead.children;
-for(var i=0;i<topLevelNodes.length&&!(this.gcNode&&this.programNode&&this.idleNode);i++){
-var node=topLevelNodes[i];
-if(node.functionName==="(garbage collector)")
-this.gcNode=node;else
-if(node.functionName==="(program)")
-this.programNode=node;else
-if(node.functionName==="(idle)")
-this.idleNode=node;
-}
-},
-
-
-
-
-
-
-
-forEachFrame:function(openFrameCallback,closeFrameCallback,startTime,stopTime)
-{
-if(!this.profileHead||!this.samples)
-return;
-
-startTime=startTime||0;
-stopTime=stopTime||Infinity;
-var samples=this.samples;
-var timestamps=this.timestamps;
-var idToNode=this._idToNode;
-var gcNode=this.gcNode;
-var samplesCount=samples.length;
-var startIndex=timestamps.lowerBound(startTime);
-var stackTop=0;
-var stackNodes=[];
-var prevId=this.profileHead.id;
-var sampleTime=timestamps[samplesCount];
-var gcParentNode=null;
-
-if(!this._stackStartTimes)
-this._stackStartTimes=new Float64Array(this.maxDepth+2);
-var stackStartTimes=this._stackStartTimes;
-if(!this._stackChildrenDuration)
-this._stackChildrenDuration=new Float64Array(this.maxDepth+2);
-var stackChildrenDuration=this._stackChildrenDuration;
-
-for(var sampleIndex=startIndex;sampleIndex<samplesCount;sampleIndex++){
-sampleTime=timestamps[sampleIndex];
-if(sampleTime>=stopTime)
-break;
-var id=samples[sampleIndex];
-if(id===prevId)
-continue;
-var node=idToNode.get(id);
-var prevNode=idToNode.get(prevId);
-
-if(node===gcNode){
-
-gcParentNode=prevNode;
-openFrameCallback(gcParentNode.depth+1,gcNode,sampleTime);
-stackStartTimes[++stackTop]=sampleTime;
-stackChildrenDuration[stackTop]=0;
-prevId=id;
-continue;
-}
-if(prevNode===gcNode){
-
-var start=stackStartTimes[stackTop];
-var duration=sampleTime-start;
-stackChildrenDuration[stackTop-1]+=duration;
-closeFrameCallback(gcParentNode.depth+1,gcNode,start,duration,duration-stackChildrenDuration[stackTop]);
---stackTop;
-prevNode=gcParentNode;
-prevId=prevNode.id;
-gcParentNode=null;
-}
-
-while(node.depth>prevNode.depth){
-stackNodes.push(node);
-node=node.parent;
-}
-
-
-while(prevNode!==node){
-var start=stackStartTimes[stackTop];
-var duration=sampleTime-start;
-stackChildrenDuration[stackTop-1]+=duration;
-closeFrameCallback(prevNode.depth,prevNode,start,duration,duration-stackChildrenDuration[stackTop]);
---stackTop;
-if(node.depth===prevNode.depth){
-stackNodes.push(node);
-node=node.parent;
-}
-prevNode=prevNode.parent;
-}
-
-
-while(stackNodes.length){
-node=stackNodes.pop();
-openFrameCallback(node.depth,node,sampleTime);
-stackStartTimes[++stackTop]=sampleTime;
-stackChildrenDuration[stackTop]=0;
-}
-
-prevId=id;
-}
-
-if(idToNode.get(prevId)===gcNode){
-var start=stackStartTimes[stackTop];
-var duration=sampleTime-start;
-stackChildrenDuration[stackTop-1]+=duration;
-closeFrameCallback(gcParentNode.depth+1,node,start,duration,duration-stackChildrenDuration[stackTop]);
---stackTop;
-}
-
-for(var node=idToNode.get(prevId);node.parent;node=node.parent){
-var start=stackStartTimes[stackTop];
-var duration=sampleTime-start;
-stackChildrenDuration[stackTop-1]+=duration;
-closeFrameCallback(node.depth,node,start,duration,duration-stackChildrenDuration[stackTop]);
---stackTop;
-}
-},
-
-
-
-
-
-nodeByIndex:function(index)
-{
-return this._idToNode.get(this.samples[index])||null;
-},
-
-__proto__:WebInspector.ProfileTreeModel.prototype};
-
-
-},{}],111:[function(require,module,exports){
+},{}],107:[function(require,module,exports){
@@ -49722,7 +48971,7 @@ Active:"Active",
Overloaded:"Overloaded"};
-},{}],112:[function(require,module,exports){
+},{}],108:[function(require,module,exports){
@@ -49976,7 +49225,7 @@ return new WebInspector.CSSLocation(header,lineNumber,this.columnNumberInSource(
}};
-},{}],113:[function(require,module,exports){
+},{}],109:[function(require,module,exports){
@@ -50947,7 +50196,7 @@ WebInspector.CSSMetadata.Weight={
"zoom":200};
-},{}],114:[function(require,module,exports){
+},{}],110:[function(require,module,exports){
@@ -51249,7 +50498,7 @@ return this.setText(text,true,true);
}};
-},{}],115:[function(require,module,exports){
+},{}],111:[function(require,module,exports){
@@ -51575,7 +50824,7 @@ return this._cssModel.setKeyframeKey(styleSheetId,range,newKeyText);
__proto__:WebInspector.CSSRule.prototype};
-},{}],116:[function(require,module,exports){
+},{}],112:[function(require,module,exports){
@@ -51890,2337 +51139,7 @@ this.insertPropertyAt(this.allProperties.length,name,value,userCallback);
}};
-},{}],117:[function(require,module,exports){
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-WebInspector.NetworkManager=function(target)
-{
-WebInspector.SDKModel.call(this,WebInspector.NetworkManager,target);
-this._dispatcher=new WebInspector.NetworkDispatcher(this);
-this._target=target;
-this._networkAgent=target.networkAgent();
-target.registerNetworkDispatcher(this._dispatcher);
-if(WebInspector.moduleSetting("cacheDisabled").get())
-this._networkAgent.setCacheDisabled(true);
-if(WebInspector.moduleSetting("monitoringXHREnabled").get())
-this._networkAgent.setMonitoringXHREnabled(true);
-
-
-if(Runtime.queryParam("remoteFrontend")||Runtime.queryParam("ws"))
-this._networkAgent.enable(10000000,5000000);else
-
-this._networkAgent.enable();
-
-this._bypassServiceWorkerSetting=WebInspector.settings.createSetting("bypassServiceWorker",false);
-if(this._bypassServiceWorkerSetting.get())
-this._bypassServiceWorkerChanged();
-this._bypassServiceWorkerSetting.addChangeListener(this._bypassServiceWorkerChanged,this);
-
-WebInspector.moduleSetting("cacheDisabled").addChangeListener(this._cacheDisabledSettingChanged,this);
-};
-
-
-WebInspector.NetworkManager.Events={
-RequestStarted:Symbol("RequestStarted"),
-RequestUpdated:Symbol("RequestUpdated"),
-RequestFinished:Symbol("RequestFinished"),
-RequestUpdateDropped:Symbol("RequestUpdateDropped"),
-ResponseReceived:Symbol("ResponseReceived")};
-
-
-WebInspector.NetworkManager._MIMETypes={
-"text/html":{"document":true},
-"text/xml":{"document":true},
-"text/plain":{"document":true},
-"application/xhtml+xml":{"document":true},
-"image/svg+xml":{"document":true},
-"text/css":{"stylesheet":true},
-"text/xsl":{"stylesheet":true},
-"text/vtt":{"texttrack":true}};
-
-
-
-
-
-
-WebInspector.NetworkManager.fromTarget=function(target)
-{
-return target.model(WebInspector.NetworkManager);
-};
-
-
-WebInspector.NetworkManager.Conditions;
-
-WebInspector.NetworkManager.NoThrottlingConditions={title:WebInspector.UIString("No throttling"),download:-1,upload:-1,latency:0};
-
-WebInspector.NetworkManager.OfflineConditions={title:WebInspector.UIString("Offline"),download:0,upload:0,latency:0};
-
-
-
-
-
-
-WebInspector.NetworkManager._connectionType=function(conditions)
-{
-if(!conditions.download&&!conditions.upload)
-return NetworkAgent.ConnectionType.None;
-var types=WebInspector.NetworkManager._connectionTypes;
-if(!types){
-WebInspector.NetworkManager._connectionTypes=[];
-types=WebInspector.NetworkManager._connectionTypes;
-types.push(["2g",NetworkAgent.ConnectionType.Cellular2g]);
-types.push(["3g",NetworkAgent.ConnectionType.Cellular3g]);
-types.push(["4g",NetworkAgent.ConnectionType.Cellular4g]);
-types.push(["bluetooth",NetworkAgent.ConnectionType.Bluetooth]);
-types.push(["wifi",NetworkAgent.ConnectionType.Wifi]);
-types.push(["wimax",NetworkAgent.ConnectionType.Wimax]);
-}
-for(var type of types){
-if(conditions.title.toLowerCase().indexOf(type[0])!==-1)
-return type[1];
-}
-return NetworkAgent.ConnectionType.Other;
-};
-
-WebInspector.NetworkManager.prototype={
-
-
-
-
-inflightRequestForURL:function(url)
-{
-return this._dispatcher._inflightRequestsByURL[url];
-},
-
-
-
-
-_cacheDisabledSettingChanged:function(event)
-{
-var enabled=event.data;
-this._networkAgent.setCacheDisabled(enabled);
-},
-
-dispose:function()
-{
-WebInspector.moduleSetting("cacheDisabled").removeChangeListener(this._cacheDisabledSettingChanged,this);
-},
-
-
-
-
-bypassServiceWorkerSetting:function()
-{
-return this._bypassServiceWorkerSetting;
-},
-
-_bypassServiceWorkerChanged:function()
-{
-this._networkAgent.setBypassServiceWorker(this._bypassServiceWorkerSetting.get());
-},
-
-__proto__:WebInspector.SDKModel.prototype};
-
-
-
-
-
-
-WebInspector.NetworkDispatcher=function(manager)
-{
-this._manager=manager;
-this._inflightRequestsById={};
-this._inflightRequestsByURL={};
-};
-
-WebInspector.NetworkDispatcher.prototype={
-
-
-
-
-_headersMapToHeadersArray:function(headersMap)
-{
-var result=[];
-for(var name in headersMap){
-var values=headersMap[name].split("\n");
-for(var i=0;i<values.length;++i)
-result.push({name:name,value:values[i]});
-}
-return result;
-},
-
-
-
-
-
-_updateNetworkRequestWithRequest:function(networkRequest,request)
-{
-networkRequest.requestMethod=request.method;
-networkRequest.setRequestHeaders(this._headersMapToHeadersArray(request.headers));
-networkRequest.requestFormData=request.postData;
-networkRequest.setInitialPriority(request.initialPriority);
-networkRequest.mixedContentType=request.mixedContentType||NetworkAgent.RequestMixedContentType.None;
-},
-
-
-
-
-
-_updateNetworkRequestWithResponse:function(networkRequest,response)
-{
-if(response.url&&networkRequest.url!==response.url)
-networkRequest.url=response.url;
-networkRequest.mimeType=response.mimeType;
-networkRequest.statusCode=response.status;
-networkRequest.statusText=response.statusText;
-networkRequest.responseHeaders=this._headersMapToHeadersArray(response.headers);
-if(response.encodedDataLength>=0)
-networkRequest.setTransferSize(response.encodedDataLength);
-if(response.headersText)
-networkRequest.responseHeadersText=response.headersText;
-if(response.requestHeaders){
-networkRequest.setRequestHeaders(this._headersMapToHeadersArray(response.requestHeaders));
-networkRequest.setRequestHeadersText(response.requestHeadersText||"");
-}
-
-networkRequest.connectionReused=response.connectionReused;
-networkRequest.connectionId=String(response.connectionId);
-if(response.remoteIPAddress)
-networkRequest.setRemoteAddress(response.remoteIPAddress,response.remotePort||-1);
-
-if(response.fromServiceWorker)
-networkRequest.fetchedViaServiceWorker=true;
-
-if(response.fromDiskCache)
-networkRequest.setFromDiskCache();
-networkRequest.timing=response.timing;
-
-networkRequest.protocol=response.protocol;
-
-networkRequest.setSecurityState(response.securityState);
-
-if(!this._mimeTypeIsConsistentWithType(networkRequest)){
-var consoleModel=this._manager._target.consoleModel;
-consoleModel.addMessage(new WebInspector.ConsoleMessage(consoleModel.target(),WebInspector.ConsoleMessage.MessageSource.Network,
-WebInspector.ConsoleMessage.MessageLevel.Log,
-WebInspector.UIString("Resource interpreted as %s but transferred with MIME type %s: \"%s\".",networkRequest.resourceType().title(),networkRequest.mimeType,networkRequest.url),
-WebInspector.ConsoleMessage.MessageType.Log,
-"",
-0,
-0,
-networkRequest.requestId));
-}
-
-if(response.securityDetails)
-networkRequest.setSecurityDetails(response.securityDetails);
-},
-
-
-
-
-
-_mimeTypeIsConsistentWithType:function(networkRequest)
-{
-
-
-
-
-
-
-if(networkRequest.hasErrorStatusCode()||networkRequest.statusCode===304||networkRequest.statusCode===204)
-return true;
-
-var resourceType=networkRequest.resourceType();
-if(resourceType!==WebInspector.resourceTypes.Stylesheet&&
-resourceType!==WebInspector.resourceTypes.Document&&
-resourceType!==WebInspector.resourceTypes.TextTrack){
-return true;
-}
-
-if(!networkRequest.mimeType)
-return true;
-
-if(networkRequest.mimeType in WebInspector.NetworkManager._MIMETypes)
-return resourceType.name()in WebInspector.NetworkManager._MIMETypes[networkRequest.mimeType];
-
-return false;
-},
-
-
-
-
-
-
-
-resourceChangedPriority:function(requestId,newPriority,timestamp)
-{
-var networkRequest=this._inflightRequestsById[requestId];
-if(networkRequest)
-networkRequest.setPriority(newPriority);
-},
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-requestWillBeSent:function(requestId,frameId,loaderId,documentURL,request,time,wallTime,initiator,redirectResponse,resourceType)
-{
-var networkRequest=this._inflightRequestsById[requestId];
-if(networkRequest){
-
-if(!redirectResponse)
-return;
-this.responseReceived(requestId,frameId,loaderId,time,PageAgent.ResourceType.Other,redirectResponse);
-networkRequest=this._appendRedirect(requestId,time,request.url);
-}else
-networkRequest=this._createNetworkRequest(requestId,frameId,loaderId,request.url,documentURL,initiator);
-networkRequest.hasNetworkData=true;
-this._updateNetworkRequestWithRequest(networkRequest,request);
-networkRequest.setIssueTime(time,wallTime);
-networkRequest.setResourceType(WebInspector.resourceTypes[resourceType]);
-
-this._startNetworkRequest(networkRequest);
-},
-
-
-
-
-
-requestServedFromCache:function(requestId)
-{
-var networkRequest=this._inflightRequestsById[requestId];
-if(!networkRequest)
-return;
-
-networkRequest.setFromMemoryCache();
-},
-
-
-
-
-
-
-
-
-
-
-responseReceived:function(requestId,frameId,loaderId,time,resourceType,response)
-{
-var networkRequest=this._inflightRequestsById[requestId];
-if(!networkRequest){
-
-var eventData={};
-eventData.url=response.url;
-eventData.frameId=frameId;
-eventData.loaderId=loaderId;
-eventData.resourceType=resourceType;
-eventData.mimeType=response.mimeType;
-this._manager.dispatchEventToListeners(WebInspector.NetworkManager.Events.RequestUpdateDropped,eventData);
-return;
-}
-
-networkRequest.responseReceivedTime=time;
-networkRequest.setResourceType(WebInspector.resourceTypes[resourceType]);
-
-this._updateNetworkRequestWithResponse(networkRequest,response);
-
-this._updateNetworkRequest(networkRequest);
-this._manager.dispatchEventToListeners(WebInspector.NetworkManager.Events.ResponseReceived,networkRequest);
-},
-
-
-
-
-
-
-
-
-dataReceived:function(requestId,time,dataLength,encodedDataLength)
-{
-var networkRequest=this._inflightRequestsById[requestId];
-if(!networkRequest)
-return;
-
-networkRequest.resourceSize+=dataLength;
-if(encodedDataLength!==-1)
-networkRequest.increaseTransferSize(encodedDataLength);
-networkRequest.endTime=time;
-
-this._updateNetworkRequest(networkRequest);
-},
-
-
-
-
-
-
-
-loadingFinished:function(requestId,finishTime,encodedDataLength)
-{
-var networkRequest=this._inflightRequestsById[requestId];
-if(!networkRequest)
-return;
-this._finishNetworkRequest(networkRequest,finishTime,encodedDataLength);
-},
-
-
-
-
-
-
-
-
-
-
-loadingFailed:function(requestId,time,resourceType,localizedDescription,canceled,blockedReason)
-{
-var networkRequest=this._inflightRequestsById[requestId];
-if(!networkRequest)
-return;
-
-networkRequest.failed=true;
-networkRequest.setResourceType(WebInspector.resourceTypes[resourceType]);
-networkRequest.canceled=canceled;
-if(blockedReason){
-networkRequest.setBlockedReason(blockedReason);
-if(blockedReason===NetworkAgent.BlockedReason.Inspector){
-var consoleModel=this._manager._target.consoleModel;
-consoleModel.addMessage(new WebInspector.ConsoleMessage(consoleModel.target(),WebInspector.ConsoleMessage.MessageSource.Network,
-WebInspector.ConsoleMessage.MessageLevel.Warning,
-WebInspector.UIString("Request was blocked by DevTools: \"%s\".",networkRequest.url),
-WebInspector.ConsoleMessage.MessageType.Log,
-"",
-0,
-0,
-networkRequest.requestId));
-}
-}
-networkRequest.localizedFailDescription=localizedDescription;
-this._finishNetworkRequest(networkRequest,time,-1);
-},
-
-
-
-
-
-
-
-webSocketCreated:function(requestId,requestURL,initiator)
-{
-var networkRequest=new WebInspector.NetworkRequest(this._manager._target,requestId,requestURL,"","","",initiator||null);
-networkRequest.setResourceType(WebInspector.resourceTypes.WebSocket);
-this._startNetworkRequest(networkRequest);
-},
-
-
-
-
-
-
-
-
-webSocketWillSendHandshakeRequest:function(requestId,time,wallTime,request)
-{
-var networkRequest=this._inflightRequestsById[requestId];
-if(!networkRequest)
-return;
-
-networkRequest.requestMethod="GET";
-networkRequest.setRequestHeaders(this._headersMapToHeadersArray(request.headers));
-networkRequest.setIssueTime(time,wallTime);
-
-this._updateNetworkRequest(networkRequest);
-},
-
-
-
-
-
-
-
-webSocketHandshakeResponseReceived:function(requestId,time,response)
-{
-var networkRequest=this._inflightRequestsById[requestId];
-if(!networkRequest)
-return;
-
-networkRequest.statusCode=response.status;
-networkRequest.statusText=response.statusText;
-networkRequest.responseHeaders=this._headersMapToHeadersArray(response.headers);
-networkRequest.responseHeadersText=response.headersText;
-if(response.requestHeaders)
-networkRequest.setRequestHeaders(this._headersMapToHeadersArray(response.requestHeaders));
-if(response.requestHeadersText)
-networkRequest.setRequestHeadersText(response.requestHeadersText);
-networkRequest.responseReceivedTime=time;
-networkRequest.protocol="websocket";
-
-this._updateNetworkRequest(networkRequest);
-},
-
-
-
-
-
-
-
-webSocketFrameReceived:function(requestId,time,response)
-{
-var networkRequest=this._inflightRequestsById[requestId];
-if(!networkRequest)
-return;
-
-networkRequest.addFrame(response,time);
-networkRequest.responseReceivedTime=time;
-
-this._updateNetworkRequest(networkRequest);
-},
-
-
-
-
-
-
-
-webSocketFrameSent:function(requestId,time,response)
-{
-var networkRequest=this._inflightRequestsById[requestId];
-if(!networkRequest)
-return;
-
-networkRequest.addFrame(response,time,true);
-networkRequest.responseReceivedTime=time;
-
-this._updateNetworkRequest(networkRequest);
-},
-
-
-
-
-
-
-
-webSocketFrameError:function(requestId,time,errorMessage)
-{
-var networkRequest=this._inflightRequestsById[requestId];
-if(!networkRequest)
-return;
-
-networkRequest.addFrameError(errorMessage,time);
-networkRequest.responseReceivedTime=time;
-
-this._updateNetworkRequest(networkRequest);
-},
-
-
-
-
-
-
-webSocketClosed:function(requestId,time)
-{
-var networkRequest=this._inflightRequestsById[requestId];
-if(!networkRequest)
-return;
-this._finishNetworkRequest(networkRequest,time,-1);
-},
-
-
-
-
-
-
-
-
-
-eventSourceMessageReceived:function(requestId,time,eventName,eventId,data)
-{
-var networkRequest=this._inflightRequestsById[requestId];
-if(!networkRequest)
-return;
-networkRequest.addEventSourceMessage(time,eventName,eventId,data);
-},
-
-
-
-
-
-
-
-_appendRedirect:function(requestId,time,redirectURL)
-{
-var originalNetworkRequest=this._inflightRequestsById[requestId];
-var previousRedirects=originalNetworkRequest.redirects||[];
-originalNetworkRequest.requestId=requestId+":redirected."+previousRedirects.length;
-delete originalNetworkRequest.redirects;
-if(previousRedirects.length>0)
-originalNetworkRequest.redirectSource=previousRedirects[previousRedirects.length-1];
-this._finishNetworkRequest(originalNetworkRequest,time,-1);
-var newNetworkRequest=this._createNetworkRequest(requestId,originalNetworkRequest.frameId,originalNetworkRequest.loaderId,
-redirectURL,originalNetworkRequest.documentURL,originalNetworkRequest.initiator());
-newNetworkRequest.redirects=previousRedirects.concat(originalNetworkRequest);
-return newNetworkRequest;
-},
-
-
-
-
-_startNetworkRequest:function(networkRequest)
-{
-this._inflightRequestsById[networkRequest.requestId]=networkRequest;
-this._inflightRequestsByURL[networkRequest.url]=networkRequest;
-this._dispatchEventToListeners(WebInspector.NetworkManager.Events.RequestStarted,networkRequest);
-},
-
-
-
-
-_updateNetworkRequest:function(networkRequest)
-{
-this._dispatchEventToListeners(WebInspector.NetworkManager.Events.RequestUpdated,networkRequest);
-},
-
-
-
-
-
-
-_finishNetworkRequest:function(networkRequest,finishTime,encodedDataLength)
-{
-networkRequest.endTime=finishTime;
-networkRequest.finished=true;
-if(encodedDataLength>=0)
-networkRequest.setTransferSize(encodedDataLength);
-this._dispatchEventToListeners(WebInspector.NetworkManager.Events.RequestFinished,networkRequest);
-delete this._inflightRequestsById[networkRequest.requestId];
-delete this._inflightRequestsByURL[networkRequest.url];
-},
-
-
-
-
-
-_dispatchEventToListeners:function(eventType,networkRequest)
-{
-this._manager.dispatchEventToListeners(eventType,networkRequest);
-},
-
-
-
-
-
-
-
-
-
-_createNetworkRequest:function(requestId,frameId,loaderId,url,documentURL,initiator)
-{
-return new WebInspector.NetworkRequest(this._manager._target,requestId,url,documentURL,frameId,loaderId,initiator);
-}};
-
-
-
-
-
-
-
-
-WebInspector.MultitargetNetworkManager=function()
-{
-WebInspector.Object.call(this);
-WebInspector.targetManager.observeTargets(this);
-
-
-this._blockedURLs=new Set();
-this._blockedSetting=WebInspector.moduleSetting("blockedURLs");
-this._blockedSetting.addChangeListener(this._updateBlockedURLs,this);
-this._blockedSetting.set([]);
-this._updateBlockedURLs();
-
-this._userAgentOverride="";
-
-this._agents=new Set();
-
-this._networkConditions=WebInspector.NetworkManager.NoThrottlingConditions;
-};
-
-
-WebInspector.MultitargetNetworkManager.Events={
-ConditionsChanged:Symbol("ConditionsChanged"),
-UserAgentChanged:Symbol("UserAgentChanged")};
-
-
-
-
-
-
-WebInspector.MultitargetNetworkManager.patchUserAgentWithChromeVersion=function(uaString)
-{
-
-var chromeRegex=new RegExp("(?:^|\\W)Chrome/(\\S+)");
-var chromeMatch=navigator.userAgent.match(chromeRegex);
-if(chromeMatch&&chromeMatch.length>1)
-return String.sprintf(uaString,chromeMatch[1]);
-return uaString;
-};
-
-WebInspector.MultitargetNetworkManager.prototype={
-
-
-
-
-targetAdded:function(target)
-{
-var networkAgent=target.networkAgent();
-if(this._extraHeaders)
-networkAgent.setExtraHTTPHeaders(this._extraHeaders);
-if(this._currentUserAgent())
-networkAgent.setUserAgentOverride(this._currentUserAgent());
-for(var url of this._blockedURLs)
-networkAgent.addBlockedURL(url);
-this._agents.add(networkAgent);
-if(this.isThrottling())
-this._updateNetworkConditions(networkAgent);
-},
-
-
-
-
-
-targetRemoved:function(target)
-{
-this._agents.delete(target.networkAgent());
-},
-
-
-
-
-isThrottling:function()
-{
-return this._networkConditions.download>=0||this._networkConditions.upload>=0||this._networkConditions.latency>0;
-},
-
-
-
-
-isOffline:function()
-{
-return!this._networkConditions.download&&!this._networkConditions.upload;
-},
-
-
-
-
-setNetworkConditions:function(conditions)
-{
-this._networkConditions=conditions;
-for(var agent of this._agents)
-this._updateNetworkConditions(agent);
-this.dispatchEventToListeners(WebInspector.MultitargetNetworkManager.Events.ConditionsChanged);
-},
-
-
-
-
-networkConditions:function()
-{
-return this._networkConditions;
-},
-
-
-
-
-_updateNetworkConditions:function(networkAgent)
-{
-var conditions=this._networkConditions;
-if(!this.isThrottling()){
-networkAgent.emulateNetworkConditions(false,0,0,0);
-}else{
-networkAgent.emulateNetworkConditions(this.isOffline(),conditions.latency,conditions.download<0?0:conditions.download,conditions.upload<0?0:conditions.upload,WebInspector.NetworkManager._connectionType(conditions));
-}
-},
-
-
-
-
-setExtraHTTPHeaders:function(headers)
-{
-this._extraHeaders=headers;
-for(var target of WebInspector.targetManager.targets())
-target.networkAgent().setExtraHTTPHeaders(this._extraHeaders);
-},
-
-
-
-
-_currentUserAgent:function()
-{
-return this._customUserAgent?this._customUserAgent:this._userAgentOverride;
-},
-
-_updateUserAgentOverride:function()
-{
-var userAgent=this._currentUserAgent();
-WebInspector.ResourceLoader.targetUserAgent=userAgent;
-for(var target of WebInspector.targetManager.targets())
-target.networkAgent().setUserAgentOverride(userAgent);
-},
-
-
-
-
-setUserAgentOverride:function(userAgent)
-{
-if(this._userAgentOverride===userAgent)
-return;
-this._userAgentOverride=userAgent;
-if(!this._customUserAgent)
-this._updateUserAgentOverride();
-this.dispatchEventToListeners(WebInspector.MultitargetNetworkManager.Events.UserAgentChanged);
-},
-
-
-
-
-userAgentOverride:function()
-{
-return this._userAgentOverride;
-},
-
-
-
-
-setCustomUserAgentOverride:function(userAgent)
-{
-this._customUserAgent=userAgent;
-this._updateUserAgentOverride();
-},
-
-_updateBlockedURLs:function()
-{
-var blocked=this._blockedSetting.get();
-for(var url of blocked){
-if(!this._blockedURLs.has(url))
-this._addBlockedURL(url);
-}
-for(var url of this._blockedURLs){
-if(blocked.indexOf(url)===-1)
-this._removeBlockedURL(url);
-}
-},
-
-
-
-
-_addBlockedURL:function(url)
-{
-this._blockedURLs.add(url);
-for(var target of WebInspector.targetManager.targets())
-target.networkAgent().addBlockedURL(url);
-},
-
-
-
-
-_removeBlockedURL:function(url)
-{
-this._blockedURLs.delete(url);
-for(var target of WebInspector.targetManager.targets())
-target.networkAgent().removeBlockedURL(url);
-},
-
-clearBrowserCache:function()
-{
-for(var target of WebInspector.targetManager.targets())
-target.networkAgent().clearBrowserCache();
-},
-
-clearBrowserCookies:function()
-{
-for(var target of WebInspector.targetManager.targets())
-target.networkAgent().clearBrowserCookies();
-},
-
-
-
-
-
-getCertificate:function(origin,callback)
-{
-var target=WebInspector.targetManager.mainTarget();
-target.networkAgent().getCertificate(origin,mycallback);
-
-
-
-
-
-function mycallback(error,certificate)
-{
-callback(error?[]:certificate);
-}
-},
-
-
-
-
-
-loadResource:function(url,callback)
-{
-var headers={};
-
-var currentUserAgent=this._currentUserAgent();
-if(currentUserAgent)
-headers["User-Agent"]=currentUserAgent;
-
-if(WebInspector.moduleSetting("cacheDisabled").get())
-headers["Cache-Control"]="no-cache";
-
-WebInspector.ResourceLoader.load(url,headers,callback);
-},
-
-__proto__:WebInspector.Object.prototype};
-
-
-
-
-
-WebInspector.multitargetNetworkManager;
-
-},{}],118:[function(require,module,exports){
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-WebInspector.NetworkRequest=function(target,requestId,url,documentURL,frameId,loaderId,initiator)
-{
-WebInspector.SDKObject.call(this,target);
-
-this._networkLog=WebInspector.NetworkLog.fromTarget(target);
-this._networkManager=WebInspector.NetworkManager.fromTarget(target);
-this._requestId=requestId;
-this.url=url;
-this._documentURL=documentURL;
-this._frameId=frameId;
-this._loaderId=loaderId;
-
-this._initiator=initiator;
-this._issueTime=-1;
-this._startTime=-1;
-this._endTime=-1;
-
-this._blockedReason=undefined;
-
-this.statusCode=0;
-this.statusText="";
-this.requestMethod="";
-this.requestTime=0;
-this.protocol="";
-
-this.mixedContentType=NetworkAgent.RequestMixedContentType.None;
-
-
-this._initialPriority=null;
-
-this._currentPriority=null;
-
-
-this._resourceType=WebInspector.resourceTypes.Other;
-this._contentEncoded=false;
-this._pendingContentCallbacks=[];
-
-this._frames=[];
-
-this._eventSourceMessages=[];
-
-this._responseHeaderValues={};
-
-this._remoteAddress="";
-
-
-this._securityState=SecurityAgent.SecurityState.Unknown;
-
-this._securityDetails=null;
-
-
-this.connectionId="0";
-};
-
-
-WebInspector.NetworkRequest.Events={
-FinishedLoading:Symbol("FinishedLoading"),
-TimingChanged:Symbol("TimingChanged"),
-RemoteAddressChanged:Symbol("RemoteAddressChanged"),
-RequestHeadersChanged:Symbol("RequestHeadersChanged"),
-ResponseHeadersChanged:Symbol("ResponseHeadersChanged"),
-WebsocketFrameAdded:Symbol("WebsocketFrameAdded"),
-EventSourceMessageAdded:Symbol("EventSourceMessageAdded")};
-
-
-
-WebInspector.NetworkRequest.InitiatorType={
-Other:"other",
-Parser:"parser",
-Redirect:"redirect",
-Script:"script"};
-
-
-
-WebInspector.NetworkRequest.NameValue;
-
-
-WebInspector.NetworkRequest.WebSocketFrameType={
-Send:"send",
-Receive:"receive",
-Error:"error"};
-
-
-
-WebInspector.NetworkRequest.WebSocketFrame;
-
-
-WebInspector.NetworkRequest.EventSourceMessage;
-
-WebInspector.NetworkRequest.prototype={
-
-
-
-
-indentityCompare:function(other)
-{
-if(this._requestId>other._requestId)
-return 1;
-if(this._requestId<other._requestId)
-return-1;
-return 0;
-},
-
-
-
-
-get requestId()
-{
-return this._requestId;
-},
-
-set requestId(requestId)
-{
-this._requestId=requestId;
-},
-
-
-
-
-get url()
-{
-return this._url;
-},
-
-set url(x)
-{
-if(this._url===x)
-return;
-
-this._url=x;
-this._parsedURL=new WebInspector.ParsedURL(x);
-delete this._queryString;
-delete this._parsedQueryParameters;
-delete this._name;
-delete this._path;
-},
-
-
-
-
-get documentURL()
-{
-return this._documentURL;
-},
-
-get parsedURL()
-{
-return this._parsedURL;
-},
-
-
-
-
-get frameId()
-{
-return this._frameId;
-},
-
-
-
-
-get loaderId()
-{
-return this._loaderId;
-},
-
-
-
-
-
-setRemoteAddress:function(ip,port)
-{
-this._remoteAddress=ip+":"+port;
-this.dispatchEventToListeners(WebInspector.NetworkRequest.Events.RemoteAddressChanged,this);
-},
-
-
-
-
-remoteAddress:function()
-{
-return this._remoteAddress;
-},
-
-
-
-
-securityState:function()
-{
-return this._securityState;
-},
-
-
-
-
-setSecurityState:function(securityState)
-{
-this._securityState=securityState;
-},
-
-
-
-
-securityDetails:function()
-{
-return this._securityDetails;
-},
-
-
-
-
-setSecurityDetails:function(securityDetails)
-{
-this._securityDetails=securityDetails;
-},
-
-
-
-
-get startTime()
-{
-return this._startTime||-1;
-},
-
-
-
-
-
-setIssueTime:function(monotonicTime,wallTime)
-{
-this._issueTime=monotonicTime;
-this._wallIssueTime=wallTime;
-this._startTime=monotonicTime;
-},
-
-
-
-
-issueTime:function()
-{
-return this._issueTime;
-},
-
-
-
-
-
-pseudoWallTime:function(monotonicTime)
-{
-return this._wallIssueTime?this._wallIssueTime-this._issueTime+monotonicTime:monotonicTime;
-},
-
-
-
-
-get responseReceivedTime()
-{
-return this._responseReceivedTime||-1;
-},
-
-set responseReceivedTime(x)
-{
-this._responseReceivedTime=x;
-},
-
-
-
-
-get endTime()
-{
-return this._endTime||-1;
-},
-
-set endTime(x)
-{
-if(this.timing&&this.timing.requestTime){
-
-this._endTime=Math.max(x,this.responseReceivedTime);
-}else{
-
-this._endTime=x;
-if(this._responseReceivedTime>x)
-this._responseReceivedTime=x;
-}
-this.dispatchEventToListeners(WebInspector.NetworkRequest.Events.TimingChanged,this);
-},
-
-
-
-
-get duration()
-{
-if(this._endTime===-1||this._startTime===-1)
-return-1;
-return this._endTime-this._startTime;
-},
-
-
-
-
-get latency()
-{
-if(this._responseReceivedTime===-1||this._startTime===-1)
-return-1;
-return this._responseReceivedTime-this._startTime;
-},
-
-
-
-
-get resourceSize()
-{
-return this._resourceSize||0;
-},
-
-set resourceSize(x)
-{
-this._resourceSize=x;
-},
-
-
-
-
-get transferSize()
-{
-return this._transferSize||0;
-},
-
-
-
-
-increaseTransferSize:function(x)
-{
-this._transferSize=(this._transferSize||0)+x;
-},
-
-
-
-
-setTransferSize:function(x)
-{
-this._transferSize=x;
-},
-
-
-
-
-get finished()
-{
-return this._finished;
-},
-
-set finished(x)
-{
-if(this._finished===x)
-return;
-
-this._finished=x;
-
-if(x){
-this.dispatchEventToListeners(WebInspector.NetworkRequest.Events.FinishedLoading,this);
-if(this._pendingContentCallbacks.length)
-this._innerRequestContent();
-}
-},
-
-
-
-
-get failed()
-{
-return this._failed;
-},
-
-set failed(x)
-{
-this._failed=x;
-},
-
-
-
-
-get canceled()
-{
-return this._canceled;
-},
-
-set canceled(x)
-{
-this._canceled=x;
-},
-
-
-
-
-blockedReason:function()
-{
-return this._blockedReason;
-},
-
-
-
-
-setBlockedReason:function(reason)
-{
-this._blockedReason=reason;
-},
-
-
-
-
-wasBlocked:function()
-{
-return!!this._blockedReason;
-},
-
-
-
-
-cached:function()
-{
-return(!!this._fromMemoryCache||!!this._fromDiskCache)&&!this._transferSize;
-},
-
-
-
-
-cachedInMemory:function()
-{
-return!!this._fromMemoryCache&&!this._transferSize;
-},
-
-setFromMemoryCache:function()
-{
-this._fromMemoryCache=true;
-delete this._timing;
-},
-
-setFromDiskCache:function()
-{
-this._fromDiskCache=true;
-},
-
-
-
-
-get fetchedViaServiceWorker()
-{
-return this._fetchedViaServiceWorker;
-},
-
-set fetchedViaServiceWorker(x)
-{
-this._fetchedViaServiceWorker=x;
-},
-
-
-
-
-get timing()
-{
-return this._timing;
-},
-
-set timing(x)
-{
-if(x&&!this._fromMemoryCache){
-
-
-this._startTime=x.requestTime;
-this._responseReceivedTime=x.requestTime+x.receiveHeadersEnd/1000.0;
-
-this._timing=x;
-this.dispatchEventToListeners(WebInspector.NetworkRequest.Events.TimingChanged,this);
-}
-},
-
-
-
-
-get mimeType()
-{
-return this._mimeType;
-},
-
-set mimeType(x)
-{
-this._mimeType=x;
-},
-
-
-
-
-get displayName()
-{
-return this._parsedURL.displayName;
-},
-
-
-
-
-name:function()
-{
-if(this._name)
-return this._name;
-this._parseNameAndPathFromURL();
-return this._name;
-},
-
-
-
-
-path:function()
-{
-if(this._path)
-return this._path;
-this._parseNameAndPathFromURL();
-return this._path;
-},
-
-_parseNameAndPathFromURL:function()
-{
-if(this._parsedURL.isDataURL()){
-this._name=this._parsedURL.dataURLDisplayName();
-this._path="";
-}else if(this._parsedURL.isAboutBlank()){
-this._name=this._parsedURL.url;
-this._path="";
-}else{
-this._path=this._parsedURL.host+this._parsedURL.folderPathComponents;
-
-var inspectedURL=this.target().inspectedURL().asParsedURL();
-this._path=this._path.trimURL(inspectedURL?inspectedURL.host:"");
-if(this._parsedURL.lastPathComponent||this._parsedURL.queryParams)
-this._name=this._parsedURL.lastPathComponent+(this._parsedURL.queryParams?"?"+this._parsedURL.queryParams:"");else
-if(this._parsedURL.folderPathComponents){
-this._name=this._parsedURL.folderPathComponents.substring(this._parsedURL.folderPathComponents.lastIndexOf("/")+1)+"/";
-this._path=this._path.substring(0,this._path.lastIndexOf("/"));
-}else{
-this._name=this._parsedURL.host;
-this._path="";
-}
-}
-},
-
-
-
-
-get folder()
-{
-var path=this._parsedURL.path;
-var indexOfQuery=path.indexOf("?");
-if(indexOfQuery!==-1)
-path=path.substring(0,indexOfQuery);
-var lastSlashIndex=path.lastIndexOf("/");
-return lastSlashIndex!==-1?path.substring(0,lastSlashIndex):"";
-},
-
-
-
-
-resourceType:function()
-{
-return this._resourceType;
-},
-
-
-
-
-setResourceType:function(resourceType)
-{
-this._resourceType=resourceType;
-},
-
-
-
-
-get domain()
-{
-return this._parsedURL.host;
-},
-
-
-
-
-get scheme()
-{
-return this._parsedURL.scheme;
-},
-
-
-
-
-get redirectSource()
-{
-if(this.redirects&&this.redirects.length>0)
-return this.redirects[this.redirects.length-1];
-return this._redirectSource;
-},
-
-set redirectSource(x)
-{
-this._redirectSource=x;
-delete this._initiatorInfo;
-},
-
-
-
-
-requestHeaders:function()
-{
-return this._requestHeaders||[];
-},
-
-
-
-
-setRequestHeaders:function(headers)
-{
-this._requestHeaders=headers;
-delete this._requestCookies;
-
-this.dispatchEventToListeners(WebInspector.NetworkRequest.Events.RequestHeadersChanged);
-},
-
-
-
-
-requestHeadersText:function()
-{
-return this._requestHeadersText;
-},
-
-
-
-
-setRequestHeadersText:function(text)
-{
-this._requestHeadersText=text;
-
-this.dispatchEventToListeners(WebInspector.NetworkRequest.Events.RequestHeadersChanged);
-},
-
-
-
-
-
-requestHeaderValue:function(headerName)
-{
-return this._headerValue(this.requestHeaders(),headerName);
-},
-
-
-
-
-get requestCookies()
-{
-if(!this._requestCookies)
-this._requestCookies=WebInspector.CookieParser.parseCookie(this.target(),this.requestHeaderValue("Cookie"));
-return this._requestCookies;
-},
-
-
-
-
-get requestFormData()
-{
-return this._requestFormData;
-},
-
-set requestFormData(x)
-{
-this._requestFormData=x;
-delete this._parsedFormParameters;
-},
-
-
-
-
-requestHttpVersion:function()
-{
-var headersText=this.requestHeadersText();
-if(!headersText)
-return this.requestHeaderValue("version")||this.requestHeaderValue(":version")||"unknown";
-var firstLine=headersText.split(/\r\n/)[0];
-var match=firstLine.match(/(HTTP\/\d+\.\d+)$/);
-return match?match[1]:"HTTP/0.9";
-},
-
-
-
-
-get responseHeaders()
-{
-return this._responseHeaders||[];
-},
-
-set responseHeaders(x)
-{
-this._responseHeaders=x;
-delete this._sortedResponseHeaders;
-delete this._serverTimings;
-delete this._responseCookies;
-this._responseHeaderValues={};
-
-this.dispatchEventToListeners(WebInspector.NetworkRequest.Events.ResponseHeadersChanged);
-},
-
-
-
-
-get responseHeadersText()
-{
-return this._responseHeadersText;
-},
-
-set responseHeadersText(x)
-{
-this._responseHeadersText=x;
-
-this.dispatchEventToListeners(WebInspector.NetworkRequest.Events.ResponseHeadersChanged);
-},
-
-
-
-
-get sortedResponseHeaders()
-{
-if(this._sortedResponseHeaders!==undefined)
-return this._sortedResponseHeaders;
-
-this._sortedResponseHeaders=this.responseHeaders.slice();
-this._sortedResponseHeaders.sort(function(a,b){return a.name.toLowerCase().compareTo(b.name.toLowerCase());});
-return this._sortedResponseHeaders;
-},
-
-
-
-
-
-responseHeaderValue:function(headerName)
-{
-var value=this._responseHeaderValues[headerName];
-if(value===undefined){
-value=this._headerValue(this.responseHeaders,headerName);
-this._responseHeaderValues[headerName]=value!==undefined?value:null;
-}
-return value!==null?value:undefined;
-},
-
-
-
-
-get responseCookies()
-{
-if(!this._responseCookies)
-this._responseCookies=WebInspector.CookieParser.parseSetCookie(this.target(),this.responseHeaderValue("Set-Cookie"));
-return this._responseCookies;
-},
-
-
-
-
-get serverTimings()
-{
-if(typeof this._serverTimings==="undefined")
-this._serverTimings=WebInspector.ServerTiming.parseHeaders(this.responseHeaders);
-return this._serverTimings;
-},
-
-
-
-
-queryString:function()
-{
-if(this._queryString!==undefined)
-return this._queryString;
-
-var queryString=null;
-var url=this.url;
-var questionMarkPosition=url.indexOf("?");
-if(questionMarkPosition!==-1){
-queryString=url.substring(questionMarkPosition+1);
-var hashSignPosition=queryString.indexOf("#");
-if(hashSignPosition!==-1)
-queryString=queryString.substring(0,hashSignPosition);
-}
-this._queryString=queryString;
-return this._queryString;
-},
-
-
-
-
-get queryParameters()
-{
-if(this._parsedQueryParameters)
-return this._parsedQueryParameters;
-var queryString=this.queryString();
-if(!queryString)
-return null;
-this._parsedQueryParameters=this._parseParameters(queryString);
-return this._parsedQueryParameters;
-},
-
-
-
-
-get formParameters()
-{
-if(this._parsedFormParameters)
-return this._parsedFormParameters;
-if(!this.requestFormData)
-return null;
-var requestContentType=this.requestContentType();
-if(!requestContentType||!requestContentType.match(/^application\/x-www-form-urlencoded\s*(;.*)?$/i))
-return null;
-this._parsedFormParameters=this._parseParameters(this.requestFormData);
-return this._parsedFormParameters;
-},
-
-
-
-
-responseHttpVersion:function()
-{
-var headersText=this._responseHeadersText;
-if(!headersText)
-return this.responseHeaderValue("version")||this.responseHeaderValue(":version")||"unknown";
-var firstLine=headersText.split(/\r\n/)[0];
-var match=firstLine.match(/^(HTTP\/\d+\.\d+)/);
-return match?match[1]:"HTTP/0.9";
-},
-
-
-
-
-
-_parseParameters:function(queryString)
-{
-function parseNameValue(pair)
-{
-var position=pair.indexOf("=");
-if(position===-1)
-return{name:pair,value:""};else
-
-return{name:pair.substring(0,position),value:pair.substring(position+1)};
-}
-return queryString.split("&").map(parseNameValue);
-},
-
-
-
-
-
-
-_headerValue:function(headers,headerName)
-{
-headerName=headerName.toLowerCase();
-
-var values=[];
-for(var i=0;i<headers.length;++i){
-if(headers[i].name.toLowerCase()===headerName)
-values.push(headers[i].value);
-}
-if(!values.length)
-return undefined;
-
-if(headerName==="set-cookie")
-return values.join("\n");
-return values.join(", ");
-},
-
-
-
-
-get content()
-{
-return this._content;
-},
-
-
-
-
-contentError:function()
-{
-return this._contentError;
-},
-
-
-
-
-get contentEncoded()
-{
-return this._contentEncoded;
-},
-
-
-
-
-
-contentURL:function()
-{
-return this._url;
-},
-
-
-
-
-
-contentType:function()
-{
-return this._resourceType;
-},
-
-
-
-
-
-requestContent:function()
-{
-
-
-
-if(this._resourceType===WebInspector.resourceTypes.WebSocket)
-return Promise.resolve(null);
-if(typeof this._content!=="undefined")
-return Promise.resolve(this.content||null);
-var callback;
-var promise=new Promise(fulfill=>callback=fulfill);
-this._pendingContentCallbacks.push(callback);
-if(this.finished)
-this._innerRequestContent();
-return promise;
-},
-
-
-
-
-
-
-
-
-searchInContent:function(query,caseSensitive,isRegex,callback)
-{
-callback([]);
-},
-
-
-
-
-isHttpFamily:function()
-{
-return!!this.url.match(/^https?:/i);
-},
-
-
-
-
-requestContentType:function()
-{
-return this.requestHeaderValue("Content-Type");
-},
-
-
-
-
-hasErrorStatusCode:function()
-{
-return this.statusCode>=400;
-},
-
-
-
-
-setInitialPriority:function(priority)
-{
-this._initialPriority=priority;
-},
-
-
-
-
-initialPriority:function()
-{
-return this._initialPriority;
-},
-
-
-
-
-setPriority:function(priority)
-{
-this._currentPriority=priority;
-},
-
-
-
-
-priority:function()
-{
-return this._currentPriority||this._initialPriority||null;
-},
-
-
-
-
-populateImageSource:function(image)
-{
-
-
-
-
-function onResourceContent(content)
-{
-var imageSrc=WebInspector.ContentProvider.contentAsDataURL(content,this._mimeType,true);
-if(imageSrc===null)
-imageSrc=this._url;
-image.src=imageSrc;
-}
-
-this.requestContent().then(onResourceContent.bind(this));
-},
-
-
-
-
-asDataURL:function()
-{
-var content=this._content;
-var charset=null;
-if(!this._contentEncoded){
-content=content.toBase64();
-charset="utf-8";
-}
-return WebInspector.ContentProvider.contentAsDataURL(content,this.mimeType,true,charset);
-},
-
-_innerRequestContent:function()
-{
-if(this._contentRequested)
-return;
-this._contentRequested=true;
-
-
-
-
-
-
-
-function onResourceContent(error,content,contentEncoded)
-{
-this._content=error?null:content;
-this._contentError=error;
-this._contentEncoded=contentEncoded;
-var callbacks=this._pendingContentCallbacks.slice();
-for(var i=0;i<callbacks.length;++i)
-callbacks[i](this._content);
-this._pendingContentCallbacks.length=0;
-delete this._contentRequested;
-}
-this.target().networkAgent().getResponseBody(this._requestId,onResourceContent.bind(this));
-},
-
-
-
-
-initiator:function()
-{
-return this._initiator;
-},
-
-
-
-
-initiatorInfo:function()
-{
-if(this._initiatorInfo)
-return this._initiatorInfo;
-
-var type=WebInspector.NetworkRequest.InitiatorType.Other;
-var url="";
-var lineNumber=-Infinity;
-var columnNumber=-Infinity;
-var scriptId=null;
-var initiator=this._initiator;
-
-if(this.redirectSource){
-type=WebInspector.NetworkRequest.InitiatorType.Redirect;
-url=this.redirectSource.url;
-}else if(initiator){
-if(initiator.type===NetworkAgent.InitiatorType.Parser){
-type=WebInspector.NetworkRequest.InitiatorType.Parser;
-url=initiator.url?initiator.url:url;
-lineNumber=initiator.lineNumber?initiator.lineNumber:lineNumber;
-}else if(initiator.type===NetworkAgent.InitiatorType.Script){
-for(var stack=initiator.stack;stack;stack=stack.parent){
-var topFrame=stack.callFrames.length?stack.callFrames[0]:null;
-if(!topFrame)
-continue;
-type=WebInspector.NetworkRequest.InitiatorType.Script;
-url=topFrame.url||WebInspector.UIString("<anonymous>");
-lineNumber=topFrame.lineNumber;
-columnNumber=topFrame.columnNumber;
-scriptId=topFrame.scriptId;
-break;
-}
-}
-}
-
-this._initiatorInfo={type:type,url:url,lineNumber:lineNumber,columnNumber:columnNumber,scriptId:scriptId};
-return this._initiatorInfo;
-},
-
-
-
-
-initiatorRequest:function()
-{
-if(this._initiatorRequest===undefined)
-this._initiatorRequest=this._networkLog.requestForURL(this.initiatorInfo().url);
-return this._initiatorRequest;
-},
-
-
-
-
-initiatorChain:function()
-{
-if(this._initiatorChain)
-return this._initiatorChain;
-this._initiatorChain=new Set();
-var request=this;
-while(request){
-this._initiatorChain.add(request);
-request=request.initiatorRequest();
-}
-return this._initiatorChain;
-},
-
-
-
-
-frames:function()
-{
-return this._frames;
-},
-
-
-
-
-
-addFrameError:function(errorMessage,time)
-{
-this._addFrame({type:WebInspector.NetworkRequest.WebSocketFrameType.Error,text:errorMessage,time:this.pseudoWallTime(time),opCode:-1,mask:false});
-},
-
-
-
-
-
-
-addFrame:function(response,time,sent)
-{
-var type=sent?WebInspector.NetworkRequest.WebSocketFrameType.Send:WebInspector.NetworkRequest.WebSocketFrameType.Receive;
-this._addFrame({type:type,text:response.payloadData,time:this.pseudoWallTime(time),opCode:response.opcode,mask:response.mask});
-},
-
-
-
-
-_addFrame:function(frame)
-{
-this._frames.push(frame);
-this.dispatchEventToListeners(WebInspector.NetworkRequest.Events.WebsocketFrameAdded,frame);
-},
-
-
-
-
-eventSourceMessages:function()
-{
-return this._eventSourceMessages;
-},
-
-
-
-
-
-
-
-addEventSourceMessage:function(time,eventName,eventId,data)
-{
-var message={time:this.pseudoWallTime(time),eventName:eventName,eventId:eventId,data:data};
-this._eventSourceMessages.push(message);
-this.dispatchEventToListeners(WebInspector.NetworkRequest.Events.EventSourceMessageAdded,message);
-},
-
-replayXHR:function()
-{
-this.target().networkAgent().replayXHR(this.requestId);
-},
-
-
-
-
-networkLog:function()
-{
-return this._networkLog;
-},
-
-
-
-
-networkManager:function()
-{
-return this._networkManager;
-},
-
-__proto__:WebInspector.SDKObject.prototype};
-
-
-},{}],119:[function(require,module,exports){
-
-
-
-
-
-
-
-
-WebInspector.ProfileNode=function(callFrame)
-{
-
-this.callFrame=callFrame;
-
-this.callUID=`${this.callFrame.functionName}@${this.callFrame.scriptId}:${this.callFrame.lineNumber}`;
-
-this.self=0;
-
-this.total=0;
-
-this.id=0;
-
-this.parent=null;
-
-this.children=[];
-};
-
-WebInspector.ProfileNode.prototype={
-
-
-
-get functionName()
-{
-return this.callFrame.functionName;
-},
-
-
-
-
-get scriptId()
-{
-return this.callFrame.scriptId;
-},
-
-
-
-
-get url()
-{
-return this.callFrame.url;
-},
-
-
-
-
-get lineNumber()
-{
-return this.callFrame.lineNumber;
-},
-
-
-
-
-get columnNumber()
-{
-return this.callFrame.columnNumber;
-}};
-
-
-
-
-
-
-WebInspector.ProfileTreeModel=function(root)
-{
-this.root=root;
-this._assignDepthsAndParents();
-this.total=this._calculateTotals(this.root);
-};
-
-WebInspector.ProfileTreeModel.prototype={
-_assignDepthsAndParents:function()
-{
-var root=this.root;
-root.depth=-1;
-root.parent=null;
-this.maxDepth=0;
-var nodesToTraverse=[root];
-while(nodesToTraverse.length){
-var parent=nodesToTraverse.pop();
-var depth=parent.depth+1;
-if(depth>this.maxDepth)
-this.maxDepth=depth;
-var children=parent.children;
-var length=children.length;
-for(var i=0;i<length;++i){
-var child=children[i];
-child.depth=depth;
-child.parent=parent;
-if(child.children.length)
-nodesToTraverse.push(child);
-}
-}
-},
-
-
-
-
-
-_calculateTotals:function(root)
-{
-var nodesToTraverse=[root];
-var dfsList=[];
-while(nodesToTraverse.length){
-var node=nodesToTraverse.pop();
-node.total=node.self;
-dfsList.push(node);
-nodesToTraverse.push(...node.children);
-}
-while(dfsList.length>1){
-var node=dfsList.pop();
-node.parent.total+=node.total;
-}
-return root.total;
-}};
-
-
-},{}],120:[function(require,module,exports){
+},{}],113:[function(require,module,exports){
@@ -54513,7 +51432,7 @@ WebInspector.targetManager.removeEventListener(WebInspector.TargetManager.Events
__proto__:WebInspector.SDKObject.prototype};
-},{}],121:[function(require,module,exports){
+},{}],114:[function(require,module,exports){
@@ -54904,994 +51823,7 @@ targetRemoved:function(target){}};
WebInspector.targetManager=new WebInspector.TargetManager();
-},{}],122:[function(require,module,exports){
-
-
-
-
-
-
-
-
-
-
-WebInspector.TracingModel=function(backingStorage)
-{
-this._backingStorage=backingStorage;
-
-this._firstWritePending=true;
-this.reset();
-};
-
-
-
-
-WebInspector.TracingModel.Phase={
-Begin:"B",
-End:"E",
-Complete:"X",
-Instant:"I",
-AsyncBegin:"S",
-AsyncStepInto:"T",
-AsyncStepPast:"p",
-AsyncEnd:"F",
-NestableAsyncBegin:"b",
-NestableAsyncEnd:"e",
-NestableAsyncInstant:"n",
-FlowBegin:"s",
-FlowStep:"t",
-FlowEnd:"f",
-Metadata:"M",
-Counter:"C",
-Sample:"P",
-CreateObject:"N",
-SnapshotObject:"O",
-DeleteObject:"D"};
-
-
-WebInspector.TracingModel.MetadataEvent={
-ProcessSortIndex:"process_sort_index",
-ProcessName:"process_name",
-ThreadSortIndex:"thread_sort_index",
-ThreadName:"thread_name"};
-
-
-WebInspector.TracingModel.TopLevelEventCategory="toplevel";
-WebInspector.TracingModel.DevToolsMetadataEventCategory="disabled-by-default-devtools.timeline";
-WebInspector.TracingModel.DevToolsTimelineEventCategory="disabled-by-default-devtools.timeline";
-
-WebInspector.TracingModel.FrameLifecycleEventCategory="cc,devtools";
-
-
-
-
-
-WebInspector.TracingModel.isNestableAsyncPhase=function(phase)
-{
-return phase==="b"||phase==="e"||phase==="n";
-};
-
-
-
-
-
-WebInspector.TracingModel.isAsyncBeginPhase=function(phase)
-{
-return phase==="S"||phase==="b";
-};
-
-
-
-
-
-WebInspector.TracingModel.isAsyncPhase=function(phase)
-{
-return WebInspector.TracingModel.isNestableAsyncPhase(phase)||phase==="S"||phase==="T"||phase==="F"||phase==="p";
-};
-
-
-
-
-
-WebInspector.TracingModel.isFlowPhase=function(phase)
-{
-return phase==="s"||phase==="t"||phase==="f";
-};
-
-
-
-
-
-WebInspector.TracingModel.isTopLevelEvent=function(event)
-{
-return event.hasCategory(WebInspector.TracingModel.TopLevelEventCategory)||
-event.hasCategory(WebInspector.TracingModel.DevToolsMetadataEventCategory)&&event.name==="Program";
-};
-
-
-
-
-
-WebInspector.TracingModel._extractId=function(payload)
-{
-var scope=payload.scope||"";
-if(typeof payload.id2==="undefined")
-return scope&&payload.id?`${scope}@${payload.id}`:payload.id;
-var id2=payload.id2;
-if(typeof id2==="object"&&"global"in id2!=="local"in id2)
-return typeof id2["global"]!=="undefined"?`:${scope}:${id2["global"]}`:`:${scope}:${payload.pid}:${id2["local"]}`;
-console.error(`Unexpected id2 field at ${payload.ts/1000}, one and only one of 'local' and 'global' should be present.`);
-};
-
-
-
-
-
-
-
-
-
-WebInspector.TracingModel.browserMainThread=function(tracingModel)
-{
-var processes=tracingModel.sortedProcesses();
-var browserProcesses=[];
-var crRendererMainThreads=[];
-for(var process of processes){
-if(process.name().toLowerCase().endsWith("browser"))
-browserProcesses.push(process);
-crRendererMainThreads.push(...process.sortedThreads().filter(t=>t.name()==="CrBrowserMain"));
-}
-if(crRendererMainThreads.length===1)
-return crRendererMainThreads[0];
-if(browserProcesses.length===1)
-return browserProcesses[0].threadByName("CrBrowserMain");
-var tracingStartedInBrowser=tracingModel.devToolsMetadataEvents().filter(e=>e.name==="TracingStartedInBrowser");
-if(tracingStartedInBrowser.length===1)
-return tracingStartedInBrowser[0].thread;
-WebInspector.console.error("Failed to find browser main thread in trace, some timeline features may be unavailable");
-return null;
-};
-
-
-
-
-WebInspector.BackingStorage=function()
-{
-};
-
-WebInspector.BackingStorage.prototype={
-
-
-
-appendString:function(string){},
-
-
-
-
-
-appendAccessibleString:function(string){},
-
-finishWriting:function(){},
-
-reset:function(){}};
-
-
-
-WebInspector.TracingModel.prototype={
-
-
-
-devToolsMetadataEvents:function()
-{
-return this._devToolsMetadataEvents;
-},
-
-
-
-
-setEventsForTest:function(events)
-{
-this.reset();
-this.addEvents(events);
-this.tracingComplete();
-},
-
-
-
-
-addEvents:function(events)
-{
-for(var i=0;i<events.length;++i)
-this._addEvent(events[i]);
-},
-
-tracingComplete:function()
-{
-this._processPendingAsyncEvents();
-this._backingStorage.appendString(this._firstWritePending?"[]":"]");
-this._backingStorage.finishWriting();
-this._firstWritePending=false;
-for(var process of this._processById.values()){
-for(var thread of process._threads.values())
-thread.tracingComplete();
-}
-},
-
-reset:function()
-{
-
-this._processById=new Map();
-this._processByName=new Map();
-this._minimumRecordTime=0;
-this._maximumRecordTime=0;
-this._devToolsMetadataEvents=[];
-if(!this._firstWritePending)
-this._backingStorage.reset();
-
-this._firstWritePending=true;
-
-this._asyncEvents=[];
-
-this._openAsyncEvents=new Map();
-
-this._openNestableAsyncEvents=new Map();
-
-this._parsedCategories=new Map();
-},
-
-
-
-
-_addEvent:function(payload)
-{
-var process=this._processById.get(payload.pid);
-if(!process){
-process=new WebInspector.TracingModel.Process(this,payload.pid);
-this._processById.set(payload.pid,process);
-}
-
-var eventsDelimiter=",\n";
-this._backingStorage.appendString(this._firstWritePending?"[":eventsDelimiter);
-this._firstWritePending=false;
-var stringPayload=JSON.stringify(payload);
-var isAccessible=payload.ph===WebInspector.TracingModel.Phase.SnapshotObject;
-var backingStorage=null;
-var keepStringsLessThan=10000;
-if(isAccessible&&stringPayload.length>keepStringsLessThan)
-backingStorage=this._backingStorage.appendAccessibleString(stringPayload);else
-
-this._backingStorage.appendString(stringPayload);
-
-var timestamp=payload.ts/1000;
-
-
-if(timestamp&&(!this._minimumRecordTime||timestamp<this._minimumRecordTime))
-this._minimumRecordTime=timestamp;
-var endTimeStamp=(payload.ts+(payload.dur||0))/1000;
-this._maximumRecordTime=Math.max(this._maximumRecordTime,endTimeStamp);
-var event=process._addEvent(payload);
-if(!event)
-return;
-
-
-
-if(WebInspector.TracingModel.isAsyncPhase(payload.ph))
-this._asyncEvents.push(event);
-event._setBackingStorage(backingStorage);
-if(event.hasCategory(WebInspector.TracingModel.DevToolsMetadataEventCategory))
-this._devToolsMetadataEvents.push(event);
-
-if(payload.ph!==WebInspector.TracingModel.Phase.Metadata)
-return;
-
-switch(payload.name){
-case WebInspector.TracingModel.MetadataEvent.ProcessSortIndex:
-process._setSortIndex(payload.args["sort_index"]);
-break;
-case WebInspector.TracingModel.MetadataEvent.ProcessName:
-var processName=payload.args["name"];
-process._setName(processName);
-this._processByName.set(processName,process);
-break;
-case WebInspector.TracingModel.MetadataEvent.ThreadSortIndex:
-process.threadById(payload.tid)._setSortIndex(payload.args["sort_index"]);
-break;
-case WebInspector.TracingModel.MetadataEvent.ThreadName:
-process.threadById(payload.tid)._setName(payload.args["name"]);
-break;}
-
-},
-
-
-
-
-minimumRecordTime:function()
-{
-return this._minimumRecordTime;
-},
-
-
-
-
-maximumRecordTime:function()
-{
-return this._maximumRecordTime;
-},
-
-
-
-
-sortedProcesses:function()
-{
-return WebInspector.TracingModel.NamedObject._sort(this._processById.valuesArray());
-},
-
-
-
-
-
-processByName:function(name)
-{
-return this._processByName.get(name);
-},
-
-
-
-
-
-
-threadByName:function(processName,threadName)
-{
-var process=this.processByName(processName);
-return process&&process.threadByName(threadName);
-},
-
-_processPendingAsyncEvents:function()
-{
-this._asyncEvents.stableSort(WebInspector.TracingModel.Event.compareStartTime);
-for(var i=0;i<this._asyncEvents.length;++i){
-var event=this._asyncEvents[i];
-if(WebInspector.TracingModel.isNestableAsyncPhase(event.phase))
-this._addNestableAsyncEvent(event);else
-
-this._addAsyncEvent(event);
-}
-this._asyncEvents=[];
-this._closeOpenAsyncEvents();
-},
-
-_closeOpenAsyncEvents:function()
-{
-for(var event of this._openAsyncEvents.values()){
-event.setEndTime(this._maximumRecordTime);
-
-
-event.steps[0].setEndTime(this._maximumRecordTime);
-}
-this._openAsyncEvents.clear();
-
-for(var eventStack of this._openNestableAsyncEvents.values()){
-while(eventStack.length)
-eventStack.pop().setEndTime(this._maximumRecordTime);
-}
-this._openNestableAsyncEvents.clear();
-},
-
-
-
-
-_addNestableAsyncEvent:function(event)
-{
-var phase=WebInspector.TracingModel.Phase;
-var key=event.categoriesString+"."+event.id;
-var openEventsStack=this._openNestableAsyncEvents.get(key);
-
-switch(event.phase){
-case phase.NestableAsyncBegin:
-if(!openEventsStack){
-openEventsStack=[];
-this._openNestableAsyncEvents.set(key,openEventsStack);
-}
-var asyncEvent=new WebInspector.TracingModel.AsyncEvent(event);
-openEventsStack.push(asyncEvent);
-event.thread._addAsyncEvent(asyncEvent);
-break;
-
-case phase.NestableAsyncInstant:
-if(openEventsStack&&openEventsStack.length)
-openEventsStack.peekLast()._addStep(event);
-break;
-
-case phase.NestableAsyncEnd:
-if(!openEventsStack||!openEventsStack.length)
-break;
-var top=openEventsStack.pop();
-if(top.name!==event.name){
-console.error(`Begin/end event mismatch for nestable async event, ${top.name} vs. ${event.name}, key: ${key}`);
-break;
-}
-top._addStep(event);}
-
-},
-
-
-
-
-_addAsyncEvent:function(event)
-{
-var phase=WebInspector.TracingModel.Phase;
-var key=event.categoriesString+"."+event.name+"."+event.id;
-var asyncEvent=this._openAsyncEvents.get(key);
-
-if(event.phase===phase.AsyncBegin){
-if(asyncEvent){
-console.error(`Event ${event.name} has already been started`);
-return;
-}
-asyncEvent=new WebInspector.TracingModel.AsyncEvent(event);
-this._openAsyncEvents.set(key,asyncEvent);
-event.thread._addAsyncEvent(asyncEvent);
-return;
-}
-if(!asyncEvent){
-
-return;
-}
-if(event.phase===phase.AsyncEnd){
-asyncEvent._addStep(event);
-this._openAsyncEvents.delete(key);
-return;
-}
-if(event.phase===phase.AsyncStepInto||event.phase===phase.AsyncStepPast){
-var lastStep=asyncEvent.steps.peekLast();
-if(lastStep.phase!==phase.AsyncBegin&&lastStep.phase!==event.phase){
-console.assert(false,"Async event step phase mismatch: "+lastStep.phase+" at "+lastStep.startTime+" vs. "+event.phase+" at "+event.startTime);
-return;
-}
-asyncEvent._addStep(event);
-return;
-}
-console.assert(false,"Invalid async event phase");
-},
-
-
-
-
-
-_parsedCategoriesForString:function(str)
-{
-var parsedCategories=this._parsedCategories.get(str);
-if(!parsedCategories){
-parsedCategories=new Set(str.split(","));
-this._parsedCategories.set(str,parsedCategories);
-}
-return parsedCategories;
-}};
-
-
-
-
-
-
-
-
-
-
-WebInspector.TracingModel.Event=function(categories,name,phase,startTime,thread)
-{
-
-this.categoriesString=categories;
-
-this._parsedCategories=thread._model._parsedCategoriesForString(categories);
-
-this.name=name;
-
-this.phase=phase;
-
-this.startTime=startTime;
-
-this.thread=thread;
-
-this.args={};
-
-
-this.warning=null;
-
-this.initiator=null;
-
-this.stackTrace=null;
-
-this.previewElement=null;
-
-this.url=null;
-
-this.backendNodeId=0;
-
-
-this.selfTime=0;
-};
-
-
-
-
-
-
-WebInspector.TracingModel.Event.fromPayload=function(payload,thread)
-{
-var event=new WebInspector.TracingModel.Event(payload.cat,payload.name,payload.ph,payload.ts/1000,thread);
-if(payload.args)
-event.addArgs(payload.args);else
-
-console.error("Missing mandatory event argument 'args' at "+payload.ts/1000);
-if(typeof payload.dur==="number")
-event.setEndTime((payload.ts+payload.dur)/1000);
-var id=WebInspector.TracingModel._extractId(payload);
-if(typeof id!=="undefined")
-event.id=id;
-if(payload.bind_id)
-event.bind_id=payload.bind_id;
-
-return event;
-};
-
-WebInspector.TracingModel.Event.prototype={
-
-
-
-
-hasCategory:function(categoryName)
-{
-return this._parsedCategories.has(categoryName);
-},
-
-
-
-
-setEndTime:function(endTime)
-{
-if(endTime<this.startTime){
-console.assert(false,"Event out of order: "+this.name);
-return;
-}
-this.endTime=endTime;
-this.duration=endTime-this.startTime;
-},
-
-
-
-
-addArgs:function(args)
-{
-
-for(var name in args){
-if(name in this.args)
-console.error("Same argument name ("+name+") is used for begin and end phases of "+this.name);
-this.args[name]=args[name];
-}
-},
-
-
-
-
-_complete:function(endEvent)
-{
-if(endEvent.args)
-this.addArgs(endEvent.args);else
-
-console.error("Missing mandatory event argument 'args' at "+endEvent.startTime);
-this.setEndTime(endEvent.startTime);
-},
-
-
-
-
-_setBackingStorage:function(backingStorage)
-{
-}};
-
-
-
-
-
-
-
-WebInspector.TracingModel.Event.compareStartTime=function(a,b)
-{
-return a.startTime-b.startTime;
-};
-
-
-
-
-
-
-WebInspector.TracingModel.Event.compareStartAndEndTime=function(a,b)
-{
-return a.startTime-b.startTime||b.endTime!==undefined&&a.endTime!==undefined&&b.endTime-a.endTime||0;
-};
-
-
-
-
-
-
-WebInspector.TracingModel.Event.orderedCompareStartTime=function(a,b)
-{
-
-
-
-return a.startTime-b.startTime||a.ordinal-b.ordinal||-1;
-};
-
-
-
-
-
-
-
-
-
-WebInspector.TracingModel.ObjectSnapshot=function(category,name,startTime,thread)
-{
-WebInspector.TracingModel.Event.call(this,category,name,WebInspector.TracingModel.Phase.SnapshotObject,startTime,thread);
-};
-
-
-
-
-
-
-WebInspector.TracingModel.ObjectSnapshot.fromPayload=function(payload,thread)
-{
-var snapshot=new WebInspector.TracingModel.ObjectSnapshot(payload.cat,payload.name,payload.ts/1000,thread);
-var id=WebInspector.TracingModel._extractId(payload);
-if(typeof id!=="undefined")
-snapshot.id=id;
-if(!payload.args||!payload.args["snapshot"]){
-console.error("Missing mandatory 'snapshot' argument at "+payload.ts/1000);
-return snapshot;
-}
-if(payload.args)
-snapshot.addArgs(payload.args);
-return snapshot;
-};
-
-WebInspector.TracingModel.ObjectSnapshot.prototype={
-
-
-
-requestObject:function(callback)
-{
-var snapshot=this.args["snapshot"];
-if(snapshot){
-callback(snapshot);
-return;
-}
-this._backingStorage().then(onRead,callback.bind(null,null));
-
-
-
-function onRead(result)
-{
-if(!result){
-callback(null);
-return;
-}
-try{
-var payload=JSON.parse(result);
-callback(payload["args"]["snapshot"]);
-}catch(e){
-WebInspector.console.error("Malformed event data in backing storage");
-callback(null);
-}
-}
-},
-
-
-
-
-objectPromise:function()
-{
-if(!this._objectPromise)
-this._objectPromise=new Promise(this.requestObject.bind(this));
-return this._objectPromise;
-},
-
-
-
-
-
-_setBackingStorage:function(backingStorage)
-{
-if(!backingStorage)
-return;
-this._backingStorage=backingStorage;
-this.args={};
-},
-
-__proto__:WebInspector.TracingModel.Event.prototype};
-
-
-
-
-
-
-
-WebInspector.TracingModel.AsyncEvent=function(startEvent)
-{
-WebInspector.TracingModel.Event.call(this,startEvent.categoriesString,startEvent.name,startEvent.phase,startEvent.startTime,startEvent.thread);
-this.addArgs(startEvent.args);
-this.steps=[startEvent];
-};
-
-WebInspector.TracingModel.AsyncEvent.prototype={
-
-
-
-_addStep:function(event)
-{
-this.steps.push(event);
-if(event.phase===WebInspector.TracingModel.Phase.AsyncEnd||event.phase===WebInspector.TracingModel.Phase.NestableAsyncEnd){
-this.setEndTime(event.startTime);
-
-
-this.steps[0].setEndTime(event.startTime);
-}
-},
-
-__proto__:WebInspector.TracingModel.Event.prototype};
-
-
-
-
-
-WebInspector.TracingModel.NamedObject=function()
-{
-};
-
-WebInspector.TracingModel.NamedObject.prototype=
-{
-
-
-
-_setName:function(name)
-{
-this._name=name;
-},
-
-
-
-
-name:function()
-{
-return this._name;
-},
-
-
-
-
-_setSortIndex:function(sortIndex)
-{
-this._sortIndex=sortIndex;
-}};
-
-
-
-
-
-WebInspector.TracingModel.NamedObject._sort=function(array)
-{
-
-
-
-
-function comparator(a,b)
-{
-return a._sortIndex!==b._sortIndex?a._sortIndex-b._sortIndex:a.name().localeCompare(b.name());
-}
-return array.sort(comparator);
-};
-
-
-
-
-
-
-
-WebInspector.TracingModel.Process=function(model,id)
-{
-WebInspector.TracingModel.NamedObject.call(this);
-this._setName("Process "+id);
-this._id=id;
-
-this._threads=new Map();
-this._threadByName=new Map();
-this._model=model;
-};
-
-WebInspector.TracingModel.Process.prototype={
-
-
-
-id:function()
-{
-return this._id;
-},
-
-
-
-
-
-threadById:function(id)
-{
-var thread=this._threads.get(id);
-if(!thread){
-thread=new WebInspector.TracingModel.Thread(this,id);
-this._threads.set(id,thread);
-}
-return thread;
-},
-
-
-
-
-
-threadByName:function(name)
-{
-return this._threadByName.get(name)||null;
-},
-
-
-
-
-
-_setThreadByName:function(name,thread)
-{
-this._threadByName.set(name,thread);
-},
-
-
-
-
-
-_addEvent:function(payload)
-{
-return this.threadById(payload.tid)._addEvent(payload);
-},
-
-
-
-
-sortedThreads:function()
-{
-return WebInspector.TracingModel.NamedObject._sort(this._threads.valuesArray());
-},
-
-__proto__:WebInspector.TracingModel.NamedObject.prototype};
-
-
-
-
-
-
-
-
-WebInspector.TracingModel.Thread=function(process,id)
-{
-WebInspector.TracingModel.NamedObject.call(this);
-this._process=process;
-this._setName("Thread "+id);
-this._events=[];
-this._asyncEvents=[];
-this._id=id;
-this._model=process._model;
-};
-
-WebInspector.TracingModel.Thread.prototype={
-tracingComplete:function()
-{
-this._asyncEvents.stableSort(WebInspector.TracingModel.Event.compareStartAndEndTime);
-this._events.stableSort(WebInspector.TracingModel.Event.compareStartTime);
-var phases=WebInspector.TracingModel.Phase;
-var stack=[];
-for(var i=0;i<this._events.length;++i){
-var e=this._events[i];
-e.ordinal=i;
-switch(e.phase){
-case phases.End:
-this._events[i]=null;
-
-if(!stack.length)
-continue;
-var top=stack.pop();
-if(top.name!==e.name||top.categoriesString!==e.categoriesString)
-console.error("B/E events mismatch at "+top.startTime+" ("+top.name+") vs. "+e.startTime+" ("+e.name+")");else
-
-top._complete(e);
-break;
-case phases.Begin:
-stack.push(e);
-break;}
-
-}
-while(stack.length)
-stack.pop().setEndTime(this._model.maximumRecordTime());
-this._events.remove(null,false);
-},
-
-
-
-
-
-_addEvent:function(payload)
-{
-var event=payload.ph===WebInspector.TracingModel.Phase.SnapshotObject?
-WebInspector.TracingModel.ObjectSnapshot.fromPayload(payload,this):
-WebInspector.TracingModel.Event.fromPayload(payload,this);
-if(WebInspector.TracingModel.isTopLevelEvent(event)){
-
-if(this._lastTopLevelEvent&&this._lastTopLevelEvent.endTime>event.startTime)
-return null;
-this._lastTopLevelEvent=event;
-}
-this._events.push(event);
-return event;
-},
-
-
-
-
-_addAsyncEvent:function(asyncEvent)
-{
-this._asyncEvents.push(asyncEvent);
-},
-
-
-
-
-
-_setName:function(name)
-{
-WebInspector.TracingModel.NamedObject.prototype._setName.call(this,name);
-this._process._setThreadByName(name,this);
-},
-
-
-
-
-id:function()
-{
-return this._id;
-},
-
-
-
-
-process:function()
-{
-return this._process;
-},
-
-
-
-
-events:function()
-{
-return this._events;
-},
-
-
-
-
-asyncEvents:function()
-{
-return this._asyncEvents;
-},
-
-__proto__:WebInspector.TracingModel.NamedObject.prototype};
-
-
-},{}],123:[function(require,module,exports){
+},{}],115:[function(require,module,exports){
@@ -56172,8230 +52104,7 @@ WebInspector.console.error(WebInspector.UIString("Failed to save timeline: %s (%
}};
-},{}],124:[function(require,module,exports){
-
-
-
-
-
-
-
-
-
-
-WebInspector.TimelineTreeView=function(model,filters)
-{
-WebInspector.VBox.call(this);
-this.element.classList.add("timeline-tree-view");
-
-this._model=model;
-this._linkifier=new WebInspector.Linkifier();
-
-this._filters=filters.slice();
-
-var columns=[];
-this._populateColumns(columns);
-
-var mainView=new WebInspector.VBox();
-this._populateToolbar(mainView.element);
-this._dataGrid=new WebInspector.SortableDataGrid(columns);
-this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChanged,this._sortingChanged,this);
-this._dataGrid.element.addEventListener("mousemove",this._onMouseMove.bind(this),true);
-this._dataGrid.setResizeMethod(WebInspector.DataGrid.ResizeMethod.Last);
-this._dataGrid.asWidget().show(mainView.element);
-
-this._splitWidget=new WebInspector.SplitWidget(true,true,"timelineTreeViewDetailsSplitWidget");
-this._splitWidget.show(this.element);
-this._splitWidget.setMainWidget(mainView);
-
-this._detailsView=new WebInspector.VBox();
-this._detailsView.element.classList.add("timeline-details-view","timeline-details-view-body");
-this._splitWidget.setSidebarWidget(this._detailsView);
-this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode,this._updateDetailsForSelection,this);
-
-
-this._lastSelectedNode;
-};
-
-WebInspector.TimelineTreeView.prototype={
-
-
-
-updateContents:function(selection)
-{
-this.setRange(selection.startTime(),selection.endTime());
-},
-
-
-
-
-
-setRange:function(startTime,endTime)
-{
-this._startTime=startTime;
-this._endTime=endTime;
-this._refreshTree();
-},
-
-
-
-
-_exposePercentages:function()
-{
-return false;
-},
-
-
-
-
-_populateToolbar:function(parent){},
-
-
-
-
-_onHover:function(node){},
-
-
-
-
-
-_linkifyLocation:function(event)
-{
-var target=this._model.targetByEvent(event);
-if(!target)
-return null;
-var frame=WebInspector.TimelineProfileTree.eventStackFrame(event);
-if(!frame)
-return null;
-return this._linkifier.maybeLinkifyConsoleCallFrame(target,frame);
-},
-
-
-
-
-
-selectProfileNode:function(treeNode,suppressSelectedEvent)
-{
-var pathToRoot=[];
-for(var node=treeNode;node;node=node.parent)
-pathToRoot.push(node);
-for(var i=pathToRoot.length-1;i>0;--i){
-var gridNode=this._dataGridNodeForTreeNode(pathToRoot[i]);
-if(gridNode&&gridNode.dataGrid)
-gridNode.expand();
-}
-var gridNode=this._dataGridNodeForTreeNode(treeNode);
-if(gridNode.dataGrid){
-gridNode.reveal();
-gridNode.select(suppressSelectedEvent);
-}
-},
-
-_refreshTree:function()
-{
-this._linkifier.reset();
-this._dataGrid.rootNode().removeChildren();
-var tree=this._buildTree();
-if(!tree.children)
-return;
-var maxSelfTime=0;
-var maxTotalTime=0;
-for(var child of tree.children.values()){
-maxSelfTime=Math.max(maxSelfTime,child.selfTime);
-maxTotalTime=Math.max(maxTotalTime,child.totalTime);
-}
-for(var child of tree.children.values()){
-
-var gridNode=new WebInspector.TimelineTreeView.TreeGridNode(child,tree.totalTime,maxSelfTime,maxTotalTime,this);
-this._dataGrid.insertChild(gridNode);
-}
-this._sortingChanged();
-this._updateDetailsForSelection();
-},
-
-
-
-
-_buildTree:function()
-{
-throw new Error("Not Implemented");
-},
-
-
-
-
-
-_buildTopDownTree:function(eventIdCallback)
-{
-return WebInspector.TimelineProfileTree.buildTopDown(this._model.mainThreadEvents(),this._filters,this._startTime,this._endTime,eventIdCallback);
-},
-
-
-
-
-_populateColumns:function(columns)
-{
-columns.push({id:"self",title:WebInspector.UIString("Self Time"),width:"110px",fixedWidth:true,sortable:true});
-columns.push({id:"total",title:WebInspector.UIString("Total Time"),width:"110px",fixedWidth:true,sortable:true});
-columns.push({id:"activity",title:WebInspector.UIString("Activity"),disclosure:true,sortable:true});
-},
-
-_sortingChanged:function()
-{
-var columnIdentifier=this._dataGrid.sortColumnIdentifier();
-if(!columnIdentifier)
-return;
-var sortFunction;
-switch(columnIdentifier){
-case"startTime":
-sortFunction=compareStartTime;
-break;
-case"self":
-sortFunction=compareNumericField.bind(null,"selfTime");
-break;
-case"total":
-sortFunction=compareNumericField.bind(null,"totalTime");
-break;
-case"activity":
-sortFunction=compareName;
-break;
-default:
-console.assert(false,"Unknown sort field: "+columnIdentifier);
-return;}
-
-this._dataGrid.sortNodes(sortFunction,!this._dataGrid.isSortOrderAscending());
-
-
-
-
-
-
-
-function compareNumericField(field,a,b)
-{
-var nodeA=a;
-var nodeB=b;
-return nodeA._profileNode[field]-nodeB._profileNode[field];
-}
-
-
-
-
-
-
-function compareStartTime(a,b)
-{
-var nodeA=a;
-var nodeB=b;
-return nodeA._profileNode.event.startTime-nodeB._profileNode.event.startTime;
-}
-
-
-
-
-
-
-function compareName(a,b)
-{
-var nodeA=a;
-var nodeB=b;
-var nameA=WebInspector.TimelineTreeView.eventNameForSorting(nodeA._profileNode.event);
-var nameB=WebInspector.TimelineTreeView.eventNameForSorting(nodeB._profileNode.event);
-return nameA.localeCompare(nameB);
-}
-},
-
-_updateDetailsForSelection:function()
-{
-var selectedNode=this._dataGrid.selectedNode?this._dataGrid.selectedNode._profileNode:null;
-if(selectedNode===this._lastSelectedNode)
-return;
-this._lastSelectedNode=selectedNode;
-this._detailsView.detachChildWidgets();
-this._detailsView.element.removeChildren();
-if(!selectedNode||!this._showDetailsForNode(selectedNode)){
-var banner=this._detailsView.element.createChild("div","full-widget-dimmed-banner");
-banner.createTextChild(WebInspector.UIString("Select item for details."));
-}
-},
-
-
-
-
-
-_showDetailsForNode:function(node)
-{
-return false;
-},
-
-
-
-
-_onMouseMove:function(event)
-{
-var gridNode=event.target&&event.target instanceof Node?
-this._dataGrid.dataGridNodeFromNode(event.target):
-null;
-var profileNode=gridNode&&gridNode._profileNode;
-if(profileNode===this._lastHoveredProfileNode)
-return;
-this._lastHoveredProfileNode=profileNode;
-this._onHover(profileNode);
-},
-
-
-
-
-
-_dataGridNodeForTreeNode:function(treeNode)
-{
-return treeNode[WebInspector.TimelineTreeView.TreeGridNode._gridNodeSymbol]||null;
-},
-
-__proto__:WebInspector.VBox.prototype};
-
-
-
-
-
-
-WebInspector.TimelineTreeView.eventNameForSorting=function(event)
-{
-if(event.name===WebInspector.TimelineModel.RecordType.JSFrame){
-var data=event.args["data"];
-return data["functionName"]+"@"+(data["scriptId"]||data["url"]||"");
-}
-return event.name+":@"+WebInspector.TimelineProfileTree.eventURL(event);
-};
-
-
-
-
-
-
-
-
-
-
-WebInspector.TimelineTreeView.GridNode=function(profileNode,grandTotalTime,maxSelfTime,maxTotalTime,treeView)
-{
-this._populated=false;
-this._profileNode=profileNode;
-this._treeView=treeView;
-this._grandTotalTime=grandTotalTime;
-this._maxSelfTime=maxSelfTime;
-this._maxTotalTime=maxTotalTime;
-WebInspector.SortableDataGridNode.call(this,null,false);
-};
-
-WebInspector.TimelineTreeView.GridNode.prototype={
-
-
-
-
-
-createCell:function(columnIdentifier)
-{
-if(columnIdentifier==="activity")
-return this._createNameCell(columnIdentifier);
-return this._createValueCell(columnIdentifier)||WebInspector.DataGridNode.prototype.createCell.call(this,columnIdentifier);
-},
-
-
-
-
-
-_createNameCell:function(columnIdentifier)
-{
-var cell=this.createTD(columnIdentifier);
-var container=cell.createChild("div","name-container");
-var icon=container.createChild("div","activity-icon");
-var name=container.createChild("div","activity-name");
-var event=this._profileNode.event;
-if(this._profileNode.isGroupNode()){
-var treeView=this._treeView;
-var info=treeView._displayInfoForGroupNode(this._profileNode);
-name.textContent=info.name;
-icon.style.backgroundColor=info.color;
-}else if(event){
-var data=event.args["data"];
-var deoptReason=data&&data["deoptReason"];
-if(deoptReason)
-container.createChild("div","activity-warning").title=WebInspector.UIString("Not optimized: %s",deoptReason);
-name.textContent=event.name===WebInspector.TimelineModel.RecordType.JSFrame?
-WebInspector.beautifyFunctionName(event.args["data"]["functionName"]):
-WebInspector.TimelineUIUtils.eventTitle(event);
-var link=this._treeView._linkifyLocation(event);
-if(link)
-container.createChild("div","activity-link").appendChild(link);
-icon.style.backgroundColor=WebInspector.TimelineUIUtils.eventColor(event);
-}
-return cell;
-},
-
-
-
-
-
-_createValueCell:function(columnIdentifier)
-{
-if(columnIdentifier!=="self"&&columnIdentifier!=="total"&&columnIdentifier!=="startTime")
-return null;
-
-var showPercents=false;
-var value;
-var maxTime;
-switch(columnIdentifier){
-case"startTime":
-value=this._profileNode.event.startTime-this._treeView._model.minimumRecordTime();
-break;
-case"self":
-value=this._profileNode.selfTime;
-maxTime=this._maxSelfTime;
-showPercents=true;
-break;
-case"total":
-value=this._profileNode.totalTime;
-maxTime=this._maxTotalTime;
-showPercents=true;
-break;
-default:
-return null;}
-
-var cell=this.createTD(columnIdentifier);
-cell.className="numeric-column";
-var textDiv=cell.createChild("div");
-textDiv.createChild("span").textContent=WebInspector.UIString("%.1f\u2009ms",value);
-
-if(showPercents&&this._treeView._exposePercentages())
-textDiv.createChild("span","percent-column").textContent=WebInspector.UIString("%.1f\u2009%%",value/this._grandTotalTime*100);
-if(maxTime){
-textDiv.classList.add("background-percent-bar");
-cell.createChild("div","background-bar-container").createChild("div","background-bar").style.width=(value*100/maxTime).toFixed(1)+"%";
-}
-return cell;
-},
-
-__proto__:WebInspector.SortableDataGridNode.prototype};
-
-
-
-
-
-
-
-
-
-
-
-WebInspector.TimelineTreeView.TreeGridNode=function(profileNode,grandTotalTime,maxSelfTime,maxTotalTime,treeView)
-{
-WebInspector.TimelineTreeView.GridNode.call(this,profileNode,grandTotalTime,maxSelfTime,maxTotalTime,treeView);
-this.hasChildren=this._profileNode.children?this._profileNode.children.size>0:false;
-profileNode[WebInspector.TimelineTreeView.TreeGridNode._gridNodeSymbol]=this;
-};
-
-WebInspector.TimelineTreeView.TreeGridNode._gridNodeSymbol=Symbol("treeGridNode");
-
-WebInspector.TimelineTreeView.TreeGridNode.prototype={
-
-
-
-populate:function()
-{
-if(this._populated)
-return;
-this._populated=true;
-if(!this._profileNode.children)
-return;
-for(var node of this._profileNode.children.values()){
-var gridNode=new WebInspector.TimelineTreeView.TreeGridNode(node,this._grandTotalTime,this._maxSelfTime,this._maxTotalTime,this._treeView);
-this.insertChildOrdered(gridNode);
-}
-},
-
-__proto__:WebInspector.TimelineTreeView.GridNode.prototype};
-
-
-
-
-
-
-
-
-
-WebInspector.AggregatedTimelineTreeView=function(model,filters)
-{
-this._groupBySetting=WebInspector.settings.createSetting("timelineTreeGroupBy",WebInspector.TimelineAggregator.GroupBy.Category);
-WebInspector.TimelineTreeView.call(this,model,filters);
-var nonessentialEvents=[
-WebInspector.TimelineModel.RecordType.EventDispatch,
-WebInspector.TimelineModel.RecordType.FunctionCall,
-WebInspector.TimelineModel.RecordType.TimerFire];
-
-this._filters.push(new WebInspector.ExclusiveNameFilter(nonessentialEvents));
-this._stackView=new WebInspector.TimelineStackView(this);
-this._stackView.addEventListener(WebInspector.TimelineStackView.Events.SelectionChanged,this._onStackViewSelectionChanged,this);
-};
-
-WebInspector.AggregatedTimelineTreeView.prototype={
-
-
-
-
-updateContents:function(selection)
-{
-this._updateExtensionResolver();
-WebInspector.TimelineTreeView.prototype.updateContents.call(this,selection);
-var rootNode=this._dataGrid.rootNode();
-if(rootNode.children.length)
-rootNode.children[0].revealAndSelect();
-},
-
-_updateExtensionResolver:function()
-{
-this._executionContextNamesByOrigin=new Map();
-for(var target of WebInspector.targetManager.targets()){
-for(var context of target.runtimeModel.executionContexts())
-this._executionContextNamesByOrigin.set(context.origin,context.name);
-}
-},
-
-
-
-
-
-_displayInfoForGroupNode:function(node)
-{
-var categories=WebInspector.TimelineUIUtils.categories();
-var color=node.id?WebInspector.TimelineUIUtils.eventColor(node.event):categories["other"].color;
-
-switch(this._groupBySetting.get()){
-case WebInspector.TimelineAggregator.GroupBy.Category:
-var category=categories[node.id]||categories["other"];
-return{name:category.title,color:category.color};
-
-case WebInspector.TimelineAggregator.GroupBy.Domain:
-case WebInspector.TimelineAggregator.GroupBy.Subdomain:
-var name=node.id;
-if(WebInspector.TimelineAggregator.isExtensionInternalURL(name))
-name=WebInspector.UIString("[Chrome extensions overhead]");else
-if(name.startsWith("chrome-extension"))
-name=this._executionContextNamesByOrigin.get(name)||name;
-return{
-name:name||WebInspector.UIString("unattributed"),
-color:color};
-
-
-case WebInspector.TimelineAggregator.GroupBy.EventName:
-var name=node.event.name===WebInspector.TimelineModel.RecordType.JSFrame?
-WebInspector.UIString("JavaScript"):WebInspector.TimelineUIUtils.eventTitle(node.event);
-return{
-name:name,
-color:node.event.name===WebInspector.TimelineModel.RecordType.JSFrame?
-WebInspector.TimelineUIUtils.eventStyle(node.event).category.color:color};
-
-
-case WebInspector.TimelineAggregator.GroupBy.URL:
-break;
-
-default:
-console.assert(false,"Unexpected aggregation type");}
-
-return{
-name:node.id||WebInspector.UIString("unattributed"),
-color:color};
-
-},
-
-
-
-
-
-_populateToolbar:function(parent)
-{
-var panelToolbar=new WebInspector.Toolbar("",parent);
-this._groupByCombobox=new WebInspector.ToolbarComboBox(this._onGroupByChanged.bind(this));
-
-
-
-
-
-function addGroupingOption(name,id)
-{
-var option=this._groupByCombobox.createOption(name,"",id);
-this._groupByCombobox.addOption(option);
-if(id===this._groupBySetting.get())
-this._groupByCombobox.select(option);
-}
-addGroupingOption.call(this,WebInspector.UIString("No Grouping"),WebInspector.TimelineAggregator.GroupBy.None);
-addGroupingOption.call(this,WebInspector.UIString("Group by Activity"),WebInspector.TimelineAggregator.GroupBy.EventName);
-addGroupingOption.call(this,WebInspector.UIString("Group by Category"),WebInspector.TimelineAggregator.GroupBy.Category);
-addGroupingOption.call(this,WebInspector.UIString("Group by Domain"),WebInspector.TimelineAggregator.GroupBy.Domain);
-addGroupingOption.call(this,WebInspector.UIString("Group by Subdomain"),WebInspector.TimelineAggregator.GroupBy.Subdomain);
-addGroupingOption.call(this,WebInspector.UIString("Group by URL"),WebInspector.TimelineAggregator.GroupBy.URL);
-panelToolbar.appendToolbarItem(this._groupByCombobox);
-},
-
-
-
-
-
-_buildHeaviestStack:function(treeNode)
-{
-console.assert(!!treeNode.parent,"Attempt to build stack for tree root");
-var result=[];
-
-for(var node=treeNode;node&&node.parent;node=node.parent)
-result.push(node);
-result=result.reverse();
-for(node=treeNode;node&&node.children&&node.children.size;){
-var children=Array.from(node.children.values());
-node=children.reduce((a,b)=>a.totalTime>b.totalTime?a:b);
-result.push(node);
-}
-return result;
-},
-
-
-
-
-
-_exposePercentages:function()
-{
-return true;
-},
-
-_onGroupByChanged:function()
-{
-this._groupBySetting.set(this._groupByCombobox.selectedOption().value);
-this._refreshTree();
-},
-
-_onStackViewSelectionChanged:function()
-{
-var treeNode=this._stackView.selectedTreeNode();
-if(treeNode)
-this.selectProfileNode(treeNode,true);
-},
-
-
-
-
-
-
-_showDetailsForNode:function(node)
-{
-var stack=this._buildHeaviestStack(node);
-this._stackView.setStack(stack,node);
-this._stackView.show(this._detailsView.element);
-return true;
-},
-
-
-
-
-_createAggregator:function()
-{
-return new WebInspector.TimelineAggregator(
-event=>WebInspector.TimelineUIUtils.eventStyle(event).title,
-event=>WebInspector.TimelineUIUtils.eventStyle(event).category.name);
-
-},
-
-__proto__:WebInspector.TimelineTreeView.prototype};
-
-
-
-
-
-
-
-
-WebInspector.CallTreeTimelineTreeView=function(model,filters)
-{
-WebInspector.AggregatedTimelineTreeView.call(this,model,filters);
-this._dataGrid.markColumnAsSortedBy("total",WebInspector.DataGrid.Order.Descending);
-};
-
-WebInspector.CallTreeTimelineTreeView.prototype={
-
-
-
-
-_buildTree:function()
-{
-var topDown=this._buildTopDownTree(WebInspector.TimelineAggregator.eventId);
-return this._createAggregator().performGrouping(topDown,this._groupBySetting.get());
-},
-
-__proto__:WebInspector.AggregatedTimelineTreeView.prototype};
-
-
-
-
-
-
-
-
-WebInspector.BottomUpTimelineTreeView=function(model,filters)
-{
-WebInspector.AggregatedTimelineTreeView.call(this,model,filters);
-this._dataGrid.markColumnAsSortedBy("self",WebInspector.DataGrid.Order.Descending);
-};
-
-WebInspector.BottomUpTimelineTreeView.prototype={
-
-
-
-
-_buildTree:function()
-{
-var topDown=this._buildTopDownTree(WebInspector.TimelineAggregator.eventId);
-return WebInspector.TimelineProfileTree.buildBottomUp(topDown,this._createAggregator().groupFunction(this._groupBySetting.get()));
-},
-
-__proto__:WebInspector.AggregatedTimelineTreeView.prototype};
-
-
-
-
-
-
-
-
-
-WebInspector.EventsTimelineTreeView=function(model,filters,delegate)
-{
-this._filtersControl=new WebInspector.TimelineFilters();
-this._filtersControl.addEventListener(WebInspector.TimelineFilters.Events.FilterChanged,this._onFilterChanged,this);
-WebInspector.TimelineTreeView.call(this,model,filters);
-this._delegate=delegate;
-this._filters.push.apply(this._filters,this._filtersControl.filters());
-this._dataGrid.markColumnAsSortedBy("startTime",WebInspector.DataGrid.Order.Ascending);
-};
-
-WebInspector.EventsTimelineTreeView.prototype={
-
-
-
-
-updateContents:function(selection)
-{
-WebInspector.TimelineTreeView.prototype.updateContents.call(this,selection);
-if(selection.type()===WebInspector.TimelineSelection.Type.TraceEvent){
-var event=selection.object();
-this._selectEvent(event,true);
-}
-},
-
-
-
-
-
-_buildTree:function()
-{
-this._currentTree=this._buildTopDownTree();
-return this._currentTree;
-},
-
-_onFilterChanged:function()
-{
-var selectedEvent=this._lastSelectedNode&&this._lastSelectedNode.event;
-this._refreshTree();
-if(selectedEvent)
-this._selectEvent(selectedEvent,false);
-},
-
-
-
-
-
-_findNodeWithEvent:function(event)
-{
-var iterators=[this._currentTree.children.values()];
-
-while(iterators.length){
-var iterator=iterators.peekLast().next();
-if(iterator.done){
-iterators.pop();
-continue;
-}
-var child=iterator.value;
-if(child.event===event)
-return child;
-if(child.children)
-iterators.push(child.children.values());
-}
-return null;
-},
-
-
-
-
-
-_selectEvent:function(event,expand)
-{
-var node=this._findNodeWithEvent(event);
-if(!node)
-return;
-this.selectProfileNode(node,false);
-if(expand)
-this._dataGridNodeForTreeNode(node).expand();
-},
-
-
-
-
-
-_populateColumns:function(columns)
-{
-columns.push({id:"startTime",title:WebInspector.UIString("Start Time"),width:"110px",fixedWidth:true,sortable:true});
-WebInspector.TimelineTreeView.prototype._populateColumns.call(this,columns);
-},
-
-
-
-
-
-_populateToolbar:function(parent)
-{
-var filtersWidget=this._filtersControl.filtersWidget();
-filtersWidget.forceShowFilterBar();
-filtersWidget.show(parent);
-},
-
-
-
-
-
-
-_showDetailsForNode:function(node)
-{
-var traceEvent=node.event;
-if(!traceEvent)
-return false;
-WebInspector.TimelineUIUtils.buildTraceEventDetails(traceEvent,this._model,this._linkifier,false,showDetails.bind(this));
-return true;
-
-
-
-
-
-function showDetails(fragment)
-{
-this._detailsView.element.appendChild(fragment);
-}
-},
-
-
-
-
-
-_onHover:function(node)
-{
-this._delegate.highlightEvent(node&&node.event);
-},
-
-__proto__:WebInspector.TimelineTreeView.prototype};
-
-
-
-
-
-
-WebInspector.TimelineStackView=function(treeView)
-{
-WebInspector.VBox.call(this);
-var header=this.element.createChild("div","timeline-stack-view-header");
-header.textContent=WebInspector.UIString("Heaviest stack");
-this._treeView=treeView;
-var columns=[
-{id:"total",title:WebInspector.UIString("Total Time"),fixedWidth:true,width:"110px"},
-{id:"activity",title:WebInspector.UIString("Activity")}];
-
-this._dataGrid=new WebInspector.ViewportDataGrid(columns);
-this._dataGrid.setResizeMethod(WebInspector.DataGrid.ResizeMethod.Last);
-this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode,this._onSelectionChanged,this);
-this._dataGrid.asWidget().show(this.element);
-};
-
-
-WebInspector.TimelineStackView.Events={
-SelectionChanged:Symbol("SelectionChanged")};
-
-
-WebInspector.TimelineStackView.prototype={
-
-
-
-
-setStack:function(stack,selectedNode)
-{
-var rootNode=this._dataGrid.rootNode();
-rootNode.removeChildren();
-var nodeToReveal=null;
-var totalTime=Math.max.apply(Math,stack.map(node=>node.totalTime));
-for(var node of stack){
-var gridNode=new WebInspector.TimelineTreeView.GridNode(node,totalTime,totalTime,totalTime,this._treeView);
-rootNode.appendChild(gridNode);
-if(node===selectedNode)
-nodeToReveal=gridNode;
-}
-nodeToReveal.revealAndSelect();
-},
-
-
-
-
-selectedTreeNode:function()
-{
-var selectedNode=this._dataGrid.selectedNode;
-return selectedNode&&selectedNode._profileNode;
-},
-
-_onSelectionChanged:function()
-{
-this.dispatchEventToListeners(WebInspector.TimelineStackView.Events.SelectionChanged);
-},
-
-__proto__:WebInspector.VBox.prototype};
-
-
-},{}],125:[function(require,module,exports){
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-WebInspector.TimelineUIUtils=function(){};
-
-
-
-
-
-
-
-WebInspector.TimelineRecordStyle=function(title,category,hidden)
-{
-this.title=title;
-this.category=category;
-this.hidden=!!hidden;
-};
-
-
-
-
-WebInspector.TimelineUIUtils._initEventStyles=function()
-{
-if(WebInspector.TimelineUIUtils._eventStylesMap)
-return WebInspector.TimelineUIUtils._eventStylesMap;
-
-var recordTypes=WebInspector.TimelineModel.RecordType;
-var categories=WebInspector.TimelineUIUtils.categories();
-
-var eventStyles={};
-eventStyles[recordTypes.Task]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Task"),categories["other"]);
-eventStyles[recordTypes.Program]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Other"),categories["other"]);
-eventStyles[recordTypes.Animation]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Animation"),categories["rendering"]);
-eventStyles[recordTypes.EventDispatch]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Event"),categories["scripting"]);
-eventStyles[recordTypes.RequestMainThreadFrame]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Request Main Thread Frame"),categories["rendering"],true);
-eventStyles[recordTypes.BeginFrame]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Frame Start"),categories["rendering"],true);
-eventStyles[recordTypes.BeginMainThreadFrame]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Frame Start (main thread)"),categories["rendering"],true);
-eventStyles[recordTypes.DrawFrame]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Draw Frame"),categories["rendering"],true);
-eventStyles[recordTypes.HitTest]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Hit Test"),categories["rendering"]);
-eventStyles[recordTypes.ScheduleStyleRecalculation]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Schedule Style Recalculation"),categories["rendering"],true);
-eventStyles[recordTypes.RecalculateStyles]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Recalculate Style"),categories["rendering"]);
-eventStyles[recordTypes.UpdateLayoutTree]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Recalculate Style"),categories["rendering"]);
-eventStyles[recordTypes.InvalidateLayout]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Invalidate Layout"),categories["rendering"],true);
-eventStyles[recordTypes.Layout]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Layout"),categories["rendering"]);
-eventStyles[recordTypes.PaintSetup]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Paint Setup"),categories["painting"]);
-eventStyles[recordTypes.PaintImage]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Paint Image"),categories["painting"],true);
-eventStyles[recordTypes.UpdateLayer]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Update Layer"),categories["painting"],true);
-eventStyles[recordTypes.UpdateLayerTree]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Update Layer Tree"),categories["rendering"]);
-eventStyles[recordTypes.Paint]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Paint"),categories["painting"]);
-eventStyles[recordTypes.RasterTask]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Rasterize Paint"),categories["painting"]);
-eventStyles[recordTypes.ScrollLayer]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Scroll"),categories["rendering"]);
-eventStyles[recordTypes.CompositeLayers]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Composite Layers"),categories["painting"]);
-eventStyles[recordTypes.ParseHTML]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Parse HTML"),categories["loading"]);
-eventStyles[recordTypes.ParseAuthorStyleSheet]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Parse Stylesheet"),categories["loading"]);
-eventStyles[recordTypes.TimerInstall]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Install Timer"),categories["scripting"]);
-eventStyles[recordTypes.TimerRemove]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Remove Timer"),categories["scripting"]);
-eventStyles[recordTypes.TimerFire]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Timer Fired"),categories["scripting"]);
-eventStyles[recordTypes.XHRReadyStateChange]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("XHR Ready State Change"),categories["scripting"]);
-eventStyles[recordTypes.XHRLoad]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("XHR Load"),categories["scripting"]);
-eventStyles[recordTypes.CompileScript]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Compile Script"),categories["scripting"]);
-eventStyles[recordTypes.EvaluateScript]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Evaluate Script"),categories["scripting"]);
-eventStyles[recordTypes.ParseScriptOnBackground]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Parse Script"),categories["scripting"]);
-eventStyles[recordTypes.MarkLoad]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Load event"),categories["scripting"],true);
-eventStyles[recordTypes.MarkDOMContent]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("DOMContentLoaded event"),categories["scripting"],true);
-eventStyles[recordTypes.MarkFirstPaint]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("First paint"),categories["painting"],true);
-eventStyles[recordTypes.TimeStamp]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Timestamp"),categories["scripting"]);
-eventStyles[recordTypes.ConsoleTime]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Console Time"),categories["scripting"]);
-eventStyles[recordTypes.UserTiming]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("User Timing"),categories["scripting"]);
-eventStyles[recordTypes.ResourceSendRequest]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Send Request"),categories["loading"]);
-eventStyles[recordTypes.ResourceReceiveResponse]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Receive Response"),categories["loading"]);
-eventStyles[recordTypes.ResourceFinish]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Finish Loading"),categories["loading"]);
-eventStyles[recordTypes.ResourceReceivedData]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Receive Data"),categories["loading"]);
-eventStyles[recordTypes.RunMicrotasks]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Run Microtasks"),categories["scripting"]);
-eventStyles[recordTypes.FunctionCall]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Function Call"),categories["scripting"]);
-eventStyles[recordTypes.GCEvent]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("GC Event"),categories["scripting"]);
-eventStyles[recordTypes.MajorGC]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Major GC"),categories["scripting"]);
-eventStyles[recordTypes.MinorGC]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Minor GC"),categories["scripting"]);
-eventStyles[recordTypes.JSFrame]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("JS Frame"),categories["scripting"]);
-eventStyles[recordTypes.RequestAnimationFrame]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Request Animation Frame"),categories["scripting"]);
-eventStyles[recordTypes.CancelAnimationFrame]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Cancel Animation Frame"),categories["scripting"]);
-eventStyles[recordTypes.FireAnimationFrame]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Animation Frame Fired"),categories["scripting"]);
-eventStyles[recordTypes.RequestIdleCallback]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Request Idle Callback"),categories["scripting"]);
-eventStyles[recordTypes.CancelIdleCallback]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Cancel Idle Callback"),categories["scripting"]);
-eventStyles[recordTypes.FireIdleCallback]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Fire Idle Callback"),categories["scripting"]);
-eventStyles[recordTypes.WebSocketCreate]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Create WebSocket"),categories["scripting"]);
-eventStyles[recordTypes.WebSocketSendHandshakeRequest]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Send WebSocket Handshake"),categories["scripting"]);
-eventStyles[recordTypes.WebSocketReceiveHandshakeResponse]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Receive WebSocket Handshake"),categories["scripting"]);
-eventStyles[recordTypes.WebSocketDestroy]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Destroy WebSocket"),categories["scripting"]);
-eventStyles[recordTypes.EmbedderCallback]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Embedder Callback"),categories["scripting"]);
-eventStyles[recordTypes.DecodeImage]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Image Decode"),categories["painting"]);
-eventStyles[recordTypes.ResizeImage]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Image Resize"),categories["painting"]);
-eventStyles[recordTypes.GPUTask]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("GPU"),categories["gpu"]);
-eventStyles[recordTypes.LatencyInfo]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("Input Latency"),categories["scripting"]);
-
-eventStyles[recordTypes.GCIdleLazySweep]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("DOM GC"),categories["scripting"]);
-eventStyles[recordTypes.GCCompleteSweep]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("DOM GC"),categories["scripting"]);
-eventStyles[recordTypes.GCCollectGarbage]=new WebInspector.TimelineRecordStyle(WebInspector.UIString("DOM GC"),categories["scripting"]);
-
-WebInspector.TimelineUIUtils._eventStylesMap=eventStyles;
-return eventStyles;
-};
-
-
-
-
-
-WebInspector.TimelineUIUtils.inputEventDisplayName=function(inputEventType)
-{
-if(!WebInspector.TimelineUIUtils._inputEventToDisplayName){
-var inputEvent=WebInspector.TimelineIRModel.InputEvents;
-
-
-WebInspector.TimelineUIUtils._inputEventToDisplayName=new Map([
-[inputEvent.Char,WebInspector.UIString("Key Character")],
-[inputEvent.KeyDown,WebInspector.UIString("Key Down")],
-[inputEvent.KeyDownRaw,WebInspector.UIString("Key Down")],
-[inputEvent.KeyUp,WebInspector.UIString("Key Up")],
-[inputEvent.Click,WebInspector.UIString("Click")],
-[inputEvent.ContextMenu,WebInspector.UIString("Context Menu")],
-[inputEvent.MouseDown,WebInspector.UIString("Mouse Down")],
-[inputEvent.MouseMove,WebInspector.UIString("Mouse Move")],
-[inputEvent.MouseUp,WebInspector.UIString("Mouse Up")],
-[inputEvent.MouseWheel,WebInspector.UIString("Mouse Wheel")],
-[inputEvent.ScrollBegin,WebInspector.UIString("Scroll Begin")],
-[inputEvent.ScrollEnd,WebInspector.UIString("Scroll End")],
-[inputEvent.ScrollUpdate,WebInspector.UIString("Scroll Update")],
-[inputEvent.FlingStart,WebInspector.UIString("Fling Start")],
-[inputEvent.FlingCancel,WebInspector.UIString("Fling Halt")],
-[inputEvent.Tap,WebInspector.UIString("Tap")],
-[inputEvent.TapCancel,WebInspector.UIString("Tap Halt")],
-[inputEvent.ShowPress,WebInspector.UIString("Tap Begin")],
-[inputEvent.TapDown,WebInspector.UIString("Tap Down")],
-[inputEvent.TouchCancel,WebInspector.UIString("Touch Cancel")],
-[inputEvent.TouchEnd,WebInspector.UIString("Touch End")],
-[inputEvent.TouchMove,WebInspector.UIString("Touch Move")],
-[inputEvent.TouchStart,WebInspector.UIString("Touch Start")],
-[inputEvent.PinchBegin,WebInspector.UIString("Pinch Begin")],
-[inputEvent.PinchEnd,WebInspector.UIString("Pinch End")],
-[inputEvent.PinchUpdate,WebInspector.UIString("Pinch Update")]]);
-
-}
-return WebInspector.TimelineUIUtils._inputEventToDisplayName.get(inputEventType)||null;
-};
-
-
-
-
-
-
-WebInspector.TimelineUIUtils.testContentMatching=function(traceEvent,regExp)
-{
-var title=WebInspector.TimelineUIUtils.eventStyle(traceEvent).title;
-var tokens=[title];
-if(traceEvent.url)
-tokens.push(traceEvent.url);
-for(var argName in traceEvent.args){
-var argValue=traceEvent.args[argName];
-for(var key in argValue)
-tokens.push(argValue[key]);
-}
-return regExp.test(tokens.join("|"));
-};
-
-
-
-
-
-WebInspector.TimelineUIUtils.categoryForRecord=function(record)
-{
-return WebInspector.TimelineUIUtils.eventStyle(record.traceEvent()).category;
-};
-
-
-
-
-
-
-WebInspector.TimelineUIUtils.eventStyle=function(event)
-{
-var eventStyles=WebInspector.TimelineUIUtils._initEventStyles();
-if(event.hasCategory(WebInspector.TimelineModel.Category.Console)||event.hasCategory(WebInspector.TimelineModel.Category.UserTiming))
-return{title:event.name,category:WebInspector.TimelineUIUtils.categories()["scripting"]};
-
-if(event.hasCategory(WebInspector.TimelineModel.Category.LatencyInfo)){
-
-var prefix="InputLatency::";
-var inputEventType=event.name.startsWith(prefix)?event.name.substr(prefix.length):event.name;
-var displayName=WebInspector.TimelineUIUtils.inputEventDisplayName(inputEventType);
-return{title:displayName||inputEventType,category:WebInspector.TimelineUIUtils.categories()["scripting"]};
-}
-var result=eventStyles[event.name];
-if(!result){
-result=new WebInspector.TimelineRecordStyle(event.name,WebInspector.TimelineUIUtils.categories()["other"],true);
-eventStyles[event.name]=result;
-}
-return result;
-};
-
-
-
-
-
-WebInspector.TimelineUIUtils.eventColor=function(event)
-{
-if(event.name===WebInspector.TimelineModel.RecordType.JSFrame){
-var frame=event.args["data"];
-if(WebInspector.TimelineUIUtils.isUserFrame(frame))
-return WebInspector.TimelineUIUtils.colorForURL(frame.url);
-}
-return WebInspector.TimelineUIUtils.eventStyle(event).category.color;
-};
-
-
-
-
-
-WebInspector.TimelineUIUtils.eventTitle=function(event)
-{
-var title=WebInspector.TimelineUIUtils.eventStyle(event).title;
-if(event.hasCategory(WebInspector.TimelineModel.Category.Console))
-return title;
-if(event.name===WebInspector.TimelineModel.RecordType.TimeStamp)
-return WebInspector.UIString("%s: %s",title,event.args["data"]["message"]);
-if(event.name===WebInspector.TimelineModel.RecordType.Animation&&event.args["data"]&&event.args["data"]["name"])
-return WebInspector.UIString("%s: %s",title,event.args["data"]["name"]);
-return title;
-};
-
-
-
-
-
-WebInspector.TimelineUIUtils.eventURL=function(event)
-{
-if(event.url)
-return event.url;
-var data=event.args["data"]||event.args["beginData"];
-return data&&data.url||null;
-};
-
-
-
-
-WebInspector.TimelineUIUtils._interactionPhaseStyles=function()
-{
-var map=WebInspector.TimelineUIUtils._interactionPhaseStylesMap;
-if(!map){
-map=new Map([
-[WebInspector.TimelineIRModel.Phases.Idle,{color:"white",label:"Idle"}],
-[WebInspector.TimelineIRModel.Phases.Response,{color:"hsl(43, 83%, 64%)",label:WebInspector.UIString("Response")}],
-[WebInspector.TimelineIRModel.Phases.Scroll,{color:"hsl(256, 67%, 70%)",label:WebInspector.UIString("Scroll")}],
-[WebInspector.TimelineIRModel.Phases.Fling,{color:"hsl(256, 67%, 70%)",label:WebInspector.UIString("Fling")}],
-[WebInspector.TimelineIRModel.Phases.Drag,{color:"hsl(256, 67%, 70%)",label:WebInspector.UIString("Drag")}],
-[WebInspector.TimelineIRModel.Phases.Animation,{color:"hsl(256, 67%, 70%)",label:WebInspector.UIString("Animation")}],
-[WebInspector.TimelineIRModel.Phases.Uncategorized,{color:"hsl(0, 0%, 87%)",label:WebInspector.UIString("Uncategorized")}]]);
-
-WebInspector.TimelineUIUtils._interactionPhaseStylesMap=map;
-}
-return map;
-};
-
-
-
-
-
-WebInspector.TimelineUIUtils.interactionPhaseColor=function(phase)
-{
-return WebInspector.TimelineUIUtils._interactionPhaseStyles().get(phase).color;
-};
-
-
-
-
-
-WebInspector.TimelineUIUtils.interactionPhaseLabel=function(phase)
-{
-return WebInspector.TimelineUIUtils._interactionPhaseStyles().get(phase).label;
-};
-
-
-
-
-
-WebInspector.TimelineUIUtils.isUserFrame=function(frame)
-{
-return frame.scriptId!=="0"&&!(frame.url&&frame.url.startsWith("native "));
-};
-
-
-
-
-
-WebInspector.TimelineUIUtils.topStackFrame=function(event)
-{
-var stackTrace=event.stackTrace||event.initiator&&event.initiator.stackTrace;
-return stackTrace&&stackTrace.length?stackTrace[0]:null;
-};
-
-
-
-
-WebInspector.TimelineUIUtils.NetworkCategory={
-HTML:Symbol("HTML"),
-Script:Symbol("Script"),
-Style:Symbol("Style"),
-Media:Symbol("Media"),
-Other:Symbol("Other")};
-
-
-
-
-
-
-WebInspector.TimelineUIUtils.networkRequestCategory=function(request)
-{
-var categories=WebInspector.TimelineUIUtils.NetworkCategory;
-switch(request.mimeType){
-case"text/html":
-return categories.HTML;
-case"application/javascript":
-case"application/x-javascript":
-case"text/javascript":
-return categories.Script;
-case"text/css":
-return categories.Style;
-case"audio/ogg":
-case"image/gif":
-case"image/jpeg":
-case"image/png":
-case"image/svg+xml":
-case"image/webp":
-case"image/x-icon":
-case"font/opentype":
-case"font/woff2":
-case"application/font-woff":
-return categories.Media;
-default:
-return categories.Other;}
-
-};
-
-
-
-
-
-WebInspector.TimelineUIUtils.networkCategoryColor=function(category)
-{
-var categories=WebInspector.TimelineUIUtils.NetworkCategory;
-switch(category){
-case categories.HTML:return"hsl(214, 67%, 66%)";
-case categories.Script:return"hsl(43, 83%, 64%)";
-case categories.Style:return"hsl(256, 67%, 70%)";
-case categories.Media:return"hsl(109, 33%, 55%)";
-default:return"hsl(0, 0%, 70%)";}
-
-};
-
-
-
-
-
-
-WebInspector.TimelineUIUtils.buildDetailsTextForTraceEvent=function(event,target)
-{
-var recordType=WebInspector.TimelineModel.RecordType;
-var detailsText;
-var eventData=event.args["data"];
-switch(event.name){
-case recordType.GCEvent:
-case recordType.MajorGC:
-case recordType.MinorGC:
-var delta=event.args["usedHeapSizeBefore"]-event.args["usedHeapSizeAfter"];
-detailsText=WebInspector.UIString("%s collected",Number.bytesToString(delta));
-break;
-case recordType.FunctionCall:
-
-if(eventData)
-detailsText=linkifyLocationAsText(eventData["scriptId"],eventData["lineNumber"],0);
-break;
-case recordType.JSFrame:
-detailsText=WebInspector.beautifyFunctionName(eventData["functionName"]);
-break;
-case recordType.EventDispatch:
-detailsText=eventData?eventData["type"]:null;
-break;
-case recordType.Paint:
-var width=WebInspector.TimelineUIUtils.quadWidth(eventData.clip);
-var height=WebInspector.TimelineUIUtils.quadHeight(eventData.clip);
-if(width&&height)
-detailsText=WebInspector.UIString("%d\u2009\u00d7\u2009%d",width,height);
-break;
-case recordType.ParseHTML:
-var endLine=event.args["endData"]&&event.args["endData"]["endLine"];
-var url=WebInspector.displayNameForURL(event.args["beginData"]["url"]);
-detailsText=WebInspector.UIString("%s [%s\u2026%s]",url,event.args["beginData"]["startLine"]+1,endLine>=0?endLine+1:"");
-break;
-
-case recordType.CompileScript:
-case recordType.EvaluateScript:
-var url=eventData["url"];
-if(url)
-detailsText=WebInspector.displayNameForURL(url)+":"+(eventData["lineNumber"]+1);
-break;
-case recordType.ParseScriptOnBackground:
-case recordType.XHRReadyStateChange:
-case recordType.XHRLoad:
-var url=eventData["url"];
-if(url)
-detailsText=WebInspector.displayNameForURL(url);
-break;
-case recordType.TimeStamp:
-detailsText=eventData["message"];
-break;
-
-case recordType.WebSocketCreate:
-case recordType.WebSocketSendHandshakeRequest:
-case recordType.WebSocketReceiveHandshakeResponse:
-case recordType.WebSocketDestroy:
-case recordType.ResourceSendRequest:
-case recordType.ResourceReceivedData:
-case recordType.ResourceReceiveResponse:
-case recordType.ResourceFinish:
-case recordType.PaintImage:
-case recordType.DecodeImage:
-case recordType.ResizeImage:
-case recordType.DecodeLazyPixelRef:
-if(event.url)
-detailsText=WebInspector.displayNameForURL(event.url);
-break;
-
-case recordType.EmbedderCallback:
-detailsText=eventData["callbackName"];
-break;
-
-case recordType.Animation:
-detailsText=eventData&&eventData["name"];
-break;
-
-case recordType.GCIdleLazySweep:
-detailsText=WebInspector.UIString("idle sweep");
-break;
-
-case recordType.GCCompleteSweep:
-detailsText=WebInspector.UIString("complete sweep");
-break;
-
-case recordType.GCCollectGarbage:
-detailsText=WebInspector.UIString("collect");
-break;
-
-default:
-if(event.hasCategory(WebInspector.TimelineModel.Category.Console))
-detailsText=null;else
-
-detailsText=linkifyTopCallFrameAsText();
-break;}
-
-
-return detailsText;
-
-
-
-
-
-
-
-function linkifyLocationAsText(scriptId,lineNumber,columnNumber)
-{
-var debuggerModel=WebInspector.DebuggerModel.fromTarget(target);
-if(!target||target.isDetached()||!scriptId||!debuggerModel)
-return null;
-var rawLocation=debuggerModel.createRawLocationByScriptId(scriptId,lineNumber,columnNumber);
-if(!rawLocation)
-return null;
-var uiLocation=WebInspector.debuggerWorkspaceBinding.rawLocationToUILocation(rawLocation);
-return uiLocation.linkText();
-}
-
-
-
-
-function linkifyTopCallFrameAsText()
-{
-var frame=WebInspector.TimelineUIUtils.topStackFrame(event);
-if(!frame)
-return null;
-var text=linkifyLocationAsText(frame.scriptId,frame.lineNumber,frame.columnNumber);
-if(!text){
-text=frame.url;
-if(typeof frame.lineNumber==="number")
-text+=":"+(frame.lineNumber+1);
-}
-return text;
-}
-};
-
-
-
-
-
-
-
-WebInspector.TimelineUIUtils.buildDetailsNodeForTraceEvent=function(event,target,linkifier)
-{
-var recordType=WebInspector.TimelineModel.RecordType;
-var details=null;
-var detailsText;
-var eventData=event.args["data"];
-switch(event.name){
-case recordType.GCEvent:
-case recordType.MajorGC:
-case recordType.MinorGC:
-case recordType.EventDispatch:
-case recordType.Paint:
-case recordType.Animation:
-case recordType.EmbedderCallback:
-case recordType.ParseHTML:
-case recordType.WebSocketCreate:
-case recordType.WebSocketSendHandshakeRequest:
-case recordType.WebSocketReceiveHandshakeResponse:
-case recordType.WebSocketDestroy:
-case recordType.GCIdleLazySweep:
-case recordType.GCCompleteSweep:
-case recordType.GCCollectGarbage:
-detailsText=WebInspector.TimelineUIUtils.buildDetailsTextForTraceEvent(event,target);
-break;
-case recordType.PaintImage:
-case recordType.DecodeImage:
-case recordType.ResizeImage:
-case recordType.DecodeLazyPixelRef:
-case recordType.XHRReadyStateChange:
-case recordType.XHRLoad:
-case recordType.ResourceSendRequest:
-case recordType.ResourceReceivedData:
-case recordType.ResourceReceiveResponse:
-case recordType.ResourceFinish:
-if(event.url)
-details=WebInspector.linkifyResourceAsNode(event.url);
-break;
-case recordType.FunctionCall:
-case recordType.JSFrame:
-details=createElement("span");
-details.createTextChild(WebInspector.beautifyFunctionName(eventData["functionName"]));
-var location=linkifyLocation(eventData["scriptId"],eventData["url"],eventData["lineNumber"],eventData["columnNumber"]);
-if(location){
-details.createTextChild(" @ ");
-details.appendChild(location);
-}
-break;
-case recordType.CompileScript:
-case recordType.EvaluateScript:
-var url=eventData["url"];
-if(url)
-details=linkifyLocation("",url,eventData["lineNumber"],0);
-break;
-case recordType.ParseScriptOnBackground:
-var url=eventData["url"];
-if(url)
-details=linkifyLocation("",url,0,0);
-break;
-default:
-if(event.hasCategory(WebInspector.TimelineModel.Category.Console))
-detailsText=null;else
-
-details=linkifyTopCallFrame();
-break;}
-
-
-if(!details&&detailsText)
-details=createTextNode(detailsText);
-return details;
-
-
-
-
-
-
-
-
-function linkifyLocation(scriptId,url,lineNumber,columnNumber)
-{
-return linkifier.linkifyScriptLocation(target,scriptId,url,lineNumber,columnNumber,"timeline-details");
-}
-
-
-
-
-function linkifyTopCallFrame()
-{
-var frame=WebInspector.TimelineUIUtils.topStackFrame(event);
-return frame?linkifier.maybeLinkifyConsoleCallFrame(target,frame,"timeline-details"):null;
-}
-};
-
-
-
-
-
-
-
-
-WebInspector.TimelineUIUtils.buildTraceEventDetails=function(event,model,linkifier,detailed,callback)
-{
-var target=model.targetByEvent(event);
-if(!target){
-callbackWrapper();
-return;
-}
-var relatedNodes=null;
-var barrier=new CallbackBarrier();
-if(!event.previewElement){
-if(event.url)
-WebInspector.DOMPresentationUtils.buildImagePreviewContents(target,event.url,false,barrier.createCallback(saveImage));else
-if(event.picture)
-WebInspector.TimelineUIUtils.buildPicturePreviewContent(event,target,barrier.createCallback(saveImage));
-}
-var nodeIdsToResolve=new Set();
-if(event.backendNodeId)
-nodeIdsToResolve.add(event.backendNodeId);
-if(event.invalidationTrackingEvents)
-WebInspector.TimelineUIUtils._collectInvalidationNodeIds(nodeIdsToResolve,event.invalidationTrackingEvents);
-if(nodeIdsToResolve.size){
-var domModel=WebInspector.DOMModel.fromTarget(target);
-if(domModel)
-domModel.pushNodesByBackendIdsToFrontend(nodeIdsToResolve,barrier.createCallback(setRelatedNodeMap));
-}
-barrier.callWhenDone(callbackWrapper);
-
-
-
-
-function saveImage(element)
-{
-event.previewElement=element||null;
-}
-
-
-
-
-function setRelatedNodeMap(nodeMap)
-{
-relatedNodes=nodeMap;
-}
-
-function callbackWrapper()
-{
-callback(WebInspector.TimelineUIUtils._buildTraceEventDetailsSynchronously(event,model,linkifier,detailed,relatedNodes));
-}
-};
-
-
-
-
-
-
-
-
-
-WebInspector.TimelineUIUtils._buildTraceEventDetailsSynchronously=function(event,model,linkifier,detailed,relatedNodesMap)
-{
-var stats={};
-var recordTypes=WebInspector.TimelineModel.RecordType;
-
-
-var relatedNodeLabel;
-
-var contentHelper=new WebInspector.TimelineDetailsContentHelper(model.targetByEvent(event),linkifier);
-contentHelper.addSection(WebInspector.TimelineUIUtils.eventTitle(event),WebInspector.TimelineUIUtils.eventStyle(event).category);
-
-var eventData=event.args["data"];
-var initiator=event.initiator;
-
-if(event.warning)
-contentHelper.appendWarningRow(event);
-if(event.name===recordTypes.JSFrame&&eventData["deoptReason"])
-contentHelper.appendWarningRow(event,WebInspector.TimelineModel.WarningType.V8Deopt);
-
-if(detailed){
-contentHelper.appendTextRow(WebInspector.UIString("Self Time"),Number.millisToString(event.selfTime,true));
-contentHelper.appendTextRow(WebInspector.UIString("Total Time"),Number.millisToString(event.duration||0,true));
-}
-
-switch(event.name){
-case recordTypes.GCEvent:
-case recordTypes.MajorGC:
-case recordTypes.MinorGC:
-var delta=event.args["usedHeapSizeBefore"]-event.args["usedHeapSizeAfter"];
-contentHelper.appendTextRow(WebInspector.UIString("Collected"),Number.bytesToString(delta));
-break;
-case recordTypes.JSFrame:
-case recordTypes.FunctionCall:
-var detailsNode=WebInspector.TimelineUIUtils.buildDetailsNodeForTraceEvent(event,model.targetByEvent(event),linkifier);
-if(detailsNode)
-contentHelper.appendElementRow(WebInspector.UIString("Function"),detailsNode);
-break;
-case recordTypes.TimerFire:
-case recordTypes.TimerInstall:
-case recordTypes.TimerRemove:
-contentHelper.appendTextRow(WebInspector.UIString("Timer ID"),eventData["timerId"]);
-if(event.name===recordTypes.TimerInstall){
-contentHelper.appendTextRow(WebInspector.UIString("Timeout"),Number.millisToString(eventData["timeout"]));
-contentHelper.appendTextRow(WebInspector.UIString("Repeats"),!eventData["singleShot"]);
-}
-break;
-case recordTypes.FireAnimationFrame:
-contentHelper.appendTextRow(WebInspector.UIString("Callback ID"),eventData["id"]);
-break;
-case recordTypes.ResourceSendRequest:
-case recordTypes.ResourceReceiveResponse:
-case recordTypes.ResourceReceivedData:
-case recordTypes.ResourceFinish:
-var url=event.name===recordTypes.ResourceSendRequest?eventData["url"]:initiator&&initiator.args["data"]["url"];
-if(url)
-contentHelper.appendElementRow(WebInspector.UIString("Resource"),WebInspector.linkifyResourceAsNode(url));
-if(eventData["requestMethod"])
-contentHelper.appendTextRow(WebInspector.UIString("Request Method"),eventData["requestMethod"]);
-if(typeof eventData["statusCode"]==="number")
-contentHelper.appendTextRow(WebInspector.UIString("Status Code"),eventData["statusCode"]);
-if(eventData["mimeType"])
-contentHelper.appendTextRow(WebInspector.UIString("MIME Type"),eventData["mimeType"]);
-if("priority"in eventData){
-var priority=WebInspector.uiLabelForPriority(eventData["priority"]);
-contentHelper.appendTextRow(WebInspector.UIString("Priority"),priority);
-}
-if(eventData["encodedDataLength"])
-contentHelper.appendTextRow(WebInspector.UIString("Encoded Data Length"),WebInspector.UIString("%d Bytes",eventData["encodedDataLength"]));
-break;
-case recordTypes.CompileScript:
-case recordTypes.EvaluateScript:
-var url=eventData["url"];
-if(url)
-contentHelper.appendLocationRow(WebInspector.UIString("Script"),url,eventData["lineNumber"],eventData["columnNumber"]);
-break;
-case recordTypes.Paint:
-var clip=eventData["clip"];
-contentHelper.appendTextRow(WebInspector.UIString("Location"),WebInspector.UIString("(%d, %d)",clip[0],clip[1]));
-var clipWidth=WebInspector.TimelineUIUtils.quadWidth(clip);
-var clipHeight=WebInspector.TimelineUIUtils.quadHeight(clip);
-contentHelper.appendTextRow(WebInspector.UIString("Dimensions"),WebInspector.UIString("%d × %d",clipWidth,clipHeight));
-
-
-case recordTypes.PaintSetup:
-case recordTypes.Rasterize:
-case recordTypes.ScrollLayer:
-relatedNodeLabel=WebInspector.UIString("Layer Root");
-break;
-case recordTypes.PaintImage:
-case recordTypes.DecodeLazyPixelRef:
-case recordTypes.DecodeImage:
-case recordTypes.ResizeImage:
-case recordTypes.DrawLazyPixelRef:
-relatedNodeLabel=WebInspector.UIString("Owner Element");
-if(event.url)
-contentHelper.appendElementRow(WebInspector.UIString("Image URL"),WebInspector.linkifyResourceAsNode(event.url));
-break;
-case recordTypes.ParseAuthorStyleSheet:
-var url=eventData["styleSheetUrl"];
-if(url)
-contentHelper.appendElementRow(WebInspector.UIString("Stylesheet URL"),WebInspector.linkifyResourceAsNode(url));
-break;
-case recordTypes.UpdateLayoutTree:
-case recordTypes.RecalculateStyles:
-contentHelper.appendTextRow(WebInspector.UIString("Elements Affected"),event.args["elementCount"]);
-break;
-case recordTypes.Layout:
-var beginData=event.args["beginData"];
-contentHelper.appendTextRow(WebInspector.UIString("Nodes That Need Layout"),WebInspector.UIString("%s of %s",beginData["dirtyObjects"],beginData["totalObjects"]));
-relatedNodeLabel=WebInspector.UIString("Layout root");
-break;
-case recordTypes.ConsoleTime:
-contentHelper.appendTextRow(WebInspector.UIString("Message"),event.name);
-break;
-case recordTypes.WebSocketCreate:
-case recordTypes.WebSocketSendHandshakeRequest:
-case recordTypes.WebSocketReceiveHandshakeResponse:
-case recordTypes.WebSocketDestroy:
-var initiatorData=initiator?initiator.args["data"]:eventData;
-if(typeof initiatorData["webSocketURL"]!=="undefined")
-contentHelper.appendTextRow(WebInspector.UIString("URL"),initiatorData["webSocketURL"]);
-if(typeof initiatorData["webSocketProtocol"]!=="undefined")
-contentHelper.appendTextRow(WebInspector.UIString("WebSocket Protocol"),initiatorData["webSocketProtocol"]);
-if(typeof eventData["message"]!=="undefined")
-contentHelper.appendTextRow(WebInspector.UIString("Message"),eventData["message"]);
-break;
-case recordTypes.EmbedderCallback:
-contentHelper.appendTextRow(WebInspector.UIString("Callback Function"),eventData["callbackName"]);
-break;
-case recordTypes.Animation:
-if(event.phase===WebInspector.TracingModel.Phase.NestableAsyncInstant)
-contentHelper.appendTextRow(WebInspector.UIString("State"),eventData["state"]);
-break;
-case recordTypes.ParseHTML:
-var beginData=event.args["beginData"];
-var url=beginData["url"];
-var startLine=beginData["startLine"]-1;
-var endLine=event.args["endData"]?event.args["endData"]["endLine"]-1:undefined;
-if(url)
-contentHelper.appendLocationRange(WebInspector.UIString("Range"),url,startLine,endLine);
-break;
-
-case recordTypes.FireIdleCallback:
-contentHelper.appendTextRow(WebInspector.UIString("Allotted Time"),Number.millisToString(eventData["allottedMilliseconds"]));
-contentHelper.appendTextRow(WebInspector.UIString("Invoked by Timeout"),eventData["timedOut"]);
-
-
-case recordTypes.RequestIdleCallback:
-case recordTypes.CancelIdleCallback:
-contentHelper.appendTextRow(WebInspector.UIString("Callback ID"),eventData["id"]);
-break;
-case recordTypes.EventDispatch:
-contentHelper.appendTextRow(WebInspector.UIString("Type"),eventData["type"]);
-break;
-
-default:
-var detailsNode=WebInspector.TimelineUIUtils.buildDetailsNodeForTraceEvent(event,model.targetByEvent(event),linkifier);
-if(detailsNode)
-contentHelper.appendElementRow(WebInspector.UIString("Details"),detailsNode);
-break;}
-
-
-if(event.timeWaitingForMainThread)
-contentHelper.appendTextRow(WebInspector.UIString("Time Waiting for Main Thread"),Number.millisToString(event.timeWaitingForMainThread,true));
-
-var relatedNode=relatedNodesMap&&relatedNodesMap.get(event.backendNodeId);
-if(relatedNode)
-contentHelper.appendElementRow(relatedNodeLabel||WebInspector.UIString("Related Node"),WebInspector.DOMPresentationUtils.linkifyNodeReference(relatedNode));
-
-if(event.previewElement){
-contentHelper.addSection(WebInspector.UIString("Preview"));
-contentHelper.appendElementRow("",event.previewElement);
-}
-
-if(event.stackTrace||event.initiator&&event.initiator.stackTrace||event.invalidationTrackingEvents)
-WebInspector.TimelineUIUtils._generateCauses(event,model.targetByEvent(event),relatedNodesMap,contentHelper);
-
-var showPieChart=detailed&&WebInspector.TimelineUIUtils._aggregatedStatsForTraceEvent(stats,model,event);
-if(showPieChart){
-contentHelper.addSection(WebInspector.UIString("Aggregated Time"));
-var pieChart=WebInspector.TimelineUIUtils.generatePieChart(stats,WebInspector.TimelineUIUtils.eventStyle(event).category,event.selfTime);
-contentHelper.appendElementRow("",pieChart);
-}
-
-return contentHelper.fragment;
-};
-
-WebInspector.TimelineUIUtils._aggregatedStatsKey=Symbol("aggregatedStats");
-
-
-
-
-
-
-
-WebInspector.TimelineUIUtils.buildRangeStats=function(model,startTime,endTime)
-{
-var aggregatedStats={};
-
-
-
-
-
-
-function compareEndTime(value,task)
-{
-return value<task.endTime()?-1:1;
-}
-var mainThreadTasks=model.mainThreadTasks();
-var taskIndex=mainThreadTasks.lowerBound(startTime,compareEndTime);
-for(;taskIndex<mainThreadTasks.length;++taskIndex){
-var task=mainThreadTasks[taskIndex];
-if(task.startTime()>endTime)
-break;
-if(task.startTime()>startTime&&task.endTime()<endTime){
-
-var taskStats=task[WebInspector.TimelineUIUtils._aggregatedStatsKey];
-if(!taskStats){
-taskStats={};
-WebInspector.TimelineUIUtils._collectAggregatedStatsForRecord(task,startTime,endTime,taskStats);
-task[WebInspector.TimelineUIUtils._aggregatedStatsKey]=taskStats;
-}
-for(var key in taskStats)
-aggregatedStats[key]=(aggregatedStats[key]||0)+taskStats[key];
-continue;
-}
-WebInspector.TimelineUIUtils._collectAggregatedStatsForRecord(task,startTime,endTime,aggregatedStats);
-}
-
-var aggregatedTotal=0;
-for(var categoryName in aggregatedStats)
-aggregatedTotal+=aggregatedStats[categoryName];
-aggregatedStats["idle"]=Math.max(0,endTime-startTime-aggregatedTotal);
-
-var startOffset=startTime-model.minimumRecordTime();
-var endOffset=endTime-model.minimumRecordTime();
-
-var contentHelper=new WebInspector.TimelineDetailsContentHelper(null,null);
-contentHelper.addSection(WebInspector.UIString("Range: %s \u2013 %s",Number.millisToString(startOffset),Number.millisToString(endOffset)));
-var pieChart=WebInspector.TimelineUIUtils.generatePieChart(aggregatedStats);
-contentHelper.appendElementRow("",pieChart);
-return contentHelper.fragment;
-};
-
-
-
-
-
-
-
-WebInspector.TimelineUIUtils._collectAggregatedStatsForRecord=function(record,startTime,endTime,aggregatedStats)
-{
-var records=[];
-
-if(!record.endTime()||record.endTime()<startTime||record.startTime()>endTime)
-return;
-
-var childrenTime=0;
-var children=record.children()||[];
-for(var i=0;i<children.length;++i){
-var child=children[i];
-if(!child.endTime()||child.endTime()<startTime||child.startTime()>endTime)
-continue;
-childrenTime+=Math.min(endTime,child.endTime())-Math.max(startTime,child.startTime());
-WebInspector.TimelineUIUtils._collectAggregatedStatsForRecord(child,startTime,endTime,aggregatedStats);
-}
-var categoryName=WebInspector.TimelineUIUtils.categoryForRecord(record).name;
-var ownTime=Math.min(endTime,record.endTime())-Math.max(startTime,record.startTime())-childrenTime;
-aggregatedStats[categoryName]=(aggregatedStats[categoryName]||0)+ownTime;
-};
-
-
-
-
-
-
-
-WebInspector.TimelineUIUtils.buildNetworkRequestDetails=function(request,model,linkifier)
-{
-var target=model.targetByEvent(request.children[0]);
-var contentHelper=new WebInspector.TimelineDetailsContentHelper(target,linkifier);
-
-var duration=request.endTime-(request.startTime||-Infinity);
-var items=[];
-if(request.url)
-contentHelper.appendElementRow(WebInspector.UIString("URL"),WebInspector.linkifyURLAsNode(request.url));
-if(isFinite(duration))
-contentHelper.appendTextRow(WebInspector.UIString("Duration"),Number.millisToString(duration,true));
-if(request.requestMethod)
-contentHelper.appendTextRow(WebInspector.UIString("Request Method"),request.requestMethod);
-if(typeof request.priority==="string"){
-var priority=WebInspector.uiLabelForPriority(request.priority);
-contentHelper.appendTextRow(WebInspector.UIString("Priority"),priority);
-}
-if(request.mimeType)
-contentHelper.appendTextRow(WebInspector.UIString("Mime Type"),request.mimeType);
-
-var title=WebInspector.UIString("Initiator");
-var sendRequest=request.children[0];
-var topFrame=WebInspector.TimelineUIUtils.topStackFrame(sendRequest);
-if(topFrame){
-var link=linkifier.maybeLinkifyConsoleCallFrame(target,topFrame);
-if(link)
-contentHelper.appendElementRow(title,link);
-}else if(sendRequest.initiator){
-var initiatorURL=WebInspector.TimelineUIUtils.eventURL(sendRequest.initiator);
-if(initiatorURL){
-var link=linkifier.maybeLinkifyScriptLocation(target,null,initiatorURL,0);
-if(link)
-contentHelper.appendElementRow(title,link);
-}
-}
-
-
-
-
-function action(fulfill)
-{
-WebInspector.DOMPresentationUtils.buildImagePreviewContents(target,request.url,false,saveImage);
-
-
-
-function saveImage(element)
-{
-request.previewElement=element||null;
-fulfill(request.previewElement);
-}
-}
-var previewPromise;
-if(request.previewElement)
-previewPromise=Promise.resolve(request.previewElement);else
-
-previewPromise=request.url&&target?new Promise(action):Promise.resolve(null);
-
-
-
-
-function appendPreview(element)
-{
-if(element)
-contentHelper.appendElementRow(WebInspector.UIString("Preview"),request.previewElement);
-return contentHelper.fragment;
-}
-return previewPromise.then(appendPreview);
-};
-
-
-
-
-
-WebInspector.TimelineUIUtils._stackTraceFromCallFrames=function(callFrames)
-{
-return{callFrames:callFrames};
-};
-
-
-
-
-
-
-
-WebInspector.TimelineUIUtils._generateCauses=function(event,target,relatedNodesMap,contentHelper)
-{
-var recordTypes=WebInspector.TimelineModel.RecordType;
-
-var callSiteStackLabel;
-var stackLabel;
-var initiator=event.initiator;
-
-switch(event.name){
-case recordTypes.TimerFire:
-callSiteStackLabel=WebInspector.UIString("Timer Installed");
-break;
-case recordTypes.FireAnimationFrame:
-callSiteStackLabel=WebInspector.UIString("Animation Frame Requested");
-break;
-case recordTypes.FireIdleCallback:
-callSiteStackLabel=WebInspector.UIString("Idle Callback Requested");
-break;
-case recordTypes.UpdateLayoutTree:
-case recordTypes.RecalculateStyles:
-stackLabel=WebInspector.UIString("Recalculation Forced");
-break;
-case recordTypes.Layout:
-callSiteStackLabel=WebInspector.UIString("First Layout Invalidation");
-stackLabel=WebInspector.UIString("Layout Forced");
-break;}
-
-
-
-if(event.stackTrace&&event.stackTrace.length){
-contentHelper.addSection(WebInspector.UIString("Call Stacks"));
-contentHelper.appendStackTrace(stackLabel||WebInspector.UIString("Stack Trace"),WebInspector.TimelineUIUtils._stackTraceFromCallFrames(event.stackTrace));
-}
-
-
-if(event.invalidationTrackingEvents&&target){
-contentHelper.addSection(WebInspector.UIString("Invalidations"));
-WebInspector.TimelineUIUtils._generateInvalidations(event,target,relatedNodesMap,contentHelper);
-}else if(initiator&&initiator.stackTrace){
-contentHelper.appendStackTrace(callSiteStackLabel||WebInspector.UIString("First Invalidated"),WebInspector.TimelineUIUtils._stackTraceFromCallFrames(initiator.stackTrace));
-}
-};
-
-
-
-
-
-
-
-WebInspector.TimelineUIUtils._generateInvalidations=function(event,target,relatedNodesMap,contentHelper)
-{
-if(!event.invalidationTrackingEvents)
-return;
-
-var invalidations={};
-event.invalidationTrackingEvents.forEach(function(invalidation){
-if(!invalidations[invalidation.type])
-invalidations[invalidation.type]=[invalidation];else
-
-invalidations[invalidation.type].push(invalidation);
-});
-
-Object.keys(invalidations).forEach(function(type){
-WebInspector.TimelineUIUtils._generateInvalidationsForType(
-type,target,invalidations[type],relatedNodesMap,contentHelper);
-});
-};
-
-
-
-
-
-
-
-
-WebInspector.TimelineUIUtils._generateInvalidationsForType=function(type,target,invalidations,relatedNodesMap,contentHelper)
-{
-var title;
-switch(type){
-case WebInspector.TimelineModel.RecordType.StyleRecalcInvalidationTracking:
-title=WebInspector.UIString("Style Invalidations");
-break;
-case WebInspector.TimelineModel.RecordType.LayoutInvalidationTracking:
-title=WebInspector.UIString("Layout Invalidations");
-break;
-default:
-title=WebInspector.UIString("Other Invalidations");
-break;}
-
-
-var invalidationsTreeOutline=new TreeOutlineInShadow();
-invalidationsTreeOutline.registerRequiredCSS("timeline/invalidationsTree.css");
-invalidationsTreeOutline.element.classList.add("invalidations-tree");
-
-var invalidationGroups=groupInvalidationsByCause(invalidations);
-invalidationGroups.forEach(function(group){
-var groupElement=new WebInspector.TimelineUIUtils.InvalidationsGroupElement(target,relatedNodesMap,contentHelper,group);
-invalidationsTreeOutline.appendChild(groupElement);
-});
-contentHelper.appendElementRow(title,invalidationsTreeOutline.element,false,true);
-
-
-
-
-
-function groupInvalidationsByCause(invalidations)
-{
-
-var causeToInvalidationMap=new Map();
-for(var index=0;index<invalidations.length;index++){
-var invalidation=invalidations[index];
-var causeKey="";
-if(invalidation.cause.reason)
-causeKey+=invalidation.cause.reason+".";
-if(invalidation.cause.stackTrace){
-invalidation.cause.stackTrace.forEach(function(stackFrame){
-causeKey+=stackFrame["functionName"]+".";
-causeKey+=stackFrame["scriptId"]+".";
-causeKey+=stackFrame["url"]+".";
-causeKey+=stackFrame["lineNumber"]+".";
-causeKey+=stackFrame["columnNumber"]+".";
-});
-}
-
-if(causeToInvalidationMap.has(causeKey))
-causeToInvalidationMap.get(causeKey).push(invalidation);else
-
-causeToInvalidationMap.set(causeKey,[invalidation]);
-}
-return causeToInvalidationMap.valuesArray();
-}
-};
-
-
-
-
-
-WebInspector.TimelineUIUtils._collectInvalidationNodeIds=function(nodeIds,invalidations)
-{
-for(var i=0;i<invalidations.length;++i){
-if(invalidations[i].nodeId)
-nodeIds.add(invalidations[i].nodeId);
-}
-};
-
-
-
-
-
-
-
-
-
-WebInspector.TimelineUIUtils.InvalidationsGroupElement=function(target,relatedNodesMap,contentHelper,invalidations)
-{
-TreeElement.call(this,"",true);
-
-this.listItemElement.classList.add("header");
-this.selectable=false;
-this.toggleOnClick=true;
-
-this._relatedNodesMap=relatedNodesMap;
-this._contentHelper=contentHelper;
-this._invalidations=invalidations;
-this.title=this._createTitle(target);
-};
-
-WebInspector.TimelineUIUtils.InvalidationsGroupElement.prototype={
-
-
-
-
-
-_createTitle:function(target)
-{
-var first=this._invalidations[0];
-var reason=first.cause.reason;
-var topFrame=first.cause.stackTrace&&first.cause.stackTrace[0];
-
-var title=createElement("span");
-if(reason)
-title.createTextChild(WebInspector.UIString("%s for ",reason));else
-
-title.createTextChild(WebInspector.UIString("Unknown cause for "));
-
-this._appendTruncatedNodeList(title,this._invalidations);
-
-if(topFrame&&this._contentHelper.linkifier()){
-title.createTextChild(WebInspector.UIString(". "));
-var stack=title.createChild("span","monospace");
-stack.createChild("span").textContent=WebInspector.beautifyFunctionName(topFrame.functionName);
-var link=this._contentHelper.linkifier().maybeLinkifyConsoleCallFrame(target,topFrame);
-if(link){
-stack.createChild("span").textContent=" @ ";
-stack.createChild("span").appendChild(link);
-}
-}
-
-return title;
-},
-
-
-
-
-onpopulate:function()
-{
-var content=createElementWithClass("div","content");
-
-var first=this._invalidations[0];
-if(first.cause.stackTrace){
-var stack=content.createChild("div");
-stack.createTextChild(WebInspector.UIString("Stack trace:"));
-this._contentHelper.createChildStackTraceElement(stack,WebInspector.TimelineUIUtils._stackTraceFromCallFrames(first.cause.stackTrace));
-}
-
-content.createTextChild(this._invalidations.length>1?WebInspector.UIString("Nodes:"):WebInspector.UIString("Node:"));
-var nodeList=content.createChild("div","node-list");
-var firstNode=true;
-for(var i=0;i<this._invalidations.length;i++){
-var invalidation=this._invalidations[i];
-var invalidationNode=this._createInvalidationNode(invalidation,true);
-if(invalidationNode){
-if(!firstNode)
-nodeList.createTextChild(WebInspector.UIString(", "));
-firstNode=false;
-
-nodeList.appendChild(invalidationNode);
-
-var extraData=invalidation.extraData?", "+invalidation.extraData:"";
-if(invalidation.changedId)
-nodeList.createTextChild(WebInspector.UIString("(changed id to \"%s\"%s)",invalidation.changedId,extraData));else
-if(invalidation.changedClass)
-nodeList.createTextChild(WebInspector.UIString("(changed class to \"%s\"%s)",invalidation.changedClass,extraData));else
-if(invalidation.changedAttribute)
-nodeList.createTextChild(WebInspector.UIString("(changed attribute to \"%s\"%s)",invalidation.changedAttribute,extraData));else
-if(invalidation.changedPseudo)
-nodeList.createTextChild(WebInspector.UIString("(changed pesudo to \"%s\"%s)",invalidation.changedPseudo,extraData));else
-if(invalidation.selectorPart)
-nodeList.createTextChild(WebInspector.UIString("(changed \"%s\"%s)",invalidation.selectorPart,extraData));
-}
-}
-
-var contentTreeElement=new TreeElement(content,false);
-contentTreeElement.selectable=false;
-this.appendChild(contentTreeElement);
-},
-
-
-
-
-
-_appendTruncatedNodeList:function(parentElement,invalidations)
-{
-var invalidationNodes=[];
-var invalidationNodeIdMap={};
-for(var i=0;i<invalidations.length;i++){
-var invalidation=invalidations[i];
-var invalidationNode=this._createInvalidationNode(invalidation,false);
-invalidationNode.addEventListener("click",consumeEvent,false);
-if(invalidationNode&&!invalidationNodeIdMap[invalidation.nodeId]){
-invalidationNodes.push(invalidationNode);
-invalidationNodeIdMap[invalidation.nodeId]=true;
-}
-}
-
-if(invalidationNodes.length===1){
-parentElement.appendChild(invalidationNodes[0]);
-}else if(invalidationNodes.length===2){
-parentElement.appendChild(invalidationNodes[0]);
-parentElement.createTextChild(WebInspector.UIString(" and "));
-parentElement.appendChild(invalidationNodes[1]);
-}else if(invalidationNodes.length>=3){
-parentElement.appendChild(invalidationNodes[0]);
-parentElement.createTextChild(WebInspector.UIString(", "));
-parentElement.appendChild(invalidationNodes[1]);
-parentElement.createTextChild(WebInspector.UIString(", and %s others",invalidationNodes.length-2));
-}
-},
-
-
-
-
-
-_createInvalidationNode:function(invalidation,showUnknownNodes)
-{
-var node=invalidation.nodeId&&this._relatedNodesMap?this._relatedNodesMap.get(invalidation.nodeId):null;
-if(node)
-return WebInspector.DOMPresentationUtils.linkifyNodeReference(node);
-if(invalidation.nodeName){
-var nodeSpan=createElement("span");
-nodeSpan.textContent=WebInspector.UIString("[ %s ]",invalidation.nodeName);
-return nodeSpan;
-}
-if(showUnknownNodes){
-var nodeSpan=createElement("span");
-return nodeSpan.createTextChild(WebInspector.UIString("[ unknown node ]"));
-}
-},
-
-__proto__:TreeElement.prototype};
-
-
-
-
-
-
-
-
-WebInspector.TimelineUIUtils._aggregatedStatsForTraceEvent=function(total,model,event)
-{
-var events=model.inspectedTargetEvents();
-
-
-
-
-
-function eventComparator(startTime,e)
-{
-return startTime-e.startTime;
-}
-var index=events.binaryIndexOf(event.startTime,eventComparator);
-
-if(index<0)
-return false;
-var hasChildren=false;
-var endTime=event.endTime;
-if(endTime){
-for(var i=index;i<events.length;i++){
-var nextEvent=events[i];
-if(nextEvent.startTime>=endTime)
-break;
-if(!nextEvent.selfTime)
-continue;
-if(nextEvent.thread!==event.thread)
-continue;
-if(i>index)
-hasChildren=true;
-var categoryName=WebInspector.TimelineUIUtils.eventStyle(nextEvent).category.name;
-total[categoryName]=(total[categoryName]||0)+nextEvent.selfTime;
-}
-}
-if(WebInspector.TracingModel.isAsyncPhase(event.phase)){
-if(event.endTime){
-var aggregatedTotal=0;
-for(var categoryName in total)
-aggregatedTotal+=total[categoryName];
-total["idle"]=Math.max(0,event.endTime-event.startTime-aggregatedTotal);
-}
-return false;
-}
-return hasChildren;
-};
-
-
-
-
-
-
-WebInspector.TimelineUIUtils.buildPicturePreviewContent=function(event,target,callback)
-{
-new WebInspector.LayerPaintEvent(event,target).loadSnapshot(onSnapshotLoaded);
-
-
-
-
-function onSnapshotLoaded(rect,snapshot)
-{
-if(!snapshot){
-callback();
-return;
-}
-snapshot.requestImage(null,null,1,onGotImage);
-snapshot.dispose();
-}
-
-
-
-
-function onGotImage(imageURL)
-{
-if(!imageURL){
-callback();
-return;
-}
-var container=createElement("div");
-container.classList.add("image-preview-container","vbox","link");
-var img=container.createChild("img");
-img.src=imageURL;
-var paintProfilerButton=container.createChild("a");
-paintProfilerButton.textContent=WebInspector.UIString("Paint Profiler");
-container.addEventListener("click",showPaintProfiler,false);
-callback(container);
-}
-
-function showPaintProfiler()
-{
-WebInspector.TimelinePanel.instance().select(WebInspector.TimelineSelection.fromTraceEvent(event),WebInspector.TimelinePanel.DetailsTab.PaintProfiler);
-}
-};
-
-
-
-
-
-
-
-WebInspector.TimelineUIUtils.createEventDivider=function(recordType,title,position)
-{
-var eventDivider=createElement("div");
-eventDivider.className="resources-event-divider";
-var recordTypes=WebInspector.TimelineModel.RecordType;
-
-if(recordType===recordTypes.MarkDOMContent)
-eventDivider.className+=" resources-blue-divider";else
-if(recordType===recordTypes.MarkLoad)
-eventDivider.className+=" resources-red-divider";else
-if(recordType===recordTypes.MarkFirstPaint)
-eventDivider.className+=" resources-green-divider";else
-if(recordType===recordTypes.TimeStamp||recordType===recordTypes.ConsoleTime||recordType===recordTypes.UserTiming)
-eventDivider.className+=" resources-orange-divider";else
-if(recordType===recordTypes.BeginFrame)
-eventDivider.className+=" timeline-frame-divider";
-
-if(title)
-eventDivider.title=title;
-eventDivider.style.left=position+"px";
-return eventDivider;
-};
-
-
-
-
-
-
-
-WebInspector.TimelineUIUtils.createDividerForRecord=function(record,zeroTime,position)
-{
-var startTime=Number.millisToString(record.startTime()-zeroTime);
-var title=WebInspector.UIString("%s at %s",WebInspector.TimelineUIUtils.eventTitle(record.traceEvent()),startTime);
-return WebInspector.TimelineUIUtils.createEventDivider(record.type(),title,position);
-};
-
-
-
-
-WebInspector.TimelineUIUtils._visibleTypes=function()
-{
-var eventStyles=WebInspector.TimelineUIUtils._initEventStyles();
-var result=[];
-for(var name in eventStyles){
-if(!eventStyles[name].hidden)
-result.push(name);
-}
-return result;
-};
-
-
-
-
-WebInspector.TimelineUIUtils.visibleEventsFilter=function()
-{
-return new WebInspector.TimelineVisibleEventsFilter(WebInspector.TimelineUIUtils._visibleTypes());
-};
-
-
-
-
-WebInspector.TimelineUIUtils.categories=function()
-{
-if(WebInspector.TimelineUIUtils._categories)
-return WebInspector.TimelineUIUtils._categories;
-WebInspector.TimelineUIUtils._categories={
-loading:new WebInspector.TimelineCategory("loading",WebInspector.UIString("Loading"),true,"hsl(214, 67%, 74%)","hsl(214, 67%, 66%)"),
-scripting:new WebInspector.TimelineCategory("scripting",WebInspector.UIString("Scripting"),true,"hsl(43, 83%, 72%)","hsl(43, 83%, 64%) "),
-rendering:new WebInspector.TimelineCategory("rendering",WebInspector.UIString("Rendering"),true,"hsl(256, 67%, 76%)","hsl(256, 67%, 70%)"),
-painting:new WebInspector.TimelineCategory("painting",WebInspector.UIString("Painting"),true,"hsl(109, 33%, 64%)","hsl(109, 33%, 55%)"),
-gpu:new WebInspector.TimelineCategory("gpu",WebInspector.UIString("GPU"),false,"hsl(109, 33%, 64%)","hsl(109, 33%, 55%)"),
-other:new WebInspector.TimelineCategory("other",WebInspector.UIString("Other"),false,"hsl(0, 0%, 87%)","hsl(0, 0%, 79%)"),
-idle:new WebInspector.TimelineCategory("idle",WebInspector.UIString("Idle"),false,"hsl(0, 100%, 100%)","hsl(0, 100%, 100%)")};
-
-return WebInspector.TimelineUIUtils._categories;
-};
-
-
-
-
-
-WebInspector.TimelineUIUtils.titleForAsyncEventGroup=function(group)
-{
-if(!WebInspector.TimelineUIUtils._titleForAsyncEventGroupMap){
-var groups=WebInspector.TimelineModel.AsyncEventGroup;
-WebInspector.TimelineUIUtils._titleForAsyncEventGroupMap=new Map([
-[groups.animation,WebInspector.UIString("Animation")],
-[groups.console,WebInspector.UIString("Console")],
-[groups.userTiming,WebInspector.UIString("User Timing")],
-[groups.input,WebInspector.UIString("Input")]]);
-
-}
-return WebInspector.TimelineUIUtils._titleForAsyncEventGroupMap.get(group)||"";
-};
-
-
-
-
-
-
-
-WebInspector.TimelineUIUtils.generatePieChart=function(aggregatedStats,selfCategory,selfTime)
-{
-var total=0;
-for(var categoryName in aggregatedStats)
-total+=aggregatedStats[categoryName];
-
-var element=createElementWithClass("div","timeline-details-view-pie-chart-wrapper hbox");
-var pieChart=new WebInspector.PieChart(100);
-pieChart.element.classList.add("timeline-details-view-pie-chart");
-pieChart.setTotal(total);
-var pieChartContainer=element.createChild("div","vbox");
-pieChartContainer.appendChild(pieChart.element);
-pieChartContainer.createChild("div","timeline-details-view-pie-chart-total").textContent=WebInspector.UIString("Total: %s",Number.millisToString(total,true));
-var footerElement=element.createChild("div","timeline-aggregated-info-legend");
-
-
-
-
-
-
-
-function appendLegendRow(name,title,value,color)
-{
-if(!value)
-return;
-pieChart.addSlice(value,color);
-var rowElement=footerElement.createChild("div");
-rowElement.createChild("span","timeline-aggregated-legend-value").textContent=Number.preciseMillisToString(value,1);
-rowElement.createChild("span","timeline-aggregated-legend-swatch").style.backgroundColor=color;
-rowElement.createChild("span","timeline-aggregated-legend-title").textContent=title;
-}
-
-
-if(selfCategory){
-if(selfTime)
-appendLegendRow(selfCategory.name,WebInspector.UIString("%s (self)",selfCategory.title),selfTime,selfCategory.color);
-
-var categoryTime=aggregatedStats[selfCategory.name];
-var value=categoryTime-selfTime;
-if(value>0)
-appendLegendRow(selfCategory.name,WebInspector.UIString("%s (children)",selfCategory.title),value,selfCategory.childColor);
-}
-
-
-for(var categoryName in WebInspector.TimelineUIUtils.categories()){
-var category=WebInspector.TimelineUIUtils.categories()[categoryName];
-if(category===selfCategory)
-continue;
-appendLegendRow(category.name,category.title,aggregatedStats[category.name],category.childColor);
-}
-return element;
-};
-
-
-
-
-
-
-
-WebInspector.TimelineUIUtils.generateDetailsContentForFrame=function(frameModel,frame,filmStripFrame)
-{
-var pieChart=WebInspector.TimelineUIUtils.generatePieChart(frame.timeByCategory);
-var contentHelper=new WebInspector.TimelineDetailsContentHelper(null,null);
-contentHelper.addSection(WebInspector.UIString("Frame"));
-
-var duration=WebInspector.TimelineUIUtils.frameDuration(frame);
-contentHelper.appendElementRow(WebInspector.UIString("Duration"),duration,frame.hasWarnings());
-if(filmStripFrame){
-var filmStripPreview=createElementWithClass("img","timeline-filmstrip-preview");
-filmStripFrame.imageDataPromise().then(onGotImageData.bind(null,filmStripPreview));
-contentHelper.appendElementRow("",filmStripPreview);
-filmStripPreview.addEventListener("click",frameClicked.bind(null,filmStripFrame),false);
-}
-var durationInMillis=frame.endTime-frame.startTime;
-contentHelper.appendTextRow(WebInspector.UIString("FPS"),Math.floor(1000/durationInMillis));
-contentHelper.appendTextRow(WebInspector.UIString("CPU time"),Number.millisToString(frame.cpuTime,true));
-
-if(Runtime.experiments.isEnabled("layersPanel")&&frame.layerTree){
-contentHelper.appendElementRow(WebInspector.UIString("Layer tree"),
-WebInspector.Linkifier.linkifyUsingRevealer(frame.layerTree,WebInspector.UIString("show")));
-}
-
-
-
-
-
-function onGotImageData(image,data)
-{
-if(data)
-image.src="data:image/jpg;base64,"+data;
-}
-
-
-
-
-function frameClicked(filmStripFrame)
-{
-new WebInspector.FilmStripView.Dialog(filmStripFrame,0);
-}
-
-return contentHelper.fragment;
-};
-
-
-
-
-
-WebInspector.TimelineUIUtils.frameDuration=function(frame)
-{
-var durationText=WebInspector.UIString("%s (at %s)",Number.millisToString(frame.endTime-frame.startTime,true),
-Number.millisToString(frame.startTimeOffset,true));
-var element=createElement("span");
-element.createTextChild(durationText);
-if(!frame.hasWarnings())
-return element;
-element.createTextChild(WebInspector.UIString(". Long frame times are an indication of "));
-element.appendChild(WebInspector.linkifyURLAsNode("https://developers.google.com/web/fundamentals/performance/rendering/",
-WebInspector.UIString("jank"),undefined,true));
-element.createTextChild(".");
-return element;
-};
-
-
-
-
-
-
-
-
-
-
-WebInspector.TimelineUIUtils.createFillStyle=function(context,width,height,color0,color1,color2)
-{
-var gradient=context.createLinearGradient(0,0,width,height);
-gradient.addColorStop(0,color0);
-gradient.addColorStop(0.25,color1);
-gradient.addColorStop(0.75,color1);
-gradient.addColorStop(1,color2);
-return gradient;
-};
-
-
-
-
-
-WebInspector.TimelineUIUtils.quadWidth=function(quad)
-{
-return Math.round(Math.sqrt(Math.pow(quad[0]-quad[2],2)+Math.pow(quad[1]-quad[3],2)));
-};
-
-
-
-
-
-WebInspector.TimelineUIUtils.quadHeight=function(quad)
-{
-return Math.round(Math.sqrt(Math.pow(quad[0]-quad[6],2)+Math.pow(quad[1]-quad[7],2)));
-};
-
-
-
-
-
-
-
-WebInspector.TimelineUIUtils.EventDispatchTypeDescriptor=function(priority,color,eventTypes)
-{
-this.priority=priority;
-this.color=color;
-this.eventTypes=eventTypes;
-};
-
-
-
-
-WebInspector.TimelineUIUtils.eventDispatchDesciptors=function()
-{
-if(WebInspector.TimelineUIUtils._eventDispatchDesciptors)
-return WebInspector.TimelineUIUtils._eventDispatchDesciptors;
-var lightOrange="hsl(40,100%,80%)";
-var orange="hsl(40,100%,50%)";
-var green="hsl(90,100%,40%)";
-var purple="hsl(256,100%,75%)";
-WebInspector.TimelineUIUtils._eventDispatchDesciptors=[
-new WebInspector.TimelineUIUtils.EventDispatchTypeDescriptor(1,lightOrange,["mousemove","mouseenter","mouseleave","mouseout","mouseover"]),
-new WebInspector.TimelineUIUtils.EventDispatchTypeDescriptor(1,lightOrange,["pointerover","pointerout","pointerenter","pointerleave","pointermove"]),
-new WebInspector.TimelineUIUtils.EventDispatchTypeDescriptor(2,green,["wheel"]),
-new WebInspector.TimelineUIUtils.EventDispatchTypeDescriptor(3,orange,["click","mousedown","mouseup"]),
-new WebInspector.TimelineUIUtils.EventDispatchTypeDescriptor(3,orange,["touchstart","touchend","touchmove","touchcancel"]),
-new WebInspector.TimelineUIUtils.EventDispatchTypeDescriptor(3,orange,["pointerdown","pointerup","pointercancel","gotpointercapture","lostpointercapture"]),
-new WebInspector.TimelineUIUtils.EventDispatchTypeDescriptor(3,purple,["keydown","keyup","keypress"])];
-
-return WebInspector.TimelineUIUtils._eventDispatchDesciptors;
-};
-
-
-
-
-
-
-
-
-
-
-WebInspector.TimelineCategory=function(name,title,visible,childColor,color)
-{
-this.name=name;
-this.title=title;
-this.visible=visible;
-this.childColor=childColor;
-this.color=color;
-this.hidden=false;
-};
-
-
-WebInspector.TimelineCategory.Events={
-VisibilityChanged:Symbol("VisibilityChanged")};
-
-
-WebInspector.TimelineCategory.prototype={
-
-
-
-get hidden()
-{
-return this._hidden;
-},
-
-set hidden(hidden)
-{
-this._hidden=hidden;
-this.dispatchEventToListeners(WebInspector.TimelineCategory.Events.VisibilityChanged,this);
-},
-
-__proto__:WebInspector.Object.prototype};
-
-
-
-
-
-
-
-
-
-
-
-
-WebInspector.TimelineMarkerStyle;
-
-
-
-
-
-WebInspector.TimelineUIUtils.markerStyleForEvent=function(event)
-{
-var red="rgb(255, 0, 0)";
-var blue="rgb(0, 0, 255)";
-var orange="rgb(255, 178, 23)";
-var green="rgb(0, 130, 0)";
-var tallMarkerDashStyle=[10,5];
-
-var title=WebInspector.TimelineUIUtils.eventTitle(event);
-
-if(event.hasCategory(WebInspector.TimelineModel.Category.Console)||event.hasCategory(WebInspector.TimelineModel.Category.UserTiming)){
-return{
-title:title,
-dashStyle:tallMarkerDashStyle,
-lineWidth:0.5,
-color:orange,
-tall:false,
-lowPriority:false};
-
-}
-var recordTypes=WebInspector.TimelineModel.RecordType;
-var tall=false;
-var color=green;
-switch(event.name){
-case recordTypes.MarkDOMContent:
-color=blue;
-tall=true;
-break;
-case recordTypes.MarkLoad:
-color=red;
-tall=true;
-break;
-case recordTypes.MarkFirstPaint:
-color=green;
-tall=true;
-break;
-case recordTypes.TimeStamp:
-color=orange;
-break;}
-
-return{
-title:title,
-dashStyle:tallMarkerDashStyle,
-lineWidth:0.5,
-color:color,
-tall:tall,
-lowPriority:false};
-
-};
-
-
-
-
-WebInspector.TimelineUIUtils.markerStyleForFrame=function()
-{
-return{
-title:WebInspector.UIString("Frame"),
-color:"rgba(100, 100, 100, 0.4)",
-lineWidth:3,
-dashStyle:[3],
-tall:true,
-lowPriority:true};
-
-};
-
-
-
-
-
-WebInspector.TimelineUIUtils.colorForURL=function(url)
-{
-if(!WebInspector.TimelineUIUtils.colorForURL._colorGenerator){
-WebInspector.TimelineUIUtils.colorForURL._colorGenerator=new WebInspector.FlameChart.ColorGenerator(
-{min:30,max:330},
-{min:50,max:80,count:3},
-85);
-}
-return WebInspector.TimelineUIUtils.colorForURL._colorGenerator.colorForID(url);
-};
-
-
-
-
-
-WebInspector.TimelinePopupContentHelper=function(title)
-{
-this._contentTable=createElement("table");
-var titleCell=this._createCell(WebInspector.UIString("%s - Details",title),"timeline-details-title");
-titleCell.colSpan=2;
-var titleRow=createElement("tr");
-titleRow.appendChild(titleCell);
-this._contentTable.appendChild(titleRow);
-};
-
-WebInspector.TimelinePopupContentHelper.prototype={
-
-
-
-contentTable:function()
-{
-return this._contentTable;
-},
-
-
-
-
-
-_createCell:function(content,styleName)
-{
-var text=createElement("label");
-text.createTextChild(String(content));
-var cell=createElement("td");
-cell.className="timeline-details";
-if(styleName)
-cell.className+=" "+styleName;
-cell.textContent=content;
-return cell;
-},
-
-
-
-
-
-appendTextRow:function(title,content)
-{
-var row=createElement("tr");
-row.appendChild(this._createCell(title,"timeline-details-row-title"));
-row.appendChild(this._createCell(content,"timeline-details-row-data"));
-this._contentTable.appendChild(row);
-},
-
-
-
-
-
-appendElementRow:function(title,content)
-{
-var row=createElement("tr");
-var titleCell=this._createCell(title,"timeline-details-row-title");
-row.appendChild(titleCell);
-var cell=createElement("td");
-cell.className="details";
-if(content instanceof Node)
-cell.appendChild(content);else
-
-cell.createTextChild(content||"");
-row.appendChild(cell);
-this._contentTable.appendChild(row);
-}};
-
-
-
-
-
-
-
-WebInspector.TimelineDetailsContentHelper=function(target,linkifier)
-{
-this.fragment=createDocumentFragment();
-
-this._linkifier=linkifier;
-this._target=target;
-
-this.element=createElementWithClass("div","timeline-details-view-block");
-this._tableElement=this.element.createChild("div","vbox timeline-details-chip-body");
-this.fragment.appendChild(this.element);
-};
-
-WebInspector.TimelineDetailsContentHelper.prototype={
-
-
-
-
-addSection:function(title,category)
-{
-if(!this._tableElement.hasChildNodes()){
-this.element.removeChildren();
-}else{
-this.element=createElementWithClass("div","timeline-details-view-block");
-this.fragment.appendChild(this.element);
-}
-
-if(title){
-var titleElement=this.element.createChild("div","timeline-details-chip-title");
-if(category)
-titleElement.createChild("div").style.backgroundColor=category.color;
-titleElement.createTextChild(title);
-}
-
-this._tableElement=this.element.createChild("div","vbox timeline-details-chip-body");
-this.fragment.appendChild(this.element);
-},
-
-
-
-
-linkifier:function()
-{
-return this._linkifier;
-},
-
-
-
-
-
-appendTextRow:function(title,value)
-{
-var rowElement=this._tableElement.createChild("div","timeline-details-view-row");
-rowElement.createChild("div","timeline-details-view-row-title").textContent=title;
-rowElement.createChild("div","timeline-details-view-row-value").textContent=value;
-},
-
-
-
-
-
-
-
-appendElementRow:function(title,content,isWarning,isStacked)
-{
-var rowElement=this._tableElement.createChild("div","timeline-details-view-row");
-if(isWarning)
-rowElement.classList.add("timeline-details-warning");
-if(isStacked)
-rowElement.classList.add("timeline-details-stack-values");
-var titleElement=rowElement.createChild("div","timeline-details-view-row-title");
-titleElement.textContent=title;
-var valueElement=rowElement.createChild("div","timeline-details-view-row-value");
-if(content instanceof Node)
-valueElement.appendChild(content);else
-
-valueElement.createTextChild(content||"");
-},
-
-
-
-
-
-
-
-appendLocationRow:function(title,url,startLine,startColumn)
-{
-if(!this._linkifier||!this._target)
-return;
-var link=this._linkifier.maybeLinkifyScriptLocation(this._target,null,url,startLine,startColumn);
-if(!link)
-return;
-this.appendElementRow(title,link);
-},
-
-
-
-
-
-
-
-appendLocationRange:function(title,url,startLine,endLine)
-{
-if(!this._linkifier||!this._target)
-return;
-var locationContent=createElement("span");
-var link=this._linkifier.maybeLinkifyScriptLocation(this._target,null,url,startLine);
-if(!link)
-return;
-locationContent.appendChild(link);
-locationContent.createTextChild(String.sprintf(" [%s\u2026%s]",startLine+1,endLine+1||""));
-this.appendElementRow(title,locationContent);
-},
-
-
-
-
-
-appendStackTrace:function(title,stackTrace)
-{
-if(!this._linkifier||!this._target)
-return;
-
-var rowElement=this._tableElement.createChild("div","timeline-details-view-row");
-rowElement.createChild("div","timeline-details-view-row-title").textContent=title;
-this.createChildStackTraceElement(rowElement,stackTrace);
-},
-
-
-
-
-
-createChildStackTraceElement:function(parentElement,stackTrace)
-{
-if(!this._linkifier||!this._target)
-return;
-parentElement.classList.add("timeline-details-stack-values");
-var stackTraceElement=parentElement.createChild("div","timeline-details-view-row-value timeline-details-view-row-stack-trace");
-var callFrameElem=WebInspector.DOMPresentationUtils.buildStackTracePreviewContents(this._target,this._linkifier,stackTrace);
-stackTraceElement.appendChild(callFrameElem);
-},
-
-
-
-
-
-appendWarningRow:function(event,warningType)
-{
-var warning=WebInspector.TimelineUIUtils.eventWarning(event,warningType);
-if(warning)
-this.appendElementRow(WebInspector.UIString("Warning"),warning,true);
-}};
-
-
-
-
-
-
-
-WebInspector.TimelineUIUtils.eventWarning=function(event,warningType)
-{
-var warning=warningType||event.warning;
-if(!warning)
-return null;
-var warnings=WebInspector.TimelineModel.WarningType;
-var span=createElement("span");
-var eventData=event.args["data"];
-
-switch(warning){
-case warnings.ForcedStyle:
-case warnings.ForcedLayout:
-span.appendChild(WebInspector.linkifyDocumentationURLAsNode("../../fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing#avoid-forced-synchronous-layouts",
-WebInspector.UIString("Forced reflow")));
-span.createTextChild(WebInspector.UIString(" is a likely performance bottleneck."));
-break;
-case warnings.IdleDeadlineExceeded:
-span.textContent=WebInspector.UIString("Idle callback execution extended beyond deadline by "+
-Number.millisToString(event.duration-eventData["allottedMilliseconds"],true));
-break;
-case warnings.V8Deopt:
-span.appendChild(WebInspector.linkifyURLAsNode("https://github.com/GoogleChrome/devtools-docs/issues/53",
-WebInspector.UIString("Not optimized"),undefined,true));
-span.createTextChild(WebInspector.UIString(": %s",eventData["deoptReason"]));
-break;
-default:
-console.assert(false,"Unhandled TimelineModel.WarningType");}
-
-return span;
-};
-
-},{}],126:[function(require,module,exports){
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-WebInspector.TracingLayerPayload;
-
-
-
-
-
-
-
-
-WebInspector.TracingLayerTile;
-
-
-
-
-
-WebInspector.LayerTreeModel=function(target)
-{
-WebInspector.SDKModel.call(this,WebInspector.LayerTreeModel,target);
-target.registerLayerTreeDispatcher(new WebInspector.LayerTreeDispatcher(this));
-WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Events.MainFrameNavigated,this._onMainFrameNavigated,this);
-
-this._layerTree=null;
-};
-
-
-WebInspector.LayerTreeModel.Events={
-LayerTreeChanged:Symbol("LayerTreeChanged"),
-LayerPainted:Symbol("LayerPainted")};
-
-
-WebInspector.LayerTreeModel.ScrollRectType={
-NonFastScrollable:{name:"NonFastScrollable",description:"Non fast scrollable"},
-TouchEventHandler:{name:"TouchEventHandler",description:"Touch event handler"},
-WheelEventHandler:{name:"WheelEventHandler",description:"Wheel event handler"},
-RepaintsOnScroll:{name:"RepaintsOnScroll",description:"Repaints on scroll"}};
-
-
-WebInspector.LayerTreeModel.prototype={
-disable:function()
-{
-if(!this._enabled)
-return;
-this._enabled=false;
-this._layerTree=null;
-this.target().layerTreeAgent().disable();
-},
-
-enable:function()
-{
-if(this._enabled)
-return;
-this._enabled=true;
-this._forceEnable();
-},
-
-_forceEnable:function()
-{
-this._layerTree=new WebInspector.AgentLayerTree(this.target());
-this._lastPaintRectByLayerId={};
-this.target().layerTreeAgent().enable();
-},
-
-
-
-
-setLayerTree:function(layerTree)
-{
-this.disable();
-this._layerTree=layerTree;
-this.dispatchEventToListeners(WebInspector.LayerTreeModel.Events.LayerTreeChanged);
-},
-
-
-
-
-layerTree:function()
-{
-return this._layerTree;
-},
-
-
-
-
-_layerTreeChanged:function(layers)
-{
-if(!this._enabled)
-return;
-var layerTree=this._layerTree;
-layerTree.setLayers(layers,onLayersSet.bind(this));
-
-
-
-
-function onLayersSet()
-{
-for(var layerId in this._lastPaintRectByLayerId){
-var lastPaintRect=this._lastPaintRectByLayerId[layerId];
-var layer=layerTree.layerById(layerId);
-if(layer)
-layer._lastPaintRect=lastPaintRect;
-}
-this._lastPaintRectByLayerId={};
-
-this.dispatchEventToListeners(WebInspector.LayerTreeModel.Events.LayerTreeChanged);
-}
-},
-
-
-
-
-
-_layerPainted:function(layerId,clipRect)
-{
-if(!this._enabled)
-return;
-var layerTree=this._layerTree;
-var layer=layerTree.layerById(layerId);
-if(!layer){
-this._lastPaintRectByLayerId[layerId]=clipRect;
-return;
-}
-layer._didPaint(clipRect);
-this.dispatchEventToListeners(WebInspector.LayerTreeModel.Events.LayerPainted,layer);
-},
-
-_onMainFrameNavigated:function()
-{
-if(this._enabled)
-this._forceEnable();
-},
-
-__proto__:WebInspector.SDKModel.prototype};
-
-
-
-
-
-
-WebInspector.LayerTreeBase=function(target)
-{
-this._target=target;
-this._domModel=target?WebInspector.DOMModel.fromTarget(target):null;
-this._layersById={};
-
-this._backendNodeIdToNode=new Map();
-this._reset();
-};
-
-WebInspector.LayerTreeBase.prototype={
-_reset:function()
-{
-this._root=null;
-this._contentRoot=null;
-this._layers=null;
-},
-
-
-
-
-target:function()
-{
-return this._target;
-},
-
-
-
-
-root:function()
-{
-return this._root;
-},
-
-
-
-
-contentRoot:function()
-{
-return this._contentRoot;
-},
-
-
-
-
-layers:function()
-{
-return this._layers;
-},
-
-
-
-
-
-
-forEachLayer:function(callback,root)
-{
-if(!root){
-root=this.root();
-if(!root)
-return false;
-}
-return callback(root)||root.children().some(this.forEachLayer.bind(this,callback));
-},
-
-
-
-
-
-layerById:function(id)
-{
-return this._layersById[id]||null;
-},
-
-
-
-
-
-_resolveBackendNodeIds:function(requestedNodeIds,callback)
-{
-if(!requestedNodeIds.size||!this._domModel){
-callback();
-return;
-}
-if(this._domModel)
-this._domModel.pushNodesByBackendIdsToFrontend(requestedNodeIds,populateBackendNodeMap.bind(this));
-
-
-
-
-
-function populateBackendNodeMap(nodesMap)
-{
-if(nodesMap){
-for(var nodeId of nodesMap.keysArray())
-this._backendNodeIdToNode.set(nodeId,nodesMap.get(nodeId)||null);
-}
-callback();
-}
-},
-
-
-
-
-setViewportSize:function(viewportSize)
-{
-this._viewportSize=viewportSize;
-},
-
-
-
-
-viewportSize:function()
-{
-return this._viewportSize;
-},
-
-
-
-
-
-_nodeForId:function(id)
-{
-return this._domModel?this._domModel.nodeForId(id):null;
-}};
-
-
-
-
-
-
-
-WebInspector.TracingLayerTree=function(target)
-{
-WebInspector.LayerTreeBase.call(this,target);
-
-this._tileById=new Map();
-};
-
-WebInspector.TracingLayerTree.prototype={
-
-
-
-
-
-setLayers:function(root,layers,callback)
-{
-var idsToResolve=new Set();
-if(root){
-
-
-this._extractNodeIdsToResolve(idsToResolve,{},root);
-}else{
-for(var i=0;i<layers.length;++i)
-this._extractNodeIdsToResolve(idsToResolve,{},layers[i]);
-}
-this._resolveBackendNodeIds(idsToResolve,onBackendNodeIdsResolved.bind(this));
-
-
-
-
-function onBackendNodeIdsResolved()
-{
-var oldLayersById=this._layersById;
-this._layersById={};
-this._contentRoot=null;
-if(root){
-this._root=this._innerSetLayers(oldLayersById,root);
-}else{
-this._layers=layers.map(this._innerSetLayers.bind(this,oldLayersById));
-this._root=this._contentRoot;
-for(var i=0;i<this._layers.length;++i){
-if(this._layers[i].id()!==this._contentRoot.id()){
-this._contentRoot.addChild(this._layers[i]);
-}
-}
-}
-callback();
-}
-},
-
-
-
-
-setTiles:function(tiles)
-{
-this._tileById=new Map();
-for(var tile of tiles)
-this._tileById.set(tile.id,tile);
-},
-
-
-
-
-
-tileById:function(id)
-{
-return this._tileById.get(id)||null;
-},
-
-
-
-
-
-
-_innerSetLayers:function(oldLayersById,payload)
-{
-var layer=oldLayersById[payload.layer_id];
-if(layer)
-layer._reset(payload);else
-
-layer=new WebInspector.TracingLayer(payload);
-this._layersById[payload.layer_id]=layer;
-if(payload.owner_node)
-layer._setNode(this._backendNodeIdToNode.get(payload.owner_node)||null);
-if(!this._contentRoot&&layer.drawsContent())
-this._contentRoot=layer;
-for(var i=0;payload.children&&i<payload.children.length;++i)
-layer.addChild(this._innerSetLayers(oldLayersById,payload.children[i]));
-return layer;
-},
-
-
-
-
-
-
-_extractNodeIdsToResolve:function(nodeIdsToResolve,seenNodeIds,payload)
-{
-var backendNodeId=payload.owner_node;
-if(backendNodeId&&!this._backendNodeIdToNode.has(backendNodeId))
-nodeIdsToResolve.add(backendNodeId);
-for(var i=0;payload.children&&i<payload.children.length;++i)
-this._extractNodeIdsToResolve(nodeIdsToResolve,seenNodeIds,payload.children[i]);
-},
-
-__proto__:WebInspector.LayerTreeBase.prototype};
-
-
-
-
-
-
-
-WebInspector.AgentLayerTree=function(target)
-{
-WebInspector.LayerTreeBase.call(this,target);
-};
-
-WebInspector.AgentLayerTree.prototype={
-
-
-
-
-setLayers:function(payload,callback)
-{
-if(!payload){
-onBackendNodeIdsResolved.call(this);
-return;
-}
-
-var idsToResolve=new Set();
-for(var i=0;i<payload.length;++i){
-var backendNodeId=payload[i].backendNodeId;
-if(!backendNodeId||this._backendNodeIdToNode.has(backendNodeId))
-continue;
-idsToResolve.add(backendNodeId);
-}
-this._resolveBackendNodeIds(idsToResolve,onBackendNodeIdsResolved.bind(this));
-
-
-
-
-function onBackendNodeIdsResolved()
-{
-this._innerSetLayers(payload);
-callback();
-}
-},
-
-
-
-
-_innerSetLayers:function(layers)
-{
-this._reset();
-
-if(!layers)
-return;
-var oldLayersById=this._layersById;
-this._layersById={};
-for(var i=0;i<layers.length;++i){
-var layerId=layers[i].layerId;
-var layer=oldLayersById[layerId];
-if(layer)
-layer._reset(layers[i]);else
-
-layer=new WebInspector.AgentLayer(this._target,layers[i]);
-this._layersById[layerId]=layer;
-var backendNodeId=layers[i].backendNodeId;
-if(backendNodeId)
-layer._setNode(this._backendNodeIdToNode.get(backendNodeId));
-if(!this._contentRoot&&layer.drawsContent())
-this._contentRoot=layer;
-var parentId=layer.parentId();
-if(parentId){
-var parent=this._layersById[parentId];
-if(!parent)
-console.assert(parent,"missing parent "+parentId+" for layer "+layerId);
-parent.addChild(layer);
-}else{
-if(this._root)
-console.assert(false,"Multiple root layers");
-this._root=layer;
-}
-}
-if(this._root)
-this._root._calculateQuad(new WebKitCSSMatrix());
-},
-
-__proto__:WebInspector.LayerTreeBase.prototype};
-
-
-
-
-
-WebInspector.Layer=function()
-{
-};
-
-WebInspector.Layer.prototype={
-
-
-
-id:function(){},
-
-
-
-
-parentId:function(){},
-
-
-
-
-parent:function(){},
-
-
-
-
-isRoot:function(){},
-
-
-
-
-children:function(){},
-
-
-
-
-addChild:function(child){},
-
-
-
-
-node:function(){},
-
-
-
-
-nodeForSelfOrAncestor:function(){},
-
-
-
-
-offsetX:function(){},
-
-
-
-
-offsetY:function(){},
-
-
-
-
-width:function(){},
-
-
-
-
-height:function(){},
-
-
-
-
-transform:function(){},
-
-
-
-
-quad:function(){},
-
-
-
-
-anchorPoint:function(){},
-
-
-
-
-invisible:function(){},
-
-
-
-
-paintCount:function(){},
-
-
-
-
-lastPaintRect:function(){},
-
-
-
-
-scrollRects:function(){},
-
-
-
-
-gpuMemoryUsage:function(){},
-
-
-
-
-requestCompositingReasons:function(callback){},
-
-
-
-
-drawsContent:function(){}};
-
-
-
-
-
-
-
-
-WebInspector.AgentLayer=function(target,layerPayload)
-{
-this._target=target;
-this._reset(layerPayload);
-};
-
-WebInspector.AgentLayer.prototype={
-
-
-
-
-id:function()
-{
-return this._layerPayload.layerId;
-},
-
-
-
-
-
-parentId:function()
-{
-return this._layerPayload.parentLayerId;
-},
-
-
-
-
-
-parent:function()
-{
-return this._parent;
-},
-
-
-
-
-
-isRoot:function()
-{
-return!this.parentId();
-},
-
-
-
-
-
-children:function()
-{
-return this._children;
-},
-
-
-
-
-
-addChild:function(child)
-{
-if(child._parent)
-console.assert(false,"Child already has a parent");
-this._children.push(child);
-child._parent=this;
-},
-
-
-
-
-_setNode:function(node)
-{
-this._node=node;
-},
-
-
-
-
-
-node:function()
-{
-return this._node;
-},
-
-
-
-
-
-nodeForSelfOrAncestor:function()
-{
-for(var layer=this;layer;layer=layer._parent){
-if(layer._node)
-return layer._node;
-}
-return null;
-},
-
-
-
-
-
-offsetX:function()
-{
-return this._layerPayload.offsetX;
-},
-
-
-
-
-
-offsetY:function()
-{
-return this._layerPayload.offsetY;
-},
-
-
-
-
-
-width:function()
-{
-return this._layerPayload.width;
-},
-
-
-
-
-
-height:function()
-{
-return this._layerPayload.height;
-},
-
-
-
-
-
-transform:function()
-{
-return this._layerPayload.transform;
-},
-
-
-
-
-
-quad:function()
-{
-return this._quad;
-},
-
-
-
-
-
-anchorPoint:function()
-{
-return[
-this._layerPayload.anchorX||0,
-this._layerPayload.anchorY||0,
-this._layerPayload.anchorZ||0];
-
-},
-
-
-
-
-
-invisible:function()
-{
-return this._layerPayload.invisible;
-},
-
-
-
-
-
-paintCount:function()
-{
-return this._paintCount||this._layerPayload.paintCount;
-},
-
-
-
-
-
-lastPaintRect:function()
-{
-return this._lastPaintRect;
-},
-
-
-
-
-
-scrollRects:function()
-{
-return this._scrollRects;
-},
-
-
-
-
-
-requestCompositingReasons:function(callback)
-{
-if(!this._target){
-callback([]);
-return;
-}
-
-var wrappedCallback=InspectorBackend.wrapClientCallback(callback,"LayerTreeAgent.reasonsForCompositingLayer(): ",undefined,[]);
-this._target.layerTreeAgent().compositingReasons(this.id(),wrappedCallback);
-},
-
-
-
-
-
-drawsContent:function()
-{
-return this._layerPayload.drawsContent;
-},
-
-
-
-
-
-gpuMemoryUsage:function()
-{
-
-
-
-var bytesPerPixel=4;
-return this.drawsContent()?this.width()*this.height()*bytesPerPixel:0;
-},
-
-
-
-
-requestSnapshot:function(callback)
-{
-if(!this._target){
-callback();
-return;
-}
-
-var wrappedCallback=InspectorBackend.wrapClientCallback(callback,"LayerTreeAgent.makeSnapshot(): ",WebInspector.PaintProfilerSnapshot.bind(null,this._target));
-this._target.layerTreeAgent().makeSnapshot(this.id(),wrappedCallback);
-},
-
-
-
-
-_didPaint:function(rect)
-{
-this._lastPaintRect=rect;
-this._paintCount=this.paintCount()+1;
-this._image=null;
-},
-
-
-
-
-_reset:function(layerPayload)
-{
-
-this._node=null;
-this._children=[];
-this._parent=null;
-this._paintCount=0;
-this._layerPayload=layerPayload;
-this._image=null;
-this._scrollRects=this._layerPayload.scrollRects||[];
-},
-
-
-
-
-
-_matrixFromArray:function(a)
-{
-function toFixed9(x){return x.toFixed(9);}
-return new WebKitCSSMatrix("matrix3d("+a.map(toFixed9).join(",")+")");
-},
-
-
-
-
-
-_calculateTransformToViewport:function(parentTransform)
-{
-var offsetMatrix=new WebKitCSSMatrix().translate(this._layerPayload.offsetX,this._layerPayload.offsetY);
-var matrix=offsetMatrix;
-
-if(this._layerPayload.transform){
-var transformMatrix=this._matrixFromArray(this._layerPayload.transform);
-var anchorVector=new WebInspector.Geometry.Vector(this._layerPayload.width*this.anchorPoint()[0],this._layerPayload.height*this.anchorPoint()[1],this.anchorPoint()[2]);
-var anchorPoint=WebInspector.Geometry.multiplyVectorByMatrixAndNormalize(anchorVector,matrix);
-var anchorMatrix=new WebKitCSSMatrix().translate(-anchorPoint.x,-anchorPoint.y,-anchorPoint.z);
-matrix=anchorMatrix.inverse().multiply(transformMatrix.multiply(anchorMatrix.multiply(matrix)));
-}
-
-matrix=parentTransform.multiply(matrix);
-return matrix;
-},
-
-
-
-
-
-
-_createVertexArrayForRect:function(width,height)
-{
-return[0,0,0,width,0,0,width,height,0,0,height,0];
-},
-
-
-
-
-_calculateQuad:function(parentTransform)
-{
-var matrix=this._calculateTransformToViewport(parentTransform);
-this._quad=[];
-var vertices=this._createVertexArrayForRect(this._layerPayload.width,this._layerPayload.height);
-for(var i=0;i<4;++i){
-var point=WebInspector.Geometry.multiplyVectorByMatrixAndNormalize(new WebInspector.Geometry.Vector(vertices[i*3],vertices[i*3+1],vertices[i*3+2]),matrix);
-this._quad.push(point.x,point.y);
-}
-
-function calculateQuadForLayer(layer)
-{
-layer._calculateQuad(matrix);
-}
-
-this._children.forEach(calculateQuadForLayer);
-}};
-
-
-
-
-
-
-
-WebInspector.TracingLayer=function(payload)
-{
-this._reset(payload);
-};
-
-WebInspector.TracingLayer.prototype={
-
-
-
-_reset:function(payload)
-{
-
-this._node=null;
-this._layerId=String(payload.layer_id);
-this._offsetX=payload.position[0];
-this._offsetY=payload.position[1];
-this._width=payload.bounds.width;
-this._height=payload.bounds.height;
-this._children=[];
-this._parentLayerId=null;
-this._parent=null;
-this._quad=payload.layer_quad||[];
-this._createScrollRects(payload);
-this._compositingReasons=payload.compositing_reasons||[];
-this._drawsContent=!!payload.draws_content;
-this._gpuMemoryUsage=payload.gpu_memory_usage;
-},
-
-
-
-
-
-id:function()
-{
-return this._layerId;
-},
-
-
-
-
-
-parentId:function()
-{
-return this._parentLayerId;
-},
-
-
-
-
-
-parent:function()
-{
-return this._parent;
-},
-
-
-
-
-
-isRoot:function()
-{
-return!this.parentId();
-},
-
-
-
-
-
-children:function()
-{
-return this._children;
-},
-
-
-
-
-
-addChild:function(child)
-{
-if(child._parent)
-console.assert(false,"Child already has a parent");
-this._children.push(child);
-child._parent=this;
-child._parentLayerId=this._layerId;
-},
-
-
-
-
-
-_setNode:function(node)
-{
-this._node=node;
-},
-
-
-
-
-
-node:function()
-{
-return this._node;
-},
-
-
-
-
-
-nodeForSelfOrAncestor:function()
-{
-for(var layer=this;layer;layer=layer._parent){
-if(layer._node)
-return layer._node;
-}
-return null;
-},
-
-
-
-
-
-offsetX:function()
-{
-return this._offsetX;
-},
-
-
-
-
-
-offsetY:function()
-{
-return this._offsetY;
-},
-
-
-
-
-
-width:function()
-{
-return this._width;
-},
-
-
-
-
-
-height:function()
-{
-return this._height;
-},
-
-
-
-
-
-transform:function()
-{
-return null;
-},
-
-
-
-
-
-quad:function()
-{
-return this._quad;
-},
-
-
-
-
-
-anchorPoint:function()
-{
-return[0.5,0.5,0];
-},
-
-
-
-
-
-invisible:function()
-{
-return false;
-},
-
-
-
-
-
-paintCount:function()
-{
-return 0;
-},
-
-
-
-
-
-lastPaintRect:function()
-{
-return null;
-},
-
-
-
-
-
-scrollRects:function()
-{
-return this._scrollRects;
-},
-
-
-
-
-
-gpuMemoryUsage:function()
-{
-return this._gpuMemoryUsage;
-},
-
-
-
-
-
-
-_scrollRectsFromParams:function(params,type)
-{
-return{rect:{x:params[0],y:params[1],width:params[2],height:params[3]},type:type};
-},
-
-
-
-
-_createScrollRects:function(payload)
-{
-this._scrollRects=[];
-if(payload.non_fast_scrollable_region)
-this._scrollRects.push(this._scrollRectsFromParams(payload.non_fast_scrollable_region,WebInspector.LayerTreeModel.ScrollRectType.NonFastScrollable.name));
-if(payload.touch_event_handler_region)
-this._scrollRects.push(this._scrollRectsFromParams(payload.touch_event_handler_region,WebInspector.LayerTreeModel.ScrollRectType.TouchEventHandler.name));
-if(payload.wheel_event_handler_region)
-this._scrollRects.push(this._scrollRectsFromParams(payload.wheel_event_handler_region,WebInspector.LayerTreeModel.ScrollRectType.WheelEventHandler.name));
-if(payload.scroll_event_handler_region)
-this._scrollRects.push(this._scrollRectsFromParams(payload.scroll_event_handler_region,WebInspector.LayerTreeModel.ScrollRectType.RepaintsOnScroll.name));
-},
-
-
-
-
-
-requestCompositingReasons:function(callback)
-{
-callback(this._compositingReasons);
-},
-
-
-
-
-
-drawsContent:function()
-{
-return this._drawsContent;
-}};
-
-
-
-
-
-
-WebInspector.DeferredLayerTree=function(target)
-{
-this._target=target;
-};
-
-WebInspector.DeferredLayerTree.prototype={
-
-
-
-resolve:function(callback){},
-
-
-
-
-target:function()
-{
-return this._target;
-}};
-
-
-
-
-
-
-
-WebInspector.LayerTreeDispatcher=function(layerTreeModel)
-{
-this._layerTreeModel=layerTreeModel;
-};
-
-WebInspector.LayerTreeDispatcher.prototype={
-
-
-
-
-layerTreeDidChange:function(layers)
-{
-this._layerTreeModel._layerTreeChanged(layers||null);
-},
-
-
-
-
-
-
-layerPainted:function(layerId,clipRect)
-{
-this._layerTreeModel._layerPainted(layerId,clipRect);
-}};
-
-
-
-
-
-
-WebInspector.LayerTreeModel.fromTarget=function(target)
-{
-if(!target.hasDOMCapability())
-return null;
-
-var model=target.model(WebInspector.LayerTreeModel);
-if(!model)
-model=new WebInspector.LayerTreeModel(target);
-return model;
-};
-
-},{}],127:[function(require,module,exports){
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-WebInspector.TimelineFrameModel=function(categoryMapper)
-{
-this._categoryMapper=categoryMapper;
-this.reset();
-};
-
-WebInspector.TimelineFrameModel._mainFrameMarkers=[
-WebInspector.TimelineModel.RecordType.ScheduleStyleRecalculation,
-WebInspector.TimelineModel.RecordType.InvalidateLayout,
-WebInspector.TimelineModel.RecordType.BeginMainThreadFrame,
-WebInspector.TimelineModel.RecordType.ScrollLayer];
-
-
-WebInspector.TimelineFrameModel.prototype={
-
-
-
-frames:function()
-{
-return this._frames;
-},
-
-
-
-
-
-
-filteredFrames:function(startTime,endTime)
-{
-
-
-
-
-
-function compareStartTime(value,object)
-{
-return value-object.startTime;
-}
-
-
-
-
-
-function compareEndTime(value,object)
-{
-return value-object.endTime;
-}
-var frames=this._frames;
-var firstFrame=frames.lowerBound(startTime,compareEndTime);
-var lastFrame=frames.lowerBound(endTime,compareStartTime);
-return frames.slice(firstFrame,lastFrame);
-},
-
-
-
-
-
-hasRasterTile:function(rasterTask)
-{
-var data=rasterTask.args["tileData"];
-if(!data)
-return false;
-var frameId=data["sourceFrameNumber"];
-var frame=frameId&&this._frameById[frameId];
-if(!frame||!frame.layerTree)
-return false;
-return true;
-},
-
-
-
-
-
-requestRasterTile:function(rasterTask,callback)
-{
-var target=this._target;
-if(!target){
-callback(null,null);
-return;
-}
-var data=rasterTask.args["tileData"];
-var frameId=data["sourceFrameNumber"];
-var frame=frameId&&this._frameById[frameId];
-if(!frame||!frame.layerTree){
-callback(null,null);
-return;
-}
-
-var tileId=data["tileId"]&&data["tileId"]["id_ref"];
-
-var fragments=[];
-
-var tile=null;
-var x0=Infinity;
-var y0=Infinity;
-
-frame.layerTree.resolve(layerTreeResolved);
-
-
-
-function layerTreeResolved(layerTree)
-{
-tile=tileId&&layerTree.tileById("cc::Tile/"+tileId);
-if(!tile){
-console.error("Tile "+tileId+" missing in frame "+frameId);
-callback(null,null);
-return;
-}
-var fetchPictureFragmentsBarrier=new CallbackBarrier();
-for(var paint of frame.paints){
-if(tile.layer_id===paint.layerId())
-paint.loadPicture(fetchPictureFragmentsBarrier.createCallback(pictureLoaded));
-}
-fetchPictureFragmentsBarrier.callWhenDone(allPicturesLoaded);
-}
-
-
-
-
-
-
-
-
-function segmentsOverlap(a1,a2,b1,b2)
-{
-console.assert(a1<=a2&&b1<=b2,"segments should be specified as ordered pairs");
-return a2>b1&&a1<b2;
-}
-
-
-
-
-
-function rectsOverlap(a,b)
-{
-return segmentsOverlap(a[0],a[0]+a[2],b[0],b[0]+b[2])&&segmentsOverlap(a[1],a[1]+a[3],b[1],b[1]+b[3]);
-}
-
-
-
-
-
-function pictureLoaded(rect,picture)
-{
-if(!rect||!picture)
-return;
-if(!rectsOverlap(rect,tile.content_rect))
-return;
-var x=rect[0];
-var y=rect[1];
-x0=Math.min(x0,x);
-y0=Math.min(y0,y);
-fragments.push({x:x,y:y,picture:picture});
-}
-
-function allPicturesLoaded()
-{
-if(!fragments.length){
-callback(null,null);
-return;
-}
-var rectArray=tile.content_rect;
-
-var rect={x:rectArray[0]-x0,y:rectArray[1]-y0,width:rectArray[2],height:rectArray[3]};
-WebInspector.PaintProfilerSnapshot.loadFromFragments(target,fragments,callback.bind(null,rect));
-}
-},
-
-reset:function()
-{
-this._minimumRecordTime=Infinity;
-this._frames=[];
-this._frameById={};
-this._lastFrame=null;
-this._lastLayerTree=null;
-this._mainFrameCommitted=false;
-this._mainFrameRequested=false;
-this._framePendingCommit=null;
-this._lastBeginFrame=null;
-this._lastNeedsBeginFrame=null;
-this._framePendingActivation=null;
-this._lastTaskBeginTime=null;
-this._target=null;
-this._sessionId=null;
-this._currentTaskTimeByCategory={};
-},
-
-
-
-
-handleBeginFrame:function(startTime)
-{
-if(!this._lastFrame)
-this._startFrame(startTime);
-this._lastBeginFrame=startTime;
-},
-
-
-
-
-handleDrawFrame:function(startTime)
-{
-if(!this._lastFrame){
-this._startFrame(startTime);
-return;
-}
-
-
-
-if(this._mainFrameCommitted||!this._mainFrameRequested){
-if(this._lastNeedsBeginFrame){
-var idleTimeEnd=this._framePendingActivation?this._framePendingActivation.triggerTime:this._lastBeginFrame||this._lastNeedsBeginFrame;
-if(idleTimeEnd>this._lastFrame.startTime){
-this._lastFrame.idle=true;
-this._startFrame(idleTimeEnd);
-if(this._framePendingActivation)
-this._commitPendingFrame();
-this._lastBeginFrame=null;
-}
-this._lastNeedsBeginFrame=null;
-}
-this._startFrame(startTime);
-}
-this._mainFrameCommitted=false;
-},
-
-handleActivateLayerTree:function()
-{
-if(!this._lastFrame)
-return;
-if(this._framePendingActivation&&!this._lastNeedsBeginFrame)
-this._commitPendingFrame();
-},
-
-handleRequestMainThreadFrame:function()
-{
-if(!this._lastFrame)
-return;
-this._mainFrameRequested=true;
-},
-
-handleCompositeLayers:function()
-{
-if(!this._framePendingCommit)
-return;
-this._framePendingActivation=this._framePendingCommit;
-this._framePendingCommit=null;
-this._mainFrameRequested=false;
-this._mainFrameCommitted=true;
-},
-
-
-
-
-handleLayerTreeSnapshot:function(layerTree)
-{
-this._lastLayerTree=layerTree;
-},
-
-
-
-
-
-handleNeedFrameChanged:function(startTime,needsBeginFrame)
-{
-if(needsBeginFrame)
-this._lastNeedsBeginFrame=startTime;
-},
-
-
-
-
-_startFrame:function(startTime)
-{
-if(this._lastFrame)
-this._flushFrame(this._lastFrame,startTime);
-this._lastFrame=new WebInspector.TimelineFrame(startTime,startTime-this._minimumRecordTime);
-},
-
-
-
-
-
-_flushFrame:function(frame,endTime)
-{
-frame._setLayerTree(this._lastLayerTree);
-frame._setEndTime(endTime);
-if(this._frames.length&&(frame.startTime!==this._frames.peekLast().endTime||frame.startTime>frame.endTime))
-console.assert(false,`Inconsistent frame time for frame ${this._frames.length} (${frame.startTime} - ${frame.endTime})`);
-this._frames.push(frame);
-if(typeof frame._mainFrameId==="number")
-this._frameById[frame._mainFrameId]=frame;
-},
-
-_commitPendingFrame:function()
-{
-this._lastFrame._addTimeForCategories(this._framePendingActivation.timeByCategory);
-this._lastFrame.paints=this._framePendingActivation.paints;
-this._lastFrame._mainFrameId=this._framePendingActivation.mainFrameId;
-this._framePendingActivation=null;
-},
-
-
-
-
-
-
-_findRecordRecursively:function(types,record)
-{
-if(types.indexOf(record.type())>=0)
-return record;
-if(!record.children())
-return null;
-for(var i=0;i<record.children().length;++i){
-var result=this._findRecordRecursively(types,record.children()[i]);
-if(result)
-return result;
-}
-return null;
-},
-
-
-
-
-
-
-addTraceEvents:function(target,events,sessionId)
-{
-this._target=target;
-this._sessionId=sessionId;
-if(!events.length)
-return;
-if(events[0].startTime<this._minimumRecordTime)
-this._minimumRecordTime=events[0].startTime;
-for(var i=0;i<events.length;++i)
-this._addTraceEvent(events[i]);
-},
-
-
-
-
-_addTraceEvent:function(event)
-{
-var eventNames=WebInspector.TimelineModel.RecordType;
-
-if(event.name===eventNames.SetLayerTreeId){
-var sessionId=event.args["sessionId"]||event.args["data"]["sessionId"];
-if(this._sessionId===sessionId)
-this._layerTreeId=event.args["layerTreeId"]||event.args["data"]["layerTreeId"];
-}else if(event.name===eventNames.TracingStartedInPage){
-this._mainThread=event.thread;
-}else if(event.phase===WebInspector.TracingModel.Phase.SnapshotObject&&event.name===eventNames.LayerTreeHostImplSnapshot&&parseInt(event.id,0)===this._layerTreeId){
-var snapshot=event;
-this.handleLayerTreeSnapshot(new WebInspector.DeferredTracingLayerTree(snapshot,this._target));
-}else{
-this._processCompositorEvents(event);
-if(event.thread===this._mainThread)
-this._addMainThreadTraceEvent(event);else
-if(this._lastFrame&&event.selfTime&&!WebInspector.TracingModel.isTopLevelEvent(event))
-this._lastFrame._addTimeForCategory(this._categoryMapper(event),event.selfTime);
-}
-},
-
-
-
-
-_processCompositorEvents:function(event)
-{
-var eventNames=WebInspector.TimelineModel.RecordType;
-
-if(event.args["layerTreeId"]!==this._layerTreeId)
-return;
-
-var timestamp=event.startTime;
-if(event.name===eventNames.BeginFrame)
-this.handleBeginFrame(timestamp);else
-if(event.name===eventNames.DrawFrame)
-this.handleDrawFrame(timestamp);else
-if(event.name===eventNames.ActivateLayerTree)
-this.handleActivateLayerTree();else
-if(event.name===eventNames.RequestMainThreadFrame)
-this.handleRequestMainThreadFrame();else
-if(event.name===eventNames.NeedsBeginFrameChanged)
-this.handleNeedFrameChanged(timestamp,event.args["data"]&&event.args["data"]["needsBeginFrame"]);
-},
-
-
-
-
-_addMainThreadTraceEvent:function(event)
-{
-var eventNames=WebInspector.TimelineModel.RecordType;
-var timestamp=event.startTime;
-var selfTime=event.selfTime||0;
-
-if(WebInspector.TracingModel.isTopLevelEvent(event)){
-this._currentTaskTimeByCategory={};
-this._lastTaskBeginTime=event.startTime;
-}
-if(!this._framePendingCommit&&WebInspector.TimelineFrameModel._mainFrameMarkers.indexOf(event.name)>=0)
-this._framePendingCommit=new WebInspector.PendingFrame(this._lastTaskBeginTime||event.startTime,this._currentTaskTimeByCategory);
-if(!this._framePendingCommit){
-this._addTimeForCategory(this._currentTaskTimeByCategory,event);
-return;
-}
-this._addTimeForCategory(this._framePendingCommit.timeByCategory,event);
-
-if(event.name===eventNames.BeginMainThreadFrame&&event.args["data"]&&event.args["data"]["frameId"])
-this._framePendingCommit.mainFrameId=event.args["data"]["frameId"];
-if(event.name===eventNames.Paint&&event.args["data"]["layerId"]&&event.picture&&this._target)
-this._framePendingCommit.paints.push(new WebInspector.LayerPaintEvent(event,this._target));
-if(event.name===eventNames.CompositeLayers&&event.args["layerTreeId"]===this._layerTreeId)
-this.handleCompositeLayers();
-},
-
-
-
-
-
-_addTimeForCategory:function(timeByCategory,event)
-{
-if(!event.selfTime)
-return;
-var categoryName=this._categoryMapper(event);
-timeByCategory[categoryName]=(timeByCategory[categoryName]||0)+event.selfTime;
-}};
-
-
-
-
-
-
-
-
-WebInspector.DeferredTracingLayerTree=function(snapshot,target)
-{
-WebInspector.DeferredLayerTree.call(this,target);
-this._snapshot=snapshot;
-};
-
-WebInspector.DeferredTracingLayerTree.prototype={
-
-
-
-
-resolve:function(callback)
-{
-this._snapshot.requestObject(onGotObject.bind(this));
-
-
-
-
-function onGotObject(result)
-{
-if(!result)
-return;
-var viewport=result["device_viewport_size"];
-var tiles=result["active_tiles"];
-var rootLayer=result["active_tree"]["root_layer"];
-var layers=result["active_tree"]["layers"];
-var layerTree=new WebInspector.TracingLayerTree(this._target);
-layerTree.setViewportSize(viewport);
-layerTree.setTiles(tiles);
-layerTree.setLayers(rootLayer,layers,callback.bind(null,layerTree));
-}
-},
-
-__proto__:WebInspector.DeferredLayerTree.prototype};
-
-
-
-
-
-
-
-
-WebInspector.TimelineFrame=function(startTime,startTimeOffset)
-{
-this.startTime=startTime;
-this.startTimeOffset=startTimeOffset;
-this.endTime=this.startTime;
-this.duration=0;
-this.timeByCategory={};
-this.cpuTime=0;
-this.idle=false;
-
-this.layerTree=null;
-
-this.paints=[];
-
-this._mainFrameId=undefined;
-};
-
-WebInspector.TimelineFrame.prototype={
-
-
-
-hasWarnings:function()
-{
-var longFrameDurationThresholdMs=22;
-return!this.idle&&this.duration>longFrameDurationThresholdMs;
-},
-
-
-
-
-_setEndTime:function(endTime)
-{
-this.endTime=endTime;
-this.duration=this.endTime-this.startTime;
-},
-
-
-
-
-_setLayerTree:function(layerTree)
-{
-this.layerTree=layerTree;
-},
-
-
-
-
-_addTimeForCategories:function(timeByCategory)
-{
-for(var category in timeByCategory)
-this._addTimeForCategory(category,timeByCategory[category]);
-},
-
-
-
-
-
-_addTimeForCategory:function(category,time)
-{
-this.timeByCategory[category]=(this.timeByCategory[category]||0)+time;
-this.cpuTime+=time;
-}};
-
-
-
-
-
-
-
-WebInspector.LayerPaintEvent=function(event,target)
-{
-this._event=event;
-this._target=target;
-};
-
-WebInspector.LayerPaintEvent.prototype={
-
-
-
-layerId:function()
-{
-return this._event.args["data"]["layerId"];
-},
-
-
-
-
-event:function()
-{
-return this._event;
-},
-
-
-
-
-loadPicture:function(callback)
-{
-this._event.picture.requestObject(onGotObject);
-
-
-
-function onGotObject(result)
-{
-if(!result||!result["skp64"]){
-callback(null,null);
-return;
-}
-var rect=result["params"]&&result["params"]["layer_rect"];
-callback(rect,result["skp64"]);
-}
-},
-
-
-
-
-loadSnapshot:function(callback)
-{
-this.loadPicture(onGotPicture.bind(this));
-
-
-
-
-
-function onGotPicture(rect,picture)
-{
-if(!rect||!picture||!this._target){
-callback(null,null);
-return;
-}
-WebInspector.PaintProfilerSnapshot.load(this._target,picture,callback.bind(null,rect));
-}
-}};
-
-
-
-
-
-
-
-WebInspector.PendingFrame=function(triggerTime,timeByCategory)
-{
-
-this.timeByCategory=timeByCategory;
-
-this.paints=[];
-
-this.mainFrameId=undefined;
-this.triggerTime=triggerTime;
-};
-
-},{}],128:[function(require,module,exports){
-
-
-
-
-
-
-
-WebInspector.TimelineIRModel=function()
-{
-this.reset();
-};
-
-
-
-
-WebInspector.TimelineIRModel.Phases={
-Idle:"Idle",
-Response:"Response",
-Scroll:"Scroll",
-Fling:"Fling",
-Drag:"Drag",
-Animation:"Animation",
-Uncategorized:"Uncategorized"};
-
-
-
-
-
-WebInspector.TimelineIRModel.InputEvents={
-Char:"Char",
-Click:"GestureClick",
-ContextMenu:"ContextMenu",
-FlingCancel:"GestureFlingCancel",
-FlingStart:"GestureFlingStart",
-ImplSideFling:WebInspector.TimelineModel.RecordType.ImplSideFling,
-KeyDown:"KeyDown",
-KeyDownRaw:"RawKeyDown",
-KeyUp:"KeyUp",
-LatencyScrollUpdate:"ScrollUpdate",
-MouseDown:"MouseDown",
-MouseMove:"MouseMove",
-MouseUp:"MouseUp",
-MouseWheel:"MouseWheel",
-PinchBegin:"GesturePinchBegin",
-PinchEnd:"GesturePinchEnd",
-PinchUpdate:"GesturePinchUpdate",
-ScrollBegin:"GestureScrollBegin",
-ScrollEnd:"GestureScrollEnd",
-ScrollUpdate:"GestureScrollUpdate",
-ScrollUpdateRenderer:"ScrollUpdate",
-ShowPress:"GestureShowPress",
-Tap:"GestureTap",
-TapCancel:"GestureTapCancel",
-TapDown:"GestureTapDown",
-TouchCancel:"TouchCancel",
-TouchEnd:"TouchEnd",
-TouchMove:"TouchMove",
-TouchStart:"TouchStart"};
-
-
-WebInspector.TimelineIRModel._mergeThresholdsMs={
-animation:1,
-mouse:40};
-
-
-WebInspector.TimelineIRModel._eventIRPhase=Symbol("eventIRPhase");
-
-
-
-
-
-WebInspector.TimelineIRModel.phaseForEvent=function(event)
-{
-return event[WebInspector.TimelineIRModel._eventIRPhase];
-};
-
-WebInspector.TimelineIRModel.prototype={
-
-
-
-
-populate:function(inputLatencies,animations)
-{
-var eventTypes=WebInspector.TimelineIRModel.InputEvents;
-var phases=WebInspector.TimelineIRModel.Phases;
-
-this.reset();
-if(!inputLatencies)
-return;
-this._processInputLatencies(inputLatencies);
-if(animations)
-this._processAnimations(animations);
-var range=new WebInspector.SegmentedRange();
-range.appendRange(this._drags);
-range.appendRange(this._cssAnimations);
-range.appendRange(this._scrolls);
-range.appendRange(this._responses);
-this._segments=range.segments();
-},
-
-
-
-
-_processInputLatencies:function(events)
-{
-var eventTypes=WebInspector.TimelineIRModel.InputEvents;
-var phases=WebInspector.TimelineIRModel.Phases;
-var thresholdsMs=WebInspector.TimelineIRModel._mergeThresholdsMs;
-
-var scrollStart;
-var flingStart;
-var touchStart;
-var firstTouchMove;
-var mouseWheel;
-var mouseDown;
-var mouseMove;
-
-for(var i=0;i<events.length;++i){
-var event=events[i];
-if(i>0&&events[i].startTime<events[i-1].startTime)
-console.assert(false,"Unordered input events");
-var type=this._inputEventType(event.name);
-switch(type){
-
-case eventTypes.ScrollBegin:
-this._scrolls.append(this._segmentForEvent(event,phases.Scroll));
-scrollStart=event;
-break;
-
-case eventTypes.ScrollEnd:
-if(scrollStart)
-this._scrolls.append(this._segmentForEventRange(scrollStart,event,phases.Scroll));else
-
-this._scrolls.append(this._segmentForEvent(event,phases.Scroll));
-scrollStart=null;
-break;
-
-case eventTypes.ScrollUpdate:
-touchStart=null;
-this._scrolls.append(this._segmentForEvent(event,phases.Scroll));
-break;
-
-case eventTypes.FlingStart:
-if(flingStart){
-WebInspector.console.error(WebInspector.UIString("Two flings at the same time? %s vs %s",flingStart.startTime,event.startTime));
-break;
-}
-flingStart=event;
-break;
-
-case eventTypes.FlingCancel:
-
-if(!flingStart)
-break;
-this._scrolls.append(this._segmentForEventRange(flingStart,event,phases.Fling));
-flingStart=null;
-break;
-
-case eventTypes.ImplSideFling:
-this._scrolls.append(this._segmentForEvent(event,phases.Fling));
-break;
-
-case eventTypes.ShowPress:
-case eventTypes.Tap:
-case eventTypes.KeyDown:
-case eventTypes.KeyDownRaw:
-case eventTypes.KeyUp:
-case eventTypes.Char:
-case eventTypes.Click:
-case eventTypes.ContextMenu:
-this._responses.append(this._segmentForEvent(event,phases.Response));
-break;
-
-case eventTypes.TouchStart:
-
-
-if(touchStart){
-WebInspector.console.error(WebInspector.UIString("Two touches at the same time? %s vs %s",touchStart.startTime,event.startTime));
-break;
-}
-touchStart=event;
-event.steps[0][WebInspector.TimelineIRModel._eventIRPhase]=phases.Response;
-firstTouchMove=null;
-break;
-
-case eventTypes.TouchCancel:
-touchStart=null;
-break;
-
-case eventTypes.TouchMove:
-if(firstTouchMove){
-this._drags.append(this._segmentForEvent(event,phases.Drag));
-}else if(touchStart){
-firstTouchMove=event;
-this._responses.append(this._segmentForEventRange(touchStart,event,phases.Response));
-}
-break;
-
-case eventTypes.TouchEnd:
-touchStart=null;
-break;
-
-case eventTypes.MouseDown:
-mouseDown=event;
-mouseMove=null;
-break;
-
-case eventTypes.MouseMove:
-if(mouseDown&&!mouseMove&&mouseDown.startTime+thresholdsMs.mouse>event.startTime){
-this._responses.append(this._segmentForEvent(mouseDown,phases.Response));
-this._responses.append(this._segmentForEvent(event,phases.Response));
-}else if(mouseDown){
-this._drags.append(this._segmentForEvent(event,phases.Drag));
-}
-mouseMove=event;
-break;
-
-case eventTypes.MouseUp:
-this._responses.append(this._segmentForEvent(event,phases.Response));
-mouseDown=null;
-break;
-
-case eventTypes.MouseWheel:
-
-if(mouseWheel&&canMerge(thresholdsMs.mouse,mouseWheel,event))
-this._scrolls.append(this._segmentForEventRange(mouseWheel,event,phases.Scroll));else
-
-this._scrolls.append(this._segmentForEvent(event,phases.Scroll));
-mouseWheel=event;
-break;}
-
-}
-
-
-
-
-
-
-
-function canMerge(threshold,first,second)
-{
-return first.endTime<second.startTime&&second.startTime<first.endTime+threshold;
-}
-},
-
-
-
-
-_processAnimations:function(events)
-{
-for(var i=0;i<events.length;++i)
-this._cssAnimations.append(this._segmentForEvent(events[i],WebInspector.TimelineIRModel.Phases.Animation));
-},
-
-
-
-
-
-
-_segmentForEvent:function(event,phase)
-{
-this._setPhaseForEvent(event,phase);
-return new WebInspector.Segment(event.startTime,event.endTime,phase);
-},
-
-
-
-
-
-
-
-_segmentForEventRange:function(startEvent,endEvent,phase)
-{
-this._setPhaseForEvent(startEvent,phase);
-this._setPhaseForEvent(endEvent,phase);
-return new WebInspector.Segment(startEvent.startTime,endEvent.endTime,phase);
-},
-
-
-
-
-
-_setPhaseForEvent:function(asyncEvent,phase)
-{
-asyncEvent.steps[0][WebInspector.TimelineIRModel._eventIRPhase]=phase;
-},
-
-
-
-
-interactionRecords:function()
-{
-return this._segments;
-},
-
-reset:function()
-{
-var thresholdsMs=WebInspector.TimelineIRModel._mergeThresholdsMs;
-
-this._segments=[];
-this._drags=new WebInspector.SegmentedRange(merge.bind(null,thresholdsMs.mouse));
-this._cssAnimations=new WebInspector.SegmentedRange(merge.bind(null,thresholdsMs.animation));
-this._responses=new WebInspector.SegmentedRange(merge.bind(null,0));
-this._scrolls=new WebInspector.SegmentedRange(merge.bind(null,thresholdsMs.animation));
-
-
-
-
-
-
-function merge(threshold,first,second)
-{
-return first.end+threshold>=second.begin&&first.data===second.data?first:null;
-}
-},
-
-
-
-
-
-_inputEventType:function(eventName)
-{
-var prefix="InputLatency::";
-if(!eventName.startsWith(prefix)){
-if(eventName===WebInspector.TimelineIRModel.InputEvents.ImplSideFling)
-return eventName;
-console.error("Unrecognized input latency event: "+eventName);
-return null;
-}
-return eventName.substr(prefix.length);
-}};
-
-
-
-},{}],129:[function(require,module,exports){
-
-
-
-
-
-WebInspector.TimelineJSProfileProcessor={};
-
-
-
-
-
-
-WebInspector.TimelineJSProfileProcessor.generateTracingEventsFromCpuProfile=function(jsProfileModel,thread)
-{
-var idleNode=jsProfileModel.idleNode;
-var programNode=jsProfileModel.programNode;
-var gcNode=jsProfileModel.gcNode;
-var samples=jsProfileModel.samples;
-var timestamps=jsProfileModel.timestamps;
-var jsEvents=[];
-
-var nodeToStackMap=new Map();
-nodeToStackMap.set(programNode,[]);
-for(var i=0;i<samples.length;++i){
-var node=jsProfileModel.nodeByIndex(i);
-if(!node){
-console.error(`Node with unknown id ${samples[i]} at index ${i}`);
-continue;
-}
-if(node===gcNode||node===idleNode)
-continue;
-var callFrames=nodeToStackMap.get(node);
-if(!callFrames){
-callFrames=new Array(node.depth+1);
-nodeToStackMap.set(node,callFrames);
-for(var j=0;node.parent;node=node.parent)
-callFrames[j++]=node;
-}
-var jsSampleEvent=new WebInspector.TracingModel.Event(WebInspector.TracingModel.DevToolsTimelineEventCategory,
-WebInspector.TimelineModel.RecordType.JSSample,
-WebInspector.TracingModel.Phase.Instant,timestamps[i],thread);
-jsSampleEvent.args["data"]={stackTrace:callFrames};
-jsEvents.push(jsSampleEvent);
-}
-return jsEvents;
-};
-
-
-
-
-
-WebInspector.TimelineJSProfileProcessor.generateJSFrameEvents=function(events)
-{
-
-
-
-
-
-function equalFrames(frame1,frame2)
-{
-return frame1.scriptId===frame2.scriptId&&frame1.functionName===frame2.functionName;
-}
-
-
-
-
-
-function eventEndTime(e)
-{
-return e.endTime||e.startTime;
-}
-
-
-
-
-
-function isJSInvocationEvent(e)
-{
-switch(e.name){
-case WebInspector.TimelineModel.RecordType.RunMicrotasks:
-case WebInspector.TimelineModel.RecordType.FunctionCall:
-case WebInspector.TimelineModel.RecordType.EvaluateScript:
-return true;}
-
-return false;
-}
-
-var jsFrameEvents=[];
-var jsFramesStack=[];
-var lockedJsStackDepth=[];
-var ordinal=0;
-var filterNativeFunctions=!WebInspector.moduleSetting("showNativeFunctionsInJSProfile").get();
-
-
-
-
-function onStartEvent(e)
-{
-e.ordinal=++ordinal;
-extractStackTrace(e);
-
-lockedJsStackDepth.push(jsFramesStack.length);
-}
-
-
-
-
-
-function onInstantEvent(e,parent)
-{
-e.ordinal=++ordinal;
-if(parent&&isJSInvocationEvent(parent))
-extractStackTrace(e);
-}
-
-
-
-
-function onEndEvent(e)
-{
-truncateJSStack(lockedJsStackDepth.pop(),e.endTime);
-}
-
-
-
-
-
-function truncateJSStack(depth,time)
-{
-if(lockedJsStackDepth.length){
-var lockedDepth=lockedJsStackDepth.peekLast();
-if(depth<lockedDepth){
-console.error("Child stack is shallower ("+depth+") than the parent stack ("+lockedDepth+") at "+time);
-depth=lockedDepth;
-}
-}
-if(jsFramesStack.length<depth){
-console.error("Trying to truncate higher than the current stack size at "+time);
-depth=jsFramesStack.length;
-}
-for(var k=0;k<jsFramesStack.length;++k)
-jsFramesStack[k].setEndTime(time);
-jsFramesStack.length=depth;
-}
-
-
-
-
-function filterStackFrames(stack)
-{
-for(var i=0,j=0;i<stack.length;++i){
-var url=stack[i].url;
-if(url&&url.startsWith("native "))
-continue;
-stack[j++]=stack[i];
-}
-stack.length=j;
-}
-
-
-
-
-function extractStackTrace(e)
-{
-var recordTypes=WebInspector.TimelineModel.RecordType;
-var callFrames;
-if(e.name===recordTypes.JSSample){
-var eventData=e.args["data"]||e.args["beginData"];
-callFrames=eventData&&eventData["stackTrace"];
-}else{
-callFrames=jsFramesStack.map(frameEvent=>frameEvent.args["data"]).reverse();
-}
-if(filterNativeFunctions)
-filterStackFrames(callFrames);
-var endTime=eventEndTime(e);
-var numFrames=callFrames.length;
-var minFrames=Math.min(numFrames,jsFramesStack.length);
-var i;
-for(i=lockedJsStackDepth.peekLast()||0;i<minFrames;++i){
-var newFrame=callFrames[numFrames-1-i];
-var oldFrame=jsFramesStack[i].args["data"];
-if(!equalFrames(newFrame,oldFrame))
-break;
-jsFramesStack[i].setEndTime(Math.max(jsFramesStack[i].endTime,endTime));
-}
-truncateJSStack(i,e.startTime);
-for(;i<numFrames;++i){
-var frame=callFrames[numFrames-1-i];
-var jsFrameEvent=new WebInspector.TracingModel.Event(WebInspector.TracingModel.DevToolsTimelineEventCategory,recordTypes.JSFrame,
-WebInspector.TracingModel.Phase.Complete,e.startTime,e.thread);
-jsFrameEvent.ordinal=e.ordinal;
-jsFrameEvent.addArgs({data:frame});
-jsFrameEvent.setEndTime(endTime);
-jsFramesStack.push(jsFrameEvent);
-jsFrameEvents.push(jsFrameEvent);
-}
-}
-
-
-
-
-
-function findFirstTopLevelEvent(events)
-{
-for(var i=0;i<events.length;++i){
-if(WebInspector.TracingModel.isTopLevelEvent(events[i]))
-return events[i];
-}
-return null;
-}
-
-var firstTopLevelEvent=findFirstTopLevelEvent(events);
-if(firstTopLevelEvent)
-WebInspector.TimelineModel.forEachEvent(events,onStartEvent,onEndEvent,onInstantEvent,firstTopLevelEvent.startTime);
-return jsFrameEvents;
-};
-
-
-
-
-WebInspector.TimelineJSProfileProcessor.CodeMap=function()
-{
-
-this._banks=new Map();
-};
-
-
-
-
-
-
-
-WebInspector.TimelineJSProfileProcessor.CodeMap.Entry=function(address,size,callFrame)
-{
-this.address=address;
-this.size=size;
-this.callFrame=callFrame;
-};
-
-
-
-
-
-
-WebInspector.TimelineJSProfileProcessor.CodeMap.comparator=function(address,entry)
-{
-return address-entry.address;
-};
-
-WebInspector.TimelineJSProfileProcessor.CodeMap.prototype={
-
-
-
-
-
-addEntry:function(addressHex,size,callFrame)
-{
-var entry=new WebInspector.TimelineJSProfileProcessor.CodeMap.Entry(this._getAddress(addressHex),size,callFrame);
-this._addEntry(addressHex,entry);
-},
-
-
-
-
-
-
-moveEntry:function(oldAddressHex,newAddressHex,size)
-{
-var entry=this._getBank(oldAddressHex).removeEntry(this._getAddress(oldAddressHex));
-if(!entry){
-console.error("Entry at address "+oldAddressHex+" not found");
-return;
-}
-entry.address=this._getAddress(newAddressHex);
-entry.size=size;
-this._addEntry(newAddressHex,entry);
-},
-
-
-
-
-
-lookupEntry:function(addressHex)
-{
-return this._getBank(addressHex).lookupEntry(this._getAddress(addressHex));
-},
-
-
-
-
-
-_addEntry:function(addressHex,entry)
-{
-
-this._getBank(addressHex).addEntry(entry);
-},
-
-
-
-
-
-_getBank:function(addressHex)
-{
-addressHex=addressHex.slice(2);
-
-var bankSizeHexDigits=13;
-var maxHexDigits=16;
-var bankName=addressHex.slice(-maxHexDigits,-bankSizeHexDigits);
-var bank=this._banks.get(bankName);
-if(!bank){
-bank=new WebInspector.TimelineJSProfileProcessor.CodeMap.Bank();
-this._banks.set(bankName,bank);
-}
-return bank;
-},
-
-
-
-
-
-_getAddress:function(addressHex)
-{
-
-var bankSizeHexDigits=13;
-addressHex=addressHex.slice(2);
-return parseInt(addressHex.slice(-bankSizeHexDigits),16);
-}};
-
-
-
-
-
-WebInspector.TimelineJSProfileProcessor.CodeMap.Bank=function()
-{
-
-this._entries=[];
-};
-
-WebInspector.TimelineJSProfileProcessor.CodeMap.Bank.prototype={
-
-
-
-
-removeEntry:function(address)
-{
-var index=this._entries.lowerBound(address,WebInspector.TimelineJSProfileProcessor.CodeMap.comparator);
-var entry=this._entries[index];
-if(!entry||entry.address!==address)
-return null;
-this._entries.splice(index,1);
-return entry;
-},
-
-
-
-
-
-lookupEntry:function(address)
-{
-var index=this._entries.upperBound(address,WebInspector.TimelineJSProfileProcessor.CodeMap.comparator)-1;
-var entry=this._entries[index];
-return entry&&address<entry.address+entry.size?entry.callFrame:null;
-},
-
-
-
-
-addEntry:function(newEntry)
-{
-var endAddress=newEntry.address+newEntry.size;
-var lastIndex=this._entries.lowerBound(endAddress,WebInspector.TimelineJSProfileProcessor.CodeMap.comparator);
-var index;
-for(index=lastIndex-1;index>=0;--index){
-var entry=this._entries[index];
-var entryEndAddress=entry.address+entry.size;
-if(entryEndAddress<=newEntry.address)
-break;
-}
-++index;
-this._entries.splice(index,lastIndex-index,newEntry);
-}};
-
-
-
-
-
-
-
-WebInspector.TimelineJSProfileProcessor._buildCallFrame=function(name,scriptId)
-{
-
-
-
-
-
-
-
-
-
-function createFrame(functionName,url,scriptId,line,column,isNative)
-{
-return{
-"functionName":functionName,
-"url":url||"",
-"scriptId":scriptId||"0",
-"lineNumber":line||0,
-"columnNumber":column||0,
-"isNative":isNative||false};
-
-}
-
-
-
-
-
-var rePrefix=/^(\w*:)?[*~]?(.*)$/m;
-var tokens=rePrefix.exec(name);
-var prefix=tokens[1];
-var body=tokens[2];
-var rawName;
-var rawUrl;
-if(prefix==="Script:"){
-rawName="";
-rawUrl=body;
-}else{
-var spacePos=body.lastIndexOf(" ");
-rawName=spacePos!==-1?body.substr(0,spacePos):body;
-rawUrl=spacePos!==-1?body.substr(spacePos+1):"";
-}
-var nativeSuffix=" native";
-var isNative=rawName.endsWith(nativeSuffix);
-var functionName=isNative?rawName.slice(0,-nativeSuffix.length):rawName;
-var urlData=WebInspector.ParsedURL.splitLineAndColumn(rawUrl);
-var url=urlData.url||"";
-var line=urlData.lineNumber||0;
-var column=urlData.columnNumber||0;
-return createFrame(functionName,url,String(scriptId),line,column,isNative);
-};
-
-
-
-
-
-WebInspector.TimelineJSProfileProcessor.processRawV8Samples=function(events)
-{
-var missingAddesses=new Set();
-
-
-
-
-
-function convertRawFrame(address)
-{
-var entry=codeMap.lookupEntry(address);
-if(entry)
-return entry.isNative?null:entry;
-if(!missingAddesses.has(address)){
-missingAddesses.add(address);
-console.error("Address "+address+" has missing code entry");
-}
-return null;
-}
-
-var recordTypes=WebInspector.TimelineModel.RecordType;
-var samples=[];
-var codeMap=new WebInspector.TimelineJSProfileProcessor.CodeMap();
-for(var i=0;i<events.length;++i){
-var e=events[i];
-var data=e.args["data"];
-switch(e.name){
-case recordTypes.JitCodeAdded:
-var frame=WebInspector.TimelineJSProfileProcessor._buildCallFrame(data["name"],data["script_id"]);
-codeMap.addEntry(data["code_start"],data["code_len"],frame);
-break;
-case recordTypes.JitCodeMoved:
-codeMap.moveEntry(data["code_start"],data["new_code_start"],data["code_len"]);
-break;
-case recordTypes.V8Sample:
-var rawStack=data["stack"];
-
-
-if(data["vm_state"]==="js"&&!rawStack.length)
-break;
-var stack=rawStack.map(convertRawFrame);
-stack.remove(null);
-var sampleEvent=new WebInspector.TracingModel.Event(
-WebInspector.TracingModel.DevToolsTimelineEventCategory,
-WebInspector.TimelineModel.RecordType.JSSample,
-WebInspector.TracingModel.Phase.Instant,e.startTime,e.thread);
-sampleEvent.ordinal=e.ordinal;
-sampleEvent.args={"data":{"stackTrace":stack}};
-samples.push(sampleEvent);
-break;}
-
-}
-
-return samples;
-};
-
-},{}],130:[function(require,module,exports){
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-WebInspector.TimelineModel=function(eventFilter)
-{
-this._eventFilter=eventFilter;
-this.reset();
-};
-
-
-
-
-WebInspector.TimelineModel.RecordType={
-Task:"Task",
-Program:"Program",
-EventDispatch:"EventDispatch",
-
-GPUTask:"GPUTask",
-
-Animation:"Animation",
-RequestMainThreadFrame:"RequestMainThreadFrame",
-BeginFrame:"BeginFrame",
-NeedsBeginFrameChanged:"NeedsBeginFrameChanged",
-BeginMainThreadFrame:"BeginMainThreadFrame",
-ActivateLayerTree:"ActivateLayerTree",
-DrawFrame:"DrawFrame",
-HitTest:"HitTest",
-ScheduleStyleRecalculation:"ScheduleStyleRecalculation",
-RecalculateStyles:"RecalculateStyles",
-UpdateLayoutTree:"UpdateLayoutTree",
-InvalidateLayout:"InvalidateLayout",
-Layout:"Layout",
-UpdateLayer:"UpdateLayer",
-UpdateLayerTree:"UpdateLayerTree",
-PaintSetup:"PaintSetup",
-Paint:"Paint",
-PaintImage:"PaintImage",
-Rasterize:"Rasterize",
-RasterTask:"RasterTask",
-ScrollLayer:"ScrollLayer",
-CompositeLayers:"CompositeLayers",
-
-ScheduleStyleInvalidationTracking:"ScheduleStyleInvalidationTracking",
-StyleRecalcInvalidationTracking:"StyleRecalcInvalidationTracking",
-StyleInvalidatorInvalidationTracking:"StyleInvalidatorInvalidationTracking",
-LayoutInvalidationTracking:"LayoutInvalidationTracking",
-LayerInvalidationTracking:"LayerInvalidationTracking",
-PaintInvalidationTracking:"PaintInvalidationTracking",
-ScrollInvalidationTracking:"ScrollInvalidationTracking",
-
-ParseHTML:"ParseHTML",
-ParseAuthorStyleSheet:"ParseAuthorStyleSheet",
-
-TimerInstall:"TimerInstall",
-TimerRemove:"TimerRemove",
-TimerFire:"TimerFire",
-
-XHRReadyStateChange:"XHRReadyStateChange",
-XHRLoad:"XHRLoad",
-CompileScript:"v8.compile",
-EvaluateScript:"EvaluateScript",
-
-CommitLoad:"CommitLoad",
-MarkLoad:"MarkLoad",
-MarkDOMContent:"MarkDOMContent",
-MarkFirstPaint:"MarkFirstPaint",
-
-TimeStamp:"TimeStamp",
-ConsoleTime:"ConsoleTime",
-UserTiming:"UserTiming",
-
-ResourceSendRequest:"ResourceSendRequest",
-ResourceReceiveResponse:"ResourceReceiveResponse",
-ResourceReceivedData:"ResourceReceivedData",
-ResourceFinish:"ResourceFinish",
-
-RunMicrotasks:"RunMicrotasks",
-FunctionCall:"FunctionCall",
-GCEvent:"GCEvent",
-MajorGC:"MajorGC",
-MinorGC:"MinorGC",
-JSFrame:"JSFrame",
-JSSample:"JSSample",
-
-
-
-V8Sample:"V8Sample",
-JitCodeAdded:"JitCodeAdded",
-JitCodeMoved:"JitCodeMoved",
-ParseScriptOnBackground:"v8.parseOnBackground",
-
-UpdateCounters:"UpdateCounters",
-
-RequestAnimationFrame:"RequestAnimationFrame",
-CancelAnimationFrame:"CancelAnimationFrame",
-FireAnimationFrame:"FireAnimationFrame",
-
-RequestIdleCallback:"RequestIdleCallback",
-CancelIdleCallback:"CancelIdleCallback",
-FireIdleCallback:"FireIdleCallback",
-
-WebSocketCreate:"WebSocketCreate",
-WebSocketSendHandshakeRequest:"WebSocketSendHandshakeRequest",
-WebSocketReceiveHandshakeResponse:"WebSocketReceiveHandshakeResponse",
-WebSocketDestroy:"WebSocketDestroy",
-
-EmbedderCallback:"EmbedderCallback",
-
-SetLayerTreeId:"SetLayerTreeId",
-TracingStartedInPage:"TracingStartedInPage",
-TracingSessionIdForWorker:"TracingSessionIdForWorker",
-
-DecodeImage:"Decode Image",
-ResizeImage:"Resize Image",
-DrawLazyPixelRef:"Draw LazyPixelRef",
-DecodeLazyPixelRef:"Decode LazyPixelRef",
-
-LazyPixelRef:"LazyPixelRef",
-LayerTreeHostImplSnapshot:"cc::LayerTreeHostImpl",
-PictureSnapshot:"cc::Picture",
-DisplayItemListSnapshot:"cc::DisplayItemList",
-LatencyInfo:"LatencyInfo",
-LatencyInfoFlow:"LatencyInfo.Flow",
-InputLatencyMouseMove:"InputLatency::MouseMove",
-InputLatencyMouseWheel:"InputLatency::MouseWheel",
-ImplSideFling:"InputHandlerProxy::HandleGestureFling::started",
-GCIdleLazySweep:"ThreadState::performIdleLazySweep",
-GCCompleteSweep:"ThreadState::completeSweep",
-GCCollectGarbage:"BlinkGCMarking",
-
-
-
-CpuProfile:"CpuProfile"};
-
-
-WebInspector.TimelineModel.Category={
-Console:"blink.console",
-UserTiming:"blink.user_timing",
-LatencyInfo:"latencyInfo"};
-
-
-
-
-
-WebInspector.TimelineModel.WarningType={
-ForcedStyle:"ForcedStyle",
-ForcedLayout:"ForcedLayout",
-IdleDeadlineExceeded:"IdleDeadlineExceeded",
-V8Deopt:"V8Deopt"};
-
-
-WebInspector.TimelineModel.MainThreadName="main";
-WebInspector.TimelineModel.WorkerThreadName="DedicatedWorker Thread";
-WebInspector.TimelineModel.RendererMainThreadName="CrRendererMain";
-
-
-
-
-WebInspector.TimelineModel.AsyncEventGroup={
-animation:Symbol("animation"),
-console:Symbol("console"),
-userTiming:Symbol("userTiming"),
-input:Symbol("input")};
-
-
-
-
-
-
-
-
-
-
-WebInspector.TimelineModel.forEachEvent=function(events,onStartEvent,onEndEvent,onInstantEvent,startTime,endTime)
-{
-startTime=startTime||0;
-endTime=endTime||Infinity;
-var stack=[];
-for(var i=0;i<events.length;++i){
-var e=events[i];
-if((e.endTime||e.startTime)<startTime)
-continue;
-if(e.startTime>=endTime)
-break;
-if(WebInspector.TracingModel.isAsyncPhase(e.phase)||WebInspector.TracingModel.isFlowPhase(e.phase))
-continue;
-while(stack.length&&stack.peekLast().endTime<=e.startTime)
-onEndEvent(stack.pop());
-if(e.duration){
-onStartEvent(e);
-stack.push(e);
-}else{
-onInstantEvent&&onInstantEvent(e,stack.peekLast()||null);
-}
-}
-while(stack.length)
-onEndEvent(stack.pop());
-};
-
-WebInspector.TimelineModel.DevToolsMetadataEvent={
-TracingStartedInBrowser:"TracingStartedInBrowser",
-TracingStartedInPage:"TracingStartedInPage",
-TracingSessionIdForWorker:"TracingSessionIdForWorker"};
-
-
-
-
-
-
-WebInspector.TimelineModel.VirtualThread=function(name)
-{
-this.name=name;
-
-this.events=[];
-
-this.asyncEventsByGroup=new Map();
-};
-
-WebInspector.TimelineModel.VirtualThread.prototype={
-
-
-
-isWorker:function()
-{
-return this.name===WebInspector.TimelineModel.WorkerThreadName;
-}};
-
-
-
-
-
-
-WebInspector.TimelineModel.Record=function(traceEvent)
-{
-this._event=traceEvent;
-this._children=[];
-};
-
-
-
-
-
-
-WebInspector.TimelineModel.Record._compareStartTime=function(a,b)
-{
-
-return a.startTime()<=b.startTime()?-1:1;
-};
-
-WebInspector.TimelineModel.Record.prototype={
-
-
-
-target:function()
-{
-var threadName=this._event.thread.name();
-
-return threadName===WebInspector.TimelineModel.RendererMainThreadName?WebInspector.targetManager.targets()[0]||null:null;
-},
-
-
-
-
-children:function()
-{
-return this._children;
-},
-
-
-
-
-startTime:function()
-{
-return this._event.startTime;
-},
-
-
-
-
-endTime:function()
-{
-return this._event.endTime||this._event.startTime;
-},
-
-
-
-
-thread:function()
-{
-if(this._event.thread.name()===WebInspector.TimelineModel.RendererMainThreadName)
-return WebInspector.TimelineModel.MainThreadName;
-return this._event.thread.name();
-},
-
-
-
-
-type:function()
-{
-return WebInspector.TimelineModel._eventType(this._event);
-},
-
-
-
-
-
-getUserObject:function(key)
-{
-if(key==="TimelineUIUtils::preview-element")
-return this._event.previewElement;
-throw new Error("Unexpected key: "+key);
-},
-
-
-
-
-
-setUserObject:function(key,value)
-{
-if(key!=="TimelineUIUtils::preview-element")
-throw new Error("Unexpected key: "+key);
-this._event.previewElement=value;
-},
-
-
-
-
-traceEvent:function()
-{
-return this._event;
-},
-
-
-
-
-_addChild:function(child)
-{
-this._children.push(child);
-child.parent=this;
-}};
-
-
-
-WebInspector.TimelineModel.MetadataEvents;
-
-
-
-
-WebInspector.TimelineModel._eventType=function(event)
-{
-if(event.hasCategory(WebInspector.TimelineModel.Category.Console))
-return WebInspector.TimelineModel.RecordType.ConsoleTime;
-if(event.hasCategory(WebInspector.TimelineModel.Category.UserTiming))
-return WebInspector.TimelineModel.RecordType.UserTiming;
-if(event.hasCategory(WebInspector.TimelineModel.Category.LatencyInfo))
-return WebInspector.TimelineModel.RecordType.LatencyInfo;
-return event.name;
-};
-
-WebInspector.TimelineModel.prototype={
-
-
-
-
-
-
-forAllRecords:function(preOrderCallback,postOrderCallback)
-{
-
-
-
-
-
-function processRecords(records,depth)
-{
-for(var i=0;i<records.length;++i){
-var record=records[i];
-if(preOrderCallback&&preOrderCallback(record,depth))
-return true;
-if(processRecords(record.children(),depth+1))
-return true;
-if(postOrderCallback&&postOrderCallback(record,depth))
-return true;
-}
-return false;
-}
-return processRecords(this._records,0);
-},
-
-
-
-
-
-forAllFilteredRecords:function(filters,callback)
-{
-
-
-
-
-
-
-function processRecord(record,depth)
-{
-var visible=WebInspector.TimelineModel.isVisible(filters,record.traceEvent());
-if(visible&&callback(record,depth))
-return true;
-
-for(var i=0;i<record.children().length;++i){
-if(processRecord.call(this,record.children()[i],visible?depth+1:depth))
-return true;
-}
-return false;
-}
-
-for(var i=0;i<this._records.length;++i)
-processRecord.call(this,this._records[i],0);
-},
-
-
-
-
-records:function()
-{
-return this._records;
-},
-
-
-
-
-cpuProfiles:function()
-{
-return this._cpuProfiles;
-},
-
-
-
-
-sessionId:function()
-{
-return this._sessionId;
-},
-
-
-
-
-
-targetByEvent:function(event)
-{
-
-var workerId=this._workerIdByThread.get(event.thread);
-var mainTarget=WebInspector.targetManager.mainTarget();
-return workerId?mainTarget.workerManager.targetByWorkerId(workerId):mainTarget;
-},
-
-
-
-
-
-setEvents:function(tracingModel,produceTraceStartedInPage)
-{
-this.reset();
-this._resetProcessingState();
-
-this._minimumRecordTime=tracingModel.minimumRecordTime();
-this._maximumRecordTime=tracingModel.maximumRecordTime();
-
-var metadataEvents=this._processMetadataEvents(tracingModel,!!produceTraceStartedInPage);
-if(Runtime.experiments.isEnabled("timelineShowAllProcesses")){
-var lastPageMetaEvent=metadataEvents.page.peekLast();
-for(var process of tracingModel.sortedProcesses()){
-for(var thread of process.sortedThreads())
-this._processThreadEvents(0,Infinity,thread,thread===lastPageMetaEvent.thread);
-}
-}else{
-var startTime=0;
-for(var i=0,length=metadataEvents.page.length;i<length;i++){
-var metaEvent=metadataEvents.page[i];
-var process=metaEvent.thread.process();
-var endTime=i+1<length?metadataEvents.page[i+1].startTime:Infinity;
-this._currentPage=metaEvent.args["data"]&&metaEvent.args["data"]["page"];
-for(var thread of process.sortedThreads()){
-if(thread.name()===WebInspector.TimelineModel.WorkerThreadName){
-var workerMetaEvent=metadataEvents.workers.find(e=>e.args["data"]["workerThreadId"]===thread.id());
-if(!workerMetaEvent)
-continue;
-var workerId=workerMetaEvent.args["data"]["workerId"];
-if(workerId)
-this._workerIdByThread.set(thread,workerId);
-}
-this._processThreadEvents(startTime,endTime,thread,thread===metaEvent.thread);
-}
-startTime=endTime;
-}
-}
-this._inspectedTargetEvents.sort(WebInspector.TracingModel.Event.compareStartTime);
-
-this._processBrowserEvents(tracingModel);
-this._buildTimelineRecords();
-this._buildGPUEvents(tracingModel);
-this._insertFirstPaintEvent();
-this._resetProcessingState();
-},
-
-
-
-
-
-
-_processMetadataEvents:function(tracingModel,produceTraceStartedInPage)
-{
-var metadataEvents=tracingModel.devToolsMetadataEvents();
-
-var pageDevToolsMetadataEvents=[];
-var workersDevToolsMetadataEvents=[];
-for(var event of metadataEvents){
-if(event.name===WebInspector.TimelineModel.DevToolsMetadataEvent.TracingStartedInPage){
-pageDevToolsMetadataEvents.push(event);
-}else if(event.name===WebInspector.TimelineModel.DevToolsMetadataEvent.TracingSessionIdForWorker){
-workersDevToolsMetadataEvents.push(event);
-}else if(event.name===WebInspector.TimelineModel.DevToolsMetadataEvent.TracingStartedInBrowser){
-console.assert(!this._mainFrameNodeId,"Multiple sessions in trace");
-this._mainFrameNodeId=event.args["frameTreeNodeId"];
-}
-}
-if(!pageDevToolsMetadataEvents.length){
-
-var pageMetaEvent=produceTraceStartedInPage?this._makeMockPageMetadataEvent(tracingModel):null;
-if(!pageMetaEvent){
-console.error(WebInspector.TimelineModel.DevToolsMetadataEvent.TracingStartedInPage+" event not found.");
-return{page:[],workers:[]};
-}
-pageDevToolsMetadataEvents.push(pageMetaEvent);
-}
-var sessionId=pageDevToolsMetadataEvents[0].args["sessionId"]||pageDevToolsMetadataEvents[0].args["data"]["sessionId"];
-this._sessionId=sessionId;
-
-var mismatchingIds=new Set();
-
-
-
-
-function checkSessionId(event)
-{
-var args=event.args;
-
-if(args["data"])
-args=args["data"];
-var id=args["sessionId"];
-if(id===sessionId)
-return true;
-mismatchingIds.add(id);
-return false;
-}
-var result={
-page:pageDevToolsMetadataEvents.filter(checkSessionId).sort(WebInspector.TracingModel.Event.compareStartTime),
-workers:workersDevToolsMetadataEvents.filter(checkSessionId).sort(WebInspector.TracingModel.Event.compareStartTime)};
-
-if(mismatchingIds.size)
-WebInspector.console.error("Timeline recording was started in more than one page simultaneously. Session id mismatch: "+this._sessionId+" and "+mismatchingIds.valuesArray()+".");
-return result;
-},
-
-
-
-
-
-_makeMockPageMetadataEvent:function(tracingModel)
-{
-var rendererMainThreadName=WebInspector.TimelineModel.RendererMainThreadName;
-
-var process=tracingModel.sortedProcesses().filter(function(p){return p.threadByName(rendererMainThreadName);})[0];
-var thread=process&&process.threadByName(rendererMainThreadName);
-if(!thread)
-return null;
-var pageMetaEvent=new WebInspector.TracingModel.Event(
-WebInspector.TracingModel.DevToolsMetadataEventCategory,
-WebInspector.TimelineModel.DevToolsMetadataEvent.TracingStartedInPage,
-WebInspector.TracingModel.Phase.Metadata,
-tracingModel.minimumRecordTime(),thread);
-pageMetaEvent.addArgs({"data":{"sessionId":"mockSessionId"}});
-return pageMetaEvent;
-},
-
-_insertFirstPaintEvent:function()
-{
-if(!this._firstCompositeLayers)
-return;
-
-
-var recordTypes=WebInspector.TimelineModel.RecordType;
-var i=this._inspectedTargetEvents.lowerBound(this._firstCompositeLayers,WebInspector.TracingModel.Event.compareStartTime);
-for(;i<this._inspectedTargetEvents.length&&this._inspectedTargetEvents[i].name!==recordTypes.DrawFrame;++i){}
-if(i>=this._inspectedTargetEvents.length)
-return;
-var drawFrameEvent=this._inspectedTargetEvents[i];
-var firstPaintEvent=new WebInspector.TracingModel.Event(drawFrameEvent.categoriesString,recordTypes.MarkFirstPaint,WebInspector.TracingModel.Phase.Instant,drawFrameEvent.startTime,drawFrameEvent.thread);
-this._mainThreadEvents.splice(this._mainThreadEvents.lowerBound(firstPaintEvent,WebInspector.TracingModel.Event.compareStartTime),0,firstPaintEvent);
-var firstPaintRecord=new WebInspector.TimelineModel.Record(firstPaintEvent);
-this._eventDividerRecords.splice(this._eventDividerRecords.lowerBound(firstPaintRecord,WebInspector.TimelineModel.Record._compareStartTime),0,firstPaintRecord);
-},
-
-
-
-
-_processBrowserEvents:function(tracingModel)
-{
-var browserMain=WebInspector.TracingModel.browserMainThread(tracingModel);
-if(!browserMain)
-return;
-
-
-browserMain.events().forEach(this._processBrowserEvent,this);
-
-var asyncEventsByGroup=new Map();
-this._processAsyncEvents(asyncEventsByGroup,browserMain.asyncEvents());
-this._mergeAsyncEvents(this._mainThreadAsyncEventsByGroup,asyncEventsByGroup);
-},
-
-_buildTimelineRecords:function()
-{
-var topLevelRecords=this._buildTimelineRecordsForThread(this.mainThreadEvents());
-for(var i=0;i<topLevelRecords.length;i++){
-var record=topLevelRecords[i];
-if(WebInspector.TracingModel.isTopLevelEvent(record.traceEvent()))
-this._mainThreadTasks.push(record);
-}
-
-
-
-
-
-function processVirtualThreadEvents(virtualThread)
-{
-var threadRecords=this._buildTimelineRecordsForThread(virtualThread.events);
-topLevelRecords=topLevelRecords.mergeOrdered(threadRecords,WebInspector.TimelineModel.Record._compareStartTime);
-}
-this.virtualThreads().forEach(processVirtualThreadEvents.bind(this));
-this._records=topLevelRecords;
-},
-
-
-
-
-_buildGPUEvents:function(tracingModel)
-{
-var thread=tracingModel.threadByName("GPU Process","CrGpuMain");
-if(!thread)
-return;
-var gpuEventName=WebInspector.TimelineModel.RecordType.GPUTask;
-this._gpuEvents=thread.events().filter(event=>event.name===gpuEventName);
-},
-
-
-
-
-
-_buildTimelineRecordsForThread:function(threadEvents)
-{
-var recordStack=[];
-var topLevelRecords=[];
-
-for(var i=0,size=threadEvents.length;i<size;++i){
-var event=threadEvents[i];
-for(var top=recordStack.peekLast();top&&top._event.endTime<=event.startTime;top=recordStack.peekLast())
-recordStack.pop();
-if(event.phase===WebInspector.TracingModel.Phase.AsyncEnd||event.phase===WebInspector.TracingModel.Phase.NestableAsyncEnd)
-continue;
-var parentRecord=recordStack.peekLast();
-
-if(WebInspector.TracingModel.isAsyncBeginPhase(event.phase)&&parentRecord&&event.endTime>parentRecord._event.endTime)
-continue;
-var record=new WebInspector.TimelineModel.Record(event);
-if(WebInspector.TimelineModel.isMarkerEvent(event))
-this._eventDividerRecords.push(record);
-if(!this._eventFilter.accept(event)&&!WebInspector.TracingModel.isTopLevelEvent(event))
-continue;
-if(parentRecord)
-parentRecord._addChild(record);else
-
-topLevelRecords.push(record);
-if(event.endTime)
-recordStack.push(record);
-}
-
-return topLevelRecords;
-},
-
-_resetProcessingState:function()
-{
-this._asyncEventTracker=new WebInspector.TimelineAsyncEventTracker();
-this._invalidationTracker=new WebInspector.InvalidationTracker();
-this._layoutInvalidate={};
-this._lastScheduleStyleRecalculation={};
-this._paintImageEventByPixelRefId={};
-this._lastPaintForLayer={};
-this._lastRecalculateStylesEvent=null;
-this._currentScriptEvent=null;
-this._eventStack=[];
-this._hadCommitLoad=false;
-this._firstCompositeLayers=null;
-
-this._knownInputEvents=new Set();
-this._currentPage=null;
-},
-
-
-
-
-
-
-
-_processThreadEvents:function(startTime,endTime,thread,isMainThread)
-{
-var events=thread.events();
-var asyncEvents=thread.asyncEvents();
-
-var jsSamples;
-if(Runtime.experiments.isEnabled("timelineTracingJSProfile")){
-jsSamples=WebInspector.TimelineJSProfileProcessor.processRawV8Samples(events);
-}else{
-var cpuProfileEvent=events.peekLast();
-if(cpuProfileEvent&&cpuProfileEvent.name===WebInspector.TimelineModel.RecordType.CpuProfile){
-var cpuProfile=cpuProfileEvent.args["data"]["cpuProfile"];
-if(cpuProfile){
-var jsProfileModel=new WebInspector.CPUProfileDataModel(cpuProfile);
-this._cpuProfiles.push(jsProfileModel);
-jsSamples=WebInspector.TimelineJSProfileProcessor.generateTracingEventsFromCpuProfile(jsProfileModel,thread);
-}
-}
-}
-
-if(jsSamples&&jsSamples.length)
-events=events.mergeOrdered(jsSamples,WebInspector.TracingModel.Event.orderedCompareStartTime);
-if(jsSamples||events.some(function(e){return e.name===WebInspector.TimelineModel.RecordType.JSSample;})){
-var jsFrameEvents=WebInspector.TimelineJSProfileProcessor.generateJSFrameEvents(events);
-if(jsFrameEvents&&jsFrameEvents.length)
-events=jsFrameEvents.mergeOrdered(events,WebInspector.TracingModel.Event.orderedCompareStartTime);
-}
-
-var threadEvents;
-var threadAsyncEventsByGroup;
-if(isMainThread){
-threadEvents=this._mainThreadEvents;
-threadAsyncEventsByGroup=this._mainThreadAsyncEventsByGroup;
-}else{
-var virtualThread=new WebInspector.TimelineModel.VirtualThread(thread.name());
-this._virtualThreads.push(virtualThread);
-threadEvents=virtualThread.events;
-threadAsyncEventsByGroup=virtualThread.asyncEventsByGroup;
-}
-
-this._eventStack=[];
-var i=events.lowerBound(startTime,function(time,event){return time-event.startTime;});
-var length=events.length;
-for(;i<length;i++){
-var event=events[i];
-if(endTime&&event.startTime>=endTime)
-break;
-if(!this._processEvent(event))
-continue;
-threadEvents.push(event);
-this._inspectedTargetEvents.push(event);
-}
-this._processAsyncEvents(threadAsyncEventsByGroup,asyncEvents,startTime,endTime);
-
-if(thread.name()==="Compositor"){
-this._mergeAsyncEvents(this._mainThreadAsyncEventsByGroup,threadAsyncEventsByGroup);
-threadAsyncEventsByGroup.clear();
-}
-},
-
-
-
-
-
-
-
-_processAsyncEvents:function(asyncEventsByGroup,asyncEvents,startTime,endTime)
-{
-var i=startTime?asyncEvents.lowerBound(startTime,function(time,asyncEvent){return time-asyncEvent.startTime;}):0;
-for(;i<asyncEvents.length;++i){
-var asyncEvent=asyncEvents[i];
-if(endTime&&asyncEvent.startTime>=endTime)
-break;
-var asyncGroup=this._processAsyncEvent(asyncEvent);
-if(!asyncGroup)
-continue;
-var groupAsyncEvents=asyncEventsByGroup.get(asyncGroup);
-if(!groupAsyncEvents){
-groupAsyncEvents=[];
-asyncEventsByGroup.set(asyncGroup,groupAsyncEvents);
-}
-groupAsyncEvents.push(asyncEvent);
-}
-},
-
-
-
-
-
-_processEvent:function(event)
-{
-var eventStack=this._eventStack;
-while(eventStack.length&&eventStack.peekLast().endTime<=event.startTime)
-eventStack.pop();
-
-var recordTypes=WebInspector.TimelineModel.RecordType;
-
-if(this._currentScriptEvent&&event.startTime>this._currentScriptEvent.endTime)
-this._currentScriptEvent=null;
-
-var eventData=event.args["data"]||event.args["beginData"]||{};
-if(eventData["stackTrace"])
-event.stackTrace=eventData["stackTrace"];
-if(event.stackTrace&&event.name!==recordTypes.JSSample){
-
-
-for(var i=0;i<event.stackTrace.length;++i){
---event.stackTrace[i].lineNumber;
---event.stackTrace[i].columnNumber;
-}
-}
-
-if(eventStack.length&&eventStack.peekLast().name===recordTypes.EventDispatch)
-eventStack.peekLast().hasChildren=true;
-this._asyncEventTracker.processEvent(event);
-if(event.initiator&&event.initiator.url)
-event.url=event.initiator.url;
-switch(event.name){
-case recordTypes.ResourceSendRequest:
-case recordTypes.WebSocketCreate:
-event.url=eventData["url"];
-event.initiator=eventStack.peekLast()||null;
-break;
-
-case recordTypes.ScheduleStyleRecalculation:
-this._lastScheduleStyleRecalculation[eventData["frame"]]=event;
-break;
-
-case recordTypes.UpdateLayoutTree:
-case recordTypes.RecalculateStyles:
-this._invalidationTracker.didRecalcStyle(event);
-if(event.args["beginData"])
-event.initiator=this._lastScheduleStyleRecalculation[event.args["beginData"]["frame"]];
-this._lastRecalculateStylesEvent=event;
-if(this._currentScriptEvent)
-event.warning=WebInspector.TimelineModel.WarningType.ForcedStyle;
-break;
-
-case recordTypes.ScheduleStyleInvalidationTracking:
-case recordTypes.StyleRecalcInvalidationTracking:
-case recordTypes.StyleInvalidatorInvalidationTracking:
-case recordTypes.LayoutInvalidationTracking:
-case recordTypes.LayerInvalidationTracking:
-case recordTypes.PaintInvalidationTracking:
-case recordTypes.ScrollInvalidationTracking:
-this._invalidationTracker.addInvalidation(new WebInspector.InvalidationTrackingEvent(event));
-break;
-
-case recordTypes.InvalidateLayout:
-
-
-var layoutInitator=event;
-var frameId=eventData["frame"];
-if(!this._layoutInvalidate[frameId]&&this._lastRecalculateStylesEvent&&this._lastRecalculateStylesEvent.endTime>event.startTime)
-layoutInitator=this._lastRecalculateStylesEvent.initiator;
-this._layoutInvalidate[frameId]=layoutInitator;
-break;
-
-case recordTypes.Layout:
-this._invalidationTracker.didLayout(event);
-var frameId=event.args["beginData"]["frame"];
-event.initiator=this._layoutInvalidate[frameId];
-
-if(event.args["endData"]){
-event.backendNodeId=event.args["endData"]["rootNode"];
-event.highlightQuad=event.args["endData"]["root"];
-}
-this._layoutInvalidate[frameId]=null;
-if(this._currentScriptEvent)
-event.warning=WebInspector.TimelineModel.WarningType.ForcedLayout;
-break;
-
-case recordTypes.FunctionCall:
-
-if(typeof eventData["scriptName"]==="string")
-eventData["url"]=eventData["scriptName"];
-if(typeof eventData["scriptLine"]==="number")
-eventData["lineNumber"]=eventData["scriptLine"];
-
-case recordTypes.EvaluateScript:
-case recordTypes.CompileScript:
-if(typeof eventData["lineNumber"]==="number")
---eventData["lineNumber"];
-if(typeof eventData["columnNumber"]==="number")
---eventData["columnNumber"];
-if(!this._currentScriptEvent)
-this._currentScriptEvent=event;
-break;
-
-case recordTypes.SetLayerTreeId:
-this._inspectedTargetLayerTreeId=event.args["layerTreeId"]||event.args["data"]["layerTreeId"];
-break;
-
-case recordTypes.Paint:
-this._invalidationTracker.didPaint(event);
-event.highlightQuad=eventData["clip"];
-event.backendNodeId=eventData["nodeId"];
-
-if(!eventData["layerId"])
-break;
-var layerId=eventData["layerId"];
-this._lastPaintForLayer[layerId]=event;
-break;
-
-case recordTypes.DisplayItemListSnapshot:
-case recordTypes.PictureSnapshot:
-var layerUpdateEvent=this._findAncestorEvent(recordTypes.UpdateLayer);
-if(!layerUpdateEvent||layerUpdateEvent.args["layerTreeId"]!==this._inspectedTargetLayerTreeId)
-break;
-var paintEvent=this._lastPaintForLayer[layerUpdateEvent.args["layerId"]];
-if(paintEvent)
-paintEvent.picture=event;
-break;
-
-case recordTypes.ScrollLayer:
-event.backendNodeId=eventData["nodeId"];
-break;
-
-case recordTypes.PaintImage:
-event.backendNodeId=eventData["nodeId"];
-event.url=eventData["url"];
-break;
-
-case recordTypes.DecodeImage:
-case recordTypes.ResizeImage:
-var paintImageEvent=this._findAncestorEvent(recordTypes.PaintImage);
-if(!paintImageEvent){
-var decodeLazyPixelRefEvent=this._findAncestorEvent(recordTypes.DecodeLazyPixelRef);
-paintImageEvent=decodeLazyPixelRefEvent&&this._paintImageEventByPixelRefId[decodeLazyPixelRefEvent.args["LazyPixelRef"]];
-}
-if(!paintImageEvent)
-break;
-event.backendNodeId=paintImageEvent.backendNodeId;
-event.url=paintImageEvent.url;
-break;
-
-case recordTypes.DrawLazyPixelRef:
-var paintImageEvent=this._findAncestorEvent(recordTypes.PaintImage);
-if(!paintImageEvent)
-break;
-this._paintImageEventByPixelRefId[event.args["LazyPixelRef"]]=paintImageEvent;
-event.backendNodeId=paintImageEvent.backendNodeId;
-event.url=paintImageEvent.url;
-break;
-
-case recordTypes.MarkDOMContent:
-case recordTypes.MarkLoad:
-var page=eventData["page"];
-if(page&&page!==this._currentPage)
-return false;
-break;
-
-case recordTypes.CommitLoad:
-var page=eventData["page"];
-if(page&&page!==this._currentPage)
-return false;
-if(!eventData["isMainFrame"])
-break;
-this._hadCommitLoad=true;
-this._firstCompositeLayers=null;
-break;
-
-case recordTypes.CompositeLayers:
-if(!this._firstCompositeLayers&&this._hadCommitLoad)
-this._firstCompositeLayers=event;
-break;
-
-case recordTypes.FireIdleCallback:
-if(event.duration>eventData["allottedMilliseconds"]){
-event.warning=WebInspector.TimelineModel.WarningType.IdleDeadlineExceeded;
-}
-break;}
-
-if(WebInspector.TracingModel.isAsyncPhase(event.phase))
-return true;
-var duration=event.duration;
-if(!duration)
-return true;
-if(eventStack.length){
-var parent=eventStack.peekLast();
-parent.selfTime-=duration;
-if(parent.selfTime<0){
-var epsilon=1e-3;
-if(parent.selfTime<-epsilon)
-console.error("Children are longer than parent at "+event.startTime+" ("+(event.startTime-this.minimumRecordTime()).toFixed(3)+") by "+parent.selfTime.toFixed(3));
-parent.selfTime=0;
-}
-}
-event.selfTime=duration;
-eventStack.push(event);
-return true;
-},
-
-
-
-
-_processBrowserEvent:function(event)
-{
-if(event.name!==WebInspector.TimelineModel.RecordType.LatencyInfoFlow)
-return;
-var frameId=event.args["frameTreeNodeId"];
-if(typeof frameId==="number"&&frameId===this._mainFrameNodeId)
-this._knownInputEvents.add(event.bind_id);
-},
-
-
-
-
-
-_processAsyncEvent:function(asyncEvent)
-{
-var groups=WebInspector.TimelineModel.AsyncEventGroup;
-if(asyncEvent.hasCategory(WebInspector.TimelineModel.Category.Console))
-return groups.console;
-if(asyncEvent.hasCategory(WebInspector.TimelineModel.Category.UserTiming))
-return groups.userTiming;
-if(asyncEvent.name===WebInspector.TimelineModel.RecordType.Animation)
-return groups.animation;
-if(asyncEvent.hasCategory(WebInspector.TimelineModel.Category.LatencyInfo)||asyncEvent.name===WebInspector.TimelineModel.RecordType.ImplSideFling){
-var lastStep=asyncEvent.steps.peekLast();
-
-if(lastStep.phase!==WebInspector.TracingModel.Phase.AsyncEnd)
-return null;
-var data=lastStep.args["data"];
-asyncEvent.causedFrame=!!(data&&data["INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT"]);
-if(asyncEvent.hasCategory(WebInspector.TimelineModel.Category.LatencyInfo)){
-if(!this._knownInputEvents.has(lastStep.id))
-return null;
-if(asyncEvent.name===WebInspector.TimelineModel.RecordType.InputLatencyMouseMove&&!asyncEvent.causedFrame)
-return null;
-var rendererMain=data["INPUT_EVENT_LATENCY_RENDERER_MAIN_COMPONENT"];
-if(rendererMain){
-var time=rendererMain["time"]/1000;
-asyncEvent.steps[0].timeWaitingForMainThread=time-asyncEvent.steps[0].startTime;
-}
-}
-return groups.input;
-}
-return null;
-},
-
-
-
-
-
-_findAncestorEvent:function(name)
-{
-for(var i=this._eventStack.length-1;i>=0;--i){
-var event=this._eventStack[i];
-if(event.name===name)
-return event;
-}
-return null;
-},
-
-
-
-
-
-_mergeAsyncEvents:function(target,source)
-{
-for(var group of source.keys()){
-var events=target.get(group)||[];
-events=events.mergeOrdered(source.get(group)||[],WebInspector.TracingModel.Event.compareStartAndEndTime);
-target.set(group,events);
-}
-},
-
-reset:function()
-{
-this._virtualThreads=[];
-
-this._mainThreadEvents=[];
-
-this._mainThreadAsyncEventsByGroup=new Map();
-
-this._inspectedTargetEvents=[];
-
-this._records=[];
-
-this._mainThreadTasks=[];
-
-this._gpuEvents=[];
-
-this._eventDividerRecords=[];
-
-this._sessionId=null;
-
-this._mainFrameNodeId=null;
-
-this._cpuProfiles=[];
-
-this._workerIdByThread=new WeakMap();
-this._minimumRecordTime=0;
-this._maximumRecordTime=0;
-},
-
-
-
-
-minimumRecordTime:function()
-{
-return this._minimumRecordTime;
-},
-
-
-
-
-maximumRecordTime:function()
-{
-return this._maximumRecordTime;
-},
-
-
-
-
-inspectedTargetEvents:function()
-{
-return this._inspectedTargetEvents;
-},
-
-
-
-
-mainThreadEvents:function()
-{
-return this._mainThreadEvents;
-},
-
-
-
-
-_setMainThreadEvents:function(events)
-{
-this._mainThreadEvents=events;
-},
-
-
-
-
-mainThreadAsyncEvents:function()
-{
-return this._mainThreadAsyncEventsByGroup;
-},
-
-
-
-
-virtualThreads:function()
-{
-return this._virtualThreads;
-},
-
-
-
-
-isEmpty:function()
-{
-return this.minimumRecordTime()===0&&this.maximumRecordTime()===0;
-},
-
-
-
-
-mainThreadTasks:function()
-{
-return this._mainThreadTasks;
-},
-
-
-
-
-gpuEvents:function()
-{
-return this._gpuEvents;
-},
-
-
-
-
-eventDividerRecords:function()
-{
-return this._eventDividerRecords;
-},
-
-
-
-
-networkRequests:function()
-{
-
-var requests=new Map();
-
-var requestsList=[];
-
-var zeroStartRequestsList=[];
-var types=WebInspector.TimelineModel.RecordType;
-var resourceTypes=new Set([
-types.ResourceSendRequest,
-types.ResourceReceiveResponse,
-types.ResourceReceivedData,
-types.ResourceFinish]);
-
-var events=this.mainThreadEvents();
-for(var i=0;i<events.length;++i){
-var e=events[i];
-if(!resourceTypes.has(e.name))
-continue;
-var id=e.args["data"]["requestId"];
-var request=requests.get(id);
-if(request){
-request.addEvent(e);
-}else{
-request=new WebInspector.TimelineModel.NetworkRequest(e);
-requests.set(id,request);
-if(request.startTime)
-requestsList.push(request);else
-
-zeroStartRequestsList.push(request);
-}
-}
-return zeroStartRequestsList.concat(requestsList);
-}};
-
-
-
-
-
-
-
-WebInspector.TimelineModel.isVisible=function(filters,event)
-{
-for(var i=0;i<filters.length;++i){
-if(!filters[i].accept(event))
-return false;
-}
-return true;
-};
-
-
-
-
-
-WebInspector.TimelineModel.isMarkerEvent=function(event)
-{
-var recordTypes=WebInspector.TimelineModel.RecordType;
-switch(event.name){
-case recordTypes.TimeStamp:
-case recordTypes.MarkFirstPaint:
-return true;
-case recordTypes.MarkDOMContent:
-case recordTypes.MarkLoad:
-return event.args["data"]["isMainFrame"];
-default:
-return false;}
-
-};
-
-
-
-
-
-WebInspector.TimelineModel.NetworkRequest=function(event)
-{
-this.startTime=event.name===WebInspector.TimelineModel.RecordType.ResourceSendRequest?event.startTime:0;
-this.endTime=Infinity;
-
-this.children=[];
-this.addEvent(event);
-};
-
-WebInspector.TimelineModel.NetworkRequest.prototype={
-
-
-
-addEvent:function(event)
-{
-this.children.push(event);
-var recordType=WebInspector.TimelineModel.RecordType;
-this.startTime=Math.min(this.startTime,event.startTime);
-var eventData=event.args["data"];
-if(eventData["mimeType"])
-this.mimeType=eventData["mimeType"];
-if("priority"in eventData)
-this.priority=eventData["priority"];
-if(event.name===recordType.ResourceFinish)
-this.endTime=event.startTime;
-if(!this.responseTime&&(event.name===recordType.ResourceReceiveResponse||event.name===recordType.ResourceReceivedData))
-this.responseTime=event.startTime;
-if(!this.url)
-this.url=eventData["url"];
-if(!this.requestMethod)
-this.requestMethod=eventData["requestMethod"];
-}};
-
-
-
-
-
-WebInspector.TimelineModel.Filter=function()
-{
-};
-
-WebInspector.TimelineModel.Filter.prototype={
-
-
-
-
-accept:function(event)
-{
-return true;
-}};
-
-
-
-
-
-
-
-WebInspector.TimelineVisibleEventsFilter=function(visibleTypes)
-{
-WebInspector.TimelineModel.Filter.call(this);
-this._visibleTypes=new Set(visibleTypes);
-};
-
-WebInspector.TimelineVisibleEventsFilter.prototype={
-
-
-
-
-
-accept:function(event)
-{
-return this._visibleTypes.has(WebInspector.TimelineModel._eventType(event));
-},
-
-__proto__:WebInspector.TimelineModel.Filter.prototype};
-
-
-
-
-
-
-
-WebInspector.ExclusiveNameFilter=function(excludeNames)
-{
-WebInspector.TimelineModel.Filter.call(this);
-this._excludeNames=new Set(excludeNames);
-};
-
-WebInspector.ExclusiveNameFilter.prototype={
-
-
-
-
-
-accept:function(event)
-{
-return!this._excludeNames.has(event.name);
-},
-
-__proto__:WebInspector.TimelineModel.Filter.prototype};
-
-
-
-
-
-
-WebInspector.ExcludeTopLevelFilter=function()
-{
-WebInspector.TimelineModel.Filter.call(this);
-};
-
-WebInspector.ExcludeTopLevelFilter.prototype={
-
-
-
-
-
-accept:function(event)
-{
-return!WebInspector.TracingModel.isTopLevelEvent(event);
-},
-
-__proto__:WebInspector.TimelineModel.Filter.prototype};
-
-
-
-
-
-
-WebInspector.InvalidationTrackingEvent=function(event)
-{
-
-this.type=event.name;
-
-this.startTime=event.startTime;
-
-this._tracingEvent=event;
-
-var eventData=event.args["data"];
-
-
-this.frame=eventData["frame"];
-
-this.nodeId=eventData["nodeId"];
-
-this.nodeName=eventData["nodeName"];
-
-this.paintId=eventData["paintId"];
-
-this.invalidationSet=eventData["invalidationSet"];
-
-this.invalidatedSelectorId=eventData["invalidatedSelectorId"];
-
-this.changedId=eventData["changedId"];
-
-this.changedClass=eventData["changedClass"];
-
-this.changedAttribute=eventData["changedAttribute"];
-
-this.changedPseudo=eventData["changedPseudo"];
-
-this.selectorPart=eventData["selectorPart"];
-
-this.extraData=eventData["extraData"];
-
-this.invalidationList=eventData["invalidationList"];
-
-this.cause={reason:eventData["reason"],stackTrace:eventData["stackTrace"]};
-
-
-if(!this.cause.reason&&this.cause.stackTrace&&this.type===WebInspector.TimelineModel.RecordType.LayoutInvalidationTracking)
-this.cause.reason="Layout forced";
-};
-
-
-WebInspector.InvalidationCause;
-
-
-
-
-WebInspector.InvalidationTracker=function()
-{
-this._initializePerFrameState();
-};
-
-WebInspector.InvalidationTracker.prototype={
-
-
-
-addInvalidation:function(invalidation)
-{
-this._startNewFrameIfNeeded();
-
-if(!invalidation.nodeId&&!invalidation.paintId){
-console.error("Invalidation lacks node information.");
-console.error(invalidation);
-return;
-}
-
-
-
-
-var recordTypes=WebInspector.TimelineModel.RecordType;
-if(invalidation.type===recordTypes.PaintInvalidationTracking&&invalidation.nodeId){
-var invalidations=this._invalidationsByNodeId[invalidation.nodeId]||[];
-for(var i=0;i<invalidations.length;++i)
-invalidations[i].paintId=invalidation.paintId;
-
-
-return;
-}
-
-
-
-
-if(invalidation.type===recordTypes.StyleRecalcInvalidationTracking&&invalidation.cause.reason==="StyleInvalidator")
-return;
-
-
-
-
-var styleRecalcInvalidation=invalidation.type===recordTypes.ScheduleStyleInvalidationTracking||
-invalidation.type===recordTypes.StyleInvalidatorInvalidationTracking||
-invalidation.type===recordTypes.StyleRecalcInvalidationTracking;
-if(styleRecalcInvalidation){
-var duringRecalcStyle=invalidation.startTime&&this._lastRecalcStyle&&
-invalidation.startTime>=this._lastRecalcStyle.startTime&&
-invalidation.startTime<=this._lastRecalcStyle.endTime;
-if(duringRecalcStyle)
-this._associateWithLastRecalcStyleEvent(invalidation);
-}
-
-
-if(this._invalidations[invalidation.type])
-this._invalidations[invalidation.type].push(invalidation);else
-
-this._invalidations[invalidation.type]=[invalidation];
-if(invalidation.nodeId){
-if(this._invalidationsByNodeId[invalidation.nodeId])
-this._invalidationsByNodeId[invalidation.nodeId].push(invalidation);else
-
-this._invalidationsByNodeId[invalidation.nodeId]=[invalidation];
-}
-},
-
-
-
-
-didRecalcStyle:function(recalcStyleEvent)
-{
-this._lastRecalcStyle=recalcStyleEvent;
-var types=[WebInspector.TimelineModel.RecordType.ScheduleStyleInvalidationTracking,
-WebInspector.TimelineModel.RecordType.StyleInvalidatorInvalidationTracking,
-WebInspector.TimelineModel.RecordType.StyleRecalcInvalidationTracking];
-for(var invalidation of this._invalidationsOfTypes(types))
-this._associateWithLastRecalcStyleEvent(invalidation);
-},
-
-
-
-
-_associateWithLastRecalcStyleEvent:function(invalidation)
-{
-if(invalidation.linkedRecalcStyleEvent)
-return;
-
-var recordTypes=WebInspector.TimelineModel.RecordType;
-var recalcStyleFrameId=this._lastRecalcStyle.args["beginData"]["frame"];
-if(invalidation.type===recordTypes.StyleInvalidatorInvalidationTracking){
-
-
-this._addSyntheticStyleRecalcInvalidations(this._lastRecalcStyle,recalcStyleFrameId,invalidation);
-}else if(invalidation.type===recordTypes.ScheduleStyleInvalidationTracking){
-
-
-}else{
-this._addInvalidationToEvent(this._lastRecalcStyle,recalcStyleFrameId,invalidation);
-}
-
-invalidation.linkedRecalcStyleEvent=true;
-},
-
-
-
-
-
-
-_addSyntheticStyleRecalcInvalidations:function(event,frameId,styleInvalidatorInvalidation)
-{
-if(!styleInvalidatorInvalidation.invalidationList){
-this._addSyntheticStyleRecalcInvalidation(styleInvalidatorInvalidation._tracingEvent,styleInvalidatorInvalidation);
-return;
-}
-if(!styleInvalidatorInvalidation.nodeId){
-console.error("Invalidation lacks node information.");
-console.error(invalidation);
-return;
-}
-for(var i=0;i<styleInvalidatorInvalidation.invalidationList.length;i++){
-var setId=styleInvalidatorInvalidation.invalidationList[i]["id"];
-var lastScheduleStyleRecalculation;
-var nodeInvalidations=this._invalidationsByNodeId[styleInvalidatorInvalidation.nodeId]||[];
-for(var j=0;j<nodeInvalidations.length;j++){
-var invalidation=nodeInvalidations[j];
-if(invalidation.frame!==frameId||invalidation.invalidationSet!==setId||invalidation.type!==WebInspector.TimelineModel.RecordType.ScheduleStyleInvalidationTracking)
-continue;
-lastScheduleStyleRecalculation=invalidation;
-}
-if(!lastScheduleStyleRecalculation){
-console.error("Failed to lookup the event that scheduled a style invalidator invalidation.");
-continue;
-}
-this._addSyntheticStyleRecalcInvalidation(lastScheduleStyleRecalculation._tracingEvent,styleInvalidatorInvalidation);
-}
-},
-
-
-
-
-
-_addSyntheticStyleRecalcInvalidation:function(baseEvent,styleInvalidatorInvalidation)
-{
-var invalidation=new WebInspector.InvalidationTrackingEvent(baseEvent);
-invalidation.type=WebInspector.TimelineModel.RecordType.StyleRecalcInvalidationTracking;
-invalidation.synthetic=true;
-if(styleInvalidatorInvalidation.cause.reason)
-invalidation.cause.reason=styleInvalidatorInvalidation.cause.reason;
-if(styleInvalidatorInvalidation.selectorPart)
-invalidation.selectorPart=styleInvalidatorInvalidation.selectorPart;
-
-this.addInvalidation(invalidation);
-if(!invalidation.linkedRecalcStyleEvent)
-this._associateWithLastRecalcStyleEvent(invalidation);
-},
-
-
-
-
-didLayout:function(layoutEvent)
-{
-var layoutFrameId=layoutEvent.args["beginData"]["frame"];
-for(var invalidation of this._invalidationsOfTypes([WebInspector.TimelineModel.RecordType.LayoutInvalidationTracking])){
-if(invalidation.linkedLayoutEvent)
-continue;
-this._addInvalidationToEvent(layoutEvent,layoutFrameId,invalidation);
-invalidation.linkedLayoutEvent=true;
-}
-},
-
-
-
-
-didPaint:function(paintEvent)
-{
-this._didPaint=true;
-
-
-
-var layerId=paintEvent.args["data"]["layerId"];
-if(layerId)
-this._lastPaintWithLayer=paintEvent;
-
-
-if(!this._lastPaintWithLayer)
-return;
-
-var effectivePaintId=this._lastPaintWithLayer.args["data"]["nodeId"];
-var paintFrameId=paintEvent.args["data"]["frame"];
-var types=[WebInspector.TimelineModel.RecordType.StyleRecalcInvalidationTracking,
-WebInspector.TimelineModel.RecordType.LayoutInvalidationTracking,
-WebInspector.TimelineModel.RecordType.PaintInvalidationTracking,
-WebInspector.TimelineModel.RecordType.ScrollInvalidationTracking];
-for(var invalidation of this._invalidationsOfTypes(types)){
-if(invalidation.paintId===effectivePaintId)
-this._addInvalidationToEvent(paintEvent,paintFrameId,invalidation);
-}
-},
-
-
-
-
-
-
-_addInvalidationToEvent:function(event,eventFrameId,invalidation)
-{
-if(eventFrameId!==invalidation.frame)
-return;
-if(!event.invalidationTrackingEvents)
-event.invalidationTrackingEvents=[invalidation];else
-
-event.invalidationTrackingEvents.push(invalidation);
-},
-
-
-
-
-
-_invalidationsOfTypes:function(types)
-{
-var invalidations=this._invalidations;
-if(!types)
-types=Object.keys(invalidations);
-function*generator()
-{
-for(var i=0;i<types.length;++i){
-var invalidationList=invalidations[types[i]]||[];
-for(var j=0;j<invalidationList.length;++j)
-yield invalidationList[j];
-}
-}
-return generator();
-},
-
-_startNewFrameIfNeeded:function()
-{
-if(!this._didPaint)
-return;
-
-this._initializePerFrameState();
-},
-
-_initializePerFrameState:function()
-{
-
-this._invalidations={};
-
-this._invalidationsByNodeId={};
-
-this._lastRecalcStyle=undefined;
-this._lastPaintWithLayer=undefined;
-this._didPaint=false;
-}};
-
-
-
-
-
-WebInspector.TimelineAsyncEventTracker=function()
-{
-WebInspector.TimelineAsyncEventTracker._initialize();
-
-this._initiatorByType=new Map();
-for(var initiator of WebInspector.TimelineAsyncEventTracker._asyncEvents.keys())
-this._initiatorByType.set(initiator,new Map());
-};
-
-WebInspector.TimelineAsyncEventTracker._initialize=function()
-{
-if(WebInspector.TimelineAsyncEventTracker._asyncEvents)
-return;
-var events=new Map();
-var type=WebInspector.TimelineModel.RecordType;
-
-events.set(type.TimerInstall,{causes:[type.TimerFire],joinBy:"timerId"});
-events.set(type.ResourceSendRequest,{causes:[type.ResourceReceiveResponse,type.ResourceReceivedData,type.ResourceFinish],joinBy:"requestId"});
-events.set(type.RequestAnimationFrame,{causes:[type.FireAnimationFrame],joinBy:"id"});
-events.set(type.RequestIdleCallback,{causes:[type.FireIdleCallback],joinBy:"id"});
-events.set(type.WebSocketCreate,{causes:[type.WebSocketSendHandshakeRequest,type.WebSocketReceiveHandshakeResponse,type.WebSocketDestroy],joinBy:"identifier"});
-
-WebInspector.TimelineAsyncEventTracker._asyncEvents=events;
-
-WebInspector.TimelineAsyncEventTracker._typeToInitiator=new Map();
-for(var entry of events){
-var types=entry[1].causes;
-for(type of types)
-WebInspector.TimelineAsyncEventTracker._typeToInitiator.set(type,entry[0]);
-}
-};
-
-WebInspector.TimelineAsyncEventTracker.prototype={
-
-
-
-processEvent:function(event)
-{
-var initiatorType=WebInspector.TimelineAsyncEventTracker._typeToInitiator.get(event.name);
-var isInitiator=!initiatorType;
-if(!initiatorType)
-initiatorType=event.name;
-var initiatorInfo=WebInspector.TimelineAsyncEventTracker._asyncEvents.get(initiatorType);
-if(!initiatorInfo)
-return;
-var id=event.args["data"][initiatorInfo.joinBy];
-if(!id)
-return;
-
-var initiatorMap=this._initiatorByType.get(initiatorType);
-if(isInitiator)
-initiatorMap.set(id,event);else
-
-event.initiator=initiatorMap.get(id)||null;
-}};
-
-
-},{}],131:[function(require,module,exports){
-
-
-
-
-WebInspector.TimelineProfileTree={};
-
-
-
-
-WebInspector.TimelineProfileTree.Node=function()
-{
-
-this.totalTime;
-
-this.selfTime;
-
-this.id;
-
-this.event;
-
-this.children;
-
-this.parent;
-this._isGroupNode=false;
-};
-
-WebInspector.TimelineProfileTree.Node.prototype={
-
-
-
-isGroupNode:function()
-{
-return this._isGroupNode;
-}};
-
-
-
-
-
-
-
-
-
-
-WebInspector.TimelineProfileTree.buildTopDown=function(events,filters,startTime,endTime,eventIdCallback)
-{
-
-var initialTime=1e7;
-var root=new WebInspector.TimelineProfileTree.Node();
-root.totalTime=initialTime;
-root.selfTime=initialTime;
-root.children=new Map();
-var parent=root;
-
-
-
-
-function onStartEvent(e)
-{
-if(!WebInspector.TimelineModel.isVisible(filters,e))
-return;
-var time=e.endTime?Math.min(endTime,e.endTime)-Math.max(startTime,e.startTime):0;
-var id=eventIdCallback?eventIdCallback(e):Symbol("uniqueEventId");
-if(!parent.children)
-parent.children=new Map();
-var node=parent.children.get(id);
-if(node){
-node.selfTime+=time;
-node.totalTime+=time;
-}else{
-node=new WebInspector.TimelineProfileTree.Node();
-node.totalTime=time;
-node.selfTime=time;
-node.parent=parent;
-node.id=id;
-node.event=e;
-parent.children.set(id,node);
-}
-parent.selfTime-=time;
-if(parent.selfTime<0){
-console.log("Error: Negative self of "+parent.selfTime,e);
-parent.selfTime=0;
-}
-if(e.endTime)
-parent=node;
-}
-
-
-
-
-function onEndEvent(e)
-{
-if(!WebInspector.TimelineModel.isVisible(filters,e))
-return;
-parent=parent.parent;
-}
-
-var instantEventCallback=eventIdCallback?undefined:onStartEvent;
-WebInspector.TimelineModel.forEachEvent(events,onStartEvent,onEndEvent,instantEventCallback,startTime,endTime);
-root.totalTime-=root.selfTime;
-root.selfTime=0;
-return root;
-};
-
-
-
-
-
-
-WebInspector.TimelineProfileTree.buildBottomUp=function(topDownTree,groupingCallback)
-{
-var buRoot=new WebInspector.TimelineProfileTree.Node();
-buRoot.selfTime=0;
-buRoot.totalTime=0;
-
-buRoot.children=new Map();
-var nodesOnStack=new Set();
-if(topDownTree.children)
-topDownTree.children.forEach(processNode);
-buRoot.totalTime=topDownTree.totalTime;
-
-
-
-
-function processNode(tdNode)
-{
-var buParent=groupingCallback&&groupingCallback(tdNode)||buRoot;
-if(buParent!==buRoot){
-buRoot.children.set(buParent.id,buParent);
-buParent.parent=buRoot;
-}
-appendNode(tdNode,buParent);
-var hadNode=nodesOnStack.has(tdNode.id);
-if(!hadNode)
-nodesOnStack.add(tdNode.id);
-if(tdNode.children)
-tdNode.children.forEach(processNode);
-if(!hadNode)
-nodesOnStack.delete(tdNode.id);
-}
-
-
-
-
-
-function appendNode(tdNode,buParent)
-{
-var selfTime=tdNode.selfTime;
-var totalTime=tdNode.totalTime;
-buParent.selfTime+=selfTime;
-buParent.totalTime+=selfTime;
-while(tdNode.parent){
-if(!buParent.children)
-buParent.children=new Map();
-var id=tdNode.id;
-var buNode=buParent.children.get(id);
-if(!buNode){
-buNode=new WebInspector.TimelineProfileTree.Node();
-buNode.selfTime=selfTime;
-buNode.totalTime=totalTime;
-buNode.event=tdNode.event;
-buNode.id=id;
-buNode.parent=buParent;
-buParent.children.set(id,buNode);
-}else{
-buNode.selfTime+=selfTime;
-if(!nodesOnStack.has(id))
-buNode.totalTime+=totalTime;
-}
-tdNode=tdNode.parent;
-buParent=buNode;
-}
-}
-
-
-var rootChildren=buRoot.children;
-for(var item of rootChildren.entries()){
-if(item[1].selfTime===0)
-rootChildren.delete(item[0]);
-}
-
-return buRoot;
-};
-
-
-
-
-
-WebInspector.TimelineProfileTree.eventURL=function(event)
-{
-var data=event.args["data"]||event.args["beginData"];
-if(data&&data["url"])
-return data["url"];
-var frame=WebInspector.TimelineProfileTree.eventStackFrame(event);
-while(frame){
-var url=frame["url"];
-if(url)
-return url;
-frame=frame.parent;
-}
-return null;
-};
-
-
-
-
-
-WebInspector.TimelineProfileTree.eventStackFrame=function(event)
-{
-if(event.name===WebInspector.TimelineModel.RecordType.JSFrame)
-return event.args["data"]||null;
-var topFrame=event.stackTrace&&event.stackTrace[0];
-if(topFrame)
-return topFrame;
-var initiator=event.initiator;
-return initiator&&initiator.stackTrace&&initiator.stackTrace[0]||null;
-};
-
-
-
-
-
-
-WebInspector.TimelineAggregator=function(titleMapper,categoryMapper)
-{
-this._titleMapper=titleMapper;
-this._categoryMapper=categoryMapper;
-
-this._groupNodes=new Map();
-};
-
-
-
-
-WebInspector.TimelineAggregator.GroupBy={
-None:"None",
-EventName:"EventName",
-Category:"Category",
-Domain:"Domain",
-Subdomain:"Subdomain",
-URL:"URL"};
-
-
-
-
-
-
-WebInspector.TimelineAggregator.eventId=function(event)
-{
-if(event.name===WebInspector.TimelineModel.RecordType.JSFrame){
-var data=event.args["data"];
-return"f:"+data["functionName"]+"@"+(data["scriptId"]||data["url"]||"");
-}
-return event.name+":@"+WebInspector.TimelineProfileTree.eventURL(event);
-};
-
-WebInspector.TimelineAggregator._extensionInternalPrefix="extensions::";
-WebInspector.TimelineAggregator._groupNodeFlag=Symbol("groupNode");
-
-
-
-
-
-WebInspector.TimelineAggregator.isExtensionInternalURL=function(url)
-{
-return url.startsWith(WebInspector.TimelineAggregator._extensionInternalPrefix);
-};
-
-WebInspector.TimelineAggregator.prototype={
-
-
-
-
-groupFunction:function(groupBy)
-{
-var idMapper=this._nodeToGroupIdFunction(groupBy);
-return idMapper&&this._nodeToGroupNode.bind(this,idMapper);
-},
-
-
-
-
-
-
-performGrouping:function(root,groupBy)
-{
-var nodeMapper=this.groupFunction(groupBy);
-if(!nodeMapper)
-return root;
-for(var node of root.children.values()){
-var groupNode=nodeMapper(node);
-groupNode.parent=root;
-groupNode.selfTime+=node.selfTime;
-groupNode.totalTime+=node.totalTime;
-groupNode.children.set(node.id,node);
-node.parent=root;
-}
-root.children=this._groupNodes;
-return root;
-},
-
-
-
-
-
-_nodeToGroupIdFunction:function(groupBy)
-{
-
-
-
-
-function groupByURL(node)
-{
-return WebInspector.TimelineProfileTree.eventURL(node.event)||"";
-}
-
-
-
-
-
-
-function groupByDomain(groupSubdomains,node)
-{
-var url=WebInspector.TimelineProfileTree.eventURL(node.event)||"";
-if(WebInspector.TimelineAggregator.isExtensionInternalURL(url))
-return WebInspector.TimelineAggregator._extensionInternalPrefix;
-var parsedURL=url.asParsedURL();
-if(!parsedURL)
-return"";
-if(parsedURL.scheme==="chrome-extension")
-return parsedURL.scheme+"://"+parsedURL.host;
-if(!groupSubdomains)
-return parsedURL.host;
-if(/^[.0-9]+$/.test(parsedURL.host))
-return parsedURL.host;
-var domainMatch=/([^.]*\.)?[^.]*$/.exec(parsedURL.host);
-return domainMatch&&domainMatch[0]||"";
-}
-
-switch(groupBy){
-case WebInspector.TimelineAggregator.GroupBy.None:return null;
-case WebInspector.TimelineAggregator.GroupBy.EventName:return node=>node.event?this._titleMapper(node.event):"";
-case WebInspector.TimelineAggregator.GroupBy.Category:return node=>node.event?this._categoryMapper(node.event):"";
-case WebInspector.TimelineAggregator.GroupBy.Subdomain:return groupByDomain.bind(null,false);
-case WebInspector.TimelineAggregator.GroupBy.Domain:return groupByDomain.bind(null,true);
-case WebInspector.TimelineAggregator.GroupBy.URL:return groupByURL;
-default:return null;}
-
-},
-
-
-
-
-
-
-_buildGroupNode:function(id,event)
-{
-var groupNode=new WebInspector.TimelineProfileTree.Node();
-groupNode.id=id;
-groupNode.selfTime=0;
-groupNode.totalTime=0;
-groupNode.children=new Map();
-groupNode.event=event;
-groupNode._isGroupNode=true;
-this._groupNodes.set(id,groupNode);
-return groupNode;
-},
-
-
-
-
-
-
-_nodeToGroupNode:function(nodeToGroupId,node)
-{
-var id=nodeToGroupId(node);
-return this._groupNodes.get(id)||this._buildGroupNode(id,node.event);
-}};
-
-
-},{}],132:[function(require,module,exports){
-
-
-
-
-
-
-
-
-
-
-
-
-
-WebInspector.SortableDataGrid=function(columnsArray,editCallback,deleteCallback,refreshCallback,contextMenuCallback)
-{
-WebInspector.ViewportDataGrid.call(this,columnsArray,editCallback,deleteCallback,refreshCallback,contextMenuCallback);
-
-this._sortingFunction=WebInspector.SortableDataGrid.TrivialComparator;
-this.setRootNode(new WebInspector.SortableDataGridNode());
-};
-
-
-WebInspector.SortableDataGrid.NodeComparator;
-
-
-
-
-
-
-WebInspector.SortableDataGrid.TrivialComparator=function(a,b)
-{
-return 0;
-};
-
-
-
-
-
-
-
-WebInspector.SortableDataGrid.NumericComparator=function(columnIdentifier,a,b)
-{
-var aValue=a.data[columnIdentifier];
-var bValue=b.data[columnIdentifier];
-var aNumber=Number(aValue instanceof Node?aValue.textContent:aValue);
-var bNumber=Number(bValue instanceof Node?bValue.textContent:bValue);
-return aNumber<bNumber?-1:aNumber>bNumber?1:0;
-};
-
-
-
-
-
-
-
-WebInspector.SortableDataGrid.StringComparator=function(columnIdentifier,a,b)
-{
-var aValue=a.data[columnIdentifier];
-var bValue=b.data[columnIdentifier];
-var aString=aValue instanceof Node?aValue.textContent:String(aValue);
-var bString=bValue instanceof Node?bValue.textContent:String(bValue);
-return aString<bString?-1:aString>bString?1:0;
-};
-
-
-
-
-
-
-
-
-WebInspector.SortableDataGrid.Comparator=function(comparator,reverseMode,a,b)
-{
-return reverseMode?comparator(b,a):comparator(a,b);
-};
-
-
-
-
-
-
-WebInspector.SortableDataGrid.create=function(columnNames,values)
-{
-var numColumns=columnNames.length;
-if(!numColumns)
-return null;
-
-var columns=[];
-for(var i=0;i<columnNames.length;++i)
-columns.push({title:columnNames[i],width:columnNames[i].length,sortable:true});
-
-var nodes=[];
-for(var i=0;i<values.length/numColumns;++i){
-var data={};
-for(var j=0;j<columnNames.length;++j)
-data[j]=values[numColumns*i+j];
-
-var node=new WebInspector.SortableDataGridNode(data);
-node.selectable=false;
-nodes.push(node);
-}
-
-var dataGrid=new WebInspector.SortableDataGrid(columns);
-var length=nodes.length;
-var rootNode=dataGrid.rootNode();
-for(var i=0;i<length;++i)
-rootNode.appendChild(nodes[i]);
-
-dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChanged,sortDataGrid);
-
-function sortDataGrid()
-{
-var nodes=dataGrid.rootNode().children;
-var sortColumnIdentifier=dataGrid.sortColumnIdentifier();
-if(!sortColumnIdentifier)
-return;
-
-var columnIsNumeric=true;
-for(var i=0;i<nodes.length;i++){
-var value=nodes[i].data[sortColumnIdentifier];
-if(isNaN(value instanceof Node?value.textContent:value)){
-columnIsNumeric=false;
-break;
-}
-}
-
-var comparator=columnIsNumeric?WebInspector.SortableDataGrid.NumericComparator:WebInspector.SortableDataGrid.StringComparator;
-dataGrid.sortNodes(comparator.bind(null,sortColumnIdentifier),!dataGrid.isSortOrderAscending());
-}
-return dataGrid;
-};
-
-WebInspector.SortableDataGrid.prototype={
-
-
-
-insertChild:function(node)
-{
-var root=this.rootNode();
-root.insertChildOrdered(node);
-},
-
-
-
-
-
-sortNodes:function(comparator,reverseMode)
-{
-this._sortingFunction=WebInspector.SortableDataGrid.Comparator.bind(null,comparator,reverseMode);
-this._rootNode._sortChildren(reverseMode);
-this.scheduleUpdateStructure();
-},
-
-__proto__:WebInspector.ViewportDataGrid.prototype};
-
-
-
-
-
-
-
-
-WebInspector.SortableDataGridNode=function(data,hasChildren)
-{
-WebInspector.ViewportDataGridNode.call(this,data,hasChildren);
-};
-
-WebInspector.SortableDataGridNode.prototype={
-
-
-
-insertChildOrdered:function(node)
-{
-this.insertChild(node,this.children.upperBound(node,this.dataGrid._sortingFunction));
-},
-
-_sortChildren:function()
-{
-this.children.sort(this.dataGrid._sortingFunction);
-for(var i=0;i<this.children.length;++i)
-this.children[i].recalculateSiblings(i);
-for(var child of this.children)
-child._sortChildren();
-},
-
-__proto__:WebInspector.ViewportDataGridNode.prototype};
-
-
-},{}],133:[function(require,module,exports){
+},{}],116:[function(require,module,exports){
(function(process){
@@ -64584,7 +52293,7 @@ return window.localStorage;
}
}).call(this,require('_process'));
-},{"./debug":134,"_process":77}],134:[function(require,module,exports){
+},{"./debug":117,"_process":77}],117:[function(require,module,exports){
@@ -64788,104 +52497,7 @@ if(val instanceof Error)return val.stack||val.message;
return val;
}
-},{"ms":146}],135:[function(require,module,exports){
-
-
-
-
-module.exports=function(WebInspector){
-
-function TimelineModelTreeView(model){
-this._rootNode=model;
-}
-
-TimelineModelTreeView.prototype.sortingChanged=function(sortItem,sortOrder){
-if(!sortItem)
-return;
-var sortFunction;
-switch(sortItem){
-case'startTime':
-sortFunction=compareStartTime;
-break;
-case'self':
-sortFunction=compareNumericField.bind(null,'selfTime');
-break;
-case'total':
-sortFunction=compareNumericField.bind(null,'totalTime');
-break;
-case'activity':
-sortFunction=compareName;
-break;
-default:
-console.assert(false,'Unknown sort field: '+sortItem);
-return;}
-
-return this.sortNodes(sortFunction,sortOrder!=='asc');
-
-function compareNumericField(field,a,b){
-var nodeA=a[1];
-var nodeB=b[1];
-return nodeA[field]-nodeB[field];
-}
-
-function compareStartTime(a,b){
-var nodeA=a[1];
-var nodeB=b[1];
-return nodeA.event.startTime-nodeB.event.startTime;
-}
-
-function compareName(a,b){
-var nodeA=a[1];
-var nodeB=b[1];
-var nameA=WebInspector.TimelineTreeView.eventNameForSorting(nodeA.event);
-var nameB=WebInspector.TimelineTreeView.eventNameForSorting(nodeB.event);
-return nameA.localeCompare(nameB);
-}
-};
-
-TimelineModelTreeView.prototype.sortNodes=function(comparator,reverseMode){
-this._sortingFunction=WebInspector.SortableDataGrid.Comparator.bind(null,comparator,reverseMode);
-sortChildren(this._rootNode,this._sortingFunction,reverseMode);
-};
-
-
-
-
-
-
-function sortChildren(parent,sortingFunction){
-if(!parent.children)return;
-parent.children=new Map([...parent.children.entries()].sort(sortingFunction));
-for(var i=0;i<parent.children.length;++i)
-recalculateSiblings(parent.children[i],i);
-for(var child of parent.children.values())
-sortChildren(child,sortingFunction);
-}
-
-
-
-
-
-function recalculateSiblings(node,myIndex){
-if(!node.parent)
-return;
-
-var previousChild=node.parent.children[myIndex-1]||null;
-if(previousChild)
-previousChild.nextSibling=node;
-node.previousSibling=previousChild;
-
-var nextChild=node.parent.children[myIndex+1]||null;
-if(nextChild)
-nextChild.previousSibling=node;
-node.nextSibling=nextChild;
-}
-
-return TimelineModelTreeView;
-
-};
-
-},{}],136:[function(require,module,exports){
+},{"ms":128}],118:[function(require,module,exports){
(function webpackUniversalModuleDefinition(root,factory){
if(typeof exports==='object'&&typeof module==='object')
@@ -71586,7 +59198,7 @@ exports.Tokenizer=Tokenizer;
});
;
-},{}],137:[function(require,module,exports){
+},{}],119:[function(require,module,exports){
(function(Buffer){
var querystring=require('querystring');
var trim=require('./trim');
@@ -71893,12 +59505,12 @@ return refs.join(', ');
module.exports=Link;
}).call(this,{"isBuffer":require("../../../lighthouse-extension/node_modules/is-buffer/index.js")});
-},{"../../../lighthouse-extension/node_modules/is-buffer/index.js":65,"./trim":138,"querystring":80}],138:[function(require,module,exports){
+},{"../../../lighthouse-extension/node_modules/is-buffer/index.js":65,"./trim":120,"querystring":80}],120:[function(require,module,exports){
module.exports=function trim(value){
return value.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,'');
};
-},{}],139:[function(require,module,exports){
+},{}],121:[function(require,module,exports){
@@ -72043,7 +59655,7 @@ return sumLuma/lumaValues.length;
})(ImageSSIM||(ImageSSIM={}));
module.exports=ImageSSIM;
-},{}],140:[function(require,module,exports){
+},{}],122:[function(require,module,exports){
var encode=require('./lib/encoder'),
decode=require('./lib/decoder');
@@ -72052,7 +59664,7 @@ encode:encode,
decode:decode};
-},{"./lib/decoder":141,"./lib/encoder":142}],141:[function(require,module,exports){
+},{"./lib/decoder":123,"./lib/encoder":124}],123:[function(require,module,exports){
(function(Buffer){
@@ -73042,7 +60654,7 @@ return image;
}
}).call(this,require("buffer").Buffer);
-},{"buffer":60}],142:[function(require,module,exports){
+},{"buffer":60}],124:[function(require,module,exports){
(function(Buffer){
@@ -73812,7 +61424,7 @@ return ctx.getImageData(0,0,cvs.width,cvs.height);
}
}).call(this,require("buffer").Buffer);
-},{"buffer":60}],143:[function(require,module,exports){
+},{"buffer":60}],125:[function(require,module,exports){
(function(process){
@@ -74028,7 +61640,7 @@ Log.events=new Emitter();
module.exports=Log;
}).call(this,require('_process'));
-},{"_process":77,"debug":133,"events":62}],144:[function(require,module,exports){
+},{"_process":77,"debug":116,"events":62}],126:[function(require,module,exports){
(function(global){
@@ -75880,7 +63492,7 @@ return false;
module.exports=isEqual;
}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{});
-},{}],145:[function(require,module,exports){
+},{}],127:[function(require,module,exports){
exports.getRenderingDataFromViewport=function(viewportProperties,uaDeviceWidth,uaDeviceHeight,uaMaxZoom,uaMinZoom){
var vw=uaDeviceWidth/100;
@@ -76223,7 +63835,7 @@ exports.expectedValues={
"viewport-fit":["auto","cover"]};
-},{}],146:[function(require,module,exports){
+},{}],128:[function(require,module,exports){
@@ -76377,7 +63989,7 @@ return Math.floor(ms/n)+' '+name;
return Math.ceil(ms/n)+' '+name+'s';
}
-},{}],147:[function(require,module,exports){
+},{}],129:[function(require,module,exports){
module.exports=function parseCacheControl(field){
if(typeof field!=='string'){
@@ -76416,7 +64028,7 @@ catch(err){}
return err?null:header;
};
-},{}],148:[function(require,module,exports){
+},{}],130:[function(require,module,exports){
var URL=require('url').URL;
@@ -76839,13 +64451,13 @@ return this._sitemaps.slice(0);
module.exports=Robots;
-},{"url":"url"}],149:[function(require,module,exports){
+},{"url":"url"}],131:[function(require,module,exports){
var Robots=require('./Robots');
module.exports=function(url,contents){
return new Robots(url,contents);
};
-},{"./Robots":148}],150:[function(require,module,exports){
+},{"./Robots":130}],132:[function(require,module,exports){
(function(process){
exports=module.exports=SemVer;
@@ -78052,7 +65664,7 @@ return parsed&&parsed.prerelease.length?parsed.prerelease:null;
}
}).call(this,require('_process'));
-},{"_process":77}],151:[function(require,module,exports){
+},{"_process":77}],133:[function(require,module,exports){
(function(Buffer){
'use strict';
@@ -78240,7 +65852,7 @@ create:frame};
}).call(this,require("buffer").Buffer);
-},{"buffer":60,"jpeg-js":140}],152:[function(require,module,exports){
+},{"buffer":60,"jpeg-js":122}],134:[function(require,module,exports){
'use strict';
const frame=require('./frame');
@@ -78298,7 +65910,7 @@ return calculateValues(frames,data);
});
};
-},{"./frame":151,"./speed-index":153}],153:[function(require,module,exports){
+},{"./frame":133,"./speed-index":135}],135:[function(require,module,exports){
'use strict';
const imageSSIM=require('image-ssim');
@@ -78521,11 +66133,11 @@ calculatePerceptualProgress,
calculateSpeedIndexes};
-},{"image-ssim":139}],154:[function(require,module,exports){
+},{"image-ssim":121}],136:[function(require,module,exports){
module.exports={
-"version":"3.0.0-beta.0"};
+"version":"3.0.3"};
-},{}],155:[function(require,module,exports){
+},{}],137:[function(require,module,exports){
module.exports={
"npm":{
"angular":[
@@ -78654,6 +66266,12 @@ require('url').URL;
+const listOfTlds=[
+'com','co','gov','edu','ac','org','go','gob','or','net','in','ne','nic','gouv',
+'web','spb','blog','jus','kiev','mil','wi','qc','ca','bel','on'];
+
+
+
@@ -78727,6 +66345,54 @@ return null;
+
+static getTld(hostname){
+const tlds=hostname.split('.').slice(-2);
+
+if(!listOfTlds.includes(tlds[0])){
+return`.${tlds[tlds.length-1]}`;
+}
+
+return`.${tlds.join('.')}`;
+}
+
+
+
+
+
+
+
+static rootDomainsMatch(urlA,urlB){
+let urlAInfo;
+let urlBInfo;
+try{
+urlAInfo=new URL(urlA);
+urlBInfo=new URL(urlB);
+}catch(err){
+return false;
+}
+
+if(!urlAInfo.hostname||!urlBInfo.hostname){
+return false;
+}
+
+const tldA=URLShim.getTld(urlAInfo.hostname);
+const tldB=URLShim.getTld(urlBInfo.hostname);
+
+
+const urlARootDomain=urlAInfo.hostname.replace(new RegExp(`${tldA}$`),'').
+split('.').splice(-1)[0];
+const urlBRootDomain=urlBInfo.hostname.replace(new RegExp(`${tldB}$`),'').
+split('.').splice(-1)[0];
+
+return urlARootDomain===urlBRootDomain;
+}
+
+
+
+
+
+
static getURLDisplayName(url,options){
return Util.getURLDisplayName(new URL(url),options);
}
@@ -78771,6 +66437,8 @@ URLShim.URL=URL;
URLShim.URLSearchParams=typeof self!=='undefined'&&self.URLSearchParams||
require('url').URLSearchParams;
+URLShim.NON_NETWORK_PROTOCOLS=['blob','data'];
+
URLShim.INVALID_URL_DEBUG_STRING=
'Lighthouse was unable to determine the URL of some script executions. '+
'It\'s possible a Chrome extension or other eval\'d code is the source.';
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/bindings/NetworkProject.js b/chromium/third_party/blink/renderer/devtools/front_end/bindings/NetworkProject.js
index 50c7d67c1f7..cddee9d847a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/bindings/NetworkProject.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/bindings/NetworkProject.js
@@ -106,6 +106,8 @@ Bindings.NetworkProject = class {
*/
static removeFrameAttribution(uiSourceCode, frameId) {
const frameAttribution = uiSourceCode[Bindings.NetworkProject._frameAttributionSymbol];
+ if (!frameAttribution)
+ return;
const attributionInfo = frameAttribution.get(frameId);
console.assert(attributionInfo, 'Failed to remove frame attribution for url: ' + uiSourceCode.url());
attributionInfo.count -= 1;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/browser_console/BrowserConsole.js b/chromium/third_party/blink/renderer/devtools/front_end/browser_console/BrowserConsole.js
index c961bc23146..aee39714f7f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/browser_console/BrowserConsole.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/browser_console/BrowserConsole.js
@@ -37,7 +37,12 @@ BrowserConsole.BrowserConsole = class {
if (consoleMessage.level === SDK.ConsoleMessage.MessageLevel.Error) {
messageElement.createTextChild(request.requestMethod + ' ');
messageElement.appendChild(Components.Linkifier.linkifyRevealable(request, request.url(), request.url()));
- messageElement.createTextChildren(' ', String(request.statusCode), ' (', request.statusText, ')');
+ if (request.failed)
+ messageElement.createTextChildren(' ', request.localizedFailDescription);
+ if (request.statusCode !== 0)
+ messageElement.createTextChildren(' ', String(request.statusCode));
+ if (request.statusText)
+ messageElement.createTextChildren(' (', request.statusText, ')');
} else {
const fragment = Console.ConsoleViewMessage.linkifyWithCustomLinkifier(
consoleMessage.messageText,
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/ResourceType.js b/chromium/third_party/blink/renderer/devtools/front_end/common/ResourceType.js
index 17beaefc805..75d32a15fd3 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/ResourceType.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/ResourceType.js
@@ -242,7 +242,7 @@ Common.ResourceType._mimeTypeByName = new Map([
]);
Common.ResourceType._resourceTypeByExtension = new Map([
- ['js', Common.resourceTypes.Script],
+ ['js', Common.resourceTypes.Script], ['mjs', Common.resourceTypes.Script],
['css', Common.resourceTypes.Stylesheet], ['xsl', Common.resourceTypes.Stylesheet],
@@ -258,8 +258,8 @@ Common.ResourceType._resourceTypeByExtension = new Map([
Common.ResourceType._mimeTypeByExtension = new Map([
// Web extensions
- ['js', 'text/javascript'], ['css', 'text/css'], ['html', 'text/html'], ['htm', 'text/html'],
- ['mjs', 'text/javascript'], ['xml', 'application/xml'], ['xsl', 'application/xml'],
+ ['js', 'text/javascript'], ['mjs', 'text/javascript'], ['css', 'text/css'], ['html', 'text/html'],
+ ['htm', 'text/html'], ['xml', 'application/xml'], ['xsl', 'application/xml'],
// HTML Embedded Scripts, ASP], JSP
['asp', 'application/x-aspx'], ['aspx', 'application/x-aspx'], ['jsp', 'application/x-jsp'],
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/common/Settings.js b/chromium/third_party/blink/renderer/devtools/front_end/common/Settings.js
index a5bcc63550b..9652e59b873 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/common/Settings.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/common/Settings.js
@@ -796,6 +796,18 @@ Common.VersionController = class {
networkLogColumnsSetting.set(columns);
}
+ _updateVersionFrom25To26() {
+ const oldSetting = Common.settings.createSetting('messageURLFilters', {});
+ const urls = Object.keys(oldSetting.get());
+ const textFilter = urls.map(url => `-url:${url}`).join(' ');
+ if (textFilter) {
+ const textFilterSetting = Common.settings.createSetting('console.textFilter', '');
+ const suffix = textFilterSetting.get() ? ` ${textFilterSetting.get()}` : '';
+ textFilterSetting.set(`${textFilter}${suffix}`);
+ }
+ oldSetting.remove();
+ }
+
_migrateSettingsFromLocalStorage() {
// This step migrates all the settings except for the ones below into the browser profile.
const localSettings = new Set([
@@ -828,7 +840,7 @@ Common.VersionController = class {
};
Common.VersionController._currentVersionName = 'inspectorVersion';
-Common.VersionController.currentVersion = 25;
+Common.VersionController.currentVersion = 26;
/**
* @type {!Common.Settings}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleContextSelector.js b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleContextSelector.js
index b1f45f4dc96..56afa11c4f4 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleContextSelector.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleContextSelector.js
@@ -14,6 +14,7 @@ Console.ConsoleContextSelector = class {
this._dropDown.setRowHeight(36);
this._toolbarItem = new UI.ToolbarItem(this._dropDown.element);
this._toolbarItem.setEnabled(false);
+ this._toolbarItem.setTitle(ls`JavaScript contexts`);
this._items.addEventListener(
UI.ListModel.Events.ItemsReplaced, () => this._toolbarItem.setEnabled(!!this._items.length));
@@ -96,9 +97,12 @@ Console.ConsoleContextSelector = class {
if (executionContext.frameId) {
const resourceTreeModel = target.model(SDK.ResourceTreeModel);
let frame = resourceTreeModel && resourceTreeModel.frameForId(executionContext.frameId);
- while (frame && frame.parentFrame) {
- depth++;
- frame = frame.parentFrame;
+ while (frame) {
+ frame = frame.parentFrame || frame.crossTargetParentFrame();
+ if (frame) {
+ depth++;
+ target = frame.resourceTreeModel().target();
+ }
}
}
let targetDepth = 0;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePinPane.js b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePinPane.js
new file mode 100644
index 00000000000..c806078b6ee
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePinPane.js
@@ -0,0 +1,114 @@
+// 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.
+
+Console.ConsolePinPane = class extends UI.VBox {
+ constructor() {
+ super(true);
+ this.registerRequiredCSS('console/consolePinPane.css');
+ this.contentElement.classList.add('console-pins', 'monospace');
+ this.contentElement.addEventListener('contextmenu', this._contextMenuEventFired.bind(this), false);
+
+ /** @type {!Set<!Console.ConsolePin>} */
+ this._pins = new Set();
+ }
+
+ /**
+ * @param {!Event} event
+ */
+ _contextMenuEventFired(event) {
+ const contextMenu = new UI.ContextMenu(event);
+ const target = event.deepElementFromPoint();
+ if (target) {
+ const targetPinElement = target.enclosingNodeOrSelfWithClass('console-pin');
+ if (targetPinElement) {
+ const targetPin = targetPinElement[Console.ConsolePin._PinSymbol];
+ contextMenu.editSection().appendItem(ls`Edit pin`, targetPin.focus.bind(targetPin));
+ contextMenu.editSection().appendItem(ls`Remove pin`, this._removePin.bind(this, targetPin));
+ }
+ }
+ contextMenu.editSection().appendItem(ls`Remove all pins`, this._removeAllPins.bind(this));
+ contextMenu.show();
+ }
+
+ _removeAllPins() {
+ for (const pin of this._pins)
+ this._removePin(pin);
+ }
+
+ /**
+ * @param {!Console.ConsolePin} pin
+ */
+ _removePin(pin) {
+ pin.element().remove();
+ this._pins.delete(pin);
+ }
+
+ /**
+ * @param {string} expression
+ */
+ addPin(expression) {
+ const pin = new Console.ConsolePin(expression, this._removePin.bind(this));
+ this.contentElement.appendChild(pin.element());
+ this._pins.add(pin);
+ pin.focus();
+ }
+};
+
+Console.ConsolePin = class {
+ /**
+ * @param {string} expression
+ * @param {function(!Console.ConsolePin)} onRemove
+ */
+ constructor(expression, onRemove) {
+ const deletePinIcon = UI.Icon.create('smallicon-cross', 'console-delete-pin');
+ deletePinIcon.addEventListener('click', () => onRemove(this));
+
+ const fragment = UI.Fragment.build`
+ <div class='console-pin'>
+ ${deletePinIcon}
+ <div class='console-pin-name' $='name'></div>
+ <div class='console-pin-preview'>${ls`not available`}</div>
+ </div>`;
+ this._pinElement = fragment.element();
+ const nameElement = fragment.$('name');
+ nameElement.title = expression;
+ this._pinElement[Console.ConsolePin._PinSymbol] = this;
+
+ /** @type {?UI.TextEditor} */
+ this._editor = null;
+
+ this._editorPromise = self.runtime.extension(UI.TextEditorFactory).instance().then(factory => {
+ this._editor = factory.createEditor({
+ lineNumbers: false,
+ lineWrapping: true,
+ mimeType: 'javascript',
+ autoHeight: true,
+ placeholder: ls`Expression`
+ });
+ this._editor.widget().show(nameElement);
+ this._editor.widget().element.classList.add('console-pin-editor');
+ this._editor.widget().element.tabIndex = -1;
+ this._editor.setText(expression);
+ this._editor.widget().element.addEventListener('keydown', event => {
+ if (event.key === 'Tab')
+ event.consume();
+ }, true);
+ });
+ }
+
+ /**
+ * @return {!Element}
+ */
+ element() {
+ return this._pinElement;
+ }
+
+ async focus() {
+ await this._editorPromise;
+ this._editor.widget().focus();
+ this._editor.setSelection(TextUtils.TextRange.createFromLocation(Infinity, Infinity));
+ }
+};
+
+Console.ConsolePin._PinSymbol = Symbol('pinSymbol');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js
index 34b61d4e10f..96070e1e0e6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsolePrompt.js
@@ -23,10 +23,17 @@ Console.ConsolePrompt = class extends UI.Widget {
this._eagerEvalSetting.addChangeListener(this._eagerSettingChanged.bind(this));
this._eagerPreviewElement.classList.toggle('hidden', !this._eagerEvalSetting.get());
+ // TODO(luoe): split out prompt styles into ConsolePrompt.css.
+ const pinsEnabled = Runtime.experiments.isEnabled('pinnedExpressions');
+ if (pinsEnabled)
+ this.element.style.marginRight = '20px';
this.element.tabIndex = 0;
/** @type {?Promise} */
this._previewRequestForTest = null;
+ /** @type {?UI.AutocompleteConfig} */
+ this._defaultAutocompleteConfig = null;
+
self.runtime.extension(UI.TextEditorFactory).instance().then(gotFactory.bind(this));
/**
@@ -37,17 +44,23 @@ Console.ConsolePrompt = class extends UI.Widget {
this._editor =
factory.createEditor({lineNumbers: false, lineWrapping: true, mimeType: 'javascript', autoHeight: true});
- this._editor.configureAutocomplete({
- substituteRangeCallback: this._substituteRange.bind(this),
+ this._defaultAutocompleteConfig = ObjectUI.JavaScriptAutocompleteConfig.createConfigForEditor(this._editor);
+ this._editor.configureAutocomplete(Object.assign({}, this._defaultAutocompleteConfig, {
suggestionsCallback: this._wordsWithQuery.bind(this),
- tooltipCallback: (lineNumber, columnNumber) => this._tooltipCallback(lineNumber, columnNumber),
anchorBehavior: this._isBelowPromptEnabled ? UI.GlassPane.AnchorBehavior.PreferTop :
UI.GlassPane.AnchorBehavior.PreferBottom
- });
+ }));
this._editor.widget().element.addEventListener('keydown', this._editorKeyDown.bind(this), true);
this._editor.widget().show(this.element);
this._editor.addEventListener(UI.TextEditor.Events.TextChanged, this._onTextChanged, this);
this._editor.addEventListener(UI.TextEditor.Events.SuggestionChanged, this._onTextChanged, this);
+ if (pinsEnabled) {
+ const pinButton = this.element.createChild('span', 'command-pin-button');
+ pinButton.title = ls`Pin expression`;
+ pinButton.addEventListener('click', () => {
+ this.dispatchEventToListeners(Console.ConsolePrompt.Events.ExpressionPinned, this.text());
+ });
+ }
if (this._isBelowPromptEnabled)
this.element.appendChild(this._eagerPreviewElement);
@@ -332,25 +345,6 @@ Console.ConsolePrompt = class extends UI.Widget {
}
/**
- * @param {number} lineNumber
- * @param {number} columnNumber
- * @return {?TextUtils.TextRange}
- */
- _substituteRange(lineNumber, columnNumber) {
- const token = this._editor.tokenAtTextPosition(lineNumber, columnNumber);
- if (token && token.type === 'js-string')
- return new TextUtils.TextRange(lineNumber, token.startColumn, lineNumber, columnNumber);
-
- const lineText = this._editor.line(lineNumber);
- let index;
- for (index = columnNumber - 1; index >= 0; index--) {
- if (' =:[({;,!+-*/&|^<>.\t\r\n'.indexOf(lineText.charAt(index)) !== -1)
- break;
- }
- return new TextUtils.TextRange(lineNumber, index + 1, lineNumber, columnNumber);
- }
-
- /**
* @param {!TextUtils.TextRange} queryRange
* @param {!TextUtils.TextRange} substituteRange
* @param {boolean=} force
@@ -358,55 +352,11 @@ Console.ConsolePrompt = class extends UI.Widget {
*/
async _wordsWithQuery(queryRange, substituteRange, force) {
const query = this._editor.text(queryRange);
- const before = this._editor.text(new TextUtils.TextRange(0, 0, queryRange.startLine, queryRange.startColumn));
+ const words = await this._defaultAutocompleteConfig.suggestionsCallback(queryRange, substituteRange, force);
const historyWords = this._historyCompletions(query, force);
- const token = this._editor.tokenAtTextPosition(substituteRange.startLine, substituteRange.startColumn);
- if (token) {
- const excludedTokens = new Set(['js-comment', 'js-string-2', 'js-def']);
- const trimmedBefore = before.trim();
- if (!trimmedBefore.endsWith('[') && !trimmedBefore.match(/\.\s*(get|set|delete)\s*\(\s*$/))
- excludedTokens.add('js-string');
- if (!trimmedBefore.endsWith('.'))
- excludedTokens.add('js-property');
- if (excludedTokens.has(token.type))
- return historyWords;
- }
- const words = await ObjectUI.javaScriptAutocomplete.completionsForTextInCurrentContext(before, query, force);
- if (!force && !this._isCaretAtEndOfPrompt()) {
- const queryAndAfter = this._editor.line(queryRange.startLine).substring(queryRange.startColumn);
- if (queryAndAfter && words.some(word => queryAndAfter.startsWith(word.text) && query.length !== word.text.length))
- return [];
- }
return words.concat(historyWords);
}
- /**
- * @param {number} lineNumber
- * @param {number} columnNumber
- * @return {!Promise<?Element>}
- */
- async _tooltipCallback(lineNumber, columnNumber) {
- const before = this._editor.text(new TextUtils.TextRange(0, 0, lineNumber, columnNumber));
- const result = await ObjectUI.javaScriptAutocomplete.argumentsHint(before);
- if (!result)
- return null;
- const {argumentIndex} = result;
- const tooltip = createElement('div');
- for (const args of result.args) {
- const argumentsElement = createElement('span');
- for (let i = 0; i < args.length; i++) {
- if (i === argumentIndex || (i < argumentIndex && args[i].startsWith('...')))
- argumentsElement.appendChild(UI.html`<b>${args[i]}</b>`);
- else
- argumentsElement.createTextChild(args[i]);
- if (i < args.length - 1)
- argumentsElement.createTextChild(', ');
- }
- tooltip.appendChild(UI.html`<div class='source-code'>\u0192(${argumentsElement})</div>`);
- }
- return tooltip;
- }
-
_editorSetForTest() {
}
};
@@ -508,5 +458,6 @@ Console.ConsoleHistoryManager = class {
};
Console.ConsolePrompt.Events = {
+ ExpressionPinned: Symbol('ExpressionPinned'),
TextChanged: Symbol('TextChanged')
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js
index bbf382abf30..d380af97275 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js
@@ -49,7 +49,7 @@ Console.ConsoleView = class extends UI.VBox {
this._filter = new Console.ConsoleViewFilter(this._onFilterChanged.bind(this));
this._isBelowPromptEnabled = Runtime.experiments.isEnabled('consoleBelowPrompt');
- const toolbar = new UI.Toolbar('', this.element);
+ const consoleToolbarContainer = this.element.createChild('div', 'console-toolbar-container');
this._splitWidget =
new UI.SplitWidget(true /* isVertical */, false /* secondIsSidebar */, 'console.sidebar.width', 100);
this._splitWidget.setMainWidget(this._searchableView);
@@ -60,7 +60,6 @@ Console.ConsoleView = class extends UI.VBox {
this._isSidebarOpen = this._splitWidget.showMode() === UI.SplitWidget.ShowMode.Both;
if (this._isSidebarOpen)
this._filter._levelMenuButton.setEnabled(false);
- toolbar.appendToolbarItem(this._splitWidget.createShowHideSidebarButton('console sidebar'));
this._splitWidget.addEventListener(UI.SplitWidget.Events.ShowModeChanged, event => {
this._isSidebarOpen = event.data === UI.SplitWidget.ShowMode.Both;
this._filter._levelMenuButton.setEnabled(!this._isSidebarOpen);
@@ -71,7 +70,6 @@ Console.ConsoleView = class extends UI.VBox {
/** @type {!Array.<!Console.ConsoleViewMessage>} */
this._visibleViewMessages = [];
- this._urlToMessageCount = {};
this._hiddenByFilterCount = 0;
/** @type {!Set<!Console.ConsoleViewMessage>} */
this._shouldBeHiddenCache = new Set();
@@ -99,6 +97,9 @@ Console.ConsoleView = class extends UI.VBox {
const groupSimilarToggle =
new UI.ToolbarSettingCheckbox(this._groupSimilarSetting, Common.UIString('Group similar'));
+ const toolbar = new UI.Toolbar('console-main-toolbar', consoleToolbarContainer);
+ const rightToolbar = new UI.Toolbar('', consoleToolbarContainer);
+ toolbar.appendToolbarItem(this._splitWidget.createShowHideSidebarButton('console sidebar'));
toolbar.appendToolbarItem(UI.Toolbar.createActionButton(
/** @type {!UI.Action }*/ (UI.actionRegistry.action('console.clear'))));
toolbar.appendSeparator();
@@ -108,10 +109,9 @@ Console.ConsoleView = class extends UI.VBox {
toolbar.appendToolbarItem(this._filter._levelMenuButton);
toolbar.appendToolbarItem(groupSimilarToggle);
toolbar.appendToolbarItem(this._progressToolbarItem);
- toolbar.appendSpacer();
- toolbar.appendToolbarItem(this._filterStatusText);
- toolbar.appendSeparator();
- toolbar.appendToolbarItem(this._showSettingsPaneButton);
+ rightToolbar.appendSeparator();
+ rightToolbar.appendToolbarItem(this._filterStatusText);
+ rightToolbar.appendToolbarItem(this._showSettingsPaneButton);
this._preserveLogCheckbox = new UI.ToolbarSettingCheckbox(
Common.moduleSetting('preserveConsoleLog'), Common.UIString('Do not clear log on page reload / navigation'),
@@ -153,6 +153,12 @@ Console.ConsoleView = class extends UI.VBox {
this._showSettingsPaneSetting.addChangeListener(
() => settingsPane.element.classList.toggle('hidden', !this._showSettingsPaneSetting.get()));
+ if (Runtime.experiments.isEnabled('pinnedExpressions')) {
+ this._pinPane = new Console.ConsolePinPane();
+ this._pinPane.element.classList.add('console-view-pinpane');
+ this._pinPane.show(this._contentsElement);
+ }
+
this._viewport = new Console.ConsoleViewport(this);
this._viewport.setStickToBottom(true);
this._viewport.contentElement().classList.add('console-group', 'console-group-messages');
@@ -192,6 +198,7 @@ Console.ConsoleView = class extends UI.VBox {
this._prompt = new Console.ConsolePrompt();
this._prompt.show(this._promptElement);
this._prompt.element.addEventListener('keydown', this._promptKeyDown.bind(this), true);
+ this._prompt.addEventListener(Console.ConsolePrompt.Events.ExpressionPinned, this._promptExpressionPinned, this);
this._prompt.addEventListener(Console.ConsolePrompt.Events.TextChanged, this._promptTextChanged, this);
this._consoleHistoryAutocompleteSetting.addChangeListener(this._consoleHistoryAutocompleteChanged, this);
@@ -207,7 +214,8 @@ Console.ConsoleView = class extends UI.VBox {
UI.context.addFlavorChangeListener(SDK.ExecutionContext, this._executionContextChanged, this);
- this._messagesElement.addEventListener('mousedown', this._updateStickToBottomOnMouseDown.bind(this), false);
+ this._messagesElement.addEventListener(
+ 'mousedown', event => this._updateStickToBottomOnMouseDown(event.button === 2), false);
this._messagesElement.addEventListener('mouseup', this._updateStickToBottomOnMouseUp.bind(this), false);
this._messagesElement.addEventListener('mouseleave', this._updateStickToBottomOnMouseUp.bind(this), false);
this._messagesElement.addEventListener('wheel', this._updateStickToBottomOnWheel.bind(this), false);
@@ -477,11 +485,6 @@ Console.ConsoleView = class extends UI.VBox {
const insertedInMiddle = insertAt < this._consoleMessages.length;
this._consoleMessages.splice(insertAt, 0, viewMessage);
- if (this._urlToMessageCount[message.url])
- ++this._urlToMessageCount[message.url];
- else
- this._urlToMessageCount[message.url] = 1;
-
this._filter.onMessageAdded(message);
this._sidebar.onMessageAdded(viewMessage);
@@ -640,29 +643,12 @@ Console.ConsoleView = class extends UI.VBox {
const sourceElement = event.target.enclosingNodeOrSelfWithClass('console-message-wrapper');
const consoleMessage = sourceElement ? sourceElement.message.consoleMessage() : null;
- const filterSubMenu = contextMenu.headerSection().appendSubMenuItem(Common.UIString('Filter'));
-
if (consoleMessage && consoleMessage.url) {
- const menuTitle = Common.UIString('Hide messages from %s', new Common.ParsedURL(consoleMessage.url).displayName);
- filterSubMenu.headerSection().appendItem(
+ const menuTitle = ls`Hide messages from ${new Common.ParsedURL(consoleMessage.url).displayName}`;
+ contextMenu.headerSection().appendItem(
menuTitle, this._filter.addMessageURLFilter.bind(this._filter, consoleMessage.url));
}
- const unhideAll = filterSubMenu.footerSection().appendItem(
- Common.UIString('Unhide all'), this._filter.removeMessageURLFilter.bind(this._filter));
-
- let hasFilters = false;
-
- for (const url in this._filter.messageURLFilters()) {
- filterSubMenu.defaultSection().appendCheckboxItem(
- String.sprintf('%s (%d)', new Common.ParsedURL(url).displayName, this._urlToMessageCount[url]),
- this._filter.removeMessageURLFilter.bind(this._filter, url), true);
- hasFilters = true;
- }
-
- filterSubMenu.setEnabled(hasFilters || (consoleMessage && consoleMessage.url));
- unhideAll.setEnabled(hasFilters);
-
contextMenu.defaultSection().appendAction('console.clear');
contextMenu.defaultSection().appendAction('console.clear.history');
contextMenu.saveSection().appendItem(Common.UIString('Save as...'), this._saveConsole.bind(this));
@@ -784,6 +770,8 @@ Console.ConsoleView = class extends UI.VBox {
_addGroupableMessagesToEnd() {
/** @type {!Set<!SDK.ConsoleMessage>} */
const alreadyAdded = new Set();
+ /** @type {!Set<string>} */
+ const processedGroupKeys = new Set();
for (let i = 0; i < this._consoleMessages.length; ++i) {
const viewMessage = this._consoleMessages[i];
const message = viewMessage.consoleMessage();
@@ -805,9 +793,13 @@ Console.ConsoleView = class extends UI.VBox {
continue;
}
+ if (processedGroupKeys.has(key))
+ continue;
+
if (!viewMessagesInGroup.find(x => this._shouldMessageBeVisible(x))) {
// Optimize for speed.
alreadyAdded.addAll(viewMessagesInGroup);
+ processedGroupKeys.add(key);
continue;
}
@@ -1117,8 +1109,11 @@ Console.ConsoleView = class extends UI.VBox {
highlightNode.scrollIntoViewIfNeeded();
}
- _updateStickToBottomOnMouseDown() {
- this._muteViewportUpdates = true;
+ /**
+ * @param {boolean=} isRightClick
+ */
+ _updateStickToBottomOnMouseDown(isRightClick) {
+ this._muteViewportUpdates = !isRightClick;
this._viewport.setStickToBottom(false);
if (this._waitForScrollTimeout) {
clearTimeout(this._waitForScrollTimeout);
@@ -1160,6 +1155,14 @@ Console.ConsoleView = class extends UI.VBox {
this._updateStickToBottomOnMouseUp();
}
+ /**
+ * @param {!Common.Event} event
+ */
+ _promptExpressionPinned(event) {
+ const text = /** @type {string} */ (event.data);
+ this._pinPane.addPin(text);
+ }
+
_promptTextChanged() {
this._viewport.setStickToBottom(this._isScrolledToBottom());
this._promptTextChangedForTest();
@@ -1190,12 +1193,10 @@ Console.ConsoleViewFilter = class {
constructor(filterChangedCallback) {
this._filterChanged = filterChangedCallback;
- this._messageURLFiltersSetting = Common.settings.createSetting('messageURLFilters', {});
this._messageLevelFiltersSetting = Console.ConsoleViewFilter.levelFilterSetting();
this._hideNetworkMessagesSetting = Common.moduleSetting('hideNetworkMessages');
this._filterByExecutionContextSetting = Common.moduleSetting('selectedContextFilterEnabled');
- this._messageURLFiltersSetting.addChangeListener(this._onFilterChanged.bind(this));
this._messageLevelFiltersSetting.addChangeListener(this._onFilterChanged.bind(this));
this._hideNetworkMessagesSetting.addChangeListener(this._onFilterChanged.bind(this));
this._filterByExecutionContextSetting.addChangeListener(this._onFilterChanged.bind(this));
@@ -1223,7 +1224,7 @@ Console.ConsoleViewFilter = class {
this._levelLabels[SDK.ConsoleMessage.MessageLevel.Warning] = Common.UIString('Warnings');
this._levelLabels[SDK.ConsoleMessage.MessageLevel.Error] = Common.UIString('Errors');
- this._levelMenuButton = new UI.ToolbarButton('');
+ this._levelMenuButton = new UI.ToolbarButton(ls`Log levels`);
this._levelMenuButton.turnIntoSelect();
this._levelMenuButton.addEventListener(UI.ToolbarButton.Events.Click, this._showLevelContextMenu.bind(this));
@@ -1254,8 +1255,7 @@ Console.ConsoleViewFilter = class {
}
_updateCurrentFilter() {
- let parsedFilters = this._filterParser.parse(this._textFilterUI.value());
-
+ const parsedFilters = this._filterParser.parse(this._textFilterUI.value());
if (this._hideNetworkMessagesSetting.get()) {
parsedFilters.push({
key: Console.ConsoleFilter.FilterType.Source,
@@ -1264,10 +1264,6 @@ Console.ConsoleViewFilter = class {
});
}
- const blockedURLs = Object.keys(this._messageURLFiltersSetting.get());
- const urlFilters = blockedURLs.map(url => ({key: Console.ConsoleFilter.FilterType.Url, text: url, negative: true}));
- parsedFilters = parsedFilters.concat(urlFilters);
-
this._currentFilter.executionContext =
this._filterByExecutionContextSetting.get() ? UI.context.flavor(SDK.ExecutionContext) : null;
this._currentFilter.parsedFilters = parsedFilters;
@@ -1335,30 +1331,12 @@ Console.ConsoleViewFilter = class {
* @param {string} url
*/
addMessageURLFilter(url) {
- const value = this._messageURLFiltersSetting.get();
- value[url] = true;
- this._messageURLFiltersSetting.set(value);
- }
-
- /**
- * @param {string} url
- */
- removeMessageURLFilter(url) {
- let value;
- if (url) {
- value = this._messageURLFiltersSetting.get();
- delete value[url];
- } else {
- value = {};
- }
- this._messageURLFiltersSetting.set(value);
- }
-
- /**
- * @returns {!Object}
- */
- messageURLFilters() {
- return this._messageURLFiltersSetting.get();
+ if (!url)
+ return;
+ const suffix = this._textFilterUI.value() ? ` ${this._textFilterUI.value()}` : '';
+ this._textFilterUI.setValue(`-url:${url}${suffix}`);
+ this._textFilterSetting.set(this._textFilterUI.value());
+ this._onFilterChanged();
}
/**
@@ -1374,7 +1352,6 @@ Console.ConsoleViewFilter = class {
}
reset() {
- this._messageURLFiltersSetting.set({});
this._messageLevelFiltersSetting.set(Console.ConsoleFilter.defaultLevelsFilterValue());
this._filterByExecutionContextSetting.set(false);
this._hideNetworkMessagesSetting.set(false);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleViewMessage.js b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleViewMessage.js
index 1ae28716d97..fdc97909bcd 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleViewMessage.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/ConsoleViewMessage.js
@@ -567,7 +567,7 @@ Console.ConsoleViewMessage = class {
const result = createElement('span');
const description = obj.description || '';
if (description.length > Console.ConsoleViewMessage._MaxTokenizableStringLength)
- result.appendChild(Console.ConsoleViewMessage._createExpandableFragment(description));
+ result.appendChild(UI.createExpandableText(description, Console.ConsoleViewMessage._LongStringVisibleLength));
else
result.createTextChild(description);
if (obj.objectId)
@@ -1368,7 +1368,7 @@ Console.ConsoleViewMessage = class {
*/
static linkifyWithCustomLinkifier(string, linkifier) {
if (string.length > Console.ConsoleViewMessage._MaxTokenizableStringLength)
- return Console.ConsoleViewMessage._createExpandableFragment(string);
+ return UI.createExpandableText(string, Console.ConsoleViewMessage._LongStringVisibleLength);
const container = createDocumentFragment();
const tokens = this._tokenizeMessageText(string);
for (const token of tokens) {
@@ -1393,31 +1393,6 @@ Console.ConsoleViewMessage = class {
}
/**
- * @param {string} text
- * @return {!DocumentFragment}
- */
- static _createExpandableFragment(text) {
- const fragment = createDocumentFragment();
- fragment.textContent = text.slice(0, Console.ConsoleViewMessage._LongStringVisibleLength);
- const hiddenText = text.slice(Console.ConsoleViewMessage._LongStringVisibleLength);
-
- const expandButton = fragment.createChild('span', 'console-inline-button');
- expandButton.setAttribute('data-text', ls`Show ${Number.withThousandsSeparator(hiddenText.length)} more`);
- expandButton.addEventListener('click', () => {
- if (expandButton.parentElement)
- expandButton.parentElement.insertBefore(createTextNode(hiddenText), expandButton);
- expandButton.remove();
- });
-
- const copyButton = fragment.createChild('span', 'console-inline-button');
- copyButton.setAttribute('data-text', ls`Copy`);
- copyButton.addEventListener('click', () => {
- InspectorFrontendHost.copyText(text);
- });
- return fragment;
- }
-
- /**
* @param {string} string
* @return {!DocumentFragment}
*/
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/consolePinPane.css b/chromium/third_party/blink/renderer/devtools/front_end/console/consolePinPane.css
new file mode 100644
index 00000000000..c71d0e75ead
--- /dev/null
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/consolePinPane.css
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+.console-pins {
+ overflow-y: auto;
+ background: var(--toolbar-bg-color);
+}
+
+.console-pins:not(:empty) {
+ border-bottom: 1px solid var(--divider-color);
+ padding: 5px 28px 0 24px;
+}
+
+.console-pin {
+ margin-bottom: 2px;
+ position: relative;
+ user-select: text;
+ flex: none;
+ padding-bottom: 6px;
+}
+
+.console-pin:not(:last-child) {
+ border-bottom: 1px solid #e4e4e4;
+}
+
+.console-pin-name {
+ margin-left: -4px;
+ margin-bottom: 1px;
+ height: auto;
+}
+
+.console-pin-name,
+.console-pin-preview {
+ width: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.console-delete-pin {
+ position: absolute;
+ top: 6px;
+ left: -16px;
+ opacity: 0.5;
+ cursor: pointer;
+}
+
+.console-delete-pin:hover {
+ opacity: 1;
+}
+
+.console-pin-name:focus-within {
+ background: #fff;
+ box-shadow: var(--focus-ring-active-shadow);
+}
+
+.console-pin-name:not(:focus-within):not(:hover) {
+ opacity: 0.6;
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/consoleView.css b/chromium/third_party/blink/renderer/devtools/front_end/console/consoleView.css
index 265e899370d..ecc43036f56 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console/consoleView.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/consoleView.css
@@ -32,7 +32,16 @@
overflow: hidden;
}
-.console-view > .toolbar {
+.console-toolbar-container {
+ display: flex;
+ flex: none;
+}
+
+.console-main-toolbar {
+ flex: 1 1 auto;
+}
+
+.console-toolbar-container > .toolbar {
background-color: var(--toolbar-bg-color);
border-bottom: var(--divider-border);
}
@@ -424,27 +433,6 @@
margin-bottom: -2px;
}
-.console-inline-button {
- background-color: #dedede;
- padding: 2px 4px;
- margin: 0 2px;
- color: #333;
- cursor: pointer;
- border-radius: 3px;
- font-size: 12px;
- font-family: sans-serif;
- white-space: nowrap;
- display: inline-block;
-}
-
-.console-inline-button::after {
- content: attr(data-text);
-}
-
-.console-inline-button:hover {
- background-color: #d5d5d5;
-}
-
.console-searchable-view {
max-height: 100%;
}
@@ -477,3 +465,33 @@
left: -13px;
top: 1px;
}
+
+.console-view-pinpane {
+ flex: none;
+ max-height: 200px;
+}
+
+.command-pin-button::before {
+ content: '\1f4cc';
+}
+
+.command-pin-button {
+ cursor: pointer;
+ position: absolute;
+ top: 1px;
+ right: -40px;
+ opacity: 0;
+ width: 40px;
+}
+
+#console-prompt:hover .command-pin-button {
+ opacity: 0.12;
+}
+
+.-theme-with-dark-background #console-prompt:hover .command-pin-button {
+ opacity: 0.25;
+}
+
+#console-prompt:hover .command-pin-button:hover {
+ opacity: 0.6;
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console/module.json b/chromium/third_party/blink/renderer/devtools/front_end/console/module.json
index 6ff93200ec9..16fd2bdfbcc 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console/module.json
@@ -164,7 +164,7 @@
"title": "Eager evaluation",
"settingName": "consoleEagerEval",
"settingType": "boolean",
- "defaultValue": false,
+ "defaultValue": true,
"options": [
{
"value": true,
@@ -188,6 +188,7 @@
"scripts": [
"ConsoleContextSelector.js",
"ConsoleFilter.js",
+ "ConsolePinPane.js",
"ConsoleSidebar.js",
"ConsoleViewport.js",
"ConsoleViewMessage.js",
@@ -197,6 +198,7 @@
],
"resources": [
"consoleContextSelector.css",
+ "consolePinPane.css",
"consoleSidebar.css",
"consoleView.css"
]
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/console_test_runner/ConsoleTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/console_test_runner/ConsoleTestRunner.js
index 9575313deea..e72a511fa43 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/console_test_runner/ConsoleTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/console_test_runner/ConsoleTestRunner.js
@@ -49,23 +49,32 @@ ConsoleTestRunner.dumpConsoleMessagesIntoArray = function(printOriginatingComman
let classNames;
if (dumpClassNames) {
- classNames = [];
+ classNames = [''];
for (let node = element.firstChild; node; node = node.traverseNextNode(element)) {
if (node.nodeType === Node.ELEMENT_NODE && node.className) {
- classNames.push(node.className.replace('platform-linux', 'platform-*')
- .replace('platform-mac', 'platform-*')
- .replace('platform-windows', 'platform-*'));
+ let depth = 0;
+ let depthTest = node;
+ while (depthTest !== element) {
+ if (depthTest.nodeType === Node.ELEMENT_NODE && depthTest.className)
+ depth++;
+ depthTest = depthTest.parentNodeOrShadowHost();
+ }
+ classNames.push(
+ ' '.repeat(depth) +
+ node.className.replace('platform-linux', 'platform-*')
+ .replace('platform-mac', 'platform-*')
+ .replace('platform-windows', 'platform-*'));
}
}
}
if (ConsoleTestRunner.dumpConsoleTableMessage(uiMessage, false, result)) {
if (dumpClassNames)
- result.push(classNames.join(' > '));
+ result.push(classNames.join('\n'));
} else {
let messageText = formatter(element, message);
messageText = messageText.replace(/VM\d+/g, 'VM');
- result.push(messageText + (dumpClassNames ? ' ' + classNames.join(' > ') : ''));
+ result.push(messageText + (dumpClassNames ? ' ' + classNames.join('\n') : ''));
}
if (printOriginatingCommand && uiMessage.consoleMessage().originatingMessage())
@@ -371,6 +380,15 @@ ConsoleTestRunner.expandConsoleMessages = function(callback, deepFilter, section
};
/**
+ * @param {function(!Element):boolean} deepFilter
+ * @param {function(!ObjectUI.ObjectPropertiesSection):boolean} sectionFilter
+ * @return {!Promise}
+ */
+ConsoleTestRunner.expandConsoleMessagesPromise = function(deepFilter, sectionFilter) {
+ return new Promise(fulfill => ConsoleTestRunner.expandConsoleMessages(fulfill, deepFilter, sectionFilter));
+};
+
+/**
* @param {!Function} callback
*/
ConsoleTestRunner.expandGettersInConsoleMessages = function(callback) {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/devtools_app.html b/chromium/third_party/blink/renderer/devtools/front_end/devtools_app.html
index c0b162b1b15..76b4116dfc6 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/devtools_app.html
+++ b/chromium/third_party/blink/renderer/devtools/front_end/devtools_app.html
@@ -4,7 +4,7 @@
* found in the LICENSE file.
-->
<!doctype html>
-<html>
+<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://chrome-devtools-frontend.appspot.com">
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js
index aceeed54c5d..231a28b4d19 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js
@@ -47,8 +47,8 @@ Elements.ComputedStyleWidget = class extends UI.ThrottledWidget {
const hbox = this.contentElement.createChild('div', 'hbox styles-sidebar-pane-toolbar');
const filterContainerElement = hbox.createChild('div', 'styles-sidebar-pane-filter-box');
- const filterInput = Elements.StylesSidebarPane.createPropertyFilterElement(
- Common.UIString('Filter'), hbox, filterCallback.bind(this), 'styles-filter-engaged');
+ const filterInput =
+ Elements.StylesSidebarPane.createPropertyFilterElement(ls`Filter`, hbox, filterCallback.bind(this));
UI.ARIAUtils.setAccessibleName(filterInput, Common.UIString('Filter Computed Styles'));
filterContainerElement.appendChild(filterInput);
this.setDefaultFocusedElement(filterInput);
@@ -57,6 +57,9 @@ Elements.ComputedStyleWidget = class extends UI.ThrottledWidget {
toolbar.appendToolbarItem(new UI.ToolbarSettingCheckbox(
this._showInheritedComputedStylePropertiesSetting, undefined, Common.UIString('Show all')));
+ this._noMatchesElement = this.contentElement.createChild('div', 'gray-info-message');
+ this._noMatchesElement.textContent = ls`No matching property`;
+
this._propertiesOutline = new UI.TreeOutlineInShadow();
this._propertiesOutline.hideOverflow();
this._propertiesOutline.registerRequiredCSS('elements/computedStyleWidgetTree.css');
@@ -141,8 +144,10 @@ Elements.ComputedStyleWidget = class extends UI.ThrottledWidget {
this._propertiesOutline.removeChildren();
this._linkifier.reset();
const cssModel = this._computedStyleModel.cssModel();
- if (!nodeStyle || !matchedStyles || !cssModel)
+ if (!nodeStyle || !matchedStyles || !cssModel) {
+ this._noMatchesElement.classList.remove('hidden');
return;
+ }
const uniqueProperties = nodeStyle.computedStyle.keysArray();
uniqueProperties.sort(propertySorter);
@@ -336,11 +341,14 @@ Elements.ComputedStyleWidget = class extends UI.ThrottledWidget {
*/
_updateFilter(regex) {
const children = this._propertiesOutline.rootElement().children();
+ let hasMatch = false;
for (const child of children) {
const property = child[Elements.ComputedStyleWidget._propertySymbol];
const matched = !regex || regex.test(property.name) || regex.test(property.value);
child.hidden = !matched;
+ hasMatch |= matched;
}
+ this._noMatchesElement.classList.toggle('hidden', hasMatch);
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsPanel.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsPanel.js
index 570f3b121ce..8979f943dba 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsPanel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsPanel.js
@@ -615,44 +615,6 @@ Elements.ElementsPanel = class extends UI.Panel {
}
/**
- * @override
- * @param {!KeyboardEvent} event
- */
- handleShortcut(event) {
- if (this._treeOutlines.find(to => to.editing()))
- return;
-
- const treeOutline = this._treeOutlines.find(to => !!to.selectedDOMNode());
- if (!treeOutline)
- return;
-
- if (UI.KeyboardShortcut.eventHasCtrlOrMeta(event) && !event.shiftKey &&
- (event.key === 'Z' || event.key === 'z')) { // Z key
- SDK.domModelUndoStack.undo();
- event.handled = true;
- }
-
- const isRedoKey = Host.isMac() ?
- event.metaKey && event.shiftKey && (event.key === 'Z' || event.key === 'z') : // Z key
- event.ctrlKey && (event.key === 'Y' || event.key === 'y'); // Y key
- if (isRedoKey) {
- SDK.domModelUndoStack.redo();
- event.handled = true;
- }
-
- if (event.handled) {
- this._stylesWidget.forceUpdate();
- return;
- }
-
- treeOutline.handleShortcut(event);
- if (event.handled)
- return;
-
- super.handleShortcut(event);
- }
-
- /**
* @param {?SDK.DOMNode} node
* @return {?Elements.ElementsTreeOutline}
*/
@@ -969,6 +931,18 @@ Elements.ElementsActionDelegate = class {
case 'elements.edit-as-html':
treeOutline.toggleEditAsHTML(node);
return true;
+ case 'elements.undo':
+ if (UI.isEditing())
+ return false;
+ SDK.domModelUndoStack.undo();
+ Elements.ElementsPanel.instance()._stylesWidget.forceUpdate();
+ return true;
+ case 'elements.redo':
+ if (UI.isEditing())
+ return false;
+ SDK.domModelUndoStack.redo();
+ Elements.ElementsPanel.instance()._stylesWidget.forceUpdate();
+ return true;
}
return false;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeElement.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeElement.js
index 441adb24d06..ecf3b62f6a7 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeElement.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeElement.js
@@ -809,7 +809,11 @@ Elements.ElementsTreeElement = class extends UI.TreeElement {
editor.widget().show(this._htmlEditElement);
editor.setText(initialValue);
editor.widget().focus();
- editor.widget().element.addEventListener('blur', this._editing.commit, true);
+ editor.widget().element.addEventListener('blur', event => {
+ // The relatedTarget is null when no element gains focus, e.g. switching windows.
+ if (event.relatedTarget)
+ this._editing.commit();
+ }, true);
editor.widget().element.addEventListener('keydown', keydown.bind(this), true);
this.treeOutline.setMultilineEditing(this._editing);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeOutline.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeOutline.js
index cef69395cce..e5c1c4f8401 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeOutline.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeOutline.js
@@ -60,6 +60,7 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
this._element.addEventListener('clipboard-copy', this._onCopyOrCut.bind(this, false), false);
this._element.addEventListener('clipboard-cut', this._onCopyOrCut.bind(this, true), false);
this._element.addEventListener('clipboard-paste', this._onPaste.bind(this), false);
+ this._element.addEventListener('keydown', this._onKeyDown.bind(this), false);
outlineDisclosureElement.appendChild(this._element);
this.element = shadowContainer;
@@ -774,7 +775,13 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
this._updateModifiedNodes();
}
- handleShortcut(event) {
+ /**
+ * @param {!Event} event
+ */
+ _onKeyDown(event) {
+ const keyboardEvent = /** @type {!KeyboardEvent} */ (event);
+ if (UI.isEditing())
+ return;
const node = this.selectedDOMNode();
if (!node)
return;
@@ -782,16 +789,16 @@ Elements.ElementsTreeOutline = class extends UI.TreeOutline {
if (!treeElement)
return;
- if (UI.KeyboardShortcut.eventHasCtrlOrMeta(event) && node.parentNode) {
- if (event.key === 'ArrowUp' && node.previousSibling) {
+ if (UI.KeyboardShortcut.eventHasCtrlOrMeta(keyboardEvent) && node.parentNode) {
+ if (keyboardEvent.key === 'ArrowUp' && node.previousSibling) {
node.moveTo(node.parentNode, node.previousSibling, this.selectNodeAfterEdit.bind(this, treeElement.expanded));
- event.handled = true;
+ keyboardEvent.consume(true);
return;
}
- if (event.key === 'ArrowDown' && node.nextSibling) {
+ if (keyboardEvent.key === 'ArrowDown' && node.nextSibling) {
node.moveTo(
node.parentNode, node.nextSibling.nextSibling, this.selectNodeAfterEdit.bind(this, treeElement.expanded));
- event.handled = true;
+ keyboardEvent.consume(true);
return;
}
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js b/chromium/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js
index 3d0051ca081..b199ff8cf8d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js
@@ -47,6 +47,9 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
this._pendingWidgetToggle = null;
this._toolbarPaneElement = this._createStylesSidebarToolbar();
+ this._noMatchesElement = this.contentElement.createChild('div', 'gray-info-message hidden');
+ this._noMatchesElement.textContent = ls`No matching selector or style`;
+
this._sectionsContainer = this.contentElement.createChild('div');
UI.ARIAUtils.markAsTree(this._sectionsContainer);
this._sectionsContainer.addEventListener('keydown', this._sectionsContainerKeyDown.bind(this), false);
@@ -144,17 +147,15 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
* @param {string} placeholder
* @param {!Element} container
* @param {function(?RegExp)} filterCallback
- * @param {string} activeClassName
* @return {!Element}
*/
- static createPropertyFilterElement(placeholder, container, filterCallback, activeClassName) {
+ static createPropertyFilterElement(placeholder, container, filterCallback) {
const input = createElementWithClass('input');
input.placeholder = placeholder;
function searchHandler() {
const regex = input.value ? new RegExp(input.value.escapeForRegExp(), 'i') : null;
filterCallback(regex);
- container.classList.toggle(activeClassName, !!input.value);
}
input.addEventListener('input', searchHandler, false);
@@ -431,8 +432,10 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
this._sectionBlocks = [];
const node = this.node();
- if (!matchedStyles || !node)
+ if (!matchedStyles || !node) {
+ this._noMatchesElement.classList.remove('hidden');
return;
+ }
this._sectionBlocks =
await this._rebuildSectionsForMatchedStyleRules(/** @type {!SDK.CSSMatchedStyles} */ (matchedStyles));
@@ -475,6 +478,8 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
if (this._filterRegex)
this._updateFilter();
+ else
+ this._noMatchesElement.classList.toggle('hidden', this._sectionBlocks.length > 0);
this._nodeStylesUpdatedForTest(/** @type {!SDK.DOMNode} */ (node), true);
if (this._decorator) {
@@ -579,8 +584,10 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
}
_updateFilter() {
+ let hasAnyVisibleBlock = false;
for (const block of this._sectionBlocks)
- block.updateFilter();
+ hasAnyVisibleBlock |= block.updateFilter();
+ this._noMatchesElement.classList.toggle('hidden', hasAnyVisibleBlock);
}
/**
@@ -615,8 +622,8 @@ Elements.StylesSidebarPane = class extends Elements.ElementsSidebarPane {
const container = this.contentElement.createChild('div', 'styles-sidebar-pane-toolbar-container');
const hbox = container.createChild('div', 'hbox styles-sidebar-pane-toolbar');
const filterContainerElement = hbox.createChild('div', 'styles-sidebar-pane-filter-box');
- const filterInput = Elements.StylesSidebarPane.createPropertyFilterElement(
- Common.UIString('Filter'), hbox, this._onFilterChanged.bind(this), 'styles-filter-engaged');
+ const filterInput =
+ Elements.StylesSidebarPane.createPropertyFilterElement(ls`Filter`, hbox, this._onFilterChanged.bind(this));
UI.ARIAUtils.setAccessibleName(filterInput, Common.UIString('Filter Styles'));
filterContainerElement.appendChild(filterInput);
const toolbar = new UI.Toolbar('styles-pane-toolbar', hbox);
@@ -743,12 +750,16 @@ Elements.SectionBlock = class {
return new Elements.SectionBlock(separatorElement);
}
+ /**
+ * @return {boolean}
+ */
updateFilter() {
let hasAnyVisibleSection = false;
for (const section of this.sections)
hasAnyVisibleSection |= section._updateFilter();
if (this._titleElement)
this._titleElement.classList.toggle('hidden', !hasAnyVisibleSection);
+ return hasAnyVisibleSection;
}
/**
@@ -2118,11 +2129,9 @@ Elements.StylesSidebarPane.CSSPropertyPrompt = class extends UI.TextPrompt {
break;
case 'Enter':
// Accept any available autocompletions and advance to the next field.
- if (this.textWithCurrentSuggestion() !== this.text()) {
- this.tabKeyPressed();
- return;
- }
- break;
+ this.tabKeyPressed();
+ event.preventDefault();
+ return;
}
super.onKeyDown(event);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/computedStyleSidebarPane.css b/chromium/third_party/blink/renderer/devtools/front_end/elements/computedStyleSidebarPane.css
index d6055adf0fb..21a0057e348 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/computedStyleSidebarPane.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/computedStyleSidebarPane.css
@@ -23,14 +23,12 @@
outline: none !important;
border: none;
width: 100%;
- background: transparent;
- margin-left: 4px;
+ background: white;
+ padding-left: 4px;
+ margin: 3px;
}
-.styles-filter-engaged {
- background-color: rgba(255, 255, 0, 0.5);
-}
-
-:host-context(.-theme-with-dark-background) .styles-filter-engaged {
- background-color: hsla(133, 100%, 30%, 0.5);
+.styles-sidebar-pane-filter-box > input:focus,
+.styles-sidebar-pane-filter-box > input:not(:placeholder-shown) {
+ box-shadow: var(--focus-ring-active-shadow);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/elementsPanel.css b/chromium/third_party/blink/renderer/devtools/front_end/elements/elementsPanel.css
index 7029b23f3dc..fb05a163f0a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/elementsPanel.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/elementsPanel.css
@@ -51,7 +51,7 @@
}
.style-panes-wrapper {
- overflow: auto;
+ overflow: hidden auto;
}
.style-panes-wrapper > div:not(:first-child) {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/module.json b/chromium/third_party/blink/renderer/devtools/front_end/elements/module.json
index f789cec02d3..b655b00e9a2 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/module.json
@@ -192,6 +192,42 @@
]
},
{
+ "type": "action",
+ "actionId": "elements.undo",
+ "contextTypes": [
+ "Elements.ElementsPanel"
+ ],
+ "className": "Elements.ElementsActionDelegate",
+ "bindings": [
+ {
+ "platform": "windows,linux",
+ "shortcut": "Ctrl+Z"
+ },
+ {
+ "platform": "mac",
+ "shortcut": "Meta+Z"
+ }
+ ]
+ },
+ {
+ "type": "action",
+ "actionId": "elements.redo",
+ "contextTypes": [
+ "Elements.ElementsPanel"
+ ],
+ "className": "Elements.ElementsActionDelegate",
+ "bindings": [
+ {
+ "platform": "windows,linux",
+ "shortcut": "Ctrl+Y"
+ },
+ {
+ "platform": "mac",
+ "shortcut": "Meta+Shift+Z"
+ }
+ ]
+ },
+ {
"type": "@Elements.MarkerDecorator",
"className": "Elements.ElementsPanel.PseudoStateMarkerDecorator",
"marker": "pseudo-state-marker"
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/elements/stylesSidebarPane.css b/chromium/third_party/blink/renderer/devtools/front_end/elements/stylesSidebarPane.css
index a4f3b7cf703..b6f41b93204 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/elements/stylesSidebarPane.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/elements/stylesSidebarPane.css
@@ -34,12 +34,10 @@
background-color: hsl(215, 25%, 91%);
}
-.styles-filter-engaged,
.styles-section .simple-selector.filter-match {
background-color: rgba(255, 255, 0, 0.5);
}
-:host-context(.-theme-with-dark-background) .styles-filter-engaged,
:host-context(.-theme-with-dark-background) .styles-section .simple-selector.filter-match {
background-color: hsla(133, 100%, 30%, 0.5);
}
@@ -179,7 +177,8 @@
box-shadow: var(--focus-ring-inactive-shadow);
}
-.styles-sidebar-pane-filter-box > input:focus {
+.styles-sidebar-pane-filter-box > input:focus,
+.styles-sidebar-pane-filter-box > input:not(:placeholder-shown) {
box-shadow: var(--focus-ring-active-shadow);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeToolbar.js b/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeToolbar.js
index 17bc7cdaf5d..d8ee0a7f031 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeToolbar.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeToolbar.js
@@ -48,7 +48,7 @@ Emulation.DeviceModeToolbar = class {
this._fillModeToolbar(modeToolbar);
rightContainer.createChild('div', 'device-mode-toolbar-spacer');
const optionsToolbar = new UI.Toolbar('device-mode-toolbar-options', rightContainer);
- optionsToolbar.makeWrappable(true);
+ optionsToolbar.makeWrappable();
this._fillOptionsToolbar(optionsToolbar);
this._emulatedDevicesList = Emulation.EmulatedDevicesList.instance();
@@ -189,12 +189,11 @@ Emulation.DeviceModeToolbar = class {
* @param {!UI.Toolbar} toolbar
*/
_fillOptionsToolbar(toolbar) {
+ toolbar.appendToolbarItem(
+ this._wrapToolbarItem(createElementWithClass('div', 'device-mode-empty-toolbar-element')));
const moreOptionsButton = new UI.ToolbarMenuButton(this._appendOptionsMenuItems.bind(this));
moreOptionsButton.setTitle(Common.UIString('More options'));
toolbar.appendToolbarItem(moreOptionsButton);
-
- toolbar.appendToolbarItem(
- this._wrapToolbarItem(createElementWithClass('div', 'device-mode-empty-toolbar-element')));
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/externs.js b/chromium/third_party/blink/renderer/devtools/front_end/externs.js
index 7f815d34ea2..52658203b54 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/externs.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/externs.js
@@ -544,7 +544,7 @@ CodeMirror.prototype = {
};
/** @type {!{cursorDiv: Element, lineSpace: Element}} */
CodeMirror.prototype.display;
-/** @type {!{mode: string}} */
+/** @type {!{mode: string, lineWrapping: boolean}} */
CodeMirror.prototype.options;
/** @type {!Object} */
CodeMirror.Pass;
@@ -557,6 +557,36 @@ CodeMirror.overlayMode = function(mode1, mode2, squashSpans) {};
CodeMirror.defineMode = function(modeName, modeConstructor) {};
CodeMirror.startState = function(mode) {};
CodeMirror.copyState = function(mode, state) {};
+CodeMirror.inputStyles = {};
+CodeMirror.inputStyles.textarea = class {
+ constructor() {
+ /** @type {!HTMLTextAreaElement} */
+ this.textarea;
+ this.prevInput = '';
+ this.composing = false;
+ this.contextMenuPending = false;
+ /** @type {!CodeMirror} */
+ this.cm;
+ }
+ /**
+ * @param {!Object} display
+ */
+ init(display) {
+ }
+
+ /**
+ * @param {boolean=} typing
+ */
+ reset(typing) {
+ }
+
+ /**
+ * @return {boolean}
+ */
+ poll() {
+ return false;
+ }
+};
/** @typedef {{canceled: boolean, from: !CodeMirror.Pos, to: !CodeMirror.Pos, text: string, origin: string, cancel: function()}} */
CodeMirror.BeforeChangeObject;
@@ -644,6 +674,13 @@ Element.prototype.animate = function(keyframes, timing) {};
/**
* @param {...!Node} nodes
* @return {undefined}
+ * @see https://dom.spec.whatwg.org/#dom-parentnode-append
+ */
+Element.prototype.append = function(nodes) {};
+
+/**
+ * @param {...!Node} nodes
+ * @return {undefined}
* @see https://dom.spec.whatwg.org/#dom-parentnode-prepend
*/
Element.prototype.prepend = function(nodes) {};
@@ -997,3 +1034,17 @@ DetailsRenderer.NodeDetailsJSON;
* }}
*/
DetailsRenderer.OpportunitySummary;
+
+
+// Clipboard API
+
+/** @constructor */
+const Clipboard = function() {};
+/**
+ * @param {string} data
+ * @return {!Promise}
+ */
+Clipboard.prototype.writeText = function(data) {};
+
+/** @type {Clipboard} */
+Navigator.prototype.clipboard;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/heap_profiler_test_runner/HeapProfilerTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/heap_profiler_test_runner/HeapProfilerTestRunner.js
index f6e224e5c4e..9d2ce468d1d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/heap_profiler_test_runner/HeapProfilerTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/heap_profiler_test_runner/HeapProfilerTestRunner.js
@@ -543,6 +543,10 @@ HeapProfilerTestRunner.expandRow = function(row, callback) {
})();
};
+HeapProfilerTestRunner.expandRowPromise = function(row) {
+ return new Promise(resolve => HeapProfilerTestRunner.expandRow(row, resolve));
+};
+
HeapProfilerTestRunner.findAndExpandGCRoots = function(callback) {
HeapProfilerTestRunner.findAndExpandRow('(GC roots)', callback);
};
@@ -551,11 +555,12 @@ HeapProfilerTestRunner.findAndExpandWindow = function(callback) {
HeapProfilerTestRunner.findAndExpandRow('Window', callback);
};
-HeapProfilerTestRunner.findAndExpandRow = function(name, callback) {
- callback = TestRunner.safeWrap(callback);
+HeapProfilerTestRunner.findAndExpandRow = async function(name, callback) {
const row = HeapProfilerTestRunner.findRow(name);
- TestRunner.assertEquals(true, !!row, '"' + name + '" row');
- HeapProfilerTestRunner.expandRow(row, callback);
+ TestRunner.assertEquals(true, !!row, `"${name}" row`);
+ await HeapProfilerTestRunner.expandRowPromise(row);
+ TestRunner.safeWrap(callback)(row);
+ return row;
};
HeapProfilerTestRunner.findButtonsNode = function(row, startNode) {
@@ -563,16 +568,11 @@ HeapProfilerTestRunner.findButtonsNode = function(row, startNode) {
if (!node.selectable && node.showNext)
return node;
}
-
return null;
};
HeapProfilerTestRunner.findRow = function(name, parent) {
- function matcher(x) {
- return x._name === name;
- }
-
- return HeapProfilerTestRunner.findMatchingRow(matcher, parent);
+ return HeapProfilerTestRunner.findMatchingRow(node => node._name === name, parent);
};
HeapProfilerTestRunner.findMatchingRow = function(matcher, parent) {
@@ -587,10 +587,12 @@ HeapProfilerTestRunner.findMatchingRow = function(matcher, parent) {
};
HeapProfilerTestRunner.switchToView = function(title, callback) {
- callback = TestRunner.safeWrap(callback);
- const view = UI.panels.heap_profiler.visibleView;
- view._changePerspectiveAndWait(title).then(callback);
- HeapProfilerTestRunner._currentGrid().scrollContainer.style.height = '10000px';
+ return new Promise(resolve => {
+ callback = TestRunner.safeWrap(callback);
+ const view = UI.panels.heap_profiler.visibleView;
+ view._changePerspectiveAndWait(title).then(callback).then(resolve);
+ HeapProfilerTestRunner._currentGrid().scrollContainer.style.height = '10000px';
+ });
};
HeapProfilerTestRunner.takeAndOpenSnapshot = async function(generator, callback) {
@@ -615,6 +617,36 @@ HeapProfilerTestRunner.takeAndOpenSnapshot = async function(generator, callback)
profileType._takeHeapSnapshot();
};
+/**
+ * @return {!Promise<!Profiler.HeapProfileHeader>}
+ */
+HeapProfilerTestRunner.takeSnapshotPromise = function() {
+ return new Promise(resolve => {
+ const heapProfileType = Profiler.ProfileTypeRegistry.instance.heapSnapshotProfileType;
+ heapProfileType.addEventListener(Profiler.HeapSnapshotProfileType.SnapshotReceived, finishHeapSnapshot);
+ heapProfileType._takeHeapSnapshot();
+
+ function finishHeapSnapshot() {
+ const profiles = heapProfileType.getProfiles();
+ if (!profiles.length)
+ throw 'FAILED: no profiles found.';
+ if (profiles.length > 1)
+ throw `FAILED: wrong number of recorded profiles was found. profiles.length = ${profiles.length}`;
+ const profile = profiles[0];
+ UI.panels.heap_profiler.showProfile(profile);
+
+ const dataGrid = HeapProfilerTestRunner.currentProfileView()._dataGrid;
+ dataGrid.addEventListener(Profiler.HeapSnapshotSortableDataGrid.Events.SortingComplete, sortingComplete, null);
+
+ function sortingComplete() {
+ dataGrid.removeEventListener(
+ Profiler.HeapSnapshotSortableDataGrid.Events.SortingComplete, sortingComplete, null);
+ resolve(profile);
+ }
+ }
+ });
+};
+
HeapProfilerTestRunner.viewColumns = function() {
return HeapProfilerTestRunner._currentGrid()._columnsArray;
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHost.js b/chromium/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHost.js
index 22139d7244e..b12d858aa15 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHost.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHost.js
@@ -157,9 +157,21 @@ Host.InspectorFrontendHostStub = class {
/**
* @override
* @param {string} text
+ * @suppressGlobalPropertiesCheck
*/
copyText(text) {
- Common.console.error('Clipboard is not enabled in hosted mode. Please inspect using chrome://inspect');
+ if (navigator.clipboard) {
+ navigator.clipboard.writeText(text);
+ } else if (document.queryCommandSupported('copy')) {
+ const input = document.createElement('input');
+ input.value = text;
+ document.body.appendChild(input);
+ input.select();
+ document.execCommand('copy');
+ document.body.removeChild(input);
+ } else {
+ Common.console.error('Clipboard is not enabled in hosted mode. Please inspect using chrome://inspect');
+ }
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/inspector.html b/chromium/third_party/blink/renderer/devtools/front_end/inspector.html
index 26ea6599cfc..c4da1f5a913 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/inspector.html
+++ b/chromium/third_party/blink/renderer/devtools/front_end/inspector.html
@@ -4,7 +4,7 @@
* found in the LICENSE file.
-->
<!doctype html>
-<html>
+<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://chrome-devtools-frontend.appspot.com">
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/InspectorMain.js b/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/InspectorMain.js
index e1ce1676667..f7cbe534626 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/InspectorMain.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/inspector_main/InspectorMain.js
@@ -31,9 +31,10 @@ InspectorMain.InspectorMain = class extends Common.Object {
}
_connectAndCreateMainTarget() {
+ const isNodeJS = !!Runtime.queryParam('v8only');
const target = SDK.targetManager.createTarget(
- 'main', Common.UIString('Main'), this._capabilitiesForMainTarget(), this._createMainConnection.bind(this),
- null);
+ 'main', Common.UIString('Main'), this._capabilitiesForMainTarget(), this._createMainConnection.bind(this), null,
+ isNodeJS);
target.runtimeAgent().runIfWaitingForDebugger();
}
@@ -41,6 +42,8 @@ InspectorMain.InspectorMain = class extends Common.Object {
* @return {number}
*/
_capabilitiesForMainTarget() {
+ if (Runtime.queryParam('v8only'))
+ return SDK.Target.Capability.JS;
return SDK.Target.Capability.Browser | SDK.Target.Capability.DOM | SDK.Target.Capability.DeviceEmulation |
SDK.Target.Capability.Emulation | SDK.Target.Capability.Input | SDK.Target.Capability.JS |
SDK.Target.Capability.Log | SDK.Target.Capability.Network | SDK.Target.Capability.ScreenCapture |
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/integration_test_runner.html b/chromium/third_party/blink/renderer/devtools/front_end/integration_test_runner.html
index 780a48a4861..f982e1be2fe 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/integration_test_runner.html
+++ b/chromium/third_party/blink/renderer/devtools/front_end/integration_test_runner.html
@@ -4,7 +4,7 @@
* found in the LICENSE file.
-->
<!doctype html>
-<html>
+<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://chrome-devtools-frontend.appspot.com">
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/js_app.html b/chromium/third_party/blink/renderer/devtools/front_end/js_app.html
index dff8942f540..ef077a4b647 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/js_app.html
+++ b/chromium/third_party/blink/renderer/devtools/front_end/js_app.html
@@ -4,7 +4,7 @@
* found in the LICENSE file.
-->
<!doctype html>
-<html>
+<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://chrome-devtools-frontend.appspot.com">
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/js_main/JsMain.js b/chromium/third_party/blink/renderer/devtools/front_end/js_main/JsMain.js
index 8b990804731..59a109da113 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/js_main/JsMain.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/js_main/JsMain.js
@@ -12,7 +12,7 @@ JsMain.JsMain = class extends Common.Object {
run() {
Host.userMetrics.actionTaken(Host.UserMetrics.Action.ConnectToNodeJSDirectly);
const target = SDK.targetManager.createTarget(
- 'main', Common.UIString('Main'), SDK.Target.Capability.JS, this._createMainConnection.bind(this), null);
+ 'main', Common.UIString('Main'), SDK.Target.Capability.JS, this._createMainConnection.bind(this), null, true /* isNodeJS */);
target.runtimeAgent().runIfWaitingForDebugger();
InspectorFrontendHost.connectionReady();
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/main/Main.js b/chromium/third_party/blink/renderer/devtools/front_end/main/Main.js
index 642849355ee..c275c351749 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/main/Main.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/main/Main.js
@@ -114,6 +114,7 @@ Main.Main = class {
Runtime.experiments.register('nativeHeapProfiler', 'Native memory sampling heap profiler', true);
Runtime.experiments.register('networkSearch', 'Network search');
Runtime.experiments.register('oopifInlineDOM', 'OOPIF: inline DOM ', true);
+ Runtime.experiments.register('pinnedExpressions', 'Pinned expressions in Console', true);
Runtime.experiments.register('protocolMonitor', 'Protocol Monitor');
Runtime.experiments.register('sourceDiff', 'Source diff');
Runtime.experiments.register('sourcesPrettyPrint', 'Automatically pretty print in the Sources Panel');
@@ -145,7 +146,7 @@ Main.Main = class {
}
Runtime.experiments.setDefaultExperiments(
- ['colorContrastRatio', 'stepIntoAsync', 'oopifInlineDOM', 'consoleBelowPrompt']);
+ ['colorContrastRatio', 'stepIntoAsync', 'oopifInlineDOM', 'consoleBelowPrompt', 'timelineTracingJSProfile']);
}
/**
@@ -383,19 +384,8 @@ Main.Main = class {
}
_postDocumentKeyDown(event) {
- if (event.handled)
- return;
-
- if (!UI.Dialog.hasInstance() && UI.inspectorView.currentPanelDeprecated() &&
- UI.inspectorView.currentPanelDeprecated().hasFocus()) {
- UI.inspectorView.currentPanelDeprecated().handleShortcut(event);
- if (event.handled) {
- event.consume(true);
- return;
- }
- }
-
- UI.shortcutRegistry.handleShortcut(event);
+ if (!event.handled)
+ UI.shortcutRegistry.handleShortcut(event);
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/ThrottlingManager.js b/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/ThrottlingManager.js
index ab8834b8c21..c2f0faa8689 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/ThrottlingManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/ThrottlingManager.js
@@ -251,6 +251,14 @@ MobileThrottling.ThrottlingManager.ActionDelegate = class {
SDK.multitargetNetworkManager.setNetworkConditions(SDK.NetworkManager.NoThrottlingConditions);
return true;
}
+ if (actionId === 'network-conditions.network-low-end-mobile') {
+ SDK.multitargetNetworkManager.setNetworkConditions(SDK.NetworkManager.Slow3GConditions);
+ return true;
+ }
+ if (actionId === 'network-conditions.network-mid-tier-mobile') {
+ SDK.multitargetNetworkManager.setNetworkConditions(SDK.NetworkManager.Fast3GConditions);
+ return true;
+ }
if (actionId === 'network-conditions.network-offline') {
SDK.multitargetNetworkManager.setNetworkConditions(SDK.NetworkManager.OfflineConditions);
return true;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/module.json b/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/module.json
index 217bc85b4c0..8971d4c8971 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/module.json
+++ b/chromium/third_party/blink/renderer/devtools/front_end/mobile_throttling/module.json
@@ -12,7 +12,23 @@
"category": "Network",
"title": "Go offline",
"className": "MobileThrottling.ThrottlingManager.ActionDelegate",
- "tags": "device"
+ "tags": "device, throttling"
+ },
+ {
+ "type": "action",
+ "actionId": "network-conditions.network-low-end-mobile",
+ "category": "Network",
+ "title": "Enable slow 3G throttling",
+ "className": "MobileThrottling.ThrottlingManager.ActionDelegate",
+ "tags": "device, throttling"
+ },
+ {
+ "type": "action",
+ "actionId": "network-conditions.network-mid-tier-mobile",
+ "category": "Network",
+ "title": "Enable fast 3G throttling",
+ "className": "MobileThrottling.ThrottlingManager.ActionDelegate",
+ "tags": "device, throttling"
},
{
"type": "action",
@@ -20,7 +36,7 @@
"category": "Network",
"title": "Go online",
"className": "MobileThrottling.ThrottlingManager.ActionDelegate",
- "tags": "device"
+ "tags": "device, throttling"
},
{
"type": "view",
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ndb_app.html b/chromium/third_party/blink/renderer/devtools/front_end/ndb_app.html
index 13977f75c6d..aca9d950a26 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ndb_app.html
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ndb_app.html
@@ -4,7 +4,7 @@
* found in the LICENSE file.
-->
<!doctype html>
-<html>
+<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://chrome-devtools-frontend.appspot.com">
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js
index 8a306a11ec5..cbc6fb46691 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js
@@ -864,6 +864,9 @@ Network.NetworkRequestNode = class extends Network.NetworkNode {
case Protocol.Network.BlockedReason.ContentType:
reason = Common.UIString('content-type');
break;
+ case Protocol.Network.BlockedReason.CollapsedByClient:
+ reason = Common.UIString('extension');
+ break;
}
this._setTextAndTitle(cell, Common.UIString('(blocked:%s)', reason));
} else if (this._request.finished) {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js
index 4811440b215..19bc05754ef 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js
@@ -134,6 +134,8 @@ Network.NetworkLogView = class extends UI.VBox {
this._dataGrid = this._columns.dataGrid();
this._setupDataGrid();
this._columns.sortByCurrentColumn();
+ filterBar.filterButton().addEventListener(
+ UI.ToolbarButton.Events.Click, this._dataGrid.scheduleUpdate.bind(this._dataGrid, true /* isFromUser */));
this._summaryBarElement = this.element.createChild('div', 'network-summary-bar');
@@ -152,26 +154,8 @@ Network.NetworkLogView = class extends UI.VBox {
Common.moduleSetting('network.group-by-frame').addChangeListener(() => this._updateGroupByFrame());
this._filterBar = filterBar;
- this._searchHint = new UI.HBox();
- this._searchHint.element.classList.add('open-search-view');
- this._filterStringSearchReminder = this._createSearchPrompt();
- this._updateSearchPrompt();
- }
-
- _createSearchPrompt() {
- const text = this._searchHint.contentElement.createChild('div', 'search-suggestion');
- text.createChild('span').textContent = ls`Search headers and response bodies for `;
- const filterString = text.createChild('strong');
- const button = UI.createTextButton('Find All', () => this._openSearchView());
- this._searchHint.contentElement.appendChild(button);
- this._filterBar.element.addEventListener('keydown', event => {
- if (event.key === 'ArrowDown')
- button.focus();
- });
- return filterString;
}
-
_updateGroupByFrame() {
const value = Common.moduleSetting('network.group-by-frame').get();
this._setGrouping(value ? 'Frame' : null);
@@ -602,7 +586,6 @@ Network.NetworkLogView = class extends UI.VBox {
this.removeAllNodeHighlights();
this._parseFilterQuery(this._textFilterUI.value());
this._filterRequests();
- this._updateSearchPrompt();
}
_showRecordingHint() {
@@ -1773,23 +1756,6 @@ Network.NetworkLogView = class extends UI.VBox {
return command.join(' ');
}
-
- _updateSearchPrompt() {
- const filterString = this._filterBar.visible() ? this._textFilterUI.value() : '';
- if (filterString.length) {
- const filterBarElement = this._filterBar.element;
- this._searchHint.show(/** @type {!Element} */ (filterBarElement.parentElement), filterBarElement.nextSibling);
- this._filterStringSearchReminder.textContent = filterString;
- } else {
- this._searchHint.hideWidget();
- }
- }
-
- _openSearchView() {
- const filterString = this._textFilterUI.value();
- this._textFilterUI.setValue('');
- Network.SearchNetworkView.openSearch(filterString, true);
- }
};
Network.NetworkLogView._isFilteredOutSymbol = Symbol('isFilteredOut');
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogViewColumns.js b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogViewColumns.js
index c00716e47e1..4f2d5ba67dd 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogViewColumns.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkLogViewColumns.js
@@ -40,6 +40,8 @@ Network.NetworkLogViewColumns = class {
this._calculatorsMap.set(Network.NetworkLogViewColumns._calculatorTypes.Time, timeCalculator);
this._calculatorsMap.set(Network.NetworkLogViewColumns._calculatorTypes.Duration, durationCalculator);
+ this._lastWheelTime = 0;
+
this._setupDataGrid();
this._setupWaterfall();
}
@@ -166,8 +168,10 @@ Network.NetworkLogViewColumns = class {
_onMouseWheel(shouldConsume, event) {
if (shouldConsume)
event.consume(true);
- this._activeScroller.scrollTop -= event.wheelDeltaY;
+ const hasRecentWheel = Date.now() - this._lastWheelTime < 80;
+ this._activeScroller.scrollBy({top: -event.wheelDeltaY, behavior: hasRecentWheel ? 'instant' : 'smooth'});
this._syncScrollers();
+ this._lastWheelTime = Date.now();
}
_syncScrollers() {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkPanel.js b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkPanel.js
index a926ad389e7..1d2fc78d0f1 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkPanel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkPanel.js
@@ -247,6 +247,7 @@ Network.NetworkPanel = class extends UI.Panel {
*/
_createThrottlingConditionsSelect() {
const toolbarItem = new UI.ToolbarComboBox(null);
+ toolbarItem.setTitle(ls`Throttling`);
toolbarItem.setMaxWidth(160);
MobileThrottling.throttlingManager().decorateSelectWithNetworkThrottling(toolbarItem.selectElement());
return toolbarItem;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkWaterfallColumn.js b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkWaterfallColumn.js
index d904b26bbce..aea813d5a32 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkWaterfallColumn.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/NetworkWaterfallColumn.js
@@ -11,7 +11,7 @@ Network.NetworkWaterfallColumn = class extends UI.VBox {
this.registerRequiredCSS('network/networkWaterfallColumn.css');
this._canvas = this.contentElement.createChild('canvas');
- this._canvas.tabIndex = 1;
+ this._canvas.tabIndex = 0;
this.setDefaultFocusedElement(this._canvas);
this._canvasPosition = this._canvas.getBoundingClientRect();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/SignedExchangeInfoView.js b/chromium/third_party/blink/renderer/devtools/front_end/network/SignedExchangeInfoView.js
index 5770a9536d9..9de48346d50 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/SignedExchangeInfoView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/SignedExchangeInfoView.js
@@ -22,24 +22,35 @@ Network.SignedExchangeInfoView = class extends UI.VBox {
root.expandTreeElementsWhenArrowing = true;
this.element.appendChild(root.element);
+ /** @type {!Map<number|undefined, !Set<string>>} */
+ const errorFieldSetMap = new Map();
+
if (signedExchangeInfo.errors && signedExchangeInfo.errors.length) {
const errorMessagesCategory = new Network.SignedExchangeInfoView.Category(root, Common.UIString('Errors'));
- for (const errorMessage of signedExchangeInfo.errors) {
+ for (const error of signedExchangeInfo.errors) {
const fragment = createDocumentFragment();
fragment.appendChild(UI.Icon.create('smallicon-error', 'prompt-icon'));
- fragment.createChild('div', 'error-log').textContent = errorMessage;
+ fragment.createChild('div', 'error-log').textContent = error.message;
errorMessagesCategory.createLeaf(fragment);
+ if (error.errorField) {
+ let errorFieldSet = errorFieldSetMap.get(error.signatureIndex);
+ if (!errorFieldSet) {
+ errorFieldSet = new Set();
+ errorFieldSetMap.set(error.signatureIndex, errorFieldSet);
+ }
+ errorFieldSet.add(error.errorField);
+ }
}
}
+
+ const titleElement = createDocumentFragment();
+ titleElement.createChild('div', 'header-name').textContent = Common.UIString('Signed HTTP exchange');
+ const learnMoreNode =
+ UI.XLink.create('https://github.com/WICG/webpackage', Common.UIString('Learn\xa0more'), 'header-toggle');
+ titleElement.appendChild(learnMoreNode);
+ const headerCategory = new Network.SignedExchangeInfoView.Category(root, titleElement);
if (signedExchangeInfo.header) {
const header = signedExchangeInfo.header;
- const titleElement = createDocumentFragment();
- titleElement.createChild('div', 'header-name').textContent = Common.UIString('Signed HTTP exchange');
- const learnMoreNode =
- UI.XLink.create('https://github.com/WICG/webpackage', Common.UIString('Learn\xa0more'), 'header-toggle');
- titleElement.appendChild(learnMoreNode);
-
- const headerCategory = new Network.SignedExchangeInfoView.Category(root, titleElement);
const redirectDestination = request.redirectDestination();
const requestURLElement = this._formatHeader(Common.UIString('Request URL'), header.requestUrl);
if (redirectDestination) {
@@ -61,16 +72,44 @@ Network.SignedExchangeInfoView = class extends UI.VBox {
}
this._responseHeadersItem.expand();
- for (const signature of header.signatures) {
+ for (let i = 0; i < header.signatures.length; ++i) {
+ const errorFieldSet = errorFieldSetMap.get(i) || new Set();
+ const signature = header.signatures[i];
const signatureCategory = new Network.SignedExchangeInfoView.Category(root, Common.UIString('Signature'));
signatureCategory.createLeaf(this._formatHeader(Common.UIString('Label'), signature.label));
- signatureCategory.createLeaf(this._formatHeader(Common.UIString('Integrity'), signature.integrity));
- signatureCategory.createLeaf(this._formatHeader(Common.UIString('Certificate URL'), signature.certUrl));
- signatureCategory.createLeaf(this._formatHeader(Common.UIString('Validity URL'), signature.validityUrl));
- signatureCategory.createLeaf().title =
- this._formatHeader(Common.UIString('Date'), new Date(1000 * signature.date).toUTCString());
- signatureCategory.createLeaf().title =
- this._formatHeader(Common.UIString('Expires'), new Date(1000 * signature.expires).toUTCString());
+ signatureCategory.createLeaf(this._formatHeaderForHexData(
+ Common.UIString('Signature'), signature.signature,
+ errorFieldSet.has(Protocol.Network.SignedExchangeErrorField.SignatureSig)));
+
+ if (signature.certUrl) {
+ const certURLElement = this._formatHeader(
+ Common.UIString('Certificate URL'), signature.certUrl,
+ errorFieldSet.has(Protocol.Network.SignedExchangeErrorField.SignatureCertUrl));
+ if (signature.certificates) {
+ const viewCertLink = certURLElement.createChild('span', 'devtools-link header-toggle');
+ viewCertLink.textContent = Common.UIString('View certificate');
+ viewCertLink.addEventListener(
+ 'click', InspectorFrontendHost.showCertificateViewer.bind(null, signature.certificates), false);
+ }
+ signatureCategory.createLeaf(certURLElement);
+ }
+ signatureCategory.createLeaf(this._formatHeader(
+ Common.UIString('Integrity'), signature.integrity,
+ errorFieldSet.has(Protocol.Network.SignedExchangeErrorField.SignatureIntegrity)));
+ if (signature.certSha256) {
+ signatureCategory.createLeaf(this._formatHeaderForHexData(
+ Common.UIString('Certificate SHA256'), signature.certSha256,
+ errorFieldSet.has(Protocol.Network.SignedExchangeErrorField.SignatureCertSha256)));
+ }
+ signatureCategory.createLeaf(this._formatHeader(
+ Common.UIString('Validity URL'), signature.validityUrl,
+ errorFieldSet.has(Protocol.Network.SignedExchangeErrorField.SignatureValidityUrl)));
+ signatureCategory.createLeaf().title = this._formatHeader(
+ Common.UIString('Date'), new Date(1000 * signature.date).toUTCString(),
+ errorFieldSet.has(Protocol.Network.SignedExchangeErrorField.SignatureTimestamps));
+ signatureCategory.createLeaf().title = this._formatHeader(
+ Common.UIString('Expires'), new Date(1000 * signature.expires).toUTCString(),
+ errorFieldSet.has(Protocol.Network.SignedExchangeErrorField.SignatureTimestamps));
}
}
if (signedExchangeInfo.securityDetails) {
@@ -88,13 +127,40 @@ Network.SignedExchangeInfoView = class extends UI.VBox {
/**
* @param {string} name
* @param {string} value
+ * @param {boolean=} highlighted
+ * @return {!DocumentFragment}
+ */
+ _formatHeader(name, value, highlighted) {
+ const fragment = createDocumentFragment();
+ const nameElement = fragment.createChild('div', 'header-name');
+ nameElement.textContent = name + ': ';
+ fragment.createChild('span', 'header-separator');
+ const valueElement = fragment.createChild('div', 'header-value source-code');
+ valueElement.textContent = value;
+ if (highlighted) {
+ nameElement.classList.add('error-field');
+ valueElement.classList.add('error-field');
+ }
+ return fragment;
+ }
+
+ /**
+ * @param {string} name
+ * @param {string} value
+ * @param {boolean=} highlighted
* @return {!DocumentFragment}
*/
- _formatHeader(name, value) {
+ _formatHeaderForHexData(name, value, highlighted) {
const fragment = createDocumentFragment();
- fragment.createChild('div', 'header-name').textContent = name + ': ';
+ const nameElement = fragment.createChild('div', 'header-name');
+ nameElement.textContent = name + ': ';
fragment.createChild('span', 'header-separator');
- fragment.createChild('div', 'header-value source-code').textContent = value;
+ const valueElement = fragment.createChild('div', 'header-value source-code hex-data');
+ valueElement.textContent = value.replace(/(.{2})/g, '$1 ');
+ if (highlighted) {
+ nameElement.classList.add('error-field');
+ valueElement.classList.add('error-field');
+ }
return fragment;
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network/signedExchangeInfoTree.css b/chromium/third_party/blink/renderer/devtools/front_end/network/signedExchangeInfoTree.css
index 23933fc7c4f..9d4ea3a4a64 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network/signedExchangeInfoTree.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network/signedExchangeInfoTree.css
@@ -80,3 +80,13 @@
vertical-align: top;
white-space: pre-wrap;
}
+
+.tree-outline .hex-data {
+ display: block;
+ word-break: break-word;
+ margin-left: 20px;
+}
+
+.tree-outline .error-field {
+ color: red;
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/network_test_runner/NetworkTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/network_test_runner/NetworkTestRunner.js
index e3d80000263..869853fea89 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/network_test_runner/NetworkTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/network_test_runner/NetworkTestRunner.js
@@ -91,7 +91,7 @@ NetworkTestRunner.dumpNetworkRequestsWithSignedExchangeInfo = function() {
}
if (request.signedExchangeInfo().errors) {
for (const errorMessage of request.signedExchangeInfo().errors)
- TestRunner.addResult(` Error: ${errorMessage}`);
+ TestRunner.addResult(` Error: ${JSON.stringify(errorMessage)}`);
}
}
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/node_app.html b/chromium/third_party/blink/renderer/devtools/front_end/node_app.html
index 6b9ddcd6857..71c675c0e72 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/node_app.html
+++ b/chromium/third_party/blink/renderer/devtools/front_end/node_app.html
@@ -4,7 +4,7 @@
* found in the LICENSE file.
-->
<!doctype html>
-<html>
+<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://chrome-devtools-frontend.appspot.com">
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/node_main/NodeMain.js b/chromium/third_party/blink/renderer/devtools/front_end/node_main/NodeMain.js
index 28dc0b480ca..3a2cb44d46d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/node_main/NodeMain.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/node_main/NodeMain.js
@@ -12,7 +12,8 @@ NodeMain.NodeMain = class extends Common.Object {
run() {
Host.userMetrics.actionTaken(Host.UserMetrics.Action.ConnectToNodeJSFromFrontend);
const target = SDK.targetManager.createTarget(
- 'main', Common.UIString('Main'), SDK.Target.Capability.Target, params => new SDK.MainConnection(params), null);
+ 'main', Common.UIString('Main'), SDK.Target.Capability.Target, params => new SDK.MainConnection(params), null,
+ false /* isNodeJS */);
target.setInspectedURL('Node.js');
InspectorFrontendHost.connectionReady();
}
@@ -99,7 +100,7 @@ NodeMain.NodeChildTargetManager = class extends SDK.SDKModel {
attachedToTarget(sessionId, targetInfo, waitingForDebugger) {
const target = this._targetManager.createTarget(
targetInfo.targetId, Common.UIString('Node.js: %s', targetInfo.url), SDK.Target.Capability.JS,
- this._createChildConnection.bind(this, this._targetAgent, sessionId), this._parentTarget);
+ this._createChildConnection.bind(this, this._targetAgent, sessionId), this._parentTarget, true /* isNodeJS */);
target.runtimeAgent().runIfWaitingForDebugger();
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptAutocomplete.js b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptAutocomplete.js
index 74763da9651..cddc8a81818 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptAutocomplete.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/JavaScriptAutocomplete.js
@@ -602,3 +602,100 @@ ObjectUI.JavaScriptAutocomplete = class {
ObjectUI.JavaScriptAutocomplete.CompletionGroup;
ObjectUI.javaScriptAutocomplete = new ObjectUI.JavaScriptAutocomplete();
+
+ObjectUI.JavaScriptAutocompleteConfig = class {
+ /**
+ * @param {!UI.TextEditor} editor
+ */
+ constructor(editor) {
+ this._editor = editor;
+ }
+
+ /**
+ * @param {!UI.TextEditor} editor
+ * @return {!UI.AutocompleteConfig}
+ */
+ static createConfigForEditor(editor) {
+ const autocomplete = new ObjectUI.JavaScriptAutocompleteConfig(editor);
+ return {
+ substituteRangeCallback: autocomplete._substituteRange.bind(autocomplete),
+ suggestionsCallback: autocomplete._suggestionsCallback.bind(autocomplete),
+ tooltipCallback: autocomplete._tooltipCallback.bind(autocomplete),
+ };
+ }
+
+ /**
+ * @param {number} lineNumber
+ * @param {number} columnNumber
+ * @return {?TextUtils.TextRange}
+ */
+ _substituteRange(lineNumber, columnNumber) {
+ const token = this._editor.tokenAtTextPosition(lineNumber, columnNumber);
+ if (token && token.type === 'js-string')
+ return new TextUtils.TextRange(lineNumber, token.startColumn, lineNumber, columnNumber);
+
+ const lineText = this._editor.line(lineNumber);
+ let index;
+ for (index = columnNumber - 1; index >= 0; index--) {
+ if (' =:[({;,!+-*/&|^<>.\t\r\n'.indexOf(lineText.charAt(index)) !== -1)
+ break;
+ }
+ return new TextUtils.TextRange(lineNumber, index + 1, lineNumber, columnNumber);
+ }
+
+ /**
+ * @param {!TextUtils.TextRange} queryRange
+ * @param {!TextUtils.TextRange} substituteRange
+ * @param {boolean=} force
+ * @return {!Promise<!UI.SuggestBox.Suggestions>}
+ */
+ async _suggestionsCallback(queryRange, substituteRange, force) {
+ const query = this._editor.text(queryRange);
+ const before = this._editor.text(new TextUtils.TextRange(0, 0, queryRange.startLine, queryRange.startColumn));
+ const token = this._editor.tokenAtTextPosition(substituteRange.startLine, substituteRange.startColumn);
+ if (token) {
+ const excludedTokens = new Set(['js-comment', 'js-string-2', 'js-def']);
+ const trimmedBefore = before.trim();
+ if (!trimmedBefore.endsWith('[') && !trimmedBefore.match(/\.\s*(get|set|delete)\s*\(\s*$/))
+ excludedTokens.add('js-string');
+ if (!trimmedBefore.endsWith('.'))
+ excludedTokens.add('js-property');
+ if (excludedTokens.has(token.type))
+ return [];
+ }
+ const queryAndAfter = this._editor.line(queryRange.startLine).substring(queryRange.startColumn);
+
+ const words = await ObjectUI.javaScriptAutocomplete.completionsForTextInCurrentContext(before, query, force);
+ if (!force && queryAndAfter && queryAndAfter !== query &&
+ words.some(word => queryAndAfter.startsWith(word.text) && query.length !== word.text.length))
+ return [];
+ return words;
+ }
+
+ /**
+ * @param {number} lineNumber
+ * @param {number} columnNumber
+ * @return {!Promise<?Element>}
+ */
+ async _tooltipCallback(lineNumber, columnNumber) {
+ const before = this._editor.text(new TextUtils.TextRange(0, 0, lineNumber, columnNumber));
+ const result = await ObjectUI.javaScriptAutocomplete.argumentsHint(before);
+ if (!result)
+ return null;
+ const argumentIndex = result.argumentIndex;
+ const tooltip = createElement('div');
+ for (const args of result.args) {
+ const argumentsElement = createElement('span');
+ for (let i = 0; i < args.length; i++) {
+ if (i === argumentIndex || (i < argumentIndex && args[i].startsWith('...')))
+ argumentsElement.appendChild(UI.html`<b>${args[i]}</b>`);
+ else
+ argumentsElement.createTextChild(args[i]);
+ if (i < args.length - 1)
+ argumentsElement.createTextChild(', ');
+ }
+ tooltip.appendChild(UI.html`<div class='source-code'>\u0192(${argumentsElement})</div>`);
+ }
+ return tooltip;
+ }
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPopoverHelper.js b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPopoverHelper.js
index a649f89a29a..5fe611ed978 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPopoverHelper.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPopoverHelper.js
@@ -50,84 +50,10 @@ ObjectUI.ObjectPopoverHelper = class {
* @param {!UI.GlassPane} popover
* @return {!Promise<?ObjectUI.ObjectPopoverHelper>}
*/
- static buildObjectPopover(result, popover) {
- let fulfill;
- const promise = new Promise(x => fulfill = x);
-
- /**
- * @param {!SDK.RemoteObject} funcObject
- * @param {!Element} popoverContentElement
- * @param {!Element} popoverValueElement
- * @param {?Array.<!SDK.RemoteObjectProperty>} properties
- * @param {?Array.<!SDK.RemoteObjectProperty>} internalProperties
- */
- function didGetFunctionProperties(
- funcObject, popoverContentElement, popoverValueElement, properties, internalProperties) {
- if (internalProperties) {
- for (let i = 0; i < internalProperties.length; i++) {
- if (internalProperties[i].name === '[[TargetFunction]]') {
- funcObject = internalProperties[i].value;
- break;
- }
- }
- }
- ObjectUI.ObjectPropertiesSection.formatObjectAsFunction(funcObject, popoverValueElement, true);
- funcObject.debuggerModel()
- .functionDetailsPromise(funcObject)
- .then(didGetFunctionDetails.bind(null, popoverContentElement));
- }
-
- /**
- * @param {!Element} popoverContentElement
- * @param {?SDK.DebuggerModel.FunctionDetails} response
- */
- function didGetFunctionDetails(popoverContentElement, response) {
- if (!response) {
- fulfill(null);
- return;
- }
-
- const container = createElementWithClass('div', 'object-popover-container');
- const title = container.createChild('div', 'function-popover-title source-code');
- const functionName = title.createChild('span', 'function-name');
- functionName.textContent = UI.beautifyFunctionName(response.functionName);
-
- const rawLocation = response.location;
- const linkContainer = title.createChild('div', 'function-title-link-container');
- const sourceURL = rawLocation && rawLocation.script() ? rawLocation.script().sourceURL : null;
- let linkifier = null;
- if (rawLocation && sourceURL) {
- linkifier = new Components.Linkifier();
- linkContainer.appendChild(linkifier.linkifyRawLocation(rawLocation, sourceURL));
- }
- container.appendChild(popoverContentElement);
- popover.contentElement.appendChild(container);
- fulfill(new ObjectUI.ObjectPopoverHelper(linkifier, false));
- }
-
+ static async buildObjectPopover(result, popover) {
const description = result.description.trimEnd(ObjectUI.ObjectPopoverHelper.MaxPopoverTextLength);
let popoverContentElement = null;
- if (result.type !== 'object') {
- popoverContentElement = createElement('span');
- UI.appendStyle(popoverContentElement, 'object_ui/objectValue.css');
- UI.appendStyle(popoverContentElement, 'object_ui/objectPopover.css');
- const valueElement = popoverContentElement.createChild('span', 'monospace object-value-' + result.type);
- valueElement.style.whiteSpace = 'pre';
-
- if (result.type === 'string')
- valueElement.createTextChildren('"', description, '"');
- else if (result.type !== 'function')
- valueElement.textContent = description;
-
- if (result.type === 'function') {
- result.getOwnProperties(
- false /* generatePreview */,
- didGetFunctionProperties.bind(null, result, popoverContentElement, valueElement));
- return promise;
- }
- popover.contentElement.appendChild(popoverContentElement);
- fulfill(new ObjectUI.ObjectPopoverHelper(null, false));
- } else {
+ if (result.type === 'object') {
let linkifier = null;
let resultHighlightedAsDOM = false;
if (result.subtype === 'node') {
@@ -153,9 +79,46 @@ ObjectUI.ObjectPopoverHelper = class {
popover.setMaxContentSize(new UI.Size(300, 250));
popover.setSizeBehavior(UI.GlassPane.SizeBehavior.SetExactSize);
popover.contentElement.appendChild(popoverContentElement);
- fulfill(new ObjectUI.ObjectPopoverHelper(linkifier, resultHighlightedAsDOM));
+ return new ObjectUI.ObjectPopoverHelper(linkifier, resultHighlightedAsDOM);
+ }
+
+ popoverContentElement = createElement('span');
+ UI.appendStyle(popoverContentElement, 'object_ui/objectValue.css');
+ UI.appendStyle(popoverContentElement, 'object_ui/objectPopover.css');
+ const valueElement = popoverContentElement.createChild('span', 'monospace object-value-' + result.type);
+ valueElement.style.whiteSpace = 'pre';
+
+ if (result.type === 'string')
+ valueElement.createTextChildren(`"${description}"`);
+ else if (result.type !== 'function')
+ valueElement.textContent = description;
+
+ if (result.type !== 'function') {
+ popover.contentElement.appendChild(popoverContentElement);
+ return new ObjectUI.ObjectPopoverHelper(null, false);
+ }
+
+ ObjectUI.ObjectPropertiesSection.formatObjectAsFunction(result, valueElement, true);
+ const response = await result.debuggerModel().functionDetailsPromise(result);
+ if (!response)
+ return null;
+
+ const container = createElementWithClass('div', 'object-popover-container');
+ const title = container.createChild('div', 'function-popover-title source-code');
+ const functionName = title.createChild('span', 'function-name');
+ functionName.textContent = UI.beautifyFunctionName(response.functionName);
+
+ const rawLocation = response.location;
+ const linkContainer = title.createChild('div', 'function-title-link-container');
+ const sourceURL = rawLocation && rawLocation.script() && rawLocation.script().sourceURL;
+ let linkifier = null;
+ if (sourceURL) {
+ linkifier = new Components.Linkifier();
+ linkContainer.appendChild(linkifier.linkifyRawLocation(rawLocation, sourceURL));
}
- return promise;
+ container.appendChild(popoverContentElement);
+ popover.contentElement.appendChild(container);
+ return new ObjectUI.ObjectPopoverHelper(linkifier, false);
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js
index e37467a56f8..88a7f85ddff 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js
@@ -129,12 +129,10 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
*/
static valueElementForFunctionDescription(description, includePreview, defaultName) {
const valueElement = createElementWithClass('span', 'object-value-function');
- let text = '';
- if (description) {
- text = description.replace(/^function [gs]et /, 'function ')
- .replace(/^function [gs]et\(/, 'function\(')
- .replace(/^[gs]et /, '');
- }
+ description = description || '';
+ const text = description.replace(/^function [gs]et /, 'function ')
+ .replace(/^function [gs]et\(/, 'function\(')
+ .replace(/^[gs]et /, '');
defaultName = defaultName || '';
// This set of best-effort regular expressions captures common function descriptions.
@@ -178,7 +176,7 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
} else {
addElements('\u0192', text, nameAndArguments(text));
}
- valueElement.title = description || '';
+ valueElement.title = description.trimEnd(500);
return valueElement;
/**
@@ -264,8 +262,10 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
if (value.preview && showPreview) {
const previewFormatter = new ObjectUI.RemoteObjectPreviewFormatter();
previewFormatter.appendObjectPreview(valueElement, value.preview, false /* isEntry */);
+ } else if (description.length > ObjectUI.ObjectPropertiesSection._maxRenderableStringLength) {
+ valueElement.appendChild(UI.createExpandableText(description, 50));
} else {
- valueElement.setTextContentTruncatedIfNeeded(description);
+ valueElement.textContent = description;
}
}
@@ -294,8 +294,12 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
*/
function createStringElement() {
const valueElement = createElementWithClass('span', 'object-value-string');
+ const text = description.replace(/\n/g, '\u21B5');
valueElement.createChild('span', 'object-value-string-quote').textContent = '"';
- valueElement.createTextChild('').setTextContentTruncatedIfNeeded(description.replace(/\n/g, '\u21B5'));
+ if (description.length > ObjectUI.ObjectPropertiesSection._maxRenderableStringLength)
+ valueElement.appendChild(UI.createExpandableText(text, 50));
+ else
+ valueElement.createTextChild(text);
valueElement.createChild('span', 'object-value-string-quote').textContent = '"';
valueElement.title = description || '';
return valueElement;
@@ -406,6 +410,8 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
/** @const */
ObjectUI.ObjectPropertiesSection._arrayLoadThreshold = 100;
+/** @const */
+ObjectUI.ObjectPropertiesSection._maxRenderableStringLength = 10000;
/**
@@ -734,9 +740,9 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
if (!this.expandedValueElement)
return;
if (value)
- this.listItemElement.replaceChild(this.expandedValueElement, this.valueElement);
+ this._rowContainer.replaceChild(this.expandedValueElement, this.valueElement);
else
- this.listItemElement.replaceChild(this.valueElement, this.expandedValueElement);
+ this._rowContainer.replaceChild(this.valueElement, this.expandedValueElement);
}
/**
@@ -768,9 +774,6 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
this._updatePropertyPath();
- const separatorElement = createElementWithClass('span', 'object-properties-section-separator');
- separatorElement.textContent = ': ';
-
if (this.property.value) {
const showPreview = this.property.name !== '__proto__';
this.valueElement = ObjectUI.ObjectPropertiesSection.createValueElementWithCustomSupport(
@@ -789,17 +792,27 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
this.expandedValueElement = this._createExpandedValueElement(this.property.value);
this.listItemElement.removeChildren();
- this.listItemElement.appendChildren(this.nameElement, separatorElement, this.valueElement);
+ this._rowContainer = UI.html`<span>${this.nameElement}: ${this.valueElement}</span>`;
+ this.listItemElement.appendChild(this._rowContainer);
}
_updatePropertyPath() {
if (this.nameElement.title)
return;
+ const name = this.property.name;
+
+ if (this.property.synthetic) {
+ this.nameElement.title = name;
+ return;
+ }
+
const useDotNotation = /^(_|\$|[A-Z])(_|\$|[A-Z]|\d)*$/i;
const isInteger = /^[1-9]\d*$/;
- const name = this.property.name;
- const parentPath = this.parent.nameElement ? this.parent.nameElement.title : '';
+
+ const parentPath =
+ (this.parent.nameElement && !this.parent.property.synthetic) ? this.parent.nameElement.title : '';
+
if (useDotNotation.test(name))
this.nameElement.title = parentPath ? `${parentPath}.${name}` : name;
else if (isInteger.test(name))
@@ -818,7 +831,7 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
contextMenu.appendApplicableItems(this.property.symbol);
if (this.property.value)
contextMenu.appendApplicableItems(this.property.value);
- if (this.nameElement && this.nameElement.title) {
+ if (!this.property.synthetic && this.nameElement && this.nameElement.title) {
const copyPathHandler = InspectorFrontendHost.copyText.bind(InspectorFrontendHost, this.nameElement.title);
contextMenu.clipboardSection().appendItem(ls`Copy property path`, copyPathHandler);
}
@@ -833,7 +846,7 @@ ObjectUI.ObjectPropertyTreeElement = class extends UI.TreeElement {
if (this._prompt || !this.treeOutline._editable || this._readOnly)
return;
- this._editableDiv = this.listItemElement.createChild('span', 'editable-div');
+ this._editableDiv = this._rowContainer.createChild('span', 'editable-div');
let text = this.property.value.description;
if (this.property.value.type === 'string' && typeof text === 'string')
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/objectPropertiesSection.css b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/objectPropertiesSection.css
index 73c0ee3e4b1..6b4df5f92e9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/object_ui/objectPropertiesSection.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/object_ui/objectPropertiesSection.css
@@ -4,11 +4,6 @@
* found in the LICENSE file.
*/
-.object-properties-section-separator {
- flex-shrink: 0;
- padding-right: 5px;
-}
-
.object-properties-section-dimmed {
opacity: 0.6;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/FlameChart.js b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/FlameChart.js
index e782d5a3480..327fd7a722b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/FlameChart.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/perf_ui/FlameChart.js
@@ -81,7 +81,7 @@ PerfUI.FlameChart = class extends UI.VBox {
this._viewportElement = this._chartViewport.viewportElement;
this._canvas = /** @type {!HTMLCanvasElement} */ (this._viewportElement.createChild('canvas'));
- this._canvas.tabIndex = 1;
+ this._canvas.tabIndex = 0;
this.setDefaultFocusedElement(this._canvas);
this._canvas.addEventListener('mousemove', this._onMouseMove.bind(this), false);
this._canvas.addEventListener('mouseout', this._onMouseOut.bind(this), false);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/platform/utilities.js b/chromium/third_party/blink/renderer/devtools/front_end/platform/utilities.js
index 89f18ce14af..fb0d8d1eaa9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/platform/utilities.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/platform/utilities.js
@@ -837,7 +837,6 @@ String.sprintf = function(format, var_arg) {
*/
String.tokenizeFormatString = function(format, formatters) {
const tokens = [];
- let substitutionIndex = 0;
function addStringToken(str) {
if (!str)
@@ -852,61 +851,51 @@ String.tokenizeFormatString = function(format, formatters) {
tokens.push({type: 'specifier', specifier: specifier, precision: precision, substitutionIndex: substitutionIndex});
}
- let index = 0;
- for (let precentIndex = format.indexOf('%', index); precentIndex !== -1; precentIndex = format.indexOf('%', index)) {
- if (format.length === index) // unescaped % sign at the end of the format string.
- break;
- addStringToken(format.substring(index, precentIndex));
- index = precentIndex + 1;
+ function addAnsiColor(code) {
+ const types = {3: 'color', 9: 'colorLight', 4: 'bgColor', 10: 'bgColorLight'};
+ const colorCodes = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'lightGray', '', 'default'];
+ const colorCodesLight =
+ ['darkGray', 'lightRed', 'lightGreen', 'lightYellow', 'lightBlue', 'lightMagenta', 'lightCyan', 'white', ''];
+ const colors = {color: colorCodes, colorLight: colorCodesLight, bgColor: colorCodes, bgColorLight: colorCodesLight};
+ const type = types[Math.floor(code / 10)];
+ if (!type)
+ return;
+ const color = colors[type][code % 10];
+ if (!color)
+ return;
+ tokens.push({
+ type: 'specifier',
+ specifier: 'c',
+ value: {description: (type.startsWith('bg') ? 'background : ' : 'color: ') + color}
+ });
+ }
- if (format[index] === '%') {
- // %% escape sequence.
+ let textStart = 0;
+ let substitutionIndex = 0;
+ const re =
+ new RegExp(`%%|%(?:(\\d+)\\$)?(?:\\.(\\d*))?([${Object.keys(formatters).join('')}])|\\u001b\\[(\\d+)m`, 'g');
+ for (let match = re.exec(format); !!match; match = re.exec(format)) {
+ const matchStart = match.index;
+ if (matchStart > textStart)
+ addStringToken(format.substring(textStart, matchStart));
+
+ if (match[0] === '%%') {
addStringToken('%');
- ++index;
- continue;
- }
-
- if (String.isDigitAt(format, index)) {
- // The first character is a number, it might be a substitution index.
- const number = parseInt(format.substring(index), 10);
- while (String.isDigitAt(format, index))
- ++index;
-
- // If the number is greater than zero and ends with a "$",
- // then this is a substitution index.
- if (number > 0 && format[index] === '$') {
- substitutionIndex = (number - 1);
- ++index;
- }
- }
-
- let precision = -1;
- if (format[index] === '.') {
- // This is a precision specifier. If no digit follows the ".",
- // then the precision should be zero.
- ++index;
- precision = parseInt(format.substring(index), 10);
- if (isNaN(precision))
- precision = 0;
-
- while (String.isDigitAt(format, index))
- ++index;
- }
-
- if (!(format[index] in formatters)) {
- addStringToken(format.substring(precentIndex, index + 1));
- ++index;
- continue;
+ } else if (match[0].startsWith('%')) {
+ // eslint-disable-next-line no-unused-vars
+ const [_, substitionString, precisionString, specifierString] = match;
+ if (substitionString && Number(substitionString) > 0)
+ substitutionIndex = Number(substitionString) - 1;
+ const precision = precisionString ? Number(precisionString) : -1;
+ addSpecifierToken(specifierString, precision, substitutionIndex);
+ ++substitutionIndex;
+ } else {
+ const code = Number(match[4]);
+ addAnsiColor(code);
}
-
- addSpecifierToken(format[index], precision, substitutionIndex);
-
- ++substitutionIndex;
- ++index;
+ textStart = matchStart + match[0].length;
}
-
- addStringToken(format.substring(index));
-
+ addStringToken(format.substring(textStart));
return tokens;
};
@@ -961,7 +950,7 @@ String.vsprintf = function(format, substitutions) {
* @template T, Q
*/
String.format = function(format, substitutions, formatters, initialValue, append, tokenizedFormat) {
- if (!format || !substitutions || !substitutions.length)
+ if (!format || ((!substitutions || !substitutions.length) && format.search(/\u001b\[(\d+)m/) === -1))
return {formattedResult: append(initialValue, format), unusedSubstitutions: substitutions};
function prettyFunctionName() {
@@ -993,7 +982,7 @@ String.format = function(format, substitutions, formatters, initialValue, append
continue;
}
- if (token.substitutionIndex >= substitutions.length) {
+ if (!token.value && token.substitutionIndex >= substitutions.length) {
// If there are not enough substitutions for the current substitutionIndex
// just output the format specifier literally and move on.
error(
@@ -1003,16 +992,17 @@ String.format = function(format, substitutions, formatters, initialValue, append
continue;
}
- usedSubstitutionIndexes[token.substitutionIndex] = true;
+ if (!token.value)
+ usedSubstitutionIndexes[token.substitutionIndex] = true;
if (!(token.specifier in formatters)) {
// Encountered an unsupported format character, treat as a string.
warn('unsupported format character \u201C' + token.specifier + '\u201D. Treating as a string.');
- result = append(result, substitutions[token.substitutionIndex]);
+ result = append(result, token.value ? '' : substitutions[token.substitutionIndex]);
continue;
}
- result = append(result, formatters[token.specifier](substitutions[token.substitutionIndex], token));
+ result = append(result, formatters[token.specifier](token.value || substitutions[token.substitutionIndex], token));
}
const unusedSubstitutions = [];
@@ -1204,13 +1194,10 @@ Multimap.prototype = {
/**
* @param {K} key
- * @return {!Set.<!V>}
+ * @return {!Set<!V>}
*/
get: function(key) {
- let result = this._map.get(key);
- if (!result)
- result = new Set();
- return result;
+ return this._map.get(key) || new Set();
},
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfileView.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfileView.js
index 0d5d6419282..4662fcb6404 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfileView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfileView.js
@@ -17,6 +17,11 @@ Profiler.HeapProfileView = class extends Profiler.ProfileView {
const views = [
Profiler.ProfileView.ViewTypes.Flame, Profiler.ProfileView.ViewTypes.Heavy, Profiler.ProfileView.ViewTypes.Tree
];
+ const isNativeProfile = [
+ Profiler.SamplingNativeHeapProfileType.TypeId, Profiler.SamplingNativeHeapSnapshotType.TypeId
+ ].includes(profileHeader.profileType().id);
+ if (isNativeProfile)
+ views.push(Profiler.ProfileView.ViewTypes.Text);
this.initialize(new Profiler.HeapProfileView.NodeFormatter(this), views);
}
@@ -40,7 +45,38 @@ Profiler.HeapProfileView = class extends Profiler.ProfileView {
* @return {!PerfUI.FlameChartDataProvider}
*/
createFlameChartDataProvider() {
- return new Profiler.HeapFlameChartDataProvider(this.profile, this._profileHeader._heapProfilerModel);
+ return new Profiler.HeapFlameChartDataProvider(this.profile, this._profileHeader.heapProfilerModel());
+ }
+
+ /**
+ * @override
+ * @param {!UI.SimpleView} view
+ */
+ populateTextView(view) {
+ const guides = '+!:|';
+ let text = `Sampling memory profile.\n\nDate/Time: ${new Date()}\n` +
+ `Report Version: 7\nNode weight: 1 KiB\n----\n\nCall graph:\n`;
+ const sortedChildren = this.profile.root.children.sort((a, b) => b.total - a.total);
+ for (const child of sortedChildren)
+ printTree(' ', child !== sortedChildren.peekLast(), child);
+ view.contentElement.createChild('pre', 'profile-text-view monospace').textContent = text;
+
+ /**
+ * @param {string} padding
+ * @param {boolean} drawGuide
+ * @param {!SDK.ProfileNode} node
+ */
+ function printTree(padding, drawGuide, node) {
+ const isAddress = node.functionName.startsWith('0x');
+ const functionName = isAddress ? '???' : node.functionName;
+ const address = isAddress ? node.functionName : '???';
+ text += `${padding}${Math.round(node.total / 1024)} ${functionName} [${address}]\n`;
+ const guideChar = drawGuide ? guides[padding.length / 2 % guides.length] : ' ';
+ const nextPadding = padding + guideChar + ' ';
+ const sortedChildren = node.children.sort((a, b) => b.total - a.total);
+ for (const child of sortedChildren)
+ printTree(nextPadding, child !== sortedChildren.peekLast(), child);
+ }
}
};
@@ -109,7 +145,7 @@ Profiler.SamplingHeapProfileTypeBase = class extends Profiler.ProfileType {
async stopRecordingProfile() {
this._recording = false;
- if (!this.profileBeingRecorded() || !this.profileBeingRecorded()._heapProfilerModel)
+ if (!this.profileBeingRecorded() || !this.profileBeingRecorded().heapProfilerModel())
return;
this.profileBeingRecorded().updateStatus(Common.UIString('Stopping\u2026'));
@@ -178,7 +214,7 @@ Profiler.SamplingHeapProfileType = class extends Profiler.SamplingHeapProfileTyp
* @override
*/
_startSampling() {
- this.profileBeingRecorded()._heapProfilerModel.startSampling();
+ this.profileBeingRecorded().heapProfilerModel().startSampling();
}
/**
@@ -186,7 +222,7 @@ Profiler.SamplingHeapProfileType = class extends Profiler.SamplingHeapProfileTyp
* return {!Promise<!Protocol.HeapProfiler.SamplingHeapProfile>}
*/
_stopSampling() {
- return this.profileBeingRecorded()._heapProfilerModel.stopSampling();
+ return this.profileBeingRecorded().heapProfilerModel().stopSampling();
}
};
@@ -213,7 +249,7 @@ Profiler.SamplingNativeHeapProfileType = class extends Profiler.SamplingHeapProf
* @override
*/
_startSampling() {
- this.profileBeingRecorded()._heapProfilerModel.startNativeSampling();
+ this.profileBeingRecorded().heapProfilerModel().startNativeSampling();
}
/**
@@ -221,7 +257,7 @@ Profiler.SamplingNativeHeapProfileType = class extends Profiler.SamplingHeapProf
* return {!Promise<!Protocol.HeapProfiler.SamplingHeapProfile>}
*/
_stopSampling() {
- return this.profileBeingRecorded()._heapProfilerModel.stopNativeSampling();
+ return this.profileBeingRecorded().heapProfilerModel().stopNativeSampling();
}
};
@@ -231,9 +267,11 @@ Profiler.SamplingNativeHeapProfileType.TypeId = 'SamplingNativeHeapRecording';
* @unrestricted
*/
Profiler.SamplingNativeHeapSnapshotType = class extends Profiler.SamplingHeapProfileTypeBase {
- constructor() {
- super(Profiler.SamplingNativeHeapSnapshotType.TypeId, ls`Native memory allocation snapshot`);
- Profiler.SamplingNativeHeapSnapshotType.instance = this;
+ /**
+ * @param {string} processType
+ */
+ constructor(processType) {
+ super(Profiler.SamplingNativeHeapSnapshotType.TypeId, ls`Native memory allocation snapshot (${processType})`);
}
/**
@@ -273,13 +311,13 @@ Profiler.SamplingNativeHeapSnapshotType = class extends Profiler.SamplingHeapPro
if (!heapProfilerModel)
return;
- const profile = new Profiler.SamplingHeapProfileHeader(
- heapProfilerModel, this, Common.UIString('Snapshot %d', this.nextProfileUid()));
+ const profile =
+ new Profiler.SamplingHeapProfileHeader(heapProfilerModel, this, ls`Snapshot ${this.nextProfileUid()}`);
this.setProfileBeingRecorded(profile);
this.addProfile(profile);
- profile.updateStatus(Common.UIString('Snapshotting\u2026'));
+ profile.updateStatus(ls`Snapshotting\u2026`);
- const protocolProfile = await heapProfilerModel.takeNativeSnapshot();
+ const protocolProfile = await this._takeNativeSnapshot(/** @type {!SDK.HeapProfilerModel} */ (heapProfilerModel));
const recordedProfile = this.profileBeingRecorded();
if (recordedProfile) {
console.assert(protocolProfile);
@@ -290,10 +328,50 @@ Profiler.SamplingNativeHeapSnapshotType = class extends Profiler.SamplingHeapPro
this.dispatchEventToListeners(Profiler.ProfileType.Events.ProfileComplete, recordedProfile);
}
+
+ /**
+ * @param {!SDK.HeapProfilerModel} heapProfilerModel
+ * @return {!Promise<!Protocol.HeapProfiler.SamplingHeapProfile>}
+ */
+ _takeNativeSnapshot(heapProfilerModel) {
+ throw 'Not implemented';
+ }
};
Profiler.SamplingNativeHeapSnapshotType.TypeId = 'SamplingNativeHeapSnapshot';
+Profiler.SamplingNativeHeapSnapshotBrowserType = class extends Profiler.SamplingNativeHeapSnapshotType {
+ constructor() {
+ super(ls`Browser`);
+ Profiler.SamplingNativeHeapSnapshotBrowserType.instance = this;
+ }
+
+ /**
+ * @override
+ * @param {!SDK.HeapProfilerModel} heapProfilerModel
+ * @return {!Promise<!Protocol.HeapProfiler.SamplingHeapProfile>}
+ */
+ _takeNativeSnapshot(heapProfilerModel) {
+ return heapProfilerModel.takeNativeBrowserSnapshot();
+ }
+};
+
+Profiler.SamplingNativeHeapSnapshotRendererType = class extends Profiler.SamplingNativeHeapSnapshotType {
+ constructor() {
+ super(ls`Renderer`);
+ Profiler.SamplingNativeHeapSnapshotRendererType.instance = this;
+ }
+
+ /**
+ * @override
+ * @param {!SDK.HeapProfilerModel} heapProfilerModel
+ * @return {!Promise<!Protocol.HeapProfiler.SamplingHeapProfile>}
+ */
+ async _takeNativeSnapshot(heapProfilerModel) {
+ return await heapProfilerModel.takeNativeSnapshot();
+ }
+};
+
/**
* @unrestricted
*/
@@ -324,6 +402,13 @@ Profiler.SamplingHeapProfileHeader = class extends Profiler.WritableProfileHeade
protocolProfile() {
return this._protocolProfile;
}
+
+ /**
+ * @return {?SDK.HeapProfilerModel}
+ */
+ heapProfilerModel() {
+ return this._heapProfilerModel;
+ }
};
/**
@@ -415,7 +500,7 @@ Profiler.HeapProfileView.NodeFormatter = class {
* @return {?Element}
*/
linkifyNode(node) {
- const heapProfilerModel = this._profileView._profileHeader._heapProfilerModel;
+ const heapProfilerModel = this._profileView._profileHeader.heapProfilerModel();
return this._profileView.linkifier().maybeLinkifyConsoleCallFrame(
heapProfilerModel ? heapProfilerModel.target() : null, node.profileNode.callFrame, 'profile-node-file');
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfilerPanel.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfilerPanel.js
index c3ae83dbe4a..0951dd56f8d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfilerPanel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapProfilerPanel.js
@@ -11,8 +11,11 @@ Profiler.HeapProfilerPanel = class extends Profiler.ProfilesPanel {
const registry = Profiler.ProfileTypeRegistry.instance;
const profileTypes =
[registry.heapSnapshotProfileType, registry.trackingHeapSnapshotProfileType, registry.samplingHeapProfileType];
- if (Runtime.experiments.isEnabled('nativeHeapProfiler'))
- profileTypes.push(registry.samplingNativeHeapProfileType, registry.samplingNativeHeapSnapshotType);
+ if (Runtime.experiments.isEnabled('nativeHeapProfiler')) {
+ profileTypes.push(registry.samplingNativeHeapProfileType);
+ profileTypes.push(registry.samplingNativeHeapSnapshotRendererType);
+ profileTypes.push(registry.samplingNativeHeapSnapshotBrowserType);
+ }
super('heap_profiler', profileTypes, 'profiler.heap-toggle-recording');
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotDataGrids.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotDataGrids.js
index f87c6fe9579..71e007b5fe5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotDataGrids.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotDataGrids.js
@@ -40,6 +40,15 @@ Profiler.HeapSnapshotSortableDataGrid = class extends DataGrid.DataGrid {
// TODO(allada) This entire class needs to be converted to use the templates in DataGridNode.
super(columns);
this._dataDisplayDelegate = dataDisplayDelegate;
+ const tooltips = [
+ ['distance', ls`Distance from window object`], ['shallowSize', ls`Size of the object itself in bytes`],
+ ['retainedSize', ls`Size of the object plus the graph it retains in bytes`]
+ ];
+ for (const info of tooltips) {
+ const headerCell = this.headerTableHeader(info[0]);
+ if (headerCell)
+ headerCell.setAttribute('title', info[1]);
+ }
/**
* @type {number}
@@ -63,6 +72,13 @@ Profiler.HeapSnapshotSortableDataGrid = class extends DataGrid.DataGrid {
}
/**
+ * @return {!Profiler.ProfileType.DataDisplayDelegate}
+ */
+ dataDisplayDelegate() {
+ return this._dataDisplayDelegate;
+ }
+
+ /**
* @return {!HeapSnapshotModel.NodeFilter}
*/
nodeFilter() {
@@ -136,7 +152,7 @@ Profiler.HeapSnapshotSortableDataGrid = class extends DataGrid.DataGrid {
}
/**
- * @return {!Array.<!Profiler.HeapSnapshotGridNode>}
+ * @return {!Array<!Profiler.HeapSnapshotGridNode>}
*/
topLevelNodes() {
return this.rootNode().children;
@@ -555,20 +571,18 @@ Profiler.HeapSnapshotContainmentDataGrid = class extends Profiler.HeapSnapshotSo
* @param {!Array.<!DataGrid.DataGrid.ColumnDescriptor>=} columns
*/
constructor(dataDisplayDelegate, columns) {
- columns =
- columns || (/** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
- {id: 'object', title: Common.UIString('Object'), disclosure: true, sortable: true},
- {id: 'distance', title: Common.UIString('Distance'), width: '70px', sortable: true, fixedWidth: true},
- {id: 'shallowSize', title: Common.UIString('Shallow Size'), width: '110px', sortable: true, fixedWidth: true},
- {
- id: 'retainedSize',
- title: Common.UIString('Retained Size'),
- width: '110px',
- sortable: true,
- fixedWidth: true,
- sort: DataGrid.DataGrid.Order.Descending
- }
- ]));
+ columns = columns || (/** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
+ {id: 'object', title: ls`Object`, disclosure: true, sortable: true},
+ {id: 'distance', title: ls`Distance`, width: '70px', sortable: true, fixedWidth: true},
+ {id: 'shallowSize', title: ls`Shallow Size`, width: '110px', sortable: true, fixedWidth: true}, {
+ id: 'retainedSize',
+ title: ls`Retained Size`,
+ width: '110px',
+ sortable: true,
+ fixedWidth: true,
+ sort: DataGrid.DataGrid.Order.Descending
+ }
+ ]));
super(dataDisplayDelegate, columns);
}
@@ -607,16 +621,16 @@ Profiler.HeapSnapshotRetainmentDataGrid = class extends Profiler.HeapSnapshotCon
*/
constructor(dataDisplayDelegate) {
const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
- {id: 'object', title: Common.UIString('Object'), disclosure: true, sortable: true}, {
+ {id: 'object', title: ls`Object`, disclosure: true, sortable: true}, {
id: 'distance',
- title: Common.UIString('Distance'),
+ title: ls`Distance`,
width: '70px',
sortable: true,
fixedWidth: true,
sort: DataGrid.DataGrid.Order.Ascending
},
- {id: 'shallowSize', title: Common.UIString('Shallow Size'), width: '110px', sortable: true, fixedWidth: true},
- {id: 'retainedSize', title: Common.UIString('Retained Size'), width: '110px', sortable: true, fixedWidth: true}
+ {id: 'shallowSize', title: ls`Shallow Size`, width: '110px', sortable: true, fixedWidth: true},
+ {id: 'retainedSize', title: ls`Retained Size`, width: '110px', sortable: true, fixedWidth: true}
]);
super(dataDisplayDelegate, columns);
}
@@ -668,12 +682,11 @@ Profiler.HeapSnapshotConstructorsDataGrid = class extends Profiler.HeapSnapshotV
*/
constructor(dataDisplayDelegate) {
const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
- {id: 'object', title: Common.UIString('Constructor'), disclosure: true, sortable: true},
- {id: 'distance', title: Common.UIString('Distance'), width: '70px', sortable: true, fixedWidth: true},
- {id: 'count', title: Common.UIString('Objects Count'), width: '100px', sortable: true, fixedWidth: true},
- {id: 'shallowSize', title: Common.UIString('Shallow Size'), width: '110px', sortable: true, fixedWidth: true}, {
+ {id: 'object', title: ls`Constructor`, disclosure: true, sortable: true},
+ {id: 'distance', title: ls`Distance`, width: '70px', sortable: true, fixedWidth: true},
+ {id: 'shallowSize', title: ls`Shallow Size`, width: '110px', sortable: true, fixedWidth: true}, {
id: 'retainedSize',
- title: Common.UIString('Retained Size'),
+ title: ls`Retained Size`,
width: '110px',
sort: DataGrid.DataGrid.Order.Descending,
sortable: true,
@@ -682,15 +695,18 @@ Profiler.HeapSnapshotConstructorsDataGrid = class extends Profiler.HeapSnapshotV
]);
super(dataDisplayDelegate, columns);
this._profileIndex = -1;
-
this._objectIdToSelect = null;
}
+ /**
+ * @param {string} sortColumn
+ * @param {boolean} sortAscending
+ * @return {!Array}
+ */
_sortFields(sortColumn, sortAscending) {
return {
- object: ['_name', sortAscending, '_count', false],
- distance: ['_distance', sortAscending, '_retainedSize', true],
- count: ['_count', sortAscending, '_name', true],
+ object: ['_name', sortAscending, '_retainedSize', false],
+ distance: ['_distance', sortAscending, '_retainedSize', false],
shallowSize: ['_shallowSize', sortAscending, '_name', true],
retainedSize: ['_retainedSize', sortAscending, '_name', true]
}[sortColumn];
@@ -795,7 +811,6 @@ Profiler.HeapSnapshotConstructorsDataGrid = class extends Profiler.HeapSnapshotV
this._filterInProgress = nodeFilter;
const aggregates = await this.snapshot.aggregatesWithFilter(nodeFilter);
-
this._aggregatesReceived(nodeFilter, aggregates);
}
@@ -821,19 +836,19 @@ Profiler.HeapSnapshotDiffDataGrid = class extends Profiler.HeapSnapshotViewportD
*/
constructor(dataDisplayDelegate) {
const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
- {id: 'object', title: Common.UIString('Constructor'), disclosure: true, sortable: true},
- {id: 'addedCount', title: Common.UIString('# New'), width: '75px', sortable: true, fixedWidth: true},
- {id: 'removedCount', title: Common.UIString('# Deleted'), width: '75px', sortable: true, fixedWidth: true},
- {id: 'countDelta', title: Common.UIString('# Delta'), width: '65px', sortable: true, fixedWidth: true}, {
+ {id: 'object', title: ls`Constructor`, disclosure: true, sortable: true},
+ {id: 'addedCount', title: ls`# New`, width: '75px', sortable: true, fixedWidth: true},
+ {id: 'removedCount', title: ls`# Deleted`, width: '75px', sortable: true, fixedWidth: true},
+ {id: 'countDelta', title: ls`# Delta`, width: '65px', sortable: true, fixedWidth: true}, {
id: 'addedSize',
- title: Common.UIString('Alloc. Size'),
+ title: ls`Alloc. Size`,
width: '75px',
sortable: true,
fixedWidth: true,
sort: DataGrid.DataGrid.Order.Descending
},
- {id: 'removedSize', title: Common.UIString('Freed Size'), width: '75px', sortable: true, fixedWidth: true},
- {id: 'sizeDelta', title: Common.UIString('Size Delta'), width: '75px', sortable: true, fixedWidth: true}
+ {id: 'removedSize', title: ls`Freed Size`, width: '75px', sortable: true, fixedWidth: true},
+ {id: 'sizeDelta', title: ls`Size Delta`, width: '75px', sortable: true, fixedWidth: true}
]);
super(dataDisplayDelegate, columns);
}
@@ -901,18 +916,18 @@ Profiler.AllocationDataGrid = class extends Profiler.HeapSnapshotViewportDataGri
*/
constructor(heapProfilerModel, dataDisplayDelegate) {
const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
- {id: 'liveCount', title: Common.UIString('Live Count'), width: '75px', sortable: true, fixedWidth: true},
- {id: 'count', title: Common.UIString('Count'), width: '65px', sortable: true, fixedWidth: true},
- {id: 'liveSize', title: Common.UIString('Live Size'), width: '75px', sortable: true, fixedWidth: true},
+ {id: 'liveCount', title: ls`Live Count`, width: '75px', sortable: true, fixedWidth: true},
+ {id: 'count', title: ls`Count`, width: '65px', sortable: true, fixedWidth: true},
+ {id: 'liveSize', title: ls`Live Size`, width: '75px', sortable: true, fixedWidth: true},
{
id: 'size',
- title: Common.UIString('Size'),
+ title: ls`Size`,
width: '75px',
sortable: true,
fixedWidth: true,
sort: DataGrid.DataGrid.Order.Descending
},
- {id: 'name', title: Common.UIString('Function'), disclosure: true, sortable: true},
+ {id: 'name', title: ls`Function`, disclosure: true, sortable: true},
]);
super(dataDisplayDelegate, columns);
this._heapProfilerModel = heapProfilerModel;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotGridNodes.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotGridNodes.js
index 6e454a5aa12..a4b53344b8f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotGridNodes.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotGridNodes.js
@@ -192,19 +192,12 @@ Profiler.HeapSnapshotGridNode = class extends DataGrid.DataGridNode {
* @return {!Element}
*/
_createValueCell(columnId) {
- const cell = createElement('td');
- cell.className = 'numeric-column';
+ const cell = UI.html`<td class="numeric-column" />`;
if (this.dataGrid.snapshot.totalSize !== 0) {
- const div = createElement('div');
- const valueSpan = createElement('span');
- valueSpan.textContent = this.data[columnId];
- div.appendChild(valueSpan);
+ const div = UI.html`<div><span>${this.data[columnId]}</span></div>`;
const percentColumn = columnId + '-percent';
if (percentColumn in this.data) {
- const percentSpan = createElement('span');
- percentSpan.className = 'percent-column';
- percentSpan.textContent = this.data[percentColumn];
- div.appendChild(percentSpan);
+ div.appendChild(UI.html`<span class="percent-column">${this.data[percentColumn]}</span>`);
div.classList.add('profile-multiple-values');
}
cell.appendChild(div);
@@ -525,15 +518,15 @@ Profiler.HeapSnapshotGenericObjectNode = class extends Profiler.HeapSnapshotGrid
switch (this._type) {
case 'concatenated string':
case 'string':
- value = '"' + value + '"';
+ value = `"${value}"`;
valueStyle = 'string';
break;
case 'regexp':
- value = '/' + value + '/';
+ value = `/${value}/`;
valueStyle = 'string';
break;
case 'closure':
- value = value + '()';
+ value = `${value}()`;
valueStyle = 'function';
break;
case 'bigint':
@@ -546,73 +539,76 @@ Profiler.HeapSnapshotGenericObjectNode = class extends Profiler.HeapSnapshotGrid
valueStyle = 'null';
break;
case 'array':
- value = (value || '') + '[]';
+ value = (value || ls`(internal array)`) + '[]';
break;
}
- if (this._reachableFromWindow && !this.detachedDOMTreeNode)
- valueStyle += ' highlight';
- if (value === 'Object')
- value = '';
- if (this.detachedDOMTreeNode)
- valueStyle += ' detached-dom-tree-node';
return this._createObjectCellWithValue(valueStyle, value);
}
+ /**
+ * @param {string} valueStyle
+ * @param {string} value
+ * @return {!Element}
+ */
_createObjectCellWithValue(valueStyle, value) {
- const cell = createElement('td');
- cell.className = 'object-column';
- const div = createElement('div');
- div.className = 'source-code event-properties';
- div.style.overflow = 'visible';
-
+ const fragment = UI.Fragment.build`
+ <td class="object-column disclosure">
+ <div class="source-code event-properties" style="overflow: visible" $="container">
+ <span class="value object-value-${valueStyle}">${value}</span>
+ <span class="object-value-id">@${this.snapshotNodeId}</span>
+ </div>
+ </td>`;
+ const div = fragment.$('container');
this._prefixObjectCell(div);
-
- const valueSpan = createElement('span');
- valueSpan.className = 'value object-value-' + valueStyle;
- valueSpan.textContent = value;
- div.appendChild(valueSpan);
-
- const idSpan = createElement('span');
- idSpan.className = 'object-value-id';
- idSpan.textContent = ' @' + this.snapshotNodeId;
- div.appendChild(idSpan);
-
- cell.appendChild(div);
- cell.classList.add('disclosure');
+ if (this._reachableFromWindow) {
+ div.appendChild(UI.html
+ `<span class="heap-object-tag" title="${ls`User object reachable from window`}">🗖</span>`);
+ }
+ if (this.detachedDOMTreeNode)
+ div.appendChild(UI.html`<span class="heap-object-tag" title="${ls`Detached from DOM tree`}">✀</span>`);
+ this._appendSourceLocation(div);
+ const cell = fragment.element();
if (this.depth)
cell.style.setProperty('padding-left', (this.depth * this.dataGrid.indentWidth) + 'px');
cell.heapSnapshotNode = this;
return cell;
}
+ /**
+ * @param {!Element} div
+ */
_prefixObjectCell(div) {
}
/**
+ * @param {!Element} div
+ */
+ async _appendSourceLocation(div) {
+ if (this._type !== 'closure')
+ return;
+ const linkContainer = UI.html`<span class="heap-object-source-link" />`;
+ div.appendChild(linkContainer);
+ const link = await this._dataGrid.dataDisplayDelegate().linkifyObject(String(this.snapshotNodeId));
+ if (link)
+ linkContainer.appendChild(link);
+ else
+ linkContainer.remove();
+ }
+
+ /**
* @override
* @param {!SDK.HeapProfilerModel} heapProfilerModel
* @param {string} objectGroupName
* @return {!Promise<!SDK.RemoteObject>}
*/
- queryObjectContent(heapProfilerModel, objectGroupName) {
- let fulfill;
- const promise = new Promise(x => fulfill = x);
-
- /**
- * @param {?SDK.RemoteObject} object
- */
- function onResult(object) {
- fulfill(object || runtimeModel.createRemoteObjectFromPrimitiveValue(Common.UIString('Preview is not available')));
- }
-
+ async queryObjectContent(heapProfilerModel, objectGroupName) {
const runtimeModel = heapProfilerModel.runtimeModel();
+ let result;
if (this._type === 'string')
- onResult(runtimeModel.createRemoteObjectFromPrimitiveValue(this._name));
- else if (!heapProfilerModel || !runtimeModel)
- onResult(null);
+ result = runtimeModel.createRemoteObjectFromPrimitiveValue(this._name);
else
- heapProfilerModel.objectForSnapshotObjectId(String(this.snapshotNodeId), objectGroupName).then(onResult);
- return promise;
+ result = await heapProfilerModel.objectForSnapshotObjectId(String(this.snapshotNodeId), objectGroupName);
+ return result || runtimeModel.createRemoteObjectFromPrimitiveValue(ls`Preview is not available`);
}
async updateHasChildren() {
@@ -739,6 +735,7 @@ Profiler.HeapSnapshotObjectNode = class extends Profiler.HeapSnapshotGenericObje
/**
* @override
+ * @param {!Element} div
*/
_prefixObjectCell(div) {
let name = this._referenceName || '(empty)';
@@ -753,29 +750,20 @@ Profiler.HeapSnapshotObjectNode = class extends Profiler.HeapSnapshotGenericObje
nameClass = 'object-value-null';
break;
case 'element':
- name = '[' + name + ']';
+ name = `[${name}]`;
break;
}
-
if (this._cycledWithAncestorGridNode)
- div.className += ' cycled-ancessor-node';
-
- const nameSpan = createElement('span');
- nameSpan.className = nameClass;
- nameSpan.textContent = name;
- div.appendChild(nameSpan);
-
- const separatorSpan = createElement('span');
- separatorSpan.className = 'grayed';
- separatorSpan.textContent = this._edgeNodeSeparator();
- div.appendChild(separatorSpan);
+ div.classList.add('cycled-ancessor-node');
+ div.prepend(UI.html`<span class="${nameClass}">${name}</span>
+ <span class="grayed">${this._edgeNodeSeparator()}</span>`);
}
/**
* @return {string}
*/
_edgeNodeSeparator() {
- return ' :: ';
+ return '::';
}
};
@@ -815,7 +803,7 @@ Profiler.HeapSnapshotRetainingObjectNode = class extends Profiler.HeapSnapshotOb
* @return {string}
*/
_edgeNodeSeparator() {
- return ' in ';
+ return ls`in`;
}
/**
@@ -960,17 +948,14 @@ Profiler.HeapSnapshotConstructorNode = class extends Profiler.HeapSnapshotGridNo
this._retainedSize = aggregate.maxRet;
const snapshot = dataGrid.snapshot;
- const countPercent = this._count / snapshot.nodeCount * 100.0;
const retainedSizePercent = this._retainedSize / snapshot.totalSize * 100.0;
const shallowSizePercent = this._shallowSize / snapshot.totalSize * 100.0;
-
this.data = {
'object': className,
'count': Number.withThousandsSeparator(this._count),
'distance': this._toUIDistance(this._distance),
'shallowSize': Number.withThousandsSeparator(this._shallowSize),
'retainedSize': Number.withThousandsSeparator(this._retainedSize),
- 'count-percent': this._toPercentString(countPercent),
'shallowSize-percent': this._toPercentString(shallowSizePercent),
'retainedSize-percent': this._toPercentString(retainedSizePercent)
};
@@ -1018,7 +1003,9 @@ Profiler.HeapSnapshotConstructorNode = class extends Profiler.HeapSnapshotGridNo
* @return {!Element}
*/
createCell(columnId) {
- const cell = columnId !== 'object' ? this._createValueCell(columnId) : super.createCell(columnId);
+ const cell = columnId === 'object' ? super.createCell(columnId) : this._createValueCell(columnId);
+ if (columnId === 'object' && this._count > 1)
+ cell.appendChild(UI.html`<span class="objects-count">×${this._count}</span>`);
if (this._searchMatched)
cell.classList.add('highlight');
return cell;
@@ -1041,7 +1028,6 @@ Profiler.HeapSnapshotConstructorNode = class extends Profiler.HeapSnapshotGridNo
const sortFields = {
object: ['name', sortAscending, 'id', true],
distance: ['distance', sortAscending, 'retainedSize', false],
- count: ['name', true, 'id', true],
shallowSize: ['selfSize', sortAscending, 'id', true],
retainedSize: ['retainedSize', sortAscending, 'id', true]
}[sortColumnId];
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js
index 1f4d6b8e545..57bf5fb754f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotView.js
@@ -43,6 +43,7 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
this.element.classList.add('heap-snapshot-view');
this._profile = profile;
+ this._linkifier = new Components.Linkifier();
profile.profileType().addEventListener(
Profiler.HeapSnapshotProfileType.SnapshotReceived, this._onReceiveSnapshot, this);
@@ -82,13 +83,13 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
this._diffWidget.setMinimumSize(50, 25);
if (isHeapTimeline) {
- this._allocationDataGrid = new Profiler.AllocationDataGrid(profile._heapProfilerModel, this);
+ this._allocationDataGrid = new Profiler.AllocationDataGrid(profile.heapProfilerModel(), this);
this._allocationDataGrid.addEventListener(
DataGrid.DataGrid.Events.SelectedNode, this._onSelectAllocationNode, this);
this._allocationWidget = this._allocationDataGrid.asWidget();
this._allocationWidget.setMinimumSize(50, 25);
- this._allocationStackView = new Profiler.HeapAllocationStackView(profile._heapProfilerModel);
+ this._allocationStackView = new Profiler.HeapAllocationStackView(profile.heapProfilerModel());
this._allocationStackView.setMinimumSize(50, 25);
this._tabbedPane = new UI.TabbedPane();
@@ -201,6 +202,24 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
this._parentDataDisplayDelegate.showObject(snapshotObjectId, perspectiveName);
}
+ /**
+ * @override
+ * @param {!Protocol.HeapProfiler.HeapSnapshotObjectId} snapshotObjectId
+ * @return {!Promise<?Element>}
+ */
+ async linkifyObject(snapshotObjectId) {
+ const heapProfilerModel = this._profile.heapProfilerModel();
+ const remoteObject = await heapProfilerModel.objectForSnapshotObjectId(String(snapshotObjectId), 'link');
+ if (!remoteObject || remoteObject.type !== 'function')
+ return null;
+ const functionDetails = await remoteObject.debuggerModel().functionDetailsPromise(remoteObject);
+ if (!functionDetails || !functionDetails.location)
+ return null;
+ const rawLocation = functionDetails.location;
+ const sourceURL = rawLocation.script() && rawLocation.script().sourceURL;
+ return sourceURL && this._linkifier ? this._linkifier.linkifyRawLocation(rawLocation, sourceURL) : null;
+ }
+
async _populate() {
const heapSnapshotProxy = await this._profile._loadPromise;
@@ -462,8 +481,9 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
*/
_inspectedObjectChanged(event) {
const selectedNode = /** @type {!DataGrid.DataGridNode} */ (event.data);
- if (this._profile._heapProfilerModel && selectedNode instanceof Profiler.HeapSnapshotGenericObjectNode)
- this._profile._heapProfilerModel.addInspectedHeapObject(String(selectedNode.snapshotNodeId));
+ const heapProfilerModel = this._profile.heapProfilerModel();
+ if (heapProfilerModel && selectedNode instanceof Profiler.HeapSnapshotGenericObjectNode)
+ heapProfilerModel.addInspectedHeapObject(String(selectedNode.snapshotNodeId));
}
/**
@@ -579,7 +599,7 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
_getPopoverRequest(event) {
const span = event.target.enclosingNodeOrSelfWithNodeName('span');
const row = event.target.enclosingNodeOrSelfWithNodeName('tr');
- const heapProfilerModel = this._profile._heapProfilerModel;
+ const heapProfilerModel = this._profile.heapProfilerModel();
if (!row || !span || !heapProfilerModel)
return null;
const node = row._dataGridNode;
@@ -679,6 +699,7 @@ Profiler.HeapSnapshotView = class extends UI.SimpleView {
}
dispose() {
+ this._linkifier.dispose();
this._popoverHelper.dispose();
if (this._allocationStackView) {
this._allocationStackView.clear();
@@ -1081,7 +1102,7 @@ Profiler.HeapSnapshotProfileType = class extends Profiler.ProfileType {
_resetProfiles(event) {
const heapProfilerModel = /** @type {!SDK.HeapProfilerModel} */ (event.data);
for (const profile of this.getProfiles()) {
- if (profile._heapProfilerModel === heapProfilerModel)
+ if (profile.heapProfilerModel() === heapProfilerModel)
this.removeProfile(profile);
}
}
@@ -1228,7 +1249,7 @@ Profiler.TrackingHeapSnapshotProfileType = class extends Profiler.HeapSnapshotPr
async _stopRecordingProfile() {
this.profileBeingRecorded().updateStatus(Common.UIString('Snapshotting\u2026'));
- const stopPromise = this.profileBeingRecorded()._heapProfilerModel.stopTrackingHeapObjects(true);
+ const stopPromise = this.profileBeingRecorded().heapProfilerModel().stopTrackingHeapObjects(true);
this._recording = false;
this.dispatchEventToListeners(Profiler.TrackingHeapSnapshotProfileType.TrackingStopped);
await stopPromise;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/IsolateSelector.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/IsolateSelector.js
index cf3460cd1cf..c334c489e75 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/IsolateSelector.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/IsolateSelector.js
@@ -21,6 +21,7 @@ Profiler.IsolateSelector = class extends UI.VBox {
this._isolateByModel = new Map();
/** @type {!Map<string, !Profiler.IsolateSelector.ListItem>} */
this._itemByIsolate = new Map();
+ this._updateTimer = null;
SDK.targetManager.observeModels(SDK.RuntimeModel, this);
SDK.targetManager.addEventListener(SDK.TargetManager.Events.NameChanged, this._targetChanged, this);
@@ -29,6 +30,20 @@ Profiler.IsolateSelector = class extends UI.VBox {
/**
* @override
+ */
+ wasShown() {
+ this._updateStats();
+ }
+
+ /**
+ * @override
+ */
+ willHide() {
+ clearTimeout(this._updateTimer);
+ }
+
+ /**
+ * @override
* @param {!SDK.RuntimeModel} model
*/
modelAdded(model) {
@@ -137,6 +152,13 @@ Profiler.IsolateSelector = class extends UI.VBox {
_update() {
this._list.invalidateRange(0, this._items.length);
}
+
+ _updateStats() {
+ for (const item of this._itemByIsolate.values())
+ item.updateStats();
+ const heapStatsUpdateIntervalMs = 2000;
+ this._updateTimer = setTimeout(() => this._updateStats(), heapStatsUpdateIntervalMs);
+ }
};
Profiler.IsolateSelector.ListItem = class {
@@ -149,9 +171,9 @@ Profiler.IsolateSelector.ListItem = class {
this.element = createElementWithClass('div', 'profile-isolate-item hbox');
this._heapDiv = this.element.createChild('div', 'profile-isolate-item-heap');
this._nameDiv = this.element.createChild('div', 'profile-isolate-item-name');
- this._updateTimer = null;
+ this._updatesDisabled = false;
this.updateTitle();
- this._updateStats();
+ this.updateStats();
}
/**
@@ -168,9 +190,6 @@ Profiler.IsolateSelector.ListItem = class {
removeModel(model) {
this._models.delete(model);
this.updateTitle();
- if (this._models.size)
- return;
- clearTimeout(this._updateTimer);
}
/**
@@ -180,14 +199,21 @@ Profiler.IsolateSelector.ListItem = class {
return Array.from(this._models);
}
- async _updateStats() {
+ async updateStats() {
+ if (this._updatesDisabled)
+ return;
const heapStats = await this._models.values().next().value.heapUsage();
- if (!heapStats)
+ if (!heapStats) {
+ this._updatesDisabled = true;
return;
- this._heapDiv.textContent =
- `${Number.bytesToString(heapStats.usedSize)} / ${Number.bytesToString(heapStats.totalSize)}`;
- const heapStatsUpdateIntervalMs = 2000;
- this._updateTimer = setTimeout(() => this._updateStats(), heapStatsUpdateIntervalMs);
+ }
+ const usedTitle = ls`Heap size in use by live JS objects.`;
+ const totalTitle = ls`Total JS heap size including live objects, garbage, and reserved space.`;
+ this._heapDiv.removeChildren();
+ this._heapDiv.append(UI.html`
+ <span title="${usedTitle}">${Number.bytesToString(heapStats.usedSize)}</span>
+ <span> / </span>
+ <span title="${totalTitle}">${Number.bytesToString(heapStats.totalSize)}</span>`);
}
updateTitle() {
@@ -203,10 +229,8 @@ Profiler.IsolateSelector.ListItem = class {
}
this._nameDiv.removeChildren();
for (const [name, count] of modelCountByName) {
- const lineDiv = this._nameDiv.createChild('div');
const title = count > 1 ? `${name} (${count})` : name;
- lineDiv.textContent = title;
- lineDiv.setAttribute('title', title);
+ this._nameDiv.appendChild(UI.html`<div title="${title}">${title}</div>`);
}
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileLauncherView.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileLauncherView.js
index dae71426f83..9b201bf694d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileLauncherView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileLauncherView.js
@@ -42,9 +42,9 @@ Profiler.ProfileLauncherView = class extends UI.VBox {
this._contentElement = this.element.createChild('div', 'profile-launcher-view-content');
this._innerContentElement = this._contentElement.createChild('div');
- const controlDiv = this._contentElement.createChild('div', 'hbox profile-launcher-control');
+ const controlDiv = this._contentElement.createChild('div', 'vbox profile-launcher-control');
controlDiv.createChild('h1').textContent = ls`Select JavaScript VM instance`;
- const targetDiv = controlDiv.createChild('div', 'hbox profile-launcher-target-list');
+ const targetDiv = controlDiv.createChild('div', 'vbox profile-launcher-target-list');
new Profiler.IsolateSelector().show(targetDiv);
this._controlButton =
UI.createTextButton('', this._controlButtonClicked.bind(this), 'profile-launcher-button', true /* primary */);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileType.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileType.js
index a8be4a1a5da..2058baa102f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileType.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileType.js
@@ -244,5 +244,11 @@ Profiler.ProfileType.DataDisplayDelegate.prototype = {
* @param {!Protocol.HeapProfiler.HeapSnapshotObjectId} snapshotObjectId
* @param {string} perspectiveName
*/
- showObject(snapshotObjectId, perspectiveName) {}
+ showObject(snapshotObjectId, perspectiveName) {},
+
+ /**
+ * @param {!Protocol.HeapProfiler.HeapSnapshotObjectId} snapshotObjectId
+ * @return {!Promise<?Element>}
+ */
+ async linkifyObject(snapshotObjectId) {}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileTypeRegistry.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileTypeRegistry.js
index 658d3277e70..c34140b6c98 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileTypeRegistry.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileTypeRegistry.js
@@ -10,7 +10,8 @@ Profiler.ProfileTypeRegistry = class {
this.heapSnapshotProfileType = new Profiler.HeapSnapshotProfileType();
this.samplingHeapProfileType = new Profiler.SamplingHeapProfileType();
this.samplingNativeHeapProfileType = new Profiler.SamplingNativeHeapProfileType();
- this.samplingNativeHeapSnapshotType = new Profiler.SamplingNativeHeapSnapshotType();
+ this.samplingNativeHeapSnapshotBrowserType = new Profiler.SamplingNativeHeapSnapshotBrowserType();
+ this.samplingNativeHeapSnapshotRendererType = new Profiler.SamplingNativeHeapSnapshotRendererType();
this.trackingHeapSnapshotProfileType = new Profiler.TrackingHeapSnapshotProfileType();
}
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileView.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileView.js
index 11c33fc6ae6..c61e126719b 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfileView.js
@@ -75,9 +75,10 @@ Profiler.ProfileView = class extends UI.SimpleView {
];
const optionNames = new Map([
- [Profiler.ProfileView.ViewTypes.Flame, Common.UIString('Chart')],
- [Profiler.ProfileView.ViewTypes.Heavy, Common.UIString('Heavy (Bottom Up)')],
- [Profiler.ProfileView.ViewTypes.Tree, Common.UIString('Tree (Top Down)')],
+ [Profiler.ProfileView.ViewTypes.Flame, ls`Chart`],
+ [Profiler.ProfileView.ViewTypes.Heavy, ls`Heavy (Bottom Up)`],
+ [Profiler.ProfileView.ViewTypes.Tree, ls`Tree (Top Down)`],
+ [Profiler.ProfileView.ViewTypes.Text, ls`Text (Top Down)`],
]);
const options =
@@ -240,6 +241,20 @@ Profiler.ProfileView = class extends UI.SimpleView {
return this._linkifier;
}
+ _ensureTextViewCreated() {
+ if (this._textView)
+ return;
+ this._textView = new UI.SimpleView(ls`Call tree`);
+ this._textView.registerRequiredCSS('profiler/profilesPanel.css');
+ this.populateTextView(this._textView);
+ }
+
+ /**
+ * @param {!UI.SimpleView} view
+ */
+ populateTextView(view) {
+ }
+
/**
* @return {!PerfUI.FlameChartDataProvider}
*/
@@ -300,6 +315,11 @@ Profiler.ProfileView = class extends UI.SimpleView {
this._visibleView = this.dataGrid.asWidget();
this._searchableElement = this.profileDataGridTree;
break;
+ case Profiler.ProfileView.ViewTypes.Text:
+ this._ensureTextViewCreated();
+ this._visibleView = this._textView;
+ this._searchableElement = this._textView;
+ break;
}
const isFlame = this._viewType.get() === Profiler.ProfileView.ViewTypes.Flame;
@@ -377,7 +397,8 @@ Profiler.ProfileView._maxLinkLength = 30;
Profiler.ProfileView.ViewTypes = {
Flame: 'Flame',
Tree: 'Tree',
- Heavy: 'Heavy'
+ Heavy: 'Heavy',
+ Text: 'Text'
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfilesPanel.js b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfilesPanel.js
index 26470613d49..25d33073763 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfilesPanel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/ProfilesPanel.js
@@ -383,6 +383,15 @@ Profiler.ProfilesPanel = class extends UI.PanelWithSidebar {
}
/**
+ * @override
+ * @param {!Protocol.HeapProfiler.HeapSnapshotObjectId} snapshotObjectId
+ * @return {!Promise<?Element>}
+ */
+ async linkifyObject(snapshotObjectId) {
+ return null;
+ }
+
+ /**
* @param {!Profiler.ProfileHeader} profile
* @return {!UI.Widget}
*/
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/heapProfiler.css b/chromium/third_party/blink/renderer/devtools/front_end/profiler/heapProfiler.css
index b60620dc790..c5f604461b5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/heapProfiler.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/heapProfiler.css
@@ -52,14 +52,16 @@
position: static;
}
-.detached-dom-tree-node {
- background-color: #FF9999;
-}
-
.heap-snapshot-view .object-value-string {
white-space: nowrap;
}
+.heap-snapshot-view td.object-column .objects-count {
+ margin-left: 10px;
+ font-size: 11px;
+ color: grey;
+}
+
.heap-snapshot-view tr:not(.selected) .object-value-id {
color: grey;
}
@@ -99,7 +101,40 @@
}
.heap-snapshot-view tr:not(.selected) td.object-column span.highlight {
- background-color: rgb(255, 255, 200);
+ background-color: inherit;
+}
+
+.heap-snapshot-view td.object-column > div > span {
+ margin-right: 6px;
+}
+
+.heap-snapshot-view td.object-column span.heap-object-source-link {
+ float: right;
+}
+
+.heap-snapshot-view td.object-column span.heap-object-source-link:empty {
+ animation: fadeInOut 2s infinite;
+}
+
+.heap-snapshot-view td.object-column span.heap-object-source-link:empty:before {
+ content: "\b7\b7";
+ font-weight: bold;
+}
+
+@keyframes fadeInOut {
+ 0% {
+ transform: rotate(0);
+ }
+ 50% {
+ transform: rotate(0.5turn);
+ }
+ 100% {
+ transform: rotate(1turn);
+ }
+}
+
+.heap-snapshot-view tr:not(.selected) td.object-column span.heap-object-tag {
+ color: #888;
}
.heap-snapshot-view td.object-column span.grayed {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/profiler/profilesPanel.css b/chromium/third_party/blink/renderer/devtools/front_end/profiler/profilesPanel.css
index de3964ed5a1..a44bd156ab2 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/profiler/profilesPanel.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/profiler/profilesPanel.css
@@ -112,9 +112,13 @@
color: white;
}
+
+.profile-launcher-view {
+ overflow: auto;
+}
+
.profile-launcher-view-content {
padding: 10px 16px;
- overflow: auto;
}
.profile-launcher-view-content h1 {
@@ -129,11 +133,8 @@
}
.profile-launcher-control {
- align-items: center;
+ align-items: flex-start;
flex-wrap: wrap;
-}
-
-.profile-launcher-control {
margin-top: 10px;
margin-right: 6px;
}
@@ -236,3 +237,11 @@ body.inactive .profile-launcher-view-content button.running:not(.toolbar-item) {
.cpu-profile-flame-chart-overview-pane {
flex: 0 0 80px !important;
}
+
+.profile-text-view {
+ padding: 10px;
+ overflow: auto;
+ margin: 0;
+ user-select: text;
+ cursor: text;
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkersView.js b/chromium/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkersView.js
index a8f3da16ff7..6e9691ffe1f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkersView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkersView.js
@@ -16,7 +16,7 @@ Resources.ServiceWorkersView = class extends UI.VBox {
this._currentWorkersView.element.classList.add('service-workers-this-origin');
this._toolbar = this._currentWorkersView.createToolbar();
- this._toolbar.makeWrappable(false, true);
+ this._toolbar.makeWrappable(true /* growVertically */);
/** @type {!Map<!SDK.ServiceWorkerRegistration, !Resources.ServiceWorkersView.Section>} */
this._sections = new Map();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/screencast/ScreencastView.js b/chromium/third_party/blink/renderer/devtools/front_end/screencast/ScreencastView.js
index 28ae541cc69..8117e9d2faf 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/screencast/ScreencastView.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/screencast/ScreencastView.js
@@ -58,7 +58,7 @@ Screencast.ScreencastView = class extends UI.VBox {
this._glassPaneElement = this._canvasContainerElement.createChild('div', 'screencast-glasspane fill hidden');
this._canvasElement = this._canvasContainerElement.createChild('canvas');
- this._canvasElement.tabIndex = 1;
+ this._canvasElement.tabIndex = 0;
this._canvasElement.addEventListener('mousedown', this._handleMouseEvent.bind(this), false);
this._canvasElement.addEventListener('mouseup', this._handleMouseEvent.bind(this), false);
this._canvasElement.addEventListener('mousemove', this._handleMouseEvent.bind(this), false);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CPUProfileDataModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CPUProfileDataModel.js
index b6d76f41178..adea776d03f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CPUProfileDataModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CPUProfileDataModel.js
@@ -173,7 +173,7 @@ SDK.CPUProfileDataModel = class extends SDK.ProfileTreeModel {
return;
const samples = this.samples;
const indices = timestamps.map((x, index) => index);
- indices.sort((a, b) => timestamps[a] - timestamps[b]);
+ indices.stableSort((a, b) => timestamps[a] - timestamps[b]);
for (let i = 0; i < timestamps.length; ++i) {
let index = indices[i];
if (index === i)
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSStyleDeclaration.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSStyleDeclaration.js
index 2692bdfc5f7..d02bd35692a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSStyleDeclaration.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/CSSStyleDeclaration.js
@@ -63,9 +63,22 @@ SDK.CSSStyleDeclaration = class {
}
this._allProperties = [];
- for (let i = 0; i < payload.cssProperties.length; ++i) {
- const property = SDK.CSSProperty.parsePayload(this, i, payload.cssProperties[i]);
- this._allProperties.push(property);
+
+ if (payload.cssText && this.range) {
+ const cssText = new TextUtils.Text(payload.cssText);
+ let start = {line: this.range.startLine, column: this.range.startColumn};
+ for (const cssProperty of payload.cssProperties) {
+ const range = cssProperty.range;
+ if (range) {
+ parseUnusedText.call(this, cssText, start.line, start.column, range.startLine, range.startColumn);
+ start = {line: range.endLine, column: range.endColumn};
+ }
+ this._allProperties.push(SDK.CSSProperty.parsePayload(this, this._allProperties.length, cssProperty));
+ }
+ parseUnusedText.call(this, cssText, start.line, start.column, this.range.endLine, this.range.endColumn);
+ } else {
+ for (const cssProperty of payload.cssProperties)
+ this._allProperties.push(SDK.CSSProperty.parsePayload(this, this._allProperties.length, cssProperty));
}
this._generateSyntheticPropertiesIfNeeded();
@@ -80,6 +93,72 @@ SDK.CSSStyleDeclaration = class {
this.cssText = payload.cssText;
this._leadingProperties = null;
+
+ /**
+ * @this {SDK.CSSStyleDeclaration}
+ * @param {!TextUtils.Text} cssText
+ * @param {number} startLine
+ * @param {number} startColumn
+ * @param {number} endLine
+ * @param {number} endColumn
+ */
+ function parseUnusedText(cssText, startLine, startColumn, endLine, endColumn) {
+ const tr = new TextUtils.TextRange(startLine, startColumn, endLine, endColumn);
+ const missingText = cssText.extract(tr.relativeTo(this.range.startLine, this.range.startColumn));
+
+ // Try to fit the malformed css into properties.
+ const lines = missingText.split('\n');
+ let lineNumber = 0;
+ let inComment = false;
+ for (const line of lines) {
+ let column = 0;
+ for (const property of line.split(';')) {
+ const strippedProperty = stripComments(property, inComment);
+ const trimmedProperty = strippedProperty.text.trim();
+ inComment = strippedProperty.inComment;
+
+ if (trimmedProperty) {
+ let name;
+ let value;
+ const colonIndex = trimmedProperty.indexOf(':');
+ if (colonIndex === -1) {
+ name = trimmedProperty;
+ value = '';
+ } else {
+ name = trimmedProperty.substring(0, colonIndex).trim();
+ value = trimmedProperty.substring(colonIndex + 1).trim();
+ }
+ const range = new TextUtils.TextRange(lineNumber, column, lineNumber, column + property.length);
+ this._allProperties.push(new SDK.CSSProperty(
+ this, this._allProperties.length, name, value, false, false, false, false, property,
+ range.relativeFrom(startLine, startColumn)));
+ }
+ column += property.length + 1;
+ }
+ lineNumber++;
+ }
+ }
+
+ /**
+ * @param {string} text
+ * @param {boolean} inComment
+ * @return {{text: string, inComment: boolean}}
+ */
+ function stripComments(text, inComment) {
+ let output = '';
+ for (let i = 0; i < text.length; i++) {
+ if (!inComment && text.substring(i, i + 2) === '/*') {
+ inComment = true;
+ i++;
+ } else if (inComment && text.substring(i, i + 2) === '*/') {
+ inComment = false;
+ i++;
+ } else if (!inComment) {
+ output += text[i];
+ }
+ }
+ return {text: output, inComment};
+ }
}
_generateSyntheticPropertiesIfNeeded() {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ChildTargetManager.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ChildTargetManager.js
index 938c219b322..559e26aa151 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ChildTargetManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ChildTargetManager.js
@@ -107,6 +107,15 @@ SDK.ChildTargetManager = class extends SDK.SDKModel {
this._fireAvailableTargetsChanged();
}
+ /**
+ * @override
+ * @param {string} targetId
+ * @param {string} status
+ * @param {number} errorCode
+ */
+ targetCrashed(targetId, status, errorCode) {
+ }
+
_fireAvailableTargetsChanged() {
SDK.targetManager.dispatchEventToListeners(
SDK.TargetManager.Events.AvailableTargetsChanged, this._targetInfos.valuesArray());
@@ -127,7 +136,7 @@ SDK.ChildTargetManager = class extends SDK.SDKModel {
}
const target = this._targetManager.createTarget(
targetInfo.targetId, targetName, this._capabilitiesForType(targetInfo.type),
- this._createChildConnection.bind(this, this._targetAgent, sessionId), this._parentTarget);
+ this._createChildConnection.bind(this, this._targetAgent, sessionId), this._parentTarget, false /* isNodeJS */);
if (SDK.ChildTargetManager._attachCallback)
SDK.ChildTargetManager._attachCallback({target, waitingForDebugger});
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMDebuggerModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMDebuggerModel.js
index af0c41ad03b..ee8f0731b89 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMDebuggerModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMDebuggerModel.js
@@ -588,6 +588,9 @@ SDK.DOMDebuggerManager = class {
Common.UIString('Timer'),
['setTimeout', 'clearTimeout', 'setInterval', 'clearInterval', 'setTimeout.callback', 'setInterval.callback']);
this._createInstrumentationBreakpoints(Common.UIString('Window'), ['DOMWindow.close']);
+ this._createInstrumentationBreakpoints(
+ Common.UIString('WebAudio'),
+ ['audioContextCreated', 'audioContextClosed', 'audioContextResumed', 'audioContextSuspended']);
this._createEventListenerBreakpoints(
Common.UIString('Media'),
@@ -669,6 +672,14 @@ SDK.DOMDebuggerManager = class {
this._resolveEventListenerBreakpoint('instrumentation:Notification.requestPermission')._title = 'requestPermission';
this._resolveEventListenerBreakpoint('instrumentation:DOMWindow.close')._title = 'window.close';
this._resolveEventListenerBreakpoint('instrumentation:Document.write')._title = 'document.write';
+ this._resolveEventListenerBreakpoint('instrumentation:audioContextCreated')._title =
+ Common.UIString('Create AudioContext');
+ this._resolveEventListenerBreakpoint('instrumentation:audioContextClosed')._title =
+ Common.UIString('Close AudioContext');
+ this._resolveEventListenerBreakpoint('instrumentation:audioContextResumed')._title =
+ Common.UIString('Resume AudioContext');
+ this._resolveEventListenerBreakpoint('instrumentation:audioContextSuspended')._title =
+ Common.UIString('Suspend AudioContext');
SDK.targetManager.observeModels(SDK.DOMDebuggerModel, this);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMModel.js
index 6dd3a9463bf..89a522246fc 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/DOMModel.js
@@ -112,7 +112,7 @@ SDK.DOMNode = class {
}
if (payload.contentDocument) {
- this._contentDocument = SDK.DOMNode.create(this._domModel, this.ownerDocument, true, payload.contentDocument);
+ this._contentDocument = new SDK.DOMDocument(this._domModel, payload.contentDocument);
this._contentDocument.parentNode = this;
this._children = [];
} else if (payload.nodeName === 'IFRAME' && payload.frameId && Runtime.experiments.isEnabled('oopifInlineDOM')) {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/DebuggerModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/DebuggerModel.js
index 1a766637b48..5bc6a1cf215 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/DebuggerModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/DebuggerModel.js
@@ -968,7 +968,7 @@ SDK.DebuggerModel.ContinueToLocationTargetCallFrames = {
SDK.DebuggerModel.SetBreakpointResult;
/**
- * @implements {Protocol.DebuggerDispatcher}
+ * @extends {Protocol.DebuggerDispatcher}
* @unrestricted
*/
SDK.DebuggerDispatcher = class {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/HeapProfilerModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/HeapProfilerModel.js
index 6f28d6120a6..f1330463f27 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/HeapProfilerModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/HeapProfilerModel.js
@@ -72,6 +72,14 @@ SDK.HeapProfilerModel = class extends SDK.SDKModel {
}
/**
+ * @return {!Promise<!Protocol.HeapProfiler.SamplingHeapProfile>}
+ */
+ async takeNativeBrowserSnapshot() {
+ const rawProfile = await this._memoryAgent.getBrowserSamplingProfile();
+ return this._convertNativeProfile(rawProfile);
+ }
+
+ /**
* @param {!Protocol.Memory.SamplingProfile} rawProfile
* @return {!Protocol.HeapProfiler.SamplingHeapProfile}
*/
@@ -123,9 +131,9 @@ SDK.HeapProfilerModel = class extends SDK.SDKModel {
* @param {string} objectGroupName
* @return {!Promise<?SDK.RemoteObject>}
*/
- objectForSnapshotObjectId(snapshotObjectId, objectGroupName) {
- return this._heapProfilerAgent.getObjectByHeapObjectId(snapshotObjectId, objectGroupName)
- .then(result => result && result.type ? this._runtimeModel.createRemoteObject(result) : null);
+ async objectForSnapshotObjectId(snapshotObjectId, objectGroupName) {
+ const result = await this._heapProfilerAgent.getObjectByHeapObjectId(snapshotObjectId, objectGroupName);
+ return result && result.type && this._runtimeModel.createRemoteObject(result) || null;
}
/**
@@ -210,7 +218,7 @@ SDK.HeapProfilerModel.Events = {
};
/**
- * @implements {Protocol.HeapProfilerDispatcher}
+ * @extends {Protocol.HeapProfilerDispatcher}
* @unrestricted
*/
SDK.HeapProfilerDispatcher = class {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkManager.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkManager.js
index 4f6a1116538..c620de61493 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkManager.js
@@ -571,15 +571,15 @@ SDK.NetworkDispatcher = class {
* @param {!Protocol.Network.RequestId} requestId
* @param {!Protocol.Network.MonotonicTime} finishTime
* @param {number} encodedDataLength
- * @param {boolean=} blockedCrossSiteDocument
+ * @param {boolean=} shouldReportCorbBlocking
*/
- loadingFinished(requestId, finishTime, encodedDataLength, blockedCrossSiteDocument) {
+ loadingFinished(requestId, finishTime, encodedDataLength, shouldReportCorbBlocking) {
let networkRequest = this._inflightRequestsById[requestId];
if (!networkRequest)
networkRequest = this._maybeAdoptMainResourceRequest(requestId);
if (!networkRequest)
return;
- this._finishNetworkRequest(networkRequest, finishTime, encodedDataLength, blockedCrossSiteDocument);
+ this._finishNetworkRequest(networkRequest, finishTime, encodedDataLength, shouldReportCorbBlocking);
}
/**
@@ -834,9 +834,9 @@ SDK.NetworkDispatcher = class {
* @param {!SDK.NetworkRequest} networkRequest
* @param {!Protocol.Network.MonotonicTime} finishTime
* @param {number} encodedDataLength
- * @param {boolean=} blockedCrossSiteDocument
+ * @param {boolean=} shouldReportCorbBlocking
*/
- _finishNetworkRequest(networkRequest, finishTime, encodedDataLength, blockedCrossSiteDocument) {
+ _finishNetworkRequest(networkRequest, finishTime, encodedDataLength, shouldReportCorbBlocking) {
networkRequest.endTime = finishTime;
networkRequest.finished = true;
if (encodedDataLength >= 0)
@@ -846,7 +846,7 @@ SDK.NetworkDispatcher = class {
delete this._inflightRequestsByURL[networkRequest.url()];
SDK.multitargetNetworkManager._inflightMainResourceRequests.delete(networkRequest.requestId());
- if (blockedCrossSiteDocument) {
+ if (shouldReportCorbBlocking) {
const message = Common.UIString(
`Cross-Origin Read Blocking (CORB) blocked cross-origin response %s with MIME type %s. ` +
`See https://www.chromestatus.com/feature/5629709824032768 for more details.`,
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkRequest.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkRequest.js
index 709c58975c3..b339904aac2 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkRequest.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/NetworkRequest.js
@@ -859,12 +859,34 @@ SDK.NetworkRequest = class extends Common.Object {
*/
async _parseFormParameters() {
const requestContentType = this.requestContentType();
- if (!requestContentType || !requestContentType.match(/^application\/x-www-form-urlencoded\s*(;.*)?$/i))
+
+ if (!requestContentType)
return null;
- const formData = await this.requestFormData();
- if (formData)
+
+ // Handling application/x-www-form-urlencoded request bodies.
+ if (requestContentType.match(/^application\/x-www-form-urlencoded\s*(;.*)?$/i)) {
+ const formData = await this.requestFormData();
+ if (!formData)
+ return null;
+
return this._parseParameters(formData);
- return null;
+ }
+
+ // Handling multipart/form-data request bodies.
+ const multipartDetails = requestContentType.match(/^multipart\/form-data\s*;\s*boundary\s*=\s*(\S+)\s*$/);
+
+ if (!multipartDetails)
+ return null;
+
+ const boundary = multipartDetails[1];
+ if (!boundary)
+ return null;
+
+ const formData = await this.requestFormData();
+ if (!formData)
+ return null;
+
+ return this._parseMultipartFormDataParameters(formData, boundary);
}
/**
@@ -908,6 +930,58 @@ SDK.NetworkRequest = class extends Common.Object {
}
/**
+ * Parses multipart/form-data; boundary=boundaryString request bodies -
+ * --boundaryString
+ * Content-Disposition: form-data; name="field-name"; filename="r.gif"
+ * Content-Type: application/octet-stream
+ *
+ * optionalValue
+ * --boundaryString
+ * Content-Disposition: form-data; name="field-name-2"
+ *
+ * optionalValue2
+ * --boundaryString--
+ *
+ * @param {string} data
+ * @param {string} boundary
+ * @return {!Array.<!SDK.NetworkRequest.NameValue>}
+ */
+ _parseMultipartFormDataParameters(data, boundary) {
+ const sanitizedBoundary = boundary.escapeForRegExp();
+ const keyValuePattern = new RegExp(
+ // Header with an optional file name.
+ '^\\r\\ncontent-disposition\\s*:\\s*form-data\\s*;\\s*name="([^"]*)"(?:\\s*;\\s*filename="([^"]*)")?' +
+ // Optional secondary header with the content type.
+ '(?:\\r\\ncontent-type\\s*:\\s*([^\\r\\n]*))?' +
+ // Padding.
+ '\\r\\n\\r\\n' +
+ // Value
+ '(.*)' +
+ // Padding.
+ '\\r\\n$',
+ 'is');
+ const fields = data.split(new RegExp(`--${sanitizedBoundary}(?:--\s*$)?`, 'g'));
+ return fields.reduce(parseMultipartField, []);
+
+ /**
+ * @param {!Array.<!SDK.NetworkRequest.NameValue>} result
+ * @param {string} field
+ * @return {!Array.<!SDK.NetworkRequest.NameValue>}
+ */
+ function parseMultipartField(result, field) {
+ const [match, name, filename, contentType, value] = field.match(keyValuePattern) || [];
+
+ if (!match)
+ return result;
+
+ const processedValue = (filename || contentType) ? ls`(binary)` : value;
+ result.push({name, value: processedValue});
+
+ return result;
+ }
+ }
+
+ /**
* @param {!Array.<!SDK.NetworkRequest.NameValue>} headers
* @param {string} headerName
* @return {string|undefined}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ProfileTreeModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ProfileTreeModel.js
index 7f7c72d3927..94a5d4c6911 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ProfileTreeModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ProfileTreeModel.js
@@ -12,7 +12,7 @@ SDK.ProfileNode = class {
/** @type {!Protocol.Runtime.CallFrame} */
this.callFrame = callFrame;
/** @type {string} */
- this.callUID = `${this.callFrame.functionName}@${this.callFrame.scriptId}:${this.callFrame.lineNumber}`;
+ this.callUID = `${callFrame.functionName}@${callFrame.scriptId}:${callFrame.lineNumber}:${callFrame.columnNumber}`;
/** @type {number} */
this.self = 0;
/** @type {number} */
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/RemoteObject.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/RemoteObject.js
index 0028837801d..35742ce539c 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/RemoteObject.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/RemoteObject.js
@@ -679,7 +679,8 @@ SDK.RemoteObjectImpl = class extends SDK.RemoteObject {
if (!property.value)
continue;
const propertyValue = this._runtimeModel.createRemoteObject(property.value);
- internalPropertiesResult.push(new SDK.RemoteObjectProperty(property.name, propertyValue, true, false));
+ internalPropertiesResult.push(new SDK.RemoteObjectProperty(
+ property.name, propertyValue, true, false, undefined, undefined, undefined, true));
}
}
callback(result, internalPropertiesResult);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ResourceTreeModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ResourceTreeModel.js
index 55dd099d817..824cd76720d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ResourceTreeModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ResourceTreeModel.js
@@ -942,4 +942,12 @@ SDK.PageDispatcher = class {
*/
windowOpen(url, windowName, windowFeatures, userGesture) {
}
+
+ /**
+ * @override
+ * @param {string} url
+ * @param {string} data
+ */
+ compilationCacheProduced(url, data) {
+ }
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/RuntimeModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/RuntimeModel.js
index afa7124f746..3356ea5e604 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/RuntimeModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/RuntimeModel.js
@@ -583,7 +583,7 @@ SDK.RuntimeModel.QueryObjectResult;
SDK.RuntimeModel.ConsoleAPICall;
/**
- * @implements {Protocol.RuntimeDispatcher}
+ * @extends {Protocol.RuntimeDispatcher}
* @unrestricted
*/
SDK.RuntimeDispatcher = class {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ScreenCaptureModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ScreenCaptureModel.js
index be05514cf6f..ddb7f44e9dc 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/ScreenCaptureModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/ScreenCaptureModel.js
@@ -216,6 +216,14 @@ SDK.ScreenCaptureModel = class extends SDK.SDKModel {
*/
windowOpen(url, windowName, windowFeatures, userGesture) {
}
+
+ /**
+ * @override
+ * @param {string} url
+ * @param {string} data
+ */
+ compilationCacheProduced(url, data) {
+ }
};
SDK.SDKModel.register(SDK.ScreenCaptureModel, SDK.Target.Capability.ScreenCapture, false);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/Target.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/Target.js
index 87cc1c6af87..d338bda71b0 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/Target.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/Target.js
@@ -16,8 +16,9 @@ SDK.Target = class extends Protocol.TargetBase {
* @param {!Protocol.InspectorBackend.Connection.Factory} connectionFactory
* @param {?SDK.Target} parentTarget
* @param {boolean} suspended
+ * @param {boolean} isNodeJS
*/
- constructor(targetManager, id, name, capabilitiesMask, connectionFactory, parentTarget, suspended) {
+ constructor(targetManager, id, name, capabilitiesMask, connectionFactory, parentTarget, suspended, isNodeJS) {
super(connectionFactory);
this._targetManager = targetManager;
this._name = name;
@@ -27,6 +28,7 @@ SDK.Target = class extends Protocol.TargetBase {
this._id = id;
this._modelByConstructor = new Map();
this._isSuspended = suspended;
+ this._isNodeJS = isNodeJS;
}
createModels(required) {
@@ -46,12 +48,11 @@ SDK.Target = class extends Protocol.TargetBase {
* @return {boolean}
*/
isNodeJS() {
- // TODO(lushnikov): this is an unreliable way to detect Node.js targets.
- return this._capabilitiesMask === SDK.Target.Capability.JS || this._isNodeJSForTest;
+ return this._isNodeJS;
}
- setIsNodeJSForTest() {
- this._isNodeJSForTest = true;
+ markAsNodeJSForTest() {
+ this._isNodeJS = true;
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/TargetManager.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/TargetManager.js
index 268d46f72b2..bf2bad76d02 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/TargetManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/TargetManager.js
@@ -174,10 +174,12 @@ SDK.TargetManager = class extends Common.Object {
* @param {number} capabilitiesMask
* @param {!Protocol.InspectorBackend.Connection.Factory} connectionFactory
* @param {?SDK.Target} parentTarget
+ * @param {boolean} isNodeJS
* @return {!SDK.Target}
*/
- createTarget(id, name, capabilitiesMask, connectionFactory, parentTarget) {
- const target = new SDK.Target(this, id, name, capabilitiesMask, connectionFactory, parentTarget, this._isSuspended);
+ createTarget(id, name, capabilitiesMask, connectionFactory, parentTarget, isNodeJS) {
+ const target =
+ new SDK.Target(this, id, name, capabilitiesMask, connectionFactory, parentTarget, this._isSuspended, isNodeJS);
target.createModels(new Set(this._modelObservers.keysArray()));
this._targets.push(target);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sdk/TracingModel.js b/chromium/third_party/blink/renderer/devtools/front_end/sdk/TracingModel.js
index 237da35a275..a440968ca7d 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sdk/TracingModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sdk/TracingModel.js
@@ -248,19 +248,20 @@ SDK.TracingModel = class {
* @param {!SDK.TracingModel.Event} event
*/
_addSampleEvent(event) {
- const group = this._profileGroups.get(event.id);
+ const id = `${event.thread.process().id()}:${event.id}`;
+ const group = this._profileGroups.get(id);
if (group)
group._addChild(event);
else
- this._profileGroups.set(event.id, new SDK.TracingModel.ProfileEventsGroup(event));
+ this._profileGroups.set(id, new SDK.TracingModel.ProfileEventsGroup(event));
}
/**
- * @param {string} id
+ * @param {!SDK.TracingModel.Event} event
* @return {?SDK.TracingModel.ProfileEventsGroup}
*/
- profileGroup(id) {
- return this._profileGroups.get(id) || null;
+ profileGroup(event) {
+ return this._profileGroups.get(`${event.thread.process().id()}:${event.id}`) || null;
}
/**
@@ -293,6 +294,14 @@ SDK.TracingModel = class {
}
/**
+ * @param {number} pid
+ * @return {?SDK.TracingModel.Process}
+ */
+ processById(pid) {
+ return this._processById.get(pid) || null;
+ }
+
+ /**
* @param {string} processName
* @param {string} threadName
* @return {?SDK.TracingModel.Thread}
@@ -558,16 +567,6 @@ SDK.TracingModel.Event = class {
* @param {!SDK.TracingModel.Event} b
* @return {number}
*/
- static compareStartAndEndTime(a, b) {
- return a.startTime - b.startTime || (b.endTime !== undefined && a.endTime !== undefined && b.endTime - a.endTime) ||
- 0;
- }
-
- /**
- * @param {!SDK.TracingModel.Event} a
- * @param {!SDK.TracingModel.Event} b
- * @return {number}
- */
static orderedCompareStartTime(a, b) {
// Array.mergeOrdered coalesces objects if comparator returns 0.
// To change this behavior this comparator return -1 in the case events
@@ -884,7 +883,7 @@ SDK.TracingModel.Thread = class extends SDK.TracingModel.NamedObject {
}
tracingComplete() {
- this._asyncEvents.stableSort(SDK.TracingModel.Event.compareStartAndEndTime);
+ this._asyncEvents.stableSort(SDK.TracingModel.Event.compareStartTime);
this._events.stableSort(SDK.TracingModel.Event.compareStartTime);
const phases = SDK.TracingModel.Phase;
const stack = [];
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourceFrame.js b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourceFrame.js
index 04a9d361bf1..f2d5e15bbee 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourceFrame.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/source_frame/SourceFrame.js
@@ -312,8 +312,10 @@ SourceFrame.SourceFrame = class extends UI.SimpleView {
if (!this.loaded || !this.isShowing())
return;
- this._textEditor.revealPosition(
- this._positionToReveal.line, this._positionToReveal.column, this._positionToReveal.shouldHighlight);
+ const [line, column] =
+ this._transformer.rawToEditorLocation(this._positionToReveal.line, this._positionToReveal.column);
+
+ this._textEditor.revealPosition(line, column, this._positionToReveal.shouldHighlight);
this._positionToReveal = null;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js
index 17a3370c355..2e0970490ba 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js
@@ -735,11 +735,6 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
Sources.SourceMapNamesResolver.resolveScopeInObject(localScope)
.getAllProperties(false, false, this._prepareScopeVariables.bind(this, callFrame));
}
-
- if (this._clearValueWidgetsTimer) {
- clearTimeout(this._clearValueWidgetsTimer);
- this._clearValueWidgetsTimer = null;
- }
}
_showContinueToLocations() {
@@ -923,19 +918,16 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
* @param {?Array.<!SDK.RemoteObjectProperty>} internalProperties
*/
_prepareScopeVariables(callFrame, properties, internalProperties) {
- if (!properties || !properties.length || properties.length > 500 || !this._textEditor.isShowing()) {
- this._clearValueWidgets();
+ this._clearValueWidgets();
+ if (!properties || !properties.length || properties.length > 500 || !this._textEditor.isShowing())
return;
- }
const functionUILocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(
/** @type {!SDK.DebuggerModel.Location} */ (callFrame.functionLocation()));
const executionUILocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(callFrame.location());
if (!functionUILocation || !executionUILocation || functionUILocation.uiSourceCode !== this._uiSourceCode ||
- executionUILocation.uiSourceCode !== this._uiSourceCode) {
- this._clearValueWidgets();
+ executionUILocation.uiSourceCode !== this._uiSourceCode)
return;
- }
const functionEditorLocation =
this._transformer.rawToEditorLocation(functionUILocation.lineNumber, functionUILocation.columnNumber);
@@ -943,17 +935,9 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
this._transformer.rawToEditorLocation(executionUILocation.lineNumber, executionUILocation.columnNumber);
const fromLine = functionEditorLocation[0];
const fromColumn = functionEditorLocation[1];
- let toLine = executionEditorLocation[0];
-
- // Make sure we have a chance to update all existing widgets.
- if (this._valueWidgets) {
- for (const line of this._valueWidgets.keys())
- toLine = Math.max(toLine, line + 1);
- }
- if (fromLine >= toLine || toLine - fromLine > 500 || fromLine < 0 || toLine >= this._textEditor.linesCount) {
- this._clearValueWidgets();
+ const toLine = executionEditorLocation[0];
+ if (fromLine >= toLine || toLine - fromLine > 500 || fromLine < 0 || toLine >= this._textEditor.linesCount)
return;
- }
const valuesMap = new Map();
for (const property of properties)
@@ -1069,6 +1053,10 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
if (this._executionLocation)
this._textEditor.clearExecutionLine();
this._executionLocation = null;
+ if (this._clearValueWidgetsTimer) {
+ clearTimeout(this._clearValueWidgetsTimer);
+ this._clearValueWidgetsTimer = null;
+ }
this._clearValueWidgetsTimer = setTimeout(this._clearValueWidgets.bind(this), 1000);
this._clearContinueToLocationsNoRestore();
});
@@ -1535,18 +1523,8 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
*/
async _createNewBreakpoint(editorLineNumber, condition, enabled) {
Host.userMetrics.actionTaken(Host.UserMetrics.Action.ScriptsBreakpointSet);
-
- const origin = this._transformer.editorToRawLocation(editorLineNumber, 0);
- const maxLengthToCheck = 1024;
- let linesToCheck = 5;
- for (; editorLineNumber < this._textEditor.linesCount && linesToCheck > 0; ++editorLineNumber) {
- const lineLength = this._textEditor.line(editorLineNumber).length;
- if (lineLength > maxLengthToCheck)
- break;
- if (lineLength === 0)
- continue;
- --linesToCheck;
-
+ if (editorLineNumber < this._textEditor.linesCount) {
+ const lineLength = Math.min(this._textEditor.line(editorLineNumber).length, 1024);
const start = this._transformer.editorToRawLocation(editorLineNumber, 0);
const end = this._transformer.editorToRawLocation(editorLineNumber, lineLength);
const locations = await this._breakpointManager.possibleBreakpoints(
@@ -1556,7 +1534,8 @@ Sources.DebuggerPlugin = class extends Sources.UISourceCodeFrame.Plugin {
return;
}
}
- this._setBreakpoint(origin[0], origin[1], condition, enabled);
+ const origin = this._transformer.editorToRawLocation(editorLineNumber, 0);
+ await this._setBreakpoint(origin[0], origin[1], condition, enabled);
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js b/chromium/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js
index c546259447a..733509e4af9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js
@@ -83,8 +83,8 @@ Sources.WatchExpressionsSidebarPane = class extends UI.ThrottledWidget {
this._watchExpressionsSetting.set(toSave);
}
- _addButtonClicked() {
- UI.viewManager.showView('sources.watch');
+ async _addButtonClicked() {
+ await UI.viewManager.showView('sources.watch');
this._createWatchExpression(null).startEditing();
}
@@ -225,7 +225,7 @@ Sources.WatchExpressionsSidebarPane = class extends UI.ThrottledWidget {
* @param {!Object} target
*/
appendApplicableItems(event, contextMenu, target) {
- if (target instanceof ObjectUI.ObjectPropertyTreeElement) {
+ if (target instanceof ObjectUI.ObjectPropertyTreeElement && !target.property.synthetic) {
contextMenu.debugSection().appendItem(
ls`Add property path to watch`, this._addPropertyPathToWatch.bind(this, target));
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/callStackSidebarPane.css b/chromium/third_party/blink/renderer/devtools/front_end/sources/callStackSidebarPane.css
index c726005f9b8..66d967fc0ab 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/callStackSidebarPane.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/callStackSidebarPane.css
@@ -99,3 +99,11 @@
display: block;
}
+:host-context(.-theme-with-dark-background) .blackboxed-message {
+ background-color: hsl(46, 98%, 22%);
+ color: #aaa;
+}
+
+:host-context(.-theme-with-dark-background) .blackboxed-message > .link {
+ color: hsl(0, 0%, 67%);
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/navigatorTree.css b/chromium/third_party/blink/renderer/devtools/front_end/sources/navigatorTree.css
index 51ed07e8f0c..706de5ae102 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/navigatorTree.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/navigatorTree.css
@@ -46,8 +46,8 @@
background: linear-gradient(45deg, hsl(0, 0%, 50%), hsl(0, 0%, 70%));
}
-.navigator-fs-tree-item:not(.has-mapped-files),
-.navigator-fs-folder-tree-item:not(.has-mapped-files) {
+.navigator-fs-tree-item:not(.has-mapped-files):not(.selected) > :not(.selection),
+.navigator-fs-folder-tree-item:not(.has-mapped-files):not(.selected) > :not(.selection) {
filter: grayscale(50%);
opacity: 0.5;
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources/watchExpressionsSidebarPane.css b/chromium/third_party/blink/renderer/devtools/front_end/sources/watchExpressionsSidebarPane.css
index 63bf691f2ad..4d2d52d6168 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources/watchExpressionsSidebarPane.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources/watchExpressionsSidebarPane.css
@@ -45,7 +45,6 @@
.watch-expression {
position: relative;
- padding: 0 6px;
flex: none;
min-height: 20px;
}
@@ -80,15 +79,18 @@
overflow: hidden;
white-space: nowrap;
padding-left: 4px;
+ min-height: 18px;
+ line-height: 18px;
-webkit-user-select: text;
}
.watch-expression-text-prompt-proxy {
- margin-left: 12px;
+ margin: 2px 12px;
}
.watch-expression-header {
flex: auto;
+ padding: 0 6px;
}
.watch-expression-object-header {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/EditorTestRunner.js b/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/EditorTestRunner.js
index 0c3e98abb25..a693414fc80 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/EditorTestRunner.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/sources_test_runner/EditorTestRunner.js
@@ -149,8 +149,16 @@ function fakeCodeMirrorKeyEvent(editor, eventType, code, charCode, modifiers) {
}
function fakeCodeMirrorInputEvent(editor, character) {
- if (typeof character === 'string')
- editor._codeMirror.display.input.textarea.value += character;
+ if (typeof character !== 'string')
+ return;
+ const input = editor._codeMirror.display.input;
+ const value = input.textarea.value;
+ const newValue =
+ value.substring(0, input.textarea.selectionStart) + character + value.substring(input.textarea.selectionEnd);
+ const caretPosition = input.textarea.selectionStart + character.length;
+ input.textarea.value = newValue;
+ input.textarea.setSelectionRange(caretPosition, caretPosition);
+ input.poll();
}
SourcesTestRunner.fakeKeyEvent = function(editor, originalCode, modifiers, callback) {
@@ -186,15 +194,10 @@ SourcesTestRunner.fakeKeyEvent = function(editor, originalCode, modifiers, callb
return;
}
+ const inputReadPromise = new Promise(x => editor._codeMirror.on('inputRead', x));
fakeCodeMirrorInputEvent(editor, originalCode);
fakeCodeMirrorKeyEvent(editor, 'keyup', code, charCode, modifiers);
-
- function callbackWrapper() {
- editor._codeMirror.off('inputRead', callbackWrapper);
- callback();
- }
-
- editor._codeMirror.on('inputRead', callbackWrapper);
+ inputReadPromise.then(callback);
};
SourcesTestRunner.dumpSelectionStats = function(textEditor) {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js b/chromium/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js
index 3d0a1cf1408..2b6ef3b892a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/text_editor/CodeMirrorTextEditor.js
@@ -44,7 +44,7 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
TextEditor.CodeMirrorUtils.appendThemeStyle(this.element);
- this._codeMirror = new window.CodeMirror(this.element, {
+ this._codeMirror = new CodeMirror(this.element, {
lineNumbers: options.lineNumbers,
matchBrackets: true,
smartIndent: true,
@@ -54,7 +54,9 @@ TextEditor.CodeMirrorTextEditor = class extends UI.VBox {
indentUnit: 4,
lineWrapping: options.lineWrapping,
lineWiseCopyCut: false,
- tabIndex: 0
+ tabIndex: 0,
+ pollInterval: Math.pow(2, 31) - 1, // ~25 days
+ inputStyle: 'devToolsAccessibleTextArea'
});
this._codeMirrorElement = this.element.lastElementChild;
@@ -1692,3 +1694,93 @@ TextEditor.CodeMirrorTextEditorFactory = class {
return new TextEditor.CodeMirrorTextEditor(options);
}
};
+
+// CodeMirror uses an offscreen <textarea> to detect input. Due to inconsistencies in the many browsers it supports,
+// it simplifies things by regularly checking if something is in the textarea, adding those characters to the document,
+// and then clearing the textarea. This breaks assistive technology that wants to read from CodeMirror, because the
+// <textarea> that they interact with is constantly empty.
+// Because we target up-to-date Chrome, we can gaurantee consistent input events. This lets us leave the current
+// line from the editor in our <textarea>. CodeMirror still expects a mostly empty <textarea>, so we pass CodeMirror a
+// fake <textarea> that only contains the users input.
+CodeMirror.inputStyles.devToolsAccessibleTextArea = class extends CodeMirror.inputStyles.textarea {
+ /**
+ * @override
+ * @param {!Object} display
+ */
+ init(display) {
+ super.init(display);
+ UI.ARIAUtils.setAccessibleName(this.textarea, ls`Code editor`);
+ this.textarea.addEventListener('compositionstart', this._onCompositionStart.bind(this));
+ }
+
+ _onCompositionStart() {
+ if (this.textarea.selectionEnd === this.textarea.value.length)
+ return;
+ // CodeMirror always expects the caret to be at the end of the textarea
+ // When in IME composition mode, clip the textarea to how CodeMirror expects it,
+ // and then let CodeMirror do it's thing.
+ this.textarea.value = this.textarea.value.substring(0, this.textarea.selectionEnd);
+ this.textarea.setSelectionRange(this.textarea.value.length, this.textarea.value.length);
+ this.prevInput = this.textarea.value;
+ }
+
+ /**
+ * @override
+ * @param {boolean=} typing
+ */
+ reset(typing) {
+ if (typing || this.contextMenuPending || this.composing || this.cm.somethingSelected()) {
+ super.reset(typing);
+ return;
+ }
+
+ // When navigating around the document, keep the current visual line in the textarea.
+ const cursor = this.cm.getCursor();
+ let start, end;
+ if (this.cm.options.lineWrapping) {
+ // To get the visual line, compute the leftmost and rightmost character positions.
+ const top = this.cm.charCoords(cursor, 'page').top;
+ start = this.cm.coordsChar({left: -Infinity, top});
+ end = this.cm.coordsChar({left: Infinity, top});
+ } else {
+ // Limit the line to 1000 characters to prevent lag.
+ const offset = Math.floor(cursor.ch / 1000) * 1000;
+ start = {ch: offset, line: cursor.line};
+ end = {ch: offset + 1000, line: cursor.line};
+ }
+ this.textarea.value = this.cm.getRange(start, end);
+ const caretPosition = cursor.ch - start.ch;
+ this.textarea.setSelectionRange(caretPosition, caretPosition);
+ this.prevInput = this.textarea.value;
+ }
+
+ /**
+ * @override
+ * @return {boolean}
+ */
+ poll() {
+ if (this.contextMenuPending || this.composing)
+ return super.poll();
+ const text = this.textarea.value;
+ let start = 0;
+ const length = Math.min(this.prevInput.length, text.length);
+ while (start < length && this.prevInput[start] === text[start])
+ ++start;
+ let end = 0;
+ while (end < length - start && this.prevInput[this.prevInput.length - end - 1] === text[text.length - end - 1])
+ ++end;
+
+ // CodeMirror expects the user to be typing into a blank <textarea>.
+ // Pass a fake textarea into super.poll that only contains the users input.
+ /** @type {!HTMLTextAreaElement} */
+ const placeholder = this.textarea;
+ this.textarea = /** @type {!HTMLTextAreaElement} */ (createElement('textarea'));
+ this.textarea.value = text.substring(start, text.length - end);
+ this.textarea.setSelectionRange(placeholder.selectionStart - start, placeholder.selectionEnd - start);
+ this.prevInput = '';
+ const result = super.poll();
+ this.prevInput = text;
+ this.textarea = placeholder;
+ return result;
+ }
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/text_editor/TextEditorAutocompleteController.js b/chromium/third_party/blink/renderer/devtools/front_end/text_editor/TextEditorAutocompleteController.js
index b74645c06ff..bd2b3510cb5 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/text_editor/TextEditorAutocompleteController.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/text_editor/TextEditorAutocompleteController.js
@@ -78,8 +78,10 @@ TextEditor.TextEditorAutocompleteController = class {
*/
_beforeChange(codeMirror, changeObject) {
this._updatedLines = this._updatedLines || {};
- for (let i = changeObject.from.line; i <= changeObject.to.line; ++i)
- this._updatedLines[i] = this._codeMirror.getLine(i);
+ for (let i = changeObject.from.line; i <= changeObject.to.line; ++i) {
+ if (this._updatedLines[i] === undefined)
+ this._updatedLines[i] = this._codeMirror.getLine(i);
+ }
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineController.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineController.js
index 7a01424bc49..1cf667ee673 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineController.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineController.js
@@ -26,6 +26,10 @@ Timeline.TimelineController = class {
SDK.targetManager.observeModels(SDK.CPUProfilerModel, this);
}
+ dispose() {
+ SDK.targetManager.unobserveModels(SDK.CPUProfilerModel, this);
+ }
+
/**
* @return {!SDK.Target}
*/
@@ -224,20 +228,74 @@ Timeline.TimelineController = class {
this._tracingModel.addEvents([cpuProfileEvent]);
}
+ /**
+ * @return {?Map<string, number>}
+ */
+ _buildTargetToProcessIdMap() {
+ const metadataEventTypes = TimelineModel.TimelineModel.DevToolsMetadataEvent;
+ const metadataEvents = this._tracingModel.devToolsMetadataEvents();
+ const browserMetaEvent = metadataEvents.find(e => e.name === metadataEventTypes.TracingStartedInBrowser);
+ if (!browserMetaEvent)
+ return null;
+
+ /** @type {!Multimap<string, string>} */
+ const pseudoPidToFrames = new Multimap();
+ /** @type {!Map<string, number>} */
+ const targetIdToPid = new Map();
+ const frames = browserMetaEvent.args.data['frames'];
+ for (const frameInfo of frames)
+ targetIdToPid.set(frameInfo.frame, frameInfo.processId);
+ for (const event of metadataEvents) {
+ const data = event.args.data;
+ switch (event.name) {
+ case metadataEventTypes.FrameCommittedInBrowser:
+ if (data.processId)
+ targetIdToPid.set(data.frame, data.processId);
+ else
+ pseudoPidToFrames.set(data.processPseudoId, data.frame);
+ break;
+ case metadataEventTypes.ProcessReadyInBrowser:
+ for (const frame of pseudoPidToFrames.get(data.processPseudoId) || [])
+ targetIdToPid.set(frame, data.processId);
+ break;
+ }
+ }
+ const mainFrame = frames.find(frame => !frame.parent);
+ const mainRendererProcessId = mainFrame.processId;
+ const mainProcess = this._tracingModel.processById(mainRendererProcessId);
+ if (mainProcess)
+ targetIdToPid.set(SDK.targetManager.mainTarget().id(), mainProcess.id());
+ return targetIdToPid;
+ }
+
_injectCpuProfileEvents() {
if (!this._cpuProfiles)
return;
const metadataEventTypes = TimelineModel.TimelineModel.DevToolsMetadataEvent;
const metadataEvents = this._tracingModel.devToolsMetadataEvents();
- const mainMetaEvent =
- metadataEvents.filter(event => event.name === metadataEventTypes.TracingStartedInPage).peekLast();
- if (!mainMetaEvent)
- return;
- const pid = mainMetaEvent.thread.process().id();
- const mainCpuProfile = this._cpuProfiles.get(this._tracingManager.target().id());
- this._injectCpuProfileEvent(pid, mainMetaEvent.thread.id(), mainCpuProfile);
+ const targetIdToPid = this._buildTargetToProcessIdMap();
+ if (targetIdToPid) {
+ for (const [id, profile] of this._cpuProfiles) {
+ const pid = targetIdToPid.get(id);
+ if (!pid)
+ continue;
+ const process = this._tracingModel.processById(pid);
+ const thread = process && process.threadByName(TimelineModel.TimelineModel.RendererMainThreadName);
+ if (thread)
+ this._injectCpuProfileEvent(pid, thread.id(), profile);
+ }
+ } else {
+ // Legacy backends support.
+ const mainMetaEvent =
+ metadataEvents.filter(event => event.name === metadataEventTypes.TracingStartedInPage).peekLast();
+ if (mainMetaEvent) {
+ const pid = mainMetaEvent.thread.process().id();
+ const mainCpuProfile = this._cpuProfiles.get(this._tracingManager.target().id());
+ this._injectCpuProfileEvent(pid, mainMetaEvent.thread.id(), mainCpuProfile);
+ }
+ }
const workerMetaEvents =
metadataEvents.filter(event => event.name === metadataEventTypes.TracingSessionIdForWorker);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineHistoryManager.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineHistoryManager.js
index 04da83f896f..7bd3fc06a89 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineHistoryManager.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelineHistoryManager.js
@@ -435,6 +435,7 @@ Timeline.TimelineHistoryManager.ToolbarButton = class extends UI.ToolbarItem {
this.element.addEventListener('click', () => void action.execute(), false);
this.setEnabled(action.enabled());
action.addEventListener(UI.Action.Events.Enabled, event => this.setEnabled(/** @type {boolean} */ (event.data)));
+ this.setTitle(action.title());
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelinePanel.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelinePanel.js
index 621e7272c91..920d3442256 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelinePanel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/TimelinePanel.js
@@ -74,7 +74,9 @@ Timeline.TimelinePanel = class extends UI.Panel {
this._showMemorySetting.setTitle(Common.UIString('Memory'));
this._showMemorySetting.addChangeListener(this._onModeChanged, this);
- this._panelToolbar = new UI.Toolbar('', this.element);
+ const timelineToolbarContainer = this.element.createChild('div', 'timeline-toolbar-container');
+ this._panelToolbar = new UI.Toolbar('timeline-main-toolbar', timelineToolbarContainer);
+ this._panelRightToolbar = new UI.Toolbar('', timelineToolbarContainer);
this._createSettingsPane();
this._updateShowSettingsToolbarButton();
@@ -228,10 +230,8 @@ Timeline.TimelinePanel = class extends UI.Panel {
this._panelToolbar.appendToolbarItem(UI.Toolbar.createActionButtonForId('components.collect-garbage'));
// Settings
- this._panelToolbar.appendSpacer();
- this._panelToolbar.appendText('');
- this._panelToolbar.appendSeparator();
- this._panelToolbar.appendToolbarItem(this._showSettingsPaneButton);
+ this._panelRightToolbar.appendSeparator();
+ this._panelRightToolbar.appendToolbarItem(this._showSettingsPaneButton);
}
_createSettingsPane() {
@@ -498,6 +498,7 @@ Timeline.TimelinePanel = class extends UI.Panel {
this._setState(Timeline.TimelinePanel.State.StopPending);
this._performanceModel = await this._controller.stopRecording();
this._setUIControlsEnabled(true);
+ this._controller.dispose();
this._controller = null;
}
@@ -513,6 +514,7 @@ Timeline.TimelinePanel = class extends UI.Panel {
this._historyManager.setEnabled(this._state === state.Idle);
this._clearButton.setEnabled(this._state === state.Idle);
this._panelToolbar.setEnabled(this._state !== state.Loading);
+ this._panelRightToolbar.setEnabled(this._state !== state.Loading);
this._dropTarget.setEnabled(this._state === state.Idle);
this._loadButton.setEnabled(this._state === state.Idle);
this._saveButton.setEnabled(this._state === state.Idle && !!this._performanceModel);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline/timelinePanel.css b/chromium/third_party/blink/renderer/devtools/front_end/timeline/timelinePanel.css
index 4d11a809d88..24a3e64bc15 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline/timelinePanel.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline/timelinePanel.css
@@ -27,11 +27,20 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-.panel.timeline > .toolbar {
+.timeline-toolbar-container {
+ display: flex;
+ flex: none;
+}
+
+.timeline-toolbar-container > .toolbar {
background-color: var(--toolbar-bg-color);
border-bottom: var(--divider-border);
}
+.timeline-main-toolbar {
+ flex: 1 1 auto;
+}
+
.timeline-settings-pane {
flex: none;
background-color: var(--toolbar-bg-color);
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js
index da32a6b9dde..d5a6910fb15 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineModel.js
@@ -170,7 +170,7 @@ TimelineModel.TimelineModel = class {
else
this._processGenericTrace(tracingModel);
}
- this._inspectedTargetEvents.sort(SDK.TracingModel.Event.compareStartTime);
+ this._inspectedTargetEvents.stableSort(SDK.TracingModel.Event.compareStartTime);
this._processAsyncBrowserEvents(tracingModel);
this._buildGPUEvents(tracingModel);
this._resetProcessingState();
@@ -429,7 +429,7 @@ TimelineModel.TimelineModel = class {
cpuProfileEvent = events.find(e => e.name === TimelineModel.TimelineModel.RecordType.Profile);
if (!cpuProfileEvent)
return null;
- const profileGroup = tracingModel.profileGroup(cpuProfileEvent.id);
+ const profileGroup = tracingModel.profileGroup(cpuProfileEvent);
if (!profileGroup) {
Common.console.error('Invalid CPU profile format.');
return null;
@@ -635,7 +635,7 @@ TimelineModel.TimelineModel = class {
for (const [type, events] of groups) {
const track = this._ensureNamedTrack(type);
track.thread = thread;
- track.asyncEvents = track.asyncEvents.mergeOrdered(events, SDK.TracingModel.Event.compareStartAndEndTime);
+ track.asyncEvents = track.asyncEvents.mergeOrdered(events, SDK.TracingModel.Event.compareStartTime);
}
}
@@ -850,7 +850,7 @@ TimelineModel.TimelineModel = class {
}
case recordTypes.FrameStartedLoading:
- if (this._mainFrame.frameId !== event.args['frame'])
+ if (timelineData.frameId !== event.args['frame'])
return false;
break;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineProfileTree.js b/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineProfileTree.js
index 1aa2b08bede..47af9d6458f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineProfileTree.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/timeline_model/TimelineProfileTree.js
@@ -579,6 +579,6 @@ TimelineModel.TimelineProfileTree._eventId = function(event) {
const functionName = frame['functionName'];
const name = TimelineModel.TimelineJSProfileProcessor.isNativeRuntimeFrame(frame) ?
TimelineModel.TimelineJSProfileProcessor.nativeGroup(functionName) || functionName :
- `${functionName}:${frame['lineNumber']}`;
+ `${functionName}:${frame['lineNumber']}:${frame['columnNumber']}`;
return `f:${name}@${location}`;
};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/toolbox.html b/chromium/third_party/blink/renderer/devtools/front_end/toolbox.html
index 03b95ec0854..267356c087a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/toolbox.html
+++ b/chromium/third_party/blink/renderer/devtools/front_end/toolbox.html
@@ -4,7 +4,7 @@
* found in the LICENSE file.
-->
<!doctype html>
-<html>
+<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' ">
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/FilterBar.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/FilterBar.js
index 2cbea285a97..a69356388bf 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/FilterBar.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/FilterBar.js
@@ -328,7 +328,7 @@ UI.NamedBitSetFilterUI = class extends Common.Object {
this._allowedTypes[UI.NamedBitSetFilterUI.ALL_TYPES] = true;
}
for (const typeName in this._typeFilterElements)
- this._typeFilterElements[typeName].classList.toggle('selected', this._allowedTypes[typeName]);
+ this._typeFilterElements[typeName].classList.toggle('selected', !!this._allowedTypes[typeName]);
this.dispatchEventToListeners(UI.FilterUI.Events.FilterChanged, null);
}
@@ -338,7 +338,7 @@ UI.NamedBitSetFilterUI = class extends Common.Object {
* @param {string=} title
*/
_addBit(name, label, title) {
- const typeFilterElement = this._filtersElement.createChild('li', name);
+ const typeFilterElement = this._filtersElement.createChild('span', name);
typeFilterElement.typeName = name;
typeFilterElement.createTextChild(label);
if (title)
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/Fragment.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/Fragment.js
index b7aabfb6f6e..3911e9be852 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/Fragment.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/Fragment.js
@@ -58,16 +58,15 @@ UI.Fragment = class {
*/
static _template(strings) {
let html = '';
- let insideText = false;
+ let insideText = true;
for (let i = 0; i < strings.length - 1; i++) {
html += strings[i];
const close = strings[i].lastIndexOf('>');
- if (close !== -1) {
- if (strings[i].indexOf('<', close + 1) === -1)
- insideText = true;
- else
- insideText = false;
- }
+ const open = strings[i].indexOf('<', close + 1);
+ if (close !== -1 && open === -1)
+ insideText = true;
+ else if (open !== -1)
+ insideText = false;
html += insideText ? UI.Fragment._textMarker : UI.Fragment._attributeMarker(i);
}
html += strings[strings.length - 1];
@@ -163,15 +162,7 @@ UI.Fragment = class {
result._elementsById.set(/** @type {string} */ (bind.elementId), element);
} else if ('replaceNodeIndex' in bind) {
const value = values[/** @type {number} */ (bind.replaceNodeIndex)];
- let node = null;
- if (value instanceof Node)
- node = value;
- else if (value instanceof UI.Fragment)
- node = value._element;
- else
- node = createTextNode('' + value);
-
- element.parentNode.replaceChild(node, element);
+ element.parentNode.replaceChild(this._nodeForValue(value), element);
} else if ('attr' in bind) {
if (bind.attr.names.length === 2 && bind.attr.values.length === 1 &&
typeof values[bind.attr.index] === 'function') {
@@ -197,6 +188,24 @@ UI.Fragment = class {
}
return result;
}
+
+ /**
+ * @param {*} value
+ * @return {!Node}
+ */
+ static _nodeForValue(value) {
+ if (value instanceof Node)
+ return value;
+ if (value instanceof UI.Fragment)
+ return value._element;
+ if (Array.isArray(value)) {
+ const node = createDocumentFragment();
+ for (const v of value)
+ node.appendChild(this._nodeForValue(v));
+ return node;
+ }
+ return createTextNode('' + value);
+ }
};
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/Panel.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/Panel.js
index 3c0387a7255..30f0ad36fb9 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/Panel.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/Panel.js
@@ -45,8 +45,6 @@ UI.Panel = class extends UI.VBox {
// For testing.
UI.panels[name] = this;
-
- this._shortcuts = /** !Object.<number, function(Event=):boolean> */ ({});
}
get name() {
@@ -69,16 +67,6 @@ UI.Panel = class extends UI.VBox {
}
/**
- * @param {!KeyboardEvent} event
- */
- handleShortcut(event) {
- const shortcutKey = UI.KeyboardShortcut.makeKeyFromEvent(event);
- const handler = this._shortcuts[shortcutKey];
- if (handler && handler(event))
- event.handled = true;
- }
-
- /**
* @param {!UI.Infobar} infobar
*/
showInfobar(infobar) {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutRegistry.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutRegistry.js
index ae30dc17ca8..6b72862fccf 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutRegistry.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutRegistry.js
@@ -147,6 +147,21 @@ UI.ShortcutRegistry = class {
return true;
const modifiers = UI.KeyboardShortcut.Modifiers;
+ // Undo/Redo will also cause input, so textual undo should take precedence over DevTools undo when editing.
+ if (Host.isMac()) {
+ if (UI.KeyboardShortcut.makeKey('z', modifiers.Meta) === key)
+ return true;
+ if (UI.KeyboardShortcut.makeKey('z', modifiers.Meta | modifiers.Shift) === key)
+ return true;
+ } else {
+ if (UI.KeyboardShortcut.makeKey('z', modifiers.Ctrl) === key)
+ return true;
+ if (UI.KeyboardShortcut.makeKey('y', modifiers.Ctrl) === key)
+ return true;
+ if (!Host.isWin() && UI.KeyboardShortcut.makeKey('z', modifiers.Ctrl | modifiers.Shift) === key)
+ return true;
+ }
+
if ((keyModifiers & (modifiers.Ctrl | modifiers.Alt)) === (modifiers.Ctrl | modifiers.Alt))
return Host.isWin();
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutsScreen.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutsScreen.js
index 8daf09a3515..9bcd4f061b8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutsScreen.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/ShortcutsScreen.js
@@ -52,9 +52,10 @@ UI.ShortcutsScreen = class {
elementsSection.addAlternateKeys(
UI.ShortcutsScreen.ElementsPanelShortcuts.EditAttribute, Common.UIString('Edit attribute'));
elementsSection.addAlternateKeys(
- UI.ShortcutsScreen.ElementsPanelShortcuts.HideElement, Common.UIString('Hide element'));
+ UI.shortcutRegistry.shortcutDescriptorsForAction('elements.hide-element'), Common.UIString('Hide element'));
elementsSection.addAlternateKeys(
- UI.ShortcutsScreen.ElementsPanelShortcuts.ToggleEditAsHTML, Common.UIString('Toggle edit as HTML'));
+ UI.shortcutRegistry.shortcutDescriptorsForAction('elements.edit-as-html'),
+ Common.UIString('Toggle edit as HTML'));
const stylesPaneSection = UI.shortcutsScreen.section(Common.UIString('Styles Pane'));
@@ -371,10 +372,6 @@ UI.ShortcutsScreen.ElementsPanelShortcuts = {
EditAttribute: [UI.KeyboardShortcut.makeDescriptor(UI.KeyboardShortcut.Keys.Enter)],
- HideElement: [UI.KeyboardShortcut.makeDescriptor(UI.KeyboardShortcut.Keys.H)],
-
- ToggleEditAsHTML: [UI.KeyboardShortcut.makeDescriptor(UI.KeyboardShortcut.Keys.F2)],
-
NextProperty: [UI.KeyboardShortcut.makeDescriptor(UI.KeyboardShortcut.Keys.Tab)],
PreviousProperty:
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/SuggestBox.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/SuggestBox.js
index 3294d29461c..1ede0c2fcfa 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/SuggestBox.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/SuggestBox.js
@@ -128,7 +128,9 @@ UI.SuggestBox = class {
}
}
const element = this.createElementForItem(/** @type {!UI.SuggestBox.Suggestion} */ (maxItem));
- return Math.min(kMaxWidth, UI.measurePreferredSize(element, this._element).width);
+ const preferredWidth =
+ UI.measurePreferredSize(element, this._element).width + UI.measuredScrollbarWidth(this._element.ownerDocument);
+ return Math.min(kMaxWidth, preferredWidth);
}
/**
@@ -197,7 +199,7 @@ UI.SuggestBox = class {
element.classList.add('secondary');
element.tabIndex = -1;
const maxTextLength = 50 + query.length;
- const displayText = (item.title || item.text).trimEnd(maxTextLength);
+ const displayText = (item.title || item.text).trim().trimEnd(maxTextLength).replace(/\n/g, '\u21B5');
const titleElement = element.createChild('span', 'suggestion-title');
const index = displayText.toLowerCase().indexOf(query.toLowerCase());
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/TextEditor.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/TextEditor.js
index 05044711691..a06fa966a9a 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/TextEditor.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/TextEditor.js
@@ -116,7 +116,7 @@ UI.TextEditor.Options;
/**
* @typedef {{
* substituteRangeCallback: ((function(number, number):?TextUtils.TextRange)|undefined),
- * tooltipCallback: ((function(number, number):?Element)|undefined),
+ * tooltipCallback: ((function(number, number):!Promise<?Element>)|undefined),
* suggestionsCallback: ((function(!TextUtils.TextRange, !TextUtils.TextRange, boolean=):?Promise.<!UI.SuggestBox.Suggestions>)|undefined),
* isWordChar: ((function(string):boolean)|undefined),
* anchorBehavior: (UI.GlassPane.AnchorBehavior|undefined)
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js
index d04dfc3c790..73cd26678ff 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js
@@ -39,7 +39,6 @@ UI.Toolbar = class {
constructor(className, parentElement) {
/** @type {!Array.<!UI.ToolbarItem>} */
this._items = [];
- this._reverse = false;
this.element = parentElement ? parentElement.createChild('div') : createElement('div');
this.element.className = className;
this.element.classList.add('toolbar');
@@ -201,14 +200,10 @@ UI.Toolbar = class {
}
/**
- * @param {boolean=} reverse
* @param {boolean=} growVertically
*/
- makeWrappable(reverse, growVertically) {
+ makeWrappable(growVertically) {
this._contentElement.classList.add('wrappable');
- this._reverse = !!reverse;
- if (reverse)
- this._contentElement.classList.add('wrappable-reverse');
if (growVertically)
this._contentElement.classList.add('toolbar-grow-vertical');
}
@@ -246,10 +241,7 @@ UI.Toolbar = class {
item._toolbar = this;
if (!this._enabled)
item._applyEnabledState(false);
- if (this._reverse)
- this._contentElement.insertBefore(item.element, this._insertionPoint.nextSibling);
- else
- this._contentElement.insertBefore(item.element, this._insertionPoint);
+ this._contentElement.insertBefore(item.element, this._insertionPoint);
this._hideSeparatorDupes();
}
@@ -603,7 +595,10 @@ UI.ToolbarInput = class extends UI.ToolbarItem {
const clearButton = this.element.createChild('div', 'toolbar-input-clear-button');
clearButton.appendChild(UI.Icon.create('mediumicon-gray-cross-hover', 'search-cancel-button'));
- clearButton.addEventListener('click', () => this._internalSetValue('', true));
+ clearButton.addEventListener('click', () => {
+ this._internalSetValue('', true);
+ this._prompt.focus();
+ });
this._updateEmptyStyles();
}
@@ -869,6 +864,15 @@ UI.ToolbarComboBox = class extends UI.ToolbarItem {
}
/**
+ * @override
+ * @param {string} title
+ */
+ setTitle(title) {
+ UI.ARIAUtils.setAccessibleName(this._selectElement, title);
+ super.setTitle(title);
+ }
+
+ /**
* @return {!HTMLSelectElement}
*/
selectElement() {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/Tooltip.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/Tooltip.js
index b0d39214e1d..a8034a04284 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/Tooltip.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/Tooltip.js
@@ -63,7 +63,7 @@ UI.Tooltip = class {
for (const element of path) {
// The offsetParent is null when the element or an ancestor has 'display: none'.
- if (element === this._anchorElement || element.offsetParent === null) {
+ if (element === this._anchorElement || (element.nodeName !== 'CONTENT' && element.offsetParent === null)) {
return;
} else if (element[UI.Tooltip._symbol]) {
this._show(element, mouseEvent);
@@ -135,7 +135,7 @@ UI.Tooltip = class {
if (!anchorTooltipAtElement) {
tooltipY = event.y + cursorOffset + tooltipHeight < containerBox.y + containerBox.height ?
event.y + cursorOffset :
- event.y - tooltipHeight;
+ event.y - tooltipHeight - 1;
} else {
const onBottom =
anchorBox.y + anchorOffset + anchorBox.height + tooltipHeight < containerBox.y + containerBox.height;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js
index 2e8957e05ec..9c2761c2ef7 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js
@@ -2019,3 +2019,29 @@ UI.createInlineButton = function(toolbarButton) {
shadowRoot.appendChild(toolbar.element);
return element;
};
+
+/**
+ * @param {string} text
+ * @param {number} maxLength
+ * @return {!DocumentFragment}
+ */
+UI.createExpandableText = function(text, maxLength) {
+ const fragment = createDocumentFragment();
+ fragment.textContent = text.slice(0, maxLength);
+ const hiddenText = text.slice(maxLength);
+
+ const expandButton = fragment.createChild('span', 'expandable-inline-button');
+ expandButton.setAttribute('data-text', ls`Show ${Number.withThousandsSeparator(hiddenText.length)} more`);
+ expandButton.addEventListener('click', () => {
+ if (expandButton.parentElement)
+ expandButton.parentElement.insertBefore(createTextNode(hiddenText), expandButton);
+ expandButton.remove();
+ });
+
+ const copyButton = fragment.createChild('span', 'expandable-inline-button');
+ copyButton.setAttribute('data-text', ls`Copy`);
+ copyButton.addEventListener('click', () => {
+ InspectorFrontendHost.copyText(text);
+ });
+ return fragment;
+};
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/filter.css b/chromium/third_party/blink/renderer/devtools/front_end/ui/filter.css
index 08ddde1ecb4..025789e4331 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/filter.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/filter.css
@@ -56,9 +56,10 @@
overflow: hidden;
height: 24px;
position: relative;
+ margin: 0;
}
-.filter-bitset-filter li {
+.filter-bitset-filter span {
display: inline-block;
flex: none;
margin: auto 2px;
@@ -77,22 +78,22 @@
display: inline-block;
}
-.filter-bitset-filter li.selected,
-.filter-bitset-filter li:hover,
-.filter-bitset-filter li:active {
+.filter-bitset-filter span.selected,
+.filter-bitset-filter span:hover,
+.filter-bitset-filter span:active {
color: white;
text-shadow: rgba(0, 0, 0, 0.4) 0 1px 0;
}
-.filter-bitset-filter li:hover {
+.filter-bitset-filter span:hover {
background: rgba(0, 0, 0, 0.2);
}
-.filter-bitset-filter li.selected {
+.filter-bitset-filter span.selected {
background: rgba(0, 0, 0, 0.3);
}
-.filter-bitset-filter li:active {
+.filter-bitset-filter span:active {
background: rgba(0, 0, 0, 0.5);
}
@@ -150,6 +151,7 @@
box-shadow: var(--focus-ring-inactive-shadow);
}
-.filter-input-field:focus {
+.filter-input-field:focus,
+.filter-input-field:not(:empty) {
box-shadow: var(--focus-ring-active-shadow);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css b/chromium/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css
index fb4b813f338..2e7fa6ecce4 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/inspectorCommon.css
@@ -75,7 +75,7 @@ iframe.fill {
.widget {
position: relative;
flex: auto;
- contain: layout style;
+ contain: style;
}
.hbox {
@@ -278,6 +278,7 @@ input {
:not(.platform-mac).-theme-with-dark-background ::-webkit-scrollbar,
:host-context(:not(.platform-mac).-theme-with-dark-background) ::-webkit-scrollbar {
width: 14px;
+ height: 14px;
}
:not(.platform-mac).-theme-with-dark-background ::-webkit-scrollbar-track,
@@ -395,3 +396,24 @@ label[is=dt-icon-label] {
-webkit-mask-position: var(--spritesheet-position);
background: #fafafa !important;
}
+
+.expandable-inline-button {
+ background-color: #dedede;
+ padding: 2px 4px;
+ margin: 0 2px;
+ color: #333;
+ cursor: pointer;
+ border-radius: 3px;
+ font-size: 12px;
+ font-family: sans-serif;
+ white-space: nowrap;
+ display: inline-block;
+}
+
+.expandable-inline-button::after {
+ content: attr(data-text);
+}
+
+.expandable-inline-button:hover {
+ background-color: #d5d5d5;
+}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/softContextMenu.css b/chromium/third_party/blink/renderer/devtools/front_end/ui/softContextMenu.css
index c49a1b07007..e159a13f0d3 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/softContextMenu.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/softContextMenu.css
@@ -68,7 +68,6 @@
}
.soft-context-menu-item-submenu-arrow {
- color: #222;
pointer-events: none;
font-size: 11px;
flex: 1 1 auto;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/suggestBox.css b/chromium/third_party/blink/renderer/devtools/front_end/ui/suggestBox.css
index 0e1130ba578..ea8c85e5f55 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/suggestBox.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/suggestBox.css
@@ -59,6 +59,10 @@
text-overflow: ellipsis;
}
+.suggestion-title span {
+ white-space: pre;
+}
+
.suggestion-subtitle {
flex: auto;
text-align: right;
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/toolbar.css b/chromium/third_party/blink/renderer/devtools/front_end/ui/toolbar.css
index 40da5f09a7d..d45a3f95bf8 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/toolbar.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/toolbar.css
@@ -25,10 +25,6 @@
overflow: visible;
}
-.toolbar-shadow.wrappable-reverse {
- flex-direction: row-reverse;
-}
-
.toolbar-shadow.toolbar-grow-vertical {
height: initial;
}
@@ -246,7 +242,8 @@ select.toolbar-item[data-keyboard-focus="true"]:focus > * {
box-shadow: var(--focus-ring-inactive-shadow);
}
-.toolbar-input.focused {
+.toolbar-input.focused,
+.toolbar-input:not(.toolbar-input-empty) {
box-shadow: var(--focus-ring-active-shadow);
}
@@ -263,7 +260,7 @@ select.toolbar-item[data-keyboard-focus="true"]:focus > * {
}
.toolbar-input-clear-button:hover {
- opacity: 1;
+ opacity: .99;
}
.toolbar-input-empty .toolbar-input-clear-button {
@@ -338,7 +335,8 @@ input[is=history-input]:hover {
box-shadow: var(--focus-ring-inactive-shadow);
}
-input[is=history-input]:focus {
+input[is=history-input]:focus,
+input[is=history-input]:not(:placeholder-shown) {
box-shadow: var(--focus-ring-active-shadow);
}
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/tooltip.css b/chromium/third_party/blink/renderer/devtools/front_end/ui/tooltip.css
index e1440b93b95..a0ad022cbcd 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/tooltip.css
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/tooltip.css
@@ -25,6 +25,7 @@
opacity: 0;
text-overflow: ellipsis;
overflow: hidden;
+ pointer-events: none;
}
.tooltip-breakword {
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/ui/treeoutline.js b/chromium/third_party/blink/renderer/devtools/front_end/ui/treeoutline.js
index a4adc62bfac..20a000dcab7 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/ui/treeoutline.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/ui/treeoutline.js
@@ -49,10 +49,6 @@ UI.TreeOutline = class extends Common.Object {
this.contentElement.setAttribute('tabIndex', -1);
this.element = this.contentElement;
UI.ARIAUtils.markAsTree(this.element);
-
- // Adjust to allow computing margin-left for the selection element.
- // Check the padding-left for the li element for correct value.
- this._paddingSize = 0;
}
_createRootElement() {
@@ -244,13 +240,6 @@ UI.TreeOutline = class extends Common.Object {
}
/**
- * @param {number} paddingSize
- */
- setPaddingSize(paddingSize) {
- this._paddingSize = paddingSize;
- }
-
- /**
* @param {!Event} event
*/
_treeKeyDown(event) {
@@ -787,27 +776,12 @@ UI.TreeElement = class {
}
}
- /**
- * @return {number}
- */
- computeLeftMargin() {
- let treeElement = this.parent;
- let depth = 0;
- while (treeElement !== null) {
- depth++;
- treeElement = treeElement.parent;
- }
-
- return -(this.treeOutline._paddingSize * (depth - 1) + 4);
- }
_ensureSelection() {
if (!this.treeOutline || !this.treeOutline._renderSelection)
return;
if (!this._selectionElement)
this._selectionElement = createElementWithClass('div', 'selection fill');
- if (this.treeOutline._paddingSize)
- this._selectionElement.style.setProperty('margin-left', this.computeLeftMargin() + 'px');
this._listItemNode.insertBefore(this._selectionElement, this.listItemElement.firstChild);
}
@@ -1035,6 +1009,14 @@ UI.TreeElement = class {
selectOnMouseDown(event) {
if (this.select(false, true))
event.consume(true);
+
+ if (this._listItemNode.draggable && this._selectionElement) {
+ const marginLeft =
+ this.treeOutline.element.getBoundingClientRect().left - this._listItemNode.getBoundingClientRect().left;
+ // By default the left margin extends far off screen. This is not a problem except when dragging an element.
+ // Setting the margin once here should be fine, because we believe the left margin should never change.
+ this._selectionElement.style.setProperty('margin-left', marginLeft + 'px');
+ }
}
/**
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/worker_app.html b/chromium/third_party/blink/renderer/devtools/front_end/worker_app.html
index 82f8321894f..ad332c56a7f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/worker_app.html
+++ b/chromium/third_party/blink/renderer/devtools/front_end/worker_app.html
@@ -4,7 +4,7 @@
* found in the LICENSE file.
-->
<!doctype html>
-<html>
+<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Security-Policy" content="object-src 'none'; script-src 'self' 'unsafe-eval' 'unsafe-inline' https://chrome-devtools-frontend.appspot.com">
diff --git a/chromium/third_party/blink/renderer/devtools/front_end/worker_main/WorkerMain.js b/chromium/third_party/blink/renderer/devtools/front_end/worker_main/WorkerMain.js
index ffb64e56e58..71cf0ca5c0f 100644
--- a/chromium/third_party/blink/renderer/devtools/front_end/worker_main/WorkerMain.js
+++ b/chromium/third_party/blink/renderer/devtools/front_end/worker_main/WorkerMain.js
@@ -13,7 +13,7 @@ WorkerMain.WorkerMain = class extends Common.Object {
const capabilities = SDK.Target.Capability.Browser | SDK.Target.Capability.Log | SDK.Target.Capability.Network |
SDK.Target.Capability.Target | SDK.Target.Capability.Inspector;
SDK.targetManager.createTarget(
- 'main', Common.UIString('Main'), capabilities, this._createMainConnection.bind(this), null);
+ 'main', Common.UIString('Main'), capabilities, this._createMainConnection.bind(this), null, false /* isNodeJS */);
InspectorFrontendHost.connectionReady();
new MobileThrottling.NetworkPanelIndicator();
}
diff --git a/chromium/third_party/blink/renderer/devtools/readme.md b/chromium/third_party/blink/renderer/devtools/readme.md
index 1f7a75afaee..a18a1f08cf7 100644
--- a/chromium/third_party/blink/renderer/devtools/readme.md
+++ b/chromium/third_party/blink/renderer/devtools/readme.md
@@ -45,6 +45,7 @@ The frontend is available through a git subtree mirror on [chromium.googlesource
* [Debugging protocol docs](https://developer.chrome.com/devtools/docs/debugger-protocol) and [Chrome Debugging Protocol Viewer](http://chromedevtools.github.io/debugger-protocol-viewer/)
* [awesome-chrome-devtools](https://github.com/paulirish/awesome-chrome-devtools): recommended tools and resources
* Contributing to DevTools: [bit.ly/devtools-contribution-guide](http://bit.ly/devtools-contribution-guide)
+* Contributing To Chrome DevTools Protocol: [docs.google.com](https://docs.google.com/document/d/1c-COD2kaK__5iMM5SEx-PzNA7HFmgttcYfOHHX0HaOM/edit?usp=sharing)
### Useful Commands
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/build/generate_protocol_externs.py b/chromium/third_party/blink/renderer/devtools/scripts/build/generate_protocol_externs.py
index 1725fa048b0..5babdfd8ade 100755
--- a/chromium/third_party/blink/renderer/devtools/scripts/build/generate_protocol_externs.py
+++ b/chromium/third_party/blink/renderer/devtools/scripts/build/generate_protocol_externs.py
@@ -231,7 +231,10 @@ def generate_protocol_externs(output_path, file1, file2):
output_file.write("\n/** @typedef {%s} */\nProtocol.%s.%s;\n" %
(type_traits[type["type"]], domain_name, type["id"]))
- output_file.write("/** @interface */\n")
+ if domain_name in ["Runtime", "Debugger", "HeapProfiler"]:
+ output_file.write("/** @constructor */\n")
+ else:
+ output_file.write("/** @interface */\n")
output_file.write("Protocol.%sDispatcher = function() {};\n" % domain_name)
if "events" in domain:
for event in domain["events"]:
diff --git a/chromium/third_party/blink/renderer/devtools/scripts/hosted_mode/server.js b/chromium/third_party/blink/renderer/devtools/scripts/hosted_mode/server.js
index ed95b9f521b..ebb34fe87fe 100644
--- a/chromium/third_party/blink/renderer/devtools/scripts/hosted_mode/server.js
+++ b/chromium/third_party/blink/renderer/devtools/scripts/hosted_mode/server.js
@@ -76,7 +76,7 @@ function requestHandler(request, response) {
var proxyFilePathToURL = {
'/front_end/SupportedCSSProperties.js': cloudURL.bind(null, 'SupportedCSSProperties.js'),
'/front_end/InspectorBackendCommands.js': cloudURL.bind(null, 'InspectorBackendCommands.js'),
- '/favicon.ico': () => 'https://chrome-devtools-frontend.appspot.com/favicon.ico'
+ '/favicon.ico': () => 'https://chrome-devtools-frontend.appspot.com/favicon.ico',
'/front_end/accessibility/ARIAProperties.js': cloudURL.bind(null, 'accessibility/ARIAProperties.js'),
};
diff --git a/chromium/third_party/blink/renderer/modules/BUILD.gn b/chromium/third_party/blink/renderer/modules/BUILD.gn
index 99f6dc245d9..6561c4f9cb5 100644
--- a/chromium/third_party/blink/renderer/modules/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/BUILD.gn
@@ -121,6 +121,7 @@ target("jumbo_" + modules_target_type, "modules") {
"//third_party/blink/renderer/modules/installedapp",
"//third_party/blink/renderer/modules/keyboard",
"//third_party/blink/renderer/modules/locks",
+ "//third_party/blink/renderer/modules/manifest",
"//third_party/blink/renderer/modules/media_capabilities",
"//third_party/blink/renderer/modules/media_controls",
"//third_party/blink/renderer/modules/mediacapturefromelement",
@@ -143,7 +144,7 @@ target("jumbo_" + modules_target_type, "modules") {
"//third_party/blink/renderer/modules/remoteplayback",
"//third_party/blink/renderer/modules/screen_orientation",
"//third_party/blink/renderer/modules/sensor",
- "//third_party/blink/renderer/modules/serviceworkers",
+ "//third_party/blink/renderer/modules/service_worker",
"//third_party/blink/renderer/modules/shapedetection",
"//third_party/blink/renderer/modules/speech",
"//third_party/blink/renderer/modules/srcobject",
@@ -155,6 +156,7 @@ target("jumbo_" + modules_target_type, "modules") {
"//third_party/blink/renderer/modules/webaudio",
"//third_party/blink/renderer/modules/webdatabase",
"//third_party/blink/renderer/modules/webgl",
+ "//third_party/blink/renderer/modules/webgpu",
"//third_party/blink/renderer/modules/webmidi",
"//third_party/blink/renderer/modules/webshare",
"//third_party/blink/renderer/modules/websockets",
@@ -188,8 +190,8 @@ jumbo_source_set("modules_testing") {
"peerconnection/testing/internals_rtc_certificate.h",
"peerconnection/testing/internals_rtc_peer_connection.cc",
"peerconnection/testing/internals_rtc_peer_connection.h",
- "serviceworkers/testing/internals_service_worker.cc",
- "serviceworkers/testing/internals_service_worker.h",
+ "service_worker/testing/internals_service_worker.cc",
+ "service_worker/testing/internals_service_worker.h",
"speech/testing/internals_speech_synthesis.cc",
"speech/testing/internals_speech_synthesis.h",
"speech/testing/platform_speech_synthesizer_mock.cc",
@@ -230,6 +232,8 @@ jumbo_source_set("unit_tests") {
"accessibility/ax_position_test.cc",
"accessibility/ax_range_test.cc",
"accessibility/ax_selection_test.cc",
+ "accessibility/testing/accessibility_selection_test.cc",
+ "accessibility/testing/accessibility_selection_test.h",
"accessibility/testing/accessibility_test.cc",
"accessibility/testing/accessibility_test.h",
"animationworklet/animation_worklet_global_scope_test.cc",
@@ -247,6 +251,8 @@ jumbo_source_set("unit_tests") {
"credentialmanager/password_credential_test.cc",
"csspaint/paint_rendering_context_2d_test.cc",
"csspaint/paint_worklet_test.cc",
+ "device_orientation/device_motion_event_pump_unittest.cc",
+ "device_orientation/device_orientation_event_pump_unittest.cc",
"document_metadata/copyless_paste_extractor_test.cc",
"eventsource/event_source_parser_test.cc",
"filesystem/dom_file_system_base_test.cc",
@@ -257,6 +263,7 @@ jumbo_source_set("unit_tests") {
"indexeddb/idb_value_wrapping_test.cc",
"indexeddb/mock_web_idb_database.cc",
"indexeddb/mock_web_idb_database.h",
+ "manifest/image_resource_type_converters_test.cc",
"media_controls/elements/media_control_input_element_test.cc",
"media_controls/elements/media_control_loading_panel_element_test.cc",
"media_controls/elements/media_control_overlay_play_button_element_test.cc",
@@ -264,6 +271,7 @@ jumbo_source_set("unit_tests") {
"media_controls/elements/media_control_scrubbing_message_element_test.cc",
"media_controls/elements/media_control_timeline_element_test.cc",
"media_controls/elements/media_control_toggle_closed_captions_button_element_test.cc",
+ "media_controls/media_controls_display_cutout_delegate_test.cc",
"media_controls/media_controls_impl_test.cc",
"media_controls/media_controls_orientation_lock_delegate_test.cc",
"media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc",
@@ -297,14 +305,14 @@ jumbo_source_set("unit_tests") {
"push_messaging/push_subscription_test.cc",
"remoteplayback/remote_playback_test.cc",
"screen_orientation/screen_orientation_controller_impl_test.cc",
- "serviceworkers/service_worker_container_test.cc",
- "serviceworkers/web_embedded_worker_impl_test.cc",
+ "service_worker/service_worker_container_test.cc",
+ "service_worker/web_embedded_worker_impl_test.cc",
"wake_lock/screen_wake_lock_test.cc",
"webaudio/audio_basic_processor_handler_test.cc",
+ "webaudio/audio_context_autoplay_test.cc",
"webaudio/audio_context_test.cc",
"webaudio/audio_worklet_global_scope_test.cc",
"webaudio/audio_worklet_thread_test.cc",
- "webaudio/base_audio_context_test.cc",
"webaudio/convolver_node_test.cc",
"webaudio/dynamics_compressor_node_test.cc",
"webaudio/script_processor_node_test.cc",
@@ -323,11 +331,13 @@ jumbo_source_set("unit_tests") {
deps = [
":modules",
":modules_testing",
+ "//services/device/public/cpp/test:test_support",
"//skia",
"//testing/gmock",
"//testing/gtest",
"//third_party/blink/public:media_devices_mojo_bindings_blink",
"//third_party/blink/renderer/core",
+ "//third_party/blink/renderer/modules/storage:unit_tests",
"//third_party/blink/renderer/platform",
"//third_party/blink/renderer/platform/wtf",
"//v8",
diff --git a/chromium/third_party/blink/renderer/modules/DEPS b/chromium/third_party/blink/renderer/modules/DEPS
index bc8b61d0902..f861230e084 100644
--- a/chromium/third_party/blink/renderer/modules/DEPS
+++ b/chromium/third_party/blink/renderer/modules/DEPS
@@ -1,5 +1,7 @@
include_rules = [
+ "+base/atomic_sequence_num.h",
"+base/memory/scoped_refptr.h",
+ "+services/network/public/cpp/shared_url_loader_factory.h",
"+services/service_manager/public/mojom/interface_provider.mojom-blink.h",
"+third_party/blink/public/common",
"+third_party/blink/public/web",
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/BUILD.gn b/chromium/third_party/blink/renderer/modules/accessibility/BUILD.gn
index fc0bb3eb371..3aadcb08e2c 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/accessibility/BUILD.gn
@@ -6,12 +6,6 @@ import("//third_party/blink/renderer/modules/modules.gni")
blink_modules_sources("accessibility") {
sources = [
- "ax_aria_grid.cc",
- "ax_aria_grid.h",
- "ax_aria_grid_cell.cc",
- "ax_aria_grid_cell.h",
- "ax_aria_grid_row.cc",
- "ax_aria_grid_row.h",
"ax_enums.cc",
"ax_enums.h",
"ax_image_map_link.cc",
@@ -60,16 +54,6 @@ blink_modules_sources("accessibility") {
"ax_sparse_attribute_setter.h",
"ax_svg_root.cc",
"ax_svg_root.h",
- "ax_table.cc",
- "ax_table.h",
- "ax_table_cell.cc",
- "ax_table_cell.h",
- "ax_table_column.cc",
- "ax_table_column.h",
- "ax_table_header_container.cc",
- "ax_table_header_container.h",
- "ax_table_row.cc",
- "ax_table_row.h",
"ax_virtual_object.cc",
"ax_virtual_object.h",
"inspector_accessibility_agent.cc",
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/accessibility_object_model_test.cc b/chromium/third_party/blink/renderer/modules/accessibility/accessibility_object_model_test.cc
index 7233d0c93bd..f48838b0f46 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/accessibility_object_model_test.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/accessibility_object_model_test.cc
@@ -3,15 +3,12 @@
// found in the LICENSE file.
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/core/dom/accessible_node.h"
-#include "third_party/blink/renderer/core/dom/accessible_node_list.h"
+#include "third_party/blink/renderer/core/aom/accessible_node.h"
+#include "third_party/blink/renderer/core/aom/accessible_node_list.h"
#include "third_party/blink/renderer/core/html/html_body_element.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/modules/accessibility/ax_object_cache_impl.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table_cell.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table_row.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
namespace blink {
@@ -228,17 +225,17 @@ TEST_F(AccessibilityObjectModelTest, Grid) {
auto* cache = AXObjectCache();
ASSERT_NE(nullptr, cache);
- auto* ax_grid = static_cast<AXTable*>(cache->GetOrCreate(grid));
+ auto* ax_grid = cache->GetOrCreate(grid);
EXPECT_EQ(16, ax_grid->AriaColumnCount());
EXPECT_EQ(9, ax_grid->AriaRowCount());
- auto* ax_cell = static_cast<AXTableCell*>(cache->GetOrCreate(cell));
- EXPECT_TRUE(ax_cell->IsTableCell());
+ auto* ax_cell = cache->GetOrCreate(cell);
+ EXPECT_TRUE(ax_cell->IsTableCellLikeRole());
EXPECT_EQ(8U, ax_cell->AriaColumnIndex());
EXPECT_EQ(5U, ax_cell->AriaRowIndex());
- auto* ax_cell2 = static_cast<AXTableCell*>(cache->GetOrCreate(cell2));
- EXPECT_TRUE(ax_cell2->IsTableCell());
+ auto* ax_cell2 = cache->GetOrCreate(cell2);
+ EXPECT_TRUE(ax_cell2->IsTableCellLikeRole());
EXPECT_EQ(10U, ax_cell2->AriaColumnIndex());
EXPECT_EQ(7U, ax_cell2->AriaRowIndex());
}
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid.cc
deleted file mode 100644
index df1a0c3d06f..00000000000
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/modules/accessibility/ax_aria_grid.h"
-
-#include "third_party/blink/renderer/modules/accessibility/ax_aria_grid_row.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table_column.h"
-
-namespace blink {
-
-AXARIAGrid::AXARIAGrid(LayoutObject* layout_object,
- AXObjectCacheImpl& ax_object_cache)
- : AXTable(layout_object, ax_object_cache) {}
-
-AXARIAGrid::~AXARIAGrid() = default;
-
-AXARIAGrid* AXARIAGrid::Create(LayoutObject* layout_object,
- AXObjectCacheImpl& ax_object_cache) {
- return new AXARIAGrid(layout_object, ax_object_cache);
-}
-
-bool AXARIAGrid::AddRow(AXObject* possible_row) {
- // This does not yet handle the case where the row is not an AXARIAGridRow or
- // AXTable row because it is in a canvas or is a virtual node, as those
- // do not have a layout object, cannot be an AXARIAGridRow, and cannot
- // currently implement the rest of our table logic.
- if (!possible_row || !possible_row->IsTableRow())
- return false;
-
- AXTableRow* row = ToAXTableRow(possible_row);
- row->SetRowIndex(static_cast<int>(rows_.size()));
- rows_.push_back(possible_row);
- return true;
-}
-
-void AXARIAGrid::ComputeRows(AXObjectVector possible_rows) {
- // Only add children that are actually rows.
- for (const auto& possible_row : possible_rows) {
- if (!AddRow(possible_row)) {
- // Normally with good authoring practices, the rows should be children of
- // the grid. However, if this is not the case, recursively look for rows
- // in the descendants of the non-row child.
- if (!possible_row->HasChildren())
- possible_row->AddChildren();
-
- ComputeRows(possible_row->Children());
- }
- }
-}
-
-unsigned AXARIAGrid::CalculateNumColumns() {
- unsigned num_cols = 0;
- for (const auto& row : rows_) {
- // Store the maximum number of columns.
- DCHECK(row->IsTableRow());
- const unsigned num_cells_in_row = ToAXTableRow(row)->Cells().size();
- if (num_cells_in_row > num_cols)
- num_cols = num_cells_in_row;
- }
- return num_cols;
-}
-
-void AXARIAGrid::AddColumnChildren(unsigned num_cols) {
- AXObjectCacheImpl& ax_cache = AXObjectCache();
- for (unsigned i = 0; i < num_cols; ++i) {
- AXTableColumn* column = ToAXTableColumn(ax_cache.GetOrCreate(kColumnRole));
- column->SetColumnIndex((int)i);
- column->SetParent(this);
- columns_.push_back(column);
- if (!column->AccessibilityIsIgnored()) // TODO is this check necessary?
- children_.push_back(column);
- }
-}
-
-void AXARIAGrid::AddHeaderContainerChild() {
- AXObject* header_container_object = HeaderContainer();
- if (header_container_object &&
- !header_container_object->AccessibilityIsIgnored())
- children_.push_back(header_container_object);
-}
-
-void AXARIAGrid::AddChildren() {
- DCHECK(!IsDetached());
- DCHECK(!have_children_);
-
- AXLayoutObject::AddChildren();
-
- if (IsAXTable() && layout_object_) {
- ComputeRows(children_);
- AddColumnChildren(CalculateNumColumns());
- AddHeaderContainerChild();
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid.h
deleted file mode 100644
index d7694c0b8f5..00000000000
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_ARIA_GRID_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_ARIA_GRID_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table.h"
-
-namespace blink {
-
-class AXObjectCacheImpl;
-
-class AXARIAGrid final : public AXTable {
- private:
- AXARIAGrid(LayoutObject*, AXObjectCacheImpl&);
-
- public:
- static AXARIAGrid* Create(LayoutObject*, AXObjectCacheImpl&);
- ~AXARIAGrid() override;
-
- bool IsAriaTable() const override { return true; }
-
- AccessibilityRole RoleValue() const final {
- return AXLayoutObject::RoleValue();
- } // Use ARIA role
-
- void AddChildren() override;
-
- private:
- // ARIA treegrids and grids support selected rows.
- bool SupportsSelectedRows() override { return true; }
- bool IsTableExposableThroughAccessibility() const override { return true; }
- bool ComputeIsDataTable() const override { return true; }
-
- void ComputeRows(AXObjectVector from_child_list);
- bool AddRow(AXObject*);
- unsigned CalculateNumColumns();
- void AddColumnChildren(unsigned num_cols);
- void AddHeaderContainerChild();
-
- DISALLOW_COPY_AND_ASSIGN(AXARIAGrid);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_ARIA_GRID_H_
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid_cell.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid_cell.cc
deleted file mode 100644
index dbccd55c912..00000000000
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid_cell.cc
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/modules/accessibility/ax_aria_grid_cell.h"
-
-#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table_row.h"
-
-namespace blink {
-
-AXARIAGridCell::AXARIAGridCell(LayoutObject* layout_object,
- AXObjectCacheImpl& ax_object_cache)
- : AXTableCell(layout_object, ax_object_cache) {}
-
-AXARIAGridCell::~AXARIAGridCell() = default;
-
-AXARIAGridCell* AXARIAGridCell::Create(LayoutObject* layout_object,
- AXObjectCacheImpl& ax_object_cache) {
- return new AXARIAGridCell(layout_object, ax_object_cache);
-}
-
-bool AXARIAGridCell::IsAriaColumnHeader() const {
- const AtomicString& role = GetAttribute(HTMLNames::roleAttr);
- return EqualIgnoringASCIICase(role, "columnheader");
-}
-
-bool AXARIAGridCell::IsAriaRowHeader() const {
- const AtomicString& role = GetAttribute(HTMLNames::roleAttr);
- return EqualIgnoringASCIICase(role, "rowheader");
-}
-
-AXObject* AXARIAGridCell::ParentTable() const {
- AXObject* ancestor =
- static_cast<AXObject*>(const_cast<AXARIAGridCell*>(this));
- do {
- ancestor = ancestor->ParentObjectUnignored();
- } while (ancestor && !ancestor->IsAXTable());
- return ancestor;
-}
-
-AXObject* AXARIAGridCell::ParentRow() const {
- AXObject* ancestor =
- static_cast<AXObject*>(const_cast<AXARIAGridCell*>(this));
- do {
- ancestor = ancestor->ParentObjectUnignored();
- } while (ancestor && !ancestor->IsTableRow());
- return ancestor;
-}
-
-bool AXARIAGridCell::RowIndexRange(
- std::pair<unsigned, unsigned>& row_range) const {
- AXObject* parent = ParentObjectUnignored();
- if (!parent)
- return false;
-
- // Use native table semantics if this is ARIA overlayed on an HTML table.
- if (AXTableCell::RowIndexRange(row_range))
- return true;
-
- AXObject* row = ParentRow();
- if (row && row->IsTableRow()) {
- // We already got a table row, use its API.
- row_range.first = ToAXTableRow(row)->RowIndex();
- } else if (parent->IsAXTable()) {
- // We reached the parent table, so we need to inspect its
- // children to determine the row index for the cell in it.
- // TODO do we still want this?
- unsigned column_count = ToAXTable(parent)->ColumnCount();
- if (!column_count)
- return false;
-
- const auto& siblings = parent->Children();
- unsigned children_size = siblings.size();
- for (unsigned k = 0; k < children_size; ++k) {
- if (siblings[k].Get() == this) {
- row_range.first = k / column_count;
- break;
- }
- }
- }
-
- // ARIA cells not based on th/td can have an aria-rowspan, however that is not
- // exposed here as this method only exposes physical coordinates, not virtual.
- row_range.second = 1;
- return true;
-}
-
-bool AXARIAGridCell::ColumnIndexRange(
- std::pair<unsigned, unsigned>& column_range) const {
- // Use native table semantics if this is ARIA overlayed on an HTML table.
- if (AXTableCell::ColumnIndexRange(column_range))
- return true;
-
- AXObject* row = ParentRow();
- if (!row)
- return false; // Auto col index range not supported if no row object
-
- DCHECK(row->IsTableRow());
- const auto& cells = ToAXTableRow(row)->Cells();
- unsigned cells_size = cells.size();
- for (unsigned k = 0; k < cells_size; ++k) {
- if (cells[k].Get() == this) {
- column_range.first = k;
- break;
- }
- }
-
- // ARIA cells not based on th/td can have an aria-colspan, however that is not
- // exposed here as this method only exposes physical coordinates, not virtual.
- column_range.second = 1;
- return true;
-}
-
-AccessibilityRole AXARIAGridCell::ScanToDecideHeaderRole() {
- if (IsAriaRowHeader())
- return kRowHeaderRole;
-
- if (IsAriaColumnHeader())
- return kColumnHeaderRole;
-
- return AXTableCell::ScanToDecideHeaderRole();
-}
-
-AXRestriction AXARIAGridCell::Restriction() const {
- const AXRestriction cell_restriction = AXLayoutObject::Restriction();
- // Specified gridcell restriction or local ARIA markup takes precedence.
- if (cell_restriction != kNone || HasAttribute(HTMLNames::aria_readonlyAttr) ||
- HasAttribute(HTMLNames::aria_disabledAttr))
- return cell_restriction;
-
- // Gridcell does not have it's own ARIA input restriction, so
- // fall back on parent grid's readonly state.
- // See ARIA specification regarding grid/treegrid and readonly.
- const AXObject* container = ParentTable();
- const bool is_in_readonly_grid = container &&
- (container->RoleValue() == kGridRole ||
- container->RoleValue() == kTreeGridRole) &&
- container->Restriction() == kReadOnly;
- return is_in_readonly_grid ? kReadOnly : kNone;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid_cell.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid_cell.h
deleted file mode 100644
index 6f9832fcf84..00000000000
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid_cell.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_ARIA_GRID_CELL_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_ARIA_GRID_CELL_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table_cell.h"
-
-namespace blink {
-
-class AXObjectCacheImpl;
-
-class AXARIAGridCell final : public AXTableCell {
- private:
- AXARIAGridCell(LayoutObject*, AXObjectCacheImpl&);
-
- public:
- static AXARIAGridCell* Create(LayoutObject*, AXObjectCacheImpl&);
- ~AXARIAGridCell() override;
-
- // fills in the start location and row span of cell
- bool RowIndexRange(std::pair<unsigned, unsigned>& row_range) const override;
- // fills in the start location and column span of cell
- bool ColumnIndexRange(
- std::pair<unsigned, unsigned>& column_range) const override;
- AccessibilityRole ScanToDecideHeaderRole() final;
- AXRestriction Restriction() const final;
-
- protected:
- bool IsAriaColumnHeader() const;
- bool IsAriaRowHeader() const;
- AXObject* ParentTable() const override;
- AXObject* ParentRow() const override;
- bool CanSetSelectedAttribute() const final {
- return Restriction() != kDisabled;
- }
-
- DISALLOW_COPY_AND_ASSIGN(AXARIAGridCell);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_ARIA_GRID_CELL_H_
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid_row.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid_row.cc
deleted file mode 100644
index b42be949953..00000000000
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid_row.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/modules/accessibility/ax_aria_grid_row.h"
-
-#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table.h"
-
-namespace blink {
-
-AXARIAGridRow::AXARIAGridRow(LayoutObject* layout_object,
- AXObjectCacheImpl& ax_object_cache)
- : AXTableRow(layout_object, ax_object_cache) {}
-
-AXARIAGridRow::~AXARIAGridRow() = default;
-
-AXARIAGridRow* AXARIAGridRow::Create(LayoutObject* layout_object,
- AXObjectCacheImpl& ax_object_cache) {
- return new AXARIAGridRow(layout_object, ax_object_cache);
-}
-
-bool AXARIAGridRow::IsARIARow() const {
- AXObject* parent = ParentTable();
- if (!parent)
- return false;
-
- AccessibilityRole parent_role = parent->AriaRoleAttribute();
- return parent_role == kTreeGridRole || parent_role == kGridRole;
-}
-
-void AXARIAGridRow::HeaderObjectsForRow(AXObjectVector& headers) {
- for (const auto& cell : Children()) {
- if (cell->RoleValue() == kRowHeaderRole)
- headers.push_back(cell);
- }
-}
-
-bool AXARIAGridRow::AddCell(AXObject* possible_cell) {
- if (!possible_cell)
- return false;
-
- AccessibilityRole role = possible_cell->RoleValue();
- if (role != kCellRole && role != kRowHeaderRole && role != kColumnHeaderRole)
- return false;
-
- cells_.push_back(possible_cell);
- return true;
-}
-
-void AXARIAGridRow::ComputeCells(AXObjectVector possible_cells) {
- // Only add children that are actually rows.
- for (const auto& possible_cell : possible_cells) {
- if (!AddCell(possible_cell)) {
- // Normally with good authoring practices, the cells should be children of
- // the row. However, if this is not the case, recursively look for cells
- // in the descendants of the non-row child.
- if (!possible_cell->HasChildren())
- possible_cell->AddChildren();
-
- ComputeCells(possible_cell->Children());
- }
- }
-}
-
-void AXARIAGridRow::AddChildren() {
- DCHECK(!IsDetached());
- DCHECK(!have_children_);
-
- AXTableRow::AddChildren();
-
- if (IsTableRow() && layout_object_) {
- ComputeCells(children_);
- }
-}
-
-AXObject* AXARIAGridRow::ParentTable() const {
- // A poorly-authored ARIA grid row could be nested within wrapper elements.
- AXObject* ancestor = static_cast<AXObject*>(const_cast<AXARIAGridRow*>(this));
- do {
- ancestor = ancestor->ParentObjectUnignored();
- } while (ancestor && !ancestor->IsAXTable());
-
- return ancestor;
-}
-
-void AXARIAGridRow::Trace(blink::Visitor* visitor) {
- visitor->Trace(cells_);
- AXTableRow::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid_row.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid_row.h
deleted file mode 100644
index 2549cfc3f14..00000000000
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_aria_grid_row.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_ARIA_GRID_ROW_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_ARIA_GRID_ROW_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table_row.h"
-
-namespace blink {
-
-class AXObjectCacheImpl;
-
-class AXARIAGridRow final : public AXTableRow {
- private:
- AXARIAGridRow(LayoutObject*, AXObjectCacheImpl&);
- void Trace(blink::Visitor*) override;
-
- AXObjectVector cells_;
-
- public:
- static AXARIAGridRow* Create(LayoutObject*, AXObjectCacheImpl&);
- ~AXARIAGridRow() override;
-
- void HeaderObjectsForRow(AXObjectVector&) override;
- AXObject* ParentTable() const final;
-
- void AddChildren() final;
- void ClearChildren() final {
- cells_.clear();
- AXTableRow::ClearChildren();
- }
- const AXObjectVector& Cells() final {
- UpdateChildrenIfNecessary();
- return cells_;
- };
-
- protected:
- bool CanSetSelectedAttribute() const final {
- return Restriction() != kDisabled;
- }
-
- private:
- bool IsARIARow() const final;
- void ComputeCells(AXObjectVector from_child_list);
- bool AddCell(AXObject*);
-
- DISALLOW_COPY_AND_ASSIGN(AXARIAGridRow);
-};
-
-DEFINE_AX_OBJECT_TYPE_CASTS(AXARIAGridRow, IsARIARow());
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_ARIA_GRID_ROW_H_
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_enums.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_enums.cc
index 81fd17865e4..a674868b4d7 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_enums.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_enums.cc
@@ -33,6 +33,8 @@ STATIC_ASSERT_ENUM(kWebAXRoleColumn, kColumnRole);
STATIC_ASSERT_ENUM(kWebAXRoleComboBoxGrouping, kComboBoxGroupingRole);
STATIC_ASSERT_ENUM(kWebAXRoleComboBoxMenuButton, kComboBoxMenuButtonRole);
STATIC_ASSERT_ENUM(kWebAXRoleComplementary, kComplementaryRole);
+STATIC_ASSERT_ENUM(kWebAXRoleContentDeletion, kContentDeletionRole);
+STATIC_ASSERT_ENUM(kWebAXRoleContentInsertion, kContentInsertionRole);
STATIC_ASSERT_ENUM(kWebAXRoleContentInfo, kContentInfoRole);
STATIC_ASSERT_ENUM(kWebAXRoleDate, kDateRole);
STATIC_ASSERT_ENUM(kWebAXRoleDateTime, kDateTimeRole);
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_enums.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_enums.h
index a434181e05f..9bee8cacfae 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_enums.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_enums.h
@@ -32,6 +32,8 @@ enum AccessibilityRole {
kComboBoxGroupingRole,
kComboBoxMenuButtonRole,
kComplementaryRole,
+ kContentDeletionRole, // ARIA role mapping expected in ARIA v1.2.
+ kContentInsertionRole, // ARIA role mapping expected in ARIA v1.2.
kContentInfoRole,
kDateRole, // No mapping to ARIA role.
kDateTimeRole, // No mapping to ARIA role.
@@ -159,7 +161,7 @@ enum AccessibilityRole {
kSearchRole,
kSearchBoxRole,
kSliderRole,
- kSliderThumbRole, // No mapping to ARIA role.
+ kSliderThumbRole, // No mapping to ARIA role.
kSpinButtonRole,
kSplitterRole,
kStaticTextRole, // No mapping to ARIA role.
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_image_map_link.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_image_map_link.cc
index cb53c16df74..a3025d4e553 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_image_map_link.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_image_map_link.cc
@@ -29,7 +29,7 @@
#include "third_party/blink/renderer/modules/accessibility/ax_image_map_link.h"
#include "SkMatrix44.h"
-#include "third_party/blink/renderer/core/dom/accessible_node.h"
+#include "third_party/blink/renderer/core/aom/accessible_node.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/modules/accessibility/ax_layout_object.h"
#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_inline_text_box.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_inline_text_box.cc
index ef9df96cacd..a0ef93d085c 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_inline_text_box.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_inline_text_box.cc
@@ -121,9 +121,11 @@ void AXInlineTextBox::GetWordBoundaries(Vector<AXRange>& words) const {
inline_text_box_->GetWordBoundaries(boundaries);
words.ReserveCapacity(boundaries.size());
for (const auto& boundary : boundaries) {
- words.emplace_back(
+ const AXRange range(
AXPosition::CreatePositionInTextObject(*this, boundary.start_index),
AXPosition::CreatePositionInTextObject(*this, boundary.end_index));
+ if (range.IsValid())
+ words.push_back(range);
}
}
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
index 6e03e7a6c0d..8fad56dd79e 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -28,9 +28,8 @@
#include "third_party/blink/renderer/modules/accessibility/ax_layout_object.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/core/aom/accessible_node.h"
#include "third_party/blink/renderer/core/css_property_names.h"
-#include "third_party/blink/renderer/core/dom/accessible_node.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/range.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
@@ -58,6 +57,10 @@
#include "third_party/blink/renderer/core/html/forms/labels_node_list.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/html/html_table_caption_element.h"
+#include "third_party/blink/renderer/core/html/html_table_cell_element.h"
+#include "third_party/blink/renderer/core/html/html_table_col_element.h"
+#include "third_party/blink/renderer/core/html/html_table_element.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include "third_party/blink/renderer/core/html/shadow/shadow_element_names.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
@@ -72,21 +75,31 @@
#include "third_party/blink/renderer/core/layout/layout_list_item.h"
#include "third_party/blink/renderer/core/layout/layout_list_marker.h"
#include "third_party/blink/renderer/core/layout/layout_menu_list.h"
+#include "third_party/blink/renderer/core/layout/layout_table.h"
+#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
+#include "third_party/blink/renderer/core/layout/layout_table_row.h"
+#include "third_party/blink/renderer/core/layout/layout_table_section.h"
#include "third_party/blink/renderer/core/layout/layout_text_control.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/inline/ng_inline_node.h"
+#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker.h"
#include "third_party/blink/renderer/core/loader/progress_tracker.h"
#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h"
+#include "third_party/blink/renderer/core/paint/ng/ng_paint_fragment_traversal.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/style/computed_style_constants.h"
#include "third_party/blink/renderer/core/svg/graphics/svg_image.h"
#include "third_party/blink/renderer/core/svg/svg_document_extensions.h"
#include "third_party/blink/renderer/core/svg/svg_svg_element.h"
#include "third_party/blink/renderer/modules/accessibility/ax_image_map_link.h"
#include "third_party/blink/renderer/modules/accessibility/ax_inline_text_box.h"
+#include "third_party/blink/renderer/modules/accessibility/ax_mock_object.h"
#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
#include "third_party/blink/renderer/modules/accessibility/ax_svg_root.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/graphics/image_data_buffer.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
#include "third_party/blink/renderer/platform/text/text_direction.h"
@@ -127,6 +140,10 @@ static inline bool IsInlineWithContinuation(LayoutObject* object) {
static inline LayoutObject* FirstChildConsideringContinuation(
LayoutObject* layout_object) {
+ if (layout_object->IsLayoutNGListMarker()) {
+ // We don't care tree structure of list marker.
+ return nullptr;
+ }
LayoutObject* first_child = layout_object->SlowFirstChild();
// CSS first-letter pseudo element is handled as continuation. Returning it
@@ -218,7 +235,7 @@ LayoutBoxModelObject* AXLayoutObject::GetLayoutBoxModelObject() const {
ScrollableArea* AXLayoutObject::GetScrollableAreaIfScrollable() const {
if (IsWebArea())
- return DocumentFrameView()->LayoutViewportScrollableArea();
+ return DocumentFrameView()->LayoutViewport();
if (!layout_object_ || !layout_object_->IsBox())
return nullptr;
@@ -247,12 +264,18 @@ AccessibilityRole AXLayoutObject::NativeAccessibilityRoleIgnoringAria() const {
if ((css_box && css_box->IsListItem()) || IsHTMLLIElement(node))
return kListItemRole;
- if (layout_object_->IsListMarker())
+ if (layout_object_->IsListMarkerIncludingNG())
return kListMarkerRole;
if (layout_object_->IsBR())
return kLineBreakRole;
if (layout_object_->IsText())
return kStaticTextRole;
+ if (layout_object_->IsTable() && node)
+ return IsDataTable() ? kTableRole : kLayoutTableRole;
+ if (layout_object_->IsTableRow() && node)
+ return DetermineTableRowRole();
+ if (layout_object_->IsTableCell() && node)
+ return DetermineTableCellRole();
if (css_box && IsImageOrAltText(css_box, node)) {
if (node && node->IsLink())
return kImageMapRole;
@@ -289,15 +312,26 @@ AccessibilityRole AXLayoutObject::DetermineAccessibilityRole() {
if (!layout_object_)
return kUnknownRole;
+ native_role_ = NativeAccessibilityRoleIgnoringAria();
+
if ((aria_role_ = DetermineAriaRoleAttribute()) != kUnknownRole)
return aria_role_;
- AccessibilityRole role = NativeAccessibilityRoleIgnoringAria();
// Anything that needs to still be exposed but doesn't have a more specific
// role should be considered a generic container. Examples are
// layout blocks with no node, in-page link targets, and plain elements
// such as a <span> with ARIA markup.
- return role == kUnknownRole ? kGenericContainerRole : role;
+ return native_role_ == kUnknownRole ? kGenericContainerRole : native_role_;
+}
+
+Node* AXLayoutObject::GetNodeOrContainingBlockNode() const {
+ if (IsDetached())
+ return nullptr;
+ if (GetLayoutObject()->IsAnonymousBlock() &&
+ GetLayoutObject()->ContainingBlock()) {
+ return GetLayoutObject()->ContainingBlock()->GetNode();
+ }
+ return GetNode();
}
void AXLayoutObject::Init() {
@@ -405,7 +439,7 @@ bool AXLayoutObject::IsOffScreen() const {
IntRect content_rect =
PixelSnappedIntRect(layout_object_->AbsoluteVisualRect());
LocalFrameView* view = layout_object_->GetFrame()->View();
- IntRect view_rect = view->VisibleContentRect();
+ IntRect view_rect(IntPoint(), view->Size());
view_rect.Intersect(content_rect);
return view_rect.IsEmpty();
}
@@ -526,6 +560,15 @@ bool HasAriaAttribute(Element* element) {
return false;
}
+static bool HasLineBox(const LayoutBlockFlow& block_flow) {
+ if (!block_flow.IsLayoutNGMixin())
+ return block_flow.FirstLineBox();
+ if (block_flow.HasNGInlineNodeData())
+ return !block_flow.GetNGInlineNodeData()->items.IsEmpty();
+ // TODO(layout-dev): We should call this function after layout completion.
+ return false;
+}
+
bool AXLayoutObject::ComputeAccessibilityIsIgnored(
IgnoredReasons* ignored_reasons) const {
#if DCHECK_IS_ON()
@@ -574,6 +617,9 @@ bool AXLayoutObject::ComputeAccessibilityIsIgnored(
return true;
}
+ if (IsTableLikeRole() || IsTableRowLikeRole() || IsTableCellLikeRole())
+ return false;
+
// A LayoutEmbeddedContent is an iframe element or embedded object element or
// something like that. We don't want to ignore those.
if (layout_object_->IsLayoutEmbeddedContent())
@@ -681,6 +727,12 @@ bool AXLayoutObject::ComputeAccessibilityIsIgnored(
if (RoleValue() == kFigureRole)
return false;
+ if (RoleValue() == kContentDeletionRole)
+ return false;
+
+ if (RoleValue() == kContentInsertionRole)
+ return false;
+
if (RoleValue() == kDetailsRole)
return false;
@@ -725,10 +777,10 @@ bool AXLayoutObject::ComputeAccessibilityIsIgnored(
// to decide.
}
- if (IsWebArea() || layout_object_->IsListMarker())
+ if (IsWebArea() || layout_object_->IsListMarkerIncludingNG())
return false;
- // Using the help text, title or accessibility description (so we
+ // Using the title or accessibility description (so we
// check if there's some kind of accessible name for the element)
// to decide an element's visibility is not as definitive as
// previous checks, so this should remain as one of the last.
@@ -763,7 +815,7 @@ bool AXLayoutObject::ComputeAccessibilityIsIgnored(
!CanSetFocusAttribute()) {
// If the layout object has any plain text in it, that text will be
// inside a LineBox, so the layout object will have a first LineBox.
- bool has_any_text = !!ToLayoutBlockFlow(layout_object_)->FirstLineBox();
+ bool has_any_text = HasLineBox(ToLayoutBlockFlow(*layout_object_));
// Always include interesting-looking objects.
if (has_any_text || MouseButtonListener())
@@ -1207,16 +1259,52 @@ void AXLayoutObject::LoadInlineTextBoxes() {
}
}
+static bool ShouldUseLayoutNG(const LayoutObject& layout_object) {
+ return (layout_object.IsLayoutInline() || layout_object.IsText()) &&
+ layout_object.EnclosingNGBlockFlow();
+}
+
+// Note: |NextOnLineInternalNG()| returns null when fragment for |layout_object|
+// is culled as legacy layout version since |LayoutInline::LastLineBox()|
+// returns null when it is culled.
+// See also |PreviousOnLineInternalNG()| which is identical except for using
+// "next" and |back()| instead of "previous" and |front()|.
+static AXObject* NextOnLineInternalNG(const AXObject& ax_object) {
+ DCHECK(ax_object.GetLayoutObject());
+ const LayoutObject& layout_object = *ax_object.GetLayoutObject();
+ DCHECK(!layout_object.IsListMarkerIncludingNG()) << layout_object;
+ DCHECK(ShouldUseLayoutNG(layout_object)) << layout_object;
+ const auto fragments = NGPaintFragment::InlineFragmentsFor(&layout_object);
+ if (fragments.IsEmpty() || fragments.IsInLayoutNGInlineFormattingContext())
+ return nullptr;
+ for (NGPaintFragmentTraversalContext runner =
+ NGPaintFragmentTraversal::NextInlineLeafOf(
+ NGPaintFragmentTraversalContext::Create(&fragments.back()));
+ !runner.IsNull();
+ runner = NGPaintFragmentTraversal::NextInlineLeafOf(runner)) {
+ LayoutObject* layout_object = runner.GetFragment()->GetLayoutObject();
+ if (AXObject* result = ax_object.AXObjectCache().GetOrCreate(layout_object))
+ return result;
+ }
+ if (!ax_object.ParentObject())
+ return nullptr;
+ // Returns next object of parent, since next of |ax_object| isn't appeared on
+ // line.
+ return ax_object.ParentObject()->NextOnLine();
+}
+
AXObject* AXLayoutObject::NextOnLine() const {
if (!GetLayoutObject())
return nullptr;
AXObject* result = nullptr;
- if (GetLayoutObject()->IsListMarker()) {
+ if (GetLayoutObject()->IsListMarkerIncludingNG()) {
AXObject* next_sibling = RawNextSibling();
if (!next_sibling || !next_sibling->Children().size())
return nullptr;
result = next_sibling->Children()[0].Get();
+ } else if (ShouldUseLayoutNG(*GetLayoutObject())) {
+ result = NextOnLineInternalNG(*this);
} else {
InlineBox* inline_box = nullptr;
if (GetLayoutObject()->IsLayoutInline()) {
@@ -1249,32 +1337,65 @@ AXObject* AXLayoutObject::NextOnLine() const {
return result;
}
+// Note: |PreviousOnLineInlineNG()| returns null when fragment for
+// |layout_object| is culled as legacy layout version since
+// |LayoutInline::FirstLineBox()| returns null when it is culled. See also
+// |NextOnLineNG()| which is identical except for using "previous" and |front()|
+// instead of "next" and |back()|.
+static AXObject* PreviousOnLineInlineNG(const AXObject& ax_object) {
+ DCHECK(ax_object.GetLayoutObject());
+ const LayoutObject& layout_object = *ax_object.GetLayoutObject();
+ DCHECK(!layout_object.IsListMarkerIncludingNG()) << layout_object;
+ DCHECK(ShouldUseLayoutNG(layout_object)) << layout_object;
+ const auto fragments = NGPaintFragment::InlineFragmentsFor(&layout_object);
+ if (fragments.IsEmpty() || fragments.IsInLayoutNGInlineFormattingContext())
+ return nullptr;
+ for (NGPaintFragmentTraversalContext runner =
+ NGPaintFragmentTraversal::PreviousInlineLeafOf(
+ NGPaintFragmentTraversalContext::Create(&fragments.front()));
+ !runner.IsNull();
+ runner = NGPaintFragmentTraversal::PreviousInlineLeafOf(runner)) {
+ LayoutObject* layout_object = runner.GetFragment()->GetLayoutObject();
+ if (AXObject* result = ax_object.AXObjectCache().GetOrCreate(layout_object))
+ return result;
+ }
+ if (!ax_object.ParentObject())
+ return nullptr;
+ // Returns previous object of parent, since next of |ax_object| isn't appeared
+ // on line.
+ return ax_object.ParentObject()->PreviousOnLine();
+}
+
AXObject* AXLayoutObject::PreviousOnLine() const {
if (!GetLayoutObject())
return nullptr;
- InlineBox* inline_box = nullptr;
- if (GetLayoutObject()->IsLayoutInline()) {
- inline_box = ToLayoutInline(GetLayoutObject())->FirstLineBox();
- } else if (GetLayoutObject()->IsText()) {
- inline_box = ToLayoutText(GetLayoutObject())->FirstTextBox();
- }
+ AXObject* result = nullptr;
+ if (ShouldUseLayoutNG(*GetLayoutObject())) {
+ result = PreviousOnLineInlineNG(*this);
+ } else {
+ InlineBox* inline_box = nullptr;
+ if (GetLayoutObject()->IsLayoutInline()) {
+ inline_box = ToLayoutInline(GetLayoutObject())->FirstLineBox();
+ } else if (GetLayoutObject()->IsText()) {
+ inline_box = ToLayoutText(GetLayoutObject())->FirstTextBox();
+ }
- if (!inline_box)
- return nullptr;
+ if (!inline_box)
+ return nullptr;
- AXObject* result = nullptr;
- for (InlineBox* prev = inline_box->PrevOnLine(); prev;
- prev = prev->PrevOnLine()) {
- LayoutObject* layout_object =
- LineLayoutAPIShim::LayoutObjectFrom(prev->GetLineLayoutItem());
- result = AXObjectCache().GetOrCreate(layout_object);
- if (result)
- break;
- }
+ for (InlineBox* prev = inline_box->PrevOnLine(); prev;
+ prev = prev->PrevOnLine()) {
+ LayoutObject* layout_object =
+ LineLayoutAPIShim::LayoutObjectFrom(prev->GetLineLayoutItem());
+ result = AXObjectCache().GetOrCreate(layout_object);
+ if (result)
+ break;
+ }
- if (!result && ParentObject())
- result = ParentObject()->PreviousOnLine();
+ if (!result && ParentObject())
+ result = ParentObject()->PreviousOnLine();
+ }
// For consistency between the forward and backward directions, try to always
// return leaf nodes.
@@ -1329,13 +1450,19 @@ String AXLayoutObject::StringValue() const {
return ToLayoutFileUploadControl(layout_object_)->FileTextValue();
// Handle other HTML input elements that aren't text controls, like date and
- // time controls, by returning the string value, with the exception of
- // checkboxes and radio buttons (which would return "on").
- if (GetNode() && IsHTMLInputElement(GetNode())) {
- HTMLInputElement* input = ToHTMLInputElement(GetNode());
- if (input->type() != InputTypeNames::checkbox &&
- input->type() != InputTypeNames::radio)
+ // time controls, by returning their value converted to text, with the
+ // exception of checkboxes and radio buttons (which would return "on"), and
+ // buttons which will return their name.
+ // https://html.spec.whatwg.org/multipage/forms.html#dom-input-value
+ if (const auto* input = ToHTMLInputElementOrNull(GetNode())) {
+ if (input->type() != InputTypeNames::button &&
+ input->type() != InputTypeNames::checkbox &&
+ input->type() != InputTypeNames::image &&
+ input->type() != InputTypeNames::radio &&
+ input->type() != InputTypeNames::reset &&
+ input->type() != InputTypeNames::submit) {
return input->value();
+ }
}
// FIXME: We might need to implement a value here for more types
@@ -1383,6 +1510,10 @@ String AXLayoutObject::TextAlternative(bool recursive,
} else if (layout_object_->IsListMarker() && !recursive) {
text_alternative = ToLayoutListMarker(layout_object_)->TextAlternative();
found_text_alternative = true;
+ } else if (layout_object_->IsLayoutNGListMarker() && !recursive) {
+ text_alternative =
+ ToLayoutNGListMarker(layout_object_)->TextAlternative();
+ found_text_alternative = true;
}
if (found_text_alternative) {
@@ -1443,9 +1574,10 @@ AXHasPopup AXLayoutObject::HasPopup() const {
return kAXHasPopupMenu;
}
+ // ARIA 1.1 default value of haspopup for combobox is "listbox".
if (RoleValue() == kComboBoxMenuButtonRole ||
RoleValue() == kTextFieldWithComboBoxRole)
- return kAXHasPopupMenu;
+ return kAXHasPopupListbox;
return AXObject::HasPopup();
}
@@ -1532,14 +1664,16 @@ AXObject* AXLayoutObject::AccessibilityHitTest(const IntPoint& point) const {
return nullptr;
auto* frame_view = DocumentFrameView();
- if (!frame_view || !frame_view->UpdateLifecycleToPrePaintClean())
+ if (!frame_view || !frame_view->UpdateAllLifecyclePhasesExceptPaint())
return nullptr;
PaintLayer* layer = ToLayoutBox(layout_object_)->Layer();
HitTestRequest request(HitTestRequest::kReadOnly | HitTestRequest::kActive);
- HitTestResult hit_test_result = HitTestResult(request, point);
- layer->HitTest(hit_test_result);
+ HitTestLocation location(point);
+ HitTestResult hit_test_result = HitTestResult(request, location);
+ layer->HitTest(location, hit_test_result,
+ LayoutRect(LayoutRect::InfiniteIntRect()));
Node* node = hit_test_result.InnerNode();
if (!node)
@@ -1658,6 +1792,15 @@ AXObject* AXLayoutObject::RawFirstChild() const {
if (!layout_object_)
return nullptr;
+ // Walk sections of a table (thead, tbody, tfoot) in visual order.
+ // Note: always call RecalcSectionsIfNeeded() before accessing
+ // the sections of a LayoutTable.
+ if (layout_object_->IsTable()) {
+ LayoutTable* table = ToLayoutTable(layout_object_);
+ table->RecalcSectionsIfNeeded();
+ return AXObjectCache().GetOrCreate(table->TopSection());
+ }
+
LayoutObject* first_child = FirstChildConsideringContinuation(layout_object_);
if (!first_child)
@@ -1670,6 +1813,13 @@ AXObject* AXLayoutObject::RawNextSibling() const {
if (!layout_object_)
return nullptr;
+ // Walk sections of a table (thead, tbody, tfoot) in visual order.
+ if (layout_object_->IsTableSection()) {
+ LayoutTableSection* section = ToLayoutTableSection(layout_object_);
+ return AXObjectCache().GetOrCreate(
+ section->Table()->SectionBelow(section, kSkipEmptySections));
+ }
+
LayoutObject* next_sibling = nullptr;
LayoutInline* inline_continuation =
@@ -1746,6 +1896,7 @@ void AXLayoutObject::AddChildren() {
AddImageMapChildren();
AddCanvasChildren();
AddRemoteSVGChildren();
+ AddTableChildren();
AddInlineTextBoxChildren(false);
AddAccessibleNodeChildren();
@@ -1765,18 +1916,6 @@ bool AXLayoutObject::CanHaveChildren() const {
return AXNodeObject::CanHaveChildren();
}
-void AXLayoutObject::UpdateChildrenIfNecessary() {
- if (NeedsToUpdateChildren())
- ClearChildren();
-
- AXObject::UpdateChildrenIfNecessary();
-}
-
-void AXLayoutObject::ClearChildren() {
- AXObject::ClearChildren();
- children_dirty_ = false;
-}
-
//
// Properties of the object's owning document or page.
//
@@ -1801,16 +1940,6 @@ Node* AXLayoutObject::GetNode() const {
return GetLayoutObject() ? GetLayoutObject()->GetNode() : nullptr;
}
-Node* AXLayoutObject::GetNodeOrContainingBlockNode() const {
- if (IsDetached())
- return nullptr;
- if (GetLayoutObject()->IsAnonymousBlock() &&
- GetLayoutObject()->ContainingBlock()) {
- return GetLayoutObject()->ContainingBlock()->GetNode();
- }
- return GetNode();
-}
-
Document* AXLayoutObject::GetDocument() const {
if (!GetLayoutObject())
return nullptr;
@@ -2460,6 +2589,529 @@ void AXLayoutObject::LineBreaks(Vector<int>& line_breaks) const {
}
}
+// The following is a heuristic used to determine if a
+// <table> should be with kTableRole or kLayoutTableRole.
+bool AXLayoutObject::IsDataTable() const {
+ if (!layout_object_ || !GetNode())
+ return false;
+
+ // If it has an ARIA role, it's definitely a data table.
+ AtomicString role;
+ if (HasAOMPropertyOrARIAAttribute(AOMStringProperty::kRole, role))
+ return true;
+
+ if (!layout_object_->IsTable())
+ return false;
+
+ // When a section of the document is contentEditable, all tables should be
+ // treated as data tables, otherwise users may not be able to work with rich
+ // text editors that allow creating and editing tables.
+ if (GetNode() && HasEditableStyle(*GetNode()))
+ return true;
+
+ // If there's no node, it's definitely a layout table. This happens
+ // when table CSS styles are used without a complete table DOM structure.
+ LayoutTable* table = ToLayoutTable(layout_object_);
+ table->RecalcSectionsIfNeeded();
+ Node* table_node = table->GetNode();
+ if (!table_node || !IsHTMLTableElement(table_node))
+ return false;
+
+ // This employs a heuristic to determine if this table should appear.
+ // Only "data" tables should be exposed as tables.
+ // Unfortunately, there is no good way to determine the difference
+ // between a "layout" table and a "data" table.
+ HTMLTableElement* table_element = ToHTMLTableElement(table_node);
+
+ // If there is a caption element, summary, THEAD, or TFOOT section, it's most
+ // certainly a data table
+ if (!table_element->Summary().IsEmpty() || table_element->tHead() ||
+ table_element->tFoot() || table_element->caption())
+ return true;
+
+ // if someone used "rules" attribute than the table should appear
+ if (!table_element->Rules().IsEmpty())
+ return true;
+
+ // if there's a colgroup or col element, it's probably a data table.
+ if (Traversal<HTMLTableColElement>::FirstChild(*table_element))
+ return true;
+
+ // go through the cell's and check for tell-tale signs of "data" table status
+ // cells have borders, or use attributes like headers, abbr, scope or axis
+ table->RecalcSectionsIfNeeded();
+ LayoutTableSection* first_body = table->FirstBody();
+ if (!first_body)
+ return false;
+
+ int num_cols_in_first_body = first_body->NumEffectiveColumns();
+ int num_rows = first_body->NumRows();
+ // If there's only one cell, it's not a good AXTable candidate.
+ if (num_rows == 1 && num_cols_in_first_body == 1)
+ return false;
+
+ // If there are at least 20 rows, we'll call it a data table.
+ if (num_rows >= 20)
+ return true;
+
+ // Store the background color of the table to check against cell's background
+ // colors.
+ const ComputedStyle* table_style = table->Style();
+ if (!table_style)
+ return false;
+ Color table_bg_color =
+ table_style->VisitedDependentColor(GetCSSPropertyBackgroundColor());
+
+ // check enough of the cells to find if the table matches our criteria
+ // Criteria:
+ // 1) must have at least one valid cell (and)
+ // 2) at least half of cells have borders (or)
+ // 3) at least half of cells have different bg colors than the table, and
+ // there is cell spacing
+ unsigned valid_cell_count = 0;
+ unsigned bordered_cell_count = 0;
+ unsigned background_difference_cell_count = 0;
+ unsigned cells_with_top_border = 0;
+ unsigned cells_with_bottom_border = 0;
+ unsigned cells_with_left_border = 0;
+ unsigned cells_with_right_border = 0;
+
+ Color alternating_row_colors[5];
+ int alternating_row_color_count = 0;
+ for (int row = 0; row < num_rows; ++row) {
+ int n_cols = first_body->NumCols(row);
+ for (int col = 0; col < n_cols; ++col) {
+ LayoutTableCell* cell = first_body->PrimaryCellAt(row, col);
+ if (!cell)
+ continue;
+ Node* cell_node = cell->GetNode();
+ if (!cell_node)
+ continue;
+
+ if (cell->Size().Width() < 1 || cell->Size().Height() < 1)
+ continue;
+
+ valid_cell_count++;
+
+ // Any <th> tag -> treat as data table.
+ if (cell_node->HasTagName(thTag))
+ return true;
+
+ // In this case, the developer explicitly assigned a "data" table
+ // attribute.
+ if (IsHTMLTableCellElement(*cell_node)) {
+ HTMLTableCellElement& cell_element = ToHTMLTableCellElement(*cell_node);
+ if (!cell_element.Headers().IsEmpty() ||
+ !cell_element.Abbr().IsEmpty() || !cell_element.Axis().IsEmpty() ||
+ !cell_element.FastGetAttribute(scopeAttr).IsEmpty())
+ return true;
+ }
+
+ const ComputedStyle* computed_style = cell->Style();
+ if (!computed_style)
+ continue;
+
+ // If the empty-cells style is set, we'll call it a data table.
+ if (computed_style->EmptyCells() == EEmptyCells::kHide)
+ return true;
+
+ // If a cell has matching bordered sides, call it a (fully) bordered cell.
+ if ((cell->BorderTop() > 0 && cell->BorderBottom() > 0) ||
+ (cell->BorderLeft() > 0 && cell->BorderRight() > 0))
+ bordered_cell_count++;
+
+ // Also keep track of each individual border, so we can catch tables where
+ // most cells have a bottom border, for example.
+ if (cell->BorderTop() > 0)
+ cells_with_top_border++;
+ if (cell->BorderBottom() > 0)
+ cells_with_bottom_border++;
+ if (cell->BorderLeft() > 0)
+ cells_with_left_border++;
+ if (cell->BorderRight() > 0)
+ cells_with_right_border++;
+
+ // If the cell has a different color from the table and there is cell
+ // spacing, then it is probably a data table cell (spacing and colors take
+ // the place of borders).
+ Color cell_color = computed_style->VisitedDependentColor(
+ GetCSSPropertyBackgroundColor());
+ if (table->HBorderSpacing() > 0 && table->VBorderSpacing() > 0 &&
+ table_bg_color != cell_color && cell_color.Alpha() != 1)
+ background_difference_cell_count++;
+
+ // If we've found 10 "good" cells, we don't need to keep searching.
+ if (bordered_cell_count >= 10 || background_difference_cell_count >= 10)
+ return true;
+
+ // For the first 5 rows, cache the background color so we can check if
+ // this table has zebra-striped rows.
+ if (row < 5 && row == alternating_row_color_count) {
+ LayoutObject* layout_row = cell->Parent();
+ if (!layout_row || !layout_row->IsBoxModelObject() ||
+ !ToLayoutBoxModelObject(layout_row)->IsTableRow())
+ continue;
+ const ComputedStyle* row_computed_style = layout_row->Style();
+ if (!row_computed_style)
+ continue;
+ Color row_color = row_computed_style->VisitedDependentColor(
+ GetCSSPropertyBackgroundColor());
+ alternating_row_colors[alternating_row_color_count] = row_color;
+ alternating_row_color_count++;
+ }
+ }
+ }
+
+ // if there is less than two valid cells, it's not a data table
+ if (valid_cell_count <= 1)
+ return false;
+
+ // half of the cells had borders, it's a data table
+ unsigned needed_cell_count = valid_cell_count / 2;
+ if (bordered_cell_count >= needed_cell_count ||
+ cells_with_top_border >= needed_cell_count ||
+ cells_with_bottom_border >= needed_cell_count ||
+ cells_with_left_border >= needed_cell_count ||
+ cells_with_right_border >= needed_cell_count)
+ return true;
+
+ // half had different background colors, it's a data table
+ if (background_difference_cell_count >= needed_cell_count)
+ return true;
+
+ // Check if there is an alternating row background color indicating a zebra
+ // striped style pattern.
+ if (alternating_row_color_count > 2) {
+ Color first_color = alternating_row_colors[0];
+ for (int k = 1; k < alternating_row_color_count; k++) {
+ // If an odd row was the same color as the first row, its not alternating.
+ if (k % 2 == 1 && alternating_row_colors[k] == first_color)
+ return false;
+ // If an even row is not the same as the first row, its not alternating.
+ if (!(k % 2) && alternating_row_colors[k] != first_color)
+ return false;
+ }
+ return true;
+ }
+
+ return false;
+}
+
+unsigned AXLayoutObject::ColumnCount() const {
+ if (AriaRoleAttribute() != kUnknownRole)
+ return AXNodeObject::ColumnCount();
+
+ LayoutObject* layout_object = GetLayoutObject();
+ if (!layout_object || !layout_object->IsTable() || !layout_object->GetNode())
+ return AXNodeObject::ColumnCount();
+
+ LayoutTable* table = ToLayoutTable(layout_object);
+ table->RecalcSectionsIfNeeded();
+ LayoutTableSection* table_section = table->TopSection();
+ if (!table_section)
+ return AXNodeObject::ColumnCount();
+
+ return table_section->NumEffectiveColumns();
+}
+
+unsigned AXLayoutObject::RowCount() const {
+ if (AriaRoleAttribute() != kUnknownRole)
+ return AXNodeObject::RowCount();
+
+ LayoutObject* layout_object = GetLayoutObject();
+ if (!layout_object || !layout_object->IsTable() || !layout_object->GetNode())
+ return AXNodeObject::RowCount();
+
+ LayoutTable* table = ToLayoutTable(layout_object);
+ table->RecalcSectionsIfNeeded();
+
+ unsigned row_count = 0;
+ LayoutTableSection* table_section = table->TopSection();
+ if (!table_section)
+ return AXNodeObject::RowCount();
+
+ while (table_section) {
+ row_count += table_section->NumRows();
+ table_section = table->SectionBelow(table_section, kSkipEmptySections);
+ }
+ return row_count;
+}
+
+unsigned AXLayoutObject::ColumnIndex() const {
+ LayoutObject* layout_object = GetLayoutObject();
+ if (!layout_object || !layout_object->GetNode())
+ return AXNodeObject::ColumnIndex();
+
+ if (layout_object->IsTableCell()) {
+ LayoutTableCell* cell = ToLayoutTableCell(layout_object);
+ return cell->Table()->AbsoluteColumnToEffectiveColumn(
+ cell->AbsoluteColumnIndex());
+ }
+
+ return AXNodeObject::ColumnIndex();
+}
+
+unsigned AXLayoutObject::RowIndex() const {
+ LayoutObject* layout_object = GetLayoutObject();
+ if (!layout_object || !layout_object->GetNode())
+ return AXNodeObject::RowIndex();
+
+ unsigned row_index = 0;
+ LayoutTableSection* row_section = nullptr;
+ LayoutTable* table = nullptr;
+ if (layout_object->IsTableRow()) {
+ LayoutTableRow* row = ToLayoutTableRow(layout_object);
+ row_index = row->RowIndex();
+ row_section = row->Section();
+ table = row->Table();
+ } else if (layout_object->IsTableCell()) {
+ LayoutTableCell* cell = ToLayoutTableCell(layout_object);
+ row_index = cell->RowIndex();
+ row_section = cell->Section();
+ table = cell->Table();
+ } else {
+ return AXNodeObject::RowIndex();
+ }
+
+ if (!table || !row_section)
+ return AXNodeObject::RowIndex();
+
+ // Since our table might have multiple sections, we have to offset our row
+ // appropriately.
+ table->RecalcSectionsIfNeeded();
+ LayoutTableSection* section = table->TopSection();
+ while (section && section != row_section) {
+ row_index += section->NumRows();
+ section = table->SectionBelow(section, kSkipEmptySections);
+ }
+
+ return row_index;
+}
+
+unsigned AXLayoutObject::ColumnSpan() const {
+ LayoutObject* layout_object = GetLayoutObject();
+ if (!layout_object || !layout_object->IsTableCell())
+ return AXNodeObject::ColumnSpan();
+
+ LayoutTableCell* cell = ToLayoutTableCell(layout_object);
+ unsigned absolute_first_col = cell->AbsoluteColumnIndex();
+ unsigned absolute_last_col = absolute_first_col + cell->ColSpan() - 1;
+ unsigned effective_first_col =
+ cell->Table()->AbsoluteColumnToEffectiveColumn(absolute_first_col);
+ unsigned effective_last_col =
+ cell->Table()->AbsoluteColumnToEffectiveColumn(absolute_last_col);
+ return effective_last_col - effective_first_col + 1;
+}
+
+unsigned AXLayoutObject::RowSpan() const {
+ LayoutObject* layout_object = GetLayoutObject();
+ if (!layout_object || !layout_object->IsTableCell())
+ return AXNodeObject::ColumnSpan();
+
+ LayoutTableCell* cell = ToLayoutTableCell(layout_object);
+ return cell->ResolvedRowSpan();
+}
+
+SortDirection AXLayoutObject::GetSortDirection() const {
+ if (RoleValue() != kRowHeaderRole && RoleValue() != kColumnHeaderRole)
+ return kSortDirectionUndefined;
+
+ const AtomicString& aria_sort =
+ GetAOMPropertyOrARIAAttribute(AOMStringProperty::kSort);
+ if (aria_sort.IsEmpty())
+ return kSortDirectionUndefined;
+ if (EqualIgnoringASCIICase(aria_sort, "none"))
+ return kSortDirectionNone;
+ if (EqualIgnoringASCIICase(aria_sort, "ascending"))
+ return kSortDirectionAscending;
+ if (EqualIgnoringASCIICase(aria_sort, "descending"))
+ return kSortDirectionDescending;
+
+ // Technically, illegal values should be exposed as is, but this does
+ // not seem to be worth the implementation effort at this time.
+ return kSortDirectionOther;
+}
+
+static AccessibilityRole DecideRoleFromSibling(LayoutTableCell* sibling_cell) {
+ if (!sibling_cell)
+ return kCellRole;
+
+ if (Node* sibling_node = sibling_cell->GetNode()) {
+ if (sibling_node->HasTagName(thTag))
+ return kColumnHeaderRole;
+ if (sibling_node->HasTagName(tdTag))
+ return kRowHeaderRole;
+ }
+
+ return kCellRole;
+}
+
+AccessibilityRole AXLayoutObject::DetermineTableRowRole() const {
+ AXObject* parent = ParentObjectUnignored();
+ if (!parent)
+ return kGenericContainerRole;
+
+ if (parent->RoleValue() == kLayoutTableRole)
+ return kLayoutTableRowRole;
+
+ if (parent->IsTableLikeRole())
+ return kRowRole;
+
+ return kGenericContainerRole;
+}
+
+AccessibilityRole AXLayoutObject::DetermineTableCellRole() const {
+ DCHECK(layout_object_);
+
+ AXObject* parent = ParentObjectUnignored();
+ if (!parent || !parent->IsTableRowLikeRole())
+ return kGenericContainerRole;
+
+ AXObject* grandparent = parent->ParentObjectUnignored();
+ if (!grandparent || !grandparent->IsTableLikeRole())
+ return kGenericContainerRole;
+
+ if (parent->RoleValue() == kLayoutTableRowRole)
+ return kLayoutTableCellRole;
+
+ if (!parent->IsTableRowLikeRole())
+ return kGenericContainerRole;
+
+ if (!GetNode() || !GetNode()->HasTagName(thTag))
+ return kCellRole;
+
+ const AtomicString& scope = GetAttribute(scopeAttr);
+ if (EqualIgnoringASCIICase(scope, "row") ||
+ EqualIgnoringASCIICase(scope, "rowgroup"))
+ return kRowHeaderRole;
+ if (EqualIgnoringASCIICase(scope, "col") ||
+ EqualIgnoringASCIICase(scope, "colgroup"))
+ return kColumnHeaderRole;
+
+ // Check the previous cell and the next cell on the same row.
+ LayoutTableCell* layout_cell = ToLayoutTableCell(layout_object_);
+ AccessibilityRole header_role = kCellRole;
+ // if header is preceded by header cells on the same row, then it is a
+ // column header. If it is preceded by other cells then it's a row header.
+ if ((header_role = DecideRoleFromSibling(layout_cell->PreviousCell())) !=
+ kCellRole)
+ return header_role;
+
+ // if header is followed by header cells on the same row, then it is a
+ // column header. If it is followed by other cells then it's a row header.
+ if ((header_role = DecideRoleFromSibling(layout_cell->NextCell())) !=
+ kCellRole)
+ return header_role;
+
+ // If there are no other cells on that row, then it is a column header.
+ return kColumnHeaderRole;
+}
+
+AXObject* AXLayoutObject::CellForColumnAndRow(unsigned target_column_index,
+ unsigned target_row_index) const {
+ LayoutObject* layout_object = GetLayoutObject();
+ if (!layout_object || !layout_object->IsTable()) {
+ return AXNodeObject::CellForColumnAndRow(target_column_index,
+ target_row_index);
+ }
+
+ LayoutTable* table = ToLayoutTable(layout_object);
+ table->RecalcSectionsIfNeeded();
+
+ LayoutTableSection* table_section = table->TopSection();
+ if (!table_section) {
+ return AXNodeObject::CellForColumnAndRow(target_column_index,
+ target_row_index);
+ }
+
+ unsigned row_offset = 0;
+ while (table_section) {
+ // Iterate backwards through the rows in case the desired cell has a rowspan
+ // and exists in a previous row.
+ for (LayoutTableRow* row = table_section->LastRow(); row;
+ row = row->PreviousRow()) {
+ unsigned row_index = row->RowIndex() + row_offset;
+ for (LayoutTableCell* cell = row->LastCell(); cell;
+ cell = cell->PreviousCell()) {
+ unsigned absolute_first_col = cell->AbsoluteColumnIndex();
+ unsigned absolute_last_col = absolute_first_col + cell->ColSpan() - 1;
+ unsigned effective_first_col =
+ cell->Table()->AbsoluteColumnToEffectiveColumn(absolute_first_col);
+ unsigned effective_last_col =
+ cell->Table()->AbsoluteColumnToEffectiveColumn(absolute_last_col);
+ unsigned row_span = cell->ResolvedRowSpan();
+ if (target_column_index >= effective_first_col &&
+ target_column_index <= effective_last_col &&
+ target_row_index >= row_index &&
+ target_row_index < row_index + row_span) {
+ return AXObjectCache().GetOrCreate(cell);
+ }
+ }
+ }
+
+ row_offset += table_section->NumRows();
+ table_section = table->SectionBelow(table_section, kSkipEmptySections);
+ }
+
+ return nullptr;
+}
+
+bool AXLayoutObject::FindAllTableCellsWithRole(AccessibilityRole role,
+ AXObjectVector& cells) const {
+ LayoutObject* layout_object = GetLayoutObject();
+ if (!layout_object || !layout_object->IsTable())
+ return false;
+
+ LayoutTable* table = ToLayoutTable(layout_object);
+ table->RecalcSectionsIfNeeded();
+
+ LayoutTableSection* table_section = table->TopSection();
+ if (!table_section)
+ return true;
+
+ while (table_section) {
+ for (LayoutTableRow* row = table_section->FirstRow(); row;
+ row = row->NextRow()) {
+ for (LayoutTableCell* cell = row->FirstCell(); cell;
+ cell = cell->NextCell()) {
+ AXObject* ax_cell = AXObjectCache().GetOrCreate(cell);
+ if (ax_cell && ax_cell->RoleValue() == role)
+ cells.push_back(ax_cell);
+ }
+ }
+
+ table_section = table->SectionBelow(table_section, kSkipEmptySections);
+ }
+
+ return true;
+}
+
+void AXLayoutObject::ColumnHeaders(AXObjectVector& headers) const {
+ if (!FindAllTableCellsWithRole(kColumnHeaderRole, headers))
+ AXNodeObject::ColumnHeaders(headers);
+}
+
+void AXLayoutObject::RowHeaders(AXObjectVector& headers) const {
+ if (!FindAllTableCellsWithRole(kRowHeaderRole, headers))
+ AXNodeObject::RowHeaders(headers);
+}
+
+AXObject* AXLayoutObject::HeaderObject() const {
+ LayoutObject* layout_object = GetLayoutObject();
+ if (!layout_object || !layout_object->IsTableRow())
+ return nullptr;
+
+ LayoutTableRow* row = ToLayoutTableRow(layout_object);
+ for (LayoutTableCell* cell = row->FirstCell(); cell;
+ cell = cell->NextCell()) {
+ AXObject* ax_cell = AXObjectCache().GetOrCreate(cell);
+ if (ax_cell && ax_cell->RoleValue() == kRowHeaderRole)
+ return ax_cell;
+ }
+
+ return nullptr;
+}
+
//
// Private.
//
@@ -2726,4 +3378,24 @@ void AXLayoutObject::AddRemoteSVGChildren() {
}
}
+void AXLayoutObject::AddTableChildren() {
+ if (!IsTableLikeRole())
+ return;
+
+ AXObjectCacheImpl& ax_cache = AXObjectCache();
+ if (layout_object_->IsTable()) {
+ LayoutTable* table = ToLayoutTable(layout_object_);
+ table->RecalcSectionsIfNeeded();
+ Node* table_node = table->GetNode();
+ if (IsHTMLTableElement(table_node)) {
+ if (HTMLTableCaptionElement* caption =
+ ToHTMLTableElement(table_node)->caption()) {
+ AXObject* caption_object = ax_cache.GetOrCreate(caption);
+ if (caption_object && !caption_object->AccessibilityIsIgnored())
+ children_.push_front(caption_object);
+ }
+ }
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_layout_object.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_layout_object.h
index 06a3fd2b58d..7c97731fc2e 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_layout_object.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_layout_object.h
@@ -59,6 +59,10 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
AccessibilityRole DetermineAccessibilityRole() override;
AccessibilityRole NativeAccessibilityRoleIgnoringAria() const override;
+ // If this is an anonymous block, returns the node of its containing layout
+ // block, otherwise returns the node of this layout object.
+ Node* GetNodeOrContainingBlockNode() const;
+
protected:
LayoutObject* layout_object_;
@@ -161,19 +165,12 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
AXObject* RawNextSibling() const override;
void AddChildren() override;
bool CanHaveChildren() const override;
- void UpdateChildrenIfNecessary() override;
- bool NeedsToUpdateChildren() const override { return children_dirty_; }
- void SetNeedsToUpdateChildren() override { children_dirty_ = true; }
- void ClearChildren() override;
// Properties of the object's owning document or page.
double EstimatedLoadingProgress() const override;
// DOM and layout tree access.
Node* GetNode() const override;
- // If this is an anonymous block, returns the node of its containing layout
- // block, otherwise returns the node of this layout object.
- Node* GetNodeOrContainingBlockNode() const;
Document* GetDocument() const override;
LocalFrameView* DocumentFrameView() const override;
Element* AnchorElement() const override;
@@ -189,6 +186,24 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
VisiblePosition VisiblePositionForIndex(int) const override;
void LineBreaks(Vector<int>&) const final;
+ // For a table.
+ bool IsDataTable() const override;
+ unsigned ColumnCount() const override;
+ unsigned RowCount() const override;
+ void ColumnHeaders(AXObjectVector&) const override;
+ void RowHeaders(AXObjectVector&) const override;
+ AXObject* CellForColumnAndRow(unsigned column, unsigned row) const override;
+
+ // For a table cell.
+ unsigned ColumnIndex() const override;
+ unsigned RowIndex() const override; // Also for a table row.
+ unsigned ColumnSpan() const override;
+ unsigned RowSpan() const override;
+ SortDirection GetSortDirection() const override;
+
+ // For a table row or column.
+ AXObject* HeaderObject() const override;
+
private:
bool IsTabItemSelected() const;
bool IsValidSelectionBound(const AXObject*) const;
@@ -205,7 +220,11 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
void AddCanvasChildren();
void AddPopupChildren();
void AddRemoteSVGChildren();
+ void AddTableChildren();
void AddInlineTextBoxChildren(bool force);
+ AccessibilityRole DetermineTableCellRole() const;
+ AccessibilityRole DetermineTableRowRole() const;
+ bool FindAllTableCellsWithRole(AccessibilityRole, AXObjectVector&) const;
LayoutRect ComputeElementRect() const;
AXSelection TextControlSelection() const;
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_list_box_option.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_list_box_option.cc
index 70c602393fb..c0ce1e480e3 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_list_box_option.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_list_box_option.cc
@@ -28,7 +28,7 @@
#include "third_party/blink/renderer/modules/accessibility/ax_list_box_option.h"
-#include "third_party/blink/renderer/core/dom/accessible_node.h"
+#include "third_party/blink/renderer/core/aom/accessible_node.h"
#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_object.h"
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc
index 9cbc7ca9b98..c56b578d7ff 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_media_controls.cc
@@ -90,6 +90,8 @@ AXObject* AccessibilityMediaControl::Create(
case kMediaOverflowList:
case kMediaDownloadButton:
case kMediaScrubbingMessage:
+ case kMediaEnterPictureInPictureButton:
+ case kMediaExitPictureInPictureButton:
return new AccessibilityMediaControl(layout_object, ax_object_cache);
}
@@ -171,6 +173,12 @@ String AccessibilityMediaControl::TextAlternative(
case kMediaOverflowList:
case kMediaScrubbingMessage:
return QueryString(WebLocalizedString::kAXMediaDefault);
+ case kMediaEnterPictureInPictureButton:
+ return QueryString(
+ WebLocalizedString::kAXMediaEnterPictureInPictureButton);
+ case kMediaExitPictureInPictureButton:
+ return QueryString(
+ WebLocalizedString::kAXMediaExitPictureInPictureButton);
case kMediaSlider:
NOTREACHED();
return QueryString(WebLocalizedString::kAXMediaDefault);
@@ -215,6 +223,12 @@ String AccessibilityMediaControl::Description(
return QueryString(WebLocalizedString::kAXMediaCastOnButtonHelp);
case kMediaOverflowButton:
return QueryString(WebLocalizedString::kAXMediaOverflowButtonHelp);
+ case kMediaEnterPictureInPictureButton:
+ return QueryString(
+ WebLocalizedString::kAXMediaEnterPictureInPictureButtonHelp);
+ case kMediaExitPictureInPictureButton:
+ return QueryString(
+ WebLocalizedString::kAXMediaExitPictureInPictureButtonHelp);
case kMediaSliderThumb:
case kMediaTextTrackList:
case kMediaTimelineContainer:
@@ -262,6 +276,8 @@ AccessibilityRole AccessibilityMediaControl::RoleValue() const {
case kMediaDownloadButton:
case kMediaCastOnButton:
case kMediaCastOffButton:
+ case kMediaEnterPictureInPictureButton:
+ case kMediaExitPictureInPictureButton:
return kButtonRole;
case kMediaTimelineContainer:
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.cc
index 4f0b82b2b72..a6b3ae05669 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.cc
@@ -26,7 +26,7 @@
#include "third_party/blink/renderer/modules/accessibility/ax_menu_list_option.h"
#include "SkMatrix44.h"
-#include "third_party/blink/renderer/core/dom/accessible_node.h"
+#include "third_party/blink/renderer/core/aom/accessible_node.h"
#include "third_party/blink/renderer/core/html/forms/html_select_element.h"
#include "third_party/blink/renderer/modules/accessibility/ax_menu_list.h"
#include "third_party/blink/renderer/modules/accessibility/ax_menu_list_popup.h"
@@ -113,6 +113,21 @@ bool AXMenuListOption::IsOffScreen() const {
return !IsVisible();
}
+int AXMenuListOption::PosInSet() const {
+ // Value should be 1-based. 0 means not supported.
+ return SetSize() ? element_->index() + 1 : 0;
+}
+
+int AXMenuListOption::SetSize() const {
+ // Return 0 if not supported.
+ if (!element_)
+ return 0;
+ HTMLSelectElement* select = element_->OwnerSelectElement();
+ if (!select)
+ return 0;
+ return select->length();
+}
+
AccessibilitySelectedState AXMenuListOption::IsSelected() const {
if (!GetNode() || !CanSetSelectedAttribute())
return kSelectedStateUndefined;
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.h
index ab0be395e59..8d60d311093 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.h
@@ -42,6 +42,9 @@ class AXMenuListOption final : public AXMockObject {
}
~AXMenuListOption() override;
+ int PosInSet() const override;
+ int SetSize() const override;
+
private:
AXMenuListOption(HTMLOptionElement*, AXObjectCacheImpl&);
void Trace(blink::Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list_popup.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list_popup.cc
index 1b6f2ba75b6..bfb71651b0e 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list_popup.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_menu_list_popup.cc
@@ -148,11 +148,13 @@ void AXMenuListPopup::DidUpdateActiveOption(int option_index,
void AXMenuListPopup::DidHide() {
AXObjectCacheImpl& cache = AXObjectCache();
+ AXObject* descendant = ActiveDescendant();
cache.PostNotification(this, AXObjectCacheImpl::kAXHide);
- if (ActiveDescendant())
+ if (descendant) {
cache.PostNotification(this, AXObjectCacheImpl::kAXChildrenChanged);
- cache.PostNotification(ActiveDescendant(),
+ cache.PostNotification(descendant,
AXObjectCacheImpl::kAXMenuListItemUnselected);
+ }
}
void AXMenuListPopup::DidShow() {
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_mock_object.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_mock_object.h
index a06594e0ec9..4282643765a 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_mock_object.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_mock_object.h
@@ -44,10 +44,9 @@ class MODULES_EXPORT AXMockObject : public AXObject {
// AXObject overrides.
AXObject* ComputeParent() const override { return parent_; }
AXRestriction Restriction() const override { return kNone; }
-
- private:
bool IsMockObject() const final { return true; }
+ private:
bool ComputeAccessibilityIsIgnored(IgnoredReasons* = nullptr) const override;
DISALLOW_COPY_AND_ASSIGN(AXMockObject);
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
index 1d625753619..013f944fc80 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -30,7 +30,7 @@
#include <math.h>
-#include "third_party/blink/renderer/core/dom/accessible_node.h"
+#include "third_party/blink/renderer/core/aom/accessible_node.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_traversal.h"
@@ -86,6 +86,7 @@ const int kDefaultHeadingLevel = 2;
AXNodeObject::AXNodeObject(Node* node, AXObjectCacheImpl& ax_object_cache)
: AXObject(ax_object_cache),
children_dirty_(false),
+ native_role_(kUnknownRole),
node_(node) {}
AXNodeObject* AXNodeObject::Create(Node* node,
@@ -313,7 +314,7 @@ AccessibilityRole AXNodeObject::NativeAccessibilityRoleIgnoringAria() const {
return kUnknownRole;
}
- if (auto* input = ToHTMLInputElementOrNull(*GetNode())) {
+ if (const auto* input = ToHTMLInputElementOrNull(*GetNode())) {
const AtomicString& type = input->type();
if (input->DataList())
return kTextFieldWithComboBoxRole;
@@ -428,6 +429,12 @@ AccessibilityRole AXNodeObject::NativeAccessibilityRoleIgnoringAria() const {
if (GetNode()->HasTagName(articleTag))
return kArticleRole;
+ if (GetNode()->HasTagName(delTag))
+ return kContentDeletionRole;
+
+ if (GetNode()->HasTagName(insTag))
+ return kContentInsertionRole;
+
if (GetNode()->HasTagName(mainTag))
return kMainRole;
@@ -511,13 +518,14 @@ AccessibilityRole AXNodeObject::DetermineAccessibilityRole() {
if (!GetNode())
return kUnknownRole;
+ native_role_ = NativeAccessibilityRoleIgnoringAria();
+
if ((aria_role_ = DetermineAriaRoleAttribute()) != kUnknownRole)
return aria_role_;
if (GetNode()->IsTextNode())
return kStaticTextRole;
- AccessibilityRole role = NativeAccessibilityRoleIgnoringAria();
- return role == kUnknownRole ? kGenericContainerRole : role;
+ return native_role_ == kUnknownRole ? kGenericContainerRole : native_role_;
}
void AXNodeObject::AccessibilityChildrenFromAOMProperty(
@@ -827,7 +835,7 @@ bool AXNodeObject::IsMultiSelectable() const {
}
bool AXNodeObject::IsNativeCheckboxOrRadio() const {
- if (auto* input = ToHTMLInputElementOrNull(GetNode())) {
+ if (const auto* input = ToHTMLInputElementOrNull(GetNode())) {
return input->type() == InputTypeNames::checkbox ||
input->type() == InputTypeNames::radio;
}
@@ -845,7 +853,7 @@ bool AXNodeObject::IsNativeImage() const {
if (IsHTMLPlugInElement(*node))
return true;
- if (auto* input = ToHTMLInputElementOrNull(*node))
+ if (const auto* input = ToHTMLInputElementOrNull(*node))
return input->type() == InputTypeNames::image;
return false;
@@ -859,7 +867,7 @@ bool AXNodeObject::IsNativeTextControl() const {
if (IsHTMLTextAreaElement(*node))
return true;
- if (auto* input = ToHTMLInputElementOrNull(*node))
+ if (const auto* input = ToHTMLInputElementOrNull(*node))
return input->IsTextField();
return false;
@@ -907,13 +915,13 @@ bool AXNodeObject::IsSpinButton() const {
}
bool AXNodeObject::IsNativeSlider() const {
- if (auto* input = ToHTMLInputElementOrNull(GetNode()))
+ if (const auto* input = ToHTMLInputElementOrNull(GetNode()))
return input->type() == InputTypeNames::range;
return false;
}
bool AXNodeObject::IsNativeSpinButton() const {
- if (auto* input = ToHTMLInputElementOrNull(GetNode()))
+ if (const auto* input = ToHTMLInputElementOrNull(GetNode()))
return input->type() == InputTypeNames::number;
return false;
}
@@ -978,11 +986,26 @@ AXRestriction AXNodeObject::Restriction() const {
// Only editable fields can be marked @readonly (unlike @aria-readonly).
if (IsHTMLTextAreaElement(*elem) && ToHTMLTextAreaElement(*elem).IsReadOnly())
return kReadOnly;
- if (auto* input = ToHTMLInputElementOrNull(*elem)) {
+ if (const auto* input = ToHTMLInputElementOrNull(*elem)) {
if (input->IsTextField() && input->IsReadOnly())
return kReadOnly;
}
+ // If a grid cell does not have it's own ARIA input restriction,
+ // fall back on parent grid's readonly state.
+ // See ARIA specification regarding grid/treegrid and readonly.
+ if (IsTableCellLikeRole()) {
+ AXObject* row = ParentObjectUnignored();
+ if (row->IsTableRowLikeRole()) {
+ AXObject* table = row->ParentObjectUnignored();
+ if (table->IsTableLikeRole() && (table->RoleValue() == kGridRole ||
+ table->RoleValue() == kTreeGridRole)) {
+ if (table->Restriction() == kReadOnly)
+ return kReadOnly;
+ }
+ }
+ }
+
// This is a node that is not readonly and not disabled.
return kNone;
}
@@ -1654,12 +1677,19 @@ String AXNodeObject::StringValue() const {
return GetText();
// Handle other HTML input elements that aren't text controls, like date and
- // time controls, by returning the string value, with the exception of
- // checkboxes and radio buttons (which would return "on").
- if (auto* input = ToHTMLInputElementOrNull(node)) {
- if (input->type() != InputTypeNames::checkbox &&
- input->type() != InputTypeNames::radio)
+ // time controls, by returning their value converted to text, with the
+ // exception of checkboxes and radio buttons (which would return "on"), and
+ // buttons which will return their name.
+ // https://html.spec.whatwg.org/multipage/forms.html#dom-input-value
+ if (const auto* input = ToHTMLInputElementOrNull(node)) {
+ if (input->type() != InputTypeNames::button &&
+ input->type() != InputTypeNames::checkbox &&
+ input->type() != InputTypeNames::image &&
+ input->type() != InputTypeNames::radio &&
+ input->type() != InputTypeNames::reset &&
+ input->type() != InputTypeNames::submit) {
return input->value();
+ }
}
return String();
@@ -1669,14 +1699,13 @@ AccessibilityRole AXNodeObject::AriaRoleAttribute() const {
return aria_role_;
}
-// Returns the nearest LayoutBlockFlow ancestor which does not have an
-// inlineBoxWrapper - i.e. is not itself an inline object.
+// Returns the nearest block-level LayoutBlockFlow ancestor
static LayoutBlockFlow* NonInlineBlockFlow(LayoutObject* object) {
LayoutObject* current = object;
while (current) {
if (current->IsLayoutBlockFlow()) {
LayoutBlockFlow* block_flow = ToLayoutBlockFlow(current);
- if (!block_flow->InlineBoxWrapper())
+ if (!block_flow->IsAtomicInlineLevel())
return block_flow;
}
current = current->Parent();
@@ -1702,6 +1731,21 @@ static bool IsInSameNonInlineBlockFlow(LayoutObject* r1, LayoutObject* r2) {
// New AX name calculation.
//
+String AXNodeObject::GetName(AXNameFrom& name_from,
+ AXObjectVector* name_objects) const {
+ String name = AXObject::GetName(name_from, name_objects);
+ if (RoleValue() == kSpinButtonRole && DatetimeAncestor()) {
+ // Fields inside a datetime control need to merge the field name with
+ // the name of the <input> element.
+ name_objects->clear();
+ String input_name = DatetimeAncestor()->GetName(name_from, name_objects);
+ if (!input_name.IsEmpty())
+ return name + " " + input_name;
+ }
+
+ return name;
+}
+
String AXNodeObject::TextAlternative(bool recursive,
bool in_aria_labelled_by_traversal,
AXObjectSet& visited,
@@ -2095,6 +2139,11 @@ void AXNodeObject::InsertChild(AXObject* child, unsigned index) {
}
}
+void AXNodeObject::ClearChildren() {
+ AXObject::ClearChildren();
+ children_dirty_ = false;
+}
+
bool AXNodeObject::CanHaveChildren() const {
// If this is an AXLayoutObject, then it's okay if this object
// doesn't have a node - there are some layoutObjects that don't have
@@ -2112,7 +2161,7 @@ bool AXNodeObject::CanHaveChildren() const {
return false;
}
- switch (NativeAccessibilityRoleIgnoringAria()) {
+ switch (native_role_) {
case kButtonRole:
case kCheckBoxRole:
case kImageRole:
@@ -2325,22 +2374,31 @@ bool AXNodeObject::OnNativeSetSequentialFocusNavigationStartingPointAction() {
}
void AXNodeObject::ChildrenChanged() {
- // This method is meant as a quick way of marking a portion of the
- // accessibility tree dirty.
if (!GetNode() && !GetLayoutObject())
return;
+ // Call SetNeedsToUpdateChildren on this node, and if this node is
+ // ignored, call it on each existing parent until reaching an unignored node,
+ // because unignored nodes recursively include all children of ignored
+ // nodes. This method is called during layout, so we need to be careful to
+ // only explore existing objects.
+ AXObject* node_to_update = this;
+ while (node_to_update) {
+ node_to_update->SetNeedsToUpdateChildren();
+ if (!node_to_update->LastKnownIsIgnoredValue())
+ break;
+ node_to_update = node_to_update->ParentObjectIfExists();
+ }
+
// If this node's children are not part of the accessibility tree then
- // invalidate the children but skip notification and walking up the ancestors.
+ // skip notification and walking up the ancestors.
// Cases where this happens:
// - an ancestor has only presentational children, or
// - this or an ancestor is a leaf node
// Uses |cached_is_descendant_of_leaf_node_| to avoid updating cached
// attributes for eachc change via | UpdateCachedAttributeValuesIfNeeded()|.
- if (!CanHaveChildren() || cached_is_descendant_of_leaf_node_) {
- SetNeedsToUpdateChildren();
+ if (!CanHaveChildren() || cached_is_descendant_of_leaf_node_)
return;
- }
AXObjectCache().PostNotification(this, AXObjectCacheImpl::kAXChildrenChanged);
@@ -2351,8 +2409,6 @@ void AXNodeObject::ChildrenChanged() {
// changes.
for (AXObject* parent = this; parent;
parent = parent->ParentObjectIfExists()) {
- parent->SetNeedsToUpdateChildren();
-
// These notifications always need to be sent because screenreaders are
// reliant on them to perform. In other words, they need to be sent even
// when the screen reader has not accessed this live region since the last
@@ -2373,6 +2429,13 @@ void AXNodeObject::ChildrenChanged() {
}
}
+void AXNodeObject::UpdateChildrenIfNecessary() {
+ if (NeedsToUpdateChildren())
+ ClearChildren();
+
+ AXObject::UpdateChildrenIfNecessary();
+}
+
void AXNodeObject::SelectionChanged() {
// Post the selected text changed event on the first ancestor that's
// focused (to handle form controls, ARIA text boxes and contentEditable),
@@ -2933,7 +2996,24 @@ String AXNodeObject::Description(AXNameFrom name_from,
description_objects->push_back(related_objects[i]->object);
}
- return CollapseWhitespace(result);
+ result = CollapseWhitespace(result);
+
+ if (RoleValue() == kSpinButtonRole && DatetimeAncestor()) {
+ // Fields inside a datetime control need to merge the field description
+ // with the description of the <input> element.
+ const AXObject* datetime_ancestor = DatetimeAncestor();
+ AXNameFrom name_from;
+ datetime_ancestor->GetName(name_from, nullptr);
+ description_objects->clear();
+ String ancestor_description = DatetimeAncestor()->Description(
+ name_from, description_from, description_objects);
+ if (!result.IsEmpty() && !ancestor_description.IsEmpty())
+ return result + " " + ancestor_description;
+ if (!ancestor_description.IsEmpty())
+ return ancestor_description;
+ }
+
+ return result;
}
// Based on
@@ -3161,7 +3241,7 @@ String AXNodeObject::Placeholder(AXNameFrom name_from) const {
return native_placeholder;
const AtomicString& aria_placeholder =
- ToHTMLElement(node)->FastGetAttribute(aria_placeholderAttr);
+ GetAOMPropertyOrARIAAttribute(AOMStringProperty::kPlaceholder);
if (!aria_placeholder.IsEmpty())
return aria_placeholder;
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_node_object.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_node_object.h
index cd546cbce82..a36cf324253 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_node_object.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_node_object.h
@@ -54,6 +54,8 @@ class MODULES_EXPORT AXNodeObject : public AXObject {
#if DCHECK_IS_ON()
bool initialized_ = false;
#endif
+ // The accessibility role, not taking ARIA into account.
+ AccessibilityRole native_role_;
bool ComputeAccessibilityIsIgnored(IgnoredReasons* = nullptr) const override;
const AXObject* InheritsPresentationalRoleFrom() const override;
@@ -157,6 +159,7 @@ class MODULES_EXPORT AXNodeObject : public AXObject {
AccessibilityRole AriaRoleAttribute() const final;
// AX name calculation.
+ String GetName(AXNameFrom&, AXObjectVector* name_objects) const override;
String TextAlternative(bool recursive,
bool in_aria_labelled_by_traversal,
AXObjectSet& visited,
@@ -190,6 +193,10 @@ class MODULES_EXPORT AXNodeObject : public AXObject {
bool CanHaveChildren() const override;
void AddChild(AXObject*);
void InsertChild(AXObject*, unsigned index);
+ void ClearChildren() override;
+ bool NeedsToUpdateChildren() const override { return children_dirty_; }
+ void SetNeedsToUpdateChildren() override { children_dirty_ = true; }
+ void UpdateChildrenIfNecessary() override;
// DOM and Render tree access.
Element* ActionElement() const override;
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_object.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_object.cc
index 8a58e2dff07..936c36e1b2f 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -30,9 +30,10 @@
#include "SkMatrix44.h"
#include "third_party/blink/public/platform/web_scroll_into_view_params.h"
+#include "third_party/blink/renderer/core/aom/accessible_node.h"
+#include "third_party/blink/renderer/core/aom/accessible_node_list.h"
#include "third_party/blink/renderer/core/css/resolver/style_resolver.h"
-#include "third_party/blink/renderer/core/dom/accessible_node.h"
-#include "third_party/blink/renderer/core/dom/accessible_node_list.h"
+#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/dom/user_gesture_indicator.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/visible_position.h"
@@ -88,6 +89,7 @@ struct RoleEntry {
AccessibilityRole webcore_role;
};
+// Mapping of ARIA role name to internal role name.
const RoleEntry kRoles[] = {{"alert", kAlertRole},
{"alertdialog", kAlertDialogRole},
{"application", kApplicationRole},
@@ -240,6 +242,8 @@ const InternalRoleEntry kInternalRoles[] = {
{kComboBoxGroupingRole, "ComboBox"},
{kComboBoxMenuButtonRole, "ComboBox"},
{kComplementaryRole, "Complementary"},
+ {kContentDeletionRole, "ContentDeletion"},
+ {kContentInsertionRole, "ContentInsertion"},
{kContentInfoRole, "ContentInfo"},
{kDateRole, "Date"},
{kDateTimeRole, "DateTime"},
@@ -413,7 +417,7 @@ static ARIARoleMap* CreateARIARoleMap() {
role_map->Set(String(kRoles[i].aria_role), kRoles[i].webcore_role);
// Grids "ignore" their non-row children during computation of children.
- role_map->Set("rowgroup", kIgnoredRole);
+ role_map->Set(String("rowgroup"), kIgnoredRole);
return role_map;
}
@@ -471,6 +475,8 @@ AXObject::AXObject(AXObjectCacheImpl& ax_object_cache)
cached_has_inherited_presentational_role_(false),
cached_is_editable_root_(false),
cached_live_region_root_(nullptr),
+ cached_aria_column_index_(0),
+ cached_aria_row_index_(0),
ax_object_cache_(&ax_object_cache) {
++number_of_live_ax_objects_;
}
@@ -794,6 +800,18 @@ bool AXObject::IsPasswordFieldAndShouldHideValue() const {
return IsPasswordField();
}
+bool AXObject::IsTextObject() const {
+ // Objects with |kLineBreakRole| are HTML <br> elements and are not backed by
+ // DOM text nodes. We can't mark them as text objects for that reason.
+ switch (RoleValue()) {
+ case kInlineTextBoxRole:
+ case kStaticTextRole:
+ return true;
+ default:
+ return false;
+ }
+}
+
bool AXObject::IsClickable() const {
if (IsButton() || IsLink() || IsTextControl())
return true;
@@ -861,16 +879,21 @@ void AXObject::UpdateCachedAttributeValuesIfNeeded() const {
!!InheritsPresentationalRoleFrom();
cached_is_ignored_ = ComputeAccessibilityIsIgnored();
cached_is_editable_root_ = ComputeIsEditableRoot();
+ // TODO(dmazzoni): remove this const_cast.
cached_live_region_root_ =
IsLiveRegion()
? const_cast<AXObject*>(this)
: (ParentObjectIfExists() ? ParentObjectIfExists()->LiveRegionRoot()
: nullptr);
- // TODO(dmazzoni): remove this const_cast.
+ cached_aria_column_index_ = ComputeAriaColumnIndex();
+ cached_aria_row_index_ = ComputeAriaRowIndex();
if (cached_is_ignored_ != LastKnownIsIgnoredValue()) {
- const_cast<AXObject*>(this)->ChildrenChanged();
last_known_is_ignored_value_ =
cached_is_ignored_ ? kIgnoreObject : kIncludeObject;
+
+ AXObject* parent = ParentObjectIfExists();
+ if (parent)
+ parent->ChildrenChanged();
}
}
@@ -1099,6 +1122,26 @@ const AXObject* AXObject::DisabledAncestor() const {
return nullptr;
}
+const AXObject* AXObject::DatetimeAncestor(int max_levels_to_check) const {
+ switch (RoleValue()) {
+ case kDateTimeRole:
+ case kDateRole:
+ case kInputTimeRole:
+ case kTimeRole:
+ return this;
+ default:
+ break;
+ }
+
+ if (max_levels_to_check == 0)
+ return nullptr;
+
+ if (AXObject* parent = ParentObject())
+ return parent->DatetimeAncestor(max_levels_to_check - 1);
+
+ return nullptr;
+}
+
bool AXObject::LastKnownIsIgnoredValue() const {
if (last_known_is_ignored_value_ == kDefaultBehavior) {
last_known_is_ignored_value_ =
@@ -1247,21 +1290,50 @@ bool AXObject::AncestorExposesActiveDescendant() const {
return parent->AncestorExposesActiveDescendant();
}
+bool AXObject::HasIndirectChildren() const {
+ return IsTableCol() || RoleValue() == kTableHeaderContainerRole;
+}
+
bool AXObject::CanSetSelectedAttribute() const {
// Sub-widget elements can be selected if not disabled (native or ARIA)
- return IsSubWidget(RoleValue()) && Restriction() != kDisabled;
+ return IsSubWidget() && Restriction() != kDisabled;
}
-// static
-bool AXObject::IsSubWidget(AccessibilityRole role) {
- switch (role) {
+bool AXObject::IsSubWidget() const {
+ switch (RoleValue()) {
case kCellRole:
case kColumnHeaderRole:
+ case kRowHeaderRole:
case kColumnRole:
+ case kRowRole: {
+ // If it has an explicit ARIA role, it's a subwidget.
+ //
+ // Reasoning:
+ // Static table cells are not selectable, but ARIA grid cells
+ // and rows definitely are according to the spec. To support
+ // ARIA 1.0, it's sufficient to just check if there's any
+ // ARIA role at all, because if so then it must be a grid-related
+ // role so it must be selectable.
+ //
+ // TODO: an ARIA 1.1+ role of "cell", or a role of "row" inside
+ // an ARIA 1.1 role of "table", should not be selectable. We may
+ // need to create separate role enums for grid cells vs table cells
+ // to implement this.
+ if (AriaRoleAttribute() != kUnknownRole)
+ return true;
+
+ // Otherwise it's only a subwidget if it's in a grid or treegrid,
+ // not in a table.
+ AXObject* parent = ParentObjectUnignored();
+ while (parent && !parent->IsTableLikeRole())
+ parent = parent->ParentObjectUnignored();
+ if (parent && (parent->RoleValue() == kGridRole ||
+ parent->RoleValue() == kTreeGridRole))
+ return true;
+ return false;
+ }
case kListBoxOptionRole:
case kMenuListOptionRole:
- case kRowHeaderRole:
- case kRowRole:
case kTabRole:
case kTreeItemRole:
return true;
@@ -1945,8 +2017,23 @@ AXObject* AXObject::ElementAccessibilityHitTest(const IntPoint& point) const {
return const_cast<AXObject*>(this);
}
+AXObject::AncestorsIterator AXObject::AncestorsBegin() {
+ AXObject* parent = ParentObjectUnignored();
+ if (parent)
+ return AXObject::AncestorsIterator(*parent);
+ return AncestorsEnd();
+}
+
+AXObject::AncestorsIterator AXObject::AncestorsEnd() {
+ return AXObject::AncestorsIterator();
+}
+
+AXObject::InOrderTraversalIterator AXObject::GetInOrderTraversalIterator() {
+ return InOrderTraversalIterator(*this);
+}
+
int AXObject::ChildCount() const {
- return static_cast<int>(Children().size());
+ return HasIndirectChildren() ? 0 : static_cast<int>(Children().size());
}
const AXObject::AXObjectVector& AXObject::Children() const {
@@ -2270,6 +2357,324 @@ void AXObject::SetScrollOffset(const IntPoint& offset) const {
kProgrammaticScroll);
}
+bool AXObject::IsTableLikeRole() const {
+ switch (RoleValue()) {
+ case kLayoutTableRole:
+ case kTableRole:
+ case kGridRole:
+ case kTreeGridRole:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool AXObject::IsTableRowLikeRole() const {
+ return RoleValue() == kRowRole || RoleValue() == kLayoutTableRowRole;
+}
+
+bool AXObject::IsTableCellLikeRole() const {
+ switch (RoleValue()) {
+ case kLayoutTableCellRole:
+ case kCellRole:
+ case kColumnHeaderRole:
+ case kRowHeaderRole:
+ return true;
+ default:
+ return false;
+ }
+}
+
+unsigned AXObject::ColumnCount() const {
+ if (!IsTableLikeRole())
+ return 0;
+
+ unsigned max_column_count = 0;
+ for (const auto& row : TableRowChildren()) {
+ unsigned column_count = row->TableCellChildren().size();
+ max_column_count = std::max(column_count, max_column_count);
+ }
+
+ return max_column_count;
+}
+
+unsigned AXObject::RowCount() const {
+ if (!IsTableLikeRole())
+ return 0;
+
+ return TableRowChildren().size();
+}
+
+void AXObject::ColumnHeaders(AXObjectVector& headers) const {
+ if (!IsTableLikeRole())
+ return;
+
+ for (const auto& row : TableRowChildren()) {
+ for (const auto& cell : row->TableCellChildren()) {
+ if (cell->RoleValue() == kColumnHeaderRole)
+ headers.push_back(cell);
+ }
+ }
+}
+
+void AXObject::RowHeaders(AXObjectVector& headers) const {
+ if (!IsTableLikeRole())
+ return;
+
+ for (const auto& row : TableRowChildren()) {
+ for (const auto& cell : row->TableCellChildren()) {
+ if (cell->RoleValue() == kRowHeaderRole)
+ headers.push_back(cell);
+ }
+ }
+}
+
+AXObject* AXObject::CellForColumnAndRow(unsigned target_column_index,
+ unsigned target_row_index) const {
+ if (!IsTableLikeRole())
+ return nullptr;
+
+ // Note that this code is only triggered if this is not a LayoutTable,
+ // i.e. it's an ARIA grid/table.
+ //
+ // TODO(dmazzoni): delete this code or rename it "for testing only"
+ // since it's only needed for Blink layout tests and not for production.
+ unsigned row_index = 0;
+ for (const auto& row : TableRowChildren()) {
+ unsigned column_index = 0;
+ for (const auto& cell : row->TableCellChildren()) {
+ if (target_column_index == column_index && target_row_index == row_index)
+ return cell;
+ column_index++;
+ }
+ row_index++;
+ }
+
+ return nullptr;
+}
+
+int AXObject::AriaColumnCount() const {
+ if (!IsTableLikeRole())
+ return 0;
+
+ int32_t col_count;
+ if (!HasAOMPropertyOrARIAAttribute(AOMIntProperty::kColCount, col_count))
+ return 0;
+
+ if (col_count > static_cast<int>(ColumnCount()))
+ return col_count;
+
+ // Spec says that if all of the columns are present in the DOM, it
+ // is not necessary to set this attribute as the user agent can
+ // automatically calculate the total number of columns.
+ // It returns 0 in order not to set this attribute.
+ if (col_count == static_cast<int>(ColumnCount()) || col_count != -1)
+ return 0;
+
+ return -1;
+}
+
+int AXObject::AriaRowCount() const {
+ if (!IsTableLikeRole())
+ return 0;
+
+ int32_t row_count;
+ if (!HasAOMPropertyOrARIAAttribute(AOMIntProperty::kRowCount, row_count))
+ return 0;
+
+ if (row_count > static_cast<int>(RowCount()))
+ return row_count;
+
+ // Spec says that if all of the rows are present in the DOM, it is
+ // not necessary to set this attribute as the user agent can
+ // automatically calculate the total number of rows.
+ // It returns 0 in order not to set this attribute.
+ if (row_count == (int)RowCount() || row_count != -1)
+ return 0;
+
+ // In the spec, -1 explicitly means an unknown number of rows.
+ return -1;
+}
+
+unsigned AXObject::ColumnIndex() const {
+ if (!IsTableCellLikeRole())
+ return 0;
+
+ const AXObject* row = TableRowParent();
+ if (!row)
+ return 0;
+
+ unsigned column_index = 0;
+ for (const auto& child : row->TableCellChildren()) {
+ if (child == this)
+ break;
+ column_index++;
+ }
+ return column_index;
+}
+
+unsigned AXObject::RowIndex() const {
+ const AXObject* row = nullptr;
+ if (IsTableRowLikeRole())
+ row = this;
+ else if (IsTableCellLikeRole())
+ row = TableRowParent();
+
+ if (!row)
+ return 0;
+
+ const AXObject* table = row->TableParent();
+ if (!table)
+ return 0;
+
+ unsigned row_index = 0;
+ for (const auto& child : table->TableRowChildren()) {
+ if (child == row)
+ break;
+ if (!child->IsTableRowLikeRole())
+ continue;
+ row_index++;
+ }
+ return row_index;
+}
+
+unsigned AXObject::ColumnSpan() const {
+ return IsTableCellLikeRole() ? 1 : 0;
+}
+
+unsigned AXObject::RowSpan() const {
+ return IsTableCellLikeRole() ? 1 : 0;
+}
+
+unsigned AXObject::AriaColumnIndex() const {
+ UpdateCachedAttributeValuesIfNeeded();
+ return cached_aria_column_index_;
+}
+
+unsigned AXObject::AriaRowIndex() const {
+ UpdateCachedAttributeValuesIfNeeded();
+ return cached_aria_row_index_;
+}
+
+unsigned AXObject::ComputeAriaColumnIndex() const {
+ if (!IsTableCellLikeRole())
+ return 0;
+
+ // First see if it has an ARIA column index explicitly set.
+ uint32_t col_index;
+ if (HasAOMPropertyOrARIAAttribute(AOMUIntProperty::kColIndex, col_index) &&
+ col_index >= 1) {
+ return col_index;
+ }
+
+ // Get the previous sibling.
+ // TODO(dmazzoni): this code depends on the DOM; move this code out of Blink
+ // and make it more general.
+ AXObject* previous = nullptr;
+ if (GetNode()) {
+ Node* previousNode = ElementTraversal::PreviousSibling(*GetNode());
+ previous = AXObjectCache().GetOrCreate(previousNode);
+ }
+
+ // It has a previous sibling, so if that cell has a column index, this one's
+ // index is one greater.
+ if (previous) {
+ col_index = previous->AriaColumnIndex();
+ if (col_index)
+ return col_index + 1;
+ return 0;
+ }
+
+ // No previous cell, so check the row to see if it sets a column index.
+ const AXObject* row = TableRowParent();
+ if (!row)
+ return 0;
+ if (row->HasAOMPropertyOrARIAAttribute(AOMUIntProperty::kColIndex,
+ col_index)) {
+ return col_index;
+ }
+
+ // Otherwise there's no ARIA column index.
+ return 0;
+}
+
+unsigned AXObject::ComputeAriaRowIndex() const {
+ if (!IsTableCellLikeRole() && !IsTableRowLikeRole())
+ return 0;
+
+ // First check if there's an ARIA row index explicitly set.
+ uint32_t row_index;
+ if (HasAOMPropertyOrARIAAttribute(AOMUIntProperty::kRowIndex, row_index) &&
+ row_index >= 1) {
+ return row_index;
+ }
+
+ // If this is a cell, return the ARIA row index of the containing row.
+ if (IsTableCellLikeRole()) {
+ const AXObject* row = TableRowParent();
+ if (row)
+ return row->AriaRowIndex();
+ return 0;
+ }
+
+ // Otherwise, this is a row. Find the previous sibling row.
+ // TODO(dmazzoni): this code depends on the DOM; move this code out of Blink
+ // and make it more general.
+ if (!GetNode())
+ return 0;
+ Node* previousNode = ElementTraversal::PreviousSibling(*GetNode());
+ AXObject* previous = AXObjectCache().GetOrCreate(previousNode);
+ if (!previous || !previous->IsTableRowLikeRole())
+ return 0;
+
+ // If the previous row has an ARIA row index, this one is the same index
+ // plus one.
+ row_index = previous->AriaRowIndex();
+ if (row_index)
+ return row_index + 1;
+
+ // Otherwise there's no ARIA row index.
+ return 0;
+}
+
+AXObject::AXObjectVector AXObject::TableRowChildren() const {
+ AXObjectVector result;
+ for (const auto& child : Children()) {
+ if (child->IsTableRowLikeRole())
+ result.push_back(child);
+ else if (child->RoleValue() == kGenericContainerRole)
+ result.AppendVector(child->TableRowChildren());
+ }
+ return result;
+}
+
+AXObject::AXObjectVector AXObject::TableCellChildren() const {
+ AXObjectVector result;
+ for (const auto& child : Children()) {
+ if (child->IsTableCellLikeRole())
+ result.push_back(child);
+ else if (child->RoleValue() == kGenericContainerRole)
+ result.AppendVector(child->TableCellChildren());
+ }
+ return result;
+}
+
+const AXObject* AXObject::TableRowParent() const {
+ const AXObject* row = ParentObjectUnignored();
+ while (row && !row->IsTableRowLikeRole() &&
+ row->RoleValue() == kGenericContainerRole)
+ row = row->ParentObjectUnignored();
+ return row;
+}
+
+const AXObject* AXObject::TableParent() const {
+ const AXObject* table = ParentObjectUnignored();
+ while (table && !table->IsTableLikeRole() &&
+ table->RoleValue() == kGenericContainerRole)
+ table = table->ParentObjectUnignored();
+ return table;
+}
+
void AXObject::GetRelativeBounds(AXObject** out_container,
FloatRect& out_bounds_in_container,
SkMatrix44& out_container_transform,
@@ -2795,9 +3200,6 @@ bool AXObject::NameFromContents(bool recursive) const {
case kIframeRole:
case kImageRole:
case kInputTimeRole:
- case kLayoutTableRole:
- case kLayoutTableColumnRole:
- case kLayoutTableRowRole:
case kListBoxRole:
case kLogRole:
case kMainRole:
@@ -2844,6 +3246,8 @@ bool AXObject::NameFromContents(bool recursive) const {
case kAnnotationRole:
case kCanvasRole:
case kCaptionRole:
+ case kContentDeletionRole:
+ case kContentInsertionRole:
case kDescriptionListDetailRole:
case kDescriptionListRole:
case kDescriptionListTermRole:
@@ -2855,6 +3259,9 @@ bool AXObject::NameFromContents(bool recursive) const {
case kImageMapRole:
case kInlineTextBoxRole:
case kLabelRole:
+ case kLayoutTableRole:
+ case kLayoutTableColumnRole:
+ case kLayoutTableRowRole:
case kLegendRole:
case kListRole:
case kListItemRole:
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_object.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_object.h
index c3be48472db..1b84d5cf49b 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_object.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -33,6 +33,7 @@
#include <ostream>
#include "base/macros.h"
+#include "third_party/blink/renderer/core/accessibility/axid.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/editing/forward.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker.h"
@@ -43,6 +44,7 @@
#include "third_party/blink/renderer/platform/geometry/float_quad.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -68,8 +70,6 @@ enum class AOMFloatProperty;
enum class AOMRelationProperty;
enum class AOMRelationListProperty;
-typedef unsigned AXID;
-
class AXSparseAttributeClient {
public:
virtual void AddBoolAttribute(AXBoolAttribute, bool) = 0;
@@ -232,6 +232,163 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
}
};
+ // Iterator for doing an in-order traversal of the accessibility tree.
+ // Includes ignored objects in the traversal.
+ class MODULES_EXPORT InOrderTraversalIterator final
+ : public GarbageCollectedFinalized<InOrderTraversalIterator> {
+ public:
+ ~InOrderTraversalIterator() = default;
+
+ InOrderTraversalIterator(const InOrderTraversalIterator& other)
+ : current_(other.current_), previous_(other.previous_) {}
+
+ InOrderTraversalIterator& operator=(const InOrderTraversalIterator& other) {
+ current_ = other.current_;
+ previous_ = other.previous_;
+ return *this;
+ }
+
+ InOrderTraversalIterator& operator++() {
+ previous_ = current_;
+ current_ = (current_ && !current_->IsDetached())
+ ? current_->NextInTreeObject()
+ : nullptr;
+ return *this;
+ }
+
+ InOrderTraversalIterator operator++(int) {
+ InOrderTraversalIterator ret = *this;
+ ++*this;
+ return ret;
+ }
+
+ InOrderTraversalIterator& operator--() {
+ current_ = previous_;
+ previous_ = (current_ && !current_->IsDetached())
+ ? current_->PreviousInTreeObject()
+ : nullptr;
+ return *this;
+ }
+
+ InOrderTraversalIterator operator--(int) {
+ InOrderTraversalIterator ret = *this;
+ --*this;
+ return ret;
+ }
+
+ AXObject& operator*() const {
+ DCHECK(current_);
+ return *current_;
+ }
+
+ AXObject* operator->() const {
+ DCHECK(current_);
+ return static_cast<AXObject*>(current_);
+ }
+
+ void Trace(blink::Visitor* visitor) {
+ visitor->Trace(current_);
+ visitor->Trace(previous_);
+ }
+
+ MODULES_EXPORT friend void swap(InOrderTraversalIterator& left,
+ InOrderTraversalIterator& right) {
+ std::swap(left.current_, right.current_);
+ std::swap(left.previous_, right.previous_);
+ }
+
+ MODULES_EXPORT friend bool operator==(
+ const InOrderTraversalIterator& left,
+ const InOrderTraversalIterator& right) {
+ return left.current_ == right.current_;
+ }
+
+ MODULES_EXPORT friend bool operator!=(
+ const InOrderTraversalIterator& left,
+ const InOrderTraversalIterator& right) {
+ return !(left == right);
+ }
+
+ private:
+ InOrderTraversalIterator() = default;
+
+ explicit InOrderTraversalIterator(AXObject& current)
+ : current_(&current), previous_(nullptr) {}
+
+ friend class AXObject;
+ friend class AXObjectCacheImpl;
+
+ Member<AXObject> current_;
+ Member<AXObject> previous_;
+ };
+
+ // Iterator for the ancestors of an |AXObject|.
+ // Walks through all the unignored parents of the object up to the root.
+ // Does not include the object itself in the list of ancestors.
+ class MODULES_EXPORT AncestorsIterator final
+ : public GarbageCollectedFinalized<AncestorsIterator> {
+ public:
+ ~AncestorsIterator() = default;
+
+ AncestorsIterator(const AncestorsIterator& other)
+ : current_(other.current_) {}
+
+ AncestorsIterator& operator=(const AncestorsIterator& other) {
+ current_ = other.current_;
+ return *this;
+ }
+
+ AncestorsIterator& operator++() {
+ current_ = (current_ && !current_->IsDetached())
+ ? current_->ParentObjectUnignored()
+ : nullptr;
+ return *this;
+ }
+
+ AncestorsIterator operator++(int) {
+ AncestorsIterator ret = *this;
+ ++*this;
+ return ret;
+ }
+
+ AXObject& operator*() const {
+ DCHECK(current_);
+ return *current_;
+ }
+
+ AXObject* operator->() const {
+ DCHECK(current_);
+ return static_cast<AXObject*>(current_);
+ }
+
+ void Trace(blink::Visitor* visitor) { visitor->Trace(current_); }
+
+ MODULES_EXPORT friend void swap(AncestorsIterator& left,
+ AncestorsIterator& right) {
+ std::swap(left.current_, right.current_);
+ }
+
+ MODULES_EXPORT friend bool operator==(const AncestorsIterator& left,
+ const AncestorsIterator& right) {
+ return left.current_ == right.current_;
+ }
+
+ MODULES_EXPORT friend bool operator!=(const AncestorsIterator& left,
+ const AncestorsIterator& right) {
+ return !(left == right);
+ }
+
+ private:
+ AncestorsIterator() = default;
+
+ explicit AncestorsIterator(AXObject& current) : current_(&current) {}
+
+ friend class AXObject;
+ friend class AXObjectCacheImpl;
+
+ Member<AXObject> current_;
+ };
+
protected:
AXObject(AXObjectCacheImpl&);
@@ -302,7 +459,6 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
virtual AccessibilityRole RoleValue() const { return role_; }
bool IsARIATextControl() const;
virtual bool IsARIARow() const { return false; }
- virtual bool IsAXTable() const { return false; }
virtual bool IsAnchor() const { return false; }
bool IsButton() const;
bool IsCanvas() const { return RoleValue() == kCanvasRole; }
@@ -310,7 +466,6 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
bool IsCheckboxOrRadio() const { return IsCheckbox() || IsRadioButton(); }
bool IsColorWell() const { return RoleValue() == kColorWellRole; }
virtual bool IsControl() const { return false; }
- virtual bool IsDataTable() const { return false; }
virtual bool IsEmbeddedObject() const { return false; }
virtual bool IsFieldset() const { return false; }
virtual bool IsHeading() const { return false; }
@@ -354,10 +509,8 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
virtual bool IsMoveableSplitter() const { return false; }
virtual bool IsSpinButton() const { return RoleValue() == kSpinButtonRole; }
bool IsTabItem() const { return RoleValue() == kTabRole; }
- virtual bool IsTableCell() const { return false; }
- virtual bool IsTableRow() const { return false; }
virtual bool IsTextControl() const { return false; }
- virtual bool IsTableCol() const { return false; }
+ bool IsTextObject() const;
bool IsTree() const { return RoleValue() == kTreeRole; }
virtual bool IsVirtualObject() const { return false; }
bool IsWebArea() const { return RoleValue() == kWebAreaRole; }
@@ -405,12 +558,16 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
bool IsDescendantOfLeafNode() const;
AXObject* LeafNodeAncestor() const;
bool IsDescendantOfDisabledNode() const;
+ const AXObject* DatetimeAncestor(int max_levels_to_check = 3) const;
const AXObject* DisabledAncestor() const;
bool LastKnownIsIgnoredValue() const;
void SetLastKnownIsIgnoredValue(bool);
bool HasInheritedPresentationalRole() const;
bool IsPresentationalChild() const;
bool CanBeActiveDescendant() const;
+ // Some objects, such as table cells, could be the children of more than one
+ // object but have only one primary parent.
+ bool HasIndirectChildren() const;
//
// Accessible name calculation
@@ -579,9 +736,6 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
virtual bool SupportsARIAOwns() const { return false; }
bool SupportsRangeValue() const;
bool SupportsARIAReadOnly() const;
- virtual SortDirection GetSortDirection() const {
- return kSortDirectionUndefined;
- }
// Returns 0-based index.
int IndexInParent() const;
@@ -638,6 +792,9 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
// High-level accessibility tree access. Other modules should only use these
// functions.
+ AncestorsIterator AncestorsBegin();
+ AncestorsIterator AncestorsEnd();
+ InOrderTraversalIterator GetInOrderTraversalIterator();
int ChildCount() const;
const AXObjectVector& Children() const;
const AXObjectVector& Children();
@@ -708,6 +865,36 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
IntPoint MaximumScrollOffset() const;
void SetScrollOffset(const IntPoint&) const;
+ // Tables and grids.
+ virtual bool IsTableLikeRole() const;
+ virtual bool IsTableRowLikeRole() const;
+ virtual bool IsTableCellLikeRole() const;
+ virtual bool IsDataTable() const { return false; }
+ virtual bool IsTableCol() const { return false; }
+
+ // For a table.
+ virtual unsigned ColumnCount() const;
+ virtual unsigned RowCount() const;
+ virtual void ColumnHeaders(AXObjectVector&) const;
+ virtual void RowHeaders(AXObjectVector&) const;
+ virtual AXObject* CellForColumnAndRow(unsigned column, unsigned row) const;
+
+ // For a cell.
+ virtual unsigned ColumnIndex() const;
+ virtual unsigned RowIndex() const;
+ virtual unsigned ColumnSpan() const;
+ virtual unsigned RowSpan() const;
+ virtual unsigned AriaColumnIndex() const;
+ virtual unsigned AriaRowIndex() const;
+ virtual int AriaColumnCount() const;
+ virtual int AriaRowCount() const;
+ virtual SortDirection GetSortDirection() const {
+ return kSortDirectionUndefined;
+ }
+
+ // For a row or column.
+ virtual AXObject* HeaderObject() const { return nullptr; }
+
// If this object itself scrolls, return its ScrollableArea.
virtual ScrollableArea* GetScrollableAreaIfScrollable() const {
return nullptr;
@@ -777,7 +964,7 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
static bool IsARIAControl(AccessibilityRole);
static bool IsARIAInput(AccessibilityRole);
// Is this a widget that requires container widget.
- static bool IsSubWidget(AccessibilityRole);
+ bool IsSubWidget() const;
static AccessibilityRole AriaRoleToWebCoreRole(const String&);
static const AtomicString& RoleName(AccessibilityRole);
static const AtomicString& InternalRoleName(AccessibilityRole);
@@ -849,6 +1036,13 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
// Returns true if the event was handled.
bool DispatchEventToAOMEventListeners(Event&);
+ // Finds table, table row, and table cell parents and children
+ // skipping over generic containers.
+ AXObjectVector TableRowChildren() const;
+ AXObjectVector TableCellChildren() const;
+ const AXObject* TableRowParent() const;
+ const AXObject* TableParent() const;
+
mutable Member<AXObject> parent_;
// The following cached attribute values (the ones starting with m_cached*)
@@ -863,6 +1057,8 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
mutable bool cached_has_inherited_presentational_role_ : 1;
mutable bool cached_is_editable_root_;
mutable Member<AXObject> cached_live_region_root_;
+ mutable int cached_aria_column_index_;
+ mutable int cached_aria_row_index_;
Member<AXObjectCacheImpl> ax_object_cache_;
@@ -879,6 +1075,8 @@ class MODULES_EXPORT AXObject : public GarbageCollectedFinalized<AXObject> {
static bool IncludesARIAWidgetRole(const String&);
static bool HasInteractiveARIAAttribute(const Element&);
AccessibilityRole RemapAriaRoleDueToParent(AccessibilityRole) const;
+ unsigned ComputeAriaColumnIndex() const;
+ unsigned ComputeAriaRowIndex() const;
static unsigned number_of_live_ax_objects_;
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
index a37842eb40c..840c6bbae9b 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -32,8 +32,8 @@
#include "third_party/blink/public/platform/modules/permissions/permission.mojom-blink.h"
#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom-blink.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/public/web/web_frame_client.h"
-#include "third_party/blink/renderer/core/dom/accessible_node.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
+#include "third_party/blink/renderer/core/aom/accessible_node.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -66,9 +66,6 @@
#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/modules/accessibility/ax_aria_grid.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_aria_grid_cell.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_aria_grid_row.h"
#include "third_party/blink/renderer/modules/accessibility/ax_image_map_link.h"
#include "third_party/blink/renderer/modules/accessibility/ax_inline_text_box.h"
#include "third_party/blink/renderer/modules/accessibility/ax_layout_object.h"
@@ -84,11 +81,6 @@
#include "third_party/blink/renderer/modules/accessibility/ax_relation_cache.h"
#include "third_party/blink/renderer/modules/accessibility/ax_slider.h"
#include "third_party/blink/renderer/modules/accessibility/ax_svg_root.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table_cell.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table_column.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table_header_container.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table_row.h"
#include "third_party/blink/renderer/modules/accessibility/ax_virtual_object.h"
#include "third_party/blink/renderer/modules/permissions/permission_utils.h"
@@ -309,16 +301,6 @@ static bool NodeHasRole(Node* node, const String& role) {
return EqualIgnoringASCIICase(ToElement(node)->getAttribute(roleAttr), role);
}
-static bool NodeHasGridRole(Node* node) {
- return NodeHasRole(node, "grid") || NodeHasRole(node, "treegrid") ||
- NodeHasRole(node, "table");
-}
-
-static bool NodeHasCellRole(Node* node) {
- return NodeHasRole(node, "cell") || NodeHasRole(node, "gridcell") ||
- NodeHasRole(node, "columnheader") || NodeHasRole(node, "rowheader");
-}
-
AXObject* AXObjectCacheImpl::CreateFromRenderer(LayoutObject* layout_object) {
// FIXME: How could layoutObject->node() ever not be an Element?
Node* node = layout_object->GetNode();
@@ -331,14 +313,6 @@ AXObject* AXObjectCacheImpl::CreateFromRenderer(LayoutObject* layout_object) {
IsHTMLDListElement(node))))
return AXList::Create(layout_object, *this);
- // aria tables
- if (NodeHasGridRole(node))
- return AXARIAGrid::Create(layout_object, *this);
- if (NodeHasRole(node, "row"))
- return AXARIAGridRow::Create(layout_object, *this);
- if (NodeHasCellRole(node))
- return AXARIAGridCell::Create(layout_object, *this);
-
// media controls
if (node && node->IsMediaControlElement())
return AccessibilityMediaControl::Create(layout_object, *this);
@@ -360,40 +334,6 @@ AXObject* AXObjectCacheImpl::CreateFromRenderer(LayoutObject* layout_object) {
if (css_box->IsMenuList())
return AXMenuList::Create(ToLayoutMenuList(css_box), *this);
- // standard tables
- if (css_box->IsTable())
- return AXTable::Create(ToLayoutTable(css_box), *this);
- if (css_box->IsTableRow()) {
- // In an ARIA [tree]grid, use an ARIA row, otherwise a table row.
- LayoutTableRow* table_row = ToLayoutTableRow(css_box);
- LayoutTable* containing_table = table_row->Table();
- DCHECK(containing_table);
- if (NodeHasGridRole(containing_table->GetNode())) {
- if (node)
- return AXARIAGridRow::Create(layout_object, *this);
- // ARIA grids only create rows for non-anonymous nodes, because if
- // the author accidentally leaves out some table CSS, extra unexpected
- // anonymous layout cells exist that don't match the ARIA markup.
- return AXLayoutObject::Create(layout_object, *this);
- }
- return AXTableRow::Create(ToLayoutTableRow(css_box), *this);
- }
- if (css_box->IsTableCell()) {
- // In an ARIA [tree]grid, use an ARIA gridcell, otherwise a table cell.
- LayoutTableCell* table_cell = ToLayoutTableCell(css_box);
- LayoutTable* containing_table = table_cell->Table();
- DCHECK(containing_table);
- if (NodeHasGridRole(containing_table->GetNode())) {
- if (node)
- return AXARIAGridCell::Create(layout_object, *this);
- // ARIA grids only create cells for non-anonymous nodes, because if
- // the author accidentally leaves out some table CSS, extra unexpected
- // anonymous layout cells exist that don't match the ARIA markup.
- return AXLayoutObject::Create(layout_object, *this);
- }
- return AXTableCell::Create(ToLayoutTableCell(css_box), *this);
- }
-
// progress bar
if (css_box->IsProgress())
return AXProgressIndicator::Create(ToLayoutProgress(css_box), *this);
@@ -469,8 +409,7 @@ AXObject* AXObjectCacheImpl::GetOrCreate(Node* node) {
node_object_mapping_.Set(node, ax_id);
new_obj->Init();
new_obj->SetLastKnownIsIgnoredValue(new_obj->AccessibilityIsIgnored());
-
- relation_cache_->UpdateRelatedTree(node);
+ MaybeNewRelationTarget(node, new_obj);
return new_obj;
}
@@ -492,6 +431,8 @@ AXObject* AXObjectCacheImpl::GetOrCreate(LayoutObject* layout_object) {
layout_object_mapping_.Set(layout_object, axid);
new_obj->Init();
new_obj->SetLastKnownIsIgnoredValue(new_obj->AccessibilityIsIgnored());
+ if (layout_object->GetNode())
+ MaybeNewRelationTarget(layout_object->GetNode(), new_obj);
return new_obj;
}
@@ -522,12 +463,6 @@ AXObject* AXObjectCacheImpl::GetOrCreate(AccessibilityRole role) {
AXObject* obj = nullptr;
switch (role) {
- case kColumnRole:
- obj = AXTableColumn::Create(*this);
- break;
- case kTableHeaderContainerRole:
- obj = AXTableHeaderContainer::Create(*this);
- break;
case kSliderThumbRole:
obj = AXSliderThumb::Create(*this);
break;
@@ -705,6 +640,17 @@ AXObject* AXObjectCacheImpl::NearestExistingAncestor(Node* node) {
return nullptr;
}
+AXObject::InOrderTraversalIterator AXObjectCacheImpl::InOrderTraversalBegin() {
+ AXObject* root = Root();
+ if (root)
+ return AXObject::InOrderTraversalIterator(*root);
+ return InOrderTraversalEnd();
+}
+
+AXObject::InOrderTraversalIterator AXObjectCacheImpl::InOrderTraversalEnd() {
+ return AXObject::InOrderTraversalIterator();
+}
+
void AXObjectCacheImpl::SelectionChanged(Node* node) {
AXObject* nearestAncestor = NearestExistingAncestor(node);
if (nearestAncestor)
@@ -737,12 +683,30 @@ void AXObjectCacheImpl::TextChanged(AXObject* obj,
PostNotification(obj, AXObjectCacheImpl::kAXTextChanged);
}
+void AXObjectCacheImpl::DocumentTitleChanged() {
+ PostNotification(Root(), AXObjectCacheImpl::kAXDocumentTitleChanged);
+}
+
void AXObjectCacheImpl::UpdateCacheAfterNodeIsAttached(Node* node) {
// Calling get() will update the AX object if we had an AXNodeObject but now
// we need an AXLayoutObject, because it was reparented to a location outside
// of a canvas.
- Get(node);
- relation_cache_->UpdateRelatedTree(node);
+ AXObject* obj = Get(node);
+ MaybeNewRelationTarget(node, obj);
+}
+
+void AXObjectCacheImpl::DidInsertChildrenOfNode(Node* node) {
+ // If a node is inserted that is a descendant of a leaf node in the
+ // accessibility tree, notify the root of that subtree that its children have
+ // changed.
+ if (!node)
+ return;
+
+ if (AXObject* obj = Get(node)) {
+ TextChanged(obj, node);
+ } else {
+ DidInsertChildrenOfNode(NodeTraversal::Parent(*node));
+ }
}
void AXObjectCacheImpl::ChildrenChanged(Node* node) {
@@ -868,6 +832,10 @@ void AXObjectCacheImpl::ListboxActiveIndexChanged(HTMLSelectElement* select) {
ToAXListBox(obj)->ActiveIndexChanged();
}
+void AXObjectCacheImpl::LocationChanged(LayoutObject* layout_object) {
+ PostNotification(layout_object, kAXLocationChanged);
+}
+
void AXObjectCacheImpl::RadiobuttonRemovedFromGroup(
HTMLInputElement* group_member) {
AXObject* obj = Get(group_member);
@@ -905,6 +873,14 @@ void AXObjectCacheImpl::HandleClicked(Node* node) {
PostNotification(obj, kAXClicked);
}
+void AXObjectCacheImpl::HandleAttributeChanged(
+ const QualifiedName& attr_name,
+ AccessibleNode* accessible_node) {
+ modification_count_++;
+ if (AXObject* obj = Get(accessible_node))
+ PostNotification(obj, kAXAriaAttributeChanged);
+}
+
void AXObjectCacheImpl::HandleAriaExpandedChange(Node* node) {
if (AXObject* obj = GetOrCreate(node))
obj->HandleAriaExpandedChanged();
@@ -922,6 +898,27 @@ void AXObjectCacheImpl::HandleAriaSelectedChanged(Node* node) {
PostNotification(listbox, kAXSelectedChildrenChanged);
}
+// This might be the new target of a relation. Handle all possible cases.
+void AXObjectCacheImpl::MaybeNewRelationTarget(Node* node, AXObject* obj) {
+ // Track reverse relations
+ relation_cache_->UpdateRelatedTree(node);
+
+ if (!obj)
+ return;
+
+ // Check whether aria-activedescendant on a focused object points to |obj|.
+ // If so, fire activedescendantchanged event now.
+ // This is only for ARIA active descendants, not in a native control like a
+ // listbox, which has its own initial active descendant handling.
+ Node* focused_node = document_->FocusedElement();
+ if (focused_node) {
+ AXObject* focus = Get(focused_node);
+ if (focus && focus->ActiveDescendant() == obj &&
+ obj->CanBeActiveDescendant())
+ focus->HandleActiveDescendantChanged();
+ }
+}
+
void AXObjectCacheImpl::HandleActiveDescendantChanged(Node* node) {
// Changing the active descendant should trigger recomputing all
// cached values even if it doesn't result in a notification, because
@@ -974,7 +971,7 @@ void AXObjectCacheImpl::HandleAttributeChanged(const QualifiedName& attr_name,
else if (attr_name == forAttr && IsHTMLLabelElement(*element))
LabelChanged(element);
else if (attr_name == idAttr)
- relation_cache_->UpdateRelatedTree(element);
+ MaybeNewRelationTarget(element, Get(element));
if (!attr_name.LocalName().StartsWith("aria-"))
return;
@@ -1104,7 +1101,7 @@ void AXObjectCacheImpl::PostPlatformNotification(AXObject* obj,
if (!obj || !obj->GetDocument() || !obj->DocumentFrameView() ||
!obj->DocumentFrameView()->GetFrame().GetPage())
return;
- // Send via WebFrameClient
+ // Send via WebLocalFrameClient
WebLocalFrameImpl* webframe = WebLocalFrameImpl::FromFrame(
obj->GetDocument()->AXObjectCacheOwner().GetFrame());
if (webframe && webframe->Client()) {
@@ -1154,6 +1151,12 @@ void AXObjectCacheImpl::HandleEditableTextContentChanged(Node* node) {
PostNotification(obj, kAXValueChanged);
}
+void AXObjectCacheImpl::HandleScaleAndLocationChanged(Document* document) {
+ if (!document)
+ return;
+ PostNotification(document, kAXLocationChanged);
+}
+
void AXObjectCacheImpl::HandleTextFormControlChanged(Node* node) {
HandleEditableTextContentChanged(node);
}
@@ -1175,7 +1178,7 @@ void AXObjectCacheImpl::HandleValueChanged(Node* node) {
void AXObjectCacheImpl::HandleUpdateActiveMenuOption(LayoutMenuList* menu_list,
int option_index) {
- AXObject* obj = GetOrCreate(menu_list);
+ AXObject* obj = Get(menu_list);
if (!obj || !obj->IsMenuList())
return;
@@ -1358,6 +1361,8 @@ STATIC_ASSERT_ENUM(kWebAXEventChildrenChanged,
STATIC_ASSERT_ENUM(kWebAXEventClicked, AXObjectCacheImpl::kAXClicked);
STATIC_ASSERT_ENUM(kWebAXEventDocumentSelectionChanged,
AXObjectCacheImpl::kAXDocumentSelectionChanged);
+STATIC_ASSERT_ENUM(kWebAXEventDocumentTitleChanged,
+ AXObjectCacheImpl::kAXDocumentTitleChanged);
STATIC_ASSERT_ENUM(kWebAXEventExpandedChanged,
AXObjectCacheImpl::kAXExpandedChanged);
STATIC_ASSERT_ENUM(kWebAXEventFocus,
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
index f52b798ebbf..0cacaaa4600 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
@@ -35,7 +35,7 @@
#include "mojo/public/cpp/bindings/binding.h"
#include "third_party/blink/public/platform/modules/permissions/permission.mojom-blink.h"
#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom-blink.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache_base.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache_base.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
#include "third_party/blink/renderer/modules/accessibility/ax_object.h"
#include "third_party/blink/renderer/modules/modules_export.h"
@@ -65,6 +65,7 @@ class MODULES_EXPORT AXObjectCacheImpl
kAXChildrenChanged,
kAXClicked,
kAXDocumentSelectionChanged,
+ kAXDocumentTitleChanged,
kAXExpandedChanged,
kAXFocusedUIElementChanged,
kAXHide,
@@ -98,6 +99,13 @@ class MODULES_EXPORT AXObjectCacheImpl
void Dispose() override;
+ //
+ // Iterators.
+ //
+
+ AXObject::InOrderTraversalIterator InOrderTraversalBegin();
+ AXObject::InOrderTraversalIterator InOrderTraversalEnd();
+
void SelectionChanged(Node*) override;
void UpdateReverseRelations(const AXObject* relation_source,
const Vector<String>& target_ids);
@@ -108,6 +116,7 @@ class MODULES_EXPORT AXObjectCacheImpl
void ListboxOptionStateChanged(HTMLOptionElement*) override;
void ListboxSelectedChildrenChanged(HTMLSelectElement*) override;
void ListboxActiveIndexChanged(HTMLSelectElement*) override;
+ void LocationChanged(LayoutObject*) override;
void RadiobuttonRemovedFromGroup(HTMLInputElement*) override;
void Remove(AccessibleNode*) override;
@@ -121,9 +130,11 @@ class MODULES_EXPORT AXObjectCacheImpl
// changed.
void TextChanged(LayoutObject*) override;
void TextChanged(AXObject*, Node* optional_node = nullptr);
+ void DocumentTitleChanged() override;
// Called when a node has just been attached, so we can make sure we have the
// right subclass of AXObject.
void UpdateCacheAfterNodeIsAttached(Node*) override;
+ void DidInsertChildrenOfNode(Node*) override;
void HandleAttributeChanged(const QualifiedName& attr_name,
Element*) override;
@@ -132,6 +143,7 @@ class MODULES_EXPORT AXObjectCacheImpl
void HandleInitialFocus() override;
void HandleTextFormControlChanged(Node*) override;
void HandleEditableTextContentChanged(Node*) override;
+ void HandleScaleAndLocationChanged(Document*) override;
void HandleTextMarkerDataAdded(Node* start, Node* end) override;
void HandleValueChanged(Node*) override;
void HandleUpdateActiveMenuOption(LayoutMenuList*, int option_index) override;
@@ -140,6 +152,8 @@ class MODULES_EXPORT AXObjectCacheImpl
void HandleLoadComplete(Document*) override;
void HandleLayoutComplete(Document*) override;
void HandleClicked(Node*) override;
+ void HandleAttributeChanged(const QualifiedName& attr_name,
+ AccessibleNode*) override;
void SetCanvasObjectBounds(HTMLCanvasElement*,
Element*,
@@ -160,9 +174,6 @@ class MODULES_EXPORT AXObjectCacheImpl
void OnTouchAccessibilityHover(const IntPoint&) override;
- // Returns the root object for the entire document.
- AXObject* RootObject();
-
AXObject* ObjectFromAXID(AXID id) const { return objects_.at(id); }
AXObject* Root();
@@ -189,6 +200,8 @@ class MODULES_EXPORT AXObjectCacheImpl
void ChildrenChanged(AXObject*, Node* node_for_relation_update = nullptr);
+ void MaybeNewRelationTarget(Node* node, AXObject* obj);
+
void HandleActiveDescendantChanged(Node*);
void HandlePossibleRoleChange(Node*);
void HandleAriaExpandedChange(Node*);
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_object_cache_test.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_object_cache_test.cc
index d46f88a1ab7..11763332dd6 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_object_cache_test.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_object_cache_test.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/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/dom/document.h"
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_object_test.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_object_test.cc
index 49fedf87d9f..783667c202a 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_object_test.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_object_test.cc
@@ -5,12 +5,13 @@
#include "third_party/blink/renderer/modules/accessibility/ax_object.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
#include "third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h"
namespace blink {
TEST_F(AccessibilityTest, IsDescendantOf) {
- SetBodyInnerHTML(R"HTML(<button id='button'>button</button>)HTML");
+ SetBodyInnerHTML(R"HTML(<button id="button">button</button>)HTML");
const AXObject* root = GetAXRootObject();
ASSERT_NE(nullptr, root);
@@ -24,7 +25,7 @@ TEST_F(AccessibilityTest, IsDescendantOf) {
}
TEST_F(AccessibilityTest, IsAncestorOf) {
- SetBodyInnerHTML(R"HTML(<button id='button'>button</button>)HTML");
+ SetBodyInnerHTML(R"HTML(<button id="button">button</button>)HTML");
const AXObject* root = GetAXRootObject();
ASSERT_NE(nullptr, root);
@@ -38,9 +39,9 @@ TEST_F(AccessibilityTest, IsAncestorOf) {
}
TEST_F(AccessibilityTest, SimpleTreeNavigation) {
- SetBodyInnerHTML(R"HTML(<input id='input' type='text' value='value'>"
- R"<p id='paragraph'>hello<br id='br'>there</p>"
- R"<button id='button'>button</button>)HTML");
+ SetBodyInnerHTML(R"HTML(<input id="input" type="text" value="value">
+ <p id="paragraph">hello<br id="br">there</p>
+ <button id="button">button</button>)HTML");
const AXObject* root = GetAXRootObject();
ASSERT_NE(nullptr, root);
@@ -70,8 +71,8 @@ TEST_F(AccessibilityTest, SimpleTreeNavigation) {
EXPECT_EQ(AccessibilityRole::kStaticTextRole,
paragraph->DeepestLastChild()->RoleValue());
- // There is a static text element in between the input and the paragraph.
- EXPECT_EQ(paragraph->PreviousSibling(), input->NextSibling());
+ EXPECT_EQ(paragraph->PreviousSibling(), input);
+ EXPECT_EQ(paragraph, input->NextSibling());
ASSERT_NE(nullptr, br->NextSibling());
EXPECT_EQ(AccessibilityRole::kStaticTextRole, br->NextSibling()->RoleValue());
ASSERT_NE(nullptr, br->PreviousSibling());
@@ -80,9 +81,9 @@ TEST_F(AccessibilityTest, SimpleTreeNavigation) {
}
TEST_F(AccessibilityTest, AXObjectComparisonOperators) {
- SetBodyInnerHTML(R"HTML(<input id='input' type='text' value='value'>"
- R"<p id='paragraph'>hello<br id='br'>there</p>"
- R"<button id='button'>button</button>)HTML");
+ SetBodyInnerHTML(R"HTML(<input id="input" type="text" value="value">
+ <p id="paragraph">hello<br id="br">there</p>
+ <button id="button">button</button>)HTML");
const AXObject* root = GetAXRootObject();
ASSERT_NE(nullptr, root);
@@ -121,4 +122,49 @@ TEST_F(AccessibilityTest, AXObjectComparisonOperators) {
EXPECT_FALSE(*button > *button);
}
+TEST_F(AccessibilityTest, AXObjectAncestorsIterator) {
+ SetBodyInnerHTML(
+ R"HTML(<p id="paragraph"><b id="bold"><br id="br"></b></p>)HTML");
+
+ AXObject* root = GetAXRootObject();
+ ASSERT_NE(nullptr, root);
+ AXObject* paragraph = GetAXObjectByElementId("paragraph");
+ ASSERT_NE(nullptr, paragraph);
+ AXObject* bold = GetAXObjectByElementId("bold");
+ ASSERT_NE(nullptr, bold);
+ AXObject* br = GetAXObjectByElementId("br");
+ ASSERT_NE(nullptr, br);
+ ASSERT_EQ(AccessibilityRole::kLineBreakRole, br->RoleValue());
+
+ AXObject::AncestorsIterator iter = br->AncestorsBegin();
+ EXPECT_EQ(*paragraph, *iter);
+ EXPECT_EQ(AccessibilityRole::kParagraphRole, iter->RoleValue());
+ EXPECT_EQ(*root, *++iter);
+ EXPECT_EQ(*root, *iter++);
+ EXPECT_EQ(br->AncestorsEnd(), ++iter);
+}
+
+TEST_F(AccessibilityTest, AXObjectInOrderTraversalIterator) {
+ SetBodyInnerHTML(R"HTML(<button id="button">Button</button>)HTML");
+
+ AXObject* root = GetAXRootObject();
+ ASSERT_NE(nullptr, root);
+ AXObject* button = GetAXObjectByElementId("button");
+ ASSERT_NE(nullptr, button);
+
+ AXObject::InOrderTraversalIterator iter = root->GetInOrderTraversalIterator();
+ EXPECT_EQ(*root, *iter);
+ ++iter; // Skip the generic container which is an ignored object.
+ EXPECT_NE(GetAXObjectCache().InOrderTraversalEnd(), iter);
+ EXPECT_EQ(*button, *++iter);
+ EXPECT_EQ(AccessibilityRole::kButtonRole, iter->RoleValue());
+ EXPECT_EQ(*button, *iter++);
+ EXPECT_EQ(GetAXObjectCache().InOrderTraversalEnd(), iter);
+ EXPECT_EQ(*button, *--iter);
+ EXPECT_EQ(*button, *iter--);
+ --iter; // Skip the generic container which is an ignored object.
+ EXPECT_EQ(AccessibilityRole::kWebAreaRole, iter->RoleValue());
+ EXPECT_EQ(GetAXObjectCache().InOrderTraversalBegin(), iter);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_position.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_position.cc
index ce08484a8a1..54fce28e26a 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_position.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_position.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/modules/accessibility/ax_position.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.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/ephemeral_range.h"
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/core/editing/iterators/text_iterator.h"
#include "third_party/blink/renderer/core/editing/position.h"
#include "third_party/blink/renderer/core/editing/position_with_affinity.h"
+#include "third_party/blink/renderer/modules/accessibility/ax_layout_object.h"
#include "third_party/blink/renderer/modules/accessibility/ax_object.h"
#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
@@ -19,9 +20,12 @@ namespace blink {
// static
const AXPosition AXPosition::CreatePositionBeforeObject(const AXObject& child) {
+ if (child.IsDetached())
+ return {};
+
// If |child| is a text object, make behavior the same as
// |CreateFirstPositionInObject| so that equality would hold.
- if (child.GetNode() && child.GetNode()->IsTextNode())
+ if (child.IsTextObject())
return CreateFirstPositionInObject(child);
const AXObject* parent = child.ParentObjectUnignored();
@@ -29,14 +33,17 @@ const AXPosition AXPosition::CreatePositionBeforeObject(const AXObject& child) {
AXPosition position(*parent);
position.text_offset_or_child_index_ = child.IndexInParent();
DCHECK(position.IsValid());
- return position;
+ return position.AsUnignoredPosition();
}
// static
const AXPosition AXPosition::CreatePositionAfterObject(const AXObject& child) {
+ if (child.IsDetached())
+ return {};
+
// If |child| is a text object, make behavior the same as
// |CreateLastPositionInObject| so that equality would hold.
- if (child.GetNode() && child.GetNode()->IsTextNode())
+ if (child.IsTextObject())
return CreateLastPositionInObject(child);
const AXObject* parent = child.ParentObjectUnignored();
@@ -44,60 +51,73 @@ const AXPosition AXPosition::CreatePositionAfterObject(const AXObject& child) {
AXPosition position(*parent);
position.text_offset_or_child_index_ = child.IndexInParent() + 1;
DCHECK(position.IsValid());
- return position;
+ return position.AsUnignoredPosition();
}
// static
const AXPosition AXPosition::CreateFirstPositionInObject(
const AXObject& container) {
- if (container.GetNode() && container.GetNode()->IsTextNode()) {
+ if (container.IsDetached())
+ return {};
+
+ if (container.IsTextObject()) {
AXPosition position(container);
position.text_offset_or_child_index_ = 0;
DCHECK(position.IsValid());
- return position;
+ return position.AsUnignoredPosition();
}
- AXPosition position(container);
+
+ const AXObject* unignored_container = container.AccessibilityIsIgnored()
+ ? container.ParentObjectUnignored()
+ : &container;
+ DCHECK(unignored_container);
+ AXPosition position(*unignored_container);
position.text_offset_or_child_index_ = 0;
DCHECK(position.IsValid());
- return position;
+ return position.AsUnignoredPosition();
}
// static
const AXPosition AXPosition::CreateLastPositionInObject(
const AXObject& container) {
- if (container.GetNode() && container.GetNode()->IsTextNode()) {
+ if (container.IsDetached())
+ return {};
+
+ if (container.IsTextObject()) {
AXPosition position(container);
- const auto first_position =
- Position::FirstPositionInNode(*container.GetNode());
- const auto last_position =
- Position::LastPositionInNode(*container.GetNode());
- position.text_offset_or_child_index_ =
- TextIterator::RangeLength(first_position, last_position);
+ position.text_offset_or_child_index_ = position.MaxTextOffset();
DCHECK(position.IsValid());
- return position;
+ return position.AsUnignoredPosition();
}
- AXPosition position(container);
- position.text_offset_or_child_index_ = container.ChildCount();
+
+ const AXObject* unignored_container = container.AccessibilityIsIgnored()
+ ? container.ParentObjectUnignored()
+ : &container;
+ DCHECK(unignored_container);
+ AXPosition position(*unignored_container);
+ position.text_offset_or_child_index_ = unignored_container->ChildCount();
DCHECK(position.IsValid());
- return position;
+ return position.AsUnignoredPosition();
}
// static
const AXPosition AXPosition::CreatePositionInTextObject(
const AXObject& container,
- int offset,
- TextAffinity affinity) {
- DCHECK(container.GetNode() && container.GetNode()->IsTextNode())
- << "Text positions should be anchored to a text node.";
+ const int offset,
+ const TextAffinity affinity) {
+ if (container.IsDetached() || !container.IsTextObject())
+ return {};
+
AXPosition position(container);
position.text_offset_or_child_index_ = offset;
position.affinity_ = affinity;
DCHECK(position.IsValid());
- return position;
+ return position.AsUnignoredPosition();
}
// static
-const AXPosition AXPosition::FromPosition(const Position& position) {
+const AXPosition AXPosition::FromPosition(const Position& position,
+ const TextAffinity affinity) {
if (position.IsNull() || position.IsOrphan())
return {};
@@ -115,41 +135,50 @@ const AXPosition AXPosition::FromPosition(const Position& position) {
DCHECK(anchor_node);
const AXObject* container = ax_object_cache_impl->GetOrCreate(anchor_node);
DCHECK(container);
+
AXPosition ax_position(*container);
if (anchor_node->IsTextNode()) {
// Convert from a DOM offset that may have uncompressed white space to a
// character offset.
- // TODO(ax-dev): Use LayoutNG offset mapping instead of |TextIterator|.
+ // TODO(nektar): Use LayoutNG offset mapping instead of
+ // |TextIterator|.
const auto first_position = Position::FirstPositionInNode(*anchor_node);
int offset =
TextIterator::RangeLength(first_position, parent_anchored_position);
ax_position.text_offset_or_child_index_ = offset;
- DCHECK(ax_position.IsValid());
- return ax_position;
+ } else {
+ // |ComputeNodeAfterPosition| returns nullptr for "after children"
+ // positions.
+ const Node* node_after_position = position.ComputeNodeAfterPosition();
+ if (!node_after_position) {
+ ax_position.text_offset_or_child_index_ = container->ChildCount();
+ } else {
+ const AXObject* ax_child =
+ ax_object_cache_impl->GetOrCreate(node_after_position);
+ DCHECK(ax_child);
+ if (ax_child->IsDescendantOf(*container)) {
+ ax_position.text_offset_or_child_index_ = ax_child->IndexInParent();
+ } else {
+ return CreatePositionBeforeObject(*ax_child);
+ }
+ }
}
- const Node* node_after_position = position.ComputeNodeAfterPosition();
- if (!node_after_position) {
- ax_position.text_offset_or_child_index_ = container->ChildCount();
- DCHECK(ax_position.IsValid());
- return ax_position;
- }
+ ax_position.affinity_ = affinity;
+ DCHECK(ax_position.IsValid());
+ return ax_position.AsUnignoredPosition();
+}
- const AXObject* ax_child =
- ax_object_cache_impl->GetOrCreate(node_after_position);
- DCHECK(ax_child);
- if (ax_child->IsDescendantOf(*container)) {
- ax_position.text_offset_or_child_index_ = ax_child->IndexInParent();
- DCHECK(ax_position.IsValid());
- return ax_position;
- }
- return CreatePositionBeforeObject(*ax_child);
+// static
+const AXPosition AXPosition::FromPosition(
+ const PositionWithAffinity& position_with_affinity) {
+ return FromPosition(position_with_affinity.GetPosition(),
+ position_with_affinity.Affinity());
}
-// Only for use by |AXSelection| to represent empty selection ranges.
AXPosition::AXPosition()
: container_object_(nullptr),
- text_offset_or_child_index_(),
+ text_offset_or_child_index_(0),
affinity_(TextAffinity::kDownstream) {
#if DCHECK_IS_ON()
dom_tree_version_ = 0;
@@ -159,7 +188,7 @@ AXPosition::AXPosition()
AXPosition::AXPosition(const AXObject& container)
: container_object_(&container),
- text_offset_or_child_index_(),
+ text_offset_or_child_index_(0),
affinity_(TextAffinity::kDownstream) {
const Document* document = container_object_->GetDocument();
DCHECK(document);
@@ -169,113 +198,305 @@ AXPosition::AXPosition(const AXObject& container)
#endif
}
-const AXObject* AXPosition::ObjectAfterPosition() const {
+const AXObject* AXPosition::ChildAfterTreePosition() const {
if (!IsValid() || IsTextPosition())
return nullptr;
- if (!container_object_->ChildCount())
- return container_object_->NextInTreeObject();
- if (container_object_->ChildCount() == ChildIndex())
- return container_object_->LastChild()->NextInTreeObject();
+ if (container_object_->ChildCount() <= ChildIndex())
+ return nullptr;
return *(container_object_->Children().begin() + ChildIndex());
}
int AXPosition::ChildIndex() const {
if (!IsTextPosition())
- return *text_offset_or_child_index_;
- NOTREACHED() << *this << " should not be a text position.";
+ return text_offset_or_child_index_;
+ NOTREACHED() << *this << " should be a tree position.";
return 0;
}
int AXPosition::TextOffset() const {
if (IsTextPosition())
- return *text_offset_or_child_index_;
+ return text_offset_or_child_index_;
NOTREACHED() << *this << " should be a text position.";
return 0;
}
+int AXPosition::MaxTextOffset() const {
+ if (!IsTextPosition()) {
+ NOTREACHED() << *this << " should be a text position.";
+ return 0;
+ }
+
+ if (container_object_->IsAXInlineTextBox() || !container_object_->GetNode()) {
+ // 1. The |Node| associated with an inline text box contains all the text in
+ // the static text object parent, whilst the inline text box might contain
+ // only part of it.
+ // 2. Some accessibility objects, such as those used for CSS "::before" and
+ // "::after" content, don't have an associated text node. We retrieve the
+ // text from the inline text box or layout object itself.
+ return container_object_->ComputedName().length();
+ }
+
+ // TODO(nektar): Use LayoutNG offset mapping instead of |TextIterator|.
+ const auto first_position =
+ Position::FirstPositionInNode(*container_object_->GetNode());
+ const auto last_position =
+ Position::LastPositionInNode(*container_object_->GetNode());
+ return TextIterator::RangeLength(first_position, last_position);
+}
+
bool AXPosition::IsValid() const {
if (!container_object_ || container_object_->IsDetached())
return false;
- if (!container_object_->GetNode() ||
- !container_object_->GetNode()->isConnected())
+ if (!container_object_->GetDocument())
return false;
+ // Some container objects, such as those for CSS "::before" and "::after"
+ // text, don't have associated DOM nodes.
+ if (container_object_->GetNode() &&
+ !container_object_->GetNode()->isConnected()) {
+ return false;
+ }
- // We can't have both an object and a text anchored position, but we must have
- // at least one of them.
- DCHECK(text_offset_or_child_index_);
- if (text_offset_or_child_index_ &&
- !container_object_->GetNode()->IsTextNode()) {
+ if (IsTextPosition()) {
+ if (text_offset_or_child_index_ > MaxTextOffset())
+ return false;
+ } else {
if (text_offset_or_child_index_ > container_object_->ChildCount())
return false;
}
- DCHECK(container_object_->GetNode()->GetDocument().IsActive());
- DCHECK(!container_object_->GetNode()->GetDocument().NeedsLayoutTreeUpdate());
+ DCHECK(container_object_->GetDocument()->IsActive());
+ DCHECK(!container_object_->GetDocument()->NeedsLayoutTreeUpdate());
#if DCHECK_IS_ON()
- DCHECK_EQ(container_object_->GetNode()->GetDocument().DomTreeVersion(),
+ DCHECK_EQ(container_object_->GetDocument()->DomTreeVersion(),
dom_tree_version_);
- DCHECK_EQ(container_object_->GetNode()->GetDocument().StyleVersion(),
- style_version_);
+ DCHECK_EQ(container_object_->GetDocument()->StyleVersion(), style_version_);
#endif // DCHECK_IS_ON()
return true;
}
bool AXPosition::IsTextPosition() const {
- return IsValid() && container_object_->GetNode()->IsTextNode();
+ // We don't call |IsValid| from here because |IsValid| uses this method.
+ if (!container_object_)
+ return false;
+ return container_object_->IsTextObject();
}
const AXPosition AXPosition::CreateNextPosition() const {
- if (IsTextPosition()) {
- if (!ContainerObject()->NextInTreeObject())
+ if (!IsValid())
+ return {};
+
+ if (IsTextPosition() && TextOffset() < MaxTextOffset())
+ return CreatePositionInTextObject(*container_object_, TextOffset() + 1);
+
+ const AXObject* child = ChildAfterTreePosition();
+ // Handles both an "after children" position, or a text position that is after
+ // the last character.
+ if (!child) {
+ const AXObject* next_in_order = container_object_->NextInTreeObject();
+ if (!next_in_order || !next_in_order->ParentObjectUnignored())
return {};
- return CreatePositionBeforeObject(*ContainerObject()->NextInTreeObject());
+ return CreatePositionBeforeObject(*next_in_order);
}
- if (!ObjectAfterPosition())
+ if (!child->ParentObjectUnignored())
return {};
- return CreatePositionBeforeObject(*ObjectAfterPosition());
+ return CreatePositionAfterObject(*child);
}
const AXPosition AXPosition::CreatePreviousPosition() const {
- if (!ContainerObject()->PreviousInTreeObject())
+ if (!IsValid())
+ return {};
+
+ if (IsTextPosition() && TextOffset() > 0)
+ return CreatePositionInTextObject(*container_object_, TextOffset() - 1);
+
+ const AXObject* child = ChildAfterTreePosition();
+ // Handles both an "after children" position, or a text position that is
+ // before the first character.
+ if (!child) {
+ if (container_object_->ChildCount()) {
+ const AXObject* last_child = container_object_->LastChild();
+ // Dont skip over any intervening text.
+ if (last_child->IsTextObject())
+ return CreatePositionAfterObject(*last_child);
+
+ return CreatePositionBeforeObject(*last_child);
+ }
+
+ const AXObject* previous_in_order =
+ container_object_->PreviousInTreeObject();
+ if (!previous_in_order || !previous_in_order->ParentObjectUnignored())
+ return {};
+ return CreatePositionAfterObject(*previous_in_order);
+ }
+
+ const AXObject* object_before_position = child->PreviousInTreeObject();
+ if (!object_before_position ||
+ !object_before_position->ParentObjectUnignored()) {
return {};
- return CreatePositionAfterObject(*ContainerObject()->PreviousInTreeObject());
+ }
+
+ // Dont skip over any intervening text.
+ if (object_before_position->IsTextObject())
+ return CreatePositionAfterObject(*object_before_position);
+
+ return CreatePositionBeforeObject(*object_before_position);
}
-const PositionWithAffinity AXPosition::ToPositionWithAffinity(
+const AXPosition AXPosition::AsUnignoredPosition(
const AXPositionAdjustmentBehavior adjustment_behavior) const {
if (!IsValid())
return {};
- const Node* container_node = container_object_->GetNode();
- if (!container_node) {
+ // There are four possibilities:
+ // 1. The container object is ignored and this is not a text position or an
+ // "after children" position. Try to find the equivalent position in the
+ // unignored parent.
+ // 2. The container object is ignored and this is a text
+ // position. Adjust to the position immediately to the left or to the right,
+ // based on the adjustment behavior, possibly changing to a non-text position
+ // and recurse. 3. The position is an "after children" position, but the last
+ // child is ignored. Do the same as 2. 4. The object after the position is
+ // ignored, but the container object is not. Do the same as 2.
+
+ const AXObject* container = container_object_;
+ const AXObject* child = ChildAfterTreePosition();
+ const AXObject* last_child = container->LastChild();
+
+ // Case 1.
+ if (container->AccessibilityIsIgnored() && child) {
+ return CreatePositionBeforeObject(*child).AsUnignoredPosition(
+ adjustment_behavior);
+ }
+
+ // Cases 2, 3 and 4.
+ if (container->AccessibilityIsIgnored() ||
+ (!child && last_child && last_child->AccessibilityIsIgnored()) ||
+ (child && child->AccessibilityIsIgnored())) {
switch (adjustment_behavior) {
case AXPositionAdjustmentBehavior::kMoveRight:
- CreateNextPosition().ToPositionWithAffinity(adjustment_behavior);
- break;
+ return CreateNextPosition().AsUnignoredPosition(adjustment_behavior);
case AXPositionAdjustmentBehavior::kMoveLeft:
- CreatePreviousPosition().ToPositionWithAffinity(adjustment_behavior);
- break;
+ return CreatePreviousPosition().AsUnignoredPosition(
+ adjustment_behavior);
}
}
- if (!IsTextPosition()) {
- if (ChildIndex() == container_object_->ChildCount()) {
+ return *this;
+}
+
+const AXPosition AXPosition::AsValidDOMPosition(
+ const AXPositionAdjustmentBehavior adjustment_behavior) const {
+ if (!IsValid())
+ return {};
+
+ // We adjust to the next or previous position if the container or the child
+ // object after a tree position are mock or virtual objects, since mock or
+ // virtual objects will not be present in the DOM tree. Alternatively, in the
+ // case of an "after children" position, we need to check if the last child of
+ // the container object is mock or virtual and adjust accordingly. Abstract
+ // inline text boxes and static text nodes for CSS "::before" and "::after"
+ // positions are also considered to be virtual since they don't have an
+ // associated DOM node.
+
+ // More Explaination:
+ // If the child after a tree position doesn't have an associated node in the
+ // DOM tree, we adjust to the next or previous position because a
+ // corresponding child node will not be found in the DOM tree. We need a
+ // corresponding child node in the DOM tree so that we can anchor the DOM
+ // position before it. We can't ask the layout tree for the child's container
+ // block node, because this might change the placement of the AX position
+ // drastically. However, if the container doesn't have a corresponding DOM
+ // node, we need to use the layout tree to find its corresponding container
+ // block node, because no AX positions inside an anonymous layout block could
+ // be represented in the DOM tree anyway.
+
+ const AXObject* container = container_object_;
+ DCHECK(container);
+ const AXObject* child = ChildAfterTreePosition();
+ const AXObject* last_child = container->LastChild();
+ if ((IsTextPosition() && !container->GetNode()) ||
+ container->IsMockObject() || container->IsVirtualObject() ||
+ (!child && last_child &&
+ (!last_child->GetNode() || last_child->IsMockObject() ||
+ last_child->IsVirtualObject())) ||
+ (child && (!child->GetNode() || child->IsMockObject() ||
+ child->IsVirtualObject()))) {
+ switch (adjustment_behavior) {
+ case AXPositionAdjustmentBehavior::kMoveRight:
+ return CreateNextPosition().AsValidDOMPosition(adjustment_behavior);
+ case AXPositionAdjustmentBehavior::kMoveLeft:
+ return CreatePreviousPosition().AsValidDOMPosition(adjustment_behavior);
+ }
+ }
+
+ if (container->GetNode())
+ return *this;
+
+ DCHECK(container->IsAXLayoutObject())
+ << "Non virtual and non mock AX objects that are not associated to a DOM "
+ "node should have an associated layout object.";
+ const Node* anchor_node =
+ ToAXLayoutObject(container)->GetNodeOrContainingBlockNode();
+ DCHECK(anchor_node)
+ << "All anonymous layout objects should have a containing block element.";
+ DCHECK(!container->IsDetached());
+ auto& ax_object_cache_impl = container->AXObjectCache();
+ const AXObject* new_container = ax_object_cache_impl.GetOrCreate(anchor_node);
+ DCHECK(new_container);
+ AXPosition position(*new_container);
+ if (new_container == container->ParentObjectUnignored()) {
+ position.text_offset_or_child_index_ = container->IndexInParent();
+ } else {
+ position.text_offset_or_child_index_ = 0;
+ }
+ DCHECK(position.IsValid());
+ return position.AsValidDOMPosition(adjustment_behavior);
+}
+
+const PositionWithAffinity AXPosition::ToPositionWithAffinity(
+ const AXPositionAdjustmentBehavior adjustment_behavior) const {
+ const AXPosition adjusted_position = AsValidDOMPosition(adjustment_behavior);
+ if (!adjusted_position.IsValid())
+ return {};
+
+ const Node* container_node = adjusted_position.container_object_->GetNode();
+ DCHECK(container_node);
+ if (!adjusted_position.IsTextPosition()) {
+ // AX positions that are unumbiguously at the start or end of a container,
+ // should convert to the corresponding DOM positions at the start or end of
+ // the same container. Other child positions in the accessibility tree
+ // should recompute their parent in the DOM tree, because they might be ARIA
+ // owned by a different object in the accessibility tree than in the DOM
+ // tree, or their parent in the accessibility tree might be ignored.
+
+ if (adjusted_position.ChildIndex() == 0) {
+ // Creates a |PositionAnchorType::kBeforeChildren| position.
+ return PositionWithAffinity(
+ Position::FirstPositionInNode(*container_node), affinity_);
+ }
+
+ if (adjusted_position.ChildIndex() == container_object_->ChildCount()) {
+ // Creates a |PositionAnchorType::kAfterChildren| position.
return PositionWithAffinity(Position::LastPositionInNode(*container_node),
affinity_);
}
+
+ // Creates a |PositionAnchorType::kOffsetInAnchor| position.
const AXObject* ax_child =
- *(container_object_->Children().begin() + ChildIndex());
+ *(adjusted_position.container_object_->Children().begin() +
+ adjusted_position.ChildIndex());
+ DCHECK(ax_child);
return PositionWithAffinity(
Position::InParentBeforeNode(*(ax_child->GetNode())), affinity_);
}
- // TODO(ax-dev): Use LayoutNG offset mapping instead of |TextIterator|.
+ // TODO(nektar): Use LayoutNG offset mapping instead of |TextIterator|.
const auto first_position = Position::FirstPositionInNode(*container_node);
const auto last_position = Position::LastPositionInNode(*container_node);
CharacterIterator character_iterator(first_position, last_position);
const EphemeralRange range = character_iterator.CalculateCharacterSubrange(
- 0, *text_offset_or_child_index_);
+ 0, adjusted_position.text_offset_or_child_index_);
return PositionWithAffinity(range.EndPosition(), affinity_);
}
@@ -374,11 +595,12 @@ std::ostream& operator<<(std::ostream& ostream, const AXPosition& position) {
if (!position.IsValid())
return ostream << "Invalid AXPosition";
if (position.IsTextPosition()) {
- return ostream << "AX text position in " << position.ContainerObject()
+ return ostream << "AX text position in " << *position.ContainerObject()
<< ", " << position.TextOffset();
}
return ostream << "AX object anchored position in "
- << position.ContainerObject() << ", " << position.ChildIndex();
+ << *position.ContainerObject() << ", "
+ << position.ChildIndex();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_position.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_position.h
index 45868abb6a8..bbae2cbe4e4 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_position.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_position.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_POSITION_H_
#include <base/logging.h>
-#include <base/optional.h>
#include <stdint.h>
#include <ostream>
@@ -20,14 +19,22 @@ namespace blink {
class AXObject;
-// When converting to a DOM position from an |AXPosition| and the corresponding
-// DOM position is invalid or doesn't exist, determines how to adjust the
-// |AXPosition| in order to make it valid.
+// When converting to a DOM position from an |AXPosition| or vice versa, and the
+// corresponding position is invalid, doesn't exist, or is inside an ignored
+// object or a range of ignored objects, determines how to adjust the new
+// position in order to make it valid.
enum class AXPositionAdjustmentBehavior { kMoveLeft, kMoveRight };
// Describes a position in the Blink accessibility tree.
// A position is either anchored to before or after a child object inside a
// container object, or is anchored to a character inside a text object.
+// The former are called tree positions, and the latter text positions.
+// Tree positions are never located on a specific |AXObject|. Rather, they are
+// always between two objects, or an object and the start / end of their
+// container's children, known as "before children" and "after children"
+// positions respectively. They should be thought of like a caret that is always
+// between two characters. Another way of calling these types of positions is
+// object anchored and text anchored.
class MODULES_EXPORT AXPosition final {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
@@ -39,25 +46,47 @@ class MODULES_EXPORT AXPosition final {
static const AXPosition CreateLastPositionInObject(const AXObject& container);
static const AXPosition CreatePositionInTextObject(
const AXObject& container,
- int offset,
- TextAffinity = TextAffinity::kDownstream);
- static const AXPosition FromPosition(const Position&);
+ const int offset,
+ const TextAffinity = TextAffinity::kDownstream);
+ static const AXPosition FromPosition(
+ const Position&,
+ const TextAffinity = TextAffinity::kDownstream);
static const AXPosition FromPosition(const PositionWithAffinity&);
+ // Creates an empty position. |IsValid| will return false.
+ AXPosition();
+
AXPosition(const AXPosition&) = default;
AXPosition& operator=(const AXPosition&) = default;
~AXPosition() = default;
+ // The |AXObject| in which the tree position is located, or in whose text the
+ // text position is found.
const AXObject* ContainerObject() const { return container_object_; }
- const AXObject* ObjectAfterPosition() const;
+
+ // Returns |nullptr| for text, and "after children" or equivalent positions.
+ const AXObject* ChildAfterTreePosition() const;
+
+ // Only valid for tree positions.
int ChildIndex() const;
+
+ // Only valid for text positions.
int TextOffset() const;
+
+ // If this is a text position, the length of the text in its container object.
+ int MaxTextOffset() const;
+
+ // When the same character offset could correspond to two possible caret
+ // positions, upstream means it's on the previous line rather than the next
+ // line.
TextAffinity Affinity() const { return affinity_; }
// Verifies if the anchor is present and if it's set to a live object with a
// connected node.
bool IsValid() const;
+ operator bool() const { return IsValid(); }
+
// Returns whether this is a position anchored to a character inside a text
// object.
bool IsTextPosition() const;
@@ -65,12 +94,31 @@ class MODULES_EXPORT AXPosition final {
const AXPosition CreateNextPosition() const;
const AXPosition CreatePreviousPosition() const;
+ // Returns an adjusted position by skipping over any ignored objects in the
+ // case of a "before object" or "after object" position, or skipping over any
+ // ignored children in the case of a "before children" or "after children"
+ // position. If a text object is ignored, returns a position anchored at the
+ // nearest object, which might not be a text object. If the container object
+ // is ignored, tries to find if an equivalent position exists in its unignored
+ // parent, since all the children of an ignored object in the accessibility
+ // tree appear as children of its immediate unignored parent.
+ const AXPosition AsUnignoredPosition(
+ const AXPositionAdjustmentBehavior =
+ AXPositionAdjustmentBehavior::kMoveLeft) const;
+
+ // Adjusts the position by skipping over any objects that don't have a
+ // corresponding |node| in the DOM tree, e.g. list bullets.
+ const AXPosition AsValidDOMPosition(
+ const AXPositionAdjustmentBehavior =
+ AXPositionAdjustmentBehavior::kMoveLeft) const;
+
+ // Converts to a DOM position.
const PositionWithAffinity ToPositionWithAffinity(
const AXPositionAdjustmentBehavior =
AXPositionAdjustmentBehavior::kMoveLeft) const;
private:
- AXPosition();
+ // Only used by static Create... methods.
explicit AXPosition(const AXObject& container);
// The |AXObject| in which the position is present.
@@ -84,23 +132,17 @@ class MODULES_EXPORT AXPosition final {
// of |container_object_| before the position. The canonical text is the DOM
// node's text but with, e.g., whitespace collapsed and any transformations
// applied.
- base::Optional<int> text_offset_or_child_index_;
+ int text_offset_or_child_index_;
// When the same character offset could correspond to two possible caret
- // positions, upstream means it's on the previous line rather than the next
- // line.
+ // positions.
TextAffinity affinity_;
#if DCHECK_IS_ON()
- // TODO(ax-dev): Use layout tree version in place of DOM and style versions.
+ // TODO(nektar): Use layout tree version in place of DOM and style versions.
uint64_t dom_tree_version_;
uint64_t style_version_;
#endif
-
- // For access to our constructor for use when creating empty AX selections.
- // There is no sense in creating empty positions in other circomstances so we
- // disallow it.
- friend class AXSelection;
};
MODULES_EXPORT bool operator==(const AXPosition&, const AXPosition&);
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_position_test.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_position_test.cc
index 7d758cfe2e2..505af19e76f 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_position_test.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_position_test.cc
@@ -11,125 +11,295 @@
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/modules/accessibility/ax_object.h"
#include "third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
namespace blink {
+namespace {
+
+constexpr char kCSSBeforeAndAfter[] = R"HTML(
+ <style>
+ q::before {
+ content: "«";
+ color: blue;
+ }
+ q::after {
+ content: "»";
+ color: red;
+ }
+ </style>
+ <q id="quote">Hello there,</q> she said.
+ )HTML";
+
+constexpr char kHTMLTable[] = R"HTML(
+ <p id="before">Before table.</p>
+ <table id="table" border="1">
+ <thead>
+ <tr id="headerRow">
+ <th id="firstHeaderCell">Number</th>
+ <th>Month</th>
+ <th id="lastHeaderCell">Expenses</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr id="firstRow">
+ <th id="firstCell">1</th>
+ <td>Jan</td>
+ <td>100</td>
+ </tr>
+ <tr>
+ <th>2</th>
+ <td>Feb</td>
+ <td>150</td>
+ </tr>
+ <tr id="lastRow">
+ <th>3</th>
+ <td>Mar</td>
+ <td id="lastCell">200</td>
+ </tr>
+ </tbody>
+ </table>
+ <p id="after">After table.</p>
+ )HTML";
+
+constexpr char kAOM[] = R"HTML(
+ <p id="before">Before virtual AOM node.</p>
+ <div id="aomParent"></div>
+ <p id="after">After virtual AOM node.</p>
+ <script>
+ let parent = document.getElementById("aomParent");
+ let node = new AccessibleNode();
+ node.role = "button";
+ node.label = "Button";
+ parent.accessibleNode.appendChild(node);
+ </script>
+ )HTML";
+
+} // namespace
+
//
// Basic tests.
//
TEST_F(AccessibilityTest, PositionInText) {
- SetBodyInnerHTML(R"HTML(<p id='paragraph'>Hello</p>)HTML");
+ SetBodyInnerHTML(R"HTML(<p id="paragraph">Hello</p>)HTML");
const Node* text = GetElementById("paragraph")->firstChild();
ASSERT_NE(nullptr, text);
+ ASSERT_TRUE(text->IsTextNode());
const AXObject* ax_static_text =
GetAXObjectByElementId("paragraph")->FirstChild();
ASSERT_NE(nullptr, ax_static_text);
ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_static_text->RoleValue());
+
const auto ax_position =
AXPosition::CreatePositionInTextObject(*ax_static_text, 3);
const auto position = ax_position.ToPositionWithAffinity();
EXPECT_EQ(text, position.AnchorNode());
EXPECT_EQ(3, position.GetPosition().OffsetInContainerNode());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+ EXPECT_EQ(nullptr, ax_position_from_dom.ChildAfterTreePosition());
}
// To prevent surprises when comparing equality of two |AXPosition|s, position
// before text object should be the same as position in text object at offset 0.
TEST_F(AccessibilityTest, PositionBeforeText) {
- SetBodyInnerHTML(R"HTML(<p id='paragraph'>Hello</p>)HTML");
+ SetBodyInnerHTML(R"HTML(<p id="paragraph">Hello</p>)HTML");
const Node* text = GetElementById("paragraph")->firstChild();
ASSERT_NE(nullptr, text);
+ ASSERT_TRUE(text->IsTextNode());
const AXObject* ax_static_text =
GetAXObjectByElementId("paragraph")->FirstChild();
ASSERT_NE(nullptr, ax_static_text);
ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_static_text->RoleValue());
+
const auto ax_position =
AXPosition::CreatePositionBeforeObject(*ax_static_text);
const auto position = ax_position.ToPositionWithAffinity();
EXPECT_EQ(text, position.AnchorNode());
EXPECT_EQ(0, position.GetPosition().OffsetInContainerNode());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+ EXPECT_EQ(nullptr, ax_position_from_dom.ChildAfterTreePosition());
}
TEST_F(AccessibilityTest, PositionBeforeTextWithFirstLetterCSSRule) {
SetBodyInnerHTML(
- R"HTML(<style>p ::first-letter { color: red; font-size: 200%; }</style>"
- R"<p id='paragraph'>Hello</p>)HTML");
+ R"HTML(<style>p ::first-letter { color: red; font-size: 200%; }</style>
+ <p id="paragraph">Hello</p>)HTML");
const Node* text = GetElementById("paragraph")->firstChild();
ASSERT_NE(nullptr, text);
+ ASSERT_TRUE(text->IsTextNode());
const AXObject* ax_static_text =
GetAXObjectByElementId("paragraph")->FirstChild();
ASSERT_NE(nullptr, ax_static_text);
ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_static_text->RoleValue());
+
const auto ax_position =
AXPosition::CreatePositionBeforeObject(*ax_static_text);
const auto position = ax_position.ToPositionWithAffinity();
EXPECT_EQ(text, position.AnchorNode());
EXPECT_EQ(0, position.GetPosition().OffsetInContainerNode());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+ EXPECT_EQ(nullptr, ax_position_from_dom.ChildAfterTreePosition());
}
// To prevent surprises when comparing equality of two |AXPosition|s, position
// after text object should be the same as position in text object at offset
// text length.
TEST_F(AccessibilityTest, PositionAfterText) {
- SetBodyInnerHTML(R"HTML(<p id='paragraph'>Hello</p>)HTML");
+ SetBodyInnerHTML(R"HTML(<p id="paragraph">Hello</p>)HTML");
const Node* text = GetElementById("paragraph")->firstChild();
ASSERT_NE(nullptr, text);
+ ASSERT_TRUE(text->IsTextNode());
const AXObject* ax_static_text =
GetAXObjectByElementId("paragraph")->FirstChild();
ASSERT_NE(nullptr, ax_static_text);
ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_static_text->RoleValue());
+
const auto ax_position =
AXPosition::CreatePositionAfterObject(*ax_static_text);
const auto position = ax_position.ToPositionWithAffinity();
EXPECT_EQ(text, position.AnchorNode());
EXPECT_EQ(5, position.GetPosition().OffsetInContainerNode());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+ EXPECT_EQ(nullptr, ax_position_from_dom.ChildAfterTreePosition());
}
TEST_F(AccessibilityTest, PositionBeforeLineBreak) {
- SetBodyInnerHTML(R"HTML(Hello<br id='br'>there)HTML");
+ SetBodyInnerHTML(R"HTML(Hello<br id="br">there)HTML");
const AXObject* ax_br = GetAXObjectByElementId("br");
ASSERT_NE(nullptr, ax_br);
+ ASSERT_EQ(AccessibilityRole::kLineBreakRole, ax_br->RoleValue());
+ const AXObject* ax_div = ax_br->ParentObjectUnignored();
+ ASSERT_NE(nullptr, ax_div);
+ ASSERT_EQ(AccessibilityRole::kGenericContainerRole, ax_div->RoleValue());
+
const auto ax_position = AXPosition::CreatePositionBeforeObject(*ax_br);
+ EXPECT_FALSE(ax_position.IsTextPosition());
+ EXPECT_EQ(ax_div, ax_position.ContainerObject());
+ EXPECT_EQ(1, ax_position.ChildIndex());
+ EXPECT_EQ(ax_br, ax_position.ChildAfterTreePosition());
+
const auto position = ax_position.ToPositionWithAffinity();
EXPECT_EQ(GetDocument().body(), position.AnchorNode());
EXPECT_EQ(1, position.GetPosition().OffsetInContainerNode());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
}
TEST_F(AccessibilityTest, PositionAfterLineBreak) {
- SetBodyInnerHTML(R"HTML(Hello<br id='br'>there)HTML");
+ SetBodyInnerHTML(R"HTML(Hello<br id="br">there)HTML");
const AXObject* ax_br = GetAXObjectByElementId("br");
ASSERT_NE(nullptr, ax_br);
+ ASSERT_EQ(AccessibilityRole::kLineBreakRole, ax_br->RoleValue());
+ const AXObject* ax_div = ax_br->ParentObjectUnignored();
+ ASSERT_NE(nullptr, ax_div);
+ ASSERT_EQ(AccessibilityRole::kGenericContainerRole, ax_div->RoleValue());
+ const AXObject* ax_static_text = GetAXRootObject()->DeepestLastChild();
+ ASSERT_NE(nullptr, ax_static_text);
+ ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_static_text->RoleValue());
+
const auto ax_position = AXPosition::CreatePositionAfterObject(*ax_br);
+ EXPECT_FALSE(ax_position.IsTextPosition());
+ EXPECT_EQ(ax_div, ax_position.ContainerObject());
+ EXPECT_EQ(2, ax_position.ChildIndex());
+ EXPECT_EQ(ax_static_text, ax_position.ChildAfterTreePosition());
+
const auto position = ax_position.ToPositionWithAffinity();
EXPECT_EQ(GetDocument().body(), position.AnchorNode());
EXPECT_EQ(2, position.GetPosition().OffsetInContainerNode());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
}
-TEST_F(AccessibilityTest, FirstPositionInContainerDiv) {
- SetBodyInnerHTML(R"HTML(<div id='div'>Hello<br>there</div>)HTML");
+TEST_F(AccessibilityTest, FirstPositionInDivContainer) {
+ SetBodyInnerHTML(R"HTML(<div id="div">Hello<br>there</div>)HTML");
const Element* div = GetElementById("div");
ASSERT_NE(nullptr, div);
const AXObject* ax_div = GetAXObjectByElementId("div");
ASSERT_NE(nullptr, ax_div);
+ ASSERT_EQ(AccessibilityRole::kGenericContainerRole, ax_div->RoleValue());
+ const AXObject* ax_static_text = GetAXRootObject()->DeepestFirstChild();
+ ASSERT_NE(nullptr, ax_static_text);
+ ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_static_text->RoleValue());
+
const auto ax_position = AXPosition::CreateFirstPositionInObject(*ax_div);
const auto position = ax_position.ToPositionWithAffinity();
EXPECT_EQ(div, position.AnchorNode());
- EXPECT_EQ(0, position.GetPosition().OffsetInContainerNode());
+ EXPECT_TRUE(position.GetPosition().IsBeforeChildren());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+ EXPECT_EQ(ax_static_text, ax_position_from_dom.ChildAfterTreePosition());
}
-TEST_F(AccessibilityTest, LastPositionInContainerDiv) {
- SetBodyInnerHTML(R"HTML(<div id='div'>Hello<br>there</div>)HTML");
+TEST_F(AccessibilityTest, LastPositionInDivContainer) {
+ SetBodyInnerHTML(R"HTML(<div id="div">Hello<br>there</div>
+ <div>Next div</div>)HTML");
const Element* div = GetElementById("div");
ASSERT_NE(nullptr, div);
const AXObject* ax_div = GetAXObjectByElementId("div");
ASSERT_NE(nullptr, ax_div);
+ ASSERT_EQ(AccessibilityRole::kGenericContainerRole, ax_div->RoleValue());
+
const auto ax_position = AXPosition::CreateLastPositionInObject(*ax_div);
const auto position = ax_position.ToPositionWithAffinity();
EXPECT_EQ(div, position.AnchorNode());
EXPECT_TRUE(position.GetPosition().IsAfterChildren());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+ EXPECT_EQ(nullptr, ax_position_from_dom.ChildAfterTreePosition());
}
-TEST_F(AccessibilityTest, PositionFromPosition) {}
+TEST_F(AccessibilityTest, FirstPositionInTextContainer) {
+ SetBodyInnerHTML(R"HTML(<div id="div">Hello</div>)HTML");
+ const Node* text = GetElementById("div")->firstChild();
+ ASSERT_NE(nullptr, text);
+ ASSERT_TRUE(text->IsTextNode());
+ const AXObject* ax_static_text = GetAXObjectByElementId("div")->FirstChild();
+ ASSERT_NE(nullptr, ax_static_text);
+ ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_static_text->RoleValue());
+
+ const auto ax_position =
+ AXPosition::CreateFirstPositionInObject(*ax_static_text);
+ const auto position = ax_position.ToPositionWithAffinity();
+ EXPECT_EQ(text, position.AnchorNode());
+ EXPECT_EQ(0, position.GetPosition().OffsetInContainerNode());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+ EXPECT_EQ(nullptr, ax_position_from_dom.ChildAfterTreePosition());
+}
+
+TEST_F(AccessibilityTest, LastPositionInTextContainer) {
+ SetBodyInnerHTML(R"HTML(<div id="div">Hello</div>)HTML");
+ const Node* text = GetElementById("div")->lastChild();
+ ASSERT_NE(nullptr, text);
+ ASSERT_TRUE(text->IsTextNode());
+ const AXObject* ax_static_text = GetAXObjectByElementId("div")->LastChild();
+ ASSERT_NE(nullptr, ax_static_text);
+ ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_static_text->RoleValue());
+
+ const auto ax_position =
+ AXPosition::CreateLastPositionInObject(*ax_static_text);
+ const auto position = ax_position.ToPositionWithAffinity();
+ EXPECT_EQ(text, position.AnchorNode());
+ EXPECT_EQ(5, position.GetPosition().OffsetInContainerNode());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+ EXPECT_EQ(nullptr, ax_position_from_dom.ChildAfterTreePosition());
+}
//
// Test comparing two AXPosition objects based on their position in the
@@ -137,8 +307,8 @@ TEST_F(AccessibilityTest, PositionFromPosition) {}
//
TEST_F(AccessibilityTest, AXPositionComparisonOperators) {
- SetBodyInnerHTML(R"HTML(<input id='input' type='text' value='value'>"
- R"<p id='paragraph'>hello<br>there</p>)HTML");
+ SetBodyInnerHTML(R"HTML(<input id="input" type="text" value="value">
+ <p id="paragraph">hello<br>there</p>)HTML");
const AXObject* root = GetAXRootObject();
ASSERT_NE(nullptr, root);
@@ -188,6 +358,18 @@ TEST_F(AccessibilityTest, AXPositionComparisonOperators) {
EXPECT_TRUE(paragraph_start < paragraph_end);
}
+TEST_F(AccessibilityTest, AXPositionOperatorBool) {
+ SetBodyInnerHTML(R"HTML(Hello)HTML");
+ const AXObject* root = GetAXRootObject();
+ ASSERT_NE(nullptr, root);
+ const auto root_first = AXPosition::CreateFirstPositionInObject(*root);
+ EXPECT_TRUE(static_cast<bool>(root_first));
+ // The following should create an after children position on the root so it
+ // should be valid.
+ EXPECT_TRUE(static_cast<bool>(root_first.CreateNextPosition()));
+ EXPECT_FALSE(static_cast<bool>(root_first.CreatePreviousPosition()));
+}
+
//
// Test converting to and from visible text with white space.
// The accessibility tree is based on visible text with white space compressed,
@@ -195,33 +377,239 @@ TEST_F(AccessibilityTest, AXPositionComparisonOperators) {
//
TEST_F(AccessibilityTest, PositionInTextWithWhiteSpace) {
- SetBodyInnerHTML(R"HTML(<p id='paragraph'> Hello </p>)HTML");
+ SetBodyInnerHTML(R"HTML(<p id="paragraph"> Hello </p>)HTML");
const Node* text = GetElementById("paragraph")->firstChild();
ASSERT_NE(nullptr, text);
+ ASSERT_TRUE(text->IsTextNode());
const AXObject* ax_static_text =
GetAXObjectByElementId("paragraph")->FirstChild();
ASSERT_NE(nullptr, ax_static_text);
ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_static_text->RoleValue());
+
const auto ax_position =
AXPosition::CreatePositionInTextObject(*ax_static_text, 3);
const auto position = ax_position.ToPositionWithAffinity();
EXPECT_EQ(text, position.AnchorNode());
EXPECT_EQ(8, position.GetPosition().OffsetInContainerNode());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+ EXPECT_EQ(nullptr, ax_position_from_dom.ChildAfterTreePosition());
}
-TEST_F(AccessibilityTest, PositionBeforeTextWithWhiteSpace) {}
+TEST_F(AccessibilityTest, PositionBeforeTextWithWhiteSpace) {
+ SetBodyInnerHTML(R"HTML(<p id="paragraph"> Hello </p>)HTML");
+ const Node* text = GetElementById("paragraph")->firstChild();
+ ASSERT_NE(nullptr, text);
+ ASSERT_TRUE(text->IsTextNode());
+ const AXObject* ax_static_text =
+ GetAXObjectByElementId("paragraph")->FirstChild();
+ ASSERT_NE(nullptr, ax_static_text);
+ ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_static_text->RoleValue());
-TEST_F(AccessibilityTest, PositionAfterTextWithWhiteSpace) {}
+ const auto ax_position =
+ AXPosition::CreatePositionBeforeObject(*ax_static_text);
+ const auto position = ax_position.ToPositionWithAffinity();
+ EXPECT_EQ(text, position.AnchorNode());
+ EXPECT_EQ(5, position.GetPosition().OffsetInContainerNode());
-TEST_F(AccessibilityTest, PositionBeforeLineBreakWithWhiteSpace) {}
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+ EXPECT_EQ(nullptr, ax_position_from_dom.ChildAfterTreePosition());
+}
-TEST_F(AccessibilityTest, PositionAfterLineBreakWithWhiteSpace) {}
+TEST_F(AccessibilityTest, PositionAfterTextWithWhiteSpace) {
+ SetBodyInnerHTML(R"HTML(<p id="paragraph"> Hello </p>)HTML");
+ const Node* text = GetElementById("paragraph")->lastChild();
+ ASSERT_NE(nullptr, text);
+ ASSERT_TRUE(text->IsTextNode());
+ const AXObject* ax_static_text =
+ GetAXObjectByElementId("paragraph")->LastChild();
+ ASSERT_NE(nullptr, ax_static_text);
+ ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_static_text->RoleValue());
+
+ const auto ax_position =
+ AXPosition::CreatePositionAfterObject(*ax_static_text);
+ const auto position = ax_position.ToPositionWithAffinity();
+ EXPECT_EQ(text, position.AnchorNode());
+ EXPECT_EQ(10, position.GetPosition().OffsetInContainerNode());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+ EXPECT_EQ(nullptr, ax_position_from_dom.ChildAfterTreePosition());
+}
-TEST_F(AccessibilityTest, FirstPositionInContainerDivWithWhiteSpace) {}
+TEST_F(AccessibilityTest, PositionBeforeLineBreakWithWhiteSpace) {
+ SetBodyInnerHTML(R"HTML(Hello <br id="br"> there)HTML");
+ const AXObject* ax_br = GetAXObjectByElementId("br");
+ ASSERT_NE(nullptr, ax_br);
+ ASSERT_EQ(AccessibilityRole::kLineBreakRole, ax_br->RoleValue());
+ const AXObject* ax_div = ax_br->ParentObjectUnignored();
+ ASSERT_NE(nullptr, ax_div);
+ ASSERT_EQ(AccessibilityRole::kGenericContainerRole, ax_div->RoleValue());
-TEST_F(AccessibilityTest, LastPositionInContainerDivWithWhiteSpace) {}
+ const auto ax_position = AXPosition::CreatePositionBeforeObject(*ax_br);
+ EXPECT_FALSE(ax_position.IsTextPosition());
+ EXPECT_EQ(ax_div, ax_position.ContainerObject());
+ EXPECT_EQ(1, ax_position.ChildIndex());
+ EXPECT_EQ(ax_br, ax_position.ChildAfterTreePosition());
-TEST_F(AccessibilityTest, PositionFromTextPositionWithWhiteSpace) {}
+ const auto position = ax_position.ToPositionWithAffinity();
+ EXPECT_EQ(GetDocument().body(), position.AnchorNode());
+ EXPECT_EQ(1, position.GetPosition().OffsetInContainerNode());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+}
+
+TEST_F(AccessibilityTest, PositionAfterLineBreakWithWhiteSpace) {
+ SetBodyInnerHTML(R"HTML(Hello <br id="br"> there)HTML");
+ const AXObject* ax_br = GetAXObjectByElementId("br");
+ ASSERT_NE(nullptr, ax_br);
+ ASSERT_EQ(AccessibilityRole::kLineBreakRole, ax_br->RoleValue());
+ const AXObject* ax_div = ax_br->ParentObjectUnignored();
+ ASSERT_NE(nullptr, ax_div);
+ ASSERT_EQ(AccessibilityRole::kGenericContainerRole, ax_div->RoleValue());
+ const AXObject* ax_static_text = GetAXRootObject()->DeepestLastChild();
+ ASSERT_NE(nullptr, ax_static_text);
+ ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_static_text->RoleValue());
+
+ const auto ax_position = AXPosition::CreatePositionAfterObject(*ax_br);
+ EXPECT_FALSE(ax_position.IsTextPosition());
+ EXPECT_EQ(ax_div, ax_position.ContainerObject());
+ EXPECT_EQ(2, ax_position.ChildIndex());
+ EXPECT_EQ(ax_static_text, ax_position.ChildAfterTreePosition());
+
+ const auto position = ax_position.ToPositionWithAffinity();
+ EXPECT_EQ(GetDocument().body(), position.AnchorNode());
+ EXPECT_EQ(2, position.GetPosition().OffsetInContainerNode());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+}
+
+TEST_F(AccessibilityTest, FirstPositionInDivContainerWithWhiteSpace) {
+ SetBodyInnerHTML(R"HTML(<div id="div"> Hello<br>there </div>)HTML");
+ const Element* div = GetElementById("div");
+ ASSERT_NE(nullptr, div);
+ const AXObject* ax_div = GetAXObjectByElementId("div");
+ ASSERT_NE(nullptr, ax_div);
+ ASSERT_EQ(AccessibilityRole::kGenericContainerRole, ax_div->RoleValue());
+ const AXObject* ax_static_text = GetAXRootObject()->DeepestFirstChild();
+ ASSERT_NE(nullptr, ax_static_text);
+ ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_static_text->RoleValue());
+
+ const auto ax_position = AXPosition::CreateFirstPositionInObject(*ax_div);
+ const auto position = ax_position.ToPositionWithAffinity();
+ EXPECT_EQ(div, position.AnchorNode());
+ EXPECT_TRUE(position.GetPosition().IsBeforeChildren());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+ EXPECT_EQ(ax_static_text, ax_position_from_dom.ChildAfterTreePosition());
+}
+
+TEST_F(AccessibilityTest, LastPositionInDivContainerWithWhiteSpace) {
+ SetBodyInnerHTML(R"HTML(<div id="div"> Hello<br>there </div>
+ <div>Next div</div>)HTML");
+ const Element* div = GetElementById("div");
+ ASSERT_NE(nullptr, div);
+ const AXObject* ax_div = GetAXObjectByElementId("div");
+ ASSERT_NE(nullptr, ax_div);
+ ASSERT_EQ(AccessibilityRole::kGenericContainerRole, ax_div->RoleValue());
+
+ const auto ax_position = AXPosition::CreateLastPositionInObject(*ax_div);
+ const auto position = ax_position.ToPositionWithAffinity();
+ EXPECT_EQ(div, position.AnchorNode());
+ EXPECT_TRUE(position.GetPosition().IsAfterChildren());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+ EXPECT_EQ(nullptr, ax_position_from_dom.ChildAfterTreePosition());
+}
+
+TEST_F(AccessibilityTest, FirstPositionInTextContainerWithWhiteSpace) {
+ SetBodyInnerHTML(R"HTML(<div id="div"> Hello </div>)HTML");
+ const Node* text = GetElementById("div")->firstChild();
+ ASSERT_NE(nullptr, text);
+ ASSERT_TRUE(text->IsTextNode());
+ const AXObject* ax_static_text = GetAXObjectByElementId("div")->FirstChild();
+ ASSERT_NE(nullptr, ax_static_text);
+ ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_static_text->RoleValue());
+
+ const auto ax_position =
+ AXPosition::CreateFirstPositionInObject(*ax_static_text);
+ const auto position = ax_position.ToPositionWithAffinity();
+ EXPECT_EQ(text, position.AnchorNode());
+ EXPECT_EQ(5, position.GetPosition().OffsetInContainerNode());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+ EXPECT_EQ(nullptr, ax_position_from_dom.ChildAfterTreePosition());
+}
+
+TEST_F(AccessibilityTest, LastPositionInTextContainerWithWhiteSpace) {
+ SetBodyInnerHTML(R"HTML(<div id="div"> Hello </div>)HTML");
+ const Node* text = GetElementById("div")->lastChild();
+ ASSERT_NE(nullptr, text);
+ ASSERT_TRUE(text->IsTextNode());
+ const AXObject* ax_static_text = GetAXObjectByElementId("div")->LastChild();
+ ASSERT_NE(nullptr, ax_static_text);
+ ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_static_text->RoleValue());
+
+ const auto ax_position =
+ AXPosition::CreateLastPositionInObject(*ax_static_text);
+ const auto position = ax_position.ToPositionWithAffinity();
+ EXPECT_EQ(text, position.AnchorNode());
+ EXPECT_EQ(10, position.GetPosition().OffsetInContainerNode());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+ EXPECT_EQ(nullptr, ax_position_from_dom.ChildAfterTreePosition());
+}
+
+// Test that DOM positions in white space will be collapsed to the first or last
+// valid offset in an |AXPosition|.
+TEST_F(AccessibilityTest, AXPositionFromDOMPositionWithWhiteSpace) {
+ SetBodyInnerHTML(R"HTML(<div id="div"> Hello </div>)HTML");
+ const Node* text = GetElementById("div")->firstChild();
+ ASSERT_NE(nullptr, text);
+ ASSERT_TRUE(text->IsTextNode());
+ ASSERT_EQ(15U, text->textContent().length());
+ const AXObject* ax_static_text = GetAXObjectByElementId("div")->FirstChild();
+ ASSERT_NE(nullptr, ax_static_text);
+ ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_static_text->RoleValue());
+
+ const Position position_at_start(*text, 0);
+ const auto ax_position_at_start = AXPosition::FromPosition(position_at_start);
+ EXPECT_TRUE(ax_position_at_start.IsTextPosition());
+ EXPECT_EQ(ax_static_text, ax_position_at_start.ContainerObject());
+ EXPECT_EQ(0, ax_position_at_start.TextOffset());
+ EXPECT_EQ(nullptr, ax_position_at_start.ChildAfterTreePosition());
+
+ const Position position_after_white_space(*text, 5);
+ const auto ax_position_after_white_space =
+ AXPosition::FromPosition(position_after_white_space);
+ EXPECT_TRUE(ax_position_after_white_space.IsTextPosition());
+ EXPECT_EQ(ax_static_text, ax_position_after_white_space.ContainerObject());
+ EXPECT_EQ(0, ax_position_after_white_space.TextOffset());
+ EXPECT_EQ(nullptr, ax_position_after_white_space.ChildAfterTreePosition());
+
+ const Position position_at_end(*text, 15);
+ const auto ax_position_at_end = AXPosition::FromPosition(position_at_end);
+ EXPECT_TRUE(ax_position_at_end.IsTextPosition());
+ EXPECT_EQ(ax_static_text, ax_position_at_end.ContainerObject());
+ EXPECT_EQ(5, ax_position_at_end.TextOffset());
+ EXPECT_EQ(nullptr, ax_position_at_end.ChildAfterTreePosition());
+
+ const Position position_before_white_space(*text, 10);
+ const auto ax_position_before_white_space =
+ AXPosition::FromPosition(position_before_white_space);
+ EXPECT_TRUE(ax_position_before_white_space.IsTextPosition());
+ EXPECT_EQ(ax_static_text, ax_position_before_white_space.ContainerObject());
+ EXPECT_EQ(5, ax_position_before_white_space.TextOffset());
+ EXPECT_EQ(nullptr, ax_position_before_white_space.ChildAfterTreePosition());
+}
//
// Test affinity.
@@ -265,11 +653,120 @@ TEST_F(AccessibilityTest, PositionInIgnoredObject) {}
// Aria-hidden can cause things in the DOM to be hidden from accessibility.
//
-TEST_F(AccessibilityTest, BeforePositionInARIAHidden) {}
+TEST_F(AccessibilityTest, BeforePositionInARIAHiddenShouldSkipARIAHidden) {
+ SetBodyInnerHTML(R"HTML(
+ <p id="before">Before aria-hidden.</p>
+ <p id="ariaHidden" aria-hidden="true">Aria-hidden.</p>
+ <p id="after">After aria-hidden.</p>
+ )HTML");
+ const Node* after = GetElementById("after");
+ ASSERT_NE(nullptr, after);
+ const AXObject* ax_before = GetAXObjectByElementId("before");
+ ASSERT_NE(nullptr, ax_before);
+ ASSERT_EQ(AccessibilityRole::kParagraphRole, ax_before->RoleValue());
+ const AXObject* ax_after = GetAXObjectByElementId("after");
+ ASSERT_NE(nullptr, ax_after);
+ ASSERT_EQ(AccessibilityRole::kParagraphRole, ax_after->RoleValue());
+ ASSERT_NE(nullptr, GetAXObjectByElementId("ariaHidden"));
+ ASSERT_TRUE(GetAXObjectByElementId("ariaHidden")->AccessibilityIsIgnored());
+
+ const auto ax_position = AXPosition::CreatePositionAfterObject(*ax_before);
+ const auto position = ax_position.ToPositionWithAffinity();
+ EXPECT_EQ(GetDocument().body(), position.AnchorNode());
+ EXPECT_EQ(5, position.GetPosition().OffsetInContainerNode());
+ EXPECT_EQ(after, position.GetPosition().ComputeNodeAfterPosition());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+ EXPECT_EQ(ax_after, ax_position_from_dom.ChildAfterTreePosition());
+}
+
+TEST_F(AccessibilityTest, PreviousPositionAfterARIAHiddenShouldSkipARIAHidden) {
+ SetBodyInnerHTML(R"HTML(
+ <p id="before">Before aria-hidden.</p>
+ <p id="ariaHidden" aria-hidden="true">Aria-hidden.</p>
+ <p id="after">After aria-hidden.</p>
+ )HTML");
+ const Node* before = GetElementById("before");
+ ASSERT_NE(nullptr, before);
+ ASSERT_NE(nullptr, before->firstChild());
+ ASSERT_TRUE(before->firstChild()->IsTextNode());
+ const Node* after = GetElementById("after");
+ ASSERT_NE(nullptr, after);
+ const AXObject* ax_after = GetAXObjectByElementId("after");
+ ASSERT_NE(nullptr, ax_after);
+ ASSERT_EQ(AccessibilityRole::kParagraphRole, ax_after->RoleValue());
+ ASSERT_NE(nullptr, GetAXObjectByElementId("ariaHidden"));
+ ASSERT_TRUE(GetAXObjectByElementId("ariaHidden")->AccessibilityIsIgnored());
+
+ const auto ax_position = AXPosition::CreatePositionBeforeObject(*ax_after);
+ const auto position = ax_position.ToPositionWithAffinity();
+ EXPECT_EQ(GetDocument().body(), position.AnchorNode());
+ EXPECT_EQ(5, position.GetPosition().OffsetInContainerNode());
+ EXPECT_EQ(after, position.GetPosition().ComputeNodeAfterPosition());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+ EXPECT_EQ(ax_after, ax_position_from_dom.ChildAfterTreePosition());
+
+ const auto ax_position_previous = ax_position.CreatePreviousPosition();
+ const auto position_previous = ax_position_previous.ToPositionWithAffinity();
+ EXPECT_EQ(before->firstChild(), position_previous.AnchorNode());
+ EXPECT_EQ(19, position_previous.GetPosition().OffsetInContainerNode());
+ EXPECT_EQ(nullptr,
+ position_previous.GetPosition().ComputeNodeAfterPosition());
-TEST_F(AccessibilityTest, AfterPositionInARIAHidden) {}
+ const auto ax_position_previous_from_dom =
+ AXPosition::FromPosition(position_previous);
+ EXPECT_EQ(ax_position_previous, ax_position_previous_from_dom);
+ EXPECT_EQ(nullptr, ax_position_previous_from_dom.ChildAfterTreePosition());
+}
+
+TEST_F(AccessibilityTest, DISABLED_FromPositionInARIAHidden) {
+ SetBodyInnerHTML(R"HTML(
+ <p id="before">Before aria-hidden.</p>
+ <p id="ariaHidden" aria-hidden="true">Aria-hidden.</p>
+ <p id="after">After aria-hidden.</p>
+ )HTML");
+ const Node* hidden = GetElementById("ariaHidden");
+ ASSERT_NE(nullptr, hidden);
+ const Node* text = hidden->firstChild();
+ ASSERT_NE(nullptr, text);
+ ASSERT_TRUE(text->IsTextNode());
+ const AXObject* ax_root = GetAXRootObject();
+ ASSERT_NE(nullptr, ax_root);
+ ASSERT_EQ(AccessibilityRole::kWebAreaRole, ax_root->RoleValue());
+ ASSERT_EQ(2, ax_root->ChildCount());
+ const AXObject* ax_after = GetAXObjectByElementId("after");
+ ASSERT_NE(nullptr, ax_after);
+ ASSERT_EQ(AccessibilityRole::kParagraphRole, ax_after->RoleValue());
+ ASSERT_NE(nullptr, GetAXObjectByElementId("ariaHidden"));
+ ASSERT_TRUE(GetAXObjectByElementId("ariaHidden")->AccessibilityIsIgnored());
+
+ const auto position_first = Position::FirstPositionInNode(*hidden);
+ const auto position_last = Position::LastPositionInNode(*hidden);
+ const auto position_before = Position::BeforeNode(*hidden);
+ const auto position_after = Position::AfterNode(*hidden);
+ const auto position_text = Position::EditingPositionOf(text, 3);
+ const auto positions = {position_first, position_last, position_before,
+ position_after, position_text};
-TEST_F(AccessibilityTest, FromPositionInARIAHidden) {}
+ for (const auto& position : positions) {
+ const auto ax_position_left = AXPosition::FromPosition(position);
+ EXPECT_TRUE(ax_position_left.IsValid());
+ EXPECT_FALSE(ax_position_left.IsTextPosition());
+ EXPECT_EQ(ax_root, ax_position_left.ContainerObject());
+ EXPECT_EQ(1, ax_position_left.ChildIndex());
+ EXPECT_EQ(ax_after, ax_position_left.ChildAfterTreePosition());
+
+ const auto ax_position_right = AXPosition::FromPosition(position);
+ EXPECT_TRUE(ax_position_right.IsValid());
+ EXPECT_FALSE(ax_position_right.IsTextPosition());
+ EXPECT_EQ(ax_root, ax_position_left.ContainerObject());
+ EXPECT_EQ(2, ax_position_left.ChildIndex());
+ EXPECT_EQ(nullptr, ax_position_left.ChildAfterTreePosition());
+ }
+}
//
// Canvas fallback can cause things to be in the accessibility tree that are not
@@ -279,21 +776,347 @@ TEST_F(AccessibilityTest, FromPositionInARIAHidden) {}
TEST_F(AccessibilityTest, PositionInCanvas) {}
//
-// Some layout objects, e.g. list bullets and CSS::before/after content, appears
-// in the accessibility tree but is not present in the DOM.
+// Some layout objects, e.g. list bullets and CSS::before/after content, appear
+// in the accessibility tree but are not present in the DOM.
//
-TEST_F(AccessibilityTest, PositionBeforeListBullet) {}
+TEST_F(AccessibilityTest, DISABLED_PositionBeforeListMarker) {
+ SetBodyInnerHTML(R"HTML(
+ <ul id="list">
+ <li id="listItem">Item.</li>
+ </ul>
+ )HTML");
+ const Node* list = GetElementById("list");
+ ASSERT_NE(nullptr, list);
+ const Node* item = GetElementById("listItem");
+ ASSERT_NE(nullptr, item);
+ const Node* text = item->firstChild();
+ ASSERT_NE(nullptr, text);
+ ASSERT_TRUE(text->IsTextNode());
+ const AXObject* ax_item = GetAXObjectByElementId("listItem");
+ ASSERT_NE(nullptr, ax_item);
+ ASSERT_EQ(AccessibilityRole::kListItemRole, ax_item->RoleValue());
+ ASSERT_EQ(2, ax_item->ChildCount());
+ const AXObject* ax_marker = ax_item->FirstChild();
+ ASSERT_NE(nullptr, ax_marker);
+ ASSERT_EQ(AccessibilityRole::kListMarkerRole, ax_marker->RoleValue());
+
+ const auto ax_position_1 = AXPosition::CreateFirstPositionInObject(*ax_item);
+ const auto position_1 = ax_position_1.ToPositionWithAffinity(
+ AXPositionAdjustmentBehavior::kMoveLeft);
+ EXPECT_EQ(list, position_1.AnchorNode());
+ EXPECT_TRUE(position_1.GetPosition().IsBeforeChildren());
+ EXPECT_EQ(item, position_1.GetPosition().ComputeNodeAfterPosition());
-TEST_F(AccessibilityTest, PositionAfterListBullet) {}
+ const auto ax_position_from_dom_1 = AXPosition::FromPosition(position_1);
+ EXPECT_EQ(ax_position_1, ax_position_from_dom_1);
+ EXPECT_EQ(ax_marker, ax_position_from_dom_1.ChildAfterTreePosition());
-TEST_F(AccessibilityTest, PositionInCSSContent) {}
+ const auto ax_position_2 = AXPosition::CreatePositionBeforeObject(*ax_marker);
+ const auto position_2 = ax_position_2.ToPositionWithAffinity(
+ AXPositionAdjustmentBehavior::kMoveLeft);
+ EXPECT_EQ(list, position_2.AnchorNode());
+ EXPECT_TRUE(position_2.GetPosition().IsBeforeChildren());
+ EXPECT_EQ(item, position_2.GetPosition().ComputeNodeAfterPosition());
+
+ const auto ax_position_from_dom_2 = AXPosition::FromPosition(position_2);
+ EXPECT_EQ(ax_position_2, ax_position_from_dom_2);
+ EXPECT_EQ(ax_marker, ax_position_from_dom_2.ChildAfterTreePosition());
+
+ const auto position_3 = ax_position_1.ToPositionWithAffinity(
+ AXPositionAdjustmentBehavior::kMoveRight);
+ EXPECT_EQ(list, position_3.AnchorNode());
+ EXPECT_TRUE(position_3.GetPosition().IsBeforeChildren());
+ EXPECT_EQ(item, position_3.GetPosition().ComputeNodeAfterPosition());
+
+ const auto ax_position_from_dom_3 = AXPosition::FromPosition(position_3);
+ EXPECT_EQ(ax_position_1, ax_position_from_dom_3);
+ EXPECT_EQ(ax_marker, ax_position_from_dom_3.ChildAfterTreePosition());
+
+ const auto position_4 = ax_position_2.ToPositionWithAffinity(
+ AXPositionAdjustmentBehavior::kMoveRight);
+ EXPECT_EQ(list, position_4.AnchorNode());
+ EXPECT_TRUE(position_4.GetPosition().IsBeforeChildren());
+ EXPECT_EQ(item, position_4.GetPosition().ComputeNodeAfterPosition());
+
+ const auto ax_position_from_dom_4 = AXPosition::FromPosition(position_4);
+ EXPECT_EQ(ax_position_2, ax_position_from_dom_4);
+ EXPECT_EQ(ax_marker, ax_position_from_dom_4.ChildAfterTreePosition());
+}
+
+TEST_F(AccessibilityTest, PositionAfterListMarker) {
+ SetBodyInnerHTML(R"HTML(
+ <ol>
+ <li id="listItem">Item.</li>
+ </ol>
+ )HTML");
+ const Node* item = GetElementById("listItem");
+ ASSERT_NE(nullptr, item);
+ const Node* text = item->firstChild();
+ ASSERT_NE(nullptr, text);
+ ASSERT_TRUE(text->IsTextNode());
+ const AXObject* ax_item = GetAXObjectByElementId("listItem");
+ ASSERT_NE(nullptr, ax_item);
+ ASSERT_EQ(AccessibilityRole::kListItemRole, ax_item->RoleValue());
+ ASSERT_EQ(2, ax_item->ChildCount());
+ const AXObject* ax_marker = ax_item->FirstChild();
+ ASSERT_NE(nullptr, ax_marker);
+ ASSERT_EQ(AccessibilityRole::kListMarkerRole, ax_marker->RoleValue());
+ const AXObject* ax_text = ax_item->LastChild();
+ ASSERT_NE(nullptr, ax_text);
+ ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_text->RoleValue());
+
+ const auto ax_position = AXPosition::CreatePositionAfterObject(*ax_marker);
+ const auto position = ax_position.ToPositionWithAffinity();
+ EXPECT_EQ(item, position.AnchorNode());
+ EXPECT_EQ(0, position.GetPosition().OffsetInContainerNode());
+ EXPECT_EQ(text, position.GetPosition().ComputeNodeAfterPosition());
+
+ const auto ax_position_from_dom = AXPosition::FromPosition(position);
+ EXPECT_EQ(ax_position, ax_position_from_dom);
+ EXPECT_EQ(ax_text, ax_position_from_dom.ChildAfterTreePosition());
+}
+
+TEST_F(AccessibilityTest, PositionInCSSContent) {
+ SetBodyInnerHTML(kCSSBeforeAndAfter);
+
+ const Node* quote = GetElementById("quote");
+ ASSERT_NE(nullptr, quote);
+ // CSS text nodes are not in the DOM tree.
+ const Node* text = quote->firstChild();
+ ASSERT_NE(nullptr, text);
+ ASSERT_FALSE(text->IsPseudoElement());
+ ASSERT_TRUE(text->IsTextNode());
+
+ const AXObject* ax_quote = GetAXObjectByElementId("quote");
+ ASSERT_NE(nullptr, ax_quote);
+ ASSERT_EQ(AccessibilityRole::kGenericContainerRole, ax_quote->RoleValue());
+ ASSERT_EQ(3, ax_quote->ChildCount());
+ const AXObject* ax_css_before = ax_quote->FirstChild();
+ ASSERT_NE(nullptr, ax_css_before);
+ ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_css_before->RoleValue());
+ const AXObject* ax_text = *(ax_quote->Children().begin() + 1);
+ ASSERT_NE(nullptr, ax_text);
+ ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_text->RoleValue());
+ const AXObject* ax_css_after = ax_quote->LastChild();
+ ASSERT_NE(nullptr, ax_css_after);
+ ASSERT_EQ(AccessibilityRole::kStaticTextRole, ax_css_after->RoleValue());
+
+ const auto ax_position_before =
+ AXPosition::CreateFirstPositionInObject(*ax_css_before);
+ EXPECT_TRUE(ax_position_before.IsTextPosition());
+ EXPECT_EQ(0, ax_position_before.TextOffset());
+ EXPECT_EQ(nullptr, ax_position_before.ChildAfterTreePosition());
+ const auto position_before = ax_position_before.ToPositionWithAffinity(
+ AXPositionAdjustmentBehavior::kMoveRight);
+ EXPECT_EQ(text, position_before.AnchorNode());
+ EXPECT_EQ(0, position_before.GetPosition().OffsetInContainerNode());
+
+ const auto ax_position_after =
+ AXPosition::CreateLastPositionInObject(*ax_css_after);
+ EXPECT_TRUE(ax_position_after.IsTextPosition());
+ EXPECT_EQ(2, ax_position_after.TextOffset());
+ EXPECT_EQ(nullptr, ax_position_after.ChildAfterTreePosition());
+ const auto position_after = ax_position_after.ToPositionWithAffinity(
+ AXPositionAdjustmentBehavior::kMoveLeft);
+ EXPECT_EQ(text, position_after.AnchorNode());
+ EXPECT_EQ(12, position_after.GetPosition().OffsetInContainerNode());
+}
//
// Objects deriving from |AXMockObject|, e.g. table columns, are in the
// accessibility tree but are neither in the DOM or layout trees.
+// Same for virtual nodes created using the Accessibility Object Model (AOM).
//
-TEST_F(AccessibilityTest, PositionInTableColumn) {}
+TEST_F(AccessibilityTest, PositionBeforeAndAfterTable) {
+ SetBodyInnerHTML(kHTMLTable);
+ const Node* after = GetElementById("after");
+ ASSERT_NE(nullptr, after);
+ const AXObject* ax_table = GetAXObjectByElementId("table");
+ ASSERT_NE(nullptr, ax_table);
+ ASSERT_EQ(AccessibilityRole::kTableRole, ax_table->RoleValue());
+ const AXObject* ax_after = GetAXObjectByElementId("after");
+ ASSERT_NE(nullptr, ax_after);
+ ASSERT_EQ(AccessibilityRole::kParagraphRole, ax_after->RoleValue());
+
+ const auto ax_position_before =
+ AXPosition::CreatePositionBeforeObject(*ax_table);
+ const auto position_before = ax_position_before.ToPositionWithAffinity();
+ EXPECT_EQ(GetDocument().body(), position_before.AnchorNode());
+ EXPECT_EQ(3, position_before.GetPosition().OffsetInContainerNode());
+ const Node* table = position_before.GetPosition().ComputeNodeAfterPosition();
+ ASSERT_NE(nullptr, table);
+ EXPECT_EQ(GetElementById("table"), table);
+
+ const auto ax_position_before_from_dom =
+ AXPosition::FromPosition(position_before);
+ EXPECT_EQ(ax_position_before, ax_position_before_from_dom);
+
+ const auto ax_position_after =
+ AXPosition::CreatePositionAfterObject(*ax_table);
+ const auto position_after = ax_position_after.ToPositionWithAffinity();
+ EXPECT_EQ(GetDocument().body(), position_after.AnchorNode());
+ EXPECT_EQ(5, position_after.GetPosition().OffsetInContainerNode());
+ const Node* node_after =
+ position_after.GetPosition().ComputeNodeAfterPosition();
+ EXPECT_EQ(after, node_after);
+
+ const auto ax_position_after_from_dom =
+ AXPosition::FromPosition(position_after);
+ EXPECT_EQ(ax_position_after, ax_position_after_from_dom);
+ EXPECT_EQ(ax_after, ax_position_after_from_dom.ChildAfterTreePosition());
+}
+
+TEST_F(AccessibilityTest, PositionAtStartAndEndOfTable) {
+ SetBodyInnerHTML(kHTMLTable);
+ const Node* table = GetElementById("table");
+ ASSERT_NE(nullptr, table);
+ const Node* last_cell = GetElementById("lastCell");
+ ASSERT_NE(nullptr, last_cell);
+ const Node* last_cell_text = last_cell->firstChild();
+ ASSERT_NE(nullptr, last_cell_text);
+ ASSERT_TRUE(last_cell_text->IsTextNode());
+ const AXObject* ax_table = GetAXObjectByElementId("table");
+ ASSERT_NE(nullptr, ax_table);
+ ASSERT_EQ(AccessibilityRole::kTableRole, ax_table->RoleValue());
+
+ const auto ax_position_at_start =
+ AXPosition::CreateFirstPositionInObject(*ax_table);
+ const auto position_at_start = ax_position_at_start.ToPositionWithAffinity();
+ EXPECT_EQ(table, position_at_start.AnchorNode());
+ EXPECT_TRUE(position_at_start.GetPosition().IsBeforeChildren());
+
+ const auto ax_position_at_start_from_dom =
+ AXPosition::FromPosition(position_at_start);
+ EXPECT_EQ(ax_position_at_start, ax_position_at_start_from_dom);
+
+ const auto ax_position_at_end =
+ AXPosition::CreateLastPositionInObject(*ax_table);
+ const auto position_at_end = ax_position_at_end.ToPositionWithAffinity();
+ EXPECT_EQ(table, position_at_end.AnchorNode());
+ EXPECT_TRUE(position_at_end.GetPosition().IsAfterChildren());
+
+ const auto ax_position_at_end_from_dom =
+ AXPosition::FromPosition(position_at_end);
+ EXPECT_EQ(ax_position_at_end.AsValidDOMPosition(),
+ ax_position_at_end_from_dom);
+ EXPECT_EQ(nullptr, ax_position_at_end_from_dom.ChildAfterTreePosition());
+}
+
+TEST_F(AccessibilityTest, PositionInTableHeader) {
+ SetBodyInnerHTML(kHTMLTable);
+ const Node* header_row = GetElementById("headerRow");
+ ASSERT_NE(nullptr, header_row);
+ const AXObject* ax_first_header_cell =
+ GetAXObjectByElementId("firstHeaderCell");
+ ASSERT_NE(nullptr, ax_first_header_cell);
+ ASSERT_EQ(AccessibilityRole::kColumnHeaderRole,
+ ax_first_header_cell->RoleValue());
+ const AXObject* ax_last_header_cell =
+ GetAXObjectByElementId("lastHeaderCell");
+ ASSERT_NE(nullptr, ax_last_header_cell);
+ ASSERT_EQ(AccessibilityRole::kColumnHeaderRole,
+ ax_last_header_cell->RoleValue());
+
+ const auto ax_position_before =
+ AXPosition::CreatePositionBeforeObject(*ax_first_header_cell);
+ const auto position_before = ax_position_before.ToPositionWithAffinity();
+ EXPECT_EQ(header_row, position_before.AnchorNode());
+ EXPECT_TRUE(position_before.GetPosition().IsBeforeChildren());
+
+ const auto ax_position_before_from_dom =
+ AXPosition::FromPosition(position_before);
+ EXPECT_EQ(ax_position_before, ax_position_before_from_dom);
+
+ const auto ax_position_after =
+ AXPosition::CreatePositionAfterObject(*ax_last_header_cell);
+ const auto position_after = ax_position_after.ToPositionWithAffinity();
+ EXPECT_EQ(header_row, position_after.AnchorNode());
+ EXPECT_TRUE(position_after.GetPosition().IsAfterChildren());
+ EXPECT_EQ(nullptr, position_after.GetPosition().ComputeNodeAfterPosition());
+
+ const auto ax_position_after_from_dom =
+ AXPosition::FromPosition(position_after);
+ EXPECT_EQ(ax_position_after, ax_position_after_from_dom);
+}
+
+TEST_F(AccessibilityTest, PositionInTableRow) {
+ SetBodyInnerHTML(kHTMLTable);
+ const Node* first_row = GetElementById("firstRow");
+ ASSERT_NE(nullptr, first_row);
+ const Node* last_row = GetElementById("lastRow");
+ ASSERT_NE(nullptr, last_row);
+ const AXObject* ax_first_cell = GetAXObjectByElementId("firstCell");
+ ASSERT_NE(nullptr, ax_first_cell);
+ ASSERT_EQ(AccessibilityRole::kRowHeaderRole, ax_first_cell->RoleValue());
+ const AXObject* ax_last_cell = GetAXObjectByElementId("lastCell");
+ ASSERT_NE(nullptr, ax_last_cell);
+ ASSERT_EQ(AccessibilityRole::kCellRole, ax_last_cell->RoleValue());
+
+ const auto ax_position_before =
+ AXPosition::CreatePositionBeforeObject(*ax_first_cell);
+ const auto position_before = ax_position_before.ToPositionWithAffinity();
+ EXPECT_EQ(first_row, position_before.AnchorNode());
+ EXPECT_TRUE(position_before.GetPosition().IsBeforeChildren());
+
+ const auto ax_position_before_from_dom =
+ AXPosition::FromPosition(position_before);
+ EXPECT_EQ(ax_position_before, ax_position_before_from_dom);
+
+ const auto ax_position_after =
+ AXPosition::CreatePositionAfterObject(*ax_last_cell);
+ const auto position_after = ax_position_after.ToPositionWithAffinity();
+ EXPECT_EQ(last_row, position_after.AnchorNode());
+ EXPECT_TRUE(position_after.GetPosition().IsAfterChildren());
+ EXPECT_EQ(nullptr, position_after.GetPosition().ComputeNodeAfterPosition());
+
+ const auto ax_position_after_from_dom =
+ AXPosition::FromPosition(position_after);
+ EXPECT_EQ(ax_position_after, ax_position_after_from_dom);
+}
+
+TEST_F(AccessibilityTest, DISABLED_PositionInVirtualAOMNode) {
+ ScopedAccessibilityObjectModelForTest(true);
+ SetBodyInnerHTML(kAOM);
+ const Node* parent = GetElementById("aomParent");
+ ASSERT_NE(nullptr, parent);
+ const Node* after = GetElementById("after");
+ ASSERT_NE(nullptr, after);
+ const AXObject* ax_parent = GetAXObjectByElementId("aomParent");
+ ASSERT_NE(nullptr, ax_parent);
+ ASSERT_EQ(AccessibilityRole::kGenericContainerRole, ax_parent->RoleValue());
+ ASSERT_EQ(1, ax_parent->ChildCount());
+ const AXObject* ax_button = ax_parent->FirstChild();
+ ASSERT_NE(nullptr, ax_button);
+ ASSERT_EQ(AccessibilityRole::kButtonRole, ax_button->RoleValue());
+ const AXObject* ax_after = GetAXObjectByElementId("after");
+ ASSERT_NE(nullptr, ax_after);
+ ASSERT_EQ(AccessibilityRole::kParagraphRole, ax_after->RoleValue());
+
+ const auto ax_position_before =
+ AXPosition::CreatePositionBeforeObject(*ax_button);
+ const auto position_before = ax_position_before.ToPositionWithAffinity();
+ EXPECT_EQ(parent, position_before.AnchorNode());
+ EXPECT_TRUE(position_before.GetPosition().IsBeforeChildren());
+ EXPECT_EQ(nullptr, position_before.GetPosition().ComputeNodeAfterPosition());
+
+ const auto ax_position_before_from_dom =
+ AXPosition::FromPosition(position_before);
+ EXPECT_EQ(ax_position_before, ax_position_before_from_dom);
+ EXPECT_EQ(ax_button, ax_position_before_from_dom.ChildAfterTreePosition());
+
+ const auto ax_position_after =
+ AXPosition::CreatePositionAfterObject(*ax_button);
+ const auto position_after = ax_position_after.ToPositionWithAffinity();
+ EXPECT_EQ(after, position_after.AnchorNode());
+ EXPECT_TRUE(position_after.GetPosition().IsBeforeChildren());
+ EXPECT_EQ(nullptr, position_after.GetPosition().ComputeNodeAfterPosition());
+
+ const auto ax_position_after_from_dom =
+ AXPosition::FromPosition(position_after);
+ EXPECT_EQ(ax_position_after, ax_position_after_from_dom);
+ EXPECT_EQ(ax_after, ax_position_after_from_dom.ChildAfterTreePosition());
+}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_progress_indicator.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_progress_indicator.cc
index 9f6c5deb870..00c46041ab5 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_progress_indicator.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_progress_indicator.cc
@@ -20,7 +20,7 @@
#include "third_party/blink/renderer/modules/accessibility/ax_progress_indicator.h"
-#include "third_party/blink/renderer/core/dom/accessible_node.h"
+#include "third_party/blink/renderer/core/aom/accessible_node.h"
#include "third_party/blink/renderer/core/html/html_progress_element.h"
#include "third_party/blink/renderer/core/layout/layout_progress.h"
#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_radio_input.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_radio_input.cc
index 75da9d1bf5b..93a91192e75 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_radio_input.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_radio_input.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/modules/accessibility/ax_radio_input.h"
-#include "third_party/blink/renderer/core/dom/accessible_node.h"
+#include "third_party/blink/renderer/core/aom/accessible_node.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/forms/radio_input_type.h"
#include "third_party/blink/renderer/core/input_type_names.h"
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_range.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_range.cc
index 98f836a7950..2e71132ef3e 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_range.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_range.cc
@@ -10,16 +10,21 @@
namespace blink {
AXRange::AXRange(const AXPosition& start, const AXPosition& end)
- : start_(start), end_(end) {
- DCHECK(start.IsValid());
- DCHECK(end.IsValid());
- DCHECK_LE(start, end);
+ : start_(), end_() {
+ if (!start.IsValid() || !end.IsValid() || start > end)
+ return;
const Document* document = start.ContainerObject()->GetDocument();
DCHECK(document);
DCHECK(document->IsActive());
DCHECK(!document->NeedsLayoutTreeUpdate());
- DCHECK_EQ(end.ContainerObject()->GetDocument(), document);
+ // We don't support ranges that span across documents.
+ if (end.ContainerObject()->GetDocument() != document)
+ return;
+
+ start_ = start;
+ end_ = end;
+
#if DCHECK_IS_ON()
dom_tree_version_ = document->DomTreeVersion();
style_version_ = document->StyleVersion();
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc
index a7a4bb9797b..74902bd58c3 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc
@@ -1,30 +1,6 @@
-/*
- * Copyright (C) 2017, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
#include "third_party/blink/renderer/modules/accessibility/ax_relation_cache.h"
@@ -55,13 +31,9 @@ void AXRelationCache::UpdateReverseRelations(const AXObject* relation_source,
// Add entries to reverse map.
for (const String& target_id : target_ids) {
- HashSet<AXID>* source_axids = id_attr_to_related_mapping_.at(target_id);
- if (!source_axids) {
- source_axids = new HashSet<AXID>();
- id_attr_to_related_mapping_.Set(target_id,
- base::WrapUnique(source_axids));
- }
- source_axids->insert(relation_source_axid);
+ auto result =
+ id_attr_to_related_mapping_.insert(target_id, HashSet<AXID>());
+ result.stored_value->value.insert(relation_source_axid);
}
}
@@ -207,12 +179,11 @@ void AXRelationCache::GetReverseRelated(
if (!element->HasID())
return;
- String id = element->GetIdAttribute();
- HashSet<AXID>* source_axids = id_attr_to_related_mapping_.at(id);
- if (!source_axids)
+ auto it = id_attr_to_related_mapping_.find(element->GetIdAttribute());
+ if (it == id_attr_to_related_mapping_.end())
return;
- for (const auto& source_axid : *source_axids) {
+ for (const auto& source_axid : it->value) {
AXObject* source_object = ObjectFromAXID(source_axid);
if (source_object)
source_objects.push_back(source_object);
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_relation_cache.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_relation_cache.h
index d11cf08a48f..6c3af3d9bc4 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_relation_cache.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_relation_cache.h
@@ -1,30 +1,6 @@
-/*
- * Copyright (C) 2017, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_RELATION_CACHE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_RELATION_CACHE_H_
@@ -109,7 +85,7 @@ class AXRelationCache {
// quickly determine if it affects an aria-owns relationship.
// - When text changes, we can recompute any label or description based on it
// and fire the appropriate change events.
- HashMap<String, std::unique_ptr<HashSet<AXID>>> id_attr_to_related_mapping_;
+ HashMap<String, HashSet<AXID>> id_attr_to_related_mapping_;
// Helpers that call back into object cache
AXObject* ObjectFromAXID(AXID) const;
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_selection.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_selection.cc
index db371325c9b..1446e00a430 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_selection.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_selection.cc
@@ -60,6 +60,10 @@ const AXSelection AXSelection::Builder::Build() {
DCHECK(document);
DCHECK(document->IsActive());
DCHECK(!document->NeedsLayoutTreeUpdate());
+ // We don't support selections that span across documents.
+ if (selection_.Extent().ContainerObject()->GetDocument() != document)
+ return {};
+
#if DCHECK_IS_ON()
selection_.dom_tree_version_ = document->DomTreeVersion();
selection_.style_version_ = document->StyleVersion();
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_selection.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_selection.h
index 32275e25057..122c4e0071f 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_selection.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_selection.h
@@ -42,6 +42,8 @@ class MODULES_EXPORT AXSelection final {
// invalid, or if the positions are in two separate documents.
bool IsValid() const;
+ operator bool() const { return IsValid(); }
+
const SelectionInDOMTree AsSelection(
const AXSelectionBehavior =
AXSelectionBehavior::kExtendToValidDOMRange) const;
@@ -60,7 +62,8 @@ class MODULES_EXPORT AXSelection final {
AXPosition extent_;
#if DCHECK_IS_ON()
- // TODO(ax-dev): Use layout tree version in place of DOM and style versions.
+ // TODO(accessibility): Use layout tree version in place of DOM and style
+ // versions.
uint64_t dom_tree_version_;
uint64_t style_version_;
#endif
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
index d7e0c8b239b..8d23a21457b 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
@@ -10,7 +10,7 @@
#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/modules/accessibility/ax_object.h"
#include "third_party/blink/renderer/modules/accessibility/ax_position.h"
-#include "third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h"
+#include "third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.h"
namespace blink {
@@ -18,13 +18,15 @@ namespace blink {
// Basic tests.
//
-TEST_F(AccessibilityTest, SetSelectionInText) {
+TEST_F(AccessibilitySelectionTest, SetSelectionInText) {
SetBodyInnerHTML(R"HTML(<p id='paragraph'>Hello</p>)HTML");
const Node* text = GetElementById("paragraph")->firstChild();
ASSERT_NE(nullptr, text);
+ ASSERT_TRUE(text->IsTextNode());
const AXObject* ax_static_text =
GetAXObjectByElementId("paragraph")->FirstChild();
ASSERT_NE(nullptr, ax_static_text);
+
const auto ax_base =
AXPosition::CreatePositionInTextObject(*ax_static_text, 3);
const auto ax_extent = AXPosition::CreatePositionAfterObject(*ax_static_text);
@@ -37,15 +39,19 @@ TEST_F(AccessibilityTest, SetSelectionInText) {
EXPECT_EQ(3, dom_selection.Base().OffsetInContainerNode());
EXPECT_EQ(text, dom_selection.Extent().AnchorNode());
EXPECT_EQ(5, dom_selection.Extent().OffsetInContainerNode());
+ EXPECT_EQ("<Paragraph: ><StaticText: Hel^lo|>",
+ GetSelectionText(ax_selection));
}
-TEST_F(AccessibilityTest, SetSelectionInTextWithWhiteSpace) {
+TEST_F(AccessibilitySelectionTest, SetSelectionInTextWithWhiteSpace) {
SetBodyInnerHTML(R"HTML(<p id='paragraph'> Hello</p>)HTML");
const Node* text = GetElementById("paragraph")->firstChild();
ASSERT_NE(nullptr, text);
+ ASSERT_TRUE(text->IsTextNode());
const AXObject* ax_static_text =
GetAXObjectByElementId("paragraph")->FirstChild();
ASSERT_NE(nullptr, ax_static_text);
+
const auto ax_base =
AXPosition::CreatePositionInTextObject(*ax_static_text, 3);
const auto ax_extent = AXPosition::CreatePositionAfterObject(*ax_static_text);
@@ -58,6 +64,8 @@ TEST_F(AccessibilityTest, SetSelectionInTextWithWhiteSpace) {
EXPECT_EQ(8, dom_selection.Base().OffsetInContainerNode());
EXPECT_EQ(text, dom_selection.Extent().AnchorNode());
EXPECT_EQ(10, dom_selection.Extent().OffsetInContainerNode());
+ EXPECT_EQ("<Paragraph: ><StaticText: Hel^lo|>",
+ GetSelectionText(ax_selection));
}
//
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.h
index 7df90b88022..f6bc6567055 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.h
@@ -5,8 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_SPARSE_ATTRIBUTE_SETTER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_SPARSE_ATTRIBUTE_SETTER_H_
-#include "third_party/blink/renderer/core/dom/accessible_node.h"
-#include "third_party/blink/renderer/core/dom/accessible_node_list.h"
+#include "third_party/blink/renderer/core/aom/accessible_node.h"
+#include "third_party/blink/renderer/core/aom/accessible_node_list.h"
#include "third_party/blink/renderer/modules/accessibility/ax_object.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_table.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_table.cc
deleted file mode 100644
index 1639db07c21..00000000000
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_table.cc
+++ /dev/null
@@ -1,599 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/modules/accessibility/ax_table.h"
-
-#include "third_party/blink/renderer/core/dom/accessible_node.h"
-#include "third_party/blink/renderer/core/dom/element_traversal.h"
-#include "third_party/blink/renderer/core/editing/editing_utilities.h"
-#include "third_party/blink/renderer/core/html/html_collection.h"
-#include "third_party/blink/renderer/core/html/html_table_caption_element.h"
-#include "third_party/blink/renderer/core/html/html_table_cell_element.h"
-#include "third_party/blink/renderer/core/html/html_table_col_element.h"
-#include "third_party/blink/renderer/core/html/html_table_element.h"
-#include "third_party/blink/renderer/core/html/html_table_row_element.h"
-#include "third_party/blink/renderer/core/html/html_table_rows_collection.h"
-#include "third_party/blink/renderer/core/html/html_table_section_element.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table_cell.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table_column.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table_row.h"
-
-namespace blink {
-
-using namespace HTMLNames;
-
-AXTable::AXTable(LayoutObject* layout_object,
- AXObjectCacheImpl& ax_object_cache)
- : AXLayoutObject(layout_object, ax_object_cache),
- header_container_(nullptr),
- is_ax_table_(true) {}
-
-AXTable::~AXTable() = default;
-
-void AXTable::Init() {
- AXLayoutObject::Init();
- // Can it be exposed with any kind of table structure / interface?
- is_ax_table_ = IsTableExposableThroughAccessibility();
- // Data tables are a subset of AX Tables. The rest are layout tables.
- is_data_table_ = is_ax_table_ && ComputeIsDataTable();
-}
-
-AXTable* AXTable::Create(LayoutObject* layout_object,
- AXObjectCacheImpl& ax_object_cache) {
- return new AXTable(layout_object, ax_object_cache);
-}
-
-bool AXTable::IsAXTable() const {
- return layout_object_ && is_ax_table_;
-}
-
-static AccessibilityRole AriaRole(const Element* element) {
- if (!element)
- return kUnknownRole;
-
- const AtomicString& aria_role = element->FastGetAttribute(roleAttr);
- if (aria_role.IsEmpty())
- return kUnknownRole;
- return AXObject::AriaRoleToWebCoreRole(aria_role);
-}
-
-static bool ElementHasSignificantAriaRole(const Element* element) {
- if (!element)
- return false;
-
- AccessibilityRole role = AriaRole(element);
- return role != kUnknownRole && role != kNoneRole &&
- role != kPresentationalRole;
-}
-
-bool AXTable::IsDataTable() const {
- return layout_object_ && is_data_table_;
-}
-
-// The following is a heuristic used to determine if a
-// <table> should be with kTableRole or kLayoutTableRole.
-bool AXTable::ComputeIsDataTable() const {
- if (!layout_object_ || !GetNode())
- return false;
-
- // When a section of the document is contentEditable, all tables should be
- // treated as data tables, otherwise users may not be able to work with rich
- // text editors that allow creating and editing tables.
- if (GetNode() && HasEditableStyle(*GetNode()))
- return true;
-
- // This employs a heuristic to determine if this table should appear.
- // Only "data" tables should be exposed as tables.
- // Unfortunately, there is no good way to determine the difference
- // between a "layout" table and a "data" table.
-
- LayoutTable* table = ToLayoutTable(layout_object_);
- Node* table_node = table->GetNode();
- DCHECK(IsHTMLTableElement(table_node));
- HTMLTableElement* table_element = ToHTMLTableElement(table_node);
-
- // If there is a caption element, summary, THEAD, or TFOOT section, it's most
- // certainly a data table
- if (!table_element->Summary().IsEmpty() || table_element->tHead() ||
- table_element->tFoot() || table_element->caption())
- return true;
-
- // if someone used "rules" attribute than the table should appear
- if (!table_element->Rules().IsEmpty())
- return true;
-
- // if there's a colgroup or col element, it's probably a data table.
- if (Traversal<HTMLTableColElement>::FirstChild(*table_element))
- return true;
-
- // go through the cell's and check for tell-tale signs of "data" table status
- // cells have borders, or use attributes like headers, abbr, scope or axis
- table->RecalcSectionsIfNeeded();
- LayoutTableSection* first_body = table->FirstBody();
- if (!first_body)
- return false;
-
- int num_cols_in_first_body = first_body->NumEffectiveColumns();
- int num_rows = first_body->NumRows();
-
- // If there's only one cell, it's not a good AXTable candidate.
- if (num_rows == 1 && num_cols_in_first_body == 1)
- return false;
-
- // If there are at least 20 rows, we'll call it a data table.
- if (num_rows >= 20)
- return true;
-
- // Store the background color of the table to check against cell's background
- // colors.
- const ComputedStyle* table_style = table->Style();
- if (!table_style)
- return false;
- Color table_bg_color =
- table_style->VisitedDependentColor(GetCSSPropertyBackgroundColor());
-
- // check enough of the cells to find if the table matches our criteria
- // Criteria:
- // 1) must have at least one valid cell (and)
- // 2) at least half of cells have borders (or)
- // 3) at least half of cells have different bg colors than the table, and
- // there is cell spacing
- unsigned valid_cell_count = 0;
- unsigned bordered_cell_count = 0;
- unsigned background_difference_cell_count = 0;
- unsigned cells_with_top_border = 0;
- unsigned cells_with_bottom_border = 0;
- unsigned cells_with_left_border = 0;
- unsigned cells_with_right_border = 0;
-
- Color alternating_row_colors[5];
- int alternating_row_color_count = 0;
-
- for (int row = 0; row < num_rows; ++row) {
- int n_cols = first_body->NumCols(row);
- for (int col = 0; col < n_cols; ++col) {
- LayoutTableCell* cell = first_body->PrimaryCellAt(row, col);
- if (!cell)
- continue;
- Node* cell_node = cell->GetNode();
- if (!cell_node)
- continue;
-
- if (cell->Size().Width() < 1 || cell->Size().Height() < 1)
- continue;
-
- valid_cell_count++;
-
- // Any <th> tag -> treat as data table.
- if (cell_node->HasTagName(thTag))
- return true;
-
- // In this case, the developer explicitly assigned a "data" table
- // attribute.
- if (IsHTMLTableCellElement(*cell_node)) {
- HTMLTableCellElement& cell_element = ToHTMLTableCellElement(*cell_node);
- if (!cell_element.Headers().IsEmpty() ||
- !cell_element.Abbr().IsEmpty() || !cell_element.Axis().IsEmpty() ||
- !cell_element.FastGetAttribute(scopeAttr).IsEmpty())
- return true;
- }
-
- const ComputedStyle* computed_style = cell->Style();
- if (!computed_style)
- continue;
-
- // If the empty-cells style is set, we'll call it a data table.
- if (computed_style->EmptyCells() == EEmptyCells::kHide)
- return true;
-
- // If a cell has matching bordered sides, call it a (fully) bordered cell.
- if ((cell->BorderTop() > 0 && cell->BorderBottom() > 0) ||
- (cell->BorderLeft() > 0 && cell->BorderRight() > 0))
- bordered_cell_count++;
-
- // Also keep track of each individual border, so we can catch tables where
- // most cells have a bottom border, for example.
- if (cell->BorderTop() > 0)
- cells_with_top_border++;
- if (cell->BorderBottom() > 0)
- cells_with_bottom_border++;
- if (cell->BorderLeft() > 0)
- cells_with_left_border++;
- if (cell->BorderRight() > 0)
- cells_with_right_border++;
-
- // If the cell has a different color from the table and there is cell
- // spacing, then it is probably a data table cell (spacing and colors take
- // the place of borders).
- Color cell_color = computed_style->VisitedDependentColor(
- GetCSSPropertyBackgroundColor());
- if (table->HBorderSpacing() > 0 && table->VBorderSpacing() > 0 &&
- table_bg_color != cell_color && cell_color.Alpha() != 1)
- background_difference_cell_count++;
-
- // If we've found 10 "good" cells, we don't need to keep searching.
- if (bordered_cell_count >= 10 || background_difference_cell_count >= 10)
- return true;
-
- // For the first 5 rows, cache the background color so we can check if
- // this table has zebra-striped rows.
- if (row < 5 && row == alternating_row_color_count) {
- LayoutObject* layout_row = cell->Parent();
- if (!layout_row || !layout_row->IsBoxModelObject() ||
- !ToLayoutBoxModelObject(layout_row)->IsTableRow())
- continue;
- const ComputedStyle* row_computed_style = layout_row->Style();
- if (!row_computed_style)
- continue;
- Color row_color = row_computed_style->VisitedDependentColor(
- GetCSSPropertyBackgroundColor());
- alternating_row_colors[alternating_row_color_count] = row_color;
- alternating_row_color_count++;
- }
- }
- }
-
- // if there is less than two valid cells, it's not a data table
- if (valid_cell_count <= 1)
- return false;
-
- // half of the cells had borders, it's a data table
- unsigned needed_cell_count = valid_cell_count / 2;
- if (bordered_cell_count >= needed_cell_count ||
- cells_with_top_border >= needed_cell_count ||
- cells_with_bottom_border >= needed_cell_count ||
- cells_with_left_border >= needed_cell_count ||
- cells_with_right_border >= needed_cell_count)
- return true;
-
- // half had different background colors, it's a data table
- if (background_difference_cell_count >= needed_cell_count)
- return true;
-
- // Check if there is an alternating row background color indicating a zebra
- // striped style pattern.
- if (alternating_row_color_count > 2) {
- Color first_color = alternating_row_colors[0];
- for (int k = 1; k < alternating_row_color_count; k++) {
- // If an odd row was the same color as the first row, its not alternating.
- if (k % 2 == 1 && alternating_row_colors[k] == first_color)
- return false;
- // If an even row is not the same as the first row, its not alternating.
- if (!(k % 2) && alternating_row_colors[k] != first_color)
- return false;
- }
- return true;
- }
-
- return false;
-}
-
-// If this returns false, the table will be exposed as a generic object
-// instead of a kTableRole object with kRowRole children and kCellRole
-// grandchildren.
-bool AXTable::IsTableExposableThroughAccessibility() const {
- if (!layout_object_)
- return false;
-
- // If the developer assigned an aria role to this, then we
- // shouldn't expose it as a table, unless, of course, the aria
- // role is a table.
- if (AriaRole(GetElement()) != kUnknownRole)
- return false;
-
- LayoutTable* table = ToLayoutTable(layout_object_);
- Node* table_node = table->GetNode();
- if (!IsHTMLTableElement(table_node))
- return false;
-
- // Do not expose as table if any of its child sections or rows has an ARIA
- // role.
- HTMLTableElement* table_element = ToHTMLTableElement(table_node);
- if (ElementHasSignificantAriaRole(table_element->tHead()))
- return false;
- if (ElementHasSignificantAriaRole(table_element->tFoot()))
- return false;
-
- HTMLCollection* bodies = table_element->tBodies();
- for (unsigned body_index = 0; body_index < bodies->length(); ++body_index) {
- Element* body_element = bodies->item(body_index);
- if (ElementHasSignificantAriaRole(body_element))
- return false;
- }
-
- HTMLTableRowsCollection* rows = table_element->rows();
- for (unsigned row_index = 0; row_index < rows->length(); ++row_index) {
- Element* row_element = rows->item(row_index);
- if (AriaRole(row_element) != kUnknownRole)
- return false;
- }
-
- return true;
-}
-
-void AXTable::ClearChildren() {
- AXLayoutObject::ClearChildren();
- rows_.clear();
- columns_.clear();
-
- if (header_container_) {
- header_container_->DetachFromParent();
- header_container_ = nullptr;
- }
-}
-
-void AXTable::AddChildren() {
- DCHECK(!IsDetached());
- if (!IsAXTable()) {
- AXLayoutObject::AddChildren();
- return;
- }
-
- DCHECK(!have_children_);
-
- have_children_ = true;
- if (!layout_object_ || !layout_object_->IsTable())
- return;
-
- LayoutTable* table = ToLayoutTable(layout_object_);
- AXObjectCacheImpl& ax_cache = AXObjectCache();
-
- Node* table_node = table->GetNode();
- if (!IsHTMLTableElement(table_node))
- return;
-
- // Add caption
- if (HTMLTableCaptionElement* caption =
- ToHTMLTableElement(table_node)->caption()) {
- AXObject* caption_object = ax_cache.GetOrCreate(caption);
- if (caption_object && !caption_object->AccessibilityIsIgnored())
- children_.push_back(caption_object);
- }
-
- // Go through all the available sections to pull out the rows and add them as
- // children.
- table->RecalcSectionsIfNeeded();
- LayoutTableSection* table_section = table->TopSection();
- if (!table_section)
- return;
-
- LayoutTableSection* initial_table_section = table_section;
- while (table_section) {
- HeapHashSet<Member<AXObject>> appended_rows;
- unsigned num_rows = table_section->NumRows();
- for (unsigned row_index = 0; row_index < num_rows; ++row_index) {
- LayoutTableRow* layout_row = table_section->RowLayoutObjectAt(row_index);
- if (!layout_row)
- continue;
-
- AXObject* row_object = ax_cache.GetOrCreate(layout_row);
- if (!row_object || !row_object->IsTableRow())
- continue;
-
- AXTableRow* row = ToAXTableRow(row_object);
- // We need to check every cell for a new row, because cell spans
- // can cause us to miss rows if we just check the first column.
- if (appended_rows.Contains(row))
- continue;
-
- row->SetRowIndex(static_cast<int>(rows_.size()));
- rows_.push_back(row);
- if (!row->AccessibilityIsIgnored())
- children_.push_back(row);
- appended_rows.insert(row);
- }
-
- table_section = table->SectionBelow(table_section, kSkipEmptySections);
- }
-
- // make the columns based on the number of columns in the first body
- unsigned length = initial_table_section->NumEffectiveColumns();
- for (unsigned i = 0; i < length; ++i) {
- AXTableColumn* column = ToAXTableColumn(ax_cache.GetOrCreate(kColumnRole));
- column->SetColumnIndex((int)i);
- column->SetParent(this);
- columns_.push_back(column);
- if (!column->AccessibilityIsIgnored())
- children_.push_back(column);
- }
-
- AXObject* header_container_object = HeaderContainer();
- if (header_container_object &&
- !header_container_object->AccessibilityIsIgnored())
- children_.push_back(header_container_object);
-}
-
-AXObject* AXTable::HeaderContainer() {
- if (header_container_)
- return header_container_.Get();
-
- AXMockObject* table_header =
- ToAXMockObject(AXObjectCache().GetOrCreate(kTableHeaderContainerRole));
- table_header->SetParent(this);
-
- header_container_ = table_header;
- return header_container_.Get();
-}
-
-const AXObject::AXObjectVector& AXTable::Columns() {
- UpdateChildrenIfNecessary();
-
- return columns_;
-}
-
-const AXObject::AXObjectVector& AXTable::Rows() {
- UpdateChildrenIfNecessary();
-
- return rows_;
-}
-
-void AXTable::ColumnHeaders(AXObjectVector& headers) {
- if (!layout_object_)
- return;
-
- UpdateChildrenIfNecessary();
- unsigned column_count = columns_.size();
- for (unsigned c = 0; c < column_count; c++) {
- AXObject* column = columns_[c].Get();
- if (column->IsTableCol())
- ToAXTableColumn(column)->HeaderObjectsForColumn(headers);
- }
-}
-
-void AXTable::RowHeaders(AXObjectVector& headers) {
- if (!layout_object_)
- return;
-
- UpdateChildrenIfNecessary();
- unsigned row_count = rows_.size();
- for (unsigned r = 0; r < row_count; r++) {
- AXObject* row = rows_[r].Get();
- if (row->IsTableRow())
- ToAXTableRow(rows_[r].Get())->HeaderObjectsForRow(headers);
- }
-}
-
-int AXTable::AriaColumnCount() {
- int32_t col_count;
- if (!HasAOMPropertyOrARIAAttribute(AOMIntProperty::kColCount, col_count))
- return 0;
-
- if (col_count > static_cast<int>(ColumnCount()))
- return col_count;
-
- // Spec says that if all of the columns are present in the DOM, it
- // is not necessary to set this attribute as the user agent can
- // automatically calculate the total number of columns.
- // It returns 0 in order not to set this attribute.
- if (col_count == static_cast<int>(ColumnCount()) || col_count != -1)
- return 0;
-
- return -1;
-}
-
-int AXTable::AriaRowCount() {
- int32_t row_count;
- if (!HasAOMPropertyOrARIAAttribute(AOMIntProperty::kRowCount, row_count))
- return 0;
-
- if (row_count > static_cast<int>(RowCount()))
- return row_count;
-
- // Spec says that if all of the rows are present in the DOM, it is
- // not necessary to set this attribute as the user agent can
- // automatically calculate the total number of rows.
- // It returns 0 in order not to set this attribute.
- if (row_count == (int)RowCount() || row_count != -1)
- return 0;
-
- // In the spec, -1 explicitly means an unknown number of rows.
- return -1;
-}
-
-unsigned AXTable::ColumnCount() {
- UpdateChildrenIfNecessary();
-
- return columns_.size();
-}
-
-unsigned AXTable::RowCount() {
- UpdateChildrenIfNecessary();
-
- return rows_.size();
-}
-
-AXTableCell* AXTable::CellForColumnAndRow(unsigned column, unsigned row) {
- UpdateChildrenIfNecessary();
- if (column >= ColumnCount() || row >= RowCount())
- return nullptr;
-
- // Iterate backwards through the rows in case the desired cell has a rowspan
- // and exists in a previous row.
- for (unsigned row_index_counter = row + 1; row_index_counter > 0;
- --row_index_counter) {
- unsigned row_index = row_index_counter - 1;
- const auto& children = rows_[row_index]->Children();
- // Since some cells may have colspans, we have to check the actual range of
- // each cell to determine which is the right one.
- for (unsigned col_index_counter =
- std::min(static_cast<unsigned>(children.size()), column + 1);
- col_index_counter > 0; --col_index_counter) {
- unsigned col_index = col_index_counter - 1;
- AXObject* child = children[col_index].Get();
-
- if (!child->IsTableCell())
- continue;
-
- std::pair<unsigned, unsigned> column_range;
- std::pair<unsigned, unsigned> row_range;
- AXTableCell* table_cell_child = ToAXTableCell(child);
- table_cell_child->ColumnIndexRange(column_range);
- table_cell_child->RowIndexRange(row_range);
-
- if ((column >= column_range.first &&
- column < (column_range.first + column_range.second)) &&
- (row >= row_range.first &&
- row < (row_range.first + row_range.second)))
- return table_cell_child;
- }
- }
-
- return nullptr;
-}
-
-AccessibilityRole AXTable::RoleValue() const {
- if (!IsAXTable())
- return AXLayoutObject::RoleValue();
-
- return IsDataTable() ? kTableRole : kLayoutTableRole;
-}
-
-bool AXTable::ComputeAccessibilityIsIgnored(
- IgnoredReasons* ignored_reasons) const {
- AXObjectInclusion decision = DefaultObjectInclusion(ignored_reasons);
- if (decision == kIncludeObject)
- return false;
- if (decision == kIgnoreObject)
- return true;
-
- if (!IsAXTable())
- return AXLayoutObject::ComputeAccessibilityIsIgnored(ignored_reasons);
-
- return false;
-}
-
-void AXTable::Trace(blink::Visitor* visitor) {
- visitor->Trace(rows_);
- visitor->Trace(columns_);
- visitor->Trace(header_container_);
- AXLayoutObject::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_table.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_table.h
deleted file mode 100644
index 60847c0d33f..00000000000
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_table.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_TABLE_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_TABLE_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_layout_object.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-
-namespace blink {
-
-class AXObjectCacheImpl;
-class AXTableCell;
-
-class MODULES_EXPORT AXTable : public AXLayoutObject {
- protected:
- AXTable(LayoutObject*, AXObjectCacheImpl&);
-
- public:
- static AXTable* Create(LayoutObject*, AXObjectCacheImpl&);
- ~AXTable() override;
- void Trace(blink::Visitor*) override;
-
- void Init() final;
-
- bool IsAXTable() const final;
- bool IsDataTable() const final;
-
- AccessibilityRole RoleValue() const override;
-
- void AddChildren() override;
- void ClearChildren() final;
-
- // To be overridden by AXARIAGrid.
- virtual bool IsAriaTable() const { return false; }
- virtual bool SupportsSelectedRows() { return false; }
-
- const AXObjectVector& Columns();
- const AXObjectVector& Rows();
-
- unsigned ColumnCount();
- unsigned RowCount();
- AXTableCell* CellForColumnAndRow(unsigned column, unsigned row);
-
- int AriaColumnCount();
- int AriaRowCount();
-
- void ColumnHeaders(AXObjectVector&);
- void RowHeaders(AXObjectVector&);
-
- // an object that contains, as children, all the objects that act as headers
- AXObject* HeaderContainer();
-
- protected:
- AXObjectVector rows_;
- AXObjectVector columns_;
-
- Member<AXObject> header_container_;
-
- bool HasARIARole() const;
- bool ComputeAccessibilityIsIgnored(IgnoredReasons* = nullptr) const final;
-
- virtual bool ComputeIsDataTable() const;
- virtual bool IsTableExposableThroughAccessibility() const;
-
- private:
- bool is_ax_table_;
- bool is_data_table_;
-
- DISALLOW_COPY_AND_ASSIGN(AXTable);
-};
-
-DEFINE_AX_OBJECT_TYPE_CASTS(AXTable, IsAXTable());
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_TABLE_H_
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_table_cell.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_table_cell.cc
deleted file mode 100644
index ecd4149bfd2..00000000000
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_table_cell.cc
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/modules/accessibility/ax_table_cell.h"
-
-#include "third_party/blink/renderer/core/dom/accessible_node.h"
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table_row.h"
-
-namespace blink {
-
-using namespace HTMLNames;
-
-AXTableCell::AXTableCell(LayoutObject* layout_object,
- AXObjectCacheImpl& ax_object_cache)
- : AXLayoutObject(layout_object, ax_object_cache) {}
-
-AXTableCell::~AXTableCell() = default;
-
-AXTableCell* AXTableCell::Create(LayoutObject* layout_object,
- AXObjectCacheImpl& ax_object_cache) {
- return new AXTableCell(layout_object, ax_object_cache);
-}
-
-bool AXTableCell::IsTableHeaderCell() const {
- return GetNode() && GetNode()->HasTagName(thTag);
-}
-
-bool AXTableCell::IsRowHeaderCell() const {
- const AtomicString& scope = GetAttribute(scopeAttr);
- return EqualIgnoringASCIICase(scope, "row") ||
- EqualIgnoringASCIICase(scope, "rowgroup");
-}
-
-bool AXTableCell::IsColumnHeaderCell() const {
- const AtomicString& scope = GetAttribute(scopeAttr);
- return EqualIgnoringASCIICase(scope, "col") ||
- EqualIgnoringASCIICase(scope, "colgroup");
-}
-
-bool AXTableCell::ComputeAccessibilityIsIgnored(
- IgnoredReasons* ignored_reasons) const {
- AXObjectInclusion decision = DefaultObjectInclusion(ignored_reasons);
- if (decision == kIncludeObject)
- return false;
- if (decision == kIgnoreObject)
- return true;
-
- if (!IsTableCell())
- return AXLayoutObject::ComputeAccessibilityIsIgnored(ignored_reasons);
-
- return false;
-}
-
-AXObject* AXTableCell::ParentTable() const {
- if (!layout_object_ || !layout_object_->IsTableCell())
- return nullptr;
-
- // If the document no longer exists, we might not have an axObjectCache.
- if (IsDetached())
- return nullptr;
-
- // Do not use getOrCreate. parentTable() can be called while the layout tree
- // is being modified by javascript, and creating a table element may try to
- // access the layout tree while in a bad state. By using only get() implies
- // that the AXTable must be created before AXTableCells. This should always be
- // the case when AT clients access a table.
- // https://bugs.webkit.org/show_bug.cgi?id=42652
- return AXObjectCache().Get(ToLayoutTableCell(layout_object_)->Table());
-}
-
-AXObject* AXTableCell::ParentRow() const {
- if (!layout_object_ || !layout_object_->IsTableCell())
- return nullptr;
-
- // If the document no longer exists, we might not have an axObjectCache.
- if (IsDetached())
- return nullptr;
-
- return AXObjectCache().Get(ToLayoutTableCell(layout_object_)->Row());
-}
-
-bool AXTableCell::IsTableCell() const {
- AXObject* row = ParentRow();
- return row && row->IsTableRow();
-}
-
-unsigned AXTableCell::AriaColumnIndex() const {
- uint32_t col_index;
- if (HasAOMPropertyOrARIAAttribute(AOMUIntProperty::kColIndex, col_index) &&
- col_index >= 1) {
- return col_index;
- }
-
- AXObject* parent = ParentRow();
- return parent ? aria_col_index_from_row_ : 0;
-}
-
-unsigned AXTableCell::AriaRowIndex() const {
- uint32_t row_index;
- if (HasAOMPropertyOrARIAAttribute(AOMUIntProperty::kRowIndex, row_index) &&
- row_index >= 1) {
- return row_index;
- }
-
- AXObject* parent = ParentRow();
- return parent ? ToAXTableRow(parent)->AriaRowIndex() : 0;
-}
-
-static AccessibilityRole DecideRoleFromSibling(LayoutTableCell* sibling_cell) {
- if (!sibling_cell)
- return kCellRole;
-
- if (Node* sibling_node = sibling_cell->GetNode()) {
- if (sibling_node->HasTagName(thTag))
- return kColumnHeaderRole;
- if (sibling_node->HasTagName(tdTag))
- return kRowHeaderRole;
- }
-
- return kCellRole;
-}
-
-AccessibilityRole AXTableCell::ScanToDecideHeaderRole() {
- if (!IsTableHeaderCell())
- return kCellRole;
-
- // Check scope attribute first.
- if (IsRowHeaderCell())
- return kRowHeaderRole;
-
- if (IsColumnHeaderCell())
- return kColumnHeaderRole;
-
- // This occurs in an edge case that mixes non-table CSS into a
- // table, and <th role="gridcell">, see bug 798410.
- // The odd CSS causes the <th> to not be a LayoutTableCell,
- // and the ARIA role causes it to fall through to here, because
- // it is not an ARIA/HTML column/row header.
- if (!layout_object_ || !layout_object_->IsTableCell())
- return kCellRole; // <th role="gridcell">.
-
- // Check the previous cell and the next cell on the same row.
- LayoutTableCell* layout_cell = ToLayoutTableCell(layout_object_);
- AccessibilityRole header_role = kCellRole;
-
- // if header is preceded by header cells on the same row, then it is a
- // column header. If it is preceded by other cells then it's a row header.
- if ((header_role = DecideRoleFromSibling(layout_cell->PreviousCell())) !=
- kCellRole)
- return header_role;
-
- // if header is followed by header cells on the same row, then it is a
- // column header. If it is followed by other cells then it's a row header.
- if ((header_role = DecideRoleFromSibling(layout_cell->NextCell())) !=
- kCellRole)
- return header_role;
-
- // If there are no other cells on that row, then it is a column header.
- return kColumnHeaderRole;
-}
-
-AccessibilityRole AXTableCell::DetermineAccessibilityRole() {
- if (!IsTableCell())
- return AXLayoutObject::DetermineAccessibilityRole();
-
- if (!ParentTable()->IsDataTable())
- return kLayoutTableCellRole;
-
- aria_role_ = DetermineAriaRoleAttribute();
- return ScanToDecideHeaderRole();
-}
-
-bool AXTableCell::RowIndexRange(
- std::pair<unsigned, unsigned>& row_range) const {
- if (!layout_object_ || !layout_object_->IsTableCell())
- return false;
-
- LayoutTableCell* layout_cell = ToLayoutTableCell(layout_object_);
- row_range.first = layout_cell->RowIndex();
- row_range.second = layout_cell->ResolvedRowSpan();
-
- // Since our table might have multiple sections, we have to offset our row
- // appropriately.
- LayoutTableSection* section = layout_cell->Section();
- LayoutTable* table = layout_cell->Table();
- if (!table || !section)
- return false;
-
- LayoutTableSection* table_section = table->TopSection();
- unsigned row_offset = 0;
- while (table_section) {
- if (table_section == section)
- break;
- row_offset += table_section->NumRows();
- table_section = table->SectionBelow(table_section, kSkipEmptySections);
- }
-
- row_range.first += row_offset;
- return true;
-}
-
-bool AXTableCell::ColumnIndexRange(
- std::pair<unsigned, unsigned>& column_range) const {
- if (!layout_object_ || !layout_object_->IsTableCell())
- return false;
-
- LayoutTableCell* cell = ToLayoutTableCell(layout_object_);
- column_range.first = cell->Table()->AbsoluteColumnToEffectiveColumn(
- cell->AbsoluteColumnIndex());
-
- column_range.second = cell->Table()->AbsoluteColumnToEffectiveColumn(
- cell->AbsoluteColumnIndex() + cell->ColSpan()) -
- column_range.first;
-
- return true;
-}
-
-SortDirection AXTableCell::GetSortDirection() const {
- if (RoleValue() != kRowHeaderRole && RoleValue() != kColumnHeaderRole)
- return kSortDirectionUndefined;
-
- const AtomicString& aria_sort =
- GetAOMPropertyOrARIAAttribute(AOMStringProperty::kSort);
- if (aria_sort.IsEmpty())
- return kSortDirectionUndefined;
- if (EqualIgnoringASCIICase(aria_sort, "none"))
- return kSortDirectionNone;
- if (EqualIgnoringASCIICase(aria_sort, "ascending"))
- return kSortDirectionAscending;
- if (EqualIgnoringASCIICase(aria_sort, "descending"))
- return kSortDirectionDescending;
- // Technically, illegal values should be exposed as is, but this does
- // not seem to be worth the implementation effort at this time.
- return kSortDirectionOther;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_table_cell.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_table_cell.h
deleted file mode 100644
index a1820d6a487..00000000000
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_table_cell.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_TABLE_CELL_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_TABLE_CELL_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_layout_object.h"
-
-namespace blink {
-
-class AXObjectCacheImpl;
-
-class MODULES_EXPORT AXTableCell : public AXLayoutObject {
- protected:
- AXTableCell(LayoutObject*, AXObjectCacheImpl&);
-
- public:
- static AXTableCell* Create(LayoutObject*, AXObjectCacheImpl&);
- ~AXTableCell() override;
-
- bool IsTableCell() const final;
-
- // fills in the start location and row span of cell
- virtual bool RowIndexRange(std::pair<unsigned, unsigned>& row_range) const;
- // fills in the start location and column span of cell
- virtual bool ColumnIndexRange(
- std::pair<unsigned, unsigned>& column_range) const;
- // In the case of cells that act as row or column headers.
- SortDirection GetSortDirection() const final;
- virtual AccessibilityRole ScanToDecideHeaderRole();
-
- unsigned AriaColumnIndex() const;
- unsigned AriaRowIndex() const;
-
- void SetARIAColIndexFromRow(int index) { aria_col_index_from_row_ = index; }
-
- protected:
- virtual AXObject* ParentTable() const;
- virtual AXObject* ParentRow() const;
- AccessibilityRole DetermineAccessibilityRole() final;
- bool CanSetSelectedAttribute() const override { return false; }
-
- private:
- bool IsTableHeaderCell() const;
- bool IsRowHeaderCell() const;
- bool IsColumnHeaderCell() const;
-
- bool ComputeAccessibilityIsIgnored(IgnoredReasons* = nullptr) const final;
-
- unsigned aria_col_index_from_row_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(AXTableCell);
-};
-
-DEFINE_AX_OBJECT_TYPE_CASTS(AXTableCell, IsTableCell());
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_TABLE_CELL_H_
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_table_column.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_table_column.cc
deleted file mode 100644
index a27ca1c04a8..00000000000
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_table_column.cc
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/modules/accessibility/ax_table_column.h"
-
-#include "third_party/blink/renderer/core/layout/layout_table_cell.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table_cell.h"
-
-namespace blink {
-
-using namespace HTMLNames;
-
-AXTableColumn::AXTableColumn(AXObjectCacheImpl& ax_object_cache)
- : AXMockObject(ax_object_cache) {}
-
-AXTableColumn::~AXTableColumn() = default;
-
-AXTableColumn* AXTableColumn::Create(AXObjectCacheImpl& ax_object_cache) {
- return new AXTableColumn(ax_object_cache);
-}
-
-void AXTableColumn::SetParent(AXObject* parent) {
- AXMockObject::SetParent(parent);
-
- ClearChildren();
-}
-
-void AXTableColumn::HeaderObjectsForColumn(AXObjectVector& headers) {
- if (!parent_)
- return;
-
- LayoutObject* layout_object = parent_->GetLayoutObject();
- if (!layout_object)
- return;
-
- if (!parent_->IsAXTable())
- return;
-
- if (ToAXTable(parent_)->IsAriaTable()) {
- for (const auto& cell : Children()) {
- if (cell->RoleValue() == kColumnHeaderRole)
- headers.push_back(cell);
- }
- return;
- }
-
- if (!layout_object->IsTable())
- return;
-
- LayoutTable* table = ToLayoutTable(layout_object);
- LayoutTableSection* table_section = table->TopSection();
- for (; table_section;
- table_section = table->SectionBelow(table_section, kSkipEmptySections)) {
- unsigned num_cols = table_section->NumEffectiveColumns();
- if (column_index_ >= num_cols)
- continue;
- unsigned num_rows = table_section->NumRows();
- for (unsigned r = 0; r < num_rows; r++) {
- LayoutTableCell* layout_cell =
- table_section->PrimaryCellAt(r, column_index_);
- if (!layout_cell)
- continue;
-
- AXObject* cell = AXObjectCache().GetOrCreate(layout_cell->GetNode());
- if (!cell || !cell->IsTableCell() || headers.Contains(cell))
- continue;
-
- if (ToAXTableCell(cell)->ScanToDecideHeaderRole() == kColumnHeaderRole)
- headers.push_back(cell);
- }
- }
-}
-
-AXObject* AXTableColumn::HeaderObject() {
- AXObjectVector headers;
- HeaderObjectsForColumn(headers);
- if (!headers.size())
- return nullptr;
-
- return headers[0].Get();
-}
-
-bool AXTableColumn::ComputeAccessibilityIsIgnored(
- IgnoredReasons* ignored_reasons) const {
- if (!parent_)
- return true;
-
- if (!parent_->AccessibilityIsIgnored())
- return false;
-
- if (ignored_reasons)
- parent_->ComputeAccessibilityIsIgnored(ignored_reasons);
-
- return true;
-}
-
-AccessibilityRole AXTableColumn::RoleValue() const {
- return parent_ && parent_->IsAXTable() && ToAXTable(parent_)->IsDataTable()
- ? kColumnRole
- : kLayoutTableColumnRole;
-}
-
-void AXTableColumn::AddChildren() {
- DCHECK(!IsDetached());
- DCHECK(!have_children_);
-
- have_children_ = true;
- if (!parent_ || !parent_->IsAXTable())
- return;
-
- AXTable* parent_table = ToAXTable(parent_);
- int num_rows = parent_table->RowCount();
-
- for (int i = 0; i < num_rows; i++) {
- AXTableCell* cell = parent_table->CellForColumnAndRow(column_index_, i);
- if (!cell)
- continue;
-
- // make sure the last one isn't the same as this one (rowspan cells)
- if (children_.size() > 0 && children_.back() == cell)
- continue;
-
- children_.push_back(cell);
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_table_column.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_table_column.h
deleted file mode 100644
index 98b6a340c47..00000000000
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_table_column.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_TABLE_COLUMN_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_TABLE_COLUMN_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_mock_object.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-
-namespace blink {
-
-class AXObjectCacheImpl;
-
-class MODULES_EXPORT AXTableColumn final : public AXMockObject {
- private:
- explicit AXTableColumn(AXObjectCacheImpl&);
-
- public:
- static AXTableColumn* Create(AXObjectCacheImpl&);
- ~AXTableColumn() override;
-
- // retrieves the topmost "column" header (th)
- AXObject* HeaderObject();
- // retrieves the "column" headers (th, scope) from top to bottom
- void HeaderObjectsForColumn(AXObjectVector&);
-
- void SetColumnIndex(int column_index) { column_index_ = column_index; }
- int ColumnIndex() const { return column_index_; }
-
- void AddChildren() override;
- void SetParent(AXObject*) override;
-
- protected:
- bool CanSetSelectedAttribute() const override { return false; }
-
- // Set the role via RoleValue() instead of DetermineAccessibilityRole(),
- // because the role depends on the parent, and DetermineAccessibilityRole()
- // is called before SetParent().
- AccessibilityRole RoleValue() const final;
-
- private:
- unsigned column_index_;
-
- bool IsTableCol() const override { return true; }
- bool ComputeAccessibilityIsIgnored(IgnoredReasons* = nullptr) const override;
-
- DISALLOW_COPY_AND_ASSIGN(AXTableColumn);
-};
-
-DEFINE_AX_OBJECT_TYPE_CASTS(AXTableColumn, IsTableCol());
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_TABLE_COLUMN_H_
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_table_header_container.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_table_header_container.cc
deleted file mode 100644
index d62c489052a..00000000000
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_table_header_container.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/modules/accessibility/ax_table_header_container.h"
-
-#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
-
-namespace blink {
-
-AXTableHeaderContainer::AXTableHeaderContainer(
- AXObjectCacheImpl& ax_object_cache)
- : AXMockObject(ax_object_cache) {}
-
-AXTableHeaderContainer::~AXTableHeaderContainer() = default;
-
-AXTableHeaderContainer* AXTableHeaderContainer::Create(
- AXObjectCacheImpl& ax_object_cache) {
- return new AXTableHeaderContainer(ax_object_cache);
-}
-
-bool AXTableHeaderContainer::ComputeAccessibilityIsIgnored(
- IgnoredReasons* ignored_reasons) const {
- if (!parent_)
- return true;
-
- if (!parent_->AccessibilityIsIgnored())
- return false;
-
- if (ignored_reasons)
- parent_->ComputeAccessibilityIsIgnored(ignored_reasons);
-
- return true;
-}
-
-void AXTableHeaderContainer::AddChildren() {
- DCHECK(!IsDetached());
- DCHECK(!have_children_);
-
- have_children_ = true;
- if (!parent_ || !parent_->IsAXTable())
- return;
-
- ToAXTable(parent_)->ColumnHeaders(children_);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_table_header_container.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_table_header_container.h
deleted file mode 100644
index 8d0addfadf9..00000000000
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_table_header_container.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_TABLE_HEADER_CONTAINER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_TABLE_HEADER_CONTAINER_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_mock_object.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table.h"
-
-namespace blink {
-
-class AXObjectCacheImpl;
-
-class AXTableHeaderContainer final : public AXMockObject {
- private:
- explicit AXTableHeaderContainer(AXObjectCacheImpl&);
-
- public:
- static AXTableHeaderContainer* Create(AXObjectCacheImpl&);
- ~AXTableHeaderContainer() override;
-
- AccessibilityRole RoleValue() const override {
- return kTableHeaderContainerRole;
- }
-
- void AddChildren() override;
-
- private:
- bool ComputeAccessibilityIsIgnored(IgnoredReasons* = nullptr) const override;
-
- DISALLOW_COPY_AND_ASSIGN(AXTableHeaderContainer);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_TABLE_HEADER_CONTAINER_H_
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_table_row.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_table_row.cc
deleted file mode 100644
index 7d3c9a70ff4..00000000000
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_table_row.cc
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/modules/accessibility/ax_table_row.h"
-
-#include "third_party/blink/renderer/core/dom/accessible_node.h"
-#include "third_party/blink/renderer/core/layout/layout_object.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table_cell.h"
-
-namespace blink {
-
-using namespace HTMLNames;
-
-AXTableRow::AXTableRow(LayoutObject* layout_object,
- AXObjectCacheImpl& ax_object_cache)
- : AXLayoutObject(layout_object, ax_object_cache) {}
-
-AXTableRow::~AXTableRow() = default;
-
-AXTableRow* AXTableRow::Create(LayoutObject* layout_object,
- AXObjectCacheImpl& ax_object_cache) {
- return new AXTableRow(layout_object, ax_object_cache);
-}
-
-void AXTableRow::AddChildren() {
- AXLayoutObject::AddChildren();
-
- // A row is allowed to have a column index, indicating the index of the
- // first cell in that row, and each subsequent cell gets the next index.
- int col_index = AriaColumnIndex();
- if (!col_index)
- return;
-
- unsigned index = 0;
- for (const auto& cell : Children()) {
- if (cell->IsTableCell())
- ToAXTableCell(cell.Get())->SetARIAColIndexFromRow(col_index + index);
- index++;
- }
-}
-
-AccessibilityRole AXTableRow::DetermineAccessibilityRole() {
- if (!IsTableRow())
- return AXLayoutObject::DetermineAccessibilityRole();
-
- if ((aria_role_ = DetermineAriaRoleAttribute()) != kUnknownRole)
- return aria_role_;
-
- return ParentTable()->IsDataTable() ? kRowRole : kLayoutTableRowRole;
-}
-
-bool AXTableRow::IsTableRow() const {
- AXObject* table = ParentTable();
- if (!table || !table->IsAXTable())
- return false;
-
- return true;
-}
-
-bool AXTableRow::ComputeAccessibilityIsIgnored(
- IgnoredReasons* ignored_reasons) const {
- AXObjectInclusion decision = DefaultObjectInclusion(ignored_reasons);
- if (decision == kIncludeObject)
- return false;
- if (decision == kIgnoreObject)
- return true;
-
- if (!IsTableRow())
- return AXLayoutObject::ComputeAccessibilityIsIgnored(ignored_reasons);
-
- return false;
-}
-
-AXObject* AXTableRow::ParentTable() const {
- AXObject* parent = ParentObjectUnignored();
- if (!parent || !parent->IsAXTable())
- return nullptr;
-
- return parent;
-}
-
-AXObject* AXTableRow::HeaderObject() {
- AXObjectVector headers;
- HeaderObjectsForRow(headers);
- if (!headers.size())
- return nullptr;
-
- return headers[0].Get();
-}
-
-unsigned AXTableRow::AriaColumnIndex() const {
- uint32_t col_index;
- if (HasAOMPropertyOrARIAAttribute(AOMUIntProperty::kColIndex, col_index) &&
- col_index >= 1) {
- return col_index;
- }
-
- return 0;
-}
-
-unsigned AXTableRow::AriaRowIndex() const {
- uint32_t row_index;
- if (HasAOMPropertyOrARIAAttribute(AOMUIntProperty::kRowIndex, row_index) &&
- row_index >= 1) {
- return row_index;
- }
-
- return 0;
-}
-
-void AXTableRow::HeaderObjectsForRow(AXObjectVector& headers) {
- if (!layout_object_ || !layout_object_->IsTableRow())
- return;
-
- for (const auto& cell : Children()) {
- if (!cell->IsTableCell())
- continue;
-
- if (ToAXTableCell(cell.Get())->ScanToDecideHeaderRole() == kRowHeaderRole)
- headers.push_back(cell);
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_table_row.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_table_row.h
deleted file mode 100644
index 8af6d175571..00000000000
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_table_row.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_TABLE_ROW_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_TABLE_ROW_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_layout_object.h"
-
-namespace blink {
-
-class AXObjectCacheImpl;
-
-class MODULES_EXPORT AXTableRow : public AXLayoutObject {
- protected:
- AXTableRow(LayoutObject*, AXObjectCacheImpl&);
-
- public:
- static AXTableRow* Create(LayoutObject*, AXObjectCacheImpl&);
- ~AXTableRow() override;
-
- void AddChildren() override;
- bool IsTableRow() const final;
-
- // retrieves the "row" header (a th tag in the rightmost column)
- virtual AXObject* HeaderObject();
- // Retrieves the "row" headers (th, scope) from left to right for the each
- // row.
- virtual void HeaderObjectsForRow(AXObjectVector&);
- virtual AXObject* ParentTable() const;
- virtual const AXObjectVector& Cells() { return Children(); }
-
- void SetRowIndex(int row_index) { row_index_ = row_index; }
- int RowIndex() const { return row_index_; }
-
- unsigned AriaColumnIndex() const;
- unsigned AriaRowIndex() const;
-
- protected:
- AccessibilityRole DetermineAccessibilityRole() final;
- bool CanSetSelectedAttribute() const override { return false; }
-
- private:
- int row_index_;
-
- bool ComputeAccessibilityIsIgnored(IgnoredReasons* = nullptr) const final;
-
- DISALLOW_COPY_AND_ASSIGN(AXTableRow);
-};
-
-DEFINE_AX_OBJECT_TYPE_CASTS(AXTableRow, IsTableRow());
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_TABLE_ROW_H_
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_virtual_object.cc b/chromium/third_party/blink/renderer/modules/accessibility/ax_virtual_object.cc
index c6b0a3f77a0..c4dfefe29d6 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_virtual_object.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_virtual_object.cc
@@ -33,6 +33,11 @@ void AXVirtualObject::AddChildren() {
children_.push_back(AXObjectCache().GetOrCreate(child));
}
+void AXVirtualObject::ChildrenChanged() {
+ ClearChildren();
+ AXObjectCache().PostNotification(this, AXObjectCacheImpl::kAXChildrenChanged);
+}
+
const AtomicString& AXVirtualObject::GetAOMPropertyOrARIAAttribute(
AOMStringProperty property) const {
if (!accessible_node_)
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/ax_virtual_object.h b/chromium/third_party/blink/renderer/modules/accessibility/ax_virtual_object.h
index 19c5e8349be..666f7dbfca0 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/ax_virtual_object.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/ax_virtual_object.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_VIRTUAL_OBJECT_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_VIRTUAL_OBJECT_H_
-#include "third_party/blink/renderer/core/dom/accessible_node.h"
+#include "third_party/blink/renderer/core/aom/accessible_node.h"
#include "third_party/blink/renderer/modules/accessibility/ax_object.h"
#include "third_party/blink/renderer/modules/modules_export.h"
@@ -24,6 +24,7 @@ class MODULES_EXPORT AXVirtualObject : public AXObject {
AXObject* ComputeParent() const override { return parent_; }
bool IsVirtualObject() const override { return true; }
void AddChildren() override;
+ void ChildrenChanged() override;
const AtomicString& GetAOMPropertyOrARIAAttribute(
AOMStringProperty) const override;
bool HasAOMPropertyOrARIAAttribute(AOMBooleanProperty,
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc b/chromium/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc
index a91842b4ff1..5a08266ddbf 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.h"
#include <memory>
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.cc b/chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.cc
new file mode 100644
index 00000000000..9a91e8f4d82
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.cc
@@ -0,0 +1,264 @@
+// 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/modules/accessibility/testing/accessibility_selection_test.h"
+
+#include "third_party/blink/renderer/core/dom/node.h"
+#include "third_party/blink/renderer/core/html/html_element.h"
+#include "third_party/blink/renderer/modules/accessibility/ax_object.h"
+#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
+#include "third_party/blink/renderer/modules/accessibility/ax_position.h"
+#include "third_party/blink/renderer/modules/accessibility/ax_selection.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+namespace {
+
+// Serialize accessibility subtree to selection text.
+// Adds a '^' at the selection anchor offset and a '|' at the focus offset.
+class AXSelectionSerializer final {
+ STACK_ALLOCATED();
+
+ public:
+ explicit AXSelectionSerializer(const AXSelection& selection)
+ : selection_(selection) {}
+
+ std::string Serialize(const AXObject& subtree) {
+ if (!selection_.IsValid())
+ return {};
+ SerializeSubtree(subtree);
+ return builder_.ToString().Utf8().data();
+ }
+
+ private:
+ void HandleTextObject(const AXObject& text_object) {
+ builder_.Append('<');
+ builder_.Append(AXObject::InternalRoleName(text_object.RoleValue()));
+ builder_.Append(": ");
+ const String name = text_object.ComputedName() + '>';
+ const AXObject& base_container = *selection_.Base().ContainerObject();
+ const AXObject& extent_container = *selection_.Extent().ContainerObject();
+
+ if (base_container == text_object && extent_container == text_object) {
+ DCHECK(selection_.Base().IsTextPosition() &&
+ selection_.Extent().IsTextPosition());
+ const int base_offset = selection_.Base().TextOffset();
+ const int extent_offset = selection_.Extent().TextOffset();
+
+ if (base_offset == extent_offset) {
+ builder_.Append(name.Left(base_offset));
+ builder_.Append('|');
+ builder_.Append(name.Substring(base_offset));
+ return;
+ }
+
+ if (base_offset < extent_offset) {
+ builder_.Append(name.Left(base_offset));
+ builder_.Append('^');
+ builder_.Append(
+ name.Substring(base_offset, extent_offset - base_offset));
+ builder_.Append('|');
+ builder_.Append(name.Substring(extent_offset));
+ return;
+ }
+
+ builder_.Append(name.Left(extent_offset));
+ builder_.Append('|');
+ builder_.Append(
+ name.Substring(extent_offset, base_offset - extent_offset));
+ builder_.Append('^');
+ builder_.Append(name.Substring(base_offset));
+ return;
+ }
+
+ if (base_container == text_object) {
+ DCHECK(selection_.Base().IsTextPosition());
+ const int base_offset = selection_.Base().TextOffset();
+
+ builder_.Append(name.Left(base_offset));
+ builder_.Append('^');
+ builder_.Append(name.Substring(base_offset));
+ return;
+ }
+
+ if (extent_container == text_object) {
+ DCHECK(selection_.Extent().IsTextPosition());
+ const int extent_offset = selection_.Extent().TextOffset();
+
+ builder_.Append(name.Left(extent_offset));
+ builder_.Append('|');
+ builder_.Append(name.Substring(extent_offset));
+ return;
+ }
+
+ builder_.Append(name);
+ }
+
+ void HandleObject(const AXObject& object) {
+ builder_.Append('<');
+ builder_.Append(AXObject::InternalRoleName(object.RoleValue()));
+ builder_.Append(": ");
+ builder_.Append(object.ComputedName());
+ builder_.Append('>');
+ SerializeSubtree(object);
+ }
+
+ void HandleSelection(const AXPosition& position) {
+ if (!position.IsValid())
+ return;
+
+ if (selection_.Extent() == position) {
+ builder_.Append('|');
+ return;
+ }
+
+ if (selection_.Base() != position)
+ return;
+
+ builder_.Append('^');
+ }
+
+ void SerializeSubtree(const AXObject& subtree) {
+ for (const Member<AXObject>& child : subtree.Children()) {
+ if (!child)
+ continue;
+ const auto position = AXPosition::CreatePositionBeforeObject(*child);
+ HandleSelection(position);
+ if (position.IsTextPosition()) {
+ HandleTextObject(*child);
+ } else {
+ HandleObject(*child);
+ }
+ }
+ HandleSelection(AXPosition::CreateLastPositionInObject(subtree));
+ }
+
+ StringBuilder builder_;
+ AXSelection selection_;
+};
+
+// Deserializes an HTML snippet with or without selection markers to an
+// accessibility tree. A '^' could be present at the selection anchor offset and
+// a '|' at the focus offset. If multiple markers are present, the deserializer
+// will DCHECK. If there are no markers, no selection will be made.
+class AXSelectionDeserializer final {
+ STACK_ALLOCATED();
+
+ public:
+ AXSelectionDeserializer(AXObjectCacheImpl& cache)
+ : ax_object_cache_(&cache), base_(), extent_() {}
+ ~AXSelectionDeserializer() = default;
+
+ // Creates an accessibility tree rooted at the given HTML element from the
+ // provided HTML snippet, selects the part of the tree indicated by the
+ // selection markers in the snippet if present, and returns the tree's root.
+ AXObject* Deserialize(const std::string& html_snippet, HTMLElement& element) {
+ element.SetInnerHTMLFromString(String::FromUTF8(html_snippet.c_str()));
+ AXObject* root = ax_object_cache_->GetOrCreate(&element);
+ if (!root)
+ return nullptr;
+
+ FindSelectionMarkers(*root);
+ if (base_ && extent_) {
+ AXSelection::Builder builder;
+ AXSelection ax_selection =
+ builder.SetBase(base_).SetExtent(extent_).Build();
+ ax_selection.Select();
+ }
+
+ return root;
+ }
+
+ private:
+ void HandleCharacterData(const AXObject& text_object) {
+ int base_offset = -1;
+ int extent_offset = -1;
+ String name = text_object.ComputedName();
+ for (unsigned i = 0; i < name.length(); ++i) {
+ const UChar character = name[i];
+ if (character == '^') {
+ DCHECK_EQ(base_offset, -1) << text_object;
+ base_offset = static_cast<int>(i);
+ continue;
+ }
+ if (character == '|') {
+ DCHECK_EQ(extent_offset, -1) << text_object;
+ extent_offset = static_cast<int>(i);
+ continue;
+ }
+ }
+
+ if (base_offset == -1 && extent_offset == -1)
+ return;
+
+ if (base_offset >= 0)
+ base_ = AXPosition::CreatePositionInTextObject(text_object, base_offset);
+ if (extent_offset >= 0) {
+ extent_ =
+ AXPosition::CreatePositionInTextObject(text_object, extent_offset);
+ }
+ }
+
+ void HandleObject(const AXObject& object) {
+ for (const Member<AXObject>& child : object.Children()) {
+ if (!child)
+ continue;
+ FindSelectionMarkers(*child);
+ }
+ }
+
+ void FindSelectionMarkers(const AXObject& root) {
+ const Node* node = root.GetNode();
+ if (node && node->IsCharacterDataNode()) {
+ HandleCharacterData(root);
+ return;
+ }
+ HandleObject(root);
+ }
+
+ Member<AXObjectCacheImpl> const ax_object_cache_;
+ AXPosition base_;
+ AXPosition extent_;
+};
+
+} // namespace
+
+AccessibilitySelectionTest::AccessibilitySelectionTest(
+ LocalFrameClient* local_frame_client)
+ : AccessibilityTest(local_frame_client) {}
+
+std::string AccessibilitySelectionTest::GetSelectionText(
+ const AXSelection& selection) const {
+ const AXObject* root = GetAXRootObject();
+ if (!root)
+ return {};
+ return AXSelectionSerializer(selection).Serialize(*root);
+}
+
+std::string AccessibilitySelectionTest::GetSelectionText(
+ const AXSelection& selection,
+ const AXObject& subtree) const {
+ return AXSelectionSerializer(selection).Serialize(subtree);
+}
+
+AXObject* AccessibilitySelectionTest::SetSelectionText(
+ const std::string& selection_text) const {
+ HTMLElement* body = GetDocument().body();
+ if (!body)
+ return nullptr;
+ return AXSelectionDeserializer(GetAXObjectCache())
+ .Deserialize(selection_text, *body);
+}
+
+AXObject* AccessibilitySelectionTest::SetSelectionText(
+ const std::string& selection_text,
+ HTMLElement& element) const {
+ return AXSelectionDeserializer(GetAXObjectCache())
+ .Deserialize(selection_text, element);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.h b/chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.h
new file mode 100644
index 00000000000..9f8dcd76fb6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.h
@@ -0,0 +1,48 @@
+// 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_MODULES_ACCESSIBILITY_TESTING_ACCESSIBILITY_SELECTION_TEST_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_TESTING_ACCESSIBILITY_SELECTION_TEST_H_
+
+#include <string>
+
+#include "third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+
+namespace blink {
+
+class AXObject;
+class AXSelection;
+class LocalFrameClient;
+
+// Makes writing and debugging selection tests easier.
+class AccessibilitySelectionTest : public AccessibilityTest {
+ USING_FAST_MALLOC(AccessibilitySelectionTest);
+
+ public:
+ AccessibilitySelectionTest(LocalFrameClient* local_frame_client = nullptr);
+
+ protected:
+ // Gets the inner HTML of the accessibility tree and annotates it with markers
+ // indicating the anchor and focus of |selection|.
+ std::string GetSelectionText(const AXSelection& selection) const;
+
+ // Gets the inner HTML of the accessibility subtree rooted at |subtree| and
+ // annotates it with markers indicating the anchor and focus of |selection|.
+ std::string GetSelectionText(const AXSelection& selection,
+ const AXObject& subtree) const;
+
+ // Sets |selection_text| as inner HTML of the document body and returns the
+ // root of the accessibility tree at body.
+ AXObject* SetSelectionText(const std::string& selection_text) const;
+
+ // Sets |selection_text| as inner HTML of |element| and returns the root of
+ // the accessibility subtree at |element|.
+ AXObject* SetSelectionText(const std::string& selection_text,
+ HTMLElement& element) const;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_TESTING_ACCESSIBILITY_SELECTION_TEST_H_
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.cc b/chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.cc
index ac7e5383216..c2f07058807 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.cc
+++ b/chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.cc
@@ -13,6 +13,9 @@
namespace blink {
+AccessibilityTest::AccessibilityTest(LocalFrameClient* local_frame_client)
+ : RenderingTest(local_frame_client) {}
+
void AccessibilityTest::SetUp() {
RenderingTest::SetUp();
DCHECK(GetDocument().GetSettings());
diff --git a/chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h b/chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h
index 6b7bfadd531..b15f578efa9 100644
--- a/chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h
+++ b/chromium/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h
@@ -22,8 +22,7 @@ class AccessibilityTest : public RenderingTest {
USING_FAST_MALLOC(AccessibilityTest);
public:
- AccessibilityTest(LocalFrameClient* local_frame_client = nullptr)
- : RenderingTest(local_frame_client) {}
+ AccessibilityTest(LocalFrameClient* local_frame_client = nullptr);
protected:
void SetUp() override;
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/BUILD.gn b/chromium/third_party/blink/renderer/modules/animationworklet/BUILD.gn
index e06318a92fc..9d3f18b510f 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/BUILD.gn
@@ -20,10 +20,12 @@ blink_modules_sources("animationworklet") {
"animator.h",
"animator_definition.cc",
"animator_definition.h",
+ "css_animation_worklet.cc",
+ "css_animation_worklet.h",
"effect_proxy.h",
- "window_animation_worklet.cc",
- "window_animation_worklet.h",
"worklet_animation.cc",
"worklet_animation.h",
+ "worklet_animation_options.cc",
+ "worklet_animation_options.h",
]
}
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet.cc b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet.cc
index 455d69feefd..cea538e58ea 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet.cc
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/animationworklet/animation_worklet.h"
+#include "base/atomic_sequence_num.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/dom/animation_worklet_proxy_client.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -13,9 +14,18 @@
#include "third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_impl.h"
#include "third_party/blink/renderer/modules/animationworklet/animation_worklet_thread.h"
+base::AtomicSequenceNumber g_next_worklet_id;
+
+int NextId() {
+ // Start id from 1. This way it safe to use it as key in hashmap with default
+ // key traits.
+ return g_next_worklet_id.GetNext() + 1;
+}
+
namespace blink {
-AnimationWorklet::AnimationWorklet(Document* document) : Worklet(document) {}
+AnimationWorklet::AnimationWorklet(Document* document)
+ : Worklet(document), scope_id_(NextId()), last_animation_id_(0) {}
AnimationWorklet::~AnimationWorklet() = default;
@@ -31,7 +41,7 @@ WorkletGlobalScopeProxy* AnimationWorklet::CreateGlobalScope() {
Document* document = ToDocument(GetExecutionContext());
AnimationWorkletProxyClient* proxy_client =
- AnimationWorkletProxyClientImpl::FromDocument(document);
+ AnimationWorkletProxyClientImpl::FromDocument(document, scope_id_);
WorkerClients* worker_clients = WorkerClients::Create();
ProvideAnimationWorkletProxyClientTo(worker_clients, proxy_client);
@@ -42,6 +52,12 @@ WorkletGlobalScopeProxy* AnimationWorklet::CreateGlobalScope() {
return proxy;
}
+WorkletAnimationId AnimationWorklet::NextWorkletAnimationId() {
+ // Id starts from 1. This way it safe to use it as key in hashmap with default
+ // key traits.
+ return {.scope_id = scope_id_, .animation_id = ++last_animation_id_};
+}
+
void AnimationWorklet::Trace(blink::Visitor* visitor) {
Worklet::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet.h b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet.h
index 7abefd82b73..fa07268915d 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet.h
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet.h
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/workers/worklet.h"
#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/graphics/compositor_animators_state.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
@@ -25,9 +26,14 @@ class MODULES_EXPORT AnimationWorklet final : public Worklet {
explicit AnimationWorklet(Document*);
~AnimationWorklet() override;
+ WorkletAnimationId NextWorkletAnimationId();
void Trace(blink::Visitor*) override;
private:
+ // Unique id associated with this worklet that is used by cc to identify all
+ // animations associated it.
+ int scope_id_;
+ int last_animation_id_;
// Implements Worklet.
bool NeedsToCreateGlobalScope() final;
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.cc b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.cc
index 6541ce1d0d8..d6f189521a5 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.cc
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.cc
@@ -4,12 +4,13 @@
#include "third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_parser.h"
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
#include "third_party/blink/renderer/core/dom/animation_worklet_proxy_client.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
+#include "third_party/blink/renderer/modules/animationworklet/worklet_animation_options.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding_macros.h"
#include "third_party/blink/renderer/platform/bindings/v8_object_constructor.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -18,37 +19,17 @@ namespace blink {
namespace {
-// Once this goes out of scope it clears any animators that have not been
-// animated.
-class ScopedAnimatorsSweeper {
- STACK_ALLOCATED();
-
- public:
- using AnimatorMap = HeapHashMap<int, TraceWrapperMember<Animator>>;
- explicit ScopedAnimatorsSweeper(AnimatorMap& animators)
- : animators_(animators) {
- for (const auto& entry : animators_) {
- Animator* animator = entry.value;
- animator->clear_did_animate();
- }
+void UpdateAnimation(Animator* animator,
+ ScriptState* script_state,
+ WorkletAnimationId id,
+ double current_time,
+ CompositorMutatorOutputState* result) {
+ CompositorMutatorOutputState::AnimationState animation_output;
+ if (animator->Animate(script_state, current_time, &animation_output)) {
+ animation_output.worklet_animation_id = id;
+ result->animations.push_back(std::move(animation_output));
}
- ~ScopedAnimatorsSweeper() {
- // Clear any animator that has not been animated.
- // TODO(majidvp): Reconsider this once we add specific entry to mutator
- // input that explicitly inform us that an animator is deleted.
- Vector<int> to_be_removed;
- for (const auto& entry : animators_) {
- int id = entry.key;
- Animator* animator = entry.value;
- if (!animator->did_animate())
- to_be_removed.push_back(id);
- }
- animators_.RemoveAll(to_be_removed);
- }
-
- private:
- AnimatorMap& animators_;
-};
+}
} // namespace
@@ -75,17 +56,6 @@ void AnimationWorkletGlobalScope::Trace(blink::Visitor* visitor) {
ThreadedWorkletGlobalScope::Trace(visitor);
}
-void AnimationWorkletGlobalScope::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- for (auto animator : animators_)
- visitor->TraceWrappers(animator.value);
-
- for (auto definition : animator_definitions_)
- visitor->TraceWrappers(definition.value);
-
- ThreadedWorkletGlobalScope::TraceWrappers(visitor);
-}
-
void AnimationWorkletGlobalScope::Dispose() {
DCHECK(IsContextThread());
if (AnimationWorkletProxyClient* proxy_client =
@@ -94,53 +64,59 @@ void AnimationWorkletGlobalScope::Dispose() {
ThreadedWorkletGlobalScope::Dispose();
}
-Animator* AnimationWorkletGlobalScope::GetAnimatorFor(int animation_id,
- const String& name) {
- Animator* animator = animators_.at(animation_id);
- if (!animator) {
- // This is a new animation so we should create an animator for it.
- animator = CreateInstance(name);
- if (!animator)
- return nullptr;
-
- animators_.Set(animation_id, animator);
- }
+Animator* AnimationWorkletGlobalScope::CreateAnimatorFor(
+ int animation_id,
+ const String& name,
+ WorkletAnimationOptions* options) {
+ DCHECK(!animators_.at(animation_id));
+ Animator* animator = CreateInstance(name, options);
+ if (!animator)
+ return nullptr;
+ animators_.Set(animation_id, animator);
return animator;
}
-std::unique_ptr<CompositorMutatorOutputState>
-AnimationWorkletGlobalScope::Mutate(
- const CompositorMutatorInputState& mutator_input) {
+std::unique_ptr<AnimationWorkletOutput> AnimationWorkletGlobalScope::Mutate(
+ const AnimationWorkletInput& mutator_input) {
DCHECK(IsContextThread());
- // Clean any animator that is not updated
- ScopedAnimatorsSweeper sweeper(animators_);
-
ScriptState* script_state = ScriptController()->GetScriptState();
ScriptState::Scope scope(script_state);
- std::unique_ptr<CompositorMutatorOutputState> result =
- std::make_unique<CompositorMutatorOutputState>();
+ std::unique_ptr<AnimationWorkletOutput> result =
+ std::make_unique<AnimationWorkletOutput>();
+
+ for (const auto& worklet_animation_id : mutator_input.removed_animations)
+ animators_.erase(worklet_animation_id.animation_id);
+
+ for (const auto& animation : mutator_input.added_and_updated_animations) {
+ int id = animation.worklet_animation_id.animation_id;
+ DCHECK(!animators_.Contains(id));
+ const String name =
+ String::FromUTF8(animation.name.data(), animation.name.size());
+
+ // Down casting to blink type to access the serialized value.
+ WorkletAnimationOptions* options =
+ static_cast<WorkletAnimationOptions*>(animation.options.get());
- for (const CompositorMutatorInputState::AnimationState& animation_input :
- mutator_input.animations) {
- int id = animation_input.animation_id;
- const String name = String::FromUTF8(animation_input.name.data(),
- animation_input.name.size());
+ Animator* animator = CreateAnimatorFor(id, name, options);
+ if (!animator)
+ continue;
- Animator* animator = GetAnimatorFor(id, name);
- // TODO(majidvp): This means there is an animatorName for which
- // definition was not registered. We should handle this case gracefully.
- // http://crbug.com/776017
+ UpdateAnimation(animator, script_state, animation.worklet_animation_id,
+ animation.current_time, result.get());
+ }
+
+ for (const auto& animation : mutator_input.updated_animations) {
+ int id = animation.worklet_animation_id.animation_id;
+ Animator* animator = animators_.at(id);
+ // We don't try to create an animator if there isn't any.
if (!animator)
continue;
- CompositorMutatorOutputState::AnimationState animation_output;
- if (animator->Animate(script_state, animation_input, &animation_output)) {
- animation_output.animation_id = id;
- result->animations.push_back(std::move(animation_output));
- }
+ UpdateAnimation(animator, script_state, animation.worklet_animation_id,
+ animation.current_time, result.get());
}
return result;
@@ -166,7 +142,7 @@ void AnimationWorkletGlobalScope::registerAnimator(
DCHECK(IsContextThread());
if (animator_definitions_.Contains(name)) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"A class with name:'" + name + "' is already registered.");
return;
}
@@ -199,7 +175,9 @@ void AnimationWorkletGlobalScope::registerAnimator(
animator_definitions_.Set(name, definition);
}
-Animator* AnimationWorkletGlobalScope::CreateInstance(const String& name) {
+Animator* AnimationWorkletGlobalScope::CreateInstance(
+ const String& name,
+ WorkletAnimationOptions* options) {
DCHECK(IsContextThread());
AnimatorDefinition* definition = animator_definitions_.at(name);
if (!definition)
@@ -208,9 +186,13 @@ Animator* AnimationWorkletGlobalScope::CreateInstance(const String& name) {
v8::Isolate* isolate = ScriptController()->GetScriptState()->GetIsolate();
v8::Local<v8::Function> constructor = definition->ConstructorLocal(isolate);
DCHECK(!IsUndefinedOrNull(constructor));
+ v8::Local<v8::Value> value;
+ if (options && options->GetData())
+ value = options->GetData()->Deserialize(isolate);
v8::Local<v8::Object> instance;
- if (!V8ObjectConstructor::NewInstance(isolate, constructor)
+ if (!V8ObjectConstructor::NewInstance(isolate, constructor,
+ !value.IsEmpty() ? 1 : 0, &value)
.ToLocal(&instance))
return nullptr;
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.h b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.h
index 685bb80e7dc..cfcb8da7720 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.h
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope.h
@@ -16,6 +16,7 @@
namespace blink {
class ExceptionState;
+class WorkletAnimationOptions;
// Represents the animation worklet global scope and implements all methods that
// the global scope exposes to user script (See
@@ -37,14 +38,11 @@ class MODULES_EXPORT AnimationWorkletGlobalScope
WorkerThread*);
~AnimationWorkletGlobalScope() override;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
void Dispose() override;
bool IsAnimationWorkletGlobalScope() const final { return true; }
- Animator* CreateInstance(const String& name);
// Invokes the |animate| function of all of its active animators.
- std::unique_ptr<CompositorMutatorOutputState> Mutate(
- const CompositorMutatorInputState&);
+ std::unique_ptr<AnimationWorkletOutput> Mutate(const AnimationWorkletInput&);
// Registers a animator definition with the given name and constructor.
void registerAnimator(const String& name,
@@ -60,7 +58,11 @@ class MODULES_EXPORT AnimationWorkletGlobalScope
WorkerThread*);
void RegisterWithProxyClientIfNeeded();
- Animator* GetAnimatorFor(int animation_id, const String& name);
+ Animator* CreateInstance(const String& name,
+ WorkletAnimationOptions* options);
+ Animator* CreateAnimatorFor(int animation_id,
+ const String& name,
+ WorkletAnimationOptions* options);
typedef HeapHashMap<String, TraceWrapperMember<AnimatorDefinition>>
DefinitionMap;
DefinitionMap animator_definitions_;
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc
index 120605d1722..461b599e5bb 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc
@@ -7,7 +7,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_url_request.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_module.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"
@@ -25,6 +24,7 @@
#include "third_party/blink/renderer/modules/animationworklet/animation_worklet_thread.h"
#include "third_party/blink/renderer/modules/animationworklet/animator.h"
#include "third_party/blink/renderer/modules/animationworklet/animator_definition.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/loader/fetch/access_control_status.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
@@ -85,13 +85,12 @@ class AnimationWorkletGlobalScopeTest : public PageTestBase {
thread->Start(
std::make_unique<GlobalScopeCreationParams>(
document->Url(), ScriptType::kModule, document->UserAgent(),
- nullptr /* content_security_policy_parsed_headers */,
- document->GetReferrerPolicy(), document->GetSecurityOrigin(),
- document->IsSecureContext(), clients, document->AddressSpace(),
+ Vector<CSPHeaderAndType>(), document->GetReferrerPolicy(),
+ document->GetSecurityOrigin(), document->IsSecureContext(), clients,
+ document->AddressSpace(),
OriginTrialContext::GetTokens(document).get(),
base::UnguessableToken::Create(), nullptr /* worker_settings */,
- kV8CacheOptionsDefault,
- new WorkletModuleResponsesMap(document->Fetcher())),
+ kV8CacheOptionsDefault, new WorkletModuleResponsesMap),
base::nullopt, WorkerInspectorProxy::PauseOnWorkerStart::kDontPause,
ParentExecutionContextTaskRunners::Create());
return thread;
@@ -223,14 +222,12 @@ class AnimationWorkletGlobalScopeTest : public PageTestBase {
// Passing a new input state with a new animation id should cause the
// worklet to create and animate an animator.
- CompositorMutatorInputState state;
- CompositorMutatorInputState::AnimationState test_animation_state;
- test_animation_state.animation_id = 1;
- test_animation_state.name = "test";
- test_animation_state.current_time = 5000;
- state.animations = {test_animation_state};
-
- std::unique_ptr<CompositorMutatorOutputState> output =
+ cc::WorkletAnimationId animation_id = {1, 1};
+ AnimationWorkletInput state;
+ state.added_and_updated_animations.emplace_back(animation_id, "test", 5000,
+ nullptr);
+
+ std::unique_ptr<AnimationWorkletOutput> output =
global_scope->Mutate(state);
EXPECT_TRUE(output);
@@ -275,14 +272,12 @@ class AnimationWorkletGlobalScopeTest : public PageTestBase {
// Passing a new input state with a new animation id should cause the
// worklet to create and animate an animator.
- CompositorMutatorInputState state;
- CompositorMutatorInputState::AnimationState test_animation_state;
- test_animation_state.animation_id = 1;
- test_animation_state.name = "test";
- test_animation_state.current_time = 5000;
- state.animations = {test_animation_state};
-
- std::unique_ptr<CompositorMutatorOutputState> output =
+ cc::WorkletAnimationId animation_id = {1, 1};
+ AnimationWorkletInput state;
+ state.added_and_updated_animations.emplace_back(animation_id, "test", 5000,
+ nullptr);
+
+ std::unique_ptr<AnimationWorkletOutput> output =
global_scope->Mutate(state);
EXPECT_TRUE(output);
@@ -290,12 +285,104 @@ class AnimationWorkletGlobalScopeTest : public PageTestBase {
EXPECT_EQ(output->animations[0].local_time,
WTF::TimeDelta::FromMillisecondsD(123));
- // Passing a new empty input state should cause the worklet to remove the
- // previously constructed animator.
- CompositorMutatorInputState empty_state;
- output = global_scope->Mutate(empty_state);
- EXPECT_TRUE(output);
- EXPECT_EQ(output->animations.size(), 0ul);
+ waitable_event->Signal();
+ }
+
+ // This test verifies that an animator instance is not created if
+ // MutatorInputState does not have an animation in
+ // added_and_updated_animations.
+ void RunAnimatorInstanceCreationTestOnWorklet(WorkerThread* thread,
+ WaitableEvent* waitable_event) {
+ AnimationWorkletGlobalScope* global_scope =
+ static_cast<AnimationWorkletGlobalScope*>(thread->GlobalScope());
+ ASSERT_TRUE(global_scope);
+ ASSERT_TRUE(global_scope->IsAnimationWorkletGlobalScope());
+ ScriptState* script_state =
+ global_scope->ScriptController()->GetScriptState();
+ ASSERT_TRUE(script_state);
+ v8::Isolate* isolate = script_state->GetIsolate();
+ ASSERT_TRUE(isolate);
+
+ EXPECT_EQ(global_scope->GetAnimatorsSizeForTest(), 0u);
+
+ ScriptState::Scope scope(script_state);
+ global_scope->ScriptController()->Evaluate(ScriptSourceCode(
+ R"JS(
+ registerAnimator('test', class {
+ animate (currentTime, effect) {
+ effect.localTime = 123;
+ }
+ });
+ )JS"));
+
+ cc::WorkletAnimationId animation_id = {1, 1};
+ AnimationWorkletInput state;
+ state.updated_animations.push_back({animation_id, 5000});
+ EXPECT_EQ(state.added_and_updated_animations.size(), 0u);
+ EXPECT_EQ(state.updated_animations.size(), 1u);
+ global_scope->Mutate(state);
+ EXPECT_EQ(global_scope->GetAnimatorsSizeForTest(), 0u);
+
+ state.removed_animations.push_back(animation_id);
+ EXPECT_EQ(state.added_and_updated_animations.size(), 0u);
+ EXPECT_EQ(state.removed_animations.size(), 1u);
+ global_scope->Mutate(state);
+ EXPECT_EQ(global_scope->GetAnimatorsSizeForTest(), 0u);
+
+ state.added_and_updated_animations.push_back(
+ {animation_id, "test", 5000, nullptr});
+ EXPECT_EQ(state.added_and_updated_animations.size(), 1u);
+ global_scope->Mutate(state);
+ EXPECT_EQ(global_scope->GetAnimatorsSizeForTest(), 1u);
+ waitable_event->Signal();
+ }
+
+ // This test verifies that an animator instance is created and removed
+ // properly.
+ void RunAnimatorInstanceUpdateTestOnWorklet(WorkerThread* thread,
+ WaitableEvent* waitable_event) {
+ AnimationWorkletGlobalScope* global_scope =
+ static_cast<AnimationWorkletGlobalScope*>(thread->GlobalScope());
+ ASSERT_TRUE(global_scope);
+ ASSERT_TRUE(global_scope->IsAnimationWorkletGlobalScope());
+ ScriptState* script_state =
+ global_scope->ScriptController()->GetScriptState();
+ ASSERT_TRUE(script_state);
+ v8::Isolate* isolate = script_state->GetIsolate();
+ ASSERT_TRUE(isolate);
+
+ EXPECT_EQ(global_scope->GetAnimatorsSizeForTest(), 0u);
+
+ ScriptState::Scope scope(script_state);
+ global_scope->ScriptController()->Evaluate(ScriptSourceCode(
+ R"JS(
+ registerAnimator('test', class {
+ animate (currentTime, effect) {
+ effect.localTime = 123;
+ }
+ });
+ )JS"));
+
+ cc::WorkletAnimationId animation_id = {1, 1};
+ AnimationWorkletInput state;
+ state.added_and_updated_animations.push_back(
+ {animation_id, "test", 5000, nullptr});
+ EXPECT_EQ(state.added_and_updated_animations.size(), 1u);
+ global_scope->Mutate(state);
+ EXPECT_EQ(global_scope->GetAnimatorsSizeForTest(), 1u);
+
+ state.added_and_updated_animations.clear();
+ state.updated_animations.push_back({animation_id, 6000});
+ EXPECT_EQ(state.added_and_updated_animations.size(), 0u);
+ EXPECT_EQ(state.updated_animations.size(), 1u);
+ global_scope->Mutate(state);
+ EXPECT_EQ(global_scope->GetAnimatorsSizeForTest(), 1u);
+
+ state.updated_animations.clear();
+ state.removed_animations.push_back(animation_id);
+ EXPECT_EQ(state.updated_animations.size(), 0u);
+ EXPECT_EQ(state.removed_animations.size(), 1u);
+ global_scope->Mutate(state);
EXPECT_EQ(global_scope->GetAnimatorsSizeForTest(), 0u);
waitable_event->Signal();
@@ -338,6 +425,16 @@ TEST_F(AnimationWorkletGlobalScopeTest, AnimationOutput) {
&AnimationWorkletGlobalScopeTest::RunAnimateOutputTestOnWorklet);
}
+TEST_F(AnimationWorkletGlobalScopeTest, AnimatorInstanceCreation) {
+ RunTestOnWorkletThread(&AnimationWorkletGlobalScopeTest::
+ RunAnimatorInstanceCreationTestOnWorklet);
+}
+
+TEST_F(AnimationWorkletGlobalScopeTest, AnimatorInstanceUpdate) {
+ RunTestOnWorkletThread(
+ &AnimationWorkletGlobalScopeTest::RunAnimatorInstanceUpdateTestOnWorklet);
+}
+
TEST_F(AnimationWorkletGlobalScopeTest,
ShouldRegisterItselfAfterFirstAnimatorRegistration) {
MockAnimationWorkletProxyClient* proxy_client =
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_impl.cc b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_impl.cc
index d72889046d3..61db57bb25d 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_impl.cc
@@ -14,9 +14,11 @@
namespace blink {
AnimationWorkletProxyClientImpl::AnimationWorkletProxyClientImpl(
+ int scope_id,
base::WeakPtr<CompositorMutatorImpl> mutator,
scoped_refptr<base::SingleThreadTaskRunner> mutator_runner)
- : mutator_(std::move(mutator)),
+ : scope_id_(scope_id),
+ mutator_(std::move(mutator)),
mutator_runner_(std::move(mutator_runner)),
state_(RunState::kUninitialized) {
DCHECK(IsMainThread());
@@ -37,7 +39,7 @@ void AnimationWorkletProxyClientImpl::SetGlobalScope(
global_scope_ = static_cast<AnimationWorkletGlobalScope*>(global_scope);
// TODO(majidvp): Add an AnimationWorklet task type when the spec is final.
- scoped_refptr<base::SingleThreadTaskRunner> global_runner_ =
+ scoped_refptr<base::SingleThreadTaskRunner> global_scope_runner =
global_scope_->GetThread()->GetTaskRunner(TaskType::kMiscPlatformAPI);
state_ = RunState::kWorking;
DCHECK(mutator_runner_);
@@ -45,7 +47,7 @@ void AnimationWorkletProxyClientImpl::SetGlobalScope(
*mutator_runner_, FROM_HERE,
CrossThreadBind(&CompositorMutatorImpl::RegisterCompositorAnimator,
mutator_, WrapCrossThreadPersistent(this),
- global_runner_));
+ global_scope_runner));
}
void AnimationWorkletProxyClientImpl::Dispose() {
@@ -71,29 +73,36 @@ void AnimationWorkletProxyClientImpl::Dispose() {
state_ = RunState::kDisposed;
}
-std::unique_ptr<CompositorMutatorOutputState>
-AnimationWorkletProxyClientImpl::Mutate(
- const CompositorMutatorInputState& input_state) {
+std::unique_ptr<AnimationWorkletOutput> AnimationWorkletProxyClientImpl::Mutate(
+ std::unique_ptr<AnimationWorkletInput> input) {
+ DCHECK(input);
+#if DCHECK_IS_ON()
+ DCHECK(input->ValidateScope(scope_id_))
+ << "Input has state that does not belong to this global scope: "
+ << scope_id_;
+#endif
+
if (!global_scope_)
return nullptr;
- auto output_state = global_scope_->Mutate(input_state);
+ auto output = global_scope_->Mutate(*input);
// TODO(petermayo): https://crbug.com/791280 PostCrossThreadTask to supply
// this rather than return it.
- return output_state;
+ return output;
}
// static
AnimationWorkletProxyClientImpl* AnimationWorkletProxyClientImpl::FromDocument(
- Document* document) {
+ Document* document,
+ int scope_id) {
WebLocalFrameImpl* local_frame =
WebLocalFrameImpl::FromFrame(document->GetFrame());
scoped_refptr<base::SingleThreadTaskRunner> mutator_queue;
base::WeakPtr<CompositorMutatorImpl> mutator =
local_frame->LocalRootFrameWidget()->EnsureCompositorMutator(
&mutator_queue);
- return new AnimationWorkletProxyClientImpl(std::move(mutator),
+ return new AnimationWorkletProxyClientImpl(scope_id, std::move(mutator),
std::move(mutator_queue));
}
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_impl.h b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_impl.h
index 275a2b7c48a..a63b30eb3ed 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_impl.h
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_proxy_client_impl.h
@@ -35,6 +35,7 @@ class MODULES_EXPORT AnimationWorkletProxyClientImpl final
// This client is hooked to the given |mutatee|, on the given
// |mutatee_runner|.
explicit AnimationWorkletProxyClientImpl(
+ int scope_id,
base::WeakPtr<CompositorMutatorImpl> mutatee,
scoped_refptr<base::SingleThreadTaskRunner> mutatee_runner);
void Trace(blink::Visitor*) override;
@@ -45,12 +46,14 @@ class MODULES_EXPORT AnimationWorkletProxyClientImpl final
// CompositorAnimator:
// These methods are invoked on the animation worklet thread.
- std::unique_ptr<CompositorMutatorOutputState> Mutate(
- const CompositorMutatorInputState&) override;
+ int GetScopeId() const override { return scope_id_; }
+ std::unique_ptr<AnimationWorkletOutput> Mutate(
+ std::unique_ptr<AnimationWorkletInput> input) override;
- static AnimationWorkletProxyClientImpl* FromDocument(Document*);
+ static AnimationWorkletProxyClientImpl* FromDocument(Document*, int scope_id);
private:
+ const int scope_id_;
base::WeakPtr<CompositorMutatorImpl> mutator_;
scoped_refptr<base::SingleThreadTaskRunner> mutator_runner_;
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_thread_test.cc b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_thread_test.cc
index dd539d5dc2b..2d9fd362ed9 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_thread_test.cc
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/animation_worklet_thread_test.cc
@@ -87,13 +87,12 @@ class AnimationWorkletThreadTest : public PageTestBase {
thread->Start(
std::make_unique<GlobalScopeCreationParams>(
document->Url(), ScriptType::kModule, document->UserAgent(),
- nullptr /* content_security_policy_parsed_headers */,
- document->GetReferrerPolicy(), document->GetSecurityOrigin(),
- document->IsSecureContext(), clients, document->AddressSpace(),
+ Vector<CSPHeaderAndType>(), document->GetReferrerPolicy(),
+ document->GetSecurityOrigin(), document->IsSecureContext(), clients,
+ document->AddressSpace(),
OriginTrialContext::GetTokens(document).get(),
base::UnguessableToken::Create(), nullptr /* worker_settings */,
- kV8CacheOptionsDefault,
- new WorkletModuleResponsesMap(document->Fetcher())),
+ kV8CacheOptionsDefault, new WorkletModuleResponsesMap),
base::nullopt, WorkerInspectorProxy::PauseOnWorkerStart::kDontPause,
ParentExecutionContextTaskRunners::Create());
return thread;
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/animator.cc b/chromium/third_party/blink/renderer/modules/animationworklet/animator.cc
index ecbe4375966..1ef75ab8ac2 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/animator.cc
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/animator.cc
@@ -25,18 +25,12 @@ Animator::~Animator() = default;
void Animator::Trace(blink::Visitor* visitor) {
visitor->Trace(definition_);
visitor->Trace(effect_);
-}
-
-void Animator::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(definition_);
- visitor->TraceWrappers(instance_.Cast<v8::Value>());
+ visitor->Trace(instance_.Cast<v8::Value>());
}
bool Animator::Animate(ScriptState* script_state,
- const CompositorMutatorInputState::AnimationState& input,
+ double current_time,
CompositorMutatorOutputState::AnimationState* output) {
- did_animate_ = true;
-
v8::Isolate* isolate = script_state->GetIsolate();
v8::Local<v8::Object> instance = instance_.NewLocal(isolate);
@@ -55,7 +49,7 @@ bool Animator::Animate(ScriptState* script_state,
ToV8(effect_, script_state->GetContext()->Global(), isolate);
v8::Local<v8::Value> v8_current_time =
- ToV8(input.current_time, script_state->GetContext()->Global(), isolate);
+ ToV8(current_time, script_state->GetContext()->Global(), isolate);
v8::Local<v8::Value> argv[] = {v8_current_time, v8_effect};
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/animator.h b/chromium/third_party/blink/renderer/modules/animationworklet/animator.h
index c2817e22d24..d4b302429e5 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/animator.h
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/animator.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_ANIMATOR_H_
#include "third_party/blink/renderer/modules/animationworklet/effect_proxy.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/graphics/compositor_animators_state.h"
@@ -23,31 +23,26 @@ class ScriptState;
// instance and knows how to invoke the |animate| function on it.
// See also |AnimationWorkletGlobalScope::CreateInstance|.
class Animator final : public GarbageCollectedFinalized<Animator>,
- public TraceWrapperBase {
+ public NameClient {
public:
Animator(v8::Isolate*, AnimatorDefinition*, v8::Local<v8::Object> instance);
~Animator();
void Trace(blink::Visitor*);
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override { return "Animator"; }
// Returns true if it successfully invoked animate callback in JS. It receives
// latest state coming from |AnimationHost| as input and fills
// the output state with new updates.
bool Animate(ScriptState*,
- const CompositorMutatorInputState::AnimationState&,
+ double current_time,
CompositorMutatorOutputState::AnimationState*);
- bool did_animate() const { return did_animate_; }
- void clear_did_animate() { did_animate_ = false; }
-
private:
// This object keeps the definition object, and animator instance alive.
// It participates in wrapper tracing as it holds onto V8 wrappers.
TraceWrapperMember<AnimatorDefinition> definition_;
TraceWrapperV8Reference<v8::Object> instance_;
- bool did_animate_ = false;
Member<EffectProxy> effect_;
};
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/animator_definition.cc b/chromium/third_party/blink/renderer/modules/animationworklet/animator_definition.cc
index 637dc344fa7..8df2f128721 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/animator_definition.cc
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/animator_definition.cc
@@ -19,9 +19,9 @@ AnimatorDefinition::AnimatorDefinition(v8::Isolate* isolate,
AnimatorDefinition::~AnimatorDefinition() = default;
-void AnimatorDefinition::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(constructor_.Cast<v8::Value>());
- visitor->TraceWrappers(animate_.Cast<v8::Value>());
+void AnimatorDefinition::Trace(Visitor* visitor) {
+ visitor->Trace(constructor_.Cast<v8::Value>());
+ visitor->Trace(animate_.Cast<v8::Value>());
}
v8::Local<v8::Function> AnimatorDefinition::ConstructorLocal(
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/animator_definition.h b/chromium/third_party/blink/renderer/modules/animationworklet/animator_definition.h
index c59c599e891..6d1eec6227d 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/animator_definition.h
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/animator_definition.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_ANIMATOR_DEFINITION_H_
#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "v8/include/v8.h"
@@ -20,14 +20,13 @@ namespace blink {
// Javascript class before completing the registration.
class MODULES_EXPORT AnimatorDefinition final
: public GarbageCollectedFinalized<AnimatorDefinition>,
- public TraceWrapperBase {
+ public NameClient {
public:
AnimatorDefinition(v8::Isolate*,
v8::Local<v8::Function> constructor,
v8::Local<v8::Function> animate);
~AnimatorDefinition();
- void Trace(blink::Visitor* visitor) {}
- void TraceWrappers(ScriptWrappableVisitor*) const override;
+ virtual void Trace(blink::Visitor* visitor);
const char* NameInHeapSnapshot() const override {
return "AnimatorDefinition";
}
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/css_animation_worklet.cc b/chromium/third_party/blink/renderer/modules/animationworklet/css_animation_worklet.cc
new file mode 100644
index 00000000000..eb1beab1083
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/css_animation_worklet.cc
@@ -0,0 +1,61 @@
+// 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/modules/animationworklet/css_animation_worklet.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"
+
+namespace blink {
+
+// static
+AnimationWorklet* CSSAnimationWorklet::animationWorklet(
+ ScriptState* script_state) {
+ LocalDOMWindow* window = ToLocalDOMWindow(script_state->GetContext());
+
+ if (!window->GetFrame())
+ return nullptr;
+ return From(*window).animation_worklet_.Get();
+}
+
+// Break the following cycle when the context gets detached.
+// Otherwise, the worklet object will leak.
+//
+// window => CSS.animationWorklet
+// => CSSAnimationWorklet
+// => AnimationWorklet <--- break this reference
+// => ThreadedWorkletMessagingProxy
+// => Document
+// => ... => window
+void CSSAnimationWorklet::ContextDestroyed(ExecutionContext*) {
+ animation_worklet_ = nullptr;
+}
+
+void CSSAnimationWorklet::Trace(blink::Visitor* visitor) {
+ visitor->Trace(animation_worklet_);
+ Supplement<LocalDOMWindow>::Trace(visitor);
+ ContextLifecycleObserver::Trace(visitor);
+}
+
+// static
+CSSAnimationWorklet& CSSAnimationWorklet::From(LocalDOMWindow& window) {
+ CSSAnimationWorklet* supplement =
+ Supplement<LocalDOMWindow>::From<CSSAnimationWorklet>(window);
+ if (!supplement) {
+ supplement = new CSSAnimationWorklet(window.GetFrame()->GetDocument());
+ ProvideTo(window, supplement);
+ }
+ return *supplement;
+}
+
+CSSAnimationWorklet::CSSAnimationWorklet(Document* document)
+ : ContextLifecycleObserver(document),
+ animation_worklet_(new AnimationWorklet(document)) {
+ DCHECK(GetExecutionContext());
+}
+
+const char CSSAnimationWorklet::kSupplementName[] = "CSSAnimationWorklet";
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/css_animation_worklet.h b/chromium/third_party/blink/renderer/modules/animationworklet/css_animation_worklet.h
new file mode 100644
index 00000000000..3593675cf88
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/css_animation_worklet.h
@@ -0,0 +1,44 @@
+// 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_MODULES_ANIMATIONWORKLET_CSS_ANIMATION_WORKLET_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_CSS_ANIMATION_WORKLET_H_
+
+#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/modules/animationworklet/animation_worklet.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+
+namespace blink {
+
+class Document;
+
+class MODULES_EXPORT CSSAnimationWorklet final
+ : public GarbageCollected<CSSAnimationWorklet>,
+ public Supplement<LocalDOMWindow>,
+ public ContextLifecycleObserver {
+ USING_GARBAGE_COLLECTED_MIXIN(CSSAnimationWorklet);
+
+ public:
+ static const char kSupplementName[];
+
+ static AnimationWorklet* animationWorklet(ScriptState*);
+
+ void ContextDestroyed(ExecutionContext*) override;
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ static CSSAnimationWorklet& From(LocalDOMWindow&);
+
+ explicit CSSAnimationWorklet(Document*);
+
+ Member<AnimationWorklet> animation_worklet_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_CSS_ANIMATION_WORKLET_H_
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/css_animation_worklet.idl b/chromium/third_party/blink/renderer/modules/animationworklet/css_animation_worklet.idl
new file mode 100644
index 00000000000..55c092abbdc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/css_animation_worklet.idl
@@ -0,0 +1,11 @@
+// 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.
+
+[
+ ImplementedAs=CSSAnimationWorklet,
+ OriginTrialEnabled=AnimationWorklet,
+ SecureContext
+] partial interface CSS {
+ [CallWith=ScriptState] static readonly attribute Worklet animationWorklet;
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/window_animation_worklet.cc b/chromium/third_party/blink/renderer/modules/animationworklet/window_animation_worklet.cc
deleted file mode 100644
index 4526d4ab8a7..00000000000
--- a/chromium/third_party/blink/renderer/modules/animationworklet/window_animation_worklet.cc
+++ /dev/null
@@ -1,59 +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/modules/animationworklet/window_animation_worklet.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"
-
-namespace blink {
-
-// static
-AnimationWorklet* WindowAnimationWorklet::animationWorklet(
- LocalDOMWindow& window) {
- if (!window.GetFrame())
- return nullptr;
- return From(window).animation_worklet_.Get();
-}
-
-// Break the following cycle when the context gets detached.
-// Otherwise, the worklet object will leak.
-//
-// window => window.animationWorklet
-// => WindowAnimationWorklet
-// => AnimationWorklet <--- break this reference
-// => ThreadedWorkletMessagingProxy
-// => Document
-// => ... => window
-void WindowAnimationWorklet::ContextDestroyed(ExecutionContext*) {
- animation_worklet_ = nullptr;
-}
-
-void WindowAnimationWorklet::Trace(blink::Visitor* visitor) {
- visitor->Trace(animation_worklet_);
- Supplement<LocalDOMWindow>::Trace(visitor);
- ContextLifecycleObserver::Trace(visitor);
-}
-
-// static
-WindowAnimationWorklet& WindowAnimationWorklet::From(LocalDOMWindow& window) {
- WindowAnimationWorklet* supplement =
- Supplement<LocalDOMWindow>::From<WindowAnimationWorklet>(window);
- if (!supplement) {
- supplement = new WindowAnimationWorklet(window.GetFrame()->GetDocument());
- ProvideTo(window, supplement);
- }
- return *supplement;
-}
-
-WindowAnimationWorklet::WindowAnimationWorklet(Document* document)
- : ContextLifecycleObserver(document),
- animation_worklet_(new AnimationWorklet(document)) {
- DCHECK(GetExecutionContext());
-}
-
-const char WindowAnimationWorklet::kSupplementName[] = "WindowAnimationWorklet";
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/window_animation_worklet.h b/chromium/third_party/blink/renderer/modules/animationworklet/window_animation_worklet.h
deleted file mode 100644
index a6da4c2f227..00000000000
--- a/chromium/third_party/blink/renderer/modules/animationworklet/window_animation_worklet.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_WINDOW_ANIMATION_WORKLET_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_WINDOW_ANIMATION_WORKLET_H_
-
-#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
-#include "third_party/blink/renderer/modules/animationworklet/animation_worklet.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/supplementable.h"
-
-namespace blink {
-
-class Document;
-class LocalDOMWindow;
-
-class MODULES_EXPORT WindowAnimationWorklet final
- : public GarbageCollected<WindowAnimationWorklet>,
- public Supplement<LocalDOMWindow>,
- public ContextLifecycleObserver {
- USING_GARBAGE_COLLECTED_MIXIN(WindowAnimationWorklet);
-
- public:
- static const char kSupplementName[];
-
- static AnimationWorklet* animationWorklet(LocalDOMWindow&);
-
- void ContextDestroyed(ExecutionContext*) override;
-
- void Trace(blink::Visitor*) override;
-
- private:
- static WindowAnimationWorklet& From(LocalDOMWindow&);
-
- explicit WindowAnimationWorklet(Document*);
-
- Member<AnimationWorklet> animation_worklet_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_WINDOW_ANIMATION_WORKLET_H_
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/window_animation_worklet.idl b/chromium/third_party/blink/renderer/modules/animationworklet/window_animation_worklet.idl
deleted file mode 100644
index 9130ad381de..00000000000
--- a/chromium/third_party/blink/renderer/modules/animationworklet/window_animation_worklet.idl
+++ /dev/null
@@ -1,11 +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.
-
-[
- ImplementedAs=WindowAnimationWorklet,
- OriginTrialEnabled=AnimationWorklet,
- SecureContext
-] partial interface Window {
- readonly attribute Worklet animationWorklet;
-};
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc
index 99843e6a5ae..957407a7a36 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc
@@ -4,21 +4,27 @@
#include "third_party/blink/renderer/modules/animationworklet/worklet_animation.h"
+#include "base/optional.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/modules/v8/animation_effect_or_animation_effect_sequence.h"
#include "third_party/blink/renderer/core/animation/element_animations.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect_model.h"
#include "third_party/blink/renderer/core/animation/scroll_timeline.h"
#include "third_party/blink/renderer/core/animation/timing.h"
+#include "third_party/blink/renderer/core/animation/worklet_animation_controller.h"
#include "third_party/blink/renderer/core/dom/node.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.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/core/layout/layout_box.h"
+#include "third_party/blink/renderer/modules/animationworklet/css_animation_worklet.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
namespace {
+
bool ConvertAnimationEffects(
const AnimationEffectOrAnimationEffectSequence& effects,
HeapVector<Member<KeyframeEffect>>& keyframe_effects,
@@ -101,17 +107,18 @@ AnimationTimeline* ConvertAnimationTimeline(
return &document.Timeline();
}
-bool CheckElementComposited(const Element& target) {
+bool CheckElementComposited(const Node& target) {
return target.GetLayoutObject() &&
target.GetLayoutObject()->GetCompositingState() ==
kPaintsIntoOwnBacking;
}
-CompositorElementId GetCompositorScrollElementId(const Element& element) {
- DCHECK(element.GetLayoutObject());
- DCHECK(element.GetLayoutObject()->HasLayer());
+base::Optional<CompositorElementId> GetCompositorScrollElementId(
+ const Node& node) {
+ if (!node.GetLayoutObject() || !node.GetLayoutObject()->UniqueId())
+ return base::nullopt;
return CompositorElementIdFromUniqueObjectId(
- element.GetLayoutObject()->UniqueId(),
+ node.GetLayoutObject()->UniqueId(),
CompositorElementIdNamespace::kScroll);
}
@@ -148,18 +155,22 @@ std::unique_ptr<CompositorScrollTimeline> ToCompositorScrollTimeline(
return nullptr;
ScrollTimeline* scroll_timeline = ToScrollTimeline(timeline);
- Element* scroll_source = scroll_timeline->scrollSource();
- CompositorElementId element_id = GetCompositorScrollElementId(*scroll_source);
+ Node* scroll_source = scroll_timeline->ResolvedScrollSource();
+ base::Optional<CompositorElementId> element_id =
+ GetCompositorScrollElementId(*scroll_source);
DoubleOrScrollTimelineAutoKeyword time_range;
scroll_timeline->timeRange(time_range);
// TODO(smcgruer): Handle 'auto' time range value.
DCHECK(time_range.IsDouble());
+ // TODO(smcgruer): If the scroll source later gets a LayoutBox (e.g. was
+ // display:none and now isn't), we need to update the compositor with the
+ // writing mode to get the correct ScrollDirection conversion.
LayoutBox* box = scroll_source->GetLayoutBox();
- DCHECK(box);
- CompositorScrollTimeline::ScrollDirection orientation = ConvertOrientation(
- scroll_timeline->GetOrientation(), box->IsHorizontalWritingMode());
+ CompositorScrollTimeline::ScrollDirection orientation =
+ ConvertOrientation(scroll_timeline->GetOrientation(),
+ box ? box->IsHorizontalWritingMode() : true);
return std::make_unique<CompositorScrollTimeline>(element_id, orientation,
time_range.GetAsDouble());
@@ -190,21 +201,25 @@ unsigned NextSequenceNumber() {
} // namespace
WorkletAnimation* WorkletAnimation::Create(
+ ScriptState* script_state,
String animator_name,
const AnimationEffectOrAnimationEffectSequence& effects,
ExceptionState& exception_state) {
- return Create(animator_name, effects, DocumentTimelineOrScrollTimeline(),
- nullptr, exception_state);
+ return Create(script_state, animator_name, effects,
+ DocumentTimelineOrScrollTimeline(), nullptr, exception_state);
}
WorkletAnimation* WorkletAnimation::Create(
+ ScriptState* script_state,
String animator_name,
const AnimationEffectOrAnimationEffectSequence& effects,
DocumentTimelineOrScrollTimeline timeline,
ExceptionState& exception_state) {
- return Create(animator_name, effects, timeline, nullptr, exception_state);
+ return Create(script_state, animator_name, effects, timeline, nullptr,
+ exception_state);
}
WorkletAnimation* WorkletAnimation::Create(
+ ScriptState* script_state,
String animator_name,
const AnimationEffectOrAnimationEffectSequence& effects,
DocumentTimelineOrScrollTimeline timeline,
@@ -214,7 +229,7 @@ WorkletAnimation* WorkletAnimation::Create(
if (!Platform::Current()->IsThreadedAnimationEnabled()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"AnimationWorklet requires threaded animations to be enabled");
return nullptr;
}
@@ -222,39 +237,49 @@ WorkletAnimation* WorkletAnimation::Create(
HeapVector<Member<KeyframeEffect>> keyframe_effects;
String error_string;
if (!ConvertAnimationEffects(effects, keyframe_effects, error_string)) {
- exception_state.ThrowDOMException(kNotSupportedError, error_string);
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ error_string);
return nullptr;
}
if (!ValidateTimeline(timeline, error_string)) {
- exception_state.ThrowDOMException(kNotSupportedError, error_string);
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ error_string);
return nullptr;
}
+ AnimationWorklet* worklet =
+ CSSAnimationWorklet::animationWorklet(script_state);
+
+ WorkletAnimationId id = worklet->NextWorkletAnimationId();
+
Document& document = keyframe_effects.at(0)->target()->GetDocument();
AnimationTimeline* animation_timeline =
ConvertAnimationTimeline(document, timeline);
WorkletAnimation* animation =
- new WorkletAnimation(animator_name, document, keyframe_effects,
+ new WorkletAnimation(id, animator_name, document, keyframe_effects,
animation_timeline, std::move(options));
return animation;
}
WorkletAnimation::WorkletAnimation(
+ WorkletAnimationId id,
const String& animator_name,
Document& document,
const HeapVector<Member<KeyframeEffect>>& effects,
AnimationTimeline* timeline,
scoped_refptr<SerializedScriptValue> options)
: sequence_number_(NextSequenceNumber()),
+ id_(id),
animator_name_(animator_name),
play_state_(Animation::kIdle),
document_(document),
effects_(effects),
timeline_(timeline),
- options_(std::move(options)) {
+ options_(std::make_unique<WorkletAnimationOptions>(options)),
+ effect_needs_restart_(false) {
DCHECK(IsMainThread());
DCHECK(Platform::Current()->IsThreadedAnimationEnabled());
@@ -319,6 +344,7 @@ void WorkletAnimation::UpdateIfNecessary() {
}
void WorkletAnimation::EffectInvalidated() {
+ effect_needs_restart_ = true;
document_->GetWorkletAnimationController().InvalidateAnimation(*this);
}
@@ -378,13 +404,6 @@ bool WorkletAnimation::StartOnCompositor(String* failure_message) {
return false;
}
- if (timeline_->IsScrollTimeline() &&
- !CheckElementComposited(*ToScrollTimeline(timeline_)->scrollSource())) {
- if (failure_message)
- *failure_message = "The ScrollTimeline scrollSource is not composited.";
- return false;
- }
-
double playback_rate = 1;
CompositorAnimations::FailureCode failure_code =
GetEffect()->CheckCanStartAnimationOnCompositor(playback_rate);
@@ -398,7 +417,8 @@ bool WorkletAnimation::StartOnCompositor(String* failure_message) {
if (!compositor_animation_) {
compositor_animation_ = CompositorAnimation::CreateWorkletAnimation(
- animator_name_, ToCompositorScrollTimeline(timeline_));
+ id_, animator_name_, ToCompositorScrollTimeline(timeline_),
+ std::move(options_));
compositor_animation_->SetAnimationDelegate(this);
}
@@ -424,11 +444,20 @@ bool WorkletAnimation::StartOnCompositor(String* failure_message) {
}
void WorkletAnimation::UpdateOnCompositor() {
- // We want to update the keyframe effect on compositor animation without
- // destroying the compositor animation instance. This is achieved by
- // canceling, and start the blink keyframe effect on compositor.
- GetEffect()->CancelAnimationOnCompositor(compositor_animation_.get());
- StartEffectOnCompositor(compositor_animation_.get(), GetEffect());
+ if (effect_needs_restart_) {
+ // We want to update the keyframe effect on compositor animation without
+ // destroying the compositor animation instance. This is achieved by
+ // canceling, and start the blink keyframe effect on compositor.
+ effect_needs_restart_ = false;
+ GetEffect()->CancelAnimationOnCompositor(compositor_animation_.get());
+ StartEffectOnCompositor(compositor_animation_.get(), GetEffect());
+ }
+
+ if (timeline_->IsScrollTimeline()) {
+ Element* scroll_source = ToScrollTimeline(timeline_)->scrollSource();
+ compositor_animation_->UpdateScrollTimelineId(
+ GetCompositorScrollElementId(*scroll_source));
+ }
}
void WorkletAnimation::DestroyCompositorAnimation() {
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.h b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.h
index 922011f1dce..c9977fd5a38 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.h
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.h
@@ -6,20 +6,22 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_WORKLET_ANIMATION_H_
#include "base/optional.h"
-#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/modules/v8/document_timeline_or_scroll_timeline.h"
#include "third_party/blink/renderer/core/animation/animation.h"
#include "third_party/blink/renderer/core/animation/animation_effect_owner.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect.h"
#include "third_party/blink/renderer/core/animation/worklet_animation_base.h"
+#include "third_party/blink/renderer/modules/animationworklet/worklet_animation_options.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_client.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_delegate.h"
+#include "third_party/blink/renderer/platform/graphics/compositor_animators_state.h"
namespace blink {
class AnimationEffectOrAnimationEffectSequence;
+class SerializedScriptValue;
// The main-thread controller for a single AnimationWorklet animator instance.
//
@@ -42,15 +44,18 @@ class MODULES_EXPORT WorkletAnimation : public WorkletAnimationBase,
public:
static WorkletAnimation* Create(
+ ScriptState*,
String animator_name,
const AnimationEffectOrAnimationEffectSequence&,
ExceptionState&);
static WorkletAnimation* Create(
+ ScriptState*,
String animator_name,
const AnimationEffectOrAnimationEffectSequence&,
DocumentTimelineOrScrollTimeline,
ExceptionState&);
static WorkletAnimation* Create(
+ ScriptState*,
String animator_name,
const AnimationEffectOrAnimationEffectSequence&,
DocumentTimelineOrScrollTimeline,
@@ -97,15 +102,16 @@ class MODULES_EXPORT WorkletAnimation : public WorkletAnimationBase,
void Dispose();
Document* GetDocument() const override { return document_.Get(); }
+ AnimationTimeline* GetTimeline() const override { return timeline_; }
const String& Name() { return animator_name_; }
- const scoped_refptr<SerializedScriptValue> Options() { return options_; }
KeyframeEffect* GetEffect() const override;
void Trace(blink::Visitor*) override;
private:
- WorkletAnimation(const String& animator_name,
+ WorkletAnimation(WorkletAnimationId id,
+ const String& animator_name,
Document&,
const HeapVector<Member<KeyframeEffect>>&,
AnimationTimeline*,
@@ -122,6 +128,8 @@ class MODULES_EXPORT WorkletAnimation : public WorkletAnimationBase,
unsigned sequence_number_;
+ WorkletAnimationId id_;
+
const String animator_name_;
Animation::AnimationPlayState play_state_;
// Start time in ms.
@@ -131,9 +139,15 @@ class MODULES_EXPORT WorkletAnimation : public WorkletAnimationBase,
HeapVector<Member<KeyframeEffect>> effects_;
Member<AnimationTimeline> timeline_;
- scoped_refptr<SerializedScriptValue> options_;
+ std::unique_ptr<WorkletAnimationOptions> options_;
std::unique_ptr<CompositorAnimation> compositor_animation_;
+
+ // Tracks whether any KeyframeEffect associated with this WorkletAnimation has
+ // been invalidated and needs to be restarted. Used to avoid unnecessarily
+ // restarting the effect on the compositor. When true, a call to
+ // |UpdateOnCompositor| will update the effect on the compositor.
+ bool effect_needs_restart_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.idl b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.idl
index da6688aaf76..675fec20c1f 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.idl
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation.idl
@@ -12,6 +12,7 @@
optional (DocumentTimeline or ScrollTimeline) timeline,
optional SerializedScriptValue options),
RaisesException=Constructor,
+ ConstructorCallWith=ScriptState,
MeasureAs=WorkletAnimationConstructor,
OriginTrialEnabled=AnimationWorklet
] interface WorkletAnimation {
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_options.cc b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_options.cc
new file mode 100644
index 00000000000..e6c5bdcc316
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_options.cc
@@ -0,0 +1,21 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/animationworklet/worklet_animation_options.h"
+
+#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
+
+namespace blink {
+
+WorkletAnimationOptions::WorkletAnimationOptions(
+ scoped_refptr<SerializedScriptValue> data)
+ : data_(data) {}
+
+std::unique_ptr<cc::AnimationOptions> WorkletAnimationOptions::Clone() const {
+ return std::make_unique<WorkletAnimationOptions>(this->data_);
+}
+
+WorkletAnimationOptions::~WorkletAnimationOptions() {}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_options.h b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_options.h
new file mode 100644
index 00000000000..900405f5bba
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_options.h
@@ -0,0 +1,30 @@
+// 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_MODULES_ANIMATIONWORKLET_WORKLET_ANIMATION_OPTIONS_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_WORKLET_ANIMATION_OPTIONS_H_
+
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/animation/compositor_animation.h"
+
+namespace blink {
+
+class SerializedScriptValue;
+
+class MODULES_EXPORT WorkletAnimationOptions final
+ : public cc::AnimationOptions {
+ public:
+ explicit WorkletAnimationOptions(scoped_refptr<SerializedScriptValue>);
+ std::unique_ptr<cc::AnimationOptions> Clone() const override;
+
+ scoped_refptr<SerializedScriptValue> GetData() { return data_; };
+ ~WorkletAnimationOptions() override;
+
+ private:
+ scoped_refptr<SerializedScriptValue> data_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_ANIMATIONWORKLET_WORKLET_ANIMATION_OPTIONS_H_
diff --git a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_test.cc b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_test.cc
index c496d0f2c50..a52b949a720 100644
--- a/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_test.cc
+++ b/chromium/third_party/blink/renderer/modules/animationworklet/worklet_animation_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/animationworklet/worklet_animation.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/modules/v8/animation_effect_or_animation_effect_sequence.h"
#include "third_party/blink/renderer/core/animation/element_animations.h"
#include "third_party/blink/renderer/core/animation/keyframe_effect.h"
@@ -39,15 +40,19 @@ KeyframeEffect* CreateKeyframeEffect(Element* element) {
return KeyframeEffect::Create(element, CreateEffectModel(), timing);
}
-WorkletAnimation* CreateWorkletAnimation(Element* element) {
+WorkletAnimation* CreateWorkletAnimation(ScriptState* script_state,
+ Element* element) {
AnimationEffectOrAnimationEffectSequence effects;
AnimationEffect* effect = CreateKeyframeEffect(element);
effects.SetAnimationEffect(effect);
DocumentTimelineOrScrollTimeline timeline;
scoped_refptr<SerializedScriptValue> options;
+
+ ScriptState::Scope scope(script_state);
DummyExceptionStateForTesting exception_state;
- return WorkletAnimation::Create("WorkletAnimation", effects, timeline,
- std::move(options), exception_state);
+ return WorkletAnimation::Create(script_state, "WorkletAnimation", effects,
+ timeline, std::move(options),
+ exception_state);
}
} // namespace
@@ -60,7 +65,11 @@ class WorkletAnimationTest : public RenderingTest {
void SetUp() override {
RenderingTest::SetUp();
element_ = GetDocument().CreateElementForBinding("test");
- worklet_animation_ = CreateWorkletAnimation(element_);
+ worklet_animation_ = CreateWorkletAnimation(GetScriptState(), element_);
+ }
+
+ ScriptState* GetScriptState() {
+ return ToScriptStateForMainWorld(&GetFrame());
}
Persistent<Element> element_;
diff --git a/chromium/third_party/blink/renderer/modules/app_banner/app_banner_controller.cc b/chromium/third_party/blink/renderer/modules/app_banner/app_banner_controller.cc
index 0ae59ff91de..b747c915b81 100644
--- a/chromium/third_party/blink/renderer/modules/app_banner/app_banner_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/app_banner/app_banner_controller.cc
@@ -34,6 +34,7 @@ void AppBannerController::BannerPromptRequest(
mojom::blink::AppBannerServicePtr service_ptr,
mojom::blink::AppBannerEventRequest event_request,
const Vector<String>& platforms,
+ bool require_gesture,
BannerPromptRequestCallback callback) {
if (!frame_ || !frame_->GetDocument()) {
std::move(callback).Run(mojom::blink::AppBannerPromptReply::NONE, "");
@@ -43,7 +44,7 @@ void AppBannerController::BannerPromptRequest(
mojom::AppBannerPromptReply reply =
frame_->DomWindow()->DispatchEvent(BeforeInstallPromptEvent::Create(
EventTypeNames::beforeinstallprompt, *frame_, std::move(service_ptr),
- std::move(event_request), platforms)) ==
+ std::move(event_request), platforms, require_gesture)) ==
DispatchEventResult::kNotCanceled
? mojom::AppBannerPromptReply::NONE
: mojom::AppBannerPromptReply::CANCEL;
diff --git a/chromium/third_party/blink/renderer/modules/app_banner/app_banner_controller.h b/chromium/third_party/blink/renderer/modules/app_banner/app_banner_controller.h
index 58abec236d8..144b2607cea 100644
--- a/chromium/third_party/blink/renderer/modules/app_banner/app_banner_controller.h
+++ b/chromium/third_party/blink/renderer/modules/app_banner/app_banner_controller.h
@@ -26,6 +26,7 @@ class MODULES_EXPORT AppBannerController final
void BannerPromptRequest(mojom::blink::AppBannerServicePtr,
mojom::blink::AppBannerEventRequest,
const Vector<String>& platforms,
+ bool require_gesture,
BannerPromptRequestCallback) override;
private:
diff --git a/chromium/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.cc b/chromium/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.cc
index c3a49868a4a..4b13f92e3d4 100644
--- a/chromium/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.cc
+++ b/chromium/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.cc
@@ -6,7 +6,6 @@
#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/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/modules/app_banner/before_install_prompt_event_init.h"
@@ -18,7 +17,8 @@ BeforeInstallPromptEvent::BeforeInstallPromptEvent(
LocalFrame& frame,
mojom::blink::AppBannerServicePtr service_ptr,
mojom::blink::AppBannerEventRequest event_request,
- const Vector<String>& platforms)
+ const Vector<String>& platforms,
+ bool require_gesture)
: Event(name, Bubbles::kNo, Cancelable::kYes),
ContextClient(&frame),
banner_service_(std::move(service_ptr)),
@@ -27,7 +27,7 @@ BeforeInstallPromptEvent::BeforeInstallPromptEvent(
user_choice_(new UserChoiceProperty(frame.GetDocument(),
this,
UserChoiceProperty::kUserChoice)),
- prompt_called_(false) {
+ require_gesture_(require_gesture) {
DCHECK(banner_service_);
DCHECK(binding_.is_bound());
UseCounter::Count(&frame, WebFeature::kBeforeInstallPromptEvent);
@@ -40,7 +40,7 @@ BeforeInstallPromptEvent::BeforeInstallPromptEvent(
: Event(name, init),
ContextClient(execution_context),
binding_(this),
- prompt_called_(false) {
+ require_gesture_(true) {
if (init.hasPlatforms())
platforms_ = init.platforms();
}
@@ -65,27 +65,33 @@ ScriptPromise BeforeInstallPromptEvent::userChoice(ScriptState* script_state) {
return user_choice_->Promise(script_state->World());
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kInvalidStateError,
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
"userChoice cannot be accessed on this event."));
}
ScriptPromise BeforeInstallPromptEvent::prompt(ScriptState* script_state) {
// |m_bannerService| must be bound to allow us to inform the AppBannerService
// to display the banner now.
- if (prompt_called_ || !banner_service_.is_bound()) {
+ if (!banner_service_.is_bound()) {
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kInvalidStateError,
- "The prompt() method may only be called once."));
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "The prompt() method cannot be called."));
}
ExecutionContext* context = ExecutionContext::From(script_state);
- UseCounter::Count(context, WebFeature::kBeforeInstallPromptEventPrompt);
-
Document* doc = ToDocumentOrNull(context);
- prompt_called_ = true;
- banner_service_->DisplayAppBanner(
- Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr));
+ if (require_gesture_ &&
+ !Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr)) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state,
+ DOMException::Create(
+ DOMExceptionCode::kNotAllowedError,
+ "The prompt() method must be called with a user gesture"));
+ }
+
+ UseCounter::Count(context, WebFeature::kBeforeInstallPromptEventPrompt);
+ banner_service_->DisplayAppBanner();
return ScriptPromise::CastUndefined(script_state);
}
diff --git a/chromium/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.h b/chromium/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.h
index e0abec22411..58fb4e91f19 100644
--- a/chromium/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.h
+++ b/chromium/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.h
@@ -43,9 +43,11 @@ class BeforeInstallPromptEvent final
LocalFrame& frame,
mojom::blink::AppBannerServicePtr service_ptr,
mojom::blink::AppBannerEventRequest event_request,
- const Vector<String>& platforms) {
+ const Vector<String>& platforms,
+ bool require_gesture) {
return new BeforeInstallPromptEvent(name, frame, std::move(service_ptr),
- std::move(event_request), platforms);
+ std::move(event_request), platforms,
+ require_gesture);
}
static BeforeInstallPromptEvent* Create(
@@ -74,7 +76,8 @@ class BeforeInstallPromptEvent final
LocalFrame&,
mojom::blink::AppBannerServicePtr,
mojom::blink::AppBannerEventRequest,
- const Vector<String>& platforms);
+ const Vector<String>& platforms,
+ bool require_gesture);
BeforeInstallPromptEvent(ExecutionContext*,
const AtomicString& name,
const BeforeInstallPromptEventInit&);
@@ -87,7 +90,10 @@ class BeforeInstallPromptEvent final
mojo::Binding<mojom::blink::AppBannerEvent> binding_;
Vector<String> platforms_;
Member<UserChoiceProperty> user_choice_;
- bool prompt_called_;
+
+ // TODO(crbug.com/869780): remove this member when the ExperimentalAppBanners
+ // feature is removed.
+ bool require_gesture_;
};
DEFINE_TYPE_CASTS(BeforeInstallPromptEvent,
diff --git a/chromium/third_party/blink/renderer/modules/audio_output_devices/audio_output_device_client_impl.cc b/chromium/third_party/blink/renderer/modules/audio_output_devices/audio_output_device_client_impl.cc
index ef9b45e7425..7eb90d424ed 100644
--- a/chromium/third_party/blink/renderer/modules/audio_output_devices/audio_output_device_client_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/audio_output_devices/audio_output_device_client_impl.cc
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/modules/audio_output_devices/audio_output_device_client_impl.h"
#include <memory>
-#include "third_party/blink/public/web/web_frame_client.h"
+#include "third_party/blink/public/web/web_local_frame_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/frame/web_local_frame_impl.h"
diff --git a/chromium/third_party/blink/renderer/modules/audio_output_devices/html_media_element_audio_output_device.cc b/chromium/third_party/blink/renderer/modules/audio_output_devices/html_media_element_audio_output_device.cc
index 91cd9385816..d14d53257ee 100644
--- a/chromium/third_party/blink/renderer/modules/audio_output_devices/html_media_element_audio_output_device.cc
+++ b/chromium/third_party/blink/renderer/modules/audio_output_devices/html_media_element_audio_output_device.cc
@@ -87,7 +87,7 @@ void SetSinkIdResolver::TimerFired(TimerBase* timer) {
// check.
DCHECK(context->IsContextDestroyed());
Reject(DOMException::Create(
- kSecurityError,
+ DOMExceptionCode::kSecurityError,
"Impossible to authorize device for detached context"));
}
}
diff --git a/chromium/third_party/blink/renderer/modules/audio_output_devices/html_media_element_audio_output_device.h b/chromium/third_party/blink/renderer/modules/audio_output_devices/html_media_element_audio_output_device.h
index 46e09a17db0..3920b7781f1 100644
--- a/chromium/third_party/blink/renderer/modules/audio_output_devices/html_media_element_audio_output_device.h
+++ b/chromium/third_party/blink/renderer/modules/audio_output_devices/html_media_element_audio_output_device.h
@@ -7,7 +7,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
diff --git a/chromium/third_party/blink/renderer/modules/audio_output_devices/set_sink_id_callbacks.cc b/chromium/third_party/blink/renderer/modules/audio_output_devices/set_sink_id_callbacks.cc
index 742adb8c6ca..557d26f4d2f 100644
--- a/chromium/third_party/blink/renderer/modules/audio_output_devices/set_sink_id_callbacks.cc
+++ b/chromium/third_party/blink/renderer/modules/audio_output_devices/set_sink_id_callbacks.cc
@@ -15,19 +15,22 @@ namespace {
DOMException* ToException(WebSetSinkIdError error) {
switch (error) {
case WebSetSinkIdError::kNotFound:
- return DOMException::Create(kNotFoundError, "Requested device not found");
+ return DOMException::Create(DOMExceptionCode::kNotFoundError,
+ "Requested device not found");
case WebSetSinkIdError::kNotAuthorized:
- return DOMException::Create(kSecurityError,
+ return DOMException::Create(DOMExceptionCode::kSecurityError,
"No permission to use requested device");
case WebSetSinkIdError::kAborted:
return DOMException::Create(
- kAbortError, "The operation could not be performed and was aborted");
+ DOMExceptionCode::kAbortError,
+ "The operation could not be performed and was aborted");
case WebSetSinkIdError::kNotSupported:
- return DOMException::Create(kNotSupportedError,
+ return DOMException::Create(DOMExceptionCode::kNotSupportedError,
"Operation not supported");
default:
NOTREACHED();
- return DOMException::Create(kAbortError, "Invalid error code");
+ return DOMException::Create(DOMExceptionCode::kAbortError,
+ "Invalid error code");
}
}
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc
index 30200363316..2ed7682ebcf 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc
@@ -6,12 +6,12 @@
#include <utility>
#include "services/service_manager/public/cpp/interface_provider.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_registration.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_request.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_registration.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_options.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_registration.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.h"
-#include "third_party/blink/renderer/modules/background_fetch/icon_definition.h"
+#include "third_party/blink/renderer/modules/manifest/image_resource.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h
index ed7eb8baf25..652f8ff66bb 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h
@@ -7,7 +7,7 @@
#include <memory>
#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom-blink.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.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/functional.h"
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_event.h b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_event.h
index b418a872042..19d07114b9b 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_event.h
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_event.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BACKGROUND_FETCH_BACKGROUND_FETCH_EVENT_H_
#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/modules/serviceworkers/extendable_event.h"
+#include "third_party/blink/renderer/modules/service_worker/extendable_event.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.cc b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.cc
index ff6b1b86112..3c346b726be 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.cc
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.cc
@@ -10,7 +10,7 @@
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/loader/threadable_loader.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h"
-#include "third_party/blink/renderer/modules/background_fetch/icon_definition.h"
+#include "third_party/blink/renderer/modules/manifest/image_resource.h"
#include "third_party/blink/renderer/platform/graphics/color_behavior.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
@@ -40,7 +40,7 @@ BackgroundFetchIconLoader::~BackgroundFetchIconLoader() {
void BackgroundFetchIconLoader::Start(BackgroundFetchBridge* bridge,
ExecutionContext* execution_context,
- HeapVector<IconDefinition> icons,
+ HeapVector<ManifestImageResource> icons,
IconCallback icon_callback) {
DCHECK(!stopped_);
DCHECK_GE(icons.size(), 1u);
@@ -139,7 +139,7 @@ int BackgroundFetchIconLoader::PickBestIconForDisplay(
//
// Note: If this is an ico file containing multiple sizes, return the best
// score.
-double BackgroundFetchIconLoader::GetIconScore(IconDefinition icon,
+double BackgroundFetchIconLoader::GetIconScore(ManifestImageResource icon,
const int ideal_size) {
// Extract sizes from the icon definition, expressed as "<width>x<height>
// <width>x<height> ...."
@@ -206,9 +206,10 @@ void BackgroundFetchIconLoader::DidFinishLoading(
return;
if (data_) {
// Decode data.
+ const bool data_complete = true;
std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
- data_, true /* data_complete*/, ImageDecoder::kAlphaPremultiplied,
- ColorBehavior::TransformToSRGB());
+ data_, data_complete, ImageDecoder::kAlphaPremultiplied,
+ ImageDecoder::kDefaultBitDepth, ColorBehavior::TransformToSRGB());
if (decoder) {
// the |ImageFrame*| is owned by the decoder.
ImageFrame* image_frame = decoder->DecodeFrameBufferAtIndex(0);
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h
index 1f4a3f786e3..400dc73c7f2 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h
@@ -10,6 +10,7 @@
#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/modules/background_fetch/background_fetch_type_converters.h"
+#include "third_party/blink/renderer/modules/manifest/image_resource.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -17,7 +18,6 @@
namespace blink {
class BackgroundFetchBridge;
-class IconDefinition;
struct WebSize;
class MODULES_EXPORT BackgroundFetchIconLoader final
@@ -39,7 +39,7 @@ class MODULES_EXPORT BackgroundFetchIconLoader final
// data, and passes the bitmap to the given callback.
void Start(BackgroundFetchBridge* bridge,
ExecutionContext* execution_context,
- HeapVector<IconDefinition>,
+ HeapVector<ManifestImageResource> icons,
IconCallback callback);
// Cancels the pending load, if there is one. The |icon_callback_| will not
@@ -75,12 +75,12 @@ class MODULES_EXPORT BackgroundFetchIconLoader final
// Get a score for the given icon, based on ideal_size. The icon with the
// highest score is chosen.
- double GetIconScore(IconDefinition icon, const int ideal_size);
+ double GetIconScore(ManifestImageResource icon, const int ideal_size);
bool stopped_ = false;
scoped_refptr<SharedBuffer> data_;
IconCallback icon_callback_;
- HeapVector<IconDefinition> icons_;
+ HeapVector<ManifestImageResource> icons_;
Member<ThreadableLoader> threadable_loader_;
};
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader_test.cc b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader_test.cc
index c15f676a419..df73355f7ad 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader_test.cc
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader_test.cc
@@ -2,14 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LiICENSE file.
+#include "third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h"
+
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
-#include "third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h"
-#include "third_party/blink/renderer/modules/background_fetch/icon_definition.h"
+#include "third_party/blink/renderer/modules/manifest/image_resource.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
@@ -63,27 +64,28 @@ class BackgroundFetchIconLoaderTest : public PageTestBase {
loaded_ = BackgroundFetchLoadState::kLoadFailed;
}
- IconDefinition CreateTestIcon(const String& url_str, const String& size) {
+ ManifestImageResource CreateTestIcon(const String& url_str,
+ const String& size) {
KURL url = RegisterMockedURL(url_str);
- IconDefinition icon;
+ ManifestImageResource icon;
icon.setSrc(url.GetString());
icon.setType("image/png");
icon.setSizes(size);
return icon;
}
- int PickRightIcon(HeapVector<IconDefinition> icons,
+ int PickRightIcon(HeapVector<ManifestImageResource> icons,
const WebSize& ideal_display_size) {
loader_->icons_ = std::move(icons);
return loader_->PickBestIconForDisplay(GetContext(), ideal_display_size);
}
void LoadIcon(const KURL& url) {
- IconDefinition icon;
+ ManifestImageResource icon;
icon.setSrc(url.GetString());
icon.setType("image/png");
icon.setSizes("500x500");
- HeapVector<IconDefinition> icons(1, icon);
+ HeapVector<ManifestImageResource> icons(1, icon);
loader_->icons_ = std::move(icons);
loader_->DidGetIconDisplaySizeIfSoLoadIcon(
GetContext(),
@@ -109,14 +111,14 @@ TEST_F(BackgroundFetchIconLoaderTest, SuccessTest) {
}
TEST_F(BackgroundFetchIconLoaderTest, PickRightIconTest) {
- IconDefinition icon0 =
+ ManifestImageResource icon0 =
CreateTestIcon(kBackgroundFetchImageLoaderIcon500x500, "500x500");
- IconDefinition icon1 =
+ ManifestImageResource icon1 =
CreateTestIcon(kBackgroundFetchImageLoaderIcon48x48, "48x48");
- IconDefinition icon2 =
+ ManifestImageResource icon2 =
CreateTestIcon(kBackgroundFetchImageLoaderIcon3000x2000, "3000x2000");
- HeapVector<IconDefinition> icons;
+ HeapVector<ManifestImageResource> icons;
icons.push_back(icon0);
icons.push_back(icon1);
icons.push_back(icon2);
@@ -126,13 +128,14 @@ TEST_F(BackgroundFetchIconLoaderTest, PickRightIconTest) {
}
TEST_F(BackgroundFetchIconLoaderTest, PickRightIconGivenAnyTest) {
- IconDefinition icon0 =
+ ManifestImageResource icon0 =
CreateTestIcon(kBackgroundFetchImageLoaderIcon500x500, "500x500");
- IconDefinition icon1 =
+ ManifestImageResource icon1 =
CreateTestIcon(kBackgroundFetchImageLoaderIcon48x48, "48x48");
- IconDefinition icon2 = CreateTestIcon(kBackgroundFetchImageLoaderIcon, "any");
+ ManifestImageResource icon2 =
+ CreateTestIcon(kBackgroundFetchImageLoaderIcon, "any");
- HeapVector<IconDefinition> icons;
+ HeapVector<ManifestImageResource> icons;
icons.push_back(icon0);
icons.push_back(icon1);
icons.push_back(icon2);
@@ -144,13 +147,13 @@ TEST_F(BackgroundFetchIconLoaderTest, PickRightIconGivenAnyTest) {
TEST_F(BackgroundFetchIconLoaderTest, PickRightIconWithTieBreakTest) {
// Test that if two icons get the same score, the one declared last gets
// picked.
- IconDefinition icon0 =
+ ManifestImageResource icon0 =
CreateTestIcon(kBackgroundFetchImageLoaderIcon500x500, "500x500");
- IconDefinition icon1 =
+ ManifestImageResource icon1 =
CreateTestIcon(kBackgroundFetchImageLoaderIcon48x48, "48x48");
- IconDefinition icon2 =
+ ManifestImageResource icon2 =
CreateTestIcon(kBackgroundFetchImageLoaderIcon3000x2000, "48x48");
- HeapVector<IconDefinition> icons;
+ HeapVector<ManifestImageResource> icons;
icons.push_back(icon0);
icons.push_back(icon1);
icons.push_back(icon2);
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc
index 133b32501b5..04edc0b08dc 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc
@@ -4,12 +4,11 @@
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_manager.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_request.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h"
#include "third_party/blink/renderer/bindings/core/v8/request_or_usv_string.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/modules/v8/request_or_usv_string_or_request_or_usv_string_sequence.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/fetch/request.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
@@ -20,7 +19,7 @@
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_options.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_registration.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.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/loader/cors/cors.h"
@@ -296,13 +295,19 @@ void BackgroundFetchManager::DidFetch(
case mojom::blink::BackgroundFetchError::DUPLICATED_DEVELOPER_ID:
DCHECK(!registration);
resolver->Reject(DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"There already is a registration for the given id."));
return;
case mojom::blink::BackgroundFetchError::STORAGE_ERROR:
DCHECK(!registration);
resolver->Reject(DOMException::Create(
- kAbortError, "Failed to store registration due to I/O error."));
+ DOMExceptionCode::kAbortError,
+ "Failed to store registration due to I/O error."));
+ return;
+ case mojom::blink::BackgroundFetchError::SERVICE_WORKER_UNAVAILABLE:
+ resolver->Reject(DOMException::Create(
+ DOMExceptionCode::kInvalidStateError,
+ "There is no service worker available to service the fetch."));
return;
case mojom::blink::BackgroundFetchError::INVALID_ARGUMENT:
case mojom::blink::BackgroundFetchError::INVALID_ID:
@@ -403,8 +408,14 @@ void BackgroundFetchManager::DidGetRegistration(
return;
case mojom::blink::BackgroundFetchError::STORAGE_ERROR:
DCHECK(!registration);
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kAbortError,
+ "Failed to get registration due to I/O error."));
+ return;
+ case mojom::blink::BackgroundFetchError::SERVICE_WORKER_UNAVAILABLE:
resolver->Reject(DOMException::Create(
- kAbortError, "Failed to get registration due to I/O error."));
+ DOMExceptionCode::kInvalidStateError,
+ "There's no service worker available to service the fetch."));
return;
case mojom::blink::BackgroundFetchError::DUPLICATED_DEVELOPER_ID:
case mojom::blink::BackgroundFetchError::INVALID_ARGUMENT:
@@ -445,11 +456,13 @@ void BackgroundFetchManager::DidGetDeveloperIds(
case mojom::blink::BackgroundFetchError::STORAGE_ERROR:
DCHECK(developer_ids.IsEmpty());
resolver->Reject(DOMException::Create(
- kAbortError, "Failed to get registration IDs due to I/O error."));
+ DOMExceptionCode::kAbortError,
+ "Failed to get registration IDs due to I/O error."));
return;
case mojom::blink::BackgroundFetchError::DUPLICATED_DEVELOPER_ID:
case mojom::blink::BackgroundFetchError::INVALID_ARGUMENT:
case mojom::blink::BackgroundFetchError::INVALID_ID:
+ case mojom::blink::BackgroundFetchError::SERVICE_WORKER_UNAVAILABLE:
// Not applicable for this callback.
break;
}
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_manager_test.cc b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_manager_test.cc
index ed6efe5ee22..c962f63da35 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_manager_test.cc
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_manager_test.cc
@@ -5,15 +5,14 @@
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_request.h"
-#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h"
#include "third_party/blink/renderer/bindings/core/v8/request_or_usv_string.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/modules/v8/request_or_usv_string_or_request_or_usv_string_sequence.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/fetch/request.h"
+#include "third_party/blink/renderer/core/fetch/request_init.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
@@ -29,20 +28,6 @@ class BackgroundFetchManagerTest : public testing::Test {
return BackgroundFetchManager::CreateWebRequestVector(
scope.GetScriptState(), requests, scope.GetExceptionState());
}
-
- // Returns a Dictionary object that represents a JavaScript dictionary with
- // a single key-value pair, where the key always is "method" with the value
- // set to |method|.
- Dictionary GetDictionaryForMethod(V8TestingScope& scope, const char* method) {
- v8::Isolate* isolate = scope.GetIsolate();
- v8::Local<v8::Object> data = v8::Object::New(isolate);
-
- data->Set(isolate->GetCurrentContext(), V8String(isolate, "method"),
- V8String(isolate, method))
- .ToChecked();
-
- return Dictionary(scope.GetIsolate(), data, scope.GetExceptionState());
- }
};
TEST_F(BackgroundFetchManagerTest, NullValue) {
@@ -53,7 +38,8 @@ TEST_F(BackgroundFetchManagerTest, NullValue) {
Vector<WebServiceWorkerRequest> web_requests =
CreateWebRequestVector(scope, requests);
ASSERT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(scope.GetExceptionState().Code(), kV8TypeError);
+ EXPECT_EQ(scope.GetExceptionState().CodeAs<ESErrorType>(),
+ ESErrorType::kTypeError);
}
TEST_F(BackgroundFetchManagerTest, SingleUSVString) {
@@ -81,9 +67,11 @@ TEST_F(BackgroundFetchManagerTest, SingleRequest) {
KURL image_url("https://www.example.com/my_image.png");
- Request* request = Request::Create(
- scope.GetScriptState(), image_url.GetString(),
- GetDictionaryForMethod(scope, "POST"), scope.GetExceptionState());
+ RequestInit request_init;
+ request_init.setMethod("POST");
+ Request* request =
+ Request::Create(scope.GetScriptState(), image_url.GetString(),
+ request_init, scope.GetExceptionState());
ASSERT_FALSE(scope.GetExceptionState().HadException());
ASSERT_TRUE(request);
@@ -113,9 +101,11 @@ TEST_F(BackgroundFetchManagerTest, Sequence) {
RequestOrUSVString icon_request =
RequestOrUSVString::FromUSVString(icon_url.GetString());
- Request* request = Request::Create(
- scope.GetScriptState(), cat_video_url.GetString(),
- GetDictionaryForMethod(scope, "DELETE"), scope.GetExceptionState());
+ RequestInit request_init;
+ request_init.setMethod("DELETE");
+ Request* request =
+ Request::Create(scope.GetScriptState(), cat_video_url.GetString(),
+ request_init, scope.GetExceptionState());
ASSERT_FALSE(scope.GetExceptionState().HadException());
ASSERT_TRUE(request);
@@ -157,7 +147,8 @@ TEST_F(BackgroundFetchManagerTest, SequenceEmpty) {
Vector<WebServiceWorkerRequest> web_requests =
CreateWebRequestVector(scope, requests);
ASSERT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(scope.GetExceptionState().Code(), kV8TypeError);
+ EXPECT_EQ(scope.GetExceptionState().CodeAs<ESErrorType>(),
+ ESErrorType::kTypeError);
}
TEST_F(BackgroundFetchManagerTest, SequenceWithNullValue) {
@@ -180,7 +171,8 @@ TEST_F(BackgroundFetchManagerTest, SequenceWithNullValue) {
Vector<WebServiceWorkerRequest> web_requests =
CreateWebRequestVector(scope, requests);
ASSERT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(scope.GetExceptionState().Code(), kV8TypeError);
+ EXPECT_EQ(scope.GetExceptionState().CodeAs<ESErrorType>(),
+ ESErrorType::kTypeError);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_options.idl b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_options.idl
index 408371e5077..c80d491e1ce 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_options.idl
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_options.idl
@@ -5,7 +5,7 @@
// https://wicg.github.io/background-fetch/#background-fetch-manager
dictionary BackgroundFetchOptions {
- sequence<IconDefinition> icons = [];
+ sequence<ImageResource> icons = [];
DOMString title = "";
[ImplementedAs=downloadTotal] unsigned long long totalDownloadSize = 0;
unsigned long long downloadTotal = 0;
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.cc b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.cc
index 3f735693d1a..15567ad0284 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.cc
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.cc
@@ -7,9 +7,9 @@
#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/modules/background_fetch/background_fetch_bridge.h"
-#include "third_party/blink/renderer/modules/background_fetch/icon_definition.h"
#include "third_party/blink/renderer/modules/event_target_modules_names.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/manifest/image_resource.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
@@ -116,8 +116,10 @@ void BackgroundFetchRegistration::DidAbort(
return;
case mojom::blink::BackgroundFetchError::STORAGE_ERROR:
resolver->Reject(DOMException::Create(
- kAbortError, "Failed to abort registration due to I/O error."));
+ DOMExceptionCode::kAbortError,
+ "Failed to abort registration due to I/O error."));
return;
+ case mojom::blink::BackgroundFetchError::SERVICE_WORKER_UNAVAILABLE:
case mojom::blink::BackgroundFetchError::DUPLICATED_DEVELOPER_ID:
case mojom::blink::BackgroundFetchError::INVALID_ARGUMENT:
// Not applicable for this callback.
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_settled_event.h b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_settled_event.h
index ae477cbca54..ec39d90d81f 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_settled_event.h
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_settled_event.h
@@ -40,7 +40,7 @@ class MODULES_EXPORT BackgroundFetchSettledEvent : public BackgroundFetchEvent {
// Web Exposed attribute defined in the IDL file.
BackgroundFetchSettledFetches* fetches() const;
- void Trace(blink::Visitor*) override;
+ void Trace(blink::Visitor* visitor) override;
protected:
BackgroundFetchSettledEvent(
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_settled_fetches_test.cc b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_settled_fetches_test.cc
index 8df0b9dd7bd..03eca52773a 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_settled_fetches_test.cc
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_settled_fetches_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_settled_fetches.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_function.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/core/fetch/request.h"
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.cc b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.cc
index 0409251cb53..719b38baa80 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.cc
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.cc
@@ -6,6 +6,7 @@
#include <utility>
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_registration.h"
+#include "third_party/blink/renderer/modules/manifest/image_resource_type_converters.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
namespace mojo {
@@ -14,57 +15,36 @@ blink::BackgroundFetchRegistration*
TypeConverter<blink::BackgroundFetchRegistration*,
blink::mojom::blink::BackgroundFetchRegistrationPtr>::
Convert(const blink::mojom::blink::BackgroundFetchRegistrationPtr&
- mojoRegistration) {
- if (!mojoRegistration)
+ mojo_registration) {
+ if (!mojo_registration)
return nullptr;
return new blink::BackgroundFetchRegistration(
- mojoRegistration->developer_id, mojoRegistration->unique_id,
- mojoRegistration->upload_total, mojoRegistration->uploaded,
- mojoRegistration->download_total, mojoRegistration->downloaded);
+ mojo_registration->developer_id, mojo_registration->unique_id,
+ mojo_registration->upload_total, mojo_registration->uploaded,
+ mojo_registration->download_total, mojo_registration->downloaded);
}
blink::mojom::blink::BackgroundFetchOptionsPtr TypeConverter<
blink::mojom::blink::BackgroundFetchOptionsPtr,
blink::BackgroundFetchOptions>::Convert(const blink::BackgroundFetchOptions&
options) {
- blink::mojom::blink::BackgroundFetchOptionsPtr mojoOptions =
+ blink::mojom::blink::BackgroundFetchOptionsPtr mojo_options =
blink::mojom::blink::BackgroundFetchOptions::New();
- WTF::Vector<blink::mojom::blink::IconDefinitionPtr> mojoIcons;
- mojoIcons.ReserveInitialCapacity(options.icons().size());
+ WTF::Vector<blink::mojom::blink::ManifestImageResourcePtr> mojo_icons;
+ mojo_icons.ReserveInitialCapacity(options.icons().size());
- for (const auto& icon : options.icons())
- mojoIcons.push_back(blink::mojom::blink::IconDefinition::From(icon));
+ for (const auto& icon : options.icons()) {
+ mojo_icons.push_back(
+ blink::mojom::blink::ManifestImageResource::From(icon));
+ }
- mojoOptions->icons = std::move(mojoIcons);
- mojoOptions->download_total = options.downloadTotal();
- mojoOptions->title = options.title();
+ mojo_options->icons = std::move(mojo_icons);
+ mojo_options->download_total = options.downloadTotal();
+ mojo_options->title = options.title();
- return mojoOptions;
-}
-
-blink::IconDefinition
-TypeConverter<blink::IconDefinition, blink::mojom::blink::IconDefinitionPtr>::
- Convert(const blink::mojom::blink::IconDefinitionPtr& mojoDefinition) {
- blink::IconDefinition definition;
- definition.setSrc(mojoDefinition->src);
- definition.setSizes(mojoDefinition->sizes);
- definition.setType(mojoDefinition->type);
-
- return definition;
-}
-
-blink::mojom::blink::IconDefinitionPtr TypeConverter<
- blink::mojom::blink::IconDefinitionPtr,
- blink::IconDefinition>::Convert(const blink::IconDefinition& definition) {
- blink::mojom::blink::IconDefinitionPtr mojoDefinition =
- blink::mojom::blink::IconDefinition::New();
- mojoDefinition->src = definition.src();
- mojoDefinition->sizes = definition.sizes();
- mojoDefinition->type = definition.type();
-
- return mojoDefinition;
+ return mojo_options;
}
} // namespace mojo
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.h b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.h
index 3e55cb3b152..3ee7d587555 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.h
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.h
@@ -7,7 +7,6 @@
#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom-blink.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_options.h"
-#include "third_party/blink/renderer/modules/background_fetch/icon_definition.h"
namespace blink {
class BackgroundFetchRegistration;
@@ -19,28 +18,15 @@ template <>
struct TypeConverter<blink::BackgroundFetchRegistration*,
blink::mojom::blink::BackgroundFetchRegistrationPtr> {
static blink::BackgroundFetchRegistration* Convert(
- const blink::mojom::blink::BackgroundFetchRegistrationPtr&);
+ const blink::mojom::blink::BackgroundFetchRegistrationPtr&
+ mojo_registration);
};
template <>
struct TypeConverter<blink::mojom::blink::BackgroundFetchOptionsPtr,
blink::BackgroundFetchOptions> {
static blink::mojom::blink::BackgroundFetchOptionsPtr Convert(
- const blink::BackgroundFetchOptions&);
-};
-
-template <>
-struct TypeConverter<blink::IconDefinition,
- blink::mojom::blink::IconDefinitionPtr> {
- static blink::IconDefinition Convert(
- const blink::mojom::blink::IconDefinitionPtr&);
-};
-
-template <>
-struct TypeConverter<blink::mojom::blink::IconDefinitionPtr,
- blink::IconDefinition> {
- static blink::mojom::blink::IconDefinitionPtr Convert(
- const blink::IconDefinition&);
+ const blink::BackgroundFetchOptions& options);
};
} // namespace mojo
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.cc b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.cc
index 95923c022f6..c1aeb79d544 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.cc
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.cc
@@ -68,11 +68,13 @@ void BackgroundFetchUpdateEvent::DidUpdateUI(
resolver->Resolve();
return;
case mojom::blink::BackgroundFetchError::STORAGE_ERROR:
- resolver->Reject(DOMException::Create(
- kAbortError, "Failed to update UI due to I/O error."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kAbortError,
+ "Failed to update UI due to I/O error."));
return;
case mojom::blink::BackgroundFetchError::DUPLICATED_DEVELOPER_ID:
case mojom::blink::BackgroundFetchError::INVALID_ARGUMENT:
+ case mojom::blink::BackgroundFetchError::SERVICE_WORKER_UNAVAILABLE:
// Not applicable for this callback.
break;
}
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.h b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.h
index be58d52eec8..56832347ef2 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.h
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.h
@@ -7,7 +7,7 @@
#include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom-blink.h"
#include "third_party/blink/renderer/modules/background_fetch/background_fetch_settled_event.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetched_event.cc b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetched_event.cc
index b4dc3409b8e..5416bd27470 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetched_event.cc
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetched_event.cc
@@ -80,9 +80,11 @@ void BackgroundFetchedEvent::DidUpdateUI(
resolver->Resolve();
return;
case mojom::blink::BackgroundFetchError::STORAGE_ERROR:
- resolver->Reject(DOMException::Create(
- kAbortError, "Failed to update UI due to I/O error."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kAbortError,
+ "Failed to update UI due to I/O error."));
return;
+ case mojom::blink::BackgroundFetchError::SERVICE_WORKER_UNAVAILABLE:
case mojom::blink::BackgroundFetchError::DUPLICATED_DEVELOPER_ID:
case mojom::blink::BackgroundFetchError::INVALID_ARGUMENT:
// Not applicable for this callback.
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetched_event.h b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetched_event.h
index bec7eebdc64..d86e7392196 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/background_fetched_event.h
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/background_fetched_event.h
@@ -17,6 +17,7 @@ namespace blink {
class BackgroundFetchSettledFetch;
class BackgroundFetchedEventInit;
+class ScriptPromiseResolver;
class ScriptState;
class ServiceWorkerRegistration;
struct WebBackgroundFetchSettledFetch;
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/icon_definition.idl b/chromium/third_party/blink/renderer/modules/background_fetch/icon_definition.idl
deleted file mode 100644
index 8fc31b5ca86..00000000000
--- a/chromium/third_party/blink/renderer/modules/background_fetch/icon_definition.idl
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://wicg.github.io/background-fetch/#background-fetch-manager
-
-dictionary IconDefinition {
- DOMString src;
- DOMString sizes;
- DOMString type;
-};
diff --git a/chromium/third_party/blink/renderer/modules/background_fetch/service_worker_registration_background_fetch.h b/chromium/third_party/blink/renderer/modules/background_fetch/service_worker_registration_background_fetch.h
index 035c79cbfbf..bcb9929b839 100644
--- a/chromium/third_party/blink/renderer/modules/background_fetch/service_worker_registration_background_fetch.h
+++ b/chromium/third_party/blink/renderer/modules/background_fetch/service_worker_registration_background_fetch.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BACKGROUND_FETCH_SERVICE_WORKER_REGISTRATION_BACKGROUND_FETCH_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BACKGROUND_FETCH_SERVICE_WORKER_REGISTRATION_BACKGROUND_FETCH_H_
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/supplementable.h"
diff --git a/chromium/third_party/blink/renderer/modules/background_sync/DEPS b/chromium/third_party/blink/renderer/modules/background_sync/DEPS
index 60c775126f8..cd9e9340e6d 100644
--- a/chromium/third_party/blink/renderer/modules/background_sync/DEPS
+++ b/chromium/third_party/blink/renderer/modules/background_sync/DEPS
@@ -2,5 +2,5 @@ include_rules = [
"-third_party/blink/renderer/modules",
"+third_party/blink/renderer/modules/background_sync",
"+third_party/blink/renderer/modules/event_modules.h",
- "+third_party/blink/renderer/modules/serviceworkers",
+ "+third_party/blink/renderer/modules/service_worker",
]
diff --git a/chromium/third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.cc b/chromium/third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.cc
index cd599b7db79..afdd17ea00d 100644
--- a/chromium/third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.cc
+++ b/chromium/third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.cc
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.h"
#include "third_party/blink/renderer/modules/background_sync/sync_manager.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.h b/chromium/third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.h
index ca0e5c4428a..d8a67c0b7a0 100644
--- a/chromium/third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.h
+++ b/chromium/third_party/blink/renderer/modules/background_sync/service_worker_registration_sync.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BACKGROUND_SYNC_SERVICE_WORKER_REGISTRATION_SYNC_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BACKGROUND_SYNC_SERVICE_WORKER_REGISTRATION_SYNC_H_
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/supplementable.h"
diff --git a/chromium/third_party/blink/renderer/modules/background_sync/sync_event.h b/chromium/third_party/blink/renderer/modules/background_sync/sync_event.h
index 94214e37db7..478a25dc517 100644
--- a/chromium/third_party/blink/renderer/modules/background_sync/sync_event.h
+++ b/chromium/third_party/blink/renderer/modules/background_sync/sync_event.h
@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/modules/background_sync/sync_event_init.h"
#include "third_party/blink/renderer/modules/event_modules.h"
-#include "third_party/blink/renderer/modules/serviceworkers/extendable_event.h"
+#include "third_party/blink/renderer/modules/service_worker/extendable_event.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/modules/background_sync/sync_manager.cc b/chromium/third_party/blink/renderer/modules/background_sync/sync_manager.cc
index 9ffbaf0aa86..18ce0431d10 100644
--- a/chromium/third_party/blink/renderer/modules/background_sync/sync_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/background_sync/sync_manager.cc
@@ -10,9 +10,8 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -31,7 +30,7 @@ ScriptPromise SyncManager::registerFunction(ScriptState* script_state,
if (!registration_->active())
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kAbortError,
+ DOMException::Create(DOMExceptionCode::kAbortError,
"Registration failed - no active Service Worker"));
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
@@ -90,22 +89,22 @@ void SyncManager::RegisterCallback(ScriptPromiseResolver* resolver,
NOTREACHED();
break;
case mojom::blink::BackgroundSyncError::STORAGE:
- resolver->Reject(
- DOMException::Create(kUnknownError, "Background Sync is disabled."));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kUnknownError,
+ "Background Sync is disabled."));
break;
case mojom::blink::BackgroundSyncError::NOT_ALLOWED:
resolver->Reject(
- DOMException::Create(kInvalidAccessError,
+ DOMException::Create(DOMExceptionCode::kInvalidAccessError,
"Attempted to register a sync event without a "
"window or registration tag too long."));
break;
case mojom::blink::BackgroundSyncError::PERMISSION_DENIED:
- resolver->Reject(
- DOMException::Create(kPermissionDeniedError, "Permission denied."));
+ resolver->Reject(DOMException::Create(
+ DOMExceptionCode::kPermissionDeniedError, "Permission denied."));
break;
case mojom::blink::BackgroundSyncError::NO_SERVICE_WORKER:
- resolver->Reject(
- DOMException::Create(kUnknownError, "No service worker is active."));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kUnknownError,
+ "No service worker is active."));
break;
}
}
@@ -133,12 +132,12 @@ void SyncManager::GetRegistrationsCallback(
NOTREACHED();
break;
case mojom::blink::BackgroundSyncError::STORAGE:
- resolver->Reject(
- DOMException::Create(kUnknownError, "Background Sync is disabled."));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kUnknownError,
+ "Background Sync is disabled."));
break;
case mojom::blink::BackgroundSyncError::NO_SERVICE_WORKER:
- resolver->Reject(
- DOMException::Create(kUnknownError, "No service worker is active."));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kUnknownError,
+ "No service worker is active."));
break;
}
}
diff --git a/chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.cc b/chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.cc
index e2075b994f1..7dc24a05041 100644
--- a/chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.cc
+++ b/chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.cc
@@ -43,7 +43,7 @@ void BatteryDispatcher::UpdateBatteryStatus(
NotifyControllers();
}
-void BatteryDispatcher::StartListening() {
+void BatteryDispatcher::StartListening(LocalFrame* frame) {
DCHECK(!monitor_.is_bound());
Platform::Current()->GetInterfaceProvider()->GetInterface(
mojo::MakeRequest(&monitor_));
diff --git a/chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.h b/chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.h
index 5c0e20be7ec..78c6592262c 100644
--- a/chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.h
+++ b/chromium/third_party/blink/renderer/modules/battery/battery_dispatcher.h
@@ -34,7 +34,7 @@ class MODULES_EXPORT BatteryDispatcher final
void UpdateBatteryStatus(const BatteryStatus&);
// Inherited from PlatformEventDispatcher.
- void StartListening() override;
+ void StartListening(LocalFrame* frame) override;
void StopListening() override;
device::mojom::blink::BatteryMonitorPtr monitor_;
diff --git a/chromium/third_party/blink/renderer/modules/battery/battery_manager.cc b/chromium/third_party/blink/renderer/modules/battery/battery_manager.cc
index aea017ee4e9..826039ea127 100644
--- a/chromium/third_party/blink/renderer/modules/battery/battery_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/battery/battery_manager.cc
@@ -113,8 +113,10 @@ void BatteryManager::ContextDestroyed(ExecutionContext*) {
bool BatteryManager::HasPendingActivity() const {
// Prevent V8 from garbage collecting the wrapper object if there are
- // event listeners attached to it.
- return GetExecutionContext() && HasEventListeners();
+ // event listeners or pending promises attached to it.
+ return HasEventListeners() ||
+ (battery_property_ &&
+ battery_property_->GetState() == ScriptPromisePropertyBase::kPending);
}
void BatteryManager::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/modules/battery/navigator_battery.idl b/chromium/third_party/blink/renderer/modules/battery/navigator_battery.idl
index 4cdc46edf1b..579ee188799 100644
--- a/chromium/third_party/blink/renderer/modules/battery/navigator_battery.idl
+++ b/chromium/third_party/blink/renderer/modules/battery/navigator_battery.idl
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// https://w3c.github.io/battery/#the-navigator-interface
[
ImplementedAs=NavigatorBattery
] partial interface Navigator {
diff --git a/chromium/third_party/blink/renderer/modules/beacon/navigator_beacon.cc b/chromium/third_party/blink/renderer/modules/beacon/navigator_beacon.cc
index 45172b3bfaf..6de7d1a5a72 100644
--- a/chromium/third_party/blink/renderer/modules/beacon/navigator_beacon.cc
+++ b/chromium/third_party/blink/renderer/modules/beacon/navigator_beacon.cc
@@ -4,9 +4,7 @@
#include "third_party/blink/renderer/modules/beacon/navigator_beacon.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/modules/v8/array_buffer_view_or_blob_or_string_or_form_data.h"
-#include "third_party/blink/renderer/core/dom/exception_code.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_frame.h"
@@ -15,6 +13,7 @@
#include "third_party/blink/renderer/core/html/forms/form_data.h"
#include "third_party/blink/renderer/core/loader/ping_loader.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.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/loader/cors/cors.h"
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.cc b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
index 431c2bf71bc..5e56ac7ac2f 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.cc
@@ -14,7 +14,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/dom/exception_code.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_frame.h"
@@ -173,7 +172,7 @@ ScriptPromise Bluetooth::requestDevice(ScriptState* script_state,
return ScriptPromise::RejectWithDOMException(
script_state,
DOMException::Create(
- kSecurityError,
+ DOMExceptionCode::kSecurityError,
"Must be handling a user gesture to show a permission request."));
}
@@ -186,7 +185,8 @@ ScriptPromise Bluetooth::requestDevice(ScriptState* script_state,
if (!service_) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kNotSupportedError));
+ script_state,
+ DOMException::Create(DOMExceptionCode::kNotSupportedError));
}
// In order to convert the arguments from service names and aliases to just
@@ -195,7 +195,7 @@ ScriptPromise Bluetooth::requestDevice(ScriptState* script_state,
ConvertRequestDeviceOptions(options, device_options, exception_state);
if (exception_state.HadException())
- return exception_state.Reject(script_state);
+ return ScriptPromise();
// Record the eTLD+1 of the frame using the API.
Document* document = ToDocument(context);
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.idl b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.idl
index 5ceef89b68e..ade4e8ddc2f 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.idl
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth.idl
@@ -5,7 +5,8 @@
// https://webbluetoothcg.github.io/web-bluetooth/#bluetooth
[
- RuntimeEnabled=WebBluetooth
+ RuntimeEnabled=WebBluetooth,
+ SecureContext
] interface Bluetooth {
- [CallWith=ScriptState, RaisesException, MeasureAs=WebBluetoothRequestDevice, SecureContext] Promise<BluetoothDevice> requestDevice (optional RequestDeviceOptions options);
+ [CallWith=ScriptState, RaisesException, MeasureAs=WebBluetoothRequestDevice] Promise<BluetoothDevice> requestDevice (optional RequestDeviceOptions options);
};
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_characteristic_properties.idl b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_characteristic_properties.idl
index d4d46cfc7ab..93af7ba7327 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_characteristic_properties.idl
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_characteristic_properties.idl
@@ -7,7 +7,8 @@
// Implement BluetoothCharacteristicProperties interface: http://crbug.com/483345
[
- RuntimeEnabled=WebBluetooth
+ RuntimeEnabled=WebBluetooth,
+ SecureContext
] interface BluetoothCharacteristicProperties {
readonly attribute boolean broadcast;
readonly attribute boolean read;
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_device.idl b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_device.idl
index 3c806288397..c1f8b5fe714 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_device.idl
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_device.idl
@@ -7,7 +7,8 @@
// Implement BluetoothDevice interface: http://crbug.com/421668
[
- RuntimeEnabled=WebBluetooth
+ RuntimeEnabled=WebBluetooth,
+ SecureContext
] interface BluetoothDevice : EventTarget
// Implement ServiceEventHandlers interface: http://crbug.com/421670
// : ServiceEventHandlers
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_error.cc b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_error.cc
index 33995c46b32..64a34feac74 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_error.cc
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_error.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_error.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
namespace blink {
@@ -37,7 +36,7 @@ DOMException* BluetoothError::CreateNotConnectedException(
}
return DOMException::Create(
- kNetworkError,
+ DOMExceptionCode::kNetworkError,
String::Format(kGATTServerNotConnectedBase, operation_string));
}
@@ -49,14 +48,16 @@ DOMException* BluetoothError::CreateDOMException(
case BluetoothErrorCode::kInvalidService:
case BluetoothErrorCode::kInvalidCharacteristic:
case BluetoothErrorCode::kInvalidDescriptor:
- return DOMException::Create(kInvalidStateError, detailed_message);
+ return DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ detailed_message);
case BluetoothErrorCode::kServiceNotFound:
case BluetoothErrorCode::kCharacteristicNotFound:
case BluetoothErrorCode::kDescriptorNotFound:
- return DOMException::Create(kNotFoundError, detailed_message);
+ return DOMException::Create(DOMExceptionCode::kNotFoundError,
+ detailed_message);
}
NOTREACHED();
- return DOMException::Create(kUnknownError);
+ return DOMException::Create(DOMExceptionCode::kUnknownError);
}
// static
@@ -72,115 +73,131 @@ DOMException* BluetoothError::CreateDOMException(
// expected to be redirected to the switch above that handles
// BluetoothErrorCode.
NOTREACHED();
- return DOMException::Create(kUnknownError);
+ return DOMException::Create(DOMExceptionCode::kUnknownError);
#define MAP_ERROR(enumeration, name, message) \
case mojom::blink::WebBluetoothResult::enumeration: \
return DOMException::Create(name, message);
// InvalidModificationErrors:
- MAP_ERROR(GATT_INVALID_ATTRIBUTE_LENGTH, kInvalidModificationError,
+ MAP_ERROR(GATT_INVALID_ATTRIBUTE_LENGTH,
+ DOMExceptionCode::kInvalidModificationError,
"GATT Error: invalid attribute length.");
// InvalidStateErrors:
- MAP_ERROR(SERVICE_NO_LONGER_EXISTS, kInvalidStateError,
+ MAP_ERROR(SERVICE_NO_LONGER_EXISTS, DOMExceptionCode::kInvalidStateError,
"GATT Service no longer exists.");
- MAP_ERROR(CHARACTERISTIC_NO_LONGER_EXISTS, kInvalidStateError,
+ MAP_ERROR(CHARACTERISTIC_NO_LONGER_EXISTS,
+ DOMExceptionCode::kInvalidStateError,
"GATT Characteristic no longer exists.");
- MAP_ERROR(DESCRIPTOR_NO_LONGER_EXISTS, kInvalidStateError,
+ MAP_ERROR(DESCRIPTOR_NO_LONGER_EXISTS,
+ DOMExceptionCode::kInvalidStateError,
"GATT Descriptor no longer exists.");
// NetworkErrors:
- MAP_ERROR(CONNECT_ALREADY_IN_PROGRESS, kNetworkError,
+ MAP_ERROR(CONNECT_ALREADY_IN_PROGRESS, DOMExceptionCode::kNetworkError,
"Connection already in progress.");
- MAP_ERROR(CONNECT_AUTH_CANCELED, kNetworkError,
+ MAP_ERROR(CONNECT_AUTH_CANCELED, DOMExceptionCode::kNetworkError,
"Authentication canceled.");
- MAP_ERROR(CONNECT_AUTH_FAILED, kNetworkError, "Authentication failed.");
- MAP_ERROR(CONNECT_AUTH_REJECTED, kNetworkError,
+ MAP_ERROR(CONNECT_AUTH_FAILED, DOMExceptionCode::kNetworkError,
+ "Authentication failed.");
+ MAP_ERROR(CONNECT_AUTH_REJECTED, DOMExceptionCode::kNetworkError,
"Authentication rejected.");
- MAP_ERROR(CONNECT_AUTH_TIMEOUT, kNetworkError, "Authentication timeout.");
- MAP_ERROR(CONNECT_UNKNOWN_ERROR, kNetworkError,
+ MAP_ERROR(CONNECT_AUTH_TIMEOUT, DOMExceptionCode::kNetworkError,
+ "Authentication timeout.");
+ MAP_ERROR(CONNECT_UNKNOWN_ERROR, DOMExceptionCode::kNetworkError,
"Unknown error when connecting to the device.");
- MAP_ERROR(CONNECT_UNKNOWN_FAILURE, kNetworkError,
+ MAP_ERROR(CONNECT_UNKNOWN_FAILURE, DOMExceptionCode::kNetworkError,
"Connection failed for unknown reason.");
- MAP_ERROR(CONNECT_UNSUPPORTED_DEVICE, kNetworkError,
+ MAP_ERROR(CONNECT_UNSUPPORTED_DEVICE, DOMExceptionCode::kNetworkError,
"Unsupported device.");
- MAP_ERROR(DEVICE_NO_LONGER_IN_RANGE, kNetworkError,
+ MAP_ERROR(DEVICE_NO_LONGER_IN_RANGE, DOMExceptionCode::kNetworkError,
"Bluetooth Device is no longer in range.");
- MAP_ERROR(GATT_NOT_PAIRED, kNetworkError, "GATT Error: Not paired.");
- MAP_ERROR(GATT_OPERATION_IN_PROGRESS, kNetworkError,
+ MAP_ERROR(GATT_NOT_PAIRED, DOMExceptionCode::kNetworkError,
+ "GATT Error: Not paired.");
+ MAP_ERROR(GATT_OPERATION_IN_PROGRESS, DOMExceptionCode::kNetworkError,
"GATT operation already in progress.");
// NotFoundErrors:
- MAP_ERROR(WEB_BLUETOOTH_NOT_SUPPORTED, kNotFoundError,
+ MAP_ERROR(WEB_BLUETOOTH_NOT_SUPPORTED, DOMExceptionCode::kNotFoundError,
"Web Bluetooth is not supported on this platform. For a list "
"of supported platforms see: https://goo.gl/J6ASzs");
- MAP_ERROR(NO_BLUETOOTH_ADAPTER, kNotFoundError,
+ MAP_ERROR(NO_BLUETOOTH_ADAPTER, DOMExceptionCode::kNotFoundError,
"Bluetooth adapter not available.");
- MAP_ERROR(CHOSEN_DEVICE_VANISHED, kNotFoundError,
+ MAP_ERROR(CHOSEN_DEVICE_VANISHED, DOMExceptionCode::kNotFoundError,
"User selected a device that doesn't exist anymore.");
- MAP_ERROR(CHOOSER_CANCELLED, kNotFoundError,
+ MAP_ERROR(CHOOSER_CANCELLED, DOMExceptionCode::kNotFoundError,
"User cancelled the requestDevice() chooser.");
- MAP_ERROR(CHOOSER_NOT_SHOWN_API_GLOBALLY_DISABLED, kNotFoundError,
+ MAP_ERROR(CHOOSER_NOT_SHOWN_API_GLOBALLY_DISABLED,
+ DOMExceptionCode::kNotFoundError,
"Web Bluetooth API globally disabled.");
- MAP_ERROR(CHOOSER_NOT_SHOWN_API_LOCALLY_DISABLED, kNotFoundError,
+ MAP_ERROR(CHOOSER_NOT_SHOWN_API_LOCALLY_DISABLED,
+ DOMExceptionCode::kNotFoundError,
"User or their enterprise policy has disabled Web Bluetooth.");
MAP_ERROR(
- CHOOSER_NOT_SHOWN_USER_DENIED_PERMISSION_TO_SCAN, kNotFoundError,
+ CHOOSER_NOT_SHOWN_USER_DENIED_PERMISSION_TO_SCAN,
+ DOMExceptionCode::kNotFoundError,
"User denied the browser permission to scan for Bluetooth devices.");
- MAP_ERROR(NO_SERVICES_FOUND, kNotFoundError,
+ MAP_ERROR(NO_SERVICES_FOUND, DOMExceptionCode::kNotFoundError,
"No Services found in device.");
- MAP_ERROR(NO_CHARACTERISTICS_FOUND, kNotFoundError,
+ MAP_ERROR(NO_CHARACTERISTICS_FOUND, DOMExceptionCode::kNotFoundError,
"No Characteristics found in service.");
- MAP_ERROR(NO_DESCRIPTORS_FOUND, kNotFoundError,
+ MAP_ERROR(NO_DESCRIPTORS_FOUND, DOMExceptionCode::kNotFoundError,
"No Descriptors found in Characteristic.");
- MAP_ERROR(BLUETOOTH_LOW_ENERGY_NOT_AVAILABLE, kNotFoundError,
+ MAP_ERROR(BLUETOOTH_LOW_ENERGY_NOT_AVAILABLE,
+ DOMExceptionCode::kNotFoundError,
"Bluetooth Low Energy not available.");
// NotSupportedErrors:
- MAP_ERROR(GATT_UNKNOWN_ERROR, kNotSupportedError, "GATT Error Unknown.");
- MAP_ERROR(GATT_UNKNOWN_FAILURE, kNotSupportedError,
+ MAP_ERROR(GATT_UNKNOWN_ERROR, DOMExceptionCode::kNotSupportedError,
+ "GATT Error Unknown.");
+ MAP_ERROR(GATT_UNKNOWN_FAILURE, DOMExceptionCode::kNotSupportedError,
"GATT operation failed for unknown reason.");
- MAP_ERROR(GATT_NOT_PERMITTED, kNotSupportedError,
+ MAP_ERROR(GATT_NOT_PERMITTED, DOMExceptionCode::kNotSupportedError,
"GATT operation not permitted.");
- MAP_ERROR(GATT_NOT_SUPPORTED, kNotSupportedError,
+ MAP_ERROR(GATT_NOT_SUPPORTED, DOMExceptionCode::kNotSupportedError,
"GATT Error: Not supported.");
- MAP_ERROR(GATT_UNTRANSLATED_ERROR_CODE, kNotSupportedError,
+ MAP_ERROR(GATT_UNTRANSLATED_ERROR_CODE,
+ DOMExceptionCode::kNotSupportedError,
"GATT Error: Unknown GattErrorCode.");
// SecurityErrors:
- MAP_ERROR(GATT_NOT_AUTHORIZED, kSecurityError,
+ MAP_ERROR(GATT_NOT_AUTHORIZED, DOMExceptionCode::kSecurityError,
"GATT operation not authorized.");
- MAP_ERROR(BLOCKLISTED_CHARACTERISTIC_UUID, kSecurityError,
+ MAP_ERROR(BLOCKLISTED_CHARACTERISTIC_UUID,
+ DOMExceptionCode::kSecurityError,
"getCharacteristic(s) called with blocklisted UUID. "
"https://goo.gl/4NeimX");
- MAP_ERROR(BLOCKLISTED_DESCRIPTOR_UUID, kSecurityError,
+ MAP_ERROR(BLOCKLISTED_DESCRIPTOR_UUID, DOMExceptionCode::kSecurityError,
"getDescriptor(s) called with blocklisted UUID. "
"https://goo.gl/4NeimX");
- MAP_ERROR(BLOCKLISTED_READ, kSecurityError,
+ MAP_ERROR(BLOCKLISTED_READ, DOMExceptionCode::kSecurityError,
"readValue() called on blocklisted object marked "
"exclude-reads. https://goo.gl/4NeimX");
- MAP_ERROR(BLOCKLISTED_WRITE, kSecurityError,
+ MAP_ERROR(BLOCKLISTED_WRITE, DOMExceptionCode::kSecurityError,
"writeValue() called on blocklisted object marked "
"exclude-writes. https://goo.gl/4NeimX");
- MAP_ERROR(NOT_ALLOWED_TO_ACCESS_ANY_SERVICE, kSecurityError,
+ MAP_ERROR(NOT_ALLOWED_TO_ACCESS_ANY_SERVICE,
+ DOMExceptionCode::kSecurityError,
"Origin is not allowed to access any service. Tip: Add the "
"service UUID to 'optionalServices' in requestDevice() "
"options. https://goo.gl/HxfxSQ");
- MAP_ERROR(NOT_ALLOWED_TO_ACCESS_SERVICE, kSecurityError,
+ MAP_ERROR(NOT_ALLOWED_TO_ACCESS_SERVICE, DOMExceptionCode::kSecurityError,
"Origin is not allowed to access the service. Tip: Add the "
"service UUID to 'optionalServices' in requestDevice() "
"options. https://goo.gl/HxfxSQ");
- MAP_ERROR(REQUEST_DEVICE_WITH_BLOCKLISTED_UUID, kSecurityError,
+ MAP_ERROR(REQUEST_DEVICE_WITH_BLOCKLISTED_UUID,
+ DOMExceptionCode::kSecurityError,
"requestDevice() called with a filter containing a blocklisted "
"UUID. https://goo.gl/4NeimX");
- MAP_ERROR(REQUEST_DEVICE_FROM_CROSS_ORIGIN_IFRAME, kSecurityError,
+ MAP_ERROR(REQUEST_DEVICE_FROM_CROSS_ORIGIN_IFRAME,
+ DOMExceptionCode::kSecurityError,
"requestDevice() called from cross-origin iframe.");
#undef MAP_ERROR
}
NOTREACHED();
- return DOMException::Create(kUnknownError);
+ return DOMException::Create(DOMExceptionCode::kUnknownError);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.cc b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.cc
index 52b7dbd44c3..7203e783c46 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.cc
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.cc
@@ -76,6 +76,13 @@ ExecutionContext* BluetoothRemoteGATTCharacteristic::GetExecutionContext()
return ContextLifecycleObserver::GetExecutionContext();
}
+bool BluetoothRemoteGATTCharacteristic::HasPendingActivity() const {
+ // This object should be considered active as long as there are registered
+ // event listeners. Even if script drops all references this can still be
+ // found again through the BluetoothRemoteGATTServer object.
+ return GetExecutionContext() && HasEventListeners();
+}
+
void BluetoothRemoteGATTCharacteristic::AddedEventListener(
const AtomicString& event_type,
RegisteredEventListener& registered_listener) {
@@ -182,10 +189,12 @@ ScriptPromise BluetoothRemoteGATTCharacteristic::writeValue(
// If bytes is more than 512 bytes long (the maximum length of an attribute
// value, per Long Attribute Values) return a promise rejected with an
// InvalidModificationError and abort.
- if (value.ByteLength() > 512)
+ if (value.ByteLength() > 512) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kInvalidModificationError,
- "Value can't exceed 512 bytes."));
+ script_state,
+ DOMException::Create(DOMExceptionCode::kInvalidModificationError,
+ "Value can't exceed 512 bytes."));
+ }
// Let valueVector be a copy of the bytes held by value.
Vector<uint8_t> value_vector;
@@ -293,7 +302,7 @@ ScriptPromise BluetoothRemoteGATTCharacteristic::getDescriptor(
String descriptor =
BluetoothUUID::getDescriptor(descriptor_uuid, exception_state);
if (exception_state.HadException())
- return exception_state.Reject(script_state);
+ return ScriptPromise();
return GetDescriptorsImpl(script_state,
mojom::blink::WebBluetoothGATTQueryQuantity::SINGLE,
@@ -314,7 +323,7 @@ ScriptPromise BluetoothRemoteGATTCharacteristic::getDescriptors(
String descriptor =
BluetoothUUID::getDescriptor(descriptor_uuid, exception_state);
if (exception_state.HadException())
- return exception_state.Reject(script_state);
+ return ScriptPromise();
return GetDescriptorsImpl(
script_state, mojom::blink::WebBluetoothGATTQueryQuantity::MULTIPLE,
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.h b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.h
index 0890312ab2b..8a9c2b440e7 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.h
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.h
@@ -7,6 +7,7 @@
#include "mojo/public/cpp/bindings/associated_binding_set.h"
#include "third_party/blink/public/platform/modules/bluetooth/web_bluetooth.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_data_view.h"
@@ -20,6 +21,7 @@ namespace blink {
class BluetoothCharacteristicProperties;
class BluetoothDevice;
+class DOMException;
class ExecutionContext;
class ScriptPromise;
class ScriptState;
@@ -34,6 +36,7 @@ class ScriptState;
// CallbackPromiseAdapter class comments.
class BluetoothRemoteGATTCharacteristic final
: public EventTargetWithInlineData,
+ public ActiveScriptWrappable<BluetoothRemoteGATTCharacteristic>,
public ContextLifecycleObserver,
public mojom::blink::WebBluetoothCharacteristicClient {
USING_PRE_FINALIZER(BluetoothRemoteGATTCharacteristic, Dispose);
@@ -71,6 +74,9 @@ class BluetoothRemoteGATTCharacteristic final
const AtomicString& InterfaceName() const override;
ExecutionContext* GetExecutionContext() const override;
+ // ActiveScriptWrappable methods:
+ bool HasPendingActivity() const override;
+
// Interface required by garbage collection.
void Trace(blink::Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.idl b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.idl
index bf38de08f89..a099782bd46 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.idl
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.idl
@@ -7,7 +7,9 @@
// Implement BluetoothRemoteGATTCharacteristic interface: https://crbug.com/483344
[
- RuntimeEnabled=WebBluetooth
+ ActiveScriptWrappable,
+ RuntimeEnabled=WebBluetooth,
+ SecureContext
] interface BluetoothRemoteGATTCharacteristic : EventTarget {//: CharacteristicEventHandlers {
[SameObject] readonly attribute BluetoothRemoteGATTService service;
readonly attribute UUID uuid;
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_descriptor.cc b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_descriptor.cc
index db83030c1a1..6e37ea020ec 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_descriptor.cc
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_descriptor.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_error.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_utils.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
@@ -124,8 +125,9 @@ ScriptPromise BluetoothRemoteGATTDescriptor::writeValue(
// InvalidModificationError and abort.
if (value.ByteLength() > 512) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kInvalidModificationError,
- "Value can't exceed 512 bytes."));
+ script_state,
+ DOMException::Create(DOMExceptionCode::kInvalidModificationError,
+ "Value can't exceed 512 bytes."));
}
// Let valueVector be a copy of the bytes held by value.
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_descriptor.idl b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_descriptor.idl
index 83b2593b121..31c55140cc2 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_descriptor.idl
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_descriptor.idl
@@ -7,7 +7,8 @@
// Implement BluetoothRemoteGATTDescriptor interface: https://crbug.com/660699
[
- RuntimeEnabled=WebBluetooth
+ RuntimeEnabled=WebBluetooth,
+ SecureContext
] interface BluetoothRemoteGATTDescriptor {
[SameObject] readonly attribute BluetoothRemoteGATTCharacteristic characteristic;
readonly attribute UUID uuid;
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.cc b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.cc
index 415c692dd96..dc208ba618e 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.cc
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.cc
@@ -11,7 +11,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#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/dom/exception_code.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_device.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_error.h"
@@ -190,7 +189,7 @@ ScriptPromise BluetoothRemoteGATTServer::getPrimaryService(
ExceptionState& exception_state) {
String service_uuid = BluetoothUUID::getService(service, exception_state);
if (exception_state.HadException())
- return exception_state.Reject(script_state);
+ return ScriptPromise();
return GetPrimaryServicesImpl(
script_state, mojom::blink::WebBluetoothGATTQueryQuantity::SINGLE,
@@ -203,7 +202,7 @@ ScriptPromise BluetoothRemoteGATTServer::getPrimaryServices(
ExceptionState& exception_state) {
String service_uuid = BluetoothUUID::getService(service, exception_state);
if (exception_state.HadException())
- return exception_state.Reject(script_state);
+ return ScriptPromise();
return GetPrimaryServicesImpl(
script_state, mojom::blink::WebBluetoothGATTQueryQuantity::MULTIPLE,
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.idl b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.idl
index b1bd31aa660..bb2ece549cb 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.idl
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_server.idl
@@ -7,7 +7,8 @@
// Implement BluetoothGATTRemoteServer interface: https://crbug.com/476735
[
- RuntimeEnabled=WebBluetooth
+ RuntimeEnabled=WebBluetooth,
+ SecureContext
] interface BluetoothRemoteGATTServer
{
[SameObject] readonly attribute BluetoothDevice device;
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.cc b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.cc
index 422cb709026..5f040576f6f 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.cc
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.cc
@@ -8,12 +8,12 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_error.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_characteristic.h"
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
@@ -93,7 +93,7 @@ ScriptPromise BluetoothRemoteGATTService::getCharacteristic(
String characteristic_uuid =
BluetoothUUID::getCharacteristic(characteristic, exception_state);
if (exception_state.HadException())
- return exception_state.Reject(script_state);
+ return ScriptPromise();
return GetCharacteristicsImpl(
script_state, mojom::blink::WebBluetoothGATTQueryQuantity::SINGLE,
@@ -107,7 +107,7 @@ ScriptPromise BluetoothRemoteGATTService::getCharacteristics(
String characteristic_uuid =
BluetoothUUID::getCharacteristic(characteristic, exception_state);
if (exception_state.HadException())
- return exception_state.Reject(script_state);
+ return ScriptPromise();
return GetCharacteristicsImpl(
script_state, mojom::blink::WebBluetoothGATTQueryQuantity::MULTIPLE,
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.idl b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.idl
index edab043c9e7..8b6957b431d 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.idl
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_service.idl
@@ -7,7 +7,8 @@
// Implement BluetoothRemoteGATTService interface: https://crbug.com/483342
[
- RuntimeEnabled=WebBluetooth
+ RuntimeEnabled=WebBluetooth,
+ SecureContext
] interface BluetoothRemoteGATTService { // : ServiceEventHandlers {
[SameObject] readonly attribute BluetoothDevice device;
readonly attribute UUID uuid;
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.cc b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.cc
index 739f9568c27..08f073c9594 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.cc
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.cc
@@ -4,8 +4,7 @@
#include "third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/uuid.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/hex_number.h"
@@ -54,13 +53,16 @@ NameToAssignedNumberMap* GetAssignedNumberToServiceNameMap() {
{"weight_scale", 0x181D},
{"bond_management", 0x181E},
{"continuous_glucose_monitoring", 0x181F},
- {"fitness_machine", 0x1826},
{"internet_protocol_support", 0x1820},
{"indoor_positioning", 0x1821},
{"pulse_oximeter", 0x1822},
{"http_proxy", 0x1823},
{"transport_discovery", 0x1824},
{"object_transfer", 0x1825},
+ {"fitness_machine", 0x1826},
+ {"mesh_provisioning", 0x1827},
+ {"mesh_proxy", 0x1828},
+ {"reconnection_configuration", 0x1829},
}));
return &services_map;
@@ -82,21 +84,28 @@ NameToAssignedNumberMap* GetAssignedNumberForCharacteristicNameMap() {
{"date_time", 0x2A08},
{"day_of_week", 0x2A09},
{"day_date_time", 0x2A0A},
+ {"exact_time_100", 0x2A0B},
{"exact_time_256", 0x2A0C},
{"dst_offset", 0x2A0D},
{"time_zone", 0x2A0E},
{"local_time_information", 0x2A0F},
+ {"secondary_time_zone", 0x2A10},
{"time_with_dst", 0x2A11},
{"time_accuracy", 0x2A12},
{"time_source", 0x2A13},
{"reference_time_information", 0x2A14},
+ {"time_broadcast", 0x2A15},
{"time_update_control_point", 0x2A16},
{"time_update_state", 0x2A17},
{"glucose_measurement", 0x2A18},
{"battery_level", 0x2A19},
+ {"battery_power_state", 0x2A1A},
+ {"battery_level_state", 0x2A1B},
{"temperature_measurement", 0x2A1C},
{"temperature_type", 0x2A1D},
{"intermediate_temperature", 0x2A1E},
+ {"temperature_celsius", 0x2A1F},
+ {"temperature_fahrenheit", 0x2A20},
{"measurement_interval", 0x2A21},
{"boot_keyboard_input_report", 0x2A22},
{"system_id", 0x2A23},
@@ -109,6 +118,8 @@ NameToAssignedNumberMap* GetAssignedNumberForCharacteristicNameMap() {
{"ieee_11073-20601_regulatory_certification_data_list", 0x2A2A},
{"current_time", 0x2A2B},
{"magnetic_declination", 0x2A2C},
+ {"position_2d", 0x2A2F},
+ {"position_3d", 0x2A30},
{"scan_refresh", 0x2A31},
{"boot_keyboard_output_report", 0x2A32},
{"boot_mouse_input_report", 0x2A33},
@@ -118,6 +129,11 @@ NameToAssignedNumberMap* GetAssignedNumberForCharacteristicNameMap() {
{"heart_rate_measurement", 0x2A37},
{"body_sensor_location", 0x2A38},
{"heart_rate_control_point", 0x2A39},
+ {"removable", 0x2A3A},
+ {"service_required", 0x2A3B},
+ {"scientific_temperature_celsius", 0x2A3C},
+ {"string", 0x2A3D},
+ {"network_availability", 0x2A3E},
{"alert_status", 0x2A3F},
{"ringer_control_point", 0x2A40},
{"ringer_setting", 0x2A41},
@@ -142,7 +158,9 @@ NameToAssignedNumberMap* GetAssignedNumberForCharacteristicNameMap() {
{"rsc_feature", 0x2A54},
{"sc_control_point", 0x2A55},
{"digital", 0x2A56},
+ {"digital_output", 0x2A57},
{"analog", 0x2A58},
+ {"analog_output", 0x2A59},
{"aggregate", 0x2A5A},
{"csc_measurement", 0x2A5B},
{"csc_feature", 0x2A5C},
@@ -150,6 +168,7 @@ NameToAssignedNumberMap* GetAssignedNumberForCharacteristicNameMap() {
{"plx_spot_check_measurement", 0x2A5E},
{"plx_continuous_measurement", 0x2A5F},
{"plx_features", 0x2A60},
+ {"pulse_oximetry_control_point", 0x2A62},
{"cycling_power_measurement", 0x2A63},
{"cycling_power_vector", 0x2A64},
{"cycling_power_feature", 0x2A65},
@@ -267,6 +286,7 @@ NameToAssignedNumberMap* GetAssignedNumberForCharacteristicNameMap() {
{"supported_power_range", 0x2AD8},
{"fitness_machine_control_point", 0x2AD9},
{"fitness_machine_status", 0x2ADA},
+ {"date_utc", 0x2AED},
}));
return &characteristics_map;
@@ -367,7 +387,7 @@ String GetUUIDForGATTAttribute(GATTAttribute attribute,
break;
}
// Otherwise, throw a TypeError.
- exception_state.ThrowDOMException(kV8TypeError, error_message.ToString());
+ exception_state.ThrowTypeError(error_message.ToString());
return String();
}
diff --git a/chromium/third_party/blink/renderer/modules/bluetooth/navigator_bluetooth.idl b/chromium/third_party/blink/renderer/modules/bluetooth/navigator_bluetooth.idl
index e73d80eabbd..595ac7a9ff2 100644
--- a/chromium/third_party/blink/renderer/modules/bluetooth/navigator_bluetooth.idl
+++ b/chromium/third_party/blink/renderer/modules/bluetooth/navigator_bluetooth.idl
@@ -6,7 +6,8 @@
[
ImplementedAs=NavigatorBluetooth,
- RuntimeEnabled=WebBluetooth
+ RuntimeEnabled=WebBluetooth,
+ SecureContext
] partial interface Navigator {
[SameObject] readonly attribute Bluetooth bluetooth;
};
diff --git a/chromium/third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.cc b/chromium/third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.cc
index 1c2f3689cb9..2a9b6c406e0 100644
--- a/chromium/third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.cc
+++ b/chromium/third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.cc
@@ -7,8 +7,6 @@
#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
-#include "third_party/blink/renderer/core/dom/events/event_queue.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/events/message_event.h"
#include "third_party/blink/renderer/platform/mojo/mojo_helper.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -38,11 +36,11 @@ mojom::blink::BroadcastChannelProviderPtr& GetThreadSpecificProvider() {
BroadcastChannel* BroadcastChannel::Create(ExecutionContext* execution_context,
const String& name,
ExceptionState& exception_state) {
- if (execution_context->GetSecurityOrigin()->IsUnique()) {
+ if (execution_context->GetSecurityOrigin()->IsOpaque()) {
// TODO(mek): Decide what to do here depending on
// https://github.com/whatwg/html/issues/1319
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"Can't create BroadcastChannel in an opaque origin");
return nullptr;
}
@@ -58,7 +56,8 @@ void BroadcastChannel::Dispose() {
void BroadcastChannel::postMessage(const ScriptValue& message,
ExceptionState& exception_state) {
if (!binding_.is_bound()) {
- exception_state.ThrowDOMException(kInvalidStateError, "Channel is closed");
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "Channel is closed");
return;
}
scoped_refptr<SerializedScriptValue> value = SerializedScriptValue::Serialize(
@@ -100,11 +99,7 @@ void BroadcastChannel::OnMessage(BlinkCloneableMessage message) {
MessageEvent* event = MessageEvent::Create(
nullptr, std::move(message.message),
GetExecutionContext()->GetSecurityOrigin()->ToString());
- event->SetTarget(this);
- bool success =
- GetExecutionContext()->GetEventQueue()->EnqueueEvent(FROM_HERE, event);
- DCHECK(success);
- ALLOW_UNUSED_LOCAL(success);
+ EnqueueEvent(event, TaskType::kInternalMedia);
}
void BroadcastChannel::OnError() {
diff --git a/chromium/third_party/blink/renderer/modules/budget/budget_service.cc b/chromium/third_party/blink/renderer/modules/budget/budget_service.cc
index 11d4ab1961b..97471dabb5d 100644
--- a/chromium/third_party/blink/renderer/modules/budget/budget_service.cc
+++ b/chromium/third_party/blink/renderer/modules/budget/budget_service.cc
@@ -10,10 +10,10 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/budget/budget_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
namespace {
@@ -31,10 +31,10 @@ DOMException* ErrorTypeToException(mojom::blink::BudgetServiceErrorType error) {
case mojom::blink::BudgetServiceErrorType::NONE:
return nullptr;
case mojom::blink::BudgetServiceErrorType::DATABASE_ERROR:
- return DOMException::Create(kDataError,
+ return DOMException::Create(DOMExceptionCode::kDataError,
"Error reading the budget database.");
case mojom::blink::BudgetServiceErrorType::NOT_SUPPORTED:
- return DOMException::Create(kNotSupportedError,
+ return DOMException::Create(DOMExceptionCode::kNotSupportedError,
"Requested opration was not supported");
}
NOTREACHED();
diff --git a/chromium/third_party/blink/renderer/modules/cache_storage/DEPS b/chromium/third_party/blink/renderer/modules/cache_storage/DEPS
index d3de51adddd..ba54022a2c0 100644
--- a/chromium/third_party/blink/renderer/modules/cache_storage/DEPS
+++ b/chromium/third_party/blink/renderer/modules/cache_storage/DEPS
@@ -6,5 +6,5 @@ include_rules = [
"+third_party/blink/renderer/modules/event_modules.h",
"+third_party/blink/renderer/modules/event_target_modules.h",
"+third_party/blink/renderer/modules/modules_export.h",
- "+third_party/blink/renderer/modules/serviceworkers",
+ "+third_party/blink/renderer/modules/service_worker",
]
diff --git a/chromium/third_party/blink/renderer/modules/cache_storage/cache.cc b/chromium/third_party/blink/renderer/modules/cache_storage/cache.cc
index 61f558dd34a..e79bf5c55d4 100644
--- a/chromium/third_party/blink/renderer/modules/cache_storage/cache.cc
+++ b/chromium/third_party/blink/renderer/modules/cache_storage/cache.cc
@@ -9,26 +9,27 @@
#include "base/optional.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_response.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_response.h"
#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.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/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_code_cache.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_response.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_script_runner.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
#include "third_party/blink/renderer/core/fetch/fetch_data_loader.h"
#include "third_party/blink/renderer/core/fetch/request.h"
+#include "third_party/blink/renderer/core/fetch/request_init.h"
#include "third_party/blink/renderer/core/fetch/response.h"
#include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/modules/cache_storage/cache_storage_error.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope.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/bindings/v8_throw_exception.h"
#include "third_party/blink/renderer/platform/histogram.h"
@@ -83,20 +84,31 @@ bool ShouldGenerateV8CodeCache(ScriptState* script_state,
// promise. It should be better to achieve this only within C++ world.
class Cache::FetchResolvedForAdd final : public ScriptFunction {
public:
+ // |exception_state| is passed so that the context_type, interface_name and
+ // property_name can be copied and then used to construct a new ExceptionState
+ // object asynchronously later.
static v8::Local<v8::Function> Create(
ScriptState* script_state,
Cache* cache,
- const HeapVector<Member<Request>>& requests) {
+ const HeapVector<Member<Request>>& requests,
+ const ExceptionState& exception_state) {
FetchResolvedForAdd* self =
- new FetchResolvedForAdd(script_state, cache, requests);
+ new FetchResolvedForAdd(script_state, cache, requests, exception_state);
return self->BindToV8Function();
}
ScriptValue Call(ScriptValue value) override {
- NonThrowableExceptionState exception_state;
+ ExceptionState exception_state(GetScriptState()->GetIsolate(),
+ context_type_, property_name_,
+ interface_name_);
HeapVector<Member<Response>> responses =
NativeValueTraits<IDLSequence<Response>>::NativeValue(
GetScriptState()->GetIsolate(), value.V8Value(), exception_state);
+ if (exception_state.HadException()) {
+ ScriptPromise rejection =
+ ScriptPromise::Reject(GetScriptState(), exception_state);
+ return ScriptValue(GetScriptState(), rejection.V8Value());
+ }
for (const auto& response : responses) {
if (!response->ok()) {
@@ -118,8 +130,8 @@ class Cache::FetchResolvedForAdd final : public ScriptFunction {
for (const auto& response : responses)
RecordResponseTypeForAdd(response);
- ScriptPromise put_promise =
- cache_->PutImpl(GetScriptState(), requests_, responses);
+ ScriptPromise put_promise = cache_->PutImpl(GetScriptState(), requests_,
+ responses, exception_state);
return ScriptValue(GetScriptState(), put_promise.V8Value());
}
@@ -132,11 +144,20 @@ class Cache::FetchResolvedForAdd final : public ScriptFunction {
private:
FetchResolvedForAdd(ScriptState* script_state,
Cache* cache,
- const HeapVector<Member<Request>>& requests)
- : ScriptFunction(script_state), cache_(cache), requests_(requests) {}
+ const HeapVector<Member<Request>>& requests,
+ const ExceptionState& exception_state)
+ : ScriptFunction(script_state),
+ cache_(cache),
+ requests_(requests),
+ context_type_(exception_state.Context()),
+ property_name_(exception_state.PropertyName()),
+ interface_name_(exception_state.InterfaceName()) {}
Member<Cache> cache_;
HeapVector<Member<Request>> requests_;
+ ExceptionState::ContextType context_type_;
+ const char* property_name_;
+ const char* interface_name_;
};
class Cache::BarrierCallbackForPut final
@@ -195,7 +216,7 @@ class Cache::BarrierCallbackForPut final
return;
completed_ = true;
ScriptState::Scope scope(resolver_->GetScriptState());
- resolver_->Reject(DOMException::Create(kAbortError));
+ resolver_->Reject(DOMException::Create(DOMExceptionCode::kAbortError));
}
virtual void Trace(blink::Visitor* visitor) {
@@ -337,15 +358,15 @@ class Cache::CodeCacheHandleCallbackForPut final
TextResourceDecoderOptions::CreateAlwaysUseUTF8ForText());
scoped_refptr<CachedMetadata> cached_metadata =
- V8ScriptRunner::GenerateFullCodeCache(
- script_state_.get(),
+ V8CodeCache::GenerateFullCodeCache(
+ script_state_,
text_decoder->Decode(static_cast<const char*>(array_buffer->Data()),
array_buffer->ByteLength()),
web_request_.Url().GetString(), text_decoder->Encoding(),
batch_operation->response->response_type ==
network::mojom::FetchResponseType::kOpaque
- ? V8ScriptRunner::OpaqueMode::kOpaque
- : V8ScriptRunner::OpaqueMode::kNotOpaque);
+ ? V8CodeCache::OpaqueMode::kOpaque
+ : V8CodeCache::OpaqueMode::kNotOpaque);
if (!cached_metadata) {
barrier_callback_->OnSuccess(index_, std::move(batch_operation));
return;
@@ -367,12 +388,13 @@ class Cache::CodeCacheHandleCallbackForPut final
void Abort() override { barrier_callback_->Abort(); }
void Trace(blink::Visitor* visitor) override {
+ visitor->Trace(script_state_);
visitor->Trace(barrier_callback_);
FetchDataLoader::Client::Trace(visitor);
}
private:
- const scoped_refptr<ScriptState> script_state_;
+ const Member<ScriptState> script_state_;
const size_t index_;
Member<BarrierCallbackForPut> barrier_callback_;
const String mime_type_;
@@ -477,14 +499,14 @@ ScriptPromise Cache::put(ScriptState* script_state,
if (request.IsRequest()) {
return PutImpl(script_state,
HeapVector<Member<Request>>(1, request.GetAsRequest()),
- HeapVector<Member<Response>>(1, response));
+ HeapVector<Member<Response>>(1, response), exception_state);
}
Request* new_request =
Request::Create(script_state, request.GetAsUSVString(), exception_state);
if (exception_state.HadException())
return ScriptPromise();
return PutImpl(script_state, HeapVector<Member<Request>>(1, new_request),
- HeapVector<Member<Response>>(1, response));
+ HeapVector<Member<Response>>(1, response), exception_state);
}
ScriptPromise Cache::keys(ScriptState* script_state, ExceptionState&) {
@@ -643,11 +665,12 @@ ScriptPromise Cache::AddAllImpl(ScriptState* script_state,
request_infos[i].SetRequest(requests[i]);
promises[i] = scoped_fetcher_->Fetch(script_state, request_infos[i],
- Dictionary(), exception_state);
+ RequestInit(), exception_state);
}
return ScriptPromise::All(script_state, promises)
- .Then(FetchResolvedForAdd::Create(script_state, this, requests));
+ .Then(FetchResolvedForAdd::Create(script_state, this, requests,
+ exception_state));
}
ScriptPromise Cache::DeleteImpl(ScriptState* script_state,
@@ -696,7 +719,8 @@ ScriptPromise Cache::DeleteImpl(ScriptState* script_state,
ScriptPromise Cache::PutImpl(ScriptState* script_state,
const HeapVector<Member<Request>>& requests,
- const HeapVector<Member<Response>>& responses) {
+ const HeapVector<Member<Response>>& responses,
+ ExceptionState& exception_state) {
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
const ScriptPromise promise = resolver->Promise();
BarrierCallbackForPut* barrier_callback =
@@ -725,18 +749,32 @@ ScriptPromise Cache::PutImpl(ScriptState* script_state,
"Partial response (status code 206) is unsupported");
return promise;
}
- if (responses[i]->IsBodyLocked() || responses[i]->bodyUsed()) {
+ if (responses[i]->IsBodyLocked(exception_state) ==
+ Body::BodyLocked::kLocked ||
+ responses[i]->IsBodyUsed(exception_state) == Body::BodyUsed::kUsed) {
+ DCHECK(!exception_state.HadException());
barrier_callback->OnError("Response body is already used");
return promise;
}
+ if (exception_state.HadException()) {
+ // TODO(ricea): Reject the promise with the actual exception.
+ barrier_callback->OnError("Could not inspect response body state");
+ return promise;
+ }
BodyStreamBuffer* buffer = responses[i]->InternalBodyBuffer();
if (ShouldGenerateV8CodeCache(script_state, responses[i])) {
FetchDataLoader* loader = FetchDataLoader::CreateLoaderAsArrayBuffer();
- buffer->StartLoading(loader, new CodeCacheHandleCallbackForPut(
- script_state, i, barrier_callback,
- requests[i], responses[i]));
+ buffer->StartLoading(
+ loader,
+ new CodeCacheHandleCallbackForPut(script_state, i, barrier_callback,
+ requests[i], responses[i]),
+ exception_state);
+ if (exception_state.HadException()) {
+ barrier_callback->OnError("Could not inspect response body state");
+ return promise;
+ }
continue;
}
@@ -745,9 +783,14 @@ ScriptPromise Cache::PutImpl(ScriptState* script_state,
// the blob handle and dispatch the put batch asynchronously.
FetchDataLoader* loader = FetchDataLoader::CreateLoaderAsBlobHandle(
responses[i]->InternalMIMEType());
- buffer->StartLoading(
- loader, new BlobHandleCallbackForPut(i, barrier_callback, requests[i],
- responses[i]));
+ buffer->StartLoading(loader,
+ new BlobHandleCallbackForPut(
+ i, barrier_callback, requests[i], responses[i]),
+ exception_state);
+ if (exception_state.HadException()) {
+ barrier_callback->OnError("Could not inspect response body state");
+ return promise;
+ }
continue;
}
diff --git a/chromium/third_party/blink/renderer/modules/cache_storage/cache.h b/chromium/third_party/blink/renderer/modules/cache_storage/cache.h
index 782de3fdde0..2667e9b8d6e 100644
--- a/chromium/third_party/blink/renderer/modules/cache_storage/cache.h
+++ b/chromium/third_party/blink/renderer/modules/cache_storage/cache.h
@@ -89,7 +89,8 @@ class MODULES_EXPORT Cache final : public ScriptWrappable {
const CacheQueryOptions&);
ScriptPromise PutImpl(ScriptState*,
const HeapVector<Member<Request>>&,
- const HeapVector<Member<Response>>&);
+ const HeapVector<Member<Response>>&,
+ ExceptionState&);
ScriptPromise KeysImpl(ScriptState*,
const Request*,
const CacheQueryOptions&);
diff --git a/chromium/third_party/blink/renderer/modules/cache_storage/cache_storage.cc b/chromium/third_party/blink/renderer/modules/cache_storage/cache_storage.cc
index dbda51cad17..a7550dd7cd2 100644
--- a/chromium/third_party/blink/renderer/modules/cache_storage/cache_storage.cc
+++ b/chromium/third_party/blink/renderer/modules/cache_storage/cache_storage.cc
@@ -12,13 +12,12 @@
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#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/fetch/response.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/modules/cache_storage/cache_storage_error.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
diff --git a/chromium/third_party/blink/renderer/modules/cache_storage/cache_storage_error.cc b/chromium/third_party/blink/renderer/modules/cache_storage/cache_storage_error.cc
index 2fa64c4c37b..0cb27077dba 100644
--- a/chromium/third_party/blink/renderer/modules/cache_storage/cache_storage_error.cc
+++ b/chromium/third_party/blink/renderer/modules/cache_storage/cache_storage_error.cc
@@ -6,7 +6,6 @@
#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/cache_storage/cache.h"
namespace blink {
@@ -15,20 +14,26 @@ DOMException* CacheStorageError::CreateException(
mojom::CacheStorageError web_error) {
switch (web_error) {
case mojom::CacheStorageError::kErrorNotImplemented:
- return DOMException::Create(kNotSupportedError,
+ return DOMException::Create(DOMExceptionCode::kNotSupportedError,
"Method is not implemented.");
case mojom::CacheStorageError::kErrorNotFound:
- return DOMException::Create(kNotFoundError, "Entry was not found.");
+ return DOMException::Create(DOMExceptionCode::kNotFoundError,
+ "Entry was not found.");
case mojom::CacheStorageError::kErrorExists:
- return DOMException::Create(kInvalidAccessError, "Entry already exists.");
+ return DOMException::Create(DOMExceptionCode::kInvalidAccessError,
+ "Entry already exists.");
case mojom::CacheStorageError::kErrorQuotaExceeded:
- return DOMException::Create(kQuotaExceededError, "Quota exceeded.");
+ return DOMException::Create(DOMExceptionCode::kQuotaExceededError,
+ "Quota exceeded.");
case mojom::CacheStorageError::kErrorCacheNameNotFound:
- return DOMException::Create(kNotFoundError, "Cache was not found.");
+ return DOMException::Create(DOMExceptionCode::kNotFoundError,
+ "Cache was not found.");
case mojom::CacheStorageError::kErrorQueryTooLarge:
- return DOMException::Create(kAbortError, "Operation too large.");
+ return DOMException::Create(DOMExceptionCode::kAbortError,
+ "Operation too large.");
case mojom::CacheStorageError::kErrorStorage:
- return DOMException::Create(kUnknownError, "Unexpected internal error.");
+ return DOMException::Create(DOMExceptionCode::kUnknownError,
+ "Unexpected internal error.");
case mojom::CacheStorageError::kSuccess:
// This function should only be called with an error.
break;
diff --git a/chromium/third_party/blink/renderer/modules/cache_storage/cache_test.cc b/chromium/third_party/blink/renderer/modules/cache_storage/cache_test.cc
index aa2a92998b5..e12bd8cab32 100644
--- a/chromium/third_party/blink/renderer/modules/cache_storage/cache_test.cc
+++ b/chromium/third_party/blink/renderer/modules/cache_storage/cache_test.cc
@@ -14,9 +14,8 @@
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_response.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_response.h"
#include "third_party/blink/public/platform/web_url_response.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
#include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h"
#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
@@ -32,10 +31,12 @@
#include "third_party/blink/renderer/core/fetch/form_data_bytes_consumer.h"
#include "third_party/blink/renderer/core/fetch/global_fetch.h"
#include "third_party/blink/renderer/core/fetch/request.h"
+#include "third_party/blink/renderer/core/fetch/request_init.h"
#include "third_party/blink/renderer/core/fetch/response.h"
#include "third_party/blink/renderer/core/fetch/response_init.h"
#include "third_party/blink/renderer/core/frame/frame.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
using blink::mojom::CacheStorageError;
@@ -57,7 +58,7 @@ class ScopedFetcherForTests final
ScriptPromise Fetch(ScriptState* script_state,
const RequestInfo& request_info,
- const Dictionary&,
+ const RequestInit&,
ExceptionState&) override {
++fetch_count_;
if (expected_url_) {
diff --git a/chromium/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc b/chromium/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc
index d460c1475d6..7152bec8894 100644
--- a/chromium/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc
+++ b/chromium/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc
@@ -11,8 +11,8 @@
#include "base/memory/scoped_refptr.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_request.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_response.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_response.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_string.h"
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
index 357d8c5a187..783f5c3e3dd 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
@@ -4,8 +4,7 @@
#include "third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "base/numerics/checked_math.h"
#include "third_party/blink/renderer/core/css/cssom/css_url_image_value.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -22,6 +21,7 @@
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_pattern.h"
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_style.h"
#include "third_party/blink/renderer/modules/canvas/canvas2d/path_2d.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/geometry/float_quad.h"
#include "third_party/blink/renderer/platform/graphics/canvas_heuristic_parameters.h"
@@ -32,8 +32,6 @@
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/graphics/stroke_data.h"
#include "third_party/blink/renderer/platform/histogram.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
namespace blink {
@@ -72,7 +70,7 @@ void BaseRenderingContext2D::RealizeSaves() {
// state (in turn necessary to support correct resizing and unwinding of the
// stack).
state_stack_.back()->ResetUnrealizedSaveCount();
- PaintCanvas* canvas = DrawingCanvas();
+ cc::PaintCanvas* canvas = DrawingCanvas();
if (canvas)
canvas->save();
ValidateStateStack();
@@ -93,18 +91,25 @@ void BaseRenderingContext2D::restore() {
DCHECK_GE(state_stack_.size(), 1u);
if (state_stack_.size() <= 1)
return;
- path_.Transform(GetState().Transform());
+ // Verify that the current state's transform is invertible.
+ if (GetState().IsTransformInvertible())
+ path_.Transform(GetState().Transform());
+
state_stack_.pop_back();
state_stack_.back()->ClearResolvedFilter();
- path_.Transform(GetState().Transform().Inverse());
- PaintCanvas* c = DrawingCanvas();
+
+ if (GetState().IsTransformInvertible())
+ path_.Transform(GetState().Transform().Inverse());
+
+ cc::PaintCanvas* c = DrawingCanvas();
+
if (c)
c->restore();
ValidateStateStack();
}
-void BaseRenderingContext2D::RestoreMatrixClipStack(PaintCanvas* c) const {
+void BaseRenderingContext2D::RestoreMatrixClipStack(cc::PaintCanvas* c) const {
if (!c)
return;
HeapVector<Member<CanvasRenderingContext2DState>>::const_iterator curr_state;
@@ -124,7 +129,7 @@ void BaseRenderingContext2D::RestoreMatrixClipStack(PaintCanvas* c) const {
void BaseRenderingContext2D::UnwindStateStack() {
if (size_t stack_size = state_stack_.size()) {
- if (PaintCanvas* sk_canvas = ExistingDrawingCanvas()) {
+ if (cc::PaintCanvas* sk_canvas = ExistingDrawingCanvas()) {
while (--stack_size)
sk_canvas->restore();
}
@@ -137,7 +142,7 @@ void BaseRenderingContext2D::Reset() {
state_stack_.resize(1);
state_stack_.front() = CanvasRenderingContext2DState::Create();
path_.Clear();
- if (PaintCanvas* c = ExistingDrawingCanvas()) {
+ if (cc::PaintCanvas* c = ExistingDrawingCanvas()) {
// The canvas should always have an initial/unbalanced save frame, which
// we use to reset the top level matrix and clip here.
DCHECK_EQ(c->getSaveCount(), 2);
@@ -432,7 +437,7 @@ void BaseRenderingContext2D::setFilter(
}
void BaseRenderingContext2D::scale(double sx, double sy) {
- PaintCanvas* c = DrawingCanvas();
+ cc::PaintCanvas* c = DrawingCanvas();
if (!c)
return;
@@ -455,7 +460,7 @@ void BaseRenderingContext2D::scale(double sx, double sy) {
}
void BaseRenderingContext2D::rotate(double angle_in_radians) {
- PaintCanvas* c = DrawingCanvas();
+ cc::PaintCanvas* c = DrawingCanvas();
if (!c)
return;
@@ -470,12 +475,12 @@ void BaseRenderingContext2D::rotate(double angle_in_radians) {
ModifiableState().SetTransform(new_transform);
if (!GetState().IsTransformInvertible())
return;
- c->rotate(clampTo<float>(angle_in_radians * (180.0 / piFloat)));
+ c->rotate(clampTo<float>(angle_in_radians * (180.0 / kPiFloat)));
path_.Transform(AffineTransform().RotateRadians(-angle_in_radians));
}
void BaseRenderingContext2D::translate(double tx, double ty) {
- PaintCanvas* c = DrawingCanvas();
+ cc::PaintCanvas* c = DrawingCanvas();
if (!c)
return;
if (!GetState().IsTransformInvertible())
@@ -505,7 +510,7 @@ void BaseRenderingContext2D::transform(double m11,
double m22,
double dx,
double dy) {
- PaintCanvas* c = DrawingCanvas();
+ cc::PaintCanvas* c = DrawingCanvas();
if (!c)
return;
@@ -535,7 +540,7 @@ void BaseRenderingContext2D::transform(double m11,
}
void BaseRenderingContext2D::resetTransform() {
- PaintCanvas* c = DrawingCanvas();
+ cc::PaintCanvas* c = DrawingCanvas();
if (!c)
return;
@@ -659,7 +664,7 @@ void BaseRenderingContext2D::DrawPathInternal(
if (!DrawingCanvas())
return;
- Draw([&sk_path](PaintCanvas* c, const PaintFlags* flags) // draw lambda
+ Draw([&sk_path](cc::PaintCanvas* c, const PaintFlags* flags) // draw lambda
{ c->drawPath(sk_path, *flags); },
[](const SkIRect& rect) // overdraw test lambda
{ return false; },
@@ -714,7 +719,7 @@ void BaseRenderingContext2D::fillRect(double x,
float fheight = clampTo<float>(height);
SkRect rect = SkRect::MakeXYWH(fx, fy, fwidth, fheight);
- Draw([&rect](PaintCanvas* c, const PaintFlags* flags) // draw lambda
+ Draw([&rect](cc::PaintCanvas* c, const PaintFlags* flags) // draw lambda
{ c->drawRect(rect, *flags); },
[&rect, this](const SkIRect& clip_bounds) // overdraw test lambda
{ return RectContainsTransformedRect(rect, clip_bounds); },
@@ -722,7 +727,7 @@ void BaseRenderingContext2D::fillRect(double x,
}
static void StrokeRectOnCanvas(const FloatRect& rect,
- PaintCanvas* canvas,
+ cc::PaintCanvas* canvas,
const PaintFlags* flags) {
DCHECK_EQ(flags->getStyle(), PaintFlags::kStroke_Style);
if ((rect.Width() > 0) != (rect.Height() > 0)) {
@@ -756,7 +761,7 @@ void BaseRenderingContext2D::strokeRect(double x,
SkRect rect = SkRect::MakeXYWH(fx, fy, fwidth, fheight);
FloatRect bounds = rect;
InflateStrokeRect(bounds);
- Draw([&rect](PaintCanvas* c, const PaintFlags* flags) // draw lambda
+ Draw([&rect](cc::PaintCanvas* c, const PaintFlags* flags) // draw lambda
{ StrokeRectOnCanvas(rect, c, flags); },
[](const SkIRect& clip_bounds) // overdraw test lambda
{ return false; },
@@ -765,7 +770,7 @@ void BaseRenderingContext2D::strokeRect(double x,
void BaseRenderingContext2D::ClipInternal(const Path& path,
const String& winding_rule_string) {
- PaintCanvas* c = DrawingCanvas();
+ cc::PaintCanvas* c = DrawingCanvas();
if (!c) {
return;
}
@@ -807,7 +812,7 @@ bool BaseRenderingContext2D::IsPointInPathInternal(
const double x,
const double y,
const String& winding_rule_string) {
- PaintCanvas* c = DrawingCanvas();
+ cc::PaintCanvas* c = DrawingCanvas();
if (!c)
return false;
if (!GetState().IsTransformInvertible())
@@ -836,7 +841,7 @@ bool BaseRenderingContext2D::isPointInStroke(Path2D* dom_path,
bool BaseRenderingContext2D::IsPointInStrokeInternal(const Path& path,
const double x,
const double y) {
- PaintCanvas* c = DrawingCanvas();
+ cc::PaintCanvas* c = DrawingCanvas();
if (!c)
return false;
if (!GetState().IsTransformInvertible())
@@ -869,7 +874,7 @@ void BaseRenderingContext2D::clearRect(double x,
if (!ValidateRectForCanvas(x, y, width, height))
return;
- PaintCanvas* c = DrawingCanvas();
+ cc::PaintCanvas* c = DrawingCanvas();
if (!c)
return;
if (!GetState().IsTransformInvertible())
@@ -938,10 +943,7 @@ static inline CanvasImageSource* ToImageSourceInternal(
const CanvasImageSourceUnion& value,
ExceptionState& exception_state) {
if (value.IsCSSImageValue()) {
- if (RuntimeEnabledFeatures::CSSPaintAPIEnabled())
- return value.GetAsCSSImageValue();
- exception_state.ThrowTypeError("CSSImageValue is not yet supported");
- return nullptr;
+ return value.GetAsCSSImageValue();
}
if (value.IsHTMLImageElement())
return value.GetAsHTMLImageElement();
@@ -957,7 +959,7 @@ static inline CanvasImageSource* ToImageSourceInternal(
->Size()
.IsEmpty()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
String::Format("The image argument is a canvas element with a width "
"or height of 0."));
return nullptr;
@@ -967,7 +969,8 @@ static inline CanvasImageSource* ToImageSourceInternal(
if (value.IsImageBitmap()) {
if (static_cast<ImageBitmap*>(value.GetAsImageBitmap())->IsNeutered()) {
exception_state.ThrowDOMException(
- kInvalidStateError, String::Format("The image source is detached"));
+ DOMExceptionCode::kInvalidStateError,
+ String::Format("The image source is detached"));
return nullptr;
}
return value.GetAsImageBitmap();
@@ -976,14 +979,15 @@ static inline CanvasImageSource* ToImageSourceInternal(
if (static_cast<OffscreenCanvas*>(value.GetAsOffscreenCanvas())
->IsNeutered()) {
exception_state.ThrowDOMException(
- kInvalidStateError, String::Format("The image source is detached"));
+ DOMExceptionCode::kInvalidStateError,
+ String::Format("The image source is detached"));
return nullptr;
}
if (static_cast<OffscreenCanvas*>(value.GetAsOffscreenCanvas())
->Size()
.IsEmpty()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
String::Format("The image argument is an OffscreenCanvas element "
"with a width or height of 0."));
return nullptr;
@@ -1057,7 +1061,7 @@ bool BaseRenderingContext2D::ShouldDrawImageAntialiased(
const FloatRect& dest_rect) const {
if (!GetState().ShouldAntialias())
return false;
- PaintCanvas* c = DrawingCanvas();
+ cc::PaintCanvas* c = DrawingCanvas();
DCHECK(c);
const SkMatrix& ctm = c->getTotalMatrix();
@@ -1084,7 +1088,7 @@ bool BaseRenderingContext2D::ShouldDrawImageAntialiased(
dest_rect.Height() * fabs(height_expansion) < 1;
}
-void BaseRenderingContext2D::DrawImageInternal(PaintCanvas* c,
+void BaseRenderingContext2D::DrawImageInternal(cc::PaintCanvas* c,
CanvasImageSource* image_source,
Image* image,
const FloatRect& src_rect,
@@ -1179,10 +1183,10 @@ void BaseRenderingContext2D::drawImage(ScriptState* script_state,
if (!DrawingCanvas())
return;
- double start_time = 0;
+ TimeTicks start_time;
base::Optional<CustomCountHistogram> timer;
if (!IsPaint2D()) {
- start_time = WTF::CurrentTimeTicksInSeconds();
+ start_time = WTF::CurrentTimeTicks();
if (CanCreateCanvas2dResourceProvider() && IsAccelerated()) {
if (image_source->IsVideoElement()) {
DEFINE_THREAD_SAFE_STATIC_LOCAL(
@@ -1260,7 +1264,7 @@ void BaseRenderingContext2D::drawImage(ScriptState* script_state,
default_object_size);
if (source_image_status == kUndecodableSourceImageStatus) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"The HTMLImageElement provided is in the 'broken' state.");
}
if (!image || !image->width() || !image->height())
@@ -1340,7 +1344,7 @@ void BaseRenderingContext2D::drawImage(ScriptState* script_state,
Draw(
[this, &image_source, &image, &src_rect, dst_rect](
- PaintCanvas* c, const PaintFlags* flags) // draw lambda
+ cc::PaintCanvas* c, const PaintFlags* flags) // draw lambda
{
DrawImageInternal(c, image_source, image.get(), src_rect, dst_rect,
flags);
@@ -1355,9 +1359,8 @@ void BaseRenderingContext2D::drawImage(ScriptState* script_state,
ValidateStateStack();
if (!IsPaint2D()) {
- DCHECK(start_time);
- timer->Count((WTF::CurrentTimeTicksInSeconds() - start_time) *
- WTF::Time::kMicrosecondsPerSecond);
+ DCHECK(!start_time.is_null());
+ timer->CountMicroseconds(WTF::CurrentTimeTicks() - start_time);
}
}
@@ -1365,7 +1368,7 @@ void BaseRenderingContext2D::ClearCanvas() {
FloatRect canvas_rect(0, 0, Width(), Height());
CheckOverdraw(canvas_rect, nullptr, CanvasRenderingContext2DState::kNoImage,
kClipFill);
- PaintCanvas* c = DrawingCanvas();
+ cc::PaintCanvas* c = DrawingCanvas();
if (c)
c->clear(HasAlpha() ? SK_ColorTRANSPARENT : SK_ColorBLACK);
}
@@ -1409,8 +1412,9 @@ CanvasGradient* BaseRenderingContext2D::createRadialGradient(
ExceptionState& exception_state) {
if (r0 < 0 || r1 < 0) {
exception_state.ThrowDOMException(
- kIndexSizeError, String::Format("The %s provided is less than 0.",
- r0 < 0 ? "r0" : "r1"));
+ DOMExceptionCode::kIndexSizeError,
+ String::Format("The %s provided is less than 0.",
+ r0 < 0 ? "r0" : "r1"));
return nullptr;
}
@@ -1472,7 +1476,7 @@ CanvasPattern* BaseRenderingContext2D::createPattern(
break;
case kZeroSizeCanvasSourceImageStatus:
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
String::Format("The canvas %s is 0.",
image_source->ElementSize(default_object_size).Width()
? "height"
@@ -1480,7 +1484,8 @@ CanvasPattern* BaseRenderingContext2D::createPattern(
return nullptr;
case kUndecodableSourceImageStatus:
exception_state.ThrowDOMException(
- kInvalidStateError, "Source image is in the 'broken' state.");
+ DOMExceptionCode::kInvalidStateError,
+ "Source image is in the 'broken' state.");
return nullptr;
case kInvalidSourceImageStatus:
image_for_rendering = Image::NullImage();
@@ -1559,7 +1564,7 @@ ImageData* BaseRenderingContext2D::createImageData(
ExceptionState& exception_state) const {
if (!sw || !sh) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
String::Format("The source %s is 0.", sw ? "height" : "width"));
return nullptr;
}
@@ -1610,7 +1615,7 @@ ImageData* BaseRenderingContext2D::getImageData(
int sw,
int sh,
ExceptionState& exception_state) {
- if (!WTF::CheckMul(sw, sh).IsValid<int>()) {
+ if (!base::CheckMul(sw, sh).IsValid<int>()) {
exception_state.ThrowRangeError("Out of memory at ImageData creation");
return nullptr;
}
@@ -1622,7 +1627,7 @@ ImageData* BaseRenderingContext2D::getImageData(
"The canvas has been tainted by cross-origin data.");
} else if (!sw || !sh) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
String::Format("The source %s is 0.", sw ? "height" : "width"));
}
@@ -1630,7 +1635,7 @@ ImageData* BaseRenderingContext2D::getImageData(
return nullptr;
if (sw < 0) {
- if (!WTF::CheckAdd(sx, sw).IsValid<int>()) {
+ if (!base::CheckAdd(sx, sw).IsValid<int>()) {
exception_state.ThrowRangeError("Out of memory at ImageData creation");
return nullptr;
}
@@ -1638,7 +1643,7 @@ ImageData* BaseRenderingContext2D::getImageData(
sw = -sw;
}
if (sh < 0) {
- if (!WTF::CheckAdd(sy, sh).IsValid<int>()) {
+ if (!base::CheckAdd(sy, sh).IsValid<int>()) {
exception_state.ThrowRangeError("Out of memory at ImageData creation");
return nullptr;
}
@@ -1646,12 +1651,11 @@ ImageData* BaseRenderingContext2D::getImageData(
sh = -sh;
}
- if (!WTF::CheckAdd(sx, sw).IsValid<int>() ||
- !WTF::CheckAdd(sy, sh).IsValid<int>()) {
+ if (!base::CheckAdd(sx, sw).IsValid<int>() ||
+ !base::CheckAdd(sy, sh).IsValid<int>()) {
exception_state.ThrowRangeError("Out of memory at ImageData creation");
return nullptr;
}
-
base::Optional<ScopedUsHistogramTimer> timer;
if (!IsPaint2D()) {
if (CanCreateCanvas2dResourceProvider() && IsAccelerated()) {
@@ -1733,14 +1737,14 @@ void BaseRenderingContext2D::putImageData(ImageData* data,
int dirty_width,
int dirty_height,
ExceptionState& exception_state) {
- if (!WTF::CheckMul(dirty_width, dirty_height).IsValid<int>()) {
+ if (!base::CheckMul(dirty_width, dirty_height).IsValid<int>()) {
return;
}
usage_counters_.num_put_image_data_calls++;
usage_counters_.area_put_image_data_calls += dirty_width * dirty_height;
if (data->BufferBase()->IsNeutered()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The source data has been neutered.");
return;
}
@@ -1911,7 +1915,7 @@ void BaseRenderingContext2D::CheckOverdraw(
const PaintFlags* flags,
CanvasRenderingContext2DState::ImageType image_type,
DrawType draw_type) {
- PaintCanvas* c = DrawingCanvas();
+ cc::PaintCanvas* c = DrawingCanvas();
if (!c)
return;
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h
index 89e18e7b22d..a5ba638548a 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.h
@@ -18,11 +18,11 @@
#include "third_party/blink/renderer/platform/graphics/canvas_heuristic_parameters.h"
#include "third_party/blink/renderer/platform/graphics/color_behavior.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_flags.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/skia/include/effects/SkComposeImageFilter.h"
namespace blink {
-
class CanvasImageSource;
class Color;
class Image;
@@ -64,13 +64,13 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
double lineDashOffset() const;
void setLineDashOffset(double);
- double shadowOffsetX() const;
- void setShadowOffsetX(double);
+ virtual double shadowOffsetX() const;
+ virtual void setShadowOffsetX(double);
- double shadowOffsetY() const;
- void setShadowOffsetY(double);
+ virtual double shadowOffsetY() const;
+ virtual void setShadowOffsetY(double);
- double shadowBlur() const;
+ virtual double shadowBlur() const;
virtual void setShadowBlur(double);
String shadowColor() const;
@@ -233,8 +233,8 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
virtual bool ParseColorOrCurrentColor(Color&,
const String& color_string) const = 0;
- virtual PaintCanvas* DrawingCanvas() const = 0;
- virtual PaintCanvas* ExistingDrawingCanvas() const = 0;
+ virtual cc::PaintCanvas* DrawingCanvas() const = 0;
+ virtual cc::PaintCanvas* ExistingDrawingCanvas() const = 0;
virtual void DisableDeferral(DisableDeferralReason) = 0;
virtual void DidDraw(const SkIRect& dirty_rect) = 0;
@@ -258,7 +258,7 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
return kRGBA8CanvasPixelFormat;
}
- void RestoreMatrixClipStack(PaintCanvas*) const;
+ void RestoreMatrixClipStack(cc::PaintCanvas*) const;
String textAlign() const;
void setTextAlign(const String&);
@@ -395,7 +395,7 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
void DrawPathInternal(const Path&,
CanvasRenderingContext2DState::PaintType,
SkPath::FillType = SkPath::kWinding_FillType);
- void DrawImageInternal(PaintCanvas*,
+ void DrawImageInternal(cc::PaintCanvas*,
CanvasImageSource*,
Image*,
const FloatRect& src_rect,
@@ -413,7 +413,7 @@ class MODULES_EXPORT BaseRenderingContext2D : public GarbageCollectedMixin,
template <typename DrawFunc>
void CompositedDraw(const DrawFunc&,
- PaintCanvas*,
+ cc::PaintCanvas*,
CanvasRenderingContext2DState::PaintType,
CanvasRenderingContext2DState::ImageType);
@@ -488,7 +488,7 @@ bool BaseRenderingContext2D::Draw(
template <typename DrawFunc>
void BaseRenderingContext2D::CompositedDraw(
const DrawFunc& draw_func,
- PaintCanvas* c,
+ cc::PaintCanvas* c,
CanvasRenderingContext2DState::PaintType paint_type,
CanvasRenderingContext2DState::ImageType image_type) {
sk_sp<PaintFilter> filter = StateGetFilter();
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_gradient.cc b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_gradient.cc
index 8711d0e1747..208ab1d939e 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_gradient.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_gradient.cc
@@ -26,10 +26,9 @@
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_gradient.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_pattern.h"
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_style.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -47,15 +46,16 @@ void CanvasGradient::addColorStop(float value,
const String& color_string,
ExceptionState& exception_state) {
if (!(value >= 0 && value <= 1.0f)) {
- exception_state.ThrowDOMException(
- kIndexSizeError, "The provided value (" + String::Number(value) +
- ") is outside the range (0.0, 1.0).");
+ exception_state.ThrowDOMException(DOMExceptionCode::kIndexSizeError,
+ "The provided value (" +
+ String::Number(value) +
+ ") is outside the range (0.0, 1.0).");
return;
}
Color color = 0;
if (!ParseColorOrCurrentColor(color, color_string, nullptr /*canvas*/)) {
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"The value provided ('" + color_string +
"') could not be parsed as a color.");
return;
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.cc b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.cc
index 9790fb624b5..6ddad03501b 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.cc
@@ -35,8 +35,7 @@
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
@@ -55,18 +54,22 @@ void CanvasPath::closePath() {
void CanvasPath::moveTo(float x, float y) {
if (!std::isfinite(x) || !std::isfinite(y))
return;
- if (!IsTransformInvertible())
+ if (!IsTransformInvertible()) {
+ path_.MoveTo(Transform().MapPoint(FloatPoint(x, y)));
return;
+ }
path_.MoveTo(FloatPoint(x, y));
}
void CanvasPath::lineTo(float x, float y) {
if (!std::isfinite(x) || !std::isfinite(y))
return;
- if (!IsTransformInvertible())
- return;
-
FloatPoint p1 = FloatPoint(x, y);
+
+ if (!IsTransformInvertible()) {
+ p1 = Transform().MapPoint(p1);
+ }
+
if (!path_.HasCurrentPoint())
path_.MoveTo(p1);
@@ -77,14 +80,17 @@ void CanvasPath::quadraticCurveTo(float cpx, float cpy, float x, float y) {
if (!std::isfinite(cpx) || !std::isfinite(cpy) || !std::isfinite(x) ||
!std::isfinite(y))
return;
- if (!IsTransformInvertible())
- return;
- if (!path_.HasCurrentPoint())
- path_.MoveTo(FloatPoint(cpx, cpy));
-
FloatPoint p1 = FloatPoint(x, y);
FloatPoint cp = FloatPoint(cpx, cpy);
+ if (!IsTransformInvertible()) {
+ p1 = Transform().MapPoint(p1);
+ cp = Transform().MapPoint(cp);
+ }
+
+ if (!path_.HasCurrentPoint())
+ path_.MoveTo(FloatPoint(cpx, cpy));
+
path_.AddQuadCurveTo(cp, p1);
}
@@ -97,15 +103,19 @@ void CanvasPath::bezierCurveTo(float cp1x,
if (!std::isfinite(cp1x) || !std::isfinite(cp1y) || !std::isfinite(cp2x) ||
!std::isfinite(cp2y) || !std::isfinite(x) || !std::isfinite(y))
return;
- if (!IsTransformInvertible())
- return;
- if (!path_.HasCurrentPoint())
- path_.MoveTo(FloatPoint(cp1x, cp1y));
FloatPoint p1 = FloatPoint(x, y);
FloatPoint cp1 = FloatPoint(cp1x, cp1y);
FloatPoint cp2 = FloatPoint(cp2x, cp2y);
+ if (!IsTransformInvertible()) {
+ p1 = Transform().MapPoint(p1);
+ cp1 = Transform().MapPoint(cp1);
+ cp2 = Transform().MapPoint(cp2);
+ }
+ if (!path_.HasCurrentPoint())
+ path_.MoveTo(FloatPoint(cp1x, cp1y));
+
path_.AddBezierCurveTo(cp1, cp2, p1);
}
@@ -121,17 +131,19 @@ void CanvasPath::arcTo(float x1,
if (r < 0) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
"The radius provided (" + String::Number(r) + ") is negative.");
return;
}
- if (!IsTransformInvertible())
- return;
-
FloatPoint p1 = FloatPoint(x1, y1);
FloatPoint p2 = FloatPoint(x2, y2);
+ if (!IsTransformInvertible()) {
+ p1 = Transform().MapPoint(p1);
+ p2 = Transform().MapPoint(p2);
+ }
+
if (!path_.HasCurrentPoint())
path_.MoveTo(p1);
else if (p1 == path_.CurrentPoint() || p1 == p2 || !r)
@@ -154,10 +166,10 @@ float AdjustEndAngle(float start_angle, float end_angle, bool anticlockwise) {
* from the ellipse's semi-major axis, acts as both the start point and the
* end point.
*/
- if (!anticlockwise && end_angle - start_angle >= twoPiFloat) {
- new_end_angle = start_angle + twoPiFloat;
- } else if (anticlockwise && start_angle - end_angle >= twoPiFloat) {
- new_end_angle = start_angle - twoPiFloat;
+ if (!anticlockwise && end_angle - start_angle >= kTwoPiFloat) {
+ new_end_angle = start_angle + kTwoPiFloat;
+ } else if (anticlockwise && start_angle - end_angle >= kTwoPiFloat) {
+ new_end_angle = start_angle - kTwoPiFloat;
/*
* Otherwise, the arc is the path along the circumference of this ellipse
@@ -173,11 +185,11 @@ float AdjustEndAngle(float start_angle, float end_angle, bool anticlockwise) {
* We preserve backward-compatibility.
*/
} else if (!anticlockwise && start_angle > end_angle) {
- new_end_angle =
- start_angle + (twoPiFloat - fmodf(start_angle - end_angle, twoPiFloat));
+ new_end_angle = start_angle +
+ (kTwoPiFloat - fmodf(start_angle - end_angle, kTwoPiFloat));
} else if (anticlockwise && start_angle < end_angle) {
- new_end_angle =
- start_angle - (twoPiFloat - fmodf(end_angle - start_angle, twoPiFloat));
+ new_end_angle = start_angle -
+ (kTwoPiFloat - fmodf(end_angle - start_angle, kTwoPiFloat));
}
DCHECK(EllipseIsRenderable(start_angle, new_end_angle));
@@ -196,21 +208,22 @@ inline FloatPoint GetPointOnEllipse(float radius_x,
void CanonicalizeAngle(float* start_angle, float* end_angle) {
// Make 0 <= startAngle < 2*PI
- float new_start_angle = fmodf(*start_angle, twoPiFloat);
+ float new_start_angle = fmodf(*start_angle, kTwoPiFloat);
if (new_start_angle < 0) {
- new_start_angle += twoPiFloat;
+ new_start_angle += kTwoPiFloat;
// Check for possible catastrophic cancellation in cases where
// newStartAngle was a tiny negative number (c.f. crbug.com/503422)
- if (new_start_angle >= twoPiFloat)
- new_start_angle -= twoPiFloat;
+ if (new_start_angle >= kTwoPiFloat)
+ new_start_angle -= kTwoPiFloat;
}
float delta = new_start_angle - *start_angle;
*start_angle = new_start_angle;
*end_angle = *end_angle + delta;
- DCHECK(new_start_angle >= 0 && new_start_angle < twoPiFloat);
+ DCHECK_GE(new_start_angle, 0);
+ DCHECK_LT(new_start_angle, kTwoPiFloat);
}
/*
@@ -256,7 +269,8 @@ void DegenerateEllipse(CanvasPath* path,
float end_angle,
bool anticlockwise) {
DCHECK(EllipseIsRenderable(start_angle, end_angle));
- DCHECK(start_angle >= 0 && start_angle < twoPiFloat);
+ DCHECK_GE(start_angle, 0);
+ DCHECK_LT(start_angle, kTwoPiFloat);
DCHECK((anticlockwise && (start_angle - end_angle) >= 0) ||
(!anticlockwise && (end_angle - start_angle) >= 0));
@@ -272,19 +286,19 @@ void DegenerateEllipse(CanvasPath* path,
return;
if (!anticlockwise) {
- // startAngle - fmodf(startAngle, piOverTwoFloat) + piOverTwoFloat is the
- // one of (0, 0.5Pi, Pi, 1.5Pi, 2Pi) that is the closest to startAngle on
- // the clockwise direction.
- for (float angle =
- start_angle - fmodf(start_angle, piOverTwoFloat) + piOverTwoFloat;
- angle < end_angle; angle += piOverTwoFloat) {
+ // start_angle - fmodf(start_angle, kPiOverTwoFloat) + kPiOverTwoFloat is
+ // the one of (0, 0.5Pi, Pi, 1.5Pi, 2Pi) that is the closest to start_angle
+ // on the clockwise direction.
+ for (float angle = start_angle - fmodf(start_angle, kPiOverTwoFloat) +
+ kPiOverTwoFloat;
+ angle < end_angle; angle += kPiOverTwoFloat) {
LineToFloatPoint(
path, center + rotation_matrix.MapPoint(
GetPointOnEllipse(radius_x, radius_y, angle)));
}
} else {
- for (float angle = start_angle - fmodf(start_angle, piOverTwoFloat);
- angle > end_angle; angle -= piOverTwoFloat) {
+ for (float angle = start_angle - fmodf(start_angle, kPiOverTwoFloat);
+ angle > end_angle; angle -= kPiOverTwoFloat) {
LineToFloatPoint(
path, center + rotation_matrix.MapPoint(
GetPointOnEllipse(radius_x, radius_y, angle)));
@@ -310,7 +324,7 @@ void CanvasPath::arc(float x,
if (radius < 0) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
"The radius provided (" + String::Number(radius) + ") is negative.");
return;
}
@@ -346,15 +360,17 @@ void CanvasPath::ellipse(float x,
return;
if (radius_x < 0) {
- exception_state.ThrowDOMException(
- kIndexSizeError, "The major-axis radius provided (" +
- String::Number(radius_x) + ") is negative.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kIndexSizeError,
+ "The major-axis radius provided (" +
+ String::Number(radius_x) +
+ ") is negative.");
return;
}
if (radius_y < 0) {
- exception_state.ThrowDOMException(
- kIndexSizeError, "The minor-axis radius provided (" +
- String::Number(radius_y) + ") is negative.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kIndexSizeError,
+ "The minor-axis radius provided (" +
+ String::Number(radius_y) +
+ ") is negative.");
return;
}
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.h b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.h
index 1fc9829dd27..e2ccb7d10a2 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.h
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.h
@@ -32,6 +32,7 @@
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/graphics/path.h"
+#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
namespace blink {
@@ -76,6 +77,9 @@ class MODULES_EXPORT CanvasPath {
void rect(float x, float y, float width, float height);
virtual bool IsTransformInvertible() const { return true; }
+ virtual AffineTransform Transform() const {
+ return AffineTransform(1, 0, 0, 1, 0, 0);
+ }
protected:
CanvasPath() { path_.SetIsVolatile(true); }
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_pattern.cc b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_pattern.cc
index aced2ee120f..8ada2295747 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_pattern.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_pattern.cc
@@ -25,9 +25,8 @@
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_pattern.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/geometry/dom_matrix_read_only.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -48,7 +47,7 @@ Pattern::RepeatMode CanvasPattern::ParseRepetitionType(
return Pattern::kRepeatModeY;
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"The provided type ('" + type +
"') is not one of 'repeat', 'no-repeat', 'repeat-x', or 'repeat-y'.");
return Pattern::kRepeatModeNone;
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
index fc94fd62336..a854c832f36 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
@@ -36,15 +36,13 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_scroll_into_view_params.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/modules/v8/rendering_context.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.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/resolver/style_resolver.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/css_property_names.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/events/mouse_event.h"
#include "third_party/blink/renderer/core/frame/settings.h"
@@ -56,6 +54,7 @@
#include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_style.h"
#include "third_party/blink/renderer/modules/canvas/canvas2d/hit_region.h"
#include "third_party/blink/renderer/modules/canvas/canvas2d/path_2d.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#include "third_party/blink/renderer/platform/fonts/text_run_paint_info.h"
#include "third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h"
@@ -93,14 +92,14 @@ class CanvasRenderingContext2DAutoRestoreSkCanvas {
CanvasRenderingContext2D* context)
: context_(context), save_count_(0) {
DCHECK(context_);
- PaintCanvas* c = context_->DrawingCanvas();
+ cc::PaintCanvas* c = context_->DrawingCanvas();
if (c) {
save_count_ = c->getSaveCount();
}
}
~CanvasRenderingContext2DAutoRestoreSkCanvas() {
- PaintCanvas* c = context_->DrawingCanvas();
+ cc::PaintCanvas* c = context_->DrawingCanvas();
if (c)
c->restoreToCount(save_count_);
context_->ValidateStateStack();
@@ -147,7 +146,7 @@ CanvasRenderingContext2D::~CanvasRenderingContext2D() = default;
void CanvasRenderingContext2D::ValidateStateStack() const {
#if DCHECK_IS_ON()
- if (PaintCanvas* sk_canvas = ExistingDrawingCanvas()) {
+ if (cc::PaintCanvas* sk_canvas = ExistingDrawingCanvas()) {
// The canvas should always have an initial save frame, to support
// resetting the top level matrix and clip.
DCHECK_GT(sk_canvas->getSaveCount(), 1);
@@ -188,7 +187,7 @@ void CanvasRenderingContext2D::LoseContext(LostContextMode lost_mode) {
if (context_lost_mode_ != kNotLostContext)
return;
context_lost_mode_ = lost_mode;
- if (context_lost_mode_ == kSyntheticLostContext && canvas()) {
+ if (context_lost_mode_ == kSyntheticLostContext && Host()) {
Host()->DiscardResourceProvider();
}
dispatch_context_lost_event_timer_.StartOneShot(TimeDelta(), FROM_HERE);
@@ -310,7 +309,7 @@ void CanvasRenderingContext2D::Reset() {
}
void CanvasRenderingContext2D::RestoreCanvasMatrixClipStack(
- PaintCanvas* c) const {
+ cc::PaintCanvas* c) const {
RestoreMatrixClipStack(c);
}
@@ -413,7 +412,7 @@ void CanvasRenderingContext2D::SnapshotStateForFilter() {
ModifiableState().SetFontForFilter(AccessFont());
}
-PaintCanvas* CanvasRenderingContext2D::DrawingCanvas() const {
+cc::PaintCanvas* CanvasRenderingContext2D::DrawingCanvas() const {
if (isContextLost())
return nullptr;
if (canvas()->GetOrCreateCanvas2DLayerBridge())
@@ -421,7 +420,7 @@ PaintCanvas* CanvasRenderingContext2D::DrawingCanvas() const {
return nullptr;
}
-PaintCanvas* CanvasRenderingContext2D::ExistingDrawingCanvas() const {
+cc::PaintCanvas* CanvasRenderingContext2D::ExistingDrawingCanvas() const {
if (IsPaintable())
return canvas()->GetCanvas2DLayerBridge()->Canvas();
return nullptr;
@@ -796,7 +795,7 @@ void CanvasRenderingContext2D::DrawTextInternal(
// to 0, for example), so update style before grabbing the drawingCanvas.
canvas()->GetDocument().UpdateStyleAndLayoutTreeForNode(canvas());
- PaintCanvas* c = DrawingCanvas();
+ cc::PaintCanvas* c = DrawingCanvas();
if (!c)
return;
@@ -883,7 +882,7 @@ void CanvasRenderingContext2D::DrawTextInternal(
Draw(
[&font, &text_run_paint_info, &location](
- PaintCanvas* c, const PaintFlags* flags) // draw lambda
+ cc::PaintCanvas* c, const PaintFlags* flags) // draw lambda
{
font.DrawBidiText(c, text_run_paint_info, location,
Font::kUseFallbackIfFontNotReady, kCDeviceScaleFactor,
@@ -913,6 +912,10 @@ bool CanvasRenderingContext2D::IsTransformInvertible() const {
return GetState().IsTransformInvertible();
}
+AffineTransform CanvasRenderingContext2D::Transform() const {
+ return GetState().Transform();
+}
+
cc::Layer* CanvasRenderingContext2D::CcLayer() const {
return IsPaintable() ? canvas()->GetCanvas2DLayerBridge()->Layer() : nullptr;
}
@@ -1012,27 +1015,27 @@ void CanvasRenderingContext2D::UpdateElementAccessibility(const Path& path,
void CanvasRenderingContext2D::addHitRegion(const HitRegionOptions& options,
ExceptionState& exception_state) {
if (options.id().IsEmpty() && !options.control()) {
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"Both id and control are null.");
return;
}
if (options.control() &&
!canvas()->IsSupportedInteractiveCanvasFallback(*options.control())) {
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"The control is neither null nor a "
"supported interactive canvas fallback "
"element.");
return;
}
- Path hit_region_path = options.hasPath() ? options.path()->GetPath() : path_;
+ Path hit_region_path = options.path() ? options.path()->GetPath() : path_;
- PaintCanvas* c = DrawingCanvas();
+ cc::PaintCanvas* c = DrawingCanvas();
if (hit_region_path.IsEmpty() || !c || !GetState().IsTransformInvertible() ||
c->isClipEmpty()) {
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"The specified path has no pixels.");
return;
}
@@ -1042,7 +1045,7 @@ void CanvasRenderingContext2D::addHitRegion(const HitRegionOptions& options,
if (GetState().HasClip()) {
hit_region_path.IntersectPath(GetState().GetCurrentClipPath());
if (hit_region_path.IsEmpty()) {
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"The specified path has no pixels.");
}
}
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h
index 04b67476025..093d6c344c0 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.h
@@ -138,7 +138,7 @@ class MODULES_EXPORT CanvasRenderingContext2D final
void LoseContext(LostContextMode) override;
void DidSetSurfaceSize() override;
- void RestoreCanvasMatrixClipStack(PaintCanvas*) const override;
+ void RestoreCanvasMatrixClipStack(cc::PaintCanvas*) const override;
// TaskObserver implementation
void DidProcessTask() final;
@@ -174,8 +174,8 @@ class MODULES_EXPORT CanvasRenderingContext2D final
bool ParseColorOrCurrentColor(Color&, const String& color_string) const final;
- PaintCanvas* DrawingCanvas() const final;
- PaintCanvas* ExistingDrawingCanvas() const final;
+ cc::PaintCanvas* DrawingCanvas() const final;
+ cc::PaintCanvas* ExistingDrawingCanvas() const final;
void DisableDeferral(DisableDeferralReason) final;
void DidDraw(const SkIRect& dirty_rect) final;
@@ -249,6 +249,7 @@ class MODULES_EXPORT CanvasRenderingContext2D final
void Stop() final;
bool IsTransformInvertible() const override;
+ AffineTransform Transform() const override;
cc::Layer* CcLayer() const override;
bool IsCanvas2DBufferValid() const override;
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_api_test.cc b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_api_test.cc
index 5eae308307b..7b1ec006673 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_api_test.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_api_test.cc
@@ -272,7 +272,7 @@ TEST_F(CanvasRenderingContext2DAPITest, CreateImageDataTooBig) {
Context2d()->createImageData(1000000, 1000000, exception_state);
EXPECT_EQ(nullptr, too_big_image_data);
EXPECT_TRUE(exception_state.HadException());
- EXPECT_EQ(kV8RangeError, exception_state.Code());
+ EXPECT_EQ(ESErrorType::kRangeError, exception_state.CodeAs<ESErrorType>());
}
TEST_F(CanvasRenderingContext2DAPITest, GetImageDataTooBig) {
@@ -282,7 +282,7 @@ TEST_F(CanvasRenderingContext2DAPITest, GetImageDataTooBig) {
Context2d()->getImageData(0, 0, 1000000, 1000000, exception_state);
EXPECT_EQ(nullptr, image_data);
EXPECT_TRUE(exception_state.HadException());
- EXPECT_EQ(kV8RangeError, exception_state.Code());
+ EXPECT_EQ(ESErrorType::kRangeError, exception_state.CodeAs<ESErrorType>());
}
TEST_F(CanvasRenderingContext2DAPITest,
@@ -293,14 +293,14 @@ TEST_F(CanvasRenderingContext2DAPITest,
1, -2147483647, 1, -2147483647, exception_state);
EXPECT_EQ(nullptr, image_data);
EXPECT_TRUE(exception_state.HadException());
- EXPECT_EQ(kV8RangeError, exception_state.Code());
+ EXPECT_EQ(ESErrorType::kRangeError, exception_state.CodeAs<ESErrorType>());
exception_state.ClearException();
image_data = Context2d()->getImageData(-2147483647, 1, -2147483647, 1,
exception_state);
EXPECT_EQ(nullptr, image_data);
EXPECT_TRUE(exception_state.HadException());
- EXPECT_EQ(kV8RangeError, exception_state.Code());
+ EXPECT_EQ(ESErrorType::kRangeError, exception_state.CodeAs<ESErrorType>());
}
void ResetCanvasForAccessibilityRectTest(Document& document) {
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.cc b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.cc
index 60128860735..baf2fde9d3a 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.cc
@@ -286,7 +286,8 @@ sk_sp<PaintFilter> CanvasRenderingContext2DState::GetFilterForOffscreenCanvas(
return resolved_filter_;
FilterOperations operations =
- FilterOperationResolver::CreateOffscreenFilterOperations(*filter_value_);
+ FilterOperationResolver::CreateOffscreenFilterOperations(
+ *filter_value_, font_for_filter_);
// We can't reuse m_fillFlags and m_strokeFlags for the filter, since these
// incorporate the global alpha, which isn't applicable here.
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.h b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.h
index 92afb24c0d9..292a085b77b 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.h
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_state.h
@@ -78,7 +78,9 @@ class CanvasRenderingContext2DState final
void ClipPath(const SkPath&, AntiAliasingMode);
bool HasClip() const { return has_clip_; }
bool HasComplexClip() const { return has_complex_clip_; }
- void PlaybackClips(PaintCanvas* canvas) const { clip_list_.Playback(canvas); }
+ void PlaybackClips(cc::PaintCanvas* canvas) const {
+ clip_list_.Playback(canvas);
+ }
const SkPath& GetCurrentClipPath() const {
return clip_list_.GetCurrentClipPath();
}
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
index 416cf6f1c91..5c679f97538 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
@@ -30,12 +30,12 @@
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
+#include "third_party/blink/renderer/platform/graphics/test/fake_canvas_resource_host.h"
#include "third_party/blink/renderer/platform/graphics/test/fake_gles2_interface.h"
#include "third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h"
#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h"
-#include "third_party/blink/renderer/platform/wtf/byte_swap.h"
#include "third_party/skia/include/core/SkColorSpaceXform.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkSurface.h"
@@ -119,6 +119,13 @@ class CanvasRenderingContext2DTest : public PageTestBase {
intptr_t GetCurrentGPUMemoryUsage() const {
return CanvasElement().GetGPUMemoryUsage();
}
+ void DrawSomething() {
+ Canvas2DLayerBridge* bridge = CanvasElement().GetCanvas2DLayerBridge();
+ bridge->DidDraw(FloatRect(0, 0, 1, 1));
+ bridge->FinalizeFrame();
+ // Grabbing an image forces a flush
+ bridge->NewImageSnapshot(kPreferAcceleration);
+ }
void CreateContext(OpacityMode,
String color_space = String(),
@@ -241,7 +248,7 @@ void CanvasRenderingContext2DTest::SetUp() {
void CanvasRenderingContext2DTest::TearDown() {
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
ReplaceMemoryCacheForTesting(global_memory_cache_.Release());
SharedGpuContext::ResetForTesting();
}
@@ -250,7 +257,7 @@ std::unique_ptr<Canvas2DLayerBridge> CanvasRenderingContext2DTest::MakeBridge(
const IntSize& size,
Canvas2DLayerBridge::AccelerationMode acceleration_mode) {
std::unique_ptr<Canvas2DLayerBridge> bridge =
- std::make_unique<Canvas2DLayerBridge>(size, 0, acceleration_mode,
+ std::make_unique<Canvas2DLayerBridge>(size, acceleration_mode,
CanvasColorParams());
bridge->SetCanvasResourceHost(canvas_element_);
return bridge;
@@ -263,7 +270,7 @@ class FakeCanvas2DLayerBridge : public Canvas2DLayerBridge {
FakeCanvas2DLayerBridge(const IntSize& size,
CanvasColorParams color_params,
AccelerationHint hint)
- : Canvas2DLayerBridge(size, 0, kDisableAcceleration, color_params),
+ : Canvas2DLayerBridge(size, kDisableAcceleration, color_params),
is_accelerated_(hint != kPreferNoAcceleration) {}
~FakeCanvas2DLayerBridge() override = default;
bool IsAccelerated() const override { return is_accelerated_; }
@@ -272,7 +279,7 @@ class FakeCanvas2DLayerBridge : public Canvas2DLayerBridge {
is_accelerated_ = is_accelerated;
}
MOCK_METHOD1(DrawFullImage, void(const PaintImage& image));
- MOCK_METHOD1(DidRestoreCanvasMatrixClipStack, void(PaintCanvas*));
+ MOCK_METHOD1(DidRestoreCanvasMatrixClipStack, void(cc::PaintCanvas*));
private:
bool is_accelerated_;
@@ -285,7 +292,6 @@ class MockImageBufferSurfaceForOverwriteTesting : public Canvas2DLayerBridge {
MockImageBufferSurfaceForOverwriteTesting(const IntSize& size,
CanvasColorParams color_params)
: Canvas2DLayerBridge(size,
- 0,
Canvas2DLayerBridge::kDisableAcceleration,
color_params) {}
~MockImageBufferSurfaceForOverwriteTesting() override = default;
@@ -300,8 +306,8 @@ class MockImageBufferSurfaceForOverwriteTesting : public Canvas2DLayerBridge {
std::make_unique<MockImageBufferSurfaceForOverwriteTesting>( \
size, CanvasColorParams()); \
MockImageBufferSurfaceForOverwriteTesting* surface_ptr = mock_surface.get(); \
- CanvasElement().CreateCanvas2DLayerBridgeForTesting(std::move(mock_surface), \
- size); \
+ CanvasElement().SetCanvas2DLayerBridgeForTesting(std::move(mock_surface), \
+ size); \
EXPECT_CALL(*surface_ptr, WillOverwriteCanvas()).Times(EXPECTED_OVERDRAWS); \
Context2d()->save();
@@ -554,7 +560,7 @@ TEST_F(CanvasRenderingContext2DTest, GPUMemoryUpdateForAcceleratedCanvas) {
kPreferAcceleration);
FakeCanvas2DLayerBridge* fake_accelerate_surface_ptr =
fake_accelerate_surface.get();
- CanvasElement().CreateCanvas2DLayerBridgeForTesting(
+ CanvasElement().SetCanvas2DLayerBridgeForTesting(
std::move(fake_accelerate_surface), size);
// 800 = 10 * 10 * 4 * 2 where 10*10 is canvas size, 4 is num of bytes per
// pixel per buffer, and 2 is an estimate of num of gpu buffers required
@@ -584,7 +590,7 @@ TEST_F(CanvasRenderingContext2DTest, GPUMemoryUpdateForAcceleratedCanvas) {
IntSize size2(10, 5);
auto fake_accelerate_surface2 = std::make_unique<FakeCanvas2DLayerBridge>(
size2, CanvasColorParams(), kPreferAcceleration);
- anotherCanvas->CreateCanvas2DLayerBridgeForTesting(
+ anotherCanvas->SetCanvas2DLayerBridgeForTesting(
std::move(fake_accelerate_surface2), size2);
EXPECT_EQ(800, GetCurrentGPUMemoryUsage());
EXPECT_EQ(1200, GetGlobalGPUMemoryUsage());
@@ -632,12 +638,13 @@ TEST_F(CanvasRenderingContext2DTest, ContextDisposedBeforeCanvas) {
TEST_F(CanvasRenderingContext2DTest, MAYBE_GetImageDataDisablesAcceleration) {
ScopedCanvas2dFixedRenderingModeForTest canvas_2d_fixed_rendering_mode(false);
+ GetPage().GetSettings().SetAcceleratedCompositingEnabled(true);
CreateContext(kNonOpaque);
IntSize size(300, 300);
std::unique_ptr<Canvas2DLayerBridge> bridge =
MakeBridge(size, Canvas2DLayerBridge::kForceAccelerationForTesting);
- CanvasElement().CreateCanvas2DLayerBridgeForTesting(std::move(bridge), size);
-
+ CanvasElement().SetCanvas2DLayerBridgeForTesting(std::move(bridge), size);
+ DrawSomething(); // Lock-in gpu acceleration
EXPECT_TRUE(CanvasElement().GetCanvas2DLayerBridge()->IsAccelerated());
EXPECT_EQ(1u, GetGlobalAcceleratedContextCount());
EXPECT_EQ(720000, GetGlobalGPUMemoryUsage());
@@ -697,8 +704,7 @@ TEST_F(CanvasRenderingContext2DTest, TextureUploadHeuristics) {
IntSize size(dst_size, dst_size);
std::unique_ptr<Canvas2DLayerBridge> bridge =
MakeBridge(size, Canvas2DLayerBridge::kEnableAcceleration);
- CanvasElement().CreateCanvas2DLayerBridgeForTesting(std::move(bridge),
- size);
+ CanvasElement().SetCanvas2DLayerBridgeForTesting(std::move(bridge), size);
EXPECT_TRUE(CanvasElement().GetCanvas2DLayerBridge()->IsAccelerated());
EXPECT_EQ(1u, GetGlobalAcceleratedContextCount());
@@ -740,11 +746,11 @@ TEST_F(CanvasRenderingContext2DTest,
IntSize size(10, 10);
auto fake_accelerate_surface = std::make_unique<FakeCanvas2DLayerBridge>(
size, CanvasColorParams(), kPreferAcceleration);
- CanvasElement().CreateCanvas2DLayerBridgeForTesting(
+ CanvasElement().SetCanvas2DLayerBridgeForTesting(
std::move(fake_accelerate_surface), size);
EXPECT_TRUE(CanvasElement().GetCanvas2DLayerBridge());
- EXPECT_FALSE(CanvasElement().GetCanvas2DLayerBridge()->GetResourceProvider());
+ EXPECT_FALSE(CanvasElement().ResourceProvider());
}
TEST_F(CanvasRenderingContext2DTest, DisableAcceleration_UpdateGPUMemoryUsage) {
@@ -753,7 +759,7 @@ TEST_F(CanvasRenderingContext2DTest, DisableAcceleration_UpdateGPUMemoryUsage) {
IntSize size(10, 10);
auto fake_accelerate_surface = std::make_unique<FakeCanvas2DLayerBridge>(
size, CanvasColorParams(), kPreferAcceleration);
- CanvasElement().CreateCanvas2DLayerBridgeForTesting(
+ CanvasElement().SetCanvas2DLayerBridgeForTesting(
std::move(fake_accelerate_surface), size);
CanvasRenderingContext2D* context = Context2d();
@@ -786,12 +792,15 @@ TEST_F(CanvasRenderingContext2DTest,
IntSize size(10, 10);
auto fake_accelerate_surface = std::make_unique<FakeCanvas2DLayerBridge>(
size, CanvasColorParams(), kPreferAcceleration);
- CanvasElement().CreateCanvas2DLayerBridgeForTesting(
+ CanvasElement().SetCanvas2DLayerBridgeForTesting(
std::move(fake_accelerate_surface), size);
+ FakeCanvasResourceHost host(size);
auto fake_deaccelerate_surface = std::make_unique<FakeCanvas2DLayerBridge>(
size, CanvasColorParams(), kPreferNoAcceleration);
- PaintCanvas* paint_canvas_ptr = fake_deaccelerate_surface->Canvas();
+ fake_deaccelerate_surface->SetCanvasResourceHost(&host);
+
+ cc::PaintCanvas* paint_canvas_ptr = fake_deaccelerate_surface->Canvas();
FakeCanvas2DLayerBridge* surface_ptr = fake_deaccelerate_surface.get();
EXPECT_CALL(*fake_deaccelerate_surface, DrawFullImage(_)).Times(1);
@@ -1133,18 +1142,21 @@ class CanvasRenderingContext2DTestWithTestingPlatform
// In these cases, the element should request a compositing update.
TEST_F(CanvasRenderingContext2DTestWithTestingPlatform,
ElementRequestsCompositingUpdateOnHibernateAndWakeUp) {
+ GetPage().GetSettings().SetAcceleratedCompositingEnabled(true);
CreateContext(kNonOpaque);
IntSize size(300, 300);
std::unique_ptr<Canvas2DLayerBridge> bridge =
MakeBridge(size, Canvas2DLayerBridge::kEnableAcceleration);
// Force hibernatation to occur in an immediate task.
bridge->DontUseIdleSchedulingForTesting();
- CanvasElement().CreateCanvas2DLayerBridgeForTesting(std::move(bridge), size);
+ CanvasElement().SetCanvas2DLayerBridgeForTesting(std::move(bridge), size);
EXPECT_TRUE(CanvasElement().GetCanvas2DLayerBridge()->IsAccelerated());
// Take a snapshot to trigger lazy resource provider creation
CanvasElement().GetCanvas2DLayerBridge()->NewImageSnapshot(
kPreferAcceleration);
+ EXPECT_TRUE(!!CanvasElement().ResourceProvider());
+ EXPECT_TRUE(CanvasElement().ResourceProvider()->IsAccelerated());
EXPECT_TRUE(CanvasElement().GetLayoutBoxModelObject());
PaintLayer* layer = CanvasElement().GetLayoutBoxModelObject()->Layer();
EXPECT_TRUE(layer);
@@ -1157,6 +1169,8 @@ TEST_F(CanvasRenderingContext2DTestWithTestingPlatform,
// If enabled, hibernation should cause compositing update.
EXPECT_EQ(!!CANVAS2D_HIBERNATION_ENABLED,
layer->NeedsCompositingInputsUpdate());
+ EXPECT_EQ(!!CANVAS2D_HIBERNATION_ENABLED,
+ !CanvasElement().ResourceProvider());
GetDocument().View()->UpdateAllLifecyclePhases();
EXPECT_FALSE(layer->NeedsCompositingInputsUpdate());
@@ -1177,7 +1191,7 @@ TEST_F(CanvasRenderingContext2DTestWithTestingPlatform,
MakeBridge(size, Canvas2DLayerBridge::kEnableAcceleration);
// Force hibernatation to occur in an immediate task.
bridge->DontUseIdleSchedulingForTesting();
- CanvasElement().CreateCanvas2DLayerBridgeForTesting(std::move(bridge), size);
+ CanvasElement().SetCanvas2DLayerBridgeForTesting(std::move(bridge), size);
EXPECT_TRUE(CanvasElement().GetCanvas2DLayerBridge()->IsAccelerated());
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/clip_list.cc b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/clip_list.cc
index 23178b411ea..b659d3d9293 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/clip_list.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/clip_list.cc
@@ -28,7 +28,7 @@ void ClipList::ClipPath(const SkPath& path,
clip_list_.push_back(new_clip);
}
-void ClipList::Playback(PaintCanvas* canvas) const {
+void ClipList::Playback(cc::PaintCanvas* canvas) const {
for (const ClipOp* it = clip_list_.begin(); it < clip_list_.end(); it++) {
canvas->clipPath(it->path_, SkClipOp::kIntersect,
it->anti_aliasing_mode_ == kAntiAliased);
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/clip_list.h b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/clip_list.h
index 1b4861eb309..6dc8547dbae 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/clip_list.h
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/clip_list.h
@@ -6,12 +6,15 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_CANVAS2D_CLIP_LIST_H_
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
class SkPath;
+namespace cc {
+class PaintCanvas;
+}
+
namespace blink {
class ClipList {
@@ -23,7 +26,7 @@ class ClipList {
~ClipList() = default;
void ClipPath(const SkPath&, AntiAliasingMode, const SkMatrix&);
- void Playback(PaintCanvas*) const;
+ void Playback(cc::PaintCanvas*) const;
const SkPath& GetCurrentClipPath() const;
private:
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/hit_region.cc b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/hit_region.cc
index 263c5ea5806..1ab9abdf56b 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/hit_region.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/hit_region.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/modules/canvas/canvas2d/hit_region.h"
-#include "third_party/blink/renderer/core/dom/ax_object_cache.h"
+#include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/path_2d.idl b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/path_2d.idl
index 29cea1a5724..047b0201aa7 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/canvas2d/path_2d.idl
+++ b/chromium/third_party/blink/renderer/modules/canvas/canvas2d/path_2d.idl
@@ -32,7 +32,7 @@
Constructor,
Constructor(Path2D path),
Constructor(DOMString text),
- Exposed(Worker OffscreenCanvas, Window StableBlinkFeatures, PaintWorklet CSSPaintAPI)
+ Exposed(Worker OffscreenCanvas, Window StableBlinkFeatures, PaintWorklet StableBlinkFeatures)
] interface Path2D {
void addPath(Path2D path, optional DOMMatrix2DInit transform);
diff --git a/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.cc b/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.cc
index bb9e2c1ea63..dfa1d902e3e 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module.cc
@@ -21,7 +21,7 @@ void HTMLCanvasElementModule::getContext(
if (canvas.SurfaceLayerBridge()) {
// The existence of canvas surfaceLayerBridge indicates that
// HTMLCanvasElement.transferControlToOffscreen() has been called.
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Cannot get context from a canvas that "
"has transferred its control to "
"offscreen.");
@@ -40,7 +40,7 @@ OffscreenCanvas* HTMLCanvasElementModule::transferControlToOffscreen(
ExceptionState& exception_state) {
if (canvas.SurfaceLayerBridge()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Cannot transfer control from a canvas for more than one time.");
return nullptr;
}
@@ -55,7 +55,7 @@ OffscreenCanvas* HTMLCanvasElementModule::TransferControlToOffscreenInternal(
ExceptionState& exception_state) {
if (canvas.RenderingContext()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Cannot transfer control from a canvas that has a rendering context.");
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module_support_webgl2_compute.idl b/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module_support_webgl2_compute.idl
new file mode 100644
index 00000000000..2fb9d4ffbc3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/canvas/htmlcanvas/html_canvas_element_module_support_webgl2_compute.idl
@@ -0,0 +1,25 @@
+// 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.
+
+// https://html.spec.whatwg.org/#the-canvas-element
+
+typedef (CanvasRenderingContext2D or
+ WebGLRenderingContext or
+ WebGL2RenderingContext or
+ WebGL2ComputeRenderingContext or
+ ImageBitmapRenderingContext or
+ XRPresentationContext) RenderingContext;
+
+[
+ ImplementedAs=HTMLCanvasElementModule
+] partial interface HTMLCanvasElement
+{
+ // The PermissiveDictionaryConversion extended attribute is needed to allow the
+ // autogenerated code to match the behavior of the custom binding. Web IDL
+ // requires throwing TypeError if the incoming argument is not an object type
+ // (and is not undefined or null). The binding must ignore this.
+ // Related spec issue: https://github.com/whatwg/html/issues/595
+ [RaisesException] RenderingContext? getContext(DOMString contextId, [PermissiveDictionaryConversion] optional CanvasContextCreationAttributesModule attributes);
+ [RuntimeEnabled=OffscreenCanvas, RaisesException, MeasureAs=OffscreenCanvas] OffscreenCanvas transferControlToOffscreen();
+};
diff --git a/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.cc b/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.cc
index c394b51d0ef..f65cafdf570 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/imagebitmap/image_bitmap_rendering_context.cc
@@ -27,7 +27,8 @@ void ImageBitmapRenderingContext::transferFromImageBitmap(
ExceptionState& exception_state) {
if (image_bitmap && image_bitmap->IsNeutered()) {
exception_state.ThrowDOMException(
- kInvalidStateError, "The input ImageBitmap has been detached");
+ DOMExceptionCode::kInvalidStateError,
+ "The input ImageBitmap has been detached");
return;
}
diff --git a/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module.cc b/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module.cc
index d22e4d6f043..4db8f9b06bd 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module.cc
@@ -20,7 +20,7 @@ void OffscreenCanvasModule::getContext(
ExceptionState& exception_state,
OffscreenRenderingContext& result) {
if (offscreen_canvas.IsNeutered()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"OffscreenCanvas object is detached");
return;
}
diff --git a/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module.h b/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module.h
index eba50624b8c..9f26f6ed460 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module.h
+++ b/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module.h
@@ -5,9 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_OFFSCREENCANVAS_OFFSCREEN_CANVAS_MODULE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_CANVAS_OFFSCREENCANVAS_OFFSCREEN_CANVAS_MODULE_H_
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.h"
#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module.idl b/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module.idl
index d7d5fc99904..496e2282b1b 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module.idl
+++ b/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module.idl
@@ -7,7 +7,7 @@
typedef (OffscreenCanvasRenderingContext2D or
WebGLRenderingContext or
WebGL2RenderingContext) OffscreenRenderingContext;
-enum OffscreenRenderingContextType { "2d", "webgl", "webgl2" };
+enum OffscreenRenderingContextType { "2d", "webgl", "webgl2", "webgl2-compute" };
[
ImplementedAs=OffscreenCanvasModule
diff --git a/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module_support_webgl2_compute.idl b/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module_support_webgl2_compute.idl
new file mode 100644
index 00000000000..cc953b87886
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_module_support_webgl2_compute.idl
@@ -0,0 +1,17 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://html.spec.whatwg.org/multipage/scripting.html#the-offscreencanvas-interface
+
+typedef (OffscreenCanvasRenderingContext2D or
+ WebGLRenderingContext or
+ WebGL2RenderingContext or
+ WebGL2ComputeRenderingContext) OffscreenRenderingContext;
+enum OffscreenRenderingContextType { "2d", "webgl", "webgl2", "webgl2-compute" };
+
+[
+ ImplementedAs=OffscreenCanvasModule
+] partial interface OffscreenCanvas {
+ [CallWith=ExecutionContext, RaisesException, RuntimeEnabled=OffscreenCanvas] OffscreenRenderingContext? getContext(OffscreenRenderingContextType contextType, optional CanvasContextCreationAttributesModule attributes);
+};
diff --git a/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_test.cc b/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_test.cc
index 441551058ca..d1e3db9986c 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_test.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_test.cc
@@ -30,8 +30,8 @@ class OffscreenCanvasTest : public PageTestBase {
HTMLCanvasElement& CanvasElement() const { return *canvas_element_; }
OffscreenCanvas& OSCanvas() const { return *offscreen_canvas_; }
- OffscreenCanvasFrameDispatcher* Dispatcher() const {
- return offscreen_canvas_->GetOrCreateFrameDispatcher();
+ CanvasResourceDispatcher* Dispatcher() const {
+ return offscreen_canvas_->GetOrCreateResourceDispatcher();
}
OffscreenCanvasRenderingContext2D& Context() const { return *context_; }
ScriptState* GetScriptState() const {
diff --git a/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc b/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc
index 74cf52e52c5..291c37fc2e1 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc
+++ b/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.cc
@@ -32,7 +32,6 @@ OffscreenCanvasRenderingContext2D::OffscreenCanvasRenderingContext2D(
OffscreenCanvas* canvas,
const CanvasContextCreationAttributesCore& attrs)
: CanvasRenderingContext(canvas, attrs) {
- Host()->RegisterContextToDispatch(this);
ExecutionContext* execution_context = canvas->GetTopExecutionContext();
if (execution_context->IsDocument()) {
Settings* settings = ToDocument(execution_context)->GetSettings();
@@ -53,9 +52,10 @@ void OffscreenCanvasRenderingContext2D::Trace(blink::Visitor* visitor) {
}
void OffscreenCanvasRenderingContext2D::commit() {
+ // TODO(fserb): consolidate this with PushFrame
SkIRect damage_rect(dirty_rect_for_commit_);
dirty_rect_for_commit_.setEmpty();
- Host()->Commit(TransferToStaticBitmapImage(), damage_rect);
+ Host()->Commit(ProduceFrame(), damage_rect);
}
// BaseRenderingContext2D implementation
@@ -96,24 +96,24 @@ bool OffscreenCanvasRenderingContext2D::CanCreateCanvas2dResourceProvider()
CanvasResourceProvider*
OffscreenCanvasRenderingContext2D::GetCanvasResourceProvider() const {
- return offscreenCanvasForBinding()->GetResourceProvider();
+ return Host()->ResourceProvider();
}
void OffscreenCanvasRenderingContext2D::Reset() {
Host()->DiscardResourceProvider();
BaseRenderingContext2D::Reset();
}
-scoped_refptr<StaticBitmapImage>
-OffscreenCanvasRenderingContext2D::TransferToStaticBitmapImage() {
+scoped_refptr<CanvasResource>
+OffscreenCanvasRenderingContext2D::ProduceFrame() {
if (!CanCreateCanvas2dResourceProvider())
return nullptr;
- scoped_refptr<StaticBitmapImage> image =
- GetCanvasResourceProvider()->Snapshot();
- if (!image)
+ scoped_refptr<CanvasResource> frame =
+ GetCanvasResourceProvider()->ProduceFrame();
+ if (!frame)
return nullptr;
- image->SetOriginClean(this->OriginClean());
- return image;
+ frame->SetOriginClean(this->OriginClean());
+ return frame;
}
void OffscreenCanvasRenderingContext2D::PushFrame() {
@@ -121,7 +121,7 @@ void OffscreenCanvasRenderingContext2D::PushFrame() {
return;
SkIRect damage_rect(dirty_rect_for_commit_);
- Host()->PushFrame(TransferToStaticBitmapImage(), damage_rect);
+ Host()->PushFrame(ProduceFrame(), damage_rect);
dirty_rect_for_commit_.setEmpty();
}
@@ -129,9 +129,14 @@ ImageBitmap* OffscreenCanvasRenderingContext2D::TransferToImageBitmap(
ScriptState* script_state) {
WebFeature feature = WebFeature::kOffscreenCanvasTransferToImageBitmap2D;
UseCounter::Count(ExecutionContext::From(script_state), feature);
- scoped_refptr<StaticBitmapImage> image = TransferToStaticBitmapImage();
+
+ if (!CanCreateCanvas2dResourceProvider())
+ return nullptr;
+ scoped_refptr<StaticBitmapImage> image =
+ GetCanvasResourceProvider()->Snapshot();
if (!image)
return nullptr;
+ image->SetOriginClean(this->OriginClean());
if (image->IsTextureBacked()) {
// Before discarding the image resource, we need to flush pending render ops
// to fully resolve the snapshot.
@@ -163,13 +168,14 @@ bool OffscreenCanvasRenderingContext2D::ParseColorOrCurrentColor(
return ::blink::ParseColorOrCurrentColor(color, color_string, nullptr);
}
-PaintCanvas* OffscreenCanvasRenderingContext2D::DrawingCanvas() const {
+cc::PaintCanvas* OffscreenCanvasRenderingContext2D::DrawingCanvas() const {
if (!CanCreateCanvas2dResourceProvider())
return nullptr;
return GetCanvasResourceProvider()->Canvas();
}
-PaintCanvas* OffscreenCanvasRenderingContext2D::ExistingDrawingCanvas() const {
+cc::PaintCanvas* OffscreenCanvasRenderingContext2D::ExistingDrawingCanvas()
+ const {
if (!IsPaintable())
return nullptr;
return GetCanvasResourceProvider()->Canvas();
@@ -196,9 +202,13 @@ sk_sp<PaintFilter> OffscreenCanvasRenderingContext2D::StateGetFilter() {
return GetState().GetFilterForOffscreenCanvas(Host()->Size(), this);
}
+void OffscreenCanvasRenderingContext2D::SnapshotStateForFilter() {
+ ModifiableState().SetFontForFilter(AccessFont());
+}
+
void OffscreenCanvasRenderingContext2D::ValidateStateStack() const {
#if DCHECK_IS_ON()
- if (PaintCanvas* sk_canvas = ExistingDrawingCanvas()) {
+ if (cc::PaintCanvas* sk_canvas = ExistingDrawingCanvas()) {
DCHECK_EQ(static_cast<size_t>(sk_canvas->getSaveCount()),
state_stack_.size() + 1);
}
@@ -210,7 +220,7 @@ bool OffscreenCanvasRenderingContext2D::isContextLost() const {
}
bool OffscreenCanvasRenderingContext2D::IsPaintable() const {
- return offscreenCanvasForBinding()->GetResourceProvider();
+ return offscreenCanvasForBinding()->ResourceProvider();
}
String OffscreenCanvasRenderingContext2D::ColorSpaceAsString() const {
@@ -232,7 +242,7 @@ bool OffscreenCanvasRenderingContext2D::WritePixels(
int x,
int y) {
DCHECK(IsPaintable());
- return offscreenCanvasForBinding()->GetResourceProvider()->WritePixels(
+ return offscreenCanvasForBinding()->ResourceProvider()->WritePixels(
orig_info, pixels, row_bytes, x, y);
}
@@ -374,7 +384,7 @@ void OffscreenCanvasRenderingContext2D::DrawTextInternal(
double y,
CanvasRenderingContext2DState::PaintType paint_type,
double* max_width) {
- PaintCanvas* c = DrawingCanvas();
+ cc::PaintCanvas* c = DrawingCanvas();
if (!c)
return;
@@ -453,7 +463,7 @@ void OffscreenCanvasRenderingContext2D::DrawTextInternal(
Draw(
[&font, &text_run_paint_info, &location](
- PaintCanvas* c, const PaintFlags* flags) // draw lambda
+ cc::PaintCanvas* c, const PaintFlags* flags) // draw lambda
{
font.DrawBidiText(c, text_run_paint_info, location,
Font::kUseFallbackIfFontNotReady, kCDeviceScaleFactor,
diff --git a/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.h b/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.h
index d1bb79e31d6..20a4a78dc59 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.h
+++ b/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.h
@@ -64,7 +64,7 @@ class MODULES_EXPORT OffscreenCanvasRenderingContext2D final
}
scoped_refptr<StaticBitmapImage> GetImage(AccelerationHint) const final;
void Reset() override;
- void RestoreCanvasMatrixClipStack(PaintCanvas* c) const override {
+ void RestoreCanvasMatrixClipStack(cc::PaintCanvas* c) const override {
RestoreMatrixClipStack(c);
}
@@ -93,8 +93,8 @@ class MODULES_EXPORT OffscreenCanvasRenderingContext2D final
bool ParseColorOrCurrentColor(Color&, const String& color_string) const final;
- PaintCanvas* DrawingCanvas() const final;
- PaintCanvas* ExistingDrawingCanvas() const final;
+ cc::PaintCanvas* DrawingCanvas() const final;
+ cc::PaintCanvas* ExistingDrawingCanvas() const final;
void DisableDeferral(DisableDeferralReason) final;
void DidDraw() final;
@@ -102,7 +102,7 @@ class MODULES_EXPORT OffscreenCanvasRenderingContext2D final
bool StateHasFilter() final;
sk_sp<PaintFilter> StateGetFilter() final;
- void SnapshotStateForFilter() final {}
+ void SnapshotStateForFilter() final;
void ValidateStateStack() const final;
@@ -142,7 +142,7 @@ class MODULES_EXPORT OffscreenCanvasRenderingContext2D final
double* max_width = nullptr);
const Font& AccessFont();
- scoped_refptr<StaticBitmapImage> TransferToStaticBitmapImage();
+ scoped_refptr<CanvasResource> ProduceFrame();
String ColorSpaceAsString() const override;
CanvasPixelFormat PixelFormat() const override;
diff --git a/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.idl b/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.idl
index 7b59bdd9c11..aed21d6d0f6 100644
--- a/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.idl
+++ b/chromium/third_party/blink/renderer/modules/canvas/offscreencanvas2d/offscreen_canvas_rendering_context_2d.idl
@@ -11,7 +11,7 @@
// back-reference to the canvas
[ImplementedAs=offscreenCanvasForBinding] readonly attribute OffscreenCanvas canvas;
- void commit();
+ [RuntimeEnabled=OffscreenCanvasCommit] void commit();
// state
void save(); // push state on state stack
diff --git a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc
index 0dadc44d3d3..d681b440b04 100644
--- a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc
+++ b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_promise.cc
@@ -5,20 +5,22 @@
#include "third_party/blink/renderer/modules/clipboard/clipboard_promise.h"
#include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/mojom/page/page_visibility_state.mojom-blink.h"
#include "third_party/blink/public/platform/modules/permissions/permission.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/core/clipboard/clipboard_mime_types.h"
#include "third_party/blink/renderer/core/clipboard/data_object.h"
#include "third_party/blink/renderer/core/clipboard/data_transfer.h"
#include "third_party/blink/renderer/core/clipboard/data_transfer_access_policy.h"
#include "third_party/blink/renderer/core/clipboard/data_transfer_item.h"
#include "third_party/blink/renderer/core/clipboard/data_transfer_item_list.h"
#include "third_party/blink/renderer/core/clipboard/system_clipboard.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_frame.h"
#include "third_party/blink/renderer/modules/permissions/permission_utils.h"
-#include "third_party/blink/renderer/platform/clipboard/clipboard_mime_types.h"
// And now, a brief note about clipboard permissions.
//
@@ -222,6 +224,7 @@ void ClipboardPromise::HandleWriteTextWithPermission(PermissionStatus status) {
}
void ClipboardPromise::Trace(blink::Visitor* visitor) {
+ visitor->Trace(script_state_);
visitor->Trace(script_promise_resolver_);
ContextLifecycleObserver::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_promise.h b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_promise.h
index 3e65c74bb4b..e009bf4ec4f 100644
--- a/chromium/third_party/blink/renderer/modules/clipboard/clipboard_promise.h
+++ b/chromium/third_party/blink/renderer/modules/clipboard/clipboard_promise.h
@@ -57,12 +57,9 @@ class ClipboardPromise final
void HandleWriteText(const String&);
void HandleWriteTextWithPermission(mojom::blink::PermissionStatus);
- ScriptState* script_state_;
-
+ Member<ScriptState> script_state_;
Member<ScriptPromiseResolver> script_promise_resolver_;
-
mojom::blink::PermissionServicePtr permission_service_;
-
mojom::ClipboardBuffer buffer_;
String write_data_;
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/BUILD.gn b/chromium/third_party/blink/renderer/modules/cookie_store/BUILD.gn
index 378a0479ebd..c49be9416da 100644
--- a/chromium/third_party/blink/renderer/modules/cookie_store/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/BUILD.gn
@@ -12,8 +12,11 @@ blink_modules_sources("cookie_store") {
"cookie_store.h",
"extendable_cookie_change_event.cc",
"extendable_cookie_change_event.h",
- "global_cookie_store.cc",
- "global_cookie_store.h",
+ "global_cookie_store_impl.h",
+ "service_worker_global_scope_cookie_store.cc",
+ "service_worker_global_scope_cookie_store.h",
+ "window_cookie_store.cc",
+ "window_cookie_store.h",
]
deps = [
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_change_event.cc b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_change_event.cc
index 24f86d74f53..c91e99e779b 100644
--- a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_change_event.cc
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_change_event.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/cookie_store/cookie_change_event.h"
+#include "third_party/blink/renderer/core/dom/dom_time_stamp.h"
#include "third_party/blink/renderer/modules/cookie_store/cookie_change_event_init.h"
#include "third_party/blink/renderer/modules/cookie_store/cookie_list_item.h"
#include "third_party/blink/renderer/modules/event_modules.h"
@@ -42,4 +43,74 @@ CookieChangeEvent::CookieChangeEvent(const AtomicString& type,
deleted_ = initializer.deleted();
}
+namespace {
+
+String ToCookieListItemSameSite(network::mojom::CookieSameSite same_site) {
+ switch (same_site) {
+ case network::mojom::CookieSameSite::STRICT_MODE:
+ return "strict";
+ case network::mojom::CookieSameSite::LAX_MODE:
+ return "lax";
+ case network::mojom::CookieSameSite::NO_RESTRICTION:
+ return "unrestricted";
+ }
+
+ NOTREACHED();
+}
+
+} // namespace
+
+// static
+void CookieChangeEvent::ToCookieListItem(
+ const WebCanonicalCookie& canonical_cookie,
+ bool is_deleted, // True for the information from a cookie deletion event.
+ CookieListItem& list_item) {
+ list_item.setName(canonical_cookie.Name());
+ list_item.setPath(canonical_cookie.Path());
+ list_item.setSecure(canonical_cookie.IsSecure());
+ list_item.setSameSite(ToCookieListItemSameSite(canonical_cookie.SameSite()));
+
+ // The domain of host-only cookies is the host name, without a dot (.) prefix.
+ String cookie_domain = canonical_cookie.Domain();
+ if (cookie_domain.StartsWith("."))
+ list_item.setDomain(cookie_domain.Substring(1));
+
+ if (!is_deleted) {
+ list_item.setValue(canonical_cookie.Value());
+ if (!canonical_cookie.ExpiryDate().is_null()) {
+ list_item.setExpires(ConvertSecondsToDOMTimeStamp(
+ canonical_cookie.ExpiryDate().ToDoubleT()));
+ }
+ }
+}
+
+// static
+void CookieChangeEvent::ToEventInfo(
+ const WebCanonicalCookie& backend_cookie,
+ ::network::mojom::CookieChangeCause change_cause,
+ HeapVector<CookieListItem>& changed,
+ HeapVector<CookieListItem>& deleted) {
+ switch (change_cause) {
+ case ::network::mojom::CookieChangeCause::INSERTED:
+ case ::network::mojom::CookieChangeCause::EXPLICIT: {
+ CookieListItem& cookie = changed.emplace_back();
+ ToCookieListItem(backend_cookie, false /* is_deleted */, cookie);
+ break;
+ }
+ case ::network::mojom::CookieChangeCause::UNKNOWN_DELETION:
+ case ::network::mojom::CookieChangeCause::EXPIRED:
+ case ::network::mojom::CookieChangeCause::EVICTED:
+ case ::network::mojom::CookieChangeCause::EXPIRED_OVERWRITE: {
+ CookieListItem& cookie = deleted.emplace_back();
+ ToCookieListItem(backend_cookie, true /* is_deleted */, cookie);
+ break;
+ }
+
+ case ::network::mojom::CookieChangeCause::OVERWRITE:
+ // A cookie overwrite causes an OVERWRITE (meaning the old cookie was
+ // deleted) and an INSERTED.
+ break;
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_change_event.h b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_change_event.h
index 978424056cc..0778a306812 100644
--- a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_change_event.h
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_change_event.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_COOKIE_STORE_COOKIE_CHANGE_EVENT_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_COOKIE_STORE_COOKIE_CHANGE_EVENT_H_
+#include "third_party/blink/public/platform/web_canonical_cookie.h"
#include "third_party/blink/renderer/modules/cookie_store/cookie_list_item.h"
#include "third_party/blink/renderer/modules/event_modules.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -48,6 +49,17 @@ class CookieChangeEvent final : public Event {
// GarbageCollected
void Trace(blink::Visitor*) override;
+ static void ToCookieListItem(
+ const WebCanonicalCookie& canonical_cookie,
+ bool is_deleted, // True for information from a cookie deletion event.
+ CookieListItem& cookie);
+
+ // Helper for converting backend event information into a CookieChangeEvent.
+ static void ToEventInfo(const WebCanonicalCookie& cookie,
+ ::network::mojom::CookieChangeCause cause,
+ HeapVector<CookieListItem>& changed,
+ HeapVector<CookieListItem>& deleted);
+
private:
CookieChangeEvent();
CookieChangeEvent(const AtomicString& type,
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_change_event.idl b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_change_event.idl
index 1952c034d4f..bb51c96b3bd 100644
--- a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_change_event.idl
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_change_event.idl
@@ -10,9 +10,10 @@
[
Exposed=Window,
- RuntimeEnabled=AsyncCookies,
+ OriginTrialEnabled=CookieStore,
+ SecureContext,
Constructor(DOMString type, optional CookieChangeEventInit eventInitDict)
] interface CookieChangeEvent : Event {
- [Measure] readonly attribute CookieList changed;
- [Measure] readonly attribute CookieList deleted;
+ [MeasureAs=CookieStoreAPI] readonly attribute CookieList changed;
+ [MeasureAs=CookieStoreAPI] readonly attribute CookieList deleted;
};
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_list_item.idl b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_list_item.idl
index e9d0618eefb..b6380896903 100644
--- a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_list_item.idl
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_list_item.idl
@@ -5,8 +5,13 @@
// https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md
dictionary CookieListItem {
- USVString name;
+ required USVString name;
USVString value;
+ USVString? domain = null;
+ USVString path = "/";
+ DOMTimeStamp? expires = null;
+ boolean secure = true;
+ CookieSameSite sameSite = "strict";
};
typedef sequence<CookieListItem> CookieList;
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.cc b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.cc
index e54686eb520..6c64e148dc0 100644
--- a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.cc
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.cc
@@ -11,15 +11,17 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/dom/exception_code.h"
+#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/modules/cookie_store/cookie_change_event.h"
#include "third_party/blink/renderer/modules/cookie_store/cookie_list_item.h"
+#include "third_party/blink/renderer/modules/cookie_store/cookie_store_delete_options.h"
#include "third_party/blink/renderer/modules/cookie_store/cookie_store_get_options.h"
+#include "third_party/blink/renderer/modules/cookie_store/cookie_store_set_extra_options.h"
#include "third_party/blink/renderer/modules/cookie_store/cookie_store_set_options.h"
#include "third_party/blink/renderer/modules/event_modules.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
@@ -34,14 +36,13 @@ namespace {
// Returns null if and only if an exception is thrown.
network::mojom::blink::CookieManagerGetOptionsPtr ToBackendOptions(
- const String& name, // Value of the "name" positional argument.
const CookieStoreGetOptions& options,
ExceptionState& exception_state) {
auto backend_options = network::mojom::blink::CookieManagerGetOptions::New();
// TODO(crbug.com/729800): Handle the url option.
- if (options.matchType() == "startsWith") {
+ if (options.matchType() == "starts-with") {
backend_options->match_type =
network::mojom::blink::CookieMatchType::STARTS_WITH;
} else {
@@ -50,133 +51,84 @@ network::mojom::blink::CookieManagerGetOptionsPtr ToBackendOptions(
network::mojom::blink::CookieMatchType::EQUALS;
}
- if (name.IsNull()) {
- if (options.hasName()) {
- backend_options->name = options.name();
- } else {
- // No name provided. Use a filter that matches all cookies. This overrides
- // a user-provided matchType.
- backend_options->match_type =
- network::mojom::blink::CookieMatchType::STARTS_WITH;
- backend_options->name = g_empty_string;
- }
+ if (options.hasName()) {
+ backend_options->name = options.name();
} else {
- if (options.hasName()) {
- exception_state.ThrowTypeError(
- "Cookie name specified both as an argument and as an option");
- return nullptr;
- }
- backend_options->name = name;
+ // No name provided. Use a filter that matches all cookies. This overrides
+ // a user-provided matchType.
+ backend_options->match_type =
+ network::mojom::blink::CookieMatchType::STARTS_WITH;
+ backend_options->name = g_empty_string;
}
return backend_options;
}
-// Returns null if and only if an exception is thrown.
-network::mojom::blink::CanonicalCookiePtr ToCanonicalCookie(
+// Returns no value if and only if an exception is thrown.
+base::Optional<WebCanonicalCookie> ToWebCanonicalCookie(
const KURL& cookie_url,
- const String& name, // Value of the "name" positional argument.
- const String& value, // Value of the "value" positional argument.
- bool for_deletion, // True for CookieStore.delete, false for set.
- const CookieStoreSetOptions& options,
+ const CookieStoreSetExtraOptions& options,
ExceptionState& exception_state) {
- auto canonical_cookie = network::mojom::blink::CanonicalCookie::New();
-
- if (name.IsNull()) {
- if (!options.hasName()) {
- exception_state.ThrowTypeError("Unspecified cookie name");
- return nullptr;
- }
- canonical_cookie->name = options.name();
- } else {
- if (options.hasName()) {
- exception_state.ThrowTypeError(
- "Cookie name specified both as an argument and as an option");
- return nullptr;
- }
- canonical_cookie->name = name;
+ const String& name = options.name();
+ const String& value = options.value();
+ if (name.IsEmpty() && value.Contains('=')) {
+ exception_state.ThrowTypeError(
+ "Cookie value cannot contain '=' if the name is empty");
+ return base::nullopt;
}
- if (for_deletion) {
- DCHECK(value.IsNull());
- if (options.hasValue()) {
- exception_state.ThrowTypeError(
- "Cookie value is meaningless when deleting");
- return nullptr;
- }
- canonical_cookie->value = g_empty_string;
+ WTF::Time expires = options.hasExpires()
+ ? WTF::Time::FromJavaTime(options.expires())
+ : WTF::Time();
- if (options.hasExpires()) {
- exception_state.ThrowTypeError(
- "Cookie expiration time is meaningless when deleting");
- return nullptr;
- }
- canonical_cookie->expiry = WTF::Time::Min();
- } else {
- if (value.IsNull()) {
- if (!options.hasValue()) {
- exception_state.ThrowTypeError("Unspecified cookie value");
- return nullptr;
- }
- canonical_cookie->value = options.value();
- } else {
- if (options.hasValue()) {
- exception_state.ThrowTypeError(
- "Cookie value specified both as an argument and as an option");
- return nullptr;
- }
- canonical_cookie->value = value;
+ String cookie_url_host = cookie_url.Host();
+ String domain;
+ if (options.hasDomain()) {
+ // The leading dot (".") from the domain attribute is stripped in the
+ // Set-Cookie header, for compatibility. This API doesn't have compatibility
+ // constraints, so reject the edge case outright.
+ if (options.domain().StartsWith(".")) {
+ exception_state.ThrowTypeError("Cookie domain cannot start with \".\"");
+ return base::nullopt;
}
- if (canonical_cookie->name.IsEmpty() &&
- canonical_cookie->value.Contains('=')) {
+ domain = String(".") + options.domain();
+ if (!cookie_url_host.EndsWith(domain) &&
+ cookie_url_host != options.domain()) {
exception_state.ThrowTypeError(
- "Cookie value cannot contain '=' if the name is empty.");
- return nullptr;
+ "Cookie domain must domain-match current host");
+ return base::nullopt;
}
-
- if (options.hasExpires())
- canonical_cookie->expiry = WTF::Time::FromJavaTime(options.expires());
- // The expires option is not set in CookieStoreSetOptions for session
- // cookies. This is represented by a null expiry field in CanonicalCookie.
- }
-
- if (options.hasDomain()) {
- // TODO(crbug.com/729800): Checks and exception throwing.
- canonical_cookie->domain = options.domain();
} else {
- // TODO(crbug.com/729800): Correct value?
- canonical_cookie->domain = cookie_url.Host();
+ // The absence of "domain" implies a host-only cookie.
+ domain = cookie_url_host;
}
- if (options.hasPath()) {
- canonical_cookie->path = options.path();
- } else {
- canonical_cookie->path = String("/");
- }
+ // The cookie store API is only exposed on secure origins. If this changes:
+ // 1) The secure option must default to false for insecure origins.
+ // 2) Only secure origins can set the "secure" option to true.
+ DCHECK(SecurityOrigin::IsSecure(cookie_url));
- bool is_secure_origin = SecurityOrigin::IsSecure(cookie_url);
- if (options.hasSecure()) {
- canonical_cookie->secure = options.secure();
- } else {
- canonical_cookie->secure = is_secure_origin;
+ const bool secure = options.secure();
+ if (!secure && (name.StartsWith("__Secure-") || name.StartsWith("__Host-"))) {
+ exception_state.ThrowTypeError(
+ "__Secure- and __Host- cookies must be secure");
}
- if (name.StartsWith("__Secure-") || name.StartsWith("__Host-")) {
- if (!canonical_cookie->secure) {
- exception_state.ThrowTypeError(
- "__Secure- and __Host- cookies must be secure");
- return nullptr;
- }
- if (!is_secure_origin) {
- exception_state.ThrowTypeError(
- "__Secure- and __Host- cookies must be written from secure origin");
- return nullptr;
- }
+ network::mojom::CookieSameSite same_site;
+ if (options.sameSite() == "strict") {
+ same_site = network::mojom::CookieSameSite::STRICT_MODE;
+ } else if (options.sameSite() == "lax") {
+ same_site = network::mojom::CookieSameSite::LAX_MODE;
+ } else {
+ DCHECK_EQ(options.sameSite(), "unrestricted");
+ same_site = network::mojom::CookieSameSite::NO_RESTRICTION;
}
- canonical_cookie->httponly = options.httpOnly();
- return canonical_cookie;
+ return WebCanonicalCookie::Create(
+ name, value, domain, options.path(), WTF::Time() /*creation*/, expires,
+ WTF::Time() /*last_access*/, secure, options.httpOnly(), same_site,
+ WebCanonicalCookie::kDefaultPriority);
}
// Returns null if and only if an exception is thrown.
@@ -195,7 +147,7 @@ blink::mojom::blink::CookieChangeSubscriptionPtr ToBackendSubscription(
backend_subscription->url = default_cookie_url;
}
- if (subscription.matchType() == "startsWith") {
+ if (subscription.matchType() == "starts-with") {
backend_subscription->match_type =
network::mojom::blink::CookieMatchType::STARTS_WITH;
} else {
@@ -217,15 +169,6 @@ blink::mojom::blink::CookieChangeSubscriptionPtr ToBackendSubscription(
return backend_subscription;
}
-void ToCookieListItem(
- const network::mojom::blink::CanonicalCookiePtr& canonical_cookie,
- bool is_deleted, // True for the information from a cookie deletion event.
- CookieListItem& cookie) {
- cookie.setName(canonical_cookie->name);
- if (!is_deleted)
- cookie.setValue(canonical_cookie->value);
-}
-
void ToCookieChangeSubscription(
const blink::mojom::blink::CookieChangeSubscription& backend_subscription,
CookieStoreGetOptions& subscription) {
@@ -239,7 +182,7 @@ void ToCookieChangeSubscription(
switch (backend_subscription.match_type) {
case network::mojom::blink::CookieMatchType::STARTS_WITH:
- subscription.setMatchType(WTF::String("startsWith"));
+ subscription.setMatchType(WTF::String("starts-with"));
break;
case network::mojom::blink::CookieMatchType::EQUALS:
subscription.setMatchType(WTF::String("equals"));
@@ -282,75 +225,93 @@ KURL DefaultSiteForCookies(ExecutionContext* execution_context) {
CookieStore::~CookieStore() = default;
ScriptPromise CookieStore::getAll(ScriptState* script_state,
- const CookieStoreGetOptions& options,
+ const String& name,
ExceptionState& exception_state) {
- return getAll(script_state, WTF::String(), options, exception_state);
+ CookieStoreGetOptions options;
+ options.setName(name);
+ return getAll(script_state, options, exception_state);
}
ScriptPromise CookieStore::getAll(ScriptState* script_state,
- const String& name,
const CookieStoreGetOptions& options,
ExceptionState& exception_state) {
- return DoRead(script_state, name, options,
- &CookieStore::GetAllForUrlToGetAllResult, exception_state);
-}
+ UseCounter::Count(CurrentExecutionContext(script_state->GetIsolate()),
+ WebFeature::kCookieStoreAPI);
-ScriptPromise CookieStore::get(ScriptState* script_state,
- const CookieStoreGetOptions& options,
- ExceptionState& exception_state) {
- return get(script_state, WTF::String(), options, exception_state);
+ return DoRead(script_state, options, &CookieStore::GetAllForUrlToGetAllResult,
+ exception_state);
}
ScriptPromise CookieStore::get(ScriptState* script_state,
const String& name,
- const CookieStoreGetOptions& options,
ExceptionState& exception_state) {
- return DoRead(script_state, name, options,
- &CookieStore::GetAllForUrlToGetResult, exception_state);
+ CookieStoreGetOptions options;
+ options.setName(name);
+ return get(script_state, options, exception_state);
}
-ScriptPromise CookieStore::has(ScriptState* script_state,
+ScriptPromise CookieStore::get(ScriptState* script_state,
const CookieStoreGetOptions& options,
ExceptionState& exception_state) {
- return has(script_state, WTF::String(), options, exception_state);
-}
+ UseCounter::Count(CurrentExecutionContext(script_state->GetIsolate()),
+ WebFeature::kCookieStoreAPI);
-ScriptPromise CookieStore::has(ScriptState* script_state,
- const String& name,
- const CookieStoreGetOptions& options,
- ExceptionState& exception_state) {
- return DoRead(script_state, name, options,
- &CookieStore::GetAllForUrlToHasResult, exception_state);
+ return DoRead(script_state, options, &CookieStore::GetAllForUrlToGetResult,
+ exception_state);
}
ScriptPromise CookieStore::set(ScriptState* script_state,
+ const String& name,
+ const String& value,
const CookieStoreSetOptions& options,
ExceptionState& exception_state) {
- return set(script_state, WTF::String(), WTF::String(), options,
- exception_state);
+ CookieStoreSetExtraOptions set_options;
+ set_options.setName(name);
+ set_options.setValue(value);
+ if (options.hasExpires())
+ set_options.setExpires(options.expires());
+ set_options.setDomain(options.domain());
+ set_options.setPath(options.path());
+ set_options.setSecure(options.secure());
+ set_options.setHttpOnly(options.httpOnly());
+ set_options.setSameSite(options.sameSite());
+ return set(script_state, set_options, exception_state);
}
ScriptPromise CookieStore::set(ScriptState* script_state,
- const String& name,
- const String& value,
- const CookieStoreSetOptions& options,
+ const CookieStoreSetExtraOptions& options,
ExceptionState& exception_state) {
- return DoWrite(script_state, name, value, options, false /* is_deletion */,
- exception_state);
+ UseCounter::Count(CurrentExecutionContext(script_state->GetIsolate()),
+ WebFeature::kCookieStoreAPI);
+
+ return DoWrite(script_state, options, exception_state);
}
ScriptPromise CookieStore::Delete(ScriptState* script_state,
- const CookieStoreSetOptions& options,
+ const String& name,
ExceptionState& exception_state) {
- return Delete(script_state, WTF::String(), options, exception_state);
+ UseCounter::Count(CurrentExecutionContext(script_state->GetIsolate()),
+ WebFeature::kCookieStoreAPI);
+
+ CookieStoreSetExtraOptions set_options;
+ set_options.setName(name);
+ set_options.setValue(g_empty_string);
+ set_options.setExpires(0);
+ return DoWrite(script_state, set_options, exception_state);
}
ScriptPromise CookieStore::Delete(ScriptState* script_state,
- const String& name,
- const CookieStoreSetOptions& options,
+ const CookieStoreDeleteOptions& options,
ExceptionState& exception_state) {
- return DoWrite(script_state, name, WTF::String(), options,
- true /* is_deletion */, exception_state);
+ CookieStoreSetExtraOptions set_options;
+ set_options.setName(options.name());
+ set_options.setValue(g_empty_string);
+ set_options.setExpires(0);
+ set_options.setDomain(options.domain());
+ set_options.setPath(options.path());
+ set_options.setSecure(options.secure());
+ set_options.setSameSite(options.sameSite());
+ return DoWrite(script_state, set_options, exception_state);
}
ScriptPromise CookieStore::subscribeToChanges(
@@ -359,6 +320,9 @@ ScriptPromise CookieStore::subscribeToChanges(
ExceptionState& exception_state) {
DCHECK(GetExecutionContext()->IsServiceWorkerGlobalScope());
+ UseCounter::Count(CurrentExecutionContext(script_state->GetIsolate()),
+ WebFeature::kCookieStoreAPI);
+
Vector<blink::mojom::blink::CookieChangeSubscriptionPtr>
backend_subscriptions;
backend_subscriptions.ReserveInitialCapacity(subscriptions.size());
@@ -366,13 +330,15 @@ ScriptPromise CookieStore::subscribeToChanges(
blink::mojom::blink::CookieChangeSubscriptionPtr backend_subscription =
ToBackendSubscription(default_cookie_url_, subscription,
exception_state);
- if (backend_subscription.is_null())
- return ScriptPromise(); // ToBackendSubscription has thrown an exception.
+ if (backend_subscription.is_null()) {
+ DCHECK(exception_state.HadException());
+ return ScriptPromise();
+ }
backend_subscriptions.emplace_back(std::move(backend_subscription));
}
if (!subscription_backend_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"CookieStore backend went away");
return ScriptPromise();
}
@@ -400,8 +366,11 @@ ScriptPromise CookieStore::getChangeSubscriptions(
ExceptionState& exception_state) {
DCHECK(GetExecutionContext()->IsServiceWorkerGlobalScope());
+ UseCounter::Count(CurrentExecutionContext(script_state->GetIsolate()),
+ WebFeature::kCookieStoreAPI);
+
if (!subscription_backend_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"CookieStore backend went away");
return ScriptPromise();
}
@@ -438,37 +407,15 @@ void CookieStore::RemoveAllEventListeners() {
}
void CookieStore::OnCookieChange(
- network::mojom::blink::CanonicalCookiePtr backend_cookie,
+ const WebCanonicalCookie& backend_cookie,
network::mojom::blink::CookieChangeCause change_cause) {
HeapVector<CookieListItem> changed, deleted;
-
- switch (change_cause) {
- case ::network::mojom::blink::CookieChangeCause::INSERTED:
- case ::network::mojom::blink::CookieChangeCause::EXPLICIT: {
- CookieListItem& cookie = changed.emplace_back();
- ToCookieListItem(backend_cookie, false /* is_deleted */, cookie);
- break;
- }
- case ::network::mojom::blink::CookieChangeCause::UNKNOWN_DELETION:
- case ::network::mojom::blink::CookieChangeCause::EXPIRED:
- case ::network::mojom::blink::CookieChangeCause::EVICTED:
- case ::network::mojom::blink::CookieChangeCause::EXPIRED_OVERWRITE: {
- CookieListItem& cookie = deleted.emplace_back();
- ToCookieListItem(backend_cookie, true /* is_deleted */, cookie);
- break;
- }
-
- case ::network::mojom::blink::CookieChangeCause::OVERWRITE:
- // A cookie overwrite causes an OVERWRITE (meaning the old cookie was
- // deleted) and an INSERTED.
- break;
- }
-
+ CookieChangeEvent::ToEventInfo(backend_cookie, change_cause, changed,
+ deleted);
if (changed.IsEmpty() && deleted.IsEmpty()) {
// The backend only reported OVERWRITE events, which are dropped.
return;
}
-
DispatchEvent(CookieChangeEvent::Create(
EventTypeNames::change, std::move(changed), std::move(deleted)));
}
@@ -505,17 +452,18 @@ CookieStore::CookieStore(
ScriptPromise CookieStore::DoRead(
ScriptState* script_state,
- const String& name,
const CookieStoreGetOptions& options,
DoReadBackendResultConverter backend_result_converter,
ExceptionState& exception_state) {
network::mojom::blink::CookieManagerGetOptionsPtr backend_options =
- ToBackendOptions(name, options, exception_state);
- if (backend_options.is_null())
- return ScriptPromise(); // ToBackendOptions has thrown an exception.
+ ToBackendOptions(options, exception_state);
+ if (backend_options.is_null()) {
+ DCHECK(exception_state.HadException());
+ return ScriptPromise();
+ }
if (!backend_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"CookieStore backend went away");
return ScriptPromise();
}
@@ -531,16 +479,17 @@ ScriptPromise CookieStore::DoRead(
// static
void CookieStore::GetAllForUrlToGetAllResult(
ScriptPromiseResolver* resolver,
- Vector<network::mojom::blink::CanonicalCookiePtr> backend_cookies) {
+ const Vector<WebCanonicalCookie>& backend_cookies) {
ScriptState* script_state = resolver->GetScriptState();
if (!script_state->ContextIsValid())
return;
HeapVector<CookieListItem> cookies;
cookies.ReserveInitialCapacity(backend_cookies.size());
- for (const auto& canonical_cookie : backend_cookies) {
+ for (const auto& backend_cookie : backend_cookies) {
CookieListItem& cookie = cookies.emplace_back();
- ToCookieListItem(canonical_cookie, false /* is_deleted */, cookie);
+ CookieChangeEvent::ToCookieListItem(backend_cookie, false /* is_deleted */,
+ cookie);
}
resolver->Resolve(std::move(cookies));
@@ -549,7 +498,7 @@ void CookieStore::GetAllForUrlToGetAllResult(
// static
void CookieStore::GetAllForUrlToGetResult(
ScriptPromiseResolver* resolver,
- Vector<network::mojom::blink::CanonicalCookiePtr> backend_cookies) {
+ const Vector<WebCanonicalCookie>& backend_cookies) {
ScriptState* script_state = resolver->GetScriptState();
if (!script_state->ContextIsValid())
return;
@@ -559,44 +508,32 @@ void CookieStore::GetAllForUrlToGetResult(
return;
}
- const auto& canonical_cookie = backend_cookies.front();
+ const auto& backend_cookie = backend_cookies.front();
CookieListItem cookie;
- ToCookieListItem(canonical_cookie, false /* is_deleted */, cookie);
+ CookieChangeEvent::ToCookieListItem(backend_cookie, false /* is_deleted */,
+ cookie);
resolver->Resolve(cookie);
}
-// static
-void CookieStore::GetAllForUrlToHasResult(
- ScriptPromiseResolver* resolver,
- Vector<network::mojom::blink::CanonicalCookiePtr> backend_cookies) {
- ScriptState* script_state = resolver->GetScriptState();
- if (!script_state->ContextIsValid())
- return;
-
- resolver->Resolve(!backend_cookies.IsEmpty());
-}
-
ScriptPromise CookieStore::DoWrite(ScriptState* script_state,
- const String& name,
- const String& value,
- const CookieStoreSetOptions& options,
- bool is_deletion,
+ const CookieStoreSetExtraOptions& options,
ExceptionState& exception_state) {
- network::mojom::blink::CanonicalCookiePtr canonical_cookie =
- ToCanonicalCookie(default_cookie_url_, name, value, is_deletion, options,
- exception_state);
- if (canonical_cookie.is_null())
- return ScriptPromise(); // ToCanonicalCookie has thrown an exception.
+ base::Optional<WebCanonicalCookie> canonical_cookie =
+ ToWebCanonicalCookie(default_cookie_url_, options, exception_state);
+ if (!canonical_cookie) {
+ DCHECK(exception_state.HadException());
+ return ScriptPromise();
+ }
if (!backend_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"CookieStore backend went away");
return ScriptPromise();
}
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
backend_->SetCanonicalCookie(
- std::move(canonical_cookie), default_cookie_url_,
+ std::move(canonical_cookie.value()), default_cookie_url_,
default_site_for_cookies_,
WTF::Bind(&CookieStore::OnSetCanonicalCookieResult,
WrapPersistent(resolver)));
@@ -612,7 +549,8 @@ void CookieStore::OnSetCanonicalCookieResult(ScriptPromiseResolver* resolver,
if (!backend_success) {
resolver->Reject(DOMException::Create(
- kUnknownError, "An unknown error occured while writing the cookie."));
+ DOMExceptionCode::kUnknownError,
+ "An unknown error occured while writing the cookie."));
return;
}
resolver->Resolve();
@@ -628,7 +566,7 @@ void CookieStore::OnSubscribeToCookieChangesResult(
if (!backend_success) {
resolver->Reject(DOMException::Create(
- kUnknownError,
+ DOMExceptionCode::kUnknownError,
"An unknown error occured while subscribing to cookie changes."));
return;
}
@@ -646,7 +584,7 @@ void CookieStore::OnGetCookieChangeSubscriptionResult(
if (!backend_success) {
resolver->Reject(DOMException::Create(
- kUnknownError,
+ DOMExceptionCode::kUnknownError,
"An unknown error occured while reading cookie change subscriptions."));
return;
}
@@ -668,7 +606,7 @@ void CookieStore::StartObserving() {
network::mojom::blink::CookieChangeListenerPtr change_listener;
change_listener_binding_.Bind(mojo::MakeRequest(&change_listener));
backend_->AddChangeListener(default_cookie_url_, default_site_for_cookies_,
- std::move(change_listener));
+ std::move(change_listener), {});
}
void CookieStore::StopObserving() {
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.h b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.h
index 8a9bd42025f..3344bb5233d 100644
--- a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.h
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.h
@@ -8,10 +8,11 @@
#include "mojo/public/cpp/bindings/binding.h"
#include "services/network/public/mojom/restricted_cookie_manager.mojom-blink.h"
#include "third_party/blink/public/mojom/cookie_store/cookie_store.mojom-blink.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/public/platform/web_canonical_cookie.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/dom/events/event_target.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/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -19,8 +20,10 @@
namespace blink {
+class CookieStoreDeleteOptions;
class CookieStoreGetOptions;
class CookieStoreSetOptions;
+class CookieStoreSetExtraOptions;
class ScriptPromiseResolver;
class ScriptState;
@@ -42,42 +45,26 @@ class CookieStore final : public EventTargetWithInlineData,
std::move(subscription_backend));
}
+ ScriptPromise getAll(ScriptState*, const String& name, ExceptionState&);
ScriptPromise getAll(ScriptState*,
const CookieStoreGetOptions&,
ExceptionState&);
- ScriptPromise getAll(ScriptState*,
- const String& name,
- const CookieStoreGetOptions&,
- ExceptionState&);
+ ScriptPromise get(ScriptState*, const String& name, ExceptionState&);
ScriptPromise get(ScriptState*,
const CookieStoreGetOptions&,
ExceptionState&);
- ScriptPromise get(ScriptState*,
- const String& name,
- const CookieStoreGetOptions&,
- ExceptionState&);
- ScriptPromise has(ScriptState*,
- const CookieStoreGetOptions&,
- ExceptionState&);
- ScriptPromise has(ScriptState*,
- const String& name,
- const CookieStoreGetOptions&,
- ExceptionState&);
ScriptPromise set(ScriptState*,
- const CookieStoreSetOptions&,
+ const CookieStoreSetExtraOptions&,
ExceptionState&);
ScriptPromise set(ScriptState*,
const String& name,
const String& value,
const CookieStoreSetOptions&,
ExceptionState&);
+ ScriptPromise Delete(ScriptState*, const String& name, ExceptionState&);
ScriptPromise Delete(ScriptState*,
- const CookieStoreSetOptions&,
- ExceptionState&);
- ScriptPromise Delete(ScriptState*,
- const String& name,
- const CookieStoreSetOptions&,
+ const CookieStoreDeleteOptions&,
ExceptionState&);
ScriptPromise subscribeToChanges(
ScriptState*,
@@ -101,7 +88,7 @@ class CookieStore final : public EventTargetWithInlineData,
void RemoveAllEventListeners() override;
// RestrictedCookieChangeListener
- void OnCookieChange(network::mojom::blink::CanonicalCookiePtr,
+ void OnCookieChange(const WebCanonicalCookie&,
network::mojom::blink::CookieChangeCause) override;
protected:
@@ -113,21 +100,19 @@ class CookieStore final : public EventTargetWithInlineData,
private:
using DoReadBackendResultConverter =
- void (*)(ScriptPromiseResolver*,
- Vector<network::mojom::blink::CanonicalCookiePtr>);
+ void (*)(ScriptPromiseResolver*, const Vector<WebCanonicalCookie>&);
CookieStore(ExecutionContext*,
network::mojom::blink::RestrictedCookieManagerPtr backend,
blink::mojom::blink::CookieStorePtr subscription_backend);
- // Common code in CookieStore::{get,getAll,has}.
+ // Common code in CookieStore::{get,getAll}.
//
// All cookie-reading methods use the same RestrictedCookieManager API, and
// only differ in how they present the returned data. The difference is
// captured in the DoReadBackendResultConverter argument, which should point
// to one of the static methods below.
ScriptPromise DoRead(ScriptState*,
- const String& name,
const CookieStoreGetOptions&,
DoReadBackendResultConverter,
ExceptionState&);
@@ -136,26 +121,17 @@ class CookieStore final : public EventTargetWithInlineData,
// the promise result expected by CookieStore.getAll.
static void GetAllForUrlToGetAllResult(
ScriptPromiseResolver*,
- Vector<network::mojom::blink::CanonicalCookiePtr> backend_result);
+ const Vector<WebCanonicalCookie>& backend_result);
// Converts the result of a RestrictedCookieManager::GetAllForUrl mojo call to
// the promise result expected by CookieStore.get.
static void GetAllForUrlToGetResult(
ScriptPromiseResolver*,
- Vector<network::mojom::blink::CanonicalCookiePtr> backend_result);
-
- // Converts the result of a RestrictedCookieManager::GetAllForUrl mojo call to
- // the promise result expected by CookieStore.has.
- static void GetAllForUrlToHasResult(
- ScriptPromiseResolver*,
- Vector<network::mojom::blink::CanonicalCookiePtr> backend_result);
+ const Vector<WebCanonicalCookie>& backend_result);
// Common code in CookieStore::delete and CookieStore::set.
ScriptPromise DoWrite(ScriptState*,
- const String& name,
- const String& value,
- const CookieStoreSetOptions&,
- bool is_deletion,
+ const CookieStoreSetExtraOptions&,
ExceptionState&);
static void OnSetCanonicalCookieResult(ScriptPromiseResolver*,
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.idl b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.idl
index fa49c175f86..74dbdd47222 100644
--- a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.idl
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store.idl
@@ -2,41 +2,37 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md
+// https://wicg.github.io/cookie-store/explainer.html
[
Exposed=(ServiceWorker,Window),
- RuntimeEnabled=AsyncCookies
+ OriginTrialEnabled=CookieStore,
+ SecureContext
] interface CookieStore : EventTarget {
- // https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md#reading
- [CallWith=ScriptState, Measure, RaisesException] Promise<CookieList?> getAll(
- USVString name, optional CookieStoreGetOptions options);
- [CallWith=ScriptState, Measure, RaisesException] Promise<CookieList?> getAll(
- optional CookieStoreGetOptions options);
+ // https://wicg.github.io/cookie-store/explainer.html#the-query-api
[CallWith=ScriptState, Measure, RaisesException] Promise<CookieListItem?> get(
- USVString name, optional CookieStoreGetOptions options);
+ USVString name);
[CallWith=ScriptState, Measure, RaisesException] Promise<CookieListItem?> get(
optional CookieStoreGetOptions options);
- [CallWith=ScriptState, Measure, RaisesException] Promise<boolean> has(
- USVString name, optional CookieStoreGetOptions options);
- [CallWith=ScriptState, Measure, RaisesException] Promise<boolean> has(
+ [CallWith=ScriptState, Measure, RaisesException] Promise<CookieList> getAll(
+ USVString name);
+ [CallWith=ScriptState, Measure, RaisesException] Promise<CookieList> getAll(
optional CookieStoreGetOptions options);
- // https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md#writing
+ // https://wicg.github.io/cookie-store/explainer.html#the-modifications-api
[CallWith=ScriptState, Measure, RaisesException] Promise<void> set(
USVString name, USVString value, optional CookieStoreSetOptions options);
[CallWith=ScriptState, Measure, RaisesException] Promise<void> set(
- CookieStoreSetOptions options);
-
+ CookieStoreSetExtraOptions options);
[CallWith=ScriptState, ImplementedAs=Delete, Measure, RaisesException]
- Promise<void> delete(USVString name, optional CookieStoreSetOptions options);
+ Promise<void> delete(USVString name);
[CallWith=ScriptState, ImplementedAs=Delete, Measure, RaisesException]
- Promise<void> delete(CookieStoreSetOptions options);
+ Promise<void> delete(CookieStoreDeleteOptions options);
+ // https://wicg.github.io/cookie-store/explainer.html#the-change-events-api
[Exposed=ServiceWorker, CallWith=ScriptState, Measure, RaisesException]
Promise<void> subscribeToChanges(
sequence<CookieStoreGetOptions> subscriptions);
-
[Exposed=ServiceWorker, CallWith=ScriptState, Measure, RaisesException]
Promise<sequence<CookieStoreGetOptions>> getChangeSubscriptions();
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store_delete_options.idl b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store_delete_options.idl
new file mode 100644
index 00000000000..e17292e3a14
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store_delete_options.idl
@@ -0,0 +1,13 @@
+// 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.
+
+// https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md
+
+dictionary CookieStoreDeleteOptions {
+ required USVString name;
+ USVString? domain = null;
+ USVString path = "/";
+ boolean secure = true;
+ CookieSameSite sameSite = "strict";
+};
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store_get_options.idl b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store_get_options.idl
index 07ed3baab27..0d6dc418643 100644
--- a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store_get_options.idl
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store_get_options.idl
@@ -6,7 +6,7 @@
enum CookieMatchType {
"equals",
- "startsWith"
+ "starts-with"
};
dictionary CookieStoreGetOptions {
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store_set_extra_options.idl b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store_set_extra_options.idl
new file mode 100644
index 00000000000..0a1b9a112bb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store_set_extra_options.idl
@@ -0,0 +1,10 @@
+// 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.
+
+// https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md
+
+dictionary CookieStoreSetExtraOptions : CookieStoreSetOptions {
+ required USVString name;
+ required USVString value;
+};
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store_set_options.idl b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store_set_options.idl
index b2f4926fbee..2cde6845880 100644
--- a/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store_set_options.idl
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/cookie_store_set_options.idl
@@ -4,12 +4,17 @@
// https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md
+enum CookieSameSite {
+ "strict",
+ "lax",
+ "unrestricted"
+};
+
dictionary CookieStoreSetOptions {
- USVString name;
- USVString value;
DOMTimeStamp? expires = null;
- USVString domain;
+ USVString? domain = null;
USVString path = "/";
- boolean? secure;
+ boolean secure = true;
boolean httpOnly = false;
+ CookieSameSite sameSite = "strict";
};
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.cc b/chromium/third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.cc
index 6de8c053863..8b26aba04b2 100644
--- a/chromium/third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.cc
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.cc
@@ -8,7 +8,7 @@
#include "third_party/blink/renderer/modules/cookie_store/cookie_list_item.h"
#include "third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event_init.h"
#include "third_party/blink/renderer/modules/event_modules.h"
-#include "third_party/blink/renderer/modules/serviceworkers/extendable_event_init.h"
+#include "third_party/blink/renderer/modules/service_worker/extendable_event_init.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -45,21 +45,4 @@ ExtendableCookieChangeEvent::ExtendableCookieChangeEvent(
deleted_ = initializer.deleted();
}
-// static
-void ExtendableCookieChangeEvent::ToCookieChangeListItem(
- const WebString& cookie_name,
- const WebString& cookie_value,
- bool is_cookie_delete,
- HeapVector<CookieListItem>& changed,
- HeapVector<CookieListItem>& deleted) {
- if (is_cookie_delete) {
- CookieListItem& cookie = deleted.emplace_back();
- cookie.setName(cookie_name);
- } else {
- CookieListItem& cookie = changed.emplace_back();
- cookie.setName(cookie_name);
- cookie.setValue(cookie_value);
- }
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.h b/chromium/third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.h
index af810bf2b7e..c0fb5e615d9 100644
--- a/chromium/third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.h
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.h
@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/modules/cookie_store/cookie_list_item.h"
#include "third_party/blink/renderer/modules/event_modules.h"
-#include "third_party/blink/renderer/modules/serviceworkers/extendable_event.h"
+#include "third_party/blink/renderer/modules/service_worker/extendable_event.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -16,7 +16,6 @@ namespace blink {
class ExtendableCookieChangeEventInit;
class WaitUntilObserver;
-class WebString;
class ExtendableCookieChangeEvent final : public ExtendableEvent {
DEFINE_WRAPPERTYPEINFO();
@@ -53,16 +52,6 @@ class ExtendableCookieChangeEvent final : public ExtendableEvent {
// GarbageCollected
void Trace(blink::Visitor*) override;
- // Helper for converting backend event information into a CookieChangeEvent.
- //
- // TODO(pwnall): Switch to blink::CanonicalCookie when
- // https://crrev.com/c/991196 lands.
- static void ToCookieChangeListItem(const WebString& cookie_name,
- const WebString& cookie_value,
- bool is_cookie_delete,
- HeapVector<CookieListItem>& changed,
- HeapVector<CookieListItem>& deleted);
-
private:
ExtendableCookieChangeEvent(const AtomicString& type,
HeapVector<CookieListItem> changed,
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.idl b/chromium/third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.idl
index becd2a5a5a5..f5bbba15119 100644
--- a/chromium/third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.idl
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.idl
@@ -9,9 +9,9 @@
[
Exposed=ServiceWorker,
- RuntimeEnabled=AsyncCookies,
+ OriginTrialEnabled=CookieStore,
Constructor(DOMString type, optional ExtendableCookieChangeEventInit eventInitDict)
] interface ExtendableCookieChangeEvent : ExtendableEvent {
- [Measure] readonly attribute CookieList changed;
- [Measure] readonly attribute CookieList deleted;
+ [MeasureAs=CookieStoreAPI] readonly attribute CookieList changed;
+ [MeasureAs=CookieStoreAPI] readonly attribute CookieList deleted;
};
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/global_cookie_store.cc b/chromium/third_party/blink/renderer/modules/cookie_store/global_cookie_store.cc
deleted file mode 100644
index 816e45a325d..00000000000
--- a/chromium/third_party/blink/renderer/modules/cookie_store/global_cookie_store.cc
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/cookie_store/global_cookie_store.h"
-
-#include <utility>
-
-#include "services/network/public/mojom/restricted_cookie_manager.mojom-blink.h"
-#include "services/service_manager/public/cpp/interface_provider.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/workers/worker_thread.h"
-#include "third_party/blink/renderer/modules/cookie_store/cookie_store.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/supplementable.h"
-
-namespace blink {
-
-namespace {
-
-template <typename T>
-class GlobalCookieStoreImpl final
- : public GarbageCollected<GlobalCookieStoreImpl<T>>,
- public Supplement<T> {
- USING_GARBAGE_COLLECTED_MIXIN(GlobalCookieStoreImpl);
-
- public:
- static const char kSupplementName[];
-
- static GlobalCookieStoreImpl& From(T& supplementable) {
- GlobalCookieStoreImpl* supplement =
- Supplement<T>::template From<GlobalCookieStoreImpl>(supplementable);
- if (!supplement) {
- supplement = new GlobalCookieStoreImpl(supplementable);
- Supplement<T>::ProvideTo(supplementable, supplement);
- }
- return *supplement;
- }
-
- CookieStore* GetCookieStore(T& scope) {
- if (!cookie_store_) {
- ExecutionContext* execution_context = scope.GetExecutionContext();
-
- service_manager::InterfaceProvider* interface_provider =
- execution_context->GetInterfaceProvider();
- if (!interface_provider)
- return nullptr;
- cookie_store_ = BuildCookieStore(execution_context, interface_provider);
- }
- return cookie_store_;
- }
-
- CookieStore* BuildCookieStore(ExecutionContext*,
- service_manager::InterfaceProvider*);
-
- void Trace(blink::Visitor* visitor) override {
- visitor->Trace(cookie_store_);
- Supplement<T>::Trace(visitor);
- }
-
- private:
- explicit GlobalCookieStoreImpl(T& supplementable)
- : Supplement<T>(supplementable) {}
-
- Member<CookieStore> cookie_store_;
-};
-
-template <>
-CookieStore* GlobalCookieStoreImpl<LocalDOMWindow>::BuildCookieStore(
- ExecutionContext* execution_context,
- service_manager::InterfaceProvider* interface_provider) {
- network::mojom::blink::RestrictedCookieManagerPtr cookie_manager_ptr;
- interface_provider->GetInterface(mojo::MakeRequest(&cookie_manager_ptr));
-
- return CookieStore::Create(execution_context, std::move(cookie_manager_ptr),
- blink::mojom::blink::CookieStorePtr());
-}
-
-template <>
-CookieStore* GlobalCookieStoreImpl<WorkerGlobalScope>::BuildCookieStore(
- ExecutionContext* execution_context,
- service_manager::InterfaceProvider* interface_provider) {
- network::mojom::blink::RestrictedCookieManagerPtr cookie_manager_ptr;
- interface_provider->GetInterface(mojo::MakeRequest(&cookie_manager_ptr));
-
- blink::mojom::blink::CookieStorePtr cookie_store_ptr;
- interface_provider->GetInterface(mojo::MakeRequest(&cookie_store_ptr));
-
- return CookieStore::Create(execution_context, std::move(cookie_manager_ptr),
- std::move(cookie_store_ptr));
-}
-
-// static
-template <typename T>
-const char GlobalCookieStoreImpl<T>::kSupplementName[] =
- "GlobalCookieStoreImpl";
-
-} // namespace
-
-CookieStore* GlobalCookieStore::cookieStore(LocalDOMWindow& window) {
- return GlobalCookieStoreImpl<LocalDOMWindow>::From(window).GetCookieStore(
- window);
-}
-
-CookieStore* GlobalCookieStore::cookieStore(ServiceWorkerGlobalScope& worker) {
- // ServiceWorkerGlobalScope is Supplementable<WorkerGlobalScope>, not
- // Supplementable<ServiceWorkerGlobalScope>.
- return GlobalCookieStoreImpl<WorkerGlobalScope>::From(worker).GetCookieStore(
- worker);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/global_cookie_store.h b/chromium/third_party/blink/renderer/modules/cookie_store/global_cookie_store.h
deleted file mode 100644
index 67a9ba62cbb..00000000000
--- a/chromium/third_party/blink/renderer/modules/cookie_store/global_cookie_store.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_COOKIE_STORE_GLOBAL_COOKIE_STORE_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_COOKIE_STORE_GLOBAL_COOKIE_STORE_H_
-
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class CookieStore;
-class LocalDOMWindow;
-class ServiceWorkerGlobalScope;
-
-// Exposes a CookieStore as the "cookieStore" attribute on the global scope.
-//
-// This currently applies to Window scopes.
-class GlobalCookieStore {
- STATIC_ONLY(GlobalCookieStore);
-
- public:
- static CookieStore* cookieStore(LocalDOMWindow&);
- static CookieStore* cookieStore(ServiceWorkerGlobalScope&);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_COOKIE_STORE_GLOBAL_COOKIE_STORE_H_
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/global_cookie_store_impl.h b/chromium/third_party/blink/renderer/modules/cookie_store/global_cookie_store_impl.h
new file mode 100644
index 00000000000..fa8c46e84e9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/global_cookie_store_impl.h
@@ -0,0 +1,71 @@
+// 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_MODULES_COOKIE_STORE_GLOBAL_COOKIE_STORE_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_COOKIE_STORE_GLOBAL_COOKIE_STORE_IMPL_H_
+
+#include <utility>
+
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/renderer/modules/cookie_store/cookie_store.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+
+namespace blink {
+
+template <typename T>
+class GlobalCookieStoreImpl final
+ : public GarbageCollected<GlobalCookieStoreImpl<T>>,
+ public Supplement<T> {
+ USING_GARBAGE_COLLECTED_MIXIN(GlobalCookieStoreImpl);
+
+ public:
+ static const char kSupplementName[];
+
+ static GlobalCookieStoreImpl& From(T& supplementable) {
+ GlobalCookieStoreImpl* supplement =
+ Supplement<T>::template From<GlobalCookieStoreImpl>(supplementable);
+ if (!supplement) {
+ supplement = new GlobalCookieStoreImpl(supplementable);
+ Supplement<T>::ProvideTo(supplementable, supplement);
+ }
+ return *supplement;
+ }
+
+ CookieStore* GetCookieStore(T& scope) {
+ if (!cookie_store_) {
+ ExecutionContext* execution_context = scope.GetExecutionContext();
+
+ service_manager::InterfaceProvider* interface_provider =
+ execution_context->GetInterfaceProvider();
+ if (!interface_provider)
+ return nullptr;
+ cookie_store_ = BuildCookieStore(execution_context, interface_provider);
+ }
+ return cookie_store_;
+ }
+
+ CookieStore* BuildCookieStore(ExecutionContext*,
+ service_manager::InterfaceProvider*);
+
+ void Trace(blink::Visitor* visitor) override {
+ visitor->Trace(cookie_store_);
+ Supplement<T>::Trace(visitor);
+ }
+
+ private:
+ explicit GlobalCookieStoreImpl(T& supplementable)
+ : Supplement<T>(supplementable) {}
+
+ Member<CookieStore> cookie_store_;
+};
+
+// static
+template <typename T>
+const char GlobalCookieStoreImpl<T>::kSupplementName[] =
+ "GlobalCookieStoreImpl";
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_COOKIE_STORE_GLOBAL_COOKIE_STORE_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.cc b/chromium/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.cc
new file mode 100644
index 00000000000..c971b0c8b67
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.cc
@@ -0,0 +1,40 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.h"
+
+#include <utility>
+
+#include "services/network/public/mojom/restricted_cookie_manager.mojom-blink.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/renderer/core/workers/worker_thread.h"
+#include "third_party/blink/renderer/modules/cookie_store/cookie_store.h"
+#include "third_party/blink/renderer/modules/cookie_store/global_cookie_store_impl.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h"
+
+namespace blink {
+
+template <>
+CookieStore* GlobalCookieStoreImpl<WorkerGlobalScope>::BuildCookieStore(
+ ExecutionContext* execution_context,
+ service_manager::InterfaceProvider* interface_provider) {
+ network::mojom::blink::RestrictedCookieManagerPtr cookie_manager_ptr;
+ interface_provider->GetInterface(mojo::MakeRequest(&cookie_manager_ptr));
+
+ blink::mojom::blink::CookieStorePtr cookie_store_ptr;
+ interface_provider->GetInterface(mojo::MakeRequest(&cookie_store_ptr));
+
+ return CookieStore::Create(execution_context, std::move(cookie_manager_ptr),
+ std::move(cookie_store_ptr));
+}
+
+CookieStore* ServiceWorkerGlobalScopeCookieStore::cookieStore(
+ ServiceWorkerGlobalScope& worker) {
+ // ServiceWorkerGlobalScope is Supplementable<WorkerGlobalScope>, not
+ // Supplementable<ServiceWorkerGlobalScope>.
+ return GlobalCookieStoreImpl<WorkerGlobalScope>::From(worker).GetCookieStore(
+ worker);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.h b/chromium/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.h
new file mode 100644
index 00000000000..cf1224ed366
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.h
@@ -0,0 +1,28 @@
+// 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_MODULES_COOKIE_STORE_SERVICE_WORKER_GLOBAL_SCOPE_COOKIE_STORE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_COOKIE_STORE_SERVICE_WORKER_GLOBAL_SCOPE_COOKIE_STORE_H_
+
+#include "third_party/blink/renderer/core/dom/events/event_target.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+
+namespace blink {
+
+class CookieStore;
+class ServiceWorkerGlobalScope;
+
+// Exposes a CookieStore as the "cookieStore" attribute on the SW global scope.
+class ServiceWorkerGlobalScopeCookieStore {
+ STATIC_ONLY(ServiceWorkerGlobalScopeCookieStore);
+
+ public:
+ static CookieStore* cookieStore(ServiceWorkerGlobalScope&);
+
+ DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(cookiechange);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_COOKIE_STORE_SERVICE_WORKER_GLOBAL_SCOPE_COOKIE_STORE_H_
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.idl b/chromium/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.idl
index 118b77702b7..c19ad6ee0fc 100644
--- a/chromium/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.idl
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/service_worker_global_scope_cookie_store.idl
@@ -5,8 +5,9 @@
// https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md
[
- RuntimeEnabled=AsyncCookies,
- ImplementedAs=GlobalCookieStore
+ OriginTrialEnabled=CookieStore,
+ ImplementedAs=ServiceWorkerGlobalScopeCookieStore
] partial interface ServiceWorkerGlobalScope {
[Replaceable, SameObject] readonly attribute CookieStore cookieStore;
+ attribute EventHandler oncookiechange;
};
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/window_cookie_store.cc b/chromium/third_party/blink/renderer/modules/cookie_store/window_cookie_store.cc
new file mode 100644
index 00000000000..eb378d47a7d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/window_cookie_store.cc
@@ -0,0 +1,34 @@
+// 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/modules/cookie_store/window_cookie_store.h"
+
+#include <utility>
+
+#include "services/network/public/mojom/restricted_cookie_manager.mojom-blink.h"
+#include "services/service_manager/public/cpp/interface_provider.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/modules/cookie_store/cookie_store.h"
+#include "third_party/blink/renderer/modules/cookie_store/global_cookie_store_impl.h"
+
+namespace blink {
+
+template <>
+CookieStore* GlobalCookieStoreImpl<LocalDOMWindow>::BuildCookieStore(
+ ExecutionContext* execution_context,
+ service_manager::InterfaceProvider* interface_provider) {
+ network::mojom::blink::RestrictedCookieManagerPtr cookie_manager_ptr;
+ interface_provider->GetInterface(mojo::MakeRequest(&cookie_manager_ptr));
+
+ return CookieStore::Create(execution_context, std::move(cookie_manager_ptr),
+ blink::mojom::blink::CookieStorePtr());
+}
+
+CookieStore* WindowCookieStore::cookieStore(LocalDOMWindow& window) {
+ return GlobalCookieStoreImpl<LocalDOMWindow>::From(window).GetCookieStore(
+ window);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/window_cookie_store.h b/chromium/third_party/blink/renderer/modules/cookie_store/window_cookie_store.h
new file mode 100644
index 00000000000..aed59ca44e9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/window_cookie_store.h
@@ -0,0 +1,25 @@
+// 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_MODULES_COOKIE_STORE_WINDOW_COOKIE_STORE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_COOKIE_STORE_WINDOW_COOKIE_STORE_H_
+
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+
+namespace blink {
+
+class CookieStore;
+class LocalDOMWindow;
+
+// Exposes a CookieStore as the "cookieStore" attribute on the Window global.
+class WindowCookieStore {
+ STATIC_ONLY(WindowCookieStore);
+
+ public:
+ static CookieStore* cookieStore(LocalDOMWindow&);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_COOKIE_STORE_WINDOW_COOKIE_STORE_H_
diff --git a/chromium/third_party/blink/renderer/modules/cookie_store/window_cookie_store.idl b/chromium/third_party/blink/renderer/modules/cookie_store/window_cookie_store.idl
index 70f6518ebcc..254a9c4242d 100644
--- a/chromium/third_party/blink/renderer/modules/cookie_store/window_cookie_store.idl
+++ b/chromium/third_party/blink/renderer/modules/cookie_store/window_cookie_store.idl
@@ -5,8 +5,9 @@
// https://github.com/WICG/async-cookies-api/blob/gh-pages/explainer.md
[
- RuntimeEnabled=AsyncCookies,
- ImplementedAs=GlobalCookieStore
+ OriginTrialEnabled=CookieStore,
+ ImplementedAs=WindowCookieStore,
+ SecureContext
] partial interface Window {
[Replaceable, SameObject] readonly attribute CookieStore cookieStore;
};
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/BUILD.gn b/chromium/third_party/blink/renderer/modules/credentialmanager/BUILD.gn
index 18f143a1e7c..92c07988a6f 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/BUILD.gn
@@ -28,5 +28,7 @@ blink_modules_sources("credentialmanager") {
"password_credential.h",
"public_key_credential.cc",
"public_key_credential.h",
+ "scoped_promise_resolver.cc",
+ "scoped_promise_resolver.h",
]
}
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/authentication_extensions_client_inputs.idl b/chromium/third_party/blink/renderer/modules/credentialmanager/authentication_extensions_client_inputs.idl
index 01ccf2a49bd..6e7920cb723 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/authentication_extensions_client_inputs.idl
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/authentication_extensions_client_inputs.idl
@@ -8,5 +8,5 @@ dictionary AuthenticationExtensionsClientInputs {
// https://w3c.github.io/webauthn/#sctn-appid-extension
USVString appid;
CableRegistrationData cableRegistration;
- sequence<CableAuthenticationData> cableAuthenticationData;
+ sequence<CableAuthenticationData> cableAuthentication;
}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/cable_authentication_data.idl b/chromium/third_party/blink/renderer/modules/credentialmanager/cable_authentication_data.idl
index a0e515b402c..c219173019f 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/cable_authentication_data.idl
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/cable_authentication_data.idl
@@ -3,7 +3,7 @@
// found in the LICENSE file.
dictionary CableAuthenticationData {
- required long version;
+ required octet version;
required BufferSource clientEid;
required BufferSource authenticatorEid;
required BufferSource sessionPreKey;
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/cable_registration_data.idl b/chromium/third_party/blink/renderer/modules/credentialmanager/cable_registration_data.idl
index 9e8f689762d..0aee556e135 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/cable_registration_data.idl
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/cable_registration_data.idl
@@ -3,6 +3,6 @@
// found in the LICENSE file.
dictionary CableRegistrationData {
- required long version;
+ required sequence<octet> versions;
required BufferSource rpPublicKey;
-}; \ No newline at end of file
+};
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/credential.cc b/chromium/third_party/blink/renderer/modules/credentialmanager/credential.cc
index ebc3a82369d..b8ca2e39656 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/credential.cc
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/credential.cc
@@ -4,8 +4,7 @@
#include "third_party/blink/renderer/modules/credentialmanager/credential.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -23,7 +22,7 @@ KURL Credential::ParseStringAsURLOrThrow(const String& url,
return KURL();
KURL parsed_url = KURL(NullURL(), url);
if (!parsed_url.IsValid()) {
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"'" + url + "' is not a valid URL.");
}
return parsed_url;
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h b/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h
index 79269618153..11ea9bfd54a 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h
@@ -38,13 +38,11 @@ class MODULES_EXPORT CredentialManagerProxy
explicit CredentialManagerProxy(Document*);
virtual ~CredentialManagerProxy();
- ::password_manager::mojom::blink::CredentialManager* CredentialManager() {
+ mojom::blink::CredentialManager* CredentialManager() {
return credential_manager_.get();
}
- ::webauth::mojom::blink::Authenticator* Authenticator() {
- return authenticator_.get();
- }
+ mojom::blink::Authenticator* Authenticator() { return authenticator_.get(); }
void FlushCredentialManagerConnectionForTesting() {
credential_manager_.FlushForTesting();
@@ -56,10 +54,8 @@ class MODULES_EXPORT CredentialManagerProxy
static CredentialManagerProxy* From(Document*);
private:
- // TODO(crbug.com/740081): Merge |credential_manager_| and |authenticator_|
- // into a single Mojo interface.
- ::password_manager::mojom::blink::CredentialManagerPtr credential_manager_;
- ::webauth::mojom::blink::AuthenticatorPtr authenticator_;
+ mojom::blink::AuthenticatorPtr authenticator_;
+ mojom::blink::CredentialManagerPtr credential_manager_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.cc b/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.cc
index e854ea655f8..b12f9dda52a 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.cc
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.cc
@@ -38,32 +38,32 @@ WTF::TimeDelta AdjustTimeout(uint32_t timeout) {
namespace mojo {
-using password_manager::mojom::blink::CredentialInfo;
-using password_manager::mojom::blink::CredentialInfoPtr;
-using password_manager::mojom::blink::CredentialType;
-using password_manager::mojom::blink::CredentialManagerError;
-using webauth::mojom::blink::AttestationConveyancePreference;
-using webauth::mojom::blink::AuthenticatorAttachment;
-using webauth::mojom::blink::AuthenticatorSelectionCriteria;
-using webauth::mojom::blink::AuthenticatorSelectionCriteriaPtr;
-using webauth::mojom::blink::AuthenticatorStatus;
-using webauth::mojom::blink::AuthenticatorTransport;
-using webauth::mojom::blink::CableAuthentication;
-using webauth::mojom::blink::CableAuthenticationPtr;
-using webauth::mojom::blink::CableRegistration;
-using webauth::mojom::blink::CableRegistrationPtr;
-using webauth::mojom::blink::PublicKeyCredentialCreationOptionsPtr;
-using webauth::mojom::blink::PublicKeyCredentialDescriptor;
-using webauth::mojom::blink::PublicKeyCredentialDescriptorPtr;
-using webauth::mojom::blink::PublicKeyCredentialRpEntity;
-using webauth::mojom::blink::PublicKeyCredentialRpEntityPtr;
-using webauth::mojom::blink::PublicKeyCredentialUserEntity;
-using webauth::mojom::blink::PublicKeyCredentialUserEntityPtr;
-using webauth::mojom::blink::PublicKeyCredentialParameters;
-using webauth::mojom::blink::PublicKeyCredentialParametersPtr;
-using webauth::mojom::blink::PublicKeyCredentialRequestOptionsPtr;
-using webauth::mojom::blink::PublicKeyCredentialType;
-using webauth::mojom::blink::UserVerificationRequirement;
+using blink::mojom::blink::AttestationConveyancePreference;
+using blink::mojom::blink::AuthenticatorAttachment;
+using blink::mojom::blink::AuthenticatorSelectionCriteria;
+using blink::mojom::blink::AuthenticatorSelectionCriteriaPtr;
+using blink::mojom::blink::AuthenticatorStatus;
+using blink::mojom::blink::AuthenticatorTransport;
+using blink::mojom::blink::CableAuthentication;
+using blink::mojom::blink::CableAuthenticationPtr;
+using blink::mojom::blink::CableRegistration;
+using blink::mojom::blink::CableRegistrationPtr;
+using blink::mojom::blink::CredentialInfo;
+using blink::mojom::blink::CredentialInfoPtr;
+using blink::mojom::blink::CredentialType;
+using blink::mojom::blink::CredentialManagerError;
+using blink::mojom::blink::PublicKeyCredentialCreationOptionsPtr;
+using blink::mojom::blink::PublicKeyCredentialDescriptor;
+using blink::mojom::blink::PublicKeyCredentialDescriptorPtr;
+using blink::mojom::blink::PublicKeyCredentialRpEntity;
+using blink::mojom::blink::PublicKeyCredentialRpEntityPtr;
+using blink::mojom::blink::PublicKeyCredentialUserEntity;
+using blink::mojom::blink::PublicKeyCredentialUserEntityPtr;
+using blink::mojom::blink::PublicKeyCredentialParameters;
+using blink::mojom::blink::PublicKeyCredentialParametersPtr;
+using blink::mojom::blink::PublicKeyCredentialRequestOptionsPtr;
+using blink::mojom::blink::PublicKeyCredentialType;
+using blink::mojom::blink::UserVerificationRequirement;
// static
CredentialInfoPtr TypeConverter<CredentialInfoPtr, blink::Credential*>::Convert(
@@ -77,7 +77,7 @@ CredentialInfoPtr TypeConverter<CredentialInfoPtr, blink::Credential*>::Convert(
info->password = password_credential->password();
info->name = password_credential->name();
info->icon = password_credential->iconURL();
- info->federation = blink::SecurityOrigin::CreateUnique();
+ info->federation = blink::SecurityOrigin::CreateUniqueOpaque();
} else {
DCHECK(credential->IsFederatedCredential());
::blink::FederatedCredential* federated_credential =
@@ -114,33 +114,33 @@ CredentialManagerError
TypeConverter<CredentialManagerError, AuthenticatorStatus>::Convert(
const AuthenticatorStatus& status) {
switch (status) {
- case webauth::mojom::blink::AuthenticatorStatus::
- AUTHENTICATOR_CRITERIA_UNSUPPORTED:
- return CredentialManagerError::AUTHENTICATOR_CRITERIA_UNSUPPORTED;
- case webauth::mojom::blink::AuthenticatorStatus::ALGORITHM_UNSUPPORTED:
- return CredentialManagerError::ALGORITHM_UNSUPPORTED;
- case webauth::mojom::blink::AuthenticatorStatus::EMPTY_ALLOW_CREDENTIALS:
- return CredentialManagerError::EMPTY_ALLOW_CREDENTIALS;
- case webauth::mojom::blink::AuthenticatorStatus::
- USER_VERIFICATION_UNSUPPORTED:
- return CredentialManagerError::USER_VERIFICATION_UNSUPPORTED;
- case webauth::mojom::blink::AuthenticatorStatus::NOT_ALLOWED_ERROR:
+ case blink::mojom::blink::AuthenticatorStatus::NOT_ALLOWED_ERROR:
return CredentialManagerError::NOT_ALLOWED;
- case webauth::mojom::blink::AuthenticatorStatus::UNKNOWN_ERROR:
+ case blink::mojom::blink::AuthenticatorStatus::UNKNOWN_ERROR:
return CredentialManagerError::UNKNOWN;
- case webauth::mojom::blink::AuthenticatorStatus::PENDING_REQUEST:
+ case blink::mojom::blink::AuthenticatorStatus::PENDING_REQUEST:
return CredentialManagerError::PENDING_REQUEST;
- case webauth::mojom::blink::AuthenticatorStatus::INVALID_DOMAIN:
+ case blink::mojom::blink::AuthenticatorStatus::INVALID_DOMAIN:
return CredentialManagerError::INVALID_DOMAIN;
- case webauth::mojom::blink::AuthenticatorStatus::CREDENTIAL_EXCLUDED:
+ case blink::mojom::blink::AuthenticatorStatus::CREDENTIAL_EXCLUDED:
return CredentialManagerError::CREDENTIAL_EXCLUDED;
- case webauth::mojom::blink::AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED:
+ case blink::mojom::blink::AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED:
return CredentialManagerError::CREDENTIAL_NOT_RECOGNIZED;
- case webauth::mojom::blink::AuthenticatorStatus::NOT_IMPLEMENTED:
+ case blink::mojom::blink::AuthenticatorStatus::NOT_IMPLEMENTED:
return CredentialManagerError::NOT_IMPLEMENTED;
- case webauth::mojom::blink::AuthenticatorStatus::NOT_FOCUSED:
+ case blink::mojom::blink::AuthenticatorStatus::NOT_FOCUSED:
return CredentialManagerError::NOT_FOCUSED;
- case webauth::mojom::blink::AuthenticatorStatus::SUCCESS:
+ case blink::mojom::blink::AuthenticatorStatus::ALGORITHM_UNSUPPORTED:
+ return CredentialManagerError::ANDROID_ALGORITHM_UNSUPPORTED;
+ case blink::mojom::blink::AuthenticatorStatus::EMPTY_ALLOW_CREDENTIALS:
+ return CredentialManagerError::ANDROID_EMPTY_ALLOW_CREDENTIALS;
+ case blink::mojom::blink::AuthenticatorStatus::
+ ANDROID_NOT_SUPPORTED_ERROR:
+ return CredentialManagerError::ANDROID_NOT_SUPPORTED_ERROR;
+ case blink::mojom::blink::AuthenticatorStatus::
+ USER_VERIFICATION_UNSUPPORTED:
+ return CredentialManagerError::ANDROID_USER_VERIFICATION_UNSUPPORTED;
+ case blink::mojom::blink::AuthenticatorStatus::SUCCESS:
NOTREACHED();
break;
}
@@ -153,9 +153,16 @@ TypeConverter<CredentialManagerError, AuthenticatorStatus>::Convert(
Vector<uint8_t> ConvertFixedSizeArray(
const blink::ArrayBufferOrArrayBufferView& buffer,
unsigned length) {
- if (buffer.GetAsArrayBufferView().View()->byteLength() != length) {
+ if (buffer.IsArrayBuffer() &&
+ (buffer.GetAsArrayBuffer()->ByteLength() != length)) {
+ return Vector<uint8_t>();
+ }
+
+ if (buffer.IsArrayBufferView() &&
+ buffer.GetAsArrayBufferView().View()->byteLength() != length) {
return Vector<uint8_t>();
}
+
return ConvertTo<Vector<uint8_t>>(buffer);
}
@@ -223,6 +230,8 @@ TypeConverter<AttestationConveyancePreference, String>::Convert(
return AttestationConveyancePreference::INDIRECT;
if (preference == "direct")
return AttestationConveyancePreference::DIRECT;
+ if (preference == "enterprise")
+ return AttestationConveyancePreference::ENTERPRISE;
NOTREACHED();
return AttestationConveyancePreference::NONE;
}
@@ -246,7 +255,7 @@ TypeConverter<AuthenticatorSelectionCriteriaPtr,
blink::AuthenticatorSelectionCriteria>::
Convert(const blink::AuthenticatorSelectionCriteria& criteria) {
auto mojo_criteria =
- webauth::mojom::blink::AuthenticatorSelectionCriteria::New();
+ blink::mojom::blink::AuthenticatorSelectionCriteria::New();
mojo_criteria->authenticator_attachment =
ConvertTo<AuthenticatorAttachment>(criteria.authenticatorAttachment());
mojo_criteria->require_resident_key = criteria.requireResidentKey();
@@ -325,7 +334,7 @@ TypeConverter<PublicKeyCredentialCreationOptionsPtr,
blink::PublicKeyCredentialCreationOptions>::
Convert(const blink::PublicKeyCredentialCreationOptions& options) {
auto mojo_options =
- webauth::mojom::blink::PublicKeyCredentialCreationOptions::New();
+ blink::mojom::blink::PublicKeyCredentialCreationOptions::New();
mojo_options->relying_party = PublicKeyCredentialRpEntity::From(options.rp());
mojo_options->user = PublicKeyCredentialUserEntity::From(options.user());
if (!mojo_options->relying_party | !mojo_options->user) {
@@ -374,17 +383,20 @@ TypeConverter<PublicKeyCredentialCreationOptionsPtr,
}
mojo_options->attestation =
- webauth::mojom::AttestationConveyancePreference::NONE;
+ blink::mojom::AttestationConveyancePreference::NONE;
if (options.hasAttestation()) {
const auto& attestation = options.attestation();
if (attestation == "none") {
// Default value.
} else if (attestation == "indirect") {
mojo_options->attestation =
- webauth::mojom::AttestationConveyancePreference::INDIRECT;
+ blink::mojom::AttestationConveyancePreference::INDIRECT;
} else if (attestation == "direct") {
mojo_options->attestation =
- webauth::mojom::AttestationConveyancePreference::DIRECT;
+ blink::mojom::AttestationConveyancePreference::DIRECT;
+ } else if (attestation == "enterprise") {
+ mojo_options->attestation =
+ blink::mojom::AttestationConveyancePreference::ENTERPRISE;
} else {
return nullptr;
}
@@ -426,7 +438,7 @@ CableRegistrationPtr
TypeConverter<CableRegistrationPtr, blink::CableRegistrationData>::Convert(
const blink::CableRegistrationData& data) {
auto entity = CableRegistration::New();
- entity->version = data.version();
+ entity->versions = data.versions();
entity->relying_party_public_key =
ConvertFixedSizeArray(data.rpPublicKey(), 65);
if (entity->relying_party_public_key.IsEmpty()) {
@@ -441,7 +453,7 @@ TypeConverter<PublicKeyCredentialRequestOptionsPtr,
blink::PublicKeyCredentialRequestOptions>::
Convert(const blink::PublicKeyCredentialRequestOptions& options) {
auto mojo_options =
- webauth::mojom::blink::PublicKeyCredentialRequestOptions::New();
+ blink::mojom::blink::PublicKeyCredentialRequestOptions::New();
mojo_options->challenge = ConvertTo<Vector<uint8_t>>(options.challenge());
if (options.hasTimeout()) {
@@ -471,9 +483,9 @@ TypeConverter<PublicKeyCredentialRequestOptionsPtr,
if (extensions.hasAppid()) {
mojo_options->appid = extensions.appid();
}
- if (extensions.hasCableAuthenticationData()) {
+ if (extensions.hasCableAuthentication()) {
Vector<CableAuthenticationPtr> mojo_data;
- for (const auto& data : extensions.cableAuthenticationData()) {
+ for (const auto& data : extensions.cableAuthentication()) {
CableAuthenticationPtr mojo_cable = CableAuthentication::From(data);
if (mojo_cable) {
mojo_data.push_back(std::move(mojo_cable));
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.h b/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.h
index 01e9f06da8f..44769ec78ef 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.h
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/credential_manager_type_converters.h
@@ -27,28 +27,27 @@ class UserVerificationRequirement;
namespace mojo {
-// password_manager::mojom::blink::CredentialManager --------------------------
+// blink::mojom::blink::CredentialManager --------------------------
template <>
-struct TypeConverter<password_manager::mojom::blink::CredentialInfoPtr,
+struct TypeConverter<blink::mojom::blink::CredentialInfoPtr,
blink::Credential*> {
- static password_manager::mojom::blink::CredentialInfoPtr Convert(
- blink::Credential*);
+ static blink::mojom::blink::CredentialInfoPtr Convert(blink::Credential*);
};
template <>
struct TypeConverter<blink::Credential*,
- password_manager::mojom::blink::CredentialInfoPtr> {
+ blink::mojom::blink::CredentialInfoPtr> {
static blink::Credential* Convert(
- const password_manager::mojom::blink::CredentialInfoPtr&);
+ const blink::mojom::blink::CredentialInfoPtr&);
};
-// webauth::mojom::blink::Authenticator ---------------------------------------
+// blink::mojom::blink::Authenticator ---------------------------------------
template <>
-struct TypeConverter<password_manager::mojom::blink::CredentialManagerError,
- webauth::mojom::blink::AuthenticatorStatus> {
- static password_manager::mojom::blink::CredentialManagerError Convert(
- const webauth::mojom::blink::AuthenticatorStatus&);
+struct TypeConverter<blink::mojom::blink::CredentialManagerError,
+ blink::mojom::blink::AuthenticatorStatus> {
+ static blink::mojom::blink::CredentialManagerError Convert(
+ const blink::mojom::blink::AuthenticatorStatus&);
};
template <>
@@ -57,96 +56,93 @@ struct TypeConverter<Vector<uint8_t>, blink::ArrayBufferOrArrayBufferView> {
};
template <>
-struct TypeConverter<webauth::mojom::blink::PublicKeyCredentialType, String> {
- static webauth::mojom::blink::PublicKeyCredentialType Convert(const String&);
+struct TypeConverter<blink::mojom::blink::PublicKeyCredentialType, String> {
+ static blink::mojom::blink::PublicKeyCredentialType Convert(const String&);
};
template <>
-struct TypeConverter<webauth::mojom::blink::AuthenticatorTransport, String> {
- static webauth::mojom::blink::AuthenticatorTransport Convert(const String&);
+struct TypeConverter<blink::mojom::blink::AuthenticatorTransport, String> {
+ static blink::mojom::blink::AuthenticatorTransport Convert(const String&);
};
template <>
-struct TypeConverter<webauth::mojom::blink::UserVerificationRequirement,
- String> {
- static webauth::mojom::blink::UserVerificationRequirement Convert(
+struct TypeConverter<blink::mojom::blink::UserVerificationRequirement, String> {
+ static blink::mojom::blink::UserVerificationRequirement Convert(
const String&);
};
template <>
-struct TypeConverter<webauth::mojom::blink::AttestationConveyancePreference,
+struct TypeConverter<blink::mojom::blink::AttestationConveyancePreference,
String> {
- static webauth::mojom::blink::AttestationConveyancePreference Convert(
+ static blink::mojom::blink::AttestationConveyancePreference Convert(
const String&);
};
template <>
-struct TypeConverter<webauth::mojom::blink::AuthenticatorAttachment, String> {
- static webauth::mojom::blink::AuthenticatorAttachment Convert(const String&);
+struct TypeConverter<blink::mojom::blink::AuthenticatorAttachment, String> {
+ static blink::mojom::blink::AuthenticatorAttachment Convert(const String&);
};
template <>
-struct TypeConverter<webauth::mojom::blink::AuthenticatorSelectionCriteriaPtr,
+struct TypeConverter<blink::mojom::blink::AuthenticatorSelectionCriteriaPtr,
blink::AuthenticatorSelectionCriteria> {
- static webauth::mojom::blink::AuthenticatorSelectionCriteriaPtr Convert(
+ static blink::mojom::blink::AuthenticatorSelectionCriteriaPtr Convert(
const blink::AuthenticatorSelectionCriteria&);
};
template <>
-struct TypeConverter<webauth::mojom::blink::PublicKeyCredentialUserEntityPtr,
+struct TypeConverter<blink::mojom::blink::PublicKeyCredentialUserEntityPtr,
blink::PublicKeyCredentialUserEntity> {
- static webauth::mojom::blink::PublicKeyCredentialUserEntityPtr Convert(
+ static blink::mojom::blink::PublicKeyCredentialUserEntityPtr Convert(
const blink::PublicKeyCredentialUserEntity&);
};
template <>
-struct TypeConverter<webauth::mojom::blink::PublicKeyCredentialRpEntityPtr,
+struct TypeConverter<blink::mojom::blink::PublicKeyCredentialRpEntityPtr,
blink::PublicKeyCredentialRpEntity> {
- static webauth::mojom::blink::PublicKeyCredentialRpEntityPtr Convert(
+ static blink::mojom::blink::PublicKeyCredentialRpEntityPtr Convert(
const blink::PublicKeyCredentialRpEntity&);
};
template <>
-struct TypeConverter<webauth::mojom::blink::PublicKeyCredentialDescriptorPtr,
+struct TypeConverter<blink::mojom::blink::PublicKeyCredentialDescriptorPtr,
blink::PublicKeyCredentialDescriptor> {
- static webauth::mojom::blink::PublicKeyCredentialDescriptorPtr Convert(
+ static blink::mojom::blink::PublicKeyCredentialDescriptorPtr Convert(
const blink::PublicKeyCredentialDescriptor&);
};
template <>
-struct TypeConverter<webauth::mojom::blink::PublicKeyCredentialParametersPtr,
+struct TypeConverter<blink::mojom::blink::PublicKeyCredentialParametersPtr,
blink::PublicKeyCredentialParameters> {
- static webauth::mojom::blink::PublicKeyCredentialParametersPtr Convert(
+ static blink::mojom::blink::PublicKeyCredentialParametersPtr Convert(
const blink::PublicKeyCredentialParameters&);
};
template <>
-struct TypeConverter<
- webauth::mojom::blink::PublicKeyCredentialCreationOptionsPtr,
- blink::PublicKeyCredentialCreationOptions> {
- static webauth::mojom::blink::PublicKeyCredentialCreationOptionsPtr Convert(
+struct TypeConverter<blink::mojom::blink::PublicKeyCredentialCreationOptionsPtr,
+ blink::PublicKeyCredentialCreationOptions> {
+ static blink::mojom::blink::PublicKeyCredentialCreationOptionsPtr Convert(
const blink::PublicKeyCredentialCreationOptions&);
};
template <>
-struct TypeConverter<webauth::mojom::blink::CableAuthenticationPtr,
+struct TypeConverter<blink::mojom::blink::CableAuthenticationPtr,
blink::CableAuthenticationData> {
- static webauth::mojom::blink::CableAuthenticationPtr Convert(
+ static blink::mojom::blink::CableAuthenticationPtr Convert(
const blink::CableAuthenticationData&);
};
template <>
-struct TypeConverter<webauth::mojom::blink::CableRegistrationPtr,
+struct TypeConverter<blink::mojom::blink::CableRegistrationPtr,
blink::CableRegistrationData> {
- static webauth::mojom::blink::CableRegistrationPtr Convert(
+ static blink::mojom::blink::CableRegistrationPtr Convert(
const blink::CableRegistrationData&);
};
template <>
-struct TypeConverter<
- webauth::mojom::blink::PublicKeyCredentialRequestOptionsPtr,
- blink::PublicKeyCredentialRequestOptions> {
- static webauth::mojom::blink::PublicKeyCredentialRequestOptionsPtr Convert(
+struct TypeConverter<blink::mojom::blink::PublicKeyCredentialRequestOptionsPtr,
+ blink::PublicKeyCredentialRequestOptions> {
+ static blink::mojom::blink::PublicKeyCredentialRequestOptionsPtr Convert(
const blink::PublicKeyCredentialRequestOptions&);
};
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc b/chromium/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
index 8a990c78b89..c67b013a996 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
@@ -8,14 +8,13 @@
#include <utility>
#include "third_party/blink/public/platform/modules/credentialmanager/credential_manager.mojom-blink.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/dom/exception_code.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_frame.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/page/frame_tree.h"
@@ -33,6 +32,8 @@
#include "third_party/blink/renderer/modules/credentialmanager/public_key_credential.h"
#include "third_party/blink/renderer/modules/credentialmanager/public_key_credential_creation_options.h"
#include "third_party/blink/renderer/modules/credentialmanager/public_key_credential_request_options.h"
+#include "third_party/blink/renderer/modules/credentialmanager/scoped_promise_resolver.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/weborigin/origin_access_entry.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -41,55 +42,20 @@ namespace blink {
namespace {
-using ::password_manager::mojom::blink::CredentialManagerError;
-using ::password_manager::mojom::blink::CredentialInfo;
-using ::password_manager::mojom::blink::CredentialInfoPtr;
-using ::password_manager::mojom::blink::CredentialMediationRequirement;
-using ::webauth::mojom::blink::AuthenticatorStatus;
+using mojom::blink::CredentialManagerError;
+using mojom::blink::CredentialInfo;
+using mojom::blink::CredentialInfoPtr;
+using mojom::blink::CredentialMediationRequirement;
+using mojom::blink::AuthenticatorStatus;
using MojoPublicKeyCredentialCreationOptions =
- ::webauth::mojom::blink::PublicKeyCredentialCreationOptions;
-using ::webauth::mojom::blink::MakeCredentialAuthenticatorResponsePtr;
+ mojom::blink::PublicKeyCredentialCreationOptions;
+using mojom::blink::MakeCredentialAuthenticatorResponsePtr;
using MojoPublicKeyCredentialRequestOptions =
- ::webauth::mojom::blink::PublicKeyCredentialRequestOptions;
-using ::webauth::mojom::blink::GetAssertionAuthenticatorResponsePtr;
+ mojom::blink::PublicKeyCredentialRequestOptions;
+using mojom::blink::GetAssertionAuthenticatorResponsePtr;
enum class RequiredOriginType { kSecure, kSecureAndSameWithAncestors };
-// Off-heap wrapper that holds a strong reference to a ScriptPromiseResolver.
-class ScopedPromiseResolver {
- WTF_MAKE_NONCOPYABLE(ScopedPromiseResolver);
-
- public:
- explicit ScopedPromiseResolver(ScriptPromiseResolver* resolver)
- : resolver_(resolver) {}
-
- ~ScopedPromiseResolver() {
- if (resolver_)
- OnConnectionError();
- }
-
- // Releases the owned |resolver_|. This is to be called by the Mojo response
- // callback responsible for resolving the corresponding ScriptPromise
- //
- // If this method is not called before |this| goes of scope, it is assumed
- // that a Mojo connection error has occurred, and the response callback was
- // never invoked. The Promise will be rejected with an appropriate exception.
- ScriptPromiseResolver* Release() { return resolver_.Release(); }
-
- private:
- void OnConnectionError() {
- // The only anticapted reason for a connection error is that the embedder
- // does not implement mojom::CredentialManager, or mojom::AuthenticatorImpl,
- // so go out on a limb and try to provide an actionable error message.
- resolver_->Reject(DOMException::Create(
- kNotSupportedError,
- "The user agent either does not implement a password store or does "
- "not support public key credentials."));
- }
-
- Persistent<ScriptPromiseResolver> resolver_;
-};
-
bool IsSameOriginWithAncestors(const Frame* frame) {
DCHECK(frame);
const Frame* current = frame;
@@ -124,7 +90,7 @@ bool CheckSecurityRequirementsBeforeRequest(
if (required_origin_type == RequiredOriginType::kSecureAndSameWithAncestors &&
!IsSameOriginWithAncestors(resolver->GetFrame())) {
resolver->Reject(DOMException::Create(
- kNotAllowedError,
+ DOMExceptionCode::kNotAllowedError,
"The following credential operations can only occur in a document which"
" is same-origin with all of its ancestors: "
"storage/retrieval of 'PasswordCredential' and 'FederatedCredential', "
@@ -157,21 +123,23 @@ bool CheckPublicKeySecurityRequirements(ScriptPromiseResolver* resolver,
const SecurityOrigin* origin =
resolver->GetFrame()->GetSecurityContext()->GetSecurityOrigin();
- if (origin->IsUnique()) {
+ if (origin->IsOpaque()) {
String error_message =
"The origin ' " + origin->ToRawString() +
"' is an opaque origin and hence not allowed to access " +
"'PublicKeyCredential' objects.";
- resolver->Reject(DOMException::Create(kNotAllowedError, error_message));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotAllowedError,
+ error_message));
return false;
}
if (origin->Protocol() != url::kHttpScheme &&
origin->Protocol() != url::kHttpsScheme) {
resolver->Reject(DOMException::Create(
- kNotAllowedError,
- "Public-key credentials are only available to secure HTTP or HTTPS "
- "origins. See https://crbug.com/824383"));
+ DOMExceptionCode::kNotAllowedError,
+ "Public-key credentials are only available to HTTPS origin or "
+ "HTTP origins that fall under 'localhost'. See "
+ "https://crbug.com/824383"));
return false;
}
@@ -189,8 +157,9 @@ bool CheckPublicKeySecurityRequirements(ScriptPromiseResolver* resolver,
OriginAccessEntry access_entry(origin->Protocol(), effective_domain,
blink::OriginAccessEntry::kAllowSubdomains);
if (effective_domain.IsEmpty() || access_entry.HostIsIPAddress()) {
- resolver->Reject(DOMException::Create(
- kSecurityError, "Effective domain is not a valid domain."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kSecurityError,
+ "Effective domain is not a valid domain."));
return false;
}
@@ -204,7 +173,7 @@ bool CheckPublicKeySecurityRequirements(ScriptPromiseResolver* resolver,
access_entry.MatchesDomain(*origin) !=
blink::OriginAccessEntry::kMatchesOrigin) {
resolver->Reject(DOMException::Create(
- kSecurityError,
+ DOMExceptionCode::kSecurityError,
"The relying party ID '" + relying_party_id +
"' is not a registrable domain suffix of, nor equal to '" +
origin->ToRawString() + "'."));
@@ -240,60 +209,58 @@ DOMException* CredentialManagerErrorToDOMException(
CredentialManagerError reason) {
switch (reason) {
case CredentialManagerError::PENDING_REQUEST:
- return DOMException::Create(kInvalidStateError,
+ return DOMException::Create(DOMExceptionCode::kInvalidStateError,
"A request is already pending.");
case CredentialManagerError::PASSWORD_STORE_UNAVAILABLE:
- return DOMException::Create(kNotSupportedError,
+ return DOMException::Create(DOMExceptionCode::kNotSupportedError,
"The password store is unavailable.");
case CredentialManagerError::NOT_ALLOWED:
return DOMException::Create(
- kNotAllowedError,
+ DOMExceptionCode::kNotAllowedError,
"The operation either timed out or was not allowed. See: "
"https://w3c.github.io/webauthn/#sec-assertion-privacy.");
- case CredentialManagerError::AUTHENTICATOR_CRITERIA_UNSUPPORTED:
- return DOMException::Create(kNotSupportedError,
- "The specified `authenticatorSelection` "
- "criteria cannot be fulfilled by CTAP1/U2F "
- "authenticators, and CTAP2 authenticators "
- "are not yet supported.");
- case CredentialManagerError::ALGORITHM_UNSUPPORTED:
- return DOMException::Create(kNotSupportedError,
- "None of the algorithms specified in "
- "`pubKeyCredParams` are compatible with "
- "CTAP1/U2F authenticators, and CTAP2 "
- "authenticators are not yet supported.");
- case CredentialManagerError::EMPTY_ALLOW_CREDENTIALS:
- return DOMException::Create(kNotSupportedError,
- "The `allowCredentials` list cannot be left "
- "empty for CTAP1/U2F authenticators, and "
- "support for CTAP2 authenticators is not yet "
- "implemented.");
- case CredentialManagerError::USER_VERIFICATION_UNSUPPORTED:
- return DOMException::Create(kNotSupportedError,
- "The specified `userVerification` "
- "requirement cannot be fulfilled by "
- "CTAP1/U2F authenticators, and CTAP2 "
- "authenticators are not yet supported.");
case CredentialManagerError::INVALID_DOMAIN:
- return DOMException::Create(kSecurityError, "This is an invalid domain.");
+ return DOMException::Create(DOMExceptionCode::kSecurityError,
+ "This is an invalid domain.");
case CredentialManagerError::CREDENTIAL_EXCLUDED:
return DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"The user attempted to register an authenticator that contains one "
"of the credentials already registered with the relying party.");
case CredentialManagerError::CREDENTIAL_NOT_RECOGNIZED:
- return DOMException::Create(kInvalidStateError,
+ return DOMException::Create(DOMExceptionCode::kInvalidStateError,
"The user attempted to use an authenticator "
"that recognized none of the provided "
"credentials.");
case CredentialManagerError::NOT_IMPLEMENTED:
- return DOMException::Create(kNotSupportedError, "Not implemented");
+ return DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "Not implemented");
case CredentialManagerError::NOT_FOCUSED:
- return DOMException::Create(kNotAllowedError,
+ return DOMException::Create(DOMExceptionCode::kNotAllowedError,
"The operation is not allowed at this time "
"because the page does not have focus.");
+ case CredentialManagerError::ANDROID_ALGORITHM_UNSUPPORTED:
+ return DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "None of the algorithms specified in "
+ "`pubKeyCredParams` are supported by "
+ "this device.");
+ case CredentialManagerError::ANDROID_EMPTY_ALLOW_CREDENTIALS:
+ return DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "Use of an empty `allowCredentials` list is "
+ "not supported on this device.");
+ case CredentialManagerError::ANDROID_NOT_SUPPORTED_ERROR:
+ return DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "Either the device has received unexpected "
+ "request parameters, or the device "
+ "cannot support this request.");
+ case CredentialManagerError::ANDROID_USER_VERIFICATION_UNSUPPORTED:
+ return DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "The specified `userVerification` "
+ "requirement cannot be fulfilled by "
+ "this device unless the device is secured "
+ "with a screen lock.");
case CredentialManagerError::UNKNOWN:
- return DOMException::Create(kNotReadableError,
+ return DOMException::Create(DOMExceptionCode::kNotReadableError,
"An unknown error occurred while talking "
"to the credential manager.");
case CredentialManagerError::SUCCESS:
@@ -455,7 +422,7 @@ ScriptPromise CredentialsContainer::get(
KURL appid_url(appid);
if (!appid_url.IsValid()) {
resolver->Reject(
- DOMException::Create(kSyntaxError,
+ DOMException::Create(DOMExceptionCode::kSyntaxError,
"The `appid` extension value is neither "
"empty/null nor a valid URL"));
return promise;
@@ -464,7 +431,7 @@ ScriptPromise CredentialsContainer::get(
}
if (options.publicKey().extensions().hasCableRegistration()) {
resolver->Reject(DOMException::Create(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"The 'cableRegistration' extension is only valid when creating "
"a credential"));
return promise;
@@ -489,7 +456,7 @@ ScriptPromise CredentialsContainer::get(
WTF::Passed(std::make_unique<ScopedPromiseResolver>(resolver))));
} else {
resolver->Reject(DOMException::Create(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"Required parameters missing in 'options.publicKey'."));
}
return promise;
@@ -546,12 +513,12 @@ ScriptPromise CredentialsContainer::store(ScriptState* script_state,
if (!(credential->IsFederatedCredential() ||
credential->IsPasswordCredential())) {
resolver->Reject(DOMException::Create(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"Store operation not permitted for PublicKey credentials."));
}
if (!IsIconURLEmptyOrSecure(credential)) {
- resolver->Reject(DOMException::Create(kSecurityError,
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kSecurityError,
"'iconURL' should be a secure URL"));
return promise;
}
@@ -584,7 +551,7 @@ ScriptPromise CredentialsContainer::create(
if ((options.hasPassword() + options.hasFederated() +
options.hasPublicKey()) != 1) {
resolver->Reject(DOMException::Create(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"Only exactly one of 'password', 'federated', and 'publicKey' "
"credential types are currently supported."));
return promise;
@@ -613,15 +580,15 @@ ScriptPromise CredentialsContainer::create(
if (options.publicKey().hasExtensions()) {
if (options.publicKey().extensions().hasAppid()) {
resolver->Reject(DOMException::Create(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"The 'appid' extension is only valid when requesting an assertion "
"for a pre-existing credential that was registered using the "
"legacy FIDO U2F API."));
return promise;
}
- if (options.publicKey().extensions().hasCableAuthenticationData()) {
+ if (options.publicKey().extensions().hasCableAuthentication()) {
resolver->Reject(DOMException::Create(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"The 'cableAuthentication' extension is only valid when requesting "
"an assertion"));
return promise;
@@ -646,7 +613,7 @@ ScriptPromise CredentialsContainer::create(
WTF::Passed(std::make_unique<ScopedPromiseResolver>(resolver))));
} else {
resolver->Reject(DOMException::Create(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"Required parameters missing in `options.publicKey`."));
}
}
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc b/chromium/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc
index a47f3e4907c..42eb8035c98 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <utility>
+#include "base/macros.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -26,16 +27,12 @@ namespace blink {
namespace {
-class MockCredentialManager
- : public ::password_manager::mojom::blink::CredentialManager {
- WTF_MAKE_NONCOPYABLE(MockCredentialManager);
-
+class MockCredentialManager : public mojom::blink::CredentialManager {
public:
MockCredentialManager() : binding_(this) {}
~MockCredentialManager() override {}
- void Bind(
- ::password_manager::mojom::blink::CredentialManagerRequest request) {
+ void Bind(::blink::mojom::blink::CredentialManagerRequest request) {
binding_.Bind(std::move(request));
}
@@ -57,31 +54,32 @@ class MockCredentialManager
void InvokeGetCallback() {
EXPECT_TRUE(binding_.is_bound());
- auto info = password_manager::mojom::blink::CredentialInfo::New();
- info->type = password_manager::mojom::blink::CredentialType::EMPTY;
- info->federation = SecurityOrigin::CreateUnique();
+ auto info = blink::mojom::blink::CredentialInfo::New();
+ info->type = blink::mojom::blink::CredentialType::EMPTY;
+ info->federation = SecurityOrigin::CreateUniqueOpaque();
std::move(get_callback_)
- .Run(password_manager::mojom::blink::CredentialManagerError::SUCCESS,
+ .Run(blink::mojom::blink::CredentialManagerError::SUCCESS,
std::move(info));
}
protected:
- void Store(password_manager::mojom::blink::CredentialInfoPtr credential,
+ void Store(blink::mojom::blink::CredentialInfoPtr credential,
StoreCallback callback) override {}
void PreventSilentAccess(PreventSilentAccessCallback callback) override {}
- void Get(
- password_manager::mojom::blink::CredentialMediationRequirement mediation,
- bool include_passwords,
- const WTF::Vector<::blink::KURL>& federations,
- GetCallback callback) override {
+ void Get(blink::mojom::blink::CredentialMediationRequirement mediation,
+ bool include_passwords,
+ const WTF::Vector<::blink::KURL>& federations,
+ GetCallback callback) override {
get_callback_ = std::move(callback);
test::ExitRunLoop();
}
private:
- mojo::Binding<::password_manager::mojom::blink::CredentialManager> binding_;
+ mojo::Binding<::blink::mojom::blink::CredentialManager> binding_;
GetCallback get_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockCredentialManager);
};
class CredentialManagerTestingContext {
@@ -97,12 +95,12 @@ class CredentialManagerTestingContext {
service_manager::InterfaceProvider::TestApi test_api(
&dummy_context_.GetFrame().GetInterfaceProvider());
test_api.SetBinderForName(
- ::password_manager::mojom::blink::CredentialManager::Name_,
+ ::blink::mojom::blink::CredentialManager::Name_,
WTF::BindRepeating(
[](MockCredentialManager* mock_credential_manager,
mojo::ScopedMessagePipeHandle handle) {
mock_credential_manager->Bind(
- ::password_manager::mojom::blink::CredentialManagerRequest(
+ ::blink::mojom::blink::CredentialManagerRequest(
std::move(handle)));
},
WTF::Unretained(mock_credential_manager)));
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/federated_credential.cc b/chromium/third_party/blink/renderer/modules/credentialmanager/federated_credential.cc
index 7fa3d981226..8aeba5de70f 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/federated_credential.cc
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/federated_credential.cc
@@ -4,8 +4,8 @@
#include "third_party/blink/renderer/modules/credentialmanager/federated_credential.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/modules/credentialmanager/federated_credential_init.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/password_credential.cc b/chromium/third_party/blink/renderer/modules/credentialmanager/password_credential.cc
index 5caeab044c8..e73605633c4 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/password_credential.cc
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/password_credential.cc
@@ -4,13 +4,13 @@
#include "third_party/blink/renderer/modules/credentialmanager/password_credential.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.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/forms/listed_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/modules/credentialmanager/password_credential_data.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/password_credential_test.cc b/chromium/third_party/blink/renderer/modules/credentialmanager/password_credential_test.cc
index f42b7fdd683..b6283d1899b 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/password_credential_test.cc
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/password_credential_test.cc
@@ -6,14 +6,13 @@
#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/html/forms/form_controller.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/testing/page_test_base.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -97,7 +96,7 @@ TEST_F(PasswordCredentialTest, CreateFromFormNoPassword) {
PasswordCredential::Create(form, exception_state);
EXPECT_EQ(nullptr, credential);
EXPECT_TRUE(exception_state.HadException());
- EXPECT_EQ(kV8TypeError, exception_state.Code());
+ EXPECT_EQ(ESErrorType::kTypeError, exception_state.CodeAs<ESErrorType>());
EXPECT_EQ("'password' must not be empty.", exception_state.Message());
}
@@ -116,7 +115,7 @@ TEST_F(PasswordCredentialTest, CreateFromFormNoId) {
PasswordCredential::Create(form, exception_state);
EXPECT_EQ(nullptr, credential);
EXPECT_TRUE(exception_state.HadException());
- EXPECT_EQ(kV8TypeError, exception_state.Code());
+ EXPECT_EQ(ESErrorType::kTypeError, exception_state.CodeAs<ESErrorType>());
EXPECT_EQ("'id' must not be empty.", exception_state.Message());
}
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/public_key_credential.cc b/chromium/third_party/blink/renderer/modules/credentialmanager/public_key_credential.cc
index e4a5d1c3afb..e219eb6b405 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/public_key_credential.cc
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/public_key_credential.cc
@@ -7,7 +7,8 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/modules/credentialmanager/credential_manager_proxy.h"
+#include "third_party/blink/renderer/modules/credentialmanager/scoped_promise_resolver.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
@@ -15,6 +16,12 @@ namespace blink {
namespace {
// https://www.w3.org/TR/webauthn/#dom-publickeycredential-type-slot:
constexpr char kPublicKeyCredentialType[] = "public-key";
+
+void OnIsUserVerifyingComplete(
+ std::unique_ptr<ScopedPromiseResolver> scoped_resolver,
+ bool available) {
+ scoped_resolver->Release()->Resolve(available);
+}
} // namespace
PublicKeyCredential* PublicKeyCredential::Create(
@@ -38,9 +45,23 @@ PublicKeyCredential::PublicKeyCredential(
ScriptPromise
PublicKeyCredential::isUserVerifyingPlatformAuthenticatorAvailable(
ScriptState* script_state) {
- return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kNotSupportedError, "Operation not implemented."));
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ // Ignore calls if the current realm execution context is no longer valid,
+ // e.g., because the responsible document was detached.
+ DCHECK(resolver->GetExecutionContext());
+ if (resolver->GetExecutionContext()->IsContextDestroyed()) {
+ resolver->Reject();
+ return promise;
+ }
+
+ auto* authenticator =
+ CredentialManagerProxy::From(script_state)->Authenticator();
+ authenticator->IsUserVerifyingPlatformAuthenticatorAvailable(WTF::Bind(
+ &OnIsUserVerifyingComplete,
+ WTF::Passed(std::make_unique<ScopedPromiseResolver>(resolver))));
+ return promise;
}
void PublicKeyCredential::getClientExtensionResults(
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/public_key_credential_creation_options.idl b/chromium/third_party/blink/renderer/modules/credentialmanager/public_key_credential_creation_options.idl
index 783c557e13f..3cf8af1e135 100644
--- a/chromium/third_party/blink/renderer/modules/credentialmanager/public_key_credential_creation_options.idl
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/public_key_credential_creation_options.idl
@@ -8,6 +8,7 @@ enum AttestationConveyancePreference {
"none",
"indirect",
"direct",
+ "enterprise",
};
// https://w3c.github.io/webauthn/#dictdef-PublicKeyCredentialCreationOptions
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/scoped_promise_resolver.cc b/chromium/third_party/blink/renderer/modules/credentialmanager/scoped_promise_resolver.cc
new file mode 100644
index 00000000000..03e877e0363
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/scoped_promise_resolver.cc
@@ -0,0 +1,31 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/credentialmanager/scoped_promise_resolver.h"
+
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
+
+namespace blink {
+
+ScopedPromiseResolver::ScopedPromiseResolver(ScriptPromiseResolver* resolver)
+ : resolver_(resolver) {}
+
+ScopedPromiseResolver::~ScopedPromiseResolver() {
+ if (resolver_)
+ OnConnectionError();
+}
+
+ScriptPromiseResolver* ScopedPromiseResolver::Release() {
+ return resolver_.Release();
+}
+
+void ScopedPromiseResolver::OnConnectionError() {
+ // The only anticipated reason for a connection error is that the embedder
+ // does not implement mojom::AuthenticatorImpl.
+ resolver_->Reject(DOMException::Create(
+ DOMExceptionCode::kNotSupportedError,
+ "The user agent does not support public key credentials."));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/credentialmanager/scoped_promise_resolver.h b/chromium/third_party/blink/renderer/modules/credentialmanager/scoped_promise_resolver.h
new file mode 100644
index 00000000000..6892b992400
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/credentialmanager/scoped_promise_resolver.h
@@ -0,0 +1,38 @@
+// 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_MODULES_CREDENTIALMANAGER_SCOPED_PROMISE_RESOLVER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_CREDENTIALMANAGER_SCOPED_PROMISE_RESOLVER_H_
+
+#include "base/macros.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+
+namespace blink {
+
+// Off-heap wrapper that holds a strong reference to a ScriptPromiseResolver.
+class ScopedPromiseResolver {
+ public:
+ explicit ScopedPromiseResolver(ScriptPromiseResolver* resolver);
+
+ ~ScopedPromiseResolver();
+
+ // Releases the owned |resolver_|. This is to be called by the Mojo response
+ // callback responsible for resolving the corresponding ScriptPromise
+ //
+ // If this method is not called before |this| goes of scope, it is assumed
+ // that a Mojo connection error has occurred, and the response callback was
+ // never invoked. The Promise will be rejected with an appropriate exception.
+ ScriptPromiseResolver* Release();
+
+ private:
+ void OnConnectionError();
+
+ Persistent<ScriptPromiseResolver> resolver_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedPromiseResolver);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_CREDENTIALMANAGER_SCOPED_PROMISE_RESOLVER_H_
diff --git a/chromium/third_party/blink/renderer/modules/crypto/crypto.cc b/chromium/third_party/blink/renderer/modules/crypto/crypto.cc
index 79c9e485d99..7c5bf68feaa 100644
--- a/chromium/third_party/blink/renderer/modules/crypto/crypto.cc
+++ b/chromium/third_party/blink/renderer/modules/crypto/crypto.cc
@@ -29,9 +29,8 @@
#include "third_party/blink/renderer/modules/crypto/crypto.h"
#include "crypto/random.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -56,7 +55,7 @@ NotShared<DOMArrayBufferView> Crypto::getRandomValues(
DCHECK(array);
if (!IsIntegerArray(array.View())) {
exception_state.ThrowDOMException(
- kTypeMismatchError,
+ DOMExceptionCode::kTypeMismatchError,
String::Format("The provided ArrayBufferView is of type '%s', which is "
"not an integer array type.",
array.View()->TypeName()));
@@ -64,7 +63,7 @@ NotShared<DOMArrayBufferView> Crypto::getRandomValues(
}
if (array.View()->byteLength() > 65536) {
exception_state.ThrowDOMException(
- kQuotaExceededError,
+ DOMExceptionCode::kQuotaExceededError,
String::Format("The ArrayBufferView's byte length (%u) exceeds the "
"number of bytes of entropy available via this API "
"(65536).",
diff --git a/chromium/third_party/blink/renderer/modules/crypto/crypto_key.cc b/chromium/third_party/blink/renderer/modules/crypto/crypto_key.cc
index 9f2eb12fe4c..6a37e560b13 100644
--- a/chromium/third_party/blink/renderer/modules/crypto/crypto_key.cc
+++ b/chromium/third_party/blink/renderer/modules/crypto/crypto_key.cc
@@ -33,9 +33,9 @@
#include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
#include "third_party/blink/public/platform/web_crypto_key_algorithm.h"
#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_uint8_array.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/to_v8.h"
#include "third_party/blink/renderer/platform/crypto_result.h"
diff --git a/chromium/third_party/blink/renderer/modules/crypto/crypto_result_impl.cc b/chromium/third_party/blink/renderer/modules/crypto/crypto_result_impl.cc
index 84cb06d8da3..50a9a6f06dc 100644
--- a/chromium/third_party/blink/renderer/modules/crypto/crypto_result_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/crypto/crypto_result_impl.cc
@@ -45,7 +45,7 @@
#include "third_party/blink/renderer/modules/crypto/crypto_key.h"
#include "third_party/blink/renderer/modules/crypto/normalize_algorithm.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/wtf/atomics.h"
+#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
namespace blink {
@@ -58,7 +58,7 @@ static void RejectWithTypeError(const String& error_details,
ScriptState::Scope scope(resolver->GetScriptState());
v8::Isolate* isolate = resolver->GetScriptState()->GetIsolate();
- resolver->Reject(v8::Exception::TypeError(V8String(isolate, error_details)));
+ resolver->Reject(V8ThrowException::CreateTypeError(isolate, error_details));
}
class CryptoResultImpl::Resolver final : public ScriptPromiseResolver {
@@ -102,17 +102,17 @@ void CryptoResultImpl::ResultCancel::Cancel() {
ExceptionCode WebCryptoErrorToExceptionCode(WebCryptoErrorType error_type) {
switch (error_type) {
case kWebCryptoErrorTypeNotSupported:
- return kNotSupportedError;
+ return ToExceptionCode(DOMExceptionCode::kNotSupportedError);
case kWebCryptoErrorTypeSyntax:
- return kSyntaxError;
+ return ToExceptionCode(DOMExceptionCode::kSyntaxError);
case kWebCryptoErrorTypeInvalidAccess:
- return kInvalidAccessError;
+ return ToExceptionCode(DOMExceptionCode::kInvalidAccessError);
case kWebCryptoErrorTypeData:
- return kDataError;
+ return ToExceptionCode(DOMExceptionCode::kDataError);
case kWebCryptoErrorTypeOperation:
- return kOperationError;
+ return ToExceptionCode(DOMExceptionCode::kOperationError);
case kWebCryptoErrorTypeType:
- return kV8TypeError;
+ return ToExceptionCode(ESErrorType::kTypeError);
}
NOTREACHED();
@@ -149,14 +149,20 @@ void CryptoResultImpl::CompleteWithError(WebCryptoErrorType error_type,
if (!resolver_)
return;
- ExceptionCode ec = WebCryptoErrorToExceptionCode(error_type);
+ ExceptionCode exception_code = WebCryptoErrorToExceptionCode(error_type);
// Handle TypeError separately, as it cannot be created using
// DOMException.
- if (ec == kV8TypeError)
+ if (exception_code == ToExceptionCode(ESErrorType::kTypeError)) {
RejectWithTypeError(error_details, resolver_);
- else
- resolver_->Reject(DOMException::Create(ec, error_details));
+ } else if (IsDOMExceptionCode(exception_code)) {
+ resolver_->Reject(DOMException::Create(
+ static_cast<DOMExceptionCode>(exception_code), error_details));
+ } else {
+ NOTREACHED();
+ resolver_->Reject(
+ DOMException::Create(DOMExceptionCode::kUnknownError, error_details));
+ }
ClearResolver();
}
diff --git a/chromium/third_party/blink/renderer/modules/crypto/crypto_result_impl.h b/chromium/third_party/blink/renderer/modules/crypto/crypto_result_impl.h
index 0c882d043fd..f404121d8fc 100644
--- a/chromium/third_party/blink/renderer/modules/crypto/crypto_result_impl.h
+++ b/chromium/third_party/blink/renderer/modules/crypto/crypto_result_impl.h
@@ -33,8 +33,8 @@
#include "third_party/blink/public/platform/web_crypto.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/bindings/exception_code.h"
#include "third_party/blink/renderer/platform/crypto_result.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
diff --git a/chromium/third_party/blink/renderer/modules/crypto/normalize_algorithm.cc b/chromium/third_party/blink/renderer/modules/crypto/normalize_algorithm.cc
index 649ea376372..013cfada404 100644
--- a/chromium/third_party/blink/renderer/modules/crypto/normalize_algorithm.cc
+++ b/chromium/third_party/blink/renderer/modules/crypto/normalize_algorithm.cc
@@ -135,7 +135,8 @@ bool VerifyAlgorithmNameMappings(const AlgorithmNameMapping* begin,
for (const AlgorithmNameMapping* it = begin; it != end; ++it) {
if (it->algorithm_name_length != strlen(it->algorithm_name))
return false;
- String str(it->algorithm_name, it->algorithm_name_length);
+ String str(it->algorithm_name,
+ static_cast<unsigned>(it->algorithm_name_length));
if (!str.ContainsOnlyASCII())
return false;
if (str.UpperASCII() != str)
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.cc b/chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.cc
index 09dc49c6fe4..4ab1a291ccd 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.cc
+++ b/chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.cc
@@ -75,7 +75,7 @@ scoped_refptr<Image> CSSPaintDefinition::Paint(
float zoom = layout_object.StyleRef().EffectiveZoom();
const FloatSize specified_size = GetSpecifiedSize(container_size, zoom);
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
MaybeCreatePaintInstance();
@@ -121,8 +121,7 @@ scoped_refptr<Image> CSSPaintDefinition::Paint(
v8::TryCatch block(isolate);
block.SetVerbose(true);
- V8ScriptRunner::CallFunction(paint,
- ExecutionContext::From(script_state_.get()),
+ V8ScriptRunner::CallFunction(paint, ExecutionContext::From(script_state_),
instance, argv.size(), argv.data(), isolate);
// The paint function may have produced an error, in which case produce an
@@ -154,10 +153,11 @@ void CSSPaintDefinition::MaybeCreatePaintInstance() {
did_call_constructor_ = true;
}
-void CSSPaintDefinition::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(constructor_.Cast<v8::Value>());
- visitor->TraceWrappers(paint_.Cast<v8::Value>());
- visitor->TraceWrappers(instance_.Cast<v8::Value>());
+void CSSPaintDefinition::Trace(Visitor* visitor) {
+ visitor->Trace(constructor_.Cast<v8::Value>());
+ visitor->Trace(paint_.Cast<v8::Value>());
+ visitor->Trace(instance_.Cast<v8::Value>());
+ visitor->Trace(script_state_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.h b/chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.h
index 88f52597d34..dede4c7bf87 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.h
+++ b/chromium/third_party/blink/renderer/modules/csspaint/css_paint_definition.h
@@ -10,8 +10,8 @@
#include "third_party/blink/renderer/core/css_property_names.h"
#include "third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_settings.h"
#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -28,7 +28,7 @@ class ImageResourceObserver;
// types as well.
class MODULES_EXPORT CSSPaintDefinition final
: public GarbageCollectedFinalized<CSSPaintDefinition>,
- public TraceWrapperBase {
+ public NameClient {
public:
static CSSPaintDefinition* Create(
ScriptState*,
@@ -65,14 +65,13 @@ class MODULES_EXPORT CSSPaintDefinition final
return context_settings_;
}
- ScriptState* GetScriptState() const { return script_state_.get(); }
+ ScriptState* GetScriptState() const { return script_state_; }
v8::Local<v8::Function> PaintFunctionForTesting(v8::Isolate* isolate) {
return paint_.NewLocal(isolate);
}
- void Trace(blink::Visitor* visitor){};
- void TraceWrappers(ScriptWrappableVisitor*) const override;
+ virtual void Trace(blink::Visitor* visitor);
const char* NameInHeapSnapshot() const override {
return "CSSPaintDefinition";
}
@@ -89,7 +88,7 @@ class MODULES_EXPORT CSSPaintDefinition final
void MaybeCreatePaintInstance();
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
// This object keeps the class instance object, constructor function and
// paint function alive. It participates in wrapper tracing as it holds onto
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/css_paint_worklet.idl b/chromium/third_party/blink/renderer/modules/csspaint/css_paint_worklet.idl
index 17b1ae56a74..bf14fcc6ec0 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/css_paint_worklet.idl
+++ b/chromium/third_party/blink/renderer/modules/csspaint/css_paint_worklet.idl
@@ -6,7 +6,6 @@
[
ImplementedAs=CSSPaintWorklet,
- RuntimeEnabled=CSSPaintAPI,
SecureContext
] partial interface CSS {
[CallWith=ScriptState,MeasureAs=PaintWorklet] static readonly attribute Worklet paintWorklet;
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.cc b/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.cc
index 818b9d21ac0..085161d5550 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.cc
+++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.cc
@@ -31,7 +31,7 @@ PaintRenderingContext2D::PaintRenderingContext2D(
void PaintRenderingContext2D::InitializePaintRecorder() {
paint_recorder_ = std::make_unique<PaintRecorder>();
- PaintCanvas* canvas = paint_recorder_->beginRecording(
+ cc::PaintCanvas* canvas = paint_recorder_->beginRecording(
container_size_.Width(), container_size_.Height());
// Always save an initial frame, to support resetting the top level matrix
@@ -41,7 +41,7 @@ void PaintRenderingContext2D::InitializePaintRecorder() {
did_record_draw_commands_in_paint_recorder_ = false;
}
-PaintCanvas* PaintRenderingContext2D::Canvas() const {
+cc::PaintCanvas* PaintRenderingContext2D::Canvas() const {
DCHECK(paint_recorder_);
DCHECK(paint_recorder_->getRecordingCanvas());
return paint_recorder_->getRecordingCanvas();
@@ -69,21 +69,46 @@ bool PaintRenderingContext2D::ParseColorOrCurrentColor(
return ::blink::ParseColorOrCurrentColor(color, color_string, nullptr);
}
+// We need to account for the |effective_zoom_| for shadow effects only, and not
+// for line width. This is because the line width is affected by skia's current
+// transform matrix (CTM) while shadows are not. The skia's CTM combines both
+// the canvas context transform and the CSS layout transform. That means, the
+// |effective_zoom_| is implictly applied to line width through CTM.
+double PaintRenderingContext2D::shadowBlur() const {
+ return BaseRenderingContext2D::shadowBlur() / effective_zoom_;
+}
+
void PaintRenderingContext2D::setShadowBlur(double blur) {
BaseRenderingContext2D::setShadowBlur(blur * effective_zoom_);
}
-PaintCanvas* PaintRenderingContext2D::DrawingCanvas() const {
+double PaintRenderingContext2D::shadowOffsetX() const {
+ return BaseRenderingContext2D::shadowOffsetX() / effective_zoom_;
+}
+
+void PaintRenderingContext2D::setShadowOffsetX(double x) {
+ BaseRenderingContext2D::setShadowOffsetX(x * effective_zoom_);
+}
+
+double PaintRenderingContext2D::shadowOffsetY() const {
+ return BaseRenderingContext2D::shadowOffsetY() / effective_zoom_;
+}
+
+void PaintRenderingContext2D::setShadowOffsetY(double y) {
+ BaseRenderingContext2D::setShadowOffsetY(y * effective_zoom_);
+}
+
+cc::PaintCanvas* PaintRenderingContext2D::DrawingCanvas() const {
return Canvas();
}
-PaintCanvas* PaintRenderingContext2D::ExistingDrawingCanvas() const {
+cc::PaintCanvas* PaintRenderingContext2D::ExistingDrawingCanvas() const {
return Canvas();
}
void PaintRenderingContext2D::ValidateStateStack() const {
#if DCHECK_IS_ON()
- if (PaintCanvas* sk_canvas = ExistingDrawingCanvas()) {
+ if (cc::PaintCanvas* sk_canvas = ExistingDrawingCanvas()) {
DCHECK_EQ(static_cast<size_t>(sk_canvas->getSaveCount()),
state_stack_.size() + 1);
}
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h b/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h
index a6d718cd0e3..a23889682d7 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h
+++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h
@@ -52,12 +52,19 @@ class MODULES_EXPORT PaintRenderingContext2D : public ScriptWrappable,
bool ParseColorOrCurrentColor(Color&, const String& color_string) const final;
- PaintCanvas* DrawingCanvas() const final;
- PaintCanvas* ExistingDrawingCanvas() const final;
+ cc::PaintCanvas* DrawingCanvas() const final;
+ cc::PaintCanvas* ExistingDrawingCanvas() const final;
void DisableDeferral(DisableDeferralReason) final {}
void DidDraw(const SkIRect&) final;
+ double shadowOffsetX() const final;
+ void setShadowOffsetX(double) final;
+
+ double shadowOffsetY() const final;
+ void setShadowOffsetY(double) final;
+
+ double shadowBlur() const final;
void setShadowBlur(double) final;
bool StateHasFilter() final;
@@ -89,7 +96,7 @@ class MODULES_EXPORT PaintRenderingContext2D : public ScriptWrappable,
float zoom);
void InitializePaintRecorder();
- PaintCanvas* Canvas() const;
+ cc::PaintCanvas* Canvas() const;
std::unique_ptr<PaintRecorder> paint_recorder_;
sk_sp<PaintRecord> previous_frame_;
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.idl b/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.idl
index d889355a1e9..7d69e7685fb 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.idl
+++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.idl
@@ -5,8 +5,7 @@
// https://drafts.css-houdini.org/css-paint-api/#paintrenderingcontext2d
[
- Exposed=PaintWorklet,
- RuntimeEnabled=CSSPaintAPI
+ Exposed=PaintWorklet
] interface PaintRenderingContext2D {
// state
void save(); // push state on state stack
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_size.idl b/chromium/third_party/blink/renderer/modules/csspaint/paint_size.idl
index d7d9a810756..1e57ff8c281 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/paint_size.idl
+++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_size.idl
@@ -5,8 +5,7 @@
// https://drafts.css-houdini.org/css-paint-api/#paintworkletglobalscope
[
- Exposed=PaintWorklet,
- RuntimeEnabled=CSSPaintAPI
+ Exposed=PaintWorklet
] interface PaintSize {
readonly attribute double width;
readonly attribute double height;
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc
index 6f8e07a1120..5f12f8a56aa 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc
+++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc
@@ -11,7 +11,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_paint_rendering_context_2d_settings.h"
#include "third_party/blink/renderer/core/css/css_syntax_descriptor.h"
#include "third_party/blink/renderer/core/css_property_names.h"
-#include "third_party/blink/renderer/core/dom/exception_code.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/main_thread_debugger.h"
@@ -136,7 +136,7 @@ void PaintWorkletGlobalScope::registerPaint(
if (paint_definitions_.Contains(name)) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"A class with name:'" + name + "' is already registered.");
return;
}
@@ -199,7 +199,7 @@ void PaintWorkletGlobalScope::registerPaint(
*definition)) {
document_definition_map.Set(name, kInvalidDocumentPaintDefinition);
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"A class with name:'" + name +
"' was registered with a different definition.");
return;
@@ -232,11 +232,4 @@ void PaintWorkletGlobalScope::Trace(blink::Visitor* visitor) {
MainThreadWorkletGlobalScope::Trace(visitor);
}
-void PaintWorkletGlobalScope::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- for (auto definition : paint_definitions_)
- visitor->TraceWrappers(definition.value);
- MainThreadWorkletGlobalScope::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h
index 8507654a2dc..1817e5dfc8b 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h
+++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h
@@ -42,7 +42,6 @@ class MODULES_EXPORT PaintWorkletGlobalScope final
double devicePixelRatio() const;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
PaintWorkletGlobalScope(LocalFrame*,
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.idl b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.idl
index 256194c67b5..cef58d789db 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.idl
+++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.idl
@@ -6,8 +6,7 @@
[
Exposed=PaintWorklet,
- Global=(Worklet,PaintWorklet),
- RuntimeEnabled=CSSPaintAPI
+ Global=(Worklet,PaintWorklet)
] interface PaintWorkletGlobalScope : WorkletGlobalScope {
[Measure] readonly attribute unrestricted double devicePixelRatio;
[Measure, RaisesException] void registerPaint(DOMString name, Function paintCtor);
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc
index 1dc425b108a..7ded3e21f87 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc
+++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc
@@ -8,9 +8,12 @@
#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_frame.h"
+#include "third_party/blink/renderer/core/frame/local_frame_client.h"
+#include "third_party/blink/renderer/core/loader/worker_fetch_context.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/workers/global_scope_creation_params.h"
+#include "third_party/blink/renderer/core/workers/worker_content_settings_client.h"
#include "third_party/blink/renderer/core/workers/worklet_module_responses_map.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/wtf.h"
@@ -32,12 +35,18 @@ PaintWorkletGlobalScopeProxy::PaintWorkletGlobalScopeProxy(
reporting_proxy_ =
std::make_unique<MainThreadWorkletReportingProxy>(document);
+ WorkerClients* worker_clients = WorkerClients::Create();
+ ProvideWorkerFetchContextToWorker(
+ worker_clients, frame->Client()->CreateWorkerFetchContext());
+ ProvideContentSettingsClientToWorker(
+ worker_clients, frame->Client()->CreateWorkerContentSettingsClient());
+
auto creation_params = std::make_unique<GlobalScopeCreationParams>(
document->Url(), ScriptType::kModule, document->UserAgent(),
- document->GetContentSecurityPolicy()->Headers().get(),
+ document->GetContentSecurityPolicy()->Headers(),
document->GetReferrerPolicy(), document->GetSecurityOrigin(),
- document->IsSecureContext(), nullptr /* worker_clients */,
- document->AddressSpace(), OriginTrialContext::GetTokens(document).get(),
+ document->IsSecureContext(), worker_clients, document->AddressSpace(),
+ OriginTrialContext::GetTokens(document).get(),
base::UnguessableToken::Create(), nullptr /* worker_settings */,
kV8CacheOptionsDefault, module_responses_map);
global_scope_ = PaintWorkletGlobalScope::Create(
@@ -48,12 +57,13 @@ PaintWorkletGlobalScopeProxy::PaintWorkletGlobalScopeProxy(
void PaintWorkletGlobalScopeProxy::FetchAndInvokeScript(
const KURL& module_url_record,
network::mojom::FetchCredentialsMode credentials_mode,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
WorkletPendingTasks* pending_tasks) {
DCHECK(IsMainThread());
- global_scope_->FetchAndInvokeScript(module_url_record, credentials_mode,
- std::move(outside_settings_task_runner),
- pending_tasks);
+ global_scope_->FetchAndInvokeScript(
+ module_url_record, credentials_mode, outside_settings_object,
+ std::move(outside_settings_task_runner), pending_tasks);
}
void PaintWorkletGlobalScopeProxy::WorkletObjectDestroyed() {
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.h b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.h
index f9ded050c27..cbf5a8dd01b 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.h
+++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.h
@@ -37,6 +37,7 @@ class MODULES_EXPORT PaintWorkletGlobalScopeProxy
void FetchAndInvokeScript(
const KURL& module_url_record,
network::mojom::FetchCredentialsMode,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
scoped_refptr<base::SingleThreadTaskRunner> outside_settings_task_runner,
WorkletPendingTasks*) override;
void WorkletObjectDestroyed() override;
diff --git a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_test.cc b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_test.cc
index cfd1275bb1d..a9f8c45c0bc 100644
--- a/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_test.cc
+++ b/chromium/third_party/blink/renderer/modules/csspaint/paint_worklet_test.cc
@@ -9,12 +9,14 @@
#include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.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/layout/layout_view.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/modules/csspaint/css_paint_definition.h"
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h"
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.h"
+#include "third_party/blink/renderer/platform/graphics/image.h"
namespace blink {
class TestPaintWorklet : public PaintWorklet {
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/BUILD.gn b/chromium/third_party/blink/renderer/modules/device_orientation/BUILD.gn
index 94a9a722d89..399ac3e87e6 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/BUILD.gn
@@ -16,6 +16,8 @@ blink_modules_sources("device_orientation") {
"device_motion_dispatcher.h",
"device_motion_event.cc",
"device_motion_event.h",
+ "device_motion_event_pump.cc",
+ "device_motion_event_pump.h",
"device_orientation_absolute_controller.cc",
"device_orientation_absolute_controller.h",
"device_orientation_controller.cc",
@@ -26,10 +28,13 @@ blink_modules_sources("device_orientation") {
"device_orientation_dispatcher.h",
"device_orientation_event.cc",
"device_orientation_event.h",
+ "device_orientation_event_pump.cc",
+ "device_orientation_event_pump.h",
"device_orientation_inspector_agent.cc",
"device_orientation_inspector_agent.h",
"device_rotation_rate.cc",
"device_rotation_rate.h",
+ "device_sensor_event_pump.h",
"dom_window_device_motion.h",
"dom_window_device_orientation.h",
]
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/DEPS b/chromium/third_party/blink/renderer/modules/device_orientation/DEPS
index cc8db4f809b..71a097e78ee 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/DEPS
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/DEPS
@@ -1,9 +1,17 @@
include_rules = [
+ "+base/run_loop.h",
+ "+mojo/public/cpp/bindings/binding.h",
+
# NOTE: These files are POD structs used to interpret shared memory across
# the Device Sensors implementation and the Blink client.
- "+services/device/public/cpp/generic_sensor/motion_data.h",
"+services/device/public/cpp/generic_sensor/orientation_data.h",
+ "+services/device/public/mojom/sensor.mojom-blink.h",
+ "+services/device/public/mojom/sensor_provider.mojom-blink.h",
+ "+services/device/public/cpp/test/fake_sensor_and_provider.h",
+ "+services/device/public/cpp/generic_sensor/sensor_reading.h",
+ "+services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h",
+ "+ui/gfx/geometry/angle_conversions.h",
"-third_party/blink/renderer/modules",
"+third_party/blink/renderer/modules/device_orientation",
"+third_party/blink/renderer/modules/event_modules.h",
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_controller.cc b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_controller.cc
index 2e8b3f76d8f..f1f4dbf278d 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_controller.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/device_orientation/device_motion_controller.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/core/frame/hosts_using_features.h"
#include "third_party/blink/renderer/core/frame/settings.h"
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_controller.h b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_controller.h
index 8a9ec8856ae..107bb0d4c2f 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_controller.h
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_controller.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_MOTION_CONTROLLER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_MOTION_CONTROLLER_H_
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/device_single_window_event_controller.h"
#include "third_party/blink/renderer/modules/modules_export.h"
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_data.cc b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_data.cc
index 87b39b19374..a1fa2dcd2f5 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_data.cc
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_data.cc
@@ -25,7 +25,6 @@
#include "third_party/blink/renderer/modules/device_orientation/device_motion_data.h"
-#include "services/device/public/cpp/generic_sensor/motion_data.h"
#include "third_party/blink/renderer/modules/device_orientation/device_acceleration_init.h"
#include "third_party/blink/renderer/modules/device_orientation/device_motion_event_init.h"
#include "third_party/blink/renderer/modules/device_orientation/device_rotation_rate_init.h"
@@ -126,25 +125,6 @@ DeviceMotionData* DeviceMotionData::Create(const DeviceMotionEventInit& init) {
init.interval());
}
-DeviceMotionData* DeviceMotionData::Create(const device::MotionData& data) {
- return DeviceMotionData::Create(
- DeviceMotionData::Acceleration::Create(
- data.has_acceleration_x, data.acceleration_x, data.has_acceleration_y,
- data.acceleration_y, data.has_acceleration_z, data.acceleration_z),
- DeviceMotionData::Acceleration::Create(
- data.has_acceleration_including_gravity_x,
- data.acceleration_including_gravity_x,
- data.has_acceleration_including_gravity_y,
- data.acceleration_including_gravity_y,
- data.has_acceleration_including_gravity_z,
- data.acceleration_including_gravity_z),
- DeviceMotionData::RotationRate::Create(
- data.has_rotation_rate_alpha, data.rotation_rate_alpha,
- data.has_rotation_rate_beta, data.rotation_rate_beta,
- data.has_rotation_rate_gamma, data.rotation_rate_gamma),
- data.interval);
-}
-
DeviceMotionData::DeviceMotionData() : interval_(0) {}
DeviceMotionData::DeviceMotionData(Acceleration* acceleration,
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_data.h b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_data.h
index 76a3f245894..aeece03e6ad 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_data.h
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_data.h
@@ -26,19 +26,17 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_MOTION_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_MOTION_DATA_H_
+#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
-namespace device {
-class MotionData;
-}
-
namespace blink {
class DeviceAccelerationInit;
class DeviceMotionEventInit;
class DeviceRotationRateInit;
-class DeviceMotionData final : public GarbageCollected<DeviceMotionData> {
+class MODULES_EXPORT DeviceMotionData final
+ : public GarbageCollected<DeviceMotionData> {
public:
class Acceleration final
: public GarbageCollected<DeviceMotionData::Acceleration> {
@@ -120,7 +118,6 @@ class DeviceMotionData final : public GarbageCollected<DeviceMotionData> {
RotationRate*,
double interval);
static DeviceMotionData* Create(const DeviceMotionEventInit&);
- static DeviceMotionData* Create(const device::MotionData&);
void Trace(blink::Visitor*);
Acceleration* GetAcceleration() const { return acceleration_.Get(); }
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_dispatcher.cc b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_dispatcher.cc
index 078a87db331..5b46504a08f 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_dispatcher.cc
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_dispatcher.cc
@@ -30,9 +30,9 @@
#include "third_party/blink/renderer/modules/device_orientation/device_motion_dispatcher.h"
-#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/modules/device_orientation/device_motion_controller.h"
#include "third_party/blink/renderer/modules/device_orientation/device_motion_data.h"
+#include "third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h"
namespace blink {
@@ -51,18 +51,25 @@ void DeviceMotionDispatcher::Trace(blink::Visitor* visitor) {
PlatformEventDispatcher::Trace(visitor);
}
-void DeviceMotionDispatcher::StartListening() {
- Platform::Current()->StartListening(kWebPlatformEventTypeDeviceMotion, this);
+void DeviceMotionDispatcher::StartListening(LocalFrame* frame) {
+ // TODO(crbug.com/850619): ensure a valid frame is passed
+ if (!frame)
+ return;
+ if (!event_pump_) {
+ event_pump_ = std::make_unique<DeviceMotionEventPump>(
+ frame->GetTaskRunner(TaskType::kSensor));
+ }
+ event_pump_->Start(frame, this);
}
void DeviceMotionDispatcher::StopListening() {
- Platform::Current()->StopListening(kWebPlatformEventTypeDeviceMotion);
+ if (event_pump_)
+ event_pump_->Stop();
last_device_motion_data_.Clear();
}
-void DeviceMotionDispatcher::DidChangeDeviceMotion(
- const device::MotionData& motion) {
- last_device_motion_data_ = DeviceMotionData::Create(motion);
+void DeviceMotionDispatcher::DidChangeDeviceMotion(DeviceMotionData* motion) {
+ last_device_motion_data_ = motion;
NotifyControllers();
}
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_dispatcher.h b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_dispatcher.h
index ae2878cc43e..70e76a1c15d 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_dispatcher.h
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_dispatcher.h
@@ -36,13 +36,10 @@
#include "third_party/blink/renderer/core/frame/platform_event_dispatcher.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
-namespace device {
-class MotionData;
-}
-
namespace blink {
class DeviceMotionData;
+class DeviceMotionEventPump;
// This class listens to device motion data and notifies all registered
// controllers.
@@ -60,7 +57,7 @@ class DeviceMotionDispatcher final
const DeviceMotionData* LatestDeviceMotionData();
// Inherited from WebDeviceMotionListener.
- void DidChangeDeviceMotion(const device::MotionData&) override;
+ void DidChangeDeviceMotion(DeviceMotionData*) override;
void Trace(blink::Visitor*) override;
@@ -68,10 +65,11 @@ class DeviceMotionDispatcher final
DeviceMotionDispatcher();
// Inherited from PlatformEventDispatcher.
- void StartListening() override;
+ void StartListening(LocalFrame*) override;
void StopListening() override;
Member<DeviceMotionData> last_device_motion_data_;
+ std::unique_ptr<DeviceMotionEventPump> event_pump_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.cc b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.cc
new file mode 100644
index 00000000000..06aab06b84a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.cc
@@ -0,0 +1,140 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <cmath>
+
+#include "services/device/public/mojom/sensor.mojom-blink.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/modules/device_orientation/device_motion_data.h"
+#include "third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h"
+#include "ui/gfx/geometry/angle_conversions.h"
+
+namespace {
+
+constexpr double kDefaultPumpDelayMilliseconds =
+ blink::DeviceMotionEventPump::kDefaultPumpDelayMicroseconds / 1000;
+
+} // namespace
+
+namespace blink {
+
+template class DeviceSensorEventPump<blink::WebDeviceMotionListener>;
+
+DeviceMotionEventPump::DeviceMotionEventPump(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : DeviceSensorEventPump<blink::WebDeviceMotionListener>(task_runner),
+ accelerometer_(this, device::mojom::blink::SensorType::ACCELEROMETER),
+ linear_acceleration_sensor_(
+ this,
+ device::mojom::blink::SensorType::LINEAR_ACCELERATION),
+ gyroscope_(this, device::mojom::blink::SensorType::GYROSCOPE) {}
+
+DeviceMotionEventPump::~DeviceMotionEventPump() {
+ StopIfObserving();
+}
+
+void DeviceMotionEventPump::SendStartMessage(LocalFrame* frame) {
+ if (!sensor_provider_) {
+ DCHECK(frame);
+
+ frame->GetInterfaceProvider().GetInterface(
+ mojo::MakeRequest(&sensor_provider_));
+ sensor_provider_.set_connection_error_handler(
+ WTF::Bind(&DeviceSensorEventPump::HandleSensorProviderError,
+ WTF::Unretained(this)));
+ }
+
+ accelerometer_.Start(sensor_provider_.get());
+ linear_acceleration_sensor_.Start(sensor_provider_.get());
+ gyroscope_.Start(sensor_provider_.get());
+}
+
+void DeviceMotionEventPump::SendStopMessage() {
+ // SendStopMessage() gets called both when the page visibility changes and if
+ // all device motion event listeners are unregistered. Since removing the
+ // event listener is more rare than the page visibility changing,
+ // Sensor::Suspend() is used to optimize this case for not doing extra work.
+
+ accelerometer_.Stop();
+ linear_acceleration_sensor_.Stop();
+ gyroscope_.Stop();
+}
+
+void DeviceMotionEventPump::FireEvent(TimerBase*) {
+ DCHECK(listener());
+
+ DeviceMotionData* data = GetDataFromSharedMemory();
+
+ // data is null if not all sensors are active
+ if (data)
+ listener()->DidChangeDeviceMotion(data);
+}
+
+bool DeviceMotionEventPump::SensorsReadyOrErrored() const {
+ return accelerometer_.ReadyOrErrored() &&
+ linear_acceleration_sensor_.ReadyOrErrored() &&
+ gyroscope_.ReadyOrErrored();
+}
+
+DeviceMotionData* DeviceMotionEventPump::GetDataFromSharedMemory() {
+ DeviceMotionData::Acceleration* acceleration = nullptr;
+ DeviceMotionData::Acceleration* acceleration_including_gravity = nullptr;
+ DeviceMotionData::RotationRate* rotation_rate = nullptr;
+
+ if (accelerometer_.SensorReadingCouldBeRead()) {
+ if (accelerometer_.reading.timestamp() == 0.0)
+ return nullptr;
+
+ acceleration_including_gravity = DeviceMotionData::Acceleration::Create(
+ !std::isnan(accelerometer_.reading.accel.x.value()),
+ accelerometer_.reading.accel.x,
+ !std::isnan(accelerometer_.reading.accel.y.value()),
+ accelerometer_.reading.accel.y,
+ !std::isnan(accelerometer_.reading.accel.z.value()),
+ accelerometer_.reading.accel.z);
+ } else {
+ acceleration_including_gravity = DeviceMotionData::Acceleration::Create(
+ false, 0.0, false, 0.0, false, 0.0);
+ }
+
+ if (linear_acceleration_sensor_.SensorReadingCouldBeRead()) {
+ if (linear_acceleration_sensor_.reading.timestamp() == 0.0)
+ return nullptr;
+
+ acceleration = DeviceMotionData::Acceleration::Create(
+ !std::isnan(linear_acceleration_sensor_.reading.accel.x.value()),
+ linear_acceleration_sensor_.reading.accel.x,
+ !std::isnan(linear_acceleration_sensor_.reading.accel.y.value()),
+ linear_acceleration_sensor_.reading.accel.y,
+ !std::isnan(linear_acceleration_sensor_.reading.accel.z.value()),
+ linear_acceleration_sensor_.reading.accel.z);
+ } else {
+ acceleration = DeviceMotionData::Acceleration::Create(false, 0.0, false,
+ 0.0, false, 0.0);
+ }
+
+ if (gyroscope_.SensorReadingCouldBeRead()) {
+ if (gyroscope_.reading.timestamp() == 0.0)
+ return nullptr;
+
+ rotation_rate = DeviceMotionData::RotationRate::Create(
+ !std::isnan(gyroscope_.reading.gyro.x.value()),
+ gfx::RadToDeg(gyroscope_.reading.gyro.x),
+ !std::isnan(gyroscope_.reading.gyro.y.value()),
+ gfx::RadToDeg(gyroscope_.reading.gyro.y),
+ !std::isnan(gyroscope_.reading.gyro.z.value()),
+ gfx::RadToDeg(gyroscope_.reading.gyro.z));
+ } else {
+ rotation_rate = DeviceMotionData::RotationRate::Create(false, 0.0, false,
+ 0.0, false, 0.0);
+ }
+
+ // The device orientation spec states that interval should be in
+ // milliseconds.
+ // https://w3c.github.io/deviceorientation/spec-source-orientation.html#devicemotion
+ return DeviceMotionData::Create(acceleration, acceleration_including_gravity,
+ rotation_rate, kDefaultPumpDelayMilliseconds);
+}
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h
new file mode 100644
index 00000000000..4d616365b3d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h
@@ -0,0 +1,48 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_MOTION_EVENT_PUMP_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_MOTION_EVENT_PUMP_H_
+
+#include "base/macros.h"
+#include "third_party/blink/public/platform/modules/device_orientation/web_device_motion_listener.h"
+#include "third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+
+namespace blink {
+
+class DeviceMotionData;
+
+class MODULES_EXPORT DeviceMotionEventPump
+ : public DeviceSensorEventPump<blink::WebDeviceMotionListener> {
+ public:
+ explicit DeviceMotionEventPump(scoped_refptr<base::SingleThreadTaskRunner>);
+ ~DeviceMotionEventPump() override;
+
+ // DeviceSensorEventPump:
+ void SendStartMessage(LocalFrame* frame) override;
+ void SendStopMessage() override;
+
+ protected:
+ // DeviceSensorEventPump:
+ void FireEvent(TimerBase*) override;
+
+ SensorEntry accelerometer_;
+ SensorEntry linear_acceleration_sensor_;
+ SensorEntry gyroscope_;
+
+ private:
+ friend class DeviceMotionEventPumpTest;
+
+ // DeviceSensorEventPump:
+ bool SensorsReadyOrErrored() const override;
+
+ DeviceMotionData* GetDataFromSharedMemory();
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceMotionEventPump);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_MOTION_EVENT_PUMP_H_
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc
new file mode 100644
index 00000000000..868c4f6cecf
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_motion_event_pump_unittest.cc
@@ -0,0 +1,425 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string.h>
+
+#include <memory>
+
+#include "base/run_loop.h"
+#include "services/device/public/cpp/test/fake_sensor_and_provider.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/modules/device_orientation/web_device_motion_listener.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/renderer/modules/device_orientation/device_motion_data.h"
+#include "third_party/blink/renderer/modules/device_orientation/device_motion_event_pump.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "ui/gfx/geometry/angle_conversions.h"
+
+namespace blink {
+
+using device::FakeSensorProvider;
+
+class MockDeviceMotionListener : public blink::WebDeviceMotionListener {
+ public:
+ MockDeviceMotionListener()
+ : did_change_device_motion_(false), number_of_events_(0) {
+ data_ = DeviceMotionData::Create();
+ }
+ ~MockDeviceMotionListener() override {}
+
+ void DidChangeDeviceMotion(DeviceMotionData* data) override {
+ data_ = data;
+ did_change_device_motion_ = true;
+ ++number_of_events_;
+ }
+
+ bool did_change_device_motion() const { return did_change_device_motion_; }
+
+ int number_of_events() const { return number_of_events_; }
+
+ const DeviceMotionData* data() const { return data_.Get(); }
+
+ private:
+ bool did_change_device_motion_;
+ int number_of_events_;
+ Persistent<DeviceMotionData> data_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockDeviceMotionListener);
+};
+
+class DeviceMotionEventPumpForTesting : public DeviceMotionEventPump {
+ public:
+ explicit DeviceMotionEventPumpForTesting(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : DeviceMotionEventPump(task_runner) {}
+ ~DeviceMotionEventPumpForTesting() override {}
+
+ int pump_delay_microseconds() const { return kDefaultPumpDelayMicroseconds; }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DeviceMotionEventPumpForTesting);
+};
+
+class DeviceMotionEventPumpTest : public testing::Test {
+ public:
+ DeviceMotionEventPumpTest() = default;
+
+ protected:
+ void SetUp() override {
+ motion_pump_.reset(new DeviceMotionEventPumpForTesting(
+ base::ThreadTaskRunnerHandle::Get()));
+ device::mojom::SensorProviderPtrInfo sensor_provider_ptr_info;
+ sensor_provider_.Bind(mojo::MakeRequest(&sensor_provider_ptr_info));
+ motion_pump_->SetSensorProviderForTesting(
+ device::mojom::blink::SensorProviderPtr(
+ device::mojom::blink::SensorProviderPtrInfo(
+ sensor_provider_ptr_info.PassHandle(),
+ device::mojom::SensorProvider::Version_)));
+
+ listener_.reset(new MockDeviceMotionListener);
+
+ ExpectAllThreeSensorsStateToBe(
+ DeviceMotionEventPump::SensorState::NOT_INITIALIZED);
+ EXPECT_EQ(DeviceMotionEventPump::PumpState::STOPPED,
+ motion_pump()->GetPumpStateForTesting());
+ }
+
+ void FireEvent() { motion_pump_->FireEvent(nullptr); }
+
+ void ExpectAccelerometerStateToBe(
+ DeviceMotionEventPump::SensorState expected_sensor_state) {
+ EXPECT_EQ(expected_sensor_state, motion_pump_->accelerometer_.sensor_state);
+ }
+
+ void ExpectLinearAccelerationSensorStateToBe(
+ DeviceMotionEventPump::SensorState expected_sensor_state) {
+ EXPECT_EQ(expected_sensor_state,
+ motion_pump_->linear_acceleration_sensor_.sensor_state);
+ }
+
+ void ExpectGyroscopeStateToBe(
+ DeviceMotionEventPump::SensorState expected_sensor_state) {
+ EXPECT_EQ(expected_sensor_state, motion_pump_->gyroscope_.sensor_state);
+ }
+
+ void ExpectAllThreeSensorsStateToBe(
+ DeviceMotionEventPump::SensorState expected_sensor_state) {
+ ExpectAccelerometerStateToBe(expected_sensor_state);
+ ExpectLinearAccelerationSensorStateToBe(expected_sensor_state);
+ ExpectGyroscopeStateToBe(expected_sensor_state);
+ }
+
+ DeviceMotionEventPumpForTesting* motion_pump() { return motion_pump_.get(); }
+
+ MockDeviceMotionListener* listener() { return listener_.get(); }
+
+ FakeSensorProvider* sensor_provider() { return &sensor_provider_; }
+
+ private:
+ std::unique_ptr<DeviceMotionEventPumpForTesting> motion_pump_;
+ std::unique_ptr<MockDeviceMotionListener> listener_;
+ FakeSensorProvider sensor_provider_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceMotionEventPumpTest);
+};
+
+TEST_F(DeviceMotionEventPumpTest, MultipleStartAndStopWithWait) {
+ motion_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE);
+ EXPECT_EQ(DeviceMotionEventPump::PumpState::RUNNING,
+ motion_pump()->GetPumpStateForTesting());
+
+ motion_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+ EXPECT_EQ(DeviceMotionEventPump::PumpState::STOPPED,
+ motion_pump()->GetPumpStateForTesting());
+
+ motion_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE);
+ EXPECT_EQ(DeviceMotionEventPump::PumpState::RUNNING,
+ motion_pump()->GetPumpStateForTesting());
+
+ motion_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+ EXPECT_EQ(DeviceMotionEventPump::PumpState::STOPPED,
+ motion_pump()->GetPumpStateForTesting());
+}
+
+TEST_F(DeviceMotionEventPumpTest, CallStop) {
+ motion_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAllThreeSensorsStateToBe(
+ DeviceMotionEventPump::SensorState::NOT_INITIALIZED);
+}
+
+TEST_F(DeviceMotionEventPumpTest, CallStartAndStop) {
+ motion_pump()->Start(nullptr, listener());
+ motion_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceMotionEventPumpTest, CallStartMultipleTimes) {
+ motion_pump()->Start(nullptr, listener());
+ motion_pump()->Start(nullptr, listener());
+ motion_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceMotionEventPumpTest, CallStopMultipleTimes) {
+ motion_pump()->Start(nullptr, listener());
+ motion_pump()->Stop();
+ motion_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+}
+
+// Test multiple DeviceSensorEventPump::Start() calls only bind sensor once.
+TEST_F(DeviceMotionEventPumpTest, SensorOnlyBindOnce) {
+ motion_pump()->Start(nullptr, listener());
+ motion_pump()->Stop();
+ motion_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE);
+
+ motion_pump()->Stop();
+
+ ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceMotionEventPumpTest, AllSensorsAreActive) {
+ motion_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE);
+
+ sensor_provider()->UpdateAccelerometerData(1, 2, 3);
+ sensor_provider()->UpdateLinearAccelerationSensorData(4, 5, 6);
+ sensor_provider()->UpdateGyroscopeData(7, 8, 9);
+
+ FireEvent();
+
+ EXPECT_TRUE(listener()->did_change_device_motion());
+
+ const DeviceMotionData* received_data = listener()->data();
+
+ EXPECT_TRUE(received_data->GetAccelerationIncludingGravity()->CanProvideX());
+ EXPECT_EQ(1, received_data->GetAccelerationIncludingGravity()->X());
+ EXPECT_TRUE(received_data->GetAccelerationIncludingGravity()->CanProvideY());
+ EXPECT_EQ(2, received_data->GetAccelerationIncludingGravity()->Y());
+ EXPECT_TRUE(received_data->GetAccelerationIncludingGravity()->CanProvideZ());
+ EXPECT_EQ(3, received_data->GetAccelerationIncludingGravity()->Z());
+
+ EXPECT_TRUE(received_data->GetAcceleration()->CanProvideX());
+ EXPECT_EQ(4, received_data->GetAcceleration()->X());
+ EXPECT_TRUE(received_data->GetAcceleration()->CanProvideY());
+ EXPECT_EQ(5, received_data->GetAcceleration()->Y());
+ EXPECT_TRUE(received_data->GetAcceleration()->CanProvideZ());
+ EXPECT_EQ(6, received_data->GetAcceleration()->Z());
+
+ EXPECT_TRUE(received_data->GetRotationRate()->CanProvideAlpha());
+ EXPECT_EQ(gfx::RadToDeg(7.0), received_data->GetRotationRate()->Alpha());
+ EXPECT_TRUE(received_data->GetRotationRate()->CanProvideBeta());
+ EXPECT_EQ(gfx::RadToDeg(8.0), received_data->GetRotationRate()->Beta());
+ EXPECT_TRUE(received_data->GetRotationRate()->CanProvideGamma());
+ EXPECT_EQ(gfx::RadToDeg(9.0), received_data->GetRotationRate()->Gamma());
+
+ motion_pump()->Stop();
+
+ ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceMotionEventPumpTest, TwoSensorsAreActive) {
+ sensor_provider()->set_linear_acceleration_sensor_is_available(false);
+
+ motion_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAccelerometerStateToBe(DeviceMotionEventPump::SensorState::ACTIVE);
+ ExpectLinearAccelerationSensorStateToBe(
+ DeviceMotionEventPump::SensorState::NOT_INITIALIZED);
+ ExpectGyroscopeStateToBe(DeviceMotionEventPump::SensorState::ACTIVE);
+
+ sensor_provider()->UpdateAccelerometerData(1, 2, 3);
+ sensor_provider()->UpdateGyroscopeData(7, 8, 9);
+
+ FireEvent();
+
+ const DeviceMotionData* received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_motion());
+
+ EXPECT_TRUE(received_data->GetAccelerationIncludingGravity()->CanProvideX());
+ EXPECT_EQ(1, received_data->GetAccelerationIncludingGravity()->X());
+ EXPECT_TRUE(received_data->GetAccelerationIncludingGravity()->CanProvideY());
+ EXPECT_EQ(2, received_data->GetAccelerationIncludingGravity()->Y());
+ EXPECT_TRUE(received_data->GetAccelerationIncludingGravity()->CanProvideZ());
+ EXPECT_EQ(3, received_data->GetAccelerationIncludingGravity()->Z());
+
+ EXPECT_FALSE(received_data->GetAcceleration()->CanProvideX());
+ EXPECT_FALSE(received_data->GetAcceleration()->CanProvideY());
+ EXPECT_FALSE(received_data->GetAcceleration()->CanProvideZ());
+
+ EXPECT_TRUE(received_data->GetRotationRate()->CanProvideAlpha());
+ EXPECT_EQ(gfx::RadToDeg(7.0), received_data->GetRotationRate()->Alpha());
+ EXPECT_TRUE(received_data->GetRotationRate()->CanProvideBeta());
+ EXPECT_EQ(gfx::RadToDeg(8.0), received_data->GetRotationRate()->Beta());
+ EXPECT_TRUE(received_data->GetRotationRate()->CanProvideGamma());
+ EXPECT_EQ(gfx::RadToDeg(9.0), received_data->GetRotationRate()->Gamma());
+
+ motion_pump()->Stop();
+
+ ExpectAccelerometerStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+ ExpectLinearAccelerationSensorStateToBe(
+ DeviceMotionEventPump::SensorState::NOT_INITIALIZED);
+ ExpectGyroscopeStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceMotionEventPumpTest, SomeSensorDataFieldsNotAvailable) {
+ motion_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE);
+
+ sensor_provider()->UpdateAccelerometerData(NAN, 2, 3);
+ sensor_provider()->UpdateLinearAccelerationSensorData(4, NAN, 6);
+ sensor_provider()->UpdateGyroscopeData(7, 8, NAN);
+
+ FireEvent();
+
+ const DeviceMotionData* received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_motion());
+
+ EXPECT_FALSE(received_data->GetAccelerationIncludingGravity()->CanProvideX());
+ EXPECT_TRUE(received_data->GetAccelerationIncludingGravity()->CanProvideY());
+ EXPECT_EQ(2, received_data->GetAccelerationIncludingGravity()->Y());
+ EXPECT_TRUE(received_data->GetAccelerationIncludingGravity()->CanProvideZ());
+ EXPECT_EQ(3, received_data->GetAccelerationIncludingGravity()->Z());
+
+ EXPECT_TRUE(received_data->GetAcceleration()->CanProvideX());
+ EXPECT_EQ(4, received_data->GetAcceleration()->X());
+ EXPECT_FALSE(received_data->GetAcceleration()->CanProvideY());
+ EXPECT_TRUE(received_data->GetAcceleration()->CanProvideZ());
+ EXPECT_EQ(6, received_data->GetAcceleration()->Z());
+
+ EXPECT_TRUE(received_data->GetRotationRate()->CanProvideAlpha());
+ EXPECT_EQ(gfx::RadToDeg(7.0), received_data->GetRotationRate()->Alpha());
+ EXPECT_TRUE(received_data->GetRotationRate()->CanProvideBeta());
+ EXPECT_EQ(gfx::RadToDeg(8.0), received_data->GetRotationRate()->Beta());
+ EXPECT_FALSE(received_data->GetRotationRate()->CanProvideGamma());
+
+ motion_pump()->Stop();
+
+ ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceMotionEventPumpTest, FireAllNullEvent) {
+ // No active sensors.
+ sensor_provider()->set_accelerometer_is_available(false);
+ sensor_provider()->set_linear_acceleration_sensor_is_available(false);
+ sensor_provider()->set_gyroscope_is_available(false);
+
+ motion_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAllThreeSensorsStateToBe(
+ DeviceMotionEventPump::SensorState::NOT_INITIALIZED);
+
+ FireEvent();
+
+ const DeviceMotionData* received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_motion());
+
+ EXPECT_FALSE(received_data->GetAcceleration()->CanProvideX());
+ EXPECT_FALSE(received_data->GetAcceleration()->CanProvideY());
+ EXPECT_FALSE(received_data->GetAcceleration()->CanProvideZ());
+
+ EXPECT_FALSE(received_data->GetAccelerationIncludingGravity()->CanProvideX());
+ EXPECT_FALSE(received_data->GetAccelerationIncludingGravity()->CanProvideY());
+ EXPECT_FALSE(received_data->GetAccelerationIncludingGravity()->CanProvideZ());
+
+ EXPECT_FALSE(received_data->GetRotationRate()->CanProvideAlpha());
+ EXPECT_FALSE(received_data->GetRotationRate()->CanProvideBeta());
+ EXPECT_FALSE(received_data->GetRotationRate()->CanProvideGamma());
+
+ motion_pump()->Stop();
+
+ ExpectAllThreeSensorsStateToBe(
+ DeviceMotionEventPump::SensorState::NOT_INITIALIZED);
+}
+
+TEST_F(DeviceMotionEventPumpTest,
+ NotFireEventWhenSensorReadingTimeStampIsZero) {
+ motion_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE);
+
+ FireEvent();
+ EXPECT_FALSE(listener()->did_change_device_motion());
+
+ sensor_provider()->UpdateAccelerometerData(1, 2, 3);
+ FireEvent();
+ EXPECT_FALSE(listener()->did_change_device_motion());
+
+ sensor_provider()->UpdateLinearAccelerationSensorData(4, 5, 6);
+ FireEvent();
+ EXPECT_FALSE(listener()->did_change_device_motion());
+
+ sensor_provider()->UpdateGyroscopeData(7, 8, 9);
+ FireEvent();
+ // Event is fired only after all the available sensors have data.
+ EXPECT_TRUE(listener()->did_change_device_motion());
+
+ motion_pump()->Stop();
+
+ ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+}
+
+// Confirm that the frequency of pumping events is not greater than 60Hz.
+// A rate above 60Hz would allow for the detection of keystrokes.
+// (crbug.com/421691)
+TEST_F(DeviceMotionEventPumpTest, PumpThrottlesEventRate) {
+ // Confirm that the delay for pumping events is 60 Hz.
+ EXPECT_GE(60, WTF::Time::kMicrosecondsPerSecond /
+ motion_pump()->pump_delay_microseconds());
+
+ motion_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::ACTIVE);
+
+ sensor_provider()->UpdateAccelerometerData(1, 2, 3);
+ sensor_provider()->UpdateLinearAccelerationSensorData(4, 5, 6);
+ sensor_provider()->UpdateGyroscopeData(7, 8, 9);
+
+ base::RunLoop loop;
+ blink::scheduler::GetSingleThreadTaskRunnerForTesting()->PostDelayedTask(
+ FROM_HERE, loop.QuitWhenIdleClosure(),
+ WTF::TimeDelta::FromMilliseconds(100));
+ loop.Run();
+ motion_pump()->Stop();
+
+ ExpectAllThreeSensorsStateToBe(DeviceMotionEventPump::SensorState::SUSPENDED);
+
+ // Check that the blink::WebDeviceMotionListener does not receive excess
+ // events.
+ EXPECT_TRUE(listener()->did_change_device_motion());
+ EXPECT_GE(6, listener()->number_of_events());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.cc b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.cc
index 349cb536e0f..becd631742e 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/device_orientation/device_orientation_absolute_controller.h"
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.h"
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc
index 6c0634056c0..198eed07893 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/device_orientation/device_orientation_controller.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/core/frame/frame_console.h"
#include "third_party/blink/renderer/core/frame/hosts_using_features.h"
@@ -156,7 +157,7 @@ void DeviceOrientationController::LogToConsolePolicyFeaturesDisabled(
const String& message = String::Format(
"The %s events are blocked by feature policy. "
"See "
- "https://github.com/WICG/feature-policy/blob/gh-pages/"
+ "https://github.com/WICG/feature-policy/blob/master/"
"features.md#sensor-features",
event_name.Ascii().data());
ConsoleMessage* console_message = ConsoleMessage::Create(
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.h b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.h
index 0ceb013be98..fdd13f6e781 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.h
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_controller.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_ORIENTATION_CONTROLLER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_ORIENTATION_CONTROLLER_H_
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/device_single_window_event_controller.h"
#include "third_party/blink/renderer/modules/modules_export.h"
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.cc b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.cc
index 84a475432be..8a15c24af20 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.cc
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.cc
@@ -30,9 +30,9 @@
#include "third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.h"
-#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/modules/device_orientation/device_orientation_controller.h"
#include "third_party/blink/renderer/modules/device_orientation/device_orientation_data.h"
+#include "third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h"
namespace blink {
@@ -60,12 +60,20 @@ void DeviceOrientationDispatcher::Trace(blink::Visitor* visitor) {
PlatformEventDispatcher::Trace(visitor);
}
-void DeviceOrientationDispatcher::StartListening() {
- Platform::Current()->StartListening(GetWebPlatformEventType(), this);
+void DeviceOrientationDispatcher::StartListening(LocalFrame* frame) {
+ // TODO(crbug.com/850619): ensure a valid frame is passed
+ if (!frame)
+ return;
+ if (!event_pump_) {
+ event_pump_ = std::make_unique<DeviceOrientationEventPump>(
+ frame->GetTaskRunner(TaskType::kSensor), absolute_);
+ }
+ event_pump_->Start(frame, this);
}
void DeviceOrientationDispatcher::StopListening() {
- Platform::Current()->StopListening(GetWebPlatformEventType());
+ if (event_pump_)
+ event_pump_->Stop();
last_device_orientation_data_.Clear();
}
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.h b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.h
index 0190b337d6f..62a9453ad32 100644
--- a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.h
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_dispatcher.h
@@ -44,6 +44,7 @@ class OrientationData;
namespace blink {
class DeviceOrientationData;
+class DeviceOrientationEventPump;
// This class listens to device orientation data and notifies all registered
// controllers.
@@ -70,13 +71,14 @@ class DeviceOrientationDispatcher final
explicit DeviceOrientationDispatcher(bool absolute);
// Inherited from PlatformEventDispatcher.
- void StartListening() override;
+ void StartListening(LocalFrame* frame) override;
void StopListening() override;
WebPlatformEventType GetWebPlatformEventType() const;
const bool absolute_;
Member<DeviceOrientationData> last_device_orientation_data_;
+ std::unique_ptr<DeviceOrientationEventPump> event_pump_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.cc b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.cc
new file mode 100644
index 00000000000..459caef8295
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.cc
@@ -0,0 +1,213 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <cmath>
+
+#include "services/device/public/mojom/sensor.mojom-blink.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h"
+
+namespace {
+
+bool IsAngleDifferentThreshold(bool has_angle1,
+ double angle1,
+ bool has_angle2,
+ double angle2) {
+ if (has_angle1 != has_angle2)
+ return true;
+
+ return (has_angle1 &&
+ std::fabs(angle1 - angle2) >=
+ blink::DeviceOrientationEventPump::kOrientationThreshold);
+}
+
+bool IsSignificantlyDifferent(const device::OrientationData& data1,
+ const device::OrientationData& data2) {
+ return IsAngleDifferentThreshold(data1.has_alpha, data1.alpha,
+ data2.has_alpha, data2.alpha) ||
+ IsAngleDifferentThreshold(data1.has_beta, data1.beta, data2.has_beta,
+ data2.beta) ||
+ IsAngleDifferentThreshold(data1.has_gamma, data1.gamma,
+ data2.has_gamma, data2.gamma);
+}
+
+} // namespace
+
+namespace blink {
+
+template class DeviceSensorEventPump<blink::WebDeviceOrientationListener>;
+
+const double DeviceOrientationEventPump::kOrientationThreshold = 0.1;
+
+DeviceOrientationEventPump::DeviceOrientationEventPump(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ bool absolute)
+ : DeviceSensorEventPump<blink::WebDeviceOrientationListener>(task_runner),
+ relative_orientation_sensor_(
+ this,
+ device::mojom::SensorType::RELATIVE_ORIENTATION_EULER_ANGLES),
+ absolute_orientation_sensor_(
+ this,
+ device::mojom::SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES),
+ absolute_(absolute),
+ fall_back_to_absolute_orientation_sensor_(!absolute) {}
+
+DeviceOrientationEventPump::~DeviceOrientationEventPump() {
+ StopIfObserving();
+}
+
+void DeviceOrientationEventPump::SendStartMessage(LocalFrame* frame) {
+ if (!sensor_provider_) {
+ DCHECK(frame);
+
+ frame->GetInterfaceProvider().GetInterface(
+ mojo::MakeRequest(&sensor_provider_));
+ sensor_provider_.set_connection_error_handler(
+ WTF::Bind(&DeviceSensorEventPump::HandleSensorProviderError,
+ WTF::Unretained(this)));
+ }
+
+ if (absolute_) {
+ absolute_orientation_sensor_.Start(sensor_provider_.get());
+ } else {
+ fall_back_to_absolute_orientation_sensor_ = true;
+ should_suspend_absolute_orientation_sensor_ = false;
+ relative_orientation_sensor_.Start(sensor_provider_.get());
+ }
+}
+
+void DeviceOrientationEventPump::SendStopMessage() {
+ // SendStopMessage() gets called both when the page visibility changes and if
+ // all device orientation event listeners are unregistered. Since removing
+ // the event listener is more rare than the page visibility changing,
+ // Sensor::Suspend() is used to optimize this case for not doing extra work.
+
+ relative_orientation_sensor_.Stop();
+ // This is needed in case we fallback to using the absolute orientation
+ // sensor. In this case, the relative orientation sensor is marked as
+ // SensorState::SHOULD_SUSPEND, and if the relative orientation sensor
+ // is not available, the absolute orientation sensor should also be marked as
+ // SensorState::SHOULD_SUSPEND, but only after the
+ // absolute_orientation_sensor_.Start() is called for initializing
+ // the absolute orientation sensor in
+ // DeviceOrientationEventPump::DidStartIfPossible().
+ if (relative_orientation_sensor_.sensor_state ==
+ SensorState::SHOULD_SUSPEND &&
+ fall_back_to_absolute_orientation_sensor_) {
+ should_suspend_absolute_orientation_sensor_ = true;
+ }
+
+ absolute_orientation_sensor_.Stop();
+
+ // Reset the cached data because DeviceOrientationDispatcher resets its
+ // data when stopping. If we don't reset here as well, then when starting back
+ // up we won't notify DeviceOrientationDispatcher of the orientation, since
+ // we think it hasn't changed.
+ data_ = device::OrientationData();
+}
+
+void DeviceOrientationEventPump::FireEvent(TimerBase*) {
+ device::OrientationData data;
+
+ DCHECK(listener());
+
+ GetDataFromSharedMemory(&data);
+
+ if (ShouldFireEvent(data)) {
+ data_ = data;
+ listener()->DidChangeDeviceOrientation(data);
+ }
+}
+
+void DeviceOrientationEventPump::DidStartIfPossible() {
+ if (!absolute_ && !relative_orientation_sensor_.sensor &&
+ fall_back_to_absolute_orientation_sensor_ && sensor_provider_) {
+ // When relative orientation sensor is not available fall back to using
+ // the absolute orientation sensor but only on the first failure.
+ fall_back_to_absolute_orientation_sensor_ = false;
+ absolute_orientation_sensor_.Start(sensor_provider_.get());
+ if (should_suspend_absolute_orientation_sensor_) {
+ // The absolute orientation sensor needs to be marked as
+ // SensorState::SUSPENDED when it is successfully initialized.
+ absolute_orientation_sensor_.sensor_state = SensorState::SHOULD_SUSPEND;
+ should_suspend_absolute_orientation_sensor_ = false;
+ }
+ return;
+ }
+ DeviceSensorEventPump::DidStartIfPossible();
+}
+
+bool DeviceOrientationEventPump::SensorsReadyOrErrored() const {
+ if (!relative_orientation_sensor_.ReadyOrErrored() ||
+ !absolute_orientation_sensor_.ReadyOrErrored()) {
+ return false;
+ }
+
+ // At most one sensor can be successfully initialized.
+ DCHECK(!relative_orientation_sensor_.sensor ||
+ !absolute_orientation_sensor_.sensor);
+
+ return true;
+}
+
+void DeviceOrientationEventPump::GetDataFromSharedMemory(
+ device::OrientationData* data) {
+ data->all_available_sensors_are_active = true;
+
+ if (!absolute_ && relative_orientation_sensor_.SensorReadingCouldBeRead()) {
+ // For DeviceOrientation Event, this provides relative orientation data.
+ data->all_available_sensors_are_active =
+ relative_orientation_sensor_.reading.timestamp() != 0.0;
+ if (!data->all_available_sensors_are_active)
+ return;
+ data->alpha = relative_orientation_sensor_.reading.orientation_euler.z;
+ data->beta = relative_orientation_sensor_.reading.orientation_euler.x;
+ data->gamma = relative_orientation_sensor_.reading.orientation_euler.y;
+ data->has_alpha = !std::isnan(
+ relative_orientation_sensor_.reading.orientation_euler.z.value());
+ data->has_beta = !std::isnan(
+ relative_orientation_sensor_.reading.orientation_euler.x.value());
+ data->has_gamma = !std::isnan(
+ relative_orientation_sensor_.reading.orientation_euler.y.value());
+ data->absolute = false;
+ } else if (absolute_orientation_sensor_.SensorReadingCouldBeRead()) {
+ // For DeviceOrientationAbsolute Event, this provides absolute orientation
+ // data.
+ //
+ // For DeviceOrientation Event, this provides absolute orientation data if
+ // relative orientation data is not available.
+ data->all_available_sensors_are_active =
+ absolute_orientation_sensor_.reading.timestamp() != 0.0;
+ if (!data->all_available_sensors_are_active)
+ return;
+ data->alpha = absolute_orientation_sensor_.reading.orientation_euler.z;
+ data->beta = absolute_orientation_sensor_.reading.orientation_euler.x;
+ data->gamma = absolute_orientation_sensor_.reading.orientation_euler.y;
+ data->has_alpha = !std::isnan(
+ absolute_orientation_sensor_.reading.orientation_euler.z.value());
+ data->has_beta = !std::isnan(
+ absolute_orientation_sensor_.reading.orientation_euler.x.value());
+ data->has_gamma = !std::isnan(
+ absolute_orientation_sensor_.reading.orientation_euler.y.value());
+ data->absolute = true;
+ } else {
+ data->absolute = absolute_;
+ }
+}
+
+bool DeviceOrientationEventPump::ShouldFireEvent(
+ const device::OrientationData& data) const {
+ if (!data.all_available_sensors_are_active)
+ return false;
+
+ if (!data.has_alpha && !data.has_beta && !data.has_gamma) {
+ // no data can be provided, this is an all-null event.
+ return true;
+ }
+
+ return IsSignificantlyDifferent(data_, data);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h
new file mode 100644
index 00000000000..cc2122b9680
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h
@@ -0,0 +1,61 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_ORIENTATION_EVENT_PUMP_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_ORIENTATION_EVENT_PUMP_H_
+
+#include "base/macros.h"
+#include "services/device/public/cpp/generic_sensor/orientation_data.h"
+#include "third_party/blink/public/platform/modules/device_orientation/web_device_orientation_listener.h"
+#include "third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+
+namespace blink {
+
+class MODULES_EXPORT DeviceOrientationEventPump
+ : public DeviceSensorEventPump<blink::WebDeviceOrientationListener> {
+ public:
+ // Angle threshold beyond which two orientation events are considered
+ // sufficiently different.
+ static const double kOrientationThreshold;
+
+ explicit DeviceOrientationEventPump(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ bool absolute);
+ ~DeviceOrientationEventPump() override;
+
+ // DeviceSensorEventPump:
+ void SendStartMessage(LocalFrame* frame) override;
+ void SendStopMessage() override;
+
+ protected:
+ // DeviceSensorEventPump:
+ void FireEvent(TimerBase*) override;
+ void DidStartIfPossible() override;
+
+ SensorEntry relative_orientation_sensor_;
+ SensorEntry absolute_orientation_sensor_;
+
+ private:
+ friend class DeviceOrientationEventPumpTest;
+ friend class DeviceAbsoluteOrientationEventPumpTest;
+
+ // DeviceSensorEventPump:
+ bool SensorsReadyOrErrored() const override;
+
+ void GetDataFromSharedMemory(device::OrientationData* data);
+
+ bool ShouldFireEvent(const device::OrientationData& data) const;
+
+ bool absolute_;
+ bool fall_back_to_absolute_orientation_sensor_;
+ bool should_suspend_absolute_orientation_sensor_ = false;
+ device::OrientationData data_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceOrientationEventPump);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_ORIENTATION_EVENT_PUMP_H_
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc
new file mode 100644
index 00000000000..95b644c61b2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump_unittest.cc
@@ -0,0 +1,1011 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string.h>
+
+#include <memory>
+
+#include "base/run_loop.h"
+#include "services/device/public/cpp/generic_sensor/orientation_data.h"
+#include "services/device/public/cpp/test/fake_sensor_and_provider.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/modules/device_orientation/web_device_orientation_listener.h"
+#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
+#include "third_party/blink/renderer/modules/device_orientation/device_orientation_event_pump.h"
+
+namespace {
+
+constexpr double kEpsilon = 1e-8;
+
+} // namespace
+
+namespace blink {
+
+using device::FakeSensorProvider;
+
+class MockDeviceOrientationListener
+ : public blink::WebDeviceOrientationListener {
+ public:
+ MockDeviceOrientationListener() : did_change_device_orientation_(false) {
+ memset(&data_, 0, sizeof(data_));
+ }
+ ~MockDeviceOrientationListener() override {}
+
+ void DidChangeDeviceOrientation(
+ const device::OrientationData& data) override {
+ memcpy(&data_, &data, sizeof(data));
+ did_change_device_orientation_ = true;
+ }
+
+ bool did_change_device_orientation() const {
+ return did_change_device_orientation_;
+ }
+ void set_did_change_device_orientation(bool value) {
+ did_change_device_orientation_ = value;
+ }
+ const device::OrientationData& data() const { return data_; }
+
+ private:
+ bool did_change_device_orientation_;
+ device::OrientationData data_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockDeviceOrientationListener);
+};
+
+class DeviceOrientationEventPumpForTesting : public DeviceOrientationEventPump {
+ public:
+ explicit DeviceOrientationEventPumpForTesting(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ bool absolute)
+ : DeviceOrientationEventPump(task_runner, absolute) {}
+ ~DeviceOrientationEventPumpForTesting() override {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DeviceOrientationEventPumpForTesting);
+};
+
+class DeviceOrientationEventPumpTest : public testing::Test {
+ public:
+ DeviceOrientationEventPumpTest() = default;
+
+ protected:
+ void SetUp() override {
+ orientation_pump_.reset(new DeviceOrientationEventPumpForTesting(
+ base::ThreadTaskRunnerHandle::Get(), false /* absolute */));
+ device::mojom::SensorProviderPtrInfo sensor_provider_ptr_info;
+ sensor_provider_.Bind(mojo::MakeRequest(&sensor_provider_ptr_info));
+ orientation_pump_->SetSensorProviderForTesting(
+ device::mojom::blink::SensorProviderPtr(
+ device::mojom::blink::SensorProviderPtrInfo(
+ sensor_provider_ptr_info.PassHandle(),
+ device::mojom::SensorProvider::Version_)));
+
+ listener_.reset(new MockDeviceOrientationListener);
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED,
+ orientation_pump()->GetPumpStateForTesting());
+ }
+
+ void FireEvent() { orientation_pump_->FireEvent(nullptr); }
+
+ void ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState expected_sensor_state) {
+ EXPECT_EQ(expected_sensor_state,
+ orientation_pump_->relative_orientation_sensor_.sensor_state);
+ }
+
+ void ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState expected_sensor_state) {
+ EXPECT_EQ(expected_sensor_state,
+ orientation_pump_->absolute_orientation_sensor_.sensor_state);
+ }
+
+ DeviceOrientationEventPump* orientation_pump() {
+ return orientation_pump_.get();
+ }
+
+ MockDeviceOrientationListener* listener() { return listener_.get(); }
+
+ FakeSensorProvider* sensor_provider() { return &sensor_provider_; }
+
+ private:
+ std::unique_ptr<DeviceOrientationEventPumpForTesting> orientation_pump_;
+ std::unique_ptr<MockDeviceOrientationListener> listener_;
+ FakeSensorProvider sensor_provider_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceOrientationEventPumpTest);
+};
+
+TEST_F(DeviceOrientationEventPumpTest, MultipleStartAndStopWithWait) {
+ orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+ EXPECT_EQ(DeviceOrientationEventPump::PumpState::RUNNING,
+ orientation_pump()->GetPumpStateForTesting());
+
+ orientation_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+ EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED,
+ orientation_pump()->GetPumpStateForTesting());
+
+ orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+ EXPECT_EQ(DeviceOrientationEventPump::PumpState::RUNNING,
+ orientation_pump()->GetPumpStateForTesting());
+
+ orientation_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+ EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED,
+ orientation_pump()->GetPumpStateForTesting());
+}
+
+TEST_F(DeviceOrientationEventPumpTest,
+ MultipleStartAndStopWithWaitWithSensorFallback) {
+ sensor_provider()->set_relative_orientation_sensor_is_available(false);
+
+ orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+ EXPECT_EQ(DeviceOrientationEventPump::PumpState::RUNNING,
+ orientation_pump()->GetPumpStateForTesting());
+
+ orientation_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+ EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED,
+ orientation_pump()->GetPumpStateForTesting());
+
+ orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+ EXPECT_EQ(DeviceOrientationEventPump::PumpState::RUNNING,
+ orientation_pump()->GetPumpStateForTesting());
+
+ orientation_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+ EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED,
+ orientation_pump()->GetPumpStateForTesting());
+}
+
+TEST_F(DeviceOrientationEventPumpTest, CallStop) {
+ orientation_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+}
+
+TEST_F(DeviceOrientationEventPumpTest, CallStopWithSensorFallback) {
+ sensor_provider()->set_relative_orientation_sensor_is_available(false);
+
+ orientation_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+}
+
+TEST_F(DeviceOrientationEventPumpTest, CallStartAndStop) {
+ orientation_pump()->Start(nullptr, listener());
+ orientation_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceOrientationEventPumpTest, CallStartAndStopWithSensorFallback) {
+ sensor_provider()->set_relative_orientation_sensor_is_available(false);
+
+ orientation_pump()->Start(nullptr, listener());
+ orientation_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceOrientationEventPumpTest, CallStartMultipleTimes) {
+ orientation_pump()->Start(nullptr, listener());
+ orientation_pump()->Start(nullptr, listener());
+ orientation_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceOrientationEventPumpTest,
+ CallStartMultipleTimesWithSensorFallback) {
+ sensor_provider()->set_relative_orientation_sensor_is_available(false);
+
+ orientation_pump()->Start(nullptr, listener());
+ orientation_pump()->Start(nullptr, listener());
+ orientation_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceOrientationEventPumpTest, CallStopMultipleTimes) {
+ orientation_pump()->Start(nullptr, listener());
+ orientation_pump()->Stop();
+ orientation_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceOrientationEventPumpTest,
+ CallStopMultipleTimesWithSensorFallback) {
+ sensor_provider()->set_relative_orientation_sensor_is_available(false);
+
+ orientation_pump()->Start(nullptr, listener());
+ orientation_pump()->Stop();
+ orientation_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+// Test a sequence of Start(), Stop(), Start() calls only bind sensor once.
+TEST_F(DeviceOrientationEventPumpTest, SensorOnlyBindOnce) {
+ orientation_pump()->Start(nullptr, listener());
+ orientation_pump()->Stop();
+ orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+
+ orientation_pump()->Stop();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+// Test when using fallback from relative orientation to absolute orientation,
+// a sequence of Start(), Stop(), Start() calls only bind sensor once.
+TEST_F(DeviceOrientationEventPumpTest, SensorOnlyBindOnceWithSensorFallback) {
+ sensor_provider()->set_relative_orientation_sensor_is_available(false);
+
+ orientation_pump()->Start(nullptr, listener());
+ orientation_pump()->Stop();
+ orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+
+ orientation_pump()->Stop();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceOrientationEventPumpTest, SensorIsActive) {
+ orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+
+ sensor_provider()->UpdateRelativeOrientationSensorData(
+ 1 /* alpha */, 2 /* beta */, 3 /* gamma */);
+
+ FireEvent();
+
+ device::OrientationData received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_orientation());
+
+ // DeviceOrientation Event provides relative orientation data when it is
+ // available.
+ EXPECT_DOUBLE_EQ(1, received_data.alpha);
+ EXPECT_TRUE(received_data.has_alpha);
+ EXPECT_DOUBLE_EQ(2, received_data.beta);
+ EXPECT_TRUE(received_data.has_beta);
+ EXPECT_DOUBLE_EQ(3, received_data.gamma);
+ EXPECT_TRUE(received_data.has_gamma);
+ EXPECT_FALSE(received_data.absolute);
+
+ orientation_pump()->Stop();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceOrientationEventPumpTest, SensorIsActiveWithSensorFallback) {
+ sensor_provider()->set_relative_orientation_sensor_is_available(false);
+
+ orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+
+ sensor_provider()->UpdateAbsoluteOrientationSensorData(
+ 4 /* alpha */, 5 /* beta */, 6 /* gamma */);
+
+ FireEvent();
+
+ device::OrientationData received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_orientation());
+
+ // DeviceOrientation Event provides absolute orientation data when relative
+ // orientation data is not available but absolute orientation data is
+ // available.
+ EXPECT_DOUBLE_EQ(4, received_data.alpha);
+ EXPECT_TRUE(received_data.has_alpha);
+ EXPECT_DOUBLE_EQ(5, received_data.beta);
+ EXPECT_TRUE(received_data.has_beta);
+ EXPECT_DOUBLE_EQ(6, received_data.gamma);
+ EXPECT_TRUE(received_data.has_gamma);
+ // Since no relative orientation data is available, DeviceOrientationEvent
+ // fallback to provide absolute orientation data.
+ EXPECT_TRUE(received_data.absolute);
+
+ orientation_pump()->Stop();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceOrientationEventPumpTest, SomeSensorDataFieldsNotAvailable) {
+ orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+
+ sensor_provider()->UpdateRelativeOrientationSensorData(
+ NAN /* alpha */, 2 /* beta */, 3 /* gamma */);
+
+ FireEvent();
+
+ device::OrientationData received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_orientation());
+
+ EXPECT_FALSE(received_data.has_alpha);
+ EXPECT_DOUBLE_EQ(2, received_data.beta);
+ EXPECT_TRUE(received_data.has_beta);
+ EXPECT_DOUBLE_EQ(3, received_data.gamma);
+ EXPECT_TRUE(received_data.has_gamma);
+ EXPECT_FALSE(received_data.absolute);
+
+ orientation_pump()->Stop();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceOrientationEventPumpTest,
+ SomeSensorDataFieldsNotAvailableWithSensorFallback) {
+ sensor_provider()->set_relative_orientation_sensor_is_available(false);
+
+ orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+
+ sensor_provider()->UpdateAbsoluteOrientationSensorData(
+ 4 /* alpha */, NAN /* beta */, 6 /* gamma */);
+
+ FireEvent();
+
+ device::OrientationData received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_orientation());
+
+ // DeviceOrientation Event provides absolute orientation data when relative
+ // orientation data is not available but absolute orientation data is
+ // available.
+ EXPECT_DOUBLE_EQ(4, received_data.alpha);
+ EXPECT_TRUE(received_data.has_alpha);
+ EXPECT_FALSE(received_data.has_beta);
+ EXPECT_DOUBLE_EQ(6, received_data.gamma);
+ EXPECT_TRUE(received_data.has_gamma);
+ // Since no relative orientation data is available, DeviceOrientationEvent
+ // fallback to provide absolute orientation data.
+ EXPECT_TRUE(received_data.absolute);
+
+ orientation_pump()->Stop();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceOrientationEventPumpTest, FireAllNullEvent) {
+ // No active sensors.
+ sensor_provider()->set_relative_orientation_sensor_is_available(false);
+ sensor_provider()->set_absolute_orientation_sensor_is_available(false);
+
+ orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+
+ FireEvent();
+
+ device::OrientationData received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_orientation());
+
+ EXPECT_FALSE(received_data.has_alpha);
+ EXPECT_FALSE(received_data.has_beta);
+ EXPECT_FALSE(received_data.has_gamma);
+ EXPECT_FALSE(received_data.absolute);
+
+ orientation_pump()->Stop();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+}
+
+TEST_F(DeviceOrientationEventPumpTest,
+ NotFireEventWhenSensorReadingTimeStampIsZero) {
+ orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+
+ FireEvent();
+
+ EXPECT_FALSE(listener()->did_change_device_orientation());
+
+ orientation_pump()->Stop();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceOrientationEventPumpTest,
+ NotFireEventWhenSensorReadingTimeStampIsZeroWithSensorFallback) {
+ sensor_provider()->set_relative_orientation_sensor_is_available(false);
+
+ orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+
+ FireEvent();
+
+ EXPECT_FALSE(listener()->did_change_device_orientation());
+
+ orientation_pump()->Stop();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceOrientationEventPumpTest, UpdateRespectsOrientationThreshold) {
+ orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+
+ sensor_provider()->UpdateRelativeOrientationSensorData(
+ 1 /* alpha */, 2 /* beta */, 3 /* gamma */);
+
+ FireEvent();
+
+ device::OrientationData received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_orientation());
+
+ // DeviceOrientation Event provides relative orientation data when it is
+ // available.
+ EXPECT_DOUBLE_EQ(1, received_data.alpha);
+ EXPECT_TRUE(received_data.has_alpha);
+ EXPECT_DOUBLE_EQ(2, received_data.beta);
+ EXPECT_TRUE(received_data.has_beta);
+ EXPECT_DOUBLE_EQ(3, received_data.gamma);
+ EXPECT_TRUE(received_data.has_gamma);
+ EXPECT_FALSE(received_data.absolute);
+
+ listener()->set_did_change_device_orientation(false);
+
+ sensor_provider()->UpdateRelativeOrientationSensorData(
+ 1 + DeviceOrientationEventPump::kOrientationThreshold / 2.0 /* alpha */,
+ 2 /* beta */, 3 /* gamma */);
+
+ FireEvent();
+
+ received_data = listener()->data();
+ EXPECT_FALSE(listener()->did_change_device_orientation());
+
+ EXPECT_DOUBLE_EQ(1, received_data.alpha);
+ EXPECT_TRUE(received_data.has_alpha);
+ EXPECT_DOUBLE_EQ(2, received_data.beta);
+ EXPECT_TRUE(received_data.has_beta);
+ EXPECT_DOUBLE_EQ(3, received_data.gamma);
+ EXPECT_TRUE(received_data.has_gamma);
+ EXPECT_FALSE(received_data.absolute);
+
+ listener()->set_did_change_device_orientation(false);
+
+ sensor_provider()->UpdateRelativeOrientationSensorData(
+ 1 + DeviceOrientationEventPump::kOrientationThreshold /* alpha */,
+ 2 /* beta */, 3 /* gamma */);
+
+ FireEvent();
+
+ received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_orientation());
+
+ EXPECT_DOUBLE_EQ(1 + DeviceOrientationEventPump::kOrientationThreshold,
+ received_data.alpha);
+ EXPECT_TRUE(received_data.has_alpha);
+ EXPECT_DOUBLE_EQ(2, received_data.beta);
+ EXPECT_TRUE(received_data.has_beta);
+ EXPECT_DOUBLE_EQ(3, received_data.gamma);
+ EXPECT_TRUE(received_data.has_gamma);
+ EXPECT_FALSE(received_data.absolute);
+
+ orientation_pump()->Stop();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceOrientationEventPumpTest,
+ UpdateRespectsOrientationThresholdWithSensorFallback) {
+ sensor_provider()->set_relative_orientation_sensor_is_available(false);
+
+ orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+
+ sensor_provider()->UpdateAbsoluteOrientationSensorData(
+ 4 /* alpha */, 5 /* beta */, 6 /* gamma */);
+
+ FireEvent();
+
+ device::OrientationData received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_orientation());
+
+ // DeviceOrientation Event provides absolute orientation data when relative
+ // orientation data is not available but absolute orientation data is
+ // available.
+ EXPECT_DOUBLE_EQ(4, received_data.alpha);
+ EXPECT_TRUE(received_data.has_alpha);
+ EXPECT_DOUBLE_EQ(5, received_data.beta);
+ EXPECT_TRUE(received_data.has_beta);
+ EXPECT_DOUBLE_EQ(6, received_data.gamma);
+ EXPECT_TRUE(received_data.has_gamma);
+ // Since no relative orientation data is available, DeviceOrientationEvent
+ // fallback to provide absolute orientation data.
+ EXPECT_TRUE(received_data.absolute);
+
+ listener()->set_did_change_device_orientation(false);
+
+ sensor_provider()->UpdateAbsoluteOrientationSensorData(
+ 4 /* alpha */,
+ 5 + DeviceOrientationEventPump::kOrientationThreshold / 2.0 /* beta */,
+ 6 /* gamma */);
+
+ FireEvent();
+
+ received_data = listener()->data();
+ EXPECT_FALSE(listener()->did_change_device_orientation());
+
+ EXPECT_DOUBLE_EQ(4, received_data.alpha);
+ EXPECT_TRUE(received_data.has_alpha);
+ EXPECT_DOUBLE_EQ(5, received_data.beta);
+ EXPECT_TRUE(received_data.has_beta);
+ EXPECT_DOUBLE_EQ(6, received_data.gamma);
+ EXPECT_TRUE(received_data.has_gamma);
+ EXPECT_TRUE(received_data.absolute);
+
+ listener()->set_did_change_device_orientation(false);
+
+ sensor_provider()->UpdateAbsoluteOrientationSensorData(
+ 4 /* alpha */,
+ 5 + DeviceOrientationEventPump::kOrientationThreshold +
+ kEpsilon /* beta */,
+ 6 /* gamma */);
+
+ FireEvent();
+
+ received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_orientation());
+
+ EXPECT_DOUBLE_EQ(4, received_data.alpha);
+ EXPECT_TRUE(received_data.has_alpha);
+ EXPECT_DOUBLE_EQ(
+ 5 + DeviceOrientationEventPump::kOrientationThreshold + kEpsilon,
+ received_data.beta);
+ EXPECT_TRUE(received_data.has_beta);
+ EXPECT_DOUBLE_EQ(6, received_data.gamma);
+ EXPECT_TRUE(received_data.has_gamma);
+ EXPECT_TRUE(received_data.absolute);
+
+ orientation_pump()->Stop();
+
+ ExpectRelativeOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+class DeviceAbsoluteOrientationEventPumpTest : public testing::Test {
+ public:
+ DeviceAbsoluteOrientationEventPumpTest() = default;
+
+ protected:
+ void SetUp() override {
+ absolute_orientation_pump_.reset(new DeviceOrientationEventPumpForTesting(
+ base::ThreadTaskRunnerHandle::Get(), true /* absolute */));
+ device::mojom::SensorProviderPtrInfo sensor_provider_ptr_info;
+ sensor_provider_.Bind(mojo::MakeRequest(&sensor_provider_ptr_info));
+ absolute_orientation_pump_->SetSensorProviderForTesting(
+ device::mojom::blink::SensorProviderPtr(
+ device::mojom::blink::SensorProviderPtrInfo(
+ sensor_provider_ptr_info.PassHandle(),
+ device::mojom::SensorProvider::Version_)));
+ listener_.reset(new MockDeviceOrientationListener);
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+ EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED,
+ absolute_orientation_pump()->GetPumpStateForTesting());
+ }
+
+ void FireEvent() { absolute_orientation_pump_->FireEvent(nullptr); }
+
+ void ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState expected_sensor_state) {
+ EXPECT_EQ(
+ expected_sensor_state,
+ absolute_orientation_pump_->absolute_orientation_sensor_.sensor_state);
+ }
+
+ DeviceOrientationEventPump* absolute_orientation_pump() {
+ return absolute_orientation_pump_.get();
+ }
+
+ MockDeviceOrientationListener* listener() { return listener_.get(); }
+
+ FakeSensorProvider* sensor_provider() { return &sensor_provider_; }
+
+ private:
+ std::unique_ptr<DeviceOrientationEventPumpForTesting>
+ absolute_orientation_pump_;
+ std::unique_ptr<MockDeviceOrientationListener> listener_;
+ FakeSensorProvider sensor_provider_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceAbsoluteOrientationEventPumpTest);
+};
+
+TEST_F(DeviceAbsoluteOrientationEventPumpTest, MultipleStartAndStopWithWait) {
+ absolute_orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+ EXPECT_EQ(DeviceOrientationEventPump::PumpState::RUNNING,
+ absolute_orientation_pump()->GetPumpStateForTesting());
+
+ absolute_orientation_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+ EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED,
+ absolute_orientation_pump()->GetPumpStateForTesting());
+
+ absolute_orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+ EXPECT_EQ(DeviceOrientationEventPump::PumpState::RUNNING,
+ absolute_orientation_pump()->GetPumpStateForTesting());
+
+ absolute_orientation_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+ EXPECT_EQ(DeviceOrientationEventPump::PumpState::STOPPED,
+ absolute_orientation_pump()->GetPumpStateForTesting());
+}
+
+TEST_F(DeviceAbsoluteOrientationEventPumpTest, CallStop) {
+ absolute_orientation_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+}
+
+TEST_F(DeviceAbsoluteOrientationEventPumpTest, CallStartAndStop) {
+ absolute_orientation_pump()->Start(nullptr, listener());
+ absolute_orientation_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceAbsoluteOrientationEventPumpTest, CallStartMultipleTimes) {
+ absolute_orientation_pump()->Start(nullptr, listener());
+ absolute_orientation_pump()->Start(nullptr, listener());
+ absolute_orientation_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceAbsoluteOrientationEventPumpTest, CallStopMultipleTimes) {
+ absolute_orientation_pump()->Start(nullptr, listener());
+ absolute_orientation_pump()->Stop();
+ absolute_orientation_pump()->Stop();
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+// Test multiple DeviceSensorEventPump::Start() calls only bind sensor once.
+TEST_F(DeviceAbsoluteOrientationEventPumpTest, SensorOnlyBindOnce) {
+ absolute_orientation_pump()->Start(nullptr, listener());
+ absolute_orientation_pump()->Stop();
+ absolute_orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+
+ absolute_orientation_pump()->Stop();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceAbsoluteOrientationEventPumpTest, SensorIsActive) {
+ absolute_orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+
+ sensor_provider()->UpdateAbsoluteOrientationSensorData(
+ 4 /* alpha */, 5 /* beta */, 6 /* gamma */);
+
+ FireEvent();
+
+ device::OrientationData received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_orientation());
+
+ EXPECT_DOUBLE_EQ(4, received_data.alpha);
+ EXPECT_TRUE(received_data.has_alpha);
+ EXPECT_DOUBLE_EQ(5, received_data.beta);
+ EXPECT_TRUE(received_data.has_beta);
+ EXPECT_DOUBLE_EQ(6, received_data.gamma);
+ EXPECT_TRUE(received_data.has_gamma);
+ EXPECT_TRUE(received_data.absolute);
+
+ absolute_orientation_pump()->Stop();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceAbsoluteOrientationEventPumpTest,
+ SomeSensorDataFieldsNotAvailable) {
+ absolute_orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+
+ sensor_provider()->UpdateAbsoluteOrientationSensorData(
+ 4 /* alpha */, NAN /* beta */, 6 /* gamma */);
+
+ FireEvent();
+
+ device::OrientationData received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_orientation());
+
+ EXPECT_DOUBLE_EQ(4, received_data.alpha);
+ EXPECT_TRUE(received_data.has_alpha);
+ EXPECT_FALSE(received_data.has_beta);
+ EXPECT_DOUBLE_EQ(6, received_data.gamma);
+ EXPECT_TRUE(received_data.has_gamma);
+ EXPECT_TRUE(received_data.absolute);
+
+ absolute_orientation_pump()->Stop();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceAbsoluteOrientationEventPumpTest, FireAllNullEvent) {
+ // No active sensor.
+ sensor_provider()->set_absolute_orientation_sensor_is_available(false);
+
+ absolute_orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+
+ FireEvent();
+
+ device::OrientationData received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_orientation());
+
+ EXPECT_FALSE(received_data.has_alpha);
+ EXPECT_FALSE(received_data.has_beta);
+ EXPECT_FALSE(received_data.has_gamma);
+ EXPECT_TRUE(received_data.absolute);
+
+ absolute_orientation_pump()->Stop();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::NOT_INITIALIZED);
+}
+
+TEST_F(DeviceAbsoluteOrientationEventPumpTest,
+ NotFireEventWhenSensorReadingTimeStampIsZero) {
+ absolute_orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+
+ FireEvent();
+
+ EXPECT_FALSE(listener()->did_change_device_orientation());
+
+ absolute_orientation_pump()->Stop();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+TEST_F(DeviceAbsoluteOrientationEventPumpTest,
+ UpdateRespectsOrientationThreshold) {
+ absolute_orientation_pump()->Start(nullptr, listener());
+ base::RunLoop().RunUntilIdle();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::ACTIVE);
+
+ sensor_provider()->UpdateAbsoluteOrientationSensorData(
+ 4 /* alpha */, 5 /* beta */, 6 /* gamma */);
+
+ FireEvent();
+
+ device::OrientationData received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_orientation());
+
+ EXPECT_DOUBLE_EQ(4, received_data.alpha);
+ EXPECT_TRUE(received_data.has_alpha);
+ EXPECT_DOUBLE_EQ(5, received_data.beta);
+ EXPECT_TRUE(received_data.has_beta);
+ EXPECT_DOUBLE_EQ(6, received_data.gamma);
+ EXPECT_TRUE(received_data.has_gamma);
+ EXPECT_TRUE(received_data.absolute);
+
+ listener()->set_did_change_device_orientation(false);
+
+ sensor_provider()->UpdateAbsoluteOrientationSensorData(
+ 4 /* alpha */,
+ 5 + DeviceOrientationEventPump::kOrientationThreshold / 2.0 /* beta */,
+ 6 /* gamma */);
+
+ FireEvent();
+
+ received_data = listener()->data();
+ EXPECT_FALSE(listener()->did_change_device_orientation());
+
+ EXPECT_DOUBLE_EQ(4, received_data.alpha);
+ EXPECT_TRUE(received_data.has_alpha);
+ EXPECT_DOUBLE_EQ(5, received_data.beta);
+ EXPECT_TRUE(received_data.has_beta);
+ EXPECT_DOUBLE_EQ(6, received_data.gamma);
+ EXPECT_TRUE(received_data.has_gamma);
+ EXPECT_TRUE(received_data.absolute);
+
+ listener()->set_did_change_device_orientation(false);
+
+ sensor_provider()->UpdateAbsoluteOrientationSensorData(
+ 4 /* alpha */,
+ 5 + DeviceOrientationEventPump::kOrientationThreshold +
+ kEpsilon /* beta */,
+ 6 /* gamma */);
+
+ FireEvent();
+
+ received_data = listener()->data();
+ EXPECT_TRUE(listener()->did_change_device_orientation());
+
+ EXPECT_DOUBLE_EQ(4, received_data.alpha);
+ EXPECT_TRUE(received_data.has_alpha);
+ EXPECT_DOUBLE_EQ(
+ 5 + DeviceOrientationEventPump::kOrientationThreshold + kEpsilon,
+ received_data.beta);
+ EXPECT_TRUE(received_data.has_beta);
+ EXPECT_DOUBLE_EQ(6, received_data.gamma);
+ EXPECT_TRUE(received_data.has_gamma);
+ EXPECT_TRUE(received_data.absolute);
+
+ absolute_orientation_pump()->Stop();
+
+ ExpectAbsoluteOrientationSensorStateToBe(
+ DeviceOrientationEventPump::SensorState::SUSPENDED);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h b/chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h
new file mode 100644
index 00000000000..bf83aeb8c40
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/device_orientation/device_sensor_event_pump.h
@@ -0,0 +1,344 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_SENSOR_EVENT_PUMP_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_SENSOR_EVENT_PUMP_H_
+
+#include <algorithm>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "mojo/public/cpp/bindings/binding.h"
+#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
+#include "services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h"
+#include "services/device/public/mojom/sensor_provider.mojom-blink.h"
+#include "third_party/blink/public/platform/modules/device_orientation/web_device_motion_listener.h"
+#include "third_party/blink/public/platform/modules/device_orientation/web_device_orientation_listener.h"
+#include "third_party/blink/renderer/platform/timer.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+
+namespace blink {
+
+class LocalFrame;
+
+template <typename ListenerType>
+class DeviceSensorEventPump {
+ public:
+ // Default rate for firing events.
+ static constexpr int kDefaultPumpFrequencyHz = 60;
+ static constexpr int kDefaultPumpDelayMicroseconds =
+ WTF::Time::kMicrosecondsPerSecond / kDefaultPumpFrequencyHz;
+
+ // The pump is a tri-state automaton with allowed transitions as follows:
+ // STOPPED -> PENDING_START
+ // PENDING_START -> RUNNING
+ // PENDING_START -> STOPPED
+ // RUNNING -> STOPPED
+ enum class PumpState { STOPPED, RUNNING, PENDING_START };
+
+ // The sensor state is an automaton with allowed transitions as follows:
+ // NOT_INITIALIZED -> INITIALIZING
+ // INITIALIZING -> ACTIVE
+ // INITIALIZING -> SHOULD_SUSPEND
+ // ACTIVE -> SUSPENDED
+ // SHOULD_SUSPEND -> INITIALIZING
+ // SHOULD_SUSPEND -> SUSPENDED
+ // SUSPENDED -> ACTIVE
+ // { INITIALIZING, ACTIVE, SHOULD_SUSPEND, SUSPENDED } -> NOT_INITIALIZED
+ enum class SensorState {
+ NOT_INITIALIZED,
+ INITIALIZING,
+ ACTIVE,
+ SHOULD_SUSPEND,
+ SUSPENDED
+ };
+
+ virtual void Start(LocalFrame* frame,
+ blink::WebPlatformEventListener* listener) {
+ DVLOG(2) << "requested start";
+
+ if (state_ != PumpState::STOPPED)
+ return;
+
+ DCHECK(!timer_.IsActive());
+
+ state_ = PumpState::PENDING_START;
+
+ DCHECK(!is_observing_);
+ listener_ = static_cast<ListenerType*>(listener);
+ is_observing_ = true;
+
+ SendStartMessage(frame);
+ }
+
+ virtual void Stop() {
+ DVLOG(2) << "requested stop";
+
+ if (state_ == PumpState::STOPPED)
+ return;
+
+ DCHECK((state_ == PumpState::PENDING_START && !timer_.IsActive()) ||
+ (state_ == PumpState::RUNNING && timer_.IsActive()));
+
+ if (timer_.IsActive())
+ timer_.Stop();
+
+ DCHECK(is_observing_);
+ listener_ = nullptr;
+ is_observing_ = false;
+
+ SendStopMessage();
+
+ state_ = PumpState::STOPPED;
+ }
+
+ void HandleSensorProviderError() { sensor_provider_.reset(); }
+
+ void SetSensorProviderForTesting(
+ device::mojom::blink::SensorProviderPtr sensor_provider) {
+ sensor_provider_ = std::move(sensor_provider);
+ }
+
+ PumpState GetPumpStateForTesting() { return state_; }
+
+ protected:
+ explicit DeviceSensorEventPump(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : state_(PumpState::STOPPED),
+ timer_(task_runner, this, &DeviceSensorEventPump::FireEvent) {}
+
+ virtual ~DeviceSensorEventPump() { DCHECK(!is_observing_); }
+
+ // This method is expected to send an IPC to the browser process to let it
+ // know that it should start observing.
+ // It is expected for subclasses to override it.
+ virtual void SendStartMessage(LocalFrame*) = 0;
+
+ // This method is expected to send an IPC to the browser process to let it
+ // know that it should start observing.
+ // It is expected for subclasses to override it.
+ virtual void SendStopMessage() = 0;
+
+ // Implementations of DeviceSensorEventPump must call StopIfObserving()
+ // from their destructor to shutdown in an orderly manner.
+ // (As Stop() calls a virtual method, it cannot be handled by
+ // ~DeviceSensorEventPump.)
+ void StopIfObserving() {
+ if (is_observing_)
+ Stop();
+ }
+
+ // Even though the TimerBase* parameter is not used, it is required by
+ // TaskRunnerTimer class
+ virtual void FireEvent(TimerBase*) = 0;
+
+ ListenerType* listener() { return listener_; }
+
+ struct SensorEntry : public device::mojom::blink::SensorClient {
+ SensorEntry(DeviceSensorEventPump* pump,
+ device::mojom::blink::SensorType sensor_type)
+ : event_pump(pump),
+ sensor_state(SensorState::NOT_INITIALIZED),
+ type(sensor_type),
+ client_binding(this) {}
+
+ ~SensorEntry() override {}
+
+ // device::mojom::SensorClient:
+ void RaiseError() override { HandleSensorError(); }
+
+ // device::mojom::SensorClient:
+ void SensorReadingChanged() override {
+ // Since DeviceSensorEventPump::FireEvent is called in a fixed
+ // frequency, the |shared_buffer| is read frequently, and
+ // Sensor::ConfigureReadingChangeNotifications() is set to false,
+ // so this method is not called and doesn't need to be implemented.
+ NOTREACHED();
+ }
+
+ // Mojo callback for SensorProvider::GetSensor().
+ void OnSensorCreated(device::mojom::blink::SensorCreationResult result,
+ device::mojom::blink::SensorInitParamsPtr params) {
+ // |sensor_state| can be SensorState::SHOULD_SUSPEND if Stop() is called
+ // before OnSensorCreated() is called.
+ DCHECK(sensor_state == SensorState::INITIALIZING ||
+ sensor_state == SensorState::SHOULD_SUSPEND);
+
+ if (!params) {
+ HandleSensorError();
+ event_pump->DidStartIfPossible();
+ return;
+ }
+ DCHECK_EQ(device::mojom::SensorCreationResult::SUCCESS, result);
+
+ constexpr size_t kReadBufferSize =
+ sizeof(device::SensorReadingSharedBuffer);
+
+ DCHECK_EQ(0u, params->buffer_offset % kReadBufferSize);
+
+ mode = params->mode;
+ default_config = std::move(params->default_configuration);
+
+ sensor.Bind(std::move(params->sensor));
+ client_binding.Bind(std::move(params->client_request));
+
+ shared_buffer_handle = std::move(params->memory);
+ DCHECK(!shared_buffer);
+ shared_buffer = shared_buffer_handle->MapAtOffset(kReadBufferSize,
+ params->buffer_offset);
+ if (!shared_buffer) {
+ HandleSensorError();
+ event_pump->DidStartIfPossible();
+ return;
+ }
+
+ const device::SensorReadingSharedBuffer* buffer =
+ static_cast<const device::SensorReadingSharedBuffer*>(
+ shared_buffer.get());
+ shared_buffer_reader.reset(
+ new device::SensorReadingSharedBufferReader(buffer));
+
+ default_config->frequency =
+ std::min(static_cast<double>(kDefaultPumpFrequencyHz),
+ params->maximum_frequency);
+
+ sensor.set_connection_error_handler(
+ WTF::Bind(&SensorEntry::HandleSensorError, WTF::Unretained(this)));
+ sensor->ConfigureReadingChangeNotifications(false /* disabled */);
+ sensor->AddConfiguration(std::move(default_config),
+ WTF::Bind(&SensorEntry::OnSensorAddConfiguration,
+ WTF::Unretained(this)));
+ }
+
+ // Mojo callback for Sensor::AddConfiguration().
+ void OnSensorAddConfiguration(bool success) {
+ if (!success)
+ HandleSensorError();
+
+ if (sensor_state == SensorState::INITIALIZING) {
+ sensor_state = SensorState::ACTIVE;
+ event_pump->DidStartIfPossible();
+ } else if (sensor_state == SensorState::SHOULD_SUSPEND) {
+ sensor->Suspend();
+ sensor_state = SensorState::SUSPENDED;
+ }
+ }
+
+ void HandleSensorError() {
+ sensor.reset();
+ sensor_state = SensorState::NOT_INITIALIZED;
+ shared_buffer_handle.reset();
+ shared_buffer.reset();
+ client_binding.Close();
+ }
+
+ bool SensorReadingCouldBeRead() {
+ if (!sensor)
+ return false;
+
+ DCHECK(shared_buffer);
+
+ if (!shared_buffer_handle->is_valid() ||
+ !shared_buffer_reader->GetReading(&reading)) {
+ HandleSensorError();
+ return false;
+ }
+
+ return true;
+ }
+
+ bool ReadyOrErrored() const {
+ // When some sensors are not available, the pump still needs to fire
+ // events which set the unavailable sensor data fields to null.
+ return sensor_state == SensorState::ACTIVE ||
+ sensor_state == SensorState::NOT_INITIALIZED;
+ }
+
+ void Start(device::mojom::blink::SensorProvider* sensor_provider) {
+ if (sensor_state == SensorState::NOT_INITIALIZED) {
+ sensor_state = SensorState::INITIALIZING;
+ sensor_provider->GetSensor(
+ type,
+ WTF::Bind(&SensorEntry::OnSensorCreated, WTF::Unretained(this)));
+ } else if (sensor_state == SensorState::SUSPENDED) {
+ sensor->Resume();
+ sensor_state = SensorState::ACTIVE;
+ event_pump->DidStartIfPossible();
+ } else if (sensor_state == SensorState::SHOULD_SUSPEND) {
+ // This can happen when calling Start(), Stop(), Start() in a sequence:
+ // After the first Start() call, the sensor state is
+ // SensorState::INITIALIZING. Then after the Stop() call, the sensor
+ // state is SensorState::SHOULD_SUSPEND, and the next Start() call needs
+ // to set the sensor state to be SensorState::INITIALIZING again.
+ sensor_state = SensorState::INITIALIZING;
+ } else {
+ NOTREACHED();
+ }
+ }
+
+ void Stop() {
+ if (sensor) {
+ sensor->Suspend();
+ sensor_state = SensorState::SUSPENDED;
+ } else if (sensor_state == SensorState::INITIALIZING) {
+ // When the sensor needs to be suspended, and it is still in the
+ // SensorState::INITIALIZING state, the sensor creation is not affected
+ // (the SensorEntry::OnSensorCreated() callback will run as usual), but
+ // the sensor is marked as SensorState::SHOULD_SUSPEND, and when the
+ // sensor is created successfully, it will be suspended and its state
+ // will be marked as SensorState::SUSPENDED in the
+ // SensorEntry::OnSensorAddConfiguration().
+ sensor_state = SensorState::SHOULD_SUSPEND;
+ }
+ }
+
+ DeviceSensorEventPump* event_pump;
+ device::mojom::blink::SensorPtr sensor;
+ SensorState sensor_state;
+ device::mojom::blink::SensorType type;
+ device::mojom::blink::ReportingMode mode;
+ device::mojom::blink::SensorConfigurationPtr default_config;
+ mojo::ScopedSharedBufferHandle shared_buffer_handle;
+ mojo::ScopedSharedBufferMapping shared_buffer;
+ std::unique_ptr<device::SensorReadingSharedBufferReader>
+ shared_buffer_reader;
+ device::SensorReading reading;
+ mojo::Binding<device::mojom::blink::SensorClient> client_binding;
+ };
+
+ friend struct SensorEntry;
+
+ virtual void DidStartIfPossible() {
+ DVLOG(2) << "did start sensor event pump";
+
+ if (state_ != PumpState::PENDING_START)
+ return;
+
+ if (!SensorsReadyOrErrored())
+ return;
+
+ DCHECK(!timer_.IsActive());
+
+ timer_.StartRepeating(
+ WTF::TimeDelta::FromMicroseconds(kDefaultPumpDelayMicroseconds),
+ FROM_HERE);
+ state_ = PumpState::RUNNING;
+ }
+
+ device::mojom::blink::SensorProviderPtr sensor_provider_;
+
+ private:
+ virtual bool SensorsReadyOrErrored() const = 0;
+
+ PumpState state_;
+ bool is_observing_ = false;
+ ListenerType* listener_ = nullptr;
+ TaskRunnerTimer<DeviceSensorEventPump> timer_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceSensorEventPump);
+};
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_DEVICE_ORIENTATION_DEVICE_SENSOR_EVENT_PUMP_H_
diff --git a/chromium/third_party/blink/renderer/modules/document_metadata/copyless_paste_extractor.cc b/chromium/third_party/blink/renderer/modules/document_metadata/copyless_paste_extractor.cc
index 8c6897f2b72..2f8f53f7a33 100644
--- a/chromium/third_party/blink/renderer/modules/document_metadata/copyless_paste_extractor.cc
+++ b/chromium/third_party/blink/renderer/modules/document_metadata/copyless_paste_extractor.cc
@@ -9,6 +9,7 @@
#include <utility>
#include "third_party/blink/public/platform/modules/document_metadata/copyless_paste.mojom-blink.h"
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element_traversal.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/html_element.h"
@@ -16,6 +17,7 @@
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/json/json_parser.h"
+#include "third_party/blink/renderer/platform/json/json_values.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -294,9 +296,9 @@ WebPagePtr CopylessPasteExtractor::extract(const Document& document) {
WebPagePtr page = WebPage::New();
// Traverse the DOM tree and extract the metadata.
- double start_time = CurrentTimeTicksInSeconds();
+ TimeTicks start_time = CurrentTimeTicks();
ExtractionStatus status = extractMetadata(*html, page->entities);
- double elapsed_time = CurrentTimeTicksInSeconds() - start_time;
+ TimeDelta elapsed_time = CurrentTimeTicks() - start_time;
DEFINE_STATIC_LOCAL(EnumerationHistogram, status_histogram,
("CopylessPaste.ExtractionStatus", kCount));
@@ -306,12 +308,12 @@ WebPagePtr CopylessPasteExtractor::extract(const Document& document) {
DEFINE_STATIC_LOCAL(
CustomCountHistogram, extractionHistogram,
("CopylessPaste.ExtractionFailedUs", 1, 1000 * 1000, 50));
- extractionHistogram.Count(1e6 * elapsed_time);
+ extractionHistogram.CountMicroseconds(elapsed_time);
return nullptr;
}
DEFINE_STATIC_LOCAL(CustomCountHistogram, extractionHistogram,
("CopylessPaste.ExtractionUs", 1, 1000 * 1000, 50));
- extractionHistogram.Count(1e6 * elapsed_time);
+ extractionHistogram.CountMicroseconds(elapsed_time);
page->url = document.Url();
page->title = document.title();
diff --git a/chromium/third_party/blink/renderer/modules/encoding/text_decoder.cc b/chromium/third_party/blink/renderer/modules/encoding/text_decoder.cc
index eac3024068a..ac02608357b 100644
--- a/chromium/third_party/blink/renderer/modules/encoding/text_decoder.cc
+++ b/chromium/third_party/blink/renderer/modules/encoding/text_decoder.cc
@@ -30,10 +30,10 @@
#include "third_party/blink/renderer/modules/encoding/text_decoder.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
#include "third_party/blink/renderer/modules/encoding/encoding.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/string_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding_registry.h"
@@ -98,7 +98,8 @@ String TextDecoder::decode(const char* start,
const TextDecodeOptions& options,
ExceptionState& exception_state) {
WTF::FlushBehavior flush =
- options.stream() ? WTF::kDoNotFlush : WTF::kDataEOF;
+ options.stream() ? WTF::FlushBehavior::kDoNotFlush
+ : WTF::FlushBehavior::kDataEOF;
bool saw_error = false;
String s = codec_->Decode(start, length, flush, fatal_, saw_error);
@@ -116,7 +117,7 @@ String TextDecoder::decode(const char* start,
s.Remove(0);
}
- if (flush)
+ if (flush != WTF::FlushBehavior::kDoNotFlush)
bom_seen_ = false;
return s;
diff --git a/chromium/third_party/blink/renderer/modules/encoding/text_encoder.cc b/chromium/third_party/blink/renderer/modules/encoding/text_encoder.cc
index ba9e8d2e4a0..81726d58ca0 100644
--- a/chromium/third_party/blink/renderer/modules/encoding/text_encoder.cc
+++ b/chromium/third_party/blink/renderer/modules/encoding/text_encoder.cc
@@ -30,9 +30,9 @@
#include "third_party/blink/renderer/modules/encoding/text_encoder.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/encoding/encoding.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/cstring.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding_registry.h"
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/content_decryption_module_result_promise.cc b/chromium/third_party/blink/renderer/modules/encryptedmedia/content_decryption_module_result_promise.cc
index b5be7df3158..d1594640ff1 100644
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/content_decryption_module_result_promise.cc
+++ b/chromium/third_party/blink/renderer/modules/encryptedmedia/content_decryption_module_result_promise.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.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/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -19,24 +20,28 @@ ExceptionCode WebCdmExceptionToExceptionCode(
WebContentDecryptionModuleException cdm_exception) {
switch (cdm_exception) {
case kWebContentDecryptionModuleExceptionTypeError:
- return kV8TypeError;
+ return ToExceptionCode(ESErrorType::kTypeError);
case kWebContentDecryptionModuleExceptionNotSupportedError:
- return kNotSupportedError;
+ return ToExceptionCode(DOMExceptionCode::kNotSupportedError);
case kWebContentDecryptionModuleExceptionInvalidStateError:
- return kInvalidStateError;
+ return ToExceptionCode(DOMExceptionCode::kInvalidStateError);
case kWebContentDecryptionModuleExceptionQuotaExceededError:
- return kQuotaExceededError;
+ return ToExceptionCode(DOMExceptionCode::kQuotaExceededError);
case kWebContentDecryptionModuleExceptionUnknownError:
- return kUnknownError;
+ return ToExceptionCode(DOMExceptionCode::kUnknownError);
}
NOTREACHED();
- return kUnknownError;
+ return ToExceptionCode(DOMExceptionCode::kUnknownError);
}
ContentDecryptionModuleResultPromise::ContentDecryptionModuleResultPromise(
- ScriptState* script_state)
- : resolver_(ScriptPromiseResolver::Create(script_state)) {}
+ ScriptState* script_state,
+ const char* interface_name,
+ const char* property_name)
+ : resolver_(ScriptPromiseResolver::Create(script_state)),
+ interface_name_(interface_name),
+ property_name_(property_name) {}
ContentDecryptionModuleResultPromise::~ContentDecryptionModuleResultPromise() =
default;
@@ -45,7 +50,8 @@ void ContentDecryptionModuleResultPromise::Complete() {
NOTREACHED();
if (!IsValidToFulfillPromise())
return;
- Reject(kInvalidStateError, "Unexpected completion.");
+ Reject(ToExceptionCode(DOMExceptionCode::kInvalidStateError),
+ "Unexpected completion.");
}
void ContentDecryptionModuleResultPromise::CompleteWithContentDecryptionModule(
@@ -53,7 +59,8 @@ void ContentDecryptionModuleResultPromise::CompleteWithContentDecryptionModule(
NOTREACHED();
if (!IsValidToFulfillPromise())
return;
- Reject(kInvalidStateError, "Unexpected completion.");
+ Reject(ToExceptionCode(DOMExceptionCode::kInvalidStateError),
+ "Unexpected completion.");
}
void ContentDecryptionModuleResultPromise::CompleteWithSession(
@@ -61,14 +68,16 @@ void ContentDecryptionModuleResultPromise::CompleteWithSession(
NOTREACHED();
if (!IsValidToFulfillPromise())
return;
- Reject(kInvalidStateError, "Unexpected completion.");
+ Reject(ToExceptionCode(DOMExceptionCode::kInvalidStateError),
+ "Unexpected completion.");
}
void ContentDecryptionModuleResultPromise::CompleteWithKeyStatus(
WebEncryptedMediaKeyInformation::KeyStatus) {
if (!IsValidToFulfillPromise())
return;
- Reject(kInvalidStateError, "Unexpected completion.");
+ Reject(ToExceptionCode(DOMExceptionCode::kInvalidStateError),
+ "Unexpected completion.");
}
void ContentDecryptionModuleResultPromise::CompleteWithError(
@@ -102,9 +111,12 @@ void ContentDecryptionModuleResultPromise::Reject(ExceptionCode code,
DCHECK(IsValidToFulfillPromise());
ScriptState::Scope scope(resolver_->GetScriptState());
- v8::Isolate* isolate = resolver_->GetScriptState()->GetIsolate();
- resolver_->Reject(
- V8ThrowDOMException::CreateDOMException(isolate, code, error_message));
+ ExceptionState exception_state(resolver_->GetScriptState()->GetIsolate(),
+ ExceptionState::kExecutionContext,
+ interface_name_, property_name_);
+ exception_state.ThrowException(code, error_message);
+ resolver_->Reject(exception_state);
+
resolver_.Clear();
}
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/content_decryption_module_result_promise.h b/chromium/third_party/blink/renderer/modules/encryptedmedia/content_decryption_module_result_promise.h
index cdd13195489..6f907691233 100644
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/content_decryption_module_result_promise.h
+++ b/chromium/third_party/blink/renderer/modules/encryptedmedia/content_decryption_module_result_promise.h
@@ -7,7 +7,7 @@
#include "third_party/blink/public/platform/web_encrypted_media_key_information.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_code.h"
#include "third_party/blink/renderer/platform/content_decryption_module_result.h"
namespace blink {
@@ -52,7 +52,10 @@ class ContentDecryptionModuleResultPromise
void Trace(blink::Visitor*) override;
protected:
- explicit ContentDecryptionModuleResultPromise(ScriptState*);
+ // |interface_name| and |property_name| must have static life time.
+ explicit ContentDecryptionModuleResultPromise(ScriptState*,
+ const char* interface_name,
+ const char* property_name);
// Resolves the promise with |value|. Used by subclasses to resolve the
// promise.
@@ -74,6 +77,8 @@ class ContentDecryptionModuleResultPromise
private:
Member<ScriptPromiseResolver> resolver_;
+ const char* const interface_name_;
+ const char* const property_name_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/encrypted_media_utils.cc b/chromium/third_party/blink/renderer/modules/encryptedmedia/encrypted_media_utils.cc
index 77f0ee8ec31..d604ed69e24 100644
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/encrypted_media_utils.cc
+++ b/chromium/third_party/blink/renderer/modules/encryptedmedia/encrypted_media_utils.cc
@@ -67,8 +67,8 @@ String EncryptedMediaUtils::ConvertFromSessionType(
return kTemporary;
case WebEncryptedMediaSessionType::kPersistentLicense:
return kPersistentLicense;
- // FIXME: Remove once removed from Chromium (crbug.com/448888).
- case WebEncryptedMediaSessionType::kPersistentReleaseMessage:
+ // TODO(crbug.com/856925): Add support for kPersistentUsageRecord.
+ case WebEncryptedMediaSessionType::kPersistentUsageRecord:
case WebEncryptedMediaSessionType::kUnknown:
// Chromium should not use Unknown.
NOTREACHED();
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.cc b/chromium/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.cc
index a45bd818d40..a4b9f87d5a8 100644
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.cc
+++ b/chromium/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.cc
@@ -5,12 +5,10 @@
#include "third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#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/typed_arrays/dom_typed_array.h"
@@ -18,6 +16,7 @@
#include "third_party/blink/renderer/modules/encryptedmedia/encrypted_media_utils.h"
#include "third_party/blink/renderer/modules/encryptedmedia/media_encrypted_event.h"
#include "third_party/blink/renderer/modules/encryptedmedia/media_keys.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/content_decryption_module_result.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -80,21 +79,24 @@ class SetContentDecryptionModuleResult final
WebContentDecryptionModule*) override {
NOTREACHED();
std::move(failure_callback_)
- .Run(kInvalidStateError, "Unexpected completion.");
+ .Run(ToExceptionCode(DOMExceptionCode::kInvalidStateError),
+ "Unexpected completion.");
}
void CompleteWithSession(
WebContentDecryptionModuleResult::SessionStatus status) override {
NOTREACHED();
std::move(failure_callback_)
- .Run(kInvalidStateError, "Unexpected completion.");
+ .Run(ToExceptionCode(DOMExceptionCode::kInvalidStateError),
+ "Unexpected completion.");
}
void CompleteWithKeyStatus(
WebEncryptedMediaKeyInformation::KeyStatus key_status) override {
NOTREACHED();
std::move(failure_callback_)
- .Run(kInvalidStateError, "Unexpected completion.");
+ .Run(ToExceptionCode(DOMExceptionCode::kInvalidStateError),
+ "Unexpected completion.");
}
void CompleteWithError(WebContentDecryptionModuleException code,
@@ -170,7 +172,7 @@ void SetMediaKeysHandler::ClearExistingMediaKeys() {
if (new_media_keys_) {
if (!new_media_keys_->ReserveForMediaElement(element_.Get())) {
this_element.is_attaching_media_keys_ = false;
- Fail(kQuotaExceededError,
+ Fail(ToExceptionCode(DOMExceptionCode::kQuotaExceededError),
"The MediaKeys object is already in use by another media element.");
return;
}
@@ -274,8 +276,11 @@ void SetMediaKeysHandler::Fail(ExceptionCode code,
// Reject promise with an appropriate error.
ScriptState::Scope scope(GetScriptState());
- v8::Isolate* isolate = GetScriptState()->GetIsolate();
- Reject(V8ThrowDOMException::CreateDOMException(isolate, code, error_message));
+ ExceptionState exception_state(GetScriptState()->GetIsolate(),
+ ExceptionState::kExecutionContext,
+ "HTMLMediaElement", "setMediaKeys");
+ exception_state.ThrowException(code, error_message);
+ Reject(exception_state);
}
void SetMediaKeysHandler::ClearFailed(ExceptionCode code,
@@ -367,7 +372,7 @@ ScriptPromise HTMLMediaElementEncryptedMedia::setMediaKeys(
// promise rejected with an InvalidStateError.
if (this_element.is_attaching_media_keys_) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kInvalidStateError,
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
"Another request is in progress."));
}
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc
index 66bdd4f57dd..05b5a3fefef 100644
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc
+++ b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc
@@ -27,6 +27,7 @@
#include <cmath>
#include <limits>
+
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_content_decryption_module.h"
#include "third_party/blink/public/platform/web_content_decryption_module_exception.h"
@@ -38,8 +39,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#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/dom/events/media_element_event_queue.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/core/dom/events/event_queue.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/modules/encryptedmedia/content_decryption_module_result_promise.h"
@@ -92,7 +92,7 @@ static bool IsPersistentSessionType(WebEncryptedMediaSessionType session_type) {
return false;
case WebEncryptedMediaSessionType::kPersistentLicense:
return true;
- case WebEncryptedMediaSessionType::kPersistentReleaseMessage:
+ case WebEncryptedMediaSessionType::kPersistentUsageRecord:
return true;
case blink::WebEncryptedMediaSessionType::kUnknown:
break;
@@ -105,14 +105,14 @@ static bool IsPersistentSessionType(WebEncryptedMediaSessionType session_type) {
static ScriptPromise CreateRejectedPromiseNotCallable(
ScriptState* script_state) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, "The session is not callable."));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "The session is not callable."));
}
static ScriptPromise CreateRejectedPromiseAlreadyClosed(
ScriptState* script_state) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kInvalidStateError,
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
"The session is already closed."));
}
@@ -120,7 +120,7 @@ static ScriptPromise CreateRejectedPromiseAlreadyInitialized(
ScriptState* script_state) {
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kInvalidStateError,
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
"The session is already initialized."));
}
@@ -227,8 +227,14 @@ class MediaKeySession::PendingAction final
// is not expected to be called, and will reject the promise.
class NewSessionResultPromise : public ContentDecryptionModuleResultPromise {
public:
- NewSessionResultPromise(ScriptState* script_state, MediaKeySession* session)
- : ContentDecryptionModuleResultPromise(script_state), session_(session) {}
+ NewSessionResultPromise(ScriptState* script_state,
+ MediaKeySession* session,
+ const char* interface_name,
+ const char* property_name)
+ : ContentDecryptionModuleResultPromise(script_state,
+ interface_name,
+ property_name),
+ session_(session) {}
~NewSessionResultPromise() override = default;
@@ -259,8 +265,14 @@ class NewSessionResultPromise : public ContentDecryptionModuleResultPromise {
// is not expected to be called, and will reject the promise.
class LoadSessionResultPromise : public ContentDecryptionModuleResultPromise {
public:
- LoadSessionResultPromise(ScriptState* script_state, MediaKeySession* session)
- : ContentDecryptionModuleResultPromise(script_state), session_(session) {}
+ LoadSessionResultPromise(ScriptState* script_state,
+ MediaKeySession* session,
+ const char* interface_name,
+ const char* property_name)
+ : ContentDecryptionModuleResultPromise(script_state,
+ interface_name,
+ property_name),
+ session_(session) {}
~LoadSessionResultPromise() override = default;
@@ -295,8 +307,14 @@ class LoadSessionResultPromise : public ContentDecryptionModuleResultPromise {
// promise).
class SimpleResultPromise : public ContentDecryptionModuleResultPromise {
public:
- SimpleResultPromise(ScriptState* script_state, MediaKeySession* session)
- : ContentDecryptionModuleResultPromise(script_state), session_(session) {}
+ SimpleResultPromise(ScriptState* script_state,
+ MediaKeySession* session,
+ const char* interface_name,
+ const char* property_name)
+ : ContentDecryptionModuleResultPromise(script_state,
+ interface_name,
+ property_name),
+ session_(session) {}
~SimpleResultPromise() override = default;
@@ -330,9 +348,8 @@ MediaKeySession::MediaKeySession(ScriptState* script_state,
MediaKeys* media_keys,
WebEncryptedMediaSessionType session_type)
: ContextLifecycleObserver(ExecutionContext::From(script_state)),
- async_event_queue_(
- MediaElementEventQueue::Create(this,
- ExecutionContext::From(script_state))),
+ async_event_queue_(EventQueue::Create(GetExecutionContext(),
+ TaskType::kMediaElementEvent)),
media_keys_(media_keys),
session_type_(session_type),
expiration_(std::numeric_limits<double>::quiet_NaN()),
@@ -465,7 +482,7 @@ ScriptPromise MediaKeySession::generateRequest(
EncryptedMediaUtils::ConvertToInitDataType(init_data_type_string);
if (init_data_type == WebEncryptedMediaInitDataType::kUnknown) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kNotSupportedError,
+ script_state, DOMException::Create(DOMExceptionCode::kNotSupportedError,
"The initialization data type '" +
init_data_type_string +
"' is not supported."));
@@ -479,8 +496,8 @@ ScriptPromise MediaKeySession::generateRequest(
// (Done in constructor.)
// 9. Let promise be a new promise.
- NewSessionResultPromise* result =
- new NewSessionResultPromise(script_state, this);
+ NewSessionResultPromise* result = new NewSessionResultPromise(
+ script_state, this, "MediaKeySession", "generateRequest");
ScriptPromise promise = result->Promise();
// 10. Run the following steps asynchronously (done in generateRequestTask())
@@ -574,8 +591,8 @@ ScriptPromise MediaKeySession::load(ScriptState* script_state,
// (Available as getExecutionContext()->getSecurityOrigin() anytime.)
// 7. Let promise be a new promise.
- LoadSessionResultPromise* result =
- new LoadSessionResultPromise(script_state, this);
+ LoadSessionResultPromise* result = new LoadSessionResultPromise(
+ script_state, this, "MediaKeySession", "load");
ScriptPromise promise = result->Promise();
// 8. Run the following steps asynchronously (done in loadTask())
@@ -694,7 +711,8 @@ ScriptPromise MediaKeySession::update(ScriptState* script_state,
DOMArrayBuffer::Create(response.Data(), response.ByteLength());
// 5. Let promise be a new promise.
- SimpleResultPromise* result = new SimpleResultPromise(script_state, this);
+ SimpleResultPromise* result =
+ new SimpleResultPromise(script_state, this, "MediaKeySession", "update");
ScriptPromise promise = result->Promise();
// 6. Run the following steps asynchronously (done in updateTask())
@@ -739,7 +757,8 @@ ScriptPromise MediaKeySession::close(ScriptState* script_state) {
return CreateRejectedPromiseNotCallable(script_state);
// 4. Let promise be a new promise.
- SimpleResultPromise* result = new SimpleResultPromise(script_state, this);
+ SimpleResultPromise* result =
+ new SimpleResultPromise(script_state, this, "MediaKeySession", "close");
ScriptPromise promise = result->Promise();
// 5. Run the following steps in parallel (done in closeTask()).
@@ -779,7 +798,8 @@ ScriptPromise MediaKeySession::remove(ScriptState* script_state) {
return CreateRejectedPromiseNotCallable(script_state);
// 3. Let promise be a new promise.
- SimpleResultPromise* result = new SimpleResultPromise(script_state, this);
+ SimpleResultPromise* result =
+ new SimpleResultPromise(script_state, this, "MediaKeySession", "remove");
ScriptPromise promise = result->Promise();
// 4. Run the following steps asynchronously (done in removeTask()).
@@ -1004,7 +1024,6 @@ void MediaKeySession::ContextDestroyed(ExecutionContext*) {
is_closed_ = true;
action_timer_.Stop();
pending_actions_.clear();
- async_event_queue_->Close();
}
void MediaKeySession::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_session.h b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_session.h
index fab052f649b..caaca9ca862 100644
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_session.h
+++ b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_session.h
@@ -41,7 +41,7 @@
namespace blink {
class DOMException;
-class MediaElementEventQueue;
+class EventQueue;
class MediaKeys;
// References are held by JS only. However, even if all JS references are
@@ -135,7 +135,7 @@ class MediaKeySession final
void KeysStatusesChange(const WebVector<WebEncryptedMediaKeyInformation>&,
bool has_additional_usable_key) override;
- Member<MediaElementEventQueue> async_event_queue_;
+ Member<EventQueue> async_event_queue_;
std::unique_ptr<WebContentDecryptionModuleSession> session_;
// Used to determine if MediaKeys is still active.
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access.cc b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access.cc
index d2d62df6541..bc8cdb23881 100644
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access.cc
+++ b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access.cc
@@ -36,8 +36,12 @@ class NewCdmResultPromise : public ContentDecryptionModuleResultPromise {
public:
NewCdmResultPromise(
ScriptState* script_state,
- const WebVector<WebEncryptedMediaSessionType>& supported_session_types)
- : ContentDecryptionModuleResultPromise(script_state),
+ const WebVector<WebEncryptedMediaSessionType>& supported_session_types,
+ const char* interface_name,
+ const char* property_name)
+ : ContentDecryptionModuleResultPromise(script_state,
+ interface_name,
+ property_name),
supported_session_types_(supported_session_types) {}
~NewCdmResultPromise() override = default;
@@ -80,6 +84,19 @@ static HeapVector<MediaKeySystemMediaCapability> ConvertCapabilities(
MediaKeySystemMediaCapability capability;
capability.setContentType(capabilities[i].content_type);
capability.setRobustness(capabilities[i].robustness);
+
+ switch (capabilities[i].encryption_scheme) {
+ case WebMediaKeySystemMediaCapability::EncryptionScheme::kNotSpecified:
+ capability.setEncryptionSchemeToNull();
+ break;
+ case WebMediaKeySystemMediaCapability::EncryptionScheme::kCenc:
+ capability.setEncryptionScheme("cenc");
+ break;
+ case WebMediaKeySystemMediaCapability::EncryptionScheme::kCbcs:
+ capability.setEncryptionScheme("cbcs");
+ break;
+ }
+
result[i] = capability;
}
return result;
@@ -155,7 +172,8 @@ ScriptPromise MediaKeySystemAccess::createMediaKeys(ScriptState* script_state) {
// 1. Let promise be a new promise.
NewCdmResultPromise* helper =
- new NewCdmResultPromise(script_state, configuration.session_types);
+ new NewCdmResultPromise(script_state, configuration.session_types,
+ "MediaKeySystemAccess", "createMediaKeys");
ScriptPromise promise = helper->Promise();
// 2. Asynchronously create and initialize the MediaKeys object.
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_system_media_capability.idl b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_system_media_capability.idl
index 289516970e9..2f28129e003 100644
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_system_media_capability.idl
+++ b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_key_system_media_capability.idl
@@ -4,7 +4,10 @@
// https://w3c.github.io/encrypted-media/#idl-def-MediaKeySystemMediaCapability
+enum EncryptionScheme { "cenc", "cbcs" };
+
dictionary MediaKeySystemMediaCapability {
DOMString contentType = "";
DOMString robustness = "";
+ [RuntimeEnabled=EncryptedMediaEncryptionSchemeQuery] EncryptionScheme? encryptionScheme = null;
};
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc
index cf360b81ec3..15ddb62e6e3 100644
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc
+++ b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc
@@ -26,13 +26,13 @@
#include "third_party/blink/renderer/modules/encryptedmedia/media_keys.h"
#include <memory>
+
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_content_decryption_module.h"
#include "third_party/blink/public/platform/web_encrypted_media_key_information.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
@@ -114,8 +114,13 @@ class MediaKeys::PendingAction final
class SetCertificateResultPromise
: public ContentDecryptionModuleResultPromise {
public:
- SetCertificateResultPromise(ScriptState* script_state, MediaKeys* media_keys)
- : ContentDecryptionModuleResultPromise(script_state),
+ SetCertificateResultPromise(ScriptState* script_state,
+ MediaKeys* media_keys,
+ const char* interface_name,
+ const char* property_name)
+ : ContentDecryptionModuleResultPromise(script_state,
+ interface_name,
+ property_name),
media_keys_(media_keys) {}
~SetCertificateResultPromise() override = default;
@@ -164,8 +169,12 @@ class GetStatusForPolicyResultPromise
: public ContentDecryptionModuleResultPromise {
public:
GetStatusForPolicyResultPromise(ScriptState* script_state,
- MediaKeys* media_keys)
- : ContentDecryptionModuleResultPromise(script_state),
+ MediaKeys* media_keys,
+ const char* interface_name,
+ const char* property_name)
+ : ContentDecryptionModuleResultPromise(script_state,
+ interface_name,
+ property_name),
media_keys_(media_keys) {}
~GetStatusForPolicyResultPromise() override = default;
@@ -238,7 +247,7 @@ MediaKeySession* MediaKeys::createSession(ScriptState* script_state,
WebEncryptedMediaSessionType session_type =
EncryptedMediaUtils::ConvertToSessionType(session_type_string);
if (!SessionTypeSupported(session_type)) {
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"Unsupported session type.");
return nullptr;
}
@@ -278,8 +287,8 @@ ScriptPromise MediaKeys::setServerCertificate(
server_certificate.Data(), server_certificate.ByteLength());
// 4. Let promise be a new promise.
- SetCertificateResultPromise* result =
- new SetCertificateResultPromise(script_state, this);
+ SetCertificateResultPromise* result = new SetCertificateResultPromise(
+ script_state, this, "MediaKeys", "setServerCertificate");
ScriptPromise promise = result->Promise();
// 5. Run the following steps asynchronously. See SetServerCertificateTask().
@@ -319,8 +328,8 @@ ScriptPromise MediaKeys::getStatusForPolicy(
String min_hdcp_version = media_keys_policy.minHdcpVersion();
// Let promise be a new promise.
- GetStatusForPolicyResultPromise* result =
- new GetStatusForPolicyResultPromise(script_state, this);
+ GetStatusForPolicyResultPromise* result = new GetStatusForPolicyResultPromise(
+ script_state, this, "MediaKeys", "getStatusForPolicy");
ScriptPromise promise = result->Promise();
// Run the following steps asynchronously. See GetStatusForPolicyTask().
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys_controller.cc b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys_controller.cc
index bcca4faa79a..ef27221f757 100644
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys_controller.cc
@@ -5,7 +5,8 @@
#include "third_party/blink/renderer/modules/encryptedmedia/media_keys_controller.h"
#include "third_party/blink/public/platform/web_content_decryption_module.h"
-#include "third_party/blink/public/web/web_frame_client.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys_get_status_for_policy.idl b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys_get_status_for_policy.idl
index 09e21a7d8ea..61aaf39af0f 100644
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys_get_status_for_policy.idl
+++ b/chromium/third_party/blink/renderer/modules/encryptedmedia/media_keys_get_status_for_policy.idl
@@ -6,7 +6,7 @@
[
ImplementedAs=MediaKeysGetStatusForPolicy,
- RuntimeEnabled=EncryptedMediaHdcpPolicyCheck,
+ OriginTrialEnabled=EncryptedMediaHdcpPolicyCheck,
SecureContext
] partial interface MediaKeys {
[Measure, CallWith=ScriptState] Promise<MediaKeyStatus> getStatusForPolicy(MediaKeysPolicy policy);
diff --git a/chromium/third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.cc b/chromium/third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.cc
index 7e0b46f0da6..313725cdcb0 100644
--- a/chromium/third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.cc
+++ b/chromium/third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.cc
@@ -15,8 +15,8 @@
#include "third_party/blink/public/platform/web_vector.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/dom/exception_code.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/core/inspector/console_message.h"
@@ -51,6 +51,17 @@ static WebVector<WebEncryptedMediaInitDataType> ConvertInitDataTypes(
return result;
}
+static WebMediaKeySystemMediaCapability::EncryptionScheme
+ConvertEncryptionScheme(const String& encryption_scheme) {
+ if (encryption_scheme == "cenc")
+ return WebMediaKeySystemMediaCapability::EncryptionScheme::kCenc;
+ if (encryption_scheme == "cbcs")
+ return WebMediaKeySystemMediaCapability::EncryptionScheme::kCbcs;
+
+ NOTREACHED();
+ return WebMediaKeySystemMediaCapability::EncryptionScheme::kNotSpecified;
+}
+
static WebVector<WebMediaKeySystemMediaCapability> ConvertCapabilities(
const HeapVector<MediaKeySystemMediaCapability>& capabilities) {
WebVector<WebMediaKeySystemMediaCapability> result(capabilities.size());
@@ -71,6 +82,17 @@ static WebVector<WebMediaKeySystemMediaCapability> ConvertCapabilities(
result[i].codecs = type.ParameterValueForName("codecs");
}
result[i].robustness = capabilities[i].robustness();
+
+ // From
+ // https://github.com/WICG/encrypted-media-encryption-scheme/blob/master/explainer.md
+ // "Asking for "any" encryption scheme is unrealistic. Defining null as
+ // "any scheme" is convenient for backward compatibility, though.
+ // Applications which ignore this feature by leaving encryptionScheme null
+ // get the same user agent behavior they did before this feature existed."
+ result[i].encryption_scheme =
+ capabilities[i].hasEncryptionScheme()
+ ? ConvertEncryptionScheme(capabilities[i].encryptionScheme())
+ : WebMediaKeySystemMediaCapability::EncryptionScheme::kNotSpecified;
}
return result;
}
@@ -214,7 +236,8 @@ void MediaKeySystemAccessInitializer::RequestNotSupported(
if (!IsExecutionContextValid())
return;
- resolver_->Reject(DOMException::Create(kNotSupportedError, error_message));
+ resolver_->Reject(DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ error_message));
resolver_.Clear();
}
@@ -290,7 +313,7 @@ ScriptPromise NavigatorRequestMediaKeySystemAccess::requestMediaKeySystemAccess(
return ScriptPromise::RejectWithDOMException(
script_state,
DOMException::Create(
- kSecurityError,
+ DOMExceptionCode::kSecurityError,
"requestMediaKeySystemAccess is disabled by feature policy."));
}
} else {
@@ -324,7 +347,7 @@ ScriptPromise NavigatorRequestMediaKeySystemAccess::requestMediaKeySystemAccess(
return ScriptPromise::RejectWithDOMException(
script_state,
DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"The context provided is not associated with a page."));
}
diff --git a/chromium/third_party/blink/renderer/modules/event_target_modules_names.json5 b/chromium/third_party/blink/renderer/modules/event_target_modules_names.json5
index 2f66c7c7ada..b98a20d37db 100644
--- a/chromium/third_party/blink/renderer/modules/event_target_modules_names.json5
+++ b/chromium/third_party/blink/renderer/modules/event_target_modules_names.json5
@@ -40,10 +40,10 @@
"modules/remoteplayback/RemotePlayback",
"modules/screen_orientation/ScreenOrientation",
"modules/sensor/Sensor",
- "modules/serviceworkers/ServiceWorker",
- "modules/serviceworkers/ServiceWorkerContainer",
- "modules/serviceworkers/ServiceWorkerGlobalScope",
- "modules/serviceworkers/ServiceWorkerRegistration",
+ "modules/service_worker/ServiceWorker",
+ "modules/service_worker/ServiceWorkerContainer",
+ "modules/service_worker/ServiceWorkerGlobalScope",
+ "modules/service_worker/ServiceWorkerRegistration",
"modules/speech/SpeechRecognition",
"modules/speech/SpeechSynthesis",
"modules/speech/SpeechSynthesisUtterance",
@@ -54,7 +54,6 @@
"modules/webmidi/MIDIInput",
"modules/webmidi/MIDIPort",
"modules/xr/XR",
- "modules/xr/XRDevice",
"modules/xr/XRSession",
{
name: "modules/websockets/WebSocket",
diff --git a/chromium/third_party/blink/renderer/modules/eventsource/event_source.cc b/chromium/third_party/blink/renderer/modules/eventsource/event_source.cc
index 540467729f3..92ed79a1e5c 100644
--- a/chromium/third_party/blink/renderer/modules/eventsource/event_source.cc
+++ b/chromium/third_party/blink/renderer/modules/eventsource/event_source.cc
@@ -35,12 +35,10 @@
#include <memory>
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_url_request.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/bindings/core/v8/serialization/serialized_script_value_factory.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#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/csp/content_security_policy.h"
@@ -51,6 +49,7 @@
#include "third_party/blink/renderer/core/loader/threadable_loader.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/modules/eventsource/event_source_init.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
@@ -87,14 +86,15 @@ EventSource* EventSource::Create(ExecutionContext* context,
if (url.IsEmpty()) {
exception_state.ThrowDOMException(
- kSyntaxError, "Cannot open an EventSource to an empty URL.");
+ DOMExceptionCode::kSyntaxError,
+ "Cannot open an EventSource to an empty URL.");
return nullptr;
}
KURL full_url = context->CompleteURL(url);
if (!full_url.IsValid()) {
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"Cannot open an EventSource to '" + url + "'. The URL is invalid.");
return nullptr;
}
@@ -110,10 +110,6 @@ EventSource::~EventSource() {
DCHECK(!loader_);
}
-void EventSource::Dispose() {
- probe::detachClientRequest(GetExecutionContext(), this);
-}
-
void EventSource::ScheduleInitialConnect() {
DCHECK_EQ(kConnecting, state_);
DCHECK(!loader_);
@@ -170,8 +166,6 @@ void EventSource::Connect() {
}
void EventSource::NetworkRequestEnded() {
- probe::didFinishEventSourceRequest(GetExecutionContext(), this);
-
loader_ = nullptr;
if (state_ != kClosed)
@@ -180,7 +174,8 @@ void EventSource::NetworkRequestEnded() {
void EventSource::ScheduleReconnect() {
state_ = kConnecting;
- connect_timer_.StartOneShot(reconnect_delay_ / 1000.0, FROM_HERE);
+ connect_timer_.StartOneShot(TimeDelta::FromMilliseconds(reconnect_delay_),
+ FROM_HERE);
DispatchEvent(Event::Create(EventTypeNames::error));
}
@@ -360,7 +355,6 @@ void EventSource::AbortConnectionAttempt() {
}
void EventSource::ContextDestroyed(ExecutionContext*) {
- probe::detachClientRequest(GetExecutionContext(), this);
close();
}
diff --git a/chromium/third_party/blink/renderer/modules/eventsource/event_source.h b/chromium/third_party/blink/renderer/modules/eventsource/event_source.h
index ff2eebf7694..f31cee8c42f 100644
--- a/chromium/third_party/blink/renderer/modules/eventsource/event_source.h
+++ b/chromium/third_party/blink/renderer/modules/eventsource/event_source.h
@@ -59,7 +59,6 @@ class MODULES_EXPORT EventSource final
public EventSourceParser::Client {
DEFINE_WRAPPERTYPEINFO();
USING_GARBAGE_COLLECTED_MIXIN(EventSource);
- USING_PRE_FINALIZER(EventSource, Dispose);
public:
static EventSource* Create(ExecutionContext*,
@@ -103,8 +102,6 @@ class MODULES_EXPORT EventSource final
private:
EventSource(ExecutionContext*, const KURL&, const EventSourceInit&);
- void Dispose();
-
void DidReceiveResponse(unsigned long,
const ResourceResponse&,
std::unique_ptr<WebDataConsumerHandle>) override;
diff --git a/chromium/third_party/blink/renderer/modules/eventsource/event_source_parser.cc b/chromium/third_party/blink/renderer/modules/eventsource/event_source_parser.cc
index 3db3525aca7..dfca4c749a7 100644
--- a/chromium/third_party/blink/renderer/modules/eventsource/event_source_parser.cc
+++ b/chromium/third_party/blink/renderer/modules/eventsource/event_source_parser.cc
@@ -127,7 +127,7 @@ void EventSourceParser::ParseLine() {
}
String EventSourceParser::FromUTF8(const char* bytes, size_t size) {
- return codec_->Decode(bytes, size, WTF::kDataEOF);
+ return codec_->Decode(bytes, size, WTF::FlushBehavior::kDataEOF);
}
void EventSourceParser::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/modules/exported/BUILD.gn b/chromium/third_party/blink/renderer/modules/exported/BUILD.gn
index 686411ed440..e27cd8b34ef 100644
--- a/chromium/third_party/blink/renderer/modules/exported/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/exported/BUILD.gn
@@ -16,10 +16,6 @@ blink_modules_sources("exported") {
"web_idb_key_range.cc",
"web_idb_value.cc",
"web_media_stream_registry.cc",
- "web_speech_grammar.cc",
- "web_speech_recognition_handle.cc",
- "web_speech_recognition_result.cc",
- "web_speech_recognizer_client.cc",
"web_storage_event_dispatcher_impl.cc",
"web_user_media_request.cc",
]
diff --git a/chromium/third_party/blink/renderer/modules/exported/web_ax_object.cc b/chromium/third_party/blink/renderer/modules/exported/web_ax_object.cc
index 2ca49376d09..d998979df5c 100644
--- a/chromium/third_party/blink/renderer/modules/exported/web_ax_object.cc
+++ b/chromium/third_party/blink/renderer/modules/exported/web_ax_object.cc
@@ -57,10 +57,6 @@
#include "third_party/blink/renderer/modules/accessibility/ax_object.h"
#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h"
#include "third_party/blink/renderer/modules/accessibility/ax_range.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table_cell.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table_column.h"
-#include "third_party/blink/renderer/modules/accessibility/ax_table_row.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -1094,63 +1090,45 @@ int WebAXObject::AriaColumnCount() const {
if (IsDetached())
return 0;
- if (!private_->IsAXTable())
- return 0;
-
- return ToAXTable(private_.Get())->AriaColumnCount();
+ return private_->IsTableLikeRole() ? private_->AriaColumnCount() : 0;
}
unsigned WebAXObject::AriaColumnIndex() const {
if (IsDetached())
return 0;
- if (!private_->IsTableCell())
- return 0;
-
- return ToAXTableCell(private_.Get())->AriaColumnIndex();
+ return private_->IsTableCellLikeRole() ? private_->AriaColumnIndex() : 0;
}
int WebAXObject::AriaRowCount() const {
if (IsDetached())
return 0;
- if (!private_->IsAXTable())
- return 0;
-
- return ToAXTable(private_.Get())->AriaRowCount();
+ return private_->IsTableLikeRole() ? private_->AriaRowCount() : 0;
}
unsigned WebAXObject::AriaRowIndex() const {
if (IsDetached())
return 0;
- if (private_->IsTableCell())
- return ToAXTableCell(private_.Get())->AriaRowIndex();
-
- if (private_->IsTableRow())
- return ToAXTableRow(private_.Get())->AriaRowIndex();
-
- return 0;
+ return private_->AriaRowIndex();
}
unsigned WebAXObject::ColumnCount() const {
if (IsDetached())
return false;
- if (!private_->IsAXTable())
- return 0;
-
- return ToAXTable(private_.Get())->ColumnCount();
+ return private_->IsTableLikeRole() ? private_->ColumnCount() : 0;
}
unsigned WebAXObject::RowCount() const {
if (IsDetached())
return 0;
- if (!private_->IsAXTable())
+ if (!private_->IsTableLikeRole())
return 0;
- return ToAXTable(private_.Get())->RowCount();
+ return private_->RowCount();
}
WebAXObject WebAXObject::CellForColumnAndRow(unsigned column,
@@ -1158,71 +1136,27 @@ WebAXObject WebAXObject::CellForColumnAndRow(unsigned column,
if (IsDetached())
return WebAXObject();
- if (!private_->IsAXTable())
+ if (!private_->IsTableLikeRole())
return WebAXObject();
- AXTableCell* cell =
- ToAXTable(private_.Get())->CellForColumnAndRow(column, row);
- return WebAXObject(static_cast<AXObject*>(cell));
-}
-
-WebAXObject WebAXObject::HeaderContainerObject() const {
- if (IsDetached())
- return WebAXObject();
-
- if (!private_->IsAXTable())
- return WebAXObject();
-
- return WebAXObject(ToAXTable(private_.Get())->HeaderContainer());
-}
-
-WebAXObject WebAXObject::RowAtIndex(unsigned row_index) const {
- if (IsDetached())
- return WebAXObject();
-
- if (!private_->IsAXTable())
- return WebAXObject();
-
- const AXObject::AXObjectVector& rows = ToAXTable(private_.Get())->Rows();
- if (row_index < rows.size())
- return WebAXObject(rows[row_index]);
-
- return WebAXObject();
-}
-
-WebAXObject WebAXObject::ColumnAtIndex(unsigned column_index) const {
- if (IsDetached())
- return WebAXObject();
-
- if (!private_->IsAXTable())
- return WebAXObject();
-
- const AXObject::AXObjectVector& columns =
- ToAXTable(private_.Get())->Columns();
- if (column_index < columns.size())
- return WebAXObject(columns[column_index]);
-
- return WebAXObject();
+ return WebAXObject(private_->CellForColumnAndRow(column, row));
}
unsigned WebAXObject::RowIndex() const {
if (IsDetached())
return 0;
- if (!private_->IsTableRow())
- return 0;
-
- return ToAXTableRow(private_.Get())->RowIndex();
+ return private_->IsTableRowLikeRole() ? private_->RowIndex() : 0;
}
WebAXObject WebAXObject::RowHeader() const {
if (IsDetached())
return WebAXObject();
- if (!private_->IsTableRow())
+ if (!private_->IsTableRowLikeRole())
return WebAXObject();
- return WebAXObject(ToAXTableRow(private_.Get())->HeaderObject());
+ return WebAXObject(private_->HeaderObject());
}
void WebAXObject::RowHeaders(
@@ -1230,11 +1164,11 @@ void WebAXObject::RowHeaders(
if (IsDetached())
return;
- if (!private_->IsAXTable())
+ if (!private_->IsTableLikeRole())
return;
AXObject::AXObjectVector headers;
- ToAXTable(private_.Get())->RowHeaders(headers);
+ private_->RowHeaders(headers);
size_t header_count = headers.size();
WebVector<WebAXObject> result(header_count);
@@ -1252,7 +1186,7 @@ unsigned WebAXObject::ColumnIndex() const {
if (private_->RoleValue() != kColumnRole)
return 0;
- return ToAXTableColumn(private_.Get())->ColumnIndex();
+ return private_->ColumnIndex();
}
WebAXObject WebAXObject::ColumnHeader() const {
@@ -1262,7 +1196,7 @@ WebAXObject WebAXObject::ColumnHeader() const {
if (private_->RoleValue() != kColumnRole)
return WebAXObject();
- return WebAXObject(ToAXTableColumn(private_.Get())->HeaderObject());
+ return WebAXObject(private_->HeaderObject());
}
void WebAXObject::ColumnHeaders(
@@ -1270,11 +1204,11 @@ void WebAXObject::ColumnHeaders(
if (IsDetached())
return;
- if (!private_->IsAXTable())
+ if (!private_->IsTableLikeRole())
return;
AXObject::AXObjectVector headers;
- ToAXTable(private_.Get())->ColumnHeaders(headers);
+ private_->ColumnHeaders(headers);
size_t header_count = headers.size();
WebVector<WebAXObject> result(header_count);
@@ -1289,48 +1223,28 @@ unsigned WebAXObject::CellColumnIndex() const {
if (IsDetached())
return 0;
- if (!private_->IsTableCell())
- return 0;
-
- std::pair<unsigned, unsigned> column_range;
- ToAXTableCell(private_.Get())->ColumnIndexRange(column_range);
- return column_range.first;
+ return private_->IsTableCellLikeRole() ? private_->ColumnIndex() : 0;
}
unsigned WebAXObject::CellColumnSpan() const {
if (IsDetached())
return 0;
- if (!private_->IsTableCell())
- return 0;
-
- std::pair<unsigned, unsigned> column_range;
- ToAXTableCell(private_.Get())->ColumnIndexRange(column_range);
- return column_range.second;
+ return private_->IsTableCellLikeRole() ? private_->ColumnSpan() : 0;
}
unsigned WebAXObject::CellRowIndex() const {
if (IsDetached())
return 0;
- if (!private_->IsTableCell())
- return 0;
-
- std::pair<unsigned, unsigned> row_range;
- ToAXTableCell(private_.Get())->RowIndexRange(row_range);
- return row_range.first;
+ return private_->IsTableCellLikeRole() ? private_->RowIndex() : 0;
}
unsigned WebAXObject::CellRowSpan() const {
if (IsDetached())
return 0;
- if (!private_->IsTableCell())
- return 0;
-
- std::pair<unsigned, unsigned> row_range;
- ToAXTableCell(private_.Get())->RowIndexRange(row_range);
- return row_range.second;
+ return private_->IsTableCellLikeRole() ? private_->RowSpan() : 0;
}
WebAXSortDirection WebAXObject::SortDirection() const {
diff --git a/chromium/third_party/blink/renderer/modules/exported/web_crypto_normalize.cc b/chromium/third_party/blink/renderer/modules/exported/web_crypto_normalize.cc
index c872dc0bd8a..a880a03ec46 100644
--- a/chromium/third_party/blink/renderer/modules/exported/web_crypto_normalize.cc
+++ b/chromium/third_party/blink/renderer/modules/exported/web_crypto_normalize.cc
@@ -32,9 +32,9 @@
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/modules/crypto/crypto_result_impl.h"
#include "third_party/blink/renderer/modules/crypto/normalize_algorithm.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/crypto_result.h"
#include "v8/include/v8.h"
diff --git a/chromium/third_party/blink/renderer/modules/exported/web_dom_file_system.cc b/chromium/third_party/blink/renderer/modules/exported/web_dom_file_system.cc
index ea0d43152cb..79e77e2904f 100644
--- a/chromium/third_party/blink/renderer/modules/exported/web_dom_file_system.cc
+++ b/chromium/third_party/blink/renderer/modules/exported/web_dom_file_system.cc
@@ -33,6 +33,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_directory_entry.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_dom_file_system.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_file_entry.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/web_local_frame_impl.h"
#include "third_party/blink/renderer/modules/filesystem/directory_entry.h"
diff --git a/chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc b/chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
index 7ac61fd9658..320fb9937ff 100644
--- a/chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
@@ -31,12 +31,13 @@
#include "third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h"
#include <memory>
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/public/platform/web_worker_fetch_context.h"
-#include "third_party/blink/public/web/modules/serviceworker/web_service_worker_context_client.h"
+#include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h"
#include "third_party/blink/public/web/web_console_message.h"
#include "third_party/blink/public/web/web_settings.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
@@ -55,11 +56,11 @@
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_inspector_proxy.h"
#include "third_party/blink/renderer/modules/indexeddb/indexed_db_client.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_container_client.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_proxy.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_installed_scripts_manager.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_thread.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_container_client.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_thread.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/loader/fetch/substitute_data.h"
@@ -146,7 +147,14 @@ void WebEmbeddedWorkerImpl::StartWorkerContext(
pause_after_download_state_ = kDoPauseAfterDownload;
devtools_worker_token_ = data.devtools_worker_token;
- shadow_page_ = std::make_unique<WorkerShadowPage>(this);
+ // |loader_factory| is null since all loads for new scripts go through
+ // ServiceWorkerNetworkProvider::script_loader_factory() rather than the
+ // shadow page's loader. This is different to shared workers, which use the
+ // script loader factory for the main script only, and the shadow page loader
+ // for importScripts().
+ shadow_page_ = std::make_unique<WorkerShadowPage>(
+ this, nullptr /* loader_factory */,
+ std::move(worker_start_data_.privacy_preferences));
WebSettings* settings = shadow_page_->GetSettings();
// Currently we block all mixed-content requests from a ServiceWorker.
@@ -273,6 +281,8 @@ void WebEmbeddedWorkerImpl::OnShadowPageInitialized() {
return;
}
+ // Note: We only get here if this is a new (i.e., not installed) service
+ // worker.
DCHECK(!main_script_loader_);
main_script_loader_ = WorkerClassicScriptLoader::Create();
main_script_loader_->LoadAsynchronously(
@@ -283,7 +293,7 @@ void WebEmbeddedWorkerImpl::OnShadowPageInitialized() {
worker_start_data_.address_space, base::OnceClosure(),
Bind(&WebEmbeddedWorkerImpl::OnScriptLoaderFinished,
WTF::Unretained(this)));
- // Do nothing here since onScriptLoaderFinished() might have been already
+ // Do nothing here since OnScriptLoaderFinished() might have been already
// invoked and |this| might have been deleted at this point.
}
@@ -340,7 +350,8 @@ void WebEmbeddedWorkerImpl::StartWorkerThread() {
worker_clients, worker_context_client_->CreateServiceWorkerProvider());
std::unique_ptr<WebWorkerFetchContext> web_worker_fetch_context =
- worker_context_client_->CreateServiceWorkerFetchContext();
+ worker_context_client_->CreateServiceWorkerFetchContext(
+ shadow_page_->DocumentLoader()->GetServiceWorkerNetworkProvider());
// |web_worker_fetch_context| is null in some unit tests.
if (web_worker_fetch_context) {
ProvideWorkerFetchContextToWorker(worker_clients,
@@ -369,7 +380,7 @@ void WebEmbeddedWorkerImpl::StartWorkerThread() {
global_scope_creation_params = std::make_unique<GlobalScopeCreationParams>(
worker_start_data_.script_url, script_type,
worker_start_data_.user_agent,
- document->GetContentSecurityPolicy()->Headers().get(),
+ document->GetContentSecurityPolicy()->Headers(),
document->GetReferrerPolicy(), starter_origin, starter_secure_context,
worker_clients, main_script_loader_->ResponseAddressSpace(),
main_script_loader_->OriginTrialTokens(), devtools_worker_token_,
@@ -386,7 +397,7 @@ void WebEmbeddedWorkerImpl::StartWorkerThread() {
// script.
global_scope_creation_params = std::make_unique<GlobalScopeCreationParams>(
worker_start_data_.script_url, script_type,
- worker_start_data_.user_agent, nullptr /* ContentSecurityPolicy */,
+ worker_start_data_.user_agent, Vector<CSPHeaderAndType>(),
kReferrerPolicyDefault, starter_origin, starter_secure_context,
worker_clients, worker_start_data_.address_space,
nullptr /* OriginTrialTokens */, devtools_worker_token_,
diff --git a/chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h b/chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h
index 1111abbd3b2..d8d935f1bfc 100644
--- a/chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h
+++ b/chromium/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h
@@ -41,7 +41,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/modules/modules_export.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_content_settings_proxy.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_content_settings_proxy.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/exported/web_speech_grammar.cc b/chromium/third_party/blink/renderer/modules/exported/web_speech_grammar.cc
deleted file mode 100644
index ef6e7dcd069..00000000000
--- a/chromium/third_party/blink/renderer/modules/exported/web_speech_grammar.cc
+++ /dev/null
@@ -1,56 +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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/public/web/web_speech_grammar.h"
-
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/modules/speech/speech_grammar.h"
-
-namespace blink {
-
-void WebSpeechGrammar::Reset() {
- private_.Reset();
-}
-
-void WebSpeechGrammar::Assign(const WebSpeechGrammar& other) {
- private_ = other.private_;
-}
-
-WebSpeechGrammar& WebSpeechGrammar::operator=(SpeechGrammar* value) {
- private_ = value;
- return *this;
-}
-
-WebURL WebSpeechGrammar::Src() const {
- DCHECK(private_.Get());
- return private_->src();
-}
-
-float WebSpeechGrammar::Weight() const {
- DCHECK(private_.Get());
- return private_->weight();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/exported/web_speech_recognition_handle.cc b/chromium/third_party/blink/renderer/modules/exported/web_speech_recognition_handle.cc
deleted file mode 100644
index 1278205b9cd..00000000000
--- a/chromium/third_party/blink/renderer/modules/exported/web_speech_recognition_handle.cc
+++ /dev/null
@@ -1,59 +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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/public/web/web_speech_recognition_handle.h"
-
-#include "third_party/blink/renderer/modules/speech/speech_recognition.h"
-
-namespace blink {
-
-void WebSpeechRecognitionHandle::Reset() {
- private_.Reset();
-}
-
-void WebSpeechRecognitionHandle::Assign(
- const WebSpeechRecognitionHandle& other) {
- private_ = other.private_;
-}
-
-bool WebSpeechRecognitionHandle::Equals(
- const WebSpeechRecognitionHandle& other) const {
- return private_.Get() == other.private_.Get();
-}
-
-bool WebSpeechRecognitionHandle::LessThan(
- const WebSpeechRecognitionHandle& other) const {
- return private_.Get() < other.private_.Get();
-}
-
-WebSpeechRecognitionHandle::WebSpeechRecognitionHandle(
- SpeechRecognition* speech_recognition)
- : private_(speech_recognition) {}
-
-WebSpeechRecognitionHandle::operator SpeechRecognition*() const {
- return private_.Get();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/exported/web_speech_recognition_result.cc b/chromium/third_party/blink/renderer/modules/exported/web_speech_recognition_result.cc
deleted file mode 100644
index d2591209c81..00000000000
--- a/chromium/third_party/blink/renderer/modules/exported/web_speech_recognition_result.cc
+++ /dev/null
@@ -1,63 +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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/public/web/web_speech_recognition_result.h"
-
-#include "third_party/blink/renderer/modules/speech/speech_recognition_alternative.h"
-#include "third_party/blink/renderer/modules/speech/speech_recognition_result.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-void WebSpeechRecognitionResult::Assign(
- const WebSpeechRecognitionResult& other) {
- private_ = other.private_;
-}
-
-void WebSpeechRecognitionResult::Assign(const WebVector<WebString>& transcripts,
- const WebVector<float>& confidences,
- bool final) {
- DCHECK_EQ(transcripts.size(), confidences.size());
-
- HeapVector<Member<SpeechRecognitionAlternative>> alternatives(
- transcripts.size());
- for (size_t i = 0; i < transcripts.size(); ++i) {
- alternatives[i] =
- SpeechRecognitionAlternative::Create(transcripts[i], confidences[i]);
- }
-
- private_ = SpeechRecognitionResult::Create(alternatives, final);
-}
-
-void WebSpeechRecognitionResult::Reset() {
- private_.Reset();
-}
-
-WebSpeechRecognitionResult::operator SpeechRecognitionResult*() const {
- return private_.Get();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/exported/web_speech_recognizer_client.cc b/chromium/third_party/blink/renderer/modules/exported/web_speech_recognizer_client.cc
deleted file mode 100644
index 8aa1aebe3cb..00000000000
--- a/chromium/third_party/blink/renderer/modules/exported/web_speech_recognizer_client.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/web/web_speech_recognizer_client.h"
-
-#include "third_party/blink/public/web/web_speech_recognition_handle.h"
-#include "third_party/blink/renderer/modules/speech/speech_recognition_client_proxy.h"
-
-namespace blink {
-
-WebSpeechRecognizerClient::WebSpeechRecognizerClient(
- SpeechRecognitionClientProxy* proxy)
- : private_(proxy) {}
-
-WebSpeechRecognizerClient::~WebSpeechRecognizerClient() {
- Reset();
-}
-
-bool WebSpeechRecognizerClient::operator==(
- const WebSpeechRecognizerClient& other) const {
- return private_.Get() == other.private_.Get();
-}
-
-bool WebSpeechRecognizerClient::operator!=(
- const WebSpeechRecognizerClient& other) const {
- return !operator==(other);
-}
-
-void WebSpeechRecognizerClient::Reset() {
- private_.Reset();
-}
-
-void WebSpeechRecognizerClient::Assign(const WebSpeechRecognizerClient& other) {
- private_ = other.private_;
-}
-
-void WebSpeechRecognizerClient::DidStartAudio(
- const WebSpeechRecognitionHandle& handle) {
- DCHECK(!private_.IsNull());
- private_->DidStartAudio(handle);
-}
-
-void WebSpeechRecognizerClient::DidStartSound(
- const WebSpeechRecognitionHandle& handle) {
- DCHECK(!private_.IsNull());
- private_->DidStartSound(handle);
-}
-
-void WebSpeechRecognizerClient::DidEndSound(
- const WebSpeechRecognitionHandle& handle) {
- DCHECK(!private_.IsNull());
- private_->DidEndSound(handle);
-}
-
-void WebSpeechRecognizerClient::DidEndAudio(
- const WebSpeechRecognitionHandle& handle) {
- DCHECK(!private_.IsNull());
- private_->DidEndAudio(handle);
-}
-
-void WebSpeechRecognizerClient::DidReceiveResults(
- const WebSpeechRecognitionHandle& handle,
- const WebVector<WebSpeechRecognitionResult>& new_final_results,
- const WebVector<WebSpeechRecognitionResult>& current_interim_results) {
- DCHECK(!private_.IsNull());
- private_->DidReceiveResults(handle, new_final_results,
- current_interim_results);
-}
-
-void WebSpeechRecognizerClient::DidReceiveNoMatch(
- const WebSpeechRecognitionHandle& handle,
- const WebSpeechRecognitionResult& result) {
- DCHECK(!private_.IsNull());
- private_->DidReceiveNoMatch(handle, result);
-}
-
-void WebSpeechRecognizerClient::DidReceiveError(
- const WebSpeechRecognitionHandle& handle,
- const WebString& message,
- ErrorCode error_code) {
- DCHECK(!private_.IsNull());
- private_->DidReceiveError(handle, message, error_code);
-}
-
-void WebSpeechRecognizerClient::DidStart(
- const WebSpeechRecognitionHandle& handle) {
- DCHECK(!private_.IsNull());
- private_->DidStart(handle);
-}
-
-void WebSpeechRecognizerClient::DidEnd(
- const WebSpeechRecognitionHandle& handle) {
- DCHECK(!private_.IsNull());
- private_->DidEnd(handle);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/directory_entry_sync.cc b/chromium/third_party/blink/renderer/modules/filesystem/directory_entry_sync.cc
index 0532d03c4ad..1c59373eca3 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/directory_entry_sync.cc
+++ b/chromium/third_party/blink/renderer/modules/filesystem/directory_entry_sync.cc
@@ -30,13 +30,12 @@
#include "third_party/blink/renderer/modules/filesystem/directory_entry_sync.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/modules/filesystem/directory_reader_sync.h"
#include "third_party/blink/renderer/modules/filesystem/entry.h"
#include "third_party/blink/renderer/modules/filesystem/file_entry_sync.h"
#include "third_party/blink/renderer/modules/filesystem/file_system_flags.h"
#include "third_party/blink/renderer/modules/filesystem/sync_callback_helper.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/directory_reader.cc b/chromium/third_party/blink/renderer/modules/filesystem/directory_reader.cc
index e723ce3e56e..607b4444dae 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/directory_reader.cc
+++ b/chromium/third_party/blink/renderer/modules/filesystem/directory_reader.cc
@@ -33,6 +33,7 @@
#include "third_party/blink/renderer/core/fileapi/file_error.h"
#include "third_party/blink/renderer/modules/filesystem/entry.h"
#include "third_party/blink/renderer/modules/filesystem/file_system_callbacks.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/directory_reader_sync.cc b/chromium/third_party/blink/renderer/modules/filesystem/directory_reader_sync.cc
index 3397b21d67d..c858480e039 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/directory_reader_sync.cc
+++ b/chromium/third_party/blink/renderer/modules/filesystem/directory_reader_sync.cc
@@ -30,12 +30,12 @@
#include "third_party/blink/renderer/modules/filesystem/directory_reader_sync.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/modules/filesystem/directory_entry.h"
#include "third_party/blink/renderer/modules/filesystem/directory_entry_sync.h"
#include "third_party/blink/renderer/modules/filesystem/entry_sync.h"
#include "third_party/blink/renderer/modules/filesystem/file_entry_sync.h"
#include "third_party/blink/renderer/modules/filesystem/file_system_callbacks.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/dom_file_system_sync.cc b/chromium/third_party/blink/renderer/modules/filesystem/dom_file_system_sync.cc
index db71fbd7121..4bcbb4d3797 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/dom_file_system_sync.cc
+++ b/chromium/third_party/blink/renderer/modules/filesystem/dom_file_system_sync.cc
@@ -35,7 +35,6 @@
#include "base/memory/ptr_util.h"
#include "third_party/blink/public/platform/web_file_system.h"
#include "third_party/blink/public/platform/web_file_system_callbacks.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/modules/filesystem/directory_entry_sync.h"
@@ -44,6 +43,7 @@
#include "third_party/blink/renderer/modules/filesystem/file_system_callbacks.h"
#include "third_party/blink/renderer/modules/filesystem/file_writer_sync.h"
#include "third_party/blink/renderer/modules/filesystem/sync_callback_helper.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/file_metadata.h"
namespace blink {
@@ -146,8 +146,9 @@ File* DOMFileSystemSync::CreateFile(const FileEntrySync* file_entry,
file_system_url, CreateFileHelper::Create(result, file_entry->name(),
file_system_url, GetType()));
if (result->failed_) {
- exception_state.ThrowDOMException(
- result->code_, "Could not create '" + file_entry->name() + "'.");
+ FileError::ThrowDOMException(
+ exception_state, static_cast<FileError::ErrorCode>(result->code_),
+ "Could not create '" + file_entry->name() + "'.");
return nullptr;
}
return result->file_.Get();
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/entry_sync.cc b/chromium/third_party/blink/renderer/modules/filesystem/entry_sync.cc
index c42435166a8..fe272eda7b1 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/entry_sync.cc
+++ b/chromium/third_party/blink/renderer/modules/filesystem/entry_sync.cc
@@ -30,14 +30,13 @@
#include "third_party/blink/renderer/modules/filesystem/entry_sync.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/modules/filesystem/directory_entry.h"
#include "third_party/blink/renderer/modules/filesystem/directory_entry_sync.h"
#include "third_party/blink/renderer/modules/filesystem/dom_file_path.h"
#include "third_party/blink/renderer/modules/filesystem/file_entry_sync.h"
#include "third_party/blink/renderer/modules/filesystem/metadata.h"
#include "third_party/blink/renderer/modules/filesystem/sync_callback_helper.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/file_entry_sync.cc b/chromium/third_party/blink/renderer/modules/filesystem/file_entry_sync.cc
index 3870cda9753..7081923ee00 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/file_entry_sync.cc
+++ b/chromium/third_party/blink/renderer/modules/filesystem/file_entry_sync.cc
@@ -30,9 +30,9 @@
#include "third_party/blink/renderer/modules/filesystem/file_entry_sync.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/fileapi/file.h"
#include "third_party/blink/renderer/modules/filesystem/file_writer_sync.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc b/chromium/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc
index dd225f05902..49f8b95e141 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc
+++ b/chromium/third_party/blink/renderer/modules/filesystem/file_system_callbacks.cc
@@ -47,6 +47,7 @@
#include "third_party/blink/renderer/modules/filesystem/file_writer.h"
#include "third_party/blink/renderer/modules/filesystem/metadata.h"
#include "third_party/blink/renderer/platform/file_metadata.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/file_writer.cc b/chromium/third_party/blink/renderer/modules/filesystem/file_writer.cc
index bbab3e38155..1736ebc2407 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/file_writer.cc
+++ b/chromium/third_party/blink/renderer/modules/filesystem/file_writer.cc
@@ -32,10 +32,10 @@
#include "third_party/blink/public/platform/web_file_writer.h"
#include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/events/progress_event.h"
#include "third_party/blink/renderer/core/fileapi/blob.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/file_writer_sync.cc b/chromium/third_party/blink/renderer/modules/filesystem/file_writer_sync.cc
index 47cb260e1a7..85377d37a0e 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/file_writer_sync.cc
+++ b/chromium/third_party/blink/renderer/modules/filesystem/file_writer_sync.cc
@@ -32,9 +32,8 @@
#include "third_party/blink/public/platform/web_file_writer.h"
#include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/fileapi/blob.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -66,7 +65,7 @@ void FileWriterSync::truncate(long long offset,
DCHECK(Writer());
DCHECK(complete_);
if (offset < 0) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
FileError::kInvalidStateErrorMessage);
return;
}
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/local_file_system.cc b/chromium/third_party/blink/renderer/modules/filesystem/local_file_system.cc
index d1fea9c69d8..18a481a788a 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/local_file_system.cc
+++ b/chromium/third_party/blink/renderer/modules/filesystem/local_file_system.cc
@@ -188,11 +188,6 @@ void LocalFileSystem::Trace(blink::Visitor* visitor) {
Supplement<WorkerClients>::Trace(visitor);
}
-void LocalFileSystem::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- Supplement<LocalFrame>::TraceWrappers(visitor);
- Supplement<WorkerClients>::TraceWrappers(visitor);
-}
-
const char LocalFileSystem::kSupplementName[] = "LocalFileSystem";
LocalFileSystem* LocalFileSystem::From(ExecutionContext& context) {
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/local_file_system.h b/chromium/third_party/blink/renderer/modules/filesystem/local_file_system.h
index 6c8e1b42997..10289752635 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/local_file_system.h
+++ b/chromium/third_party/blink/renderer/modules/filesystem/local_file_system.h
@@ -34,6 +34,7 @@
#include <memory>
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/workers/worker_clients.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/file_system_type.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/supplementable.h"
@@ -52,7 +53,7 @@ class WebFileSystem;
class LocalFileSystem final : public GarbageCollectedFinalized<LocalFileSystem>,
public Supplement<LocalFrame>,
public Supplement<WorkerClients>,
- public TraceWrapperBase {
+ public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(LocalFileSystem);
WTF_MAKE_NONCOPYABLE(LocalFileSystem);
@@ -76,7 +77,6 @@ class LocalFileSystem final : public GarbageCollectedFinalized<LocalFileSystem>,
static LocalFileSystem* From(ExecutionContext&);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override { return "LocalFileSystem"; }
private:
diff --git a/chromium/third_party/blink/renderer/modules/filesystem/worker_global_scope_file_system.cc b/chromium/third_party/blink/renderer/modules/filesystem/worker_global_scope_file_system.cc
index 34a8d381147..f7c40b2fbab 100644
--- a/chromium/third_party/blink/renderer/modules/filesystem/worker_global_scope_file_system.cc
+++ b/chromium/third_party/blink/renderer/modules/filesystem/worker_global_scope_file_system.cc
@@ -29,8 +29,6 @@
#include <memory>
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/fileapi/file_error.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
@@ -41,6 +39,7 @@
#include "third_party/blink/renderer/modules/filesystem/file_system_callbacks.h"
#include "third_party/blink/renderer/modules/filesystem/local_file_system.h"
#include "third_party/blink/renderer/modules/filesystem/sync_callback_helper.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/file_system_type.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -95,7 +94,7 @@ DOMFileSystemSync* WorkerGlobalScopeFileSystem::webkitRequestFileSystemSync(
FileSystemType file_system_type = static_cast<FileSystemType>(type);
if (!DOMFileSystemBase::IsValidType(file_system_type)) {
exception_state.ThrowDOMException(
- kInvalidModificationError,
+ DOMExceptionCode::kInvalidModificationError,
"the type must be kTemporary or kPersistent.");
return nullptr;
}
@@ -160,7 +159,7 @@ EntrySync* WorkerGlobalScopeFileSystem::webkitResolveLocalFileSystemSyncURL(
}
if (!completed_url.IsValid()) {
- exception_state.ThrowDOMException(kEncodingError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kEncodingError,
"the URL '" + url + "' is invalid.");
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/BUILD.gn b/chromium/third_party/blink/renderer/modules/gamepad/BUILD.gn
index a00b583a330..2545e1c57c2 100644
--- a/chromium/third_party/blink/renderer/modules/gamepad/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/gamepad/BUILD.gn
@@ -20,6 +20,8 @@ blink_modules_sources("gamepad") {
"gamepad_list.h",
"gamepad_pose.cc",
"gamepad_pose.h",
+ "gamepad_shared_memory_reader.cc",
+ "gamepad_shared_memory_reader.h",
"navigator_gamepad.cc",
"navigator_gamepad.h",
]
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/DEPS b/chromium/third_party/blink/renderer/modules/gamepad/DEPS
index d605f2761e2..2fa9b45716d 100644
--- a/chromium/third_party/blink/renderer/modules/gamepad/DEPS
+++ b/chromium/third_party/blink/renderer/modules/gamepad/DEPS
@@ -1,15 +1,19 @@
include_rules = [
+ "+device/base/synchronization/shared_memory_seqlock_buffer.h",
# NOTE: These files are POD structs used to interpret shared memory across
# the Device Gamepad implementation and the Blink client.
"+device/gamepad/public/cpp/gamepad.h",
"+device/gamepad/public/cpp/gamepads.h",
"+device/gamepad/public/mojom/gamepad.mojom-blink.h",
-
+ "+device/gamepad/public/mojom/gamepad_hardware_buffer.h",
+ "+mojo/public/cpp/bindings/binding.h",
+ "+mojo/public/cpp/system/buffer.h",
"-third_party/blink/renderer/modules",
"+third_party/blink/renderer/modules/event_modules.h",
"+third_party/blink/renderer/modules/gamepad",
"+third_party/blink/renderer/modules/modules_export.h",
+ "+third_party/blink/renderer/platform/wtf/noncopyable.h",
# For shared metrics.
"+third_party/blink/renderer/modules/vr/navigator_vr.h",
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/gamepad.cc b/chromium/third_party/blink/renderer/modules/gamepad/gamepad.cc
index 78a0e44bd5c..b131b170f05 100644
--- a/chromium/third_party/blink/renderer/modules/gamepad/gamepad.cc
+++ b/chromium/third_party/blink/renderer/modules/gamepad/gamepad.cc
@@ -31,7 +31,7 @@ namespace blink {
Gamepad::Gamepad()
: index_(0),
- timestamp_(0),
+ timestamp_(0.0),
display_id_(0),
is_axis_data_dirty_(true),
is_button_data_dirty_(true) {}
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/gamepad.h b/chromium/third_party/blink/renderer/modules/gamepad/gamepad.h
index d7a36fbc5bd..e4141d5422b 100644
--- a/chromium/third_party/blink/renderer/modules/gamepad/gamepad.h
+++ b/chromium/third_party/blink/renderer/modules/gamepad/gamepad.h
@@ -27,6 +27,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_GAMEPAD_GAMEPAD_H_
#include "device/gamepad/public/cpp/gamepad.h"
+#include "third_party/blink/renderer/core/dom/dom_high_res_time_stamp.h"
#include "third_party/blink/renderer/modules/gamepad/gamepad_button.h"
#include "third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.h"
#include "third_party/blink/renderer/modules/gamepad/gamepad_pose.h"
@@ -55,8 +56,8 @@ class Gamepad final : public ScriptWrappable {
bool connected() const { return connected_; }
void SetConnected(bool val) { connected_ = val; }
- unsigned long long timestamp() const { return timestamp_; }
- void SetTimestamp(unsigned long long val) { timestamp_ = val; }
+ DOMHighResTimeStamp timestamp() const { return timestamp_; }
+ void SetTimestamp(DOMHighResTimeStamp val) { timestamp_ = val; }
const String& mapping() const { return mapping_; }
void SetMapping(const String& val) { mapping_ = val; }
@@ -91,7 +92,7 @@ class Gamepad final : public ScriptWrappable {
String id_;
unsigned index_;
bool connected_;
- unsigned long long timestamp_;
+ DOMHighResTimeStamp timestamp_;
String mapping_;
DoubleVector axes_;
GamepadButtonVector buttons_;
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/gamepad.idl b/chromium/third_party/blink/renderer/modules/gamepad/gamepad.idl
index c4d1ea464bc..4d5cc263263 100644
--- a/chromium/third_party/blink/renderer/modules/gamepad/gamepad.idl
+++ b/chromium/third_party/blink/renderer/modules/gamepad/gamepad.idl
@@ -34,7 +34,7 @@ interface Gamepad {
readonly attribute DOMString id;
readonly attribute unsigned long index;
readonly attribute boolean connected;
- readonly attribute unsigned long long timestamp;
+ readonly attribute DOMHighResTimeStamp timestamp;
readonly attribute DOMString mapping;
[CachedAttribute=isAxisDataDirty, MeasureAs=GamepadAxes] readonly attribute FrozenArray<double> axes;
[CachedAttribute=isButtonDataDirty, MeasureAs=GamepadButtons] readonly attribute FrozenArray<GamepadButton> buttons;
@@ -43,7 +43,7 @@ interface Gamepad {
// https://github.com/w3c/gamepad/pull/68
[RuntimeEnabled=GamepadVibration, MeasureAs=GamepadVibrationActuator] readonly attribute GamepadHapticActuator? vibrationActuator;
- [OriginTrialEnabled=GamepadExtensions, MeasureAs=GamepadPose] readonly attribute GamepadPose? pose;
+ [RuntimeEnabled=GamepadExtensions, MeasureAs=GamepadPose] readonly attribute GamepadPose? pose;
[OriginTrialEnabled=WebXRGamepadSupport, MeasureAs=GamepadHand] readonly attribute GamepadHand hand;
// https://w3c.github.io/webvr/#interface-gamepad
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.cc b/chromium/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.cc
index e55344aff00..20abe6a14d9 100644
--- a/chromium/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.cc
+++ b/chromium/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.h"
#include "third_party/blink/renderer/modules/gamepad/navigator_gamepad.h"
namespace blink {
@@ -19,7 +20,9 @@ GamepadDispatcher& GamepadDispatcher::Instance() {
}
void GamepadDispatcher::SampleGamepads(device::Gamepads& gamepads) {
- Platform::Current()->SampleGamepads(gamepads);
+ if (reader_) {
+ reader_->SampleGamepads(gamepads);
+ }
}
void GamepadDispatcher::PlayVibrationEffectOnce(
@@ -72,17 +75,22 @@ void GamepadDispatcher::DispatchDidConnectOrDisconnectGamepad(
DCHECK(index < device::Gamepads::kItemsLengthCap);
DCHECK_EQ(connected, gamepad.connected);
- latest_change_.pad = gamepad;
- latest_change_.index = index;
NotifyControllers();
}
-void GamepadDispatcher::StartListening() {
- Platform::Current()->StartListening(kWebPlatformEventTypeGamepad, this);
+void GamepadDispatcher::StartListening(LocalFrame* frame) {
+ if (!reader_) {
+ // TODO(crbug.com/850619): ensure a valid frame is passed
+ if (!frame)
+ return;
+ reader_ = std::make_unique<GamepadSharedMemoryReader>(*frame);
+ }
+ reader_->Start(this);
}
void GamepadDispatcher::StopListening() {
- Platform::Current()->StopListening(kWebPlatformEventTypeGamepad);
+ if (reader_)
+ reader_->Stop();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h b/chromium/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h
index 686096cdf96..381b073c6c9 100644
--- a/chromium/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h
+++ b/chromium/third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h
@@ -13,6 +13,8 @@
namespace blink {
+class GamepadSharedMemoryReader;
+
class GamepadDispatcher final
: public GarbageCollectedFinalized<GamepadDispatcher>,
public PlatformEventDispatcher,
@@ -34,16 +36,6 @@ class GamepadDispatcher final
device::mojom::blink::GamepadHapticsManager::
ResetVibrationActuatorCallback);
- struct ConnectionChange {
- DISALLOW_NEW();
- device::Gamepad pad;
- unsigned index;
- };
-
- const ConnectionChange& LatestConnectionChange() const {
- return latest_change_;
- }
-
void Trace(blink::Visitor*) override;
private:
@@ -56,15 +48,14 @@ class GamepadDispatcher final
void DidDisconnectGamepad(unsigned index, const device::Gamepad&) override;
// PlatformEventDispatcher
- void StartListening() override;
+ void StartListening(LocalFrame* frame) override;
void StopListening() override;
void DispatchDidConnectOrDisconnectGamepad(unsigned index,
const device::Gamepad&,
bool connected);
- ConnectionChange latest_change_;
-
+ std::unique_ptr<GamepadSharedMemoryReader> reader_;
device::mojom::blink::GamepadHapticsManagerPtr gamepad_haptics_manager_;
};
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc b/chromium/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc
index c8aef48b1d5..9b353880ce5 100644
--- a/chromium/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc
+++ b/chromium/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace {
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/gamepad_pose.idl b/chromium/third_party/blink/renderer/modules/gamepad/gamepad_pose.idl
index 05495f25d8c..e9f87f53295 100644
--- a/chromium/third_party/blink/renderer/modules/gamepad/gamepad_pose.idl
+++ b/chromium/third_party/blink/renderer/modules/gamepad/gamepad_pose.idl
@@ -4,7 +4,7 @@
// https://w3c.github.io/gamepad/extensions.html#gamepadpose-interface
[
- OriginTrialEnabled=GamepadExtensions
+ RuntimeEnabled=GamepadExtensions
] interface GamepadPose {
[MeasureAs=GamepadPoseHasOrientation] readonly attribute boolean hasOrientation;
[MeasureAs=GamepadPoseHasPosition] readonly attribute boolean hasPosition;
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.cc b/chromium/third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.cc
new file mode 100644
index 00000000000..5b8aac1da21
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.cc
@@ -0,0 +1,140 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.h"
+#include "base/metrics/histogram_macros.h"
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/platform/interface_provider.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+
+namespace blink {
+
+GamepadSharedMemoryReader::GamepadSharedMemoryReader(LocalFrame& frame)
+ : binding_(this) {
+ frame.GetInterfaceProvider().GetInterface(
+ mojo::MakeRequest(&gamepad_monitor_));
+ device::mojom::blink::GamepadObserverPtr observer;
+ binding_.Bind(mojo::MakeRequest(&observer));
+ gamepad_monitor_->SetObserver(std::move(observer));
+}
+
+void GamepadSharedMemoryReader::SendStartMessage() {
+ if (gamepad_monitor_) {
+ gamepad_monitor_->GamepadStartPolling(&renderer_shared_buffer_region_);
+ }
+}
+
+void GamepadSharedMemoryReader::SendStopMessage() {
+ if (gamepad_monitor_) {
+ gamepad_monitor_->GamepadStopPolling();
+ }
+}
+
+void GamepadSharedMemoryReader::Start(blink::WebGamepadListener* listener) {
+ DCHECK(!listener_);
+ listener_ = listener;
+
+ SendStartMessage();
+
+ // If we don't get a valid handle from the browser, don't try to Map (we're
+ // probably out of memory or file handles).
+ bool is_valid = renderer_shared_buffer_region_.IsValid();
+ UMA_HISTOGRAM_BOOLEAN("Gamepad.ValidSharedMemoryHandle", is_valid);
+
+ if (!is_valid)
+ return;
+
+ renderer_shared_buffer_mapping_ = renderer_shared_buffer_region_.Map();
+ CHECK(renderer_shared_buffer_mapping_.IsValid());
+ const void* memory = renderer_shared_buffer_mapping_.memory();
+ CHECK(memory);
+ gamepad_hardware_buffer_ =
+ static_cast<const device::GamepadHardwareBuffer*>(memory);
+}
+
+void GamepadSharedMemoryReader::Stop() {
+ DCHECK(listener_);
+ listener_ = nullptr;
+ renderer_shared_buffer_region_ = base::ReadOnlySharedMemoryRegion();
+ renderer_shared_buffer_mapping_ = base::ReadOnlySharedMemoryMapping();
+ gamepad_hardware_buffer_ = nullptr;
+
+ SendStopMessage();
+}
+
+void GamepadSharedMemoryReader::SampleGamepads(device::Gamepads& gamepads) {
+ // Blink should have started observing at this point.
+ CHECK(listener_);
+
+ // ==========
+ // DANGER
+ // ==========
+ //
+ // This logic is duplicated in Pepper as well. If you change it, that also
+ // needs to be in sync. See ppapi/proxy/gamepad_resource.cc.
+ device::Gamepads read_into;
+ TRACE_EVENT0("GAMEPAD", "SampleGamepads");
+
+ if (!renderer_shared_buffer_region_.IsValid())
+ return;
+
+ // Only try to read this many times before failing to avoid waiting here
+ // very long in case of contention with the writer. TODO(scottmg) Tune this
+ // number (as low as 1?) if histogram shows distribution as mostly
+ // 0-and-maximum.
+ const int kMaximumContentionCount = 10;
+ int contention_count = -1;
+ base::subtle::Atomic32 version;
+ do {
+ version = gamepad_hardware_buffer_->seqlock.ReadBegin();
+ memcpy(&read_into, &gamepad_hardware_buffer_->data, sizeof(read_into));
+ ++contention_count;
+ if (contention_count == kMaximumContentionCount)
+ break;
+ } while (gamepad_hardware_buffer_->seqlock.ReadRetry(version));
+ UMA_HISTOGRAM_COUNTS("Gamepad.ReadContentionCount", contention_count);
+
+ if (contention_count >= kMaximumContentionCount) {
+ // We failed to successfully read, presumably because the hardware
+ // thread was taking unusually long. Don't copy the data to the output
+ // buffer, and simply leave what was there before.
+ return;
+ }
+
+ // New data was read successfully, copy it into the output buffer.
+ memcpy(&gamepads, &read_into, sizeof(gamepads));
+
+ if (!ever_interacted_with_) {
+ // Clear the connected flag if the user hasn't interacted with any of the
+ // gamepads to prevent fingerprinting. The actual data is not cleared.
+ // WebKit will only copy out data into the JS buffers for connected
+ // gamepads so this is sufficient.
+ for (unsigned i = 0; i < device::Gamepads::kItemsLengthCap; i++)
+ gamepads.items[i].connected = false;
+ }
+}
+
+GamepadSharedMemoryReader::~GamepadSharedMemoryReader() {
+ if (listener_)
+ Stop();
+}
+
+void GamepadSharedMemoryReader::GamepadConnected(
+ int index,
+ const device::Gamepad& gamepad) {
+ // The browser already checks if the user actually interacted with a device.
+ ever_interacted_with_ = true;
+
+ if (listener_)
+ listener_->DidConnectGamepad(index, gamepad);
+}
+
+void GamepadSharedMemoryReader::GamepadDisconnected(
+ int index,
+ const device::Gamepad& gamepad) {
+ if (listener_)
+ listener_->DidDisconnectGamepad(index, gamepad);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.h b/chromium/third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.h
new file mode 100644
index 00000000000..f1342ccd183
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/gamepad/gamepad_shared_memory_reader.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_GAMEPAD_GAMEPAD_SHARED_MEMORY_READER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_GAMEPAD_GAMEPAD_SHARED_MEMORY_READER_H_
+
+#include <memory>
+
+#include "device/base/synchronization/shared_memory_seqlock_buffer.h"
+#include "device/gamepad/public/cpp/gamepads.h"
+#include "device/gamepad/public/mojom/gamepad.mojom-blink.h"
+#include "device/gamepad/public/mojom/gamepad_hardware_buffer.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/system/buffer.h"
+#include "third_party/blink/public/platform/web_gamepad_listener.h"
+#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
+
+namespace blink {
+
+class LocalFrame;
+
+class GamepadSharedMemoryReader : public device::mojom::blink::GamepadObserver {
+ WTF_MAKE_NONCOPYABLE(GamepadSharedMemoryReader);
+
+ public:
+ explicit GamepadSharedMemoryReader(LocalFrame& frame);
+ ~GamepadSharedMemoryReader() override;
+
+ void SampleGamepads(device::Gamepads& gamepads);
+ void Start(blink::WebGamepadListener* listener);
+ void Stop();
+
+ protected:
+ void SendStartMessage();
+ void SendStopMessage();
+
+ private:
+ // device::mojom::blink::GamepadObserver methods.
+ void GamepadConnected(int index, const device::Gamepad& gamepad) override;
+ void GamepadDisconnected(int index, const device::Gamepad& gamepad) override;
+
+ base::ReadOnlySharedMemoryRegion renderer_shared_buffer_region_;
+ base::ReadOnlySharedMemoryMapping renderer_shared_buffer_mapping_;
+ const device::GamepadHardwareBuffer* gamepad_hardware_buffer_ = nullptr;
+
+ bool ever_interacted_with_ = false;
+
+ mojo::Binding<device::mojom::blink::GamepadObserver> binding_;
+ device::mojom::blink::GamepadMonitorPtr gamepad_monitor_;
+ blink::WebGamepadListener* listener_ = nullptr;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_GAMEPAD_GAMEPAD_SHARED_MEMORY_READER_H_
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc b/chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc
index bf2a00db602..a6e566ae2b4 100644
--- a/chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc
+++ b/chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc
@@ -31,8 +31,10 @@
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/navigator.h"
+#include "third_party/blink/renderer/core/loader/document_loader.h"
#include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
#include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/core/timing/performance.h"
#include "third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h"
#include "third_party/blink/renderer/modules/gamepad/gamepad_event.h"
#include "third_party/blink/renderer/modules/gamepad/gamepad_list.h"
@@ -63,12 +65,14 @@ void HasGamepadConnectionChanged(const String& old_id,
*gamepad_lost = id_changed || (old_connected && !new_connected);
}
-bool HasUserActivation(GamepadList& gamepads) {
+bool HasUserActivation(GamepadList* gamepads) {
+ if (!gamepads)
+ return false;
// A button press counts as a user activation if the button's value is greater
// than the activation threshold. A threshold is used so that analog buttons
// or triggers do not generate an activation from a light touch.
- for (size_t pad_index = 0; pad_index < gamepads.length(); ++pad_index) {
- Gamepad* pad = gamepads.item(pad_index);
+ for (size_t pad_index = 0; pad_index < gamepads->length(); ++pad_index) {
+ Gamepad* pad = gamepads->item(pad_index);
if (pad) {
const GamepadButtonVector& buttons = pad->buttons();
for (size_t i = 0; i < buttons.size(); ++i) {
@@ -86,13 +90,19 @@ bool HasUserActivation(GamepadList& gamepads) {
template <typename T>
static void SampleGamepad(unsigned index,
T& gamepad,
- const device::Gamepad& device_gamepad) {
+ const device::Gamepad& device_gamepad,
+ const TimeTicks& navigation_start) {
String old_id = gamepad.id();
bool old_was_connected = gamepad.connected();
+ TimeTicks last_updated =
+ TimeTicks() + TimeDelta::FromMicroseconds(device_gamepad.timestamp);
+ DOMHighResTimeStamp timestamp =
+ Performance::MonotonicTimeToDOMHighResTimeStamp(navigation_start,
+ last_updated, false);
gamepad.SetId(device_gamepad.id);
gamepad.SetConnected(device_gamepad.connected);
- gamepad.SetTimestamp(device_gamepad.timestamp);
+ gamepad.SetTimestamp(timestamp);
gamepad.SetAxes(device_gamepad.axes_length, device_gamepad.axes);
gamepad.SetButtons(device_gamepad.buttons_length, device_gamepad.buttons);
gamepad.SetPose(device_gamepad.pose);
@@ -108,7 +118,8 @@ static void SampleGamepad(unsigned index,
gamepad.SetIndex(index);
gamepad.SetMapping(device_gamepad.mapping);
gamepad.SetVibrationActuator(device_gamepad.vibration_actuator);
- gamepad.SetDisplayId(device_gamepad.display_id);
+ // Re-map display ids, since we will hand out at most one VRDisplay.
+ gamepad.SetDisplayId(device_gamepad.display_id ? 1 : 0);
} else if (!gamepad.vibrationActuator() &&
device_gamepad.vibration_actuator.not_null) {
// Some gamepads require additional steps to determine haptics capability.
@@ -120,7 +131,9 @@ static void SampleGamepad(unsigned index,
}
template <typename GamepadType, typename ListType>
-static void SampleGamepads(ListType* into, const ExecutionContext* context) {
+static void SampleGamepads(ListType* into,
+ const ExecutionContext* context,
+ const TimeTicks& navigation_start) {
device::Gamepads gamepads;
GamepadDispatcher::Instance().SampleGamepads(gamepads);
@@ -131,9 +144,9 @@ static void SampleGamepads(ListType* into, const ExecutionContext* context) {
bool hide_xr_gamepad = false;
if (web_gamepad.is_xr) {
bool webxr_enabled =
- (context && OriginTrials::webXRGamepadSupportEnabled(context) &&
- OriginTrials::webXREnabled(context));
- bool webvr_enabled = (context && OriginTrials::webVREnabled(context));
+ (context && OriginTrials::WebXRGamepadSupportEnabled(context) &&
+ OriginTrials::WebXREnabled(context));
+ bool webvr_enabled = (context && RuntimeEnabledFeatures::WebVREnabled());
if (!webxr_enabled && !webvr_enabled) {
// If neither WebXR nor WebVR are enabled, we should not expose XR-
@@ -148,7 +161,7 @@ static void SampleGamepads(ListType* into, const ExecutionContext* context) {
GamepadType* gamepad = into->item(i);
if (!gamepad)
gamepad = GamepadType::Create();
- SampleGamepad(i, *gamepad, web_gamepad);
+ SampleGamepad(i, *gamepad, web_gamepad, navigation_start);
into->Set(i, gamepad);
} else {
into->Set(i, nullptr);
@@ -193,9 +206,10 @@ GamepadList* NavigatorGamepad::Gamepads() {
SampleAndCheckConnectedGamepads();
- // Allow gamepad button presses to qualify as user activations.
- if (RuntimeEnabledFeatures::UserActivationV2Enabled() &&
- GetPage()->IsPageVisible() && HasUserActivation(*gamepads_)) {
+ // Allow gamepad button presses to qualify as user activations if the page is
+ // visible.
+ if (RuntimeEnabledFeatures::UserActivationV2Enabled() && GetFrame() &&
+ GetPage() && GetPage()->IsPageVisible() && HasUserActivation(gamepads_)) {
Frame::NotifyUserActivation(GetFrame(), UserGestureToken::kNewGesture);
}
@@ -265,6 +279,14 @@ NavigatorGamepad::NavigatorGamepad(Navigator& navigator)
: nullptr) {
if (navigator.DomWindow())
navigator.DomWindow()->RegisterEventListenerObserver(this);
+
+ // Fetch |window.performance.timing.navigationStart|. Gamepad timestamps are
+ // reported relative to this value.
+ if (GetFrame()) {
+ DocumentLoader* loader = GetFrame()->Loader().GetDocumentLoader();
+ if (loader)
+ navigation_start_ = loader->GetTiming().NavigationStart();
+ }
}
NavigatorGamepad::~NavigatorGamepad() = default;
@@ -340,7 +362,8 @@ void NavigatorGamepad::SampleAndCheckConnectedGamepads() {
// Compare the current sample with the old data and enqueue connection
// events for any differences.
- SampleGamepads<Gamepad>(gamepads_back_.Get(), execution_context);
+ SampleGamepads<Gamepad>(gamepads_back_.Get(), execution_context,
+ navigation_start_);
if (CheckConnectedGamepads(gamepads_.Get(), gamepads_back_.Get())) {
// If we had any disconnected gamepads, we can't overwrite gamepads_
// because the Gamepad object from the old buffer is reused as the
@@ -353,7 +376,8 @@ void NavigatorGamepad::SampleAndCheckConnectedGamepads() {
dispatch_one_event_runner_->RunAsync();
}
}
- SampleGamepads<Gamepad>(gamepads_.Get(), execution_context);
+ SampleGamepads<Gamepad>(gamepads_.Get(), execution_context,
+ navigation_start_);
}
}
diff --git a/chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.h b/chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.h
index 4ed01fbd7d5..a71aa760e07 100644
--- a/chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.h
+++ b/chromium/third_party/blink/renderer/modules/gamepad/navigator_gamepad.h
@@ -27,6 +27,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_GAMEPAD_NAVIGATOR_GAMEPAD_H_
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/core/dom/dom_high_res_time_stamp.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/navigator.h"
#include "third_party/blink/renderer/core/frame/platform_event_controller.h"
@@ -90,6 +91,7 @@ class MODULES_EXPORT NavigatorGamepad final
Member<GamepadList> gamepads_back_;
HeapDeque<Member<Gamepad>> pending_events_;
Member<AsyncMethodRunner<NavigatorGamepad>> dispatch_one_event_runner_;
+ TimeTicks navigation_start_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.cc b/chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.cc
index 101241da09b..ce8d3a7f3cf 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.cc
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/geolocation/geo_notifier.h"
#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/modules/geolocation/geolocation.h"
#include "third_party/blink/renderer/modules/geolocation/position_error.h"
#include "third_party/blink/renderer/modules/geolocation/position_options.h"
@@ -43,11 +44,6 @@ void GeoNotifier::Trace(blink::Visitor* visitor) {
visitor->Trace(fatal_error_);
}
-void GeoNotifier::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(success_callback_);
- visitor->TraceWrappers(error_callback_);
-}
-
void GeoNotifier::SetFatalError(PositionError* error) {
// If a fatal error has already been set, stick with it. This makes sure that
// when permission is denied, this is the error reported, as required by the
@@ -76,7 +72,8 @@ void GeoNotifier::RunErrorCallback(PositionError* error) {
}
void GeoNotifier::StartTimer() {
- timer_->StartOneShot(options_.timeout() / 1000.0, FROM_HERE);
+ timer_->StartOneShot(TimeDelta::FromMilliseconds(options_.timeout()),
+ FROM_HERE);
}
void GeoNotifier::StopTimer() {
@@ -97,12 +94,6 @@ void GeoNotifier::Timer::StartOneShot(TimeDelta interval,
timer_.StartOneShot(interval, caller);
}
-void GeoNotifier::Timer::StartOneShot(double interval,
- const base::Location& caller) {
- DCHECK(notifier_->geolocation_->DoesOwnNotifier(notifier_));
- timer_.StartOneShot(interval, caller);
-}
-
void GeoNotifier::Timer::Stop() {
DCHECK(notifier_->geolocation_->DoesOwnNotifier(notifier_));
timer_.Stop();
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.h b/chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.h
index da39bdbf7a5..b50ede3a0f5 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.h
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geo_notifier.h
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_position_callback.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_position_error_callback.h"
#include "third_party/blink/renderer/modules/geolocation/position_options.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/timer.h"
@@ -20,7 +21,7 @@ class Geoposition;
class PositionError;
class GeoNotifier final : public GarbageCollectedFinalized<GeoNotifier>,
- public TraceWrapperBase {
+ public NameClient {
public:
static GeoNotifier* Create(Geolocation* geolocation,
V8PositionCallback* position_callback,
@@ -31,7 +32,6 @@ class GeoNotifier final : public GarbageCollectedFinalized<GeoNotifier>,
}
~GeoNotifier() = default;
void Trace(blink::Visitor*);
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override { return "GeoNotifier"; }
const PositionOptions& Options() const { return options_; }
@@ -71,7 +71,6 @@ class GeoNotifier final : public GarbageCollectedFinalized<GeoNotifier>,
// TimerBase-compatible API
void StartOneShot(TimeDelta interval, const base::Location& caller);
- void StartOneShot(double interval, const base::Location& caller);
void Stop();
bool IsActive() const { return timer_.IsActive(); }
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/geolocation.cc b/chromium/third_party/blink/renderer/modules/geolocation/geolocation.cc
index 1e8911b6ef8..102af1a7056 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/geolocation.cc
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geolocation.cc
@@ -91,7 +91,7 @@ static void ReportGeolocationViolation(ExecutionContext* context) {
PerformanceMonitor::ReportGenericViolation(
context, PerformanceMonitor::kDiscouragedAPIUse,
"Only request geolocation information in response to a user gesture.",
- 0, nullptr);
+ base::TimeDelta(), nullptr);
}
}
@@ -104,7 +104,8 @@ Geolocation* Geolocation::Create(ExecutionContext* context) {
Geolocation::Geolocation(ExecutionContext* context)
: ContextLifecycleObserver(context),
- PageVisibilityObserver(GetDocument()->GetPage()) {}
+ PageVisibilityObserver(GetDocument()->GetPage()),
+ watchers_(new GeolocationWatchers()) {}
Geolocation::~Geolocation() = default;
@@ -119,17 +120,6 @@ void Geolocation::Trace(blink::Visitor* visitor) {
PageVisibilityObserver::Trace(visitor);
}
-void Geolocation::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- for (const auto& one_shot : one_shots_)
- visitor->TraceWrappers(one_shot);
- visitor->TraceWrappers(watchers_);
- for (const auto& one_shot : one_shots_being_invoked_)
- visitor->TraceWrappers(one_shot);
- for (const auto& watcher : watchers_being_invoked_)
- visitor->TraceWrappers(watcher);
- ScriptWrappable::TraceWrappers(visitor);
-}
-
Document* Geolocation::GetDocument() const {
return ToDocument(GetExecutionContext());
}
@@ -141,7 +131,7 @@ LocalFrame* Geolocation::GetFrame() const {
void Geolocation::ContextDestroyed(ExecutionContext*) {
StopTimers();
one_shots_.clear();
- watchers_.Clear();
+ watchers_->Clear();
StopUpdating();
@@ -227,7 +217,7 @@ int Geolocation::watchPosition(V8PositionCallback* success_callback,
// have.
do {
watch_id = GetExecutionContext()->CircularSequentialID();
- } while (!watchers_.Add(watch_id, notifier));
+ } while (!watchers_->Add(watch_id, notifier));
StartRequest(notifier);
@@ -272,7 +262,7 @@ void Geolocation::FatalErrorOccurred(GeoNotifier* notifier) {
// This request has failed fatally. Remove it from our lists.
one_shots_.erase(notifier);
- watchers_.Remove(notifier);
+ watchers_->Remove(notifier);
if (!HasListeners())
StopUpdating();
@@ -287,7 +277,7 @@ void Geolocation::RequestUsesCachedPosition(GeoNotifier* notifier) {
// exists, start the service to get updates.
if (one_shots_.Contains(notifier)) {
one_shots_.erase(notifier);
- } else if (watchers_.Contains(notifier)) {
+ } else if (watchers_->Contains(notifier)) {
if (notifier->Options().timeout() > 0)
StartUpdating(notifier);
notifier->StartTimer();
@@ -310,7 +300,7 @@ void Geolocation::RequestTimedOut(GeoNotifier* notifier) {
bool Geolocation::DoesOwnNotifier(GeoNotifier* notifier) const {
return one_shots_.Contains(notifier) ||
one_shots_being_invoked_.Contains(notifier) ||
- watchers_.Contains(notifier) ||
+ watchers_->Contains(notifier) ||
watchers_being_invoked_.Contains(notifier);
}
@@ -329,12 +319,12 @@ void Geolocation::clearWatch(int watch_id) {
if (watch_id <= 0)
return;
- GeoNotifier* notifier = watchers_.Find(watch_id);
+ GeoNotifier* notifier = watchers_->Find(watch_id);
if (!notifier)
return;
notifier->StopTimer();
- watchers_.Remove(watch_id);
+ watchers_->Remove(watch_id);
if (!HasListeners())
StopUpdating();
@@ -345,7 +335,7 @@ void Geolocation::StopTimers() {
notifier->StopTimer();
}
- for (const auto& notifier : watchers_.Notifiers()) {
+ for (const auto& notifier : watchers_->Notifiers()) {
notifier->StopTimer();
}
}
@@ -368,11 +358,11 @@ void Geolocation::HandleError(PositionError* error) {
// by a callback through getCurrentPosition, watchPosition, and/or
// clearWatch.
swap(one_shots_, one_shots_being_invoked_);
- watchers_.CopyNotifiersToVector(watchers_being_invoked_);
+ watchers_->CopyNotifiersToVector(watchers_being_invoked_);
if (error->IsFatal()) {
// Clear the watchers before invoking the callbacks.
- watchers_.Clear();
+ watchers_->Clear();
}
// Invoke the callbacks. Do not send a non-fatal error to the notifiers
@@ -425,7 +415,7 @@ void Geolocation::MakeSuccessCallbacks() {
// by a callback through getCurrentPosition, watchPosition, and/or
// clearWatch.
swap(one_shots_, one_shots_being_invoked_);
- watchers_.CopyNotifiersToVector(watchers_being_invoked_);
+ watchers_->CopyNotifiersToVector(watchers_being_invoked_);
// Invoke the callbacks.
//
@@ -518,7 +508,7 @@ void Geolocation::PageVisibilityChanged() {
bool Geolocation::HasPendingActivity() const {
return !one_shots_.IsEmpty() || !one_shots_being_invoked_.IsEmpty() ||
- !watchers_.IsEmpty() || !watchers_being_invoked_.IsEmpty();
+ !watchers_->IsEmpty() || !watchers_being_invoked_.IsEmpty();
}
void Geolocation::OnGeolocationConnectionError() {
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/geolocation.h b/chromium/third_party/blink/renderer/modules/geolocation/geolocation.h
index 2fac36a21a9..9a59a4e3f32 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/geolocation.h
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geolocation.h
@@ -29,6 +29,7 @@
#include "services/device/public/mojom/geolocation.mojom-blink.h"
#include "third_party/blink/public/platform/modules/geolocation/geolocation_service.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_position_callback.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_position_error_callback.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
@@ -61,7 +62,6 @@ class MODULES_EXPORT Geolocation final
static Geolocation* Create(ExecutionContext*);
~Geolocation() override;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
// Inherited from ContextLifecycleObserver and PageVisibilityObserver.
void ContextDestroyed(ExecutionContext*) override;
@@ -156,7 +156,7 @@ class MODULES_EXPORT Geolocation final
explicit Geolocation(ExecutionContext*);
bool HasListeners() const {
- return !one_shots_.IsEmpty() || !watchers_.IsEmpty();
+ return !one_shots_.IsEmpty() || !watchers_->IsEmpty();
}
void StopTimers();
@@ -196,7 +196,7 @@ class MODULES_EXPORT Geolocation final
void OnGeolocationConnectionError();
GeoNotifierSet one_shots_;
- GeolocationWatchers watchers_;
+ TraceWrapperMember<GeolocationWatchers> watchers_;
// GeoNotifiers that are in the middle of invocation.
//
// |HandleError(error)| and |MakeSuccessCallbacks| need to clear |one_shots_|
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/geolocation_watchers.cc b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_watchers.cc
index 842cac20dd0..21244f88aea 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/geolocation_watchers.cc
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_watchers.cc
@@ -14,14 +14,6 @@ void GeolocationWatchers::Trace(blink::Visitor* visitor) {
visitor->Trace(notifier_to_id_map_);
}
-void GeolocationWatchers::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- for (const auto& notifier : id_to_notifier_map_.Values())
- visitor->TraceWrappers(notifier);
- // |notifier_to_id_map_| is a HeapHashMap that is the inverse mapping of
- // |id_to_notifier_map_|. As the contents are the same, we don't need to
- // trace |id_to_notifier_map_|.
-}
-
bool GeolocationWatchers::Add(int id, GeoNotifier* notifier) {
DCHECK_GT(id, 0);
if (!id_to_notifier_map_.insert(id, notifier).is_new_entry)
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/geolocation_watchers.h b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_watchers.h
index 0fe30262d26..78bffbda4d9 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/geolocation_watchers.h
+++ b/chromium/third_party/blink/renderer/modules/geolocation/geolocation_watchers.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_GEOLOCATION_WATCHERS_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_GEOLOCATION_WATCHERS_H_
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -12,13 +13,11 @@ namespace blink {
class GeoNotifier;
-class GeolocationWatchers : public TraceWrapperBase {
- DISALLOW_NEW();
-
+class GeolocationWatchers : public GarbageCollected<GeolocationWatchers>,
+ public NameClient {
public:
GeolocationWatchers() = default;
void Trace(blink::Visitor*);
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "GeolocationWatchers";
}
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/navigator_geolocation.cc b/chromium/third_party/blink/renderer/modules/geolocation/navigator_geolocation.cc
index a455f83b7ac..78a4ea18706 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/navigator_geolocation.cc
+++ b/chromium/third_party/blink/renderer/modules/geolocation/navigator_geolocation.cc
@@ -62,10 +62,4 @@ void NavigatorGeolocation::Trace(blink::Visitor* visitor) {
Supplement<Navigator>::Trace(visitor);
}
-void NavigatorGeolocation::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(geolocation_);
- Supplement<Navigator>::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/geolocation/navigator_geolocation.h b/chromium/third_party/blink/renderer/modules/geolocation/navigator_geolocation.h
index 3bbd398821f..00f39e269c7 100644
--- a/chromium/third_party/blink/renderer/modules/geolocation/navigator_geolocation.h
+++ b/chromium/third_party/blink/renderer/modules/geolocation/navigator_geolocation.h
@@ -21,6 +21,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_NAVIGATOR_GEOLOCATION_H_
#include "third_party/blink/renderer/core/frame/navigator.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/supplementable.h"
@@ -33,7 +34,7 @@ class Navigator;
class NavigatorGeolocation final
: public GarbageCollected<NavigatorGeolocation>,
public Supplement<Navigator>,
- public TraceWrapperBase {
+ public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(NavigatorGeolocation);
public:
@@ -44,7 +45,6 @@ class NavigatorGeolocation final
Geolocation* geolocation();
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "NavigatorGeolocation";
}
diff --git a/chromium/third_party/blink/renderer/modules/imagecapture/image_capture.cc b/chromium/third_party/blink/renderer/modules/imagecapture/image_capture.cc
index 110e7964e61..e9d81621b24 100644
--- a/chromium/third_party/blink/renderer/modules/imagecapture/image_capture.cc
+++ b/chromium/third_party/blink/renderer/modules/imagecapture/image_capture.cc
@@ -14,7 +14,6 @@
#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/fileapi/blob.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
@@ -89,7 +88,7 @@ ImageCapture* ImageCapture::Create(ExecutionContext* context,
ExceptionState& exception_state) {
if (track->kind() != "video") {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"Cannot create an ImageCapturer from a non-video Track.");
return nullptr;
}
@@ -127,7 +126,8 @@ ScriptPromise ImageCapture::getPhotoCapabilities(ScriptState* script_state) {
ScriptPromise promise = resolver->Promise();
if (!service_) {
- resolver->Reject(DOMException::Create(kNotFoundError, kNoServiceError));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
+ kNoServiceError));
return promise;
}
service_requests_.insert(resolver);
@@ -152,7 +152,8 @@ ScriptPromise ImageCapture::getPhotoSettings(ScriptState* script_state) {
ScriptPromise promise = resolver->Promise();
if (!service_) {
- resolver->Reject(DOMException::Create(kNotFoundError, kNoServiceError));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
+ kNoServiceError));
return promise;
}
service_requests_.insert(resolver);
@@ -179,13 +180,15 @@ ScriptPromise ImageCapture::setOptions(ScriptState* script_state,
ScriptPromise promise = resolver->Promise();
if (TrackIsInactive(*stream_track_)) {
- resolver->Reject(DOMException::Create(
- kInvalidStateError, "The associated Track is in an invalid state."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "The associated Track is in an invalid state."));
return promise;
}
if (!service_) {
- resolver->Reject(DOMException::Create(kNotFoundError, kNoServiceError));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
+ kNoServiceError));
return promise;
}
service_requests_.insert(resolver);
@@ -199,8 +202,9 @@ ScriptPromise ImageCapture::setOptions(ScriptState* script_state,
if (photo_capabilities_ &&
(height < photo_capabilities_->imageHeight()->min() ||
height > photo_capabilities_->imageHeight()->max())) {
- resolver->Reject(DOMException::Create(
- kNotSupportedError, "imageHeight setting out of range"));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "imageHeight setting out of range"));
return promise;
}
settings->height = height;
@@ -211,8 +215,9 @@ ScriptPromise ImageCapture::setOptions(ScriptState* script_state,
if (photo_capabilities_ &&
(width < photo_capabilities_->imageWidth()->min() ||
width > photo_capabilities_->imageWidth()->max())) {
- resolver->Reject(DOMException::Create(kNotSupportedError,
- "imageWidth setting out of range"));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "imageWidth setting out of range"));
return promise;
}
settings->width = width;
@@ -222,8 +227,9 @@ ScriptPromise ImageCapture::setOptions(ScriptState* script_state,
if (settings->has_red_eye_reduction) {
if (photo_capabilities_ &&
!photo_capabilities_->IsRedEyeReductionControllable()) {
- resolver->Reject(DOMException::Create(
- kNotSupportedError, "redEyeReduction is not controllable."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "redEyeReduction is not controllable."));
return promise;
}
settings->red_eye_reduction = photo_settings.redEyeReduction();
@@ -234,8 +240,8 @@ ScriptPromise ImageCapture::setOptions(ScriptState* script_state,
const String fill_light_mode = photo_settings.fillLightMode();
if (photo_capabilities_ && photo_capabilities_->fillLightMode().Find(
fill_light_mode) == kNotFound) {
- resolver->Reject(DOMException::Create(kNotSupportedError,
- "Unsupported fillLightMode"));
+ resolver->Reject(DOMException::Create(
+ DOMExceptionCode::kNotSupportedError, "Unsupported fillLightMode"));
return promise;
}
settings->fill_light_mode = ParseFillLightMode(fill_light_mode);
@@ -253,12 +259,14 @@ ScriptPromise ImageCapture::takePhoto(ScriptState* script_state) {
ScriptPromise promise = resolver->Promise();
if (TrackIsInactive(*stream_track_)) {
- resolver->Reject(DOMException::Create(
- kInvalidStateError, "The associated Track is in an invalid state."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "The associated Track is in an invalid state."));
return promise;
}
if (!service_) {
- resolver->Reject(DOMException::Create(kNotFoundError, kNoServiceError));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
+ kNoServiceError));
return promise;
}
@@ -286,8 +294,9 @@ ScriptPromise ImageCapture::grabFrame(ScriptState* script_state) {
ScriptPromise promise = resolver->Promise();
if (TrackIsInactive(*stream_track_)) {
- resolver->Reject(DOMException::Create(
- kInvalidStateError, "The associated Track is in an invalid state."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "The associated Track is in an invalid state."));
return promise;
}
@@ -298,14 +307,15 @@ ScriptPromise ImageCapture::grabFrame(ScriptState* script_state) {
if (!frame_grabber_) {
resolver->Reject(DOMException::Create(
- kUnknownError, "Couldn't create platform resources"));
+ DOMExceptionCode::kUnknownError, "Couldn't create platform resources"));
return promise;
}
// The platform does not know about MediaStreamTrack, so we wrap it up.
WebMediaStreamTrack track(stream_track_->Component());
- frame_grabber_->GrabFrame(
- &track, new CallbackPromiseAdapter<ImageBitmap, void>(resolver));
+ auto resolver_callback_adapter =
+ std::make_unique<CallbackPromiseAdapter<ImageBitmap, void>>(resolver);
+ frame_grabber_->GrabFrame(&track, std::move(resolver_callback_adapter));
return promise;
}
@@ -321,7 +331,8 @@ void ImageCapture::SetMediaTrackConstraints(
const HeapVector<MediaTrackConstraintSet>& constraints_vector) {
DCHECK_GT(constraints_vector.size(), 0u);
if (!service_) {
- resolver->Reject(DOMException::Create(kNotFoundError, kNoServiceError));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
+ kNoServiceError));
return;
}
// TODO(mcasas): add support more than one single advanced constraint.
@@ -342,8 +353,8 @@ void ImageCapture::SetMediaTrackConstraints(
(constraints.hasSharpness() && !capabilities_.hasSharpness()) ||
(constraints.hasZoom() && !capabilities_.hasZoom()) ||
(constraints.hasTorch() && !capabilities_.hasTorch())) {
- resolver->Reject(
- DOMException::Create(kNotSupportedError, "Unsupported constraint(s)"));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "Unsupported constraint(s)"));
return;
}
@@ -359,8 +370,9 @@ void ImageCapture::SetMediaTrackConstraints(
constraints.whiteBalanceMode().GetAsString();
if (capabilities_.whiteBalanceMode().Find(white_balance_mode) ==
kNotFound) {
- resolver->Reject(DOMException::Create(kNotSupportedError,
- "Unsupported whiteBalanceMode."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "Unsupported whiteBalanceMode."));
return;
}
temp_constraints.setWhiteBalanceMode(constraints.whiteBalanceMode());
@@ -371,8 +383,8 @@ void ImageCapture::SetMediaTrackConstraints(
if (settings->has_exposure_mode) {
const auto exposure_mode = constraints.exposureMode().GetAsString();
if (capabilities_.exposureMode().Find(exposure_mode) == kNotFound) {
- resolver->Reject(DOMException::Create(kNotSupportedError,
- "Unsupported exposureMode."));
+ resolver->Reject(DOMException::Create(
+ DOMExceptionCode::kNotSupportedError, "Unsupported exposureMode."));
return;
}
temp_constraints.setExposureMode(constraints.exposureMode());
@@ -384,8 +396,8 @@ void ImageCapture::SetMediaTrackConstraints(
if (settings->has_focus_mode) {
const auto focus_mode = constraints.focusMode().GetAsString();
if (capabilities_.focusMode().Find(focus_mode) == kNotFound) {
- resolver->Reject(
- DOMException::Create(kNotSupportedError, "Unsupported focusMode."));
+ resolver->Reject(DOMException::Create(
+ DOMExceptionCode::kNotSupportedError, "Unsupported focusMode."));
return;
}
temp_constraints.setFocusMode(constraints.focusMode());
@@ -414,8 +426,9 @@ void ImageCapture::SetMediaTrackConstraints(
constraints.exposureCompensation().GetAsDouble();
if (exposure_compensation < capabilities_.exposureCompensation()->min() ||
exposure_compensation > capabilities_.exposureCompensation()->max()) {
- resolver->Reject(DOMException::Create(
- kNotSupportedError, "exposureCompensation setting out of range"));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "exposureCompensation setting out of range"));
return;
}
temp_constraints.setExposureCompensation(
@@ -428,8 +441,9 @@ void ImageCapture::SetMediaTrackConstraints(
const auto color_temperature = constraints.colorTemperature().GetAsDouble();
if (color_temperature < capabilities_.colorTemperature()->min() ||
color_temperature > capabilities_.colorTemperature()->max()) {
- resolver->Reject(DOMException::Create(
- kNotSupportedError, "colorTemperature setting out of range"));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "colorTemperature setting out of range"));
return;
}
temp_constraints.setColorTemperature(constraints.colorTemperature());
@@ -439,8 +453,8 @@ void ImageCapture::SetMediaTrackConstraints(
if (settings->has_iso) {
const auto iso = constraints.iso().GetAsDouble();
if (iso < capabilities_.iso()->min() || iso > capabilities_.iso()->max()) {
- resolver->Reject(
- DOMException::Create(kNotSupportedError, "iso setting out of range"));
+ resolver->Reject(DOMException::Create(
+ DOMExceptionCode::kNotSupportedError, "iso setting out of range"));
return;
}
temp_constraints.setIso(constraints.iso());
@@ -453,8 +467,9 @@ void ImageCapture::SetMediaTrackConstraints(
const auto brightness = constraints.brightness().GetAsDouble();
if (brightness < capabilities_.brightness()->min() ||
brightness > capabilities_.brightness()->max()) {
- resolver->Reject(DOMException::Create(kNotSupportedError,
- "brightness setting out of range"));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "brightness setting out of range"));
return;
}
temp_constraints.setBrightness(constraints.brightness());
@@ -466,8 +481,9 @@ void ImageCapture::SetMediaTrackConstraints(
const auto contrast = constraints.contrast().GetAsDouble();
if (contrast < capabilities_.contrast()->min() ||
contrast > capabilities_.contrast()->max()) {
- resolver->Reject(DOMException::Create(kNotSupportedError,
- "contrast setting out of range"));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "contrast setting out of range"));
return;
}
temp_constraints.setContrast(constraints.contrast());
@@ -479,8 +495,9 @@ void ImageCapture::SetMediaTrackConstraints(
const auto saturation = constraints.saturation().GetAsDouble();
if (saturation < capabilities_.saturation()->min() ||
saturation > capabilities_.saturation()->max()) {
- resolver->Reject(DOMException::Create(kNotSupportedError,
- "saturation setting out of range"));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "saturation setting out of range"));
return;
}
temp_constraints.setSaturation(constraints.saturation());
@@ -492,8 +509,9 @@ void ImageCapture::SetMediaTrackConstraints(
const auto sharpness = constraints.sharpness().GetAsDouble();
if (sharpness < capabilities_.sharpness()->min() ||
sharpness > capabilities_.sharpness()->max()) {
- resolver->Reject(DOMException::Create(kNotSupportedError,
- "sharpness setting out of range"));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "sharpness setting out of range"));
return;
}
temp_constraints.setSharpness(constraints.sharpness());
@@ -505,8 +523,8 @@ void ImageCapture::SetMediaTrackConstraints(
const auto zoom = constraints.zoom().GetAsDouble();
if (zoom < capabilities_.zoom()->min() ||
zoom > capabilities_.zoom()->max()) {
- resolver->Reject(DOMException::Create(kNotSupportedError,
- "zoom setting out of range"));
+ resolver->Reject(DOMException::Create(
+ DOMExceptionCode::kNotSupportedError, "zoom setting out of range"));
return;
}
temp_constraints.setZoom(constraints.zoom());
@@ -519,8 +537,8 @@ void ImageCapture::SetMediaTrackConstraints(
if (settings->has_torch) {
const auto torch = constraints.torch().GetAsBoolean();
if (torch && !capabilities_.torch()) {
- resolver->Reject(
- DOMException::Create(kNotSupportedError, "torch not supported"));
+ resolver->Reject(DOMException::Create(
+ DOMExceptionCode::kNotSupportedError, "torch not supported"));
return;
}
temp_constraints.setTorch(constraints.torch());
@@ -616,7 +634,8 @@ void ImageCapture::OnMojoGetPhotoState(
DCHECK(service_requests_.Contains(resolver));
if (photo_state.is_null()) {
- resolver->Reject(DOMException::Create(kUnknownError, "platform error"));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kUnknownError,
+ "platform error"));
service_requests_.erase(resolver);
return;
}
@@ -663,7 +682,8 @@ void ImageCapture::OnMojoSetOptions(ScriptPromiseResolver* resolver,
DCHECK(service_requests_.Contains(resolver));
if (!result) {
- resolver->Reject(DOMException::Create(kUnknownError, "setOptions failed"));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kUnknownError,
+ "setOptions failed"));
service_requests_.erase(resolver);
return;
}
@@ -685,7 +705,8 @@ void ImageCapture::OnMojoTakePhoto(ScriptPromiseResolver* resolver,
// TODO(mcasas): Should be using a mojo::StructTraits.
if (blob->data.IsEmpty()) {
- resolver->Reject(DOMException::Create(kUnknownError, "platform error"));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kUnknownError,
+ "platform error"));
} else {
resolver->Resolve(
Blob::Create(blob->data.data(), blob->data.size(), blob->mime_type));
@@ -795,8 +816,10 @@ void ImageCapture::UpdateMediaTrackCapabilities(
void ImageCapture::OnServiceConnectionError() {
service_.reset();
- for (ScriptPromiseResolver* resolver : service_requests_)
- resolver->Reject(DOMException::Create(kNotFoundError, kNoServiceError));
+ for (ScriptPromiseResolver* resolver : service_requests_) {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
+ kNoServiceError));
+ }
service_requests_.clear();
}
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/OWNERS b/chromium/third_party/blink/renderer/modules/indexeddb/OWNERS
index b48e06048c1..acc03749c6c 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/OWNERS
@@ -1,3 +1,6 @@
file://content/browser/indexed_db/OWNERS
pwnall@chromium.org
+
+# TEAM: storage-dev@chromium.org
+# COMPONENT: Blink>Storage>IndexedDB
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc b/chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc
index 0af332c6fc0..32306872aa6 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc
@@ -29,17 +29,16 @@
#include <memory>
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_key_range.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/modules/v8/to_v8_for_modules.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_idb_request.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/indexed_db_names.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_any.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_database.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_object_store.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_tracing.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_transaction.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/bindings/v8_private_property.h"
@@ -103,28 +102,29 @@ IDBRequest* IDBCursor::update(ScriptState* script_state,
ExceptionState& exception_state) {
IDB_TRACE("IDBCursor::updateRequestSetup");
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return nullptr;
}
if (transaction_->IsReadOnly()) {
exception_state.ThrowDOMException(
- kReadOnlyError,
+ DOMExceptionCode::kReadOnlyError,
"The record may not be updated inside a read-only transaction.");
return nullptr;
}
if (IsDeleted()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kSourceDeletedErrorMessage);
return nullptr;
}
if (!got_value_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kNoValueErrorMessage);
return nullptr;
}
if (IsKeyCursor()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kIsKeyCursorErrorMessage);
return nullptr;
}
@@ -145,17 +145,18 @@ void IDBCursor::advance(unsigned count, ExceptionState& exception_state) {
return;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return;
}
if (IsDeleted()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kSourceDeletedErrorMessage);
return;
}
if (!got_value_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kNoValueErrorMessage);
return;
}
@@ -173,17 +174,18 @@ void IDBCursor::Continue(ScriptState* script_state,
IDBRequest::AsyncTraceState metrics("IDBCursor::continue");
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return;
}
if (!got_value_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kNoValueErrorMessage);
return;
}
if (IsDeleted()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kSourceDeletedErrorMessage);
return;
}
@@ -196,7 +198,7 @@ void IDBCursor::Continue(ScriptState* script_state,
if (exception_state.HadException())
return;
if (key && !key->IsValid()) {
- exception_state.ThrowDOMException(kDataError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
IDBDatabase::kNotValidKeyErrorMessage);
return;
}
@@ -211,19 +213,20 @@ void IDBCursor::continuePrimaryKey(ScriptState* script_state,
IDBRequest::AsyncTraceState metrics("IDBCursor::continuePrimaryKey");
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return;
}
if (IsDeleted()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kSourceDeletedErrorMessage);
return;
}
if (!source_.IsIDBIndex()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The cursor's source is not an index.");
return;
}
@@ -231,12 +234,13 @@ void IDBCursor::continuePrimaryKey(ScriptState* script_state,
if (direction_ != kWebIDBCursorDirectionNext &&
direction_ != kWebIDBCursorDirectionPrev) {
exception_state.ThrowDOMException(
- kInvalidAccessError, "The cursor's direction is not 'next' or 'prev'.");
+ DOMExceptionCode::kInvalidAccessError,
+ "The cursor's direction is not 'next' or 'prev'.");
return;
}
if (!got_value_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kNoValueErrorMessage);
return;
}
@@ -246,7 +250,7 @@ void IDBCursor::continuePrimaryKey(ScriptState* script_state,
if (exception_state.HadException())
return;
if (!key->IsValid()) {
- exception_state.ThrowDOMException(kDataError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
IDBDatabase::kNotValidKeyErrorMessage);
return;
}
@@ -257,7 +261,7 @@ void IDBCursor::continuePrimaryKey(ScriptState* script_state,
if (exception_state.HadException())
return;
if (!primary_key->IsValid()) {
- exception_state.ThrowDOMException(kDataError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
IDBDatabase::kNotValidKeyErrorMessage);
return;
}
@@ -286,7 +290,7 @@ void IDBCursor::Continue(std::unique_ptr<IDBKey> key,
current_primary_key->IsLessThan(primary_key.get()));
if (!ok) {
exception_state.ThrowDOMException(
- kDataError,
+ DOMExceptionCode::kDataError,
"The parameter is less than or equal to this cursor's position.");
return;
}
@@ -296,7 +300,7 @@ void IDBCursor::Continue(std::unique_ptr<IDBKey> key,
(primary_key && key->IsEqual(key_.get()) &&
primary_key->IsLessThan(current_primary_key));
if (!ok) {
- exception_state.ThrowDOMException(kDataError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
"The parameter is greater than or "
"equal to this cursor's position.");
return;
@@ -319,33 +323,34 @@ IDBRequest* IDBCursor::Delete(ScriptState* script_state,
IDB_TRACE("IDBCursor::deleteRequestSetup");
IDBRequest::AsyncTraceState metrics("IDBCursor::delete");
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return nullptr;
}
if (transaction_->IsReadOnly()) {
exception_state.ThrowDOMException(
- kReadOnlyError,
+ DOMExceptionCode::kReadOnlyError,
"The record may not be deleted inside a read-only transaction.");
return nullptr;
}
if (IsDeleted()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kSourceDeletedErrorMessage);
return nullptr;
}
if (!got_value_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kNoValueErrorMessage);
return nullptr;
}
if (IsKeyCursor()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kIsKeyCursorErrorMessage);
return nullptr;
}
if (!transaction_->BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.cc b/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.cc
index ca2a9d4ecf7..75ccc9d068c 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.cc
@@ -25,18 +25,17 @@
#include "third_party/blink/renderer/modules/indexeddb/idb_database.h"
+#include "base/atomic_sequence_num.h"
#include "base/optional.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_callbacks.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_database_exception.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_key_path.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_observation.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_types.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_idb_observer_callback.h"
#include "third_party/blink/renderer/core/dom/events/event_queue.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_any.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_event_dispatcher.h"
@@ -47,6 +46,7 @@
#include "third_party/blink/renderer/modules/indexeddb/idb_tracing.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_version_change_event.h"
#include "third_party/blink/renderer/modules/indexeddb/web_idb_database_callbacks_impl.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/atomics.h"
@@ -108,6 +108,7 @@ IDBDatabase::IDBDatabase(ExecutionContext* context,
v8::Isolate* isolate)
: ContextLifecycleObserver(context),
backend_(std::move(backend)),
+ event_queue_(EventQueue::Create(context, TaskType::kInternalIndexedDB)),
database_callbacks_(callbacks),
isolate_(isolate) {
database_callbacks_->Connect(this);
@@ -122,29 +123,24 @@ void IDBDatabase::Trace(blink::Visitor* visitor) {
visitor->Trace(version_change_transaction_);
visitor->Trace(transactions_);
visitor->Trace(observers_);
- visitor->Trace(enqueued_events_);
+ visitor->Trace(event_queue_);
visitor->Trace(database_callbacks_);
EventTargetWithInlineData::Trace(visitor);
ContextLifecycleObserver::Trace(visitor);
}
-void IDBDatabase::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- for (const auto& observer : observers_.Values()) {
- visitor->TraceWrappers(observer);
- }
- EventTargetWithInlineData::TraceWrappers(visitor);
-}
-
int64_t IDBDatabase::NextTransactionId() {
+ // Starts at 1, unlike AtomicSequenceNumber.
// Only keep a 32-bit counter to allow ports to use the other 32
// bits of the id.
- static int current_transaction_id = 0;
- return AtomicIncrement(&current_transaction_id);
+ static base::AtomicSequenceNumber current_transaction_id;
+ return current_transaction_id.GetNext() + 1;
}
int32_t IDBDatabase::NextObserverId() {
- static int current_observer_id = 0;
- return AtomicIncrement(&current_observer_id);
+ // Starts at 1, unlike AtomicSequenceNumber.
+ static base::AtomicSequenceNumber current_observer_id;
+ return current_observer_id.GetNext() + 1;
}
void IDBDatabase::SetMetadata(const IDBDatabaseMetadata& metadata) {
@@ -273,26 +269,28 @@ IDBObjectStore* IDBDatabase::createObjectStore(
if (!version_change_transaction_) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
IDBDatabase::kNotVersionChangeTransactionErrorMessage);
return nullptr;
}
if (!version_change_transaction_->IsActive()) {
exception_state.ThrowDOMException(
- kTransactionInactiveError,
+ DOMExceptionCode::kTransactionInactiveError,
version_change_transaction_->InactiveErrorMessage());
return nullptr;
}
if (!key_path.IsNull() && !key_path.IsValid()) {
exception_state.ThrowDOMException(
- kSyntaxError, "The keyPath option is not a valid key path.");
+ DOMExceptionCode::kSyntaxError,
+ "The keyPath option is not a valid key path.");
return nullptr;
}
if (ContainsObjectStore(name)) {
exception_state.ThrowDOMException(
- kConstraintError, IDBDatabase::kObjectStoreNameTakenErrorMessage);
+ DOMExceptionCode::kConstraintError,
+ IDBDatabase::kObjectStoreNameTakenErrorMessage);
return nullptr;
}
@@ -300,14 +298,14 @@ IDBObjectStore* IDBDatabase::createObjectStore(
key_path.GetString().IsEmpty()) ||
key_path.GetType() == IDBKeyPath::kArrayType)) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"The autoIncrement option was set but the "
"keyPath option was empty or an array.");
return nullptr;
}
if (!backend_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return nullptr;
}
@@ -336,13 +334,13 @@ void IDBDatabase::deleteObjectStore(const String& name,
RecordApiCallsHistogram(kIDBDeleteObjectStoreCall);
if (!version_change_transaction_) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
IDBDatabase::kNotVersionChangeTransactionErrorMessage);
return;
}
if (!version_change_transaction_->IsActive()) {
exception_state.ThrowDOMException(
- kTransactionInactiveError,
+ DOMExceptionCode::kTransactionInactiveError,
version_change_transaction_->InactiveErrorMessage());
return;
}
@@ -350,12 +348,13 @@ void IDBDatabase::deleteObjectStore(const String& name,
int64_t object_store_id = FindObjectStoreId(name);
if (object_store_id == IDBObjectStoreMetadata::kInvalidId) {
exception_state.ThrowDOMException(
- kNotFoundError, "The specified object store was not found.");
+ DOMExceptionCode::kNotFoundError,
+ "The specified object store was not found.");
return;
}
if (!backend_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return;
}
@@ -386,24 +385,25 @@ IDBTransaction* IDBDatabase::transaction(
if (version_change_transaction_) {
exception_state.ThrowDOMException(
- kInvalidStateError, "A version change transaction is running.");
+ DOMExceptionCode::kInvalidStateError,
+ "A version change transaction is running.");
return nullptr;
}
if (close_pending_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The database connection is closing.");
return nullptr;
}
if (!backend_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return nullptr;
}
if (scope.IsEmpty()) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"The storeNames parameter was empty.");
return nullptr;
}
@@ -413,7 +413,8 @@ IDBTransaction* IDBDatabase::transaction(
int64_t object_store_id = FindObjectStoreId(name);
if (object_store_id == IDBObjectStoreMetadata::kInvalidId) {
exception_state.ThrowDOMException(
- kNotFoundError, "One of the specified object stores was not found.");
+ DOMExceptionCode::kNotFoundError,
+ "One of the specified object stores was not found.");
return nullptr;
}
object_store_ids.push_back(object_store_id);
@@ -468,15 +469,11 @@ void IDBDatabase::CloseConnection() {
if (!GetExecutionContext())
return;
- EventQueue* event_queue = GetExecutionContext()->GetEventQueue();
// Remove any pending versionchange events scheduled to fire on this
// connection. They would have been scheduled by the backend when another
// connection attempted an upgrade, but the frontend connection is being
// closed before they could fire.
- for (size_t i = 0; i < enqueued_events_.size(); ++i) {
- bool removed = event_queue->CancelEvent(enqueued_events_[i].Get());
- DCHECK(removed);
- }
+ event_queue_->CancelAllEvents();
}
void IDBDatabase::OnVersionChange(int64_t old_version, int64_t new_version) {
@@ -502,10 +499,8 @@ void IDBDatabase::OnVersionChange(int64_t old_version, int64_t new_version) {
void IDBDatabase::EnqueueEvent(Event* event) {
DCHECK(GetExecutionContext());
- EventQueue* event_queue = GetExecutionContext()->GetEventQueue();
event->SetTarget(this);
- event_queue->EnqueueEvent(FROM_HERE, event);
- enqueued_events_.push_back(event);
+ event_queue_->EnqueueEvent(FROM_HERE, event);
}
DispatchEventResult IDBDatabase::DispatchEventInternal(Event* event) {
@@ -514,10 +509,6 @@ DispatchEventResult IDBDatabase::DispatchEventInternal(Event* event) {
return DispatchEventResult::kCanceledBeforeDispatch;
DCHECK(event->type() == EventTypeNames::versionchange ||
event->type() == EventTypeNames::close);
- for (size_t i = 0; i < enqueued_events_.size(); ++i) {
- if (enqueued_events_[i].Get() == event)
- enqueued_events_.EraseAt(i);
- }
DispatchEventResult dispatch_result =
EventTarget::DispatchEventInternal(event);
@@ -614,12 +605,19 @@ void IDBDatabase::RecordApiCallsHistogram(IndexedDatabaseMethods method) {
api_calls_histogram.Count(method);
}
-STATIC_ASSERT_ENUM(kWebIDBDatabaseExceptionUnknownError, kUnknownError);
-STATIC_ASSERT_ENUM(kWebIDBDatabaseExceptionConstraintError, kConstraintError);
-STATIC_ASSERT_ENUM(kWebIDBDatabaseExceptionDataError, kDataError);
-STATIC_ASSERT_ENUM(kWebIDBDatabaseExceptionVersionError, kVersionError);
-STATIC_ASSERT_ENUM(kWebIDBDatabaseExceptionAbortError, kAbortError);
-STATIC_ASSERT_ENUM(kWebIDBDatabaseExceptionQuotaError, kQuotaExceededError);
-STATIC_ASSERT_ENUM(kWebIDBDatabaseExceptionTimeoutError, kTimeoutError);
+STATIC_ASSERT_ENUM(kWebIDBDatabaseExceptionUnknownError,
+ DOMExceptionCode::kUnknownError);
+STATIC_ASSERT_ENUM(kWebIDBDatabaseExceptionConstraintError,
+ DOMExceptionCode::kConstraintError);
+STATIC_ASSERT_ENUM(kWebIDBDatabaseExceptionDataError,
+ DOMExceptionCode::kDataError);
+STATIC_ASSERT_ENUM(kWebIDBDatabaseExceptionVersionError,
+ DOMExceptionCode::kVersionError);
+STATIC_ASSERT_ENUM(kWebIDBDatabaseExceptionAbortError,
+ DOMExceptionCode::kAbortError);
+STATIC_ASSERT_ENUM(kWebIDBDatabaseExceptionQuotaError,
+ DOMExceptionCode::kQuotaExceededError);
+STATIC_ASSERT_ENUM(kWebIDBDatabaseExceptionTimeoutError,
+ DOMExceptionCode::kTimeoutError);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.h b/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.h
index 61189fc2a57..183bfbd4ced 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_database.h
@@ -71,7 +71,6 @@ class MODULES_EXPORT IDBDatabase final
v8::Isolate*);
~IDBDatabase() override;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
// Overwrites the database metadata, including object store and index
// metadata. Used to pass metadata to the database when it is opened.
@@ -198,9 +197,7 @@ class MODULES_EXPORT IDBDatabase final
bool close_pending_ = false;
- // Keep track of the versionchange events waiting to be fired on this
- // database so that we can cancel them if the database closes.
- HeapVector<Member<Event>> enqueued_events_;
+ Member<EventQueue> event_queue_;
Member<IDBDatabaseCallbacks> database_callbacks_;
// Maintain the isolate so that all externally allocated memory can be
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_factory.cc b/chromium/third_party/blink/renderer/modules/indexeddb/idb_factory.cc
index f658550cc53..15d4f746059 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_factory.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_factory.cc
@@ -34,11 +34,9 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_security_origin.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.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/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_database.h"
@@ -46,6 +44,7 @@
#include "third_party/blink/renderer/modules/indexeddb/idb_key.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_tracing.h"
#include "third_party/blink/renderer/modules/indexeddb/indexed_db_client.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -90,8 +89,8 @@ IDBRequest* IDBFactory::GetDatabaseNames(ScriptState* script_state,
if (!IndexedDBClient::From(ExecutionContext::From(script_state))
->AllowIndexedDB(ExecutionContext::From(script_state),
"Database Listing")) {
- request->HandleResponse(
- DOMException::Create(kUnknownError, kPermissionDeniedErrorMessage));
+ request->HandleResponse(DOMException::Create(
+ DOMExceptionCode::kUnknownError, kPermissionDeniedErrorMessage));
return request;
}
@@ -146,8 +145,8 @@ IDBOpenDBRequest* IDBFactory::OpenInternal(ScriptState* script_state,
if (!IndexedDBClient::From(ExecutionContext::From(script_state))
->AllowIndexedDB(ExecutionContext::From(script_state), name)) {
- request->HandleResponse(
- DOMException::Create(kUnknownError, kPermissionDeniedErrorMessage));
+ request->HandleResponse(DOMException::Create(
+ DOMExceptionCode::kUnknownError, kPermissionDeniedErrorMessage));
return request;
}
@@ -213,8 +212,8 @@ IDBOpenDBRequest* IDBFactory::DeleteDatabaseInternal(
if (!IndexedDBClient::From(ExecutionContext::From(script_state))
->AllowIndexedDB(ExecutionContext::From(script_state), name)) {
- request->HandleResponse(
- DOMException::Create(kUnknownError, kPermissionDeniedErrorMessage));
+ request->HandleResponse(DOMException::Create(
+ DOMExceptionCode::kUnknownError, kPermissionDeniedErrorMessage));
return request;
}
@@ -239,7 +238,7 @@ short IDBFactory::cmp(ScriptState* script_state,
return 0;
DCHECK(first);
if (!first->IsValid()) {
- exception_state.ThrowDOMException(kDataError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
IDBDatabase::kNotValidKeyErrorMessage);
return 0;
}
@@ -251,7 +250,7 @@ short IDBFactory::cmp(ScriptState* script_state,
return 0;
DCHECK(second);
if (!second->IsValid()) {
- exception_state.ThrowDOMException(kDataError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
IDBDatabase::kNotValidKeyErrorMessage);
return 0;
}
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_index.cc b/chromium/third_party/blink/renderer/modules/indexeddb/idb_index.cc
index 1e5d912babd..c8dd61b5f31 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_index.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_index.cc
@@ -27,18 +27,17 @@
#include <memory>
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_key_range.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/bindings/modules/v8/idb_object_store_or_idb_index_or_idb_cursor.h"
#include "third_party/blink/renderer/bindings/modules/v8/to_v8_for_modules.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_database.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_key.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_object_store.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_tracing.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_transaction.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
using blink::WebIDBCallbacks;
using blink::WebIDBCursor;
@@ -70,30 +69,31 @@ void IDBIndex::setName(const String& name, ExceptionState& exception_state) {
IDB_TRACE("IDBIndex::setName");
if (!transaction_->IsVersionChange()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
IDBDatabase::kNotVersionChangeTransactionErrorMessage);
return;
}
if (IsDeleted()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kIndexDeletedErrorMessage);
return;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return;
}
if (this->name() == name)
return;
if (object_store_->ContainsIndex(name)) {
- exception_state.ThrowDOMException(kConstraintError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kConstraintError,
IDBDatabase::kIndexNameTakenErrorMessage);
return;
}
if (!BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return;
}
@@ -121,13 +121,14 @@ IDBRequest* IDBIndex::openCursor(ScriptState* script_state,
metadata_->name.Utf8());
IDBRequest::AsyncTraceState metrics("IDBIndex::openCursor");
if (IsDeleted()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kIndexDeletedErrorMessage);
return nullptr;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return nullptr;
}
WebIDBCursorDirection direction =
@@ -138,7 +139,7 @@ IDBRequest* IDBIndex::openCursor(ScriptState* script_state,
return nullptr;
if (!BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return nullptr;
}
@@ -166,13 +167,14 @@ IDBRequest* IDBIndex::count(ScriptState* script_state,
metadata_->name.Utf8());
IDBRequest::AsyncTraceState metrics("IDBIndex::count");
if (IsDeleted()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kIndexDeletedErrorMessage);
return nullptr;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return nullptr;
}
@@ -182,7 +184,7 @@ IDBRequest* IDBIndex::count(ScriptState* script_state,
return nullptr;
if (!BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return nullptr;
}
@@ -202,13 +204,14 @@ IDBRequest* IDBIndex::openKeyCursor(ScriptState* script_state,
metadata_->name.Utf8());
IDBRequest::AsyncTraceState metrics("IDBIndex::openKeyCursor");
if (IsDeleted()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kIndexDeletedErrorMessage);
return nullptr;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return nullptr;
}
WebIDBCursorDirection direction =
@@ -218,7 +221,7 @@ IDBRequest* IDBIndex::openKeyCursor(ScriptState* script_state,
if (exception_state.HadException())
return nullptr;
if (!BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return nullptr;
}
@@ -293,13 +296,14 @@ IDBRequest* IDBIndex::GetInternal(ScriptState* script_state,
bool key_only,
IDBRequest::AsyncTraceState metrics) {
if (IsDeleted()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kIndexDeletedErrorMessage);
return nullptr;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return nullptr;
}
@@ -309,11 +313,12 @@ IDBRequest* IDBIndex::GetInternal(ScriptState* script_state,
return nullptr;
if (!key_range) {
exception_state.ThrowDOMException(
- kDataError, IDBDatabase::kNoKeyOrKeyRangeErrorMessage);
+ DOMExceptionCode::kDataError,
+ IDBDatabase::kNoKeyOrKeyRangeErrorMessage);
return nullptr;
}
if (!BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return nullptr;
}
@@ -334,13 +339,14 @@ IDBRequest* IDBIndex::GetAllInternal(ScriptState* script_state,
max_count = std::numeric_limits<uint32_t>::max();
if (IsDeleted()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kIndexDeletedErrorMessage);
return nullptr;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return nullptr;
}
@@ -349,7 +355,7 @@ IDBRequest* IDBIndex::GetAllInternal(ScriptState* script_state,
if (exception_state.HadException())
return nullptr;
if (!BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_range.cc b/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_range.cc
index 6da510f44ea..3554ee367e4 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_range.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_range.cc
@@ -25,13 +25,12 @@
#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/bindings/modules/v8/to_v8_for_modules.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_database.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -51,7 +50,7 @@ IDBKeyRange* IDBKeyRange::FromScriptValue(ExecutionContext* context,
if (exception_state.HadException())
return nullptr;
if (!key || !key->IsValid()) {
- exception_state.ThrowDOMException(kDataError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
IDBDatabase::kNotValidKeyErrorMessage);
return nullptr;
}
@@ -90,7 +89,7 @@ ScriptValue IDBKeyRange::UpperValue(ScriptState* script_state) const {
IDBKeyRange* IDBKeyRange::only(std::unique_ptr<IDBKey> key,
ExceptionState& exception_state) {
if (!key || !key->IsValid()) {
- exception_state.ThrowDOMException(kDataError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
IDBDatabase::kNotValidKeyErrorMessage);
return nullptr;
}
@@ -109,7 +108,7 @@ IDBKeyRange* IDBKeyRange::only(ScriptState* script_state,
if (exception_state.HadException())
return nullptr;
if (!key || !key->IsValid()) {
- exception_state.ThrowDOMException(kDataError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
IDBDatabase::kNotValidKeyErrorMessage);
return nullptr;
}
@@ -129,7 +128,7 @@ IDBKeyRange* IDBKeyRange::lowerBound(ScriptState* script_state,
if (exception_state.HadException())
return nullptr;
if (!bound || !bound->IsValid()) {
- exception_state.ThrowDOMException(kDataError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
IDBDatabase::kNotValidKeyErrorMessage);
return nullptr;
}
@@ -149,7 +148,7 @@ IDBKeyRange* IDBKeyRange::upperBound(ScriptState* script_state,
if (exception_state.HadException())
return nullptr;
if (!bound || !bound->IsValid()) {
- exception_state.ThrowDOMException(kDataError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
IDBDatabase::kNotValidKeyErrorMessage);
return nullptr;
}
@@ -170,7 +169,7 @@ IDBKeyRange* IDBKeyRange::bound(ScriptState* script_state,
if (exception_state.HadException())
return nullptr;
if (!lower || !lower->IsValid()) {
- exception_state.ThrowDOMException(kDataError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
IDBDatabase::kNotValidKeyErrorMessage);
return nullptr;
}
@@ -182,19 +181,20 @@ IDBKeyRange* IDBKeyRange::bound(ScriptState* script_state,
if (exception_state.HadException())
return nullptr;
if (!upper || !upper->IsValid()) {
- exception_state.ThrowDOMException(kDataError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
IDBDatabase::kNotValidKeyErrorMessage);
return nullptr;
}
if (upper->IsLessThan(lower.get())) {
exception_state.ThrowDOMException(
- kDataError, "The lower key is greater than the upper key.");
+ DOMExceptionCode::kDataError,
+ "The lower key is greater than the upper key.");
return nullptr;
}
if (upper->IsEqual(lower.get()) && (lower_open || upper_open)) {
exception_state.ThrowDOMException(
- kDataError,
+ DOMExceptionCode::kDataError,
"The lower key and upper key are equal and one of the bounds is open.");
return nullptr;
}
@@ -216,7 +216,7 @@ bool IDBKeyRange::includes(ScriptState* script_state,
if (exception_state.HadException())
return false;
if (!key || !key->IsValid()) {
- exception_state.ThrowDOMException(kDataError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
IDBDatabase::kNotValidKeyErrorMessage);
return false;
}
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_range.idl b/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_range.idl
index 19fc34e192a..49dbff00b80 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_range.idl
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_key_range.idl
@@ -41,7 +41,5 @@
optional boolean lowerOpen = false,
optional boolean upperOpen = false);
- // '_' prefix is needed because "includes" is a keyword of Web IDL and our
- // parser cannot handle a keyword as an identifier. (https://crbug.com/820353)
[CallWith=ScriptState, RaisesException] boolean _includes(any key);
};
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc b/chromium/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc
index 18453d9a689..edacac192e5 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc
@@ -35,13 +35,11 @@
#include "third_party/blink/public/platform/web_blob_info.h"
#include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/public/platform/web_vector.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_factory.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/bindings/modules/v8/to_v8_for_modules.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h"
#include "third_party/blink/renderer/core/dom/dom_string_list.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_any.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.h"
@@ -50,6 +48,7 @@
#include "third_party/blink/renderer/modules/indexeddb/idb_key_path.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_tracing.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.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/histogram.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
@@ -80,18 +79,20 @@ void IDBObjectStore::setName(const String& name,
IDB_TRACE("IDBObjectStore::setName");
if (!transaction_->IsVersionChange()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
IDBDatabase::kNotVersionChangeTransactionErrorMessage);
return;
}
if (IsDeleted()) {
exception_state.ThrowDOMException(
- kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
+ DOMExceptionCode::kInvalidStateError,
+ IDBDatabase::kObjectStoreDeletedErrorMessage);
return;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return;
}
@@ -99,11 +100,12 @@ void IDBObjectStore::setName(const String& name,
return;
if (transaction_->db()->ContainsObjectStore(name)) {
exception_state.ThrowDOMException(
- kConstraintError, IDBDatabase::kObjectStoreNameTakenErrorMessage);
+ DOMExceptionCode::kConstraintError,
+ IDBDatabase::kObjectStoreNameTakenErrorMessage);
return;
}
if (!BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return;
}
@@ -133,12 +135,14 @@ IDBRequest* IDBObjectStore::get(ScriptState* script_state,
IDBRequest::AsyncTraceState metrics("IDBObjectStore::get");
if (IsDeleted()) {
exception_state.ThrowDOMException(
- kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
+ DOMExceptionCode::kInvalidStateError,
+ IDBDatabase::kObjectStoreDeletedErrorMessage);
return nullptr;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return nullptr;
}
IDBKeyRange* key_range = IDBKeyRange::FromScriptValue(
@@ -147,11 +151,12 @@ IDBRequest* IDBObjectStore::get(ScriptState* script_state,
return nullptr;
if (!key_range) {
exception_state.ThrowDOMException(
- kDataError, IDBDatabase::kNoKeyOrKeyRangeErrorMessage);
+ DOMExceptionCode::kDataError,
+ IDBDatabase::kNoKeyOrKeyRangeErrorMessage);
return nullptr;
}
if (!BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return nullptr;
}
@@ -172,12 +177,14 @@ IDBRequest* IDBObjectStore::getKey(ScriptState* script_state,
IDBRequest::AsyncTraceState metrics("IDBObjectStore::getKey");
if (IsDeleted()) {
exception_state.ThrowDOMException(
- kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
+ DOMExceptionCode::kInvalidStateError,
+ IDBDatabase::kObjectStoreDeletedErrorMessage);
return nullptr;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return nullptr;
}
IDBKeyRange* key_range = IDBKeyRange::FromScriptValue(
@@ -186,11 +193,12 @@ IDBRequest* IDBObjectStore::getKey(ScriptState* script_state,
return nullptr;
if (!key_range) {
exception_state.ThrowDOMException(
- kDataError, IDBDatabase::kNoKeyOrKeyRangeErrorMessage);
+ DOMExceptionCode::kDataError,
+ IDBDatabase::kNoKeyOrKeyRangeErrorMessage);
return nullptr;
}
if (!BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return nullptr;
}
@@ -222,12 +230,14 @@ IDBRequest* IDBObjectStore::getAll(ScriptState* script_state,
if (IsDeleted()) {
exception_state.ThrowDOMException(
- kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
+ DOMExceptionCode::kInvalidStateError,
+ IDBDatabase::kObjectStoreDeletedErrorMessage);
return nullptr;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return nullptr;
}
IDBKeyRange* range = IDBKeyRange::FromScriptValue(
@@ -235,7 +245,7 @@ IDBRequest* IDBObjectStore::getAll(ScriptState* script_state,
if (exception_state.HadException())
return nullptr;
if (!BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return nullptr;
}
@@ -267,12 +277,14 @@ IDBRequest* IDBObjectStore::getAllKeys(ScriptState* script_state,
if (IsDeleted()) {
exception_state.ThrowDOMException(
- kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
+ DOMExceptionCode::kInvalidStateError,
+ IDBDatabase::kObjectStoreDeletedErrorMessage);
return nullptr;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return nullptr;
}
IDBKeyRange* range = IDBKeyRange::FromScriptValue(
@@ -280,7 +292,7 @@ IDBRequest* IDBObjectStore::getAllKeys(ScriptState* script_state,
if (exception_state.HadException())
return nullptr;
if (!BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return nullptr;
}
@@ -387,17 +399,20 @@ IDBRequest* IDBObjectStore::DoPut(ScriptState* script_state,
IDBRequest::AsyncTraceState metrics(tracing_name);
if (IsDeleted()) {
exception_state.ThrowDOMException(
- kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
+ DOMExceptionCode::kInvalidStateError,
+ IDBDatabase::kObjectStoreDeletedErrorMessage);
return nullptr;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return nullptr;
}
if (transaction_->IsReadOnly()) {
exception_state.ThrowDOMException(
- kReadOnlyError, IDBDatabase::kTransactionReadOnlyErrorMessage);
+ DOMExceptionCode::kReadOnlyError,
+ IDBDatabase::kTransactionReadOnlyErrorMessage);
return nullptr;
}
@@ -423,7 +438,7 @@ IDBRequest* IDBObjectStore::DoPut(ScriptState* script_state,
const bool has_key_generator = autoIncrement();
if (put_mode != kWebIDBPutModeCursorUpdate && uses_in_line_keys && key) {
- exception_state.ThrowDOMException(kDataError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
"The object store uses in-line keys and "
"the key parameter was provided.");
return nullptr;
@@ -447,7 +462,7 @@ IDBRequest* IDBObjectStore::DoPut(ScriptState* script_state,
return nullptr;
if (!key_path_key || !key_path_key->IsEqual(key)) {
exception_state.ThrowDOMException(
- kDataError,
+ DOMExceptionCode::kDataError,
"The effective object store of this cursor uses in-line keys and "
"evaluating the key path of the value parameter results in a "
"different value than the cursor's effective key.");
@@ -456,7 +471,7 @@ IDBRequest* IDBObjectStore::DoPut(ScriptState* script_state,
}
if (!uses_in_line_keys && !has_key_generator && !key) {
- exception_state.ThrowDOMException(kDataError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
"The object store uses out-of-line keys "
"and has no key generator and the key "
"parameter was not provided.");
@@ -476,7 +491,7 @@ IDBRequest* IDBObjectStore::DoPut(ScriptState* script_state,
return nullptr;
if (key_path_key && !key_path_key->IsValid()) {
exception_state.ThrowDOMException(
- kDataError,
+ DOMExceptionCode::kDataError,
"Evaluating the object store's key path yielded a value that is "
"not a valid key.");
return nullptr;
@@ -498,7 +513,7 @@ IDBRequest* IDBObjectStore::DoPut(ScriptState* script_state,
if (!key_path_key) {
if (!has_key_generator) {
- exception_state.ThrowDOMException(kDataError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
"Evaluating the object store's key "
"path did not yield a value.");
return nullptr;
@@ -511,7 +526,7 @@ IDBRequest* IDBObjectStore::DoPut(ScriptState* script_state,
// them from the backing store.
if (!CanInjectIDBKeyIntoScriptValue(script_state->GetIsolate(), clone,
key_path)) {
- exception_state.ThrowDOMException(kDataError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
"A generated key could not be "
"inserted into the value.");
return nullptr;
@@ -523,13 +538,13 @@ IDBRequest* IDBObjectStore::DoPut(ScriptState* script_state,
}
if (key && !key->IsValid()) {
- exception_state.ThrowDOMException(kDataError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kDataError,
IDBDatabase::kNotValidKeyErrorMessage);
return nullptr;
}
if (!BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return nullptr;
}
@@ -583,17 +598,20 @@ IDBRequest* IDBObjectStore::Delete(ScriptState* script_state,
IDBRequest::AsyncTraceState metrics("IDBObjectStore::delete");
if (IsDeleted()) {
exception_state.ThrowDOMException(
- kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
+ DOMExceptionCode::kInvalidStateError,
+ IDBDatabase::kObjectStoreDeletedErrorMessage);
return nullptr;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return nullptr;
}
if (transaction_->IsReadOnly()) {
exception_state.ThrowDOMException(
- kReadOnlyError, IDBDatabase::kTransactionReadOnlyErrorMessage);
+ DOMExceptionCode::kReadOnlyError,
+ IDBDatabase::kTransactionReadOnlyErrorMessage);
return nullptr;
}
@@ -603,11 +621,12 @@ IDBRequest* IDBObjectStore::Delete(ScriptState* script_state,
return nullptr;
if (!key_range) {
exception_state.ThrowDOMException(
- kDataError, IDBDatabase::kNoKeyOrKeyRangeErrorMessage);
+ DOMExceptionCode::kDataError,
+ IDBDatabase::kNoKeyOrKeyRangeErrorMessage);
return nullptr;
}
if (!BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return nullptr;
}
@@ -633,21 +652,24 @@ IDBRequest* IDBObjectStore::clear(ScriptState* script_state,
IDBRequest::AsyncTraceState metrics("IDBObjectStore::clear");
if (IsDeleted()) {
exception_state.ThrowDOMException(
- kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
+ DOMExceptionCode::kInvalidStateError,
+ IDBDatabase::kObjectStoreDeletedErrorMessage);
return nullptr;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return nullptr;
}
if (transaction_->IsReadOnly()) {
exception_state.ThrowDOMException(
- kReadOnlyError, IDBDatabase::kTransactionReadOnlyErrorMessage);
+ DOMExceptionCode::kReadOnlyError,
+ IDBDatabase::kTransactionReadOnlyErrorMessage);
return nullptr;
}
if (!BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return nullptr;
}
@@ -682,6 +704,7 @@ class IndexPopulator final : public EventListener {
}
void Trace(blink::Visitor* visitor) override {
+ visitor->Trace(script_state_);
visitor->Trace(database_);
EventListener::Trace(visitor);
}
@@ -708,7 +731,7 @@ class IndexPopulator final : public EventListener {
return;
IDB_TRACE("IDBObjectStore::IndexPopulator::handleEvent");
- DCHECK_EQ(ExecutionContext::From(script_state_.get()), execution_context);
+ DCHECK_EQ(ExecutionContext::From(script_state_), execution_context);
DCHECK_EQ(event->type(), EventTypeNames::success);
EventTarget* target = event->target();
IDBRequest* request = static_cast<IDBRequest*>(target);
@@ -716,7 +739,7 @@ class IndexPopulator final : public EventListener {
if (!database_->Backend()) // If database is stopped?
return;
- ScriptState::Scope scope(script_state_.get());
+ ScriptState::Scope scope(script_state_);
IDBAny* cursor_any = request->ResultAsAny();
IDBCursorWithValue* cursor = nullptr;
@@ -730,7 +753,7 @@ class IndexPopulator final : public EventListener {
ASSERT_NO_EXCEPTION);
const IDBKey* primary_key = cursor->IdbPrimaryKey();
- ScriptValue value = cursor->value(script_state_.get());
+ ScriptValue value = cursor->value(script_state_);
WebVector<WebVector<WebIDBKey>> index_keys_list;
index_keys_list.reserve(1);
@@ -750,7 +773,7 @@ class IndexPopulator final : public EventListener {
}
}
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
Member<IDBDatabase> database_;
const int64_t transaction_id_;
const int64_t object_store_id_;
@@ -768,38 +791,41 @@ IDBIndex* IDBObjectStore::createIndex(ScriptState* script_state,
IDBRequest::AsyncTraceState metrics("IDBObjectStore::createIndex");
if (!transaction_->IsVersionChange()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
IDBDatabase::kNotVersionChangeTransactionErrorMessage);
return nullptr;
}
if (IsDeleted()) {
exception_state.ThrowDOMException(
- kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
+ DOMExceptionCode::kInvalidStateError,
+ IDBDatabase::kObjectStoreDeletedErrorMessage);
return nullptr;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return nullptr;
}
if (ContainsIndex(name)) {
- exception_state.ThrowDOMException(kConstraintError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kConstraintError,
IDBDatabase::kIndexNameTakenErrorMessage);
return nullptr;
}
if (!key_path.IsValid()) {
exception_state.ThrowDOMException(
- kSyntaxError, "The keyPath argument contains an invalid key path.");
+ DOMExceptionCode::kSyntaxError,
+ "The keyPath argument contains an invalid key path.");
return nullptr;
}
if (key_path.GetType() == IDBKeyPath::kArrayType && options.multiEntry()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"The keyPath argument was an array and the multiEntry option is true.");
return nullptr;
}
if (!BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return nullptr;
}
@@ -841,12 +867,14 @@ IDBIndex* IDBObjectStore::index(const String& name,
IDB_TRACE1("IDBObjectStore::index", "store_name", metadata_->name.Utf8());
if (IsDeleted()) {
exception_state.ThrowDOMException(
- kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
+ DOMExceptionCode::kInvalidStateError,
+ IDBDatabase::kObjectStoreDeletedErrorMessage);
return nullptr;
}
if (transaction_->IsFinished() || transaction_->IsFinishing()) {
exception_state.ThrowDOMException(
- kInvalidStateError, IDBDatabase::kTransactionFinishedErrorMessage);
+ DOMExceptionCode::kInvalidStateError,
+ IDBDatabase::kTransactionFinishedErrorMessage);
return nullptr;
}
@@ -856,7 +884,7 @@ IDBIndex* IDBObjectStore::index(const String& name,
int64_t index_id = FindIndexId(name);
if (index_id == IDBIndexMetadata::kInvalidId) {
- exception_state.ThrowDOMException(kNotFoundError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotFoundError,
IDBDatabase::kNoSuchIndexErrorMessage);
return nullptr;
}
@@ -877,28 +905,30 @@ void IDBObjectStore::deleteIndex(const String& name,
metadata_->name.Utf8());
if (!transaction_->IsVersionChange()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
IDBDatabase::kNotVersionChangeTransactionErrorMessage);
return;
}
if (IsDeleted()) {
exception_state.ThrowDOMException(
- kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
+ DOMExceptionCode::kInvalidStateError,
+ IDBDatabase::kObjectStoreDeletedErrorMessage);
return;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return;
}
int64_t index_id = FindIndexId(name);
if (index_id == IDBIndexMetadata::kInvalidId) {
- exception_state.ThrowDOMException(kNotFoundError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotFoundError,
IDBDatabase::kNoSuchIndexErrorMessage);
return;
}
if (!BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return;
}
@@ -923,12 +953,14 @@ IDBRequest* IDBObjectStore::openCursor(ScriptState* script_state,
IDBRequest::AsyncTraceState metrics("IDBObjectStore::openCursor");
if (IsDeleted()) {
exception_state.ThrowDOMException(
- kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
+ DOMExceptionCode::kInvalidStateError,
+ IDBDatabase::kObjectStoreDeletedErrorMessage);
return nullptr;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return nullptr;
}
@@ -940,7 +972,7 @@ IDBRequest* IDBObjectStore::openCursor(ScriptState* script_state,
return nullptr;
if (!BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return nullptr;
}
@@ -973,12 +1005,14 @@ IDBRequest* IDBObjectStore::openKeyCursor(ScriptState* script_state,
IDBRequest::AsyncTraceState metrics("IDBObjectStore::openKeyCursor");
if (IsDeleted()) {
exception_state.ThrowDOMException(
- kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
+ DOMExceptionCode::kInvalidStateError,
+ IDBDatabase::kObjectStoreDeletedErrorMessage);
return nullptr;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return nullptr;
}
@@ -990,7 +1024,7 @@ IDBRequest* IDBObjectStore::openKeyCursor(ScriptState* script_state,
return nullptr;
if (!BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return nullptr;
}
@@ -1014,12 +1048,14 @@ IDBRequest* IDBObjectStore::count(ScriptState* script_state,
IDBRequest::AsyncTraceState metrics("IDBObjectStore::count");
if (IsDeleted()) {
exception_state.ThrowDOMException(
- kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
+ DOMExceptionCode::kInvalidStateError,
+ IDBDatabase::kObjectStoreDeletedErrorMessage);
return nullptr;
}
if (!transaction_->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction_->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction_->InactiveErrorMessage());
return nullptr;
}
@@ -1029,7 +1065,7 @@ IDBRequest* IDBObjectStore::count(ScriptState* script_state,
return nullptr;
if (!BackendDB()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_object_store.h b/chromium/third_party/blink/renderer/modules/indexeddb/idb_object_store.h
index 6a33e485e30..8284b43f1c1 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_object_store.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_object_store.h
@@ -56,6 +56,7 @@ class MODULES_EXPORT IDBObjectStore final : public ScriptWrappable {
return new IDBObjectStore(std::move(metadata), transaction);
}
~IDBObjectStore() override = default;
+
void Trace(blink::Visitor*) override;
const IDBObjectStoreMetadata& Metadata() const { return *metadata_; }
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_observation.cc b/chromium/third_party/blink/renderer/modules/indexeddb/idb_observation.cc
index 867f2799190..4e7f2df4948 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_observation.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_observation.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/modules/indexeddb/idb_observation.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_observation.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/bindings/modules/v8/to_v8_for_modules.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h"
@@ -13,6 +12,7 @@
#include "third_party/blink/renderer/modules/indexeddb/idb_any.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_value.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_observer.cc b/chromium/third_party/blink/renderer/modules/indexeddb/idb_observer.cc
index ce090e91552..c40aefac549 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_observer.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_observer.cc
@@ -6,16 +6,15 @@
#include <bitset>
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/modules/v8/to_v8_for_modules.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_idb_observer_callback.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/indexed_db_names.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_database.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_observer_changes.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_observer_init.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_transaction.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -31,18 +30,19 @@ void IDBObserver::observe(IDBDatabase* database,
const IDBObserverInit& options,
ExceptionState& exception_state) {
if (!transaction->IsActive()) {
- exception_state.ThrowDOMException(kTransactionInactiveError,
- transaction->InactiveErrorMessage());
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kTransactionInactiveError,
+ transaction->InactiveErrorMessage());
return;
}
if (transaction->IsVersionChange()) {
exception_state.ThrowDOMException(
- kTransactionInactiveError,
+ DOMExceptionCode::kTransactionInactiveError,
IDBDatabase::kCannotObserveVersionChangeTransaction);
return;
}
if (!database->Backend()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return;
}
@@ -82,7 +82,7 @@ void IDBObserver::observe(IDBDatabase* database,
void IDBObserver::unobserve(IDBDatabase* database,
ExceptionState& exception_state) {
if (!database->Backend()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return;
}
@@ -104,9 +104,4 @@ void IDBObserver::Trace(blink::Visitor* visitor) {
ScriptWrappable::Trace(visitor);
}
-void IDBObserver::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(callback_);
- ScriptWrappable::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_observer.h b/chromium/third_party/blink/renderer/modules/indexeddb/idb_observer.h
index 5bc8323da09..78ac326ef80 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_observer.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_observer.h
@@ -36,7 +36,6 @@ class MODULES_EXPORT IDBObserver final : public ScriptWrappable {
void unobserve(IDBDatabase*, ExceptionState&);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
explicit IDBObserver(V8IDBObserverCallback*);
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_observer_changes.cc b/chromium/third_party/blink/renderer/modules/indexeddb/idb_observer_changes.cc
index 7483aadd6d7..1e5ceec881b 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_observer_changes.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_observer_changes.cc
@@ -5,13 +5,13 @@
#include "third_party/blink/renderer/modules/indexeddb/idb_observer_changes.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_observation.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/modules/v8/to_v8_for_modules.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_any.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_observation.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.cc b/chromium/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.cc
index d8806e76e42..38205ce3f8b 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.cc
@@ -29,7 +29,6 @@
#include "base/optional.h"
#include "third_party/blink/renderer/bindings/modules/v8/idb_object_store_or_idb_index_or_idb_cursor.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_database.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_database_callbacks.h"
@@ -193,10 +192,9 @@ DispatchEventResult IDBOpenDBRequest::DispatchEventInternal(Event* event) {
if (event->type() == EventTypeNames::success &&
ResultAsAny()->GetType() == IDBAny::kIDBDatabaseType &&
ResultAsAny()->IdbDatabase()->IsClosePending()) {
- DequeueEvent(event);
SetResult(nullptr);
- HandleResponse(
- DOMException::Create(kAbortError, "The connection was closed."));
+ HandleResponse(DOMException::Create(DOMExceptionCode::kAbortError,
+ "The connection was closed."));
return DispatchEventResult::kCanceledBeforeDispatch;
}
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_request.cc b/chromium/third_party/blink/renderer/modules/indexeddb/idb_request.cc
index bda14b6e867..49cdcc08c0f 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_request.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_request.cc
@@ -33,14 +33,12 @@
#include <utility>
#include "third_party/blink/public/platform/web_blob_info.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/bindings/modules/v8/idb_object_store_or_idb_index_or_idb_cursor.h"
#include "third_party/blink/renderer/bindings/modules/v8/to_v8_for_modules.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/dom/events/event_queue.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/indexed_db_names.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.h"
@@ -51,6 +49,7 @@
#include "third_party/blink/renderer/modules/indexeddb/idb_value.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.h"
#include "third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
@@ -138,7 +137,9 @@ IDBRequest::IDBRequest(ScriptState* script_state,
transaction_(transaction),
isolate_(script_state->GetIsolate()),
metrics_(std::move(metrics)),
- source_(source) {}
+ source_(source),
+ event_queue_(EventQueue::Create(ExecutionContext::From(script_state),
+ TaskType::kInternalIndexedDB)) {}
IDBRequest::~IDBRequest() {
DCHECK((ready_state_ == DONE && metrics_.IsEmpty()) ||
@@ -150,7 +151,7 @@ void IDBRequest::Trace(blink::Visitor* visitor) {
visitor->Trace(source_);
visitor->Trace(result_);
visitor->Trace(error_);
- visitor->Trace(enqueued_events_);
+ visitor->Trace(event_queue_);
visitor->Trace(pending_cursor_);
EventTargetWithInlineData::Trace(visitor);
PausableObject::Trace(visitor);
@@ -162,11 +163,12 @@ ScriptValue IDBRequest::result(ScriptState* script_state,
// Must throw if returning an empty value. Message is arbitrary since it
// will never be seen.
exception_state.ThrowDOMException(
- kInvalidStateError, IDBDatabase::kRequestNotFinishedErrorMessage);
+ DOMExceptionCode::kInvalidStateError,
+ IDBDatabase::kRequestNotFinishedErrorMessage);
return ScriptValue();
}
if (!GetExecutionContext()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
IDBDatabase::kDatabaseClosedErrorMessage);
return ScriptValue();
}
@@ -178,7 +180,8 @@ ScriptValue IDBRequest::result(ScriptState* script_state,
DOMException* IDBRequest::error(ExceptionState& exception_state) const {
if (ready_state_ != DONE) {
exception_state.ThrowDOMException(
- kInvalidStateError, IDBDatabase::kRequestNotFinishedErrorMessage);
+ DOMExceptionCode::kInvalidStateError,
+ IDBDatabase::kRequestNotFinishedErrorMessage);
return nullptr;
}
return error_;
@@ -225,17 +228,12 @@ void IDBRequest::Abort() {
if (ready_state_ == DONE)
return;
- EventQueue* event_queue = GetExecutionContext()->GetEventQueue();
- for (size_t i = 0; i < enqueued_events_.size(); ++i) {
- bool removed = event_queue->CancelEvent(enqueued_events_[i].Get());
- DCHECK(removed);
- }
- enqueued_events_.clear();
+ event_queue_->CancelAllEvents();
error_.Clear();
result_.Clear();
EnqueueResponse(DOMException::Create(
- kAbortError,
+ DOMExceptionCode::kAbortError,
"The transaction was aborted, so the request cannot be fulfilled."));
request_aborted_ = true;
}
@@ -298,7 +296,7 @@ bool IDBRequest::ShouldEnqueueEvent() const {
// NotifyContextDestroyed() call yet, it will hang onto an ExecutionContext
// whose event queue has been nulled out. The event queue null check covers
// these specific circumstances.
- if (!execution_context || !execution_context->GetEventQueue())
+ if (!execution_context)
return false;
DCHECK(ready_state_ == PENDING || ready_state_ == DONE);
@@ -613,7 +611,6 @@ void IDBRequest::ContextDestroyed(ExecutionContext*) {
transaction_->UnregisterRequest(this);
}
- enqueued_events_.clear();
if (source_.IsIDBCursor())
source_.GetAsIDBCursor()->ContextWillBeDestroyed();
if (result_)
@@ -640,12 +637,10 @@ DispatchEventResult IDBRequest::DispatchEventInternal(Event* event) {
return DispatchEventResult::kCanceledBeforeDispatch;
DCHECK_EQ(ready_state_, PENDING);
DCHECK(has_pending_activity_);
- DCHECK(enqueued_events_.size());
DCHECK_EQ(event->target(), this);
if (event->type() != EventTypeNames::blocked)
ready_state_ = DONE;
- DequeueEvent(event);
HeapVector<Member<EventTarget>> targets;
targets.push_back(this);
@@ -708,8 +703,9 @@ DispatchEventResult IDBRequest::DispatchEventInternal(Event* event) {
// (which might trigger commit).
if (!request_aborted_) {
if (did_throw_in_event_handler_) {
- transaction_->SetError(DOMException::Create(
- kAbortError, "Uncaught exception in event handler."));
+ transaction_->SetError(
+ DOMException::Create(DOMExceptionCode::kAbortError,
+ "Uncaught exception in event handler."));
transaction_->abort(IGNORE_EXCEPTION_FOR_TESTING);
} else if (event->type() == EventTypeNames::error &&
dispatch_result == DispatchEventResult::kNotCanceled) {
@@ -763,21 +759,9 @@ void IDBRequest::EnqueueEvent(Event* event) {
<< "When queueing event " << event->type() << ", ready_state_ was "
<< ready_state_;
- EventQueue* event_queue = GetExecutionContext()->GetEventQueue();
event->SetTarget(this);
- // Keep track of enqueued events in case we need to abort prior to dispatch,
- // in which case these must be cancelled. If the events not dispatched for
- // other reasons they must be removed from this list via DequeueEvent().
- if (event_queue->EnqueueEvent(FROM_HERE, event))
- enqueued_events_.push_back(event);
-}
-
-void IDBRequest::DequeueEvent(Event* event) {
- for (size_t i = 0; i < enqueued_events_.size(); ++i) {
- if (enqueued_events_[i].Get() == event)
- enqueued_events_.EraseAt(i);
- }
+ event_queue_->EnqueueEvent(FROM_HERE, event);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_request.h b/chromium/third_party/blink/renderer/modules/indexeddb/idb_request.h
index 8ce4b0d81b0..51017b09d7a 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_request.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_request.h
@@ -42,6 +42,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/idb_object_store_or_idb_index_or_idb_cursor.h"
#include "third_party/blink/renderer/core/dom/dom_string_list.h"
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
+#include "third_party/blink/renderer/core/dom/events/event_queue.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/dom/pausable_object.h"
#include "third_party/blink/renderer/modules/event_modules.h"
@@ -335,7 +336,6 @@ class MODULES_EXPORT IDBRequest : public EventTargetWithInlineData,
protected:
IDBRequest(ScriptState*, const Source&, IDBTransaction*, AsyncTraceState);
void EnqueueEvent(Event*);
- void DequeueEvent(Event*);
virtual bool ShouldEnqueueEvent() const;
void EnqueueResultInternal(IDBAny*);
void SetResult(IDBAny*);
@@ -388,7 +388,7 @@ class MODULES_EXPORT IDBRequest : public EventTargetWithInlineData,
Member<DOMException> error_;
bool has_pending_activity_ = true;
- HeapVector<Member<Event>> enqueued_events_;
+ Member<EventQueue> event_queue_;
// Only used if the result type will be a cursor.
IndexedDB::CursorType cursor_type_ = IndexedDB::kCursorKeyAndValue;
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_request_loader.cc b/chromium/third_party/blink/renderer/modules/indexeddb/idb_request_loader.cc
index 05fd0b31c7b..f3a516cfcef 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_request_loader.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_request_loader.cc
@@ -139,8 +139,8 @@ void IDBRequestLoader::ReportError() {
DCHECK(started_);
DCHECK(!canceled_);
#endif // DCHECK_IS_ON()
- queue_item_->OnResultLoadComplete(
- DOMException::Create(kDataError, "Failed to read large IndexedDB value"));
+ queue_item_->OnResultLoadComplete(DOMException::Create(
+ DOMExceptionCode::kDataError, "Failed to read large IndexedDB value"));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.cc b/chromium/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.cc
index 89cb7b04ab8..cfbe57f7323 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <utility>
+#include "base/callback.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_cursor.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.h b/chromium/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.h
index a02b249774d..2cb8f84ed02 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.h
@@ -7,6 +7,7 @@
#include <memory>
+#include "base/callback.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc b/chromium/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc
index b767ab6295b..f7003c6e2bd 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc
@@ -35,7 +35,6 @@
#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/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/testing/null_execution_context.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_database.h"
@@ -106,8 +105,8 @@ void EnsureIDBCallbacksDontThrow(IDBRequest* request,
ASSERT_TRUE(request->transaction());
V8TestingScope scope;
- request->HandleResponse(
- DOMException::Create(kAbortError, "Description goes here."));
+ request->HandleResponse(DOMException::Create(DOMExceptionCode::kAbortError,
+ "Description goes here."));
request->HandleResponse(nullptr, IDBKey::CreateInvalid(),
IDBKey::CreateInvalid(),
CreateNullIDBValueForTesting(scope.GetIsolate()));
@@ -231,8 +230,8 @@ TEST_F(IDBRequestTest, AbortErrorAfterAbort) {
// Now simulate the back end having fired an abort error at the request to
// clear up any intermediaries. Ensure an assertion is not raised.
- request->HandleResponse(
- DOMException::Create(kAbortError, "Description goes here."));
+ request->HandleResponse(DOMException::Create(DOMExceptionCode::kAbortError,
+ "Description goes here."));
// Stop the request lest it be GCed and its destructor
// finds the object in a pending state (and asserts.)
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.cc b/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.cc
index c0cc9b2be5d..68b3d5d58b7 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.cc
@@ -25,10 +25,8 @@
#include "third_party/blink/renderer/modules/indexeddb/idb_transaction.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/dom/events/event_queue.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/indexed_db_names.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_database.h"
@@ -38,6 +36,7 @@
#include "third_party/blink/renderer/modules/indexeddb/idb_open_db_request.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_request_queue_item.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_tracing.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/bindings/v8_per_isolate_data.h"
@@ -90,7 +89,9 @@ IDBTransaction::IDBTransaction(ExecutionContext* execution_context,
database_(db),
mode_(kWebIDBTransactionModeReadOnly),
scope_(scope),
- state_(kActive) {
+ state_(kActive),
+ event_queue_(
+ EventQueue::Create(execution_context, TaskType::kInternalIndexedDB)) {
DCHECK(database_);
DCHECK(!scope_.IsEmpty()) << "Observer transactions must operate "
"on a well-defined set of stores";
@@ -106,7 +107,9 @@ IDBTransaction::IDBTransaction(ScriptState* script_state,
id_(id),
database_(db),
mode_(mode),
- scope_(scope) {
+ scope_(scope),
+ event_queue_(EventQueue::Create(ExecutionContext::From(script_state),
+ TaskType::kInternalIndexedDB)) {
DCHECK(database_);
DCHECK(!scope_.IsEmpty()) << "Non-versionchange transactions must operate "
"on a well-defined set of stores";
@@ -133,7 +136,9 @@ IDBTransaction::IDBTransaction(ExecutionContext* execution_context,
open_db_request_(open_db_request),
mode_(kWebIDBTransactionModeVersionChange),
state_(kInactive),
- old_database_metadata_(old_metadata) {
+ old_database_metadata_(old_metadata),
+ event_queue_(
+ EventQueue::Create(execution_context, TaskType::kInternalIndexedDB)) {
DCHECK(database_);
DCHECK(open_db_request_);
DCHECK(scope_.IsEmpty());
@@ -157,6 +162,7 @@ void IDBTransaction::Trace(blink::Visitor* visitor) {
visitor->Trace(object_store_map_);
visitor->Trace(old_store_metadata_);
visitor->Trace(deleted_indexes_);
+ visitor->Trace(event_queue_);
EventTargetWithInlineData::Trace(visitor);
ContextLifecycleObserver::Trace(visitor);
}
@@ -175,7 +181,8 @@ IDBObjectStore* IDBTransaction::objectStore(const String& name,
ExceptionState& exception_state) {
if (IsFinished() || IsFinishing()) {
exception_state.ThrowDOMException(
- kInvalidStateError, IDBDatabase::kTransactionFinishedErrorMessage);
+ DOMExceptionCode::kInvalidStateError,
+ IDBDatabase::kTransactionFinishedErrorMessage);
return nullptr;
}
@@ -185,7 +192,8 @@ IDBObjectStore* IDBTransaction::objectStore(const String& name,
if (!IsVersionChange() && !scope_.Contains(name)) {
exception_state.ThrowDOMException(
- kNotFoundError, IDBDatabase::kNoSuchObjectStoreErrorMessage);
+ DOMExceptionCode::kNotFoundError,
+ IDBDatabase::kNoSuchObjectStoreErrorMessage);
return nullptr;
}
@@ -193,7 +201,8 @@ IDBObjectStore* IDBTransaction::objectStore(const String& name,
if (object_store_id == IDBObjectStoreMetadata::kInvalidId) {
DCHECK(IsVersionChange());
exception_state.ThrowDOMException(
- kNotFoundError, IDBDatabase::kNoSuchObjectStoreErrorMessage);
+ DOMExceptionCode::kNotFoundError,
+ IDBDatabase::kNoSuchObjectStoreErrorMessage);
return nullptr;
}
@@ -333,7 +342,8 @@ void IDBTransaction::SetActive(bool active) {
void IDBTransaction::abort(ExceptionState& exception_state) {
if (state_ == kFinishing || state_ == kFinished) {
exception_state.ThrowDOMException(
- kInvalidStateError, IDBDatabase::kTransactionFinishedErrorMessage);
+ DOMExceptionCode::kInvalidStateError,
+ IDBDatabase::kTransactionFinishedErrorMessage);
return;
}
@@ -546,9 +556,8 @@ void IDBTransaction::EnqueueEvent(Event* event) {
if (!GetExecutionContext())
return;
- EventQueue* event_queue = GetExecutionContext()->GetEventQueue();
event->SetTarget(this);
- event_queue->EnqueueEvent(FROM_HERE, event);
+ event_queue_->EnqueueEvent(FROM_HERE, event);
}
void IDBTransaction::AbortOutstandingRequests() {
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.h b/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.h
index 243d3491fd5..5a2970a568d 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction.h
@@ -47,6 +47,7 @@
namespace blink {
class DOMException;
+class EventQueue;
class ExecutionContext;
class ExceptionState;
class IDBDatabase;
@@ -280,6 +281,8 @@ class MODULES_EXPORT IDBTransaction final
//
// Only valid for versionchange transactions.
IDBDatabaseMetadata old_database_metadata_;
+
+ Member<EventQueue> event_queue_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction_test.cc b/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction_test.cc
index 4dd059531af..732ed6a1157 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction_test.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_transaction_test.cc
@@ -40,7 +40,6 @@
#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/dom/events/event_queue.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_database.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_database_callbacks.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_key.h"
@@ -142,7 +141,8 @@ TEST_F(IDBTransactionTest, ContextDestroyedEarlyDeath) {
// This will generate an Abort() call to the back end which is dropped by the
// fake proxy, so an explicit OnAbort call is made.
scope.GetExecutionContext()->NotifyContextDestroyed();
- transaction_->OnAbort(DOMException::Create(kAbortError, "Aborted"));
+ transaction_->OnAbort(
+ DOMException::Create(DOMExceptionCode::kAbortError, "Aborted"));
transaction_.Clear();
store_.Clear();
@@ -177,14 +177,14 @@ TEST_F(IDBTransactionTest, ContextDestroyedAfterDone) {
// This will generate an Abort() call to the back end which is dropped by the
// fake proxy, so an explicit OnAbort call is made.
scope.GetExecutionContext()->NotifyContextDestroyed();
- transaction_->OnAbort(DOMException::Create(kAbortError, "Aborted"));
+ transaction_->OnAbort(
+ DOMException::Create(DOMExceptionCode::kAbortError, "Aborted"));
transaction_.Clear();
store_.Clear();
// The request completed, so it has enqueued a success event. Discard the
// event, so that the transaction can go away.
EXPECT_EQ(1U, live_transactions.size());
- scope.GetExecutionContext()->GetEventQueue()->Close();
ThreadState::Current()->CollectAllGarbage();
EXPECT_EQ(0U, live_transactions.size());
@@ -216,7 +216,8 @@ TEST_F(IDBTransactionTest, ContextDestroyedWithQueuedResult) {
// This will generate an Abort() call to the back end which is dropped by the
// fake proxy, so an explicit OnAbort call is made.
scope.GetExecutionContext()->NotifyContextDestroyed();
- transaction_->OnAbort(DOMException::Create(kAbortError, "Aborted"));
+ transaction_->OnAbort(
+ DOMException::Create(DOMExceptionCode::kAbortError, "Aborted"));
transaction_.Clear();
store_.Clear();
@@ -257,7 +258,8 @@ TEST_F(IDBTransactionTest, ContextDestroyedWithTwoQueuedResults) {
// This will generate an Abort() call to the back end which is dropped by the
// fake proxy, so an explicit OnAbort call is made.
scope.GetExecutionContext()->NotifyContextDestroyed();
- transaction_->OnAbort(DOMException::Create(kAbortError, "Aborted"));
+ transaction_->OnAbort(
+ DOMException::Create(DOMExceptionCode::kAbortError, "Aborted"));
transaction_.Clear();
store_.Clear();
@@ -300,7 +302,8 @@ TEST_F(IDBTransactionTest, DocumentShutdownWithQueuedAndBlockedResults) {
// This will generate an Abort() call to the back end which is dropped by the
// fake proxy, so an explicit OnAbort call is made.
scope.GetDocument().Shutdown();
- transaction_->OnAbort(DOMException::Create(kAbortError, "Aborted"));
+ transaction_->OnAbort(
+ DOMException::Create(DOMExceptionCode::kAbortError, "Aborted"));
transaction_.Clear();
store_.Clear();
@@ -340,7 +343,8 @@ TEST_F(IDBTransactionTest, TransactionFinish) {
// Fire an abort to make sure this doesn't free the transaction during use.
// The test will not fail if it is, but ASAN would notice the error.
- db_->OnAbort(kTransactionId, DOMException::Create(kAbortError, "Aborted"));
+ db_->OnAbort(kTransactionId,
+ DOMException::Create(DOMExceptionCode::kAbortError, "Aborted"));
// OnAbort() should have cleared the transaction's reference to the database.
ThreadState::Current()->CollectAllGarbage();
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.h b/chromium/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.h
index 879fd93a6e6..5ae34bdef89 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/idb_value_wrapping.h
@@ -8,9 +8,9 @@
#include "base/feature_list.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/platform/web_blob_info.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/string_view.h"
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_client.cc b/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_client.cc
index 7d7df261903..b92e3a87e24 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_client.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_client.cc
@@ -70,11 +70,6 @@ void IndexedDBClient::Trace(blink::Visitor* visitor) {
Supplement<WorkerClients>::Trace(visitor);
}
-void IndexedDBClient::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- Supplement<LocalFrame>::TraceWrappers(visitor);
- Supplement<WorkerClients>::TraceWrappers(visitor);
-}
-
void ProvideIndexedDBClientTo(LocalFrame& frame, IndexedDBClient* client) {
Supplement<LocalFrame>::ProvideTo(frame, client);
}
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_client.h b/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_client.h
index d6f2858b7a5..e34ad57b346 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_client.h
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/indexed_db_client.h
@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/workers/worker_clients.h"
#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.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/text/wtf_string.h"
@@ -44,7 +45,7 @@ class WorkerClients;
class IndexedDBClient : public GarbageCollected<IndexedDBClient>,
public Supplement<LocalFrame>,
public Supplement<WorkerClients>,
- public TraceWrapperBase {
+ public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(IndexedDBClient);
WTF_MAKE_NONCOPYABLE(IndexedDBClient);
@@ -55,7 +56,6 @@ class IndexedDBClient : public GarbageCollected<IndexedDBClient>,
static IndexedDBClient* Create(WorkerClients&);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override { return "IndexedDBClient"; }
bool AllowIndexedDB(ExecutionContext*, const String& name);
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc b/chromium/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc
index da51ab297f9..c3f3e7a21a5 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc
@@ -35,7 +35,6 @@
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_cursor.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_types.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -60,6 +59,7 @@
#include "third_party/blink/renderer/modules/indexeddb/idb_open_db_request.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_request.h"
#include "third_party/blink/renderer/modules/indexeddb/idb_transaction.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/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -97,10 +97,10 @@ static const char kIndexedDBAgentEnabled[] = "indexedDBAgentEnabled";
namespace {
-static const char kIndexedDBObjectGroup[] = "indexeddb";
-static const char kNoDocumentError[] = "No document for given frame found";
+const char kIndexedDBObjectGroup[] = "indexeddb";
+const char kNoDocumentError[] = "No document for given frame found";
-static Response AssertIDBFactory(Document* document, IDBFactory*& result) {
+Response AssertIDBFactory(Document* document, IDBFactory*& result) {
LocalDOMWindow* dom_window = document->domWindow();
if (!dom_window)
return Response::Error("No IndexedDB factory for given frame found");
@@ -151,10 +151,6 @@ class GetDatabaseNamesCallback final : public EventListener {
request_callback_->sendSuccess(std::move(database_names));
}
- void Trace(blink::Visitor* visitor) override {
- EventListener::Trace(visitor);
- }
-
private:
GetDatabaseNamesCallback(
std::unique_ptr<RequestDatabaseNamesCallback> request_callback,
@@ -191,10 +187,6 @@ class DeleteCallback final : public EventListener {
request_callback_->sendSuccess();
}
- void Trace(blink::Visitor* visitor) override {
- EventListener::Trace(visitor);
- }
-
private:
DeleteCallback(std::unique_ptr<DeleteDatabaseCallback> request_callback,
const String& security_origin)
@@ -273,7 +265,7 @@ class OpenDatabaseCallback final : public EventListener {
public:
static OpenDatabaseCallback* Create(
ExecutableWithDatabase<RequestCallback>* executable_with_database,
- scoped_refptr<ScriptState> script_state) {
+ ScriptState* script_state) {
return new OpenDatabaseCallback(executable_with_database, script_state);
}
@@ -300,21 +292,26 @@ class OpenDatabaseCallback final : public EventListener {
}
IDBDatabase* idb_database = request_result->IdbDatabase();
- executable_with_database_->Execute(idb_database, script_state_.get());
+ executable_with_database_->Execute(idb_database, script_state_);
V8PerIsolateData::From(script_state_->GetIsolate())->RunEndOfScopeTasks();
idb_database->close();
}
+ void Trace(blink::Visitor* visitor) override {
+ visitor->Trace(script_state_);
+ EventListener::Trace(visitor);
+ }
+
private:
OpenDatabaseCallback(
ExecutableWithDatabase<RequestCallback>* executable_with_database,
- scoped_refptr<ScriptState> script_state)
+ ScriptState* script_state)
: EventListener(EventListener::kCPPEventListenerType),
executable_with_database_(executable_with_database),
script_state_(script_state) {}
scoped_refptr<ExecutableWithDatabase<RequestCallback>>
executable_with_database_;
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
};
template <typename RequestCallback>
@@ -358,7 +355,7 @@ class UpgradeDatabaseCallback final : public EventListener {
executable_with_database_;
};
-static IDBTransaction* TransactionForDatabase(
+IDBTransaction* TransactionForDatabase(
ScriptState* script_state,
IDBDatabase* idb_database,
const String& object_store_name,
@@ -373,9 +370,8 @@ static IDBTransaction* TransactionForDatabase(
return idb_transaction;
}
-static IDBObjectStore* ObjectStoreForTransaction(
- IDBTransaction* idb_transaction,
- const String& object_store_name) {
+IDBObjectStore* ObjectStoreForTransaction(IDBTransaction* idb_transaction,
+ const String& object_store_name) {
DummyExceptionStateForTesting exception_state;
IDBObjectStore* idb_object_store =
idb_transaction->objectStore(object_store_name, exception_state);
@@ -384,8 +380,8 @@ static IDBObjectStore* ObjectStoreForTransaction(
return idb_object_store;
}
-static IDBIndex* IndexForObjectStore(IDBObjectStore* idb_object_store,
- const String& index_name) {
+IDBIndex* IndexForObjectStore(IDBObjectStore* idb_object_store,
+ const String& index_name) {
DummyExceptionStateForTesting exception_state;
IDBIndex* idb_index = idb_object_store->index(index_name, exception_state);
if (exception_state.HadException())
@@ -393,8 +389,7 @@ static IDBIndex* IndexForObjectStore(IDBObjectStore* idb_object_store,
return idb_index;
}
-static std::unique_ptr<KeyPath> KeyPathFromIDBKeyPath(
- const IDBKeyPath& idb_key_path) {
+std::unique_ptr<KeyPath> KeyPathFromIDBKeyPath(const IDBKeyPath& idb_key_path) {
std::unique_ptr<KeyPath> key_path;
switch (idb_key_path.GetType()) {
case IDBKeyPath::kNullType:
@@ -618,25 +613,23 @@ class OpenCursorCallback final : public EventListener {
return;
}
- Document* document =
- ToDocument(ExecutionContext::From(script_state_.get()));
+ Document* document = ToDocument(ExecutionContext::From(script_state_));
if (!document)
return;
- ScriptState* script_state = script_state_.get();
- ScriptState::Scope scope(script_state);
- v8::Local<v8::Context> context = script_state->GetContext();
+ ScriptState::Scope scope(script_state_);
+ v8::Local<v8::Context> context = script_state_->GetContext();
v8_inspector::StringView object_group =
ToV8InspectorStringView(kIndexedDBObjectGroup);
std::unique_ptr<DataEntry> data_entry =
DataEntry::create()
.setKey(v8_session_->wrapObject(
- context, idb_cursor->key(script_state).V8Value(), object_group,
+ context, idb_cursor->key(script_state_).V8Value(), object_group,
true /* generatePreview */))
.setPrimaryKey(v8_session_->wrapObject(
- context, idb_cursor->primaryKey(script_state).V8Value(),
+ context, idb_cursor->primaryKey(script_state_).V8Value(),
object_group, true /* generatePreview */))
.setValue(v8_session_->wrapObject(
- context, idb_cursor->value(script_state).V8Value(),
+ context, idb_cursor->value(script_state_).V8Value(),
object_group, true /* generatePreview */))
.build();
result_->addItem(std::move(data_entry));
@@ -647,6 +640,7 @@ class OpenCursorCallback final : public EventListener {
}
void Trace(blink::Visitor* visitor) override {
+ visitor->Trace(script_state_);
EventListener::Trace(visitor);
}
@@ -666,7 +660,7 @@ class OpenCursorCallback final : public EventListener {
}
v8_inspector::V8InspectorSession* v8_session_;
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
std::unique_ptr<RequestDataCallback> request_callback_;
int skip_count_;
unsigned page_size_;
@@ -891,10 +885,6 @@ class DeleteObjectStoreEntriesListener final : public EventListener {
request_callback_->sendSuccess();
}
- void Trace(blink::Visitor* visitor) override {
- EventListener::Trace(visitor);
- }
-
private:
DeleteObjectStoreEntriesListener(
std::unique_ptr<DeleteObjectStoreEntriesCallback> request_callback)
@@ -1001,10 +991,6 @@ class ClearObjectStoreListener final : public EventListener {
request_callback_->sendSuccess();
}
- void Trace(blink::Visitor* visitor) override {
- EventListener::Trace(visitor);
- }
-
private:
ClearObjectStoreListener(
std::unique_ptr<ClearObjectStoreCallback> request_callback)
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc
index a81c45459d4..bebb7e661d8 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_callbacks_impl.cc
@@ -82,7 +82,8 @@ void WebIDBCallbacksImpl::OnError(const WebIDBDatabaseError& error) {
return;
probe::AsyncTask async_task(request_->GetExecutionContext(), this, "error");
- request_->HandleResponse(DOMException::Create(error.Code(), error.Message()));
+ request_->HandleResponse(DOMException::Create(
+ static_cast<DOMExceptionCode>(error.Code()), error.Message()));
}
void WebIDBCallbacksImpl::OnSuccess(
diff --git a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database_callbacks_impl.cc b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database_callbacks_impl.cc
index b2bfa8cc16a..fc7c46b8722 100644
--- a/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database_callbacks_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/indexeddb/web_idb_database_callbacks_impl.cc
@@ -70,8 +70,10 @@ void WebIDBDatabaseCallbacksImpl::OnVersionChange(long long old_version,
void WebIDBDatabaseCallbacksImpl::OnAbort(long long transaction_id,
const WebIDBDatabaseError& error) {
if (callbacks_) {
- callbacks_->OnAbort(transaction_id,
- DOMException::Create(error.Code(), error.Message()));
+ callbacks_->OnAbort(
+ transaction_id,
+ DOMException::Create(static_cast<DOMExceptionCode>(error.Code()),
+ error.Message()));
}
}
diff --git a/chromium/third_party/blink/renderer/modules/installedapp/navigator_installed_app.cc b/chromium/third_party/blink/renderer/modules/installedapp/navigator_installed_app.cc
index 09f2fe93842..ed430f8b897 100644
--- a/chromium/third_party/blink/renderer/modules/installedapp/navigator_installed_app.cc
+++ b/chromium/third_party/blink/renderer/modules/installedapp/navigator_installed_app.cc
@@ -12,7 +12,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/dom/exception_code.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"
@@ -77,7 +76,7 @@ ScriptPromise NavigatorInstalledApp::getInstalledRelatedApps(
InstalledAppController* app_controller = Controller();
if (!app_controller) { // If the associated frame is detached
DOMException* exception = DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"The object is no longer associated to a document.");
resolver->Reject(exception);
return promise;
@@ -85,7 +84,7 @@ ScriptPromise NavigatorInstalledApp::getInstalledRelatedApps(
if (!app_controller->GetSupplementable()->IsMainFrame()) {
DOMException* exception =
- DOMException::Create(kInvalidStateError,
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
"getInstalledRelatedApps() is only supported in "
"top-level browsing contexts.");
resolver->Reject(exception);
diff --git a/chromium/third_party/blink/renderer/modules/keyboard/keyboard.idl b/chromium/third_party/blink/renderer/modules/keyboard/keyboard.idl
index b7456431219..86832c9d1d4 100644
--- a/chromium/third_party/blink/renderer/modules/keyboard/keyboard.idl
+++ b/chromium/third_party/blink/renderer/modules/keyboard/keyboard.idl
@@ -2,10 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// TODO(joedow): Remove RuntimeEnabled flag after the next branch point.
[
Exposed=Window,
- RuntimeEnabled=KeyboardLock,
SecureContext
] interface Keyboard {
// Keyboard Lock specification: https://w3c.github.io/keyboard-lock/
@@ -19,7 +17,6 @@
// Keyboard Map specification: https://wicg.github.io/keyboard-map/
[CallWith=ScriptState,
- RuntimeEnabled=KeyboardMap,
MeasureAs=KeyboardApiGetLayoutMap
] Promise<KeyboardLayoutMap> getLayoutMap();
};
diff --git a/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.cc b/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.cc
index 43d7f10f1d6..c4d58193ebf 100644
--- a/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.cc
+++ b/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.cc
@@ -5,14 +5,29 @@
#include "third_party/blink/renderer/modules/keyboard/keyboard_layout.h"
#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/mojom/page/page_visibility_state.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/frame/local_frame.h"
namespace blink {
+namespace {
+
+constexpr char kKeyboardMapFrameDetachedErrorMsg[] =
+ "Current frame is detached.";
+
+constexpr char kKeyboardMapChildFrameErrorMsg[] =
+ "getLayoutMap() must be called from a top-level browsing context.";
+
+constexpr char kKeyboardMapRequestFailedErrorMsg[] =
+ "getLayoutMap() request could not be completed.";
+
+} // namespace
+
using mojom::PageVisibilityState;
KeyboardLayout::KeyboardLayout(ExecutionContext* context)
@@ -21,18 +36,41 @@ KeyboardLayout::KeyboardLayout(ExecutionContext* context)
ScriptPromise KeyboardLayout::GetKeyboardLayoutMap(ScriptState* script_state) {
DCHECK(script_state);
- script_promise_resolver_ = ScriptPromiseResolver::Create(script_state);
- if (EnsureServiceConnected()) {
- service_->GetKeyboardLayoutMap(
- WTF::Bind(&KeyboardLayout::GotKeyboardLayoutMap, WrapPersistent(this),
- WrapPersistent(script_promise_resolver_.Get())));
+ if (script_promise_resolver_) {
return script_promise_resolver_->Promise();
}
- script_promise_resolver_->Reject();
+ if (!IsLocalFrameAttached()) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kKeyboardMapFrameDetachedErrorMsg));
+ }
+
+ if (!CalledFromSupportedContext(ExecutionContext::From(script_state))) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kKeyboardMapChildFrameErrorMsg));
+ }
+
+ if (!EnsureServiceConnected()) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kKeyboardMapRequestFailedErrorMsg));
+ }
+
+ script_promise_resolver_ = ScriptPromiseResolver::Create(script_state);
+ service_->GetKeyboardLayoutMap(
+ WTF::Bind(&KeyboardLayout::GotKeyboardLayoutMap, WrapPersistent(this),
+ WrapPersistent(script_promise_resolver_.Get())));
return script_promise_resolver_->Promise();
}
+bool KeyboardLayout::IsLocalFrameAttached() {
+ if (GetFrame())
+ return true;
+ return false;
+}
+
bool KeyboardLayout::EnsureServiceConnected() {
if (!service_) {
LocalFrame* frame = GetFrame();
@@ -40,23 +78,36 @@ bool KeyboardLayout::EnsureServiceConnected() {
return false;
}
frame->GetInterfaceProvider().GetInterface(mojo::MakeRequest(&service_));
+ DCHECK(service_);
}
- DCHECK(service_);
return true;
}
+bool KeyboardLayout::CalledFromSupportedContext(ExecutionContext* context) {
+ DCHECK(context);
+ // This API is only accessible from a top level, secure browsing context.
+ LocalFrame* frame = GetFrame();
+ return frame && frame->IsMainFrame() && context->IsSecureContext();
+}
+
void KeyboardLayout::GotKeyboardLayoutMap(
ScriptPromiseResolver* resolver,
mojom::blink::GetKeyboardLayoutMapResultPtr result) {
DCHECK(script_promise_resolver_);
- if (result->status == mojom::blink::GetKeyboardLayoutMapStatus::kSuccess) {
- script_promise_resolver_->Resolve(
- new KeyboardLayoutMap(result->layout_map));
- return;
+ switch (result->status) {
+ case mojom::blink::GetKeyboardLayoutMapStatus::kSuccess:
+ script_promise_resolver_->Resolve(
+ new KeyboardLayoutMap(result->layout_map));
+ break;
+ case mojom::blink::GetKeyboardLayoutMapStatus::kFail:
+ script_promise_resolver_->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kKeyboardMapRequestFailedErrorMsg));
+ break;
}
- script_promise_resolver_->Reject();
+ script_promise_resolver_ = nullptr;
}
void KeyboardLayout::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.h b/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.h
index c628b7628d7..99bfe0487ca 100644
--- a/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.h
+++ b/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout.h
@@ -30,8 +30,15 @@ class KeyboardLayout final : public GarbageCollectedFinalized<KeyboardLayout>,
void Trace(blink::Visitor*) override;
private:
+ // Returns true if the local frame is attached to the renderer.
+ bool IsLocalFrameAttached();
+
+ // Returns true if |service_| is initialized and ready to be called.
bool EnsureServiceConnected();
+ // Returns true if the current frame is a top-level browsing context.
+ bool CalledFromSupportedContext(ExecutionContext*);
+
void GotKeyboardLayoutMap(ScriptPromiseResolver*,
mojom::blink::GetKeyboardLayoutMapResultPtr);
diff --git a/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout_map.h b/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout_map.h
index d0c40c795e5..d332924c37b 100644
--- a/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout_map.h
+++ b/chromium/third_party/blink/renderer/modules/keyboard/keyboard_layout_map.h
@@ -5,9 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_KEYBOARD_KEYBOARD_LAYOUT_MAP_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_KEYBOARD_KEYBOARD_LAYOUT_MAP_H_
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.cc b/chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.cc
index 2e738caa98b..274e38e53ea 100644
--- a/chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.cc
+++ b/chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.cc
@@ -8,7 +8,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
@@ -19,18 +18,19 @@ namespace blink {
namespace {
-constexpr char kFrameDetachedErrorMsg[] = "Current frame is detached.";
+constexpr char kKeyboardLockFrameDetachedErrorMsg[] =
+ "Current frame is detached.";
-constexpr char kPromisePreemptedErrorMsg[] =
+constexpr char kKeyboardLockPromisePreemptedErrorMsg[] =
"This request has been superseded by a subsequent lock() method call.";
-constexpr char kNoValidKeyCodesErrorMsg[] =
+constexpr char kKeyboardLockNoValidKeyCodesErrorMsg[] =
"No valid key codes passed into lock().";
-constexpr char kChildFrameErrorMsg[] =
+constexpr char kKeyboardLockChildFrameErrorMsg[] =
"lock() must be called from a top-level browsing context.";
-constexpr char kRequestFailedErrorMsg[] =
+constexpr char kKeyboardLockRequestFailedErrorMsg[] =
"lock() request could not be registered.";
} // namespace
@@ -44,15 +44,22 @@ ScriptPromise KeyboardLock::lock(ScriptState* state,
const Vector<String>& keycodes) {
DCHECK(state);
+ if (!IsLocalFrameAttached()) {
+ return ScriptPromise::RejectWithDOMException(
+ state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kKeyboardLockFrameDetachedErrorMsg));
+ }
+
if (!CalledFromSupportedContext(ExecutionContext::From(state))) {
return ScriptPromise::RejectWithDOMException(
- state, DOMException::Create(kInvalidStateError, kChildFrameErrorMsg));
+ state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kKeyboardLockChildFrameErrorMsg));
}
if (!EnsureServiceConnected()) {
return ScriptPromise::RejectWithDOMException(
- state,
- DOMException::Create(kInvalidStateError, kFrameDetachedErrorMsg));
+ state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kKeyboardLockRequestFailedErrorMsg));
}
request_keylock_resolver_ = ScriptPromiseResolver::Create(state);
@@ -75,6 +82,12 @@ void KeyboardLock::unlock(ScriptState* state) {
service_->CancelKeyboardLock();
}
+bool KeyboardLock::IsLocalFrameAttached() {
+ if (GetFrame())
+ return true;
+ return false;
+}
+
bool KeyboardLock::EnsureServiceConnected() {
if (!service_) {
LocalFrame* frame = GetFrame();
@@ -82,16 +95,17 @@ bool KeyboardLock::EnsureServiceConnected() {
return false;
}
frame->GetInterfaceProvider().GetInterface(mojo::MakeRequest(&service_));
+ DCHECK(service_);
}
- DCHECK(service_);
return true;
}
bool KeyboardLock::CalledFromSupportedContext(ExecutionContext* context) {
- // KeyboardLock API is only accessible from a top level browsing context.
+ DCHECK(context);
+ // This API is only accessible from a top level, secure browsing context.
LocalFrame* frame = GetFrame();
- return frame && frame->IsMainFrame();
+ return frame && frame->IsMainFrame() && context->IsSecureContext();
}
void KeyboardLock::LockRequestFinished(
@@ -101,8 +115,8 @@ void KeyboardLock::LockRequestFinished(
// If |resolver| is not the current promise, then reject the promise.
if (resolver != request_keylock_resolver_) {
- resolver->Reject(
- DOMException::Create(kAbortError, kPromisePreemptedErrorMsg));
+ resolver->Reject(DOMException::Create(
+ DOMExceptionCode::kAbortError, kKeyboardLockPromisePreemptedErrorMsg));
return;
}
@@ -112,19 +126,23 @@ void KeyboardLock::LockRequestFinished(
break;
case mojom::KeyboardLockRequestResult::kFrameDetachedError:
request_keylock_resolver_->Reject(
- DOMException::Create(kInvalidStateError, kFrameDetachedErrorMsg));
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kKeyboardLockFrameDetachedErrorMsg));
break;
case mojom::KeyboardLockRequestResult::kNoValidKeyCodesError:
request_keylock_resolver_->Reject(
- DOMException::Create(kInvalidAccessError, kNoValidKeyCodesErrorMsg));
+ DOMException::Create(DOMExceptionCode::kInvalidAccessError,
+ kKeyboardLockNoValidKeyCodesErrorMsg));
break;
case mojom::KeyboardLockRequestResult::kChildFrameError:
request_keylock_resolver_->Reject(
- DOMException::Create(kInvalidStateError, kChildFrameErrorMsg));
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kKeyboardLockChildFrameErrorMsg));
break;
case mojom::KeyboardLockRequestResult::kRequestFailedError:
request_keylock_resolver_->Reject(
- DOMException::Create(kInvalidStateError, kRequestFailedErrorMsg));
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kKeyboardLockRequestFailedErrorMsg));
break;
}
request_keylock_resolver_ = nullptr;
diff --git a/chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.h b/chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.h
index cef8ddc72da..55f1a912366 100644
--- a/chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.h
+++ b/chromium/third_party/blink/renderer/modules/keyboard/keyboard_lock.h
@@ -31,11 +31,14 @@ class KeyboardLock final : public GarbageCollectedFinalized<KeyboardLock>,
void Trace(blink::Visitor*) override;
private:
+ // Returns true if the local frame is attached to the renderer.
+ bool IsLocalFrameAttached();
+
// Returns true if |service_| is initialized and ready to be called.
bool EnsureServiceConnected();
// Returns true if the current frame is a top-level browsing context.
- bool CalledFromSupportedContext(ExecutionContext* context);
+ bool CalledFromSupportedContext(ExecutionContext*);
void LockRequestFinished(ScriptPromiseResolver*,
mojom::KeyboardLockRequestResult);
diff --git a/chromium/third_party/blink/renderer/modules/keyboard/navigator_keyboard.idl b/chromium/third_party/blink/renderer/modules/keyboard/navigator_keyboard.idl
index efda7e71a84..903a1921e5b 100644
--- a/chromium/third_party/blink/renderer/modules/keyboard/navigator_keyboard.idl
+++ b/chromium/third_party/blink/renderer/modules/keyboard/navigator_keyboard.idl
@@ -3,8 +3,7 @@
// found in the LICENSE file.
[
- ImplementedAs=NavigatorKeyboard,
- RuntimeEnabled=KeyboardLock
+ ImplementedAs=NavigatorKeyboard
] partial interface Navigator {
[SameObject, SecureContext] readonly attribute Keyboard keyboard;
};
diff --git a/chromium/third_party/blink/renderer/modules/locks/OWNERS b/chromium/third_party/blink/renderer/modules/locks/OWNERS
index c60c1f51b18..435d42dc535 100644
--- a/chromium/third_party/blink/renderer/modules/locks/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/locks/OWNERS
@@ -1 +1,4 @@
file://content/browser/locks/OWNERS
+
+# TEAM: storage-dev@chromium.org
+# COMPONENT: Blink>Storage
diff --git a/chromium/third_party/blink/renderer/modules/locks/lock.cc b/chromium/third_party/blink/renderer/modules/locks/lock.cc
index e2729a26dc1..05f7c0c50b7 100644
--- a/chromium/third_party/blink/renderer/modules/locks/lock.cc
+++ b/chromium/third_party/blink/renderer/modules/locks/lock.cc
@@ -4,12 +4,14 @@
#include "third_party/blink/renderer/modules/locks/lock.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/modules/locks/lock_manager.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
@@ -144,7 +146,8 @@ void Lock::ReleaseIfHeld() {
void Lock::OnConnectionError() {
resolver_->Reject(DOMException::Create(
- kAbortError, "Lock broken by another request with the 'steal' option."));
+ DOMExceptionCode::kAbortError,
+ "Lock broken by another request with the 'steal' option."));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/locks/lock.idl b/chromium/third_party/blink/renderer/modules/locks/lock.idl
index 3d48eddaeae..df2dd986550 100644
--- a/chromium/third_party/blink/renderer/modules/locks/lock.idl
+++ b/chromium/third_party/blink/renderer/modules/locks/lock.idl
@@ -6,7 +6,7 @@
[
SecureContext,
Exposed=(Window,Worker),
- OriginTrialEnabled=WebLocksAPI
+ RuntimeEnabled=WebLocksAPI
] interface Lock {
readonly attribute DOMString name;
readonly attribute LockMode mode;
diff --git a/chromium/third_party/blink/renderer/modules/locks/lock_manager.cc b/chromium/third_party/blink/renderer/modules/locks/lock_manager.cc
index 0539f124581..5655ca1640b 100644
--- a/chromium/third_party/blink/renderer/modules/locks/lock_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/locks/lock_manager.cc
@@ -11,15 +11,16 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_lock_granted_callback.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/dom/exception_code.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/modules/locks/lock.h"
#include "third_party/blink/renderer/modules/locks/lock_info.h"
#include "third_party/blink/renderer/modules/locks/lock_manager_snapshot.h"
#include "third_party/blink/renderer/platform/bindings/microtask.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/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/persistent.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"
@@ -50,7 +51,7 @@ HeapVector<LockInfo> ToLockInfos(
class LockManager::LockRequestImpl final
: public GarbageCollectedFinalized<LockRequestImpl>,
- public TraceWrapperBase,
+ public NameClient,
public mojom::blink::LockRequest {
WTF_MAKE_NONCOPYABLE(LockRequestImpl);
EAGERLY_FINALIZE();
@@ -77,12 +78,6 @@ class LockManager::LockRequestImpl final
visitor->Trace(callback_);
}
- // Wrapper tracing is needed for callbacks. The reference chain is
- // NavigatorLocksImpl -> LockManager -> LockRequestImpl ->
- // V8LockGrantedCallback.
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- visitor->TraceWrappers(callback_);
- }
const char* NameInHeapSnapshot() const override {
return "LockManager::LockRequestImpl";
}
@@ -102,7 +97,8 @@ class LockManager::LockRequestImpl final
if (!resolver_->GetScriptState()->ContextIsValid())
return;
- resolver_->Reject(DOMException::Create(kAbortError, reason));
+ resolver_->Reject(
+ DOMException::Create(DOMExceptionCode::kAbortError, reason));
}
void Failed() override {
@@ -195,6 +191,8 @@ ScriptPromise LockManager::request(ScriptState* script_state,
ExecutionContext* context = ExecutionContext::From(script_state);
DCHECK(context->IsContextThread());
+ // 5. If origin is an opaque origin, then reject promise with a
+ // "SecurityError" DOMException.
if (!context->GetSecurityOrigin()->CanAccessLocks()) {
exception_state.ThrowSecurityError(
"Access to the Locks API is denied in this context.");
@@ -215,42 +213,56 @@ ScriptPromise LockManager::request(ScriptState* script_state,
mojom::blink::LockMode mode = Lock::StringToMode(options.mode());
- if (options.steal() && options.ifAvailable()) {
- exception_state.ThrowDOMException(
- kNotSupportedError,
- "The 'steal' and 'ifAvailable' options cannot be used together.");
+ // 6. Otherwise, if name starts with U+002D HYPHEN-MINUS (-), then reject
+ // promise with a "NotSupportedError" DOMException.
+ if (name.StartsWith("-")) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ "Names cannot start with '-'.");
return ScriptPromise();
}
- if (name.StartsWith("-")) {
- exception_state.ThrowDOMException(kNotSupportedError,
- "Names cannot start with '-'.");
+ // 7. Otherwise, if both options’ steal dictionary member and option’s
+ // ifAvailable dictionary member are true, then reject promise with a
+ // "NotSupportedError" DOMException.
+ if (options.steal() && options.ifAvailable()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kNotSupportedError,
+ "The 'steal' and 'ifAvailable' options cannot be used together.");
return ScriptPromise();
}
+ // 8. Otherwise, if options’ steal dictionary member is true and option’s mode
+ // dictionary member is not "exclusive", then reject promise with a
+ // "NotSupportedError" DOMException.
if (options.steal() && mode != mojom::blink::LockMode::EXCLUSIVE) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"The 'steal' option may only be used with 'exclusive' locks.");
return ScriptPromise();
}
+ // 9. Otherwise, if option’s signal dictionary member is present, and either
+ // of options’ steal dictionary member or options’ ifAvailable dictionary
+ // member is true, then reject promise with a "NotSupportedError"
+ // DOMException.
if (options.hasSignal() && options.ifAvailable()) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"The 'signal' and 'ifAvailable' options cannot be used together.");
return ScriptPromise();
}
-
if (options.hasSignal() && options.steal()) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"The 'signal' and 'steal' options cannot be used together.");
return ScriptPromise();
}
+ // 10. Otherwise, if options’ signal dictionary member is present and its
+ // aborted flag is set, then reject promise with an "AbortError" DOMException.
if (options.hasSignal() && options.signal()->aborted()) {
- exception_state.ThrowDOMException(kAbortError, kRequestAbortedMessage);
+ exception_state.ThrowDOMException(DOMExceptionCode::kAbortError,
+ kRequestAbortedMessage);
return ScriptPromise();
}
@@ -264,11 +276,20 @@ ScriptPromise LockManager::request(ScriptState* script_state,
ScriptPromise promise = resolver->Promise();
mojom::blink::LockRequestPtr request_ptr;
+ // 11.1. Let request be the result of running the steps to request a lock with
+ // promise, the current agent, environment’s id, origin, callback, name,
+ // options’ mode dictionary member, options’ ifAvailable dictionary member,
+ // and options’ steal dictionary member.
LockRequestImpl* request = new LockRequestImpl(
callback, resolver, name, mode, mojo::MakeRequest(&request_ptr), this);
AddPendingRequest(request);
+ // 11.2. If options’ signal dictionary member is present, then add the
+ // following abort steps to options’ signal dictionary member:
if (options.hasSignal()) {
+ // 11.2.1. Enqueue the steps to abort the request request to the lock task
+ // queue.
+ // 11.2.2. Reject promise with an "AbortError" DOMException.
options.signal()->AddAlgorithm(WTF::Bind(&LockRequestImpl::Abort,
WrapWeakPersistent(request),
String(kRequestAbortedMessage)));
@@ -276,6 +297,7 @@ ScriptPromise LockManager::request(ScriptState* script_state,
service_->RequestLock(name, mode, wait, std::move(request_ptr));
+ // 12. Return promise.
return promise;
}
@@ -338,12 +360,6 @@ void LockManager::Trace(blink::Visitor* visitor) {
visitor->Trace(held_locks_);
}
-void LockManager::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- for (auto request : pending_requests_)
- visitor->TraceWrappers(request);
- ScriptWrappable::TraceWrappers(visitor);
-}
-
void LockManager::ContextDestroyed(ExecutionContext*) {
for (auto request : pending_requests_)
request->Cancel();
diff --git a/chromium/third_party/blink/renderer/modules/locks/lock_manager.h b/chromium/third_party/blink/renderer/modules/locks/lock_manager.h
index 974e464625e..cb113896b34 100644
--- a/chromium/third_party/blink/renderer/modules/locks/lock_manager.h
+++ b/chromium/third_party/blink/renderer/modules/locks/lock_manager.h
@@ -42,11 +42,6 @@ class LockManager final : public ScriptWrappable,
void Trace(blink::Visitor*) override;
- // Wrapper tracing is needed for callbacks. The reference chain is
- // NavigatorLocksImpl -> LockManager -> LockRequestImpl ->
- // V8LockGrantedCallback.
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
// Terminate all outstanding requests when the context is destroyed, since
// this can unblock requests by other contexts.
void ContextDestroyed(ExecutionContext*) override;
diff --git a/chromium/third_party/blink/renderer/modules/locks/lock_manager.idl b/chromium/third_party/blink/renderer/modules/locks/lock_manager.idl
index 6eb423c5223..e2185dfd616 100644
--- a/chromium/third_party/blink/renderer/modules/locks/lock_manager.idl
+++ b/chromium/third_party/blink/renderer/modules/locks/lock_manager.idl
@@ -8,7 +8,7 @@ callback LockGrantedCallback = any (Lock lock);
[
SecureContext,
Exposed=(Window,Worker),
- OriginTrialEnabled=WebLocksAPI
+ RuntimeEnabled=WebLocksAPI
] interface LockManager {
[CallWith=ScriptState, RaisesException, Measure] Promise<Lock> request(
DOMString name,
diff --git a/chromium/third_party/blink/renderer/modules/locks/lock_options.idl b/chromium/third_party/blink/renderer/modules/locks/lock_options.idl
index ce2a2908577..cbe48a9984c 100644
--- a/chromium/third_party/blink/renderer/modules/locks/lock_options.idl
+++ b/chromium/third_party/blink/renderer/modules/locks/lock_options.idl
@@ -9,5 +9,5 @@ dictionary LockOptions {
LockMode mode = "exclusive";
boolean ifAvailable = false;
boolean steal = false;
- AbortSignal? signal;
+ AbortSignal signal;
};
diff --git a/chromium/third_party/blink/renderer/modules/locks/navigator_locks.cc b/chromium/third_party/blink/renderer/modules/locks/navigator_locks.cc
index 264a6dc6edc..f18cfb50ecb 100644
--- a/chromium/third_party/blink/renderer/modules/locks/navigator_locks.cc
+++ b/chromium/third_party/blink/renderer/modules/locks/navigator_locks.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/core/frame/navigator.h"
#include "third_party/blink/renderer/core/workers/worker_navigator.h"
#include "third_party/blink/renderer/modules/locks/lock_manager.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/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/supplementable.h"
@@ -18,7 +19,7 @@ namespace {
template <typename T>
class NavigatorLocksImpl final : public GarbageCollected<NavigatorLocksImpl<T>>,
public Supplement<T>,
- public TraceWrapperBase {
+ public NameClient {
USING_GARBAGE_COLLECTED_MIXIN(NavigatorLocksImpl);
public:
@@ -46,13 +47,6 @@ class NavigatorLocksImpl final : public GarbageCollected<NavigatorLocksImpl<T>>,
Supplement<T>::Trace(visitor);
}
- // Wrapper tracing is needed for callbacks. The reference chain is
- // NavigatorLocksImpl -> LockManager -> LockRequestImpl ->
- // V8LockGrantedCallback.
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- visitor->TraceWrappers(lock_manager_);
- }
-
const char* NameInHeapSnapshot() const override {
return "NavigatorLocksImpl";
}
diff --git a/chromium/third_party/blink/renderer/modules/locks/navigator_locks.idl b/chromium/third_party/blink/renderer/modules/locks/navigator_locks.idl
index 61fa4674441..3ee3ff4a71b 100644
--- a/chromium/third_party/blink/renderer/modules/locks/navigator_locks.idl
+++ b/chromium/third_party/blink/renderer/modules/locks/navigator_locks.idl
@@ -7,7 +7,7 @@
SecureContext,
Exposed=Window,
ImplementedAs=NavigatorLocks,
- OriginTrialEnabled=WebLocksAPI
+ RuntimeEnabled=WebLocksAPI
] partial interface Navigator {
[CallWith=ScriptState] readonly attribute LockManager locks;
};
diff --git a/chromium/third_party/blink/renderer/modules/locks/worker_navigator_locks.idl b/chromium/third_party/blink/renderer/modules/locks/worker_navigator_locks.idl
index 50d105762ca..3dc5d025f1d 100644
--- a/chromium/third_party/blink/renderer/modules/locks/worker_navigator_locks.idl
+++ b/chromium/third_party/blink/renderer/modules/locks/worker_navigator_locks.idl
@@ -7,7 +7,7 @@
SecureContext,
Exposed=Worker,
ImplementedAs=NavigatorLocks,
- OriginTrialEnabled=WebLocksAPI
+ RuntimeEnabled=WebLocksAPI
] partial interface WorkerNavigator {
[CallWith=ScriptState] readonly attribute LockManager locks;
};
diff --git a/chromium/third_party/blink/renderer/modules/manifest/BUILD.gn b/chromium/third_party/blink/renderer/modules/manifest/BUILD.gn
new file mode 100644
index 00000000000..74c8b787652
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/BUILD.gn
@@ -0,0 +1,12 @@
+# 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/modules/modules.gni")
+
+blink_modules_sources("manifest") {
+ sources = [
+ "image_resource_type_converters.cc",
+ "image_resource_type_converters.h",
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/modules/manifest/OWNERS b/chromium/third_party/blink/renderer/modules/manifest/OWNERS
new file mode 100644
index 00000000000..d2d20202136
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/OWNERS
@@ -0,0 +1,2 @@
+per-file *_type_converter*.*=set noparent
+per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/manifest/image_resource.idl b/chromium/third_party/blink/renderer/modules/manifest/image_resource.idl
new file mode 100644
index 00000000000..338b2102968
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/image_resource.idl
@@ -0,0 +1,14 @@
+// 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.
+
+// https://w3c.github.io/manifest/#dom-imageresource
+
+[ImplementedAs=ManifestImageResource]
+dictionary ImageResource {
+ required USVString src;
+ DOMString sizes;
+ USVString type;
+ USVString purpose;
+ USVString platform;
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/manifest/image_resource_type_converters.cc b/chromium/third_party/blink/renderer/modules/manifest/image_resource_type_converters.cc
new file mode 100644
index 00000000000..6068f41d522
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/image_resource_type_converters.cc
@@ -0,0 +1,107 @@
+// 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/modules/manifest/image_resource_type_converters.h"
+
+#include "third_party/blink/public/common/mime_util/mime_util.h"
+#include "third_party/blink/public/platform/web_icon_sizes_parser.h"
+#include "third_party/blink/public/platform/web_size.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/platform/web_vector.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/hash_set.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace mojo {
+
+namespace {
+
+using Purpose = blink::mojom::blink::ManifestImageResource::Purpose;
+using blink::WebSize;
+using blink::WebString;
+using blink::WebVector;
+
+// https://w3c.github.io/manifest/#sizes-member.
+WTF::Vector<WebSize> ParseSizes(const WTF::String& sizes) {
+ WebVector<WebSize> parsed_sizes = blink::WebIconSizesParser::ParseIconSizes(
+ WebString::FromASCII(sizes.Ascii().data()));
+ WTF::HashSet<std::pair<int, int>, WTF::PairHash<int, int>,
+ WTF::PairHashTraits<WTF::UnsignedWithZeroKeyHashTraits<int>,
+ WTF::UnsignedWithZeroKeyHashTraits<int>>>
+ unique_sizes;
+
+ WTF::Vector<WebSize> results;
+ for (const auto& size : parsed_sizes) {
+ auto add_result =
+ unique_sizes.insert(std::make_pair(size.width, size.height));
+ if (add_result.is_new_entry) {
+ results.push_back(size);
+ }
+ }
+
+ return results;
+}
+
+// https://w3c.github.io/manifest/#purpose-member.
+WTF::Vector<Purpose> ParsePurpose(const WTF::String& purpose) {
+ WTF::HashSet<WTF::String> valid_purpose_set;
+ WTF::Vector<Purpose> results;
+
+ // Only two purpose values are defined.
+ valid_purpose_set.ReserveCapacityForSize(2u);
+ results.ReserveInitialCapacity(2u);
+
+ WTF::Vector<WTF::String> split_purposes;
+ purpose.LowerASCII().Split(' ', false /* allow_empty_entries */,
+ split_purposes);
+
+ for (const WTF::String& lowercase_purpose : split_purposes) {
+ Purpose purpose_enum;
+ if (lowercase_purpose == "any") {
+ purpose_enum = Purpose::ANY;
+ } else if (lowercase_purpose == "badge") {
+ purpose_enum = Purpose::BADGE;
+ } else {
+ // TODO(rayankans): Issue developer warning.
+ continue;
+ }
+
+ auto add_result = valid_purpose_set.insert(lowercase_purpose);
+ if (add_result.is_new_entry) {
+ results.push_back(purpose_enum);
+ } else {
+ // TODO(rayankans): Issue developer warning.
+ }
+ }
+
+ return results;
+}
+
+WTF::String ParseType(const WTF::String& type) {
+ if (type.IsNull() || type.IsEmpty())
+ return "";
+
+ if (!blink::IsSupportedMimeType(type.Ascii().data())) {
+ // TODO(rayankans): Issue developer warning.
+ return "";
+ }
+ return type;
+}
+
+} // namespace
+
+blink::mojom::blink::ManifestImageResourcePtr TypeConverter<
+ blink::mojom::blink::ManifestImageResourcePtr,
+ blink::ManifestImageResource>::Convert(const blink::ManifestImageResource&
+ image_resource) {
+ auto image_resource_ptr = blink::mojom::blink::ManifestImageResource::New();
+ image_resource_ptr->src = blink::KURL(image_resource.src());
+ image_resource_ptr->sizes = ParseSizes(image_resource.sizes());
+ image_resource_ptr->purpose = ParsePurpose(image_resource.purpose());
+ image_resource_ptr->type = ParseType(image_resource.type());
+ return image_resource_ptr;
+}
+
+} // namespace mojo
diff --git a/chromium/third_party/blink/renderer/modules/manifest/image_resource_type_converters.h b/chromium/third_party/blink/renderer/modules/manifest/image_resource_type_converters.h
new file mode 100644
index 00000000000..4f0f1a45cc7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/image_resource_type_converters.h
@@ -0,0 +1,24 @@
+// 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_MODULES_MANIFEST_IMAGE_RESOURCE_TYPE_CONVERTERS_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_MANIFEST_IMAGE_RESOURCE_TYPE_CONVERTERS_H_
+
+#include "third_party/blink/public/mojom/manifest/manifest.mojom-blink.h"
+#include "third_party/blink/renderer/modules/manifest/image_resource.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+
+namespace mojo {
+
+template <>
+struct MODULES_EXPORT
+ TypeConverter<blink::mojom::blink::ManifestImageResourcePtr,
+ blink::ManifestImageResource> {
+ static blink::mojom::blink::ManifestImageResourcePtr Convert(
+ const blink::ManifestImageResource& image_resource);
+};
+
+} // namespace mojo
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MANIFEST_IMAGE_RESOURCE_TYPE_CONVERTERS_H_
diff --git a/chromium/third_party/blink/renderer/modules/manifest/image_resource_type_converters_test.cc b/chromium/third_party/blink/renderer/modules/manifest/image_resource_type_converters_test.cc
new file mode 100644
index 00000000000..4f86f8a710f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/manifest/image_resource_type_converters_test.cc
@@ -0,0 +1,189 @@
+// 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/modules/manifest/image_resource_type_converters.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/manifest/manifest.mojom-blink.h"
+#include "third_party/blink/public/platform/web_size.h"
+#include "third_party/blink/renderer/modules/manifest/image_resource.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace mojo {
+
+namespace {
+
+using Purpose = blink::mojom::blink::ManifestImageResource::Purpose;
+using blink::mojom::blink::ManifestImageResource;
+using blink::mojom::blink::ManifestImageResourcePtr;
+using blink::WebSize;
+
+TEST(ImageResourceConverter, EmptySizesTest) {
+ blink::ManifestImageResource resource;
+
+ ManifestImageResourcePtr converted = ManifestImageResource::From(resource);
+ ASSERT_TRUE(converted->sizes.IsEmpty());
+
+ // Explicitly set to empty.
+ resource.setSizes("");
+ converted = ManifestImageResource::From(resource);
+ ASSERT_TRUE(converted->sizes.IsEmpty());
+}
+
+TEST(ImageResourceConverter, ValidSizesTest) {
+ blink::ManifestImageResource resource;
+
+ resource.setSizes("2x3");
+ ManifestImageResourcePtr converted = ManifestImageResource::From(resource);
+ ASSERT_EQ(converted->sizes.size(), 1u);
+ EXPECT_EQ(converted->sizes.front(), WebSize(2, 3));
+
+ resource.setSizes("42X24");
+ converted = ManifestImageResource::From(resource);
+ ASSERT_EQ(converted->sizes.size(), 1u);
+ EXPECT_EQ(converted->sizes.front(), WebSize(42, 24));
+
+ resource.setSizes("any");
+ converted = ManifestImageResource::From(resource);
+ ASSERT_EQ(converted->sizes.size(), 1u);
+ EXPECT_EQ(converted->sizes.front(), WebSize(0, 0));
+
+ resource.setSizes("ANY");
+ converted = ManifestImageResource::From(resource);
+ ASSERT_EQ(converted->sizes.size(), 1u);
+ EXPECT_EQ(converted->sizes.front(), WebSize(0, 0));
+
+ resource.setSizes("2x2 4x4");
+ converted = ManifestImageResource::From(resource);
+ ASSERT_EQ(converted->sizes.size(), 2u);
+ EXPECT_EQ(converted->sizes.front(), WebSize(2, 2));
+ EXPECT_EQ(converted->sizes.back(), WebSize(4, 4));
+
+ resource.setSizes("2x2 4x4 2x2");
+ converted = ManifestImageResource::From(resource);
+ ASSERT_EQ(2u, converted->sizes.size());
+ EXPECT_EQ(WebSize(2, 2), converted->sizes.front());
+ EXPECT_EQ(WebSize(4, 4), converted->sizes.back());
+
+ resource.setSizes(" 2x2 any");
+ converted = ManifestImageResource::From(resource);
+ ASSERT_EQ(2u, converted->sizes.size());
+ EXPECT_EQ(WebSize(2, 2), converted->sizes.front());
+ EXPECT_EQ(WebSize(0, 0), converted->sizes.back());
+}
+
+TEST(ImageResourceConverter, InvalidSizesTest) {
+ blink::ManifestImageResource resource;
+
+ resource.setSizes("02x3");
+ ManifestImageResourcePtr converted = ManifestImageResource::From(resource);
+ ASSERT_TRUE(converted->sizes.IsEmpty());
+
+ resource.setSizes("42X024");
+ converted = ManifestImageResource::From(resource);
+ ASSERT_TRUE(converted->sizes.IsEmpty());
+
+ resource.setSizes("42x");
+ converted = ManifestImageResource::From(resource);
+ ASSERT_TRUE(converted->sizes.IsEmpty());
+
+ resource.setSizes("foo");
+ converted = ManifestImageResource::From(resource);
+ ASSERT_TRUE(converted->sizes.IsEmpty());
+}
+
+TEST(ImageResourceConverter, EmptyPurposeTest) {
+ blink::ManifestImageResource resource;
+
+ ManifestImageResourcePtr converted = ManifestImageResource::From(resource);
+ ASSERT_TRUE(converted->purpose.IsEmpty());
+
+ // Explicitly set to empty.
+ resource.setPurpose("");
+ converted = ManifestImageResource::From(resource);
+ ASSERT_TRUE(converted->purpose.IsEmpty());
+}
+
+TEST(ImageResourceConverter, ValidPurposeTest) {
+ blink::ManifestImageResource resource;
+
+ resource.setPurpose("any");
+ ManifestImageResourcePtr converted = ManifestImageResource::From(resource);
+ ASSERT_EQ(1u, converted->purpose.size());
+ ASSERT_EQ(Purpose::ANY, converted->purpose.front());
+
+ resource.setPurpose(" Badge");
+ converted = ManifestImageResource::From(resource);
+ ASSERT_EQ(1u, converted->purpose.size());
+ ASSERT_EQ(Purpose::BADGE, converted->purpose.front());
+
+ resource.setPurpose(" Badge AnY");
+ converted = ManifestImageResource::From(resource);
+ ASSERT_EQ(2u, converted->purpose.size());
+ ASSERT_EQ(Purpose::BADGE, converted->purpose.front());
+ ASSERT_EQ(Purpose::ANY, converted->purpose.back());
+
+ resource.setPurpose("any badge AnY");
+ converted = ManifestImageResource::From(resource);
+ ASSERT_EQ(2u, converted->purpose.size());
+ ASSERT_EQ(Purpose::ANY, converted->purpose.front());
+ ASSERT_EQ(Purpose::BADGE, converted->purpose.back());
+}
+
+TEST(ImageResourceConverter, InvalidPurposeTest) {
+ blink::ManifestImageResource resource;
+
+ resource.setPurpose("any?");
+ ManifestImageResourcePtr converted = ManifestImageResource::From(resource);
+ ASSERT_TRUE(converted->purpose.IsEmpty());
+}
+
+TEST(ImageResourceConverter, EmptyTypeTest) {
+ blink::ManifestImageResource resource;
+
+ ManifestImageResourcePtr converted = ManifestImageResource::From(resource);
+ ASSERT_TRUE(converted->type.IsEmpty());
+
+ // Explicitly set to empty.
+ resource.setType("");
+ converted = ManifestImageResource::From(resource);
+ ASSERT_TRUE(converted->type.IsEmpty());
+}
+
+TEST(ImageResourceConverter, InvalidTypeTest) {
+ blink::ManifestImageResource resource;
+
+ resource.setType("image/NOTVALID!");
+ ManifestImageResourcePtr converted = ManifestImageResource::From(resource);
+ ASSERT_TRUE(converted->type.IsEmpty());
+}
+
+TEST(ImageResourceConverter, ValidTypeTest) {
+ blink::ManifestImageResource resource;
+
+ resource.setType("image/jpeg");
+ ManifestImageResourcePtr converted = ManifestImageResource::From(resource);
+ EXPECT_EQ("image/jpeg", converted->type);
+}
+
+TEST(ImageResourceConverter, ExampleValueTest) {
+ blink::ManifestImageResource resource;
+ resource.setSrc("http://example.com/lolcat.jpg");
+ resource.setPurpose("BADGE");
+ resource.setSizes("32x32 64x64 128x128");
+ resource.setType("image/jpeg");
+
+ auto expected_resource = ManifestImageResource::New();
+ expected_resource->src = blink::KURL("http://example.com/lolcat.jpg");
+ expected_resource->purpose = {Purpose::BADGE};
+ expected_resource->sizes = {{32, 32}, {64, 64}, {128, 128}};
+ expected_resource->type = "image/jpeg";
+
+ EXPECT_EQ(expected_resource, ManifestImageResource::From(resource));
+}
+
+} // namespace
+
+} // namespace mojo
diff --git a/chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc b/chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc
index b9bc415e392..503294aafe3 100644
--- a/chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc
+++ b/chromium/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc
@@ -288,7 +288,7 @@ ScriptPromise MediaCapabilities::encodingInfo(
->GetTaskRunner(TaskType::kInternalMediaRealTime));
if (!handler) {
resolver->Reject(DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Platform error: could not create MediaRecorderHandler."));
return promise;
}
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/BUILD.gn b/chromium/third_party/blink/renderer/modules/media_controls/BUILD.gn
index af9a8b5ff38..ec9163260ae 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/media_controls/BUILD.gn
@@ -68,6 +68,8 @@ blink_modules_sources("media_controls") {
"elements/media_control_toggle_closed_captions_button_element.h",
"elements/media_control_volume_slider_element.cc",
"elements/media_control_volume_slider_element.h",
+ "media_controls_display_cutout_delegate.cc",
+ "media_controls_display_cutout_delegate.h",
"media_controls_impl.cc",
"media_controls_impl.h",
"media_controls_media_event_listener.cc",
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.cc
index 57cd78a8436..6fd6c4713b6 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_cast_button_element.h"
#include "third_party/blink/public/platform/platform.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/geometry/dom_rect.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_download_button_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_download_button_element.cc
index 29c99ac72db..938d9c1ef5a 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_download_button_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_download_button_element.cc
@@ -76,14 +76,11 @@ void MediaControlDownloadButtonElement::DefaultEventHandler(Event* event) {
Platform::Current()->RecordAction(
UserMetricsAction("Media.Controls.Download"));
ResourceRequest request(url);
- request.SetUIStartTime(
- (event->PlatformTimeStamp() - TimeTicks()).InSecondsF());
- request.SetInputPerfMetricReportPolicy(
- InputToLoadPerfMetricReportPolicy::kReportLink);
request.SetSuggestedFilename(MediaElement().title());
request.SetRequestContext(WebURLRequest::kRequestContextDownload);
request.SetRequestorOrigin(SecurityOrigin::Create(GetDocument().Url()));
- GetDocument().GetFrame()->Client()->DownloadURL(request);
+ GetDocument().GetFrame()->Client()->DownloadURL(
+ request, DownloadCrossOriginRedirects::kFollow);
}
MediaControlInputElement::DefaultEventHandler(event);
}
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_element_type.h b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_element_type.h
index 9d0f6f4216a..e0efbcb3162 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_element_type.h
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_element_type.h
@@ -36,6 +36,8 @@ enum MediaControlElementType {
kMediaOverflowList,
kMediaDownloadButton,
kMediaScrubbingMessage,
+ kMediaEnterPictureInPictureButton,
+ kMediaExitPictureInPictureButton,
};
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_ELEMENTS_MEDIA_CONTROL_ELEMENT_TYPE_H_
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_fullscreen_button_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_fullscreen_button_element.cc
index 921d1dadc34..3ac97ca28b4 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_fullscreen_button_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_fullscreen_button_element.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_fullscreen_button_element.h"
#include "third_party/blink/public/platform/platform.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/frame/settings.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element_test.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element_test.cc
index 8332b76cb77..17a12b2350d 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element_test.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_input_element_test.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_input_element.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/dom/events/event.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"
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.cc
index de4274fde76..5012a090020 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_list_element.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/dom/events/event.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_overflow_menu_button_element.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.cc
index 82d819a4482..f65966ea56b 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.cc
@@ -8,6 +8,7 @@
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/events/mouse_event.h"
#include "third_party/blink/renderer/core/geometry/dom_rect.h"
@@ -15,6 +16,7 @@
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/html/media/html_media_source.h"
#include "third_party/blink/renderer/core/input_type_names.h"
+#include "third_party/blink/renderer/core/layout/layout_view.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_resource_loader.h"
@@ -266,7 +268,15 @@ void MediaControlOverlayPlayButtonElement::DefaultEventHandler(Event* event) {
}
bool MediaControlOverlayPlayButtonElement::KeepEventInNode(Event* event) {
- return ShouldCausePlayPause(event);
+ // We only care about user interaction events.
+ if (!MediaControlElementsHelper::IsUserInteractionEvent(event))
+ return false;
+
+ // For mouse events, only keep in node if they're on the internal button.
+ if (event->IsMouseEvent() && MediaControlsImpl::IsModern())
+ return IsMouseEventOnInternalButton(ToMouseEvent(event));
+
+ return true;
}
bool MediaControlOverlayPlayButtonElement::ShouldCausePlayPause(
@@ -279,18 +289,28 @@ bool MediaControlOverlayPlayButtonElement::ShouldCausePlayPause(
if (!MediaControlsImpl::IsModern() || !event->IsMouseEvent())
return true;
- // If the event doesn't have position data we should just default to
- // play/pause.
// TODO(beccahughes): Move to PointerEvent.
- MouseEvent* mouse_event = ToMouseEvent(event);
+ return IsMouseEventOnInternalButton(ToMouseEvent(event));
+}
+
+bool MediaControlOverlayPlayButtonElement::IsMouseEventOnInternalButton(
+ MouseEvent* mouse_event) const {
+ // If no position data available, default to yes.
if (!mouse_event->HasPosition())
return true;
- // If the click happened on the internal button or a margin around it then
- // we should play/pause.
- return IsPointInRect(*internal_button_->getBoundingClientRect(),
- kInnerButtonTouchPaddingSize, mouse_event->clientX(),
- mouse_event->clientY());
+ // Find the zoom-adjusted internal button bounding box.
+ DOMRect* box = internal_button_->getBoundingClientRect();
+ float zoom = ComputedStyleRef().EffectiveZoom() /
+ GetDocument().GetLayoutView()->ZoomFactor();
+ box->setX(box->x() * zoom);
+ box->setY(box->y() * zoom);
+ box->setWidth(box->width() * zoom);
+ box->setHeight(box->height() * zoom);
+
+ // Check the button and a margin around it.
+ return IsPointInRect(*box, kInnerButtonTouchPaddingSize,
+ mouse_event->clientX(), mouse_event->clientY());
}
WebSize MediaControlOverlayPlayButtonElement::GetSizeOrDefault() const {
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.h b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.h
index bc17fcfa93c..144654ce9aa 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.h
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_overlay_play_button_element.h
@@ -19,6 +19,7 @@ namespace blink {
class Event;
class MediaControlsImpl;
+class MouseEvent;
class MODULES_EXPORT MediaControlOverlayPlayButtonElement final
: public MediaControlInputElement {
@@ -82,6 +83,7 @@ class MODULES_EXPORT MediaControlOverlayPlayButtonElement final
bool KeepEventInNode(Event*) override;
bool ShouldCausePlayPause(Event*) const;
+ bool IsMouseEventOnInternalButton(MouseEvent*) const;
void MaybePlayPause();
void MaybeJump(int);
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.cc
index 4cd181bf1ba..cd492d9f641 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.cc
@@ -29,9 +29,29 @@ bool MediaControlPictureInPictureButtonElement::
return true;
}
+void MediaControlPictureInPictureButtonElement::UpdateDisplayType() {
+ DCHECK(MediaElement().IsHTMLVideoElement());
+ bool isInPictureInPicture =
+ PictureInPictureControllerImpl::From(MediaElement().GetDocument())
+ .IsPictureInPictureElement(&ToHTMLVideoElement(MediaElement()));
+ SetDisplayType(isInPictureInPicture ? kMediaExitPictureInPictureButton
+ : kMediaEnterPictureInPictureButton);
+ SetClass("on", isInPictureInPicture);
+ UpdateOverflowString();
+
+ MediaControlInputElement::UpdateDisplayType();
+}
+
WebLocalizedString::Name
MediaControlPictureInPictureButtonElement::GetOverflowStringName() const {
- return WebLocalizedString::kOverflowMenuPictureInPicture;
+ DCHECK(MediaElement().IsHTMLVideoElement());
+ bool isInPictureInPicture =
+ PictureInPictureControllerImpl::From(MediaElement().GetDocument())
+ .IsPictureInPictureElement(&ToHTMLVideoElement(MediaElement()));
+
+ return isInPictureInPicture
+ ? WebLocalizedString::kOverflowMenuExitPictureInPicture
+ : WebLocalizedString::kOverflowMenuEnterPictureInPicture;
}
bool MediaControlPictureInPictureButtonElement::HasOverflowButton() const {
@@ -51,9 +71,11 @@ void MediaControlPictureInPictureButtonElement::DefaultEventHandler(
PictureInPictureControllerImpl::From(MediaElement().GetDocument());
DCHECK(MediaElement().IsHTMLVideoElement());
- // TODO(crbug.com/840516): Toggle PiP instead.
- controller.EnterPictureInPicture(&ToHTMLVideoElement(MediaElement()),
- nullptr);
+ HTMLVideoElement* video_element = &ToHTMLVideoElement(MediaElement());
+ if (controller.IsPictureInPictureElement(video_element))
+ controller.ExitPictureInPicture(video_element, nullptr);
+ else
+ controller.EnterPictureInPicture(video_element, nullptr);
}
MediaControlInputElement::DefaultEventHandler(event);
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.h b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.h
index 6f2c47524bb..13c85750a47 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.h
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_picture_in_picture_button_element.h
@@ -19,6 +19,7 @@ class MediaControlPictureInPictureButtonElement final
// MediaControlInputElement:
bool WillRespondToMouseClickEvents() override;
+ void UpdateDisplayType() override;
WebLocalizedString::Name GetOverflowStringName() const override;
bool HasOverflowButton() const override;
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_scrubbing_message_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_scrubbing_message_element.cc
index b56e5c467b1..aa7722eae72 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_scrubbing_message_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_scrubbing_message_element.cc
@@ -4,12 +4,12 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_scrubbing_message_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/html/html_style_element.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_resource_loader.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_slider_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_slider_element.cc
index 3ee28fb94e9..e1f55e00caf 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_slider_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_slider_element.cc
@@ -21,8 +21,9 @@ void SetSegmentDivPosition(blink::HTMLDivElement* segment,
blink::MediaControlSliderElement::Position position,
int width,
float zoom_factor) {
- int segment_width = int((position.width * width) / zoom_factor);
- int segment_left = int((position.left * width) / zoom_factor);
+ int segment_width =
+ clampTo<int>(floor((position.width * width) / zoom_factor));
+ int segment_left = clampTo<int>(floor((position.left * width) / zoom_factor));
int current_width = 0;
int current_left = 0;
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc
index d6e9692241a..bee8c4bb3f4 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc
@@ -5,6 +5,8 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
+#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
#include "third_party/blink/renderer/core/html/forms/html_label_element.h"
#include "third_party/blink/renderer/core/html/html_span_element.h"
@@ -14,7 +16,6 @@
#include "third_party/blink/renderer/core/input_type_names.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"
-#include "third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.cc
index 74dadb5c756..2b72e374ee2 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.cc
@@ -4,8 +4,8 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_time_display_element.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_metrics.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_metrics.cc
index 02010712163..fd0ab0a8bf4 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_metrics.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_metrics.cc
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <cmath>
#include <limits>
+#include "base/numerics/safe_conversions.h"
#include "third_party/blink/renderer/platform/keyboard_codes.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
@@ -172,7 +173,7 @@ int32_t ToTimeDeltaSample(double delta_seconds) {
} while (false)
void RecordDragGestureDurationByWidth(int timeline_width, TimeDelta duration) {
- int32_t sample = static_cast<int32_t>(duration.InMilliseconds());
+ int32_t sample = base::saturated_cast<int32_t>(duration.InMilliseconds());
RECORD_TIMELINE_UMA_BY_WIDTH(timeline_width, DragGestureDuration, sample,
CustomCountHistogram, 1 /* 1 ms */,
60000 /* 1 minute */, 50);
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.cc b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.cc
index 113c9977d6d..a58b550a85c 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.cc
@@ -10,9 +10,38 @@
#include "third_party/blink/renderer/core/html/track/text_track_list.h"
#include "third_party/blink/renderer/core/input_type_names.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"
+#include "third_party/blink/renderer/platform/language.h"
namespace blink {
+namespace {
+
+// The CSS class to use if we should use the closed captions icon.
+const char kClosedCaptionClass[] = "closed-captions";
+
+const char* kClosedCaptionLocales[] = {
+ // English (United States)
+ "en", "en-US",
+
+ // Spanish (Latin America and Caribbean)
+ "es-419",
+
+ // Portuguese (Brazil)
+ "pt-BR",
+};
+
+// Returns true if the default language should use the closed captions icon.
+bool UseClosedCaptionsIcon() {
+ for (auto*& locale : kClosedCaptionLocales) {
+ if (locale == DefaultLanguage())
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace
+
MediaControlToggleClosedCaptionsButtonElement::
MediaControlToggleClosedCaptionsButtonElement(
MediaControlsImpl& media_controls)
@@ -20,6 +49,7 @@ MediaControlToggleClosedCaptionsButtonElement::
setType(InputTypeNames::button);
SetShadowPseudoId(
AtomicString("-webkit-media-controls-toggle-closed-captions-button"));
+ SetClass(kClosedCaptionClass, UseClosedCaptionsIcon());
}
bool MediaControlToggleClosedCaptionsButtonElement::
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_display_cutout_delegate.cc b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_display_cutout_delegate.cc
new file mode 100644
index 00000000000..c7306b258cb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_display_cutout_delegate.cc
@@ -0,0 +1,170 @@
+// 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/modules/media_controls/media_controls_display_cutout_delegate.h"
+
+#include "third_party/blink/public/platform/web_point.h"
+#include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/events/touch_event.h"
+#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/core/frame/viewport_data.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
+#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
+#include "third_party/blink/renderer/core/html/media/html_video_element.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+
+namespace blink {
+
+namespace {
+
+WebPoint ExtractWebPoint(Touch* touch) {
+ return WebPoint(touch->pageX(), touch->pageY());
+}
+
+double CalculateDistance(WebPoint first, WebPoint second) {
+ double dx = first.x - second.x;
+ double dy = first.y - second.y;
+ return sqrt(dx * dx + dy * dy);
+}
+
+} // namespace
+
+// static
+bool MediaControlsDisplayCutoutDelegate::IsEnabled() {
+ return RuntimeEnabledFeatures::DisplayCutoutAPIEnabled() &&
+ RuntimeEnabledFeatures::MediaControlsExpandGestureEnabled();
+}
+
+MediaControlsDisplayCutoutDelegate::MediaControlsDisplayCutoutDelegate(
+ HTMLVideoElement& video_element)
+ : EventListener(kCPPEventListenerType), video_element_(video_element) {}
+
+void MediaControlsDisplayCutoutDelegate::Attach() {
+ DCHECK(video_element_->isConnected());
+
+ GetDocument().addEventListener(EventTypeNames::fullscreenchange, this, true);
+ GetDocument().addEventListener(EventTypeNames::webkitfullscreenchange, this,
+ true);
+}
+
+void MediaControlsDisplayCutoutDelegate::Detach() {
+ DCHECK(!video_element_->isConnected());
+
+ GetDocument().removeEventListener(EventTypeNames::fullscreenchange, this,
+ true);
+ GetDocument().removeEventListener(EventTypeNames::webkitfullscreenchange,
+ this, true);
+}
+
+bool MediaControlsDisplayCutoutDelegate::operator==(
+ const EventListener& other) const {
+ return this == &other;
+}
+
+void MediaControlsDisplayCutoutDelegate::Trace(blink::Visitor* visitor) {
+ EventListener::Trace(visitor);
+ visitor->Trace(video_element_);
+}
+
+void MediaControlsDisplayCutoutDelegate::DidEnterFullscreen() {
+ video_element_->addEventListener(EventTypeNames::touchstart, this, true);
+ video_element_->addEventListener(EventTypeNames::touchend, this, true);
+ video_element_->addEventListener(EventTypeNames::touchmove, this, true);
+ video_element_->addEventListener(EventTypeNames::touchcancel, this, true);
+}
+
+void MediaControlsDisplayCutoutDelegate::DidExitFullscreen() {
+ GetDocument().GetViewportData().SetExpandIntoDisplayCutout(false);
+
+ video_element_->removeEventListener(EventTypeNames::touchstart, this, true);
+ video_element_->removeEventListener(EventTypeNames::touchend, this, true);
+ video_element_->removeEventListener(EventTypeNames::touchmove, this, true);
+ video_element_->removeEventListener(EventTypeNames::touchcancel, this, true);
+}
+
+void MediaControlsDisplayCutoutDelegate::handleEvent(
+ ExecutionContext* execution_context,
+ Event* event) {
+ if (event->IsTouchEvent()) {
+ HandleTouchEvent(ToTouchEvent(event));
+ return;
+ }
+ if (event->type() == EventTypeNames::fullscreenchange ||
+ event->type() == EventTypeNames::webkitfullscreenchange) {
+ // The fullscreen state has changed.
+ if (video_element_->IsFullscreen()) {
+ DidEnterFullscreen();
+ } else if (!Fullscreen::FullscreenElementFrom(GetDocument())) {
+ DidExitFullscreen();
+ }
+
+ return;
+ }
+
+ NOTREACHED();
+}
+
+void MediaControlsDisplayCutoutDelegate::HandleTouchEvent(TouchEvent* event) {
+ // Check if the current media element is fullscreen.
+ DCHECK(video_element_->IsFullscreen());
+
+ // Filter out any touch events that are not two fingered.
+ if (event->touches()->length() != 2)
+ return;
+
+ // Mark the event as handled.
+ event->SetDefaultHandled();
+
+ // If it is a touch start event then we should flush any previous points we
+ // have stored.
+ if (event->type() == EventTypeNames::touchstart)
+ previous_.reset();
+
+ // Extract the two touch points and calculate the distance.
+ WebPoint first = ExtractWebPoint(event->touches()->item(0));
+ WebPoint second = ExtractWebPoint(event->touches()->item(1));
+ double distance = CalculateDistance(first, second);
+ Direction direction = Direction::kUnknown;
+
+ // Compare the current distance with the previous to work out the direction we
+ // are going in. If we are idle then we should just copy the direction we had
+ // previously.
+ if (previous_.has_value()) {
+ if (distance > previous_->first) {
+ direction = Direction::kExpanding;
+ } else if (distance < previous_->first) {
+ direction = Direction::kContracting;
+ } else {
+ direction = previous_->second;
+ }
+ }
+
+ // If we have a |previous| value and that is different from |direction| then
+ // we have either identified the direction and |previous| is kUnknown or the
+ // direction has changed. In either case we should update the display cutout.
+ if (previous_.has_value() && previous_->second != direction) {
+ DCHECK(direction != Direction::kUnknown);
+
+ UseCounter::Count(GetDocument(),
+ WebFeature::kMediaControlsDisplayCutoutGesture);
+ GetDocument().GetViewportData().SetExpandIntoDisplayCutout(
+ direction == Direction::kExpanding);
+ }
+
+ // If we are finishing a touch then clear any stored value, otherwise store
+ // the latest distance.
+ if (event->type() == EventTypeNames::touchend ||
+ event->type() == EventTypeNames::touchcancel) {
+ DCHECK(previous_.has_value());
+ previous_.reset();
+ } else {
+ previous_ = ResultPair(distance, direction);
+ }
+}
+
+Document& MediaControlsDisplayCutoutDelegate::GetDocument() {
+ return video_element_->GetDocument();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_display_cutout_delegate.h b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_display_cutout_delegate.h
new file mode 100644
index 00000000000..baae1e1a1ce
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_display_cutout_delegate.h
@@ -0,0 +1,76 @@
+// 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_MODULES_MEDIA_CONTROLS_MEDIA_CONTROLS_DISPLAY_CUTOUT_DELEGATE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_MEDIA_CONTROLS_DISPLAY_CUTOUT_DELEGATE_H_
+
+#include "base/optional.h"
+#include "third_party/blink/renderer/core/dom/events/event_listener.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+
+namespace blink {
+
+class Document;
+class HTMLVideoElement;
+class TouchEvent;
+
+// MediaControlsDisplayCutoutDelegate implements a two-fingered pinch gesture
+// to expand the video element into the display cutout when the video is
+// fullscreen.
+class MODULES_EXPORT MediaControlsDisplayCutoutDelegate final
+ : public EventListener {
+ public:
+ static bool IsEnabled();
+
+ explicit MediaControlsDisplayCutoutDelegate(HTMLVideoElement&);
+
+ // Called by MediaControlsImpl when the HTMLVideoElement is added to a
+ // document. All event listeners should be added.
+ void Attach();
+
+ // Called by MediaControls when the HTMLVideoElement is no longer in the
+ // document. All event listeners should be removed in order to prepare the
+ // object to be garbage collected.
+ void Detach();
+
+ bool operator==(const EventListener&) const override;
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ friend class MediaControlsDisplayCutoutDelegateTest;
+
+ // Stores the direction of the pinch gesture.
+ enum class Direction {
+ // We do not have enough data to work out the direction.
+ kUnknown,
+
+ // The distance between the two points is expanding.
+ kExpanding,
+
+ // The distance between the two points is contracting.
+ kContracting,
+ };
+
+ void DidEnterFullscreen();
+ void DidExitFullscreen();
+
+ // EventListener implementation.
+ void handleEvent(ExecutionContext*, Event*) override;
+
+ void HandleTouchEvent(TouchEvent*);
+
+ Document& GetDocument();
+
+ // Pair storing the previous result. |first| is the distance between the two
+ // points stored as a double. |second| is the Direction.
+ using ResultPair = std::pair<double, Direction>;
+ base::Optional<ResultPair> previous_;
+
+ Member<HTMLVideoElement> video_element_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIA_CONTROLS_MEDIA_CONTROLS_DISPLAY_CUTOUT_DELEGATE_H_
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_display_cutout_delegate_test.cc b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_display_cutout_delegate_test.cc
new file mode 100644
index 00000000000..22e5a529922
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_display_cutout_delegate_test.cc
@@ -0,0 +1,315 @@
+// 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/modules/media_controls/media_controls_display_cutout_delegate.h"
+
+#include "third_party/blink/public/mojom/page/display_cutout.mojom-blink.h"
+#include "third_party/blink/renderer/core/events/touch_event.h"
+#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/core/frame/viewport_data.h"
+#include "third_party/blink/renderer/core/frame/web_feature.h"
+#include "third_party/blink/renderer/core/fullscreen/fullscreen.h"
+#include "third_party/blink/renderer/core/html/media/html_video_element.h"
+#include "third_party/blink/renderer/core/input/touch.h"
+#include "third_party/blink/renderer/core/input/touch_list.h"
+#include "third_party/blink/renderer/core/loader/empty_clients.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+#include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+
+namespace blink {
+
+namespace {
+
+class DisplayCutoutMockChromeClient : public EmptyChromeClient {
+ public:
+ // ChromeClient overrides:
+ void EnterFullscreen(LocalFrame& frame, const FullscreenOptions&) override {
+ Fullscreen::DidEnterFullscreen(*frame.GetDocument());
+ }
+ void ExitFullscreen(LocalFrame& frame) override {
+ Fullscreen::DidExitFullscreen(*frame.GetDocument());
+ }
+};
+
+} // namespace
+
+class MediaControlsDisplayCutoutDelegateTest : public PageTestBase {
+ public:
+ void SetUp() override {
+ chrome_client_ = new DisplayCutoutMockChromeClient();
+
+ Page::PageClients clients;
+ FillWithEmptyClients(clients);
+ clients.chrome_client = chrome_client_.Get();
+ SetupPageWithClients(&clients, EmptyLocalFrameClient::Create());
+
+ RuntimeEnabledFeatures::SetDisplayCutoutAPIEnabled(true);
+ RuntimeEnabledFeatures::SetMediaControlsExpandGestureEnabled(true);
+
+ GetDocument().write("<body><video id=video></body>");
+ }
+
+ void SimulateEnterFullscreen() {
+ {
+ std::unique_ptr<UserGestureIndicator> gesture =
+ Frame::NotifyUserActivation(GetDocument().GetFrame());
+ Fullscreen::RequestFullscreen(GetVideoElement());
+ }
+
+ test::RunPendingTasks();
+ GetDocument().ServiceScriptedAnimations(base::TimeTicks());
+
+ EXPECT_TRUE(GetVideoElement().IsFullscreen());
+ }
+
+ void SimulateExitFullscreen() {
+ Fullscreen::FullyExitFullscreen(GetDocument());
+
+ GetDocument().ServiceScriptedAnimations(base::TimeTicks());
+
+ EXPECT_FALSE(GetVideoElement().IsFullscreen());
+ }
+
+ void SimulateContractingGesture() {
+ TouchList* list = CreateTouchListWithTwoPoints(5, 5, -5, -5);
+ SimulateEvent(CreateTouchEventWithList(EventTypeNames::touchstart, list));
+
+ list = CreateTouchListWithTwoPoints(4, 4, -4, -4);
+ SimulateEvent(CreateTouchEventWithList(EventTypeNames::touchmove, list));
+
+ list = CreateTouchListWithTwoPoints(0, 0, 0, 0);
+ SimulateEvent(CreateTouchEventWithList(EventTypeNames::touchend, list));
+ }
+
+ void SimulateExpandingGesture() {
+ TouchList* list = CreateTouchListWithTwoPoints(1, 1, -1, -1);
+ SimulateEvent(CreateTouchEventWithList(EventTypeNames::touchstart, list));
+
+ list = CreateTouchListWithTwoPoints(4, 4, -4, -4);
+ SimulateEvent(CreateTouchEventWithList(EventTypeNames::touchmove, list));
+
+ list = CreateTouchListWithTwoPoints(5, 5, -5, -5);
+ SimulateEvent(CreateTouchEventWithList(EventTypeNames::touchend, list));
+ }
+
+ void SimulateSingleTouchGesture() {
+ TouchList* list = CreateTouchListWithOnePoint(1, 1);
+ SimulateEvent(CreateTouchEventWithList(EventTypeNames::touchstart, list));
+
+ list = CreateTouchListWithOnePoint(4, 4);
+ SimulateEvent(CreateTouchEventWithList(EventTypeNames::touchmove, list));
+
+ list = CreateTouchListWithOnePoint(5, 5);
+ SimulateEvent(CreateTouchEventWithList(EventTypeNames::touchend, list));
+ }
+
+ bool HasGestureState() { return GetDelegate().previous_.has_value(); }
+
+ bool DirectionIsExpanding() {
+ return GetDelegate().previous_->second ==
+ MediaControlsDisplayCutoutDelegate::Direction::kExpanding;
+ }
+
+ bool DirectionIsUnknown() {
+ return GetDelegate().previous_->second ==
+ MediaControlsDisplayCutoutDelegate::Direction::kUnknown;
+ }
+
+ void SimulateEvent(TouchEvent* event) {
+ GetVideoElement().FireEventListeners(event);
+ }
+
+ TouchList* CreateTouchListWithOnePoint(int x, int y) {
+ TouchList* list = TouchList::Create();
+ list->Append(CreateTouchAtPoint(x, y));
+ return list;
+ }
+
+ TouchList* CreateTouchListWithTwoPoints(int x1, int y1, int x2, int y2) {
+ TouchList* list = TouchList::Create();
+ list->Append(CreateTouchAtPoint(x1, y1));
+ list->Append(CreateTouchAtPoint(x2, y2));
+ return list;
+ }
+
+ TouchEvent* CreateTouchEventWithList(const AtomicString& type,
+ TouchList* list) {
+ TouchEvent* event = TouchEvent::Create();
+ event->initEvent(type, true, false);
+ event->SetTouches(list);
+ return event;
+ }
+
+ Touch* CreateTouchAtPoint(int x, int y) {
+ return Touch::Create(GetDocument().GetFrame(), &GetVideoElement(),
+ 1 /* identifier */, FloatPoint(x, y), FloatPoint(x, y),
+ FloatSize(1, 1), 90, 0, "test");
+ }
+
+ mojom::ViewportFit CurrentViewportFit() const {
+ return GetDocument().GetViewportData().GetCurrentViewportFitForTests();
+ }
+
+ private:
+ MediaControlsDisplayCutoutDelegate& GetDelegate() {
+ MediaControlsImpl* controls =
+ static_cast<MediaControlsImpl*>(GetVideoElement().GetMediaControls());
+ return *controls->display_cutout_delegate_;
+ }
+
+ HTMLVideoElement& GetVideoElement() {
+ return *ToHTMLVideoElement(GetDocument().getElementById("video"));
+ }
+
+ Persistent<DisplayCutoutMockChromeClient> chrome_client_;
+};
+
+TEST_F(MediaControlsDisplayCutoutDelegateTest, CombinedGesture) {
+ SimulateEnterFullscreen();
+
+ // Simulate the an expanding gesture but do not finish it.
+ TouchList* list = CreateTouchListWithTwoPoints(1, 1, -1, -1);
+ SimulateEvent(CreateTouchEventWithList(EventTypeNames::touchstart, list));
+ list = CreateTouchListWithTwoPoints(4, 4, -4, -4);
+ SimulateEvent(CreateTouchEventWithList(EventTypeNames::touchmove, list));
+
+ // Check the viewport fit value has been correctly set.
+ EXPECT_EQ(mojom::ViewportFit::kCoverForcedByUserAgent, CurrentViewportFit());
+
+ // Finish the gesture by contracting.
+ list = CreateTouchListWithTwoPoints(0, 0, 0, 0);
+ SimulateEvent(CreateTouchEventWithList(EventTypeNames::touchend, list));
+
+ // Check the viewport fit value has been correctly set.
+ EXPECT_EQ(mojom::ViewportFit::kAuto, CurrentViewportFit());
+
+ // Make sure we recorded a UseCounter metric.
+ EXPECT_TRUE(UseCounter::IsCounted(
+ GetDocument(), WebFeature::kMediaControlsDisplayCutoutGesture));
+}
+
+TEST_F(MediaControlsDisplayCutoutDelegateTest, ContractingGesture) {
+ // Go fullscreen and simulate an expanding gesture.
+ SimulateEnterFullscreen();
+ SimulateExpandingGesture();
+
+ // Check the viewport fit value has been correctly set.
+ EXPECT_EQ(mojom::ViewportFit::kCoverForcedByUserAgent, CurrentViewportFit());
+
+ // Simulate a contracting gesture and check the value has been restored.
+ SimulateContractingGesture();
+ EXPECT_EQ(mojom::ViewportFit::kAuto, CurrentViewportFit());
+
+ // Make sure we recorded a UseCounter metric.
+ EXPECT_TRUE(UseCounter::IsCounted(
+ GetDocument(), WebFeature::kMediaControlsDisplayCutoutGesture));
+}
+
+TEST_F(MediaControlsDisplayCutoutDelegateTest, ContractingGesture_Noop) {
+ // Go fullscreen and simulate a contracting gesture.
+ SimulateEnterFullscreen();
+ SimulateContractingGesture();
+
+ // Check that the value did not change.
+ EXPECT_EQ(mojom::ViewportFit::kAuto, CurrentViewportFit());
+}
+
+TEST_F(MediaControlsDisplayCutoutDelegateTest, ExpandingGesture) {
+ // Go fullscreen and simulate an expanding gesture.
+ SimulateEnterFullscreen();
+ SimulateExpandingGesture();
+
+ // Check the viewport fit value has been correctly set.
+ EXPECT_EQ(mojom::ViewportFit::kCoverForcedByUserAgent, CurrentViewportFit());
+
+ // Exit fullscreen and check the value has been restored.
+ SimulateExitFullscreen();
+ EXPECT_EQ(mojom::ViewportFit::kAuto, CurrentViewportFit());
+
+ // Make sure we recorded a UseCounter metric.
+ EXPECT_TRUE(UseCounter::IsCounted(
+ GetDocument(), WebFeature::kMediaControlsDisplayCutoutGesture));
+}
+
+TEST_F(MediaControlsDisplayCutoutDelegateTest, ExpandingGesture_DoubleNoop) {
+ // Go fullscreen and simulate an expanding gesture.
+ SimulateEnterFullscreen();
+ SimulateExpandingGesture();
+
+ // Check the viewport fit value has been correctly set.
+ EXPECT_EQ(mojom::ViewportFit::kCoverForcedByUserAgent, CurrentViewportFit());
+
+ // Simulate another expanding gesture and make sure nothing changed.
+ SimulateExpandingGesture();
+ EXPECT_EQ(mojom::ViewportFit::kCoverForcedByUserAgent, CurrentViewportFit());
+}
+
+TEST_F(MediaControlsDisplayCutoutDelegateTest, IncompleteGestureClearsState) {
+ SimulateEnterFullscreen();
+
+ // Simulate a gesture and check we have state.
+ TouchList* list = CreateTouchListWithTwoPoints(1, 1, -1, -1);
+ SimulateEvent(CreateTouchEventWithList(EventTypeNames::touchstart, list));
+
+ list = CreateTouchListWithTwoPoints(2, 2, -2, -2);
+ SimulateEvent(CreateTouchEventWithList(EventTypeNames::touchmove, list));
+ EXPECT_TRUE(DirectionIsExpanding());
+
+ // Simulate another start gesture and make sure we do not have a direction.
+ list = CreateTouchListWithTwoPoints(3, 3, -3, -3);
+ SimulateEvent(CreateTouchEventWithList(EventTypeNames::touchstart, list));
+ EXPECT_TRUE(DirectionIsUnknown());
+}
+
+TEST_F(MediaControlsDisplayCutoutDelegateTest, MetricsNoop) {
+ EXPECT_FALSE(UseCounter::IsCounted(
+ GetDocument(), WebFeature::kMediaControlsDisplayCutoutGesture));
+}
+
+TEST_F(MediaControlsDisplayCutoutDelegateTest, NoFullscreen_Noop) {
+ // Simulate an expanding gesture and make sure it had no effect.
+ SimulateExpandingGesture();
+ EXPECT_EQ(mojom::ViewportFit::kAuto, CurrentViewportFit());
+}
+
+TEST_F(MediaControlsDisplayCutoutDelegateTest, SingleTouchGesture_Noop) {
+ // Simulate a single touch gesture and make sure it had no effect.
+ SimulateEnterFullscreen();
+ SimulateSingleTouchGesture();
+ EXPECT_EQ(mojom::ViewportFit::kAuto, CurrentViewportFit());
+}
+
+TEST_F(MediaControlsDisplayCutoutDelegateTest, TouchCancelShouldClearState) {
+ SimulateEnterFullscreen();
+
+ // Simulate a gesture and check we have state.
+ TouchList* list = CreateTouchListWithTwoPoints(1, 1, -1, -1);
+ SimulateEvent(CreateTouchEventWithList(EventTypeNames::touchstart, list));
+ EXPECT_TRUE(HasGestureState());
+
+ // Simulate a touchcancel gesture and check that clears the state.
+ list = CreateTouchListWithTwoPoints(1, 1, -1, -1);
+ SimulateEvent(CreateTouchEventWithList(EventTypeNames::touchcancel, list));
+ EXPECT_FALSE(HasGestureState());
+ EXPECT_EQ(mojom::ViewportFit::kAuto, CurrentViewportFit());
+}
+
+TEST_F(MediaControlsDisplayCutoutDelegateTest, TouchEndShouldClearState) {
+ SimulateEnterFullscreen();
+
+ // Simulate a gesture and check we have state.
+ TouchList* list = CreateTouchListWithTwoPoints(1, 1, -1, -1);
+ SimulateEvent(CreateTouchEventWithList(EventTypeNames::touchstart, list));
+ EXPECT_TRUE(HasGestureState());
+
+ // Simulate a touchend gesture and check that clears the state.
+ list = CreateTouchListWithTwoPoints(1, 1, -1, -1);
+ SimulateEvent(CreateTouchEventWithList(EventTypeNames::touchend, list));
+ EXPECT_FALSE(HasGestureState());
+ EXPECT_EQ(mojom::ViewportFit::kAuto, CurrentViewportFit());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl.cc b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl.cc
index 98d2d5835f3..5ca3a5f8314 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl.cc
@@ -28,9 +28,9 @@
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_size.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_trusted_html.h"
#include "third_party/blink/renderer/core/css/css_style_declaration.h"
+#include "third_party/blink/renderer/core/dom/events/event_dispatch_forbidden_scope.h"
#include "third_party/blink/renderer/core/dom/mutation_observer.h"
#include "third_party/blink/renderer/core/dom/mutation_observer_init.h"
#include "third_party/blink/renderer/core/dom/mutation_record.h"
@@ -73,6 +73,7 @@
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_toggle_closed_captions_button_element.h"
#include "third_party/blink/renderer/modules/media_controls/elements/media_control_volume_slider_element.h"
+#include "third_party/blink/renderer/modules/media_controls/media_controls_display_cutout_delegate.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_media_event_listener.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_resource_loader.h"
@@ -80,7 +81,7 @@
#include "third_party/blink/renderer/modules/media_controls/media_download_in_product_help_manager.h"
#include "third_party/blink/renderer/modules/remoteplayback/html_media_element_remote_playback.h"
#include "third_party/blink/renderer/modules/remoteplayback/remote_playback.h"
-#include "third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/text/platform_locale.h"
@@ -129,14 +130,6 @@ const char kScrubbingMessageCSSClass[] = "scrubbing-message";
const char kTestModeCSSClass[] = "test-mode";
const char kImmersiveModeCSSClass[] = "immersive-mode";
-const char kSizingSmallCSSClass[] = "sizing-small";
-const char kSizingMediumCSSClass[] = "sizing-medium";
-const char kSizingLargeCSSClass[] = "sizing-large";
-
-// The minimum width in pixels to reach a given size.
-constexpr int kSizingMediumThreshold = 741;
-constexpr int kSizingLargeThreshold = 1441;
-
// The ratio of video width/height to use for play button size.
constexpr float kSizingSmallOverlayPlayButtonSizeRatio = 0.25;
constexpr float kSizingMediumOverlayPlayButtonSizeRatio = 0.15;
@@ -218,10 +211,12 @@ bool PreferHiddenVolumeControls(const Document& document) {
// If you change this value, then also update the corresponding value in
// LayoutTests/media/media-controls.js.
-double kTimeWithoutMouseMovementBeforeHidingMediaControls = 3;
-double kModernTimeWithoutMouseMovementBeforeHidingMediaControls = 2.5;
+constexpr TimeDelta kTimeWithoutMouseMovementBeforeHidingMediaControls =
+ TimeDelta::FromSeconds(3);
+constexpr TimeDelta kModernTimeWithoutMouseMovementBeforeHidingMediaControls =
+ TimeDelta::FromSecondsD(2.5);
-double GetTimeWithoutMouseMovementBeforeHidingMediaControls() {
+TimeDelta GetTimeWithoutMouseMovementBeforeHidingMediaControls() {
return MediaControlsImpl::IsModern()
? kModernTimeWithoutMouseMovementBeforeHidingMediaControls
: kTimeWithoutMouseMovementBeforeHidingMediaControls;
@@ -378,6 +373,7 @@ MediaControlsImpl::MediaControlsImpl(HTMLMediaElement& media_element)
media_event_listener_(new MediaControlsMediaEventListener(this)),
orientation_lock_delegate_(nullptr),
rotate_to_fullscreen_delegate_(nullptr),
+ display_cutout_delegate_(nullptr),
hide_media_controls_timer_(
media_element.GetDocument().GetTaskRunner(TaskType::kInternalMedia),
this,
@@ -415,6 +411,14 @@ MediaControlsImpl* MediaControlsImpl::Create(HTMLMediaElement& media_element,
new MediaControlsOrientationLockDelegate(
ToHTMLVideoElement(media_element));
}
+
+ if (MediaControlsDisplayCutoutDelegate::IsEnabled() &&
+ media_element.IsHTMLVideoElement()) {
+ // Initialize the pinch gesture to expand into the display cutout feature.
+ controls->display_cutout_delegate_ = new MediaControlsDisplayCutoutDelegate(
+ ToHTMLVideoElement(media_element));
+ }
+
if (RuntimeEnabledFeatures::VideoRotateToFullscreenEnabled() &&
media_element.IsHTMLVideoElement()) {
// Initialize the rotate-to-fullscreen feature.
@@ -559,7 +563,10 @@ void MediaControlsImpl::InitializeControls() {
volume_slider_->SetIsWanted(false);
}
- if (RuntimeEnabledFeatures::PictureInPictureEnabled()) {
+ if (RuntimeEnabledFeatures::PictureInPictureEnabled() &&
+ GetDocument().GetSettings() &&
+ GetDocument().GetSettings()->GetPictureInPictureEnabled() &&
+ MediaElement().IsHTMLVideoElement()) {
picture_in_picture_button_ =
new MediaControlPictureInPictureButtonElement(*this);
picture_in_picture_button_->SetIsWanted(
@@ -601,7 +608,7 @@ void MediaControlsImpl::InitializeControls() {
overflow_list_->ParserAppendChild(
toggle_closed_captions_button_->CreateOverflowElement(
new MediaControlToggleClosedCaptionsButtonElement(*this)));
- if (RuntimeEnabledFeatures::PictureInPictureEnabled()) {
+ if (picture_in_picture_button_) {
overflow_list_->ParserAppendChild(
picture_in_picture_button_->CreateOverflowElement(
new MediaControlPictureInPictureButtonElement(*this)));
@@ -669,6 +676,8 @@ Node::InsertionNotificationRequest MediaControlsImpl::InsertedInto(
orientation_lock_delegate_->Attach();
if (rotate_to_fullscreen_delegate_)
rotate_to_fullscreen_delegate_->Attach();
+ if (display_cutout_delegate_)
+ display_cutout_delegate_->Attach();
if (!resize_observer_) {
resize_observer_ =
@@ -797,6 +806,8 @@ void MediaControlsImpl::RemovedFrom(ContainerNode*) {
orientation_lock_delegate_->Detach();
if (rotate_to_fullscreen_delegate_)
rotate_to_fullscreen_delegate_->Detach();
+ if (display_cutout_delegate_)
+ display_cutout_delegate_->Detach();
if (resize_observer_) {
resize_observer_->disconnect();
@@ -927,7 +938,13 @@ void MediaControlsImpl::Hide() {
timeline_->OnControlsHidden();
UpdateCSSClassFromState();
- UpdateActingAsAudioControls();
+
+ // Hide is called when the HTMLMediaElement is removed from a document. If we
+ // stop acting as audio controls during this removal, we end up inserting
+ // nodes during the removal, firing a DCHECK. To avoid this, only update here
+ // when the media element is connected.
+ if (MediaElement().isConnected())
+ UpdateActingAsAudioControls();
}
bool MediaControlsImpl::IsVisible() const {
@@ -1316,14 +1333,18 @@ void MediaControlsImpl::UpdateScrubbingMessageFits() const {
}
void MediaControlsImpl::UpdateSizingCSSClass() {
- int width = size_.Width();
- SetClass(kSizingSmallCSSClass,
- ShouldShowVideoControls() && width < kSizingMediumThreshold);
- SetClass(kSizingMediumCSSClass, ShouldShowVideoControls() &&
- width >= kSizingMediumThreshold &&
- width < kSizingLargeThreshold);
- SetClass(kSizingLargeCSSClass,
- ShouldShowVideoControls() && width >= kSizingLargeThreshold);
+ MediaControlsSizingClass sizing_class =
+ MediaControls::GetSizingClass(size_.Width());
+
+ SetClass(kMediaControlsSizingSmallCSSClass,
+ ShouldShowVideoControls() &&
+ sizing_class == MediaControlsSizingClass::kSmall);
+ SetClass(kMediaControlsSizingMediumCSSClass,
+ ShouldShowVideoControls() &&
+ sizing_class == MediaControlsSizingClass::kMedium);
+ SetClass(kMediaControlsSizingLargeCSSClass,
+ ShouldShowVideoControls() &&
+ sizing_class == MediaControlsSizingClass::kLarge);
UpdateOverlayPlayButtonWidthCSSVar();
}
@@ -1338,10 +1359,11 @@ void MediaControlsImpl::UpdateOverlayPlayButtonWidthCSSVar() {
int height = size_.Height();
double minDimension = std::min(width, height);
+ MediaControlsSizingClass sizing_class = MediaControls::GetSizingClass(width);
double sizingRatio;
- if (width >= kSizingLargeThreshold) {
+ if (sizing_class == MediaControlsSizingClass::kLarge) {
sizingRatio = kSizingLargeOverlayPlayButtonSizeRatio;
- } else if (width >= kSizingMediumThreshold) {
+ } else if (sizing_class == MediaControlsSizingClass::kMedium) {
sizingRatio = kSizingMediumOverlayPlayButtonSizeRatio;
} else {
sizingRatio = kSizingSmallOverlayPlayButtonSizeRatio;
@@ -1693,6 +1715,14 @@ void MediaControlsImpl::OnExitedFullscreen() {
StartHideMediaControlsTimer();
}
+void MediaControlsImpl::OnPictureInPictureChanged() {
+ // This will only be called if the media controls are listening to the
+ // Picture-in-Picture events which only happen when they provide a
+ // Picture-in-Picture button.
+ DCHECK(picture_in_picture_button_);
+ picture_in_picture_button_->UpdateDisplayType();
+}
+
void MediaControlsImpl::OnPanelKeypress() {
// If the user is interacting with the controls via the keyboard, don't hide
// the controls. This is called when the user mutes/unmutes, turns CC on/off,
@@ -2031,6 +2061,7 @@ void MediaControlsImpl::Trace(blink::Visitor* visitor) {
visitor->Trace(media_event_listener_);
visitor->Trace(orientation_lock_delegate_);
visitor->Trace(rotate_to_fullscreen_delegate_);
+ visitor->Trace(display_cutout_delegate_);
visitor->Trace(download_iph_manager_);
visitor->Trace(media_button_panel_);
visitor->Trace(loading_panel_);
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl.h b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl.h
index 7b013d6909d..28ef1e8e192 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl.h
+++ b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl.h
@@ -38,6 +38,7 @@ namespace blink {
class Event;
class HTMLVideoElement;
class MediaControlsMediaEventListener;
+class MediaControlsDisplayCutoutDelegate;
class MediaControlsOrientationLockDelegate;
class MediaControlsRotateToFullscreenDelegate;
class MediaControlsWindowEventListener;
@@ -200,6 +201,7 @@ class MODULES_EXPORT MediaControlsImpl final : public HTMLDivElement,
friend class MediaControlsWindowEventListener;
// For tests.
+ friend class MediaControlsDisplayCutoutDelegateTest;
friend class MediaControlsOrientationLockDelegateTest;
friend class MediaControlsOrientationLockAndRotateToFullscreenDelegateTest;
friend class MediaControlsRotateToFullscreenDelegateTest;
@@ -315,6 +317,7 @@ class MODULES_EXPORT MediaControlsImpl final : public HTMLDivElement,
void OnLoadedMetadata();
void OnEnteredFullscreen();
void OnExitedFullscreen();
+ void OnPictureInPictureChanged();
void OnPanelKeypress();
void OnMediaKeyboardEvent(Event* event) { DefaultEventHandler(event); }
void OnWaiting();
@@ -351,6 +354,7 @@ class MODULES_EXPORT MediaControlsImpl final : public HTMLDivElement,
Member<MediaControlsOrientationLockDelegate> orientation_lock_delegate_;
Member<MediaControlsRotateToFullscreenDelegate>
rotate_to_fullscreen_delegate_;
+ Member<MediaControlsDisplayCutoutDelegate> display_cutout_delegate_;
TaskRunnerTimer<MediaControlsImpl> hide_media_controls_timer_;
unsigned hide_timer_behavior_flags_;
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl_test.cc b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl_test.cc
index 078a5b3ec57..4bd7baed6c9 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl_test.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_impl_test.cc
@@ -15,10 +15,12 @@
#include "third_party/blink/public/platform/web_screen_info.h"
#include "third_party/blink/public/platform/web_size.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
+#include "third_party/blink/renderer/core/css/document_style_environment_variables.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/element_traversal.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/geometry/dom_rect.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
@@ -1335,4 +1337,42 @@ TEST_F(MediaControlsImplTest, CastOverlayShowsOnSomeEvents) {
}
}
+class ModernMediaControlsImplTest : public MediaControlsImplTest {
+ public:
+ void SetUp() override {
+ RuntimeEnabledFeatures::SetModernMediaControlsEnabled(true);
+ MediaControlsImplTest::SetUp();
+ }
+};
+
+TEST_F(ModernMediaControlsImplTest, ControlsShouldUseSafeAreaInsets) {
+ {
+ const ComputedStyle* style = MediaControls().EnsureComputedStyle();
+ EXPECT_EQ(0.0, style->MarginTop().Pixels());
+ EXPECT_EQ(0.0, style->MarginLeft().Pixels());
+ EXPECT_EQ(0.0, style->MarginBottom().Pixels());
+ EXPECT_EQ(0.0, style->MarginRight().Pixels());
+ }
+
+ GetStyleEngine().EnsureEnvironmentVariables().SetVariable(
+ "safe-area-inset-top", "1px");
+ GetStyleEngine().EnsureEnvironmentVariables().SetVariable(
+ "safe-area-inset-left", "2px");
+ GetStyleEngine().EnsureEnvironmentVariables().SetVariable(
+ "safe-area-inset-bottom", "3px");
+ GetStyleEngine().EnsureEnvironmentVariables().SetVariable(
+ "safe-area-inset-right", "4px");
+
+ EXPECT_TRUE(GetDocument().NeedsLayoutTreeUpdate());
+ GetDocument().View()->UpdateAllLifecyclePhases();
+
+ {
+ const ComputedStyle* style = MediaControls().EnsureComputedStyle();
+ EXPECT_EQ(1.0, style->MarginTop().Pixels());
+ EXPECT_EQ(2.0, style->MarginLeft().Pixels());
+ EXPECT_EQ(3.0, style->MarginBottom().Pixels());
+ EXPECT_EQ(4.0, style->MarginRight().Pixels());
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_media_event_listener.cc b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_media_event_listener.cc
index 67eb2e9a1ae..ffe4904ed7e 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_media_event_listener.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_media_event_listener.cc
@@ -4,7 +4,9 @@
#include "third_party/blink/renderer/modules/media_controls/media_controls_media_event_listener.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/frame/settings.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/html/track/text_track_list.h"
#include "third_party/blink/renderer/modules/media_controls/media_controls_impl.h"
@@ -49,6 +51,19 @@ void MediaControlsMediaEventListener::Attach() {
media_controls_->GetDocument().addEventListener(
EventTypeNames::fullscreenchange, this, false);
+ // Picture-in-Picture events.
+ if (RuntimeEnabledFeatures::PictureInPictureEnabled() &&
+ media_controls_->GetDocument().GetSettings() &&
+ media_controls_->GetDocument()
+ .GetSettings()
+ ->GetPictureInPictureEnabled() &&
+ GetMediaElement().IsHTMLVideoElement()) {
+ GetMediaElement().addEventListener(EventTypeNames::enterpictureinpicture,
+ this, false);
+ GetMediaElement().addEventListener(EventTypeNames::leavepictureinpicture,
+ this, false);
+ }
+
// TextTracks events.
TextTrackList* text_tracks = GetMediaElement().textTracks();
text_tracks->addEventListener(EventTypeNames::addtrack, this, false);
@@ -188,6 +203,13 @@ void MediaControlsMediaEventListener::handleEvent(
return;
}
+ // Picture-in-Picture events.
+ if (event->type() == EventTypeNames::enterpictureinpicture ||
+ event->type() == EventTypeNames::leavepictureinpicture) {
+ media_controls_->OnPictureInPictureChanged();
+ return;
+ }
+
// TextTracks events.
if (event->type() == EventTypeNames::addtrack ||
event->type() == EventTypeNames::removetrack) {
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc
index edc8fb519ab..b591afcf2e2 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc
@@ -88,13 +88,13 @@ class MockScreenOrientation final
void DidEnterFullscreen(Document* document) {
DCHECK(document);
- Fullscreen::From(*document).DidEnterFullscreen();
+ Fullscreen::DidEnterFullscreen(*document);
document->ServiceScriptedAnimations(WTF::CurrentTimeTicks());
}
void DidExitFullscreen(Document* document) {
DCHECK(document);
- Fullscreen::From(*document).DidExitFullscreen();
+ Fullscreen::DidExitFullscreen(*document);
document->ServiceScriptedAnimations(WTF::CurrentTimeTicks());
}
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc
index 4923cac0e5f..c01ec30bd36 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc
+++ b/chromium/third_party/blink/renderer/modules/media_controls/media_controls_rotate_to_fullscreen_delegate_test.cc
@@ -12,6 +12,7 @@
#include "third_party/blink/public/platform/web_size.h"
#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/events/event.h"
#include "third_party/blink/renderer/core/dom/user_gesture_indicator.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -62,10 +63,10 @@ class MockChromeClient : public EmptyChromeClient {
std::move(screen_orientation));
}
void EnterFullscreen(LocalFrame& frame, const FullscreenOptions&) override {
- Fullscreen::From(*frame.GetDocument()).DidEnterFullscreen();
+ Fullscreen::DidEnterFullscreen(*frame.GetDocument());
}
void ExitFullscreen(LocalFrame& frame) override {
- Fullscreen::From(*frame.GetDocument()).DidExitFullscreen();
+ Fullscreen::DidExitFullscreen(*frame.GetDocument());
}
MOCK_CONST_METHOD0(GetScreenInfo, WebScreenInfo());
@@ -190,8 +191,8 @@ void MediaControlsRotateToFullscreenDelegateTest::InitScreenAndVideo(
WebScreenInfo screen_info;
screen_info.orientation_type = initial_screen_orientation;
EXPECT_CALL(GetChromeClient(), GetScreenInfo())
- .Times(1)
- .WillOnce(Return(screen_info));
+ .Times(AtLeast(1))
+ .WillRepeatedly(Return(screen_info));
// Set up the WebMediaPlayer instance.
GetDocument().body()->AppendChild(&GetVideo());
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/resources/ic_picture_in_picture_exit.svg b/chromium/third_party/blink/renderer/modules/media_controls/resources/ic_picture_in_picture_exit.svg
new file mode 100644
index 00000000000..ce14e63417c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/media_controls/resources/ic_picture_in_picture_exit.svg
@@ -0,0 +1,6 @@
+<svg width="22" height="18" xmlns="http://www.w3.org/2000/svg">
+ <g fill="none" fill-rule="evenodd" opacity=".87">
+ <path d="M18 4H4v10h14V4zm4 12V1.98C22 .88 21.1 0 20 0H2C.9 0 0 .88 0 1.98V16c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2zm-2 .02H2V1.97h18v14.05z" fill="#000" fill-rule="nonzero"/>
+ <path d="M-1-3h24v24H-1z"/>
+ </g>
+</svg> \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/resources/ic_subtitles.svg b/chromium/third_party/blink/renderer/modules/media_controls/resources/ic_subtitles.svg
new file mode 100644
index 00000000000..aa5d49cb76a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/media_controls/resources/ic_subtitles.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="#000000">
+ <path d="M0 0h24v24H0z" fill="none"/>
+ <path d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zM4 12h4v2H4v-2zm10 6H4v-2h10v2zm6 0h-4v-2h4v2zm0-4H10v-2h10v2z"/>
+</svg>
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/resources/mediaInterstitials.css b/chromium/third_party/blink/renderer/modules/media_controls/resources/mediaInterstitials.css
index e88476d1240..766321f272e 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/resources/mediaInterstitials.css
+++ b/chromium/third_party/blink/renderer/modules/media_controls/resources/mediaInterstitials.css
@@ -37,8 +37,7 @@ video::-internal-media-interstitial-background-image {
filter: grayscale(100%) blur(5px) opacity(40%);
}
-video::-internal-media-remoting-cast-icon,
-video::-internal-picture-in-picture-icon {
+video::-internal-media-remoting-cast-icon {
-webkit-appearance: none;
background-size: 100% 100%;
background-repeat: no-repeat;
@@ -55,7 +54,8 @@ video::-internal-picture-in-picture-icon {
top: calc(50% - 3vw);
}
-video::-internal-media-interstitial-message {
+video::-internal-media-interstitial-message,
+video::-internal-picture-in-picture-interstitial-message {
display: inline;
position: absolute;
top: calc(50% + 1vw);
@@ -65,12 +65,30 @@ video::-internal-media-interstitial-message {
text-wrap: none;
text-align: center;
background-color: transparent;
- font-size: 90%;
font-family: Roboto-Regular, Sans-serif, Segoe, Serif, Helvetica;
padding: 0px;
margin: 0px;
}
+video::-internal-media-interstitial-message {
+ font-size: 90%;
+}
+
+video::-internal-picture-in-picture-interstitial-message {
+ top: 0;
+ left: 0;
+ width: auto;
+
+ color: rgba(255,255,255,0.8);
+ text-align: left;
+ letter-spacing: 0.2px;
+
+ /** default to small */
+ font-size: 14px;
+ line-height: 20px;
+ margin: 8px 16px;
+}
+
video::-internal-media-remoting-toast-message {
display: inline;
position: absolute;
@@ -89,12 +107,19 @@ video::-internal-media-remoting-toast-message {
}
video::-internal-media-remoting-cast-icon {
- background-image: -webkit-image-set(
- url(default_100_percent/legacy/mediaremoting_cast.png) 1x,
- url(default_200_percent/legacy/mediaremoting_cast.png) 2x);
+ background-image: -webkit-image-set(
+ url(default_100_percent/legacy/mediaremoting_cast.png) 1x,
+ url(default_200_percent/legacy/mediaremoting_cast.png) 2x);
+}
+
+video::-internal-picture-in-picture-interstitial-message.sizing-medium {
+ font-size: 24px;
+ line-height: 28px;
+ margin: 32px 64px;
}
-video::-internal-picture-in-picture-icon {
- background-image: -webkit-image-set(
- url(default_100_percent/legacy/mediaplayer_pictureinpicture.png) 1x);
+video::-internal-picture-in-picture-interstitial-message.sizing-large {
+ font-size: 40px;
+ line-height: 47px;
+ margin: 64px 96px;
}
diff --git a/chromium/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css b/chromium/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css
index 2faa7f38207..c02f8468adb 100644
--- a/chromium/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css
+++ b/chromium/third_party/blink/renderer/modules/media_controls/resources/modernMediaControls.css
@@ -36,6 +36,11 @@ video::-webkit-media-controls {
justify-content: flex-end;
align-items: center;
font-size: 14px;
+
+ margin-top: env(safe-area-inset-top);
+ margin-left: env(safe-area-inset-left);
+ margin-right: env(safe-area-inset-right);
+ margin-bottom: env(safe-area-inset-bottom);
}
audio::-webkit-media-controls-enclosure,
@@ -329,6 +334,10 @@ audio::-webkit-media-controls-toggle-closed-captions-button {
}
video::-webkit-media-controls-toggle-closed-captions-button {
+ background-image: -webkit-image-set(url(ic_subtitles.svg) 1x);
+}
+
+video::-webkit-media-controls-toggle-closed-captions-button.closed-captions {
background-image: -webkit-image-set(url(ic_closed_caption.svg) 1x);
}
@@ -347,6 +356,11 @@ video::-internal-media-controls-picture-in-picture-button {
url(ic_picture_in_picture.svg) 1x);
}
+video::-internal-media-controls-picture-in-picture-button.on {
+ background-image: -webkit-image-set(
+ url(ic_picture_in_picture_exit.svg) 1x);
+}
+
video::-webkit-media-controls:not(.audio-only) [pseudo="-webkit-media-controls-panel"] [pseudo="-internal-media-controls-overflow-button"] {
background-image: -webkit-image-set(url(ic_menu_white.svg) 1x);
}
@@ -691,25 +705,6 @@ video::-webkit-media-controls.sizing-large div[pseudo="-internal-media-controls-
}
/* TODO(https://crbug.com/857120): All these are the same, so these are unnecessary. */
-video::-webkit-media-controls.sizing-small label[pseudo="-internal-media-controls-overflow-menu-list-item" i] {
- font-size: 14px;
- height: 48px;
- padding: 0 16px 0;
-}
-
-video::-webkit-media-controls.sizing-medium label[pseudo="-internal-media-controls-overflow-menu-list-item" i] {
- font-size: 14px;
- height: 48px;
- padding: 0 16px 0;
-}
-
-video::-webkit-media-controls.sizing-large label[pseudo="-internal-media-controls-overflow-menu-list-item" i] {
- font-size: 14px;
- height: 48px;
- padding: 0 16px 0;
-}
-
-/* TODO(https://crbug.com/857120): All these are the same, so these are unnecessary. */
video::-webkit-media-controls.sizing-small label[pseudo="-internal-media-controls-overflow-menu-list-item" i] input {
margin-left: 0;
margin-right: 16px;
@@ -770,6 +765,7 @@ video::-internal-media-controls-overflow-menu-list-item:focus,
audio::-internal-media-controls-text-track-list-item:focus,
video::-internal-media-controls-text-track-list-item:focus {
background-color: #e0e0e0;
+ outline: none;
}
audio::-internal-media-controls-text-track-list-header,
diff --git a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_canvas_element_capture.cc b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_canvas_element_capture.cc
index 44561f05047..d4a2845da0d 100644
--- a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_canvas_element_capture.cc
+++ b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_canvas_element_capture.cc
@@ -9,7 +9,6 @@
#include "third_party/blink/public/platform/web_canvas_capture_handler.h"
#include "third_party/blink/public/platform/web_media_stream.h"
#include "third_party/blink/public/platform/web_media_stream_track.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
#include "third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_media_stream_track.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream.h"
@@ -34,7 +33,7 @@ MediaStream* HTMLCanvasElementCapture::captureStream(
double frame_rate,
ExceptionState& exception_state) {
if (frame_rate < 0.0) {
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"Given frame rate is not supported.");
return nullptr;
}
@@ -67,7 +66,8 @@ MediaStream* HTMLCanvasElementCapture::captureStream(
if (!handler) {
exception_state.ThrowDOMException(
- kNotSupportedError, "No CanvasCapture handler can be created.");
+ DOMExceptionCode::kNotSupportedError,
+ "No CanvasCapture handler can be created.");
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc
index b55bffb40c3..fa721b21655 100644
--- a/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc
+++ b/chromium/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc
@@ -9,7 +9,6 @@
#include "third_party/blink/public/platform/web_media_stream.h"
#include "third_party/blink/public/platform/web_media_stream_track.h"
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/html/track/audio_track_list.h"
#include "third_party/blink/renderer/core/html/track/video_track_list.h"
@@ -63,7 +62,7 @@ void MediaElementEventListener::handleEvent(ExecutionContext* context,
const MediaStreamTrackVector tracks = media_stream_->getTracks();
for (const auto& track : tracks) {
track->stopTrack(context);
- media_stream_->RemoveTrackByComponent(track->Component());
+ media_stream_->RemoveTrackByComponentAndFireEvents(track->Component());
}
media_stream_->StreamEnded();
@@ -77,7 +76,7 @@ void MediaElementEventListener::handleEvent(ExecutionContext* context,
const MediaStreamTrackVector tracks = media_stream_->getTracks();
for (const auto& track : tracks) {
track->stopTrack(context);
- media_stream_->RemoveTrackByComponent(track->Component());
+ media_stream_->RemoveTrackByComponentAndFireEvents(track->Component());
}
MediaStreamDescriptor* const descriptor =
media_element_->currentSrc().IsEmpty()
@@ -85,10 +84,14 @@ void MediaElementEventListener::handleEvent(ExecutionContext* context,
: MediaStreamRegistry::Registry().LookupMediaStreamDescriptor(
media_element_->currentSrc().GetString());
DCHECK(descriptor);
- for (size_t i = 0; i < descriptor->NumberOfAudioComponents(); i++)
- media_stream_->AddTrackByComponent(descriptor->AudioComponent(i));
- for (size_t i = 0; i < descriptor->NumberOfVideoComponents(); i++)
- media_stream_->AddTrackByComponent(descriptor->VideoComponent(i));
+ for (size_t i = 0; i < descriptor->NumberOfAudioComponents(); i++) {
+ media_stream_->AddTrackByComponentAndFireEvents(
+ descriptor->AudioComponent(i));
+ }
+ for (size_t i = 0; i < descriptor->NumberOfVideoComponents(); i++) {
+ media_stream_->AddTrackByComponentAndFireEvents(
+ descriptor->VideoComponent(i));
+ }
UpdateSources(context);
return;
}
@@ -108,15 +111,13 @@ void MediaElementEventListener::handleEvent(ExecutionContext* context,
&web_stream, media_element_->GetWebMediaPlayer());
}
- WebVector<WebMediaStreamTrack> video_tracks;
- web_stream.VideoTracks(video_tracks);
+ WebVector<WebMediaStreamTrack> video_tracks = web_stream.VideoTracks();
for (const auto& track : video_tracks)
- media_stream_->AddTrackByComponent(track);
+ media_stream_->AddTrackByComponentAndFireEvents(track);
- WebVector<WebMediaStreamTrack> audio_tracks;
- web_stream.AudioTracks(audio_tracks);
+ WebVector<WebMediaStreamTrack> audio_tracks = web_stream.AudioTracks();
for (const auto& track : audio_tracks)
- media_stream_->AddTrackByComponent(track);
+ media_stream_->AddTrackByComponentAndFireEvents(track);
DVLOG(2) << "#videotracks: " << video_tracks.size()
<< " #audiotracks: " << audio_tracks.size();
@@ -154,7 +155,7 @@ MediaStream* HTMLMediaElementCapture::captureStream(
if (HTMLMediaElementEncryptedMedia::mediaKeys(element)) {
// This exception is not defined in the spec, see
// https://github.com/w3c/mediacapture-fromelement/issues/20.
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"Stream capture not supported with EME");
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc b/chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc
index 95412d07480..06ae24723c4 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder.cc
@@ -182,7 +182,8 @@ MediaRecorder::MediaRecorder(ExecutionContext* context,
if (!recorder_handler_) {
exception_state.ThrowDOMException(
- kNotSupportedError, "No MediaRecorder handler can be created.");
+ DOMExceptionCode::kNotSupportedError,
+ "No MediaRecorder handler can be created.");
return;
}
@@ -196,14 +197,22 @@ MediaRecorder::MediaRecorder(ExecutionContext* context,
content_type.Parameter("codecs"), audio_bits_per_second_,
video_bits_per_second_)) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"Failed to initialize native MediaRecorder the type provided (" +
mime_type_ + ") is not supported.");
return;
}
+ // If the user requested no mimeType, query |recorder_handler_|.
+ if (options.mimeType().IsEmpty()) {
+ const String actual_mime_type = recorder_handler_->ActualMimeType();
+ if (!actual_mime_type.IsEmpty())
+ mime_type_ = actual_mime_type;
+ }
stopped_ = false;
}
+MediaRecorder::~MediaRecorder() = default;
+
String MediaRecorder::state() const {
return StateToString(state_);
}
@@ -215,14 +224,14 @@ void MediaRecorder::start(ExceptionState& exception_state) {
void MediaRecorder::start(int time_slice, ExceptionState& exception_state) {
if (state_ != State::kInactive) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"The MediaRecorder's state is '" + StateToString(state_) + "'.");
return;
}
state_ = State::kRecording;
if (!recorder_handler_->Start(time_slice)) {
- exception_state.ThrowDOMException(kUnknownError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kUnknownError,
"The MediaRecorder failed to start "
"because there are no audio or video "
"tracks available.");
@@ -234,7 +243,7 @@ void MediaRecorder::start(int time_slice, ExceptionState& exception_state) {
void MediaRecorder::stop(ExceptionState& exception_state) {
if (state_ == State::kInactive) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"The MediaRecorder's state is '" + StateToString(state_) + "'.");
return;
}
@@ -245,7 +254,7 @@ void MediaRecorder::stop(ExceptionState& exception_state) {
void MediaRecorder::pause(ExceptionState& exception_state) {
if (state_ == State::kInactive) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"The MediaRecorder's state is '" + StateToString(state_) + "'.");
return;
}
@@ -262,7 +271,7 @@ void MediaRecorder::pause(ExceptionState& exception_state) {
void MediaRecorder::resume(ExceptionState& exception_state) {
if (state_ == State::kInactive) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"The MediaRecorder's state is '" + StateToString(state_) + "'.");
return;
}
@@ -278,7 +287,7 @@ void MediaRecorder::resume(ExceptionState& exception_state) {
void MediaRecorder::requestData(ExceptionState& exception_state) {
if (state_ == State::kInactive) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"The MediaRecorder's state is '" + StateToString(state_) + "'.");
return;
}
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder.h b/chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder.h
index 9545319263d..7597107ccb8 100644
--- a/chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder.h
+++ b/chromium/third_party/blink/renderer/modules/mediarecorder/media_recorder.h
@@ -42,7 +42,7 @@ class MODULES_EXPORT MediaRecorder final
const MediaRecorderOptions& options,
ExceptionState& exception_state);
- ~MediaRecorder() override = default;
+ ~MediaRecorder() override;
MediaStream* stream() const { return stream_.Get(); }
const String& mimeType() const { return mime_type_; }
diff --git a/chromium/third_party/blink/renderer/modules/mediasession/media_metadata.cc b/chromium/third_party/blink/renderer/modules/mediasession/media_metadata.cc
index 49c61ffbfde..831942c83cb 100644
--- a/chromium/third_party/blink/renderer/modules/mediasession/media_metadata.cc
+++ b/chromium/third_party/blink/renderer/modules/mediasession/media_metadata.cc
@@ -5,13 +5,12 @@
#include "third_party/blink/renderer/modules/mediasession/media_metadata.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/modules/mediasession/media_image.h"
#include "third_party/blink/renderer/modules/mediasession/media_metadata_init.h"
#include "third_party/blink/renderer/modules/mediasession/media_session.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/mediasession/media_metadata.h b/chromium/third_party/blink/renderer/modules/mediasession/media_metadata.h
index f7940d4923f..e632ad6543b 100644
--- a/chromium/third_party/blink/renderer/modules/mediasession/media_metadata.h
+++ b/chromium/third_party/blink/renderer/modules/mediasession/media_metadata.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASESSION_MEDIA_METADATA_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASESSION_MEDIA_METADATA_H_
+#include "third_party/blink/renderer/modules/mediasession/media_image.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -14,7 +15,6 @@
namespace blink {
class ExceptionState;
-class MediaImage;
class MediaMetadataInit;
class MediaSession;
class ScriptState;
diff --git a/chromium/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.cc b/chromium/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.cc
index f5e8be079dd..b70fa5a6063 100644
--- a/chromium/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.cc
+++ b/chromium/third_party/blink/renderer/modules/mediasession/media_metadata_sanitizer.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/public/platform/web_icon_sizes_parser.h"
#include "third_party/blink/public/platform/web_size.h"
+#include "third_party/blink/public/platform/web_string.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/modules/mediasession/media_image.h"
diff --git a/chromium/third_party/blink/renderer/modules/mediasession/media_session.cc b/chromium/third_party/blink/renderer/modules/mediasession/media_session.cc
index 9696453fb1a..1ba96056294 100644
--- a/chromium/third_party/blink/renderer/modules/mediasession/media_session.cc
+++ b/chromium/third_party/blink/renderer/modules/mediasession/media_session.cc
@@ -235,10 +235,4 @@ void MediaSession::Trace(blink::Visitor* visitor) {
ContextClient::Trace(visitor);
}
-void MediaSession::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- for (auto handler : action_handlers_.Values())
- visitor->TraceWrappers(handler);
- ScriptWrappable::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/mediasession/media_session.h b/chromium/third_party/blink/renderer/modules/mediasession/media_session.h
index 6d2156e10ef..45c9a2f63de 100644
--- a/chromium/third_party/blink/renderer/modules/mediasession/media_session.h
+++ b/chromium/third_party/blink/renderer/modules/mediasession/media_session.h
@@ -47,7 +47,6 @@ class MODULES_EXPORT MediaSession final
void OnMetadataChanged();
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
friend class V8MediaSession;
diff --git a/chromium/third_party/blink/renderer/modules/mediasource/media_source.cc b/chromium/third_party/blink/renderer/modules/mediasource/media_source.cc
index 93c4412c0ad..4852e555429 100644
--- a/chromium/third_party/blink/renderer/modules/mediasource/media_source.cc
+++ b/chromium/third_party/blink/renderer/modules/mediasource/media_source.cc
@@ -35,11 +35,8 @@
#include "base/memory/ptr_util.h"
#include "third_party/blink/public/platform/web_media_source.h"
#include "third_party/blink/public/platform/web_source_buffer.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/core/dom/events/media_element_event_queue.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/core/dom/events/event_queue.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
@@ -47,6 +44,8 @@
#include "third_party/blink/renderer/core/html/track/video_track_list.h"
#include "third_party/blink/renderer/modules/mediasource/media_source_registry.h"
#include "third_party/blink/renderer/modules/mediasource/source_buffer_track_base_supplement.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/network/mime/content_type.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
@@ -66,7 +65,7 @@ static bool ThrowExceptionIfClosed(bool is_open,
ExceptionState& exception_state) {
if (!is_open) {
MediaSource::LogAndThrowDOMException(
- exception_state, kInvalidStateError,
+ exception_state, DOMExceptionCode::kInvalidStateError,
"The MediaSource's readyState is not 'open'.");
return true;
}
@@ -81,7 +80,8 @@ static bool ThrowExceptionIfClosedOrUpdating(bool is_open,
return true;
if (is_updating) {
- MediaSource::LogAndThrowDOMException(exception_state, kInvalidStateError,
+ MediaSource::LogAndThrowDOMException(exception_state,
+ DOMExceptionCode::kInvalidStateError,
"The 'updating' attribute is true on "
"one or more of this MediaSource's "
"SourceBuffers.");
@@ -113,7 +113,8 @@ MediaSource* MediaSource::Create(ExecutionContext* context) {
MediaSource::MediaSource(ExecutionContext* context)
: ContextLifecycleObserver(context),
ready_state_(ClosedKeyword()),
- async_event_queue_(MediaElementEventQueue::Create(this, context)),
+ async_event_queue_(
+ EventQueue::Create(context, TaskType::kMediaElementEvent)),
attached_element_(nullptr),
source_buffers_(SourceBufferList::Create(GetExecutionContext(),
async_event_queue_.Get())),
@@ -131,10 +132,10 @@ MediaSource::~MediaSource() {
}
void MediaSource::LogAndThrowDOMException(ExceptionState& exception_state,
- ExceptionCode error,
+ DOMExceptionCode error,
const String& message) {
- BLINK_MSLOG << __func__ << " (error=" << error << ", message=" << message
- << ")";
+ BLINK_MSLOG << __func__ << " (error=" << ToExceptionCode(error)
+ << ", message=" << message << ")";
exception_state.ThrowDOMException(error, message);
}
@@ -149,7 +150,7 @@ SourceBuffer* MediaSource::addSourceBuffer(const String& type,
BLINK_MSLOG << __func__ << " this=" << this << " type=" << type;
// 2.2
- // https://www.w3.org/TR/media-source/#widl-MediaSource-addSourceBuffer-SourceBuffer-DOMString-type/
+ // https://www.w3.org/TR/media-source/#dom-mediasource-addsourcebuffer
// 1. If type is an empty string then throw a TypeError exception
// and abort these steps.
if (type.IsEmpty()) {
@@ -161,7 +162,7 @@ SourceBuffer* MediaSource::addSourceBuffer(const String& type,
// NotSupportedError exception and abort these steps.
if (!isTypeSupported(type)) {
LogAndThrowDOMException(
- exception_state, kNotSupportedError,
+ exception_state, DOMExceptionCode::kNotSupportedError,
"The type provided ('" + type + "') is unsupported.");
return nullptr;
}
@@ -169,7 +170,8 @@ SourceBuffer* MediaSource::addSourceBuffer(const String& type,
// 4. If the readyState attribute is not in the "open" state then throw an
// InvalidStateError exception and abort these steps.
if (!IsOpen()) {
- LogAndThrowDOMException(exception_state, kInvalidStateError,
+ LogAndThrowDOMException(exception_state,
+ DOMExceptionCode::kInvalidStateError,
"The MediaSource's readyState is not 'open'.");
return nullptr;
}
@@ -181,8 +183,10 @@ SourceBuffer* MediaSource::addSourceBuffer(const String& type,
CreateWebSourceBuffer(content_type.GetType(), codecs, exception_state);
if (!web_source_buffer) {
- DCHECK(exception_state.Code() == kNotSupportedError ||
- exception_state.Code() == kQuotaExceededError);
+ DCHECK(exception_state.CodeAs<DOMExceptionCode>() ==
+ DOMExceptionCode::kNotSupportedError ||
+ exception_state.CodeAs<DOMExceptionCode>() ==
+ DOMExceptionCode::kQuotaExceededError);
// 2. If type contains a MIME type that is not supported ..., then throw a
// NotSupportedError exception and abort these steps.
// 3. If the user agent can't handle any more SourceBuffer objects then
@@ -190,13 +194,27 @@ SourceBuffer* MediaSource::addSourceBuffer(const String& type,
return nullptr;
}
+ bool generate_timestamps_flag =
+ web_source_buffer->GetGenerateTimestampsFlag();
+
SourceBuffer* buffer = SourceBuffer::Create(std::move(web_source_buffer),
this, async_event_queue_.Get());
- // 6. Add the new object to sourceBuffers and fire a addsourcebuffer on that
- // object.
+ // 8. Add the new object to sourceBuffers and queue a simple task to fire a
+ // simple event named addsourcebuffer at sourceBuffers.
source_buffers_->Add(buffer);
- // 7. Return the new object to the caller.
+ // Steps 6 and 7 (Set the SourceBuffer's mode attribute based on the byte
+ // stream format's generate timestamps flag). We do this after adding to
+ // sourceBuffers (step 8) to enable direct reuse of the setMode() logic here,
+ // which depends on |buffer| being in |source_buffers_| in our
+ // implementation.
+ if (generate_timestamps_flag) {
+ buffer->setMode(SourceBuffer::SequenceKeyword(), exception_state);
+ } else {
+ buffer->setMode(SourceBuffer::SegmentsKeyword(), exception_state);
+ }
+
+ // 9. Return the new object to the caller.
BLINK_MSLOG << __func__ << " this=" << this << " type=" << type << " -> "
<< buffer;
return buffer;
@@ -213,7 +231,7 @@ void MediaSource::removeSourceBuffer(SourceBuffer* buffer,
// throw a NotFoundError exception and abort these steps.
if (!source_buffers_->length() || !source_buffers_->Contains(buffer)) {
LogAndThrowDOMException(
- exception_state, kNotFoundError,
+ exception_state, DOMExceptionCode::kNotFoundError,
"The SourceBuffer provided is not contained in this MediaSource.");
return;
}
@@ -536,7 +554,7 @@ void MediaSource::DurationChangeAlgorithm(double new_duration,
if (new_duration < highest_buffered_presentation_timestamp) {
if (RuntimeEnabledFeatures::MediaSourceNewAbortAndDurationEnabled()) {
LogAndThrowDOMException(
- exception_state, kInvalidStateError,
+ exception_state, DOMExceptionCode::kInvalidStateError,
"Setting duration below highest presentation timestamp of any "
"buffered coded frames is disallowed. Instead, first do asynchronous "
"remove(newDuration, oldDuration) on all sourceBuffers, where "
@@ -783,7 +801,6 @@ bool MediaSource::HasPendingActivity() const {
}
void MediaSource::ContextDestroyed(ExecutionContext*) {
- async_event_queue_->Close();
if (!IsClosed())
SetReadyState(ClosedKeyword());
web_media_source_.reset();
@@ -807,7 +824,7 @@ std::unique_ptr<WebSourceBuffer> MediaSource::CreateWebSourceBuffer(
// types specified for the other SourceBuffer objects in sourceBuffers,
// then throw a NotSupportedError exception and abort these steps.
LogAndThrowDOMException(
- exception_state, kNotSupportedError,
+ exception_state, DOMExceptionCode::kNotSupportedError,
"The type provided ('" + type + "') is not supported.");
return nullptr;
case WebMediaSource::kAddStatusReachedIdLimit:
@@ -816,7 +833,8 @@ std::unique_ptr<WebSourceBuffer> MediaSource::CreateWebSourceBuffer(
// https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html#widl-MediaSource-addSourceBuffer-SourceBuffer-DOMString-type
// Step 3: If the user agent can't handle any more SourceBuffer objects
// then throw a QuotaExceededError exception and abort these steps.
- LogAndThrowDOMException(exception_state, kQuotaExceededError,
+ LogAndThrowDOMException(exception_state,
+ DOMExceptionCode::kQuotaExceededError,
"This MediaSource has reached the limit of "
"SourceBuffer objects it can handle. No "
"additional SourceBuffer objects may be added.");
diff --git a/chromium/third_party/blink/renderer/modules/mediasource/media_source.h b/chromium/third_party/blink/renderer/modules/mediasource/media_source.h
index 2ba15cb8b6d..0b288aa1ce0 100644
--- a/chromium/third_party/blink/renderer/modules/mediasource/media_source.h
+++ b/chromium/third_party/blink/renderer/modules/mediasource/media_source.h
@@ -32,21 +32,22 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASOURCE_MEDIA_SOURCE_H_
#include <memory>
+
#include "third_party/blink/public/platform/web_media_source.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/fileapi/url_registry.h"
#include "third_party/blink/renderer/core/html/media/html_media_source.h"
#include "third_party/blink/renderer/core/html/time_ranges.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
#include "third_party/blink/renderer/modules/mediasource/source_buffer.h"
#include "third_party/blink/renderer/modules/mediasource/source_buffer_list.h"
+#include "third_party/blink/renderer/platform/bindings/exception_code.h"
namespace blink {
+class EventQueue;
class ExceptionState;
-class MediaElementEventQueue;
class WebSourceBuffer;
class MediaSource final : public EventTargetWithInlineData,
@@ -65,7 +66,7 @@ class MediaSource final : public EventTargetWithInlineData,
~MediaSource() override;
static void LogAndThrowDOMException(ExceptionState&,
- ExceptionCode error,
+ DOMExceptionCode error,
const String& message);
static void LogAndThrowTypeError(ExceptionState&, const String&);
@@ -145,7 +146,7 @@ class MediaSource final : public EventTargetWithInlineData,
std::unique_ptr<WebMediaSource> web_media_source_;
AtomicString ready_state_;
- Member<MediaElementEventQueue> async_event_queue_;
+ Member<EventQueue> async_event_queue_;
WeakMember<HTMLMediaElement> attached_element_;
Member<SourceBufferList> source_buffers_;
diff --git a/chromium/third_party/blink/renderer/modules/mediasource/source_buffer.cc b/chromium/third_party/blink/renderer/modules/mediasource/source_buffer.cc
index 4d7e6fa8538..6aaa0b9bcb4 100644
--- a/chromium/third_party/blink/renderer/modules/mediasource/source_buffer.cc
+++ b/chromium/third_party/blink/renderer/modules/mediasource/source_buffer.cc
@@ -33,13 +33,11 @@
#include <limits>
#include <memory>
#include <sstream>
+
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_source_buffer.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/core/dom/events/media_element_event_queue.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/core/dom/events/event_queue.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/core/frame/use_counter.h"
@@ -53,7 +51,10 @@
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
#include "third_party/blink/renderer/modules/mediasource/media_source.h"
#include "third_party/blink/renderer/modules/mediasource/source_buffer_track_base_supplement.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
+#include "third_party/blink/renderer/platform/network/mime/content_type.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
@@ -72,13 +73,13 @@ static bool ThrowExceptionIfRemovedOrUpdating(bool is_removed,
ExceptionState& exception_state) {
if (is_removed) {
MediaSource::LogAndThrowDOMException(
- exception_state, kInvalidStateError,
+ exception_state, DOMExceptionCode::kInvalidStateError,
"This SourceBuffer has been removed from the parent media source.");
return true;
}
if (is_updating) {
MediaSource::LogAndThrowDOMException(
- exception_state, kInvalidStateError,
+ exception_state, DOMExceptionCode::kInvalidStateError,
"This SourceBuffer is still processing an 'appendBuffer' or "
"'remove' operation.");
return true;
@@ -106,7 +107,7 @@ WTF::String WebTimeRangesToString(const WebTimeRanges& ranges) {
SourceBuffer* SourceBuffer::Create(
std::unique_ptr<WebSourceBuffer> web_source_buffer,
MediaSource* source,
- MediaElementEventQueue* async_event_queue) {
+ EventQueue* async_event_queue) {
SourceBuffer* source_buffer =
new SourceBuffer(std::move(web_source_buffer), source, async_event_queue);
source_buffer->PauseIfNeeded();
@@ -115,7 +116,7 @@ SourceBuffer* SourceBuffer::Create(
SourceBuffer::SourceBuffer(std::unique_ptr<WebSourceBuffer> web_source_buffer,
MediaSource* source,
- MediaElementEventQueue* async_event_queue)
+ EventQueue* async_event_queue)
: PausableObject(source->GetExecutionContext()),
web_source_buffer_(std::move(web_source_buffer)),
source_(source),
@@ -172,40 +173,54 @@ void SourceBuffer::setMode(const AtomicString& new_mode,
ExceptionState& exception_state) {
BLINK_SBLOG << __func__ << " this=" << this << " newMode=" << new_mode;
// Section 3.1 On setting mode attribute steps.
- // 1. Let new mode equal the new value being assigned to this attribute.
- // 2. If this object has been removed from the sourceBuffers attribute of the
+ // https://www.w3.org/TR/media-source/#dom-sourcebuffer-mode
+ // 1. If this object has been removed from the sourceBuffers attribute of the
// parent media source, then throw an INVALID_STATE_ERR exception and abort
// these steps.
- // 3. If the updating attribute equals true, then throw an INVALID_STATE_ERR
+ // 2. If the updating attribute equals true, then throw an INVALID_STATE_ERR
// exception and abort these steps.
+ // 3. Let new mode equal the new value being assigned to this attribute.
if (ThrowExceptionIfRemovedOrUpdating(IsRemoved(), updating_,
- exception_state))
+ exception_state)) {
return;
+ }
- // 4. If the readyState attribute of the parent media source is in the "ended"
+ // 4. If generate timestamps flag equals true and new mode equals "segments",
+ // then throw a TypeError exception and abort these steps.
+ if (web_source_buffer_->GetGenerateTimestampsFlag() &&
+ new_mode == SegmentsKeyword()) {
+ MediaSource::LogAndThrowTypeError(
+ exception_state, "The mode value provided (" + SegmentsKeyword() +
+ ") is invalid for a byte stream format that uses "
+ "generated timestamps.");
+ return;
+ }
+
+ // 5. If the readyState attribute of the parent media source is in the "ended"
// state then run the following steps:
- // 4.1 Set the readyState attribute of the parent media source to "open"
- // 4.2 Queue a task to fire a simple event named sourceopen at the parent
+ // 5.1 Set the readyState attribute of the parent media source to "open"
+ // 5.2 Queue a task to fire a simple event named sourceopen at the parent
// media source.
source_->OpenIfInEndedState();
- // 5. If the append state equals PARSING_MEDIA_SEGMENT, then throw an
+ // 6. If the append state equals PARSING_MEDIA_SEGMENT, then throw an
// INVALID_STATE_ERR and abort these steps.
- // 6. If the new mode equals "sequence", then set the group start timestamp to
+ // 7. If the new mode equals "sequence", then set the group start timestamp to
// the highest presentation end timestamp.
WebSourceBuffer::AppendMode append_mode =
WebSourceBuffer::kAppendModeSegments;
if (new_mode == SequenceKeyword())
append_mode = WebSourceBuffer::kAppendModeSequence;
if (!web_source_buffer_->SetMode(append_mode)) {
- MediaSource::LogAndThrowDOMException(exception_state, kInvalidStateError,
+ MediaSource::LogAndThrowDOMException(exception_state,
+ DOMExceptionCode::kInvalidStateError,
"The mode may not be set while the "
"SourceBuffer's append state is "
"'PARSING_MEDIA_SEGMENT'.");
return;
}
- // 7. Update the attribute to new mode.
+ // 8. Update the attribute to new mode.
mode_ = new_mode;
}
@@ -216,7 +231,7 @@ TimeRanges* SourceBuffer::buffered(ExceptionState& exception_state) const {
// these steps.
if (IsRemoved()) {
MediaSource::LogAndThrowDOMException(
- exception_state, kInvalidStateError,
+ exception_state, DOMExceptionCode::kInvalidStateError,
"This SourceBuffer has been removed from the parent media source.");
return nullptr;
}
@@ -258,7 +273,8 @@ void SourceBuffer::setTimestampOffset(double offset,
// 6. If the mode attribute equals "sequence", then set the group start
// timestamp to new timestamp offset.
if (!web_source_buffer_->SetTimestampOffset(offset)) {
- MediaSource::LogAndThrowDOMException(exception_state, kInvalidStateError,
+ MediaSource::LogAndThrowDOMException(exception_state,
+ DOMExceptionCode::kInvalidStateError,
"The timestamp offset may not be set "
"while the SourceBuffer's append "
"state is 'PARSING_MEDIA_SEGMENT'.");
@@ -389,13 +405,13 @@ void SourceBuffer::abort(ExceptionState& exception_state) {
// steps.
if (IsRemoved()) {
MediaSource::LogAndThrowDOMException(
- exception_state, kInvalidStateError,
+ exception_state, DOMExceptionCode::kInvalidStateError,
"This SourceBuffer has been removed from the parent media source.");
return;
}
if (!source_->IsOpen()) {
MediaSource::LogAndThrowDOMException(
- exception_state, kInvalidStateError,
+ exception_state, DOMExceptionCode::kInvalidStateError,
"The parent media source's readyState is not 'open'.");
return;
}
@@ -409,7 +425,7 @@ void SourceBuffer::abort(ExceptionState& exception_state) {
// RuntimeEnabledFeature.
if (RuntimeEnabledFeatures::MediaSourceNewAbortAndDurationEnabled()) {
MediaSource::LogAndThrowDOMException(
- exception_state, kInvalidStateError,
+ exception_state, DOMExceptionCode::kInvalidStateError,
"Aborting asynchronous remove() operation is disallowed.");
return;
}
@@ -501,6 +517,73 @@ void SourceBuffer::remove(double start,
remove_async_part_runner_->RunAsync();
}
+void SourceBuffer::changeType(const String& type,
+ ExceptionState& exception_state) {
+ BLINK_SBLOG << __func__ << " this=" << this << " type=" << type;
+
+ // Per 30 May 2018 Codec Switching feature incubation spec:
+ // https://rawgit.com/WICG/media-source/3b3742ea788999bb7ae4a4553ac7d574b0547dbe/index.html#dom-sourcebuffer-changetype
+ // 1. If type is an empty string then throw a TypeError exception and abort
+ // these steps.
+ if (type.IsEmpty()) {
+ MediaSource::LogAndThrowTypeError(exception_state,
+ "The type provided is empty");
+ return;
+ }
+
+ // 2. If this object has been removed from the sourceBuffers attribute of the
+ // parent media source, then throw an InvalidStateError exception and abort
+ // these steps.
+ // 3. If the updating attribute equals true, then throw an InvalidStateError
+ // exception and abort these steps.
+ if (ThrowExceptionIfRemovedOrUpdating(IsRemoved(), updating_,
+ exception_state))
+ return;
+
+ // 4. If type contains a MIME type that is not supported or contains a MIME
+ // type that is not supported with the types specified (currently or
+ // previously) of SourceBuffer objects in the sourceBuffers attribute of
+ // the parent media source, then throw a NotSupportedError exception and
+ // abort these steps.
+ ContentType content_type(type);
+ String codecs = content_type.Parameter("codecs");
+ if (!MediaSource::isTypeSupported(type) ||
+ !web_source_buffer_->CanChangeType(content_type.GetType(), codecs)) {
+ MediaSource::LogAndThrowDOMException(
+ exception_state, DOMExceptionCode::kNotSupportedError,
+ "Changing to the type provided ('" + type + "') is not supported.");
+ return;
+ }
+
+ // 5. If the readyState attribute of the parent media source is in the "ended"
+ // state then run the following steps:
+ // 1. Set the readyState attribute of the parent media source to "open"
+ // 2. Queue a task to fire a simple event named sourceopen at the parent
+ // media source.
+ source_->OpenIfInEndedState();
+
+ // 6. Run the reset parser state algorithm.
+ web_source_buffer_->ResetParserState();
+
+ // 7. Update the generate timestamps flag on this SourceBuffer object to the
+ // value in the "Generate Timestamps Flag" column of the byte stream format
+ // registry entry that is associated with type.
+ // This call also updates the pipeline to switch bytestream parser and codecs.
+ web_source_buffer_->ChangeType(content_type.GetType(), codecs);
+
+ // 8. If the generate timestamps flag equals true: Set the mode attribute on
+ // this SourceBuffer object to "sequence", including running the associated
+ // steps for that attribute being set. Otherwise: keep the previous value
+ // of the mode attribute on this SourceBuffer object, without running any
+ // associated steps for that attribute being set.
+ if (web_source_buffer_->GetGenerateTimestampsFlag())
+ setMode(SequenceKeyword(), exception_state);
+
+ // 9. Set pending initialization segment for changeType flag to true.
+ // The logic for this flag is handled by the pipeline (the new bytestream
+ // parser will expect an initialization segment first).
+}
+
void SourceBuffer::setTrackDefaults(TrackDefaultList* track_defaults,
ExceptionState& exception_state) {
// Per 02 Dec 2014 Editor's Draft
@@ -1131,7 +1214,7 @@ bool SourceBuffer::PrepareAppend(double media_time,
DCHECK(source_->MediaElement());
if (source_->MediaElement()->error()) {
MediaSource::LogAndThrowDOMException(
- exception_state, kInvalidStateError,
+ exception_state, DOMExceptionCode::kInvalidStateError,
"The HTMLMediaElement.error attribute is not null.");
TRACE_EVENT_ASYNC_END0("media", "SourceBuffer::prepareAppend", this);
return false;
@@ -1150,7 +1233,8 @@ bool SourceBuffer::PrepareAppend(double media_time,
// exception and abort these steps.
BLINK_SBLOG << __func__ << " this=" << this
<< " -> throw QuotaExceededError";
- MediaSource::LogAndThrowDOMException(exception_state, kQuotaExceededError,
+ MediaSource::LogAndThrowDOMException(exception_state,
+ DOMExceptionCode::kQuotaExceededError,
"The SourceBuffer is full, and cannot "
"free space to append additional "
"buffers.");
diff --git a/chromium/third_party/blink/renderer/modules/mediasource/source_buffer.h b/chromium/third_party/blink/renderer/modules/mediasource/source_buffer.h
index bfb345890dd..1e2ec4a9ae2 100644
--- a/chromium/third_party/blink/renderer/modules/mediasource/source_buffer.h
+++ b/chromium/third_party/blink/renderer/modules/mediasource/source_buffer.h
@@ -47,8 +47,8 @@ namespace blink {
class AudioTrackList;
class DOMArrayBuffer;
class DOMArrayBufferView;
+class EventQueue;
class ExceptionState;
-class MediaElementEventQueue;
class MediaSource;
class TimeRanges;
class VideoTrackList;
@@ -65,7 +65,7 @@ class SourceBuffer final : public EventTargetWithInlineData,
public:
static SourceBuffer* Create(std::unique_ptr<WebSourceBuffer>,
MediaSource*,
- MediaElementEventQueue*);
+ EventQueue*);
static const AtomicString& SegmentsKeyword();
static const AtomicString& SequenceKeyword();
@@ -82,6 +82,7 @@ class SourceBuffer final : public EventTargetWithInlineData,
void appendBuffer(NotShared<DOMArrayBufferView> data, ExceptionState&);
void abort(ExceptionState&);
void remove(double start, double end, ExceptionState&);
+ void changeType(const String& type, ExceptionState&);
double appendWindowStart() const;
void setAppendWindowStart(double, ExceptionState&);
double appendWindowEnd() const;
@@ -119,9 +120,7 @@ class SourceBuffer final : public EventTargetWithInlineData,
void Trace(blink::Visitor*) override;
private:
- SourceBuffer(std::unique_ptr<WebSourceBuffer>,
- MediaSource*,
- MediaElementEventQueue*);
+ SourceBuffer(std::unique_ptr<WebSourceBuffer>, MediaSource*, EventQueue*);
void Dispose();
bool IsRemoved() const;
@@ -160,7 +159,7 @@ class SourceBuffer final : public EventTargetWithInlineData,
std::unique_ptr<WebSourceBuffer> web_source_buffer_;
Member<MediaSource> source_;
Member<TrackDefaultList> track_defaults_;
- Member<MediaElementEventQueue> async_event_queue_;
+ Member<EventQueue> async_event_queue_;
AtomicString mode_;
bool updating_;
diff --git a/chromium/third_party/blink/renderer/modules/mediasource/source_buffer.idl b/chromium/third_party/blink/renderer/modules/mediasource/source_buffer.idl
index d6232bbcb1f..5c56ebfc9b4 100644
--- a/chromium/third_party/blink/renderer/modules/mediasource/source_buffer.idl
+++ b/chromium/third_party/blink/renderer/modules/mediasource/source_buffer.idl
@@ -73,6 +73,9 @@ enum AppendMode {
[RaisesException] void abort();
[RaisesException] void remove(double start, unrestricted double end);
+ // Explicitly change the container or codecs
+ [RaisesException, RuntimeEnabled=MediaSourceExperimental] void changeType(DOMString type);
+
// Gets or sets the TrackDefaultList this SourceBuffer may consult during
// the initialization segment algorithm.
[RaisesException=Setter, RuntimeEnabled=MediaSourceExperimental] attribute TrackDefaultList trackDefaults;
diff --git a/chromium/third_party/blink/renderer/modules/mediasource/source_buffer_list.cc b/chromium/third_party/blink/renderer/modules/mediasource/source_buffer_list.cc
index e52c53cf719..7c86cfe167c 100644
--- a/chromium/third_party/blink/renderer/modules/mediasource/source_buffer_list.cc
+++ b/chromium/third_party/blink/renderer/modules/mediasource/source_buffer_list.cc
@@ -30,14 +30,14 @@
#include "third_party/blink/renderer/modules/mediasource/source_buffer_list.h"
-#include "third_party/blink/renderer/core/dom/events/media_element_event_queue.h"
+#include "third_party/blink/renderer/core/dom/events/event_queue.h"
#include "third_party/blink/renderer/modules/event_modules.h"
#include "third_party/blink/renderer/modules/mediasource/source_buffer.h"
namespace blink {
SourceBufferList::SourceBufferList(ExecutionContext* context,
- MediaElementEventQueue* async_event_queue)
+ EventQueue* async_event_queue)
: ContextClient(context), async_event_queue_(async_event_queue) {}
SourceBufferList::~SourceBufferList() = default;
diff --git a/chromium/third_party/blink/renderer/modules/mediasource/source_buffer_list.h b/chromium/third_party/blink/renderer/modules/mediasource/source_buffer_list.h
index ee7d52feb0c..1a5fa6013cb 100644
--- a/chromium/third_party/blink/renderer/modules/mediasource/source_buffer_list.h
+++ b/chromium/third_party/blink/renderer/modules/mediasource/source_buffer_list.h
@@ -37,8 +37,8 @@
namespace blink {
+class EventQueue;
class SourceBuffer;
-class MediaElementEventQueue;
class SourceBufferList final : public EventTargetWithInlineData,
public ContextClient {
@@ -47,7 +47,7 @@ class SourceBufferList final : public EventTargetWithInlineData,
public:
static SourceBufferList* Create(ExecutionContext* context,
- MediaElementEventQueue* async_event_queue) {
+ EventQueue* async_event_queue) {
return new SourceBufferList(context, async_event_queue);
}
~SourceBufferList() override;
@@ -79,11 +79,11 @@ class SourceBufferList final : public EventTargetWithInlineData,
void Trace(blink::Visitor*) override;
private:
- SourceBufferList(ExecutionContext*, MediaElementEventQueue*);
+ SourceBufferList(ExecutionContext*, EventQueue*);
void ScheduleEvent(const AtomicString&);
- Member<MediaElementEventQueue> async_event_queue_;
+ Member<EventQueue> async_event_queue_;
HeapVector<Member<SourceBuffer>> list_;
};
diff --git a/chromium/third_party/blink/renderer/modules/mediasource/track_default.cc b/chromium/third_party/blink/renderer/modules/mediasource/track_default.cc
index 383e4a1909f..a0bf329b7ce 100644
--- a/chromium/third_party/blink/renderer/modules/mediasource/track_default.cc
+++ b/chromium/third_party/blink/renderer/modules/mediasource/track_default.cc
@@ -4,11 +4,11 @@
#include "third_party/blink/renderer/modules/mediasource/track_default.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/core/html/track/audio_track.h"
#include "third_party/blink/renderer/core/html/track/text_track.h"
#include "third_party/blink/renderer/core/html/track/video_track.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/mediasource/track_default_list.cc b/chromium/third_party/blink/renderer/modules/mediasource/track_default_list.cc
index 31100f61642..83979690974 100644
--- a/chromium/third_party/blink/renderer/modules/mediasource/track_default_list.cc
+++ b/chromium/third_party/blink/renderer/modules/mediasource/track_default_list.cc
@@ -4,8 +4,7 @@
#include "third_party/blink/renderer/modules/mediasource/track_default_list.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
@@ -38,9 +37,9 @@ TrackDefaultList* TrackDefaultList::Create(
if (!type_and_id_to_track_default_map.insert(key, track_default)
.is_new_entry) {
exception_state.ThrowDOMException(
- kInvalidAccessError, "Duplicate TrackDefault type (" + key.first +
- ") and byteStreamTrackID (" + key.second +
- ")");
+ DOMExceptionCode::kInvalidAccessError,
+ "Duplicate TrackDefault type (" + key.first +
+ ") and byteStreamTrackID (" + key.second + ")");
return nullptr;
}
}
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_constraints_impl.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_constraints_impl.cc
index 4109bc98aef..dc8304c11cf 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_constraints_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_constraints_impl.cc
@@ -32,11 +32,11 @@
#include "third_party/blink/renderer/bindings/core/v8/array_value.h"
#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/modules/mediastream/media_track_constraints.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.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/hash_map.h"
@@ -340,10 +340,6 @@ static void ParseOldStyleNames(
} else if (constraint.name_.Equals(kGoogExperimentalNoiseSuppression)) {
result.goog_experimental_noise_suppression.SetExact(
ToBoolean(constraint.value_));
- } else if (constraint.name_.Equals(kGoogBeamforming)) {
- result.goog_beamforming.SetExact(ToBoolean(constraint.value_));
- } else if (constraint.name_.Equals(kGoogArrayGeometry)) {
- result.goog_array_geometry.SetExact(constraint.value_);
} else if (constraint.name_.Equals(kGoogHighpassFilter)) {
result.goog_highpass_filter.SetExact(ToBoolean(constraint.value_));
} else if (constraint.name_.Equals(kGoogTypingNoiseDetection)) {
@@ -435,7 +431,11 @@ static void ParseOldStyleNames(
} else if (constraint.name_.Equals(kPowerLineFrequency)) {
result.goog_power_line_frequency.SetExact(
atoi(constraint.value_.Utf8().c_str()));
- } else if (constraint.name_.Equals(kGoogLeakyBucket)) {
+ } else if (constraint.name_.Equals(kGoogLeakyBucket) ||
+ constraint.name_.Equals(kGoogBeamforming) ||
+ constraint.name_.Equals(kGoogArrayGeometry)) {
+ // TODO(crbug.com/856176): Remove the kGoogBeamforming and
+ // kGoogArrayGeometry special cases.
context->AddConsoleMessage(ConsoleMessage::Create(
kDeprecationMessageSource, kWarningMessageLevel,
"Obsolete constraint named " + String(constraint.name_) +
@@ -464,6 +464,7 @@ static void ParseOldStyleNames(
kDeprecationMessageSource, kWarningMessageLevel,
"Unknown constraint named " + String(constraint.name_) +
" rejected"));
+ // TODO(crbug.com/856176): Don't throw an error.
error_state.ThrowConstraintError("Unknown name of constraint detected",
constraint.name_);
}
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_devices.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_devices.cc
index 891c586853c..0d835761e04 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_devices.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_devices.cc
@@ -12,7 +12,6 @@
#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/dom/events/event.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/modules/mediastream/input_device_info.h"
@@ -87,8 +86,8 @@ ScriptPromise MediaDevices::enumerateDevices(ScriptState* script_state) {
ToDocument(ExecutionContext::From(script_state))->GetFrame();
if (!frame) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kNotSupportedError, "Current frame is detached."));
+ script_state, DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "Current frame is detached."));
}
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
@@ -116,7 +115,7 @@ ScriptPromise MediaDevices::getUserMedia(ScriptState* script_state,
if (!user_media)
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kNotSupportedError,
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
"No media device controller available; is this a "
"detached window?"));
@@ -127,7 +126,7 @@ ScriptPromise MediaDevices::getUserMedia(ScriptState* script_state,
DCHECK(error_state.HadException());
if (error_state.CanGenerateException()) {
error_state.RaiseException(exception_state);
- return exception_state.Reject(script_state);
+ return ScriptPromise();
}
ScriptPromise rejected_promise = resolver->Promise();
resolver->Reject(error_state.CreateError());
@@ -137,7 +136,8 @@ ScriptPromise MediaDevices::getUserMedia(ScriptState* script_state,
String error_message;
if (!request->IsSecureContextUse(error_message)) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kNotSupportedError, error_message));
+ script_state, DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ error_message));
}
auto promise = resolver->Promise();
request->Start();
@@ -312,8 +312,8 @@ void MediaDevices::DevicesEnumerated(
void MediaDevices::OnDispatcherHostConnectionError() {
for (ScriptPromiseResolver* resolver : requests_) {
- resolver->Reject(
- DOMException::Create(kAbortError, "enumerateDevices() failed."));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kAbortError,
+ "enumerateDevices() failed."));
}
requests_.clear();
dispatcher_host_.reset();
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_devices_test.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
index eab5ff04036..8752d092203 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_devices_test.cc
@@ -10,11 +10,14 @@
#include "mojo/public/cpp/bindings/binding.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/core/testing/null_execution_context.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_constraints.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
using blink::mojom::blink::MediaDeviceInfoPtr;
using blink::mojom::blink::MediaDeviceType;
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_error_state.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_error_state.cc
index f8a6c98df32..87c1270051e 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_error_state.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_error_state.cc
@@ -30,19 +30,19 @@
#include "third_party/blink/renderer/modules/mediastream/media_error_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/mediastream/overconstrained_error.h"
namespace blink {
-MediaErrorState::MediaErrorState() : error_type_(kNoError), code_(0) {}
+MediaErrorState::MediaErrorState()
+ : error_type_(kNoError), code_(DOMExceptionCode::kNoError) {}
void MediaErrorState::ThrowTypeError(const String& message) {
error_type_ = kTypeError;
message_ = message;
}
-void MediaErrorState::ThrowDOMException(ExceptionCode code,
+void MediaErrorState::ThrowDOMException(DOMExceptionCode code,
const String& message) {
error_type_ = kDOMException;
code_ = code;
@@ -85,7 +85,7 @@ void MediaErrorState::RaiseException(ExceptionState& target) {
// So far, we have this in the constructor of RTCPeerConnection,
// which is due to be deprecated.
// TODO(hta): Remove this code. https://crbug.com/576581
- target.ThrowDOMException(kNotSupportedError,
+ target.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"Unsatisfiable constraint " + constraint_);
break;
default:
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_error_state.h b/chromium/third_party/blink/renderer/modules/mediastream/media_error_state.h
index 9263c977a67..d5282d041c5 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_error_state.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_error_state.h
@@ -31,8 +31,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_ERROR_STATE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_ERROR_STATE_H_
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/modules/v8/dom_exception_or_overconstrained_error.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -45,7 +45,7 @@ class MediaErrorState {
public:
MediaErrorState();
void ThrowTypeError(const String& message);
- void ThrowDOMException(ExceptionCode, const String& message);
+ void ThrowDOMException(DOMExceptionCode, const String& message);
void ThrowConstraintError(const String& message, const String& constraint);
void Reset();
@@ -59,7 +59,7 @@ class MediaErrorState {
enum ErrorType { kNoError, kTypeError, kDOMException, kConstraintError };
ErrorType error_type_;
String name_;
- ExceptionCode code_;
+ DOMExceptionCode code_;
String message_;
String constraint_;
};
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_stream.cc
index 05231fb8f03..99bea50b140 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream.cc
@@ -26,12 +26,11 @@
#include "third_party/blink/renderer/modules/mediastream/media_stream.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.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/modules/mediastream/media_stream_registry.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_track_event.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/mediastream/media_stream_center.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
@@ -253,7 +252,8 @@ void MediaStream::addTrack(MediaStreamTrack* track,
ExceptionState& exception_state) {
if (!track) {
exception_state.ThrowDOMException(
- kTypeMismatchError, "The MediaStreamTrack provided is invalid.");
+ DOMExceptionCode::kTypeMismatchError,
+ "The MediaStreamTrack provided is invalid.");
return;
}
@@ -284,7 +284,8 @@ void MediaStream::removeTrack(MediaStreamTrack* track,
ExceptionState& exception_state) {
if (!track) {
exception_state.ThrowDOMException(
- kTypeMismatchError, "The MediaStreamTrack provided is invalid.");
+ DOMExceptionCode::kTypeMismatchError,
+ "The MediaStreamTrack provided is invalid.");
return;
}
@@ -398,34 +399,18 @@ const AtomicString& MediaStream::InterfaceName() const {
return EventTargetNames::MediaStream;
}
-void MediaStream::AddTrackByComponent(MediaStreamComponent* component) {
+void MediaStream::AddTrackByComponentAndFireEvents(
+ MediaStreamComponent* component) {
DCHECK(component);
if (!GetExecutionContext())
return;
-
MediaStreamTrack* track =
MediaStreamTrack::Create(GetExecutionContext(), component);
- switch (component->Source()->GetType()) {
- case MediaStreamSource::kTypeAudio:
- audio_tracks_.push_back(track);
- break;
- case MediaStreamSource::kTypeVideo:
- video_tracks_.push_back(track);
- break;
- }
- track->RegisterMediaStream(this);
- descriptor_->AddComponent(component);
-
- ScheduleDispatchEvent(
- MediaStreamTrackEvent::Create(EventTypeNames::addtrack, track));
-
- if (!active() && !track->Ended()) {
- descriptor_->SetActive(true);
- ScheduleDispatchEvent(Event::Create(EventTypeNames::active));
- }
+ AddTrackAndFireEvents(track);
}
-void MediaStream::RemoveTrackByComponent(MediaStreamComponent* component) {
+void MediaStream::RemoveTrackByComponentAndFireEvents(
+ MediaStreamComponent* component) {
DCHECK(component);
if (!GetExecutionContext())
return;
@@ -464,6 +449,33 @@ void MediaStream::RemoveTrackByComponent(MediaStreamComponent* component) {
}
}
+void MediaStream::AddTrackAndFireEvents(MediaStreamTrack* track) {
+ DCHECK(track);
+ switch (track->Component()->Source()->GetType()) {
+ case MediaStreamSource::kTypeAudio:
+ audio_tracks_.push_back(track);
+ break;
+ case MediaStreamSource::kTypeVideo:
+ video_tracks_.push_back(track);
+ break;
+ }
+ track->RegisterMediaStream(this);
+ descriptor_->AddComponent(track->Component());
+
+ ScheduleDispatchEvent(
+ MediaStreamTrackEvent::Create(EventTypeNames::addtrack, track));
+
+ if (!active() && !track->Ended()) {
+ descriptor_->SetActive(true);
+ ScheduleDispatchEvent(Event::Create(EventTypeNames::active));
+ }
+}
+
+void MediaStream::RemoveTrackAndFireEvents(MediaStreamTrack* track) {
+ DCHECK(track);
+ RemoveTrackByComponentAndFireEvents(track->Component());
+}
+
void MediaStream::ScheduleDispatchEvent(Event* event) {
scheduled_events_.push_back(event);
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream.h b/chromium/third_party/blink/renderer/modules/mediastream/media_stream.h
index 1d045842438..8b815ef7050 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream.h
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream.h
@@ -82,6 +82,9 @@ class MODULES_EXPORT MediaStream final : public EventTargetWithInlineData,
String id() const { return descriptor_->Id(); }
+ // Adds the track, this may cause "onactive" to fire but it won't cause
+ // "onaddtrack" because the track was added explicitly by the JavaScript
+ // application.
void addTrack(MediaStreamTrack*, ExceptionState&);
void removeTrack(MediaStreamTrack*, ExceptionState&);
MediaStreamTrack* getTrackById(String);
@@ -105,8 +108,16 @@ class MODULES_EXPORT MediaStream final : public EventTargetWithInlineData,
// MediaStreamDescriptorClient implementation
void StreamEnded() override;
- void AddTrackByComponent(MediaStreamComponent*) override;
- void RemoveTrackByComponent(MediaStreamComponent*) override;
+ void AddTrackByComponentAndFireEvents(MediaStreamComponent*) override;
+ void RemoveTrackByComponentAndFireEvents(MediaStreamComponent*) override;
+
+ // Adds the track and, unlike JavaScript-invoked addTrack(), fires related
+ // events like "onaddtrack".
+ void AddTrackAndFireEvents(MediaStreamTrack*);
+ void RemoveTrackAndFireEvents(MediaStreamTrack*);
+
+ void AddRemoteTrack(MediaStreamTrack*);
+ void RemoveRemoteTrack(MediaStreamTrack*);
MediaStreamDescriptor* Descriptor() const { return descriptor_; }
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_track.cc b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_track.cc
index 35c6ccf778f..3f8ac81c741 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_stream_track.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_stream_track.cc
@@ -26,13 +26,12 @@
#include "third_party/blink/renderer/modules/mediastream/media_stream_track.h"
#include <memory>
+
#include "third_party/blink/public/platform/web_media_stream_track.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/dom/events/event.h"
-#include "third_party/blink/renderer/core/dom/exception_code.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/core/origin_trials/origin_trials.h"
@@ -59,6 +58,7 @@ static const char kContentHintStringAudioSpeech[] = "speech";
static const char kContentHintStringAudioMusic[] = "music";
static const char kContentHintStringVideoMotion[] = "motion";
static const char kContentHintStringVideoDetail[] = "detail";
+static const char kContentHintStringVideoText[] = "text";
// The set of constrainable properties for image capture is available at
// https://w3c.github.io/mediacapture-image/#constrainable-properties
@@ -225,6 +225,8 @@ String MediaStreamTrack::ContentHint() const {
return kContentHintStringVideoMotion;
case WebMediaStreamTrack::ContentHintType::kVideoDetail:
return kContentHintStringVideoDetail;
+ case WebMediaStreamTrack::ContentHintType::kVideoText:
+ return kContentHintStringVideoText;
}
NOTREACHED();
@@ -256,6 +258,8 @@ void MediaStreamTrack::SetContentHint(const String& hint) {
translated_hint = WebMediaStreamTrack::ContentHintType::kVideoMotion;
} else if (hint == kContentHintStringVideoDetail) {
translated_hint = WebMediaStreamTrack::ContentHintType::kVideoDetail;
+ } else if (hint == kContentHintStringVideoText) {
+ translated_hint = WebMediaStreamTrack::ContentHintType::kVideoText;
} else {
// TODO(pbos): Log warning?
// Invalid values for video are to be ignored (similar to invalid enum
@@ -470,12 +474,23 @@ void MediaStreamTrack::getSettings(MediaTrackSettings& settings) {
settings.setAutoGainControl(*platform_settings.auto_gain_control);
if (platform_settings.noise_supression)
settings.setNoiseSuppression(*platform_settings.noise_supression);
- if (OriginTrials::experimentalHardwareEchoCancellationEnabled(
+ if (OriginTrials::ExperimentalHardwareEchoCancellationEnabled(
GetExecutionContext()) &&
!platform_settings.echo_cancellation_type.IsNull()) {
settings.setEchoCancellationType(platform_settings.echo_cancellation_type);
}
+ if (platform_settings.HasSampleRate())
+ settings.setSampleRate(platform_settings.sample_rate);
+ if (platform_settings.HasSampleSize())
+ settings.setSampleSize(platform_settings.sample_size);
+ if (platform_settings.HasChannelCount())
+ settings.setChannelCount(platform_settings.channel_count);
+ if (platform_settings.HasLatency())
+ settings.setLatency(platform_settings.latency);
+ if (platform_settings.HasVolume())
+ settings.setVolume(platform_settings.volume);
+
if (image_capture_)
image_capture_->GetMediaTrackSettings(settings);
}
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/media_track_settings.idl b/chromium/third_party/blink/renderer/modules/mediastream/media_track_settings.idl
index 2feca7cf03f..20d06f4e29c 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/media_track_settings.idl
+++ b/chromium/third_party/blink/renderer/modules/mediastream/media_track_settings.idl
@@ -10,19 +10,17 @@ dictionary MediaTrackSettings {
double aspectRatio;
double frameRate;
DOMString facingMode;
- // volume, sampleRate and sampleSize are not implemented.
- // double volume;
- // long sampleRate;
- // long sampleSize;
+ double volume;
+ long sampleRate;
+ long sampleSize;
boolean echoCancellation;
boolean autoGainControl;
boolean noiseSuppression;
- [OriginTrialEnabled=ExperimentalHardwareEchoCancellation] DOMString echoCancellationType;
- // latency and channelCount are not implemented.
- // double latency;
- // long channelCount;
+ double latency;
+ long channelCount;
DOMString deviceId;
DOMString groupId;
+ [OriginTrialEnabled=ExperimentalHardwareEchoCancellation] DOMString echoCancellationType;
// Media Capture Depth Stream Extensions
// https://w3c.github.io/mediacapture-depth/#mediatracksettings-dictionary
// TODO(aleksandar.stojiljkovic): videoKind, depthNear, depthFar,
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/navigator_media_stream.cc b/chromium/third_party/blink/renderer/modules/mediastream/navigator_media_stream.cc
index c1243d7b1cc..542b64aaf80 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/navigator_media_stream.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/navigator_media_stream.cc
@@ -24,11 +24,9 @@
#include "third_party/blink/renderer/modules/mediastream/navigator_media_stream.h"
#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_navigator_user_media_error_callback.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_navigator_user_media_success_callback.h"
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/navigator.h"
#include "third_party/blink/renderer/core/frame/settings.h"
@@ -37,6 +35,7 @@
#include "third_party/blink/renderer/modules/mediastream/media_stream_constraints.h"
#include "third_party/blink/renderer/modules/mediastream/user_media_controller.h"
#include "third_party/blink/renderer/modules/mediastream/user_media_request.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -53,7 +52,7 @@ void NavigatorMediaStream::getUserMedia(
UserMediaController::From(navigator.GetFrame());
if (!user_media) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"No user media controller available; is this a detached window?");
return;
}
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/user_media_client.cc b/chromium/third_party/blink/renderer/modules/mediastream/user_media_client.cc
index 3582c0b1b09..2d824337fd0 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/user_media_client.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/user_media_client.cc
@@ -32,7 +32,7 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/web/web_apply_constraints_request.h"
-#include "third_party/blink/public/web/web_frame_client.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/public/web/web_user_media_client.h"
#include "third_party/blink/public/web/web_user_media_request.h"
#include "third_party/blink/renderer/modules/mediastream/apply_constraints_request.h"
diff --git a/chromium/third_party/blink/renderer/modules/mediastream/user_media_request.cc b/chromium/third_party/blink/renderer/modules/mediastream/user_media_request.cc
index b10ae1670af..71c2aa70a0d 100644
--- a/chromium/third_party/blink/renderer/modules/mediastream/user_media_request.cc
+++ b/chromium/third_party/blink/renderer/modules/mediastream/user_media_request.cc
@@ -35,11 +35,8 @@
#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/dom/exception_code.h"
#include "third_party/blink/renderer/core/dom/space_split_string.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/core/frame/hosts_using_features.h"
@@ -50,6 +47,7 @@
#include "third_party/blink/renderer/modules/mediastream/media_track_constraints.h"
#include "third_party/blink/renderer/modules/mediastream/overconstrained_error.h"
#include "third_party/blink/renderer/modules/mediastream/user_media_controller.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_center.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h"
@@ -108,7 +106,7 @@ class FeatureCounter {
WTF_MAKE_NONCOPYABLE(FeatureCounter);
public:
- FeatureCounter(ExecutionContext* context)
+ explicit FeatureCounter(ExecutionContext* context)
: context_(context), is_unconstrained_(true) {}
void Count(WebFeature feature) {
UseCounter::Count(context_, feature);
@@ -209,14 +207,6 @@ void CountAudioConstraintUses(ExecutionContext* context,
WebFeature::kMediaStreamConstraintsGoogExperimentalNoiseSuppression);
}
if (RequestUsesDiscreteConstraint(
- constraints, &WebMediaTrackConstraintSet::goog_beamforming)) {
- counter.Count(WebFeature::kMediaStreamConstraintsGoogBeamforming);
- }
- if (RequestUsesDiscreteConstraint(
- constraints, &WebMediaTrackConstraintSet::goog_array_geometry)) {
- counter.Count(WebFeature::kMediaStreamConstraintsGoogArrayGeometry);
- }
- if (RequestUsesDiscreteConstraint(
constraints, &WebMediaTrackConstraintSet::goog_audio_mirroring)) {
counter.Count(WebFeature::kMediaStreamConstraintsGoogAudioMirroring);
}
@@ -426,14 +416,14 @@ UserMediaRequest::UserMediaRequest(ExecutionContext* context,
audio_(audio),
video_(video),
should_disable_hardware_noise_suppression_(
- OriginTrials::disableHardwareNoiseSuppressionEnabled(context)),
+ OriginTrials::DisableHardwareNoiseSuppressionEnabled(context)),
controller_(controller),
callbacks_(callbacks) {
if (should_disable_hardware_noise_suppression_) {
UseCounter::Count(context,
WebFeature::kUserMediaDisableHardwareNoiseSuppression);
}
- if (OriginTrials::experimentalHardwareEchoCancellationEnabled(context)) {
+ if (OriginTrials::ExperimentalHardwareEchoCancellationEnabled(context)) {
UseCounter::Count(
context,
WebFeature::kUserMediaEnableExperimentalHardwareEchoCancellation);
@@ -565,38 +555,38 @@ void UserMediaRequest::Fail(WebUserMediaRequest::Error name,
if (!GetExecutionContext())
return;
- ExceptionCode ec = kNotSupportedError;
+ DOMExceptionCode exception_code = DOMExceptionCode::kNotSupportedError;
switch (name) {
case WebUserMediaRequest::Error::kPermissionDenied:
case WebUserMediaRequest::Error::kPermissionDismissed:
case WebUserMediaRequest::Error::kInvalidState:
case WebUserMediaRequest::Error::kFailedDueToShutdown:
case WebUserMediaRequest::Error::kKillSwitchOn:
- ec = kNotAllowedError;
+ exception_code = DOMExceptionCode::kNotAllowedError;
break;
case WebUserMediaRequest::Error::kDevicesNotFound:
- ec = kNotFoundError;
+ exception_code = DOMExceptionCode::kNotFoundError;
break;
case WebUserMediaRequest::Error::kTabCapture:
case WebUserMediaRequest::Error::kScreenCapture:
case WebUserMediaRequest::Error::kCapture:
- ec = kAbortError;
+ exception_code = DOMExceptionCode::kAbortError;
break;
case WebUserMediaRequest::Error::kTrackStart:
- ec = kNotReadableError;
+ exception_code = DOMExceptionCode::kNotReadableError;
break;
case WebUserMediaRequest::Error::kNotSupported:
- ec = kNotSupportedError;
+ exception_code = DOMExceptionCode::kNotSupportedError;
break;
case WebUserMediaRequest::Error::kSecurityError:
- ec = kSecurityError;
+ exception_code = DOMExceptionCode::kSecurityError;
break;
default:
NOTREACHED();
}
callbacks_->OnError(nullptr,
DOMExceptionOrOverconstrainedError::FromDOMException(
- DOMException::Create(ec, message)));
+ DOMException::Create(exception_code, message)));
}
void UserMediaRequest::ContextDestroyed(ExecutionContext*) {
diff --git a/chromium/third_party/blink/renderer/modules/modules_export.h b/chromium/third_party/blink/renderer/modules/modules_export.h
index 0bc87cd8a87..922794bdaf3 100644
--- a/chromium/third_party/blink/renderer/modules/modules_export.h
+++ b/chromium/third_party/blink/renderer/modules/modules_export.h
@@ -42,31 +42,4 @@
#endif // !defined(COMPONENT_BUILD)
-//
-// MODULES_TEMPLATE_CLASS_EXPORT
-// MODULES_EXTERN_TEMPLATE_EXPORT
-// MODULES_TEMPLATE_EXPORT
-//
-#if BLINK_MODULES_IMPLEMENTATION
-
-#if defined(COMPILER_MSVC)
-#define MODULES_TEMPLATE_CLASS_EXPORT
-#define MODULES_EXTERN_TEMPLATE_EXPORT MODULES_EXPORT
-#define MODULES_TEMPLATE_EXPORT MODULES_EXPORT
-#endif
-
-#if defined(COMPILER_GCC)
-#define MODULES_TEMPLATE_CLASS_EXPORT MODULES_EXPORT
-#define MODULES_EXTERN_TEMPLATE_EXPORT MODULES_EXPORT
-#define MODULES_TEMPLATE_EXPORT
-#endif
-
-#else // BLINK_MODULES_IMPLEMENTATION
-
-#define MODULES_TEMPLATE_CLASS_EXPORT
-#define MODULES_EXTERN_TEMPLATE_EXPORT MODULES_EXPORT
-#define MODULES_TEMPLATE_EXPORT
-
-#endif // BLINK_MODULES_IMPLEMENTATION
-
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MODULES_EXPORT_H_
diff --git a/chromium/third_party/blink/renderer/modules/modules_idl_files.gni b/chromium/third_party/blink/renderer/modules/modules_idl_files.gni
index e20c9263704..4531e3f0d32 100644
--- a/chromium/third_party/blink/renderer/modules/modules_idl_files.gni
+++ b/chromium/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -3,6 +3,7 @@
# found in the LICENSE file.
import("//third_party/blink/renderer/bindings/bindings.gni")
+import("//third_party/blink/renderer/config.gni")
# The paths in this file are absolute since this file is imported and the
# file lists must be valid from multple "current directories".
@@ -225,6 +226,7 @@ modules_idl_files =
"peerconnection/rtc_rtp_contributing_source.idl",
"peerconnection/rtc_rtp_receiver.idl",
"peerconnection/rtc_rtp_sender.idl",
+ "peerconnection/rtc_rtp_transceiver.idl",
"peerconnection/rtc_session_description.idl",
"peerconnection/rtc_stats_report.idl",
"peerconnection/rtc_stats_response.idl",
@@ -265,18 +267,18 @@ modules_idl_files =
"sensor/relative_orientation_sensor.idl",
"sensor/sensor.idl",
"sensor/sensor_error_event.idl",
- "serviceworkers/client.idl",
- "serviceworkers/clients.idl",
- "serviceworkers/extendable_event.idl",
- "serviceworkers/extendable_message_event.idl",
- "serviceworkers/fetch_event.idl",
- "serviceworkers/install_event.idl",
- "serviceworkers/navigation_preload_manager.idl",
- "serviceworkers/service_worker.idl",
- "serviceworkers/service_worker_container.idl",
- "serviceworkers/service_worker_global_scope.idl",
- "serviceworkers/service_worker_registration.idl",
- "serviceworkers/window_client.idl",
+ "service_worker/client.idl",
+ "service_worker/clients.idl",
+ "service_worker/extendable_event.idl",
+ "service_worker/extendable_message_event.idl",
+ "service_worker/fetch_event.idl",
+ "service_worker/install_event.idl",
+ "service_worker/navigation_preload_manager.idl",
+ "service_worker/service_worker.idl",
+ "service_worker/service_worker_container.idl",
+ "service_worker/service_worker_global_scope.idl",
+ "service_worker/service_worker_registration.idl",
+ "service_worker/window_client.idl",
"shapedetection/barcode_detector.idl",
"shapedetection/detected_barcode.idl",
"shapedetection/detected_face.idl",
@@ -397,6 +399,9 @@ modules_idl_files =
"webgl/webgl_uniform_location.idl",
"webgl/webgl_vertex_array_object.idl",
"webgl/webgl_vertex_array_object_oes.idl",
+ "webgpu/webgpu.idl",
+ "webgpu/webgpu_adapter.idl",
+ "webgpu/webgpu_device.idl",
"webmidi/midi_access.idl",
"webmidi/midi_connection_event.idl",
"webmidi/midi_input.idl",
@@ -424,13 +429,15 @@ modules_idl_files =
"xr/xr_coordinate_system.idl",
"xr/xr_device.idl",
"xr/xr_device_pose.idl",
+ "xr/xr_frame.idl",
"xr/xr_frame_of_reference.idl",
+ "xr/xr_hit_result.idl",
"xr/xr_input_pose.idl",
"xr/xr_input_source.idl",
"xr/xr_input_source_event.idl",
"xr/xr_layer.idl",
"xr/xr_presentation_context.idl",
- "xr/xr_presentation_frame.idl",
+ "xr/xr_ray.idl",
"xr/xr_session.idl",
"xr/xr_session_event.idl",
"xr/xr_stage_bounds.idl",
@@ -441,6 +448,11 @@ modules_idl_files =
],
"abspath")
+if (support_webgl2_compute_context) {
+ modules_idl_files +=
+ get_path_info([ "webgl/webgl2_compute_rendering_context.idl" ], "abspath")
+}
+
modules_callback_function_idl_files =
get_path_info([
"xr/xr_frame_request_callback.idl",
@@ -459,7 +471,6 @@ modules_dictionary_idl_files =
"background_fetch/background_fetch_options.idl",
"background_fetch/background_fetch_settled_event_init.idl",
"background_fetch/background_fetched_event_init.idl",
- "background_fetch/icon_definition.idl",
"background_sync/sync_event_init.idl",
"bluetooth/bluetooth_le_scan_filter_init.idl",
"bluetooth/request_device_options.idl",
@@ -469,8 +480,10 @@ modules_dictionary_idl_files =
"canvas/htmlcanvas/canvas_context_creation_attributes_module.idl",
"cookie_store/cookie_change_event_init.idl",
"cookie_store/cookie_list_item.idl",
+ "cookie_store/cookie_store_delete_options.idl",
"cookie_store/cookie_store_get_options.idl",
"cookie_store/cookie_store_set_options.idl",
+ "cookie_store/cookie_store_set_extra_options.idl",
"cookie_store/extendable_cookie_change_event_init.idl",
"credentialmanager/authentication_extensions_client_inputs.idl",
"credentialmanager/authentication_extensions_client_outputs.idl",
@@ -518,6 +531,7 @@ modules_dictionary_idl_files =
"locks/lock_info.idl",
"locks/lock_manager_snapshot.idl",
"locks/lock_options.idl",
+ "manifest/image_resource.idl",
"media_capabilities/audio_configuration.idl",
"media_capabilities/media_configuration.idl",
"media_capabilities/media_decoding_configuration.idl",
@@ -549,11 +563,13 @@ modules_dictionary_idl_files =
"notifications/notification_action.idl",
"notifications/notification_event_init.idl",
"notifications/notification_options.idl",
+ "payments/address_errors.idl",
"payments/android_pay_method_data.idl",
"payments/android_pay_tokenization.idl",
"payments/basic_card_request.idl",
"payments/can_make_payment_event_init.idl",
"payments/image_object.idl",
+ "payments/payer_error_fields.idl",
"payments/payment_handler_response.idl",
"payments/payment_request_event_init.idl",
"payments/payment_currency_amount.idl",
@@ -567,6 +583,7 @@ modules_dictionary_idl_files =
"payments/payment_instrument.idl",
"payments/payment_request_update_event_init.idl",
"payments/payment_shipping_option.idl",
+ "payments/payment_validation_errors.idl",
"peerconnection/rtc_answer_options.idl",
"peerconnection/rtc_configuration.idl",
"peerconnection/rtc_data_channel_event_init.idl",
@@ -578,9 +595,17 @@ modules_dictionary_idl_files =
"peerconnection/rtc_offer_answer_options.idl",
"peerconnection/rtc_offer_options.idl",
"peerconnection/rtc_peer_connection_ice_event_init.idl",
+ "peerconnection/rtc_rtcp_parameters.idl",
+ "peerconnection/rtc_rtp_capabilities.idl",
+ "peerconnection/rtc_rtp_codec_capability.idl",
"peerconnection/rtc_rtp_codec_parameters.idl",
+ "peerconnection/rtc_rtp_coding_parameters.idl",
"peerconnection/rtc_rtp_encoding_parameters.idl",
+ "peerconnection/rtc_rtp_header_extension_capability.idl",
+ "peerconnection/rtc_rtp_header_extension_parameters.idl",
"peerconnection/rtc_rtp_parameters.idl",
+ "peerconnection/rtc_rtp_transceiver_init.idl",
+ "peerconnection/rtc_rtp_send_parameters.idl",
"peerconnection/rtc_session_description_init.idl",
"peerconnection/rtc_track_event_init.idl",
"permissions/clipboard_permission_descriptor.idl",
@@ -595,12 +620,12 @@ modules_dictionary_idl_files =
"sensor/sensor_error_event_init.idl",
"sensor/sensor_options.idl",
"sensor/spatial_sensor_options.idl",
- "serviceworkers/client_query_options.idl",
- "serviceworkers/extendable_event_init.idl",
- "serviceworkers/extendable_message_event_init.idl",
- "serviceworkers/fetch_event_init.idl",
- "serviceworkers/navigation_preload_state.idl",
- "serviceworkers/registration_options.idl",
+ "service_worker/client_query_options.idl",
+ "service_worker/extendable_event_init.idl",
+ "service_worker/extendable_message_event_init.idl",
+ "service_worker/fetch_event_init.idl",
+ "service_worker/navigation_preload_state.idl",
+ "service_worker/registration_options.idl",
"shapedetection/face_detector_options.idl",
"shapedetection/landmark.idl",
"speech/speech_recognition_error_init.idl",
@@ -638,6 +663,7 @@ modules_dictionary_idl_files =
"webaudio/wave_shaper_options.idl",
"webgl/webgl_context_attributes.idl",
"webgl/webgl_context_event_init.idl",
+ "webgpu/webgpu_adapter_descriptor.idl",
"webmidi/midi_connection_event_init.idl",
"webmidi/midi_message_event_init.idl",
"webmidi/midi_options.idl",
@@ -659,7 +685,7 @@ modules_dictionary_idl_files =
modules_dependency_idl_files =
get_path_info(
[
- "animationworklet/window_animation_worklet.idl",
+ "animationworklet/css_animation_worklet.idl",
"app_banner/window_installation.idl",
"audio_output_devices/html_media_element_audio_output_device.idl",
"background_fetch/service_worker_global_scope_background_fetch.idl",
@@ -673,7 +699,6 @@ modules_dependency_idl_files =
"budget/worker_navigator_budget.idl",
"cache_storage/window_cache_storage.idl",
"cache_storage/worker_cache_storage.idl",
- "canvas/htmlcanvas/html_canvas_element_module.idl",
"canvas/canvas2d/canvas_path.idl",
"clipboard/navigator_clipboard.idl",
"cookie_store/service_worker_global_scope_cookie_store.idl",
@@ -722,7 +747,6 @@ modules_dependency_idl_files =
"netinfo/worker_navigator_network_information.idl",
"notifications/service_worker_global_scope_notifications.idl",
"notifications/service_worker_registration_notifications.idl",
- "canvas/offscreencanvas/offscreen_canvas_module.idl",
"payments/html_iframe_element_payments.idl",
"payments/payment_app_service_worker_global_scope.idl",
"payments/payment_app_service_worker_registration.idl",
@@ -740,7 +764,7 @@ modules_dependency_idl_files =
"quota/worker_navigator_storage_quota.idl",
"remoteplayback/html_media_element_remote_playback.idl",
"screen_orientation/screen_screen_orientation.idl",
- "serviceworkers/navigator_service_worker.idl",
+ "service_worker/navigator_service_worker.idl",
"speech/window_speech.idl",
"speech/window_speech_synthesis.idl",
"srcobject/html_media_element_src_object.idl",
@@ -751,6 +775,7 @@ modules_dependency_idl_files =
"webdatabase/window_web_database.idl",
"webgl/webgl2_rendering_context_base.idl",
"webgl/webgl_rendering_context_base.idl",
+ "webgpu/window_webgpu.idl",
"webmidi/navigator_web_midi.idl",
"webshare/navigator_share.idl",
"webusb/navigator_usb.idl",
@@ -758,6 +783,24 @@ modules_dependency_idl_files =
],
"abspath")
+if (support_webgl2_compute_context) {
+ modules_dependency_idl_files += get_path_info(
+ [
+ "canvas/htmlcanvas/html_canvas_element_module_support_webgl2_compute.idl",
+ "canvas/offscreencanvas/offscreen_canvas_module_support_webgl2_compute.idl",
+ "webgl/webgl2_compute_rendering_context_base.idl",
+ ],
+ "abspath")
+} else {
+ modules_dependency_idl_files +=
+ get_path_info([
+ "canvas/htmlcanvas/html_canvas_element_module.idl",
+ "canvas/offscreencanvas/offscreen_canvas_module.idl",
+ "webgl/webgl2_compute_rendering_context_base.idl",
+ ],
+ "abspath")
+}
+
modules_testing_dependency_idl_files =
get_path_info(
[
@@ -766,7 +809,7 @@ modules_testing_dependency_idl_files =
"navigatorcontentutils/testing/internals_navigator_content_utils.idl",
"peerconnection/testing/internals_rtc_certificate.idl",
"peerconnection/testing/internals_rtc_peer_connection.idl",
- "serviceworkers/testing/internals_service_worker.idl",
+ "service_worker/testing/internals_service_worker.idl",
"speech/testing/internals_speech_synthesis.idl",
"vibration/testing/internals_vibration.idl",
"webaudio/testing/internals_web_audio.idl",
diff --git a/chromium/third_party/blink/renderer/modules/modules_initializer.cc b/chromium/third_party/blink/renderer/modules/modules_initializer.cc
index b140ed7a61c..690c337d13d 100644
--- a/chromium/third_party/blink/renderer/modules/modules_initializer.cc
+++ b/chromium/third_party/blink/renderer/modules/modules_initializer.cc
@@ -71,8 +71,8 @@
#include "third_party/blink/renderer/modules/remoteplayback/html_media_element_remote_playback.h"
#include "third_party/blink/renderer/modules/remoteplayback/remote_playback.h"
#include "third_party/blink/renderer/modules/screen_orientation/screen_orientation_controller_impl.h"
-#include "third_party/blink/renderer/modules/serviceworkers/navigator_service_worker.h"
-#include "third_party/blink/renderer/modules/speech/speech_recognition_client_proxy.h"
+#include "third_party/blink/renderer/modules/service_worker/navigator_service_worker.h"
+#include "third_party/blink/renderer/modules/speech/speech_recognition_controller.h"
#include "third_party/blink/renderer/modules/storage/dom_window_storage_controller.h"
#include "third_party/blink/renderer/modules/storage/inspector_dom_storage_agent.h"
#include "third_party/blink/renderer/modules/storage/storage_namespace_controller.h"
@@ -83,6 +83,9 @@
#include "third_party/blink/renderer/modules/webdatabase/database_manager.h"
#include "third_party/blink/renderer/modules/webdatabase/inspector_database_agent.h"
#include "third_party/blink/renderer/modules/webdatabase/web_database_impl.h"
+#if defined(SUPPORT_WEBGL2_COMPUTE_CONTEXT)
+#include "third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.h"
+#endif
#include "third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h"
#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context.h"
#include "third_party/blink/renderer/modules/xr/xr_presentation_context.h"
@@ -125,6 +128,10 @@ void ModulesInitializer::Initialize() {
std::make_unique<WebGLRenderingContext::Factory>());
HTMLCanvasElement::RegisterRenderingContextFactory(
std::make_unique<WebGL2RenderingContext::Factory>());
+#if defined(SUPPORT_WEBGL2_COMPUTE_CONTEXT)
+ HTMLCanvasElement::RegisterRenderingContextFactory(
+ std::make_unique<WebGL2ComputeRenderingContext::Factory>());
+#endif
HTMLCanvasElement::RegisterRenderingContextFactory(
std::make_unique<ImageBitmapRenderingContext::Factory>());
HTMLCanvasElement::RegisterRenderingContextFactory(
@@ -137,6 +144,10 @@ void ModulesInitializer::Initialize() {
std::make_unique<WebGLRenderingContext::Factory>());
OffscreenCanvas::RegisterRenderingContextFactory(
std::make_unique<WebGL2RenderingContext::Factory>());
+#if defined(SUPPORT_WEBGL2_COMPUTE_CONTEXT)
+ OffscreenCanvas::RegisterRenderingContextFactory(
+ std::make_unique<WebGL2ComputeRenderingContext::Factory>());
+#endif
}
void ModulesInitializer::InitLocalFrame(LocalFrame& frame) const {
@@ -158,7 +169,7 @@ void ModulesInitializer::InitLocalFrame(LocalFrame& frame) const {
void ModulesInitializer::InstallSupplements(LocalFrame& frame) const {
WebLocalFrameImpl* web_frame = WebLocalFrameImpl::FromFrame(&frame);
- WebFrameClient* client = web_frame->Client();
+ WebLocalFrameClient* client = web_frame->Client();
DCHECK(client);
ProvidePushControllerTo(frame, client->PushClient());
ProvideUserMediaTo(frame, UserMediaClient::Create(client->UserMediaClient()));
@@ -176,8 +187,7 @@ void ModulesInitializer::InstallSupplements(LocalFrame& frame) const {
new AudioOutputDeviceClientImpl(frame));
}
InstalledAppController::ProvideTo(frame, client->GetRelatedAppsFetcher());
- ::blink::ProvideSpeechRecognitionTo(
- frame, SpeechRecognitionClientProxy::Create(client->SpeechRecognizer()));
+ ::blink::ProvideSpeechRecognitionTo(frame);
}
void ModulesInitializer::ProvideLocalFileSystemToWorker(
@@ -229,7 +239,7 @@ void ModulesInitializer::OnClearWindowObjectInMainWorld(
NavigatorGamepad::From(document);
NavigatorServiceWorker::From(document);
DOMWindowStorageController::From(document);
- if (OriginTrials::webVREnabled(document.GetExecutionContext()))
+ if (RuntimeEnabledFeatures::WebVREnabled())
NavigatorVR::From(document);
if (RuntimeEnabledFeatures::PresentationEnabled() &&
settings.GetPresentationReceiver()) {
@@ -240,7 +250,7 @@ void ModulesInitializer::OnClearWindowObjectInMainWorld(
}
std::unique_ptr<WebMediaPlayer> ModulesInitializer::CreateWebMediaPlayer(
- WebFrameClient* web_frame_client,
+ WebLocalFrameClient* web_frame_client,
HTMLMediaElement& html_media_element,
const WebMediaPlayerSource& source,
WebMediaPlayerClient* media_player_client,
diff --git a/chromium/third_party/blink/renderer/modules/modules_initializer.h b/chromium/third_party/blink/renderer/modules/modules_initializer.h
index 3d9ed459114..4a0fea1b936 100644
--- a/chromium/third_party/blink/renderer/modules/modules_initializer.h
+++ b/chromium/third_party/blink/renderer/modules/modules_initializer.h
@@ -34,7 +34,7 @@ class MODULES_EXPORT ModulesInitializer : public CoreInitializer {
InspectedFrames*,
Page*) const override;
std::unique_ptr<WebMediaPlayer> CreateWebMediaPlayer(
- WebFrameClient*,
+ WebLocalFrameClient*,
HTMLMediaElement&,
const WebMediaPlayerSource&,
WebMediaPlayerClient*,
diff --git a/chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.cc b/chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.cc
index f2b77c24b56..587fae6bbbc 100644
--- a/chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.cc
+++ b/chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.cc
@@ -26,10 +26,10 @@
#include "third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.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/use_counter.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -56,7 +56,7 @@ static bool VerifyCustomHandlerURL(const Document& document,
int index = url.Find(kToken);
if (-1 == index) {
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"The url provided ('" + url + "') does not contain '%s'.");
return false;
}
@@ -69,7 +69,7 @@ static bool VerifyCustomHandlerURL(const Document& document,
if (kurl.IsEmpty() || !kurl.IsValid()) {
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"The custom handler URL created by removing '%s' and prepending '" +
document.BaseURL().GetString() + "' is invalid.");
return false;
diff --git a/chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.cc b/chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.cc
index b23ea57a736..dadaead7c8e 100644
--- a/chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.cc
+++ b/chromium/third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils_client.h"
-#include "third_party/blink/public/web/web_frame_client.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
diff --git a/chromium/third_party/blink/renderer/modules/navigatorcontentutils/testing/navigator_content_utils_client_mock.h b/chromium/third_party/blink/renderer/modules/navigatorcontentutils/testing/navigator_content_utils_client_mock.h
index 534eaab73ce..87062c64f2f 100644
--- a/chromium/third_party/blink/renderer/modules/navigatorcontentutils/testing/navigator_content_utils_client_mock.h
+++ b/chromium/third_party/blink/renderer/modules/navigatorcontentutils/testing/navigator_content_utils_client_mock.h
@@ -31,7 +31,7 @@ class NavigatorContentUtilsClientMock final
private:
// TODO(sashab): Make NavigatorContentUtilsClientMock non-virtual and test it
- // using a WebFrameClient mock.
+ // using a WebLocalFrameClient mock.
NavigatorContentUtilsClientMock() : NavigatorContentUtilsClient(nullptr) {}
typedef struct {
diff --git a/chromium/third_party/blink/renderer/modules/netinfo/network_information.cc b/chromium/third_party/blink/renderer/modules/netinfo/network_information.cc
index c348ebee1c3..1e4fd253849 100644
--- a/chromium/third_party/blink/renderer/modules/netinfo/network_information.cc
+++ b/chromium/third_party/blink/renderer/modules/netinfo/network_information.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include "third_party/blink/public/platform/task_type.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/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/settings.h"
@@ -22,9 +23,12 @@ Settings* GetSettings(ExecutionContext* execution_context) {
if (!execution_context)
return nullptr;
- Document* document = ToDocument(execution_context);
- if (!document)
+ if (!execution_context->IsDocument())
return nullptr;
+
+ Document* document = ToDocument(execution_context);
+ // |document| is guaranteed to be non-null since |execution_context| is
+ // non-null.
return document->GetSettings();
}
diff --git a/chromium/third_party/blink/renderer/modules/nfc/navigator_nfc.cc b/chromium/third_party/blink/renderer/modules/nfc/navigator_nfc.cc
index 628ef889fde..8a08fe21fa6 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/navigator_nfc.cc
+++ b/chromium/third_party/blink/renderer/modules/nfc/navigator_nfc.cc
@@ -39,9 +39,4 @@ void NavigatorNFC::Trace(blink::Visitor* visitor) {
Supplement<Navigator>::Trace(visitor);
}
-void NavigatorNFC::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(nfc_);
- Supplement<Navigator>::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/nfc/navigator_nfc.h b/chromium/third_party/blink/renderer/modules/nfc/navigator_nfc.h
index c91cba42c8d..f0bb42b5305 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/navigator_nfc.h
+++ b/chromium/third_party/blink/renderer/modules/nfc/navigator_nfc.h
@@ -27,7 +27,6 @@ class NavigatorNFC final : public GarbageCollected<NavigatorNFC>,
static NFC* nfc(Navigator&);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
explicit NavigatorNFC(Navigator&);
diff --git a/chromium/third_party/blink/renderer/modules/nfc/nfc.cc b/chromium/third_party/blink/renderer/modules/nfc/nfc.cc
index e5e6c06acb3..e86dbe865b6 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/nfc.cc
+++ b/chromium/third_party/blink/renderer/modules/nfc/nfc.cc
@@ -12,7 +12,6 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_string_resource.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/dom/exception_code.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/typed_arrays/dom_array_buffer.h"
@@ -205,8 +204,8 @@ struct TypeConverter<base::Optional<Vector<uint8_t>>, blink::ScriptValue> {
return base::nullopt;
}
- String string = blink::V8StringToWebCoreString<String>(
- jsonString, blink::kDoNotExternalize);
+ String string =
+ blink::ToBlinkString<String>(jsonString, blink::kDoNotExternalize);
return mojo::ConvertTo<Vector<uint8_t>>(string);
}
@@ -373,10 +372,10 @@ ScriptPromise RejectWithTypeError(ScriptState* script_state,
}
ScriptPromise RejectWithDOMException(ScriptState* script_state,
- ExceptionCode ec,
+ DOMExceptionCode exception_code,
const String& message) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(ec, message));
+ script_state, DOMException::Create(exception_code, message));
}
ScriptPromise RejectIfInvalidTextRecord(ScriptState* script_state,
@@ -391,7 +390,7 @@ ScriptPromise RejectIfInvalidTextRecord(ScriptState* script_state,
if (record.hasMediaType() &&
!record.mediaType().StartsWithIgnoringASCIICase(kPlainTextMimePrefix)) {
- return RejectWithDOMException(script_state, kSyntaxError,
+ return RejectWithDOMException(script_state, DOMExceptionCode::kSyntaxError,
"Invalid media type for 'text' record.");
}
@@ -408,7 +407,7 @@ ScriptPromise RejectIfInvalidURLRecord(ScriptState* script_state,
blink::V8StringResource<> string_resource = record.data().V8Value();
if (!string_resource.Prepare() ||
!KURL(NullURL(), string_resource).IsValid()) {
- return RejectWithDOMException(script_state, kSyntaxError,
+ return RejectWithDOMException(script_state, DOMExceptionCode::kSyntaxError,
"Cannot parse data for 'url' record.");
}
@@ -429,7 +428,7 @@ ScriptPromise RejectIfInvalidJSONRecord(ScriptState* script_state,
(record.mediaType() != kJsonMimeType &&
!(record.mediaType().StartsWithIgnoringASCIICase(kJsonMimePrefix) &&
record.mediaType().EndsWithIgnoringASCIICase(kJsonMimePostfix)))) {
- return RejectWithDOMException(script_state, kSyntaxError,
+ return RejectWithDOMException(script_state, DOMExceptionCode::kSyntaxError,
"Invalid media type for 'json' record.");
}
@@ -701,19 +700,20 @@ ScriptPromise NFC::push(ScriptState* script_state,
device::mojom::blink::NFCMessagePtr message =
device::mojom::blink::NFCMessage::From(push_message);
if (!message) {
- return RejectWithDOMException(script_state, kSyntaxError,
+ return RejectWithDOMException(script_state, DOMExceptionCode::kSyntaxError,
"Cannot convert NFCMessage.");
}
if (!SetURL(
ExecutionContext::From(script_state)->GetSecurityOrigin()->ToString(),
message)) {
- return RejectWithDOMException(script_state, kSyntaxError,
+ return RejectWithDOMException(script_state, DOMExceptionCode::kSyntaxError,
"Cannot set WebNFC Id.");
}
if (GetNFCMessageSize(message) > device::mojom::blink::NFCMessage::kMaxSize) {
- return RejectWithDOMException(script_state, kNotSupportedError,
+ return RejectWithDOMException(script_state,
+ DOMExceptionCode::kNotSupportedError,
"NFCMessage exceeds maximum supported size.");
}
@@ -756,7 +756,8 @@ ScriptPromise NFC::watch(ScriptState* script_state,
if (options.hasURL() && !options.url().IsEmpty()) {
KURL pattern_url(options.url());
if (!pattern_url.IsValid() || pattern_url.Protocol() != kProtocolHttps) {
- return RejectWithDOMException(script_state, kSyntaxError,
+ return RejectWithDOMException(script_state,
+ DOMExceptionCode::kSyntaxError,
"Invalid URL pattern was provided.");
}
}
@@ -781,7 +782,8 @@ ScriptPromise NFC::cancelWatch(ScriptState* script_state, long id) {
if (id) {
callbacks_.erase(id);
} else {
- return RejectWithDOMException(script_state, kNotFoundError,
+ return RejectWithDOMException(script_state,
+ DOMExceptionCode::kNotFoundError,
"Provided watch id cannot be found.");
}
@@ -882,11 +884,13 @@ ScriptPromise NFC::RejectIfNotSupported(ScriptState* script_state) {
String error_message;
if (!IsSupportedInContext(ExecutionContext::From(script_state),
error_message)) {
- return RejectWithDOMException(script_state, kSecurityError, error_message);
+ return RejectWithDOMException(
+ script_state, DOMExceptionCode::kSecurityError, error_message);
}
if (!nfc_) {
- return RejectWithDOMException(script_state, kNotSupportedError,
+ return RejectWithDOMException(script_state,
+ DOMExceptionCode::kNotSupportedError,
"WebNFC is not supported.");
}
@@ -926,10 +930,4 @@ void NFC::Trace(blink::Visitor* visitor) {
ContextLifecycleObserver::Trace(visitor);
}
-void NFC::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- for (const auto& callback : callbacks_.Values())
- visitor->TraceWrappers(callback);
- ScriptWrappable::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/nfc/nfc.h b/chromium/third_party/blink/renderer/modules/nfc/nfc.h
index be1a13cef0a..393638048eb 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/nfc.h
+++ b/chromium/third_party/blink/renderer/modules/nfc/nfc.h
@@ -20,6 +20,7 @@ namespace blink {
class NFCPushOptions;
using NFCPushMessage = StringOrArrayBufferOrNFCMessage;
class NFCWatchOptions;
+class ScriptPromiseResolver;
class NFC final : public ScriptWrappable,
public PageVisibilityObserver,
@@ -61,7 +62,6 @@ class NFC final : public ScriptWrappable,
// Interface required by garbage collection.
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
// Returns boolean indicating whether NFC is supported in this context. If
diff --git a/chromium/third_party/blink/renderer/modules/nfc/nfc_error.cc b/chromium/third_party/blink/renderer/modules/nfc/nfc_error.cc
index 19f3e17f478..8f683718a5e 100644
--- a/chromium/third_party/blink/renderer/modules/nfc/nfc_error.cc
+++ b/chromium/third_party/blink/renderer/modules/nfc/nfc_error.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/modules/nfc/nfc_error.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
using device::mojom::blink::NFCErrorType;
@@ -15,32 +14,33 @@ DOMException* NFCError::Take(ScriptPromiseResolver*,
const NFCErrorType& error_type) {
switch (error_type) {
case NFCErrorType::SECURITY:
- return DOMException::Create(kSecurityError, "NFC operation not allowed.");
+ return DOMException::Create(DOMExceptionCode::kSecurityError,
+ "NFC operation not allowed.");
case NFCErrorType::NOT_SUPPORTED:
case NFCErrorType::DEVICE_DISABLED:
- return DOMException::Create(kNotSupportedError,
+ return DOMException::Create(DOMExceptionCode::kNotSupportedError,
"NFC operation not supported.");
case NFCErrorType::NOT_FOUND:
- return DOMException::Create(kNotFoundError,
+ return DOMException::Create(DOMExceptionCode::kNotFoundError,
"Invalid NFC watch Id was provided.");
case NFCErrorType::INVALID_MESSAGE:
- return DOMException::Create(kSyntaxError,
+ return DOMException::Create(DOMExceptionCode::kSyntaxError,
"Invalid NFC message was provided.");
case NFCErrorType::OPERATION_CANCELLED:
- return DOMException::Create(kAbortError,
+ return DOMException::Create(DOMExceptionCode::kAbortError,
"The NFC operation was cancelled.");
case NFCErrorType::TIMER_EXPIRED:
- return DOMException::Create(kTimeoutError,
+ return DOMException::Create(DOMExceptionCode::kTimeoutError,
"NFC operation has timed-out.");
case NFCErrorType::CANNOT_CANCEL:
- return DOMException::Create(kNoModificationAllowedError,
+ return DOMException::Create(DOMExceptionCode::kNoModificationAllowedError,
"NFC operation cannot be canceled.");
case NFCErrorType::IO_ERROR:
- return DOMException::Create(kNetworkError,
+ return DOMException::Create(DOMExceptionCode::kNetworkError,
"NFC data transfer error has occurred.");
}
NOTREACHED();
- return DOMException::Create(kUnknownError,
+ return DOMException::Create(DOMExceptionCode::kUnknownError,
"An unknown NFC error has occurred.");
}
diff --git a/chromium/third_party/blink/renderer/modules/notifications/DEPS b/chromium/third_party/blink/renderer/modules/notifications/DEPS
index b0ecf2d1e4c..4d7ba796554 100644
--- a/chromium/third_party/blink/renderer/modules/notifications/DEPS
+++ b/chromium/third_party/blink/renderer/modules/notifications/DEPS
@@ -8,6 +8,6 @@ include_rules = [
"+third_party/blink/renderer/modules/modules_export.h",
"+third_party/blink/renderer/modules/notifications",
"+third_party/blink/renderer/modules/permissions",
- "+third_party/blink/renderer/modules/serviceworkers",
+ "+third_party/blink/renderer/modules/service_worker",
"+third_party/blink/renderer/modules/vibration",
]
diff --git a/chromium/third_party/blink/renderer/modules/notifications/notification.cc b/chromium/third_party/blink/renderer/modules/notifications/notification.cc
index 52338c5a603..7dc85efa933 100644
--- a/chromium/third_party/blink/renderer/modules/notifications/notification.cc
+++ b/chromium/third_party/blink/renderer/modules/notifications/notification.cc
@@ -34,7 +34,6 @@
#include "third_party/blink/public/platform/modules/notifications/web_notification_action.h"
#include "third_party/blink/public/platform/modules/notifications/web_notification_constants.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_factory.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_notification_action.h"
@@ -53,6 +52,7 @@
#include "third_party/blink/renderer/modules/notifications/notification_manager.h"
#include "third_party/blink/renderer/modules/notifications/notification_options.h"
#include "third_party/blink/renderer/modules/notifications/notification_resources_loader.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/resource_coordinator/frame_resource_coordinator.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -228,7 +228,7 @@ void Notification::OnShow() {
DispatchEvent(Event::Create(EventTypeNames::show));
}
-void Notification::OnClick() {
+void Notification::OnClick(OnClickCallback completed_closure) {
ExecutionContext* context = GetExecutionContext();
Document* document = context->IsDocument() ? ToDocument(context) : nullptr;
std::unique_ptr<UserGestureIndicator> gesture_indicator =
@@ -236,6 +236,8 @@ void Notification::OnClick() {
UserGestureToken::kNewGesture);
ScopedWindowFocusAllowedIndicator window_focus_allowed(GetExecutionContext());
DispatchEvent(Event::Create(EventTypeNames::click));
+
+ std::move(completed_closure).Run();
}
void Notification::OnClose(OnCloseCallback completed_closure) {
@@ -408,7 +410,7 @@ ScriptPromise Notification::requestPermission(
PerformanceMonitor::ReportGenericViolation(
context, PerformanceMonitor::kDiscouragedAPIUse,
"Only request notification permission in response to a user gesture.",
- 0, nullptr);
+ base::TimeDelta(), nullptr);
}
// Sites cannot request notification permission from insecure contexts.
diff --git a/chromium/third_party/blink/renderer/modules/notifications/notification.h b/chromium/third_party/blink/renderer/modules/notifications/notification.h
index 50f1ddef4f1..879da4f9191 100644
--- a/chromium/third_party/blink/renderer/modules/notifications/notification.h
+++ b/chromium/third_party/blink/renderer/modules/notifications/notification.h
@@ -92,7 +92,7 @@ class MODULES_EXPORT Notification final
// NonPersistentNotificationListener interface.
void OnShow() override;
- void OnClick() override;
+ void OnClick(OnClickCallback completed_closure) override;
void OnClose(OnCloseCallback completed_closure) override;
String title() const;
diff --git a/chromium/third_party/blink/renderer/modules/notifications/notification_data.cc b/chromium/third_party/blink/renderer/modules/notifications/notification_data.cc
index 9e61348baf8..37342635b6a 100644
--- a/chromium/third_party/blink/renderer/modules/notifications/notification_data.cc
+++ b/chromium/third_party/blink/renderer/modules/notifications/notification_data.cc
@@ -5,13 +5,13 @@
#include "third_party/blink/renderer/modules/notifications/notification_data.h"
#include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_factory.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/notifications/notification.h"
#include "third_party/blink/renderer/modules/notifications/notification_options.h"
#include "third_party/blink/renderer/modules/vibration/vibration_controller.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/string_view.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
diff --git a/chromium/third_party/blink/renderer/modules/notifications/notification_data_test.cc b/chromium/third_party/blink/renderer/modules/notifications/notification_data_test.cc
index 224aa5ec25b..f250a34e91a 100644
--- a/chromium/third_party/blink/renderer/modules/notifications/notification_data_test.cc
+++ b/chromium/third_party/blink/renderer/modules/notifications/notification_data_test.cc
@@ -5,10 +5,10 @@
#include "third_party/blink/renderer/modules/notifications/notification_data.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/testing/null_execution_context.h"
#include "third_party/blink/renderer/modules/notifications/notification.h"
#include "third_party/blink/renderer/modules/notifications/notification_options.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.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/time.h"
diff --git a/chromium/third_party/blink/renderer/modules/notifications/notification_event.h b/chromium/third_party/blink/renderer/modules/notifications/notification_event.h
index 0b79eea8da5..309aee02c78 100644
--- a/chromium/third_party/blink/renderer/modules/notifications/notification_event.h
+++ b/chromium/third_party/blink/renderer/modules/notifications/notification_event.h
@@ -8,7 +8,7 @@
#include "third_party/blink/renderer/modules/event_modules.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/notifications/notification.h"
-#include "third_party/blink/renderer/modules/serviceworkers/extendable_event.h"
+#include "third_party/blink/renderer/modules/service_worker/extendable_event.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/notifications/notification_image_loader.cc b/chromium/third_party/blink/renderer/modules/notifications/notification_image_loader.cc
index e1bc73bb010..164d95d543a 100644
--- a/chromium/third_party/blink/renderer/modules/notifications/notification_image_loader.cc
+++ b/chromium/third_party/blink/renderer/modules/notifications/notification_image_loader.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/notifications/notification_image_loader.h"
#include <memory>
+#include "base/numerics/safe_conversions.h"
#include "skia/ext/image_operations.h"
#include "third_party/blink/public/platform/modules/notifications/web_notification_constants.h"
#include "third_party/blink/public/platform/web_url_request.h"
@@ -48,7 +49,7 @@ const unsigned long kImageFetchTimeoutInMs = 90000;
namespace blink {
NotificationImageLoader::NotificationImageLoader(Type type)
- : type_(type), stopped_(false), start_time_(0.0) {}
+ : type_(type), stopped_(false) {}
NotificationImageLoader::~NotificationImageLoader() = default;
@@ -81,15 +82,17 @@ SkBitmap NotificationImageLoader::ScaleDownIfNeeded(const SkBitmap& image,
double scale =
std::min(static_cast<double>(max_width_px) / image.width(),
static_cast<double>(max_height_px) / image.height());
- double start_time = CurrentTimeTicksInMilliseconds();
+ TimeTicks start_time = CurrentTimeTicks();
// TODO(peter): Try using RESIZE_BETTER for large images.
SkBitmap scaled_image =
skia::ImageOperations::Resize(image, skia::ImageOperations::RESIZE_BEST,
std::lround(scale * image.width()),
std::lround(scale * image.height()));
- NOTIFICATION_HISTOGRAM_COUNTS(LoadScaleDownTime, type,
- CurrentTimeTicksInMilliseconds() - start_time,
- 1000 * 10 /* 10 seconds max */);
+ NOTIFICATION_HISTOGRAM_COUNTS(
+ LoadScaleDownTime, type,
+ base::saturated_cast<base::HistogramBase::Sample>(
+ (CurrentTimeTicks() - start_time).InMilliseconds()),
+ 1000 * 10 /* 10 seconds max */);
return scaled_image;
}
return image;
@@ -100,7 +103,7 @@ void NotificationImageLoader::Start(ExecutionContext* context,
ImageCallback image_callback) {
DCHECK(!stopped_);
- start_time_ = CurrentTimeTicksInMilliseconds();
+ start_time_ = CurrentTimeTicks();
image_callback_ = std::move(image_callback);
ThreadableLoaderOptions threadable_loader_options;
@@ -147,17 +150,20 @@ void NotificationImageLoader::DidFinishLoading(
if (stopped_)
return;
- NOTIFICATION_HISTOGRAM_COUNTS(LoadFinishTime, type_,
- CurrentTimeTicksInMilliseconds() - start_time_,
- 1000 * 60 * 60 /* 1 hour max */);
+ NOTIFICATION_HISTOGRAM_COUNTS(
+ LoadFinishTime, type_,
+ base::saturated_cast<base::HistogramBase::Sample>(
+ (CurrentTimeTicks() - start_time_).InMilliseconds()),
+ 1000 * 60 * 60 /* 1 hour max */);
if (data_) {
NOTIFICATION_HISTOGRAM_COUNTS(LoadFileSize, type_, data_->size(),
10000000 /* ~10mb max */);
+ const bool data_complete = true;
std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
- data_, true /* dataComplete */, ImageDecoder::kAlphaPremultiplied,
- ColorBehavior::TransformToSRGB());
+ data_, data_complete, ImageDecoder::kAlphaPremultiplied,
+ ImageDecoder::kDefaultBitDepth, ColorBehavior::TransformToSRGB());
if (decoder) {
// The |ImageFrame*| is owned by the decoder.
ImageFrame* image_frame = decoder->DecodeFrameBufferAtIndex(0);
@@ -171,9 +177,11 @@ void NotificationImageLoader::DidFinishLoading(
}
void NotificationImageLoader::DidFail(const ResourceError& error) {
- NOTIFICATION_HISTOGRAM_COUNTS(LoadFailTime, type_,
- CurrentTimeTicksInMilliseconds() - start_time_,
- 1000 * 60 * 60 /* 1 hour max */);
+ NOTIFICATION_HISTOGRAM_COUNTS(
+ LoadFailTime, type_,
+ base::saturated_cast<base::HistogramBase::Sample>(
+ (CurrentTimeTicks() - start_time_).InMilliseconds()),
+ 1000 * 60 * 60 /* 1 hour max */);
RunCallbackWithEmptyBitmap();
}
diff --git a/chromium/third_party/blink/renderer/modules/notifications/notification_image_loader.h b/chromium/third_party/blink/renderer/modules/notifications/notification_image_loader.h
index 7fbc78ce835..7b40f7de172 100644
--- a/chromium/third_party/blink/renderer/modules/notifications/notification_image_loader.h
+++ b/chromium/third_party/blink/renderer/modules/notifications/notification_image_loader.h
@@ -13,6 +13,7 @@
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
+#include "third_party/blink/renderer/platform/wtf/time.h"
#include "third_party/skia/include/core/SkBitmap.h"
namespace blink {
@@ -65,7 +66,7 @@ class MODULES_EXPORT NotificationImageLoader final
Type type_;
bool stopped_;
- double start_time_;
+ TimeTicks start_time_;
scoped_refptr<SharedBuffer> data_;
ImageCallback image_callback_;
Member<ThreadableLoader> threadable_loader_;
diff --git a/chromium/third_party/blink/renderer/modules/notifications/notification_manager.cc b/chromium/third_party/blink/renderer/modules/notifications/notification_manager.cc
index d14ede826d7..f5656f2aa92 100644
--- a/chromium/third_party/blink/renderer/modules/notifications/notification_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/notifications/notification_manager.cc
@@ -10,9 +10,10 @@
#include "third_party/blink/public/platform/modules/notifications/web_notification_data.h"
#include "third_party/blink/public/platform/modules/permissions/permission.mojom-blink.h"
#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_registration.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_registration.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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_frame.h"
#include "third_party/blink/renderer/modules/notifications/notification.h"
diff --git a/chromium/third_party/blink/renderer/modules/notifications/service_worker_registration_notifications.cc b/chromium/third_party/blink/renderer/modules/notifications/service_worker_registration_notifications.cc
index 4fc5040db55..48055401b08 100644
--- a/chromium/third_party/blink/renderer/modules/notifications/service_worker_registration_notifications.cc
+++ b/chromium/third_party/blink/renderer/modules/notifications/service_worker_registration_notifications.cc
@@ -9,14 +9,14 @@
#include "third_party/blink/public/platform/modules/notifications/web_notification_data.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_security_origin.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/notifications/get_notification_options.h"
#include "third_party/blink/renderer/modules/notifications/notification_data.h"
#include "third_party/blink/renderer/modules/notifications/notification_manager.h"
#include "third_party/blink/renderer/modules/notifications/notification_options.h"
#include "third_party/blink/renderer/modules/notifications/notification_resources_loader.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -39,28 +39,27 @@ ScriptPromise ServiceWorkerRegistrationNotifications::showNotification(
// If context object's active worker is null, reject the promise with a
// TypeError exception.
- if (!registration.active())
- return ScriptPromise::Reject(
- script_state,
- V8ThrowException::CreateTypeError(script_state->GetIsolate(),
- "No active registration available on "
- "the ServiceWorkerRegistration."));
+ if (!registration.active()) {
+ exception_state.ThrowTypeError(
+ "No active registration available on "
+ "the ServiceWorkerRegistration.");
+ return ScriptPromise();
+ }
// If permission for notification's origin is not "granted", reject the
// promise with a TypeError exception, and terminate these substeps.
if (NotificationManager::From(execution_context)->GetPermissionStatus() !=
- mojom::blink::PermissionStatus::GRANTED)
- return ScriptPromise::Reject(
- script_state,
- V8ThrowException::CreateTypeError(
- script_state->GetIsolate(),
- "No notification permission has been granted for this origin."));
+ mojom::blink::PermissionStatus::GRANTED) {
+ exception_state.ThrowTypeError(
+ "No notification permission has been granted for this origin.");
+ return ScriptPromise();
+ }
// Validate the developer-provided options to get the WebNotificationData.
WebNotificationData data = CreateWebNotificationData(
execution_context, title, options, exception_state);
if (exception_state.HadException())
- return exception_state.Reject(script_state);
+ return ScriptPromise();
// Log number of actions developer provided in linear histogram:
// 0 -> underflow bucket,
diff --git a/chromium/third_party/blink/renderer/modules/payments/BUILD.gn b/chromium/third_party/blink/renderer/modules/payments/BUILD.gn
index 516aa725d3d..50bd846f9e7 100644
--- a/chromium/third_party/blink/renderer/modules/payments/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/payments/BUILD.gn
@@ -23,7 +23,6 @@ blink_modules_sources("payments") {
"payment_app_service_worker_global_scope.h",
"payment_app_service_worker_registration.cc",
"payment_app_service_worker_registration.h",
- "payment_completer.h",
"payment_event_data_conversion.cc",
"payment_event_data_conversion.h",
"payment_handler_utils.cc",
@@ -42,6 +41,7 @@ blink_modules_sources("payments") {
"payment_request_update_event.h",
"payment_response.cc",
"payment_response.h",
+ "payment_state_resolver.h",
"payment_updater.h",
"payments_validators.cc",
"payments_validators.h",
diff --git a/chromium/third_party/blink/renderer/modules/payments/abort_payment_event.cc b/chromium/third_party/blink/renderer/modules/payments/abort_payment_event.cc
index 37ece642ed9..bfa812d0166 100644
--- a/chromium/third_party/blink/renderer/modules/payments/abort_payment_event.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/abort_payment_event.cc
@@ -4,13 +4,13 @@
#include "third_party/blink/renderer/modules/payments/abort_payment_event.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/modules/event_modules.h"
-#include "third_party/blink/renderer/modules/serviceworkers/extendable_event_init.h"
-#include "third_party/blink/renderer/modules/serviceworkers/respond_with_observer.h"
-#include "third_party/blink/renderer/modules/serviceworkers/wait_until_observer.h"
+#include "third_party/blink/renderer/modules/service_worker/extendable_event_init.h"
+#include "third_party/blink/renderer/modules/service_worker/respond_with_observer.h"
+#include "third_party/blink/renderer/modules/service_worker/wait_until_observer.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/wtf/text/atomic_string.h"
diff --git a/chromium/third_party/blink/renderer/modules/payments/abort_payment_event.h b/chromium/third_party/blink/renderer/modules/payments/abort_payment_event.h
index 8287982551a..6fc74bf58c3 100644
--- a/chromium/third_party/blink/renderer/modules/payments/abort_payment_event.h
+++ b/chromium/third_party/blink/renderer/modules/payments/abort_payment_event.h
@@ -6,7 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_ABORT_PAYMENT_EVENT_H_
#include "third_party/blink/renderer/modules/event_modules.h"
-#include "third_party/blink/renderer/modules/serviceworkers/extendable_event.h"
+#include "third_party/blink/renderer/modules/service_worker/extendable_event.h"
#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/wtf/noncopyable.h"
diff --git a/chromium/third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.cc b/chromium/third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.cc
index 660b2571f54..b44dae52744 100644
--- a/chromium/third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.cc
@@ -4,13 +4,14 @@
#include "third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.h"
-#include <v8.h>
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/payments/payment_handler_utils.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.h"
-#include "third_party/blink/renderer/modules/serviceworkers/wait_until_observer.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h"
+#include "third_party/blink/renderer/modules/service_worker/wait_until_observer.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "v8/include/v8.h"
namespace blink {
@@ -30,11 +31,13 @@ void AbortPaymentRespondWithObserver::OnResponseRejected(
}
void AbortPaymentRespondWithObserver::OnResponseFulfilled(
- const ScriptValue& value) {
+ const ScriptValue& value,
+ ExceptionState::ContextType context_type,
+ const char* interface_name,
+ const char* property_name) {
DCHECK(GetExecutionContext());
- ExceptionState exception_state(value.GetIsolate(),
- ExceptionState::kUnknownContext,
- "AbortPaymentEvent", "respondWith");
+ ExceptionState exception_state(value.GetIsolate(), context_type,
+ interface_name, property_name);
bool response = ToBoolean(ToIsolate(GetExecutionContext()), value.V8Value(),
exception_state);
if (exception_state.HadException()) {
diff --git a/chromium/third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.h b/chromium/third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.h
index 1c1ec6c01a6..c10eab76034 100644
--- a/chromium/third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.h
+++ b/chromium/third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.h
@@ -7,7 +7,7 @@
#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink.h"
#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/modules/serviceworkers/respond_with_observer.h"
+#include "third_party/blink/renderer/modules/service_worker/respond_with_observer.h"
namespace blink {
@@ -26,7 +26,10 @@ class MODULES_EXPORT AbortPaymentRespondWithObserver final
~AbortPaymentRespondWithObserver() override = default;
void OnResponseRejected(mojom::ServiceWorkerResponseError) override;
- void OnResponseFulfilled(const ScriptValue&) override;
+ void OnResponseFulfilled(const ScriptValue&,
+ ExceptionState::ContextType,
+ const char* interface_name,
+ const char* property_name) override;
void OnNoResponse() override;
void Trace(blink::Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/modules/payments/address_errors.idl b/chromium/third_party/blink/renderer/modules/payments/address_errors.idl
new file mode 100644
index 00000000000..1b0369834ed
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/payments/address_errors.idl
@@ -0,0 +1,20 @@
+// 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.
+
+// https://w3c.github.io/payment-request/#addresserrors-dictionary
+
+dictionary AddressErrors {
+ DOMString addressLine;
+ DOMString city;
+ DOMString country;
+ DOMString dependentLocality;
+ DOMString languageCode;
+ DOMString organization;
+ DOMString phone;
+ DOMString postalCode;
+ DOMString recipient;
+ DOMString region;
+ DOMString regionCode;
+ DOMString sortingCode;
+};
diff --git a/chromium/third_party/blink/renderer/modules/payments/basic_card_helper.cc b/chromium/third_party/blink/renderer/modules/payments/basic_card_helper.cc
index e0a7d1607d2..3d3511afe79 100644
--- a/chromium/third_party/blink/renderer/modules/payments/basic_card_helper.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/basic_card_helper.cc
@@ -84,9 +84,9 @@ void BasicCardHelper::ParseBasiccardData(
}
}
-bool BasicCardHelper::ContainsNetworkNames(const Vector<String>& input) {
+bool BasicCardHelper::IsNetworkName(const String& input) {
for (size_t i = 0; i < arraysize(kBasicCardNetworks); ++i) {
- if (input.Contains(kBasicCardNetworks[i].name)) {
+ if (input == kBasicCardNetworks[i].name) {
return true;
}
}
diff --git a/chromium/third_party/blink/renderer/modules/payments/basic_card_helper.h b/chromium/third_party/blink/renderer/modules/payments/basic_card_helper.h
index 7b65063427b..48d74181632 100644
--- a/chromium/third_party/blink/renderer/modules/payments/basic_card_helper.h
+++ b/chromium/third_party/blink/renderer/modules/payments/basic_card_helper.h
@@ -6,11 +6,13 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_BASIC_CARD_HELPER_H_
#include "third_party/blink/public/platform/modules/payments/payment_request.mojom-blink.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
+class ScriptValue;
+
class BasicCardHelper {
STATIC_ONLY(BasicCardHelper);
@@ -25,8 +27,8 @@ class BasicCardHelper {
Vector<::payments::mojom::blink::BasicCardType>& supported_types_output,
ExceptionState&);
- // Check whether |input| contains 'basic-card' network names.
- static bool ContainsNetworkNames(const Vector<String>& input);
+ // Check whether |input| is 'basic-card' network name.
+ static bool IsNetworkName(const String& input);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/payments/can_make_payment_event.cc b/chromium/third_party/blink/renderer/modules/payments/can_make_payment_event.cc
index b3468af1eed..7d563b26b3c 100644
--- a/chromium/third_party/blink/renderer/modules/payments/can_make_payment_event.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/can_make_payment_event.cc
@@ -8,9 +8,9 @@
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_location.h"
-#include "third_party/blink/renderer/modules/serviceworkers/respond_with_observer.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_window_client_callback.h"
+#include "third_party/blink/renderer/modules/service_worker/respond_with_observer.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_window_client_callback.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -59,7 +59,7 @@ void CanMakePaymentEvent::respondWith(ScriptState* script_state,
ExceptionState& exception_state) {
if (!isTrusted()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Cannot respond with data when the event is not trusted");
return;
}
@@ -85,8 +85,12 @@ CanMakePaymentEvent::CanMakePaymentEvent(
: ExtendableEvent(type, initializer, wait_until_observer),
top_origin_(initializer.topOrigin()),
payment_request_origin_(initializer.paymentRequestOrigin()),
- method_data_(std::move(initializer.methodData())),
- modifiers_(initializer.modifiers()),
+ method_data_(initializer.hasMethodData()
+ ? initializer.methodData()
+ : HeapVector<PaymentMethodData>()),
+ modifiers_(initializer.hasModifiers()
+ ? initializer.modifiers()
+ : HeapVector<PaymentDetailsModifier>()),
observer_(respond_with_observer) {}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/payments/can_make_payment_event.h b/chromium/third_party/blink/renderer/modules/payments/can_make_payment_event.h
index dd3c1b3e0bf..486eb43c666 100644
--- a/chromium/third_party/blink/renderer/modules/payments/can_make_payment_event.h
+++ b/chromium/third_party/blink/renderer/modules/payments/can_make_payment_event.h
@@ -10,7 +10,7 @@
#include "third_party/blink/renderer/modules/payments/can_make_payment_event_init.h"
#include "third_party/blink/renderer/modules/payments/payment_details_modifier.h"
#include "third_party/blink/renderer/modules/payments/payment_method_data.h"
-#include "third_party/blink/renderer/modules/serviceworkers/extendable_event.h"
+#include "third_party/blink/renderer/modules/service_worker/extendable_event.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace WTF {
diff --git a/chromium/third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.cc b/chromium/third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.cc
index 9a69fb78019..60da1171b80 100644
--- a/chromium/third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.cc
@@ -4,13 +4,14 @@
#include "third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.h"
-#include <v8.h>
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/payments/payment_handler_utils.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.h"
-#include "third_party/blink/renderer/modules/serviceworkers/wait_until_observer.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h"
+#include "third_party/blink/renderer/modules/service_worker/wait_until_observer.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "v8/include/v8.h"
namespace blink {
@@ -30,11 +31,13 @@ void CanMakePaymentRespondWithObserver::OnResponseRejected(
}
void CanMakePaymentRespondWithObserver::OnResponseFulfilled(
- const ScriptValue& value) {
+ const ScriptValue& value,
+ ExceptionState::ContextType context_type,
+ const char* interface_name,
+ const char* property_name) {
DCHECK(GetExecutionContext());
- ExceptionState exception_state(value.GetIsolate(),
- ExceptionState::kUnknownContext,
- "PaymentRequestEvent", "respondWith");
+ ExceptionState exception_state(value.GetIsolate(), context_type,
+ interface_name, property_name);
bool response = ToBoolean(ToIsolate(GetExecutionContext()), value.V8Value(),
exception_state);
if (exception_state.HadException()) {
diff --git a/chromium/third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.h b/chromium/third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.h
index d3966b6f7a1..d851af1daee 100644
--- a/chromium/third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.h
+++ b/chromium/third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.h
@@ -7,7 +7,7 @@
#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink.h"
#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/modules/serviceworkers/respond_with_observer.h"
+#include "third_party/blink/renderer/modules/service_worker/respond_with_observer.h"
namespace blink {
@@ -26,7 +26,10 @@ class MODULES_EXPORT CanMakePaymentRespondWithObserver final
~CanMakePaymentRespondWithObserver() override = default;
void OnResponseRejected(mojom::ServiceWorkerResponseError) override;
- void OnResponseFulfilled(const ScriptValue&) override;
+ void OnResponseFulfilled(const ScriptValue&,
+ ExceptionState::ContextType,
+ const char* interface_name,
+ const char* property_name) override;
void OnNoResponse() override;
void Trace(blink::Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/modules/payments/complete_test.cc b/chromium/third_party/blink/renderer/modules/payments/complete_test.cc
index 950a85cb926..052e14ee136 100644
--- a/chromium/third_party/blink/renderer/modules/payments/complete_test.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/complete_test.cc
@@ -23,9 +23,12 @@ TEST(CompleteTest, CannotCallCompleteTwice) {
request->show(scope.GetScriptState());
static_cast<payments::mojom::blink::PaymentRequestClient*>(request)
->OnPaymentResponse(BuildPaymentResponseForTest());
- request->Complete(scope.GetScriptState(), PaymentCompleter::kFail);
+ request->Complete(scope.GetScriptState(),
+ PaymentStateResolver::PaymentComplete::kFail);
- request->Complete(scope.GetScriptState(), PaymentCompleter::kSuccess)
+ request
+ ->Complete(scope.GetScriptState(),
+ PaymentStateResolver::PaymentComplete::kSuccess)
.Then(funcs.ExpectNoCall(), funcs.ExpectCall());
}
@@ -41,7 +44,9 @@ TEST(CompleteTest, ResolveCompletePromiseOnUnknownError) {
static_cast<payments::mojom::blink::PaymentRequestClient*>(request)
->OnPaymentResponse(BuildPaymentResponseForTest());
- request->Complete(scope.GetScriptState(), PaymentCompleter::kSuccess)
+ request
+ ->Complete(scope.GetScriptState(),
+ PaymentStateResolver::PaymentComplete::kSuccess)
.Then(funcs.ExpectCall(), funcs.ExpectNoCall());
static_cast<payments::mojom::blink::PaymentRequestClient*>(request)->OnError(
@@ -60,7 +65,9 @@ TEST(CompleteTest, ResolveCompletePromiseOnUserClosingUI) {
static_cast<payments::mojom::blink::PaymentRequestClient*>(request)
->OnPaymentResponse(BuildPaymentResponseForTest());
- request->Complete(scope.GetScriptState(), PaymentCompleter::kSuccess)
+ request
+ ->Complete(scope.GetScriptState(),
+ PaymentStateResolver::PaymentComplete::kSuccess)
.Then(funcs.ExpectCall(), funcs.ExpectNoCall());
static_cast<payments::mojom::blink::PaymentRequestClient*>(request)->OnError(
@@ -83,7 +90,9 @@ TEST(CompleteTest, RejectCompletePromiseAfterError) {
static_cast<payments::mojom::blink::PaymentRequestClient*>(request)->OnError(
payments::mojom::blink::PaymentErrorReason::USER_CANCEL);
- request->Complete(scope.GetScriptState(), PaymentCompleter::kSuccess)
+ request
+ ->Complete(scope.GetScriptState(),
+ PaymentStateResolver::PaymentComplete::kSuccess)
.Then(funcs.ExpectNoCall(), funcs.ExpectCall());
}
@@ -99,7 +108,9 @@ TEST(CompleteTest, ResolvePromiseOnComplete) {
static_cast<payments::mojom::blink::PaymentRequestClient*>(request)
->OnPaymentResponse(BuildPaymentResponseForTest());
- request->Complete(scope.GetScriptState(), PaymentCompleter::kSuccess)
+ request
+ ->Complete(scope.GetScriptState(),
+ PaymentStateResolver::PaymentComplete::kSuccess)
.Then(funcs.ExpectCall(), funcs.ExpectNoCall());
static_cast<payments::mojom::blink::PaymentRequestClient*>(request)
@@ -120,7 +131,9 @@ TEST(CompleteTest, RejectCompletePromiseOnUpdateDetailsFailure) {
->OnPaymentResponse(BuildPaymentResponseForTest());
String error_message;
- request->Complete(scope.GetScriptState(), PaymentCompleter::kSuccess)
+ request
+ ->Complete(scope.GetScriptState(),
+ PaymentStateResolver::PaymentComplete::kSuccess)
.Then(funcs.ExpectNoCall(), funcs.ExpectCall(&error_message));
request->OnUpdatePaymentDetailsFailure("oops");
@@ -144,7 +157,9 @@ TEST(CompleteTest, RejectCompletePromiseAfterTimeout) {
request->OnCompleteTimeoutForTesting();
String error_message;
- request->Complete(scope.GetScriptState(), PaymentCompleter::kSuccess)
+ request
+ ->Complete(scope.GetScriptState(),
+ PaymentStateResolver::PaymentComplete::kSuccess)
.Then(funcs.ExpectNoCall(), funcs.ExpectCall(&error_message));
v8::MicrotasksScope::PerformCheckpoint(scope.GetScriptState()->GetIsolate());
diff --git a/chromium/third_party/blink/renderer/modules/payments/payer_error_fields.idl b/chromium/third_party/blink/renderer/modules/payments/payer_error_fields.idl
new file mode 100644
index 00000000000..a56a8892749
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/payments/payer_error_fields.idl
@@ -0,0 +1,11 @@
+// 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.
+
+// https://w3c.github.io/payment-request/#payererrorfields-dictionary
+
+dictionary PayerErrorFields {
+ DOMString email;
+ DOMString name;
+ DOMString phone;
+};
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_app_service_worker_registration.cc b/chromium/third_party/blink/renderer/modules/payments/payment_app_service_worker_registration.cc
index a9caf53e8ab..d8a139f0275 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_app_service_worker_registration.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_app_service_worker_registration.cc
@@ -6,7 +6,7 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/modules/payments/payment_manager.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_app_service_worker_registration.h b/chromium/third_party/blink/renderer/modules/payments/payment_app_service_worker_registration.h
index f4c86e9384f..337c715f31b 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_app_service_worker_registration.h
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_app_service_worker_registration.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_PAYMENT_APP_SERVICE_WORKER_REGISTRATION_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_PAYMENT_APP_SERVICE_WORKER_REGISTRATION_H_
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/supplementable.h"
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_completer.h b/chromium/third_party/blink/renderer/modules/payments/payment_completer.h
deleted file mode 100644
index d09b55876d1..00000000000
--- a/chromium/third_party/blink/renderer/modules/payments/payment_completer.h
+++ /dev/null
@@ -1,28 +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_MODULES_PAYMENTS_PAYMENT_COMPLETER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_PAYMENT_COMPLETER_H_
-
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
-
-namespace blink {
-
-class ScriptState;
-
-class MODULES_EXPORT PaymentCompleter : public GarbageCollectedMixin {
- public:
- enum PaymentComplete { kFail, kSuccess, kUnknown };
-
- virtual ScriptPromise Complete(ScriptState*, PaymentComplete result) = 0;
-
- protected:
- virtual ~PaymentCompleter() = default;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_PAYMENT_COMPLETER_H_
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_details_modifier.idl b/chromium/third_party/blink/renderer/modules/payments/payment_details_modifier.idl
index 0da69cefd7c..9eb92085538 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_details_modifier.idl
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_details_modifier.idl
@@ -5,15 +5,7 @@
// https://w3c.github.io/browser-payment-api/#idl-def-paymentdetailsmodifier
dictionary PaymentDetailsModifier {
- // TODO(zino): The supportedMethods's type was changed from
- // sequence<DOMString> to DOMString[1][2]. But we are not sure if we can
- // remove them now. So, we will define it as union type of DOMString and
- // sequence<DOMString> temporarily for now.
- // Please see: https://crbug.com/754779
- //
- // [1] https://github.com/w3c/browser-payment-api/pull/551
- // [2] https://w3c.github.io/browser-payment-api/#paymentdetailsmodifier-dictionary
- required (DOMString or sequence<DOMString>) supportedMethods;
+ [ImplementedAs=supportedMethod] required DOMString supportedMethods;
PaymentItem total;
sequence<PaymentItem> additionalDisplayItems;
[RuntimeEnabled=PaymentDetailsModifierData] object data;
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion.cc b/chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion.cc
index 0e02dcf8e27..f96645282a7 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion.cc
@@ -37,12 +37,7 @@ PaymentDetailsModifier ToPaymentDetailsModifier(
ScriptState* script_state,
const WebPaymentDetailsModifier& web_modifier) {
PaymentDetailsModifier modifier;
- Vector<String> supported_methods;
- for (const auto& web_method : web_modifier.supported_methods) {
- supported_methods.push_back(web_method);
- }
- modifier.setSupportedMethods(
- StringOrStringSequence::FromStringSequence(supported_methods));
+ modifier.setSupportedMethod(web_modifier.supported_method);
modifier.setTotal(ToPaymentItem(web_modifier.total));
HeapVector<PaymentItem> additional_display_items;
for (const auto& web_item : web_modifier.additional_display_items) {
@@ -71,12 +66,7 @@ PaymentMethodData ToPaymentMethodData(
ScriptState* script_state,
const WebPaymentMethodData& web_method_data) {
PaymentMethodData method_data;
- Vector<String> supported_methods;
- for (const auto& method : web_method_data.supported_methods) {
- supported_methods.push_back(method);
- }
- method_data.setSupportedMethods(
- StringOrStringSequence::FromStringSequence(supported_methods));
+ method_data.setSupportedMethod(web_method_data.supported_method);
method_data.setData(
StringDataToScriptValue(script_state, web_method_data.stringified_data));
return method_data;
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion_test.cc b/chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion_test.cc
index a01e3ecb077..3f0109f72f1 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion_test.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_event_data_conversion_test.cc
@@ -24,8 +24,7 @@ static WebPaymentCurrencyAmount CreateWebPaymentCurrencyAmountForTest() {
static WebPaymentMethodData CreateWebPaymentMethodDataForTest() {
WebPaymentMethodData web_method_data;
- WebString method = WebString::FromUTF8("foo");
- web_method_data.supported_methods = WebVector<WebString>(&method, 1);
+ web_method_data.supported_method = "foo";
web_method_data.stringified_data = "{\"merchantId\":\"12345\"}";
return web_method_data;
}
@@ -69,20 +68,11 @@ TEST(PaymentEventDataConversionTest, ToCanMakePaymentEventData) {
ASSERT_TRUE(data.hasMethodData());
ASSERT_EQ(1UL, data.methodData().size());
- ASSERT_TRUE(data.methodData().front().hasSupportedMethods());
- ASSERT_EQ(1UL, data.methodData()
- .front()
- .supportedMethods()
- .GetAsStringSequence()
- .size());
- ASSERT_EQ("foo", data.methodData()
- .front()
- .supportedMethods()
- .GetAsStringSequence()
- .front());
+ ASSERT_TRUE(data.methodData().front().hasSupportedMethod());
+ ASSERT_EQ("foo", data.methodData().front().supportedMethod());
ASSERT_TRUE(data.methodData().front().hasData());
ASSERT_TRUE(data.methodData().front().data().IsObject());
- String stringified_data = V8StringToWebCoreString<String>(
+ String stringified_data = ToBlinkString<String>(
v8::JSON::Stringify(
scope.GetContext(),
data.methodData().front().data().V8Value().As<v8::Object>())
@@ -110,20 +100,11 @@ TEST(PaymentEventDataConversionTest, ToPaymentRequestEventData) {
ASSERT_TRUE(data.hasMethodData());
ASSERT_EQ(1UL, data.methodData().size());
- ASSERT_TRUE(data.methodData().front().hasSupportedMethods());
- ASSERT_EQ(1UL, data.methodData()
- .front()
- .supportedMethods()
- .GetAsStringSequence()
- .size());
- ASSERT_EQ("foo", data.methodData()
- .front()
- .supportedMethods()
- .GetAsStringSequence()
- .front());
+ ASSERT_TRUE(data.methodData().front().hasSupportedMethod());
+ ASSERT_EQ("foo", data.methodData().front().supportedMethod());
ASSERT_TRUE(data.methodData().front().hasData());
ASSERT_TRUE(data.methodData().front().data().IsObject());
- String stringified_data = V8StringToWebCoreString<String>(
+ String stringified_data = ToBlinkString<String>(
v8::JSON::Stringify(
scope.GetContext(),
data.methodData().front().data().V8Value().As<v8::Object>())
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_handler_utils.cc b/chromium/third_party/blink/renderer/modules/payments/payment_handler_utils.cc
index 9ea8091140f..7a571d466d0 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_handler_utils.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_handler_utils.cc
@@ -44,6 +44,7 @@ void PaymentHandlerUtils::ReportResponseError(
case ServiceWorkerResponseError::kRedirectedResponseForNotFollowRequest:
case ServiceWorkerResponseError::kDataPipeCreationFailed:
case ServiceWorkerResponseError::kResponseTypeCORSForRequestModeSameOrigin:
+ case ServiceWorkerResponseError::kResponseBodyBroken:
NOTREACHED();
error_message = error_message + "an unexpected error occurred.";
break;
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_instruments.cc b/chromium/third_party/blink/renderer/modules/payments/payment_instruments.cc
index 49144aa3068..a0a30bf7a90 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_instruments.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_instruments.cc
@@ -13,7 +13,6 @@
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_feature.mojom-blink.h"
#include "third_party/blink/public/platform/web_icon_sizes_parser.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
@@ -28,6 +27,7 @@
#include "third_party/blink/renderer/modules/payments/payment_instrument.h"
#include "third_party/blink/renderer/modules/payments/payment_manager.h"
#include "third_party/blink/renderer/modules/permissions/permission_utils.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -41,19 +41,19 @@ bool rejectError(ScriptPromiseResolver* resolver,
case payments::mojom::blink::PaymentHandlerStatus::SUCCESS:
return false;
case payments::mojom::blink::PaymentHandlerStatus::NOT_IMPLEMENTED:
- resolver->Reject(
- DOMException::Create(kNotSupportedError, "Not implemented yet"));
+ resolver->Reject(DOMException::Create(
+ DOMExceptionCode::kNotSupportedError, "Not implemented yet"));
return true;
case payments::mojom::blink::PaymentHandlerStatus::NOT_FOUND:
resolver->Resolve();
return true;
case payments::mojom::blink::PaymentHandlerStatus::NO_ACTIVE_WORKER:
- resolver->Reject(
- DOMException::Create(kInvalidStateError, "No active service worker"));
+ resolver->Reject(DOMException::Create(
+ DOMExceptionCode::kInvalidStateError, "No active service worker"));
return true;
case payments::mojom::blink::PaymentHandlerStatus::STORAGE_OPERATION_FAILED:
- resolver->Reject(DOMException::Create(kInvalidStateError,
- "Storage operation is failed"));
+ resolver->Reject(DOMException::Create(
+ DOMExceptionCode::kInvalidStateError, "Storage operation is failed"));
return true;
case payments::mojom::blink::PaymentHandlerStatus::
FETCH_INSTRUMENT_ICON_FAILED: {
@@ -87,7 +87,7 @@ bool AllowedToUsePaymentFeatures(ScriptState* script_state) {
ScriptPromise RejectNotAllowedToUsePaymentFeatures(ScriptState* script_state) {
return ScriptPromise::RejectWithDOMException(
script_state, DOMException::Create(
- kSecurityError,
+ DOMExceptionCode::kSecurityError,
"Must be in a top-level browsing context or an iframe "
"needs to specify allow=\"payment\" explicitly"));
}
@@ -106,8 +106,8 @@ ScriptPromise PaymentInstruments::deleteInstrument(
if (!manager_.is_bound()) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, kPaymentManagerUnavailable));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kPaymentManagerUnavailable));
}
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
@@ -127,8 +127,8 @@ ScriptPromise PaymentInstruments::get(ScriptState* script_state,
if (!manager_.is_bound()) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, kPaymentManagerUnavailable));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kPaymentManagerUnavailable));
}
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
@@ -147,8 +147,8 @@ ScriptPromise PaymentInstruments::keys(ScriptState* script_state) {
if (!manager_.is_bound()) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, kPaymentManagerUnavailable));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kPaymentManagerUnavailable));
}
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
@@ -167,8 +167,8 @@ ScriptPromise PaymentInstruments::has(ScriptState* script_state,
if (!manager_.is_bound()) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, kPaymentManagerUnavailable));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kPaymentManagerUnavailable));
}
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
@@ -190,8 +190,8 @@ ScriptPromise PaymentInstruments::set(ScriptState* script_state,
if (!manager_.is_bound()) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, kPaymentManagerUnavailable));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kPaymentManagerUnavailable));
}
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
@@ -217,8 +217,8 @@ ScriptPromise PaymentInstruments::clear(ScriptState* script_state) {
if (!manager_.is_bound()) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, kPaymentManagerUnavailable));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kPaymentManagerUnavailable));
}
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
@@ -252,8 +252,9 @@ void PaymentInstruments::OnRequestPermission(
ScriptState::Scope scope(resolver->GetScriptState());
if (status != mojom::blink::PermissionStatus::GRANTED) {
- resolver->Reject(DOMException::Create(
- kNotAllowedError, "Not allowed to install this payment handler"));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kNotAllowedError,
+ "Not allowed to install this payment handler"));
return;
}
@@ -272,10 +273,11 @@ void PaymentInstruments::OnRequestPermission(
return;
}
- mojom::blink::ManifestIconPtr icon = mojom::blink::ManifestIcon::New();
+ mojom::blink::ManifestImageResourcePtr icon =
+ mojom::blink::ManifestImageResource::New();
icon->src = parsed_url;
icon->type = image_object.type();
- icon->purpose.push_back(blink::mojom::ManifestIcon_Purpose::ANY);
+ icon->purpose.push_back(blink::mojom::ManifestImageResource_Purpose::ANY);
WebVector<WebSize> web_sizes =
WebIconSizesParser::ParseIconSizes(image_object.sizes());
for (const auto& web_size : web_sizes) {
@@ -307,7 +309,7 @@ void PaymentInstruments::OnRequestPermission(
details.capabilities(), instrument->supported_networks,
instrument->supported_types, exception_state);
if (exception_state.HadException()) {
- exception_state.Reject(resolver);
+ resolver->Reject(exception_state);
return;
}
}
@@ -373,7 +375,7 @@ void PaymentInstruments::onGetPaymentInstrument(
stored_instrument->stringified_capabilities,
exception_state)));
if (exception_state.HadException()) {
- exception_state.Reject(resolver);
+ resolver->Reject(exception_state);
return;
}
}
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_manager.cc b/chromium/third_party/blink/renderer/modules/payments/payment_manager.cc
index a69885d3aa2..29517bb614a 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_manager.cc
@@ -8,8 +8,9 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/modules/payments/payment_instruments.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_method_data.idl b/chromium/third_party/blink/renderer/modules/payments/payment_method_data.idl
index 4cd8cfc77e3..be09a4c4561 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_method_data.idl
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_method_data.idl
@@ -5,14 +5,6 @@
// https://w3c.github.io/browser-payment-api/#idl-def-paymentmethoddata
dictionary PaymentMethodData {
- // TODO(zino): The supportedMethods's type was changed from
- // sequence<DOMString> to DOMString[1][2]. But we are not sure if we can
- // remove them now. So, we will define it as union type of DOMString and
- // sequence<DOMString> temporarily for now.
- // Please see: https://crbug.com/754779
- //
- // [1] https://github.com/w3c/browser-payment-api/pull/551
- // [2] https://w3c.github.io/browser-payment-api/#paymentdetailsmodifier-dictionary
- required (DOMString or sequence<DOMString>) supportedMethods;
+ [ImplementedAs=supportedMethod] required DOMString supportedMethods;
object data;
};
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_request.cc b/chromium/third_party/blink/renderer/modules/payments/payment_request.cc
index 58900ce5631..4b803e9cb19 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request.cc
@@ -12,7 +12,6 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_feature.mojom-blink.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/script_regexp.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_string_resource.h"
@@ -23,7 +22,6 @@
#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/dom/events/event_queue.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/event_type_names.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/core/frame/frame_owner.h"
@@ -47,6 +45,7 @@
#include "third_party/blink/renderer/modules/payments/payment_response.h"
#include "third_party/blink/renderer/modules/payments/payment_shipping_option.h"
#include "third_party/blink/renderer/modules/payments/payments_validators.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/feature_policy/feature_policy.h"
#include "third_party/blink/renderer/platform/mojo/mojo_helper.h"
@@ -140,7 +139,7 @@ namespace {
// If the website does not call complete() 60 seconds after show() has been
// resolved, then behave as if the website called complete("fail").
-static const int kCompleteTimeoutSeconds = 60;
+constexpr TimeDelta kCompleteTimeout = TimeDelta::FromSeconds(60);
// Validates ShippingOption or PaymentItem, which happen to have identical
// fields, except for "id", which is present only in ShippingOption.
@@ -418,11 +417,10 @@ void SetBasicCardMethodData(const ScriptValue& input,
output->supported_types, exception_state);
}
-void StringifyAndParseMethodSpecificData(
- const Vector<String>& supported_methods,
- const ScriptValue& input,
- PaymentMethodDataPtr& output,
- ExceptionState& exception_state) {
+void StringifyAndParseMethodSpecificData(const String& supported_method,
+ const ScriptValue& input,
+ PaymentMethodDataPtr& output,
+ ExceptionState& exception_state) {
DCHECK(!input.IsEmpty());
v8::Local<v8::String> value;
if (!input.V8Value()->IsObject() ||
@@ -433,8 +431,7 @@ void StringifyAndParseMethodSpecificData(
return;
}
- output->stringified_data =
- V8StringToWebCoreString<String>(value, kDoNotExternalize);
+ output->stringified_data = ToBlinkString<String>(value, kDoNotExternalize);
if (output->stringified_data.length() >
PaymentRequest::kMaxJSONStringLength) {
@@ -447,24 +444,24 @@ void StringifyAndParseMethodSpecificData(
// Serialize payment method specific data to be sent to the payment apps. The
// payment apps are responsible for validating and processing their method
// data asynchronously. Do not throw exceptions here.
- if (supported_methods.Contains("https://android.com/pay") ||
- supported_methods.Contains("https://google.com/pay")) {
+ if (supported_method == "https://android.com/pay" ||
+ supported_method == "https://google.com/pay") {
SetAndroidPayMethodData(input, output, exception_state);
if (exception_state.HadException())
exception_state.ClearException();
}
if (RuntimeEnabledFeatures::PaymentRequestBasicCardEnabled() &&
- supported_methods.Contains("basic-card")) {
+ supported_method == "basic-card") {
SetBasicCardMethodData(input, output, exception_state);
if (exception_state.HadException())
exception_state.ClearException();
}
}
-void CountPaymentRequestNetworkNameInSupportedMethods(
- const Vector<String>& supported_methods,
+void CountPaymentRequestNetworkNameInSupportedMethod(
+ const String& supported_method,
ExecutionContext& execution_context) {
- if (BasicCardHelper::ContainsNetworkNames(supported_methods)) {
+ if (BasicCardHelper::IsNetworkName(supported_method)) {
Deprecation::CountDeprecation(
&execution_context,
WebFeature::kPaymentRequestNetworkNameInSupportedMethods);
@@ -518,54 +515,23 @@ void ValidateAndConvertPaymentDetailsModifiers(
return;
}
- Vector<String> supported_methods;
- if (modifier.supportedMethods().IsString()) {
- supported_methods.push_back(modifier.supportedMethods().GetAsString());
- }
- if (modifier.supportedMethods().IsStringSequence()) {
- supported_methods = modifier.supportedMethods().GetAsStringSequence();
- if (supported_methods.size() > 1) {
- Deprecation::CountDeprecation(
- &execution_context,
- WebFeature::kPaymentRequestSupportedMethodsArray);
- }
- }
- if (supported_methods.IsEmpty()) {
- exception_state.ThrowTypeError(
- "Must specify at least one payment method identifier");
+ if (!IsValidMethodFormat(modifier.supportedMethod())) {
+ exception_state.ThrowRangeError(
+ "Invalid payment method identifier format");
return;
}
- if (supported_methods.size() > PaymentRequest::kMaxListSize) {
- exception_state.ThrowTypeError(
- "At most 1024 supportedMethods allowed for modifier");
- return;
- }
-
- for (const String& method : supported_methods) {
- if (method.length() > PaymentRequest::kMaxStringLength) {
- exception_state.ThrowTypeError(
- "Supported method name for identifier cannot be longer than 1024 "
- "characters");
- return;
- }
- if (!IsValidMethodFormat(method)) {
- exception_state.ThrowRangeError(
- "Invalid payment method identifier format");
- return;
- }
- }
- CountPaymentRequestNetworkNameInSupportedMethods(supported_methods,
- execution_context);
+ CountPaymentRequestNetworkNameInSupportedMethod(modifier.supportedMethod(),
+ execution_context);
output.back()->method_data =
payments::mojom::blink::PaymentMethodData::New();
- output.back()->method_data->supported_methods = supported_methods;
+ output.back()->method_data->supported_method = modifier.supportedMethod();
if (modifier.hasData() && !modifier.data().IsEmpty()) {
- StringifyAndParseMethodSpecificData(supported_methods, modifier.data(),
- output.back()->method_data,
- exception_state);
+ StringifyAndParseMethodSpecificData(
+ modifier.supportedMethod(), modifier.data(),
+ output.back()->method_data, exception_state);
} else {
output.back()->method_data->stringified_data = "";
}
@@ -672,57 +638,23 @@ void ValidateAndConvertPaymentMethodData(
}
for (const PaymentMethodData payment_method_data : input) {
- Vector<String> supported_methods;
- if (payment_method_data.supportedMethods().IsString()) {
- supported_methods.push_back(
- payment_method_data.supportedMethods().GetAsString());
- }
- if (payment_method_data.supportedMethods().IsStringSequence()) {
- supported_methods =
- payment_method_data.supportedMethods().GetAsStringSequence();
- if (supported_methods.size() > 1) {
- Deprecation::CountDeprecation(
- &execution_context,
- WebFeature::kPaymentRequestSupportedMethodsArray);
- }
- }
- if (supported_methods.IsEmpty()) {
- exception_state.ThrowTypeError(
- "Each payment method needs to include at least one payment method "
- "identifier");
+ if (!IsValidMethodFormat(payment_method_data.supportedMethod())) {
+ exception_state.ThrowRangeError(
+ "Invalid payment method identifier format");
return;
}
+ method_names.insert(payment_method_data.supportedMethod());
- if (supported_methods.size() > PaymentRequest::kMaxListSize) {
- exception_state.ThrowTypeError(
- "At most 1024 payment method identifiers are supported");
- return;
- }
-
- for (const String identifier : supported_methods) {
- if (identifier.length() > PaymentRequest::kMaxStringLength) {
- exception_state.ThrowTypeError(
- "A payment method identifier cannot be longer than 1024 "
- "characters");
- return;
- }
- if (!IsValidMethodFormat(identifier)) {
- exception_state.ThrowRangeError(
- "Invalid payment method identifier format");
- return;
- }
- method_names.insert(identifier);
- }
-
- CountPaymentRequestNetworkNameInSupportedMethods(supported_methods,
- execution_context);
+ CountPaymentRequestNetworkNameInSupportedMethod(
+ payment_method_data.supportedMethod(), execution_context);
output.push_back(payments::mojom::blink::PaymentMethodData::New());
- output.back()->supported_methods = supported_methods;
+
+ output.back()->supported_method = payment_method_data.supportedMethod();
if (payment_method_data.hasData() &&
!payment_method_data.data().IsEmpty()) {
- StringifyAndParseMethodSpecificData(supported_methods,
+ StringifyAndParseMethodSpecificData(payment_method_data.supportedMethod(),
payment_method_data.data(),
output.back(), exception_state);
} else {
@@ -739,23 +671,6 @@ bool AllowedToUsePaymentRequest(const Frame* frame) {
if (!frame)
return false;
- if (!IsSupportedInFeaturePolicy(mojom::FeaturePolicyFeature::kPayment)) {
- // 2. If |document|'s browsing context is a top-level browsing context, then
- // return true.
- if (frame->IsMainFrame())
- return true;
-
- // 3. If |document|'s browsing context has a browsing context container that
- // is an iframe element with an |allowpaymentrequest| attribute specified,
- // and whose node document is allowed to use the feature indicated by
- // |allowpaymentrequest|, then return true.
- if (frame->Owner() && frame->Owner()->AllowPaymentRequest())
- return AllowedToUsePaymentRequest(frame->Tree().Parent());
-
- // 4. Return false.
- return false;
- }
-
// 2. If Feature Policy is enabled, return the policy for "payment" feature.
return frame->IsFeatureEnabled(mojom::FeaturePolicyFeature::kPayment);
}
@@ -795,14 +710,14 @@ PaymentRequest::~PaymentRequest() = default;
ScriptPromise PaymentRequest::show(ScriptState* script_state) {
if (!payment_provider_.is_bound() || show_resolver_) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, "Already called show() once"));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Already called show() once"));
}
if (!script_state->ContextIsValid() || !LocalDOMWindow::From(script_state) ||
!LocalDOMWindow::From(script_state)->GetFrame()) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kInvalidStateError,
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
"Cannot show the payment request"));
}
@@ -818,8 +733,8 @@ ScriptPromise PaymentRequest::show(ScriptState* script_state) {
// immersive mode.
if (GetFrame()->GetDocument()->GetSettings()->GetImmersiveModeEnabled()) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, "Page popups are suppressed"));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Page popups are suppressed"));
}
payment_provider_->Show(is_user_gesture);
@@ -831,14 +746,14 @@ ScriptPromise PaymentRequest::show(ScriptState* script_state) {
ScriptPromise PaymentRequest::abort(ScriptState* script_state) {
if (!script_state->ContextIsValid()) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, "Cannot abort payment"));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Cannot abort payment"));
}
if (abort_resolver_) {
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kInvalidStateError,
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
"Cannot abort() again until the previous abort() "
"has resolved or rejected"));
}
@@ -846,7 +761,7 @@ ScriptPromise PaymentRequest::abort(ScriptState* script_state) {
if (!show_resolver_) {
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kInvalidStateError,
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
"Never called show(), so nothing to abort"));
}
@@ -859,7 +774,7 @@ ScriptPromise PaymentRequest::canMakePayment(ScriptState* script_state) {
if (!payment_provider_.is_bound() || show_resolver_ ||
can_make_payment_resolver_ || !script_state->ContextIsValid()) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kInvalidStateError,
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
"Cannot query payment request"));
}
@@ -881,17 +796,25 @@ ExecutionContext* PaymentRequest::GetExecutionContext() const {
return ContextLifecycleObserver::GetExecutionContext();
}
+ScriptPromise PaymentRequest::Retry(ScriptState*,
+ const PaymentValidationErrors&) {
+ // TODO(zino): Should implement this method. Please see
+ // https://crbug.com/861704
+ NOTIMPLEMENTED();
+ return ScriptPromise();
+}
+
ScriptPromise PaymentRequest::Complete(ScriptState* script_state,
PaymentComplete result) {
if (!script_state->ContextIsValid()) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, "Cannot complete payment"));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Cannot complete payment"));
}
if (complete_resolver_) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kInvalidStateError,
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
"Already called complete() once"));
}
@@ -899,14 +822,15 @@ ScriptPromise PaymentRequest::Complete(ScriptState* script_state,
return ScriptPromise::RejectWithDOMException(
script_state,
DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Timed out after 60 seconds, complete() called too late"));
}
// User has cancelled the transaction while the website was processing it.
if (!payment_provider_) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kAbortError, "Request cancelled"));
+ script_state, DOMException::Create(DOMExceptionCode::kAbortError,
+ "Request cancelled"));
}
complete_timer_.Stop();
@@ -938,7 +862,7 @@ void PaymentRequest::OnUpdatePaymentDetails(
if (!details.hasTotal()) {
show_resolver_->Reject(
- DOMException::Create(kSyntaxError, "Total required"));
+ DOMException::Create(DOMExceptionCode::kSyntaxError, "Total required"));
ClearResolversAndCloseMojoConnection();
return;
}
@@ -961,10 +885,14 @@ void PaymentRequest::OnUpdatePaymentDetails(
}
void PaymentRequest::OnUpdatePaymentDetailsFailure(const String& error) {
- if (show_resolver_)
- show_resolver_->Reject(DOMException::Create(kAbortError, error));
- if (complete_resolver_)
- complete_resolver_->Reject(DOMException::Create(kAbortError, error));
+ if (show_resolver_) {
+ show_resolver_->Reject(
+ DOMException::Create(DOMExceptionCode::kAbortError, error));
+ }
+ if (complete_resolver_) {
+ complete_resolver_->Reject(
+ DOMException::Create(DOMExceptionCode::kAbortError, error));
+ }
ClearResolversAndCloseMojoConnection();
}
@@ -1061,7 +989,8 @@ void PaymentRequest::OnShippingAddressChange(PaymentAddressPtr address) {
String error_message;
if (!PaymentsValidators::IsValidShippingAddress(address, &error_message)) {
- show_resolver_->Reject(DOMException::Create(kSyntaxError, error_message));
+ show_resolver_->Reject(
+ DOMException::Create(DOMExceptionCode::kSyntaxError, error_message));
ClearResolversAndCloseMojoConnection();
return;
}
@@ -1108,7 +1037,8 @@ void PaymentRequest::OnPaymentResponse(PaymentResponsePtr response) {
if (options_.requestShipping()) {
if (!response->shipping_address || response->shipping_option.IsEmpty()) {
- show_resolver_->Reject(DOMException::Create(kSyntaxError));
+ show_resolver_->Reject(
+ DOMException::Create(DOMExceptionCode::kSyntaxError));
ClearResolversAndCloseMojoConnection();
return;
}
@@ -1116,7 +1046,8 @@ void PaymentRequest::OnPaymentResponse(PaymentResponsePtr response) {
String error_message;
if (!PaymentsValidators::IsValidShippingAddress(response->shipping_address,
&error_message)) {
- show_resolver_->Reject(DOMException::Create(kSyntaxError, error_message));
+ show_resolver_->Reject(
+ DOMException::Create(DOMExceptionCode::kSyntaxError, error_message));
ClearResolversAndCloseMojoConnection();
return;
}
@@ -1126,7 +1057,8 @@ void PaymentRequest::OnPaymentResponse(PaymentResponsePtr response) {
shipping_option_ = response->shipping_option;
} else {
if (response->shipping_address || !response->shipping_option.IsNull()) {
- show_resolver_->Reject(DOMException::Create(kSyntaxError));
+ show_resolver_->Reject(
+ DOMException::Create(DOMExceptionCode::kSyntaxError));
ClearResolversAndCloseMojoConnection();
return;
}
@@ -1138,12 +1070,13 @@ void PaymentRequest::OnPaymentResponse(PaymentResponsePtr response) {
(!options_.requestPayerName() && !response->payer_name.IsNull()) ||
(!options_.requestPayerEmail() && !response->payer_email.IsNull()) ||
(!options_.requestPayerPhone() && !response->payer_phone.IsNull())) {
- show_resolver_->Reject(DOMException::Create(kSyntaxError));
+ show_resolver_->Reject(
+ DOMException::Create(DOMExceptionCode::kSyntaxError));
ClearResolversAndCloseMojoConnection();
return;
}
- complete_timer_.StartOneShot(kCompleteTimeoutSeconds, FROM_HERE);
+ complete_timer_.StartOneShot(kCompleteTimeout, FROM_HERE);
show_resolver_->Resolve(new PaymentResponse(
std::move(response), shipping_address_.Get(), this, id_));
@@ -1155,18 +1088,18 @@ void PaymentRequest::OnPaymentResponse(PaymentResponsePtr response) {
}
void PaymentRequest::OnError(PaymentErrorReason error) {
- ExceptionCode ec = kUnknownError;
+ DOMExceptionCode exception_code = DOMExceptionCode::kUnknownError;
String message;
switch (error) {
case PaymentErrorReason::USER_CANCEL: {
- ec = kAbortError;
+ exception_code = DOMExceptionCode::kAbortError;
message = "Request cancelled";
break;
}
case PaymentErrorReason::NOT_SUPPORTED: {
- ec = kNotSupportedError;
+ exception_code = DOMExceptionCode::kNotSupportedError;
DCHECK_LE(1U, method_names_.size());
auto it = method_names_.begin();
if (method_names_.size() == 1U) {
@@ -1188,7 +1121,7 @@ void PaymentRequest::OnError(PaymentErrorReason error) {
}
case PaymentErrorReason::UNKNOWN: {
- ec = kUnknownError;
+ exception_code = DOMExceptionCode::kUnknownError;
message = "Request failed";
break;
}
@@ -1206,13 +1139,15 @@ void PaymentRequest::OnError(PaymentErrorReason error) {
}
if (show_resolver_)
- show_resolver_->Reject(DOMException::Create(ec, message));
+ show_resolver_->Reject(DOMException::Create(exception_code, message));
if (abort_resolver_)
- abort_resolver_->Reject(DOMException::Create(ec, message));
+ abort_resolver_->Reject(DOMException::Create(exception_code, message));
- if (can_make_payment_resolver_)
- can_make_payment_resolver_->Reject(DOMException::Create(ec, message));
+ if (can_make_payment_resolver_) {
+ can_make_payment_resolver_->Reject(
+ DOMException::Create(exception_code, message));
+ }
ClearResolversAndCloseMojoConnection();
}
@@ -1229,13 +1164,13 @@ void PaymentRequest::OnAbort(bool aborted_successfully) {
if (!aborted_successfully) {
abort_resolver_->Reject(DOMException::Create(
- kInvalidStateError, "Unable to abort the payment"));
+ DOMExceptionCode::kInvalidStateError, "Unable to abort the payment"));
abort_resolver_.Clear();
return;
}
- show_resolver_->Reject(
- DOMException::Create(kAbortError, "The website has aborted the payment"));
+ show_resolver_->Reject(DOMException::Create(
+ DOMExceptionCode::kAbortError, "The website has aborted the payment"));
abort_resolver_->Resolve();
ClearResolversAndCloseMojoConnection();
}
@@ -1258,7 +1193,8 @@ void PaymentRequest::OnCanMakePayment(CanMakePaymentQueryResult result) {
break;
case CanMakePaymentQueryResult::QUERY_QUOTA_EXCEEDED:
can_make_payment_resolver_->Reject(DOMException::Create(
- kNotAllowedError, "Not allowed to check whether can make payment"));
+ DOMExceptionCode::kNotAllowedError,
+ "Not allowed to check whether can make payment"));
break;
}
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_request.h b/chromium/third_party/blink/renderer/modules/payments/payment_request.h
index 6a3b0d816db..7a3d307ccef 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request.h
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request.h
@@ -9,14 +9,15 @@
#include "components/payments/mojom/payment_request_data.mojom-blink.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "third_party/blink/public/platform/modules/payments/payment_request.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/modules/payments/payment_completer.h"
#include "third_party/blink/renderer/modules/payments/payment_method_data.h"
#include "third_party/blink/renderer/modules/payments/payment_options.h"
+#include "third_party/blink/renderer/modules/payments/payment_state_resolver.h"
#include "third_party/blink/renderer/modules/payments/payment_updater.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -38,7 +39,7 @@ class ScriptState;
class MODULES_EXPORT PaymentRequest final
: public EventTargetWithInlineData,
public payments::mojom::blink::PaymentRequestClient,
- public PaymentCompleter,
+ public PaymentStateResolver,
public PaymentUpdater,
public ContextLifecycleObserver,
public ActiveScriptWrappable<PaymentRequest> {
@@ -79,8 +80,9 @@ class MODULES_EXPORT PaymentRequest final
const AtomicString& InterfaceName() const override;
ExecutionContext* GetExecutionContext() const override;
- // PaymentCompleter:
+ // PaymentStateResolver:
ScriptPromise Complete(ScriptState*, PaymentComplete result) override;
+ ScriptPromise Retry(ScriptState*, const PaymentValidationErrors&) override;
// PaymentUpdater:
void OnUpdatePaymentDetails(const ScriptValue& details_script_value) override;
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_request.idl b/chromium/third_party/blink/renderer/modules/payments/payment_request.idl
index cfc59a9f121..41e01295d93 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request.idl
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request.idl
@@ -14,9 +14,9 @@
Exposed=Window,
ActiveScriptWrappable
] interface PaymentRequest : EventTarget {
- [CallWith=ScriptState] Promise<PaymentResponse> show();
- [CallWith=ScriptState] Promise<void> abort();
- [CallWith=ScriptState] Promise<boolean> canMakePayment();
+ [CallWith=ScriptState, NewObject] Promise<PaymentResponse> show();
+ [CallWith=ScriptState, NewObject] Promise<void> abort();
+ [CallWith=ScriptState, NewObject] Promise<boolean> canMakePayment();
readonly attribute DOMString id;
[ImplementedAs=getShippingAddress] readonly attribute PaymentAddress? shippingAddress;
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_request_details_test.cc b/chromium/third_party/blink/renderer/modules/payments/payment_request_details_test.cc
index 63b18ebc8d0..f894f7185fa 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request_details_test.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request_details_test.cc
@@ -6,26 +6,27 @@
#include <ostream> // NOLINT
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/exception_code.h"
#include "third_party/blink/renderer/modules/payments/payment_details_init.h"
#include "third_party/blink/renderer/modules/payments/payment_options.h"
#include "third_party/blink/renderer/modules/payments/payment_test_helper.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/weborigin/security_origin.h"
namespace blink {
namespace {
class DetailsTestCase {
public:
- DetailsTestCase(PaymentTestDetailToChange detail,
- PaymentTestDataToChange data,
- PaymentTestModificationType mod_type,
- const char* value_to_use,
- bool expect_exception = false,
- ExceptionCode expected_exception_code = 0)
+ DetailsTestCase(
+ PaymentTestDetailToChange detail,
+ PaymentTestDataToChange data,
+ PaymentTestModificationType mod_type,
+ const char* value_to_use,
+ bool expect_exception = false,
+ ESErrorType expected_exception_code = static_cast<ESErrorType>(0))
: detail_(detail),
data_(data),
mod_type_(mod_type),
@@ -42,7 +43,7 @@ class DetailsTestCase {
bool ExpectException() const { return expect_exception_; }
- ExceptionCode GetExpectedExceptionCode() const {
+ ESErrorType GetExpectedExceptionCode() const {
return expected_exception_code_;
}
@@ -53,7 +54,7 @@ class DetailsTestCase {
PaymentTestModificationType mod_type_;
const char* value_to_use_;
bool expect_exception_;
- ExceptionCode expected_exception_code_;
+ ESErrorType expected_exception_code_;
};
std::ostream& operator<<(std::ostream& out, DetailsTestCase test_case) {
@@ -136,9 +137,10 @@ TEST_P(PaymentRequestDetailsTest, ValidatesDetails) {
EXPECT_EQ(GetParam().ExpectException(),
scope.GetExceptionState().HadException());
- if (GetParam().ExpectException())
+ if (GetParam().ExpectException()) {
EXPECT_EQ(GetParam().GetExpectedExceptionCode(),
- scope.GetExceptionState().Code());
+ scope.GetExceptionState().CodeAs<ESErrorType>());
+ }
}
INSTANTIATE_TEST_CASE_P(
@@ -149,7 +151,7 @@ INSTANTIATE_TEST_CASE_P(
kPaymentTestOverwriteValue,
"",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailTotal,
kPaymentTestDataLabel,
kPaymentTestOverwriteValue,
@@ -160,7 +162,7 @@ INSTANTIATE_TEST_CASE_P(
kPaymentTestOverwriteValue,
"",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailItem,
kPaymentTestDataLabel,
kPaymentTestOverwriteValue,
@@ -171,7 +173,7 @@ INSTANTIATE_TEST_CASE_P(
kPaymentTestOverwriteValue,
"",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailShippingOption,
kPaymentTestDataId,
kPaymentTestOverwriteValue,
@@ -187,7 +189,7 @@ INSTANTIATE_TEST_CASE_P(
kPaymentTestOverwriteValue,
"",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierTotal,
kPaymentTestDataLabel,
kPaymentTestOverwriteValue,
@@ -198,7 +200,7 @@ INSTANTIATE_TEST_CASE_P(
kPaymentTestOverwriteValue,
"",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierItem,
kPaymentTestDataLabel,
kPaymentTestOverwriteValue,
@@ -457,235 +459,235 @@ INSTANTIATE_TEST_CASE_P(
kPaymentTestOverwriteValue,
"-0",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-3",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-3.00",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"notdigits",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"ALSONOTDIGITS",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"10.",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
".99",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-10.",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"10-",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"1-0",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"1.0.0",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"1/3",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-01234567890123456789.0123456789",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-01234567890123456789012345678.9",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-012345678901234567890123456789",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"notdigits",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"ALSONOTDIGITS",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"10.",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
".99",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-10.",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"10-",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"1-0",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"1.0.0",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"1/3",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailShippingOption,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailShippingOption,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailShippingOption,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"notdigits",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailShippingOption,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"ALSONOTDIGITS",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailShippingOption,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"10.",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailShippingOption,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
".99",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailShippingOption,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-10.",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailShippingOption,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"10-",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailShippingOption,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"1-0",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailShippingOption,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"1.0.0",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailShippingOption,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"1/3",
true,
- kV8TypeError)));
+ ESErrorType::kTypeError)));
INSTANTIATE_TEST_CASE_P(
InvalidValueFormatForModifier,
@@ -695,169 +697,169 @@ INSTANTIATE_TEST_CASE_P(
kPaymentTestOverwriteValue,
"-0",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-3",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-3.00",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"notdigits",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"ALSONOTDIGITS",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"10.",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
".99",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-10.",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"10-",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"1-0",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"1.0.0",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"1/3",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-01234567890123456789.0123456789",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-01234567890123456789012345678.9",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierTotal,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-012345678901234567890123456789",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"notdigits",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"ALSONOTDIGITS",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"10.",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
".99",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"-10.",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"10-",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"1-0",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"1.0.0",
true,
- kV8TypeError),
+ ESErrorType::kTypeError),
DetailsTestCase(kPaymentTestDetailModifierItem,
kPaymentTestDataValue,
kPaymentTestOverwriteValue,
"1/3",
true,
- kV8TypeError)));
+ ESErrorType::kTypeError)));
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_request_event.cc b/chromium/third_party/blink/renderer/modules/payments/payment_request_event.cc
index 0f97bd0d8fd..a411eb90f26 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request_event.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request_event.cc
@@ -11,9 +11,9 @@
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/core/workers/worker_location.h"
-#include "third_party/blink/renderer/modules/serviceworkers/respond_with_observer.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_window_client_callback.h"
+#include "third_party/blink/renderer/modules/service_worker/respond_with_observer.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_window_client_callback.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -77,7 +77,7 @@ ScriptPromise PaymentRequestEvent::openWindow(ScriptState* script_state,
if (!isTrusted()) {
resolver->Reject(DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Cannot open a window when the event is not trusted"));
return promise;
}
@@ -97,7 +97,7 @@ ScriptPromise PaymentRequestEvent::openWindow(ScriptState* script_state,
if (!context->IsWindowInteractionAllowed()) {
resolver->Reject(DOMException::Create(
- kNotAllowedError,
+ DOMExceptionCode::kNotAllowedError,
"Not allowed to open a window without user activation"));
return promise;
}
@@ -113,7 +113,7 @@ void PaymentRequestEvent::respondWith(ScriptState* script_state,
ExceptionState& exception_state) {
if (!isTrusted()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Cannot respond with data when the event is not trusted");
return;
}
@@ -140,9 +140,14 @@ PaymentRequestEvent::PaymentRequestEvent(
top_origin_(initializer.topOrigin()),
payment_request_origin_(initializer.paymentRequestOrigin()),
payment_request_id_(initializer.paymentRequestId()),
- method_data_(std::move(initializer.methodData())),
- total_(initializer.total()),
- modifiers_(initializer.modifiers()),
+ method_data_(initializer.hasMethodData()
+ ? initializer.methodData()
+ : HeapVector<PaymentMethodData>()),
+ total_(initializer.hasTotal() ? initializer.total()
+ : PaymentCurrencyAmount()),
+ modifiers_(initializer.hasModifiers()
+ ? initializer.modifiers()
+ : HeapVector<PaymentDetailsModifier>()),
instrument_key_(initializer.instrumentKey()),
observer_(respond_with_observer) {}
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_request_event.h b/chromium/third_party/blink/renderer/modules/payments/payment_request_event.h
index 59cab909e63..7c113bf99eb 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request_event.h
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request_event.h
@@ -8,7 +8,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/modules/event_modules.h"
#include "third_party/blink/renderer/modules/payments/payment_request_event_init.h"
-#include "third_party/blink/renderer/modules/serviceworkers/extendable_event.h"
+#include "third_party/blink/renderer/modules/service_worker/extendable_event.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace WTF {
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.cc b/chromium/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.cc
index 82d6fcbd4ad..b2401063f74 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.h"
-#include <v8.h>
#include "third_party/blink/public/platform/modules/payments/web_payment_handler_response.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
@@ -13,8 +12,10 @@
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/modules/payments/payment_handler_response.h"
#include "third_party/blink/renderer/modules/payments/payment_handler_utils.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.h"
-#include "third_party/blink/renderer/modules/serviceworkers/wait_until_observer.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h"
+#include "third_party/blink/renderer/modules/service_worker/wait_until_observer.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "v8/include/v8.h"
namespace blink {
@@ -36,11 +37,13 @@ void PaymentRequestRespondWithObserver::OnResponseRejected(
}
void PaymentRequestRespondWithObserver::OnResponseFulfilled(
- const ScriptValue& value) {
+ const ScriptValue& value,
+ ExceptionState::ContextType context_type,
+ const char* interface_name,
+ const char* property_name) {
DCHECK(GetExecutionContext());
- ExceptionState exception_state(value.GetIsolate(),
- ExceptionState::kUnknownContext,
- "PaymentRequestEvent", "respondWith");
+ ExceptionState exception_state(value.GetIsolate(), context_type,
+ interface_name, property_name);
PaymentHandlerResponse response = ScriptValue::To<PaymentHandlerResponse>(
ToIsolate(GetExecutionContext()), value, exception_state);
if (exception_state.HadException()) {
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.h b/chromium/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.h
index 6ffbede5f56..12e6cb598de 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.h
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.h
@@ -7,7 +7,7 @@
#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink.h"
#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/modules/serviceworkers/respond_with_observer.h"
+#include "third_party/blink/renderer/modules/service_worker/respond_with_observer.h"
namespace blink {
@@ -28,7 +28,10 @@ class MODULES_EXPORT PaymentRequestRespondWithObserver final
WaitUntilObserver*);
void OnResponseRejected(mojom::ServiceWorkerResponseError) override;
- void OnResponseFulfilled(const ScriptValue&) override;
+ void OnResponseFulfilled(const ScriptValue&,
+ ExceptionState::ContextType,
+ const char* interface_name,
+ const char* property_name) override;
void OnNoResponse() override;
void Trace(blink::Visitor*) override;
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_request_test.cc b/chromium/third_party/blink/renderer/modules/payments/payment_request_test.cc
index 38d11c9b85b..0663a0fbec0 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request_test.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request_test.cc
@@ -7,7 +7,6 @@
#include "testing/gtest/include/gtest/gtest.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/exception_code.h"
#include "third_party/blink/renderer/modules/payments/payment_test_helper.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
@@ -32,7 +31,8 @@ TEST(PaymentRequestTest, SupportedMethodListRequired) {
BuildPaymentDetailsInitForTest(), scope.GetExceptionState());
EXPECT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(kV8TypeError, scope.GetExceptionState().Code());
+ EXPECT_EQ(ESErrorType::kTypeError,
+ scope.GetExceptionState().CodeAs<ESErrorType>());
}
TEST(PaymentRequestTest, NullShippingOptionWhenNoOptionsAvailable) {
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_request_update_event.cc b/chromium/third_party/blink/renderer/modules/payments/payment_request_update_event.cc
index a2baf10f47b..92e86937a7d 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request_update_event.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request_update_event.cc
@@ -6,13 +6,12 @@
#include "base/location.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/payments/payment_updater.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -20,7 +19,7 @@ namespace {
// Reject the payment request if the page does not resolve the promise from
// updateWith within 60 seconds.
-static const int kAbortTimeout = 60;
+constexpr TimeDelta kAbortTimeout = TimeDelta::FromSeconds(60);
class UpdatePaymentDetailsFunction : public ScriptFunction {
public:
@@ -104,7 +103,7 @@ void PaymentRequestUpdateEvent::updateWith(ScriptState* script_state,
ExceptionState& exception_state) {
if (!isTrusted()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Cannot update details when the event is not trusted");
return;
}
@@ -113,7 +112,7 @@ void PaymentRequestUpdateEvent::updateWith(ScriptState* script_state,
return;
if (wait_for_update_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Cannot update details twice");
return;
}
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc b/chromium/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc
index e45399ad898..ff8142374b8 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc
@@ -7,13 +7,13 @@
#include <memory>
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/core/event_type_names.h"
#include "third_party/blink/renderer/modules/payments/payment_request.h"
#include "third_party/blink/renderer/modules/payments/payment_test_helper.h"
#include "third_party/blink/renderer/modules/payments/payment_updater.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_response.cc b/chromium/third_party/blink/renderer/modules/payments/payment_response.cc
index 7cda19c9dc5..e0e340fb2d9 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_response.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_response.cc
@@ -4,11 +4,12 @@
#include "third_party/blink/renderer/modules/payments/payment_response.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/modules/payments/payment_address.h"
-#include "third_party/blink/renderer/modules/payments/payment_completer.h"
+#include "third_party/blink/renderer/modules/payments/payment_state_resolver.h"
+#include "third_party/blink/renderer/modules/payments/payment_validation_errors.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink {
@@ -16,7 +17,7 @@ namespace blink {
PaymentResponse::PaymentResponse(
payments::mojom::blink::PaymentResponsePtr response,
PaymentAddress* shipping_address,
- PaymentCompleter* payment_completer,
+ PaymentStateResolver* payment_state_resolver,
const String& requestId)
: requestId_(requestId),
method_name_(response->method_name),
@@ -26,8 +27,8 @@ PaymentResponse::PaymentResponse(
payer_name_(response->payer_name),
payer_email_(response->payer_email),
payer_phone_(response->payer_phone),
- payment_completer_(payment_completer) {
- DCHECK(payment_completer_);
+ payment_state_resolver_(payment_state_resolver) {
+ DCHECK(payment_state_resolver_);
}
PaymentResponse::~PaymentResponse() = default;
@@ -62,18 +63,24 @@ ScriptValue PaymentResponse::details(ScriptState* script_state,
ScriptPromise PaymentResponse::complete(ScriptState* script_state,
const String& result) {
- PaymentCompleter::PaymentComplete converted_result =
- PaymentCompleter::kUnknown;
+ PaymentStateResolver::PaymentComplete converted_result =
+ PaymentStateResolver::PaymentComplete::kUnknown;
if (result == "success")
- converted_result = PaymentCompleter::kSuccess;
+ converted_result = PaymentStateResolver::PaymentComplete::kSuccess;
else if (result == "fail")
- converted_result = PaymentCompleter::kFail;
- return payment_completer_->Complete(script_state, converted_result);
+ converted_result = PaymentStateResolver::PaymentComplete::kFail;
+ return payment_state_resolver_->Complete(script_state, converted_result);
+}
+
+ScriptPromise PaymentResponse::retry(
+ ScriptState* script_state,
+ const PaymentValidationErrors& error_fields) {
+ return payment_state_resolver_->Retry(script_state, error_fields);
}
void PaymentResponse::Trace(blink::Visitor* visitor) {
visitor->Trace(shipping_address_);
- visitor->Trace(payment_completer_);
+ visitor->Trace(payment_state_resolver_);
ScriptWrappable::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_response.h b/chromium/third_party/blink/renderer/modules/payments/payment_response.h
index a00b776324f..6ad8d55ec5d 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_response.h
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_response.h
@@ -19,7 +19,8 @@ namespace blink {
class ExceptionState;
class PaymentAddress;
-class PaymentCompleter;
+class PaymentStateResolver;
+class PaymentValidationErrors;
class ScriptState;
class MODULES_EXPORT PaymentResponse final : public ScriptWrappable {
@@ -29,7 +30,7 @@ class MODULES_EXPORT PaymentResponse final : public ScriptWrappable {
public:
PaymentResponse(payments::mojom::blink::PaymentResponsePtr,
PaymentAddress* shipping_address_,
- PaymentCompleter*,
+ PaymentStateResolver*,
const String& requestId);
~PaymentResponse() override;
@@ -45,6 +46,7 @@ class MODULES_EXPORT PaymentResponse final : public ScriptWrappable {
const String& payerPhone() const { return payer_phone_; }
ScriptPromise complete(ScriptState*, const String& result = "");
+ ScriptPromise retry(ScriptState*, const PaymentValidationErrors&);
void Trace(blink::Visitor*) override;
@@ -57,7 +59,7 @@ class MODULES_EXPORT PaymentResponse final : public ScriptWrappable {
String payer_name_;
String payer_email_;
String payer_phone_;
- Member<PaymentCompleter> payment_completer_;
+ Member<PaymentStateResolver> payment_state_resolver_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_response.idl b/chromium/third_party/blink/renderer/modules/payments/payment_response.idl
index 53dcc0a9eb6..545ede68953 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_response.idl
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_response.idl
@@ -28,5 +28,6 @@ enum PaymentComplete {
readonly attribute DOMString? payerEmail;
readonly attribute DOMString? payerPhone;
- [CallWith=ScriptState] Promise<void> complete(optional PaymentComplete paymentResult = "unknown");
+ [CallWith=ScriptState, NewObject] Promise<void> complete(optional PaymentComplete paymentResult = "unknown");
+ [CallWith=ScriptState, NewObject, RuntimeEnabled=PaymentRetry] Promise<void> retry(PaymentValidationErrors errorFields);
};
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_response_test.cc b/chromium/third_party/blink/renderer/modules/payments/payment_response_test.cc
index 97d01753d34..53c12f8a740 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_response_test.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_response_test.cc
@@ -8,33 +8,37 @@
#include <utility>
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.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/modules/payments/payment_address.h"
-#include "third_party/blink/renderer/modules/payments/payment_completer.h"
+#include "third_party/blink/renderer/modules/payments/payment_state_resolver.h"
#include "third_party/blink/renderer/modules/payments/payment_test_helper.h"
+#include "third_party/blink/renderer/modules/payments/payment_validation_errors.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
namespace blink {
namespace {
-class MockPaymentCompleter
- : public GarbageCollectedFinalized<MockPaymentCompleter>,
- public PaymentCompleter {
- USING_GARBAGE_COLLECTED_MIXIN(MockPaymentCompleter);
- WTF_MAKE_NONCOPYABLE(MockPaymentCompleter);
+class MockPaymentStateResolver final
+ : public GarbageCollectedFinalized<MockPaymentStateResolver>,
+ public PaymentStateResolver {
+ USING_GARBAGE_COLLECTED_MIXIN(MockPaymentStateResolver);
+ WTF_MAKE_NONCOPYABLE(MockPaymentStateResolver);
public:
- MockPaymentCompleter() {
+ MockPaymentStateResolver() {
ON_CALL(*this, Complete(testing::_, testing::_))
.WillByDefault(testing::ReturnPointee(&dummy_promise_));
}
- ~MockPaymentCompleter() override = default;
+ ~MockPaymentStateResolver() override = default;
MOCK_METHOD2(Complete, ScriptPromise(ScriptState*, PaymentComplete result));
+ MOCK_METHOD2(Retry,
+ ScriptPromise(ScriptState*,
+ const PaymentValidationErrors& errorFields));
void Trace(blink::Visitor* visitor) override {}
@@ -52,7 +56,7 @@ TEST(PaymentResponseTest, DataCopiedOver) {
input->payer_name = "Jon Doe";
input->payer_email = "abc@gmail.com";
input->payer_phone = "0123";
- MockPaymentCompleter* complete_callback = new MockPaymentCompleter;
+ MockPaymentStateResolver* complete_callback = new MockPaymentStateResolver;
PaymentResponse* output =
new PaymentResponse(std::move(input), nullptr, complete_callback, "id");
@@ -84,7 +88,7 @@ TEST(PaymentResponseTest, PaymentResponseDetailsJSONObject) {
payments::mojom::blink::PaymentResponsePtr input =
BuildPaymentResponseForTest();
input->stringified_details = "transactionId";
- MockPaymentCompleter* complete_callback = new MockPaymentCompleter;
+ MockPaymentStateResolver* complete_callback = new MockPaymentStateResolver;
PaymentResponse* output =
new PaymentResponse(std::move(input), nullptr, complete_callback, "id");
@@ -100,12 +104,12 @@ TEST(PaymentResponseTest, CompleteCalledWithSuccess) {
BuildPaymentResponseForTest();
input->method_name = "foo";
input->stringified_details = "{\"transactionId\": 123}";
- MockPaymentCompleter* complete_callback = new MockPaymentCompleter;
+ MockPaymentStateResolver* complete_callback = new MockPaymentStateResolver;
PaymentResponse* output =
new PaymentResponse(std::move(input), nullptr, complete_callback, "id");
EXPECT_CALL(*complete_callback,
- Complete(scope.GetScriptState(), PaymentCompleter::kSuccess));
+ Complete(scope.GetScriptState(), PaymentStateResolver::kSuccess));
output->complete(scope.GetScriptState(), "success");
}
@@ -116,12 +120,12 @@ TEST(PaymentResponseTest, CompleteCalledWithFailure) {
BuildPaymentResponseForTest();
input->method_name = "foo";
input->stringified_details = "{\"transactionId\": 123}";
- MockPaymentCompleter* complete_callback = new MockPaymentCompleter;
+ MockPaymentStateResolver* complete_callback = new MockPaymentStateResolver;
PaymentResponse* output =
new PaymentResponse(std::move(input), nullptr, complete_callback, "id");
EXPECT_CALL(*complete_callback,
- Complete(scope.GetScriptState(), PaymentCompleter::kFail));
+ Complete(scope.GetScriptState(), PaymentStateResolver::kFail));
output->complete(scope.GetScriptState(), "fail");
}
@@ -146,12 +150,12 @@ TEST(PaymentResponseTest, JSONSerializerTest) {
PaymentAddress* address =
new PaymentAddress(std::move(input->shipping_address));
- PaymentResponse* output = new PaymentResponse(std::move(input), address,
- new MockPaymentCompleter, "id");
+ PaymentResponse* output = new PaymentResponse(
+ std::move(input), address, new MockPaymentStateResolver, "id");
ScriptValue json_object = output->toJSONForBinding(scope.GetScriptState());
EXPECT_TRUE(json_object.IsObject());
- String json_string = V8StringToWebCoreString<String>(
+ String json_string = ToBlinkString<String>(
v8::JSON::Stringify(scope.GetContext(),
json_object.V8Value().As<v8::Object>())
.ToLocalChecked(),
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_state_resolver.h b/chromium/third_party/blink/renderer/modules/payments/payment_state_resolver.h
new file mode 100644
index 00000000000..5cded1ec7fd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_state_resolver.h
@@ -0,0 +1,30 @@
+// 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_MODULES_PAYMENTS_PAYMENT_STATE_RESOLVER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_PAYMENT_STATE_RESOLVER_H_
+
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+
+namespace blink {
+
+class PaymentValidationErrors;
+class ScriptState;
+
+class MODULES_EXPORT PaymentStateResolver : public GarbageCollectedMixin {
+ public:
+ enum PaymentComplete { kFail, kSuccess, kUnknown };
+
+ virtual ScriptPromise Complete(ScriptState*, PaymentComplete result) = 0;
+ virtual ScriptPromise Retry(ScriptState*, const PaymentValidationErrors&) = 0;
+
+ protected:
+ virtual ~PaymentStateResolver() = default;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_PAYMENT_STATE_RESOLVER_H_
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_test_helper.cc b/chromium/third_party/blink/renderer/modules/payments/payment_test_helper.cc
index d778b2c52d8..01b16898ce4 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_test_helper.cc
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_test_helper.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/modules/payments/payment_method_data.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
namespace blink {
namespace {
@@ -127,9 +128,7 @@ PaymentDetailsModifier BuildPaymentDetailsModifierForTest(
item = BuildPaymentItemForTest();
PaymentDetailsModifier modifier;
- StringOrStringSequence supportedMethods;
- supportedMethods.SetStringSequence(Vector<String>(1, "foo"));
- modifier.setSupportedMethods(supportedMethods);
+ modifier.setSupportedMethod("foo");
modifier.setTotal(total);
modifier.setAdditionalDisplayItems(HeapVector<PaymentItem>(1, item));
return modifier;
@@ -185,9 +184,7 @@ PaymentDetailsUpdate BuildPaymentDetailsErrorMsgForTest(
HeapVector<PaymentMethodData> BuildPaymentMethodDataForTest() {
HeapVector<PaymentMethodData> method_data(1, PaymentMethodData());
- StringOrStringSequence supportedMethods;
- supportedMethods.SetStringSequence(Vector<String>(1, "foo"));
- method_data[0].setSupportedMethods(supportedMethods);
+ method_data[0].setSupportedMethod("foo");
return method_data;
}
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_test_helper.h b/chromium/third_party/blink/renderer/modules/payments/payment_test_helper.h
index 2d66bccdf1c..ddd5662db91 100644
--- a/chromium/third_party/blink/renderer/modules/payments/payment_test_helper.h
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_test_helper.h
@@ -108,7 +108,7 @@ class PaymentRequestMockFunctionScope {
String* value_;
};
- ScriptState* script_state_;
+ Member<ScriptState> script_state_;
Vector<Persistent<MockFunction>> mock_functions_;
};
diff --git a/chromium/third_party/blink/renderer/modules/payments/payment_validation_errors.idl b/chromium/third_party/blink/renderer/modules/payments/payment_validation_errors.idl
new file mode 100644
index 00000000000..d25f288226b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/payments/payment_validation_errors.idl
@@ -0,0 +1,10 @@
+// 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.
+
+// https://w3c.github.io/payment-request/#dom-paymentvalidationerrors
+
+dictionary PaymentValidationErrors {
+ PayerErrorFields payer;
+ AddressErrors shippingAddress;
+};
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/BUILD.gn b/chromium/third_party/blink/renderer/modules/peerconnection/BUILD.gn
index 990592d8b28..924ebf1e8a0 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/BUILD.gn
@@ -32,6 +32,8 @@ blink_modules_sources("peerconnection") {
"rtc_rtp_receiver.h",
"rtc_rtp_sender.cc",
"rtc_rtp_sender.h",
+ "rtc_rtp_transceiver.cc",
+ "rtc_rtp_transceiver.h",
"rtc_session_description.cc",
"rtc_session_description.h",
"rtc_session_description_request_impl.cc",
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
index 623b2b6bec7..b68c03908dc 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
@@ -30,28 +30,28 @@
#include "base/memory/ptr_util.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_rtc_peer_connection_handler.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#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/fileapi/blob.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
static void ThrowNotOpenException(ExceptionState& exception_state) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"RTCDataChannel.readyState is not 'open'");
}
static void ThrowCouldNotSendDataException(ExceptionState& exception_state) {
- exception_state.ThrowDOMException(kNetworkError, "Could not send data");
+ exception_state.ThrowDOMException(DOMExceptionCode::kNetworkError,
+ "Could not send data");
}
static void ThrowNoBlobSupportException(ExceptionState& exception_state) {
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"Blob support not implemented yet");
}
@@ -74,7 +74,7 @@ RTCDataChannel* RTCDataChannel::Create(
std::unique_ptr<WebRTCDataChannelHandler> handler =
base::WrapUnique(peer_connection_handler->CreateDataChannel(label, init));
if (!handler) {
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"RTCDataChannel is not supported");
return nullptr;
}
@@ -193,7 +193,7 @@ void RTCDataChannel::setBinaryType(const String& binary_type,
else if (binary_type == "arraybuffer")
binary_type_ = kBinaryTypeArrayBuffer;
else
- exception_state.ThrowDOMException(kTypeMismatchError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kTypeMismatchError,
"Unknown binary type : " + binary_type);
}
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_init.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_init.idl
index 6ecbe841598..c699b0cd03e 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_init.idl
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_init.idl
@@ -6,9 +6,11 @@
dictionary RTCDataChannelInit {
boolean ordered = true;
- // TODO(guidou): Rename |maxRetransmitTime| to |maxPacketLifeTime|.
- // https://crbug.com/696681
+ // TODO(crbug.com/696681): Deprecate maxRetransmitTime in favor of
+ // maxPacketLifeTime (they're the same thing, maxRetransmitTime is just the
+ // older name)
unsigned short maxRetransmitTime;
+ unsigned short maxPacketLifeTime;
unsigned short maxRetransmits;
USVString protocol = "";
boolean negotiated = false;
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_test.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_test.cc
index 65818137d23..5e13deab339 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_test.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_data_channel_test.cc
@@ -11,11 +11,11 @@
#include "base/memory/scoped_refptr.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_rtc_data_channel_handler.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#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/testing/null_execution_context.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.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/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.cc
index 51a427d21c5..0e47b72215f 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.cc
@@ -31,12 +31,10 @@
#include "third_party/blink/public/platform/web_media_stream_track.h"
#include "third_party/blink/public/platform/web_rtc_dtmf_sender_handler.h"
#include "third_party/blink/public/platform/web_rtc_peer_connection_handler.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_track.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_dtmf_tone_change_event.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -59,9 +57,6 @@ RTCDTMFSender* RTCDTMFSender::Create(
RTCDTMFSender::RTCDTMFSender(ExecutionContext* context,
std::unique_ptr<WebRTCDTMFSenderHandler> handler)
: ContextLifecycleObserver(context),
- track_(nullptr),
- duration_(kDefaultToneDurationMs),
- inter_tone_gap_(kDefaultInterToneGapMs),
handler_(std::move(handler)),
stopped_(false),
scheduled_event_timer_(context->GetTaskRunner(TaskType::kNetworking),
@@ -83,14 +78,6 @@ bool RTCDTMFSender::canInsertDTMF() const {
return handler_->CanInsertDTMF();
}
-MediaStreamTrack* RTCDTMFSender::track() const {
- return track_.Get();
-}
-
-void RTCDTMFSender::SetTrack(MediaStreamTrack* track) {
- track_ = track;
-}
-
String RTCDTMFSender::toneBuffer() const {
return handler_->CurrentToneBuffer();
}
@@ -115,7 +102,7 @@ void RTCDTMFSender::insertDTMF(const String& tones,
// TODO(hta): Add check on transceiver's "stopped" and "currentDirection"
// attributes
if (!canInsertDTMF()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The 'canInsertDTMF' attribute is false: "
"this sender cannot send DTMF.");
return;
@@ -123,7 +110,7 @@ void RTCDTMFSender::insertDTMF(const String& tones,
// Spec: Throw on illegal characters
if (strspn(tones.Ascii().data(), "0123456789abcdABCD#*,") != tones.length()) {
exception_state.ThrowDOMException(
- kInvalidCharacterError,
+ DOMExceptionCode::kInvalidCharacterError,
"Illegal characters in InsertDTMF tone argument");
return;
}
@@ -135,12 +122,13 @@ void RTCDTMFSender::insertDTMF(const String& tones,
inter_tone_gap = std::max(inter_tone_gap, kMinInterToneGapMs);
inter_tone_gap = std::min(inter_tone_gap, kMaxInterToneGapMs);
- duration_ = duration;
- inter_tone_gap_ = inter_tone_gap;
// Spec: a-d should be represented in the tone buffer as A-D
- if (!handler_->InsertDTMF(tones.UpperASCII(), duration_, inter_tone_gap_))
+ if (!handler_->InsertDTMF(tones.UpperASCII(), duration, inter_tone_gap)) {
exception_state.ThrowDOMException(
- kSyntaxError, "Could not send provided tones, '" + tones + "'.");
+ DOMExceptionCode::kSyntaxError,
+ "Could not send provided tones, '" + tones + "'.");
+ return;
+ }
}
void RTCDTMFSender::DidPlayTone(const WebString& tone) {
@@ -180,7 +168,6 @@ void RTCDTMFSender::ScheduledEventTimerFired(TimerBase*) {
}
void RTCDTMFSender::Trace(blink::Visitor* visitor) {
- visitor->Trace(track_);
visitor->Trace(scheduled_events_);
EventTargetWithInlineData::Trace(visitor);
ContextLifecycleObserver::Trace(visitor);
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.h b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.h
index e12e337efc5..c356c957487 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.h
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.h
@@ -35,7 +35,6 @@
namespace blink {
class ExceptionState;
-class MediaStreamTrack;
class WebRTCDTMFSenderHandler;
class RTCDTMFSender final : public EventTargetWithInlineData,
@@ -51,11 +50,7 @@ class RTCDTMFSender final : public EventTargetWithInlineData,
~RTCDTMFSender() override;
bool canInsertDTMF() const;
- MediaStreamTrack* track() const;
- void SetTrack(MediaStreamTrack*);
String toneBuffer() const;
- int duration() const { return duration_; }
- int interToneGap() const { return inter_tone_gap_; }
void insertDTMF(const String& tones, ExceptionState&);
void insertDTMF(const String& tones, int duration, ExceptionState&);
@@ -86,10 +81,6 @@ class RTCDTMFSender final : public EventTargetWithInlineData,
// WebRTCDTMFSenderHandlerClient
void DidPlayTone(const WebString&) override;
- Member<MediaStreamTrack> track_;
- int duration_;
- int inter_tone_gap_;
-
std::unique_ptr<WebRTCDTMFSenderHandler> handler_;
bool stopped_;
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.idl
index 70aaa9a12b3..30ca23d4169 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.idl
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.idl
@@ -23,14 +23,11 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-interface RTCDTMFSender : EventTarget {
- readonly attribute boolean canInsertDTMF;
- [Measure] readonly attribute MediaStreamTrack track;
- readonly attribute DOMString toneBuffer;
- [Measure] readonly attribute long duration;
- [Measure] readonly attribute long interToneGap;
+// http://w3c.github.io/webrtc-pc/#rtcdtmfsender
+interface RTCDTMFSender : EventTarget {
[RaisesException] void insertDTMF(DOMString tones, optional long duration, optional long interToneGap);
-
attribute EventHandler ontonechange;
+ readonly attribute boolean canInsertDTMF;
+ readonly attribute DOMString toneBuffer;
};
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_error_util.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_error_util.cc
index b92fa22bc06..b329909bed3 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_error_util.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_error_util.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/peerconnection/rtc_error_util.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -15,18 +16,23 @@ DOMException* CreateDOMExceptionFromRTCError(const webrtc::RTCError& error) {
NOTREACHED();
break;
case webrtc::RTCErrorType::SYNTAX_ERROR:
- return DOMException::Create(kSyntaxError, error.message());
+ return DOMException::Create(DOMExceptionCode::kSyntaxError,
+ error.message());
case webrtc::RTCErrorType::INVALID_MODIFICATION:
- return DOMException::Create(kInvalidModificationError, error.message());
+ return DOMException::Create(DOMExceptionCode::kInvalidModificationError,
+ error.message());
case webrtc::RTCErrorType::NETWORK_ERROR:
- return DOMException::Create(kNetworkError, error.message());
+ return DOMException::Create(DOMExceptionCode::kNetworkError,
+ error.message());
case webrtc::RTCErrorType::UNSUPPORTED_PARAMETER:
case webrtc::RTCErrorType::UNSUPPORTED_OPERATION:
case webrtc::RTCErrorType::RESOURCE_EXHAUSTED:
case webrtc::RTCErrorType::INTERNAL_ERROR:
- return DOMException::Create(kOperationError, error.message());
+ return DOMException::Create(DOMExceptionCode::kOperationError,
+ error.message());
case webrtc::RTCErrorType::INVALID_STATE:
- return DOMException::Create(kInvalidStateError, error.message());
+ return DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ error.message());
case webrtc::RTCErrorType::INVALID_PARAMETER:
// One use of this value is to signal invalid SDP syntax.
// According to spec, this should return an RTCError with name
@@ -34,17 +40,71 @@ DOMException* CreateDOMExceptionFromRTCError(const webrtc::RTCError& error) {
// "sdpLineNumber" set to indicate the line where the error
// occured.
// TODO(https://crbug.com/821806): Implement the RTCError object.
- return DOMException::Create(kInvalidAccessError, error.message());
+ return DOMException::Create(DOMExceptionCode::kInvalidAccessError,
+ error.message());
case webrtc::RTCErrorType::INVALID_RANGE:
- return DOMException::Create(kV8RangeError, error.message());
+ // INVALID_RANGE should create a RangeError, which isn't a DOMException
default:
LOG(ERROR) << "Got unhandled RTC error "
<< static_cast<int>(error.type());
- // No DOM equivalent. Needs per-error evaluation.
+ // No DOM equivalent.
+ // Needs per-error evaluation or use ThrowExceptionFromRTCError.
NOTREACHED();
break;
}
NOTREACHED();
return nullptr;
}
+
+void ThrowExceptionFromRTCError(const webrtc::RTCError& error,
+ ExceptionState& exception_state) {
+ switch (error.type()) {
+ case webrtc::RTCErrorType::NONE:
+ // This should never happen.
+ NOTREACHED();
+ break;
+ case webrtc::RTCErrorType::SYNTAX_ERROR:
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
+ error.message());
+ return;
+ case webrtc::RTCErrorType::INVALID_MODIFICATION:
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidModificationError, error.message());
+ return;
+ case webrtc::RTCErrorType::NETWORK_ERROR:
+ exception_state.ThrowDOMException(DOMExceptionCode::kNetworkError,
+ error.message());
+ return;
+ case webrtc::RTCErrorType::UNSUPPORTED_PARAMETER:
+ case webrtc::RTCErrorType::UNSUPPORTED_OPERATION:
+ case webrtc::RTCErrorType::RESOURCE_EXHAUSTED:
+ case webrtc::RTCErrorType::INTERNAL_ERROR:
+ exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
+ error.message());
+ return;
+ case webrtc::RTCErrorType::INVALID_STATE:
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ error.message());
+ return;
+ case webrtc::RTCErrorType::INVALID_PARAMETER:
+ // One use of this value is to signal invalid SDP syntax.
+ // According to spec, this should return an RTCError with name
+ // "RTCError" and detail "sdp-syntax-error", with
+ // "sdpLineNumber" set to indicate the line where the error
+ // occured.
+ // TODO(https://crbug.com/821806): Implement the RTCError object.
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
+ error.message());
+ return;
+ case webrtc::RTCErrorType::INVALID_RANGE:
+ exception_state.ThrowRangeError(error.message());
+ return;
+ default:
+ LOG(ERROR) << "Got unhandled RTC error "
+ << static_cast<int>(error.type());
+ NOTREACHED();
+ break;
+ }
+ NOTREACHED();
+}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_error_util.h b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_error_util.h
index a94c38e4c81..0fd2dce39a5 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_error_util.h
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_error_util.h
@@ -11,9 +11,12 @@
namespace blink {
class DOMException;
+class ExceptionState;
DOMException* CreateDOMExceptionFromRTCError(const webrtc::RTCError&);
+void ThrowExceptionFromRTCError(const webrtc::RTCError&, ExceptionState&);
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_ERROR_UTIL_H_
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_ice_candidate.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_ice_candidate.cc
index 762dc8e1b56..36cd0a5f0e1 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_ice_candidate.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_ice_candidate.cc
@@ -30,14 +30,13 @@
#include "third_party/blink/renderer/modules/peerconnection/rtc_ice_candidate.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_ice_candidate_init.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -47,8 +46,9 @@ RTCIceCandidate* RTCIceCandidate::Create(
ExceptionState& exception_state) {
if (!candidate_init.hasCandidate() || !candidate_init.candidate().length()) {
exception_state.ThrowDOMException(
- kTypeMismatchError, ExceptionMessages::IncorrectPropertyType(
- "candidate", "is not a string, or is empty."));
+ DOMExceptionCode::kTypeMismatchError,
+ ExceptionMessages::IncorrectPropertyType(
+ "candidate", "is not a string, or is empty."));
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
index 8b58d4b5d73..1506e6e6346 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
@@ -54,11 +54,10 @@
#include "third_party/blink/public/platform/web_rtc_session_description_request.h"
#include "third_party/blink/public/platform/web_rtc_stats_request.h"
#include "third_party/blink/public/platform/web_rtc_void_request.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_void_function.h"
+#include "third_party/blink/renderer/bindings/modules/v8/media_stream_track_or_string.h"
#include "third_party/blink/renderer/bindings/modules/v8/rtc_ice_candidate_init_or_rtc_ice_candidate.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_media_stream_track.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_certificate.h"
@@ -68,7 +67,6 @@
#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/dom/dom_time_stamp.h"
-#include "third_party/blink/renderer/core/dom/exception_code.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/deprecation.h"
@@ -87,11 +85,14 @@
#include "third_party/blink/renderer/modules/peerconnection/rtc_data_channel_event.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_data_channel_init.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_error_util.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_ice_server.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_offer_options.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_ice_event.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_init.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_session_description.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_session_description_init.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_session_description_request_impl.h"
@@ -103,6 +104,7 @@
#include "third_party/blink/renderer/modules/peerconnection/rtc_void_request_promise_impl.h"
#include "third_party/blink/renderer/modules/peerconnection/testing/internals_rtc_peer_connection.h"
#include "third_party/blink/renderer/modules/peerconnection/web_rtc_stats_report_callback_resolver.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/microtask.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
@@ -120,15 +122,20 @@ const char kSignalingStateClosedMessage[] =
"The RTCPeerConnection's signalingState is 'closed'.";
const char kModifiedSdpMessage[] =
"The SDP does not match the previously generated SDP for this type";
+const char kOnlySupportedInUnifiedPlanMessage[] =
+ "This operation is only supported in 'unified-plan'. 'unified-plan' will "
+ "become the default behavior in the future, but it is currently "
+ "experimental. To try it out, construct the RTCPeerConnection with "
+ "sdpSemantics:'unified-plan' present in the RTCConfiguration argument.";
// The maximum number of PeerConnections that can exist simultaneously.
const long kMaxPeerConnections = 500;
bool ThrowExceptionIfSignalingStateClosed(
- RTCPeerConnection::SignalingState state,
+ webrtc::PeerConnectionInterface::SignalingState state,
ExceptionState& exception_state) {
- if (state == RTCPeerConnection::kSignalingStateClosed) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ if (state == webrtc::PeerConnectionInterface::SignalingState::kClosed) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
kSignalingStateClosedMessage);
return true;
}
@@ -147,14 +154,15 @@ void AsyncCallErrorCallback(V8RTCPeerConnectionErrorCallback* error_callback,
}
bool CallErrorCallbackIfSignalingStateClosed(
- RTCPeerConnection::SignalingState state,
+ webrtc::PeerConnectionInterface::SignalingState state,
V8RTCPeerConnectionErrorCallback* error_callback) {
- if (state == RTCPeerConnection::kSignalingStateClosed) {
- if (error_callback)
+ if (state == webrtc::PeerConnectionInterface::SignalingState::kClosed) {
+ if (error_callback) {
AsyncCallErrorCallback(
- error_callback, DOMException::Create(kInvalidStateError,
- kSignalingStateClosedMessage));
-
+ error_callback,
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kSignalingStateClosedMessage));
+ }
return true;
}
@@ -329,23 +337,26 @@ WebRTCConfiguration ParseConfiguration(ExecutionContext* context,
KURL url(NullURL(), url_string);
if (!url.IsValid()) {
exception_state.ThrowDOMException(
- kSyntaxError, "'" + url_string + "' is not a valid URL.");
+ DOMExceptionCode::kSyntaxError,
+ "'" + url_string + "' is not a valid URL.");
return WebRTCConfiguration();
}
if (!(url.ProtocolIs("turn") || url.ProtocolIs("turns") ||
url.ProtocolIs("stun"))) {
exception_state.ThrowDOMException(
- kSyntaxError, "'" + url.Protocol() +
- "' is not one of the supported URL schemes "
- "'stun', 'turn' or 'turns'.");
+ DOMExceptionCode::kSyntaxError,
+ "'" + url.Protocol() +
+ "' is not one of the supported URL schemes "
+ "'stun', 'turn' or 'turns'.");
return WebRTCConfiguration();
}
if ((url.ProtocolIs("turn") || url.ProtocolIs("turns")) &&
(username.IsNull() || credential.IsNull())) {
- exception_state.ThrowDOMException(kInvalidAccessError,
- "Both username and credential are "
- "required when the URL scheme is "
- "\"turn\" or \"turns\".");
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidAccessError,
+ "Both username and credential are "
+ "required when the URL scheme is "
+ "\"turn\" or \"turns\".");
}
ice_servers.push_back(WebRTCIceServer{url, username, credential});
}
@@ -484,11 +495,6 @@ RTCPeerConnection* RTCPeerConnection::Create(
ParseConfiguration(context, rtc_configuration, exception_state);
if (exception_state.HadException())
return nullptr;
- // Override default SDP semantics if RuntimeEnabled=RTCUnifiedPlanByDefault.
- if (!rtc_configuration.hasSdpSemantics() &&
- RuntimeEnabledFeatures::RTCUnifiedPlanByDefaultEnabled()) {
- configuration.sdp_semantics = WebRTCSdpSemantics::kUnifiedPlan;
- }
// Make sure no certificates have expired.
if (configuration.certificates.size() > 0) {
@@ -497,7 +503,7 @@ RTCPeerConnection* RTCPeerConnection::Create(
configuration.certificates) {
DOMTimeStamp expires = certificate->Expires();
if (expires <= now) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"Expired certificate(s).");
return nullptr;
}
@@ -513,7 +519,7 @@ RTCPeerConnection* RTCPeerConnection::Create(
}
RTCPeerConnection* peer_connection = new RTCPeerConnection(
- context, configuration, constraints, exception_state);
+ context, std::move(configuration), constraints, exception_state);
peer_connection->PauseIfNeeded();
if (exception_state.HadException())
return nullptr;
@@ -522,11 +528,12 @@ RTCPeerConnection* RTCPeerConnection::Create(
}
RTCPeerConnection::RTCPeerConnection(ExecutionContext* context,
- const WebRTCConfiguration& configuration,
+ WebRTCConfiguration configuration,
WebMediaConstraints constraints,
ExceptionState& exception_state)
: PausableObject(context),
- signaling_state_(kSignalingStateStable),
+ signaling_state_(
+ webrtc::PeerConnectionInterface::SignalingState::kStable),
ice_gathering_state_(kICEGatheringStateNew),
ice_connection_state_(kICEConnectionStateNew),
// WebRTC spec specifies kNetworking as task source.
@@ -541,6 +548,24 @@ RTCPeerConnection::RTCPeerConnection(ExecutionContext* context,
closed_(false),
has_data_channels_(false),
sdp_semantics_(configuration.sdp_semantics) {
+ // The original SDP semantics value is the value passed in by the caller,
+ // which if not specified has the value "kDefault". For |sdp_semantics_| this
+ // is translated to the actual SDP semantics used ("kPlanB" or
+ // "kUnifiedPlan"), but for the sake of UMA use counters it is of interest to
+ // know if the caller did not explicitly set it.
+ WebRTCSdpSemantics original_sdp_semantics_value = sdp_semantics_;
+ if (sdp_semantics_ == WebRTCSdpSemantics::kDefault) {
+ if (!RuntimeEnabledFeatures::RTCUnifiedPlanByDefaultEnabled()) {
+ // By default: The default SDP semantics is: "kPlanB".
+ sdp_semantics_ = configuration.sdp_semantics = WebRTCSdpSemantics::kPlanB;
+ } else {
+ // Override default SDP semantics to "kUnifiedPlan" with
+ // RuntimeEnabled=RTCUnifiedPlanByDefault.
+ sdp_semantics_ = configuration.sdp_semantics =
+ WebRTCSdpSemantics::kUnifiedPlan;
+ }
+ }
+
Document* document = ToDocument(GetExecutionContext());
InstanceCounters::IncrementCounter(
@@ -551,7 +576,7 @@ RTCPeerConnection::RTCPeerConnection(ExecutionContext* context,
InstanceCounters::kRTCPeerConnectionCounter) > kMaxPeerConnections) {
closed_ = true;
stopped_ = true;
- exception_state.ThrowDOMException(kUnknownError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kUnknownError,
"Cannot create so many PeerConnections");
return;
}
@@ -559,7 +584,7 @@ RTCPeerConnection::RTCPeerConnection(ExecutionContext* context,
closed_ = true;
stopped_ = true;
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"PeerConnections may not be created in detached documents.");
return;
}
@@ -569,7 +594,7 @@ RTCPeerConnection::RTCPeerConnection(ExecutionContext* context,
if (!peer_handler_) {
closed_ = true;
stopped_ = true;
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"No PeerConnection handler can be "
"created, perhaps WebRTC is disabled?");
return;
@@ -578,11 +603,13 @@ RTCPeerConnection::RTCPeerConnection(ExecutionContext* context,
document->GetFrame()->Client()->DispatchWillStartUsingPeerConnectionHandler(
peer_handler_.get());
- if (!peer_handler_->Initialize(configuration, constraints)) {
+ if (!peer_handler_->Initialize(configuration, constraints,
+ original_sdp_semantics_value)) {
closed_ = true;
stopped_ = true;
exception_state.ThrowDOMException(
- kNotSupportedError, "Failed to initialize native PeerConnection.");
+ DOMExceptionCode::kNotSupportedError,
+ "Failed to initialize native PeerConnection.");
return;
}
@@ -609,15 +636,18 @@ void RTCPeerConnection::Dispose() {
ScriptPromise RTCPeerConnection::createOffer(ScriptState* script_state,
const RTCOfferOptions& options) {
- if (signaling_state_ == kSignalingStateClosed)
+ if (signaling_state_ ==
+ webrtc::PeerConnectionInterface::SignalingState::kClosed) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, kSignalingStateClosedMessage));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kSignalingStateClosedMessage));
+ }
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
RTCSessionDescriptionRequest* request =
- RTCSessionDescriptionRequestPromiseImpl::Create(this, resolver);
+ RTCSessionDescriptionRequestPromiseImpl::Create(
+ this, resolver, "RTCPeerConnection", "createOffer");
if (options.hasOfferToReceiveAudio() || options.hasOfferToReceiveVideo()) {
ExecutionContext* context = ExecutionContext::From(script_state);
UseCounter::Count(
@@ -670,8 +700,9 @@ ScriptPromise RTCPeerConnection::createOffer(
// WebIDL.
if (media_error_state.CanGenerateException()) {
String error_msg = media_error_state.GetErrorMessage();
- AsyncCallErrorCallback(error_callback,
- DOMException::Create(kOperationError, error_msg));
+ AsyncCallErrorCallback(
+ error_callback,
+ DOMException::Create(DOMExceptionCode::kOperationError, error_msg));
return ScriptPromise::CastUndefined(script_state);
}
@@ -691,15 +722,18 @@ ScriptPromise RTCPeerConnection::createOffer(
ScriptPromise RTCPeerConnection::createAnswer(ScriptState* script_state,
const RTCAnswerOptions& options) {
- if (signaling_state_ == kSignalingStateClosed)
+ if (signaling_state_ ==
+ webrtc::PeerConnectionInterface::SignalingState::kClosed) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, kSignalingStateClosedMessage));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kSignalingStateClosedMessage));
+ }
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
RTCSessionDescriptionRequest* request =
- RTCSessionDescriptionRequestPromiseImpl::Create(this, resolver);
+ RTCSessionDescriptionRequestPromiseImpl::Create(
+ this, resolver, "RTCPeerConnection", "createAnswer");
peer_handler_->CreateAnswer(request, ConvertToWebRTCAnswerOptions(options));
return promise;
}
@@ -733,8 +767,9 @@ ScriptPromise RTCPeerConnection::createAnswer(
// WebIDL.
if (media_error_state.CanGenerateException()) {
String error_msg = media_error_state.GetErrorMessage();
- AsyncCallErrorCallback(error_callback,
- DOMException::Create(kOperationError, error_msg));
+ AsyncCallErrorCallback(
+ error_callback,
+ DOMException::Create(DOMExceptionCode::kOperationError, error_msg));
return ScriptPromise::CastUndefined(script_state);
}
@@ -749,8 +784,9 @@ DOMException* RTCPeerConnection::checkSdpForStateErrors(
ExecutionContext* context,
const RTCSessionDescriptionInit& session_description_init,
String* sdp) {
- if (signaling_state_ == kSignalingStateClosed) {
- return DOMException::Create(kInvalidStateError,
+ if (signaling_state_ ==
+ webrtc::PeerConnectionInterface::SignalingState::kClosed) {
+ return DOMException::Create(DOMExceptionCode::kInvalidStateError,
kSignalingStateClosedMessage);
}
@@ -760,7 +796,7 @@ DOMException* RTCPeerConnection::checkSdpForStateErrors(
*sdp = last_offer_;
} else if (session_description_init.sdp() != last_offer_) {
if (FingerprintMismatch(last_offer_, *sdp)) {
- return DOMException::Create(kInvalidModificationError,
+ return DOMException::Create(DOMExceptionCode::kInvalidModificationError,
kModifiedSdpMessage);
} else {
UseCounter::Count(context, WebFeature::kRTCLocalSdpModification);
@@ -774,7 +810,7 @@ DOMException* RTCPeerConnection::checkSdpForStateErrors(
*sdp = last_answer_;
} else if (session_description_init.sdp() != last_answer_) {
if (FingerprintMismatch(last_answer_, *sdp)) {
- return DOMException::Create(kInvalidModificationError,
+ return DOMException::Create(DOMExceptionCode::kInvalidModificationError,
kModifiedSdpMessage);
} else {
UseCounter::Count(context, WebFeature::kRTCLocalSdpModification);
@@ -797,7 +833,8 @@ ScriptPromise RTCPeerConnection::setLocalDescription(
}
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
- RTCVoidRequest* request = RTCVoidRequestPromiseImpl::Create(this, resolver);
+ RTCVoidRequest* request = RTCVoidRequestPromiseImpl::Create(
+ this, resolver, "RTCPeerConnection", "setLocalDescription");
peer_handler_->SetLocalDescription(
request, WebRTCSessionDescription(session_description_init.type(), sdp));
return promise;
@@ -855,14 +892,17 @@ RTCSessionDescription* RTCPeerConnection::localDescription() {
ScriptPromise RTCPeerConnection::setRemoteDescription(
ScriptState* script_state,
const RTCSessionDescriptionInit& session_description_init) {
- if (signaling_state_ == kSignalingStateClosed)
+ if (signaling_state_ ==
+ webrtc::PeerConnectionInterface::SignalingState::kClosed) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, kSignalingStateClosedMessage));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kSignalingStateClosedMessage));
+ }
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
- RTCVoidRequest* request = RTCVoidRequestPromiseImpl::Create(this, resolver);
+ RTCVoidRequest* request = RTCVoidRequestPromiseImpl::Create(
+ this, resolver, "RTCPeerConnection", "setRemoteDescription");
peer_handler_->SetRemoteDescription(
request, WebRTCSessionDescription(session_description_init.type(),
session_description_init.sdp()));
@@ -921,6 +961,12 @@ void RTCPeerConnection::setConfiguration(
WebRTCConfiguration configuration = ParseConfiguration(
ExecutionContext::From(script_state), rtc_configuration, exception_state);
+ // Overwrite "kDefault" with |sdp_semantics_| as set in the constructor to
+ // avoid duplicate logic for interpreting the default and SetConfiguration()
+ // failing if different layers have different notions of default.
+ if (configuration.sdp_semantics == blink::WebRTCSdpSemantics::kDefault) {
+ configuration.sdp_semantics = sdp_semantics_;
+ }
if (exception_state.HadException())
return;
@@ -936,12 +982,12 @@ void RTCPeerConnection::setConfiguration(
// All errors besides InvalidModification should have been detected above.
if (error == webrtc::RTCErrorType::INVALID_MODIFICATION) {
exception_state.ThrowDOMException(
- kInvalidModificationError,
+ DOMExceptionCode::kInvalidModificationError,
"Attempted to modify the PeerConnection's "
"configuration in an unsupported way.");
} else {
exception_state.ThrowDOMException(
- kOperationError,
+ DOMExceptionCode::kOperationError,
"Could not update the PeerConnection with the given configuration.");
}
}
@@ -1011,8 +1057,9 @@ ScriptPromise RTCPeerConnection::generateCertificate(
WebRTCKeyParams::CreateRSA(modulus_length, public_exponent);
} else {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kNotSupportedError,
- unsupported_params_string));
+ script_state,
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ unsupported_params_string));
}
break;
case kWebCryptoAlgorithmIdEcdsa:
@@ -1023,16 +1070,18 @@ ScriptPromise RTCPeerConnection::generateCertificate(
key_params = WebRTCKeyParams::CreateECDSA(kWebRTCECCurveNistP256);
} else {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kNotSupportedError,
- unsupported_params_string));
+ script_state,
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ unsupported_params_string));
}
break;
default:
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kNotSupportedError,
- "The 1st argument provided is an "
- "AlgorithmIdentifier, but the "
- "algorithm is not supported."));
+ script_state,
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "The 1st argument provided is an "
+ "AlgorithmIdentifier, but the "
+ "algorithm is not supported."));
break;
}
DCHECK(key_params.has_value());
@@ -1044,8 +1093,8 @@ ScriptPromise RTCPeerConnection::generateCertificate(
// generator support these parameters?
if (!certificate_generator->IsSupportedKeyParams(key_params.value())) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kNotSupportedError, unsupported_params_string));
+ script_state, DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ unsupported_params_string));
}
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
@@ -1074,29 +1123,34 @@ ScriptPromise RTCPeerConnection::generateCertificate(
ScriptPromise RTCPeerConnection::addIceCandidate(
ScriptState* script_state,
- const RTCIceCandidateInitOrRTCIceCandidate& candidate) {
- if (signaling_state_ == kSignalingStateClosed)
+ const RTCIceCandidateInitOrRTCIceCandidate& candidate,
+ ExceptionState& exception_state) {
+ if (signaling_state_ ==
+ webrtc::PeerConnectionInterface::SignalingState::kClosed) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, kSignalingStateClosedMessage));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kSignalingStateClosedMessage));
+ }
- if (IsIceCandidateMissingSdp(candidate))
- return ScriptPromise::Reject(
- script_state,
- V8ThrowException::CreateTypeError(
- script_state->GetIsolate(),
- "Candidate missing values for both sdpMid and sdpMLineIndex"));
+ if (IsIceCandidateMissingSdp(candidate)) {
+ exception_state.ThrowTypeError(
+ "Candidate missing values for both sdpMid and sdpMLineIndex");
+ return ScriptPromise();
+ }
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
- RTCVoidRequest* request = RTCVoidRequestPromiseImpl::Create(this, resolver);
+ RTCVoidRequest* request = RTCVoidRequestPromiseImpl::Create(
+ this, resolver, "RTCPeerConnection", "addIceCandidate");
scoped_refptr<WebRTCICECandidate> web_candidate = ConvertToWebRTCIceCandidate(
ExecutionContext::From(script_state), candidate);
bool implemented =
peer_handler_->AddICECandidate(request, std::move(web_candidate));
- if (!implemented)
- resolver->Reject(DOMException::Create(
- kOperationError, "This operation could not be completed."));
+ if (!implemented) {
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kOperationError,
+ "This operation could not be completed."));
+ }
return promise;
}
@@ -1105,19 +1159,19 @@ ScriptPromise RTCPeerConnection::addIceCandidate(
ScriptState* script_state,
const RTCIceCandidateInitOrRTCIceCandidate& candidate,
V8VoidFunction* success_callback,
- V8RTCPeerConnectionErrorCallback* error_callback) {
+ V8RTCPeerConnectionErrorCallback* error_callback,
+ ExceptionState& exception_state) {
DCHECK(success_callback);
DCHECK(error_callback);
if (CallErrorCallbackIfSignalingStateClosed(signaling_state_, error_callback))
return ScriptPromise::CastUndefined(script_state);
- if (IsIceCandidateMissingSdp(candidate))
- return ScriptPromise::Reject(
- script_state,
- V8ThrowException::CreateTypeError(
- script_state->GetIsolate(),
- "Candidate missing values for both sdpMid and sdpMLineIndex"));
+ if (IsIceCandidateMissingSdp(candidate)) {
+ exception_state.ThrowTypeError(
+ "Candidate missing values for both sdpMid and sdpMLineIndex");
+ return ScriptPromise();
+ }
RTCVoidRequest* request = RTCVoidRequestImpl::Create(
GetExecutionContext(), this, success_callback, error_callback);
@@ -1128,7 +1182,7 @@ ScriptPromise RTCPeerConnection::addIceCandidate(
if (!implemented)
AsyncCallErrorCallback(
error_callback,
- DOMException::Create(kOperationError,
+ DOMException::Create(DOMExceptionCode::kOperationError,
"This operation could not be completed."));
return ScriptPromise::CastUndefined(script_state);
@@ -1136,17 +1190,17 @@ ScriptPromise RTCPeerConnection::addIceCandidate(
String RTCPeerConnection::signalingState() const {
switch (signaling_state_) {
- case kSignalingStateStable:
+ case webrtc::PeerConnectionInterface::SignalingState::kStable:
return "stable";
- case kSignalingStateHaveLocalOffer:
+ case webrtc::PeerConnectionInterface::SignalingState::kHaveLocalOffer:
return "have-local-offer";
- case kSignalingStateHaveRemoteOffer:
+ case webrtc::PeerConnectionInterface::SignalingState::kHaveRemoteOffer:
return "have-remote-offer";
- case kSignalingStateHaveLocalPrAnswer:
+ case webrtc::PeerConnectionInterface::SignalingState::kHaveLocalPrAnswer:
return "have-local-pranswer";
- case kSignalingStateHaveRemotePrAnswer:
+ case webrtc::PeerConnectionInterface::SignalingState::kHaveRemotePrAnswer:
return "have-remote-pranswer";
- case kSignalingStateClosed:
+ case webrtc::PeerConnectionInterface::SignalingState::kClosed:
return "closed";
}
@@ -1235,17 +1289,28 @@ void RTCPeerConnection::removeStream(MediaStream* stream,
}
String RTCPeerConnection::id(ScriptState* script_state) const {
- DCHECK(OriginTrials::rtcPeerConnectionIdEnabled(
+ DCHECK(OriginTrials::RtcPeerConnectionIdEnabled(
ExecutionContext::From(script_state)));
return peer_handler_->Id();
}
MediaStreamVector RTCPeerConnection::getLocalStreams() const {
MediaStreamVector local_streams;
- for (const auto& rtp_sender : getSenders()) {
- for (const auto& stream : rtp_sender->streams()) {
- if (!local_streams.Contains(stream))
- local_streams.push_back(stream);
+ if (sdp_semantics_ == WebRTCSdpSemantics::kPlanB) {
+ for (const auto& sender : rtp_senders_) {
+ for (const auto& stream : sender->streams()) {
+ if (!local_streams.Contains(stream))
+ local_streams.push_back(stream);
+ }
+ }
+ } else {
+ for (const auto& transceiver : transceivers_) {
+ if (!transceiver->DirectionHasSend())
+ continue;
+ for (const auto& stream : transceiver->sender()->streams()) {
+ if (!local_streams.Contains(stream))
+ local_streams.push_back(stream);
+ }
}
}
return local_streams;
@@ -1253,37 +1318,46 @@ MediaStreamVector RTCPeerConnection::getLocalStreams() const {
MediaStreamVector RTCPeerConnection::getRemoteStreams() const {
MediaStreamVector remote_streams;
- for (const auto& rtp_receiver : rtp_receivers_) {
- for (const auto& stream : rtp_receiver->streams()) {
- if (!remote_streams.Contains(stream))
- remote_streams.push_back(stream);
+ if (sdp_semantics_ == WebRTCSdpSemantics::kPlanB) {
+ for (const auto& receiver : rtp_receivers_) {
+ for (const auto& stream : receiver->streams()) {
+ if (!remote_streams.Contains(stream))
+ remote_streams.push_back(stream);
+ }
+ }
+ } else {
+ for (const auto& transceiver : transceivers_) {
+ if (!transceiver->DirectionHasRecv())
+ continue;
+ for (const auto& stream : transceiver->receiver()->streams()) {
+ if (!remote_streams.Contains(stream))
+ remote_streams.push_back(stream);
+ }
}
}
return remote_streams;
}
-MediaStream* RTCPeerConnection::getRemoteStream(
- MediaStreamDescriptor* descriptor) const {
+MediaStream* RTCPeerConnection::getRemoteStreamById(const WebString& id) const {
for (const auto& rtp_receiver : rtp_receivers_) {
for (const auto& stream : rtp_receiver->streams()) {
- if (stream->Descriptor() == descriptor)
+ if (static_cast<WebString>(stream->id()) == id) {
return stream;
+ }
}
}
return nullptr;
}
-size_t RTCPeerConnection::getRemoteStreamUsageCount(
- MediaStreamDescriptor* descriptor) const {
- size_t usage_count = 0;
+bool RTCPeerConnection::IsRemoteStream(MediaStream* stream) const {
for (const auto& receiver : rtp_receivers_) {
- WebVector<WebMediaStream> streams = receiver->web_receiver().Streams();
- for (const WebMediaStream& stream : streams) {
- if (stream == descriptor)
- ++usage_count;
+ for (const auto& receiver_stream : receiver->streams()) {
+ if (receiver_stream == stream) {
+ return true;
+ }
}
}
- return usage_count;
+ return false;
}
ScriptPromise RTCPeerConnection::getStats(
@@ -1319,7 +1393,7 @@ ScriptPromise RTCPeerConnection::getStats(
exception_state.ThrowTypeError(
"The argument provided as parameter 1 is neither a callback (function) "
"or selector (MediaStreamTrack or null).");
- return exception_state.Reject(script_state);
+ return ScriptPromise::Reject(script_state, exception_state);
}
ScriptPromise RTCPeerConnection::getStats(ScriptState* script_state,
@@ -1363,7 +1437,7 @@ ScriptPromise RTCPeerConnection::PromiseBasedGetStats(
LOG(ERROR) << "Internal error: peer_handler_ has been discarded";
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kOperationError,
+ DOMException::Create(DOMExceptionCode::kOperationError,
"Internal error: release in progress"));
}
ScriptPromiseResolver* resolver =
@@ -1394,14 +1468,14 @@ ScriptPromise RTCPeerConnection::PromiseBasedGetStats(
if (track_uses == 0u) {
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kInvalidAccessError,
+ DOMException::Create(DOMExceptionCode::kInvalidAccessError,
"There is no sender or receiver for the track."));
}
if (track_uses > 1u) {
return ScriptPromise::RejectWithDOMException(
script_state,
DOMException::Create(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"There are more than one sender or receiver for the track."));
}
// There is just one use of the track, a sender or receiver.
@@ -1413,6 +1487,11 @@ ScriptPromise RTCPeerConnection::PromiseBasedGetStats(
return track_receiver->getStats(script_state);
}
+const HeapVector<Member<RTCRtpTransceiver>>&
+RTCPeerConnection::getTransceivers() const {
+ return transceivers_;
+}
+
const HeapVector<Member<RTCRtpSender>>& RTCPeerConnection::getSenders() const {
return rtp_senders_;
}
@@ -1422,6 +1501,50 @@ const HeapVector<Member<RTCRtpReceiver>>& RTCPeerConnection::getReceivers()
return rtp_receivers_;
}
+RTCRtpTransceiver* RTCPeerConnection::addTransceiver(
+ const MediaStreamTrackOrString& track_or_kind,
+ const RTCRtpTransceiverInit& init,
+ ExceptionState& exception_state) {
+ if (sdp_semantics_ != WebRTCSdpSemantics::kUnifiedPlan) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ kOnlySupportedInUnifiedPlanMessage);
+ return nullptr;
+ }
+ if (ThrowExceptionIfSignalingStateClosed(signaling_state_, exception_state))
+ return nullptr;
+ auto webrtc_init = ToRtpTransceiverInit(init);
+ webrtc::RTCErrorOr<std::unique_ptr<WebRTCRtpTransceiver>> result =
+ webrtc::RTCError(webrtc::RTCErrorType::UNSUPPORTED_OPERATION);
+ if (track_or_kind.IsMediaStreamTrack()) {
+ MediaStreamTrack* track = track_or_kind.GetAsMediaStreamTrack();
+ RegisterTrack(track);
+ result = peer_handler_->AddTransceiverWithTrack(track->Component(),
+ std::move(webrtc_init));
+ } else {
+ const String& kind_string = track_or_kind.GetAsString();
+ // TODO(hbos): Make cricket::MediaType an allowed identifier in
+ // rtc_peer_connection.cc and use that instead of a boolean.
+ std::string kind;
+ if (kind_string == "audio") {
+ kind = webrtc::MediaStreamTrackInterface::kAudioKind;
+ } else if (kind_string == "video") {
+ kind = webrtc::MediaStreamTrackInterface::kVideoKind;
+ } else {
+ exception_state.ThrowTypeError(
+ "The argument provided as parameter 1 is not a valid "
+ "MediaStreamTrack kind ('audio' or 'video').");
+ return nullptr;
+ }
+ result = peer_handler_->AddTransceiverWithKind(std::move(kind),
+ std::move(webrtc_init));
+ }
+ if (!result.ok()) {
+ ThrowExceptionFromRTCError(result.error(), exception_state);
+ return nullptr;
+ }
+ return CreateOrUpdateTransceiver(result.MoveValue());
+}
+
RTCRtpSender* RTCPeerConnection::addTrack(MediaStreamTrack* track,
MediaStreamVector streams,
ExceptionState& exception_state) {
@@ -1429,22 +1552,19 @@ RTCRtpSender* RTCPeerConnection::addTrack(MediaStreamTrack* track,
DCHECK(track->Component());
if (ThrowExceptionIfSignalingStateClosed(signaling_state_, exception_state))
return nullptr;
- // TODO(bugs.webrtc.org/8530): Take out WebRTCSdpSemantics::kDefault check
- // once default is no longer interpreted as Plan B lower down.
- if ((sdp_semantics_ == WebRTCSdpSemantics::kPlanB ||
- sdp_semantics_ == WebRTCSdpSemantics::kDefault) &&
- streams.size() >= 2) {
+ if (sdp_semantics_ == WebRTCSdpSemantics::kPlanB && streams.size() >= 2) {
// TODO(hbos): Update peer_handler_ to call the AddTrack() that returns the
// appropriate errors, and let the lower layers handle it.
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"Adding a track to multiple streams is not supported.");
return nullptr;
}
for (const auto& sender : rtp_senders_) {
if (sender->track() == track) {
exception_state.ThrowDOMException(
- kInvalidAccessError, "A sender already exists for the track.");
+ DOMExceptionCode::kInvalidAccessError,
+ "A sender already exists for the track.");
return nullptr;
}
}
@@ -1453,20 +1573,46 @@ RTCRtpSender* RTCPeerConnection::addTrack(MediaStreamTrack* track,
for (size_t i = 0; i < streams.size(); ++i) {
web_streams[i] = streams[i]->Descriptor();
}
- std::unique_ptr<WebRTCRtpSender> web_rtp_sender =
- peer_handler_->AddTrack(track->Component(), web_streams);
- if (!web_rtp_sender) {
- exception_state.ThrowDOMException(
- kNotSupportedError, "A sender could not be created for this track.");
+ webrtc::RTCErrorOr<std::unique_ptr<WebRTCRtpTransceiver>>
+ error_or_transceiver =
+ peer_handler_->AddTrack(track->Component(), web_streams);
+ if (!error_or_transceiver.ok()) {
+ ThrowExceptionFromRTCError(error_or_transceiver.error(), exception_state);
return nullptr;
}
- DCHECK(FindSender(*web_rtp_sender) == rtp_senders_.end());
- RTCRtpSender* rtp_sender =
- new RTCRtpSender(this, std::move(web_rtp_sender), track, streams);
- tracks_.insert(track->Component(), track);
- rtp_senders_.push_back(rtp_sender);
- return rtp_sender;
+ auto web_transceiver = error_or_transceiver.MoveValue();
+
+ // The track must be known to the peer connection when performing
+ // CreateOrUpdateSender() below.
+ RegisterTrack(track);
+
+ auto stream_ids = web_transceiver->Sender()->StreamIds();
+ RTCRtpSender* sender;
+ if (sdp_semantics_ == WebRTCSdpSemantics::kPlanB) {
+ DCHECK_EQ(web_transceiver->ImplementationType(),
+ WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly);
+ sender = CreateOrUpdateSender(web_transceiver->Sender(), track->kind());
+ } else {
+ DCHECK_EQ(sdp_semantics_, WebRTCSdpSemantics::kUnifiedPlan);
+ DCHECK_EQ(web_transceiver->ImplementationType(),
+ WebRTCRtpTransceiverImplementationType::kFullTransceiver);
+ RTCRtpTransceiver* transceiver =
+ CreateOrUpdateTransceiver(std::move(web_transceiver));
+ sender = transceiver->sender();
+ }
+ // Newly created senders have no streams set, we have to set it ourselves.
+ sender->set_streams(streams);
+
+ // The stream IDs should match between layers, with one exception;
+ // in Plan B if no stream was supplied, the lower layer still generates a
+ // stream which has no blink layer correspondence.
+ DCHECK(sdp_semantics_ != WebRTCSdpSemantics::kPlanB ||
+ (streams.size() == 0u && stream_ids.size() == 1u) ||
+ stream_ids.size() == streams.size());
+ DCHECK(sdp_semantics_ != WebRTCSdpSemantics::kUnifiedPlan ||
+ stream_ids.size() == streams.size());
+ return sender;
}
void RTCPeerConnection::removeTrack(RTCRtpSender* sender,
@@ -1477,24 +1623,34 @@ void RTCPeerConnection::removeTrack(RTCRtpSender* sender,
auto* it = FindSender(*sender->web_sender());
if (it == rtp_senders_.end()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"The sender was not created by this peer connection.");
return;
}
- if (!peer_handler_->RemoveTrack(sender->web_sender())) {
- // Operation aborted. This indicates that the sender is no longer used by
- // the peer connection, i.e. that it was removed due to setting a remote
- // description of type "rollback".
- // Note: Until the WebRTC library supports re-using senders, a sender will
- // also stop being used as a result of being removed.
- return;
+ auto error_or_transceiver = peer_handler_->RemoveTrack(sender->web_sender());
+ if (sdp_semantics_ == WebRTCSdpSemantics::kPlanB) {
+ // Plan B: Was the sender removed?
+ if (!error_or_transceiver.ok()) {
+ // Operation aborted. This indicates that the sender is no longer used by
+ // the peer connection, i.e. that it was removed due to setting a remote
+ // description of type "rollback".
+ return;
+ }
+ // Successfully removing the track results in the sender's track property
+ // being nulled.
+ DCHECK(!sender->web_sender()->Track());
+ sender->SetTrack(nullptr);
+ rtp_senders_.erase(it);
+ } else {
+ // Unified Plan: Was the transceiver updated?
+ DCHECK_EQ(sdp_semantics_, WebRTCSdpSemantics::kUnifiedPlan);
+ if (!error_or_transceiver.ok()) {
+ ThrowExceptionFromRTCError(error_or_transceiver.error(), exception_state);
+ return;
+ }
+ CreateOrUpdateTransceiver(error_or_transceiver.MoveValue());
}
- // Successfully removing the track results in the sender's track property
- // being nulled.
- DCHECK(!sender->web_sender()->Track());
- sender->SetTrack(nullptr);
- rtp_senders_.erase(it);
}
RTCDataChannel* RTCPeerConnection::createDataChannel(
@@ -1508,7 +1664,16 @@ RTCDataChannel* RTCPeerConnection::createDataChannel(
WebRTCDataChannelInit init;
init.ordered = data_channel_dict.ordered();
ExecutionContext* context = ExecutionContext::From(script_state);
- if (data_channel_dict.hasMaxRetransmitTime()) {
+ // maxPacketLifeTime and maxRetransmitTime are two names for the same thing,
+ // but maxPacketLifeTime is the standardized name so it takes precedence.
+ if (data_channel_dict.hasMaxPacketLifeTime()) {
+ UseCounter::Count(
+ context,
+ WebFeature::kRTCPeerConnectionCreateDataChannelMaxPacketLifeTime);
+ init.max_retransmit_time = data_channel_dict.maxPacketLifeTime();
+ } else if (data_channel_dict.hasMaxRetransmitTime()) {
+ Deprecation::CountDeprecation(
+ context, WebFeature::kRTCDataChannelInitMaxRetransmitTime);
UseCounter::Count(
context,
WebFeature::kRTCPeerConnectionCreateDataChannelMaxRetransmitTime);
@@ -1574,13 +1739,111 @@ HeapVector<Member<RTCRtpReceiver>>::iterator RTCPeerConnection::FindReceiver(
return rtp_receivers_.end();
}
+HeapVector<Member<RTCRtpTransceiver>>::iterator
+RTCPeerConnection::FindTransceiver(
+ const WebRTCRtpTransceiver& web_transceiver) {
+ for (auto* it = transceivers_.begin(); it != transceivers_.end(); ++it) {
+ if ((*it)->web_transceiver()->Id() == web_transceiver.Id())
+ return it;
+ }
+ return transceivers_.end();
+}
+
+RTCRtpSender* RTCPeerConnection::CreateOrUpdateSender(
+ std::unique_ptr<WebRTCRtpSender> web_sender,
+ String kind) {
+ // The track corresponding to |web_track| must already be known to us by being
+ // in |tracks_|, as is a prerequisite of CreateOrUpdateSender().
+ WebMediaStreamTrack web_track = web_sender->Track();
+ MediaStreamTrack* track;
+ if (web_track.IsNull()) {
+ track = nullptr;
+ } else {
+ track = tracks_.at(web_track);
+ DCHECK(track);
+ }
+
+ // Create or update sender. If the web sender has stream IDs the sender's
+ // streams need to be set separately outside of this method.
+ auto* sender_it = FindSender(*web_sender);
+ RTCRtpSender* sender;
+ if (sender_it == rtp_senders_.end()) {
+ // Create new sender (with empty stream set).
+ sender = new RTCRtpSender(this, std::move(web_sender), kind, track, {});
+ rtp_senders_.push_back(sender);
+ } else {
+ // Update existing sender (not touching the stream set).
+ sender = *sender_it;
+ DCHECK_EQ(sender->web_sender()->Id(), web_sender->Id());
+ sender->SetTrack(track);
+ }
+ return sender;
+}
+
+RTCRtpReceiver* RTCPeerConnection::CreateOrUpdateReceiver(
+ std::unique_ptr<WebRTCRtpReceiver> web_receiver) {
+ auto* receiver_it = FindReceiver(*web_receiver);
+ // Create track.
+ MediaStreamTrack* track;
+ if (receiver_it == rtp_receivers_.end()) {
+ track =
+ MediaStreamTrack::Create(GetExecutionContext(), web_receiver->Track());
+ RegisterTrack(track);
+ } else {
+ track = (*receiver_it)->track();
+ }
+
+ // Create or update receiver. If the web receiver has stream IDs the
+ // receiver's streams need to be set separately outside of this method.
+ RTCRtpReceiver* receiver;
+ if (receiver_it == rtp_receivers_.end()) {
+ // Create new receiver.
+ receiver = new RTCRtpReceiver(std::move(web_receiver), track, {});
+ rtp_receivers_.push_back(receiver);
+ } else {
+ // Update existing receiver is a no-op.
+ receiver = *receiver_it;
+ DCHECK_EQ(receiver->web_receiver().Id(), web_receiver->Id());
+ DCHECK_EQ(receiver->track(), track); // Its track should never change.
+ }
+ return receiver;
+}
+
+RTCRtpTransceiver* RTCPeerConnection::CreateOrUpdateTransceiver(
+ std::unique_ptr<WebRTCRtpTransceiver> web_transceiver) {
+ String kind = (web_transceiver->Receiver()->Track().Source().GetType() ==
+ WebMediaStreamSource::kTypeAudio)
+ ? "audio"
+ : "video";
+ RTCRtpSender* sender = CreateOrUpdateSender(web_transceiver->Sender(), kind);
+ RTCRtpReceiver* receiver =
+ CreateOrUpdateReceiver(web_transceiver->Receiver());
+
+ RTCRtpTransceiver* transceiver;
+ auto* transceiver_it = FindTransceiver(*web_transceiver);
+ if (transceiver_it == transceivers_.end()) {
+ // Create new tranceiver.
+ transceiver = new RTCRtpTransceiver(this, std::move(web_transceiver),
+ sender, receiver);
+ transceivers_.push_back(transceiver);
+ } else {
+ // Update existing transceiver.
+ transceiver = *transceiver_it;
+ // The sender and receiver have already been updated above.
+ DCHECK_EQ(transceiver->sender(), sender);
+ DCHECK_EQ(transceiver->receiver(), receiver);
+ transceiver->UpdateMembers();
+ }
+ return transceiver;
+}
+
RTCDTMFSender* RTCPeerConnection::createDTMFSender(
MediaStreamTrack* track,
ExceptionState& exception_state) {
if (ThrowExceptionIfSignalingStateClosed(signaling_state_, exception_state))
return nullptr;
if (track->kind() != "audio") {
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"track.kind is not 'audio'.");
return nullptr;
}
@@ -1593,26 +1856,32 @@ RTCDTMFSender* RTCPeerConnection::createDTMFSender(
}
if (!found_rtp_sender) {
exception_state.ThrowDOMException(
- kSyntaxError, "No RTCRtpSender is available for the track provided.");
+ DOMExceptionCode::kSyntaxError,
+ "No RTCRtpSender is available for the track provided.");
return nullptr;
}
RTCDTMFSender* dtmf_sender = found_rtp_sender->dtmf();
if (!dtmf_sender) {
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"Unable to create DTMF sender for track");
return nullptr;
}
- dtmf_sender->SetTrack(track);
return dtmf_sender;
}
void RTCPeerConnection::close() {
- if (signaling_state_ == RTCPeerConnection::kSignalingStateClosed)
+ if (signaling_state_ ==
+ webrtc::PeerConnectionInterface::SignalingState::kClosed)
return;
CloseInternal();
}
+void RTCPeerConnection::RegisterTrack(MediaStreamTrack* track) {
+ DCHECK(track);
+ tracks_.insert(track->Component(), track);
+}
+
void RTCPeerConnection::NoteSdpCreated(const RTCSessionDescription& desc) {
if (desc.type() == "offer") {
last_offer_ = desc.sdp();
@@ -1674,10 +1943,11 @@ void RTCPeerConnection::DidGenerateICECandidate(
ScheduleDispatchEvent(RTCPeerConnectionIceEvent::Create(ice_candidate));
}
-void RTCPeerConnection::DidChangeSignalingState(SignalingState new_state) {
+void RTCPeerConnection::DidChangeSignalingState(
+ webrtc::PeerConnectionInterface::SignalingState new_state) {
DCHECK(!closed_);
DCHECK(GetExecutionContext()->IsContextThread());
- ChangeSignalingState(new_state);
+ ChangeSignalingState(new_state, true);
}
void RTCPeerConnection::DidChangeICEGatheringState(
@@ -1694,118 +1964,84 @@ void RTCPeerConnection::DidChangeICEConnectionState(
ChangeIceConnectionState(new_state);
}
-void RTCPeerConnection::DidAddRemoteTrack(
- std::unique_ptr<WebRTCRtpReceiver> web_rtp_receiver) {
+void RTCPeerConnection::DidAddReceiverPlanB(
+ std::unique_ptr<WebRTCRtpReceiver> web_receiver) {
DCHECK(!closed_);
DCHECK(GetExecutionContext()->IsContextThread());
- if (signaling_state_ == kSignalingStateClosed)
+ DCHECK_EQ(sdp_semantics_, WebRTCSdpSemantics::kPlanB);
+ if (signaling_state_ ==
+ webrtc::PeerConnectionInterface::SignalingState::kClosed)
return;
+ // Create track.
+ MediaStreamTrack* track =
+ MediaStreamTrack::Create(GetExecutionContext(), web_receiver->Track());
+ tracks_.insert(track->Component(), track);
+ // Create or update streams.
HeapVector<Member<MediaStream>> streams;
- WebVector<WebMediaStream> web_streams = web_rtp_receiver->Streams();
- streams.ReserveCapacity(web_streams.size());
- for (const WebMediaStream& web_stream : web_streams) {
- MediaStream* stream = getRemoteStream(web_stream);
+ for (const auto& stream_id : web_receiver->StreamIds()) {
+ MediaStream* stream = getRemoteStreamById(stream_id);
if (!stream) {
- // This is a new stream that we need to create.
- // Get or create audio tracks.
- WebVector<WebMediaStreamTrack> audio_web_tracks;
- web_stream.AudioTracks(audio_web_tracks);
+ // The stream is new, create it containing this track.
+ MediaStreamComponentVector audio_track_components;
MediaStreamTrackVector audio_tracks;
- audio_tracks.ReserveCapacity(audio_web_tracks.size());
- for (const WebMediaStreamTrack& audio_web_track : audio_web_tracks) {
- MediaStreamTrack* audio_track = tracks_.at(audio_web_track);
- if (!audio_track) {
- audio_track =
- MediaStreamTrack::Create(GetExecutionContext(), audio_web_track);
- tracks_.insert(audio_track->Component(), audio_track);
- }
- audio_tracks.push_back(audio_track);
- }
- // Get or create video tracks.
- WebVector<WebMediaStreamTrack> video_web_tracks;
- web_stream.VideoTracks(video_web_tracks);
+ MediaStreamComponentVector video_track_components;
MediaStreamTrackVector video_tracks;
- video_tracks.ReserveCapacity(video_web_tracks.size());
- for (const WebMediaStreamTrack& video_web_track : video_web_tracks) {
- MediaStreamTrack* video_track = tracks_.at(video_web_track);
- if (!video_track) {
- video_track =
- MediaStreamTrack::Create(GetExecutionContext(), video_web_track);
- tracks_.insert(video_track->Component(), video_track);
- }
- video_tracks.push_back(video_track);
+ if (track->Component()->Source()->GetType() ==
+ MediaStreamSource::kTypeAudio) {
+ audio_track_components.push_back(track->Component());
+ audio_tracks.push_back(track);
+ } else {
+ DCHECK(track->Component()->Source()->GetType() ==
+ MediaStreamSource::kTypeVideo);
+ video_track_components.push_back(track->Component());
+ video_tracks.push_back(track);
}
- // Create stream with tracks.
- stream = MediaStream::Create(GetExecutionContext(), web_stream,
- audio_tracks, video_tracks);
- stream->RegisterObserver(this);
+ MediaStreamDescriptor* descriptor = MediaStreamDescriptor::Create(
+ stream_id, std::move(audio_track_components),
+ std::move(video_track_components));
+ stream =
+ MediaStream::Create(GetExecutionContext(), descriptor,
+ std::move(audio_tracks), std::move(video_tracks));
+ // Schedule to fire "pc.onaddstream".
ScheduleDispatchEvent(
MediaStreamEvent::Create(EventTypeNames::addstream, stream));
} else {
- // The stream already exists. Because the blink stream is wired up to
- // reflect when web tracks are added to the corresponding web stream, the
- // receiver's track will already have a blink track created for it and
- // added to the blink stream. Find it and add it to |tracks_| so that the
- // RTCPeerConnection knows of its existence.
- // TODO(hbos): This wiring is problematic since it assumes the blink track
- // should always be created. If the track already exists (on some other
- // stream or receiver) we will end up with multiple blink tracks for the
- // same component. When a web track is added to the web stream, we need to
- // check if a blink track already exists for it by querying the
- // RTCPeerConnection. https://crbug.com/769743
- MediaStreamTrack* receiver_track = nullptr;
- for (const auto& track : stream->getTracks()) {
- if (track->Component() == web_rtp_receiver->Track()) {
- receiver_track = track;
- break;
- }
- }
- DCHECK(receiver_track);
- tracks_.insert(receiver_track->Component(), receiver_track);
+ // The stream already exists, add the track to it.
+ // This will cause to schedule to fire "stream.onaddtrack".
+ stream->AddTrackAndFireEvents(track);
}
streams.push_back(stream);
}
- DCHECK(FindReceiver(*web_rtp_receiver) == rtp_receivers_.end());
- MediaStreamTrack* track = GetTrack(web_rtp_receiver->Track());
- if (!track) {
- // Receiver with track, without a stream. May be created by Unified Plan.
- track = MediaStreamTrack::Create(GetExecutionContext(),
- web_rtp_receiver->Track());
- }
+ DCHECK(FindReceiver(*web_receiver) == rtp_receivers_.end());
RTCRtpReceiver* rtp_receiver =
- new RTCRtpReceiver(std::move(web_rtp_receiver), track, streams);
+ new RTCRtpReceiver(std::move(web_receiver), track, streams);
rtp_receivers_.push_back(rtp_receiver);
ScheduleDispatchEvent(
- new RTCTrackEvent(rtp_receiver, rtp_receiver->track(), streams));
+ new RTCTrackEvent(rtp_receiver, rtp_receiver->track(), streams, nullptr));
}
-void RTCPeerConnection::DidRemoveRemoteTrack(
- std::unique_ptr<WebRTCRtpReceiver> web_rtp_receiver) {
+void RTCPeerConnection::DidRemoveReceiverPlanB(
+ std::unique_ptr<WebRTCRtpReceiver> web_receiver) {
DCHECK(!closed_);
DCHECK(GetExecutionContext()->IsContextThread());
+ DCHECK_EQ(sdp_semantics_, WebRTCSdpSemantics::kPlanB);
- WebVector<WebMediaStream> web_streams = web_rtp_receiver->Streams();
- auto* it = FindReceiver(*web_rtp_receiver);
+ auto* it = FindReceiver(*web_receiver);
DCHECK(it != rtp_receivers_.end());
RTCRtpReceiver* rtp_receiver = *it;
+ auto streams = rtp_receiver->streams();
MediaStreamTrack* track = rtp_receiver->track();
rtp_receivers_.erase(it);
// End streams no longer in use and fire "removestream" events. This behavior
// is no longer in the spec.
- for (const WebMediaStream& web_stream : web_streams) {
- MediaStreamDescriptor* stream_descriptor = web_stream;
- DCHECK(stream_descriptor->Client());
- MediaStream* stream =
- static_cast<MediaStream*>(stream_descriptor->Client());
-
- // The track should already have been removed from the stream thanks to
- // wiring listening to the webrtc layer stream. This should make sure the
- // "removetrack" event fires.
- DCHECK(!stream->getTracks().Contains(track));
+ for (const auto& stream : streams) {
+ // Remove the track.
+ // This will cause to schedule to fire "stream.onremovetrack".
+ stream->RemoveTrackAndFireEvents(track);
// Was this the last usage of the stream? Remove from remote streams.
- if (!getRemoteStreamUsageCount(web_stream)) {
+ if (!IsRemoteStream(stream)) {
// TODO(hbos): The stream should already have ended by being empty, no
// need for |StreamEnded|.
stream->StreamEnded();
@@ -1820,12 +2056,132 @@ void RTCPeerConnection::DidRemoveRemoteTrack(
MediaStreamSource::kReadyStateMuted);
}
+void RTCPeerConnection::DidModifyTransceivers(
+ std::vector<std::unique_ptr<WebRTCRtpTransceiver>> web_transceivers,
+ bool is_remote_description) {
+ HeapVector<Member<MediaStreamTrack>> mute_tracks;
+ HeapVector<std::pair<Member<MediaStream>, Member<MediaStreamTrack>>>
+ remove_list;
+ HeapVector<std::pair<Member<MediaStream>, Member<MediaStreamTrack>>> add_list;
+ HeapVector<Member<RTCRtpTransceiver>> track_events;
+ for (auto& web_transceiver : web_transceivers) {
+ auto* it = FindTransceiver(*web_transceiver);
+ bool previously_had_recv =
+ (it != transceivers_.end()) ? (*it)->FiredDirectionHasRecv() : false;
+ RTCRtpTransceiver* transceiver =
+ CreateOrUpdateTransceiver(std::move(web_transceiver));
+
+ // The transceiver is now up-to-date. Compare before/after values of
+ // FiredDirectionHasRecv() and process the remote track if it changed.
+ if (is_remote_description && !previously_had_recv &&
+ transceiver->FiredDirectionHasRecv()) {
+ ProcessAdditionOfRemoteTrack(
+ transceiver, transceiver->web_transceiver()->Receiver()->StreamIds(),
+ &add_list, &track_events);
+ }
+ if (previously_had_recv && !transceiver->FiredDirectionHasRecv()) {
+ ProcessRemovalOfRemoteTrack(transceiver, &remove_list, &mute_tracks);
+ }
+ }
+
+ for (auto& track : mute_tracks) {
+ track->Component()->Source()->SetReadyState(
+ MediaStreamSource::kReadyStateMuted);
+ }
+ for (auto& pair : remove_list) {
+ auto& stream = pair.first;
+ auto& track = pair.second;
+ if (stream->getTracks().Contains(track)) {
+ stream->RemoveTrackAndFireEvents(track);
+ }
+ }
+ for (auto& pair : add_list) {
+ auto& stream = pair.first;
+ auto& track = pair.second;
+ if (!stream->getTracks().Contains(track)) {
+ stream->AddTrackAndFireEvents(track);
+ }
+ }
+
+ for (auto& transceiver : track_events) {
+ ScheduleDispatchEvent(new RTCTrackEvent(
+ transceiver->receiver(), transceiver->receiver()->track(),
+ transceiver->receiver()->streams(), transceiver));
+ }
+}
+
+void RTCPeerConnection::ProcessAdditionOfRemoteTrack(
+ RTCRtpTransceiver* transceiver,
+ const WebVector<WebString>& stream_ids,
+ HeapVector<std::pair<Member<MediaStream>, Member<MediaStreamTrack>>>*
+ add_list,
+ HeapVector<Member<RTCRtpTransceiver>>* track_events) {
+ SetAssociatedMediaStreams(transceiver->receiver(), stream_ids, nullptr,
+ add_list);
+ track_events->push_back(transceiver);
+}
+
+void RTCPeerConnection::ProcessRemovalOfRemoteTrack(
+ RTCRtpTransceiver* transceiver,
+ HeapVector<std::pair<Member<MediaStream>, Member<MediaStreamTrack>>>*
+ remove_list,
+ HeapVector<Member<MediaStreamTrack>>* mute_tracks) {
+ WebVector<WebString> stream_ids = {};
+ SetAssociatedMediaStreams(transceiver->receiver(), stream_ids, remove_list,
+ nullptr);
+ if (!transceiver->receiver()->track()->muted())
+ mute_tracks->push_back(transceiver->receiver()->track());
+}
+
+void RTCPeerConnection::SetAssociatedMediaStreams(
+ RTCRtpReceiver* receiver,
+ const WebVector<WebString>& stream_ids,
+ HeapVector<std::pair<Member<MediaStream>, Member<MediaStreamTrack>>>*
+ remove_list,
+ HeapVector<std::pair<Member<MediaStream>, Member<MediaStreamTrack>>>*
+ add_list) {
+ MediaStreamVector known_streams = getRemoteStreams();
+
+ MediaStreamVector streams;
+ for (const auto& stream_id : stream_ids) {
+ MediaStream* curr_stream = nullptr;
+ for (const auto& known_stream : known_streams) {
+ if (static_cast<WebString>(known_stream->id()) == stream_id) {
+ curr_stream = known_stream;
+ break;
+ }
+ }
+ if (!curr_stream) {
+ curr_stream = MediaStream::Create(
+ GetExecutionContext(), MediaStreamDescriptor::Create(
+ static_cast<String>(stream_id), {}, {}));
+ }
+ streams.push_back(curr_stream);
+ }
+
+ const MediaStreamVector& prev_streams = receiver->streams();
+ if (remove_list) {
+ for (const auto& stream : prev_streams) {
+ if (!streams.Contains(stream))
+ remove_list->push_back(std::make_pair(stream, receiver->track()));
+ }
+ }
+ if (add_list) {
+ for (const auto& stream : streams) {
+ if (!prev_streams.Contains(stream))
+ add_list->push_back(std::make_pair(stream, receiver->track()));
+ }
+ }
+ receiver->set_streams(std::move(streams));
+}
+
void RTCPeerConnection::DidAddRemoteDataChannel(
WebRTCDataChannelHandler* handler) {
DCHECK(!closed_);
DCHECK(GetExecutionContext()->IsContextThread());
- if (signaling_state_ == kSignalingStateClosed)
+ if (signaling_state_ ==
+ webrtc::PeerConnectionInterface::SignalingState::kClosed)
return;
RTCDataChannel* channel =
@@ -1841,7 +2197,7 @@ void RTCPeerConnection::ReleasePeerConnectionHandler() {
stopped_ = true;
ice_connection_state_ = kICEConnectionStateClosed;
- signaling_state_ = kSignalingStateClosed;
+ signaling_state_ = webrtc::PeerConnectionInterface::SignalingState::kClosed;
dispatch_scheduled_event_runner_->Stop();
@@ -1851,17 +2207,11 @@ void RTCPeerConnection::ReleasePeerConnectionHandler() {
}
void RTCPeerConnection::ClosePeerConnection() {
- DCHECK(signaling_state_ != RTCPeerConnection::kSignalingStateClosed);
+ DCHECK(signaling_state_ !=
+ webrtc::PeerConnectionInterface::SignalingState::kClosed);
CloseInternal();
}
-RTCPeerConnection::WebRTCOriginTrials RTCPeerConnection::GetOriginTrials() {
- RTCPeerConnection::WebRTCOriginTrials trials;
- trials.vaapi_hwvp8_encoding_enabled =
- OriginTrials::webRtcVaapiHWVP8EncodingEnabled(GetExecutionContext());
- return trials;
-}
-
const AtomicString& RTCPeerConnection::InterfaceName() const {
return EventTargetNames::RTCPeerConnection;
}
@@ -1882,10 +2232,19 @@ void RTCPeerConnection::ContextDestroyed(ExecutionContext*) {
ReleasePeerConnectionHandler();
}
-void RTCPeerConnection::ChangeSignalingState(SignalingState signaling_state) {
- if (signaling_state_ != kSignalingStateClosed) {
+void RTCPeerConnection::ChangeSignalingState(
+ webrtc::PeerConnectionInterface::SignalingState signaling_state,
+ bool dispatch_event_immediately) {
+ if (signaling_state_ == signaling_state)
+ return;
+ if (signaling_state_ !=
+ webrtc::PeerConnectionInterface::SignalingState::kClosed) {
signaling_state_ = signaling_state;
- ScheduleDispatchEvent(Event::Create(EventTypeNames::signalingstatechange));
+ Event* event = Event::Create(EventTypeNames::signalingstatechange);
+ if (dispatch_event_immediately)
+ DispatchEvent(event);
+ else
+ ScheduleDispatchEvent(event);
}
}
@@ -1938,12 +2297,18 @@ bool RTCPeerConnection::SetIceConnectionState(
}
void RTCPeerConnection::CloseInternal() {
- DCHECK(signaling_state_ != RTCPeerConnection::kSignalingStateClosed);
+ DCHECK(signaling_state_ !=
+ webrtc::PeerConnectionInterface::SignalingState::kClosed);
peer_handler_->Stop();
closed_ = true;
ChangeIceConnectionState(kICEConnectionStateClosed);
- ChangeSignalingState(kSignalingStateClosed);
+ ChangeSignalingState(webrtc::PeerConnectionInterface::SignalingState::kClosed,
+ false);
+ for (auto& transceiver : transceivers_) {
+ transceiver->OnPeerConnectionClosed();
+ }
+
Document* document = ToDocument(GetExecutionContext());
HostsUsingFeatures::CountAnyWorld(
*document, HostsUsingFeatures::Feature::kRTCPeerConnectionUsed);
@@ -2006,6 +2371,7 @@ void RTCPeerConnection::Trace(blink::Visitor* visitor) {
visitor->Trace(tracks_);
visitor->Trace(rtp_senders_);
visitor->Trace(rtp_receivers_);
+ visitor->Trace(transceivers_);
visitor->Trace(dispatch_scheduled_event_runner_);
visitor->Trace(scheduled_events_);
EventTargetWithInlineData::Trace(visitor);
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h
index faf41aebef7..0c170bb7499 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h
@@ -44,6 +44,7 @@
#include "third_party/blink/renderer/modules/event_target_modules.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_ice_candidate.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.h"
#include "third_party/blink/renderer/platform/async_method_runner.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
@@ -52,6 +53,7 @@ namespace blink {
class ExceptionState;
class MediaStreamTrack;
+class MediaStreamTrackOrString;
class RTCAnswerOptions;
class RTCConfiguration;
class RTCDTMFSender;
@@ -62,6 +64,7 @@ class RTCOfferOptions;
class RTCPeerConnectionTest;
class RTCRtpReceiver;
class RTCRtpSender;
+class RTCRtpTransceiverInit;
class RTCSessionDescription;
class RTCSessionDescriptionInit;
class ScriptState;
@@ -131,24 +134,24 @@ class MODULES_EXPORT RTCPeerConnection final
ExceptionState&);
ScriptPromise addIceCandidate(ScriptState*,
- const RTCIceCandidateInitOrRTCIceCandidate&);
+ const RTCIceCandidateInitOrRTCIceCandidate&,
+ ExceptionState&);
ScriptPromise addIceCandidate(ScriptState*,
const RTCIceCandidateInitOrRTCIceCandidate&,
V8VoidFunction*,
- V8RTCPeerConnectionErrorCallback*);
+ V8RTCPeerConnectionErrorCallback*,
+ ExceptionState&);
String iceGatheringState() const;
String iceConnectionState() const;
+ // A local stream is any stream associated with a sender.
MediaStreamVector getLocalStreams() const;
-
+ // A remote stream is any stream associated with a receiver.
MediaStreamVector getRemoteStreams() const;
- // Returns the remote stream for the descriptor, if one exists.
- MediaStream* getRemoteStream(MediaStreamDescriptor*) const;
- // Counts the number of receivers that have a remote stream for the descriptor
- // in its set of associated remote streams.
- size_t getRemoteStreamUsageCount(MediaStreamDescriptor*) const;
+ MediaStream* getRemoteStreamById(const WebString&) const;
+ bool IsRemoteStream(MediaStream* stream) const;
void addStream(ScriptState*,
MediaStream*,
@@ -174,8 +177,12 @@ class MODULES_EXPORT RTCPeerConnection final
MediaStreamTrack* selector);
ScriptPromise PromiseBasedGetStats(ScriptState*, MediaStreamTrack* selector);
+ const HeapVector<Member<RTCRtpTransceiver>>& getTransceivers() const;
const HeapVector<Member<RTCRtpSender>>& getSenders() const;
const HeapVector<Member<RTCRtpReceiver>>& getReceivers() const;
+ RTCRtpTransceiver* addTransceiver(const MediaStreamTrackOrString&,
+ const RTCRtpTransceiverInit&,
+ ExceptionState&);
RTCRtpSender* addTrack(MediaStreamTrack*, MediaStreamVector, ExceptionState&);
void removeTrack(RTCRtpSender*, ExceptionState&);
DEFINE_ATTRIBUTE_EVENT_LISTENER(track);
@@ -190,6 +197,11 @@ class MODULES_EXPORT RTCPeerConnection final
bool IsClosed() { return closed_; }
void close();
+ // Makes the peer connection aware of the track. This is used to map web
+ // tracks to blink tracks, as is necessary for plumbing. There is no need to
+ // unregister the track because Weak references are used.
+ void RegisterTrack(MediaStreamTrack*);
+
// We allow getStats after close, but not other calls or callbacks.
bool ShouldFireDefaultCallbacks() { return !closed_ && !stopped_; }
bool ShouldFireGetStatsCallback() { return !stopped_; }
@@ -213,15 +225,17 @@ class MODULES_EXPORT RTCPeerConnection final
// WebRTCPeerConnectionHandlerClient
void NegotiationNeeded() override;
void DidGenerateICECandidate(scoped_refptr<WebRTCICECandidate>) override;
- void DidChangeSignalingState(SignalingState) override;
+ void DidChangeSignalingState(
+ webrtc::PeerConnectionInterface::SignalingState) override;
void DidChangeICEGatheringState(ICEGatheringState) override;
void DidChangeICEConnectionState(ICEConnectionState) override;
- void DidAddRemoteTrack(std::unique_ptr<WebRTCRtpReceiver>) override;
- void DidRemoveRemoteTrack(std::unique_ptr<WebRTCRtpReceiver>) override;
+ void DidAddReceiverPlanB(std::unique_ptr<WebRTCRtpReceiver>) override;
+ void DidRemoveReceiverPlanB(std::unique_ptr<WebRTCRtpReceiver>) override;
+ void DidModifyTransceivers(std::vector<std::unique_ptr<WebRTCRtpTransceiver>>,
+ bool is_remote_description) override;
void DidAddRemoteDataChannel(WebRTCDataChannelHandler*) override;
void ReleasePeerConnectionHandler() override;
void ClosePeerConnection() override;
- WebRTCOriginTrials GetOriginTrials() override;
// EventTarget
const AtomicString& InterfaceName() const override;
@@ -269,7 +283,7 @@ class MODULES_EXPORT RTCPeerConnection final
};
RTCPeerConnection(ExecutionContext*,
- const WebRTCConfiguration&,
+ WebRTCConfiguration,
WebMediaConstraints,
ExceptionState&);
void Dispose();
@@ -284,8 +298,71 @@ class MODULES_EXPORT RTCPeerConnection final
const WebRTCRtpSender& web_sender);
HeapVector<Member<RTCRtpReceiver>>::iterator FindReceiver(
const WebRTCRtpReceiver& web_receiver);
-
- // The "Change" methods set the state asynchronously and fire the
+ HeapVector<Member<RTCRtpTransceiver>>::iterator FindTransceiver(
+ const WebRTCRtpTransceiver& web_transceiver);
+
+ // Creates or updates the sender such that it is up-to-date with the
+ // WebRTCRtpSender in all regards *except for streams*. The web sender only
+ // knows of stream IDs; updating the stream objects requires additional logic
+ // which is different depending on context, e.g:
+ // - If created/updated with addTrack(), the streams were supplied as
+ // arguments.
+ // The web sender's web track must already have a correspondent blink track in
+ // |tracks_|. The caller is responsible for ensuring this with
+ // RegisterTrack(), e.g:
+ // - On addTrack(), the track is supplied as an argument.
+ RTCRtpSender* CreateOrUpdateSender(std::unique_ptr<WebRTCRtpSender>,
+ String kind);
+ // Creates or updates the receiver such that it is up-to-date with the
+ // WebRTCRtpReceiver in all regards *except for streams*. The web receiver
+ // only knows of stream IDs; updating the stream objects requires additional
+ // logic which is different depending on context, e.g:
+ // - If created/updated with setRemoteDescription(), there is an algorithm for
+ // processing the addition/removal of remote tracks which includes how to
+ // create and update the associated streams set.
+ RTCRtpReceiver* CreateOrUpdateReceiver(std::unique_ptr<WebRTCRtpReceiver>);
+ // Creates or updates the transceiver such that it, including its sender and
+ // receiver, are up-to-date with the WebRTCRtpTransceiver in all regerds
+ // *except for sender and receiver streams*. The web sender and web receiver
+ // only knows of stream IDs; updating the stream objects require additional
+ // logic which is different depending on context. See above.
+ RTCRtpTransceiver* CreateOrUpdateTransceiver(
+ std::unique_ptr<WebRTCRtpTransceiver>);
+
+ // https://w3c.github.io/webrtc-pc/#process-remote-track-addition
+ void ProcessAdditionOfRemoteTrack(
+ RTCRtpTransceiver* transceiver,
+ const WebVector<WebString>& stream_ids,
+ HeapVector<std::pair<Member<MediaStream>, Member<MediaStreamTrack>>>*
+ add_list,
+ HeapVector<Member<RTCRtpTransceiver>>* track_events);
+ // https://w3c.github.io/webrtc-pc/#process-remote-track-removal
+ void ProcessRemovalOfRemoteTrack(
+ RTCRtpTransceiver* transceiver,
+ HeapVector<std::pair<Member<MediaStream>, Member<MediaStreamTrack>>>*
+ remove_list,
+ HeapVector<Member<MediaStreamTrack>>* mute_tracks);
+ // Update the |receiver->streams()| to the streams indicated by |stream_ids|,
+ // adding to |remove_list| and |add_list| accordingly.
+ // https://w3c.github.io/webrtc-pc/#set-associated-remote-streams
+ void SetAssociatedMediaStreams(
+ RTCRtpReceiver* receiver,
+ const WebVector<WebString>& stream_ids,
+ HeapVector<std::pair<Member<MediaStream>, Member<MediaStreamTrack>>>*
+ remove_list,
+ HeapVector<std::pair<Member<MediaStream>, Member<MediaStreamTrack>>>*
+ add_list);
+
+ // Sets the signaling state synchronously, and dispatches a
+ // signalingstatechange event synchronously or asynchronously depending on
+ // |dispatch_event_immediately|.
+ // TODO(hbos): The ability to not fire the event asynchronously is there
+ // because CloseInternal() has historically fired asynchronously along with
+ // other asynchronously fired events. If close() does not fire any events,
+ // |dispatch_event_immediately| can be removed. https://crbug.com/849247
+ void ChangeSignalingState(webrtc::PeerConnectionInterface::SignalingState,
+ bool dispatch_event_immediately);
+ // The remaining "Change" methods set the state asynchronously and fire the
// corresponding event immediately after changing the state (if it was really
// changed).
//
@@ -298,15 +375,6 @@ class MODULES_EXPORT RTCPeerConnection final
// possible to, for example, end up with two "icegatheringstatechange" events
// that are delayed somehow and cause the application to read a "complete"
// gathering state twice, missing the "gathering" state in the middle.
- //
- // TODO(deadbeef): This wasn't done for the signaling state because it
- // resulted in a change to the order of the signaling state being updated
- // relative to the SetLocalDescription or SetRemoteDescription promise being
- // resolved. Some additional refactoring would be necessary to fix this; for
- // example, passing the new signaling state along with the SRD/SLD callbacks
- // as opposed to relying on a separate event.
- void ChangeSignalingState(WebRTCPeerConnectionHandlerClient::SignalingState);
-
void ChangeIceGatheringState(
WebRTCPeerConnectionHandlerClient::ICEGatheringState);
bool SetIceGatheringState(
@@ -325,7 +393,7 @@ class MODULES_EXPORT RTCPeerConnection final
const RTCSessionDescriptionInit&,
String* sdp);
- SignalingState signaling_state_;
+ webrtc::PeerConnectionInterface::SignalingState signaling_state_;
ICEGatheringState ice_gathering_state_;
ICEConnectionState ice_connection_state_;
@@ -333,8 +401,15 @@ class MODULES_EXPORT RTCPeerConnection final
// includes tracks of |rtp_senders_| and |rtp_receivers_|.
HeapHashMap<WeakMember<MediaStreamComponent>, WeakMember<MediaStreamTrack>>
tracks_;
+ // In Plan B, senders and receivers exist independently of one another.
+ // In Unified Plan, all senders and receivers are the sender-receiver pairs of
+ // transceivers.
+ // TODO(hbos): When Plan B is removed, remove |rtp_senders_| and
+ // |rtp_receivers_| since these are part of |transceivers_|.
+ // https://crbug.com/857004
HeapVector<Member<RTCRtpSender>> rtp_senders_;
HeapVector<Member<RTCRtpReceiver>> rtp_receivers_;
+ HeapVector<Member<RTCRtpTransceiver>> transceivers_;
std::unique_ptr<WebRTCPeerConnectionHandler> peer_handler_;
@@ -355,6 +430,13 @@ class MODULES_EXPORT RTCPeerConnection final
String last_answer_;
bool has_data_channels_; // For RAPPOR metrics
+ // In Plan B, senders and receivers are added or removed independently of one
+ // another. In Unified Plan, senders and receivers are created in pairs as
+ // transceivers. Transceivers may become inactive, but are never removed.
+ // The value of this member affects the behavior of some methods and what
+ // information is surfaced from webrtc. This has the value "kPlanB" or
+ // "kUnifiedPlan", if constructed with "kDefault" it is translated to one or
+ // the other.
WebRTCSdpSemantics sdp_semantics_;
};
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl
index 293e6f1d36a..35913caf0d8 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.idl
@@ -77,7 +77,7 @@ enum RTCIceConnectionState {
readonly attribute RTCSessionDescription? remoteDescription;
// readonly attribute RTCSessionDescription? currentRemoteDescription;
// readonly attribute RTCSessionDescription? pendingRemoteDescription;
- [CallWith=ScriptState, MeasureAs=RTCPeerConnectionAddIceCandidatePromise] Promise<void> addIceCandidate ((RTCIceCandidateInit or RTCIceCandidate) candidate);
+ [CallWith=ScriptState, RaisesException, MeasureAs=RTCPeerConnectionAddIceCandidatePromise] Promise<void> addIceCandidate((RTCIceCandidateInit or RTCIceCandidate) candidate);
readonly attribute RTCSignalingState signalingState;
readonly attribute RTCIceGatheringState iceGatheringState;
readonly attribute RTCIceConnectionState iceConnectionState;
@@ -102,7 +102,7 @@ enum RTCIceConnectionState {
// TODO(guidou): The failureCallback argument should be non-optional.
// TODO(crbug.com/841185): |failureCallback| is not nullable in the spec.
[CallWith=ScriptState] Promise<void> setRemoteDescription(RTCSessionDescriptionInit description, VoidFunction successCallback, optional RTCPeerConnectionErrorCallback? failureCallback);
- [CallWith=ScriptState, MeasureAs=RTCPeerConnectionAddIceCandidateLegacy] Promise<void> addIceCandidate((RTCIceCandidateInit or RTCIceCandidate) candidate, VoidFunction successCallback, RTCPeerConnectionErrorCallback failureCallback);
+ [CallWith=ScriptState, RaisesException, MeasureAs=RTCPeerConnectionAddIceCandidateLegacy] Promise<void> addIceCandidate((RTCIceCandidateInit or RTCIceCandidate) candidate, VoidFunction successCallback, RTCPeerConnectionErrorCallback failureCallback);
// Legacy getStats() API. The returned metrics are a completely different
// set of metrics than the standard compliant version, presented in a
@@ -132,10 +132,16 @@ enum RTCIceConnectionState {
[CallWith=ScriptState] Promise<any> getStats(optional any callbackOrSelector);
// RTP Media API
+ // https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-gettransceivers
+ [Measure] sequence<RTCRtpTranceiver> getTransceivers();
// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-getsenders
[Measure] sequence<RTCRtpSender> getSenders();
// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-getreceivers
[Measure] sequence<RTCRtpReceiver> getReceivers();
+ // https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-addtransceiver
+ [Measure, RaisesException] RTCRtpTransceiver addTransceiver(
+ (MediaStreamTrack or DOMString) track_or_kind,
+ optional RTCRtpTransceiverInit init);
// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-addtrack
[Measure, RaisesException] RTCRtpSender addTrack(MediaStreamTrack track, MediaStream... streams);
// https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-removetrack
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_test.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_test.cc
index b1329e47863..cdef1438738 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_test.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_test.cc
@@ -144,19 +144,22 @@ TEST_F(RTCPeerConnectionTest, GetTrackRemoveStreamAndGCAll) {
MediaStreamTrack* track =
CreateTrack(scope, MediaStreamSource::kTypeAudio, "audioTrack");
- HeapVector<Member<MediaStreamTrack>> tracks;
- tracks.push_back(track);
- MediaStream* stream =
- MediaStream::Create(scope.GetExecutionContext(), tracks);
- ASSERT_TRUE(stream);
-
MediaStreamComponent* track_component = track->Component();
- EXPECT_FALSE(pc->GetTrack(track_component));
- AddStream(scope, pc, stream);
- EXPECT_TRUE(pc->GetTrack(track_component));
+ {
+ HeapVector<Member<MediaStreamTrack>> tracks;
+ tracks.push_back(track);
+ MediaStream* stream =
+ MediaStream::Create(scope.GetExecutionContext(), tracks);
+ ASSERT_TRUE(stream);
+
+ EXPECT_FALSE(pc->GetTrack(track_component));
+ AddStream(scope, pc, stream);
+ EXPECT_TRUE(pc->GetTrack(track_component));
+
+ RemoveStream(scope, pc, stream);
+ }
- RemoveStream(scope, pc, stream);
// This will destroy |MediaStream|, |MediaStreamTrack| and its
// |MediaStreamComponent|, which will remove its mapping from the peer
// connection.
@@ -173,19 +176,22 @@ TEST_F(RTCPeerConnectionTest,
MediaStreamTrack* track =
CreateTrack(scope, MediaStreamSource::kTypeAudio, "audioTrack");
- HeapVector<Member<MediaStreamTrack>> tracks;
- tracks.push_back(track);
- MediaStream* stream =
- MediaStream::Create(scope.GetExecutionContext(), tracks);
- ASSERT_TRUE(stream);
-
Persistent<MediaStreamComponent> track_component = track->Component();
- EXPECT_FALSE(pc->GetTrack(track_component.Get()));
- AddStream(scope, pc, stream);
- EXPECT_TRUE(pc->GetTrack(track_component.Get()));
+ {
+ HeapVector<Member<MediaStreamTrack>> tracks;
+ tracks.push_back(track);
+ MediaStream* stream =
+ MediaStream::Create(scope.GetExecutionContext(), tracks);
+ ASSERT_TRUE(stream);
+
+ EXPECT_FALSE(pc->GetTrack(track_component.Get()));
+ AddStream(scope, pc, stream);
+ EXPECT_TRUE(pc->GetTrack(track_component.Get()));
+
+ RemoveStream(scope, pc, stream);
+ }
- RemoveStream(scope, pc, stream);
// This will destroy |MediaStream| and |MediaStreamTrack| (but not
// |MediaStreamComponent|), which will remove its mapping from the peer
// connection.
@@ -201,19 +207,22 @@ TEST_F(RTCPeerConnectionTest, GetTrackRemoveStreamAndGCWithPersistentStream) {
MediaStreamTrack* track =
CreateTrack(scope, MediaStreamSource::kTypeAudio, "audioTrack");
- HeapVector<Member<MediaStreamTrack>> tracks;
- tracks.push_back(track);
- Persistent<MediaStream> stream =
- MediaStream::Create(scope.GetExecutionContext(), tracks);
- ASSERT_TRUE(stream);
-
MediaStreamComponent* track_component = track->Component();
+ Persistent<MediaStream> stream;
- EXPECT_FALSE(pc->GetTrack(track_component));
- AddStream(scope, pc, stream);
- EXPECT_TRUE(pc->GetTrack(track_component));
+ {
+ HeapVector<Member<MediaStreamTrack>> tracks;
+ tracks.push_back(track);
+ stream = MediaStream::Create(scope.GetExecutionContext(), tracks);
+ ASSERT_TRUE(stream);
+
+ EXPECT_FALSE(pc->GetTrack(track_component));
+ AddStream(scope, pc, stream);
+ EXPECT_TRUE(pc->GetTrack(track_component));
+
+ RemoveStream(scope, pc, stream);
+ }
- RemoveStream(scope, pc, stream);
// With a persistent |MediaStream|, the |MediaStreamTrack| and
// |MediaStreamComponent| will not be destroyed and continue to be mapped by
// peer connection.
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtcp_parameters.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtcp_parameters.idl
new file mode 100644
index 00000000000..fc0f417467e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtcp_parameters.idl
@@ -0,0 +1,9 @@
+// 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.
+
+// https://w3c.github.io/webrtc-pc/#rtcrtcpparameters*
+dictionary RTCRtcpParameters {
+ DOMString cname;
+ boolean reducedSize;
+};
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_capabilities.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_capabilities.idl
new file mode 100644
index 00000000000..d189f3755f7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_capabilities.idl
@@ -0,0 +1,9 @@
+// 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.
+
+// https://w3c.github.io/webrtc-pc/#rtcrtpcapabilities*
+dictionary RTCRtpCapabilities {
+ required sequence<RTCRtpCodecCapability> codecs;
+ required sequence<RTCRtpHeaderExtensionCapability> headerExtensions;
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_codec_capability.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_codec_capability.idl
new file mode 100644
index 00000000000..345d84cacf6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_codec_capability.idl
@@ -0,0 +1,11 @@
+// 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.
+
+// https://w3c.github.io/webrtc-pc/#rtcrtpcodeccapability*
+dictionary RTCRtpCodecCapability {
+ required DOMString mimeType;
+ required unsigned long clockRate;
+ unsigned short channels;
+ DOMString sdpFmtpLine;
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_codec_parameters.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_codec_parameters.idl
index 4f1cb44be77..6d478a52787 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_codec_parameters.idl
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_codec_parameters.idl
@@ -4,9 +4,9 @@
// https://w3c.github.io/webrtc-pc/#rtcrtpcodecparameters*
dictionary RTCRtpCodecParameters {
- octet payloadType;
- DOMString mimeType;
- unsigned long clockRate;
- unsigned short channels;
- DOMString sdpFmtpLine;
+ required octet payloadType;
+ required DOMString mimeType;
+ required unsigned long clockRate;
+ unsigned short channels;
+ DOMString sdpFmtpLine;
}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_coding_parameters.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_coding_parameters.idl
new file mode 100644
index 00000000000..ba674153205
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_coding_parameters.idl
@@ -0,0 +1,8 @@
+// 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.
+
+// https://w3c.github.io/webrtc-pc/#rtcrtpcodingparameters
+dictionary RTCRtpCodingParameters {
+ //TODO(orphis): Missing rid. https://crbug.com/857034
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_encoding_parameters.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_encoding_parameters.idl
index 59699705d33..63b427d6dd1 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_encoding_parameters.idl
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_encoding_parameters.idl
@@ -11,8 +11,13 @@ enum RTCPriorityType {
};
// https://w3c.github.io/webrtc-pc/#rtcrtpencodingparameters*
-dictionary RTCRtpEncodingParameters {
+dictionary RTCRtpEncodingParameters : RTCRtpCodingParameters {
+ //TODO(orphis): Missing codecPayloadType. https://crbug.com/857042
+ //TODO(orphis): Missing dtx. https://crbug.com/857044
boolean active = true;
RTCPriorityType priority = "low";
+ //TODO(orphis): Missing ptime. https://crbug.com/857046
unsigned long maxBitrate;
+ //TODO(orphis): Missing maxFramerate. https://crbug.com/857047
+ //TODO(orphis): Missing scaleResolutionDownBy. https://crbug.com/857048
}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_header_extension_capability.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_header_extension_capability.idl
new file mode 100644
index 00000000000..388f11b49ac
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_header_extension_capability.idl
@@ -0,0 +1,8 @@
+// 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.
+
+// https://w3c.github.io/webrtc-pc/#rtcrtpheaderextensioncapability*
+dictionary RTCRtpHeaderExtensionCapability {
+ DOMString uri;
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_header_extension_parameters.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_header_extension_parameters.idl
new file mode 100644
index 00000000000..7cba93f934c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_header_extension_parameters.idl
@@ -0,0 +1,10 @@
+// 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.
+
+// https://w3c.github.io/webrtc-pc/#rtcrtpheaderextensionparameters*
+dictionary RTCRtpHeaderExtensionParameters {
+ required DOMString uri;
+ required unsigned short id;
+ boolean encrypted = false;
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_parameters.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_parameters.idl
index d6ea3e29ed2..da981363393 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_parameters.idl
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_parameters.idl
@@ -4,7 +4,7 @@
// https://w3c.github.io/webrtc-pc/#rtcrtpparameters*
dictionary RTCRtpParameters {
- DOMString transactionId;
- sequence<RTCRtpEncodingParameters> encodings;
- sequence<RTCRtpCodecParameters> codecs;
+ required sequence<RTCRtpHeaderExtensionParameters> headerExtensions;
+ required RTCRtcpParameters rtcp;
+ required sequence<RTCRtpCodecParameters> codecs;
}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
index c19c692a4e5..faa91366739 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
@@ -7,9 +7,11 @@
#include "third_party/blink/public/platform/web_media_stream.h"
#include "third_party/blink/public/platform/web_media_stream_track.h"
#include "third_party/blink/public/platform/web_rtc_rtp_contributing_source.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_capabilities.h"
#include "third_party/blink/renderer/modules/peerconnection/web_rtc_stats_report_callback_resolver.h"
#include "third_party/blink/renderer/platform/bindings/microtask.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/webrtc/api/rtpparameters.h"
namespace blink {
@@ -21,11 +23,6 @@ RTCRtpReceiver::RTCRtpReceiver(std::unique_ptr<WebRTCRtpReceiver> receiver,
streams_(std::move(streams)) {
DCHECK(receiver_);
DCHECK(track_);
- // Some bots require #if around the DCHECK to avoid compile error about
- // |StateMatchesWebReceiver| (which is behind #if) not being defined.
-#if DCHECK_IS_ON()
- DCHECK(StateMatchesWebReceiver());
-#endif // DCHECK_IS_ON()
}
MediaStreamTrack* RTCRtpReceiver::track() const {
@@ -53,27 +50,10 @@ MediaStreamVector RTCRtpReceiver::streams() const {
return streams_;
}
-#if DCHECK_IS_ON()
-
-bool RTCRtpReceiver::StateMatchesWebReceiver() const {
- if (track_->Component() !=
- static_cast<MediaStreamComponent*>(receiver_->Track())) {
- return false;
- }
- WebVector<WebMediaStream> web_streams = receiver_->Streams();
- if (streams_.size() != web_streams.size())
- return false;
- for (size_t i = 0; i < streams_.size(); ++i) {
- if (streams_[i]->Descriptor() !=
- static_cast<MediaStreamDescriptor*>(web_streams[i])) {
- return false;
- }
- }
- return true;
+void RTCRtpReceiver::set_streams(MediaStreamVector streams) {
+ streams_ = std::move(streams);
}
-#endif // DCHECK_IS_ON()
-
void RTCRtpReceiver::UpdateSourcesIfNeeded() {
if (!contributing_sources_needs_updating_)
return;
@@ -114,4 +94,49 @@ void RTCRtpReceiver::Trace(blink::Visitor* visitor) {
ScriptWrappable::Trace(visitor);
}
+void RTCRtpReceiver::getCapabilities(
+ const String& kind,
+ base::Optional<RTCRtpCapabilities>& capabilities) {
+ if (kind != "audio" && kind != "video")
+ return;
+
+ capabilities = RTCRtpCapabilities{};
+
+ std::unique_ptr<webrtc::RtpCapabilities> rtc_capabilities =
+ blink::Platform::Current()->GetRtpSenderCapabilities(kind);
+
+ HeapVector<RTCRtpCodecCapability> codecs;
+ codecs.ReserveInitialCapacity(rtc_capabilities->codecs.size());
+ for (const auto& rtc_codec : rtc_capabilities->codecs) {
+ codecs.emplace_back();
+ auto& codec = codecs.back();
+ codec.setMimeType(WTF::String::FromUTF8(rtc_codec.mime_type().c_str()));
+ if (rtc_codec.clock_rate)
+ codec.setClockRate(rtc_codec.clock_rate.value());
+ if (rtc_codec.num_channels)
+ codec.setChannels(rtc_codec.num_channels.value());
+ if (rtc_codec.parameters.size()) {
+ std::string sdp_fmtp_line;
+ for (const auto& parameter : rtc_codec.parameters) {
+ if (sdp_fmtp_line.size())
+ sdp_fmtp_line += ";";
+ sdp_fmtp_line += parameter.first + "=" + parameter.second;
+ }
+ codec.setSdpFmtpLine(sdp_fmtp_line.c_str());
+ }
+ }
+ capabilities->setCodecs(codecs);
+
+ HeapVector<RTCRtpHeaderExtensionCapability> header_extensions;
+ header_extensions.ReserveInitialCapacity(
+ rtc_capabilities->header_extensions.size());
+ for (const auto& rtc_header_extension : rtc_capabilities->header_extensions) {
+ header_extensions.emplace_back();
+ auto& header_extension = header_extensions.back();
+ header_extension.setUri(
+ WTF::String::FromUTF8(rtc_header_extension.uri.c_str()));
+ }
+ capabilities->setHeaderExtensions(header_extensions);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h
index 840ff7a5ee5..fcc57a5b042 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h
@@ -7,6 +7,7 @@
#include <map>
+#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_rtc_rtp_receiver.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_track.h"
@@ -17,6 +18,7 @@
#include "third_party/blink/renderer/platform/heap/visitor.h"
namespace blink {
+class RTCRtpCapabilities;
// https://w3c.github.io/webrtc-pc/#rtcrtpreceiver-interface
class RTCRtpReceiver final : public ScriptWrappable {
@@ -28,20 +30,21 @@ class RTCRtpReceiver final : public ScriptWrappable {
MediaStreamTrack*,
MediaStreamVector);
+ static void getCapabilities(const String& kind,
+ base::Optional<RTCRtpCapabilities>& result);
+
MediaStreamTrack* track() const;
const HeapVector<Member<RTCRtpContributingSource>>& getContributingSources();
ScriptPromise getStats(ScriptState*);
const WebRTCRtpReceiver& web_receiver() const;
MediaStreamVector streams() const;
+ void set_streams(MediaStreamVector streams);
void UpdateSourcesIfNeeded();
void Trace(blink::Visitor*) override;
private:
-#if DCHECK_IS_ON()
- bool StateMatchesWebReceiver() const;
-#endif // DCHECK_IS_ON()
void SetContributingSourcesNeedsUpdating();
std::unique_ptr<WebRTCRtpReceiver> receiver_;
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.idl
index 39c10496a25..c31fddbb40e 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.idl
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.idl
@@ -6,6 +6,7 @@
[Exposed=Window]
interface RTCRtpReceiver {
readonly attribute MediaStreamTrack track;
+ static RTCRtpCapabilities? getCapabilities(DOMString kind);
sequence<RTCRtpContributingSource> getContributingSources();
[CallWith=ScriptState] Promise<RTCStatsReport> getStats();
// TODO(hbos): Support every member of the spec. https://crbug.com/700916
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_send_parameters.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_send_parameters.idl
new file mode 100644
index 00000000000..29664cbe38d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_send_parameters.idl
@@ -0,0 +1,10 @@
+// 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.
+
+// https://w3c.github.io/webrtc-pc/#rtcsendrtpparameters
+dictionary RTCRtpSendParameters : RTCRtpParameters {
+ required DOMString transactionId;
+ required sequence<RTCRtpEncodingParameters> encodings;
+ //TODO(orphis): Missing degradationPrerence. https://crbug.com/857041
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
index 56489c42d67..74d64280c36 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h"
+
+#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_rtc_dtmf_sender_handler.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
@@ -10,8 +12,10 @@
#include "third_party/blink/renderer/modules/peerconnection/rtc_dtmf_sender.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_error_util.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_capabilities.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_void_request_script_promise_resolver_impl.h"
#include "third_party/blink/renderer/modules/peerconnection/web_rtc_stats_report_callback_resolver.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_void_request.h"
namespace blink {
@@ -32,7 +36,12 @@ class ReplaceTrackRequest : public RTCVoidRequest {
}
void RequestFailed(const webrtc::RTCError& error) override {
- resolver_->Reject(CreateDOMExceptionFromRTCError(error));
+ ScriptState::Scope scope(resolver_->GetScriptState());
+ ExceptionState exception_state(resolver_->GetScriptState()->GetIsolate(),
+ ExceptionState::kExecutionContext,
+ "RTCRtpSender", "replaceTrack");
+ ThrowExceptionFromRTCError(error, exception_state);
+ resolver_->Reject(exception_state);
}
void Trace(blink::Visitor* visitor) override {
@@ -51,7 +60,10 @@ class ReplaceTrackRequest : public RTCVoidRequest {
class SetParametersRequest : public RTCVoidRequestScriptPromiseResolverImpl {
public:
SetParametersRequest(ScriptPromiseResolver* resolver, RTCRtpSender* sender)
- : RTCVoidRequestScriptPromiseResolverImpl(resolver), sender_(sender) {}
+ : RTCVoidRequestScriptPromiseResolverImpl(resolver,
+ "RTCRtpSender",
+ "setParameters"),
+ sender_(sender) {}
void RequestSucceeded() override {
sender_->ClearLastReturnedParameters();
@@ -72,12 +84,13 @@ class SetParametersRequest : public RTCVoidRequestScriptPromiseResolverImpl {
Member<RTCRtpSender> sender_;
};
-bool HasInvalidModification(const RTCRtpParameters& parameters,
- const RTCRtpParameters& new_parameters) {
+bool HasInvalidModification(const RTCRtpSendParameters& parameters,
+ const RTCRtpSendParameters& new_parameters) {
if (parameters.hasTransactionId() != new_parameters.hasTransactionId() ||
(parameters.hasTransactionId() &&
- parameters.transactionId() != new_parameters.transactionId()))
+ parameters.transactionId() != new_parameters.transactionId())) {
return true;
+ }
if (parameters.hasEncodings() != new_parameters.hasEncodings())
return true;
@@ -86,6 +99,45 @@ bool HasInvalidModification(const RTCRtpParameters& parameters,
return true;
}
+ if (parameters.hasHeaderExtensions() != new_parameters.hasHeaderExtensions())
+ return true;
+
+ if (parameters.hasHeaderExtensions()) {
+ if (parameters.headerExtensions().size() !=
+ new_parameters.headerExtensions().size())
+ return true;
+
+ for (size_t i = 0; i < parameters.headerExtensions().size(); ++i) {
+ const auto& header_extension = parameters.headerExtensions()[i];
+ const auto& new_header_extension = new_parameters.headerExtensions()[i];
+ if (header_extension.hasUri() != new_header_extension.hasUri() ||
+ (header_extension.hasUri() &&
+ header_extension.uri() != new_header_extension.uri()) ||
+ header_extension.hasId() != new_header_extension.hasId() ||
+ (header_extension.hasId() &&
+ header_extension.id() != new_header_extension.id()) ||
+ header_extension.hasEncrypted() !=
+ new_header_extension.hasEncrypted() ||
+ (header_extension.hasEncrypted() &&
+ header_extension.encrypted() != new_header_extension.encrypted())) {
+ return true;
+ }
+ }
+ }
+
+ if (parameters.hasRtcp() != new_parameters.hasRtcp() ||
+ (parameters.hasRtcp() &&
+ ((parameters.rtcp().hasCname() != new_parameters.rtcp().hasCname() ||
+ (parameters.rtcp().hasCname() &&
+ parameters.rtcp().cname() != new_parameters.rtcp().cname())) ||
+ (parameters.rtcp().hasReducedSize() !=
+ new_parameters.rtcp().hasReducedSize() ||
+ (parameters.rtcp().hasReducedSize() &&
+ parameters.rtcp().reducedSize() !=
+ new_parameters.rtcp().reducedSize()))))) {
+ return true;
+ }
+
if (parameters.hasCodecs() != new_parameters.hasCodecs())
return true;
@@ -165,20 +217,13 @@ double PriorityToDouble(const WTF::String& priority) {
std::tuple<std::vector<webrtc::RtpEncodingParameters>,
webrtc::DegradationPreference>
-ToRtpParameters(const RTCRtpParameters& parameters) {
+ToRtpParameters(const RTCRtpSendParameters& parameters) {
std::vector<webrtc::RtpEncodingParameters> encodings;
if (parameters.hasEncodings()) {
encodings.reserve(parameters.encodings().size());
for (const auto& encoding : parameters.encodings()) {
- // TODO(orphis): Forward missing fields from the WebRTC library:
- // codecPayloadType, dtx, ptime, maxFramerate, scaleResolutionDownBy,
- // rid
- encodings.push_back({});
- encodings.back().active = encoding.active();
- encodings.back().bitrate_priority = PriorityToDouble(encoding.priority());
- if (encoding.hasMaxBitrate())
- encodings.back().max_bitrate_bps = clampTo<int>(encoding.maxBitrate());
+ encodings.push_back(ToRtpEncodingParameters(encoding));
}
}
@@ -189,18 +234,32 @@ ToRtpParameters(const RTCRtpParameters& parameters) {
} // namespace
+webrtc::RtpEncodingParameters ToRtpEncodingParameters(
+ const RTCRtpEncodingParameters& encoding) {
+ // TODO(orphis): Forward missing fields from the WebRTC library:
+ // codecPayloadType, dtx, ptime, maxFramerate, scaleResolutionDownBy,
+ // rid
+ webrtc::RtpEncodingParameters webrtc_encoding;
+ webrtc_encoding.active = encoding.active();
+ webrtc_encoding.bitrate_priority = PriorityToDouble(encoding.priority());
+ if (encoding.hasMaxBitrate())
+ webrtc_encoding.max_bitrate_bps = clampTo<int>(encoding.maxBitrate());
+ return webrtc_encoding;
+}
+
RTCRtpSender::RTCRtpSender(RTCPeerConnection* pc,
std::unique_ptr<WebRTCRtpSender> sender,
+ String kind,
MediaStreamTrack* track,
MediaStreamVector streams)
: pc_(pc),
sender_(std::move(sender)),
+ kind_(std::move(kind)),
track_(track),
streams_(std::move(streams)) {
DCHECK(pc_);
DCHECK(sender_);
- DCHECK(track_);
- kind_ = track->kind();
+ DCHECK(!track || kind_ == track->kind());
}
MediaStreamTrack* RTCRtpSender::track() {
@@ -212,27 +271,34 @@ ScriptPromise RTCRtpSender::replaceTrack(ScriptState* script_state,
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
if (pc_->IsClosed()) {
- resolver->Reject(DOMException::Create(kInvalidStateError,
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kInvalidStateError,
"The peer connection is closed."));
return promise;
}
WebMediaStreamTrack web_track;
- if (with_track)
+ if (with_track) {
+ pc_->RegisterTrack(with_track);
web_track = with_track->Component();
+ }
ReplaceTrackRequest* request =
new ReplaceTrackRequest(this, with_track, resolver);
sender_->ReplaceTrack(web_track, request);
return promise;
}
-void RTCRtpSender::getParameters(RTCRtpParameters& parameters) {
+void RTCRtpSender::getParameters(RTCRtpSendParameters& parameters) {
// TODO(orphis): Forward missing fields from the WebRTC library:
- // rtcp, headerExtensions, degradationPreference
+ // degradationPreference
std::unique_ptr<webrtc::RtpParameters> webrtc_parameters =
sender_->GetParameters();
parameters.setTransactionId(webrtc_parameters->transaction_id.c_str());
+ RTCRtcpParameters rtcp;
+ rtcp.setCname(webrtc_parameters->rtcp.cname.c_str());
+ rtcp.setReducedSize(webrtc_parameters->rtcp.reduced_size);
+ parameters.setRtcp(rtcp);
+
HeapVector<RTCRtpEncodingParameters> encodings;
encodings.ReserveCapacity(webrtc_parameters->encodings.size());
for (const auto& web_encoding : webrtc_parameters->encodings) {
@@ -248,6 +314,17 @@ void RTCRtpSender::getParameters(RTCRtpParameters& parameters) {
}
parameters.setEncodings(encodings);
+ HeapVector<RTCRtpHeaderExtensionParameters> headers;
+ headers.ReserveCapacity(webrtc_parameters->header_extensions.size());
+ for (const auto& web_header : webrtc_parameters->header_extensions) {
+ headers.emplace_back();
+ RTCRtpHeaderExtensionParameters& header = headers.back();
+ header.setUri(web_header.uri.c_str());
+ header.setId(web_header.id);
+ header.setEncrypted(web_header.encrypt);
+ }
+ parameters.setHeaderExtensions(headers);
+
HeapVector<RTCRtpCodecParameters> codecs;
codecs.ReserveCapacity(webrtc_parameters->codecs.size());
for (const auto& web_codec : webrtc_parameters->codecs) {
@@ -274,14 +351,15 @@ void RTCRtpSender::getParameters(RTCRtpParameters& parameters) {
last_returned_parameters_ = parameters;
}
-ScriptPromise RTCRtpSender::setParameters(ScriptState* script_state,
- const RTCRtpParameters& parameters) {
+ScriptPromise RTCRtpSender::setParameters(
+ ScriptState* script_state,
+ const RTCRtpSendParameters& parameters) {
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
if (!last_returned_parameters_) {
resolver->Reject(DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"getParameters() needs to be called before setParameters()."));
return promise;
}
@@ -292,7 +370,7 @@ ScriptPromise RTCRtpSender::setParameters(ScriptState* script_state,
// level instead.
if (HasInvalidModification(last_returned_parameters_.value(), parameters)) {
resolver->Reject(
- DOMException::Create(kInvalidModificationError,
+ DOMException::Create(DOMExceptionCode::kInvalidModificationError,
"Read-only field modified in setParameters()."));
return promise;
}
@@ -342,6 +420,10 @@ MediaStreamVector RTCRtpSender::streams() const {
return streams_;
}
+void RTCRtpSender::set_streams(MediaStreamVector streams) {
+ streams_ = std::move(streams);
+}
+
RTCDTMFSender* RTCRtpSender::dtmf() {
// Lazy initialization of dtmf_ to avoid overhead when not used.
if (!dtmf_ && kind_ == "audio") {
@@ -365,4 +447,49 @@ void RTCRtpSender::Trace(blink::Visitor* visitor) {
ScriptWrappable::Trace(visitor);
}
+void RTCRtpSender::getCapabilities(
+ const String& kind,
+ base::Optional<RTCRtpCapabilities>& capabilities) {
+ if (kind != "audio" && kind != "video")
+ return;
+
+ capabilities = RTCRtpCapabilities{};
+
+ std::unique_ptr<webrtc::RtpCapabilities> rtc_capabilities =
+ blink::Platform::Current()->GetRtpSenderCapabilities(kind);
+
+ HeapVector<RTCRtpCodecCapability> codecs;
+ codecs.ReserveInitialCapacity(rtc_capabilities->codecs.size());
+ for (const auto& rtc_codec : rtc_capabilities->codecs) {
+ codecs.emplace_back();
+ auto& codec = codecs.back();
+ codec.setMimeType(WTF::String::FromUTF8(rtc_codec.mime_type().c_str()));
+ if (rtc_codec.clock_rate)
+ codec.setClockRate(rtc_codec.clock_rate.value());
+ if (rtc_codec.num_channels)
+ codec.setChannels(rtc_codec.num_channels.value());
+ if (rtc_codec.parameters.size()) {
+ std::string sdp_fmtp_line;
+ for (const auto& parameter : rtc_codec.parameters) {
+ if (sdp_fmtp_line.size())
+ sdp_fmtp_line += ";";
+ sdp_fmtp_line += parameter.first + "=" + parameter.second;
+ }
+ codec.setSdpFmtpLine(sdp_fmtp_line.c_str());
+ }
+ }
+ capabilities->setCodecs(codecs);
+
+ HeapVector<RTCRtpHeaderExtensionCapability> header_extensions;
+ header_extensions.ReserveInitialCapacity(
+ rtc_capabilities->header_extensions.size());
+ for (const auto& rtc_header_extension : rtc_capabilities->header_extensions) {
+ header_extensions.emplace_back();
+ auto& header_extension = header_extensions.back();
+ header_extension.setUri(
+ WTF::String::FromUTF8(rtc_header_extension.uri.c_str()));
+ }
+ capabilities->setHeaderExtensions(header_extensions);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h
index 9f655eafff4..6803a213b32 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h
@@ -8,19 +8,24 @@
#include "third_party/blink/public/platform/web_rtc_rtp_sender.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream.h"
-#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_parameters.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_encoding_parameters.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_send_parameters.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/member.h"
#include "third_party/blink/renderer/platform/heap/visitor.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/webrtc/api/rtptransceiverinterface.h"
namespace blink {
class MediaStreamTrack;
class RTCDTMFSender;
class RTCPeerConnection;
-class RTCRtpParameters;
+class RTCRtpCapabilities;
+
+webrtc::RtpEncodingParameters ToRtpEncodingParameters(
+ const RTCRtpEncodingParameters&);
// https://w3c.github.io/webrtc-pc/#rtcrtpsender-interface
class RTCRtpSender final : public ScriptWrappable {
@@ -31,14 +36,17 @@ class RTCRtpSender final : public ScriptWrappable {
// https://github.com/w3c/webrtc-pc/issues/1712
RTCRtpSender(RTCPeerConnection*,
std::unique_ptr<WebRTCRtpSender>,
+ String kind,
MediaStreamTrack*,
MediaStreamVector streams);
MediaStreamTrack* track();
ScriptPromise replaceTrack(ScriptState*, MediaStreamTrack*);
RTCDTMFSender* dtmf();
- void getParameters(RTCRtpParameters&);
- ScriptPromise setParameters(ScriptState*, const RTCRtpParameters&);
+ static void getCapabilities(const String& kind,
+ base::Optional<RTCRtpCapabilities>& result);
+ void getParameters(RTCRtpSendParameters&);
+ ScriptPromise setParameters(ScriptState*, const RTCRtpSendParameters&);
ScriptPromise getStats(ScriptState*);
WebRTCRtpSender* web_sender();
@@ -47,19 +55,20 @@ class RTCRtpSender final : public ScriptWrappable {
void SetTrack(MediaStreamTrack*);
void ClearLastReturnedParameters();
MediaStreamVector streams() const;
+ void set_streams(MediaStreamVector streams);
void Trace(blink::Visitor*) override;
private:
Member<RTCPeerConnection> pc_;
std::unique_ptr<WebRTCRtpSender> sender_;
- Member<MediaStreamTrack> track_;
- // The spec says that "kind" should be looked up in transceiver, but
- // keeping it in sender at least until transceiver is implemented.
+ // The spec says that "kind" should be looked up in transceiver, but keeping
+ // a copy here as long as we support Plan B.
String kind_;
+ Member<MediaStreamTrack> track_;
Member<RTCDTMFSender> dtmf_;
MediaStreamVector streams_;
- base::Optional<RTCRtpParameters> last_returned_parameters_;
+ base::Optional<RTCRtpSendParameters> last_returned_parameters_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.idl
index be8ed5e0877..dcf54c4adb3 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.idl
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.idl
@@ -6,8 +6,9 @@
[Exposed=Window]
interface RTCRtpSender {
readonly attribute MediaStreamTrack? track;
- [RuntimeEnabled=RTCRtpSenderParameters, CallWith=ScriptState] Promise<void> setParameters(optional RTCRtpParameters parameters);
- [RuntimeEnabled=RTCRtpSenderParameters] RTCRtpParameters getParameters();
+ static RTCRtpCapabilities? getCapabilities(DOMString kind);
+ [RuntimeEnabled=RTCRtpSenderParameters, CallWith=ScriptState] Promise<void> setParameters(optional RTCRtpSendParameters parameters);
+ [RuntimeEnabled=RTCRtpSenderParameters] RTCRtpSendParameters getParameters();
[Measure, CallWith=ScriptState] Promise<void> replaceTrack(MediaStreamTrack? withTrack);
[Measure] readonly attribute RTCDTMFSender? dtmf;
[CallWith=ScriptState] Promise<RTCStatsReport> getStats();
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.cc
new file mode 100644
index 00000000000..789a24c2bea
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.cc
@@ -0,0 +1,200 @@
+// 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/modules/peerconnection/rtc_rtp_transceiver.h"
+
+#include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/heap/member.h"
+#include "third_party/blink/renderer/platform/heap/visitor.h"
+#include "third_party/blink/renderer/platform/wtf/assertions.h"
+
+namespace blink {
+
+namespace {
+
+String TransceiverDirectionToString(
+ const webrtc::RtpTransceiverDirection& direction) {
+ switch (direction) {
+ case webrtc::RtpTransceiverDirection::kSendRecv:
+ return "sendrecv";
+ case webrtc::RtpTransceiverDirection::kSendOnly:
+ return "sendonly";
+ case webrtc::RtpTransceiverDirection::kRecvOnly:
+ return "recvonly";
+ case webrtc::RtpTransceiverDirection::kInactive:
+ return "inactive";
+ }
+}
+
+String OptionalTransceiverDirectionToString(
+ const base::Optional<webrtc::RtpTransceiverDirection>& direction) {
+ return direction ? TransceiverDirectionToString(*direction)
+ : String(); // null
+}
+
+bool TransceiverDirectionFromString(
+ const String& direction_string,
+ base::Optional<webrtc::RtpTransceiverDirection>* direction_out) {
+ if (!direction_string) {
+ *direction_out = base::nullopt;
+ return true;
+ }
+ if (direction_string == "sendrecv") {
+ *direction_out = webrtc::RtpTransceiverDirection::kSendRecv;
+ return true;
+ }
+ if (direction_string == "sendonly") {
+ *direction_out = webrtc::RtpTransceiverDirection::kSendOnly;
+ return true;
+ }
+ if (direction_string == "recvonly") {
+ *direction_out = webrtc::RtpTransceiverDirection::kRecvOnly;
+ return true;
+ }
+ if (direction_string == "inactive") {
+ *direction_out = webrtc::RtpTransceiverDirection::kInactive;
+ return true;
+ }
+ return false;
+}
+
+} // namespace
+
+webrtc::RtpTransceiverInit ToRtpTransceiverInit(
+ const RTCRtpTransceiverInit& init) {
+ webrtc::RtpTransceiverInit webrtc_init;
+ base::Optional<webrtc::RtpTransceiverDirection> direction;
+ if (init.hasDirection() &&
+ TransceiverDirectionFromString(init.direction(), &direction) &&
+ direction) {
+ webrtc_init.direction = *direction;
+ }
+ DCHECK(init.hasStreams());
+ for (const auto& stream : init.streams()) {
+ webrtc_init.stream_ids.push_back(stream->id().Utf8().data());
+ }
+ DCHECK(init.hasSendEncodings());
+ // TODO(orphis,hbos): Pass the encodings down to the lower layer using
+ // ToRtpEncodingParameters() once implemented in third_party/webrtc.
+ // https://crbug.com/803494
+ return webrtc_init;
+}
+
+RTCRtpTransceiver::RTCRtpTransceiver(
+ RTCPeerConnection* pc,
+ std::unique_ptr<WebRTCRtpTransceiver> web_transceiver,
+ RTCRtpSender* sender,
+ RTCRtpReceiver* receiver)
+ : pc_(pc),
+ web_transceiver_(std::move(web_transceiver)),
+ sender_(sender),
+ receiver_(receiver),
+ fired_direction_(base::nullopt) {
+ DCHECK(pc_);
+ DCHECK(web_transceiver_);
+ DCHECK(sender_);
+ DCHECK(receiver_);
+ UpdateMembers();
+}
+
+String RTCRtpTransceiver::mid() const {
+ return web_transceiver_->Mid();
+}
+
+RTCRtpSender* RTCRtpTransceiver::sender() const {
+ return sender_;
+}
+
+RTCRtpReceiver* RTCRtpTransceiver::receiver() const {
+ return receiver_;
+}
+
+bool RTCRtpTransceiver::stopped() const {
+ return stopped_;
+}
+
+String RTCRtpTransceiver::direction() const {
+ return direction_;
+}
+
+void RTCRtpTransceiver::setDirection(String direction,
+ ExceptionState& exception_state) {
+ base::Optional<webrtc::RtpTransceiverDirection> webrtc_direction;
+ if (!TransceiverDirectionFromString(direction, &webrtc_direction) ||
+ !webrtc_direction) {
+ exception_state.ThrowTypeError("Invalid RTCRtpTransceiverDirection.");
+ return;
+ }
+ if (pc_->IsClosed()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "The peer connection is closed.");
+ return;
+ }
+ if (stopped_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "The transceiver is stopped.");
+ return;
+ }
+ web_transceiver_->SetDirection(*webrtc_direction);
+ UpdateMembers();
+}
+
+String RTCRtpTransceiver::currentDirection() const {
+ return current_direction_;
+}
+
+void RTCRtpTransceiver::UpdateMembers() {
+ stopped_ = web_transceiver_->Stopped();
+ direction_ = TransceiverDirectionToString(web_transceiver_->Direction());
+ current_direction_ = OptionalTransceiverDirectionToString(
+ web_transceiver_->CurrentDirection());
+ fired_direction_ = web_transceiver_->FiredDirection();
+}
+
+void RTCRtpTransceiver::OnPeerConnectionClosed() {
+ receiver_->track()->Component()->Source()->SetReadyState(
+ MediaStreamSource::kReadyStateMuted);
+ stopped_ = true;
+ current_direction_ = String(); // null
+}
+
+WebRTCRtpTransceiver* RTCRtpTransceiver::web_transceiver() const {
+ return web_transceiver_.get();
+}
+
+base::Optional<webrtc::RtpTransceiverDirection>
+RTCRtpTransceiver::fired_direction() const {
+ return fired_direction_;
+}
+
+bool RTCRtpTransceiver::DirectionHasSend() const {
+ auto direction = web_transceiver_->Direction();
+ return direction == webrtc::RtpTransceiverDirection::kSendRecv ||
+ direction == webrtc::RtpTransceiverDirection::kSendOnly;
+}
+
+bool RTCRtpTransceiver::DirectionHasRecv() const {
+ auto direction = web_transceiver_->Direction();
+ return direction == webrtc::RtpTransceiverDirection::kSendRecv ||
+ direction == webrtc::RtpTransceiverDirection::kRecvOnly;
+}
+
+bool RTCRtpTransceiver::FiredDirectionHasRecv() const {
+ return fired_direction_ &&
+ (*fired_direction_ == webrtc::RtpTransceiverDirection::kSendRecv ||
+ *fired_direction_ == webrtc::RtpTransceiverDirection::kRecvOnly);
+}
+
+void RTCRtpTransceiver::Trace(Visitor* visitor) {
+ visitor->Trace(pc_);
+ visitor->Trace(sender_);
+ visitor->Trace(receiver_);
+ ScriptWrappable::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.h b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.h
new file mode 100644
index 00000000000..c123616bcd8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.h
@@ -0,0 +1,78 @@
+// 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_MODULES_PEERCONNECTION_RTC_RTP_TRANSCEIVER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_RTP_TRANSCEIVER_H_
+
+#include "base/optional.h"
+#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_init.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/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/heap/member.h"
+#include "third_party/blink/renderer/platform/heap/visitor.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/webrtc/api/rtptransceiverinterface.h"
+
+namespace blink {
+
+class RTCPeerConnection;
+class RTCRtpReceiver;
+class RTCRtpSender;
+
+webrtc::RtpTransceiverInit ToRtpTransceiverInit(const RTCRtpTransceiverInit&);
+
+class RTCRtpTransceiver final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ RTCRtpTransceiver(RTCPeerConnection* pc,
+ std::unique_ptr<WebRTCRtpTransceiver>,
+ RTCRtpSender*,
+ RTCRtpReceiver*);
+
+ // rtc_rtp_transciever.idl
+ String mid() const;
+ RTCRtpSender* sender() const;
+ RTCRtpReceiver* receiver() const;
+ bool stopped() const;
+ // Enum type RTCRtpTransceiverDirection
+ String direction() const;
+ void setDirection(String direction, ExceptionState&);
+ String currentDirection() const;
+
+ // Updates the transceiver attributes by fetching values from
+ // |web_transceiver_|. This is made an explicit operation (rather than
+ // fetching the values from the |web_transceivers_| directly every time an
+ // attribute is read) to make it possible to look at before/after snapshots of
+ // the attributes when a session description has been applied. This is
+ // necessary in order for blink to know when to process the addition/removal
+ // of remote tracks:
+ // https://w3c.github.io/webrtc-pc/#set-the-rtcsessiondescription.
+ void UpdateMembers();
+ void OnPeerConnectionClosed();
+
+ WebRTCRtpTransceiver* web_transceiver() const;
+ base::Optional<webrtc::RtpTransceiverDirection> fired_direction() const;
+ bool DirectionHasSend() const;
+ bool DirectionHasRecv() const;
+ bool FiredDirectionHasRecv() const;
+
+ void Trace(Visitor*) override;
+
+ private:
+ Member<RTCPeerConnection> pc_;
+ std::unique_ptr<WebRTCRtpTransceiver> web_transceiver_;
+ Member<RTCRtpSender> sender_;
+ Member<RTCRtpReceiver> receiver_;
+ bool stopped_;
+ String direction_;
+ String current_direction_;
+ base::Optional<webrtc::RtpTransceiverDirection> fired_direction_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PEERCONNECTION_RTC_RTP_TRANSCEIVER_H_
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.idl
new file mode 100644
index 00000000000..a8ad59befb8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.idl
@@ -0,0 +1,22 @@
+// 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.
+
+// https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiverdirection
+enum RTCRtpTransceiverDirection {
+ "sendrecv",
+ "sendonly",
+ "recvonly",
+ "inactive"
+};
+
+// https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver
+[Exposed=Window]
+interface RTCRtpTransceiver {
+ readonly attribute DOMString? mid;
+ [SameObject] readonly attribute RTCRtpSender sender;
+ [SameObject] readonly attribute RTCRtpReceiver receiver;
+ readonly attribute boolean stopped;
+ [Measure, RaisesException=Setter] attribute RTCRtpTransceiverDirection direction;
+ readonly attribute RTCRtpTransceiverDirection? currentDirection;
+};
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_init.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_init.idl
new file mode 100644
index 00000000000..6c7b886bcd2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_init.idl
@@ -0,0 +1,11 @@
+// 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.
+
+// https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiverinit
+dictionary RTCRtpTransceiverInit {
+ // RTCRtpTransceiverDirection is defined in rtc_rtp_transceiver.idl.
+ RTCRtpTransceiverDirection direction = "sendrecv";
+ sequence<MediaStream> streams = [];
+ sequence<RTCRtpEncodingParameters> sendEncodings = [];
+};
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_session_description_request_impl.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_session_description_request_impl.cc
index 3c57b0bec23..3f7ecf0dc77 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_session_description_request_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_session_description_request_impl.cc
@@ -33,7 +33,6 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/platform/web_rtc_session_description.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_error_util.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_session_description.h"
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_session_description_request_promise_impl.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_session_description_request_promise_impl.cc
index 2e5b9dd1643..c3fc0f392ea 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_session_description_request_promise_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_session_description_request_promise_impl.cc
@@ -7,7 +7,6 @@
#include "third_party/blink/public/platform/web_rtc_session_description.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_error_util.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_session_description.h"
@@ -15,16 +14,23 @@
namespace blink {
RTCSessionDescriptionRequestPromiseImpl*
-RTCSessionDescriptionRequestPromiseImpl::Create(
- RTCPeerConnection* requester,
- ScriptPromiseResolver* resolver) {
- return new RTCSessionDescriptionRequestPromiseImpl(requester, resolver);
+RTCSessionDescriptionRequestPromiseImpl::Create(RTCPeerConnection* requester,
+ ScriptPromiseResolver* resolver,
+ const char* interface_name,
+ const char* property_name) {
+ return new RTCSessionDescriptionRequestPromiseImpl(
+ requester, resolver, interface_name, property_name);
}
RTCSessionDescriptionRequestPromiseImpl::
RTCSessionDescriptionRequestPromiseImpl(RTCPeerConnection* requester,
- ScriptPromiseResolver* resolver)
- : requester_(requester), resolver_(resolver) {
+ ScriptPromiseResolver* resolver,
+ const char* interface_name,
+ const char* property_name)
+ : requester_(requester),
+ resolver_(resolver),
+ interface_name_(interface_name),
+ property_name_(property_name) {
DCHECK(requester_);
DCHECK(resolver_);
}
@@ -50,7 +56,12 @@ void RTCSessionDescriptionRequestPromiseImpl::RequestSucceeded(
void RTCSessionDescriptionRequestPromiseImpl::RequestFailed(
const webrtc::RTCError& error) {
if (requester_ && requester_->ShouldFireDefaultCallbacks()) {
- resolver_->Reject(CreateDOMExceptionFromRTCError(error));
+ ScriptState::Scope scope(resolver_->GetScriptState());
+ ExceptionState exception_state(resolver_->GetScriptState()->GetIsolate(),
+ ExceptionState::kExecutionContext,
+ interface_name_, property_name_);
+ ThrowExceptionFromRTCError(error, exception_state);
+ resolver_->Reject(exception_state);
} else {
// This is needed to have the resolver release its internal resources
// while leaving the associated promise pending as specified.
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_session_description_request_promise_impl.h b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_session_description_request_promise_impl.h
index e29e6d2f984..55583fd8c47 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_session_description_request_promise_impl.h
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_session_description_request_promise_impl.h
@@ -19,7 +19,9 @@ class RTCSessionDescriptionRequestPromiseImpl final
public:
static RTCSessionDescriptionRequestPromiseImpl* Create(
RTCPeerConnection*,
- ScriptPromiseResolver*);
+ ScriptPromiseResolver*,
+ const char* interface_name,
+ const char* property_name);
~RTCSessionDescriptionRequestPromiseImpl() override;
// RTCSessionDescriptionRequest
@@ -30,12 +32,16 @@ class RTCSessionDescriptionRequestPromiseImpl final
private:
RTCSessionDescriptionRequestPromiseImpl(RTCPeerConnection*,
- ScriptPromiseResolver*);
+ ScriptPromiseResolver*,
+ const char* interface_name,
+ const char* property_name);
void Clear();
Member<RTCPeerConnection> requester_;
Member<ScriptPromiseResolver> resolver_;
+ const char* interface_name_;
+ const char* property_name_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event.cc
index 2451c08afc5..075c1008eec 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event.cc
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/modules/mediastream/media_stream.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_track.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h"
+#include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_track_event_init.h"
namespace blink {
@@ -21,18 +22,21 @@ RTCTrackEvent::RTCTrackEvent(const AtomicString& type,
: Event(type, eventInitDict),
receiver_(eventInitDict.receiver()),
track_(eventInitDict.track()),
- streams_(eventInitDict.streams()) {
+ streams_(eventInitDict.streams()),
+ transceiver_(eventInitDict.transceiver()) {
DCHECK(receiver_);
DCHECK(track_);
}
RTCTrackEvent::RTCTrackEvent(RTCRtpReceiver* receiver,
MediaStreamTrack* track,
- const HeapVector<Member<MediaStream>>& streams)
+ const HeapVector<Member<MediaStream>>& streams,
+ RTCRtpTransceiver* transceiver)
: Event(EventTypeNames::track, Bubbles::kNo, Cancelable::kNo),
receiver_(receiver),
track_(track),
- streams_(streams) {
+ streams_(streams),
+ transceiver_(transceiver) {
DCHECK(receiver_);
DCHECK(track_);
}
@@ -49,10 +53,15 @@ HeapVector<Member<MediaStream>> RTCTrackEvent::streams() const {
return streams_;
}
+RTCRtpTransceiver* RTCTrackEvent::transceiver() const {
+ return transceiver_;
+}
+
void RTCTrackEvent::Trace(blink::Visitor* visitor) {
visitor->Trace(receiver_);
visitor->Trace(track_);
visitor->Trace(streams_);
+ visitor->Trace(transceiver_);
Event::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event.h b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event.h
index 575666f9a80..cbeaf6bd0a1 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event.h
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event.h
@@ -15,6 +15,7 @@ namespace blink {
class MediaStream;
class MediaStreamTrack;
class RTCRtpReceiver;
+class RTCRtpTransceiver;
class RTCTrackEventInit;
// https://w3c.github.io/webrtc-pc/#rtctrackevent
@@ -26,11 +27,13 @@ class RTCTrackEvent final : public Event {
const RTCTrackEventInit& eventInitDict);
RTCTrackEvent(RTCRtpReceiver*,
MediaStreamTrack*,
- const HeapVector<Member<MediaStream>>&);
+ const HeapVector<Member<MediaStream>>&,
+ RTCRtpTransceiver*);
RTCRtpReceiver* receiver() const;
MediaStreamTrack* track() const;
HeapVector<Member<MediaStream>> streams() const;
+ RTCRtpTransceiver* transceiver() const;
void Trace(blink::Visitor*) override;
@@ -41,6 +44,7 @@ class RTCTrackEvent final : public Event {
Member<RTCRtpReceiver> receiver_;
Member<MediaStreamTrack> track_;
HeapVector<Member<MediaStream>> streams_;
+ Member<RTCRtpTransceiver> transceiver_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event.idl
index c103db6e2bc..5c55b025712 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event.idl
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event.idl
@@ -11,6 +11,5 @@
readonly attribute MediaStreamTrack track;
[SameObject]
readonly attribute FrozenArray<MediaStream> streams;
- // TODO(hbos): When RTCRtpTransceiver is supported, add:
- // readonly attribute RTCRtpTransceiver transceiver;
+ readonly attribute RTCRtpTransceiver transceiver;
};
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event_init.idl b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event_init.idl
index 74d6c438fa7..f12d204f71c 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event_init.idl
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_track_event_init.idl
@@ -7,6 +7,5 @@ dictionary RTCTrackEventInit : EventInit {
required RTCRtpReceiver receiver;
required MediaStreamTrack track;
sequence<MediaStream> streams = [];
- // TODO(hbos): When RTCRtpTransceiver is supported, add:
- // required RTCRtpTransceiver transceiver;
+ required RTCRtpTransceiver transceiver;
};
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_impl.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_impl.cc
index b7ca76694e5..250c7cb0490 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_impl.cc
@@ -31,7 +31,6 @@
#include "third_party/blink/renderer/modules/peerconnection/rtc_void_request_impl.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_error_util.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h"
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_impl.h b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_impl.h
index df88ffee812..3905e4d8b65 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_impl.h
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_impl.h
@@ -34,7 +34,6 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_void_function.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_peer_connection_error_callback.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/peerconnection/rtc_void_request.h"
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_promise_impl.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_promise_impl.cc
index 5b5fe607ed2..667d3e474d7 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_promise_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_promise_impl.cc
@@ -6,7 +6,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_error_util.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h"
@@ -14,14 +13,22 @@ namespace blink {
RTCVoidRequestPromiseImpl* RTCVoidRequestPromiseImpl::Create(
RTCPeerConnection* requester,
- ScriptPromiseResolver* resolver) {
- return new RTCVoidRequestPromiseImpl(requester, resolver);
+ ScriptPromiseResolver* resolver,
+ const char* interface_name,
+ const char* property_name) {
+ return new RTCVoidRequestPromiseImpl(requester, resolver, interface_name,
+ property_name);
}
RTCVoidRequestPromiseImpl::RTCVoidRequestPromiseImpl(
RTCPeerConnection* requester,
- ScriptPromiseResolver* resolver)
- : requester_(requester), resolver_(resolver) {
+ ScriptPromiseResolver* resolver,
+ const char* interface_name,
+ const char* property_name)
+ : requester_(requester),
+ resolver_(resolver),
+ interface_name_(interface_name),
+ property_name_(property_name) {
DCHECK(requester_);
DCHECK(resolver_);
}
@@ -42,7 +49,12 @@ void RTCVoidRequestPromiseImpl::RequestSucceeded() {
void RTCVoidRequestPromiseImpl::RequestFailed(const webrtc::RTCError& error) {
if (requester_ && requester_->ShouldFireDefaultCallbacks()) {
- resolver_->Reject(CreateDOMExceptionFromRTCError(error));
+ ScriptState::Scope scope(resolver_->GetScriptState());
+ ExceptionState exception_state(resolver_->GetScriptState()->GetIsolate(),
+ ExceptionState::kExecutionContext,
+ interface_name_, property_name_);
+ ThrowExceptionFromRTCError(error, exception_state);
+ resolver_->Reject(exception_state);
} else {
// This is needed to have the resolver release its internal resources
// while leaving the associated promise pending as specified.
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_promise_impl.h b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_promise_impl.h
index 26ddf5329b2..11bf4eea377 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_promise_impl.h
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_promise_impl.h
@@ -16,7 +16,9 @@ class RTCPeerConnection;
class RTCVoidRequestPromiseImpl final : public RTCVoidRequest {
public:
static RTCVoidRequestPromiseImpl* Create(RTCPeerConnection*,
- ScriptPromiseResolver*);
+ ScriptPromiseResolver*,
+ const char* interface_name,
+ const char* property_name);
~RTCVoidRequestPromiseImpl() override;
// RTCVoidRequest
@@ -26,12 +28,17 @@ class RTCVoidRequestPromiseImpl final : public RTCVoidRequest {
void Trace(blink::Visitor*) override;
private:
- RTCVoidRequestPromiseImpl(RTCPeerConnection*, ScriptPromiseResolver*);
+ RTCVoidRequestPromiseImpl(RTCPeerConnection*,
+ ScriptPromiseResolver*,
+ const char* interface_name,
+ const char* property_name);
void Clear();
Member<RTCPeerConnection> requester_;
Member<ScriptPromiseResolver> resolver_;
+ const char* interface_name_;
+ const char* property_name_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_script_promise_resolver_impl.cc b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_script_promise_resolver_impl.cc
index 29f29939aab..17fd6ec747d 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_script_promise_resolver_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_script_promise_resolver_impl.cc
@@ -5,21 +5,26 @@
#include "third_party/blink/renderer/modules/peerconnection/rtc_void_request_script_promise_resolver_impl.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_error_util.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h"
namespace blink {
RTCVoidRequestScriptPromiseResolverImpl*
-RTCVoidRequestScriptPromiseResolverImpl::Create(
- ScriptPromiseResolver* resolver) {
- return new RTCVoidRequestScriptPromiseResolverImpl(resolver);
+RTCVoidRequestScriptPromiseResolverImpl::Create(ScriptPromiseResolver* resolver,
+ const char* interface_name,
+ const char* property_name) {
+ return new RTCVoidRequestScriptPromiseResolverImpl(resolver, interface_name,
+ property_name);
}
RTCVoidRequestScriptPromiseResolverImpl::
- RTCVoidRequestScriptPromiseResolverImpl(ScriptPromiseResolver* resolver)
- : resolver_(resolver) {
+ RTCVoidRequestScriptPromiseResolverImpl(ScriptPromiseResolver* resolver,
+ const char* interface_name,
+ const char* property_name)
+ : resolver_(resolver),
+ interface_name_(interface_name),
+ property_name_(property_name) {
DCHECK(resolver_);
}
@@ -32,7 +37,12 @@ void RTCVoidRequestScriptPromiseResolverImpl::RequestSucceeded() {
void RTCVoidRequestScriptPromiseResolverImpl::RequestFailed(
const webrtc::RTCError& error) {
- resolver_->Reject(CreateDOMExceptionFromRTCError(error));
+ ScriptState::Scope scope(resolver_->GetScriptState());
+ ExceptionState exception_state(resolver_->GetScriptState()->GetIsolate(),
+ ExceptionState::kExecutionContext,
+ interface_name_, property_name_);
+ ThrowExceptionFromRTCError(error, exception_state);
+ resolver_->Reject(exception_state);
}
void RTCVoidRequestScriptPromiseResolverImpl::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_script_promise_resolver_impl.h b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_script_promise_resolver_impl.h
index eed62be224c..73ecbe2fe71 100644
--- a/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_script_promise_resolver_impl.h
+++ b/chromium/third_party/blink/renderer/modules/peerconnection/rtc_void_request_script_promise_resolver_impl.h
@@ -15,7 +15,9 @@ class ScriptPromiseResolver;
class RTCVoidRequestScriptPromiseResolverImpl : public RTCVoidRequest {
public:
static RTCVoidRequestScriptPromiseResolverImpl* Create(
- ScriptPromiseResolver*);
+ ScriptPromiseResolver*,
+ const char* interface_name,
+ const char* property_name);
~RTCVoidRequestScriptPromiseResolverImpl() override;
// RTCVoidRequest
@@ -25,9 +27,13 @@ class RTCVoidRequestScriptPromiseResolverImpl : public RTCVoidRequest {
void Trace(blink::Visitor*) override;
protected:
- RTCVoidRequestScriptPromiseResolverImpl(ScriptPromiseResolver*);
+ RTCVoidRequestScriptPromiseResolverImpl(ScriptPromiseResolver*,
+ const char* interface_name,
+ const char* property_name);
Member<ScriptPromiseResolver> resolver_;
+ const char* interface_name_;
+ const char* property_name_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/permissions/permissions.cc b/chromium/third_party/blink/renderer/modules/permissions/permissions.cc
index 7e25fc49415..20d74e84b64 100644
--- a/chromium/third_party/blink/renderer/modules/permissions/permissions.cc
+++ b/chromium/third_party/blink/renderer/modules/permissions/permissions.cc
@@ -8,16 +8,15 @@
#include <utility>
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_clipboard_permission_descriptor.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_midi_permission_descriptor.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_permission_descriptor.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_push_permission_descriptor.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/dom/exception_code.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_frame.h"
@@ -48,7 +47,7 @@ namespace {
// current context. The caller should make sure that no assumption is made
// after this has been called.
PermissionDescriptorPtr ParsePermission(ScriptState* script_state,
- const Dictionary raw_permission,
+ const ScriptValue raw_permission,
ExceptionState& exception_state) {
PermissionDescriptor permission =
NativeValueTraits<PermissionDescriptor>::NativeValue(
@@ -82,7 +81,7 @@ PermissionDescriptorPtr ParsePermission(ScriptState* script_state,
// Only "userVisibleOnly" push is supported for now.
if (!push_permission.userVisibleOnly()) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"Push Permission without userVisibleOnly:true isn't supported yet.");
return nullptr;
}
@@ -98,11 +97,9 @@ PermissionDescriptorPtr ParsePermission(ScriptState* script_state,
}
if (name == "background-sync")
return CreatePermissionDescriptor(PermissionName::BACKGROUND_SYNC);
- // TODO(riju): Remove runtime flag check when Generic Sensor feature is
- // stable.
if (name == "ambient-light-sensor" || name == "accelerometer" ||
name == "gyroscope" || name == "magnetometer") {
- if (!OriginTrials::sensorEnabled(ExecutionContext::From(script_state))) {
+ if (!RuntimeEnabledFeatures::SensorEnabled()) {
exception_state.ThrowTypeError("GenericSensor flag is not enabled.");
return nullptr;
}
@@ -147,14 +144,12 @@ PermissionDescriptorPtr ParsePermission(ScriptState* script_state,
} // anonymous namespace
ScriptPromise Permissions::query(ScriptState* script_state,
- const Dictionary& raw_permission) {
- ExceptionState exception_state(script_state->GetIsolate(),
- ExceptionState::kGetterContext, "Permissions",
- "query");
+ const ScriptValue& raw_permission,
+ ExceptionState& exception_state) {
PermissionDescriptorPtr descriptor =
ParsePermission(script_state, raw_permission, exception_state);
if (exception_state.HadException())
- return exception_state.Reject(script_state);
+ return ScriptPromise();
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
@@ -173,14 +168,12 @@ ScriptPromise Permissions::query(ScriptState* script_state,
}
ScriptPromise Permissions::request(ScriptState* script_state,
- const Dictionary& raw_permission) {
- ExceptionState exception_state(script_state->GetIsolate(),
- ExceptionState::kGetterContext, "Permissions",
- "request");
+ const ScriptValue& raw_permission,
+ ExceptionState& exception_state) {
PermissionDescriptorPtr descriptor =
ParsePermission(script_state, raw_permission, exception_state);
if (exception_state.HadException())
- return exception_state.Reject(script_state);
+ return ScriptPromise();
ExecutionContext* context = ExecutionContext::From(script_state);
@@ -202,14 +195,12 @@ ScriptPromise Permissions::request(ScriptState* script_state,
}
ScriptPromise Permissions::revoke(ScriptState* script_state,
- const Dictionary& raw_permission) {
- ExceptionState exception_state(script_state->GetIsolate(),
- ExceptionState::kGetterContext, "Permissions",
- "revoke");
+ const ScriptValue& raw_permission,
+ ExceptionState& exception_state) {
PermissionDescriptorPtr descriptor =
ParsePermission(script_state, raw_permission, exception_state);
if (exception_state.HadException())
- return exception_state.Reject(script_state);
+ return ScriptPromise();
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
@@ -226,20 +217,18 @@ ScriptPromise Permissions::revoke(ScriptState* script_state,
ScriptPromise Permissions::requestAll(
ScriptState* script_state,
- const Vector<Dictionary>& raw_permissions) {
- ExceptionState exception_state(script_state->GetIsolate(),
- ExceptionState::kGetterContext, "Permissions",
- "requestAll");
+ const Vector<ScriptValue>& raw_permissions,
+ ExceptionState& exception_state) {
Vector<PermissionDescriptorPtr> internal_permissions;
Vector<int> caller_index_to_internal_index;
caller_index_to_internal_index.resize(raw_permissions.size());
for (size_t i = 0; i < raw_permissions.size(); ++i) {
- const Dictionary& raw_permission = raw_permissions[i];
+ const ScriptValue& raw_permission = raw_permissions[i];
auto descriptor =
ParsePermission(script_state, raw_permission, exception_state);
if (exception_state.HadException())
- return exception_state.Reject(script_state);
+ return ScriptPromise();
// Only append permissions types that are not already present in the vector.
size_t internal_index = kNotFound;
diff --git a/chromium/third_party/blink/renderer/modules/permissions/permissions.h b/chromium/third_party/blink/renderer/modules/permissions/permissions.h
index d9d7d71085d..cfe417b21b1 100644
--- a/chromium/third_party/blink/renderer/modules/permissions/permissions.h
+++ b/chromium/third_party/blink/renderer/modules/permissions/permissions.h
@@ -12,19 +12,21 @@
namespace blink {
-class Dictionary;
class ExecutionContext;
class ScriptPromiseResolver;
class ScriptState;
+class ScriptValue;
class Permissions final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- ScriptPromise query(ScriptState*, const Dictionary&);
- ScriptPromise request(ScriptState*, const Dictionary&);
- ScriptPromise revoke(ScriptState*, const Dictionary&);
- ScriptPromise requestAll(ScriptState*, const Vector<Dictionary>&);
+ ScriptPromise query(ScriptState*, const ScriptValue&, ExceptionState&);
+ ScriptPromise request(ScriptState*, const ScriptValue&, ExceptionState&);
+ ScriptPromise revoke(ScriptState*, const ScriptValue&, ExceptionState&);
+ ScriptPromise requestAll(ScriptState*,
+ const Vector<ScriptValue>&,
+ ExceptionState&);
private:
mojom::blink::PermissionService& GetService(ExecutionContext*);
diff --git a/chromium/third_party/blink/renderer/modules/permissions/permissions.idl b/chromium/third_party/blink/renderer/modules/permissions/permissions.idl
index 121b7624cab..c66fe36bd9d 100644
--- a/chromium/third_party/blink/renderer/modules/permissions/permissions.idl
+++ b/chromium/third_party/blink/renderer/modules/permissions/permissions.idl
@@ -9,8 +9,10 @@
Exposed=(Window,Worker),
RuntimeEnabled=Permissions
] interface Permissions {
- [CallWith=ScriptState, Measure] Promise<PermissionStatus> query(Dictionary permission);
- [RuntimeEnabled=PermissionsRequestRevoke, CallWith=ScriptState, Measure] Promise<PermissionStatus> request(Dictionary permissions);
- [RuntimeEnabled=PermissionsRequestRevoke, CallWith=ScriptState, Measure] Promise<PermissionStatus> revoke(Dictionary permission);
- [RuntimeEnabled=PermissionsRequestRevoke, CallWith=ScriptState, Measure] Promise<sequence<PermissionStatus>> requestAll(sequence<Dictionary> permissions);
+ [CallWith=ScriptState, RaisesException, Measure] Promise<PermissionStatus> query(object permission);
+
+ // Non standard APIs
+ [RuntimeEnabled=PermissionsRequestRevoke, CallWith=ScriptState, RaisesException, Measure] Promise<PermissionStatus> request(object permissions);
+ [RuntimeEnabled=PermissionsRequestRevoke, CallWith=ScriptState, RaisesException, Measure] Promise<PermissionStatus> revoke(object permission);
+ [RuntimeEnabled=PermissionsRequestRevoke, CallWith=ScriptState, RaisesException, Measure] Promise<sequence<PermissionStatus>> requestAll(sequence<object> permissions);
};
diff --git a/chromium/third_party/blink/renderer/modules/picture_in_picture/OWNERS b/chromium/third_party/blink/renderer/modules/picture_in_picture/OWNERS
index 87b34de6d07..b6c67ebc706 100644
--- a/chromium/third_party/blink/renderer/modules/picture_in_picture/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/picture_in_picture/OWNERS
@@ -1,2 +1,5 @@
+beaufort.francois@gmail.com
+mlamouri@chromium.org
+
# TEAM: media-dev@chromium.org
-# COMPONENT: Blink>Media>PictureInPicture \ No newline at end of file
+# COMPONENT: Blink>Media>PictureInPicture
diff --git a/chromium/third_party/blink/renderer/modules/picture_in_picture/document_picture_in_picture.cc b/chromium/third_party/blink/renderer/modules/picture_in_picture/document_picture_in_picture.cc
index 0d752b8c76c..6c2d74cf411 100644
--- a/chromium/third_party/blink/renderer/modules/picture_in_picture/document_picture_in_picture.cc
+++ b/chromium/third_party/blink/renderer/modules/picture_in_picture/document_picture_in_picture.cc
@@ -37,14 +37,14 @@ ScriptPromise DocumentPictureInPicture::exitPictureInPicture(
if (!picture_in_picture_element) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, kNoPictureInPictureElement));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kNoPictureInPictureElement));
}
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
- // TODO(crbug.com/806249): Check element is a video element.
+ DCHECK(IsHTMLVideoElement(picture_in_picture_element));
document.GetTaskRunner(TaskType::kMediaElementEvent)
->PostTask(
FROM_HERE,
diff --git a/chromium/third_party/blink/renderer/modules/picture_in_picture/document_picture_in_picture.idl b/chromium/third_party/blink/renderer/modules/picture_in_picture/document_picture_in_picture.idl
index 63b77888b88..ec0ccfdc396 100644
--- a/chromium/third_party/blink/renderer/modules/picture_in_picture/document_picture_in_picture.idl
+++ b/chromium/third_party/blink/renderer/modules/picture_in_picture/document_picture_in_picture.idl
@@ -6,13 +6,13 @@
// https://wicg.github.io/picture-in-picture/#documentorshadowroot-extension
[
ImplementedAs=DocumentPictureInPicture,
- OriginTrialEnabled=PictureInPictureAPI
+ RuntimeEnabled=PictureInPictureAPI
]
partial interface Document {
[Measure] readonly attribute boolean pictureInPictureEnabled;
- [CallWith=ScriptState, Measure] Promise<void> exitPictureInPicture();
+ [CallWith=ScriptState, Measure, NewObject] Promise<void> exitPictureInPicture();
// TODO(crbug.com/656517): Define this attribute in DocumentOrShadowRoot.
[Measure] readonly attribute HTMLVideoElement? pictureInPictureElement;
-}; \ No newline at end of file
+};
diff --git a/chromium/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.cc b/chromium/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.cc
index 830a85bab7d..02c3959ecf4 100644
--- a/chromium/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.cc
+++ b/chromium/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/public/platform/web_media_player.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/dom/events/event.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
@@ -47,27 +48,32 @@ ScriptPromise HTMLVideoElementPictureInPicture::requestPictureInPicture(
case Status::kFrameDetached:
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kInvalidStateError, kDetachedError));
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kDetachedError));
case Status::kMetadataNotLoaded:
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kInvalidStateError, kMetadataNotLoadedError));
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kMetadataNotLoadedError));
case Status::kVideoTrackNotAvailable:
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kInvalidStateError,
- kVideoTrackNotAvailableError));
+ script_state,
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kVideoTrackNotAvailableError));
case Status::kDisabledByFeaturePolicy:
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kSecurityError, kFeaturePolicyBlocked));
+ script_state, DOMException::Create(DOMExceptionCode::kSecurityError,
+ kFeaturePolicyBlocked));
case Status::kDisabledByAttribute:
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kInvalidStateError,
- kDisablePictureInPicturePresent));
+ script_state,
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kDisablePictureInPicturePresent));
case Status::kDisabledBySystem:
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kNotSupportedError, kNotAvailable));
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ kNotAvailable));
case Status::kEnabled:
break;
}
@@ -78,15 +84,15 @@ ScriptPromise HTMLVideoElementPictureInPicture::requestPictureInPicture(
DCHECK(frame);
if (!Frame::ConsumeTransientUserActivation(frame)) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kNotAllowedError, kUserGestureRequired));
+ script_state, DOMException::Create(DOMExceptionCode::kNotAllowedError,
+ kUserGestureRequired));
}
// TODO(crbug.com/806249): Remove this when MediaStreams are supported.
if (element.GetLoadType() == WebMediaPlayer::kLoadTypeMediaStream) {
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kNotSupportedError,
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
"MediaStreams are not supported yet."));
}
diff --git a/chromium/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.h b/chromium/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.h
index 5e0922a81de..97718342fdd 100644
--- a/chromium/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.h
+++ b/chromium/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.h
@@ -29,6 +29,7 @@ class HTMLVideoElementPictureInPicture {
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(enterpictureinpicture);
DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(leavepictureinpicture);
+ DEFINE_STATIC_ATTRIBUTE_EVENT_LISTENER(pictureinpicturecontrolclick);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.idl b/chromium/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.idl
index fe0c46e71ea..34ee29bcccc 100644
--- a/chromium/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.idl
+++ b/chromium/third_party/blink/renderer/modules/picture_in_picture/html_video_element_picture_in_picture.idl
@@ -5,14 +5,14 @@
// https://wicg.github.io/picture-in-picture/#htmlvideoelement-extensions
[
ImplementedAs=HTMLVideoElementPictureInPicture,
- OriginTrialEnabled=PictureInPictureAPI
+ RuntimeEnabled=PictureInPictureAPI
]
partial interface HTMLVideoElement {
- [CallWith=ScriptState, Measure] Promise<PictureInPictureWindow> requestPictureInPicture();
+ [CallWith=ScriptState, Measure, NewObject] Promise<PictureInPictureWindow> requestPictureInPicture();
attribute EventHandler onenterpictureinpicture;
attribute EventHandler onleavepictureinpicture;
+ [RuntimeEnabled=PictureInPictureControl] attribute EventHandler onpictureinpicturecontrolclick;
[CEReactions, Measure, Reflect] attribute boolean disablePictureInPicture;
-
-}; \ No newline at end of file
+};
diff --git a/chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc b/chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc
index 3fc181446c1..75819a52df2 100644
--- a/chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc
@@ -7,10 +7,12 @@
#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/dom/events/event.h"
+#include "third_party/blink/renderer/core/events/picture_in_picture_control_event.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include "third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_window.h"
#include "third_party/blink/renderer/platform/feature_policy/feature_policy.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
@@ -50,8 +52,7 @@ PictureInPictureControllerImpl::IsDocumentAllowed() const {
// If document is not allowed to use the policy-controlled feature named
// "picture-in-picture", return kDisabledByFeaturePolicy status.
- if (IsSupportedInFeaturePolicy(
- blink::mojom::FeaturePolicyFeature::kPictureInPicture) &&
+ if (RuntimeEnabledFeatures::PictureInPictureAPIEnabled() &&
!frame->IsFeatureEnabled(
blink::mojom::FeaturePolicyFeature::kPictureInPicture)) {
return Status::kDisabledByFeaturePolicy;
@@ -82,9 +83,16 @@ PictureInPictureControllerImpl::IsElementAllowed(
void PictureInPictureControllerImpl::EnterPictureInPicture(
HTMLVideoElement* element,
ScriptPromiseResolver* resolver) {
- element->enterPictureInPicture(WTF::Bind(
- &PictureInPictureControllerImpl::OnEnteredPictureInPicture,
- WrapPersistent(this), WrapPersistent(element), WrapPersistent(resolver)));
+ if (picture_in_picture_element_ != element) {
+ element->enterPictureInPicture(
+ WTF::Bind(&PictureInPictureControllerImpl::OnEnteredPictureInPicture,
+ WrapPersistent(this), WrapPersistent(element),
+ WrapPersistent(resolver)));
+ return;
+ }
+
+ if (resolver)
+ resolver->Resolve(picture_in_picture_window_);
}
void PictureInPictureControllerImpl::OnEnteredPictureInPicture(
@@ -92,9 +100,10 @@ void PictureInPictureControllerImpl::OnEnteredPictureInPicture(
ScriptPromiseResolver* resolver,
const WebSize& picture_in_picture_window_size) {
if (IsElementAllowed(*element) == Status::kDisabledByAttribute) {
- if (resolver)
- resolver->Reject(DOMException::Create(kInvalidStateError, ""));
- // TODO(crbug.com/806249): Test that WMPI sends the message.
+ if (resolver) {
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError, ""));
+ }
element->exitPictureInPicture(base::DoNothing());
return;
}
@@ -153,6 +162,22 @@ void PictureInPictureControllerImpl::OnExitedPictureInPicture(
resolver->Resolve();
}
+void PictureInPictureControllerImpl::OnPictureInPictureControlClicked(
+ const WebString& control_id) {
+ DCHECK(GetSupplementable());
+
+ // Bail out if document is not active.
+ if (!GetSupplementable()->IsActive())
+ return;
+
+ if (RuntimeEnabledFeatures::PictureInPictureControlEnabled() &&
+ picture_in_picture_element_) {
+ picture_in_picture_element_->DispatchEvent(
+ PictureInPictureControlEvent::Create(
+ EventTypeNames::pictureinpicturecontrolclick, control_id));
+ }
+}
+
Element* PictureInPictureControllerImpl::PictureInPictureElement(
TreeScope& scope) const {
if (!picture_in_picture_element_)
@@ -163,8 +188,7 @@ Element* PictureInPictureControllerImpl::PictureInPictureElement(
bool PictureInPictureControllerImpl::IsPictureInPictureElement(
const Element* element) const {
- if (!element)
- return false;
+ DCHECK(element);
return element == picture_in_picture_element_;
}
diff --git a/chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.h b/chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.h
index 94c3d66bfe4..45b0e6aeb02 100644
--- a/chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.h
+++ b/chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.h
@@ -11,6 +11,8 @@ namespace blink {
class HTMLVideoElement;
class PictureInPictureWindow;
+class TreeScope;
+struct WebSize;
// The PictureInPictureControllerImpl is keeping the state and implementing the
// logic around the Picture-in-Picture feature. It is meant to be used as well
@@ -43,23 +45,21 @@ class PictureInPictureControllerImpl : public PictureInPictureController {
// request Picture-in-Picture.
Status IsDocumentAllowed() const;
- // Enter Picture-in-Picture for a video element and resolve promise.
- void EnterPictureInPicture(HTMLVideoElement*, ScriptPromiseResolver*);
-
// Meant to be called internally when an element has entered successfully
// Picture-in-Picture.
void OnEnteredPictureInPicture(HTMLVideoElement*,
ScriptPromiseResolver*,
const WebSize& picture_in_picture_window_size);
- // Exit Picture-in-Picture for a video element and resolve promise if any.
- void ExitPictureInPicture(HTMLVideoElement*, ScriptPromiseResolver*);
-
// Returns element currently in Picture-in-Picture if any. Null otherwise.
Element* PictureInPictureElement(TreeScope&) const;
// Implementation of PictureInPictureController.
+ void EnterPictureInPicture(HTMLVideoElement*,
+ ScriptPromiseResolver*) override;
+ void ExitPictureInPicture(HTMLVideoElement*, ScriptPromiseResolver*) override;
void OnExitedPictureInPicture(ScriptPromiseResolver*) override;
+ void OnPictureInPictureControlClicked(const WebString& control_id) override;
Status IsElementAllowed(const HTMLVideoElement&) const override;
bool IsPictureInPictureElement(const Element*) const override;
diff --git a/chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_window.idl b/chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_window.idl
index 71e98cf3c78..5ec2557d792 100644
--- a/chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_window.idl
+++ b/chromium/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_window.idl
@@ -5,7 +5,7 @@
// https://wicg.github.io/picture-in-picture/#interface-picture-in-picture-window
[
ActiveScriptWrappable,
- OriginTrialEnabled=PictureInPictureAPI
+ RuntimeEnabled=PictureInPictureAPI
]
interface PictureInPictureWindow : EventTarget {
[Measure] readonly attribute long width;
diff --git a/chromium/third_party/blink/renderer/modules/picture_in_picture/shadow_root_picture_in_picture.idl b/chromium/third_party/blink/renderer/modules/picture_in_picture/shadow_root_picture_in_picture.idl
index 3166b31f9a1..89e8103953f 100644
--- a/chromium/third_party/blink/renderer/modules/picture_in_picture/shadow_root_picture_in_picture.idl
+++ b/chromium/third_party/blink/renderer/modules/picture_in_picture/shadow_root_picture_in_picture.idl
@@ -5,9 +5,9 @@
// https://wicg.github.io/picture-in-picture/#documentorshadowroot-extension
[
ImplementedAs=ShadowRootPictureInPicture,
- OriginTrialEnabled=PictureInPictureAPI
+ RuntimeEnabled=PictureInPictureAPI
]
partial interface ShadowRoot {
// TODO(crbug.com/656517): Define this attribute in DocumentOrShadowRoot.
[Measure] readonly attribute HTMLVideoElement? pictureInPictureElement;
-}; \ No newline at end of file
+};
diff --git a/chromium/third_party/blink/renderer/modules/plugins/dom_plugin_array.cc b/chromium/third_party/blink/renderer/modules/plugins/dom_plugin_array.cc
index d601ec5ec67..e8cbb82500f 100644
--- a/chromium/third_party/blink/renderer/modules/plugins/dom_plugin_array.cc
+++ b/chromium/third_party/blink/renderer/modules/plugins/dom_plugin_array.cc
@@ -98,7 +98,7 @@ void DOMPluginArray::refresh(bool reload) {
if (!GetFrame())
return;
- Page::RefreshPlugins();
+ PluginData::RefreshBrowserSidePluginCache();
if (PluginData* data = GetPluginData())
data->ResetPluginData();
@@ -112,7 +112,7 @@ void DOMPluginArray::refresh(bool reload) {
}
if (reload) {
- GetFrame()->Reload(kFrameLoadTypeReload,
+ GetFrame()->Reload(WebFrameLoadType::kReload,
ClientRedirectPolicy::kClientRedirect);
}
}
diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_callbacks.cc b/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_callbacks.cc
index 8b39520b74e..437194d7e6d 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_callbacks.cc
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_callbacks.cc
@@ -19,7 +19,8 @@ DOMException* CreateAvailabilityNotSupportedError() {
"getAvailability() isn't supported at the moment. It can be due to "
"a permanent or temporary system limitation. It is recommended to "
"try to blindly start a presentation in that case.");
- return DOMException::Create(kNotSupportedError, not_supported_error);
+ return DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ not_supported_error);
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_state.cc b/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_state.cc
index a16567168da..ee609bef2f3 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_state.cc
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_availability_state.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/presentation/presentation_availability_state.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/modules/presentation/presentation_availability_observer.h"
#include "third_party/blink/renderer/modules/presentation/presentation_controller.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_connection.cc b/chromium/third_party/blink/renderer/modules/presentation/presentation_connection.cc
index 8669db4aa77..918a2efe481 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_connection.cc
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_connection.cc
@@ -9,7 +9,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/dom/exception_code.h"
#include "third_party/blink/renderer/core/events/message_event.h"
#include "third_party/blink/renderer/core/fileapi/file_reader_loader.h"
#include "third_party/blink/renderer/core/fileapi/file_reader_loader_client.h"
@@ -92,7 +91,7 @@ const AtomicString& ConnectionCloseReasonToString(
}
void ThrowPresentationDisconnectedError(ExceptionState& exception_state) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Presentation connection is disconnected.");
}
diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_connection.h b/chromium/third_party/blink/renderer/modules/presentation/presentation_connection.h
index 0cda9903efd..4012e758d1a 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_connection.h
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_connection.h
@@ -28,6 +28,7 @@ class DOMArrayBufferView;
class PresentationController;
class PresentationReceiver;
class PresentationRequest;
+class WebString;
class PresentationConnection : public EventTargetWithInlineData,
public ContextLifecycleObserver,
diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_error.cc b/chromium/third_party/blink/renderer/modules/presentation/presentation_error.cc
index c98c2152702..adb492e0407 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_error.cc
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_error.cc
@@ -4,26 +4,25 @@
#include "third_party/blink/renderer/modules/presentation/presentation_error.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
namespace blink {
DOMException* CreatePresentationError(
const mojom::blink::PresentationError& error) {
- ExceptionCode code = kUnknownError;
+ DOMExceptionCode code = DOMExceptionCode::kUnknownError;
switch (error.error_type) {
case mojom::blink::PresentationErrorType::NO_AVAILABLE_SCREENS:
case mojom::blink::PresentationErrorType::NO_PRESENTATION_FOUND:
- code = kNotFoundError;
+ code = DOMExceptionCode::kNotFoundError;
break;
case mojom::blink::PresentationErrorType::PRESENTATION_REQUEST_CANCELLED:
- code = kNotAllowedError;
+ code = DOMExceptionCode::kNotAllowedError;
break;
case mojom::blink::PresentationErrorType::PREVIOUS_START_IN_PROGRESS:
- code = kOperationError;
+ code = DOMExceptionCode::kOperationError;
break;
case mojom::blink::PresentationErrorType::UNKNOWN:
- code = kUnknownError;
+ code = DOMExceptionCode::kUnknownError;
break;
}
diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_receiver.cc b/chromium/third_party/blink/renderer/modules/presentation/presentation_receiver.cc
index e20b4314b9f..cfbe7e85d3a 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_receiver.cc
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_receiver.cc
@@ -9,7 +9,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/dom/exception_code.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/core/frame/local_dom_window.h"
diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_request.cc b/chromium/third_party/blink/renderer/modules/presentation/presentation_request.cc
index 483183cd655..4942ca775bd 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_request.cc
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_request.cc
@@ -7,7 +7,6 @@
#include <memory>
#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/document.h"
@@ -25,6 +24,7 @@
#include "third_party/blink/renderer/modules/presentation/presentation_connection_callbacks.h"
#include "third_party/blink/renderer/modules/presentation/presentation_controller.h"
#include "third_party/blink/renderer/modules/presentation/presentation_error.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -37,6 +37,12 @@ Settings* GetSettings(ExecutionContext* execution_context) {
return document->GetSettings();
}
+bool IsKnownProtocolForPresentationUrl(const KURL& url) {
+ // TODO(crbug.com/733381): Restrict to https + custom schemes.
+ return url.ProtocolIsInHTTPFamily() || url.ProtocolIs("cast") ||
+ url.ProtocolIs("cast-dial");
+}
+
} // anonymous namespace
// static
@@ -60,19 +66,14 @@ PresentationRequest* PresentationRequest::Create(
return nullptr;
}
- if (urls.IsEmpty()) {
- exception_state.ThrowDOMException(kNotSupportedError,
- "Do not support empty sequence of URLs.");
- return nullptr;
- }
-
- Vector<KURL> parsed_urls(urls.size());
+ Vector<KURL> parsed_urls;
for (size_t i = 0; i < urls.size(); ++i) {
const KURL& parsed_url = KURL(execution_context->Url(), urls[i]);
if (!parsed_url.IsValid()) {
exception_state.ThrowDOMException(
- kSyntaxError, "'" + urls[i] + "' can't be resolved to a valid URL.");
+ DOMExceptionCode::kSyntaxError,
+ "'" + urls[i] + "' can't be resolved to a valid URL.");
return nullptr;
}
@@ -85,8 +86,16 @@ PresentationRequest* PresentationRequest::Create(
return nullptr;
}
- parsed_urls[i] = parsed_url;
+ if (IsKnownProtocolForPresentationUrl(parsed_url))
+ parsed_urls.push_back(parsed_url);
}
+
+ if (parsed_urls.IsEmpty()) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ "Do not support empty sequence of URLs.");
+ return nullptr;
+ }
+
return new PresentationRequest(execution_context, parsed_urls);
}
@@ -150,7 +159,7 @@ ScriptPromise PresentationRequest::start(ScriptState* script_state) {
return ScriptPromise::RejectWithDOMException(
script_state,
DOMException::Create(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"PresentationRequest::start() requires user gesture."));
PresentationController* controller =
@@ -159,7 +168,7 @@ ScriptPromise PresentationRequest::start(ScriptState* script_state) {
return ScriptPromise::RejectWithDOMException(
script_state,
DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"The PresentationRequest is no longer associated to a frame."));
RecordStartOriginTypeAccess(*execution_context);
@@ -181,7 +190,7 @@ ScriptPromise PresentationRequest::reconnect(ScriptState* script_state,
return ScriptPromise::RejectWithDOMException(
script_state,
DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"The PresentationRequest is no longer associated to a frame."));
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
@@ -211,7 +220,7 @@ ScriptPromise PresentationRequest::getAvailability(ScriptState* script_state) {
return ScriptPromise::RejectWithDOMException(
script_state,
DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"The PresentationRequest is no longer associated to a frame."));
if (!availability_property_) {
diff --git a/chromium/third_party/blink/renderer/modules/presentation/presentation_request_test.cc b/chromium/third_party/blink/renderer/modules/presentation/presentation_request_test.cc
index b0e3ad92000..0623740bb66 100644
--- a/chromium/third_party/blink/renderer/modules/presentation/presentation_request_test.cc
+++ b/chromium/third_party/blink/renderer/modules/presentation/presentation_request_test.cc
@@ -6,8 +6,9 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/core/execution_context/security_context.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
namespace blink {
namespace {
@@ -52,7 +53,8 @@ TEST(PresentationRequestTest, TestMultipleUrlConstructorInvalidUrl) {
PresentationRequest::Create(scope.GetExecutionContext(), urls,
scope.GetExceptionState());
EXPECT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(kSyntaxError, scope.GetExceptionState().Code());
+ EXPECT_EQ(DOMExceptionCode::kSyntaxError,
+ scope.GetExceptionState().CodeAs<DOMExceptionCode>());
}
TEST(PresentationRequestTest, TestMixedContentNotCheckedForNonHttpFamily) {
@@ -61,13 +63,14 @@ TEST(PresentationRequestTest, TestMixedContentNotCheckedForNonHttpFamily) {
SecurityOrigin::CreateFromString("https://example.test"));
PresentationRequest* request = PresentationRequest::Create(
- scope.GetExecutionContext(), "foo://bar", scope.GetExceptionState());
+ scope.GetExecutionContext(), "cast://deadbeef?param=foo",
+ scope.GetExceptionState());
ASSERT_FALSE(scope.GetExceptionState().HadException());
WTF::Vector<KURL> request_urls = request->Urls();
EXPECT_EQ(static_cast<size_t>(1), request_urls.size());
EXPECT_TRUE(request_urls[0].IsValid());
- EXPECT_EQ("foo://bar", request_urls[0].GetString());
+ EXPECT_EQ("cast://deadbeef?param=foo", request_urls[0].GetString());
}
TEST(PresentationRequestTest, TestSingleUrlConstructorMixedContent) {
@@ -78,7 +81,8 @@ TEST(PresentationRequestTest, TestSingleUrlConstructorMixedContent) {
PresentationRequest::Create(scope.GetExecutionContext(), "http://example.com",
scope.GetExceptionState());
EXPECT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(kSecurityError, scope.GetExceptionState().Code());
+ EXPECT_EQ(DOMExceptionCode::kSecurityError,
+ scope.GetExceptionState().CodeAs<DOMExceptionCode>());
}
TEST(PresentationRequestTest, TestMultipleUrlConstructorMixedContent) {
@@ -93,7 +97,8 @@ TEST(PresentationRequestTest, TestMultipleUrlConstructorMixedContent) {
PresentationRequest::Create(scope.GetExecutionContext(), urls,
scope.GetExceptionState());
EXPECT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(kSecurityError, scope.GetExceptionState().Code());
+ EXPECT_EQ(DOMExceptionCode::kSecurityError,
+ scope.GetExceptionState().CodeAs<DOMExceptionCode>());
}
TEST(PresentationRequestTest, TestMultipleUrlConstructorEmptySequence) {
@@ -103,7 +108,50 @@ TEST(PresentationRequestTest, TestMultipleUrlConstructorEmptySequence) {
PresentationRequest::Create(scope.GetExecutionContext(), urls,
scope.GetExceptionState());
EXPECT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(kNotSupportedError, scope.GetExceptionState().Code());
+ EXPECT_EQ(DOMExceptionCode::kNotSupportedError,
+ scope.GetExceptionState().CodeAs<DOMExceptionCode>());
+}
+
+TEST(PresentationRequestTest, TestSingleUrlConstructorUnknownScheme) {
+ V8TestingScope scope;
+ PresentationRequest::Create(scope.GetExecutionContext(), "foobar:unknown",
+ scope.GetExceptionState());
+ EXPECT_TRUE(scope.GetExceptionState().HadException());
+ EXPECT_EQ(DOMExceptionCode::kNotSupportedError,
+ scope.GetExceptionState().CodeAs<DOMExceptionCode>());
+}
+
+TEST(PresentationRequestTest, TestMultipleUrlConstructorSomeUnknownSchemes) {
+ V8TestingScope scope;
+ WTF::Vector<String> urls;
+ urls.push_back("foobar:unknown");
+ urls.push_back("https://example.com");
+ urls.push_back("cast://deadbeef?param=foo");
+ urls.push_back("deadbeef:random");
+
+ PresentationRequest* request = PresentationRequest::Create(
+ scope.GetExecutionContext(), urls, scope.GetExceptionState());
+ ASSERT_FALSE(scope.GetExceptionState().HadException());
+
+ WTF::Vector<KURL> request_urls = request->Urls();
+ EXPECT_EQ(static_cast<size_t>(2), request_urls.size());
+ EXPECT_TRUE(request_urls[0].IsValid());
+ EXPECT_EQ("https://example.com/", request_urls[0].GetString());
+ EXPECT_TRUE(request_urls[1].IsValid());
+ EXPECT_EQ("cast://deadbeef?param=foo", request_urls[1].GetString());
+}
+
+TEST(PresentationRequestTest, TestMultipleUrlConstructorAllUnknownSchemes) {
+ V8TestingScope scope;
+ WTF::Vector<String> urls;
+ urls.push_back("foobar:unknown");
+ urls.push_back("deadbeef:random");
+
+ PresentationRequest::Create(scope.GetExecutionContext(), urls,
+ scope.GetExceptionState());
+ EXPECT_TRUE(scope.GetExceptionState().HadException());
+ EXPECT_EQ(DOMExceptionCode::kNotSupportedError,
+ scope.GetExceptionState().CodeAs<DOMExceptionCode>());
}
} // anonymous namespace
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/DEPS b/chromium/third_party/blink/renderer/modules/push_messaging/DEPS
index ec0a1eb8c01..1e7481b07f4 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/DEPS
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/DEPS
@@ -4,5 +4,5 @@ include_rules = [
"+third_party/blink/renderer/modules/modules_export.h",
"+third_party/blink/renderer/modules/permissions",
"+third_party/blink/renderer/modules/push_messaging",
- "+third_party/blink/renderer/modules/serviceworkers",
+ "+third_party/blink/renderer/modules/service_worker",
]
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_error.cc b/chromium/third_party/blink/renderer/modules/push_messaging/push_error.cc
index 696fed296db..92e342ad50c 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_error.cc
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_error.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/modules/push_messaging/push_error.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink {
@@ -14,23 +13,30 @@ DOMException* PushError::Take(ScriptPromiseResolver* resolver,
const WebPushError& web_error) {
switch (web_error.error_type) {
case WebPushError::kErrorTypeAbort:
- return DOMException::Create(kAbortError, web_error.message);
+ return DOMException::Create(DOMExceptionCode::kAbortError,
+ web_error.message);
case WebPushError::kErrorTypeInvalidState:
- return DOMException::Create(kInvalidStateError, web_error.message);
+ return DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ web_error.message);
case WebPushError::kErrorTypeNetwork:
- return DOMException::Create(kNetworkError, web_error.message);
+ return DOMException::Create(DOMExceptionCode::kNetworkError,
+ web_error.message);
case WebPushError::kErrorTypeNone:
NOTREACHED();
- return DOMException::Create(kUnknownError, web_error.message);
+ return DOMException::Create(DOMExceptionCode::kUnknownError,
+ web_error.message);
case WebPushError::kErrorTypeNotAllowed:
- return DOMException::Create(kNotAllowedError, web_error.message);
+ return DOMException::Create(DOMExceptionCode::kNotAllowedError,
+ web_error.message);
case WebPushError::kErrorTypeNotFound:
- return DOMException::Create(kNotFoundError, web_error.message);
+ return DOMException::Create(DOMExceptionCode::kNotFoundError,
+ web_error.message);
case WebPushError::kErrorTypeNotSupported:
- return DOMException::Create(kNotSupportedError, web_error.message);
+ return DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ web_error.message);
}
NOTREACHED();
- return DOMException::Create(kUnknownError);
+ return DOMException::Create(DOMExceptionCode::kUnknownError);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_event.h b/chromium/third_party/blink/renderer/modules/push_messaging/push_event.h
index bd45590a774..ce17e4ca406 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_event.h
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_event.h
@@ -8,7 +8,7 @@
#include "third_party/blink/renderer/modules/event_modules.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/push_messaging/push_message_data.h"
-#include "third_party/blink/renderer/modules/serviceworkers/extendable_event.h"
+#include "third_party/blink/renderer/modules/service_worker/extendable_event.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_manager.cc b/chromium/third_party/blink/renderer/modules/push_messaging/push_manager.cc
index bc9c442ecb1..6ec4b2964ed 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_manager.cc
@@ -15,7 +15,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/dom/exception_code.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_frame.h"
@@ -26,7 +25,7 @@
#include "third_party/blink/renderer/modules/push_messaging/push_subscription_callbacks.h"
#include "third_party/blink/renderer/modules/push_messaging/push_subscription_options.h"
#include "third_party/blink/renderer/modules/push_messaging/push_subscription_options_init.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
@@ -57,7 +56,7 @@ ScriptPromise PushManager::subscribe(ScriptState* script_state,
if (!registration_->active())
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kAbortError,
+ DOMException::Create(DOMExceptionCode::kAbortError,
"Subscription failed - no active Service Worker"));
const WebPushSubscriptionOptions& web_options =
@@ -77,7 +76,7 @@ ScriptPromise PushManager::subscribe(ScriptState* script_state,
if (!document->domWindow() || !frame)
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kInvalidStateError,
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
"Document is detached from window."));
PushController::ClientFrom(frame).Subscribe(
registration_->WebRegistration(), web_options,
@@ -113,7 +112,7 @@ ScriptPromise PushManager::permissionState(
if (!document->domWindow() || !document->GetFrame())
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kInvalidStateError,
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
"Document is detached from window."));
}
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_message_data.cc b/chromium/third_party/blink/renderer/modules/push_messaging/push_message_data.cc
index 2e8adc5eeae..e5f0b9a6c57 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_message_data.cc
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_message_data.cc
@@ -6,11 +6,11 @@
#include <memory>
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/modules/v8/array_buffer_or_array_buffer_view_or_usv_string.h"
#include "third_party/blink/renderer/core/fileapi/blob.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.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/blob/blob_data.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_bridge.cc b/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_bridge.cc
index 80202fd8ba3..da7c2ff21e7 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_bridge.cc
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_bridge.cc
@@ -6,7 +6,6 @@
#include "third_party/blink/public/platform/modules/push_messaging/web_push_error.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/permissions/permission_utils.h"
#include "third_party/blink/renderer/modules/push_messaging/push_error.h"
#include "third_party/blink/renderer/modules/push_messaging/push_subscription_options_init.h"
@@ -80,8 +79,8 @@ ScriptPromise PushMessagingBridge::GetPermissionState(
//
// TODO(peter): Would it be better to resolve DENIED rather than rejecting?
if (!options.hasUserVisibleOnly() || !options.userVisibleOnly()) {
- resolver->Reject(
- DOMException::Create(kNotSupportedError, kUserVisibleOnlyRequired));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ kUserVisibleOnlyRequired));
return promise;
}
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_bridge.h b/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_bridge.h
index 6e54e1fc4c6..f2690b06198 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_bridge.h
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_messaging_bridge.h
@@ -7,7 +7,7 @@
#include "third_party/blink/public/platform/modules/permissions/permission.mojom-blink.h"
#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom-blink.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/supplementable.h"
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription.cc b/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription.cc
index d8fdf6febc3..2e2032d8723 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription.cc
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription.cc
@@ -13,7 +13,7 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/modules/push_messaging/push_error.h"
#include "third_party/blink/renderer/modules/push_messaging/push_subscription_options.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/base64.h"
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription_callbacks.cc b/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription_callbacks.cc
index 4915d6cb86c..a3e42e93b0f 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription_callbacks.cc
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription_callbacks.cc
@@ -11,7 +11,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/modules/push_messaging/push_error.h"
#include "third_party/blink/renderer/modules/push_messaging/push_subscription.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription_options.cc b/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription_options.cc
index b2e626afd8a..0a7c4810557 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription_options.cc
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription_options.cc
@@ -6,10 +6,9 @@
#include "third_party/blink/public/platform/modules/push_messaging/web_push_subscription_options.h"
#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/modules/push_messaging/push_subscription_options_init.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/ascii_ctype.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -54,7 +53,8 @@ String BufferSourceToString(
return WebString::FromLatin1(input, length);
exception_state.ThrowDOMException(
- kInvalidAccessError, "The provided applicationServerKey is not valid.");
+ DOMExceptionCode::kInvalidAccessError,
+ "The provided applicationServerKey is not valid.");
return String();
}
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription_test.cc b/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription_test.cc
index e6fd6e2e697..f547d844d78 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription_test.cc
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/push_subscription_test.cc
@@ -45,7 +45,7 @@ TEST(PushSubscriptionTest, SerializesToBase64URLWithoutPadding) {
subscription.toJSONForBinding(v8_testing_scope.GetScriptState());
EXPECT_TRUE(json_object.IsObject());
- String json_string = V8StringToWebCoreString<String>(
+ String json_string = ToBlinkString<String>(
v8::JSON::Stringify(v8_testing_scope.GetContext(),
json_object.V8Value().As<v8::Object>())
.ToLocalChecked(),
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/service_worker_registration_push.cc b/chromium/third_party/blink/renderer/modules/push_messaging/service_worker_registration_push.cc
index 1e25905ad82..ac32d649a11 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/service_worker_registration_push.cc
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/service_worker_registration_push.cc
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/modules/push_messaging/service_worker_registration_push.h"
#include "third_party/blink/renderer/modules/push_messaging/push_manager.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/push_messaging/service_worker_registration_push.h b/chromium/third_party/blink/renderer/modules/push_messaging/service_worker_registration_push.h
index 64f58829f81..16a0120f985 100644
--- a/chromium/third_party/blink/renderer/modules/push_messaging/service_worker_registration_push.h
+++ b/chromium/third_party/blink/renderer/modules/push_messaging/service_worker_registration_push.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PUSH_MESSAGING_SERVICE_WORKER_REGISTRATION_PUSH_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_PUSH_MESSAGING_SERVICE_WORKER_REGISTRATION_PUSH_H_
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/supplementable.h"
diff --git a/chromium/third_party/blink/renderer/modules/quota/deprecated_storage_info.cc b/chromium/third_party/blink/renderer/modules/quota/deprecated_storage_info.cc
index d89221c7ed0..47152d209d9 100644
--- a/chromium/third_party/blink/renderer/modules/quota/deprecated_storage_info.cc
+++ b/chromium/third_party/blink/renderer/modules/quota/deprecated_storage_info.cc
@@ -32,7 +32,6 @@
#include "base/location.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/quota/deprecated_storage_quota.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
@@ -52,7 +51,7 @@ void DeprecatedStorageInfo::queryUsageAndQuota(
if (!storage_quota) {
// Unknown storage type is requested.
DeprecatedStorageQuota::EnqueueStorageErrorCallback(
- script_state, error_callback, kNotSupportedError);
+ script_state, error_callback, DOMExceptionCode::kNotSupportedError);
return;
}
storage_quota->queryUsageAndQuota(script_state, success_callback,
@@ -71,7 +70,7 @@ void DeprecatedStorageInfo::requestQuota(
if (!storage_quota) {
// Unknown storage type is requested.
DeprecatedStorageQuota::EnqueueStorageErrorCallback(
- script_state, error_callback, kNotSupportedError);
+ script_state, error_callback, DOMExceptionCode::kNotSupportedError);
return;
}
storage_quota->requestQuota(script_state, new_quota_in_bytes,
diff --git a/chromium/third_party/blink/renderer/modules/quota/deprecated_storage_quota.cc b/chromium/third_party/blink/renderer/modules/quota/deprecated_storage_quota.cc
index 8ad4565cc71..2b9c1cb4e92 100644
--- a/chromium/third_party/blink/renderer/modules/quota/deprecated_storage_quota.cc
+++ b/chromium/third_party/blink/renderer/modules/quota/deprecated_storage_quota.cc
@@ -39,7 +39,6 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_storage_quota_callback.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_storage_usage_callback.h"
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/quota/dom_error.h"
#include "third_party/blink/renderer/modules/quota/quota_utils.h"
@@ -72,8 +71,8 @@ void DeprecatedQueryStorageUsageAndQuotaCallback(
int64_t quota_in_bytes) {
if (status_code != mojom::QuotaStatusCode::kOk) {
if (error_callback) {
- error_callback->InvokeAndReportException(
- nullptr, DOMError::Create(static_cast<ExceptionCode>(status_code)));
+ error_callback->InvokeAndReportException(nullptr,
+ DOMError::Create(status_code));
}
return;
}
@@ -92,8 +91,8 @@ void RequestStorageQuotaCallback(
int64_t granted_quota_in_bytes) {
if (status_code != mojom::QuotaStatusCode::kOk) {
if (error_callback) {
- error_callback->InvokeAndReportException(
- nullptr, DOMError::Create(static_cast<ExceptionCode>(status_code)));
+ error_callback->InvokeAndReportException(nullptr,
+ DOMError::Create(status_code));
}
return;
}
@@ -108,7 +107,7 @@ void RequestStorageQuotaCallback(
void DeprecatedStorageQuota::EnqueueStorageErrorCallback(
ScriptState* script_state,
V8StorageErrorCallback* error_callback,
- ExceptionCode exception_code) {
+ DOMExceptionCode exception_code) {
if (!error_callback)
return;
@@ -137,15 +136,15 @@ void DeprecatedStorageQuota::queryUsageAndQuota(
storage_type != StorageType::kPersistent) {
// Unknown storage type is requested.
EnqueueStorageErrorCallback(script_state, error_callback,
- kNotSupportedError);
+ DOMExceptionCode::kNotSupportedError);
return;
}
const SecurityOrigin* security_origin =
execution_context->GetSecurityOrigin();
- if (security_origin->IsUnique()) {
+ if (security_origin->IsOpaque()) {
EnqueueStorageErrorCallback(script_state, error_callback,
- kNotSupportedError);
+ DOMExceptionCode::kNotSupportedError);
return;
}
@@ -175,7 +174,7 @@ void DeprecatedStorageQuota::requestQuota(
storage_type != StorageType::kPersistent) {
// Unknown storage type is requested.
EnqueueStorageErrorCallback(script_state, error_callback,
- kNotSupportedError);
+ DOMExceptionCode::kNotSupportedError);
return;
}
@@ -186,7 +185,7 @@ void DeprecatedStorageQuota::requestQuota(
Document* document = ToDocument(execution_context);
const SecurityOrigin* security_origin = document->GetSecurityOrigin();
- if (security_origin->IsUnique()) {
+ if (security_origin->IsOpaque()) {
// Unique origins cannot store persistent state.
std::move(callback).Run(blink::mojom::QuotaStatusCode::kErrorAbort, 0, 0);
return;
diff --git a/chromium/third_party/blink/renderer/modules/quota/deprecated_storage_quota.h b/chromium/third_party/blink/renderer/modules/quota/deprecated_storage_quota.h
index cd3ef9a9687..0d5bb07f26d 100644
--- a/chromium/third_party/blink/renderer/modules/quota/deprecated_storage_quota.h
+++ b/chromium/third_party/blink/renderer/modules/quota/deprecated_storage_quota.h
@@ -32,7 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_QUOTA_DEPRECATED_STORAGE_QUOTA_H_
#include "third_party/blink/public/mojom/quota/quota_dispatcher_host.mojom-blink.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_code.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -59,7 +59,7 @@ class DeprecatedStorageQuota final : public ScriptWrappable {
static void EnqueueStorageErrorCallback(ScriptState*,
V8StorageErrorCallback*,
- ExceptionCode);
+ DOMExceptionCode);
void queryUsageAndQuota(ScriptState*,
V8StorageUsageCallback*,
diff --git a/chromium/third_party/blink/renderer/modules/quota/dom_error.cc b/chromium/third_party/blink/renderer/modules/quota/dom_error.cc
index 2b6e13435c2..0a28ba7ea3f 100644
--- a/chromium/third_party/blink/renderer/modules/quota/dom_error.cc
+++ b/chromium/third_party/blink/renderer/modules/quota/dom_error.cc
@@ -27,6 +27,17 @@
namespace blink {
+// static
+DOMError* DOMError::Create(mojom::QuotaStatusCode status_code) {
+ ExceptionCode exception_code = static_cast<ExceptionCode>(status_code);
+ if (IsDOMExceptionCode(exception_code)) {
+ DOMExceptionCode code = static_cast<DOMExceptionCode>(exception_code);
+ return new DOMError(DOMException::GetErrorName(code),
+ DOMException::GetErrorMessage(code));
+ }
+ return new DOMError("UnknownError", "Unknown error.");
+}
+
DOMError::~DOMError() = default;
DOMError::DOMError(const String& name) : name_(name) {}
diff --git a/chromium/third_party/blink/renderer/modules/quota/dom_error.h b/chromium/third_party/blink/renderer/modules/quota/dom_error.h
index e0ff2ab6c7b..b0f902e9da8 100644
--- a/chromium/third_party/blink/renderer/modules/quota/dom_error.h
+++ b/chromium/third_party/blink/renderer/modules/quota/dom_error.h
@@ -26,6 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_QUOTA_DOM_ERROR_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_QUOTA_DOM_ERROR_H_
+#include "third_party/blink/public/mojom/quota/quota_types.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -42,15 +43,11 @@ class MODULES_EXPORT DOMError : public ScriptWrappable {
static DOMError* Create(const String& name, const String& message) {
return new DOMError(name, message);
}
-
- static DOMError* Create(ExceptionCode ec) {
- return new DOMError(DOMException::GetErrorName(ec),
- DOMException::GetErrorMessage(ec));
- }
-
- static DOMError* Create(ExceptionCode ec, const String& message) {
- return new DOMError(DOMException::GetErrorName(ec), message);
+ static DOMError* Create(DOMExceptionCode exception_code) {
+ return new DOMError(DOMException::GetErrorName(exception_code),
+ DOMException::GetErrorMessage(exception_code));
}
+ static DOMError* Create(mojom::QuotaStatusCode status_code);
~DOMError() override;
diff --git a/chromium/third_party/blink/renderer/modules/quota/storage_manager.cc b/chromium/third_party/blink/renderer/modules/quota/storage_manager.cc
index 67d8779afab..297e370f686 100644
--- a/chromium/third_party/blink/renderer/modules/quota/storage_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/quota/storage_manager.cc
@@ -11,7 +11,6 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_storage_estimate.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/dom/exception_code.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_frame.h"
@@ -40,7 +39,7 @@ void QueryStorageUsageAndQuotaCallback(ScriptPromiseResolver* resolver,
// TODO(sashab): Replace this with a switch statement, and remove the enum
// values from QuotaStatusCode.
resolver->Reject(
- DOMException::Create(static_cast<ExceptionCode>(status_code)));
+ DOMException::Create(static_cast<DOMExceptionCode>(status_code)));
return;
}
@@ -59,7 +58,7 @@ ScriptPromise StorageManager::persist(ScriptState* script_state) {
DCHECK(execution_context->IsSecureContext()); // [SecureContext] in IDL
const SecurityOrigin* security_origin =
execution_context->GetSecurityOrigin();
- if (security_origin->IsUnique()) {
+ if (security_origin->IsOpaque()) {
resolver->Reject(V8ThrowException::CreateTypeError(
script_state->GetIsolate(), kUniqueOriginErrorMessage));
return promise;
@@ -84,7 +83,7 @@ ScriptPromise StorageManager::persisted(ScriptState* script_state) {
DCHECK(execution_context->IsSecureContext()); // [SecureContext] in IDL
const SecurityOrigin* security_origin =
execution_context->GetSecurityOrigin();
- if (security_origin->IsUnique()) {
+ if (security_origin->IsOpaque()) {
resolver->Reject(V8ThrowException::CreateTypeError(
script_state->GetIsolate(), kUniqueOriginErrorMessage));
return promise;
@@ -105,7 +104,7 @@ ScriptPromise StorageManager::estimate(ScriptState* script_state) {
DCHECK(execution_context->IsSecureContext()); // [SecureContext] in IDL
const SecurityOrigin* security_origin =
execution_context->GetSecurityOrigin();
- if (security_origin->IsUnique()) {
+ if (security_origin->IsOpaque()) {
resolver->Reject(V8ThrowException::CreateTypeError(
script_state->GetIsolate(), kUniqueOriginErrorMessage));
return promise;
@@ -155,11 +154,12 @@ mojom::blink::QuotaDispatcherHost& StorageManager::GetQuotaHost(
}
STATIC_ASSERT_ENUM(mojom::QuotaStatusCode::kErrorNotSupported,
- kNotSupportedError);
+ DOMExceptionCode::kNotSupportedError);
STATIC_ASSERT_ENUM(mojom::QuotaStatusCode::kErrorInvalidModification,
- kInvalidModificationError);
+ DOMExceptionCode::kInvalidModificationError);
STATIC_ASSERT_ENUM(mojom::QuotaStatusCode::kErrorInvalidAccess,
- kInvalidAccessError);
-STATIC_ASSERT_ENUM(mojom::QuotaStatusCode::kErrorAbort, kAbortError);
+ DOMExceptionCode::kInvalidAccessError);
+STATIC_ASSERT_ENUM(mojom::QuotaStatusCode::kErrorAbort,
+ DOMExceptionCode::kAbortError);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/remoteplayback/availability_callback_wrapper.cc b/chromium/third_party/blink/renderer/modules/remoteplayback/availability_callback_wrapper.cc
index 05fc406a9d0..5f04db553cb 100644
--- a/chromium/third_party/blink/renderer/modules/remoteplayback/availability_callback_wrapper.cc
+++ b/chromium/third_party/blink/renderer/modules/remoteplayback/availability_callback_wrapper.cc
@@ -32,9 +32,4 @@ void AvailabilityCallbackWrapper::Trace(blink::Visitor* visitor) {
visitor->Trace(bindings_cb_);
}
-void AvailabilityCallbackWrapper::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(bindings_cb_);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/remoteplayback/availability_callback_wrapper.h b/chromium/third_party/blink/renderer/modules/remoteplayback/availability_callback_wrapper.h
index a0f94778ed3..12b81f08264 100644
--- a/chromium/third_party/blink/renderer/modules/remoteplayback/availability_callback_wrapper.h
+++ b/chromium/third_party/blink/renderer/modules/remoteplayback/availability_callback_wrapper.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/callback.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/wtf/compiler.h"
@@ -22,7 +22,7 @@ class V8RemotePlaybackAvailabilityCallback;
// to be kept in the RemotePlayback's |availability_callbacks_| map.
class AvailabilityCallbackWrapper final
: public GarbageCollectedFinalized<AvailabilityCallbackWrapper>,
- public TraceWrapperBase {
+ public NameClient {
WTF_MAKE_NONCOPYABLE(AvailabilityCallbackWrapper);
public:
@@ -33,7 +33,6 @@ class AvailabilityCallbackWrapper final
void Run(RemotePlayback*, bool new_availability);
virtual void Trace(blink::Visitor*);
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "AvailabilityCallbackWrapper";
}
diff --git a/chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc b/chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
index 6212d2ccd24..02e692b9498 100644
--- a/chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
+++ b/chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback.cc
@@ -100,15 +100,16 @@ ScriptPromise RemotePlayback::watchAvailability(
ScriptPromise promise = resolver->Promise();
if (media_element_->FastHasAttribute(HTMLNames::disableremoteplaybackAttr)) {
- resolver->Reject(DOMException::Create(
- kInvalidStateError, "disableRemotePlayback attribute is present."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "disableRemotePlayback attribute is present."));
return promise;
}
int id = WatchAvailabilityInternal(new AvailabilityCallbackWrapper(callback));
if (id == kWatchAvailabilityNotSupported) {
resolver->Reject(DOMException::Create(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"Availability monitoring is not supported on this device."));
return promise;
}
@@ -129,14 +130,16 @@ ScriptPromise RemotePlayback::cancelWatchAvailability(ScriptState* script_state,
ScriptPromise promise = resolver->Promise();
if (media_element_->FastHasAttribute(HTMLNames::disableremoteplaybackAttr)) {
- resolver->Reject(DOMException::Create(
- kInvalidStateError, "disableRemotePlayback attribute is present."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "disableRemotePlayback attribute is present."));
return promise;
}
if (!CancelWatchAvailabilityInternal(id)) {
- resolver->Reject(DOMException::Create(
- kNotFoundError, "A callback with the given id is not found."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kNotFoundError,
+ "A callback with the given id is not found."));
return promise;
}
@@ -150,8 +153,9 @@ ScriptPromise RemotePlayback::cancelWatchAvailability(
ScriptPromise promise = resolver->Promise();
if (media_element_->FastHasAttribute(HTMLNames::disableremoteplaybackAttr)) {
- resolver->Reject(DOMException::Create(
- kInvalidStateError, "disableRemotePlayback attribute is present."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "disableRemotePlayback attribute is present."));
return promise;
}
@@ -167,41 +171,42 @@ ScriptPromise RemotePlayback::prompt(ScriptState* script_state) {
ScriptPromise promise = resolver->Promise();
if (media_element_->FastHasAttribute(HTMLNames::disableremoteplaybackAttr)) {
- resolver->Reject(DOMException::Create(
- kInvalidStateError, "disableRemotePlayback attribute is present."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "disableRemotePlayback attribute is present."));
return promise;
}
if (prompt_promise_resolver_) {
resolver->Reject(DOMException::Create(
- kOperationError,
+ DOMExceptionCode::kOperationError,
"A prompt is already being shown for this media element."));
return promise;
}
if (!Frame::HasTransientUserActivation(media_element_->GetFrame())) {
resolver->Reject(DOMException::Create(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"RemotePlayback::prompt() requires user gesture."));
return promise;
}
if (!RuntimeEnabledFeatures::RemotePlaybackBackendEnabled()) {
resolver->Reject(DOMException::Create(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"The RemotePlayback API is disabled on this platform."));
return promise;
}
if (availability_ == WebRemotePlaybackAvailability::kDeviceNotAvailable) {
- resolver->Reject(DOMException::Create(kNotFoundError,
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
"No remote playback devices found."));
return promise;
}
if (availability_ == WebRemotePlaybackAvailability::kSourceNotCompatible) {
resolver->Reject(DOMException::Create(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"The currentSrc is not compatible with remote playback"));
return promise;
}
@@ -324,8 +329,9 @@ void RemotePlayback::StateChanged(WebRemotePlaybackState state) {
// prompt() succeeded.
if (state_ != WebRemotePlaybackState::kConnected &&
state == WebRemotePlaybackState::kDisconnected) {
- prompt_promise_resolver_->Reject(DOMException::Create(
- kAbortError, "Failed to connect to the remote device."));
+ prompt_promise_resolver_->Reject(
+ DOMException::Create(DOMExceptionCode::kAbortError,
+ "Failed to connect to the remote device."));
} else {
DCHECK((state_ == WebRemotePlaybackState::kDisconnected &&
state == WebRemotePlaybackState::kConnecting) ||
@@ -388,8 +394,8 @@ void RemotePlayback::PromptCancelled() {
if (!prompt_promise_resolver_)
return;
- prompt_promise_resolver_->Reject(
- DOMException::Create(kNotAllowedError, "The prompt was dismissed."));
+ prompt_promise_resolver_->Reject(DOMException::Create(
+ DOMExceptionCode::kNotAllowedError, "The prompt was dismissed."));
prompt_promise_resolver_ = nullptr;
}
@@ -434,8 +440,9 @@ bool RemotePlayback::RemotePlaybackAvailable() const {
void RemotePlayback::RemotePlaybackDisabled() {
if (prompt_promise_resolver_) {
- prompt_promise_resolver_->Reject(DOMException::Create(
- kInvalidStateError, "disableRemotePlayback attribute is present."));
+ prompt_promise_resolver_->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "disableRemotePlayback attribute is present."));
prompt_promise_resolver_ = nullptr;
}
@@ -611,10 +618,4 @@ void RemotePlayback::Trace(blink::Visitor* visitor) {
ContextLifecycleObserver::Trace(visitor);
}
-void RemotePlayback::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- for (auto callback : availability_callbacks_.Values())
- visitor->TraceWrappers(callback);
- EventTargetWithInlineData::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback.h b/chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback.h
index 8d999147254..1179b8996bf 100644
--- a/chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback.h
+++ b/chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback.h
@@ -130,7 +130,6 @@ class MODULES_EXPORT RemotePlayback final
DEFINE_ATTRIBUTE_EVENT_LISTENER(disconnect);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
friend class V8RemotePlayback;
diff --git a/chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback_test.cc b/chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback_test.cc
index 4c444f852bb..2427c47e321 100644
--- a/chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback_test.cc
+++ b/chromium/third_party/blink/renderer/modules/remoteplayback/remote_playback_test.cc
@@ -7,7 +7,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/modules/remoteplayback/web_remote_playback_state.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_remote_playback_availability_callback.h"
#include "third_party/blink/renderer/core/dom/user_gesture_indicator.h"
@@ -17,6 +17,7 @@
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
#include "third_party/blink/renderer/modules/presentation/presentation_controller.h"
#include "third_party/blink/renderer/modules/remoteplayback/html_media_element_remote_playback.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.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"
diff --git a/chromium/third_party/blink/renderer/modules/screen_orientation/lock_orientation_callback.cc b/chromium/third_party/blink/renderer/modules/screen_orientation/lock_orientation_callback.cc
index 1f8091e84b6..3afebe88967 100644
--- a/chromium/third_party/blink/renderer/modules/screen_orientation/lock_orientation_callback.cc
+++ b/chromium/third_party/blink/renderer/modules/screen_orientation/lock_orientation_callback.cc
@@ -6,7 +6,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/screen_orientation/screen_orientation.h"
namespace blink {
@@ -22,29 +21,29 @@ void LockOrientationCallback::OnSuccess() {
}
void LockOrientationCallback::OnError(WebLockOrientationError error) {
- ExceptionCode code = 0;
- String msg = "";
+ DOMExceptionCode code = DOMExceptionCode::kUnknownError;
+ String message = "";
switch (error) {
case kWebLockOrientationErrorNotAvailable:
- code = kNotSupportedError;
- msg = "screen.orientation.lock() is not available on this device.";
+ code = DOMExceptionCode::kNotSupportedError;
+ message = "screen.orientation.lock() is not available on this device.";
break;
case kWebLockOrientationErrorFullscreenRequired:
- code = kSecurityError;
- msg =
+ code = DOMExceptionCode::kSecurityError;
+ message =
"The page needs to be fullscreen in order to call "
"screen.orientation.lock().";
break;
case kWebLockOrientationErrorCanceled:
- code = kAbortError;
- msg =
+ code = DOMExceptionCode::kAbortError;
+ message =
"A call to screen.orientation.lock() or screen.orientation.unlock() "
"canceled this call.";
break;
}
- resolver_->Reject(DOMException::Create(code, msg));
+ resolver_->Reject(DOMException::Create(code, message));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation.cc b/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation.cc
index 6865984cced..2af9f927629 100644
--- a/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation.cc
+++ b/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation.cc
@@ -11,7 +11,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/dom/exception_code.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
#include "third_party/blink/renderer/modules/screen_orientation/lock_orientation_callback.h"
@@ -108,7 +107,7 @@ ScreenOrientation* ScreenOrientation::Create(LocalFrame* frame) {
// created when the LocalFrame is created so we shouldn't be in that
// situation.
// In order to create the ScreenOrientationController lazily, we would need
- // to be able to access WebFrameClient from modules/.
+ // to be able to access WebLocalFrameClient from modules/.
orientation->Controller()->SetOrientation(orientation);
return orientation;
@@ -154,7 +153,7 @@ ScriptPromise ScreenOrientation::lock(ScriptState* state,
if (!document || !Controller()) {
DOMException* exception = DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"The object is no longer associated to a document.");
resolver->Reject(exception);
return promise;
@@ -162,7 +161,7 @@ ScriptPromise ScreenOrientation::lock(ScriptState* state,
if (document->IsSandboxed(kSandboxOrientationLock)) {
DOMException* exception =
- DOMException::Create(kSecurityError,
+ DOMException::Create(DOMExceptionCode::kSecurityError,
"The document is sandboxed and lacks the "
"'allow-orientation-lock' flag.");
resolver->Reject(exception);
diff --git a/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_dispatcher.cc b/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_dispatcher.cc
index 0de3b3da9a2..9d514753652 100644
--- a/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_dispatcher.cc
+++ b/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_dispatcher.cc
@@ -27,7 +27,7 @@ void ScreenOrientationDispatcher::Trace(blink::Visitor* visitor) {
PlatformEventDispatcher::Trace(visitor);
}
-void ScreenOrientationDispatcher::StartListening() {
+void ScreenOrientationDispatcher::StartListening(LocalFrame* frame) {
DCHECK(!listener_);
Platform::Current()->GetConnector()->BindInterface(
diff --git a/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_dispatcher.h b/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_dispatcher.h
index d7365d43ca5..e928d510e6c 100644
--- a/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_dispatcher.h
+++ b/chromium/third_party/blink/renderer/modules/screen_orientation/screen_orientation_dispatcher.h
@@ -36,7 +36,7 @@ class ScreenOrientationDispatcher final
ScreenOrientationDispatcher();
// Inherited from PlatformEventDispatcher.
- void StartListening() override;
+ void StartListening(LocalFrame*) override;
void StopListening() override;
device::mojom::blink::ScreenOrientationListenerPtr listener_;
diff --git a/chromium/third_party/blink/renderer/modules/sensor/OWNERS b/chromium/third_party/blink/renderer/modules/sensor/OWNERS
index 0c8539395e9..655a26ab830 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/sensor/OWNERS
@@ -1,5 +1,4 @@
alexander.shalamov@intel.com
-mikhail.pozdnyakov@intel.com
reillyg@chromium.org
rijubrata.bhaumik@intel.com
timvolodine@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/sensor/README.md b/chromium/third_party/blink/renderer/modules/sensor/README.md
index b3b3faabe85..7cb9d81b2a2 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/README.md
+++ b/chromium/third_party/blink/renderer/modules/sensor/README.md
@@ -1,7 +1,7 @@
# Generic Sensor
`third_party/blink/renderer/modules/sensor` implements the following concrete
-sensor intrefaces based on the [Generic Sensor API]
+sensor interfaces based on the [Generic Sensor API]
(https://w3c.github.io/sensors):
1. [Ambient Light Sensor] (https://w3c.github.io/ambient-light)
1. [Accelerometer] (https://w3c.github.io/accelerometer)
@@ -10,7 +10,7 @@ sensor intrefaces based on the [Generic Sensor API]
1. [Absolute Orientation Sensor] (https://w3c.github.io/orientation-sensor)
The platform-specific parts of the implementation are located in
-`device/generic_sensor`.
+`services/device/generic_sensor`.
## Testing
diff --git a/chromium/third_party/blink/renderer/modules/sensor/absolute_orientation_sensor.idl b/chromium/third_party/blink/renderer/modules/sensor/absolute_orientation_sensor.idl
index 9f8e9437afd..16caeb0a349 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/absolute_orientation_sensor.idl
+++ b/chromium/third_party/blink/renderer/modules/sensor/absolute_orientation_sensor.idl
@@ -6,7 +6,7 @@
// https://w3c.github.io/orientation-sensor/#absoluteorientationsensor-interface
[
- OriginTrialEnabled=Sensor,
+ RuntimeEnabled=Sensor,
Constructor(optional SpatialSensorOptions sensorOptions),
ConstructorCallWith=ExecutionContext,
SecureContext,
diff --git a/chromium/third_party/blink/renderer/modules/sensor/accelerometer.idl b/chromium/third_party/blink/renderer/modules/sensor/accelerometer.idl
index 822afc43f56..34c5608d677 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/accelerometer.idl
+++ b/chromium/third_party/blink/renderer/modules/sensor/accelerometer.idl
@@ -6,7 +6,7 @@
// https://w3c.github.io/accelerometer/#accelerometer-interface
[
- OriginTrialEnabled=Sensor,
+ RuntimeEnabled=Sensor,
Constructor(optional SpatialSensorOptions sensorOptions),
ConstructorCallWith=ExecutionContext,
SecureContext,
diff --git a/chromium/third_party/blink/renderer/modules/sensor/gyroscope.idl b/chromium/third_party/blink/renderer/modules/sensor/gyroscope.idl
index b121251d2f4..944961aff68 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/gyroscope.idl
+++ b/chromium/third_party/blink/renderer/modules/sensor/gyroscope.idl
@@ -6,7 +6,7 @@
// https://w3c.github.io/gyroscope/#gyroscope-interface
[
- OriginTrialEnabled=Sensor,
+ RuntimeEnabled=Sensor,
Constructor(optional SpatialSensorOptions sensorOptions),
ConstructorCallWith=ExecutionContext,
RaisesException=Constructor,
diff --git a/chromium/third_party/blink/renderer/modules/sensor/linear_acceleration_sensor.idl b/chromium/third_party/blink/renderer/modules/sensor/linear_acceleration_sensor.idl
index b9f7e927090..44894260278 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/linear_acceleration_sensor.idl
+++ b/chromium/third_party/blink/renderer/modules/sensor/linear_acceleration_sensor.idl
@@ -6,7 +6,7 @@
// https://w3c.github.io/accelerometer/#linearaccelerationsensor
[
- OriginTrialEnabled=Sensor,
+ RuntimeEnabled=Sensor,
Constructor(optional SpatialSensorOptions sensorOptions),
ConstructorCallWith=ExecutionContext,
SecureContext,
diff --git a/chromium/third_party/blink/renderer/modules/sensor/orientation_sensor.cc b/chromium/third_party/blink/renderer/modules/sensor/orientation_sensor.cc
index 07704d3186b..733c3627f60 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/orientation_sensor.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/orientation_sensor.cc
@@ -4,8 +4,8 @@
#include "third_party/blink/renderer/modules/sensor/orientation_sensor.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/geometry/dom_matrix.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
using device::mojom::blink::SensorType;
@@ -87,7 +87,7 @@ void OrientationSensor::PopulateMatrixInternal(
return;
}
if (!hasReading()) {
- exception_state.ThrowDOMException(kNotReadableError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotReadableError,
"Sensor data is not available.");
return;
}
diff --git a/chromium/third_party/blink/renderer/modules/sensor/orientation_sensor.idl b/chromium/third_party/blink/renderer/modules/sensor/orientation_sensor.idl
index d0a028a6bc2..ecf5ce6aaed 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/orientation_sensor.idl
+++ b/chromium/third_party/blink/renderer/modules/sensor/orientation_sensor.idl
@@ -8,7 +8,7 @@
typedef (Float32Array or Float64Array or DOMMatrix) RotationMatrixType;
[
- OriginTrialEnabled=Sensor,
+ RuntimeEnabled=Sensor,
SecureContext,
Exposed=Window
] interface OrientationSensor : Sensor {
diff --git a/chromium/third_party/blink/renderer/modules/sensor/relative_orientation_sensor.idl b/chromium/third_party/blink/renderer/modules/sensor/relative_orientation_sensor.idl
index 8a6362af149..0b7f746ae21 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/relative_orientation_sensor.idl
+++ b/chromium/third_party/blink/renderer/modules/sensor/relative_orientation_sensor.idl
@@ -6,7 +6,7 @@
// https://w3c.github.io/orientation-sensor/#relativeorientationsensor-interface
[
- OriginTrialEnabled=Sensor,
+ RuntimeEnabled=Sensor,
Constructor(optional SpatialSensorOptions sensorOptions),
ConstructorCallWith=ExecutionContext,
SecureContext,
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor.cc b/chromium/third_party/blink/renderer/modules/sensor/sensor.cc
index 6d481fd2fc2..a819ae10b29 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor.cc
@@ -8,7 +8,6 @@
#include "services/device/public/mojom/sensor.mojom-blink.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/dom/exception_code.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/timing/dom_window_performance.h"
#include "third_party/blink/renderer/core/timing/window_performance.h"
@@ -234,7 +233,7 @@ void Sensor::OnSensorReadingChanged() {
}
}
-void Sensor::OnSensorError(ExceptionCode code,
+void Sensor::OnSensorError(DOMExceptionCode code,
const String& sanitized_message,
const String& unsanitized_message) {
HandleError(code, sanitized_message, unsanitized_message);
@@ -245,7 +244,8 @@ void Sensor::OnAddConfigurationRequestCompleted(bool result) {
return;
if (!result) {
- HandleError(kNotReadableError, "start() call has failed.");
+ HandleError(DOMExceptionCode::kNotReadableError,
+ "start() call has failed.");
return;
}
@@ -262,7 +262,7 @@ void Sensor::Activate() {
InitSensorProxyIfNeeded();
if (!sensor_proxy_) {
- HandleError(kInvalidStateError,
+ HandleError(DOMExceptionCode::kInvalidStateError,
"The Sensor is no longer associated to a frame.");
return;
}
@@ -313,7 +313,7 @@ void Sensor::RequestAddConfiguration() {
WrapWeakPersistent(this)));
}
-void Sensor::HandleError(ExceptionCode code,
+void Sensor::HandleError(DOMExceptionCode code,
const String& sanitized_message,
const String& unsanitized_message) {
if (!GetExecutionContext()) {
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor.h b/chromium/third_party/blink/renderer/modules/sensor/sensor.h
index 08c118b3b82..2bc47db4928 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor.h
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor.h
@@ -16,6 +16,7 @@
#include "third_party/blink/renderer/modules/sensor/sensor_options.h"
#include "third_party/blink/renderer/modules/sensor/sensor_proxy.h"
#include "third_party/blink/renderer/modules/sensor/spatial_sensor_options.h"
+#include "third_party/blink/renderer/platform/bindings/exception_code.h"
#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/web_task_runner.h"
@@ -91,7 +92,7 @@ class Sensor : public EventTargetWithInlineData,
// SensorProxy::Observer overrides.
void OnSensorInitialized() override;
void OnSensorReadingChanged() override;
- void OnSensorError(ExceptionCode,
+ void OnSensorError(DOMExceptionCode,
const String& sanitized_message,
const String& unsanitized_message) override;
@@ -108,15 +109,14 @@ class Sensor : public EventTargetWithInlineData,
void RequestAddConfiguration();
- void HandleError(ExceptionCode = kUnknownError,
- const String& sanitized_message = String(),
+ void HandleError(DOMExceptionCode,
+ const String& sanitized_message,
const String& unsanitized_message = String());
void NotifyReading();
void NotifyActivated();
void NotifyError(DOMException* error);
- private:
double frequency_;
device::mojom::blink::SensorType type_;
SensorState state_;
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor.idl b/chromium/third_party/blink/renderer/modules/sensor/sensor.idl
index 6ea6e8a5967..f33dec6eaf6 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor.idl
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor.idl
@@ -8,7 +8,7 @@
[
ActiveScriptWrappable,
SecureContext,
- OriginTrialEnabled=Sensor,
+ RuntimeEnabled=Sensor,
Exposed=Window
] interface Sensor : EventTarget {
[MeasureAs=GenericSensorActivated] readonly attribute boolean activated;
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor_error_event.idl b/chromium/third_party/blink/renderer/modules/sensor/sensor_error_event.idl
index 64769adcb27..919151d4d00 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor_error_event.idl
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor_error_event.idl
@@ -6,7 +6,7 @@
// https://w3c.github.io/sensors/#sensorerrorevent
[
- OriginTrialEnabled=Sensor,
+ RuntimeEnabled=Sensor,
SecureContext,
Constructor(DOMString type, SensorErrorEventInit eventInitDict),
Exposed=Window
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor_inspector_agent.cc b/chromium/third_party/blink/renderer/modules/sensor/sensor_inspector_agent.cc
index 1aff8de0f6d..d1acd73b023 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor_inspector_agent.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor_inspector_agent.cc
@@ -4,10 +4,12 @@
#include "third_party/blink/renderer/modules/sensor/sensor_inspector_agent.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/inspector/console_message.h"
#include "third_party/blink/renderer/modules/sensor/sensor_provider_proxy.h"
#include "third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.h"
+#include "third_party/blink/renderer/platform/bindings/exception_code.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.cc b/chromium/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.cc
index fab070a9084..33df93deadf 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor_provider_proxy.cc
@@ -79,7 +79,7 @@ SensorProxy* SensorProviderProxy::GetSensorProxy(
void SensorProviderProxy::OnSensorProviderConnectionError() {
sensor_provider_.reset();
for (SensorProxy* sensor : sensor_proxies_) {
- sensor->ReportError(kNotReadableError,
+ sensor->ReportError(DOMExceptionCode::kNotReadableError,
SensorProxy::kDefaultErrorDescription);
}
}
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.cc b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.cc
index 12f25645b02..584ecf60106 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.cc
@@ -56,7 +56,7 @@ void SensorProxy::Detach() {
}
}
-void SensorProxy::ReportError(ExceptionCode code, const String& message) {
+void SensorProxy::ReportError(DOMExceptionCode code, const String& message) {
auto copy = observers_;
for (Observer* observer : copy) {
observer->OnSensorError(code, message, String());
@@ -103,17 +103,30 @@ void SensorProxy::UpdateSuspendedStatus() {
if (!IsInitialized())
return;
- bool page_visible =
- GetPage()->VisibilityState() == mojom::PageVisibilityState::kVisible;
+ if (ShouldSuspendUpdates())
+ Suspend();
+ else
+ Resume();
+}
+
+bool SensorProxy::ShouldSuspendUpdates() const {
+ if (GetPage()->VisibilityState() != mojom::PageVisibilityState::kVisible)
+ return true;
LocalFrame* focused_frame = GetPage()->GetFocusController().FocusedFrame();
- bool main_frame_focused =
- focused_frame && !focused_frame->IsCrossOriginSubframe();
+ if (!focused_frame)
+ return true;
- if (page_visible && main_frame_focused)
- Resume();
- else
- Suspend();
+ LocalFrame* this_frame = provider_->GetSupplementable();
+ if (focused_frame == this_frame)
+ return false;
+
+ const SecurityOrigin* focused_frame_origin =
+ focused_frame->GetSecurityContext()->GetSecurityOrigin();
+ const SecurityOrigin* this_origin =
+ this_frame->GetSecurityContext()->GetSecurityOrigin();
+
+ return !focused_frame_origin->CanAccess(this_origin);
}
SensorProvider* SensorProxy::sensor_provider() const {
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.h b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.h
index e85f93d5f80..63e584bd7a4 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.h
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy.h
@@ -9,9 +9,9 @@
#include "services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.h"
#include "services/device/public/mojom/sensor.mojom-blink.h"
#include "services/device/public/mojom/sensor_provider.mojom-blink.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/page/focus_changed_observer.h"
#include "third_party/blink/renderer/core/page/page_visibility_observer.h"
+#include "third_party/blink/renderer/platform/bindings/exception_code.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
@@ -36,7 +36,7 @@ class SensorProxy : public GarbageCollectedFinalized<SensorProxy>,
// event if needed.
virtual void OnSensorReadingChanged() {}
// An error has occurred.
- virtual void OnSensorError(ExceptionCode,
+ virtual void OnSensorError(DOMExceptionCode,
const String& sanitized_message,
const String& unsanitized_message) {}
};
@@ -58,7 +58,7 @@ class SensorProxy : public GarbageCollectedFinalized<SensorProxy>,
virtual std::pair<double, double> GetFrequencyLimits() const = 0;
virtual void SetReadingForInspector(const device::SensorReading&) {}
- virtual void ReportError(ExceptionCode code, const String& description);
+ virtual void ReportError(DOMExceptionCode code, const String& description);
// Getters.
bool IsInitializing() const { return state_ == kInitializing; }
bool IsInitialized() const { return state_ == kInitialized; }
@@ -103,6 +103,9 @@ class SensorProxy : public GarbageCollectedFinalized<SensorProxy>,
// FocusChangedObserver overrides.
void FocusedFrameChanged() override;
+ // Returns true if conditions to suspend sensor reading updates are met.
+ bool ShouldSuspendUpdates() const;
+
Member<SensorProviderProxy> provider_;
bool detached_ = false;
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.cc b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.cc
index aaaa603e7dc..c52eb7c19f2 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.cc
@@ -95,12 +95,13 @@ void SensorProxyImpl::Resume() {
void SensorProxyImpl::UpdateSensorReading() {
DCHECK(ShouldProcessReadings());
+ DCHECK(shared_buffer_handle_->is_valid());
+
+ // Try to read the latest value from shared memory. Failure should not be
+ // fatal because we only retry a finite number of times.
device::SensorReading reading_data;
- if (!shared_buffer_handle_->is_valid() ||
- !shared_buffer_reader_->GetReading(&reading_data)) {
- HandleSensorError();
+ if (!shared_buffer_reader_->GetReading(&reading_data))
return;
- }
double latest_timestamp = reading_data.timestamp();
if (reading_.timestamp() != latest_timestamp &&
@@ -126,7 +127,8 @@ void SensorProxyImpl::SensorReadingChanged() {
UpdateSensorReading();
}
-void SensorProxyImpl::ReportError(ExceptionCode code, const String& message) {
+void SensorProxyImpl::ReportError(DOMExceptionCode code,
+ const String& message) {
state_ = kUninitialized;
active_frequencies_.clear();
reading_ = device::SensorReading();
@@ -147,9 +149,9 @@ void SensorProxyImpl::ReportError(ExceptionCode code, const String& message) {
void SensorProxyImpl::HandleSensorError(SensorCreationResult error) {
if (error == SensorCreationResult::ERROR_NOT_ALLOWED) {
String description = "Permissions to access sensor are not granted";
- ReportError(kNotAllowedError, std::move(description));
+ ReportError(DOMExceptionCode::kNotAllowedError, std::move(description));
} else {
- ReportError(kNotReadableError, kDefaultErrorDescription);
+ ReportError(DOMExceptionCode::kNotReadableError, kDefaultErrorDescription);
}
}
@@ -191,8 +193,10 @@ void SensorProxyImpl::OnSensorCreated(SensorCreationResult result,
const auto* buffer = static_cast<const device::SensorReadingSharedBuffer*>(
shared_buffer_.get());
- shared_buffer_reader_.reset(
- new device::SensorReadingSharedBufferReader(buffer));
+ shared_buffer_reader_ =
+ std::make_unique<device::SensorReadingSharedBufferReader>(buffer);
+ shared_buffer_reader_->GetReading(&reading_);
+
frequency_limits_.first = params->minimum_frequency;
frequency_limits_.second = params->maximum_frequency;
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.h b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.h
index 8c55c27f824..ac0329b8ba4 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.h
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_impl.h
@@ -41,7 +41,7 @@ class SensorProxyImpl final : public SensorProxy,
device::mojom::blink::SensorConfigurationPtr) override;
double GetDefaultFrequency() const override;
std::pair<double, double> GetFrequencyLimits() const override;
- void ReportError(ExceptionCode code, const String& message) override;
+ void ReportError(DOMExceptionCode code, const String& message) override;
void Suspend() override;
void Resume() override;
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.cc b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.cc
index 5016e51d7c2..67bb5840d19 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.cc
@@ -7,6 +7,7 @@
#include "services/device/public/cpp/generic_sensor/sensor_traits.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_thread.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/modules/sensor/sensor_reading_remapper.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
@@ -80,7 +81,7 @@ void SensorProxyInspectorImpl::SetReadingForInspector(
observer->OnSensorReadingChanged();
}
-void SensorProxyInspectorImpl::ReportError(ExceptionCode code,
+void SensorProxyInspectorImpl::ReportError(DOMExceptionCode code,
const String& message) {
state_ = kUninitialized;
reading_ = device::SensorReading();
diff --git a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.h b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.h
index 06b758c81ea..80463f17f03 100644
--- a/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.h
+++ b/chromium/third_party/blink/renderer/modules/sensor/sensor_proxy_inspector_impl.h
@@ -31,7 +31,7 @@ class SensorProxyInspectorImpl final : public SensorProxy {
std::pair<double, double> GetFrequencyLimits() const override;
void SetReadingForInspector(const device::SensorReading&) override;
- void ReportError(ExceptionCode, const String&) override;
+ void ReportError(DOMExceptionCode, const String&) override;
private:
void OnSensorCreated();
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/BUILD.gn b/chromium/third_party/blink/renderer/modules/service_worker/BUILD.gn
new file mode 100644
index 00000000000..15340c6fc0b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/BUILD.gn
@@ -0,0 +1,66 @@
+# 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.
+
+import("//third_party/blink/renderer/modules/modules.gni")
+
+blink_modules_sources("service_worker") {
+ sources = [
+ "extendable_event.cc",
+ "extendable_event.h",
+ "extendable_message_event.cc",
+ "extendable_message_event.h",
+ "fetch_event.cc",
+ "fetch_event.h",
+ "fetch_respond_with_observer.cc",
+ "fetch_respond_with_observer.h",
+ "install_event.cc",
+ "install_event.h",
+ "navigation_preload_callbacks.cc",
+ "navigation_preload_callbacks.h",
+ "navigation_preload_manager.cc",
+ "navigation_preload_manager.h",
+ "navigator_service_worker.cc",
+ "navigator_service_worker.h",
+ "respond_with_observer.cc",
+ "respond_with_observer.h",
+ "service_worker.cc",
+ "service_worker.h",
+ "service_worker_client.cc",
+ "service_worker_client.h",
+ "service_worker_clients.cc",
+ "service_worker_clients.h",
+ "service_worker_container.cc",
+ "service_worker_container.h",
+ "service_worker_container_client.cc",
+ "service_worker_container_client.h",
+ "service_worker_content_settings_proxy.cc",
+ "service_worker_content_settings_proxy.h",
+ "service_worker_error.cc",
+ "service_worker_error.h",
+ "service_worker_global_scope.cc",
+ "service_worker_global_scope.h",
+ "service_worker_global_scope_client.cc",
+ "service_worker_global_scope_client.h",
+ "service_worker_global_scope_proxy.cc",
+ "service_worker_global_scope_proxy.h",
+ "service_worker_installed_scripts_manager.cc",
+ "service_worker_installed_scripts_manager.h",
+ "service_worker_registration.cc",
+ "service_worker_registration.h",
+ "service_worker_script_cached_metadata_handler.cc",
+ "service_worker_script_cached_metadata_handler.h",
+ "service_worker_thread.cc",
+ "service_worker_thread.h",
+ "service_worker_window_client.cc",
+ "service_worker_window_client.h",
+ "service_worker_window_client_callback.cc",
+ "service_worker_window_client_callback.h",
+ "wait_until_observer.cc",
+ "wait_until_observer.h",
+ ]
+
+ public_deps = [
+ "//third_party/blink/renderer/platform",
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/DEPS b/chromium/third_party/blink/renderer/modules/service_worker/DEPS
new file mode 100644
index 00000000000..2a04715c1b4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/DEPS
@@ -0,0 +1,21 @@
+include_rules = [
+ "+mojo/public/cpp/system/data_pipe.h",
+ "+services/network/public/mojom",
+ "-third_party/blink/renderer/modules",
+ "+third_party/blink/renderer/modules/event_modules.h",
+ "+third_party/blink/renderer/modules/event_target_modules.h",
+ "+third_party/blink/renderer/modules/modules_export.h",
+ "+third_party/blink/renderer/modules/service_worker",
+]
+
+specific_include_rules = {
+ "service_worker_global_scope_proxy\.cc": [
+ "+third_party/blink/renderer/modules/background_fetch",
+ "+third_party/blink/renderer/modules/background_sync",
+ "+third_party/blink/renderer/modules/cookie_store",
+ "+third_party/blink/renderer/modules/exported",
+ "+third_party/blink/renderer/modules/notifications",
+ "+third_party/blink/renderer/modules/payments",
+ "+third_party/blink/renderer/modules/push_messaging",
+ ],
+}
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/OWNERS b/chromium/third_party/blink/renderer/modules/service_worker/OWNERS
new file mode 100644
index 00000000000..c4264613708
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/OWNERS
@@ -0,0 +1,5 @@
+file://content/browser/service_worker/OWNERS
+
+# TEAM: worker-dev@chromium.org
+# COMPONENT: Blink>ServiceWorker
+
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/README.md b/chromium/third_party/blink/renderer/modules/service_worker/README.md
new file mode 100644
index 00000000000..29fe7fb441b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/README.md
@@ -0,0 +1,6 @@
+[content/browser/service_worker]: /content/browser/service_worker/README.md
+
+Renderer process code in Blink for service workers. This is the closest code
+to the web-exposed Service Worker API.
+
+See the main service worker documentation in [content/browser/service_worker].
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/client.idl b/chromium/third_party/blink/renderer/modules/service_worker/client.idl
index 27612021a23..27612021a23 100644
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/client.idl
+++ b/chromium/third_party/blink/renderer/modules/service_worker/client.idl
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/client_query_options.idl b/chromium/third_party/blink/renderer/modules/service_worker/client_query_options.idl
index e84083918c4..e84083918c4 100644
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/client_query_options.idl
+++ b/chromium/third_party/blink/renderer/modules/service_worker/client_query_options.idl
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/clients.idl b/chromium/third_party/blink/renderer/modules/service_worker/clients.idl
index 8f90d4dd343..8f90d4dd343 100644
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/clients.idl
+++ b/chromium/third_party/blink/renderer/modules/service_worker/clients.idl
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/extendable_event.cc b/chromium/third_party/blink/renderer/modules/service_worker/extendable_event.cc
new file mode 100644
index 00000000000..6a43b0bd864
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/extendable_event.cc
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2014 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/modules/service_worker/extendable_event.h"
+
+#include "third_party/blink/renderer/modules/service_worker/wait_until_observer.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+
+namespace blink {
+
+ExtendableEvent* ExtendableEvent::Create(
+ const AtomicString& type,
+ const ExtendableEventInit& event_init) {
+ return new ExtendableEvent(type, event_init);
+}
+
+ExtendableEvent* ExtendableEvent::Create(const AtomicString& type,
+ const ExtendableEventInit& event_init,
+ WaitUntilObserver* observer) {
+ return new ExtendableEvent(type, event_init, observer);
+}
+
+ExtendableEvent::~ExtendableEvent() = default;
+
+void ExtendableEvent::waitUntil(ScriptState* script_state,
+ ScriptPromise script_promise,
+ ExceptionState& exception_state) {
+ if (!observer_) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ "Can not call waitUntil on a script constructed ExtendableEvent.");
+ return;
+ }
+
+ observer_->WaitUntil(script_state, script_promise, exception_state);
+}
+
+ExtendableEvent::ExtendableEvent(const AtomicString& type,
+ const ExtendableEventInit& initializer)
+ : Event(type, initializer) {}
+
+ExtendableEvent::ExtendableEvent(const AtomicString& type,
+ const ExtendableEventInit& initializer,
+ WaitUntilObserver* observer)
+ : Event(type, initializer), observer_(observer) {}
+
+const AtomicString& ExtendableEvent::InterfaceName() const {
+ return EventNames::ExtendableEvent;
+}
+
+void ExtendableEvent::Trace(blink::Visitor* visitor) {
+ visitor->Trace(observer_);
+ Event::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/extendable_event.h b/chromium/third_party/blink/renderer/modules/service_worker/extendable_event.h
new file mode 100644
index 00000000000..22a1fa3eea2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/extendable_event.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2014 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_MODULES_SERVICE_WORKER_EXTENDABLE_EVENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_EXTENDABLE_EVENT_H_
+
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/modules/event_modules.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/modules/service_worker/extendable_event_init.h"
+
+namespace blink {
+
+class WaitUntilObserver;
+
+class MODULES_EXPORT ExtendableEvent : public Event {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static ExtendableEvent* Create(const AtomicString& type,
+ const ExtendableEventInit&);
+ static ExtendableEvent* Create(const AtomicString& type,
+ const ExtendableEventInit&,
+ WaitUntilObserver*);
+
+ ~ExtendableEvent() override;
+
+ void waitUntil(ScriptState*, ScriptPromise, ExceptionState&);
+
+ const AtomicString& InterfaceName() const override;
+ void Trace(blink::Visitor*) override;
+
+ protected:
+ ExtendableEvent(const AtomicString& type, const ExtendableEventInit&);
+ ExtendableEvent(const AtomicString& type,
+ const ExtendableEventInit&,
+ WaitUntilObserver*);
+
+ Member<WaitUntilObserver> observer_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_EXTENDABLE_EVENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_event.idl b/chromium/third_party/blink/renderer/modules/service_worker/extendable_event.idl
index a55175d6c8e..a55175d6c8e 100644
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_event.idl
+++ b/chromium/third_party/blink/renderer/modules/service_worker/extendable_event.idl
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_event_init.idl b/chromium/third_party/blink/renderer/modules/service_worker/extendable_event_init.idl
index bef230b9d38..bef230b9d38 100644
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_event_init.idl
+++ b/chromium/third_party/blink/renderer/modules/service_worker/extendable_event_init.idl
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/extendable_message_event.cc b/chromium/third_party/blink/renderer/modules/service_worker/extendable_message_event.cc
new file mode 100644
index 00000000000..c9826adceed
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/extendable_message_event.cc
@@ -0,0 +1,133 @@
+// 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/modules/service_worker/extendable_message_event.h"
+
+namespace blink {
+
+ExtendableMessageEvent* ExtendableMessageEvent::Create(
+ const AtomicString& type,
+ const ExtendableMessageEventInit& initializer) {
+ return new ExtendableMessageEvent(type, initializer);
+}
+
+ExtendableMessageEvent* ExtendableMessageEvent::Create(
+ const AtomicString& type,
+ const ExtendableMessageEventInit& initializer,
+ WaitUntilObserver* observer) {
+ return new ExtendableMessageEvent(type, initializer, observer);
+}
+
+ExtendableMessageEvent* ExtendableMessageEvent::Create(
+ scoped_refptr<SerializedScriptValue> data,
+ const String& origin,
+ MessagePortArray* ports,
+ WaitUntilObserver* observer) {
+ return new ExtendableMessageEvent(std::move(data), origin, ports, observer);
+}
+
+ExtendableMessageEvent* ExtendableMessageEvent::Create(
+ scoped_refptr<SerializedScriptValue> data,
+ const String& origin,
+ MessagePortArray* ports,
+ ServiceWorkerClient* source,
+ WaitUntilObserver* observer) {
+ ExtendableMessageEvent* event =
+ new ExtendableMessageEvent(std::move(data), origin, ports, observer);
+ event->source_as_client_ = source;
+ return event;
+}
+
+ExtendableMessageEvent* ExtendableMessageEvent::Create(
+ scoped_refptr<SerializedScriptValue> data,
+ const String& origin,
+ MessagePortArray* ports,
+ ServiceWorker* source,
+ WaitUntilObserver* observer) {
+ ExtendableMessageEvent* event =
+ new ExtendableMessageEvent(std::move(data), origin, ports, observer);
+ event->source_as_service_worker_ = source;
+ return event;
+}
+
+MessagePortArray ExtendableMessageEvent::ports() const {
+ // TODO(bashi): Currently we return a copied array because the binding
+ // layer could modify the content of the array while executing JS callbacks.
+ // Avoid copying once we can make sure that the binding layer won't
+ // modify the content.
+ if (ports_) {
+ return *ports_;
+ }
+ return MessagePortArray();
+}
+
+void ExtendableMessageEvent::source(
+ ClientOrServiceWorkerOrMessagePort& result) const {
+ if (source_as_client_)
+ result = ClientOrServiceWorkerOrMessagePort::FromClient(source_as_client_);
+ else if (source_as_service_worker_)
+ result = ClientOrServiceWorkerOrMessagePort::FromServiceWorker(
+ source_as_service_worker_);
+ else if (source_as_message_port_)
+ result = ClientOrServiceWorkerOrMessagePort::FromMessagePort(
+ source_as_message_port_);
+ else
+ result = ClientOrServiceWorkerOrMessagePort();
+}
+
+const AtomicString& ExtendableMessageEvent::InterfaceName() const {
+ return EventNames::ExtendableMessageEvent;
+}
+
+void ExtendableMessageEvent::Trace(blink::Visitor* visitor) {
+ visitor->Trace(source_as_client_);
+ visitor->Trace(source_as_service_worker_);
+ visitor->Trace(source_as_message_port_);
+ visitor->Trace(ports_);
+ ExtendableEvent::Trace(visitor);
+}
+
+ExtendableMessageEvent::ExtendableMessageEvent(
+ const AtomicString& type,
+ const ExtendableMessageEventInit& initializer)
+ : ExtendableMessageEvent(type, initializer, nullptr) {}
+
+ExtendableMessageEvent::ExtendableMessageEvent(
+ const AtomicString& type,
+ const ExtendableMessageEventInit& initializer,
+ WaitUntilObserver* observer)
+ : ExtendableEvent(type, initializer, observer) {
+ if (initializer.hasOrigin())
+ origin_ = initializer.origin();
+ if (initializer.hasLastEventId())
+ last_event_id_ = initializer.lastEventId();
+ if (initializer.hasSource()) {
+ if (initializer.source().IsClient())
+ source_as_client_ = initializer.source().GetAsClient();
+ else if (initializer.source().IsServiceWorker())
+ source_as_service_worker_ = initializer.source().GetAsServiceWorker();
+ else if (initializer.source().IsMessagePort())
+ source_as_message_port_ = initializer.source().GetAsMessagePort();
+ }
+ if (initializer.hasPorts())
+ ports_ = new MessagePortArray(initializer.ports());
+}
+
+ExtendableMessageEvent::ExtendableMessageEvent(
+ scoped_refptr<SerializedScriptValue> data,
+ const String& origin,
+ MessagePortArray* ports,
+ WaitUntilObserver* observer)
+ : ExtendableEvent(EventTypeNames::message,
+ ExtendableMessageEventInit(),
+ observer),
+ serialized_data_(std::move(data)),
+ origin_(origin),
+ last_event_id_(String()),
+ ports_(ports) {
+ if (serialized_data_)
+ serialized_data_->RegisterMemoryAllocatedWithCurrentScriptContext();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/extendable_message_event.h b/chromium/third_party/blink/renderer/modules/service_worker/extendable_message_event.h
new file mode 100644
index 00000000000..e56addf886d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/extendable_message_event.h
@@ -0,0 +1,81 @@
+// 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_MODULES_SERVICE_WORKER_EXTENDABLE_MESSAGE_EVENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_EXTENDABLE_MESSAGE_EVENT_H_
+
+#include "third_party/blink/renderer/modules/event_modules.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/modules/service_worker/extendable_event.h"
+#include "third_party/blink/renderer/modules/service_worker/extendable_message_event_init.h"
+
+namespace blink {
+
+class MODULES_EXPORT ExtendableMessageEvent final : public ExtendableEvent {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static ExtendableMessageEvent* Create(
+ const AtomicString& type,
+ const ExtendableMessageEventInit& initializer);
+ static ExtendableMessageEvent* Create(
+ const AtomicString& type,
+ const ExtendableMessageEventInit& initializer,
+ WaitUntilObserver*);
+ static ExtendableMessageEvent* Create(
+ scoped_refptr<SerializedScriptValue> data,
+ const String& origin,
+ MessagePortArray* ports,
+ WaitUntilObserver*);
+ static ExtendableMessageEvent* Create(
+ scoped_refptr<SerializedScriptValue> data,
+ const String& origin,
+ MessagePortArray* ports,
+ ServiceWorkerClient* source,
+ WaitUntilObserver*);
+ static ExtendableMessageEvent* Create(
+ scoped_refptr<SerializedScriptValue> data,
+ const String& origin,
+ MessagePortArray* ports,
+ ServiceWorker* source,
+ WaitUntilObserver*);
+
+ SerializedScriptValue* SerializedData() const {
+ return serialized_data_.get();
+ }
+ void SetSerializedData(scoped_refptr<SerializedScriptValue> serialized_data) {
+ serialized_data_ = std::move(serialized_data);
+ }
+ const String& origin() const { return origin_; }
+ const String& lastEventId() const { return last_event_id_; }
+ MessagePortArray ports() const;
+ void source(ClientOrServiceWorkerOrMessagePort& result) const;
+
+ const AtomicString& InterfaceName() const override;
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ ExtendableMessageEvent(const AtomicString& type,
+ const ExtendableMessageEventInit& initializer);
+ ExtendableMessageEvent(const AtomicString& type,
+ const ExtendableMessageEventInit& initializer,
+ WaitUntilObserver*);
+ ExtendableMessageEvent(scoped_refptr<SerializedScriptValue> data,
+ const String& origin,
+ MessagePortArray* ports,
+ WaitUntilObserver*);
+
+ scoped_refptr<SerializedScriptValue> serialized_data_;
+ String origin_;
+ String last_event_id_;
+ Member<ServiceWorkerClient> source_as_client_;
+ Member<ServiceWorker> source_as_service_worker_;
+ Member<MessagePort> source_as_message_port_;
+ Member<MessagePortArray> ports_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_EXTENDABLE_MESSAGE_EVENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_message_event.idl b/chromium/third_party/blink/renderer/modules/service_worker/extendable_message_event.idl
index a508c35226f..a508c35226f 100644
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_message_event.idl
+++ b/chromium/third_party/blink/renderer/modules/service_worker/extendable_message_event.idl
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_message_event_init.idl b/chromium/third_party/blink/renderer/modules/service_worker/extendable_message_event_init.idl
index 765cda39e5e..765cda39e5e 100644
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_message_event_init.idl
+++ b/chromium/third_party/blink/renderer/modules/service_worker/extendable_message_event_init.idl
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.cc b/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.cc
new file mode 100644
index 00000000000..a499d4c2239
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.cc
@@ -0,0 +1,195 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/service_worker/fetch_event.h"
+
+#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h"
+#include "third_party/blink/public/platform/web_url_response.h"
+#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
+#include "third_party/blink/renderer/core/dom/abort_signal.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/fetch/bytes_consumer_for_data_consumer_handle.h"
+#include "third_party/blink/renderer/core/fetch/request.h"
+#include "third_party/blink/renderer/core/fetch/response.h"
+#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/core/timing/worker_global_scope_performance.h"
+#include "third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_error.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
+#include "third_party/blink/renderer/platform/network/network_utils.h"
+
+namespace blink {
+
+FetchEvent* FetchEvent::Create(ScriptState* script_state,
+ const AtomicString& type,
+ const FetchEventInit& initializer) {
+ return new FetchEvent(script_state, type, initializer, nullptr, nullptr,
+ false);
+}
+
+FetchEvent* FetchEvent::Create(ScriptState* script_state,
+ const AtomicString& type,
+ const FetchEventInit& initializer,
+ FetchRespondWithObserver* respond_with_observer,
+ WaitUntilObserver* wait_until_observer,
+ bool navigation_preload_sent) {
+ return new FetchEvent(script_state, type, initializer, respond_with_observer,
+ wait_until_observer, navigation_preload_sent);
+}
+
+Request* FetchEvent::request() const {
+ return request_;
+}
+
+String FetchEvent::clientId() const {
+ return client_id_;
+}
+
+bool FetchEvent::isReload() const {
+ UseCounter::Count(GetExecutionContext(), WebFeature::kFetchEventIsReload);
+ return is_reload_;
+}
+
+void FetchEvent::respondWith(ScriptState* script_state,
+ ScriptPromise script_promise,
+ ExceptionState& exception_state) {
+ stopImmediatePropagation();
+ if (observer_)
+ observer_->RespondWith(script_state, script_promise, exception_state);
+}
+
+ScriptPromise FetchEvent::preloadResponse(ScriptState* script_state) {
+ return preload_response_property_->Promise(script_state->World());
+}
+
+const AtomicString& FetchEvent::InterfaceName() const {
+ return EventNames::FetchEvent;
+}
+
+bool FetchEvent::HasPendingActivity() const {
+ // Prevent V8 from garbage collecting the wrapper object while waiting for the
+ // preload response. This is in order to keep the resolver of preloadResponse
+ // Promise alive. Note that |preload_response_property_| can be nullptr as
+ // GC can run while running the FetchEvent constructor, before the member is
+ // set. If it isn't set we treat it as a pending state.
+ return !preload_response_property_ ||
+ preload_response_property_->GetState() ==
+ PreloadResponseProperty::kPending;
+}
+
+FetchEvent::FetchEvent(ScriptState* script_state,
+ const AtomicString& type,
+ const FetchEventInit& initializer,
+ FetchRespondWithObserver* respond_with_observer,
+ WaitUntilObserver* wait_until_observer,
+ bool navigation_preload_sent)
+ : ExtendableEvent(type, initializer, wait_until_observer),
+ ContextClient(ExecutionContext::From(script_state)),
+ observer_(respond_with_observer),
+ preload_response_property_(new PreloadResponseProperty(
+ ExecutionContext::From(script_state),
+ this,
+ PreloadResponseProperty::kPreloadResponse)) {
+ if (!navigation_preload_sent)
+ preload_response_property_->ResolveWithUndefined();
+
+ client_id_ = initializer.clientId();
+ is_reload_ = initializer.isReload();
+ request_ = initializer.request();
+}
+
+FetchEvent::~FetchEvent() = default;
+
+void FetchEvent::OnNavigationPreloadResponse(
+ ScriptState* script_state,
+ std::unique_ptr<WebURLResponse> response,
+ std::unique_ptr<WebDataConsumerHandle> data_consume_handle) {
+ if (!script_state->ContextIsValid())
+ return;
+ DCHECK(preload_response_property_);
+ DCHECK(!preload_response_);
+ ScriptState::Scope scope(script_state);
+ preload_response_ = std::move(response);
+ // TODO(ricea): Verify that this response can't be aborted from JS.
+ FetchResponseData* response_data =
+ data_consume_handle
+ ? FetchResponseData::CreateWithBuffer(new BodyStreamBuffer(
+ script_state,
+ new BytesConsumerForDataConsumerHandle(
+ ExecutionContext::From(script_state),
+ std::move(data_consume_handle)),
+ new AbortSignal(ExecutionContext::From(script_state))))
+ : FetchResponseData::Create();
+ Vector<KURL> url_list(1);
+ url_list[0] = preload_response_->Url();
+ response_data->SetURLList(url_list);
+ response_data->SetStatus(preload_response_->HttpStatusCode());
+ response_data->SetStatusMessage(preload_response_->HttpStatusText());
+ response_data->SetResponseTime(
+ preload_response_->ToResourceResponse().ResponseTime());
+ const HTTPHeaderMap& headers(
+ preload_response_->ToResourceResponse().HttpHeaderFields());
+ for (const auto& header : headers) {
+ response_data->HeaderList()->Append(header.key, header.value);
+ }
+ FetchResponseData* tainted_response =
+ NetworkUtils::IsRedirectResponseCode(preload_response_->HttpStatusCode())
+ ? response_data->CreateOpaqueRedirectFilteredResponse()
+ : response_data->CreateBasicFilteredResponse();
+ preload_response_property_->Resolve(
+ Response::Create(ExecutionContext::From(script_state), tainted_response));
+}
+
+void FetchEvent::OnNavigationPreloadError(
+ ScriptState* script_state,
+ std::unique_ptr<WebServiceWorkerError> error) {
+ if (!script_state->ContextIsValid())
+ return;
+ DCHECK(preload_response_property_);
+ if (preload_response_property_->GetState() !=
+ PreloadResponseProperty::kPending) {
+ return;
+ }
+ preload_response_property_->Reject(
+ ServiceWorkerError::Take(nullptr, *error.get()));
+}
+
+void FetchEvent::OnNavigationPreloadComplete(
+ WorkerGlobalScope* worker_global_scope,
+ TimeTicks completion_time,
+ int64_t encoded_data_length,
+ int64_t encoded_body_length,
+ int64_t decoded_body_length) {
+ DCHECK(preload_response_);
+ std::unique_ptr<WebURLResponse> response = std::move(preload_response_);
+ ResourceResponse resource_response = response->ToResourceResponse();
+ resource_response.SetEncodedDataLength(encoded_data_length);
+ resource_response.SetEncodedBodyLength(encoded_body_length);
+ resource_response.SetDecodedBodyLength(decoded_body_length);
+ // According to the Resource Timing spec, the initiator type of
+ // navigation preload request is "navigation".
+ scoped_refptr<ResourceTimingInfo> info = ResourceTimingInfo::Create(
+ "navigation", resource_response.GetResourceLoadTiming()->RequestTime(),
+ false /* is_main_resource */);
+ info->SetNegativeAllowed(true);
+ info->SetLoadFinishTime(completion_time);
+ info->SetInitialURL(request_->url());
+ info->SetFinalResponse(resource_response);
+ info->AddFinalTransferSize(encoded_data_length);
+ WorkerGlobalScopePerformance::performance(*worker_global_scope)
+ ->GenerateAndAddResourceTiming(*info);
+}
+
+void FetchEvent::Trace(blink::Visitor* visitor) {
+ visitor->Trace(observer_);
+ visitor->Trace(request_);
+ visitor->Trace(preload_response_property_);
+ ExtendableEvent::Trace(visitor);
+ ContextClient::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.h b/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.h
new file mode 100644
index 00000000000..1bf70d4484b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.h
@@ -0,0 +1,105 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_FETCH_EVENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_FETCH_EVENT_H_
+
+#include <memory>
+
+#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_property.h"
+#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/core/fetch/request.h"
+#include "third_party/blink/renderer/modules/event_modules.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/modules/service_worker/extendable_event.h"
+#include "third_party/blink/renderer/modules/service_worker/fetch_event_init.h"
+#include "third_party/blink/renderer/modules/service_worker/wait_until_observer.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
+
+namespace blink {
+
+class ExceptionState;
+class FetchRespondWithObserver;
+class Request;
+class Response;
+class ScriptState;
+class WebDataConsumerHandle;
+struct WebServiceWorkerError;
+class WebURLResponse;
+class WorkerGlobalScope;
+
+// A fetch event is dispatched by the client to a service worker's script
+// context. FetchRespondWithObserver can be used to notify the client about the
+// service worker's response.
+class MODULES_EXPORT FetchEvent final
+ : public ExtendableEvent,
+ public ActiveScriptWrappable<FetchEvent>,
+ public ContextClient {
+ DEFINE_WRAPPERTYPEINFO();
+ USING_GARBAGE_COLLECTED_MIXIN(FetchEvent);
+
+ public:
+ using PreloadResponseProperty = ScriptPromiseProperty<Member<FetchEvent>,
+ Member<Response>,
+ Member<DOMException>>;
+ static FetchEvent* Create(ScriptState*,
+ const AtomicString& type,
+ const FetchEventInit&);
+ static FetchEvent* Create(ScriptState*,
+ const AtomicString& type,
+ const FetchEventInit&,
+ FetchRespondWithObserver*,
+ WaitUntilObserver*,
+ bool navigation_preload_sent);
+
+ ~FetchEvent() override;
+
+ Request* request() const;
+ String clientId() const;
+ bool isReload() const;
+
+ void respondWith(ScriptState*, ScriptPromise, ExceptionState&);
+ ScriptPromise preloadResponse(ScriptState*);
+
+ void OnNavigationPreloadResponse(ScriptState*,
+ std::unique_ptr<WebURLResponse>,
+ std::unique_ptr<WebDataConsumerHandle>);
+ void OnNavigationPreloadError(ScriptState*,
+ std::unique_ptr<WebServiceWorkerError>);
+ void OnNavigationPreloadComplete(WorkerGlobalScope*,
+ TimeTicks completion_time,
+ int64_t encoded_data_length,
+ int64_t encoded_body_length,
+ int64_t decoded_body_length);
+
+ const AtomicString& InterfaceName() const override;
+
+ // ScriptWrappable
+ bool HasPendingActivity() const override;
+
+ void Trace(blink::Visitor*) override;
+
+ protected:
+ FetchEvent(ScriptState*,
+ const AtomicString& type,
+ const FetchEventInit&,
+ FetchRespondWithObserver*,
+ WaitUntilObserver*,
+ bool navigation_preload_sent);
+
+ private:
+ Member<FetchRespondWithObserver> observer_;
+ TraceWrapperMember<Request> request_;
+ Member<PreloadResponseProperty> preload_response_property_;
+ std::unique_ptr<WebURLResponse> preload_response_;
+ String client_id_;
+ bool is_reload_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_FETCH_EVENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/fetch_event.idl b/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.idl
index 16e30dba8ef..16e30dba8ef 100644
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/fetch_event.idl
+++ b/chromium/third_party/blink/renderer/modules/service_worker/fetch_event.idl
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/fetch_event_init.idl b/chromium/third_party/blink/renderer/modules/service_worker/fetch_event_init.idl
index 67706abada1..67706abada1 100644
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/fetch_event_init.idl
+++ b/chromium/third_party/blink/renderer/modules/service_worker/fetch_event_init.idl
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc b/chromium/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc
new file mode 100644
index 00000000000..2aabdee38fb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.cc
@@ -0,0 +1,347 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.h"
+
+#include <memory>
+#include <utility>
+
+#include "services/network/public/mojom/fetch_api.mojom-blink.h"
+#include "services/network/public/mojom/request_context_frame_type.mojom-blink.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_response.h"
+#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_response.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
+#include "third_party/blink/renderer/core/fetch/bytes_consumer.h"
+#include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/core/inspector/console_types.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h"
+#include "third_party/blink/renderer/modules/service_worker/wait_until_observer.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "v8/include/v8.h"
+
+using blink::mojom::ServiceWorkerResponseError;
+
+namespace blink {
+namespace {
+
+// Returns the error message to let the developer know about the reason of the
+// unusual failures.
+const String GetMessageForResponseError(ServiceWorkerResponseError error,
+ const KURL& request_url) {
+ String error_message = "The FetchEvent for \"" + request_url.GetString() +
+ "\" resulted in a network error response: ";
+ switch (error) {
+ case ServiceWorkerResponseError::kPromiseRejected:
+ error_message = error_message + "the promise was rejected.";
+ break;
+ case ServiceWorkerResponseError::kDefaultPrevented:
+ error_message =
+ error_message +
+ "preventDefault() was called without calling respondWith().";
+ break;
+ case ServiceWorkerResponseError::kNoV8Instance:
+ error_message =
+ error_message +
+ "an object that was not a Response was passed to respondWith().";
+ break;
+ case ServiceWorkerResponseError::kResponseTypeError:
+ error_message = error_message +
+ "the promise was resolved with an error response object.";
+ break;
+ case ServiceWorkerResponseError::kResponseTypeOpaque:
+ error_message =
+ error_message +
+ "an \"opaque\" response was used for a request whose type "
+ "is not no-cors";
+ break;
+ case ServiceWorkerResponseError::kResponseTypeNotBasicOrDefault:
+ NOTREACHED();
+ break;
+ case ServiceWorkerResponseError::kBodyUsed:
+ error_message =
+ error_message +
+ "a Response whose \"bodyUsed\" is \"true\" cannot be used "
+ "to respond to a request.";
+ break;
+ case ServiceWorkerResponseError::kResponseTypeOpaqueForClientRequest:
+ error_message = error_message +
+ "an \"opaque\" response was used for a client request.";
+ break;
+ case ServiceWorkerResponseError::kResponseTypeOpaqueRedirect:
+ error_message = error_message +
+ "an \"opaqueredirect\" type response was used for a "
+ "request whose redirect mode is not \"manual\".";
+ break;
+ case ServiceWorkerResponseError::kResponseTypeCORSForRequestModeSameOrigin:
+ error_message = error_message +
+ "a \"cors\" type response was used for a request whose "
+ "mode is \"same-origin\".";
+ break;
+ case ServiceWorkerResponseError::kBodyLocked:
+ error_message = error_message +
+ "a Response whose \"body\" is locked cannot be used to "
+ "respond to a request.";
+ break;
+ case ServiceWorkerResponseError::kRedirectedResponseForNotFollowRequest:
+ error_message = error_message +
+ "a redirected response was used for a request whose "
+ "redirect mode is not \"follow\".";
+ break;
+ case ServiceWorkerResponseError::kDataPipeCreationFailed:
+ error_message = error_message + "insufficient resources.";
+ break;
+ case ServiceWorkerResponseError::kResponseBodyBroken:
+ error_message =
+ error_message + "a response body's status could not be checked.";
+ break;
+ case ServiceWorkerResponseError::kUnknown:
+ default:
+ error_message = error_message + "an unexpected error occurred.";
+ break;
+ }
+ return error_message;
+}
+
+bool IsNavigationRequest(network::mojom::RequestContextFrameType frame_type) {
+ return frame_type != network::mojom::RequestContextFrameType::kNone;
+}
+
+bool IsClientRequest(network::mojom::RequestContextFrameType frame_type,
+ WebURLRequest::RequestContext request_context) {
+ return IsNavigationRequest(frame_type) ||
+ request_context == WebURLRequest::kRequestContextSharedWorker ||
+ request_context == WebURLRequest::kRequestContextWorker;
+}
+
+// Notifies the result of FetchDataLoader to |handle_|. |handle_| pass through
+// the result to its observer which is outside of blink.
+class FetchLoaderClient final
+ : public GarbageCollectedFinalized<FetchLoaderClient>,
+ public FetchDataLoader::Client {
+ WTF_MAKE_NONCOPYABLE(FetchLoaderClient);
+ USING_GARBAGE_COLLECTED_MIXIN(FetchLoaderClient);
+
+ public:
+ explicit FetchLoaderClient(
+ std::unique_ptr<WebServiceWorkerStreamHandle> handle)
+ : handle_(std::move(handle)) {}
+
+ void DidFetchDataLoadedDataPipe() override { handle_->Completed(); }
+ void DidFetchDataLoadFailed() override { handle_->Aborted(); }
+ void Abort() override {
+ // A fetch() aborted via AbortSignal in the ServiceWorker will just look
+ // like an ordinary failure to the page.
+ // TODO(ricea): Should a fetch() on the page get an AbortError instead?
+ handle_->Aborted();
+ }
+
+ void Trace(blink::Visitor* visitor) override {
+ FetchDataLoader::Client::Trace(visitor);
+ }
+
+ private:
+ std::unique_ptr<WebServiceWorkerStreamHandle> handle_;
+};
+
+} // namespace
+
+FetchRespondWithObserver* FetchRespondWithObserver::Create(
+ ExecutionContext* context,
+ int fetch_event_id,
+ const KURL& request_url,
+ network::mojom::FetchRequestMode request_mode,
+ network::mojom::FetchRedirectMode redirect_mode,
+ network::mojom::RequestContextFrameType frame_type,
+ WebURLRequest::RequestContext request_context,
+ WaitUntilObserver* observer) {
+ return new FetchRespondWithObserver(context, fetch_event_id, request_url,
+ request_mode, redirect_mode, frame_type,
+ request_context, observer);
+}
+
+// This function may be called when an exception is scheduled. Thus, it must
+// never invoke any code that might throw. In particular, it must never invoke
+// JavaScript.
+void FetchRespondWithObserver::OnResponseRejected(
+ ServiceWorkerResponseError error) {
+ DCHECK(GetExecutionContext());
+ GetExecutionContext()->AddConsoleMessage(
+ ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel,
+ GetMessageForResponseError(error, request_url_)));
+
+ // The default value of WebServiceWorkerResponse's status is 0, which maps
+ // to a network error.
+ WebServiceWorkerResponse web_response;
+ web_response.SetError(error);
+ ServiceWorkerGlobalScopeClient::From(GetExecutionContext())
+ ->RespondToFetchEvent(event_id_, web_response, event_dispatch_time_);
+}
+
+void FetchRespondWithObserver::OnResponseFulfilled(
+ const ScriptValue& value,
+ ExceptionState::ContextType context_type,
+ const char* interface_name,
+ const char* property_name) {
+ DCHECK(GetExecutionContext());
+ if (!V8Response::hasInstance(value.V8Value(),
+ ToIsolate(GetExecutionContext()))) {
+ OnResponseRejected(ServiceWorkerResponseError::kNoV8Instance);
+ return;
+ }
+ Response* response = V8Response::ToImplWithTypeCheck(
+ ToIsolate(GetExecutionContext()), value.V8Value());
+ // "If one of the following conditions is true, return a network error:
+ // - |response|'s type is |error|.
+ // - |request|'s mode is |same-origin| and |response|'s type is |cors|.
+ // - |request|'s mode is not |no-cors| and response's type is |opaque|.
+ // - |request| is a client request and |response|'s type is neither
+ // |basic| nor |default|."
+ const network::mojom::FetchResponseType response_type =
+ response->GetResponse()->GetType();
+ if (response_type == network::mojom::FetchResponseType::kError) {
+ OnResponseRejected(ServiceWorkerResponseError::kResponseTypeError);
+ return;
+ }
+ if (response_type == network::mojom::FetchResponseType::kCORS &&
+ request_mode_ == network::mojom::FetchRequestMode::kSameOrigin) {
+ OnResponseRejected(
+ ServiceWorkerResponseError::kResponseTypeCORSForRequestModeSameOrigin);
+ return;
+ }
+ if (response_type == network::mojom::FetchResponseType::kOpaque) {
+ if (request_mode_ != network::mojom::FetchRequestMode::kNoCORS) {
+ OnResponseRejected(ServiceWorkerResponseError::kResponseTypeOpaque);
+ return;
+ }
+
+ // The request mode of client requests should be "same-origin" but it is
+ // not explicitly stated in the spec yet. So we need to check here.
+ // FIXME: Set the request mode of client requests to "same-origin" and
+ // remove this check when the spec will be updated.
+ // Spec issue: https://github.com/whatwg/fetch/issues/101
+ if (IsClientRequest(frame_type_, request_context_)) {
+ OnResponseRejected(
+ ServiceWorkerResponseError::kResponseTypeOpaqueForClientRequest);
+ return;
+ }
+ }
+ if (redirect_mode_ != network::mojom::FetchRedirectMode::kManual &&
+ response_type == network::mojom::FetchResponseType::kOpaqueRedirect) {
+ OnResponseRejected(ServiceWorkerResponseError::kResponseTypeOpaqueRedirect);
+ return;
+ }
+ if (redirect_mode_ != network::mojom::FetchRedirectMode::kFollow &&
+ response->redirected()) {
+ OnResponseRejected(
+ ServiceWorkerResponseError::kRedirectedResponseForNotFollowRequest);
+ return;
+ }
+
+ ExceptionState exception_state(value.GetScriptState()->GetIsolate(),
+ context_type, interface_name, property_name);
+ if (response->IsBodyLocked(exception_state) == Body::BodyLocked::kLocked) {
+ DCHECK(!exception_state.HadException());
+ OnResponseRejected(ServiceWorkerResponseError::kBodyLocked);
+ return;
+ }
+
+ if (exception_state.HadException()) {
+ OnResponseRejected(ServiceWorkerResponseError::kResponseBodyBroken);
+ return;
+ }
+
+ if (response->IsBodyUsed(exception_state) == Body::BodyUsed::kUsed) {
+ DCHECK(!exception_state.HadException());
+ OnResponseRejected(ServiceWorkerResponseError::kBodyUsed);
+ return;
+ }
+
+ if (exception_state.HadException()) {
+ OnResponseRejected(ServiceWorkerResponseError::kResponseBodyBroken);
+ return;
+ }
+
+ WebServiceWorkerResponse web_response;
+ response->PopulateWebServiceWorkerResponse(web_response);
+
+ BodyStreamBuffer* buffer = response->InternalBodyBuffer();
+ if (buffer) {
+ scoped_refptr<BlobDataHandle> blob_data_handle =
+ buffer->DrainAsBlobDataHandle(
+ BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize,
+ exception_state);
+ if (exception_state.HadException()) {
+ OnResponseRejected(ServiceWorkerResponseError::kResponseBodyBroken);
+ return;
+ }
+ if (blob_data_handle) {
+ // Handle the blob response body.
+ web_response.SetBlobDataHandle(blob_data_handle);
+ ServiceWorkerGlobalScopeClient::From(GetExecutionContext())
+ ->RespondToFetchEvent(event_id_, web_response, event_dispatch_time_);
+ return;
+ }
+ // Handle the stream response body.
+ mojo::ScopedDataPipeProducerHandle producer;
+ mojo::ScopedDataPipeConsumerHandle consumer;
+ MojoResult result = mojo::CreateDataPipe(nullptr, &producer, &consumer);
+ if (result != MOJO_RESULT_OK) {
+ OnResponseRejected(ServiceWorkerResponseError::kDataPipeCreationFailed);
+ return;
+ }
+ DCHECK(producer.is_valid());
+ DCHECK(consumer.is_valid());
+
+ std::unique_ptr<WebServiceWorkerStreamHandle> body_stream_handle =
+ std::make_unique<WebServiceWorkerStreamHandle>(std::move(consumer));
+ ServiceWorkerGlobalScopeClient::From(GetExecutionContext())
+ ->RespondToFetchEventWithResponseStream(event_id_, web_response,
+ body_stream_handle.get(),
+ event_dispatch_time_);
+
+ buffer->StartLoading(FetchDataLoader::CreateLoaderAsDataPipe(
+ std::move(producer), task_runner_),
+ new FetchLoaderClient(std::move(body_stream_handle)),
+ exception_state);
+ if (exception_state.HadException()) {
+ OnResponseRejected(ServiceWorkerResponseError::kResponseBodyBroken);
+ return;
+ }
+ return;
+ }
+ ServiceWorkerGlobalScopeClient::From(GetExecutionContext())
+ ->RespondToFetchEvent(event_id_, web_response, event_dispatch_time_);
+}
+
+void FetchRespondWithObserver::OnNoResponse() {
+ ServiceWorkerGlobalScopeClient::From(GetExecutionContext())
+ ->RespondToFetchEventWithNoResponse(event_id_, event_dispatch_time_);
+}
+
+FetchRespondWithObserver::FetchRespondWithObserver(
+ ExecutionContext* context,
+ int fetch_event_id,
+ const KURL& request_url,
+ network::mojom::FetchRequestMode request_mode,
+ network::mojom::FetchRedirectMode redirect_mode,
+ network::mojom::RequestContextFrameType frame_type,
+ WebURLRequest::RequestContext request_context,
+ WaitUntilObserver* observer)
+ : RespondWithObserver(context, fetch_event_id, observer),
+ request_url_(request_url),
+ request_mode_(request_mode),
+ redirect_mode_(redirect_mode),
+ frame_type_(frame_type),
+ request_context_(request_context),
+ task_runner_(context->GetTaskRunner(TaskType::kNetworking)) {}
+
+void FetchRespondWithObserver::Trace(blink::Visitor* visitor) {
+ RespondWithObserver::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.h b/chromium/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.h
new file mode 100644
index 00000000000..394d7e066ad
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.h
@@ -0,0 +1,67 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_FETCH_RESPOND_WITH_OBSERVER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_FETCH_RESPOND_WITH_OBSERVER_H_
+
+#include "services/network/public/mojom/fetch_api.mojom-blink.h"
+#include "third_party/blink/public/platform/web_url_request.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/modules/service_worker/respond_with_observer.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+
+namespace blink {
+
+class ExecutionContext;
+class ScriptValue;
+class WaitUntilObserver;
+
+// This class observes the service worker's handling of a FetchEvent and
+// notifies the client.
+class MODULES_EXPORT FetchRespondWithObserver : public RespondWithObserver {
+ public:
+ ~FetchRespondWithObserver() override = default;
+
+ static FetchRespondWithObserver* Create(
+ ExecutionContext*,
+ int fetch_event_id,
+ const KURL& request_url,
+ network::mojom::FetchRequestMode,
+ network::mojom::FetchRedirectMode,
+ network::mojom::RequestContextFrameType,
+ WebURLRequest::RequestContext,
+ WaitUntilObserver*);
+
+ void OnResponseRejected(mojom::ServiceWorkerResponseError) override;
+ void OnResponseFulfilled(const ScriptValue&,
+ ExceptionState::ContextType context_type,
+ const char* interface_name,
+ const char* property_name) override;
+ void OnNoResponse() override;
+
+ void Trace(blink::Visitor*) override;
+
+ protected:
+ FetchRespondWithObserver(ExecutionContext*,
+ int fetch_event_id,
+ const KURL& request_url,
+ network::mojom::FetchRequestMode,
+ network::mojom::FetchRedirectMode,
+ network::mojom::RequestContextFrameType,
+ WebURLRequest::RequestContext,
+ WaitUntilObserver*);
+
+ private:
+ const KURL request_url_;
+ const network::mojom::FetchRequestMode request_mode_;
+ const network::mojom::FetchRedirectMode redirect_mode_;
+ const network::mojom::RequestContextFrameType frame_type_;
+ const WebURLRequest::RequestContext request_context_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_FETCH_RESPOND_WITH_OBSERVER_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/install_event.cc b/chromium/third_party/blink/renderer/modules/service_worker/install_event.cc
new file mode 100644
index 00000000000..bf57ae88683
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/install_event.cc
@@ -0,0 +1,42 @@
+// 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/modules/service_worker/install_event.h"
+
+#include "third_party/blink/public/platform/web_security_origin.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+
+namespace blink {
+
+InstallEvent* InstallEvent::Create(const AtomicString& type,
+ const ExtendableEventInit& event_init) {
+ return new InstallEvent(type, event_init);
+}
+
+InstallEvent* InstallEvent::Create(const AtomicString& type,
+ const ExtendableEventInit& event_init,
+ int event_id,
+ WaitUntilObserver* observer) {
+ return new InstallEvent(type, event_init, event_id, observer);
+}
+
+InstallEvent::~InstallEvent() = default;
+
+const AtomicString& InstallEvent::InterfaceName() const {
+ return EventNames::InstallEvent;
+}
+
+InstallEvent::InstallEvent(const AtomicString& type,
+ const ExtendableEventInit& initializer)
+ : ExtendableEvent(type, initializer), event_id_(0) {}
+
+InstallEvent::InstallEvent(const AtomicString& type,
+ const ExtendableEventInit& initializer,
+ int event_id,
+ WaitUntilObserver* observer)
+ : ExtendableEvent(type, initializer, observer), event_id_(event_id) {}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/install_event.h b/chromium/third_party/blink/renderer/modules/service_worker/install_event.h
new file mode 100644
index 00000000000..14cfeba1699
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/install_event.h
@@ -0,0 +1,40 @@
+// 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_MODULES_SERVICE_WORKER_INSTALL_EVENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_INSTALL_EVENT_H_
+
+#include "third_party/blink/renderer/modules/event_modules.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/modules/service_worker/extendable_event.h"
+
+namespace blink {
+
+class MODULES_EXPORT InstallEvent : public ExtendableEvent {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static InstallEvent* Create(const AtomicString& type,
+ const ExtendableEventInit&);
+ static InstallEvent* Create(const AtomicString& type,
+ const ExtendableEventInit&,
+ int event_id,
+ WaitUntilObserver*);
+
+ ~InstallEvent() override;
+
+ const AtomicString& InterfaceName() const override;
+
+ protected:
+ InstallEvent(const AtomicString& type, const ExtendableEventInit&);
+ InstallEvent(const AtomicString& type,
+ const ExtendableEventInit&,
+ int event_id,
+ WaitUntilObserver*);
+ const int event_id_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_INSTALL_EVENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/install_event.idl b/chromium/third_party/blink/renderer/modules/service_worker/install_event.idl
index ce16062c0b9..ce16062c0b9 100644
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/install_event.idl
+++ b/chromium/third_party/blink/renderer/modules/service_worker/install_event.idl
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_callbacks.cc b/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_callbacks.cc
new file mode 100644
index 00000000000..88d4c2ac601
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_callbacks.cc
@@ -0,0 +1,90 @@
+// 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/modules/service_worker/navigation_preload_callbacks.h"
+
+#include "third_party/blink/public/platform/modules/service_worker/web_navigation_preload_state.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/modules/service_worker/navigation_preload_state.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_error.h"
+
+namespace blink {
+
+EnableNavigationPreloadCallbacks::EnableNavigationPreloadCallbacks(
+ ScriptPromiseResolver* resolver)
+ : resolver_(resolver) {
+ DCHECK(resolver_);
+}
+
+EnableNavigationPreloadCallbacks::~EnableNavigationPreloadCallbacks() = default;
+
+void EnableNavigationPreloadCallbacks::OnSuccess() {
+ if (!resolver_->GetExecutionContext() ||
+ resolver_->GetExecutionContext()->IsContextDestroyed())
+ return;
+ resolver_->Resolve();
+}
+
+void EnableNavigationPreloadCallbacks::OnError(
+ const WebServiceWorkerError& error) {
+ if (!resolver_->GetExecutionContext() ||
+ resolver_->GetExecutionContext()->IsContextDestroyed())
+ return;
+ resolver_->Reject(ServiceWorkerError::Take(resolver_.Get(), error));
+}
+
+GetNavigationPreloadStateCallbacks::GetNavigationPreloadStateCallbacks(
+ ScriptPromiseResolver* resolver)
+ : resolver_(resolver) {
+ DCHECK(resolver_);
+}
+
+GetNavigationPreloadStateCallbacks::~GetNavigationPreloadStateCallbacks() =
+ default;
+
+void GetNavigationPreloadStateCallbacks::OnSuccess(
+ const WebNavigationPreloadState& state) {
+ if (!resolver_->GetExecutionContext() ||
+ resolver_->GetExecutionContext()->IsContextDestroyed())
+ return;
+ NavigationPreloadState dict;
+ dict.setEnabled(state.enabled);
+ dict.setHeaderValue(state.header_value);
+ resolver_->Resolve(dict);
+}
+
+void GetNavigationPreloadStateCallbacks::OnError(
+ const WebServiceWorkerError& error) {
+ if (!resolver_->GetExecutionContext() ||
+ resolver_->GetExecutionContext()->IsContextDestroyed())
+ return;
+ resolver_->Reject(ServiceWorkerError::Take(resolver_.Get(), error));
+}
+
+SetNavigationPreloadHeaderCallbacks::SetNavigationPreloadHeaderCallbacks(
+ ScriptPromiseResolver* resolver)
+ : resolver_(resolver) {
+ DCHECK(resolver_);
+}
+
+SetNavigationPreloadHeaderCallbacks::~SetNavigationPreloadHeaderCallbacks() =
+ default;
+
+void SetNavigationPreloadHeaderCallbacks::OnSuccess() {
+ if (!resolver_->GetExecutionContext() ||
+ resolver_->GetExecutionContext()->IsContextDestroyed())
+ return;
+ resolver_->Resolve();
+}
+
+void SetNavigationPreloadHeaderCallbacks::OnError(
+ const WebServiceWorkerError& error) {
+ if (!resolver_->GetExecutionContext() ||
+ resolver_->GetExecutionContext()->IsContextDestroyed())
+ return;
+ resolver_->Reject(ServiceWorkerError::Take(resolver_.Get(), error));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_callbacks.h b/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_callbacks.h
new file mode 100644
index 00000000000..89d60fb47b8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_callbacks.h
@@ -0,0 +1,67 @@
+// 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_MODULES_SERVICE_WORKER_NAVIGATION_PRELOAD_CALLBACKS_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_NAVIGATION_PRELOAD_CALLBACKS_H_
+
+#include "base/macros.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_registration.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+
+namespace blink {
+
+class ScriptPromiseResolver;
+struct WebNavigationPreloadState;
+struct WebServiceWorkerError;
+
+class EnableNavigationPreloadCallbacks final
+ : public WebServiceWorkerRegistration::WebEnableNavigationPreloadCallbacks {
+ public:
+ explicit EnableNavigationPreloadCallbacks(ScriptPromiseResolver*);
+ ~EnableNavigationPreloadCallbacks() override;
+
+ // WebEnableNavigationPreloadCallbacks interface.
+ void OnSuccess() override;
+ void OnError(const WebServiceWorkerError&) override;
+
+ private:
+ Persistent<ScriptPromiseResolver> resolver_;
+ DISALLOW_COPY_AND_ASSIGN(EnableNavigationPreloadCallbacks);
+};
+
+class GetNavigationPreloadStateCallbacks final
+ : public WebServiceWorkerRegistration::
+ WebGetNavigationPreloadStateCallbacks {
+ public:
+ explicit GetNavigationPreloadStateCallbacks(ScriptPromiseResolver*);
+ ~GetNavigationPreloadStateCallbacks() override;
+
+ // WebGetNavigationPreloadStateCallbacks interface.
+ void OnSuccess(const WebNavigationPreloadState&) override;
+ void OnError(const WebServiceWorkerError&) override;
+
+ private:
+ Persistent<ScriptPromiseResolver> resolver_;
+ DISALLOW_COPY_AND_ASSIGN(GetNavigationPreloadStateCallbacks);
+};
+
+class SetNavigationPreloadHeaderCallbacks final
+ : public WebServiceWorkerRegistration::
+ WebSetNavigationPreloadHeaderCallbacks {
+ public:
+ explicit SetNavigationPreloadHeaderCallbacks(ScriptPromiseResolver*);
+ ~SetNavigationPreloadHeaderCallbacks() override;
+
+ // WebSetNavigationPreloadHeaderCallbacks interface.
+ void OnSuccess(void) override;
+ void OnError(const WebServiceWorkerError&) override;
+
+ private:
+ Persistent<ScriptPromiseResolver> resolver_;
+ DISALLOW_COPY_AND_ASSIGN(SetNavigationPreloadHeaderCallbacks);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_NAVIGATION_PRELOAD_CALLBACKS_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_manager.cc b/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_manager.cc
new file mode 100644
index 00000000000..e64157b046b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_manager.cc
@@ -0,0 +1,70 @@
+// 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/modules/service_worker/navigation_preload_manager.h"
+
+#include <memory>
+
+#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/modules/service_worker/navigation_preload_callbacks.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_container_client.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
+#include "third_party/blink/renderer/platform/network/http_parsers.h"
+
+namespace blink {
+
+ScriptPromise NavigationPreloadManager::enable(ScriptState* script_state) {
+ return SetEnabled(true, script_state);
+}
+
+ScriptPromise NavigationPreloadManager::disable(ScriptState* script_state) {
+ return SetEnabled(false, script_state);
+}
+
+ScriptPromise NavigationPreloadManager::setHeaderValue(
+ ScriptState* script_state,
+ const String& value) {
+ if (!IsValidHTTPHeaderValue(value)) {
+ return ScriptPromise::Reject(
+ script_state, V8ThrowException::CreateTypeError(
+ script_state->GetIsolate(),
+ "The string provided to setHeaderValue ('" + value +
+ "') is not a valid HTTP header field value."));
+ }
+
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+ ScriptPromise promise = resolver->Promise();
+ registration_->WebRegistration()->SetNavigationPreloadHeader(
+ value, std::make_unique<SetNavigationPreloadHeaderCallbacks>(resolver));
+ return promise;
+}
+
+ScriptPromise NavigationPreloadManager::getState(ScriptState* script_state) {
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+ ScriptPromise promise = resolver->Promise();
+ registration_->WebRegistration()->GetNavigationPreloadState(
+ std::make_unique<GetNavigationPreloadStateCallbacks>(resolver));
+ return promise;
+}
+
+NavigationPreloadManager::NavigationPreloadManager(
+ ServiceWorkerRegistration* registration)
+ : registration_(registration) {}
+
+ScriptPromise NavigationPreloadManager::SetEnabled(bool enable,
+ ScriptState* script_state) {
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+ ScriptPromise promise = resolver->Promise();
+ registration_->WebRegistration()->EnableNavigationPreload(
+ enable, std::make_unique<EnableNavigationPreloadCallbacks>(resolver));
+ return promise;
+}
+
+void NavigationPreloadManager::Trace(blink::Visitor* visitor) {
+ visitor->Trace(registration_);
+ ScriptWrappable::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_manager.h b/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_manager.h
new file mode 100644
index 00000000000..263ff5cb605
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_manager.h
@@ -0,0 +1,42 @@
+// 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_MODULES_SERVICE_WORKER_NAVIGATION_PRELOAD_MANAGER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_NAVIGATION_PRELOAD_MANAGER_H_
+
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+class ServiceWorkerRegistration;
+
+class NavigationPreloadManager final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static NavigationPreloadManager* Create(
+ ServiceWorkerRegistration* registration) {
+ return new NavigationPreloadManager(registration);
+ }
+
+ ScriptPromise enable(ScriptState*);
+ ScriptPromise disable(ScriptState*);
+ ScriptPromise setHeaderValue(ScriptState*, const String& value);
+ ScriptPromise getState(ScriptState*);
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ explicit NavigationPreloadManager(ServiceWorkerRegistration*);
+
+ ScriptPromise SetEnabled(bool enable, ScriptState*);
+
+ Member<ServiceWorkerRegistration> registration_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_NAVIGATION_PRELOAD_MANAGER_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_manager.idl b/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_manager.idl
index 6176378d549..6176378d549 100644
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_manager.idl
+++ b/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_manager.idl
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_state.idl b/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_state.idl
index 1c8c4a1a566..1c8c4a1a566 100644
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_state.idl
+++ b/chromium/third_party/blink/renderer/modules/service_worker/navigation_preload_state.idl
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/navigator_service_worker.cc b/chromium/third_party/blink/renderer/modules/service_worker/navigator_service_worker.cc
new file mode 100644
index 00000000000..157a288afa9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/navigator_service_worker.cc
@@ -0,0 +1,142 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/service_worker/navigator_service_worker.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/frame/navigator.h"
+#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_container.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+
+namespace blink {
+
+NavigatorServiceWorker::NavigatorServiceWorker(Navigator& navigator) {}
+
+NavigatorServiceWorker* NavigatorServiceWorker::From(Document& document) {
+ LocalFrame* frame = document.GetFrame();
+ if (!frame)
+ return nullptr;
+
+ // Bail-out if we are about to be navigated away.
+ // We check that DocumentLoader is attached since:
+ // - This serves as the signal since the DocumentLoader is detached in
+ // FrameLoader::PrepareForCommit().
+ // - Creating ServiceWorkerProvider in
+ // RenderFrameImpl::CreateServiceWorkerProvider() assumes that there is a
+ // DocumentLoader attached to the frame.
+ if (!frame->Loader().GetDocumentLoader())
+ return nullptr;
+
+ LocalDOMWindow* dom_window = frame->DomWindow();
+ if (!dom_window)
+ return nullptr;
+ Navigator& navigator = *dom_window->navigator();
+ return &From(navigator);
+}
+
+NavigatorServiceWorker& NavigatorServiceWorker::From(Navigator& navigator) {
+ NavigatorServiceWorker* supplement = ToNavigatorServiceWorker(navigator);
+ if (!supplement) {
+ supplement = new NavigatorServiceWorker(navigator);
+ ProvideTo(navigator, supplement);
+ }
+ if (navigator.GetFrame() && navigator.GetFrame()
+ ->GetSecurityContext()
+ ->GetSecurityOrigin()
+ ->CanAccessServiceWorkers()) {
+ // Ensure ServiceWorkerContainer. It can be cleared regardless of
+ // |supplement|. See comments in NavigatorServiceWorker::serviceWorker() for
+ // details.
+ supplement->serviceWorker(navigator.GetFrame(), ASSERT_NO_EXCEPTION);
+ }
+ return *supplement;
+}
+
+NavigatorServiceWorker* NavigatorServiceWorker::ToNavigatorServiceWorker(
+ Navigator& navigator) {
+ return Supplement<Navigator>::From<NavigatorServiceWorker>(navigator);
+}
+
+const char NavigatorServiceWorker::kSupplementName[] = "NavigatorServiceWorker";
+
+ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker(
+ ScriptState* script_state,
+ Navigator& navigator,
+ ExceptionState& exception_state) {
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+ DCHECK(!navigator.GetFrame() ||
+ execution_context->GetSecurityOrigin()->CanAccess(
+ navigator.GetFrame()->GetSecurityContext()->GetSecurityOrigin()));
+ return NavigatorServiceWorker::From(navigator).serviceWorker(
+ navigator.GetFrame(), exception_state);
+}
+
+ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker(
+ ScriptState* script_state,
+ Navigator& navigator,
+ String& error_message) {
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+ DCHECK(!navigator.GetFrame() ||
+ execution_context->GetSecurityOrigin()->CanAccess(
+ navigator.GetFrame()->GetSecurityContext()->GetSecurityOrigin()));
+ return NavigatorServiceWorker::From(navigator).serviceWorker(
+ navigator.GetFrame(), error_message);
+}
+
+ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker(
+ LocalFrame* frame,
+ ExceptionState& exception_state) {
+ String error_message;
+ ServiceWorkerContainer* result = serviceWorker(frame, error_message);
+ if (!error_message.IsEmpty()) {
+ DCHECK(!result);
+ exception_state.ThrowSecurityError(error_message);
+ }
+ return result;
+}
+
+ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker(
+ LocalFrame* frame,
+ String& error_message) {
+ if (frame && !frame->GetSecurityContext()
+ ->GetSecurityOrigin()
+ ->CanAccessServiceWorkers()) {
+ if (frame->GetSecurityContext()->IsSandboxed(kSandboxOrigin)) {
+ error_message =
+ "Service worker is disabled because the context is sandboxed and "
+ "lacks the 'allow-same-origin' flag.";
+ } else {
+ error_message =
+ "Access to service workers is denied in this document origin.";
+ }
+ return nullptr;
+ } else if (frame &&
+ frame->GetSecurityContext()->GetSecurityOrigin()->IsLocal()) {
+ UseCounter::Count(frame, WebFeature::kFileAccessedServiceWorker);
+ }
+ if (!service_worker_ && frame) {
+ // We need to create a new ServiceWorkerContainer when the frame
+ // navigates to a new document. In practice, this happens only when the
+ // frame navigates from the initial empty page to a new same-origin page.
+ DCHECK(frame->DomWindow());
+ service_worker_ = ServiceWorkerContainer::Create(
+ frame->DomWindow()->GetExecutionContext(), this);
+ }
+ return service_worker_.Get();
+}
+
+void NavigatorServiceWorker::ClearServiceWorker() {
+ service_worker_ = nullptr;
+}
+
+void NavigatorServiceWorker::Trace(blink::Visitor* visitor) {
+ visitor->Trace(service_worker_);
+ Supplement<Navigator>::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/navigator_service_worker.h b/chromium/third_party/blink/renderer/modules/service_worker/navigator_service_worker.h
new file mode 100644
index 00000000000..681910dfe41
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/navigator_service_worker.h
@@ -0,0 +1,52 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_NAVIGATOR_SERVICE_WORKER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_NAVIGATOR_SERVICE_WORKER_H_
+
+#include "third_party/blink/renderer/core/frame/navigator.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+
+namespace blink {
+
+class Document;
+class ExceptionState;
+class Navigator;
+class ScriptState;
+class ServiceWorkerContainer;
+
+class MODULES_EXPORT NavigatorServiceWorker final
+ : public GarbageCollected<NavigatorServiceWorker>,
+ public Supplement<Navigator> {
+ USING_GARBAGE_COLLECTED_MIXIN(NavigatorServiceWorker);
+
+ public:
+ static const char kSupplementName[];
+
+ static NavigatorServiceWorker* From(Document&);
+ static NavigatorServiceWorker& From(Navigator&);
+ static NavigatorServiceWorker* ToNavigatorServiceWorker(Navigator&);
+ static ServiceWorkerContainer* serviceWorker(ScriptState*,
+ Navigator&,
+ ExceptionState&);
+ static ServiceWorkerContainer* serviceWorker(ScriptState*,
+ Navigator&,
+ String& error_message);
+ void ClearServiceWorker();
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ explicit NavigatorServiceWorker(Navigator&);
+ ServiceWorkerContainer* serviceWorker(LocalFrame*, ExceptionState&);
+ ServiceWorkerContainer* serviceWorker(LocalFrame*, String& error_message);
+
+ Member<ServiceWorkerContainer> service_worker_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_NAVIGATOR_SERVICE_WORKER_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/navigator_service_worker.idl b/chromium/third_party/blink/renderer/modules/service_worker/navigator_service_worker.idl
new file mode 100644
index 00000000000..6569d07a232
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/navigator_service_worker.idl
@@ -0,0 +1,10 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://w3c.github.io/ServiceWorker/#navigator-serviceworker
+[
+ ImplementedAs=NavigatorServiceWorker
+] partial interface Navigator {
+ [SecureContext, RaisesException, CallWith=ScriptState] readonly attribute ServiceWorkerContainer serviceWorker;
+};
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/registration_options.idl b/chromium/third_party/blink/renderer/modules/service_worker/registration_options.idl
index 4442ea6b261..4442ea6b261 100644
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/registration_options.idl
+++ b/chromium/third_party/blink/renderer/modules/service_worker/registration_options.idl
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.cc b/chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.cc
new file mode 100644
index 00000000000..564b748a583
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.cc
@@ -0,0 +1,101 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/service_worker/respond_with_observer.h"
+
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_response.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/modules/service_worker/wait_until_observer.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+#include "v8/include/v8.h"
+
+using blink::mojom::ServiceWorkerResponseError;
+
+namespace blink {
+
+void RespondWithObserver::ContextDestroyed(ExecutionContext*) {
+ if (observer_) {
+ DCHECK_EQ(kPending, state_);
+ observer_.Clear();
+ }
+ state_ = kDone;
+}
+
+void RespondWithObserver::WillDispatchEvent() {
+ event_dispatch_time_ = WTF::CurrentTime();
+}
+
+void RespondWithObserver::DidDispatchEvent(
+ DispatchEventResult dispatch_result) {
+ DCHECK(GetExecutionContext());
+ if (state_ != kInitial)
+ return;
+
+ if (dispatch_result == DispatchEventResult::kNotCanceled) {
+ OnNoResponse();
+ } else {
+ OnResponseRejected(ServiceWorkerResponseError::kDefaultPrevented);
+ }
+
+ state_ = kDone;
+ observer_.Clear();
+}
+
+void RespondWithObserver::RespondWith(ScriptState* script_state,
+ ScriptPromise script_promise,
+ ExceptionState& exception_state) {
+ if (state_ != kInitial) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ "The event has already been responded to.");
+ return;
+ }
+
+ state_ = kPending;
+ observer_->WaitUntil(
+ script_state, script_promise, exception_state,
+ WTF::BindRepeating(&RespondWithObserver::ResponseWasFulfilled,
+ WrapPersistent(this), exception_state.Context(),
+ WTF::Unretained(exception_state.InterfaceName()),
+ WTF::Unretained(exception_state.PropertyName())),
+ WTF::BindRepeating(&RespondWithObserver::ResponseWasRejected,
+ WrapPersistent(this),
+ ServiceWorkerResponseError::kPromiseRejected));
+}
+
+void RespondWithObserver::ResponseWasRejected(ServiceWorkerResponseError error,
+ const ScriptValue& value) {
+ OnResponseRejected(error);
+ state_ = kDone;
+ observer_.Clear();
+}
+
+void RespondWithObserver::ResponseWasFulfilled(
+ ExceptionState::ContextType context_type,
+ const char* interface_name,
+ const char* property_name,
+ const ScriptValue& value) {
+ OnResponseFulfilled(value, context_type, interface_name, property_name);
+ state_ = kDone;
+ observer_.Clear();
+}
+
+RespondWithObserver::RespondWithObserver(ExecutionContext* context,
+ int event_id,
+ WaitUntilObserver* observer)
+ : ContextLifecycleObserver(context),
+ event_id_(event_id),
+ state_(kInitial),
+ observer_(observer) {}
+
+void RespondWithObserver::Trace(blink::Visitor* visitor) {
+ visitor->Trace(observer_);
+ ContextLifecycleObserver::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.h b/chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.h
new file mode 100644
index 00000000000..ed0547e7ec3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/respond_with_observer.h
@@ -0,0 +1,87 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_RESPOND_WITH_OBSERVER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_RESPOND_WITH_OBSERVER_H_
+
+#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-shared.h"
+#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/core/dom/events/event_target.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+class ExecutionContext;
+class ScriptPromise;
+class ScriptState;
+class ScriptValue;
+class WaitUntilObserver;
+
+// This is a base class to implement respondWith. The respondWith has the three
+// types of results: fulfilled, rejected and not called. Derived classes for
+// each event should implement the procedure of the three behaviors by
+// overriding onResponseFulfilled, onResponseRejected and onNoResponse.
+class MODULES_EXPORT RespondWithObserver
+ : public GarbageCollectedFinalized<RespondWithObserver>,
+ public ContextLifecycleObserver {
+ USING_GARBAGE_COLLECTED_MIXIN(RespondWithObserver);
+
+ public:
+ virtual ~RespondWithObserver() = default;
+
+ void ContextDestroyed(ExecutionContext*) override;
+
+ void WillDispatchEvent();
+ void DidDispatchEvent(DispatchEventResult dispatch_result);
+
+ // The respondWith() observes the promise until the given promise is resolved
+ // or rejected and then delays calling ServiceWorkerGlobalScopeClient::
+ // didHandle*Event() in order to notify the result to the client.
+ void RespondWith(ScriptState*, ScriptPromise, ExceptionState&);
+
+ // Called when the respondWith() promise was rejected.
+ virtual void OnResponseRejected(mojom::ServiceWorkerResponseError) = 0;
+
+ // Called when the respondWith() promise was fulfilled.
+ virtual void OnResponseFulfilled(const ScriptValue&,
+ ExceptionState::ContextType,
+ const char* interface_name,
+ const char* property_name) = 0;
+
+ // Called when the event handler finished without calling respondWith().
+ virtual void OnNoResponse() = 0;
+
+ void Trace(blink::Visitor*) override;
+
+ protected:
+ RespondWithObserver(ExecutionContext*, int event_id, WaitUntilObserver*);
+ const int event_id_;
+ double event_dispatch_time_ = 0;
+
+ private:
+ class ThenFunction;
+
+ void ResponseWasRejected(mojom::ServiceWorkerResponseError,
+ const ScriptValue&);
+ void ResponseWasFulfilled(ExceptionState::ContextType,
+ const char* interface_name,
+ const char* property_name,
+ const ScriptValue&);
+
+ enum State { kInitial, kPending, kDone };
+ State state_;
+
+ // RespondWith should ensure the ExtendableEvent is alive until the promise
+ // passed to RespondWith is resolved. The lifecycle of the ExtendableEvent
+ // is controlled by WaitUntilObserver, so not only
+ // WaitUntilObserver::ThenFunction but RespondWith needs to have a strong
+ // reference to the WaitUntilObserver.
+ Member<WaitUntilObserver> observer_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_RESPOND_WITH_OBSERVER_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker.cc
new file mode 100644
index 00000000000..33dad765d81
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker.cc
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * 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/modules/service_worker/service_worker.h"
+
+#include <memory>
+#include "third_party/blink/public/mojom/service_worker/service_worker_state.mojom-blink.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.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/messaging/blink_transferable_message.h"
+#include "third_party/blink/renderer/core/messaging/message_port.h"
+#include "third_party/blink/renderer/modules/event_target_modules.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_container_client.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+
+namespace blink {
+
+const AtomicString& ServiceWorker::InterfaceName() const {
+ return EventTargetNames::ServiceWorker;
+}
+
+void ServiceWorker::postMessage(ScriptState* script_state,
+ scoped_refptr<SerializedScriptValue> message,
+ const MessagePortArray& ports,
+ ExceptionState& exception_state) {
+ ServiceWorkerContainerClient* client =
+ ServiceWorkerContainerClient::From(GetExecutionContext());
+ if (!client || !client->Provider()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ "Failed to post a message: No associated provider is available.");
+ return;
+ }
+
+ BlinkTransferableMessage msg;
+ msg.message = message;
+ msg.ports = MessagePort::DisentanglePorts(
+ ExecutionContext::From(script_state), ports, exception_state);
+ if (exception_state.HadException())
+ return;
+
+ if (handle_->ServiceWorker()->GetState() ==
+ mojom::blink::ServiceWorkerState::kRedundant) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "ServiceWorker is in redundant state.");
+ return;
+ }
+
+ handle_->ServiceWorker()->PostMessageToServiceWorker(
+ ToTransferableMessage(std::move(msg)));
+}
+
+ScriptPromise ServiceWorker::InternalsTerminate(ScriptState* script_state) {
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+ ScriptPromise promise = resolver->Promise();
+ handle_->ServiceWorker()->TerminateForTesting(
+ std::make_unique<CallbackPromiseAdapter<void, void>>(resolver));
+ return promise;
+}
+
+void ServiceWorker::DispatchStateChangeEvent() {
+ this->DispatchEvent(Event::Create(EventTypeNames::statechange));
+}
+
+String ServiceWorker::scriptURL() const {
+ return handle_->ServiceWorker()->Url().GetString();
+}
+
+String ServiceWorker::state() const {
+ switch (handle_->ServiceWorker()->GetState()) {
+ case mojom::blink::ServiceWorkerState::kUnknown:
+ // The web platform should never see this internal state
+ NOTREACHED();
+ return "unknown";
+ case mojom::blink::ServiceWorkerState::kInstalling:
+ return "installing";
+ case mojom::blink::ServiceWorkerState::kInstalled:
+ return "installed";
+ case mojom::blink::ServiceWorkerState::kActivating:
+ return "activating";
+ case mojom::blink::ServiceWorkerState::kActivated:
+ return "activated";
+ case mojom::blink::ServiceWorkerState::kRedundant:
+ return "redundant";
+ }
+ NOTREACHED();
+ return g_null_atom;
+}
+
+ServiceWorker* ServiceWorker::From(
+ ExecutionContext* execution_context,
+ std::unique_ptr<WebServiceWorker::Handle> handle) {
+ return GetOrCreate(execution_context, std::move(handle));
+}
+
+bool ServiceWorker::HasPendingActivity() const {
+ if (was_stopped_)
+ return false;
+ return handle_->ServiceWorker()->GetState() !=
+ mojom::blink::ServiceWorkerState::kRedundant;
+}
+
+void ServiceWorker::ContextDestroyed(ExecutionContext*) {
+ was_stopped_ = true;
+}
+
+ServiceWorker* ServiceWorker::GetOrCreate(
+ ExecutionContext* execution_context,
+ std::unique_ptr<WebServiceWorker::Handle> handle) {
+ if (!handle)
+ return nullptr;
+
+ ServiceWorker* existing_worker =
+ static_cast<ServiceWorker*>(handle->ServiceWorker()->Proxy());
+ if (existing_worker) {
+ DCHECK_EQ(existing_worker->GetExecutionContext(), execution_context);
+ return existing_worker;
+ }
+
+ return new ServiceWorker(execution_context, std::move(handle));
+}
+
+ServiceWorker::ServiceWorker(ExecutionContext* execution_context,
+ std::unique_ptr<WebServiceWorker::Handle> handle)
+ : AbstractWorker(execution_context),
+ handle_(std::move(handle)),
+ was_stopped_(false) {
+ DCHECK(handle_);
+ handle_->ServiceWorker()->SetProxy(this);
+}
+
+ServiceWorker::~ServiceWorker() = default;
+
+void ServiceWorker::Trace(blink::Visitor* visitor) {
+ AbstractWorker::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker.h
new file mode 100644
index 00000000000..bdd5d3a4936
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * 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_MODULES_SERVICE_WORKER_SERVICE_WORKER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_H_
+
+#include <memory>
+#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_proxy.h"
+#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
+#include "third_party/blink/renderer/core/workers/abstract_worker.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+
+namespace blink {
+
+class ScriptState;
+
+class MODULES_EXPORT ServiceWorker final
+ : public AbstractWorker,
+ public ActiveScriptWrappable<ServiceWorker>,
+ public WebServiceWorkerProxy {
+ DEFINE_WRAPPERTYPEINFO();
+ USING_GARBAGE_COLLECTED_MIXIN(ServiceWorker);
+
+ public:
+ static ServiceWorker* From(ExecutionContext*,
+ std::unique_ptr<WebServiceWorker::Handle>);
+
+ ~ServiceWorker() override;
+ void Trace(blink::Visitor*) override;
+
+ // Eager finalization needed to promptly release owned WebServiceWorker.
+ EAGERLY_FINALIZE();
+
+ void postMessage(ScriptState*,
+ scoped_refptr<SerializedScriptValue> message,
+ const MessagePortArray&,
+ ExceptionState&);
+ static bool CanTransferArrayBuffersAndImageBitmaps() { return false; }
+
+ String scriptURL() const;
+ String state() const;
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(statechange);
+
+ ServiceWorker* ToServiceWorker() override { return this; }
+
+ // ScriptWrappable overrides.
+ bool HasPendingActivity() const final;
+
+ // WebServiceWorkerProxy overrides.
+ void DispatchStateChangeEvent() override;
+
+ // AbstractWorker overrides.
+ const AtomicString& InterfaceName() const override;
+
+ ScriptPromise InternalsTerminate(ScriptState*);
+
+ private:
+ static ServiceWorker* GetOrCreate(ExecutionContext*,
+ std::unique_ptr<WebServiceWorker::Handle>);
+ ServiceWorker(ExecutionContext*, std::unique_ptr<WebServiceWorker::Handle>);
+
+ // PausableObject overrides.
+ void ContextDestroyed(ExecutionContext*) override;
+
+ // A handle to the service worker representation in the embedder.
+ std::unique_ptr<WebServiceWorker::Handle> handle_;
+ bool was_stopped_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker.idl b/chromium/third_party/blink/renderer/modules/service_worker/service_worker.idl
new file mode 100644
index 00000000000..505ea0114a1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker.idl
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * 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.
+ */
+
+// https://w3c.github.io/ServiceWorker/#serviceworker-interface
+
+enum ServiceWorkerState {
+ "installing",
+ "installed",
+ "activating",
+ "activated",
+ "redundant"
+};
+
+[
+ ActiveScriptWrappable,
+ SecureContext
+] interface ServiceWorker : EventTarget {
+
+ [PostMessage, RaisesException] void postMessage(any message, optional sequence<object> transfer);
+
+ readonly attribute USVString scriptURL;
+ readonly attribute ServiceWorkerState state;
+
+ attribute EventHandler onstatechange;
+};
+
+ServiceWorker implements AbstractWorker;
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_client.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_client.cc
new file mode 100644
index 00000000000..4a1d2df4f77
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_client.cc
@@ -0,0 +1,105 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/service_worker/service_worker_client.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_window_client.h"
+
+#include <memory>
+#include "base/memory/scoped_refptr.h"
+#include "services/network/public/mojom/request_context_frame_type.mojom-blink.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom-blink.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
+#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/core/messaging/blink_transferable_message.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+
+namespace blink {
+
+ServiceWorkerClient* ServiceWorkerClient::Take(
+ ScriptPromiseResolver*,
+ std::unique_ptr<WebServiceWorkerClientInfo> web_client) {
+ if (!web_client)
+ return nullptr;
+
+ switch (web_client->client_type) {
+ case mojom::ServiceWorkerClientType::kWindow:
+ return ServiceWorkerWindowClient::Create(*web_client);
+ case mojom::ServiceWorkerClientType::kSharedWorker:
+ return ServiceWorkerClient::Create(*web_client);
+ case mojom::ServiceWorkerClientType::kAll:
+ NOTREACHED();
+ return nullptr;
+ }
+ NOTREACHED();
+ return nullptr;
+}
+
+ServiceWorkerClient* ServiceWorkerClient::Create(
+ const WebServiceWorkerClientInfo& info) {
+ return new ServiceWorkerClient(info);
+}
+
+ServiceWorkerClient::ServiceWorkerClient(const WebServiceWorkerClientInfo& info)
+ : uuid_(info.uuid),
+ url_(info.url.GetString()),
+ type_(info.client_type),
+ frame_type_(info.frame_type) {}
+
+ServiceWorkerClient::~ServiceWorkerClient() = default;
+
+String ServiceWorkerClient::type() const {
+ switch (type_) {
+ case mojom::ServiceWorkerClientType::kWindow:
+ return "window";
+ case mojom::ServiceWorkerClientType::kSharedWorker:
+ return "sharedworker";
+ case mojom::ServiceWorkerClientType::kAll:
+ NOTREACHED();
+ return String();
+ }
+
+ NOTREACHED();
+ return String();
+}
+
+String ServiceWorkerClient::frameType(ScriptState* script_state) const {
+ UseCounter::Count(ExecutionContext::From(script_state),
+ WebFeature::kServiceWorkerClientFrameType);
+ switch (frame_type_) {
+ case network::mojom::RequestContextFrameType::kAuxiliary:
+ return "auxiliary";
+ case network::mojom::RequestContextFrameType::kNested:
+ return "nested";
+ case network::mojom::RequestContextFrameType::kNone:
+ return "none";
+ case network::mojom::RequestContextFrameType::kTopLevel:
+ return "top-level";
+ }
+
+ NOTREACHED();
+ return String();
+}
+
+void ServiceWorkerClient::postMessage(
+ ScriptState* script_state,
+ scoped_refptr<SerializedScriptValue> message,
+ const MessagePortArray& ports,
+ ExceptionState& exception_state) {
+ ExecutionContext* context = ExecutionContext::From(script_state);
+ BlinkTransferableMessage msg;
+ msg.message = message;
+ msg.ports = MessagePort::DisentanglePorts(context, ports, exception_state);
+ if (exception_state.HadException())
+ return;
+
+ ServiceWorkerGlobalScopeClient::From(context)->PostMessageToClient(
+ uuid_, ToTransferableMessage(std::move(msg)));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_client.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_client.h
new file mode 100644
index 00000000000..7cbe7818f79
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_client.h
@@ -0,0 +1,61 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_CLIENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_CLIENT_H_
+
+#include <memory>
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_clients_info.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#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/wtf/forward.h"
+
+namespace blink {
+
+class ScriptPromiseResolver;
+class ScriptState;
+
+class MODULES_EXPORT ServiceWorkerClient : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ // To be used by CallbackPromiseAdapter.
+ using WebType = std::unique_ptr<WebServiceWorkerClientInfo>;
+
+ static ServiceWorkerClient* Take(ScriptPromiseResolver*,
+ std::unique_ptr<WebServiceWorkerClientInfo>);
+ static ServiceWorkerClient* Create(const WebServiceWorkerClientInfo&);
+
+ ~ServiceWorkerClient() override;
+
+ // Client.idl
+ String url() const { return url_; }
+ String type() const;
+ String frameType(ScriptState*) const;
+ String id() const { return uuid_; }
+ void postMessage(ScriptState*,
+ scoped_refptr<SerializedScriptValue> message,
+ const MessagePortArray&,
+ ExceptionState&);
+
+ static bool CanTransferArrayBuffersAndImageBitmaps() { return false; }
+
+ protected:
+ explicit ServiceWorkerClient(const WebServiceWorkerClientInfo&);
+
+ String Uuid() const { return uuid_; }
+
+ private:
+ String uuid_;
+ String url_;
+ mojom::ServiceWorkerClientType type_;
+ network::mojom::RequestContextFrameType frame_type_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_clients.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_clients.cc
new file mode 100644
index 00000000000..d717f2161ac
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_clients.cc
@@ -0,0 +1,193 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/service_worker/service_worker_clients.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/memory/ptr_util.h"
+#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom-blink.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_client_query_options.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_clients_info.h"
+#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/workers/worker_global_scope.h"
+#include "third_party/blink/renderer/core/workers/worker_location.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_error.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_window_client.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_window_client_callback.h"
+#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+namespace {
+
+class ClientArray {
+ public:
+ using WebType = const WebServiceWorkerClientsInfo&;
+ static HeapVector<Member<ServiceWorkerClient>> Take(
+ ScriptPromiseResolver*,
+ const WebServiceWorkerClientsInfo& web_clients) {
+ HeapVector<Member<ServiceWorkerClient>> clients;
+ for (size_t i = 0; i < web_clients.clients.size(); ++i) {
+ const WebServiceWorkerClientInfo& client = web_clients.clients[i];
+ if (client.client_type == mojom::ServiceWorkerClientType::kWindow)
+ clients.push_back(ServiceWorkerWindowClient::Create(client));
+ else
+ clients.push_back(ServiceWorkerClient::Create(client));
+ }
+ return clients;
+ }
+
+ private:
+ WTF_MAKE_NONCOPYABLE(ClientArray);
+ ClientArray() = delete;
+};
+
+mojom::ServiceWorkerClientType GetClientType(const String& type) {
+ if (type == "window")
+ return mojom::ServiceWorkerClientType::kWindow;
+ if (type == "sharedworker")
+ return mojom::ServiceWorkerClientType::kSharedWorker;
+ if (type == "all")
+ return mojom::ServiceWorkerClientType::kAll;
+ NOTREACHED();
+ return mojom::ServiceWorkerClientType::kWindow;
+}
+
+class GetCallback : public WebServiceWorkerClientCallbacks {
+ public:
+ explicit GetCallback(ScriptPromiseResolver* resolver) : resolver_(resolver) {}
+ ~GetCallback() override = default;
+
+ void OnSuccess(
+ std::unique_ptr<WebServiceWorkerClientInfo> web_client) override {
+ std::unique_ptr<WebServiceWorkerClientInfo> client =
+ base::WrapUnique(web_client.release());
+ if (!resolver_->GetExecutionContext() ||
+ resolver_->GetExecutionContext()->IsContextDestroyed())
+ return;
+ if (!client) {
+ // Resolve the promise with undefined.
+ resolver_->Resolve();
+ return;
+ }
+ resolver_->Resolve(ServiceWorkerClient::Take(resolver_, std::move(client)));
+ }
+
+ void OnError(const WebServiceWorkerError& error) override {
+ if (!resolver_->GetExecutionContext() ||
+ resolver_->GetExecutionContext()->IsContextDestroyed())
+ return;
+ resolver_->Reject(ServiceWorkerError::Take(resolver_.Get(), error));
+ }
+
+ private:
+ Persistent<ScriptPromiseResolver> resolver_;
+ WTF_MAKE_NONCOPYABLE(GetCallback);
+};
+
+} // namespace
+
+ServiceWorkerClients* ServiceWorkerClients::Create() {
+ return new ServiceWorkerClients();
+}
+
+ServiceWorkerClients::ServiceWorkerClients() = default;
+
+ScriptPromise ServiceWorkerClients::get(ScriptState* script_state,
+ const String& id) {
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+ // TODO(jungkees): May be null due to worker termination:
+ // http://crbug.com/413518.
+ if (!execution_context)
+ return ScriptPromise();
+
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ ServiceWorkerGlobalScopeClient::From(execution_context)
+ ->GetClient(id, std::make_unique<GetCallback>(resolver));
+ return promise;
+}
+
+ScriptPromise ServiceWorkerClients::matchAll(
+ ScriptState* script_state,
+ const ClientQueryOptions& options) {
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+ // FIXME: May be null due to worker termination: http://crbug.com/413518.
+ if (!execution_context)
+ return ScriptPromise();
+
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ WebServiceWorkerClientQueryOptions web_options;
+ web_options.client_type = GetClientType(options.type());
+ web_options.include_uncontrolled = options.includeUncontrolled();
+ ServiceWorkerGlobalScopeClient::From(execution_context)
+ ->GetClients(web_options,
+ std::make_unique<
+ CallbackPromiseAdapter<ClientArray, ServiceWorkerError>>(
+ resolver));
+ return promise;
+}
+
+ScriptPromise ServiceWorkerClients::claim(ScriptState* script_state) {
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+
+ // FIXME: May be null due to worker termination: http://crbug.com/413518.
+ if (!execution_context)
+ return ScriptPromise();
+
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ auto callbacks =
+ std::make_unique<CallbackPromiseAdapter<void, ServiceWorkerError>>(
+ resolver);
+ ServiceWorkerGlobalScopeClient::From(execution_context)
+ ->Claim(std::move(callbacks));
+ return promise;
+}
+
+ScriptPromise ServiceWorkerClients::openWindow(ScriptState* script_state,
+ const String& url) {
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+ ScriptPromise promise = resolver->Promise();
+ ExecutionContext* context = ExecutionContext::From(script_state);
+
+ KURL parsed_url = KURL(ToWorkerGlobalScope(context)->location()->Url(), url);
+ if (!parsed_url.IsValid()) {
+ resolver->Reject(V8ThrowException::CreateTypeError(
+ script_state->GetIsolate(), "'" + url + "' is not a valid URL."));
+ return promise;
+ }
+
+ if (!context->GetSecurityOrigin()->CanDisplay(parsed_url)) {
+ resolver->Reject(V8ThrowException::CreateTypeError(
+ script_state->GetIsolate(),
+ "'" + parsed_url.ElidedString() + "' cannot be opened."));
+ return promise;
+ }
+
+ if (!context->IsWindowInteractionAllowed()) {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kInvalidAccessError,
+ "Not allowed to open a window."));
+ return promise;
+ }
+ context->ConsumeWindowInteraction();
+
+ ServiceWorkerGlobalScopeClient::From(context)->OpenWindowForClients(
+ parsed_url, std::make_unique<NavigateClientCallback>(resolver));
+ return promise;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_clients.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_clients.h
new file mode 100644
index 00000000000..3e6bc04da34
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_clients.h
@@ -0,0 +1,36 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_CLIENTS_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_CLIENTS_H_
+
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_clients_info.h"
+#include "third_party/blink/renderer/modules/service_worker/client_query_options.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+class ScriptPromise;
+class ScriptState;
+
+class ServiceWorkerClients final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static ServiceWorkerClients* Create();
+
+ // Clients.idl
+ ScriptPromise get(ScriptState*, const String& id);
+ ScriptPromise matchAll(ScriptState*, const ClientQueryOptions&);
+ ScriptPromise openWindow(ScriptState*, const String& url);
+ ScriptPromise claim(ScriptState*);
+
+ private:
+ ServiceWorkerClients();
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_CLIENTS_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.cc
new file mode 100644
index 00000000000..c2cd91e8b21
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.cc
@@ -0,0 +1,474 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * 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/modules/service_worker/service_worker_container.h"
+
+#include <memory>
+#include <utility>
+#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_registration.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
+#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_factory.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/events/message_event.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/deprecation.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/core/messaging/blink_transferable_message.h"
+#include "third_party/blink/renderer/core/messaging/message_port.h"
+#include "third_party/blink/renderer/modules/event_target_modules.h"
+#include "third_party/blink/renderer/modules/service_worker/navigator_service_worker.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_container_client.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_error.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.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/weborigin/scheme_registry.h"
+#include "third_party/blink/renderer/platform/weborigin/security_violation_reporting_policy.h"
+
+namespace blink {
+
+namespace {
+
+mojom::ServiceWorkerUpdateViaCache ParseUpdateViaCache(const String& value) {
+ if (value == "imports")
+ return mojom::ServiceWorkerUpdateViaCache::kImports;
+ if (value == "all")
+ return mojom::ServiceWorkerUpdateViaCache::kAll;
+ if (value == "none")
+ return mojom::ServiceWorkerUpdateViaCache::kNone;
+ // Default value.
+ return mojom::ServiceWorkerUpdateViaCache::kImports;
+}
+
+class GetRegistrationCallback : public WebServiceWorkerProvider::
+ WebServiceWorkerGetRegistrationCallbacks {
+ public:
+ explicit GetRegistrationCallback(ScriptPromiseResolver* resolver)
+ : resolver_(resolver) {}
+ ~GetRegistrationCallback() override = default;
+
+ void OnSuccess(
+ std::unique_ptr<WebServiceWorkerRegistration::Handle> handle) override {
+ if (!resolver_->GetExecutionContext() ||
+ resolver_->GetExecutionContext()->IsContextDestroyed())
+ return;
+ if (!handle) {
+ // Resolve the promise with undefined.
+ resolver_->Resolve();
+ return;
+ }
+ resolver_->Resolve(ServiceWorkerRegistration::GetOrCreate(
+ resolver_->GetExecutionContext(), std::move(handle)));
+ }
+
+ void OnError(const WebServiceWorkerError& error) override {
+ if (!resolver_->GetExecutionContext() ||
+ resolver_->GetExecutionContext()->IsContextDestroyed())
+ return;
+ resolver_->Reject(ServiceWorkerError::Take(resolver_.Get(), error));
+ }
+
+ private:
+ Persistent<ScriptPromiseResolver> resolver_;
+ WTF_MAKE_NONCOPYABLE(GetRegistrationCallback);
+};
+
+} // namespace
+
+class ServiceWorkerContainer::GetRegistrationForReadyCallback
+ : public WebServiceWorkerProvider::
+ WebServiceWorkerGetRegistrationForReadyCallbacks {
+ public:
+ explicit GetRegistrationForReadyCallback(ReadyProperty* ready)
+ : ready_(ready) {}
+ ~GetRegistrationForReadyCallback() override = default;
+
+ void OnSuccess(
+ std::unique_ptr<WebServiceWorkerRegistration::Handle> handle) override {
+ DCHECK_EQ(ready_->GetState(), ReadyProperty::kPending);
+
+ if (ready_->GetExecutionContext() &&
+ !ready_->GetExecutionContext()->IsContextDestroyed()) {
+ ready_->Resolve(ServiceWorkerRegistration::GetOrCreate(
+ ready_->GetExecutionContext(), std::move(handle)));
+ }
+ }
+
+ private:
+ Persistent<ReadyProperty> ready_;
+ WTF_MAKE_NONCOPYABLE(GetRegistrationForReadyCallback);
+};
+
+ServiceWorkerContainer* ServiceWorkerContainer::Create(
+ ExecutionContext* execution_context,
+ NavigatorServiceWorker* navigator) {
+ return new ServiceWorkerContainer(execution_context, navigator);
+}
+
+ServiceWorkerContainer::~ServiceWorkerContainer() {
+ DCHECK(!provider_);
+}
+
+void ServiceWorkerContainer::ContextDestroyed(ExecutionContext*) {
+ if (provider_) {
+ provider_->SetClient(nullptr);
+ provider_ = nullptr;
+ }
+ controller_ = nullptr;
+ navigator_->ClearServiceWorker();
+}
+
+void ServiceWorkerContainer::Trace(blink::Visitor* visitor) {
+ visitor->Trace(controller_);
+ visitor->Trace(ready_);
+ visitor->Trace(navigator_);
+ EventTargetWithInlineData::Trace(visitor);
+ ContextLifecycleObserver::Trace(visitor);
+}
+
+ScriptPromise ServiceWorkerContainer::registerServiceWorker(
+ ScriptState* script_state,
+ const String& url,
+ const RegistrationOptions& options) {
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ if (!provider_) {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Failed to register a ServiceWorker: "
+ "The document is in an invalid "
+ "state."));
+ return promise;
+ }
+
+ auto callbacks = std::make_unique<CallbackPromiseAdapter<
+ ServiceWorkerRegistration, ServiceWorkerErrorForUpdate>>(resolver);
+
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+
+ // The IDL definition is expected to restrict service worker to secure
+ // contexts.
+ CHECK(execution_context->IsSecureContext());
+
+ scoped_refptr<const SecurityOrigin> document_origin =
+ execution_context->GetSecurityOrigin();
+ KURL page_url = KURL(NullURL(), document_origin->ToString());
+ if (!SchemeRegistry::ShouldTreatURLSchemeAsAllowingServiceWorkers(
+ page_url.Protocol())) {
+ callbacks->OnError(WebServiceWorkerError(
+ mojom::blink::ServiceWorkerErrorType::kSecurity,
+ String("Failed to register a ServiceWorker: The URL protocol of the "
+ "current origin ('" +
+ document_origin->ToString() + "') is not supported.")));
+ return promise;
+ }
+
+ KURL script_url = execution_context->CompleteURL(url);
+ script_url.RemoveFragmentIdentifier();
+
+ if (!document_origin->CanRequest(script_url)) {
+ scoped_refptr<const SecurityOrigin> script_origin =
+ SecurityOrigin::Create(script_url);
+ callbacks->OnError(
+ WebServiceWorkerError(mojom::blink::ServiceWorkerErrorType::kSecurity,
+ String("Failed to register a ServiceWorker: The "
+ "origin of the provided scriptURL ('" +
+ script_origin->ToString() +
+ "') does not match the current origin ('" +
+ document_origin->ToString() + "').")));
+ return promise;
+ }
+ if (!SchemeRegistry::ShouldTreatURLSchemeAsAllowingServiceWorkers(
+ script_url.Protocol())) {
+ callbacks->OnError(WebServiceWorkerError(
+ mojom::blink::ServiceWorkerErrorType::kSecurity,
+ String("Failed to register a ServiceWorker: The URL protocol of the "
+ "script ('" +
+ script_url.GetString() + "') is not supported.")));
+ return promise;
+ }
+
+ KURL pattern_url;
+ if (options.scope().IsNull())
+ pattern_url = KURL(script_url, "./");
+ else
+ pattern_url = execution_context->CompleteURL(options.scope());
+ pattern_url.RemoveFragmentIdentifier();
+
+ if (!document_origin->CanRequest(pattern_url)) {
+ scoped_refptr<const SecurityOrigin> pattern_origin =
+ SecurityOrigin::Create(pattern_url);
+ callbacks->OnError(
+ WebServiceWorkerError(mojom::blink::ServiceWorkerErrorType::kSecurity,
+ String("Failed to register a ServiceWorker: The "
+ "origin of the provided scope ('" +
+ pattern_origin->ToString() +
+ "') does not match the current origin ('" +
+ document_origin->ToString() + "').")));
+ return promise;
+ }
+ if (!SchemeRegistry::ShouldTreatURLSchemeAsAllowingServiceWorkers(
+ pattern_url.Protocol())) {
+ callbacks->OnError(WebServiceWorkerError(
+ mojom::blink::ServiceWorkerErrorType::kSecurity,
+ String("Failed to register a ServiceWorker: The URL protocol of the "
+ "scope ('" +
+ pattern_url.GetString() + "') is not supported.")));
+ return promise;
+ }
+
+ WebString web_error_message;
+ if (!provider_->ValidateScopeAndScriptURL(pattern_url, script_url,
+ &web_error_message)) {
+ callbacks->OnError(WebServiceWorkerError(
+ mojom::blink::ServiceWorkerErrorType::kType,
+ WebString::FromUTF8("Failed to register a ServiceWorker: " +
+ web_error_message.Utf8())));
+ return promise;
+ }
+
+ ContentSecurityPolicy* csp = execution_context->GetContentSecurityPolicy();
+ if (csp) {
+ if (!csp->AllowRequestWithoutIntegrity(
+ WebURLRequest::kRequestContextServiceWorker, script_url) ||
+ !csp->AllowWorkerContextFromSource(
+ script_url, ResourceRequest::RedirectStatus::kNoRedirect,
+ SecurityViolationReportingPolicy::kReport)) {
+ callbacks->OnError(WebServiceWorkerError(
+ mojom::blink::ServiceWorkerErrorType::kSecurity,
+ String(
+ "Failed to register a ServiceWorker: The provided scriptURL ('" +
+ script_url.GetString() +
+ "') violates the Content Security Policy.")));
+ return promise;
+ }
+ }
+
+ mojom::ServiceWorkerUpdateViaCache update_via_cache =
+ ParseUpdateViaCache(options.updateViaCache());
+
+ provider_->RegisterServiceWorker(pattern_url, script_url, update_via_cache,
+ std::move(callbacks));
+ return promise;
+}
+
+ScriptPromise ServiceWorkerContainer::getRegistration(
+ ScriptState* script_state,
+ const String& document_url) {
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ if (!provider_) {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Failed to get a "
+ "ServiceWorkerRegistration: The "
+ "document is in an invalid state."));
+ return promise;
+ }
+
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+
+ // The IDL definition is expected to restrict service worker to secure
+ // contexts.
+ CHECK(execution_context->IsSecureContext());
+
+ scoped_refptr<const SecurityOrigin> document_origin =
+ execution_context->GetSecurityOrigin();
+ KURL page_url = KURL(NullURL(), document_origin->ToString());
+ if (!SchemeRegistry::ShouldTreatURLSchemeAsAllowingServiceWorkers(
+ page_url.Protocol())) {
+ resolver->Reject(DOMException::Create(
+ DOMExceptionCode::kSecurityError,
+ "Failed to get a ServiceWorkerRegistration: The URL protocol of the "
+ "current origin ('" +
+ document_origin->ToString() + "') is not supported."));
+ return promise;
+ }
+
+ KURL completed_url = execution_context->CompleteURL(document_url);
+ completed_url.RemoveFragmentIdentifier();
+ if (!document_origin->CanRequest(completed_url)) {
+ scoped_refptr<const SecurityOrigin> document_url_origin =
+ SecurityOrigin::Create(completed_url);
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kSecurityError,
+ "Failed to get a ServiceWorkerRegistration: The "
+ "origin of the provided documentURL ('" +
+ document_url_origin->ToString() +
+ "') does not match the current origin ('" +
+ document_origin->ToString() + "')."));
+ return promise;
+ }
+ provider_->GetRegistration(
+ completed_url, std::make_unique<GetRegistrationCallback>(resolver));
+
+ return promise;
+}
+
+ScriptPromise ServiceWorkerContainer::getRegistrations(
+ ScriptState* script_state) {
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ if (!provider_) {
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Failed to get ServiceWorkerRegistration objects: "
+ "The document is in an invalid state."));
+ return promise;
+ }
+
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+
+ // The IDL definition is expected to restrict service worker to secure
+ // contexts.
+ CHECK(execution_context->IsSecureContext());
+
+ scoped_refptr<const SecurityOrigin> document_origin =
+ execution_context->GetSecurityOrigin();
+ KURL page_url = KURL(NullURL(), document_origin->ToString());
+ if (!SchemeRegistry::ShouldTreatURLSchemeAsAllowingServiceWorkers(
+ page_url.Protocol())) {
+ resolver->Reject(DOMException::Create(
+ DOMExceptionCode::kSecurityError,
+ "Failed to get ServiceWorkerRegistration objects: The URL protocol of "
+ "the current origin ('" +
+ document_origin->ToString() + "') is not supported."));
+ return promise;
+ }
+
+ provider_->GetRegistrations(
+ std::make_unique<CallbackPromiseAdapter<ServiceWorkerRegistrationArray,
+ ServiceWorkerError>>(resolver));
+
+ return promise;
+}
+
+ServiceWorkerContainer::ReadyProperty*
+ServiceWorkerContainer::CreateReadyProperty() {
+ return new ReadyProperty(GetExecutionContext(), this, ReadyProperty::kReady);
+}
+
+ScriptPromise ServiceWorkerContainer::ready(ScriptState* caller_state) {
+ if (!GetExecutionContext())
+ return ScriptPromise();
+
+ if (!caller_state->World().IsMainWorld()) {
+ // FIXME: Support .ready from isolated worlds when
+ // ScriptPromiseProperty can vend Promises in isolated worlds.
+ return ScriptPromise::RejectWithDOMException(
+ caller_state,
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "'ready' is only supported in pages."));
+ }
+
+ if (!ready_) {
+ ready_ = CreateReadyProperty();
+ if (provider_) {
+ provider_->GetRegistrationForReady(
+ std::make_unique<GetRegistrationForReadyCallback>(ready_.Get()));
+ }
+ }
+
+ return ready_->Promise(caller_state->World());
+}
+
+void ServiceWorkerContainer::SetController(
+ std::unique_ptr<WebServiceWorker::Handle> handle,
+ bool should_notify_controller_change) {
+ if (!GetExecutionContext())
+ return;
+ controller_ = ServiceWorker::From(GetExecutionContext(), std::move(handle));
+ if (controller_) {
+ UseCounter::Count(GetExecutionContext(),
+ WebFeature::kServiceWorkerControlledPage);
+ }
+ if (should_notify_controller_change)
+ DispatchEvent(Event::Create(EventTypeNames::controllerchange));
+}
+
+void ServiceWorkerContainer::DispatchMessageEvent(
+ std::unique_ptr<WebServiceWorker::Handle> handle,
+ TransferableMessage message) {
+ if (!GetExecutionContext() || !GetExecutionContext()->ExecutingWindow())
+ return;
+ auto msg = ToBlinkTransferableMessage(std::move(message));
+ MessagePortArray* ports =
+ MessagePort::EntanglePorts(*GetExecutionContext(), std::move(msg.ports));
+ ServiceWorker* source =
+ ServiceWorker::From(GetExecutionContext(), std::move(handle));
+ DispatchEvent(MessageEvent::Create(
+ ports, std::move(msg.message),
+ GetExecutionContext()->GetSecurityOrigin()->ToString(),
+ String() /* lastEventId */, source));
+}
+
+void ServiceWorkerContainer::CountFeature(mojom::WebFeature feature) {
+ if (!GetExecutionContext())
+ return;
+ if (Deprecation::DeprecationMessage(feature).IsEmpty())
+ UseCounter::Count(GetExecutionContext(), feature);
+ else
+ Deprecation::CountDeprecation(GetExecutionContext(), feature);
+}
+
+const AtomicString& ServiceWorkerContainer::InterfaceName() const {
+ return EventTargetNames::ServiceWorkerContainer;
+}
+
+ServiceWorkerContainer::ServiceWorkerContainer(
+ ExecutionContext* execution_context,
+ NavigatorServiceWorker* navigator)
+ : ContextLifecycleObserver(execution_context),
+ provider_(nullptr),
+ navigator_(navigator) {
+ if (!execution_context)
+ return;
+
+ if (ServiceWorkerContainerClient* client =
+ ServiceWorkerContainerClient::From(execution_context)) {
+ provider_ = client->Provider();
+ if (provider_)
+ provider_->SetClient(this);
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.h
new file mode 100644
index 00000000000..ea5bc3e4f53
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * 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_MODULES_SERVICE_WORKER_SERVICE_WORKER_CONTAINER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_CONTAINER_H_
+
+#include <memory>
+#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom-blink.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider_client.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_property.h"
+#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/core/dom/events/event_target.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/modules/service_worker/registration_options.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
+#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/wtf/forward.h"
+
+namespace blink {
+
+class ExecutionContext;
+class NavigatorServiceWorker;
+class WebServiceWorker;
+class WebServiceWorkerProvider;
+
+class MODULES_EXPORT ServiceWorkerContainer final
+ : public EventTargetWithInlineData,
+ public ContextLifecycleObserver,
+ public WebServiceWorkerProviderClient {
+ DEFINE_WRAPPERTYPEINFO();
+ USING_GARBAGE_COLLECTED_MIXIN(ServiceWorkerContainer);
+
+ public:
+ using RegistrationCallbacks =
+ WebServiceWorkerProvider::WebServiceWorkerRegistrationCallbacks;
+
+ static ServiceWorkerContainer* Create(ExecutionContext*,
+ NavigatorServiceWorker*);
+ ~ServiceWorkerContainer() override;
+
+ void Trace(blink::Visitor*) override;
+
+ ServiceWorker* controller() { return controller_; }
+ ScriptPromise ready(ScriptState*);
+ WebServiceWorkerProvider* Provider() { return provider_; }
+
+ ScriptPromise registerServiceWorker(ScriptState*,
+ const String& pattern,
+ const RegistrationOptions&);
+ ScriptPromise getRegistration(ScriptState*, const String& document_url);
+ ScriptPromise getRegistrations(ScriptState*);
+
+ void ContextDestroyed(ExecutionContext*) override;
+
+ // WebServiceWorkerProviderClient implementation.
+ void SetController(std::unique_ptr<WebServiceWorker::Handle>,
+ bool should_notify_controller_change) override;
+ void DispatchMessageEvent(std::unique_ptr<WebServiceWorker::Handle>,
+ TransferableMessage) override;
+ void CountFeature(mojom::WebFeature) override;
+
+ // EventTarget overrides.
+ ExecutionContext* GetExecutionContext() const override {
+ return ContextLifecycleObserver::GetExecutionContext();
+ }
+ const AtomicString& InterfaceName() const override;
+
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(controllerchange);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(message);
+
+ private:
+ ServiceWorkerContainer(ExecutionContext*, NavigatorServiceWorker*);
+
+ class GetRegistrationForReadyCallback;
+ using ReadyProperty =
+ ScriptPromiseProperty<Member<ServiceWorkerContainer>,
+ Member<ServiceWorkerRegistration>,
+ Member<ServiceWorkerRegistration>>;
+ ReadyProperty* CreateReadyProperty();
+
+ WebServiceWorkerProvider* provider_;
+ Member<ServiceWorker> controller_;
+ Member<ReadyProperty> ready_;
+ Member<NavigatorServiceWorker> navigator_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_CONTAINER_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.idl b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.idl
new file mode 100644
index 00000000000..e4ad5ca2178
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container.idl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * 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.
+ */
+
+// https://w3c.github.io/ServiceWorker/#serviceworkercontainer-interface
+[
+ SecureContext
+] interface ServiceWorkerContainer : EventTarget {
+ readonly attribute ServiceWorker? controller;
+ [CallWith=ScriptState] readonly attribute Promise<ServiceWorkerRegistration> ready;
+
+ [CallWith=ScriptState, ImplementedAs=registerServiceWorker] Promise<ServiceWorkerRegistration> register(USVString url, optional RegistrationOptions options);
+ [CallWith=ScriptState] Promise<ServiceWorkerRegistration> getRegistration(optional USVString documentURL = "");
+ [CallWith=ScriptState] Promise<sequence<ServiceWorkerRegistration>> getRegistrations();
+
+ attribute EventHandler oncontrollerchange;
+ attribute EventHandler onmessage;
+};
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_client.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_client.cc
new file mode 100644
index 00000000000..c1af3c5b759
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_client.cc
@@ -0,0 +1,67 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/service_worker/service_worker_container_client.h"
+
+#include <memory>
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider.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_frame.h"
+#include "third_party/blink/renderer/core/frame/local_frame_client.h"
+#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
+
+namespace blink {
+
+ServiceWorkerContainerClient::ServiceWorkerContainerClient(
+ Document& document,
+ std::unique_ptr<WebServiceWorkerProvider> provider)
+ : Supplement<Document>(document), provider_(std::move(provider)) {}
+
+ServiceWorkerContainerClient::ServiceWorkerContainerClient(
+ WorkerClients& clients,
+ std::unique_ptr<WebServiceWorkerProvider> provider)
+ : Supplement<WorkerClients>(clients), provider_(std::move(provider)) {}
+
+ServiceWorkerContainerClient::~ServiceWorkerContainerClient() = default;
+
+const char ServiceWorkerContainerClient::kSupplementName[] =
+ "ServiceWorkerContainerClient";
+
+ServiceWorkerContainerClient* ServiceWorkerContainerClient::From(
+ ExecutionContext* context) {
+ if (!context)
+ return nullptr;
+ if (context->IsWorkerGlobalScope()) {
+ WorkerClients* worker_clients = ToWorkerGlobalScope(context)->Clients();
+ DCHECK(worker_clients);
+ ServiceWorkerContainerClient* client =
+ Supplement<WorkerClients>::From<ServiceWorkerContainerClient>(
+ worker_clients);
+ DCHECK(client);
+ return client;
+ }
+ Document* document = ToDocument(context);
+ if (!document->GetFrame() || !document->GetFrame()->Client())
+ return nullptr;
+
+ ServiceWorkerContainerClient* client =
+ Supplement<Document>::From<ServiceWorkerContainerClient>(document);
+ if (!client) {
+ client = new ServiceWorkerContainerClient(
+ *document,
+ document->GetFrame()->Client()->CreateServiceWorkerProvider());
+ Supplement<Document>::ProvideTo(*document, client);
+ }
+ return client;
+}
+
+void ProvideServiceWorkerContainerClientToWorker(
+ WorkerClients* clients,
+ std::unique_ptr<WebServiceWorkerProvider> provider) {
+ clients->ProvideSupplement(
+ new ServiceWorkerContainerClient(*clients, std::move(provider)));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_client.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_client.h
new file mode 100644
index 00000000000..639bcb27662
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_client.h
@@ -0,0 +1,62 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_CONTAINER_CLIENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_CONTAINER_CLIENT_H_
+
+#include <memory>
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/workers/worker_clients.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace blink {
+
+class ExecutionContext;
+class WebServiceWorkerProvider;
+
+// This mainly exists to provide access to WebServiceWorkerProvider.
+// Owned by Document (or WorkerClients).
+class MODULES_EXPORT ServiceWorkerContainerClient final
+ : public GarbageCollectedFinalized<ServiceWorkerContainerClient>,
+ public Supplement<Document>,
+ public Supplement<WorkerClients>,
+ public NameClient {
+ USING_GARBAGE_COLLECTED_MIXIN(ServiceWorkerContainerClient);
+ WTF_MAKE_NONCOPYABLE(ServiceWorkerContainerClient);
+
+ public:
+ static const char kSupplementName[];
+
+ ServiceWorkerContainerClient(Document&,
+ std::unique_ptr<WebServiceWorkerProvider>);
+ ServiceWorkerContainerClient(WorkerClients&,
+ std::unique_ptr<WebServiceWorkerProvider>);
+ virtual ~ServiceWorkerContainerClient();
+
+ WebServiceWorkerProvider* Provider() { return provider_.get(); }
+
+ static ServiceWorkerContainerClient* From(ExecutionContext*);
+
+ void Trace(blink::Visitor* visitor) override {
+ Supplement<Document>::Trace(visitor);
+ Supplement<WorkerClients>::Trace(visitor);
+ }
+
+ const char* NameInHeapSnapshot() const override {
+ return "ServiceWorkerContainerClient";
+ }
+
+ private:
+ std::unique_ptr<WebServiceWorkerProvider> provider_;
+};
+
+MODULES_EXPORT void ProvideServiceWorkerContainerClientToWorker(
+ WorkerClients*,
+ std::unique_ptr<WebServiceWorkerProvider>);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_CONTAINER_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc
new file mode 100644
index 00000000000..6099c2337ba
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc
@@ -0,0 +1,404 @@
+
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/service_worker/service_worker_container.h"
+
+#include <memory>
+#include <utility>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_clients_info.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.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/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/page/focus_controller.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+#include "third_party/blink/renderer/modules/service_worker/navigator_service_worker.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_container_client.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+namespace {
+
+// Promise-related test support.
+
+struct StubScriptFunction {
+ public:
+ StubScriptFunction() : call_count_(0) {}
+
+ // The returned ScriptFunction can outlive the StubScriptFunction,
+ // but it should not be called after the StubScriptFunction dies.
+ v8::Local<v8::Function> GetFunction(ScriptState* script_state) {
+ return ScriptFunctionImpl::CreateFunction(script_state, *this);
+ }
+
+ size_t CallCount() { return call_count_; }
+ ScriptValue Arg() { return arg_; }
+
+ private:
+ size_t call_count_;
+ ScriptValue arg_;
+
+ class ScriptFunctionImpl : public ScriptFunction {
+ public:
+ static v8::Local<v8::Function> CreateFunction(ScriptState* script_state,
+ StubScriptFunction& owner) {
+ ScriptFunctionImpl* self = new ScriptFunctionImpl(script_state, owner);
+ return self->BindToV8Function();
+ }
+
+ private:
+ ScriptFunctionImpl(ScriptState* script_state, StubScriptFunction& owner)
+ : ScriptFunction(script_state), owner_(owner) {}
+
+ ScriptValue Call(ScriptValue arg) override {
+ owner_.arg_ = arg;
+ owner_.call_count_++;
+ return ScriptValue();
+ }
+
+ StubScriptFunction& owner_;
+ };
+};
+
+class ScriptValueTest {
+ public:
+ virtual ~ScriptValueTest() = default;
+ virtual void operator()(ScriptValue) const = 0;
+};
+
+// Runs microtasks and expects |promise| to be rejected. Calls
+// |valueTest| with the value passed to |reject|, if any.
+void ExpectRejected(ScriptState* script_state,
+ ScriptPromise& promise,
+ const ScriptValueTest& value_test) {
+ StubScriptFunction resolved, rejected;
+ promise.Then(resolved.GetFunction(script_state),
+ rejected.GetFunction(script_state));
+ v8::MicrotasksScope::PerformCheckpoint(promise.GetIsolate());
+ EXPECT_EQ(0ul, resolved.CallCount());
+ EXPECT_EQ(1ul, rejected.CallCount());
+ if (rejected.CallCount())
+ value_test(rejected.Arg());
+}
+
+// DOM-related test support.
+
+// Matches a ScriptValue and a DOMException with a specific name and message.
+class ExpectDOMException : public ScriptValueTest {
+ public:
+ ExpectDOMException(const String& expected_name,
+ const String& expected_message)
+ : expected_name_(expected_name), expected_message_(expected_message) {}
+
+ ~ExpectDOMException() override = default;
+
+ void operator()(ScriptValue value) const override {
+ DOMException* exception = V8DOMException::ToImplWithTypeCheck(
+ value.GetIsolate(), value.V8Value());
+ EXPECT_TRUE(exception) << "the value should be a DOMException";
+ if (!exception)
+ return;
+ EXPECT_EQ(expected_name_, exception->name());
+ EXPECT_EQ(expected_message_, exception->message());
+ }
+
+ private:
+ String expected_name_;
+ String expected_message_;
+};
+
+// Service Worker-specific tests.
+
+class NotReachedWebServiceWorkerProvider : public WebServiceWorkerProvider {
+ public:
+ ~NotReachedWebServiceWorkerProvider() override = default;
+
+ void RegisterServiceWorker(
+ const WebURL& pattern,
+ const WebURL& script_url,
+ mojom::ServiceWorkerUpdateViaCache update_via_cache,
+ std::unique_ptr<WebServiceWorkerRegistrationCallbacks> callbacks)
+ override {
+ ADD_FAILURE()
+ << "the provider should not be called to register a Service Worker";
+ }
+
+ bool ValidateScopeAndScriptURL(const WebURL& scope,
+ const WebURL& script_url,
+ WebString* error_message) override {
+ return true;
+ }
+};
+
+class ServiceWorkerContainerTest : public PageTestBase {
+ protected:
+ void SetUp() override { PageTestBase::SetUp(IntSize()); }
+
+ ~ServiceWorkerContainerTest() override {
+ V8GCController::CollectAllGarbageForTesting(GetIsolate());
+ }
+
+ ExecutionContext* GetExecutionContext() { return &GetDocument(); }
+ NavigatorServiceWorker* GetNavigatorServiceWorker() {
+ return NavigatorServiceWorker::From(GetDocument());
+ }
+ v8::Isolate* GetIsolate() { return v8::Isolate::GetCurrent(); }
+ ScriptState* GetScriptState() {
+ return ToScriptStateForMainWorld(GetDocument().GetFrame());
+ }
+
+ void Provide(std::unique_ptr<WebServiceWorkerProvider> provider) {
+ Supplement<Document>::ProvideTo(
+ GetDocument(),
+ new ServiceWorkerContainerClient(GetDocument(), std::move(provider)));
+ }
+
+ void SetPageURL(const String& url) {
+ // For URL completion.
+ GetDocument().SetURL(KURL(NullURL(), url));
+
+ // The basis for security checks.
+ GetDocument().SetSecurityOrigin(SecurityOrigin::CreateFromString(url));
+
+ if (url.StartsWith("https://") || url.StartsWith("http://localhost/")) {
+ GetDocument().SetSecureContextStateForTesting(
+ SecureContextState::kSecure);
+ }
+ }
+
+ void TestRegisterRejected(const String& script_url,
+ const String& scope,
+ const ScriptValueTest& value_test) {
+ // When the registration is rejected, a register call must not reach
+ // the provider.
+ Provide(std::make_unique<NotReachedWebServiceWorkerProvider>());
+
+ ServiceWorkerContainer* container = ServiceWorkerContainer::Create(
+ GetExecutionContext(), GetNavigatorServiceWorker());
+ ScriptState::Scope script_scope(GetScriptState());
+ RegistrationOptions options;
+ options.setScope(scope);
+ ScriptPromise promise =
+ container->registerServiceWorker(GetScriptState(), script_url, options);
+ ExpectRejected(GetScriptState(), promise, value_test);
+ }
+
+ void TestGetRegistrationRejected(const String& document_url,
+ const ScriptValueTest& value_test) {
+ Provide(std::make_unique<NotReachedWebServiceWorkerProvider>());
+
+ ServiceWorkerContainer* container = ServiceWorkerContainer::Create(
+ GetExecutionContext(), GetNavigatorServiceWorker());
+ ScriptState::Scope script_scope(GetScriptState());
+ ScriptPromise promise =
+ container->getRegistration(GetScriptState(), document_url);
+ ExpectRejected(GetScriptState(), promise, value_test);
+ }
+};
+
+TEST_F(ServiceWorkerContainerTest, Register_CrossOriginScriptIsRejected) {
+ SetPageURL("https://www.example.com");
+ TestRegisterRejected(
+ "https://www.example.com:8080/", // Differs by port
+ "https://www.example.com/",
+ ExpectDOMException("SecurityError",
+ "Failed to register a ServiceWorker: The origin of "
+ "the provided scriptURL "
+ "('https://www.example.com:8080') does not match the "
+ "current origin ('https://www.example.com')."));
+}
+
+TEST_F(ServiceWorkerContainerTest, Register_CrossOriginScopeIsRejected) {
+ SetPageURL("https://www.example.com");
+ TestRegisterRejected(
+ "https://www.example.com",
+ "wss://www.example.com/", // Differs by protocol
+ ExpectDOMException("SecurityError",
+ "Failed to register a ServiceWorker: The origin of "
+ "the provided scope ('wss://www.example.com') does "
+ "not match the current origin "
+ "('https://www.example.com')."));
+}
+
+TEST_F(ServiceWorkerContainerTest, GetRegistration_CrossOriginURLIsRejected) {
+ SetPageURL("https://www.example.com/");
+ TestGetRegistrationRejected(
+ "https://foo.example.com/", // Differs by host
+ ExpectDOMException("SecurityError",
+ "Failed to get a ServiceWorkerRegistration: The "
+ "origin of the provided documentURL "
+ "('https://foo.example.com') does not match the "
+ "current origin ('https://www.example.com')."));
+}
+
+class StubWebServiceWorkerProvider {
+ public:
+ StubWebServiceWorkerProvider()
+ : register_call_count_(0),
+ get_registration_call_count_(0),
+ update_via_cache_(mojom::ServiceWorkerUpdateViaCache::kImports) {}
+
+ // Creates a WebServiceWorkerProvider. This can outlive the
+ // StubWebServiceWorkerProvider, but |registerServiceWorker| and
+ // other methods must not be called after the
+ // StubWebServiceWorkerProvider dies.
+ std::unique_ptr<WebServiceWorkerProvider> Provider() {
+ return std::make_unique<WebServiceWorkerProviderImpl>(*this);
+ }
+
+ size_t RegisterCallCount() { return register_call_count_; }
+ const WebURL& RegisterScope() { return register_scope_; }
+ const WebURL& RegisterScriptURL() { return register_script_url_; }
+ size_t GetRegistrationCallCount() { return get_registration_call_count_; }
+ const WebURL& GetRegistrationURL() { return get_registration_url_; }
+ mojom::ServiceWorkerUpdateViaCache UpdateViaCache() const {
+ return update_via_cache_;
+ }
+
+ private:
+ class WebServiceWorkerProviderImpl : public WebServiceWorkerProvider {
+ public:
+ WebServiceWorkerProviderImpl(StubWebServiceWorkerProvider& owner)
+ : owner_(owner) {}
+
+ ~WebServiceWorkerProviderImpl() override = default;
+
+ void RegisterServiceWorker(
+ const WebURL& pattern,
+ const WebURL& script_url,
+ mojom::ServiceWorkerUpdateViaCache update_via_cache,
+ std::unique_ptr<WebServiceWorkerRegistrationCallbacks> callbacks)
+ override {
+ owner_.register_call_count_++;
+ owner_.register_scope_ = pattern;
+ owner_.register_script_url_ = script_url;
+ owner_.update_via_cache_ = update_via_cache;
+ registration_callbacks_to_delete_.push_back(std::move(callbacks));
+ }
+
+ void GetRegistration(
+ const WebURL& document_url,
+ std::unique_ptr<WebServiceWorkerGetRegistrationCallbacks> callbacks)
+ override {
+ owner_.get_registration_call_count_++;
+ owner_.get_registration_url_ = document_url;
+ get_registration_callbacks_to_delete_.push_back(std::move(callbacks));
+ }
+
+ bool ValidateScopeAndScriptURL(const WebURL& scope,
+ const WebURL& script_url,
+ WebString* error_message) override {
+ return true;
+ }
+
+ private:
+ StubWebServiceWorkerProvider& owner_;
+ Vector<std::unique_ptr<WebServiceWorkerRegistrationCallbacks>>
+ registration_callbacks_to_delete_;
+ Vector<std::unique_ptr<WebServiceWorkerGetRegistrationCallbacks>>
+ get_registration_callbacks_to_delete_;
+ };
+
+ private:
+ size_t register_call_count_;
+ WebURL register_scope_;
+ WebURL register_script_url_;
+ size_t get_registration_call_count_;
+ WebURL get_registration_url_;
+ mojom::ServiceWorkerUpdateViaCache update_via_cache_;
+};
+
+TEST_F(ServiceWorkerContainerTest,
+ RegisterUnregister_NonHttpsSecureOriginDelegatesToProvider) {
+ SetPageURL("http://localhost/x/index.html");
+
+ StubWebServiceWorkerProvider stub_provider;
+ Provide(stub_provider.Provider());
+
+ ServiceWorkerContainer* container = ServiceWorkerContainer::Create(
+ GetExecutionContext(), GetNavigatorServiceWorker());
+
+ // register
+ {
+ ScriptState::Scope script_scope(GetScriptState());
+ RegistrationOptions options;
+ options.setScope("y/");
+ container->registerServiceWorker(GetScriptState(), "/x/y/worker.js",
+ options);
+
+ EXPECT_EQ(1ul, stub_provider.RegisterCallCount());
+ EXPECT_EQ(WebURL(KURL("http://localhost/x/y/")),
+ stub_provider.RegisterScope());
+ EXPECT_EQ(WebURL(KURL("http://localhost/x/y/worker.js")),
+ stub_provider.RegisterScriptURL());
+ EXPECT_EQ(mojom::ServiceWorkerUpdateViaCache::kImports,
+ stub_provider.UpdateViaCache());
+ }
+}
+
+TEST_F(ServiceWorkerContainerTest,
+ GetRegistration_OmittedDocumentURLDefaultsToPageURL) {
+ SetPageURL("http://localhost/x/index.html");
+
+ StubWebServiceWorkerProvider stub_provider;
+ Provide(stub_provider.Provider());
+
+ ServiceWorkerContainer* container = ServiceWorkerContainer::Create(
+ GetExecutionContext(), GetNavigatorServiceWorker());
+
+ {
+ ScriptState::Scope script_scope(GetScriptState());
+ container->getRegistration(GetScriptState(), "");
+ EXPECT_EQ(1ul, stub_provider.GetRegistrationCallCount());
+ EXPECT_EQ(WebURL(KURL("http://localhost/x/index.html")),
+ stub_provider.GetRegistrationURL());
+ EXPECT_EQ(mojom::ServiceWorkerUpdateViaCache::kImports,
+ stub_provider.UpdateViaCache());
+ }
+}
+
+TEST_F(ServiceWorkerContainerTest,
+ RegisterUnregister_UpdateViaCacheOptionDelegatesToProvider) {
+ SetPageURL("http://localhost/x/index.html");
+
+ StubWebServiceWorkerProvider stub_provider;
+ Provide(stub_provider.Provider());
+
+ ServiceWorkerContainer* container = ServiceWorkerContainer::Create(
+ GetExecutionContext(), GetNavigatorServiceWorker());
+
+ // register
+ {
+ ScriptState::Scope script_scope(GetScriptState());
+ RegistrationOptions options;
+ options.setUpdateViaCache("none");
+ container->registerServiceWorker(GetScriptState(), "/x/y/worker.js",
+ options);
+
+ EXPECT_EQ(1ul, stub_provider.RegisterCallCount());
+ EXPECT_EQ(WebURL(KURL(KURL(), "http://localhost/x/y/")),
+ stub_provider.RegisterScope());
+ EXPECT_EQ(WebURL(KURL(KURL(), "http://localhost/x/y/worker.js")),
+ stub_provider.RegisterScriptURL());
+ EXPECT_EQ(mojom::ServiceWorkerUpdateViaCache::kNone,
+ stub_provider.UpdateViaCache());
+ }
+}
+
+} // namespace
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_content_settings_proxy.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_content_settings_proxy.cc
new file mode 100644
index 00000000000..f545f92c75a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_content_settings_proxy.cc
@@ -0,0 +1,46 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/service_worker/service_worker_content_settings_proxy.h"
+
+#include <memory>
+
+namespace blink {
+
+ServiceWorkerContentSettingsProxy::ServiceWorkerContentSettingsProxy(
+ mojom::blink::WorkerContentSettingsProxyPtrInfo host_info)
+ : host_info_(std::move(host_info)) {}
+
+ServiceWorkerContentSettingsProxy::~ServiceWorkerContentSettingsProxy() =
+ default;
+
+bool ServiceWorkerContentSettingsProxy::RequestFileSystemAccessSync() {
+ NOTREACHED();
+ return false;
+}
+
+bool ServiceWorkerContentSettingsProxy::AllowIndexedDB(
+ const blink::WebString& name,
+ const blink::WebSecurityOrigin&) {
+ bool result = false;
+ GetService()->AllowIndexedDB(name, &result);
+ return result;
+}
+
+// Use ThreadSpecific to ensure that |content_settings_instance_host| is
+// destructed on worker thread.
+// Each worker has a dedicated thread so this is safe.
+mojom::blink::WorkerContentSettingsProxyPtr&
+ServiceWorkerContentSettingsProxy::GetService() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ ThreadSpecific<mojom::blink::WorkerContentSettingsProxyPtr>,
+ content_settings_instance_host, ());
+ if (!content_settings_instance_host.IsSet()) {
+ DCHECK(host_info_.is_valid());
+ content_settings_instance_host->Bind(std::move(host_info_));
+ }
+ return *content_settings_instance_host;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_content_settings_proxy.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_content_settings_proxy.h
new file mode 100644
index 00000000000..188a62ba895
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_content_settings_proxy.h
@@ -0,0 +1,48 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_CONTENT_SETTINGS_PROXY_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_CONTENT_SETTINGS_PROXY_H_
+
+#include "third_party/blink/public/platform/web_content_settings_client.h"
+#include "third_party/blink/public/platform/web_security_origin.h"
+#include "third_party/blink/public/web/worker_content_settings_proxy.mojom-blink.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+
+namespace blink {
+
+// Provides the content settings information from browser process.
+// This proxy is created and destroyed on the main thread and used on the
+// worker thread.
+class ServiceWorkerContentSettingsProxy final
+ : public blink::WebContentSettingsClient {
+ public:
+ explicit ServiceWorkerContentSettingsProxy(
+ mojom::blink::WorkerContentSettingsProxyPtrInfo host_info);
+ ~ServiceWorkerContentSettingsProxy() override;
+
+ void SetSecurityOrigin(scoped_refptr<const blink::SecurityOrigin>);
+
+ // WebContentSettingsClient overrides.
+ // Asks the browser process about the settings.
+ // Blocks until the response arrives.
+ bool RequestFileSystemAccessSync() override;
+ bool AllowIndexedDB(const WebString& name, const WebSecurityOrigin&) override;
+
+ private:
+ // To ensure the returned pointer is destructed on the same thread
+ // that it was constructed on, this uses ThreadSpecific.
+ mojom::blink::WorkerContentSettingsProxyPtr& GetService();
+
+ // This is set on the main thread at the ctor,
+ // and moved to thread local storage on the worker thread
+ // when GetService() is called for the first time.
+ mojom::blink::WorkerContentSettingsProxyPtrInfo host_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContentSettingsProxy);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_CONTENT_SETTINGS_PROXY_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_error.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_error.cc
new file mode 100644
index 00000000000..3502f8a7dc3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_error.cc
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * 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/modules/service_worker/service_worker_error.h"
+
+#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
+
+using blink::WebServiceWorkerError;
+
+namespace blink {
+
+namespace {
+
+struct ExceptionParams {
+ ExceptionParams(DOMExceptionCode code,
+ const String& default_message = String(),
+ const String& message = String())
+ : code(code), message(message.IsEmpty() ? default_message : message) {}
+
+ DOMExceptionCode code;
+ String message;
+};
+
+ExceptionParams GetExceptionParams(const WebServiceWorkerError& web_error) {
+ switch (web_error.error_type) {
+ case mojom::blink::ServiceWorkerErrorType::kAbort:
+ return ExceptionParams(DOMExceptionCode::kAbortError,
+ "The Service Worker operation was aborted.",
+ web_error.message);
+ case mojom::blink::ServiceWorkerErrorType::kActivate:
+ // Not currently returned as a promise rejection.
+ // TODO: Introduce new ActivateError type to ExceptionCodes?
+ return ExceptionParams(DOMExceptionCode::kAbortError,
+ "The Service Worker activation failed.",
+ web_error.message);
+ case mojom::blink::ServiceWorkerErrorType::kDisabled:
+ return ExceptionParams(DOMExceptionCode::kNotSupportedError,
+ "Service Worker support is disabled.",
+ web_error.message);
+ case mojom::blink::ServiceWorkerErrorType::kInstall:
+ // TODO: Introduce new InstallError type to ExceptionCodes?
+ return ExceptionParams(DOMExceptionCode::kAbortError,
+ "The Service Worker installation failed.",
+ web_error.message);
+ case mojom::blink::ServiceWorkerErrorType::kScriptEvaluateFailed:
+ return ExceptionParams(DOMExceptionCode::kAbortError,
+ "The Service Worker script failed to evaluate.",
+ web_error.message);
+ case mojom::blink::ServiceWorkerErrorType::kNavigation:
+ // ErrorTypeNavigation should have bailed out before calling this.
+ NOTREACHED();
+ return ExceptionParams(DOMExceptionCode::kUnknownError);
+ case mojom::blink::ServiceWorkerErrorType::kNetwork:
+ return ExceptionParams(DOMExceptionCode::kNetworkError,
+ "The Service Worker failed by network.",
+ web_error.message);
+ case mojom::blink::ServiceWorkerErrorType::kNotFound:
+ return ExceptionParams(
+ DOMExceptionCode::kNotFoundError,
+ "The specified Service Worker resource was not found.",
+ web_error.message);
+ case mojom::blink::ServiceWorkerErrorType::kSecurity:
+ return ExceptionParams(
+ DOMExceptionCode::kSecurityError,
+ "The Service Worker security policy prevented an action.",
+ web_error.message);
+ case mojom::blink::ServiceWorkerErrorType::kState:
+ return ExceptionParams(DOMExceptionCode::kInvalidStateError,
+ "The Service Worker state was not valid.",
+ web_error.message);
+ case mojom::blink::ServiceWorkerErrorType::kTimeout:
+ return ExceptionParams(DOMExceptionCode::kAbortError,
+ "The Service Worker operation timed out.",
+ web_error.message);
+ case mojom::blink::ServiceWorkerErrorType::kUnknown:
+ return ExceptionParams(DOMExceptionCode::kUnknownError,
+ "An unknown error occurred within Service Worker.",
+ web_error.message);
+ case mojom::blink::ServiceWorkerErrorType::kNone:
+ case mojom::blink::ServiceWorkerErrorType::kType:
+ // ErrorTypeType should have been handled before reaching this point.
+ NOTREACHED();
+ return ExceptionParams(DOMExceptionCode::kUnknownError);
+ }
+ NOTREACHED();
+ return ExceptionParams(DOMExceptionCode::kUnknownError);
+}
+
+} // namespace
+
+// static
+DOMException* ServiceWorkerError::Take(ScriptPromiseResolver*,
+ const WebServiceWorkerError& web_error) {
+ ExceptionParams params = GetExceptionParams(web_error);
+ return DOMException::Create(params.code, params.message);
+}
+
+// static
+v8::Local<v8::Value> ServiceWorkerErrorForUpdate::Take(
+ ScriptPromiseResolver* resolver,
+ const WebServiceWorkerError& web_error) {
+ ScriptState* script_state = resolver->GetScriptState();
+ switch (web_error.error_type) {
+ case mojom::blink::ServiceWorkerErrorType::kNetwork:
+ case mojom::blink::ServiceWorkerErrorType::kNotFound:
+ case mojom::blink::ServiceWorkerErrorType::kScriptEvaluateFailed:
+ // According to the spec, these errors during update should result in
+ // a TypeError.
+ return V8ThrowException::CreateTypeError(
+ script_state->GetIsolate(), GetExceptionParams(web_error).message);
+ case mojom::blink::ServiceWorkerErrorType::kType:
+ return V8ThrowException::CreateTypeError(script_state->GetIsolate(),
+ web_error.message);
+ default:
+ return ToV8(ServiceWorkerError::Take(resolver, web_error),
+ script_state->GetContext()->Global(),
+ script_state->GetIsolate());
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_error.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_error.h
new file mode 100644
index 00000000000..f6d34c61eb7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_error.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * 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_MODULES_SERVICE_WORKER_SERVICE_WORKER_ERROR_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_ERROR_H_
+
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+class DOMException;
+class ScriptPromiseResolver;
+
+class ServiceWorkerError {
+ STATIC_ONLY(ServiceWorkerError);
+
+ public:
+ // For CallbackPromiseAdapter
+ using WebType = const WebServiceWorkerError&;
+ static DOMException* Take(ScriptPromiseResolver*,
+ const WebServiceWorkerError& web_error);
+};
+
+class ServiceWorkerErrorForUpdate : public ServiceWorkerError {
+ STATIC_ONLY(ServiceWorkerErrorForUpdate);
+
+ public:
+ // For CallbackPromiseAdapter
+ static v8::Local<v8::Value> Take(ScriptPromiseResolver* resolver,
+ const WebServiceWorkerError& web_error);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_ERROR_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
new file mode 100644
index 00000000000..81089270260
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
@@ -0,0 +1,414 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * 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/modules/service_worker/service_worker_global_scope.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/memory/ptr_util.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/bindings/core/v8/source_location.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/fetch/global_fetch.h"
+#include "third_party/blink/renderer/core/frame/use_counter.h"
+#include "third_party/blink/renderer/core/inspector/console_message.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"
+#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
+#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
+#include "third_party/blink/renderer/core/workers/installed_scripts_manager.h"
+#include "third_party/blink/renderer/core/workers/worker_clients.h"
+#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
+#include "third_party/blink/renderer/modules/event_target_modules.h"
+#include "third_party/blink/renderer/modules/service_worker/respond_with_observer.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_clients.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_thread.h"
+#include "third_party/blink/renderer/modules/service_worker/wait_until_observer.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/histogram.h"
+#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
+#include "third_party/blink/renderer/platform/network/content_security_policy_response_headers.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/time.h"
+
+namespace blink {
+
+ServiceWorkerGlobalScope* ServiceWorkerGlobalScope::Create(
+ ServiceWorkerThread* thread,
+ std::unique_ptr<GlobalScopeCreationParams> creation_params,
+ mojom::blink::CacheStoragePtrInfo cache_storage_info,
+ base::TimeTicks time_origin) {
+ // If the script is being loaded via script streaming, the script is not yet
+ // loaded.
+ if (thread->GetInstalledScriptsManager() &&
+ thread->GetInstalledScriptsManager()->IsScriptInstalled(
+ creation_params->script_url)) {
+ // CSP headers, referrer policy, and origin trial tokens will be provided by
+ // the InstalledScriptsManager in EvaluateClassicScript().
+ DCHECK(creation_params->content_security_policy_parsed_headers.IsEmpty());
+ DCHECK_EQ(kReferrerPolicyDefault, creation_params->referrer_policy);
+ DCHECK(creation_params->origin_trial_tokens->IsEmpty());
+ }
+ return new ServiceWorkerGlobalScope(std::move(creation_params), thread,
+ std::move(cache_storage_info),
+ time_origin);
+}
+
+ServiceWorkerGlobalScope::ServiceWorkerGlobalScope(
+ std::unique_ptr<GlobalScopeCreationParams> creation_params,
+ ServiceWorkerThread* thread,
+ mojom::blink::CacheStoragePtrInfo cache_storage_info,
+ base::TimeTicks time_origin)
+ : WorkerGlobalScope(std::move(creation_params), thread, time_origin),
+ cache_storage_info_(std::move(cache_storage_info)) {}
+
+ServiceWorkerGlobalScope::~ServiceWorkerGlobalScope() = default;
+
+void ServiceWorkerGlobalScope::ReadyToEvaluateScript() {
+ DCHECK(!evaluate_script_ready_);
+ evaluate_script_ready_ = true;
+ if (evaluate_script_)
+ std::move(evaluate_script_).Run();
+}
+
+void ServiceWorkerGlobalScope::EvaluateClassicScript(
+ const KURL& script_url,
+ String source_code,
+ std::unique_ptr<Vector<char>> cached_meta_data) {
+ DCHECK(IsContextThread());
+
+ if (!evaluate_script_ready_) {
+ evaluate_script_ =
+ WTF::Bind(&ServiceWorkerGlobalScope::EvaluateClassicScript,
+ WrapWeakPersistent(this), script_url, std::move(source_code),
+ std::move(cached_meta_data));
+ return;
+ }
+
+ // Receive the main script via script streaming if needed.
+ InstalledScriptsManager* installed_scripts_manager =
+ GetThread()->GetInstalledScriptsManager();
+ if (installed_scripts_manager &&
+ installed_scripts_manager->IsScriptInstalled(script_url)) {
+ // GetScriptData blocks until the script is received from the browser.
+ InstalledScriptsManager::ScriptData script_data;
+ InstalledScriptsManager::ScriptStatus status =
+ installed_scripts_manager->GetScriptData(script_url, &script_data);
+ if (status == InstalledScriptsManager::ScriptStatus::kFailed) {
+ // This eventually terminates the worker thread.
+ ReportingProxy().DidEvaluateClassicScript(false);
+ return;
+ }
+
+ DCHECK(source_code.IsEmpty());
+ DCHECK(!cached_meta_data);
+ source_code = script_data.TakeSourceText();
+ cached_meta_data = script_data.TakeMetaData();
+
+ base::Optional<ContentSecurityPolicyResponseHeaders>
+ content_security_policy_raw_headers =
+ script_data.GetContentSecurityPolicyResponseHeaders();
+ ApplyContentSecurityPolicyFromHeaders(
+ content_security_policy_raw_headers.value());
+
+ String referrer_policy = script_data.GetReferrerPolicy();
+ if (!referrer_policy.IsNull())
+ ParseAndSetReferrerPolicy(referrer_policy);
+
+ std::unique_ptr<Vector<String>> origin_trial_tokens =
+ script_data.CreateOriginTrialTokens();
+ OriginTrialContext::AddTokens(this, origin_trial_tokens.get());
+
+ // This may block until CSP and referrer policy are set on the main
+ // thread.
+ ReportingProxy().DidLoadInstalledScript(
+ content_security_policy_raw_headers.value(), referrer_policy);
+ }
+
+ WorkerGlobalScope::EvaluateClassicScript(script_url, source_code,
+ std::move(cached_meta_data));
+}
+
+void ServiceWorkerGlobalScope::ImportModuleScript(
+ const KURL& module_url_record,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
+ network::mojom::FetchCredentialsMode credentials_mode) {
+ // TODO(nhiroki): Implement module loading for service workers.
+ // (https://crbug.com/824647)
+ NOTREACHED();
+}
+
+void ServiceWorkerGlobalScope::CountWorkerScript(size_t script_size,
+ size_t cached_metadata_size) {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ CustomCountHistogram, script_size_histogram,
+ ("ServiceWorker.ScriptSize", 1000, 5000000, 50));
+ script_size_histogram.Count(script_size);
+
+ if (cached_metadata_size) {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ CustomCountHistogram, script_cached_metadata_size_histogram,
+ ("ServiceWorker.ScriptCachedMetadataSize", 1000, 50000000, 50));
+ script_cached_metadata_size_histogram.Count(cached_metadata_size);
+ }
+
+ RecordScriptSize(script_size, cached_metadata_size);
+}
+
+void ServiceWorkerGlobalScope::CountImportedScript(
+ size_t script_size,
+ size_t cached_metadata_size) {
+ RecordScriptSize(script_size, cached_metadata_size);
+}
+
+void ServiceWorkerGlobalScope::RecordScriptSize(size_t script_size,
+ size_t cached_metadata_size) {
+ ++script_count_;
+ script_total_size_ += script_size;
+ script_cached_metadata_total_size_ += cached_metadata_size;
+}
+
+void ServiceWorkerGlobalScope::DidEvaluateClassicScript() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, script_count_histogram,
+ ("ServiceWorker.ScriptCount", 1, 1000, 50));
+ script_count_histogram.Count(script_count_);
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ CustomCountHistogram, script_total_size_histogram,
+ ("ServiceWorker.ScriptTotalSize", 1000, 5000000, 50));
+ script_total_size_histogram.Count(script_total_size_);
+ if (script_cached_metadata_total_size_) {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ CustomCountHistogram, cached_metadata_histogram,
+ ("ServiceWorker.ScriptCachedMetadataTotalSize", 1000, 50000000, 50));
+ cached_metadata_histogram.Count(script_cached_metadata_total_size_);
+ }
+ did_evaluate_script_ = true;
+}
+
+ScriptPromise ServiceWorkerGlobalScope::fetch(ScriptState* script_state,
+ const RequestInfo& input,
+ const RequestInit& init,
+ ExceptionState& exception_state) {
+ return GlobalFetch::fetch(script_state, *this, input, init, exception_state);
+}
+
+ServiceWorkerClients* ServiceWorkerGlobalScope::clients() {
+ if (!clients_)
+ clients_ = ServiceWorkerClients::Create();
+ return clients_;
+}
+
+ServiceWorkerRegistration* ServiceWorkerGlobalScope::registration() {
+ return registration_;
+}
+
+ScriptPromise ServiceWorkerGlobalScope::skipWaiting(ScriptState* script_state) {
+ ExecutionContext* execution_context = ExecutionContext::From(script_state);
+ // FIXME: short-term fix, see details at:
+ // https://codereview.chromium.org/535193002/.
+ if (!execution_context)
+ return ScriptPromise();
+
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ ServiceWorkerGlobalScopeClient::From(execution_context)
+ ->SkipWaiting(
+ std::make_unique<CallbackPromiseAdapter<void, void>>(resolver));
+ return promise;
+}
+
+void ServiceWorkerGlobalScope::SetRegistration(
+ std::unique_ptr<WebServiceWorkerRegistration::Handle> handle) {
+ if (!GetExecutionContext())
+ return;
+ registration_ = ServiceWorkerRegistration::GetOrCreate(
+ GetExecutionContext(), base::WrapUnique(handle.release()));
+}
+
+bool ServiceWorkerGlobalScope::AddEventListenerInternal(
+ const AtomicString& event_type,
+ EventListener* listener,
+ const AddEventListenerOptionsResolved& options) {
+ if (did_evaluate_script_) {
+ String message = String::Format(
+ "Event handler of '%s' event must be added on the initial evaluation "
+ "of worker script.",
+ event_type.Utf8().data());
+ AddConsoleMessage(ConsoleMessage::Create(kJSMessageSource,
+ kWarningMessageLevel, message));
+ }
+ return WorkerGlobalScope::AddEventListenerInternal(event_type, listener,
+ options);
+}
+
+const AtomicString& ServiceWorkerGlobalScope::InterfaceName() const {
+ return EventTargetNames::ServiceWorkerGlobalScope;
+}
+
+void ServiceWorkerGlobalScope::DispatchExtendableEvent(
+ Event* event,
+ WaitUntilObserver* observer) {
+ observer->WillDispatchEvent();
+ DispatchEvent(event);
+
+ // Check if the worker thread is forcibly terminated during the event
+ // because of timeout etc.
+ observer->DidDispatchEvent(GetThread()->IsForciblyTerminated());
+}
+
+void ServiceWorkerGlobalScope::DispatchExtendableEventWithRespondWith(
+ Event* event,
+ WaitUntilObserver* wait_until_observer,
+ RespondWithObserver* respond_with_observer) {
+ wait_until_observer->WillDispatchEvent();
+ respond_with_observer->WillDispatchEvent();
+ DispatchEventResult dispatch_result = DispatchEvent(event);
+ respond_with_observer->DidDispatchEvent(dispatch_result);
+ // false is okay because waitUntil() for events with respondWith() doesn't
+ // care about the promise rejection or an uncaught runtime script error.
+ wait_until_observer->DidDispatchEvent(false /* event_dispatch_failed */);
+}
+
+void ServiceWorkerGlobalScope::Trace(blink::Visitor* visitor) {
+ visitor->Trace(clients_);
+ visitor->Trace(registration_);
+ WorkerGlobalScope::Trace(visitor);
+}
+
+void ServiceWorkerGlobalScope::importScripts(const Vector<String>& urls,
+ ExceptionState& exception_state) {
+ InstalledScriptsManager* installed_scripts_manager =
+ GetThread()->GetInstalledScriptsManager();
+ for (auto& url : urls) {
+ KURL completed_url = CompleteURL(url);
+ // Counts the usage of importScripts() of new scripts after installation
+ // because we want to deprecate such usage (https://crbug.com/719052).
+ // This will undercount because installed scripts manager is only provided
+ // to installed service workers on startup, but this gives us an idea of
+ // the usage.
+ if (installed_scripts_manager &&
+ !installed_scripts_manager->IsScriptInstalled(completed_url)) {
+ DCHECK(installed_scripts_manager->IsScriptInstalled(Url()));
+ CountFeature(WebFeature::kServiceWorkerImportScriptNotInstalled);
+ }
+ // Bust the MemoryCache to ensure script requests reach the browser-side
+ // and get added to and retrieved from the ServiceWorker's script cache.
+ // FIXME: Revisit in light of the solution to crbug/388375.
+ RemoveURLFromMemoryCache(completed_url);
+ }
+ WorkerGlobalScope::importScripts(urls, exception_state);
+}
+
+SingleCachedMetadataHandler*
+ServiceWorkerGlobalScope::CreateWorkerScriptCachedMetadataHandler(
+ const KURL& script_url,
+ const Vector<char>* meta_data) {
+ return ServiceWorkerScriptCachedMetadataHandler::Create(this, script_url,
+ meta_data);
+}
+
+void ServiceWorkerGlobalScope::ExceptionThrown(ErrorEvent* event) {
+ WorkerGlobalScope::ExceptionThrown(event);
+ if (WorkerThreadDebugger* debugger =
+ WorkerThreadDebugger::From(GetThread()->GetIsolate()))
+ debugger->ExceptionThrown(GetThread(), event);
+}
+
+void ServiceWorkerGlobalScope::CountCacheStorageInstalledScript(
+ uint64_t script_size,
+ uint64_t script_metadata_size) {
+ ++cache_storage_installed_script_count_;
+ cache_storage_installed_script_total_size_ += script_size;
+ cache_storage_installed_script_metadata_total_size_ += script_metadata_size;
+
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ CustomCountHistogram, script_size_histogram,
+ ("ServiceWorker.CacheStorageInstalledScript.ScriptSize", 1000, 5000000,
+ 50));
+ script_size_histogram.Count(script_size);
+
+ if (script_metadata_size) {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ CustomCountHistogram, script_metadata_size_histogram,
+ ("ServiceWorker.CacheStorageInstalledScript.CachedMetadataSize", 1000,
+ 50000000, 50));
+ script_metadata_size_histogram.Count(script_metadata_size);
+ }
+}
+
+void ServiceWorkerGlobalScope::SetIsInstalling(bool is_installing) {
+ is_installing_ = is_installing;
+ if (is_installing)
+ return;
+
+ // Installing phase is finished; record the stats for the scripts that are
+ // stored in Cache storage during installation.
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ CustomCountHistogram, cache_storage_installed_script_count_histogram,
+ ("ServiceWorker.CacheStorageInstalledScript.Count", 1, 1000, 50));
+ cache_storage_installed_script_count_histogram.Count(
+ cache_storage_installed_script_count_);
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ CustomCountHistogram, cache_storage_installed_script_total_size_histogram,
+ ("ServiceWorker.CacheStorageInstalledScript.ScriptTotalSize", 1000,
+ 50000000, 50));
+ cache_storage_installed_script_total_size_histogram.Count(
+ cache_storage_installed_script_total_size_);
+
+ if (cache_storage_installed_script_metadata_total_size_) {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ CustomCountHistogram,
+ cache_storage_installed_script_metadata_total_size_histogram,
+ ("ServiceWorker.CacheStorageInstalledScript.CachedMetadataTotalSize",
+ 1000, 50000000, 50));
+ cache_storage_installed_script_metadata_total_size_histogram.Count(
+ cache_storage_installed_script_metadata_total_size_);
+ }
+}
+
+mojom::blink::CacheStoragePtrInfo ServiceWorkerGlobalScope::TakeCacheStorage() {
+ return std::move(cache_storage_info_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h
new file mode 100644
index 00000000000..f00b65661e5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * 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_MODULES_SERVICE_WORKER_SERVICE_WORKER_GLOBAL_SCOPE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_GLOBAL_SCOPE_H_
+
+#include <memory>
+#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom-blink.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_registration.h"
+#include "third_party/blink/renderer/bindings/core/v8/request_or_usv_string.h"
+#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace blink {
+
+class RespondWithObserver;
+class RequestInit;
+class ScriptPromise;
+class ScriptState;
+class ServiceWorkerClients;
+class ServiceWorkerRegistration;
+class ServiceWorkerThread;
+class WaitUntilObserver;
+struct GlobalScopeCreationParams;
+
+typedef RequestOrUSVString RequestInfo;
+
+class MODULES_EXPORT ServiceWorkerGlobalScope final : public WorkerGlobalScope {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static ServiceWorkerGlobalScope* Create(
+ ServiceWorkerThread*,
+ std::unique_ptr<GlobalScopeCreationParams>,
+ mojom::blink::CacheStoragePtrInfo,
+ base::TimeTicks time_origin);
+
+ ~ServiceWorkerGlobalScope() override;
+ bool IsServiceWorkerGlobalScope() const override { return true; }
+
+ // Implements WorkerGlobalScope.
+ void EvaluateClassicScript(
+ const KURL& script_url,
+ String source_code,
+ std::unique_ptr<Vector<char>> cached_meta_data) override;
+ void ImportModuleScript(
+ const KURL& module_url_record,
+ FetchClientSettingsObjectSnapshot* outside_settings_object,
+ network::mojom::FetchCredentialsMode) override;
+
+ // Counts an evaluated script and its size. Called for the main worker script.
+ void CountWorkerScript(size_t script_size, size_t cached_metadata_size);
+
+ // Counts an evaluated script and its size. Called for each of imported
+ // scripts.
+ void CountImportedScript(size_t script_size, size_t cached_metadata_size);
+
+ // Called when the main worker script is evaluated.
+ void DidEvaluateClassicScript();
+
+ // ServiceWorkerGlobalScope.idl
+ ServiceWorkerClients* clients();
+ ServiceWorkerRegistration* registration();
+
+ ScriptPromise fetch(ScriptState*,
+ const RequestInfo&,
+ const RequestInit&,
+ ExceptionState&);
+
+ ScriptPromise skipWaiting(ScriptState*);
+
+ void SetRegistration(std::unique_ptr<WebServiceWorkerRegistration::Handle>);
+
+ // EventTarget
+ const AtomicString& InterfaceName() const override;
+
+ void DispatchExtendableEvent(Event*, WaitUntilObserver*);
+
+ // For ExtendableEvents that also have a respondWith() function.
+ void DispatchExtendableEventWithRespondWith(Event*,
+ WaitUntilObserver*,
+ RespondWithObserver*);
+
+ bool IsInstalling() const { return is_installing_; }
+ void SetIsInstalling(bool is_installing);
+
+ // Script evaluation does not start until this function is called.
+ void ReadyToEvaluateScript();
+
+ void CountCacheStorageInstalledScript(uint64_t script_size,
+ uint64_t script_metadata_size);
+
+ mojom::blink::CacheStoragePtrInfo TakeCacheStorage();
+
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(install);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(activate);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(fetch);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(message);
+
+ void Trace(blink::Visitor*) override;
+
+ protected:
+ // EventTarget
+ bool AddEventListenerInternal(
+ const AtomicString& event_type,
+ EventListener*,
+ const AddEventListenerOptionsResolved&) override;
+
+ private:
+ ServiceWorkerGlobalScope(std::unique_ptr<GlobalScopeCreationParams>,
+ ServiceWorkerThread*,
+ mojom::blink::CacheStoragePtrInfo,
+ base::TimeTicks time_origin);
+ void importScripts(const Vector<String>& urls, ExceptionState&) override;
+ SingleCachedMetadataHandler* CreateWorkerScriptCachedMetadataHandler(
+ const KURL& script_url,
+ const Vector<char>* meta_data) override;
+ void ExceptionThrown(ErrorEvent*) override;
+
+ // Records the |script_size| and |cached_metadata_size| for UMA to measure the
+ // number of scripts and the total bytes of scripts.
+ void RecordScriptSize(size_t script_size, size_t cached_metadata_size);
+
+ Member<ServiceWorkerClients> clients_;
+ Member<ServiceWorkerRegistration> registration_;
+ bool did_evaluate_script_ = false;
+ size_t script_count_ = 0;
+ size_t script_total_size_ = 0;
+ size_t script_cached_metadata_total_size_ = 0;
+ bool is_installing_ = false;
+ size_t cache_storage_installed_script_count_ = 0;
+ uint64_t cache_storage_installed_script_total_size_ = 0;
+ uint64_t cache_storage_installed_script_metadata_total_size_ = 0;
+
+ bool evaluate_script_ready_ = false;
+ base::OnceClosure evaluate_script_;
+
+ // May be provided in the constructor as an optimization so InterfaceProvider
+ // doesn't need to be used. Taken at the initial call to
+ // ServiceWorkerGlobalScope#caches.
+ mojom::blink::CacheStoragePtrInfo cache_storage_info_;
+};
+
+DEFINE_TYPE_CASTS(ServiceWorkerGlobalScope,
+ ExecutionContext,
+ context,
+ context->IsServiceWorkerGlobalScope(),
+ context.IsServiceWorkerGlobalScope());
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_GLOBAL_SCOPE_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.idl b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.idl
new file mode 100644
index 00000000000..db68a46873b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.idl
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * 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.
+ */
+
+// https://w3c.github.io/ServiceWorker/#serviceworkerglobalscope-interface
+
+[
+ Exposed=ServiceWorker,
+ Global=(Worker,ServiceWorker)
+] interface ServiceWorkerGlobalScope : WorkerGlobalScope {
+
+ readonly attribute Clients clients;
+ readonly attribute ServiceWorkerRegistration registration;
+
+ [CallWith=ScriptState, RaisesException] Promise<Response> fetch(RequestInfo input, optional RequestInit init);
+
+ [CallWith=ScriptState] Promise<void> skipWaiting();
+
+ attribute EventHandler onactivate;
+ attribute EventHandler onfetch;
+ attribute EventHandler oninstall;
+ attribute EventHandler onmessage;
+};
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.cc
new file mode 100644
index 00000000000..68b29db3412
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.cc
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2014 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/modules/service_worker/service_worker_global_scope_client.h"
+
+#include <memory>
+#include <utility>
+#include "third_party/blink/public/platform/modules/payments/web_payment_handler_response.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_response.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/fetch/response.h"
+#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
+
+namespace blink {
+
+ServiceWorkerGlobalScopeClient::ServiceWorkerGlobalScopeClient(
+ WebServiceWorkerContextClient& client)
+ : client_(client) {}
+
+void ServiceWorkerGlobalScopeClient::GetClient(
+ const WebString& id,
+ std::unique_ptr<WebServiceWorkerClientCallbacks> callbacks) {
+ client_.GetClient(id, std::move(callbacks));
+}
+
+void ServiceWorkerGlobalScopeClient::GetClients(
+ const WebServiceWorkerClientQueryOptions& options,
+ std::unique_ptr<WebServiceWorkerClientsCallbacks> callbacks) {
+ client_.GetClients(options, std::move(callbacks));
+}
+
+void ServiceWorkerGlobalScopeClient::OpenWindowForClients(
+ const WebURL& url,
+ std::unique_ptr<WebServiceWorkerClientCallbacks> callbacks) {
+ client_.OpenNewTab(url, std::move(callbacks));
+}
+
+void ServiceWorkerGlobalScopeClient::OpenWindowForPaymentHandler(
+ const WebURL& url,
+ std::unique_ptr<WebServiceWorkerClientCallbacks> callbacks) {
+ client_.OpenPaymentHandlerWindow(url, std::move(callbacks));
+}
+
+void ServiceWorkerGlobalScopeClient::SetCachedMetadata(const WebURL& url,
+ const char* data,
+ size_t size) {
+ client_.SetCachedMetadata(url, data, size);
+}
+
+void ServiceWorkerGlobalScopeClient::ClearCachedMetadata(const WebURL& url) {
+ client_.ClearCachedMetadata(url);
+}
+
+void ServiceWorkerGlobalScopeClient::DidHandleActivateEvent(
+ int event_id,
+ mojom::ServiceWorkerEventStatus status,
+ double event_dispatch_time) {
+ client_.DidHandleActivateEvent(event_id, status, event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::DidHandleBackgroundFetchAbortEvent(
+ int event_id,
+ mojom::ServiceWorkerEventStatus status,
+ double event_dispatch_time) {
+ client_.DidHandleBackgroundFetchAbortEvent(event_id, status,
+ event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::DidHandleBackgroundFetchClickEvent(
+ int event_id,
+ mojom::ServiceWorkerEventStatus status,
+ double event_dispatch_time) {
+ client_.DidHandleBackgroundFetchClickEvent(event_id, status,
+ event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::DidHandleBackgroundFetchFailEvent(
+ int event_id,
+ mojom::ServiceWorkerEventStatus status,
+ double event_dispatch_time) {
+ client_.DidHandleBackgroundFetchFailEvent(event_id, status,
+ event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::DidHandleBackgroundFetchedEvent(
+ int event_id,
+ mojom::ServiceWorkerEventStatus status,
+ double event_dispatch_time) {
+ client_.DidHandleBackgroundFetchedEvent(event_id, status,
+ event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::DidHandleCookieChangeEvent(
+ int event_id,
+ mojom::ServiceWorkerEventStatus status,
+ double event_dispatch_time) {
+ client_.DidHandleCookieChangeEvent(event_id, status, event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::DidHandleExtendableMessageEvent(
+ int event_id,
+ mojom::ServiceWorkerEventStatus status,
+ double event_dispatch_time) {
+ client_.DidHandleExtendableMessageEvent(event_id, status,
+ event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::RespondToFetchEventWithNoResponse(
+ int fetch_event_id,
+ double event_dispatch_time) {
+ client_.RespondToFetchEventWithNoResponse(fetch_event_id,
+ event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::RespondToFetchEvent(
+ int fetch_event_id,
+ const WebServiceWorkerResponse& response,
+ double event_dispatch_time) {
+ client_.RespondToFetchEvent(fetch_event_id, response, event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::RespondToFetchEventWithResponseStream(
+ int fetch_event_id,
+ const WebServiceWorkerResponse& response,
+ WebServiceWorkerStreamHandle* stream_handle,
+ double event_dispatch_time) {
+ client_.RespondToFetchEventWithResponseStream(
+ fetch_event_id, response, stream_handle, event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::RespondToAbortPaymentEvent(
+ int event_id,
+ bool abort_payment,
+ double event_dispatch_time) {
+ client_.RespondToAbortPaymentEvent(event_id, abort_payment,
+ event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::RespondToCanMakePaymentEvent(
+ int event_id,
+ bool response,
+ double event_dispatch_time) {
+ client_.RespondToCanMakePaymentEvent(event_id, response, event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::RespondToPaymentRequestEvent(
+ int event_id,
+ const WebPaymentHandlerResponse& response,
+ double event_dispatch_time) {
+ client_.RespondToPaymentRequestEvent(event_id, response, event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::DidHandleFetchEvent(
+ int fetch_event_id,
+ mojom::ServiceWorkerEventStatus status,
+ double event_dispatch_time) {
+ client_.DidHandleFetchEvent(fetch_event_id, status, event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::DidHandleInstallEvent(
+ int install_event_id,
+ mojom::ServiceWorkerEventStatus status,
+ double event_dispatch_time) {
+ client_.DidHandleInstallEvent(install_event_id, status, event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::DidHandleNotificationClickEvent(
+ int event_id,
+ mojom::ServiceWorkerEventStatus status,
+ double event_dispatch_time) {
+ client_.DidHandleNotificationClickEvent(event_id, status,
+ event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::DidHandleNotificationCloseEvent(
+ int event_id,
+ mojom::ServiceWorkerEventStatus status,
+ double event_dispatch_time) {
+ client_.DidHandleNotificationCloseEvent(event_id, status,
+ event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::DidHandlePushEvent(
+ int push_event_id,
+ mojom::ServiceWorkerEventStatus status,
+ double event_dispatch_time) {
+ client_.DidHandlePushEvent(push_event_id, status, event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::DidHandleSyncEvent(
+ int sync_event_id,
+ mojom::ServiceWorkerEventStatus status,
+ double event_dispatch_time) {
+ client_.DidHandleSyncEvent(sync_event_id, status, event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::DidHandleAbortPaymentEvent(
+ int abort_payment_event_id,
+ mojom::ServiceWorkerEventStatus status,
+ double event_dispatch_time) {
+ client_.DidHandleAbortPaymentEvent(abort_payment_event_id, status,
+ event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::DidHandleCanMakePaymentEvent(
+ int payment_request_event_id,
+ mojom::ServiceWorkerEventStatus status,
+ double event_dispatch_time) {
+ client_.DidHandleCanMakePaymentEvent(payment_request_event_id, status,
+ event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::DidHandlePaymentRequestEvent(
+ int payment_request_event_id,
+ mojom::ServiceWorkerEventStatus status,
+ double event_dispatch_time) {
+ client_.DidHandlePaymentRequestEvent(payment_request_event_id, status,
+ event_dispatch_time);
+}
+
+void ServiceWorkerGlobalScopeClient::PostMessageToClient(
+ const WebString& client_uuid,
+ TransferableMessage message) {
+ client_.PostMessageToClient(client_uuid, std::move(message));
+}
+
+void ServiceWorkerGlobalScopeClient::SkipWaiting(
+ std::unique_ptr<WebServiceWorkerSkipWaitingCallbacks> callbacks) {
+ client_.SkipWaiting(std::move(callbacks));
+}
+
+void ServiceWorkerGlobalScopeClient::Claim(
+ std::unique_ptr<WebServiceWorkerClientsClaimCallbacks> callbacks) {
+ client_.Claim(std::move(callbacks));
+}
+
+void ServiceWorkerGlobalScopeClient::Focus(
+ const WebString& client_uuid,
+ std::unique_ptr<WebServiceWorkerClientCallbacks> callback) {
+ client_.Focus(client_uuid, std::move(callback));
+}
+
+void ServiceWorkerGlobalScopeClient::Navigate(
+ const WebString& client_uuid,
+ const WebURL& url,
+ std::unique_ptr<WebServiceWorkerClientCallbacks> callback) {
+ client_.Navigate(client_uuid, url, std::move(callback));
+}
+
+const char ServiceWorkerGlobalScopeClient::kSupplementName[] =
+ "ServiceWorkerGlobalScopeClient";
+
+ServiceWorkerGlobalScopeClient* ServiceWorkerGlobalScopeClient::From(
+ ExecutionContext* context) {
+ // TODO(horo): Replace CHECK() to DCHECK() when crbug.com/749930 is fixed.
+ CHECK(context);
+ WorkerClients* worker_clients = ToWorkerGlobalScope(context)->Clients();
+ CHECK(worker_clients);
+ ServiceWorkerGlobalScopeClient* client =
+ Supplement<WorkerClients>::From<ServiceWorkerGlobalScopeClient>(
+ worker_clients);
+ CHECK(client);
+ return client;
+}
+
+void ServiceWorkerGlobalScopeClient::Trace(blink::Visitor* visitor) {
+ Supplement<WorkerClients>::Trace(visitor);
+}
+
+void ProvideServiceWorkerGlobalScopeClientToWorker(
+ WorkerClients* clients,
+ ServiceWorkerGlobalScopeClient* client) {
+ clients->ProvideSupplement(client);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h
new file mode 100644
index 00000000000..cb62c62aaf4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2014 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_MODULES_SERVICE_WORKER_SERVICE_WORKER_GLOBAL_SCOPE_CLIENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_GLOBAL_SCOPE_CLIENT_H_
+
+#include <memory>
+#include "third_party/blink/public/common/message_port/transferable_message.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom-blink.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_clients_claim_callbacks.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_clients_info.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_skip_waiting_callbacks.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_stream_handle.h"
+#include "third_party/blink/renderer/core/messaging/message_port.h"
+#include "third_party/blink/renderer/core/workers/worker_clients.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
+
+namespace blink {
+
+struct WebPaymentHandlerResponse;
+struct WebServiceWorkerClientQueryOptions;
+class ExecutionContext;
+class WebServiceWorkerContextClient;
+class WebServiceWorkerResponse;
+class WebURL;
+class WorkerClients;
+
+// See WebServiceWorkerContextClient for documentation for the methods in this
+// class.
+class MODULES_EXPORT ServiceWorkerGlobalScopeClient
+ : public GarbageCollected<ServiceWorkerGlobalScopeClient>,
+ public Supplement<WorkerClients> {
+ USING_GARBAGE_COLLECTED_MIXIN(ServiceWorkerGlobalScopeClient);
+ WTF_MAKE_NONCOPYABLE(ServiceWorkerGlobalScopeClient);
+
+ public:
+ static const char kSupplementName[];
+
+ explicit ServiceWorkerGlobalScopeClient(WebServiceWorkerContextClient&);
+
+ // Called from ServiceWorkerClients.
+ void GetClient(const WebString&,
+ std::unique_ptr<WebServiceWorkerClientCallbacks>);
+ void GetClients(const WebServiceWorkerClientQueryOptions&,
+ std::unique_ptr<WebServiceWorkerClientsCallbacks>);
+ void OpenWindowForClients(const WebURL&,
+ std::unique_ptr<WebServiceWorkerClientCallbacks>);
+ void OpenWindowForPaymentHandler(
+ const WebURL&,
+ std::unique_ptr<WebServiceWorkerClientCallbacks>);
+ void SetCachedMetadata(const WebURL&, const char*, size_t);
+ void ClearCachedMetadata(const WebURL&);
+
+ void DidHandleActivateEvent(int event_id,
+ mojom::ServiceWorkerEventStatus,
+ double event_dispatch_time);
+ void DidHandleBackgroundFetchAbortEvent(int event_id,
+ mojom::ServiceWorkerEventStatus,
+ double event_dispatch_time);
+ void DidHandleBackgroundFetchClickEvent(int event_id,
+ mojom::ServiceWorkerEventStatus,
+ double event_dispatch_time);
+ void DidHandleBackgroundFetchFailEvent(int event_id,
+ mojom::ServiceWorkerEventStatus,
+ double event_dispatch_time);
+ void DidHandleBackgroundFetchedEvent(int event_id,
+ mojom::ServiceWorkerEventStatus,
+ double event_dispatch_time);
+ void DidHandleCookieChangeEvent(int event_id,
+ mojom::ServiceWorkerEventStatus,
+ double event_dispatch_time);
+ void DidHandleExtendableMessageEvent(int event_id,
+ mojom::ServiceWorkerEventStatus,
+ double event_dispatch_time);
+ void RespondToFetchEventWithNoResponse(int fetch_event_id,
+ double event_dispatch_time);
+ void RespondToFetchEvent(int fetch_event_id,
+ const WebServiceWorkerResponse&,
+ double event_dispatch_time);
+ void RespondToFetchEventWithResponseStream(int fetch_event_id,
+ const WebServiceWorkerResponse&,
+ WebServiceWorkerStreamHandle*,
+ double event_dispatch_time);
+ void RespondToAbortPaymentEvent(int event_id,
+ bool abort_payment,
+ double event_dispatch_time);
+ void RespondToCanMakePaymentEvent(int event_id,
+ bool can_make_payment,
+ double event_dispatch_time);
+ void RespondToPaymentRequestEvent(int event_id,
+ const WebPaymentHandlerResponse&,
+ double event_dispatch_time);
+ void DidHandleFetchEvent(int fetch_event_id,
+ mojom::ServiceWorkerEventStatus,
+ double event_dispatch_time);
+ void DidHandleInstallEvent(int install_event_id,
+ mojom::ServiceWorkerEventStatus,
+ double event_dispatch_time);
+ void DidHandleNotificationClickEvent(int event_id,
+ mojom::ServiceWorkerEventStatus,
+ double event_dispatch_time);
+ void DidHandleNotificationCloseEvent(int event_id,
+ mojom::ServiceWorkerEventStatus,
+ double event_dispatch_time);
+ void DidHandlePushEvent(int push_event_id,
+ mojom::ServiceWorkerEventStatus,
+ double event_dispatch_time);
+ void DidHandleSyncEvent(int sync_event_id,
+ mojom::ServiceWorkerEventStatus,
+ double event_dispatch_time);
+ void DidHandleAbortPaymentEvent(int abort_payment_event_id,
+ mojom::ServiceWorkerEventStatus,
+ double event_dispatch_time);
+ void DidHandleCanMakePaymentEvent(int payment_request_event_id,
+ mojom::ServiceWorkerEventStatus,
+ double event_dispatch_time);
+ void DidHandlePaymentRequestEvent(int payment_request_event_id,
+ mojom::ServiceWorkerEventStatus,
+ double event_dispatch_time);
+ void PostMessageToClient(const WebString& client_uuid, TransferableMessage);
+ void SkipWaiting(std::unique_ptr<WebServiceWorkerSkipWaitingCallbacks>);
+ void Claim(std::unique_ptr<WebServiceWorkerClientsClaimCallbacks>);
+ void Focus(const WebString& client_uuid,
+ std::unique_ptr<WebServiceWorkerClientCallbacks>);
+ void Navigate(const WebString& client_uuid,
+ const WebURL&,
+ std::unique_ptr<WebServiceWorkerClientCallbacks>);
+
+ static ServiceWorkerGlobalScopeClient* From(ExecutionContext*);
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ WebServiceWorkerContextClient& client_;
+};
+
+MODULES_EXPORT void ProvideServiceWorkerGlobalScopeClientToWorker(
+ WorkerClients*,
+ ServiceWorkerGlobalScopeClient*);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_GLOBAL_SCOPE_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
new file mode 100644
index 00000000000..88c47ee2bbf
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
@@ -0,0 +1,703 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * 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/modules/service_worker/service_worker_global_scope_proxy.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/memory/ptr_util.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom-blink.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom-blink.h"
+#include "third_party/blink/public/platform/modules/notifications/web_notification_data.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h"
+#include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h"
+#include "third_party/blink/public/web/web_serialized_script_value.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/execution_context.h"
+#include "third_party/blink/renderer/core/fetch/headers.h"
+#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
+#include "third_party/blink/renderer/core/inspector/console_message.h"
+#include "third_party/blink/renderer/core/messaging/blink_transferable_message.h"
+#include "third_party/blink/renderer/core/messaging/message_port.h"
+#include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
+#include "third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h"
+#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
+#include "third_party/blink/renderer/core/workers/worker_thread.h"
+#include "third_party/blink/renderer/modules/background_fetch/background_fetch_click_event.h"
+#include "third_party/blink/renderer/modules/background_fetch/background_fetch_click_event_init.h"
+#include "third_party/blink/renderer/modules/background_fetch/background_fetch_event.h"
+#include "third_party/blink/renderer/modules/background_fetch/background_fetch_event_init.h"
+#include "third_party/blink/renderer/modules/background_fetch/background_fetch_fail_event.h"
+#include "third_party/blink/renderer/modules/background_fetch/background_fetch_fail_event_init.h"
+#include "third_party/blink/renderer/modules/background_fetch/background_fetch_settled_event_init.h"
+#include "third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.h"
+#include "third_party/blink/renderer/modules/background_sync/sync_event.h"
+#include "third_party/blink/renderer/modules/cookie_store/cookie_change_event.h"
+#include "third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.h"
+#include "third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h"
+#include "third_party/blink/renderer/modules/notifications/notification.h"
+#include "third_party/blink/renderer/modules/notifications/notification_event.h"
+#include "third_party/blink/renderer/modules/notifications/notification_event_init.h"
+#include "third_party/blink/renderer/modules/payments/abort_payment_event.h"
+#include "third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.h"
+#include "third_party/blink/renderer/modules/payments/can_make_payment_event.h"
+#include "third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.h"
+#include "third_party/blink/renderer/modules/payments/payment_event_data_conversion.h"
+#include "third_party/blink/renderer/modules/payments/payment_request_event.h"
+#include "third_party/blink/renderer/modules/payments/payment_request_event_init.h"
+#include "third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.h"
+#include "third_party/blink/renderer/modules/push_messaging/push_event.h"
+#include "third_party/blink/renderer/modules/push_messaging/push_message_data.h"
+#include "third_party/blink/renderer/modules/service_worker/extendable_event.h"
+#include "third_party/blink/renderer/modules/service_worker/extendable_message_event.h"
+#include "third_party/blink/renderer/modules/service_worker/fetch_event.h"
+#include "third_party/blink/renderer/modules/service_worker/fetch_respond_with_observer.h"
+#include "third_party/blink/renderer/modules/service_worker/install_event.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_client.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_window_client.h"
+#include "third_party/blink/renderer/modules/service_worker/wait_until_observer.h"
+#include "third_party/blink/renderer/platform/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
+#include "third_party/blink/renderer/platform/network/content_security_policy_response_headers.h"
+#include "third_party/blink/renderer/platform/waitable_event.h"
+#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+
+namespace blink {
+
+namespace {
+
+void SetContentSecurityPolicyAndReferrerPolicyOnMainThread(
+ WebEmbeddedWorkerImpl* embedded_worker,
+ ContentSecurityPolicyResponseHeaders csp_headers,
+ String referrer_policy,
+ WaitableEvent* waitable_event) {
+ DCHECK(IsMainThread());
+ ContentSecurityPolicy* content_security_policy =
+ ContentSecurityPolicy::Create();
+ content_security_policy->DidReceiveHeaders(csp_headers);
+ embedded_worker->SetContentSecurityPolicyAndReferrerPolicy(
+ content_security_policy, std::move(referrer_policy));
+ waitable_event->Signal();
+}
+
+} // namespace
+
+ServiceWorkerGlobalScopeProxy* ServiceWorkerGlobalScopeProxy::Create(
+ WebEmbeddedWorkerImpl& embedded_worker,
+ WebServiceWorkerContextClient& client) {
+ return new ServiceWorkerGlobalScopeProxy(embedded_worker, client);
+}
+
+ServiceWorkerGlobalScopeProxy::~ServiceWorkerGlobalScopeProxy() {
+ DCHECK(IsMainThread());
+ // Verify that the proxy has been detached.
+ DCHECK(!embedded_worker_);
+}
+
+void ServiceWorkerGlobalScopeProxy::Trace(blink::Visitor* visitor) {
+ visitor->Trace(parent_execution_context_task_runners_);
+}
+
+void ServiceWorkerGlobalScopeProxy::ReadyToEvaluateScript() {
+ WorkerGlobalScope()->ReadyToEvaluateScript();
+}
+
+void ServiceWorkerGlobalScopeProxy::SetRegistration(
+ std::unique_ptr<WebServiceWorkerRegistration::Handle> handle) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ WorkerGlobalScope()->SetRegistration(std::move(handle));
+}
+
+void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchAbortEvent(
+ int event_id,
+ const WebString& developer_id,
+ const WebString& unique_id,
+ const WebVector<WebBackgroundFetchSettledFetch>& fetches) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ WaitUntilObserver* observer = WaitUntilObserver::Create(
+ WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchAbort, event_id);
+
+ ScriptState* script_state =
+ WorkerGlobalScope()->ScriptController()->GetScriptState();
+
+ // Do not remove this, |scope| is needed by
+ // BackgroundFetchSettledFetches::Create which eventually calls ToV8.
+ ScriptState::Scope scope(script_state);
+
+ BackgroundFetchSettledEventInit init;
+ init.setId(developer_id);
+ init.setFetches(BackgroundFetchSettledFetches::Create(script_state, fetches));
+
+ BackgroundFetchSettledEvent* event = BackgroundFetchSettledEvent::Create(
+ EventTypeNames::backgroundfetchabort, init, unique_id, observer);
+
+ WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
+}
+
+void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchClickEvent(
+ int event_id,
+ const WebString& developer_id,
+ BackgroundFetchState status) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ WaitUntilObserver* observer = WaitUntilObserver::Create(
+ WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchClick, event_id);
+
+ BackgroundFetchClickEventInit init;
+ init.setId(developer_id);
+
+ switch (status) {
+ case BackgroundFetchState::kPending:
+ init.setState("pending");
+ break;
+ case BackgroundFetchState::kSucceeded:
+ init.setState("succeeded");
+ break;
+ case BackgroundFetchState::kFailed:
+ init.setState("failed");
+ break;
+ }
+
+ BackgroundFetchClickEvent* event = BackgroundFetchClickEvent::Create(
+ EventTypeNames::backgroundfetchclick, init, observer);
+
+ WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
+}
+
+void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchFailEvent(
+ int event_id,
+ const WebString& developer_id,
+ const WebString& unique_id,
+ const WebVector<WebBackgroundFetchSettledFetch>& fetches) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ WaitUntilObserver* observer = WaitUntilObserver::Create(
+ WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchFail, event_id);
+
+ ScriptState* script_state =
+ WorkerGlobalScope()->ScriptController()->GetScriptState();
+
+ // Do not remove this, |scope| is needed by
+ // BackgroundFetchSettledFetches::Create which eventually calls ToV8.
+ ScriptState::Scope scope(script_state);
+
+ BackgroundFetchSettledEventInit init;
+ init.setId(developer_id);
+ init.setFetches(BackgroundFetchSettledFetches::Create(script_state, fetches));
+
+ BackgroundFetchUpdateEvent* event = BackgroundFetchUpdateEvent::Create(
+ EventTypeNames::backgroundfetchfail, init, unique_id, script_state,
+ observer, worker_global_scope_->registration());
+
+ WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
+}
+
+void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchedEvent(
+ int event_id,
+ const WebString& developer_id,
+ const WebString& unique_id,
+ const WebVector<WebBackgroundFetchSettledFetch>& fetches) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ WaitUntilObserver* observer = WaitUntilObserver::Create(
+ WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetched, event_id);
+
+ ScriptState* script_state =
+ WorkerGlobalScope()->ScriptController()->GetScriptState();
+
+ // Do not remove this, |scope| is needed by
+ // BackgroundFetchSettledFetches::Create which eventually calls ToV8.
+ ScriptState::Scope scope(script_state);
+
+ BackgroundFetchSettledEventInit init;
+ init.setId(developer_id);
+ init.setFetches(BackgroundFetchSettledFetches::Create(script_state, fetches));
+
+ BackgroundFetchUpdateEvent* event = BackgroundFetchUpdateEvent::Create(
+ EventTypeNames::backgroundfetched, init, unique_id, script_state,
+ observer, worker_global_scope_->registration());
+
+ WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
+}
+
+void ServiceWorkerGlobalScopeProxy::DispatchActivateEvent(int event_id) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ WaitUntilObserver* observer = WaitUntilObserver::Create(
+ WorkerGlobalScope(), WaitUntilObserver::kActivate, event_id);
+ Event* event = ExtendableEvent::Create(EventTypeNames::activate,
+ ExtendableEventInit(), observer);
+ WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
+}
+
+void ServiceWorkerGlobalScopeProxy::DispatchCookieChangeEvent(
+ int event_id,
+ const WebCanonicalCookie& cookie,
+ network::mojom::CookieChangeCause change_cause) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ WaitUntilObserver* observer = WaitUntilObserver::Create(
+ WorkerGlobalScope(), WaitUntilObserver::kCookieChange, event_id);
+
+ HeapVector<CookieListItem> changed;
+ HeapVector<CookieListItem> deleted;
+ CookieChangeEvent::ToEventInfo(cookie, change_cause, changed, deleted);
+ Event* event = ExtendableCookieChangeEvent::Create(
+ EventTypeNames::cookiechange, std::move(changed), std::move(deleted),
+ observer);
+
+ // TODO(pwnall): Handle handle the case when
+ // (changed.IsEmpty() && deleted.IsEmpty()).
+
+ // TODO(pwnall): Investigate dispatching this on cookieStore.
+ WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
+}
+
+void ServiceWorkerGlobalScopeProxy::DispatchExtendableMessageEvent(
+ int event_id,
+ TransferableMessage message,
+ const WebSecurityOrigin& source_origin,
+ const WebServiceWorkerClientInfo& client) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ auto msg = ToBlinkTransferableMessage(std::move(message));
+ MessagePortArray* ports =
+ MessagePort::EntanglePorts(*worker_global_scope_, std::move(msg.ports));
+ String origin;
+ if (!source_origin.IsOpaque())
+ origin = source_origin.ToString();
+ ServiceWorkerClient* source = nullptr;
+ if (client.client_type == mojom::ServiceWorkerClientType::kWindow)
+ source = ServiceWorkerWindowClient::Create(client);
+ else
+ source = ServiceWorkerClient::Create(client);
+ WaitUntilObserver* observer = WaitUntilObserver::Create(
+ WorkerGlobalScope(), WaitUntilObserver::kMessage, event_id);
+
+ Event* event = ExtendableMessageEvent::Create(std::move(msg.message), origin,
+ ports, source, observer);
+ WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
+}
+
+void ServiceWorkerGlobalScopeProxy::DispatchExtendableMessageEvent(
+ int event_id,
+ TransferableMessage message,
+ const WebSecurityOrigin& source_origin,
+ std::unique_ptr<WebServiceWorker::Handle> handle) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ auto msg = ToBlinkTransferableMessage(std::move(message));
+ MessagePortArray* ports =
+ MessagePort::EntanglePorts(*worker_global_scope_, std::move(msg.ports));
+ String origin;
+ if (!source_origin.IsOpaque())
+ origin = source_origin.ToString();
+ ServiceWorker* source =
+ ServiceWorker::From(worker_global_scope_->GetExecutionContext(),
+ base::WrapUnique(handle.release()));
+ WaitUntilObserver* observer = WaitUntilObserver::Create(
+ WorkerGlobalScope(), WaitUntilObserver::kMessage, event_id);
+
+ Event* event = ExtendableMessageEvent::Create(std::move(msg.message), origin,
+ ports, source, observer);
+ WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
+}
+
+void ServiceWorkerGlobalScopeProxy::DispatchFetchEvent(
+ int fetch_event_id,
+ const WebServiceWorkerRequest& web_request,
+ bool navigation_preload_sent) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ ScriptState::Scope scope(
+ WorkerGlobalScope()->ScriptController()->GetScriptState());
+ WaitUntilObserver* wait_until_observer = WaitUntilObserver::Create(
+ WorkerGlobalScope(), WaitUntilObserver::kFetch, fetch_event_id);
+ FetchRespondWithObserver* respond_with_observer =
+ FetchRespondWithObserver::Create(
+ WorkerGlobalScope(), fetch_event_id, web_request.Url(),
+ web_request.Mode(), web_request.RedirectMode(),
+ web_request.GetFrameType(), web_request.GetRequestContext(),
+ wait_until_observer);
+ Request* request = Request::Create(
+ WorkerGlobalScope()->ScriptController()->GetScriptState(), web_request);
+ request->getHeaders()->SetGuard(Headers::kImmutableGuard);
+ FetchEventInit event_init;
+ event_init.setCancelable(true);
+ event_init.setRequest(request);
+ event_init.setClientId(
+ web_request.IsMainResourceLoad() ? WebString() : web_request.ClientId());
+ event_init.setIsReload(web_request.IsReload());
+ ScriptState* script_state =
+ WorkerGlobalScope()->ScriptController()->GetScriptState();
+ FetchEvent* fetch_event = FetchEvent::Create(
+ script_state, EventTypeNames::fetch, event_init, respond_with_observer,
+ wait_until_observer, navigation_preload_sent);
+ if (navigation_preload_sent) {
+ // Keep |fetchEvent| until OnNavigationPreloadComplete() or
+ // onNavigationPreloadError() will be called.
+ pending_preload_fetch_events_.insert(fetch_event_id, fetch_event);
+ }
+
+ WorkerGlobalScope()->DispatchExtendableEventWithRespondWith(
+ fetch_event, wait_until_observer, respond_with_observer);
+}
+
+void ServiceWorkerGlobalScopeProxy::OnNavigationPreloadResponse(
+ int fetch_event_id,
+ std::unique_ptr<WebURLResponse> response,
+ std::unique_ptr<WebDataConsumerHandle> data_consume_handle) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ auto it = pending_preload_fetch_events_.find(fetch_event_id);
+ DCHECK(it != pending_preload_fetch_events_.end());
+ FetchEvent* fetch_event = it->value.Get();
+ DCHECK(fetch_event);
+ fetch_event->OnNavigationPreloadResponse(
+ WorkerGlobalScope()->ScriptController()->GetScriptState(),
+ std::move(response), std::move(data_consume_handle));
+}
+
+void ServiceWorkerGlobalScopeProxy::OnNavigationPreloadError(
+ int fetch_event_id,
+ std::unique_ptr<WebServiceWorkerError> error) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ FetchEvent* fetch_event = pending_preload_fetch_events_.Take(fetch_event_id);
+ DCHECK(fetch_event);
+ // Display an unsanitized console message.
+ if (!error->unsanitized_message.IsEmpty()) {
+ WorkerGlobalScope()->AddConsoleMessage(ConsoleMessage::Create(
+ kWorkerMessageSource, blink::MessageLevel::kErrorMessageLevel,
+ error->unsanitized_message));
+ }
+ // Reject the preloadResponse promise.
+ fetch_event->OnNavigationPreloadError(
+ WorkerGlobalScope()->ScriptController()->GetScriptState(),
+ std::move(error));
+}
+
+void ServiceWorkerGlobalScopeProxy::OnNavigationPreloadComplete(
+ int fetch_event_id,
+ TimeTicks completion_time,
+ int64_t encoded_data_length,
+ int64_t encoded_body_length,
+ int64_t decoded_body_length) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ FetchEvent* fetch_event = pending_preload_fetch_events_.Take(fetch_event_id);
+ DCHECK(fetch_event);
+ fetch_event->OnNavigationPreloadComplete(
+ WorkerGlobalScope(), completion_time, encoded_data_length,
+ encoded_body_length, decoded_body_length);
+}
+
+void ServiceWorkerGlobalScopeProxy::DispatchInstallEvent(int event_id) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ WaitUntilObserver* observer = WaitUntilObserver::Create(
+ WorkerGlobalScope(), WaitUntilObserver::kInstall, event_id);
+ Event* event = InstallEvent::Create(
+ EventTypeNames::install, ExtendableEventInit(), event_id, observer);
+ WorkerGlobalScope()->SetIsInstalling(true);
+ WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
+}
+
+void ServiceWorkerGlobalScopeProxy::DispatchNotificationClickEvent(
+ int event_id,
+ const WebString& notification_id,
+ const WebNotificationData& data,
+ int action_index,
+ const WebString& reply) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ WaitUntilObserver* observer = WaitUntilObserver::Create(
+ WorkerGlobalScope(), WaitUntilObserver::kNotificationClick, event_id);
+ NotificationEventInit event_init;
+ event_init.setNotification(Notification::Create(
+ WorkerGlobalScope(), notification_id, data, true /* showing */));
+ if (0 <= action_index && action_index < static_cast<int>(data.actions.size()))
+ event_init.setAction(data.actions[action_index].action);
+ event_init.setReply(reply);
+ Event* event = NotificationEvent::Create(EventTypeNames::notificationclick,
+ event_init, observer);
+ WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
+}
+
+void ServiceWorkerGlobalScopeProxy::DispatchNotificationCloseEvent(
+ int event_id,
+ const WebString& notification_id,
+ const WebNotificationData& data) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ WaitUntilObserver* observer = WaitUntilObserver::Create(
+ WorkerGlobalScope(), WaitUntilObserver::kNotificationClose, event_id);
+ NotificationEventInit event_init;
+ event_init.setAction(WTF::String()); // initialize as null.
+ event_init.setNotification(Notification::Create(
+ WorkerGlobalScope(), notification_id, data, false /* showing */));
+ Event* event = NotificationEvent::Create(EventTypeNames::notificationclose,
+ event_init, observer);
+ WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
+}
+
+void ServiceWorkerGlobalScopeProxy::DispatchPushEvent(int event_id,
+ const WebString& data) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ WaitUntilObserver* observer = WaitUntilObserver::Create(
+ WorkerGlobalScope(), WaitUntilObserver::kPush, event_id);
+ Event* event = PushEvent::Create(EventTypeNames::push,
+ PushMessageData::Create(data), observer);
+ WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
+}
+
+void ServiceWorkerGlobalScopeProxy::DispatchSyncEvent(int event_id,
+ const WebString& id,
+ bool last_chance) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ WaitUntilObserver* observer = WaitUntilObserver::Create(
+ WorkerGlobalScope(), WaitUntilObserver::kSync, event_id);
+ Event* event =
+ SyncEvent::Create(EventTypeNames::sync, id, last_chance, observer);
+ WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
+}
+
+void ServiceWorkerGlobalScopeProxy::DispatchAbortPaymentEvent(int event_id) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ WaitUntilObserver* wait_until_observer = WaitUntilObserver::Create(
+ WorkerGlobalScope(), WaitUntilObserver::kAbortPayment, event_id);
+ AbortPaymentRespondWithObserver* respond_with_observer =
+ new AbortPaymentRespondWithObserver(WorkerGlobalScope(), event_id,
+ wait_until_observer);
+
+ Event* event = AbortPaymentEvent::Create(
+ EventTypeNames::abortpayment, ExtendableEventInit(),
+ respond_with_observer, wait_until_observer);
+
+ WorkerGlobalScope()->DispatchExtendableEventWithRespondWith(
+ event, wait_until_observer, respond_with_observer);
+}
+
+void ServiceWorkerGlobalScopeProxy::DispatchCanMakePaymentEvent(
+ int event_id,
+ const WebCanMakePaymentEventData& web_event_data) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ WaitUntilObserver* wait_until_observer = WaitUntilObserver::Create(
+ WorkerGlobalScope(), WaitUntilObserver::kCanMakePayment, event_id);
+ CanMakePaymentRespondWithObserver* respond_with_observer =
+ new CanMakePaymentRespondWithObserver(WorkerGlobalScope(), event_id,
+ wait_until_observer);
+
+ Event* event = CanMakePaymentEvent::Create(
+ EventTypeNames::canmakepayment,
+ PaymentEventDataConversion::ToCanMakePaymentEventInit(
+ WorkerGlobalScope()->ScriptController()->GetScriptState(),
+ web_event_data),
+ respond_with_observer, wait_until_observer);
+
+ WorkerGlobalScope()->DispatchExtendableEventWithRespondWith(
+ event, wait_until_observer, respond_with_observer);
+}
+
+void ServiceWorkerGlobalScopeProxy::DispatchPaymentRequestEvent(
+ int event_id,
+ const WebPaymentRequestEventData& web_app_request) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ WaitUntilObserver* wait_until_observer = WaitUntilObserver::Create(
+ WorkerGlobalScope(), WaitUntilObserver::kPaymentRequest, event_id);
+ PaymentRequestRespondWithObserver* respond_with_observer =
+ PaymentRequestRespondWithObserver::Create(WorkerGlobalScope(), event_id,
+ wait_until_observer);
+
+ Event* event = PaymentRequestEvent::Create(
+ EventTypeNames::paymentrequest,
+ PaymentEventDataConversion::ToPaymentRequestEventInit(
+ WorkerGlobalScope()->ScriptController()->GetScriptState(),
+ web_app_request),
+ respond_with_observer, wait_until_observer);
+
+ WorkerGlobalScope()->DispatchExtendableEventWithRespondWith(
+ event, wait_until_observer, respond_with_observer);
+}
+
+bool ServiceWorkerGlobalScopeProxy::HasFetchEventHandler() {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ return WorkerGlobalScope()->HasEventListeners(EventTypeNames::fetch);
+}
+
+void ServiceWorkerGlobalScopeProxy::CountFeature(WebFeature feature) {
+ Client().CountFeature(feature);
+}
+
+void ServiceWorkerGlobalScopeProxy::CountDeprecation(WebFeature feature) {
+ // Go through the same code path with countFeature() because a deprecation
+ // message is already shown on the worker console and a remaining work is just
+ // to record an API use.
+ CountFeature(feature);
+}
+
+void ServiceWorkerGlobalScopeProxy::ReportException(
+ const String& error_message,
+ std::unique_ptr<SourceLocation> location,
+ int exception_id) {
+ Client().ReportException(error_message, location->LineNumber(),
+ location->ColumnNumber(), location->Url());
+}
+
+void ServiceWorkerGlobalScopeProxy::ReportConsoleMessage(
+ MessageSource source,
+ MessageLevel level,
+ const String& message,
+ SourceLocation* location) {
+ Client().ReportConsoleMessage(source, level, message, location->LineNumber(),
+ location->Url());
+}
+
+void ServiceWorkerGlobalScopeProxy::PostMessageToPageInspector(
+ int session_id,
+ const String& message) {
+ DCHECK(embedded_worker_);
+ PostCrossThreadTask(
+ *parent_execution_context_task_runners_->Get(
+ TaskType::kInternalInspector),
+ FROM_HERE,
+ CrossThreadBind(&WebEmbeddedWorkerImpl::PostMessageToPageInspector,
+ CrossThreadUnretained(embedded_worker_), session_id,
+ message));
+}
+
+void ServiceWorkerGlobalScopeProxy::DidCreateWorkerGlobalScope(
+ WorkerOrWorkletGlobalScope* worker_global_scope) {
+ DCHECK(!worker_global_scope_);
+ worker_global_scope_ =
+ static_cast<ServiceWorkerGlobalScope*>(worker_global_scope);
+ Client().WorkerContextStarted(this);
+}
+
+void ServiceWorkerGlobalScopeProxy::DidInitializeWorkerContext() {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ ScriptState::Scope scope(
+ WorkerGlobalScope()->ScriptController()->GetScriptState());
+ Client().DidInitializeWorkerContext(
+ WorkerGlobalScope()->ScriptController()->GetContext());
+}
+
+void ServiceWorkerGlobalScopeProxy::DidLoadInstalledScript(
+ const ContentSecurityPolicyResponseHeaders& csp_headers_on_worker_thread,
+ const String& referrer_policy_on_worker_thread) {
+ // Post a task to the main thread to set CSP and ReferrerPolicy on the shadow
+ // page.
+ DCHECK(embedded_worker_);
+ WaitableEvent waitable_event;
+ PostCrossThreadTask(
+ *parent_execution_context_task_runners_->Get(TaskType::kInternalWorker),
+ FROM_HERE,
+ CrossThreadBind(&SetContentSecurityPolicyAndReferrerPolicyOnMainThread,
+ CrossThreadUnretained(embedded_worker_),
+ csp_headers_on_worker_thread,
+ referrer_policy_on_worker_thread,
+ CrossThreadUnretained(&waitable_event)));
+ Client().WorkerScriptLoaded();
+
+ // Wait for the task to complete before returning. This ensures that worker
+ // script evaluation can't start and issue any fetches until CSP and
+ // ReferrerPolicy are set.
+ waitable_event.Wait();
+}
+
+void ServiceWorkerGlobalScopeProxy::WillEvaluateClassicScript(
+ size_t script_size,
+ size_t cached_metadata_size) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ worker_global_scope_->CountWorkerScript(script_size, cached_metadata_size);
+ Client().WillEvaluateClassicScript();
+}
+
+void ServiceWorkerGlobalScopeProxy::WillEvaluateImportedClassicScript(
+ size_t script_size,
+ size_t cached_metadata_size) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ worker_global_scope_->CountImportedScript(script_size, cached_metadata_size);
+}
+
+void ServiceWorkerGlobalScopeProxy::DidEvaluateClassicScript(bool success) {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ WorkerGlobalScope()->DidEvaluateClassicScript();
+ Client().DidEvaluateClassicScript(success);
+}
+
+void ServiceWorkerGlobalScopeProxy::DidCloseWorkerGlobalScope() {
+ // This should never be called because close() is not defined in
+ // ServiceWorkerGlobalScope.
+ NOTREACHED();
+}
+
+void ServiceWorkerGlobalScopeProxy::WillDestroyWorkerGlobalScope() {
+ DCHECK(WorkerGlobalScope()->IsContextThread());
+ v8::HandleScope handle_scope(WorkerGlobalScope()->GetThread()->GetIsolate());
+ Client().WillDestroyWorkerContext(
+ WorkerGlobalScope()->ScriptController()->GetContext());
+ worker_global_scope_ = nullptr;
+}
+
+void ServiceWorkerGlobalScopeProxy::DidTerminateWorkerThread() {
+ // This should be called after WillDestroyWorkerGlobalScope().
+ DCHECK(!worker_global_scope_);
+ Client().WorkerContextDestroyed();
+}
+
+ServiceWorkerGlobalScopeProxy::ServiceWorkerGlobalScopeProxy(
+ WebEmbeddedWorkerImpl& embedded_worker,
+ WebServiceWorkerContextClient& client)
+ : embedded_worker_(&embedded_worker),
+ client_(&client),
+ worker_global_scope_(nullptr) {
+ DCHECK(IsMainThread());
+ // ServiceWorker can sometimes run tasks that are initiated by/associated with
+ // a document's frame but these documents can be from a different process. So
+ // we intentionally populate the task runners with default task runners of the
+ // main thread.
+ parent_execution_context_task_runners_ =
+ ParentExecutionContextTaskRunners::Create();
+}
+
+void ServiceWorkerGlobalScopeProxy::Detach() {
+ DCHECK(IsMainThread());
+ embedded_worker_ = nullptr;
+ client_ = nullptr;
+}
+
+void ServiceWorkerGlobalScopeProxy::TerminateWorkerContext() {
+ embedded_worker_->TerminateWorkerContext();
+}
+
+WebServiceWorkerContextClient& ServiceWorkerGlobalScopeProxy::Client() const {
+ DCHECK(client_);
+ return *client_;
+}
+
+ServiceWorkerGlobalScope* ServiceWorkerGlobalScopeProxy::WorkerGlobalScope()
+ const {
+ DCHECK(worker_global_scope_);
+ DCHECK(worker_global_scope_->IsContextThread());
+ return worker_global_scope_;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h
new file mode 100644
index 00000000000..89c1dcd1d4b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * 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_MODULES_SERVICE_WORKER_SERVICE_WORKER_GLOBAL_SCOPE_PROXY_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_GLOBAL_SCOPE_PROXY_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_proxy.h"
+#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/time.h"
+
+namespace blink {
+
+class FetchEvent;
+class ParentExecutionContextTaskRunners;
+class ServiceWorkerGlobalScope;
+class WebDataConsumerHandle;
+class WebEmbeddedWorkerImpl;
+class WebServiceWorkerContextClient;
+struct WebServiceWorkerError;
+class WebServiceWorkerRequest;
+class WebURLResponse;
+
+// This class is created and destructed on the main thread, but live most
+// of its time as a resident of the worker thread. All methods other than its
+// ctor/dtor and Detach() are called on the worker thread.
+//
+// This implements WebServiceWorkerContextProxy, which connects ServiceWorker's
+// WorkerGlobalScope and embedder/chrome, and implements ServiceWorker-specific
+// events/upcall methods that are to be called by embedder/chromium,
+// e.g. onfetch.
+//
+// An instance of this class is supposed to outlive until
+// workerThreadTerminated() is called by its corresponding
+// WorkerGlobalScope.
+class ServiceWorkerGlobalScopeProxy final
+ : public GarbageCollectedFinalized<ServiceWorkerGlobalScopeProxy>,
+ public WebServiceWorkerContextProxy,
+ public WorkerReportingProxy {
+ public:
+ static ServiceWorkerGlobalScopeProxy* Create(WebEmbeddedWorkerImpl&,
+ WebServiceWorkerContextClient&);
+ ~ServiceWorkerGlobalScopeProxy() override;
+
+ // WebServiceWorkerContextProxy overrides:
+ void ReadyToEvaluateScript() override;
+ void SetRegistration(
+ std::unique_ptr<WebServiceWorkerRegistration::Handle>) override;
+ void DispatchActivateEvent(int) override;
+ void DispatchBackgroundFetchAbortEvent(
+ int event_id,
+ const WebString& developer_id,
+ const WebString& unique_id,
+ const WebVector<WebBackgroundFetchSettledFetch>& fetches) override;
+ void DispatchBackgroundFetchClickEvent(int event_id,
+ const WebString& developer_id,
+ BackgroundFetchState) override;
+ void DispatchBackgroundFetchFailEvent(
+ int event_id,
+ const WebString& developer_id,
+ const WebString& unique_id,
+ const WebVector<WebBackgroundFetchSettledFetch>& fetches) override;
+ void DispatchBackgroundFetchedEvent(
+ int event_id,
+ const WebString& developer_id,
+ const WebString& unique_id,
+ const WebVector<WebBackgroundFetchSettledFetch>& fetches) override;
+ void DispatchCookieChangeEvent(
+ int event_id,
+ const WebCanonicalCookie& cookie,
+ network::mojom::CookieChangeCause change_cause) override;
+ void DispatchExtendableMessageEvent(
+ int event_id,
+ TransferableMessage,
+ const WebSecurityOrigin& source_origin,
+ const WebServiceWorkerClientInfo&) override;
+ void DispatchExtendableMessageEvent(
+ int event_id,
+ TransferableMessage,
+ const WebSecurityOrigin& source_origin,
+ std::unique_ptr<WebServiceWorker::Handle>) override;
+ void DispatchFetchEvent(int fetch_event_id,
+ const WebServiceWorkerRequest&,
+ bool navigation_preload_sent) override;
+ void DispatchInstallEvent(int) override;
+ void DispatchNotificationClickEvent(int,
+ const WebString& notification_id,
+ const WebNotificationData&,
+ int action_index,
+ const WebString& reply) override;
+ void DispatchNotificationCloseEvent(int,
+ const WebString& notification_id,
+ const WebNotificationData&) override;
+ void DispatchPushEvent(int, const WebString& data) override;
+ void DispatchSyncEvent(int, const WebString& tag, bool last_chance) override;
+ void DispatchAbortPaymentEvent(int) override;
+ void DispatchCanMakePaymentEvent(int,
+ const WebCanMakePaymentEventData&) override;
+ void DispatchPaymentRequestEvent(int,
+ const WebPaymentRequestEventData&) override;
+ bool HasFetchEventHandler() override;
+ void OnNavigationPreloadResponse(
+ int fetch_event_id,
+ std::unique_ptr<WebURLResponse>,
+ std::unique_ptr<WebDataConsumerHandle>) override;
+ void OnNavigationPreloadError(
+ int fetch_event_id,
+ std::unique_ptr<WebServiceWorkerError>) override;
+ void OnNavigationPreloadComplete(int fetch_event_id,
+ TimeTicks completion_time,
+ int64_t encoded_data_length,
+ int64_t encoded_body_length,
+ int64_t decoded_body_length) override;
+
+ // WorkerReportingProxy overrides:
+ void CountFeature(WebFeature) override;
+ void CountDeprecation(WebFeature) override;
+ void ReportException(const String& error_message,
+ std::unique_ptr<SourceLocation>,
+ int exception_id) override;
+ void ReportConsoleMessage(MessageSource,
+ MessageLevel,
+ const String& message,
+ SourceLocation*) override;
+ void PostMessageToPageInspector(int session_id, const String&) override;
+ void DidCreateWorkerGlobalScope(WorkerOrWorkletGlobalScope*) override;
+ void DidInitializeWorkerContext() override;
+ void DidLoadInstalledScript(
+ const ContentSecurityPolicyResponseHeaders&,
+ const String& referrer_policy_on_worker_thread) override;
+ void WillEvaluateClassicScript(size_t script_size,
+ size_t cached_metadata_size) override;
+ void WillEvaluateImportedClassicScript(size_t script_size,
+ size_t cached_metadata_size) override;
+ void DidEvaluateClassicScript(bool success) override;
+ void DidCloseWorkerGlobalScope() override;
+ void WillDestroyWorkerGlobalScope() override;
+ void DidTerminateWorkerThread() override;
+
+ void Trace(blink::Visitor*);
+
+ // Detaches this proxy object entirely from the outside world, clearing out
+ // all references.
+ //
+ // It is called on the main thread during WebEmbeddedWorkerImpl finalization
+ // _after_ the worker thread using the proxy has been terminated.
+ void Detach();
+
+ void TerminateWorkerContext();
+
+ private:
+ ServiceWorkerGlobalScopeProxy(WebEmbeddedWorkerImpl&,
+ WebServiceWorkerContextClient&);
+
+ WebServiceWorkerContextClient& Client() const;
+ ServiceWorkerGlobalScope* WorkerGlobalScope() const;
+
+ // Non-null until the WebEmbeddedWorkerImpl explicitly detach()es
+ // as part of its finalization.
+ WebEmbeddedWorkerImpl* embedded_worker_;
+
+ Member<ParentExecutionContextTaskRunners>
+ parent_execution_context_task_runners_;
+
+ // The worker thread uses this map to track |FetchEvent|s created
+ // on the worker thread (heap.) But as the proxy object is created
+ // on the main thread & its heap, we must use a cross-heap reference
+ // to each |FetchEvent| so as to obey the "per-thread heap rule" that
+ // a heap should only have per-thread heap references. Keeping a
+ // cross-heap reference requires the use of a CrossThreadPersistent<>
+ // to remain safe and sound.
+ //
+ HashMap<int, CrossThreadPersistent<FetchEvent>> pending_preload_fetch_events_;
+
+ WebServiceWorkerContextClient* client_;
+
+ CrossThreadPersistent<ServiceWorkerGlobalScope> worker_global_scope_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerGlobalScopeProxy);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_GLOBAL_SCOPE_PROXY_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc
new file mode 100644
index 00000000000..8138d1b4290
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.cc
@@ -0,0 +1,71 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.h"
+
+#include <memory>
+#include <utility>
+
+#include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_thread.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
+
+namespace blink {
+
+ServiceWorkerInstalledScriptsManager::ServiceWorkerInstalledScriptsManager(
+ std::unique_ptr<WebServiceWorkerInstalledScriptsManager> manager)
+ : manager_(std::move(manager)) {
+ DCHECK(manager_);
+}
+
+bool ServiceWorkerInstalledScriptsManager::IsScriptInstalled(
+ const KURL& script_url) const {
+ return manager_->IsScriptInstalled(script_url);
+}
+
+InstalledScriptsManager::ScriptStatus
+ServiceWorkerInstalledScriptsManager::GetScriptData(
+ const KURL& script_url,
+ InstalledScriptsManager::ScriptData* out_script_data) {
+ DCHECK(!IsMainThread());
+ // This blocks until the script is received from the browser.
+ std::unique_ptr<WebServiceWorkerInstalledScriptsManager::RawScriptData>
+ raw_script_data = manager_->GetRawScriptData(script_url);
+ DCHECK(raw_script_data);
+ if (!raw_script_data->IsValid()) {
+ *out_script_data = InstalledScriptsManager::ScriptData();
+ return ScriptStatus::kFailed;
+ }
+
+ // This is from WorkerClassicScriptLoader::DidReceiveData.
+ std::unique_ptr<TextResourceDecoder> decoder =
+ TextResourceDecoder::Create(TextResourceDecoderOptions(
+ TextResourceDecoderOptions::kPlainTextContent,
+ raw_script_data->Encoding().IsEmpty()
+ ? UTF8Encoding()
+ : WTF::TextEncoding(raw_script_data->Encoding())));
+
+ StringBuilder source_text_builder;
+ for (const auto& chunk : raw_script_data->ScriptTextChunks())
+ source_text_builder.Append(decoder->Decode(chunk.Data(), chunk.size()));
+
+ std::unique_ptr<Vector<char>> meta_data;
+ if (raw_script_data->MetaDataChunks().size() > 0) {
+ size_t total_metadata_size = 0;
+ for (const auto& chunk : raw_script_data->MetaDataChunks())
+ total_metadata_size += chunk.size();
+ meta_data = std::make_unique<Vector<char>>();
+ meta_data->ReserveInitialCapacity(total_metadata_size);
+ for (const auto& chunk : raw_script_data->MetaDataChunks())
+ meta_data->Append(chunk.Data(), chunk.size());
+ }
+
+ InstalledScriptsManager::ScriptData script_data(
+ script_url, source_text_builder.ToString(), std::move(meta_data),
+ raw_script_data->TakeHeaders());
+ *out_script_data = std::move(script_data);
+ return ScriptStatus::kSuccess;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.h
new file mode 100644
index 00000000000..91e909807ca
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.h
@@ -0,0 +1,33 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_INSTALLED_SCRIPTS_MANAGER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_INSTALLED_SCRIPTS_MANAGER_H_
+
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_installed_scripts_manager.h"
+#include "third_party/blink/renderer/core/workers/installed_scripts_manager.h"
+
+namespace blink {
+
+// ServiceWorkerInstalledScriptsManager provides the main script and imported
+// scripts of an installed service worker. The scripts are streamed from the
+// browser process in parallel with worker thread initialization.
+class ServiceWorkerInstalledScriptsManager final
+ : public InstalledScriptsManager {
+ public:
+ explicit ServiceWorkerInstalledScriptsManager(
+ std::unique_ptr<WebServiceWorkerInstalledScriptsManager>);
+
+ // InstalledScriptsManager implementation.
+ bool IsScriptInstalled(const KURL& script_url) const override;
+ ScriptStatus GetScriptData(const KURL& script_url,
+ ScriptData* out_script_data) override;
+
+ private:
+ std::unique_ptr<WebServiceWorkerInstalledScriptsManager> manager_;
+};
+
+} // namespace blink
+
+#endif // WorkerInstalledScriptsManager_h
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_registration.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_registration.cc
new file mode 100644
index 00000000000..eb4d7c6b4bc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_registration.cc
@@ -0,0 +1,184 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/memory/ptr_util.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom-blink.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider.h"
+#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#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/modules/event_target_modules.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_container_client.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_error.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
+
+namespace blink {
+
+ServiceWorkerRegistration* ServiceWorkerRegistration::Take(
+ ScriptPromiseResolver* resolver,
+ std::unique_ptr<WebServiceWorkerRegistration::Handle> handle) {
+ return GetOrCreate(resolver->GetExecutionContext(), std::move(handle));
+}
+
+bool ServiceWorkerRegistration::HasPendingActivity() const {
+ return !stopped_;
+}
+
+const AtomicString& ServiceWorkerRegistration::InterfaceName() const {
+ return EventTargetNames::ServiceWorkerRegistration;
+}
+
+void ServiceWorkerRegistration::DispatchUpdateFoundEvent() {
+ DispatchEvent(Event::Create(EventTypeNames::updatefound));
+}
+
+void ServiceWorkerRegistration::SetInstalling(
+ std::unique_ptr<WebServiceWorker::Handle> handle) {
+ if (!GetExecutionContext())
+ return;
+ installing_ = ServiceWorker::From(GetExecutionContext(),
+ base::WrapUnique(handle.release()));
+}
+
+void ServiceWorkerRegistration::SetWaiting(
+ std::unique_ptr<WebServiceWorker::Handle> handle) {
+ if (!GetExecutionContext())
+ return;
+ waiting_ = ServiceWorker::From(GetExecutionContext(),
+ base::WrapUnique(handle.release()));
+}
+
+void ServiceWorkerRegistration::SetActive(
+ std::unique_ptr<WebServiceWorker::Handle> handle) {
+ if (!GetExecutionContext())
+ return;
+ active_ = ServiceWorker::From(GetExecutionContext(),
+ base::WrapUnique(handle.release()));
+}
+
+ServiceWorkerRegistration* ServiceWorkerRegistration::GetOrCreate(
+ ExecutionContext* execution_context,
+ std::unique_ptr<WebServiceWorkerRegistration::Handle> handle) {
+ DCHECK(handle);
+
+ ServiceWorkerRegistration* existing_registration =
+ static_cast<ServiceWorkerRegistration*>(handle->Registration()->Proxy());
+ if (existing_registration) {
+ DCHECK_EQ(existing_registration->GetExecutionContext(), execution_context);
+ return existing_registration;
+ }
+
+ return new ServiceWorkerRegistration(execution_context, std::move(handle));
+}
+
+NavigationPreloadManager* ServiceWorkerRegistration::navigationPreload() {
+ if (!navigation_preload_)
+ navigation_preload_ = NavigationPreloadManager::Create(this);
+ return navigation_preload_;
+}
+
+String ServiceWorkerRegistration::scope() const {
+ return handle_->Registration()->Scope().GetString();
+}
+
+String ServiceWorkerRegistration::updateViaCache() const {
+ switch (handle_->Registration()->UpdateViaCache()) {
+ case mojom::ServiceWorkerUpdateViaCache::kImports:
+ return "imports";
+ case mojom::ServiceWorkerUpdateViaCache::kAll:
+ return "all";
+ case mojom::ServiceWorkerUpdateViaCache::kNone:
+ return "none";
+ }
+ NOTREACHED();
+ return "";
+}
+
+ScriptPromise ServiceWorkerRegistration::update(ScriptState* script_state) {
+ ServiceWorkerContainerClient* client =
+ ServiceWorkerContainerClient::From(GetExecutionContext());
+ if (!client || !client->Provider()) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state,
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Failed to update a ServiceWorkerRegistration: No "
+ "associated provider is available."));
+ }
+
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+ ScriptPromise promise = resolver->Promise();
+ handle_->Registration()->Update(
+ std::make_unique<CallbackPromiseAdapter<ServiceWorkerRegistration,
+ ServiceWorkerErrorForUpdate>>(
+ resolver));
+ return promise;
+}
+
+ScriptPromise ServiceWorkerRegistration::unregister(ScriptState* script_state) {
+ ServiceWorkerContainerClient* client =
+ ServiceWorkerContainerClient::From(GetExecutionContext());
+ if (!client || !client->Provider()) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state,
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Failed to unregister a "
+ "ServiceWorkerRegistration: No "
+ "associated provider is available."));
+ }
+
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+ ScriptPromise promise = resolver->Promise();
+ handle_->Registration()->Unregister(
+ std::make_unique<CallbackPromiseAdapter<bool, ServiceWorkerError>>(
+ resolver));
+ return promise;
+}
+
+ServiceWorkerRegistration::ServiceWorkerRegistration(
+ ExecutionContext* execution_context,
+ std::unique_ptr<WebServiceWorkerRegistration::Handle> handle)
+ : ContextLifecycleObserver(execution_context),
+ handle_(std::move(handle)),
+ stopped_(false) {
+ DCHECK(handle_);
+ DCHECK(!handle_->Registration()->Proxy());
+
+ if (!execution_context)
+ return;
+ handle_->Registration()->SetProxy(this);
+}
+
+ServiceWorkerRegistration::~ServiceWorkerRegistration() = default;
+
+void ServiceWorkerRegistration::Dispose() {
+ // Promptly clears a raw reference from content/ to an on-heap object
+ // so that content/ doesn't access it in a lazy sweeping phase.
+ handle_.reset();
+}
+
+void ServiceWorkerRegistration::Trace(blink::Visitor* visitor) {
+ visitor->Trace(installing_);
+ visitor->Trace(waiting_);
+ visitor->Trace(active_);
+ visitor->Trace(navigation_preload_);
+ EventTargetWithInlineData::Trace(visitor);
+ ContextLifecycleObserver::Trace(visitor);
+ Supplementable<ServiceWorkerRegistration>::Trace(visitor);
+}
+
+void ServiceWorkerRegistration::ContextDestroyed(ExecutionContext*) {
+ if (stopped_)
+ return;
+ stopped_ = true;
+ handle_->Registration()->ProxyStopped();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_registration.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_registration.h
new file mode 100644
index 00000000000..fbb096a32ad
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_registration.h
@@ -0,0 +1,129 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_H_
+
+#include <memory>
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_registration.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_registration_proxy.h"
+#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/core/dom/events/event_target.h"
+#include "third_party/blink/renderer/modules/service_worker/navigation_preload_manager.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace blink {
+
+class ScriptPromise;
+class ScriptState;
+
+// The implementation of a service worker registration object in Blink. Actual
+// registration representation is in the embedder and this class accesses it
+// via WebServiceWorkerRegistration::Handle object.
+class ServiceWorkerRegistration final
+ : public EventTargetWithInlineData,
+ public ActiveScriptWrappable<ServiceWorkerRegistration>,
+ public ContextLifecycleObserver,
+ public WebServiceWorkerRegistrationProxy,
+ public Supplementable<ServiceWorkerRegistration> {
+ DEFINE_WRAPPERTYPEINFO();
+ USING_GARBAGE_COLLECTED_MIXIN(ServiceWorkerRegistration);
+ USING_PRE_FINALIZER(ServiceWorkerRegistration, Dispose);
+
+ public:
+ // Called from CallbackPromiseAdapter.
+ using WebType = std::unique_ptr<WebServiceWorkerRegistration::Handle>;
+ static ServiceWorkerRegistration* Take(
+ ScriptPromiseResolver*,
+ std::unique_ptr<WebServiceWorkerRegistration::Handle>);
+
+ // ScriptWrappable overrides.
+ bool HasPendingActivity() const final;
+
+ // EventTarget overrides.
+ const AtomicString& InterfaceName() const override;
+ ExecutionContext* GetExecutionContext() const override {
+ return ContextLifecycleObserver::GetExecutionContext();
+ }
+
+ // WebServiceWorkerRegistrationProxy overrides.
+ void DispatchUpdateFoundEvent() override;
+ void SetInstalling(std::unique_ptr<WebServiceWorker::Handle>) override;
+ void SetWaiting(std::unique_ptr<WebServiceWorker::Handle>) override;
+ void SetActive(std::unique_ptr<WebServiceWorker::Handle>) override;
+
+ // Returns an existing registration object for the handle if it exists.
+ // Otherwise, returns a new registration object.
+ static ServiceWorkerRegistration* GetOrCreate(
+ ExecutionContext*,
+ std::unique_ptr<WebServiceWorkerRegistration::Handle>);
+
+ ServiceWorker* installing() { return installing_; }
+ ServiceWorker* waiting() { return waiting_; }
+ ServiceWorker* active() { return active_; }
+ NavigationPreloadManager* navigationPreload();
+
+ String scope() const;
+ String updateViaCache() const;
+
+ WebServiceWorkerRegistration* WebRegistration() {
+ return handle_->Registration();
+ }
+
+ ScriptPromise update(ScriptState*);
+ ScriptPromise unregister(ScriptState*);
+
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(updatefound);
+
+ ~ServiceWorkerRegistration() override;
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ ServiceWorkerRegistration(
+ ExecutionContext*,
+ std::unique_ptr<WebServiceWorkerRegistration::Handle>);
+ void Dispose();
+
+ // ContextLifecycleObserver overrides.
+ void ContextDestroyed(ExecutionContext*) override;
+
+ // A handle to the registration representation in the embedder.
+ std::unique_ptr<WebServiceWorkerRegistration::Handle> handle_;
+
+ Member<ServiceWorker> installing_;
+ Member<ServiceWorker> waiting_;
+ Member<ServiceWorker> active_;
+ Member<NavigationPreloadManager> navigation_preload_;
+
+ bool stopped_;
+};
+
+class ServiceWorkerRegistrationArray {
+ STATIC_ONLY(ServiceWorkerRegistrationArray);
+
+ public:
+ // Called from CallbackPromiseAdapter.
+ using WebType = std::unique_ptr<
+ WebVector<std::unique_ptr<WebServiceWorkerRegistration::Handle>>>;
+ static HeapVector<Member<ServiceWorkerRegistration>> Take(
+ ScriptPromiseResolver* resolver,
+ WebType web_service_worker_registrations) {
+ HeapVector<Member<ServiceWorkerRegistration>> registrations;
+ for (auto& registration : *web_service_worker_registrations) {
+ registrations.push_back(
+ ServiceWorkerRegistration::Take(resolver, std::move(registration)));
+ }
+ return registrations;
+ }
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_registration.idl b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_registration.idl
new file mode 100644
index 00000000000..a50faeb704d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_registration.idl
@@ -0,0 +1,32 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://w3c.github.io/ServiceWorker/#enumdef-serviceworkerupdateviacache
+[
+ RuntimeEnabled=ServiceWorkerUpdateViaCache
+] enum ServiceWorkerUpdateViaCache {
+ "imports",
+ "all",
+ "none"
+};
+
+// https://w3c.github.io/ServiceWorker/#serviceworkerregistration-interface
+[
+ ActiveScriptWrappable,
+ SecureContext,
+ Exposed=(Window,Worker)
+] interface ServiceWorkerRegistration : EventTarget {
+ readonly attribute ServiceWorker? installing;
+ readonly attribute ServiceWorker? waiting;
+ readonly attribute ServiceWorker? active;
+ readonly attribute NavigationPreloadManager navigationPreload;
+
+ readonly attribute USVString scope;
+ [RuntimeEnabled=ServiceWorkerUpdateViaCache] readonly attribute ServiceWorkerUpdateViaCache updateViaCache;
+
+ [CallWith=ScriptState] Promise<ServiceWorkerRegistration> update();
+ [CallWith=ScriptState] Promise<boolean> unregister();
+
+ attribute EventHandler onupdatefound;
+};
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.cc
new file mode 100644
index 00000000000..5d06b1c74c6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.cc
@@ -0,0 +1,72 @@
+// 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/modules/service_worker/service_worker_script_cached_metadata_handler.h"
+
+#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h"
+#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
+
+namespace blink {
+
+ServiceWorkerScriptCachedMetadataHandler::
+ ServiceWorkerScriptCachedMetadataHandler(
+ WorkerGlobalScope* worker_global_scope,
+ const KURL& script_url,
+ const Vector<char>* meta_data)
+ : worker_global_scope_(worker_global_scope), script_url_(script_url) {
+ if (meta_data)
+ cached_metadata_ = CachedMetadata::CreateFromSerializedData(
+ meta_data->data(), meta_data->size());
+}
+
+ServiceWorkerScriptCachedMetadataHandler::
+ ~ServiceWorkerScriptCachedMetadataHandler() = default;
+
+void ServiceWorkerScriptCachedMetadataHandler::Trace(blink::Visitor* visitor) {
+ visitor->Trace(worker_global_scope_);
+ CachedMetadataHandler::Trace(visitor);
+}
+
+void ServiceWorkerScriptCachedMetadataHandler::SetCachedMetadata(
+ uint32_t data_type_id,
+ const char* data,
+ size_t size,
+ CacheType type) {
+ if (type != kSendToPlatform)
+ return;
+ cached_metadata_ = CachedMetadata::Create(data_type_id, data, size);
+ const Vector<char>& serialized_data = cached_metadata_->SerializedData();
+ ServiceWorkerGlobalScopeClient::From(worker_global_scope_)
+ ->SetCachedMetadata(script_url_, serialized_data.data(),
+ serialized_data.size());
+}
+
+void ServiceWorkerScriptCachedMetadataHandler::ClearCachedMetadata(
+ CacheType type) {
+ if (type != kSendToPlatform)
+ return;
+ cached_metadata_ = nullptr;
+ ServiceWorkerGlobalScopeClient::From(worker_global_scope_)
+ ->ClearCachedMetadata(script_url_);
+}
+
+scoped_refptr<CachedMetadata>
+ServiceWorkerScriptCachedMetadataHandler::GetCachedMetadata(
+ uint32_t data_type_id) const {
+ if (!cached_metadata_ || cached_metadata_->DataTypeID() != data_type_id)
+ return nullptr;
+ return cached_metadata_;
+}
+
+String ServiceWorkerScriptCachedMetadataHandler::Encoding() const {
+ return g_empty_string;
+}
+
+bool ServiceWorkerScriptCachedMetadataHandler::IsServedFromCacheStorage()
+ const {
+ return false;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.h
new file mode 100644
index 00000000000..cea3dafcad6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_script_cached_metadata_handler.h
@@ -0,0 +1,53 @@
+// 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_MODULES_SERVICE_WORKER_SERVICE_WORKER_SCRIPT_CACHED_METADATA_HANDLER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_SCRIPT_CACHED_METADATA_HANDLER_H_
+
+#include <stdint.h>
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+class WorkerGlobalScope;
+class CachedMetadata;
+
+class ServiceWorkerScriptCachedMetadataHandler
+ : public SingleCachedMetadataHandler {
+ public:
+ static ServiceWorkerScriptCachedMetadataHandler* Create(
+ WorkerGlobalScope* worker_global_scope,
+ const KURL& script_url,
+ const Vector<char>* meta_data) {
+ return new ServiceWorkerScriptCachedMetadataHandler(worker_global_scope,
+ script_url, meta_data);
+ }
+ ~ServiceWorkerScriptCachedMetadataHandler() override;
+ void Trace(blink::Visitor*) override;
+ void SetCachedMetadata(uint32_t data_type_id,
+ const char*,
+ size_t,
+ CacheType) override;
+ void ClearCachedMetadata(CacheType) override;
+ scoped_refptr<CachedMetadata> GetCachedMetadata(
+ uint32_t data_type_id) const override;
+ String Encoding() const override;
+ bool IsServedFromCacheStorage() const override;
+
+ private:
+ ServiceWorkerScriptCachedMetadataHandler(WorkerGlobalScope*,
+ const KURL& script_url,
+ const Vector<char>* meta_data);
+
+ Member<WorkerGlobalScope> worker_global_scope_;
+ KURL script_url_;
+ scoped_refptr<CachedMetadata> cached_metadata_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_SCRIPT_CACHED_METADATA_HANDLER_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.cc
new file mode 100644
index 00000000000..6c0099605f6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.cc
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * 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/modules/service_worker/service_worker_thread.h"
+
+#include <memory>
+
+#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
+#include "third_party/blink/renderer/core/workers/worker_backing_thread.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.h"
+
+namespace blink {
+
+ServiceWorkerThread::ServiceWorkerThread(
+ ThreadableLoadingContext* loading_context,
+ ServiceWorkerGlobalScopeProxy* global_scope_proxy,
+ std::unique_ptr<ServiceWorkerInstalledScriptsManager>
+ installed_scripts_manager,
+ mojom::blink::CacheStoragePtrInfo cache_storage_info)
+ : WorkerThread(loading_context, *global_scope_proxy),
+ global_scope_proxy_(global_scope_proxy),
+ worker_backing_thread_(WorkerBackingThread::Create(
+ WebThreadCreationParams(GetThreadType()))),
+ installed_scripts_manager_(std::move(installed_scripts_manager)),
+ cache_storage_info_(std::move(cache_storage_info)) {}
+
+ServiceWorkerThread::~ServiceWorkerThread() {
+ global_scope_proxy_->Detach();
+}
+
+void ServiceWorkerThread::ClearWorkerBackingThread() {
+ worker_backing_thread_ = nullptr;
+}
+
+InstalledScriptsManager* ServiceWorkerThread::GetInstalledScriptsManager() {
+ return installed_scripts_manager_.get();
+}
+
+void ServiceWorkerThread::TerminateForTesting() {
+ global_scope_proxy_->TerminateWorkerContext();
+ WorkerThread::TerminateForTesting();
+}
+
+WorkerOrWorkletGlobalScope* ServiceWorkerThread::CreateWorkerGlobalScope(
+ std::unique_ptr<GlobalScopeCreationParams> creation_params) {
+ return ServiceWorkerGlobalScope::Create(this, std::move(creation_params),
+ std::move(cache_storage_info_),
+ time_origin_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.h
new file mode 100644
index 00000000000..ddff0041540
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_thread.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * 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_MODULES_SERVICE_WORKER_SERVICE_WORKER_THREAD_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_THREAD_H_
+
+#include <memory>
+#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom-blink.h"
+#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
+#include "third_party/blink/renderer/core/workers/worker_thread.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+
+namespace blink {
+
+class ServiceWorkerGlobalScopeProxy;
+class ServiceWorkerInstalledScriptsManager;
+struct GlobalScopeCreationParams;
+
+// ServiceWorkerThread is an implementation of WorkerThread for service workers.
+// This provides a backing thread and an installed scripts manager.
+class MODULES_EXPORT ServiceWorkerThread final : public WorkerThread {
+ public:
+ // ServiceWorkerThread owns a given ServiceWorkerGlobalScopeProxy via
+ // Persistent.
+ ServiceWorkerThread(ThreadableLoadingContext*,
+ ServiceWorkerGlobalScopeProxy*,
+ std::unique_ptr<ServiceWorkerInstalledScriptsManager>,
+ mojom::blink::CacheStoragePtrInfo cache_storage_info);
+ ~ServiceWorkerThread() override;
+
+ WorkerBackingThread& GetWorkerBackingThread() override {
+ return *worker_backing_thread_;
+ }
+ void ClearWorkerBackingThread() override;
+ InstalledScriptsManager* GetInstalledScriptsManager() override;
+ void TerminateForTesting() override;
+
+ private:
+ WorkerOrWorkletGlobalScope* CreateWorkerGlobalScope(
+ std::unique_ptr<GlobalScopeCreationParams>) override;
+
+ WebThreadType GetThreadType() const override {
+ return WebThreadType::kServiceWorkerThread;
+ }
+
+ Persistent<ServiceWorkerGlobalScopeProxy> global_scope_proxy_;
+ std::unique_ptr<WorkerBackingThread> worker_backing_thread_;
+ std::unique_ptr<ServiceWorkerInstalledScriptsManager>
+ installed_scripts_manager_;
+ mojom::blink::CacheStoragePtrInfo cache_storage_info_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_THREAD_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client.cc
new file mode 100644
index 00000000000..d3849e40e7e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client.cc
@@ -0,0 +1,94 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/service_worker/service_worker_window_client.h"
+
+#include <memory>
+#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/page/page_visibility_state.h"
+#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
+#include "third_party/blink/renderer/core/workers/worker_location.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_error.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_window_client_callback.h"
+#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
+
+namespace blink {
+
+ServiceWorkerWindowClient* ServiceWorkerWindowClient::Take(
+ ScriptPromiseResolver*,
+ std::unique_ptr<WebServiceWorkerClientInfo> web_client) {
+ return web_client ? ServiceWorkerWindowClient::Create(*web_client) : nullptr;
+}
+
+ServiceWorkerWindowClient* ServiceWorkerWindowClient::Create(
+ const WebServiceWorkerClientInfo& info) {
+ return new ServiceWorkerWindowClient(info);
+}
+
+ServiceWorkerWindowClient::ServiceWorkerWindowClient(
+ const WebServiceWorkerClientInfo& info)
+ : ServiceWorkerClient(info),
+ page_visibility_state_(info.page_visibility_state),
+ is_focused_(info.is_focused) {}
+
+ServiceWorkerWindowClient::~ServiceWorkerWindowClient() = default;
+
+String ServiceWorkerWindowClient::visibilityState() const {
+ return PageVisibilityStateString(page_visibility_state_);
+}
+
+ScriptPromise ServiceWorkerWindowClient::focus(ScriptState* script_state) {
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ if (!ExecutionContext::From(script_state)->IsWindowInteractionAllowed()) {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kInvalidAccessError,
+ "Not allowed to focus a window."));
+ return promise;
+ }
+ ExecutionContext::From(script_state)->ConsumeWindowInteraction();
+
+ ServiceWorkerGlobalScopeClient::From(ExecutionContext::From(script_state))
+ ->Focus(Uuid(),
+ std::make_unique<CallbackPromiseAdapter<ServiceWorkerWindowClient,
+ ServiceWorkerError>>(
+ resolver));
+ return promise;
+}
+
+ScriptPromise ServiceWorkerWindowClient::navigate(ScriptState* script_state,
+ const String& url) {
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+ ScriptPromise promise = resolver->Promise();
+ ExecutionContext* context = ExecutionContext::From(script_state);
+
+ KURL parsed_url = KURL(ToWorkerGlobalScope(context)->location()->Url(), url);
+ if (!parsed_url.IsValid() || parsed_url.ProtocolIsAbout()) {
+ resolver->Reject(V8ThrowException::CreateTypeError(
+ script_state->GetIsolate(), "'" + url + "' is not a valid URL."));
+ return promise;
+ }
+ if (!context->GetSecurityOrigin()->CanDisplay(parsed_url)) {
+ resolver->Reject(V8ThrowException::CreateTypeError(
+ script_state->GetIsolate(),
+ "'" + parsed_url.ElidedString() + "' cannot navigate."));
+ return promise;
+ }
+
+ ServiceWorkerGlobalScopeClient::From(context)->Navigate(
+ Uuid(), parsed_url, std::make_unique<NavigateClientCallback>(resolver));
+ return promise;
+}
+
+void ServiceWorkerWindowClient::Trace(blink::Visitor* visitor) {
+ ServiceWorkerClient::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client.h
new file mode 100644
index 00000000000..1b81d633637
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client.h
@@ -0,0 +1,52 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_WINDOW_CLIENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_WINDOW_CLIENT_H_
+
+#include <memory>
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_client.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace blink {
+
+class ScriptPromiseResolver;
+class ScriptState;
+
+class MODULES_EXPORT ServiceWorkerWindowClient final
+ : public ServiceWorkerClient {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ // To be used by CallbackPromiseAdapter.
+ using WebType = std::unique_ptr<WebServiceWorkerClientInfo>;
+
+ static ServiceWorkerWindowClient* Take(
+ ScriptPromiseResolver*,
+ std::unique_ptr<WebServiceWorkerClientInfo>);
+
+ static ServiceWorkerWindowClient* Create(const WebServiceWorkerClientInfo&);
+ ~ServiceWorkerWindowClient() override;
+
+ // WindowClient.idl
+ String visibilityState() const;
+ bool focused() const { return is_focused_; }
+ ScriptPromise focus(ScriptState*);
+ ScriptPromise navigate(ScriptState*, const String& url);
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ explicit ServiceWorkerWindowClient(const WebServiceWorkerClientInfo&);
+
+ mojom::PageVisibilityState page_visibility_state_;
+ bool is_focused_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_WINDOW_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client_callback.cc b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client_callback.cc
new file mode 100644
index 00000000000..2400813dc70
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client_callback.cc
@@ -0,0 +1,43 @@
+// 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/modules/service_worker/service_worker_window_client_callback.h"
+
+#include <memory>
+
+#include "base/memory/ptr_util.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/core/dom/dom_exception.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_error.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_window_client.h"
+#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
+
+namespace blink {
+
+void NavigateClientCallback::OnSuccess(
+ std::unique_ptr<WebServiceWorkerClientInfo> client_info) {
+ if (!resolver_->GetExecutionContext() ||
+ resolver_->GetExecutionContext()->IsContextDestroyed())
+ return;
+ resolver_->Resolve(ServiceWorkerWindowClient::Take(
+ resolver_.Get(), base::WrapUnique(client_info.release())));
+}
+
+void NavigateClientCallback::OnError(const WebServiceWorkerError& error) {
+ if (!resolver_->GetExecutionContext() ||
+ resolver_->GetExecutionContext()->IsContextDestroyed())
+ return;
+
+ if (error.error_type == mojom::blink::ServiceWorkerErrorType::kNavigation) {
+ ScriptState::Scope scope(resolver_->GetScriptState());
+ resolver_->Reject(V8ThrowException::CreateTypeError(
+ resolver_->GetScriptState()->GetIsolate(), error.message));
+ return;
+ }
+
+ resolver_->Reject(ServiceWorkerError::Take(resolver_.Get(), error));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client_callback.h b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client_callback.h
new file mode 100644
index 00000000000..cf82b10dc2e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/service_worker_window_client_callback.h
@@ -0,0 +1,31 @@
+// 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_MODULES_SERVICE_WORKER_SERVICE_WORKER_WINDOW_CLIENT_CALLBACK_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_WINDOW_CLIENT_CALLBACK_H_
+
+#include "base/macros.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_clients_info.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+class ScriptPromiseResolver;
+
+class NavigateClientCallback : public WebServiceWorkerClientCallbacks {
+ public:
+ explicit NavigateClientCallback(ScriptPromiseResolver* resolver)
+ : resolver_(resolver) {}
+
+ void OnSuccess(std::unique_ptr<WebServiceWorkerClientInfo>) override;
+ void OnError(const WebServiceWorkerError&) override;
+
+ private:
+ Persistent<ScriptPromiseResolver> resolver_;
+ DISALLOW_COPY_AND_ASSIGN(NavigateClientCallback);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_SERVICE_WORKER_WINDOW_CLIENT_CALLBACK_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/testing/internals_service_worker.cc b/chromium/third_party/blink/renderer/modules/service_worker/testing/internals_service_worker.cc
new file mode 100644
index 00000000000..0a32f53b399
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/testing/internals_service_worker.cc
@@ -0,0 +1,18 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/service_worker/testing/internals_service_worker.h"
+
+#include "third_party/blink/renderer/modules/service_worker/service_worker.h"
+
+namespace blink {
+
+ScriptPromise InternalsServiceWorker::terminateServiceWorker(
+ ScriptState* script_state,
+ Internals& internals,
+ ServiceWorker* worker) {
+ return worker->InternalsTerminate(script_state);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/testing/internals_service_worker.h b/chromium/third_party/blink/renderer/modules/service_worker/testing/internals_service_worker.h
new file mode 100644
index 00000000000..c765b7b8ae6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/testing/internals_service_worker.h
@@ -0,0 +1,28 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_TESTING_INTERNALS_SERVICE_WORKER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_TESTING_INTERNALS_SERVICE_WORKER_H_
+
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+
+namespace blink {
+
+class Internals;
+class ScriptState;
+class ServiceWorker;
+
+class InternalsServiceWorker {
+ STATIC_ONLY(InternalsServiceWorker);
+
+ public:
+ static ScriptPromise terminateServiceWorker(ScriptState*,
+ Internals&,
+ ServiceWorker*);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_TESTING_INTERNALS_SERVICE_WORKER_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/testing/internals_service_worker.idl b/chromium/third_party/blink/renderer/modules/service_worker/testing/internals_service_worker.idl
index 10d2a62c32a..10d2a62c32a 100644
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/testing/internals_service_worker.idl
+++ b/chromium/third_party/blink/renderer/modules/service_worker/testing/internals_service_worker.idl
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.cc b/chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.cc
new file mode 100644
index 00000000000..7af9c60258e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.cc
@@ -0,0 +1,326 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/service_worker/wait_until_observer.h"
+
+#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom-blink.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h"
+#include "third_party/blink/renderer/platform/bindings/microtask.h"
+#include "third_party/blink/renderer/platform/layout_test_support.h"
+#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+namespace {
+
+// Timeout before a service worker that was given window interaction
+// permission loses them. The unit is seconds.
+const unsigned kWindowInteractionTimeout = 10;
+const unsigned kWindowInteractionTimeoutForTest = 1;
+
+TimeDelta WindowInteractionTimeout() {
+ return TimeDelta::FromSeconds(LayoutTestSupport::IsRunningLayoutTest()
+ ? kWindowInteractionTimeoutForTest
+ : kWindowInteractionTimeout);
+}
+
+} // anonymous namespace
+
+class WaitUntilObserver::ThenFunction final : public ScriptFunction {
+ public:
+ enum ResolveType {
+ kFulfilled,
+ kRejected,
+ };
+
+ static v8::Local<v8::Function> CreateFunction(
+ ScriptState* script_state,
+ WaitUntilObserver* observer,
+ ResolveType type,
+ PromiseSettledCallback callback) {
+ ThenFunction* self =
+ new ThenFunction(script_state, observer, type, std::move(callback));
+ return self->BindToV8Function();
+ }
+
+ void Trace(blink::Visitor* visitor) override {
+ visitor->Trace(observer_);
+ ScriptFunction::Trace(visitor);
+ }
+
+ private:
+ ThenFunction(ScriptState* script_state,
+ WaitUntilObserver* observer,
+ ResolveType type,
+ PromiseSettledCallback callback)
+ : ScriptFunction(script_state),
+ observer_(observer),
+ resolve_type_(type),
+ callback_(std::move(callback)) {}
+
+ ScriptValue Call(ScriptValue value) override {
+ DCHECK(observer_);
+ DCHECK(resolve_type_ == kFulfilled || resolve_type_ == kRejected);
+ if (callback_)
+ callback_.Run(value);
+ // According from step 4 of ExtendableEvent::waitUntil() in spec:
+ // https://w3c.github.io/ServiceWorker/#dom-extendableevent-waituntil
+ // "Upon fulfillment or rejection of f, queue a microtask to run these
+ // substeps: Decrement the pending promises count by one."
+
+ // At this time point the microtask A running resolve/reject function of
+ // this promise has already been queued, in order to allow microtask A to
+ // call waitUntil, we enqueue another microtask B to delay the promise
+ // settled notification to |observer_|, thus A will run before B so A can
+ // call waitUntil well, but any other microtask C possibly enqueued by A
+ // will run after B so C maybe can't call waitUntil if there has no any
+ // extend lifetime promise at that time.
+ if (resolve_type_ == kRejected) {
+ Microtask::EnqueueMicrotask(
+ WTF::Bind(&WaitUntilObserver::OnPromiseRejected,
+ WrapPersistent(observer_.Get())));
+ value =
+ ScriptPromise::Reject(value.GetScriptState(), value).GetScriptValue();
+ } else {
+ Microtask::EnqueueMicrotask(
+ WTF::Bind(&WaitUntilObserver::OnPromiseFulfilled,
+ WrapPersistent(observer_.Get())));
+ }
+ observer_ = nullptr;
+ return value;
+ }
+
+ Member<WaitUntilObserver> observer_;
+ ResolveType resolve_type_;
+ PromiseSettledCallback callback_;
+};
+
+WaitUntilObserver* WaitUntilObserver::Create(ExecutionContext* context,
+ EventType type,
+ int event_id) {
+ return new WaitUntilObserver(context, type, event_id);
+}
+
+void WaitUntilObserver::WillDispatchEvent() {
+ event_dispatch_time_ = WTF::CurrentTime();
+ // When handling a notificationclick or paymentrequest event, we want to
+ // allow one window to be focused or opened. These calls are allowed between
+ // the call to willDispatchEvent() and the last call to
+ // DecrementPendingPromiseCount(). If waitUntil() isn't called, that means
+ // between willDispatchEvent() and didDispatchEvent().
+ if (type_ == kNotificationClick || type_ == kPaymentRequest)
+ execution_context_->AllowWindowInteraction();
+
+ DCHECK_EQ(EventDispatchState::kInitial, event_dispatch_state_);
+ event_dispatch_state_ = EventDispatchState::kDispatching;
+}
+
+void WaitUntilObserver::DidDispatchEvent(bool event_dispatch_failed) {
+ event_dispatch_state_ = event_dispatch_failed
+ ? EventDispatchState::kFailed
+ : EventDispatchState::kDispatched;
+ MaybeCompleteEvent();
+}
+
+void WaitUntilObserver::WaitUntil(ScriptState* script_state,
+ ScriptPromise script_promise,
+ ExceptionState& exception_state,
+ PromiseSettledCallback on_promise_fulfilled,
+ PromiseSettledCallback on_promise_rejected) {
+ if (pending_promises_ == 0) {
+ switch (event_dispatch_state_) {
+ case EventDispatchState::kInitial:
+ NOTREACHED();
+ return;
+ case EventDispatchState::kDispatching:
+ if (!v8::MicrotasksScope::IsRunningMicrotasks(
+ script_state->GetIsolate())) {
+ break;
+ }
+ // didDispatchEvent() is called after both the event handler
+ // execution finished and microtasks queued by the event handler execution
+ // finished, it's hard to get the precise time point between the 2
+ // execution phases.
+ // So even in EventDispatchState::kDispatching state at this time point,
+ // running microtask indicates that event handler execution has actually
+ // finished, in such case if there aren't any outstanding extend lifetime
+ // promises, we should throw here.
+ FALLTHROUGH;
+ case EventDispatchState::kDispatched:
+ case EventDispatchState::kFailed:
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kInvalidStateError,
+ "The event handler is already finished "
+ "and no extend lifetime promises are "
+ "outstanding.");
+ return;
+ }
+ }
+
+ if (!execution_context_)
+ return;
+
+ // When handling a notificationclick event, we want to allow one window to
+ // be focused or opened. See comments in ::willDispatchEvent(). When
+ // waitUntil() is being used, opening or closing a window must happen in a
+ // timeframe specified by windowInteractionTimeout(), otherwise the calls
+ // will fail.
+ if (type_ == kNotificationClick) {
+ consume_window_interaction_timer_.StartOneShot(WindowInteractionTimeout(),
+ FROM_HERE);
+ }
+
+ IncrementPendingPromiseCount();
+ script_promise.Then(
+ ThenFunction::CreateFunction(script_state, this, ThenFunction::kFulfilled,
+ std::move(on_promise_fulfilled)),
+ ThenFunction::CreateFunction(script_state, this, ThenFunction::kRejected,
+ std::move(on_promise_rejected)));
+}
+
+WaitUntilObserver::WaitUntilObserver(ExecutionContext* context,
+ EventType type,
+ int event_id)
+ : execution_context_(context),
+ type_(type),
+ event_id_(event_id),
+ consume_window_interaction_timer_(
+ Platform::Current()->CurrentThread()->GetTaskRunner(),
+ this,
+ &WaitUntilObserver::ConsumeWindowInteraction) {}
+
+void WaitUntilObserver::OnPromiseFulfilled() {
+ DecrementPendingPromiseCount();
+}
+
+void WaitUntilObserver::OnPromiseRejected() {
+ has_rejected_promise_ = true;
+ DecrementPendingPromiseCount();
+}
+
+void WaitUntilObserver::IncrementPendingPromiseCount() {
+ ++pending_promises_;
+}
+
+void WaitUntilObserver::DecrementPendingPromiseCount() {
+ DCHECK_GT(pending_promises_, 0);
+ --pending_promises_;
+ MaybeCompleteEvent();
+}
+
+void WaitUntilObserver::MaybeCompleteEvent() {
+ if (!execution_context_)
+ return;
+
+ switch (event_dispatch_state_) {
+ case EventDispatchState::kInitial:
+ NOTREACHED();
+ return;
+ case EventDispatchState::kDispatching:
+ // Still dispatching, do not complete the event.
+ return;
+ case EventDispatchState::kDispatched:
+ // Still waiting for a promise, do not complete the event.
+ if (pending_promises_ != 0)
+ return;
+ // Dispatch finished and there are no pending promises, complete the
+ // event.
+ break;
+ case EventDispatchState::kFailed:
+ // Dispatch had some error, complete the event immediatelly.
+ break;
+ }
+
+ ServiceWorkerGlobalScopeClient* client =
+ ServiceWorkerGlobalScopeClient::From(execution_context_);
+ mojom::ServiceWorkerEventStatus status =
+ (event_dispatch_state_ == EventDispatchState::kFailed ||
+ has_rejected_promise_)
+ ? mojom::ServiceWorkerEventStatus::REJECTED
+ : mojom::ServiceWorkerEventStatus::COMPLETED;
+ switch (type_) {
+ case kAbortPayment:
+ client->DidHandleAbortPaymentEvent(event_id_, status,
+ event_dispatch_time_);
+ break;
+ case kActivate:
+ client->DidHandleActivateEvent(event_id_, status, event_dispatch_time_);
+ break;
+ case kCanMakePayment:
+ client->DidHandleCanMakePaymentEvent(event_id_, status,
+ event_dispatch_time_);
+ break;
+ case kCookieChange:
+ client->DidHandleCookieChangeEvent(event_id_, status,
+ event_dispatch_time_);
+ break;
+ case kFetch:
+ client->DidHandleFetchEvent(event_id_, status, event_dispatch_time_);
+ break;
+ case kInstall:
+ ToServiceWorkerGlobalScope(execution_context_)->SetIsInstalling(false);
+ client->DidHandleInstallEvent(event_id_, status, event_dispatch_time_);
+ break;
+ case kMessage:
+ client->DidHandleExtendableMessageEvent(event_id_, status,
+ event_dispatch_time_);
+ break;
+ case kNotificationClick:
+ client->DidHandleNotificationClickEvent(event_id_, status,
+ event_dispatch_time_);
+ consume_window_interaction_timer_.Stop();
+ ConsumeWindowInteraction(nullptr);
+ break;
+ case kNotificationClose:
+ client->DidHandleNotificationCloseEvent(event_id_, status,
+ event_dispatch_time_);
+ break;
+ case kPush:
+ client->DidHandlePushEvent(event_id_, status, event_dispatch_time_);
+ break;
+ case kSync:
+ client->DidHandleSyncEvent(event_id_, status, event_dispatch_time_);
+ break;
+ case kPaymentRequest:
+ client->DidHandlePaymentRequestEvent(event_id_, status,
+ event_dispatch_time_);
+ break;
+ case kBackgroundFetchAbort:
+ client->DidHandleBackgroundFetchAbortEvent(event_id_, status,
+ event_dispatch_time_);
+ break;
+ case kBackgroundFetchClick:
+ client->DidHandleBackgroundFetchClickEvent(event_id_, status,
+ event_dispatch_time_);
+ break;
+ case kBackgroundFetchFail:
+ client->DidHandleBackgroundFetchFailEvent(event_id_, status,
+ event_dispatch_time_);
+ break;
+ case kBackgroundFetched:
+ client->DidHandleBackgroundFetchedEvent(event_id_, status,
+ event_dispatch_time_);
+ break;
+ }
+ execution_context_ = nullptr;
+}
+
+void WaitUntilObserver::ConsumeWindowInteraction(TimerBase*) {
+ if (!execution_context_)
+ return;
+ execution_context_->ConsumeWindowInteraction();
+}
+
+void WaitUntilObserver::Trace(blink::Visitor* visitor) {
+ visitor->Trace(execution_context_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.h b/chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.h
new file mode 100644
index 00000000000..f602d983f66
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/wait_until_observer.h
@@ -0,0 +1,119 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_WAIT_UNTIL_OBSERVER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_WAIT_UNTIL_OBSERVER_H_
+
+#include "base/callback.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/modules/service_worker/service_worker_global_scope_client.h"
+#include "third_party/blink/renderer/platform/timer.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace blink {
+
+class ExceptionState;
+class ExecutionContext;
+class ScriptPromise;
+class ScriptState;
+class ScriptValue;
+
+// Created for each ExtendableEvent instance.
+class MODULES_EXPORT WaitUntilObserver final
+ : public GarbageCollectedFinalized<WaitUntilObserver> {
+ public:
+ using PromiseSettledCallback =
+ base::RepeatingCallback<void(const ScriptValue&)>;
+
+ enum EventType {
+ kAbortPayment,
+ kActivate,
+ kCanMakePayment,
+ kCookieChange,
+ kFetch,
+ kInstall,
+ kMessage,
+ kNotificationClick,
+ kNotificationClose,
+ kPaymentRequest,
+ kPush,
+ kSync,
+ kBackgroundFetchAbort,
+ kBackgroundFetchClick,
+ kBackgroundFetchFail,
+ kBackgroundFetched
+ };
+
+ static WaitUntilObserver* Create(ExecutionContext*, EventType, int event_id);
+
+ // Must be called before dispatching the event.
+ void WillDispatchEvent();
+ // Must be called after dispatching the event. If |event_dispatch_failed| is
+ // true, then DidDispatchEvent() immediately reports to
+ // ServiceWorkerGlobalScopeClient that the event finished, without waiting for
+ // all waitUntil promises to settle.
+ void DidDispatchEvent(bool event_dispatch_failed);
+
+ // Observes the promise and delays reporting to ServiceWorkerGlobalScopeClient
+ // that the event completed until the given promise is resolved or rejected.
+ // WaitUntil may be called multiple times. The event is extended until all
+ // promises have settled.
+ // If provided, |on_promise_fulfilled| or |on_promise_rejected| is invoked
+ // once |script_promise| fulfills or rejects. This enables the caller to do
+ // custom handling.
+ void WaitUntil(
+ ScriptState*,
+ ScriptPromise /* script_promise */,
+ ExceptionState&,
+ PromiseSettledCallback on_promise_fulfilled = PromiseSettledCallback(),
+ PromiseSettledCallback on_promise_rejected = PromiseSettledCallback());
+
+ virtual void Trace(blink::Visitor*);
+
+ private:
+ friend class InternalsServiceWorker;
+ class ThenFunction;
+
+ enum class EventDispatchState {
+ // Event dispatch has not yet started.
+ kInitial,
+ // Event dispatch has started but not yet finished.
+ kDispatching,
+ // Event dispatch completed. There may still be outstanding waitUntil
+ // promises that must settle before notifying ServiceWorkerGlobalScopeClient
+ // that the event finished.
+ kDispatched,
+ // Event dispatch failed. Any outstanding waitUntil promises are ignored.
+ kFailed
+ };
+
+ WaitUntilObserver(ExecutionContext*, EventType, int event_id);
+
+ void IncrementPendingPromiseCount();
+ void DecrementPendingPromiseCount();
+
+ // Enqueued as a microtask when a promise passed to a waitUntil() call that is
+ // associated with this observer was fulfilled.
+ void OnPromiseFulfilled();
+ // Enqueued as a microtask when a promise passed to a waitUntil() call that is
+ // associated with this observer was rejected.
+ void OnPromiseRejected();
+
+ void ConsumeWindowInteraction(TimerBase*);
+
+ void MaybeCompleteEvent();
+
+ Member<ExecutionContext> execution_context_;
+ EventType type_;
+ int event_id_;
+ int pending_promises_ = 0;
+ EventDispatchState event_dispatch_state_ = EventDispatchState::kInitial;
+ bool has_rejected_promise_ = false;
+ double event_dispatch_time_ = 0;
+ TaskRunnerTimer<WaitUntilObserver> consume_window_interaction_timer_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICE_WORKER_WAIT_UNTIL_OBSERVER_H_
diff --git a/chromium/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc b/chromium/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc
new file mode 100644
index 00000000000..d17f7e49ba5
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc
@@ -0,0 +1,366 @@
+// 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/public/web/web_embedded_worker.h"
+
+#include <memory>
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/message_port/message_port_channel.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_installed_scripts_manager.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_provider.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_content_settings_client.h"
+#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
+#include "third_party/blink/public/platform/web_url_response.h"
+#include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h"
+#include "third_party/blink/public/web/modules/service_worker/web_service_worker_context_proxy.h"
+#include "third_party/blink/public/web/web_embedded_worker_start_data.h"
+#include "third_party/blink/public/web/web_settings.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.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/waitable_event.h"
+
+namespace blink {
+namespace {
+
+class MockServiceWorkerContextClient : public WebServiceWorkerContextClient {
+ public:
+ MockServiceWorkerContextClient() = default;
+ ~MockServiceWorkerContextClient() override = default;
+
+ MOCK_METHOD0(WorkerReadyForInspection, void());
+ MOCK_METHOD0(WorkerContextFailedToStart, void());
+ MOCK_METHOD0(WorkerScriptLoaded, void());
+
+ void WorkerContextStarted(WebServiceWorkerContextProxy* proxy) override {
+ // In production code, ReadyToEvaluateScript() is called when
+ // ServiceWorkerContextClient receives the InitializeGlobalScope() IPC
+ // message.
+ proxy->ReadyToEvaluateScript();
+ }
+ void DidEvaluateClassicScript(bool /* success */) override {
+ script_evaluated_event_.Signal();
+ }
+
+ // Work-around for mocking a method that return unique_ptr.
+ MOCK_METHOD0(CreateServiceWorkerNetworkProviderProxy,
+ WebServiceWorkerNetworkProvider*());
+ MOCK_METHOD0(CreateServiceWorkerProviderProxy, WebServiceWorkerProvider*());
+ std::unique_ptr<WebServiceWorkerNetworkProvider>
+ CreateServiceWorkerNetworkProvider() override {
+ return std::unique_ptr<WebServiceWorkerNetworkProvider>(
+ CreateServiceWorkerNetworkProviderProxy());
+ }
+ std::unique_ptr<WebServiceWorkerProvider> CreateServiceWorkerProvider()
+ override {
+ return std::unique_ptr<WebServiceWorkerProvider>(
+ CreateServiceWorkerProviderProxy());
+ }
+ void GetClient(const WebString&,
+ std::unique_ptr<WebServiceWorkerClientCallbacks>) override {
+ NOTREACHED();
+ }
+ void GetClients(const WebServiceWorkerClientQueryOptions&,
+ std::unique_ptr<WebServiceWorkerClientsCallbacks>) override {
+ NOTREACHED();
+ }
+ void OpenNewTab(const WebURL&,
+ std::unique_ptr<WebServiceWorkerClientCallbacks>) override {
+ NOTREACHED();
+ }
+ void OpenPaymentHandlerWindow(
+ const WebURL&,
+ std::unique_ptr<WebServiceWorkerClientCallbacks>) override {
+ NOTREACHED();
+ }
+ void PostMessageToClient(const WebString& uuid,
+ TransferableMessage) override {
+ NOTREACHED();
+ }
+ void SkipWaiting(
+ std::unique_ptr<WebServiceWorkerSkipWaitingCallbacks>) override {
+ NOTREACHED();
+ }
+ void Claim(std::unique_ptr<WebServiceWorkerClientsClaimCallbacks>) override {
+ NOTREACHED();
+ }
+ void Focus(const WebString& uuid,
+ std::unique_ptr<WebServiceWorkerClientCallbacks>) override {
+ NOTREACHED();
+ }
+ void Navigate(const WebString& uuid,
+ const WebURL&,
+ std::unique_ptr<WebServiceWorkerClientCallbacks>) override {
+ NOTREACHED();
+ }
+ void WorkerContextDestroyed() override { termination_event_.Signal(); }
+
+ void WaitUntilScriptEvaluated() { script_evaluated_event_.Wait(); }
+ void WaitUntilThreadTermination() { termination_event_.Wait(); }
+
+ private:
+ WaitableEvent script_evaluated_event_;
+ WaitableEvent termination_event_;
+};
+
+class MockServiceWorkerInstalledScriptsManager
+ : public WebServiceWorkerInstalledScriptsManager {
+ public:
+ MOCK_CONST_METHOD1(IsScriptInstalled, bool(const WebURL& script_url));
+ MOCK_METHOD1(GetRawScriptData,
+ std::unique_ptr<RawScriptData>(const WebURL& script_url));
+};
+
+class WebEmbeddedWorkerImplTest : public testing::Test {
+ protected:
+ void SetUp() override {
+ auto client = std::make_unique<MockServiceWorkerContextClient>();
+ auto installed_scripts_manager =
+ std::make_unique<MockServiceWorkerInstalledScriptsManager>();
+ mock_client_ = client.get();
+ mock_installed_scripts_manager_ = installed_scripts_manager.get();
+ worker_ = WebEmbeddedWorker::Create(
+ std::move(client), std::move(installed_scripts_manager),
+ mojo::ScopedMessagePipeHandle(), mojo::ScopedMessagePipeHandle(),
+ mojo::ScopedMessagePipeHandle());
+
+ WebURL script_url = URLTestHelpers::ToKURL("https://www.example.com/sw.js");
+ WebURLResponse response;
+ response.SetMIMEType("text/javascript");
+ response.SetHTTPStatusCode(200);
+ Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(script_url,
+ response, "");
+
+ start_data_.script_url = script_url;
+ start_data_.user_agent = WebString("dummy user agent");
+ start_data_.pause_after_download_mode =
+ WebEmbeddedWorkerStartData::kDontPauseAfterDownload;
+ start_data_.wait_for_debugger_mode =
+ WebEmbeddedWorkerStartData::kDontWaitForDebugger;
+ start_data_.v8_cache_options = WebSettings::kV8CacheOptionsDefault;
+ }
+
+ void TearDown() override {
+ Platform::Current()
+ ->GetURLLoaderMockFactory()
+ ->UnregisterAllURLsAndClearMemoryCache();
+ }
+
+ WebEmbeddedWorkerStartData start_data_;
+ MockServiceWorkerContextClient* mock_client_;
+ MockServiceWorkerInstalledScriptsManager* mock_installed_scripts_manager_;
+ std::unique_ptr<WebEmbeddedWorker> worker_;
+};
+
+} // namespace
+
+TEST_F(WebEmbeddedWorkerImplTest, TerminateSoonAfterStart) {
+ EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
+ worker_->StartWorkerContext(start_data_);
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+
+ EXPECT_CALL(*mock_client_, WorkerContextFailedToStart()).Times(1);
+ worker_->TerminateWorkerContext();
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+}
+
+TEST_F(WebEmbeddedWorkerImplTest, TerminateWhileWaitingForDebugger) {
+ EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
+ start_data_.wait_for_debugger_mode =
+ WebEmbeddedWorkerStartData::kWaitForDebugger;
+ worker_->StartWorkerContext(start_data_);
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+
+ EXPECT_CALL(*mock_client_, WorkerContextFailedToStart()).Times(1);
+ worker_->TerminateWorkerContext();
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+}
+
+TEST_F(WebEmbeddedWorkerImplTest, TerminateWhileLoadingScript) {
+ EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
+ worker_->StartWorkerContext(start_data_);
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+
+ // Load the shadow page.
+ EXPECT_CALL(*mock_client_, CreateServiceWorkerNetworkProviderProxy())
+ .WillOnce(testing::Return(nullptr));
+ EXPECT_CALL(*mock_installed_scripts_manager_,
+ IsScriptInstalled(start_data_.script_url))
+ .Times(testing::AtLeast(1))
+ .WillRepeatedly(testing::Return(false));
+ Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+ testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
+
+ // Terminate before loading the script.
+ EXPECT_CALL(*mock_client_, WorkerContextFailedToStart()).Times(1);
+ worker_->TerminateWorkerContext();
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+}
+
+TEST_F(WebEmbeddedWorkerImplTest, TerminateWhilePausedAfterDownload) {
+ EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
+ start_data_.pause_after_download_mode =
+ WebEmbeddedWorkerStartData::kPauseAfterDownload;
+ worker_->StartWorkerContext(start_data_);
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+
+ // Load the shadow page.
+ EXPECT_CALL(*mock_client_, CreateServiceWorkerNetworkProviderProxy())
+ .WillOnce(testing::Return(nullptr));
+ EXPECT_CALL(*mock_installed_scripts_manager_,
+ IsScriptInstalled(start_data_.script_url))
+ .Times(testing::AtLeast(1))
+ .WillRepeatedly(testing::Return(false));
+
+ Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+ testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
+
+ // Load the script.
+ EXPECT_CALL(*mock_client_, WorkerScriptLoaded()).Times(1);
+ EXPECT_CALL(*mock_client_, CreateServiceWorkerProviderProxy()).Times(0);
+ Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+
+ // Terminate before resuming after download.
+ EXPECT_CALL(*mock_client_, CreateServiceWorkerProviderProxy()).Times(0);
+ EXPECT_CALL(*mock_client_, WorkerContextFailedToStart()).Times(1);
+ worker_->TerminateWorkerContext();
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+}
+
+TEST_F(WebEmbeddedWorkerImplTest, ScriptNotFound) {
+ WebURL script_url =
+ URLTestHelpers::ToKURL("https://www.example.com/sw-404.js");
+ WebURLResponse response;
+ response.SetMIMEType("text/javascript");
+ response.SetHTTPStatusCode(404);
+ ResourceError error = ResourceError::Failure(script_url);
+ Platform::Current()->GetURLLoaderMockFactory()->RegisterErrorURL(
+ script_url, response, error);
+ start_data_.script_url = script_url;
+
+ EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
+ worker_->StartWorkerContext(start_data_);
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+
+ // Load the shadow page.
+ EXPECT_CALL(*mock_client_, CreateServiceWorkerNetworkProviderProxy())
+ .WillOnce(testing::Return(nullptr));
+ EXPECT_CALL(*mock_installed_scripts_manager_,
+ IsScriptInstalled(start_data_.script_url))
+ .Times(testing::AtLeast(1))
+ .WillRepeatedly(testing::Return(false));
+
+ Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+ testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
+
+ // Load the script.
+ EXPECT_CALL(*mock_client_, WorkerScriptLoaded()).Times(0);
+ EXPECT_CALL(*mock_client_, CreateServiceWorkerProviderProxy()).Times(0);
+ EXPECT_CALL(*mock_client_, WorkerContextFailedToStart()).Times(1);
+ Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+}
+
+// The running worker is detected as a memory leak. crbug.com/586897 and
+// crbug.com/807754.
+#if defined(ADDRESS_SANITIZER)
+#define MAYBE_DontPauseAfterDownload DISABLED_DontPauseAfterDownload
+#else
+#define MAYBE_DontPauseAfterDownload DontPauseAfterDownload
+#endif
+TEST_F(WebEmbeddedWorkerImplTest, MAYBE_DontPauseAfterDownload) {
+ EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
+ worker_->StartWorkerContext(start_data_);
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+
+ // Load the shadow page.
+ EXPECT_CALL(*mock_client_, CreateServiceWorkerNetworkProviderProxy())
+ .WillOnce(testing::Return(nullptr));
+ EXPECT_CALL(*mock_installed_scripts_manager_,
+ IsScriptInstalled(start_data_.script_url))
+ .Times(testing::AtLeast(1))
+ .WillRepeatedly(testing::Return(false));
+ Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+ testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
+
+ // Load the script.
+ EXPECT_CALL(*mock_client_, WorkerScriptLoaded()).Times(1);
+ EXPECT_CALL(*mock_client_, CreateServiceWorkerProviderProxy())
+ .WillOnce(testing::Return(nullptr));
+ // This is called on the worker thread.
+ EXPECT_CALL(*mock_installed_scripts_manager_,
+ IsScriptInstalled(start_data_.script_url))
+ .Times(testing::AtLeast(1))
+ .WillRepeatedly(testing::Return(false));
+ Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ mock_client_->WaitUntilScriptEvaluated();
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+ testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
+
+ // Terminate the running worker thread.
+ EXPECT_CALL(*mock_client_, WorkerContextFailedToStart()).Times(0);
+ worker_->TerminateWorkerContext();
+ mock_client_->WaitUntilThreadTermination();
+}
+
+// The running worker is detected as a memory leak. crbug.com/586897 and
+// crbug.com/807754.
+#if defined(ADDRESS_SANITIZER)
+#define MAYBE_PauseAfterDownload DISABLED_PauseAfterDownload
+#else
+#define MAYBE_PauseAfterDownload PauseAfterDownload
+#endif
+TEST_F(WebEmbeddedWorkerImplTest, MAYBE_PauseAfterDownload) {
+ EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
+ start_data_.pause_after_download_mode =
+ WebEmbeddedWorkerStartData::kPauseAfterDownload;
+ worker_->StartWorkerContext(start_data_);
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+
+ // Load the shadow page.
+ EXPECT_CALL(*mock_client_, CreateServiceWorkerNetworkProviderProxy())
+ .WillOnce(testing::Return(nullptr));
+ EXPECT_CALL(*mock_installed_scripts_manager_,
+ IsScriptInstalled(start_data_.script_url))
+ .Times(testing::AtLeast(1))
+ .WillRepeatedly(testing::Return(false));
+ Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+ testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
+
+ // Load the script.
+ EXPECT_CALL(*mock_client_, WorkerScriptLoaded()).Times(1);
+ EXPECT_CALL(*mock_client_, CreateServiceWorkerProviderProxy()).Times(0);
+ Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+
+ // Resume after download.
+ EXPECT_CALL(*mock_client_, CreateServiceWorkerProviderProxy())
+ .WillOnce(testing::Return(nullptr));
+ // This is called on the worker thread.
+ EXPECT_CALL(*mock_installed_scripts_manager_,
+ IsScriptInstalled(start_data_.script_url))
+ .Times(testing::AtLeast(1))
+ .WillRepeatedly(testing::Return(false));
+ worker_->ResumeAfterDownload();
+ mock_client_->WaitUntilScriptEvaluated();
+ testing::Mock::VerifyAndClearExpectations(mock_client_);
+ testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
+
+ // Terminate the running worker thread.
+ EXPECT_CALL(*mock_client_, WorkerContextFailedToStart()).Times(0);
+ worker_->TerminateWorkerContext();
+ mock_client_->WaitUntilThreadTermination();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/window_client.idl b/chromium/third_party/blink/renderer/modules/service_worker/window_client.idl
index 5b310450b2d..5b310450b2d 100644
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/window_client.idl
+++ b/chromium/third_party/blink/renderer/modules/service_worker/window_client.idl
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/BUILD.gn b/chromium/third_party/blink/renderer/modules/serviceworkers/BUILD.gn
deleted file mode 100644
index 4b0b2b4543a..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/BUILD.gn
+++ /dev/null
@@ -1,66 +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.
-
-import("//third_party/blink/renderer/modules/modules.gni")
-
-blink_modules_sources("serviceworkers") {
- sources = [
- "extendable_event.cc",
- "extendable_event.h",
- "extendable_message_event.cc",
- "extendable_message_event.h",
- "fetch_event.cc",
- "fetch_event.h",
- "fetch_respond_with_observer.cc",
- "fetch_respond_with_observer.h",
- "install_event.cc",
- "install_event.h",
- "navigation_preload_callbacks.cc",
- "navigation_preload_callbacks.h",
- "navigation_preload_manager.cc",
- "navigation_preload_manager.h",
- "navigator_service_worker.cc",
- "navigator_service_worker.h",
- "respond_with_observer.cc",
- "respond_with_observer.h",
- "service_worker.cc",
- "service_worker.h",
- "service_worker_client.cc",
- "service_worker_client.h",
- "service_worker_clients.cc",
- "service_worker_clients.h",
- "service_worker_container.cc",
- "service_worker_container.h",
- "service_worker_container_client.cc",
- "service_worker_container_client.h",
- "service_worker_content_settings_proxy.cc",
- "service_worker_content_settings_proxy.h",
- "service_worker_error.cc",
- "service_worker_error.h",
- "service_worker_global_scope.cc",
- "service_worker_global_scope.h",
- "service_worker_global_scope_client.cc",
- "service_worker_global_scope_client.h",
- "service_worker_global_scope_proxy.cc",
- "service_worker_global_scope_proxy.h",
- "service_worker_installed_scripts_manager.cc",
- "service_worker_installed_scripts_manager.h",
- "service_worker_registration.cc",
- "service_worker_registration.h",
- "service_worker_script_cached_metadata_handler.cc",
- "service_worker_script_cached_metadata_handler.h",
- "service_worker_thread.cc",
- "service_worker_thread.h",
- "service_worker_window_client.cc",
- "service_worker_window_client.h",
- "service_worker_window_client_callback.cc",
- "service_worker_window_client_callback.h",
- "wait_until_observer.cc",
- "wait_until_observer.h",
- ]
-
- public_deps = [
- "//third_party/blink/renderer/platform",
- ]
-}
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/DEPS b/chromium/third_party/blink/renderer/modules/serviceworkers/DEPS
deleted file mode 100644
index 8c6d4bf9e96..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/DEPS
+++ /dev/null
@@ -1,21 +0,0 @@
-include_rules = [
- "+mojo/public/cpp/system/data_pipe.h",
- "+services/network/public/mojom",
- "-third_party/blink/renderer/modules",
- "+third_party/blink/renderer/modules/event_modules.h",
- "+third_party/blink/renderer/modules/event_target_modules.h",
- "+third_party/blink/renderer/modules/modules_export.h",
- "+third_party/blink/renderer/modules/serviceworkers",
-]
-
-specific_include_rules = {
- "service_worker_global_scope_proxy\.cc": [
- "+third_party/blink/renderer/modules/background_fetch",
- "+third_party/blink/renderer/modules/background_sync",
- "+third_party/blink/renderer/modules/cookie_store",
- "+third_party/blink/renderer/modules/exported",
- "+third_party/blink/renderer/modules/notifications",
- "+third_party/blink/renderer/modules/payments",
- "+third_party/blink/renderer/modules/push_messaging",
- ],
-}
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/OWNERS b/chromium/third_party/blink/renderer/modules/serviceworkers/OWNERS
deleted file mode 100644
index 299b6b925b6..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-file://content/browser/service_worker/OWNERS
-
-# TEAM: worker-dev@chromium.org
-# COMPONENT: Blink>ServiceWorker
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_event.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_event.cc
deleted file mode 100644
index 3917750be90..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_event.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2014 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/modules/serviceworkers/extendable_event.h"
-
-#include "third_party/blink/renderer/modules/serviceworkers/wait_until_observer.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-
-namespace blink {
-
-ExtendableEvent* ExtendableEvent::Create(
- const AtomicString& type,
- const ExtendableEventInit& event_init) {
- return new ExtendableEvent(type, event_init);
-}
-
-ExtendableEvent* ExtendableEvent::Create(const AtomicString& type,
- const ExtendableEventInit& event_init,
- WaitUntilObserver* observer) {
- return new ExtendableEvent(type, event_init, observer);
-}
-
-ExtendableEvent::~ExtendableEvent() = default;
-
-void ExtendableEvent::waitUntil(ScriptState* script_state,
- ScriptPromise script_promise,
- ExceptionState& exception_state) {
- if (!observer_) {
- exception_state.ThrowDOMException(
- kInvalidStateError,
- "Can not call waitUntil on a script constructed ExtendableEvent.");
- return;
- }
-
- observer_->WaitUntil(script_state, script_promise, exception_state);
-}
-
-ExtendableEvent::ExtendableEvent(const AtomicString& type,
- const ExtendableEventInit& initializer)
- : Event(type, initializer) {}
-
-ExtendableEvent::ExtendableEvent(const AtomicString& type,
- const ExtendableEventInit& initializer,
- WaitUntilObserver* observer)
- : Event(type, initializer), observer_(observer) {}
-
-const AtomicString& ExtendableEvent::InterfaceName() const {
- return EventNames::ExtendableEvent;
-}
-
-void ExtendableEvent::Trace(blink::Visitor* visitor) {
- visitor->Trace(observer_);
- Event::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_event.h b/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_event.h
deleted file mode 100644
index 55c7e87eabf..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_event.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2014 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_MODULES_SERVICEWORKERS_EXTENDABLE_EVENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_EXTENDABLE_EVENT_H_
-
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/modules/event_modules.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/modules/serviceworkers/extendable_event_init.h"
-
-namespace blink {
-
-class WaitUntilObserver;
-
-class MODULES_EXPORT ExtendableEvent : public Event {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- static ExtendableEvent* Create(const AtomicString& type,
- const ExtendableEventInit&);
- static ExtendableEvent* Create(const AtomicString& type,
- const ExtendableEventInit&,
- WaitUntilObserver*);
-
- ~ExtendableEvent() override;
-
- void waitUntil(ScriptState*, ScriptPromise, ExceptionState&);
-
- const AtomicString& InterfaceName() const override;
- void Trace(blink::Visitor*) override;
-
- protected:
- ExtendableEvent(const AtomicString& type, const ExtendableEventInit&);
- ExtendableEvent(const AtomicString& type,
- const ExtendableEventInit&,
- WaitUntilObserver*);
-
- Member<WaitUntilObserver> observer_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_EXTENDABLE_EVENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_message_event.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_message_event.cc
deleted file mode 100644
index 8efb357a0a9..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_message_event.cc
+++ /dev/null
@@ -1,133 +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/modules/serviceworkers/extendable_message_event.h"
-
-namespace blink {
-
-ExtendableMessageEvent* ExtendableMessageEvent::Create(
- const AtomicString& type,
- const ExtendableMessageEventInit& initializer) {
- return new ExtendableMessageEvent(type, initializer);
-}
-
-ExtendableMessageEvent* ExtendableMessageEvent::Create(
- const AtomicString& type,
- const ExtendableMessageEventInit& initializer,
- WaitUntilObserver* observer) {
- return new ExtendableMessageEvent(type, initializer, observer);
-}
-
-ExtendableMessageEvent* ExtendableMessageEvent::Create(
- scoped_refptr<SerializedScriptValue> data,
- const String& origin,
- MessagePortArray* ports,
- WaitUntilObserver* observer) {
- return new ExtendableMessageEvent(std::move(data), origin, ports, observer);
-}
-
-ExtendableMessageEvent* ExtendableMessageEvent::Create(
- scoped_refptr<SerializedScriptValue> data,
- const String& origin,
- MessagePortArray* ports,
- ServiceWorkerClient* source,
- WaitUntilObserver* observer) {
- ExtendableMessageEvent* event =
- new ExtendableMessageEvent(std::move(data), origin, ports, observer);
- event->source_as_client_ = source;
- return event;
-}
-
-ExtendableMessageEvent* ExtendableMessageEvent::Create(
- scoped_refptr<SerializedScriptValue> data,
- const String& origin,
- MessagePortArray* ports,
- ServiceWorker* source,
- WaitUntilObserver* observer) {
- ExtendableMessageEvent* event =
- new ExtendableMessageEvent(std::move(data), origin, ports, observer);
- event->source_as_service_worker_ = source;
- return event;
-}
-
-MessagePortArray ExtendableMessageEvent::ports() const {
- // TODO(bashi): Currently we return a copied array because the binding
- // layer could modify the content of the array while executing JS callbacks.
- // Avoid copying once we can make sure that the binding layer won't
- // modify the content.
- if (ports_) {
- return *ports_;
- }
- return MessagePortArray();
-}
-
-void ExtendableMessageEvent::source(
- ClientOrServiceWorkerOrMessagePort& result) const {
- if (source_as_client_)
- result = ClientOrServiceWorkerOrMessagePort::FromClient(source_as_client_);
- else if (source_as_service_worker_)
- result = ClientOrServiceWorkerOrMessagePort::FromServiceWorker(
- source_as_service_worker_);
- else if (source_as_message_port_)
- result = ClientOrServiceWorkerOrMessagePort::FromMessagePort(
- source_as_message_port_);
- else
- result = ClientOrServiceWorkerOrMessagePort();
-}
-
-const AtomicString& ExtendableMessageEvent::InterfaceName() const {
- return EventNames::ExtendableMessageEvent;
-}
-
-void ExtendableMessageEvent::Trace(blink::Visitor* visitor) {
- visitor->Trace(source_as_client_);
- visitor->Trace(source_as_service_worker_);
- visitor->Trace(source_as_message_port_);
- visitor->Trace(ports_);
- ExtendableEvent::Trace(visitor);
-}
-
-ExtendableMessageEvent::ExtendableMessageEvent(
- const AtomicString& type,
- const ExtendableMessageEventInit& initializer)
- : ExtendableMessageEvent(type, initializer, nullptr) {}
-
-ExtendableMessageEvent::ExtendableMessageEvent(
- const AtomicString& type,
- const ExtendableMessageEventInit& initializer,
- WaitUntilObserver* observer)
- : ExtendableEvent(type, initializer, observer) {
- if (initializer.hasOrigin())
- origin_ = initializer.origin();
- if (initializer.hasLastEventId())
- last_event_id_ = initializer.lastEventId();
- if (initializer.hasSource()) {
- if (initializer.source().IsClient())
- source_as_client_ = initializer.source().GetAsClient();
- else if (initializer.source().IsServiceWorker())
- source_as_service_worker_ = initializer.source().GetAsServiceWorker();
- else if (initializer.source().IsMessagePort())
- source_as_message_port_ = initializer.source().GetAsMessagePort();
- }
- if (initializer.hasPorts())
- ports_ = new MessagePortArray(initializer.ports());
-}
-
-ExtendableMessageEvent::ExtendableMessageEvent(
- scoped_refptr<SerializedScriptValue> data,
- const String& origin,
- MessagePortArray* ports,
- WaitUntilObserver* observer)
- : ExtendableEvent(EventTypeNames::message,
- ExtendableMessageEventInit(),
- observer),
- serialized_data_(std::move(data)),
- origin_(origin),
- last_event_id_(String()),
- ports_(ports) {
- if (serialized_data_)
- serialized_data_->RegisterMemoryAllocatedWithCurrentScriptContext();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_message_event.h b/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_message_event.h
deleted file mode 100644
index 4be645e3a05..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/extendable_message_event.h
+++ /dev/null
@@ -1,81 +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_MODULES_SERVICEWORKERS_EXTENDABLE_MESSAGE_EVENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_EXTENDABLE_MESSAGE_EVENT_H_
-
-#include "third_party/blink/renderer/modules/event_modules.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/modules/serviceworkers/extendable_event.h"
-#include "third_party/blink/renderer/modules/serviceworkers/extendable_message_event_init.h"
-
-namespace blink {
-
-class MODULES_EXPORT ExtendableMessageEvent final : public ExtendableEvent {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- static ExtendableMessageEvent* Create(
- const AtomicString& type,
- const ExtendableMessageEventInit& initializer);
- static ExtendableMessageEvent* Create(
- const AtomicString& type,
- const ExtendableMessageEventInit& initializer,
- WaitUntilObserver*);
- static ExtendableMessageEvent* Create(
- scoped_refptr<SerializedScriptValue> data,
- const String& origin,
- MessagePortArray* ports,
- WaitUntilObserver*);
- static ExtendableMessageEvent* Create(
- scoped_refptr<SerializedScriptValue> data,
- const String& origin,
- MessagePortArray* ports,
- ServiceWorkerClient* source,
- WaitUntilObserver*);
- static ExtendableMessageEvent* Create(
- scoped_refptr<SerializedScriptValue> data,
- const String& origin,
- MessagePortArray* ports,
- ServiceWorker* source,
- WaitUntilObserver*);
-
- SerializedScriptValue* SerializedData() const {
- return serialized_data_.get();
- }
- void SetSerializedData(scoped_refptr<SerializedScriptValue> serialized_data) {
- serialized_data_ = std::move(serialized_data);
- }
- const String& origin() const { return origin_; }
- const String& lastEventId() const { return last_event_id_; }
- MessagePortArray ports() const;
- void source(ClientOrServiceWorkerOrMessagePort& result) const;
-
- const AtomicString& InterfaceName() const override;
-
- void Trace(blink::Visitor*) override;
-
- private:
- ExtendableMessageEvent(const AtomicString& type,
- const ExtendableMessageEventInit& initializer);
- ExtendableMessageEvent(const AtomicString& type,
- const ExtendableMessageEventInit& initializer,
- WaitUntilObserver*);
- ExtendableMessageEvent(scoped_refptr<SerializedScriptValue> data,
- const String& origin,
- MessagePortArray* ports,
- WaitUntilObserver*);
-
- scoped_refptr<SerializedScriptValue> serialized_data_;
- String origin_;
- String last_event_id_;
- Member<ServiceWorkerClient> source_as_client_;
- Member<ServiceWorker> source_as_service_worker_;
- Member<MessagePort> source_as_message_port_;
- Member<MessagePortArray> ports_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_EXTENDABLE_MESSAGE_EVENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/fetch_event.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/fetch_event.cc
deleted file mode 100644
index 68e36b6a717..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/fetch_event.cc
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/serviceworkers/fetch_event.h"
-
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_error.h"
-#include "third_party/blink/public/platform/web_url_response.h"
-#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
-#include "third_party/blink/renderer/core/dom/abort_signal.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/fetch/bytes_consumer_for_data_consumer_handle.h"
-#include "third_party/blink/renderer/core/fetch/request.h"
-#include "third_party/blink/renderer/core/fetch/response.h"
-#include "third_party/blink/renderer/core/frame/use_counter.h"
-#include "third_party/blink/renderer/core/timing/worker_global_scope_performance.h"
-#include "third_party/blink/renderer/modules/serviceworkers/fetch_respond_with_observer.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_error.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
-#include "third_party/blink/renderer/platform/network/network_utils.h"
-
-namespace blink {
-
-FetchEvent* FetchEvent::Create(ScriptState* script_state,
- const AtomicString& type,
- const FetchEventInit& initializer) {
- return new FetchEvent(script_state, type, initializer, nullptr, nullptr,
- false);
-}
-
-FetchEvent* FetchEvent::Create(ScriptState* script_state,
- const AtomicString& type,
- const FetchEventInit& initializer,
- FetchRespondWithObserver* respond_with_observer,
- WaitUntilObserver* wait_until_observer,
- bool navigation_preload_sent) {
- return new FetchEvent(script_state, type, initializer, respond_with_observer,
- wait_until_observer, navigation_preload_sent);
-}
-
-Request* FetchEvent::request() const {
- return request_;
-}
-
-String FetchEvent::clientId() const {
- return client_id_;
-}
-
-bool FetchEvent::isReload() const {
- UseCounter::Count(GetExecutionContext(), WebFeature::kFetchEventIsReload);
- return is_reload_;
-}
-
-void FetchEvent::respondWith(ScriptState* script_state,
- ScriptPromise script_promise,
- ExceptionState& exception_state) {
- stopImmediatePropagation();
- if (observer_)
- observer_->RespondWith(script_state, script_promise, exception_state);
-}
-
-ScriptPromise FetchEvent::preloadResponse(ScriptState* script_state) {
- return preload_response_property_->Promise(script_state->World());
-}
-
-const AtomicString& FetchEvent::InterfaceName() const {
- return EventNames::FetchEvent;
-}
-
-bool FetchEvent::HasPendingActivity() const {
- // Prevent V8 from garbage collecting the wrapper object while waiting for the
- // preload response. This is in order to keep the resolver of preloadResponse
- // Promise alive. Note that |preload_response_property_| can be nullptr as
- // GC can run while running the FetchEvent constructor, before the member is
- // set. If it isn't set we treat it as a pending state.
- return !preload_response_property_ ||
- preload_response_property_->GetState() ==
- PreloadResponseProperty::kPending;
-}
-
-FetchEvent::FetchEvent(ScriptState* script_state,
- const AtomicString& type,
- const FetchEventInit& initializer,
- FetchRespondWithObserver* respond_with_observer,
- WaitUntilObserver* wait_until_observer,
- bool navigation_preload_sent)
- : ExtendableEvent(type, initializer, wait_until_observer),
- ContextClient(ExecutionContext::From(script_state)),
- observer_(respond_with_observer),
- preload_response_property_(new PreloadResponseProperty(
- ExecutionContext::From(script_state),
- this,
- PreloadResponseProperty::kPreloadResponse)) {
- if (!navigation_preload_sent)
- preload_response_property_->ResolveWithUndefined();
-
- client_id_ = initializer.clientId();
- is_reload_ = initializer.isReload();
- if (initializer.hasRequest()) {
- ScriptState::Scope scope(script_state);
- request_ = initializer.request();
- v8::Local<v8::Value> request = ToV8(request_, script_state);
- v8::Local<v8::Value> event = ToV8(this, script_state);
- if (event.IsEmpty()) {
- // |toV8| can return an empty handle when the worker is terminating.
- // We don't want the renderer to crash in such cases.
- // TODO(yhirano): Replace this branch with an assertion when the
- // graceful shutdown mechanism is introduced.
- return;
- }
- DCHECK(event->IsObject());
- // Sets a hidden value in order to teach V8 the dependency from
- // the event to the request.
- V8PrivateProperty::GetFetchEventRequest(script_state->GetIsolate())
- .Set(event.As<v8::Object>(), request);
- // From the same reason as above, setHiddenValue can return false.
- // TODO(yhirano): Add an assertion that it returns true once the
- // graceful shutdown mechanism is introduced.
- }
-}
-
-FetchEvent::~FetchEvent() = default;
-
-void FetchEvent::OnNavigationPreloadResponse(
- ScriptState* script_state,
- std::unique_ptr<WebURLResponse> response,
- std::unique_ptr<WebDataConsumerHandle> data_consume_handle) {
- if (!script_state->ContextIsValid())
- return;
- DCHECK(preload_response_property_);
- DCHECK(!preload_response_);
- ScriptState::Scope scope(script_state);
- preload_response_ = std::move(response);
- // TODO(ricea): Verify that this response can't be aborted from JS.
- FetchResponseData* response_data =
- data_consume_handle
- ? FetchResponseData::CreateWithBuffer(new BodyStreamBuffer(
- script_state,
- new BytesConsumerForDataConsumerHandle(
- ExecutionContext::From(script_state),
- std::move(data_consume_handle)),
- new AbortSignal(ExecutionContext::From(script_state))))
- : FetchResponseData::Create();
- Vector<KURL> url_list(1);
- url_list[0] = preload_response_->Url();
- response_data->SetURLList(url_list);
- response_data->SetStatus(preload_response_->HttpStatusCode());
- response_data->SetStatusMessage(preload_response_->HttpStatusText());
- response_data->SetResponseTime(
- preload_response_->ToResourceResponse().ResponseTime());
- const HTTPHeaderMap& headers(
- preload_response_->ToResourceResponse().HttpHeaderFields());
- for (const auto& header : headers) {
- response_data->HeaderList()->Append(header.key, header.value);
- }
- FetchResponseData* tainted_response =
- NetworkUtils::IsRedirectResponseCode(preload_response_->HttpStatusCode())
- ? response_data->CreateOpaqueRedirectFilteredResponse()
- : response_data->CreateBasicFilteredResponse();
- preload_response_property_->Resolve(
- Response::Create(ExecutionContext::From(script_state), tainted_response));
-}
-
-void FetchEvent::OnNavigationPreloadError(
- ScriptState* script_state,
- std::unique_ptr<WebServiceWorkerError> error) {
- if (!script_state->ContextIsValid())
- return;
- DCHECK(preload_response_property_);
- if (preload_response_property_->GetState() !=
- PreloadResponseProperty::kPending) {
- return;
- }
- preload_response_property_->Reject(
- ServiceWorkerError::Take(nullptr, *error.get()));
-}
-
-void FetchEvent::OnNavigationPreloadComplete(
- WorkerGlobalScope* worker_global_scope,
- TimeTicks completion_time,
- int64_t encoded_data_length,
- int64_t encoded_body_length,
- int64_t decoded_body_length) {
- DCHECK(preload_response_);
- std::unique_ptr<WebURLResponse> response = std::move(preload_response_);
- ResourceResponse resource_response = response->ToResourceResponse();
- resource_response.SetEncodedDataLength(encoded_data_length);
- resource_response.SetEncodedBodyLength(encoded_body_length);
- resource_response.SetDecodedBodyLength(decoded_body_length);
- // According to the Resource Timing spec, the initiator type of
- // navigation preload request is "navigation".
- scoped_refptr<ResourceTimingInfo> info = ResourceTimingInfo::Create(
- "navigation", resource_response.GetResourceLoadTiming()->RequestTime(),
- false /* is_main_resource */);
- info->SetNegativeAllowed(true);
- info->SetLoadFinishTime(completion_time);
- info->SetInitialURL(request_->url());
- info->SetFinalResponse(resource_response);
- info->AddFinalTransferSize(encoded_data_length);
- WorkerGlobalScopePerformance::performance(*worker_global_scope)
- ->GenerateAndAddResourceTiming(*info);
-}
-
-void FetchEvent::Trace(blink::Visitor* visitor) {
- visitor->Trace(observer_);
- visitor->Trace(request_);
- visitor->Trace(preload_response_property_);
- ExtendableEvent::Trace(visitor);
- ContextClient::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/fetch_event.h b/chromium/third_party/blink/renderer/modules/serviceworkers/fetch_event.h
deleted file mode 100644
index be8bf5bc79e..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/fetch_event.h
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_FETCH_EVENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_FETCH_EVENT_H_
-
-#include <memory>
-
-#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_property.h"
-#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
-#include "third_party/blink/renderer/core/fetch/request.h"
-#include "third_party/blink/renderer/modules/event_modules.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/modules/serviceworkers/extendable_event.h"
-#include "third_party/blink/renderer/modules/serviceworkers/fetch_event_init.h"
-#include "third_party/blink/renderer/modules/serviceworkers/wait_until_observer.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
-
-namespace blink {
-
-class ExceptionState;
-class FetchRespondWithObserver;
-class Request;
-class Response;
-class ScriptState;
-class WebDataConsumerHandle;
-struct WebServiceWorkerError;
-class WebURLResponse;
-class WorkerGlobalScope;
-
-// A fetch event is dispatched by the client to a service worker's script
-// context. FetchRespondWithObserver can be used to notify the client about the
-// service worker's response.
-class MODULES_EXPORT FetchEvent final
- : public ExtendableEvent,
- public ActiveScriptWrappable<FetchEvent>,
- public ContextClient {
- DEFINE_WRAPPERTYPEINFO();
- USING_GARBAGE_COLLECTED_MIXIN(FetchEvent);
-
- public:
- using PreloadResponseProperty = ScriptPromiseProperty<Member<FetchEvent>,
- Member<Response>,
- Member<DOMException>>;
- static FetchEvent* Create(ScriptState*,
- const AtomicString& type,
- const FetchEventInit&);
- static FetchEvent* Create(ScriptState*,
- const AtomicString& type,
- const FetchEventInit&,
- FetchRespondWithObserver*,
- WaitUntilObserver*,
- bool navigation_preload_sent);
-
- ~FetchEvent() override;
-
- Request* request() const;
- String clientId() const;
- bool isReload() const;
-
- void respondWith(ScriptState*, ScriptPromise, ExceptionState&);
- ScriptPromise preloadResponse(ScriptState*);
-
- void OnNavigationPreloadResponse(ScriptState*,
- std::unique_ptr<WebURLResponse>,
- std::unique_ptr<WebDataConsumerHandle>);
- void OnNavigationPreloadError(ScriptState*,
- std::unique_ptr<WebServiceWorkerError>);
- void OnNavigationPreloadComplete(WorkerGlobalScope*,
- TimeTicks completion_time,
- int64_t encoded_data_length,
- int64_t encoded_body_length,
- int64_t decoded_body_length);
-
- const AtomicString& InterfaceName() const override;
-
- // ScriptWrappable
- bool HasPendingActivity() const override;
-
- void Trace(blink::Visitor*) override;
-
- protected:
- FetchEvent(ScriptState*,
- const AtomicString& type,
- const FetchEventInit&,
- FetchRespondWithObserver*,
- WaitUntilObserver*,
- bool navigation_preload_sent);
-
- private:
- Member<FetchRespondWithObserver> observer_;
- Member<Request> request_;
- Member<PreloadResponseProperty> preload_response_property_;
- std::unique_ptr<WebURLResponse> preload_response_;
- String client_id_;
- bool is_reload_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_FETCH_EVENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/fetch_respond_with_observer.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/fetch_respond_with_observer.cc
deleted file mode 100644
index 3ad3feb9e3a..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/fetch_respond_with_observer.cc
+++ /dev/null
@@ -1,309 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/serviceworkers/fetch_respond_with_observer.h"
-
-#include <memory>
-#include <utility>
-
-#include <v8.h>
-#include "services/network/public/mojom/fetch_api.mojom-blink.h"
-#include "services/network/public/mojom/request_context_frame_type.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_response.h"
-#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_response.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/fetch/body_stream_buffer.h"
-#include "third_party/blink/renderer/core/fetch/bytes_consumer.h"
-#include "third_party/blink/renderer/core/inspector/console_message.h"
-#include "third_party/blink/renderer/core/inspector/console_types.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.h"
-#include "third_party/blink/renderer/modules/serviceworkers/wait_until_observer.h"
-
-using blink::mojom::ServiceWorkerResponseError;
-
-namespace blink {
-namespace {
-
-// Returns the error message to let the developer know about the reason of the
-// unusual failures.
-const String GetMessageForResponseError(ServiceWorkerResponseError error,
- const KURL& request_url) {
- String error_message = "The FetchEvent for \"" + request_url.GetString() +
- "\" resulted in a network error response: ";
- switch (error) {
- case ServiceWorkerResponseError::kPromiseRejected:
- error_message = error_message + "the promise was rejected.";
- break;
- case ServiceWorkerResponseError::kDefaultPrevented:
- error_message =
- error_message +
- "preventDefault() was called without calling respondWith().";
- break;
- case ServiceWorkerResponseError::kNoV8Instance:
- error_message =
- error_message +
- "an object that was not a Response was passed to respondWith().";
- break;
- case ServiceWorkerResponseError::kResponseTypeError:
- error_message = error_message +
- "the promise was resolved with an error response object.";
- break;
- case ServiceWorkerResponseError::kResponseTypeOpaque:
- error_message =
- error_message +
- "an \"opaque\" response was used for a request whose type "
- "is not no-cors";
- break;
- case ServiceWorkerResponseError::kResponseTypeNotBasicOrDefault:
- NOTREACHED();
- break;
- case ServiceWorkerResponseError::kBodyUsed:
- error_message =
- error_message +
- "a Response whose \"bodyUsed\" is \"true\" cannot be used "
- "to respond to a request.";
- break;
- case ServiceWorkerResponseError::kResponseTypeOpaqueForClientRequest:
- error_message = error_message +
- "an \"opaque\" response was used for a client request.";
- break;
- case ServiceWorkerResponseError::kResponseTypeOpaqueRedirect:
- error_message = error_message +
- "an \"opaqueredirect\" type response was used for a "
- "request whose redirect mode is not \"manual\".";
- break;
- case ServiceWorkerResponseError::kResponseTypeCORSForRequestModeSameOrigin:
- error_message = error_message +
- "a \"cors\" type response was used for a request whose "
- "mode is \"same-origin\".";
- break;
- case ServiceWorkerResponseError::kBodyLocked:
- error_message = error_message +
- "a Response whose \"body\" is locked cannot be used to "
- "respond to a request.";
- break;
- case ServiceWorkerResponseError::kRedirectedResponseForNotFollowRequest:
- error_message = error_message +
- "a redirected response was used for a request whose "
- "redirect mode is not \"follow\".";
- break;
- case ServiceWorkerResponseError::kDataPipeCreationFailed:
- error_message = error_message + "insufficient resources.";
- break;
- case ServiceWorkerResponseError::kUnknown:
- default:
- error_message = error_message + "an unexpected error occurred.";
- break;
- }
- return error_message;
-}
-
-bool IsNavigationRequest(network::mojom::RequestContextFrameType frame_type) {
- return frame_type != network::mojom::RequestContextFrameType::kNone;
-}
-
-bool IsClientRequest(network::mojom::RequestContextFrameType frame_type,
- WebURLRequest::RequestContext request_context) {
- return IsNavigationRequest(frame_type) ||
- request_context == WebURLRequest::kRequestContextSharedWorker ||
- request_context == WebURLRequest::kRequestContextWorker;
-}
-
-// Notifies the result of FetchDataLoader to |handle_|. |handle_| pass through
-// the result to its observer which is outside of blink.
-class FetchLoaderClient final
- : public GarbageCollectedFinalized<FetchLoaderClient>,
- public FetchDataLoader::Client {
- WTF_MAKE_NONCOPYABLE(FetchLoaderClient);
- USING_GARBAGE_COLLECTED_MIXIN(FetchLoaderClient);
-
- public:
- explicit FetchLoaderClient(
- std::unique_ptr<WebServiceWorkerStreamHandle> handle)
- : handle_(std::move(handle)) {}
-
- void DidFetchDataLoadedDataPipe() override { handle_->Completed(); }
- void DidFetchDataLoadFailed() override { handle_->Aborted(); }
- void Abort() override {
- // A fetch() aborted via AbortSignal in the ServiceWorker will just look
- // like an ordinary failure to the page.
- // TODO(ricea): Should a fetch() on the page get an AbortError instead?
- handle_->Aborted();
- }
-
- void Trace(blink::Visitor* visitor) override {
- FetchDataLoader::Client::Trace(visitor);
- }
-
- private:
- std::unique_ptr<WebServiceWorkerStreamHandle> handle_;
-};
-
-} // namespace
-
-FetchRespondWithObserver* FetchRespondWithObserver::Create(
- ExecutionContext* context,
- int fetch_event_id,
- const KURL& request_url,
- network::mojom::FetchRequestMode request_mode,
- network::mojom::FetchRedirectMode redirect_mode,
- network::mojom::RequestContextFrameType frame_type,
- WebURLRequest::RequestContext request_context,
- WaitUntilObserver* observer) {
- return new FetchRespondWithObserver(context, fetch_event_id, request_url,
- request_mode, redirect_mode, frame_type,
- request_context, observer);
-}
-
-void FetchRespondWithObserver::OnResponseRejected(
- ServiceWorkerResponseError error) {
- DCHECK(GetExecutionContext());
- GetExecutionContext()->AddConsoleMessage(
- ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel,
- GetMessageForResponseError(error, request_url_)));
-
- // The default value of WebServiceWorkerResponse's status is 0, which maps
- // to a network error.
- WebServiceWorkerResponse web_response;
- web_response.SetError(error);
- ServiceWorkerGlobalScopeClient::From(GetExecutionContext())
- ->RespondToFetchEvent(event_id_, web_response, event_dispatch_time_);
-}
-
-void FetchRespondWithObserver::OnResponseFulfilled(const ScriptValue& value) {
- DCHECK(GetExecutionContext());
- if (!V8Response::hasInstance(value.V8Value(),
- ToIsolate(GetExecutionContext()))) {
- OnResponseRejected(ServiceWorkerResponseError::kNoV8Instance);
- return;
- }
- Response* response = V8Response::ToImplWithTypeCheck(
- ToIsolate(GetExecutionContext()), value.V8Value());
- // "If one of the following conditions is true, return a network error:
- // - |response|'s type is |error|.
- // - |request|'s mode is |same-origin| and |response|'s type is |cors|.
- // - |request|'s mode is not |no-cors| and response's type is |opaque|.
- // - |request| is a client request and |response|'s type is neither
- // |basic| nor |default|."
- const network::mojom::FetchResponseType response_type =
- response->GetResponse()->GetType();
- if (response_type == network::mojom::FetchResponseType::kError) {
- OnResponseRejected(ServiceWorkerResponseError::kResponseTypeError);
- return;
- }
- if (response_type == network::mojom::FetchResponseType::kCORS &&
- request_mode_ == network::mojom::FetchRequestMode::kSameOrigin) {
- OnResponseRejected(
- ServiceWorkerResponseError::kResponseTypeCORSForRequestModeSameOrigin);
- return;
- }
- if (response_type == network::mojom::FetchResponseType::kOpaque) {
- if (request_mode_ != network::mojom::FetchRequestMode::kNoCORS) {
- OnResponseRejected(ServiceWorkerResponseError::kResponseTypeOpaque);
- return;
- }
-
- // The request mode of client requests should be "same-origin" but it is
- // not explicitly stated in the spec yet. So we need to check here.
- // FIXME: Set the request mode of client requests to "same-origin" and
- // remove this check when the spec will be updated.
- // Spec issue: https://github.com/whatwg/fetch/issues/101
- if (IsClientRequest(frame_type_, request_context_)) {
- OnResponseRejected(
- ServiceWorkerResponseError::kResponseTypeOpaqueForClientRequest);
- return;
- }
- }
- if (redirect_mode_ != network::mojom::FetchRedirectMode::kManual &&
- response_type == network::mojom::FetchResponseType::kOpaqueRedirect) {
- OnResponseRejected(ServiceWorkerResponseError::kResponseTypeOpaqueRedirect);
- return;
- }
- if (redirect_mode_ != network::mojom::FetchRedirectMode::kFollow &&
- response->redirected()) {
- OnResponseRejected(
- ServiceWorkerResponseError::kRedirectedResponseForNotFollowRequest);
- return;
- }
- if (response->IsBodyLocked()) {
- OnResponseRejected(ServiceWorkerResponseError::kBodyLocked);
- return;
- }
- if (response->bodyUsed()) {
- OnResponseRejected(ServiceWorkerResponseError::kBodyUsed);
- return;
- }
-
- WebServiceWorkerResponse web_response;
- response->PopulateWebServiceWorkerResponse(web_response);
-
- BodyStreamBuffer* buffer = response->InternalBodyBuffer();
- if (buffer) {
- scoped_refptr<BlobDataHandle> blob_data_handle =
- buffer->DrainAsBlobDataHandle(
- BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize);
- if (blob_data_handle) {
- // Handle the blob response body.
- web_response.SetBlobDataHandle(blob_data_handle);
- ServiceWorkerGlobalScopeClient::From(GetExecutionContext())
- ->RespondToFetchEvent(event_id_, web_response, event_dispatch_time_);
- return;
- }
- // Handle the stream response body.
- mojo::ScopedDataPipeProducerHandle producer;
- mojo::ScopedDataPipeConsumerHandle consumer;
- MojoResult result = mojo::CreateDataPipe(nullptr, &producer, &consumer);
- if (result != MOJO_RESULT_OK) {
- OnResponseRejected(ServiceWorkerResponseError::kDataPipeCreationFailed);
- return;
- }
- DCHECK(producer.is_valid());
- DCHECK(consumer.is_valid());
-
- std::unique_ptr<WebServiceWorkerStreamHandle> body_stream_handle =
- std::make_unique<WebServiceWorkerStreamHandle>(std::move(consumer));
- ServiceWorkerGlobalScopeClient::From(GetExecutionContext())
- ->RespondToFetchEventWithResponseStream(event_id_, web_response,
- body_stream_handle.get(),
- event_dispatch_time_);
-
- buffer->StartLoading(FetchDataLoader::CreateLoaderAsDataPipe(
- std::move(producer), task_runner_),
- new FetchLoaderClient(std::move(body_stream_handle)));
- return;
- }
- ServiceWorkerGlobalScopeClient::From(GetExecutionContext())
- ->RespondToFetchEvent(event_id_, web_response, event_dispatch_time_);
-}
-
-void FetchRespondWithObserver::OnNoResponse() {
- ServiceWorkerGlobalScopeClient::From(GetExecutionContext())
- ->RespondToFetchEventWithNoResponse(event_id_, event_dispatch_time_);
-}
-
-FetchRespondWithObserver::FetchRespondWithObserver(
- ExecutionContext* context,
- int fetch_event_id,
- const KURL& request_url,
- network::mojom::FetchRequestMode request_mode,
- network::mojom::FetchRedirectMode redirect_mode,
- network::mojom::RequestContextFrameType frame_type,
- WebURLRequest::RequestContext request_context,
- WaitUntilObserver* observer)
- : RespondWithObserver(context, fetch_event_id, observer),
- request_url_(request_url),
- request_mode_(request_mode),
- redirect_mode_(redirect_mode),
- frame_type_(frame_type),
- request_context_(request_context),
- task_runner_(context->GetTaskRunner(TaskType::kNetworking)) {}
-
-void FetchRespondWithObserver::Trace(blink::Visitor* visitor) {
- RespondWithObserver::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/fetch_respond_with_observer.h b/chromium/third_party/blink/renderer/modules/serviceworkers/fetch_respond_with_observer.h
deleted file mode 100644
index 169d233fa54..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/fetch_respond_with_observer.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_FETCH_RESPOND_WITH_OBSERVER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_FETCH_RESPOND_WITH_OBSERVER_H_
-
-#include "services/network/public/mojom/fetch_api.mojom-blink.h"
-#include "third_party/blink/public/platform/web_url_request.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/modules/serviceworkers/respond_with_observer.h"
-#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-
-namespace blink {
-
-class ExecutionContext;
-class ScriptValue;
-class WaitUntilObserver;
-
-// This class observes the service worker's handling of a FetchEvent and
-// notifies the client.
-class MODULES_EXPORT FetchRespondWithObserver : public RespondWithObserver {
- public:
- ~FetchRespondWithObserver() override = default;
-
- static FetchRespondWithObserver* Create(
- ExecutionContext*,
- int fetch_event_id,
- const KURL& request_url,
- network::mojom::FetchRequestMode,
- network::mojom::FetchRedirectMode,
- network::mojom::RequestContextFrameType,
- WebURLRequest::RequestContext,
- WaitUntilObserver*);
-
- void OnResponseRejected(mojom::ServiceWorkerResponseError) override;
- void OnResponseFulfilled(const ScriptValue&) override;
- void OnNoResponse() override;
-
- void Trace(blink::Visitor*) override;
-
- protected:
- FetchRespondWithObserver(ExecutionContext*,
- int fetch_event_id,
- const KURL& request_url,
- network::mojom::FetchRequestMode,
- network::mojom::FetchRedirectMode,
- network::mojom::RequestContextFrameType,
- WebURLRequest::RequestContext,
- WaitUntilObserver*);
-
- private:
- const KURL request_url_;
- const network::mojom::FetchRequestMode request_mode_;
- const network::mojom::FetchRedirectMode redirect_mode_;
- const network::mojom::RequestContextFrameType frame_type_;
- const WebURLRequest::RequestContext request_context_;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_FETCH_RESPOND_WITH_OBSERVER_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/install_event.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/install_event.cc
deleted file mode 100644
index db741d3ec82..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/install_event.cc
+++ /dev/null
@@ -1,43 +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/modules/serviceworkers/install_event.h"
-
-#include "third_party/blink/public/platform/web_security_origin.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-
-namespace blink {
-
-InstallEvent* InstallEvent::Create(const AtomicString& type,
- const ExtendableEventInit& event_init) {
- return new InstallEvent(type, event_init);
-}
-
-InstallEvent* InstallEvent::Create(const AtomicString& type,
- const ExtendableEventInit& event_init,
- int event_id,
- WaitUntilObserver* observer) {
- return new InstallEvent(type, event_init, event_id, observer);
-}
-
-InstallEvent::~InstallEvent() = default;
-
-const AtomicString& InstallEvent::InterfaceName() const {
- return EventNames::InstallEvent;
-}
-
-InstallEvent::InstallEvent(const AtomicString& type,
- const ExtendableEventInit& initializer)
- : ExtendableEvent(type, initializer), event_id_(0) {}
-
-InstallEvent::InstallEvent(const AtomicString& type,
- const ExtendableEventInit& initializer,
- int event_id,
- WaitUntilObserver* observer)
- : ExtendableEvent(type, initializer, observer), event_id_(event_id) {}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/install_event.h b/chromium/third_party/blink/renderer/modules/serviceworkers/install_event.h
deleted file mode 100644
index b740ea0f051..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/install_event.h
+++ /dev/null
@@ -1,40 +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_MODULES_SERVICEWORKERS_INSTALL_EVENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_INSTALL_EVENT_H_
-
-#include "third_party/blink/renderer/modules/event_modules.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/modules/serviceworkers/extendable_event.h"
-
-namespace blink {
-
-class MODULES_EXPORT InstallEvent : public ExtendableEvent {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- static InstallEvent* Create(const AtomicString& type,
- const ExtendableEventInit&);
- static InstallEvent* Create(const AtomicString& type,
- const ExtendableEventInit&,
- int event_id,
- WaitUntilObserver*);
-
- ~InstallEvent() override;
-
- const AtomicString& InterfaceName() const override;
-
- protected:
- InstallEvent(const AtomicString& type, const ExtendableEventInit&);
- InstallEvent(const AtomicString& type,
- const ExtendableEventInit&,
- int event_id,
- WaitUntilObserver*);
- const int event_id_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_INSTALL_EVENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_callbacks.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_callbacks.cc
deleted file mode 100644
index 8cf72b1e031..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_callbacks.cc
+++ /dev/null
@@ -1,90 +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/modules/serviceworkers/navigation_preload_callbacks.h"
-
-#include "third_party/blink/public/platform/modules/serviceworker/web_navigation_preload_state.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/modules/serviceworkers/navigation_preload_state.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_error.h"
-
-namespace blink {
-
-EnableNavigationPreloadCallbacks::EnableNavigationPreloadCallbacks(
- ScriptPromiseResolver* resolver)
- : resolver_(resolver) {
- DCHECK(resolver_);
-}
-
-EnableNavigationPreloadCallbacks::~EnableNavigationPreloadCallbacks() = default;
-
-void EnableNavigationPreloadCallbacks::OnSuccess() {
- if (!resolver_->GetExecutionContext() ||
- resolver_->GetExecutionContext()->IsContextDestroyed())
- return;
- resolver_->Resolve();
-}
-
-void EnableNavigationPreloadCallbacks::OnError(
- const WebServiceWorkerError& error) {
- if (!resolver_->GetExecutionContext() ||
- resolver_->GetExecutionContext()->IsContextDestroyed())
- return;
- resolver_->Reject(ServiceWorkerError::Take(resolver_.Get(), error));
-}
-
-GetNavigationPreloadStateCallbacks::GetNavigationPreloadStateCallbacks(
- ScriptPromiseResolver* resolver)
- : resolver_(resolver) {
- DCHECK(resolver_);
-}
-
-GetNavigationPreloadStateCallbacks::~GetNavigationPreloadStateCallbacks() =
- default;
-
-void GetNavigationPreloadStateCallbacks::OnSuccess(
- const WebNavigationPreloadState& state) {
- if (!resolver_->GetExecutionContext() ||
- resolver_->GetExecutionContext()->IsContextDestroyed())
- return;
- NavigationPreloadState dict;
- dict.setEnabled(state.enabled);
- dict.setHeaderValue(state.header_value);
- resolver_->Resolve(dict);
-}
-
-void GetNavigationPreloadStateCallbacks::OnError(
- const WebServiceWorkerError& error) {
- if (!resolver_->GetExecutionContext() ||
- resolver_->GetExecutionContext()->IsContextDestroyed())
- return;
- resolver_->Reject(ServiceWorkerError::Take(resolver_.Get(), error));
-}
-
-SetNavigationPreloadHeaderCallbacks::SetNavigationPreloadHeaderCallbacks(
- ScriptPromiseResolver* resolver)
- : resolver_(resolver) {
- DCHECK(resolver_);
-}
-
-SetNavigationPreloadHeaderCallbacks::~SetNavigationPreloadHeaderCallbacks() =
- default;
-
-void SetNavigationPreloadHeaderCallbacks::OnSuccess() {
- if (!resolver_->GetExecutionContext() ||
- resolver_->GetExecutionContext()->IsContextDestroyed())
- return;
- resolver_->Resolve();
-}
-
-void SetNavigationPreloadHeaderCallbacks::OnError(
- const WebServiceWorkerError& error) {
- if (!resolver_->GetExecutionContext() ||
- resolver_->GetExecutionContext()->IsContextDestroyed())
- return;
- resolver_->Reject(ServiceWorkerError::Take(resolver_.Get(), error));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_callbacks.h b/chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_callbacks.h
deleted file mode 100644
index 0539d4545da..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_callbacks.h
+++ /dev/null
@@ -1,67 +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_MODULES_SERVICEWORKERS_NAVIGATION_PRELOAD_CALLBACKS_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_NAVIGATION_PRELOAD_CALLBACKS_H_
-
-#include "base/macros.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_registration.h"
-#include "third_party/blink/renderer/platform/heap/persistent.h"
-
-namespace blink {
-
-class ScriptPromiseResolver;
-struct WebNavigationPreloadState;
-struct WebServiceWorkerError;
-
-class EnableNavigationPreloadCallbacks final
- : public WebServiceWorkerRegistration::WebEnableNavigationPreloadCallbacks {
- public:
- explicit EnableNavigationPreloadCallbacks(ScriptPromiseResolver*);
- ~EnableNavigationPreloadCallbacks() override;
-
- // WebEnableNavigationPreloadCallbacks interface.
- void OnSuccess() override;
- void OnError(const WebServiceWorkerError&) override;
-
- private:
- Persistent<ScriptPromiseResolver> resolver_;
- DISALLOW_COPY_AND_ASSIGN(EnableNavigationPreloadCallbacks);
-};
-
-class GetNavigationPreloadStateCallbacks final
- : public WebServiceWorkerRegistration::
- WebGetNavigationPreloadStateCallbacks {
- public:
- explicit GetNavigationPreloadStateCallbacks(ScriptPromiseResolver*);
- ~GetNavigationPreloadStateCallbacks() override;
-
- // WebGetNavigationPreloadStateCallbacks interface.
- void OnSuccess(const WebNavigationPreloadState&) override;
- void OnError(const WebServiceWorkerError&) override;
-
- private:
- Persistent<ScriptPromiseResolver> resolver_;
- DISALLOW_COPY_AND_ASSIGN(GetNavigationPreloadStateCallbacks);
-};
-
-class SetNavigationPreloadHeaderCallbacks final
- : public WebServiceWorkerRegistration::
- WebSetNavigationPreloadHeaderCallbacks {
- public:
- explicit SetNavigationPreloadHeaderCallbacks(ScriptPromiseResolver*);
- ~SetNavigationPreloadHeaderCallbacks() override;
-
- // WebSetNavigationPreloadHeaderCallbacks interface.
- void OnSuccess(void) override;
- void OnError(const WebServiceWorkerError&) override;
-
- private:
- Persistent<ScriptPromiseResolver> resolver_;
- DISALLOW_COPY_AND_ASSIGN(SetNavigationPreloadHeaderCallbacks);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_NAVIGATION_PRELOAD_CALLBACKS_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_manager.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_manager.cc
deleted file mode 100644
index fdd37b2e177..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_manager.cc
+++ /dev/null
@@ -1,70 +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/modules/serviceworkers/navigation_preload_manager.h"
-
-#include <memory>
-
-#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
-#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/modules/serviceworkers/navigation_preload_callbacks.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_container_client.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
-#include "third_party/blink/renderer/platform/network/http_parsers.h"
-
-namespace blink {
-
-ScriptPromise NavigationPreloadManager::enable(ScriptState* script_state) {
- return SetEnabled(true, script_state);
-}
-
-ScriptPromise NavigationPreloadManager::disable(ScriptState* script_state) {
- return SetEnabled(false, script_state);
-}
-
-ScriptPromise NavigationPreloadManager::setHeaderValue(
- ScriptState* script_state,
- const String& value) {
- if (!IsValidHTTPHeaderValue(value)) {
- return ScriptPromise::Reject(
- script_state, V8ThrowException::CreateTypeError(
- script_state->GetIsolate(),
- "The string provided to setHeaderValue ('" + value +
- "') is not a valid HTTP header field value."));
- }
-
- ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- ScriptPromise promise = resolver->Promise();
- registration_->WebRegistration()->SetNavigationPreloadHeader(
- value, std::make_unique<SetNavigationPreloadHeaderCallbacks>(resolver));
- return promise;
-}
-
-ScriptPromise NavigationPreloadManager::getState(ScriptState* script_state) {
- ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- ScriptPromise promise = resolver->Promise();
- registration_->WebRegistration()->GetNavigationPreloadState(
- std::make_unique<GetNavigationPreloadStateCallbacks>(resolver));
- return promise;
-}
-
-NavigationPreloadManager::NavigationPreloadManager(
- ServiceWorkerRegistration* registration)
- : registration_(registration) {}
-
-ScriptPromise NavigationPreloadManager::SetEnabled(bool enable,
- ScriptState* script_state) {
- ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- ScriptPromise promise = resolver->Promise();
- registration_->WebRegistration()->EnableNavigationPreload(
- enable, std::make_unique<EnableNavigationPreloadCallbacks>(resolver));
- return promise;
-}
-
-void NavigationPreloadManager::Trace(blink::Visitor* visitor) {
- visitor->Trace(registration_);
- ScriptWrappable::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_manager.h b/chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_manager.h
deleted file mode 100644
index 23af255924e..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/navigation_preload_manager.h
+++ /dev/null
@@ -1,42 +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_MODULES_SERVICEWORKERS_NAVIGATION_PRELOAD_MANAGER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_NAVIGATION_PRELOAD_MANAGER_H_
-
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-
-namespace blink {
-
-class ServiceWorkerRegistration;
-
-class NavigationPreloadManager final : public ScriptWrappable {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- static NavigationPreloadManager* Create(
- ServiceWorkerRegistration* registration) {
- return new NavigationPreloadManager(registration);
- }
-
- ScriptPromise enable(ScriptState*);
- ScriptPromise disable(ScriptState*);
- ScriptPromise setHeaderValue(ScriptState*, const String& value);
- ScriptPromise getState(ScriptState*);
-
- void Trace(blink::Visitor*) override;
-
- private:
- explicit NavigationPreloadManager(ServiceWorkerRegistration*);
-
- ScriptPromise SetEnabled(bool enable, ScriptState*);
-
- Member<ServiceWorkerRegistration> registration_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_NAVIGATION_PRELOAD_MANAGER_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/navigator_service_worker.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/navigator_service_worker.cc
deleted file mode 100644
index aadb540bb72..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/navigator_service_worker.cc
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/serviceworkers/navigator_service_worker.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/frame/navigator.h"
-#include "third_party/blink/renderer/core/frame/use_counter.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_container.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-
-namespace blink {
-
-NavigatorServiceWorker::NavigatorServiceWorker(Navigator& navigator) {}
-
-NavigatorServiceWorker* NavigatorServiceWorker::From(Document& document) {
- if (!document.GetFrame() || !document.GetFrame()->DomWindow())
- return nullptr;
- Navigator& navigator = *document.GetFrame()->DomWindow()->navigator();
- return &From(navigator);
-}
-
-NavigatorServiceWorker& NavigatorServiceWorker::From(Navigator& navigator) {
- NavigatorServiceWorker* supplement = ToNavigatorServiceWorker(navigator);
- if (!supplement) {
- supplement = new NavigatorServiceWorker(navigator);
- ProvideTo(navigator, supplement);
- }
- if (navigator.GetFrame() && navigator.GetFrame()
- ->GetSecurityContext()
- ->GetSecurityOrigin()
- ->CanAccessServiceWorkers()) {
- // Ensure ServiceWorkerContainer. It can be cleared regardless of
- // |supplement|. See comments in NavigatorServiceWorker::serviceWorker() for
- // details.
- supplement->serviceWorker(navigator.GetFrame(), ASSERT_NO_EXCEPTION);
- }
- return *supplement;
-}
-
-NavigatorServiceWorker* NavigatorServiceWorker::ToNavigatorServiceWorker(
- Navigator& navigator) {
- return Supplement<Navigator>::From<NavigatorServiceWorker>(navigator);
-}
-
-const char NavigatorServiceWorker::kSupplementName[] = "NavigatorServiceWorker";
-
-ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker(
- ScriptState* script_state,
- Navigator& navigator,
- ExceptionState& exception_state) {
- ExecutionContext* execution_context = ExecutionContext::From(script_state);
- DCHECK(!navigator.GetFrame() ||
- execution_context->GetSecurityOrigin()->CanAccess(
- navigator.GetFrame()->GetSecurityContext()->GetSecurityOrigin()));
- return NavigatorServiceWorker::From(navigator).serviceWorker(
- navigator.GetFrame(), exception_state);
-}
-
-ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker(
- ScriptState* script_state,
- Navigator& navigator,
- String& error_message) {
- ExecutionContext* execution_context = ExecutionContext::From(script_state);
- DCHECK(!navigator.GetFrame() ||
- execution_context->GetSecurityOrigin()->CanAccess(
- navigator.GetFrame()->GetSecurityContext()->GetSecurityOrigin()));
- return NavigatorServiceWorker::From(navigator).serviceWorker(
- navigator.GetFrame(), error_message);
-}
-
-ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker(
- LocalFrame* frame,
- ExceptionState& exception_state) {
- String error_message;
- ServiceWorkerContainer* result = serviceWorker(frame, error_message);
- if (!error_message.IsEmpty()) {
- DCHECK(!result);
- exception_state.ThrowSecurityError(error_message);
- }
- return result;
-}
-
-ServiceWorkerContainer* NavigatorServiceWorker::serviceWorker(
- LocalFrame* frame,
- String& error_message) {
- if (frame && !frame->GetSecurityContext()
- ->GetSecurityOrigin()
- ->CanAccessServiceWorkers()) {
- if (frame->GetSecurityContext()->IsSandboxed(kSandboxOrigin)) {
- error_message =
- "Service worker is disabled because the context is sandboxed and "
- "lacks the 'allow-same-origin' flag.";
- } else {
- error_message =
- "Access to service workers is denied in this document origin.";
- }
- return nullptr;
- } else if (frame &&
- frame->GetSecurityContext()->GetSecurityOrigin()->IsLocal()) {
- UseCounter::Count(frame, WebFeature::kFileAccessedServiceWorker);
- }
- if (!service_worker_ && frame) {
- // We need to create a new ServiceWorkerContainer when the frame
- // navigates to a new document. In practice, this happens only when the
- // frame navigates from the initial empty page to a new same-origin page.
- DCHECK(frame->DomWindow());
- service_worker_ = ServiceWorkerContainer::Create(
- frame->DomWindow()->GetExecutionContext(), this);
- }
- return service_worker_.Get();
-}
-
-void NavigatorServiceWorker::ClearServiceWorker() {
- service_worker_ = nullptr;
-}
-
-void NavigatorServiceWorker::Trace(blink::Visitor* visitor) {
- visitor->Trace(service_worker_);
- Supplement<Navigator>::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/navigator_service_worker.h b/chromium/third_party/blink/renderer/modules/serviceworkers/navigator_service_worker.h
deleted file mode 100644
index 73734a1a359..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/navigator_service_worker.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_NAVIGATOR_SERVICE_WORKER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_NAVIGATOR_SERVICE_WORKER_H_
-
-#include "third_party/blink/renderer/core/frame/navigator.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/supplementable.h"
-
-namespace blink {
-
-class Document;
-class ExceptionState;
-class Navigator;
-class ScriptState;
-class ServiceWorkerContainer;
-
-class MODULES_EXPORT NavigatorServiceWorker final
- : public GarbageCollected<NavigatorServiceWorker>,
- public Supplement<Navigator> {
- USING_GARBAGE_COLLECTED_MIXIN(NavigatorServiceWorker);
-
- public:
- static const char kSupplementName[];
-
- static NavigatorServiceWorker* From(Document&);
- static NavigatorServiceWorker& From(Navigator&);
- static NavigatorServiceWorker* ToNavigatorServiceWorker(Navigator&);
- static ServiceWorkerContainer* serviceWorker(ScriptState*,
- Navigator&,
- ExceptionState&);
- static ServiceWorkerContainer* serviceWorker(ScriptState*,
- Navigator&,
- String& error_message);
- void ClearServiceWorker();
-
- void Trace(blink::Visitor*) override;
-
- private:
- explicit NavigatorServiceWorker(Navigator&);
- ServiceWorkerContainer* serviceWorker(LocalFrame*, ExceptionState&);
- ServiceWorkerContainer* serviceWorker(LocalFrame*, String& error_message);
-
- Member<ServiceWorkerContainer> service_worker_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_NAVIGATOR_SERVICE_WORKER_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/navigator_service_worker.idl b/chromium/third_party/blink/renderer/modules/serviceworkers/navigator_service_worker.idl
deleted file mode 100644
index ef59d5d5e4e..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/navigator_service_worker.idl
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://w3c.github.io/ServiceWorker/#navigator-serviceworker
-[
- ImplementedAs=NavigatorServiceWorker
-] partial interface Navigator {
- [RaisesException, CallWith=ScriptState] readonly attribute ServiceWorkerContainer serviceWorker;
-};
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/respond_with_observer.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/respond_with_observer.cc
deleted file mode 100644
index 9624d038f1d..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/respond_with_observer.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/serviceworkers/respond_with_observer.h"
-
-#include <v8.h>
-
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_response.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/modules/serviceworkers/wait_until_observer.h"
-
-using blink::mojom::ServiceWorkerResponseError;
-
-namespace blink {
-
-void RespondWithObserver::ContextDestroyed(ExecutionContext*) {
- if (observer_) {
- DCHECK_EQ(kPending, state_);
- observer_.Clear();
- }
- state_ = kDone;
-}
-
-void RespondWithObserver::WillDispatchEvent() {
- event_dispatch_time_ = WTF::CurrentTime();
-}
-
-void RespondWithObserver::DidDispatchEvent(
- DispatchEventResult dispatch_result) {
- DCHECK(GetExecutionContext());
- if (state_ != kInitial)
- return;
-
- if (dispatch_result == DispatchEventResult::kNotCanceled) {
- OnNoResponse();
- } else {
- OnResponseRejected(ServiceWorkerResponseError::kDefaultPrevented);
- }
-
- state_ = kDone;
- observer_.Clear();
-}
-
-void RespondWithObserver::RespondWith(ScriptState* script_state,
- ScriptPromise script_promise,
- ExceptionState& exception_state) {
- if (state_ != kInitial) {
- exception_state.ThrowDOMException(
- kInvalidStateError, "The event has already been responded to.");
- return;
- }
-
- state_ = kPending;
- observer_->WaitUntil(
- script_state, script_promise, exception_state,
- WTF::BindRepeating(&RespondWithObserver::ResponseWasFulfilled,
- WrapPersistent(this)),
- WTF::BindRepeating(&RespondWithObserver::ResponseWasRejected,
- WrapPersistent(this),
- ServiceWorkerResponseError::kPromiseRejected));
-}
-
-void RespondWithObserver::ResponseWasRejected(ServiceWorkerResponseError error,
- const ScriptValue& value) {
- OnResponseRejected(error);
- state_ = kDone;
- observer_.Clear();
-}
-
-void RespondWithObserver::ResponseWasFulfilled(const ScriptValue& value) {
- OnResponseFulfilled(value);
- state_ = kDone;
- observer_.Clear();
-}
-
-RespondWithObserver::RespondWithObserver(ExecutionContext* context,
- int event_id,
- WaitUntilObserver* observer)
- : ContextLifecycleObserver(context),
- event_id_(event_id),
- state_(kInitial),
- observer_(observer) {}
-
-void RespondWithObserver::Trace(blink::Visitor* visitor) {
- visitor->Trace(observer_);
- ContextLifecycleObserver::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/respond_with_observer.h b/chromium/third_party/blink/renderer/modules/serviceworkers/respond_with_observer.h
deleted file mode 100644
index dbdf81615e4..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/respond_with_observer.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_RESPOND_WITH_OBSERVER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_RESPOND_WITH_OBSERVER_H_
-
-#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-shared.h"
-#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
-#include "third_party/blink/renderer/core/dom/events/event_target.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-
-namespace blink {
-
-class ExceptionState;
-class ExecutionContext;
-class ScriptPromise;
-class ScriptState;
-class ScriptValue;
-class WaitUntilObserver;
-
-// This is a base class to implement respondWith. The respondWith has the three
-// types of results: fulfilled, rejected and not called. Derived classes for
-// each event should implement the procedure of the three behaviors by
-// overriding onResponseFulfilled, onResponseRejected and onNoResponse.
-class MODULES_EXPORT RespondWithObserver
- : public GarbageCollectedFinalized<RespondWithObserver>,
- public ContextLifecycleObserver {
- USING_GARBAGE_COLLECTED_MIXIN(RespondWithObserver);
-
- public:
- virtual ~RespondWithObserver() = default;
-
- void ContextDestroyed(ExecutionContext*) override;
-
- void WillDispatchEvent();
- void DidDispatchEvent(DispatchEventResult dispatch_result);
-
- // The respondWith() observes the promise until the given promise is resolved
- // or rejected and then delays calling ServiceWorkerGlobalScopeClient::
- // didHandle*Event() in order to notify the result to the client.
- void RespondWith(ScriptState*, ScriptPromise, ExceptionState&);
-
- // Called when the respondWith() promise was rejected.
- virtual void OnResponseRejected(mojom::ServiceWorkerResponseError) = 0;
-
- // Called when the respondWith() promise was fulfilled.
- virtual void OnResponseFulfilled(const ScriptValue&) = 0;
-
- // Called when the event handler finished without calling respondWith().
- virtual void OnNoResponse() = 0;
-
- void Trace(blink::Visitor*) override;
-
- protected:
- RespondWithObserver(ExecutionContext*, int event_id, WaitUntilObserver*);
- const int event_id_;
- double event_dispatch_time_ = 0;
-
- private:
- class ThenFunction;
-
- void ResponseWasRejected(mojom::ServiceWorkerResponseError,
- const ScriptValue&);
- void ResponseWasFulfilled(const ScriptValue&);
-
- enum State { kInitial, kPending, kDone };
- State state_;
-
- // RespondWith should ensure the ExtendableEvent is alive until the promise
- // passed to RespondWith is resolved. The lifecycle of the ExtendableEvent
- // is controlled by WaitUntilObserver, so not only
- // WaitUntilObserver::ThenFunction but RespondWith needs to have a strong
- // reference to the WaitUntilObserver.
- Member<WaitUntilObserver> observer_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_RESPOND_WITH_OBSERVER_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker.cc
deleted file mode 100644
index 40960b98523..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker.cc
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * 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/modules/serviceworkers/service_worker.h"
-
-#include <memory>
-#include "third_party/blink/public/mojom/service_worker/service_worker_state.mojom-blink.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/messaging/blink_transferable_message.h"
-#include "third_party/blink/renderer/core/messaging/message_port.h"
-#include "third_party/blink/renderer/modules/event_target_modules.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_container_client.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-
-namespace blink {
-
-const AtomicString& ServiceWorker::InterfaceName() const {
- return EventTargetNames::ServiceWorker;
-}
-
-void ServiceWorker::postMessage(ScriptState* script_state,
- scoped_refptr<SerializedScriptValue> message,
- const MessagePortArray& ports,
- ExceptionState& exception_state) {
- ServiceWorkerContainerClient* client =
- ServiceWorkerContainerClient::From(GetExecutionContext());
- if (!client || !client->Provider()) {
- exception_state.ThrowDOMException(
- kInvalidStateError,
- "Failed to post a message: No associated provider is available.");
- return;
- }
-
- BlinkTransferableMessage msg;
- msg.message = message;
- msg.ports = MessagePort::DisentanglePorts(
- ExecutionContext::From(script_state), ports, exception_state);
- if (exception_state.HadException())
- return;
-
- if (handle_->ServiceWorker()->GetState() ==
- mojom::blink::ServiceWorkerState::kRedundant) {
- exception_state.ThrowDOMException(kInvalidStateError,
- "ServiceWorker is in redundant state.");
- return;
- }
-
- handle_->ServiceWorker()->PostMessageToServiceWorker(
- ToTransferableMessage(std::move(msg)));
-}
-
-ScriptPromise ServiceWorker::InternalsTerminate(ScriptState* script_state) {
- ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- ScriptPromise promise = resolver->Promise();
- handle_->ServiceWorker()->TerminateForTesting(
- std::make_unique<CallbackPromiseAdapter<void, void>>(resolver));
- return promise;
-}
-
-void ServiceWorker::DispatchStateChangeEvent() {
- this->DispatchEvent(Event::Create(EventTypeNames::statechange));
-}
-
-String ServiceWorker::scriptURL() const {
- return handle_->ServiceWorker()->Url().GetString();
-}
-
-String ServiceWorker::state() const {
- switch (handle_->ServiceWorker()->GetState()) {
- case mojom::blink::ServiceWorkerState::kUnknown:
- // The web platform should never see this internal state
- NOTREACHED();
- return "unknown";
- case mojom::blink::ServiceWorkerState::kInstalling:
- return "installing";
- case mojom::blink::ServiceWorkerState::kInstalled:
- return "installed";
- case mojom::blink::ServiceWorkerState::kActivating:
- return "activating";
- case mojom::blink::ServiceWorkerState::kActivated:
- return "activated";
- case mojom::blink::ServiceWorkerState::kRedundant:
- return "redundant";
- }
- NOTREACHED();
- return g_null_atom;
-}
-
-ServiceWorker* ServiceWorker::From(
- ExecutionContext* execution_context,
- std::unique_ptr<WebServiceWorker::Handle> handle) {
- return GetOrCreate(execution_context, std::move(handle));
-}
-
-bool ServiceWorker::HasPendingActivity() const {
- if (was_stopped_)
- return false;
- return handle_->ServiceWorker()->GetState() !=
- mojom::blink::ServiceWorkerState::kRedundant;
-}
-
-void ServiceWorker::ContextDestroyed(ExecutionContext*) {
- was_stopped_ = true;
-}
-
-ServiceWorker* ServiceWorker::GetOrCreate(
- ExecutionContext* execution_context,
- std::unique_ptr<WebServiceWorker::Handle> handle) {
- if (!handle)
- return nullptr;
-
- ServiceWorker* existing_worker =
- static_cast<ServiceWorker*>(handle->ServiceWorker()->Proxy());
- if (existing_worker) {
- DCHECK_EQ(existing_worker->GetExecutionContext(), execution_context);
- return existing_worker;
- }
-
- return new ServiceWorker(execution_context, std::move(handle));
-}
-
-ServiceWorker::ServiceWorker(ExecutionContext* execution_context,
- std::unique_ptr<WebServiceWorker::Handle> handle)
- : AbstractWorker(execution_context),
- handle_(std::move(handle)),
- was_stopped_(false) {
- DCHECK(handle_);
- handle_->ServiceWorker()->SetProxy(this);
-}
-
-ServiceWorker::~ServiceWorker() = default;
-
-void ServiceWorker::Trace(blink::Visitor* visitor) {
- AbstractWorker::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker.h b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker.h
deleted file mode 100644
index b48e57098eb..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * 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_MODULES_SERVICEWORKERS_SERVICE_WORKER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_H_
-
-#include <memory>
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_proxy.h"
-#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
-#include "third_party/blink/renderer/core/workers/abstract_worker.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-
-namespace blink {
-
-class ScriptState;
-
-class MODULES_EXPORT ServiceWorker final
- : public AbstractWorker,
- public ActiveScriptWrappable<ServiceWorker>,
- public WebServiceWorkerProxy {
- DEFINE_WRAPPERTYPEINFO();
- USING_GARBAGE_COLLECTED_MIXIN(ServiceWorker);
-
- public:
- static ServiceWorker* From(ExecutionContext*,
- std::unique_ptr<WebServiceWorker::Handle>);
-
- ~ServiceWorker() override;
- void Trace(blink::Visitor*) override;
-
- // Eager finalization needed to promptly release owned WebServiceWorker.
- EAGERLY_FINALIZE();
-
- void postMessage(ScriptState*,
- scoped_refptr<SerializedScriptValue> message,
- const MessagePortArray&,
- ExceptionState&);
- static bool CanTransferArrayBuffersAndImageBitmaps() { return false; }
-
- String scriptURL() const;
- String state() const;
- DEFINE_ATTRIBUTE_EVENT_LISTENER(statechange);
-
- ServiceWorker* ToServiceWorker() override { return this; }
-
- // ScriptWrappable overrides.
- bool HasPendingActivity() const final;
-
- // WebServiceWorkerProxy overrides.
- void DispatchStateChangeEvent() override;
-
- // AbstractWorker overrides.
- const AtomicString& InterfaceName() const override;
-
- ScriptPromise InternalsTerminate(ScriptState*);
-
- private:
- static ServiceWorker* GetOrCreate(ExecutionContext*,
- std::unique_ptr<WebServiceWorker::Handle>);
- ServiceWorker(ExecutionContext*, std::unique_ptr<WebServiceWorker::Handle>);
-
- // PausableObject overrides.
- void ContextDestroyed(ExecutionContext*) override;
-
- // A handle to the service worker representation in the embedder.
- std::unique_ptr<WebServiceWorker::Handle> handle_;
- bool was_stopped_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker.idl b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker.idl
deleted file mode 100644
index 038367d1518..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker.idl
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * 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.
- */
-
-// https://w3c.github.io/ServiceWorker/#serviceworker-interface
-
-enum ServiceWorkerState {
- "installing",
- "installed",
- "activating",
- "activated",
- "redundant"
-};
-
-[
- ActiveScriptWrappable
-] interface ServiceWorker : EventTarget {
-
- [PostMessage, RaisesException] void postMessage(any message, optional sequence<object> transfer);
-
- readonly attribute USVString scriptURL;
- readonly attribute ServiceWorkerState state;
-
- attribute EventHandler onstatechange;
-};
-
-ServiceWorker implements AbstractWorker;
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_client.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_client.cc
deleted file mode 100644
index 9a5af7dd569..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_client.cc
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_client.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_window_client.h"
-
-#include <memory>
-#include "base/memory/scoped_refptr.h"
-#include "services/network/public/mojom/request_context_frame_type.mojom-blink.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom-blink.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/frame/use_counter.h"
-#include "third_party/blink/renderer/core/messaging/blink_transferable_message.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-
-namespace blink {
-
-ServiceWorkerClient* ServiceWorkerClient::Take(
- ScriptPromiseResolver*,
- std::unique_ptr<WebServiceWorkerClientInfo> web_client) {
- if (!web_client)
- return nullptr;
-
- switch (web_client->client_type) {
- case mojom::ServiceWorkerClientType::kWindow:
- return ServiceWorkerWindowClient::Create(*web_client);
- case mojom::ServiceWorkerClientType::kSharedWorker:
- return ServiceWorkerClient::Create(*web_client);
- case mojom::ServiceWorkerClientType::kAll:
- NOTREACHED();
- return nullptr;
- }
- NOTREACHED();
- return nullptr;
-}
-
-ServiceWorkerClient* ServiceWorkerClient::Create(
- const WebServiceWorkerClientInfo& info) {
- return new ServiceWorkerClient(info);
-}
-
-ServiceWorkerClient::ServiceWorkerClient(const WebServiceWorkerClientInfo& info)
- : uuid_(info.uuid),
- url_(info.url.GetString()),
- type_(info.client_type),
- frame_type_(info.frame_type) {}
-
-ServiceWorkerClient::~ServiceWorkerClient() = default;
-
-String ServiceWorkerClient::type() const {
- switch (type_) {
- case mojom::ServiceWorkerClientType::kWindow:
- return "window";
- case mojom::ServiceWorkerClientType::kSharedWorker:
- return "sharedworker";
- case mojom::ServiceWorkerClientType::kAll:
- NOTREACHED();
- return String();
- }
-
- NOTREACHED();
- return String();
-}
-
-String ServiceWorkerClient::frameType(ScriptState* script_state) const {
- UseCounter::Count(ExecutionContext::From(script_state),
- WebFeature::kServiceWorkerClientFrameType);
- switch (frame_type_) {
- case network::mojom::RequestContextFrameType::kAuxiliary:
- return "auxiliary";
- case network::mojom::RequestContextFrameType::kNested:
- return "nested";
- case network::mojom::RequestContextFrameType::kNone:
- return "none";
- case network::mojom::RequestContextFrameType::kTopLevel:
- return "top-level";
- }
-
- NOTREACHED();
- return String();
-}
-
-void ServiceWorkerClient::postMessage(
- ScriptState* script_state,
- scoped_refptr<SerializedScriptValue> message,
- const MessagePortArray& ports,
- ExceptionState& exception_state) {
- ExecutionContext* context = ExecutionContext::From(script_state);
- BlinkTransferableMessage msg;
- msg.message = message;
- msg.ports = MessagePort::DisentanglePorts(context, ports, exception_state);
- if (exception_state.HadException())
- return;
-
- ServiceWorkerGlobalScopeClient::From(context)->PostMessageToClient(
- uuid_, ToTransferableMessage(std::move(msg)));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_client.h b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_client.h
deleted file mode 100644
index 7e91720fbde..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_client.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_CLIENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_CLIENT_H_
-
-#include <memory>
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_clients_info.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#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/wtf/forward.h"
-
-namespace blink {
-
-class ScriptPromiseResolver;
-class ScriptState;
-
-class MODULES_EXPORT ServiceWorkerClient : public ScriptWrappable {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- // To be used by CallbackPromiseAdapter.
- using WebType = std::unique_ptr<WebServiceWorkerClientInfo>;
-
- static ServiceWorkerClient* Take(ScriptPromiseResolver*,
- std::unique_ptr<WebServiceWorkerClientInfo>);
- static ServiceWorkerClient* Create(const WebServiceWorkerClientInfo&);
-
- ~ServiceWorkerClient() override;
-
- // Client.idl
- String url() const { return url_; }
- String type() const;
- String frameType(ScriptState*) const;
- String id() const { return uuid_; }
- void postMessage(ScriptState*,
- scoped_refptr<SerializedScriptValue> message,
- const MessagePortArray&,
- ExceptionState&);
-
- static bool CanTransferArrayBuffersAndImageBitmaps() { return false; }
-
- protected:
- explicit ServiceWorkerClient(const WebServiceWorkerClientInfo&);
-
- String Uuid() const { return uuid_; }
-
- private:
- String uuid_;
- String url_;
- mojom::ServiceWorkerClientType type_;
- network::mojom::RequestContextFrameType frame_type_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_clients.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_clients.cc
deleted file mode 100644
index 6ce0c201fdf..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_clients.cc
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_clients.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/memory/ptr_util.h"
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_client_query_options.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_clients_info.h"
-#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
-#include "third_party/blink/renderer/core/workers/worker_location.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_error.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_window_client.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_window_client_callback.h"
-#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-namespace {
-
-class ClientArray {
- public:
- using WebType = const WebServiceWorkerClientsInfo&;
- static HeapVector<Member<ServiceWorkerClient>> Take(
- ScriptPromiseResolver*,
- const WebServiceWorkerClientsInfo& web_clients) {
- HeapVector<Member<ServiceWorkerClient>> clients;
- for (size_t i = 0; i < web_clients.clients.size(); ++i) {
- const WebServiceWorkerClientInfo& client = web_clients.clients[i];
- if (client.client_type == mojom::ServiceWorkerClientType::kWindow)
- clients.push_back(ServiceWorkerWindowClient::Create(client));
- else
- clients.push_back(ServiceWorkerClient::Create(client));
- }
- return clients;
- }
-
- private:
- WTF_MAKE_NONCOPYABLE(ClientArray);
- ClientArray() = delete;
-};
-
-mojom::ServiceWorkerClientType GetClientType(const String& type) {
- if (type == "window")
- return mojom::ServiceWorkerClientType::kWindow;
- if (type == "sharedworker")
- return mojom::ServiceWorkerClientType::kSharedWorker;
- if (type == "all")
- return mojom::ServiceWorkerClientType::kAll;
- NOTREACHED();
- return mojom::ServiceWorkerClientType::kWindow;
-}
-
-class GetCallback : public WebServiceWorkerClientCallbacks {
- public:
- explicit GetCallback(ScriptPromiseResolver* resolver) : resolver_(resolver) {}
- ~GetCallback() override = default;
-
- void OnSuccess(
- std::unique_ptr<WebServiceWorkerClientInfo> web_client) override {
- std::unique_ptr<WebServiceWorkerClientInfo> client =
- base::WrapUnique(web_client.release());
- if (!resolver_->GetExecutionContext() ||
- resolver_->GetExecutionContext()->IsContextDestroyed())
- return;
- if (!client) {
- // Resolve the promise with undefined.
- resolver_->Resolve();
- return;
- }
- resolver_->Resolve(ServiceWorkerClient::Take(resolver_, std::move(client)));
- }
-
- void OnError(const WebServiceWorkerError& error) override {
- if (!resolver_->GetExecutionContext() ||
- resolver_->GetExecutionContext()->IsContextDestroyed())
- return;
- resolver_->Reject(ServiceWorkerError::Take(resolver_.Get(), error));
- }
-
- private:
- Persistent<ScriptPromiseResolver> resolver_;
- WTF_MAKE_NONCOPYABLE(GetCallback);
-};
-
-} // namespace
-
-ServiceWorkerClients* ServiceWorkerClients::Create() {
- return new ServiceWorkerClients();
-}
-
-ServiceWorkerClients::ServiceWorkerClients() = default;
-
-ScriptPromise ServiceWorkerClients::get(ScriptState* script_state,
- const String& id) {
- ExecutionContext* execution_context = ExecutionContext::From(script_state);
- // TODO(jungkees): May be null due to worker termination:
- // http://crbug.com/413518.
- if (!execution_context)
- return ScriptPromise();
-
- ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- ScriptPromise promise = resolver->Promise();
-
- ServiceWorkerGlobalScopeClient::From(execution_context)
- ->GetClient(id, std::make_unique<GetCallback>(resolver));
- return promise;
-}
-
-ScriptPromise ServiceWorkerClients::matchAll(
- ScriptState* script_state,
- const ClientQueryOptions& options) {
- ExecutionContext* execution_context = ExecutionContext::From(script_state);
- // FIXME: May be null due to worker termination: http://crbug.com/413518.
- if (!execution_context)
- return ScriptPromise();
-
- ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- ScriptPromise promise = resolver->Promise();
-
- WebServiceWorkerClientQueryOptions web_options;
- web_options.client_type = GetClientType(options.type());
- web_options.include_uncontrolled = options.includeUncontrolled();
- ServiceWorkerGlobalScopeClient::From(execution_context)
- ->GetClients(web_options,
- std::make_unique<
- CallbackPromiseAdapter<ClientArray, ServiceWorkerError>>(
- resolver));
- return promise;
-}
-
-ScriptPromise ServiceWorkerClients::claim(ScriptState* script_state) {
- ExecutionContext* execution_context = ExecutionContext::From(script_state);
-
- // FIXME: May be null due to worker termination: http://crbug.com/413518.
- if (!execution_context)
- return ScriptPromise();
-
- ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- ScriptPromise promise = resolver->Promise();
-
- auto callbacks =
- std::make_unique<CallbackPromiseAdapter<void, ServiceWorkerError>>(
- resolver);
- ServiceWorkerGlobalScopeClient::From(execution_context)
- ->Claim(std::move(callbacks));
- return promise;
-}
-
-ScriptPromise ServiceWorkerClients::openWindow(ScriptState* script_state,
- const String& url) {
- ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- ScriptPromise promise = resolver->Promise();
- ExecutionContext* context = ExecutionContext::From(script_state);
-
- KURL parsed_url = KURL(ToWorkerGlobalScope(context)->location()->Url(), url);
- if (!parsed_url.IsValid()) {
- resolver->Reject(V8ThrowException::CreateTypeError(
- script_state->GetIsolate(), "'" + url + "' is not a valid URL."));
- return promise;
- }
-
- if (!context->GetSecurityOrigin()->CanDisplay(parsed_url)) {
- resolver->Reject(V8ThrowException::CreateTypeError(
- script_state->GetIsolate(),
- "'" + parsed_url.ElidedString() + "' cannot be opened."));
- return promise;
- }
-
- if (!context->IsWindowInteractionAllowed()) {
- resolver->Reject(DOMException::Create(kInvalidAccessError,
- "Not allowed to open a window."));
- return promise;
- }
- context->ConsumeWindowInteraction();
-
- ServiceWorkerGlobalScopeClient::From(context)->OpenWindowForClients(
- parsed_url, std::make_unique<NavigateClientCallback>(resolver));
- return promise;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_clients.h b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_clients.h
deleted file mode 100644
index 46b79156e5b..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_clients.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_CLIENTS_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_CLIENTS_H_
-
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_clients_info.h"
-#include "third_party/blink/renderer/modules/serviceworkers/client_query_options.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-
-namespace blink {
-
-class ScriptPromise;
-class ScriptState;
-
-class ServiceWorkerClients final : public ScriptWrappable {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- static ServiceWorkerClients* Create();
-
- // Clients.idl
- ScriptPromise get(ScriptState*, const String& id);
- ScriptPromise matchAll(ScriptState*, const ClientQueryOptions&);
- ScriptPromise openWindow(ScriptState*, const String& url);
- ScriptPromise claim(ScriptState*);
-
- private:
- ServiceWorkerClients();
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_CLIENTS_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container.cc
deleted file mode 100644
index 771d70af83e..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container.cc
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * 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/modules/serviceworkers/service_worker_container.h"
-
-#include <memory>
-#include <utility>
-#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_registration.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_factory.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/dom/exception_code.h"
-#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/csp/content_security_policy.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/use_counter.h"
-#include "third_party/blink/renderer/core/messaging/blink_transferable_message.h"
-#include "third_party/blink/renderer/core/messaging/message_port.h"
-#include "third_party/blink/renderer/modules/event_target_modules.h"
-#include "third_party/blink/renderer/modules/serviceworkers/navigator_service_worker.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_container_client.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_error.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.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/weborigin/scheme_registry.h"
-#include "third_party/blink/renderer/platform/weborigin/security_violation_reporting_policy.h"
-
-namespace blink {
-
-namespace {
-
-mojom::ServiceWorkerUpdateViaCache ParseUpdateViaCache(const String& value) {
- if (value == "imports")
- return mojom::ServiceWorkerUpdateViaCache::kImports;
- if (value == "all")
- return mojom::ServiceWorkerUpdateViaCache::kAll;
- if (value == "none")
- return mojom::ServiceWorkerUpdateViaCache::kNone;
- // Default value.
- return mojom::ServiceWorkerUpdateViaCache::kImports;
-}
-
-class GetRegistrationCallback : public WebServiceWorkerProvider::
- WebServiceWorkerGetRegistrationCallbacks {
- public:
- explicit GetRegistrationCallback(ScriptPromiseResolver* resolver)
- : resolver_(resolver) {}
- ~GetRegistrationCallback() override = default;
-
- void OnSuccess(
- std::unique_ptr<WebServiceWorkerRegistration::Handle> handle) override {
- if (!resolver_->GetExecutionContext() ||
- resolver_->GetExecutionContext()->IsContextDestroyed())
- return;
- if (!handle) {
- // Resolve the promise with undefined.
- resolver_->Resolve();
- return;
- }
- resolver_->Resolve(ServiceWorkerRegistration::GetOrCreate(
- resolver_->GetExecutionContext(), std::move(handle)));
- }
-
- void OnError(const WebServiceWorkerError& error) override {
- if (!resolver_->GetExecutionContext() ||
- resolver_->GetExecutionContext()->IsContextDestroyed())
- return;
- resolver_->Reject(ServiceWorkerError::Take(resolver_.Get(), error));
- }
-
- private:
- Persistent<ScriptPromiseResolver> resolver_;
- WTF_MAKE_NONCOPYABLE(GetRegistrationCallback);
-};
-
-} // namespace
-
-class ServiceWorkerContainer::GetRegistrationForReadyCallback
- : public WebServiceWorkerProvider::
- WebServiceWorkerGetRegistrationForReadyCallbacks {
- public:
- explicit GetRegistrationForReadyCallback(ReadyProperty* ready)
- : ready_(ready) {}
- ~GetRegistrationForReadyCallback() override = default;
-
- void OnSuccess(
- std::unique_ptr<WebServiceWorkerRegistration::Handle> handle) override {
- DCHECK_EQ(ready_->GetState(), ReadyProperty::kPending);
-
- if (ready_->GetExecutionContext() &&
- !ready_->GetExecutionContext()->IsContextDestroyed()) {
- ready_->Resolve(ServiceWorkerRegistration::GetOrCreate(
- ready_->GetExecutionContext(), std::move(handle)));
- }
- }
-
- private:
- Persistent<ReadyProperty> ready_;
- WTF_MAKE_NONCOPYABLE(GetRegistrationForReadyCallback);
-};
-
-ServiceWorkerContainer* ServiceWorkerContainer::Create(
- ExecutionContext* execution_context,
- NavigatorServiceWorker* navigator) {
- return new ServiceWorkerContainer(execution_context, navigator);
-}
-
-ServiceWorkerContainer::~ServiceWorkerContainer() {
- DCHECK(!provider_);
-}
-
-void ServiceWorkerContainer::ContextDestroyed(ExecutionContext*) {
- if (provider_) {
- provider_->SetClient(nullptr);
- provider_ = nullptr;
- }
- controller_ = nullptr;
- navigator_->ClearServiceWorker();
-}
-
-void ServiceWorkerContainer::Trace(blink::Visitor* visitor) {
- visitor->Trace(controller_);
- visitor->Trace(ready_);
- visitor->Trace(navigator_);
- EventTargetWithInlineData::Trace(visitor);
- ContextLifecycleObserver::Trace(visitor);
-}
-
-void ServiceWorkerContainer::RegisterServiceWorkerImpl(
- ExecutionContext* execution_context,
- const KURL& raw_script_url,
- const KURL& scope,
- mojom::ServiceWorkerUpdateViaCache update_via_cache,
- std::unique_ptr<RegistrationCallbacks> callbacks) {
- if (!provider_) {
- callbacks->OnError(
- WebServiceWorkerError(mojom::blink::ServiceWorkerErrorType::kState,
- "Failed to register a ServiceWorker: The "
- "document is in an invalid state."));
- return;
- }
-
- scoped_refptr<const SecurityOrigin> document_origin =
- execution_context->GetSecurityOrigin();
- String error_message;
- // Restrict to secure origins:
- // https://w3c.github.io/webappsec-secure-contexts/#is-settings-object-contextually-secure
- if (!execution_context->IsSecureContext(error_message)) {
- callbacks->OnError(WebServiceWorkerError(
- mojom::blink::ServiceWorkerErrorType::kSecurity, error_message));
- return;
- }
-
- KURL page_url = KURL(NullURL(), document_origin->ToString());
- if (!SchemeRegistry::ShouldTreatURLSchemeAsAllowingServiceWorkers(
- page_url.Protocol())) {
- callbacks->OnError(WebServiceWorkerError(
- mojom::blink::ServiceWorkerErrorType::kSecurity,
- String("Failed to register a ServiceWorker: The URL protocol of the "
- "current origin ('" +
- document_origin->ToString() + "') is not supported.")));
- return;
- }
-
- KURL script_url = raw_script_url;
- script_url.RemoveFragmentIdentifier();
- if (!document_origin->CanRequest(script_url)) {
- scoped_refptr<const SecurityOrigin> script_origin =
- SecurityOrigin::Create(script_url);
- callbacks->OnError(
- WebServiceWorkerError(mojom::blink::ServiceWorkerErrorType::kSecurity,
- String("Failed to register a ServiceWorker: The "
- "origin of the provided scriptURL ('" +
- script_origin->ToString() +
- "') does not match the current origin ('" +
- document_origin->ToString() + "').")));
- return;
- }
- if (!SchemeRegistry::ShouldTreatURLSchemeAsAllowingServiceWorkers(
- script_url.Protocol())) {
- callbacks->OnError(WebServiceWorkerError(
- mojom::blink::ServiceWorkerErrorType::kSecurity,
- String("Failed to register a ServiceWorker: The URL protocol of the "
- "script ('" +
- script_url.GetString() + "') is not supported.")));
- return;
- }
-
- KURL pattern_url = scope;
- pattern_url.RemoveFragmentIdentifier();
-
- if (!document_origin->CanRequest(pattern_url)) {
- scoped_refptr<const SecurityOrigin> pattern_origin =
- SecurityOrigin::Create(pattern_url);
- callbacks->OnError(
- WebServiceWorkerError(mojom::blink::ServiceWorkerErrorType::kSecurity,
- String("Failed to register a ServiceWorker: The "
- "origin of the provided scope ('" +
- pattern_origin->ToString() +
- "') does not match the current origin ('" +
- document_origin->ToString() + "').")));
- return;
- }
- if (!SchemeRegistry::ShouldTreatURLSchemeAsAllowingServiceWorkers(
- pattern_url.Protocol())) {
- callbacks->OnError(WebServiceWorkerError(
- mojom::blink::ServiceWorkerErrorType::kSecurity,
- String("Failed to register a ServiceWorker: The URL protocol of the "
- "scope ('" +
- pattern_url.GetString() + "') is not supported.")));
- return;
- }
-
- WebString web_error_message;
- if (!provider_->ValidateScopeAndScriptURL(pattern_url, script_url,
- &web_error_message)) {
- callbacks->OnError(WebServiceWorkerError(
- mojom::blink::ServiceWorkerErrorType::kType,
- WebString::FromUTF8("Failed to register a ServiceWorker: " +
- web_error_message.Utf8())));
- return;
- }
-
- ContentSecurityPolicy* csp = execution_context->GetContentSecurityPolicy();
- if (csp) {
- if (!(csp->AllowRequestWithoutIntegrity(
- WebURLRequest::kRequestContextServiceWorker, script_url) &&
- csp->AllowWorkerContextFromSource(
- script_url, ResourceRequest::RedirectStatus::kNoRedirect,
- SecurityViolationReportingPolicy::kReport))) {
- callbacks->OnError(WebServiceWorkerError(
- mojom::blink::ServiceWorkerErrorType::kSecurity,
- String(
- "Failed to register a ServiceWorker: The provided scriptURL ('" +
- script_url.GetString() +
- "') violates the Content Security Policy.")));
- return;
- }
- }
-
- provider_->RegisterServiceWorker(pattern_url, script_url, update_via_cache,
- std::move(callbacks));
-}
-
-ScriptPromise ServiceWorkerContainer::registerServiceWorker(
- ScriptState* script_state,
- const String& url,
- const RegistrationOptions& options) {
- ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- ScriptPromise promise = resolver->Promise();
-
- if (!provider_) {
- resolver->Reject(DOMException::Create(kInvalidStateError,
- "Failed to register a ServiceWorker: "
- "The document is in an invalid "
- "state."));
- return promise;
- }
-
- ExecutionContext* execution_context = ExecutionContext::From(script_state);
- // FIXME: May be null due to worker termination: http://crbug.com/413518.
- if (!execution_context)
- return ScriptPromise();
-
- KURL script_url = execution_context->CompleteURL(url);
- script_url.RemoveFragmentIdentifier();
-
- KURL pattern_url;
- if (options.scope().IsNull())
- pattern_url = KURL(script_url, "./");
- else
- pattern_url = execution_context->CompleteURL(options.scope());
-
- mojom::ServiceWorkerUpdateViaCache update_via_cache =
- ParseUpdateViaCache(options.updateViaCache());
-
- RegisterServiceWorkerImpl(
- execution_context, script_url, pattern_url, update_via_cache,
- std::make_unique<CallbackPromiseAdapter<ServiceWorkerRegistration,
- ServiceWorkerErrorForUpdate>>(
- resolver));
-
- return promise;
-}
-
-ScriptPromise ServiceWorkerContainer::getRegistration(
- ScriptState* script_state,
- const String& document_url) {
- ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- ScriptPromise promise = resolver->Promise();
-
- if (!provider_) {
- resolver->Reject(DOMException::Create(kInvalidStateError,
- "Failed to get a "
- "ServiceWorkerRegistration: The "
- "document is in an invalid state."));
- return promise;
- }
-
- ExecutionContext* execution_context = ExecutionContext::From(script_state);
- // FIXME: May be null due to worker termination: http://crbug.com/413518.
- if (!execution_context)
- return ScriptPromise();
-
- scoped_refptr<const SecurityOrigin> document_origin =
- execution_context->GetSecurityOrigin();
- String error_message;
- if (!execution_context->IsSecureContext(error_message)) {
- resolver->Reject(DOMException::Create(kSecurityError, error_message));
- return promise;
- }
-
- KURL page_url = KURL(NullURL(), document_origin->ToString());
- if (!SchemeRegistry::ShouldTreatURLSchemeAsAllowingServiceWorkers(
- page_url.Protocol())) {
- resolver->Reject(DOMException::Create(
- kSecurityError,
- "Failed to get a ServiceWorkerRegistration: The URL protocol of the "
- "current origin ('" +
- document_origin->ToString() + "') is not supported."));
- return promise;
- }
-
- KURL completed_url = execution_context->CompleteURL(document_url);
- completed_url.RemoveFragmentIdentifier();
- if (!document_origin->CanRequest(completed_url)) {
- scoped_refptr<const SecurityOrigin> document_url_origin =
- SecurityOrigin::Create(completed_url);
- resolver->Reject(
- DOMException::Create(kSecurityError,
- "Failed to get a ServiceWorkerRegistration: The "
- "origin of the provided documentURL ('" +
- document_url_origin->ToString() +
- "') does not match the current origin ('" +
- document_origin->ToString() + "')."));
- return promise;
- }
- provider_->GetRegistration(
- completed_url, std::make_unique<GetRegistrationCallback>(resolver));
-
- return promise;
-}
-
-ScriptPromise ServiceWorkerContainer::getRegistrations(
- ScriptState* script_state) {
- ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- ScriptPromise promise = resolver->Promise();
-
- if (!provider_) {
- resolver->Reject(
- DOMException::Create(kInvalidStateError,
- "Failed to get ServiceWorkerRegistration objects: "
- "The document is in an invalid state."));
- return promise;
- }
-
- ExecutionContext* execution_context = ExecutionContext::From(script_state);
- scoped_refptr<const SecurityOrigin> document_origin =
- execution_context->GetSecurityOrigin();
- String error_message;
- if (!execution_context->IsSecureContext(error_message)) {
- resolver->Reject(DOMException::Create(kSecurityError, error_message));
- return promise;
- }
-
- KURL page_url = KURL(NullURL(), document_origin->ToString());
- if (!SchemeRegistry::ShouldTreatURLSchemeAsAllowingServiceWorkers(
- page_url.Protocol())) {
- resolver->Reject(DOMException::Create(
- kSecurityError,
- "Failed to get ServiceWorkerRegistration objects: The URL protocol of "
- "the current origin ('" +
- document_origin->ToString() + "') is not supported."));
- return promise;
- }
-
- provider_->GetRegistrations(
- std::make_unique<CallbackPromiseAdapter<ServiceWorkerRegistrationArray,
- ServiceWorkerError>>(resolver));
-
- return promise;
-}
-
-ServiceWorkerContainer::ReadyProperty*
-ServiceWorkerContainer::CreateReadyProperty() {
- return new ReadyProperty(GetExecutionContext(), this, ReadyProperty::kReady);
-}
-
-ScriptPromise ServiceWorkerContainer::ready(ScriptState* caller_state) {
- if (!GetExecutionContext())
- return ScriptPromise();
-
- if (!caller_state->World().IsMainWorld()) {
- // FIXME: Support .ready from isolated worlds when
- // ScriptPromiseProperty can vend Promises in isolated worlds.
- return ScriptPromise::RejectWithDOMException(
- caller_state,
- DOMException::Create(kNotSupportedError,
- "'ready' is only supported in pages."));
- }
-
- if (!ready_) {
- ready_ = CreateReadyProperty();
- if (provider_) {
- provider_->GetRegistrationForReady(
- std::make_unique<GetRegistrationForReadyCallback>(ready_.Get()));
- }
- }
-
- return ready_->Promise(caller_state->World());
-}
-
-void ServiceWorkerContainer::SetController(
- std::unique_ptr<WebServiceWorker::Handle> handle,
- bool should_notify_controller_change) {
- if (!GetExecutionContext())
- return;
- controller_ = ServiceWorker::From(GetExecutionContext(), std::move(handle));
- if (controller_) {
- UseCounter::Count(GetExecutionContext(),
- WebFeature::kServiceWorkerControlledPage);
- }
- if (should_notify_controller_change)
- DispatchEvent(Event::Create(EventTypeNames::controllerchange));
-}
-
-void ServiceWorkerContainer::DispatchMessageEvent(
- std::unique_ptr<WebServiceWorker::Handle> handle,
- TransferableMessage message) {
- if (!GetExecutionContext() || !GetExecutionContext()->ExecutingWindow())
- return;
- auto msg = ToBlinkTransferableMessage(std::move(message));
- MessagePortArray* ports =
- MessagePort::EntanglePorts(*GetExecutionContext(), std::move(msg.ports));
- ServiceWorker* source =
- ServiceWorker::From(GetExecutionContext(), std::move(handle));
- DispatchEvent(MessageEvent::Create(
- ports, std::move(msg.message),
- GetExecutionContext()->GetSecurityOrigin()->ToString(),
- String() /* lastEventId */, source));
-}
-
-void ServiceWorkerContainer::CountFeature(mojom::WebFeature feature) {
- if (!GetExecutionContext())
- return;
- if (Deprecation::DeprecationMessage(feature).IsEmpty())
- UseCounter::Count(GetExecutionContext(), feature);
- else
- Deprecation::CountDeprecation(GetExecutionContext(), feature);
-}
-
-const AtomicString& ServiceWorkerContainer::InterfaceName() const {
- return EventTargetNames::ServiceWorkerContainer;
-}
-
-ServiceWorkerContainer::ServiceWorkerContainer(
- ExecutionContext* execution_context,
- NavigatorServiceWorker* navigator)
- : ContextLifecycleObserver(execution_context),
- provider_(nullptr),
- navigator_(navigator) {
- if (!execution_context)
- return;
-
- if (ServiceWorkerContainerClient* client =
- ServiceWorkerContainerClient::From(execution_context)) {
- provider_ = client->Provider();
- if (provider_)
- provider_->SetClient(this);
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container.h b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container.h
deleted file mode 100644
index 7e424adf821..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * 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_MODULES_SERVICEWORKERS_SERVICE_WORKER_CONTAINER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_CONTAINER_H_
-
-#include <memory>
-#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider_client.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_property.h"
-#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
-#include "third_party/blink/renderer/core/dom/events/event_target.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/modules/serviceworkers/registration_options.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
-#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/wtf/forward.h"
-
-namespace blink {
-
-class ExecutionContext;
-class NavigatorServiceWorker;
-class WebServiceWorker;
-class WebServiceWorkerProvider;
-
-class MODULES_EXPORT ServiceWorkerContainer final
- : public EventTargetWithInlineData,
- public ContextLifecycleObserver,
- public WebServiceWorkerProviderClient {
- DEFINE_WRAPPERTYPEINFO();
- USING_GARBAGE_COLLECTED_MIXIN(ServiceWorkerContainer);
-
- public:
- using RegistrationCallbacks =
- WebServiceWorkerProvider::WebServiceWorkerRegistrationCallbacks;
-
- static ServiceWorkerContainer* Create(ExecutionContext*,
- NavigatorServiceWorker*);
- ~ServiceWorkerContainer() override;
-
- void Trace(blink::Visitor*) override;
-
- ServiceWorker* controller() { return controller_; }
- ScriptPromise ready(ScriptState*);
- WebServiceWorkerProvider* Provider() { return provider_; }
-
- void RegisterServiceWorkerImpl(ExecutionContext*,
- const KURL& script_url,
- const KURL& scope,
- mojom::ServiceWorkerUpdateViaCache,
- std::unique_ptr<RegistrationCallbacks>);
-
- ScriptPromise registerServiceWorker(ScriptState*,
- const String& pattern,
- const RegistrationOptions&);
- ScriptPromise getRegistration(ScriptState*, const String& document_url);
- ScriptPromise getRegistrations(ScriptState*);
-
- void ContextDestroyed(ExecutionContext*) override;
-
- // WebServiceWorkerProviderClient implementation.
- void SetController(std::unique_ptr<WebServiceWorker::Handle>,
- bool should_notify_controller_change) override;
- void DispatchMessageEvent(std::unique_ptr<WebServiceWorker::Handle>,
- TransferableMessage) override;
- void CountFeature(mojom::WebFeature) override;
-
- // EventTarget overrides.
- ExecutionContext* GetExecutionContext() const override {
- return ContextLifecycleObserver::GetExecutionContext();
- }
- const AtomicString& InterfaceName() const override;
-
- DEFINE_ATTRIBUTE_EVENT_LISTENER(controllerchange);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(message);
-
- private:
- ServiceWorkerContainer(ExecutionContext*, NavigatorServiceWorker*);
-
- class GetRegistrationForReadyCallback;
- using ReadyProperty =
- ScriptPromiseProperty<Member<ServiceWorkerContainer>,
- Member<ServiceWorkerRegistration>,
- Member<ServiceWorkerRegistration>>;
- ReadyProperty* CreateReadyProperty();
-
- WebServiceWorkerProvider* provider_;
- Member<ServiceWorker> controller_;
- Member<ReadyProperty> ready_;
- Member<NavigatorServiceWorker> navigator_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_CONTAINER_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container.idl b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container.idl
deleted file mode 100644
index 135059b0fb8..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container.idl
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * 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.
- */
-
-// https://w3c.github.io/ServiceWorker/#serviceworkercontainer-interface
-interface ServiceWorkerContainer : EventTarget {
- readonly attribute ServiceWorker? controller;
- [CallWith=ScriptState] readonly attribute Promise<ServiceWorkerRegistration> ready;
-
- [CallWith=ScriptState, ImplementedAs=registerServiceWorker] Promise<ServiceWorkerRegistration> register(USVString url, optional RegistrationOptions options);
- [CallWith=ScriptState] Promise<ServiceWorkerRegistration> getRegistration(optional USVString documentURL = "");
- [CallWith=ScriptState] Promise<sequence<ServiceWorkerRegistration>> getRegistrations();
-
- attribute EventHandler oncontrollerchange;
- attribute EventHandler onmessage;
-};
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container_client.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container_client.cc
deleted file mode 100644
index 45bd801f5d9..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container_client.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_container_client.h"
-
-#include <memory>
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider.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_frame.h"
-#include "third_party/blink/renderer/core/frame/local_frame_client.h"
-#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
-
-namespace blink {
-
-ServiceWorkerContainerClient::ServiceWorkerContainerClient(
- Document& document,
- std::unique_ptr<WebServiceWorkerProvider> provider)
- : Supplement<Document>(document), provider_(std::move(provider)) {}
-
-ServiceWorkerContainerClient::ServiceWorkerContainerClient(
- WorkerClients& clients,
- std::unique_ptr<WebServiceWorkerProvider> provider)
- : Supplement<WorkerClients>(clients), provider_(std::move(provider)) {}
-
-ServiceWorkerContainerClient::~ServiceWorkerContainerClient() = default;
-
-const char ServiceWorkerContainerClient::kSupplementName[] =
- "ServiceWorkerContainerClient";
-
-ServiceWorkerContainerClient* ServiceWorkerContainerClient::From(
- ExecutionContext* context) {
- if (!context)
- return nullptr;
- if (context->IsWorkerGlobalScope()) {
- WorkerClients* worker_clients = ToWorkerGlobalScope(context)->Clients();
- DCHECK(worker_clients);
- ServiceWorkerContainerClient* client =
- Supplement<WorkerClients>::From<ServiceWorkerContainerClient>(
- worker_clients);
- DCHECK(client);
- return client;
- }
- Document* document = ToDocument(context);
- if (!document->GetFrame() || !document->GetFrame()->Client())
- return nullptr;
-
- ServiceWorkerContainerClient* client =
- Supplement<Document>::From<ServiceWorkerContainerClient>(document);
- if (!client) {
- client = new ServiceWorkerContainerClient(
- *document,
- document->GetFrame()->Client()->CreateServiceWorkerProvider());
- Supplement<Document>::ProvideTo(*document, client);
- }
- return client;
-}
-
-void ProvideServiceWorkerContainerClientToWorker(
- WorkerClients* clients,
- std::unique_ptr<WebServiceWorkerProvider> provider) {
- clients->ProvideSupplement(
- new ServiceWorkerContainerClient(*clients, std::move(provider)));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container_client.h b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container_client.h
deleted file mode 100644
index a163a6a67ca..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container_client.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_CONTAINER_CLIENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_CONTAINER_CLIENT_H_
-
-#include <memory>
-#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/workers/worker_clients.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
-
-namespace blink {
-
-class ExecutionContext;
-class WebServiceWorkerProvider;
-
-// This mainly exists to provide access to WebServiceWorkerProvider.
-// Owned by Document (or WorkerClients).
-class MODULES_EXPORT ServiceWorkerContainerClient final
- : public GarbageCollectedFinalized<ServiceWorkerContainerClient>,
- public Supplement<Document>,
- public Supplement<WorkerClients>,
- public TraceWrapperBase {
- USING_GARBAGE_COLLECTED_MIXIN(ServiceWorkerContainerClient);
- WTF_MAKE_NONCOPYABLE(ServiceWorkerContainerClient);
-
- public:
- static const char kSupplementName[];
-
- ServiceWorkerContainerClient(Document&,
- std::unique_ptr<WebServiceWorkerProvider>);
- ServiceWorkerContainerClient(WorkerClients&,
- std::unique_ptr<WebServiceWorkerProvider>);
- virtual ~ServiceWorkerContainerClient();
-
- WebServiceWorkerProvider* Provider() { return provider_.get(); }
-
- static ServiceWorkerContainerClient* From(ExecutionContext*);
-
- void Trace(blink::Visitor* visitor) override {
- Supplement<Document>::Trace(visitor);
- Supplement<WorkerClients>::Trace(visitor);
- }
-
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- Supplement<Document>::TraceWrappers(visitor);
- Supplement<WorkerClients>::TraceWrappers(visitor);
- }
-
- const char* NameInHeapSnapshot() const override {
- return "ServiceWorkerContainerClient";
- }
-
- private:
- std::unique_ptr<WebServiceWorkerProvider> provider_;
-};
-
-MODULES_EXPORT void ProvideServiceWorkerContainerClientToWorker(
- WorkerClients*,
- std::unique_ptr<WebServiceWorkerProvider>);
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_CONTAINER_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container_test.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container_test.cc
deleted file mode 100644
index a753be55089..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_container_test.cc
+++ /dev/null
@@ -1,422 +0,0 @@
-
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_container.h"
-
-#include <memory>
-#include <utility>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_clients_info.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider.h"
-#include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.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/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/page/focus_controller.h"
-#include "third_party/blink/renderer/core/testing/page_test_base.h"
-#include "third_party/blink/renderer/modules/serviceworkers/navigator_service_worker.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_container_client.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-namespace {
-
-// Promise-related test support.
-
-struct StubScriptFunction {
- public:
- StubScriptFunction() : call_count_(0) {}
-
- // The returned ScriptFunction can outlive the StubScriptFunction,
- // but it should not be called after the StubScriptFunction dies.
- v8::Local<v8::Function> GetFunction(ScriptState* script_state) {
- return ScriptFunctionImpl::CreateFunction(script_state, *this);
- }
-
- size_t CallCount() { return call_count_; }
- ScriptValue Arg() { return arg_; }
-
- private:
- size_t call_count_;
- ScriptValue arg_;
-
- class ScriptFunctionImpl : public ScriptFunction {
- public:
- static v8::Local<v8::Function> CreateFunction(ScriptState* script_state,
- StubScriptFunction& owner) {
- ScriptFunctionImpl* self = new ScriptFunctionImpl(script_state, owner);
- return self->BindToV8Function();
- }
-
- private:
- ScriptFunctionImpl(ScriptState* script_state, StubScriptFunction& owner)
- : ScriptFunction(script_state), owner_(owner) {}
-
- ScriptValue Call(ScriptValue arg) override {
- owner_.arg_ = arg;
- owner_.call_count_++;
- return ScriptValue();
- }
-
- StubScriptFunction& owner_;
- };
-};
-
-class ScriptValueTest {
- public:
- virtual ~ScriptValueTest() = default;
- virtual void operator()(ScriptValue) const = 0;
-};
-
-// Runs microtasks and expects |promise| to be rejected. Calls
-// |valueTest| with the value passed to |reject|, if any.
-void ExpectRejected(ScriptState* script_state,
- ScriptPromise& promise,
- const ScriptValueTest& value_test) {
- StubScriptFunction resolved, rejected;
- promise.Then(resolved.GetFunction(script_state),
- rejected.GetFunction(script_state));
- v8::MicrotasksScope::PerformCheckpoint(promise.GetIsolate());
- EXPECT_EQ(0ul, resolved.CallCount());
- EXPECT_EQ(1ul, rejected.CallCount());
- if (rejected.CallCount())
- value_test(rejected.Arg());
-}
-
-// DOM-related test support.
-
-// Matches a ScriptValue and a DOMException with a specific name and message.
-class ExpectDOMException : public ScriptValueTest {
- public:
- ExpectDOMException(const String& expected_name,
- const String& expected_message)
- : expected_name_(expected_name), expected_message_(expected_message) {}
-
- ~ExpectDOMException() override = default;
-
- void operator()(ScriptValue value) const override {
- DOMException* exception = V8DOMException::ToImplWithTypeCheck(
- value.GetIsolate(), value.V8Value());
- EXPECT_TRUE(exception) << "the value should be a DOMException";
- if (!exception)
- return;
- EXPECT_EQ(expected_name_, exception->name());
- EXPECT_EQ(expected_message_, exception->message());
- }
-
- private:
- String expected_name_;
- String expected_message_;
-};
-
-// Service Worker-specific tests.
-
-class NotReachedWebServiceWorkerProvider : public WebServiceWorkerProvider {
- public:
- ~NotReachedWebServiceWorkerProvider() override = default;
-
- void RegisterServiceWorker(
- const WebURL& pattern,
- const WebURL& script_url,
- mojom::ServiceWorkerUpdateViaCache update_via_cache,
- std::unique_ptr<WebServiceWorkerRegistrationCallbacks> callbacks)
- override {
- ADD_FAILURE()
- << "the provider should not be called to register a Service Worker";
- }
-
- bool ValidateScopeAndScriptURL(const WebURL& scope,
- const WebURL& script_url,
- WebString* error_message) override {
- return true;
- }
-};
-
-class ServiceWorkerContainerTest : public PageTestBase {
- protected:
- void SetUp() override { PageTestBase::SetUp(IntSize()); }
-
- ~ServiceWorkerContainerTest() override {
- V8GCController::CollectAllGarbageForTesting(GetIsolate());
- }
-
- ExecutionContext* GetExecutionContext() { return &GetDocument(); }
- NavigatorServiceWorker* GetNavigatorServiceWorker() {
- return NavigatorServiceWorker::From(GetDocument());
- }
- v8::Isolate* GetIsolate() { return v8::Isolate::GetCurrent(); }
- ScriptState* GetScriptState() {
- return ToScriptStateForMainWorld(GetDocument().GetFrame());
- }
-
- void Provide(std::unique_ptr<WebServiceWorkerProvider> provider) {
- Supplement<Document>::ProvideTo(
- GetDocument(),
- new ServiceWorkerContainerClient(GetDocument(), std::move(provider)));
- }
-
- void SetPageURL(const String& url) {
- // For URL completion.
- GetDocument().SetURL(KURL(NullURL(), url));
-
- // The basis for security checks.
- GetDocument().SetSecurityOrigin(SecurityOrigin::CreateFromString(url));
-
- if (url.StartsWith("https://") || url.StartsWith("http://localhost/")) {
- GetDocument().SetSecureContextStateForTesting(
- SecureContextState::kSecure);
- }
- }
-
- void TestRegisterRejected(const String& script_url,
- const String& scope,
- const ScriptValueTest& value_test) {
- // When the registration is rejected, a register call must not reach
- // the provider.
- Provide(std::make_unique<NotReachedWebServiceWorkerProvider>());
-
- ServiceWorkerContainer* container = ServiceWorkerContainer::Create(
- GetExecutionContext(), GetNavigatorServiceWorker());
- ScriptState::Scope script_scope(GetScriptState());
- RegistrationOptions options;
- options.setScope(scope);
- ScriptPromise promise =
- container->registerServiceWorker(GetScriptState(), script_url, options);
- ExpectRejected(GetScriptState(), promise, value_test);
- }
-
- void TestGetRegistrationRejected(const String& document_url,
- const ScriptValueTest& value_test) {
- Provide(std::make_unique<NotReachedWebServiceWorkerProvider>());
-
- ServiceWorkerContainer* container = ServiceWorkerContainer::Create(
- GetExecutionContext(), GetNavigatorServiceWorker());
- ScriptState::Scope script_scope(GetScriptState());
- ScriptPromise promise =
- container->getRegistration(GetScriptState(), document_url);
- ExpectRejected(GetScriptState(), promise, value_test);
- }
-};
-
-TEST_F(ServiceWorkerContainerTest, Register_NonSecureOriginIsRejected) {
- SetPageURL("http://www.example.com/");
- TestRegisterRejected(
- "http://www.example.com/worker.js", "http://www.example.com/",
- ExpectDOMException(
- "SecurityError",
- "Only secure origins are allowed (see: https://goo.gl/Y0ZkNV)."));
-}
-
-TEST_F(ServiceWorkerContainerTest, Register_CrossOriginScriptIsRejected) {
- SetPageURL("https://www.example.com");
- TestRegisterRejected(
- "https://www.example.com:8080/", // Differs by port
- "https://www.example.com/",
- ExpectDOMException("SecurityError",
- "Failed to register a ServiceWorker: The origin of "
- "the provided scriptURL "
- "('https://www.example.com:8080') does not match the "
- "current origin ('https://www.example.com')."));
-}
-
-TEST_F(ServiceWorkerContainerTest, Register_CrossOriginScopeIsRejected) {
- SetPageURL("https://www.example.com");
- TestRegisterRejected(
- "https://www.example.com",
- "wss://www.example.com/", // Differs by protocol
- ExpectDOMException("SecurityError",
- "Failed to register a ServiceWorker: The origin of "
- "the provided scope ('wss://www.example.com') does "
- "not match the current origin "
- "('https://www.example.com')."));
-}
-
-TEST_F(ServiceWorkerContainerTest, GetRegistration_NonSecureOriginIsRejected) {
- SetPageURL("http://www.example.com/");
- TestGetRegistrationRejected(
- "http://www.example.com/",
- ExpectDOMException(
- "SecurityError",
- "Only secure origins are allowed (see: https://goo.gl/Y0ZkNV)."));
-}
-
-TEST_F(ServiceWorkerContainerTest, GetRegistration_CrossOriginURLIsRejected) {
- SetPageURL("https://www.example.com/");
- TestGetRegistrationRejected(
- "https://foo.example.com/", // Differs by host
- ExpectDOMException("SecurityError",
- "Failed to get a ServiceWorkerRegistration: The "
- "origin of the provided documentURL "
- "('https://foo.example.com') does not match the "
- "current origin ('https://www.example.com')."));
-}
-
-class StubWebServiceWorkerProvider {
- public:
- StubWebServiceWorkerProvider()
- : register_call_count_(0),
- get_registration_call_count_(0),
- update_via_cache_(mojom::ServiceWorkerUpdateViaCache::kImports) {}
-
- // Creates a WebServiceWorkerProvider. This can outlive the
- // StubWebServiceWorkerProvider, but |registerServiceWorker| and
- // other methods must not be called after the
- // StubWebServiceWorkerProvider dies.
- std::unique_ptr<WebServiceWorkerProvider> Provider() {
- return std::make_unique<WebServiceWorkerProviderImpl>(*this);
- }
-
- size_t RegisterCallCount() { return register_call_count_; }
- const WebURL& RegisterScope() { return register_scope_; }
- const WebURL& RegisterScriptURL() { return register_script_url_; }
- size_t GetRegistrationCallCount() { return get_registration_call_count_; }
- const WebURL& GetRegistrationURL() { return get_registration_url_; }
- mojom::ServiceWorkerUpdateViaCache UpdateViaCache() const {
- return update_via_cache_;
- }
-
- private:
- class WebServiceWorkerProviderImpl : public WebServiceWorkerProvider {
- public:
- WebServiceWorkerProviderImpl(StubWebServiceWorkerProvider& owner)
- : owner_(owner) {}
-
- ~WebServiceWorkerProviderImpl() override = default;
-
- void RegisterServiceWorker(
- const WebURL& pattern,
- const WebURL& script_url,
- mojom::ServiceWorkerUpdateViaCache update_via_cache,
- std::unique_ptr<WebServiceWorkerRegistrationCallbacks> callbacks)
- override {
- owner_.register_call_count_++;
- owner_.register_scope_ = pattern;
- owner_.register_script_url_ = script_url;
- owner_.update_via_cache_ = update_via_cache;
- registration_callbacks_to_delete_.push_back(std::move(callbacks));
- }
-
- void GetRegistration(
- const WebURL& document_url,
- std::unique_ptr<WebServiceWorkerGetRegistrationCallbacks> callbacks)
- override {
- owner_.get_registration_call_count_++;
- owner_.get_registration_url_ = document_url;
- get_registration_callbacks_to_delete_.push_back(std::move(callbacks));
- }
-
- bool ValidateScopeAndScriptURL(const WebURL& scope,
- const WebURL& script_url,
- WebString* error_message) override {
- return true;
- }
-
- private:
- StubWebServiceWorkerProvider& owner_;
- Vector<std::unique_ptr<WebServiceWorkerRegistrationCallbacks>>
- registration_callbacks_to_delete_;
- Vector<std::unique_ptr<WebServiceWorkerGetRegistrationCallbacks>>
- get_registration_callbacks_to_delete_;
- };
-
- private:
- size_t register_call_count_;
- WebURL register_scope_;
- WebURL register_script_url_;
- size_t get_registration_call_count_;
- WebURL get_registration_url_;
- mojom::ServiceWorkerUpdateViaCache update_via_cache_;
-};
-
-TEST_F(ServiceWorkerContainerTest,
- RegisterUnregister_NonHttpsSecureOriginDelegatesToProvider) {
- SetPageURL("http://localhost/x/index.html");
-
- StubWebServiceWorkerProvider stub_provider;
- Provide(stub_provider.Provider());
-
- ServiceWorkerContainer* container = ServiceWorkerContainer::Create(
- GetExecutionContext(), GetNavigatorServiceWorker());
-
- // register
- {
- ScriptState::Scope script_scope(GetScriptState());
- RegistrationOptions options;
- options.setScope("y/");
- container->registerServiceWorker(GetScriptState(), "/x/y/worker.js",
- options);
-
- EXPECT_EQ(1ul, stub_provider.RegisterCallCount());
- EXPECT_EQ(WebURL(KURL("http://localhost/x/y/")),
- stub_provider.RegisterScope());
- EXPECT_EQ(WebURL(KURL("http://localhost/x/y/worker.js")),
- stub_provider.RegisterScriptURL());
- EXPECT_EQ(mojom::ServiceWorkerUpdateViaCache::kImports,
- stub_provider.UpdateViaCache());
- }
-}
-
-TEST_F(ServiceWorkerContainerTest,
- GetRegistration_OmittedDocumentURLDefaultsToPageURL) {
- SetPageURL("http://localhost/x/index.html");
-
- StubWebServiceWorkerProvider stub_provider;
- Provide(stub_provider.Provider());
-
- ServiceWorkerContainer* container = ServiceWorkerContainer::Create(
- GetExecutionContext(), GetNavigatorServiceWorker());
-
- {
- ScriptState::Scope script_scope(GetScriptState());
- container->getRegistration(GetScriptState(), "");
- EXPECT_EQ(1ul, stub_provider.GetRegistrationCallCount());
- EXPECT_EQ(WebURL(KURL("http://localhost/x/index.html")),
- stub_provider.GetRegistrationURL());
- EXPECT_EQ(mojom::ServiceWorkerUpdateViaCache::kImports,
- stub_provider.UpdateViaCache());
- }
-}
-
-TEST_F(ServiceWorkerContainerTest,
- RegisterUnregister_UpdateViaCacheOptionDelegatesToProvider) {
- SetPageURL("http://localhost/x/index.html");
-
- StubWebServiceWorkerProvider stub_provider;
- Provide(stub_provider.Provider());
-
- ServiceWorkerContainer* container = ServiceWorkerContainer::Create(
- GetExecutionContext(), GetNavigatorServiceWorker());
-
- // register
- {
- ScriptState::Scope script_scope(GetScriptState());
- RegistrationOptions options;
- options.setUpdateViaCache("none");
- container->registerServiceWorker(GetScriptState(), "/x/y/worker.js",
- options);
-
- EXPECT_EQ(1ul, stub_provider.RegisterCallCount());
- EXPECT_EQ(WebURL(KURL(KURL(), "http://localhost/x/y/")),
- stub_provider.RegisterScope());
- EXPECT_EQ(WebURL(KURL(KURL(), "http://localhost/x/y/worker.js")),
- stub_provider.RegisterScriptURL());
- EXPECT_EQ(mojom::ServiceWorkerUpdateViaCache::kNone,
- stub_provider.UpdateViaCache());
- }
-}
-
-} // namespace
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_content_settings_proxy.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_content_settings_proxy.cc
deleted file mode 100644
index e13b8109efd..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_content_settings_proxy.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_content_settings_proxy.h"
-
-#include <memory>
-
-namespace blink {
-
-ServiceWorkerContentSettingsProxy::ServiceWorkerContentSettingsProxy(
- mojom::blink::WorkerContentSettingsProxyPtrInfo host_info)
- : host_info_(std::move(host_info)) {}
-
-ServiceWorkerContentSettingsProxy::~ServiceWorkerContentSettingsProxy() =
- default;
-
-bool ServiceWorkerContentSettingsProxy::RequestFileSystemAccessSync() {
- NOTREACHED();
- return false;
-}
-
-bool ServiceWorkerContentSettingsProxy::AllowIndexedDB(
- const blink::WebString& name,
- const blink::WebSecurityOrigin&) {
- bool result = false;
- GetService()->AllowIndexedDB(name, &result);
- return result;
-}
-
-// Use ThreadSpecific to ensure that |content_settings_instance_host| is
-// destructed on worker thread.
-// Each worker has a dedicated thread so this is safe.
-mojom::blink::WorkerContentSettingsProxyPtr&
-ServiceWorkerContentSettingsProxy::GetService() {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- ThreadSpecific<mojom::blink::WorkerContentSettingsProxyPtr>,
- content_settings_instance_host, ());
- if (!content_settings_instance_host.IsSet()) {
- DCHECK(host_info_.is_valid());
- content_settings_instance_host->Bind(std::move(host_info_));
- }
- return *content_settings_instance_host;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_content_settings_proxy.h b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_content_settings_proxy.h
deleted file mode 100644
index 3bcec3912b6..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_content_settings_proxy.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_CONTENT_SETTINGS_PROXY_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_CONTENT_SETTINGS_PROXY_H_
-
-#include "third_party/blink/public/platform/web_content_settings_client.h"
-#include "third_party/blink/public/platform/web_security_origin.h"
-#include "third_party/blink/public/web/worker_content_settings_proxy.mojom-blink.h"
-#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
-
-namespace blink {
-
-// Provides the content settings information from browser process.
-// This proxy is created and destroyed on the main thread and used on the
-// worker thread.
-class ServiceWorkerContentSettingsProxy final
- : public blink::WebContentSettingsClient {
- public:
- explicit ServiceWorkerContentSettingsProxy(
- mojom::blink::WorkerContentSettingsProxyPtrInfo host_info);
- ~ServiceWorkerContentSettingsProxy() override;
-
- void SetSecurityOrigin(scoped_refptr<const blink::SecurityOrigin>);
-
- // WebContentSettingsClient overrides.
- // Asks the browser process about the settings.
- // Blocks until the response arrives.
- bool RequestFileSystemAccessSync() override;
- bool AllowIndexedDB(const WebString& name, const WebSecurityOrigin&) override;
-
- private:
- // To ensure the returned pointer is destructed on the same thread
- // that it was constructed on, this uses ThreadSpecific.
- mojom::blink::WorkerContentSettingsProxyPtr& GetService();
-
- // This is set on the main thread at the ctor,
- // and moved to thread local storage on the worker thread
- // when GetService() is called for the first time.
- mojom::blink::WorkerContentSettingsProxyPtrInfo host_info_;
-
- DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContentSettingsProxy);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_CONTENT_SETTINGS_PROXY_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_error.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_error.cc
deleted file mode 100644
index a84f4ffd845..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_error.cc
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_error.h"
-
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
-#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
-#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
-
-using blink::WebServiceWorkerError;
-
-namespace blink {
-
-namespace {
-
-struct ExceptionParams {
- ExceptionParams(ExceptionCode code,
- const String& default_message = String(),
- const String& message = String())
- : code(code), message(message.IsEmpty() ? default_message : message) {}
-
- ExceptionCode code;
- String message;
-};
-
-ExceptionParams GetExceptionParams(const WebServiceWorkerError& web_error) {
- switch (web_error.error_type) {
- case mojom::blink::ServiceWorkerErrorType::kAbort:
- return ExceptionParams(kAbortError,
- "The Service Worker operation was aborted.",
- web_error.message);
- case mojom::blink::ServiceWorkerErrorType::kActivate:
- // Not currently returned as a promise rejection.
- // TODO: Introduce new ActivateError type to ExceptionCodes?
- return ExceptionParams(kAbortError,
- "The Service Worker activation failed.",
- web_error.message);
- case mojom::blink::ServiceWorkerErrorType::kDisabled:
- return ExceptionParams(kNotSupportedError,
- "Service Worker support is disabled.",
- web_error.message);
- case mojom::blink::ServiceWorkerErrorType::kInstall:
- // TODO: Introduce new InstallError type to ExceptionCodes?
- return ExceptionParams(kAbortError,
- "The Service Worker installation failed.",
- web_error.message);
- case mojom::blink::ServiceWorkerErrorType::kScriptEvaluateFailed:
- return ExceptionParams(kAbortError,
- "The Service Worker script failed to evaluate.",
- web_error.message);
- case mojom::blink::ServiceWorkerErrorType::kNavigation:
- // ErrorTypeNavigation should have bailed out before calling this.
- NOTREACHED();
- return ExceptionParams(kUnknownError);
- case mojom::blink::ServiceWorkerErrorType::kNetwork:
- return ExceptionParams(kNetworkError,
- "The Service Worker failed by network.",
- web_error.message);
- case mojom::blink::ServiceWorkerErrorType::kNotFound:
- return ExceptionParams(
- kNotFoundError,
- "The specified Service Worker resource was not found.",
- web_error.message);
- case mojom::blink::ServiceWorkerErrorType::kSecurity:
- return ExceptionParams(
- kSecurityError,
- "The Service Worker security policy prevented an action.",
- web_error.message);
- case mojom::blink::ServiceWorkerErrorType::kState:
- return ExceptionParams(kInvalidStateError,
- "The Service Worker state was not valid.",
- web_error.message);
- case mojom::blink::ServiceWorkerErrorType::kTimeout:
- return ExceptionParams(kAbortError,
- "The Service Worker operation timed out.",
- web_error.message);
- case mojom::blink::ServiceWorkerErrorType::kUnknown:
- return ExceptionParams(kUnknownError,
- "An unknown error occurred within Service Worker.",
- web_error.message);
- case mojom::blink::ServiceWorkerErrorType::kNone:
- case mojom::blink::ServiceWorkerErrorType::kType:
- // ErrorTypeType should have been handled before reaching this point.
- NOTREACHED();
- return ExceptionParams(kUnknownError);
- }
- NOTREACHED();
- return ExceptionParams(kUnknownError);
-}
-
-} // namespace
-
-// static
-DOMException* ServiceWorkerError::Take(ScriptPromiseResolver*,
- const WebServiceWorkerError& web_error) {
- ExceptionParams params = GetExceptionParams(web_error);
- return DOMException::Create(params.code, params.message);
-}
-
-// static
-v8::Local<v8::Value> ServiceWorkerErrorForUpdate::Take(
- ScriptPromiseResolver* resolver,
- const WebServiceWorkerError& web_error) {
- ScriptState* script_state = resolver->GetScriptState();
- switch (web_error.error_type) {
- case mojom::blink::ServiceWorkerErrorType::kNetwork:
- case mojom::blink::ServiceWorkerErrorType::kNotFound:
- case mojom::blink::ServiceWorkerErrorType::kScriptEvaluateFailed:
- // According to the spec, these errors during update should result in
- // a TypeError.
- return V8ThrowException::CreateTypeError(
- script_state->GetIsolate(), GetExceptionParams(web_error).message);
- case mojom::blink::ServiceWorkerErrorType::kType:
- return V8ThrowException::CreateTypeError(script_state->GetIsolate(),
- web_error.message);
- default:
- return ToV8(ServiceWorkerError::Take(resolver, web_error),
- script_state->GetContext()->Global(),
- script_state->GetIsolate());
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_error.h b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_error.h
deleted file mode 100644
index ba102275711..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_error.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * 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_MODULES_SERVICEWORKERS_SERVICE_WORKER_ERROR_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_ERROR_H_
-
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_error.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-class DOMException;
-class ScriptPromiseResolver;
-
-class ServiceWorkerError {
- STATIC_ONLY(ServiceWorkerError);
-
- public:
- // For CallbackPromiseAdapter
- using WebType = const WebServiceWorkerError&;
- static DOMException* Take(ScriptPromiseResolver*,
- const WebServiceWorkerError& web_error);
-};
-
-class ServiceWorkerErrorForUpdate : public ServiceWorkerError {
- STATIC_ONLY(ServiceWorkerErrorForUpdate);
-
- public:
- // For CallbackPromiseAdapter
- static v8::Local<v8::Value> Take(ScriptPromiseResolver* resolver,
- const WebServiceWorkerError& web_error);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_ERROR_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.cc
deleted file mode 100644
index c45a90bcca1..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.cc
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * 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/modules/serviceworkers/service_worker_global_scope.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/memory/ptr_util.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
-#include "third_party/blink/renderer/core/dom/events/event.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/fetch/global_fetch.h"
-#include "third_party/blink/renderer/core/inspector/console_message.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"
-#include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h"
-#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
-#include "third_party/blink/renderer/core/workers/installed_scripts_manager.h"
-#include "third_party/blink/renderer/core/workers/worker_clients.h"
-#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
-#include "third_party/blink/renderer/modules/event_target_modules.h"
-#include "third_party/blink/renderer/modules/serviceworkers/respond_with_observer.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_clients.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_script_cached_metadata_handler.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_thread.h"
-#include "third_party/blink/renderer/modules/serviceworkers/wait_until_observer.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/histogram.h"
-#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
-#include "third_party/blink/renderer/platform/network/content_security_policy_response_headers.h"
-#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-#include "third_party/blink/renderer/platform/wtf/time.h"
-
-namespace blink {
-
-ServiceWorkerGlobalScope* ServiceWorkerGlobalScope::Create(
- ServiceWorkerThread* thread,
- std::unique_ptr<GlobalScopeCreationParams> creation_params,
- mojom::blink::CacheStoragePtrInfo cache_storage_info,
- double time_origin) {
- // If the script is being loaded via script streaming, the script is not yet
- // loaded.
- if (thread->GetInstalledScriptsManager() &&
- thread->GetInstalledScriptsManager()->IsScriptInstalled(
- creation_params->script_url)) {
- // CSP headers, referrer policy, and origin trial tokens will be provided by
- // the InstalledScriptsManager in EvaluateClassicScript().
- DCHECK(creation_params->content_security_policy_parsed_headers->IsEmpty());
- DCHECK_EQ(kReferrerPolicyDefault, creation_params->referrer_policy);
- DCHECK(creation_params->origin_trial_tokens->IsEmpty());
- }
- return new ServiceWorkerGlobalScope(std::move(creation_params), thread,
- std::move(cache_storage_info),
- time_origin);
-}
-
-ServiceWorkerGlobalScope::ServiceWorkerGlobalScope(
- std::unique_ptr<GlobalScopeCreationParams> creation_params,
- ServiceWorkerThread* thread,
- mojom::blink::CacheStoragePtrInfo cache_storage_info,
- double time_origin)
- : WorkerGlobalScope(std::move(creation_params), thread, time_origin),
- cache_storage_info_(std::move(cache_storage_info)) {}
-
-ServiceWorkerGlobalScope::~ServiceWorkerGlobalScope() = default;
-
-void ServiceWorkerGlobalScope::ReadyToEvaluateScript() {
- DCHECK(!evaluate_script_ready_);
- evaluate_script_ready_ = true;
- if (evaluate_script_)
- std::move(evaluate_script_).Run();
-}
-
-void ServiceWorkerGlobalScope::EvaluateClassicScript(
- const KURL& script_url,
- String source_code,
- std::unique_ptr<Vector<char>> cached_meta_data) {
- DCHECK(IsContextThread());
-
- if (!evaluate_script_ready_) {
- evaluate_script_ =
- WTF::Bind(&ServiceWorkerGlobalScope::EvaluateClassicScript,
- WrapWeakPersistent(this), script_url, std::move(source_code),
- std::move(cached_meta_data));
- return;
- }
-
- // Receive the main script via script streaming if needed.
- InstalledScriptsManager* installed_scripts_manager =
- GetThread()->GetInstalledScriptsManager();
- if (installed_scripts_manager &&
- installed_scripts_manager->IsScriptInstalled(script_url)) {
- // GetScriptData blocks until the script is received from the browser.
- InstalledScriptsManager::ScriptData script_data;
- InstalledScriptsManager::ScriptStatus status =
- installed_scripts_manager->GetScriptData(script_url, &script_data);
- if (status == InstalledScriptsManager::ScriptStatus::kFailed) {
- // This eventually terminates the worker thread.
- ReportingProxy().DidEvaluateClassicScript(false);
- return;
- }
-
- DCHECK(source_code.IsEmpty());
- DCHECK(!cached_meta_data);
- source_code = script_data.TakeSourceText();
- cached_meta_data = script_data.TakeMetaData();
-
- base::Optional<ContentSecurityPolicyResponseHeaders>
- content_security_policy_raw_headers =
- script_data.GetContentSecurityPolicyResponseHeaders();
- ApplyContentSecurityPolicyFromHeaders(
- content_security_policy_raw_headers.value());
-
- String referrer_policy = script_data.GetReferrerPolicy();
- if (!referrer_policy.IsNull())
- ParseAndSetReferrerPolicy(referrer_policy);
-
- std::unique_ptr<Vector<String>> origin_trial_tokens =
- script_data.CreateOriginTrialTokens();
- OriginTrialContext::AddTokens(this, origin_trial_tokens.get());
-
- // This may block until CSP and referrer policy are set on the main
- // thread.
- ReportingProxy().DidLoadInstalledScript(
- content_security_policy_raw_headers.value(), referrer_policy);
- }
-
- WorkerGlobalScope::EvaluateClassicScript(script_url, source_code,
- std::move(cached_meta_data));
-}
-
-void ServiceWorkerGlobalScope::ImportModuleScript(
- const KURL& module_url_record,
- network::mojom::FetchCredentialsMode credentials_mode) {
- // TODO(nhiroki): Implement module loading for service workers.
- // (https://crbug.com/824647)
- NOTREACHED();
-}
-
-void ServiceWorkerGlobalScope::CountWorkerScript(size_t script_size,
- size_t cached_metadata_size) {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram, script_size_histogram,
- ("ServiceWorker.ScriptSize", 1000, 5000000, 50));
- script_size_histogram.Count(script_size);
-
- if (cached_metadata_size) {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram, script_cached_metadata_size_histogram,
- ("ServiceWorker.ScriptCachedMetadataSize", 1000, 50000000, 50));
- script_cached_metadata_size_histogram.Count(cached_metadata_size);
- }
-
- RecordScriptSize(script_size, cached_metadata_size);
-}
-
-void ServiceWorkerGlobalScope::CountImportedScript(
- size_t script_size,
- size_t cached_metadata_size) {
- RecordScriptSize(script_size, cached_metadata_size);
-}
-
-void ServiceWorkerGlobalScope::RecordScriptSize(size_t script_size,
- size_t cached_metadata_size) {
- ++script_count_;
- script_total_size_ += script_size;
- script_cached_metadata_total_size_ += cached_metadata_size;
-}
-
-void ServiceWorkerGlobalScope::DidEvaluateClassicScript() {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, script_count_histogram,
- ("ServiceWorker.ScriptCount", 1, 1000, 50));
- script_count_histogram.Count(script_count_);
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram, script_total_size_histogram,
- ("ServiceWorker.ScriptTotalSize", 1000, 5000000, 50));
- script_total_size_histogram.Count(script_total_size_);
- if (script_cached_metadata_total_size_) {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram, cached_metadata_histogram,
- ("ServiceWorker.ScriptCachedMetadataTotalSize", 1000, 50000000, 50));
- cached_metadata_histogram.Count(script_cached_metadata_total_size_);
- }
- did_evaluate_script_ = true;
-}
-
-ScriptPromise ServiceWorkerGlobalScope::fetch(ScriptState* script_state,
- const RequestInfo& input,
- const Dictionary& init,
- ExceptionState& exception_state) {
- return GlobalFetch::fetch(script_state, *this, input, init, exception_state);
-}
-
-ServiceWorkerClients* ServiceWorkerGlobalScope::clients() {
- if (!clients_)
- clients_ = ServiceWorkerClients::Create();
- return clients_;
-}
-
-ServiceWorkerRegistration* ServiceWorkerGlobalScope::registration() {
- return registration_;
-}
-
-ScriptPromise ServiceWorkerGlobalScope::skipWaiting(ScriptState* script_state) {
- ExecutionContext* execution_context = ExecutionContext::From(script_state);
- // FIXME: short-term fix, see details at:
- // https://codereview.chromium.org/535193002/.
- if (!execution_context)
- return ScriptPromise();
-
- ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- ScriptPromise promise = resolver->Promise();
-
- ServiceWorkerGlobalScopeClient::From(execution_context)
- ->SkipWaiting(
- std::make_unique<CallbackPromiseAdapter<void, void>>(resolver));
- return promise;
-}
-
-void ServiceWorkerGlobalScope::SetRegistration(
- std::unique_ptr<WebServiceWorkerRegistration::Handle> handle) {
- if (!GetExecutionContext())
- return;
- registration_ = ServiceWorkerRegistration::GetOrCreate(
- GetExecutionContext(), base::WrapUnique(handle.release()));
-}
-
-bool ServiceWorkerGlobalScope::AddEventListenerInternal(
- const AtomicString& event_type,
- EventListener* listener,
- const AddEventListenerOptionsResolved& options) {
- if (did_evaluate_script_) {
- String message = String::Format(
- "Event handler of '%s' event must be added on the initial evaluation "
- "of worker script.",
- event_type.Utf8().data());
- AddConsoleMessage(ConsoleMessage::Create(kJSMessageSource,
- kWarningMessageLevel, message));
- }
- return WorkerGlobalScope::AddEventListenerInternal(event_type, listener,
- options);
-}
-
-const AtomicString& ServiceWorkerGlobalScope::InterfaceName() const {
- return EventTargetNames::ServiceWorkerGlobalScope;
-}
-
-void ServiceWorkerGlobalScope::DispatchExtendableEvent(
- Event* event,
- WaitUntilObserver* observer) {
- observer->WillDispatchEvent();
- DispatchEvent(event);
-
- // Check if the worker thread is forcibly terminated during the event
- // because of timeout etc.
- observer->DidDispatchEvent(GetThread()->IsForciblyTerminated());
-}
-
-void ServiceWorkerGlobalScope::DispatchExtendableEventWithRespondWith(
- Event* event,
- WaitUntilObserver* wait_until_observer,
- RespondWithObserver* respond_with_observer) {
- wait_until_observer->WillDispatchEvent();
- respond_with_observer->WillDispatchEvent();
- DispatchEventResult dispatch_result = DispatchEvent(event);
- respond_with_observer->DidDispatchEvent(dispatch_result);
- // false is okay because waitUntil() for events with respondWith() doesn't
- // care about the promise rejection or an uncaught runtime script error.
- wait_until_observer->DidDispatchEvent(false /* event_dispatch_failed */);
-}
-
-void ServiceWorkerGlobalScope::Trace(blink::Visitor* visitor) {
- visitor->Trace(clients_);
- visitor->Trace(registration_);
- WorkerGlobalScope::Trace(visitor);
-}
-
-void ServiceWorkerGlobalScope::importScripts(const Vector<String>& urls,
- ExceptionState& exception_state) {
- // Bust the MemoryCache to ensure script requests reach the browser-side
- // and get added to and retrieved from the ServiceWorker's script cache.
- // FIXME: Revisit in light of the solution to crbug/388375.
- for (Vector<String>::const_iterator it = urls.begin(); it != urls.end(); ++it)
- GetExecutionContext()->RemoveURLFromMemoryCache(CompleteURL(*it));
- WorkerGlobalScope::importScripts(urls, exception_state);
-}
-
-SingleCachedMetadataHandler*
-ServiceWorkerGlobalScope::CreateWorkerScriptCachedMetadataHandler(
- const KURL& script_url,
- const Vector<char>* meta_data) {
- return ServiceWorkerScriptCachedMetadataHandler::Create(this, script_url,
- meta_data);
-}
-
-void ServiceWorkerGlobalScope::ExceptionThrown(ErrorEvent* event) {
- WorkerGlobalScope::ExceptionThrown(event);
- if (WorkerThreadDebugger* debugger =
- WorkerThreadDebugger::From(GetThread()->GetIsolate()))
- debugger->ExceptionThrown(GetThread(), event);
-}
-
-void ServiceWorkerGlobalScope::CountCacheStorageInstalledScript(
- uint64_t script_size,
- uint64_t script_metadata_size) {
- ++cache_storage_installed_script_count_;
- cache_storage_installed_script_total_size_ += script_size;
- cache_storage_installed_script_metadata_total_size_ += script_metadata_size;
-
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram, script_size_histogram,
- ("ServiceWorker.CacheStorageInstalledScript.ScriptSize", 1000, 5000000,
- 50));
- script_size_histogram.Count(script_size);
-
- if (script_metadata_size) {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram, script_metadata_size_histogram,
- ("ServiceWorker.CacheStorageInstalledScript.CachedMetadataSize", 1000,
- 50000000, 50));
- script_metadata_size_histogram.Count(script_metadata_size);
- }
-}
-
-void ServiceWorkerGlobalScope::SetIsInstalling(bool is_installing) {
- is_installing_ = is_installing;
- if (is_installing)
- return;
-
- // Installing phase is finished; record the stats for the scripts that are
- // stored in Cache storage during installation.
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram, cache_storage_installed_script_count_histogram,
- ("ServiceWorker.CacheStorageInstalledScript.Count", 1, 1000, 50));
- cache_storage_installed_script_count_histogram.Count(
- cache_storage_installed_script_count_);
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram, cache_storage_installed_script_total_size_histogram,
- ("ServiceWorker.CacheStorageInstalledScript.ScriptTotalSize", 1000,
- 50000000, 50));
- cache_storage_installed_script_total_size_histogram.Count(
- cache_storage_installed_script_total_size_);
-
- if (cache_storage_installed_script_metadata_total_size_) {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram,
- cache_storage_installed_script_metadata_total_size_histogram,
- ("ServiceWorker.CacheStorageInstalledScript.CachedMetadataTotalSize",
- 1000, 50000000, 50));
- cache_storage_installed_script_metadata_total_size_histogram.Count(
- cache_storage_installed_script_metadata_total_size_);
- }
-}
-
-mojom::blink::CacheStoragePtrInfo ServiceWorkerGlobalScope::TakeCacheStorage() {
- return std::move(cache_storage_info_);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.h b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.h
deleted file mode 100644
index 203a62eae47..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.h
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * 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_MODULES_SERVICEWORKERS_SERVICE_WORKER_GLOBAL_SCOPE_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_GLOBAL_SCOPE_H_
-
-#include <memory>
-#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_registration.h"
-#include "third_party/blink/renderer/bindings/core/v8/request_or_usv_string.h"
-#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
-
-namespace blink {
-
-class Dictionary;
-class RespondWithObserver;
-class ScriptPromise;
-class ScriptState;
-class ServiceWorkerClients;
-class ServiceWorkerRegistration;
-class ServiceWorkerThread;
-class WaitUntilObserver;
-struct GlobalScopeCreationParams;
-
-typedef RequestOrUSVString RequestInfo;
-
-class MODULES_EXPORT ServiceWorkerGlobalScope final : public WorkerGlobalScope {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- static ServiceWorkerGlobalScope* Create(
- ServiceWorkerThread*,
- std::unique_ptr<GlobalScopeCreationParams>,
- mojom::blink::CacheStoragePtrInfo,
- double time_origin);
-
- ~ServiceWorkerGlobalScope() override;
- bool IsServiceWorkerGlobalScope() const override { return true; }
-
- // Implements WorkerGlobalScope.
- void EvaluateClassicScript(
- const KURL& script_url,
- String source_code,
- std::unique_ptr<Vector<char>> cached_meta_data) override;
- void ImportModuleScript(const KURL& module_url_record,
- network::mojom::FetchCredentialsMode) override;
-
- // Counts an evaluated script and its size. Called for the main worker script.
- void CountWorkerScript(size_t script_size, size_t cached_metadata_size);
-
- // Counts an evaluated script and its size. Called for each of imported
- // scripts.
- void CountImportedScript(size_t script_size, size_t cached_metadata_size);
-
- // Called when the main worker script is evaluated.
- void DidEvaluateClassicScript();
-
- // ServiceWorkerGlobalScope.idl
- ServiceWorkerClients* clients();
- ServiceWorkerRegistration* registration();
-
- ScriptPromise fetch(ScriptState*,
- const RequestInfo&,
- const Dictionary&,
- ExceptionState&);
-
- ScriptPromise skipWaiting(ScriptState*);
-
- void SetRegistration(std::unique_ptr<WebServiceWorkerRegistration::Handle>);
-
- // EventTarget
- const AtomicString& InterfaceName() const override;
-
- void DispatchExtendableEvent(Event*, WaitUntilObserver*);
-
- // For ExtendableEvents that also have a respondWith() function.
- void DispatchExtendableEventWithRespondWith(Event*,
- WaitUntilObserver*,
- RespondWithObserver*);
-
- bool IsInstalling() const { return is_installing_; }
- void SetIsInstalling(bool is_installing);
-
- // Script evaluation does not start until this function is called.
- void ReadyToEvaluateScript();
-
- void CountCacheStorageInstalledScript(uint64_t script_size,
- uint64_t script_metadata_size);
-
- mojom::blink::CacheStoragePtrInfo TakeCacheStorage();
-
- DEFINE_ATTRIBUTE_EVENT_LISTENER(install);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(activate);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(fetch);
- DEFINE_ATTRIBUTE_EVENT_LISTENER(message);
-
- void Trace(blink::Visitor*) override;
-
- protected:
- // EventTarget
- bool AddEventListenerInternal(
- const AtomicString& event_type,
- EventListener*,
- const AddEventListenerOptionsResolved&) override;
-
- private:
- ServiceWorkerGlobalScope(std::unique_ptr<GlobalScopeCreationParams>,
- ServiceWorkerThread*,
- mojom::blink::CacheStoragePtrInfo,
- double time_origin);
- void importScripts(const Vector<String>& urls, ExceptionState&) override;
- SingleCachedMetadataHandler* CreateWorkerScriptCachedMetadataHandler(
- const KURL& script_url,
- const Vector<char>* meta_data) override;
- void ExceptionThrown(ErrorEvent*) override;
-
- // Records the |script_size| and |cached_metadata_size| for UMA to measure the
- // number of scripts and the total bytes of scripts.
- void RecordScriptSize(size_t script_size, size_t cached_metadata_size);
-
- Member<ServiceWorkerClients> clients_;
- Member<ServiceWorkerRegistration> registration_;
- bool did_evaluate_script_ = false;
- size_t script_count_ = 0;
- size_t script_total_size_ = 0;
- size_t script_cached_metadata_total_size_ = 0;
- bool is_installing_ = false;
- size_t cache_storage_installed_script_count_ = 0;
- uint64_t cache_storage_installed_script_total_size_ = 0;
- uint64_t cache_storage_installed_script_metadata_total_size_ = 0;
-
- bool evaluate_script_ready_ = false;
- base::OnceClosure evaluate_script_;
-
- // May be provided in the constructor as an optimization so InterfaceProvider
- // doesn't need to be used. Taken at the initial call to
- // ServiceWorkerGlobalScope#caches.
- mojom::blink::CacheStoragePtrInfo cache_storage_info_;
-};
-
-DEFINE_TYPE_CASTS(ServiceWorkerGlobalScope,
- ExecutionContext,
- context,
- context->IsServiceWorkerGlobalScope(),
- context.IsServiceWorkerGlobalScope());
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_GLOBAL_SCOPE_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.idl b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.idl
deleted file mode 100644
index aca0474ba06..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.idl
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * 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.
- */
-
-// https://w3c.github.io/ServiceWorker/#serviceworkerglobalscope-interface
-
-[
- Exposed=ServiceWorker,
- Global=(Worker,ServiceWorker)
-] interface ServiceWorkerGlobalScope : WorkerGlobalScope {
-
- readonly attribute Clients clients;
- readonly attribute ServiceWorkerRegistration registration;
-
- [CallWith=ScriptState, RaisesException] Promise<Response> fetch(RequestInfo input, optional Dictionary init);
-
- [CallWith=ScriptState] Promise<void> skipWaiting();
-
- attribute EventHandler onactivate;
- attribute EventHandler onfetch;
- attribute EventHandler oninstall;
- attribute EventHandler onmessage;
-};
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.cc
deleted file mode 100644
index 3a6fe4c5581..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.cc
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * Copyright (C) 2014 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/modules/serviceworkers/service_worker_global_scope_client.h"
-
-#include <memory>
-#include <utility>
-#include "third_party/blink/public/platform/modules/payments/web_payment_handler_response.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_response.h"
-#include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/public/web/modules/serviceworker/web_service_worker_context_client.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/fetch/response.h"
-#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
-
-namespace blink {
-
-ServiceWorkerGlobalScopeClient::ServiceWorkerGlobalScopeClient(
- WebServiceWorkerContextClient& client)
- : client_(client) {}
-
-void ServiceWorkerGlobalScopeClient::GetClient(
- const WebString& id,
- std::unique_ptr<WebServiceWorkerClientCallbacks> callbacks) {
- client_.GetClient(id, std::move(callbacks));
-}
-
-void ServiceWorkerGlobalScopeClient::GetClients(
- const WebServiceWorkerClientQueryOptions& options,
- std::unique_ptr<WebServiceWorkerClientsCallbacks> callbacks) {
- client_.GetClients(options, std::move(callbacks));
-}
-
-void ServiceWorkerGlobalScopeClient::OpenWindowForClients(
- const WebURL& url,
- std::unique_ptr<WebServiceWorkerClientCallbacks> callbacks) {
- client_.OpenNewTab(url, std::move(callbacks));
-}
-
-void ServiceWorkerGlobalScopeClient::OpenWindowForPaymentHandler(
- const WebURL& url,
- std::unique_ptr<WebServiceWorkerClientCallbacks> callbacks) {
- client_.OpenPaymentHandlerWindow(url, std::move(callbacks));
-}
-
-void ServiceWorkerGlobalScopeClient::SetCachedMetadata(const WebURL& url,
- const char* data,
- size_t size) {
- client_.SetCachedMetadata(url, data, size);
-}
-
-void ServiceWorkerGlobalScopeClient::ClearCachedMetadata(const WebURL& url) {
- client_.ClearCachedMetadata(url);
-}
-
-void ServiceWorkerGlobalScopeClient::DidHandleActivateEvent(
- int event_id,
- mojom::ServiceWorkerEventStatus status,
- double event_dispatch_time) {
- client_.DidHandleActivateEvent(event_id, status, event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::DidHandleBackgroundFetchAbortEvent(
- int event_id,
- mojom::ServiceWorkerEventStatus status,
- double event_dispatch_time) {
- client_.DidHandleBackgroundFetchAbortEvent(event_id, status,
- event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::DidHandleBackgroundFetchClickEvent(
- int event_id,
- mojom::ServiceWorkerEventStatus status,
- double event_dispatch_time) {
- client_.DidHandleBackgroundFetchClickEvent(event_id, status,
- event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::DidHandleBackgroundFetchFailEvent(
- int event_id,
- mojom::ServiceWorkerEventStatus status,
- double event_dispatch_time) {
- client_.DidHandleBackgroundFetchFailEvent(event_id, status,
- event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::DidHandleBackgroundFetchedEvent(
- int event_id,
- mojom::ServiceWorkerEventStatus status,
- double event_dispatch_time) {
- client_.DidHandleBackgroundFetchedEvent(event_id, status,
- event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::DidHandleCookieChangeEvent(
- int event_id,
- mojom::ServiceWorkerEventStatus status,
- double event_dispatch_time) {
- client_.DidHandleCookieChangeEvent(event_id, status, event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::DidHandleExtendableMessageEvent(
- int event_id,
- mojom::ServiceWorkerEventStatus status,
- double event_dispatch_time) {
- client_.DidHandleExtendableMessageEvent(event_id, status,
- event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::RespondToFetchEventWithNoResponse(
- int fetch_event_id,
- double event_dispatch_time) {
- client_.RespondToFetchEventWithNoResponse(fetch_event_id,
- event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::RespondToFetchEvent(
- int fetch_event_id,
- const WebServiceWorkerResponse& response,
- double event_dispatch_time) {
- client_.RespondToFetchEvent(fetch_event_id, response, event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::RespondToFetchEventWithResponseStream(
- int fetch_event_id,
- const WebServiceWorkerResponse& response,
- WebServiceWorkerStreamHandle* stream_handle,
- double event_dispatch_time) {
- client_.RespondToFetchEventWithResponseStream(
- fetch_event_id, response, stream_handle, event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::RespondToAbortPaymentEvent(
- int event_id,
- bool abort_payment,
- double event_dispatch_time) {
- client_.RespondToAbortPaymentEvent(event_id, abort_payment,
- event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::RespondToCanMakePaymentEvent(
- int event_id,
- bool response,
- double event_dispatch_time) {
- client_.RespondToCanMakePaymentEvent(event_id, response, event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::RespondToPaymentRequestEvent(
- int event_id,
- const WebPaymentHandlerResponse& response,
- double event_dispatch_time) {
- client_.RespondToPaymentRequestEvent(event_id, response, event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::DidHandleFetchEvent(
- int fetch_event_id,
- mojom::ServiceWorkerEventStatus status,
- double event_dispatch_time) {
- client_.DidHandleFetchEvent(fetch_event_id, status, event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::DidHandleInstallEvent(
- int install_event_id,
- mojom::ServiceWorkerEventStatus status,
- double event_dispatch_time) {
- client_.DidHandleInstallEvent(install_event_id, status, event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::DidHandleNotificationClickEvent(
- int event_id,
- mojom::ServiceWorkerEventStatus status,
- double event_dispatch_time) {
- client_.DidHandleNotificationClickEvent(event_id, status,
- event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::DidHandleNotificationCloseEvent(
- int event_id,
- mojom::ServiceWorkerEventStatus status,
- double event_dispatch_time) {
- client_.DidHandleNotificationCloseEvent(event_id, status,
- event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::DidHandlePushEvent(
- int push_event_id,
- mojom::ServiceWorkerEventStatus status,
- double event_dispatch_time) {
- client_.DidHandlePushEvent(push_event_id, status, event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::DidHandleSyncEvent(
- int sync_event_id,
- mojom::ServiceWorkerEventStatus status,
- double event_dispatch_time) {
- client_.DidHandleSyncEvent(sync_event_id, status, event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::DidHandleAbortPaymentEvent(
- int abort_payment_event_id,
- mojom::ServiceWorkerEventStatus status,
- double event_dispatch_time) {
- client_.DidHandleAbortPaymentEvent(abort_payment_event_id, status,
- event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::DidHandleCanMakePaymentEvent(
- int payment_request_event_id,
- mojom::ServiceWorkerEventStatus status,
- double event_dispatch_time) {
- client_.DidHandleCanMakePaymentEvent(payment_request_event_id, status,
- event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::DidHandlePaymentRequestEvent(
- int payment_request_event_id,
- mojom::ServiceWorkerEventStatus status,
- double event_dispatch_time) {
- client_.DidHandlePaymentRequestEvent(payment_request_event_id, status,
- event_dispatch_time);
-}
-
-void ServiceWorkerGlobalScopeClient::PostMessageToClient(
- const WebString& client_uuid,
- TransferableMessage message) {
- client_.PostMessageToClient(client_uuid, std::move(message));
-}
-
-void ServiceWorkerGlobalScopeClient::SkipWaiting(
- std::unique_ptr<WebServiceWorkerSkipWaitingCallbacks> callbacks) {
- client_.SkipWaiting(std::move(callbacks));
-}
-
-void ServiceWorkerGlobalScopeClient::Claim(
- std::unique_ptr<WebServiceWorkerClientsClaimCallbacks> callbacks) {
- client_.Claim(std::move(callbacks));
-}
-
-void ServiceWorkerGlobalScopeClient::Focus(
- const WebString& client_uuid,
- std::unique_ptr<WebServiceWorkerClientCallbacks> callback) {
- client_.Focus(client_uuid, std::move(callback));
-}
-
-void ServiceWorkerGlobalScopeClient::Navigate(
- const WebString& client_uuid,
- const WebURL& url,
- std::unique_ptr<WebServiceWorkerClientCallbacks> callback) {
- client_.Navigate(client_uuid, url, std::move(callback));
-}
-
-const char ServiceWorkerGlobalScopeClient::kSupplementName[] =
- "ServiceWorkerGlobalScopeClient";
-
-ServiceWorkerGlobalScopeClient* ServiceWorkerGlobalScopeClient::From(
- ExecutionContext* context) {
- // TODO(horo): Replace CHECK() to DCHECK() when crbug.com/749930 is fixed.
- CHECK(context);
- WorkerClients* worker_clients = ToWorkerGlobalScope(context)->Clients();
- CHECK(worker_clients);
- ServiceWorkerGlobalScopeClient* client =
- Supplement<WorkerClients>::From<ServiceWorkerGlobalScopeClient>(
- worker_clients);
- CHECK(client);
- return client;
-}
-
-void ServiceWorkerGlobalScopeClient::Trace(blink::Visitor* visitor) {
- Supplement<WorkerClients>::Trace(visitor);
-}
-
-void ProvideServiceWorkerGlobalScopeClientToWorker(
- WorkerClients* clients,
- ServiceWorkerGlobalScopeClient* client) {
- clients->ProvideSupplement(client);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.h b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.h
deleted file mode 100644
index 21fbacc61b2..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2014 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_MODULES_SERVICEWORKERS_SERVICE_WORKER_GLOBAL_SCOPE_CLIENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_GLOBAL_SCOPE_CLIENT_H_
-
-#include <memory>
-#include "third_party/blink/public/common/message_port/transferable_message.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_clients_claim_callbacks.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_clients_info.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_skip_waiting_callbacks.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_stream_handle.h"
-#include "third_party/blink/renderer/core/messaging/message_port.h"
-#include "third_party/blink/renderer/core/workers/worker_clients.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
-
-namespace blink {
-
-struct WebPaymentHandlerResponse;
-struct WebServiceWorkerClientQueryOptions;
-class ExecutionContext;
-class WebServiceWorkerContextClient;
-class WebServiceWorkerResponse;
-class WebURL;
-class WorkerClients;
-
-// See WebServiceWorkerContextClient for documentation for the methods in this
-// class.
-class MODULES_EXPORT ServiceWorkerGlobalScopeClient
- : public GarbageCollected<ServiceWorkerGlobalScopeClient>,
- public Supplement<WorkerClients> {
- USING_GARBAGE_COLLECTED_MIXIN(ServiceWorkerGlobalScopeClient);
- WTF_MAKE_NONCOPYABLE(ServiceWorkerGlobalScopeClient);
-
- public:
- static const char kSupplementName[];
-
- explicit ServiceWorkerGlobalScopeClient(WebServiceWorkerContextClient&);
-
- // Called from ServiceWorkerClients.
- void GetClient(const WebString&,
- std::unique_ptr<WebServiceWorkerClientCallbacks>);
- void GetClients(const WebServiceWorkerClientQueryOptions&,
- std::unique_ptr<WebServiceWorkerClientsCallbacks>);
- void OpenWindowForClients(const WebURL&,
- std::unique_ptr<WebServiceWorkerClientCallbacks>);
- void OpenWindowForPaymentHandler(
- const WebURL&,
- std::unique_ptr<WebServiceWorkerClientCallbacks>);
- void SetCachedMetadata(const WebURL&, const char*, size_t);
- void ClearCachedMetadata(const WebURL&);
-
- void DidHandleActivateEvent(int event_id,
- mojom::ServiceWorkerEventStatus,
- double event_dispatch_time);
- void DidHandleBackgroundFetchAbortEvent(int event_id,
- mojom::ServiceWorkerEventStatus,
- double event_dispatch_time);
- void DidHandleBackgroundFetchClickEvent(int event_id,
- mojom::ServiceWorkerEventStatus,
- double event_dispatch_time);
- void DidHandleBackgroundFetchFailEvent(int event_id,
- mojom::ServiceWorkerEventStatus,
- double event_dispatch_time);
- void DidHandleBackgroundFetchedEvent(int event_id,
- mojom::ServiceWorkerEventStatus,
- double event_dispatch_time);
- void DidHandleCookieChangeEvent(int event_id,
- mojom::ServiceWorkerEventStatus,
- double event_dispatch_time);
- void DidHandleExtendableMessageEvent(int event_id,
- mojom::ServiceWorkerEventStatus,
- double event_dispatch_time);
- void RespondToFetchEventWithNoResponse(int fetch_event_id,
- double event_dispatch_time);
- void RespondToFetchEvent(int fetch_event_id,
- const WebServiceWorkerResponse&,
- double event_dispatch_time);
- void RespondToFetchEventWithResponseStream(int fetch_event_id,
- const WebServiceWorkerResponse&,
- WebServiceWorkerStreamHandle*,
- double event_dispatch_time);
- void RespondToAbortPaymentEvent(int event_id,
- bool abort_payment,
- double event_dispatch_time);
- void RespondToCanMakePaymentEvent(int event_id,
- bool can_make_payment,
- double event_dispatch_time);
- void RespondToPaymentRequestEvent(int event_id,
- const WebPaymentHandlerResponse&,
- double event_dispatch_time);
- void DidHandleFetchEvent(int fetch_event_id,
- mojom::ServiceWorkerEventStatus,
- double event_dispatch_time);
- void DidHandleInstallEvent(int install_event_id,
- mojom::ServiceWorkerEventStatus,
- double event_dispatch_time);
- void DidHandleNotificationClickEvent(int event_id,
- mojom::ServiceWorkerEventStatus,
- double event_dispatch_time);
- void DidHandleNotificationCloseEvent(int event_id,
- mojom::ServiceWorkerEventStatus,
- double event_dispatch_time);
- void DidHandlePushEvent(int push_event_id,
- mojom::ServiceWorkerEventStatus,
- double event_dispatch_time);
- void DidHandleSyncEvent(int sync_event_id,
- mojom::ServiceWorkerEventStatus,
- double event_dispatch_time);
- void DidHandleAbortPaymentEvent(int abort_payment_event_id,
- mojom::ServiceWorkerEventStatus,
- double event_dispatch_time);
- void DidHandleCanMakePaymentEvent(int payment_request_event_id,
- mojom::ServiceWorkerEventStatus,
- double event_dispatch_time);
- void DidHandlePaymentRequestEvent(int payment_request_event_id,
- mojom::ServiceWorkerEventStatus,
- double event_dispatch_time);
- void PostMessageToClient(const WebString& client_uuid, TransferableMessage);
- void SkipWaiting(std::unique_ptr<WebServiceWorkerSkipWaitingCallbacks>);
- void Claim(std::unique_ptr<WebServiceWorkerClientsClaimCallbacks>);
- void Focus(const WebString& client_uuid,
- std::unique_ptr<WebServiceWorkerClientCallbacks>);
- void Navigate(const WebString& client_uuid,
- const WebURL&,
- std::unique_ptr<WebServiceWorkerClientCallbacks>);
-
- static ServiceWorkerGlobalScopeClient* From(ExecutionContext*);
-
- void Trace(blink::Visitor*) override;
-
- private:
- WebServiceWorkerContextClient& client_;
-};
-
-MODULES_EXPORT void ProvideServiceWorkerGlobalScopeClientToWorker(
- WorkerClients*,
- ServiceWorkerGlobalScopeClient*);
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_GLOBAL_SCOPE_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_proxy.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_proxy.cc
deleted file mode 100644
index 91f1dbc304e..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_proxy.cc
+++ /dev/null
@@ -1,694 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * 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/modules/serviceworkers/service_worker_global_scope_proxy.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/memory/ptr_util.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom-blink.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/notifications/web_notification_data.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_request.h"
-#include "third_party/blink/public/web/modules/serviceworker/web_service_worker_context_client.h"
-#include "third_party/blink/public/web/web_serialized_script_value.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/execution_context.h"
-#include "third_party/blink/renderer/core/fetch/headers.h"
-#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
-#include "third_party/blink/renderer/core/inspector/console_message.h"
-#include "third_party/blink/renderer/core/messaging/blink_transferable_message.h"
-#include "third_party/blink/renderer/core/messaging/message_port.h"
-#include "third_party/blink/renderer/core/origin_trials/origin_trials.h"
-#include "third_party/blink/renderer/core/workers/parent_execution_context_task_runners.h"
-#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
-#include "third_party/blink/renderer/core/workers/worker_thread.h"
-#include "third_party/blink/renderer/modules/background_fetch/background_fetch_click_event.h"
-#include "third_party/blink/renderer/modules/background_fetch/background_fetch_click_event_init.h"
-#include "third_party/blink/renderer/modules/background_fetch/background_fetch_event.h"
-#include "third_party/blink/renderer/modules/background_fetch/background_fetch_event_init.h"
-#include "third_party/blink/renderer/modules/background_fetch/background_fetch_fail_event.h"
-#include "third_party/blink/renderer/modules/background_fetch/background_fetch_fail_event_init.h"
-#include "third_party/blink/renderer/modules/background_fetch/background_fetch_settled_event_init.h"
-#include "third_party/blink/renderer/modules/background_fetch/background_fetch_update_event.h"
-#include "third_party/blink/renderer/modules/background_sync/sync_event.h"
-#include "third_party/blink/renderer/modules/cookie_store/extendable_cookie_change_event.h"
-#include "third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h"
-#include "third_party/blink/renderer/modules/notifications/notification.h"
-#include "third_party/blink/renderer/modules/notifications/notification_event.h"
-#include "third_party/blink/renderer/modules/notifications/notification_event_init.h"
-#include "third_party/blink/renderer/modules/payments/abort_payment_event.h"
-#include "third_party/blink/renderer/modules/payments/abort_payment_respond_with_observer.h"
-#include "third_party/blink/renderer/modules/payments/can_make_payment_event.h"
-#include "third_party/blink/renderer/modules/payments/can_make_payment_respond_with_observer.h"
-#include "third_party/blink/renderer/modules/payments/payment_event_data_conversion.h"
-#include "third_party/blink/renderer/modules/payments/payment_request_event.h"
-#include "third_party/blink/renderer/modules/payments/payment_request_event_init.h"
-#include "third_party/blink/renderer/modules/payments/payment_request_respond_with_observer.h"
-#include "third_party/blink/renderer/modules/push_messaging/push_event.h"
-#include "third_party/blink/renderer/modules/push_messaging/push_message_data.h"
-#include "third_party/blink/renderer/modules/serviceworkers/extendable_event.h"
-#include "third_party/blink/renderer/modules/serviceworkers/extendable_message_event.h"
-#include "third_party/blink/renderer/modules/serviceworkers/fetch_event.h"
-#include "third_party/blink/renderer/modules/serviceworkers/fetch_respond_with_observer.h"
-#include "third_party/blink/renderer/modules/serviceworkers/install_event.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_client.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_window_client.h"
-#include "third_party/blink/renderer/modules/serviceworkers/wait_until_observer.h"
-#include "third_party/blink/renderer/platform/cross_thread_functional.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
-#include "third_party/blink/renderer/platform/network/content_security_policy_response_headers.h"
-#include "third_party/blink/renderer/platform/waitable_event.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/functional.h"
-
-namespace blink {
-
-namespace {
-
-void SetContentSecurityPolicyAndReferrerPolicyOnMainThread(
- WebEmbeddedWorkerImpl* embedded_worker,
- ContentSecurityPolicyResponseHeaders csp_headers,
- String referrer_policy,
- WaitableEvent* waitable_event) {
- DCHECK(IsMainThread());
- ContentSecurityPolicy* content_security_policy =
- ContentSecurityPolicy::Create();
- content_security_policy->DidReceiveHeaders(csp_headers);
- embedded_worker->SetContentSecurityPolicyAndReferrerPolicy(
- content_security_policy, std::move(referrer_policy));
- waitable_event->Signal();
-}
-
-} // namespace
-
-ServiceWorkerGlobalScopeProxy* ServiceWorkerGlobalScopeProxy::Create(
- WebEmbeddedWorkerImpl& embedded_worker,
- WebServiceWorkerContextClient& client) {
- return new ServiceWorkerGlobalScopeProxy(embedded_worker, client);
-}
-
-ServiceWorkerGlobalScopeProxy::~ServiceWorkerGlobalScopeProxy() {
- DCHECK(IsMainThread());
- // Verify that the proxy has been detached.
- DCHECK(!embedded_worker_);
-}
-
-void ServiceWorkerGlobalScopeProxy::Trace(blink::Visitor* visitor) {
- visitor->Trace(parent_execution_context_task_runners_);
-}
-
-void ServiceWorkerGlobalScopeProxy::ReadyToEvaluateScript() {
- WorkerGlobalScope()->ReadyToEvaluateScript();
-}
-
-void ServiceWorkerGlobalScopeProxy::SetRegistration(
- std::unique_ptr<WebServiceWorkerRegistration::Handle> handle) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- WorkerGlobalScope()->SetRegistration(std::move(handle));
-}
-
-void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchAbortEvent(
- int event_id,
- const WebString& developer_id,
- const WebString& unique_id,
- const WebVector<WebBackgroundFetchSettledFetch>& fetches) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- WaitUntilObserver* observer = WaitUntilObserver::Create(
- WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchAbort, event_id);
-
- ScriptState* script_state =
- WorkerGlobalScope()->ScriptController()->GetScriptState();
-
- BackgroundFetchSettledEventInit init;
- init.setId(developer_id);
- init.setFetches(BackgroundFetchSettledFetches::Create(script_state, fetches));
-
- BackgroundFetchSettledEvent* event = BackgroundFetchSettledEvent::Create(
- EventTypeNames::backgroundfetchabort, init, unique_id, observer);
-
- WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
-}
-
-void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchClickEvent(
- int event_id,
- const WebString& developer_id,
- BackgroundFetchState status) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- WaitUntilObserver* observer = WaitUntilObserver::Create(
- WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchClick, event_id);
-
- BackgroundFetchClickEventInit init;
- init.setId(developer_id);
-
- switch (status) {
- case BackgroundFetchState::kPending:
- init.setState("pending");
- break;
- case BackgroundFetchState::kSucceeded:
- init.setState("succeeded");
- break;
- case BackgroundFetchState::kFailed:
- init.setState("failed");
- break;
- }
-
- BackgroundFetchClickEvent* event = BackgroundFetchClickEvent::Create(
- EventTypeNames::backgroundfetchclick, init, observer);
-
- WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
-}
-
-void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchFailEvent(
- int event_id,
- const WebString& developer_id,
- const WebString& unique_id,
- const WebVector<WebBackgroundFetchSettledFetch>& fetches) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- WaitUntilObserver* observer = WaitUntilObserver::Create(
- WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetchFail, event_id);
-
- ScriptState* script_state =
- WorkerGlobalScope()->ScriptController()->GetScriptState();
-
- BackgroundFetchSettledEventInit init;
- init.setId(developer_id);
- init.setFetches(BackgroundFetchSettledFetches::Create(script_state, fetches));
-
- BackgroundFetchUpdateEvent* event = BackgroundFetchUpdateEvent::Create(
- EventTypeNames::backgroundfetched, init, unique_id, script_state,
- observer, worker_global_scope_->registration());
-
- WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
-}
-
-void ServiceWorkerGlobalScopeProxy::DispatchBackgroundFetchedEvent(
- int event_id,
- const WebString& developer_id,
- const WebString& unique_id,
- const WebVector<WebBackgroundFetchSettledFetch>& fetches) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- WaitUntilObserver* observer = WaitUntilObserver::Create(
- WorkerGlobalScope(), WaitUntilObserver::kBackgroundFetched, event_id);
-
- ScriptState* script_state =
- WorkerGlobalScope()->ScriptController()->GetScriptState();
-
- // Do not remove this, it modifies V8 state.
- ScriptState::Scope scope(script_state);
-
- BackgroundFetchSettledEventInit init;
- init.setId(developer_id);
- init.setFetches(BackgroundFetchSettledFetches::Create(script_state, fetches));
-
- BackgroundFetchUpdateEvent* event = BackgroundFetchUpdateEvent::Create(
- EventTypeNames::backgroundfetched, init, unique_id, script_state,
- observer, worker_global_scope_->registration());
-
- WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
-}
-
-void ServiceWorkerGlobalScopeProxy::DispatchActivateEvent(int event_id) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- WaitUntilObserver* observer = WaitUntilObserver::Create(
- WorkerGlobalScope(), WaitUntilObserver::kActivate, event_id);
- Event* event = ExtendableEvent::Create(EventTypeNames::activate,
- ExtendableEventInit(), observer);
- WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
-}
-
-void ServiceWorkerGlobalScopeProxy::DispatchCookieChangeEvent(
- int event_id,
- const WebString& cookie_name,
- const WebString& cookie_value,
- bool is_cookie_delete) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- WaitUntilObserver* observer = WaitUntilObserver::Create(
- WorkerGlobalScope(), WaitUntilObserver::kCookieChange, event_id);
-
- HeapVector<CookieListItem> changed;
- HeapVector<CookieListItem> deleted;
- ExtendableCookieChangeEvent::ToCookieChangeListItem(
- cookie_name, cookie_value, is_cookie_delete, changed, deleted);
- Event* event = ExtendableCookieChangeEvent::Create(
- EventTypeNames::cookiechange, std::move(changed), std::move(deleted),
- observer);
-
- // TODO(pwnall): When switching to blink::CanonicalCookie, handle the case
- // when (changed.IsEmpty() && deleted.IsEmpty()).
-
- // TODO(pwnall): Investigate dispatching this on cookieStore.
- WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
-}
-
-void ServiceWorkerGlobalScopeProxy::DispatchExtendableMessageEvent(
- int event_id,
- TransferableMessage message,
- const WebSecurityOrigin& source_origin,
- const WebServiceWorkerClientInfo& client) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- auto msg = ToBlinkTransferableMessage(std::move(message));
- MessagePortArray* ports =
- MessagePort::EntanglePorts(*worker_global_scope_, std::move(msg.ports));
- String origin;
- if (!source_origin.IsUnique())
- origin = source_origin.ToString();
- ServiceWorkerClient* source = nullptr;
- if (client.client_type == mojom::ServiceWorkerClientType::kWindow)
- source = ServiceWorkerWindowClient::Create(client);
- else
- source = ServiceWorkerClient::Create(client);
- WaitUntilObserver* observer = WaitUntilObserver::Create(
- WorkerGlobalScope(), WaitUntilObserver::kMessage, event_id);
-
- Event* event = ExtendableMessageEvent::Create(std::move(msg.message), origin,
- ports, source, observer);
- WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
-}
-
-void ServiceWorkerGlobalScopeProxy::DispatchExtendableMessageEvent(
- int event_id,
- TransferableMessage message,
- const WebSecurityOrigin& source_origin,
- std::unique_ptr<WebServiceWorker::Handle> handle) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- auto msg = ToBlinkTransferableMessage(std::move(message));
- MessagePortArray* ports =
- MessagePort::EntanglePorts(*worker_global_scope_, std::move(msg.ports));
- String origin;
- if (!source_origin.IsUnique())
- origin = source_origin.ToString();
- ServiceWorker* source =
- ServiceWorker::From(worker_global_scope_->GetExecutionContext(),
- base::WrapUnique(handle.release()));
- WaitUntilObserver* observer = WaitUntilObserver::Create(
- WorkerGlobalScope(), WaitUntilObserver::kMessage, event_id);
-
- Event* event = ExtendableMessageEvent::Create(std::move(msg.message), origin,
- ports, source, observer);
- WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
-}
-
-void ServiceWorkerGlobalScopeProxy::DispatchFetchEvent(
- int fetch_event_id,
- const WebServiceWorkerRequest& web_request,
- bool navigation_preload_sent) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- ScriptState::Scope scope(
- WorkerGlobalScope()->ScriptController()->GetScriptState());
- WaitUntilObserver* wait_until_observer = WaitUntilObserver::Create(
- WorkerGlobalScope(), WaitUntilObserver::kFetch, fetch_event_id);
- FetchRespondWithObserver* respond_with_observer =
- FetchRespondWithObserver::Create(
- WorkerGlobalScope(), fetch_event_id, web_request.Url(),
- web_request.Mode(), web_request.RedirectMode(),
- web_request.GetFrameType(), web_request.GetRequestContext(),
- wait_until_observer);
- Request* request = Request::Create(
- WorkerGlobalScope()->ScriptController()->GetScriptState(), web_request);
- request->getHeaders()->SetGuard(Headers::kImmutableGuard);
- FetchEventInit event_init;
- event_init.setCancelable(true);
- event_init.setRequest(request);
- event_init.setClientId(
- web_request.IsMainResourceLoad() ? WebString() : web_request.ClientId());
- event_init.setIsReload(web_request.IsReload());
- ScriptState* script_state =
- WorkerGlobalScope()->ScriptController()->GetScriptState();
- FetchEvent* fetch_event = FetchEvent::Create(
- script_state, EventTypeNames::fetch, event_init, respond_with_observer,
- wait_until_observer, navigation_preload_sent);
- if (navigation_preload_sent) {
- // Keep |fetchEvent| until OnNavigationPreloadComplete() or
- // onNavigationPreloadError() will be called.
- pending_preload_fetch_events_.insert(fetch_event_id, fetch_event);
- }
-
- WorkerGlobalScope()->DispatchExtendableEventWithRespondWith(
- fetch_event, wait_until_observer, respond_with_observer);
-}
-
-void ServiceWorkerGlobalScopeProxy::OnNavigationPreloadResponse(
- int fetch_event_id,
- std::unique_ptr<WebURLResponse> response,
- std::unique_ptr<WebDataConsumerHandle> data_consume_handle) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- auto it = pending_preload_fetch_events_.find(fetch_event_id);
- DCHECK(it != pending_preload_fetch_events_.end());
- FetchEvent* fetch_event = it->value.Get();
- DCHECK(fetch_event);
- fetch_event->OnNavigationPreloadResponse(
- WorkerGlobalScope()->ScriptController()->GetScriptState(),
- std::move(response), std::move(data_consume_handle));
-}
-
-void ServiceWorkerGlobalScopeProxy::OnNavigationPreloadError(
- int fetch_event_id,
- std::unique_ptr<WebServiceWorkerError> error) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- FetchEvent* fetch_event = pending_preload_fetch_events_.Take(fetch_event_id);
- DCHECK(fetch_event);
- // Display an unsanitized console message.
- if (!error->unsanitized_message.IsEmpty()) {
- WorkerGlobalScope()->AddConsoleMessage(ConsoleMessage::Create(
- kWorkerMessageSource, blink::MessageLevel::kErrorMessageLevel,
- error->unsanitized_message));
- }
- // Reject the preloadResponse promise.
- fetch_event->OnNavigationPreloadError(
- WorkerGlobalScope()->ScriptController()->GetScriptState(),
- std::move(error));
-}
-
-void ServiceWorkerGlobalScopeProxy::OnNavigationPreloadComplete(
- int fetch_event_id,
- TimeTicks completion_time,
- int64_t encoded_data_length,
- int64_t encoded_body_length,
- int64_t decoded_body_length) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- FetchEvent* fetch_event = pending_preload_fetch_events_.Take(fetch_event_id);
- DCHECK(fetch_event);
- fetch_event->OnNavigationPreloadComplete(
- WorkerGlobalScope(), completion_time, encoded_data_length,
- encoded_body_length, decoded_body_length);
-}
-
-void ServiceWorkerGlobalScopeProxy::DispatchInstallEvent(int event_id) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- WaitUntilObserver* observer = WaitUntilObserver::Create(
- WorkerGlobalScope(), WaitUntilObserver::kInstall, event_id);
- Event* event = InstallEvent::Create(
- EventTypeNames::install, ExtendableEventInit(), event_id, observer);
- WorkerGlobalScope()->SetIsInstalling(true);
- WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
-}
-
-void ServiceWorkerGlobalScopeProxy::DispatchNotificationClickEvent(
- int event_id,
- const WebString& notification_id,
- const WebNotificationData& data,
- int action_index,
- const WebString& reply) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- WaitUntilObserver* observer = WaitUntilObserver::Create(
- WorkerGlobalScope(), WaitUntilObserver::kNotificationClick, event_id);
- NotificationEventInit event_init;
- event_init.setNotification(Notification::Create(
- WorkerGlobalScope(), notification_id, data, true /* showing */));
- if (0 <= action_index && action_index < static_cast<int>(data.actions.size()))
- event_init.setAction(data.actions[action_index].action);
- event_init.setReply(reply);
- Event* event = NotificationEvent::Create(EventTypeNames::notificationclick,
- event_init, observer);
- WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
-}
-
-void ServiceWorkerGlobalScopeProxy::DispatchNotificationCloseEvent(
- int event_id,
- const WebString& notification_id,
- const WebNotificationData& data) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- WaitUntilObserver* observer = WaitUntilObserver::Create(
- WorkerGlobalScope(), WaitUntilObserver::kNotificationClose, event_id);
- NotificationEventInit event_init;
- event_init.setAction(WTF::String()); // initialize as null.
- event_init.setNotification(Notification::Create(
- WorkerGlobalScope(), notification_id, data, false /* showing */));
- Event* event = NotificationEvent::Create(EventTypeNames::notificationclose,
- event_init, observer);
- WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
-}
-
-void ServiceWorkerGlobalScopeProxy::DispatchPushEvent(int event_id,
- const WebString& data) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- WaitUntilObserver* observer = WaitUntilObserver::Create(
- WorkerGlobalScope(), WaitUntilObserver::kPush, event_id);
- Event* event = PushEvent::Create(EventTypeNames::push,
- PushMessageData::Create(data), observer);
- WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
-}
-
-void ServiceWorkerGlobalScopeProxy::DispatchSyncEvent(int event_id,
- const WebString& id,
- bool last_chance) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- WaitUntilObserver* observer = WaitUntilObserver::Create(
- WorkerGlobalScope(), WaitUntilObserver::kSync, event_id);
- Event* event =
- SyncEvent::Create(EventTypeNames::sync, id, last_chance, observer);
- WorkerGlobalScope()->DispatchExtendableEvent(event, observer);
-}
-
-void ServiceWorkerGlobalScopeProxy::DispatchAbortPaymentEvent(int event_id) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- WaitUntilObserver* wait_until_observer = WaitUntilObserver::Create(
- WorkerGlobalScope(), WaitUntilObserver::kAbortPayment, event_id);
- AbortPaymentRespondWithObserver* respond_with_observer =
- new AbortPaymentRespondWithObserver(WorkerGlobalScope(), event_id,
- wait_until_observer);
-
- Event* event = AbortPaymentEvent::Create(
- EventTypeNames::abortpayment, ExtendableEventInit(),
- respond_with_observer, wait_until_observer);
-
- WorkerGlobalScope()->DispatchExtendableEventWithRespondWith(
- event, wait_until_observer, respond_with_observer);
-}
-
-void ServiceWorkerGlobalScopeProxy::DispatchCanMakePaymentEvent(
- int event_id,
- const WebCanMakePaymentEventData& web_event_data) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- WaitUntilObserver* wait_until_observer = WaitUntilObserver::Create(
- WorkerGlobalScope(), WaitUntilObserver::kCanMakePayment, event_id);
- CanMakePaymentRespondWithObserver* respond_with_observer =
- new CanMakePaymentRespondWithObserver(WorkerGlobalScope(), event_id,
- wait_until_observer);
-
- Event* event = CanMakePaymentEvent::Create(
- EventTypeNames::canmakepayment,
- PaymentEventDataConversion::ToCanMakePaymentEventInit(
- WorkerGlobalScope()->ScriptController()->GetScriptState(),
- web_event_data),
- respond_with_observer, wait_until_observer);
-
- WorkerGlobalScope()->DispatchExtendableEventWithRespondWith(
- event, wait_until_observer, respond_with_observer);
-}
-
-void ServiceWorkerGlobalScopeProxy::DispatchPaymentRequestEvent(
- int event_id,
- const WebPaymentRequestEventData& web_app_request) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- WaitUntilObserver* wait_until_observer = WaitUntilObserver::Create(
- WorkerGlobalScope(), WaitUntilObserver::kPaymentRequest, event_id);
- PaymentRequestRespondWithObserver* respond_with_observer =
- PaymentRequestRespondWithObserver::Create(WorkerGlobalScope(), event_id,
- wait_until_observer);
-
- Event* event = PaymentRequestEvent::Create(
- EventTypeNames::paymentrequest,
- PaymentEventDataConversion::ToPaymentRequestEventInit(
- WorkerGlobalScope()->ScriptController()->GetScriptState(),
- web_app_request),
- respond_with_observer, wait_until_observer);
-
- WorkerGlobalScope()->DispatchExtendableEventWithRespondWith(
- event, wait_until_observer, respond_with_observer);
-}
-
-bool ServiceWorkerGlobalScopeProxy::HasFetchEventHandler() {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- return WorkerGlobalScope()->HasEventListeners(EventTypeNames::fetch);
-}
-
-void ServiceWorkerGlobalScopeProxy::CountFeature(WebFeature feature) {
- Client().CountFeature(feature);
-}
-
-void ServiceWorkerGlobalScopeProxy::CountDeprecation(WebFeature feature) {
- // Go through the same code path with countFeature() because a deprecation
- // message is already shown on the worker console and a remaining work is just
- // to record an API use.
- CountFeature(feature);
-}
-
-void ServiceWorkerGlobalScopeProxy::ReportException(
- const String& error_message,
- std::unique_ptr<SourceLocation> location,
- int exception_id) {
- Client().ReportException(error_message, location->LineNumber(),
- location->ColumnNumber(), location->Url());
-}
-
-void ServiceWorkerGlobalScopeProxy::ReportConsoleMessage(
- MessageSource source,
- MessageLevel level,
- const String& message,
- SourceLocation* location) {
- Client().ReportConsoleMessage(source, level, message, location->LineNumber(),
- location->Url());
-}
-
-void ServiceWorkerGlobalScopeProxy::PostMessageToPageInspector(
- int session_id,
- const String& message) {
- DCHECK(embedded_worker_);
- PostCrossThreadTask(
- *parent_execution_context_task_runners_->Get(
- TaskType::kInternalInspector),
- FROM_HERE,
- CrossThreadBind(&WebEmbeddedWorkerImpl::PostMessageToPageInspector,
- CrossThreadUnretained(embedded_worker_), session_id,
- message));
-}
-
-void ServiceWorkerGlobalScopeProxy::DidCreateWorkerGlobalScope(
- WorkerOrWorkletGlobalScope* worker_global_scope) {
- DCHECK(!worker_global_scope_);
- worker_global_scope_ =
- static_cast<ServiceWorkerGlobalScope*>(worker_global_scope);
- Client().WorkerContextStarted(this);
-}
-
-void ServiceWorkerGlobalScopeProxy::DidInitializeWorkerContext() {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- ScriptState::Scope scope(
- WorkerGlobalScope()->ScriptController()->GetScriptState());
- Client().DidInitializeWorkerContext(
- WorkerGlobalScope()->ScriptController()->GetContext());
-}
-
-void ServiceWorkerGlobalScopeProxy::DidLoadInstalledScript(
- const ContentSecurityPolicyResponseHeaders& csp_headers_on_worker_thread,
- const String& referrer_policy_on_worker_thread) {
- // Post a task to the main thread to set CSP and ReferrerPolicy on the shadow
- // page.
- DCHECK(embedded_worker_);
- WaitableEvent waitable_event;
- PostCrossThreadTask(
- *parent_execution_context_task_runners_->Get(TaskType::kInternalWorker),
- FROM_HERE,
- CrossThreadBind(&SetContentSecurityPolicyAndReferrerPolicyOnMainThread,
- CrossThreadUnretained(embedded_worker_),
- csp_headers_on_worker_thread,
- referrer_policy_on_worker_thread,
- CrossThreadUnretained(&waitable_event)));
- Client().WorkerScriptLoaded();
-
- // Wait for the task to complete before returning. This ensures that worker
- // script evaluation can't start and issue any fetches until CSP and
- // ReferrerPolicy are set.
- waitable_event.Wait();
-}
-
-void ServiceWorkerGlobalScopeProxy::WillEvaluateClassicScript(
- size_t script_size,
- size_t cached_metadata_size) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- worker_global_scope_->CountWorkerScript(script_size, cached_metadata_size);
-}
-
-void ServiceWorkerGlobalScopeProxy::WillEvaluateImportedClassicScript(
- size_t script_size,
- size_t cached_metadata_size) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- worker_global_scope_->CountImportedScript(script_size, cached_metadata_size);
-}
-
-void ServiceWorkerGlobalScopeProxy::DidEvaluateClassicScript(bool success) {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- WorkerGlobalScope()->DidEvaluateClassicScript();
- Client().DidEvaluateClassicScript(success);
-}
-
-void ServiceWorkerGlobalScopeProxy::DidCloseWorkerGlobalScope() {
- // This should never be called because close() is not defined in
- // ServiceWorkerGlobalScope.
- NOTREACHED();
-}
-
-void ServiceWorkerGlobalScopeProxy::WillDestroyWorkerGlobalScope() {
- DCHECK(WorkerGlobalScope()->IsContextThread());
- v8::HandleScope handle_scope(WorkerGlobalScope()->GetThread()->GetIsolate());
- Client().WillDestroyWorkerContext(
- WorkerGlobalScope()->ScriptController()->GetContext());
- worker_global_scope_ = nullptr;
-}
-
-void ServiceWorkerGlobalScopeProxy::DidTerminateWorkerThread() {
- // This should be called after WillDestroyWorkerGlobalScope().
- DCHECK(!worker_global_scope_);
- Client().WorkerContextDestroyed();
-}
-
-ServiceWorkerGlobalScopeProxy::ServiceWorkerGlobalScopeProxy(
- WebEmbeddedWorkerImpl& embedded_worker,
- WebServiceWorkerContextClient& client)
- : embedded_worker_(&embedded_worker),
- client_(&client),
- worker_global_scope_(nullptr) {
- DCHECK(IsMainThread());
- // ServiceWorker can sometimes run tasks that are initiated by/associated with
- // a document's frame but these documents can be from a different process. So
- // we intentionally populate the task runners with default task runners of the
- // main thread.
- parent_execution_context_task_runners_ =
- ParentExecutionContextTaskRunners::Create();
-}
-
-void ServiceWorkerGlobalScopeProxy::Detach() {
- DCHECK(IsMainThread());
- embedded_worker_ = nullptr;
- client_ = nullptr;
-}
-
-void ServiceWorkerGlobalScopeProxy::TerminateWorkerContext() {
- embedded_worker_->TerminateWorkerContext();
-}
-
-WebServiceWorkerContextClient& ServiceWorkerGlobalScopeProxy::Client() const {
- DCHECK(client_);
- return *client_;
-}
-
-ServiceWorkerGlobalScope* ServiceWorkerGlobalScopeProxy::WorkerGlobalScope()
- const {
- DCHECK(worker_global_scope_);
- DCHECK(worker_global_scope_->IsContextThread());
- return worker_global_scope_;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_proxy.h b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_proxy.h
deleted file mode 100644
index a012b73a4aa..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_proxy.h
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * 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_MODULES_SERVICEWORKERS_SERVICE_WORKER_GLOBAL_SCOPE_PROXY_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_GLOBAL_SCOPE_PROXY_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/public/web/modules/serviceworker/web_service_worker_context_proxy.h"
-#include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
-#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/blink/renderer/platform/wtf/time.h"
-
-namespace blink {
-
-class FetchEvent;
-class ParentExecutionContextTaskRunners;
-class ServiceWorkerGlobalScope;
-class WebDataConsumerHandle;
-class WebEmbeddedWorkerImpl;
-class WebServiceWorkerContextClient;
-struct WebServiceWorkerError;
-class WebServiceWorkerRequest;
-class WebURLResponse;
-
-// This class is created and destructed on the main thread, but live most
-// of its time as a resident of the worker thread. All methods other than its
-// ctor/dtor and Detach() are called on the worker thread.
-//
-// This implements WebServiceWorkerContextProxy, which connects ServiceWorker's
-// WorkerGlobalScope and embedder/chrome, and implements ServiceWorker-specific
-// events/upcall methods that are to be called by embedder/chromium,
-// e.g. onfetch.
-//
-// An instance of this class is supposed to outlive until
-// workerThreadTerminated() is called by its corresponding
-// WorkerGlobalScope.
-class ServiceWorkerGlobalScopeProxy final
- : public GarbageCollectedFinalized<ServiceWorkerGlobalScopeProxy>,
- public WebServiceWorkerContextProxy,
- public WorkerReportingProxy {
- public:
- static ServiceWorkerGlobalScopeProxy* Create(WebEmbeddedWorkerImpl&,
- WebServiceWorkerContextClient&);
- ~ServiceWorkerGlobalScopeProxy() override;
-
- // WebServiceWorkerContextProxy overrides:
- void ReadyToEvaluateScript() override;
- void SetRegistration(
- std::unique_ptr<WebServiceWorkerRegistration::Handle>) override;
- void DispatchActivateEvent(int) override;
- void DispatchBackgroundFetchAbortEvent(
- int event_id,
- const WebString& developer_id,
- const WebString& unique_id,
- const WebVector<WebBackgroundFetchSettledFetch>& fetches) override;
- void DispatchBackgroundFetchClickEvent(int event_id,
- const WebString& developer_id,
- BackgroundFetchState) override;
- void DispatchBackgroundFetchFailEvent(
- int event_id,
- const WebString& developer_id,
- const WebString& unique_id,
- const WebVector<WebBackgroundFetchSettledFetch>& fetches) override;
- void DispatchBackgroundFetchedEvent(
- int event_id,
- const WebString& developer_id,
- const WebString& unique_id,
- const WebVector<WebBackgroundFetchSettledFetch>& fetches) override;
- void DispatchCookieChangeEvent(int event_id,
- const WebString& cookie_name,
- const WebString& cookie_value,
- bool is_cookie_delete) override;
- void DispatchExtendableMessageEvent(
- int event_id,
- TransferableMessage,
- const WebSecurityOrigin& source_origin,
- const WebServiceWorkerClientInfo&) override;
- void DispatchExtendableMessageEvent(
- int event_id,
- TransferableMessage,
- const WebSecurityOrigin& source_origin,
- std::unique_ptr<WebServiceWorker::Handle>) override;
- void DispatchFetchEvent(int fetch_event_id,
- const WebServiceWorkerRequest&,
- bool navigation_preload_sent) override;
- void DispatchInstallEvent(int) override;
- void DispatchNotificationClickEvent(int,
- const WebString& notification_id,
- const WebNotificationData&,
- int action_index,
- const WebString& reply) override;
- void DispatchNotificationCloseEvent(int,
- const WebString& notification_id,
- const WebNotificationData&) override;
- void DispatchPushEvent(int, const WebString& data) override;
- void DispatchSyncEvent(int, const WebString& tag, bool last_chance) override;
- void DispatchAbortPaymentEvent(int) override;
- void DispatchCanMakePaymentEvent(int,
- const WebCanMakePaymentEventData&) override;
- void DispatchPaymentRequestEvent(int,
- const WebPaymentRequestEventData&) override;
- bool HasFetchEventHandler() override;
- void OnNavigationPreloadResponse(
- int fetch_event_id,
- std::unique_ptr<WebURLResponse>,
- std::unique_ptr<WebDataConsumerHandle>) override;
- void OnNavigationPreloadError(
- int fetch_event_id,
- std::unique_ptr<WebServiceWorkerError>) override;
- void OnNavigationPreloadComplete(int fetch_event_id,
- TimeTicks completion_time,
- int64_t encoded_data_length,
- int64_t encoded_body_length,
- int64_t decoded_body_length) override;
-
- // WorkerReportingProxy overrides:
- void CountFeature(WebFeature) override;
- void CountDeprecation(WebFeature) override;
- void ReportException(const String& error_message,
- std::unique_ptr<SourceLocation>,
- int exception_id) override;
- void ReportConsoleMessage(MessageSource,
- MessageLevel,
- const String& message,
- SourceLocation*) override;
- void PostMessageToPageInspector(int session_id, const String&) override;
- void DidCreateWorkerGlobalScope(WorkerOrWorkletGlobalScope*) override;
- void DidInitializeWorkerContext() override;
- void DidLoadInstalledScript(
- const ContentSecurityPolicyResponseHeaders&,
- const String& referrer_policy_on_worker_thread) override;
- void WillEvaluateClassicScript(size_t script_size,
- size_t cached_metadata_size) override;
- void WillEvaluateImportedClassicScript(size_t script_size,
- size_t cached_metadata_size) override;
- void DidEvaluateClassicScript(bool success) override;
- void DidCloseWorkerGlobalScope() override;
- void WillDestroyWorkerGlobalScope() override;
- void DidTerminateWorkerThread() override;
-
- void Trace(blink::Visitor*);
-
- // Detaches this proxy object entirely from the outside world, clearing out
- // all references.
- //
- // It is called on the main thread during WebEmbeddedWorkerImpl finalization
- // _after_ the worker thread using the proxy has been terminated.
- void Detach();
-
- void TerminateWorkerContext();
-
- private:
- ServiceWorkerGlobalScopeProxy(WebEmbeddedWorkerImpl&,
- WebServiceWorkerContextClient&);
-
- WebServiceWorkerContextClient& Client() const;
- ServiceWorkerGlobalScope* WorkerGlobalScope() const;
-
- // Non-null until the WebEmbeddedWorkerImpl explicitly detach()es
- // as part of its finalization.
- WebEmbeddedWorkerImpl* embedded_worker_;
-
- Member<ParentExecutionContextTaskRunners>
- parent_execution_context_task_runners_;
-
- // The worker thread uses this map to track |FetchEvent|s created
- // on the worker thread (heap.) But as the proxy object is created
- // on the main thread & its heap, we must use a cross-heap reference
- // to each |FetchEvent| so as to obey the "per-thread heap rule" that
- // a heap should only have per-thread heap references. Keeping a
- // cross-heap reference requires the use of a CrossThreadPersistent<>
- // to remain safe and sound.
- //
- HashMap<int, CrossThreadPersistent<FetchEvent>> pending_preload_fetch_events_;
-
- WebServiceWorkerContextClient* client_;
-
- CrossThreadPersistent<ServiceWorkerGlobalScope> worker_global_scope_;
-
- DISALLOW_COPY_AND_ASSIGN(ServiceWorkerGlobalScopeProxy);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_GLOBAL_SCOPE_PROXY_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_installed_scripts_manager.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_installed_scripts_manager.cc
deleted file mode 100644
index 1f89aa4492a..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_installed_scripts_manager.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_installed_scripts_manager.h"
-
-#include <memory>
-#include <utility>
-
-#include "third_party/blink/renderer/core/html/parser/text_resource_decoder.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_thread.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-
-namespace blink {
-
-ServiceWorkerInstalledScriptsManager::ServiceWorkerInstalledScriptsManager(
- std::unique_ptr<WebServiceWorkerInstalledScriptsManager> manager)
- : manager_(std::move(manager)) {
- DCHECK(manager_);
-}
-
-bool ServiceWorkerInstalledScriptsManager::IsScriptInstalled(
- const KURL& script_url) const {
- return manager_->IsScriptInstalled(script_url);
-}
-
-InstalledScriptsManager::ScriptStatus
-ServiceWorkerInstalledScriptsManager::GetScriptData(
- const KURL& script_url,
- InstalledScriptsManager::ScriptData* out_script_data) {
- DCHECK(!IsMainThread());
- // This blocks until the script is received from the browser.
- std::unique_ptr<WebServiceWorkerInstalledScriptsManager::RawScriptData>
- raw_script_data = manager_->GetRawScriptData(script_url);
- DCHECK(raw_script_data);
- if (!raw_script_data->IsValid()) {
- *out_script_data = InstalledScriptsManager::ScriptData();
- return ScriptStatus::kFailed;
- }
-
- // This is from WorkerClassicScriptLoader::DidReceiveData.
- std::unique_ptr<TextResourceDecoder> decoder =
- TextResourceDecoder::Create(TextResourceDecoderOptions(
- TextResourceDecoderOptions::kPlainTextContent,
- raw_script_data->Encoding().IsEmpty()
- ? UTF8Encoding()
- : WTF::TextEncoding(raw_script_data->Encoding())));
-
- StringBuilder source_text_builder;
- for (const auto& chunk : raw_script_data->ScriptTextChunks())
- source_text_builder.Append(decoder->Decode(chunk.Data(), chunk.size()));
-
- std::unique_ptr<Vector<char>> meta_data;
- if (raw_script_data->MetaDataChunks().size() > 0) {
- size_t total_metadata_size = 0;
- for (const auto& chunk : raw_script_data->MetaDataChunks())
- total_metadata_size += chunk.size();
- meta_data = std::make_unique<Vector<char>>();
- meta_data->ReserveInitialCapacity(total_metadata_size);
- for (const auto& chunk : raw_script_data->MetaDataChunks())
- meta_data->Append(chunk.Data(), chunk.size());
- }
-
- InstalledScriptsManager::ScriptData script_data(
- script_url, source_text_builder.ToString(), std::move(meta_data),
- raw_script_data->TakeHeaders());
- *out_script_data = std::move(script_data);
- return ScriptStatus::kSuccess;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_installed_scripts_manager.h b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_installed_scripts_manager.h
deleted file mode 100644
index f8b0e463c43..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_installed_scripts_manager.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_INSTALLED_SCRIPTS_MANAGER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_INSTALLED_SCRIPTS_MANAGER_H_
-
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_installed_scripts_manager.h"
-#include "third_party/blink/renderer/core/workers/installed_scripts_manager.h"
-
-namespace blink {
-
-// ServiceWorkerInstalledScriptsManager provides the main script and imported
-// scripts of an installed service worker. The scripts are streamed from the
-// browser process in parallel with worker thread initialization.
-class ServiceWorkerInstalledScriptsManager final
- : public InstalledScriptsManager {
- public:
- explicit ServiceWorkerInstalledScriptsManager(
- std::unique_ptr<WebServiceWorkerInstalledScriptsManager>);
-
- // InstalledScriptsManager implementation.
- bool IsScriptInstalled(const KURL& script_url) const override;
- ScriptStatus GetScriptData(const KURL& script_url,
- ScriptData* out_script_data) override;
-
- private:
- std::unique_ptr<WebServiceWorkerInstalledScriptsManager> manager_;
-};
-
-} // namespace blink
-
-#endif // WorkerInstalledScriptsManager_h
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_registration.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_registration.cc
deleted file mode 100644
index e9d1eb8e46a..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_registration.cc
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/memory/ptr_util.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom-blink.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider.h"
-#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#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/dom/exception_code.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/modules/event_target_modules.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_container_client.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_error.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-
-namespace blink {
-
-ServiceWorkerRegistration* ServiceWorkerRegistration::Take(
- ScriptPromiseResolver* resolver,
- std::unique_ptr<WebServiceWorkerRegistration::Handle> handle) {
- return GetOrCreate(resolver->GetExecutionContext(), std::move(handle));
-}
-
-bool ServiceWorkerRegistration::HasPendingActivity() const {
- return !stopped_;
-}
-
-const AtomicString& ServiceWorkerRegistration::InterfaceName() const {
- return EventTargetNames::ServiceWorkerRegistration;
-}
-
-void ServiceWorkerRegistration::DispatchUpdateFoundEvent() {
- DispatchEvent(Event::Create(EventTypeNames::updatefound));
-}
-
-void ServiceWorkerRegistration::SetInstalling(
- std::unique_ptr<WebServiceWorker::Handle> handle) {
- if (!GetExecutionContext())
- return;
- installing_ = ServiceWorker::From(GetExecutionContext(),
- base::WrapUnique(handle.release()));
-}
-
-void ServiceWorkerRegistration::SetWaiting(
- std::unique_ptr<WebServiceWorker::Handle> handle) {
- if (!GetExecutionContext())
- return;
- waiting_ = ServiceWorker::From(GetExecutionContext(),
- base::WrapUnique(handle.release()));
-}
-
-void ServiceWorkerRegistration::SetActive(
- std::unique_ptr<WebServiceWorker::Handle> handle) {
- if (!GetExecutionContext())
- return;
- active_ = ServiceWorker::From(GetExecutionContext(),
- base::WrapUnique(handle.release()));
-}
-
-ServiceWorkerRegistration* ServiceWorkerRegistration::GetOrCreate(
- ExecutionContext* execution_context,
- std::unique_ptr<WebServiceWorkerRegistration::Handle> handle) {
- DCHECK(handle);
-
- ServiceWorkerRegistration* existing_registration =
- static_cast<ServiceWorkerRegistration*>(handle->Registration()->Proxy());
- if (existing_registration) {
- DCHECK_EQ(existing_registration->GetExecutionContext(), execution_context);
- return existing_registration;
- }
-
- return new ServiceWorkerRegistration(execution_context, std::move(handle));
-}
-
-NavigationPreloadManager* ServiceWorkerRegistration::navigationPreload() {
- if (!navigation_preload_)
- navigation_preload_ = NavigationPreloadManager::Create(this);
- return navigation_preload_;
-}
-
-String ServiceWorkerRegistration::scope() const {
- return handle_->Registration()->Scope().GetString();
-}
-
-String ServiceWorkerRegistration::updateViaCache() const {
- switch (handle_->Registration()->UpdateViaCache()) {
- case mojom::ServiceWorkerUpdateViaCache::kImports:
- return "imports";
- case mojom::ServiceWorkerUpdateViaCache::kAll:
- return "all";
- case mojom::ServiceWorkerUpdateViaCache::kNone:
- return "none";
- }
- NOTREACHED();
- return "";
-}
-
-ScriptPromise ServiceWorkerRegistration::update(ScriptState* script_state) {
- ServiceWorkerContainerClient* client =
- ServiceWorkerContainerClient::From(GetExecutionContext());
- if (!client || !client->Provider())
- return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError,
- "Failed to update a ServiceWorkerRegistration: No "
- "associated provider is available."));
-
- ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- ScriptPromise promise = resolver->Promise();
- handle_->Registration()->Update(
- std::make_unique<
- CallbackPromiseAdapter<void, ServiceWorkerErrorForUpdate>>(resolver));
- return promise;
-}
-
-ScriptPromise ServiceWorkerRegistration::unregister(ScriptState* script_state) {
- ServiceWorkerContainerClient* client =
- ServiceWorkerContainerClient::From(GetExecutionContext());
- if (!client || !client->Provider())
- return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError,
- "Failed to unregister a "
- "ServiceWorkerRegistration: No "
- "associated provider is available."));
-
- ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- ScriptPromise promise = resolver->Promise();
- handle_->Registration()->Unregister(
- std::make_unique<CallbackPromiseAdapter<bool, ServiceWorkerError>>(
- resolver));
- return promise;
-}
-
-ServiceWorkerRegistration::ServiceWorkerRegistration(
- ExecutionContext* execution_context,
- std::unique_ptr<WebServiceWorkerRegistration::Handle> handle)
- : ContextLifecycleObserver(execution_context),
- handle_(std::move(handle)),
- stopped_(false) {
- DCHECK(handle_);
- DCHECK(!handle_->Registration()->Proxy());
-
- if (!execution_context)
- return;
- handle_->Registration()->SetProxy(this);
-}
-
-ServiceWorkerRegistration::~ServiceWorkerRegistration() = default;
-
-void ServiceWorkerRegistration::Dispose() {
- // Promptly clears a raw reference from content/ to an on-heap object
- // so that content/ doesn't access it in a lazy sweeping phase.
- handle_.reset();
-}
-
-void ServiceWorkerRegistration::Trace(blink::Visitor* visitor) {
- visitor->Trace(installing_);
- visitor->Trace(waiting_);
- visitor->Trace(active_);
- visitor->Trace(navigation_preload_);
- EventTargetWithInlineData::Trace(visitor);
- ContextLifecycleObserver::Trace(visitor);
- Supplementable<ServiceWorkerRegistration>::Trace(visitor);
-}
-
-void ServiceWorkerRegistration::ContextDestroyed(ExecutionContext*) {
- if (stopped_)
- return;
- stopped_ = true;
- handle_->Registration()->ProxyStopped();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h
deleted file mode 100644
index 6cbf0811bfe..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_REGISTRATION_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_REGISTRATION_H_
-
-#include <memory>
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_registration.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_registration_proxy.h"
-#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
-#include "third_party/blink/renderer/core/dom/events/event_target.h"
-#include "third_party/blink/renderer/modules/serviceworkers/navigation_preload_manager.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
-#include "third_party/blink/renderer/platform/supplementable.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
-
-namespace blink {
-
-class ScriptPromise;
-class ScriptState;
-
-// The implementation of a service worker registration object in Blink. Actual
-// registration representation is in the embedder and this class accesses it
-// via WebServiceWorkerRegistration::Handle object.
-class ServiceWorkerRegistration final
- : public EventTargetWithInlineData,
- public ActiveScriptWrappable<ServiceWorkerRegistration>,
- public ContextLifecycleObserver,
- public WebServiceWorkerRegistrationProxy,
- public Supplementable<ServiceWorkerRegistration> {
- DEFINE_WRAPPERTYPEINFO();
- USING_GARBAGE_COLLECTED_MIXIN(ServiceWorkerRegistration);
- USING_PRE_FINALIZER(ServiceWorkerRegistration, Dispose);
-
- public:
- // Called from CallbackPromiseAdapter.
- using WebType = std::unique_ptr<WebServiceWorkerRegistration::Handle>;
- static ServiceWorkerRegistration* Take(
- ScriptPromiseResolver*,
- std::unique_ptr<WebServiceWorkerRegistration::Handle>);
-
- // ScriptWrappable overrides.
- bool HasPendingActivity() const final;
-
- // EventTarget overrides.
- const AtomicString& InterfaceName() const override;
- ExecutionContext* GetExecutionContext() const override {
- return ContextLifecycleObserver::GetExecutionContext();
- }
-
- // WebServiceWorkerRegistrationProxy overrides.
- void DispatchUpdateFoundEvent() override;
- void SetInstalling(std::unique_ptr<WebServiceWorker::Handle>) override;
- void SetWaiting(std::unique_ptr<WebServiceWorker::Handle>) override;
- void SetActive(std::unique_ptr<WebServiceWorker::Handle>) override;
-
- // Returns an existing registration object for the handle if it exists.
- // Otherwise, returns a new registration object.
- static ServiceWorkerRegistration* GetOrCreate(
- ExecutionContext*,
- std::unique_ptr<WebServiceWorkerRegistration::Handle>);
-
- ServiceWorker* installing() { return installing_; }
- ServiceWorker* waiting() { return waiting_; }
- ServiceWorker* active() { return active_; }
- NavigationPreloadManager* navigationPreload();
-
- String scope() const;
- String updateViaCache() const;
-
- WebServiceWorkerRegistration* WebRegistration() {
- return handle_->Registration();
- }
-
- ScriptPromise update(ScriptState*);
- ScriptPromise unregister(ScriptState*);
-
- DEFINE_ATTRIBUTE_EVENT_LISTENER(updatefound);
-
- ~ServiceWorkerRegistration() override;
-
- void Trace(blink::Visitor*) override;
-
- private:
- ServiceWorkerRegistration(
- ExecutionContext*,
- std::unique_ptr<WebServiceWorkerRegistration::Handle>);
- void Dispose();
-
- // ContextLifecycleObserver overrides.
- void ContextDestroyed(ExecutionContext*) override;
-
- // A handle to the registration representation in the embedder.
- std::unique_ptr<WebServiceWorkerRegistration::Handle> handle_;
-
- Member<ServiceWorker> installing_;
- Member<ServiceWorker> waiting_;
- Member<ServiceWorker> active_;
- Member<NavigationPreloadManager> navigation_preload_;
-
- bool stopped_;
-};
-
-class ServiceWorkerRegistrationArray {
- STATIC_ONLY(ServiceWorkerRegistrationArray);
-
- public:
- // Called from CallbackPromiseAdapter.
- using WebType = std::unique_ptr<
- WebVector<std::unique_ptr<WebServiceWorkerRegistration::Handle>>>;
- static HeapVector<Member<ServiceWorkerRegistration>> Take(
- ScriptPromiseResolver* resolver,
- WebType web_service_worker_registrations) {
- HeapVector<Member<ServiceWorkerRegistration>> registrations;
- for (auto& registration : *web_service_worker_registrations) {
- registrations.push_back(
- ServiceWorkerRegistration::Take(resolver, std::move(registration)));
- }
- return registrations;
- }
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_REGISTRATION_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_registration.idl b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_registration.idl
deleted file mode 100644
index f71459cd250..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_registration.idl
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://w3c.github.io/ServiceWorker/#enumdef-serviceworkerupdateviacache
-[
- RuntimeEnabled=ServiceWorkerUpdateViaCache
-] enum ServiceWorkerUpdateViaCache {
- "imports",
- "all",
- "none"
-};
-
-// https://w3c.github.io/ServiceWorker/#serviceworkerregistration-interface
-[
- ActiveScriptWrappable,
- Exposed=(Window,Worker)
-] interface ServiceWorkerRegistration : EventTarget {
- readonly attribute ServiceWorker? installing;
- readonly attribute ServiceWorker? waiting;
- readonly attribute ServiceWorker? active;
- readonly attribute NavigationPreloadManager navigationPreload;
-
- readonly attribute USVString scope;
- [RuntimeEnabled=ServiceWorkerUpdateViaCache] readonly attribute ServiceWorkerUpdateViaCache updateViaCache;
-
- [CallWith=ScriptState] Promise<void> update();
- [CallWith=ScriptState] Promise<boolean> unregister();
-
- attribute EventHandler onupdatefound;
-};
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_script_cached_metadata_handler.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_script_cached_metadata_handler.cc
deleted file mode 100644
index 70b8d464d48..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_script_cached_metadata_handler.cc
+++ /dev/null
@@ -1,72 +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/modules/serviceworkers/service_worker_script_cached_metadata_handler.h"
-
-#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.h"
-#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h"
-
-namespace blink {
-
-ServiceWorkerScriptCachedMetadataHandler::
- ServiceWorkerScriptCachedMetadataHandler(
- WorkerGlobalScope* worker_global_scope,
- const KURL& script_url,
- const Vector<char>* meta_data)
- : worker_global_scope_(worker_global_scope), script_url_(script_url) {
- if (meta_data)
- cached_metadata_ = CachedMetadata::CreateFromSerializedData(
- meta_data->data(), meta_data->size());
-}
-
-ServiceWorkerScriptCachedMetadataHandler::
- ~ServiceWorkerScriptCachedMetadataHandler() = default;
-
-void ServiceWorkerScriptCachedMetadataHandler::Trace(blink::Visitor* visitor) {
- visitor->Trace(worker_global_scope_);
- CachedMetadataHandler::Trace(visitor);
-}
-
-void ServiceWorkerScriptCachedMetadataHandler::SetCachedMetadata(
- uint32_t data_type_id,
- const char* data,
- size_t size,
- CacheType type) {
- if (type != kSendToPlatform)
- return;
- cached_metadata_ = CachedMetadata::Create(data_type_id, data, size);
- const Vector<char>& serialized_data = cached_metadata_->SerializedData();
- ServiceWorkerGlobalScopeClient::From(worker_global_scope_)
- ->SetCachedMetadata(script_url_, serialized_data.data(),
- serialized_data.size());
-}
-
-void ServiceWorkerScriptCachedMetadataHandler::ClearCachedMetadata(
- CacheType type) {
- if (type != kSendToPlatform)
- return;
- cached_metadata_ = nullptr;
- ServiceWorkerGlobalScopeClient::From(worker_global_scope_)
- ->ClearCachedMetadata(script_url_);
-}
-
-scoped_refptr<CachedMetadata>
-ServiceWorkerScriptCachedMetadataHandler::GetCachedMetadata(
- uint32_t data_type_id) const {
- if (!cached_metadata_ || cached_metadata_->DataTypeID() != data_type_id)
- return nullptr;
- return cached_metadata_;
-}
-
-String ServiceWorkerScriptCachedMetadataHandler::Encoding() const {
- return g_empty_string;
-}
-
-bool ServiceWorkerScriptCachedMetadataHandler::IsServedFromCacheStorage()
- const {
- return false;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_script_cached_metadata_handler.h b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_script_cached_metadata_handler.h
deleted file mode 100644
index fc5b010e67a..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_script_cached_metadata_handler.h
+++ /dev/null
@@ -1,53 +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_MODULES_SERVICEWORKERS_SERVICE_WORKER_SCRIPT_CACHED_METADATA_HANDLER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_SCRIPT_CACHED_METADATA_HANDLER_H_
-
-#include <stdint.h>
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h"
-#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-class WorkerGlobalScope;
-class CachedMetadata;
-
-class ServiceWorkerScriptCachedMetadataHandler
- : public SingleCachedMetadataHandler {
- public:
- static ServiceWorkerScriptCachedMetadataHandler* Create(
- WorkerGlobalScope* worker_global_scope,
- const KURL& script_url,
- const Vector<char>* meta_data) {
- return new ServiceWorkerScriptCachedMetadataHandler(worker_global_scope,
- script_url, meta_data);
- }
- ~ServiceWorkerScriptCachedMetadataHandler() override;
- void Trace(blink::Visitor*) override;
- void SetCachedMetadata(uint32_t data_type_id,
- const char*,
- size_t,
- CacheType) override;
- void ClearCachedMetadata(CacheType) override;
- scoped_refptr<CachedMetadata> GetCachedMetadata(
- uint32_t data_type_id) const override;
- String Encoding() const override;
- bool IsServedFromCacheStorage() const override;
-
- private:
- ServiceWorkerScriptCachedMetadataHandler(WorkerGlobalScope*,
- const KURL& script_url,
- const Vector<char>* meta_data);
-
- Member<WorkerGlobalScope> worker_global_scope_;
- KURL script_url_;
- scoped_refptr<CachedMetadata> cached_metadata_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_SCRIPT_CACHED_METADATA_HANDLER_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_thread.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_thread.cc
deleted file mode 100644
index 92444694f19..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_thread.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * 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/modules/serviceworkers/service_worker_thread.h"
-
-#include <memory>
-
-#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
-#include "third_party/blink/renderer/core/workers/worker_backing_thread.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_proxy.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_installed_scripts_manager.h"
-
-namespace blink {
-
-ServiceWorkerThread::ServiceWorkerThread(
- ThreadableLoadingContext* loading_context,
- ServiceWorkerGlobalScopeProxy* global_scope_proxy,
- std::unique_ptr<ServiceWorkerInstalledScriptsManager>
- installed_scripts_manager,
- mojom::blink::CacheStoragePtrInfo cache_storage_info)
- : WorkerThread(loading_context, *global_scope_proxy),
- global_scope_proxy_(global_scope_proxy),
- worker_backing_thread_(WorkerBackingThread::Create(
- WebThreadCreationParams(GetThreadType()))),
- installed_scripts_manager_(std::move(installed_scripts_manager)),
- cache_storage_info_(std::move(cache_storage_info)) {}
-
-ServiceWorkerThread::~ServiceWorkerThread() {
- global_scope_proxy_->Detach();
-}
-
-void ServiceWorkerThread::ClearWorkerBackingThread() {
- worker_backing_thread_ = nullptr;
-}
-
-InstalledScriptsManager* ServiceWorkerThread::GetInstalledScriptsManager() {
- return installed_scripts_manager_.get();
-}
-
-void ServiceWorkerThread::TerminateForTesting() {
- global_scope_proxy_->TerminateWorkerContext();
- WorkerThread::TerminateForTesting();
-}
-
-WorkerOrWorkletGlobalScope* ServiceWorkerThread::CreateWorkerGlobalScope(
- std::unique_ptr<GlobalScopeCreationParams> creation_params) {
- return ServiceWorkerGlobalScope::Create(this, std::move(creation_params),
- std::move(cache_storage_info_),
- time_origin_);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_thread.h b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_thread.h
deleted file mode 100644
index 8838c7870b4..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_thread.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * 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_MODULES_SERVICEWORKERS_SERVICE_WORKER_THREAD_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_THREAD_H_
-
-#include <memory>
-#include "third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom-blink.h"
-#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
-#include "third_party/blink/renderer/core/workers/worker_thread.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-
-namespace blink {
-
-class ServiceWorkerGlobalScopeProxy;
-class ServiceWorkerInstalledScriptsManager;
-struct GlobalScopeCreationParams;
-
-// ServiceWorkerThread is an implementation of WorkerThread for service workers.
-// This provides a backing thread and an installed scripts manager.
-class MODULES_EXPORT ServiceWorkerThread final : public WorkerThread {
- public:
- // ServiceWorkerThread owns a given ServiceWorkerGlobalScopeProxy via
- // Persistent.
- ServiceWorkerThread(ThreadableLoadingContext*,
- ServiceWorkerGlobalScopeProxy*,
- std::unique_ptr<ServiceWorkerInstalledScriptsManager>,
- mojom::blink::CacheStoragePtrInfo cache_storage_info);
- ~ServiceWorkerThread() override;
-
- WorkerBackingThread& GetWorkerBackingThread() override {
- return *worker_backing_thread_;
- }
- void ClearWorkerBackingThread() override;
- InstalledScriptsManager* GetInstalledScriptsManager() override;
- void TerminateForTesting() override;
-
- private:
- WorkerOrWorkletGlobalScope* CreateWorkerGlobalScope(
- std::unique_ptr<GlobalScopeCreationParams>) override;
-
- WebThreadType GetThreadType() const override {
- return WebThreadType::kServiceWorkerThread;
- }
-
- Persistent<ServiceWorkerGlobalScopeProxy> global_scope_proxy_;
- std::unique_ptr<WorkerBackingThread> worker_backing_thread_;
- std::unique_ptr<ServiceWorkerInstalledScriptsManager>
- installed_scripts_manager_;
- mojom::blink::CacheStoragePtrInfo cache_storage_info_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_THREAD_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_window_client.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_window_client.cc
deleted file mode 100644
index b48a638f02b..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_window_client.cc
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_window_client.h"
-
-#include <memory>
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/page/page_visibility_state.h"
-#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
-#include "third_party/blink/renderer/core/workers/worker_location.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_error.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_window_client_callback.h"
-#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
-
-namespace blink {
-
-ServiceWorkerWindowClient* ServiceWorkerWindowClient::Take(
- ScriptPromiseResolver*,
- std::unique_ptr<WebServiceWorkerClientInfo> web_client) {
- return web_client ? ServiceWorkerWindowClient::Create(*web_client) : nullptr;
-}
-
-ServiceWorkerWindowClient* ServiceWorkerWindowClient::Create(
- const WebServiceWorkerClientInfo& info) {
- return new ServiceWorkerWindowClient(info);
-}
-
-ServiceWorkerWindowClient::ServiceWorkerWindowClient(
- const WebServiceWorkerClientInfo& info)
- : ServiceWorkerClient(info),
- page_visibility_state_(info.page_visibility_state),
- is_focused_(info.is_focused) {}
-
-ServiceWorkerWindowClient::~ServiceWorkerWindowClient() = default;
-
-String ServiceWorkerWindowClient::visibilityState() const {
- return PageVisibilityStateString(page_visibility_state_);
-}
-
-ScriptPromise ServiceWorkerWindowClient::focus(ScriptState* script_state) {
- ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- ScriptPromise promise = resolver->Promise();
-
- if (!ExecutionContext::From(script_state)->IsWindowInteractionAllowed()) {
- resolver->Reject(DOMException::Create(kInvalidAccessError,
- "Not allowed to focus a window."));
- return promise;
- }
- ExecutionContext::From(script_state)->ConsumeWindowInteraction();
-
- ServiceWorkerGlobalScopeClient::From(ExecutionContext::From(script_state))
- ->Focus(Uuid(),
- std::make_unique<CallbackPromiseAdapter<ServiceWorkerWindowClient,
- ServiceWorkerError>>(
- resolver));
- return promise;
-}
-
-ScriptPromise ServiceWorkerWindowClient::navigate(ScriptState* script_state,
- const String& url) {
- ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
- ScriptPromise promise = resolver->Promise();
- ExecutionContext* context = ExecutionContext::From(script_state);
-
- KURL parsed_url = KURL(ToWorkerGlobalScope(context)->location()->Url(), url);
- if (!parsed_url.IsValid() || parsed_url.ProtocolIsAbout()) {
- resolver->Reject(V8ThrowException::CreateTypeError(
- script_state->GetIsolate(), "'" + url + "' is not a valid URL."));
- return promise;
- }
- if (!context->GetSecurityOrigin()->CanDisplay(parsed_url)) {
- resolver->Reject(V8ThrowException::CreateTypeError(
- script_state->GetIsolate(),
- "'" + parsed_url.ElidedString() + "' cannot navigate."));
- return promise;
- }
-
- ServiceWorkerGlobalScopeClient::From(context)->Navigate(
- Uuid(), parsed_url, std::make_unique<NavigateClientCallback>(resolver));
- return promise;
-}
-
-void ServiceWorkerWindowClient::Trace(blink::Visitor* visitor) {
- ServiceWorkerClient::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_window_client.h b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_window_client.h
deleted file mode 100644
index 5af56af7f3a..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_window_client.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_WINDOW_CLIENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_WINDOW_CLIENT_H_
-
-#include <memory>
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_client.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
-
-namespace blink {
-
-class ScriptPromiseResolver;
-class ScriptState;
-
-class MODULES_EXPORT ServiceWorkerWindowClient final
- : public ServiceWorkerClient {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- // To be used by CallbackPromiseAdapter.
- using WebType = std::unique_ptr<WebServiceWorkerClientInfo>;
-
- static ServiceWorkerWindowClient* Take(
- ScriptPromiseResolver*,
- std::unique_ptr<WebServiceWorkerClientInfo>);
-
- static ServiceWorkerWindowClient* Create(const WebServiceWorkerClientInfo&);
- ~ServiceWorkerWindowClient() override;
-
- // WindowClient.idl
- String visibilityState() const;
- bool focused() const { return is_focused_; }
- ScriptPromise focus(ScriptState*);
- ScriptPromise navigate(ScriptState*, const String& url);
-
- void Trace(blink::Visitor*) override;
-
- private:
- explicit ServiceWorkerWindowClient(const WebServiceWorkerClientInfo&);
-
- mojom::PageVisibilityState page_visibility_state_;
- bool is_focused_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_WINDOW_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_window_client_callback.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_window_client_callback.cc
deleted file mode 100644
index 2534bcedc62..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_window_client_callback.cc
+++ /dev/null
@@ -1,43 +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/modules/serviceworkers/service_worker_window_client_callback.h"
-
-#include <memory>
-
-#include "base/memory/ptr_util.h"
-#include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_error.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_window_client.h"
-#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
-
-namespace blink {
-
-void NavigateClientCallback::OnSuccess(
- std::unique_ptr<WebServiceWorkerClientInfo> client_info) {
- if (!resolver_->GetExecutionContext() ||
- resolver_->GetExecutionContext()->IsContextDestroyed())
- return;
- resolver_->Resolve(ServiceWorkerWindowClient::Take(
- resolver_.Get(), base::WrapUnique(client_info.release())));
-}
-
-void NavigateClientCallback::OnError(const WebServiceWorkerError& error) {
- if (!resolver_->GetExecutionContext() ||
- resolver_->GetExecutionContext()->IsContextDestroyed())
- return;
-
- if (error.error_type == mojom::blink::ServiceWorkerErrorType::kNavigation) {
- ScriptState::Scope scope(resolver_->GetScriptState());
- resolver_->Reject(V8ThrowException::CreateTypeError(
- resolver_->GetScriptState()->GetIsolate(), error.message));
- return;
- }
-
- resolver_->Reject(ServiceWorkerError::Take(resolver_.Get(), error));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_window_client_callback.h b/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_window_client_callback.h
deleted file mode 100644
index cf630b227ff..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/service_worker_window_client_callback.h
+++ /dev/null
@@ -1,30 +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_MODULES_SERVICEWORKERS_SERVICE_WORKER_WINDOW_CLIENT_CALLBACK_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_WINDOW_CLIENT_CALLBACK_H_
-
-#include "base/macros.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_clients_info.h"
-
-namespace blink {
-
-class ScriptPromiseResolver;
-
-class NavigateClientCallback : public WebServiceWorkerClientCallbacks {
- public:
- explicit NavigateClientCallback(ScriptPromiseResolver* resolver)
- : resolver_(resolver) {}
-
- void OnSuccess(std::unique_ptr<WebServiceWorkerClientInfo>) override;
- void OnError(const WebServiceWorkerError&) override;
-
- private:
- Persistent<ScriptPromiseResolver> resolver_;
- DISALLOW_COPY_AND_ASSIGN(NavigateClientCallback);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_SERVICE_WORKER_WINDOW_CLIENT_CALLBACK_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/testing/internals_service_worker.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/testing/internals_service_worker.cc
deleted file mode 100644
index 57221abb96e..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/testing/internals_service_worker.cc
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/serviceworkers/testing/internals_service_worker.h"
-
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker.h"
-
-namespace blink {
-
-ScriptPromise InternalsServiceWorker::terminateServiceWorker(
- ScriptState* script_state,
- Internals& internals,
- ServiceWorker* worker) {
- return worker->InternalsTerminate(script_state);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/testing/internals_service_worker.h b/chromium/third_party/blink/renderer/modules/serviceworkers/testing/internals_service_worker.h
deleted file mode 100644
index 524d2b163a6..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/testing/internals_service_worker.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_TESTING_INTERNALS_SERVICE_WORKER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_TESTING_INTERNALS_SERVICE_WORKER_H_
-
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class Internals;
-class ScriptState;
-class ServiceWorker;
-
-class InternalsServiceWorker {
- STATIC_ONLY(InternalsServiceWorker);
-
- public:
- static ScriptPromise terminateServiceWorker(ScriptState*,
- Internals&,
- ServiceWorker*);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_TESTING_INTERNALS_SERVICE_WORKER_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/wait_until_observer.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/wait_until_observer.cc
deleted file mode 100644
index 28d48f76eef..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/wait_until_observer.cc
+++ /dev/null
@@ -1,327 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/serviceworkers/wait_until_observer.h"
-
-#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom-blink.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope.h"
-#include "third_party/blink/renderer/platform/bindings/microtask.h"
-#include "third_party/blink/renderer/platform/layout_test_support.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "v8/include/v8.h"
-
-namespace blink {
-
-namespace {
-
-// Timeout before a service worker that was given window interaction
-// permission loses them. The unit is seconds.
-const unsigned kWindowInteractionTimeout = 10;
-const unsigned kWindowInteractionTimeoutForTest = 1;
-
-unsigned WindowInteractionTimeout() {
- return LayoutTestSupport::IsRunningLayoutTest()
- ? kWindowInteractionTimeoutForTest
- : kWindowInteractionTimeout;
-}
-
-} // anonymous namespace
-
-class WaitUntilObserver::ThenFunction final : public ScriptFunction {
- public:
- enum ResolveType {
- kFulfilled,
- kRejected,
- };
-
- static v8::Local<v8::Function> CreateFunction(
- ScriptState* script_state,
- WaitUntilObserver* observer,
- ResolveType type,
- PromiseSettledCallback callback) {
- ThenFunction* self =
- new ThenFunction(script_state, observer, type, std::move(callback));
- return self->BindToV8Function();
- }
-
- void Trace(blink::Visitor* visitor) override {
- visitor->Trace(observer_);
- ScriptFunction::Trace(visitor);
- }
-
- private:
- ThenFunction(ScriptState* script_state,
- WaitUntilObserver* observer,
- ResolveType type,
- PromiseSettledCallback callback)
- : ScriptFunction(script_state),
- observer_(observer),
- resolve_type_(type),
- callback_(std::move(callback)) {}
-
- ScriptValue Call(ScriptValue value) override {
- DCHECK(observer_);
- DCHECK(resolve_type_ == kFulfilled || resolve_type_ == kRejected);
- if (callback_)
- callback_.Run(value);
- // According from step 4 of ExtendableEvent::waitUntil() in spec:
- // https://w3c.github.io/ServiceWorker/#dom-extendableevent-waituntil
- // "Upon fulfillment or rejection of f, queue a microtask to run these
- // substeps: Decrement the pending promises count by one."
-
- // At this time point the microtask A running resolve/reject function of
- // this promise has already been queued, in order to allow microtask A to
- // call waitUntil, we enqueue another microtask B to delay the promise
- // settled notification to |observer_|, thus A will run before B so A can
- // call waitUntil well, but any other microtask C possibly enqueued by A
- // will run after B so C maybe can't call waitUntil if there has no any
- // extend lifetime promise at that time.
- if (resolve_type_ == kRejected) {
- Microtask::EnqueueMicrotask(
- WTF::Bind(&WaitUntilObserver::OnPromiseRejected,
- WrapPersistent(observer_.Get())));
- value =
- ScriptPromise::Reject(value.GetScriptState(), value).GetScriptValue();
- } else {
- Microtask::EnqueueMicrotask(
- WTF::Bind(&WaitUntilObserver::OnPromiseFulfilled,
- WrapPersistent(observer_.Get())));
- }
- observer_ = nullptr;
- return value;
- }
-
- Member<WaitUntilObserver> observer_;
- ResolveType resolve_type_;
- PromiseSettledCallback callback_;
-};
-
-WaitUntilObserver* WaitUntilObserver::Create(ExecutionContext* context,
- EventType type,
- int event_id) {
- return new WaitUntilObserver(context, type, event_id);
-}
-
-void WaitUntilObserver::WillDispatchEvent() {
- event_dispatch_time_ = WTF::CurrentTime();
- // When handling a notificationclick or paymentrequest event, we want to
- // allow one window to be focused or opened. These calls are allowed between
- // the call to willDispatchEvent() and the last call to
- // DecrementPendingPromiseCount(). If waitUntil() isn't called, that means
- // between willDispatchEvent() and didDispatchEvent().
- if (type_ == kNotificationClick || type_ == kPaymentRequest)
- execution_context_->AllowWindowInteraction();
-
- DCHECK_EQ(EventDispatchState::kInitial, event_dispatch_state_);
- event_dispatch_state_ = EventDispatchState::kDispatching;
-}
-
-void WaitUntilObserver::DidDispatchEvent(bool event_dispatch_failed) {
- event_dispatch_state_ = event_dispatch_failed
- ? EventDispatchState::kFailed
- : EventDispatchState::kDispatched;
- MaybeCompleteEvent();
-}
-
-void WaitUntilObserver::WaitUntil(ScriptState* script_state,
- ScriptPromise script_promise,
- ExceptionState& exception_state,
- PromiseSettledCallback on_promise_fulfilled,
- PromiseSettledCallback on_promise_rejected) {
- if (pending_promises_ == 0) {
- switch (event_dispatch_state_) {
- case EventDispatchState::kInitial:
- NOTREACHED();
- return;
- case EventDispatchState::kDispatching:
- if (!v8::MicrotasksScope::IsRunningMicrotasks(
- script_state->GetIsolate())) {
- break;
- }
- // didDispatchEvent() is called after both the event handler
- // execution finished and microtasks queued by the event handler execution
- // finished, it's hard to get the precise time point between the 2
- // execution phases.
- // So even in EventDispatchState::kDispatching state at this time point,
- // running microtask indicates that event handler execution has actually
- // finished, in such case if there aren't any outstanding extend lifetime
- // promises, we should throw here.
- FALLTHROUGH;
- case EventDispatchState::kDispatched:
- case EventDispatchState::kFailed:
- exception_state.ThrowDOMException(
- kInvalidStateError,
- "The event handler is already finished "
- "and no extend lifetime promises are "
- "outstanding.");
- return;
- }
- }
-
- if (!execution_context_)
- return;
-
- // When handling a notificationclick event, we want to allow one window to
- // be focused or opened. See comments in ::willDispatchEvent(). When
- // waitUntil() is being used, opening or closing a window must happen in a
- // timeframe specified by windowInteractionTimeout(), otherwise the calls
- // will fail.
- if (type_ == kNotificationClick) {
- consume_window_interaction_timer_.StartOneShot(WindowInteractionTimeout(),
- FROM_HERE);
- }
-
- IncrementPendingPromiseCount();
- script_promise.Then(
- ThenFunction::CreateFunction(script_state, this, ThenFunction::kFulfilled,
- std::move(on_promise_fulfilled)),
- ThenFunction::CreateFunction(script_state, this, ThenFunction::kRejected,
- std::move(on_promise_rejected)));
-}
-
-WaitUntilObserver::WaitUntilObserver(ExecutionContext* context,
- EventType type,
- int event_id)
- : execution_context_(context),
- type_(type),
- event_id_(event_id),
- consume_window_interaction_timer_(
- Platform::Current()->CurrentThread()->GetTaskRunner(),
- this,
- &WaitUntilObserver::ConsumeWindowInteraction) {}
-
-void WaitUntilObserver::OnPromiseFulfilled() {
- DecrementPendingPromiseCount();
-}
-
-void WaitUntilObserver::OnPromiseRejected() {
- has_rejected_promise_ = true;
- DecrementPendingPromiseCount();
-}
-
-void WaitUntilObserver::IncrementPendingPromiseCount() {
- ++pending_promises_;
-}
-
-void WaitUntilObserver::DecrementPendingPromiseCount() {
- DCHECK_GT(pending_promises_, 0);
- --pending_promises_;
- MaybeCompleteEvent();
-}
-
-void WaitUntilObserver::MaybeCompleteEvent() {
- if (!execution_context_)
- return;
-
- switch (event_dispatch_state_) {
- case EventDispatchState::kInitial:
- NOTREACHED();
- return;
- case EventDispatchState::kDispatching:
- // Still dispatching, do not complete the event.
- return;
- case EventDispatchState::kDispatched:
- // Still waiting for a promise, do not complete the event.
- if (pending_promises_ != 0)
- return;
- // Dispatch finished and there are no pending promises, complete the
- // event.
- break;
- case EventDispatchState::kFailed:
- // Dispatch had some error, complete the event immediatelly.
- break;
- }
-
- ServiceWorkerGlobalScopeClient* client =
- ServiceWorkerGlobalScopeClient::From(execution_context_);
- mojom::ServiceWorkerEventStatus status =
- (event_dispatch_state_ == EventDispatchState::kFailed ||
- has_rejected_promise_)
- ? mojom::ServiceWorkerEventStatus::REJECTED
- : mojom::ServiceWorkerEventStatus::COMPLETED;
- switch (type_) {
- case kAbortPayment:
- client->DidHandleAbortPaymentEvent(event_id_, status,
- event_dispatch_time_);
- break;
- case kActivate:
- client->DidHandleActivateEvent(event_id_, status, event_dispatch_time_);
- break;
- case kCanMakePayment:
- client->DidHandleCanMakePaymentEvent(event_id_, status,
- event_dispatch_time_);
- break;
- case kCookieChange:
- client->DidHandleCookieChangeEvent(event_id_, status,
- event_dispatch_time_);
- break;
- case kFetch:
- client->DidHandleFetchEvent(event_id_, status, event_dispatch_time_);
- break;
- case kInstall:
- ToServiceWorkerGlobalScope(execution_context_)->SetIsInstalling(false);
- client->DidHandleInstallEvent(event_id_, status, event_dispatch_time_);
- break;
- case kMessage:
- client->DidHandleExtendableMessageEvent(event_id_, status,
- event_dispatch_time_);
- break;
- case kNotificationClick:
- client->DidHandleNotificationClickEvent(event_id_, status,
- event_dispatch_time_);
- consume_window_interaction_timer_.Stop();
- ConsumeWindowInteraction(nullptr);
- break;
- case kNotificationClose:
- client->DidHandleNotificationCloseEvent(event_id_, status,
- event_dispatch_time_);
- break;
- case kPush:
- client->DidHandlePushEvent(event_id_, status, event_dispatch_time_);
- break;
- case kSync:
- client->DidHandleSyncEvent(event_id_, status, event_dispatch_time_);
- break;
- case kPaymentRequest:
- client->DidHandlePaymentRequestEvent(event_id_, status,
- event_dispatch_time_);
- break;
- case kBackgroundFetchAbort:
- client->DidHandleBackgroundFetchAbortEvent(event_id_, status,
- event_dispatch_time_);
- break;
- case kBackgroundFetchClick:
- client->DidHandleBackgroundFetchClickEvent(event_id_, status,
- event_dispatch_time_);
- break;
- case kBackgroundFetchFail:
- client->DidHandleBackgroundFetchFailEvent(event_id_, status,
- event_dispatch_time_);
- break;
- case kBackgroundFetched:
- client->DidHandleBackgroundFetchedEvent(event_id_, status,
- event_dispatch_time_);
- break;
- }
- execution_context_ = nullptr;
-}
-
-void WaitUntilObserver::ConsumeWindowInteraction(TimerBase*) {
- if (!execution_context_)
- return;
- execution_context_->ConsumeWindowInteraction();
-}
-
-void WaitUntilObserver::Trace(blink::Visitor* visitor) {
- visitor->Trace(execution_context_);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/wait_until_observer.h b/chromium/third_party/blink/renderer/modules/serviceworkers/wait_until_observer.h
deleted file mode 100644
index b1ef6e68d26..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/wait_until_observer.h
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_WAIT_UNTIL_OBSERVER_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_WAIT_UNTIL_OBSERVER_H_
-
-#include "base/callback.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/modules/serviceworkers/service_worker_global_scope_client.h"
-#include "third_party/blink/renderer/platform/timer.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
-
-namespace blink {
-
-class ExceptionState;
-class ExecutionContext;
-class ScriptPromise;
-class ScriptState;
-
-// Created for each ExtendableEvent instance.
-class MODULES_EXPORT WaitUntilObserver final
- : public GarbageCollectedFinalized<WaitUntilObserver> {
- public:
- using PromiseSettledCallback =
- base::RepeatingCallback<void(const ScriptValue&)>;
-
- enum EventType {
- kAbortPayment,
- kActivate,
- kCanMakePayment,
- kCookieChange,
- kFetch,
- kInstall,
- kMessage,
- kNotificationClick,
- kNotificationClose,
- kPaymentRequest,
- kPush,
- kSync,
- kBackgroundFetchAbort,
- kBackgroundFetchClick,
- kBackgroundFetchFail,
- kBackgroundFetched
- };
-
- static WaitUntilObserver* Create(ExecutionContext*, EventType, int event_id);
-
- // Must be called before dispatching the event.
- void WillDispatchEvent();
- // Must be called after dispatching the event. If |event_dispatch_failed| is
- // true, then DidDispatchEvent() immediately reports to
- // ServiceWorkerGlobalScopeClient that the event finished, without waiting for
- // all waitUntil promises to settle.
- void DidDispatchEvent(bool event_dispatch_failed);
-
- // Observes the promise and delays reporting to ServiceWorkerGlobalScopeClient
- // that the event completed until the given promise is resolved or rejected.
- // WaitUntil may be called multiple times. The event is extended until all
- // promises have settled.
- // If provided, |on_promise_fulfilled| or |on_promise_rejected| is invoked
- // once |script_promise| fulfills or rejects. This enables the caller to do
- // custom handling.
- void WaitUntil(
- ScriptState*,
- ScriptPromise /* script_promise */,
- ExceptionState&,
- PromiseSettledCallback on_promise_fulfilled = PromiseSettledCallback(),
- PromiseSettledCallback on_promise_rejected = PromiseSettledCallback());
-
- virtual void Trace(blink::Visitor*);
-
- private:
- friend class InternalsServiceWorker;
- class ThenFunction;
-
- enum class EventDispatchState {
- // Event dispatch has not yet started.
- kInitial,
- // Event dispatch has started but not yet finished.
- kDispatching,
- // Event dispatch completed. There may still be outstanding waitUntil
- // promises that must settle before notifying ServiceWorkerGlobalScopeClient
- // that the event finished.
- kDispatched,
- // Event dispatch failed. Any outstanding waitUntil promises are ignored.
- kFailed
- };
-
- WaitUntilObserver(ExecutionContext*, EventType, int event_id);
-
- void IncrementPendingPromiseCount();
- void DecrementPendingPromiseCount();
-
- // Enqueued as a microtask when a promise passed to a waitUntil() call that is
- // associated with this observer was fulfilled.
- void OnPromiseFulfilled();
- // Enqueued as a microtask when a promise passed to a waitUntil() call that is
- // associated with this observer was rejected.
- void OnPromiseRejected();
-
- void ConsumeWindowInteraction(TimerBase*);
-
- void MaybeCompleteEvent();
-
- Member<ExecutionContext> execution_context_;
- EventType type_;
- int event_id_;
- int pending_promises_ = 0;
- EventDispatchState event_dispatch_state_ = EventDispatchState::kInitial;
- bool has_rejected_promise_ = false;
- double event_dispatch_time_ = 0;
- TaskRunnerTimer<WaitUntilObserver> consume_window_interaction_timer_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SERVICEWORKERS_WAIT_UNTIL_OBSERVER_H_
diff --git a/chromium/third_party/blink/renderer/modules/serviceworkers/web_embedded_worker_impl_test.cc b/chromium/third_party/blink/renderer/modules/serviceworkers/web_embedded_worker_impl_test.cc
deleted file mode 100644
index bd1a89d5bf3..00000000000
--- a/chromium/third_party/blink/renderer/modules/serviceworkers/web_embedded_worker_impl_test.cc
+++ /dev/null
@@ -1,366 +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/public/web/web_embedded_worker.h"
-
-#include <memory>
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/message_port/message_port_channel.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_installed_scripts_manager.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_network_provider.h"
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_provider.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/web_content_settings_client.h"
-#include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
-#include "third_party/blink/public/platform/web_url_response.h"
-#include "third_party/blink/public/web/modules/serviceworker/web_service_worker_context_client.h"
-#include "third_party/blink/public/web/modules/serviceworker/web_service_worker_context_proxy.h"
-#include "third_party/blink/public/web/web_embedded_worker_start_data.h"
-#include "third_party/blink/public/web/web_settings.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.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/waitable_event.h"
-
-namespace blink {
-namespace {
-
-class MockServiceWorkerContextClient : public WebServiceWorkerContextClient {
- public:
- MockServiceWorkerContextClient() = default;
- ~MockServiceWorkerContextClient() override = default;
-
- MOCK_METHOD0(WorkerReadyForInspection, void());
- MOCK_METHOD0(WorkerContextFailedToStart, void());
- MOCK_METHOD0(WorkerScriptLoaded, void());
-
- void WorkerContextStarted(WebServiceWorkerContextProxy* proxy) override {
- // In production code, ReadyToEvaluateScript() is called when
- // ServiceWorkerContextClient receives the InitializeGlobalScope() IPC
- // message.
- proxy->ReadyToEvaluateScript();
- }
- void DidEvaluateClassicScript(bool /* success */) override {
- script_evaluated_event_.Signal();
- }
-
- // Work-around for mocking a method that return unique_ptr.
- MOCK_METHOD0(CreateServiceWorkerNetworkProviderProxy,
- WebServiceWorkerNetworkProvider*());
- MOCK_METHOD0(CreateServiceWorkerProviderProxy, WebServiceWorkerProvider*());
- std::unique_ptr<WebServiceWorkerNetworkProvider>
- CreateServiceWorkerNetworkProvider() override {
- return std::unique_ptr<WebServiceWorkerNetworkProvider>(
- CreateServiceWorkerNetworkProviderProxy());
- }
- std::unique_ptr<WebServiceWorkerProvider> CreateServiceWorkerProvider()
- override {
- return std::unique_ptr<WebServiceWorkerProvider>(
- CreateServiceWorkerProviderProxy());
- }
- void GetClient(const WebString&,
- std::unique_ptr<WebServiceWorkerClientCallbacks>) override {
- NOTREACHED();
- }
- void GetClients(const WebServiceWorkerClientQueryOptions&,
- std::unique_ptr<WebServiceWorkerClientsCallbacks>) override {
- NOTREACHED();
- }
- void OpenNewTab(const WebURL&,
- std::unique_ptr<WebServiceWorkerClientCallbacks>) override {
- NOTREACHED();
- }
- void OpenPaymentHandlerWindow(
- const WebURL&,
- std::unique_ptr<WebServiceWorkerClientCallbacks>) override {
- NOTREACHED();
- }
- void PostMessageToClient(const WebString& uuid,
- TransferableMessage) override {
- NOTREACHED();
- }
- void SkipWaiting(
- std::unique_ptr<WebServiceWorkerSkipWaitingCallbacks>) override {
- NOTREACHED();
- }
- void Claim(std::unique_ptr<WebServiceWorkerClientsClaimCallbacks>) override {
- NOTREACHED();
- }
- void Focus(const WebString& uuid,
- std::unique_ptr<WebServiceWorkerClientCallbacks>) override {
- NOTREACHED();
- }
- void Navigate(const WebString& uuid,
- const WebURL&,
- std::unique_ptr<WebServiceWorkerClientCallbacks>) override {
- NOTREACHED();
- }
- void WorkerContextDestroyed() override { termination_event_.Signal(); }
-
- void WaitUntilScriptEvaluated() { script_evaluated_event_.Wait(); }
- void WaitUntilThreadTermination() { termination_event_.Wait(); }
-
- private:
- WaitableEvent script_evaluated_event_;
- WaitableEvent termination_event_;
-};
-
-class MockServiceWorkerInstalledScriptsManager
- : public WebServiceWorkerInstalledScriptsManager {
- public:
- MOCK_CONST_METHOD1(IsScriptInstalled, bool(const WebURL& script_url));
- MOCK_METHOD1(GetRawScriptData,
- std::unique_ptr<RawScriptData>(const WebURL& script_url));
-};
-
-class WebEmbeddedWorkerImplTest : public testing::Test {
- protected:
- void SetUp() override {
- auto client = std::make_unique<MockServiceWorkerContextClient>();
- auto installed_scripts_manager =
- std::make_unique<MockServiceWorkerInstalledScriptsManager>();
- mock_client_ = client.get();
- mock_installed_scripts_manager_ = installed_scripts_manager.get();
- worker_ = WebEmbeddedWorker::Create(
- std::move(client), std::move(installed_scripts_manager),
- mojo::ScopedMessagePipeHandle(), mojo::ScopedMessagePipeHandle(),
- mojo::ScopedMessagePipeHandle());
-
- WebURL script_url = URLTestHelpers::ToKURL("https://www.example.com/sw.js");
- WebURLResponse response;
- response.SetMIMEType("text/javascript");
- response.SetHTTPStatusCode(200);
- Platform::Current()->GetURLLoaderMockFactory()->RegisterURL(script_url,
- response, "");
-
- start_data_.script_url = script_url;
- start_data_.user_agent = WebString("dummy user agent");
- start_data_.pause_after_download_mode =
- WebEmbeddedWorkerStartData::kDontPauseAfterDownload;
- start_data_.wait_for_debugger_mode =
- WebEmbeddedWorkerStartData::kDontWaitForDebugger;
- start_data_.v8_cache_options = WebSettings::kV8CacheOptionsDefault;
- }
-
- void TearDown() override {
- Platform::Current()
- ->GetURLLoaderMockFactory()
- ->UnregisterAllURLsAndClearMemoryCache();
- }
-
- WebEmbeddedWorkerStartData start_data_;
- MockServiceWorkerContextClient* mock_client_;
- MockServiceWorkerInstalledScriptsManager* mock_installed_scripts_manager_;
- std::unique_ptr<WebEmbeddedWorker> worker_;
-};
-
-} // namespace
-
-TEST_F(WebEmbeddedWorkerImplTest, TerminateSoonAfterStart) {
- EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
- worker_->StartWorkerContext(start_data_);
- testing::Mock::VerifyAndClearExpectations(mock_client_);
-
- EXPECT_CALL(*mock_client_, WorkerContextFailedToStart()).Times(1);
- worker_->TerminateWorkerContext();
- testing::Mock::VerifyAndClearExpectations(mock_client_);
-}
-
-TEST_F(WebEmbeddedWorkerImplTest, TerminateWhileWaitingForDebugger) {
- EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
- start_data_.wait_for_debugger_mode =
- WebEmbeddedWorkerStartData::kWaitForDebugger;
- worker_->StartWorkerContext(start_data_);
- testing::Mock::VerifyAndClearExpectations(mock_client_);
-
- EXPECT_CALL(*mock_client_, WorkerContextFailedToStart()).Times(1);
- worker_->TerminateWorkerContext();
- testing::Mock::VerifyAndClearExpectations(mock_client_);
-}
-
-TEST_F(WebEmbeddedWorkerImplTest, TerminateWhileLoadingScript) {
- EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
- worker_->StartWorkerContext(start_data_);
- testing::Mock::VerifyAndClearExpectations(mock_client_);
-
- // Load the shadow page.
- EXPECT_CALL(*mock_client_, CreateServiceWorkerNetworkProviderProxy())
- .WillOnce(testing::Return(nullptr));
- EXPECT_CALL(*mock_installed_scripts_manager_,
- IsScriptInstalled(start_data_.script_url))
- .Times(testing::AtLeast(1))
- .WillRepeatedly(testing::Return(false));
- Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
- testing::Mock::VerifyAndClearExpectations(mock_client_);
- testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
-
- // Terminate before loading the script.
- EXPECT_CALL(*mock_client_, WorkerContextFailedToStart()).Times(1);
- worker_->TerminateWorkerContext();
- testing::Mock::VerifyAndClearExpectations(mock_client_);
-}
-
-TEST_F(WebEmbeddedWorkerImplTest, TerminateWhilePausedAfterDownload) {
- EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
- start_data_.pause_after_download_mode =
- WebEmbeddedWorkerStartData::kPauseAfterDownload;
- worker_->StartWorkerContext(start_data_);
- testing::Mock::VerifyAndClearExpectations(mock_client_);
-
- // Load the shadow page.
- EXPECT_CALL(*mock_client_, CreateServiceWorkerNetworkProviderProxy())
- .WillOnce(testing::Return(nullptr));
- EXPECT_CALL(*mock_installed_scripts_manager_,
- IsScriptInstalled(start_data_.script_url))
- .Times(testing::AtLeast(1))
- .WillRepeatedly(testing::Return(false));
-
- Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
- testing::Mock::VerifyAndClearExpectations(mock_client_);
- testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
-
- // Load the script.
- EXPECT_CALL(*mock_client_, WorkerScriptLoaded()).Times(1);
- EXPECT_CALL(*mock_client_, CreateServiceWorkerProviderProxy()).Times(0);
- Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
- testing::Mock::VerifyAndClearExpectations(mock_client_);
-
- // Terminate before resuming after download.
- EXPECT_CALL(*mock_client_, CreateServiceWorkerProviderProxy()).Times(0);
- EXPECT_CALL(*mock_client_, WorkerContextFailedToStart()).Times(1);
- worker_->TerminateWorkerContext();
- testing::Mock::VerifyAndClearExpectations(mock_client_);
-}
-
-TEST_F(WebEmbeddedWorkerImplTest, ScriptNotFound) {
- WebURL script_url =
- URLTestHelpers::ToKURL("https://www.example.com/sw-404.js");
- WebURLResponse response;
- response.SetMIMEType("text/javascript");
- response.SetHTTPStatusCode(404);
- ResourceError error = ResourceError::Failure(script_url);
- Platform::Current()->GetURLLoaderMockFactory()->RegisterErrorURL(
- script_url, response, error);
- start_data_.script_url = script_url;
-
- EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
- worker_->StartWorkerContext(start_data_);
- testing::Mock::VerifyAndClearExpectations(mock_client_);
-
- // Load the shadow page.
- EXPECT_CALL(*mock_client_, CreateServiceWorkerNetworkProviderProxy())
- .WillOnce(testing::Return(nullptr));
- EXPECT_CALL(*mock_installed_scripts_manager_,
- IsScriptInstalled(start_data_.script_url))
- .Times(testing::AtLeast(1))
- .WillRepeatedly(testing::Return(false));
-
- Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
- testing::Mock::VerifyAndClearExpectations(mock_client_);
- testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
-
- // Load the script.
- EXPECT_CALL(*mock_client_, WorkerScriptLoaded()).Times(0);
- EXPECT_CALL(*mock_client_, CreateServiceWorkerProviderProxy()).Times(0);
- EXPECT_CALL(*mock_client_, WorkerContextFailedToStart()).Times(1);
- Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
- testing::Mock::VerifyAndClearExpectations(mock_client_);
-}
-
-// The running worker is detected as a memory leak. crbug.com/586897 and
-// crbug.com/807754.
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_DontPauseAfterDownload DISABLED_DontPauseAfterDownload
-#else
-#define MAYBE_DontPauseAfterDownload DontPauseAfterDownload
-#endif
-TEST_F(WebEmbeddedWorkerImplTest, MAYBE_DontPauseAfterDownload) {
- EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
- worker_->StartWorkerContext(start_data_);
- testing::Mock::VerifyAndClearExpectations(mock_client_);
-
- // Load the shadow page.
- EXPECT_CALL(*mock_client_, CreateServiceWorkerNetworkProviderProxy())
- .WillOnce(testing::Return(nullptr));
- EXPECT_CALL(*mock_installed_scripts_manager_,
- IsScriptInstalled(start_data_.script_url))
- .Times(testing::AtLeast(1))
- .WillRepeatedly(testing::Return(false));
- Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
- testing::Mock::VerifyAndClearExpectations(mock_client_);
- testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
-
- // Load the script.
- EXPECT_CALL(*mock_client_, WorkerScriptLoaded()).Times(1);
- EXPECT_CALL(*mock_client_, CreateServiceWorkerProviderProxy())
- .WillOnce(testing::Return(nullptr));
- // This is called on the worker thread.
- EXPECT_CALL(*mock_installed_scripts_manager_,
- IsScriptInstalled(start_data_.script_url))
- .Times(testing::AtLeast(1))
- .WillRepeatedly(testing::Return(false));
- Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
- mock_client_->WaitUntilScriptEvaluated();
- testing::Mock::VerifyAndClearExpectations(mock_client_);
- testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
-
- // Terminate the running worker thread.
- EXPECT_CALL(*mock_client_, WorkerContextFailedToStart()).Times(0);
- worker_->TerminateWorkerContext();
- mock_client_->WaitUntilThreadTermination();
-}
-
-// The running worker is detected as a memory leak. crbug.com/586897 and
-// crbug.com/807754.
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_PauseAfterDownload DISABLED_PauseAfterDownload
-#else
-#define MAYBE_PauseAfterDownload PauseAfterDownload
-#endif
-TEST_F(WebEmbeddedWorkerImplTest, MAYBE_PauseAfterDownload) {
- EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
- start_data_.pause_after_download_mode =
- WebEmbeddedWorkerStartData::kPauseAfterDownload;
- worker_->StartWorkerContext(start_data_);
- testing::Mock::VerifyAndClearExpectations(mock_client_);
-
- // Load the shadow page.
- EXPECT_CALL(*mock_client_, CreateServiceWorkerNetworkProviderProxy())
- .WillOnce(testing::Return(nullptr));
- EXPECT_CALL(*mock_installed_scripts_manager_,
- IsScriptInstalled(start_data_.script_url))
- .Times(testing::AtLeast(1))
- .WillRepeatedly(testing::Return(false));
- Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
- testing::Mock::VerifyAndClearExpectations(mock_client_);
- testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
-
- // Load the script.
- EXPECT_CALL(*mock_client_, WorkerScriptLoaded()).Times(1);
- EXPECT_CALL(*mock_client_, CreateServiceWorkerProviderProxy()).Times(0);
- Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
- testing::Mock::VerifyAndClearExpectations(mock_client_);
-
- // Resume after download.
- EXPECT_CALL(*mock_client_, CreateServiceWorkerProviderProxy())
- .WillOnce(testing::Return(nullptr));
- // This is called on the worker thread.
- EXPECT_CALL(*mock_installed_scripts_manager_,
- IsScriptInstalled(start_data_.script_url))
- .Times(testing::AtLeast(1))
- .WillRepeatedly(testing::Return(false));
- worker_->ResumeAfterDownload();
- mock_client_->WaitUntilScriptEvaluated();
- testing::Mock::VerifyAndClearExpectations(mock_client_);
- testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
-
- // Terminate the running worker thread.
- EXPECT_CALL(*mock_client_, WorkerContextFailedToStart()).Times(0);
- worker_->TerminateWorkerContext();
- mock_client_->WaitUntilThreadTermination();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.cc b/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.cc
index dce477794e5..2ee1c2eccca 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.cc
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/barcode_detector.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/modules/shapedetection/barcode_detector.h"
#include "services/service_manager/public/cpp/interface_provider.h"
+#include "services/shape_detection/public/mojom/barcodedetection_provider.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/geometry/dom_rect.h"
@@ -20,10 +21,14 @@ BarcodeDetector* BarcodeDetector::Create(ExecutionContext* context) {
}
BarcodeDetector::BarcodeDetector(ExecutionContext* context) : ShapeDetector() {
- auto request = mojo::MakeRequest(&barcode_service_);
+ shape_detection::mojom::blink::BarcodeDetectionProviderPtr provider;
+ auto request = mojo::MakeRequest(&provider);
if (auto* interface_provider = context->GetInterfaceProvider()) {
interface_provider->GetInterface(std::move(request));
}
+ provider->CreateBarcodeDetection(
+ mojo::MakeRequest(&barcode_service_),
+ shape_detection::mojom::blink::BarcodeDetectorOptions::New());
barcode_service_.set_connection_error_handler(
WTF::Bind(&BarcodeDetector::OnBarcodeServiceConnectionError,
@@ -34,8 +39,9 @@ ScriptPromise BarcodeDetector::DoDetect(ScriptPromiseResolver* resolver,
SkBitmap bitmap) {
ScriptPromise promise = resolver->Promise();
if (!barcode_service_) {
- resolver->Reject(DOMException::Create(
- kNotSupportedError, "Barcode detection service unavailable."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "Barcode detection service unavailable."));
return promise;
}
barcode_service_requests_.insert(resolver);
@@ -64,9 +70,9 @@ void BarcodeDetector::OnDetectBarcodes(
}
detected_barcodes.push_back(DetectedBarcode::Create(
barcode->raw_value,
- DOMRect::Create(barcode->bounding_box.x, barcode->bounding_box.y,
- barcode->bounding_box.width,
- barcode->bounding_box.height),
+ DOMRectReadOnly::Create(
+ barcode->bounding_box.x, barcode->bounding_box.y,
+ barcode->bounding_box.width, barcode->bounding_box.height),
corner_points));
}
@@ -75,7 +81,7 @@ void BarcodeDetector::OnDetectBarcodes(
void BarcodeDetector::OnBarcodeServiceConnectionError() {
for (const auto& request : barcode_service_requests_) {
- request->Reject(DOMException::Create(kNotSupportedError,
+ request->Reject(DOMException::Create(DOMExceptionCode::kNotSupportedError,
"Barcode Detection not implemented."));
}
barcode_service_requests_.clear();
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.cc b/chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.cc
index 5da23bd47f6..402e2f647cc 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.cc
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.cc
@@ -10,12 +10,12 @@ namespace blink {
DetectedBarcode* DetectedBarcode::Create() {
HeapVector<Point2D> empty_list;
- return new DetectedBarcode(g_empty_string, DOMRect::Create(0, 0, 0, 0),
- empty_list);
+ return new DetectedBarcode(g_empty_string,
+ DOMRectReadOnly::Create(0, 0, 0, 0), empty_list);
}
DetectedBarcode* DetectedBarcode::Create(String raw_value,
- DOMRect* bounding_box,
+ DOMRectReadOnly* bounding_box,
HeapVector<Point2D> corner_points) {
return new DetectedBarcode(raw_value, bounding_box, corner_points);
}
@@ -24,7 +24,7 @@ const String& DetectedBarcode::rawValue() const {
return raw_value_;
}
-DOMRect* DetectedBarcode::boundingBox() const {
+DOMRectReadOnly* DetectedBarcode::boundingBox() const {
return bounding_box_.Get();
}
@@ -33,7 +33,7 @@ const HeapVector<Point2D>& DetectedBarcode::cornerPoints() const {
}
DetectedBarcode::DetectedBarcode(String raw_value,
- DOMRect* bounding_box,
+ DOMRectReadOnly* bounding_box,
HeapVector<Point2D> corner_points)
: raw_value_(raw_value),
bounding_box_(bounding_box),
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.h b/chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.h
index 18e4575c67c..69dcfd9ddde 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.h
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.h
@@ -12,25 +12,25 @@
namespace blink {
-class DOMRect;
+class DOMRectReadOnly;
class MODULES_EXPORT DetectedBarcode final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
static DetectedBarcode* Create();
- static DetectedBarcode* Create(String, DOMRect*, HeapVector<Point2D>);
+ static DetectedBarcode* Create(String, DOMRectReadOnly*, HeapVector<Point2D>);
const String& rawValue() const;
- DOMRect* boundingBox() const;
+ DOMRectReadOnly* boundingBox() const;
const HeapVector<Point2D>& cornerPoints() const;
void Trace(blink::Visitor*) override;
private:
- DetectedBarcode(String, DOMRect*, HeapVector<Point2D>);
+ DetectedBarcode(String, DOMRectReadOnly*, HeapVector<Point2D>);
const String raw_value_;
- const Member<DOMRect> bounding_box_;
+ const Member<DOMRectReadOnly> bounding_box_;
const HeapVector<Point2D> corner_points_;
};
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.idl b/chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.idl
index 6bd2f7b537f..56951d2c1cd 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.idl
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/detected_barcode.idl
@@ -10,7 +10,7 @@
] interface DetectedBarcode {
// TODO(mcasas): Implement missing fields. https://crbug.com/646083
[SameObject] readonly attribute DOMString rawValue;
- [SameObject] readonly attribute DOMRect boundingBox;
+ [SameObject] readonly attribute DOMRectReadOnly boundingBox;
// 4 corner points in clockwise direction starting with top-left. Due to
// possible perspective distortions, this is not necessarily a rectangle.
[SameObject, SaveSameObject] readonly attribute FrozenArray<Point2D> cornerPoints;
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/detected_face.cc b/chromium/third_party/blink/renderer/modules/shapedetection/detected_face.cc
index bbea8e3d055..00863ffbbb7 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/detected_face.cc
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/detected_face.cc
@@ -5,24 +5,23 @@
#include "third_party/blink/renderer/modules/shapedetection/detected_face.h"
#include "third_party/blink/renderer/core/geometry/dom_rect.h"
-#include "third_party/blink/renderer/modules/shapedetection/landmark.h"
namespace blink {
DetectedFace* DetectedFace::Create() {
- return new DetectedFace(DOMRect::Create());
+ return new DetectedFace(DOMRectReadOnly::Create(0, 0, 0, 0));
}
-DetectedFace* DetectedFace::Create(DOMRect* bounding_box) {
+DetectedFace* DetectedFace::Create(DOMRectReadOnly* bounding_box) {
return new DetectedFace(bounding_box);
}
-DetectedFace* DetectedFace::Create(DOMRect* bounding_box,
+DetectedFace* DetectedFace::Create(DOMRectReadOnly* bounding_box,
const HeapVector<Landmark>& landmarks) {
return new DetectedFace(bounding_box, landmarks);
}
-DOMRect* DetectedFace::boundingBox() const {
+DOMRectReadOnly* DetectedFace::boundingBox() const {
return bounding_box_.Get();
}
@@ -30,10 +29,10 @@ const HeapVector<Landmark>& DetectedFace::landmarks() const {
return landmarks_;
}
-DetectedFace::DetectedFace(DOMRect* bounding_box)
+DetectedFace::DetectedFace(DOMRectReadOnly* bounding_box)
: bounding_box_(bounding_box) {}
-DetectedFace::DetectedFace(DOMRect* bounding_box,
+DetectedFace::DetectedFace(DOMRectReadOnly* bounding_box,
const HeapVector<Landmark>& landmarks)
: bounding_box_(bounding_box), landmarks_(landmarks) {}
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/detected_face.h b/chromium/third_party/blink/renderer/modules/shapedetection/detected_face.h
index e2a86775501..0e5268aa2de 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/detected_face.h
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/detected_face.h
@@ -6,31 +6,31 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SHAPEDETECTION_DETECTED_FACE_H_
#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/modules/shapedetection/landmark.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
namespace blink {
-class DOMRect;
-class Landmark;
+class DOMRectReadOnly;
class MODULES_EXPORT DetectedFace final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
static DetectedFace* Create();
- static DetectedFace* Create(DOMRect*);
- static DetectedFace* Create(DOMRect*, const HeapVector<Landmark>&);
+ static DetectedFace* Create(DOMRectReadOnly*);
+ static DetectedFace* Create(DOMRectReadOnly*, const HeapVector<Landmark>&);
- DOMRect* boundingBox() const;
+ DOMRectReadOnly* boundingBox() const;
const HeapVector<Landmark>& landmarks() const;
void Trace(blink::Visitor*) override;
private:
- explicit DetectedFace(DOMRect*);
- DetectedFace(DOMRect*, const HeapVector<Landmark>&);
+ explicit DetectedFace(DOMRectReadOnly*);
+ DetectedFace(DOMRectReadOnly*, const HeapVector<Landmark>&);
- const Member<DOMRect> bounding_box_;
+ const Member<DOMRectReadOnly> bounding_box_;
const HeapVector<Landmark> landmarks_;
};
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/detected_face.idl b/chromium/third_party/blink/renderer/modules/shapedetection/detected_face.idl
index fe8dba26ac1..d07c2972ffe 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/detected_face.idl
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/detected_face.idl
@@ -9,6 +9,6 @@
RuntimeEnabled=ShapeDetection
] interface DetectedFace {
// TODO(xianglu): Implement any other fields. https://crbug.com/646083
- [SameObject] readonly attribute DOMRect boundingBox;
+ [SameObject] readonly attribute DOMRectReadOnly boundingBox;
[SameObject, SaveSameObject] readonly attribute FrozenArray<Landmark> landmarks;
};
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/detected_text.cc b/chromium/third_party/blink/renderer/modules/shapedetection/detected_text.cc
index 92cd9b820fd..7240b5c502c 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/detected_text.cc
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/detected_text.cc
@@ -10,11 +10,12 @@ namespace blink {
DetectedText* DetectedText::Create() {
HeapVector<Point2D> empty_list;
- return new DetectedText(g_empty_string, DOMRect::Create(), empty_list);
+ return new DetectedText(g_empty_string, DOMRectReadOnly::Create(0, 0, 0, 0),
+ empty_list);
}
DetectedText* DetectedText::Create(String raw_value,
- DOMRect* bounding_box,
+ DOMRectReadOnly* bounding_box,
HeapVector<Point2D> corner_points) {
return new DetectedText(raw_value, bounding_box, corner_points);
}
@@ -23,7 +24,7 @@ const String& DetectedText::rawValue() const {
return raw_value_;
}
-DOMRect* DetectedText::boundingBox() const {
+DOMRectReadOnly* DetectedText::boundingBox() const {
return bounding_box_.Get();
}
@@ -32,7 +33,7 @@ const HeapVector<Point2D>& DetectedText::cornerPoints() const {
}
DetectedText::DetectedText(String raw_value,
- DOMRect* bounding_box,
+ DOMRectReadOnly* bounding_box,
HeapVector<Point2D> corner_points)
: raw_value_(raw_value),
bounding_box_(bounding_box),
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/detected_text.h b/chromium/third_party/blink/renderer/modules/shapedetection/detected_text.h
index d94064dbc6b..342072d3e57 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/detected_text.h
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/detected_text.h
@@ -12,25 +12,25 @@
namespace blink {
-class DOMRect;
+class DOMRectReadOnly;
class MODULES_EXPORT DetectedText final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
static DetectedText* Create();
- static DetectedText* Create(String, DOMRect*, HeapVector<Point2D>);
+ static DetectedText* Create(String, DOMRectReadOnly*, HeapVector<Point2D>);
const String& rawValue() const;
- DOMRect* boundingBox() const;
+ DOMRectReadOnly* boundingBox() const;
const HeapVector<Point2D>& cornerPoints() const;
void Trace(blink::Visitor*) override;
private:
- DetectedText(String, DOMRect*, HeapVector<Point2D>);
+ DetectedText(String, DOMRectReadOnly*, HeapVector<Point2D>);
const String raw_value_;
- const Member<DOMRect> bounding_box_;
+ const Member<DOMRectReadOnly> bounding_box_;
const HeapVector<Point2D> corner_points_;
};
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/detected_text.idl b/chromium/third_party/blink/renderer/modules/shapedetection/detected_text.idl
index 059dcd2d8a6..ec0a22a7bea 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/detected_text.idl
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/detected_text.idl
@@ -9,7 +9,7 @@
RuntimeEnabled=ShapeDetection
] interface DetectedText {
[SameObject] readonly attribute DOMString rawValue;
- [SameObject] readonly attribute DOMRect boundingBox;
+ [SameObject] readonly attribute DOMRectReadOnly boundingBox;
// 4 corner points in clockwise direction starting with top-left. Due to
// possible perspective distortions, this is not necessarily a rectangle.
[SameObject] readonly attribute FrozenArray<Point2D> cornerPoints;
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/face_detector.cc b/chromium/third_party/blink/renderer/modules/shapedetection/face_detector.cc
index e702c47f481..991dea9d475 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/face_detector.cc
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/face_detector.cc
@@ -50,8 +50,9 @@ ScriptPromise FaceDetector::DoDetect(ScriptPromiseResolver* resolver,
SkBitmap bitmap) {
ScriptPromise promise = resolver->Promise();
if (!face_service_) {
- resolver->Reject(DOMException::Create(
- kNotSupportedError, "Face detection service unavailable."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "Face detection service unavailable."));
return promise;
}
face_service_requests_.insert(resolver);
@@ -88,8 +89,9 @@ void FaceDetector::OnDetectFaces(
}
detected_faces.push_back(DetectedFace::Create(
- DOMRect::Create(face->bounding_box.x, face->bounding_box.y,
- face->bounding_box.width, face->bounding_box.height),
+ DOMRectReadOnly::Create(face->bounding_box.x, face->bounding_box.y,
+ face->bounding_box.width,
+ face->bounding_box.height),
landmarks));
}
@@ -98,7 +100,7 @@ void FaceDetector::OnDetectFaces(
void FaceDetector::OnFaceServiceConnectionError() {
for (const auto& request : face_service_requests_) {
- request->Reject(DOMException::Create(kNotSupportedError,
+ request->Reject(DOMException::Create(DOMExceptionCode::kNotSupportedError,
"Face Detection not implemented."));
}
face_service_requests_.clear();
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/shape_detector.cc b/chromium/third_party/blink/renderer/modules/shapedetection/shape_detector.cc
index 32f9b185b08..d05cc4af604 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/shape_detector.cc
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/shape_detector.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/shapedetection/shape_detector.h"
+#include "base/numerics/checked_math.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/execution_context/execution_context.h"
@@ -15,7 +16,6 @@
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/core/SkImageInfo.h"
@@ -44,15 +44,15 @@ ScriptPromise ShapeDetector::detect(
canvas_image_source = image_source.GetAsOffscreenCanvas();
} else {
NOTREACHED() << "Unsupported CanvasImageSource";
- resolver->Reject(
- DOMException::Create(kNotSupportedError, "Unsupported source."));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "Unsupported source."));
return promise;
}
if (canvas_image_source->WouldTaintOrigin(
ExecutionContext::From(script_state)->GetSecurityOrigin())) {
- resolver->Reject(
- DOMException::Create(kSecurityError, "Source would taint origin."));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kSecurityError,
+ "Source would taint origin."));
return promise;
}
@@ -72,8 +72,8 @@ ScriptPromise ShapeDetector::detect(
scoped_refptr<Image> image = canvas_image_source->GetSourceImageForCanvas(
&source_image_status, kPreferNoAcceleration, size);
if (!image || source_image_status != kNormalSourceImageStatus) {
- resolver->Reject(
- DOMException::Create(kInvalidStateError, "Invalid element or state."));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Invalid element or state."));
return promise;
}
if (size.IsEmpty()) {
@@ -91,8 +91,9 @@ ScriptPromise ShapeDetector::detect(
if (!sk_image->asLegacyBitmap(&sk_bitmap)) {
// TODO(mcasas): retrieve the pixels from elsewhere.
NOTREACHED();
- resolver->Reject(DOMException::Create(
- kInvalidStateError, "Failed to get pixels for current frame."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Failed to get pixels for current frame."));
return promise;
}
@@ -114,12 +115,13 @@ ScriptPromise ShapeDetector::DetectShapesOnImageData(
SkImageInfo::Make(image_data->width(), image_data->height(),
kN32_SkColorType, kOpaque_SkAlphaType),
image_data->width() * 4 /* bytes per pixel */)) {
- resolver->Reject(DOMException::Create(
- kInvalidStateError, "Failed to allocate pixels for current frame."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Failed to allocate pixels for current frame."));
return promise;
}
- WTF::CheckedNumeric<int> allocation_size = image_data->Size().Area() * 4;
+ base::CheckedNumeric<int> allocation_size = image_data->Size().Area() * 4;
CHECK_EQ(allocation_size.ValueOrDefault(0), sk_bitmap.computeByteSize());
memcpy(sk_bitmap.getPixels(), image_data->data()->Data(),
@@ -140,15 +142,17 @@ ScriptPromise ShapeDetector::DetectShapesOnImageElement(
ImageResourceContent* const image_resource = img->CachedImage();
if (!image_resource || image_resource->ErrorOccurred()) {
- resolver->Reject(DOMException::Create(
- kInvalidStateError, "Failed to load or decode HTMLImageElement."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Failed to load or decode HTMLImageElement."));
return promise;
}
Image* const blink_image = image_resource->GetImage();
if (!blink_image) {
- resolver->Reject(DOMException::Create(
- kInvalidStateError, "Failed to get image from resource."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Failed to get image from resource."));
return promise;
}
@@ -160,8 +164,9 @@ ScriptPromise ShapeDetector::DetectShapesOnImageElement(
SkBitmap sk_bitmap;
if (!sk_image || !sk_image->asLegacyBitmap(&sk_bitmap)) {
- resolver->Reject(DOMException::Create(
- kInvalidStateError, "Failed to get image from current frame."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Failed to get image from current frame."));
return promise;
}
diff --git a/chromium/third_party/blink/renderer/modules/shapedetection/text_detector.cc b/chromium/third_party/blink/renderer/modules/shapedetection/text_detector.cc
index f018a15d7f2..9dc25067788 100644
--- a/chromium/third_party/blink/renderer/modules/shapedetection/text_detector.cc
+++ b/chromium/third_party/blink/renderer/modules/shapedetection/text_detector.cc
@@ -33,8 +33,9 @@ ScriptPromise TextDetector::DoDetect(ScriptPromiseResolver* resolver,
SkBitmap bitmap) {
ScriptPromise promise = resolver->Promise();
if (!text_service_) {
- resolver->Reject(DOMException::Create(
- kNotSupportedError, "Text detection service unavailable."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "Text detection service unavailable."));
return promise;
}
text_service_requests_.insert(resolver);
@@ -63,8 +64,9 @@ void TextDetector::OnDetectText(
}
detected_text.push_back(DetectedText::Create(
text->raw_value,
- DOMRect::Create(text->bounding_box.x, text->bounding_box.y,
- text->bounding_box.width, text->bounding_box.height),
+ DOMRectReadOnly::Create(text->bounding_box.x, text->bounding_box.y,
+ text->bounding_box.width,
+ text->bounding_box.height),
corner_points));
}
@@ -73,7 +75,7 @@ void TextDetector::OnDetectText(
void TextDetector::OnTextServiceConnectionError() {
for (const auto& request : text_service_requests_) {
- request->Reject(DOMException::Create(kNotSupportedError,
+ request->Reject(DOMException::Create(DOMExceptionCode::kNotSupportedError,
"Text Detection not implemented."));
}
text_service_requests_.clear();
diff --git a/chromium/third_party/blink/renderer/modules/speech/BUILD.gn b/chromium/third_party/blink/renderer/modules/speech/BUILD.gn
index f9f8f458500..df1bbde0c12 100644
--- a/chromium/third_party/blink/renderer/modules/speech/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/speech/BUILD.gn
@@ -18,8 +18,6 @@ blink_modules_sources("speech") {
"speech_recognition_alternative.cc",
"speech_recognition_alternative.h",
"speech_recognition_client.h",
- "speech_recognition_client_proxy.cc",
- "speech_recognition_client_proxy.h",
"speech_recognition_controller.cc",
"speech_recognition_controller.h",
"speech_recognition_error.cc",
diff --git a/chromium/third_party/blink/renderer/modules/speech/DEPS b/chromium/third_party/blink/renderer/modules/speech/DEPS
index f26ccc26d7c..04e6d625efe 100644
--- a/chromium/third_party/blink/renderer/modules/speech/DEPS
+++ b/chromium/third_party/blink/renderer/modules/speech/DEPS
@@ -5,4 +5,5 @@ include_rules = [
"+third_party/blink/renderer/modules/modules_export.h",
"+third_party/blink/renderer/modules/mediastream",
"+third_party/blink/renderer/modules/speech",
+ "+mojo/public/cpp/bindings/binding.h"
]
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_grammar_list.idl b/chromium/third_party/blink/renderer/modules/speech/speech_grammar_list.idl
index 85a60d4586a..51bae98d2e3 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_grammar_list.idl
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_grammar_list.idl
@@ -31,6 +31,6 @@
] interface SpeechGrammarList {
readonly attribute unsigned long length;
getter SpeechGrammar item(unsigned long index);
- [CallWith=ScriptState] void addFromUri(DOMString src, optional float weight);
+ [CallWith=ScriptState, Measure] void addFromUri(DOMString src, optional float weight);
void addFromString(DOMString string, optional float weight);
};
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_recognition.cc b/chromium/third_party/blink/renderer/modules/speech/speech_recognition.cc
index 4da52f0a5a1..2394ae84e3b 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_recognition.cc
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_recognition.cc
@@ -25,13 +25,14 @@
#include "third_party/blink/renderer/modules/speech/speech_recognition.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include <algorithm>
+#include "build/build_config.h"
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/modules/speech/speech_recognition_controller.h"
#include "third_party/blink/renderer/modules/speech/speech_recognition_error.h"
#include "third_party/blink/renderer/modules/speech/speech_recognition_event.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -48,13 +49,24 @@ void SpeechRecognition::start(ExceptionState& exception_state) {
return;
if (started_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"recognition has already started.");
return;
}
final_results_.clear();
- controller_->Start(this, grammars_, lang_, continuous_, interim_results_,
+
+ mojom::blink::SpeechRecognitionSessionClientPtrInfo session_client;
+ binding_.Bind(mojo::MakeRequest(&session_client),
+ GetExecutionContext()->GetInterfaceInvalidator());
+ binding_.set_connection_error_handler(WTF::Bind(
+ &SpeechRecognition::OnConnectionError, WrapWeakPersistent(this)));
+
+ mojom::blink::SpeechRecognitionSessionRequest session_request =
+ MakeRequest(&session_, GetExecutionContext()->GetInterfaceInvalidator());
+
+ controller_->Start(std::move(session_request), std::move(session_client),
+ *grammars_, lang_, continuous_, interim_results_,
max_alternatives_);
started_ = true;
}
@@ -65,7 +77,7 @@ void SpeechRecognition::stopFunction() {
if (started_ && !stopping_) {
stopping_ = true;
- controller_->Stop(this);
+ session_->StopCapture();
}
}
@@ -75,70 +87,92 @@ void SpeechRecognition::abort() {
if (started_ && !stopping_) {
stopping_ = true;
- controller_->Abort(this);
+ session_->Abort();
}
}
-void SpeechRecognition::DidStartAudio() {
- DispatchEvent(Event::Create(EventTypeNames::audiostart));
+void SpeechRecognition::ResultRetrieved(
+ WTF::Vector<mojom::blink::SpeechRecognitionResultPtr> results) {
+ auto* it = std::stable_partition(
+ results.begin(), results.end(),
+ [](const auto& result) { return !result->is_provisional; });
+ size_t provisional_count = results.end() - it;
+
+ // Add the new results to the previous final results.
+ HeapVector<Member<SpeechRecognitionResult>> aggregated_results =
+ std::move(final_results_);
+ aggregated_results.ReserveCapacity(aggregated_results.size() +
+ results.size());
+
+ for (const auto& result : results) {
+ HeapVector<Member<SpeechRecognitionAlternative>> alternatives;
+ alternatives.ReserveInitialCapacity(result->hypotheses.size());
+ for (const auto& hypothesis : result->hypotheses) {
+ alternatives.push_back(SpeechRecognitionAlternative::Create(
+ hypothesis->utterance, hypothesis->confidence));
+ }
+ aggregated_results.push_back(SpeechRecognitionResult::Create(
+ std::move(alternatives), !result->is_provisional));
+ }
+
+ // |aggregated_results| now contains the following (in the given order):
+ //
+ // (1) previous final results from |final_results_|
+ // (2) new final results from |results|
+ // (3) new provisional results from |results|
+
+ // |final_results_| = (1) + (2).
+ HeapVector<Member<SpeechRecognitionResult>> new_final_results;
+ new_final_results.ReserveInitialCapacity(aggregated_results.size() -
+ provisional_count);
+ new_final_results.AppendRange(aggregated_results.begin(),
+ aggregated_results.end() - provisional_count);
+ final_results_ = std::move(new_final_results);
+
+ // We dispatch an event with (1) + (2) + (3).
+ DispatchEvent(SpeechRecognitionEvent::CreateResult(
+ aggregated_results.size() - results.size(),
+ std::move(aggregated_results)));
+}
+
+void SpeechRecognition::ErrorOccurred(
+ mojom::blink::SpeechRecognitionErrorPtr error) {
+ if (error->code == mojom::blink::SpeechRecognitionErrorCode::kNoMatch) {
+ DispatchEvent(SpeechRecognitionEvent::CreateNoMatch(nullptr));
+ } else {
+ // TODO(primiano): message?
+ DispatchEvent(SpeechRecognitionError::Create(error->code, String()));
+ }
}
-void SpeechRecognition::DidStartSound() {
- DispatchEvent(Event::Create(EventTypeNames::soundstart));
+void SpeechRecognition::Started() {
+ DispatchEvent(Event::Create(EventTypeNames::start));
}
-void SpeechRecognition::DidStartSpeech() {
- DispatchEvent(Event::Create(EventTypeNames::speechstart));
+void SpeechRecognition::AudioStarted() {
+ DispatchEvent(Event::Create(EventTypeNames::audiostart));
}
-void SpeechRecognition::DidEndSpeech() {
- DispatchEvent(Event::Create(EventTypeNames::speechend));
+void SpeechRecognition::SoundStarted() {
+ DispatchEvent(Event::Create(EventTypeNames::soundstart));
+ DispatchEvent(Event::Create(EventTypeNames::speechstart));
}
-void SpeechRecognition::DidEndSound() {
+void SpeechRecognition::SoundEnded() {
+ DispatchEvent(Event::Create(EventTypeNames::speechend));
DispatchEvent(Event::Create(EventTypeNames::soundend));
}
-void SpeechRecognition::DidEndAudio() {
+void SpeechRecognition::AudioEnded() {
DispatchEvent(Event::Create(EventTypeNames::audioend));
}
-void SpeechRecognition::DidReceiveResults(
- const HeapVector<Member<SpeechRecognitionResult>>& new_final_results,
- const HeapVector<Member<SpeechRecognitionResult>>&
- current_interim_results) {
- size_t result_index = final_results_.size();
-
- for (size_t i = 0; i < new_final_results.size(); ++i)
- final_results_.push_back(new_final_results[i]);
-
- HeapVector<Member<SpeechRecognitionResult>> results = final_results_;
- for (size_t i = 0; i < current_interim_results.size(); ++i)
- results.push_back(current_interim_results[i]);
-
- DispatchEvent(SpeechRecognitionEvent::CreateResult(result_index, results));
-}
-
-void SpeechRecognition::DidReceiveNoMatch(SpeechRecognitionResult* result) {
- DispatchEvent(SpeechRecognitionEvent::CreateNoMatch(result));
-}
-
-void SpeechRecognition::DidReceiveError(SpeechRecognitionError* error) {
- DispatchEvent(error);
- started_ = false;
-}
-
-void SpeechRecognition::DidStart() {
- DispatchEvent(Event::Create(EventTypeNames::start));
-}
-
-void SpeechRecognition::DidEnd() {
+void SpeechRecognition::Ended() {
started_ = false;
stopping_ = false;
- // If m_controller is null, this is being aborted from the ExecutionContext
- // being detached, so don't dispatch an event.
- if (controller_)
- DispatchEvent(Event::Create(EventTypeNames::end));
+ session_.reset();
+ binding_.Close();
+ DispatchEvent(Event::Create(EventTypeNames::end));
}
const AtomicString& SpeechRecognition::InterfaceName() const {
@@ -151,17 +185,30 @@ ExecutionContext* SpeechRecognition::GetExecutionContext() const {
void SpeechRecognition::ContextDestroyed(ExecutionContext*) {
controller_ = nullptr;
- if (HasPendingActivity())
- abort();
}
bool SpeechRecognition::HasPendingActivity() const {
return started_;
}
+void SpeechRecognition::PageVisibilityChanged() {
+#if defined(OS_ANDROID)
+ if (!GetPage()->IsPageVisible())
+ abort();
+#endif
+}
+
+void SpeechRecognition::OnConnectionError() {
+ ErrorOccurred(mojom::blink::SpeechRecognitionError::New(
+ mojom::blink::SpeechRecognitionErrorCode::kNetwork,
+ mojom::blink::SpeechAudioErrorDetails::kNone));
+ Ended();
+}
+
SpeechRecognition::SpeechRecognition(LocalFrame* frame,
ExecutionContext* context)
: ContextLifecycleObserver(context),
+ PageVisibilityObserver(frame ? frame->GetPage() : nullptr),
grammars_(SpeechGrammarList::Create()), // FIXME: The spec is not clear
// on the default value for the
// grammars attribute.
@@ -170,9 +217,8 @@ SpeechRecognition::SpeechRecognition(LocalFrame* frame,
max_alternatives_(1),
controller_(SpeechRecognitionController::From(frame)),
started_(false),
- stopping_(false) {
- // FIXME: Need to hook up to get notified when the visibility changes.
-}
+ stopping_(false),
+ binding_(this) {}
SpeechRecognition::~SpeechRecognition() = default;
@@ -182,6 +228,7 @@ void SpeechRecognition::Trace(blink::Visitor* visitor) {
visitor->Trace(final_results_);
EventTargetWithInlineData::Trace(visitor);
ContextLifecycleObserver::Trace(visitor);
+ PageVisibilityObserver::Trace(visitor);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_recognition.h b/chromium/third_party/blink/renderer/modules/speech/speech_recognition.h
index da7aafd4de3..b4e08c6ccf8 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_recognition.h
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_recognition.h
@@ -26,14 +26,17 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SPEECH_SPEECH_RECOGNITION_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SPEECH_SPEECH_RECOGNITION_H_
+#include "third_party/blink/public/mojom/speech/speech_recognizer.mojom-blink.h"
#include "third_party/blink/public/platform/web_private_ptr.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
+#include "third_party/blink/renderer/core/page/page_visibility_observer.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/speech/speech_grammar_list.h"
#include "third_party/blink/renderer/modules/speech/speech_recognition_result.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/mojo/revocable_binding.h"
#include "third_party/blink/renderer/platform/wtf/compiler.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -43,12 +46,13 @@ class ExceptionState;
class ExecutionContext;
class LocalFrame;
class SpeechRecognitionController;
-class SpeechRecognitionError;
class MODULES_EXPORT SpeechRecognition final
: public EventTargetWithInlineData,
public ActiveScriptWrappable<SpeechRecognition>,
- public ContextLifecycleObserver {
+ public ContextLifecycleObserver,
+ public mojom::blink::SpeechRecognitionSessionClient,
+ public PageVisibilityObserver {
USING_GARBAGE_COLLECTED_MIXIN(SpeechRecognition);
DEFINE_WRAPPERTYPEINFO();
@@ -78,21 +82,16 @@ class MODULES_EXPORT SpeechRecognition final
void stopFunction();
void abort();
- // Called by the SpeechRecognitionClient.
- void DidStartAudio();
- void DidStartSound();
- void DidStartSpeech();
- void DidEndSpeech();
- void DidEndSound();
- void DidEndAudio();
- void DidReceiveResults(
- const HeapVector<Member<SpeechRecognitionResult>>& new_final_results,
- const HeapVector<Member<SpeechRecognitionResult>>&
- current_interim_results);
- void DidReceiveNoMatch(SpeechRecognitionResult*);
- void DidReceiveError(SpeechRecognitionError*);
- void DidStart();
- void DidEnd();
+ // mojom::blink::SpeechRecognitionSessionClient
+ void ResultRetrieved(
+ WTF::Vector<mojom::blink::SpeechRecognitionResultPtr> results) override;
+ void ErrorOccurred(mojom::blink::SpeechRecognitionErrorPtr error) override;
+ void Started() override;
+ void AudioStarted() override;
+ void SoundStarted() override;
+ void SoundEnded() override;
+ void AudioEnded() override;
+ void Ended() override;
// EventTarget
const AtomicString& InterfaceName() const override;
@@ -104,6 +103,9 @@ class MODULES_EXPORT SpeechRecognition final
// ContextLifecycleObserver
void ContextDestroyed(ExecutionContext*) override;
+ // PageVisibilityObserver
+ void PageVisibilityChanged() override;
+
DEFINE_ATTRIBUTE_EVENT_LISTENER(audiostart);
DEFINE_ATTRIBUTE_EVENT_LISTENER(soundstart);
DEFINE_ATTRIBUTE_EVENT_LISTENER(speechstart);
@@ -121,6 +123,8 @@ class MODULES_EXPORT SpeechRecognition final
private:
SpeechRecognition(LocalFrame*, ExecutionContext*);
+ void OnConnectionError();
+
Member<SpeechGrammarList> grammars_;
String lang_;
bool continuous_;
@@ -131,6 +135,8 @@ class MODULES_EXPORT SpeechRecognition final
bool started_;
bool stopping_;
HeapVector<Member<SpeechRecognitionResult>> final_results_;
+ RevocableBinding<mojom::blink::SpeechRecognitionSessionClient> binding_;
+ mojom::blink::RevocableSpeechRecognitionSessionPtr session_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_client.h b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_client.h
deleted file mode 100644
index eda5bfc8edc..00000000000
--- a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_client.h
+++ /dev/null
@@ -1,61 +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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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_MODULES_SPEECH_SPEECH_RECOGNITION_CLIENT_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SPEECH_SPEECH_RECOGNITION_CLIENT_H_
-
-#include <memory>
-
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-class LocalFrame;
-class SpeechGrammarList;
-class SpeechRecognition;
-
-class SpeechRecognitionClient
- : public GarbageCollectedFinalized<SpeechRecognitionClient> {
- public:
- virtual void Start(SpeechRecognition*,
- const SpeechGrammarList*,
- const String& lang,
- bool continuous,
- bool interim_results,
- unsigned long max_alternatives) = 0;
- virtual void Stop(SpeechRecognition*) = 0;
- virtual void Abort(SpeechRecognition*) = 0;
- virtual void Trace(blink::Visitor*) {}
-
- virtual ~SpeechRecognitionClient() = default;
-};
-
-MODULES_EXPORT void ProvideSpeechRecognitionTo(LocalFrame&,
- SpeechRecognitionClient*);
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SPEECH_SPEECH_RECOGNITION_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_client_proxy.cc b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_client_proxy.cc
deleted file mode 100644
index b92e32aa344..00000000000
--- a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_client_proxy.cc
+++ /dev/null
@@ -1,168 +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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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/modules/speech/speech_recognition_client_proxy.h"
-
-#include <memory>
-
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/public/platform/web_security_origin.h"
-#include "third_party/blink/public/web/web_speech_grammar.h"
-#include "third_party/blink/public/web/web_speech_recognition_handle.h"
-#include "third_party/blink/public/web/web_speech_recognition_params.h"
-#include "third_party/blink/public/web/web_speech_recognition_result.h"
-#include "third_party/blink/public/web/web_speech_recognizer.h"
-#include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/modules/speech/speech_grammar_list.h"
-#include "third_party/blink/renderer/modules/speech/speech_recognition.h"
-#include "third_party/blink/renderer/modules/speech/speech_recognition_error.h"
-#include "third_party/blink/renderer/modules/speech/speech_recognition_result.h"
-#include "third_party/blink/renderer/modules/speech/speech_recognition_result_list.h"
-#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
-
-namespace blink {
-
-SpeechRecognitionClientProxy::~SpeechRecognitionClientProxy() = default;
-
-SpeechRecognitionClientProxy* SpeechRecognitionClientProxy::Create(
- WebSpeechRecognizer* recognizer) {
- return new SpeechRecognitionClientProxy(recognizer);
-}
-
-void SpeechRecognitionClientProxy::Start(SpeechRecognition* recognition,
- const SpeechGrammarList* grammar_list,
- const String& lang,
- bool continuous,
- bool interim_results,
- unsigned long max_alternatives) {
- size_t length =
- grammar_list ? static_cast<size_t>(grammar_list->length()) : 0U;
- WebVector<WebSpeechGrammar> web_speech_grammars(length);
- for (unsigned long i = 0; i < length; ++i)
- web_speech_grammars[i] = grammar_list->item(i);
-
- WebSpeechRecognitionParams params(
- web_speech_grammars, lang, continuous, interim_results, max_alternatives,
- WebSecurityOrigin(
- recognition->GetExecutionContext()->GetSecurityOrigin()));
- recognizer_->Start(recognition, params, WebSpeechRecognizerClient(this));
-}
-
-void SpeechRecognitionClientProxy::Stop(SpeechRecognition* recognition) {
- recognizer_->Stop(recognition, WebSpeechRecognizerClient(this));
-}
-
-void SpeechRecognitionClientProxy::Abort(SpeechRecognition* recognition) {
- recognizer_->Abort(recognition, WebSpeechRecognizerClient(this));
-}
-
-void SpeechRecognitionClientProxy::DidStartAudio(
- const WebSpeechRecognitionHandle& handle) {
- SpeechRecognition* recognition(handle);
- recognition->DidStartAudio();
-}
-
-void SpeechRecognitionClientProxy::DidStartSound(
- const WebSpeechRecognitionHandle& handle) {
- SpeechRecognition* recognition(handle);
- recognition->DidStartSound();
- recognition->DidStartSpeech();
-}
-
-void SpeechRecognitionClientProxy::DidEndSound(
- const WebSpeechRecognitionHandle& handle) {
- SpeechRecognition* recognition(handle);
- recognition->DidEndSpeech();
- recognition->DidEndSound();
-}
-
-void SpeechRecognitionClientProxy::DidEndAudio(
- const WebSpeechRecognitionHandle& handle) {
- SpeechRecognition* recognition(handle);
- recognition->DidEndAudio();
-}
-
-void SpeechRecognitionClientProxy::DidReceiveResults(
- const WebSpeechRecognitionHandle& handle,
- const WebVector<WebSpeechRecognitionResult>& new_final_results,
- const WebVector<WebSpeechRecognitionResult>& current_interim_results) {
- SpeechRecognition* recognition(handle);
-
- HeapVector<Member<SpeechRecognitionResult>> final_results_vector(
- new_final_results.size());
- for (size_t i = 0; i < new_final_results.size(); ++i) {
- final_results_vector[i] =
- Member<SpeechRecognitionResult>(new_final_results[i]);
- }
-
- HeapVector<Member<SpeechRecognitionResult>> interim_results_vector(
- current_interim_results.size());
- for (size_t i = 0; i < current_interim_results.size(); ++i) {
- interim_results_vector[i] =
- Member<SpeechRecognitionResult>(current_interim_results[i]);
- }
-
- recognition->DidReceiveResults(final_results_vector, interim_results_vector);
-}
-
-void SpeechRecognitionClientProxy::DidReceiveNoMatch(
- const WebSpeechRecognitionHandle& handle,
- const WebSpeechRecognitionResult& result) {
- SpeechRecognition* recognition(handle);
- recognition->DidReceiveNoMatch(result);
-}
-
-void SpeechRecognitionClientProxy::DidReceiveError(
- const WebSpeechRecognitionHandle& handle,
- const WebString& message,
- WebSpeechRecognizerClient::ErrorCode code) {
- SpeechRecognition* recognition(handle);
- SpeechRecognitionError::ErrorCode error_code =
- static_cast<SpeechRecognitionError::ErrorCode>(code);
- recognition->DidReceiveError(
- SpeechRecognitionError::Create(error_code, message));
-}
-
-void SpeechRecognitionClientProxy::DidStart(
- const WebSpeechRecognitionHandle& handle) {
- SpeechRecognition* recognition(handle);
- recognition->DidStart();
-}
-
-void SpeechRecognitionClientProxy::DidEnd(
- const WebSpeechRecognitionHandle& handle) {
- SpeechRecognition* recognition(handle);
- recognition->DidEnd();
-}
-
-void SpeechRecognitionClientProxy::Trace(blink::Visitor* visitor) {
- SpeechRecognitionClient::Trace(visitor);
-}
-
-SpeechRecognitionClientProxy::SpeechRecognitionClientProxy(
- WebSpeechRecognizer* recognizer)
- : recognizer_(recognizer) {}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_client_proxy.h b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_client_proxy.h
deleted file mode 100644
index 1fee3a47671..00000000000
--- a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_client_proxy.h
+++ /dev/null
@@ -1,90 +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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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_MODULES_SPEECH_SPEECH_RECOGNITION_CLIENT_PROXY_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_SPEECH_SPEECH_RECOGNITION_CLIENT_PROXY_H_
-
-#include <memory>
-#include "third_party/blink/public/platform/web_vector.h"
-#include "third_party/blink/public/web/web_speech_recognizer_client.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
-#include "third_party/blink/renderer/modules/speech/speech_recognition_client.h"
-#include "third_party/blink/renderer/platform/wtf/compiler.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-class WebSpeechRecognitionHandle;
-class WebSpeechRecognitionResult;
-class WebSpeechRecognizer;
-class WebString;
-
-class MODULES_EXPORT SpeechRecognitionClientProxy final
- : public SpeechRecognitionClient {
- public:
- ~SpeechRecognitionClientProxy() override;
-
- // Constructing a proxy object with a null WebSpeechRecognizer is safe in
- // itself, but attempting to call start/stop/abort on it will crash.
- static SpeechRecognitionClientProxy* Create(WebSpeechRecognizer*);
-
- // SpeechRecognitionClient:
- void Start(SpeechRecognition*,
- const SpeechGrammarList*,
- const String& lang,
- bool continuous,
- bool interim_results,
- unsigned long max_alternatives) override;
- void Stop(SpeechRecognition*) override;
- void Abort(SpeechRecognition*) override;
-
- void DidStartAudio(const WebSpeechRecognitionHandle&);
- void DidStartSound(const WebSpeechRecognitionHandle&);
- void DidEndSound(const WebSpeechRecognitionHandle&);
- void DidEndAudio(const WebSpeechRecognitionHandle&);
- void DidReceiveResults(
- const WebSpeechRecognitionHandle&,
- const WebVector<WebSpeechRecognitionResult>& new_final_results,
- const WebVector<WebSpeechRecognitionResult>& current_interim_results);
- void DidReceiveNoMatch(const WebSpeechRecognitionHandle&,
- const WebSpeechRecognitionResult&);
- void DidReceiveError(const WebSpeechRecognitionHandle&,
- const WebString& message,
- WebSpeechRecognizerClient::ErrorCode);
- void DidStart(const WebSpeechRecognitionHandle&);
- void DidEnd(const WebSpeechRecognitionHandle&);
-
- // Required by garbage collection
- void Trace(blink::Visitor* visitor) override;
-
- private:
- explicit SpeechRecognitionClientProxy(WebSpeechRecognizer*);
-
- WebSpeechRecognizer* recognizer_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SPEECH_SPEECH_RECOGNITION_CLIENT_PROXY_H_
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.cc b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.cc
index bd7656e648c..6bd603d0da6 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.cc
@@ -27,28 +27,66 @@
#include <memory>
+#include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/modules/speech/speech_grammar_list.h"
+#include "third_party/blink/renderer/modules/speech/speech_recognition.h"
+
namespace blink {
const char SpeechRecognitionController::kSupplementName[] =
"SpeechRecognitionController";
-SpeechRecognitionController::SpeechRecognitionController(
- SpeechRecognitionClient* client)
- : client_(client) {}
+SpeechRecognitionController::SpeechRecognitionController(LocalFrame& frame)
+ : Supplement<LocalFrame>(frame) {}
SpeechRecognitionController::~SpeechRecognitionController() {
// FIXME: Call m_client->pageDestroyed(); once we have implemented a client.
}
SpeechRecognitionController* SpeechRecognitionController::Create(
- SpeechRecognitionClient* client) {
- return new SpeechRecognitionController(client);
+ LocalFrame& frame) {
+ return new SpeechRecognitionController(frame);
+}
+
+void SpeechRecognitionController::Start(
+ mojom::blink::SpeechRecognitionSessionRequest session_request,
+ mojom::blink::SpeechRecognitionSessionClientPtrInfo session_client,
+ const SpeechGrammarList& grammars,
+ const String& lang,
+ bool continuous,
+ bool interim_results,
+ unsigned long max_alternatives) {
+ mojom::blink::StartSpeechRecognitionRequestParamsPtr msg_params =
+ mojom::blink::StartSpeechRecognitionRequestParams::New();
+ for (unsigned i = 0; i < grammars.length(); i++) {
+ SpeechGrammar* grammar = grammars.item(i);
+ msg_params->grammars.push_back(mojom::blink::SpeechRecognitionGrammar::New(
+ grammar->src(), grammar->weight()));
+ }
+ msg_params->language = lang.IsNull() ? g_empty_string : lang;
+ msg_params->max_hypotheses = max_alternatives;
+ msg_params->continuous = continuous;
+ msg_params->interim_results = interim_results;
+ msg_params->origin = GetSupplementable()->GetDocument()->GetSecurityOrigin();
+ msg_params->client = std::move(session_client);
+ msg_params->session_request = std::move(session_request);
+
+ GetSpeechRecognizer().Start(std::move(msg_params));
}
-void ProvideSpeechRecognitionTo(LocalFrame& frame,
- SpeechRecognitionClient* client) {
+void ProvideSpeechRecognitionTo(LocalFrame& frame) {
SpeechRecognitionController::ProvideTo(
- frame, SpeechRecognitionController::Create(client));
+ frame, SpeechRecognitionController::Create(frame));
+}
+
+mojom::blink::SpeechRecognizer&
+SpeechRecognitionController::GetSpeechRecognizer() {
+ if (!speech_recognizer_) {
+ GetSupplementable()->GetInterfaceProvider().GetInterface(
+ mojo::MakeRequest(&speech_recognizer_));
+ }
+ return *speech_recognizer_;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.h b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.h
index 19a3db25e85..1f98f355d1f 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.h
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_controller.h
@@ -28,11 +28,14 @@
#include <memory>
+#include "third_party/blink/public/mojom/speech/speech_recognizer.mojom-blink.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/modules/speech/speech_recognition_client.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
namespace blink {
+class SpeechGrammarList;
+
class SpeechRecognitionController final
: public GarbageCollectedFinalized<SpeechRecognitionController>,
public Supplement<LocalFrame> {
@@ -43,35 +46,29 @@ class SpeechRecognitionController final
virtual ~SpeechRecognitionController();
- void Start(SpeechRecognition* recognition,
- const SpeechGrammarList* grammars,
+ void Start(mojom::blink::SpeechRecognitionSessionRequest session_request,
+ mojom::blink::SpeechRecognitionSessionClientPtrInfo session_client,
+ const SpeechGrammarList& grammars,
const String& lang,
bool continuous,
bool interim_results,
- unsigned long max_alternatives) {
- client_->Start(recognition, grammars, lang, continuous, interim_results,
- max_alternatives);
- }
+ unsigned long max_alternatives);
- void Stop(SpeechRecognition* recognition) { client_->Stop(recognition); }
- void Abort(SpeechRecognition* recognition) { client_->Abort(recognition); }
-
- static SpeechRecognitionController* Create(SpeechRecognitionClient*);
+ static SpeechRecognitionController* Create(LocalFrame& frame);
static SpeechRecognitionController* From(LocalFrame* frame) {
return Supplement<LocalFrame>::From<SpeechRecognitionController>(frame);
}
- void Trace(blink::Visitor* visitor) override {
- Supplement<LocalFrame>::Trace(visitor);
- visitor->Trace(client_);
- }
-
private:
- explicit SpeechRecognitionController(SpeechRecognitionClient*);
+ explicit SpeechRecognitionController(LocalFrame& frame);
+
+ mojom::blink::SpeechRecognizer& GetSpeechRecognizer();
- Member<SpeechRecognitionClient> client_;
+ mojom::blink::SpeechRecognizerPtr speech_recognizer_;
};
+MODULES_EXPORT void ProvideSpeechRecognitionTo(LocalFrame& frame);
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_SPEECH_SPEECH_RECOGNITION_CONTROLLER_H_
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_error.cc b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_error.cc
index 7a6a56f3c2e..44f1bd88004 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_error.cc
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_error.cc
@@ -23,40 +23,43 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "third_party/blink/public/web/web_speech_recognizer_client.h"
#include "third_party/blink/renderer/modules/speech/speech_recognition_error.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink {
-static String ErrorCodeToString(SpeechRecognitionError::ErrorCode code) {
+static String ErrorCodeToString(mojom::blink::SpeechRecognitionErrorCode code) {
switch (code) {
- case SpeechRecognitionError::kErrorCodeOther:
+ case mojom::blink::SpeechRecognitionErrorCode::kNone:
return "other";
- case SpeechRecognitionError::kErrorCodeNoSpeech:
+ case mojom::blink::SpeechRecognitionErrorCode::kNoSpeech:
return "no-speech";
- case SpeechRecognitionError::kErrorCodeAborted:
+ case mojom::blink::SpeechRecognitionErrorCode::kAborted:
return "aborted";
- case SpeechRecognitionError::kErrorCodeAudioCapture:
+ case mojom::blink::SpeechRecognitionErrorCode::kAudioCapture:
return "audio-capture";
- case SpeechRecognitionError::kErrorCodeNetwork:
+ case mojom::blink::SpeechRecognitionErrorCode::kNetwork:
return "network";
- case SpeechRecognitionError::kErrorCodeNotAllowed:
+ case mojom::blink::SpeechRecognitionErrorCode::kNotAllowed:
return "not-allowed";
- case SpeechRecognitionError::kErrorCodeServiceNotAllowed:
+ case mojom::blink::SpeechRecognitionErrorCode::kServiceNotAllowed:
return "service-not-allowed";
- case SpeechRecognitionError::kErrorCodeBadGrammar:
+ case mojom::blink::SpeechRecognitionErrorCode::kBadGrammar:
return "bad-grammar";
- case SpeechRecognitionError::kErrorCodeLanguageNotSupported:
+ case mojom::blink::SpeechRecognitionErrorCode::kLanguageNotSupported:
return "language-not-supported";
+ case mojom::blink::SpeechRecognitionErrorCode::kNoMatch:
+ NOTREACHED();
+ break;
}
NOTREACHED();
return String();
}
-SpeechRecognitionError* SpeechRecognitionError::Create(ErrorCode code,
- const String& message) {
+SpeechRecognitionError* SpeechRecognitionError::Create(
+ mojom::blink::SpeechRecognitionErrorCode code,
+ const String& message) {
return new SpeechRecognitionError(ErrorCodeToString(code), message);
}
@@ -86,23 +89,4 @@ const AtomicString& SpeechRecognitionError::InterfaceName() const {
return EventNames::SpeechRecognitionError;
}
-STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kOtherError,
- SpeechRecognitionError::kErrorCodeOther);
-STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kNoSpeechError,
- SpeechRecognitionError::kErrorCodeNoSpeech);
-STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kAbortedError,
- SpeechRecognitionError::kErrorCodeAborted);
-STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kAudioCaptureError,
- SpeechRecognitionError::kErrorCodeAudioCapture);
-STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kNetworkError,
- SpeechRecognitionError::kErrorCodeNetwork);
-STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kNotAllowedError,
- SpeechRecognitionError::kErrorCodeNotAllowed);
-STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kServiceNotAllowedError,
- SpeechRecognitionError::kErrorCodeServiceNotAllowed);
-STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kBadGrammarError,
- SpeechRecognitionError::kErrorCodeBadGrammar);
-STATIC_ASSERT_ENUM(WebSpeechRecognizerClient::kLanguageNotSupportedError,
- SpeechRecognitionError::kErrorCodeLanguageNotSupported);
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_error.h b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_error.h
index 6cf9703c23b..4314c11f1bd 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_error.h
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_error.h
@@ -26,6 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SPEECH_SPEECH_RECOGNITION_ERROR_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_SPEECH_SPEECH_RECOGNITION_ERROR_H_
+#include "third_party/blink/public/mojom/speech/speech_recognition_error_code.mojom-blink.h"
#include "third_party/blink/renderer/modules/event_modules.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/speech/speech_recognition_error_init.h"
@@ -37,21 +38,9 @@ class MODULES_EXPORT SpeechRecognitionError final : public Event {
DEFINE_WRAPPERTYPEINFO();
public:
- enum ErrorCode {
- // FIXME: This is an unspecified error and Chromium should stop using it.
- kErrorCodeOther = 0,
-
- kErrorCodeNoSpeech = 1,
- kErrorCodeAborted = 2,
- kErrorCodeAudioCapture = 3,
- kErrorCodeNetwork = 4,
- kErrorCodeNotAllowed = 5,
- kErrorCodeServiceNotAllowed = 6,
- kErrorCodeBadGrammar = 7,
- kErrorCodeLanguageNotSupported = 8
- };
-
- static SpeechRecognitionError* Create(ErrorCode, const String&);
+ static SpeechRecognitionError* Create(
+ mojom::blink::SpeechRecognitionErrorCode,
+ const String&);
static SpeechRecognitionError* Create(const AtomicString&,
const SpeechRecognitionErrorInit&);
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_event.idl b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_event.idl
index 06bab39452d..449032f7388 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_recognition_event.idl
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_recognition_event.idl
@@ -32,6 +32,6 @@
readonly attribute unsigned long resultIndex;
readonly attribute SpeechRecognitionResultList? results;
- readonly attribute Document? interpretation;
- readonly attribute Document? emma;
+ [Measure] readonly attribute Document? interpretation;
+ [Measure] readonly attribute Document? emma;
};
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_synthesis.cc b/chromium/third_party/blink/renderer/modules/speech/speech_synthesis.cc
index 4c1f29a0552..ad460c9db39 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_synthesis.cc
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_synthesis.cc
@@ -25,10 +25,14 @@
#include "third_party/blink/renderer/modules/speech/speech_synthesis.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/use_counter.h"
+#include "third_party/blink/renderer/core/html/media/autoplay_policy.h"
+#include "third_party/blink/renderer/core/timing/dom_window_performance.h"
+#include "third_party/blink/renderer/core/timing/performance.h"
#include "third_party/blink/renderer/modules/speech/speech_synthesis_event.h"
#include "third_party/blink/renderer/platform/speech/platform_speech_synthesis_voice.h"
-#include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink {
@@ -39,7 +43,9 @@ SpeechSynthesis* SpeechSynthesis::Create(ExecutionContext* context) {
SpeechSynthesis::SpeechSynthesis(ExecutionContext* context)
: ContextClient(context),
platform_speech_synthesizer_(PlatformSpeechSynthesizer::Create(this)),
- is_paused_(false) {}
+ is_paused_(false) {
+ DCHECK(!GetExecutionContext() || GetExecutionContext()->IsDocument());
+}
void SpeechSynthesis::SetPlatformSynthesizer(
PlatformSpeechSynthesizer* synthesizer) {
@@ -88,13 +94,34 @@ void SpeechSynthesis::StartSpeakingImmediately() {
SpeechSynthesisUtterance* utterance = CurrentSpeechUtterance();
DCHECK(utterance);
- utterance->SetStartTime(CurrentTimeTicksInSeconds());
+ double millis;
+ if (!GetElapsedTimeMillis(&millis))
+ return;
+
+ utterance->SetStartTime(millis / 1000.0);
is_paused_ = false;
platform_speech_synthesizer_->Speak(utterance->PlatformUtterance());
}
void SpeechSynthesis::speak(SpeechSynthesisUtterance* utterance) {
DCHECK(utterance);
+ Document* document = ToDocument(GetExecutionContext());
+ if (!document)
+ return;
+
+ // If SpeechSynthesis followed autoplay policy, we could simply fire an error
+ // here and ignore this utterance. For now, just log some UseCounters to
+ // evaluate potential breakage.
+ //
+ // Note: Non-UseCounter based TTS metrics are of the form TextToSpeech.* and
+ // are generally global, whereas these are scoped to a single page load.
+ UseCounter::Count(document, WebFeature::kTextToSpeech_Speak);
+ UseCounter::CountCrossOriginIframe(
+ *document, WebFeature::kTextToSpeech_SpeakCrossOrigin);
+ if (!IsAllowedToStartByAutoplay()) {
+ UseCounter::Count(document,
+ WebFeature::kTextToSpeech_SpeakDisallowedByAutoplay);
+ }
utterance_queue_.push_back(utterance);
@@ -126,11 +153,11 @@ void SpeechSynthesis::FireEvent(const AtomicString& type,
SpeechSynthesisUtterance* utterance,
unsigned long char_index,
const String& name) {
- if (!GetExecutionContext())
+ double millis;
+ if (!GetElapsedTimeMillis(&millis))
return;
- double elapsed_time_millis =
- (CurrentTimeTicksInSeconds() - utterance->StartTime()) * 1000.0;
+ double elapsed_time_millis = millis - utterance->StartTime() * 1000.0;
utterance->DispatchEvent(SpeechSynthesisEvent::Create(
type, utterance, char_index, elapsed_time_millis, name));
}
@@ -243,4 +270,31 @@ void SpeechSynthesis::Trace(blink::Visitor* visitor) {
EventTargetWithInlineData::Trace(visitor);
}
+bool SpeechSynthesis::GetElapsedTimeMillis(double* millis) {
+ if (!GetExecutionContext())
+ return false;
+ Document* delegate_document = ToDocument(GetExecutionContext());
+ if (!delegate_document || delegate_document->IsStopped())
+ return false;
+ LocalDOMWindow* delegate_dom_window = delegate_document->domWindow();
+ if (!delegate_dom_window)
+ return false;
+
+ *millis = DOMWindowPerformance::performance(*delegate_dom_window)->now();
+ return true;
+}
+
+bool SpeechSynthesis::IsAllowedToStartByAutoplay() const {
+ Document* document = ToDocument(GetExecutionContext());
+ DCHECK(document);
+
+ // Note: could check the utterance->volume here, but that could be overriden
+ // in the case of SSML.
+ if (AutoplayPolicy::GetAutoplayPolicyForDocument(*document) !=
+ AutoplayPolicy::Type::kDocumentUserActivationRequired) {
+ return true;
+ }
+ return AutoplayPolicy::IsDocumentAllowedToPlay(*document);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_synthesis.h b/chromium/third_party/blink/renderer/modules/speech/speech_synthesis.h
index c6d06014426..4b87c237429 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_synthesis.h
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_synthesis.h
@@ -95,6 +95,12 @@ class MODULES_EXPORT SpeechSynthesis final
// Returns the utterance at the front of the queue.
SpeechSynthesisUtterance* CurrentSpeechUtterance() const;
+ // Gets a timestamp in millis that is safe to expose to the web.
+ // Returns false if it cannot get a timestamp.
+ bool GetElapsedTimeMillis(double* millis);
+
+ bool IsAllowedToStartByAutoplay() const;
+
Member<PlatformSpeechSynthesizer> platform_speech_synthesizer_;
HeapVector<Member<SpeechSynthesisVoice>> voice_list_;
HeapDeque<Member<SpeechSynthesisUtterance>> utterance_queue_;
diff --git a/chromium/third_party/blink/renderer/modules/speech/speech_synthesis.idl b/chromium/third_party/blink/renderer/modules/speech/speech_synthesis.idl
index 6f076656bb3..94611415cd0 100644
--- a/chromium/third_party/blink/renderer/modules/speech/speech_synthesis.idl
+++ b/chromium/third_party/blink/renderer/modules/speech/speech_synthesis.idl
@@ -32,7 +32,7 @@
readonly attribute boolean speaking;
readonly attribute boolean paused;
- void speak(SpeechSynthesisUtterance utterance);
+ [Measure] void speak(SpeechSynthesisUtterance utterance);
void cancel();
void pause();
void resume();
diff --git a/chromium/third_party/blink/renderer/modules/storage/BUILD.gn b/chromium/third_party/blink/renderer/modules/storage/BUILD.gn
index fe250beae04..d6c8f876a63 100644
--- a/chromium/third_party/blink/renderer/modules/storage/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/storage/BUILD.gn
@@ -12,10 +12,10 @@ blink_modules_sources("storage") {
"dom_window_storage_controller.h",
"inspector_dom_storage_agent.cc",
"inspector_dom_storage_agent.h",
- "storage.cc",
- "storage.h",
"storage_area.cc",
"storage_area.h",
+ "storage_area_map.cc",
+ "storage_area_map.h",
"storage_event.cc",
"storage_event.h",
"storage_namespace.cc",
@@ -24,3 +24,24 @@ blink_modules_sources("storage") {
"storage_namespace_controller.h",
]
}
+
+jumbo_source_set("unit_tests") {
+ testonly = true
+ sources = [
+ "storage_area_map_test.cc",
+ ]
+
+ configs += [
+ "//third_party/blink/renderer:config",
+ "//third_party/blink/renderer:inside_blink",
+ "//third_party/blink/renderer/core:blink_core_pch",
+ ]
+
+ deps = [
+ "//testing/gmock",
+ "//testing/gtest",
+ "//third_party/blink/renderer/modules",
+ "//third_party/blink/renderer/platform",
+ "//third_party/blink/renderer/platform/wtf",
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/modules/storage/OWNERS b/chromium/third_party/blink/renderer/modules/storage/OWNERS
index d1e5fd47709..1559acca15e 100644
--- a/chromium/third_party/blink/renderer/modules/storage/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/storage/OWNERS
@@ -1,3 +1,7 @@
+# Primary:
+mek@chromium.org
+
+# Secondary:
jsbell@chromium.org
pwnall@chromium.org
diff --git a/chromium/third_party/blink/renderer/modules/storage/README.md b/chromium/third_party/blink/renderer/modules/storage/README.md
new file mode 100644
index 00000000000..1b1875d7e38
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/storage/README.md
@@ -0,0 +1,25 @@
+# `blink/renderer/modules/storage`
+
+This diretory contains the renderer side implementation of the DOM Storage API.
+This API is defined in the
+[HTML Spec](https://html.spec.whatwg.org/multipage/webstorage.html)'s section on
+Web Storage.
+
+The browser side code for this lives in `content/browser/dom_storage/`.
+
+## Class structure
+
+`StorageArea` implements the WebIDL `Storage` interface. Instances of this class
+will in the future hold a reference to a shared `CachedStorageArea` instance.
+All `StorageArea` instances representing the same area will use the same
+`CachedStorageArea` instance. Today instead each `StorageArea` owns a separate
+`WebStorageArea` instance, implemented by the content layer.
+
+`CachedStorageArea` will be responsible for communicating with the browser
+process over the `StorageArea` mojom interface. It will also cache all the data
+for a area in a `StorageAreaMap` instance, and will dispatch events it receives
+to the relevant `StorageArea` and `InspectorDOMStorageAgent` instances.
+
+`StorageAreaMap` represents the in-memory version of the data in a particular
+storage area. It will be owned by a instance of the (yet-to-be-written)
+`CachedStorageArea` class.
diff --git a/chromium/third_party/blink/renderer/modules/storage/dom_window_storage.cc b/chromium/third_party/blink/renderer/modules/storage/dom_window_storage.cc
index cab94026fea..848aebe7a10 100644
--- a/chromium/third_party/blink/renderer/modules/storage/dom_window_storage.cc
+++ b/chromium/third_party/blink/renderer/modules/storage/dom_window_storage.cc
@@ -11,7 +11,7 @@
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/page/page.h"
-#include "third_party/blink/renderer/modules/storage/storage.h"
+#include "third_party/blink/renderer/modules/storage/storage_area.h"
#include "third_party/blink/renderer/modules/storage/storage_namespace.h"
#include "third_party/blink/renderer/modules/storage/storage_namespace_controller.h"
@@ -41,18 +41,18 @@ DOMWindowStorage& DOMWindowStorage::From(LocalDOMWindow& window) {
}
// static
-Storage* DOMWindowStorage::sessionStorage(LocalDOMWindow& window,
- ExceptionState& exception_state) {
+StorageArea* DOMWindowStorage::sessionStorage(LocalDOMWindow& window,
+ ExceptionState& exception_state) {
return From(window).sessionStorage(exception_state);
}
// static
-Storage* DOMWindowStorage::localStorage(LocalDOMWindow& window,
- ExceptionState& exception_state) {
+StorageArea* DOMWindowStorage::localStorage(LocalDOMWindow& window,
+ ExceptionState& exception_state) {
return From(window).localStorage(exception_state);
}
-Storage* DOMWindowStorage::sessionStorage(
+StorageArea* DOMWindowStorage::sessionStorage(
ExceptionState& exception_state) const {
if (!GetSupplementable()->GetFrame())
return nullptr;
@@ -77,7 +77,7 @@ Storage* DOMWindowStorage::sessionStorage(
}
if (session_storage_) {
- if (!session_storage_->Area()->CanAccessStorage(document->GetFrame())) {
+ if (!session_storage_->CanAccessStorage()) {
exception_state.ThrowSecurityError(access_denied_message);
return nullptr;
}
@@ -88,19 +88,21 @@ Storage* DOMWindowStorage::sessionStorage(
if (!page)
return nullptr;
- StorageArea* storage_area =
+ auto storage_area =
StorageNamespaceController::From(page)->SessionStorage()->GetStorageArea(
document->GetSecurityOrigin());
- if (!storage_area->CanAccessStorage(document->GetFrame())) {
+ session_storage_ =
+ StorageArea::Create(document->GetFrame(), std::move(storage_area),
+ StorageArea::StorageType::kSessionStorage);
+ if (!session_storage_->CanAccessStorage()) {
exception_state.ThrowSecurityError(access_denied_message);
return nullptr;
}
-
- session_storage_ = Storage::Create(document->GetFrame(), storage_area);
return session_storage_;
}
-Storage* DOMWindowStorage::localStorage(ExceptionState& exception_state) const {
+StorageArea* DOMWindowStorage::localStorage(
+ ExceptionState& exception_state) const {
if (!GetSupplementable()->GetFrame())
return nullptr;
@@ -124,7 +126,7 @@ Storage* DOMWindowStorage::localStorage(ExceptionState& exception_state) const {
}
if (local_storage_) {
- if (!local_storage_->Area()->CanAccessStorage(document->GetFrame())) {
+ if (!local_storage_->CanAccessStorage()) {
exception_state.ThrowSecurityError(access_denied_message);
return nullptr;
}
@@ -134,13 +136,15 @@ Storage* DOMWindowStorage::localStorage(ExceptionState& exception_state) const {
Page* page = document->GetPage();
if (!page || !page->GetSettings().GetLocalStorageEnabled())
return nullptr;
- StorageArea* storage_area =
+ auto storage_area =
StorageNamespace::LocalStorageArea(document->GetSecurityOrigin());
- if (!storage_area->CanAccessStorage(document->GetFrame())) {
+ local_storage_ =
+ StorageArea::Create(document->GetFrame(), std::move(storage_area),
+ StorageArea::StorageType::kLocalStorage);
+ if (!local_storage_->CanAccessStorage()) {
exception_state.ThrowSecurityError(access_denied_message);
return nullptr;
}
- local_storage_ = Storage::Create(document->GetFrame(), storage_area);
return local_storage_;
}
diff --git a/chromium/third_party/blink/renderer/modules/storage/dom_window_storage.h b/chromium/third_party/blink/renderer/modules/storage/dom_window_storage.h
index 9765c848dce..d958b9075aa 100644
--- a/chromium/third_party/blink/renderer/modules/storage/dom_window_storage.h
+++ b/chromium/third_party/blink/renderer/modules/storage/dom_window_storage.h
@@ -12,7 +12,7 @@ namespace blink {
class ExceptionState;
class LocalDOMWindow;
-class Storage;
+class StorageArea;
class DOMWindowStorage final : public GarbageCollected<DOMWindowStorage>,
public Supplement<LocalDOMWindow> {
@@ -22,21 +22,21 @@ class DOMWindowStorage final : public GarbageCollected<DOMWindowStorage>,
static const char kSupplementName[];
static DOMWindowStorage& From(LocalDOMWindow&);
- static Storage* sessionStorage(LocalDOMWindow&, ExceptionState&);
- static Storage* localStorage(LocalDOMWindow&, ExceptionState&);
+ static StorageArea* sessionStorage(LocalDOMWindow&, ExceptionState&);
+ static StorageArea* localStorage(LocalDOMWindow&, ExceptionState&);
- Storage* sessionStorage(ExceptionState&) const;
- Storage* localStorage(ExceptionState&) const;
- Storage* OptionalSessionStorage() const { return session_storage_.Get(); }
- Storage* OptionalLocalStorage() const { return local_storage_.Get(); }
+ StorageArea* sessionStorage(ExceptionState&) const;
+ StorageArea* localStorage(ExceptionState&) const;
+ StorageArea* OptionalSessionStorage() const { return session_storage_.Get(); }
+ StorageArea* OptionalLocalStorage() const { return local_storage_.Get(); }
void Trace(blink::Visitor*) override;
private:
explicit DOMWindowStorage(LocalDOMWindow&);
- mutable Member<Storage> session_storage_;
- mutable Member<Storage> local_storage_;
+ mutable Member<StorageArea> session_storage_;
+ mutable Member<StorageArea> local_storage_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/storage/inspector_dom_storage_agent.cc b/chromium/third_party/blink/renderer/modules/storage/inspector_dom_storage_agent.cc
index 776c7748d3c..a3b49bc4f2f 100644
--- a/chromium/third_party/blink/renderer/modules/storage/inspector_dom_storage_agent.cc
+++ b/chromium/third_party/blink/renderer/modules/storage/inspector_dom_storage_agent.cc
@@ -29,17 +29,16 @@
#include "third_party/blink/renderer/modules/storage/inspector_dom_storage_agent.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/dom/exception_code.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/inspected_frames.h"
#include "third_party/blink/renderer/core/page/page.h"
-#include "third_party/blink/renderer/modules/storage/storage.h"
+#include "third_party/blink/renderer/modules/storage/storage_area.h"
#include "third_party/blink/renderer/modules/storage/storage_namespace.h"
#include "third_party/blink/renderer/modules/storage/storage_namespace_controller.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
namespace blink {
@@ -53,8 +52,13 @@ static const char kDomStorageAgentEnabled[] = "domStorageAgentEnabled";
static Response ToResponse(ExceptionState& exception_state) {
if (!exception_state.HadException())
return Response::OK();
- return Response::Error(DOMException::GetErrorName(exception_state.Code()) +
- " " + exception_state.Message());
+
+ String name_prefix = IsDOMExceptionCode(exception_state.Code())
+ ? DOMException::GetErrorName(
+ exception_state.CodeAs<DOMExceptionCode>()) +
+ " "
+ : g_empty_string;
+ return Response::Error(name_prefix + exception_state.Message());
}
InspectorDOMStorageAgent::InspectorDOMStorageAgent(
@@ -99,14 +103,12 @@ Response InspectorDOMStorageAgent::disable() {
Response InspectorDOMStorageAgent::clear(
std::unique_ptr<protocol::DOMStorage::StorageId> storage_id) {
- LocalFrame* frame = nullptr;
StorageArea* storage_area = nullptr;
- Response response =
- FindStorageArea(std::move(storage_id), frame, storage_area);
+ Response response = FindStorageArea(std::move(storage_id), storage_area);
if (!response.isSuccess())
return response;
DummyExceptionStateForTesting exception_state;
- storage_area->Clear(exception_state, frame);
+ storage_area->clear(exception_state);
if (exception_state.HadException())
return Response::Error("Could not clear the storage");
return Response::OK();
@@ -115,10 +117,8 @@ Response InspectorDOMStorageAgent::clear(
Response InspectorDOMStorageAgent::getDOMStorageItems(
std::unique_ptr<protocol::DOMStorage::StorageId> storage_id,
std::unique_ptr<protocol::Array<protocol::Array<String>>>* items) {
- LocalFrame* frame = nullptr;
StorageArea* storage_area = nullptr;
- Response response =
- FindStorageArea(std::move(storage_id), frame, storage_area);
+ Response response = FindStorageArea(std::move(storage_id), storage_area);
if (!response.isSuccess())
return response;
@@ -126,12 +126,12 @@ Response InspectorDOMStorageAgent::getDOMStorageItems(
protocol::Array<protocol::Array<String>>::create();
DummyExceptionStateForTesting exception_state;
- for (unsigned i = 0; i < storage_area->length(exception_state, frame); ++i) {
- String name(storage_area->Key(i, exception_state, frame));
+ for (unsigned i = 0; i < storage_area->length(exception_state); ++i) {
+ String name(storage_area->key(i, exception_state));
response = ToResponse(exception_state);
if (!response.isSuccess())
return response;
- String value(storage_area->GetItem(name, exception_state, frame));
+ String value(storage_area->getItem(name, exception_state));
response = ToResponse(exception_state);
if (!response.isSuccess())
return response;
@@ -149,30 +149,26 @@ Response InspectorDOMStorageAgent::setDOMStorageItem(
std::unique_ptr<protocol::DOMStorage::StorageId> storage_id,
const String& key,
const String& value) {
- LocalFrame* frame = nullptr;
StorageArea* storage_area = nullptr;
- Response response =
- FindStorageArea(std::move(storage_id), frame, storage_area);
+ Response response = FindStorageArea(std::move(storage_id), storage_area);
if (!response.isSuccess())
return response;
DummyExceptionStateForTesting exception_state;
- storage_area->SetItem(key, value, exception_state, frame);
+ storage_area->setItem(key, value, exception_state);
return ToResponse(exception_state);
}
Response InspectorDOMStorageAgent::removeDOMStorageItem(
std::unique_ptr<protocol::DOMStorage::StorageId> storage_id,
const String& key) {
- LocalFrame* frame = nullptr;
StorageArea* storage_area = nullptr;
- Response response =
- FindStorageArea(std::move(storage_id), frame, storage_area);
+ Response response = FindStorageArea(std::move(storage_id), storage_area);
if (!response.isSuccess())
return response;
DummyExceptionStateForTesting exception_state;
- storage_area->RemoveItem(key, exception_state, frame);
+ storage_area->removeItem(key, exception_state);
return ToResponse(exception_state);
}
@@ -194,8 +190,8 @@ void InspectorDOMStorageAgent::DidDispatchDOMStorageEvent(
if (!GetFrontend())
return;
- std::unique_ptr<protocol::DOMStorage::StorageId> id =
- GetStorageId(security_origin, storage_type == StorageArea::kLocalStorage);
+ std::unique_ptr<protocol::DOMStorage::StorageId> id = GetStorageId(
+ security_origin, storage_type == StorageArea::StorageType::kLocalStorage);
if (key.IsNull())
GetFrontend()->domStorageItemsCleared(std::move(id));
@@ -210,11 +206,10 @@ void InspectorDOMStorageAgent::DidDispatchDOMStorageEvent(
Response InspectorDOMStorageAgent::FindStorageArea(
std::unique_ptr<protocol::DOMStorage::StorageId> storage_id,
- LocalFrame*& frame,
StorageArea*& storage_area) {
String security_origin = storage_id->getSecurityOrigin();
bool is_local_storage = storage_id->getIsLocalStorage();
- frame =
+ LocalFrame* frame =
inspected_frames_->FrameWithSecurityOrigin(security_origin);
if (!frame)
return Response::Error("Frame not found for the given security origin");
@@ -222,8 +217,11 @@ Response InspectorDOMStorageAgent::FindStorageArea(
if (is_local_storage) {
if (!frame->GetDocument()->GetSecurityOrigin()->CanAccessLocalStorage())
return Response::Error("Security origin cannot access local storage");
- storage_area = StorageNamespace::LocalStorageArea(
- frame->GetDocument()->GetSecurityOrigin());
+ storage_area =
+ StorageArea::Create(frame,
+ StorageNamespace::LocalStorageArea(
+ frame->GetDocument()->GetSecurityOrigin()),
+ StorageArea::StorageType::kLocalStorage);
return Response::OK();
}
@@ -233,8 +231,11 @@ Response InspectorDOMStorageAgent::FindStorageArea(
StorageNamespaceController::From(frame->GetPage())->SessionStorage();
if (!session_storage)
return Response::Error("SessionStorage is not supported");
- storage_area = session_storage->GetStorageArea(
- frame->GetDocument()->GetSecurityOrigin());
+ storage_area =
+ StorageArea::Create(frame,
+ session_storage->GetStorageArea(
+ frame->GetDocument()->GetSecurityOrigin()),
+ StorageArea::StorageType::kSessionStorage);
return Response::OK();
}
diff --git a/chromium/third_party/blink/renderer/modules/storage/inspector_dom_storage_agent.h b/chromium/third_party/blink/renderer/modules/storage/inspector_dom_storage_agent.h
index e29f3c1c348..adc23d1b128 100644
--- a/chromium/third_party/blink/renderer/modules/storage/inspector_dom_storage_agent.h
+++ b/chromium/third_party/blink/renderer/modules/storage/inspector_dom_storage_agent.h
@@ -38,9 +38,7 @@
namespace blink {
-class LocalFrame;
class InspectedFrames;
-class StorageArea;
class MODULES_EXPORT InspectorDOMStorageAgent final
: public InspectorBaseAgent<protocol::DOMStorage::Metainfo> {
@@ -80,7 +78,6 @@ class MODULES_EXPORT InspectorDOMStorageAgent final
protocol::Response FindStorageArea(
std::unique_ptr<protocol::DOMStorage::StorageId>,
- LocalFrame*&,
StorageArea*&);
std::unique_ptr<protocol::DOMStorage::StorageId> GetStorageId(
const SecurityOrigin*,
diff --git a/chromium/third_party/blink/renderer/modules/storage/storage.cc b/chromium/third_party/blink/renderer/modules/storage/storage.cc
deleted file mode 100644
index 1309e4bad77..00000000000
--- a/chromium/third_party/blink/renderer/modules/storage/storage.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/modules/storage/storage.h"
-
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-Storage* Storage::Create(LocalFrame* frame, StorageArea* storage_area) {
- return new Storage(frame, storage_area);
-}
-
-Storage::Storage(LocalFrame* frame, StorageArea* storage_area)
- : ContextClient(frame), storage_area_(storage_area) {
- DCHECK(frame);
- DCHECK(storage_area_);
-}
-
-void Storage::NamedPropertyEnumerator(Vector<String>& names,
- ExceptionState& exception_state) {
- unsigned length = this->length(exception_state);
- if (exception_state.HadException())
- return;
- names.resize(length);
- for (unsigned i = 0; i < length; ++i) {
- String key = this->key(i, exception_state);
- if (exception_state.HadException())
- return;
- DCHECK(!key.IsNull());
- String val = getItem(key, exception_state);
- if (exception_state.HadException())
- return;
- names[i] = key;
- }
-}
-
-bool Storage::NamedPropertyQuery(const AtomicString& name,
- ExceptionState& exception_state) {
- if (name == "length")
- return false;
- bool found = Contains(name, exception_state);
- if (exception_state.HadException() || !found)
- return false;
- return true;
-}
-
-void Storage::Trace(blink::Visitor* visitor) {
- visitor->Trace(storage_area_);
- ScriptWrappable::Trace(visitor);
- ContextClient::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/storage/storage.h b/chromium/third_party/blink/renderer/modules/storage/storage.h
deleted file mode 100644
index 56767f37239..00000000000
--- a/chromium/third_party/blink/renderer/modules/storage/storage.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_STORAGE_STORAGE_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_STORAGE_STORAGE_H_
-
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
-#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
-#include "third_party/blink/renderer/modules/storage/storage_area.h"
-#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/wtf/forward.h"
-
-namespace blink {
-
-class ExceptionState;
-class LocalFrame;
-
-class Storage final : public ScriptWrappable, public ContextClient {
- DEFINE_WRAPPERTYPEINFO();
- USING_GARBAGE_COLLECTED_MIXIN(Storage);
-
- public:
- static Storage* Create(LocalFrame*, StorageArea*);
- unsigned length(ExceptionState& ec) const {
- return storage_area_->length(ec, GetFrame());
- }
- String key(unsigned index, ExceptionState& ec) const {
- return storage_area_->Key(index, ec, GetFrame());
- }
- String getItem(const String& key, ExceptionState& ec) const {
- return storage_area_->GetItem(key, ec, GetFrame());
- }
- bool setItem(const String& key, const String& value, ExceptionState& ec) {
- storage_area_->SetItem(key, value, ec, GetFrame());
- return true;
- }
- DeleteResult removeItem(const String& key, ExceptionState& ec) {
- storage_area_->RemoveItem(key, ec, GetFrame());
- return kDeleteSuccess;
- }
- void clear(ExceptionState& ec) { storage_area_->Clear(ec, GetFrame()); }
- bool Contains(const String& key, ExceptionState& ec) const {
- return storage_area_->Contains(key, ec, GetFrame());
- }
-
- StorageArea* Area() const { return storage_area_.Get(); }
-
- void NamedPropertyEnumerator(Vector<String>&, ExceptionState&);
- bool NamedPropertyQuery(const AtomicString&, ExceptionState&);
-
- void Trace(blink::Visitor*) override;
-
- private:
- Storage(LocalFrame*, StorageArea*);
-
- Member<StorageArea> storage_area_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_STORAGE_STORAGE_H_
diff --git a/chromium/third_party/blink/renderer/modules/storage/storage.idl b/chromium/third_party/blink/renderer/modules/storage/storage.idl
index 76b98152ff7..3a5e7f455cc 100644
--- a/chromium/third_party/blink/renderer/modules/storage/storage.idl
+++ b/chromium/third_party/blink/renderer/modules/storage/storage.idl
@@ -25,6 +25,7 @@
// https://html.spec.whatwg.org/multipage/webstorage.html#the-storage-interface
+[ImplementedAs=StorageArea]
interface Storage {
[RaisesException=Getter] readonly attribute unsigned long length;
[RaisesException] DOMString? key(unsigned long index);
diff --git a/chromium/third_party/blink/renderer/modules/storage/storage_area.cc b/chromium/third_party/blink/renderer/modules/storage/storage_area.cc
index c856132a6e3..36f73d3a52d 100644
--- a/chromium/third_party/blink/renderer/modules/storage/storage_area.cc
+++ b/chromium/third_party/blink/renderer/modules/storage/storage_area.cc
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2009 Google Inc. All Rights Reserved.
- * (C) 2008 Apple Inc.
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -11,10 +10,10 @@
* 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 GOOGLE INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -26,136 +25,180 @@
#include "third_party/blink/renderer/modules/storage/storage_area.h"
-#include <memory>
+#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/platform/web_storage_area.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/exception_code.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/page.h"
#include "third_party/blink/renderer/modules/storage/dom_window_storage.h"
#include "third_party/blink/renderer/modules/storage/inspector_dom_storage_agent.h"
-#include "third_party/blink/renderer/modules/storage/storage.h"
#include "third_party/blink/renderer/modules/storage/storage_event.h"
#include "third_party/blink/renderer/modules/storage/storage_namespace.h"
#include "third_party/blink/renderer/modules/storage/storage_namespace_controller.h"
-#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
-StorageArea* StorageArea::Create(std::unique_ptr<WebStorageArea> storage_area,
+StorageArea* StorageArea::Create(LocalFrame* frame,
+ std::unique_ptr<WebStorageArea> storage_area,
StorageType storage_type) {
- return new StorageArea(std::move(storage_area), storage_type);
+ return new StorageArea(frame, std::move(storage_area), storage_type);
}
-StorageArea::StorageArea(std::unique_ptr<WebStorageArea> storage_area,
+StorageArea::StorageArea(LocalFrame* frame,
+ std::unique_ptr<WebStorageArea> storage_area,
StorageType storage_type)
- : storage_area_(std::move(storage_area)),
- storage_type_(storage_type),
- frame_used_for_can_access_storage_(nullptr),
- can_access_storage_cached_result_(false) {}
-
-StorageArea::~StorageArea() = default;
-
-void StorageArea::Trace(blink::Visitor* visitor) {
- visitor->Trace(frame_used_for_can_access_storage_);
+ : ContextClient(frame),
+ storage_area_(std::move(storage_area)),
+ storage_type_(storage_type) {
+ DCHECK(frame);
+ DCHECK(storage_area_);
}
-unsigned StorageArea::length(ExceptionState& exception_state,
- LocalFrame* frame) {
- if (!CanAccessStorage(frame)) {
+unsigned StorageArea::length(ExceptionState& exception_state) const {
+ if (!CanAccessStorage()) {
exception_state.ThrowSecurityError("access is denied for this document.");
return 0;
}
return storage_area_->length();
}
-String StorageArea::Key(unsigned index,
- ExceptionState& exception_state,
- LocalFrame* frame) {
- if (!CanAccessStorage(frame)) {
+String StorageArea::key(unsigned index, ExceptionState& exception_state) const {
+ if (!CanAccessStorage()) {
exception_state.ThrowSecurityError("access is denied for this document.");
return String();
}
- return storage_area_->Key(index);
+ bool did_decrease_iterator = false;
+ String result = storage_area_->Key(index, &did_decrease_iterator);
+ if (did_decrease_iterator)
+ UseCounter::Count(GetFrame(), WebFeature::kReverseIterateDOMStorage);
+ return result;
}
-String StorageArea::GetItem(const String& key,
- ExceptionState& exception_state,
- LocalFrame* frame) {
- if (!CanAccessStorage(frame)) {
+String StorageArea::getItem(const String& key,
+ ExceptionState& exception_state) const {
+ if (!CanAccessStorage()) {
exception_state.ThrowSecurityError("access is denied for this document.");
return String();
}
return storage_area_->GetItem(key);
}
-void StorageArea::SetItem(const String& key,
+bool StorageArea::setItem(const String& key,
const String& value,
- ExceptionState& exception_state,
- LocalFrame* frame) {
- if (!CanAccessStorage(frame)) {
+ ExceptionState& exception_state) {
+ if (!CanAccessStorage()) {
exception_state.ThrowSecurityError("access is denied for this document.");
- return;
+ return true;
}
WebStorageArea::Result result = WebStorageArea::kResultOK;
- storage_area_->SetItem(key, value, frame->GetDocument()->Url(), result);
- if (result != WebStorageArea::kResultOK)
+ storage_area_->SetItem(key, value, GetFrame()->GetDocument()->Url(), result);
+ if (result != WebStorageArea::kResultOK) {
exception_state.ThrowDOMException(
- kQuotaExceededError,
+ DOMExceptionCode::kQuotaExceededError,
"Setting the value of '" + key + "' exceeded the quota.");
+ }
+ return true;
}
-void StorageArea::RemoveItem(const String& key,
- ExceptionState& exception_state,
- LocalFrame* frame) {
- if (!CanAccessStorage(frame)) {
+DeleteResult StorageArea::removeItem(const String& key,
+ ExceptionState& exception_state) {
+ if (!CanAccessStorage()) {
exception_state.ThrowSecurityError("access is denied for this document.");
- return;
+ return kDeleteSuccess;
}
- storage_area_->RemoveItem(key, frame->GetDocument()->Url());
+ storage_area_->RemoveItem(key, GetFrame()->GetDocument()->Url());
+ return kDeleteSuccess;
}
-void StorageArea::Clear(ExceptionState& exception_state, LocalFrame* frame) {
- if (!CanAccessStorage(frame)) {
+void StorageArea::clear(ExceptionState& exception_state) {
+ if (!CanAccessStorage()) {
exception_state.ThrowSecurityError("access is denied for this document.");
return;
}
- storage_area_->Clear(frame->GetDocument()->Url());
+ storage_area_->Clear(GetFrame()->GetDocument()->Url());
}
bool StorageArea::Contains(const String& key,
- ExceptionState& exception_state,
- LocalFrame* frame) {
- if (!CanAccessStorage(frame)) {
+ ExceptionState& exception_state) const {
+ if (!CanAccessStorage()) {
exception_state.ThrowSecurityError("access is denied for this document.");
return false;
}
- return !GetItem(key, exception_state, frame).IsNull();
+ return !storage_area_->GetItem(key).IsNull();
+}
+
+void StorageArea::NamedPropertyEnumerator(Vector<String>& names,
+ ExceptionState& exception_state) {
+ unsigned length = this->length(exception_state);
+ if (exception_state.HadException())
+ return;
+ names.resize(length);
+ for (unsigned i = 0; i < length; ++i) {
+ String key = this->key(i, exception_state);
+ if (exception_state.HadException())
+ return;
+ DCHECK(!key.IsNull());
+ String val = getItem(key, exception_state);
+ if (exception_state.HadException())
+ return;
+ names[i] = key;
+ }
+}
+
+bool StorageArea::NamedPropertyQuery(const AtomicString& name,
+ ExceptionState& exception_state) {
+ if (name == "length")
+ return false;
+ bool found = Contains(name, exception_state);
+ return found && !exception_state.HadException();
}
-bool StorageArea::CanAccessStorage(LocalFrame* frame) {
+void StorageArea::Trace(blink::Visitor* visitor) {
+ ScriptWrappable::Trace(visitor);
+ ContextClient::Trace(visitor);
+}
+
+bool StorageArea::CanAccessStorage() const {
+ LocalFrame* frame = GetFrame();
if (!frame || !frame->GetPage())
return false;
- // Should the LocalFrame die before this StorageArea does,
- // that cached reference will be cleared.
- if (frame_used_for_can_access_storage_ == frame)
+ if (did_check_can_access_storage_)
return can_access_storage_cached_result_;
StorageNamespaceController* controller =
StorageNamespaceController::From(frame->GetPage());
if (!controller)
return false;
- bool result = controller->CanAccessStorage(frame, storage_type_);
- // Move attention to the new LocalFrame.
- frame_used_for_can_access_storage_ = frame;
- can_access_storage_cached_result_ = result;
- return result;
+ can_access_storage_cached_result_ =
+ controller->CanAccessStorageArea(frame, storage_type_);
+ did_check_can_access_storage_ = true;
+ return can_access_storage_cached_result_;
}
+namespace {
+Page* FindPageWithSessionStorageNamespace(
+ const WebStorageNamespace& session_namespace) {
+ // Iterate over all pages that have a StorageNamespaceController supplement.
+ for (Page* page : Page::OrdinaryPages()) {
+ const bool kDontCreateIfMissing = false;
+ StorageNamespace* storage_namespace =
+ StorageNamespaceController::From(page)->SessionStorage(
+ kDontCreateIfMissing);
+ if (storage_namespace &&
+ storage_namespace->IsSameNamespace(session_namespace))
+ return page;
+ }
+ return nullptr;
+}
+
+bool IsEventSource(StorageArea* storage, WebStorageArea* source_area_instance) {
+ DCHECK(storage);
+ WebStorageArea* web_area = storage->Area();
+ return web_area == source_area_instance;
+}
+} // namespace
+
void StorageArea::DispatchLocalStorageEvent(
const String& key,
const String& old_value,
@@ -167,42 +210,32 @@ void StorageArea::DispatchLocalStorageEvent(
for (Page* page : Page::OrdinaryPages()) {
for (Frame* frame = page->MainFrame(); frame;
frame = frame->Tree().TraverseNext()) {
- // FIXME: We do not yet have a way to dispatch events to out-of-process
- // frames.
+ // Remote frames are cross-origin and do not need to be notified of
+ // events.
if (!frame->IsLocalFrame())
continue;
LocalFrame* local_frame = ToLocalFrame(frame);
LocalDOMWindow* local_window = local_frame->DomWindow();
- Storage* storage =
+ StorageArea* storage =
DOMWindowStorage::From(*local_window).OptionalLocalStorage();
if (storage &&
local_frame->GetDocument()->GetSecurityOrigin()->IsSameSchemeHostPort(
security_origin) &&
- !IsEventSource(storage, source_area_instance))
+ !IsEventSource(storage, source_area_instance)) {
+ // https://www.w3.org/TR/webstorage/#the-storage-event
local_frame->DomWindow()->EnqueueWindowEvent(
StorageEvent::Create(EventTypeNames::storage, key, old_value,
- new_value, page_url, storage));
+ new_value, page_url, storage),
+ TaskType::kDOMManipulation);
+ }
}
if (InspectorDOMStorageAgent* agent =
- StorageNamespaceController::From(page)->InspectorAgent())
+ StorageNamespaceController::From(page)->InspectorAgent()) {
agent->DidDispatchDOMStorageEvent(key, old_value, new_value,
- kLocalStorage, security_origin);
- }
-}
-
-static Page* FindPageWithSessionStorageNamespace(
- const WebStorageNamespace& session_namespace) {
- // Iterate over all pages that have a StorageNamespaceController supplement.
- for (Page* page : Page::OrdinaryPages()) {
- const bool kDontCreateIfMissing = false;
- StorageNamespace* storage_namespace =
- StorageNamespaceController::From(page)->SessionStorage(
- kDontCreateIfMissing);
- if (storage_namespace &&
- storage_namespace->IsSameNamespace(session_namespace))
- return page;
+ StorageType::kLocalStorage,
+ security_origin);
+ }
}
- return nullptr;
}
void StorageArea::DispatchSessionStorageEvent(
@@ -219,33 +252,30 @@ void StorageArea::DispatchSessionStorageEvent(
for (Frame* frame = page->MainFrame(); frame;
frame = frame->Tree().TraverseNext()) {
- // FIXME: We do not yet have a way to dispatch events to out-of-process
- // frames.
+ // Remote frames are cross-origin and do not need to be notified of events.
if (!frame->IsLocalFrame())
continue;
LocalFrame* local_frame = ToLocalFrame(frame);
LocalDOMWindow* local_window = local_frame->DomWindow();
- Storage* storage =
+ StorageArea* storage =
DOMWindowStorage::From(*local_window).OptionalSessionStorage();
if (storage &&
local_frame->GetDocument()->GetSecurityOrigin()->IsSameSchemeHostPort(
security_origin) &&
- !IsEventSource(storage, source_area_instance))
+ !IsEventSource(storage, source_area_instance)) {
+ // https://www.w3.org/TR/webstorage/#the-storage-event
local_frame->DomWindow()->EnqueueWindowEvent(
StorageEvent::Create(EventTypeNames::storage, key, old_value,
- new_value, page_url, storage));
+ new_value, page_url, storage),
+ TaskType::kDOMManipulation);
+ }
}
if (InspectorDOMStorageAgent* agent =
- StorageNamespaceController::From(page)->InspectorAgent())
+ StorageNamespaceController::From(page)->InspectorAgent()) {
agent->DidDispatchDOMStorageEvent(key, old_value, new_value,
- kSessionStorage, security_origin);
-}
-
-bool StorageArea::IsEventSource(Storage* storage,
- WebStorageArea* source_area_instance) {
- DCHECK(storage);
- StorageArea* area = storage->Area();
- return area->storage_area_.get() == source_area_instance;
+ StorageType::kSessionStorage,
+ security_origin);
+ }
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/storage/storage_area.h b/chromium/third_party/blink/renderer/modules/storage/storage_area.h
index 6751c981d7d..f7780afc6e3 100644
--- a/chromium/third_party/blink/renderer/modules/storage/storage_area.h
+++ b/chromium/third_party/blink/renderer/modules/storage/storage_area.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Google Inc. All Rights Reserved.
+ * Copyright (C) 2008 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* 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 GOOGLE INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -26,43 +26,47 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_STORAGE_STORAGE_AREA_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_STORAGE_STORAGE_AREA_H_
-#include <memory>
-#include "third_party/blink/renderer/core/frame/local_frame.h"
-#include "third_party/blink/renderer/modules/modules_export.h"
+#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
+#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
+#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/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
namespace blink {
class ExceptionState;
-class KURL;
-class SecurityOrigin;
-class Storage;
+class LocalFrame;
class WebStorageArea;
class WebStorageNamespace;
-class MODULES_EXPORT StorageArea final
- : public GarbageCollectedFinalized<StorageArea> {
+class StorageArea final : public ScriptWrappable, public ContextClient {
+ DEFINE_WRAPPERTYPEINFO();
+ USING_GARBAGE_COLLECTED_MIXIN(StorageArea);
+
public:
- enum StorageType { kLocalStorage, kSessionStorage };
+ enum class StorageType { kLocalStorage, kSessionStorage };
+
+ static StorageArea* Create(LocalFrame*,
+ std::unique_ptr<WebStorageArea>,
+ StorageType);
+
+ unsigned length(ExceptionState&) const;
+ String key(unsigned index, ExceptionState&) const;
+ String getItem(const String& key, ExceptionState&) const;
+ bool setItem(const String& key, const String& value, ExceptionState&);
+ DeleteResult removeItem(const String& key, ExceptionState&);
+ void clear(ExceptionState&);
+ bool Contains(const String& key, ExceptionState& ec) const;
- static StorageArea* Create(std::unique_ptr<WebStorageArea>, StorageType);
+ WebStorageArea* Area() const { return storage_area_.get(); }
- virtual ~StorageArea();
+ void NamedPropertyEnumerator(Vector<String>&, ExceptionState&);
+ bool NamedPropertyQuery(const AtomicString&, ExceptionState&);
- // The HTML5 DOM Storage API
- unsigned length(ExceptionState&, LocalFrame* source_frame);
- String Key(unsigned index, ExceptionState&, LocalFrame* source_frame);
- String GetItem(const String& key, ExceptionState&, LocalFrame* source_frame);
- void SetItem(const String& key,
- const String& value,
- ExceptionState&,
- LocalFrame* source_frame);
- void RemoveItem(const String& key, ExceptionState&, LocalFrame* source_frame);
- void Clear(ExceptionState&, LocalFrame* source_frame);
- bool Contains(const String& key, ExceptionState&, LocalFrame* source_frame);
+ bool CanAccessStorage() const;
- bool CanAccessStorage(LocalFrame*);
+ void Trace(blink::Visitor*) override;
static void DispatchLocalStorageEvent(const String& key,
const String& old_value,
@@ -78,17 +82,14 @@ class MODULES_EXPORT StorageArea final
const WebStorageNamespace&,
WebStorageArea* source_area_instance);
- void Trace(blink::Visitor*);
-
private:
- StorageArea(std::unique_ptr<WebStorageArea>, StorageType);
-
- static bool IsEventSource(Storage*, WebStorageArea* source_area_instance);
+ StorageArea(LocalFrame*, std::unique_ptr<WebStorageArea>, StorageType);
std::unique_ptr<WebStorageArea> storage_area_;
StorageType storage_type_;
- WeakMember<LocalFrame> frame_used_for_can_access_storage_;
- bool can_access_storage_cached_result_;
+
+ mutable bool did_check_can_access_storage_ = false;
+ mutable bool can_access_storage_cached_result_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/storage/storage_area_map.cc b/chromium/third_party/blink/renderer/modules/storage/storage_area_map.cc
new file mode 100644
index 00000000000..62ab01c2864
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/storage/storage_area_map.cc
@@ -0,0 +1,118 @@
+// 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/modules/storage/storage_area_map.h"
+
+namespace blink {
+
+namespace {
+
+// For quota purposes we count each character as 2 bytes.
+size_t QuotaForString(const String& s) {
+ return s.length() * sizeof(UChar);
+}
+
+} // namespace
+
+StorageAreaMap::StorageAreaMap(size_t quota) : quota_(quota) {
+ ResetKeyIterator();
+}
+
+unsigned StorageAreaMap::GetLength() const {
+ return keys_values_.size();
+}
+
+String StorageAreaMap::GetKey(unsigned index) const {
+ if (index >= GetLength())
+ return String();
+
+ // Decide if we should leave |key_iterator_| alone, or reset to either the
+ // beginning or end of the map for shortest iteration distance.
+ const unsigned distance_to_current = index > last_key_index_
+ ? index - last_key_index_
+ : last_key_index_ - index;
+ const unsigned distance_to_end = GetLength() - index;
+ if (index < distance_to_current && index < distance_to_end) {
+ // Distance from start is shortest, so reset iterator to begin.
+ last_key_index_ = 0;
+ key_iterator_ = keys_values_.begin();
+ } else if (distance_to_end < distance_to_current && distance_to_end < index) {
+ // Distance from end is shortest, so reset iterator to end.
+ last_key_index_ = GetLength();
+ key_iterator_ = keys_values_.end();
+ }
+
+ while (last_key_index_ < index) {
+ ++key_iterator_;
+ ++last_key_index_;
+ }
+ while (last_key_index_ > index) {
+ --key_iterator_;
+ --last_key_index_;
+ }
+ return key_iterator_->key;
+}
+
+String StorageAreaMap::GetItem(const String& key) const {
+ auto it = keys_values_.find(key);
+ if (it == keys_values_.end())
+ return String();
+ return it->value;
+}
+
+bool StorageAreaMap::SetItem(const String& key,
+ const String& value,
+ String* old_value) {
+ return SetItemInternal(key, value, old_value, true);
+}
+
+void StorageAreaMap::SetItemIgnoringQuota(const String& key,
+ const String& value) {
+ SetItemInternal(key, value, nullptr, false);
+}
+
+bool StorageAreaMap::RemoveItem(const String& key, String* old_value) {
+ const auto it = keys_values_.find(key);
+ if (it == keys_values_.end())
+ return false;
+ quota_used_ -= QuotaForString(key) + QuotaForString(it->value);
+ if (old_value)
+ *old_value = it->value;
+ keys_values_.erase(it);
+ ResetKeyIterator();
+ return true;
+}
+
+void StorageAreaMap::ResetKeyIterator() const {
+ key_iterator_ = keys_values_.begin();
+ last_key_index_ = 0;
+}
+
+bool StorageAreaMap::SetItemInternal(const String& key,
+ const String& value,
+ String* old_value,
+ bool check_quota) {
+ const auto it = keys_values_.find(key);
+ size_t old_item_size = 0;
+ if (it != keys_values_.end()) {
+ old_item_size = QuotaForString(key) + QuotaForString(it->value);
+ if (old_value)
+ *old_value = it->value;
+ }
+ DCHECK_GE(quota_used_, old_item_size);
+ size_t new_item_size = QuotaForString(key) + QuotaForString(value);
+ size_t new_quota_used = quota_used_ - old_item_size + new_item_size;
+
+ // Only check quota if the size is increasing, this allows
+ // shrinking changes to pre-existing files that are over budget.
+ if (check_quota && new_item_size > old_item_size && new_quota_used > quota_)
+ return false;
+
+ keys_values_.Set(key, value);
+ ResetKeyIterator();
+ quota_used_ = new_quota_used;
+ return true;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/storage/storage_area_map.h b/chromium/third_party/blink/renderer/modules/storage/storage_area_map.h
new file mode 100644
index 00000000000..100493011c2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/storage/storage_area_map.h
@@ -0,0 +1,60 @@
+// 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_MODULES_STORAGE_STORAGE_AREA_MAP_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_STORAGE_STORAGE_AREA_MAP_H_
+
+#include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+// This class is used to represent the in-memory version of the data in a
+// StorageArea. This class is responsible for enforcing a quota, and for
+// providing somewhat efficient iteration over all the items in the map via
+// GetLength/GetKey/GetItem.
+// Any modifications to the data in the map can cause all items to be reordered.
+// Nothing is guaranteed about the order of items in the map.
+// For the purpose of quota each character in the key and value strings is
+// counted as two bytes, even if the actual in-memory representation of the
+// string only uses one byte per character.
+class MODULES_EXPORT StorageAreaMap {
+ public:
+ explicit StorageAreaMap(size_t quota);
+
+ unsigned GetLength() const;
+ String GetKey(unsigned index) const;
+ String GetItem(const String& key) const;
+
+ // Returns false iff quota would be exceeded.
+ bool SetItem(const String& key, const String& value, String* old_value);
+ void SetItemIgnoringQuota(const String& key, const String& value);
+ // Returns fals iff item wasn't found.
+ bool RemoveItem(const String& key, String* old_value);
+
+ size_t quota_used() const { return quota_used_; }
+ size_t quota() const { return quota_; }
+
+ private:
+ void ResetKeyIterator() const;
+ bool SetItemInternal(const String& key,
+ const String& value,
+ String* old_value,
+ bool check_quota);
+
+ HashMap<String, String> keys_values_;
+
+ // To make iterating over all keys somewhat less inefficient, we keep track of
+ // an iterator to and index of the last key returned by GetKey().
+ mutable HashMap<String, String>::const_iterator key_iterator_;
+ mutable unsigned last_key_index_;
+
+ size_t quota_used_ = 0;
+ const size_t quota_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_STORAGE_STORAGE_AREA_MAP_H_
diff --git a/chromium/third_party/blink/renderer/modules/storage/storage_area_map_test.cc b/chromium/third_party/blink/renderer/modules/storage/storage_area_map_test.cc
new file mode 100644
index 00000000000..671720b9cd2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/storage/storage_area_map_test.cc
@@ -0,0 +1,132 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/storage/storage_area_map.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+TEST(StorageAreaMapTest, Basics) {
+ const String kKey("key");
+ const String kValue("value");
+ const size_t kValueQuota = kValue.length() * 2;
+ const size_t kItemQuota = (kKey.length() + kValue.length()) * 2;
+ const String kKey2("key2");
+ const size_t kKey2Quota = kKey2.length() * 2;
+ const String kValue2("value2");
+ const size_t kItem2Quota = (kKey2.length() + kValue2.length()) * 2;
+ const size_t kQuota = 1024; // 1K quota for this test.
+
+ StorageAreaMap map(kQuota);
+ String old_value;
+ EXPECT_EQ(kQuota, map.quota());
+
+ // Check the behavior of an empty map.
+ EXPECT_EQ(0u, map.GetLength());
+ EXPECT_TRUE(map.GetKey(0).IsNull());
+ EXPECT_TRUE(map.GetKey(100).IsNull());
+ EXPECT_TRUE(map.GetItem(kKey).IsNull());
+ EXPECT_FALSE(map.RemoveItem(kKey, nullptr));
+ EXPECT_EQ(0u, map.quota_used());
+
+ // Check the behavior of a map containing some values.
+ EXPECT_TRUE(map.SetItem(kKey, kValue, &old_value));
+ EXPECT_TRUE(old_value.IsNull());
+ EXPECT_EQ(1u, map.GetLength());
+ EXPECT_EQ(kKey, map.GetKey(0));
+ EXPECT_TRUE(map.GetKey(1).IsNull());
+ EXPECT_EQ(kValue, map.GetItem(kKey));
+ EXPECT_TRUE(map.GetItem(kKey2).IsNull());
+ EXPECT_EQ(kItemQuota, map.quota_used());
+ EXPECT_TRUE(map.RemoveItem(kKey, &old_value));
+ EXPECT_EQ(kValue, old_value);
+ old_value = String();
+ EXPECT_EQ(0u, map.quota_used());
+
+ EXPECT_TRUE(map.SetItem(kKey, kValue, nullptr));
+ EXPECT_TRUE(map.SetItem(kKey2, kValue, nullptr));
+ EXPECT_EQ(kItemQuota + kKey2Quota + kValueQuota, map.quota_used());
+ EXPECT_TRUE(map.SetItem(kKey2, kValue2, &old_value));
+ EXPECT_EQ(kValue, old_value);
+ EXPECT_EQ(kItemQuota + kItem2Quota, map.quota_used());
+ EXPECT_EQ(2u, map.GetLength());
+ String key1 = map.GetKey(0);
+ String key2 = map.GetKey(1);
+ EXPECT_TRUE((key1 == kKey && key2 == kKey2) ||
+ (key1 == kKey2 && key2 == kKey))
+ << key1 << ", " << key2;
+ EXPECT_EQ(key1, map.GetKey(0));
+ EXPECT_EQ(key2, map.GetKey(1));
+ EXPECT_EQ(kItemQuota + kItem2Quota, map.quota_used());
+}
+
+TEST(StorageAreaMapTest, EnforcesQuota) {
+ const String kKey("test_key");
+ const String kValue("test_value");
+ const String kKey2("test_key_2");
+ String old_value;
+
+ // A 50 byte quota is too small to hold both keys and values, so we
+ // should see the StorageAreaMap enforcing it.
+ const size_t kQuota = 50;
+
+ StorageAreaMap map(kQuota);
+ EXPECT_TRUE(map.SetItem(kKey, kValue, nullptr));
+ EXPECT_FALSE(map.SetItem(kKey2, kValue, nullptr));
+ EXPECT_EQ(1u, map.GetLength());
+ EXPECT_EQ(kValue, map.GetItem(kKey));
+ EXPECT_TRUE(map.GetItem(kKey2).IsNull());
+
+ EXPECT_TRUE(map.RemoveItem(kKey, nullptr));
+ EXPECT_EQ(0u, map.GetLength());
+ EXPECT_TRUE(map.SetItem(kKey2, kValue, nullptr));
+ EXPECT_EQ(1u, map.GetLength());
+
+ // Verify that the SetItemIgnoringQuota method does not do quota checking.
+ map.SetItemIgnoringQuota(kKey, kValue);
+ EXPECT_GT(map.quota_used(), kQuota);
+ EXPECT_EQ(2u, map.GetLength());
+ EXPECT_EQ(kValue, map.GetItem(kKey));
+ EXPECT_EQ(kValue, map.GetItem(kKey2));
+
+ // When overbudget, a new value of greater size than the existing value can
+ // not be set, but a new value of lesser or equal size can be set.
+ EXPECT_TRUE(map.SetItem(kKey, kValue, nullptr));
+ EXPECT_FALSE(map.SetItem(kKey, kValue + kValue, nullptr));
+ EXPECT_TRUE(map.SetItem(kKey, "", nullptr));
+ EXPECT_EQ("", map.GetItem(kKey));
+ EXPECT_EQ(kValue, map.GetItem(kKey2));
+}
+
+TEST(StorageAreaMapTest, Iteration) {
+ const int kNumTestItems = 100;
+ const size_t kQuota = 102400; // 100K quota for this test.
+ StorageAreaMap map(kQuota);
+
+ // Fill the map with some data.
+ for (int i = 0; i < kNumTestItems; ++i)
+ EXPECT_TRUE(map.SetItem("key" + String::Number(i), "val", nullptr));
+ EXPECT_EQ(unsigned{kNumTestItems}, map.GetLength());
+
+ Vector<String> keys(kNumTestItems);
+ // Iterate over all keys.
+ for (int i = 0; i < kNumTestItems; ++i)
+ keys[i] = map.GetKey(i);
+
+ // Now iterate over some subsets, and make sure the right keys are returned.
+ for (int i = 5; i < 15; ++i)
+ EXPECT_EQ(keys[i], map.GetKey(i));
+ for (int i = kNumTestItems - 5; i >= kNumTestItems - 15; --i)
+ EXPECT_EQ(keys[i], map.GetKey(i));
+ for (int i = 20; i >= 10; --i)
+ EXPECT_EQ(keys[i], map.GetKey(i));
+ for (int i = 15; i < 20; ++i)
+ EXPECT_EQ(keys[i], map.GetKey(i));
+ for (int i = kNumTestItems - 1; i >= 0; --i)
+ EXPECT_EQ(keys[i], map.GetKey(i));
+ EXPECT_TRUE(map.GetKey(kNumTestItems).IsNull());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/storage/storage_event.cc b/chromium/third_party/blink/renderer/modules/storage/storage_event.cc
index 0bca510c489..8b2c8c07567 100644
--- a/chromium/third_party/blink/renderer/modules/storage/storage_event.cc
+++ b/chromium/third_party/blink/renderer/modules/storage/storage_event.cc
@@ -26,7 +26,7 @@
#include "third_party/blink/renderer/modules/storage/storage_event.h"
#include "third_party/blink/renderer/modules/event_modules.h"
-#include "third_party/blink/renderer/modules/storage/storage.h"
+#include "third_party/blink/renderer/modules/storage/storage_area.h"
#include "third_party/blink/renderer/modules/storage/storage_event_init.h"
namespace blink {
@@ -44,7 +44,7 @@ StorageEvent* StorageEvent::Create(const AtomicString& type,
const String& old_value,
const String& new_value,
const String& url,
- Storage* storage_area) {
+ StorageArea* storage_area) {
return new StorageEvent(type, key, old_value, new_value, url, storage_area);
}
@@ -58,7 +58,7 @@ StorageEvent::StorageEvent(const AtomicString& type,
const String& old_value,
const String& new_value,
const String& url,
- Storage* storage_area)
+ StorageArea* storage_area)
: Event(type, Bubbles::kNo, Cancelable::kNo),
key_(key),
old_value_(old_value),
@@ -88,7 +88,7 @@ void StorageEvent::initStorageEvent(const AtomicString& type,
const String& old_value,
const String& new_value,
const String& url,
- Storage* storage_area) {
+ StorageArea* storage_area) {
if (IsBeingDispatched())
return;
diff --git a/chromium/third_party/blink/renderer/modules/storage/storage_event.h b/chromium/third_party/blink/renderer/modules/storage/storage_event.h
index 4a0c43a1356..361c22fe344 100644
--- a/chromium/third_party/blink/renderer/modules/storage/storage_event.h
+++ b/chromium/third_party/blink/renderer/modules/storage/storage_event.h
@@ -32,7 +32,7 @@
namespace blink {
-class Storage;
+class StorageArea;
class StorageEventInit;
class StorageEvent final : public Event {
@@ -45,7 +45,7 @@ class StorageEvent final : public Event {
const String& old_value,
const String& new_value,
const String& url,
- Storage* storage_area);
+ StorageArea* storage_area);
static StorageEvent* Create(const AtomicString&, const StorageEventInit&);
~StorageEvent() override;
@@ -53,7 +53,7 @@ class StorageEvent final : public Event {
const String& oldValue() const { return old_value_; }
const String& newValue() const { return new_value_; }
const String& url() const { return url_; }
- Storage* storageArea() const { return storage_area_.Get(); }
+ StorageArea* storageArea() const { return storage_area_.Get(); }
void initStorageEvent(const AtomicString& type,
bool bubbles,
@@ -62,13 +62,13 @@ class StorageEvent final : public Event {
const String& old_value,
const String& new_value,
const String& url,
- Storage* storage_area);
+ StorageArea* storage_area);
// Needed once we support init<blank>EventNS
// void initStorageEventNS(in DOMString namespaceURI, in DOMString typeArg,
// in boolean canBubbleArg, in boolean cancelableArg, in DOMString keyArg,
// in DOMString oldValueArg, in DOMString newValueArg,
- // in DOMString urlArg, Storage storageAreaArg);
+ // in DOMString urlArg, StorageArea storageAreaArg);
const AtomicString& InterfaceName() const override;
@@ -81,14 +81,14 @@ class StorageEvent final : public Event {
const String& old_value,
const String& new_value,
const String& url,
- Storage* storage_area);
+ StorageArea* storage_area);
StorageEvent(const AtomicString&, const StorageEventInit&);
String key_;
String old_value_;
String new_value_;
String url_;
- Member<Storage> storage_area_;
+ Member<StorageArea> storage_area_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/storage/storage_namespace.cc b/chromium/third_party/blink/renderer/modules/storage/storage_namespace.cc
index d3e9cad700c..617817f297f 100644
--- a/chromium/third_party/blink/renderer/modules/storage/storage_namespace.cc
+++ b/chromium/third_party/blink/renderer/modules/storage/storage_namespace.cc
@@ -32,7 +32,6 @@
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_storage_area.h"
#include "third_party/blink/public/platform/web_storage_namespace.h"
-#include "third_party/blink/renderer/modules/storage/storage_area.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
namespace blink {
@@ -43,23 +42,21 @@ StorageNamespace::StorageNamespace(
StorageNamespace::~StorageNamespace() = default;
-StorageArea* StorageNamespace::LocalStorageArea(const SecurityOrigin* origin) {
+std::unique_ptr<WebStorageArea> StorageNamespace::LocalStorageArea(
+ const SecurityOrigin* origin) {
DCHECK(IsMainThread());
static std::unique_ptr<WebStorageNamespace> local_storage_namespace = nullptr;
if (!local_storage_namespace)
local_storage_namespace =
Platform::Current()->CreateLocalStorageNamespace();
- return StorageArea::Create(
- base::WrapUnique(local_storage_namespace->CreateStorageArea(
- WebSecurityOrigin(origin))),
- StorageArea::kLocalStorage);
+ return base::WrapUnique(
+ local_storage_namespace->CreateStorageArea(WebSecurityOrigin(origin)));
}
-StorageArea* StorageNamespace::GetStorageArea(const SecurityOrigin* origin) {
- return StorageArea::Create(
- base::WrapUnique(
- web_storage_namespace_->CreateStorageArea(WebSecurityOrigin(origin))),
- StorageArea::kSessionStorage);
+std::unique_ptr<WebStorageArea> StorageNamespace::GetStorageArea(
+ const SecurityOrigin* origin) {
+ return base::WrapUnique(
+ web_storage_namespace_->CreateStorageArea(WebSecurityOrigin(origin)));
}
bool StorageNamespace::IsSameNamespace(
diff --git a/chromium/third_party/blink/renderer/modules/storage/storage_namespace.h b/chromium/third_party/blink/renderer/modules/storage/storage_namespace.h
index 0b9c81c5f74..c3b3be0ebcd 100644
--- a/chromium/third_party/blink/renderer/modules/storage/storage_namespace.h
+++ b/chromium/third_party/blink/renderer/modules/storage/storage_namespace.h
@@ -27,6 +27,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_STORAGE_STORAGE_NAMESPACE_H_
#include <memory>
+#include "third_party/blink/public/platform/web_storage_area.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -34,7 +35,6 @@ namespace blink {
class WebStorageNamespace;
class SecurityOrigin;
-class StorageArea;
class MODULES_EXPORT StorageNamespace {
USING_FAST_MALLOC(StorageNamespace);
@@ -43,9 +43,10 @@ class MODULES_EXPORT StorageNamespace {
explicit StorageNamespace(std::unique_ptr<WebStorageNamespace>);
~StorageNamespace();
- static StorageArea* LocalStorageArea(const SecurityOrigin*);
+ static std::unique_ptr<WebStorageArea> LocalStorageArea(
+ const SecurityOrigin*);
+ std::unique_ptr<WebStorageArea> GetStorageArea(const SecurityOrigin*);
- StorageArea* GetStorageArea(const SecurityOrigin*);
bool IsSameNamespace(const WebStorageNamespace& session_namespace) const;
private:
diff --git a/chromium/third_party/blink/renderer/modules/storage/storage_namespace_controller.cc b/chromium/third_party/blink/renderer/modules/storage/storage_namespace_controller.cc
index 907d74e84aa..9ee5d2880ba 100644
--- a/chromium/third_party/blink/renderer/modules/storage/storage_namespace_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/storage/storage_namespace_controller.cc
@@ -18,9 +18,9 @@ namespace blink {
#define STATIC_ASSERT_MATCHING_ENUM(enum_name1, enum_name2) \
static_assert(static_cast<int>(enum_name1) == static_cast<int>(enum_name2), \
"mismatching enums: " #enum_name1)
-STATIC_ASSERT_MATCHING_ENUM(StorageArea::kLocalStorage,
+STATIC_ASSERT_MATCHING_ENUM(StorageArea::StorageType::kLocalStorage,
ContentSettingsClient::StorageType::kLocal);
-STATIC_ASSERT_MATCHING_ENUM(StorageArea::kSessionStorage,
+STATIC_ASSERT_MATCHING_ENUM(StorageArea::StorageType::kSessionStorage,
ContentSettingsClient::StorageType::kSession);
const char StorageNamespaceController::kSupplementName[] =
@@ -59,7 +59,7 @@ StorageNamespaceController::CreateSessionStorageNamespace() {
web_view_client_->GetSessionStorageNamespaceId()));
}
-bool StorageNamespaceController::CanAccessStorage(
+bool StorageNamespaceController::CanAccessStorageArea(
LocalFrame* frame,
StorageArea::StorageType type) const {
DCHECK(frame->GetContentSettingsClient());
diff --git a/chromium/third_party/blink/renderer/modules/storage/storage_namespace_controller.h b/chromium/third_party/blink/renderer/modules/storage/storage_namespace_controller.h
index 894689e05e8..b53f45859fd 100644
--- a/chromium/third_party/blink/renderer/modules/storage/storage_namespace_controller.h
+++ b/chromium/third_party/blink/renderer/modules/storage/storage_namespace_controller.h
@@ -29,7 +29,7 @@ class MODULES_EXPORT StorageNamespaceController final
StorageNamespace* SessionStorage(bool optional_create = true);
~StorageNamespaceController();
- bool CanAccessStorage(LocalFrame*, StorageArea::StorageType) const;
+ bool CanAccessStorageArea(LocalFrame*, StorageArea::StorageType) const;
static void ProvideStorageNamespaceTo(Page&, WebViewClient*);
static StorageNamespaceController* From(Page* page) {
diff --git a/chromium/third_party/blink/renderer/modules/vibration/navigator_vibration.cc b/chromium/third_party/blink/renderer/modules/vibration/navigator_vibration.cc
index 5bca0a042ce..3381c6414ac 100644
--- a/chromium/third_party/blink/renderer/modules/vibration/navigator_vibration.cc
+++ b/chromium/third_party/blink/renderer/modules/vibration/navigator_vibration.cc
@@ -94,7 +94,7 @@ bool NavigatorVibration::vibrate(Navigator& navigator,
"https://www.chromestatus.com/feature/5644273861001216.";
}
- Intervention::GenerateReport(frame, message);
+ Intervention::GenerateReport(frame, "NavigatorVibrate", message);
return false;
}
diff --git a/chromium/third_party/blink/renderer/modules/vibration/vibration_controller.cc b/chromium/third_party/blink/renderer/modules/vibration/vibration_controller.cc
index ae76aa1c906..20965e8dca3 100644
--- a/chromium/third_party/blink/renderer/modules/vibration/vibration_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/vibration/vibration_controller.cc
@@ -152,7 +152,8 @@ void VibrationController::DidVibrate() {
pattern_.EraseAt(0);
}
- timer_do_vibrate_.StartOneShot(interval / 1000.0, FROM_HERE);
+ timer_do_vibrate_.StartOneShot(TimeDelta::FromMilliseconds(interval),
+ FROM_HERE);
}
void VibrationController::Cancel() {
diff --git a/chromium/third_party/blink/renderer/modules/vr/OWNERS b/chromium/third_party/blink/renderer/modules/vr/OWNERS
index 4e35d8a0a39..042b46ff6f6 100644
--- a/chromium/third_party/blink/renderer/modules/vr/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/vr/OWNERS
@@ -1,5 +1,5 @@
bajones@chromium.org
-kbr@chromium.org
klausw@chromium.org
-# COMPONENT: Blink>WebVR
+# TEAM: xr-dev@chromium.org
+# COMPONENT: Blink>WebXR>VR
diff --git a/chromium/third_party/blink/renderer/modules/vr/PRESUBMIT.py b/chromium/third_party/blink/renderer/modules/vr/PRESUBMIT.py
new file mode 100644
index 00000000000..19d6c2c67bc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/vr/PRESUBMIT.py
@@ -0,0 +1,24 @@
+# Copyright (c) 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.
+
+"""Top-level presubmit script for third_party/blink/renderer/modules/vr.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details about the presubmit API built into depot_tools.
+"""
+
+
+def PostUploadHook(cl, change, output_api): # pylint: disable=C0103,W0613
+ """git cl upload will call this hook after the issue is created/modified.
+
+ This hook modifies the CL description in order to run extra GPU
+ tests (in particular, WebXR and WebVR browser tests) in addition
+ to the regular CQ try bots. This test suite is too large to run
+ against all Chromium commits, but should be run against changes
+ likely to affect these tests.
+ """
+ return output_api.EnsureCQIncludeTrybotsAreAdded(
+ cl,
+ ['luci.chromium.try:win_optional_gpu_tests_rel'],
+ 'Automatically added optional GPU tests to run on CQ.')
diff --git a/chromium/third_party/blink/renderer/modules/vr/navigator_vr.cc b/chromium/third_party/blink/renderer/modules/vr/navigator_vr.cc
index 0232b0957f7..815847206ee 100644
--- a/chromium/third_party/blink/renderer/modules/vr/navigator_vr.cc
+++ b/chromium/third_party/blink/renderer/modules/vr/navigator_vr.cc
@@ -6,11 +6,11 @@
#include "services/metrics/public/cpp/ukm_builders.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/web/web_frame.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/dom/exception_code.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"
@@ -32,10 +32,6 @@ namespace {
const char kFeaturePolicyBlockedMessage[] =
"Access to the feature \"vr\" is disallowed by feature policy.";
-const char kGetVRDisplaysCrossOriginBlockedMessage[] =
- "Access to navigator.getVRDisplays requires a user gesture in cross-origin "
- "embedded frames.";
-
const char kNotAssociatedWithDocumentMessage[] =
"The object is no longer associated with a document.";
@@ -121,7 +117,7 @@ ScriptPromise NavigatorVR::getVRDisplays(ScriptState* script_state,
Navigator& navigator) {
if (!navigator.GetFrame()) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kInvalidStateError,
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
kNotAssociatedWithDocumentMessage));
}
return NavigatorVR::From(navigator).getVRDisplays(script_state);
@@ -130,7 +126,7 @@ ScriptPromise NavigatorVR::getVRDisplays(ScriptState* script_state,
ScriptPromise NavigatorVR::getVRDisplays(ScriptState* script_state) {
if (!GetDocument()) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kInvalidStateError,
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
kNotAssociatedWithDocumentMessage));
}
@@ -145,31 +141,20 @@ ScriptPromise NavigatorVR::getVRDisplays(ScriptState* script_state) {
LocalFrame* frame = GetDocument()->GetFrame();
if (!frame) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kInvalidStateError,
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
kNotAssociatedWithDocumentMessage));
}
- if (IsSupportedInFeaturePolicy(mojom::FeaturePolicyFeature::kWebVr)) {
- if (!frame->IsFeatureEnabled(mojom::FeaturePolicyFeature::kWebVr)) {
- return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kSecurityError, kFeaturePolicyBlockedMessage));
- }
- } else if (!frame->HasBeenActivated() && frame->IsCrossOriginSubframe()) {
- // Before we introduced feature policy, cross-origin iframes had access to
- // WebVR APIs. Ideally, we want to block access to WebVR APIs for
- // cross-origin iframes. To be backward compatible, we changed to require a
- // user gesture for cross-origin iframes.
+ if (!frame->IsFeatureEnabled(mojom::FeaturePolicyFeature::kWebVr)) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kSecurityError,
- kGetVRDisplaysCrossOriginBlockedMessage));
+ script_state, DOMException::Create(DOMExceptionCode::kSecurityError,
+ kFeaturePolicyBlockedMessage));
}
// Similar to the restriciton above, we're going to block developers from
// using the legacy API if they've already made calls to the new API.
if (xr_) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kInvalidStateError,
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
kCannotUseBothNewAndOldAPIMessage));
}
@@ -243,7 +228,8 @@ void NavigatorVR::EnqueueVREvent(VRDisplayEvent* event) {
if (!GetSupplementable()->GetFrame())
return;
- GetSupplementable()->GetFrame()->DomWindow()->EnqueueWindowEvent(event);
+ GetSupplementable()->GetFrame()->DomWindow()->EnqueueWindowEvent(
+ event, TaskType::kMiscPlatformAPI);
}
void NavigatorVR::DispatchVREvent(VRDisplayEvent* event) {
diff --git a/chromium/third_party/blink/renderer/modules/vr/navigator_vr.idl b/chromium/third_party/blink/renderer/modules/vr/navigator_vr.idl
index 7e7fc582542..133163db0df 100644
--- a/chromium/third_party/blink/renderer/modules/vr/navigator_vr.idl
+++ b/chromium/third_party/blink/renderer/modules/vr/navigator_vr.idl
@@ -10,5 +10,5 @@
[SecureContext, OriginTrialEnabled=WebXR, MeasureAs=NavigatorXR] readonly attribute XR xr;
// Legacy API
- [OriginTrialEnabled=WebVR, CallWith=ScriptState] Promise getVRDisplays();
+ [RuntimeEnabled=WebVR, CallWith=ScriptState] Promise getVRDisplays();
};
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_controller.cc b/chromium/third_party/blink/renderer/modules/vr/vr_controller.cc
index da0e2fb0854..6805adadfc9 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_controller.cc
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_controller.cc
@@ -60,13 +60,11 @@ void VRController::SetListeningForActivate(bool listening) {
// here. Upon calling SetClient in the constructor we should receive one call
// for each VRDisplay that was already connected at the time.
void VRController::OnDisplayConnected(
- device::mojom::blink::VRMagicWindowProviderPtr magic_window_provider,
device::mojom::blink::VRDisplayHostPtr display,
device::mojom::blink::VRDisplayClientRequest request,
device::mojom::blink::VRDisplayInfoPtr display_info) {
VRDisplay* vr_display =
- new VRDisplay(navigator_vr_, std::move(magic_window_provider),
- std::move(display), std::move(request));
+ new VRDisplay(navigator_vr_, std::move(display), std::move(request));
vr_display->Update(display_info);
vr_display->OnConnected();
vr_display->FocusChanged();
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_controller.h b/chromium/third_party/blink/renderer/modules/vr/vr_controller.h
index 5d5fae9bb5e..b91a0e55d14 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_controller.h
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_controller.h
@@ -34,8 +34,7 @@ class VRController final : public GarbageCollectedFinalized<VRController>,
void GetDisplays(ScriptPromiseResolver*);
void SetListeningForActivate(bool);
- void OnDisplayConnected(device::mojom::blink::VRMagicWindowProviderPtr,
- device::mojom::blink::VRDisplayHostPtr,
+ void OnDisplayConnected(device::mojom::blink::VRDisplayHostPtr,
device::mojom::blink::VRDisplayClientRequest,
device::mojom::blink::VRDisplayInfoPtr) override;
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_display.cc b/chromium/third_party/blink/renderer/modules/vr/vr_display.cc
index 4a96315e84a..a221211fdad 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_display.cc
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_display.cc
@@ -67,17 +67,17 @@ class VRDisplayFrameRequestCallback
void Invoke(double high_res_time_ms) override {
if (Id() != vr_display_->PendingMagicWindowVSyncId())
return;
- double monotonic_time;
+ TimeTicks monotonic_time;
if (!vr_display_->GetDocument() || !vr_display_->GetDocument()->Loader()) {
- monotonic_time = WTF::CurrentTimeTicksInSeconds();
+ monotonic_time = WTF::CurrentTimeTicks();
} else {
// Convert document-zero time back to monotonic time.
- double reference_monotonic_time =
- TimeTicksInSeconds(vr_display_->GetDocument()
- ->Loader()
- ->GetTiming()
- .ReferenceMonotonicTime());
- monotonic_time = (high_res_time_ms / 1000.0) + reference_monotonic_time;
+ TimeTicks reference_monotonic_time = vr_display_->GetDocument()
+ ->Loader()
+ ->GetTiming()
+ .ReferenceMonotonicTime();
+ monotonic_time = reference_monotonic_time +
+ TimeDelta::FromMillisecondsD(high_res_time_ms);
}
vr_display_->OnMagicWindowVSync(monotonic_time);
}
@@ -95,16 +95,25 @@ class VRDisplayFrameRequestCallback
VRDisplay::VRDisplay(
NavigatorVR* navigator_vr,
- device::mojom::blink::VRMagicWindowProviderPtr magic_window_provider,
device::mojom::blink::VRDisplayHostPtr display,
device::mojom::blink::VRDisplayClientRequest request)
: PausableObject(navigator_vr->GetDocument()),
navigator_vr_(navigator_vr),
capabilities_(new VRDisplayCapabilities()),
- magic_window_provider_(std::move(magic_window_provider)),
display_(std::move(display)),
display_client_binding_(this, std::move(request)) {
PauseIfNeeded(); // Initialize SuspendabaleObject.
+
+ // Request a non-exclusive session to provide magic window.
+ device::mojom::blink::XRSessionOptionsPtr options =
+ device::mojom::blink::XRSessionOptions::New();
+ options->immersive = false;
+ // Set in_on_display_activate to true, this will prevent the request present
+ // from being logged.
+ // TODO(offenwanger): clean up the logging when refactors are complete.
+ display_->RequestSession(std::move(options), true,
+ WTF::Bind(&VRDisplay::OnMagicWindowRequestReturned,
+ WrapPersistent(this)));
}
VRDisplay::~VRDisplay() = default;
@@ -227,32 +236,38 @@ void VRDisplay::RequestVSync() {
if (display_blurred_)
return;
- if (!is_presenting_) {
+ if (is_presenting_) {
+ DCHECK(vr_presentation_provider_.is_bound());
+
+ if (pending_presenting_vsync_)
+ return;
+
+ pending_magic_window_vsync_ = false;
+ pending_presenting_vsync_ = true;
+ vr_presentation_provider_->GetFrameData(
+ WTF::Bind(&VRDisplay::OnPresentingVSync, WrapWeakPersistent(this)));
+
+ DVLOG(2) << __FUNCTION__ << " done: pending_presenting_vsync_="
+ << pending_presenting_vsync_;
+ } else {
+ // Check if magic_window_provider_, if not then we are not fully
+ // initialized, or we do not support magic window, so don't request the
+ // vsync. If and when magic_window_provider_ is set it will run this code
+ // again.
+ if (!magic_window_provider_)
+ return;
if (pending_magic_window_vsync_)
return;
magic_window_vsync_waiting_for_pose_.Reset();
magic_window_pose_request_time_ = WTF::CurrentTimeTicks();
- magic_window_provider_->GetPose(
- WTF::Bind(&VRDisplay::OnMagicWindowPose, WrapWeakPersistent(this)));
+ magic_window_provider_->GetFrameData(WTF::Bind(
+ &VRDisplay::OnMagicWindowFrameData, WrapWeakPersistent(this)));
pending_magic_window_vsync_ = true;
pending_magic_window_vsync_id_ =
doc->RequestAnimationFrame(new VRDisplayFrameRequestCallback(this));
DVLOG(2) << __FUNCTION__ << " done: pending_magic_window_vsync_="
<< pending_magic_window_vsync_;
- return;
}
- DCHECK(vr_presentation_provider_.is_bound());
-
- if (pending_presenting_vsync_)
- return;
-
- pending_magic_window_vsync_ = false;
- pending_presenting_vsync_ = true;
- vr_presentation_provider_->GetVSync(
- WTF::Bind(&VRDisplay::OnPresentingVSync, WrapWeakPersistent(this)));
-
- DVLOG(2) << __FUNCTION__
- << " done: pending_presenting_vsync_=" << pending_presenting_vsync_;
}
int VRDisplay::requestAnimationFrame(V8FrameRequestCallback* callback) {
@@ -331,8 +346,8 @@ ScriptPromise VRDisplay::requestPresent(ScriptState* script_state,
// If the VRDisplay does not advertise the ability to present reject the
// request.
if (!capabilities_->canPresent()) {
- DOMException* exception =
- DOMException::Create(kInvalidStateError, "VRDisplay cannot present.");
+ DOMException* exception = DOMException::Create(
+ DOMExceptionCode::kInvalidStateError, "VRDisplay cannot present.");
resolver->Reject(exception);
ReportPresentationResult(PresentationResult::kVRDisplayCannotPresent);
return promise;
@@ -347,8 +362,9 @@ ScriptPromise VRDisplay::requestPresent(ScriptState* script_state,
// updated.
if (first_present) {
if (!Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr)) {
- DOMException* exception = DOMException::Create(
- kInvalidStateError, "API can only be initiated by a user gesture.");
+ DOMException* exception =
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "API can only be initiated by a user gesture.");
resolver->Reject(exception);
ReportPresentationResult(PresentationResult::kNotInitiatedByUserGesture);
return promise;
@@ -363,8 +379,8 @@ ScriptPromise VRDisplay::requestPresent(ScriptState* script_state,
// A valid number of layers must be provided in order to present.
if (layers.size() == 0 || layers.size() > capabilities_->maxLayers()) {
ForceExitPresent();
- DOMException* exception =
- DOMException::Create(kInvalidStateError, "Invalid number of layers.");
+ DOMException* exception = DOMException::Create(
+ DOMExceptionCode::kInvalidStateError, "Invalid number of layers.");
resolver->Reject(exception);
ReportPresentationResult(PresentationResult::kInvalidNumberOfLayers);
return promise;
@@ -374,8 +390,8 @@ ScriptPromise VRDisplay::requestPresent(ScriptState* script_state,
// previous, valid source, so delay m_layer reassignment
if (layers[0].source().IsNull()) {
ForceExitPresent();
- DOMException* exception =
- DOMException::Create(kInvalidStateError, "Invalid layer source.");
+ DOMException* exception = DOMException::Create(
+ DOMExceptionCode::kInvalidStateError, "Invalid layer source.");
resolver->Reject(exception);
ReportPresentationResult(PresentationResult::kInvalidLayerSource);
return promise;
@@ -394,8 +410,9 @@ ScriptPromise VRDisplay::requestPresent(ScriptState* script_state,
if (!rendering_context || !rendering_context->Is3d()) {
ForceExitPresent();
- DOMException* exception = DOMException::Create(
- kInvalidStateError, "Layer source must have a WebGLRenderingContext");
+ DOMException* exception =
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Layer source must have a WebGLRenderingContext");
resolver->Reject(exception);
ReportPresentationResult(
PresentationResult::kLayerSourceMissingWebGLContext);
@@ -410,7 +427,7 @@ ScriptPromise VRDisplay::requestPresent(ScriptState* script_state,
(layer_.rightBounds().size() != 0 && layer_.rightBounds().size() != 4)) {
ForceExitPresent();
DOMException* exception = DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Layer bounds must either be an empty array or have 4 values");
resolver->Reject(exception);
ReportPresentationResult(PresentationResult::kInvalidLayerBounds);
@@ -420,8 +437,9 @@ ScriptPromise VRDisplay::requestPresent(ScriptState* script_state,
for (float value : layer_.leftBounds()) {
if (std::isnan(value)) {
ForceExitPresent();
- DOMException* exception = DOMException::Create(
- kInvalidStateError, "Layer bounds must not contain NAN values");
+ DOMException* exception =
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Layer bounds must not contain NAN values");
resolver->Reject(exception);
ReportPresentationResult(PresentationResult::kInvalidLayerBounds);
return promise;
@@ -431,8 +449,9 @@ ScriptPromise VRDisplay::requestPresent(ScriptState* script_state,
for (float value : layer_.rightBounds()) {
if (std::isnan(value)) {
ForceExitPresent();
- DOMException* exception = DOMException::Create(
- kInvalidStateError, "Layer bounds must not contain NAN values");
+ DOMException* exception =
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Layer bounds must not contain NAN values");
resolver->Reject(exception);
ReportPresentationResult(PresentationResult::kInvalidLayerBounds);
return promise;
@@ -447,29 +466,25 @@ ScriptPromise VRDisplay::requestPresent(ScriptState* script_state,
} else if (first_present) {
if (!display_) {
ForceExitPresent();
- DOMException* exception = DOMException::Create(
- kInvalidStateError, "The service is no longer active.");
+ DOMException* exception =
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "The service is no longer active.");
resolver->Reject(exception);
return promise;
}
pending_present_resolvers_.push_back(resolver);
- frame_transport_ = new XRFrameTransport();
- // Set up RequestPresentOptions based on canvas properties.
- device::mojom::blink::VRRequestPresentOptionsPtr options =
- device::mojom::blink::VRRequestPresentOptions::New();
- options->preserve_drawing_buffer =
- rendering_context_->CreationAttributes().preserve_drawing_buffer;
-
- display_->RequestPresent(
- frame_transport_->GetSubmitFrameClient(),
- mojo::MakeRequest(&vr_presentation_provider_), std::move(options),
- in_display_activate_,
- WTF::Bind(&VRDisplay::OnPresentComplete, WrapPersistent(this)));
- vr_presentation_provider_.set_connection_error_handler(
- WTF::Bind(&VRDisplay::OnPresentationProviderConnectionError,
- WrapWeakPersistent(this)));
+ // Set up the VR backwards compatible XRSessionOptions based on canvas
+ // properties.
+ device::mojom::blink::XRSessionOptionsPtr options =
+ device::mojom::blink::XRSessionOptions::New();
+ options->immersive = true;
+ options->use_legacy_webvr_render_path = true;
+
+ display_->RequestSession(
+ std::move(options), in_display_activate_,
+ WTF::Bind(&VRDisplay::OnRequestSessionReturned, WrapPersistent(this)));
pending_present_request_ = true;
// The old vr_presentation_provider_ won't be delivering any vsyncs anymore,
@@ -484,17 +499,26 @@ ScriptPromise VRDisplay::requestPresent(ScriptState* script_state,
return promise;
}
-void VRDisplay::OnPresentComplete(
- bool success,
- device::mojom::blink::VRDisplayFrameTransportOptionsPtr transport_options) {
- frame_transport_->SetTransportOptions(std::move(transport_options));
+void VRDisplay::OnRequestSessionReturned(
+ device::mojom::blink::XRSessionPtr session) {
pending_present_request_ = false;
- if (success) {
+ if (session && session->connection) {
+ vr_presentation_provider_.Bind(std::move(session->connection->provider));
+ vr_presentation_provider_.set_connection_error_handler(
+ WTF::Bind(&VRDisplay::OnPresentationProviderConnectionError,
+ WrapWeakPersistent(this)));
+
+ frame_transport_ = new XRFrameTransport();
+ frame_transport_->BindSubmitFrameClient(
+ std::move(session->connection->client_request));
+ frame_transport_->SetTransportOptions(
+ std::move(session->connection->transport_options));
+
this->BeginPresent();
} else {
this->ForceExitPresent();
DOMException* exception = DOMException::Create(
- kNotAllowedError, "Presentation request was denied.");
+ DOMExceptionCode::kNotAllowedError, "Presentation request was denied.");
while (!pending_present_resolvers_.IsEmpty()) {
ScriptPromiseResolver* resolver = pending_present_resolvers_.TakeFirst();
@@ -503,6 +527,16 @@ void VRDisplay::OnPresentComplete(
}
}
+void VRDisplay::OnMagicWindowRequestReturned(
+ device::mojom::blink::XRSessionPtr session) {
+ if (!session || !session->magic_window_provider) {
+ // System does not support any kind of magic window.
+ return;
+ }
+ magic_window_provider_.Bind(std::move(session->magic_window_provider));
+ RequestVSync();
+}
+
ScriptPromise VRDisplay::exitPresent(ScriptState* script_state) {
DVLOG(1) << __FUNCTION__;
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
@@ -511,14 +545,14 @@ ScriptPromise VRDisplay::exitPresent(ScriptState* script_state) {
if (!is_presenting_) {
// Can't stop presenting if we're not presenting.
DOMException* exception = DOMException::Create(
- kInvalidStateError, "VRDisplay is not presenting.");
+ DOMExceptionCode::kInvalidStateError, "VRDisplay is not presenting.");
resolver->Reject(exception);
return promise;
}
if (!display_) {
- DOMException* exception =
- DOMException::Create(kInvalidStateError, "VRService is not available.");
+ DOMException* exception = DOMException::Create(
+ DOMExceptionCode::kInvalidStateError, "VRService is not available.");
resolver->Reject(exception);
return promise;
}
@@ -536,14 +570,16 @@ void VRDisplay::BeginPresent() {
DOMException* exception = nullptr;
if (!frame_transport_) {
- exception = DOMException::Create(
- kInvalidStateError, "VRDisplay presentation path not configured.");
+ exception =
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "VRDisplay presentation path not configured.");
}
if (layer_.source().IsOffscreenCanvas()) {
// TODO(junov, crbug.com/695497): Implement OffscreenCanvas presentation
- exception = DOMException::Create(
- kInvalidStateError, "OffscreenCanvas presentation not implemented.");
+ exception =
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "OffscreenCanvas presentation not implemented.");
} else {
// A canvas must be either Offscreen or plain HTMLCanvas.
DCHECK(layer_.source().IsHTMLCanvasElement());
@@ -575,7 +611,7 @@ void VRDisplay::BeginPresent() {
}
is_presenting_ = true;
// Call RequestVSync to switch from the (internal) document rAF to the
- // VrPresentationProvider VSync.
+ // VrPresentationProvider GetFrameData rate.
RequestVSync();
ReportPresentationResult(PresentationResult::kSuccess);
@@ -591,7 +627,7 @@ void VRDisplay::BeginPresent() {
// Run window.rAF once manually so that applications get a chance to
// schedule a VRDisplay.rAF in case they do so only while presenting.
if (!pending_vrdisplay_raf_ && !capabilities_->hasExternalDisplay()) {
- double timestamp = WTF::CurrentTimeTicksInSeconds();
+ TimeTicks timestamp = WTF::CurrentTimeTicks();
Platform::Current()->CurrentThread()->GetTaskRunner()->PostTask(
FROM_HERE, WTF::Bind(&VRDisplay::ProcessScheduledWindowAnimations,
WrapWeakPersistent(this), timestamp));
@@ -838,7 +874,7 @@ void VRDisplay::OnDeactivate(
EventTypeNames::vrdisplaydeactivate, this, reason));
}
-void VRDisplay::ProcessScheduledWindowAnimations(double timestamp) {
+void VRDisplay::ProcessScheduledWindowAnimations(TimeTicks timestamp) {
TRACE_EVENT1("gpu", "VRDisplay::window.rAF", "frame", vr_frame_id_);
auto* doc = navigator_vr_->GetDocument();
if (!doc)
@@ -849,8 +885,7 @@ void VRDisplay::ProcessScheduledWindowAnimations(double timestamp) {
bool had_pending_vrdisplay_raf = pending_vrdisplay_raf_;
// TODO(klausw): update timestamp based on scheduling delay?
- page->Animator().ServiceScriptedAnimations(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(timestamp));
+ page->Animator().ServiceScriptedAnimations(timestamp);
if (had_pending_vrdisplay_raf != pending_vrdisplay_raf_) {
DVLOG(1) << __FUNCTION__
@@ -868,7 +903,7 @@ void VRDisplay::ProcessScheduledWindowAnimations(double timestamp) {
}
}
-void VRDisplay::ProcessScheduledAnimations(double timestamp) {
+void VRDisplay::ProcessScheduledAnimations(TimeTicks timestamp) {
DVLOG(2) << __FUNCTION__;
// Check if we still have a valid context, the animation controller
// or document may have disappeared since we scheduled this.
@@ -894,8 +929,7 @@ void VRDisplay::ProcessScheduledAnimations(double timestamp) {
base::AutoReset<bool> animating(&in_animation_frame_, true);
pending_vrdisplay_raf_ = false;
did_submit_this_frame_ = false;
- scripted_animation_controller_->ServiceScriptedAnimations(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(timestamp));
+ scripted_animation_controller_->ServiceScriptedAnimations(timestamp);
// If presenting and the script didn't call SubmitFrame, let the device
// side know so that it can cleanly reuse resources and make appropriate
// timing decisions. Note that is_presenting_ could become false during
@@ -920,17 +954,10 @@ void VRDisplay::ProcessScheduledAnimations(double timestamp) {
}
void VRDisplay::OnPresentingVSync(
- device::mojom::blink::VRPosePtr pose,
- WTF::TimeDelta time_delta,
- int16_t frame_id,
- device::mojom::blink::VRPresentationProvider::VSyncStatus status,
- const base::Optional<gpu::MailboxHolder>& buffer_holder) {
+ device::mojom::blink::XRFrameDataPtr frame_data) {
TRACE_EVENT0("gpu", __FUNCTION__);
- switch (status) {
- case device::mojom::blink::VRPresentationProvider::VSyncStatus::SUCCESS:
- break;
- case device::mojom::blink::VRPresentationProvider::VSyncStatus::CLOSING:
- return;
+ if (!frame_data) {
+ return;
}
if (!context_gl_) {
@@ -943,8 +970,8 @@ void VRDisplay::OnPresentingVSync(
// an early exit woud break animation.
pending_presenting_vsync_ = false;
- frame_pose_ = std::move(pose);
- vr_frame_id_ = frame_id;
+ frame_pose_ = std::move(frame_data->pose);
+ vr_frame_id_ = frame_data->frame_id;
if (frame_transport_ && frame_transport_->DrawingIntoSharedBuffer()) {
NOTIMPLEMENTED();
@@ -960,10 +987,11 @@ void VRDisplay::OnPresentingVSync(
// the interface being waited on.
Platform::Current()->CurrentThread()->GetTaskRunner()->PostTask(
FROM_HERE, WTF::Bind(&VRDisplay::ProcessScheduledAnimations,
- WrapWeakPersistent(this), time_delta.InSecondsF()));
+ WrapWeakPersistent(this),
+ TimeTicks() + frame_data->time_delta));
}
-void VRDisplay::OnMagicWindowVSync(double timestamp) {
+void VRDisplay::OnMagicWindowVSync(TimeTicks timestamp) {
DVLOG(2) << __FUNCTION__;
pending_magic_window_vsync_ = false;
pending_magic_window_vsync_id_ = -1;
@@ -988,12 +1016,15 @@ void VRDisplay::OnMagicWindowVSync(double timestamp) {
}
}
-void VRDisplay::OnMagicWindowPose(device::mojom::blink::VRPosePtr pose) {
+void VRDisplay::OnMagicWindowFrameData(
+ device::mojom::blink::XRFrameDataPtr data) {
magic_window_pose_received_time_ = WTF::CurrentTimeTicks();
- if (!in_animation_frame_) {
- frame_pose_ = std::move(pose);
- } else {
- pending_pose_ = std::move(pose);
+ if (data) {
+ if (!in_animation_frame_) {
+ frame_pose_ = std::move(data->pose);
+ } else {
+ pending_pose_ = std::move(data->pose);
+ }
}
if (magic_window_vsync_waiting_for_pose_) {
// We have a vsync waiting for a pose, run it now.
@@ -1081,9 +1112,4 @@ void VRDisplay::Trace(blink::Visitor* visitor) {
ContextLifecycleObserver::Trace(visitor);
}
-void VRDisplay::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(scripted_animation_controller_);
- EventTargetWithInlineData::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_display.h b/chromium/third_party/blink/renderer/modules/vr/vr_display.h
index bb8a16d7eed..bfd146986b0 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_display.h
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_display.h
@@ -51,7 +51,8 @@ class VRDisplay final : public EventTargetWithInlineData,
public:
~VRDisplay() override;
- unsigned displayId() const { return display_id_; }
+ // We hand out at most one VRDisplay, so hardcode displayId to 1.
+ unsigned displayId() const { return 1; }
const String& displayName() const { return display_name_; }
VRDisplayCapabilities* capabilities() const { return capabilities_; }
@@ -98,17 +99,15 @@ class VRDisplay final : public EventTargetWithInlineData,
void FocusChanged();
- void OnMagicWindowVSync(double timestamp);
+ void OnMagicWindowVSync(TimeTicks timestamp);
int PendingMagicWindowVSyncId() { return pending_magic_window_vsync_id_; }
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
protected:
friend class VRController;
VRDisplay(NavigatorVR*,
- device::mojom::blink::VRMagicWindowProviderPtr,
device::mojom::blink::VRDisplayHostPtr,
device::mojom::blink::VRDisplayClientRequest);
@@ -124,9 +123,8 @@ class VRDisplay final : public EventTargetWithInlineData,
VRController* Controller();
private:
- void OnPresentComplete(
- bool success,
- device::mojom::blink::VRDisplayFrameTransportOptionsPtr);
+ void OnRequestSessionReturned(device::mojom::blink::XRSessionPtr session);
+ void OnMagicWindowRequestReturned(device::mojom::blink::XRSessionPtr session);
void OnConnected();
void OnDisconnected();
@@ -144,21 +142,16 @@ class VRDisplay final : public EventTargetWithInlineData,
OnActivateCallback on_handled) override;
void OnDeactivate(device::mojom::blink::VRDisplayEventReason) override;
- void OnPresentingVSync(
- device::mojom::blink::VRPosePtr,
- WTF::TimeDelta,
- int16_t frame_id,
- device::mojom::blink::VRPresentationProvider::VSyncStatus,
- const base::Optional<gpu::MailboxHolder>& buffer_holder);
+ void OnPresentingVSync(device::mojom::blink::XRFrameDataPtr);
void OnPresentationProviderConnectionError();
- void OnMagicWindowPose(device::mojom::blink::VRPosePtr);
+ void OnMagicWindowFrameData(device::mojom::blink::XRFrameDataPtr);
bool FocusedOrPresenting();
ScriptedAnimationController& EnsureScriptedAnimationController(Document*);
- void ProcessScheduledAnimations(double timestamp);
- void ProcessScheduledWindowAnimations(double timestamp);
+ void ProcessScheduledAnimations(TimeTicks timestamp);
+ void ProcessScheduledWindowAnimations(TimeTicks timestamp);
// Request delivery of a VSync event for either magic window mode or
// presenting mode as applicable. May be called more than once per frame, it
@@ -182,7 +175,7 @@ class VRDisplay final : public EventTargetWithInlineData,
device::mojom::blink::VRPosePtr frame_pose_;
device::mojom::blink::VRPosePtr pending_pose_;
- // Set to true between OnActivate and RequestPresent to indicate that we're in
+ // Set to true between OnActivate and requestPresent to indicate that we're in
// a display activation state.
bool in_display_activate_ = false;
@@ -225,6 +218,7 @@ class VRDisplay final : public EventTargetWithInlineData,
bool did_log_requestPresent_ = false;
device::mojom::blink::VRMagicWindowProviderPtr magic_window_provider_;
+
device::mojom::blink::VRDisplayHostPtr display_;
bool present_image_needs_copy_ = false;
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_display.idl b/chromium/third_party/blink/renderer/modules/vr/vr_display.idl
index 026d6ce8317..207643036ba 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_display.idl
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_display.idl
@@ -10,7 +10,7 @@ enum VREye {
// https://w3c.github.io/webvr/#interface-vrdisplay
[
ActiveScriptWrappable,
- OriginTrialEnabled=WebVR
+ RuntimeEnabled=WebVR
] interface VRDisplay : EventTarget {
// An identifier for this device unique across VRDisplays.
readonly attribute unsigned long displayId;
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_display_capabilities.idl b/chromium/third_party/blink/renderer/modules/vr/vr_display_capabilities.idl
index 14d8265674a..78cd1f5eca0 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_display_capabilities.idl
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_display_capabilities.idl
@@ -4,7 +4,7 @@
// https://w3c.github.io/webvr/#interface-vrdisplaycapabilities
[
- OriginTrialEnabled=WebVR
+ RuntimeEnabled=WebVR
] interface VRDisplayCapabilities {
// Whether or not the VR display is capable of reporting user position.
// If false position may still be reported using simulated values like
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_display_event.idl b/chromium/third_party/blink/renderer/modules/vr/vr_display_event.idl
index ae9103af393..56272794a5c 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_display_event.idl
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_display_event.idl
@@ -12,7 +12,7 @@ enum VRDisplayEventReason {
// https://w3c.github.io/webvr/#interface-vrdisplayevent
[
- OriginTrialEnabled=WebVR,
+ RuntimeEnabled=WebVR,
Constructor(DOMString type, optional VRDisplayEventInit eventInitDict)
] interface VRDisplayEvent : Event {
readonly attribute VRDisplay display;
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_eye_parameters.idl b/chromium/third_party/blink/renderer/modules/vr/vr_eye_parameters.idl
index 7b5b630e1d2..4da215cefc0 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_eye_parameters.idl
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_eye_parameters.idl
@@ -4,7 +4,7 @@
// https://w3c.github.io/webvr/#interface-vreyeparameters
[
- OriginTrialEnabled=WebVR
+ RuntimeEnabled=WebVR
] interface VREyeParameters {
/* These values will vary after a FOV has been set */
[DeprecateAs=VREyeParametersOffset] readonly attribute Float32Array offset;
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_frame_data.idl b/chromium/third_party/blink/renderer/modules/vr/vr_frame_data.idl
index 5d1f3484ea7..9df122c1159 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_frame_data.idl
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_frame_data.idl
@@ -4,7 +4,7 @@
// https://w3c.github.io/webvr/#interface-vrframedata
[
- OriginTrialEnabled=WebVR,
+ RuntimeEnabled=WebVR,
Constructor
] interface VRFrameData {
readonly attribute Float32Array leftProjectionMatrix;
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_pose.idl b/chromium/third_party/blink/renderer/modules/vr/vr_pose.idl
index e935c5fe015..e8dcd6349c0 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_pose.idl
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_pose.idl
@@ -4,7 +4,7 @@
// https://w3c.github.io/webvr/#interface-vrpose
[
- OriginTrialEnabled=WebVR
+ RuntimeEnabled=WebVR
] interface VRPose {
readonly attribute Float32Array? position;
[MeasureAs=VRPoseLinearVelocity] readonly attribute Float32Array? linearVelocity;
diff --git a/chromium/third_party/blink/renderer/modules/vr/vr_stage_parameters.idl b/chromium/third_party/blink/renderer/modules/vr/vr_stage_parameters.idl
index 458582f9ba8..562c9b5a2f2 100644
--- a/chromium/third_party/blink/renderer/modules/vr/vr_stage_parameters.idl
+++ b/chromium/third_party/blink/renderer/modules/vr/vr_stage_parameters.idl
@@ -4,7 +4,7 @@
// https://w3c.github.io/webvr/#interface-vrstageparameters
[
- OriginTrialEnabled=WebVR
+ RuntimeEnabled=WebVR
] interface VRStageParameters {
// A 16 element array containing the components of a 4x4 transform
// matrix. This matrix transforms the sitting space position
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/DEPS b/chromium/third_party/blink/renderer/modules/webaudio/DEPS
index 5011e3e1c62..700b540d84f 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/DEPS
+++ b/chromium/third_party/blink/renderer/modules/webaudio/DEPS
@@ -1,4 +1,6 @@
include_rules = [
+ "+services/metrics/public/cpp/ukm_builders.h",
+ "+services/metrics/public/cpp/ukm_recorder.h",
"-third_party/blink/renderer/modules",
"+third_party/blink/renderer/modules/event_modules.h",
"+third_party/blink/renderer/modules/event_target_modules.h",
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/analyser_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/analyser_node.cc
index d90c8434c24..f1567e169b2 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/analyser_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/analyser_node.cc
@@ -23,13 +23,13 @@
* DAMAGE.
*/
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/webaudio/analyser_node.h"
+
#include "third_party/blink/renderer/modules/webaudio/analyser_options.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_input.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -81,7 +81,7 @@ void AnalyserHandler::SetFftSize(unsigned size,
ExceptionState& exception_state) {
if (!analyser_.SetFftSize(size)) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
(size < RealtimeAnalyser::kMinFFTSize ||
size > RealtimeAnalyser::kMaxFFTSize)
? ExceptionMessages::IndexOutsideRange(
@@ -100,8 +100,9 @@ void AnalyserHandler::SetMinDecibels(double k,
analyser_.SetMinDecibels(k);
} else {
exception_state.ThrowDOMException(
- kIndexSizeError, ExceptionMessages::IndexExceedsMaximumBound(
- "minDecibels", k, MaxDecibels()));
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexExceedsMaximumBound("minDecibels", k,
+ MaxDecibels()));
}
}
@@ -111,8 +112,9 @@ void AnalyserHandler::SetMaxDecibels(double k,
analyser_.SetMaxDecibels(k);
} else {
exception_state.ThrowDOMException(
- kIndexSizeError, ExceptionMessages::IndexExceedsMinimumBound(
- "maxDecibels", k, MinDecibels()));
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexExceedsMinimumBound("maxDecibels", k,
+ MinDecibels()));
}
}
@@ -121,9 +123,10 @@ void AnalyserHandler::SetMinMaxDecibels(double min_decibels,
ExceptionState& exception_state) {
if (min_decibels >= max_decibels) {
exception_state.ThrowDOMException(
- kIndexSizeError, "maxDecibels (" + String::Number(max_decibels) +
- ") must be greater than or equal to minDecibels " +
- "( " + String::Number(min_decibels) + ").");
+ DOMExceptionCode::kIndexSizeError,
+ "maxDecibels (" + String::Number(max_decibels) +
+ ") must be greater than or equal to minDecibels " + "( " +
+ String::Number(min_decibels) + ").");
return;
}
analyser_.SetMinDecibels(min_decibels);
@@ -137,14 +140,14 @@ void AnalyserHandler::SetSmoothingTimeConstant(
analyser_.SetSmoothingTimeConstant(k);
} else {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
ExceptionMessages::IndexOutsideRange(
"smoothing value", k, 0.0, ExceptionMessages::kInclusiveBound, 1.0,
ExceptionMessages::kInclusiveBound));
}
}
-void AnalyserHandler::UpdatePullStatus() {
+void AnalyserHandler::UpdatePullStatusIfNeeded() {
DCHECK(Context()->IsGraphOwner());
if (Output(0).IsConnected()) {
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/analyser_node.h b/chromium/third_party/blink/renderer/modules/webaudio/analyser_node.h
index 377679c8815..3b805158e30 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/analyser_node.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/analyser_node.h
@@ -80,7 +80,7 @@ class AnalyserHandler final : public AudioBasicInspectorHandler {
// because the node must get pulled even if there are no inputs or
// outputs so that the internal state is properly updated with the
// correct time data.
- void UpdatePullStatus() override;
+ void UpdatePullStatusIfNeeded() override;
bool RequiresTailProcessing() const final;
double TailTime() const final;
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/async_audio_decoder.cc b/chromium/third_party/blink/renderer/modules/webaudio/async_audio_decoder.cc
index bd1da12c37d..d5287d2b31a 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/async_audio_decoder.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/async_audio_decoder.cc
@@ -27,13 +27,14 @@
#include "base/location.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/modules/webaudio/audio_buffer.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
#include "third_party/blink/renderer/platform/audio/audio_bus.h"
#include "third_party/blink/renderer/platform/audio/audio_file_reader.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
-#include "third_party/blink/renderer/platform/threading/background_task_runner.h"
+#include "third_party/blink/renderer/platform/scheduler/public/background_scheduler.h"
#include "third_party/blink/renderer/platform/web_task_runner.h"
namespace blink {
@@ -50,7 +51,7 @@ void AsyncAudioDecoder::DecodeAsync(
if (!audio_data)
return;
- BackgroundTaskRunner::PostOnBackgroundThread(
+ BackgroundScheduler::PostOnBackgroundThread(
FROM_HERE,
CrossThreadBind(&AsyncAudioDecoder::DecodeOnBackgroundThread,
WrapCrossThreadPersistent(audio_data), sample_rate,
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_basic_inspector_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_basic_inspector_node.cc
index d7f02ffd28c..0320632587c 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_basic_inspector_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_basic_inspector_node.cc
@@ -50,30 +50,6 @@ void AudioBasicInspectorHandler::PullInputs(size_t frames_to_process) {
Input(0).Pull(Output(0).Bus(), frames_to_process);
}
-AudioNode* AudioBasicInspectorNode::connect(AudioNode* destination,
- unsigned output_index,
- unsigned input_index,
- ExceptionState& exception_state) {
- DCHECK(IsMainThread());
-
- BaseAudioContext::GraphAutoLocker locker(context());
-
- AudioNode::connect(destination, output_index, input_index, exception_state);
- static_cast<AudioBasicInspectorHandler&>(Handler()).UpdatePullStatus();
-
- return destination;
-}
-
-void AudioBasicInspectorNode::disconnect(unsigned output_index,
- ExceptionState& exception_state) {
- DCHECK(IsMainThread());
-
- BaseAudioContext::GraphAutoLocker locker(context());
-
- AudioNode::disconnect(output_index, exception_state);
- static_cast<AudioBasicInspectorHandler&>(Handler()).UpdatePullStatus();
-}
-
void AudioBasicInspectorHandler::CheckNumberOfChannelsForInput(
AudioNodeInput* input) {
DCHECK(Context()->IsAudioThread());
@@ -93,10 +69,10 @@ void AudioBasicInspectorHandler::CheckNumberOfChannelsForInput(
AudioHandler::CheckNumberOfChannelsForInput(input);
- UpdatePullStatus();
+ UpdatePullStatusIfNeeded();
}
-void AudioBasicInspectorHandler::UpdatePullStatus() {
+void AudioBasicInspectorHandler::UpdatePullStatusIfNeeded() {
DCHECK(Context()->IsGraphOwner());
if (Output(0).IsConnected()) {
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_basic_inspector_node.h b/chromium/third_party/blink/renderer/modules/webaudio/audio_basic_inspector_node.h
index 68af198b837..eaaf754ef94 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_basic_inspector_node.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_basic_inspector_node.h
@@ -30,9 +30,6 @@
namespace blink {
-class BaseAudioContext;
-class ExceptionState;
-
// AudioBasicInspectorNode is an AudioNode with one input and one output where
// the output might not necessarily connect to another node's input.
// If the output is not connected to any other node, then the
@@ -54,7 +51,7 @@ class AudioBasicInspectorHandler : public AudioHandler {
double TailTime() const override { return 0; }
double LatencyTime() const override { return 0; }
- virtual void UpdatePullStatus();
+ void UpdatePullStatusIfNeeded() override;
protected:
// When setting to true, AudioBasicInspectorHandler will be pulled
@@ -66,15 +63,6 @@ class AudioBasicInspectorNode : public AudioNode {
protected:
explicit AudioBasicInspectorNode(BaseAudioContext& context)
: AudioNode(context) {}
-
- private:
- // TODO(tkent): Should AudioBasicInspectorNode override other variants of
- // connect() and disconnect()?
- AudioNode* connect(AudioNode*,
- unsigned output_index,
- unsigned input_index,
- ExceptionState&) final;
- void disconnect(unsigned output_index, ExceptionState&) final;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_buffer.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_buffer.cc
index 71da68ca003..e3133cde0da 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_buffer.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_buffer.cc
@@ -28,14 +28,13 @@
#include "third_party/blink/renderer/modules/webaudio/audio_buffer.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/webaudio/audio_buffer_options.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
#include "third_party/blink/renderer/platform/audio/audio_bus.h"
#include "third_party/blink/renderer/platform/audio/audio_file_reader.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/typed_arrays/float32_array.h"
namespace blink {
@@ -63,28 +62,30 @@ AudioBuffer* AudioBuffer::Create(unsigned number_of_channels,
if (!number_of_channels ||
number_of_channels > BaseAudioContext::MaxNumberOfChannels()) {
exception_state.ThrowDOMException(
- kNotSupportedError, ExceptionMessages::IndexOutsideRange(
- "number of channels", number_of_channels, 1u,
- ExceptionMessages::kInclusiveBound,
- BaseAudioContext::MaxNumberOfChannels(),
- ExceptionMessages::kInclusiveBound));
+ DOMExceptionCode::kNotSupportedError,
+ ExceptionMessages::IndexOutsideRange(
+ "number of channels", number_of_channels, 1u,
+ ExceptionMessages::kInclusiveBound,
+ BaseAudioContext::MaxNumberOfChannels(),
+ ExceptionMessages::kInclusiveBound));
return nullptr;
}
if (!AudioUtilities::IsValidAudioBufferSampleRate(sample_rate)) {
exception_state.ThrowDOMException(
- kNotSupportedError, ExceptionMessages::IndexOutsideRange(
- "sample rate", sample_rate,
- AudioUtilities::MinAudioBufferSampleRate(),
- ExceptionMessages::kInclusiveBound,
- AudioUtilities::MaxAudioBufferSampleRate(),
- ExceptionMessages::kInclusiveBound));
+ DOMExceptionCode::kNotSupportedError,
+ ExceptionMessages::IndexOutsideRange(
+ "sample rate", sample_rate,
+ AudioUtilities::MinAudioBufferSampleRate(),
+ ExceptionMessages::kInclusiveBound,
+ AudioUtilities::MaxAudioBufferSampleRate(),
+ ExceptionMessages::kInclusiveBound));
return nullptr;
}
if (!number_of_frames) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
ExceptionMessages::IndexExceedsMinimumBound(
"number of frames", number_of_frames, static_cast<size_t>(0)));
return nullptr;
@@ -95,10 +96,10 @@ AudioBuffer* AudioBuffer::Create(unsigned number_of_channels,
if (!audio_buffer) {
exception_state.ThrowDOMException(
- kNotSupportedError, "createBuffer(" +
- String::Number(number_of_channels) + ", " +
- String::Number(number_of_frames) + ", " +
- String::Number(sample_rate) + ") failed.");
+ DOMExceptionCode::kNotSupportedError,
+ "createBuffer(" + String::Number(number_of_channels) + ", " +
+ String::Number(number_of_frames) + ", " +
+ String::Number(sample_rate) + ") failed.");
}
return audio_buffer;
@@ -224,9 +225,10 @@ NotShared<DOMFloat32Array> AudioBuffer::getChannelData(
ExceptionState& exception_state) {
if (channel_index >= channels_.size()) {
exception_state.ThrowDOMException(
- kIndexSizeError, "channel index (" + String::Number(channel_index) +
- ") exceeds number of channels (" +
- String::Number(channels_.size()) + ")");
+ DOMExceptionCode::kIndexSizeError,
+ "channel index (" + String::Number(channel_index) +
+ ") exceeds number of channels (" +
+ String::Number(channels_.size()) + ")");
return NotShared<DOMFloat32Array>(nullptr);
}
@@ -253,11 +255,12 @@ void AudioBuffer::copyFromChannel(NotShared<DOMFloat32Array> destination,
if (channel_number < 0 ||
channel_number >= static_cast<long>(channels_.size())) {
exception_state.ThrowDOMException(
- kIndexSizeError, ExceptionMessages::IndexOutsideRange(
- "channelNumber", channel_number, 0L,
- ExceptionMessages::kInclusiveBound,
- static_cast<long>(channels_.size() - 1),
- ExceptionMessages::kInclusiveBound));
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexOutsideRange(
+ "channelNumber", channel_number, 0L,
+ ExceptionMessages::kInclusiveBound,
+ static_cast<long>(channels_.size() - 1),
+ ExceptionMessages::kInclusiveBound));
return;
}
@@ -266,11 +269,12 @@ void AudioBuffer::copyFromChannel(NotShared<DOMFloat32Array> destination,
if (start_in_channel >= channel_data->length()) {
exception_state.ThrowDOMException(
- kIndexSizeError, ExceptionMessages::IndexOutsideRange(
- "startInChannel", start_in_channel, 0UL,
- ExceptionMessages::kInclusiveBound,
- static_cast<unsigned long>(channel_data->length()),
- ExceptionMessages::kExclusiveBound));
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexOutsideRange(
+ "startInChannel", start_in_channel, 0UL,
+ ExceptionMessages::kInclusiveBound,
+ static_cast<unsigned long>(channel_data->length()),
+ ExceptionMessages::kExclusiveBound));
return;
}
@@ -300,11 +304,12 @@ void AudioBuffer::copyToChannel(NotShared<DOMFloat32Array> source,
if (channel_number < 0 ||
channel_number >= static_cast<long>(channels_.size())) {
exception_state.ThrowDOMException(
- kIndexSizeError, ExceptionMessages::IndexOutsideRange(
- "channelNumber", channel_number, 0L,
- ExceptionMessages::kInclusiveBound,
- static_cast<long>(channels_.size() - 1),
- ExceptionMessages::kInclusiveBound));
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexOutsideRange(
+ "channelNumber", channel_number, 0L,
+ ExceptionMessages::kInclusiveBound,
+ static_cast<long>(channels_.size() - 1),
+ ExceptionMessages::kInclusiveBound));
return;
}
@@ -312,11 +317,12 @@ void AudioBuffer::copyToChannel(NotShared<DOMFloat32Array> source,
if (start_in_channel >= channel_data->length()) {
exception_state.ThrowDOMException(
- kIndexSizeError, ExceptionMessages::IndexOutsideRange(
- "startInChannel", start_in_channel, 0UL,
- ExceptionMessages::kInclusiveBound,
- static_cast<unsigned long>(channel_data->length()),
- ExceptionMessages::kExclusiveBound));
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexOutsideRange(
+ "startInChannel", start_in_channel, 0UL,
+ ExceptionMessages::kInclusiveBound,
+ static_cast<unsigned long>(channel_data->length()),
+ ExceptionMessages::kExclusiveBound));
return;
}
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.cc
index 68990d10fa7..8f7d4cbdab0 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.cc
@@ -24,15 +24,15 @@
*/
#include <algorithm>
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.h"
#include "third_party/blink/renderer/modules/webaudio/audio_buffer_source_options.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
namespace blink {
@@ -383,7 +383,7 @@ void AudioBufferSourceHandler::SetBuffer(AudioBuffer* buffer,
DCHECK(IsMainThread());
if (buffer && buffer_has_been_set_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Cannot set buffer to non-null after it "
"has been already been set to a non-null "
"buffer");
@@ -407,7 +407,7 @@ void AudioBufferSourceHandler::SetBuffer(AudioBuffer* buffer,
// many channels either.
if (number_of_channels > BaseAudioContext::MaxNumberOfChannels()) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
ExceptionMessages::IndexOutsideRange(
"number of input channels", number_of_channels, 1u,
ExceptionMessages::kInclusiveBound,
@@ -502,10 +502,10 @@ void AudioBufferSourceHandler::StartSource(double when,
ExceptionState& exception_state) {
DCHECK(IsMainThread());
- Context()->MaybeRecordStartAttempt();
+ Context()->NotifySourceNodeStart();
if (GetPlaybackState() != UNSCHEDULED_STATE) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"cannot call start more than once.");
return;
}
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_context.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_context.cc
index 357edd163b0..23a82aacfa7 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_context.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_context.cc
@@ -4,21 +4,24 @@
#include "third_party/blink/renderer/modules/webaudio/audio_context.h"
+#include "build/build_config.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
#include "third_party/blink/public/platform/web_audio_latency_hint.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/use_counter.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/timing/dom_window_performance.h"
#include "third_party/blink/renderer/core/timing/window_performance.h"
#include "third_party/blink/renderer/modules/webaudio/audio_context_options.h"
#include "third_party/blink/renderer/modules/webaudio/audio_timestamp.h"
#include "third_party/blink/renderer/modules/webaudio/default_audio_destination_node.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/histogram.h"
#if DEBUG_AUDIONODE_REFERENCES
@@ -60,7 +63,7 @@ AudioContext* AudioContext::Create(Document& document,
if (!AudioUtilities::IsValidAudioBufferSampleRate(
audio_context->sampleRate())) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
ExceptionMessages::IndexOutsideRange(
"hardware sample rate", audio_context->sampleRate(),
AudioUtilities::MinAudioBufferSampleRate(),
@@ -76,7 +79,8 @@ AudioContext* AudioContext::Create(Document& document,
// quantum". NOTE: for now AudioContext does not need an explicit
// startRendering() call from JavaScript. We may want to consider
// requiring it for symmetry with OfflineAudioContext.
- audio_context->MaybeUnlockUserGesture();
+ audio_context->MaybeAllowAutoplayWithUnlockType(
+ AutoplayUnlockType::kContextConstructor);
if (audio_context->IsAllowedToStart()) {
audio_context->StartRendering();
audio_context->SetContextState(kRunning);
@@ -104,6 +108,8 @@ AudioContext* AudioContext::Create(Document& document,
"https://goo.gl/7K7WLu"));
}
+ probe::didCreateAudioContext(&document);
+
return audio_context;
}
@@ -112,10 +118,39 @@ AudioContext::AudioContext(Document& document,
: BaseAudioContext(&document, kRealtimeContext),
context_id_(g_context_id++) {
destination_node_ = DefaultAudioDestinationNode::Create(this, latency_hint);
+
+ switch (GetAutoplayPolicy()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ break;
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ if (document.GetFrame() &&
+ document.GetFrame()->IsCrossOriginSubframe()) {
+ autoplay_status_ = AutoplayStatus::kAutoplayStatusFailed;
+ user_gesture_required_ = true;
+ }
+ break;
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ autoplay_status_ = AutoplayStatus::kAutoplayStatusFailed;
+ user_gesture_required_ = true;
+ break;
+ }
+
Initialize();
}
+void AudioContext::Uninitialize() {
+ DCHECK(IsMainThread());
+ DCHECK_NE(g_hardware_context_count, 0u);
+ --g_hardware_context_count;
+
+ DidClose();
+ RecordAutoplayMetrics();
+ BaseAudioContext::Uninitialize();
+}
+
AudioContext::~AudioContext() {
+ DCHECK(!autoplay_status_.has_value());
#if DEBUG_AUDIONODE_REFERENCES
fprintf(stderr, "[%16p]: AudioContext::~AudioContext(): %u\n", this,
context_id_);
@@ -135,8 +170,9 @@ ScriptPromise AudioContext::suspendContext(ScriptState* script_state) {
ScriptPromise promise = resolver->Promise();
if (ContextState() == kClosed) {
- resolver->Reject(DOMException::Create(
- kInvalidStateError, "Cannot suspend a context that has been closed"));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Cannot suspend a context that has been closed"));
} else {
// Stop rendering now.
if (destination())
@@ -145,6 +181,9 @@ ScriptPromise AudioContext::suspendContext(ScriptState* script_state) {
// Since we don't have any way of knowing when the hardware actually stops,
// we'll just resolve the promise now.
resolver->Resolve();
+
+ // Probe reports the suspension only when the promise is resolved.
+ probe::didSuspendAudioContext(GetDocument());
}
return promise;
@@ -156,7 +195,7 @@ ScriptPromise AudioContext::resumeContext(ScriptState* script_state) {
if (IsContextClosed()) {
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kInvalidAccessError,
+ DOMException::Create(DOMExceptionCode::kInvalidAccessError,
"cannot resume a closed AudioContext"));
}
@@ -171,11 +210,14 @@ ScriptPromise AudioContext::resumeContext(ScriptState* script_state) {
}
// Restart the destination node to pull on the audio graph.
if (destination()) {
- MaybeUnlockUserGesture();
+ MaybeAllowAutoplayWithUnlockType(AutoplayUnlockType::kContextResume);
if (IsAllowedToStart()) {
// Do not set the state to running here. We wait for the
// destination to start to set the state.
StartRendering();
+
+ // Probe reports only when the user gesture allows the audio rendering.
+ probe::didResumeAudioContext(GetDocument());
}
}
@@ -207,6 +249,12 @@ void AudioContext::getOutputTimestamp(ScriptState* script_state,
AudioIOPosition position = OutputPosition();
+ // The timestamp of what is currently being played (contextTime) cannot be
+ // later than what is being rendered. (currentTime)
+ if (position.position > currentTime()) {
+ position.position = currentTime();
+ }
+
double performance_time = performance->MonotonicTimeToDOMHighResTimeStamp(
TimeTicksFromSeconds(position.timestamp));
if (performance_time < 0.0)
@@ -222,35 +270,28 @@ ScriptPromise AudioContext::closeContext(ScriptState* script_state) {
// resolved, so just create a new promise and reject it.
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kInvalidStateError,
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
"Cannot close a context that is being closed or "
"has already been closed."));
}
- // Save the current sample rate for any subsequent decodeAudioData calls.
- SetClosedContextSampleRate(sampleRate());
-
close_resolver_ = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = close_resolver_->Promise();
- // Stop the audio context. This will stop the destination node from pulling
- // audio anymore. And since we have disconnected the destination from the
- // audio graph, and thus has no references, the destination node can GCed if
- // JS has no references. uninitialize() will also resolve the Promise created
- // here.
- Uninitialize();
+ // Stops the rendering, but it doesn't release the resources here.
+ StopRendering();
+
+ // The promise from closing context resolves immediately after this function.
+ DidClose();
+
+ probe::didCloseAudioContext(GetDocument());
return promise;
}
void AudioContext::DidClose() {
- // This is specific to AudioContexts. OfflineAudioContexts
- // are closed in their completion event.
SetContextState(kClosed);
- DCHECK(g_hardware_context_count);
- --g_hardware_context_count;
-
if (close_resolver_)
close_resolver_->Resolve();
}
@@ -271,7 +312,160 @@ void AudioContext::StopRendering() {
}
double AudioContext::baseLatency() const {
- return FramesPerBuffer() / static_cast<double>(sampleRate());
+ DCHECK(IsMainThread());
+ DCHECK(destination());
+
+ // TODO(hongchan): Due to the incompatible constructor between
+ // AudioDestinationNode and DefaultAudioDestinationNode, casting directly from
+ // |destination()| is impossible. This is a temporary workaround until the
+ // refactoring is completed.
+ DefaultAudioDestinationHandler& destination_handler =
+ static_cast<DefaultAudioDestinationHandler&>(
+ destination()->GetAudioDestinationHandler());
+ return destination_handler.GetFramesPerBuffer() /
+ static_cast<double>(sampleRate());
+}
+
+void AudioContext::NotifySourceNodeStart() {
+ source_node_started_ = true;
+ if (!user_gesture_required_)
+ return;
+
+ MaybeAllowAutoplayWithUnlockType(AutoplayUnlockType::kSourceNodeStart);
+
+ if (IsAllowedToStart())
+ StartRendering();
+}
+
+AutoplayPolicy::Type AudioContext::GetAutoplayPolicy() const {
+ Document* document = GetDocument();
+ DCHECK(document);
+
+ auto autoplay_policy =
+ AutoplayPolicy::GetAutoplayPolicyForDocument(*document);
+
+ if (autoplay_policy ==
+ AutoplayPolicy::Type::kDocumentUserActivationRequired &&
+ RuntimeEnabledFeatures::AutoplayIgnoresWebAudioEnabled()) {
+// When ignored, the policy is different on Android compared to Desktop.
+#if defined(OS_ANDROID)
+ return AutoplayPolicy::Type::kUserGestureRequired;
+#else
+ // Force no user gesture required on desktop.
+ return AutoplayPolicy::Type::kNoUserGestureRequired;
+#endif
+ }
+
+ return autoplay_policy;
+}
+
+bool AudioContext::AreAutoplayRequirementsFulfilled() const {
+ switch (GetAutoplayPolicy()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ return true;
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ return Frame::HasTransientUserActivation(
+ GetDocument() ? GetDocument()->GetFrame() : nullptr);
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ return AutoplayPolicy::IsDocumentAllowedToPlay(*GetDocument());
+ }
+
+ NOTREACHED();
+ return false;
+}
+
+void AudioContext::MaybeAllowAutoplayWithUnlockType(AutoplayUnlockType type) {
+ if (!user_gesture_required_ || !AreAutoplayRequirementsFulfilled())
+ return;
+
+ DCHECK(!autoplay_status_.has_value() ||
+ autoplay_status_ != AutoplayStatus::kAutoplayStatusSucceeded);
+
+ user_gesture_required_ = false;
+ autoplay_status_ = AutoplayStatus::kAutoplayStatusSucceeded;
+
+ DCHECK(!autoplay_unlock_type_.has_value());
+ autoplay_unlock_type_ = type;
+}
+
+bool AudioContext::IsAllowedToStart() const {
+ if (!user_gesture_required_)
+ return true;
+
+ Document* document = ToDocument(GetExecutionContext());
+ DCHECK(document);
+
+ switch (GetAutoplayPolicy()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ NOTREACHED();
+ break;
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ DCHECK(document->GetFrame() &&
+ document->GetFrame()->IsCrossOriginSubframe());
+ document->AddConsoleMessage(ConsoleMessage::Create(
+ kOtherMessageSource, kWarningMessageLevel,
+ "The AudioContext was not allowed to start. It must be resumed (or "
+ "created) from a user gesture event handler. https://goo.gl/7K7WLu"));
+ break;
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ document->AddConsoleMessage(ConsoleMessage::Create(
+ kOtherMessageSource, kWarningMessageLevel,
+ "The AudioContext was not allowed to start. It must be resumed (or "
+ "created) after a user gesture on the page. https://goo.gl/7K7WLu"));
+ break;
+ }
+
+ return false;
+}
+
+void AudioContext::RecordAutoplayMetrics() {
+ if (!autoplay_status_.has_value())
+ return;
+
+ ukm::UkmRecorder* ukm_recorder = GetDocument()->UkmRecorder();
+ DCHECK(ukm_recorder);
+ ukm::builders::Media_Autoplay_AudioContext(GetDocument()->UkmSourceID())
+ .SetStatus(autoplay_status_.value())
+ .SetUnlockType(autoplay_unlock_type_
+ ? static_cast<int>(autoplay_unlock_type_.value())
+ : -1)
+ .SetSourceNodeStarted(source_node_started_)
+ .Record(ukm_recorder);
+
+ // Record autoplay_status_ value.
+ DEFINE_STATIC_LOCAL(
+ EnumerationHistogram, autoplay_histogram,
+ ("WebAudio.Autoplay", AutoplayStatus::kAutoplayStatusCount));
+ DEFINE_STATIC_LOCAL(
+ EnumerationHistogram, cross_origin_autoplay_histogram,
+ ("WebAudio.Autoplay.CrossOrigin", AutoplayStatus::kAutoplayStatusCount));
+
+ autoplay_histogram.Count(autoplay_status_.value());
+
+ if (GetDocument()->GetFrame() &&
+ GetDocument()->GetFrame()->IsCrossOriginSubframe()) {
+ cross_origin_autoplay_histogram.Count(autoplay_status_.value());
+ }
+
+ autoplay_status_.reset();
+
+ // Record autoplay_unlock_type_ value.
+ if (autoplay_unlock_type_.has_value()) {
+ DEFINE_STATIC_LOCAL(EnumerationHistogram, autoplay_unlock_type_histogram,
+ ("WebAudio.Autoplay.UnlockType",
+ static_cast<int>(AutoplayUnlockType::kCount)));
+
+ autoplay_unlock_type_histogram.Count(
+ static_cast<int>(autoplay_unlock_type_.value()));
+
+ autoplay_unlock_type_.reset();
+ }
+}
+
+void AudioContext::ContextDestroyed(ExecutionContext*) {
+ Uninitialize();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_context.h b/chromium/third_party/blink/renderer/modules/webaudio/audio_context.h
index 9a239c3ef75..a239599207a 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_context.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_context.h
@@ -7,6 +7,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
+#include "third_party/blink/renderer/core/html/media/autoplay_policy.h"
#include "third_party/blink/renderer/modules/webaudio/audio_context_options.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -33,6 +34,9 @@ class MODULES_EXPORT AudioContext : public BaseAudioContext {
~AudioContext() override;
void Trace(blink::Visitor*) override;
+ // For ContextLifeCycleObserver
+ void ContextDestroyed(ExecutionContext*) final;
+
ScriptPromise closeContext(ScriptState*);
bool IsContextClosed() const final;
@@ -44,17 +48,81 @@ class MODULES_EXPORT AudioContext : public BaseAudioContext {
void getOutputTimestamp(ScriptState*, AudioTimestamp&);
double baseLatency() const;
+ // Called by handlers of AudioScheduledSourceNode and AudioBufferSourceNode to
+ // notify their associated AudioContext when start() is called. It may resume
+ // the AudioContext if it is now allowed to start.
+ void NotifySourceNodeStart() final;
+
protected:
AudioContext(Document&, const WebAudioLatencyHint&);
-
- void DidClose() final;
+ void Uninitialize() final;
private:
+ friend class AudioContextAutoplayTest;
+
+ // Do not change the order of this enum, it is used for metrics.
+ enum AutoplayStatus {
+ // The AudioContext failed to activate because of user gesture requirements.
+ kAutoplayStatusFailed = 0,
+ // Same as AutoplayStatusFailed but start() on a node was called with a user
+ // gesture.
+ // This value is no longer used but the enum entry should not be re-used
+ // because it is used for metrics.
+ // kAutoplayStatusFailedWithStart = 1,
+ // The AudioContext had user gesture requirements and was able to activate
+ // with a user gesture.
+ kAutoplayStatusSucceeded = 2,
+
+ // Keep at the end.
+ kAutoplayStatusCount
+ };
+
+ // Returns the AutoplayPolicy currently applying to this instance.
+ AutoplayPolicy::Type GetAutoplayPolicy() const;
+
+ // Returns whether the autoplay requirements are fulfilled.
+ bool AreAutoplayRequirementsFulfilled() const;
+
+ // Do not change the order of this enum, it is used for metrics.
+ enum class AutoplayUnlockType {
+ kContextConstructor = 0,
+ kContextResume = 1,
+ kSourceNodeStart = 2,
+ kCount
+ };
+
+ // If possible, allows autoplay for the AudioContext and marke it as allowed
+ // by the given type.
+ void MaybeAllowAutoplayWithUnlockType(AutoplayUnlockType);
+
+ // Returns whether the AudioContext is allowed to start rendering.
+ bool IsAllowedToStart() const;
+
+ // Record the current autoplay metrics.
+ void RecordAutoplayMetrics();
+
void StopRendering();
+ void DidClose();
+
unsigned context_id_;
Member<ScriptPromiseResolver> close_resolver_;
+ // Whether a user gesture is required to start this AudioContext.
+ bool user_gesture_required_ = false;
+
+ // Autoplay status associated with this AudioContext, if any.
+ // Will only be set if there is an autoplay policy in place.
+ // Will never be set for OfflineAudioContext.
+ base::Optional<AutoplayStatus> autoplay_status_;
+
+ // Autoplay unlock type for this AudioContext.
+ // Will only be set if there is an autoplay policy in place.
+ // Will never be set for OfflineAudioContext.
+ base::Optional<AutoplayUnlockType> autoplay_unlock_type_;
+
+ // Records if start() was ever called for any source node in this context.
+ bool source_node_started_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_context_autoplay_test.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_context_autoplay_test.cc
new file mode 100644
index 00000000000..93af83128ff
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_context_autoplay_test.cc
@@ -0,0 +1,732 @@
+// 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/modules/webaudio/audio_context.h"
+
+#include <memory>
+
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_audio_device.h"
+#include "third_party/blink/public/platform/web_audio_latency_hint.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/dom/user_gesture_indicator.h"
+#include "third_party/blink/renderer/core/frame/frame_owner.h"
+#include "third_party/blink/renderer/core/frame/frame_types.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"
+#include "third_party/blink/renderer/core/html/media/autoplay_policy.h"
+#include "third_party/blink/renderer/core/loader/document_loader.h"
+#include "third_party/blink/renderer/core/loader/empty_clients.h"
+#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_context_options.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_worklet_thread.h"
+#include "third_party/blink/renderer/platform/testing/histogram_tester.h"
+#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
+
+namespace blink {
+
+namespace {
+
+const char* const kAutoplayMetric = "WebAudio.Autoplay";
+const char* const kAutoplayCrossOriginMetric = "WebAudio.Autoplay.CrossOrigin";
+
+class MockCrossOriginLocalFrameClient final : public EmptyLocalFrameClient {
+ public:
+ static MockCrossOriginLocalFrameClient* Create(Frame* parent) {
+ return new MockCrossOriginLocalFrameClient(parent);
+ }
+
+ void Trace(blink::Visitor* visitor) override {
+ visitor->Trace(parent_);
+ EmptyLocalFrameClient::Trace(visitor);
+ }
+
+ Frame* Parent() const override { return parent_.Get(); }
+ Frame* Top() const override { return parent_.Get(); }
+
+ private:
+ explicit MockCrossOriginLocalFrameClient(Frame* parent) : parent_(parent) {}
+
+ Member<Frame> parent_;
+};
+
+class MockWebAudioDeviceForAutoplayTest : public WebAudioDevice {
+ public:
+ explicit MockWebAudioDeviceForAutoplayTest(double sample_rate,
+ int frames_per_buffer)
+ : sample_rate_(sample_rate), frames_per_buffer_(frames_per_buffer) {}
+ ~MockWebAudioDeviceForAutoplayTest() override = default;
+
+ void Start() override {}
+ void Stop() override {}
+ double SampleRate() override { return sample_rate_; }
+ int FramesPerBuffer() override { return frames_per_buffer_; }
+
+ private:
+ double sample_rate_;
+ int frames_per_buffer_;
+};
+
+class AudioContextAutoplayTestPlatform : public TestingPlatformSupport {
+ public:
+ std::unique_ptr<WebAudioDevice> CreateAudioDevice(
+ unsigned number_of_input_channels,
+ unsigned number_of_channels,
+ const WebAudioLatencyHint& latency_hint,
+ WebAudioDevice::RenderCallback*,
+ const WebString& device_id) override {
+ return std::make_unique<MockWebAudioDeviceForAutoplayTest>(
+ AudioHardwareSampleRate(), AudioHardwareBufferSize());
+ }
+
+ std::unique_ptr<WebThread> CreateThread(
+ const WebThreadCreationParams& params) override {
+ return old_platform_->CreateThread(params);
+ }
+
+ double AudioHardwareSampleRate() override { return 44100; }
+ size_t AudioHardwareBufferSize() override { return 128; }
+};
+
+} // anonymous namespace
+
+class AudioContextAutoplayTest
+ : public testing::TestWithParam<AutoplayPolicy::Type> {
+ protected:
+ using AutoplayStatus = AudioContext::AutoplayStatus;
+
+ void SetUp() override {
+ dummy_page_holder_ = DummyPageHolder::Create();
+ dummy_frame_owner_ = DummyFrameOwner::Create();
+ GetDocument().UpdateSecurityOrigin(
+ SecurityOrigin::Create("https", "example.com", 80));
+
+ CreateChildFrame();
+
+ GetDocument().GetSettings()->SetAutoplayPolicy(GetParam());
+ ChildDocument().GetSettings()->SetAutoplayPolicy(GetParam());
+
+ histogram_tester_ = std::make_unique<HistogramTester>();
+ }
+
+ void TearDown() override {
+ if (child_frame_)
+ child_frame_->Detach(FrameDetachType::kRemove);
+ }
+
+ void CreateChildFrame() {
+ child_frame_ = LocalFrame::Create(
+ MockCrossOriginLocalFrameClient::Create(GetDocument().GetFrame()),
+ *GetDocument().GetFrame()->GetPage(), dummy_frame_owner_.Get());
+ child_frame_->SetView(
+ LocalFrameView::Create(*child_frame_, IntSize(500, 500)));
+ child_frame_->Init();
+
+ ChildDocument().UpdateSecurityOrigin(
+ SecurityOrigin::Create("https", "cross-origin.com", 80));
+ }
+
+ Document& GetDocument() { return dummy_page_holder_->GetDocument(); }
+
+ Document& ChildDocument() { return *child_frame_->GetDocument(); }
+
+ ScriptState* GetScriptStateFrom(const Document& document) {
+ return ToScriptStateForMainWorld(document.GetFrame());
+ }
+
+ void RejectPendingResolvers(AudioContext* audio_context) {
+ audio_context->RejectPendingResolvers();
+ }
+
+ void RecordAutoplayStatus(AudioContext* audio_context) {
+ audio_context->RecordAutoplayMetrics();
+ }
+
+ HistogramTester* GetHistogramTester() {
+ return histogram_tester_.get();
+ }
+
+ private:
+ std::unique_ptr<DummyPageHolder> dummy_page_holder_;
+ Persistent<DummyFrameOwner> dummy_frame_owner_;
+ Persistent<LocalFrame> child_frame_;
+ std::unique_ptr<HistogramTester> histogram_tester_;
+ ScopedTestingPlatformSupport<AudioContextAutoplayTestPlatform> platform_;
+};
+
+// Creates an AudioContext without a gesture inside a x-origin child frame.
+TEST_P(AudioContextAutoplayTest, AutoplayMetrics_CreateNoGesture_Child) {
+ AudioContext* audio_context = AudioContext::Create(
+ ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
+ RecordAutoplayStatus(audio_context);
+
+ switch (GetParam()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayCrossOriginMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
+ break;
+ }
+}
+
+// Creates an AudioContext without a gesture inside a main frame.
+TEST_P(AudioContextAutoplayTest, AutoplayMetrics_CreateNoGesture_Main) {
+ AudioContext* audio_context = AudioContext::Create(
+ GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
+ RecordAutoplayStatus(audio_context);
+
+ switch (GetParam()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ }
+}
+
+// Creates an AudioContext then call resume without a gesture in a x-origin
+// child frame.
+TEST_P(AudioContextAutoplayTest,
+ AutoplayMetrics_CallResumeNoGesture_Child) {
+ ScriptState::Scope scope(GetScriptStateFrom(ChildDocument()));
+
+ AudioContext* audio_context = AudioContext::Create(
+ ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
+ audio_context->resumeContext(GetScriptStateFrom(ChildDocument()));
+ RejectPendingResolvers(audio_context);
+ RecordAutoplayStatus(audio_context);
+
+ switch (GetParam()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayCrossOriginMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
+ break;
+ }
+}
+
+// Creates an AudioContext then call resume without a gesture in a main frame.
+TEST_P(AudioContextAutoplayTest, AutoplayMetrics_CallResumeNoGesture_Main) {
+ ScriptState::Scope scope(GetScriptStateFrom(GetDocument()));
+
+ AudioContext* audio_context = AudioContext::Create(
+ GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
+ audio_context->resumeContext(GetScriptStateFrom(ChildDocument()));
+ RejectPendingResolvers(audio_context);
+ RecordAutoplayStatus(audio_context);
+
+ switch (GetParam()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ }
+}
+
+// Creates an AudioContext with a user gesture inside a x-origin child frame.
+TEST_P(AudioContextAutoplayTest, AutoplayMetrics_CreateGesture_Child) {
+ std::unique_ptr<UserGestureIndicator> user_gesture_scope =
+ Frame::NotifyUserActivation(ChildDocument().GetFrame(),
+ UserGestureToken::kNewGesture);
+
+ AudioContext* audio_context = AudioContext::Create(
+ ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
+ RecordAutoplayStatus(audio_context);
+
+ switch (GetParam()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayCrossOriginMetric, AutoplayStatus::kAutoplayStatusSucceeded,
+ 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
+ break;
+ }
+}
+
+// Creates an AudioContext with a user gesture inside a main frame.
+TEST_P(AudioContextAutoplayTest, AutoplayMetrics_CreateGesture_Main) {
+ std::unique_ptr<UserGestureIndicator> user_gesture_scope =
+ Frame::NotifyUserActivation(GetDocument().GetFrame(),
+ UserGestureToken::kNewGesture);
+
+ AudioContext* audio_context = AudioContext::Create(
+ GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
+ RecordAutoplayStatus(audio_context);
+
+ switch (GetParam()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ }
+}
+
+// Creates an AudioContext then calls resume with a user gesture inside a
+// x-origin child frame.
+TEST_P(AudioContextAutoplayTest, AutoplayMetrics_CallResumeGesture_Child) {
+ ScriptState::Scope scope(GetScriptStateFrom(ChildDocument()));
+
+ AudioContext* audio_context = AudioContext::Create(
+ ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
+
+ std::unique_ptr<UserGestureIndicator> user_gesture_scope =
+ Frame::NotifyUserActivation(ChildDocument().GetFrame(),
+ UserGestureToken::kNewGesture);
+
+ audio_context->resumeContext(GetScriptStateFrom(ChildDocument()));
+ RejectPendingResolvers(audio_context);
+ RecordAutoplayStatus(audio_context);
+
+ switch (GetParam()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayCrossOriginMetric, AutoplayStatus::kAutoplayStatusSucceeded,
+ 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
+ break;
+ }
+}
+
+// Creates an AudioContext then calls resume with a user gesture inside a main
+// frame.
+TEST_P(AudioContextAutoplayTest, AutoplayMetrics_CallResumeGesture_Main) {
+ ScriptState::Scope scope(GetScriptStateFrom(GetDocument()));
+
+ AudioContext* audio_context = AudioContext::Create(
+ GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
+
+ std::unique_ptr<UserGestureIndicator> user_gesture_scope =
+ Frame::NotifyUserActivation(GetDocument().GetFrame(),
+ UserGestureToken::kNewGesture);
+
+ audio_context->resumeContext(GetScriptStateFrom(GetDocument()));
+ RejectPendingResolvers(audio_context);
+ RecordAutoplayStatus(audio_context);
+
+ switch (GetParam()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ }
+}
+
+// Creates an AudioContext then calls start on a node without a gesture inside a
+// x-origin child frame.
+TEST_P(AudioContextAutoplayTest, AutoplayMetrics_NodeStartNoGesture_Child) {
+ AudioContext* audio_context = AudioContext::Create(
+ ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
+ audio_context->NotifySourceNodeStart();
+ RecordAutoplayStatus(audio_context);
+
+ switch (GetParam()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayCrossOriginMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
+ break;
+ }
+}
+
+// Creates an AudioContext then calls start on a node without a gesture inside a
+// main frame.
+TEST_P(AudioContextAutoplayTest, AutoplayMetrics_NodeStartNoGesture_Main) {
+ AudioContext* audio_context = AudioContext::Create(
+ GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
+ audio_context->NotifySourceNodeStart();
+ RecordAutoplayStatus(audio_context);
+
+ switch (GetParam()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ }
+}
+
+// Creates an AudioContext then calls start on a node with a gesture inside a
+// x-origin child frame.
+TEST_P(AudioContextAutoplayTest, AutoplayMetrics_NodeStartGesture_Child) {
+ AudioContext* audio_context = AudioContext::Create(
+ ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
+
+ std::unique_ptr<UserGestureIndicator> user_gesture_scope =
+ Frame::NotifyUserActivation(ChildDocument().GetFrame(),
+ UserGestureToken::kNewGesture);
+ audio_context->NotifySourceNodeStart();
+ RecordAutoplayStatus(audio_context);
+
+ switch (GetParam()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayCrossOriginMetric, AutoplayStatus::kAutoplayStatusSucceeded,
+ 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
+ break;
+ }
+}
+
+// Creates an AudioContext then calls start on a node with a gesture inside a
+// main frame.
+TEST_P(AudioContextAutoplayTest, AutoplayMetrics_NodeStartGesture_Main) {
+ AudioContext* audio_context = AudioContext::Create(
+ GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
+
+ std::unique_ptr<UserGestureIndicator> user_gesture_scope =
+ Frame::NotifyUserActivation(GetDocument().GetFrame(),
+ UserGestureToken::kNewGesture);
+ audio_context->NotifySourceNodeStart();
+ RecordAutoplayStatus(audio_context);
+
+ switch (GetParam()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ }
+}
+
+// Creates an AudioContext then calls start on a node without a gesture and
+// finally allows the AudioContext to produce sound inside x-origin child frame.
+TEST_P(AudioContextAutoplayTest,
+ AutoplayMetrics_NodeStartNoGestureThenSuccess_Child) {
+ ScriptState::Scope scope(GetScriptStateFrom(ChildDocument()));
+
+ AudioContext* audio_context = AudioContext::Create(
+ ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
+ audio_context->NotifySourceNodeStart();
+
+ std::unique_ptr<UserGestureIndicator> user_gesture_scope =
+ Frame::NotifyUserActivation(ChildDocument().GetFrame(),
+ UserGestureToken::kNewGesture);
+ audio_context->resumeContext(GetScriptStateFrom(ChildDocument()));
+ RejectPendingResolvers(audio_context);
+ RecordAutoplayStatus(audio_context);
+
+ switch (GetParam()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayCrossOriginMetric, AutoplayStatus::kAutoplayStatusSucceeded,
+ 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
+ break;
+ }
+}
+
+// Creates an AudioContext then calls start on a node without a gesture and
+// finally allows the AudioContext to produce sound inside a main frame.
+TEST_P(AudioContextAutoplayTest,
+ AutoplayMetrics_NodeStartNoGestureThenSuccess_Main) {
+ ScriptState::Scope scope(GetScriptStateFrom(GetDocument()));
+
+ AudioContext* audio_context = AudioContext::Create(
+ GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
+ audio_context->NotifySourceNodeStart();
+
+ std::unique_ptr<UserGestureIndicator> user_gesture_scope =
+ Frame::NotifyUserActivation(GetDocument().GetFrame(),
+ UserGestureToken::kNewGesture);
+ audio_context->resumeContext(GetScriptStateFrom(GetDocument()));
+ RejectPendingResolvers(audio_context);
+ RecordAutoplayStatus(audio_context);
+
+ switch (GetParam()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ }
+}
+
+// Creates an AudioContext then calls start on a node with a gesture and
+// finally allows the AudioContext to produce sound inside x-origin child frame.
+TEST_P(AudioContextAutoplayTest,
+ AutoplayMetrics_NodeStartGestureThenSucces_Child) {
+ ScriptState::Scope scope(GetScriptStateFrom(ChildDocument()));
+
+ AudioContext* audio_context = AudioContext::Create(
+ ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
+
+ std::unique_ptr<UserGestureIndicator> user_gesture_scope =
+ Frame::NotifyUserActivation(ChildDocument().GetFrame(),
+ UserGestureToken::kNewGesture);
+ audio_context->NotifySourceNodeStart();
+ audio_context->resumeContext(GetScriptStateFrom(ChildDocument()));
+ RejectPendingResolvers(audio_context);
+ RecordAutoplayStatus(audio_context);
+
+ switch (GetParam()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayCrossOriginMetric, AutoplayStatus::kAutoplayStatusSucceeded,
+ 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
+ break;
+ }
+}
+
+// Creates an AudioContext then calls start on a node with a gesture and
+// finally allows the AudioContext to produce sound inside a main frame.
+TEST_P(AudioContextAutoplayTest,
+ AutoplayMetrics_NodeStartGestureThenSucces_Main) {
+ ScriptState::Scope scope(GetScriptStateFrom(GetDocument()));
+
+ AudioContext* audio_context = AudioContext::Create(
+ GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
+
+ std::unique_ptr<UserGestureIndicator> user_gesture_scope =
+ Frame::NotifyUserActivation(GetDocument().GetFrame(),
+ UserGestureToken::kNewGesture);
+ audio_context->NotifySourceNodeStart();
+ audio_context->resumeContext(GetScriptStateFrom(GetDocument()));
+ RejectPendingResolvers(audio_context);
+ RecordAutoplayStatus(audio_context);
+
+ switch (GetParam()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ }
+}
+
+// Attempts to autoplay an AudioContext in a x-origin child frame when the
+// document previous received a user gesture.
+TEST_P(AudioContextAutoplayTest,
+ AutoplayMetrics_DocumentReceivedGesture_Child) {
+ Frame::NotifyUserActivation(ChildDocument().GetFrame(),
+ UserGestureToken::kNewGesture);
+
+ AudioContext* audio_context = AudioContext::Create(
+ ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
+ RecordAutoplayStatus(audio_context);
+
+ switch (GetParam()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayCrossOriginMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
+ break;
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayCrossOriginMetric, AutoplayStatus::kAutoplayStatusSucceeded,
+ 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
+ break;
+ }
+}
+
+// Attempts to autoplay an AudioContext in a main child frame when the
+// document previous received a user gesture.
+TEST_P(AudioContextAutoplayTest,
+ AutoplayMetrics_DocumentReceivedGesture_Main) {
+ Frame::NotifyUserActivation(ChildDocument().GetFrame(),
+ UserGestureToken::kNewGesture);
+
+ AudioContext* audio_context = AudioContext::Create(
+ GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
+ RecordAutoplayStatus(audio_context);
+
+ switch (GetParam()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ }
+}
+
+// Attempts to autoplay an AudioContext in a main child frame when the
+// document received a user gesture before navigation.
+TEST_P(AudioContextAutoplayTest,
+ AutoplayMetrics_DocumentReceivedGesture_BeforeNavigation) {
+ GetDocument().GetFrame()->SetDocumentHasReceivedUserGestureBeforeNavigation(
+ true);
+
+ AudioContext* audio_context = AudioContext::Create(
+ GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
+ RecordAutoplayStatus(audio_context);
+
+ switch (GetParam()) {
+ case AutoplayPolicy::Type::kNoUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequired:
+ case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ case AutoplayPolicy::Type::kDocumentUserActivationRequired:
+ GetHistogramTester()->ExpectBucketCount(
+ kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
+ GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
+ break;
+ }
+}
+
+INSTANTIATE_TEST_CASE_P(
+ AudioContextAutoplayTest,
+ AudioContextAutoplayTest,
+ testing::Values(AutoplayPolicy::Type::kNoUserGestureRequired,
+ AutoplayPolicy::Type::kUserGestureRequired,
+ AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin,
+ AutoplayPolicy::Type::kDocumentUserActivationRequired));
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_context_test.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_context_test.cc
index 714e083fe59..6f994307305 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_context_test.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_context_test.cc
@@ -9,6 +9,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_audio_device.h"
#include "third_party/blink/public/platform/web_audio_latency_hint.h"
+#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_destination_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_destination_node.cc
index d3d89db4acf..ac37756aab8 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_destination_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_destination_node.cc
@@ -24,13 +24,8 @@
*/
#include "third_party/blink/renderer/modules/webaudio/audio_destination_node.h"
-#include "third_party/blink/renderer/modules/webaudio/audio_node_input.h"
-#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
+
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
-#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
-#include "third_party/blink/renderer/platform/audio/denormal_disabler.h"
-#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
-#include "third_party/blink/renderer/platform/wtf/atomics.h"
namespace blink {
@@ -43,77 +38,6 @@ AudioDestinationHandler::~AudioDestinationHandler() {
DCHECK(!IsInitialized());
}
-void AudioDestinationHandler::Render(AudioBus* source_bus,
- AudioBus* destination_bus,
- size_t number_of_frames,
- const AudioIOPosition& output_position) {
- TRACE_EVENT0("webaudio", "AudioDestinationHandler::Render");
-
- // We don't want denormals slowing down any of the audio processing
- // since they can very seriously hurt performance. This will take care of all
- // AudioNodes because they all process within this scope.
- DenormalDisabler denormal_disabler;
-
- // Need to check if the context actually alive. Otherwise the subsequent
- // steps will fail. If the context is not alive somehow, return immediately
- // and do nothing.
- //
- // TODO(hongchan): because the context can go away while rendering, so this
- // check cannot guarantee the safe execution of the following steps.
- DCHECK(Context());
- if (!Context())
- return;
-
- Context()->GetDeferredTaskHandler().SetAudioThreadToCurrentThread();
-
- // If the destination node is not initialized, pass the silence to the final
- // audio destination (one step before the FIFO). This check is for the case
- // where the destination is in the middle of tearing down process.
- if (!IsInitialized()) {
- destination_bus->Zero();
- return;
- }
-
- // Let the context take care of any business at the start of each render
- // quantum.
- Context()->HandlePreRenderTasks(output_position);
-
- // Prepare the local audio input provider for this render quantum.
- if (source_bus)
- local_audio_input_provider_.Set(source_bus);
-
- DCHECK_GE(NumberOfInputs(), 1u);
- if (NumberOfInputs() < 1) {
- destination_bus->Zero();
- return;
- }
- // This will cause the node(s) connected to us to process, which in turn will
- // pull on their input(s), all the way backwards through the rendering graph.
- AudioBus* rendered_bus = Input(0).Pull(destination_bus, number_of_frames);
-
- if (!rendered_bus) {
- destination_bus->Zero();
- } else if (rendered_bus != destination_bus) {
- // in-place processing was not possible - so copy
- destination_bus->CopyFrom(*rendered_bus);
- }
-
- // Process nodes which need a little extra help because they are not connected
- // to anything, but still need to process.
- Context()->GetDeferredTaskHandler().ProcessAutomaticPullNodes(
- number_of_frames);
-
- // Let the context take care of any business at the end of each render
- // quantum.
- Context()->HandlePostRenderTasks();
-
- // Advance current sample-frame.
- size_t new_sample_frame = current_sample_frame_ + number_of_frames;
- ReleaseStore(&current_sample_frame_, new_sample_frame);
-
- Context()->UpdateWorkletGlobalScopeOnRenderingThread();
-}
-
// ----------------------------------------------------------------
AudioDestinationNode::AudioDestinationNode(BaseAudioContext& context)
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_destination_node.h b/chromium/third_party/blink/renderer/modules/webaudio/audio_destination_node.h
index 120edf81f65..c143f860bd3 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_destination_node.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_destination_node.h
@@ -26,42 +26,24 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_AUDIO_DESTINATION_NODE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_AUDIO_DESTINATION_NODE_H_
-#include "third_party/blink/renderer/modules/webaudio/audio_buffer.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node.h"
-#include "third_party/blink/renderer/platform/audio/audio_bus.h"
-#include "third_party/blink/renderer/platform/audio/audio_io_callback.h"
-#include "third_party/blink/renderer/platform/audio/audio_source_provider.h"
+#include "third_party/blink/renderer/platform/wtf/atomics.h"
namespace blink {
-class AudioBus;
-class BaseAudioContext;
-
-class AudioDestinationHandler : public AudioHandler, public AudioIOCallback {
+// The AudioDestinationHandler (ADH) is a base class for the rendering backend
+// for AudioDestinatioNode. It contains common information required for the
+// rendering such as current sample frame, sample rate and maximum channel count
+// of the context.
+class AudioDestinationHandler : public AudioHandler {
public:
AudioDestinationHandler(AudioNode&);
~AudioDestinationHandler() override;
- // AudioHandler
- void Process(size_t) final {
- } // we're pulled by hardware so this is never called
-
- // The audio hardware calls render() to get the next render quantum of audio
- // into destinationBus. It will optionally give us local/live audio input in
- // sourceBus (if it's not 0).
- void Render(AudioBus* source_bus,
- AudioBus* destination_bus,
- size_t number_of_frames,
- const AudioIOPosition& output_position) final;
-
- size_t CurrentSampleFrame() const {
- return AcquireLoad(&current_sample_frame_);
- }
- double CurrentTime() const {
- return CurrentSampleFrame() / static_cast<double>(SampleRate());
- }
-
- virtual unsigned long MaxChannelCount() const { return 0; }
+ // The method MUST NOT be invoked when rendering a graph because the
+ // destination node is a sink. Instead, this node gets pulled by the
+ // underlying renderer (audio hardware or worker thread).
+ void Process(size_t) final { NOTREACHED(); }
virtual void StartRendering() = 0;
virtual void StopRendering() = 0;
@@ -71,60 +53,50 @@ class AudioDestinationHandler : public AudioHandler, public AudioIOCallback {
// restart of the context.
virtual void RestartRendering() = 0;
- // Returns the rendering callback buffer size.
- size_t CallbackBufferSize() const override = 0;
+ size_t CurrentSampleFrame() const {
+ return AcquireLoad(&current_sample_frame_);
+ }
+
+ double CurrentTime() const {
+ return CurrentSampleFrame() / SampleRate();
+ }
+
virtual double SampleRate() const = 0;
+ virtual unsigned long MaxChannelCount() const = 0;
- // Returns the audio buffer size in frames used by the AudioContext.
- virtual int FramesPerBuffer() const = 0;
+ void ContextDestroyed() { is_execution_context_destroyed_ = true; }
+ bool IsExecutionContextDestroyed() const {
+ return is_execution_context_destroyed_;
+ }
protected:
- // LocalAudioInputProvider allows us to expose an AudioSourceProvider for
- // local/live audio input. If there is local/live audio input, we call set()
- // with the audio input data every render quantum.
- class LocalAudioInputProvider final : public AudioSourceProvider {
- public:
- LocalAudioInputProvider()
- : source_bus_(AudioBus::Create(
- 2,
- AudioUtilities::kRenderQuantumFrames)) // FIXME: handle
- // non-stereo local input.
- {}
-
- void Set(AudioBus* bus) {
- if (bus)
- source_bus_->CopyFrom(*bus);
- }
-
- // AudioSourceProvider.
- void ProvideInput(AudioBus* destination_bus,
- size_t number_of_frames) override {
- bool is_good = destination_bus &&
- destination_bus->length() == number_of_frames &&
- source_bus_->length() == number_of_frames;
- DCHECK(is_good);
- if (is_good)
- destination_bus->CopyFrom(*source_bus_);
- }
-
- private:
- scoped_refptr<AudioBus> source_bus_;
- };
-
- // Counts the number of sample-frames processed by the destination.
+ // The number of sample frames processed by the destination so far.
size_t current_sample_frame_;
- LocalAudioInputProvider local_audio_input_provider_;
+ private:
+ // True if the execution context is being destroyed. If this is true, the
+ // destination ndoe must avoid checking for or accessing the execution
+ // context.
+ bool is_execution_context_destroyed_ = false;
};
+// -----------------------------------------------------------------------------
+
+// AudioDestinationNode (ADN) is a base class of two different types of nodes:
+// 1. DefaultDestinationNode for AudioContext (real time)
+// 2. OfflineDestinationNode for OfflineAudioContext (non-real time)
+// They have different rendering mechanisms, so the AudioDestinationHandler
+// (ADH), which is a counterpart of the destination node, encapsulates a
+// different rendering backend.
class AudioDestinationNode : public AudioNode {
DEFINE_WRAPPERTYPEINFO();
public:
- AudioDestinationHandler& GetAudioDestinationHandler() const;
-
unsigned long maxChannelCount() const;
- size_t CallbackBufferSize() const { return Handler().CallbackBufferSize(); }
+
+ // Returns its own handler object instead of a generic one from
+ // AudioNode::Handler().
+ AudioDestinationHandler& GetAudioDestinationHandler() const;
protected:
AudioDestinationNode(BaseAudioContext&);
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_node.cc
index 8e21999bb3f..1fcc1afca2c 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_node.cc
@@ -23,15 +23,14 @@
* DAMAGE.
*/
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_input.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_options.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
#include "third_party/blink/renderer/modules/webaudio/audio_param.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/instance_counters.h"
#include "third_party/blink/renderer/platform/wtf/atomics.h"
@@ -233,11 +232,12 @@ void AudioHandler::SetChannelCount(unsigned long channel_count,
}
} else {
exception_state.ThrowDOMException(
- kNotSupportedError, ExceptionMessages::IndexOutsideRange<unsigned long>(
- "channel count", channel_count, 1,
- ExceptionMessages::kInclusiveBound,
- BaseAudioContext::MaxNumberOfChannels(),
- ExceptionMessages::kInclusiveBound));
+ DOMExceptionCode::kNotSupportedError,
+ ExceptionMessages::IndexOutsideRange<unsigned long>(
+ "channel count", channel_count, 1,
+ ExceptionMessages::kInclusiveBound,
+ BaseAudioContext::MaxNumberOfChannels(),
+ ExceptionMessages::kInclusiveBound));
}
}
@@ -406,7 +406,7 @@ void AudioHandler::UnsilenceOutputs() {
void AudioHandler::EnableOutputsIfNecessary() {
DCHECK(IsMainThread());
- BaseAudioContext::GraphAutoLocker locker(Context());
+ DCHECK(Context()->IsGraphOwner());
// We're enabling outputs for this handler. Remove this from the tail
// processing list (if it's there) so that we don't inadvertently disable the
@@ -511,6 +511,8 @@ void AudioHandler::BreakConnection() {
}
void AudioHandler::BreakConnectionWithLock() {
+ DCHECK(Context()->IsGraphOwner());
+
AtomicDecrement(&connection_ref_count_);
#if DEBUG_AUDIONODE_REFERENCES
@@ -671,13 +673,13 @@ AudioNode* AudioNode::connect(AudioNode* destination,
if (context()->IsContextClosed()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Cannot connect after the context has been closed.");
return nullptr;
}
if (!destination) {
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"invalid destination node.");
return nullptr;
}
@@ -685,24 +687,25 @@ AudioNode* AudioNode::connect(AudioNode* destination,
// Sanity check input and output indices.
if (output_index >= numberOfOutputs()) {
exception_state.ThrowDOMException(
- kIndexSizeError, "output index (" + String::Number(output_index) +
- ") exceeds number of outputs (" +
- String::Number(numberOfOutputs()) + ").");
+ DOMExceptionCode::kIndexSizeError,
+ "output index (" + String::Number(output_index) +
+ ") exceeds number of outputs (" +
+ String::Number(numberOfOutputs()) + ").");
return nullptr;
}
if (destination && input_index >= destination->numberOfInputs()) {
exception_state.ThrowDOMException(
- kIndexSizeError, "input index (" + String::Number(input_index) +
- ") exceeds number of inputs (" +
- String::Number(destination->numberOfInputs()) +
- ").");
+ DOMExceptionCode::kIndexSizeError,
+ "input index (" + String::Number(input_index) +
+ ") exceeds number of inputs (" +
+ String::Number(destination->numberOfInputs()) + ").");
return nullptr;
}
if (context() != destination->context()) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"cannot connect to a destination "
"belonging to a different audio context.");
return nullptr;
@@ -713,7 +716,7 @@ AudioNode* AudioNode::connect(AudioNode* destination,
// receive? Just disallow this.
if (Handler().GetNodeType() == AudioHandler::kNodeTypeScriptProcessor &&
Handler().NumberOfOutputChannels() == 0) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"cannot connect a ScriptProcessorNode "
"with 0 output channels to any "
"destination node.");
@@ -727,8 +730,7 @@ AudioNode* AudioNode::connect(AudioNode* destination,
connected_nodes_[output_index] = new HeapHashSet<Member<AudioNode>>();
connected_nodes_[output_index]->insert(destination);
- // Let context know that a connection has been made.
- context()->IncrementConnectionCount();
+ Handler().UpdatePullStatusIfNeeded();
return destination;
}
@@ -741,27 +743,29 @@ void AudioNode::connect(AudioParam* param,
if (context()->IsContextClosed()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Cannot connect after the context has been closed.");
return;
}
if (!param) {
- exception_state.ThrowDOMException(kSyntaxError, "invalid AudioParam.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
+ "invalid AudioParam.");
return;
}
if (output_index >= numberOfOutputs()) {
exception_state.ThrowDOMException(
- kIndexSizeError, "output index (" + String::Number(output_index) +
- ") exceeds number of outputs (" +
- String::Number(numberOfOutputs()) + ").");
+ DOMExceptionCode::kIndexSizeError,
+ "output index (" + String::Number(output_index) +
+ ") exceeds number of outputs (" +
+ String::Number(numberOfOutputs()) + ").");
return;
}
if (context() != param->Context()) {
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"cannot connect to an AudioParam "
"belonging to a different audio context.");
return;
@@ -771,6 +775,8 @@ void AudioNode::connect(AudioParam* param,
if (!connected_params_[output_index])
connected_params_[output_index] = new HeapHashSet<Member<AudioParam>>();
connected_params_[output_index]->insert(param);
+
+ Handler().UpdatePullStatusIfNeeded();
}
void AudioNode::DisconnectAllFromOutput(unsigned output_index) {
@@ -810,6 +816,8 @@ void AudioNode::disconnect() {
// Disconnect all outgoing connections.
for (unsigned i = 0; i < numberOfOutputs(); ++i)
DisconnectAllFromOutput(i);
+
+ Handler().UpdatePullStatusIfNeeded();
}
void AudioNode::disconnect(unsigned output_index,
@@ -820,7 +828,7 @@ void AudioNode::disconnect(unsigned output_index,
// Sanity check on the output index.
if (output_index >= numberOfOutputs()) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
ExceptionMessages::IndexOutsideRange(
"output index", output_index, 0u,
ExceptionMessages::kInclusiveBound, numberOfOutputs() - 1,
@@ -829,6 +837,8 @@ void AudioNode::disconnect(unsigned output_index,
}
// Disconnect all outgoing connections from the given output.
DisconnectAllFromOutput(output_index);
+
+ Handler().UpdatePullStatusIfNeeded();
}
void AudioNode::disconnect(AudioNode* destination,
@@ -853,9 +863,12 @@ void AudioNode::disconnect(AudioNode* destination,
// If there is no connection to the destination, throw an exception.
if (number_of_disconnections == 0) {
exception_state.ThrowDOMException(
- kInvalidAccessError, "the given destination is not connected.");
+ DOMExceptionCode::kInvalidAccessError,
+ "the given destination is not connected.");
return;
}
+
+ Handler().UpdatePullStatusIfNeeded();
}
void AudioNode::disconnect(AudioNode* destination,
@@ -867,7 +880,7 @@ void AudioNode::disconnect(AudioNode* destination,
if (output_index >= numberOfOutputs()) {
// The output index is out of range. Throw an exception.
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
ExceptionMessages::IndexOutsideRange(
"output index", output_index, 0u,
ExceptionMessages::kInclusiveBound, numberOfOutputs() - 1,
@@ -888,10 +901,12 @@ void AudioNode::disconnect(AudioNode* destination,
// If there is no connection to the destination, throw an exception.
if (number_of_disconnections == 0) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"output (" + String::Number(output_index) +
") is not connected to the given destination.");
}
+
+ Handler().UpdatePullStatusIfNeeded();
}
void AudioNode::disconnect(AudioNode* destination,
@@ -903,7 +918,7 @@ void AudioNode::disconnect(AudioNode* destination,
if (output_index >= numberOfOutputs()) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
ExceptionMessages::IndexOutsideRange(
"output index", output_index, 0u,
ExceptionMessages::kInclusiveBound, numberOfOutputs() - 1,
@@ -913,7 +928,7 @@ void AudioNode::disconnect(AudioNode* destination,
if (input_index >= destination->Handler().NumberOfInputs()) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
ExceptionMessages::IndexOutsideRange(
"input index", input_index, 0u, ExceptionMessages::kInclusiveBound,
destination->numberOfInputs() - 1,
@@ -925,12 +940,14 @@ void AudioNode::disconnect(AudioNode* destination,
if (!DisconnectFromOutputIfConnected(output_index, *destination,
input_index)) {
exception_state.ThrowDOMException(
- kInvalidAccessError, "output (" + String::Number(output_index) +
- ") is not connected to the input (" +
- String::Number(input_index) +
- ") of the destination.");
+ DOMExceptionCode::kInvalidAccessError,
+ "output (" + String::Number(output_index) +
+ ") is not connected to the input (" + String::Number(input_index) +
+ ") of the destination.");
return;
}
+
+ Handler().UpdatePullStatusIfNeeded();
}
void AudioNode::disconnect(AudioParam* destination_param,
@@ -951,10 +968,12 @@ void AudioNode::disconnect(AudioParam* destination_param,
// Throw an exception when there is no valid connection to the destination.
if (number_of_disconnections == 0) {
- exception_state.ThrowDOMException(kInvalidAccessError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidAccessError,
"the given AudioParam is not connected.");
return;
}
+
+ Handler().UpdatePullStatusIfNeeded();
}
void AudioNode::disconnect(AudioParam* destination_param,
@@ -966,7 +985,7 @@ void AudioNode::disconnect(AudioParam* destination_param,
if (output_index >= Handler().NumberOfOutputs()) {
// The output index is out of range. Throw an exception.
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
ExceptionMessages::IndexOutsideRange(
"output index", output_index, 0u,
ExceptionMessages::kInclusiveBound, numberOfOutputs() - 1,
@@ -977,21 +996,13 @@ void AudioNode::disconnect(AudioParam* destination_param,
// If the output index is valid, proceed to disconnect.
if (!DisconnectFromOutputIfConnected(output_index, *destination_param)) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"specified destination AudioParam and node output (" +
String::Number(output_index) + ") are not connected.");
return;
}
-}
-
-void AudioNode::DisconnectWithoutException(unsigned output_index) {
- DCHECK(IsMainThread());
- BaseAudioContext::GraphAutoLocker locker(context());
- // Sanity check input and output indices.
- if (output_index >= Handler().NumberOfOutputs())
- return;
- DisconnectAllFromOutput(output_index);
+ Handler().UpdatePullStatusIfNeeded();
}
unsigned AudioNode::numberOfInputs() const {
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_node.h b/chromium/third_party/blink/renderer/modules/webaudio/audio_node.h
index 306447565a9..e16e9596b90 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_node.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_node.h
@@ -238,10 +238,9 @@ class MODULES_EXPORT AudioHandler : public ThreadSafeRefCounted<AudioHandler> {
void UpdateChannelCountMode();
void UpdateChannelInterpretation();
- // Default callbackBufferSize should be the render quantum size
- virtual size_t CallbackBufferSize() const {
- return AudioUtilities::kRenderQuantumFrames;
- }
+ // Called when this node's outputs may have become connected or disconnected
+ // to handle automatic pull nodes.
+ virtual void UpdatePullStatusIfNeeded() {}
protected:
// Inputs and outputs must be created before the AudioHandler is
@@ -320,13 +319,13 @@ class MODULES_EXPORT AudioNode : public EventTargetWithInlineData {
void HandleChannelOptions(const AudioNodeOptions&, ExceptionState&);
- virtual AudioNode* connect(AudioNode*,
- unsigned output_index,
- unsigned input_index,
- ExceptionState&);
+ AudioNode* connect(AudioNode*,
+ unsigned output_index,
+ unsigned input_index,
+ ExceptionState&);
void connect(AudioParam*, unsigned output_index, ExceptionState&);
void disconnect();
- virtual void disconnect(unsigned output_index, ExceptionState&);
+ void disconnect(unsigned output_index, ExceptionState&);
void disconnect(AudioNode*, ExceptionState&);
void disconnect(AudioNode*, unsigned output_index, ExceptionState&);
void disconnect(AudioNode*,
@@ -351,9 +350,6 @@ class MODULES_EXPORT AudioNode : public EventTargetWithInlineData {
// Called inside AudioHandler constructors.
void DidAddOutput(unsigned number_of_outputs);
- // Like disconnect, but no exception is thrown if the outputIndex is invalid.
- // Just do nothing in that case.
- void DisconnectWithoutException(unsigned output_index);
protected:
explicit AudioNode(BaseAudioContext&);
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_node_output.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_node_output.cc
index d3084c44bb6..c229c43406d 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_node_output.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_node_output.cc
@@ -170,7 +170,7 @@ void AudioNodeOutput::AddInput(AudioNodeInput& input) {
void AudioNodeOutput::RemoveInput(AudioNodeInput& input) {
DCHECK(GetDeferredTaskHandler().IsGraphOwner());
- input.Handler().BreakConnection();
+ input.Handler().BreakConnectionWithLock();
inputs_.erase(&input);
}
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc
index 14df3dc8398..2d596c59c27 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_param.cc
@@ -25,11 +25,11 @@
#include "third_party/blink/renderer/modules/webaudio/audio_param.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
@@ -436,7 +436,7 @@ void AudioParam::setAutomationRate(const String& rate,
ExceptionState& exception_state) {
if (Handler().IsAutomationRateFixed()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
Handler().GetParamName() +
".automationRate is fixed and cannot be changed to \"" + rate +
"\"");
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_param_map.h b/chromium/third_party/blink/renderer/modules/webaudio/audio_param_map.h
index 8815e8e1f09..052b53b37e4 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_param_map.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_param_map.h
@@ -5,10 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_AUDIO_PARAM_MAP_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_AUDIO_PARAM_MAP_H_
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/modules/webaudio/audio_param.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/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
index 6a67251bdac..12737c6e218 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
@@ -30,12 +30,11 @@
#include "base/memory/ptr_util.h"
#include "build/build_config.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/cpu.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
@@ -493,7 +492,7 @@ void AudioParamTimeline::SetValueCurveAtTime(const Vector<float>& curve,
if (curve.size() < 2) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
ExceptionMessages::IndexExceedsMinimumBound(
"curve length", curve.size(), static_cast<size_t>(2)));
return;
@@ -555,7 +554,7 @@ void AudioParamTimeline::InsertEvent(std::unique_ptr<ParamEvent> event,
test_type == ParamEvent::kCancelValues) &&
events_[i]->Time() > event->Time() && events_[i]->Time() < end_time) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
EventToString(*event) + " overlaps " + EventToString(*events_[i]));
return;
}
@@ -567,8 +566,9 @@ void AudioParamTimeline::InsertEvent(std::unique_ptr<ParamEvent> event,
if (event->GetType() != ParamEvent::kSetValueCurveEnd &&
event->Time() >= events_[i]->Time() && event->Time() < end_time) {
exception_state.ThrowDOMException(
- kNotSupportedError, EventToString(*event) + " overlaps " +
- EventToString(*events_[i]));
+ DOMExceptionCode::kNotSupportedError,
+ EventToString(*event) + " overlaps " +
+ EventToString(*events_[i]));
return;
}
}
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.cc
index f42ff28bbda..27936b87f28 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.cc
@@ -26,14 +26,15 @@
#include "third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.h"
#include <algorithm>
+
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/event_modules.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/web_task_runner.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
namespace blink {
@@ -164,10 +165,10 @@ void AudioScheduledSourceHandler::Start(double when,
ExceptionState& exception_state) {
DCHECK(IsMainThread());
- Context()->MaybeRecordStartAttempt();
+ Context()->NotifySourceNodeStart();
if (GetPlaybackState() != UNSCHEDULED_STATE) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"cannot call start more than once.");
return;
}
@@ -200,7 +201,8 @@ void AudioScheduledSourceHandler::Stop(double when,
if (GetPlaybackState() == UNSCHEDULED_STATE) {
exception_state.ThrowDOMException(
- kInvalidStateError, "cannot call stop without calling start first.");
+ DOMExceptionCode::kInvalidStateError,
+ "cannot call stop without calling start first.");
return;
}
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet.cc
index 38678861a93..a6fba8c4a19 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet.cc
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/core/workers/worker_clients.h"
#include "third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_worklet_node.h"
#include "third_party/blink/renderer/modules/webaudio/cross_thread_audio_worklet_processor_info.h"
namespace blink {
@@ -23,12 +24,12 @@ AudioWorklet::AudioWorklet(BaseAudioContext* context)
: Worklet(ToDocument(context->GetExecutionContext())), context_(context) {}
void AudioWorklet::CreateProcessor(
- AudioWorkletHandler* handler,
+ scoped_refptr<AudioWorkletHandler> handler,
MessagePortChannel message_port_channel,
scoped_refptr<SerializedScriptValue> node_options) {
DCHECK(IsMainThread());
DCHECK(GetMessagingProxy());
- GetMessagingProxy()->CreateProcessor(handler,
+ GetMessagingProxy()->CreateProcessor(std::move(handler),
std::move(message_port_channel),
std::move(node_options));
}
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet.h b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet.h
index 19c48976811..dd82c715c43 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet.h
@@ -30,7 +30,7 @@ class MODULES_EXPORT AudioWorklet final : public Worklet {
~AudioWorklet() override = default;
- void CreateProcessor(AudioWorkletHandler*,
+ void CreateProcessor(scoped_refptr<AudioWorkletHandler>,
MessagePortChannel,
scoped_refptr<SerializedScriptValue> node_options);
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc
index d89c2493eb4..9dc2b84f96d 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.cc
@@ -17,7 +17,6 @@
#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_param_descriptor.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_worklet_processor.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/messaging/message_port.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
@@ -65,7 +64,7 @@ void AudioWorkletGlobalScope::registerProcessor(
if (processor_definition_map_.Contains(name)) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"A class with name:'" + name + "' is already registered.");
return;
}
@@ -290,10 +289,22 @@ bool AudioWorkletGlobalScope::Process(
for (const auto& param : *param_value_map) {
const String& param_name = param.key;
const AudioFloatArray* param_array = param.value.get();
+
+ // If the AudioParam is constant, then the param array should have length 1.
+ // Manually check to see if the parameter is truly constant.
+ unsigned array_size = 1;
+
+ for (unsigned k = 1; k < param_array->size(); ++k) {
+ if (param_array->Data()[k] != param_array->Data()[0]) {
+ array_size = param_array->size();
+ break;
+ }
+ }
+
v8::Local<v8::ArrayBuffer> array_buffer =
- v8::ArrayBuffer::New(isolate, param_array->size() * sizeof(float));
+ v8::ArrayBuffer::New(isolate, array_size * sizeof(float));
v8::Local<v8::Float32Array> float32_array =
- v8::Float32Array::New(array_buffer, 0, param_array->size());
+ v8::Float32Array::New(array_buffer, 0, array_size);
bool success;
if (!param_values
->CreateDataProperty(current_context,
@@ -303,8 +314,7 @@ bool AudioWorkletGlobalScope::Process(
return false;
}
const v8::ArrayBuffer::Contents& contents = array_buffer->GetContents();
- memcpy(contents.Data(), param_array->Data(),
- param_array->size() * sizeof(float));
+ memcpy(contents.Data(), param_array->Data(), array_size * sizeof(float));
}
v8::Local<v8::Value> argv[] = {inputs, outputs, param_values};
@@ -394,15 +404,4 @@ void AudioWorkletGlobalScope::Trace(blink::Visitor* visitor) {
ThreadedWorkletGlobalScope::Trace(visitor);
}
-void AudioWorkletGlobalScope::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- for (auto definition : processor_definition_map_)
- visitor->TraceWrappers(definition.value);
-
- for (auto processor : processor_instances_)
- visitor->TraceWrappers(processor);
-
- ThreadedWorkletGlobalScope::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.h b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.h
index ccb7df1c519..d92c0055a41 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.h
@@ -103,7 +103,6 @@ class MODULES_EXPORT AudioWorkletGlobalScope final
float sampleRate() const { return sample_rate_; }
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
AudioWorkletGlobalScope(std::unique_ptr<GlobalScopeCreationParams>,
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc
index 30c15d49774..59e564d2255 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc
@@ -70,14 +70,12 @@ class AudioWorkletGlobalScopeTest : public PageTestBase {
thread->Start(
std::make_unique<GlobalScopeCreationParams>(
document->Url(), ScriptType::kModule, document->UserAgent(),
- nullptr /* content_security_policy_parsed_headers */,
- document->GetReferrerPolicy(), document->GetSecurityOrigin(),
- document->IsSecureContext(), nullptr /* worker_clients */,
- document->AddressSpace(),
+ Vector<CSPHeaderAndType>(), document->GetReferrerPolicy(),
+ document->GetSecurityOrigin(), document->IsSecureContext(),
+ nullptr /* worker_clients */, document->AddressSpace(),
OriginTrialContext::GetTokens(document).get(),
base::UnguessableToken::Create(), nullptr /* worker_settings */,
- kV8CacheOptionsDefault,
- new WorkletModuleResponsesMap(document->Fetcher())),
+ kV8CacheOptionsDefault, new WorkletModuleResponsesMap),
base::nullopt, WorkerInspectorProxy::PauseOnWorkerStart::kDontPause,
ParentExecutionContextTaskRunners::Create());
return thread;
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.cc
index 996496a7b82..479330b64c2 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.cc
@@ -23,7 +23,7 @@ AudioWorkletMessagingProxy::AudioWorkletMessagingProxy(
: ThreadedWorkletMessagingProxy(execution_context), worklet_(worklet) {}
void AudioWorkletMessagingProxy::CreateProcessor(
- AudioWorkletHandler* handler,
+ scoped_refptr<AudioWorkletHandler> handler,
MessagePortChannel message_port_channel,
scoped_refptr<SerializedScriptValue> node_options) {
DCHECK(IsMainThread());
@@ -33,7 +33,7 @@ void AudioWorkletMessagingProxy::CreateProcessor(
&AudioWorkletMessagingProxy::CreateProcessorOnRenderingThread,
WrapCrossThreadPersistent(this),
CrossThreadUnretained(GetWorkerThread()),
- CrossThreadUnretained(handler),
+ handler,
handler->Name(),
std::move(message_port_channel),
std::move(node_options)));
@@ -41,7 +41,7 @@ void AudioWorkletMessagingProxy::CreateProcessor(
void AudioWorkletMessagingProxy::CreateProcessorOnRenderingThread(
WorkerThread* worker_thread,
- AudioWorkletHandler* handler,
+ scoped_refptr<AudioWorkletHandler> handler,
const String& name,
MessagePortChannel message_port_channel,
scoped_refptr<SerializedScriptValue> node_options) {
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h
index 58d238a8ebf..c961ded1fc8 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h
@@ -16,6 +16,7 @@ class CrossThreadAudioParamInfo;
class CrossThreadAudioWorkletProcessorInfo;
class ExecutionContext;
class MessagePortChannel;
+class SerializedScriptValue;
class WorkerThread;
// AudioWorkletMessagingProxy is a main thread interface for
@@ -27,7 +28,7 @@ class AudioWorkletMessagingProxy final : public ThreadedWorkletMessagingProxy {
// Since the creation of AudioWorkletProcessor needs to be done in the
// different thread, this method is a wrapper for cross-thread task posting.
- void CreateProcessor(AudioWorkletHandler*,
+ void CreateProcessor(scoped_refptr<AudioWorkletHandler>,
MessagePortChannel,
scoped_refptr<SerializedScriptValue> node_options);
@@ -35,7 +36,7 @@ class AudioWorkletMessagingProxy final : public ThreadedWorkletMessagingProxy {
// AudioWorkletProcessor.
void CreateProcessorOnRenderingThread(
WorkerThread*,
- AudioWorkletHandler*,
+ scoped_refptr<AudioWorkletHandler>,
const String& name,
MessagePortChannel,
scoped_refptr<SerializedScriptValue> node_options);
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.cc
index 891d36f26ea..7dc449ad697 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.cc
@@ -19,6 +19,7 @@
#include "third_party/blink/renderer/modules/webaudio/cross_thread_audio_worklet_processor_info.h"
#include "third_party/blink/renderer/platform/audio/audio_bus.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
@@ -262,18 +263,18 @@ AudioWorkletNode* AudioWorkletNode::Create(
if (options.numberOfInputs() == 0 && options.numberOfOutputs() == 0) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"AudioWorkletNode cannot be created: Number of inputs and number of "
- "outputs cannot be both zero.");
+ "outputs cannot be both zero.");
return nullptr;
}
if (options.hasOutputChannelCount()) {
if (options.numberOfOutputs() != options.outputChannelCount().size()) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
"AudioWorkletNode cannot be created: Length of specified "
- "'outputChannelCount' (" +
+ "'outputChannelCount' (" +
String::Number(options.outputChannelCount().size()) +
") does not match the given number of outputs (" +
String::Number(options.numberOfOutputs()) + ").");
@@ -284,10 +285,9 @@ AudioWorkletNode* AudioWorkletNode::Create(
if (channel_count < 1 ||
channel_count > BaseAudioContext::MaxNumberOfChannels()) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
ExceptionMessages::IndexOutsideRange<unsigned long>(
- "channel count", channel_count,
- 1,
+ "channel count", channel_count, 1,
ExceptionMessages::kInclusiveBound,
BaseAudioContext::MaxNumberOfChannels(),
ExceptionMessages::kInclusiveBound));
@@ -298,16 +298,16 @@ AudioWorkletNode* AudioWorkletNode::Create(
if (!context->audioWorklet()->IsReady()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"AudioWorkletNode cannot be created: AudioWorklet does not have a "
- "valid AudioWorkletGlobalScope. Load a script via "
- "audioWorklet.addModule() first.");
+ "valid AudioWorkletGlobalScope. Load a script via "
+ "audioWorklet.addModule() first.");
return nullptr;
}
if (!context->audioWorklet()->IsProcessorRegistered(name)) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"AudioWorkletNode cannot be created: The node name '" + name +
"' is not defined in AudioWorkletGlobalScope.");
return nullptr;
@@ -323,9 +323,8 @@ AudioWorkletNode* AudioWorkletNode::Create(
channel->port1());
if (!node) {
- exception_state.ThrowDOMException(
- kInvalidStateError,
- "AudioWorkletNode cannot be created.");
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "AudioWorkletNode cannot be created.");
return nullptr;
}
@@ -360,7 +359,7 @@ AudioWorkletNode* AudioWorkletNode::Create(
// This is non-blocking async call. |node| still can be returned to user
// before the scheduled async task is completed.
- context->audioWorklet()->CreateProcessor(&node->GetWorkletHandler(),
+ context->audioWorklet()->CreateProcessor(node->GetWorkletHandler(),
std::move(processor_port_channel),
std::move(serialized_node_options));
@@ -383,8 +382,8 @@ void AudioWorkletNode::FireProcessorError() {
DispatchEvent(Event::Create(EventTypeNames::processorerror));
}
-AudioWorkletHandler& AudioWorkletNode::GetWorkletHandler() const {
- return static_cast<AudioWorkletHandler&>(Handler());
+scoped_refptr<AudioWorkletHandler> AudioWorkletNode::GetWorkletHandler() const {
+ return WrapRefCounted(&static_cast<AudioWorkletHandler&>(Handler()));
}
void AudioWorkletNode::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.h b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.h
index 16b44b018bd..be38e866031 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_node.h
@@ -99,8 +99,6 @@ class AudioWorkletNode final : public AudioNode,
const AudioWorkletNodeOptions&,
ExceptionState&);
- AudioWorkletHandler& GetWorkletHandler() const;
-
// ActiveScriptWrappable
bool HasPendingActivity() const final;
@@ -120,6 +118,8 @@ class AudioWorkletNode final : public AudioNode,
const Vector<CrossThreadAudioParamInfo>,
MessagePort* node_port);
+ scoped_refptr<AudioWorkletHandler> GetWorkletHandler() const;
+
Member<AudioParamMap> parameter_map_;
Member<MessagePort> node_port_;
};
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor_definition.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor_definition.cc
index 41da6268858..b3cc204dc0c 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor_definition.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor_definition.cc
@@ -63,10 +63,4 @@ const AudioParamDescriptor*
return nullptr;
}
-void AudioWorkletProcessorDefinition::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(constructor_.Cast<v8::Value>());
- visitor->TraceWrappers(process_.Cast<v8::Value>());
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor_definition.h b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor_definition.h
index 6de972b8019..b5100163ee7 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor_definition.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_processor_definition.h
@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/webaudio/audio_param_descriptor.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -24,7 +24,7 @@ namespace blink {
// must be called on the worker thread.
class MODULES_EXPORT AudioWorkletProcessorDefinition final
: public GarbageCollectedFinalized<AudioWorkletProcessorDefinition>,
- public TraceWrapperBase {
+ public NameClient {
public:
static AudioWorkletProcessorDefinition* Create(
v8::Isolate*,
@@ -47,9 +47,10 @@ class MODULES_EXPORT AudioWorkletProcessorDefinition final
void MarkAsSynchronized() { is_synchronized_ = true; }
void Trace(blink::Visitor* visitor) {
+ visitor->Trace(constructor_.Cast<v8::Value>());
+ visitor->Trace(process_.Cast<v8::Value>());
visitor->Trace(audio_param_descriptors_);
};
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "AudioWorkletProcessorDefinition";
}
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc
index 6f537798a8d..060c0164670 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc
@@ -54,14 +54,12 @@ class AudioWorkletThreadTest : public PageTestBase {
thread->Start(
std::make_unique<GlobalScopeCreationParams>(
document->Url(), ScriptType::kModule, document->UserAgent(),
- nullptr /* content_security_policy_parsed_headers */,
- document->GetReferrerPolicy(), document->GetSecurityOrigin(),
- document->IsSecureContext(), nullptr /* worker_clients */,
- document->AddressSpace(),
+ Vector<CSPHeaderAndType>(), document->GetReferrerPolicy(),
+ document->GetSecurityOrigin(), document->IsSecureContext(),
+ nullptr /* worker_clients */, document->AddressSpace(),
OriginTrialContext::GetTokens(document).get(),
base::UnguessableToken::Create(), nullptr /* worker_settings */,
- kV8CacheOptionsDefault,
- new WorkletModuleResponsesMap(document->Fetcher())),
+ kV8CacheOptionsDefault, new WorkletModuleResponsesMap),
base::nullopt, WorkerInspectorProxy::PauseOnWorkerStart::kDontPause,
ParentExecutionContextTaskRunners::Create());
return thread;
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.cc b/chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.cc
index 44244ea5865..f30bd880a15 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.cc
@@ -29,14 +29,10 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/dom/exception_code.h"
#include "third_party/blink/renderer/core/frame/settings.h"
-#include "third_party/blink/renderer/core/html/media/autoplay_policy.h"
#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_types.h"
@@ -73,7 +69,9 @@
#include "third_party/blink/renderer/modules/webaudio/script_processor_node.h"
#include "third_party/blink/renderer/modules/webaudio/stereo_panner_node.h"
#include "third_party/blink/renderer/modules/webaudio/wave_shaper_node.h"
+#include "third_party/blink/renderer/platform/uuid.h"
#include "third_party/blink/renderer/platform/audio/iir_filter.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/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/histogram.h"
@@ -93,53 +91,23 @@ BaseAudioContext::BaseAudioContext(Document* document,
enum ContextType context_type)
: PausableObject(document),
destination_node_(nullptr),
+ uuid_(CreateCanonicalUUIDString()),
is_cleared_(false),
is_resolving_resume_promises_(false),
has_posted_cleanup_task_(false),
- user_gesture_required_(false),
- connection_count_(0),
deferred_task_handler_(DeferredTaskHandler::Create()),
context_state_(kSuspended),
- closed_context_sample_rate_(-1),
periodic_wave_sine_(nullptr),
periodic_wave_square_(nullptr),
periodic_wave_sawtooth_(nullptr),
periodic_wave_triangle_(nullptr),
- output_position_() {
- switch (context_type) {
- case kRealtimeContext:
- switch (GetAutoplayPolicy()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- break;
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- if (document->GetFrame() &&
- document->GetFrame()->IsCrossOriginSubframe()) {
- autoplay_status_ = AutoplayStatus::kAutoplayStatusFailed;
- user_gesture_required_ = true;
- }
- break;
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- autoplay_status_ = AutoplayStatus::kAutoplayStatusFailed;
- user_gesture_required_ = true;
- break;
- }
- break;
- case kOfflineContext:
- // Nothing needed for offline context
- break;
- default:
- NOTREACHED();
- break;
- }
-}
+ output_position_() {}
BaseAudioContext::~BaseAudioContext() {
GetDeferredTaskHandler().ContextWillBeDestroyed();
DCHECK(!active_source_nodes_.size());
DCHECK(!is_resolving_resume_promises_);
DCHECK(!resume_resolvers_.size());
- DCHECK(!autoplay_status_.has_value());
}
void BaseAudioContext::Initialize() {
@@ -152,6 +120,14 @@ void BaseAudioContext::Initialize() {
if (destination_node_) {
destination_node_->Handler().Initialize();
+ // TODO(crbug.com/863951). The audio thread needs some things from the
+ // destination handler like the currentTime. But the audio thread
+ // shouldn't access the |destination_node_| since it's an Oilpan object.
+ // Thus, get the destination handler, a non-oilpan object, so we can get
+ // the items directly from the handler instead of through the destination
+ // node.
+ destination_handler_ = &destination_node_->GetAudioDestinationHandler();
+
// The AudioParams in the listener need access to the destination node, so
// only create the listener if the destination node exists.
listener_ = AudioListener::Create(*this);
@@ -184,17 +160,15 @@ void BaseAudioContext::Uninitialize() {
// Reject any pending resolvers before we go away.
RejectPendingResolvers();
- DidClose();
DCHECK(listener_);
listener_->WaitForHRTFDatabaseLoaderThreadCompletion();
- RecordAutoplayStatus();
-
Clear();
}
void BaseAudioContext::ContextDestroyed(ExecutionContext*) {
+ destination()->GetAudioDestinationHandler().ContextDestroyed();
Uninitialize();
}
@@ -218,7 +192,7 @@ AudioDestinationNode* BaseAudioContext::destination() const {
void BaseAudioContext::ThrowExceptionForClosedState(
ExceptionState& exception_state) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"AudioContext has been closed.");
}
@@ -305,10 +279,6 @@ ScriptPromise BaseAudioContext::decodeAudioData(
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
- float rate = IsContextClosed() ? ClosedContextSampleRate() : sampleRate();
-
- DCHECK_GT(rate, 0);
-
v8::Isolate* isolate = script_state->GetIsolate();
WTF::ArrayBufferContents buffer_contents;
// Detach the audio array buffer from the main thread and start
@@ -320,13 +290,14 @@ ScriptPromise BaseAudioContext::decodeAudioData(
decode_audio_resolvers_.insert(resolver);
audio_decoder_.DecodeAsync(
- audio, rate, ToV8PersistentCallbackFunction(success_callback),
+ audio, sampleRate(), ToV8PersistentCallbackFunction(success_callback),
ToV8PersistentCallbackFunction(error_callback), resolver, this);
} else {
// If audioData is already detached (neutered) we need to reject the
// promise with an error.
- DOMException* error = DOMException::Create(
- kDataCloneError, "Cannot decode detached ArrayBuffer");
+ DOMException* error =
+ DOMException::Create(DOMExceptionCode::kDataCloneError,
+ "Cannot decode detached ArrayBuffer");
resolver->Reject(error);
if (error_callback) {
error_callback->InvokeAndReportException(this, error);
@@ -350,8 +321,8 @@ void BaseAudioContext::HandleDecodeAudioData(
success_callback->InvokeAndReportException(this, audio_buffer);
} else {
// Reject the promise and run the error callback
- DOMException* error =
- DOMException::Create(kEncodingError, "Unable to decode audio data");
+ DOMException* error = DOMException::Create(DOMExceptionCode::kEncodingError,
+ "Unable to decode audio data");
resolver->Reject(error);
if (error_callback)
error_callback->InvokeAndReportException(this, error);
@@ -608,15 +579,6 @@ PeriodicWave* BaseAudioContext::GetPeriodicWave(int type) {
}
}
-void BaseAudioContext::MaybeRecordStartAttempt() {
- if (!user_gesture_required_ || !AreAutoplayRequirementsFulfilled())
- return;
-
- DCHECK(!autoplay_status_.has_value() ||
- autoplay_status_ != AutoplayStatus::kAutoplayStatusSucceeded);
- autoplay_status_ = AutoplayStatus::kAutoplayStatusFailedWithStart;
-}
-
String BaseAudioContext::state() const {
// These strings had better match the strings for AudioContextState in
// AudioContext.idl.
@@ -683,38 +645,6 @@ Document* BaseAudioContext::GetDocument() const {
return ToDocument(GetExecutionContext());
}
-AutoplayPolicy::Type BaseAudioContext::GetAutoplayPolicy() const {
- if (RuntimeEnabledFeatures::AutoplayIgnoresWebAudioEnabled()) {
-// When ignored, the policy is different on Android compared to Desktop.
-#if defined(OS_ANDROID)
- return AutoplayPolicy::Type::kUserGestureRequired;
-#else
- // Force no user gesture required on desktop.
- return AutoplayPolicy::Type::kNoUserGestureRequired;
-#endif
- }
-
- Document* document = GetDocument();
- DCHECK(document);
- return AutoplayPolicy::GetAutoplayPolicyForDocument(*document);
-}
-
-bool BaseAudioContext::AreAutoplayRequirementsFulfilled() const {
- switch (GetAutoplayPolicy()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- return true;
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- return Frame::HasTransientUserActivation(
- GetDocument() ? GetDocument()->GetFrame() : nullptr);
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- return AutoplayPolicy::IsDocumentAllowedToPlay(*GetDocument());
- }
-
- NOTREACHED();
- return false;
-}
-
void BaseAudioContext::NotifySourceNodeStartedProcessing(AudioNode* node) {
DCHECK(IsMainThread());
GraphAutoLocker locker(this);
@@ -792,7 +722,7 @@ void BaseAudioContext::PerformCleanupOnMainThread() {
for (auto& resolver : resume_resolvers_) {
if (context_state_ == kClosed) {
resolver->Reject(DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"Cannot resume a context that has been closed"));
} else {
SetContextState(kRunning);
@@ -827,7 +757,7 @@ void BaseAudioContext::PerformCleanupOnMainThread() {
for (AudioHandler* handler : finished_handlers) {
for (unsigned i = 0; i < active_source_nodes_.size(); ++i) {
if (handler == &active_source_nodes_[i]->Handler()) {
- handler->BreakConnection();
+ handler->BreakConnectionWithLock();
removables[i] = true;
remove_count++;
break;
@@ -882,53 +812,11 @@ void BaseAudioContext::ResolvePromisesForUnpause() {
void BaseAudioContext::RejectPendingDecodeAudioDataResolvers() {
// Now reject any pending decodeAudioData resolvers
for (auto& resolver : decode_audio_resolvers_)
- resolver->Reject(DOMException::Create(kInvalidStateError,
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kInvalidStateError,
"Audio context is going away"));
decode_audio_resolvers_.clear();
}
-void BaseAudioContext::MaybeUnlockUserGesture() {
- if (!user_gesture_required_ || !AreAutoplayRequirementsFulfilled())
- return;
-
- DCHECK(!autoplay_status_.has_value() ||
- autoplay_status_ != AutoplayStatus::kAutoplayStatusSucceeded);
-
- user_gesture_required_ = false;
- autoplay_status_ = AutoplayStatus::kAutoplayStatusSucceeded;
-}
-
-bool BaseAudioContext::IsAllowedToStart() const {
- if (!user_gesture_required_)
- return true;
-
- Document* document = ToDocument(GetExecutionContext());
- DCHECK(document);
-
- switch (GetAutoplayPolicy()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- NOTREACHED();
- break;
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- DCHECK(document->GetFrame() &&
- document->GetFrame()->IsCrossOriginSubframe());
- document->AddConsoleMessage(ConsoleMessage::Create(
- kOtherMessageSource, kWarningMessageLevel,
- "The AudioContext was not allowed to start. It must be resumed (or "
- "created) from a user gesture event handler."));
- break;
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- document->AddConsoleMessage(ConsoleMessage::Create(
- kOtherMessageSource, kWarningMessageLevel,
- "The AudioContext was not allowed to start. It must be resume (or "
- "created) after a user gesture on the page. https://goo.gl/7K7WLu"));
- break;
- }
-
- return false;
-}
-
AudioIOPosition BaseAudioContext::OutputPosition() {
DCHECK(IsMainThread());
GraphAutoLocker locker(this);
@@ -942,7 +830,7 @@ void BaseAudioContext::RejectPendingResolvers() {
// pending.
for (auto& resolver : resume_resolvers_) {
- resolver->Reject(DOMException::Create(kInvalidStateError,
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kInvalidStateError,
"Audio context is going away"));
}
resume_resolvers_.clear();
@@ -951,27 +839,6 @@ void BaseAudioContext::RejectPendingResolvers() {
RejectPendingDecodeAudioDataResolvers();
}
-void BaseAudioContext::RecordAutoplayStatus() {
- if (!autoplay_status_.has_value())
- return;
-
- DEFINE_STATIC_LOCAL(
- EnumerationHistogram, autoplay_histogram,
- ("WebAudio.Autoplay", AutoplayStatus::kAutoplayStatusCount));
- DEFINE_STATIC_LOCAL(
- EnumerationHistogram, cross_origin_autoplay_histogram,
- ("WebAudio.Autoplay.CrossOrigin", AutoplayStatus::kAutoplayStatusCount));
-
- autoplay_histogram.Count(autoplay_status_.value());
-
- if (GetDocument()->GetFrame() &&
- GetDocument()->GetFrame()->IsCrossOriginSubframe()) {
- cross_origin_autoplay_histogram.Count(autoplay_status_.value());
- }
-
- autoplay_status_.reset();
-}
-
const AtomicString& BaseAudioContext::InterfaceName() const {
return EventTargetNames::AudioContext;
}
@@ -987,7 +854,6 @@ void BaseAudioContext::StartRendering() {
// set the state.
DCHECK(IsMainThread());
DCHECK(destination_node_);
- DCHECK(IsAllowedToStart());
if (context_state_ == kSuspended) {
destination()->GetAudioDestinationHandler().StartRendering();
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.h b/chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.h
index c24b3338755..f55e32c4b70 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/base_audio_context.h
@@ -34,7 +34,6 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_decode_success_callback.h"
#include "third_party/blink/renderer/core/dom/events/event_listener.h"
#include "third_party/blink/renderer/core/dom/pausable_object.h"
-#include "third_party/blink/renderer/core/html/media/autoplay_policy.h"
#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
@@ -44,6 +43,7 @@
#include "third_party/blink/renderer/modules/webaudio/deferred_task_handler.h"
#include "third_party/blink/renderer/modules/webaudio/iir_filter_node.h"
#include "third_party/blink/renderer/platform/audio/audio_bus.h"
+#include "third_party/blink/renderer/platform/audio/audio_io_callback.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/threading.h"
@@ -120,44 +120,19 @@ class MODULES_EXPORT BaseAudioContext
}
// Document notification
- void ContextDestroyed(ExecutionContext*) final;
+ void ContextDestroyed(ExecutionContext*) override;
bool HasPendingActivity() const override;
// Cannnot be called from the audio thread.
AudioDestinationNode* destination() const;
size_t CurrentSampleFrame() const {
- // TODO: What is the correct value for the current frame if the destination
- // node has gone away? 0 is a valid frame.
- return destination_node_ ? destination_node_->GetAudioDestinationHandler()
- .CurrentSampleFrame()
- : 0;
+ return destination_handler_->CurrentSampleFrame();
}
- double currentTime() const {
- // TODO: What is the correct value for the current time if the destination
- // node has gone away? 0 is a valid time.
- return destination_node_
- ? destination_node_->GetAudioDestinationHandler().CurrentTime()
- : 0;
- }
-
- float sampleRate() const {
- return destination_node_
- ? destination_node_->GetAudioDestinationHandler().SampleRate()
- : ClosedContextSampleRate();
- }
+ double currentTime() const { return destination_handler_->CurrentTime(); }
- float FramesPerBuffer() const {
- return destination_node_ ? destination_node_->GetAudioDestinationHandler()
- .FramesPerBuffer()
- : 0;
- }
-
- size_t CallbackBufferSize() const {
- return destination_node_ ? destination_node_->Handler().CallbackBufferSize()
- : 0;
- }
+ float sampleRate() const { return destination_handler_->SampleRate(); }
String state() const;
AudioContextState ContextState() const { return context_state_; }
@@ -272,14 +247,6 @@ class MODULES_EXPORT BaseAudioContext
// Called at the end of each render quantum.
void HandlePostRenderTasks();
- // Keeps track of the number of connections made.
- void IncrementConnectionCount() {
- DCHECK(IsMainThread());
- connection_count_++;
- }
-
- unsigned ConnectionCount() const { return connection_count_; }
-
DeferredTaskHandler& GetDeferredTaskHandler() const {
return *deferred_task_handler_;
}
@@ -309,9 +276,6 @@ class MODULES_EXPORT BaseAudioContext
DEFINE_ATTRIBUTE_EVENT_LISTENER(statechange);
- // Start the AudioContext. `isAllowedToStart()` MUST be called
- // before. This does NOT set the context state to running. The
- // caller must set the state AFTER calling startRendering.
void StartRendering();
void NotifyStateChange();
@@ -328,10 +292,9 @@ class MODULES_EXPORT BaseAudioContext
// initialized internally if necessary.
PeriodicWave* GetPeriodicWave(int type);
- // For metrics purpose, records when start() is called on a
- // AudioScheduledSourceHandler or a AudioBufferSourceHandler without a user
- // gesture while the AudioContext requires a user gesture.
- void MaybeRecordStartAttempt();
+ // Called by handlers of AudioScheduledSourceNode and AudioBufferSourceNode to
+ // notify their associated AudioContext when start() is called.
+ virtual void NotifySourceNodeStart() = 0;
// AudioWorklet IDL
AudioWorklet* audioWorklet() const;
@@ -359,12 +322,10 @@ class MODULES_EXPORT BaseAudioContext
explicit BaseAudioContext(Document*, enum ContextType);
void Initialize();
- void Uninitialize();
+ virtual void Uninitialize();
void SetContextState(AudioContextState);
- virtual void DidClose() {}
-
// Tries to handle AudioBufferSourceNodes that were started but became
// disconnected or was never connected. Because these never get pulled
// anymore, they will stay around forever. So if we can, try to stop them so
@@ -379,40 +340,20 @@ class MODULES_EXPORT BaseAudioContext
// collect all of the promises here until they can be resolved or rejected.
HeapVector<Member<ScriptPromiseResolver>> resume_resolvers_;
- void SetClosedContextSampleRate(float new_sample_rate) {
- closed_context_sample_rate_ = new_sample_rate;
- }
- float ClosedContextSampleRate() const { return closed_context_sample_rate_; }
-
void RejectPendingDecodeAudioDataResolvers();
- // If any, unlock user gesture requirements if a user gesture is being
- // processed.
- void MaybeUnlockUserGesture();
+ AudioIOPosition OutputPosition();
- // Returns whether the AudioContext is allowed to start rendering.
- bool IsAllowedToStart() const;
+ // Returns the Document wich wich the instance is associated.
+ Document* GetDocument() const;
- AudioIOPosition OutputPosition();
+ const String& Uuid() const { return uuid_; }
private:
- friend class BaseAudioContextAutoplayTest;
- friend class DISABLED_BaseAudioContextAutoplayTest;
-
- // Do not change the order of this enum, it is used for metrics.
- enum AutoplayStatus {
- // The AudioContext failed to activate because of user gesture requirements.
- kAutoplayStatusFailed = 0,
- // Same as AutoplayStatusFailed but start() on a node was called with a user
- // gesture.
- kAutoplayStatusFailedWithStart = 1,
- // The AudioContext had user gesture requirements and was able to activate
- // with a user gesture.
- kAutoplayStatusSucceeded = 2,
-
- // Keep at the end.
- kAutoplayStatusCount
- };
+ friend class AudioContextAutoplayTest;
+
+ // Unique ID for each context.
+ const String uuid_;
bool is_cleared_;
void Clear();
@@ -421,15 +362,6 @@ class MODULES_EXPORT BaseAudioContext
// haven't finished playing. Make sure to release them here.
void ReleaseActiveSourceNodes();
- // Returns the Document wich wich the instance is associated.
- Document* GetDocument() const;
-
- // Returns the AutoplayPolicy currently applying to this instance.
- AutoplayPolicy::Type GetAutoplayPolicy() const;
-
- // Returns whether the autoplay requirements are fulfilled.
- bool AreAutoplayRequirementsFulfilled() const;
-
// Listener for the PannerNodes
Member<AudioListener> listener_;
@@ -472,9 +404,6 @@ class MODULES_EXPORT BaseAudioContext
// resolvers.
virtual void RejectPendingResolvers();
- // Record the current autoplay status and clear it.
- void RecordAutoplayStatus();
-
// True if we're in the process of resolving promises for resume(). Resolving
// can take some time and the audio context process loop is very fast, so we
// don't want to call resolve an excessive number of times.
@@ -485,11 +414,6 @@ class MODULES_EXPORT BaseAudioContext
// thread. Cleared by the main thread task once it has run.
bool has_posted_cleanup_task_;
- // Whether a user gesture is required to start this AudioContext.
- bool user_gesture_required_;
-
- unsigned connection_count_;
-
// Graph locking.
scoped_refptr<DeferredTaskHandler> deferred_task_handler_;
@@ -498,11 +422,6 @@ class MODULES_EXPORT BaseAudioContext
AsyncAudioDecoder audio_decoder_;
- // When a context is closed, the sample rate is cleared. But decodeAudioData
- // can be called after the context has been closed and it needs the sample
- // rate. When the context is closed, the sample rate is saved here.
- float closed_context_sample_rate_;
-
// Vector of promises created by decodeAudioData. This keeps the resolvers
// alive until decodeAudioData finishes decoding and can tell the main thread
// to resolve them.
@@ -520,9 +439,11 @@ class MODULES_EXPORT BaseAudioContext
// It is somewhat arbitrary and could be increased if necessary.
enum { kMaxNumberOfChannels = 32 };
- base::Optional<AutoplayStatus> autoplay_status_;
AudioIOPosition output_position_;
+ // The handler associated with the above |destination_node_|.
+ scoped_refptr<AudioDestinationHandler> destination_handler_;
+
Member<AudioWorklet> audio_worklet_;
// In order to update some information (e.g. current frame) in
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/base_audio_context_test.cc b/chromium/third_party/blink/renderer/modules/webaudio/base_audio_context_test.cc
deleted file mode 100644
index b2104c786ca..00000000000
--- a/chromium/third_party/blink/renderer/modules/webaudio/base_audio_context_test.cc
+++ /dev/null
@@ -1,732 +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/modules/webaudio/base_audio_context.h"
-
-#include <memory>
-
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/web_audio_device.h"
-#include "third_party/blink/public/platform/web_audio_latency_hint.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/dom/user_gesture_indicator.h"
-#include "third_party/blink/renderer/core/frame/frame_owner.h"
-#include "third_party/blink/renderer/core/frame/frame_types.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"
-#include "third_party/blink/renderer/core/html/media/autoplay_policy.h"
-#include "third_party/blink/renderer/core/loader/document_loader.h"
-#include "third_party/blink/renderer/core/loader/empty_clients.h"
-#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
-#include "third_party/blink/renderer/modules/webaudio/audio_context_options.h"
-#include "third_party/blink/renderer/modules/webaudio/audio_worklet_thread.h"
-#include "third_party/blink/renderer/platform/testing/histogram_tester.h"
-#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
-
-namespace blink {
-
-namespace {
-
-const char* const kAutoplayMetric = "WebAudio.Autoplay";
-const char* const kAutoplayCrossOriginMetric = "WebAudio.Autoplay.CrossOrigin";
-
-class MockCrossOriginLocalFrameClient final : public EmptyLocalFrameClient {
- public:
- static MockCrossOriginLocalFrameClient* Create(Frame* parent) {
- return new MockCrossOriginLocalFrameClient(parent);
- }
-
- void Trace(blink::Visitor* visitor) override {
- visitor->Trace(parent_);
- EmptyLocalFrameClient::Trace(visitor);
- }
-
- Frame* Parent() const override { return parent_.Get(); }
- Frame* Top() const override { return parent_.Get(); }
-
- private:
- explicit MockCrossOriginLocalFrameClient(Frame* parent) : parent_(parent) {}
-
- Member<Frame> parent_;
-};
-
-class MockWebAudioDeviceForBaseAudioContext : public WebAudioDevice {
- public:
- explicit MockWebAudioDeviceForBaseAudioContext(double sample_rate,
- int frames_per_buffer)
- : sample_rate_(sample_rate), frames_per_buffer_(frames_per_buffer) {}
- ~MockWebAudioDeviceForBaseAudioContext() override = default;
-
- void Start() override {}
- void Stop() override {}
- double SampleRate() override { return sample_rate_; }
- int FramesPerBuffer() override { return frames_per_buffer_; }
-
- private:
- double sample_rate_;
- int frames_per_buffer_;
-};
-
-class BaseAudioContextTestPlatform : public TestingPlatformSupport {
- public:
- std::unique_ptr<WebAudioDevice> CreateAudioDevice(
- unsigned number_of_input_channels,
- unsigned number_of_channels,
- const WebAudioLatencyHint& latency_hint,
- WebAudioDevice::RenderCallback*,
- const WebString& device_id) override {
- return std::make_unique<MockWebAudioDeviceForBaseAudioContext>(
- AudioHardwareSampleRate(), AudioHardwareBufferSize());
- }
-
- std::unique_ptr<WebThread> CreateThread(
- const WebThreadCreationParams& params) override {
- return old_platform_->CreateThread(params);
- }
-
- double AudioHardwareSampleRate() override { return 44100; }
- size_t AudioHardwareBufferSize() override { return 128; }
-};
-
-} // anonymous namespace
-
-class BaseAudioContextAutoplayTest
- : public testing::TestWithParam<AutoplayPolicy::Type> {
- protected:
- using AutoplayStatus = BaseAudioContext::AutoplayStatus;
-
- void SetUp() override {
- dummy_page_holder_ = DummyPageHolder::Create();
- dummy_frame_owner_ = DummyFrameOwner::Create();
- GetDocument().UpdateSecurityOrigin(
- SecurityOrigin::Create("https", "example.com", 80));
-
- CreateChildFrame();
-
- GetDocument().GetSettings()->SetAutoplayPolicy(GetParam());
- ChildDocument().GetSettings()->SetAutoplayPolicy(GetParam());
-
- histogram_tester_ = std::make_unique<HistogramTester>();
- }
-
- void TearDown() override {
- if (child_frame_)
- child_frame_->Detach(FrameDetachType::kRemove);
- }
-
- void CreateChildFrame() {
- child_frame_ = LocalFrame::Create(
- MockCrossOriginLocalFrameClient::Create(GetDocument().GetFrame()),
- *GetDocument().GetFrame()->GetPage(), dummy_frame_owner_.Get());
- child_frame_->SetView(
- LocalFrameView::Create(*child_frame_, IntSize(500, 500)));
- child_frame_->Init();
-
- ChildDocument().UpdateSecurityOrigin(
- SecurityOrigin::Create("https", "cross-origin.com", 80));
- }
-
- Document& GetDocument() { return dummy_page_holder_->GetDocument(); }
-
- Document& ChildDocument() { return *child_frame_->GetDocument(); }
-
- ScriptState* GetScriptStateFrom(const Document& document) {
- return ToScriptStateForMainWorld(document.GetFrame());
- }
-
- void RejectPendingResolvers(BaseAudioContext* audio_context) {
- audio_context->RejectPendingResolvers();
- }
-
- void RecordAutoplayStatus(BaseAudioContext* audio_context) {
- audio_context->RecordAutoplayStatus();
- }
-
- HistogramTester* GetHistogramTester() {
- return histogram_tester_.get();
- }
-
- private:
- std::unique_ptr<DummyPageHolder> dummy_page_holder_;
- Persistent<DummyFrameOwner> dummy_frame_owner_;
- Persistent<LocalFrame> child_frame_;
- std::unique_ptr<HistogramTester> histogram_tester_;
- ScopedTestingPlatformSupport<BaseAudioContextTestPlatform> platform_;
-};
-
-// Creates an AudioContext without a gesture inside a x-origin child frame.
-TEST_P(BaseAudioContextAutoplayTest, AutoplayMetrics_CreateNoGesture_Child) {
- BaseAudioContext* audio_context = BaseAudioContext::Create(
- ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
- RecordAutoplayStatus(audio_context);
-
- switch (GetParam()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayCrossOriginMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
- break;
- }
-}
-
-// Creates an AudioContext without a gesture inside a main frame.
-TEST_P(BaseAudioContextAutoplayTest, AutoplayMetrics_CreateNoGesture_Main) {
- BaseAudioContext* audio_context = BaseAudioContext::Create(
- GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
- RecordAutoplayStatus(audio_context);
-
- switch (GetParam()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- }
-}
-
-// Creates an AudioContext then call resume without a gesture in a x-origin
-// child frame.
-TEST_P(BaseAudioContextAutoplayTest,
- AutoplayMetrics_CallResumeNoGesture_Child) {
- ScriptState::Scope scope(GetScriptStateFrom(ChildDocument()));
-
- BaseAudioContext* audio_context = BaseAudioContext::Create(
- ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
- audio_context->resumeContext(GetScriptStateFrom(ChildDocument()));
- RejectPendingResolvers(audio_context);
- RecordAutoplayStatus(audio_context);
-
- switch (GetParam()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayCrossOriginMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
- break;
- }
-}
-
-// Creates an AudioContext then call resume without a gesture in a main frame.
-TEST_P(BaseAudioContextAutoplayTest, AutoplayMetrics_CallResumeNoGesture_Main) {
- ScriptState::Scope scope(GetScriptStateFrom(GetDocument()));
-
- BaseAudioContext* audio_context = BaseAudioContext::Create(
- GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
- audio_context->resumeContext(GetScriptStateFrom(ChildDocument()));
- RejectPendingResolvers(audio_context);
- RecordAutoplayStatus(audio_context);
-
- switch (GetParam()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- }
-}
-
-// Creates an AudioContext with a user gesture inside a x-origin child frame.
-TEST_P(BaseAudioContextAutoplayTest, AutoplayMetrics_CreateGesture_Child) {
- std::unique_ptr<UserGestureIndicator> user_gesture_scope =
- Frame::NotifyUserActivation(ChildDocument().GetFrame(),
- UserGestureToken::kNewGesture);
-
- BaseAudioContext* audio_context = BaseAudioContext::Create(
- ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
- RecordAutoplayStatus(audio_context);
-
- switch (GetParam()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayCrossOriginMetric, AutoplayStatus::kAutoplayStatusSucceeded,
- 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
- break;
- }
-}
-
-// Creates an AudioContext with a user gesture inside a main frame.
-TEST_P(BaseAudioContextAutoplayTest, AutoplayMetrics_CreateGesture_Main) {
- std::unique_ptr<UserGestureIndicator> user_gesture_scope =
- Frame::NotifyUserActivation(GetDocument().GetFrame(),
- UserGestureToken::kNewGesture);
-
- BaseAudioContext* audio_context = BaseAudioContext::Create(
- GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
- RecordAutoplayStatus(audio_context);
-
- switch (GetParam()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- }
-}
-
-// Creates an AudioContext then calls resume with a user gesture inside a
-// x-origin child frame.
-TEST_P(BaseAudioContextAutoplayTest, AutoplayMetrics_CallResumeGesture_Child) {
- ScriptState::Scope scope(GetScriptStateFrom(ChildDocument()));
-
- BaseAudioContext* audio_context = BaseAudioContext::Create(
- ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
-
- std::unique_ptr<UserGestureIndicator> user_gesture_scope =
- Frame::NotifyUserActivation(ChildDocument().GetFrame(),
- UserGestureToken::kNewGesture);
-
- audio_context->resumeContext(GetScriptStateFrom(ChildDocument()));
- RejectPendingResolvers(audio_context);
- RecordAutoplayStatus(audio_context);
-
- switch (GetParam()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayCrossOriginMetric, AutoplayStatus::kAutoplayStatusSucceeded,
- 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
- break;
- }
-}
-
-// Creates an AudioContext then calls resume with a user gesture inside a main
-// frame.
-TEST_P(BaseAudioContextAutoplayTest, AutoplayMetrics_CallResumeGesture_Main) {
- ScriptState::Scope scope(GetScriptStateFrom(GetDocument()));
-
- BaseAudioContext* audio_context = BaseAudioContext::Create(
- GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
-
- std::unique_ptr<UserGestureIndicator> user_gesture_scope =
- Frame::NotifyUserActivation(GetDocument().GetFrame(),
- UserGestureToken::kNewGesture);
-
- audio_context->resumeContext(GetScriptStateFrom(GetDocument()));
- RejectPendingResolvers(audio_context);
- RecordAutoplayStatus(audio_context);
-
- switch (GetParam()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- }
-}
-
-// Creates an AudioContext then calls start on a node without a gesture inside a
-// x-origin child frame.
-TEST_P(BaseAudioContextAutoplayTest, AutoplayMetrics_NodeStartNoGesture_Child) {
- BaseAudioContext* audio_context = BaseAudioContext::Create(
- ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
- audio_context->MaybeRecordStartAttempt();
- RecordAutoplayStatus(audio_context);
-
- switch (GetParam()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayCrossOriginMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
- break;
- }
-}
-
-// Creates an AudioContext then calls start on a node without a gesture inside a
-// main frame.
-TEST_P(BaseAudioContextAutoplayTest, AutoplayMetrics_NodeStartNoGesture_Main) {
- BaseAudioContext* audio_context = BaseAudioContext::Create(
- GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
- audio_context->MaybeRecordStartAttempt();
- RecordAutoplayStatus(audio_context);
-
- switch (GetParam()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- }
-}
-
-// Creates an AudioContext then calls start on a node with a gesture inside a
-// x-origin child frame.
-TEST_P(BaseAudioContextAutoplayTest, AutoplayMetrics_NodeStartGesture_Child) {
- BaseAudioContext* audio_context = BaseAudioContext::Create(
- ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
-
- std::unique_ptr<UserGestureIndicator> user_gesture_scope =
- Frame::NotifyUserActivation(ChildDocument().GetFrame(),
- UserGestureToken::kNewGesture);
- audio_context->MaybeRecordStartAttempt();
- RecordAutoplayStatus(audio_context);
-
- switch (GetParam()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusFailedWithStart, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayCrossOriginMetric,
- AutoplayStatus::kAutoplayStatusFailedWithStart, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
- break;
- }
-}
-
-// Creates an AudioContext then calls start on a node with a gesture inside a
-// main frame.
-TEST_P(BaseAudioContextAutoplayTest, AutoplayMetrics_NodeStartGesture_Main) {
- BaseAudioContext* audio_context = BaseAudioContext::Create(
- GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
-
- std::unique_ptr<UserGestureIndicator> user_gesture_scope =
- Frame::NotifyUserActivation(GetDocument().GetFrame(),
- UserGestureToken::kNewGesture);
- audio_context->MaybeRecordStartAttempt();
- RecordAutoplayStatus(audio_context);
-
- switch (GetParam()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusFailedWithStart, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- }
-}
-
-// Creates an AudioContext then calls start on a node without a gesture and
-// finally allows the AudioContext to produce sound inside x-origin child frame.
-TEST_P(BaseAudioContextAutoplayTest,
- AutoplayMetrics_NodeStartNoGestureThenSuccess_Child) {
- ScriptState::Scope scope(GetScriptStateFrom(ChildDocument()));
-
- BaseAudioContext* audio_context = BaseAudioContext::Create(
- ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
- audio_context->MaybeRecordStartAttempt();
-
- std::unique_ptr<UserGestureIndicator> user_gesture_scope =
- Frame::NotifyUserActivation(ChildDocument().GetFrame(),
- UserGestureToken::kNewGesture);
- audio_context->resumeContext(GetScriptStateFrom(ChildDocument()));
- RejectPendingResolvers(audio_context);
- RecordAutoplayStatus(audio_context);
-
- switch (GetParam()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayCrossOriginMetric, AutoplayStatus::kAutoplayStatusSucceeded,
- 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
- break;
- }
-}
-
-// Creates an AudioContext then calls start on a node without a gesture and
-// finally allows the AudioContext to produce sound inside a main frame.
-TEST_P(BaseAudioContextAutoplayTest,
- AutoplayMetrics_NodeStartNoGestureThenSuccess_Main) {
- ScriptState::Scope scope(GetScriptStateFrom(GetDocument()));
-
- BaseAudioContext* audio_context = BaseAudioContext::Create(
- GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
- audio_context->MaybeRecordStartAttempt();
-
- std::unique_ptr<UserGestureIndicator> user_gesture_scope =
- Frame::NotifyUserActivation(GetDocument().GetFrame(),
- UserGestureToken::kNewGesture);
- audio_context->resumeContext(GetScriptStateFrom(GetDocument()));
- RejectPendingResolvers(audio_context);
- RecordAutoplayStatus(audio_context);
-
- switch (GetParam()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- }
-}
-
-// Creates an AudioContext then calls start on a node with a gesture and
-// finally allows the AudioContext to produce sound inside x-origin child frame.
-TEST_P(BaseAudioContextAutoplayTest,
- AutoplayMetrics_NodeStartGestureThenSucces_Child) {
- ScriptState::Scope scope(GetScriptStateFrom(ChildDocument()));
-
- BaseAudioContext* audio_context = BaseAudioContext::Create(
- ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
-
- std::unique_ptr<UserGestureIndicator> user_gesture_scope =
- Frame::NotifyUserActivation(ChildDocument().GetFrame(),
- UserGestureToken::kNewGesture);
- audio_context->MaybeRecordStartAttempt();
- audio_context->resumeContext(GetScriptStateFrom(ChildDocument()));
- RejectPendingResolvers(audio_context);
- RecordAutoplayStatus(audio_context);
-
- switch (GetParam()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayCrossOriginMetric, AutoplayStatus::kAutoplayStatusSucceeded,
- 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
- break;
- }
-}
-
-// Creates an AudioContext then calls start on a node with a gesture and
-// finally allows the AudioContext to produce sound inside a main frame.
-TEST_P(BaseAudioContextAutoplayTest,
- AutoplayMetrics_NodeStartGestureThenSucces_Main) {
- ScriptState::Scope scope(GetScriptStateFrom(GetDocument()));
-
- BaseAudioContext* audio_context = BaseAudioContext::Create(
- GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
-
- std::unique_ptr<UserGestureIndicator> user_gesture_scope =
- Frame::NotifyUserActivation(GetDocument().GetFrame(),
- UserGestureToken::kNewGesture);
- audio_context->MaybeRecordStartAttempt();
- audio_context->resumeContext(GetScriptStateFrom(GetDocument()));
- RejectPendingResolvers(audio_context);
- RecordAutoplayStatus(audio_context);
-
- switch (GetParam()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- }
-}
-
-// Attempts to autoplay an AudioContext in a x-origin child frame when the
-// document previous received a user gesture.
-TEST_P(BaseAudioContextAutoplayTest,
- AutoplayMetrics_DocumentReceivedGesture_Child) {
- Frame::NotifyUserActivation(ChildDocument().GetFrame(),
- UserGestureToken::kNewGesture);
-
- BaseAudioContext* audio_context = BaseAudioContext::Create(
- ChildDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
- RecordAutoplayStatus(audio_context);
-
- switch (GetParam()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayCrossOriginMetric, AutoplayStatus::kAutoplayStatusFailed, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
- break;
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayCrossOriginMetric, AutoplayStatus::kAutoplayStatusSucceeded,
- 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 1);
- break;
- }
-}
-
-// Attempts to autoplay an AudioContext in a main child frame when the
-// document previous received a user gesture.
-TEST_P(BaseAudioContextAutoplayTest,
- AutoplayMetrics_DocumentReceivedGesture_Main) {
- Frame::NotifyUserActivation(ChildDocument().GetFrame(),
- UserGestureToken::kNewGesture);
-
- BaseAudioContext* audio_context = BaseAudioContext::Create(
- GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
- RecordAutoplayStatus(audio_context);
-
- switch (GetParam()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- }
-}
-
-// Attempts to autoplay an AudioContext in a main child frame when the
-// document received a user gesture before navigation.
-TEST_P(BaseAudioContextAutoplayTest,
- AutoplayMetrics_DocumentReceivedGesture_BeforeNavigation) {
- GetDocument().GetFrame()->SetDocumentHasReceivedUserGestureBeforeNavigation(
- true);
-
- BaseAudioContext* audio_context = BaseAudioContext::Create(
- GetDocument(), AudioContextOptions(), ASSERT_NO_EXCEPTION);
- RecordAutoplayStatus(audio_context);
-
- switch (GetParam()) {
- case AutoplayPolicy::Type::kNoUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequired:
- case AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin:
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 0);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- case AutoplayPolicy::Type::kDocumentUserActivationRequired:
- GetHistogramTester()->ExpectBucketCount(
- kAutoplayMetric, AutoplayStatus::kAutoplayStatusSucceeded, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayMetric, 1);
- GetHistogramTester()->ExpectTotalCount(kAutoplayCrossOriginMetric, 0);
- break;
- }
-}
-
-INSTANTIATE_TEST_CASE_P(
- BaseAudioContextAutoplayTest,
- BaseAudioContextAutoplayTest,
- testing::Values(AutoplayPolicy::Type::kNoUserGestureRequired,
- AutoplayPolicy::Type::kUserGestureRequired,
- AutoplayPolicy::Type::kUserGestureRequiredForCrossOrigin,
- AutoplayPolicy::Type::kDocumentUserActivationRequired));
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/biquad_filter_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/biquad_filter_node.cc
index d31cc7a792b..a418bb59127 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/biquad_filter_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/biquad_filter_node.cc
@@ -27,11 +27,10 @@
#include <memory>
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/webaudio/audio_basic_processor_handler.h"
#include "third_party/blink/renderer/modules/webaudio/biquad_filter_options.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/histogram.h"
namespace blink {
@@ -216,7 +215,7 @@ void BiquadFilterNode::getFrequencyResponse(
if (mag_response.View()->length() != frequency_hz_length) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
ExceptionMessages::IndexOutsideRange(
"magResponse length", mag_response.View()->length(),
frequency_hz_length, ExceptionMessages::kInclusiveBound,
@@ -226,7 +225,7 @@ void BiquadFilterNode::getFrequencyResponse(
if (phase_response.View()->length() != frequency_hz_length) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
ExceptionMessages::IndexOutsideRange(
"phaseResponse length", phase_response.View()->length(),
frequency_hz_length, ExceptionMessages::kInclusiveBound,
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/channel_merger_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/channel_merger_node.cc
index 02a4795947d..e6c2b074ba2 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/channel_merger_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/channel_merger_node.cc
@@ -26,15 +26,15 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/modules/webaudio/channel_merger_node.h"
+
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_input.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
-#include "third_party/blink/renderer/modules/webaudio/channel_merger_node.h"
#include "third_party/blink/renderer/modules/webaudio/channel_merger_options.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -102,7 +102,7 @@ void ChannelMergerHandler::SetChannelCount(unsigned long channel_count,
// channelCount must be 1.
if (channel_count != 1) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"ChannelMerger: channelCount cannot be changed from 1");
}
}
@@ -116,7 +116,7 @@ void ChannelMergerHandler::SetChannelCountMode(
// channcelCountMode must be 'explicit'.
if (mode != "explicit") {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"ChannelMerger: channelCountMode cannot be changed from 'explicit'");
}
}
@@ -151,11 +151,12 @@ ChannelMergerNode* ChannelMergerNode::Create(BaseAudioContext& context,
if (!number_of_inputs ||
number_of_inputs > BaseAudioContext::MaxNumberOfChannels()) {
exception_state.ThrowDOMException(
- kIndexSizeError, ExceptionMessages::IndexOutsideRange<size_t>(
- "number of inputs", number_of_inputs, 1,
- ExceptionMessages::kInclusiveBound,
- BaseAudioContext::MaxNumberOfChannels(),
- ExceptionMessages::kInclusiveBound));
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexOutsideRange<size_t>(
+ "number of inputs", number_of_inputs, 1,
+ ExceptionMessages::kInclusiveBound,
+ BaseAudioContext::MaxNumberOfChannels(),
+ ExceptionMessages::kInclusiveBound));
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/channel_splitter_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/channel_splitter_node.cc
index 19e0feca8fa..1b87eb74314 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/channel_splitter_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/channel_splitter_node.cc
@@ -23,14 +23,14 @@
* DAMAGE.
*/
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/modules/webaudio/channel_splitter_node.h"
+
#include "third_party/blink/renderer/modules/webaudio/audio_node_input.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
-#include "third_party/blink/renderer/modules/webaudio/channel_splitter_node.h"
#include "third_party/blink/renderer/modules/webaudio/channel_splitter_options.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -91,7 +91,7 @@ void ChannelSplitterHandler::SetChannelCount(unsigned long channel_count,
// channelCount cannot be changed from the number of outputs.
if (channel_count != NumberOfOutputs()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"ChannelSplitter: channelCount cannot be changed from " +
String::Number(NumberOfOutputs()));
}
@@ -106,7 +106,7 @@ void ChannelSplitterHandler::SetChannelCountMode(
// channcelCountMode must be 'explicit'.
if (mode != "explicit") {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"ChannelSplitter: channelCountMode cannot be changed from 'explicit'");
}
}
@@ -119,7 +119,7 @@ void ChannelSplitterHandler::SetChannelInterpretation(
// channelInterpretation must be "discrete"
if (mode != "discrete") {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"ChannelSplitter: channelInterpretation "
"cannot be changed from 'discrete'");
}
@@ -157,11 +157,12 @@ ChannelSplitterNode* ChannelSplitterNode::Create(
if (!number_of_outputs ||
number_of_outputs > BaseAudioContext::MaxNumberOfChannels()) {
exception_state.ThrowDOMException(
- kIndexSizeError, ExceptionMessages::IndexOutsideRange<size_t>(
- "number of outputs", number_of_outputs, 1,
- ExceptionMessages::kInclusiveBound,
- BaseAudioContext::MaxNumberOfChannels(),
- ExceptionMessages::kInclusiveBound));
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexOutsideRange<size_t>(
+ "number of outputs", number_of_outputs, 1,
+ ExceptionMessages::kInclusiveBound,
+ BaseAudioContext::MaxNumberOfChannels(),
+ ExceptionMessages::kInclusiveBound));
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/constant_source_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/constant_source_node.cc
index 3fe45de33ee..75a87fd2eb4 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/constant_source_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/constant_source_node.cc
@@ -5,12 +5,11 @@
#include "third_party/blink/renderer/modules/webaudio/constant_source_node.h"
#include <algorithm>
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+
#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
#include "third_party/blink/renderer/modules/webaudio/constant_source_options.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/convolver_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/convolver_node.cc
index e0e008a7577..2d73dfee3ab 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/convolver_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/convolver_node.cc
@@ -23,15 +23,14 @@
* DAMAGE.
*/
+#include "third_party/blink/renderer/modules/webaudio/convolver_node.h"
#include <memory>
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/webaudio/audio_buffer.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_input.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
-#include "third_party/blink/renderer/modules/webaudio/convolver_node.h"
#include "third_party/blink/renderer/modules/webaudio/convolver_options.h"
#include "third_party/blink/renderer/platform/audio/reverb.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
// Note about empirical tuning:
// The maximum FFT size affects reverb performance and accuracy.
@@ -45,7 +44,9 @@ const size_t MaxFFTSize = 32768;
namespace blink {
ConvolverHandler::ConvolverHandler(AudioNode& node, float sample_rate)
- : AudioHandler(kNodeTypeConvolver, node, sample_rate), normalize_(true) {
+ : AudioHandler(kNodeTypeConvolver, node, sample_rate),
+ normalize_(true),
+ buffer_has_been_set_(false) {
AddInput();
AddOutput(1);
@@ -95,12 +96,24 @@ void ConvolverHandler::SetBuffer(AudioBuffer* buffer,
ExceptionState& exception_state) {
DCHECK(IsMainThread());
- if (!buffer)
+ if (!buffer) {
+ reverb_.reset();
+ buffer_ = buffer;
return;
+ }
+
+ if (buffer && buffer_has_been_set_) {
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ "Cannot set buffer to non-null after it "
+ "has been already been set to a non-null "
+ "buffer");
+ return;
+ }
+ buffer_has_been_set_ = true;
if (buffer->sampleRate() != Context()->sampleRate()) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"The buffer sample rate of " + String::Number(buffer->sampleRate()) +
" does not match the context rate of " +
String::Number(Context()->sampleRate()) + " Hz.");
@@ -119,8 +132,9 @@ void ConvolverHandler::SetBuffer(AudioBuffer* buffer,
if (!is_channel_count_good) {
exception_state.ThrowDOMException(
- kNotSupportedError, "The buffer must have 1, 2, or 4 channels, not " +
- String::Number(number_of_channels));
+ DOMExceptionCode::kNotSupportedError,
+ "The buffer must have 1, 2, or 4 channels, not " +
+ String::Number(number_of_channels));
return;
}
@@ -207,7 +221,7 @@ void ConvolverHandler::SetChannelCount(unsigned long channel_count,
// channelCount must be 2.
if (channel_count != 2) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"ConvolverNode: channelCount cannot be changed from 2");
}
}
@@ -220,7 +234,7 @@ void ConvolverHandler::SetChannelCountMode(const String& mode,
// channcelCountMode must be 'clamped-max'.
if (mode != "clamped-max") {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"ConvolverNode: channelCountMode cannot be changed from 'clamped-max'");
}
}
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/convolver_node.h b/chromium/third_party/blink/renderer/modules/webaudio/convolver_node.h
index 96ee2e419d1..16e71832ef9 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/convolver_node.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/convolver_node.h
@@ -85,6 +85,10 @@ class MODULES_EXPORT ConvolverHandler final : public AudioHandler {
// Normalize the impulse response or not. Must default to true.
bool normalize_;
+ // True if the |buffer| attribute has ever been set to a non-null
+ // value. Defaults to false.
+ bool buffer_has_been_set_;
+
FRIEND_TEST_ALL_PREFIXES(ConvolverNodeTest, ReverbLifetime);
};
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/convolver_node_test.cc b/chromium/third_party/blink/renderer/modules/webaudio/convolver_node_test.cc
index 548264494ef..cb5179a2dd1 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/convolver_node_test.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/convolver_node_test.cc
@@ -5,6 +5,7 @@
#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_buffer.h"
#include "third_party/blink/renderer/modules/webaudio/convolver_node.h"
#include "third_party/blink/renderer/modules/webaudio/offline_audio_context.h"
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.cc
index c81bf9ea716..a5427bff57a 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.cc
@@ -25,34 +25,38 @@
#include "third_party/blink/renderer/modules/webaudio/default_audio_destination_node.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_node_input.h"
+#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
#include "third_party/blink/renderer/modules/webaudio/audio_worklet.h"
#include "third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
+#include "third_party/blink/renderer/platform/audio/denormal_disabler.h"
+#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
+#include "third_party/blink/renderer/platform/wtf/atomics.h"
namespace blink {
+scoped_refptr<DefaultAudioDestinationHandler>
+DefaultAudioDestinationHandler::Create(
+ AudioNode& node,
+ const WebAudioLatencyHint& latency_hint) {
+ return base::AdoptRef(new DefaultAudioDestinationHandler(node, latency_hint));
+}
+
DefaultAudioDestinationHandler::DefaultAudioDestinationHandler(
AudioNode& node,
const WebAudioLatencyHint& latency_hint)
: AudioDestinationHandler(node),
- number_of_input_channels_(0),
latency_hint_(latency_hint) {
- // Node-specific default mixing rules.
+ // Node-specific default channel count and mixing rules.
channel_count_ = 2;
SetInternalChannelCountMode(kExplicit);
SetInternalChannelInterpretation(AudioBus::kSpeakers);
}
-scoped_refptr<DefaultAudioDestinationHandler>
-DefaultAudioDestinationHandler::Create(
- AudioNode& node,
- const WebAudioLatencyHint& latency_hint) {
- return base::AdoptRef(new DefaultAudioDestinationHandler(node, latency_hint));
-}
-
DefaultAudioDestinationHandler::~DefaultAudioDestinationHandler() {
DCHECK(!IsInitialized());
}
@@ -79,33 +83,37 @@ void DefaultAudioDestinationHandler::Uninitialize() {
if (destination_->IsPlaying())
StopDestination();
- number_of_input_channels_ = 0;
AudioHandler::Uninitialize();
}
-void DefaultAudioDestinationHandler::CreateDestination() {
- destination_ = AudioDestination::Create(*this, ChannelCount(), latency_hint_);
-}
-
-void DefaultAudioDestinationHandler::StartDestination() {
- DCHECK(!destination_->IsPlaying());
+void DefaultAudioDestinationHandler::SetChannelCount(
+ unsigned long channel_count,
+ ExceptionState& exception_state) {
+ DCHECK(IsMainThread());
- AudioWorklet* audio_worklet = Context()->audioWorklet();
- if (audio_worklet && audio_worklet->IsReady()) {
- // This task runner is only used to fire the audio render callback, so it
- // MUST not be throttled to avoid potential audio glitch.
- destination_->StartWithWorkletTaskRunner(
- audio_worklet->GetMessagingProxy()
- ->GetBackingWorkerThread()
- ->GetTaskRunner(TaskType::kInternalMedia));
- } else {
- destination_->Start();
+ // The channelCount for the input to this node controls the actual number of
+ // channels we send to the audio hardware. It can only be set if the number
+ // is less than the number of hardware channels.
+ if (!MaxChannelCount() || channel_count > MaxChannelCount()) {
+ exception_state.ThrowDOMException(
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexOutsideRange<unsigned>(
+ "channel count", channel_count, 1,
+ ExceptionMessages::kInclusiveBound, MaxChannelCount(),
+ ExceptionMessages::kInclusiveBound));
+ return;
}
-}
-void DefaultAudioDestinationHandler::StopDestination() {
- DCHECK(destination_->IsPlaying());
- destination_->Stop();
+ unsigned long old_channel_count = this->ChannelCount();
+ AudioHandler::SetChannelCount(channel_count, exception_state);
+
+ // Stop, re-create and start the destination to apply the new channel count.
+ if (!exception_state.HadException() &&
+ this->ChannelCount() != old_channel_count && IsInitialized()) {
+ StopDestination();
+ CreateDestination();
+ StartDestination();
+ }
}
void DefaultAudioDestinationHandler::StartRendering() {
@@ -135,50 +143,104 @@ unsigned long DefaultAudioDestinationHandler::MaxChannelCount() const {
return AudioDestination::MaxChannelCount();
}
-size_t DefaultAudioDestinationHandler::CallbackBufferSize() const {
- return destination_->CallbackBufferSize();
+double DefaultAudioDestinationHandler::SampleRate() const {
+ return destination_ ? destination_->SampleRate() : 0;
}
-void DefaultAudioDestinationHandler::SetChannelCount(
- unsigned long channel_count,
- ExceptionState& exception_state) {
- // The channelCount for the input to this node controls the actual number of
- // channels we send to the audio hardware. It can only be set depending on the
- // maximum number of channels supported by the hardware.
+void DefaultAudioDestinationHandler::Render(
+ AudioBus* destination_bus,
+ size_t number_of_frames,
+ const AudioIOPosition& output_position) {
+ TRACE_EVENT0("webaudio", "DefaultAudioDestinationHandler::Render");
+
+ // Denormals can seriously hurt performance of audio processing. This will
+ // take care of all AudioNode processes within this scope.
+ DenormalDisabler denormal_disabler;
+
+ // A sanity check for the associated context, but this does not guarantee the
+ // safe execution of the subsequence operations because the hanlder holds
+ // the context as |UntracedMember| and it can go away anytime.
+ DCHECK(Context());
+ if (!Context())
+ return;
- DCHECK(IsMainThread());
+ Context()->GetDeferredTaskHandler().SetAudioThreadToCurrentThread();
- if (!MaxChannelCount() || channel_count > MaxChannelCount()) {
- exception_state.ThrowDOMException(
- kIndexSizeError,
- ExceptionMessages::IndexOutsideRange<unsigned>(
- "channel count", channel_count, 1,
- ExceptionMessages::kInclusiveBound, MaxChannelCount(),
- ExceptionMessages::kInclusiveBound));
+ // If this node is not initialized yet, pass silence to the platform audio
+ // destination. It is for the case where this node is in the middle of
+ // tear-down process.
+ if (!IsInitialized()) {
+ destination_bus->Zero();
return;
}
- unsigned long old_channel_count = this->ChannelCount();
- AudioHandler::SetChannelCount(channel_count, exception_state);
+ Context()->HandlePreRenderTasks(output_position);
- if (!exception_state.HadException() &&
- this->ChannelCount() != old_channel_count && IsInitialized()) {
- // Recreate/restart destination.
- StopDestination();
- CreateDestination();
- StartDestination();
+ DCHECK_GE(NumberOfInputs(), 1u);
+ if (NumberOfInputs() < 1) {
+ destination_bus->Zero();
+ return;
+ }
+
+ // Renders the graph by pulling all the input(s) to this node. This will in
+ // turn pull on their input(s), all the way backwards through the graph.
+ AudioBus* rendered_bus = Input(0).Pull(destination_bus, number_of_frames);
+
+ if (!rendered_bus) {
+ destination_bus->Zero();
+ } else if (rendered_bus != destination_bus) {
+ // in-place processing was not possible - so copy
+ destination_bus->CopyFrom(*rendered_bus);
}
+
+ // Processes "automatic" nodes that are not connected to anything.
+ Context()->GetDeferredTaskHandler().ProcessAutomaticPullNodes(
+ number_of_frames);
+
+ Context()->HandlePostRenderTasks();
+
+ // Advances the current sample-frame.
+ size_t new_sample_frame = current_sample_frame_ + number_of_frames;
+ ReleaseStore(&current_sample_frame_, new_sample_frame);
+
+ Context()->UpdateWorkletGlobalScopeOnRenderingThread();
}
-double DefaultAudioDestinationHandler::SampleRate() const {
- return destination_ ? destination_->SampleRate() : 0;
+size_t DefaultAudioDestinationHandler::GetCallbackBufferSize() const {
+ return destination_->CallbackBufferSize();
}
-int DefaultAudioDestinationHandler::FramesPerBuffer() const {
+int DefaultAudioDestinationHandler::GetFramesPerBuffer() const {
return destination_ ? destination_->FramesPerBuffer() : 0;
}
-// ----------------------------------------------------------------
+void DefaultAudioDestinationHandler::CreateDestination() {
+ destination_ = AudioDestination::Create(*this, ChannelCount(), latency_hint_);
+}
+
+void DefaultAudioDestinationHandler::StartDestination() {
+ DCHECK(!destination_->IsPlaying());
+
+ AudioWorklet* audio_worklet = Context()->audioWorklet();
+ if (audio_worklet && audio_worklet->IsReady()) {
+ // This task runner is only used to fire the audio render callback, so it
+ // MUST not be throttled to avoid potential audio glitch.
+ destination_->StartWithWorkletTaskRunner(
+ audio_worklet->GetMessagingProxy()
+ ->GetBackingWorkerThread()
+ ->GetTaskRunner(TaskType::kInternalMedia));
+ } else {
+ destination_->Start();
+ }
+}
+
+void DefaultAudioDestinationHandler::StopDestination() {
+ DCHECK(destination_->IsPlaying());
+
+ destination_->Stop();
+}
+
+// -----------------------------------------------------------------------------
DefaultAudioDestinationNode::DefaultAudioDestinationNode(
BaseAudioContext& context,
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.h b/chromium/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.h
index 2abfee80394..65268abf8b7 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.h
@@ -30,6 +30,7 @@
#include "third_party/blink/public/platform/web_audio_latency_hint.h"
#include "third_party/blink/renderer/modules/webaudio/audio_destination_node.h"
#include "third_party/blink/renderer/platform/audio/audio_destination.h"
+#include "third_party/blink/renderer/platform/audio/audio_io_callback.h"
namespace blink {
@@ -37,60 +38,62 @@ class BaseAudioContext;
class ExceptionState;
class WebAudioLatencyHint;
-class DefaultAudioDestinationHandler final : public AudioDestinationHandler {
+class DefaultAudioDestinationHandler final : public AudioDestinationHandler,
+ public AudioIOCallback {
public:
static scoped_refptr<DefaultAudioDestinationHandler> Create(
AudioNode&,
const WebAudioLatencyHint&);
~DefaultAudioDestinationHandler() override;
- // AudioHandler
+ // For AudioHandler.
void Dispose() override;
void Initialize() override;
void Uninitialize() override;
void SetChannelCount(unsigned long, ExceptionState&) override;
+ double LatencyTime() const override { return 0; }
+ double TailTime() const override { return 0; }
+ bool RequiresTailProcessing() const final { return false; }
- // AudioDestinationHandler
+ // For AudioDestinationHandler.
void StartRendering() override;
void StopRendering() override;
void RestartRendering() override;
unsigned long MaxChannelCount() const override;
- // Returns the rendering callback buffer size.
- size_t CallbackBufferSize() const override;
double SampleRate() const override;
- int FramesPerBuffer() const override;
- double TailTime() const override { return 0; }
- double LatencyTime() const override { return 0; }
- bool RequiresTailProcessing() const final { return false; }
+ // For AudioIOCallback. This is invoked by the platform audio destination to
+ // get the next render quantum into |destination_bus| and update
+ // |output_position|.
+ void Render(AudioBus* destination_bus,
+ size_t number_of_frames,
+ const AudioIOPosition& output_position) final;
+
+ // Returns a hadrware callback buffer size from audio infra.
+ size_t GetCallbackBufferSize() const;
+
+ // Returns a given frames-per-buffer size from audio infra.
+ int GetFramesPerBuffer() const;
private:
explicit DefaultAudioDestinationHandler(AudioNode&,
const WebAudioLatencyHint&);
- void CreateDestination();
- // Starts platform/AudioDestination. If the runtime flag for AudioWorklet is
- // set, uses the AudioWorkletThread's backing thread for the rendering.
+ void CreateDestination();
void StartDestination();
-
void StopDestination();
- // Uses |RefPtr| to keep the AudioDestination alive until all the cross-thread
- // tasks are completed.
- scoped_refptr<AudioDestination> destination_;
-
- String input_device_id_;
- unsigned number_of_input_channels_;
const WebAudioLatencyHint latency_hint_;
+ scoped_refptr<AudioDestination> destination_;
};
+// -----------------------------------------------------------------------------
+
class DefaultAudioDestinationNode final : public AudioDestinationNode {
public:
static DefaultAudioDestinationNode* Create(BaseAudioContext*,
const WebAudioLatencyHint&);
- size_t CallbackBufferSize() const { return Handler().CallbackBufferSize(); };
-
private:
explicit DefaultAudioDestinationNode(BaseAudioContext&,
const WebAudioLatencyHint&);
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc b/chromium/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc
index 2fa973ef7d7..d0115b1065c 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/deferred_task_handler.cc
@@ -23,10 +23,12 @@
* DAMAGE.
*/
+#include "third_party/blink/renderer/modules/webaudio/deferred_task_handler.h"
+
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
-#include "third_party/blink/renderer/modules/webaudio/deferred_task_handler.h"
#include "third_party/blink/renderer/modules/webaudio/offline_audio_context.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/web_task_runner.h"
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/delay_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/delay_node.cc
index a433e930782..cc527506953 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/delay_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/delay_node.cc
@@ -27,12 +27,11 @@
#include <memory>
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/webaudio/audio_basic_processor_handler.h"
#include "third_party/blink/renderer/modules/webaudio/delay_options.h"
#include "third_party/blink/renderer/modules/webaudio/delay_processor.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
namespace blink {
@@ -97,7 +96,7 @@ DelayNode* DelayNode::Create(BaseAudioContext& context,
if (max_delay_time <= 0 || max_delay_time >= kMaximumAllowedDelayTime) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
ExceptionMessages::IndexOutsideRange(
"max delay time", max_delay_time, 0.0,
ExceptionMessages::kExclusiveBound, kMaximumAllowedDelayTime,
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/dynamics_compressor_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/dynamics_compressor_node.cc
index dbf44301fb3..1fd4e451a0d 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/dynamics_compressor_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/dynamics_compressor_node.cc
@@ -23,14 +23,15 @@
* DAMAGE.
*/
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/modules/webaudio/dynamics_compressor_node.h"
+
#include "third_party/blink/renderer/modules/webaudio/audio_node_input.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
-#include "third_party/blink/renderer/modules/webaudio/dynamics_compressor_node.h"
#include "third_party/blink/renderer/modules/webaudio/dynamics_compressor_options.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
#include "third_party/blink/renderer/platform/audio/dynamics_compressor.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
// Set output to stereo by default.
static const unsigned defaultNumberOfOutputChannels = 2;
@@ -154,10 +155,11 @@ void DynamicsCompressorHandler::SetChannelCount(
}
} else {
exception_state.ThrowDOMException(
- kNotSupportedError, ExceptionMessages::IndexOutsideRange<unsigned long>(
- "channelCount", channel_count, 1,
- ExceptionMessages::kInclusiveBound, 2,
- ExceptionMessages::kInclusiveBound));
+ DOMExceptionCode::kNotSupportedError,
+ ExceptionMessages::IndexOutsideRange<unsigned long>(
+ "channelCount", channel_count, 1,
+ ExceptionMessages::kInclusiveBound, 2,
+ ExceptionMessages::kInclusiveBound));
}
}
@@ -176,7 +178,7 @@ void DynamicsCompressorHandler::SetChannelCountMode(
} else if (mode == "max") {
// This is not supported for a DynamicsCompressorNode, which can
// only handle 1 or 2 channels.
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"The provided value 'max' is not an "
"allowed value for ChannelCountMode");
new_channel_count_mode_ = old_mode;
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/iir_filter_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/iir_filter_node.cc
index 0e02dce339d..96e2aa951bf 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/iir_filter_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/iir_filter_node.cc
@@ -6,12 +6,11 @@
#include <memory>
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
#include "third_party/blink/renderer/modules/webaudio/iir_filter_options.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/histogram.h"
namespace blink {
@@ -118,7 +117,7 @@ IIRFilterNode* IIRFilterNode::Create(BaseAudioContext& context,
if (feedback_coef.size() == 0 ||
(feedback_coef.size() > IIRFilter::kMaxOrder + 1)) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
ExceptionMessages::IndexOutsideRange<size_t>(
"number of feedback coefficients", feedback_coef.size(), 1,
ExceptionMessages::kInclusiveBound, IIRFilter::kMaxOrder + 1,
@@ -129,7 +128,7 @@ IIRFilterNode* IIRFilterNode::Create(BaseAudioContext& context,
if (feedforward_coef.size() == 0 ||
(feedforward_coef.size() > IIRFilter::kMaxOrder + 1)) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
ExceptionMessages::IndexOutsideRange<size_t>(
"number of feedforward coefficients", feedforward_coef.size(), 1,
ExceptionMessages::kInclusiveBound, IIRFilter::kMaxOrder + 1,
@@ -139,7 +138,8 @@ IIRFilterNode* IIRFilterNode::Create(BaseAudioContext& context,
if (feedback_coef[0] == 0) {
exception_state.ThrowDOMException(
- kInvalidStateError, "First feedback coefficient cannot be zero.");
+ DOMExceptionCode::kInvalidStateError,
+ "First feedback coefficient cannot be zero.");
return nullptr;
}
@@ -154,7 +154,7 @@ IIRFilterNode* IIRFilterNode::Create(BaseAudioContext& context,
if (!has_non_zero_coef) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"At least one feedforward coefficient must be non-zero.");
return nullptr;
}
@@ -212,7 +212,7 @@ void IIRFilterNode::getFrequencyResponse(
// the arrays have the same length as the |frequency_hz| array.
if (mag_response.View()->length() != frequency_hz_length) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
ExceptionMessages::IndexOutsideRange(
"magResponse length", mag_response.View()->length(),
frequency_hz_length, ExceptionMessages::kInclusiveBound,
@@ -222,7 +222,7 @@ void IIRFilterNode::getFrequencyResponse(
if (phase_response.View()->length() != frequency_hz_length) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
ExceptionMessages::IndexOutsideRange(
"phaseResponse length", phase_response.View()->length(),
frequency_hz_length, ExceptionMessages::kInclusiveBound,
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.cc
index d55da1fcc18..9c24f3a4ff5 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.cc
@@ -26,13 +26,14 @@
#include "third_party/blink/renderer/modules/webaudio/media_element_audio_source_node.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/core/frame/deprecation.h"
#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/modules/webaudio/audio_node_output.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
#include "third_party/blink/renderer/modules/webaudio/media_element_audio_source_options.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/locker.h"
@@ -235,7 +236,7 @@ MediaElementAudioSourceNode* MediaElementAudioSourceNode::Create(
// First check if this media element already has a source node.
if (media_element.AudioSourceNode()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"HTMLMediaElement already connected "
"previously to a different "
"MediaElementSourceNode.");
@@ -249,6 +250,11 @@ MediaElementAudioSourceNode* MediaElementAudioSourceNode::Create(
media_element.SetAudioSourceNode(node);
// context keeps reference until node is disconnected
context.NotifySourceNodeStartedProcessing(node);
+ if (!context.HasRealtimeConstraint()) {
+ Deprecation::CountDeprecation(
+ node->GetExecutionContext(),
+ WebFeature::kMediaElementSourceOnOfflineContext);
+ }
}
return node;
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/media_stream_audio_destination_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/media_stream_audio_destination_node.cc
index ef84d6b2a0f..d9f697bf68a 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/media_stream_audio_destination_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/media_stream_audio_destination_node.cc
@@ -23,14 +23,15 @@
* DAMAGE.
*/
+#include "third_party/blink/renderer/modules/webaudio/media_stream_audio_destination_node.h"
+
#include "third_party/blink/public/platform/web_rtc_peer_connection_handler.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_input.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_options.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
-#include "third_party/blink/renderer/modules/webaudio/media_stream_audio_destination_node.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_center.h"
#include "third_party/blink/renderer/platform/uuid.h"
#include "third_party/blink/renderer/platform/wtf/locker.h"
@@ -119,7 +120,7 @@ void MediaStreamAudioDestinationHandler::SetChannelCount(
// exception here is useful to developers.
if (channel_count < 1 || channel_count > MaxChannelCount()) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
ExceptionMessages::IndexOutsideRange<unsigned>(
"channel count", channel_count, 1,
ExceptionMessages::kInclusiveBound, MaxChannelCount(),
@@ -181,6 +182,12 @@ MediaStreamAudioDestinationNode* MediaStreamAudioDestinationNode::Create(
node->HandleChannelOptions(options, exception_state);
+ if (!context->HasRealtimeConstraint()) {
+ Deprecation::CountDeprecation(
+ node->GetExecutionContext(),
+ WebFeature::kMediaStreamDestinationOnOfflineContext);
+ }
+
return node;
}
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/media_stream_audio_source_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/media_stream_audio_source_node.cc
index 52aaf0bb0f8..59c845c491f 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/media_stream_audio_source_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/media_stream_audio_source_node.cc
@@ -26,11 +26,11 @@
#include "third_party/blink/renderer/modules/webaudio/media_stream_audio_source_node.h"
#include <memory>
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/core/frame/deprecation.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
#include "third_party/blink/renderer/modules/webaudio/media_stream_audio_source_options.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/locker.h"
namespace blink {
@@ -144,7 +144,7 @@ MediaStreamAudioSourceNode* MediaStreamAudioSourceNode::Create(
MediaStreamTrackVector audio_tracks = media_stream.getAudioTracks();
if (audio_tracks.IsEmpty()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"MediaStream has no audio track");
return nullptr;
}
@@ -166,6 +166,12 @@ MediaStreamAudioSourceNode* MediaStreamAudioSourceNode::Create(
// context keeps reference until node is disconnected
context.NotifySourceNodeStartedProcessing(node);
+ if (!context.HasRealtimeConstraint()) {
+ Deprecation::CountDeprecation(
+ node->GetExecutionContext(),
+ WebFeature::kMediaStreamSourceOnOfflineContext);
+ }
+
return node;
}
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc b/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc
index 2d89cd73d23..a8626462212 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc
@@ -23,22 +23,21 @@
* DAMAGE.
*/
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
+#include "third_party/blink/renderer/modules/webaudio/offline_audio_context.h"
+
+#include "third_party/blink/public/platform/platform.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/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/webaudio/audio_listener.h"
#include "third_party/blink/renderer/modules/webaudio/deferred_task_handler.h"
#include "third_party/blink/renderer/modules/webaudio/offline_audio_completion_event.h"
-#include "third_party/blink/renderer/modules/webaudio/offline_audio_context.h"
#include "third_party/blink/renderer/modules/webaudio/offline_audio_context_options.h"
#include "third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
-
-#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.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/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/histogram.h"
@@ -52,7 +51,7 @@ OfflineAudioContext* OfflineAudioContext::Create(
ExceptionState& exception_state) {
// FIXME: add support for workers.
if (!context || !context->IsDocument()) {
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"Workers are not supported.");
return nullptr;
}
@@ -61,7 +60,7 @@ OfflineAudioContext* OfflineAudioContext::Create(
if (!number_of_frames) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
ExceptionMessages::IndexExceedsMinimumBound<unsigned>(
"number of frames", number_of_frames, 1));
return nullptr;
@@ -70,22 +69,24 @@ OfflineAudioContext* OfflineAudioContext::Create(
if (number_of_channels == 0 ||
number_of_channels > BaseAudioContext::MaxNumberOfChannels()) {
exception_state.ThrowDOMException(
- kNotSupportedError, ExceptionMessages::IndexOutsideRange<unsigned>(
- "number of channels", number_of_channels, 1,
- ExceptionMessages::kInclusiveBound,
- BaseAudioContext::MaxNumberOfChannels(),
- ExceptionMessages::kInclusiveBound));
+ DOMExceptionCode::kNotSupportedError,
+ ExceptionMessages::IndexOutsideRange<unsigned>(
+ "number of channels", number_of_channels, 1,
+ ExceptionMessages::kInclusiveBound,
+ BaseAudioContext::MaxNumberOfChannels(),
+ ExceptionMessages::kInclusiveBound));
return nullptr;
}
if (!AudioUtilities::IsValidAudioBufferSampleRate(sample_rate)) {
exception_state.ThrowDOMException(
- kNotSupportedError, ExceptionMessages::IndexOutsideRange(
- "sampleRate", sample_rate,
- AudioUtilities::MinAudioBufferSampleRate(),
- ExceptionMessages::kInclusiveBound,
- AudioUtilities::MaxAudioBufferSampleRate(),
- ExceptionMessages::kInclusiveBound));
+ DOMExceptionCode::kNotSupportedError,
+ ExceptionMessages::IndexOutsideRange(
+ "sampleRate", sample_rate,
+ AudioUtilities::MinAudioBufferSampleRate(),
+ ExceptionMessages::kInclusiveBound,
+ AudioUtilities::MaxAudioBufferSampleRate(),
+ ExceptionMessages::kInclusiveBound));
return nullptr;
}
@@ -168,7 +169,7 @@ ScriptPromise OfflineAudioContext::startOfflineRendering(
if (IsContextClosed()) {
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kInvalidStateError,
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
"cannot call startRendering on an "
"OfflineAudioContext in a stopped state."));
}
@@ -179,7 +180,7 @@ ScriptPromise OfflineAudioContext::startOfflineRendering(
return ScriptPromise::RejectWithDOMException(
script_state,
DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"cannot startRendering when an OfflineAudioContext is " + state()));
}
@@ -187,7 +188,7 @@ ScriptPromise OfflineAudioContext::startOfflineRendering(
if (is_rendering_started_) {
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kInvalidStateError,
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
"cannot call startRendering more than once"));
}
@@ -205,7 +206,7 @@ ScriptPromise OfflineAudioContext::startOfflineRendering(
if (!render_target) {
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kNotSupportedError,
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
"startRendering failed to create AudioBuffer(" +
String::Number(number_of_channels) + ", " +
String::Number(total_render_frames_) + ", " +
@@ -236,7 +237,7 @@ ScriptPromise OfflineAudioContext::suspendContext(ScriptState* script_state,
// If the rendering is finished, reject the promise.
if (ContextState() == AudioContextState::kClosed) {
- resolver->Reject(DOMException::Create(kInvalidStateError,
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kInvalidStateError,
"the rendering is already finished"));
return promise;
}
@@ -244,7 +245,7 @@ ScriptPromise OfflineAudioContext::suspendContext(ScriptState* script_state,
// The specified suspend time is negative; reject the promise.
if (when < 0) {
resolver->Reject(DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"negative suspend time (" + String::Number(when) + ") is not allowed"));
return promise;
}
@@ -255,7 +256,7 @@ ScriptPromise OfflineAudioContext::suspendContext(ScriptState* script_state,
double total_render_duration = total_render_frames_ / sampleRate();
if (total_render_duration <= when) {
resolver->Reject(DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"cannot schedule a suspend at " +
String::NumberToStringECMAScript(when) +
" seconds because it is greater than "
@@ -277,7 +278,7 @@ ScriptPromise OfflineAudioContext::suspendContext(ScriptState* script_state,
double current_time_clamped =
std::min(currentTime(), length() / static_cast<double>(sampleRate()));
resolver->Reject(DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"suspend(" + String::Number(when) + ") failed to suspend at frame " +
String::Number(frame) + " because it is earlier than the current " +
"frame of " + String::Number(current_frame_clamped) + " (" +
@@ -293,9 +294,9 @@ ScriptPromise OfflineAudioContext::suspendContext(ScriptState* script_state,
// reject the promise.
if (scheduled_suspends_.Contains(frame)) {
resolver->Reject(DOMException::Create(
- kInvalidStateError, "cannot schedule more than one suspend at frame " +
- String::Number(frame) + " (" +
- String::Number(when) + " seconds)"));
+ DOMExceptionCode::kInvalidStateError,
+ "cannot schedule more than one suspend at frame " +
+ String::Number(frame) + " (" + String::Number(when) + " seconds)"));
return promise;
}
@@ -313,15 +314,16 @@ ScriptPromise OfflineAudioContext::resumeContext(ScriptState* script_state) {
// If the rendering has not started, reject the promise.
if (!is_rendering_started_) {
resolver->Reject(DOMException::Create(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"cannot resume an offline context that has not started"));
return promise;
}
// If the context is in a closed state, reject the promise.
if (ContextState() == AudioContextState::kClosed) {
- resolver->Reject(DOMException::Create(
- kInvalidStateError, "cannot resume a closed offline context"));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "cannot resume a closed offline context"));
return promise;
}
@@ -371,8 +373,9 @@ void OfflineAudioContext::FireCompletionEvent() {
complete_resolver_->Resolve(rendered_buffer);
} else {
// The resolver should be rejected when the execution context is gone.
- complete_resolver_->Reject(DOMException::Create(
- kInvalidStateError, "the execution context does not exist"));
+ complete_resolver_->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "the execution context does not exist"));
}
is_rendering_started_ = false;
@@ -447,7 +450,7 @@ void OfflineAudioContext::RejectPendingResolvers() {
for (auto& pending_suspend_resolver : scheduled_suspends_) {
pending_suspend_resolver.value->Reject(DOMException::Create(
- kInvalidStateError, "Audio context is going away"));
+ DOMExceptionCode::kInvalidStateError, "Audio context is going away"));
}
scheduled_suspends_.clear();
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_context.h b/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_context.h
index ee10cdb6120..dc9e3bddb19 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_context.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_context.h
@@ -85,6 +85,9 @@ class MODULES_EXPORT OfflineAudioContext final : public BaseAudioContext {
// from the map (m_scheduledSuspends) and resolved.
void ResolveSuspendOnMainThread(size_t);
+ // OfflineAudioContext is not affected by Autoplay, so this MUST do nothing.
+ void NotifySourceNodeStart() final {}
+
// The HashMap with 'zero' key is needed because |currentSampleFrame| can be
// zero.
using SuspendMap = HeapHashMap<size_t,
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc
index dc9595eb751..673121b3094 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.cc
@@ -135,12 +135,6 @@ void OfflineAudioDestinationHandler::StopRendering() {
NOTREACHED();
}
-size_t OfflineAudioDestinationHandler::CallbackBufferSize() const {
- // The callback buffer size has no meaning for an offline context.
- NOTREACHED();
- return 0;
-}
-
void OfflineAudioDestinationHandler::InitializeOfflineRenderThread(
AudioBuffer* render_target) {
DCHECK(IsMainThread());
@@ -271,6 +265,12 @@ void OfflineAudioDestinationHandler::NotifyComplete() {
render_thread_.reset();
+ // If the execution context has been destroyed, there's no where to
+ // send the notification, so just return.
+ if (IsExecutionContextDestroyed()) {
+ return;
+ }
+
// The OfflineAudioContext might be gone.
if (Context() && Context()->GetExecutionContext())
Context()->FireCompletionEvent();
@@ -314,10 +314,6 @@ bool OfflineAudioDestinationHandler::RenderIfNotSuspended(
return true;
}
- // Prepare the local audio input provider for this render quantum.
- if (source_bus)
- local_audio_input_provider_.Set(source_bus);
-
DCHECK_GE(NumberOfInputs(), 1u);
if (NumberOfInputs() < 1) {
destination_bus->Zero();
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h b/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h
index 1928524c9a1..db4a535ab41 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h
@@ -66,15 +66,7 @@ class OfflineAudioDestinationHandler final : public AudioDestinationHandler {
void RestartRendering() override;
- // Returns the rendering callback buffer size. This should never be
- // called.
- size_t CallbackBufferSize() const override;
-
double SampleRate() const override { return sample_rate_; }
- int FramesPerBuffer() const override {
- NOTREACHED();
- return 0;
- }
size_t RenderQuantumFrames() const {
return AudioUtilities::kRenderQuantumFrames;
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/oscillator_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/oscillator_node.cc
index a7c84e2187a..5c679152a33 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/oscillator_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/oscillator_node.cc
@@ -24,14 +24,13 @@
*/
#include <algorithm>
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+
#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
#include "third_party/blink/renderer/modules/webaudio/oscillator_node.h"
#include "third_party/blink/renderer/modules/webaudio/periodic_wave.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
#include "third_party/blink/renderer/platform/audio/vector_math.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
@@ -119,7 +118,7 @@ void OscillatorHandler::SetType(const String& type,
} else if (type == "triangle") {
SetType(TRIANGLE);
} else if (type == "custom") {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"'type' cannot be set directly to "
"'custom'. Use setPeriodicWave() to "
"create a custom Oscillator type.");
@@ -509,7 +508,7 @@ OscillatorNode* OscillatorNode::Create(BaseAudioContext* context,
ExceptionState& exception_state) {
if (options.type() == "custom" && !options.hasPeriodicWave()) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"A PeriodicWave must be specified if the type is set to \"custom\"");
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/panner_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/panner_node.cc
index 3c5f8d65e7b..51821b017fa 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/panner_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/panner_node.cc
@@ -23,17 +23,17 @@
* DAMAGE.
*/
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/modules/webaudio/panner_node.h"
+
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/webaudio/audio_buffer_source_node.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_input.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
-#include "third_party/blink/renderer/modules/webaudio/panner_node.h"
#include "third_party/blink/renderer/modules/webaudio/panner_options.h"
#include "third_party/blink/renderer/platform/audio/hrtf_panner.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
@@ -591,10 +591,11 @@ void PannerHandler::SetChannelCount(unsigned long channel_count,
}
} else {
exception_state.ThrowDOMException(
- kNotSupportedError, ExceptionMessages::IndexOutsideRange<unsigned long>(
- "channelCount", channel_count, 1,
- ExceptionMessages::kInclusiveBound, 2,
- ExceptionMessages::kInclusiveBound));
+ DOMExceptionCode::kNotSupportedError,
+ ExceptionMessages::IndexOutsideRange<unsigned long>(
+ "channelCount", channel_count, 1,
+ ExceptionMessages::kInclusiveBound, 2,
+ ExceptionMessages::kInclusiveBound));
}
}
@@ -612,7 +613,7 @@ void PannerHandler::SetChannelCountMode(const String& mode,
} else if (mode == "max") {
// This is not supported for a PannerNode, which can only handle 1 or 2
// channels.
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"Panner: 'max' is not allowed");
new_channel_count_mode_ = old_mode;
} else {
@@ -788,9 +789,9 @@ double PannerNode::refDistance() const {
void PannerNode::setRefDistance(double distance,
ExceptionState& exception_state) {
if (distance < 0) {
- exception_state.ThrowDOMException(
- kV8RangeError, ExceptionMessages::IndexExceedsMinimumBound<double>(
- "refDistance", distance, 0));
+ exception_state.ThrowRangeError(
+ ExceptionMessages::IndexExceedsMinimumBound<double>("refDistance",
+ distance, 0));
return;
}
@@ -804,9 +805,9 @@ double PannerNode::maxDistance() const {
void PannerNode::setMaxDistance(double distance,
ExceptionState& exception_state) {
if (distance <= 0) {
- exception_state.ThrowDOMException(
- kV8RangeError, ExceptionMessages::IndexExceedsMinimumBound<double>(
- "maxDistance", distance, 0));
+ exception_state.ThrowRangeError(
+ ExceptionMessages::IndexExceedsMinimumBound<double>("maxDistance",
+ distance, 0));
return;
}
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/periodic_wave.cc b/chromium/third_party/blink/renderer/modules/webaudio/periodic_wave.cc
index 675bf79980c..01568dbfa4c 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/periodic_wave.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/periodic_wave.cc
@@ -28,15 +28,14 @@
#include <algorithm>
#include <memory>
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
#include "third_party/blink/renderer/modules/webaudio/oscillator_node.h"
#include "third_party/blink/renderer/modules/webaudio/periodic_wave.h"
#include "third_party/blink/renderer/modules/webaudio/periodic_wave_options.h"
#include "third_party/blink/renderer/platform/audio/fft_frame.h"
#include "third_party/blink/renderer/platform/audio/vector_math.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -66,10 +65,10 @@ PeriodicWave* PeriodicWave::Create(BaseAudioContext& context,
if (real.size() != imag.size()) {
exception_state.ThrowDOMException(
- kIndexSizeError, "length of real array (" +
- String::Number(real.size()) +
- ") and length of imaginary array (" +
- String::Number(imag.size()) + ") must match.");
+ DOMExceptionCode::kIndexSizeError,
+ "length of real array (" + String::Number(real.size()) +
+ ") and length of imaginary array (" + String::Number(imag.size()) +
+ ") must match.");
return nullptr;
}
@@ -319,7 +318,7 @@ void PeriodicWave::GenerateBasicWaveform(int shape) {
imag_p[0] = 0;
for (unsigned n = 1; n < half_size; ++n) {
- float pi_factor = 2 / (n * piFloat);
+ float pi_factor = 2 / (n * kPiFloat);
// All waveforms are odd functions with a positive slope at time 0. Hence
// the coefficients for cos() are always 0.
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/realtime_analyser.cc b/chromium/third_party/blink/renderer/modules/webaudio/realtime_analyser.cc
index f061b2e7b50..e6a293d6e69 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/realtime_analyser.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/realtime_analyser.cc
@@ -124,7 +124,7 @@ void ApplyWindow(float* p, size_t n) {
for (unsigned i = 0; i < n; ++i) {
double x = static_cast<double>(i) / static_cast<double>(n);
double window =
- a0 - a1 * cos(twoPiDouble * x) + a2 * cos(twoPiDouble * 2.0 * x);
+ a0 - a1 * cos(kTwoPiDouble * x) + a2 * cos(kTwoPiDouble * 2.0 * x);
p[i] *= float(window);
}
}
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/script_processor_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/script_processor_node.cc
index 445f8a5853d..12f620d5ac8 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/script_processor_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/script_processor_node.cc
@@ -29,16 +29,17 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/webaudio/audio_buffer.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_input.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
#include "third_party/blink/renderer/modules/webaudio/audio_processing_event.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
+#include "third_party/blink/renderer/modules/webaudio/default_audio_destination_node.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/waitable_event.h"
+#include "third_party/blink/renderer/platform/web_task_runner.h"
namespace blink {
@@ -336,10 +337,11 @@ void ScriptProcessorHandler::SetChannelCount(unsigned long channel_count,
BaseAudioContext::GraphAutoLocker locker(Context());
if (channel_count != channel_count_) {
- exception_state.ThrowDOMException(
- kNotSupportedError, "channelCount cannot be changed from " +
- String::Number(channel_count_) + " to " +
- String::Number(channel_count));
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+ "channelCount cannot be changed from " +
+ String::Number(channel_count_) +
+ " to " +
+ String::Number(channel_count));
}
}
@@ -351,7 +353,7 @@ void ScriptProcessorHandler::SetChannelCountMode(
if ((mode == "max") || (mode == "clamped-max")) {
exception_state.ThrowDOMException(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"channelCountMode cannot be changed from 'explicit' to '" + mode + "'");
}
}
@@ -373,7 +375,7 @@ static size_t ChooseBufferSize(size_t callback_buffer_size) {
// Choose a buffer size based on the audio hardware buffer size. Arbitarily
// make it a power of two that is 4 times greater than the hardware buffer
// size.
- // FIXME: What is the best way to choose this?
+ // TODO(crbug.com/855758): What is the best way to choose this?
size_t buffer_size =
1 << static_cast<unsigned>(log2(4 * callback_buffer_size) + 0.5);
@@ -397,29 +399,29 @@ ScriptProcessorNode* ScriptProcessorNode::Create(
ScriptProcessorNode* ScriptProcessorNode::Create(
BaseAudioContext& context,
- size_t buffer_size,
+ size_t requested_buffer_size,
ExceptionState& exception_state) {
DCHECK(IsMainThread());
// Default is 2 inputs and 2 outputs.
- return Create(context, buffer_size, 2, 2, exception_state);
+ return Create(context, requested_buffer_size, 2, 2, exception_state);
}
ScriptProcessorNode* ScriptProcessorNode::Create(
BaseAudioContext& context,
- size_t buffer_size,
+ size_t requested_buffer_size,
unsigned number_of_input_channels,
ExceptionState& exception_state) {
DCHECK(IsMainThread());
// Default is 2 outputs.
- return Create(context, buffer_size, number_of_input_channels, 2,
+ return Create(context, requested_buffer_size, number_of_input_channels, 2,
exception_state);
}
ScriptProcessorNode* ScriptProcessorNode::Create(
BaseAudioContext& context,
- size_t buffer_size,
+ size_t requested_buffer_size,
unsigned number_of_input_channels,
unsigned number_of_output_channels,
ExceptionState& exception_state) {
@@ -432,14 +434,14 @@ ScriptProcessorNode* ScriptProcessorNode::Create(
if (number_of_input_channels == 0 && number_of_output_channels == 0) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
"number of input channels and output channels cannot both be zero.");
return nullptr;
}
if (number_of_input_channels > BaseAudioContext::MaxNumberOfChannels()) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
"number of input channels (" +
String::Number(number_of_input_channels) + ") exceeds maximum (" +
String::Number(BaseAudioContext::MaxNumberOfChannels()) + ").");
@@ -448,24 +450,34 @@ ScriptProcessorNode* ScriptProcessorNode::Create(
if (number_of_output_channels > BaseAudioContext::MaxNumberOfChannels()) {
exception_state.ThrowDOMException(
- kIndexSizeError,
+ DOMExceptionCode::kIndexSizeError,
"number of output channels (" +
String::Number(number_of_output_channels) + ") exceeds maximum (" +
String::Number(BaseAudioContext::MaxNumberOfChannels()) + ").");
return nullptr;
}
- // Check for valid buffer size.
- switch (buffer_size) {
+ // Sanitize user-supplied buffer size.
+ size_t buffer_size;
+ switch (requested_buffer_size) {
case 0:
// Choose an appropriate size. For an AudioContext, we need to
// choose an appropriate size based on the callback buffer size.
// For OfflineAudioContext, there's no callback buffer size, so
// just use the minimum valid buffer size.
- buffer_size =
- context.HasRealtimeConstraint()
- ? ChooseBufferSize(context.destination()->CallbackBufferSize())
- : 256;
+ if (context.HasRealtimeConstraint()) {
+ // TODO(crbug.com/854229): Due to the incompatible constructor between
+ // AudioDestinationNode and DefaultAudioDestinationNode, casting
+ // directly from |destination()| is impossible. This is a temporary
+ // workaround until the refactoring is completed.
+ DefaultAudioDestinationHandler& destination_handler =
+ static_cast<DefaultAudioDestinationHandler&>(
+ context.destination()->GetAudioDestinationHandler());
+ buffer_size =
+ ChooseBufferSize(destination_handler.GetCallbackBufferSize());
+ } else {
+ buffer_size = 256;
+ }
break;
case 256:
case 512:
@@ -474,11 +486,12 @@ ScriptProcessorNode* ScriptProcessorNode::Create(
case 4096:
case 8192:
case 16384:
+ buffer_size = requested_buffer_size;
break;
default:
exception_state.ThrowDOMException(
- kIndexSizeError,
- "buffer size (" + String::Number(buffer_size) +
+ DOMExceptionCode::kIndexSizeError,
+ "buffer size (" + String::Number(requested_buffer_size) +
") must be 0 or a power of two between 256 and 16384.");
return nullptr;
}
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/script_processor_node.h b/chromium/third_party/blink/renderer/modules/webaudio/script_processor_node.h
index 26af461ca5d..fa04c857c96 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/script_processor_node.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/script_processor_node.h
@@ -126,14 +126,14 @@ class ScriptProcessorNode final
// The value chosen must carefully balance between latency and audio quality.
static ScriptProcessorNode* Create(BaseAudioContext&, ExceptionState&);
static ScriptProcessorNode* Create(BaseAudioContext&,
- size_t buffer_size,
+ size_t requested_buffer_size,
ExceptionState&);
static ScriptProcessorNode* Create(BaseAudioContext&,
- size_t buffer_size,
+ size_t requested_buffer_size,
unsigned number_of_input_channels,
ExceptionState&);
static ScriptProcessorNode* Create(BaseAudioContext&,
- size_t buffer_size,
+ size_t requested_buffer_size,
unsigned number_of_input_channels,
unsigned number_of_output_channels,
ExceptionState&);
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/stereo_panner_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/stereo_panner_node.cc
index 9ef38b67cf1..9d01baaeb51 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/stereo_panner_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/stereo_panner_node.cc
@@ -2,16 +2,16 @@
// 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/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/modules/webaudio/stereo_panner_node.h"
+
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_input.h"
#include "third_party/blink/renderer/modules/webaudio/audio_node_output.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
-#include "third_party/blink/renderer/modules/webaudio/stereo_panner_node.h"
#include "third_party/blink/renderer/modules/webaudio/stereo_panner_options.h"
#include "third_party/blink/renderer/platform/audio/stereo_panner.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
namespace blink {
@@ -104,10 +104,11 @@ void StereoPannerHandler::SetChannelCount(unsigned long channel_count,
}
} else {
exception_state.ThrowDOMException(
- kNotSupportedError, ExceptionMessages::IndexOutsideRange<unsigned long>(
- "channelCount", channel_count, 1,
- ExceptionMessages::kInclusiveBound, 2,
- ExceptionMessages::kInclusiveBound));
+ DOMExceptionCode::kNotSupportedError,
+ ExceptionMessages::IndexOutsideRange<unsigned long>(
+ "channelCount", channel_count, 1,
+ ExceptionMessages::kInclusiveBound, 2,
+ ExceptionMessages::kInclusiveBound));
}
}
@@ -125,7 +126,7 @@ void StereoPannerHandler::SetChannelCountMode(const String& mode,
} else if (mode == "max") {
// This is not supported for a StereoPannerNode, which can only handle
// 1 or 2 channels.
- exception_state.ThrowDOMException(kNotSupportedError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"StereoPanner: 'max' is not allowed");
new_channel_count_mode_ = old_mode;
} else {
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_dsp_kernel.cc b/chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_dsp_kernel.cc
index 6ffee6b427c..0e48f88bef2 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_dsp_kernel.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_dsp_kernel.cc
@@ -34,7 +34,7 @@
namespace blink {
WaveShaperDSPKernel::WaveShaperDSPKernel(WaveShaperProcessor* processor)
- : AudioDSPKernel(processor) {
+ : AudioDSPKernel(processor), tail_time_(0) {
if (processor->Oversample() != WaveShaperProcessor::kOverSampleNone)
LazyInitializeOversampling();
}
@@ -75,6 +75,39 @@ void WaveShaperDSPKernel::Process(const float* source,
}
}
+double WaveShaperDSPKernel::WaveShaperCurveValue(float input,
+ const float* curve_data,
+ int curve_length) const {
+ // Calculate a virtual index based on input -1 -> +1 with -1 being curve[0],
+ // +1 being curve[curveLength - 1], and 0 being at the center of the curve
+ // data. Then linearly interpolate between the two points in the curve.
+ double virtual_index = 0.5 * (input + 1) * (curve_length - 1);
+ double output;
+
+ if (virtual_index < 0) {
+ // input < -1, so use curve[0]
+ output = curve_data[0];
+ } else if (virtual_index >= curve_length - 1) {
+ // input >= 1, so use last curve value
+ output = curve_data[curve_length - 1];
+ } else {
+ // The general case where -1 <= input < 1, where 0 <= virtualIndex <
+ // curveLength - 1, so interpolate between the nearest samples on the
+ // curve.
+ unsigned index1 = static_cast<unsigned>(virtual_index);
+ unsigned index2 = index1 + 1;
+ double interpolation_factor = virtual_index - index1;
+
+ double value1 = curve_data[index1];
+ double value2 = curve_data[index2];
+
+ output =
+ (1.0 - interpolation_factor) * value1 + interpolation_factor * value2;
+ }
+
+ return output;
+}
+
void WaveShaperDSPKernel::ProcessCurve(const float* source,
float* destination,
size_t frames_to_process) {
@@ -103,33 +136,7 @@ void WaveShaperDSPKernel::ProcessCurve(const float* source,
for (unsigned i = 0; i < frames_to_process; ++i) {
const float input = source[i];
- // Calculate a virtual index based on input -1 -> +1 with -1 being curve[0],
- // +1 being curve[curveLength - 1], and 0 being at the center of the curve
- // data. Then linearly interpolate between the two points in the curve.
- double virtual_index = 0.5 * (input + 1) * (curve_length - 1);
- double output;
-
- if (virtual_index < 0) {
- // input < -1, so use curve[0]
- output = curve_data[0];
- } else if (virtual_index >= curve_length - 1) {
- // input >= 1, so use last curve value
- output = curve_data[curve_length - 1];
- } else {
- // The general case where -1 <= input < 1, where 0 <= virtualIndex <
- // curveLength - 1, so interpolate between the nearest samples on the
- // curve.
- unsigned index1 = static_cast<unsigned>(virtual_index);
- unsigned index2 = index1 + 1;
- double interpolation_factor = virtual_index - index1;
-
- double value1 = curve_data[index1];
- double value2 = curve_data[index2];
-
- output =
- (1.0 - interpolation_factor) * value1 + interpolation_factor * value2;
- }
- destination[i] = output;
+ destination[i] = WaveShaperCurveValue(input, curve_data, curve_length);
}
}
@@ -186,6 +193,10 @@ bool WaveShaperDSPKernel::RequiresTailProcessing() const {
return true;
}
+double WaveShaperDSPKernel::TailTime() const {
+ return tail_time_;
+}
+
double WaveShaperDSPKernel::LatencyTime() const {
size_t latency_frames = 0;
WaveShaperDSPKernel* kernel = const_cast<WaveShaperDSPKernel*>(this);
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_dsp_kernel.h b/chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_dsp_kernel.h
index b3c308aedfc..77f037b7f85 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_dsp_kernel.h
+++ b/chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_dsp_kernel.h
@@ -49,7 +49,7 @@ class WaveShaperDSPKernel final : public AudioDSPKernel {
float* dest,
size_t frames_to_process) override;
void Reset() override;
- double TailTime() const override { return 0; }
+ double TailTime() const override;
double LatencyTime() const override;
bool RequiresTailProcessing() const final;
@@ -57,6 +57,14 @@ class WaveShaperDSPKernel final : public AudioDSPKernel {
// needed.
void LazyInitializeOversampling();
+ // Computes value of the WaveShaper
+ double WaveShaperCurveValue(float input,
+ const float* curve_data,
+ int curve_length) const;
+
+ // Set the tail time
+ void SetTailTime(double time) { tail_time_ = time; }
+
protected:
// Apply the shaping curve.
void ProcessCurve(const float* source, float* dest, size_t frames_to_process);
@@ -80,6 +88,14 @@ class WaveShaperDSPKernel final : public AudioDSPKernel {
std::unique_ptr<DownSampler> down_sampler_;
std::unique_ptr<UpSampler> up_sampler2_;
std::unique_ptr<DownSampler> down_sampler2_;
+
+ private:
+ // Tail time for the WaveShaper. This basically can have two values: 0 and
+ // infinity. It only takes the value of infinity if the wave shaper curve is
+ // such that a zero input produces a non-zero output. In this case, the node
+ // has an infinite tail so that silent input continues to produce non-silent
+ // output.
+ double tail_time_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_node.cc b/chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_node.cc
index eb0ff5552bf..b74b95d8f5e 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_node.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_node.cc
@@ -27,11 +27,10 @@
#include <memory>
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/webaudio/base_audio_context.h"
#include "third_party/blink/renderer/modules/webaudio/wave_shaper_options.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
@@ -94,12 +93,17 @@ void WaveShaperNode::SetCurveImpl(const float* curve_data,
if (curve_data && curve_length < 2) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
ExceptionMessages::IndexExceedsMinimumBound<unsigned>("curve length",
curve_length, 2));
return;
}
+ // This is to synchronize with the changes made in
+ // AudioBasicProcessorNode::CheckNumberOfChannelsForInput() where we can
+ // Initialize() and Uninitialize(), changing the number of kernels.
+ BaseAudioContext::GraphAutoLocker context_locker(context());
+
GetWaveShaperProcessor()->SetCurve(curve_data, curve_length);
}
diff --git a/chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_processor.cc b/chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_processor.cc
index ab5bfa13cdb..ec42e046c84 100644
--- a/chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_processor.cc
+++ b/chromium/third_party/blink/renderer/modules/webaudio/wave_shaper_processor.cc
@@ -58,6 +58,20 @@ void WaveShaperProcessor::SetCurve(const float* curve_data,
// Copy the curve data, if any, to our internal buffer.
curve_ = std::make_unique<Vector<float>>(curve_length);
memcpy(curve_->data(), curve_data, sizeof(float) * curve_length);
+
+ DCHECK_GE(kernels_.size(), 1ULL);
+
+ // Compute the curve output for a zero input, and set the tail time for all
+ // the kernels.
+ WaveShaperDSPKernel* kernel =
+ static_cast<WaveShaperDSPKernel*>(kernels_[0].get());
+ double output = kernel->WaveShaperCurveValue(0.0, curve_data, curve_length);
+ double tail_time = output == 0 ? 0 : std::numeric_limits<double>::infinity();
+
+ for (unsigned k = 0; k < kernels_.size(); ++k) {
+ kernel = static_cast<WaveShaperDSPKernel*>(kernels_[k].get());
+ kernel->SetTailTime(tail_time);
+ }
}
void WaveShaperProcessor::SetOversample(OverSampleType oversample) {
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/database.cc b/chromium/third_party/blink/renderer/modules/webdatabase/database.cc
index ac9fbb91b22..1bad37db3a7 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/database.cc
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/database.cc
@@ -27,11 +27,11 @@
#include <memory>
+#include "base/thread_annotations.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_database_observer.h"
#include "third_party/blink/public/platform/web_security_origin.h"
-#include "third_party/blink/renderer/core/dom/exception_code.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/core/probe/core_probes.h"
@@ -55,7 +55,6 @@
#include "third_party/blink/renderer/platform/waitable_event.h"
#include "third_party/blink/renderer/platform/web_task_runner.h"
#include "third_party/blink/renderer/platform/wtf/atomics.h"
-#include "third_party/blink/renderer/platform/wtf/time.h"
// Registering "opened" databases with the DatabaseTracker
// =======================================================
@@ -88,17 +87,77 @@
namespace blink {
-// Defines static local variable after making sure that guid lock is held.
-// (We can't use DEFINE_STATIC_LOCAL for this because it asserts thread
-// safety, which is externally guaranteed by the guideMutex lock)
+namespace {
+
+// Stores a cached version of each database, keyed by a unique integer obtained
+// by providing an origin-name pair.
+class DatabaseVersionCache {
+ public:
+ Mutex& GetMutex() const LOCK_RETURNED(mutex_) { return mutex_; }
+
+ // Registers a globally-unique integer using the string key (reusing it if it
+ // already exists), and returns the integer. Currently, these IDs live for the
+ // lifetime of the process.
+ DatabaseGuid RegisterOriginAndName(const String& origin, const String& name)
+ EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
+ CheckLocked();
+ String string_id = origin + "/" + name;
+ DCHECK(string_id.IsSafeToSendToAnotherThread());
+ DatabaseGuid guid = origin_name_to_guid_.at(string_id);
+ if (!guid) {
+ guid = next_guid_++;
+ origin_name_to_guid_.Set(string_id, guid);
+ }
+ count_.insert(guid);
+ return guid;
+ }
+
+ // Releases one use of this identifier (corresponding to a call to
+ // RegisterOriginAndName). If all uses are released, the cached version will
+ // be erased from memory.
+ void ReleaseGuid(DatabaseGuid guid) EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
+ CheckLocked();
+ DCHECK(count_.Contains(guid));
+ if (count_.erase(guid))
+ guid_to_version_.erase(guid);
+ }
+
+ // The null string is returned only if the cached version has not been set.
+ String GetVersion(DatabaseGuid guid) const EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
+ CheckLocked();
+ return guid_to_version_.at(guid).IsolatedCopy();
+ }
+
+ // Updates the cached version of a database.
+ // The null string is treated as the empty string.
+ void SetVersion(DatabaseGuid guid, const String& new_version)
+ EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
+ CheckLocked();
+ guid_to_version_.Set(guid, new_version.IsNull()
+ ? g_empty_string
+ : new_version.IsolatedCopy());
+ }
+
+ private:
+ void CheckLocked() const ASSERT_EXCLUSIVE_LOCK(mutex_) {
#if DCHECK_IS_ON()
-#define DEFINE_STATIC_LOCAL_WITH_LOCK(type, name, arguments) \
- DCHECK(GuidMutex().Locked()); \
- static type& name = *new type arguments
-#else
-#define DEFINE_STATIC_LOCAL_WITH_LOCK(type, name, arguments) \
- static type& name = *new type arguments
+ DCHECK(mutex_.Locked());
#endif
+ }
+
+ mutable Mutex mutex_;
+ HashMap<String, DatabaseGuid> origin_name_to_guid_ GUARDED_BY(mutex_);
+ HashCountedSet<DatabaseGuid> count_ GUARDED_BY(mutex_);
+ HashMap<DatabaseGuid, String> guid_to_version_ GUARDED_BY(mutex_);
+ DatabaseGuid next_guid_ GUARDED_BY(mutex_) = 1;
+};
+
+DatabaseVersionCache& GetDatabaseVersionCache() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(DatabaseVersionCache, cache, ());
+ return cache;
+}
+
+} // namespace
static const char kVersionKey[] = "WebKitDatabaseVersionKey";
static const char kInfoTableName[] = "__WebKitDatabaseInfoTable__";
@@ -162,63 +221,6 @@ static bool SetTextValueInDatabase(SQLiteDatabase& db,
return true;
}
-// FIXME: move all guid-related functions to a DatabaseVersionTracker class.
-static RecursiveMutex& GuidMutex() {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(RecursiveMutex, mutex, ());
- return mutex;
-}
-
-typedef HashMap<DatabaseGuid, String> GuidVersionMap;
-static GuidVersionMap& GuidToVersionMap() {
- DEFINE_STATIC_LOCAL_WITH_LOCK(GuidVersionMap, map, ());
- return map;
-}
-
-// NOTE: Caller must lock guidMutex().
-static inline void UpdateGuidVersionMap(DatabaseGuid guid, String new_version) {
- // Ensure the the mutex is locked.
-#if DCHECK_IS_ON()
- DCHECK(GuidMutex().Locked());
-#endif
-
- // Note: It is not safe to put an empty string into the guidToVersionMap()
- // map. That's because the map is cross-thread, but empty strings are
- // per-thread. The copy() function makes a version of the string you can
- // use on the current thread, but we need a string we can keep in a
- // cross-thread data structure.
- // FIXME: This is a quite-awkward restriction to have to program with.
-
- // Map null string to empty string (see comment above).
- GuidToVersionMap().Set(
- guid, new_version.IsEmpty() ? String() : new_version.IsolatedCopy());
-}
-
-static HashCountedSet<DatabaseGuid>& GuidCount() {
- DEFINE_STATIC_LOCAL_WITH_LOCK(HashCountedSet<DatabaseGuid>, guid_count, ());
- return guid_count;
-}
-
-static DatabaseGuid GuidForOriginAndName(const String& origin,
- const String& name) {
- // Ensure the the mutex is locked.
-#if DCHECK_IS_ON()
- DCHECK(GuidMutex().Locked());
-#endif
-
- String string_id = origin + "/" + name;
-
- typedef HashMap<String, int> IDGuidMap;
- DEFINE_STATIC_LOCAL_WITH_LOCK(IDGuidMap, string_identifier_to_guid_map, ());
- DatabaseGuid guid = string_identifier_to_guid_map.at(string_id);
- if (!guid) {
- static int current_new_guid = 1;
- guid = current_new_guid++;
- string_identifier_to_guid_map.Set(string_id, guid);
- }
-
- return guid;
-}
-
Database::Database(DatabaseContext* database_context,
const String& name,
const String& expected_version,
@@ -245,9 +247,9 @@ Database::Database(DatabaseContext* database_context,
name_ = "";
{
- RecursiveMutexLocker locker(GuidMutex());
- guid_ = GuidForOriginAndName(GetSecurityOrigin()->ToString(), name);
- GuidCount().insert(guid_);
+ auto& cache = GetDatabaseVersionCache();
+ MutexLocker locker(cache.GetMutex());
+ guid_ = cache.RegisterOriginAndName(GetSecurityOrigin()->ToString(), name);
}
filename_ = DatabaseManager::Manager().FullPathForDatabase(
@@ -426,12 +428,9 @@ void Database::CloseDatabase() {
// See comment at the top this file regarding calling removeOpenDatabase().
DatabaseTracker::Tracker().RemoveOpenDatabase(this);
{
- RecursiveMutexLocker locker(GuidMutex());
-
- DCHECK(GuidCount().Contains(guid_));
- if (GuidCount().erase(guid_)) {
- GuidToVersionMap().erase(guid_);
- }
+ auto& cache = GetDatabaseVersionCache();
+ MutexLocker locker(cache.GetMutex());
+ cache.ReleaseGuid(guid_);
}
}
@@ -464,7 +463,7 @@ class DoneCreatingDatabaseOnExitCaller {
bool Database::PerformOpenAndVerify(bool should_set_version_in_new_database,
DatabaseError& error,
String& error_message) {
- double call_start_time = WTF::CurrentTimeTicksInSeconds();
+ TimeTicks call_start_time = WTF::CurrentTimeTicks();
DoneCreatingDatabaseOnExitCaller on_exit_caller(this);
DCHECK(error_message.IsEmpty());
DCHECK_EQ(error,
@@ -476,8 +475,9 @@ bool Database::PerformOpenAndVerify(bool should_set_version_in_new_database,
if (!sqlite_database_.Open(filename_)) {
ReportOpenDatabaseResult(
- 1, kInvalidStateError, sqlite_database_.LastError(),
- WTF::CurrentTimeTicksInSeconds() - call_start_time);
+ 1, static_cast<int>(DOMExceptionCode::kInvalidStateError),
+ sqlite_database_.LastError(),
+ WTF::CurrentTimeTicks() - call_start_time);
error_message = FormatErrorMessage("unable to open database",
sqlite_database_.LastError(),
sqlite_database_.LastErrorMsg());
@@ -492,13 +492,11 @@ bool Database::PerformOpenAndVerify(bool should_set_version_in_new_database,
String current_version;
{
- RecursiveMutexLocker locker(GuidMutex());
+ auto& cache = GetDatabaseVersionCache();
+ MutexLocker locker(cache.GetMutex());
- GuidVersionMap::iterator entry = GuidToVersionMap().find(guid_);
- if (entry != GuidToVersionMap().end()) {
- // Map null string to empty string (see updateGuidVersionMap()).
- current_version =
- entry->value.IsNull() ? g_empty_string : entry->value.IsolatedCopy();
+ current_version = cache.GetVersion(guid_);
+ if (!current_version.IsNull()) {
STORAGE_DVLOG(1) << "Current cached version for guid " << guid_ << " is "
<< current_version;
@@ -514,7 +512,7 @@ bool Database::PerformOpenAndVerify(bool should_set_version_in_new_database,
String version_from_database;
if (GetVersionFromDatabase(version_from_database, false)) {
current_version = version_from_database;
- UpdateGuidVersionMap(guid_, current_version);
+ cache.SetVersion(guid_, current_version);
}
sqlite_database_.SetBusyTimeout(kMaxSqliteBusyWaitTime);
} else {
@@ -524,8 +522,9 @@ bool Database::PerformOpenAndVerify(bool should_set_version_in_new_database,
transaction.begin();
if (!transaction.InProgress()) {
ReportOpenDatabaseResult(
- 2, kInvalidStateError, sqlite_database_.LastError(),
- WTF::CurrentTimeTicksInSeconds() - call_start_time);
+ 2, static_cast<int>(DOMExceptionCode::kInvalidStateError),
+ sqlite_database_.LastError(),
+ WTF::CurrentTimeTicks() - call_start_time);
error_message = FormatErrorMessage(
"unable to open database, failed to start transaction",
sqlite_database_.LastError(), sqlite_database_.LastErrorMsg());
@@ -542,8 +541,9 @@ bool Database::PerformOpenAndVerify(bool should_set_version_in_new_database,
" (key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT "
"REPLACE,value TEXT NOT NULL ON CONFLICT FAIL);")) {
ReportOpenDatabaseResult(
- 3, kInvalidStateError, sqlite_database_.LastError(),
- WTF::CurrentTimeTicksInSeconds() - call_start_time);
+ 3, static_cast<int>(DOMExceptionCode::kInvalidStateError),
+ sqlite_database_.LastError(),
+ WTF::CurrentTimeTicks() - call_start_time);
error_message = FormatErrorMessage(
"unable to open database, failed to create 'info' table",
sqlite_database_.LastError(), sqlite_database_.LastErrorMsg());
@@ -553,8 +553,9 @@ bool Database::PerformOpenAndVerify(bool should_set_version_in_new_database,
}
} else if (!GetVersionFromDatabase(current_version, false)) {
ReportOpenDatabaseResult(
- 4, kInvalidStateError, sqlite_database_.LastError(),
- WTF::CurrentTimeTicksInSeconds() - call_start_time);
+ 4, static_cast<int>(DOMExceptionCode::kInvalidStateError),
+ sqlite_database_.LastError(),
+ WTF::CurrentTimeTicks() - call_start_time);
error_message = FormatErrorMessage(
"unable to open database, failed to read current version",
sqlite_database_.LastError(), sqlite_database_.LastErrorMsg());
@@ -572,8 +573,9 @@ bool Database::PerformOpenAndVerify(bool should_set_version_in_new_database,
<< " that was just created";
if (!SetVersionInDatabase(expected_version_, false)) {
ReportOpenDatabaseResult(
- 5, kInvalidStateError, sqlite_database_.LastError(),
- WTF::CurrentTimeTicksInSeconds() - call_start_time);
+ 5, static_cast<int>(DOMExceptionCode::kInvalidStateError),
+ sqlite_database_.LastError(),
+ WTF::CurrentTimeTicks() - call_start_time);
error_message = FormatErrorMessage(
"unable to open database, failed to write current version",
sqlite_database_.LastError(), sqlite_database_.LastErrorMsg());
@@ -583,7 +585,7 @@ bool Database::PerformOpenAndVerify(bool should_set_version_in_new_database,
}
current_version = expected_version_;
}
- UpdateGuidVersionMap(guid_, current_version);
+ cache.SetVersion(guid_, current_version);
transaction.Commit();
}
}
@@ -602,8 +604,8 @@ bool Database::PerformOpenAndVerify(bool should_set_version_in_new_database,
if ((!new_ || should_set_version_in_new_database) &&
expected_version_.length() && expected_version_ != current_version) {
ReportOpenDatabaseResult(
- 6, kInvalidStateError, 0,
- WTF::CurrentTimeTicksInSeconds() - call_start_time);
+ 6, static_cast<int>(DOMExceptionCode::kInvalidStateError), 0,
+ WTF::CurrentTimeTicks() - call_start_time);
error_message =
"unable to open database, version mismatch, '" + expected_version_ +
"' does not match the currentVersion of '" + current_version + "'";
@@ -628,8 +630,8 @@ bool Database::PerformOpenAndVerify(bool should_set_version_in_new_database,
expected_version_ = "";
}
- ReportOpenDatabaseResult(
- 0, -1, 0, WTF::CurrentTimeTicksInSeconds() - call_start_time); // OK
+ ReportOpenDatabaseResult(0, -1, 0,
+ WTF::CurrentTimeTicks() - call_start_time); // OK
if (GetDatabaseContext()->GetDatabaseThread())
GetDatabaseContext()->GetDatabaseThread()->RecordDatabaseOpen(this);
@@ -706,14 +708,15 @@ void Database::SetExpectedVersion(const String& version) {
}
String Database::GetCachedVersion() const {
- RecursiveMutexLocker locker(GuidMutex());
- return GuidToVersionMap().at(guid_).IsolatedCopy();
+ auto& cache = GetDatabaseVersionCache();
+ MutexLocker locker(cache.GetMutex());
+ return cache.GetVersion(guid_);
}
void Database::SetCachedVersion(const String& actual_version) {
- // Update the in memory database version map.
- RecursiveMutexLocker locker(GuidMutex());
- UpdateGuidVersionMap(guid_, actual_version);
+ auto& cache = GetDatabaseVersionCache();
+ MutexLocker locker(cache.GetMutex());
+ cache.SetVersion(guid_, actual_version);
}
bool Database::GetActualVersionForTransaction(String& actual_version) {
@@ -784,7 +787,7 @@ void Database::IncrementalVacuumIfNeeded() {
void Database::ReportOpenDatabaseResult(int error_site,
int web_sql_error_code,
int sqlite_error_code,
- double duration) {
+ TimeDelta duration) {
if (Platform::Current()->DatabaseObserver()) {
Platform::Current()->DatabaseObserver()->ReportOpenDatabaseResult(
WebSecurityOrigin(GetSecurityOrigin()), StringIdentifier(), error_site,
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/database.h b/chromium/third_party/blink/renderer/modules/webdatabase/database.h
index 456406c721e..028fca4713a 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/database.h
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/database.h
@@ -38,6 +38,7 @@
#include "third_party/blink/renderer/platform/weborigin/security_origin.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/time.h"
namespace blink {
@@ -160,7 +161,7 @@ class Database final : public ScriptWrappable {
void ReportOpenDatabaseResult(int error_site,
int web_sql_error_code,
int sqlite_error_code,
- double duration);
+ TimeDelta duration);
void ReportChangeVersionResult(int error_site,
int web_sql_error_code,
int sqlite_error_code);
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/database_manager.cc b/chromium/third_party/blink/renderer/modules/webdatabase/database_manager.cc
index d39237aa409..b0e4bc74089 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/database_manager.cc
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/database_manager.cc
@@ -27,9 +27,6 @@
#include "base/location.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.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/modules/webdatabase/database.h"
@@ -38,6 +35,7 @@
#include "third_party/blink/renderer/modules/webdatabase/database_task.h"
#include "third_party/blink/renderer/modules/webdatabase/database_tracker.h"
#include "third_party/blink/renderer/modules/webdatabase/storage_log.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
namespace blink {
@@ -115,7 +113,8 @@ void DatabaseManager::ThrowExceptionForDatabaseError(
exception_state.ThrowSecurityError(error_message);
return;
case DatabaseError::kInvalidDatabaseState:
- exception_state.ThrowDOMException(kInvalidStateError, error_message);
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
+ error_message);
return;
default:
NOTREACHED();
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/dom_window_web_database.cc b/chromium/third_party/blink/renderer/modules/webdatabase/dom_window_web_database.cc
index de6ee3c67e8..9700310bd25 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/dom_window_web_database.cc
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/dom_window_web_database.cc
@@ -26,13 +26,13 @@
#include "third_party/blink/renderer/modules/webdatabase/dom_window_web_database.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_database_callback.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/use_counter.h"
#include "third_party/blink/renderer/modules/webdatabase/database.h"
#include "third_party/blink/renderer/modules/webdatabase/database_manager.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/inspector_database_agent.cc b/chromium/third_party/blink/renderer/modules/webdatabase/inspector_database_agent.cc
index d7ed0423a8e..95499656922 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/inspector_database_agent.cc
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/inspector_database_agent.cc
@@ -28,7 +28,6 @@
#include "third_party/blink/renderer/modules/webdatabase/inspector_database_agent.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/page/page.h"
@@ -41,6 +40,7 @@
#include "third_party/blink/renderer/modules/webdatabase/sql_result_set_row_list.h"
#include "third_party/blink/renderer/modules/webdatabase/sql_transaction.h"
#include "third_party/blink/renderer/modules/webdatabase/sqlite/sql_value.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/sql_result_set.cc b/chromium/third_party/blink/renderer/modules/webdatabase/sql_result_set.cc
index 7229e5d1616..3bef9f70470 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/sql_result_set.cc
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/sql_result_set.cc
@@ -28,8 +28,7 @@
#include "third_party/blink/renderer/modules/webdatabase/sql_result_set.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
@@ -56,7 +55,8 @@ int64_t SQLResultSet::insertId(ExceptionState& exception_state) const {
return insert_id_;
exception_state.ThrowDOMException(
- kInvalidAccessError, "The query didn't result in any rows being added.");
+ DOMExceptionCode::kInvalidAccessError,
+ "The query didn't result in any rows being added.");
return -1;
}
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/sql_result_set_row_list.cc b/chromium/third_party/blink/renderer/modules/webdatabase/sql_result_set_row_list.cc
index e6d0941048e..d4a001466e5 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/sql_result_set_row_list.cc
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/sql_result_set_row_list.cc
@@ -31,7 +31,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/bindings/modules/v8/to_v8_for_modules.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
namespace blink {
@@ -49,8 +49,9 @@ ScriptValue SQLResultSetRowList::item(ScriptState* script_state,
ExceptionState& exception_state) {
if (index >= length()) {
exception_state.ThrowDOMException(
- kIndexSizeError, ExceptionMessages::IndexExceedsMaximumBound<unsigned>(
- "index", index, length()));
+ DOMExceptionCode::kIndexSizeError,
+ ExceptionMessages::IndexExceedsMaximumBound<unsigned>("index", index,
+ length()));
return ScriptValue();
}
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc b/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc
index 0b800c71578..6c1024fc530 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction.cc
@@ -28,8 +28,6 @@
#include "third_party/blink/renderer/modules/webdatabase/sql_transaction.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/modules/webdatabase/database.h"
#include "third_party/blink/renderer/modules/webdatabase/database_authorizer.h"
@@ -39,6 +37,7 @@
#include "third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.h"
#include "third_party/blink/renderer/modules/webdatabase/sql_transaction_client.h" // FIXME: Should be used in the backend only.
#include "third_party/blink/renderer/modules/webdatabase/storage_log.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -313,13 +312,13 @@ void SQLTransaction::ExecuteSQL(const String& sql_statement,
ExceptionState& exception_state) {
DCHECK(IsMainThread());
if (!execute_sql_allowed_) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"SQL execution is disallowed.");
return;
}
if (!database_->Opened()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"The database has not been opened.");
return;
}
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.cc b/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.cc
index c54c17d3c00..9376297e0cd 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.cc
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.cc
@@ -398,7 +398,6 @@ SQLTransactionBackend::~SQLTransactionBackend() {
}
void SQLTransactionBackend::Trace(blink::Visitor* visitor) {
- visitor->Trace(database_);
visitor->Trace(wrapper_);
}
diff --git a/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.h b/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.h
index 5e6d7d8d7c7..bd98c3509ea 100644
--- a/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.h
+++ b/chromium/third_party/blink/renderer/modules/webdatabase/sql_transaction_backend.h
@@ -121,7 +121,7 @@ class SQLTransactionBackend final
CrossThreadPersistent<SQLTransaction> frontend_;
CrossThreadPersistent<SQLStatementBackend> current_statement_backend_;
- Member<Database> database_;
+ CrossThreadPersistent<Database> database_;
Member<SQLTransactionWrapper> wrapper_;
std::unique_ptr<SQLErrorData> transaction_error_;
diff --git a/chromium/third_party/blink/renderer/modules/webgl/BUILD.gn b/chromium/third_party/blink/renderer/modules/webgl/BUILD.gn
index 57812f54f3a..b4fa673896c 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/webgl/BUILD.gn
@@ -127,6 +127,15 @@ blink_modules_sources("webgl") {
"webgl_vertex_array_object_oes.h",
]
+ if (support_webgl2_compute_context) {
+ sources += [
+ "webgl2_compute_rendering_context.cc",
+ "webgl2_compute_rendering_context.h",
+ "webgl2_compute_rendering_context_base.cc",
+ "webgl2_compute_rendering_context_base.h",
+ ]
+ }
+
# The modules/webgl/ directly is a larger module, and
# the implementation depends on a fair chunk of core/ --
# include the core pch for faster Windows compilation times.
diff --git a/chromium/third_party/blink/renderer/modules/webgl/oes_vertex_array_object.cc b/chromium/third_party/blink/renderer/modules/webgl/oes_vertex_array_object.cc
index 639540f4014..9a14b859003 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/oes_vertex_array_object.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/oes_vertex_array_object.cc
@@ -26,9 +26,9 @@
#include "third_party/blink/renderer/modules/webgl/oes_vertex_array_object.h"
#include "gpu/command_buffer/client/gles2_interface.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
#include "third_party/blink/renderer/modules/webgl/webgl_vertex_array_object_oes.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.cc
new file mode 100644
index 00000000000..0e654818853
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.cc
@@ -0,0 +1,157 @@
+// 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/modules/webgl/webgl2_compute_rendering_context.h"
+
+#include <memory>
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
+#include "third_party/blink/renderer/bindings/modules/v8/offscreen_rendering_context.h"
+#include "third_party/blink/renderer/bindings/modules/v8/rendering_context.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/loader/frame_loader.h"
+#include "third_party/blink/renderer/modules/webgl/ext_color_buffer_float.h"
+#include "third_party/blink/renderer/modules/webgl/ext_disjoint_timer_query_webgl2.h"
+#include "third_party/blink/renderer/modules/webgl/ext_texture_filter_anisotropic.h"
+#include "third_party/blink/renderer/modules/webgl/oes_texture_float_linear.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_compressed_texture_astc.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_compressed_texture_etc.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_compressed_texture_etc1.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_compressed_texture_pvrtc.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_compressed_texture_s3tc.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_compressed_texture_s3tc_srgb.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_context_attribute_helpers.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_context_event.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_debug_renderer_info.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_debug_shaders.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_lose_context.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h"
+
+namespace blink {
+
+// An helper function for the two create() methods. The return value is an
+// indicate of whether the create() should return nullptr or not.
+static bool ShouldCreateWebGL2ComputeContext(
+ WebGraphicsContext3DProvider* context_provider,
+ CanvasRenderingContextHost* host) {
+ if (!context_provider) {
+ host->HostDispatchEvent(WebGLContextEvent::Create(
+ EventTypeNames::webglcontextcreationerror,
+ "Failed to create a WebGL2 Compute context."));
+ return false;
+ }
+
+ gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
+ std::unique_ptr<Extensions3DUtil> extensions_util =
+ Extensions3DUtil::Create(gl);
+ if (!extensions_util)
+ return false;
+ if (extensions_util->SupportsExtension("GL_EXT_debug_marker")) {
+ String context_label(
+ String::Format("WebGL2ComputeRenderingContext-%p", context_provider));
+ gl->PushGroupMarkerEXT(0, context_label.Ascii().data());
+ }
+ return true;
+}
+
+CanvasRenderingContext* WebGL2ComputeRenderingContext::Factory::Create(
+ CanvasRenderingContextHost* host,
+ const CanvasContextCreationAttributesCore& attrs) {
+ bool using_gpu_compositing;
+ std::unique_ptr<WebGraphicsContext3DProvider> context_provider(
+ CreateWebGraphicsContext3DProvider(host, attrs,
+ Platform::kWebGL2ComputeContextType,
+ &using_gpu_compositing));
+ if (!ShouldCreateWebGL2ComputeContext(context_provider.get(), host))
+ return nullptr;
+ WebGL2ComputeRenderingContext* rendering_context =
+ new WebGL2ComputeRenderingContext(host, std::move(context_provider),
+ using_gpu_compositing, attrs);
+
+ if (!rendering_context->GetDrawingBuffer()) {
+ host->HostDispatchEvent(WebGLContextEvent::Create(
+ EventTypeNames::webglcontextcreationerror,
+ "Could not create a WebGL2 Compute context."));
+ return nullptr;
+ }
+
+ rendering_context->InitializeNewContext();
+ rendering_context->RegisterContextExtensions();
+
+ return rendering_context;
+}
+
+void WebGL2ComputeRenderingContext::Factory::OnError(HTMLCanvasElement* canvas,
+ const String& error) {
+ canvas->DispatchEvent(WebGLContextEvent::Create(
+ EventTypeNames::webglcontextcreationerror, error));
+}
+
+WebGL2ComputeRenderingContext::WebGL2ComputeRenderingContext(
+ CanvasRenderingContextHost* host,
+ std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
+ bool using_gpu_compositing,
+ const CanvasContextCreationAttributesCore& requested_attributes)
+ : WebGL2ComputeRenderingContextBase(host,
+ std::move(context_provider),
+ using_gpu_compositing,
+ requested_attributes) {}
+
+void WebGL2ComputeRenderingContext::SetCanvasGetContextResult(
+ RenderingContext& result) {
+ result.SetWebGL2ComputeRenderingContext(this);
+}
+
+void WebGL2ComputeRenderingContext::SetOffscreenCanvasGetContextResult(
+ OffscreenRenderingContext& result) {
+ result.SetWebGL2ComputeRenderingContext(this);
+}
+
+ImageBitmap* WebGL2ComputeRenderingContext::TransferToImageBitmap(
+ ScriptState* script_state) {
+ return TransferToImageBitmapBase(script_state);
+}
+
+void WebGL2ComputeRenderingContext::RegisterContextExtensions() {
+ // Register extensions.
+ RegisterExtension<EXTColorBufferFloat>(ext_color_buffer_float_);
+ RegisterExtension<EXTDisjointTimerQueryWebGL2>(
+ ext_disjoint_timer_query_web_gl2_);
+ RegisterExtension<EXTTextureFilterAnisotropic>(
+ ext_texture_filter_anisotropic_);
+ RegisterExtension<OESTextureFloatLinear>(oes_texture_float_linear_);
+ RegisterExtension<WebGLCompressedTextureASTC>(webgl_compressed_texture_astc_);
+ RegisterExtension<WebGLCompressedTextureETC>(webgl_compressed_texture_etc_);
+ RegisterExtension<WebGLCompressedTextureETC1>(webgl_compressed_texture_etc1_);
+ RegisterExtension<WebGLCompressedTexturePVRTC>(
+ webgl_compressed_texture_pvrtc_);
+ RegisterExtension<WebGLCompressedTextureS3TC>(webgl_compressed_texture_s3tc_);
+ RegisterExtension<WebGLCompressedTextureS3TCsRGB>(
+ webgl_compressed_texture_s3tc_srgb_);
+ RegisterExtension<WebGLDebugRendererInfo>(webgl_debug_renderer_info_);
+ RegisterExtension<WebGLDebugShaders>(webgl_debug_shaders_);
+ RegisterExtension<WebGLLoseContext>(webgl_lose_context_);
+}
+
+void WebGL2ComputeRenderingContext::Trace(blink::Visitor* visitor) {
+ visitor->Trace(ext_color_buffer_float_);
+ visitor->Trace(ext_disjoint_timer_query_web_gl2_);
+ visitor->Trace(ext_texture_filter_anisotropic_);
+ visitor->Trace(oes_texture_float_linear_);
+ visitor->Trace(webgl_compressed_texture_astc_);
+ visitor->Trace(webgl_compressed_texture_etc_);
+ visitor->Trace(webgl_compressed_texture_etc1_);
+ visitor->Trace(webgl_compressed_texture_pvrtc_);
+ visitor->Trace(webgl_compressed_texture_s3tc_);
+ visitor->Trace(webgl_compressed_texture_s3tc_srgb_);
+ visitor->Trace(webgl_debug_renderer_info_);
+ visitor->Trace(webgl_debug_shaders_);
+ visitor->Trace(webgl_lose_context_);
+ WebGL2ComputeRenderingContextBase::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.h b/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.h
new file mode 100644
index 00000000000..2b83035147e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.h
@@ -0,0 +1,88 @@
+// 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_MODULES_WEBGL_WEBGL2_COMPUTE_RENDERING_CONTEXT_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL2_COMPUTE_RENDERING_CONTEXT_H_
+
+#include <memory>
+#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context_factory.h"
+#include "third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h"
+
+namespace blink {
+
+class CanvasContextCreationAttributesCore;
+class EXTColorBufferFloat;
+class EXTTextureFilterAnisotropic;
+class OESTextureFloatLinear;
+class WebGLDebugRendererInfo;
+class WebGLLoseContext;
+
+class WebGL2ComputeRenderingContext : public WebGL2ComputeRenderingContextBase {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ class Factory : public CanvasRenderingContextFactory {
+ WTF_MAKE_NONCOPYABLE(Factory);
+
+ public:
+ Factory() = default;
+ ~Factory() override = default;
+
+ CanvasRenderingContext* Create(
+ CanvasRenderingContextHost*,
+ const CanvasContextCreationAttributesCore&) override;
+ CanvasRenderingContext::ContextType GetContextType() const override {
+ return CanvasRenderingContext::kContextWebgl2Compute;
+ }
+ void OnError(HTMLCanvasElement*, const String& error) override;
+ };
+
+ CanvasRenderingContext::ContextType GetContextType() const override {
+ return CanvasRenderingContext::kContextWebgl2Compute;
+ }
+ ImageBitmap* TransferToImageBitmap(ScriptState*) final;
+ String ContextName() const override {
+ return "WebGL2ComputeRenderingContext";
+ }
+ void RegisterContextExtensions() override;
+ void SetCanvasGetContextResult(RenderingContext&) final;
+ void SetOffscreenCanvasGetContextResult(OffscreenRenderingContext&) final;
+
+ void Trace(blink::Visitor*) override;
+
+ protected:
+ WebGL2ComputeRenderingContext(
+ CanvasRenderingContextHost*,
+ std::unique_ptr<WebGraphicsContext3DProvider>,
+ bool using_gpu_compositing,
+ const CanvasContextCreationAttributesCore& requested_attributes);
+
+ Member<EXTColorBufferFloat> ext_color_buffer_float_;
+ Member<EXTDisjointTimerQueryWebGL2> ext_disjoint_timer_query_web_gl2_;
+ Member<EXTTextureFilterAnisotropic> ext_texture_filter_anisotropic_;
+ Member<OESTextureFloatLinear> oes_texture_float_linear_;
+ Member<WebGLCompressedTextureASTC> webgl_compressed_texture_astc_;
+ Member<WebGLCompressedTextureETC> webgl_compressed_texture_etc_;
+ Member<WebGLCompressedTextureETC1> webgl_compressed_texture_etc1_;
+ Member<WebGLCompressedTexturePVRTC> webgl_compressed_texture_pvrtc_;
+ Member<WebGLCompressedTextureS3TC> webgl_compressed_texture_s3tc_;
+ Member<WebGLCompressedTextureS3TCsRGB> webgl_compressed_texture_s3tc_srgb_;
+ Member<WebGLDebugRendererInfo> webgl_debug_renderer_info_;
+ Member<WebGLDebugShaders> webgl_debug_shaders_;
+ Member<WebGLLoseContext> webgl_lose_context_;
+};
+
+DEFINE_TYPE_CASTS(WebGL2ComputeRenderingContext,
+ CanvasRenderingContext,
+ context,
+ context->Is3d() &&
+ WebGLRenderingContextBase::GetWebGLVersion(context) ==
+ Platform::kWebGL2ComputeContextType,
+ context.Is3d() &&
+ WebGLRenderingContextBase::GetWebGLVersion(&context) ==
+ Platform::kWebGL2ComputeContextType);
+
+} // namespace blink
+
+#endif
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.idl
new file mode 100644
index 00000000000..9a434041c65
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.idl
@@ -0,0 +1,11 @@
+// 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.
+
+[
+ DoNotCheckConstants,
+ Exposed(Worker OffscreenCanvas, Window StableBlinkFeatures)
+] interface WebGL2ComputeRenderingContext { };
+WebGL2ComputeRenderingContext implements WebGLRenderingContextBase;
+WebGL2ComputeRenderingContext implements WebGL2RenderingContextBase;
+WebGL2ComputeRenderingContext implements WebGL2ComputeRenderingContextBase;
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc
new file mode 100644
index 00000000000..ffb32f12422
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc
@@ -0,0 +1,63 @@
+// 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/modules/webgl/webgl2_compute_rendering_context_base.h"
+
+#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
+
+namespace blink {
+
+WebGL2ComputeRenderingContextBase::WebGL2ComputeRenderingContextBase(
+ CanvasRenderingContextHost* host,
+ std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
+ bool using_gpu_compositing,
+ const CanvasContextCreationAttributesCore& requested_attributes)
+ : WebGL2RenderingContextBase(host,
+ std::move(context_provider),
+ using_gpu_compositing,
+ requested_attributes,
+ Platform::kWebGL2ComputeContextType) {}
+
+void WebGL2ComputeRenderingContextBase::DestroyContext() {
+ WebGL2RenderingContextBase::DestroyContext();
+}
+
+void WebGL2ComputeRenderingContextBase::InitializeNewContext() {
+ DCHECK(!isContextLost());
+
+ WebGL2RenderingContextBase::InitializeNewContext();
+}
+
+void WebGL2ComputeRenderingContextBase::dispatchCompute(GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ) {
+ SynthesizeGLError(GL_INVALID_OPERATION, "dispatchCompute", "UNIMPLEMENTED");
+ return;
+}
+
+void WebGL2ComputeRenderingContextBase::bindImageTexture(GLuint unit,
+ WebGLTexture* texture,
+ GLint level,
+ GLboolean layered,
+ GLint layer,
+ GLenum access,
+ GLenum format) {
+ SynthesizeGLError(GL_INVALID_OPERATION, "bindImageTexture", "UNIMPLEMENTED");
+}
+
+void WebGL2ComputeRenderingContextBase::memoryBarrier(GLbitfield barriers) {
+ SynthesizeGLError(GL_INVALID_OPERATION, "memoryBarrier", "UNIMPLEMENTED");
+}
+
+void WebGL2ComputeRenderingContextBase::memoryBarrierByRegion(
+ GLbitfield barriers) {
+ SynthesizeGLError(GL_INVALID_OPERATION, "memoryBarrierByRegion",
+ "UNIMPLEMENTED");
+}
+
+void WebGL2ComputeRenderingContextBase::Trace(blink::Visitor* visitor) {
+ WebGL2RenderingContextBase::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h b/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h
new file mode 100644
index 00000000000..3339f9cb79b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h
@@ -0,0 +1,61 @@
+// 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_MODULES_WEBGL_WEBGL2_COMPUTE_RENDERING_CONTEXT_BASE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL2_COMPUTE_RENDERING_CONTEXT_BASE_H_
+
+#include "third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h"
+#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
+#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
+
+namespace blink {
+
+class WebGLTexture;
+
+class WebGL2ComputeRenderingContextBase : public WebGL2RenderingContextBase {
+ public:
+ void DestroyContext() override;
+
+ /* Launch one or more compute work groups */
+ void dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ);
+
+ /* Bind a level of a texture to an image unit */
+ void bindImageTexture(GLuint unit,
+ WebGLTexture* texture,
+ GLint level,
+ GLboolean layered,
+ GLint layer,
+ GLenum access,
+ GLenum format);
+
+ /* Memory access synchronization */
+ void memoryBarrier(GLbitfield barriers);
+ void memoryBarrierByRegion(GLbitfield barriers);
+
+ /* WebGLRenderingContextBase overrides */
+ void InitializeNewContext() override;
+
+ void Trace(blink::Visitor*) override;
+
+ protected:
+ WebGL2ComputeRenderingContextBase(
+ CanvasRenderingContextHost*,
+ std::unique_ptr<WebGraphicsContext3DProvider>,
+ bool using_gpu_compositing,
+ const CanvasContextCreationAttributesCore& requested_attributes);
+};
+
+DEFINE_TYPE_CASTS(WebGL2ComputeRenderingContextBase,
+ CanvasRenderingContext,
+ context,
+ context->Is3d() &&
+ WebGLRenderingContextBase::GetWebGLVersion(context) ==
+ Platform::kWebGL2ComputeContextType,
+ context.Is3d() &&
+ WebGLRenderingContextBase::GetWebGLVersion(&context) ==
+ Platform::kWebGL2ComputeContextType);
+
+} // namespace blink
+
+#endif
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl
new file mode 100644
index 00000000000..4ec4777fd01
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.idl
@@ -0,0 +1,65 @@
+// 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.
+
+[
+ NoInterfaceObject
+] interface WebGL2ComputeRenderingContextBase {
+ // TODO(jiajia.qin@intel.com): add more enums and apis
+ const GLenum COMPUTE_SHADER = 0x91B9;
+ const GLenum BUFFER_VARIABLE = 0x92E5;
+ const GLenum SHADER_STORAGE_BLOCK = 0x92E6;
+ const GLenum VERTEX_ATTRIB_ARRAY_BARRIER_BIT = 0x00000001;
+ const GLenum ELEMENT_ARRAY_BARRIER_BIT = 0x00000002;
+ const GLenum UNIFORM_BARRIER_BIT = 0x00000004;
+ const GLenum TEXTURE_FETCH_BARRIER_BIT = 0x00000008;
+ const GLenum SHADER_IMAGE_ACCESS_BARRIER_BIT = 0x00000020;
+ const GLenum COMMAND_BARRIER_BIT = 0x00000040;
+ const GLenum PIXEL_BUFFER_BARRIER_BIT = 0x00000080;
+ const GLenum TEXTURE_UPDATE_BARRIER_BIT = 0x00000100;
+ const GLenum BUFFER_UPDATE_BARRIER_BIT = 0x00000200;
+ const GLenum FRAMEBUFFER_BARRIER_BIT = 0x00000400;
+ const GLenum TRANSFORM_FEEDBACK_BARRIER_BIT = 0x00000800;
+ const GLenum ATOMIC_COUNTER_BARRIER_BIT = 0x00001000;
+ const GLenum SHADER_STORAGE_BARRIER_BIT = 0x00002000;
+ const GLenum FALSE = 0;
+ const GLenum TRUE = 1;
+ const GLenum READ_ONLY = 0x88B8;
+ const GLenum WRITE_ONLY = 0x88B9;
+ const GLenum READ_WRITE = 0x88BA;
+ const GLenum SHADER_STORAGE_BUFFER = 0x90D2;
+ const GLenum SHADER_STORAGE_BUFFER_BINDING = 0x90D3;
+ const GLenum SHADER_STORAGE_BUFFER_START = 0x90D4;
+ const GLenum SHADER_STORAGE_BUFFER_SIZE = 0x90D5;
+ const GLenum MAX_VERTEX_SHADER_STORAGE_BLOCKS = 0x90D6;
+ const GLenum MAX_FRAGMENT_SHADER_STORAGE_BLOCKS = 0x90DA;
+ const GLenum MAX_COMPUTE_SHADER_STORAGE_BLOCKS = 0x90DB;
+ const GLenum MAX_COMBINED_SHADER_STORAGE_BLOCKS = 0x90DC;
+ const GLenum MAX_SHADER_STORAGE_BUFFER_BINDINGS = 0x90DD;
+ const GLenum MAX_SHADER_STORAGE_BLOCK_SIZE = 0x90DE;
+ const GLenum SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT = 0x90DF;
+ const GLenum MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS = 0x8264;
+ const GLenum MAX_COMPUTE_ATOMIC_COUNTERS = 0x8265;
+ const GLenum ATOMIC_COUNTER_BUFFER_INDEX = 0x9301;
+ const GLenum ATOMIC_COUNTER_BUFFER = 0x92C0;
+ const GLenum ATOMIC_COUNTER_BUFFER_BINDING = 0x92C1;
+ const GLenum ATOMIC_COUNTER_BUFFER_START = 0x92C2;
+ const GLenum ATOMIC_COUNTER_BUFFER_SIZE = 0x92C3;
+ const GLenum MAX_VERTEX_ATOMIC_COUNTER_BUFFERS = 0x92CC;
+ const GLenum MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS = 0x92D0;
+ const GLenum MAX_COMBINED_ATOMIC_COUNTER_BUFFERS = 0x92D1;
+ const GLenum MAX_VERTEX_ATOMIC_COUNTERS = 0x92D2;
+ const GLenum MAX_FRAGMENT_ATOMIC_COUNTERS = 0x92D6;
+ const GLenum MAX_COMBINED_ATOMIC_COUNTERS = 0x92D7;
+ const GLenum MAX_ATOMIC_COUNTER_BUFFER_SIZE = 0x92D8;
+ const GLenum MAX_ATOMIC_COUNTER_BUFFER_BINDINGS = 0x92DC;
+ const GLenum ACTIVE_ATOMIC_COUNTER_BUFFERS = 0x92D9;
+ const GLenum UNSIGNED_INT_ATOMIC_COUNTER = 0x92DB;
+
+ void dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ);
+ void bindImageTexture(GLuint unit, WebGLTexture ? texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+ void memoryBarrier(GLbitfield barriers);
+ void memoryBarrierByRegion(GLbitfield barriers);
+};
+WebGL2ComputeRenderingContextBase implements WebGLRenderingContextBase;
+WebGL2ComputeRenderingContextBase implements WebGL2RenderingContextBase;
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.cc
index f1c6c0fbf76..274e3c8121f 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.cc
@@ -62,8 +62,8 @@ CanvasRenderingContext* WebGL2RenderingContext::Factory::Create(
const CanvasContextCreationAttributesCore& attrs) {
bool using_gpu_compositing;
std::unique_ptr<WebGraphicsContext3DProvider> context_provider(
- CreateWebGraphicsContext3DProvider(host, attrs, 2,
- &using_gpu_compositing));
+ CreateWebGraphicsContext3DProvider(
+ host, attrs, Platform::kWebGL2ContextType, &using_gpu_compositing));
if (!ShouldCreateContext(context_provider.get(), host))
return nullptr;
WebGL2RenderingContext* rendering_context = new WebGL2RenderingContext(
@@ -96,7 +96,8 @@ WebGL2RenderingContext::WebGL2RenderingContext(
: WebGL2RenderingContextBase(host,
std::move(context_provider),
using_gpu_compositing,
- requested_attributes) {}
+ requested_attributes,
+ Platform::kWebGL2ContextType) {}
void WebGL2RenderingContext::SetCanvasGetContextResult(
RenderingContext& result) {
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h b/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h
index c39a3e1c0d6..db77f15bb5b 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h
@@ -75,10 +75,11 @@ DEFINE_TYPE_CASTS(WebGL2RenderingContext,
CanvasRenderingContext,
context,
context->Is3d() &&
- WebGLRenderingContextBase::GetWebGLVersion(context) == 2,
+ WebGLRenderingContextBase::GetWebGLVersion(context) ==
+ Platform::kWebGL2ContextType,
context.Is3d() &&
WebGLRenderingContextBase::GetWebGLVersion(&context) ==
- 2);
+ Platform::kWebGL2ContextType);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc
index 89fa58d061b..2f4376ad2be 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc
@@ -5,6 +5,8 @@
#include "third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h"
#include <memory>
+#include "base/numerics/checked_math.h"
+#include "base/numerics/safe_conversions.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
#include "third_party/blink/renderer/bindings/modules/v8/webgl_any.h"
@@ -26,7 +28,6 @@
#include "third_party/blink/renderer/modules/webgl/webgl_transform_feedback.h"
#include "third_party/blink/renderer/modules/webgl/webgl_uniform_location.h"
#include "third_party/blink/renderer/modules/webgl/webgl_vertex_array_object.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
using WTF::String;
@@ -59,7 +60,7 @@ bool ValidateSubSourceAndGetData(DOMArrayBufferView* view,
// type size is at most 8, so no overflow.
byte_offset = sub_offset * type_size;
}
- CheckedNumeric<long long> total = byte_offset;
+ base::CheckedNumeric<long long> total = byte_offset;
total += byte_length;
if (!total.IsValid() || total.ValueOrDie() > view->byteLength()) {
return false;
@@ -138,12 +139,13 @@ WebGL2RenderingContextBase::WebGL2RenderingContextBase(
CanvasRenderingContextHost* host,
std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
bool using_gpu_compositing,
- const CanvasContextCreationAttributesCore& requested_attributes)
+ const CanvasContextCreationAttributesCore& requested_attributes,
+ Platform::ContextType context_type)
: WebGLRenderingContextBase(host,
std::move(context_provider),
using_gpu_compositing,
requested_attributes,
- 2) {
+ context_type) {
supported_internal_formats_storage_.insert(
kSupportedInternalFormatsStorage,
kSupportedInternalFormatsStorage +
@@ -421,8 +423,8 @@ void WebGL2RenderingContextBase::framebufferTextureLayer(GLenum target,
"framebufferTextureLayer", target, attachment))
return;
if (texture && !texture->Validate(ContextGroup(), this)) {
- SynthesizeGLError(GL_INVALID_VALUE, "framebufferTextureLayer",
- "no texture or texture not from this context");
+ SynthesizeGLError(GL_INVALID_OPERATION, "framebufferTextureLayer",
+ "texture does not belong to this context");
return;
}
GLenum textarget = texture ? texture->GetTarget() : 0;
@@ -3412,9 +3414,8 @@ void WebGL2RenderingContextBase::drawArraysInstanced(GLenum mode,
ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
drawing_buffer_.get());
- ClearIfComposited();
+ OnBeforeDrawCall();
ContextGL()->DrawArraysInstancedANGLE(mode, first, count, instance_count);
- MarkContextChanged(kCanvasChanged);
}
void WebGL2RenderingContextBase::drawElementsInstanced(GLenum mode,
@@ -3433,11 +3434,10 @@ void WebGL2RenderingContextBase::drawElementsInstanced(GLenum mode,
ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
drawing_buffer_.get());
- ClearIfComposited();
+ OnBeforeDrawCall();
ContextGL()->DrawElementsInstancedANGLE(
mode, count, type, reinterpret_cast<void*>(static_cast<intptr_t>(offset)),
instance_count);
- MarkContextChanged(kCanvasChanged);
}
void WebGL2RenderingContextBase::drawRangeElements(GLenum mode,
@@ -3457,11 +3457,10 @@ void WebGL2RenderingContextBase::drawRangeElements(GLenum mode,
ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
drawing_buffer_.get());
- ClearIfComposited();
+ OnBeforeDrawCall();
ContextGL()->DrawRangeElements(
mode, start, end, count, type,
reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
- MarkContextChanged(kCanvasChanged);
}
void WebGL2RenderingContextBase::drawBuffers(const Vector<GLenum>& buffers) {
@@ -3524,7 +3523,7 @@ bool WebGL2RenderingContextBase::ValidateClearBuffer(const char* function_name,
GLenum buffer,
GLsizei size,
GLuint src_offset) {
- CheckedNumeric<GLsizei> checked_size(size);
+ base::CheckedNumeric<GLsizei> checked_size(size);
checked_size -= src_offset;
if (!checked_size.IsValid()) {
SynthesizeGLError(GL_INVALID_VALUE, function_name,
@@ -4036,9 +4035,6 @@ GLboolean WebGL2RenderingContextBase::isSampler(WebGLSampler* sampler) {
void WebGL2RenderingContextBase::bindSampler(GLuint unit,
WebGLSampler* sampler) {
- if (isContextLost())
- return;
-
bool deleted;
if (!CheckObjectToBeBound("bindSampler", sampler, deleted))
return;
@@ -4067,7 +4063,12 @@ void WebGL2RenderingContextBase::SamplerParameter(WebGLSampler* sampler,
if (isContextLost() || !ValidateWebGLObject("samplerParameter", sampler))
return;
- GLint param = is_float ? static_cast<GLint>(paramf) : parami;
+ GLint param;
+ if (is_float) {
+ param = base::saturated_cast<GLint>(paramf);
+ } else {
+ param = parami;
+ }
switch (pname) {
case GL_TEXTURE_MAX_LOD:
case GL_TEXTURE_MIN_LOD:
@@ -4202,6 +4203,15 @@ WebGLSync* WebGL2RenderingContextBase::fenceSync(GLenum condition,
if (isContextLost())
return nullptr;
+ if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) {
+ SynthesizeGLError(GL_INVALID_ENUM, "fenceSync",
+ "condition must be SYNC_GPU_COMMANDS_COMPLETE");
+ return nullptr;
+ }
+ if (flags != 0) {
+ SynthesizeGLError(GL_INVALID_VALUE, "fenceSync", "flags must be zero");
+ return nullptr;
+ }
return WebGLFenceSync::Create(this, condition, flags);
}
@@ -4209,7 +4219,7 @@ GLboolean WebGL2RenderingContextBase::isSync(WebGLSync* sync) {
if (isContextLost() || !sync)
return 0;
- return ContextGL()->IsSync(sync->Object());
+ return sync->Object() != 0;
}
void WebGL2RenderingContextBase::deleteSync(WebGLSync* sync) {
@@ -4307,7 +4317,7 @@ void WebGL2RenderingContextBase::deleteTransformFeedback(
GLboolean WebGL2RenderingContextBase::isTransformFeedback(
WebGLTransformFeedback* feedback) {
- if (isContextLost() || !feedback)
+ if (isContextLost() || !feedback || !feedback->Validate(ContextGroup(), this))
return 0;
if (!feedback->HasEverBeenBound())
@@ -4484,11 +4494,12 @@ WebGLActiveInfo* WebGL2RenderingContextBase::getTransformFeedbackVarying(
max_name_length, &length, &size,
&type, name.get());
- if (length == 0 || size == 0 || type == 0) {
+ if (length <= 0 || size == 0 || type == 0) {
return nullptr;
}
- return WebGLActiveInfo::Create(String(name.get(), length), type, size);
+ return WebGLActiveInfo::Create(
+ String(name.get(), static_cast<uint32_t>(length)), type, size);
}
void WebGL2RenderingContextBase::pauseTransformFeedback() {
@@ -4547,6 +4558,22 @@ bool WebGL2RenderingContextBase::ValidateTransformFeedbackPrimitiveMode(
}
}
+void WebGL2RenderingContextBase::OnBeforeDrawCall() {
+ if (transform_feedback_binding_->active() &&
+ !transform_feedback_binding_->paused()) {
+ for (WebGLBuffer* buffer :
+ transform_feedback_binding_
+ ->bound_indexed_transform_feedback_buffers()) {
+ if (buffer) {
+ ContextGL()->InvalidateReadbackBufferShadowDataCHROMIUM(
+ buffer->Object());
+ }
+ }
+ }
+
+ WebGLRenderingContextBase::OnBeforeDrawCall();
+}
+
void WebGL2RenderingContextBase::bindBufferBase(GLenum target,
GLuint index,
WebGLBuffer* buffer) {
@@ -4860,7 +4887,9 @@ String WebGL2RenderingContextBase::getActiveUniformBlockName(
uniform_block_index, max_name_length,
&length, name.get());
- return String(name.get(), length);
+ if (length <= 0)
+ return String();
+ return String(name.get(), static_cast<uint32_t>(length));
}
void WebGL2RenderingContextBase::uniformBlockBinding(
@@ -4888,7 +4917,8 @@ WebGLVertexArrayObject* WebGL2RenderingContextBase::createVertexArray() {
void WebGL2RenderingContextBase::deleteVertexArray(
WebGLVertexArrayObject* vertex_array) {
- if (isContextLost() || !vertex_array)
+ if (isContextLost() || !vertex_array ||
+ !ValidateWebGLObject("deleteVertexArray", vertex_array))
return;
if (!vertex_array->IsDefaultObject() &&
@@ -4900,7 +4930,8 @@ void WebGL2RenderingContextBase::deleteVertexArray(
GLboolean WebGL2RenderingContextBase::isVertexArray(
WebGLVertexArrayObject* vertex_array) {
- if (isContextLost() || !vertex_array)
+ if (isContextLost() || !vertex_array ||
+ !vertex_array->Validate(ContextGroup(), this))
return 0;
if (!vertex_array->HasEverBeenBound())
@@ -4911,13 +4942,12 @@ GLboolean WebGL2RenderingContextBase::isVertexArray(
void WebGL2RenderingContextBase::bindVertexArray(
WebGLVertexArrayObject* vertex_array) {
- if (isContextLost())
+ bool deleted;
+ if (!CheckObjectToBeBound("bindVertexArray", vertex_array, deleted))
return;
-
- if (vertex_array &&
- (vertex_array->IsDeleted() || !vertex_array->Validate(nullptr, this))) {
+ if (deleted) {
SynthesizeGLError(GL_INVALID_OPERATION, "bindVertexArray",
- "invalid vertexArray");
+ "attempt to bind a deleted vertex array");
return;
}
@@ -5680,28 +5710,6 @@ void WebGL2RenderingContextBase::Trace(blink::Visitor* visitor) {
WebGLRenderingContextBase::Trace(visitor);
}
-void WebGL2RenderingContextBase::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(read_framebuffer_binding_);
- visitor->TraceWrappers(transform_feedback_binding_);
- visitor->TraceWrappers(bound_copy_read_buffer_);
- visitor->TraceWrappers(bound_copy_write_buffer_);
- visitor->TraceWrappers(bound_pixel_pack_buffer_);
- visitor->TraceWrappers(bound_pixel_unpack_buffer_);
- visitor->TraceWrappers(bound_transform_feedback_buffer_);
- visitor->TraceWrappers(bound_uniform_buffer_);
- for (auto& buf : bound_indexed_uniform_buffers_) {
- visitor->TraceWrappers(buf);
- }
- visitor->TraceWrappers(current_boolean_occlusion_query_);
- visitor->TraceWrappers(current_transform_feedback_primitives_written_query_);
- visitor->TraceWrappers(current_elapsed_query_);
- for (auto& unit : sampler_units_) {
- visitor->TraceWrappers(unit);
- }
- WebGLRenderingContextBase::TraceWrappers(visitor);
-}
-
WebGLTexture* WebGL2RenderingContextBase::ValidateTexture3DBinding(
const char* function_name,
GLenum target) {
@@ -5876,7 +5884,7 @@ const char* WebGL2RenderingContextBase::ValidateGetBufferSubDataBounds(
WebGLBuffer* source_buffer,
GLintptr source_byte_offset,
long long destination_byte_length) {
- CheckedNumeric<long long> src_end = source_byte_offset;
+ base::CheckedNumeric<long long> src_end = source_byte_offset;
src_end += destination_byte_length;
if (!src_end.IsValid() || src_end.ValueOrDie() > source_buffer->GetSize()) {
SynthesizeGLError(GL_INVALID_VALUE, function_name,
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h b/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h
index 010726cc7a1..7ef3f4cf82f 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h
@@ -903,6 +903,8 @@ class WebGL2RenderingContextBase : public WebGLRenderingContextBase {
bool ValidateTransformFeedbackPrimitiveMode(const char* function_name,
GLenum primitive_mode);
+ void OnBeforeDrawCall() override;
+
/* Uniform Buffer Objects and Transform Feedback Buffers */
void bindBufferBase(GLenum, GLuint, WebGLBuffer*);
void bindBufferRange(GLenum, GLuint, WebGLBuffer*, long long, long long);
@@ -970,7 +972,6 @@ class WebGL2RenderingContextBase : public WebGLRenderingContextBase {
GLint GetMaxTransformFeedbackSeparateAttribs() const;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
protected:
friend class V8WebGL2RenderingContext;
@@ -980,7 +981,8 @@ class WebGL2RenderingContextBase : public WebGLRenderingContextBase {
CanvasRenderingContextHost*,
std::unique_ptr<WebGraphicsContext3DProvider>,
bool using_gpu_compositing,
- const CanvasContextCreationAttributesCore& requested_attributes);
+ const CanvasContextCreationAttributesCore& requested_attributes,
+ Platform::ContextType context_type);
// DrawingBuffer::Client implementation.
void DrawingBufferClientRestorePixelUnpackBufferBinding() override;
@@ -1147,10 +1149,11 @@ DEFINE_TYPE_CASTS(WebGL2RenderingContextBase,
CanvasRenderingContext,
context,
context->Is3d() &&
- WebGLRenderingContextBase::GetWebGLVersion(context) >= 2,
+ WebGLRenderingContextBase::GetWebGLVersion(context) ==
+ Platform::kWebGL2ContextType,
context.Is3d() &&
- WebGLRenderingContextBase::GetWebGLVersion(&context) >=
- 2);
+ WebGLRenderingContextBase::GetWebGLVersion(&context) ==
+ Platform::kWebGL2ContextType);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_active_info.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl_active_info.idl
index 6e9eda95683..4a144fc31f8 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_active_info.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_active_info.idl
@@ -25,7 +25,9 @@
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.11
-interface WebGLActiveInfo {
+[
+ Exposed(Worker OffscreenCanvas, Window StableBlinkFeatures)
+] interface WebGLActiveInfo {
readonly attribute long size;
readonly attribute unsigned long type;
readonly attribute DOMString name;
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_buffer.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl_buffer.idl
index f661a048402..8d9091a612e 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_buffer.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_buffer.idl
@@ -25,5 +25,7 @@
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.4
-interface WebGLBuffer {
+[
+ Exposed(Worker OffscreenCanvas, Window StableBlinkFeatures)
+] interface WebGLBuffer {
};
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_context_attribute_helpers.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_context_attribute_helpers.cc
index 7274af57b8e..3846b2a179d 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_context_attribute_helpers.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_context_attribute_helpers.cc
@@ -27,13 +27,12 @@ WebGLContextAttributes ToWebGLContextAttributes(
Platform::ContextAttributes ToPlatformContextAttributes(
const CanvasContextCreationAttributesCore& attrs,
- unsigned web_gl_version,
+ Platform::ContextType context_type,
bool support_own_offscreen_surface) {
Platform::ContextAttributes result;
result.fail_if_major_performance_caveat =
attrs.fail_if_major_performance_caveat;
- result.context_type = web_gl_version == 2 ? Platform::kWebGL2ContextType
- : Platform::kWebGL1ContextType;
+ result.context_type = context_type;
if (support_own_offscreen_surface) {
// Only ask for alpha/depth/stencil/antialias if we may be using the default
// framebuffer. They are not needed for standard offscreen rendering.
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_context_attribute_helpers.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_context_attribute_helpers.h
index 3791d41b466..d1cbf484c4c 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_context_attribute_helpers.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_context_attribute_helpers.h
@@ -18,7 +18,7 @@ WebGLContextAttributes ToWebGLContextAttributes(
// Platform API.
Platform::ContextAttributes ToPlatformContextAttributes(
const CanvasContextCreationAttributesCore&,
- unsigned web_gl_version,
+ Platform::ContextType context_type,
bool support_own_offscreen_surface);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_context_group.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_context_group.cc
index 8db5724aecc..079d47232ab 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_context_group.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_context_group.cc
@@ -50,10 +50,4 @@ uint32_t WebGLContextGroup::NumberOfContextLosses() const {
return number_of_context_losses_;
}
-void WebGLContextGroup::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- for (auto context : contexts_) {
- visitor->TraceWrappers(context);
- }
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_context_group.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_context_group.h
index fb2ce660454..f92bd52ab4c 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_context_group.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_context_group.h
@@ -28,14 +28,14 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
namespace blink {
class WebGLContextGroup final : public GarbageCollected<WebGLContextGroup>,
- public TraceWrapperBase {
+ public NameClient {
WTF_MAKE_NONCOPYABLE(WebGLContextGroup);
public:
@@ -62,7 +62,6 @@ class WebGLContextGroup final : public GarbageCollected<WebGLContextGroup>,
uint32_t NumberOfContextLosses() const;
void Trace(blink::Visitor* visitor) { visitor->Trace(contexts_); }
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "WebGLContextGroup";
}
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_context_object.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_context_object.cc
index 33e5e4f20b7..fd0a1de2bfe 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_context_object.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_context_object.cc
@@ -55,9 +55,4 @@ void WebGLContextObject::Trace(blink::Visitor* visitor) {
WebGLObject::Trace(visitor);
}
-void WebGLContextObject::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(context_);
- WebGLObject::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_context_object.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_context_object.h
index c5255945a57..65575a26a3b 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_context_object.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_context_object.h
@@ -44,8 +44,6 @@ class WebGLContextObject : public WebGLObject {
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
protected:
explicit WebGLContextObject(WebGLRenderingContextBase*);
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_debug_shaders.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_debug_shaders.cc
index a4dde63e3ff..115a1af2aea 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_debug_shaders.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_debug_shaders.cc
@@ -25,10 +25,10 @@
#include "third_party/blink/renderer/modules/webgl/webgl_debug_shaders.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/modules/webgl/gl_string_query.h"
#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
#include "third_party/blink/renderer/modules/webgl/webgl_shader.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_fence_sync.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_fence_sync.cc
index 9ec35558a87..0e8efc0a4f8 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_fence_sync.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_fence_sync.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/webgl/webgl_fence_sync.h"
+#include <GLES2/gl2extchromium.h>
#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h"
@@ -12,14 +13,24 @@ namespace blink {
WebGLSync* WebGLFenceSync::Create(WebGL2RenderingContextBase* ctx,
GLenum condition,
GLbitfield flags) {
+ DCHECK(condition == GL_SYNC_GPU_COMMANDS_COMPLETE);
+ DCHECK(flags == 0);
return new WebGLFenceSync(ctx, condition, flags);
}
WebGLFenceSync::WebGLFenceSync(WebGL2RenderingContextBase* ctx,
GLenum condition,
GLbitfield flags)
- : WebGLSync(ctx,
- ctx->ContextGL()->FenceSync(condition, flags),
- GL_SYNC_FENCE) {}
+ : WebGLSync(ctx, insertQuery(ctx), GL_SYNC_FENCE) {}
+
+GLuint WebGLFenceSync::insertQuery(WebGL2RenderingContextBase* ctx) {
+ auto* gl = ctx->ContextGL();
+ GLuint query = 0;
+ gl->GenQueriesEXT(1, &query);
+ gl->BeginQueryEXT(GL_READBACK_SHADOW_COPIES_UPDATED_CHROMIUM, query);
+ // This query is used like a fence. There doesn't need to be anything inside.
+ gl->EndQueryEXT(GL_READBACK_SHADOW_COPIES_UPDATED_CHROMIUM);
+ return query;
+}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_fence_sync.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_fence_sync.h
index 0d1c69cd7fd..cb971d579d2 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_fence_sync.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_fence_sync.h
@@ -21,6 +21,9 @@ class WebGLFenceSync : public WebGLSync {
WebGLFenceSync(WebGL2RenderingContextBase*,
GLenum condition,
GLbitfield flags);
+
+ private:
+ GLuint insertQuery(WebGL2RenderingContextBase*);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_framebuffer.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_framebuffer.cc
index 6afd427be4b..1d9b966ed7b 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_framebuffer.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_framebuffer.cc
@@ -40,9 +40,6 @@ class WebGLRenderbufferAttachment final
static WebGLFramebuffer::WebGLAttachment* Create(WebGLRenderbuffer*);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- visitor->TraceWrappers(renderbuffer_);
- }
const char* NameInHeapSnapshot() const override { return "WebGLAttachment"; }
private:
@@ -114,9 +111,6 @@ class WebGLTextureAttachment final : public WebGLFramebuffer::WebGLAttachment {
GLint layer);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- visitor->TraceWrappers(texture_);
- }
const char* NameInHeapSnapshot() const override {
return "WebGLTextureAttachment";
}
@@ -562,11 +556,4 @@ void WebGLFramebuffer::Trace(blink::Visitor* visitor) {
WebGLContextObject::Trace(visitor);
}
-void WebGLFramebuffer::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- for (const auto& attachment : attachments_) {
- visitor->TraceWrappers(attachment.value);
- }
- WebGLContextObject::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_framebuffer.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_framebuffer.h
index 080f469797a..ee755029e3a 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_framebuffer.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_framebuffer.h
@@ -28,7 +28,7 @@
#include "third_party/blink/renderer/modules/webgl/webgl_context_object.h"
#include "third_party/blink/renderer/modules/webgl/webgl_shared_object.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable_visitor.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
namespace gpu {
namespace gles2 {
@@ -46,7 +46,7 @@ class WebGLFramebuffer final : public WebGLContextObject {
public:
class WebGLAttachment : public GarbageCollected<WebGLAttachment>,
- public TraceWrapperBase {
+ public NameClient {
public:
virtual WebGLSharedObject* Object() const = 0;
virtual bool IsSharedObject(WebGLSharedObject*) const = 0;
@@ -117,7 +117,6 @@ class WebGLFramebuffer final : public WebGLContextObject {
GLenum GetReadBuffer() const { return read_buffer_; }
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override { return "WebGLFramebuffer"; }
protected:
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_framebuffer.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl_framebuffer.idl
index f4251bfe920..59f7d683df4 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_framebuffer.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_framebuffer.idl
@@ -25,5 +25,7 @@
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.5
-interface WebGLFramebuffer {
+[
+ Exposed(Worker OffscreenCanvas, Window StableBlinkFeatures)
+] interface WebGLFramebuffer {
};
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_program.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_program.cc
index 82e6ef4594e..d3d659d6ddd 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_program.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_program.cc
@@ -153,10 +153,4 @@ void WebGLProgram::Trace(blink::Visitor* visitor) {
WebGLSharedPlatform3DObject::Trace(visitor);
}
-void WebGLProgram::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(vertex_shader_);
- visitor->TraceWrappers(fragment_shader_);
- WebGLSharedPlatform3DObject::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_program.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_program.h
index 4c340aaa61d..063d217b140 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_program.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_program.h
@@ -71,7 +71,6 @@ class WebGLProgram final : public WebGLSharedPlatform3DObject {
bool DetachShader(WebGLShader*);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
protected:
explicit WebGLProgram(WebGLRenderingContextBase*);
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_program.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl_program.idl
index fec20d34ea6..cdb648ee77d 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_program.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_program.idl
@@ -25,5 +25,7 @@
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.6
-interface WebGLProgram {
+[
+ Exposed(Worker OffscreenCanvas, Window StableBlinkFeatures)
+] interface WebGLProgram {
};
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_query.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl_query.idl
index 5c298b63f1d..6824d2a5090 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_query.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_query.idl
@@ -4,5 +4,7 @@
// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.2
-interface WebGLQuery {
+[
+ Exposed(Worker OffscreenCanvas, Window StableBlinkFeatures)
+] interface WebGLQuery {
};
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_renderbuffer.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl_renderbuffer.idl
index ad98b9f4d66..c78a00a000e 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_renderbuffer.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_renderbuffer.idl
@@ -25,5 +25,7 @@
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.7
-interface WebGLRenderbuffer {
+[
+ Exposed(Worker OffscreenCanvas, Window StableBlinkFeatures)
+] interface WebGLRenderbuffer {
};
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context.cc
index 98588bdd169..0e874487418 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context.cc
@@ -26,6 +26,7 @@
#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context.h"
#include <memory>
+#include "base/numerics/checked_math.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
@@ -64,7 +65,6 @@
#include "third_party/blink/renderer/modules/webgl/webgl_draw_buffers.h"
#include "third_party/blink/renderer/modules/webgl/webgl_lose_context.h"
#include "third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
namespace blink {
@@ -92,8 +92,8 @@ CanvasRenderingContext* WebGLRenderingContext::Factory::Create(
const CanvasContextCreationAttributesCore& attrs) {
bool using_gpu_compositing;
std::unique_ptr<WebGraphicsContext3DProvider> context_provider(
- CreateWebGraphicsContext3DProvider(host, attrs, 1,
- &using_gpu_compositing));
+ CreateWebGraphicsContext3DProvider(
+ host, attrs, Platform::kWebGL1ContextType, &using_gpu_compositing));
if (!ShouldCreateContext(context_provider.get()))
return nullptr;
@@ -126,7 +126,7 @@ WebGLRenderingContext::WebGLRenderingContext(
std::move(context_provider),
using_gpu_compositing,
requested_attributes,
- 1) {}
+ Platform::kWebGL1ContextType) {}
void WebGLRenderingContext::SetCanvasGetContextResult(
RenderingContext& result) {
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h
index 984a5052579..5d13ec8aed7 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h
@@ -123,10 +123,11 @@ DEFINE_TYPE_CASTS(WebGLRenderingContext,
CanvasRenderingContext,
context,
context->Is3d() &&
- WebGLRenderingContextBase::GetWebGLVersion(context) == 1,
+ WebGLRenderingContextBase::GetWebGLVersion(context) ==
+ Platform::kWebGL1ContextType,
context.Is3d() &&
WebGLRenderingContextBase::GetWebGLVersion(&context) ==
- 1);
+ Platform::kWebGL1ContextType);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
index 7a43c86378d..d22b722fcad 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -27,13 +27,12 @@
#include <memory>
+#include "base/numerics/checked_math.h"
#include "build/build_config.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/config/gpu_feature_info.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/modules/v8/html_canvas_element_or_offscreen_canvas.h"
#include "third_party/blink/renderer/bindings/modules/v8/webgl_any.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -91,6 +90,7 @@
#include "third_party/blink/renderer/modules/webgl/webgl_vertex_array_object.h"
#include "third_party/blink/renderer/modules/webgl/webgl_vertex_array_object_oes.h"
#include "third_party/blink/renderer/modules/xr/xr_device.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable_visitor.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding_macros.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
@@ -102,28 +102,26 @@
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/waitable_event.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
+#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
#include "third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h"
namespace blink {
+bool WebGLRenderingContextBase::webgl_context_limits_initialized_ = false;
+unsigned WebGLRenderingContextBase::max_active_webgl_contexts_ = 0;
+unsigned WebGLRenderingContextBase::max_active_webgl_contexts_on_worker_ = 0;
+
namespace {
-const double kSecondsBetweenRestoreAttempts = 1.0;
+constexpr TimeDelta kDurationBetweenRestoreAttempts = TimeDelta::FromSeconds(1);
const int kMaxGLErrorsAllowedToConsole = 256;
-const unsigned kMaxGLActiveContextsOnWorker = 4;
-
-#if defined(OS_ANDROID)
-const unsigned kMaxGLActiveContexts = 8;
-#else // defined(OS_ANDROID)
-const unsigned kMaxGLActiveContexts = 16;
-#endif // defined(OS_ANDROID)
-unsigned CurrentMaxGLContexts() {
- return IsMainThread() ? kMaxGLActiveContexts : kMaxGLActiveContextsOnWorker;
+Mutex& WebGLContextLimitMutex() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, mutex, ());
+ return mutex;
}
using WebGLRenderingContextBaseSet =
@@ -181,6 +179,25 @@ ScopedRGBEmulationColorMask::~ScopedRGBEmulationColorMask() {
}
}
+void WebGLRenderingContextBase::InitializeWebGLContextLimits(
+ const DrawingBuffer::WebGLContextLimits& limits) {
+ MutexLocker locker(WebGLContextLimitMutex());
+ if (!webgl_context_limits_initialized_) {
+ // These do not change over the lifetime of the browser.
+ max_active_webgl_contexts_ = limits.max_active_webgl_contexts;
+ max_active_webgl_contexts_on_worker_ =
+ limits.max_active_webgl_contexts_on_worker;
+ webgl_context_limits_initialized_ = true;
+ }
+}
+
+unsigned WebGLRenderingContextBase::CurrentMaxGLContexts() {
+ MutexLocker locker(WebGLContextLimitMutex());
+ DCHECK(webgl_context_limits_initialized_);
+ return IsMainThread() ? max_active_webgl_contexts_
+ : max_active_webgl_contexts_on_worker_;
+}
+
void WebGLRenderingContextBase::ForciblyLoseOldestContext(
const String& reason) {
WebGLRenderingContextBase* candidate = OldestContext();
@@ -646,15 +663,14 @@ std::unique_ptr<WebGraphicsContext3DProvider>
WebGLRenderingContextBase::CreateContextProviderInternal(
CanvasRenderingContextHost* host,
const CanvasContextCreationAttributesCore& attributes,
- unsigned web_gl_version,
+ Platform::ContextType context_type,
bool* using_gpu_compositing) {
DCHECK(host);
ExecutionContext* execution_context = host->GetTopExecutionContext();
DCHECK(execution_context);
Platform::ContextAttributes context_attributes = ToPlatformContextAttributes(
- attributes, web_gl_version,
- SupportOwnOffscreenSurface(execution_context));
+ attributes, context_type, SupportOwnOffscreenSurface(execution_context));
Platform::GraphicsInfo gl_info;
std::unique_ptr<WebGraphicsContext3DProvider> context_provider;
@@ -697,7 +713,7 @@ std::unique_ptr<WebGraphicsContext3DProvider>
WebGLRenderingContextBase::CreateWebGraphicsContext3DProvider(
CanvasRenderingContextHost* host,
const CanvasContextCreationAttributesCore& attributes,
- unsigned webgl_version,
+ Platform::ContextType context_type,
bool* using_gpu_compositing) {
// The host might block creation of a new WebGL context despite the
// page settings; in particular, if WebGL contexts were lost one or
@@ -709,15 +725,19 @@ WebGLRenderingContextBase::CreateWebGraphicsContext3DProvider(
"Web page caused context loss and was blocked"));
return nullptr;
}
- if ((webgl_version == 1 && !host->IsWebGL1Enabled()) ||
- (webgl_version == 2 && !host->IsWebGL2Enabled())) {
+ if ((context_type == Platform::kWebGL1ContextType &&
+ !host->IsWebGL1Enabled()) ||
+ (context_type == Platform::kWebGL2ContextType &&
+ !host->IsWebGL2Enabled()) ||
+ (context_type == Platform::kWebGL2ComputeContextType &&
+ !host->IsWebGL2Enabled())) {
host->HostDispatchEvent(WebGLContextEvent::Create(
EventTypeNames::webglcontextcreationerror,
"disabled by enterprise policy or commandline switch"));
return nullptr;
}
- return CreateContextProviderInternal(host, attributes, webgl_version,
+ return CreateContextProviderInternal(host, attributes, context_type,
using_gpu_compositing);
}
@@ -729,28 +749,21 @@ ImageBitmap* WebGLRenderingContextBase::TransferToImageBitmapBase(
ScriptState* script_state) {
WebFeature feature = WebFeature::kOffscreenCanvasTransferToImageBitmapWebGL;
UseCounter::Count(ExecutionContext::From(script_state), feature);
- if (!GetDrawingBuffer())
- return nullptr;
- std::unique_ptr<viz::SingleReleaseCallback> image_release_callback;
- scoped_refptr<StaticBitmapImage> image =
- GetDrawingBuffer()->TransferToStaticBitmapImage(&image_release_callback);
- GetDrawingBuffer()->SwapPreviousFrameCallback(
- std::move(image_release_callback));
-
- return ImageBitmap::Create(image);
+ return ImageBitmap::Create(
+ GetDrawingBuffer()->TransferToStaticBitmapImage(nullptr));
}
void WebGLRenderingContextBase::commit() {
int width = GetDrawingBuffer()->Size().Width();
int height = GetDrawingBuffer()->Size().Height();
- std::unique_ptr<viz::SingleReleaseCallback> image_release_callback;
- scoped_refptr<StaticBitmapImage> image =
- GetStaticBitmapImage(&image_release_callback);
- GetDrawingBuffer()->SwapPreviousFrameCallback(
- std::move(image_release_callback));
-
- Host()->Commit(std::move(image), SkIRect::MakeWH(width, height));
+ if (PaintRenderingResultsToCanvas(kBackBuffer)) {
+ if (Host()->GetOrCreateCanvasResourceProvider(kPreferAcceleration)) {
+ Host()->Commit(Host()->ResourceProvider()->ProduceFrame(),
+ SkIRect::MakeWH(width, height));
+ }
+ }
+ MarkLayerComposited();
}
scoped_refptr<StaticBitmapImage>
@@ -771,10 +784,15 @@ scoped_refptr<StaticBitmapImage> WebGLRenderingContextBase::GetImage(
return nullptr;
GetDrawingBuffer()->ResolveAndBindForReadAndDraw();
IntSize size = ClampedCanvasSize();
+ // Since we are grabbing a snapshot that is not for compositing, we use a
+ // custom resource provider. This avoids consuming compositing-specific
+ // resources (e.g. GpuMemoryBuffer)
std::unique_ptr<CanvasResourceProvider> resource_provider =
CanvasResourceProvider::Create(
size, CanvasResourceProvider::kAcceleratedResourceUsage,
- SharedGpuContext::ContextProviderWrapper(), 0, ColorParams());
+ SharedGpuContext::ContextProviderWrapper(), 0, ColorParams(),
+ CanvasResourceProvider::kDefaultPresentationMode,
+ nullptr); // canvas_resource_dispatcher
if (!resource_provider || !resource_provider->IsValid())
return nullptr;
if (!CopyRenderingResultsFromDrawingBuffer(resource_provider.get(),
@@ -794,8 +812,8 @@ ScriptPromise WebGLRenderingContextBase::setCompatibleXRDevice(
if (isContextLost()) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, "Context lost."));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Context lost."));
}
if (xr_device == compatible_xr_device_) {
@@ -811,7 +829,7 @@ ScriptPromise WebGLRenderingContextBase::setCompatibleXRDevice(
return ScriptPromise::RejectWithDOMException(
script_state,
DOMException::Create(
- kNotSupportedError,
+ DOMExceptionCode::kNotSupportedError,
"Context is not compatible. Switching not yet implemented."));
}
}
@@ -966,7 +984,7 @@ WebGLRenderingContextBase::WebGLRenderingContextBase(
std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
bool using_gpu_compositing,
const CanvasContextCreationAttributesCore& requested_attributes,
- unsigned version)
+ Platform::ContextType version)
: WebGLRenderingContextBase(
host,
host->GetTopExecutionContext()->GetTaskRunner(TaskType::kWebGL),
@@ -981,7 +999,7 @@ WebGLRenderingContextBase::WebGLRenderingContextBase(
std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
bool using_gpu_compositing,
const CanvasContextCreationAttributesCore& requested_attributes,
- unsigned version)
+ Platform::ContextType context_type)
: CanvasRenderingContext(host, requested_attributes),
context_group_(new WebGLContextGroup()),
is_hidden_(false),
@@ -1008,11 +1026,9 @@ WebGLRenderingContextBase::WebGLRenderingContextBase(
is_web_gl_depth_texture_formats_types_added_(false),
is_ext_srgb_formats_types_added_(false),
is_ext_color_buffer_float_formats_added_(false),
- version_(version) {
+ context_type_(context_type) {
DCHECK(context_provider);
- Host()->RegisterContextToDispatch(this);
-
// TODO(offenwanger) Make sure this is being created on a compatible adapter.
compatible_xr_device_ =
static_cast<XRDevice*>(requested_attributes.compatible_xr_device.Get());
@@ -1031,6 +1047,7 @@ WebGLRenderingContextBase::WebGLRenderingContextBase(
return;
}
+ InitializeWebGLContextLimits(buffer->webgl_context_limits());
drawing_buffer_ = std::move(buffer);
GetDrawingBuffer()->Bind(GL_FRAMEBUFFER);
SetupFlags();
@@ -1073,10 +1090,12 @@ scoped_refptr<DrawingBuffer> WebGLRenderingContextBase::CreateDrawingBuffer(
CreationAttributes().preserve_drawing_buffer ? DrawingBuffer::kPreserve
: DrawingBuffer::kDiscard;
DrawingBuffer::WebGLVersion web_gl_version = DrawingBuffer::kWebGL1;
- if (Version() == 1) {
+ if (context_type_ == Platform::kWebGL1ContextType) {
web_gl_version = DrawingBuffer::kWebGL1;
- } else if (Version() == 2) {
+ } else if (context_type_ == Platform::kWebGL2ContextType) {
web_gl_version = DrawingBuffer::kWebGL2;
+ } else if (context_type_ == Platform::kWebGL2ComputeContextType) {
+ web_gl_version = DrawingBuffer::kWebGL2Compute;
} else {
NOTREACHED();
}
@@ -1271,7 +1290,7 @@ unsigned WebGLRenderingContextBase::GetWebGLVersion(
const CanvasRenderingContext* context) {
if (!context->Is3d())
return 0;
- return static_cast<const WebGLRenderingContextBase*>(context)->Version();
+ return static_cast<const WebGLRenderingContextBase*>(context)->ContextType();
}
WebGLRenderingContextBase::~WebGLRenderingContextBase() {
@@ -1367,19 +1386,15 @@ void WebGLRenderingContextBase::DidDraw() {
}
void WebGLRenderingContextBase::PushFrame() {
- if (!marked_canvas_dirty_)
- return;
-
- marked_canvas_dirty_ = false;
int width = GetDrawingBuffer()->Size().Width();
int height = GetDrawingBuffer()->Size().Height();
-
- std::unique_ptr<viz::SingleReleaseCallback> image_release_callback;
- scoped_refptr<StaticBitmapImage> image =
- GetStaticBitmapImage(&image_release_callback);
- GetDrawingBuffer()->SwapPreviousFrameCallback(
- std::move(image_release_callback));
- return Host()->PushFrame(std::move(image), SkIRect::MakeWH(width, height));
+ if (PaintRenderingResultsToCanvas(kBackBuffer)) {
+ if (Host()->GetOrCreateCanvasResourceProvider(kPreferAcceleration)) {
+ Host()->PushFrame(Host()->ResourceProvider()->ProduceFrame(),
+ SkIRect::MakeWH(width, height));
+ }
+ }
+ MarkLayerComposited();
}
void WebGLRenderingContextBase::FinalizeFrame() {
@@ -1528,21 +1543,19 @@ bool WebGLRenderingContextBase::PaintRenderingResultsToCanvas(
if (!marked_canvas_dirty_ && !must_clear_now)
return false;
- canvas()->ClearCopiedImage();
+ if (canvas())
+ canvas()->ClearCopiedImage();
marked_canvas_dirty_ = false;
- if (!canvas()->GetOrCreateCanvasResourceProviderForWebGL())
- return false;
-
- if (!canvas()->GetOrCreateCanvasResourceProviderForWebGL()->IsAccelerated())
+ if (!Host()->GetOrCreateCanvasResourceProvider(kPreferAcceleration))
return false;
ScopedTexture2DRestorer restorer(this);
ScopedFramebufferRestorer fbo_restorer(this);
GetDrawingBuffer()->ResolveAndBindForReadAndDraw();
- if (!CopyRenderingResultsFromDrawingBuffer(
- canvas()->ResourceProviderForWebGL(), source_buffer)) {
+ if (!CopyRenderingResultsFromDrawingBuffer(Host()->ResourceProvider(),
+ source_buffer)) {
// Currently, copyRenderingResultsFromDrawingBuffer is expected to always
// succeed because cases where canvas()-buffer() is not accelerated are
// handle before reaching this point. If that assumption ever stops holding
@@ -1550,7 +1563,6 @@ bool WebGLRenderingContextBase::PaintRenderingResultsToCanvas(
NOTREACHED();
return false;
}
-
return true;
}
@@ -1565,23 +1577,36 @@ bool WebGLRenderingContextBase::CopyRenderingResultsFromDrawingBuffer(
SourceDrawingBuffer source_buffer) const {
if (!drawing_buffer_)
return false;
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> shared_context_wrapper =
- SharedGpuContext::ContextProviderWrapper();
- if (!shared_context_wrapper)
- return false;
- gpu::gles2::GLES2Interface* gl =
- shared_context_wrapper->ContextProvider()->ContextGL();
- GLuint texture_id = resource_provider->GetBackingTextureHandleForOverwrite();
- if (!texture_id)
- return false;
+ if (resource_provider->IsAccelerated()) {
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> shared_context_wrapper =
+ SharedGpuContext::ContextProviderWrapper();
+ if (!shared_context_wrapper)
+ return false;
+ gpu::gles2::GLES2Interface* gl =
+ shared_context_wrapper->ContextProvider()->ContextGL();
+ GLuint texture_id =
+ resource_provider->GetBackingTextureHandleForOverwrite();
+ if (!texture_id)
+ return false;
+
+ // TODO(xlai): Flush should not be necessary if the synchronization in
+ // CopyToPlatformTexture is done correctly. See crbug.com/794706.
+ gl->Flush();
- // TODO(xlai): Flush should not be necessary if the synchronization in
- // CopyToPlatformTexture is done correctly. See crbug.com/794706.
- gl->Flush();
+ return drawing_buffer_->CopyToPlatformTexture(
+ gl, GL_TEXTURE_2D, texture_id, true, false, IntPoint(0, 0),
+ IntRect(IntPoint(0, 0), drawing_buffer_->Size()), source_buffer);
+ }
- return drawing_buffer_->CopyToPlatformTexture(
- gl, GL_TEXTURE_2D, texture_id, true, false, IntPoint(0, 0),
- IntRect(IntPoint(0, 0), drawing_buffer_->Size()), source_buffer);
+ // Note: This code path could work for all cases. The only reason there
+ // is a separate path for the accelerated case is that we assume texture
+ // copying is faster than drawImage.
+ scoped_refptr<StaticBitmapImage> image = GetImage(kPreferAcceleration);
+ if (!image)
+ return false;
+ resource_provider->Canvas()->drawImage(image->PaintImageForCurrentFrame(), 0,
+ 0, nullptr);
+ return true;
}
IntSize WebGLRenderingContextBase::DrawingBufferSize() const {
@@ -2500,9 +2525,8 @@ void WebGLRenderingContextBase::drawArrays(GLenum mode,
ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
drawing_buffer_.get());
- ClearIfComposited();
+ OnBeforeDrawCall();
ContextGL()->DrawArrays(mode, first, count);
- MarkContextChanged(kCanvasChanged);
}
void WebGLRenderingContextBase::drawElements(GLenum mode,
@@ -2520,11 +2544,10 @@ void WebGLRenderingContextBase::drawElements(GLenum mode,
ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
drawing_buffer_.get());
- ClearIfComposited();
+ OnBeforeDrawCall();
ContextGL()->DrawElements(
mode, count, type,
reinterpret_cast<void*>(static_cast<intptr_t>(offset)));
- MarkContextChanged(kCanvasChanged);
}
void WebGLRenderingContextBase::DrawArraysInstancedANGLE(GLenum mode,
@@ -2542,9 +2565,8 @@ void WebGLRenderingContextBase::DrawArraysInstancedANGLE(GLenum mode,
ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
drawing_buffer_.get());
- ClearIfComposited();
+ OnBeforeDrawCall();
ContextGL()->DrawArraysInstancedANGLE(mode, first, count, primcount);
- MarkContextChanged(kCanvasChanged);
}
void WebGLRenderingContextBase::DrawElementsInstancedANGLE(GLenum mode,
@@ -2563,11 +2585,10 @@ void WebGLRenderingContextBase::DrawElementsInstancedANGLE(GLenum mode,
ScopedRGBEmulationColorMask emulation_color_mask(this, color_mask_,
drawing_buffer_.get());
- ClearIfComposited();
+ OnBeforeDrawCall();
ContextGL()->DrawElementsInstancedANGLE(
mode, count, type, reinterpret_cast<void*>(static_cast<intptr_t>(offset)),
primcount);
- MarkContextChanged(kCanvasChanged);
}
void WebGLRenderingContextBase::enable(GLenum cap) {
@@ -3910,7 +3931,7 @@ void WebGLRenderingContextBase::hint(GLenum target, GLenum mode) {
}
GLboolean WebGLRenderingContextBase::isBuffer(WebGLBuffer* buffer) {
- if (!buffer || isContextLost())
+ if (!buffer || isContextLost() || !buffer->Validate(ContextGroup(), this))
return 0;
if (!buffer->HasEverBeenBound())
@@ -3935,7 +3956,8 @@ GLboolean WebGLRenderingContextBase::isEnabled(GLenum cap) {
GLboolean WebGLRenderingContextBase::isFramebuffer(
WebGLFramebuffer* framebuffer) {
- if (!framebuffer || isContextLost())
+ if (!framebuffer || isContextLost() ||
+ !framebuffer->Validate(ContextGroup(), this))
return 0;
if (!framebuffer->HasEverBeenBound())
@@ -3947,7 +3969,7 @@ GLboolean WebGLRenderingContextBase::isFramebuffer(
}
GLboolean WebGLRenderingContextBase::isProgram(WebGLProgram* program) {
- if (!program || isContextLost())
+ if (!program || isContextLost() || !program->Validate(ContextGroup(), this))
return 0;
return ContextGL()->IsProgram(program->Object());
@@ -3955,7 +3977,8 @@ GLboolean WebGLRenderingContextBase::isProgram(WebGLProgram* program) {
GLboolean WebGLRenderingContextBase::isRenderbuffer(
WebGLRenderbuffer* renderbuffer) {
- if (!renderbuffer || isContextLost())
+ if (!renderbuffer || isContextLost() ||
+ !renderbuffer->Validate(ContextGroup(), this))
return 0;
if (!renderbuffer->HasEverBeenBound())
@@ -3967,14 +3990,14 @@ GLboolean WebGLRenderingContextBase::isRenderbuffer(
}
GLboolean WebGLRenderingContextBase::isShader(WebGLShader* shader) {
- if (!shader || isContextLost())
+ if (!shader || isContextLost() || !shader->Validate(ContextGroup(), this))
return 0;
return ContextGL()->IsShader(shader->Object());
}
GLboolean WebGLRenderingContextBase::isTexture(WebGLTexture* texture) {
- if (!texture || isContextLost())
+ if (!texture || isContextLost() || !texture->Validate(ContextGroup(), this))
return 0;
if (!texture->HasEverBeenBound())
@@ -4214,7 +4237,7 @@ void WebGLRenderingContextBase::ReadPixelsHelper(GLint x,
"no destination ArrayBufferView");
return;
}
- CheckedNumeric<GLuint> offset_in_bytes = offset;
+ base::CheckedNumeric<GLuint> offset_in_bytes = offset;
offset_in_bytes *= pixels->TypeSize();
if (!offset_in_bytes.IsValid() ||
offset_in_bytes.ValueOrDie() > pixels->byteLength()) {
@@ -4229,7 +4252,8 @@ void WebGLRenderingContextBase::ReadPixelsHelper(GLint x,
SynthesizeGLError(GL_INVALID_FRAMEBUFFER_OPERATION, "readPixels", reason);
return;
}
- CheckedNumeric<GLuint> buffer_size = pixels->byteLength() - offset_in_bytes;
+ base::CheckedNumeric<GLuint> buffer_size =
+ pixels->byteLength() - offset_in_bytes;
if (!buffer_size.IsValid()) {
SynthesizeGLError(GL_INVALID_VALUE, "readPixels",
"destination offset out of range");
@@ -4667,8 +4691,8 @@ scoped_refptr<Image> WebGLRenderingContextBase::DrawImageIntoBuffer(
PaintFlags flags;
// TODO(ccameron): WebGL should produce sRGB images.
// https://crbug.com/672299
- image->Draw(resource_provider->Canvas(), flags, dest_rect, src_rect,
- kDoNotRespectImageOrientation,
+ image->Draw(resource_provider->Canvas(), flags, FloatRect(dest_rect),
+ FloatRect(src_rect), kDoNotRespectImageOrientation,
Image::kDoNotClampImageToSourceRect, Image::kSyncDecode);
return resource_provider->Snapshot();
}
@@ -5192,9 +5216,10 @@ void WebGLRenderingContextBase::TexImageHelperHTMLCanvasElement(
else
function_type = kTexSubImage;
if (!ValidateTexFunc(func_name, function_type, kSourceHTMLCanvasElement,
- target, level, internalformat, canvas->width(),
- canvas->height(), depth, 0, format, type, xoffset,
- yoffset, zoffset))
+ target, level, internalformat,
+ source_sub_rectangle.Width(),
+ source_sub_rectangle.Height(), depth, 0, format, type,
+ xoffset, yoffset, zoffset))
return;
// Note that the sub-rectangle validation is needed for the GPU-GPU
@@ -5396,7 +5421,11 @@ void WebGLRenderingContextBase::TexImageHelperHTMLVideoElement(
CanvasResourceProvider::Create(
IntSize(video->videoWidth(), video->videoHeight()),
CanvasResourceProvider::kAcceleratedResourceUsage,
- SharedGpuContext::ContextProviderWrapper());
+ SharedGpuContext::ContextProviderWrapper(),
+ 0, // msaa_sample_count
+ CanvasColorParams(),
+ CanvasResourceProvider::kDefaultPresentationMode,
+ nullptr); // canvas_resource_dispatcher
if (resource_provider && resource_provider->IsValid()) {
// The video element paints an RGBA frame into our surface here. By
// using an AcceleratedImageBufferSurface, we enable the WebMediaPlayer
@@ -7197,7 +7226,7 @@ bool WebGLRenderingContextBase::ValidateTexFuncData(
SynthesizeGLError(error, function_name, "invalid texture dimensions");
return false;
}
- CheckedNumeric<uint32_t> total = src_offset;
+ base::CheckedNumeric<uint32_t> total = src_offset;
total *= pixels->TypeSize();
total += total_bytes_required;
total += skip_bytes;
@@ -7579,6 +7608,11 @@ bool WebGLRenderingContextBase::ValidateDrawElements(const char* function_name,
return true;
}
+void WebGLRenderingContextBase::OnBeforeDrawCall() {
+ ClearIfComposited();
+ MarkContextChanged(kCanvasChanged);
+}
+
void WebGLRenderingContextBase::DispatchContextLostEvent(TimerBase*) {
WebGLContextEvent* event =
WebGLContextEvent::Create(EventTypeNames::webglcontextlost, "");
@@ -7610,8 +7644,11 @@ void WebGLRenderingContextBase::MaybeRestoreContext(TimerBase*) {
return;
Settings* settings = frame->GetSettings();
- if (settings && ((version_ == 1 && !settings->GetWebGL1Enabled()) ||
- (version_ == 2 && !settings->GetWebGL2Enabled()))) {
+ if (settings && ((context_type_ == Platform::kWebGL1ContextType &&
+ !settings->GetWebGL1Enabled()) ||
+ ((context_type_ == Platform::kWebGL2ContextType ||
+ context_type_ == Platform::kWebGL2ComputeContextType) &&
+ !settings->GetWebGL2Enabled()))) {
return;
}
}
@@ -7622,7 +7659,7 @@ void WebGLRenderingContextBase::MaybeRestoreContext(TimerBase*) {
auto* execution_context = Host()->GetTopExecutionContext();
Platform::ContextAttributes attributes = ToPlatformContextAttributes(
- CreationAttributes(), Version(),
+ CreationAttributes(), context_type_,
SupportOwnOffscreenSurface(execution_context));
Platform::GraphicsInfo gl_info;
std::unique_ptr<WebGraphicsContext3DProvider> context_provider;
@@ -7650,7 +7687,7 @@ void WebGLRenderingContextBase::MaybeRestoreContext(TimerBase*) {
}
if (!buffer) {
if (context_lost_mode_ == kRealLostContext) {
- restore_timer_.StartOneShot(kSecondsBetweenRestoreAttempts, FROM_HERE);
+ restore_timer_.StartOneShot(kDurationBetweenRestoreAttempts, FROM_HERE);
} else {
// This likely shouldn't happen but is the best way to report it to the
// WebGL app.
@@ -7700,7 +7737,12 @@ CanvasResourceProvider* WebGLRenderingContextBase::
}
std::unique_ptr<CanvasResourceProvider> temp(CanvasResourceProvider::Create(
- size, CanvasResourceProvider::kSoftwareResourceUsage));
+ size, CanvasResourceProvider::kSoftwareResourceUsage,
+ nullptr, // context_provider_wrapper
+ 0, // msaa_sample_count,
+ CanvasColorParams(), // TODO: should this use the canvas's colorspace?
+ CanvasResourceProvider::kDefaultPresentationMode,
+ nullptr)); // canvas_resource_dispatcher
if (!temp)
return nullptr;
i = std::min(resource_providers_.size() - 1, i);
@@ -7890,28 +7932,6 @@ void WebGLRenderingContextBase::Trace(blink::Visitor* visitor) {
CanvasRenderingContext::Trace(visitor);
}
-void WebGLRenderingContextBase::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(context_group_);
- visitor->TraceWrappers(bound_array_buffer_);
- visitor->TraceWrappers(renderbuffer_binding_);
- visitor->TraceWrappers(framebuffer_binding_);
- visitor->TraceWrappers(current_program_);
- visitor->TraceWrappers(bound_vertex_array_object_);
- // Trace wrappers explicitly here since TextureUnitState is not a heap
- // object, i.e., we cannot set its mark bits.
- for (auto& unit : texture_units_) {
- visitor->TraceWrappers(unit.texture2d_binding_);
- visitor->TraceWrappers(unit.texture_cube_map_binding_);
- visitor->TraceWrappers(unit.texture3d_binding_);
- visitor->TraceWrappers(unit.texture2d_array_binding_);
- }
- for (auto tracker : extensions_) {
- visitor->TraceWrappers(tracker);
- }
- CanvasRenderingContext::TraceWrappers(visitor);
-}
-
int WebGLRenderingContextBase::ExternallyAllocatedBufferCountPerPixel() {
if (isContextLost())
return 0;
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
index 75f929c77fb..bed21bdfaf2 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
@@ -29,6 +29,7 @@
#include <memory>
#include <set>
+#include "base/numerics/checked_math.h"
#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "third_party/blink/public/platform/platform.h"
@@ -46,14 +47,12 @@
#include "third_party/blink/renderer/modules/webgl/webgl_texture.h"
#include "third_party/blink/renderer/modules/webgl/webgl_vertex_array_object_base.h"
#include "third_party/blink/renderer/modules/xr/xr_device.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/bindings/script_wrappable.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable_visitor.h"
#include "third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h"
#include "third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h"
#include "third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h"
#include "third_party/blink/renderer/platform/timer.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/khronos/GLES2/gl2.h"
@@ -144,11 +143,11 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
static std::unique_ptr<WebGraphicsContext3DProvider>
CreateWebGraphicsContext3DProvider(CanvasRenderingContextHost*,
const CanvasContextCreationAttributesCore&,
- unsigned web_gl_version,
+ Platform::ContextType context_type,
bool* using_gpu_compositing);
static void ForceNextWebGLContextCreationToFail();
- unsigned Version() const { return version_; }
+ Platform::ContextType ContextType() const { return context_type_; }
int drawingBufferWidth() const;
int drawingBufferHeight() const;
@@ -570,8 +569,6 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
// Returns approximate gpu memory allocated per pixel.
int ExternallyAllocatedBufferCountPerPixel() override;
@@ -597,7 +594,10 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
scoped_refptr<StaticBitmapImage> GetImage(
AccelerationHint = kPreferAcceleration) const override;
void SetFilterQuality(SkFilterQuality) override;
- bool IsWebGL2OrHigher() { return Version() >= 2; }
+ bool IsWebGL2OrHigher() {
+ return context_type_ == Platform::kWebGL2ContextType ||
+ context_type_ == Platform::kWebGL2ComputeContextType;
+ }
void getHTMLOrOffscreenCanvas(HTMLCanvasElementOrOffscreenCanvas&) const;
@@ -641,7 +641,7 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
std::unique_ptr<WebGraphicsContext3DProvider>,
bool using_gpu_compositing,
const CanvasContextCreationAttributesCore&,
- unsigned);
+ Platform::ContextType);
scoped_refptr<DrawingBuffer> CreateDrawingBuffer(
std::unique_ptr<WebGraphicsContext3DProvider>,
bool using_gpu_compositing);
@@ -827,7 +827,7 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
};
class ExtensionTracker : public GarbageCollected<ExtensionTracker>,
- public TraceWrapperBase {
+ public NameClient {
public:
ExtensionTracker(ExtensionFlags flags, const char* const* prefixes)
: draft_(flags & kDraftExtension), prefixes_(prefixes) {}
@@ -846,7 +846,6 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
virtual WebGLExtension* GetExtensionObjectIfAlreadyEnabled() = 0;
virtual void Trace(blink::Visitor* visitor) {}
- void TraceWrappers(ScriptWrappableVisitor*) const override {}
const char* NameInHeapSnapshot() const override {
return "ExtensionTracker";
}
@@ -897,11 +896,6 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
ExtensionTracker::Trace(visitor);
}
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- visitor->TraceWrappers(extension_);
- ExtensionTracker::TraceWrappers(visitor);
- }
-
private:
TypedExtensionTracker(Member<T>& extension_field,
ExtensionFlags flags,
@@ -1106,7 +1100,7 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
// According to the WebGL 2.0 spec, specifying depth > 1 means
// to select multiple rectangles stacked vertically.
- WTF::CheckedNumeric<GLint> max_y_accessed;
+ base::CheckedNumeric<GLint> max_y_accessed;
if (unpack_image_height) {
max_y_accessed = unpack_image_height;
} else {
@@ -1481,6 +1475,9 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
GLenum type,
long long offset);
+ // State updates and operations necessary before or at draw call time.
+ virtual void OnBeforeDrawCall();
+
// Helper functions to bufferData() and bufferSubData().
void BufferDataImpl(GLenum target,
long long size,
@@ -1682,12 +1679,12 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
std::unique_ptr<WebGraphicsContext3DProvider>,
bool using_gpu_compositing,
const CanvasContextCreationAttributesCore&,
- unsigned);
+ Platform::ContextType);
static bool SupportOwnOffscreenSurface(ExecutionContext*);
static std::unique_ptr<WebGraphicsContext3DProvider>
CreateContextProviderInternal(CanvasRenderingContextHost*,
const CanvasContextCreationAttributesCore&,
- unsigned web_gl_version,
+ Platform::ContextType context_type,
bool* using_gpu_compositing);
void TexImageCanvasByGPU(TexImageFunctionID,
HTMLCanvasElement*,
@@ -1703,7 +1700,7 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
GLint,
const IntRect&);
- const unsigned version_;
+ const Platform::ContextType context_type_;
bool IsPaintable() const final { return GetDrawingBuffer(); }
@@ -1714,6 +1711,14 @@ class MODULES_EXPORT WebGLRenderingContextBase : public CanvasRenderingContext,
bool CopyRenderingResultsFromDrawingBuffer(CanvasResourceProvider*,
SourceDrawingBuffer) const;
void HoldReferenceToDrawingBuffer(DrawingBuffer*);
+
+ static void InitializeWebGLContextLimits(
+ const DrawingBuffer::WebGLContextLimits&);
+ static unsigned CurrentMaxGLContexts();
+
+ static bool webgl_context_limits_initialized_;
+ static unsigned max_active_webgl_contexts_;
+ static unsigned max_active_webgl_contexts_on_worker_;
};
// TODO(fserb): remove this.
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.idl
index 8d9c786eeeb..7755123e605 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.idl
@@ -705,7 +705,7 @@ typedef unrestricted float GLclampf;
void viewport(GLint x, GLint y, GLsizei width, GLsizei height);
- [RuntimeEnabled=OffscreenCanvas] void commit();
+ [RuntimeEnabled=OffscreenCanvasCommit] void commit();
// WebXR Device API support
[OriginTrialEnabled=WebXR, SecureContext, CallWith=ScriptState] Promise setCompatibleXRDevice(XRDevice device);
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_sampler.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl_sampler.idl
index 618de16ebef..ff8f8e1bff5 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_sampler.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_sampler.idl
@@ -4,5 +4,7 @@
// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.3
-interface WebGLSampler {
+[
+ Exposed(Worker OffscreenCanvas, Window StableBlinkFeatures)
+] interface WebGLSampler {
};
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_shader.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl_shader.idl
index 1b0016b346b..f05d8f1f1d4 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_shader.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_shader.idl
@@ -25,5 +25,7 @@
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.8
-interface WebGLShader {
+[
+ Exposed(Worker OffscreenCanvas, Window StableBlinkFeatures)
+] interface WebGLShader {
};
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_shader_precision_format.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl_shader_precision_format.idl
index e80b1e40439..447cb77ca25 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_shader_precision_format.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_shader_precision_format.idl
@@ -26,7 +26,9 @@
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.12
-interface WebGLShaderPrecisionFormat {
+[
+ Exposed(Worker OffscreenCanvas, Window StableBlinkFeatures)
+] interface WebGLShaderPrecisionFormat {
readonly attribute long rangeMin;
readonly attribute long rangeMax;
readonly attribute long precision;
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_shared_object.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_shared_object.cc
index b71e11360a7..8eeabfe86cf 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_shared_object.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_shared_object.cc
@@ -56,9 +56,4 @@ void WebGLSharedObject::Trace(blink::Visitor* visitor) {
WebGLObject::Trace(visitor);
}
-void WebGLSharedObject::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(context_group_);
- WebGLObject::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_shared_object.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_shared_object.h
index 6f00f9f8591..f2d4822dc1c 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_shared_object.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_shared_object.h
@@ -54,8 +54,6 @@ class WebGLSharedObject : public WebGLObject {
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
protected:
explicit WebGLSharedObject(WebGLRenderingContextBase*);
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_sync.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_sync.cc
index d10c6116a4e..5aea3371718 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_sync.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_sync.cc
@@ -12,7 +12,7 @@
namespace blink {
WebGLSync::WebGLSync(WebGL2RenderingContextBase* ctx,
- GLsync object,
+ GLuint object,
GLenum object_type)
: WebGLSharedObject(ctx),
sync_status_(GL_UNSIGNALED),
@@ -43,13 +43,12 @@ void WebGLSync::UpdateCache(gpu::gles2::GLES2Interface* gl) {
// We can only update the cached result when control returns to the browser.
allow_cache_update_ = false;
- GLsizei length = -1;
- GLint value = 0;
- gl->GetSynciv(object_, GL_SYNC_STATUS, 1, &length, &value);
- if (value) {
- sync_status_ = value;
- }
- if (sync_status_ != GL_SIGNALED) {
+ GLuint value = 0;
+ gl->GetQueryObjectuivEXT(object_, GL_QUERY_RESULT_AVAILABLE, &value);
+ if (value == GL_TRUE) {
+ sync_status_ = GL_SIGNALED;
+ } else {
+ sync_status_ = GL_UNSIGNALED;
ScheduleAllowCacheUpdate();
}
}
@@ -87,8 +86,8 @@ void WebGLSync::AllowCacheUpdate() {
}
void WebGLSync::DeleteObjectImpl(gpu::gles2::GLES2Interface* gl) {
- gl->DeleteSync(object_);
- object_ = nullptr;
+ gl->DeleteQueriesEXT(1, &object_);
+ object_ = 0;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_sync.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_sync.h
index fcc206aec59..2f88db96216 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_sync.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_sync.h
@@ -25,16 +25,16 @@ class WebGLSync : public WebGLSharedObject {
public:
~WebGLSync() override;
- GLsync Object() const { return object_; }
+ GLuint Object() const { return object_; }
void UpdateCache(gpu::gles2::GLES2Interface*);
GLint GetCachedResult(GLenum pname);
bool IsSignaled() const;
protected:
- WebGLSync(WebGL2RenderingContextBase*, GLsync, GLenum object_type);
+ WebGLSync(WebGL2RenderingContextBase*, GLuint, GLenum object_type);
- bool HasObject() const override { return object_ != nullptr; }
+ bool HasObject() const override { return object_ != 0; }
void DeleteObjectImpl(gpu::gles2::GLES2Interface*) override;
GLenum ObjectType() const { return object_type_; }
@@ -49,7 +49,7 @@ class WebGLSync : public WebGLSharedObject {
// Initialized in cpp file to avoid including gl3.h in this header.
GLint sync_status_;
- GLsync object_;
+ GLuint object_;
GLenum object_type_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_sync.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl_sync.idl
index bf464c20b96..2f6cc7c9be4 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_sync.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_sync.idl
@@ -4,5 +4,7 @@
// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.4
-interface WebGLSync {
+[
+ Exposed(Worker OffscreenCanvas, Window StableBlinkFeatures)
+] interface WebGLSync {
};
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_texture.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl_texture.idl
index 84805407f56..dfd20ad933e 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_texture.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_texture.idl
@@ -25,7 +25,9 @@
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.9
-interface WebGLTexture {
+[
+ Exposed(Worker OffscreenCanvas, Window StableBlinkFeatures)
+] interface WebGLTexture {
[RuntimeEnabled=ExtraWebGLVideoTextureMetadata] readonly attribute unsigned long lastUploadedVideoWidth;
[RuntimeEnabled=ExtraWebGLVideoTextureMetadata] readonly attribute unsigned long lastUploadedVideoHeight;
[RuntimeEnabled=ExtraWebGLVideoTextureMetadata] readonly attribute double lastUploadedVideoTimestamp;
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.cc
index 2488d042470..db1df4bf068 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.cc
@@ -148,12 +148,4 @@ void WebGLTransformFeedback::Trace(blink::Visitor* visitor) {
WebGLContextObject::Trace(visitor);
}
-void WebGLTransformFeedback::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- for (auto& buf : bound_indexed_transform_feedback_buffers_) {
- visitor->TraceWrappers(buf);
- }
- WebGLContextObject::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.h
index d7fc4a4506f..cf561d31357 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.h
@@ -51,10 +51,13 @@ class WebGLTransformFeedback : public WebGLContextObject {
void UnbindBuffer(WebGLBuffer*);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
bool active() const { return active_; }
bool paused() const { return paused_; }
+ const HeapVector<TraceWrapperMember<WebGLBuffer>>&
+ bound_indexed_transform_feedback_buffers() const {
+ return bound_indexed_transform_feedback_buffers_;
+ }
void SetActive(bool active) {
active_ = active;
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.idl
index 4220a9eea43..919d72ac636 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_transform_feedback.idl
@@ -4,5 +4,7 @@
// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.5
-interface WebGLTransformFeedback {
+[
+ Exposed(Worker OffscreenCanvas, Window StableBlinkFeatures)
+] interface WebGLTransformFeedback {
};
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_uniform_location.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl_uniform_location.idl
index 5d273d3c34d..b6c6568fee7 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_uniform_location.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_uniform_location.idl
@@ -26,5 +26,7 @@
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.10
-interface WebGLUniformLocation {
+[
+ Exposed(Worker OffscreenCanvas, Window StableBlinkFeatures)
+] interface WebGLUniformLocation {
};
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_vertex_array_object.idl b/chromium/third_party/blink/renderer/modules/webgl/webgl_vertex_array_object.idl
index 54d2c907fc1..2b74799425d 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_vertex_array_object.idl
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_vertex_array_object.idl
@@ -4,5 +4,7 @@
// https://www.khronos.org/registry/webgl/specs/latest/2.0/#3.6
-interface WebGLVertexArrayObject {
+[
+ Exposed(Worker OffscreenCanvas, Window StableBlinkFeatures)
+] interface WebGLVertexArrayObject {
};
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_vertex_array_object_base.cc b/chromium/third_party/blink/renderer/modules/webgl/webgl_vertex_array_object_base.cc
index 54bbc5a2b6a..da110a05a7c 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_vertex_array_object_base.cc
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_vertex_array_object_base.cc
@@ -132,13 +132,4 @@ void WebGLVertexArrayObjectBase::Trace(blink::Visitor* visitor) {
WebGLContextObject::Trace(visitor);
}
-void WebGLVertexArrayObjectBase::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(bound_element_array_buffer_);
- for (size_t i = 0; i < array_buffer_list_.size(); ++i) {
- visitor->TraceWrappers(array_buffer_list_[i]);
- }
- WebGLContextObject::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgl/webgl_vertex_array_object_base.h b/chromium/third_party/blink/renderer/modules/webgl/webgl_vertex_array_object_base.h
index 6f6596b3342..18930ea7181 100644
--- a/chromium/third_party/blink/renderer/modules/webgl/webgl_vertex_array_object_base.h
+++ b/chromium/third_party/blink/renderer/modules/webgl/webgl_vertex_array_object_base.h
@@ -43,7 +43,6 @@ class WebGLVertexArrayObjectBase : public WebGLContextObject {
void UnbindBuffer(WebGLBuffer*);
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
protected:
WebGLVertexArrayObjectBase(WebGLRenderingContextBase*, VaoType);
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/BUILD.gn b/chromium/third_party/blink/renderer/modules/webgpu/BUILD.gn
new file mode 100644
index 00000000000..3e2e9fffb75
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/BUILD.gn
@@ -0,0 +1,18 @@
+# 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/modules/modules.gni")
+
+blink_modules_sources("webgpu") {
+ sources = [
+ "webgpu.cc",
+ "webgpu.h",
+ "webgpu_adapter.cc",
+ "webgpu_adapter.h",
+ "webgpu_device.cc",
+ "webgpu_device.h",
+ "window_webgpu.cc",
+ "window_webgpu.h",
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/OWNERS b/chromium/third_party/blink/renderer/modules/webgpu/OWNERS
new file mode 100644
index 00000000000..1a2169f842c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/OWNERS
@@ -0,0 +1,5 @@
+cwallez@chromium.org
+kainino@chromium.org
+kbr@chromium.org
+
+# COMPONENT: Blink>WebGPU
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/README.md b/chromium/third_party/blink/renderer/modules/webgpu/README.md
new file mode 100644
index 00000000000..fc38f89393f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/README.md
@@ -0,0 +1,7 @@
+# WebGPU Blink module
+
+The WebGPU API is the successor to the WebGL and WebGL 2 graphics APIs for the Web.
+It will provide modern features such as “GPU compute” as well as lower overhead access to GPU hardware and better, more predictable performance.
+WebGPU is being developed by the [“GPU for the Web”](https://www.w3.org/community/gpu/) W3C community group.
+
+This Blink module implements the WebGPU API's [sketch WebIDL](https://github.com/gpuweb/gpuweb/blob/master/design/sketch.webidl) that will evolve as WebGPU gets closer to an MVP.
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/webgpu.cc b/chromium/third_party/blink/renderer/modules/webgpu/webgpu.cc
new file mode 100644
index 00000000000..4ec95c9d1e2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/webgpu.cc
@@ -0,0 +1,23 @@
+// 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/modules/webgpu/webgpu.h"
+
+#include "third_party/blink/renderer/modules/webgpu/webgpu_adapter.h"
+#include "third_party/blink/renderer/modules/webgpu/webgpu_adapter_descriptor.h"
+
+namespace blink {
+
+// static
+WebGPU* WebGPU::Create() {
+ return new WebGPU();
+}
+
+WebGPUAdapter* WebGPU::getAdapter(const WebGPUAdapterDescriptor& descriptor) {
+ return WebGPUAdapter::Create(descriptor.powerPreference());
+}
+
+WebGPU::WebGPU() {}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/webgpu.h b/chromium/third_party/blink/renderer/modules/webgpu/webgpu.h
new file mode 100644
index 00000000000..d989b7a1966
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/webgpu.h
@@ -0,0 +1,30 @@
+// 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_MODULES_WEBGPU_WEBGPU_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_H_
+
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+
+namespace blink {
+
+class WebGPUAdapter;
+class WebGPUAdapterDescriptor;
+
+class WebGPU final : public ScriptWrappable {
+ DISALLOW_COPY_AND_ASSIGN(WebGPU);
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static WebGPU* Create();
+
+ WebGPUAdapter* getAdapter(const WebGPUAdapterDescriptor&);
+
+ private:
+ WebGPU();
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_H_
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/webgpu.idl b/chromium/third_party/blink/renderer/modules/webgpu/webgpu.idl
new file mode 100644
index 00000000000..8877baff2fe
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/webgpu.idl
@@ -0,0 +1,9 @@
+// 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.
+
+[
+ RuntimeEnabled=WebGPU
+] interface WebGPU {
+ WebGPUAdapter getAdapter(WebGPUAdapterDescriptor descriptor);
+};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/webgpu_adapter.cc b/chromium/third_party/blink/renderer/modules/webgpu/webgpu_adapter.cc
new file mode 100644
index 00000000000..1e1f49e55d9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/webgpu_adapter.cc
@@ -0,0 +1,26 @@
+// 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/modules/webgpu/webgpu_adapter.h"
+
+#include "third_party/blink/renderer/modules/webgpu/webgpu_device.h"
+
+namespace blink {
+
+// static
+WebGPUAdapter* WebGPUAdapter::Create(const String& name) {
+ return new WebGPUAdapter(name);
+}
+
+const String& WebGPUAdapter::name() const {
+ return name_;
+}
+
+WebGPUDevice* WebGPUAdapter::createDevice() {
+ return WebGPUDevice::Create(this);
+}
+
+WebGPUAdapter::WebGPUAdapter(const String& name) : name_(name) {}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/webgpu_adapter.h b/chromium/third_party/blink/renderer/modules/webgpu/webgpu_adapter.h
new file mode 100644
index 00000000000..d1342c60662
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/webgpu_adapter.h
@@ -0,0 +1,34 @@
+// 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_MODULES_WEBGPU_WEBGPU_ADAPTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_ADAPTER_H_
+
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class WebGPUDevice;
+
+class WebGPUAdapter final : public ScriptWrappable {
+ DISALLOW_COPY_AND_ASSIGN(WebGPUAdapter);
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static WebGPUAdapter* Create(const String& name);
+
+ const String& name() const;
+
+ WebGPUDevice* createDevice();
+
+ private:
+ WebGPUAdapter(const String& name);
+
+ String name_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_ADAPTER_H_
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/webgpu_adapter.idl b/chromium/third_party/blink/renderer/modules/webgpu/webgpu_adapter.idl
new file mode 100644
index 00000000000..7623ef7c3c0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/webgpu_adapter.idl
@@ -0,0 +1,11 @@
+// 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.
+
+[
+ RuntimeEnabled=WebGPU
+] interface WebGPUAdapter {
+ readonly attribute DOMString name;
+
+ WebGPUDevice createDevice();
+};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/webgpu_adapter_descriptor.idl b/chromium/third_party/blink/renderer/modules/webgpu/webgpu_adapter_descriptor.idl
new file mode 100644
index 00000000000..4c9a6ca3fb7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/webgpu_adapter_descriptor.idl
@@ -0,0 +1,13 @@
+// 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.
+
+enum WebGPUPowerPreference {
+ "default",
+ "low-power",
+ "high-performance",
+};
+
+dictionary WebGPUAdapterDescriptor {
+ WebGPUPowerPreference powerPreference = "default";
+};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/webgpu_device.cc b/chromium/third_party/blink/renderer/modules/webgpu/webgpu_device.cc
new file mode 100644
index 00000000000..2364f6ee641
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/webgpu_device.cc
@@ -0,0 +1,27 @@
+// 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/modules/webgpu/webgpu_device.h"
+
+#include "third_party/blink/renderer/modules/webgpu/webgpu_adapter.h"
+
+namespace blink {
+
+// static
+WebGPUDevice* WebGPUDevice::Create(WebGPUAdapter* adapter) {
+ return new WebGPUDevice(adapter);
+}
+
+WebGPUAdapter* WebGPUDevice::adapter() const {
+ return adapter_;
+}
+
+void WebGPUDevice::Trace(blink::Visitor* visitor) {
+ visitor->Trace(adapter_);
+ ScriptWrappable::Trace(visitor);
+}
+
+WebGPUDevice::WebGPUDevice(WebGPUAdapter* adapter) : adapter_(adapter) {}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/webgpu_device.h b/chromium/third_party/blink/renderer/modules/webgpu/webgpu_device.h
new file mode 100644
index 00000000000..9fa781276c7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/webgpu_device.h
@@ -0,0 +1,33 @@
+// 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_MODULES_WEBGPU_WEBGPU_DEVICE_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_DEVICE_H_
+
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+
+namespace blink {
+
+class WebGPUAdapter;
+
+class WebGPUDevice final : public ScriptWrappable {
+ DISALLOW_COPY_AND_ASSIGN(WebGPUDevice);
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ static WebGPUDevice* Create(WebGPUAdapter*);
+
+ WebGPUAdapter* adapter() const;
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ WebGPUDevice(WebGPUAdapter*);
+
+ Member<WebGPUAdapter> adapter_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WEBGPU_DEVICE_H_
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/webgpu_device.idl b/chromium/third_party/blink/renderer/modules/webgpu/webgpu_device.idl
new file mode 100644
index 00000000000..e7fb9034cc9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/webgpu_device.idl
@@ -0,0 +1,9 @@
+// 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.
+
+[
+ RuntimeEnabled=WebGPU
+] interface WebGPUDevice {
+ readonly attribute WebGPUAdapter adapter;
+};
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/window_webgpu.cc b/chromium/third_party/blink/renderer/modules/webgpu/window_webgpu.cc
new file mode 100644
index 00000000000..1a578453d91
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/window_webgpu.cc
@@ -0,0 +1,45 @@
+// 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/modules/webgpu/window_webgpu.h"
+
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/modules/webgpu/webgpu.h"
+
+namespace blink {
+
+const char WindowWebGPU::kSupplementName[] = "WindowWebGPU";
+
+// static
+WindowWebGPU& WindowWebGPU::From(LocalDOMWindow& window) {
+ WindowWebGPU* supplement =
+ Supplement<LocalDOMWindow>::From<WindowWebGPU>(window);
+ if (!supplement) {
+ supplement = new WindowWebGPU(window);
+ ProvideTo(window, supplement);
+ }
+ return *supplement;
+}
+
+// static
+WebGPU* WindowWebGPU::webgpu(LocalDOMWindow& window) {
+ return WindowWebGPU::From(window).webgpu();
+}
+
+WebGPU* WindowWebGPU::webgpu() const {
+ if (!webgpu_) {
+ webgpu_ = WebGPU::Create();
+ }
+ return webgpu_.Get();
+}
+
+void WindowWebGPU::Trace(blink::Visitor* visitor) {
+ visitor->Trace(webgpu_);
+ Supplement<LocalDOMWindow>::Trace(visitor);
+}
+
+WindowWebGPU::WindowWebGPU(LocalDOMWindow& window)
+ : Supplement<LocalDOMWindow>(window) {}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/window_webgpu.h b/chromium/third_party/blink/renderer/modules/webgpu/window_webgpu.h
new file mode 100644
index 00000000000..426040f0ce1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/window_webgpu.h
@@ -0,0 +1,37 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WINDOW_WEBGPU_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WINDOW_WEBGPU_H_
+
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/supplementable.h"
+
+namespace blink {
+
+class WebGPU;
+class LocalDOMWindow;
+
+class WindowWebGPU final : public GarbageCollected<WindowWebGPU>,
+ public Supplement<LocalDOMWindow> {
+ USING_GARBAGE_COLLECTED_MIXIN(WindowWebGPU);
+
+ public:
+ static const char kSupplementName[];
+
+ static WindowWebGPU& From(LocalDOMWindow&);
+ static WebGPU* webgpu(LocalDOMWindow&);
+ WebGPU* webgpu() const;
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ explicit WindowWebGPU(LocalDOMWindow&);
+
+ mutable Member<WebGPU> webgpu_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_WINDOW_WEBGPU_H_
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/window_webgpu.idl b/chromium/third_party/blink/renderer/modules/webgpu/window_webgpu.idl
new file mode 100644
index 00000000000..344cd7d93db
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/window_webgpu.idl
@@ -0,0 +1,10 @@
+// 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.
+
+[
+ RuntimeEnabled=WebGPU,
+ ImplementedAs=WindowWebGPU
+] partial interface Window {
+ [Replaceable, SameObject] readonly attribute WebGPU webgpu;
+};
diff --git a/chromium/third_party/blink/renderer/modules/webmidi/midi_access_initializer.cc b/chromium/third_party/blink/renderer/modules/webmidi/midi_access_initializer.cc
index 95c8e3281ab..33a8b5b3175 100644
--- a/chromium/third_party/blink/renderer/modules/webmidi/midi_access_initializer.cc
+++ b/chromium/third_party/blink/renderer/modules/webmidi/midi_access_initializer.cc
@@ -10,7 +10,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/navigator.h"
@@ -100,13 +99,14 @@ void MIDIAccessInitializer::DidStartSession(Result result) {
std::move(accessor_), options_.hasSysex() && options_.sysex(),
port_descriptors_, GetExecutionContext()));
case Result::NOT_SUPPORTED:
- return Reject(DOMException::Create(kNotSupportedError));
+ return Reject(DOMException::Create(DOMExceptionCode::kNotSupportedError));
case Result::INITIALIZATION_ERROR:
- return Reject(DOMException::Create(
- kInvalidStateError, "Platform dependent initialization failed."));
+ return Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "Platform dependent initialization failed."));
}
NOTREACHED();
- Reject(DOMException::Create(kInvalidStateError,
+ Reject(DOMException::Create(DOMExceptionCode::kInvalidStateError,
"Unknown internal error occurred."));
}
@@ -119,7 +119,7 @@ void MIDIAccessInitializer::OnPermissionsUpdated(PermissionStatus status) {
if (status == PermissionStatus::GRANTED)
accessor_->StartSession();
else
- Reject(DOMException::Create(kSecurityError));
+ Reject(DOMException::Create(DOMExceptionCode::kSecurityError));
}
void MIDIAccessInitializer::OnPermissionUpdated(PermissionStatus status) {
@@ -127,7 +127,7 @@ void MIDIAccessInitializer::OnPermissionUpdated(PermissionStatus status) {
if (status == PermissionStatus::GRANTED)
accessor_->StartSession();
else
- Reject(DOMException::Create(kSecurityError));
+ Reject(DOMException::Create(DOMExceptionCode::kSecurityError));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webmidi/midi_output.cc b/chromium/third_party/blink/renderer/modules/webmidi/midi_output.cc
index ce2b69eae43..2c712d16ac9 100644
--- a/chromium/third_party/blink/renderer/modules/webmidi/midi_output.cc
+++ b/chromium/third_party/blink/renderer/modules/webmidi/midi_output.cc
@@ -31,9 +31,7 @@
#include "third_party/blink/renderer/modules/webmidi/midi_output.h"
#include "media/midi/midi_service.mojom-blink.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/exception_code.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/use_counter.h"
@@ -42,6 +40,7 @@
#include "third_party/blink/renderer/core/timing/worker_global_scope_performance.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
#include "third_party/blink/renderer/modules/webmidi/midi_access.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
using midi::mojom::PortState;
@@ -116,7 +115,7 @@ class MessageValidator {
if (IsSysex()) {
if (!sysex_enabled) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"System exclusive message is not allowed " + GetPositionString());
return false;
}
diff --git a/chromium/third_party/blink/renderer/modules/webmidi/midi_port.cc b/chromium/third_party/blink/renderer/modules/webmidi/midi_port.cc
index f18eb85e43f..48a502e4425 100644
--- a/chromium/third_party/blink/renderer/modules/webmidi/midi_port.cc
+++ b/chromium/third_party/blink/renderer/modules/webmidi/midi_port.cc
@@ -192,11 +192,6 @@ void MIDIPort::Trace(blink::Visitor* visitor) {
ContextLifecycleObserver::Trace(visitor);
}
-void MIDIPort::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(access_);
- EventTargetWithInlineData::TraceWrappers(visitor);
-}
-
void MIDIPort::OpenAsynchronously(ScriptPromiseResolver* resolver) {
// The frame should exist, but it may be already detached and the execution
// context may be lost here.
@@ -245,13 +240,6 @@ ScriptPromise MIDIPort::Accept(ScriptState* script_state) {
script_state->GetIsolate()));
}
-ScriptPromise MIDIPort::Reject(ScriptState* script_state,
- ExceptionCode ec,
- const String& message) {
- return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(ec, message));
-}
-
void MIDIPort::SetStates(PortState state, ConnectionState connection) {
DCHECK(state != PortState::DISCONNECTED ||
connection != kConnectionStateOpen);
diff --git a/chromium/third_party/blink/renderer/modules/webmidi/midi_port.h b/chromium/third_party/blink/renderer/modules/webmidi/midi_port.h
index f3c1783d4a6..c8e43429c0b 100644
--- a/chromium/third_party/blink/renderer/modules/webmidi/midi_port.h
+++ b/chromium/third_party/blink/renderer/modules/webmidi/midi_port.h
@@ -36,7 +36,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
#include "third_party/blink/renderer/modules/webmidi/midi_accessor.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
@@ -80,8 +79,6 @@ class MIDIPort : public EventTargetWithInlineData,
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
DEFINE_ATTRIBUTE_EVENT_LISTENER(statechange);
// EventTarget
@@ -115,7 +112,6 @@ class MIDIPort : public EventTargetWithInlineData,
void CloseAsynchronously(ScriptPromiseResolver*);
ScriptPromise Accept(ScriptState*);
- ScriptPromise Reject(ScriptState*, ExceptionCode, const String& message);
void SetStates(midi::mojom::PortState, ConnectionState);
diff --git a/chromium/third_party/blink/renderer/modules/webmidi/midi_port_map.h b/chromium/third_party/blink/renderer/modules/webmidi/midi_port_map.h
index a4c4bfb0fb6..5961c6b1f8a 100644
--- a/chromium/third_party/blink/renderer/modules/webmidi/midi_port_map.h
+++ b/chromium/third_party/blink/renderer/modules/webmidi/midi_port_map.h
@@ -5,9 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBMIDI_MIDI_PORT_MAP_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBMIDI_MIDI_PORT_MAP_H_
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
diff --git a/chromium/third_party/blink/renderer/modules/webmidi/navigator_web_midi.cc b/chromium/third_party/blink/renderer/modules/webmidi/navigator_web_midi.cc
index 6cfdfe1888a..4185a3532d4 100644
--- a/chromium/third_party/blink/renderer/modules/webmidi/navigator_web_midi.cc
+++ b/chromium/third_party/blink/renderer/modules/webmidi/navigator_web_midi.cc
@@ -85,8 +85,8 @@ ScriptPromise NavigatorWebMIDI::requestMIDIAccess(ScriptState* script_state,
const MIDIOptions& options) {
if (!script_state->ContextIsValid()) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kAbortError, "The frame is not working."));
+ script_state, DOMException::Create(DOMExceptionCode::kAbortError,
+ "The frame is not working."));
}
Document& document = *ToDocument(ExecutionContext::From(script_state));
@@ -110,8 +110,8 @@ ScriptPromise NavigatorWebMIDI::requestMIDIAccess(ScriptState* script_state,
ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel,
kFeaturePolicyConsoleWarning));
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kSecurityError, kFeaturePolicyErrorMessage));
+ script_state, DOMException::Create(DOMExceptionCode::kSecurityError,
+ kFeaturePolicyErrorMessage));
}
} else {
Deprecation::CountDeprecationFeaturePolicy(
diff --git a/chromium/third_party/blink/renderer/modules/webshare/navigator_share.cc b/chromium/third_party/blink/renderer/modules/webshare/navigator_share.cc
index e11415a16f6..dca964a2ab1 100644
--- a/chromium/third_party/blink/renderer/modules/webshare/navigator_share.cc
+++ b/chromium/third_party/blink/renderer/modules/webshare/navigator_share.cc
@@ -8,7 +8,6 @@
#include "third_party/blink/public/platform/platform.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/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/navigator.h"
@@ -69,13 +68,14 @@ void NavigatorShare::ShareClientImpl::Callback(mojom::blink::ShareError error) {
if (error == mojom::blink::ShareError::OK) {
resolver_->Resolve();
} else {
- resolver_->Reject(DOMException::Create(kAbortError, ErrorToString(error)));
+ resolver_->Reject(DOMException::Create(DOMExceptionCode::kAbortError,
+ ErrorToString(error)));
}
}
void NavigatorShare::ShareClientImpl::OnConnectionError() {
resolver_->Reject(DOMException::Create(
- kAbortError,
+ DOMExceptionCode::kAbortError,
"Internal error: could not connect to Web Share interface."));
}
@@ -122,7 +122,7 @@ ScriptPromise NavigatorShare::share(ScriptState* script_state,
if (!Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr)) {
DOMException* error = DOMException::Create(
- kNotAllowedError,
+ DOMExceptionCode::kNotAllowedError,
"Must be handling a user gesture to perform a share request.");
return ScriptPromise::RejectWithDOMException(script_state, error);
}
@@ -131,7 +131,7 @@ ScriptPromise NavigatorShare::share(ScriptState* script_state,
LocalFrame* frame = doc->GetFrame();
if (!frame) {
DOMException* error =
- DOMException::Create(kAbortError,
+ DOMException::Create(DOMExceptionCode::kAbortError,
"Internal error: document frame is missing (the "
"navigator may be detached).");
return ScriptPromise::RejectWithDOMException(script_state, error);
diff --git a/chromium/third_party/blink/renderer/modules/websockets/dom_websocket.cc b/chromium/third_party/blink/renderer/modules/websockets/dom_websocket.cc
index ff4dcf57e21..75126c8edfb 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/dom_websocket.cc
+++ b/chromium/third_party/blink/renderer/modules/websockets/dom_websocket.cc
@@ -33,12 +33,10 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_insecure_request_policy.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/bindings/core/v8/script_controller.h"
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/bindings/core/v8/string_or_string_sequence.h"
#include "third_party/blink/renderer/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#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/execution_context/security_context.h"
@@ -51,6 +49,7 @@
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
#include "third_party/blink/renderer/modules/websockets/close_event.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/network/network_log.h"
@@ -212,7 +211,7 @@ static String JoinStrings(const Vector<String>& strings,
}
static void SetInvalidStateErrorForSendMethod(ExceptionState& exception_state) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Still in CONNECTING state.");
}
@@ -259,30 +258,30 @@ DOMWebSocket* DOMWebSocket::Create(ExecutionContext* context,
ExceptionState& exception_state) {
if (url.IsNull()) {
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"Failed to create a WebSocket: the provided URL is invalid.");
return nullptr;
}
- DOMWebSocket* web_socket = new DOMWebSocket(context);
- web_socket->PauseIfNeeded();
+ DOMWebSocket* websocket = new DOMWebSocket(context);
+ websocket->PauseIfNeeded();
if (protocols.IsNull()) {
Vector<String> protocols_vector;
- web_socket->Connect(url, protocols_vector, exception_state);
+ websocket->Connect(url, protocols_vector, exception_state);
} else if (protocols.IsString()) {
Vector<String> protocols_vector;
protocols_vector.push_back(protocols.GetAsString());
- web_socket->Connect(url, protocols_vector, exception_state);
+ websocket->Connect(url, protocols_vector, exception_state);
} else {
DCHECK(protocols.IsStringSequence());
- web_socket->Connect(url, protocols.GetAsStringSequence(), exception_state);
+ websocket->Connect(url, protocols.GetAsStringSequence(), exception_state);
}
if (exception_state.HadException())
return nullptr;
- return web_socket;
+ return websocket;
}
void DOMWebSocket::Connect(const String& url,
@@ -305,22 +304,23 @@ void DOMWebSocket::Connect(const String& url,
if (!url_.IsValid()) {
state_ = kClosed;
- exception_state.ThrowDOMException(kSyntaxError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError,
"The URL '" + url + "' is invalid.");
return;
}
if (!url_.ProtocolIs("ws") && !url_.ProtocolIs("wss")) {
state_ = kClosed;
exception_state.ThrowDOMException(
- kSyntaxError, "The URL's scheme must be either 'ws' or 'wss'. '" +
- url_.Protocol() + "' is not allowed.");
+ DOMExceptionCode::kSyntaxError,
+ "The URL's scheme must be either 'ws' or 'wss'. '" + url_.Protocol() +
+ "' is not allowed.");
return;
}
if (url_.HasFragmentIdentifier()) {
state_ = kClosed;
exception_state.ThrowDOMException(
- kSyntaxError,
+ DOMExceptionCode::kSyntaxError,
"The URL contains a fragment identifier ('" +
url_.FragmentIdentifier() +
"'). Fragment identifiers are not allowed in WebSocket URLs.");
@@ -353,9 +353,9 @@ void DOMWebSocket::Connect(const String& url,
if (!IsValidSubprotocolString(protocols[i])) {
state_ = kClosed;
exception_state.ThrowDOMException(
- kSyntaxError, "The subprotocol '" +
- EncodeSubprotocolString(protocols[i]) +
- "' is invalid.");
+ DOMExceptionCode::kSyntaxError,
+ "The subprotocol '" + EncodeSubprotocolString(protocols[i]) +
+ "' is invalid.");
return;
}
}
@@ -366,9 +366,9 @@ void DOMWebSocket::Connect(const String& url,
if (!visited.insert(protocols[i]).is_new_entry) {
state_ = kClosed;
exception_state.ThrowDOMException(
- kSyntaxError, "The subprotocol '" +
- EncodeSubprotocolString(protocols[i]) +
- "' is duplicated.");
+ DOMExceptionCode::kSyntaxError,
+ "The subprotocol '" + EncodeSubprotocolString(protocols[i]) +
+ "' is duplicated.");
return;
}
}
@@ -542,7 +542,7 @@ void DOMWebSocket::CloseInternal(int code,
(WebSocketChannel::kCloseEventCodeMinimumUserDefined <= code &&
code <= WebSocketChannel::kCloseEventCodeMaximumUserDefined))) {
exception_state.ThrowDOMException(
- kInvalidAccessError,
+ DOMExceptionCode::kInvalidAccessError,
"The code must be either 1000, or between 3000 and 4999. " +
String::Number(code) + " is neither.");
return;
@@ -552,8 +552,9 @@ void DOMWebSocket::CloseInternal(int code,
CString utf8 = reason.Utf8();
if (utf8.length() > kMaxReasonSizeInBytes) {
exception_state.ThrowDOMException(
- kSyntaxError, "The message must not be greater than " +
- String::Number(kMaxReasonSizeInBytes) + " bytes.");
+ DOMExceptionCode::kSyntaxError,
+ "The message must not be greater than " +
+ String::Number(kMaxReasonSizeInBytes) + " bytes.");
return;
}
if (!reason.IsEmpty() && !reason.Is8Bit()) {
diff --git a/chromium/third_party/blink/renderer/modules/websockets/dom_websocket_test.cc b/chromium/third_party/blink/renderer/modules/websockets/dom_websocket_test.cc
index c80c04d727f..a1cc7d17cf7 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/dom_websocket_test.cc
+++ b/chromium/third_party/blink/renderer/modules/websockets/dom_websocket_test.cc
@@ -9,16 +9,15 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_insecure_request_policy.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.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/core/dom/document.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/execution_context/security_context.h"
#include "third_party/blink/renderer/core/fileapi/blob.h"
#include "third_party/blink/renderer/core/inspector/console_types.h"
#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/text/cstring.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -135,165 +134,169 @@ class DOMWebSocketTestScope {
TEST(DOMWebSocketTest, connectToBadURL) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
- web_socket_scope.Socket().Connect("xxx", Vector<String>(),
- scope.GetExceptionState());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
+ websocket_scope.Socket().Connect("xxx", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(kSyntaxError, scope.GetExceptionState().Code());
+ EXPECT_EQ(DOMExceptionCode::kSyntaxError,
+ scope.GetExceptionState().CodeAs<DOMExceptionCode>());
EXPECT_EQ("The URL 'xxx' is invalid.", scope.GetExceptionState().Message());
- EXPECT_EQ(DOMWebSocket::kClosed, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosed, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, connectToNonWsURL) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
- web_socket_scope.Socket().Connect("http://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
+ websocket_scope.Socket().Connect("http://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(kSyntaxError, scope.GetExceptionState().Code());
+ EXPECT_EQ(DOMExceptionCode::kSyntaxError,
+ scope.GetExceptionState().CodeAs<DOMExceptionCode>());
EXPECT_EQ(
"The URL's scheme must be either 'ws' or 'wss'. 'http' is not allowed.",
scope.GetExceptionState().Message());
- EXPECT_EQ(DOMWebSocket::kClosed, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosed, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, connectToURLHavingFragmentIdentifier) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
- web_socket_scope.Socket().Connect("ws://example.com/#fragment",
- Vector<String>(),
- scope.GetExceptionState());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
+ websocket_scope.Socket().Connect("ws://example.com/#fragment",
+ Vector<String>(), scope.GetExceptionState());
EXPECT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(kSyntaxError, scope.GetExceptionState().Code());
+ EXPECT_EQ(DOMExceptionCode::kSyntaxError,
+ scope.GetExceptionState().CodeAs<DOMExceptionCode>());
EXPECT_EQ(
"The URL contains a fragment identifier ('fragment'). Fragment "
"identifiers are not allowed in WebSocket URLs.",
scope.GetExceptionState().Message());
- EXPECT_EQ(DOMWebSocket::kClosed, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosed, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, invalidPort) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
- web_socket_scope.Socket().Connect("ws://example.com:7", Vector<String>(),
- scope.GetExceptionState());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
+ websocket_scope.Socket().Connect("ws://example.com:7", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(kSecurityError, scope.GetExceptionState().Code());
+ EXPECT_EQ(DOMExceptionCode::kSecurityError,
+ scope.GetExceptionState().CodeAs<DOMExceptionCode>());
EXPECT_EQ("The port 7 is not allowed.", scope.GetExceptionState().Message());
- EXPECT_EQ(DOMWebSocket::kClosed, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosed, websocket_scope.Socket().readyState());
}
// FIXME: Add a test for Content Security Policy.
TEST(DOMWebSocketTest, invalidSubprotocols) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
Vector<String> subprotocols;
subprotocols.push_back("@subprotocol-|'\"x\x01\x02\x03x");
- web_socket_scope.Socket().Connect("ws://example.com/", subprotocols,
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", subprotocols,
+ scope.GetExceptionState());
EXPECT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(kSyntaxError, scope.GetExceptionState().Code());
+ EXPECT_EQ(DOMExceptionCode::kSyntaxError,
+ scope.GetExceptionState().CodeAs<DOMExceptionCode>());
EXPECT_EQ(
"The subprotocol '@subprotocol-|'\"x\\u0001\\u0002\\u0003x' is invalid.",
scope.GetExceptionState().Message());
- EXPECT_EQ(DOMWebSocket::kClosed, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosed, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, insecureRequestsUpgrade) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("wss://example.com/endpoint"), String()))
.WillOnce(Return(true));
}
scope.GetDocument().SetInsecureRequestPolicy(kUpgradeInsecureRequests);
- web_socket_scope.Socket().Connect(
- "ws://example.com/endpoint", Vector<String>(), scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/endpoint",
+ Vector<String>(), scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kConnecting, web_socket_scope.Socket().readyState());
- EXPECT_EQ(KURL("wss://example.com/endpoint"),
- web_socket_scope.Socket().url());
+ EXPECT_EQ(DOMWebSocket::kConnecting, websocket_scope.Socket().readyState());
+ EXPECT_EQ(KURL("wss://example.com/endpoint"), websocket_scope.Socket().url());
}
TEST(DOMWebSocketTest, insecureRequestsDoNotUpgrade) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/endpoint"), String()))
.WillOnce(Return(true));
}
scope.GetDocument().SetInsecureRequestPolicy(kLeaveInsecureRequestsAlone);
- web_socket_scope.Socket().Connect(
- "ws://example.com/endpoint", Vector<String>(), scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/endpoint",
+ Vector<String>(), scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kConnecting, web_socket_scope.Socket().readyState());
- EXPECT_EQ(KURL("ws://example.com/endpoint"), web_socket_scope.Socket().url());
+ EXPECT_EQ(DOMWebSocket::kConnecting, websocket_scope.Socket().readyState());
+ EXPECT_EQ(KURL("ws://example.com/endpoint"), websocket_scope.Socket().url());
}
TEST(DOMWebSocketTest, channelConnectSuccess) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
Vector<String> subprotocols;
subprotocols.push_back("aa");
subprotocols.push_back("bb");
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/hoge"), String("aa, bb")))
.WillOnce(Return(true));
}
- web_socket_scope.Socket().Connect("ws://example.com/hoge",
- Vector<String>(subprotocols),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/hoge",
+ Vector<String>(subprotocols),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kConnecting, web_socket_scope.Socket().readyState());
- EXPECT_EQ(KURL("ws://example.com/hoge"), web_socket_scope.Socket().url());
+ EXPECT_EQ(DOMWebSocket::kConnecting, websocket_scope.Socket().readyState());
+ EXPECT_EQ(KURL("ws://example.com/hoge"), websocket_scope.Socket().url());
}
TEST(DOMWebSocketTest, channelConnectFail) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
Vector<String> subprotocols;
subprotocols.push_back("aa");
subprotocols.push_back("bb");
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String("aa, bb")))
.WillOnce(Return(false));
- EXPECT_CALL(web_socket_scope.Channel(), Disconnect());
+ EXPECT_CALL(websocket_scope.Channel(), Disconnect());
}
- web_socket_scope.Socket().Connect("ws://example.com/",
- Vector<String>(subprotocols),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/",
+ Vector<String>(subprotocols),
+ scope.GetExceptionState());
EXPECT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(kSecurityError, scope.GetExceptionState().Code());
+ EXPECT_EQ(DOMExceptionCode::kSecurityError,
+ scope.GetExceptionState().CodeAs<DOMExceptionCode>());
EXPECT_EQ(
"An insecure WebSocket connection may not be initiated from a page "
"loaded over HTTPS.",
scope.GetExceptionState().Message());
- EXPECT_EQ(DOMWebSocket::kClosed, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosed, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, isValidSubprotocolString) {
@@ -324,480 +327,483 @@ TEST(DOMWebSocketTest, isValidSubprotocolString) {
TEST(DOMWebSocketTest, connectSuccess) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
Vector<String> subprotocols;
subprotocols.push_back("aa");
subprotocols.push_back("bb");
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String("aa, bb")))
.WillOnce(Return(true));
}
- web_socket_scope.Socket().Connect("ws://example.com/", subprotocols,
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", subprotocols,
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kConnecting, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kConnecting, websocket_scope.Socket().readyState());
- web_socket_scope.Socket().DidConnect("bb", "cc");
+ websocket_scope.Socket().DidConnect("bb", "cc");
- EXPECT_EQ(DOMWebSocket::kOpen, web_socket_scope.Socket().readyState());
- EXPECT_EQ("bb", web_socket_scope.Socket().protocol());
- EXPECT_EQ("cc", web_socket_scope.Socket().extensions());
+ EXPECT_EQ(DOMWebSocket::kOpen, websocket_scope.Socket().readyState());
+ EXPECT_EQ("bb", websocket_scope.Socket().protocol());
+ EXPECT_EQ("cc", websocket_scope.Socket().extensions());
}
TEST(DOMWebSocketTest, didClose) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
- EXPECT_CALL(web_socket_scope.Channel(), Disconnect());
+ EXPECT_CALL(websocket_scope.Channel(), Disconnect());
}
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kConnecting, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kConnecting, websocket_scope.Socket().readyState());
- web_socket_scope.Socket().DidClose(
+ websocket_scope.Socket().DidClose(
WebSocketChannelClient::kClosingHandshakeIncomplete, 1006, "");
- EXPECT_EQ(DOMWebSocket::kClosed, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosed, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, maximumReasonSize) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
- EXPECT_CALL(web_socket_scope.Channel(), FailMock(_, _, _));
+ EXPECT_CALL(websocket_scope.Channel(), FailMock(_, _, _));
}
StringBuilder reason;
for (size_t i = 0; i < 123; ++i)
reason.Append('a');
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kConnecting, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kConnecting, websocket_scope.Socket().readyState());
- web_socket_scope.Socket().close(1000, reason.ToString(),
- scope.GetExceptionState());
+ websocket_scope.Socket().close(1000, reason.ToString(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kClosing, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosing, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, reasonSizeExceeding) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
}
StringBuilder reason;
for (size_t i = 0; i < 124; ++i)
reason.Append('a');
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kConnecting, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kConnecting, websocket_scope.Socket().readyState());
- web_socket_scope.Socket().close(1000, reason.ToString(),
- scope.GetExceptionState());
+ websocket_scope.Socket().close(1000, reason.ToString(),
+ scope.GetExceptionState());
EXPECT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(kSyntaxError, scope.GetExceptionState().Code());
+ EXPECT_EQ(DOMExceptionCode::kSyntaxError,
+ scope.GetExceptionState().CodeAs<DOMExceptionCode>());
EXPECT_EQ("The message must not be greater than 123 bytes.",
scope.GetExceptionState().Message());
- EXPECT_EQ(DOMWebSocket::kConnecting, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kConnecting, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, closeWhenConnecting) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
EXPECT_CALL(
- web_socket_scope.Channel(),
+ websocket_scope.Channel(),
FailMock(
String("WebSocket is closed before the connection is established."),
kWarningMessageLevel, _));
}
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kConnecting, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kConnecting, websocket_scope.Socket().readyState());
- web_socket_scope.Socket().close(1000, "bye", scope.GetExceptionState());
+ websocket_scope.Socket().close(1000, "bye", scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kClosing, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosing, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, close) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
- EXPECT_CALL(web_socket_scope.Channel(), Close(3005, String("bye")));
+ EXPECT_CALL(websocket_scope.Channel(), Close(3005, String("bye")));
}
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kConnecting, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kConnecting, websocket_scope.Socket().readyState());
- web_socket_scope.Socket().DidConnect("", "");
- EXPECT_EQ(DOMWebSocket::kOpen, web_socket_scope.Socket().readyState());
- web_socket_scope.Socket().close(3005, "bye", scope.GetExceptionState());
+ websocket_scope.Socket().DidConnect("", "");
+ EXPECT_EQ(DOMWebSocket::kOpen, websocket_scope.Socket().readyState());
+ websocket_scope.Socket().close(3005, "bye", scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kClosing, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosing, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, closeWithoutReason) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
- EXPECT_CALL(web_socket_scope.Channel(), Close(3005, String()));
+ EXPECT_CALL(websocket_scope.Channel(), Close(3005, String()));
}
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kConnecting, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kConnecting, websocket_scope.Socket().readyState());
- web_socket_scope.Socket().DidConnect("", "");
- EXPECT_EQ(DOMWebSocket::kOpen, web_socket_scope.Socket().readyState());
- web_socket_scope.Socket().close(3005, scope.GetExceptionState());
+ websocket_scope.Socket().DidConnect("", "");
+ EXPECT_EQ(DOMWebSocket::kOpen, websocket_scope.Socket().readyState());
+ websocket_scope.Socket().close(3005, scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kClosing, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosing, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, closeWithoutCodeAndReason) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
- EXPECT_CALL(web_socket_scope.Channel(), Close(-1, String()));
+ EXPECT_CALL(websocket_scope.Channel(), Close(-1, String()));
}
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kConnecting, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kConnecting, websocket_scope.Socket().readyState());
- web_socket_scope.Socket().DidConnect("", "");
- EXPECT_EQ(DOMWebSocket::kOpen, web_socket_scope.Socket().readyState());
- web_socket_scope.Socket().close(scope.GetExceptionState());
+ websocket_scope.Socket().DidConnect("", "");
+ EXPECT_EQ(DOMWebSocket::kOpen, websocket_scope.Socket().readyState());
+ websocket_scope.Socket().close(scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kClosing, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosing, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, closeWhenClosing) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
- EXPECT_CALL(web_socket_scope.Channel(), Close(-1, String()));
+ EXPECT_CALL(websocket_scope.Channel(), Close(-1, String()));
}
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kConnecting, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kConnecting, websocket_scope.Socket().readyState());
- web_socket_scope.Socket().DidConnect("", "");
- EXPECT_EQ(DOMWebSocket::kOpen, web_socket_scope.Socket().readyState());
- web_socket_scope.Socket().close(scope.GetExceptionState());
+ websocket_scope.Socket().DidConnect("", "");
+ EXPECT_EQ(DOMWebSocket::kOpen, websocket_scope.Socket().readyState());
+ websocket_scope.Socket().close(scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kClosing, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosing, websocket_scope.Socket().readyState());
- web_socket_scope.Socket().close(scope.GetExceptionState());
+ websocket_scope.Socket().close(scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kClosing, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosing, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, closeWhenClosed) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
- EXPECT_CALL(web_socket_scope.Channel(), Close(-1, String()));
- EXPECT_CALL(web_socket_scope.Channel(), Disconnect());
+ EXPECT_CALL(websocket_scope.Channel(), Close(-1, String()));
+ EXPECT_CALL(websocket_scope.Channel(), Disconnect());
}
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kConnecting, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kConnecting, websocket_scope.Socket().readyState());
- web_socket_scope.Socket().DidConnect("", "");
- EXPECT_EQ(DOMWebSocket::kOpen, web_socket_scope.Socket().readyState());
- web_socket_scope.Socket().close(scope.GetExceptionState());
+ websocket_scope.Socket().DidConnect("", "");
+ EXPECT_EQ(DOMWebSocket::kOpen, websocket_scope.Socket().readyState());
+ websocket_scope.Socket().close(scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kClosing, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosing, websocket_scope.Socket().readyState());
- web_socket_scope.Socket().DidClose(
+ websocket_scope.Socket().DidClose(
WebSocketChannelClient::kClosingHandshakeComplete, 1000, String());
- EXPECT_EQ(DOMWebSocket::kClosed, web_socket_scope.Socket().readyState());
- web_socket_scope.Socket().close(scope.GetExceptionState());
+ EXPECT_EQ(DOMWebSocket::kClosed, websocket_scope.Socket().readyState());
+ websocket_scope.Socket().close(scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kClosed, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosed, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, sendStringWhenConnecting) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
}
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- web_socket_scope.Socket().send("hello", scope.GetExceptionState());
+ websocket_scope.Socket().send("hello", scope.GetExceptionState());
EXPECT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(kInvalidStateError, scope.GetExceptionState().Code());
+ EXPECT_EQ(DOMExceptionCode::kInvalidStateError,
+ scope.GetExceptionState().CodeAs<DOMExceptionCode>());
EXPECT_EQ("Still in CONNECTING state.", scope.GetExceptionState().Message());
- EXPECT_EQ(DOMWebSocket::kConnecting, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kConnecting, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, sendStringWhenClosing) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
Checkpoint checkpoint;
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
- EXPECT_CALL(web_socket_scope.Channel(), FailMock(_, _, _));
+ EXPECT_CALL(websocket_scope.Channel(), FailMock(_, _, _));
}
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- web_socket_scope.Socket().close(scope.GetExceptionState());
+ websocket_scope.Socket().close(scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- web_socket_scope.Socket().send("hello", scope.GetExceptionState());
+ websocket_scope.Socket().send("hello", scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kClosing, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosing, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, sendStringWhenClosed) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
Checkpoint checkpoint;
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
- EXPECT_CALL(web_socket_scope.Channel(), Disconnect());
+ EXPECT_CALL(websocket_scope.Channel(), Disconnect());
EXPECT_CALL(checkpoint, Call(1));
}
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- web_socket_scope.Socket().DidClose(
+ websocket_scope.Socket().DidClose(
WebSocketChannelClient::kClosingHandshakeIncomplete, 1006, "");
checkpoint.Call(1);
- web_socket_scope.Socket().send("hello", scope.GetExceptionState());
+ websocket_scope.Socket().send("hello", scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kClosed, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosed, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, sendStringSuccess) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
- EXPECT_CALL(web_socket_scope.Channel(), Send(CString("hello")));
+ EXPECT_CALL(websocket_scope.Channel(), Send(CString("hello")));
}
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- web_socket_scope.Socket().DidConnect("", "");
- web_socket_scope.Socket().send("hello", scope.GetExceptionState());
+ websocket_scope.Socket().DidConnect("", "");
+ websocket_scope.Socket().send("hello", scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kOpen, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kOpen, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, sendNonLatin1String) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Send(CString("\xe7\x8b\x90\xe0\xa4\x94")));
}
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- web_socket_scope.Socket().DidConnect("", "");
+ websocket_scope.Socket().DidConnect("", "");
UChar non_latin1_string[] = {0x72d0, 0x0914, 0x0000};
- web_socket_scope.Socket().send(non_latin1_string, scope.GetExceptionState());
+ websocket_scope.Socket().send(non_latin1_string, scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kOpen, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kOpen, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, sendArrayBufferWhenConnecting) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
DOMArrayBufferView* view = DOMUint8Array::Create(8);
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
}
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- web_socket_scope.Socket().send(view->buffer(), scope.GetExceptionState());
+ websocket_scope.Socket().send(view->buffer(), scope.GetExceptionState());
EXPECT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(kInvalidStateError, scope.GetExceptionState().Code());
+ EXPECT_EQ(DOMExceptionCode::kInvalidStateError,
+ scope.GetExceptionState().CodeAs<DOMExceptionCode>());
EXPECT_EQ("Still in CONNECTING state.", scope.GetExceptionState().Message());
- EXPECT_EQ(DOMWebSocket::kConnecting, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kConnecting, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, sendArrayBufferWhenClosing) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
DOMArrayBufferView* view = DOMUint8Array::Create(8);
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
- EXPECT_CALL(web_socket_scope.Channel(), FailMock(_, _, _));
+ EXPECT_CALL(websocket_scope.Channel(), FailMock(_, _, _));
}
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- web_socket_scope.Socket().close(scope.GetExceptionState());
+ websocket_scope.Socket().close(scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- web_socket_scope.Socket().send(view->buffer(), scope.GetExceptionState());
+ websocket_scope.Socket().send(view->buffer(), scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kClosing, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosing, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, sendArrayBufferWhenClosed) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
Checkpoint checkpoint;
DOMArrayBufferView* view = DOMUint8Array::Create(8);
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
- EXPECT_CALL(web_socket_scope.Channel(), Disconnect());
+ EXPECT_CALL(websocket_scope.Channel(), Disconnect());
EXPECT_CALL(checkpoint, Call(1));
}
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- web_socket_scope.Socket().DidClose(
+ websocket_scope.Socket().DidClose(
WebSocketChannelClient::kClosingHandshakeIncomplete, 1006, "");
checkpoint.Call(1);
- web_socket_scope.Socket().send(view->buffer(), scope.GetExceptionState());
+ websocket_scope.Socket().send(view->buffer(), scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kClosed, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosed, websocket_scope.Socket().readyState());
}
TEST(DOMWebSocketTest, sendArrayBufferSuccess) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
DOMArrayBufferView* view = DOMUint8Array::Create(8);
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
- EXPECT_CALL(web_socket_scope.Channel(), Send(Ref(*view->buffer()), 0, 8));
+ EXPECT_CALL(websocket_scope.Channel(), Send(Ref(*view->buffer()), 0, 8));
}
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- web_socket_scope.Socket().DidConnect("", "");
- web_socket_scope.Socket().send(view->buffer(), scope.GetExceptionState());
+ websocket_scope.Socket().DidConnect("", "");
+ websocket_scope.Socket().send(view->buffer(), scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kOpen, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kOpen, websocket_scope.Socket().readyState());
}
// FIXME: We should have Blob tests here.
@@ -809,16 +815,16 @@ TEST(DOMWebSocketTest, sendArrayBufferSuccess) {
TEST(DOMWebSocketTest, binaryType) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
- EXPECT_EQ("blob", web_socket_scope.Socket().binaryType());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
+ EXPECT_EQ("blob", websocket_scope.Socket().binaryType());
- web_socket_scope.Socket().setBinaryType("arraybuffer");
+ websocket_scope.Socket().setBinaryType("arraybuffer");
- EXPECT_EQ("arraybuffer", web_socket_scope.Socket().binaryType());
+ EXPECT_EQ("arraybuffer", websocket_scope.Socket().binaryType());
- web_socket_scope.Socket().setBinaryType("blob");
+ websocket_scope.Socket().setBinaryType("blob");
- EXPECT_EQ("blob", web_socket_scope.Socket().binaryType());
+ EXPECT_EQ("blob", websocket_scope.Socket().binaryType());
}
// FIXME: We should add tests for suspend / resume.
@@ -828,24 +834,24 @@ class DOMWebSocketValidClosingTest
TEST_P(DOMWebSocketValidClosingTest, test) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
- EXPECT_CALL(web_socket_scope.Channel(), FailMock(_, _, _));
+ EXPECT_CALL(websocket_scope.Channel(), FailMock(_, _, _));
}
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kConnecting, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kConnecting, websocket_scope.Socket().readyState());
- web_socket_scope.Socket().close(GetParam(), "bye", scope.GetExceptionState());
+ websocket_scope.Socket().close(GetParam(), "bye", scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kClosing, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kClosing, websocket_scope.Socket().readyState());
}
INSTANTIATE_TEST_CASE_P(DOMWebSocketValidClosing,
@@ -857,28 +863,29 @@ class DOMWebSocketInvalidClosingCodeTest
TEST_P(DOMWebSocketInvalidClosingCodeTest, test) {
V8TestingScope scope;
- DOMWebSocketTestScope web_socket_scope(scope.GetExecutionContext());
+ DOMWebSocketTestScope websocket_scope(scope.GetExecutionContext());
{
InSequence s;
- EXPECT_CALL(web_socket_scope.Channel(),
+ EXPECT_CALL(websocket_scope.Channel(),
Connect(KURL("ws://example.com/"), String()))
.WillOnce(Return(true));
}
- web_socket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
- scope.GetExceptionState());
+ websocket_scope.Socket().Connect("ws://example.com/", Vector<String>(),
+ scope.GetExceptionState());
EXPECT_FALSE(scope.GetExceptionState().HadException());
- EXPECT_EQ(DOMWebSocket::kConnecting, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kConnecting, websocket_scope.Socket().readyState());
- web_socket_scope.Socket().close(GetParam(), "bye", scope.GetExceptionState());
+ websocket_scope.Socket().close(GetParam(), "bye", scope.GetExceptionState());
EXPECT_TRUE(scope.GetExceptionState().HadException());
- EXPECT_EQ(kInvalidAccessError, scope.GetExceptionState().Code());
+ EXPECT_EQ(DOMExceptionCode::kInvalidAccessError,
+ scope.GetExceptionState().CodeAs<DOMExceptionCode>());
EXPECT_EQ(String::Format("The code must be either 1000, or between 3000 and "
"4999. %d is neither.",
GetParam()),
scope.GetExceptionState().Message());
- EXPECT_EQ(DOMWebSocket::kConnecting, web_socket_scope.Socket().readyState());
+ EXPECT_EQ(DOMWebSocket::kConnecting, websocket_scope.Socket().readyState());
}
INSTANTIATE_TEST_CASE_P(
diff --git a/chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc b/chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc
index c83016cf108..25e05c0ded8 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl.cc
@@ -58,7 +58,6 @@
#include "third_party/blink/renderer/modules/websockets/websocket_handle_impl.h"
#include "third_party/blink/renderer/platform/loader/fetch/unique_identifier.h"
#include "third_party/blink/renderer/platform/network/network_log.h"
-#include "third_party/blink/renderer/platform/network/web_socket_handshake_request.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -130,19 +129,18 @@ WebSocketChannelImpl::BlobLoader::BlobLoader(
void WebSocketChannelImpl::BlobLoader::Cancel() {
loader_->Cancel();
- // DidFail will be called immediately.
- // |this| is deleted here.
+ loader_ = nullptr;
}
void WebSocketChannelImpl::BlobLoader::DidFinishLoading() {
channel_->DidFinishLoadingBlob(loader_->ArrayBufferResult());
- // |this| is deleted here.
+ loader_ = nullptr;
}
void WebSocketChannelImpl::BlobLoader::DidFail(
FileError::ErrorCode error_code) {
channel_->DidFailLoadingBlob(error_code);
- // |this| is deleted here.
+ loader_ = nullptr;
}
struct WebSocketChannelImpl::ConnectInfo {
@@ -547,7 +545,6 @@ void WebSocketChannelImpl::HandleDidClose(bool was_clean,
was_clean ? WebSocketChannelClient::kClosingHandshakeComplete
: WebSocketChannelClient::kClosingHandshakeIncomplete;
client->DidClose(status, code, reason);
- // client->DidClose may delete this object.
}
ExecutionContext* WebSocketChannelImpl::GetExecutionContext() const {
@@ -580,7 +577,7 @@ void WebSocketChannelImpl::DidConnect(WebSocketHandle* handle,
void WebSocketChannelImpl::DidStartOpeningHandshake(
WebSocketHandle* handle,
- scoped_refptr<WebSocketHandshakeRequest> request) {
+ network::mojom::blink::WebSocketHandshakeRequestPtr request) {
NETWORK_DVLOG(1) << this << " DidStartOpeningHandshake(" << handle << ")";
DCHECK(handle_);
@@ -597,7 +594,7 @@ void WebSocketChannelImpl::DidStartOpeningHandshake(
void WebSocketChannelImpl::DidFinishOpeningHandshake(
WebSocketHandle* handle,
- const WebSocketHandshakeResponse* response) {
+ network::mojom::blink::WebSocketHandshakeResponsePtr response) {
NETWORK_DVLOG(1) << this << " DidFinishOpeningHandshake(" << handle << ")";
DCHECK(handle_);
@@ -608,7 +605,8 @@ void WebSocketChannelImpl::DidFinishOpeningHandshake(
TRACE_EVENT_SCOPE_THREAD, "data",
InspectorWebSocketEvent::Data(GetExecutionContext(), identifier_));
probe::didReceiveWebSocketHandshakeResponse(
- GetExecutionContext(), identifier_, handshake_request_.get(), response);
+ GetExecutionContext(), identifier_, handshake_request_.get(),
+ response.get());
handshake_request_ = nullptr;
}
@@ -626,7 +624,6 @@ void WebSocketChannelImpl::DidFail(WebSocketHandle* handle,
// WebSocketConnection. Hence we fail this channel by calling
// |this->failAsError| function.
FailAsError(message);
- // |this| may be deleted.
}
void WebSocketChannelImpl::DidReceiveData(WebSocketHandle* handle,
@@ -680,7 +677,6 @@ void WebSocketChannelImpl::DidReceiveData(WebSocketHandle* handle,
receiving_message_data_.clear();
if (message.IsNull()) {
FailAsError("Could not decode a text frame as UTF-8.");
- // failAsError may delete this object.
} else {
client_->DidReceiveTextMessage(message);
}
@@ -716,7 +712,6 @@ void WebSocketChannelImpl::DidClose(WebSocketHandle* handle,
}
HandleDidClose(was_clean, code, reason);
- // HandleDidClose may delete this object.
}
void WebSocketChannelImpl::DidReceiveFlowControl(WebSocketHandle* handle,
@@ -785,7 +780,6 @@ void WebSocketChannelImpl::DidFailLoadingBlob(FileError::ErrorCode error_code) {
// FIXME: Generate human-friendly reason message.
FailAsError("Failed to load Blob: error code = " +
String::Number(error_code));
- // |this| can be deleted here.
}
void WebSocketChannelImpl::TearDownFailedConnection() {
@@ -797,7 +791,6 @@ void WebSocketChannelImpl::TearDownFailedConnection() {
client_->DidError();
HandleDidClose(false, kCloseEventCodeAbnormalClosure, String());
- // HandleDidClose may delete this object.
}
bool WebSocketChannelImpl::ShouldDisallowConnection(const KURL& url) {
diff --git a/chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h b/chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h
index 8bf476f65d9..d7e4af0a8de 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h
+++ b/chromium/third_party/blink/renderer/modules/websockets/websocket_channel_impl.h
@@ -55,7 +55,6 @@
namespace blink {
-class WebSocketHandshakeRequest;
class WebSocketHandshakeThrottle;
// This is an implementation of WebSocketChannel. This is created on the main
@@ -163,9 +162,10 @@ class MODULES_EXPORT WebSocketChannelImpl final
const String& extensions) override;
void DidStartOpeningHandshake(
WebSocketHandle*,
- scoped_refptr<WebSocketHandshakeRequest>) override;
- void DidFinishOpeningHandshake(WebSocketHandle*,
- const WebSocketHandshakeResponse*) override;
+ network::mojom::blink::WebSocketHandshakeRequestPtr) override;
+ void DidFinishOpeningHandshake(
+ WebSocketHandle*,
+ network::mojom::blink::WebSocketHandshakeResponsePtr) override;
void DidFail(WebSocketHandle*, const String& message) override;
void DidReceiveData(WebSocketHandle*,
bool fin,
@@ -213,7 +213,7 @@ class MODULES_EXPORT WebSocketChannelImpl final
connection_handle_for_scheduler_;
std::unique_ptr<SourceLocation> location_at_construction_;
- scoped_refptr<WebSocketHandshakeRequest> handshake_request_;
+ network::mojom::blink::WebSocketHandshakeRequestPtr handshake_request_;
std::unique_ptr<WebSocketHandshakeThrottle> handshake_throttle_;
// This field is only initialised if the object is still waiting for a
// throttle response when DidConnect is called.
diff --git a/chromium/third_party/blink/renderer/modules/websockets/websocket_handle_client.h b/chromium/third_party/blink/renderer/modules/websockets/websocket_handle_client.h
index 405411cde1d..1896d2f83b7 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/websocket_handle_client.h
+++ b/chromium/third_party/blink/renderer/modules/websockets/websocket_handle_client.h
@@ -31,12 +31,11 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBSOCKETS_WEBSOCKET_HANDLE_CLIENT_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBSOCKETS_WEBSOCKET_HANDLE_CLIENT_H_
+#include "services/network/public/mojom/websocket.mojom-blink.h"
#include "third_party/blink/renderer/modules/websockets/websocket_handle.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
namespace blink {
-class WebSocketHandshakeRequest;
-class WebSocketHandshakeResponse;
class WebSocketHandleClient {
public:
@@ -49,13 +48,14 @@ class WebSocketHandleClient {
// This notification can be omitted when the inspector is not active.
virtual void DidStartOpeningHandshake(
WebSocketHandle*,
- scoped_refptr<WebSocketHandshakeRequest>) = 0;
+ network::mojom::blink::WebSocketHandshakeRequestPtr) = 0;
// Called when the browser finishes the opening handshake.
// This notification precedes didConnect.
// This notification can be omitted when the inspector is not active.
- virtual void DidFinishOpeningHandshake(WebSocketHandle*,
- const WebSocketHandshakeResponse*) = 0;
+ virtual void DidFinishOpeningHandshake(
+ WebSocketHandle*,
+ network::mojom::blink::WebSocketHandshakeResponsePtr) = 0;
// Called when the browser is required to fail the connection.
// |message| can be displayed in the inspector, but should not be passed
diff --git a/chromium/third_party/blink/renderer/modules/websockets/websocket_handle_impl.cc b/chromium/third_party/blink/renderer/modules/websockets/websocket_handle_impl.cc
index 935f50cf95e..079a508ddff 100644
--- a/chromium/third_party/blink/renderer/modules/websockets/websocket_handle_impl.cc
+++ b/chromium/third_party/blink/renderer/modules/websockets/websocket_handle_impl.cc
@@ -7,9 +7,8 @@
#include "base/single_thread_task_runner.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/modules/websockets/websocket_handle_client.h"
+#include "third_party/blink/renderer/platform/network/http_names.h"
#include "third_party/blink/renderer/platform/network/network_log.h"
-#include "third_party/blink/renderer/platform/network/web_socket_handshake_request.h"
-#include "third_party/blink/renderer/platform/network/web_socket_handshake_response.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
@@ -54,11 +53,15 @@ void WebSocketHandleImpl::Connect(network::mojom::blink::WebSocketPtr websocket,
client_ = client;
network::mojom::blink::WebSocketClientPtr client_proxy;
+ Vector<network::mojom::blink::HttpHeaderPtr> additional_headers;
+ if (!user_agent_override.IsNull()) {
+ additional_headers.push_back(network::mojom::blink::HttpHeader::New(
+ HTTPNames::User_Agent, user_agent_override));
+ }
client_binding_.Bind(mojo::MakeRequest(&client_proxy, task_runner));
- websocket_->AddChannelRequest(
- url, protocols, site_for_cookies,
- user_agent_override.IsNull() ? g_empty_string : user_agent_override,
- std::move(client_proxy));
+ websocket_->AddChannelRequest(url, protocols, site_for_cookies,
+ std::move(additional_headers),
+ std::move(client_proxy));
}
void WebSocketHandleImpl::Send(bool fin,
@@ -149,33 +152,14 @@ void WebSocketHandleImpl::OnStartOpeningHandshake(
network::mojom::blink::WebSocketHandshakeRequestPtr request) {
NETWORK_DVLOG(1) << this << " OnStartOpeningHandshake("
<< request->url.GetString() << ")";
-
- scoped_refptr<WebSocketHandshakeRequest> request_to_pass =
- WebSocketHandshakeRequest::Create(request->url);
- for (size_t i = 0; i < request->headers.size(); ++i) {
- const network::mojom::blink::HttpHeaderPtr& header = request->headers[i];
- request_to_pass->AddHeaderField(AtomicString(header->name),
- AtomicString(header->value));
- }
- request_to_pass->SetHeadersText(request->headers_text);
- client_->DidStartOpeningHandshake(this, request_to_pass);
+ client_->DidStartOpeningHandshake(this, std::move(request));
}
void WebSocketHandleImpl::OnFinishOpeningHandshake(
network::mojom::blink::WebSocketHandshakeResponsePtr response) {
NETWORK_DVLOG(1) << this << " OnFinishOpeningHandshake("
<< response->url.GetString() << ")";
-
- WebSocketHandshakeResponse response_to_pass;
- response_to_pass.SetStatusCode(response->status_code);
- response_to_pass.SetStatusText(response->status_text);
- for (size_t i = 0; i < response->headers.size(); ++i) {
- const network::mojom::blink::HttpHeaderPtr& header = response->headers[i];
- response_to_pass.AddHeaderField(AtomicString(header->name),
- AtomicString(header->value));
- }
- response_to_pass.SetHeadersText(response->headers_text);
- client_->DidFinishOpeningHandshake(this, &response_to_pass);
+ client_->DidFinishOpeningHandshake(this, std::move(response));
}
void WebSocketHandleImpl::OnAddChannelResponse(const String& protocol,
diff --git a/chromium/third_party/blink/renderer/modules/webusb/navigator_usb.cc b/chromium/third_party/blink/renderer/modules/webusb/navigator_usb.cc
index f6731d7551a..31c3f8465ae 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/navigator_usb.cc
+++ b/chromium/third_party/blink/renderer/modules/webusb/navigator_usb.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/modules/webusb/navigator_usb.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/navigator.h"
#include "third_party/blink/renderer/modules/webusb/usb.h"
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb.cc b/chromium/third_party/blink/renderer/modules/webusb/usb.cc
index 5ad319f8a49..431d39b3e70 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb.cc
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb.cc
@@ -12,7 +12,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/dom/exception_code.h"
#include "third_party/blink/renderer/core/frame/frame.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
#include "third_party/blink/renderer/modules/webusb/usb_connection_event.h"
@@ -32,8 +31,6 @@ namespace {
const char kFeaturePolicyBlocked[] =
"Access to the feature \"usb\" is disallowed by feature policy.";
-const char kIframeBlocked[] =
- "Access to this method is not allowed in embedded frames.";
const char kNoDeviceSelected[] = "No device selected.";
UsbDeviceFilterPtr ConvertDeviceFilter(const USBDeviceFilter& filter) {
@@ -80,12 +77,13 @@ void USB::Dispose() {
ScriptPromise USB::getDevices(ScriptState* script_state) {
if (!IsContextSupported()) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kNotSupportedError));
+ script_state,
+ DOMException::Create(DOMExceptionCode::kNotSupportedError));
}
if (!IsFeatureEnabled()) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kSecurityError, kFeaturePolicyBlocked));
+ script_state, DOMException::Create(DOMExceptionCode::kSecurityError,
+ kFeaturePolicyBlocked));
}
EnsureDeviceManagerConnection();
@@ -102,18 +100,14 @@ ScriptPromise USB::requestDevice(ScriptState* script_state,
LocalFrame* frame = GetFrame();
if (!frame) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kNotSupportedError));
+ script_state,
+ DOMException::Create(DOMExceptionCode::kNotSupportedError));
}
- if (IsSupportedInFeaturePolicy(mojom::FeaturePolicyFeature::kUsb)) {
- if (!frame->IsFeatureEnabled(mojom::FeaturePolicyFeature::kUsb)) {
- return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kSecurityError, kFeaturePolicyBlocked));
- }
- } else if (!frame->IsMainFrame()) {
+ if (!frame->IsFeatureEnabled(mojom::FeaturePolicyFeature::kUsb)) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kSecurityError, kIframeBlocked));
+ script_state, DOMException::Create(DOMExceptionCode::kSecurityError,
+ kFeaturePolicyBlocked));
}
if (!chooser_service_) {
@@ -127,7 +121,7 @@ ScriptPromise USB::requestDevice(ScriptState* script_state,
return ScriptPromise::RejectWithDOMException(
script_state,
DOMException::Create(
- kSecurityError,
+ DOMExceptionCode::kSecurityError,
"Must be handling a user gesture to show a permission request."));
}
@@ -197,10 +191,12 @@ void USB::OnGetPermission(ScriptPromiseResolver* resolver,
EnsureDeviceManagerConnection();
- if (device_manager_ && device_info)
+ if (device_manager_ && device_info) {
resolver->Resolve(GetOrCreateDevice(std::move(device_info)));
- else
- resolver->Reject(DOMException::Create(kNotFoundError, kNoDeviceSelected));
+ } else {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
+ kNoDeviceSelected));
+ }
}
void USB::OnDeviceAdded(UsbDeviceInfoPtr device_info) {
@@ -232,8 +228,10 @@ void USB::OnDeviceManagerConnectionError() {
void USB::OnChooserServiceConnectionError() {
chooser_service_.reset();
- for (ScriptPromiseResolver* resolver : chooser_service_requests_)
- resolver->Reject(DOMException::Create(kNotFoundError, kNoDeviceSelected));
+ for (ScriptPromiseResolver* resolver : chooser_service_requests_) {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
+ kNoDeviceSelected));
+ }
chooser_service_requests_.clear();
}
@@ -270,39 +268,35 @@ void USB::EnsureDeviceManagerConnection() {
}
bool USB::IsContextSupported() const {
- ExecutionContext* context = GetExecutionContext();
- if (!context)
- return false;
-
- if (!(context->IsDedicatedWorkerGlobalScope() ||
- context->IsSharedWorkerGlobalScope() || context->IsDocument()))
- return false;
-
// Since WebUSB on Web Workers is in the process of being implemented, we
- // check here if the runtime flag for this feature is enabled.
+ // check here if the runtime flag for the appropriate worker is enabled..
// TODO(https://crbug.com/837406): Remove this check once the feature has
// shipped.
- if (!context->IsDocument() &&
- !RuntimeEnabledFeatures::WebUSBOnDedicatedAndSharedWorkersEnabled())
+ ExecutionContext* context = GetExecutionContext();
+ if (!context)
return false;
+ DCHECK(context->IsDocument() || context->IsDedicatedWorkerGlobalScope() ||
+ context->IsSharedWorkerGlobalScope());
+ DCHECK(!context->IsDedicatedWorkerGlobalScope() ||
+ RuntimeEnabledFeatures::WebUSBOnDedicatedWorkersEnabled());
+ DCHECK(!context->IsSharedWorkerGlobalScope() ||
+ RuntimeEnabledFeatures::WebUSBOnSharedWorkersEnabled());
+
return true;
}
bool USB::IsFeatureEnabled() const {
- // At the moment, FeaturePolicy is not supported in workers, so we skip the
- // check on workers.
- // TODO(https://crbug.com/843780): Enable the FeaturePolicy check for the
- // supported worker contexts once it is available for workers.
- if (GetExecutionContext()->IsDocument()) {
- FeaturePolicy* policy =
- GetExecutionContext()->GetSecurityContext().GetFeaturePolicy();
+ ExecutionContext* context = GetExecutionContext();
+ FeaturePolicy* policy = context->GetSecurityContext().GetFeaturePolicy();
+ // Feature policy is not yet supported in all contexts.
+ if (policy)
return policy->IsFeatureEnabled(mojom::FeaturePolicyFeature::kUsb);
- }
- if (GetExecutionContext()->IsDedicatedWorkerGlobalScope() ||
- GetExecutionContext()->IsSharedWorkerGlobalScope()) {
+
+ // TODO(https://crbug.com/843780): Enable this check for shared workers.
+ if (context->IsSharedWorkerGlobalScope())
return true;
- }
+
return false;
}
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb.idl b/chromium/third_party/blink/renderer/modules/webusb/usb.idl
index 5a656b9a64c..06b82871d7b 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb.idl
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb.idl
@@ -5,7 +5,7 @@
// https://wicg.github.io/webusb/#usb
[
- Exposed(DedicatedWorker WebUSBOnDedicatedAndSharedWorkers, SharedWorker WebUSBOnDedicatedAndSharedWorkers, Window WebUSB),
+ Exposed(DedicatedWorker WebUSBOnDedicatedWorkers, SharedWorker WebUSBOnSharedWorkers, Window WebUSB),
SecureContext
] interface USB : EventTarget {
attribute EventHandler onconnect;
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_alternate_interface.cc b/chromium/third_party/blink/renderer/modules/webusb/usb_alternate_interface.cc
index 5069ecc5b90..ebcddcca82e 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_alternate_interface.cc
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_alternate_interface.cc
@@ -4,9 +4,9 @@
#include "third_party/blink/renderer/modules/webusb/usb_alternate_interface.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/modules/webusb/usb_endpoint.h"
#include "third_party/blink/renderer/modules/webusb/usb_interface.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_alternate_interface.idl b/chromium/third_party/blink/renderer/modules/webusb/usb_alternate_interface.idl
index 056448de612..20cfe45c31b 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_alternate_interface.idl
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_alternate_interface.idl
@@ -6,8 +6,9 @@
[
Constructor(USBInterface deviceInterface, octet alternateSetting),
- Exposed(DedicatedWorker WebUSBOnDedicatedAndSharedWorkers, SharedWorker WebUSBOnDedicatedAndSharedWorkers, Window WebUSB),
- RaisesException=Constructor
+ Exposed(DedicatedWorker WebUSBOnDedicatedWorkers, SharedWorker WebUSBOnSharedWorkers, Window WebUSB),
+ RaisesException=Constructor,
+ SecureContext
] interface USBAlternateInterface {
readonly attribute octet alternateSetting;
readonly attribute octet interfaceClass;
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_configuration.cc b/chromium/third_party/blink/renderer/modules/webusb/usb_configuration.cc
index 6b2bd395860..582ffe46995 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_configuration.cc
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_configuration.cc
@@ -5,9 +5,9 @@
#include "third_party/blink/renderer/modules/webusb/usb_configuration.h"
#include "device/usb/public/mojom/device.mojom-blink.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/modules/webusb/usb_device.h"
#include "third_party/blink/renderer/modules/webusb/usb_interface.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_configuration.idl b/chromium/third_party/blink/renderer/modules/webusb/usb_configuration.idl
index 37987771358..a4ebe754bea 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_configuration.idl
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_configuration.idl
@@ -6,8 +6,9 @@
[
Constructor(USBDevice device, octet configurationValue),
- Exposed(DedicatedWorker WebUSBOnDedicatedAndSharedWorkers, SharedWorker WebUSBOnDedicatedAndSharedWorkers, Window WebUSB),
- RaisesException=Constructor
+ Exposed(DedicatedWorker WebUSBOnDedicatedWorkers, SharedWorker WebUSBOnSharedWorkers, Window WebUSB),
+ RaisesException=Constructor,
+ SecureContext
] interface USBConfiguration {
readonly attribute octet configurationValue;
readonly attribute DOMString? configurationName;
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_connection_event.idl b/chromium/third_party/blink/renderer/modules/webusb/usb_connection_event.idl
index 91a9db2a4c2..ed62a8e08d6 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_connection_event.idl
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_connection_event.idl
@@ -6,7 +6,8 @@
[
Constructor(DOMString type, USBConnectionEventInit eventInitDict),
- Exposed(DedicatedWorker WebUSBOnDedicatedAndSharedWorkers, SharedWorker WebUSBOnDedicatedAndSharedWorkers, Window WebUSB)
+ Exposed(DedicatedWorker WebUSBOnDedicatedWorkers, SharedWorker WebUSBOnSharedWorkers, Window WebUSB),
+ SecureContext
] interface USBConnectionEvent : Event {
[SameObject] readonly attribute USBDevice device;
};
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_device.cc b/chromium/third_party/blink/renderer/modules/webusb/usb_device.cc
index 7555a5380a9..f74584f3323 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_device.cc
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_device.cc
@@ -11,7 +11,6 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
-#include "third_party/blink/renderer/core/dom/exception_code.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
@@ -23,6 +22,7 @@
#include "third_party/blink/renderer/modules/webusb/usb_out_transfer_result.h"
#include "third_party/blink/renderer/platform/mojo/mojo_helper.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
using device::mojom::blink::UsbControlTransferParamsPtr;
using device::mojom::blink::UsbControlTransferType;
@@ -51,17 +51,20 @@ const char kOpenRequired[] = "The device must be opened first.";
DOMException* ConvertFatalTransferStatus(const UsbTransferStatus& status) {
switch (status) {
case UsbTransferStatus::TRANSFER_ERROR:
- return DOMException::Create(kNetworkError,
+ return DOMException::Create(DOMExceptionCode::kNetworkError,
"A transfer error has occurred.");
case UsbTransferStatus::PERMISSION_DENIED:
- return DOMException::Create(kSecurityError,
+ return DOMException::Create(DOMExceptionCode::kSecurityError,
"The transfer was not allowed.");
case UsbTransferStatus::TIMEOUT:
- return DOMException::Create(kTimeoutError, "The transfer timed out.");
+ return DOMException::Create(DOMExceptionCode::kTimeoutError,
+ "The transfer timed out.");
case UsbTransferStatus::CANCELLED:
- return DOMException::Create(kAbortError, "The transfer was cancelled.");
+ return DOMException::Create(DOMExceptionCode::kAbortError,
+ "The transfer was cancelled.");
case UsbTransferStatus::DISCONNECT:
- return DOMException::Create(kNotFoundError, kDeviceDisconnected);
+ return DOMException::Create(DOMExceptionCode::kNotFoundError,
+ kDeviceDisconnected);
case UsbTransferStatus::COMPLETED:
case UsbTransferStatus::STALLED:
case UsbTransferStatus::BABBLE:
@@ -192,11 +195,12 @@ ScriptPromise USBDevice::selectConfiguration(ScriptState* script_state,
ScriptPromise promise = resolver->Promise();
if (EnsureNoDeviceOrInterfaceChangeInProgress(resolver)) {
if (!opened_) {
- resolver->Reject(DOMException::Create(kInvalidStateError, kOpenRequired));
+ resolver->Reject(DOMException::Create(
+ DOMExceptionCode::kInvalidStateError, kOpenRequired));
} else {
int configuration_index = FindConfigurationIndex(configuration_value);
if (configuration_index == -1) {
- resolver->Reject(DOMException::Create(kNotFoundError,
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
"The configuration value "
"provided is not supported by "
"the device."));
@@ -223,11 +227,12 @@ ScriptPromise USBDevice::claimInterface(ScriptState* script_state,
if (EnsureDeviceConfigured(resolver)) {
int interface_index = FindInterfaceIndex(interface_number);
if (interface_index == -1) {
- resolver->Reject(
- DOMException::Create(kNotFoundError, kInterfaceNotFound));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
+ kInterfaceNotFound));
} else if (interface_state_change_in_progress_.Get(interface_index)) {
- resolver->Reject(DOMException::Create(kInvalidStateError,
- kInterfaceStateChangeInProgress));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kInterfaceStateChangeInProgress));
} else if (claimed_interfaces_.Get(interface_index)) {
resolver->Resolve();
} else if (IsProtectedInterfaceClass(interface_index)) {
@@ -237,7 +242,7 @@ ScriptPromise USBDevice::claimInterface(ScriptState* script_state,
"has been blocked because it "
"implements a protected interface class."));
resolver->Reject(DOMException::Create(
- kSecurityError,
+ DOMExceptionCode::kSecurityError,
"The requested interface implements a protected class."));
} else {
interface_state_change_in_progress_.Set(interface_index);
@@ -258,13 +263,14 @@ ScriptPromise USBDevice::releaseInterface(ScriptState* script_state,
if (EnsureDeviceConfigured(resolver)) {
int interface_index = FindInterfaceIndex(interface_number);
if (interface_index == -1) {
- resolver->Reject(DOMException::Create(kNotFoundError,
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
"The interface number provided is "
"not supported by the device in "
"its current configuration."));
} else if (interface_state_change_in_progress_.Get(interface_index)) {
- resolver->Reject(DOMException::Create(kInvalidStateError,
- kInterfaceStateChangeInProgress));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kInterfaceStateChangeInProgress));
} else if (!claimed_interfaces_.Get(interface_index)) {
resolver->Resolve();
} else {
@@ -294,7 +300,7 @@ ScriptPromise USBDevice::selectAlternateInterface(ScriptState* script_state,
int alternate_index =
FindAlternateIndex(interface_index, alternate_setting);
if (alternate_index == -1) {
- resolver->Reject(DOMException::Create(kNotFoundError,
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
"The alternate setting provided is "
"not supported by the device in "
"its current configuration."));
@@ -456,7 +462,8 @@ ScriptPromise USBDevice::reset(ScriptState* script_state) {
ScriptPromise promise = resolver->Promise();
if (EnsureNoDeviceOrInterfaceChangeInProgress(resolver)) {
if (!opened_) {
- resolver->Reject(DOMException::Create(kInvalidStateError, kOpenRequired));
+ resolver->Reject(DOMException::Create(
+ DOMExceptionCode::kInvalidStateError, kOpenRequired));
} else {
device_requests_.insert(resolver);
device_->Reset(WTF::Bind(&USBDevice::AsyncReset, WrapPersistent(this),
@@ -546,32 +553,38 @@ bool USBDevice::IsProtectedInterfaceClass(int interface_index) const {
bool USBDevice::EnsureNoDeviceOrInterfaceChangeInProgress(
ScriptPromiseResolver* resolver) const {
- if (!device_)
- resolver->Reject(DOMException::Create(kNotFoundError, kDeviceDisconnected));
- else if (device_state_change_in_progress_)
- resolver->Reject(
- DOMException::Create(kInvalidStateError, kDeviceStateChangeInProgress));
- else if (AnyInterfaceChangeInProgress())
- resolver->Reject(DOMException::Create(kInvalidStateError,
+ if (!device_) {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
+ kDeviceDisconnected));
+ } else if (device_state_change_in_progress_) {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kDeviceStateChangeInProgress));
+ } else if (AnyInterfaceChangeInProgress()) {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kInvalidStateError,
kInterfaceStateChangeInProgress));
- else
+ } else {
return true;
+ }
return false;
}
bool USBDevice::EnsureDeviceConfigured(ScriptPromiseResolver* resolver) const {
- if (!device_)
- resolver->Reject(DOMException::Create(kNotFoundError, kDeviceDisconnected));
- else if (device_state_change_in_progress_)
+ if (!device_) {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
+ kDeviceDisconnected));
+ } else if (device_state_change_in_progress_) {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kDeviceStateChangeInProgress));
+ } else if (!opened_) {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kOpenRequired));
+ } else if (configuration_index_ == -1) {
resolver->Reject(
- DOMException::Create(kInvalidStateError, kDeviceStateChangeInProgress));
- else if (!opened_)
- resolver->Reject(DOMException::Create(kInvalidStateError, kOpenRequired));
- else if (configuration_index_ == -1)
- resolver->Reject(DOMException::Create(
- kInvalidStateError, "The device must have a configuration selected."));
- else
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "The device must have a configuration selected."));
+ } else {
return true;
+ }
return false;
}
@@ -580,16 +593,19 @@ bool USBDevice::EnsureInterfaceClaimed(uint8_t interface_number,
if (!EnsureDeviceConfigured(resolver))
return false;
int interface_index = FindInterfaceIndex(interface_number);
- if (interface_index == -1)
- resolver->Reject(DOMException::Create(kNotFoundError, kInterfaceNotFound));
- else if (interface_state_change_in_progress_.Get(interface_index))
- resolver->Reject(DOMException::Create(kInvalidStateError,
+ if (interface_index == -1) {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
+ kInterfaceNotFound));
+ } else if (interface_state_change_in_progress_.Get(interface_index)) {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kInvalidStateError,
kInterfaceStateChangeInProgress));
- else if (!claimed_interfaces_.Get(interface_index))
- resolver->Reject(DOMException::Create(
- kInvalidStateError, "The specified interface has not been claimed."));
- else
+ } else if (!claimed_interfaces_.Get(interface_index)) {
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ "The specified interface has not been claimed."));
+ } else {
return true;
+ }
return false;
}
@@ -599,13 +615,14 @@ bool USBDevice::EnsureEndpointAvailable(bool in_transfer,
if (!EnsureDeviceConfigured(resolver))
return false;
if (endpoint_number == 0 || endpoint_number >= 16) {
- resolver->Reject(DOMException::Create(
- kIndexSizeError, "The specified endpoint number is out of range."));
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kIndexSizeError,
+ "The specified endpoint number is out of range."));
return false;
}
auto& bit_vector = in_transfer ? in_endpoints_ : out_endpoints_;
if (!bit_vector.Get(endpoint_number - 1)) {
- resolver->Reject(DOMException::Create(kNotFoundError,
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
"The specified endpoint is not part "
"of a claimed and selected alternate "
"interface."));
@@ -635,7 +652,7 @@ UsbControlTransferParamsPtr USBDevice::ConvertControlTransferParameters(
mojo_parameters->type = UsbControlTransferType::VENDOR;
} else {
resolver->Reject(DOMException::Create(
- kTypeMismatchError,
+ DOMExceptionCode::kTypeMismatchError,
"The control transfer requestType parameter is invalid."));
return nullptr;
}
@@ -657,7 +674,7 @@ UsbControlTransferParamsPtr USBDevice::ConvertControlTransferParameters(
mojo_parameters->recipient = UsbControlTransferRecipient::OTHER;
} else {
resolver->Reject(DOMException::Create(
- kTypeMismatchError,
+ DOMExceptionCode::kTypeMismatchError,
"The control transfer recipient parameter is invalid."));
return nullptr;
}
@@ -702,7 +719,8 @@ void USBDevice::AsyncOpen(ScriptPromiseResolver* resolver,
return;
case UsbOpenDeviceError::ACCESS_DENIED:
OnDeviceOpenedOrClosed(false /* not opened */);
- resolver->Reject(DOMException::Create(kSecurityError, "Access denied."));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kSecurityError,
+ "Access denied."));
return;
}
}
@@ -733,11 +751,13 @@ void USBDevice::AsyncSelectConfiguration(size_t configuration_index,
return;
OnConfigurationSelected(success, configuration_index);
- if (success)
+ if (success) {
resolver->Resolve();
- else
- resolver->Reject(DOMException::Create(
- kNetworkError, "Unable to set device configuration."));
+ } else {
+ resolver->Reject(
+ DOMException::Create(DOMExceptionCode::kNetworkError,
+ "Unable to set device configuration."));
+ }
}
void USBDevice::OnConfigurationSelected(bool success,
@@ -765,11 +785,12 @@ void USBDevice::AsyncClaimInterface(size_t interface_index,
return;
OnInterfaceClaimedOrUnclaimed(success, interface_index);
- if (success)
+ if (success) {
resolver->Resolve();
- else
- resolver->Reject(
- DOMException::Create(kNetworkError, "Unable to claim interface."));
+ } else {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNetworkError,
+ "Unable to claim interface."));
+ }
}
void USBDevice::AsyncReleaseInterface(size_t interface_index,
@@ -779,11 +800,12 @@ void USBDevice::AsyncReleaseInterface(size_t interface_index,
return;
OnInterfaceClaimedOrUnclaimed(!success, interface_index);
- if (success)
+ if (success) {
resolver->Resolve();
- else
- resolver->Reject(
- DOMException::Create(kNetworkError, "Unable to release interface."));
+ } else {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNetworkError,
+ "Unable to release interface."));
+ }
}
void USBDevice::OnInterfaceClaimedOrUnclaimed(bool claimed,
@@ -810,11 +832,12 @@ void USBDevice::AsyncSelectAlternateInterface(size_t interface_index,
SetEndpointsForInterface(interface_index, success);
interface_state_change_in_progress_.Clear(interface_index);
- if (success)
+ if (success) {
resolver->Resolve();
- else
- resolver->Reject(
- DOMException::Create(kNetworkError, "Unable to set device interface."));
+ } else {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNetworkError,
+ "Unable to set device interface."));
+ }
}
void USBDevice::AsyncControlTransferIn(ScriptPromiseResolver* resolver,
@@ -851,11 +874,12 @@ void USBDevice::AsyncClearHalt(ScriptPromiseResolver* resolver, bool success) {
if (!MarkRequestComplete(resolver))
return;
- if (success)
+ if (success) {
resolver->Resolve();
- else
- resolver->Reject(
- DOMException::Create(kNetworkError, "Unable to clear endpoint."));
+ } else {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNetworkError,
+ "Unable to clear endpoint."));
+ }
}
void USBDevice::AsyncTransferIn(ScriptPromiseResolver* resolver,
@@ -941,18 +965,21 @@ void USBDevice::AsyncReset(ScriptPromiseResolver* resolver, bool success) {
if (!MarkRequestComplete(resolver))
return;
- if (success)
+ if (success) {
resolver->Resolve();
- else
- resolver->Reject(
- DOMException::Create(kNetworkError, "Unable to reset the device."));
+ } else {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNetworkError,
+ "Unable to reset the device."));
+ }
}
void USBDevice::OnConnectionError() {
device_.reset();
opened_ = false;
- for (ScriptPromiseResolver* resolver : device_requests_)
- resolver->Reject(DOMException::Create(kNotFoundError, kDeviceDisconnected));
+ for (ScriptPromiseResolver* resolver : device_requests_) {
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
+ kDeviceDisconnected));
+ }
device_requests_.clear();
}
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_device.idl b/chromium/third_party/blink/renderer/modules/webusb/usb_device.idl
index 39c1c325082..bff5d2ed90d 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_device.idl
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_device.idl
@@ -13,7 +13,8 @@ enum USBTransferStatus {
// https://wicg.github.io/webusb/#device-usage
[
- Exposed(DedicatedWorker WebUSBOnDedicatedAndSharedWorkers, SharedWorker WebUSBOnDedicatedAndSharedWorkers, Window WebUSB)
+ Exposed(DedicatedWorker WebUSBOnDedicatedWorkers, SharedWorker WebUSBOnSharedWorkers, Window WebUSB),
+ SecureContext
] interface USBDevice {
readonly attribute octet usbVersionMajor;
readonly attribute octet usbVersionMinor;
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_endpoint.cc b/chromium/third_party/blink/renderer/modules/webusb/usb_endpoint.cc
index def27169b8e..0152b9a70d9 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_endpoint.cc
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_endpoint.cc
@@ -5,9 +5,9 @@
#include "third_party/blink/renderer/modules/webusb/usb_endpoint.h"
#include "device/usb/public/mojom/device.mojom-blink.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/modules/webusb/usb_alternate_interface.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
using device::mojom::blink::UsbTransferType;
using device::mojom::blink::UsbTransferDirection;
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_endpoint.idl b/chromium/third_party/blink/renderer/modules/webusb/usb_endpoint.idl
index 329bac46c5e..80d529894e3 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_endpoint.idl
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_endpoint.idl
@@ -17,8 +17,9 @@ enum USBEndpointType {
[
Constructor(USBAlternateInterface alternate, octet endpointNumber, USBDirection direction),
- Exposed(DedicatedWorker WebUSBOnDedicatedAndSharedWorkers, SharedWorker WebUSBOnDedicatedAndSharedWorkers, Window WebUSB),
- RaisesException=Constructor
+ Exposed(DedicatedWorker WebUSBOnDedicatedWorkers, SharedWorker WebUSBOnSharedWorkers, Window WebUSB),
+ RaisesException=Constructor,
+ SecureContext
] interface USBEndpoint {
readonly attribute octet endpointNumber;
readonly attribute USBDirection direction;
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_in_transfer_result.idl b/chromium/third_party/blink/renderer/modules/webusb/usb_in_transfer_result.idl
index 4971bc715b3..3efc62c55ca 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_in_transfer_result.idl
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_in_transfer_result.idl
@@ -5,8 +5,9 @@
// https://wicg.github.io/webusb/#usbintransferresult
[
- Exposed(DedicatedWorker WebUSBOnDedicatedAndSharedWorkers, SharedWorker WebUSBOnDedicatedAndSharedWorkers, Window WebUSB),
- Constructor(USBTransferStatus status, optional DataView? data)
+ Exposed(DedicatedWorker WebUSBOnDedicatedWorkers, SharedWorker WebUSBOnSharedWorkers, Window WebUSB),
+ Constructor(USBTransferStatus status, optional DataView? data),
+ SecureContext
] interface USBInTransferResult {
readonly attribute DataView? data;
readonly attribute USBTransferStatus status;
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_interface.cc b/chromium/third_party/blink/renderer/modules/webusb/usb_interface.cc
index 83d8689fba1..4091c9a38f9 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_interface.cc
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_interface.cc
@@ -5,10 +5,10 @@
#include "third_party/blink/renderer/modules/webusb/usb_interface.h"
#include "device/usb/public/mojom/device.mojom-blink.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/modules/webusb/usb_alternate_interface.h"
#include "third_party/blink/renderer/modules/webusb/usb_configuration.h"
#include "third_party/blink/renderer/modules/webusb/usb_device.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_interface.idl b/chromium/third_party/blink/renderer/modules/webusb/usb_interface.idl
index 3aa2651ed01..a25d466adcb 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_interface.idl
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_interface.idl
@@ -6,8 +6,9 @@
[
Constructor(USBConfiguration configuration, octet interfaceNumber),
- Exposed(DedicatedWorker WebUSBOnDedicatedAndSharedWorkers, SharedWorker WebUSBOnDedicatedAndSharedWorkers, Window WebUSB),
- RaisesException=Constructor
+ Exposed(DedicatedWorker WebUSBOnDedicatedWorkers, SharedWorker WebUSBOnSharedWorkers, Window WebUSB),
+ RaisesException=Constructor,
+ SecureContext
] interface USBInterface {
readonly attribute octet interfaceNumber;
readonly attribute USBAlternateInterface? alternate;
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_in_transfer_packet.idl b/chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_in_transfer_packet.idl
index c09bdb2f189..313adbb9374 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_in_transfer_packet.idl
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_in_transfer_packet.idl
@@ -6,7 +6,8 @@
[
Constructor(USBTransferStatus status, optional DataView? data),
- Exposed(DedicatedWorker WebUSBOnDedicatedAndSharedWorkers, SharedWorker WebUSBOnDedicatedAndSharedWorkers, Window WebUSB)
+ Exposed(DedicatedWorker WebUSBOnDedicatedWorkers, SharedWorker WebUSBOnSharedWorkers, Window WebUSB),
+ SecureContext
] interface USBIsochronousInTransferPacket {
readonly attribute USBTransferStatus status;
readonly attribute DataView? data;
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_in_transfer_result.idl b/chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_in_transfer_result.idl
index 880d5c5718f..0d6b8187d74 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_in_transfer_result.idl
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_in_transfer_result.idl
@@ -6,7 +6,8 @@
[
Constructor(sequence<USBIsochronousInTransferPacket> packets, optional DataView? data),
- Exposed(DedicatedWorker WebUSBOnDedicatedAndSharedWorkers, SharedWorker WebUSBOnDedicatedAndSharedWorkers, Window WebUSB)
+ Exposed(DedicatedWorker WebUSBOnDedicatedWorkers, SharedWorker WebUSBOnSharedWorkers, Window WebUSB),
+ SecureContext
] interface USBIsochronousInTransferResult {
readonly attribute DataView? data;
readonly attribute FrozenArray<USBIsochronousInTransferPacket> packets;
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_out_transfer_packet.idl b/chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_out_transfer_packet.idl
index b97c605df8c..f080b0e4bc2 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_out_transfer_packet.idl
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_out_transfer_packet.idl
@@ -6,7 +6,8 @@
[
Constructor(USBTransferStatus status, optional unsigned long bytesWritten = 0),
- Exposed(DedicatedWorker WebUSBOnDedicatedAndSharedWorkers, SharedWorker WebUSBOnDedicatedAndSharedWorkers, Window WebUSB)
+ Exposed(DedicatedWorker WebUSBOnDedicatedWorkers, SharedWorker WebUSBOnSharedWorkers, Window WebUSB),
+ SecureContext
] interface USBIsochronousOutTransferPacket {
readonly attribute unsigned long bytesWritten;
readonly attribute USBTransferStatus status;
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_out_transfer_result.idl b/chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_out_transfer_result.idl
index a56515e3796..01e694029a0 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_out_transfer_result.idl
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_isochronous_out_transfer_result.idl
@@ -6,7 +6,8 @@
[
Constructor(sequence<USBIsochronousOutTransferPacket> packets),
- Exposed(DedicatedWorker WebUSBOnDedicatedAndSharedWorkers, SharedWorker WebUSBOnDedicatedAndSharedWorkers, Window WebUSB)
+ Exposed(DedicatedWorker WebUSBOnDedicatedWorkers, SharedWorker WebUSBOnSharedWorkers, Window WebUSB),
+ SecureContext
] interface USBIsochronousOutTransferResult {
readonly attribute FrozenArray<USBIsochronousOutTransferPacket> packets;
};
diff --git a/chromium/third_party/blink/renderer/modules/webusb/usb_out_transfer_result.idl b/chromium/third_party/blink/renderer/modules/webusb/usb_out_transfer_result.idl
index 8ff6e95045b..b68561e164b 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/usb_out_transfer_result.idl
+++ b/chromium/third_party/blink/renderer/modules/webusb/usb_out_transfer_result.idl
@@ -5,8 +5,9 @@
// https://wicg.github.io/webusb/#usbouttransferresult
[
- Exposed(DedicatedWorker WebUSBOnDedicatedAndSharedWorkers, SharedWorker WebUSBOnDedicatedAndSharedWorkers, Window WebUSB),
- Constructor(USBTransferStatus status, optional unsigned long bytesWritten = 0)
+ Exposed(DedicatedWorker WebUSBOnDedicatedWorkers, SharedWorker WebUSBOnSharedWorkers, Window WebUSB),
+ Constructor(USBTransferStatus status, optional unsigned long bytesWritten = 0),
+ SecureContext
] interface USBOutTransferResult {
readonly attribute unsigned long bytesWritten;
readonly attribute USBTransferStatus status;
diff --git a/chromium/third_party/blink/renderer/modules/webusb/worker_navigator_usb.cc b/chromium/third_party/blink/renderer/modules/webusb/worker_navigator_usb.cc
index fa1fbfd4430..d26f54be32c 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/worker_navigator_usb.cc
+++ b/chromium/third_party/blink/renderer/modules/webusb/worker_navigator_usb.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/core/workers/worker_navigator.h"
#include "third_party/blink/renderer/modules/webusb/usb.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
@@ -20,22 +21,34 @@ WorkerNavigatorUSB& WorkerNavigatorUSB::From(
return *supplement;
}
+// static
USB* WorkerNavigatorUSB::usb(ScriptState* script_state,
WorkerNavigator& worker_navigator) {
return WorkerNavigatorUSB::From(worker_navigator).usb(script_state);
}
USB* WorkerNavigatorUSB::usb(ScriptState* script_state) {
- // A bug in the WebIDL compiler causes this attribute to be exposed to the
- // WorkerNavigator interface in the ServiceWorkerGlobalScope, therefore we
- // will just return the empty usb_ member if the current context is a
- // ServiceWorkerGlobalScope.
- // TODO(https://crbug.com/839117): Once this attribute stops being exposed to
- // the WorkerNavigator for a Service worker, remove this check.
- if (!usb_ &&
- !ExecutionContext::From(script_state)->IsServiceWorkerGlobalScope()) {
- DCHECK(ExecutionContext::From(script_state));
- usb_ = USB::Create(*ExecutionContext::From(script_state));
+ // A bug in the WebIDL compiler causes this attribute to be incorrectly
+ // exposed in the other worker contexts if one of the RuntimeEnabled flags is
+ // enabled. Therefore, we will just return the empty usb_ member if the
+ // appropriate flag is not enabled for the current context, or if the
+ // current context is a ServiceWorkerGlobalScope.
+ // TODO(https://crbug.com/839117): Once this attribute stops being incorrectly
+ // exposed to the worker contexts, remove these checks.
+ if (!usb_) {
+ ExecutionContext* context = ExecutionContext::From(script_state);
+ DCHECK(context);
+
+ bool isDedicatedWorkerAndEnabled =
+ context->IsDedicatedWorkerGlobalScope() &&
+ RuntimeEnabledFeatures::WebUSBOnDedicatedWorkersEnabled();
+ bool isSharedWorkerAndEnabled =
+ context->IsSharedWorkerGlobalScope() &&
+ RuntimeEnabledFeatures::WebUSBOnSharedWorkersEnabled();
+
+ if (isDedicatedWorkerAndEnabled || isSharedWorkerAndEnabled) {
+ usb_ = USB::Create(*context);
+ }
}
return usb_;
}
diff --git a/chromium/third_party/blink/renderer/modules/webusb/worker_navigator_usb.idl b/chromium/third_party/blink/renderer/modules/webusb/worker_navigator_usb.idl
index d7880d1d5d4..555bbcc74af 100644
--- a/chromium/third_party/blink/renderer/modules/webusb/worker_navigator_usb.idl
+++ b/chromium/third_party/blink/renderer/modules/webusb/worker_navigator_usb.idl
@@ -5,9 +5,9 @@
// https://wicg.github.io/webusb/#enumeration
[
- Exposed=(DedicatedWorker, SharedWorker),
+ Exposed(DedicatedWorker WebUSBOnDedicatedWorkers, SharedWorker WebUSBOnSharedWorkers),
ImplementedAs=WorkerNavigatorUSB,
SecureContext
] partial interface WorkerNavigator {
- [CallWith=ScriptState, SameObject, RuntimeEnabled=WebUSBOnDedicatedAndSharedWorkers] readonly attribute USB usb;
+ [CallWith=ScriptState, SameObject] readonly attribute USB usb;
};
diff --git a/chromium/third_party/blink/renderer/modules/xr/BUILD.gn b/chromium/third_party/blink/renderer/modules/xr/BUILD.gn
index 0bd7b4656c6..c9d3f2f3904 100644
--- a/chromium/third_party/blink/renderer/modules/xr/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/xr/BUILD.gn
@@ -16,12 +16,16 @@ blink_modules_sources("xr") {
"xr_device.h",
"xr_device_pose.cc",
"xr_device_pose.h",
+ "xr_frame.cc",
+ "xr_frame.h",
"xr_frame_of_reference.cc",
"xr_frame_of_reference.h",
"xr_frame_provider.cc",
"xr_frame_provider.h",
"xr_frame_request_callback_collection.cc",
"xr_frame_request_callback_collection.h",
+ "xr_hit_result.cc",
+ "xr_hit_result.h",
"xr_input_pose.cc",
"xr_input_pose.h",
"xr_input_source.cc",
@@ -32,8 +36,8 @@ blink_modules_sources("xr") {
"xr_layer.h",
"xr_presentation_context.cc",
"xr_presentation_context.h",
- "xr_presentation_frame.cc",
- "xr_presentation_frame.h",
+ "xr_ray.cc",
+ "xr_ray.h",
"xr_session.cc",
"xr_session.h",
"xr_session_event.cc",
diff --git a/chromium/third_party/blink/renderer/modules/xr/OWNERS b/chromium/third_party/blink/renderer/modules/xr/OWNERS
index 26c48a27959..c42d16c525b 100644
--- a/chromium/third_party/blink/renderer/modules/xr/OWNERS
+++ b/chromium/third_party/blink/renderer/modules/xr/OWNERS
@@ -1,4 +1,5 @@
bajones@chromium.org
klausw@chromium.org
-# COMPONENT: Blink>WebVR \ No newline at end of file
+# TEAM: xr-dev@chromium.org
+# COMPONENT: Blink>WebXR
diff --git a/chromium/third_party/blink/renderer/modules/xr/PRESUBMIT.py b/chromium/third_party/blink/renderer/modules/xr/PRESUBMIT.py
new file mode 100644
index 00000000000..81cd49bc4f9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/xr/PRESUBMIT.py
@@ -0,0 +1,24 @@
+# Copyright (c) 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.
+
+"""Top-level presubmit script for third_party/blink/renderer/modules/xr.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details about the presubmit API built into depot_tools.
+"""
+
+
+def PostUploadHook(cl, change, output_api): # pylint: disable=C0103,W0613
+ """git cl upload will call this hook after the issue is created/modified.
+
+ This hook modifies the CL description in order to run extra GPU
+ tests (in particular, WebXR and WebVR browser tests) in addition
+ to the regular CQ try bots. This test suite is too large to run
+ against all Chromium commits, but should be run against changes
+ likely to affect these tests.
+ """
+ return output_api.EnsureCQIncludeTrybotsAreAdded(
+ cl,
+ ['luci.chromium.try:win_optional_gpu_tests_rel'],
+ 'Automatically added optional GPU tests to run on CQ.')
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr.cc b/chromium/third_party/blink/renderer/modules/xr/xr.cc
index 2d4657dfd1e..58c4a8aa7f4 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr.cc
@@ -25,10 +25,6 @@ const char kNavigatorDetachedError[] =
const char kFeaturePolicyBlocked[] =
"Access to the feature \"xr\" is disallowed by feature policy.";
-const char kCrossOriginSubframeBlocked[] =
- "Blocked call to navigator.xr.requestDevice inside a cross-origin "
- "iframe because the frame has never been activated by the user.";
-
const char kNoDevicesMessage[] = "No devices found.";
} // namespace
@@ -75,8 +71,8 @@ ScriptPromise XR::requestDevice(ScriptState* script_state) {
if (!frame) {
// Reject if the frame is inaccessible.
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kInvalidStateError, kNavigatorDetachedError));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kNavigatorDetachedError));
}
if (!did_log_requestDevice_ && frame->GetDocument()) {
@@ -86,19 +82,12 @@ ScriptPromise XR::requestDevice(ScriptState* script_state) {
did_log_requestDevice_ = true;
}
- if (IsSupportedInFeaturePolicy(mojom::FeaturePolicyFeature::kWebVr)) {
- if (!frame->IsFeatureEnabled(mojom::FeaturePolicyFeature::kWebVr)) {
- // Only allow the call to be made if the appropraite feature policy is in
- // place.
- return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kSecurityError, kFeaturePolicyBlocked));
- }
- } else if (!frame->HasBeenActivated() && frame->IsCrossOriginSubframe()) {
- // Block calls from cross-origin iframes that have never had a user gesture.
+ if (!frame->IsFeatureEnabled(mojom::FeaturePolicyFeature::kWebVr)) {
+ // Only allow the call to be made if the appropraite feature policy is in
+ // place.
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kSecurityError, kCrossOriginSubframeBlocked));
+ script_state, DOMException::Create(DOMExceptionCode::kSecurityError,
+ kFeaturePolicyBlocked));
}
// If we're still waiting for a previous call to resolve return that promise
@@ -118,7 +107,8 @@ ScriptPromise XR::requestDevice(ScriptState* script_state) {
// other method of getting the prefered device, insert that here. For now,
// just get the first device out of the list, if there is one.
if (devices_.size() == 0) {
- resolver->Reject(DOMException::Create(kNotFoundError, kNoDevicesMessage));
+ resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
+ kNoDevicesMessage));
} else {
resolver->Resolve(devices_[0]);
}
@@ -137,13 +127,12 @@ ScriptPromise XR::requestDevice(ScriptState* script_state) {
// here. Upon calling SetClient in the constructor we should receive one call
// for each XRDevice that was already connected at the time.
void XR::OnDisplayConnected(
- device::mojom::blink::VRMagicWindowProviderPtr magic_window_provider,
device::mojom::blink::VRDisplayHostPtr display,
device::mojom::blink::VRDisplayClientRequest client_request,
device::mojom::blink::VRDisplayInfoPtr display_info) {
XRDevice* xr_device =
- new XRDevice(this, std::move(magic_window_provider), std::move(display),
- std::move(client_request), std::move(display_info));
+ new XRDevice(this, std::move(display), std::move(client_request),
+ std::move(display_info));
devices_.push_back(xr_device);
@@ -161,10 +150,10 @@ void XR::OnDevicesSynced() {
void XR::ResolveRequestDevice() {
if (pending_devices_resolver_) {
if (devices_.size() == 0) {
- pending_devices_resolver_->Reject(
- DOMException::Create(kNotFoundError, kNoDevicesMessage));
+ pending_devices_resolver_->Reject(DOMException::Create(
+ DOMExceptionCode::kNotFoundError, kNoDevicesMessage));
} else {
- if (!did_log_returned_device_ || !did_log_supports_exclusive_) {
+ if (!did_log_returned_device_ || !did_log_supports_immersive_) {
Document* doc = GetFrame() ? GetFrame()->GetDocument() : nullptr;
if (doc) {
ukm::builders::XR_WebXR ukm_builder(ukm_source_id_);
@@ -173,9 +162,9 @@ void XR::ResolveRequestDevice() {
// We only expose a single device to WebXR, so report that device's
// capabilities.
- if (devices_[0]->SupportsExclusive()) {
+ if (devices_[0]->SupportsImmersive()) {
ukm_builder.SetReturnedPresentationCapableDevice(1);
- did_log_supports_exclusive_ = true;
+ did_log_supports_immersive_ = true;
}
ukm_builder.Record(doc->UkmRecorder());
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr.h b/chromium/third_party/blink/renderer/modules/xr/xr.h
index c7127cac59b..4c6efa8c063 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr.h
@@ -37,8 +37,7 @@ class XR final : public EventTargetWithInlineData,
ScriptPromise requestDevice(ScriptState*);
// XRServiceClient overrides.
- void OnDisplayConnected(device::mojom::blink::VRMagicWindowProviderPtr,
- device::mojom::blink::VRDisplayHostPtr,
+ void OnDisplayConnected(device::mojom::blink::VRDisplayHostPtr,
device::mojom::blink::VRDisplayClientRequest,
device::mojom::blink::VRDisplayInfoPtr) override;
@@ -68,7 +67,7 @@ class XR final : public EventTargetWithInlineData,
// Indicates whether use of requestDevice has already been logged.
bool did_log_requestDevice_ = false;
bool did_log_returned_device_ = false;
- bool did_log_supports_exclusive_ = false;
+ bool did_log_supports_immersive_ = false;
const int64_t ukm_source_id_;
HeapVector<Member<XRDevice>> devices_;
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_canvas_input_provider.cc b/chromium/third_party/blink/renderer/modules/xr/xr_canvas_input_provider.cc
index 458efaa5bfe..91b22ee9e7c 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_canvas_input_provider.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_canvas_input_provider.cc
@@ -66,8 +66,8 @@ void XRCanvasInputProvider::Stop() {
}
bool XRCanvasInputProvider::ShouldProcessEvents() {
- // Don't process canvas gestures if there's an active exclusive session.
- return !(session_->device()->frameProvider()->exclusive_session());
+ // Don't process canvas gestures if there's an active immersive session.
+ return !(session_->device()->frameProvider()->immersive_session());
}
void XRCanvasInputProvider::OnClick(MouseEvent* event) {
@@ -86,7 +86,7 @@ void XRCanvasInputProvider::UpdateInputSource(MouseEvent* event) {
if (!input_source_) {
input_source_ = new XRInputSource(session_, 0);
- input_source_->SetPointerOrigin(XRInputSource::kOriginScreen);
+ input_source_->SetTargetRayMode(XRInputSource::kScreen);
}
// Get the event location relative to the canvas element.
@@ -117,9 +117,4 @@ void XRCanvasInputProvider::Trace(blink::Visitor* visitor) {
visitor->Trace(input_source_);
}
-void XRCanvasInputProvider::TraceWrappers(
- blink::ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(input_source_);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_canvas_input_provider.h b/chromium/third_party/blink/renderer/modules/xr/xr_canvas_input_provider.h
index 9e9560f035e..201092ae33a 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_canvas_input_provider.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_canvas_input_provider.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_CANVAS_INPUT_PROVIDER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_CANVAS_INPUT_PROVIDER_H_
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
@@ -22,7 +22,7 @@ class XRSession;
class XRCanvasInputProvider
: public GarbageCollectedFinalized<XRCanvasInputProvider>,
- public TraceWrapperBase {
+ public NameClient {
public:
XRCanvasInputProvider(XRSession*, HTMLCanvasElement*);
virtual ~XRCanvasInputProvider();
@@ -39,7 +39,6 @@ class XRCanvasInputProvider
XRInputSource* GetInputSource();
virtual void Trace(blink::Visitor*);
- void TraceWrappers(blink::ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "XRCanvasInputProvider";
}
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_device.cc b/chromium/third_party/blink/renderer/modules/xr/xr_device.cc
index 25df2d2ef5b..7925e0210b3 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_device.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_device.cc
@@ -6,6 +6,7 @@
#include "services/metrics/public/cpp/ukm_builders.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.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/frame/frame.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
@@ -18,80 +19,100 @@ namespace blink {
namespace {
-const char kActiveExclusiveSession[] =
- "XRDevice already has an active, exclusive session";
+const char kActiveImmersiveSession[] =
+ "XRDevice already has an active, immersive session";
-const char kExclusiveNotSupported[] =
- "XRDevice does not support the creation of exclusive sessions.";
+const char kImmersiveNotSupported[] =
+ "XRDevice does not support the creation of immersive sessions.";
const char kNoOutputContext[] =
- "Non-exclusive sessions must be created with an outputContext.";
+ "Non-immersive sessions must be created with an outputContext.";
const char kRequestRequiresUserActivation[] =
"The requested session requires user activation.";
+const char kSessionNotSupported[] =
+ "The specified session configuration is not supported.";
+
+const char kRequestFailed[] = "Request for XRSession failed.";
+
} // namespace
XRDevice::XRDevice(
XR* xr,
- device::mojom::blink::VRMagicWindowProviderPtr magic_window_provider,
device::mojom::blink::VRDisplayHostPtr display,
device::mojom::blink::VRDisplayClientRequest client_request,
device::mojom::blink::VRDisplayInfoPtr display_info)
: xr_(xr),
- magic_window_provider_(std::move(magic_window_provider)),
display_(std::move(display)),
display_client_binding_(this, std::move(client_request)) {
SetXRDisplayInfo(std::move(display_info));
}
-ExecutionContext* XRDevice::GetExecutionContext() const {
- return xr_->GetExecutionContext();
-}
-
-const AtomicString& XRDevice::InterfaceName() const {
- return EventTargetNames::XRDevice;
-}
-
const char* XRDevice::checkSessionSupport(
const XRSessionCreationOptions& options) const {
- if (options.exclusive()) {
- // Validation for exclusive sessions.
- if (!supports_exclusive_) {
- return kExclusiveNotSupported;
- }
- } else {
- // Validation for non-exclusive sessions.
+ if (!options.immersive()) {
+ // Validation for non-immersive sessions. Validation for immersive sessions
+ // happens browser side.
if (!options.hasOutputContext()) {
return kNoOutputContext;
}
}
+ if (options.environmentIntegration() && !supports_ar_) {
+ return kSessionNotSupported;
+ }
+
+ if (options.immersive() && !supports_immersive_) {
+ return kSessionNotSupported;
+ }
+
return nullptr;
}
ScriptPromise XRDevice::supportsSession(
ScriptState* script_state,
- const XRSessionCreationOptions& options) const {
+ const XRSessionCreationOptions& options) {
// Check to see if the device is capable of supporting the requested session
// options. Note that reporting support here does not guarantee that creating
// a session with those options will succeed, as other external and
- // time-sensitve factors (focus state, existance of another exclusive session,
+ // time-sensitve factors (focus state, existance of another immersive session,
// etc.) may prevent the creation of a session as well.
const char* reject_reason = checkSessionSupport(options);
if (reject_reason) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kNotSupportedError, reject_reason));
+ script_state, DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ reject_reason));
}
// If the above checks pass, resolve without a value. Future API iterations
// may specify a value to be returned here.
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
- resolver->Resolve();
+
+ device::mojom::blink::XRSessionOptionsPtr session_options =
+ device::mojom::blink::XRSessionOptions::New();
+ session_options->immersive = options.immersive();
+
+ display_->SupportsSession(
+ std::move(session_options),
+ WTF::Bind(&XRDevice::OnSupportsSessionReturned, WrapPersistent(this),
+ WrapPersistent(resolver)));
+
return promise;
}
+void XRDevice::OnSupportsSessionReturned(ScriptPromiseResolver* resolver,
+ bool supports_session) {
+ // kImmersiveNotSupported is currently the only reason that SupportsSession
+ // rejects on the browser side. That or there are no devices, but that should
+ // technically not be possible.
+ supports_session
+ ? resolver->Resolve()
+ : resolver->Reject(DOMException::Create(
+ DOMExceptionCode::kNotSupportedError, kImmersiveNotSupported));
+}
+
int64_t XRDevice::GetSourceId() const {
return xr_->GetSourceId();
}
@@ -101,11 +122,11 @@ ScriptPromise XRDevice::requestSession(
const XRSessionCreationOptions& options) {
Document* doc = ToDocumentOrNull(ExecutionContext::From(script_state));
- if (options.exclusive() && !did_log_request_exclusive_session_ && doc) {
+ if (options.immersive() && !did_log_request_immersive_session_ && doc) {
ukm::builders::XR_WebXR(GetSourceId())
.SetDidRequestPresentation(1)
.Record(doc->UkmRecorder());
- did_log_request_exclusive_session_ = true;
+ did_log_request_immersive_session_ = true;
}
// Check first to see if the device is capable of supporting the requested
@@ -113,53 +134,95 @@ ScriptPromise XRDevice::requestSession(
const char* reject_reason = checkSessionSupport(options);
if (reject_reason) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kNotSupportedError, reject_reason));
+ script_state, DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ reject_reason));
}
+ // TODO(ijamardo): Should we just exit if there is not document?
+ bool has_user_activation =
+ Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr);
+
// Check if the current page state prevents the requested session from being
// created.
- if (options.exclusive()) {
- if (frameProvider()->exclusive_session()) {
+ if (options.immersive()) {
+ if (frameProvider()->immersive_session()) {
return ScriptPromise::RejectWithDOMException(
script_state,
- DOMException::Create(kInvalidStateError, kActiveExclusiveSession));
+ DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kActiveImmersiveSession));
}
- if (!Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr)) {
+ if (!has_user_activation) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kSecurityError, kRequestRequiresUserActivation));
+ script_state, DOMException::Create(DOMExceptionCode::kSecurityError,
+ kRequestRequiresUserActivation));
}
}
// All AR sessions require a user gesture.
- // TODO(https://crbug.com/828321): Use session options instead.
- if (RuntimeEnabledFeatures::WebXRHitTestEnabled()) {
- if (!Frame::HasTransientUserActivation(doc ? doc->GetFrame() : nullptr)) {
+ if (options.environmentIntegration()) {
+ if (!has_user_activation) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kSecurityError, kRequestRequiresUserActivation));
+ script_state, DOMException::Create(DOMExceptionCode::kSecurityError,
+ kRequestRequiresUserActivation));
}
}
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
ScriptPromise promise = resolver->Promise();
+ device::mojom::blink::XRSessionOptionsPtr session_options =
+ device::mojom::blink::XRSessionOptions::New();
+ session_options->immersive = options.immersive();
+ session_options->provide_passthrough_camera =
+ options.environmentIntegration();
+ session_options->has_user_activation = has_user_activation;
+
+ // TODO(offenwanger): Once device activation is sorted out for WebXR, either
+ // pass in the value for metrics, or remove the value as soon as legacy API
+ // has been removed.
+ display_->RequestSession(
+ std::move(session_options), false /* triggered by display activate */,
+ WTF::Bind(&XRDevice::OnRequestSessionReturned, WrapWeakPersistent(this),
+ WrapPersistent(resolver), options));
+ return promise;
+}
+
+void XRDevice::OnRequestSessionReturned(
+ ScriptPromiseResolver* resolver,
+ const XRSessionCreationOptions& options,
+ device::mojom::blink::XRSessionPtr session_ptr) {
+ if (!session_ptr) {
+ DOMException* exception = DOMException::Create(
+ DOMExceptionCode::kNotAllowedError, kRequestFailed);
+ resolver->Reject(exception);
+ return;
+ }
+
+ if (session_ptr->magic_window_provider)
+ magic_window_provider_.Bind(std::move(session_ptr->magic_window_provider));
+
XRPresentationContext* output_context = nullptr;
if (options.hasOutputContext()) {
output_context = options.outputContext();
}
- XRSession* session = new XRSession(this, options.exclusive(), output_context);
+ XRSession::EnvironmentBlendMode blend_mode = XRSession::kBlendModeOpaque;
+ if (options.environmentIntegration()) {
+ blend_mode = XRSession::kBlendModeAlphaBlend;
+ }
+
+ XRSession* session =
+ new XRSession(this, options.immersive(), options.environmentIntegration(),
+ output_context, blend_mode);
sessions_.insert(session);
- if (options.exclusive()) {
- frameProvider()->BeginExclusiveSession(session, resolver);
- } else {
- resolver->Resolve(session);
+ if (options.immersive()) {
+ frameProvider()->BeginImmersiveSession(session,
+ std::move(session_ptr->connection));
}
- return promise;
+ resolver->Resolve(session);
}
void XRDevice::OnFrameFocusChanged() {
@@ -188,7 +251,7 @@ void XRDevice::OnExitPresent() {}
void XRDevice::OnBlur() {
// The device is reporting to us that it is blurred. This could happen for a
// variety of reasons, such as browser UI, a different application using the
- // headset, or another page entering an exclusive session.
+ // headset, or another page entering an immersive session.
has_device_focus_ = false;
OnFocusChanged();
}
@@ -219,14 +282,15 @@ void XRDevice::SetXRDisplayInfo(
display_info_id_++;
display_info_ = std::move(display_info);
is_external_ = display_info_->capabilities->hasExternalDisplay;
- supports_exclusive_ = (display_info_->capabilities->canPresent);
+ supports_immersive_ = (display_info_->capabilities->canPresent);
+ supports_ar_ = display_info_->capabilities->can_provide_pass_through_images;
}
void XRDevice::Trace(blink::Visitor* visitor) {
visitor->Trace(xr_);
visitor->Trace(frame_provider_);
visitor->Trace(sessions_);
- EventTargetWithInlineData::Trace(visitor);
+ ScriptWrappable::Trace(visitor);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_device.h b/chromium/third_party/blink/renderer/modules/xr/xr_device.h
index 9ecd7fc6eae..f4db8e216aa 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_device.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_device.h
@@ -8,25 +8,26 @@
#include "device/vr/public/mojom/vr_service.mojom-blink.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/core/dom/events/event_target.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/modules/xr/xr_session_creation_options.h"
+#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/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
+class ScriptPromiseResolver;
class XR;
class XRFrameProvider;
class XRSession;
-class XRDevice final : public EventTargetWithInlineData,
+class XRDevice final : public ScriptWrappable,
public device::mojom::blink::VRDisplayClient {
DEFINE_WRAPPERTYPEINFO();
public:
XRDevice(XR*,
- device::mojom::blink::VRMagicWindowProviderPtr,
device::mojom::blink::VRDisplayHostPtr,
device::mojom::blink::VRDisplayClientRequest,
device::mojom::blink::VRDisplayInfoPtr);
@@ -34,15 +35,9 @@ class XRDevice final : public EventTargetWithInlineData,
bool external() const { return is_external_; }
- ScriptPromise supportsSession(ScriptState*,
- const XRSessionCreationOptions&) const;
+ ScriptPromise supportsSession(ScriptState*, const XRSessionCreationOptions&);
ScriptPromise requestSession(ScriptState*, const XRSessionCreationOptions&);
- // EventTarget overrides.
- ExecutionContext* GetExecutionContext() const override;
- const AtomicString& InterfaceName() const override;
- void Trace(blink::Visitor*) override;
-
// XRDisplayClient
void OnChanged(device::mojom::blink::VRDisplayInfoPtr) override;
void OnExitPresent() override;
@@ -77,15 +72,23 @@ class XRDevice final : public EventTargetWithInlineData,
bool HasDeviceFocus() { return has_device_focus_; }
bool HasDeviceAndFrameFocus() { return IsFrameFocused() && HasDeviceFocus(); }
- bool SupportsExclusive() { return supports_exclusive_; }
+ bool SupportsImmersive() { return supports_immersive_; }
int64_t GetSourceId() const;
+ void Trace(blink::Visitor*) override;
+
private:
void SetXRDisplayInfo(device::mojom::blink::VRDisplayInfoPtr);
const char* checkSessionSupport(const XRSessionCreationOptions&) const;
+ void OnRequestSessionReturned(ScriptPromiseResolver* resolver,
+ const XRSessionCreationOptions& options,
+ device::mojom::blink::XRSessionPtr session);
+ void OnSupportsSessionReturned(ScriptPromiseResolver* resolver,
+ bool supports_session);
+
// There are two components to focus - whether the frame itself has
// traditional focus and whether the device reports that we have focus. These
// are aggregated so we can hand out focus/blur events on sessions and
@@ -96,12 +99,13 @@ class XRDevice final : public EventTargetWithInlineData,
Member<XR> xr_;
Member<XRFrameProvider> frame_provider_;
HeapHashSet<WeakMember<XRSession>> sessions_;
- bool is_external_;
- bool supports_exclusive_;
+ bool is_external_ = false;
+ bool supports_immersive_ = false;
+ bool supports_ar_ = false;
bool has_device_focus_ = true;
- // Indicates whether we've already logged a request for an exclusive session.
- bool did_log_request_exclusive_session_ = false;
+ // Indicates whether we've already logged a request for an immersive session.
+ bool did_log_request_immersive_session_ = false;
device::mojom::blink::VRMagicWindowProviderPtr magic_window_provider_;
device::mojom::blink::VRDisplayHostPtr display_;
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_device.idl b/chromium/third_party/blink/renderer/modules/xr/xr_device.idl
index 16a78316107..30e102b5e07 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_device.idl
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_device.idl
@@ -6,7 +6,7 @@
[
SecureContext,
OriginTrialEnabled=WebXR
-] interface XRDevice : EventTarget {
+] interface XRDevice {
[CallWith=ScriptState, MeasureAs=XRSupportsSession] Promise supportsSession([PermissiveDictionaryConversion] optional XRSessionCreationOptions options);
[CallWith=ScriptState, MeasureAs=XRRequestSession] Promise requestSession([PermissiveDictionaryConversion] optional XRSessionCreationOptions options);
};
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_frame.cc b/chromium/third_party/blink/renderer/modules/xr/xr_frame.cc
new file mode 100644
index 00000000000..aa0f07eb382
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_frame.cc
@@ -0,0 +1,129 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/xr/xr_frame.h"
+
+#include "third_party/blink/renderer/modules/xr/xr_coordinate_system.h"
+#include "third_party/blink/renderer/modules/xr/xr_device_pose.h"
+#include "third_party/blink/renderer/modules/xr/xr_input_pose.h"
+#include "third_party/blink/renderer/modules/xr/xr_input_source.h"
+#include "third_party/blink/renderer/modules/xr/xr_session.h"
+#include "third_party/blink/renderer/modules/xr/xr_view.h"
+
+namespace blink {
+
+XRFrame::XRFrame(XRSession* session) : session_(session) {}
+
+const HeapVector<Member<XRView>>& XRFrame::views() const {
+ return session_->views();
+}
+
+XRDevicePose* XRFrame::getDevicePose(
+ XRCoordinateSystem* coordinate_system) const {
+ session_->LogGetPose();
+
+ // If we don't have a valid base pose return null. Most common when tracking
+ // is lost.
+ if (!base_pose_matrix_ || !coordinate_system) {
+ return nullptr;
+ }
+
+ // Must use a coordinate system created from the same session.
+ if (coordinate_system->session() != session_) {
+ return nullptr;
+ }
+
+ std::unique_ptr<TransformationMatrix> pose =
+ coordinate_system->TransformBasePose(*base_pose_matrix_);
+
+ if (!pose) {
+ return nullptr;
+ }
+
+ return new XRDevicePose(session(), std::move(pose));
+}
+
+XRInputPose* XRFrame::getInputPose(
+ XRInputSource* input_source,
+ XRCoordinateSystem* coordinate_system) const {
+ if (!input_source || !coordinate_system) {
+ return nullptr;
+ }
+
+ // Must use an input source and coordinate system from the same session.
+ if (input_source->session() != session_ ||
+ coordinate_system->session() != session_) {
+ return nullptr;
+ }
+
+ switch (input_source->target_ray_mode_) {
+ case XRInputSource::kScreen: {
+ // If the pointer origin is the screen we need the head's base pose and
+ // the pointer transform matrix to continue. The pointer transform will
+ // represent the point the canvas was clicked as an offset from the view.
+ if (!base_pose_matrix_ || !input_source->pointer_transform_matrix_) {
+ return nullptr;
+ }
+
+ // Multiply the head pose and pointer transform to get the final pointer.
+ std::unique_ptr<TransformationMatrix> pointer_pose =
+ coordinate_system->TransformBasePose(*base_pose_matrix_);
+ pointer_pose->Multiply(*(input_source->pointer_transform_matrix_));
+
+ return new XRInputPose(std::move(pointer_pose), nullptr);
+ }
+ case XRInputSource::kGaze: {
+ // If the pointer origin is the users head, this is a gaze cursor and the
+ // returned pointer is based on the device pose. If we don't have a valid
+ // base pose (most common when tracking is lost) return null.
+ if (!base_pose_matrix_) {
+ return nullptr;
+ }
+
+ // Just return the head pose as the pointer pose.
+ std::unique_ptr<TransformationMatrix> pointer_pose =
+ coordinate_system->TransformBasePose(*base_pose_matrix_);
+
+ return new XRInputPose(std::move(pointer_pose), nullptr,
+ input_source->emulatedPosition());
+ }
+ case XRInputSource::kTrackedPointer: {
+ // If the input source doesn't have a base pose return null;
+ if (!input_source->base_pose_matrix_) {
+ return nullptr;
+ }
+
+ std::unique_ptr<TransformationMatrix> grip_pose =
+ coordinate_system->TransformBaseInputPose(
+ *(input_source->base_pose_matrix_), *base_pose_matrix_);
+
+ if (!grip_pose) {
+ return nullptr;
+ }
+
+ std::unique_ptr<TransformationMatrix> pointer_pose(
+ TransformationMatrix::Create(*grip_pose));
+
+ if (input_source->pointer_transform_matrix_) {
+ pointer_pose->Multiply(*(input_source->pointer_transform_matrix_));
+ }
+
+ return new XRInputPose(std::move(pointer_pose), std::move(grip_pose),
+ input_source->emulatedPosition());
+ }
+ }
+
+ return nullptr;
+}
+
+void XRFrame::SetBasePoseMatrix(const TransformationMatrix& base_pose_matrix) {
+ base_pose_matrix_ = TransformationMatrix::Create(base_pose_matrix);
+}
+
+void XRFrame::Trace(blink::Visitor* visitor) {
+ visitor->Trace(session_);
+ ScriptWrappable::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_frame.h b/chromium/third_party/blink/renderer/modules/xr/xr_frame.h
new file mode 100644
index 00000000000..0af9ba5c298
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_frame.h
@@ -0,0 +1,47 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_FRAME_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_FRAME_H_
+
+#include "device/vr/public/mojom/vr_service.mojom-blink.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace blink {
+
+class XRCoordinateSystem;
+class XRDevicePose;
+class XRInputPose;
+class XRInputSource;
+class XRSession;
+class XRView;
+
+class XRFrame final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ explicit XRFrame(XRSession*);
+
+ XRSession* session() const { return session_; }
+
+ const HeapVector<Member<XRView>>& views() const;
+ XRDevicePose* getDevicePose(XRCoordinateSystem*) const;
+ XRInputPose* getInputPose(XRInputSource*, XRCoordinateSystem*) const;
+
+ void SetBasePoseMatrix(const TransformationMatrix&);
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ const Member<XRSession> session_;
+ std::unique_ptr<TransformationMatrix> base_pose_matrix_;
+};
+
+} // namespace blink
+
+#endif // XRWebGLLayer_h
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_frame.idl b/chromium/third_party/blink/renderer/modules/xr/xr_frame.idl
new file mode 100644
index 00000000000..bfa5a79ce9d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_frame.idl
@@ -0,0 +1,16 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// https://immersive-web.github.io/webxr/#xrframe
+[
+ SecureContext,
+ OriginTrialEnabled=WebXR
+] interface XRFrame {
+ readonly attribute XRSession session;
+ readonly attribute FrozenArray<XRView> views;
+
+ XRDevicePose? getDevicePose(XRCoordinateSystem coordinateSystem);
+ XRInputPose? getInputPose(XRInputSource inputSource,
+ XRCoordinateSystem coordinateSystem);
+};
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_frame_of_reference.cc b/chromium/third_party/blink/renderer/modules/xr/xr_frame_of_reference.cc
index 3bc1dc4813c..d58997d19ba 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_frame_of_reference.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_frame_of_reference.cc
@@ -115,7 +115,7 @@ std::unique_ptr<TransformationMatrix> XRFrameOfReference::TransformBasePose(
}
// Serves the same purpose as TransformBasePose, but for input poses. Needs to
-// know the head pose so that cases like the headModel frame of reference can
+// know the head pose so that cases like the head-model frame of reference can
// properly adjust the input's relative position.
std::unique_ptr<TransformationMatrix>
XRFrameOfReference::TransformBaseInputPose(
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_frame_of_reference.idl b/chromium/third_party/blink/renderer/modules/xr/xr_frame_of_reference.idl
index 7db8630760e..e5e797d6769 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_frame_of_reference.idl
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_frame_of_reference.idl
@@ -5,8 +5,8 @@
// https://immersive-web.github.io/webxr/#xrframeofreference-interface
enum XRFrameOfReferenceType {
- "headModel",
- "eyeLevel",
+ "head-model",
+ "eye-level",
"stage",
};
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_frame_provider.cc b/chromium/third_party/blink/renderer/modules/xr/xr_frame_provider.cc
index 0a9b3162fe6..8a5a4e9b791 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_frame_provider.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_frame_provider.cc
@@ -35,7 +35,7 @@ class XRFrameProviderRequestCallback
: frame_provider_(frame_provider) {}
~XRFrameProviderRequestCallback() override = default;
void Invoke(double high_res_time_ms) override {
- frame_provider_->OnNonExclusiveVSync(high_res_time_ms / 1000.0);
+ frame_provider_->OnNonImmersiveVSync(high_res_time_ms);
}
void Trace(blink::Visitor* visitor) override {
@@ -86,67 +86,32 @@ std::unique_ptr<TransformationMatrix> getPoseMatrix(
} // namespace
XRFrameProvider::XRFrameProvider(XRDevice* device)
- : device_(device), last_has_focus_(device->HasDeviceAndFrameFocus()) {}
-
-void XRFrameProvider::BeginExclusiveSession(XRSession* session,
- ScriptPromiseResolver* resolver) {
- // Make sure the session is indeed an exclusive one.
- DCHECK(session && session->exclusive());
-
- // Ensure we can only have one exclusive session at a time.
- DCHECK(!exclusive_session_);
- DCHECK(!exclusive_session_can_send_frames_);
-
- exclusive_session_ = session;
- exclusive_session_can_send_frames_ = false;
-
- pending_exclusive_session_resolver_ = resolver;
-
- // Establish the connection with the VSyncProvider if needed.
- if (!presentation_provider_.is_bound()) {
- frame_transport_ = new XRFrameTransport();
-
- // Set up RequestPresentOptions based on canvas properties.
- device::mojom::blink::VRRequestPresentOptionsPtr options =
- device::mojom::blink::VRRequestPresentOptions::New();
- options->preserve_drawing_buffer = false;
- options->webxr_input = true;
- options->shared_buffer_draw_supported = true;
-
- // TODO(offenwanger): Once device activation is sorted out for WebXR, either
- // pass in the value for metrics, or remove it as soon as legacy API has
- // been removed.
- device_->xrDisplayHostPtr()->RequestPresent(
- frame_transport_->GetSubmitFrameClient(),
- mojo::MakeRequest(&presentation_provider_), std::move(options), false,
- WTF::Bind(&XRFrameProvider::OnPresentComplete, WrapPersistent(this)));
-
- presentation_provider_.set_connection_error_handler(
- WTF::Bind(&XRFrameProvider::OnPresentationProviderConnectionError,
- WrapWeakPersistent(this)));
- }
+ : device_(device), last_has_focus_(device->HasDeviceAndFrameFocus()) {
+ frame_transport_ = new XRFrameTransport();
}
-void XRFrameProvider::OnPresentComplete(
- bool success,
- device::mojom::blink::VRDisplayFrameTransportOptionsPtr transport_options) {
- if (success) {
- frame_transport_->SetTransportOptions(std::move(transport_options));
- frame_transport_->PresentChange();
- pending_exclusive_session_resolver_->Resolve(exclusive_session_);
- exclusive_session_can_send_frames_ = true;
- } else {
- exclusive_session_->ForceEnd();
- exclusive_session_can_send_frames_ = false;
+void XRFrameProvider::BeginImmersiveSession(
+ XRSession* session,
+ device::mojom::blink::XRPresentationConnectionPtr connection) {
+ // Make sure the session is indeed an immersive one.
+ DCHECK(session && session->immersive());
- if (pending_exclusive_session_resolver_) {
- DOMException* exception = DOMException::Create(
- kNotAllowedError, "Request for exclusive XRSession was denied.");
- pending_exclusive_session_resolver_->Reject(exception);
- }
- }
+ // Ensure we can only have one immersive session at a time.
+ DCHECK(!immersive_session_);
+ DCHECK(connection);
- pending_exclusive_session_resolver_ = nullptr;
+ immersive_session_ = session;
+
+ presentation_provider_.Bind(std::move(connection->provider));
+ presentation_provider_.set_connection_error_handler(
+ WTF::Bind(&XRFrameProvider::OnPresentationProviderConnectionError,
+ WrapWeakPersistent(this)));
+
+ frame_transport_->BindSubmitFrameClient(
+ std::move(connection->client_request));
+ frame_transport_->SetTransportOptions(
+ std::move(connection->transport_options));
+ frame_transport_->PresentChange();
}
void XRFrameProvider::OnFocusChanged() {
@@ -154,55 +119,46 @@ void XRFrameProvider::OnFocusChanged() {
// If we are gaining focus, schedule a frame for magic window. This accounts
// for skipping RAFs in ProcessScheduledFrame. Only do this when there are
- // magic window sessions but no exclusive session. Note that exclusive
+ // magic window sessions but no immersive session. Note that immersive
// sessions don't stop scheduling RAFs when focus is lost, so there is no need
- // to schedule exclusive frames when focus is acquired.
+ // to schedule immersive frames when focus is acquired.
if (focus && !last_has_focus_ && requesting_sessions_.size() > 0 &&
- !exclusive_session_) {
- ScheduleNonExclusiveFrame();
+ !immersive_session_) {
+ ScheduleNonImmersiveFrame();
}
last_has_focus_ = focus;
}
void XRFrameProvider::OnPresentationProviderConnectionError() {
- if (pending_exclusive_session_resolver_) {
- DOMException* exception = DOMException::Create(
- kNotAllowedError,
- "Error occured while requesting exclusive XRSession.");
- pending_exclusive_session_resolver_->Reject(exception);
- pending_exclusive_session_resolver_ = nullptr;
- }
presentation_provider_.reset();
if (vsync_connection_failed_)
return;
- exclusive_session_->ForceEnd();
- exclusive_session_can_send_frames_ = false;
+ immersive_session_->ForceEnd();
vsync_connection_failed_ = true;
}
-// Called by the exclusive session when it is ended.
-void XRFrameProvider::OnExclusiveSessionEnded() {
- if (!exclusive_session_)
+// Called by the immersive session when it is ended.
+void XRFrameProvider::OnImmersiveSessionEnded() {
+ if (!immersive_session_)
return;
device_->xrDisplayHostPtr()->ExitPresent();
- exclusive_session_ = nullptr;
- exclusive_session_can_send_frames_ = false;
- pending_exclusive_vsync_ = false;
+ immersive_session_ = nullptr;
+ pending_immersive_vsync_ = false;
frame_id_ = -1;
if (presentation_provider_.is_bound()) {
presentation_provider_.reset();
}
- frame_transport_ = nullptr;
+ frame_transport_ = new XRFrameTransport();
- // When we no longer have an active exclusive session schedule all the
- // outstanding frames that were requested while the exclusive session was
+ // When we no longer have an active immersive session schedule all the
+ // outstanding frames that were requested while the immersive session was
// active.
if (requesting_sessions_.size() > 0)
- ScheduleNonExclusiveFrame();
+ ScheduleNonImmersiveFrame();
}
// Schedule a session to be notified when the next XR frame is available.
@@ -210,125 +166,117 @@ void XRFrameProvider::RequestFrame(XRSession* session) {
TRACE_EVENT0("gpu", __FUNCTION__);
DCHECK(session);
- // Exclusive frame logic.
- if (session->exclusive()) {
- ScheduleExclusiveFrame();
+ // Immersive frame logic.
+ if (session->immersive()) {
+ ScheduleImmersiveFrame();
return;
}
- // Non-exclusive frame logic.
+ // Non-immersive frame logic.
requesting_sessions_.push_back(session);
- // If there's an active exclusive session save the request but suppress
- // processing it until the exclusive session is no longer active.
- if (exclusive_session_)
+ // If there's an active immersive session save the request but suppress
+ // processing it until the immersive session is no longer active.
+ if (immersive_session_)
return;
- if (device_->xrDisplayInfoPtr()
- ->capabilities->can_provide_pass_through_images) {
- DoubleSize session_size_double = session->OutputCanvasSize();
- IntSize session_size(session_size_double.Width(),
- session_size_double.Height());
- ar_requested_transfer_size_ =
- ar_requested_transfer_size_.ExpandedTo(session_size);
- // Have to pick an angle so we'll take the last angle.
- ar_requested_transfer_angle_ = session->OutputCanvasAngle();
+ ScheduleNonImmersiveFrame();
+}
+
+bool XRFrameProvider::HasARSession() {
+ for (unsigned i = 0; i < requesting_sessions_.size(); ++i) {
+ XRSession* session = requesting_sessions_.at(i).Get();
+ if (session->environmentIntegration())
+ return true;
}
- ScheduleNonExclusiveFrame();
+ return false;
}
-void XRFrameProvider::ScheduleExclusiveFrame() {
+void XRFrameProvider::ScheduleImmersiveFrame() {
TRACE_EVENT0("gpu", __FUNCTION__);
- if (pending_exclusive_vsync_)
+ if (pending_immersive_vsync_)
return;
- pending_exclusive_vsync_ = true;
+ pending_immersive_vsync_ = true;
- presentation_provider_->GetVSync(
- WTF::Bind(&XRFrameProvider::OnExclusiveVSync, WrapWeakPersistent(this)));
+ presentation_provider_->GetFrameData(WTF::Bind(
+ &XRFrameProvider::OnImmersiveFrameData, WrapWeakPersistent(this)));
}
-// TODO(lincolnfrog): add a ScheduleNonExclusiveARFrame, if we want camera RAF
+// TODO(lincolnfrog): add a ScheduleNonImmersiveARFrame, if we want camera RAF
// alignment instead of doc RAF alignment.
-void XRFrameProvider::ScheduleNonExclusiveFrame() {
+void XRFrameProvider::ScheduleNonImmersiveFrame() {
TRACE_EVENT0("gpu", __FUNCTION__);
- DCHECK(!exclusive_session_)
+ DCHECK(!immersive_session_)
<< "Scheduling should be done via the exclusive session if present.";
+ DCHECK(device_->xrMagicWindowProviderPtr())
+ << "If there is no exclusive session, it should be impossible to "
+ "schedule a frame without a MagicWindowProvider.";
- if (pending_non_exclusive_vsync_)
+ if (pending_non_immersive_vsync_)
return;
LocalFrame* frame = device_->xr()->GetFrame();
if (!frame)
return;
+ // TODO(https://crbug.com/856224) Review the lifetime of this object and
+ // ensure that doc can never be null and remove this check.
Document* doc = frame->GetDocument();
if (!doc)
return;
- pending_non_exclusive_vsync_ = true;
+ pending_non_immersive_vsync_ = true;
+
+ device_->xrMagicWindowProviderPtr()->GetFrameData(WTF::Bind(
+ &XRFrameProvider::OnNonImmersiveFrameData, WrapWeakPersistent(this)));
// TODO(https://crbug.com/839253): Generalize the pass-through images
- // code path so that it also works for exclusive sessions on an AR device
+ // code path so that it also works for immersive sessions on an AR device
// with pass-through technology.
- if (device_->xrDisplayInfoPtr()
- ->capabilities->can_provide_pass_through_images) {
- DVLOG(2) << __FUNCTION__ << ": transfer_size "
- << ar_requested_transfer_size_.Width() << "x"
- << ar_requested_transfer_size_.Height()
- << " angle=" << ar_requested_transfer_angle_;
- DCHECK(display::Display::IsValidRotation(ar_requested_transfer_angle_));
-
- // TODO(https://crbug.com/836496): ensure valid frame sizes, including when
- // using multiple sessions. Currently, we take the max size of all the
- // active session's requested sizes and pass that to the browser as-is.
- // Unsupported sizes such as zero or excessively large ones may be rejected
- // by the device, resulting in null MagicWindowFrameData responses.
- // Requests for frames of 0 size are making it to this point - we should
- // ensure that frames are not scheduled until the frame context is ready.
- // In the future, we should signal an error back to the client.
-
- device_->xrMagicWindowProviderPtr()->GetFrameData(
- ar_requested_transfer_size_,
- display::Display::DegreesToRotation(ar_requested_transfer_angle_),
- WTF::Bind(&XRFrameProvider::OnNonExclusiveFrameData,
- WrapWeakPersistent(this)));
- } else {
- device_->xrMagicWindowProviderPtr()->GetPose(WTF::Bind(
- &XRFrameProvider::OnNonExclusivePose, WrapWeakPersistent(this)));
+
+ // TODO(http://crbug.com/856257) Remove the special casing for AR and non-AR.
+ if (!HasARSession()) {
doc->RequestAnimationFrame(new XRFrameProviderRequestCallback(this));
}
}
-void XRFrameProvider::OnExclusiveVSync(
- device::mojom::blink::VRPosePtr pose,
- WTF::TimeDelta time_delta,
- int16_t frame_id,
- device::mojom::blink::VRPresentationProvider::VSyncStatus status,
- const base::Optional<gpu::MailboxHolder>& buffer_holder) {
+void XRFrameProvider::OnImmersiveFrameData(
+ device::mojom::blink::XRFrameDataPtr data) {
TRACE_EVENT0("gpu", __FUNCTION__);
DVLOG(2) << __FUNCTION__;
vsync_connection_failed_ = false;
- switch (status) {
- case device::mojom::blink::VRPresentationProvider::VSyncStatus::SUCCESS:
- break;
- case device::mojom::blink::VRPresentationProvider::VSyncStatus::CLOSING:
- return;
+ if (!data) {
+ return;
}
- // We may have lost the exclusive session since the last VSync request.
- if (!exclusive_session_) {
+ // We may have lost the immersive session since the last VSync request.
+ if (!immersive_session_) {
// TODO(https://crbug.com/836496): do we need to include this in the
- // image size calculation for AR? What about exclusive AR (full-screen?)
+ // image size calculation for AR? What about immersive AR (full-screen?)
return;
}
- frame_pose_ = std::move(pose);
- frame_id_ = frame_id;
- buffer_mailbox_holder_ = buffer_holder;
+ LocalFrame* frame = device_->xr()->GetFrame();
+ if (!frame)
+ return;
+ Document* doc = frame->GetDocument();
+ if (!doc)
+ return;
+
+ base::TimeTicks monotonic_time_now = TimeTicks() + data->time_delta;
+ double high_res_now_ms =
+ doc->Loader()
+ ->GetTiming()
+ .MonotonicTimeToZeroBasedDocumentTime(monotonic_time_now)
+ .InMillisecondsF();
- pending_exclusive_vsync_ = false;
+ frame_pose_ = std::move(data->pose);
+ frame_id_ = data->frame_id;
+ buffer_mailbox_holder_ = data->buffer_holder;
+
+ pending_immersive_vsync_ = false;
// Post a task to handle scheduled animations after the current
// execution context finishes, so that we yield to non-mojo tasks in
@@ -336,141 +284,128 @@ void XRFrameProvider::OnExclusiveVSync(
// execution context caused extreme input delay due to processing
// multiple frames without yielding, see crbug.com/701444.
Platform::Current()->CurrentThread()->GetTaskRunner()->PostTask(
- FROM_HERE,
- WTF::Bind(&XRFrameProvider::ProcessScheduledFrame,
- WrapWeakPersistent(this), nullptr, time_delta.InSecondsF()));
+ FROM_HERE, WTF::Bind(&XRFrameProvider::ProcessScheduledFrame,
+ WrapWeakPersistent(this), nullptr, high_res_now_ms));
}
-void XRFrameProvider::OnNonExclusiveVSync(double timestamp) {
+void XRFrameProvider::OnNonImmersiveVSync(double high_res_now_ms) {
TRACE_EVENT0("gpu", __FUNCTION__);
DVLOG(2) << __FUNCTION__;
- pending_non_exclusive_vsync_ = false;
+ pending_non_immersive_vsync_ = false;
- // Suppress non-exclusive vsyncs when there's an exclusive session active.
- if (exclusive_session_)
+ // Suppress non-immersive vsyncs when there's an immersive session active.
+ if (immersive_session_)
return;
Platform::Current()->CurrentThread()->GetTaskRunner()->PostTask(
FROM_HERE, WTF::Bind(&XRFrameProvider::ProcessScheduledFrame,
- WrapWeakPersistent(this), nullptr, timestamp));
-}
-
-void XRFrameProvider::OnNonExclusivePose(device::mojom::blink::VRPosePtr pose) {
- frame_pose_ = std::move(pose);
+ WrapWeakPersistent(this), nullptr, high_res_now_ms));
}
-void XRFrameProvider::OnNonExclusiveFrameData(
- device::mojom::blink::VRMagicWindowFrameDataPtr frame_data) {
+void XRFrameProvider::OnNonImmersiveFrameData(
+ device::mojom::blink::XRFrameDataPtr frame_data) {
TRACE_EVENT0("gpu", __FUNCTION__);
DVLOG(2) << __FUNCTION__;
// TODO(https://crbug.com/837834): add unit tests for this code path.
- pending_non_exclusive_vsync_ = false;
+ pending_non_immersive_vsync_ = false;
+ LocalFrame* frame = device_->xr()->GetFrame();
+ if (!frame)
+ return;
+ Document* doc = frame->GetDocument();
+ if (!doc)
+ return;
if (!frame_data) {
// Unexpectedly didn't get frame data, and we don't have a timestamp.
// Try to request a regular animation frame to avoid getting stuck.
DVLOG(1) << __FUNCTION__ << ": NO FRAME DATA!";
frame_pose_ = nullptr;
- LocalFrame* frame = device_->xr()->GetFrame();
- if (!frame)
- return;
- Document* doc = frame->GetDocument();
- if (!doc)
- return;
doc->RequestAnimationFrame(new XRFrameProviderRequestCallback(this));
return;
}
frame_pose_ = std::move(frame_data->pose);
- double timestamp = frame_data->time_delta.InSecondsF();
-
- Platform::Current()->CurrentThread()->GetTaskRunner()->PostTask(
- FROM_HERE,
- WTF::Bind(&XRFrameProvider::ProcessScheduledFrame,
- WrapWeakPersistent(this), std::move(frame_data), timestamp));
-}
-
-// TODO(836349): revisit sending this data to blink at all.
-void XRFrameProvider::RenderBackgroundImage(
- const device::mojom::blink::VRMagicWindowFrameDataPtr& frame_data,
- XRSession* session) {
- DCHECK(frame_data);
- TRACE_EVENT0("gpu", __FUNCTION__);
-
- XRLayer* layer = session->baseLayer();
- if (!layer)
- return;
-
- // TODO(https://crbug.com/837509): Remove this static_cast.
- XRWebGLLayer* webgl_layer = static_cast<XRWebGLLayer*>(layer);
- webgl_layer->OverwriteColorBufferFromMailboxTexture(
- frame_data->buffer_holder, IntSize(frame_data->buffer_size));
+ base::TimeTicks monotonic_time_now = TimeTicks() + frame_data->time_delta;
+ double high_res_now_ms =
+ doc->Loader()
+ ->GetTiming()
+ .MonotonicTimeToZeroBasedDocumentTime(monotonic_time_now)
+ .InMillisecondsF();
+
+ if (HasARSession()) {
+ Platform::Current()->CurrentThread()->GetTaskRunner()->PostTask(
+ FROM_HERE, WTF::Bind(&XRFrameProvider::ProcessScheduledFrame,
+ WrapWeakPersistent(this), std::move(frame_data),
+ high_res_now_ms));
+ }
}
void XRFrameProvider::ProcessScheduledFrame(
- device::mojom::blink::VRMagicWindowFrameDataPtr frame_data,
- double timestamp) {
+ device::mojom::blink::XRFrameDataPtr frame_data,
+ double high_res_now_ms) {
DVLOG(2) << __FUNCTION__;
- TRACE_EVENT1("gpu", "XRFrameProvider::ProcessScheduledFrame", "frame",
- frame_id_);
+ TRACE_EVENT2("gpu", "XRFrameProvider::ProcessScheduledFrame", "frame",
+ frame_id_, "timestamp", high_res_now_ms);
- if (!device_->HasDeviceAndFrameFocus() && !exclusive_session_) {
+ if (!device_->HasDeviceAndFrameFocus() && !immersive_session_) {
return; // Not currently focused, so we won't expose poses (except to
- // exclusive sessions).
+ // immersive sessions).
}
- if (exclusive_session_can_send_frames_) {
+ if (immersive_session_) {
if (frame_pose_ && frame_pose_->input_state.has_value()) {
- exclusive_session_->OnInputStateChange(frame_id_,
+ immersive_session_->OnInputStateChange(frame_id_,
frame_pose_->input_state.value());
}
+ // Check if immersive session is still set as OnInputStateChange may have
+ // allowed a ForceEndSession to be triggered.
+ if (!immersive_session_)
+ return;
+
if (frame_pose_ && frame_pose_->pose_reset) {
- exclusive_session_->OnPoseReset();
+ immersive_session_->OnPoseReset();
}
- // If there's an exclusive session active only process its frame.
+ // Check if immersive session is still set as OnPoseReset may have allowed a
+ // ForceEndSession to be triggered.
+ if (!immersive_session_)
+ return;
+
+ // If there's an immersive session active only process its frame.
std::unique_ptr<TransformationMatrix> pose_matrix =
getPoseMatrix(frame_pose_);
// Sanity check: if drawing into a shared buffer, the optional mailbox
// holder must be present.
DCHECK(!frame_transport_->DrawingIntoSharedBuffer() ||
buffer_mailbox_holder_);
- exclusive_session_->OnFrame(std::move(pose_matrix), buffer_mailbox_holder_);
+ immersive_session_->OnFrame(high_res_now_ms, std::move(pose_matrix),
+ buffer_mailbox_holder_, base::nullopt,
+ base::nullopt);
} else {
// In the process of fulfilling the frame requests for each session they are
// extremely likely to request another frame. Work off of a separate list
// from the requests to prevent infinite loops.
HeapVector<Member<XRSession>> processing_sessions;
swap(requesting_sessions_, processing_sessions);
- if (device_->xrDisplayInfoPtr()
- ->capabilities->can_provide_pass_through_images) {
- // Clear the AR transfer size for next frame.
- ar_requested_transfer_size_.SetWidth(0);
- ar_requested_transfer_size_.SetHeight(0);
- }
// Inform sessions with a pending request of the new frame
for (unsigned i = 0; i < processing_sessions.size(); ++i) {
XRSession* session = processing_sessions.at(i).Get();
- if (frame_data) {
- // TODO(https://crbug.com/837883): only render background for
- // sessions that are using AR.
- RenderBackgroundImage(frame_data, session);
- }
if (frame_pose_ && frame_pose_->input_state.has_value()) {
session->OnInputStateChange(frame_id_,
frame_pose_->input_state.value());
}
- if (frame_data) {
- session->SetNonExclusiveProjectionMatrix(frame_data->projection_matrix);
+ if (frame_data && frame_data->projection_matrix.has_value()) {
+ session->SetNonImmersiveProjectionMatrix(
+ frame_data->projection_matrix.value());
}
if (frame_pose_ && frame_pose_->pose_reset) {
@@ -479,14 +414,23 @@ void XRFrameProvider::ProcessScheduledFrame(
std::unique_ptr<TransformationMatrix> pose_matrix =
getPoseMatrix(frame_pose_);
- session->OnFrame(std::move(pose_matrix), base::nullopt);
+ // TODO(https://crbug.com/837883): only render background for
+ // sessions that are using AR.
+ if (frame_data) {
+ session->OnFrame(high_res_now_ms, std::move(pose_matrix), base::nullopt,
+ frame_data->buffer_holder, frame_data->buffer_size);
+ } else {
+ session->OnFrame(high_res_now_ms, std::move(pose_matrix), base::nullopt,
+ base::nullopt, base::nullopt);
+ }
}
}
}
void XRFrameProvider::SubmitWebGLLayer(XRWebGLLayer* layer, bool was_changed) {
DCHECK(layer);
- DCHECK(layer->session() == exclusive_session_);
+ DCHECK(immersive_session_);
+ DCHECK(layer->session() == immersive_session_);
if (!presentation_provider_.is_bound())
return;
@@ -494,9 +438,18 @@ void XRFrameProvider::SubmitWebGLLayer(XRWebGLLayer* layer, bool was_changed) {
WebGLRenderingContextBase* webgl_context = layer->context();
+ if (frame_id_ < 0) {
+ // There is no valid frame_id_, and the browser side is not currently
+ // expecting a frame to be submitted. That can happen for the first
+ // immersive frame if the animation loop submits without a preceding
+ // immersive GetFrameData response, in that case frame_id_ is -1 (see
+ // https://crbug.com/855722).
+ return;
+ }
+
if (!was_changed) {
- // Just tell the device side that there was no submitted frame instead
- // of executing the implicit end-of-frame submit.
+ // Just tell the device side that there was no submitted frame instead of
+ // executing the implicit end-of-frame submit.
frame_transport_->FrameSubmitMissing(presentation_provider_.get(),
webgl_context->ContextGL(), frame_id_);
return;
@@ -506,7 +459,6 @@ void XRFrameProvider::SubmitWebGLLayer(XRWebGLLayer* layer, bool was_changed) {
std::unique_ptr<viz::SingleReleaseCallback> image_release_callback;
- DCHECK(exclusive_session_can_send_frames_);
if (frame_transport_->DrawingIntoSharedBuffer()) {
// Image is written to shared buffer already. Just submit with a
// placeholder.
@@ -550,7 +502,7 @@ void XRFrameProvider::SubmitWebGLLayer(XRWebGLLayer* layer, bool was_changed) {
// TODO(bajones): This only works because we're restricted to a single layer at
// the moment. Will need an overhaul when we get more robust layering support.
void XRFrameProvider::UpdateWebGLLayerViewports(XRWebGLLayer* layer) {
- DCHECK(layer->session() == exclusive_session_);
+ DCHECK(layer->session() == immersive_session_);
DCHECK(presentation_provider_);
XRViewport* left = layer->GetViewportForEye(XRView::kEyeLeft);
@@ -580,9 +532,8 @@ void XRFrameProvider::Dispose() {
void XRFrameProvider::Trace(blink::Visitor* visitor) {
visitor->Trace(device_);
- visitor->Trace(pending_exclusive_session_resolver_);
visitor->Trace(frame_transport_);
- visitor->Trace(exclusive_session_);
+ visitor->Trace(immersive_session_);
visitor->Trace(requesting_sessions_);
}
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_frame_provider.h b/chromium/third_party/blink/renderer/modules/xr/xr_frame_provider.h
index 0109a2a3c01..159a4d55c17 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_frame_provider.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_frame_provider.h
@@ -14,7 +14,6 @@
namespace blink {
-class ScriptPromiseResolver;
class XRDevice;
class XRSession;
class XRFrameTransport;
@@ -27,14 +26,17 @@ class XRFrameProvider final
public:
explicit XRFrameProvider(XRDevice*);
- XRSession* exclusive_session() const { return exclusive_session_; }
+ XRSession* immersive_session() const { return immersive_session_; }
+ device::mojom::blink::VRSubmitFrameClientPtr GetSubmitFrameClient();
- void BeginExclusiveSession(XRSession*, ScriptPromiseResolver*);
- void OnExclusiveSessionEnded();
+ void BeginImmersiveSession(
+ XRSession* session,
+ device::mojom::blink::XRPresentationConnectionPtr connection);
+ void OnImmersiveSessionEnded();
void RequestFrame(XRSession*);
- void OnNonExclusiveVSync(double timestamp);
+ void OnNonImmersiveVSync(double high_res_now_ms);
void SubmitWebGLLayer(XRWebGLLayer*, bool was_changed);
void UpdateWebGLLayerViewports(XRWebGLLayer*);
@@ -45,60 +47,35 @@ class XRFrameProvider final
virtual void Trace(blink::Visitor*);
private:
- void OnExclusiveVSync(
- device::mojom::blink::VRPosePtr,
- WTF::TimeDelta,
- int16_t frame_id,
- device::mojom::blink::VRPresentationProvider::VSyncStatus,
- const base::Optional<gpu::MailboxHolder>& buffer_holder);
- void OnNonExclusiveFrameData(device::mojom::blink::VRMagicWindowFrameDataPtr);
- void OnNonExclusivePose(device::mojom::blink::VRPosePtr);
-
- void ScheduleExclusiveFrame();
- void ScheduleNonExclusiveFrame();
-
- void OnPresentComplete(
- bool success,
- device::mojom::blink::VRDisplayFrameTransportOptionsPtr);
+ void OnImmersiveFrameData(device::mojom::blink::XRFrameDataPtr data);
+ void OnNonImmersiveFrameData(device::mojom::blink::XRFrameDataPtr data);
+
+ void ScheduleImmersiveFrame();
+ void ScheduleNonImmersiveFrame();
+
void OnPresentationProviderConnectionError();
- void ProcessScheduledFrame(
- device::mojom::blink::VRMagicWindowFrameDataPtr frame_data,
- double timestamp);
+ void ProcessScheduledFrame(device::mojom::blink::XRFrameDataPtr frame_data,
+ double high_res_now_ms);
- void RenderBackgroundImage(
- const device::mojom::blink::VRMagicWindowFrameDataPtr& frame_data,
- XRSession* session);
+ bool HasARSession();
const Member<XRDevice> device_;
- Member<XRSession> exclusive_session_;
- Member<ScriptPromiseResolver> pending_exclusive_session_resolver_;
+ Member<XRSession> immersive_session_;
Member<XRFrameTransport> frame_transport_;
- // Careful, exclusive_session_ being true does not mean it's OK to send
- // frames. The initialization handshake may not be complete yet. This boolean
- // starts out false at the start of a session, becomes true after a
- // successful OnPresentComplete(), and remains true for the lifetime of the
- // exclusive session.
- bool exclusive_session_can_send_frames_ = false;
-
- // Non-exclusive Sessions which have requested a frame update.
+ // Non-immersive Sessions which have requested a frame update.
HeapVector<Member<XRSession>> requesting_sessions_;
device::mojom::blink::VRPresentationProviderPtr presentation_provider_;
device::mojom::blink::VRMagicWindowProviderPtr magic_window_provider_;
device::mojom::blink::VRPosePtr frame_pose_;
- // Track the size/orientation of the requested canvas.
- // TODO(https://crbug.com/836496): move these to XRSession.
- IntSize ar_requested_transfer_size_;
- int ar_requested_transfer_angle_ = 0;
-
// This frame ID is XR-specific and is used to track when frames arrive at the
// XR compositor so that it knows which poses to use, when to apply bounds
// updates, etc.
int16_t frame_id_ = -1;
- bool pending_exclusive_vsync_ = false;
- bool pending_non_exclusive_vsync_ = false;
+ bool pending_immersive_vsync_ = false;
+ bool pending_non_immersive_vsync_ = false;
bool vsync_connection_failed_ = false;
base::Optional<gpu::MailboxHolder> buffer_mailbox_holder_;
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_frame_request_callback.idl b/chromium/third_party/blink/renderer/modules/xr/xr_frame_request_callback.idl
index 74ed911d7d5..916e35dc384 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_frame_request_callback.idl
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_frame_request_callback.idl
@@ -3,4 +3,4 @@
// found in the LICENSE file.
// https://immersive-web.github.io/webxr/#callbackdef-xrframerequestcallback
-callback XRFrameRequestCallback = void (DOMHighResTimeStamp time, XRPresentationFrame frame);
+callback XRFrameRequestCallback = void (DOMHighResTimeStamp time, XRFrame frame);
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.cc b/chromium/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.cc
index e3b047402a1..0de1f348c74 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.cc
@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/bindings/modules/v8/v8_xr_frame_request_callback.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/modules/xr/xr_presentation_frame.h"
+#include "third_party/blink/renderer/modules/xr/xr_frame.h"
#include "third_party/blink/renderer/modules/xr/xr_session.h"
namespace blink {
@@ -33,9 +33,9 @@ void XRFrameRequestCallbackCollection::CancelCallback(CallbackId id) {
}
}
-void XRFrameRequestCallbackCollection::ExecuteCallbacks(
- XRSession* session,
- XRPresentationFrame* frame) {
+void XRFrameRequestCallbackCollection::ExecuteCallbacks(XRSession* session,
+ double timestamp,
+ XRFrame* frame) {
// First, generate a list of callbacks to consider. Callbacks registered from
// this point on are considered only for the "next" frame, not this one.
DCHECK(callbacks_to_invoke_.IsEmpty());
@@ -50,7 +50,7 @@ void XRFrameRequestCallbackCollection::ExecuteCallbacks(
probe::AsyncTask async_task(context_, callback);
probe::UserCallback probe(context_, "XRRequestFrame", AtomicString(), true);
- callback->InvokeAndReportException(session, 0, frame);
+ callback->InvokeAndReportException(session, timestamp, frame);
}
callbacks_to_invoke_.clear();
@@ -61,11 +61,4 @@ void XRFrameRequestCallbackCollection::Trace(blink::Visitor* visitor) {
visitor->Trace(context_);
}
-void XRFrameRequestCallbackCollection::TraceWrappers(
- blink::ScriptWrappableVisitor* visitor) const {
- for (const auto& callback : callbacks_.Values()) {
- visitor->TraceWrappers(callback);
- }
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.h b/chromium/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.h
index e8bea9443e5..28b79e93f15 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_FRAME_REQUEST_CALLBACK_COLLECTION_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_FRAME_REQUEST_CALLBACK_COLLECTION_H_
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -12,24 +13,23 @@ namespace blink {
class ExecutionContext;
class V8XRFrameRequestCallback;
-class XRPresentationFrame;
+class XRFrame;
class XRSession;
-class XRFrameRequestCallbackCollection final : public TraceWrapperBase {
- DISALLOW_NEW();
-
+class XRFrameRequestCallbackCollection final
+ : public GarbageCollectedFinalized<XRFrameRequestCallbackCollection>,
+ public NameClient {
public:
explicit XRFrameRequestCallbackCollection(ExecutionContext*);
using CallbackId = int;
CallbackId RegisterCallback(V8XRFrameRequestCallback*);
void CancelCallback(CallbackId);
- void ExecuteCallbacks(XRSession*, XRPresentationFrame*);
+ void ExecuteCallbacks(XRSession*, double timestamp, XRFrame*);
bool IsEmpty() const { return !callbacks_.size(); }
void Trace(blink::Visitor*);
- void TraceWrappers(blink::ScriptWrappableVisitor*) const override;
const char* NameInHeapSnapshot() const override {
return "XRFrameRequestCallbackCollection";
}
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_hit_result.cc b/chromium/third_party/blink/renderer/modules/xr/xr_hit_result.cc
new file mode 100644
index 00000000000..004c50aa759
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_hit_result.cc
@@ -0,0 +1,25 @@
+// 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/modules/xr/xr_hit_result.h"
+
+#include "third_party/blink/renderer/modules/xr/xr_utils.h"
+#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
+
+namespace blink {
+XRHitResult::XRHitResult(std::unique_ptr<TransformationMatrix> hit_transform)
+ : hit_transform_(std::move(hit_transform)) {}
+
+XRHitResult::~XRHitResult() {}
+
+DOMFloat32Array* XRHitResult::hitMatrix() const {
+ if (!hit_transform_)
+ return nullptr;
+ // TODO(https://crbug.com/845296): rename
+ // transformationMatrixToFloat32Array() to
+ // TransformationMatrixToDOMFloat32Array().
+ return transformationMatrixToFloat32Array(*hit_transform_);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_hit_result.h b/chromium/third_party/blink/renderer/modules/xr/xr_hit_result.h
new file mode 100644
index 00000000000..27d8dcee773
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_hit_result.h
@@ -0,0 +1,29 @@
+// 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_MODULES_XR_XR_HIT_RESULT_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_HIT_RESULT_H_
+
+#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
+
+namespace blink {
+
+class TransformationMatrix;
+
+class XRHitResult final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ explicit XRHitResult(std::unique_ptr<TransformationMatrix>);
+ ~XRHitResult() override;
+
+ DOMFloat32Array* hitMatrix() const;
+
+ private:
+ const std::unique_ptr<TransformationMatrix> hit_transform_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_HIT_RESULT_H_
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_hit_result.idl b/chromium/third_party/blink/renderer/modules/xr/xr_hit_result.idl
new file mode 100644
index 00000000000..de430e69503
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_hit_result.idl
@@ -0,0 +1,7 @@
+// 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.
+
+[RuntimeEnabled=WebXRHitTest, SecureContext, Exposed=Window] interface XRHitResult {
+ readonly attribute Float32Array hitMatrix;
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_input_pose.cc b/chromium/third_party/blink/renderer/modules/xr/xr_input_pose.cc
index c40afa39796..8057426f241 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_input_pose.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_input_pose.cc
@@ -11,18 +11,12 @@ namespace blink {
XRInputPose::XRInputPose(std::unique_ptr<TransformationMatrix> pointer_matrix,
std::unique_ptr<TransformationMatrix> grip_matrix,
bool emulated_position)
- : pointer_matrix_(std::move(pointer_matrix)),
+ : target_ray_(new XRRay(std::move(pointer_matrix))),
grip_matrix_(std::move(grip_matrix)),
emulated_position_(emulated_position) {}
XRInputPose::~XRInputPose() {}
-DOMFloat32Array* XRInputPose::pointerMatrix() const {
- if (!pointer_matrix_)
- return nullptr;
- return transformationMatrixToFloat32Array(*pointer_matrix_);
-}
-
DOMFloat32Array* XRInputPose::gripMatrix() const {
if (!grip_matrix_)
return nullptr;
@@ -30,6 +24,7 @@ DOMFloat32Array* XRInputPose::gripMatrix() const {
}
void XRInputPose::Trace(blink::Visitor* visitor) {
+ visitor->Trace(target_ray_);
ScriptWrappable::Trace(visitor);
}
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_input_pose.h b/chromium/third_party/blink/renderer/modules/xr/xr_input_pose.h
index a377f6429b4..7d5448d8272 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_input_pose.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_input_pose.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_INPUT_POSE_H_
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
+#include "third_party/blink/renderer/modules/xr/xr_ray.h"
#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/transforms/transformation_matrix.h"
@@ -17,19 +18,19 @@ class XRInputPose final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- XRInputPose(std::unique_ptr<TransformationMatrix> pointer_matrix,
+ XRInputPose(std::unique_ptr<TransformationMatrix> target_ray_matrix,
std::unique_ptr<TransformationMatrix> grip_matrix,
bool emulated_position = false);
~XRInputPose() override;
- DOMFloat32Array* pointerMatrix() const;
+ XRRay* targetRay() const { return target_ray_; }
DOMFloat32Array* gripMatrix() const;
bool emulatedPosition() const { return emulated_position_; }
void Trace(blink::Visitor*) override;
private:
- const std::unique_ptr<TransformationMatrix> pointer_matrix_;
+ const Member<XRRay> target_ray_;
const std::unique_ptr<TransformationMatrix> grip_matrix_;
const bool emulated_position_;
};
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_input_pose.idl b/chromium/third_party/blink/renderer/modules/xr/xr_input_pose.idl
index 6113cc72548..377ee58a76d 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_input_pose.idl
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_input_pose.idl
@@ -6,7 +6,7 @@
SecureContext,
OriginTrialEnabled=WebXR
] interface XRInputPose {
- readonly attribute Float32Array pointerMatrix;
+ readonly attribute XRRay targetRay;
readonly attribute Float32Array? gripMatrix;
readonly attribute boolean emulatedPosition;
}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_input_source.cc b/chromium/third_party/blink/renderer/modules/xr/xr_input_source.cc
index 761a46d50c6..125a9b2368a 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_input_source.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_input_source.cc
@@ -9,29 +9,29 @@ namespace blink {
XRInputSource::XRInputSource(XRSession* session, uint32_t source_id)
: session_(session), source_id_(source_id) {
- SetPointerOrigin(kOriginHead);
+ SetTargetRayMode(kGaze);
SetHandedness(kHandNone);
}
-void XRInputSource::SetPointerOrigin(PointerOrigin pointer_origin) {
- if (pointer_origin_ == pointer_origin)
+void XRInputSource::SetTargetRayMode(TargetRayMode target_ray_mode) {
+ if (target_ray_mode_ == target_ray_mode)
return;
- pointer_origin_ = pointer_origin;
-
- switch (pointer_origin_) {
- case kOriginHead:
- pointer_origin_string_ = "head";
- break;
- case kOriginHand:
- pointer_origin_string_ = "hand";
- break;
- case kOriginScreen:
- pointer_origin_string_ = "screen";
- break;
- default:
- NOTREACHED() << "Unknown pointer origin: " << pointer_origin_;
+ target_ray_mode_ = target_ray_mode;
+
+ switch (target_ray_mode_) {
+ case kGaze:
+ target_ray_mode_string_ = "gaze";
+ return;
+ case kTrackedPointer:
+ target_ray_mode_string_ = "tracked-pointer";
+ return;
+ case kScreen:
+ target_ray_mode_string_ = "screen";
+ return;
}
+
+ NOTREACHED() << "Unknown target ray mode: " << target_ray_mode_;
}
void XRInputSource::SetHandedness(Handedness handedness) {
@@ -43,16 +43,16 @@ void XRInputSource::SetHandedness(Handedness handedness) {
switch (handedness_) {
case kHandNone:
handedness_string_ = "";
- break;
+ return;
case kHandLeft:
handedness_string_ = "left";
- break;
+ return;
case kHandRight:
handedness_string_ = "right";
- break;
- default:
- NOTREACHED() << "Unknown handedness: " << handedness_;
+ return;
}
+
+ NOTREACHED() << "Unknown handedness: " << handedness_;
}
void XRInputSource::SetEmulatedPosition(bool emulated_position) {
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_input_source.h b/chromium/third_party/blink/renderer/modules/xr/xr_input_source.h
index 18daf0b71fd..1b936361ac6 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_input_source.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_input_source.h
@@ -20,7 +20,7 @@ class XRInputSource : public ScriptWrappable {
public:
enum Handedness { kHandNone = 0, kHandLeft = 1, kHandRight = 2 };
- enum PointerOrigin { kOriginHead = 1, kOriginHand = 2, kOriginScreen = 3 };
+ enum TargetRayMode { kGaze = 1, kTrackedPointer = 2, kScreen = 3 };
XRInputSource(XRSession*, uint32_t source_id);
~XRInputSource() override = default;
@@ -28,12 +28,12 @@ class XRInputSource : public ScriptWrappable {
XRSession* session() const { return session_; }
const String& handedness() const { return handedness_string_; }
- const String& pointerOrigin() const { return pointer_origin_string_; }
+ const String& targetRayMode() const { return target_ray_mode_string_; }
bool emulatedPosition() const { return emulated_position_; }
uint32_t source_id() const { return source_id_; }
- void SetPointerOrigin(PointerOrigin);
+ void SetTargetRayMode(TargetRayMode);
void SetHandedness(Handedness);
void SetEmulatedPosition(bool emulated_position);
void SetBasePoseMatrix(std::unique_ptr<TransformationMatrix>);
@@ -46,7 +46,7 @@ class XRInputSource : public ScriptWrappable {
bool selection_cancelled = false;
private:
- friend class XRPresentationFrame;
+ friend class XRFrame;
const Member<XRSession> session_;
const uint32_t source_id_;
@@ -54,8 +54,8 @@ class XRInputSource : public ScriptWrappable {
Handedness handedness_;
String handedness_string_;
- PointerOrigin pointer_origin_;
- String pointer_origin_string_;
+ TargetRayMode target_ray_mode_;
+ String target_ray_mode_string_;
bool emulated_position_ = false;
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_input_source.idl b/chromium/third_party/blink/renderer/modules/xr/xr_input_source.idl
index bc084732141..f290e724bc3 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_input_source.idl
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_input_source.idl
@@ -7,9 +7,9 @@ enum XRHandedness {
"right"
};
-enum XRPointerOrigin {
- "head",
- "grip",
+enum XRTargetRayMode {
+ "gaze",
+ "tracked-pointer",
"screen"
};
@@ -18,5 +18,5 @@ enum XRPointerOrigin {
OriginTrialEnabled=WebXR
] interface XRInputSource {
readonly attribute XRHandedness handedness;
- readonly attribute XRPointerOrigin pointerOrigin;
+ readonly attribute XRTargetRayMode targetRayMode;
}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_input_source_event.cc b/chromium/third_party/blink/renderer/modules/xr/xr_input_source_event.cc
index ce47b89c169..c9e918a53b9 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_input_source_event.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_input_source_event.cc
@@ -9,7 +9,7 @@ namespace blink {
XRInputSourceEvent::XRInputSourceEvent() {}
XRInputSourceEvent::XRInputSourceEvent(const AtomicString& type,
- XRPresentationFrame* frame,
+ XRFrame* frame,
XRInputSource* input_source)
: Event(type, Bubbles::kYes, Cancelable::kNo),
frame_(frame),
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_input_source_event.h b/chromium/third_party/blink/renderer/modules/xr/xr_input_source_event.h
index 3df04918dfd..a94b263b5c9 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_input_source_event.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_input_source_event.h
@@ -6,9 +6,9 @@
#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_INPUT_SOURCE_EVENT_H_
#include "third_party/blink/renderer/modules/event_modules.h"
+#include "third_party/blink/renderer/modules/xr/xr_frame.h"
#include "third_party/blink/renderer/modules/xr/xr_input_source.h"
#include "third_party/blink/renderer/modules/xr/xr_input_source_event_init.h"
-#include "third_party/blink/renderer/modules/xr/xr_presentation_frame.h"
namespace blink {
@@ -18,7 +18,7 @@ class XRInputSourceEvent final : public Event {
public:
static XRInputSourceEvent* Create() { return new XRInputSourceEvent; }
static XRInputSourceEvent* Create(const AtomicString& type,
- XRPresentationFrame* frame,
+ XRFrame* frame,
XRInputSource* input_source) {
return new XRInputSourceEvent(type, frame, input_source);
}
@@ -30,7 +30,7 @@ class XRInputSourceEvent final : public Event {
~XRInputSourceEvent() override;
- XRPresentationFrame* frame() const { return frame_.Get(); }
+ XRFrame* frame() const { return frame_.Get(); }
XRInputSource* inputSource() const { return input_source_.Get(); }
const AtomicString& InterfaceName() const override;
@@ -39,12 +39,10 @@ class XRInputSourceEvent final : public Event {
private:
XRInputSourceEvent();
- XRInputSourceEvent(const AtomicString& type,
- XRPresentationFrame*,
- XRInputSource*);
+ XRInputSourceEvent(const AtomicString& type, XRFrame*, XRInputSource*);
XRInputSourceEvent(const AtomicString&, const XRInputSourceEventInit&);
- Member<XRPresentationFrame> frame_;
+ Member<XRFrame> frame_;
Member<XRInputSource> input_source_;
};
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_input_source_event.idl b/chromium/third_party/blink/renderer/modules/xr/xr_input_source_event.idl
index cbcb28c9150..0c8fe9f30a8 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_input_source_event.idl
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_input_source_event.idl
@@ -7,6 +7,6 @@
OriginTrialEnabled=WebXR,
Constructor(DOMString type, XRInputSourceEventInit eventInitDict)
] interface XRInputSourceEvent : Event {
- readonly attribute XRPresentationFrame frame;
+ readonly attribute XRFrame frame;
readonly attribute XRInputSource inputSource;
};
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_input_source_event_init.idl b/chromium/third_party/blink/renderer/modules/xr/xr_input_source_event_init.idl
index b24af31a375..e5ca3ac255c 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_input_source_event_init.idl
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_input_source_event_init.idl
@@ -5,6 +5,6 @@
[
SecureContext
] dictionary XRInputSourceEventInit : EventInit {
- required XRPresentationFrame frame;
+ required XRFrame frame;
required XRInputSource inputSource;
}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_presentation_context.cc b/chromium/third_party/blink/renderer/modules/xr/xr_presentation_context.cc
index ba46309b911..1ee356f0a76 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_presentation_context.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_presentation_context.cc
@@ -24,7 +24,7 @@ void XRPresentationContext::SetCanvasGetContextResult(
CanvasRenderingContext* XRPresentationContext::Factory::Create(
CanvasRenderingContextHost* host,
const CanvasContextCreationAttributesCore& attrs) {
- if (!OriginTrials::webXREnabled(host->GetTopExecutionContext()))
+ if (!OriginTrials::WebXREnabled(host->GetTopExecutionContext()))
return nullptr;
return new XRPresentationContext(host, attrs);
}
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_presentation_frame.cc b/chromium/third_party/blink/renderer/modules/xr/xr_presentation_frame.cc
deleted file mode 100644
index 5b413d5d7a5..00000000000
--- a/chromium/third_party/blink/renderer/modules/xr/xr_presentation_frame.cc
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/modules/xr/xr_presentation_frame.h"
-
-#include "third_party/blink/renderer/modules/xr/xr_coordinate_system.h"
-#include "third_party/blink/renderer/modules/xr/xr_device_pose.h"
-#include "third_party/blink/renderer/modules/xr/xr_input_pose.h"
-#include "third_party/blink/renderer/modules/xr/xr_input_source.h"
-#include "third_party/blink/renderer/modules/xr/xr_session.h"
-#include "third_party/blink/renderer/modules/xr/xr_view.h"
-
-namespace blink {
-
-XRPresentationFrame::XRPresentationFrame(XRSession* session)
- : session_(session) {}
-
-const HeapVector<Member<XRView>>& XRPresentationFrame::views() const {
- return session_->views();
-}
-
-XRDevicePose* XRPresentationFrame::getDevicePose(
- XRCoordinateSystem* coordinate_system) const {
- session_->LogGetPose();
-
- // If we don't have a valid base pose return null. Most common when tracking
- // is lost.
- if (!base_pose_matrix_ || !coordinate_system) {
- return nullptr;
- }
-
- // Must use a coordinate system created from the same session.
- if (coordinate_system->session() != session_) {
- return nullptr;
- }
-
- std::unique_ptr<TransformationMatrix> pose =
- coordinate_system->TransformBasePose(*base_pose_matrix_);
-
- if (!pose) {
- return nullptr;
- }
-
- return new XRDevicePose(session(), std::move(pose));
-}
-
-XRInputPose* XRPresentationFrame::getInputPose(
- XRInputSource* input_source,
- XRCoordinateSystem* coordinate_system) const {
- if (!input_source || !coordinate_system) {
- return nullptr;
- }
-
- // Must use an input source and coordinate system from the same session.
- if (input_source->session() != session_ ||
- coordinate_system->session() != session_) {
- return nullptr;
- }
-
- switch (input_source->pointer_origin_) {
- case XRInputSource::kOriginScreen: {
- // If the pointer origin is the screen we need the head's base pose and
- // the pointer transform matrix to continue. The pointer transform will
- // represent the point the canvas was clicked as an offset from the view.
- if (!base_pose_matrix_ || !input_source->pointer_transform_matrix_) {
- return nullptr;
- }
-
- // Multiply the head pose and pointer transform to get the final pointer.
- std::unique_ptr<TransformationMatrix> pointer_pose =
- coordinate_system->TransformBasePose(*base_pose_matrix_);
- pointer_pose->Multiply(*(input_source->pointer_transform_matrix_));
-
- return new XRInputPose(std::move(pointer_pose), nullptr);
- }
- case XRInputSource::kOriginHead: {
- // If the pointer origin is the users head, this is a gaze cursor and the
- // returned pointer is based on the device pose. If we don't have a valid
- // base pose (most common when tracking is lost) return null.
- if (!base_pose_matrix_) {
- return nullptr;
- }
-
- // Just return the head pose as the pointer pose.
- std::unique_ptr<TransformationMatrix> pointer_pose =
- coordinate_system->TransformBasePose(*base_pose_matrix_);
-
- return new XRInputPose(std::move(pointer_pose), nullptr,
- input_source->emulatedPosition());
- }
- case XRInputSource::kOriginHand: {
- // If the input source doesn't have a base pose return null;
- if (!input_source->base_pose_matrix_) {
- return nullptr;
- }
-
- std::unique_ptr<TransformationMatrix> grip_pose =
- coordinate_system->TransformBaseInputPose(
- *(input_source->base_pose_matrix_), *base_pose_matrix_);
-
- if (!grip_pose) {
- return nullptr;
- }
-
- std::unique_ptr<TransformationMatrix> pointer_pose(
- TransformationMatrix::Create(*grip_pose));
-
- if (input_source->pointer_transform_matrix_) {
- pointer_pose->Multiply(*(input_source->pointer_transform_matrix_));
- }
-
- return new XRInputPose(std::move(pointer_pose), std::move(grip_pose),
- input_source->emulatedPosition());
- }
- }
-
- return nullptr;
-}
-
-void XRPresentationFrame::SetBasePoseMatrix(
- const TransformationMatrix& base_pose_matrix) {
- base_pose_matrix_ = TransformationMatrix::Create(base_pose_matrix);
-}
-
-void XRPresentationFrame::Trace(blink::Visitor* visitor) {
- visitor->Trace(session_);
- ScriptWrappable::Trace(visitor);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_presentation_frame.h b/chromium/third_party/blink/renderer/modules/xr/xr_presentation_frame.h
deleted file mode 100644
index 109ca754b1d..00000000000
--- a/chromium/third_party/blink/renderer/modules/xr/xr_presentation_frame.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_PRESENTATION_FRAME_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_PRESENTATION_FRAME_H_
-
-#include "device/vr/public/mojom/vr_service.mojom-blink.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
-
-namespace blink {
-
-class XRCoordinateSystem;
-class XRDevicePose;
-class XRInputPose;
-class XRInputSource;
-class XRSession;
-class XRView;
-
-class XRPresentationFrame final : public ScriptWrappable {
- DEFINE_WRAPPERTYPEINFO();
-
- public:
- explicit XRPresentationFrame(XRSession*);
-
- XRSession* session() const { return session_; }
-
- const HeapVector<Member<XRView>>& views() const;
- XRDevicePose* getDevicePose(XRCoordinateSystem*) const;
- XRInputPose* getInputPose(XRInputSource*, XRCoordinateSystem*) const;
-
- void SetBasePoseMatrix(const TransformationMatrix&);
-
- void Trace(blink::Visitor*) override;
-
- private:
- const Member<XRSession> session_;
- std::unique_ptr<TransformationMatrix> base_pose_matrix_;
-};
-
-} // namespace blink
-
-#endif // XRWebGLLayer_h
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_presentation_frame.idl b/chromium/third_party/blink/renderer/modules/xr/xr_presentation_frame.idl
deleted file mode 100644
index 9e2221399ea..00000000000
--- a/chromium/third_party/blink/renderer/modules/xr/xr_presentation_frame.idl
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// https://immersive-web.github.io/webxr/#xrpresentationframe-interface
-[
- SecureContext,
- OriginTrialEnabled=WebXR
-] interface XRPresentationFrame {
- readonly attribute XRSession session;
- readonly attribute FrozenArray<XRView> views;
-
- XRDevicePose? getDevicePose(XRCoordinateSystem coordinateSystem);
- XRInputPose? getInputPose(XRInputSource inputSource,
- XRCoordinateSystem coordinateSystem);
-};
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_ray.cc b/chromium/third_party/blink/renderer/modules/xr/xr_ray.cc
new file mode 100644
index 00000000000..22ae3d40ed2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_ray.cc
@@ -0,0 +1,39 @@
+// 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/modules/xr/xr_ray.h"
+
+#include "third_party/blink/renderer/modules/xr/xr_utils.h"
+#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
+
+namespace blink {
+XRRay::XRRay(std::unique_ptr<TransformationMatrix> transform_matrix)
+ : transform_matrix_(std::move(transform_matrix)) {
+ FloatPoint3D origin = transform_matrix_->MapPoint(FloatPoint3D(0, 0, 0));
+ FloatPoint3D dir = transform_matrix_->MapPoint(FloatPoint3D(0, 0, -1));
+ dir.Move(-origin.X(), -origin.Y(), -origin.Z());
+ dir.Normalize();
+
+ origin_ = DOMPointReadOnly::Create(origin.X(), origin.Y(), origin.Z(), 1.0);
+ direction_ = DOMPointReadOnly::Create(dir.X(), dir.Y(), dir.Z(), 0.0);
+}
+
+XRRay::~XRRay() {}
+
+DOMFloat32Array* XRRay::transformMatrix() const {
+ if (!transform_matrix_)
+ return nullptr;
+ // TODO(https://crbug.com/845296): rename
+ // transformationMatrixToFloat32Array() to
+ // TransformationMatrixToDOMFloat32Array().
+ return transformationMatrixToFloat32Array(*transform_matrix_);
+}
+
+void XRRay::Trace(blink::Visitor* visitor) {
+ visitor->Trace(origin_);
+ visitor->Trace(direction_);
+ ScriptWrappable::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_ray.h b/chromium/third_party/blink/renderer/modules/xr/xr_ray.h
new file mode 100644
index 00000000000..e157b24702e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_ray.h
@@ -0,0 +1,37 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_RAY_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_RAY_H_
+
+#include "third_party/blink/renderer/core/geometry/dom_point_read_only.h"
+#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+
+namespace blink {
+
+class TransformationMatrix;
+
+class XRRay final : public ScriptWrappable {
+ DEFINE_WRAPPERTYPEINFO();
+
+ public:
+ explicit XRRay(std::unique_ptr<TransformationMatrix>);
+ ~XRRay() override;
+
+ DOMPointReadOnly* origin() const { return origin_; }
+ DOMPointReadOnly* direction() const { return direction_; }
+ DOMFloat32Array* transformMatrix() const;
+
+ void Trace(blink::Visitor*) override;
+
+ private:
+ Member<DOMPointReadOnly> origin_;
+ Member<DOMPointReadOnly> direction_;
+ const std::unique_ptr<TransformationMatrix> transform_matrix_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_RAY_H_
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_ray.idl b/chromium/third_party/blink/renderer/modules/xr/xr_ray.idl
new file mode 100644
index 00000000000..b9ca32e318e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_ray.idl
@@ -0,0 +1,10 @@
+// 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.
+
+// https://immersive-web.github.io/webxr/#xrray-interface
+[SecureContext, OriginTrialEnabled=WebXR] interface XRRay {
+ readonly attribute DOMPointReadOnly origin;
+ readonly attribute DOMPointReadOnly direction;
+ readonly attribute Float32Array transformMatrix;
+}; \ No newline at end of file
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_session.cc b/chromium/third_party/blink/renderer/modules/xr/xr_session.cc
index 1bcdfa8f838..d838ef8bdba 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_session.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_session.cc
@@ -19,15 +19,18 @@
#include "third_party/blink/renderer/modules/xr/xr.h"
#include "third_party/blink/renderer/modules/xr/xr_canvas_input_provider.h"
#include "third_party/blink/renderer/modules/xr/xr_device.h"
+#include "third_party/blink/renderer/modules/xr/xr_frame.h"
#include "third_party/blink/renderer/modules/xr/xr_frame_of_reference.h"
#include "third_party/blink/renderer/modules/xr/xr_frame_of_reference_options.h"
#include "third_party/blink/renderer/modules/xr/xr_frame_provider.h"
+#include "third_party/blink/renderer/modules/xr/xr_hit_result.h"
#include "third_party/blink/renderer/modules/xr/xr_input_source_event.h"
#include "third_party/blink/renderer/modules/xr/xr_layer.h"
#include "third_party/blink/renderer/modules/xr/xr_presentation_context.h"
-#include "third_party/blink/renderer/modules/xr/xr_presentation_frame.h"
#include "third_party/blink/renderer/modules/xr/xr_session_event.h"
#include "third_party/blink/renderer/modules/xr/xr_view.h"
+#include "third_party/blink/renderer/modules/xr/xr_webgl_layer.h"
+#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
namespace blink {
@@ -87,12 +90,16 @@ class XRSession::XRSessionResizeObserverDelegate final
};
XRSession::XRSession(XRDevice* device,
- bool exclusive,
- XRPresentationContext* output_context)
+ bool immersive,
+ bool environment_integration,
+ XRPresentationContext* output_context,
+ EnvironmentBlendMode environment_blend_mode)
: device_(device),
- exclusive_(exclusive),
+ immersive_(immersive),
+ environment_integration_(environment_integration),
output_context_(output_context),
- callback_collection_(device->GetExecutionContext()) {
+ callback_collection_(new XRFrameRequestCallbackCollection(
+ device->xr()->GetExecutionContext())) {
blurred_ = !HasAppropriateFocus();
// When an output context is provided, monitor it for resize events.
@@ -104,7 +111,7 @@ XRSession::XRSession(XRDevice* device,
resize_observer_->observe(canvas);
// Begin processing input events on the output context's canvas.
- if (!exclusive_) {
+ if (!immersive_) {
canvas_input_provider_ = new XRCanvasInputProvider(this, canvas);
}
@@ -112,6 +119,21 @@ XRSession::XRSession(XRDevice* device,
UpdateCanvasDimensions(canvas);
}
}
+
+ switch (environment_blend_mode) {
+ case kBlendModeOpaque:
+ blend_mode_string_ = "opaque";
+ break;
+ case kBlendModeAdditive:
+ blend_mode_string_ = "additive";
+ break;
+ case kBlendModeAlphaBlend:
+ blend_mode_string_ = "alpha-blend";
+ break;
+ default:
+ NOTREACHED() << "Unknown environment blend mode: "
+ << environment_blend_mode;
+ }
}
void XRSession::setDepthNear(double value) {
@@ -131,24 +153,24 @@ void XRSession::setDepthFar(double value) {
void XRSession::setBaseLayer(XRLayer* value) {
base_layer_ = value;
// Make sure that the layer's drawing buffer is updated to the right size
- // if this is a non-exclusive session.
- if (!exclusive_ && base_layer_) {
+ // if this is a non-immersive session.
+ if (!immersive_ && base_layer_) {
base_layer_->OnResize();
}
}
-void XRSession::SetNonExclusiveProjectionMatrix(
+void XRSession::SetNonImmersiveProjectionMatrix(
const WTF::Vector<float>& projection_matrix) {
DCHECK_EQ(projection_matrix.size(), 16lu);
- non_exclusive_projection_matrix_ = projection_matrix;
+ non_immersive_projection_matrix_ = projection_matrix;
// It is about as expensive to check equality as to just
// update the views, so just update.
update_views_next_frame_ = true;
}
ExecutionContext* XRSession::GetExecutionContext() const {
- return device_->GetExecutionContext();
+ return device_->xr()->GetExecutionContext();
}
const AtomicString& XRSession::InterfaceName() const {
@@ -161,14 +183,15 @@ ScriptPromise XRSession::requestFrameOfReference(
const XRFrameOfReferenceOptions& options) {
if (ended_) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kInvalidStateError, kSessionEnded));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kSessionEnded));
}
XRFrameOfReference* frameOfRef = nullptr;
- if (type == "headModel") {
+ if (type == "head-model") {
frameOfRef =
new XRFrameOfReference(this, XRFrameOfReference::kTypeHeadModel);
- } else if (type == "eyeLevel") {
+ } else if (type == "eye-level") {
frameOfRef =
new XRFrameOfReference(this, XRFrameOfReference::kTypeEyeLevel);
} else if (type == "stage") {
@@ -179,15 +202,16 @@ ScriptPromise XRSession::requestFrameOfReference(
frameOfRef = new XRFrameOfReference(this, XRFrameOfReference::kTypeStage);
} else {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kNotSupportedError,
- kNonEmulatedStageNotSupported));
+ script_state,
+ DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ kNonEmulatedStageNotSupported));
}
}
if (!frameOfRef) {
return ScriptPromise::RejectWithDOMException(
- script_state,
- DOMException::Create(kNotSupportedError, kUnknownFrameOfReference));
+ script_state, DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ kUnknownFrameOfReference));
}
ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
@@ -208,7 +232,7 @@ int XRSession::requestAnimationFrame(V8XRFrameRequestCallback* callback) {
if (!base_layer_)
return 0;
- int id = callback_collection_.RegisterCallback(callback);
+ int id = callback_collection_->RegisterCallback(callback);
if (!pending_frame_) {
// Kick off a request for a new XR frame.
device_->frameProvider()->RequestFrame(this);
@@ -218,7 +242,7 @@ int XRSession::requestAnimationFrame(V8XRFrameRequestCallback* callback) {
}
void XRSession::cancelAnimationFrame(int id) {
- callback_collection_.CancelCallback(id);
+ callback_collection_->CancelCallback(id);
}
HeapVector<Member<XRInputSource>> XRSession::getInputSources() const {
@@ -245,11 +269,87 @@ HeapVector<Member<XRInputSource>> XRSession::getInputSources() const {
return source_array;
}
+ScriptPromise XRSession::requestHitTest(ScriptState* script_state,
+ NotShared<DOMFloat32Array> origin,
+ NotShared<DOMFloat32Array> direction,
+ XRCoordinateSystem* coordinate_system) {
+ if (ended_) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kSessionEnded));
+ }
+
+ if (!coordinate_system) {
+ return ScriptPromise::Reject(
+ script_state, V8ThrowException::CreateTypeError(
+ script_state->GetIsolate(),
+ "The coordinateSystem parameter is empty."));
+ }
+
+ if (origin.View()->length() != 3 || direction.View()->length() != 3) {
+ return ScriptPromise::RejectWithDOMException(
+ script_state, DOMException::Create(DOMExceptionCode::kNotSupportedError,
+ "Invalid ray!"));
+ }
+
+ // TODO(https://crbug.com/846411): use coordinate_system.
+
+ // TODO(https://crbug.com/843376): Reject the promise if device doesn't
+ // support the hit-test API.
+
+ device::mojom::blink::XRRayPtr ray = device::mojom::blink::XRRay::New();
+ ray->origin.resize(3);
+ ray->origin[0] = origin.View()->Data()[0];
+ ray->origin[1] = origin.View()->Data()[1];
+ ray->origin[2] = origin.View()->Data()[2];
+ ray->direction.resize(3);
+ ray->direction[0] = direction.View()->Data()[0];
+ ray->direction[1] = direction.View()->Data()[1];
+ ray->direction[2] = direction.View()->Data()[2];
+
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
+ ScriptPromise promise = resolver->Promise();
+
+ // TODO(https://crbug.com/845520): Promise should be rejected if session
+ // is deleted.
+ device_->xrMagicWindowProviderPtr()->RequestHitTest(
+ std::move(ray),
+ WTF::Bind(&XRSession::OnHitTestResults, WrapWeakPersistent(this),
+ WrapPersistent(resolver)));
+
+ return promise;
+}
+
+void XRSession::OnHitTestResults(
+ ScriptPromiseResolver* resolver,
+ base::Optional<WTF::Vector<device::mojom::blink::XRHitResultPtr>> results) {
+ if (!results) {
+ resolver->Reject();
+ return;
+ }
+
+ HeapVector<Member<XRHitResult>> hit_results;
+ for (const auto& mojom_result : results.value()) {
+ XRHitResult* hit_result = new XRHitResult(TransformationMatrix::Create(
+ mojom_result->hit_matrix[0], mojom_result->hit_matrix[1],
+ mojom_result->hit_matrix[2], mojom_result->hit_matrix[3],
+ mojom_result->hit_matrix[4], mojom_result->hit_matrix[5],
+ mojom_result->hit_matrix[6], mojom_result->hit_matrix[7],
+ mojom_result->hit_matrix[8], mojom_result->hit_matrix[9],
+ mojom_result->hit_matrix[10], mojom_result->hit_matrix[11],
+ mojom_result->hit_matrix[12], mojom_result->hit_matrix[13],
+ mojom_result->hit_matrix[14], mojom_result->hit_matrix[15]));
+ hit_results.push_back(hit_result);
+ }
+ resolver->Resolve(hit_results);
+}
+
ScriptPromise XRSession::end(ScriptState* script_state) {
// Don't allow a session to end twice.
if (ended_) {
return ScriptPromise::RejectWithDOMException(
- script_state, DOMException::Create(kInvalidStateError, kSessionEnded));
+ script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+ kSessionEnded));
}
ForceEnd();
@@ -274,31 +374,39 @@ void XRSession::ForceEnd() {
canvas_input_provider_ = nullptr;
}
- // If this session is the active exclusive session for the device, notify the
+ // If this session is the active immersive session for the device, notify the
// frameProvider that it's ended.
- if (device_->frameProvider()->exclusive_session() == this) {
- device_->frameProvider()->OnExclusiveSessionEnded();
+ if (device_->frameProvider()->immersive_session() == this) {
+ device_->frameProvider()->OnImmersiveSessionEnded();
}
DispatchEvent(XRSessionEvent::Create(EventTypeNames::end, this));
}
-double XRSession::DefaultFramebufferScale() const {
- if (exclusive_)
- return device_->xrDisplayInfoPtr()->webxr_default_framebuffer_scale;
+double XRSession::NativeFramebufferScale() const {
+ if (immersive_) {
+ double scale = device_->xrDisplayInfoPtr()->webxr_default_framebuffer_scale;
+ DCHECK(scale);
+
+ // Return the inverse of the default scale, since that's what we'll need to
+ // multiply the default size by to get back to the native size.
+ return 1.0 / scale;
+ }
return 1.0;
}
-DoubleSize XRSession::IdealFramebufferSize() const {
- if (!exclusive_) {
+DoubleSize XRSession::DefaultFramebufferSize() const {
+ if (!immersive_) {
return OutputCanvasSize();
}
- double width = device_->xrDisplayInfoPtr()->leftEye->renderWidth +
- device_->xrDisplayInfoPtr()->rightEye->renderWidth;
+ double width = (device_->xrDisplayInfoPtr()->leftEye->renderWidth +
+ device_->xrDisplayInfoPtr()->rightEye->renderWidth);
double height = std::max(device_->xrDisplayInfoPtr()->leftEye->renderHeight,
device_->xrDisplayInfoPtr()->rightEye->renderHeight);
- return DoubleSize(width, height);
+
+ double scale = device_->xrDisplayInfoPtr()->webxr_default_framebuffer_scale;
+ return DoubleSize(width * scale, height * scale);
}
DoubleSize XRSession::OutputCanvasSize() const {
@@ -309,10 +417,6 @@ DoubleSize XRSession::OutputCanvasSize() const {
return DoubleSize(output_width_, output_height_);
}
-int XRSession::OutputCanvasAngle() const {
- return output_angle_;
-}
-
void XRSession::OnFocus() {
if (!blurred_)
return;
@@ -329,11 +433,11 @@ void XRSession::OnBlur() {
DispatchEvent(XRSessionEvent::Create(EventTypeNames::blur, this));
}
-// Exclusive sessions may still not be blurred in headset even if the page isn't
+// Immersive sessions may still not be blurred in headset even if the page isn't
// focused. This prevents the in-headset experience from freezing on an
// external display headset when the user clicks on another tab.
bool XRSession::HasAppropriateFocus() {
- return exclusive_ ? device_->HasDeviceFocus()
+ return immersive_ ? device_->HasDeviceFocus()
: device_->HasDeviceAndFrameFocus();
}
@@ -346,8 +450,11 @@ void XRSession::OnFocusChanged() {
}
void XRSession::OnFrame(
+ double timestamp,
std::unique_ptr<TransformationMatrix> base_pose_matrix,
- const base::Optional<gpu::MailboxHolder>& buffer_mailbox_holder) {
+ const base::Optional<gpu::MailboxHolder>& output_mailbox_holder,
+ const base::Optional<gpu::MailboxHolder>& background_mailbox_holder,
+ const base::Optional<IntSize>& background_size) {
TRACE_EVENT0("gpu", __FUNCTION__);
DVLOG(2) << __FUNCTION__;
// Don't process any outstanding frames once the session is ended.
@@ -361,7 +468,7 @@ void XRSession::OnFrame(
if (!base_layer_)
return;
- XRPresentationFrame* presentation_frame = CreatePresentationFrame();
+ XRFrame* presentation_frame = CreatePresentationFrame();
if (pending_frame_) {
pending_frame_ = false;
@@ -374,13 +481,24 @@ void XRSession::OnFrame(
// Cache the base layer, since it could change during the frame callback.
XRLayer* frame_base_layer = base_layer_;
- frame_base_layer->OnFrameStart(buffer_mailbox_holder);
+ frame_base_layer->OnFrameStart(output_mailbox_holder);
+
+ // TODO(836349): revisit sending background image data to blink at all.
+ if (background_mailbox_holder) {
+ // If using a background image, the caller must provide its pixel size
+ // also. The source size can differ from the current drawing buffer size.
+ DCHECK(background_size);
+ // TODO(https://crbug.com/837509): Remove this static_cast.
+ XRWebGLLayer* webgl_layer = static_cast<XRWebGLLayer*>(frame_base_layer);
+ webgl_layer->OverwriteColorBufferFromMailboxTexture(
+ background_mailbox_holder.value(), background_size.value());
+ }
// Resolve the queued requestAnimationFrame callbacks. All XR rendering will
// happen within these calls. resolving_frame_ will be true for the duration
// of the callbacks.
base::AutoReset<bool> resolving(&resolving_frame_, true);
- callback_collection_.ExecuteCallbacks(this, presentation_frame);
+ callback_collection_->ExecuteCallbacks(this, timestamp, presentation_frame);
// The session might have ended in the middle of the frame. Only call
// OnFrameEnd if it's still valid.
@@ -400,8 +518,8 @@ void XRSession::LogGetPose() const {
}
}
-XRPresentationFrame* XRSession::CreatePresentationFrame() {
- XRPresentationFrame* presentation_frame = new XRPresentationFrame(this);
+XRFrame* XRSession::CreatePresentationFrame() {
+ XRFrame* presentation_frame = new XRFrame(this);
if (base_pose_matrix_) {
presentation_frame->SetBasePoseMatrix(*base_pose_matrix_);
}
@@ -421,13 +539,21 @@ void XRSession::UpdateCanvasDimensions(Element* element) {
update_views_next_frame_ = true;
output_width_ = element->OffsetWidth() * devicePixelRatio;
output_height_ = element->OffsetHeight() * devicePixelRatio;
+ int output_angle = 0;
// TODO(crbug.com/836948): handle square canvases.
// TODO(crbug.com/840346): we should not need to use ScreenOrientation here.
ScreenOrientation* orientation = ScreenOrientation::Create(frame);
+
if (orientation) {
- output_angle_ = orientation->angle();
- DVLOG(2) << __FUNCTION__ << ": got angle=" << output_angle_;
+ output_angle = orientation->angle();
+ DVLOG(2) << __FUNCTION__ << ": got angle=" << output_angle;
+ }
+
+ if (device_->xrMagicWindowProviderPtr()) {
+ device_->xrMagicWindowProviderPtr()->UpdateSessionGeometry(
+ IntSize(output_width_, output_height_),
+ display::Display::DegreesToRotation(output_angle));
}
if (base_layer_) {
@@ -547,8 +673,8 @@ void XRSession::UpdateInputSourceState(
const device::mojom::blink::XRInputSourceDescriptionPtr& desc =
state->description;
- input_source->SetPointerOrigin(
- static_cast<XRInputSource::PointerOrigin>(desc->pointer_origin));
+ input_source->SetTargetRayMode(
+ static_cast<XRInputSource::TargetRayMode>(desc->target_ray_mode));
input_source->SetHandedness(
static_cast<XRInputSource::Handedness>(desc->handedness));
@@ -593,23 +719,23 @@ void XRSession::UpdateInputSourceState(
XRInputSourceEvent* XRSession::CreateInputSourceEvent(
const AtomicString& type,
XRInputSource* input_source) {
- XRPresentationFrame* presentation_frame = CreatePresentationFrame();
+ XRFrame* presentation_frame = CreatePresentationFrame();
return XRInputSourceEvent::Create(type, presentation_frame, input_source);
}
const HeapVector<Member<XRView>>& XRSession::views() {
- // TODO(bajones): For now we assume that exclusive sessions render a stereo
- // pair of views and non-exclusive sessions render a single view. That doesn't
+ // TODO(bajones): For now we assume that immersive sessions render a stereo
+ // pair of views and non-immersive sessions render a single view. That doesn't
// always hold true, however, so the view configuration should ultimately come
// from the backing service.
if (views_dirty_) {
- if (exclusive_) {
+ if (immersive_) {
// If we don't already have the views allocated, do so now.
if (views_.IsEmpty()) {
views_.push_back(new XRView(this, XRView::kEyeLeft));
views_.push_back(new XRView(this, XRView::kEyeRight));
}
- // In exclusive mode the projection and view matrices must be aligned with
+ // In immersive mode the projection and view matrices must be aligned with
// the device's physical optics.
UpdateViewFromEyeParameters(views_[XRView::kEyeLeft],
device_->xrDisplayInfoPtr()->leftEye,
@@ -629,11 +755,11 @@ const HeapVector<Member<XRView>>& XRSession::views() {
static_cast<float>(output_height_);
}
- if (non_exclusive_projection_matrix_.size() > 0) {
+ if (non_immersive_projection_matrix_.size() > 0) {
views_[XRView::kEyeLeft]->UpdateProjectionMatrixFromRawValues(
- non_exclusive_projection_matrix_, depth_near_, depth_far_);
+ non_immersive_projection_matrix_, depth_near_, depth_far_);
} else {
- // In non-exclusive mode, if there is no explicit projection matrix
+ // In non-immersive mode, if there is no explicit projection matrix
// provided, the projection matrix must be aligned with the
// output canvas dimensions.
views_[XRView::kEyeLeft]->UpdateProjectionMatrixFromAspect(
@@ -647,9 +773,9 @@ const HeapVector<Member<XRView>>& XRSession::views() {
// AR mode, we're not picking up the change on the right frame. Remove this
// fallback once that's sorted out.
DVLOG(2) << __FUNCTION__ << ": FIXME, fallback proj matrix update";
- if (non_exclusive_projection_matrix_.size() > 0) {
+ if (non_immersive_projection_matrix_.size() > 0) {
views_[XRView::kEyeLeft]->UpdateProjectionMatrixFromRawValues(
- non_exclusive_projection_matrix_, depth_near_, depth_far_);
+ non_immersive_projection_matrix_, depth_near_, depth_far_);
}
}
@@ -668,12 +794,4 @@ void XRSession::Trace(blink::Visitor* visitor) {
EventTargetWithInlineData::Trace(visitor);
}
-void XRSession::TraceWrappers(blink::ScriptWrappableVisitor* visitor) const {
- for (const auto& input_source : input_sources_.Values())
- visitor->TraceWrappers(input_source);
-
- visitor->TraceWrappers(callback_collection_);
- EventTargetWithInlineData::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_session.h b/chromium/third_party/blink/renderer/modules/xr/xr_session.h
index 02dd8802ee9..c71429ba1f8 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_session.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_session.h
@@ -9,6 +9,8 @@
#include "mojo/public/cpp/bindings/binding.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
+#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
+#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
#include "third_party/blink/renderer/modules/xr/xr_frame_request_callback_collection.h"
#include "third_party/blink/renderer/modules/xr/xr_input_source.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
@@ -21,8 +23,10 @@ namespace blink {
class Element;
class ResizeObserver;
+class ScriptPromiseResolver;
class V8XRFrameRequestCallback;
class XRCanvasInputProvider;
+class XRCoordinateSystem;
class XRDevice;
class XRFrameOfReferenceOptions;
class XRInputSourceEvent;
@@ -34,12 +38,24 @@ class XRSession final : public EventTargetWithInlineData {
DEFINE_WRAPPERTYPEINFO();
public:
- XRSession(XRDevice*, bool exclusive, XRPresentationContext* output_context);
+ enum EnvironmentBlendMode {
+ kBlendModeOpaque = 1,
+ kBlendModeAdditive = 2,
+ kBlendModeAlphaBlend = 3
+ };
+
+ XRSession(XRDevice*,
+ bool immersive,
+ bool environment_integration,
+ XRPresentationContext* output_context,
+ EnvironmentBlendMode environment_blend_mode);
~XRSession() override = default;
XRDevice* device() const { return device_; }
- bool exclusive() const { return exclusive_; }
+ bool immersive() const { return immersive_; }
+ bool environmentIntegration() const { return environment_integration_; }
XRPresentationContext* outputContext() const { return output_context_; }
+ const String& environmentBlendMode() const { return blend_mode_string_; }
// Near and far depths are used when computing projection matrices for this
// Session's views. Changes will propegate to the appropriate matrices on the
@@ -73,6 +89,11 @@ class XRSession final : public EventTargetWithInlineData {
HeapVector<Member<XRInputSource>> getInputSources() const;
+ ScriptPromise requestHitTest(ScriptState* script_state,
+ NotShared<DOMFloat32Array> origin,
+ NotShared<DOMFloat32Array> direction,
+ XRCoordinateSystem* coordinate_system);
+
// Called by JavaScript to manually end the session.
ScriptPromise end(ScriptState*);
@@ -82,14 +103,13 @@ class XRSession final : public EventTargetWithInlineData {
// when the presentation service connection is closed.
void ForceEnd();
- // Describes the default scalar to be applied to the ideal framebuffer
- // dimensions when the developer does not specify one. Should be a value that
- // provides a good balance between quality and performance.
- double DefaultFramebufferScale() const;
+ // Describes the scalar to be applied to the default framebuffer dimensions
+ // which gives 1:1 pixel ratio at the center of the user's view.
+ double NativeFramebufferScale() const;
- // Describes the ideal dimensions of layer framebuffers, preferrably defined
- // as the size which gives 1:1 pixel ratio at the center of the user's view.
- DoubleSize IdealFramebufferSize() const;
+ // Describes the recommended dimensions of layer framebuffers. Should be a
+ // value that provides a good balance between quality and performance.
+ DoubleSize DefaultFramebufferSize() const;
// Reports the size of the output context's, if one is available. If not
// reports (0, 0);
@@ -97,16 +117,16 @@ class XRSession final : public EventTargetWithInlineData {
void LogGetPose() const;
- // Output canvas orientation in degrees. Expected to be multiple of 90.
- int OutputCanvasAngle() const;
-
// EventTarget overrides.
ExecutionContext* GetExecutionContext() const override;
const AtomicString& InterfaceName() const override;
void OnFocusChanged();
- void OnFrame(std::unique_ptr<TransformationMatrix>,
- const base::Optional<gpu::MailboxHolder>&);
+ void OnFrame(double timestamp,
+ std::unique_ptr<TransformationMatrix>,
+ const base::Optional<gpu::MailboxHolder>& output_mailbox_holder,
+ const base::Optional<gpu::MailboxHolder>& bg_mailbox_holder,
+ const base::Optional<IntSize>& background_size);
void OnInputStateChange(
int16_t frame_id,
const WTF::Vector<device::mojom::blink::XRInputSourceStatePtr>&);
@@ -119,15 +139,14 @@ class XRSession final : public EventTargetWithInlineData {
void OnPoseReset();
- void SetNonExclusiveProjectionMatrix(const WTF::Vector<float>&);
+ void SetNonImmersiveProjectionMatrix(const WTF::Vector<float>&);
void Trace(blink::Visitor*) override;
- void TraceWrappers(blink::ScriptWrappableVisitor*) const override;
private:
class XRSessionResizeObserverDelegate;
- XRPresentationFrame* CreatePresentationFrame();
+ XRFrame* CreatePresentationFrame();
void UpdateCanvasDimensions(Element*);
void UpdateInputSourceState(
@@ -140,19 +159,26 @@ class XRSession final : public EventTargetWithInlineData {
void OnBlur();
bool HasAppropriateFocus();
+ void OnHitTestResults(
+ ScriptPromiseResolver* resolver,
+ base::Optional<WTF::Vector<device::mojom::blink::XRHitResultPtr>>
+ results);
+
const Member<XRDevice> device_;
- const bool exclusive_;
+ const bool immersive_;
+ const bool environment_integration_;
const Member<XRPresentationContext> output_context_;
+ String blend_mode_string_;
Member<XRLayer> base_layer_;
HeapVector<Member<XRView>> views_;
InputSourceMap input_sources_;
Member<ResizeObserver> resize_observer_;
Member<XRCanvasInputProvider> canvas_input_provider_;
- XRFrameRequestCallbackCollection callback_collection_;
+ TraceWrapperMember<XRFrameRequestCallbackCollection> callback_collection_;
std::unique_ptr<TransformationMatrix> base_pose_matrix_;
- WTF::Vector<float> non_exclusive_projection_matrix_;
+ WTF::Vector<float> non_immersive_projection_matrix_;
double depth_near_ = 0.1;
double depth_far_ = 1000.0;
@@ -171,7 +197,6 @@ class XRSession final : public EventTargetWithInlineData {
// Dimensions of the output canvas.
int output_width_ = 1;
int output_height_ = 1;
- int output_angle_ = 0;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_session.idl b/chromium/third_party/blink/renderer/modules/xr/xr_session.idl
index d9baba12528..a34084b75e3 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_session.idl
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_session.idl
@@ -3,13 +3,20 @@
// found in the LICENSE file.
// https://immersive-web.github.io/webxr/#xrsession-interface
+enum XREnvironmentBlendMode {
+ "opaque",
+ "additive",
+ "alpha-blend",
+};
+
[
SecureContext,
OriginTrialEnabled=WebXR
] interface XRSession : EventTarget {
readonly attribute XRDevice device;
- readonly attribute boolean exclusive;
+ readonly attribute boolean immersive;
readonly attribute XRPresentationContext outputContext;
+ readonly attribute XREnvironmentBlendMode environmentBlendMode;
attribute double depthNear;
attribute double depthFar;
@@ -28,5 +35,7 @@
[MeasureAs=XRSessionGetInputSources] FrozenArray<XRInputSource> getInputSources();
+ [RuntimeEnabled=WebXRHitTest, CallWith=ScriptState] Promise<FrozenArray<XRHitResult>> requestHitTest(Float32Array origin, Float32Array direction, XRCoordinateSystem coordinateSystem);
+
[CallWith=ScriptState] Promise<void> end();
};
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_session_creation_options.idl b/chromium/third_party/blink/renderer/modules/xr/xr_session_creation_options.idl
index 6a1bbf6e0b2..60db82cc910 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_session_creation_options.idl
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_session_creation_options.idl
@@ -6,6 +6,7 @@
[
SecureContext
] dictionary XRSessionCreationOptions {
- boolean exclusive = false;
+ [RuntimeEnabled=WebXRHitTest] boolean environmentIntegration = false;
+ boolean immersive = false;
XRPresentationContext outputContext;
};
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_view.cc b/chromium/third_party/blink/renderer/modules/xr/xr_view.cc
index b56d25bb737..2486ab6146f 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_view.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_view.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/modules/xr/xr_view.h"
-#include "third_party/blink/renderer/modules/xr/xr_presentation_frame.h"
+#include "third_party/blink/renderer/modules/xr/xr_frame.h"
#include "third_party/blink/renderer/modules/xr/xr_session.h"
#include "third_party/blink/renderer/platform/geometry/float_point_3d.h"
@@ -41,6 +41,8 @@ void XRView::UpdateProjectionMatrixFromRawValues(
float inverse_near_far = 1.0f / (near_depth - far_depth);
out[10] = (near_depth + far_depth) * inverse_near_far;
out[14] = (2.0f * far_depth * near_depth) * inverse_near_far;
+
+ inv_projection_dirty_ = true;
}
void XRView::UpdateProjectionMatrixFromFoV(float up_rad,
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer.cc b/chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer.cc
index 50ea39fea65..0971d900225 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer.cc
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer.cc
@@ -4,8 +4,6 @@
#include "third_party/blink/renderer/modules/xr/xr_webgl_layer.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_messages.h"
-#include "third_party/blink/renderer/bindings/core/v8/exception_state.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h"
#include "third_party/blink/renderer/modules/webgl/webgl_framebuffer.h"
@@ -16,6 +14,7 @@
#include "third_party/blink/renderer/modules/xr/xr_session.h"
#include "third_party/blink/renderer/modules/xr/xr_view.h"
#include "third_party/blink/renderer/modules/xr/xr_viewport.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/geometry/double_size.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
@@ -25,7 +24,6 @@ namespace blink {
namespace {
const double kFramebufferMinScale = 0.2;
-const double kFramebufferMaxScale = 1.0;
const double kViewportMinScale = 0.2;
const double kViewportMaxScale = 1.0;
@@ -43,7 +41,7 @@ XRWebGLLayer* XRWebGLLayer::Create(
const XRWebGLLayerInit& initializer,
ExceptionState& exception_state) {
if (session->ended()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Cannot create an XRWebGLLayer for an "
"XRSession which has already ended.");
return nullptr;
@@ -57,7 +55,7 @@ XRWebGLLayer* XRWebGLLayer::Create(
}
if (webgl_context->isContextLost()) {
- exception_state.ThrowDOMException(kInvalidStateError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
"Cannot create an XRWebGLLayer with a "
"lost WebGL context.");
return nullptr;
@@ -65,7 +63,7 @@ XRWebGLLayer* XRWebGLLayer::Create(
if (!webgl_context->IsXRDeviceCompatible(session->device())) {
exception_state.ThrowDOMException(
- kInvalidStateError,
+ DOMExceptionCode::kInvalidStateError,
"The session's device is not the compatible device for this context.");
return nullptr;
}
@@ -76,18 +74,23 @@ XRWebGLLayer* XRWebGLLayer::Create(
bool want_alpha_channel = initializer.alpha();
bool want_multiview = initializer.multiview();
- double framebuffer_scale = session->DefaultFramebufferScale();
+ double framebuffer_scale = 1.0;
+
+ if (initializer.hasFramebufferScaleFactor()) {
+ // The max size will be either the native resolution or the default
+ // if that happens to be larger than the native res. (That can happen on
+ // desktop systems.)
+ double max_scale = std::max(session->NativeFramebufferScale(), 1.0);
- if (initializer.hasFramebufferScaleFactor() &&
- initializer.framebufferScaleFactor() != 0.0) {
// Clamp the developer-requested framebuffer size to ensure it's not too
// small to see or unreasonably large.
- framebuffer_scale =
- ClampToRange(initializer.framebufferScaleFactor(), kFramebufferMinScale,
- kFramebufferMaxScale);
+ // TODO: Would be best to have the max value communicated from the service
+ // rather than limited to the native res.
+ framebuffer_scale = ClampToRange(initializer.framebufferScaleFactor(),
+ kFramebufferMinScale, max_scale);
}
- DoubleSize framebuffers_size = session->IdealFramebufferSize();
+ DoubleSize framebuffers_size = session->DefaultFramebufferSize();
IntSize desired_size(framebuffers_size.Width() * framebuffer_scale,
framebuffers_size.Height() * framebuffer_scale);
@@ -102,7 +105,7 @@ XRWebGLLayer* XRWebGLLayer::Create(
want_stencil_buffer, want_antialiasing, want_multiview);
if (!drawing_buffer) {
- exception_state.ThrowDOMException(kOperationError,
+ exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
"Unable to create a framebuffer.");
return nullptr;
}
@@ -118,12 +121,12 @@ XRWebGLLayer::XRWebGLLayer(XRSession* session,
double framebuffer_scale)
: XRLayer(session, kXRWebGLLayerType),
webgl_context_(webgl_context),
- drawing_buffer_(drawing_buffer),
+ drawing_buffer_(std::move(drawing_buffer)),
framebuffer_(framebuffer),
framebuffer_scale_(framebuffer_scale) {
- DCHECK(drawing_buffer);
+ DCHECK(drawing_buffer_);
// If the contents need mirroring, indicate that to the drawing buffer.
- if (session->exclusive() && session->outputContext() &&
+ if (session->immersive() && session->outputContext() &&
session->device()->external()) {
mirroring_ = true;
drawing_buffer_->SetMirrorClient(this);
@@ -134,11 +137,12 @@ XRWebGLLayer::XRWebGLLayer(XRSession* session,
XRWebGLLayer::~XRWebGLLayer() {
if (mirroring_)
drawing_buffer_->SetMirrorClient(nullptr);
+ drawing_buffer_->BeginDestruction();
}
void XRWebGLLayer::getXRWebGLRenderingContext(
WebGLRenderingContextOrWebGL2RenderingContext& result) const {
- if (webgl_context_->Version() == 2) {
+ if (webgl_context_->ContextType() == Platform::kWebGL2ContextType) {
result.SetWebGL2RenderingContext(
static_cast<WebGL2RenderingContext*>(webgl_context_.Get()));
} else {
@@ -165,9 +169,9 @@ XRViewport* XRWebGLLayer::GetViewportForEye(XRView::Eye eye) {
}
void XRWebGLLayer::requestViewportScaling(double scale_factor) {
- if (!session()->exclusive()) {
+ if (!session()->immersive()) {
// TODO(bajones): For the moment we're just going to ignore viewport changes
- // in non-exclusive mode. This is legal, but probably not what developers
+ // in non-immersive mode. This is legal, but probably not what developers
// would like to see. Look into making viewport scale apply properly.
scale_factor = 1.0;
} else {
@@ -182,13 +186,18 @@ void XRWebGLLayer::requestViewportScaling(double scale_factor) {
requested_viewport_scale_ = scale_factor;
}
+double XRWebGLLayer::getNativeFramebufferScaleFactor(XRSession* session) {
+ return session->NativeFramebufferScale();
+ ;
+}
+
void XRWebGLLayer::UpdateViewports() {
long framebuffer_width = framebufferWidth();
long framebuffer_height = framebufferHeight();
viewports_dirty_ = false;
- if (session()->exclusive()) {
+ if (session()->immersive()) {
left_viewport_ =
new XRViewport(0, 0, framebuffer_width * 0.5 * viewport_scale_,
framebuffer_height * viewport_scale_);
@@ -245,6 +254,7 @@ void XRWebGLLayer::OverwriteColorBufferFromMailboxTexture(
const gpu::MailboxHolder& mailbox_holder,
const IntSize& size) {
drawing_buffer_->OverwriteColorBufferFromMailboxTexture(mailbox_holder, size);
+ framebuffer_->SetContentsChanged(true);
}
void XRWebGLLayer::OnFrameStart(
@@ -273,7 +283,7 @@ void XRWebGLLayer::OnFrameEnd() {
}
// Submit the frame to the XR compositor.
- if (session()->exclusive()) {
+ if (session()->immersive()) {
// Always call submit, but notify if the contents were changed or not.
session()->device()->frameProvider()->SubmitWebGLLayer(
this, framebuffer_->HaveContentsChanged());
@@ -288,17 +298,17 @@ void XRWebGLLayer::OnFrameEnd() {
}
void XRWebGLLayer::OnResize() {
- if (!session()->exclusive()) {
- // For non-exclusive sessions a resize indicates we should adjust the
+ if (!session()->immersive()) {
+ // For non-immersive sessions a resize indicates we should adjust the
// drawing buffer size to match the canvas.
- DoubleSize framebuffers_size = session()->IdealFramebufferSize();
+ DoubleSize framebuffers_size = session()->DefaultFramebufferSize();
IntSize desired_size(framebuffers_size.Width() * framebuffer_scale_,
framebuffers_size.Height() * framebuffer_scale_);
drawing_buffer_->Resize(desired_size);
}
- // With both exclusive and non-exclusive session the viewports should be
+ // With both immersive and non-immersive session the viewports should be
// recomputed when the output canvas resizes.
viewports_dirty_ = true;
}
@@ -333,9 +343,4 @@ void XRWebGLLayer::Trace(blink::Visitor* visitor) {
XRLayer::Trace(visitor);
}
-void XRWebGLLayer::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(webgl_context_);
- XRLayer::TraceWrappers(visitor);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer.h b/chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer.h
index dc606b3175a..c0012c27700 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer.h
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer.h
@@ -60,6 +60,8 @@ class XRWebGLLayer final : public XRLayer,
XRViewport* getViewport(XRView*);
void requestViewportScaling(double scale_factor);
+ static double getNativeFramebufferScaleFactor(XRSession* session);
+
XRViewport* GetViewportForEye(XRView::Eye);
void UpdateViewports();
@@ -80,7 +82,6 @@ class XRWebGLLayer final : public XRLayer,
std::unique_ptr<viz::SingleReleaseCallback>) override;
void Trace(blink::Visitor*) override;
- void TraceWrappers(ScriptWrappableVisitor*) const override;
private:
XRWebGLLayer(XRSession*,
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer.idl b/chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer.idl
index 39e334cbbe3..56db1739098 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer.idl
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer.idl
@@ -24,4 +24,6 @@ typedef (WebGLRenderingContext or WebGL2RenderingContext) XRWebGLRenderingContex
XRViewport? getViewport(XRView view);
void requestViewportScaling(double viewportScaleFactor);
+
+ static double getNativeFramebufferScaleFactor(XRSession session);
};
diff --git a/chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer_init.idl b/chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer_init.idl
index 976fffa680a..7209d81b091 100644
--- a/chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer_init.idl
+++ b/chromium/third_party/blink/renderer/modules/xr/xr_webgl_layer_init.idl
@@ -11,5 +11,5 @@
boolean stencil = false;
boolean alpha = true;
boolean multiview = false;
- double framebufferScaleFactor;
+ double framebufferScaleFactor = 1.0;
};
diff --git a/chromium/third_party/blink/renderer/platform/BUILD.gn b/chromium/third_party/blink/renderer/platform/BUILD.gn
index 05177001104..d5d8e48305b 100644
--- a/chromium/third_party/blink/renderer/platform/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/BUILD.gn
@@ -140,8 +140,6 @@ executable("character_data_generator") {
]
configs += [ "//third_party/blink/renderer:config" ]
deps = [
- "//build/config:exe_and_shlib_deps",
-
# Default manifest on Windows (a no-op elsewhere).
"//build/win:default_exe_manifest",
"//third_party/icu",
@@ -190,7 +188,6 @@ group("blink_platform_public_deps") {
"//gpu/command_buffer/client:client",
"//gpu/command_buffer/client:gles2_interface",
"//gpu/command_buffer/common:common",
- "//media",
"//net",
"//services/device/public/mojom:generic_sensor_blink",
"//services/device/public/mojom:mojom_blink",
@@ -359,7 +356,7 @@ jumbo_component("platform") {
"audio/cpu/x86/vector_math_impl.h",
"audio/cpu/x86/vector_math_sse.cc",
"audio/cpu/x86/vector_math_sse.h",
- "audio/cpu/x86/vector_math_x8_6.h",
+ "audio/cpu/x86/vector_math_x86.h",
"audio/denormal_disabler.h",
"audio/direct_convolver.cc",
"audio/direct_convolver.h",
@@ -409,6 +406,8 @@ jumbo_component("platform") {
"audio/reverb_convolver_stage.h",
"audio/reverb_input_buffer.cc",
"audio/reverb_input_buffer.h",
+ "audio/simple_fft_convolver.cc",
+ "audio/simple_fft_convolver.h",
"audio/sinc_resampler.cc",
"audio/sinc_resampler.h",
"audio/stereo_panner.cc",
@@ -428,8 +427,14 @@ jumbo_component("platform") {
"bindings/dom_wrapper_map.h",
"bindings/dom_wrapper_world.cc",
"bindings/dom_wrapper_world.h",
+ "bindings/exception_code.h",
+ "bindings/exception_messages.cc",
+ "bindings/exception_messages.h",
+ "bindings/exception_state.cc",
+ "bindings/exception_state.h",
"bindings/microtask.cc",
"bindings/microtask.h",
+ "bindings/name_client.h",
"bindings/origin_trial_features.cc",
"bindings/origin_trial_features.h",
"bindings/runtime_call_stats.cc",
@@ -444,14 +449,12 @@ jumbo_component("platform") {
"bindings/script_wrappable.h",
"bindings/script_wrappable_marking_visitor.cc",
"bindings/script_wrappable_marking_visitor.h",
- "bindings/script_wrappable_visitor.cc",
"bindings/script_wrappable_visitor.h",
"bindings/script_wrappable_visitor_verifier.h",
"bindings/shared_persistent.h",
"bindings/string_resource.cc",
"bindings/string_resource.h",
"bindings/to_v8.h",
- "bindings/trace_wrapper_base.h",
"bindings/trace_wrapper_member.h",
"bindings/trace_wrapper_v8_reference.h",
"bindings/trace_wrapper_v8_string.cc",
@@ -483,10 +486,6 @@ jumbo_component("platform") {
"bindings/wrapper_type_info.cc",
"bindings/wrapper_type_info.h",
"calculation_value.h",
- "clipboard/clipboard_mime_types.cc",
- "clipboard/clipboard_mime_types.h",
- "clipboard/clipboard_utilities.cc",
- "clipboard/clipboard_utilities.h",
"content_decryption_module_result.h",
"content_setting_callbacks.cc",
"content_setting_callbacks.h",
@@ -504,23 +503,18 @@ jumbo_component("platform") {
"data_resource_helper.h",
"date_components.cc",
"date_components.h",
- "decimal.cc",
- "decimal.h",
"drag_image.cc",
"drag_image.h",
- "event_dispatch_forbidden_scope.cc",
- "event_dispatch_forbidden_scope.h",
"exported/file_path_conversion.cc",
"exported/interface_registry.cc",
"exported/platform.cc",
"exported/service_registry.cc",
"exported/url_conversion.cc",
- "exported/web_active_gesture_animation.cc",
- "exported/web_active_gesture_animation.h",
"exported/web_audio_bus.cc",
"exported/web_audio_device.cc",
"exported/web_blob_info.cc",
"exported/web_cache.cc",
+ "exported/web_canonical_cookie.cc",
"exported/web_canvas_capture_handler.cc",
"exported/web_coalesced_input_event.cc",
"exported/web_content_decryption_module.cc",
@@ -568,6 +562,7 @@ jumbo_component("platform") {
"exported/web_rtc_rtp_contributing_source.cc",
"exported/web_rtc_rtp_receiver.cc",
"exported/web_rtc_rtp_sender.cc",
+ "exported/web_rtc_rtp_transceiver.cc",
"exported/web_rtc_session_description.cc",
"exported/web_rtc_session_description_request.cc",
"exported/web_rtc_stats.cc",
@@ -603,8 +598,6 @@ jumbo_component("platform") {
"file_metadata.cc",
"file_metadata.h",
"file_system_type.h",
- "fonts/accept_languages_resolver.cc",
- "fonts/accept_languages_resolver.h",
"fonts/alternate_font_family.h",
"fonts/android/font_cache_android.cc",
"fonts/bitmap_glyphs_blacklist.cc",
@@ -696,13 +689,13 @@ jumbo_component("platform") {
"fonts/shaping/caching_word_shape_iterator.h",
"fonts/shaping/caching_word_shaper.cc",
"fonts/shaping/caching_word_shaper.h",
- "fonts/shaping/case_mapping_harf_buzz_buffer_filler.cc",
- "fonts/shaping/case_mapping_harf_buzz_buffer_filler.h",
- "fonts/shaping/harf_buzz_face.cc",
- "fonts/shaping/harf_buzz_face.h",
- "fonts/shaping/harf_buzz_font_cache.h",
- "fonts/shaping/harf_buzz_shaper.cc",
- "fonts/shaping/harf_buzz_shaper.h",
+ "fonts/shaping/case_mapping_harfbuzz_buffer_filler.cc",
+ "fonts/shaping/case_mapping_harfbuzz_buffer_filler.h",
+ "fonts/shaping/harfbuzz_face.cc",
+ "fonts/shaping/harfbuzz_face.h",
+ "fonts/shaping/harfbuzz_font_cache.h",
+ "fonts/shaping/harfbuzz_shaper.cc",
+ "fonts/shaping/harfbuzz_shaper.h",
"fonts/shaping/run_segmenter.cc",
"fonts/shaping/run_segmenter.h",
"fonts/shaping/shape_cache.cc",
@@ -818,6 +811,9 @@ jumbo_component("platform") {
"graphics/canvas_metrics.h",
"graphics/canvas_resource.cc",
"graphics/canvas_resource.h",
+ "graphics/canvas_resource_dispatcher.cc",
+ "graphics/canvas_resource_dispatcher.h",
+ "graphics/canvas_resource_host.cc",
"graphics/canvas_resource_host.h",
"graphics/canvas_resource_provider.cc",
"graphics/canvas_resource_provider.h",
@@ -832,8 +828,6 @@ jumbo_component("platform") {
"graphics/color_space_profile_data.h",
"graphics/compositing/chunk_to_layer_mapper.cc",
"graphics/compositing/chunk_to_layer_mapper.h",
- "graphics/compositing/composited_layer_raster_invalidator.cc",
- "graphics/compositing/composited_layer_raster_invalidator.h",
"graphics/compositing/content_layer_client_impl.cc",
"graphics/compositing/content_layer_client_impl.h",
"graphics/compositing/paint_artifact_compositor.cc",
@@ -850,7 +844,6 @@ jumbo_component("platform") {
"graphics/compositor_filter_operations.cc",
"graphics/compositor_filter_operations.h",
"graphics/compositor_mutator.h",
- "graphics/compositor_mutator.h",
"graphics/compositor_mutator_client.cc",
"graphics/compositor_mutator_client.h",
"graphics/compositor_mutator_impl.cc",
@@ -990,26 +983,12 @@ jumbo_component("platform") {
"graphics/logging_canvas.h",
"graphics/mailbox_texture_holder.cc",
"graphics/mailbox_texture_holder.h",
- "graphics/offscreen_canvas_frame_dispatcher.cc",
- "graphics/offscreen_canvas_frame_dispatcher.h",
"graphics/offscreen_canvas_placeholder.cc",
"graphics/offscreen_canvas_placeholder.h",
"graphics/offscreen_canvas_resource_provider.cc",
"graphics/offscreen_canvas_resource_provider.h",
- "graphics/paint/clip_display_item.cc",
- "graphics/paint/clip_display_item.h",
"graphics/paint/clip_paint_property_node.cc",
"graphics/paint/clip_paint_property_node.h",
- "graphics/paint/clip_path_display_item.cc",
- "graphics/paint/clip_path_display_item.h",
- "graphics/paint/clip_path_recorder.cc",
- "graphics/paint/clip_path_recorder.h",
- "graphics/paint/clip_recorder.cc",
- "graphics/paint/clip_recorder.h",
- "graphics/paint/compositing_display_item.cc",
- "graphics/paint/compositing_display_item.h",
- "graphics/paint/compositing_recorder.cc",
- "graphics/paint/compositing_recorder.h",
"graphics/paint/cull_rect.cc",
"graphics/paint/cull_rect.h",
"graphics/paint/display_item.cc",
@@ -1019,16 +998,14 @@ jumbo_component("platform") {
"graphics/paint/display_item_client.h",
"graphics/paint/display_item_list.cc",
"graphics/paint/display_item_list.h",
+ "graphics/paint/display_item_raster_invalidator.cc",
+ "graphics/paint/display_item_raster_invalidator.h",
"graphics/paint/drawing_display_item.cc",
"graphics/paint/drawing_display_item.h",
"graphics/paint/drawing_recorder.cc",
"graphics/paint/drawing_recorder.h",
"graphics/paint/effect_paint_property_node.cc",
"graphics/paint/effect_paint_property_node.h",
- "graphics/paint/filter_display_item.cc",
- "graphics/paint/filter_display_item.h",
- "graphics/paint/float_clip_display_item.cc",
- "graphics/paint/float_clip_display_item.h",
"graphics/paint/float_clip_rect.h",
"graphics/paint/foreign_layer_display_item.cc",
"graphics/paint/foreign_layer_display_item.h",
@@ -1038,6 +1015,7 @@ jumbo_component("platform") {
"graphics/paint/geometry_mapper_clip_cache.h",
"graphics/paint/geometry_mapper_transform_cache.cc",
"graphics/paint/geometry_mapper_transform_cache.h",
+ "graphics/paint/hit_test_data.cc",
"graphics/paint/hit_test_data.h",
"graphics/paint/paint_artifact.cc",
"graphics/paint/paint_artifact.h",
@@ -1066,21 +1044,17 @@ jumbo_component("platform") {
"graphics/paint/property_tree_state.h",
"graphics/paint/raster_invalidation_tracking.cc",
"graphics/paint/raster_invalidation_tracking.h",
+ "graphics/paint/raster_invalidator.cc",
+ "graphics/paint/raster_invalidator.h",
"graphics/paint/ref_counted_property_tree_state.cc",
"graphics/paint/ref_counted_property_tree_state.h",
"graphics/paint/scoped_display_item_fragment.h",
"graphics/paint/scoped_paint_chunk_properties.h",
- "graphics/paint/scroll_display_item.cc",
- "graphics/paint/scroll_display_item.h",
"graphics/paint/scroll_hit_test_display_item.cc",
"graphics/paint/scroll_hit_test_display_item.h",
"graphics/paint/scroll_paint_property_node.cc",
"graphics/paint/scroll_paint_property_node.h",
"graphics/paint/subsequence_recorder.h",
- "graphics/paint/transform_3d_display_item.cc",
- "graphics/paint/transform_3d_display_item.h",
- "graphics/paint/transform_display_item.cc",
- "graphics/paint/transform_display_item.h",
"graphics/paint/transform_paint_property_node.cc",
"graphics/paint/transform_paint_property_node.h",
"graphics/paint_generated_image.cc",
@@ -1172,12 +1146,8 @@ jumbo_component("platform") {
"json/json_values.cc",
"json/json_values.h",
"keyboard_codes.h",
- "kill_ring.h",
- "kill_ring_none.cc",
"language.cc",
"language.h",
- "layout_locale.cc",
- "layout_locale.h",
"layout_test_support.cc",
"layout_test_support.h",
"layout_unit.cc",
@@ -1201,7 +1171,6 @@ jumbo_component("platform") {
"mac/color_mac.mm",
"mac/graphics_context_canvas.h",
"mac/graphics_context_canvas.mm",
- "mac/kill_ring_mac.mm",
"mac/local_current_graphics_context.h",
"mac/local_current_graphics_context.mm",
"mac/ns_scroller_imp_details.h",
@@ -1235,6 +1204,8 @@ jumbo_component("platform") {
"mojo/big_string_mojom_traits.h",
"mojo/bluetooth_struct_traits.cc",
"mojo/bluetooth_struct_traits.h",
+ "mojo/canonical_cookie_mojom_traits.cc",
+ "mojo/canonical_cookie_mojom_traits.h",
"mojo/fetch_api_request_struct_traits.cc",
"mojo/interface_invalidator.cc",
"mojo/interface_invalidator.h",
@@ -1258,8 +1229,6 @@ jumbo_component("platform") {
"platform_chrome_client.h",
"plugins/plugin_data.cc",
"plugins/plugin_data.h",
- "plugins/plugin_list_builder.cc",
- "plugins/plugin_list_builder.h",
"plugins/plugin_script_forbidden_scope.cc",
"plugins/plugin_script_forbidden_scope.h",
"pod_arena.h",
@@ -1348,6 +1317,8 @@ jumbo_component("platform") {
"text/hyphenation.h",
"text/icu_error.cc",
"text/icu_error.h",
+ "text/layout_locale.cc",
+ "text/layout_locale.h",
"text/line_ending.cc",
"text/line_ending.h",
"text/linux/hyphenation_linux.cc",
@@ -1396,8 +1367,6 @@ jumbo_component("platform") {
"theme.cc",
"theme.h",
"theme_types.h",
- "threading/background_task_runner.cc",
- "threading/background_task_runner.h",
"time_clamper.cc",
"time_clamper.h",
"timer.cc",
@@ -1524,13 +1493,16 @@ jumbo_component("platform") {
deps = [
":platform_export",
"//base/allocator:buildflags",
- "//components/viz/service",
+ "//components/viz/client",
+ "//components/viz/common",
"//device/vr/public/mojom:mojom_blink",
"//gin",
+ "//media",
"//mojo/public/cpp/base",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/bindings:wtf_support",
"//services/service_manager/public/cpp",
+ "//services/ui/public/cpp/gpu",
"//skia:skcms",
"//third_party:freetype_harfbuzz",
"//third_party/blink/public:embedded_frame_sink_mojo_bindings_blink",
@@ -1542,10 +1514,8 @@ jumbo_component("platform") {
if (is_mac) {
sources -= [
- # Uses KillRingMac.mm instead.
"fonts/skia/font_cache_skia.cc",
"fonts/web_font_render_style.cc",
- "kill_ring_none.cc",
"scroll/scroll_animator.cc",
"scroll/scroll_animator.h",
@@ -1572,7 +1542,6 @@ jumbo_component("platform") {
}
if (is_win) {
- sources += [ "clipboard/clipboard_utilities_win.cc" ]
sources -= [
# TODO(https://crbug.com/808221): Use WebFontRenderStyle on Windows.
"fonts/web_font_render_style.cc",
@@ -1658,6 +1627,8 @@ jumbo_static_library("test_support") {
"testing/fuzzed_data_provider.h",
"testing/histogram_tester.cc",
"testing/histogram_tester.h",
+ "testing/layer_tree_host_embedder.cc",
+ "testing/layer_tree_host_embedder.h",
"testing/message_loop_for_mojo.h",
"testing/mock_web_crypto.cc",
"testing/mock_web_crypto.h",
@@ -1665,8 +1636,11 @@ jumbo_static_library("test_support") {
"testing/paint_test_configurations.h",
"testing/picture_matchers.cc",
"testing/picture_matchers.h",
+ "testing/scoped_fake_plugin_registry.cc",
+ "testing/scoped_fake_plugin_registry.h",
"testing/scoped_mocked_url.cc",
"testing/scoped_mocked_url.h",
+ "testing/stub_graphics_layer_client.h",
"testing/test_paint_artifact.cc",
"testing/test_paint_artifact.h",
"testing/testing_platform_support.cc",
@@ -1680,8 +1654,6 @@ jumbo_static_library("test_support") {
"testing/url_test_helpers.cc",
"testing/url_test_helpers.h",
"testing/use_mock_scrollbar_settings.h",
- "testing/web_layer_tree_view_impl_for_testing.cc",
- "testing/web_layer_tree_view_impl_for_testing.h",
"testing/weburl_loader_mock.cc",
"testing/weburl_loader_mock.h",
"testing/weburl_loader_mock_factory_impl.cc",
@@ -1709,7 +1681,10 @@ jumbo_static_library("test_support") {
deps = [
"//base/test:test_support",
- "//mojo/edk",
+ "//mojo/core/embedder",
+ "//mojo/public/cpp/bindings",
+ "//services/service_manager/public/cpp",
+ "//skia",
"//third_party/blink/renderer/platform/blob:test_support",
"//third_party/blink/renderer/platform/loader:test_support",
"//third_party/blink/renderer/platform/network:test_support",
@@ -1744,15 +1719,15 @@ jumbo_source_set("blink_platform_unittests_sources") {
"audio/push_pull_fifo_test.cc",
"audio/vector_math_test.cc",
"bindings/runtime_call_stats_test.cc",
- "decimal_test.cc",
"drag_image_test.cc",
"exported/file_path_conversion_test.cc",
+ "exported/web_canonical_cookie_test.cc",
"exported/web_cors_test.cc",
"exported/web_string_test.cc",
"feature_policy/feature_policy_test.cc",
- "fonts/accept_languages_resolver_test.cc",
"fonts/android/font_cache_android_test.cc",
"fonts/bitmap_glyphs_blacklist_test.cc",
+ "fonts/cursor_position_test.cc",
"fonts/font_cache_test.cc",
"fonts/font_description_test.cc",
"fonts/font_family_test.cc",
@@ -1767,7 +1742,7 @@ jumbo_source_set("blink_platform_unittests_sources") {
"fonts/orientation_iterator_test.cc",
"fonts/script_run_iterator_test.cc",
"fonts/shaping/caching_word_shaper_test.cc",
- "fonts/shaping/harf_buzz_shaper_test.cc",
+ "fonts/shaping/harfbuzz_shaper_test.cc",
"fonts/shaping/run_segmenter_test.cc",
"fonts/shaping/shape_result_bloberizer_test.cc",
"fonts/shaping/shaping_line_breaker_test.cc",
@@ -1795,7 +1770,6 @@ jumbo_source_set("blink_platform_unittests_sources") {
"graphics/accelerated_static_bitmap_image_test.cc",
"graphics/bitmap_image_test.cc",
"graphics/compositing/chunk_to_layer_mapper_test.cc",
- "graphics/compositing/composited_layer_raster_invalidator_test.cc",
"graphics/compositing/paint_artifact_compositor_test.cc",
"graphics/compositing/paint_chunks_to_cc_layer_test.cc",
"graphics/compositor_element_id_test.cc",
@@ -1811,6 +1785,7 @@ jumbo_source_set("blink_platform_unittests_sources") {
"graphics/high_contrast_image_classifier_test.cc",
"graphics/paint/cull_rect_test.cc",
"graphics/paint/display_item_client_test.cc",
+ "graphics/paint/display_item_raster_invalidator_test.cc",
"graphics/paint/display_item_test.cc",
"graphics/paint/drawing_display_item_test.cc",
"graphics/paint/drawing_recorder_test.cc",
@@ -1823,6 +1798,7 @@ jumbo_source_set("blink_platform_unittests_sources") {
"graphics/paint/paint_property_node_test.cc",
"graphics/paint/paint_record_builder_test.cc",
"graphics/paint/property_tree_state_test.cc",
+ "graphics/paint/raster_invalidator_test.cc",
"graphics/paint_invalidation_reason_test.cc",
"graphics/path_test.cc",
"graphics/placeholder_image_test.cc",
@@ -1837,12 +1813,12 @@ jumbo_source_set("blink_platform_unittests_sources") {
"image-decoders/image_decoder_test.cc",
"image-decoders/image_decoder_test_helpers.cc",
"image-decoders/image_decoder_test_helpers.h",
+ "image-decoders/image_frame_test.cc",
"image-decoders/jpeg/jpeg_image_decoder_test.cc",
"image-decoders/png/png_image_decoder_test.cc",
"image-decoders/webp/webp_image_decoder_test.cc",
"json/json_parser_test.cc",
"json/json_values_test.cc",
- "layout_locale_test.cc",
"layout_unit_test.cc",
"lifecycle_context_test.cc",
"long_task_detector_test.cc",
@@ -1855,6 +1831,7 @@ jumbo_source_set("blink_platform_unittests_sources") {
"mojo/kurl_security_origin_test.cc",
"mojo/notification_struct_traits_test.cc",
"mojo/string16_mojom_traits_test.cc",
+ "plugins/plugin_data_test.cc",
"pod_arena_test.cc",
"pod_free_list_arena_test.cc",
"pod_interval_tree_test.cc",
@@ -1873,6 +1850,7 @@ jumbo_source_set("blink_platform_unittests_sources") {
"text/date_time_format_test.cc",
"text/hyphenation_test.cc",
"text/icu_error_test.cc",
+ "text/layout_locale_test.cc",
"text/line_ending_test.cc",
"text/platform_locale_test.cc",
"text/segmented_string_test.cc",
@@ -1883,7 +1861,6 @@ jumbo_source_set("blink_platform_unittests_sources") {
"text/text_run_test.cc",
"text/unicode_utilities_test.cc",
"text/writing_mode_utils_test.cc",
- "threading/background_task_runner_test.cc",
"time_clamper_test.cc",
"timer_test.cc",
"transforms/affine_transform_test.cc",
@@ -1935,7 +1912,7 @@ jumbo_source_set("blink_platform_unittests_sources") {
"//base/test:test_support",
"//cc",
"//cc:test_support",
- "//mojo/edk",
+ "//mojo/core/embedder",
"//mojo/public/cpp/bindings/tests:for_blink_tests",
"//mojo/public/cpp/test_support:test_utils",
"//mojo/public/interfaces/bindings/tests:test_interfaces_blink",
@@ -1975,8 +1952,7 @@ executable("image_decode_bench") {
deps = [
":platform",
- "//build/config:exe_and_shlib_deps",
- "//mojo/edk",
+ "//mojo/core/embedder",
"//third_party/blink/renderer/platform/wtf",
]
@@ -1993,6 +1969,7 @@ test("blink_platform_perftests") {
"testing/blink_perf_test_suite.cc",
"testing/blink_perf_test_suite.h",
"testing/run_all_perf_tests.cc",
+ "testing/shape_result_perf_test.cc",
"testing/shaping_line_breaker_perf_test.cc",
]
@@ -2008,6 +1985,9 @@ test("blink_platform_perftests") {
":test_support",
"//base",
"//base/test:test_support",
+ "//mojo/public/cpp/bindings/tests:for_blink_tests",
+ "//mojo/public/cpp/test_support:test_utils",
+ "//mojo/public/interfaces/bindings/tests:test_interfaces_blink",
"//services/network/public/cpp:cpp",
"//testing/gtest",
"//testing/perf",
@@ -2067,6 +2047,23 @@ if (current_cpu == "x86" || current_cpu == "x64") {
}
}
+test("blink_fuzzer_unittests") {
+ deps = [
+ ":test_support",
+ "//third_party/blink/public:test_support",
+ ]
+
+ sources = [
+ "testing/run_all_tests.cc",
+ ]
+
+ if (is_linux) {
+ deps += [
+ "//third_party/blink/renderer/platform/scheduler:scheduler_fuzzer_tests",
+ ]
+ }
+}
+
# This source set is used for fuzzers that need an environment similar to unit
# tests.
jumbo_source_set("blink_fuzzer_test_support") {
@@ -2157,7 +2154,7 @@ fuzzer_test("feature_policy_fuzzer") {
fuzzer_test("blink_harfbuzz_shaper_fuzzer") {
sources = [
- "fonts/shaping/harf_buzz_shaper_fuzzer.cc",
+ "fonts/shaping/harfbuzz_shaper_fuzzer.cc",
]
deps = [
":blink_fuzzer_test_support",
@@ -2216,6 +2213,7 @@ jumbo_source_set("unit_tests") {
"graphics/canvas_color_params_test.cc",
"graphics/canvas_resource_test.cc",
"graphics/color_correction_test_utils.cc",
+ "graphics/compositor_mutator_impl_test.cc",
"graphics/deferred_image_decoder_test.cc",
"graphics/gpu/drawing_buffer_software_rendering_test.cc",
"graphics/graphics_layer_test.cc",
@@ -2223,8 +2221,8 @@ jumbo_source_set("unit_tests") {
"graphics/image_frame_generator_test.cc",
"graphics/image_layer_chromium_test.cc",
"graphics/offscreen_canvas_frame_dispatcher_test.cc",
+ "graphics/test/fake_canvas_resource_host.h",
"graphics/test/fake_gles2_interface.h",
- "graphics/test/fake_scrollable_area.h",
"graphics/test/fake_web_graphics_context_3d_provider.h",
"graphics/test/mock_image_decoder.h",
"graphics/test/mock_paint_canvas.h",
diff --git a/chromium/third_party/blink/renderer/platform/DEPS b/chromium/third_party/blink/renderer/platform/DEPS
index 2da4a9ced4f..e00bfd444fd 100644
--- a/chromium/third_party/blink/renderer/platform/DEPS
+++ b/chromium/third_party/blink/renderer/platform/DEPS
@@ -1,13 +1,16 @@
include_rules = [
# To whitelist base/ stuff Blink is allowed to include, we list up all
# directories and files instead of writing 'base/'.
- "+base/allocator/partition_allocator/oom.h",
+ "+base/allocator/partition_allocator",
+ "+base/atomic_ref_count.h",
"+base/bind.h",
"+base/bind_helpers.h",
"+base/bit_cast.h",
+ "+base/compiler_specific.h",
"+base/cpu.h",
"+base/feature_list.h",
"+base/files",
+ "+base/containers/adapters.h",
"+base/containers/flat_map.h",
"+base/guid.h",
"+base/json",
@@ -33,15 +36,16 @@ include_rules = [
"+base/synchronization/waitable_event.h",
"+base/sys_info.h",
"+base/android/sys_utils.h",
+ "+base/task/sequence_manager/task_time_observer.h",
"+base/test",
"+base/test/fuzzed_data_provider.h",
"+base/threading/thread_task_runner_handle.h",
"+base/time",
"+base/timer",
"+base/trace_event",
+ "+base/unguessable_token.h",
"+base/values.h",
"+base/lazy_instance.h",
- "+net/base/escape.h",
"+net/base/filename_util.h",
"+net/http/http_util.h",
"+net/http/http_request_headers.h",
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_animation.cc b/chromium/third_party/blink/renderer/platform/animation/compositor_animation.cc
index 2da7d25d62a..547ea225b6b 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_animation.cc
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_animation.cc
@@ -20,12 +20,13 @@ std::unique_ptr<CompositorAnimation> CompositorAnimation::Create() {
std::unique_ptr<CompositorAnimation>
CompositorAnimation::CreateWorkletAnimation(
+ cc::WorkletAnimationId worklet_animation_id,
const String& name,
- std::unique_ptr<CompositorScrollTimeline> scroll_timeline) {
+ std::unique_ptr<CompositorScrollTimeline> scroll_timeline,
+ std::unique_ptr<cc::AnimationOptions> options) {
return std::make_unique<CompositorAnimation>(cc::WorkletAnimation::Create(
- cc::AnimationIdProvider::NextAnimationId(),
- std::string(name.Ascii().data(), name.length()),
- std::move(scroll_timeline)));
+ worklet_animation_id, std::string(name.Ascii().data(), name.length()),
+ std::move(scroll_timeline), std::move(options)));
}
CompositorAnimation::CompositorAnimation(
@@ -80,6 +81,11 @@ void CompositorAnimation::AbortKeyframeModel(int keyframe_model_id) {
animation_->AbortKeyframeModel(keyframe_model_id);
}
+void CompositorAnimation::UpdateScrollTimelineId(
+ base::Optional<cc::ElementId> element_id) {
+ cc::ToWorkletAnimation(animation_.get())->SetScrollSourceId(element_id);
+}
+
void CompositorAnimation::NotifyAnimationStarted(base::TimeTicks monotonic_time,
int target_property,
int group) {
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_animation.h b/chromium/third_party/blink/renderer/platform/animation/compositor_animation.h
index d7c7c78b80d..c604a1847a3 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_animation.h
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_animation.h
@@ -7,6 +7,7 @@
#include <memory>
#include "base/memory/scoped_refptr.h"
+#include "base/optional.h"
#include "cc/animation/animation_delegate.h"
#include "cc/animation/scroll_timeline.h"
#include "cc/animation/single_keyframe_effect_animation.h"
@@ -33,8 +34,10 @@ class PLATFORM_EXPORT CompositorAnimation : public cc::AnimationDelegate {
public:
static std::unique_ptr<CompositorAnimation> Create();
static std::unique_ptr<CompositorAnimation> CreateWorkletAnimation(
+ cc::WorkletAnimationId,
const String& name,
- std::unique_ptr<CompositorScrollTimeline>);
+ std::unique_ptr<CompositorScrollTimeline>,
+ std::unique_ptr<cc::AnimationOptions>);
explicit CompositorAnimation(
scoped_refptr<cc::SingleKeyframeEffectAnimation>);
@@ -57,6 +60,8 @@ class PLATFORM_EXPORT CompositorAnimation : public cc::AnimationDelegate {
void PauseKeyframeModel(int keyframe_model_id, double time_offset);
void AbortKeyframeModel(int keyframe_model_id);
+ void UpdateScrollTimelineId(base::Optional<cc::ElementId>);
+
private:
// cc::AnimationDelegate implementation.
void NotifyAnimationStarted(base::TimeTicks monotonic_time,
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_animation_host_test.cc b/chromium/third_party/blink/renderer/platform/animation/compositor_animation_host_test.cc
index 569889d559c..bb898794c55 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_animation_host_test.cc
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_animation_host_test.cc
@@ -5,10 +5,11 @@
#include "third_party/blink/renderer/platform/animation/compositor_animation_host.h"
#include <memory>
+
#include "base/memory/scoped_refptr.h"
+#include "cc/animation/animation_host.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_timeline.h"
#include "third_party/blink/renderer/platform/testing/compositor_test.h"
-#include "third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.h"
namespace blink {
@@ -22,9 +23,9 @@ TEST_F(CompositorAnimationHostTest, AnimationHostNullWhenTimelineDetached) {
timeline->GetAnimationTimeline();
EXPECT_FALSE(cc_timeline->animation_host());
- WebLayerTreeViewImplForTesting layer_tree_view;
- CompositorAnimationHost compositor_animation_host(
- layer_tree_view.CompositorAnimationHost());
+ std::unique_ptr<cc::AnimationHost> animation_host =
+ cc::AnimationHost::CreateMainInstance();
+ CompositorAnimationHost compositor_animation_host(animation_host.get());
compositor_animation_host.AddTimeline(*timeline);
EXPECT_TRUE(cc_timeline->animation_host());
diff --git a/chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline_test.cc b/chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline_test.cc
index d35bee94611..410eb38f925 100644
--- a/chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline_test.cc
+++ b/chromium/third_party/blink/renderer/platform/animation/compositor_animation_timeline_test.cc
@@ -5,12 +5,12 @@
#include "third_party/blink/renderer/platform/animation/compositor_animation_timeline.h"
#include <memory>
+
#include "base/memory/scoped_refptr.h"
#include "cc/animation/animation_host.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_host.h"
#include "third_party/blink/renderer/platform/testing/compositor_test.h"
-#include "third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.h"
namespace blink {
@@ -25,19 +25,18 @@ TEST_F(CompositorAnimationTimelineTest,
timeline->GetAnimationTimeline();
EXPECT_FALSE(cc_timeline->animation_host());
- WebLayerTreeViewImplForTesting layer_tree_view;
- CompositorAnimationHost compositor_animation_host(
- layer_tree_view.CompositorAnimationHost());
+ std::unique_ptr<cc::AnimationHost> animation_host =
+ cc::AnimationHost::CreateMainInstance();
+ CompositorAnimationHost compositor_animation_host(animation_host.get());
compositor_animation_host.AddTimeline(*timeline);
- cc::AnimationHost* animation_host = cc_timeline->animation_host();
- EXPECT_TRUE(animation_host);
+ EXPECT_EQ(cc_timeline->animation_host(), animation_host.get());
EXPECT_TRUE(animation_host->GetTimelineById(cc_timeline->id()));
// Delete CompositorAnimationTimeline while attached to host.
timeline = nullptr;
- EXPECT_FALSE(cc_timeline->animation_host());
+ EXPECT_EQ(cc_timeline->animation_host(), nullptr);
EXPECT_FALSE(animation_host->GetTimelineById(cc_timeline->id()));
}
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_destination.cc b/chromium/third_party/blink/renderer/platform/audio/audio_destination.cc
index 24e122b12ac..1c98e7ca63f 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_destination.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_destination.cc
@@ -36,6 +36,7 @@
#include "third_party/blink/public/platform/web_audio_latency_hint.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
#include "third_party/blink/renderer/platform/audio/push_pull_fifo.h"
+#include "third_party/blink/renderer/platform/audio/vector_math.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -149,6 +150,23 @@ void AudioDestination::Render(const WebVector<float*>& destination_data,
delay_timestamp, "delay (s)", delay);
}
+// Determine if the rendered data is audible.
+static bool IsAudible(const AudioBus* rendered_data) {
+ // Compute the energy in each channel and sum up the energy in each channel
+ // for the total energy.
+ float energy = 0;
+
+ unsigned data_size = rendered_data->length();
+ for (unsigned k = 0; k < rendered_data->NumberOfChannels(); ++k) {
+ const float* data = rendered_data->Channel(k)->Data();
+ float channel_energy;
+ VectorMath::Vsvesq(data, 1, &channel_energy, data_size);
+ energy += channel_energy;
+ }
+
+ return energy > 0;
+}
+
void AudioDestination::RequestRender(size_t frames_requested,
size_t frames_to_render,
double delay,
@@ -183,8 +201,26 @@ void AudioDestination::RequestRender(size_t frames_requested,
output_position.position = 0.0;
// Process WebAudio graph and push the rendered output to FIFO.
- callback_.Render(nullptr, render_bus_.get(),
+ callback_.Render(render_bus_.get(),
AudioUtilities::kRenderQuantumFrames, output_position);
+
+ // Detect silence (or not) for MEI
+ bool is_audible = IsAudible(render_bus_.get());
+
+ if (is_audible) {
+ ++total_audible_renders_;
+ }
+
+ if (was_audible_) {
+ if (!is_audible) {
+ was_audible_ = false;
+ }
+ } else {
+ if (is_audible) {
+ was_audible_ = true;
+ }
+ }
+
fifo_->Push(render_bus_.get());
}
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_destination.h b/chromium/third_party/blink/renderer/platform/audio/audio_destination.h
index a42f2ee932b..71388f76156 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_destination.h
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_destination.h
@@ -138,6 +138,15 @@ class PLATFORM_EXPORT AudioDestination
// graph into the FIFO.
scoped_refptr<AudioBus> render_bus_;
+ // Keeps track if the output of this destination was audible, before the
+ // current rendering quantum. Used for recording "playback" time.
+ bool was_audible_ = false;
+
+ // Counts the number of render quanta where audible sound was played. We
+ // determine audibility on render quantum boundaries, so counting quanta is
+ // all that's needed.
+ size_t total_audible_renders_ = 0;
+
// Accessed by rendering thread: the render callback function of WebAudio
// engine. (i.e. DestinationNode)
AudioIOCallback& callback_;
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_dsp_kernel_processor.cc b/chromium/third_party/blink/renderer/platform/audio/audio_dsp_kernel_processor.cc
index 27a4021ce25..e15026be65f 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_dsp_kernel_processor.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_dsp_kernel_processor.cc
@@ -28,8 +28,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "third_party/blink/renderer/platform/audio/audio_dsp_kernel.h"
#include "third_party/blink/renderer/platform/audio/audio_dsp_kernel_processor.h"
+#include "third_party/blink/renderer/platform/audio/audio_dsp_kernel.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/audio/audio_io_callback.h b/chromium/third_party/blink/renderer/platform/audio/audio_io_callback.h
index 079bb199e5f..e97f83a8a0c 100644
--- a/chromium/third_party/blink/renderer/platform/audio/audio_io_callback.h
+++ b/chromium/third_party/blink/renderer/platform/audio/audio_io_callback.h
@@ -46,11 +46,9 @@ struct AudioIOPosition {
// Abstract base-class for isochronous audio I/O client.
class AudioIOCallback {
public:
- // render() is called periodically to get the next render quantum of audio
- // into destinationBus. Optional audio input is given in sourceBus (if it's
- // not 0).
- virtual void Render(AudioBus* source_bus,
- AudioBus* destination_bus,
+ // Called periodically to get the next render quantum of audio into
+ // |destination_bus|.
+ virtual void Render(AudioBus* destination_bus,
size_t frames_to_process,
const AudioIOPosition& output_position) = 0;
diff --git a/chromium/third_party/blink/renderer/platform/audio/biquad.cc b/chromium/third_party/blink/renderer/platform/audio/biquad.cc
index c9a643d5505..a97089040c0 100644
--- a/chromium/third_party/blink/renderer/platform/audio/biquad.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/biquad.cc
@@ -276,7 +276,7 @@ void Biquad::SetLowpassParams(int index, double cutoff, double resonance) {
resonance = pow10(resonance / 20);
- double theta = piDouble * cutoff;
+ double theta = kPiDouble * cutoff;
double alpha = sin(theta) / (2 * resonance);
double cosw = cos(theta);
double beta = (1 - cosw) / 2;
@@ -308,7 +308,7 @@ void Biquad::SetHighpassParams(int index, double cutoff, double resonance) {
// Compute biquad coefficients for highpass filter
resonance = pow10(resonance / 20);
- double theta = piDouble * cutoff;
+ double theta = kPiDouble * cutoff;
double alpha = sin(theta) / (2 * resonance);
double cosw = cos(theta);
double beta = (1 + cosw) / 2;
@@ -357,7 +357,7 @@ void Biquad::SetLowShelfParams(int index, double frequency, double db_gain) {
// The z-transform is a constant gain.
SetNormalizedCoefficients(index, a * a, 0, 0, 1, 0, 0);
} else if (frequency > 0) {
- double w0 = piDouble * frequency;
+ double w0 = kPiDouble * frequency;
double s = 1; // filter slope (1 is max value)
double alpha = 0.5 * sin(w0) * sqrt((a + 1 / a) * (1 / s - 1) + 2);
double k = cos(w0);
@@ -389,7 +389,7 @@ void Biquad::SetHighShelfParams(int index, double frequency, double db_gain) {
// The z-transform is 1.
SetNormalizedCoefficients(index, 1, 0, 0, 1, 0, 0);
} else if (frequency > 0) {
- double w0 = piDouble * frequency;
+ double w0 = kPiDouble * frequency;
double s = 1; // filter slope (1 is max value)
double alpha = 0.5 * sin(w0) * sqrt((a + 1 / a) * (1 / s - 1) + 2);
double k = cos(w0);
@@ -425,7 +425,7 @@ void Biquad::SetPeakingParams(int index,
if (frequency > 0 && frequency < 1) {
if (q > 0) {
- double w0 = piDouble * frequency;
+ double w0 = kPiDouble * frequency;
double alpha = sin(w0) / (2 * q);
double k = cos(w0);
@@ -458,7 +458,7 @@ void Biquad::SetAllpassParams(int index, double frequency, double q) {
if (frequency > 0 && frequency < 1) {
if (q > 0) {
- double w0 = piDouble * frequency;
+ double w0 = kPiDouble * frequency;
double alpha = sin(w0) / (2 * q);
double k = cos(w0);
@@ -491,7 +491,7 @@ void Biquad::SetNotchParams(int index, double frequency, double q) {
if (frequency > 0 && frequency < 1) {
if (q > 0) {
- double w0 = piDouble * frequency;
+ double w0 = kPiDouble * frequency;
double alpha = sin(w0) / (2 * q);
double k = cos(w0);
@@ -523,7 +523,7 @@ void Biquad::SetBandpassParams(int index, double frequency, double q) {
q = std::max(0.0, q);
if (frequency > 0 && frequency < 1) {
- double w0 = piDouble * frequency;
+ double w0 = kPiDouble * frequency;
if (q > 0) {
double alpha = sin(w0) / (2 * q);
double k = cos(w0);
@@ -585,7 +585,7 @@ void Biquad::GetFrequencyResponse(int n_frequencies,
mag_response[k] = std::nanf("");
phase_response[k] = std::nanf("");
} else {
- double omega = -piDouble * frequency[k];
+ double omega = -kPiDouble * frequency[k];
std::complex<double> z = std::complex<double>(cos(omega), sin(omega));
std::complex<double> numerator = b0 + (b1 + b2 * z) * z;
std::complex<double> denominator =
diff --git a/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_impl.h b/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_impl.h
index 8562a56d8d8..ef87b87e120 100644
--- a/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_impl.h
+++ b/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_impl.h
@@ -3,9 +3,9 @@
// found in the LICENSE file.
// This file intentionally does not have header guards, it's included from
-// VectorMathAVX.h and from VectorMathSSE.h with different macro definitions.
-// The following line silences a presubmit warning that would otherwise be
-// triggered by this: no-include-guard-because-multiply-included
+// vector_math_avx.h and from vector_math_sse.h with different macro
+// definitions. The following line silences a presubmit warning that would
+// otherwise be triggered by this: no-include-guard-because-multiply-included
#include "build/build_config.h"
diff --git a/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_x86.h b/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_x86.h
new file mode 100644
index 00000000000..f023b8f2dc1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_x86.h
@@ -0,0 +1,413 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_CPU_X86_VECTOR_MATH_X86_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_CPU_X86_VECTOR_MATH_X86_H_
+
+#include "base/cpu.h"
+#include "third_party/blink/renderer/platform/audio/cpu/x86/vector_math_avx.h"
+#include "third_party/blink/renderer/platform/audio/cpu/x86/vector_math_sse.h"
+#include "third_party/blink/renderer/platform/audio/vector_math_scalar.h"
+#include "third_party/blink/renderer/platform/wtf/assertions.h"
+
+namespace blink {
+namespace VectorMath {
+namespace X86 {
+
+struct FrameCounts {
+ size_t scalar_for_alignment;
+ size_t sse_for_alignment;
+ size_t avx;
+ size_t sse;
+ size_t scalar;
+};
+
+static bool CPUSupportsAVX() {
+ static bool supports = ::base::CPU().has_avx();
+ return supports;
+}
+
+static size_t GetAVXAlignmentOffsetInNumberOfFloats(const float* source_p) {
+ constexpr size_t kBytesPerRegister = AVX::kBitsPerRegister / 8u;
+ constexpr size_t kAlignmentOffsetMask = kBytesPerRegister - 1u;
+ size_t offset = reinterpret_cast<size_t>(source_p) & kAlignmentOffsetMask;
+ DCHECK_EQ(0u, offset % sizeof(*source_p));
+ return offset / sizeof(*source_p);
+}
+
+static ALWAYS_INLINE FrameCounts
+SplitFramesToProcess(const float* source_p, size_t frames_to_process) {
+ FrameCounts counts = {0u, 0u, 0u, 0u, 0u};
+
+ const size_t avx_alignment_offset =
+ GetAVXAlignmentOffsetInNumberOfFloats(source_p);
+
+ // If the first frame is not AVX aligned, the first several frames (at most
+ // seven) must be processed separately for proper alignment.
+ const size_t total_for_alignment =
+ (AVX::kPackedFloatsPerRegister - avx_alignment_offset) &
+ ~AVX::kFramesToProcessMask;
+ const size_t scalar_for_alignment =
+ total_for_alignment & ~SSE::kFramesToProcessMask;
+ const size_t sse_for_alignment =
+ total_for_alignment & SSE::kFramesToProcessMask;
+
+ // Check which CPU features can be used based on the number of frames to
+ // process and based on CPU support.
+ const bool use_at_least_avx =
+ CPUSupportsAVX() &&
+ frames_to_process >= scalar_for_alignment + sse_for_alignment +
+ AVX::kPackedFloatsPerRegister;
+ const bool use_at_least_sse =
+ use_at_least_avx ||
+ frames_to_process >= scalar_for_alignment + SSE::kPackedFloatsPerRegister;
+
+ if (use_at_least_sse) {
+ counts.scalar_for_alignment = scalar_for_alignment;
+ frames_to_process -= counts.scalar_for_alignment;
+ // The remaining frames are SSE aligned.
+ DCHECK(SSE::IsAligned(source_p + counts.scalar_for_alignment));
+
+ if (use_at_least_avx) {
+ counts.sse_for_alignment = sse_for_alignment;
+ frames_to_process -= counts.sse_for_alignment;
+ // The remaining frames are AVX aligned.
+ DCHECK(AVX::IsAligned(source_p + counts.scalar_for_alignment +
+ counts.sse_for_alignment));
+
+ // Process as many as possible of the remaining frames using AVX.
+ counts.avx = frames_to_process & AVX::kFramesToProcessMask;
+ frames_to_process -= counts.avx;
+ }
+
+ // Process as many as possible of the remaining frames using SSE.
+ counts.sse = frames_to_process & SSE::kFramesToProcessMask;
+ frames_to_process -= counts.sse;
+ }
+
+ // Process the remaining frames separately.
+ counts.scalar = frames_to_process;
+ return counts;
+}
+
+static ALWAYS_INLINE void PrepareFilterForConv(
+ const float* filter_p,
+ int filter_stride,
+ size_t filter_size,
+ AudioFloatArray* prepared_filter) {
+ if (CPUSupportsAVX()) {
+ AVX::PrepareFilterForConv(filter_p, filter_stride, filter_size,
+ prepared_filter);
+ } else {
+ SSE::PrepareFilterForConv(filter_p, filter_stride, filter_size,
+ prepared_filter);
+ }
+}
+
+static ALWAYS_INLINE void Conv(const float* source_p,
+ int source_stride,
+ const float* filter_p,
+ int filter_stride,
+ float* dest_p,
+ int dest_stride,
+ size_t frames_to_process,
+ size_t filter_size,
+ const AudioFloatArray* prepared_filter) {
+ const float* prepared_filter_p =
+ prepared_filter ? prepared_filter->Data() : nullptr;
+ if (source_stride == 1 && dest_stride == 1 && prepared_filter_p) {
+ if (CPUSupportsAVX() && (filter_size & ~AVX::kFramesToProcessMask) == 0u) {
+ // |frames_to_process| is always a multiply of render quantum and
+ // therefore the frames can always be processed using AVX.
+ CHECK_EQ(frames_to_process & ~AVX::kFramesToProcessMask, 0u);
+ AVX::Conv(source_p, prepared_filter_p, dest_p, frames_to_process,
+ filter_size);
+ return;
+ }
+ if ((filter_size & ~SSE::kFramesToProcessMask) == 0u) {
+ // |frames_to_process| is always a multiply of render quantum and
+ // therefore the frames can always be processed using SSE.
+ CHECK_EQ(frames_to_process & ~SSE::kFramesToProcessMask, 0u);
+ SSE::Conv(source_p, prepared_filter_p, dest_p, frames_to_process,
+ filter_size);
+ return;
+ }
+ }
+ Scalar::Conv(source_p, source_stride, filter_p, filter_stride, dest_p,
+ dest_stride, frames_to_process, filter_size, nullptr);
+}
+
+static ALWAYS_INLINE void Vadd(const float* source1p,
+ int source_stride1,
+ const float* source2p,
+ int source_stride2,
+ float* dest_p,
+ int dest_stride,
+ size_t frames_to_process) {
+ if (source_stride1 == 1 && source_stride2 == 1 && dest_stride == 1) {
+ const FrameCounts frame_counts =
+ SplitFramesToProcess(source1p, frames_to_process);
+
+ Scalar::Vadd(source1p, 1, source2p, 1, dest_p, 1,
+ frame_counts.scalar_for_alignment);
+ size_t i = frame_counts.scalar_for_alignment;
+ if (frame_counts.sse_for_alignment > 0u) {
+ SSE::Vadd(source1p + i, source2p + i, dest_p + i,
+ frame_counts.sse_for_alignment);
+ i += frame_counts.sse_for_alignment;
+ }
+ if (frame_counts.avx > 0u) {
+ AVX::Vadd(source1p + i, source2p + i, dest_p + i, frame_counts.avx);
+ i += frame_counts.avx;
+ }
+ if (frame_counts.sse > 0u) {
+ SSE::Vadd(source1p + i, source2p + i, dest_p + i, frame_counts.sse);
+ i += frame_counts.sse;
+ }
+ Scalar::Vadd(source1p + i, 1, source2p + i, 1, dest_p + i, 1,
+ frame_counts.scalar);
+ DCHECK_EQ(frames_to_process, i + frame_counts.scalar);
+ } else {
+ Scalar::Vadd(source1p, source_stride1, source2p, source_stride2, dest_p,
+ dest_stride, frames_to_process);
+ }
+}
+
+static ALWAYS_INLINE void Vclip(const float* source_p,
+ int source_stride,
+ const float* low_threshold_p,
+ const float* high_threshold_p,
+ float* dest_p,
+ int dest_stride,
+ size_t frames_to_process) {
+ if (source_stride == 1 && dest_stride == 1) {
+ const FrameCounts frame_counts =
+ SplitFramesToProcess(source_p, frames_to_process);
+
+ Scalar::Vclip(source_p, 1, low_threshold_p, high_threshold_p, dest_p, 1,
+ frame_counts.scalar_for_alignment);
+ size_t i = frame_counts.scalar_for_alignment;
+ if (frame_counts.sse_for_alignment > 0u) {
+ SSE::Vclip(source_p + i, low_threshold_p, high_threshold_p, dest_p + i,
+ frame_counts.sse_for_alignment);
+ i += frame_counts.sse_for_alignment;
+ }
+ if (frame_counts.avx > 0u) {
+ AVX::Vclip(source_p + i, low_threshold_p, high_threshold_p, dest_p + i,
+ frame_counts.avx);
+ i += frame_counts.avx;
+ }
+ if (frame_counts.sse > 0u) {
+ SSE::Vclip(source_p + i, low_threshold_p, high_threshold_p, dest_p + i,
+ frame_counts.sse);
+ i += frame_counts.sse;
+ }
+ Scalar::Vclip(source_p + i, 1, low_threshold_p, high_threshold_p,
+ dest_p + i, 1, frame_counts.scalar);
+ DCHECK_EQ(frames_to_process, i + frame_counts.scalar);
+ } else {
+ Scalar::Vclip(source_p, source_stride, low_threshold_p, high_threshold_p,
+ dest_p, dest_stride, frames_to_process);
+ }
+}
+
+static ALWAYS_INLINE void Vmaxmgv(const float* source_p,
+ int source_stride,
+ float* max_p,
+ size_t frames_to_process) {
+ if (source_stride == 1) {
+ const FrameCounts frame_counts =
+ SplitFramesToProcess(source_p, frames_to_process);
+
+ Scalar::Vmaxmgv(source_p, 1, max_p, frame_counts.scalar_for_alignment);
+ size_t i = frame_counts.scalar_for_alignment;
+ if (frame_counts.sse_for_alignment > 0u) {
+ SSE::Vmaxmgv(source_p + i, max_p, frame_counts.sse_for_alignment);
+ i += frame_counts.sse_for_alignment;
+ }
+ if (frame_counts.avx > 0u) {
+ AVX::Vmaxmgv(source_p + i, max_p, frame_counts.avx);
+ i += frame_counts.avx;
+ }
+ if (frame_counts.sse > 0u) {
+ SSE::Vmaxmgv(source_p + i, max_p, frame_counts.sse);
+ i += frame_counts.sse;
+ }
+ Scalar::Vmaxmgv(source_p + i, 1, max_p, frame_counts.scalar);
+ DCHECK_EQ(frames_to_process, i + frame_counts.scalar);
+ } else {
+ Scalar::Vmaxmgv(source_p, source_stride, max_p, frames_to_process);
+ }
+}
+
+static ALWAYS_INLINE void Vmul(const float* source1p,
+ int source_stride1,
+ const float* source2p,
+ int source_stride2,
+ float* dest_p,
+ int dest_stride,
+ size_t frames_to_process) {
+ if (source_stride1 == 1 && source_stride2 == 1 && dest_stride == 1) {
+ const FrameCounts frame_counts =
+ SplitFramesToProcess(source1p, frames_to_process);
+
+ Scalar::Vmul(source1p, 1, source2p, 1, dest_p, 1,
+ frame_counts.scalar_for_alignment);
+ size_t i = frame_counts.scalar_for_alignment;
+ if (frame_counts.sse_for_alignment > 0u) {
+ SSE::Vmul(source1p + i, source2p + i, dest_p + i,
+ frame_counts.sse_for_alignment);
+ i += frame_counts.sse_for_alignment;
+ }
+ if (frame_counts.avx > 0u) {
+ AVX::Vmul(source1p + i, source2p + i, dest_p + i, frame_counts.avx);
+ i += frame_counts.avx;
+ }
+ if (frame_counts.sse > 0u) {
+ SSE::Vmul(source1p + i, source2p + i, dest_p + i, frame_counts.sse);
+ i += frame_counts.sse;
+ }
+ Scalar::Vmul(source1p + i, 1, source2p + i, 1, dest_p + i, 1,
+ frame_counts.scalar);
+ DCHECK_EQ(frames_to_process, i + frame_counts.scalar);
+ } else {
+ Scalar::Vmul(source1p, source_stride1, source2p, source_stride2, dest_p,
+ dest_stride, frames_to_process);
+ }
+}
+
+static ALWAYS_INLINE void Vsma(const float* source_p,
+ int source_stride,
+ const float* scale,
+ float* dest_p,
+ int dest_stride,
+ size_t frames_to_process) {
+ if (source_stride == 1 && dest_stride == 1) {
+ const FrameCounts frame_counts =
+ SplitFramesToProcess(source_p, frames_to_process);
+
+ Scalar::Vsma(source_p, 1, scale, dest_p, 1,
+ frame_counts.scalar_for_alignment);
+ size_t i = frame_counts.scalar_for_alignment;
+ if (frame_counts.sse_for_alignment > 0u) {
+ SSE::Vsma(source_p + i, scale, dest_p + i,
+ frame_counts.sse_for_alignment);
+ i += frame_counts.sse_for_alignment;
+ }
+ if (frame_counts.avx > 0u) {
+ AVX::Vsma(source_p + i, scale, dest_p + i, frame_counts.avx);
+ i += frame_counts.avx;
+ }
+ if (frame_counts.sse > 0u) {
+ SSE::Vsma(source_p + i, scale, dest_p + i, frame_counts.sse);
+ i += frame_counts.sse;
+ }
+ Scalar::Vsma(source_p + i, 1, scale, dest_p + i, 1, frame_counts.scalar);
+ DCHECK_EQ(frames_to_process, i + frame_counts.scalar);
+ } else {
+ Scalar::Vsma(source_p, source_stride, scale, dest_p, dest_stride,
+ frames_to_process);
+ }
+}
+
+static ALWAYS_INLINE void Vsmul(const float* source_p,
+ int source_stride,
+ const float* scale,
+ float* dest_p,
+ int dest_stride,
+ size_t frames_to_process) {
+ if (source_stride == 1 && dest_stride == 1) {
+ const FrameCounts frame_counts =
+ SplitFramesToProcess(source_p, frames_to_process);
+
+ Scalar::Vsmul(source_p, 1, scale, dest_p, 1,
+ frame_counts.scalar_for_alignment);
+ size_t i = frame_counts.scalar_for_alignment;
+ if (frame_counts.sse_for_alignment > 0u) {
+ SSE::Vsmul(source_p + i, scale, dest_p + i,
+ frame_counts.sse_for_alignment);
+ i += frame_counts.sse_for_alignment;
+ }
+ if (frame_counts.avx > 0u) {
+ AVX::Vsmul(source_p + i, scale, dest_p + i, frame_counts.avx);
+ i += frame_counts.avx;
+ }
+ if (frame_counts.sse > 0u) {
+ SSE::Vsmul(source_p + i, scale, dest_p + i, frame_counts.sse);
+ i += frame_counts.sse;
+ }
+ Scalar::Vsmul(source_p + i, 1, scale, dest_p + i, 1, frame_counts.scalar);
+ DCHECK_EQ(frames_to_process, i + frame_counts.scalar);
+ } else {
+ Scalar::Vsmul(source_p, source_stride, scale, dest_p, dest_stride,
+ frames_to_process);
+ }
+}
+
+static ALWAYS_INLINE void Vsvesq(const float* source_p,
+ int source_stride,
+ float* sum_p,
+ size_t frames_to_process) {
+ if (source_stride == 1) {
+ const FrameCounts frame_counts =
+ SplitFramesToProcess(source_p, frames_to_process);
+
+ Scalar::Vsvesq(source_p, 1, sum_p, frame_counts.scalar_for_alignment);
+ size_t i = frame_counts.scalar_for_alignment;
+ if (frame_counts.sse_for_alignment > 0u) {
+ SSE::Vsvesq(source_p + i, sum_p, frame_counts.sse_for_alignment);
+ i += frame_counts.sse_for_alignment;
+ }
+ if (frame_counts.avx > 0u) {
+ AVX::Vsvesq(source_p + i, sum_p, frame_counts.avx);
+ i += frame_counts.avx;
+ }
+ if (frame_counts.sse > 0u) {
+ SSE::Vsvesq(source_p + i, sum_p, frame_counts.sse);
+ i += frame_counts.sse;
+ }
+ Scalar::Vsvesq(source_p + i, 1, sum_p, frame_counts.scalar);
+ DCHECK_EQ(frames_to_process, i + frame_counts.scalar);
+ } else {
+ Scalar::Vsvesq(source_p, source_stride, sum_p, frames_to_process);
+ }
+}
+
+static ALWAYS_INLINE void Zvmul(const float* real1p,
+ const float* imag1p,
+ const float* real2p,
+ const float* imag2p,
+ float* real_dest_p,
+ float* imag_dest_p,
+ size_t frames_to_process) {
+ FrameCounts frame_counts = SplitFramesToProcess(real1p, frames_to_process);
+
+ Scalar::Zvmul(real1p, imag1p, real2p, imag2p, real_dest_p, imag_dest_p,
+ frame_counts.scalar_for_alignment);
+ size_t i = frame_counts.scalar_for_alignment;
+ if (frame_counts.sse_for_alignment > 0u) {
+ SSE::Zvmul(real1p + i, imag1p + i, real2p + i, imag2p + i, real_dest_p + i,
+ imag_dest_p + i, frame_counts.sse_for_alignment);
+ i += frame_counts.sse_for_alignment;
+ }
+ if (frame_counts.avx > 0u) {
+ AVX::Zvmul(real1p + i, imag1p + i, real2p + i, imag2p + i, real_dest_p + i,
+ imag_dest_p + i, frame_counts.avx);
+ i += frame_counts.avx;
+ }
+ if (frame_counts.sse > 0u) {
+ SSE::Zvmul(real1p + i, imag1p + i, real2p + i, imag2p + i, real_dest_p + i,
+ imag_dest_p + i, frame_counts.sse);
+ i += frame_counts.sse;
+ }
+ Scalar::Zvmul(real1p + i, imag1p + i, real2p + i, imag2p + i, real_dest_p + i,
+ imag_dest_p + i, frame_counts.scalar);
+ DCHECK_EQ(frames_to_process, i + frame_counts.scalar);
+}
+
+} // namespace X86
+} // namespace VectorMath
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_CPU_X86_VECTOR_MATH_X86_H_
diff --git a/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_x8_6.h b/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_x8_6.h
deleted file mode 100644
index cc35b44b7bf..00000000000
--- a/chromium/third_party/blink/renderer/platform/audio/cpu/x86/vector_math_x8_6.h
+++ /dev/null
@@ -1,413 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_CPU_X86_VECTOR_MATH_X8_6_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_CPU_X86_VECTOR_MATH_X8_6_H_
-
-#include "base/cpu.h"
-#include "third_party/blink/renderer/platform/audio/cpu/x86/vector_math_avx.h"
-#include "third_party/blink/renderer/platform/audio/cpu/x86/vector_math_sse.h"
-#include "third_party/blink/renderer/platform/audio/vector_math_scalar.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-
-namespace blink {
-namespace VectorMath {
-namespace X86 {
-
-struct FrameCounts {
- size_t scalar_for_alignment;
- size_t sse_for_alignment;
- size_t avx;
- size_t sse;
- size_t scalar;
-};
-
-static bool CPUSupportsAVX() {
- static bool supports = ::base::CPU().has_avx();
- return supports;
-}
-
-static size_t GetAVXAlignmentOffsetInNumberOfFloats(const float* source_p) {
- constexpr size_t kBytesPerRegister = AVX::kBitsPerRegister / 8u;
- constexpr size_t kAlignmentOffsetMask = kBytesPerRegister - 1u;
- size_t offset = reinterpret_cast<size_t>(source_p) & kAlignmentOffsetMask;
- DCHECK_EQ(0u, offset % sizeof(*source_p));
- return offset / sizeof(*source_p);
-}
-
-static ALWAYS_INLINE FrameCounts
-SplitFramesToProcess(const float* source_p, size_t frames_to_process) {
- FrameCounts counts = {0u, 0u, 0u, 0u, 0u};
-
- const size_t avx_alignment_offset =
- GetAVXAlignmentOffsetInNumberOfFloats(source_p);
-
- // If the first frame is not AVX aligned, the first several frames (at most
- // seven) must be processed separately for proper alignment.
- const size_t total_for_alignment =
- (AVX::kPackedFloatsPerRegister - avx_alignment_offset) &
- ~AVX::kFramesToProcessMask;
- const size_t scalar_for_alignment =
- total_for_alignment & ~SSE::kFramesToProcessMask;
- const size_t sse_for_alignment =
- total_for_alignment & SSE::kFramesToProcessMask;
-
- // Check which CPU features can be used based on the number of frames to
- // process and based on CPU support.
- const bool use_at_least_avx =
- CPUSupportsAVX() &&
- frames_to_process >= scalar_for_alignment + sse_for_alignment +
- AVX::kPackedFloatsPerRegister;
- const bool use_at_least_sse =
- use_at_least_avx ||
- frames_to_process >= scalar_for_alignment + SSE::kPackedFloatsPerRegister;
-
- if (use_at_least_sse) {
- counts.scalar_for_alignment = scalar_for_alignment;
- frames_to_process -= counts.scalar_for_alignment;
- // The remaining frames are SSE aligned.
- DCHECK(SSE::IsAligned(source_p + counts.scalar_for_alignment));
-
- if (use_at_least_avx) {
- counts.sse_for_alignment = sse_for_alignment;
- frames_to_process -= counts.sse_for_alignment;
- // The remaining frames are AVX aligned.
- DCHECK(AVX::IsAligned(source_p + counts.scalar_for_alignment +
- counts.sse_for_alignment));
-
- // Process as many as possible of the remaining frames using AVX.
- counts.avx = frames_to_process & AVX::kFramesToProcessMask;
- frames_to_process -= counts.avx;
- }
-
- // Process as many as possible of the remaining frames using SSE.
- counts.sse = frames_to_process & SSE::kFramesToProcessMask;
- frames_to_process -= counts.sse;
- }
-
- // Process the remaining frames separately.
- counts.scalar = frames_to_process;
- return counts;
-}
-
-static ALWAYS_INLINE void PrepareFilterForConv(
- const float* filter_p,
- int filter_stride,
- size_t filter_size,
- AudioFloatArray* prepared_filter) {
- if (CPUSupportsAVX()) {
- AVX::PrepareFilterForConv(filter_p, filter_stride, filter_size,
- prepared_filter);
- } else {
- SSE::PrepareFilterForConv(filter_p, filter_stride, filter_size,
- prepared_filter);
- }
-}
-
-static ALWAYS_INLINE void Conv(const float* source_p,
- int source_stride,
- const float* filter_p,
- int filter_stride,
- float* dest_p,
- int dest_stride,
- size_t frames_to_process,
- size_t filter_size,
- const AudioFloatArray* prepared_filter) {
- const float* prepared_filter_p =
- prepared_filter ? prepared_filter->Data() : nullptr;
- if (source_stride == 1 && dest_stride == 1 && prepared_filter_p) {
- if (CPUSupportsAVX() && (filter_size & ~AVX::kFramesToProcessMask) == 0u) {
- // |frames_to_process| is always a multiply of render quantum and
- // therefore the frames can always be processed using AVX.
- CHECK_EQ(frames_to_process & ~AVX::kFramesToProcessMask, 0u);
- AVX::Conv(source_p, prepared_filter_p, dest_p, frames_to_process,
- filter_size);
- return;
- }
- if ((filter_size & ~SSE::kFramesToProcessMask) == 0u) {
- // |frames_to_process| is always a multiply of render quantum and
- // therefore the frames can always be processed using SSE.
- CHECK_EQ(frames_to_process & ~SSE::kFramesToProcessMask, 0u);
- SSE::Conv(source_p, prepared_filter_p, dest_p, frames_to_process,
- filter_size);
- return;
- }
- }
- Scalar::Conv(source_p, source_stride, filter_p, filter_stride, dest_p,
- dest_stride, frames_to_process, filter_size, nullptr);
-}
-
-static ALWAYS_INLINE void Vadd(const float* source1p,
- int source_stride1,
- const float* source2p,
- int source_stride2,
- float* dest_p,
- int dest_stride,
- size_t frames_to_process) {
- if (source_stride1 == 1 && source_stride2 == 1 && dest_stride == 1) {
- const FrameCounts frame_counts =
- SplitFramesToProcess(source1p, frames_to_process);
-
- Scalar::Vadd(source1p, 1, source2p, 1, dest_p, 1,
- frame_counts.scalar_for_alignment);
- size_t i = frame_counts.scalar_for_alignment;
- if (frame_counts.sse_for_alignment > 0u) {
- SSE::Vadd(source1p + i, source2p + i, dest_p + i,
- frame_counts.sse_for_alignment);
- i += frame_counts.sse_for_alignment;
- }
- if (frame_counts.avx > 0u) {
- AVX::Vadd(source1p + i, source2p + i, dest_p + i, frame_counts.avx);
- i += frame_counts.avx;
- }
- if (frame_counts.sse > 0u) {
- SSE::Vadd(source1p + i, source2p + i, dest_p + i, frame_counts.sse);
- i += frame_counts.sse;
- }
- Scalar::Vadd(source1p + i, 1, source2p + i, 1, dest_p + i, 1,
- frame_counts.scalar);
- DCHECK_EQ(frames_to_process, i + frame_counts.scalar);
- } else {
- Scalar::Vadd(source1p, source_stride1, source2p, source_stride2, dest_p,
- dest_stride, frames_to_process);
- }
-}
-
-static ALWAYS_INLINE void Vclip(const float* source_p,
- int source_stride,
- const float* low_threshold_p,
- const float* high_threshold_p,
- float* dest_p,
- int dest_stride,
- size_t frames_to_process) {
- if (source_stride == 1 && dest_stride == 1) {
- const FrameCounts frame_counts =
- SplitFramesToProcess(source_p, frames_to_process);
-
- Scalar::Vclip(source_p, 1, low_threshold_p, high_threshold_p, dest_p, 1,
- frame_counts.scalar_for_alignment);
- size_t i = frame_counts.scalar_for_alignment;
- if (frame_counts.sse_for_alignment > 0u) {
- SSE::Vclip(source_p + i, low_threshold_p, high_threshold_p, dest_p + i,
- frame_counts.sse_for_alignment);
- i += frame_counts.sse_for_alignment;
- }
- if (frame_counts.avx > 0u) {
- AVX::Vclip(source_p + i, low_threshold_p, high_threshold_p, dest_p + i,
- frame_counts.avx);
- i += frame_counts.avx;
- }
- if (frame_counts.sse > 0u) {
- SSE::Vclip(source_p + i, low_threshold_p, high_threshold_p, dest_p + i,
- frame_counts.sse);
- i += frame_counts.sse;
- }
- Scalar::Vclip(source_p + i, 1, low_threshold_p, high_threshold_p,
- dest_p + i, 1, frame_counts.scalar);
- DCHECK_EQ(frames_to_process, i + frame_counts.scalar);
- } else {
- Scalar::Vclip(source_p, source_stride, low_threshold_p, high_threshold_p,
- dest_p, dest_stride, frames_to_process);
- }
-}
-
-static ALWAYS_INLINE void Vmaxmgv(const float* source_p,
- int source_stride,
- float* max_p,
- size_t frames_to_process) {
- if (source_stride == 1) {
- const FrameCounts frame_counts =
- SplitFramesToProcess(source_p, frames_to_process);
-
- Scalar::Vmaxmgv(source_p, 1, max_p, frame_counts.scalar_for_alignment);
- size_t i = frame_counts.scalar_for_alignment;
- if (frame_counts.sse_for_alignment > 0u) {
- SSE::Vmaxmgv(source_p + i, max_p, frame_counts.sse_for_alignment);
- i += frame_counts.sse_for_alignment;
- }
- if (frame_counts.avx > 0u) {
- AVX::Vmaxmgv(source_p + i, max_p, frame_counts.avx);
- i += frame_counts.avx;
- }
- if (frame_counts.sse > 0u) {
- SSE::Vmaxmgv(source_p + i, max_p, frame_counts.sse);
- i += frame_counts.sse;
- }
- Scalar::Vmaxmgv(source_p + i, 1, max_p, frame_counts.scalar);
- DCHECK_EQ(frames_to_process, i + frame_counts.scalar);
- } else {
- Scalar::Vmaxmgv(source_p, source_stride, max_p, frames_to_process);
- }
-}
-
-static ALWAYS_INLINE void Vmul(const float* source1p,
- int source_stride1,
- const float* source2p,
- int source_stride2,
- float* dest_p,
- int dest_stride,
- size_t frames_to_process) {
- if (source_stride1 == 1 && source_stride2 == 1 && dest_stride == 1) {
- const FrameCounts frame_counts =
- SplitFramesToProcess(source1p, frames_to_process);
-
- Scalar::Vmul(source1p, 1, source2p, 1, dest_p, 1,
- frame_counts.scalar_for_alignment);
- size_t i = frame_counts.scalar_for_alignment;
- if (frame_counts.sse_for_alignment > 0u) {
- SSE::Vmul(source1p + i, source2p + i, dest_p + i,
- frame_counts.sse_for_alignment);
- i += frame_counts.sse_for_alignment;
- }
- if (frame_counts.avx > 0u) {
- AVX::Vmul(source1p + i, source2p + i, dest_p + i, frame_counts.avx);
- i += frame_counts.avx;
- }
- if (frame_counts.sse > 0u) {
- SSE::Vmul(source1p + i, source2p + i, dest_p + i, frame_counts.sse);
- i += frame_counts.sse;
- }
- Scalar::Vmul(source1p + i, 1, source2p + i, 1, dest_p + i, 1,
- frame_counts.scalar);
- DCHECK_EQ(frames_to_process, i + frame_counts.scalar);
- } else {
- Scalar::Vmul(source1p, source_stride1, source2p, source_stride2, dest_p,
- dest_stride, frames_to_process);
- }
-}
-
-static ALWAYS_INLINE void Vsma(const float* source_p,
- int source_stride,
- const float* scale,
- float* dest_p,
- int dest_stride,
- size_t frames_to_process) {
- if (source_stride == 1 && dest_stride == 1) {
- const FrameCounts frame_counts =
- SplitFramesToProcess(source_p, frames_to_process);
-
- Scalar::Vsma(source_p, 1, scale, dest_p, 1,
- frame_counts.scalar_for_alignment);
- size_t i = frame_counts.scalar_for_alignment;
- if (frame_counts.sse_for_alignment > 0u) {
- SSE::Vsma(source_p + i, scale, dest_p + i,
- frame_counts.sse_for_alignment);
- i += frame_counts.sse_for_alignment;
- }
- if (frame_counts.avx > 0u) {
- AVX::Vsma(source_p + i, scale, dest_p + i, frame_counts.avx);
- i += frame_counts.avx;
- }
- if (frame_counts.sse > 0u) {
- SSE::Vsma(source_p + i, scale, dest_p + i, frame_counts.sse);
- i += frame_counts.sse;
- }
- Scalar::Vsma(source_p + i, 1, scale, dest_p + i, 1, frame_counts.scalar);
- DCHECK_EQ(frames_to_process, i + frame_counts.scalar);
- } else {
- Scalar::Vsma(source_p, source_stride, scale, dest_p, dest_stride,
- frames_to_process);
- }
-}
-
-static ALWAYS_INLINE void Vsmul(const float* source_p,
- int source_stride,
- const float* scale,
- float* dest_p,
- int dest_stride,
- size_t frames_to_process) {
- if (source_stride == 1 && dest_stride == 1) {
- const FrameCounts frame_counts =
- SplitFramesToProcess(source_p, frames_to_process);
-
- Scalar::Vsmul(source_p, 1, scale, dest_p, 1,
- frame_counts.scalar_for_alignment);
- size_t i = frame_counts.scalar_for_alignment;
- if (frame_counts.sse_for_alignment > 0u) {
- SSE::Vsmul(source_p + i, scale, dest_p + i,
- frame_counts.sse_for_alignment);
- i += frame_counts.sse_for_alignment;
- }
- if (frame_counts.avx > 0u) {
- AVX::Vsmul(source_p + i, scale, dest_p + i, frame_counts.avx);
- i += frame_counts.avx;
- }
- if (frame_counts.sse > 0u) {
- SSE::Vsmul(source_p + i, scale, dest_p + i, frame_counts.sse);
- i += frame_counts.sse;
- }
- Scalar::Vsmul(source_p + i, 1, scale, dest_p + i, 1, frame_counts.scalar);
- DCHECK_EQ(frames_to_process, i + frame_counts.scalar);
- } else {
- Scalar::Vsmul(source_p, source_stride, scale, dest_p, dest_stride,
- frames_to_process);
- }
-}
-
-static ALWAYS_INLINE void Vsvesq(const float* source_p,
- int source_stride,
- float* sum_p,
- size_t frames_to_process) {
- if (source_stride == 1) {
- const FrameCounts frame_counts =
- SplitFramesToProcess(source_p, frames_to_process);
-
- Scalar::Vsvesq(source_p, 1, sum_p, frame_counts.scalar_for_alignment);
- size_t i = frame_counts.scalar_for_alignment;
- if (frame_counts.sse_for_alignment > 0u) {
- SSE::Vsvesq(source_p + i, sum_p, frame_counts.sse_for_alignment);
- i += frame_counts.sse_for_alignment;
- }
- if (frame_counts.avx > 0u) {
- AVX::Vsvesq(source_p + i, sum_p, frame_counts.avx);
- i += frame_counts.avx;
- }
- if (frame_counts.sse > 0u) {
- SSE::Vsvesq(source_p + i, sum_p, frame_counts.sse);
- i += frame_counts.sse;
- }
- Scalar::Vsvesq(source_p + i, 1, sum_p, frame_counts.scalar);
- DCHECK_EQ(frames_to_process, i + frame_counts.scalar);
- } else {
- Scalar::Vsvesq(source_p, source_stride, sum_p, frames_to_process);
- }
-}
-
-static ALWAYS_INLINE void Zvmul(const float* real1p,
- const float* imag1p,
- const float* real2p,
- const float* imag2p,
- float* real_dest_p,
- float* imag_dest_p,
- size_t frames_to_process) {
- FrameCounts frame_counts = SplitFramesToProcess(real1p, frames_to_process);
-
- Scalar::Zvmul(real1p, imag1p, real2p, imag2p, real_dest_p, imag_dest_p,
- frame_counts.scalar_for_alignment);
- size_t i = frame_counts.scalar_for_alignment;
- if (frame_counts.sse_for_alignment > 0u) {
- SSE::Zvmul(real1p + i, imag1p + i, real2p + i, imag2p + i, real_dest_p + i,
- imag_dest_p + i, frame_counts.sse_for_alignment);
- i += frame_counts.sse_for_alignment;
- }
- if (frame_counts.avx > 0u) {
- AVX::Zvmul(real1p + i, imag1p + i, real2p + i, imag2p + i, real_dest_p + i,
- imag_dest_p + i, frame_counts.avx);
- i += frame_counts.avx;
- }
- if (frame_counts.sse > 0u) {
- SSE::Zvmul(real1p + i, imag1p + i, real2p + i, imag2p + i, real_dest_p + i,
- imag_dest_p + i, frame_counts.sse);
- i += frame_counts.sse;
- }
- Scalar::Zvmul(real1p + i, imag1p + i, real2p + i, imag2p + i, real_dest_p + i,
- imag_dest_p + i, frame_counts.scalar);
- DCHECK_EQ(frames_to_process, i + frame_counts.scalar);
-}
-
-} // namespace X86
-} // namespace VectorMath
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_CPU_X86_VECTOR_MATH_X8_6_H_
diff --git a/chromium/third_party/blink/renderer/platform/audio/down_sampler.cc b/chromium/third_party/blink/renderer/platform/audio/down_sampler.cc
index 90415979257..ad5fb79d5eb 100644
--- a/chromium/third_party/blink/renderer/platform/audio/down_sampler.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/down_sampler.cc
@@ -60,14 +60,14 @@ std::unique_ptr<AudioFloatArray> MakeReducedKernel(size_t size) {
// processing after doing the main convolution using m_reducedKernel.
for (int i = 1; i < n; i += 2) {
// Compute the sinc() with offset.
- double s = sinc_scale_factor * piDouble * (i - half_size);
+ double s = sinc_scale_factor * kPiDouble * (i - half_size);
double sinc = !s ? 1.0 : sin(s) / s;
sinc *= sinc_scale_factor;
// Compute Blackman window, matching the offset of the sinc().
double x = static_cast<double>(i) / n;
double window =
- a0 - a1 * cos(twoPiDouble * x) + a2 * cos(twoPiDouble * 2.0 * x);
+ a0 - a1 * cos(kTwoPiDouble * x) + a2 * cos(kTwoPiDouble * 2.0 * x);
// Window the sinc() function.
// Then store only the odd terms in the kernel.
diff --git a/chromium/third_party/blink/renderer/platform/audio/down_sampler.h b/chromium/third_party/blink/renderer/platform/audio/down_sampler.h
index 21b5f127f8a..7f1f17429e8 100644
--- a/chromium/third_party/blink/renderer/platform/audio/down_sampler.h
+++ b/chromium/third_party/blink/renderer/platform/audio/down_sampler.h
@@ -32,7 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_DOWN_SAMPLER_H_
#include "third_party/blink/renderer/platform/audio/audio_array.h"
-#include "third_party/blink/renderer/platform/audio/direct_convolver.h"
+#include "third_party/blink/renderer/platform/audio/simple_fft_convolver.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
@@ -62,8 +62,8 @@ class PLATFORM_EXPORT DownSampler {
size_t input_block_size_;
- // Half-band filter.
- DirectConvolver convolver_;
+ // Half-band filter. SimpleFFTConvolver is always faster than DirectConvolver.
+ SimpleFFTConvolver convolver_;
AudioFloatArray temp_buffer_;
diff --git a/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.cc b/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.cc
index 94ad47bd512..34a85f0e77e 100644
--- a/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/dynamics_compressor_kernel.cc
@@ -297,7 +297,7 @@ void DynamicsCompressorKernel::Process(
float desired_gain = detector_average_;
// Pre-warp so we get desiredGain after sin() warp below.
- float scaled_desired_gain = asinf(desired_gain) / (piOverTwoFloat);
+ float scaled_desired_gain = asinf(desired_gain) / kPiOverTwoFloat;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Deal with envelopes
@@ -440,7 +440,7 @@ void DynamicsCompressorKernel::Process(
// Warp pre-compression gain to smooth out sharp exponential transition
// points.
float post_warp_compressor_gain =
- sinf(piOverTwoFloat * compressor_gain);
+ sinf(kPiOverTwoFloat * compressor_gain);
// Calculate total gain using master gain and effect blend.
float total_gain =
diff --git a/chromium/third_party/blink/renderer/platform/audio/equal_power_panner.cc b/chromium/third_party/blink/renderer/platform/audio/equal_power_panner.cc
index c6a80d72e91..a87f17b0021 100644
--- a/chromium/third_party/blink/renderer/platform/audio/equal_power_panner.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/equal_power_panner.cc
@@ -101,8 +101,8 @@ void EqualPowerPanner::Pan(double azimuth,
}
}
- desired_gain_l = std::cos(piOverTwoDouble * desired_pan_position);
- desired_gain_r = std::sin(piOverTwoDouble * desired_pan_position);
+ desired_gain_l = std::cos(kPiOverTwoDouble * desired_pan_position);
+ desired_gain_r = std::sin(kPiOverTwoDouble * desired_pan_position);
int n = frames_to_process;
@@ -170,8 +170,8 @@ void EqualPowerPanner::CalculateDesiredGain(double& desired_gain_l,
}
}
- desired_gain_l = std::cos(piOverTwoDouble * desired_pan_position);
- desired_gain_r = std::sin(piOverTwoDouble * desired_pan_position);
+ desired_gain_l = std::cos(kPiOverTwoDouble * desired_pan_position);
+ desired_gain_r = std::sin(kPiOverTwoDouble * desired_pan_position);
}
void EqualPowerPanner::PanWithSampleAccurateValues(
diff --git a/chromium/third_party/blink/renderer/platform/audio/fft_frame.cc b/chromium/third_party/blink/renderer/platform/audio/fft_frame.cc
index bde6baf4aa4..55c658a54ff 100644
--- a/chromium/third_party/blink/renderer/platform/audio/fft_frame.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/fft_frame.cc
@@ -139,32 +139,35 @@ void FFTFrame::InterpolateFrequencyComponents(const FFTFrame& frame1,
last_phase2 = phase2;
// Unwrap phase deltas
- if (delta_phase1 > piDouble)
- delta_phase1 -= twoPiDouble;
- if (delta_phase1 < -piDouble)
- delta_phase1 += twoPiDouble;
- if (delta_phase2 > piDouble)
- delta_phase2 -= twoPiDouble;
- if (delta_phase2 < -piDouble)
- delta_phase2 += twoPiDouble;
+ if (delta_phase1 > kPiDouble)
+ delta_phase1 -= kTwoPiDouble;
+ if (delta_phase1 < -kPiDouble)
+ delta_phase1 += kTwoPiDouble;
+ if (delta_phase2 > kPiDouble)
+ delta_phase2 -= kTwoPiDouble;
+ if (delta_phase2 < -kPiDouble)
+ delta_phase2 += kTwoPiDouble;
// Blend group-delays
double delta_phase_blend;
- if (delta_phase1 - delta_phase2 > piDouble)
- delta_phase_blend = s1 * delta_phase1 + s2 * (twoPiDouble + delta_phase2);
- else if (delta_phase2 - delta_phase1 > piDouble)
- delta_phase_blend = s1 * (twoPiDouble + delta_phase1) + s2 * delta_phase2;
- else
+ if (delta_phase1 - delta_phase2 > kPiDouble) {
+ delta_phase_blend =
+ s1 * delta_phase1 + s2 * (kTwoPiDouble + delta_phase2);
+ } else if (delta_phase2 - delta_phase1 > kPiDouble) {
+ delta_phase_blend =
+ s1 * (kTwoPiDouble + delta_phase1) + s2 * delta_phase2;
+ } else {
delta_phase_blend = s1 * delta_phase1 + s2 * delta_phase2;
+ }
phase_accum += delta_phase_blend;
// Unwrap
- if (phase_accum > piDouble)
- phase_accum -= twoPiDouble;
- if (phase_accum < -piDouble)
- phase_accum += twoPiDouble;
+ if (phase_accum > kPiDouble)
+ phase_accum -= kTwoPiDouble;
+ if (phase_accum < -kPiDouble)
+ phase_accum += kTwoPiDouble;
std::complex<double> c = std::polar(mag, phase_accum);
@@ -184,7 +187,7 @@ double FFTFrame::ExtractAverageGroupDelay() {
int half_size = FftSize() / 2;
const double sample_phase_delay =
- (twoPiDouble) / static_cast<double>(FftSize());
+ kTwoPiDouble / static_cast<double>(FftSize());
// Calculate weighted average group delay
for (int i = 0; i < half_size; i++) {
@@ -196,10 +199,10 @@ double FFTFrame::ExtractAverageGroupDelay() {
last_phase = phase;
// Unwrap
- if (delta_phase < -piDouble)
- delta_phase += twoPiDouble;
- if (delta_phase > piDouble)
- delta_phase -= twoPiDouble;
+ if (delta_phase < -kPiDouble)
+ delta_phase += kTwoPiDouble;
+ if (delta_phase > kPiDouble)
+ delta_phase -= kTwoPiDouble;
ave_sum += mag * delta_phase;
weight_sum += mag;
@@ -230,7 +233,7 @@ void FFTFrame::AddConstantGroupDelay(double sample_frame_delay) {
float* imag_p = ImagData();
const double sample_phase_delay =
- (twoPiDouble) / static_cast<double>(FftSize());
+ kTwoPiDouble / static_cast<double>(FftSize());
double phase_adj = -sample_frame_delay * sample_phase_delay;
diff --git a/chromium/third_party/blink/renderer/platform/audio/iir_filter.cc b/chromium/third_party/blink/renderer/platform/audio/iir_filter.cc
index 6ce33eb6cb9..b9e435eeea2 100644
--- a/chromium/third_party/blink/renderer/platform/audio/iir_filter.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/iir_filter.cc
@@ -135,7 +135,7 @@ void IIRFilter::GetFrequencyResponse(int n_frequencies,
phase_response[k] = std::nanf("");
} else {
// zRecip = 1/z = exp(-j*frequency)
- double omega = -piDouble * frequency[k];
+ double omega = -kPiDouble * frequency[k];
std::complex<double> z_recip =
std::complex<double>(cos(omega), sin(omega));
diff --git a/chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.cc b/chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.cc
new file mode 100644
index 00000000000..eefe344a9b7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.cc
@@ -0,0 +1,61 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/audio/simple_fft_convolver.h"
+#include "third_party/blink/renderer/platform/audio/vector_math.h"
+
+namespace blink {
+
+SimpleFFTConvolver::SimpleFFTConvolver(
+ size_t input_block_size,
+ const std::unique_ptr<AudioFloatArray>& convolution_kernel)
+ : convolution_kernel_size_(convolution_kernel->size()),
+ fft_kernel_(2 * input_block_size),
+ frame_(2 * input_block_size),
+ input_buffer_(2 *
+ input_block_size), // 2nd half of buffer is always zeroed
+ output_buffer_(2 * input_block_size),
+ last_overlap_buffer_(input_block_size) {
+ DCHECK_LE(convolution_kernel_size_, FftSize() / 2);
+ // Do padded FFT to get frequency-domain version of the convolution kernel.
+ // This FFT and caching is done once in here so that it does not have to be
+ // done repeatedly in |Process|.
+ fft_kernel_.DoPaddedFFT(convolution_kernel->Data(), convolution_kernel_size_);
+}
+
+void SimpleFFTConvolver::Process(const float* source_p,
+ float* dest_p,
+ size_t frames_to_process) {
+ size_t half_size = FftSize() / 2;
+
+ // frames_to_process must be exactly half_size.
+ DCHECK(source_p);
+ DCHECK(dest_p);
+ DCHECK_EQ(frames_to_process, half_size);
+ if (!(source_p && dest_p && frames_to_process == half_size))
+ return;
+
+ // Do padded FFT (get frequency-domain version) by copying samples to the 1st
+ // half of the input buffer (the second half is always zero), multiply in
+ // frequency-domain and do inverse FFT to get output samples.
+ input_buffer_.CopyToRange(source_p, 0, half_size);
+ frame_.DoFFT(input_buffer_.Data());
+ frame_.Multiply(fft_kernel_);
+ frame_.DoInverseFFT(output_buffer_.Data());
+
+ // Overlap-add 1st half with 2nd half from previous time and write
+ // to destination.
+ VectorMath::Vadd(output_buffer_.Data(), 1, last_overlap_buffer_.Data(), 1,
+ dest_p, 1, half_size);
+
+ // Finally, save 2nd half for the next time.
+ last_overlap_buffer_.CopyToRange(output_buffer_.Data() + half_size, 0,
+ half_size);
+}
+
+void SimpleFFTConvolver::Reset() {
+ last_overlap_buffer_.Zero();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.h b/chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.h
new file mode 100644
index 00000000000..571ac9e0f5e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/audio/simple_fft_convolver.h
@@ -0,0 +1,58 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_SIMPLE_FFT_CONVOLVER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_SIMPLE_FFT_CONVOLVER_H_
+
+#include <memory>
+
+#include "third_party/blink/renderer/platform/audio/audio_array.h"
+#include "third_party/blink/renderer/platform/audio/fft_frame.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
+
+namespace blink {
+
+// The SimpleFFTConvolver does an FFT convolution. It differs from
+// the FFTConvolver in that it restricts the maximum size of
+// |convolution_kernel| to |input_block_size|. This restriction allows it to do
+// an FFT on every Process call. Therefore, the processing delay of
+// the SimpleFFTConvolver is the same as that of the DirectConvolver and thus
+// smaller than that of the FFTConvolver.
+class PLATFORM_EXPORT SimpleFFTConvolver {
+ USING_FAST_MALLOC(SimpleFFTConvolver);
+ WTF_MAKE_NONCOPYABLE(SimpleFFTConvolver);
+
+ public:
+ SimpleFFTConvolver(
+ size_t input_block_size,
+ const std::unique_ptr<AudioFloatArray>& convolution_kernel);
+
+ void Process(const float* source_p, float* dest_p, size_t frames_to_process);
+
+ void Reset();
+
+ size_t ConvolutionKernelSize() const { return convolution_kernel_size_; }
+
+ private:
+ size_t FftSize() const { return frame_.FftSize(); }
+
+ size_t convolution_kernel_size_;
+ FFTFrame fft_kernel_;
+ FFTFrame frame_;
+
+ // Buffer input until we get fftSize / 2 samples then do an FFT
+ AudioFloatArray input_buffer_;
+
+ // Stores output which we read a little at a time
+ AudioFloatArray output_buffer_;
+
+ // Saves the 2nd half of the FFT buffer, so we can do an overlap-add with the
+ // 1st half of the next one
+ AudioFloatArray last_overlap_buffer_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_SIMPLE_FFT_CONVOLVER_H_
diff --git a/chromium/third_party/blink/renderer/platform/audio/sinc_resampler.cc b/chromium/third_party/blink/renderer/platform/audio/sinc_resampler.cc
index 79a1681ef2e..c949fa60bce 100644
--- a/chromium/third_party/blink/renderer/platform/audio/sinc_resampler.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/sinc_resampler.cc
@@ -117,14 +117,14 @@ void SincResampler::InitializeKernel() {
for (int i = 0; i < n; ++i) {
// Compute the sinc() with offset.
double s =
- sinc_scale_factor * piDouble * (i - half_size - subsample_offset);
+ sinc_scale_factor * kPiDouble * (i - half_size - subsample_offset);
double sinc = !s ? 1.0 : std::sin(s) / s;
sinc *= sinc_scale_factor;
// Compute Blackman window, matching the offset of the sinc().
double x = (i - subsample_offset) / n;
- double window = a0 - a1 * std::cos(twoPiDouble * x) +
- a2 * std::cos(twoPiDouble * 2.0 * x);
+ double window = a0 - a1 * std::cos(kTwoPiDouble * x) +
+ a2 * std::cos(kTwoPiDouble * 2.0 * x);
// Window the sinc() function and store at the correct offset.
kernel_storage_[i + offset_index * kernel_size_] = sinc * window;
diff --git a/chromium/third_party/blink/renderer/platform/audio/stereo_panner.cc b/chromium/third_party/blink/renderer/platform/audio/stereo_panner.cc
index 6c911eba328..d375cd24adb 100644
--- a/chromium/third_party/blink/renderer/platform/audio/stereo_panner.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/stereo_panner.cc
@@ -63,7 +63,7 @@ void StereoPanner::PanWithSampleAccurateValues(const AudioBus* input_bus,
float input_l = *source_l++;
double pan = clampTo(*pan_values++, -1.0, 1.0);
// Pan from left to right [-1; 1] will be normalized as [0; 1].
- pan_radian = (pan * 0.5 + 0.5) * piOverTwoDouble;
+ pan_radian = (pan * 0.5 + 0.5) * kPiOverTwoDouble;
gain_l = std::cos(pan_radian);
gain_r = std::sin(pan_radian);
*destination_l++ = static_cast<float>(input_l * gain_l);
@@ -75,7 +75,7 @@ void StereoPanner::PanWithSampleAccurateValues(const AudioBus* input_bus,
float input_r = *source_r++;
double pan = clampTo(*pan_values++, -1.0, 1.0);
// Normalize [-1; 0] to [0; 1]. Do nothing when [0; 1].
- pan_radian = (pan <= 0 ? pan + 1 : pan) * piOverTwoDouble;
+ pan_radian = (pan <= 0 ? pan + 1 : pan) * kPiOverTwoDouble;
gain_l = std::cos(pan_radian);
gain_r = std::sin(pan_radian);
if (pan <= 0) {
@@ -126,7 +126,7 @@ void StereoPanner::PanToTargetValue(const AudioBus* input_bus,
if (number_of_input_channels == 1) { // For mono source case.
// Pan from left to right [-1; 1] will be normalized as [0; 1].
- double pan_radian = (target_pan * 0.5 + 0.5) * piOverTwoDouble;
+ double pan_radian = (target_pan * 0.5 + 0.5) * kPiOverTwoDouble;
double gain_l = std::cos(pan_radian);
double gain_r = std::sin(pan_radian);
@@ -141,7 +141,7 @@ void StereoPanner::PanToTargetValue(const AudioBus* input_bus,
// Normalize [-1; 0] to [0; 1] for the left pan position (<= 0), and
// do nothing when [0; 1].
double pan_radian =
- (target_pan <= 0 ? target_pan + 1 : target_pan) * piOverTwoDouble;
+ (target_pan <= 0 ? target_pan + 1 : target_pan) * kPiOverTwoDouble;
double gain_l = std::cos(pan_radian);
double gain_r = std::sin(pan_radian);
diff --git a/chromium/third_party/blink/renderer/platform/audio/up_sampler.cc b/chromium/third_party/blink/renderer/platform/audio/up_sampler.cc
index 62eae93248d..99bdf05257d 100644
--- a/chromium/third_party/blink/renderer/platform/audio/up_sampler.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/up_sampler.cc
@@ -57,13 +57,13 @@ std::unique_ptr<AudioFloatArray> MakeKernel(size_t size) {
for (int i = 0; i < n; ++i) {
// Compute the sinc() with offset.
- double s = piDouble * (i - half_size - subsample_offset);
+ double s = kPiDouble * (i - half_size - subsample_offset);
double sinc = !s ? 1.0 : sin(s) / s;
// Compute Blackman window, matching the offset of the sinc().
double x = (i - subsample_offset) / n;
double window =
- a0 - a1 * cos(twoPiDouble * x) + a2 * cos(twoPiDouble * 2.0 * x);
+ a0 - a1 * cos(kTwoPiDouble * x) + a2 * cos(kTwoPiDouble * 2.0 * x);
// Window the sinc() function.
(*kernel)[i] = sinc * window;
@@ -76,13 +76,30 @@ std::unique_ptr<AudioFloatArray> MakeKernel(size_t size) {
UpSampler::UpSampler(size_t input_block_size)
: input_block_size_(input_block_size),
- convolver_(input_block_size, MakeKernel(kDefaultKernelSize)),
temp_buffer_(input_block_size),
- input_buffer_(input_block_size * 2) {}
+ input_buffer_(input_block_size * 2) {
+ std::unique_ptr<AudioFloatArray> convolution_kernel =
+ MakeKernel(kDefaultKernelSize);
+ if (input_block_size_ <= 128) {
+ // If the input block size is small enough, use direct convolution because
+ // it is faster than FFT convolution for such input block sizes.
+ direct_convolver_ = std::make_unique<DirectConvolver>(
+ input_block_size_, std::move(convolution_kernel));
+ } else {
+ // Otherwise, use FFT convolution because it is faster than direct
+ // convolution for large input block sizes.
+ simple_fft_convolver_ = std::make_unique<SimpleFFTConvolver>(
+ input_block_size_, std::move(convolution_kernel));
+ }
+}
void UpSampler::Process(const float* source_p,
float* dest_p,
size_t source_frames_to_process) {
+ const size_t convolution_kernel_size =
+ direct_convolver_ ? direct_convolver_->ConvolutionKernelSize()
+ : simple_fft_convolver_->ConvolutionKernelSize();
+
bool is_input_block_size_good = source_frames_to_process == input_block_size_;
DCHECK(is_input_block_size_good);
if (!is_input_block_size_good)
@@ -93,13 +110,7 @@ void UpSampler::Process(const float* source_p,
if (!is_temp_buffer_good)
return;
- bool is_kernel_good =
- convolver_.ConvolutionKernelSize() == kDefaultKernelSize;
- DCHECK(is_kernel_good);
- if (!is_kernel_good)
- return;
-
- size_t half_size = convolver_.ConvolutionKernelSize() / 2;
+ size_t half_size = convolution_kernel_size / 2;
// Copy source samples to 2nd half of input buffer.
bool is_input_buffer_good =
@@ -119,7 +130,13 @@ void UpSampler::Process(const float* source_p,
// Compute odd sample-frames 1,3,5,7...
float* odd_samples_p = temp_buffer_.Data();
- convolver_.Process(source_p, odd_samples_p, source_frames_to_process);
+ if (direct_convolver_) {
+ direct_convolver_->Process(source_p, odd_samples_p,
+ source_frames_to_process);
+ } else {
+ simple_fft_convolver_->Process(source_p, odd_samples_p,
+ source_frames_to_process);
+ }
for (unsigned i = 0; i < source_frames_to_process; ++i)
dest_p[i * 2 + 1] = odd_samples_p[i];
@@ -130,14 +147,18 @@ void UpSampler::Process(const float* source_p,
}
void UpSampler::Reset() {
- convolver_.Reset();
+ direct_convolver_.reset();
+ simple_fft_convolver_.reset();
input_buffer_.Zero();
}
size_t UpSampler::LatencyFrames() const {
+ const size_t convolution_kernel_size =
+ direct_convolver_ ? direct_convolver_->ConvolutionKernelSize()
+ : simple_fft_convolver_->ConvolutionKernelSize();
// Divide by two since this is a linear phase kernel and the delay is at the
// center of the kernel.
- return convolver_.ConvolutionKernelSize() / 2;
+ return convolution_kernel_size / 2;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/audio/up_sampler.h b/chromium/third_party/blink/renderer/platform/audio/up_sampler.h
index 69000eeb843..e76a8d84ecc 100644
--- a/chromium/third_party/blink/renderer/platform/audio/up_sampler.h
+++ b/chromium/third_party/blink/renderer/platform/audio/up_sampler.h
@@ -31,8 +31,11 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_UP_SAMPLER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_UP_SAMPLER_H_
+#include <memory>
+
#include "third_party/blink/renderer/platform/audio/audio_array.h"
#include "third_party/blink/renderer/platform/audio/direct_convolver.h"
+#include "third_party/blink/renderer/platform/audio/simple_fft_convolver.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
@@ -63,7 +66,8 @@ class PLATFORM_EXPORT UpSampler {
size_t input_block_size_;
// Computes the odd sample-frames of the output.
- DirectConvolver convolver_;
+ std::unique_ptr<DirectConvolver> direct_convolver_;
+ std::unique_ptr<SimpleFFTConvolver> simple_fft_convolver_;
AudioFloatArray temp_buffer_;
diff --git a/chromium/third_party/blink/renderer/platform/audio/vector_math.cc b/chromium/third_party/blink/renderer/platform/audio/vector_math.cc
index 388fecddd00..af76fad0b2b 100644
--- a/chromium/third_party/blink/renderer/platform/audio/vector_math.cc
+++ b/chromium/third_party/blink/renderer/platform/audio/vector_math.cc
@@ -38,7 +38,7 @@
#elif HAVE_MIPS_MSA_INTRINSICS
#include "third_party/blink/renderer/platform/audio/cpu/mips/vector_math_msa.h"
#elif defined(ARCH_CPU_X86_FAMILY)
-#include "third_party/blink/renderer/platform/audio/cpu/x86/vector_math_x8_6.h"
+#include "third_party/blink/renderer/platform/audio/cpu/x86/vector_math_x86.h"
#else
#include "third_party/blink/renderer/platform/audio/vector_math_scalar.h"
#endif
diff --git a/chromium/third_party/blink/renderer/platform/bindings/README.md b/chromium/third_party/blink/renderer/platform/bindings/README.md
index e7d530b5126..dad15021965 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/README.md
+++ b/chromium/third_party/blink/renderer/platform/bindings/README.md
@@ -4,7 +4,7 @@ This directory contains classes and functionality used to implement the V8 bindi
Some of the things you can find here are:
-* Functionality to wrap Blink C++ objects with a JavaScript object and maintain wrappers in multiple worlds (see [ScriptWrappable](ScriptWrappable.h), [ActiveScriptWrappable](ActiveScriptWrappable.h))
+* Functionality to wrap Blink C++ objects with a JavaScript object and maintain wrappers in multiple worlds (see [ScriptWrappable](script_wrappable.h), [ActiveScriptWrappableBase](active_script_wrappable_base.h))
* Implementation of wrapper tracing (see [documentation](TraceWrapperReference.md))
-* Important abstractions for script execution (see [ScriptState](ScriptState.h), [V8PerIsolateData](V8PerIsolateData.h), [V8PerContextData](V8PerContextData.h))
-* Utility functions to interface with V8 and convert between V8 and Blink types (see [V8Binding.h](V8Binding.h), [ToV8.h](ToV8.h))
+* Important abstractions for script execution (see [ScriptState](script_state.h), [V8PerIsolateData](v8_per_isolate_data.h), [V8PerContextData](v8_per_context_data.h))
+* Utility functions to interface with V8 and convert between V8 and Blink types (see [v8_binding.h](v8_binding.h), [to_v8.h](to_v8.h))
diff --git a/chromium/third_party/blink/renderer/platform/bindings/TraceWrapperReference.md b/chromium/third_party/blink/renderer/platform/bindings/TraceWrapperReference.md
index 23adab6a7ab..d8b0b2c2aac 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/TraceWrapperReference.md
+++ b/chromium/third_party/blink/renderer/platform/bindings/TraceWrapperReference.md
@@ -1,52 +1,45 @@
# Wrapper Tracing Reference
This document describes wrapper tracing and how its API is supposed to be used.
+Note that wrapper tracing is based on Oilpan garbage collection infrastructure, which makes [Oilpan's documentation][oilpan-docs] a good first read.
[TOC]
## Quickstart guide
-Wrapper tracing is used to represent reachability across V8 and Blink. The
-following checklist highlights the modifications needed to make a class
-participate in wrapper tracing.
-
-1. Make sure that objects participating in tracing either inherit from
-`ScriptWrappable` (if they can reference wrappers) or `TraceWrapperBase`
-(transitively holding wrappers alive).
-2. Use `TraceWrapperMember<T>` to annotate fields that need to be followed to
-find other wrappers that this object should keep alive.
-3. Use `TraceWrapperV8Reference<T>` to annotate references to V8 that this
-object should keep alive.
-4. Declare a `virtual void TraceWrappers(ScriptWrappableVisitor*) const`
-method to trace other wrappers.
-5. Define the method and trace all fields that received a wrapper tracing type
-in (1) and (2) using `visitor->TraceWrappers(<field_>)` in the body.
+Wrapper tracing is used to represent reachability across V8 and Blink.
+The following checklist highlights the modifications needed to make a class participate in wrapper tracing.
+
+1. Make sure that objects participating in tracing either inherit from `ScriptWrappable` if they can reference wrappers or are otherwise part of Oilpan's heap, e.g. by making them inherit from `GarbageCollected` or one of its friends.
+2. Use `TraceWrapperMember<T>` to annotate fields that need to be followed to find other wrappers that this object should keep alive.
+3. Use `TraceWrapperV8Reference<T>` to annotate references to V8 that this object should keep alive.
+4. Make sure those fields are properly visited from `T::Trace`, similar to all other garbage collected types.
The following example illustrates these steps:
```c++
-#include "platform/bindings/ScriptWrappable.h"
-#include "platform/bindings/TraceWrapperMember.h"
-#include "platform/bindings/TraceWrapperV8Reference.h"
+#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
+#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
class SomeDOMObject : public ScriptWrappable { // (1)
DEFINE_WRAPPERTYPEINFO();
public:
- virtual void TraceWrappers(
- ScriptWrappableVisitor*) const; // (4)
+ void Trace(Visitor*) override;
private:
- TraceWrapperMember<OtherWrappable> other_wrappable_; // (2)
Member<NonWrappable> non_wrappable_;
+ TraceWrapperMember<OtherWrappable> other_wrappable_; // (2)
TraceWrapperV8Reference<v8::Value> v8object_; // (3)
// ...
};
-void SomeDOMObject::TraceWrappers(
- ScriptWrappableVisitor* visitor) const { // (5)
- visitor->TraceWrappers(other_wrappable_); // (5)
- visitor->TraceWrappers(v8object_); // (5)
+void SomeDOMObject::Trace(Visitor* visitor) {
+ visitor->Trace(non_wrappable_);
+ visitor->Trace(other_wrappable_); // (4)
+ visitor->Trace(v8object_); // (4)
+ ScriptWrappable::Trace(visitor);
}
```
@@ -54,26 +47,19 @@ For more in-depth information and how to deal with corner cases continue on read
## Background
-Blink and V8 need to cooperate to collect JavaScript *wrappers*. Each V8
-*wrapper* object (*W*) in JavaScript is assigned a C++ *DOM object* (*D*) in
-Blink. A single C++ *DOM object* can hold onto one or many *wrapper* objects.
-During a garbage collection initiated from JavaScript, a *wrapper* then keeps
-the C++ *DOM object* and all its transitive dependencies, including other
-*wrappers*, alive, effectively tracing paths like
-*W<sub>x</sub> -> D<sub>1</sub> -> ⋯ -> D<sub>n</sub> -> W<sub>y</sub>*.
+Blink and V8 need to cooperate to collect JavaScript *wrappers*.
+Each V8 *wrapper* object (*W*) in JavaScript is assigned a C++ *DOM object* (*D*) in Blink.
+A single C++ *DOM object* can hold onto one or many *wrapper* objects.
+During a garbage collection initiated from JavaScript, a *wrapper* then keeps the C++ *DOM object* and all its transitive dependencies, including other *wrappers*, alive, effectively tracing paths like *W<sub>x</sub> -> D<sub>1</sub> -> ⋯ -> D<sub>n</sub> -> W<sub>y</sub>*.
-Previously, this relationship was expressed using so-called object groups,
-effectively assigning all C++ *DOM objects* in a given DOM tree the same group.
-The group would only die if all objects belonging to the same group die. A brief
-introduction on the limitations on this approach can be found in
-[this slide deck][object-grouping-slides].
+Previously, this relationship was expressed using so-called object groups, effectively assigning all C++ *DOM objects* in a given DOM tree the same group.
+The group would only die if all objects belonging to the same group die.
+A brief introduction on the limitations on this approach can be found in [this slide deck][object-grouping-slides].
-Wrapper tracing solves this problem by determining liveness based on
-reachability by tracing through the C++ *DOM objects*. The rest of this document
-describes how the API is used to keep JavaScript wrapper objects alive.
+Wrapper tracing solves this problem by determining liveness based on reachability by tracing through the C++ *DOM objects*.
+The rest of this document describes how the API is used to keep JavaScript wrapper objects alive.
-Note that *wrappables* have to be *on-heap objects* and thus all
-[Oilpan-related rules][oilpan-docs] apply.
+Note that *wrappables* have to be part of Oilpan and thus all [Oilpan-related rules][oilpan-docs] apply.
[object-grouping-slides]: https://docs.google.com/presentation/d/1I6leiRm0ysSTqy7QWh33Gfp7_y4ngygyM2tDAqdF0fI/
[oilpan-docs]: https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/platform/heap/BlinkGCAPIReference.md
@@ -88,108 +74,99 @@ Pick the header file depending on what types are needed.
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
```
-The following example will guide through the modifications that are needed to
-adjust a given class `SomeDOMObject` to participate in wrapper tracing.
+The following example will guide through the modifications that are needed to adjust a given class `SomeDOMObject` to participate in wrapper tracing.
```c++
class SomeDOMObject : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
// ...
+
private:
Member<OtherWrappable /* extending ScriptWrappable */> other_wrappable_;
Member<NonWrappable> non_wrappable_;
};
```
-In this scenario `SomeDOMObject` is the object that is wrapped by an object on
-the JavaScript side. The next step is to identify the paths that lead to other
-wrappables. In this case, only `other_wrappable_` needs to be traced to find
-other *wrappers* in V8.
+In this scenario `SomeDOMObject` is the object that is wrapped by an object on the JavaScript side.
+The next step is to identify the paths that lead to other wrappables.
+In this case, only `other_wrappable_` needs to be traced to find other *wrappers* in V8.
```c++
class SomeDOMObject : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- virtual void TraceWrappers(ScriptWrappableVisitor*) const;
+ void Trace(Visitor*) override;
private:
Member<OtherWrappable> other_wrappable_;
Member<NonWrappable> non_wrappable_;
};
-void SomeDOMObject::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(other_wrappable_);
+void SomeDOMObject::Trace(Visitor* visitor) {
+ visitor->Trace(other_wrappable_);
+ visitor->Trace(non_wrappable_);
+ ScriptWrappable::Trace(visitor);
}
```
+Blink and V8 implement *incremental* wrapper tracing, which means that marking can be interleaved with JavaScript or even DOM operations.
+This poses a challenge, because already marked objects will not be considered again if they are reached through some other path.
-Blink and V8 implement *incremental* wrapper tracing, which means that marking
-can be interleaved with JavaScript or even DOM operations. This poses a
-challenge, because already marked objects will not be considered again if they
-are reached through some other path.
-
-For example, consider an object `A` that has already been marked and a write
-to a field `A.x` setting `x` to an unmarked object `Y`. Since `A.x` is
-the only reference keeping `Y`, and `A` has already been marked, the garbage
-collector will not find `Y` and reclaim it.
+For example, consider an object `A` that has already been marked and a write to a field `A.x` setting `x` to an unmarked object `Y`.
+Since `A.x` is the only reference keeping `Y`, and `A` has already been marked, the garbage collector will not find `Y` and reclaim it.
-To overcome this problem we require all writes of interesting objects, i.e.,
-writes to traced fields, to go through a write barrier.
-The write barrier will check for the problem case above and make sure
-`Y` will be marked. In order to automatically issue a write barrier
-`other_wrappable_` needs `TraceWrapperMember` type.
+To overcome this problem we require all writes of interesting objects, i.e., writes to traced fields, to go through a write barrier.
+The write barrier will check for the problem case above and make sure `Y` will be marked.
+In order to automatically issue a write barrier `other_wrappable_` needs `TraceWrapperMember` type.
```c++
class SomeDOMObject : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- virtual void TraceWrappers(ScriptWrappableVisitor*) const;
+ void Trace(Visitor*) override;
private:
TraceWrapperMember<OtherWrappable> other_wrappable_;
Member<NonWrappable> non_wrappable_;
};
-void SomeDOMObject::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(other_wrappable_);
+void SomeDOMObject::Trace(Visitor* visitor) {
+ visitor->Trace(other_wrappable_);
+ visitor->Trace(non_wrappable_);
+ ScriptWrappable::Trace(visitor);
}
```
-`TraceWrapperMember` makes sure that any write to `other_wrappable_` will
-consider doing a write barrier. Using the proper type, the write barrier is
-correct by construction, i.e., it will never be missed.
+`TraceWrapperMember` makes sure that any write to `other_wrappable_` will consider doing a write barrier.
+Using the proper type, the write barrier is correct by construction, i.e., it will never be missed.
## Heap collections
-The proper type usage for collections, e.g. `HeapVector` looks like the
-following.
+Wrapper tracing is integrated into Oilpan's support for collections, so there's no additional work needed other than making sure the collection is visited in the corresponding `Trace` method.
+The proper type usage for collections, e.g. `HeapVector` looks like the following.
```c++
class SomeDOMObject : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- // ...
+ void Trace(Visitor*) override;
+
void AppendNewValue(OtherWrappable* newValue);
- virtual void TraceWrappers(ScriptWrappableVisitor*) const;
private:
HeapVector<TraceWrapperMember<OtherWrappable>> other_wrappables_;
};
-void SomeDOMObject::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- for (auto other : other_wrappables_)
- visitor->TraceWrappers(other);
+void SomeDOMObject::Trace(Visitor* visitor) {
+ visitor->Trace(other_wrappables_);
+ ScriptWrappable::Trace(visitor);
}
```
-Note that this is different to Oilpan which can just trace the whole collection.
`TraceWrapperMember` can be constructed in place, so using `append` and
friends will work out of the box, e.g.
@@ -199,9 +176,6 @@ void SomeDOMObject::AppendNewValue(OtherWrappable* newValue) {
}
```
-The compiler will throw an error for each omitted `TraceWrapperMember`
-construction.
-
### Swapping `HeapVector` containing `TraceWrapperMember` and `Member`
It is possible to swap two `HeapVectors` containing `TraceWrapperMember` and
@@ -222,44 +196,34 @@ blink::swap(c, temporary);
## Tracing through non-`ScriptWrappable` types
-Sometimes it is necessary to trace through types that do not inherit from
-`ScriptWrappable`. For example, consider the object graph
-`A -> B -> C` where both `A` and `C` are `ScriptWrappable`s that
-need to be traced.
+Sometimes it is necessary to trace through types that do not inherit from `ScriptWrappable`.
+For example, consider the object graph `A -> B -> C` where both `A` and `C` are `ScriptWrappable`s that need to be traced.
-In this case, the same rules as with `ScriptWrappables` apply, except for the
-difference that these classes need to inherit from `TraceWrapperBase`.
-
-### Memory-footprint critical uses
-
-In the case we cannot afford inheriting from `TraceWrapperBase`, which will
-add a vtable pointer for tracing wrappers, use
-`DEFINE_TRAIT_FOR_TRACE_WRAPPERS(ClassName)` after defining
-`ClassName` to define the proper tracing specializations.
+In this case, the same rules as with `ScriptWrappables` apply, except for the difference that these classes need to inherit from some other class that is managed by Oilpan, e.g. `GarbageCollected`.
## Explicit write barriers
-Sometimes it is necessary to stick with the regular types and issue the write
-barriers explicitly. In this case, tracing needs to be adjusted to tell the
-system that all barriers will be done manually.
+Sometimes it is necessary to stick with the regular types or raw pointers and issue the write barriers explicitly.
+In this case, tracing needs to be adjusted to tell the system that all barriers will be done manually.
```c++
class ManualWrappable : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
- void setNew(OtherWrappable* newValue) {
+ void Trace(Visitor*) override;
+
+ void SetNew(OtherWrappable* newValue) {
other_wrappable_ = newValue;
SriptWrappableVisitor::WriteBarrier(other_wrappable_);
}
- virtual void TraceWrappers(ScriptWrappableVisitor*) const;
private:
Member<OtherWrappable>> other_wrappable_;
};
-void ManualWrappable::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappersWithManualWriteBarrier(other_wrappable_);
+void ManualWrappable::Trace(Visitor* visitor) {
+ visitor->TraceWithWrappers(other_wrappable_.Get());
+ ScriptWrappable::Trace(visitor);
}
```
diff --git a/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.cc b/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.cc
index 5fa35eb59b3..2ddaaa2285d 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.cc
@@ -41,12 +41,8 @@ void ActiveScriptWrappableBase::TraceActiveScriptWrappables(
continue;
ScriptWrappable* script_wrappable = active_wrappable->ToScriptWrappable();
// Notify the visitor about this script_wrappable by dispatching to the
- // corresponding visitor->Visit(script_wrappable) method.
- // Ideally, we would call visitor->TraceWrappers(script_wrappable) here,
- // but that method requires TraceWrapperMember<T>. Since we are getting
- // the script wrappable from ActiveScriptWrappables, we do not have
- // TraceWrapperMember<T> and have to use TraceWrappersFromGeneratedCode.
- visitor->TraceWrappersFromGeneratedCode(script_wrappable);
+ // corresponding Trace method.
+ visitor->TraceWithWrappers(script_wrappable);
}
}
diff --git a/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.cc b/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.cc
index 7add6d9ccad..3579f5886c1 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.cc
@@ -18,9 +18,10 @@ CallbackFunctionBase::CallbackFunctionBase(
incumbent_script_state_ = ScriptState::From(isolate->GetIncumbentContext());
}
-void CallbackFunctionBase::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(callback_function_);
+void CallbackFunctionBase::Trace(Visitor* visitor) {
+ visitor->Trace(callback_function_);
+ visitor->Trace(callback_relevant_script_state_);
+ visitor->Trace(incumbent_script_state_);
}
V8PersistentCallbackFunctionBase::V8PersistentCallbackFunctionBase(
diff --git a/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.h b/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.h
index 1bed7cd8e6c..b46b253fe11 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/callback_function_base.h
@@ -5,8 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_CALLBACK_FUNCTION_BASE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_CALLBACK_FUNCTION_BASE_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/bindings/trace_wrapper_base.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -25,21 +25,17 @@ class V8PersistentCallbackFunctionBase;
// implement it.
class PLATFORM_EXPORT CallbackFunctionBase
: public GarbageCollectedFinalized<CallbackFunctionBase>,
- public TraceWrapperBase {
+ public NameClient {
public:
virtual ~CallbackFunctionBase() = default;
- virtual void Trace(blink::Visitor* visitor) {}
- void TraceWrappers(ScriptWrappableVisitor*) const override;
- const char* NameInHeapSnapshot() const override {
- return "CallbackFunctionBase";
- }
+ virtual void Trace(blink::Visitor* visitor);
v8::Isolate* GetIsolate() const {
return callback_relevant_script_state_->GetIsolate();
}
ScriptState* CallbackRelevantScriptState() {
- return callback_relevant_script_state_.get();
+ return callback_relevant_script_state_;
}
protected:
@@ -48,17 +44,17 @@ class PLATFORM_EXPORT CallbackFunctionBase
v8::Local<v8::Function> CallbackFunction() const {
return callback_function_.NewLocal(GetIsolate());
}
- ScriptState* IncumbentScriptState() { return incumbent_script_state_.get(); }
+ ScriptState* IncumbentScriptState() { return incumbent_script_state_; }
private:
// The "callback function type" value.
TraceWrapperV8Reference<v8::Function> callback_function_;
// The associated Realm of the callback function type value.
- scoped_refptr<ScriptState> callback_relevant_script_state_;
+ Member<ScriptState> callback_relevant_script_state_;
// The callback context, i.e. the incumbent Realm when an ECMAScript value is
// converted to an IDL value.
// https://heycam.github.io/webidl/#dfn-callback-context
- scoped_refptr<ScriptState> incumbent_script_state_;
+ Member<ScriptState> incumbent_script_state_;
friend class V8PersistentCallbackFunctionBase;
};
diff --git a/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.cc b/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.cc
index 9fd0d8fcba2..f57bebd4c9a 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.cc
@@ -21,9 +21,10 @@ CallbackInterfaceBase::CallbackInterfaceBase(
incumbent_script_state_ = ScriptState::From(isolate->GetIncumbentContext());
}
-void CallbackInterfaceBase::TraceWrappers(
- ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(callback_object_);
+void CallbackInterfaceBase::Trace(Visitor* visitor) {
+ visitor->Trace(callback_object_);
+ visitor->Trace(callback_relevant_script_state_);
+ visitor->Trace(incumbent_script_state_);
}
V8PersistentCallbackInterfaceBase::V8PersistentCallbackInterfaceBase(
diff --git a/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.h b/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.h
index b3a5d239ce5..4f86ee390bf 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/callback_interface_base.h
@@ -5,8 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_CALLBACK_INTERFACE_BASE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_CALLBACK_INTERFACE_BASE_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/bindings/trace_wrapper_base.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -24,7 +24,7 @@ class V8PersistentCallbackInterfaceBase;
// not implement any operation. Subclasses will implement it.
class PLATFORM_EXPORT CallbackInterfaceBase
: public GarbageCollectedFinalized<CallbackInterfaceBase>,
- public TraceWrapperBase {
+ public NameClient {
public:
// Whether the callback interface is a "single operation callback interface"
// or not.
@@ -36,17 +36,13 @@ class PLATFORM_EXPORT CallbackInterfaceBase
virtual ~CallbackInterfaceBase() = default;
- virtual void Trace(blink::Visitor*) {}
- void TraceWrappers(ScriptWrappableVisitor*) const override;
- const char* NameInHeapSnapshot() const override {
- return "CallbackInterfaceBase";
- }
+ virtual void Trace(blink::Visitor*);
v8::Isolate* GetIsolate() {
return callback_relevant_script_state_->GetIsolate();
}
ScriptState* CallbackRelevantScriptState() {
- return callback_relevant_script_state_.get();
+ return callback_relevant_script_state_;
}
// NodeIteratorBase counts the invocation of those which are callable and
@@ -65,7 +61,7 @@ class PLATFORM_EXPORT CallbackInterfaceBase
// Returns true iff the callback interface is a single operation callback
// interface and the callback interface type value is callable.
bool IsCallbackObjectCallable() const { return is_callback_object_callable_; }
- ScriptState* IncumbentScriptState() { return incumbent_script_state_.get(); }
+ ScriptState* IncumbentScriptState() { return incumbent_script_state_; }
private:
// The "callback interface type" value.
@@ -74,11 +70,11 @@ class PLATFORM_EXPORT CallbackInterfaceBase
// The associated Realm of the callback interface type value. Note that the
// callback interface type value can be different from the function object
// to be invoked.
- scoped_refptr<ScriptState> callback_relevant_script_state_;
+ Member<ScriptState> callback_relevant_script_state_;
// The callback context, i.e. the incumbent Realm when an ECMAScript value is
// converted to an IDL value.
// https://heycam.github.io/webidl/#dfn-callback-context
- scoped_refptr<ScriptState> incumbent_script_state_;
+ Member<ScriptState> incumbent_script_state_;
friend class V8PersistentCallbackInterfaceBase;
// ToV8 needs to call |CallbackObject| member function.
diff --git a/chromium/third_party/blink/renderer/platform/bindings/dom_data_store.h b/chromium/third_party/blink/renderer/platform/bindings/dom_data_store.h
index c66d44d5e38..93285e63258 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/dom_data_store.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/dom_data_store.h
@@ -31,8 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_DOM_DATA_STORE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_DOM_DATA_STORE_H_
-#include <memory>
-
#include "base/optional.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_map.h"
#include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
@@ -147,11 +145,6 @@ class DOMDataStore {
visitor->Trace(&wrapper_map_.value(), script_wrappable);
}
- void TraceWrappers(const ScriptWrappable* script_wrappable,
- ScriptWrappableVisitor* visitor) {
- visitor->TraceWrappers(&wrapper_map_.value(), script_wrappable);
- }
-
void MarkWrapper(ScriptWrappable* script_wrappable) {
wrapper_map_->MarkWrapper(script_wrappable);
}
diff --git a/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_map.h b/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_map.h
index 6d532f09e45..443913d366b 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_map.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_map.h
@@ -33,8 +33,8 @@
#include <utility>
-#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/compiler.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "v8/include/v8-util.h"
diff --git a/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc b/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc
index 8f49afaeac3..52934680ed9 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.cc
@@ -35,6 +35,7 @@
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/hash_traits.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
@@ -126,17 +127,6 @@ void DOMWrapperWorld::Trace(const ScriptWrappable* script_wrappable,
}
}
-void DOMWrapperWorld::TraceWrappers(const ScriptWrappable* script_wrappable,
- ScriptWrappableVisitor* visitor) {
- // Marking for worlds other than the main world.
- DCHECK(ThreadState::Current()->GetIsolate());
- for (DOMWrapperWorld* world : GetWorldMap().Values()) {
- DOMDataStore& data_store = world->DomDataStore();
- if (data_store.ContainsWrapper(script_wrappable))
- data_store.TraceWrappers(script_wrappable, visitor);
- }
-}
-
DOMWrapperWorld::~DOMWrapperWorld() {
DCHECK(!IsMainWorld());
if (IsMainThread())
diff --git a/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h b/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h
index e6cef6de75d..d4b610dca5d 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/dom_wrapper_world.h
@@ -38,7 +38,7 @@
#include "third_party/blink/public/platform/web_isolated_world_ids.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
#include "v8/include/v8.h"
@@ -46,6 +46,8 @@ namespace blink {
class DOMDataStore;
class DOMObjectHolderBase;
+class ScriptWrappable;
+class SecurityOrigin;
// This class represent a collection of DOM wrappers for a specific world. This
// is identified by a world id that is a per-thread global identifier (see
@@ -97,7 +99,6 @@ class PLATFORM_EXPORT DOMWrapperWorld : public RefCounted<DOMWrapperWorld> {
// Traces wrappers corresponding to the ScriptWrappable in DOM data stores.
static void Trace(const ScriptWrappable*, Visitor*);
- static void TraceWrappers(const ScriptWrappable*, ScriptWrappableVisitor*);
static DOMWrapperWorld& World(v8::Local<v8::Context> context) {
return ScriptState::From(context)->World();
diff --git a/chromium/third_party/blink/renderer/platform/bindings/exception_code.h b/chromium/third_party/blink/renderer/platform/bindings/exception_code.h
new file mode 100644
index 00000000000..9436a269ee0
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/bindings/exception_code.h
@@ -0,0 +1,156 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_EXCEPTION_CODE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_EXCEPTION_CODE_H_
+
+namespace blink {
+
+// DOMException uses |unsigned short| for exception codes.
+// https://heycam.github.io/webidl/#idl-DOMException
+// In our DOM implementation we use |int| instead, and use different numerical
+// ranges for different types of exceptions (not limited to DOMException), so
+// that an exception of any type can be expressed with a single integer.
+//
+// Zero value in ExceptionCode means no exception being thrown.
+using ExceptionCode = int;
+
+// DOMException's error code
+// https://heycam.github.io/webidl/#idl-DOMException-error-names
+enum class DOMExceptionCode : ExceptionCode {
+ // DOMExceptions with the legacy error code.
+
+ // Zero value is used for representing no exception.
+ kNoError = 0,
+
+ // The minimum value of the legacy error code of DOMException defined in
+ // Web IDL.
+ // https://heycam.github.io/webidl/#idl-DOMException
+ kLegacyErrorCodeMin = 1,
+
+ kIndexSizeError = 1, // Deprecated. Use ECMAScript RangeError instead.
+ // DOMStringSizeError (= 2) is deprecated and no longer supported.
+ kHierarchyRequestError = 3,
+ kWrongDocumentError = 4,
+ kInvalidCharacterError = 5,
+ // NoDataAllowedError (= 6) is deprecated and no longer supported.
+ kNoModificationAllowedError = 7,
+ kNotFoundError = 8,
+ kNotSupportedError = 9,
+ kInUseAttributeError = 10, // Historical. Only used in setAttributeNode etc
+ // which have been removed from the DOM specs.
+ kInvalidStateError = 11,
+ // Web IDL 2.7.1 Error names
+ // https://heycam.github.io/webidl/#idl-DOMException-error-names
+ // Note: Don't confuse the "SyntaxError" DOMException defined here with
+ // ECMAScript's SyntaxError. "SyntaxError" DOMException is used to report
+ // parsing errors in web APIs, for example when parsing selectors, while
+ // the ECMAScript SyntaxError is reserved for the ECMAScript parser.
+ kSyntaxError = 12,
+ kInvalidModificationError = 13,
+ kNamespaceError = 14,
+ // kInvalidAccessError is deprecated. Use ECMAScript TypeError for invalid
+ // arguments, |kNotSupportedError| for unsupported operations, and
+ // |kNotAllowedError| for denied requests instead.
+ kInvalidAccessError = 15, // Deprecated.
+ // ValidationError (= 16) is deprecated and no longer supported.
+ kTypeMismatchError = 17, // Deprecated. Use ECMAScript TypeError instead.
+ // SecurityError should be thrown with ExceptionState::ThrowSecurityError
+ // with careful consideration about the message that is observable by web
+ // author. Avoid using this error code unless it's really SecurityError.
+ //
+ // "NotAllowedError" is often a better choice because the error represetnts
+ // "The request is not allowed by the user agent or the platform in the
+ // current context, possibly because the user denied permission."
+ // https://heycam.github.io/webidl/#idl-DOMException-error-names
+ kSecurityError = 18,
+ kNetworkError = 19,
+ kAbortError = 20,
+ kURLMismatchError = 21,
+ kQuotaExceededError = 22,
+ kTimeoutError = 23,
+ kInvalidNodeTypeError = 24,
+ kDataCloneError = 25,
+
+ // The maximum value of the legacy error code of DOMException defined in
+ // Web IDL.
+ // https://heycam.github.io/webidl/#idl-DOMException
+ kLegacyErrorCodeMax = 25,
+
+ // DOMExceptions without the legacy error code.
+ kEncodingError,
+ kNotReadableError,
+ kUnknownError,
+ kConstraintError,
+ kDataError,
+ kTransactionInactiveError,
+ kReadOnlyError,
+ kVersionError,
+ kOperationError,
+ kNotAllowedError,
+
+ // The rest of entries are defined out of scope of Web IDL.
+
+ // DOMError (obsolete, not DOMException) defined in File system (obsolete).
+ // https://www.w3.org/TR/2012/WD-file-system-api-20120417/
+ kPathExistsError,
+
+ // Push API
+ //
+ // PermissionDeniedError (obsolete) was replaced with NotAllowedError in the
+ // standard.
+ // https://github.com/WICG/BackgroundSync/issues/124
+ kPermissionDeniedError,
+
+ // Pointer Events
+ // https://w3c.github.io/pointerevents/
+ // Pointer Events introduced a new DOMException outside Web IDL.
+ // The name "InvalidPointerId" does not end with the suffix "Error".
+ kInvalidPointerId,
+
+ kNumOfCodes,
+};
+
+inline bool IsDOMExceptionCode(ExceptionCode exception_code) {
+ return static_cast<ExceptionCode>(1) <= exception_code &&
+ exception_code <
+ static_cast<ExceptionCode>(DOMExceptionCode::kNumOfCodes);
+}
+
+// Exception codes that correspond to ECMAScript Error objects.
+// https://tc39.github.io/ecma262/#sec-error-objects
+enum class ESErrorType : ExceptionCode {
+ kError = 1000, // ECMAScript Error object
+ kRangeError, // ECMAScript RangeError object
+ kReferenceError, // ECMAScript ReferenceError object
+ // Note that ECMAScript SyntaxError object is different from DOMException's
+ // SyntaxError. See also the comment at |DOMExceptionCode::kSyntaxError|.
+ kSyntaxError, // ECMAScript SyntaxError object
+ kTypeError, // ECMAScript TypeError object
+};
+
+// Exception codes used only inside ExceptionState implementation.
+enum class InternalExceptionType : ExceptionCode {
+ // An exception code that is used when rethrowing a v8::Value as an
+ // exception where there is no way to determine an exception code.
+ kRethrownException = 2000,
+};
+
+// Upcast from DOMExceptionCode to ExceptionCode as ExceptionCode is considered
+// as an union of DOMExceptionCode and ESErrorType.
+// Downcast should be performed with explicit static_cast with a range check.
+inline ExceptionCode ToExceptionCode(DOMExceptionCode exception_code) {
+ return static_cast<ExceptionCode>(exception_code);
+}
+
+// Upcast from ESErrorType to ExceptionCode as ExceptionCode is considered
+// as an union of DOMExceptionCode and ESErrorType.
+// Downcast should be performed with explicit static_cast with a range check.
+inline ExceptionCode ToExceptionCode(ESErrorType exception_code) {
+ return static_cast<ExceptionCode>(exception_code);
+}
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_EXCEPTION_CODE_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/exception_messages.cc b/chromium/third_party/blink/renderer/platform/bindings/exception_messages.cc
new file mode 100644
index 00000000000..545e3399b08
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/bindings/exception_messages.cc
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+
+#include "third_party/blink/renderer/platform/wtf/decimal.h"
+#include "third_party/blink/renderer/platform/wtf/math_extras.h"
+
+namespace blink {
+
+String ExceptionMessages::FailedToConvertJSValue(const char* type) {
+ return String::Format("Failed to convert value to '%s'.", type);
+}
+
+String ExceptionMessages::FailedToConstruct(const char* type,
+ const String& detail) {
+ return "Failed to construct '" + String(type) +
+ (!detail.IsEmpty() ? String("': " + detail) : String("'"));
+}
+
+String ExceptionMessages::FailedToEnumerate(const char* type,
+ const String& detail) {
+ return "Failed to enumerate the properties of '" + String(type) +
+ (!detail.IsEmpty() ? String("': " + detail) : String("'"));
+}
+
+String ExceptionMessages::FailedToExecute(const char* method,
+ const char* type,
+ const String& detail) {
+ return "Failed to execute '" + String(method) + "' on '" + String(type) +
+ (!detail.IsEmpty() ? String("': " + detail) : String("'"));
+}
+
+String ExceptionMessages::FailedToGet(const char* property,
+ const char* type,
+ const String& detail) {
+ return "Failed to read the '" + String(property) + "' property from '" +
+ String(type) + "': " + detail;
+}
+
+String ExceptionMessages::FailedToSet(const char* property,
+ const char* type,
+ const String& detail) {
+ return "Failed to set the '" + String(property) + "' property on '" +
+ String(type) + "': " + detail;
+}
+
+String ExceptionMessages::FailedToDelete(const char* property,
+ const char* type,
+ const String& detail) {
+ return "Failed to delete the '" + String(property) + "' property from '" +
+ String(type) + "': " + detail;
+}
+
+String ExceptionMessages::FailedToGetIndexed(const char* type,
+ const String& detail) {
+ return "Failed to read an indexed property from '" + String(type) +
+ "': " + detail;
+}
+
+String ExceptionMessages::FailedToSetIndexed(const char* type,
+ const String& detail) {
+ return "Failed to set an indexed property on '" + String(type) +
+ "': " + detail;
+}
+
+String ExceptionMessages::FailedToDeleteIndexed(const char* type,
+ const String& detail) {
+ return "Failed to delete an indexed property from '" + String(type) +
+ "': " + detail;
+}
+
+String ExceptionMessages::ConstructorNotCallableAsFunction(const char* type) {
+ return FailedToConstruct(type,
+ "Please use the 'new' operator, this DOM object "
+ "constructor cannot be called as a function.");
+}
+
+String ExceptionMessages::IncorrectPropertyType(const String& property,
+ const String& detail) {
+ return "The '" + property + "' property " + detail;
+}
+
+String ExceptionMessages::InvalidArity(const char* expected,
+ unsigned provided) {
+ return "Valid arities are: " + String(expected) + ", but " +
+ String::Number(provided) + " arguments provided.";
+}
+
+String ExceptionMessages::ArgumentNullOrIncorrectType(
+ int argument_index,
+ const String& expected_type) {
+ return "The " + OrdinalNumber(argument_index) +
+ " argument provided is either null, or an invalid " + expected_type +
+ " object.";
+}
+
+String ExceptionMessages::NotASequenceTypeProperty(
+ const String& property_name) {
+ return "'" + property_name +
+ "' property is neither an array, nor does it have indexed properties.";
+}
+
+String ExceptionMessages::NotEnoughArguments(unsigned expected,
+ unsigned provided) {
+ return String::Number(expected) + " argument" + (expected > 1 ? "s" : "") +
+ " required, but only " + String::Number(provided) + " present.";
+}
+
+String ExceptionMessages::NotAFiniteNumber(double value, const char* name) {
+ DCHECK(!std::isfinite(value));
+ return String::Format("The %s is %s.", name,
+ std::isinf(value) ? "infinite" : "not a number");
+}
+
+String ExceptionMessages::NotAFiniteNumber(const Decimal& value,
+ const char* name) {
+ DCHECK(!value.IsFinite());
+ return String::Format("The %s is %s.", name,
+ value.IsInfinity() ? "infinite" : "not a number");
+}
+
+String ExceptionMessages::OrdinalNumber(int number) {
+ String suffix("th");
+ switch (number % 10) {
+ case 1:
+ if (number % 100 != 11)
+ suffix = "st";
+ break;
+ case 2:
+ if (number % 100 != 12)
+ suffix = "nd";
+ break;
+ case 3:
+ if (number % 100 != 13)
+ suffix = "rd";
+ break;
+ }
+ return String::Number(number) + suffix;
+}
+
+String ExceptionMessages::ReadOnly(const char* detail) {
+ DEFINE_STATIC_LOCAL(String, read_only, ("This object is read-only."));
+ return detail
+ ? String::Format("This object is read-only, because %s.", detail)
+ : read_only;
+}
+
+template <>
+String ExceptionMessages::FormatNumber<float>(float number) {
+ return FormatPotentiallyNonFiniteNumber(number);
+}
+
+template <>
+String ExceptionMessages::FormatNumber<double>(double number) {
+ return FormatPotentiallyNonFiniteNumber(number);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/exception_messages.h b/chromium/third_party/blink/renderer/platform/bindings/exception_messages.h
new file mode 100644
index 00000000000..6ba3229fe3e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/bindings/exception_messages.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_EXCEPTION_MESSAGES_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_EXCEPTION_MESSAGES_H_
+
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+class Decimal;
+
+class PLATFORM_EXPORT ExceptionMessages {
+ STATIC_ONLY(ExceptionMessages);
+
+ public:
+ enum BoundType {
+ kInclusiveBound,
+ kExclusiveBound,
+ };
+
+ static String ArgumentNullOrIncorrectType(int argument_index,
+ const String& expected_type);
+ static String ConstructorNotCallableAsFunction(const char* type);
+
+ static String FailedToConvertJSValue(const char* type);
+
+ static String FailedToConstruct(const char* type, const String& detail);
+ static String FailedToEnumerate(const char* type, const String& detail);
+ static String FailedToExecute(const char* method,
+ const char* type,
+ const String& detail);
+ static String FailedToGet(const char* property,
+ const char* type,
+ const String& detail);
+ static String FailedToSet(const char* property,
+ const char* type,
+ const String& detail);
+ static String FailedToDelete(const char* property,
+ const char* type,
+ const String& detail);
+ static String FailedToGetIndexed(const char* type, const String& detail);
+ static String FailedToSetIndexed(const char* type, const String& detail);
+ static String FailedToDeleteIndexed(const char* type, const String& detail);
+
+ template <typename NumType>
+ static String FormatNumber(NumType number) {
+ return FormatFiniteNumber(number);
+ }
+
+ static String IncorrectPropertyType(const String& property,
+ const String& detail);
+
+ template <typename NumberType>
+ static String IndexExceedsMaximumBound(const char* name,
+ NumberType given,
+ NumberType bound) {
+ bool eq = given == bound;
+ StringBuilder result;
+ result.Append("The ");
+ result.Append(name);
+ result.Append(" provided (");
+ result.Append(FormatNumber(given));
+ result.Append(") is greater than ");
+ result.Append(eq ? "or equal to " : "");
+ result.Append("the maximum bound (");
+ result.Append(FormatNumber(bound));
+ result.Append(").");
+ return result.ToString();
+ }
+
+ template <typename NumberType>
+ static String IndexExceedsMinimumBound(const char* name,
+ NumberType given,
+ NumberType bound) {
+ bool eq = given == bound;
+ StringBuilder result;
+ result.Append("The ");
+ result.Append(name);
+ result.Append(" provided (");
+ result.Append(FormatNumber(given));
+ result.Append(") is less than ");
+ result.Append(eq ? "or equal to " : "");
+ result.Append("the minimum bound (");
+ result.Append(FormatNumber(bound));
+ result.Append(").");
+ return result.ToString();
+ }
+
+ template <typename NumberType>
+ static String IndexOutsideRange(const char* name,
+ NumberType given,
+ NumberType lower_bound,
+ BoundType lower_type,
+ NumberType upper_bound,
+ BoundType upper_type) {
+ StringBuilder result;
+ result.Append("The ");
+ result.Append(name);
+ result.Append(" provided (");
+ result.Append(FormatNumber(given));
+ result.Append(") is outside the range ");
+ result.Append(lower_type == kExclusiveBound ? '(' : '[');
+ result.Append(FormatNumber(lower_bound));
+ result.Append(", ");
+ result.Append(FormatNumber(upper_bound));
+ result.Append(upper_type == kExclusiveBound ? ')' : ']');
+ result.Append('.');
+ return result.ToString();
+ }
+
+ static String InvalidArity(const char* expected, unsigned provided);
+
+ static String NotASequenceTypeProperty(const String& property_name);
+ static String NotAFiniteNumber(double value,
+ const char* name = "value provided");
+ static String NotAFiniteNumber(const Decimal& value,
+ const char* name = "value provided");
+
+ static String NotEnoughArguments(unsigned expected, unsigned provided);
+
+ static String ReadOnly(const char* detail = nullptr);
+
+ private:
+ template <typename NumType>
+ static String FormatFiniteNumber(NumType number) {
+ if (number > 1e20 || number < -1e20)
+ return String::Format("%e", 1.0 * number);
+ return String::Number(number);
+ }
+
+ template <typename NumType>
+ static String FormatPotentiallyNonFiniteNumber(NumType number) {
+ if (std::isnan(number))
+ return "NaN";
+ if (std::isinf(number))
+ return number > 0 ? "Infinity" : "-Infinity";
+ if (number > 1e20 || number < -1e20)
+ return String::Format("%e", number);
+ return String::Number(number);
+ }
+
+ static String OrdinalNumber(int number);
+};
+
+template <>
+PLATFORM_EXPORT String ExceptionMessages::FormatNumber<float>(float number);
+
+template <>
+PLATFORM_EXPORT String ExceptionMessages::FormatNumber<double>(double number);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_EXCEPTION_MESSAGES_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/exception_state.cc b/chromium/third_party/blink/renderer/platform/bindings/exception_state.cc
new file mode 100644
index 00000000000..969c5c20892
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/bindings/exception_state.cc
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+
+#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
+#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
+
+namespace blink {
+
+ExceptionState::CreateDOMExceptionFunction
+ ExceptionState::s_create_dom_exception_func_ = nullptr;
+
+// static
+void ExceptionState::SetCreateDOMExceptionFunction(
+ CreateDOMExceptionFunction func) {
+ DCHECK(!s_create_dom_exception_func_);
+ s_create_dom_exception_func_ = func;
+ DCHECK(s_create_dom_exception_func_);
+}
+
+void ExceptionState::ThrowException(ExceptionCode exception_code,
+ const String& message) {
+ // SecurityError is thrown via ThrowSecurityError, and _careful_ consideration
+ // must be given to the data exposed to JavaScript via |sanitized_message|.
+ DCHECK_NE(exception_code, ToExceptionCode(DOMExceptionCode::kSecurityError));
+
+ const String& processed_message = AddExceptionContext(message);
+
+ v8::Local<v8::Value> exception;
+ switch (static_cast<ESErrorType>(exception_code)) {
+ case ESErrorType::kError:
+ exception = V8ThrowException::CreateError(isolate_, processed_message);
+ break;
+ case ESErrorType::kRangeError:
+ exception =
+ V8ThrowException::CreateRangeError(isolate_, processed_message);
+ break;
+ case ESErrorType::kReferenceError:
+ exception =
+ V8ThrowException::CreateReferenceError(isolate_, processed_message);
+ break;
+ case ESErrorType::kSyntaxError:
+ exception =
+ V8ThrowException::CreateSyntaxError(isolate_, processed_message);
+ break;
+ case ESErrorType::kTypeError:
+ exception =
+ V8ThrowException::CreateTypeError(isolate_, processed_message);
+ break;
+ default:
+ if (IsDOMExceptionCode(exception_code)) {
+ exception = s_create_dom_exception_func_(
+ isolate_, static_cast<DOMExceptionCode>(exception_code),
+ processed_message, String());
+ } else {
+ NOTREACHED();
+ exception = s_create_dom_exception_func_(
+ isolate_, DOMExceptionCode::kUnknownError, processed_message,
+ String());
+ }
+ }
+
+ SetException(exception_code, processed_message, exception);
+}
+
+void ExceptionState::ThrowDOMException(DOMExceptionCode exception_code,
+ const String& message) {
+ // SecurityError is thrown via ThrowSecurityError, and _careful_ consideration
+ // must be given to the data exposed to JavaScript via |sanitized_message|.
+ DCHECK_NE(exception_code, DOMExceptionCode::kSecurityError);
+
+ const String& processed_message = AddExceptionContext(message);
+ SetException(ToExceptionCode(exception_code), processed_message,
+ s_create_dom_exception_func_(isolate_, exception_code,
+ processed_message, String()));
+}
+
+void ExceptionState::ThrowSecurityError(const String& sanitized_message,
+ const String& unsanitized_message) {
+ const String& final_sanitized = AddExceptionContext(sanitized_message);
+ const String& final_unsanitized = AddExceptionContext(unsanitized_message);
+ SetException(
+ ToExceptionCode(DOMExceptionCode::kSecurityError), final_sanitized,
+ s_create_dom_exception_func_(isolate_, DOMExceptionCode::kSecurityError,
+ final_sanitized, final_unsanitized));
+}
+
+void ExceptionState::ThrowRangeError(const String& message) {
+ SetException(ToExceptionCode(ESErrorType::kRangeError), message,
+ V8ThrowException::CreateRangeError(
+ isolate_, AddExceptionContext(message)));
+}
+
+void ExceptionState::ThrowTypeError(const String& message) {
+ SetException(ToExceptionCode(ESErrorType::kTypeError), message,
+ V8ThrowException::CreateTypeError(isolate_,
+ AddExceptionContext(message)));
+}
+
+void ExceptionState::ThrowDOMException(DOMExceptionCode exception_code,
+ const char* message) {
+ ThrowDOMException(exception_code, String(message));
+}
+
+void ExceptionState::ThrowSecurityError(const char* sanitized_message,
+ const char* unsanitized_message) {
+ ThrowSecurityError(String(sanitized_message), String(unsanitized_message));
+}
+
+void ExceptionState::ThrowRangeError(const char* message) {
+ ThrowRangeError(String(message));
+}
+
+void ExceptionState::ThrowTypeError(const char* message) {
+ ThrowTypeError(String(message));
+}
+
+void ExceptionState::RethrowV8Exception(v8::Local<v8::Value> value) {
+ SetException(
+ static_cast<ExceptionCode>(InternalExceptionType::kRethrownException),
+ String(), value);
+}
+
+void ExceptionState::ClearException() {
+ code_ = 0;
+ message_ = String();
+ exception_.Clear();
+}
+
+void ExceptionState::SetException(ExceptionCode exception_code,
+ const String& message,
+ v8::Local<v8::Value> exception) {
+ CHECK(exception_code);
+
+ code_ = exception_code;
+ message_ = message;
+ if (exception.IsEmpty()) {
+ exception_.Clear();
+ } else {
+ DCHECK(isolate_);
+ exception_.Set(isolate_, exception);
+ }
+}
+
+String ExceptionState::AddExceptionContext(const String& message) const {
+ if (message.IsEmpty())
+ return message;
+
+ String processed_message = message;
+ if (PropertyName() && InterfaceName() && context_ != kUnknownContext) {
+ if (context_ == kDeletionContext)
+ processed_message = ExceptionMessages::FailedToDelete(
+ PropertyName(), InterfaceName(), message);
+ else if (context_ == kExecutionContext)
+ processed_message = ExceptionMessages::FailedToExecute(
+ PropertyName(), InterfaceName(), message);
+ else if (context_ == kGetterContext)
+ processed_message = ExceptionMessages::FailedToGet(
+ PropertyName(), InterfaceName(), message);
+ else if (context_ == kSetterContext)
+ processed_message = ExceptionMessages::FailedToSet(
+ PropertyName(), InterfaceName(), message);
+ } else if (!PropertyName() && InterfaceName()) {
+ if (context_ == kConstructionContext)
+ processed_message =
+ ExceptionMessages::FailedToConstruct(InterfaceName(), message);
+ else if (context_ == kEnumerationContext)
+ processed_message =
+ ExceptionMessages::FailedToEnumerate(InterfaceName(), message);
+ else if (context_ == kIndexedDeletionContext)
+ processed_message =
+ ExceptionMessages::FailedToDeleteIndexed(InterfaceName(), message);
+ else if (context_ == kIndexedGetterContext)
+ processed_message =
+ ExceptionMessages::FailedToGetIndexed(InterfaceName(), message);
+ else if (context_ == kIndexedSetterContext)
+ processed_message =
+ ExceptionMessages::FailedToSetIndexed(InterfaceName(), message);
+ }
+ return processed_message;
+}
+
+NonThrowableExceptionState::NonThrowableExceptionState()
+ : ExceptionState(nullptr,
+ ExceptionState::kUnknownContext,
+ nullptr,
+ nullptr),
+ file_(""),
+ line_(0) {}
+
+NonThrowableExceptionState::NonThrowableExceptionState(const char* file,
+ int line)
+ : ExceptionState(nullptr,
+ ExceptionState::kUnknownContext,
+ nullptr,
+ nullptr),
+ file_(file),
+ line_(line) {}
+
+void NonThrowableExceptionState::ThrowDOMException(
+ DOMExceptionCode exception_code,
+ const String& message) {
+ DCHECK_AT(false, file_, line_) << "DOMExeption should not be thrown.";
+}
+
+void NonThrowableExceptionState::ThrowRangeError(const String& message) {
+ DCHECK_AT(false, file_, line_) << "RangeError should not be thrown.";
+}
+
+void NonThrowableExceptionState::ThrowSecurityError(
+ const String& sanitized_message,
+ const String&) {
+ DCHECK_AT(false, file_, line_) << "SecurityError should not be thrown.";
+}
+
+void NonThrowableExceptionState::ThrowTypeError(const String& message) {
+ DCHECK_AT(false, file_, line_) << "TypeError should not be thrown.";
+}
+
+void NonThrowableExceptionState::RethrowV8Exception(v8::Local<v8::Value>) {
+ DCHECK_AT(false, file_, line_) << "An exception should not be rethrown.";
+}
+
+void DummyExceptionStateForTesting::ThrowDOMException(
+ DOMExceptionCode exception_code,
+ const String& message) {
+ SetException(ToExceptionCode(exception_code), message,
+ v8::Local<v8::Value>());
+}
+
+void DummyExceptionStateForTesting::ThrowRangeError(const String& message) {
+ SetException(ToExceptionCode(ESErrorType::kRangeError), message,
+ v8::Local<v8::Value>());
+}
+
+void DummyExceptionStateForTesting::ThrowSecurityError(
+ const String& sanitized_message,
+ const String&) {
+ SetException(ToExceptionCode(DOMExceptionCode::kSecurityError),
+ sanitized_message, v8::Local<v8::Value>());
+}
+
+void DummyExceptionStateForTesting::ThrowTypeError(const String& message) {
+ SetException(ToExceptionCode(ESErrorType::kTypeError), message,
+ v8::Local<v8::Value>());
+}
+
+void DummyExceptionStateForTesting::RethrowV8Exception(v8::Local<v8::Value>) {
+ SetException(
+ static_cast<ExceptionCode>(InternalExceptionType::kRethrownException),
+ String(), v8::Local<v8::Value>());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/exception_state.h b/chromium/third_party/blink/renderer/platform/bindings/exception_state.h
new file mode 100644
index 00000000000..0918f256d22
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/bindings/exception_state.h
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_EXCEPTION_STATE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_EXCEPTION_STATE_H_
+
+#include "third_party/blink/renderer/platform/bindings/exception_code.h"
+#include "third_party/blink/renderer/platform/bindings/scoped_persistent.h"
+#include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "v8/include/v8.h"
+
+namespace blink {
+
+// ExceptionState is a scope-like class and provides a way to throw an exception
+// with an option to cancel it. An exception message may be auto-generated.
+class PLATFORM_EXPORT ExceptionState {
+ STACK_ALLOCATED();
+ WTF_MAKE_NONCOPYABLE(ExceptionState);
+
+ public:
+ enum ContextType {
+ kConstructionContext,
+ kExecutionContext,
+ kDeletionContext,
+ kGetterContext,
+ kSetterContext,
+ kEnumerationContext,
+ kQueryContext,
+ kIndexedGetterContext,
+ kIndexedSetterContext,
+ kIndexedDeletionContext,
+ kUnknownContext, // FIXME: Remove this once we've flipped over to the new
+ // API.
+ };
+
+ // A function pointer type that creates a DOMException.
+ using CreateDOMExceptionFunction =
+ v8::Local<v8::Value> (*)(v8::Isolate*,
+ DOMExceptionCode,
+ const String& sanitized_message,
+ const String& unsanitized_message);
+
+ // Sets the function to create a DOMException. Must be called only once.
+ static void SetCreateDOMExceptionFunction(CreateDOMExceptionFunction);
+
+ ExceptionState(v8::Isolate* isolate,
+ ContextType context_type,
+ const char* interface_name,
+ const char* property_name)
+ : code_(0),
+ context_(context_type),
+ property_name_(property_name),
+ interface_name_(interface_name),
+ isolate_(isolate) {}
+
+ ExceptionState(v8::Isolate* isolate,
+ ContextType context_type,
+ const char* interface_name)
+ : ExceptionState(isolate, context_type, interface_name, nullptr) {
+#if DCHECK_IS_ON()
+ switch (context_) {
+ case kConstructionContext:
+ case kEnumerationContext:
+ case kIndexedGetterContext:
+ case kIndexedSetterContext:
+ case kIndexedDeletionContext:
+ break;
+ default:
+ NOTREACHED();
+ }
+#endif // DCHECK_IS_ON()
+ }
+
+ ~ExceptionState() {
+ if (!exception_.IsEmpty()) {
+ V8ThrowException::ThrowException(isolate_, exception_.NewLocal(isolate_));
+ }
+ }
+
+ // Throws an appropriate exception due to the given exception code. The
+ // exception will be either of ECMAScript Error object or DOMException.
+ void ThrowException(ExceptionCode, const String& message);
+
+ // Throws a DOMException due to the given exception code.
+ virtual void ThrowDOMException(DOMExceptionCode, const String& message);
+
+ // Throws a DOMException with SECURITY_ERR.
+ virtual void ThrowSecurityError(const String& sanitized_message,
+ const String& unsanitized_message = String());
+
+ // Throws an ECMAScript Error object.
+ virtual void ThrowRangeError(const String& message);
+ virtual void ThrowTypeError(const String& message);
+
+ // These overloads reduce the binary code size because the call sites do not
+ // need the conversion by String::String(const char*) that is inlined at each
+ // call site. As there are many call sites that pass in a const char*, this
+ // size optimization is effective (32kb reduction as of June 2018).
+ // See also https://crbug.com/849743
+ void ThrowDOMException(DOMExceptionCode, const char* message);
+ void ThrowSecurityError(const char* sanitized_message,
+ const char* unsanitized_message = nullptr);
+ void ThrowRangeError(const char* message);
+ void ThrowTypeError(const char* message);
+
+ // Rethrows a v8::Value as an exception.
+ virtual void RethrowV8Exception(v8::Local<v8::Value>);
+
+ // Returns true if there is a pending exception.
+ //
+ // Note that this function returns true even when |exception_| is empty, and
+ // that V8ThrowDOMException::CreateOrEmpty may return an empty handle.
+ bool HadException() const { return code_; }
+
+ void ClearException();
+
+ ExceptionCode Code() const { return code_; }
+
+ template <typename T>
+ T CodeAs() const {
+ return static_cast<T>(Code());
+ }
+
+ const String& Message() const { return message_; }
+
+ v8::Local<v8::Value> GetException() {
+ DCHECK(!exception_.IsEmpty());
+ return exception_.NewLocal(isolate_);
+ }
+
+ ContextType Context() const { return context_; }
+ const char* PropertyName() const { return property_name_; }
+ const char* InterfaceName() const { return interface_name_; }
+
+ protected:
+ void SetException(ExceptionCode, const String&, v8::Local<v8::Value>);
+
+ private:
+ String AddExceptionContext(const String&) const;
+
+ // Since DOMException is defined in core/, we need a dependency injection in
+ // order to create a DOMException in platform/.
+ static CreateDOMExceptionFunction s_create_dom_exception_func_;
+
+ ExceptionCode code_;
+ ContextType context_;
+ String message_;
+ const char* property_name_;
+ const char* interface_name_;
+ // The exception is empty when it was thrown through
+ // DummyExceptionStateForTesting.
+ ScopedPersistent<v8::Value> exception_;
+ v8::Isolate* isolate_;
+};
+
+// NonThrowableExceptionState never allow call sites to throw an exception.
+// Should be used if an exception must not be thrown.
+class PLATFORM_EXPORT NonThrowableExceptionState final : public ExceptionState {
+ public:
+ NonThrowableExceptionState();
+ NonThrowableExceptionState(const char*, int);
+
+ void ThrowDOMException(DOMExceptionCode, const String& message) override;
+ void ThrowTypeError(const String& message) override;
+ void ThrowSecurityError(const String& sanitized_message,
+ const String& unsanitized_message) override;
+ void ThrowRangeError(const String& message) override;
+ void RethrowV8Exception(v8::Local<v8::Value>) override;
+ ExceptionState& ReturnThis() { return *this; }
+
+ private:
+ const char* file_;
+ const int line_;
+};
+
+// Syntax sugar for NonThrowableExceptionState.
+// This can be used as a default value of an ExceptionState parameter like this:
+//
+// Node* removeChild(Node*, ExceptionState& = ASSERT_NO_EXCEPTION);
+#if DCHECK_IS_ON()
+#define ASSERT_NO_EXCEPTION \
+ (::blink::NonThrowableExceptionState(__FILE__, __LINE__).ReturnThis())
+#else
+#define ASSERT_NO_EXCEPTION \
+ (::blink::DummyExceptionStateForTesting().ReturnThis())
+#endif
+
+// DummyExceptionStateForTesting ignores all thrown exceptions. You should not
+// use DummyExceptionStateForTesting in production code, where you need to
+// handle all exceptions properly. If you really need to ignore exceptions in
+// production code for some special reason, explicitly call clearException().
+class PLATFORM_EXPORT DummyExceptionStateForTesting final
+ : public ExceptionState {
+ public:
+ DummyExceptionStateForTesting()
+ : ExceptionState(nullptr,
+ ExceptionState::kUnknownContext,
+ nullptr,
+ nullptr) {}
+ ~DummyExceptionStateForTesting() {
+ // Prevent the base class throw an exception.
+ if (HadException()) {
+ ClearException();
+ }
+ }
+ void ThrowDOMException(DOMExceptionCode, const String& message) override;
+ void ThrowTypeError(const String& message) override;
+ void ThrowSecurityError(const String& sanitized_message,
+ const String& unsanitized_message) override;
+ void ThrowRangeError(const String& message) override;
+ void RethrowV8Exception(v8::Local<v8::Value>) override;
+ ExceptionState& ReturnThis() { return *this; }
+};
+
+// Syntax sugar for DummyExceptionStateForTesting.
+// This can be used as a default value of an ExceptionState parameter like this:
+//
+// Node* removeChild(Node*, ExceptionState& = IGNORE_EXCEPTION_FOR_TESTING);
+#define IGNORE_EXCEPTION_FOR_TESTING \
+ (::blink::DummyExceptionStateForTesting().ReturnThis())
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_EXCEPTION_STATE_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/name_client.h b/chromium/third_party/blink/renderer/platform/bindings/name_client.h
new file mode 100644
index 00000000000..436006bc13c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/bindings/name_client.h
@@ -0,0 +1,29 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_NAME_CLIENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_NAME_CLIENT_H_
+
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
+
+namespace blink {
+
+// Provides classes with a human-readable name that can be used for inspecting
+// the object graph.
+class PLATFORM_EXPORT NameClient {
+ WTF_MAKE_NONCOPYABLE(NameClient);
+
+ public:
+ NameClient() = default;
+ ~NameClient() = default;
+
+ // Human-readable name of this object. The DevTools heap snapshot uses
+ // this method to show the object.
+ virtual const char* NameInHeapSnapshot() const = 0;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_NAME_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.cc b/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.cc
index 80d04c72f8c..4c248ff1a62 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.cc
@@ -6,9 +6,11 @@
#include <inttypes.h>
#include <algorithm>
-#include "base/time/tick_clock.h"
+#include "base/time/default_tick_clock.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
+#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
+#include "third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
@@ -27,7 +29,7 @@ RuntimeCallStats* g_runtime_call_stats_for_testing = nullptr;
void RuntimeCallCounter::Dump(TracedValue& value) const {
value.BeginArray(name_);
value.PushDouble(count_);
- value.PushDouble(time_.InMicroseconds());
+ value.PushDouble(time_.InMicrosecondsF());
value.EndArray();
}
@@ -191,7 +193,18 @@ const char* const RuntimeCallStatsScopedTracer::s_category_group_ =
const char* const RuntimeCallStatsScopedTracer::s_name_ =
"BlinkRuntimeCallStats";
-void RuntimeCallStatsScopedTracer::AddBeginTraceEvent() {
+void RuntimeCallStatsScopedTracer::AddBeginTraceEventIfEnabled(
+ v8::Isolate* isolate) {
+ bool category_group_enabled;
+ TRACE_EVENT_CATEGORY_GROUP_ENABLED(s_category_group_,
+ &category_group_enabled);
+ if (LIKELY(!category_group_enabled))
+ return;
+
+ RuntimeCallStats* stats = RuntimeCallStats::From(isolate);
+ if (stats->InUse())
+ return;
+ stats_ = stats;
stats_->Reset();
stats_->SetInUse(true);
TRACE_EVENT_BEGIN0(s_category_group_, s_name_);
diff --git a/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.h b/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.h
index c6d12b9b2f6..98c8bc13410 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/runtime_call_stats.h
@@ -10,12 +10,10 @@
#include "base/optional.h"
#include "third_party/blink/renderer/platform/bindings/runtime_call_stats_count_everything_buildflags.h"
-#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
-#include "third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
#include "v8/include/v8.h"
@@ -25,6 +23,8 @@ class TickClock;
namespace blink {
+class TracedValue;
+
// A simple counter used to track total execution count & time for a particular
// function/scope.
class PLATFORM_EXPORT RuntimeCallCounter {
@@ -356,18 +356,8 @@ class PLATFORM_EXPORT RuntimeCallTimerScope {
class PLATFORM_EXPORT RuntimeCallStatsScopedTracer {
public:
explicit RuntimeCallStatsScopedTracer(v8::Isolate* isolate) {
- bool category_group_enabled;
- TRACE_EVENT_CATEGORY_GROUP_ENABLED(s_category_group_,
- &category_group_enabled);
- if (LIKELY(!category_group_enabled ||
- !RuntimeEnabledFeatures::BlinkRuntimeCallStatsEnabled()))
- return;
-
- RuntimeCallStats* stats = RuntimeCallStats::From(isolate);
- if (!stats->InUse()) {
- stats_ = stats;
- AddBeginTraceEvent();
- }
+ if (UNLIKELY(RuntimeEnabledFeatures::BlinkRuntimeCallStatsEnabled()))
+ AddBeginTraceEventIfEnabled(isolate);
}
~RuntimeCallStatsScopedTracer() {
@@ -376,7 +366,7 @@ class PLATFORM_EXPORT RuntimeCallStatsScopedTracer {
}
private:
- void AddBeginTraceEvent();
+ void AddBeginTraceEventIfEnabled(v8::Isolate* isolate);
void AddEndTraceEvent();
static const char* const s_category_group_;
diff --git a/chromium/third_party/blink/renderer/platform/bindings/scoped_persistent.h b/chromium/third_party/blink/renderer/platform/bindings/scoped_persistent.h
index 137745250cd..644746a6028 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/scoped_persistent.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/scoped_persistent.h
@@ -31,8 +31,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCOPED_PERSISTENT_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCOPED_PERSISTENT_H_
-#include <memory>
-
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "v8/include/v8.h"
diff --git a/chromium/third_party/blink/renderer/platform/bindings/script_state.cc b/chromium/third_party/blink/renderer/platform/bindings/script_state.cc
index 9463657494f..9e0b06d0056 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/script_state.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/script_state.cc
@@ -5,30 +5,14 @@
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
+#include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h"
#include "third_party/blink/renderer/platform/instance_counters.h"
namespace blink {
-scoped_refptr<ScriptState> ScriptState::Create(
- v8::Local<v8::Context> context,
- scoped_refptr<DOMWrapperWorld> world) {
- scoped_refptr<ScriptState> script_state =
- base::AdoptRef(new ScriptState(context, std::move(world)));
- // This AddRef() is for keeping this ScriptState alive as long as the
- // v8::Context is alive. This is Release()d in the weak callback of the
- // v8::Context.
- script_state->AddRef();
- return script_state;
-}
-
-static void DerefCallback(const v8::WeakCallbackInfo<ScriptState>& data) {
- data.GetParameter()->Release();
-}
-
-static void ContextCollectedCallback(
- const v8::WeakCallbackInfo<ScriptState>& data) {
- data.GetParameter()->ClearContext();
- data.SetSecondPassCallback(DerefCallback);
+ScriptState* ScriptState::Create(v8::Local<v8::Context> context,
+ scoped_refptr<DOMWrapperWorld> world) {
+ return new ScriptState(context, std::move(world));
}
ScriptState::ScriptState(v8::Local<v8::Context> context,
@@ -36,9 +20,10 @@ ScriptState::ScriptState(v8::Local<v8::Context> context,
: isolate_(context->GetIsolate()),
context_(isolate_, context),
world_(std::move(world)),
- per_context_data_(V8PerContextData::Create(context)) {
+ per_context_data_(V8PerContextData::Create(context)),
+ reference_from_v8_context_(this) {
DCHECK(world_);
- context_.SetWeak(this, &ContextCollectedCallback);
+ context_.SetWeak(this, &OnV8ContextCollectedCallback);
context->SetAlignedPointerInEmbedderData(kV8ContextPerContextDataIndex, this);
}
@@ -60,4 +45,28 @@ void ScriptState::DisposePerContextData() {
InstanceCounters::kDetachedScriptStateCounter);
}
+void ScriptState::DissociateContext() {
+ DCHECK(!per_context_data_);
+
+ // On a worker thread we tear down V8's isolate without running a GC.
+ // Alternately we manually clear all references between V8 and Blink, and run
+ // operations that should have been invoked by weak callbacks if a GC were
+ // run.
+
+ v8::HandleScope scope(GetIsolate());
+ // Cut the reference from V8 context to ScriptState.
+ GetContext()->SetAlignedPointerInEmbedderData(kV8ContextPerContextDataIndex,
+ nullptr);
+ reference_from_v8_context_.Clear();
+
+ // Cut the reference from ScriptState to V8 context.
+ context_.Clear();
+}
+
+void ScriptState::OnV8ContextCollectedCallback(
+ const v8::WeakCallbackInfo<ScriptState>& data) {
+ data.GetParameter()->reference_from_v8_context_.Clear();
+ data.GetParameter()->context_.Clear();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/script_state.h b/chromium/third_party/blink/renderer/platform/bindings/script_state.h
index 87187ff4296..e064e7f7eb7 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/script_state.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/script_state.h
@@ -7,16 +7,19 @@
#include <memory>
+#include "gin/public/context_holder.h"
+#include "gin/public/gin_embedders.h"
#include "third_party/blink/renderer/platform/bindings/scoped_persistent.h"
-#include "third_party/blink/renderer/platform/bindings/v8_per_context_data.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/heap/self_keep_alive.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
#include "v8/include/v8.h"
namespace blink {
class DOMWrapperWorld;
class ScriptValue;
+class V8PerContextData;
// ScriptState is an abstraction class that holds all information about script
// exectuion (e.g., v8::Isolate, v8::Context, DOMWrapperWorld, ExecutionContext
@@ -29,9 +32,9 @@ class ScriptValue;
//
// In some cases, you need ScriptState in code that doesn't have any JavaScript
// on the stack. Then you can store ScriptState on a C++ object using
-// scoped_refptr<ScriptState>.
+// Member<ScriptState> or Persistent<ScriptState>.
//
-// class SomeObject {
+// class SomeObject : public GarbageCollected<SomeObject> {
// void someMethod(ScriptState* scriptState) {
// script_state_ = scriptState; // Record the ScriptState.
// ...;
@@ -43,11 +46,16 @@ class ScriptValue;
// return;
// }
// // Enter the ScriptState.
-// ScriptState::Scope scope(script_state_.get());
+// ScriptState::Scope scope(script_state_);
// // Do V8 related things.
// ToV8(...);
// }
-// scoped_refptr<ScriptState> script_state_;
+//
+// virtual void Trace(Visitor* visitor) {
+// visitor->Trace(script_state_); // ScriptState also needs to be traced.
+// }
+//
+// Member<ScriptState> script_state_;
// };
//
// You should not store ScriptState on a C++ object that can be accessed
@@ -63,7 +71,8 @@ class ScriptValue;
// ScriptState is created when v8::Context is created.
// ScriptState is destroyed when v8::Context is garbage-collected and
// all V8 proxy objects that have references to the ScriptState are destructed.
-class PLATFORM_EXPORT ScriptState : public RefCounted<ScriptState> {
+class PLATFORM_EXPORT ScriptState final
+ : public GarbageCollectedFinalized<ScriptState> {
WTF_MAKE_NONCOPYABLE(ScriptState);
public:
@@ -87,12 +96,13 @@ class PLATFORM_EXPORT ScriptState : public RefCounted<ScriptState> {
v8::Local<v8::Context> context_;
};
- static scoped_refptr<ScriptState> Create(v8::Local<v8::Context>,
- scoped_refptr<DOMWrapperWorld>);
- virtual ~ScriptState();
+ static ScriptState* Create(v8::Local<v8::Context>,
+ scoped_refptr<DOMWrapperWorld>);
+ ~ScriptState();
- static ScriptState* Current(v8::Isolate* isolate) // DEPRECATED
- {
+ void Trace(blink::Visitor*) {}
+
+ static ScriptState* Current(v8::Isolate* isolate) { // DEPRECATED
return From(isolate->GetCurrentContext());
}
@@ -139,20 +149,28 @@ class PLATFORM_EXPORT ScriptState : public RefCounted<ScriptState> {
return !context_.IsEmpty() && per_context_data_;
}
void DetachGlobalObject();
- void ClearContext() { return context_.Clear(); }
V8PerContextData* PerContextData() const { return per_context_data_.get(); }
void DisposePerContextData();
+ // This method is expected to be called only from
+ // WorkerOrWorkletScriptController to run operations that should have been
+ // invoked by a weak callback if a V8 GC were run, in a worker thread
+ // termination.
+ void DissociateContext();
+
protected:
ScriptState(v8::Local<v8::Context>, scoped_refptr<DOMWrapperWorld>);
private:
+ static void OnV8ContextCollectedCallback(
+ const v8::WeakCallbackInfo<ScriptState>&);
+
v8::Isolate* isolate_;
// This persistent handle is weak.
ScopedPersistent<v8::Context> context_;
- // This RefPtr doesn't cause a cycle because all persistent handles that
+ // This refptr doesn't cause a cycle because all persistent handles that
// DOMWrapperWorld holds are weak.
scoped_refptr<DOMWrapperWorld> world_;
@@ -163,17 +181,48 @@ class PLATFORM_EXPORT ScriptState : public RefCounted<ScriptState> {
// disposePerContextData() once you no longer need V8PerContextData.
// Otherwise, the v8::Context will leak.
std::unique_ptr<V8PerContextData> per_context_data_;
+
+ // v8::Context has an internal field to this ScriptState* as a raw pointer,
+ // which is out of scope of Blink GC, but it must be a strong reference. We
+ // use |reference_from_v8_context_| to represent this strong reference. The
+ // lifetime of |reference_from_v8_context_| and the internal field must match
+ // exactly.
+ SelfKeepAlive<ScriptState> reference_from_v8_context_;
+
+ static constexpr int kV8ContextPerContextDataIndex = static_cast<int>(
+ gin::kPerContextDataStartIndex + // NOLINT(readability/enum_casing)
+ gin::kEmbedderBlink); // NOLINT(readability/enum_casing)
};
// ScriptStateProtectingContext keeps the context associated with the
-// ScriptState alive. You need to call clear() once you no longer need the
+// ScriptState alive. You need to call Clear() once you no longer need the
// context. Otherwise, the context will leak.
-class ScriptStateProtectingContext {
+class ScriptStateProtectingContext
+ : public GarbageCollectedFinalized<ScriptStateProtectingContext> {
WTF_MAKE_NONCOPYABLE(ScriptStateProtectingContext);
- USING_FAST_MALLOC(ScriptStateProtectingContext);
public:
- ScriptStateProtectingContext(ScriptState* script_state)
+ static ScriptStateProtectingContext* Create(ScriptState* script_state) {
+ return new ScriptStateProtectingContext(script_state);
+ }
+
+ void Trace(blink::Visitor* visitor) { visitor->Trace(script_state_); }
+
+ ScriptState* Get() const { return script_state_; }
+ void Reset() {
+ script_state_ = nullptr;
+ context_.Clear();
+ }
+
+ // ScriptState like interface
+ bool ContextIsValid() const { return script_state_->ContextIsValid(); }
+ v8::Isolate* GetIsolate() const { return script_state_->GetIsolate(); }
+ v8::Local<v8::Context> GetContext() const {
+ return script_state_->GetContext();
+ }
+
+ private:
+ explicit ScriptStateProtectingContext(ScriptState* script_state)
: script_state_(script_state) {
if (script_state_) {
context_.Set(script_state_->GetIsolate(), script_state_->GetContext());
@@ -182,15 +231,7 @@ class ScriptStateProtectingContext {
}
}
- ScriptState* operator->() const { return script_state_.get(); }
- ScriptState* Get() const { return script_state_.get(); }
- void Clear() {
- script_state_ = nullptr;
- context_.Clear();
- }
-
- private:
- scoped_refptr<ScriptState> script_state_;
+ Member<ScriptState> script_state_;
ScopedPersistent<v8::Context> context_;
};
diff --git a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.cc b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.cc
index 8b5de7a79c7..d32c3d53673 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.cc
@@ -44,11 +44,6 @@ void ScriptWrappable::Trace(Visitor* visitor) {
DOMWrapperWorld::Trace(this, visitor);
}
-void ScriptWrappable::TraceWrappers(ScriptWrappableVisitor* visitor) const {
- visitor->TraceWrappers(main_world_wrapper_);
- DOMWrapperWorld::TraceWrappers(this, visitor);
-}
-
const char* ScriptWrappable::NameInHeapSnapshot() const {
return GetWrapperTypeInfo()->interface_name;
}
diff --git a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.h b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.h
index cf57e9e7f64..8020b098b13 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable.h
@@ -32,7 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCRIPT_WRAPPABLE_H_
#include "build/build_config.h"
-#include "third_party/blink/renderer/platform/bindings/trace_wrapper_base.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -51,7 +51,7 @@ namespace blink {
// objects for other worlds are stored in DOMWrapperMap.
class PLATFORM_EXPORT ScriptWrappable
: public GarbageCollectedFinalized<ScriptWrappable>,
- public TraceWrapperBase {
+ public NameClient {
WTF_MAKE_NONCOPYABLE(ScriptWrappable);
public:
@@ -59,11 +59,6 @@ class PLATFORM_EXPORT ScriptWrappable
virtual void Trace(blink::Visitor*);
- // Traces wrapper objects corresponding to this ScriptWrappable in all worlds.
- void TraceWrappers(ScriptWrappableVisitor*) const override;
-
- bool IsScriptWrappable() const override { return true; }
-
const char* NameInHeapSnapshot() const override;
template <typename T>
@@ -161,13 +156,6 @@ class PLATFORM_EXPORT ScriptWrappable
return main_world_wrapper_.NewLocal(isolate);
}
- // Only use when really necessary, i.e., when passing over this
- // ScriptWrappable's reference to V8. Should only be needed by GC
- // infrastructure.
- const v8::Persistent<v8::Object>* RawMainWorldWrapper() const {
- return &main_world_wrapper_.Get();
- }
-
TraceWrapperV8Reference<v8::Object> main_world_wrapper_;
};
diff --git a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.cc b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.cc
index e0f83319b34..2ab286e5e56 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.cc
@@ -56,7 +56,7 @@ void ScriptWrappableMarkingVisitor::TraceEpilogue() {
ScriptWrappableVisitorVerifier verifier;
for (auto& marking_data : verifier_deque_) {
// Check that all children of this object are marked.
- marking_data.TraceWrappers(&verifier);
+ marking_data.Trace(&verifier);
}
#endif
@@ -114,8 +114,7 @@ void ScriptWrappableMarkingVisitor::ScheduleIdleLazyCleanup() {
idle_cleanup_task_scheduled_ = true;
}
-void ScriptWrappableMarkingVisitor::PerformLazyCleanup(
- double deadline_seconds) {
+void ScriptWrappableMarkingVisitor::PerformLazyCleanup(TimeTicks deadline) {
idle_cleanup_task_scheduled_ = false;
if (!should_cleanup_)
@@ -124,7 +123,7 @@ void ScriptWrappableMarkingVisitor::PerformLazyCleanup(
TRACE_EVENT1("blink_gc,devtools.timeline",
"ScriptWrappableMarkingVisitor::performLazyCleanup",
"idleDeltaInSeconds",
- deadline_seconds - CurrentTimeTicksInSeconds());
+ (deadline - CurrentTimeTicks()).InSecondsF());
const int kDeadlineCheckInterval = 2500;
int processed_wrapper_count = 0;
@@ -142,7 +141,7 @@ void ScriptWrappableMarkingVisitor::PerformLazyCleanup(
processed_wrapper_count++;
if (processed_wrapper_count % kDeadlineCheckInterval == 0) {
- if (deadline_seconds <= CurrentTimeTicksInSeconds()) {
+ if (deadline <= CurrentTimeTicks()) {
ScheduleIdleLazyCleanup();
return;
}
@@ -173,7 +172,7 @@ void ScriptWrappableMarkingVisitor::RegisterV8Reference(
ScriptWrappable* script_wrappable =
reinterpret_cast<ScriptWrappable*>(internal_fields.second);
- TraceWrappersFromGeneratedCode(script_wrappable);
+ TraceWithWrappers(script_wrappable);
}
void ScriptWrappableMarkingVisitor::RegisterV8References(
@@ -197,13 +196,15 @@ bool ScriptWrappableMarkingVisitor::AdvanceTracing(
CHECK(!ThreadState::Current()->IsWrapperTracingForbidden());
CHECK(tracing_in_progress_);
base::AutoReset<bool>(&advancing_tracing_, true);
+ TimeTicks deadline =
+ TimeTicks() + TimeDelta::FromMillisecondsD(deadline_in_ms);
while (actions.force_completion ==
v8::EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION ||
- WTF::CurrentTimeTicksInMilliseconds() < deadline_in_ms) {
+ WTF::CurrentTimeTicks() < deadline) {
if (marking_deque_.IsEmpty()) {
return false;
}
- marking_deque_.TakeFirst().TraceWrappers(this);
+ marking_deque_.TakeFirst().Trace(this);
}
return true;
}
@@ -228,7 +229,7 @@ void ScriptWrappableMarkingVisitor::WriteBarrier(
// Conservatively assume that the source object containing |dst_object| is
// marked.
- visitor->TraceWrappers(dst_object);
+ visitor->Trace(dst_object);
}
void ScriptWrappableMarkingVisitor::WriteBarrier(
@@ -239,7 +240,7 @@ void ScriptWrappableMarkingVisitor::WriteBarrier(
if (!visitor->WrapperTracingInProgress())
return;
// Conservatively assume that the source object key is marked.
- visitor->TraceWrappers(wrapper_map, key);
+ visitor->Trace(wrapper_map, key);
}
void ScriptWrappableMarkingVisitor::Visit(
@@ -252,24 +253,31 @@ void ScriptWrappableMarkingVisitor::Visit(
traced_wrapper.Get().RegisterExternalReference(isolate_);
}
-void ScriptWrappableMarkingVisitor::Visit(
+void ScriptWrappableMarkingVisitor::VisitWithWrappers(
void* object,
- TraceWrapperDescriptor wrapper_descriptor) {
+ TraceDescriptor descriptor) {
HeapObjectHeader* header =
- HeapObjectHeader::FromPayload(wrapper_descriptor.base_object_payload);
+ HeapObjectHeader::FromPayload(descriptor.base_object_payload);
if (header->IsWrapperHeaderMarked())
return;
MarkWrapperHeader(header);
DCHECK(tracing_in_progress_);
DCHECK(header->IsWrapperHeaderMarked());
- marking_deque_.push_back(MarkingDequeItem(wrapper_descriptor));
+ marking_deque_.push_back(MarkingDequeItem(descriptor));
#if DCHECK_IS_ON()
if (!advancing_tracing_) {
- verifier_deque_.push_back(MarkingDequeItem(wrapper_descriptor));
+ verifier_deque_.push_back(MarkingDequeItem(descriptor));
}
#endif
}
+void ScriptWrappableMarkingVisitor::VisitBackingStoreStrongly(
+ void* object,
+ void** object_slot,
+ TraceDescriptor desc) {
+ desc.callback(this, desc.base_object_payload);
+}
+
void ScriptWrappableMarkingVisitor::Visit(
DOMWrapperMap<ScriptWrappable>* wrapper_map,
const ScriptWrappable* key) {
diff --git a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.h b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.h
index 89384364fd8..4050f645e64 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.h
@@ -11,6 +11,7 @@
#include "third_party/blink/renderer/platform/heap/threading_traits.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
+#include "third_party/blink/renderer/platform/wtf/time.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "v8/include/v8.h"
@@ -35,8 +36,6 @@ class PLATFORM_EXPORT ScriptWrappableMarkingVisitor
public:
static ScriptWrappableMarkingVisitor* CurrentVisitor(v8::Isolate*);
- bool WrapperTracingInProgress() const { return tracing_in_progress_; }
-
// Replace all dead objects in the marking deque with nullptr after Oilpan
// garbage collection.
static void InvalidateDeadObjectsInMarkingDeque(v8::Isolate*);
@@ -48,33 +47,14 @@ class PLATFORM_EXPORT ScriptWrappableMarkingVisitor
//
// On assignment 'x.a = y' during incremental marking the Dijkstra barrier
// suggests checking the color of 'x' and only mark 'y' if 'x' is marked.
-
+ //
// Since checking 'x' is expensive in the current setting, as it requires
// either a back pointer or expensive lookup logic due to large objects and
// multiple inheritance, just assume that 'x' is black. We assume here that
// since an object 'x' is referenced for a write, it will generally also be
// alive in the current GC cycle.
template <typename T>
- static void WriteBarrier(const T* dst_object) {
- if (!ThreadState::IsAnyWrapperTracing() || !dst_object)
- return;
-
- const ThreadState* thread_state =
- ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState();
- DCHECK(thread_state);
- // Bail out if tracing is not in progress.
- if (!thread_state->IsWrapperTracing())
- return;
-
- // If the wrapper is already marked we can bail out here.
- if (TraceTrait<T>::GetHeapObjectHeader(const_cast<T*>(dst_object))
- ->IsWrapperHeaderMarked())
- return;
-
- CurrentVisitor(thread_state->GetIsolate())
- ->Visit(const_cast<T*>(dst_object),
- TraceWrapperDescriptorFor(dst_object));
- }
+ inline static void WriteBarrier(const T* dst_object);
static void WriteBarrier(v8::Isolate*,
const TraceWrapperV8Reference<v8::Value>&);
@@ -86,6 +66,8 @@ class PLATFORM_EXPORT ScriptWrappableMarkingVisitor
ScriptWrappableMarkingVisitor(v8::Isolate* isolate) : isolate_(isolate){};
~ScriptWrappableMarkingVisitor() override;
+ bool WrapperTracingInProgress() const { return tracing_in_progress_; }
+
// v8::EmbedderHeapTracer interface.
void TracePrologue() override;
@@ -99,11 +81,15 @@ class PLATFORM_EXPORT ScriptWrappableMarkingVisitor
void EnterFinalPause() override;
size_t NumberOfWrappersToTrace() override;
- // Visitor interface.
+ // ScriptWrappableVisitor interface.
+
void Visit(const TraceWrapperV8Reference<v8::Value>&) override;
- void Visit(void*, TraceWrapperDescriptor) override;
+ void VisitWithWrappers(void*, TraceDescriptor) override;
void Visit(DOMWrapperMap<ScriptWrappable>*,
const ScriptWrappable* key) override;
+ void VisitBackingStoreStrongly(void* object,
+ void** object_slot,
+ TraceDescriptor desc) override;
protected:
using Visitor::Visit;
@@ -113,18 +99,17 @@ class PLATFORM_EXPORT ScriptWrappableMarkingVisitor
private:
class MarkingDequeItem {
public:
- explicit MarkingDequeItem(const TraceWrapperDescriptor& wrapper_descriptor)
- : raw_object_pointer_(wrapper_descriptor.base_object_payload),
- trace_wrappers_callback_(wrapper_descriptor.trace_wrappers_callback) {
+ explicit MarkingDequeItem(const TraceDescriptor& descriptor)
+ : raw_object_pointer_(descriptor.base_object_payload),
+ trace_callback_(descriptor.callback) {
DCHECK(raw_object_pointer_);
- DCHECK(trace_wrappers_callback_);
+ DCHECK(trace_callback_);
}
// Traces wrappers if the underlying object has not yet been invalidated.
- inline void TraceWrappers(ScriptWrappableVisitor* visitor) const {
+ inline void Trace(ScriptWrappableVisitor* visitor) const {
if (raw_object_pointer_) {
- trace_wrappers_callback_(visitor,
- const_cast<void*>(raw_object_pointer_));
+ trace_callback_(visitor, const_cast<void*>(raw_object_pointer_));
}
}
@@ -136,7 +121,7 @@ class PLATFORM_EXPORT ScriptWrappableMarkingVisitor
return raw_object_pointer_ && !GetHeapObjectHeader()->IsMarked();
}
- // Invalidates the current wrapper marking data, i.e., calling TraceWrappers
+ // Invalidates the current wrapper marking data, i.e., calling Trace
// will result in a noop.
inline void Invalidate() { raw_object_pointer_ = nullptr; }
@@ -146,7 +131,7 @@ class PLATFORM_EXPORT ScriptWrappableMarkingVisitor
}
const void* raw_object_pointer_;
- TraceWrappersCallback trace_wrappers_callback_;
+ TraceCallback trace_callback_;
};
void MarkWrapperHeader(HeapObjectHeader*);
@@ -154,7 +139,7 @@ class PLATFORM_EXPORT ScriptWrappableMarkingVisitor
// Schedule an idle task to perform a lazy (incremental) clean up of
// wrappers.
void ScheduleIdleLazyCleanup();
- void PerformLazyCleanup(double deadline_seconds);
+ void PerformLazyCleanup(TimeTicks deadline);
void InvalidateDeadObjectsInMarkingDeque();
@@ -228,6 +213,28 @@ class PLATFORM_EXPORT ScriptWrappableMarkingVisitor
WriteBarrierOnHeapVectorSwap2);
};
+template <typename T>
+inline void ScriptWrappableMarkingVisitor::WriteBarrier(const T* dst_object) {
+ if (!ThreadState::IsAnyWrapperTracing() || !dst_object)
+ return;
+
+ const ThreadState* thread_state =
+ ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState();
+ DCHECK(thread_state);
+ // Bail out if tracing is not in progress.
+ if (!thread_state->IsWrapperTracing())
+ return;
+
+ // If the wrapper is already marked we can bail out here.
+ if (TraceTrait<T>::GetHeapObjectHeader(const_cast<T*>(dst_object))
+ ->IsWrapperHeaderMarked())
+ return;
+
+ CurrentVisitor(thread_state->GetIsolate())
+ ->VisitWithWrappers(const_cast<T*>(dst_object),
+ TraceDescriptorFor(dst_object));
+}
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCRIPT_WRAPPABLE_MARKING_VISITOR_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_visitor.cc b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_visitor.cc
deleted file mode 100644
index af91f849cf2..00000000000
--- a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_visitor.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/bindings/script_wrappable_visitor.h"
-
-#include "third_party/blink/renderer/platform/bindings/dom_wrapper_map.h"
-#include "third_party/blink/renderer/platform/bindings/trace_wrapper_base.h"
-#include "third_party/blink/renderer/platform/supplementable.h"
-
-namespace blink {
-
-void ScriptWrappableVisitor::TraceWrappers(
- DOMWrapperMap<ScriptWrappable>* wrapper_map,
- const ScriptWrappable* key) {
- Visit(wrapper_map, key);
-}
-
-void ScriptWrappableVisitor::DispatchTraceWrappers(
- TraceWrapperBase* wrapper_base) {
- wrapper_base->TraceWrappers(this);
-}
-
-void ScriptWrappableVisitor::DispatchTraceWrappersForSupplement(
- TraceWrapperBaseForSupplement* wrapper_base) {
- wrapper_base->TraceWrappers(this);
-}
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_visitor.h b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_visitor.h
index 63e83d2bbd1..4caa74fcc81 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_visitor.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_visitor.h
@@ -5,102 +5,18 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCRIPT_WRAPPABLE_VISITOR_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCRIPT_WRAPPABLE_VISITOR_H_
-#include "third_party/blink/renderer/platform/bindings/trace_wrapper_base.h"
-#include "third_party/blink/renderer/platform/heap/heap_page.h"
-#include "third_party/blink/renderer/platform/heap/threading_traits.h"
#include "third_party/blink/renderer/platform/heap/visitor.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/deque.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-#include "v8/include/v8.h"
namespace blink {
-template <typename T>
-class DOMWrapperMap;
-class ScriptWrappable;
-class ScriptWrappableVisitor;
-template <typename T>
-class Supplement;
-class TraceWrapperBase;
-class TraceWrapperBaseForSupplement;
-template <typename T>
-class TraceWrapperV8Reference;
-
-#define DEFINE_TRAIT_FOR_TRACE_WRAPPERS(ClassName) \
- template <> \
- inline void TraceTrait<ClassName>::TraceWrappers( \
- ScriptWrappableVisitor* visitor, void* t) { \
- static_assert(sizeof(ClassName), "type needs to be defined"); \
- static_assert(IsGarbageCollectedType<ClassName>::value, \
- "only objects deriving from GarbageCollected can be used"); \
- static_cast<ClassName*>(t)->TraceWrappers(visitor); \
- }
-
-// Abstract visitor for wrapper references in a ScriptWrappable.
-// Usage:
-// - Define a derived class that overrides Visit(..) methods.
-// - Create an instance of the derived class: visitor.
-// - Call visitor.DispatchTraceWrappers(traceable).
-// DispatchTraceWrappers will invoke Visit() method for all
-// wrapper references in traceable.
+// Abstract visitor for visiting ScriptWrappable. Inherit from this
+// visitor and implement the remaining Visit*() methods to visit all
+// references related to wrappers.
class PLATFORM_EXPORT ScriptWrappableVisitor : public Visitor {
public:
ScriptWrappableVisitor() : Visitor(ThreadState::Current()) {}
- // Trace all wrappers of |tracable|.
- //
- // If you cannot use TraceWrapperMember & the corresponding TraceWrappers()
- // for some reason (e.g., unions using raw pointers), see
- // |TraceWrappersWithManualWriteBarrier()| below.
- template <typename T>
- void TraceWrappers(const TraceWrapperMember<T>& traceable) {
- static_assert(sizeof(T), "T must be fully defined");
- Visit(traceable.Get());
- }
-
- // Enable partial tracing of objects. This is used when tracing interior
- // objects without their own header.
- template <typename T>
- void TraceWrappers(const T& traceable) {
- static_assert(sizeof(T), "T must be fully defined");
- traceable.TraceWrappers(this);
- }
-
- // Only called from automatically generated bindings code.
- template <typename T>
- void TraceWrappersFromGeneratedCode(const T* traceable) {
- Visit(traceable);
- }
-
- // Require all users of manual write barriers to make this explicit in their
- // |TraceWrappers| definition. Be sure to add
- // |ScriptWrappableMarkingVisitor::WriteBarrier(new_value)| after all
- // assignments to the field. Otherwise, the objects may be collected
- // prematurely.
- template <typename T>
- void TraceWrappersWithManualWriteBarrier(const T* traceable) {
- Visit(traceable);
- }
-
- template <typename V8Type>
- void TraceWrappers(const TraceWrapperV8Reference<V8Type>& v8reference) {
- Visit(v8reference.template Cast<v8::Value>());
- }
-
- // Trace wrappers in non-main worlds.
- void TraceWrappers(DOMWrapperMap<ScriptWrappable>*,
- const ScriptWrappable* key);
-
- virtual void DispatchTraceWrappers(TraceWrapperBase*);
- template <typename T>
- void DispatchTraceWrappers(Supplement<T>* traceable) {
- TraceWrapperBaseForSupplement* base = traceable;
- DispatchTraceWrappersForSupplement(base);
- }
- // Catch all handlers needed because of mixins except for Supplement<T>.
- void DispatchTraceWrappers(const void*) const { CHECK(false); }
-
// Unused blink::Visitor overrides. Derived visitors should still override
// the cross-component visitation methods. See Visitor documentation.
void Visit(void* object, TraceDescriptor desc) final {}
@@ -108,7 +24,6 @@ class PLATFORM_EXPORT ScriptWrappableVisitor : public Visitor {
void** object_slot,
TraceDescriptor desc,
WeakCallback callback) final {}
- void VisitBackingStoreStrongly(void*, void**, TraceDescriptor) final {}
void VisitBackingStoreWeakly(void*,
void**,
TraceDescriptor,
@@ -120,21 +35,6 @@ class PLATFORM_EXPORT ScriptWrappableVisitor : public Visitor {
protected:
using Visitor::Visit;
-
- private:
- // Helper method to invoke the virtual Visit method with wrapper descriptor.
- template <typename T>
- void Visit(const T* traceable) {
- static_assert(sizeof(T), "T must be fully defined");
- if (!traceable)
- return;
- Visit(const_cast<T*>(traceable), TraceWrapperDescriptorFor(traceable));
- }
-
- // Supplement-specific implementation of DispatchTraceWrappers. The suffix of
- // "ForSupplement" is necessary not to make this member function a candidate
- // of overload resolutions.
- void DispatchTraceWrappersForSupplement(TraceWrapperBaseForSupplement*);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_visitor_verifier.h b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_visitor_verifier.h
index 65c6b99ef79..84724bc686d 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_visitor_verifier.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/script_wrappable_visitor_verifier.h
@@ -18,16 +18,16 @@ class ScriptWrappableVisitorVerifier final : public ScriptWrappableVisitor {
public:
void Visit(const TraceWrapperV8Reference<v8::Value>&) final {}
- void Visit(void* object, TraceWrapperDescriptor descriptor) final {
+ void VisitWithWrappers(void* object, TraceDescriptor descriptor) final {
HeapObjectHeader* header =
HeapObjectHeader::FromPayload(descriptor.base_object_payload);
const char* name = GCInfoTable::Get()
.GCInfoFromIndex(header->GcInfoIndex())
->name_(descriptor.base_object_payload);
// If this FATAL is hit, it means that a white (not discovered by
- // TraceWrappers) object was assigned as a member to a black object (already
- // processed by TraceWrappers). The black object will not be processed
- // anymore so white object will remain undetected and therefore its wrapper
+ // Trace) object was assigned as a member to a black object (already
+ // processed by Trace). The black object will not be processed anymore
+ // so white object will remain undetected and therefore its wrapper
// and all wrappers reachable from it would be collected.
//
// This means there is a write barrier missing somewhere. Check the
@@ -40,6 +40,10 @@ class ScriptWrappableVisitorVerifier final : public ScriptWrappableVisitor {
void Visit(DOMWrapperMap<ScriptWrappable>*,
const ScriptWrappable* key) final {}
+ void VisitBackingStoreStrongly(void* object,
+ void** object_slot,
+ TraceDescriptor desc) final {}
+
protected:
using Visitor::Visit;
};
diff --git a/chromium/third_party/blink/renderer/platform/bindings/string_resource.cc b/chromium/third_party/blink/renderer/platform/bindings/string_resource.cc
index 3d973cda4a9..3be41ac09ee 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/string_resource.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/string_resource.cc
@@ -18,7 +18,7 @@ struct StringTraits {
template <>
struct StringTraits<String> {
static const String& FromStringResource(StringResourceBase* resource) {
- return resource->WebcoreString();
+ return resource->GetWTFString();
}
template <typename V8StringTrait>
static String FromV8String(v8::Local<v8::String>, int);
@@ -26,7 +26,7 @@ struct StringTraits<String> {
template <>
struct StringTraits<AtomicString> {
- static const AtomicString& FromStringResource(StringResourceBase* resource) {
+ static const AtomicString FromStringResource(StringResourceBase* resource) {
return resource->GetAtomicString();
}
template <typename V8StringTrait>
@@ -71,7 +71,7 @@ AtomicString StringTraits<AtomicString>::FromV8String(
if (length <= kInlineBufferSize) {
typename V8StringTrait::CharType inline_buffer[kInlineBufferSize];
V8StringTrait::Write(v8_string, inline_buffer, length);
- return AtomicString(inline_buffer, length);
+ return AtomicString(inline_buffer, static_cast<unsigned>(length));
}
typename V8StringTrait::CharType* buffer;
String string = String::CreateUninitialized(length, buffer);
@@ -80,8 +80,8 @@ AtomicString StringTraits<AtomicString>::FromV8String(
}
template <typename StringType>
-StringType V8StringToWebCoreString(v8::Local<v8::String> v8_string,
- ExternalMode external) {
+StringType ToBlinkString(v8::Local<v8::String> v8_string,
+ ExternalMode external) {
{
// This portion of this function is very hot in certain Dromeao benchmarks.
v8::String::Encoding encoding;
@@ -125,14 +125,12 @@ StringType V8StringToWebCoreString(v8::Local<v8::String> v8_string,
// Explicitly instantiate the above template with the expected
// parameterizations, to ensure the compiler generates the code; otherwise link
// errors can result in GCC 4.4.
-template String V8StringToWebCoreString<String>(v8::Local<v8::String>,
- ExternalMode);
-template AtomicString V8StringToWebCoreString<AtomicString>(
- v8::Local<v8::String>,
- ExternalMode);
+template String ToBlinkString<String>(v8::Local<v8::String>, ExternalMode);
+template AtomicString ToBlinkString<AtomicString>(v8::Local<v8::String>,
+ ExternalMode);
// Fast but non thread-safe version.
-String Int32ToWebCoreStringFast(int value) {
+static String ToBlinkStringFast(int value) {
// Caching of small strings below is not thread safe: newly constructed
// AtomicString are not safely published.
DCHECK(IsMainThread());
@@ -155,11 +153,11 @@ String Int32ToWebCoreStringFast(int value) {
return web_core_string;
}
-String Int32ToWebCoreString(int value) {
+String ToBlinkString(int value) {
// If we are on the main thread (this should always true for non-workers),
// call the faster one.
if (IsMainThread())
- return Int32ToWebCoreStringFast(value);
+ return ToBlinkStringFast(value);
return String::Number(value);
}
diff --git a/chromium/third_party/blink/renderer/platform/bindings/string_resource.h b/chromium/third_party/blink/renderer/platform/bindings/string_resource.h
index 9a8a6b6bda7..41b0f5a2a59 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/string_resource.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/string_resource.h
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+#include "third_party/blink/renderer/platform/wtf/text/movable_string.h"
#include "third_party/blink/renderer/platform/wtf/threading.h"
#include "v8/include/v8.h"
@@ -39,6 +40,17 @@ class StringResourceBase {
string.CharactersSizeInBytes());
}
+ explicit StringResourceBase(const MovableString& string)
+ : movable_string_(string) {
+#if DCHECK_IS_ON()
+ thread_id_ = WTF::CurrentThread();
+#endif
+ // TODO(lizeb): This is only true without compression.
+ DCHECK(!string.IsNull());
+ v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(
+ string.CharactersSizeInBytes());
+ }
+
virtual ~StringResourceBase() {
#if DCHECK_IS_ON()
DCHECK(thread_id_ == WTF::CurrentThread());
@@ -51,12 +63,24 @@ class StringResourceBase {
-reduced_external_memory);
}
- const String& WebcoreString() { return plain_string_; }
+ const String& GetWTFString() {
+ if (!movable_string_.IsNull()) {
+ DCHECK(plain_string_.IsNull());
+ DCHECK(atomic_string_.IsNull());
+ return movable_string_.ToString();
+ }
+ return plain_string_;
+ }
- const AtomicString& GetAtomicString() {
+ AtomicString GetAtomicString() {
#if DCHECK_IS_ON()
DCHECK(thread_id_ == WTF::CurrentThread());
#endif
+ if (!movable_string_.IsNull()) {
+ DCHECK(plain_string_.IsNull());
+ DCHECK(atomic_string_.IsNull());
+ return AtomicString(movable_string_.ToString());
+ }
if (atomic_string_.IsNull()) {
atomic_string_ = AtomicString(plain_string_);
DCHECK(!atomic_string_.IsNull());
@@ -78,6 +102,9 @@ class StringResourceBase {
// the original string alive because v8 may keep derived pointers
// into that string.
AtomicString atomic_string_;
+ // If this string is movable, its value is held here, and the other
+ // members above are null.
+ MovableString movable_string_;
private:
#if DCHECK_IS_ON()
@@ -128,12 +155,53 @@ class StringResource8 final : public StringResourceBase,
DISALLOW_COPY_AND_ASSIGN(StringResource8);
};
+class MovableStringResource16 final
+ : public StringResourceBase,
+ public v8::String::ExternalStringResource {
+ public:
+ explicit MovableStringResource16(const MovableString& string)
+ : StringResourceBase(string) {
+ DCHECK(!movable_string_.Is8Bit());
+ }
+
+ // V8 external resources are "compressible", not "movable".
+ bool IsCompressible() const override { return true; }
+
+ size_t length() const override { return movable_string_.length(); }
+
+ const uint16_t* data() const override {
+ return reinterpret_cast<const uint16_t*>(movable_string_.Characters16());
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(MovableStringResource16);
+};
+
+class MovableStringResource8 final
+ : public StringResourceBase,
+ public v8::String::ExternalOneByteStringResource {
+ public:
+ explicit MovableStringResource8(const MovableString& string)
+ : StringResourceBase(string) {
+ DCHECK(movable_string_.Is8Bit());
+ }
+
+ // V8 external resources are "compressible", not "movable".
+ bool IsCompressible() const override { return true; }
+
+ size_t length() const override { return movable_string_.length(); }
+
+ const char* data() const override {
+ return reinterpret_cast<const char*>(movable_string_.Characters8());
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(MovableStringResource8);
+};
+
enum ExternalMode { kExternalize, kDoNotExternalize };
template <typename StringType>
-PLATFORM_EXPORT StringType V8StringToWebCoreString(v8::Local<v8::String>,
- ExternalMode);
-PLATFORM_EXPORT String Int32ToWebCoreString(int value);
+PLATFORM_EXPORT StringType ToBlinkString(v8::Local<v8::String>, ExternalMode);
+PLATFORM_EXPORT String ToBlinkString(int value);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/to_v8.h b/chromium/third_party/blink/renderer/platform/bindings/to_v8.h
index e0a9e26a102..1595d8dec5d 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/to_v8.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/to_v8.h
@@ -16,7 +16,6 @@
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "v8/include/v8.h"
@@ -81,7 +80,7 @@ inline v8::Local<v8::Value> ToV8SignedIntegerInternal<8>(int64_t value,
v8::Isolate* isolate) {
int32_t value_in32_bit = static_cast<int32_t>(value);
if (value_in32_bit == value)
- return v8::Integer::New(isolate, value);
+ return v8::Integer::New(isolate, value_in32_bit);
// V8 doesn't have a 64-bit integer implementation.
return v8::Number::New(isolate, value);
}
@@ -103,7 +102,7 @@ inline v8::Local<v8::Value> ToV8UnsignedIntegerInternal<8>(
v8::Isolate* isolate) {
uint32_t value_in32_bit = static_cast<uint32_t>(value);
if (value_in32_bit == value)
- return v8::Integer::NewFromUnsigned(isolate, value);
+ return v8::Integer::NewFromUnsigned(isolate, value_in32_bit);
// V8 doesn't have a 64-bit integer implementation.
return v8::Number::New(isolate, value);
}
diff --git a/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_base.h b/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_base.h
deleted file mode 100644
index e35a12dcb13..00000000000
--- a/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_base.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_TRACE_WRAPPER_BASE_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_TRACE_WRAPPER_BASE_H_
-
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
-
-namespace blink {
-
-class ScriptWrappableVisitor;
-
-class PLATFORM_EXPORT TraceWrapperBase {
- WTF_MAKE_NONCOPYABLE(TraceWrapperBase);
-
- public:
- TraceWrapperBase() = default;
- ~TraceWrapperBase() = default;
- virtual bool IsScriptWrappable() const { return false; }
-
- virtual void TraceWrappers(ScriptWrappableVisitor*) const = 0;
-
- // Human-readable name of this object. The DevTools heap snapshot uses
- // this method to show the object.
- virtual const char* NameInHeapSnapshot() const = 0;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_TRACE_WRAPPER_BASE_H_
diff --git a/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_member.h b/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_member.h
index 2d4dd707a7e..2c3a489e016 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_member.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_member.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_TRACE_WRAPPER_MEMBER_H_
#include "third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.h"
-#include "third_party/blink/renderer/platform/bindings/trace_wrapper_base.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
namespace blink {
@@ -16,14 +15,10 @@ class Member;
// TraceWrapperMember is used for Member fields that should participate in
// wrapper tracing, i.e., strongly hold a ScriptWrappable alive. All
-// TraceWrapperMember fields must be traced in the class' |TraceWrappers|
-// method.
+// TraceWrapperMember fields must be traced in the class' |Trace| method.
template <class T>
class TraceWrapperMember : public Member<T> {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
- // TODO(mlippautz): Enable the following check.
- // static_assert(std::is_base_of<TraceWrapperBase, T>::value,
- // "T must inherit from TraceWrapperBase");
public:
TraceWrapperMember() : Member<T>(nullptr) {}
diff --git a/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h b/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h
index 3584abdb153..6b8aa95de27 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h
@@ -10,9 +10,8 @@
namespace blink {
/**
- * TraceWrapperV8Reference is used to trace from Blink to V8. If wrapper
- * tracing is disabled, the reference is a weak v8::Persistent. Otherwise,
- * the reference is (strongly) traced by wrapper tracing.
+ * TraceWrapperV8Reference is used to trace from Blink to V8. The reference is
+ * (strongly) traced by wrapper tracing.
*
* TODO(mlippautz): Use a better handle type than v8::Persistent.
*/
@@ -58,8 +57,7 @@ class TraceWrapperV8Reference {
return reinterpret_cast<const TraceWrapperV8Reference<S>&>(
const_cast<const TraceWrapperV8Reference<T>&>(*this));
}
- // TODO(mlippautz): Support TraceWrappers(const
- // TraceWrapperV8Reference<v8::Module>&) and remove UnsafeCast.
+
template <typename S>
const TraceWrapperV8Reference<S>& UnsafeCast() const {
return reinterpret_cast<const TraceWrapperV8Reference<S>&>(
diff --git a/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_string.cc b/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_string.cc
index 3fd53edc211..af5b491f2b3 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_string.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_string.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_string.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -22,8 +23,7 @@ String TraceWrapperV8String::Flatten(v8::Isolate* isolate) const {
return String();
DCHECK(isolate);
v8::HandleScope handle_scope(isolate);
- return V8StringToWebCoreString<String>(string_.NewLocal(isolate),
- kExternalize);
+ return ToBlinkString<String>(string_.NewLocal(isolate), kExternalize);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_string.h b/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_string.h
index 557870aded6..5af791f5332 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_string.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/trace_wrapper_v8_string.h
@@ -5,9 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_TRACE_WRAPPER_V8_STRING_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_TRACE_WRAPPER_V8_STRING_H_
-#include "third_party/blink/renderer/platform/bindings/trace_wrapper_base.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "v8/include/v8.h"
namespace blink {
@@ -15,7 +15,8 @@ namespace blink {
// Small shim around TraceWrapperReference<v8::String> with a few
// utility methods. Internally, v8::String is represented as string
// rope.
-class PLATFORM_EXPORT TraceWrapperV8String final : public TraceWrapperBase {
+class GC_PLUGIN_IGNORE("crbug.com/841830")
+ PLATFORM_EXPORT TraceWrapperV8String final : public NameClient {
DISALLOW_COPY_AND_ASSIGN(TraceWrapperV8String);
DISALLOW_NEW();
@@ -32,9 +33,8 @@ class PLATFORM_EXPORT TraceWrapperV8String final : public TraceWrapperBase {
void Concat(v8::Isolate*, const String&);
String Flatten(v8::Isolate*) const;
- void TraceWrappers(ScriptWrappableVisitor* visitor) const override {
- visitor->TraceWrappers(string_);
- }
+ virtual void Trace(Visitor* visitor) { visitor->Trace(string_); }
+
const char* NameInHeapSnapshot() const override {
return "TraceWrapperV8String";
}
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_binding.h b/chromium/third_party/blink/renderer/platform/bindings/v8_binding.h
index 54b6db45c3e..180bc217978 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_binding.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_binding.h
@@ -39,10 +39,9 @@
#include "third_party/blink/renderer/platform/bindings/v8_binding_macros.h"
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/bindings/v8_value_cache.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_view.h"
#include "v8/include/v8.h"
namespace blink {
@@ -217,7 +216,7 @@ inline void V8SetReturnValueFast(const CallbackInfo& callback_info,
// an external string then it is transformed into an external string at this
// point to avoid repeated conversions.
inline String ToCoreString(v8::Local<v8::String> value) {
- return V8StringToWebCoreString<String>(value, kExternalize);
+ return ToBlinkString<String>(value, kExternalize);
}
inline String ToCoreStringWithNullCheck(v8::Local<v8::String> value) {
@@ -234,7 +233,7 @@ inline String ToCoreStringWithUndefinedOrNullCheck(
}
inline AtomicString ToCoreAtomicString(v8::Local<v8::String> value) {
- return V8StringToWebCoreString<AtomicString>(value, kExternalize);
+ return ToBlinkString<AtomicString>(value, kExternalize);
}
// This method will return a null String if the v8::Value does not contain a
@@ -291,6 +290,14 @@ inline v8::Local<v8::Value> V8StringOrNull(v8::Isolate* isolate,
isolate, string.Impl());
}
+inline v8::Local<v8::String> V8String(v8::Isolate* isolate,
+ const MovableString& string) {
+ if (string.IsNull())
+ return v8::String::Empty(isolate);
+ return V8PerIsolateData::From(isolate)->GetStringCache()->V8ExternalString(
+ isolate, string);
+}
+
inline v8::Local<v8::String> V8AtomicString(v8::Isolate* isolate,
const StringView& string) {
DCHECK(isolate);
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_dom_activity_logger.cc b/chromium/third_party/blink/renderer/platform/bindings/v8_dom_activity_logger.cc
index 39c7b4c3800..5a2f20c489a 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_dom_activity_logger.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_dom_activity_logger.cc
@@ -6,6 +6,7 @@
#include <memory>
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
+#include "third_party/blink/renderer/platform/bindings/v8_per_context_data.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/text/string_hash.h"
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h b/chromium/third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h
index 6be7ed51cb9..dbcdd80a548 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h
@@ -31,6 +31,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_DOM_WRAPPER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_V8_DOM_WRAPPER_H_
+#include "base/stl_util.h"
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
#include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
@@ -90,7 +91,7 @@ inline void V8DOMWrapper::SetNativeInfo(
int indices[] = {kV8DOMWrapperObjectIndex, kV8DOMWrapperTypeIndex};
void* values[] = {script_wrappable,
const_cast<WrapperTypeInfo*>(wrapper_type_info)};
- wrapper->SetAlignedPointerInInternalFields(arraysize(indices), indices,
+ wrapper->SetAlignedPointerInInternalFields(base::size(indices), indices,
values);
auto* per_isolate_data = V8PerIsolateData::From(isolate);
// We notify ScriptWrappableVisitor about the new wrapper association,
@@ -106,7 +107,7 @@ inline void V8DOMWrapper::ClearNativeInfo(v8::Isolate* isolate,
v8::Local<v8::Object> wrapper) {
int indices[] = {kV8DOMWrapperObjectIndex, kV8DOMWrapperTypeIndex};
void* values[] = {nullptr, nullptr};
- wrapper->SetAlignedPointerInInternalFields(arraysize(indices), indices,
+ wrapper->SetAlignedPointerInInternalFields(base::size(indices), indices,
values);
}
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_per_context_data.cc b/chromium/third_party/blink/renderer/platform/bindings/v8_per_context_data.cc
index 6116a9471e7..70b71cff50e 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_per_context_data.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_per_context_data.cc
@@ -37,8 +37,10 @@
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/platform/bindings/origin_trial_features.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/bindings/v0_custom_element_binding.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "third_party/blink/renderer/platform/bindings/v8_object_constructor.h"
+#include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h"
#include "third_party/blink/renderer/platform/instance_counters.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_per_context_data.h b/chromium/third_party/blink/renderer/platform/bindings/v8_per_context_data.h
index 939b5f71fd1..750773b1a42 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_per_context_data.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_per_context_data.h
@@ -36,9 +36,8 @@
#include "gin/public/context_holder.h"
#include "gin/public/gin_embedders.h"
#include "third_party/blink/renderer/platform/bindings/scoped_persistent.h"
-#include "third_party/blink/renderer/platform/bindings/v0_custom_element_binding.h"
#include "third_party/blink/renderer/platform/bindings/v8_global_value_map.h"
-#include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
@@ -49,14 +48,10 @@
namespace blink {
+class V0CustomElementBinding;
class V8DOMActivityLogger;
class V8PerContextData;
-
-enum V8ContextEmbedderDataField {
- kV8ContextPerContextDataIndex = static_cast<int>(
- gin::kPerContextDataStartIndex + // NOLINT(readability/enum_casing)
- gin::kEmbedderBlink), // NOLINT(readability/enum_casing)
-};
+struct WrapperTypeInfo;
// Used to hold data that is associated with a single v8::Context object, and
// has a 1:1 relationship with v8::Context.
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc b/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc
index 108efb6d07e..44cb5a9489f 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.cc
@@ -28,10 +28,16 @@
#include <memory>
#include <utility>
+#include "base/single_thread_task_runner.h"
+#include "base/time/default_tick_clock.h"
+#include "gin/public/v8_idle_task_runner.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/public/web/blink.h"
+#include "third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h"
#include "third_party/blink/renderer/platform/bindings/dom_data_store.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_binding.h"
#include "third_party/blink/renderer/platform/bindings/v8_object_constructor.h"
#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h b/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h
index 5b22a053a3e..7788274e57c 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h
@@ -29,31 +29,32 @@
#include <memory>
#include "base/single_thread_task_runner.h"
-#include "base/time/default_tick_clock.h"
+#include "gin/public/gin_embedders.h"
#include "gin/public/isolate_holder.h"
-#include "gin/public/v8_idle_task_runner.h"
#include "third_party/blink/renderer/platform/bindings/runtime_call_stats.h"
#include "third_party/blink/renderer/platform/bindings/scoped_persistent.h"
-#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable_marking_visitor.h"
-#include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h"
+#include "third_party/blink/renderer/platform/bindings/v8_global_value_map.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "v8/include/v8.h"
+namespace base {
+class SingleThreadTaskRunner;
+}
+
namespace blink {
class ActiveScriptWrappableBase;
-class DOMDataStore;
+class DOMWrapperWorld;
+class ScriptState;
class StringCache;
class V8PrivateProperty;
struct WrapperTypeInfo;
-typedef WTF::Vector<DOMDataStore*> DOMDataStoreList;
-
// Used to hold data that is associated with a single v8::Isolate object, and
// has a 1:1 relationship with v8::Isolate.
class PLATFORM_EXPORT V8PerIsolateData {
@@ -290,7 +291,7 @@ class PLATFORM_EXPORT V8PerIsolateData {
std::unique_ptr<StringCache> string_cache_;
std::unique_ptr<V8PrivateProperty> private_property_;
- scoped_refptr<ScriptState> script_regexp_script_state_;
+ Persistent<ScriptState> script_regexp_script_state_;
bool constructor_mode_;
friend class ConstructorMode;
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_private_property.h b/chromium/third_party/blink/renderer/platform/bindings/v8_private_property.h
index 128bd766433..34ac38312c8 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_private_property.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_private_property.h
@@ -20,8 +20,7 @@ namespace blink {
class ScriptWrappable;
// TODO(peria): Remove properties just to keep V8 objects alive.
-// e.g. InternalBody.Buffer, InternalBody.Stream, IDBCursor.Request,
-// FetchEvent.Request.
+// e.g. IDBCursor.Request.
// Apply |X| for each pair of (InterfaceName, PrivateKeyName).
#define V8_PRIVATE_PROPERTY_FOR_EACH(X) \
X(CustomElement, Document) \
@@ -35,11 +34,8 @@ class ScriptWrappable;
X(CustomElementLifecycle, DetachedCallback) \
X(DOMException, Error) \
X(ErrorEvent, Error) \
- X(FetchEvent, Request) \
X(Global, Event) \
X(IDBCursor, Request) \
- X(InternalBody, Buffer) \
- X(InternalBody, Stream) \
X(IntersectionObserver, Callback) \
X(MessageChannel, Port1) \
X(MessageChannel, Port2) \
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_value_cache.cc b/chromium/third_party/blink/renderer/platform/bindings/v8_value_cache.cc
index c80e76ab2a4..7fe6873e2e5 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_value_cache.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_value_cache.cc
@@ -61,6 +61,28 @@ void StringCacheMapTraits::OnWeakCallback(
->InvalidateLastString();
}
+MovableStringCacheMapTraits::MapType*
+MovableStringCacheMapTraits::MapFromWeakCallbackInfo(
+ const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
+ return &(V8PerIsolateData::From(data.GetIsolate())
+ ->GetStringCache()
+ ->movable_string_cache_);
+}
+
+void MovableStringCacheMapTraits::Dispose(v8::Isolate* isolate,
+ v8::Global<v8::String> value,
+ MovableStringImpl* key) {
+ key->Release();
+}
+
+void MovableStringCacheMapTraits::DisposeWeak(
+ const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
+ data.GetParameter()->Release();
+}
+
+void MovableStringCacheMapTraits::OnWeakCallback(
+ const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {}
+
void StringCache::Dispose() {
// The MapType::Dispose callback calls StringCache::InvalidateLastString,
// which will only work while the destructor has not yet finished. Thus,
@@ -91,6 +113,29 @@ static v8::Local<v8::String> MakeExternalString(v8::Isolate* isolate,
return new_string;
}
+static v8::Local<v8::String> MakeExternalString(v8::Isolate* isolate,
+ const MovableString& string) {
+ if (string.Is8Bit()) {
+ auto* string_resource = new MovableStringResource8(string);
+ v8::Local<v8::String> new_string;
+ if (!v8::String::NewExternalOneByte(isolate, string_resource)
+ .ToLocal(&new_string)) {
+ delete string_resource;
+ return v8::String::Empty(isolate);
+ }
+ return new_string;
+ }
+
+ auto* string_resource = new MovableStringResource16(string);
+ v8::Local<v8::String> new_string;
+ if (!v8::String::NewExternalTwoByte(isolate, string_resource)
+ .ToLocal(&new_string)) {
+ delete string_resource;
+ return v8::String::Empty(isolate);
+ }
+ return new_string;
+}
+
v8::Local<v8::String> StringCache::V8ExternalStringSlow(
v8::Isolate* isolate,
StringImpl* string_impl) {
@@ -110,6 +155,21 @@ v8::Local<v8::String> StringCache::V8ExternalStringSlow(
return CreateStringAndInsertIntoCache(isolate, string_impl);
}
+v8::Local<v8::String> StringCache::V8ExternalString(
+ v8::Isolate* isolate,
+ const MovableString& string) {
+ if (!string.length())
+ return v8::String::Empty(isolate);
+
+ MovableStringCacheMapTraits::MapType::PersistentValueReference
+ cached_v8_string = movable_string_cache_.GetReference(string.Impl());
+ if (!cached_v8_string.IsEmpty()) {
+ return cached_v8_string.NewLocal(isolate);
+ }
+
+ return CreateStringAndInsertIntoCache(isolate, string);
+}
+
void StringCache::SetReturnValueFromStringSlow(
v8::ReturnValue<v8::Value> return_value,
StringImpl* string_impl) {
@@ -154,6 +214,29 @@ v8::Local<v8::String> StringCache::CreateStringAndInsertIntoCache(
return new_string;
}
+v8::Local<v8::String> StringCache::CreateStringAndInsertIntoCache(
+ v8::Isolate* isolate,
+ const MovableString& string) {
+ MovableStringImpl* string_impl = string.Impl();
+ DCHECK(!movable_string_cache_.Contains(string_impl));
+ DCHECK(string_impl->length());
+
+ v8::Local<v8::String> new_string =
+ MakeExternalString(isolate, MovableString(string));
+ DCHECK(!new_string.IsEmpty());
+ DCHECK(new_string->Length());
+
+ v8::UniquePersistent<v8::String> wrapper(isolate, new_string);
+
+ string_impl->AddRef();
+ // MovableStringImpl objects are not cache in |string_cache_| or
+ // |last_string_impl_|.
+ MovableStringCacheMapTraits::MapType::PersistentValueReference unused;
+ movable_string_cache_.Set(string_impl, std::move(wrapper), &unused);
+
+ return new_string;
+}
+
void StringCache::InvalidateLastString() {
last_string_impl_ = nullptr;
last_v8_string_.Reset();
diff --git a/chromium/third_party/blink/renderer/platform/bindings/v8_value_cache.h b/chromium/third_party/blink/renderer/platform/bindings/v8_value_cache.h
index cbb9b7097ed..66ed25cdd8e 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/v8_value_cache.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/v8_value_cache.h
@@ -33,6 +33,7 @@
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+#include "third_party/blink/renderer/platform/wtf/text/movable_string.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "v8/include/v8.h"
@@ -74,6 +75,44 @@ class StringCacheMapTraits
static void DisposeWeak(const v8::WeakCallbackInfo<WeakCallbackDataType>&);
};
+class MovableStringCacheMapTraits
+ : public V8GlobalValueMapTraits<MovableStringImpl*,
+ v8::String,
+ v8::kWeakWithParameter> {
+ STATIC_ONLY(MovableStringCacheMapTraits);
+
+ public:
+ // Weak traits:
+ typedef MovableStringImpl WeakCallbackDataType;
+ typedef v8::GlobalValueMap<MovableStringImpl*,
+ v8::String,
+ MovableStringCacheMapTraits>
+ MapType;
+
+ static WeakCallbackDataType* WeakCallbackParameter(
+ MapType* map,
+ MovableStringImpl* key,
+ v8::Local<v8::String>& value) {
+ return key;
+ }
+ static void DisposeCallbackData(WeakCallbackDataType* callback_data) {}
+
+ static MapType* MapFromWeakCallbackInfo(
+ const v8::WeakCallbackInfo<WeakCallbackDataType>&);
+
+ static MovableStringImpl* KeyFromWeakCallbackInfo(
+ const v8::WeakCallbackInfo<WeakCallbackDataType>& data) {
+ return data.GetParameter();
+ }
+
+ static void OnWeakCallback(const v8::WeakCallbackInfo<WeakCallbackDataType>&);
+
+ static void Dispose(v8::Isolate*,
+ v8::Global<v8::String> value,
+ MovableStringImpl* key);
+ static void DisposeWeak(const v8::WeakCallbackInfo<WeakCallbackDataType>&);
+};
+
// String cache helps convert WTF strings (StringImpl*) into v8 strings by
// only creating a v8::String for a particular StringImpl* once and caching it
// for future use. It is held by and can be retrieved from V8PerIsolateData, and
@@ -84,7 +123,8 @@ class PLATFORM_EXPORT StringCache {
WTF_MAKE_NONCOPYABLE(StringCache);
public:
- explicit StringCache(v8::Isolate* isolate) : string_cache_(isolate) {}
+ explicit StringCache(v8::Isolate* isolate)
+ : string_cache_(isolate), movable_string_cache_(isolate) {}
v8::Local<v8::String> V8ExternalString(v8::Isolate* isolate,
StringImpl* string_impl) {
@@ -94,6 +134,9 @@ class PLATFORM_EXPORT StringCache {
return V8ExternalStringSlow(isolate, string_impl);
}
+ v8::Local<v8::String> V8ExternalString(v8::Isolate* isolate,
+ const MovableString& string);
+
void SetReturnValueFromString(v8::ReturnValue<v8::Value> return_value,
StringImpl* string_impl) {
DCHECK(string_impl);
@@ -106,16 +149,20 @@ class PLATFORM_EXPORT StringCache {
void Dispose();
friend class StringCacheMapTraits;
+ friend class MovableStringCacheMapTraits;
private:
v8::Local<v8::String> V8ExternalStringSlow(v8::Isolate*, StringImpl*);
void SetReturnValueFromStringSlow(v8::ReturnValue<v8::Value>, StringImpl*);
v8::Local<v8::String> CreateStringAndInsertIntoCache(v8::Isolate*,
StringImpl*);
+ v8::Local<v8::String> CreateStringAndInsertIntoCache(v8::Isolate*,
+ const MovableString&);
void InvalidateLastString();
StringCacheMapTraits::MapType string_cache_;
StringCacheMapTraits::MapType::PersistentValueReference last_v8_string_;
+ MovableStringCacheMapTraits::MapType movable_string_cache_;
// Note: RefPtr is a must as we cache by StringImpl* equality, not identity
// hence lastStringImpl might be not a key of the cache (in sense of identity)
diff --git a/chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.cc b/chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.cc
index 0b1581ee8d4..1788bf2a4ac 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.cc
+++ b/chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.cc
@@ -4,6 +4,9 @@
#include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h"
+
namespace blink {
static_assert(offsetof(struct WrapperTypeInfo, gin_embedder) ==
@@ -11,4 +14,15 @@ static_assert(offsetof(struct WrapperTypeInfo, gin_embedder) ==
"offset of WrapperTypeInfo.ginEmbedder must be the same as "
"gin::WrapperInfo.embedder");
+void WrapperTypeInfo::WrapperCreated() {
+ ThreadState::Current()->Heap().stats_collector()->IncreaseWrapperCount(1);
+}
+
+void WrapperTypeInfo::WrapperDestroyed() {
+ ThreadHeapStatsCollector* stats_collector =
+ ThreadState::Current()->Heap().stats_collector();
+ stats_collector->DecreaseWrapperCount(1);
+ stats_collector->IncreaseCollectedWrapperCount(1);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.h b/chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.h
index 201bf7ad516..2e6899dce06 100644
--- a/chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.h
+++ b/chromium/third_party/blink/renderer/platform/bindings/wrapper_type_info.h
@@ -32,14 +32,14 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_WRAPPER_TYPE_INFO_H_
#include "gin/public/wrapper_info.h"
-#include "third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "v8/include/v8.h"
namespace blink {
+class ActiveScriptWrappableBase;
class DOMWrapperWorld;
class ScriptWrappable;
@@ -99,15 +99,8 @@ struct WrapperTypeInfo {
v8::External::Cast(*type_info_wrapper)->Value());
}
- static void WrapperCreated() {
- ThreadState::Current()->Heap().HeapStats().IncreaseWrapperCount(1);
- }
-
- static void WrapperDestroyed() {
- ThreadHeapStats& heap_stats = ThreadState::Current()->Heap().HeapStats();
- heap_stats.DecreaseWrapperCount(1);
- heap_stats.IncreaseCollectedWrapperCount(1);
- }
+ PLATFORM_EXPORT static void WrapperCreated();
+ PLATFORM_EXPORT static void WrapperDestroyed();
bool Equals(const WrapperTypeInfo* that) const { return this == that; }
diff --git a/chromium/third_party/blink/renderer/platform/blob/OWNERS b/chromium/third_party/blink/renderer/platform/blob/OWNERS
index 9561ef853b6..592111ed461 100644
--- a/chromium/third_party/blink/renderer/platform/blob/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/blob/OWNERS
@@ -7,4 +7,4 @@ per-file *.typemap=set noparent
per-file *.typemap=file://ipc/SECURITY_OWNERS
# TEAM: storage-dev@chromium.org
-# COMPONENT: Blink>FileAPI
+# COMPONENT: Blink>Storage>FileAPI
diff --git a/chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc b/chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc
index b052941e0f6..412ae11284f 100644
--- a/chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc
+++ b/chromium/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc
@@ -8,6 +8,7 @@
#include "base/task_scheduler/post_task.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/web_task_runner.h"
diff --git a/chromium/third_party/blink/renderer/platform/blob/blob_data.cc b/chromium/third_party/blink/renderer/platform/blob/blob_data.cc
index ba69654a506..543574f8eb2 100644
--- a/chromium/third_party/blink/renderer/platform/blob/blob_data.cc
+++ b/chromium/third_party/blink/renderer/platform/blob/blob_data.cc
@@ -362,6 +362,18 @@ BlobPtr BlobDataHandle::CloneBlobPtr() {
return blob_clone;
}
+network::mojom::blink::DataPipeGetterPtr BlobDataHandle::AsDataPipeGetter() {
+ MutexLocker locker(blob_info_mutex_);
+ if (!blob_info_.is_valid())
+ return nullptr;
+ network::mojom::blink::DataPipeGetterPtr result;
+ BlobPtr blob;
+ blob.Bind(std::move(blob_info_));
+ blob->AsDataPipeGetter(MakeRequest(&result));
+ blob_info_ = blob.PassInterface();
+ return result;
+}
+
void BlobDataHandle::ReadAll(mojo::ScopedDataPipeProducerHandle pipe,
mojom::blink::BlobReaderClientPtr client) {
MutexLocker locker(blob_info_mutex_);
diff --git a/chromium/third_party/blink/renderer/platform/blob/blob_data.h b/chromium/third_party/blink/renderer/platform/blob/blob_data.h
index 773bcf6c177..e51d4c055a7 100644
--- a/chromium/third_party/blink/renderer/platform/blob/blob_data.h
+++ b/chromium/third_party/blink/renderer/platform/blob/blob_data.h
@@ -192,6 +192,7 @@ class PLATFORM_EXPORT BlobDataHandle
~BlobDataHandle();
mojom::blink::BlobPtr CloneBlobPtr();
+ network::mojom::blink::DataPipeGetterPtr AsDataPipeGetter();
void ReadAll(mojo::ScopedDataPipeProducerHandle,
mojom::blink::BlobReaderClientPtr);
diff --git a/chromium/third_party/blink/renderer/platform/blob/blob_registry.h b/chromium/third_party/blink/renderer/platform/blob/blob_registry.h
index 56d2fcb049c..13cd04d38fe 100644
--- a/chromium/third_party/blink/renderer/platform/blob/blob_registry.h
+++ b/chromium/third_party/blink/renderer/platform/blob/blob_registry.h
@@ -38,7 +38,6 @@
namespace blink {
-class BlobBytesConsumer;
class BlobDataHandle;
class BlobURLRegistry;
class KURL;
@@ -49,12 +48,11 @@ class PLATFORM_EXPORT BlobRegistry {
STATIC_ONLY(BlobRegistry);
// Calling methods in this class directly won't work when Blob URL management
- // is switched to mojo. Instead codew should call PublicURLManager methods to
+ // is switched to mojo. Instead code should call PublicURLManager methods to
// create/revoke blob URLs.
// To avoid new usage of these methods, mark all as private with friends for
// existing usage.
private:
- friend class BlobBytesConsumer;
friend class BlobURLRegistry;
// Methods for controlling Blob URLs.
diff --git a/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.cc b/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.cc
index 096cae3fad3..f8e69fd93e4 100644
--- a/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.cc
+++ b/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.cc
@@ -5,19 +5,52 @@
#include "third_party/blink/renderer/platform/blob/testing/fake_blob.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "mojo/public/cpp/system/data_pipe_utils.h"
+#include "third_party/blink/public/platform/web_string.h"
namespace blink {
+namespace {
-FakeBlob::FakeBlob(const String& uuid) : uuid_(uuid) {}
+class SimpleDataPipeGetter : public network::mojom::blink::DataPipeGetter {
+ public:
+ SimpleDataPipeGetter(const String& str) : str_(str) {}
+ ~SimpleDataPipeGetter() override = default;
+
+ // network::mojom::DataPipeGetter implementation:
+ void Read(mojo::ScopedDataPipeProducerHandle handle,
+ ReadCallback callback) override {
+ std::move(callback).Run(0 /* OK */, str_.length());
+ bool result = mojo::BlockingCopyFromString(WebString(str_).Utf8(), handle);
+ DCHECK(result);
+ }
+
+ void Clone(network::mojom::blink::DataPipeGetterRequest request) override {
+ mojo::MakeStrongBinding(std::make_unique<SimpleDataPipeGetter>(str_),
+ std::move(request));
+ }
+
+ private:
+ String str_;
+
+ DISALLOW_COPY_AND_ASSIGN(SimpleDataPipeGetter);
+};
+
+} // namespace
+
+FakeBlob::FakeBlob(const String& uuid, const String& body, State* state)
+ : uuid_(uuid), body_(body), state_(state) {}
void FakeBlob::Clone(mojom::blink::BlobRequest request) {
- mojo::MakeStrongBinding(std::make_unique<FakeBlob>(uuid_),
+ mojo::MakeStrongBinding(std::make_unique<FakeBlob>(uuid_, body_, state_),
std::move(request));
}
void FakeBlob::AsDataPipeGetter(
network::mojom::blink::DataPipeGetterRequest request) {
- NOTREACHED();
+ if (state_)
+ state_->did_initiate_read_operation = true;
+ mojo::MakeStrongBinding(std::make_unique<SimpleDataPipeGetter>(body_),
+ std::move(request));
}
void FakeBlob::ReadRange(uint64_t offset,
@@ -27,9 +60,16 @@ void FakeBlob::ReadRange(uint64_t offset,
NOTREACHED();
}
-void FakeBlob::ReadAll(mojo::ScopedDataPipeProducerHandle,
- mojom::blink::BlobReaderClientPtr) {
- NOTREACHED();
+void FakeBlob::ReadAll(mojo::ScopedDataPipeProducerHandle handle,
+ mojom::blink::BlobReaderClientPtr client) {
+ if (state_)
+ state_->did_initiate_read_operation = true;
+ if (client)
+ client->OnCalculatedSize(body_.length(), body_.length());
+ bool result = mojo::BlockingCopyFromString(WebString(body_).Utf8(), handle);
+ DCHECK(result);
+ if (client)
+ client->OnComplete(0 /* OK */, body_.length());
}
void FakeBlob::ReadSideData(ReadSideDataCallback callback) {
diff --git a/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.h b/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.h
index 447645fabe0..6013df817dd 100644
--- a/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.h
+++ b/chromium/third_party/blink/renderer/platform/blob/testing/fake_blob.h
@@ -9,11 +9,17 @@
namespace blink {
-// Mocked Blob implementation for testing. You can't read from a FakeBlob, but
-// it does have a UUID.
+// Mocked Blob implementation for testing. Implements all methods except for
+// ReadRange and ReadSideData.
class FakeBlob : public mojom::blink::Blob {
public:
- explicit FakeBlob(const String& uuid);
+ struct State {
+ bool did_initiate_read_operation = false;
+ };
+
+ FakeBlob(const String& uuid,
+ const String& body = String(),
+ State* state = nullptr);
void Clone(mojom::blink::BlobRequest) override;
void AsDataPipeGetter(network::mojom::blink::DataPipeGetterRequest) override;
@@ -25,9 +31,10 @@ class FakeBlob : public mojom::blink::Blob {
mojom::blink::BlobReaderClientPtr) override;
void ReadSideData(ReadSideDataCallback) override;
void GetInternalUUID(GetInternalUUIDCallback) override;
-
private:
String uuid_;
+ String body_;
+ State* state_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/clipboard/DEPS b/chromium/third_party/blink/renderer/platform/clipboard/DEPS
deleted file mode 100644
index 715fce4a84b..00000000000
--- a/chromium/third_party/blink/renderer/platform/clipboard/DEPS
+++ /dev/null
@@ -1,12 +0,0 @@
-include_rules = [
- # Don't depend on platform/.
- "-third_party/blink/renderer/platform",
-
- # Module.
- "+third_party/blink/renderer/platform/clipboard",
-
- # Dependencies.
- "+third_party/blink/renderer/platform/platform_export.h",
- "+third_party/blink/renderer/platform/weborigin/kurl.h",
- "+third_party/blink/renderer/platform/wtf",
-]
diff --git a/chromium/third_party/blink/renderer/platform/clipboard/clipboard_mime_types.cc b/chromium/third_party/blink/renderer/platform/clipboard/clipboard_mime_types.cc
deleted file mode 100644
index 5234818fa0b..00000000000
--- a/chromium/third_party/blink/renderer/platform/clipboard/clipboard_mime_types.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/platform/clipboard/clipboard_mime_types.h"
-
-namespace blink {
-
-const char kMimeTypeText[] = "text";
-const char kMimeTypeTextPlain[] = "text/plain";
-const char kMimeTypeTextPlainEtc[] = "text/plain;";
-const char kMimeTypeTextHTML[] = "text/html";
-const char kMimeTypeTextRTF[] = "text/rtf";
-const char kMimeTypeURL[] = "url";
-const char kMimeTypeTextURIList[] = "text/uri-list";
-const char kMimeTypeDownloadURL[] = "downloadurl";
-const char kMimeTypeFiles[] = "Files";
-const char kMimeTypeImagePng[] = "image/png";
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/clipboard/clipboard_mime_types.h b/chromium/third_party/blink/renderer/platform/clipboard/clipboard_mime_types.h
deleted file mode 100644
index b9e29c94f81..00000000000
--- a/chromium/third_party/blink/renderer/platform/clipboard/clipboard_mime_types.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_CLIPBOARD_CLIPBOARD_MIME_TYPES_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_CLIPBOARD_CLIPBOARD_MIME_TYPES_H_
-
-#include "third_party/blink/renderer/platform/platform_export.h"
-
-namespace blink {
-
-PLATFORM_EXPORT extern const char kMimeTypeText[];
-PLATFORM_EXPORT extern const char kMimeTypeTextPlain[];
-PLATFORM_EXPORT extern const char kMimeTypeTextPlainEtc[];
-PLATFORM_EXPORT extern const char kMimeTypeTextHTML[];
-PLATFORM_EXPORT extern const char kMimeTypeTextRTF[];
-PLATFORM_EXPORT extern const char kMimeTypeURL[];
-PLATFORM_EXPORT extern const char kMimeTypeTextURIList[];
-PLATFORM_EXPORT extern const char kMimeTypeDownloadURL[];
-PLATFORM_EXPORT extern const char kMimeTypeFiles[];
-PLATFORM_EXPORT extern const char kMimeTypeImagePng[];
-
-} // namespace blink
-
-#endif
diff --git a/chromium/third_party/blink/renderer/platform/clipboard/clipboard_utilities.cc b/chromium/third_party/blink/renderer/platform/clipboard/clipboard_utilities.cc
deleted file mode 100644
index 058b9098c9f..00000000000
--- a/chromium/third_party/blink/renderer/platform/clipboard/clipboard_utilities.cc
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/platform/clipboard/clipboard_utilities.h"
-
-#include "net/base/escape.h"
-#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-void ReplaceNBSPWithSpace(String& str) {
- static const UChar kNonBreakingSpaceCharacter = 0xA0;
- static const UChar kSpaceCharacter = ' ';
- str.Replace(kNonBreakingSpaceCharacter, kSpaceCharacter);
-}
-
-String ConvertURIListToURL(const String& uri_list) {
- Vector<String> items;
- // Line separator is \r\n per RFC 2483 - however, for compatibility
- // reasons we allow just \n here.
- uri_list.Split('\n', items);
- // Process the input and return the first valid URL. In case no URLs can
- // be found, return an empty string. This is in line with the HTML5 spec.
- for (size_t i = 0; i < items.size(); ++i) {
- String& line = items[i];
- line = line.StripWhiteSpace();
- if (line.IsEmpty())
- continue;
- if (line[0] == '#')
- continue;
- KURL url = KURL(line);
- if (url.IsValid())
- return url;
- }
- return String();
-}
-
-static String EscapeForHTML(const String& str) {
- std::string output =
- net::EscapeForHTML(StringUTF8Adaptor(str).AsStringPiece());
- return String(output.c_str());
-}
-
-// TODO(slangley): crbug.com/775830. Remove the implementation of
-// URLToImageMarkup from clipboard_utils.h once we can delete
-// MockClipboard.
-String URLToImageMarkup(const KURL& url, const String& title) {
- StringBuilder builder;
- builder.Append("<img src=\"");
- builder.Append(EscapeForHTML(url.GetString()));
- builder.Append("\"");
- if (!title.IsEmpty()) {
- builder.Append(" alt=\"");
- builder.Append(EscapeForHTML(title));
- builder.Append("\"");
- }
- builder.Append("/>");
- return builder.ToString();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/clipboard/clipboard_utilities.h b/chromium/third_party/blink/renderer/platform/clipboard/clipboard_utilities.h
deleted file mode 100644
index 514bc6f24bf..00000000000
--- a/chromium/third_party/blink/renderer/platform/clipboard/clipboard_utilities.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_CLIPBOARD_CLIPBOARD_UTILITIES_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_CLIPBOARD_CLIPBOARD_UTILITIES_H_
-
-#include "build/build_config.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
-
-namespace blink {
-
-#if defined(OS_WIN)
-PLATFORM_EXPORT void ReplaceNewlinesWithWindowsStyleNewlines(String&);
-#endif
-PLATFORM_EXPORT void ReplaceNBSPWithSpace(String&);
-PLATFORM_EXPORT String ConvertURIListToURL(const String& uri_list);
-PLATFORM_EXPORT String URLToImageMarkup(const KURL&, const String& title);
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_CLIPBOARD_CLIPBOARD_UTILITIES_H_
diff --git a/chromium/third_party/blink/renderer/platform/clipboard/clipboard_utilities_win.cc b/chromium/third_party/blink/renderer/platform/clipboard/clipboard_utilities_win.cc
deleted file mode 100644
index 88ae9d6e9e8..00000000000
--- a/chromium/third_party/blink/renderer/platform/clipboard/clipboard_utilities_win.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2009 Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/platform/clipboard/clipboard_utilities.h"
-
-#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-#include <shlwapi.h>
-
-namespace blink {
-
-void ReplaceNewlinesWithWindowsStyleNewlines(String& str) {
- DEFINE_STATIC_LOCAL(String, windows_newline, ("\r\n"));
- StringBuilder result;
- for (unsigned index = 0; index < str.length(); ++index) {
- if (str[index] != '\n' || (index > 0 && str[index - 1] == '\r'))
- result.Append(str[index]);
- else
- result.Append(windows_newline);
- }
- str = result.ToString();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/cross_thread_copier.h b/chromium/third_party/blink/renderer/platform/cross_thread_copier.h
index 1b4880b03da..f42cc3b88ac 100644
--- a/chromium/third_party/blink/renderer/platform/cross_thread_copier.h
+++ b/chromium/third_party/blink/renderer/platform/cross_thread_copier.h
@@ -46,6 +46,9 @@
namespace base {
template <typename, typename>
class RefCountedThreadSafe;
+class TimeDelta;
+class TimeTicks;
+class Time;
}
class SkRefCnt;
@@ -124,6 +127,24 @@ struct CrossThreadCopier<sk_sp<T>>
"sk_sp<T> can be passed across threads only if T is SkRefCnt.");
};
+template <>
+struct CrossThreadCopier<base::TimeDelta>
+ : public CrossThreadCopierPassThrough<base::TimeDelta> {
+ STATIC_ONLY(CrossThreadCopier);
+};
+
+template <>
+struct CrossThreadCopier<base::TimeTicks>
+ : public CrossThreadCopierPassThrough<base::TimeTicks> {
+ STATIC_ONLY(CrossThreadCopier);
+};
+
+template <>
+struct CrossThreadCopier<base::Time>
+ : public CrossThreadCopierPassThrough<base::Time> {
+ STATIC_ONLY(CrossThreadCopier);
+};
+
// nullptr_t can be passed through without any changes.
template <>
struct CrossThreadCopier<std::nullptr_t>
diff --git a/chromium/third_party/blink/renderer/platform/decimal.cc b/chromium/third_party/blink/renderer/platform/decimal.cc
deleted file mode 100644
index 10979afd0d6..00000000000
--- a/chromium/third_party/blink/renderer/platform/decimal.cc
+++ /dev/null
@@ -1,1007 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/platform/decimal.h"
-
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/math_extras.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-
-#include <algorithm>
-#include <float.h>
-
-namespace blink {
-
-namespace DecimalPrivate {
-
-static int const kExponentMax = 1023;
-static int const kExponentMin = -1023;
-static int const kPrecision = 18;
-
-static const uint64_t kMaxCoefficient =
- UINT64_C(0xDE0B6B3A763FFFF); // 999999999999999999 == 18 9's
-
-// This class handles Decimal special values.
-class SpecialValueHandler {
- STACK_ALLOCATED();
- WTF_MAKE_NONCOPYABLE(SpecialValueHandler);
-
- public:
- enum HandleResult {
- kBothFinite,
- kBothInfinity,
- kEitherNaN,
- kLHSIsInfinity,
- kRHSIsInfinity,
- };
-
- SpecialValueHandler(const Decimal& lhs, const Decimal& rhs);
- HandleResult Handle();
- Decimal Value() const;
-
- private:
- enum Result {
- kResultIsLHS,
- kResultIsRHS,
- kResultIsUnknown,
- };
-
- const Decimal& lhs_;
- const Decimal& rhs_;
- Result result_;
-};
-
-SpecialValueHandler::SpecialValueHandler(const Decimal& lhs, const Decimal& rhs)
- : lhs_(lhs), rhs_(rhs), result_(kResultIsUnknown) {}
-
-SpecialValueHandler::HandleResult SpecialValueHandler::Handle() {
- if (lhs_.IsFinite() && rhs_.IsFinite())
- return kBothFinite;
-
- const Decimal::EncodedData::FormatClass lhs_class =
- lhs_.Value().GetFormatClass();
- const Decimal::EncodedData::FormatClass rhs_class =
- rhs_.Value().GetFormatClass();
- if (lhs_class == Decimal::EncodedData::kClassNaN) {
- result_ = kResultIsLHS;
- return kEitherNaN;
- }
-
- if (rhs_class == Decimal::EncodedData::kClassNaN) {
- result_ = kResultIsRHS;
- return kEitherNaN;
- }
-
- if (lhs_class == Decimal::EncodedData::kClassInfinity)
- return rhs_class == Decimal::EncodedData::kClassInfinity ? kBothInfinity
- : kLHSIsInfinity;
-
- if (rhs_class == Decimal::EncodedData::kClassInfinity)
- return kRHSIsInfinity;
-
- NOTREACHED();
- return kBothFinite;
-}
-
-Decimal SpecialValueHandler::Value() const {
- switch (result_) {
- case kResultIsLHS:
- return lhs_;
- case kResultIsRHS:
- return rhs_;
- case kResultIsUnknown:
- default:
- NOTREACHED();
- return lhs_;
- }
-}
-
-// This class is used for 128 bit unsigned integer arithmetic.
-class UInt128 {
- public:
- UInt128(uint64_t low, uint64_t high) : high_(high), low_(low) {}
-
- UInt128& operator/=(uint32_t);
-
- uint64_t High() const { return high_; }
- uint64_t Low() const { return low_; }
-
- static UInt128 Multiply(uint64_t u, uint64_t v) {
- return UInt128(u * v, MultiplyHigh(u, v));
- }
-
- private:
- static uint32_t HighUInt32(uint64_t x) {
- return static_cast<uint32_t>(x >> 32);
- }
- static uint32_t LowUInt32(uint64_t x) {
- return static_cast<uint32_t>(x & ((static_cast<uint64_t>(1) << 32) - 1));
- }
- static uint64_t MakeUInt64(uint32_t low, uint32_t high) {
- return low | (static_cast<uint64_t>(high) << 32);
- }
-
- static uint64_t MultiplyHigh(uint64_t, uint64_t);
-
- uint64_t high_;
- uint64_t low_;
-};
-
-UInt128& UInt128::operator/=(const uint32_t divisor) {
- DCHECK(divisor);
-
- if (!high_) {
- low_ /= divisor;
- return *this;
- }
-
- uint32_t dividend[4];
- dividend[0] = LowUInt32(low_);
- dividend[1] = HighUInt32(low_);
- dividend[2] = LowUInt32(high_);
- dividend[3] = HighUInt32(high_);
-
- uint32_t quotient[4];
- uint32_t remainder = 0;
- for (int i = 3; i >= 0; --i) {
- const uint64_t work = MakeUInt64(dividend[i], remainder);
- remainder = static_cast<uint32_t>(work % divisor);
- quotient[i] = static_cast<uint32_t>(work / divisor);
- }
- low_ = MakeUInt64(quotient[0], quotient[1]);
- high_ = MakeUInt64(quotient[2], quotient[3]);
- return *this;
-}
-
-// Returns high 64bit of 128bit product.
-uint64_t UInt128::MultiplyHigh(uint64_t u, uint64_t v) {
- const uint64_t u_low = LowUInt32(u);
- const uint64_t u_high = HighUInt32(u);
- const uint64_t v_low = LowUInt32(v);
- const uint64_t v_high = HighUInt32(v);
- const uint64_t partial_product = u_high * v_low + HighUInt32(u_low * v_low);
- return u_high * v_high + HighUInt32(partial_product) +
- HighUInt32(u_low * v_high + LowUInt32(partial_product));
-}
-
-static int CountDigits(uint64_t x) {
- int number_of_digits = 0;
- for (uint64_t power_of_ten = 1; x >= power_of_ten; power_of_ten *= 10) {
- ++number_of_digits;
- if (power_of_ten >= std::numeric_limits<uint64_t>::max() / 10)
- break;
- }
- return number_of_digits;
-}
-
-static uint64_t ScaleDown(uint64_t x, int n) {
- DCHECK_GE(n, 0);
- while (n > 0 && x) {
- x /= 10;
- --n;
- }
- return x;
-}
-
-static uint64_t ScaleUp(uint64_t x, int n) {
- DCHECK_GE(n, 0);
- DCHECK_LE(n, kPrecision);
-
- uint64_t y = 1;
- uint64_t z = 10;
- for (;;) {
- if (n & 1)
- y = y * z;
-
- n >>= 1;
- if (!n)
- return x * y;
-
- z = z * z;
- }
-}
-
-} // namespace DecimalPrivate
-
-using namespace DecimalPrivate;
-
-Decimal::EncodedData::EncodedData(Sign sign, FormatClass format_class)
- : coefficient_(0), exponent_(0), format_class_(format_class), sign_(sign) {}
-
-Decimal::EncodedData::EncodedData(Sign sign, int exponent, uint64_t coefficient)
- : format_class_(coefficient ? kClassNormal : kClassZero), sign_(sign) {
- if (exponent >= kExponentMin && exponent <= kExponentMax) {
- while (coefficient > kMaxCoefficient) {
- coefficient /= 10;
- ++exponent;
- }
- }
-
- if (exponent > kExponentMax) {
- coefficient_ = 0;
- exponent_ = 0;
- format_class_ = kClassInfinity;
- return;
- }
-
- if (exponent < kExponentMin) {
- coefficient_ = 0;
- exponent_ = 0;
- format_class_ = kClassZero;
- return;
- }
-
- coefficient_ = coefficient;
- exponent_ = static_cast<int16_t>(exponent);
-}
-
-bool Decimal::EncodedData::operator==(const EncodedData& another) const {
- return sign_ == another.sign_ && format_class_ == another.format_class_ &&
- exponent_ == another.exponent_ && coefficient_ == another.coefficient_;
-}
-
-Decimal::Decimal(int32_t i32)
- : data_(i32 < 0 ? kNegative : kPositive,
- 0,
- i32 < 0 ? static_cast<uint64_t>(-static_cast<int64_t>(i32))
- : static_cast<uint64_t>(i32)) {}
-
-Decimal::Decimal(Sign sign, int exponent, uint64_t coefficient)
- : data_(sign, exponent, coefficient) {}
-
-Decimal::Decimal(const EncodedData& data) : data_(data) {}
-
-Decimal::Decimal(const Decimal& other) = default;
-
-Decimal& Decimal::operator=(const Decimal& other) = default;
-
-Decimal& Decimal::operator+=(const Decimal& other) {
- data_ = (*this + other).data_;
- return *this;
-}
-
-Decimal& Decimal::operator-=(const Decimal& other) {
- data_ = (*this - other).data_;
- return *this;
-}
-
-Decimal& Decimal::operator*=(const Decimal& other) {
- data_ = (*this * other).data_;
- return *this;
-}
-
-Decimal& Decimal::operator/=(const Decimal& other) {
- data_ = (*this / other).data_;
- return *this;
-}
-
-Decimal Decimal::operator-() const {
- if (IsNaN())
- return *this;
-
- Decimal result(*this);
- result.data_.SetSign(InvertSign(data_.GetSign()));
- return result;
-}
-
-Decimal Decimal::operator+(const Decimal& rhs) const {
- const Decimal& lhs = *this;
- const Sign lhs_sign = lhs.GetSign();
- const Sign rhs_sign = rhs.GetSign();
-
- SpecialValueHandler handler(lhs, rhs);
- switch (handler.Handle()) {
- case SpecialValueHandler::kBothFinite:
- break;
-
- case SpecialValueHandler::kBothInfinity:
- return lhs_sign == rhs_sign ? lhs : Nan();
-
- case SpecialValueHandler::kEitherNaN:
- return handler.Value();
-
- case SpecialValueHandler::kLHSIsInfinity:
- return lhs;
-
- case SpecialValueHandler::kRHSIsInfinity:
- return rhs;
- }
-
- const AlignedOperands aligned_operands = AlignOperands(lhs, rhs);
-
- const uint64_t result =
- lhs_sign == rhs_sign
- ? aligned_operands.lhs_coefficient + aligned_operands.rhs_coefficient
- : aligned_operands.lhs_coefficient - aligned_operands.rhs_coefficient;
-
- if (lhs_sign == kNegative && rhs_sign == kPositive && !result)
- return Decimal(kPositive, aligned_operands.exponent, 0);
-
- return static_cast<int64_t>(result) >= 0
- ? Decimal(lhs_sign, aligned_operands.exponent, result)
- : Decimal(InvertSign(lhs_sign), aligned_operands.exponent,
- -static_cast<int64_t>(result));
-}
-
-Decimal Decimal::operator-(const Decimal& rhs) const {
- const Decimal& lhs = *this;
- const Sign lhs_sign = lhs.GetSign();
- const Sign rhs_sign = rhs.GetSign();
-
- SpecialValueHandler handler(lhs, rhs);
- switch (handler.Handle()) {
- case SpecialValueHandler::kBothFinite:
- break;
-
- case SpecialValueHandler::kBothInfinity:
- return lhs_sign == rhs_sign ? Nan() : lhs;
-
- case SpecialValueHandler::kEitherNaN:
- return handler.Value();
-
- case SpecialValueHandler::kLHSIsInfinity:
- return lhs;
-
- case SpecialValueHandler::kRHSIsInfinity:
- return Infinity(InvertSign(rhs_sign));
- }
-
- const AlignedOperands aligned_operands = AlignOperands(lhs, rhs);
-
- const uint64_t result =
- lhs_sign == rhs_sign
- ? aligned_operands.lhs_coefficient - aligned_operands.rhs_coefficient
- : aligned_operands.lhs_coefficient + aligned_operands.rhs_coefficient;
-
- if (lhs_sign == kNegative && rhs_sign == kNegative && !result)
- return Decimal(kPositive, aligned_operands.exponent, 0);
-
- return static_cast<int64_t>(result) >= 0
- ? Decimal(lhs_sign, aligned_operands.exponent, result)
- : Decimal(InvertSign(lhs_sign), aligned_operands.exponent,
- -static_cast<int64_t>(result));
-}
-
-Decimal Decimal::operator*(const Decimal& rhs) const {
- const Decimal& lhs = *this;
- const Sign lhs_sign = lhs.GetSign();
- const Sign rhs_sign = rhs.GetSign();
- const Sign result_sign = lhs_sign == rhs_sign ? kPositive : kNegative;
-
- SpecialValueHandler handler(lhs, rhs);
- switch (handler.Handle()) {
- case SpecialValueHandler::kBothFinite: {
- const uint64_t lhs_coefficient = lhs.data_.Coefficient();
- const uint64_t rhs_coefficient = rhs.data_.Coefficient();
- int result_exponent = lhs.Exponent() + rhs.Exponent();
- UInt128 work(UInt128::Multiply(lhs_coefficient, rhs_coefficient));
- while (work.High()) {
- work /= 10;
- ++result_exponent;
- }
- return Decimal(result_sign, result_exponent, work.Low());
- }
-
- case SpecialValueHandler::kBothInfinity:
- return Infinity(result_sign);
-
- case SpecialValueHandler::kEitherNaN:
- return handler.Value();
-
- case SpecialValueHandler::kLHSIsInfinity:
- return rhs.IsZero() ? Nan() : Infinity(result_sign);
-
- case SpecialValueHandler::kRHSIsInfinity:
- return lhs.IsZero() ? Nan() : Infinity(result_sign);
- }
-
- NOTREACHED();
- return Nan();
-}
-
-Decimal Decimal::operator/(const Decimal& rhs) const {
- const Decimal& lhs = *this;
- const Sign lhs_sign = lhs.GetSign();
- const Sign rhs_sign = rhs.GetSign();
- const Sign result_sign = lhs_sign == rhs_sign ? kPositive : kNegative;
-
- SpecialValueHandler handler(lhs, rhs);
- switch (handler.Handle()) {
- case SpecialValueHandler::kBothFinite:
- break;
-
- case SpecialValueHandler::kBothInfinity:
- return Nan();
-
- case SpecialValueHandler::kEitherNaN:
- return handler.Value();
-
- case SpecialValueHandler::kLHSIsInfinity:
- return Infinity(result_sign);
-
- case SpecialValueHandler::kRHSIsInfinity:
- return Zero(result_sign);
- }
-
- DCHECK(lhs.IsFinite());
- DCHECK(rhs.IsFinite());
-
- if (rhs.IsZero())
- return lhs.IsZero() ? Nan() : Infinity(result_sign);
-
- int result_exponent = lhs.Exponent() - rhs.Exponent();
-
- if (lhs.IsZero())
- return Decimal(result_sign, result_exponent, 0);
-
- uint64_t remainder = lhs.data_.Coefficient();
- const uint64_t divisor = rhs.data_.Coefficient();
- uint64_t result = 0;
- for (;;) {
- while (remainder < divisor && result < kMaxCoefficient / 10) {
- remainder *= 10;
- result *= 10;
- --result_exponent;
- }
- if (remainder < divisor)
- break;
- uint64_t quotient = remainder / divisor;
- if (result > kMaxCoefficient - quotient)
- break;
- result += quotient;
- remainder %= divisor;
- if (!remainder)
- break;
- }
-
- if (remainder > divisor / 2)
- ++result;
-
- return Decimal(result_sign, result_exponent, result);
-}
-
-bool Decimal::operator==(const Decimal& rhs) const {
- return data_ == rhs.data_ || CompareTo(rhs).IsZero();
-}
-
-bool Decimal::operator!=(const Decimal& rhs) const {
- if (data_ == rhs.data_)
- return false;
- const Decimal result = CompareTo(rhs);
- if (result.IsNaN())
- return false;
- return !result.IsZero();
-}
-
-bool Decimal::operator<(const Decimal& rhs) const {
- const Decimal result = CompareTo(rhs);
- if (result.IsNaN())
- return false;
- return !result.IsZero() && result.IsNegative();
-}
-
-bool Decimal::operator<=(const Decimal& rhs) const {
- if (data_ == rhs.data_)
- return true;
- const Decimal result = CompareTo(rhs);
- if (result.IsNaN())
- return false;
- return result.IsZero() || result.IsNegative();
-}
-
-bool Decimal::operator>(const Decimal& rhs) const {
- const Decimal result = CompareTo(rhs);
- if (result.IsNaN())
- return false;
- return !result.IsZero() && result.IsPositive();
-}
-
-bool Decimal::operator>=(const Decimal& rhs) const {
- if (data_ == rhs.data_)
- return true;
- const Decimal result = CompareTo(rhs);
- if (result.IsNaN())
- return false;
- return result.IsZero() || !result.IsNegative();
-}
-
-Decimal Decimal::Abs() const {
- Decimal result(*this);
- result.data_.SetSign(kPositive);
- return result;
-}
-
-Decimal::AlignedOperands Decimal::AlignOperands(const Decimal& lhs,
- const Decimal& rhs) {
- DCHECK(lhs.IsFinite());
- DCHECK(rhs.IsFinite());
-
- const int lhs_exponent = lhs.Exponent();
- const int rhs_exponent = rhs.Exponent();
- int exponent = std::min(lhs_exponent, rhs_exponent);
- uint64_t lhs_coefficient = lhs.data_.Coefficient();
- uint64_t rhs_coefficient = rhs.data_.Coefficient();
-
- if (lhs_exponent > rhs_exponent) {
- const int number_of_lhs_digits = CountDigits(lhs_coefficient);
- if (number_of_lhs_digits) {
- const int lhs_shift_amount = lhs_exponent - rhs_exponent;
- const int overflow = number_of_lhs_digits + lhs_shift_amount - kPrecision;
- if (overflow <= 0) {
- lhs_coefficient = ScaleUp(lhs_coefficient, lhs_shift_amount);
- } else {
- lhs_coefficient = ScaleUp(lhs_coefficient, lhs_shift_amount - overflow);
- rhs_coefficient = ScaleDown(rhs_coefficient, overflow);
- exponent += overflow;
- }
- }
-
- } else if (lhs_exponent < rhs_exponent) {
- const int number_of_rhs_digits = CountDigits(rhs_coefficient);
- if (number_of_rhs_digits) {
- const int rhs_shift_amount = rhs_exponent - lhs_exponent;
- const int overflow = number_of_rhs_digits + rhs_shift_amount - kPrecision;
- if (overflow <= 0) {
- rhs_coefficient = ScaleUp(rhs_coefficient, rhs_shift_amount);
- } else {
- rhs_coefficient = ScaleUp(rhs_coefficient, rhs_shift_amount - overflow);
- lhs_coefficient = ScaleDown(lhs_coefficient, overflow);
- exponent += overflow;
- }
- }
- }
-
- AlignedOperands aligned_operands;
- aligned_operands.exponent = exponent;
- aligned_operands.lhs_coefficient = lhs_coefficient;
- aligned_operands.rhs_coefficient = rhs_coefficient;
- return aligned_operands;
-}
-
-static bool IsMultiplePowersOfTen(uint64_t coefficient, int n) {
- return !coefficient || !(coefficient % ScaleUp(1, n));
-}
-
-// Round toward positive infinity.
-Decimal Decimal::Ceil() const {
- if (IsSpecial())
- return *this;
-
- if (Exponent() >= 0)
- return *this;
-
- uint64_t result = data_.Coefficient();
- const int number_of_digits = CountDigits(result);
- const int number_of_drop_digits = -Exponent();
- if (number_of_digits <= number_of_drop_digits)
- return IsPositive() ? Decimal(1) : Zero(kPositive);
-
- result = ScaleDown(result, number_of_drop_digits);
- if (IsPositive() &&
- !IsMultiplePowersOfTen(data_.Coefficient(), number_of_drop_digits))
- ++result;
- return Decimal(GetSign(), 0, result);
-}
-
-Decimal Decimal::CompareTo(const Decimal& rhs) const {
- const Decimal result(*this - rhs);
- switch (result.data_.GetFormatClass()) {
- case EncodedData::kClassInfinity:
- return result.IsNegative() ? Decimal(-1) : Decimal(1);
-
- case EncodedData::kClassNaN:
- case EncodedData::kClassNormal:
- return result;
-
- case EncodedData::kClassZero:
- return Zero(kPositive);
-
- default:
- NOTREACHED();
- return Nan();
- }
-}
-
-// Round toward negative infinity.
-Decimal Decimal::Floor() const {
- if (IsSpecial())
- return *this;
-
- if (Exponent() >= 0)
- return *this;
-
- uint64_t result = data_.Coefficient();
- const int number_of_digits = CountDigits(result);
- const int number_of_drop_digits = -Exponent();
- if (number_of_digits < number_of_drop_digits)
- return IsPositive() ? Zero(kPositive) : Decimal(-1);
-
- result = ScaleDown(result, number_of_drop_digits);
- if (IsNegative() &&
- !IsMultiplePowersOfTen(data_.Coefficient(), number_of_drop_digits))
- ++result;
- return Decimal(GetSign(), 0, result);
-}
-
-Decimal Decimal::FromDouble(double double_value) {
- if (std::isfinite(double_value))
- return FromString(String::NumberToStringECMAScript(double_value));
-
- if (std::isinf(double_value))
- return Infinity(double_value < 0 ? kNegative : kPositive);
-
- return Nan();
-}
-
-Decimal Decimal::FromString(const String& str) {
- int exponent = 0;
- Sign exponent_sign = kPositive;
- int number_of_digits = 0;
- int number_of_digits_after_dot = 0;
- int number_of_extra_digits = 0;
- Sign sign = kPositive;
-
- enum {
- kStateDigit,
- kStateDot,
- kStateDotDigit,
- kStateE,
- kStateEDigit,
- kStateESign,
- kStateSign,
- kStateStart,
- kStateZero,
- } state = kStateStart;
-
-#define HandleCharAndBreak(expected, nextState) \
- if (ch == expected) { \
- state = nextState; \
- break; \
- }
-
-#define HandleTwoCharsAndBreak(expected1, expected2, nextState) \
- if (ch == expected1 || ch == expected2) { \
- state = nextState; \
- break; \
- }
-
- uint64_t accumulator = 0;
- for (unsigned index = 0; index < str.length(); ++index) {
- const int ch = str[index];
- switch (state) {
- case kStateDigit:
- if (ch >= '0' && ch <= '9') {
- if (number_of_digits < kPrecision) {
- ++number_of_digits;
- accumulator *= 10;
- accumulator += ch - '0';
- } else {
- ++number_of_extra_digits;
- }
- break;
- }
-
- HandleCharAndBreak('.', kStateDot);
- HandleTwoCharsAndBreak('E', 'e', kStateE);
- return Nan();
-
- case kStateDot:
- case kStateDotDigit:
- if (ch >= '0' && ch <= '9') {
- if (number_of_digits < kPrecision) {
- ++number_of_digits;
- ++number_of_digits_after_dot;
- accumulator *= 10;
- accumulator += ch - '0';
- }
- state = kStateDotDigit;
- break;
- }
-
- HandleTwoCharsAndBreak('E', 'e', kStateE);
- return Nan();
-
- case kStateE:
- if (ch == '+') {
- exponent_sign = kPositive;
- state = kStateESign;
- break;
- }
-
- if (ch == '-') {
- exponent_sign = kNegative;
- state = kStateESign;
- break;
- }
-
- if (ch >= '0' && ch <= '9') {
- exponent = ch - '0';
- state = kStateEDigit;
- break;
- }
-
- return Nan();
-
- case kStateEDigit:
- if (ch >= '0' && ch <= '9') {
- exponent *= 10;
- exponent += ch - '0';
- if (exponent > kExponentMax + kPrecision) {
- if (accumulator)
- return exponent_sign == kNegative ? Zero(kPositive)
- : Infinity(sign);
- return Zero(sign);
- }
- state = kStateEDigit;
- break;
- }
-
- return Nan();
-
- case kStateESign:
- if (ch >= '0' && ch <= '9') {
- exponent = ch - '0';
- state = kStateEDigit;
- break;
- }
-
- return Nan();
-
- case kStateSign:
- if (ch >= '1' && ch <= '9') {
- accumulator = ch - '0';
- number_of_digits = 1;
- state = kStateDigit;
- break;
- }
-
- HandleCharAndBreak('0', kStateZero);
- return Nan();
-
- case kStateStart:
- if (ch >= '1' && ch <= '9') {
- accumulator = ch - '0';
- number_of_digits = 1;
- state = kStateDigit;
- break;
- }
-
- if (ch == '-') {
- sign = kNegative;
- state = kStateSign;
- break;
- }
-
- if (ch == '+') {
- sign = kPositive;
- state = kStateSign;
- break;
- }
-
- HandleCharAndBreak('0', kStateZero);
- HandleCharAndBreak('.', kStateDot);
- return Nan();
-
- case kStateZero:
- if (ch == '0')
- break;
-
- if (ch >= '1' && ch <= '9') {
- accumulator = ch - '0';
- number_of_digits = 1;
- state = kStateDigit;
- break;
- }
-
- HandleCharAndBreak('.', kStateDot);
- HandleTwoCharsAndBreak('E', 'e', kStateE);
- return Nan();
-
- default:
- NOTREACHED();
- return Nan();
- }
- }
-
- if (state == kStateZero)
- return Zero(sign);
-
- if (state == kStateDigit || state == kStateEDigit ||
- state == kStateDotDigit) {
- int result_exponent = exponent * (exponent_sign == kNegative ? -1 : 1) -
- number_of_digits_after_dot + number_of_extra_digits;
- if (result_exponent < kExponentMin)
- return Zero(kPositive);
-
- const int overflow = result_exponent - kExponentMax + 1;
- if (overflow > 0) {
- if (overflow + number_of_digits - number_of_digits_after_dot > kPrecision)
- return Infinity(sign);
- accumulator = ScaleUp(accumulator, overflow);
- result_exponent -= overflow;
- }
-
- return Decimal(sign, result_exponent, accumulator);
- }
-
- return Nan();
-}
-
-Decimal Decimal::Infinity(const Sign sign) {
- return Decimal(EncodedData(sign, EncodedData::kClassInfinity));
-}
-
-Decimal Decimal::Nan() {
- return Decimal(EncodedData(kPositive, EncodedData::kClassNaN));
-}
-
-Decimal Decimal::Remainder(const Decimal& rhs) const {
- const Decimal quotient = *this / rhs;
- return quotient.IsSpecial()
- ? quotient
- : *this - (quotient.IsNegative() ? quotient.Ceil()
- : quotient.Floor()) *
- rhs;
-}
-
-Decimal Decimal::Round() const {
- if (IsSpecial())
- return *this;
-
- if (Exponent() >= 0)
- return *this;
-
- uint64_t result = data_.Coefficient();
- const int number_of_digits = CountDigits(result);
- const int number_of_drop_digits = -Exponent();
- if (number_of_digits < number_of_drop_digits)
- return Zero(kPositive);
-
- result = ScaleDown(result, number_of_drop_digits - 1);
- if (result % 10 >= 5)
- result += 10;
- result /= 10;
- return Decimal(GetSign(), 0, result);
-}
-
-double Decimal::ToDouble() const {
- if (IsFinite()) {
- bool valid;
- const double double_value = ToString().ToDouble(&valid);
- return valid ? double_value : std::numeric_limits<double>::quiet_NaN();
- }
-
- if (IsInfinity())
- return IsNegative() ? -std::numeric_limits<double>::infinity()
- : std::numeric_limits<double>::infinity();
-
- return std::numeric_limits<double>::quiet_NaN();
-}
-
-String Decimal::ToString() const {
- switch (data_.GetFormatClass()) {
- case EncodedData::kClassInfinity:
- return GetSign() ? "-Infinity" : "Infinity";
-
- case EncodedData::kClassNaN:
- return "NaN";
-
- case EncodedData::kClassNormal:
- case EncodedData::kClassZero:
- break;
-
- default:
- NOTREACHED();
- return "";
- }
-
- StringBuilder builder;
- if (GetSign())
- builder.Append('-');
-
- int original_exponent = Exponent();
- uint64_t coefficient = data_.Coefficient();
-
- if (original_exponent < 0) {
- const int kMaxDigits = DBL_DIG;
- uint64_t last_digit = 0;
- while (CountDigits(coefficient) > kMaxDigits) {
- last_digit = coefficient % 10;
- coefficient /= 10;
- ++original_exponent;
- }
-
- if (last_digit >= 5)
- ++coefficient;
-
- while (original_exponent < 0 && coefficient && !(coefficient % 10)) {
- coefficient /= 10;
- ++original_exponent;
- }
- }
-
- const String digits = String::Number(coefficient);
- int coefficient_length = static_cast<int>(digits.length());
- const int adjusted_exponent = original_exponent + coefficient_length - 1;
- if (original_exponent <= 0 && adjusted_exponent >= -6) {
- if (!original_exponent) {
- builder.Append(digits);
- return builder.ToString();
- }
-
- if (adjusted_exponent >= 0) {
- for (int i = 0; i < coefficient_length; ++i) {
- builder.Append(digits[i]);
- if (i == adjusted_exponent)
- builder.Append('.');
- }
- return builder.ToString();
- }
-
- builder.Append("0.");
- for (int i = adjusted_exponent + 1; i < 0; ++i)
- builder.Append('0');
-
- builder.Append(digits);
-
- } else {
- builder.Append(digits[0]);
- while (coefficient_length >= 2 && digits[coefficient_length - 1] == '0')
- --coefficient_length;
- if (coefficient_length >= 2) {
- builder.Append('.');
- for (int i = 1; i < coefficient_length; ++i)
- builder.Append(digits[i]);
- }
-
- if (adjusted_exponent) {
- builder.Append(adjusted_exponent < 0 ? "e" : "e+");
- builder.AppendNumber(adjusted_exponent);
- }
- }
- return builder.ToString();
-}
-
-Decimal Decimal::Zero(Sign sign) {
- return Decimal(EncodedData(sign, EncodedData::kClassZero));
-}
-
-std::ostream& operator<<(std::ostream& ostream, const Decimal& decimal) {
- Decimal::EncodedData data = decimal.Value();
- return ostream << "encode("
- << String::Number(data.Coefficient()).Ascii().data() << ", "
- << String::Number(data.Exponent()).Ascii().data() << ", "
- << (data.GetSign() == Decimal::kNegative ? "Negative"
- : "Positive")
- << ")=" << decimal.ToString().Ascii().data();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/decimal.h b/chromium/third_party/blink/renderer/platform/decimal.h
deleted file mode 100644
index fe971d67e99..00000000000
--- a/chromium/third_party/blink/renderer/platform/decimal.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_DECIMAL_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_DECIMAL_H_
-
-#include <stdint.h>
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-namespace DecimalPrivate {
-class SpecialValueHandler;
-}
-
-// This class represents decimal base floating point number.
-//
-// FIXME: Once all C++ compiler support decimal type, we should replace this
-// class to compiler supported one. See below URI for current status of decimal
-// type for C++:
-// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1977.html
-class PLATFORM_EXPORT Decimal {
- USING_FAST_MALLOC(Decimal);
-
- public:
- enum Sign {
- kPositive,
- kNegative,
- };
-
- // You should not use EncodedData other than unit testing.
- class EncodedData {
- DISALLOW_NEW();
- // For accessing FormatClass.
- friend class Decimal;
- friend class DecimalPrivate::SpecialValueHandler;
-
- public:
- EncodedData(Sign, int exponent, uint64_t coefficient);
-
- bool operator==(const EncodedData&) const;
- bool operator!=(const EncodedData& another) const {
- return !operator==(another);
- }
-
- uint64_t Coefficient() const { return coefficient_; }
- int CountDigits() const;
- int Exponent() const { return exponent_; }
- bool IsFinite() const { return !IsSpecial(); }
- bool IsInfinity() const { return format_class_ == kClassInfinity; }
- bool IsNaN() const { return format_class_ == kClassNaN; }
- bool IsSpecial() const {
- return format_class_ == kClassInfinity || format_class_ == kClassNaN;
- }
- bool IsZero() const { return format_class_ == kClassZero; }
- Sign GetSign() const { return sign_; }
- void SetSign(Sign sign) { sign_ = sign; }
-
- private:
- enum FormatClass {
- kClassInfinity,
- kClassNormal,
- kClassNaN,
- kClassZero,
- };
-
- EncodedData(Sign, FormatClass);
- FormatClass GetFormatClass() const { return format_class_; }
-
- uint64_t coefficient_;
- int16_t exponent_;
- FormatClass format_class_;
- Sign sign_;
- };
-
- Decimal(int32_t = 0);
- Decimal(Sign, int exponent, uint64_t coefficient);
- Decimal(const Decimal&);
-
- Decimal& operator=(const Decimal&);
- Decimal& operator+=(const Decimal&);
- Decimal& operator-=(const Decimal&);
- Decimal& operator*=(const Decimal&);
- Decimal& operator/=(const Decimal&);
-
- Decimal operator-() const;
-
- bool operator==(const Decimal&) const;
- bool operator!=(const Decimal&) const;
- bool operator<(const Decimal&) const;
- bool operator<=(const Decimal&) const;
- bool operator>(const Decimal&) const;
- bool operator>=(const Decimal&) const;
-
- Decimal operator+(const Decimal&) const;
- Decimal operator-(const Decimal&) const;
- Decimal operator*(const Decimal&)const;
- Decimal operator/(const Decimal&) const;
-
- int Exponent() const {
- DCHECK(IsFinite());
- return data_.Exponent();
- }
-
- bool IsFinite() const { return data_.IsFinite(); }
- bool IsInfinity() const { return data_.IsInfinity(); }
- bool IsNaN() const { return data_.IsNaN(); }
- bool IsNegative() const { return GetSign() == kNegative; }
- bool IsPositive() const { return GetSign() == kPositive; }
- bool IsSpecial() const { return data_.IsSpecial(); }
- bool IsZero() const { return data_.IsZero(); }
-
- Decimal Abs() const;
- Decimal Ceil() const;
- Decimal Floor() const;
- Decimal Remainder(const Decimal&) const;
- Decimal Round() const;
-
- double ToDouble() const;
- // Note: toString method supports infinity and nan but fromString not.
- String ToString() const;
-
- static Decimal FromDouble(double);
- // fromString supports following syntax EBNF:
- // number ::= sign? digit+ ('.' digit*) (exponent-marker sign? digit+)?
- // | sign? '.' digit+ (exponent-marker sign? digit+)?
- // sign ::= '+' | '-'
- // exponent-marker ::= 'e' | 'E'
- // digit ::= '0' | '1' | ... | '9'
- // Note: fromString doesn't support "infinity" and "nan".
- static Decimal FromString(const String&);
- static Decimal Infinity(Sign);
- static Decimal Nan();
- static Decimal Zero(Sign);
-
- // You should not use below methods. We expose them for unit testing.
- explicit Decimal(const EncodedData&);
- const EncodedData& Value() const { return data_; }
-
- private:
- struct AlignedOperands {
- uint64_t lhs_coefficient;
- uint64_t rhs_coefficient;
- int exponent;
- };
-
- Decimal(double);
- Decimal CompareTo(const Decimal&) const;
-
- static AlignedOperands AlignOperands(const Decimal& lhs, const Decimal& rhs);
- static inline Sign InvertSign(Sign sign) {
- return sign == kNegative ? kPositive : kNegative;
- }
-
- Sign GetSign() const { return data_.GetSign(); }
-
- EncodedData data_;
-};
-
-PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, const Decimal&);
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_DECIMAL_H_
diff --git a/chromium/third_party/blink/renderer/platform/decimal_test.cc b/chromium/third_party/blink/renderer/platform/decimal_test.cc
deleted file mode 100644
index 8bd321acfe1..00000000000
--- a/chromium/third_party/blink/renderer/platform/decimal_test.cc
+++ /dev/null
@@ -1,1161 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/platform/decimal.h"
-
-#include <float.h>
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/wtf/math_extras.h"
-#include "third_party/blink/renderer/platform/wtf/text/cstring.h"
-
-namespace blink {
-
-// Simulate core/html/forms/StepRange
-class DecimalStepRange {
- public:
- Decimal maximum;
- Decimal minimum;
- Decimal step;
-
- DecimalStepRange(const Decimal& minimum,
- const Decimal& maximum,
- const Decimal& step)
- : maximum(maximum), minimum(minimum), step(step) {}
-
- Decimal ClampValue(Decimal value) const {
- const Decimal result = minimum + ((value - minimum) / step).Round() * step;
- DCHECK(result.IsFinite());
- return result > maximum ? result - step : result;
- }
-};
-
-class DecimalTest : public testing::Test {
- protected:
- using Sign = Decimal::Sign;
- static const Sign kPositive = Decimal::kPositive;
- static const Sign kNegative = Decimal::kNegative;
-
- Decimal Encode(uint64_t coefficient, int exponent, Sign sign) {
- return Decimal(sign, exponent, coefficient);
- }
-
- Decimal FromString(const String& string) {
- return Decimal::FromString(string);
- }
-
- Decimal StepDown(const String& minimum,
- const String& maximum,
- const String& step,
- const String& value_string,
- int number_of_step_times) {
- DecimalStepRange step_range(FromString(minimum), FromString(maximum),
- FromString(step));
- Decimal value = FromString(value_string);
- for (int i = 0; i < number_of_step_times; ++i) {
- value -= step_range.step;
- value = step_range.ClampValue(value);
- }
- return value;
- }
-
- Decimal StepUp(const String& minimum,
- const String& maximum,
- const String& step,
- const String& value_string,
- int number_of_step_times) {
- DecimalStepRange step_range(FromString(minimum), FromString(maximum),
- FromString(step));
- Decimal value = FromString(value_string);
- for (int i = 0; i < number_of_step_times; ++i) {
- value += step_range.step;
- value = step_range.ClampValue(value);
- }
- return value;
- }
-};
-
-// FIXME: We should use expectedSign without "Decimal::", however, g++ causes
-// undefined references for DecimalTest::Positive and Negative.
-#define EXPECT_DECIMAL_ENCODED_DATA_EQ(expectedCoefficient, expectedExponent, \
- expectedSign, decimal) \
- EXPECT_EQ((expectedCoefficient), (decimal).Value().Coefficient()); \
- EXPECT_EQ((expectedExponent), (decimal).Value().Exponent()); \
- EXPECT_EQ(Decimal::expectedSign, (decimal).Value().GetSign());
-
-#define EXPECT_DECIMAL_STREQ(expected, decimal) \
- EXPECT_STREQ((expected), (decimal).ToString().Ascii().data())
-
-TEST_F(DecimalTest, Abs) {
- EXPECT_EQ(Encode(0, 0, kPositive), Encode(0, 0, kPositive).Abs());
- EXPECT_EQ(Encode(0, 0, kPositive), Encode(0, 0, kNegative).Abs());
-
- EXPECT_EQ(Encode(0, 10, kPositive), Encode(0, 10, kPositive).Abs());
- EXPECT_EQ(Encode(0, 10, kPositive), Encode(0, 10, kNegative).Abs());
-
- EXPECT_EQ(Encode(0, -10, kPositive), Encode(0, -10, kPositive).Abs());
- EXPECT_EQ(Encode(0, -10, kPositive), Encode(0, -10, kNegative).Abs());
-
- EXPECT_EQ(Encode(1, 0, kPositive), Encode(1, 0, kPositive).Abs());
- EXPECT_EQ(Encode(1, 0, kPositive), Encode(1, 0, kNegative).Abs());
-
- EXPECT_EQ(Encode(1, 10, kPositive), Encode(1, 10, kPositive).Abs());
- EXPECT_EQ(Encode(1, 10, kPositive), Encode(1, 10, kNegative).Abs());
-
- EXPECT_EQ(Encode(1, -10, kPositive), Encode(1, -10, kPositive).Abs());
- EXPECT_EQ(Encode(1, -10, kPositive), Encode(1, -10, kNegative).Abs());
-}
-
-TEST_F(DecimalTest, AbsBigExponent) {
- EXPECT_EQ(Encode(1, 1000, kPositive), Encode(1, 1000, kPositive).Abs());
- EXPECT_EQ(Encode(1, 1000, kPositive), Encode(1, 1000, kNegative).Abs());
-}
-
-TEST_F(DecimalTest, AbsSmallExponent) {
- EXPECT_EQ(Encode(1, -1000, kPositive), Encode(1, -1000, kPositive).Abs());
- EXPECT_EQ(Encode(1, -1000, kPositive), Encode(1, -1000, kNegative).Abs());
-}
-
-TEST_F(DecimalTest, AbsSpecialValues) {
- EXPECT_EQ(Decimal::Infinity(kPositive), Decimal::Infinity(kPositive).Abs());
- EXPECT_EQ(Decimal::Infinity(kPositive), Decimal::Infinity(kNegative).Abs());
- EXPECT_EQ(Decimal::Nan(), Decimal::Nan().Abs());
-}
-
-TEST_F(DecimalTest, Add) {
- EXPECT_EQ(Encode(0, 0, kPositive), Decimal(0) + Decimal(0));
- EXPECT_EQ(Decimal(1), Decimal(2) + Decimal(-1));
- EXPECT_EQ(Decimal(1), Decimal(-1) + Decimal(2));
- EXPECT_EQ(Encode(100, 0, kPositive), Decimal(99) + Decimal(1));
- EXPECT_EQ(Encode(100, 0, kNegative), Decimal(-50) + Decimal(-50));
- EXPECT_EQ(Encode(UINT64_C(1000000000000000), 35, kPositive),
- Encode(1, 50, kPositive) + Decimal(1));
- EXPECT_EQ(Encode(UINT64_C(1000000000000000), 35, kPositive),
- Decimal(1) + Encode(1, 50, kPositive));
- EXPECT_EQ(Encode(UINT64_C(10000000001), 0, kPositive),
- Encode(1, 10, kPositive) + Decimal(1));
- EXPECT_EQ(Encode(UINT64_C(10000000001), 0, kPositive),
- Decimal(1) + Encode(1, 10, kPositive));
- EXPECT_EQ(Encode(1, 0, kPositive),
- Encode(1, -1022, kPositive) + Encode(1, 0, kPositive));
- EXPECT_EQ(Encode(2, -1022, kPositive),
- Encode(1, -1022, kPositive) + Encode(1, -1022, kPositive));
-}
-
-TEST_F(DecimalTest, AddBigExponent) {
- EXPECT_EQ(Encode(1, 1022, kPositive),
- Encode(1, 1022, kPositive) + Encode(1, 0, kPositive));
- EXPECT_EQ(Encode(2, 1022, kPositive),
- Encode(1, 1022, kPositive) + Encode(1, 1022, kPositive));
- EXPECT_EQ(Decimal::Infinity(kPositive),
- Encode(std::numeric_limits<uint64_t>::max(), 1022, kPositive) +
- Encode(1, 0, kPositive));
- EXPECT_EQ(Encode(1, 1022, kPositive),
- Encode(1, 1022, kPositive) + Encode(1, -1000, kPositive));
-}
-
-TEST_F(DecimalTest, AddSmallExponent) {
- EXPECT_EQ(Encode(1, 0, kPositive),
- Encode(1, -1022, kPositive) + Encode(1, 0, kPositive));
- EXPECT_EQ(Encode(2, -1022, kPositive),
- Encode(1, -1022, kPositive) + Encode(1, -1022, kPositive));
-}
-
-TEST_F(DecimalTest, AddSpecialValues) {
- const Decimal infinity(Decimal::Infinity(kPositive));
- const Decimal minus_infinity(Decimal::Infinity(kNegative));
- const Decimal na_n(Decimal::Nan());
- const Decimal ten(10);
-
- EXPECT_EQ(infinity, infinity + infinity);
- EXPECT_EQ(na_n, infinity + minus_infinity);
- EXPECT_EQ(na_n, minus_infinity + infinity);
- EXPECT_EQ(minus_infinity, minus_infinity + minus_infinity);
-
- EXPECT_EQ(infinity, infinity + ten);
- EXPECT_EQ(infinity, ten + infinity);
- EXPECT_EQ(minus_infinity, minus_infinity + ten);
- EXPECT_EQ(minus_infinity, ten + minus_infinity);
-
- EXPECT_EQ(na_n, na_n + na_n);
- EXPECT_EQ(na_n, na_n + ten);
- EXPECT_EQ(na_n, ten + na_n);
-
- EXPECT_EQ(na_n, na_n - infinity);
- EXPECT_EQ(na_n, na_n - minus_infinity);
- EXPECT_EQ(na_n, infinity - na_n);
- EXPECT_EQ(na_n, minus_infinity - na_n);
-}
-
-TEST_F(DecimalTest, Ceil) {
- EXPECT_EQ(Decimal(1), Decimal(1).Ceil());
- EXPECT_EQ(Decimal(1), Encode(1, -10, kPositive).Ceil());
- EXPECT_EQ(Decimal(2), Encode(11, -1, kPositive).Ceil());
- EXPECT_EQ(Decimal(2), Encode(13, -1, kPositive).Ceil());
- EXPECT_EQ(Decimal(2), Encode(15, -1, kPositive).Ceil());
- EXPECT_EQ(Decimal(2), Encode(19, -1, kPositive).Ceil());
- EXPECT_EQ(Decimal(2), Encode(151, -2, kPositive).Ceil());
- EXPECT_EQ(Decimal(2), Encode(101, -2, kPositive).Ceil());
- EXPECT_EQ(Decimal(1), Encode(199, -3, kPositive).Ceil());
- EXPECT_EQ(Decimal(2), Encode(199, -2, kPositive).Ceil());
- EXPECT_EQ(Decimal(3), Encode(209, -2, kPositive).Ceil());
-
- EXPECT_EQ(Decimal(-1), Decimal(-1).Ceil());
- EXPECT_EQ(Decimal(0), Encode(1, -10, kNegative).Ceil());
- EXPECT_EQ(Decimal(-1), Encode(11, -1, kNegative).Ceil());
- EXPECT_EQ(Decimal(-1), Encode(13, -1, kNegative).Ceil());
- EXPECT_EQ(Decimal(-1), Encode(15, -1, kNegative).Ceil());
- EXPECT_EQ(Decimal(-1), Encode(19, -1, kNegative).Ceil());
- EXPECT_EQ(Decimal(-1), Encode(151, -2, kNegative).Ceil());
- EXPECT_EQ(Decimal(-1), Encode(101, -2, kNegative).Ceil());
- EXPECT_EQ(Decimal(0), Encode(199, -3, kNegative).Ceil());
- EXPECT_EQ(Decimal(-1), Encode(199, -2, kNegative).Ceil());
- EXPECT_EQ(Decimal(-2), Encode(209, -2, kNegative).Ceil());
- EXPECT_EQ(Decimal(1),
- Encode(UINT64_C(123456789012345678), -18, kPositive).Ceil());
-}
-
-TEST_F(DecimalTest, CeilingBigExponent) {
- EXPECT_EQ(Encode(1, 1000, kPositive), Encode(1, 1000, kPositive).Ceil());
- EXPECT_EQ(Encode(1, 1000, kNegative), Encode(1, 1000, kNegative).Ceil());
-}
-
-TEST_F(DecimalTest, CeilingSmallExponent) {
- EXPECT_EQ(Encode(1, 0, kPositive), Encode(1, -1000, kPositive).Ceil());
- EXPECT_EQ(Encode(0, 0, kNegative), Encode(1, -1000, kNegative).Ceil());
-}
-
-TEST_F(DecimalTest, CeilingSpecialValues) {
- EXPECT_EQ(Decimal::Infinity(kPositive), Decimal::Infinity(kPositive).Ceil());
- EXPECT_EQ(Decimal::Infinity(kNegative), Decimal::Infinity(kNegative).Ceil());
- EXPECT_EQ(Decimal::Nan(), Decimal::Nan().Ceil());
-}
-
-TEST_F(DecimalTest, Compare) {
- EXPECT_TRUE(Decimal(0) == Decimal(0));
- EXPECT_TRUE(Decimal(0) != Decimal(1));
- EXPECT_TRUE(Decimal(0) < Decimal(1));
- EXPECT_TRUE(Decimal(0) <= Decimal(0));
- EXPECT_TRUE(Decimal(0) > Decimal(-1));
- EXPECT_TRUE(Decimal(0) >= Decimal(0));
-
- EXPECT_FALSE(Decimal(1) == Decimal(2));
- EXPECT_FALSE(Decimal(1) != Decimal(1));
- EXPECT_FALSE(Decimal(1) < Decimal(0));
- EXPECT_FALSE(Decimal(1) <= Decimal(0));
- EXPECT_FALSE(Decimal(1) > Decimal(2));
- EXPECT_FALSE(Decimal(1) >= Decimal(2));
-}
-
-TEST_F(DecimalTest, CompareBigExponent) {
- EXPECT_TRUE(Encode(1, 1000, kPositive) == Encode(1, 1000, kPositive));
- EXPECT_FALSE(Encode(1, 1000, kPositive) != Encode(1, 1000, kPositive));
- EXPECT_FALSE(Encode(1, 1000, kPositive) < Encode(1, 1000, kPositive));
- EXPECT_TRUE(Encode(1, 1000, kPositive) <= Encode(1, 1000, kPositive));
- EXPECT_FALSE(Encode(1, 1000, kPositive) > Encode(1, 1000, kPositive));
- EXPECT_TRUE(Encode(1, 1000, kPositive) >= Encode(1, 1000, kPositive));
-
- EXPECT_TRUE(Encode(1, 1000, kNegative) == Encode(1, 1000, kNegative));
- EXPECT_FALSE(Encode(1, 1000, kNegative) != Encode(1, 1000, kNegative));
- EXPECT_FALSE(Encode(1, 1000, kNegative) < Encode(1, 1000, kNegative));
- EXPECT_TRUE(Encode(1, 1000, kNegative) <= Encode(1, 1000, kNegative));
- EXPECT_FALSE(Encode(1, 1000, kNegative) > Encode(1, 1000, kNegative));
- EXPECT_TRUE(Encode(1, 1000, kNegative) >= Encode(1, 1000, kNegative));
-
- EXPECT_FALSE(Encode(2, 1000, kPositive) == Encode(1, 1000, kPositive));
- EXPECT_TRUE(Encode(2, 1000, kPositive) != Encode(1, 1000, kPositive));
- EXPECT_FALSE(Encode(2, 1000, kPositive) < Encode(1, 1000, kPositive));
- EXPECT_FALSE(Encode(2, 1000, kPositive) <= Encode(1, 1000, kPositive));
- EXPECT_TRUE(Encode(2, 1000, kPositive) > Encode(1, 1000, kPositive));
- EXPECT_TRUE(Encode(2, 1000, kPositive) >= Encode(1, 1000, kPositive));
-
- EXPECT_FALSE(Encode(2, 1000, kNegative) == Encode(1, 1000, kNegative));
- EXPECT_TRUE(Encode(2, 1000, kNegative) != Encode(1, 1000, kNegative));
- EXPECT_TRUE(Encode(2, 1000, kNegative) < Encode(1, 1000, kNegative));
- EXPECT_TRUE(Encode(2, 1000, kNegative) <= Encode(1, 1000, kNegative));
- EXPECT_FALSE(Encode(2, 1000, kNegative) > Encode(1, 1000, kNegative));
- EXPECT_FALSE(Encode(2, 1000, kNegative) >= Encode(1, 1000, kNegative));
-}
-
-TEST_F(DecimalTest, CompareSmallExponent) {
- EXPECT_TRUE(Encode(1, -1000, kPositive) == Encode(1, -1000, kPositive));
- EXPECT_FALSE(Encode(1, -1000, kPositive) != Encode(1, -1000, kPositive));
- EXPECT_FALSE(Encode(1, -1000, kPositive) < Encode(1, -1000, kPositive));
- EXPECT_TRUE(Encode(1, -1000, kPositive) <= Encode(1, -1000, kPositive));
- EXPECT_FALSE(Encode(1, -1000, kPositive) > Encode(1, -1000, kPositive));
- EXPECT_TRUE(Encode(1, -1000, kPositive) >= Encode(1, -1000, kPositive));
-
- EXPECT_TRUE(Encode(1, -1000, kNegative) == Encode(1, -1000, kNegative));
- EXPECT_FALSE(Encode(1, -1000, kNegative) != Encode(1, -1000, kNegative));
- EXPECT_FALSE(Encode(1, -1000, kNegative) < Encode(1, -1000, kNegative));
- EXPECT_TRUE(Encode(1, -1000, kNegative) <= Encode(1, -1000, kNegative));
- EXPECT_FALSE(Encode(1, -1000, kNegative) > Encode(1, -1000, kNegative));
- EXPECT_TRUE(Encode(1, -1000, kNegative) >= Encode(1, -1000, kNegative));
-
- EXPECT_FALSE(Encode(2, -1000, kPositive) == Encode(1, -1000, kPositive));
- EXPECT_TRUE(Encode(2, -1000, kPositive) != Encode(1, -1000, kPositive));
- EXPECT_FALSE(Encode(2, -1000, kPositive) < Encode(1, -1000, kPositive));
- EXPECT_FALSE(Encode(2, -1000, kPositive) <= Encode(1, -1000, kPositive));
- EXPECT_TRUE(Encode(2, -1000, kPositive) > Encode(1, -1000, kPositive));
- EXPECT_TRUE(Encode(2, -1000, kPositive) >= Encode(1, -1000, kPositive));
-
- EXPECT_FALSE(Encode(2, -1000, kNegative) == Encode(1, -1000, kNegative));
- EXPECT_TRUE(Encode(2, -1000, kNegative) != Encode(1, -1000, kNegative));
- EXPECT_TRUE(Encode(2, -1000, kNegative) < Encode(1, -1000, kNegative));
- EXPECT_TRUE(Encode(2, -1000, kNegative) <= Encode(1, -1000, kNegative));
- EXPECT_FALSE(Encode(2, -1000, kNegative) > Encode(1, -1000, kNegative));
- EXPECT_FALSE(Encode(2, -1000, kNegative) >= Encode(1, -1000, kNegative));
-}
-
-TEST_F(DecimalTest, CompareSpecialValues) {
- const Decimal infinity(Decimal::Infinity(kPositive));
- const Decimal minus_infinity(Decimal::Infinity(kNegative));
- const Decimal na_n(Decimal::Nan());
- const Decimal zero(Decimal::Zero(kPositive));
- const Decimal minus_zero(Decimal::Zero(kNegative));
- const Decimal ten(10);
-
- EXPECT_TRUE(zero == zero);
- EXPECT_FALSE(zero != zero);
- EXPECT_FALSE(zero < zero);
- EXPECT_TRUE(zero <= zero);
- EXPECT_FALSE(zero > zero);
- EXPECT_TRUE(zero >= zero);
-
- EXPECT_TRUE(zero == minus_zero);
- EXPECT_FALSE(zero != minus_zero);
- EXPECT_FALSE(zero < minus_zero);
- EXPECT_TRUE(zero <= minus_zero);
- EXPECT_FALSE(zero > minus_zero);
- EXPECT_TRUE(zero >= minus_zero);
-
- EXPECT_TRUE(minus_zero == zero);
- EXPECT_FALSE(minus_zero != zero);
- EXPECT_FALSE(minus_zero < zero);
- EXPECT_TRUE(minus_zero <= zero);
- EXPECT_FALSE(minus_zero > zero);
- EXPECT_TRUE(minus_zero >= zero);
-
- EXPECT_TRUE(minus_zero == minus_zero);
- EXPECT_FALSE(minus_zero != minus_zero);
- EXPECT_FALSE(minus_zero < minus_zero);
- EXPECT_TRUE(minus_zero <= minus_zero);
- EXPECT_FALSE(minus_zero > minus_zero);
- EXPECT_TRUE(minus_zero >= minus_zero);
-
- EXPECT_TRUE(infinity == infinity);
- EXPECT_FALSE(infinity != infinity);
- EXPECT_FALSE(infinity < infinity);
- EXPECT_TRUE(infinity <= infinity);
- EXPECT_FALSE(infinity > infinity);
- EXPECT_TRUE(infinity >= infinity);
-
- EXPECT_FALSE(infinity == ten);
- EXPECT_TRUE(infinity != ten);
- EXPECT_FALSE(infinity < ten);
- EXPECT_FALSE(infinity <= ten);
- EXPECT_TRUE(infinity > ten);
- EXPECT_TRUE(infinity >= ten);
-
- EXPECT_FALSE(infinity == minus_infinity);
- EXPECT_TRUE(infinity != minus_infinity);
- EXPECT_FALSE(infinity < minus_infinity);
- EXPECT_FALSE(infinity <= minus_infinity);
- EXPECT_TRUE(infinity > minus_infinity);
- EXPECT_TRUE(infinity >= minus_infinity);
-
- EXPECT_FALSE(infinity == na_n);
- EXPECT_FALSE(infinity != na_n);
- EXPECT_FALSE(infinity < na_n);
- EXPECT_FALSE(infinity <= na_n);
- EXPECT_FALSE(infinity > na_n);
- EXPECT_FALSE(infinity >= na_n);
-
- EXPECT_FALSE(minus_infinity == infinity);
- EXPECT_TRUE(minus_infinity != infinity);
- EXPECT_TRUE(minus_infinity < infinity);
- EXPECT_TRUE(minus_infinity <= infinity);
- EXPECT_FALSE(minus_infinity > infinity);
- EXPECT_FALSE(minus_infinity >= infinity);
-
- EXPECT_FALSE(minus_infinity == ten);
- EXPECT_TRUE(minus_infinity != ten);
- EXPECT_TRUE(minus_infinity < ten);
- EXPECT_TRUE(minus_infinity <= ten);
- EXPECT_FALSE(minus_infinity > ten);
- EXPECT_FALSE(minus_infinity >= ten);
-
- EXPECT_TRUE(minus_infinity == minus_infinity);
- EXPECT_FALSE(minus_infinity != minus_infinity);
- EXPECT_FALSE(minus_infinity < minus_infinity);
- EXPECT_TRUE(minus_infinity <= minus_infinity);
- EXPECT_FALSE(minus_infinity > minus_infinity);
- EXPECT_TRUE(minus_infinity >= minus_infinity);
-
- EXPECT_FALSE(minus_infinity == na_n);
- EXPECT_FALSE(minus_infinity != na_n);
- EXPECT_FALSE(minus_infinity < na_n);
- EXPECT_FALSE(minus_infinity <= na_n);
- EXPECT_FALSE(minus_infinity > na_n);
- EXPECT_FALSE(minus_infinity >= na_n);
-
- EXPECT_FALSE(na_n == infinity);
- EXPECT_FALSE(na_n != infinity);
- EXPECT_FALSE(na_n < infinity);
- EXPECT_FALSE(na_n <= infinity);
- EXPECT_FALSE(na_n > infinity);
- EXPECT_FALSE(na_n >= infinity);
-
- EXPECT_FALSE(na_n == ten);
- EXPECT_FALSE(na_n != ten);
- EXPECT_FALSE(na_n < ten);
- EXPECT_FALSE(na_n <= ten);
- EXPECT_FALSE(na_n > ten);
- EXPECT_FALSE(na_n >= ten);
-
- EXPECT_FALSE(na_n == minus_infinity);
- EXPECT_FALSE(na_n != minus_infinity);
- EXPECT_FALSE(na_n < minus_infinity);
- EXPECT_FALSE(na_n <= minus_infinity);
- EXPECT_FALSE(na_n > minus_infinity);
- EXPECT_FALSE(na_n >= minus_infinity);
-
- EXPECT_TRUE(na_n == na_n);
- EXPECT_FALSE(na_n != na_n);
- EXPECT_FALSE(na_n < na_n);
- EXPECT_TRUE(na_n <= na_n);
- EXPECT_FALSE(na_n > na_n);
- EXPECT_TRUE(na_n >= na_n);
-}
-
-TEST_F(DecimalTest, Constructor) {
- EXPECT_DECIMAL_ENCODED_DATA_EQ(0u, 0, kPositive, Encode(0, 0, kPositive));
- EXPECT_DECIMAL_ENCODED_DATA_EQ(0u, 0, kNegative, Encode(0, 0, kNegative));
- EXPECT_DECIMAL_ENCODED_DATA_EQ(1u, 0, kPositive, Encode(1, 0, kPositive));
- EXPECT_DECIMAL_ENCODED_DATA_EQ(1u, 0, kNegative, Encode(1, 0, kNegative));
- EXPECT_DECIMAL_ENCODED_DATA_EQ(1u, 1022, kPositive,
- Encode(1, 1022, kPositive));
- EXPECT_DECIMAL_ENCODED_DATA_EQ(1u, 1022, kNegative,
- Encode(1, 1022, kNegative));
- EXPECT_DECIMAL_ENCODED_DATA_EQ(1u, 1023, kPositive,
- Encode(1, 1023, kPositive));
- EXPECT_DECIMAL_ENCODED_DATA_EQ(1u, 1023, kNegative,
- Encode(1, 1023, kNegative));
- EXPECT_TRUE(Encode(1, 2000, kPositive).IsInfinity());
- EXPECT_TRUE(Encode(1, 2000, kNegative).IsInfinity());
- EXPECT_DECIMAL_ENCODED_DATA_EQ(0u, 0, kPositive, Encode(1, -2000, kPositive));
- EXPECT_DECIMAL_ENCODED_DATA_EQ(0u, 0, kNegative, Encode(1, -2000, kNegative));
- EXPECT_DECIMAL_ENCODED_DATA_EQ(
- UINT64_C(99999999999999998), 0, kPositive,
- Encode(UINT64_C(99999999999999998), 0, kPositive));
- EXPECT_DECIMAL_ENCODED_DATA_EQ(
- UINT64_C(99999999999999998), 0, kNegative,
- Encode(UINT64_C(99999999999999998), 0, kNegative));
- EXPECT_DECIMAL_ENCODED_DATA_EQ(
- UINT64_C(99999999999999999), 0, kPositive,
- Encode(UINT64_C(99999999999999999), 0, kPositive));
- EXPECT_DECIMAL_ENCODED_DATA_EQ(
- UINT64_C(99999999999999999), 0, kNegative,
- Encode(UINT64_C(99999999999999999), 0, kNegative));
- EXPECT_DECIMAL_ENCODED_DATA_EQ(
- UINT64_C(100000000000000000), 0, kPositive,
- Encode(UINT64_C(100000000000000000), 0, kPositive));
- EXPECT_DECIMAL_ENCODED_DATA_EQ(
- UINT64_C(100000000000000000), 0, kNegative,
- Encode(UINT64_C(100000000000000000), 0, kNegative));
-}
-
-TEST_F(DecimalTest, Division) {
- EXPECT_EQ(Encode(0, 0, kPositive), Decimal(0) / Decimal(1));
- EXPECT_EQ(Encode(2, 0, kNegative), Decimal(2) / Decimal(-1));
- EXPECT_EQ(Encode(5, -1, kNegative), Decimal(-1) / Decimal(2));
- EXPECT_EQ(Encode(99, 0, kPositive), Decimal(99) / Decimal(1));
- EXPECT_EQ(Decimal(1), Decimal(-50) / Decimal(-50));
- EXPECT_EQ(Encode(UINT64_C(333333333333333333), -18, kPositive),
- Decimal(1) / Decimal(3));
- EXPECT_EQ(Encode(UINT64_C(12345678901234), -1, kPositive),
- Encode(UINT64_C(12345678901234), 0, kPositive) / Decimal(10));
- EXPECT_EQ(Encode(UINT64_C(500005000050000500), -18, kPositive),
- Decimal(50000) / Decimal(99999));
-}
-
-TEST_F(DecimalTest, DivisionBigExponent) {
- EXPECT_EQ(Encode(1, 1022, kPositive),
- Encode(1, 1022, kPositive) / Encode(1, 0, kPositive));
- EXPECT_EQ(Encode(1, 0, kPositive),
- Encode(1, 1022, kPositive) / Encode(1, 1022, kPositive));
- EXPECT_EQ(Decimal::Infinity(kPositive),
- Encode(1, 1022, kPositive) / Encode(1, -1000, kPositive));
-}
-
-TEST_F(DecimalTest, DivisionSmallExponent) {
- EXPECT_EQ(Encode(1, -1022, kPositive),
- Encode(1, -1022, kPositive) / Encode(1, 0, kPositive));
- EXPECT_EQ(Encode(1, 0, kPositive),
- Encode(1, -1022, kPositive) / Encode(1, -1022, kPositive));
-}
-
-TEST_F(DecimalTest, DivisionSpecialValues) {
- const Decimal infinity(Decimal::Infinity(kPositive));
- const Decimal minus_infinity(Decimal::Infinity(kNegative));
- const Decimal na_n(Decimal::Nan());
- const Decimal zero(Decimal::Zero(kPositive));
- const Decimal minus_zero(Decimal::Zero(kNegative));
- const Decimal ten(10);
- const Decimal minus_ten(-10);
-
- EXPECT_EQ(na_n, zero / zero);
- EXPECT_EQ(na_n, zero / minus_zero);
- EXPECT_EQ(na_n, minus_zero / zero);
- EXPECT_EQ(na_n, minus_zero / minus_zero);
-
- EXPECT_EQ(infinity, ten / zero);
- EXPECT_EQ(minus_infinity, ten / minus_zero);
- EXPECT_EQ(minus_infinity, minus_ten / zero);
- EXPECT_EQ(infinity, minus_ten / minus_zero);
-
- EXPECT_EQ(infinity, infinity / zero);
- EXPECT_EQ(minus_infinity, infinity / minus_zero);
- EXPECT_EQ(minus_infinity, minus_infinity / zero);
- EXPECT_EQ(infinity, minus_infinity / minus_zero);
-
- EXPECT_EQ(na_n, infinity / infinity);
- EXPECT_EQ(na_n, infinity / minus_infinity);
- EXPECT_EQ(na_n, minus_infinity / infinity);
- EXPECT_EQ(na_n, minus_infinity / minus_infinity);
-
- EXPECT_EQ(zero, ten / infinity);
- EXPECT_EQ(minus_zero, ten / minus_infinity);
- EXPECT_EQ(minus_zero, minus_ten / infinity);
- EXPECT_EQ(zero, minus_ten / minus_infinity);
-
- EXPECT_EQ(na_n, na_n / na_n);
- EXPECT_EQ(na_n, na_n / ten);
- EXPECT_EQ(na_n, ten / na_n);
-
- EXPECT_EQ(na_n, na_n / infinity);
- EXPECT_EQ(na_n, na_n / minus_infinity);
- EXPECT_EQ(na_n, infinity / na_n);
- EXPECT_EQ(na_n, minus_infinity / na_n);
-}
-
-TEST_F(DecimalTest, EncodedData) {
- EXPECT_EQ(Encode(0, 0, kPositive), Encode(0, 0, kPositive));
- EXPECT_EQ(Encode(0, 0, kNegative), Encode(0, 0, kNegative));
- EXPECT_EQ(Decimal(1), Decimal(1));
- EXPECT_EQ(Encode(1, 0, kNegative), Encode(1, 0, kNegative));
- EXPECT_EQ(Decimal::Infinity(kPositive), Encode(1, 2000, kPositive));
- EXPECT_EQ(Decimal::Zero(kPositive), Encode(1, -2000, kPositive));
-}
-
-TEST_F(DecimalTest, Floor) {
- EXPECT_EQ(Decimal(1), Decimal(1).Floor());
- EXPECT_EQ(Decimal(0), Encode(1, -10, kPositive).Floor());
- EXPECT_EQ(Decimal(1), Encode(11, -1, kPositive).Floor());
- EXPECT_EQ(Decimal(1), Encode(13, -1, kPositive).Floor());
- EXPECT_EQ(Decimal(1), Encode(15, -1, kPositive).Floor());
- EXPECT_EQ(Decimal(1), Encode(19, -1, kPositive).Floor());
- EXPECT_EQ(Decimal(1), Encode(193332, -5, kPositive).Floor());
- EXPECT_EQ(Decimal(12), Encode(12002, -3, kPositive).Floor());
-
- EXPECT_EQ(Decimal(-1), Decimal(-1).Floor());
- EXPECT_EQ(Decimal(-1), Encode(1, -10, kNegative).Floor());
- EXPECT_EQ(Decimal(-2), Encode(11, -1, kNegative).Floor());
- EXPECT_EQ(Decimal(-2), Encode(13, -1, kNegative).Floor());
- EXPECT_EQ(Decimal(-2), Encode(15, -1, kNegative).Floor());
- EXPECT_EQ(Decimal(-2), Encode(19, -1, kNegative).Floor());
- EXPECT_EQ(Decimal(-2), Encode(193332, -5, kNegative).Floor());
- EXPECT_EQ(Decimal(-13), Encode(12002, -3, kNegative).Floor());
-
- // crbug.com/572769
- EXPECT_EQ(Decimal(-1), Encode(992971299197409433, -18, kNegative).Floor());
-}
-
-TEST_F(DecimalTest, FloorBigExponent) {
- EXPECT_EQ(Encode(1, 1000, kPositive), Encode(1, 1000, kPositive).Floor());
- EXPECT_EQ(Encode(1, 1000, kNegative), Encode(1, 1000, kNegative).Floor());
-}
-
-TEST_F(DecimalTest, FloorSmallExponent) {
- EXPECT_EQ(Encode(0, 0, kPositive), Encode(1, -1000, kPositive).Floor());
- EXPECT_EQ(Encode(1, 0, kNegative), Encode(1, -1000, kNegative).Floor());
-}
-
-TEST_F(DecimalTest, FloorSpecialValues) {
- EXPECT_EQ(Decimal::Infinity(kPositive), Decimal::Infinity(kPositive).Floor());
- EXPECT_EQ(Decimal::Infinity(kNegative), Decimal::Infinity(kNegative).Floor());
- EXPECT_EQ(Decimal::Nan(), Decimal::Nan().Floor());
-}
-
-TEST_F(DecimalTest, FromDouble) {
- EXPECT_EQ(Encode(0, 0, kPositive), Decimal::FromDouble(0.0));
- EXPECT_EQ(Encode(0, 0, kNegative), Decimal::FromDouble(-0.0));
- EXPECT_EQ(Encode(1, 0, kPositive), Decimal::FromDouble(1));
- EXPECT_EQ(Encode(1, 0, kNegative), Decimal::FromDouble(-1));
- EXPECT_EQ(Encode(123, 0, kPositive), Decimal::FromDouble(123));
- EXPECT_EQ(Encode(123, 0, kNegative), Decimal::FromDouble(-123));
- EXPECT_EQ(Encode(1, -1, kPositive), Decimal::FromDouble(0.1));
- EXPECT_EQ(Encode(1, -1, kNegative), Decimal::FromDouble(-0.1));
-}
-
-TEST_F(DecimalTest, FromDoubleLimits) {
- EXPECT_EQ(Encode(UINT64_C(2220446049250313), -31, kPositive),
- Decimal::FromDouble(std::numeric_limits<double>::epsilon()));
- EXPECT_EQ(Encode(UINT64_C(2220446049250313), -31, kNegative),
- Decimal::FromDouble(-std::numeric_limits<double>::epsilon()));
- EXPECT_EQ(Encode(UINT64_C(17976931348623157), 292, kPositive),
- Decimal::FromDouble(std::numeric_limits<double>::max()));
- EXPECT_EQ(Encode(UINT64_C(17976931348623157), 292, kNegative),
- Decimal::FromDouble(-std::numeric_limits<double>::max()));
- EXPECT_EQ(Encode(UINT64_C(22250738585072014), -324, kPositive),
- Decimal::FromDouble(std::numeric_limits<double>::min()));
- EXPECT_EQ(Encode(UINT64_C(22250738585072014), -324, kNegative),
- Decimal::FromDouble(-std::numeric_limits<double>::min()));
- EXPECT_TRUE(Decimal::FromDouble(std::numeric_limits<double>::infinity())
- .IsInfinity());
- EXPECT_TRUE(Decimal::FromDouble(-std::numeric_limits<double>::infinity())
- .IsInfinity());
- EXPECT_TRUE(
- Decimal::FromDouble(std::numeric_limits<double>::quiet_NaN()).IsNaN());
- EXPECT_TRUE(
- Decimal::FromDouble(-std::numeric_limits<double>::quiet_NaN()).IsNaN());
-}
-
-TEST_F(DecimalTest, FromInt32) {
- EXPECT_EQ(Encode(0, 0, kPositive), Decimal(0));
- EXPECT_EQ(Encode(1, 0, kPositive), Decimal(1));
- EXPECT_EQ(Encode(1, 0, kNegative), Decimal(-1));
- EXPECT_EQ(Encode(100, 0, kPositive), Decimal(100));
- EXPECT_EQ(Encode(100, 0, kNegative), Decimal(-100));
- EXPECT_EQ(Encode(0x7FFFFFFF, 0, kPositive),
- Decimal(std::numeric_limits<int32_t>::max()));
- EXPECT_EQ(Encode(0x80000000u, 0, kNegative),
- Decimal(std::numeric_limits<int32_t>::min()));
-}
-
-TEST_F(DecimalTest, FromString) {
- EXPECT_EQ(Encode(0, 0, kPositive), FromString("0"));
- EXPECT_EQ(Encode(0, 0, kNegative), FromString("-0"));
- EXPECT_EQ(Decimal(1), FromString("1"));
- EXPECT_EQ(Encode(1, 0, kNegative), FromString("-1"));
- EXPECT_EQ(Decimal(1), FromString("01"));
- EXPECT_EQ(Encode(3, 0, kPositive), FromString("+3"));
- EXPECT_EQ(Encode(0, 3, kPositive), FromString("0E3"));
- EXPECT_EQ(Encode(5, -1, kPositive), FromString(".5"));
- EXPECT_EQ(Encode(100, 0, kPositive), FromString("100"));
- EXPECT_EQ(Encode(100, 0, kNegative), FromString("-100"));
- EXPECT_EQ(Encode(123, -2, kPositive), FromString("1.23"));
- EXPECT_EQ(Encode(123, -2, kNegative), FromString("-1.23"));
- EXPECT_EQ(Encode(123, 8, kPositive), FromString("1.23E10"));
- EXPECT_EQ(Encode(123, 8, kNegative), FromString("-1.23E10"));
- EXPECT_EQ(Encode(123, 8, kPositive), FromString("1.23E+10"));
- EXPECT_EQ(Encode(123, 8, kNegative), FromString("-1.23E+10"));
- EXPECT_EQ(Encode(123, -12, kPositive), FromString("1.23E-10"));
- EXPECT_EQ(Encode(123, -12, kNegative), FromString("-1.23E-10"));
- EXPECT_EQ(Encode(5, -7, kPositive), FromString("0.0000005"));
- EXPECT_EQ(Encode(0, 0, kPositive), FromString("0e9999"));
- EXPECT_EQ(Encode(123, -3, kPositive), FromString("0.123"));
- EXPECT_EQ(Encode(0, -2, kPositive), FromString("00.00"));
- EXPECT_EQ(Encode(1, 2, kPositive), FromString("1E2"));
- EXPECT_EQ(Decimal::Infinity(kPositive), FromString("1E20000"));
- EXPECT_EQ(Decimal::Zero(kPositive), FromString("1E-20000"));
- EXPECT_EQ(Encode(1000, 1023, kPositive), FromString("1E1026"));
- EXPECT_EQ(Decimal::Zero(kPositive), FromString("1E-1026"));
- EXPECT_EQ(Decimal::Infinity(kPositive), FromString("1234567890E1036"));
-
- // 2^1024
- const uint64_t kLeadingDigitsOf2PowerOf1024 = UINT64_C(17976931348623159);
- EXPECT_EQ(Encode(kLeadingDigitsOf2PowerOf1024, 292, kPositive),
- FromString("1797693134862315907729305190789024733617976978942306572"
- "7343008115773267580550096313270847732240753602112011387"
- "9871393357658789768814416622492847430639474124377767893"
- "4248654852763022196012460941194530829520850057688381506"
- "8234246288147391311054082723716335051068458629823994724"
- "5938479716304835356329624224137216"));
-}
-
-// These strings are look like proper number, but we don't accept them.
-TEST_F(DecimalTest, FromStringLikeNumber) {
- EXPECT_EQ(Decimal::Nan(), FromString(" 123 "));
- EXPECT_EQ(Decimal::Nan(), FromString("1,234"));
-}
-
-// fromString doesn't support infinity and NaN.
-TEST_F(DecimalTest, FromStringSpecialValues) {
- EXPECT_EQ(Decimal::Nan(), FromString("INF"));
- EXPECT_EQ(Decimal::Nan(), FromString("Infinity"));
- EXPECT_EQ(Decimal::Nan(), FromString("infinity"));
- EXPECT_EQ(Decimal::Nan(), FromString("+Infinity"));
- EXPECT_EQ(Decimal::Nan(), FromString("+infinity"));
- EXPECT_EQ(Decimal::Nan(), FromString("-Infinity"));
- EXPECT_EQ(Decimal::Nan(), FromString("-infinity"));
- EXPECT_EQ(Decimal::Nan(), FromString("NaN"));
- EXPECT_EQ(Decimal::Nan(), FromString("nan"));
- EXPECT_EQ(Decimal::Nan(), FromString("+NaN"));
- EXPECT_EQ(Decimal::Nan(), FromString("+nan"));
- EXPECT_EQ(Decimal::Nan(), FromString("-NaN"));
- EXPECT_EQ(Decimal::Nan(), FromString("-nan"));
-}
-
-TEST_F(DecimalTest, fromStringTruncated) {
- EXPECT_EQ(Decimal::Nan(), FromString("x"));
- EXPECT_EQ(Decimal::Nan(), FromString("0."));
- EXPECT_EQ(Decimal::Nan(), FromString("1x"));
-
- EXPECT_EQ(Decimal::Nan(), FromString("1Ex"));
- EXPECT_EQ(Decimal::Nan(), FromString("1E2x"));
- EXPECT_EQ(Decimal::Nan(), FromString("1E+x"));
-}
-
-TEST_F(DecimalTest, Multiplication) {
- EXPECT_EQ(Encode(0, 0, kPositive), Decimal(0) * Decimal(0));
- EXPECT_EQ(Encode(2, 0, kNegative), Decimal(2) * Decimal(-1));
- EXPECT_EQ(Encode(2, 0, kNegative), Decimal(-1) * Decimal(2));
- EXPECT_EQ(Encode(99, 0, kPositive), Decimal(99) * Decimal(1));
- EXPECT_EQ(Encode(2500, 0, kPositive), Decimal(-50) * Decimal(-50));
- EXPECT_EQ(Encode(1, 21, kPositive),
- Encode(UINT64_C(10000000000), 0, kPositive) *
- Encode(UINT64_C(100000000000), 0, kPositive));
-}
-
-TEST_F(DecimalTest, MultiplicationBigExponent) {
- EXPECT_EQ(Encode(1, 1022, kPositive),
- Encode(1, 1022, kPositive) * Encode(1, 0, kPositive));
- EXPECT_EQ(Decimal::Infinity(kPositive),
- Encode(1, 1022, kPositive) * Encode(1, 1022, kPositive));
- EXPECT_EQ(Encode(1, 22, kPositive),
- Encode(1, 1022, kPositive) * Encode(1, -1000, kPositive));
-}
-
-TEST_F(DecimalTest, MultiplicationSmallExponent) {
- EXPECT_EQ(Encode(1, -1022, kPositive),
- Encode(1, -1022, kPositive) * Encode(1, 0, kPositive));
- EXPECT_EQ(Encode(0, 0, kPositive),
- Encode(1, -1022, kPositive) * Encode(1, -1022, kPositive));
-}
-
-TEST_F(DecimalTest, MultiplicationSpecialValues) {
- const Decimal infinity(Decimal::Infinity(kPositive));
- const Decimal minus_infinity(Decimal::Infinity(kNegative));
- const Decimal na_n(Decimal::Nan());
- const Decimal ten(10);
- const Decimal minus_ten(-10);
- const Decimal zero(Decimal::Zero(kPositive));
- const Decimal minus_zero(Decimal::Zero(kNegative));
-
- EXPECT_EQ(infinity, infinity * infinity);
- EXPECT_EQ(minus_infinity, infinity * minus_infinity);
- EXPECT_EQ(minus_infinity, minus_infinity * infinity);
- EXPECT_EQ(infinity, minus_infinity * minus_infinity);
-
- EXPECT_EQ(na_n, infinity * zero);
- EXPECT_EQ(na_n, zero * minus_infinity);
- EXPECT_EQ(na_n, minus_infinity * zero);
- EXPECT_EQ(na_n, minus_infinity * zero);
-
- EXPECT_EQ(na_n, infinity * minus_zero);
- EXPECT_EQ(na_n, minus_zero * minus_infinity);
- EXPECT_EQ(na_n, minus_infinity * minus_zero);
- EXPECT_EQ(na_n, minus_infinity * minus_zero);
-
- EXPECT_EQ(infinity, infinity * ten);
- EXPECT_EQ(infinity, ten * infinity);
- EXPECT_EQ(minus_infinity, minus_infinity * ten);
- EXPECT_EQ(minus_infinity, ten * minus_infinity);
-
- EXPECT_EQ(minus_infinity, infinity * minus_ten);
- EXPECT_EQ(minus_infinity, minus_ten * infinity);
- EXPECT_EQ(infinity, minus_infinity * minus_ten);
- EXPECT_EQ(infinity, minus_ten * minus_infinity);
-
- EXPECT_EQ(na_n, na_n * na_n);
- EXPECT_EQ(na_n, na_n * ten);
- EXPECT_EQ(na_n, ten * na_n);
-
- EXPECT_EQ(na_n, na_n * infinity);
- EXPECT_EQ(na_n, na_n * minus_infinity);
- EXPECT_EQ(na_n, infinity * na_n);
- EXPECT_EQ(na_n, minus_infinity * na_n);
-}
-
-TEST_F(DecimalTest, Negate) {
- EXPECT_EQ(Encode(0, 0, kNegative), -Encode(0, 0, kPositive));
- EXPECT_EQ(Encode(0, 0, kPositive), -Encode(0, 0, kNegative));
-
- EXPECT_EQ(Encode(0, 10, kNegative), -Encode(0, 10, kPositive));
- EXPECT_EQ(Encode(0, 10, kPositive), -Encode(0, 10, kNegative));
-
- EXPECT_EQ(Encode(0, -10, kNegative), -Encode(0, -10, kPositive));
- EXPECT_EQ(Encode(0, -10, kPositive), -Encode(0, -10, kNegative));
-
- EXPECT_EQ(Encode(1, 0, kNegative), -Encode(1, 0, kPositive));
- EXPECT_EQ(Encode(1, 0, kPositive), -Encode(1, 0, kNegative));
-
- EXPECT_EQ(Encode(1, 10, kNegative), -Encode(1, 10, kPositive));
- EXPECT_EQ(Encode(1, 10, kPositive), -Encode(1, 10, kNegative));
-
- EXPECT_EQ(Encode(1, -10, kNegative), -Encode(1, -10, kPositive));
- EXPECT_EQ(Encode(1, -10, kPositive), -Encode(1, -10, kNegative));
-}
-
-TEST_F(DecimalTest, NegateBigExponent) {
- EXPECT_EQ(Encode(1, 1000, kNegative), -Encode(1, 1000, kPositive));
- EXPECT_EQ(Encode(1, 1000, kPositive), -Encode(1, 1000, kNegative));
-}
-
-TEST_F(DecimalTest, NegateSmallExponent) {
- EXPECT_EQ(Encode(1, -1000, kNegative), -Encode(1, -1000, kPositive));
- EXPECT_EQ(Encode(1, -1000, kPositive), -Encode(1, -1000, kNegative));
-}
-
-TEST_F(DecimalTest, NegateSpecialValues) {
- EXPECT_EQ(Decimal::Infinity(kNegative), -Decimal::Infinity(kPositive));
- EXPECT_EQ(Decimal::Infinity(kPositive), -Decimal::Infinity(kNegative));
- EXPECT_EQ(Decimal::Nan(), -Decimal::Nan());
-}
-
-TEST_F(DecimalTest, Predicates) {
- EXPECT_TRUE(Decimal::Zero(kPositive).IsFinite());
- EXPECT_FALSE(Decimal::Zero(kPositive).IsInfinity());
- EXPECT_FALSE(Decimal::Zero(kPositive).IsNaN());
- EXPECT_TRUE(Decimal::Zero(kPositive).IsPositive());
- EXPECT_FALSE(Decimal::Zero(kPositive).IsNegative());
- EXPECT_FALSE(Decimal::Zero(kPositive).IsSpecial());
- EXPECT_TRUE(Decimal::Zero(kPositive).IsZero());
-
- EXPECT_TRUE(Decimal::Zero(kNegative).IsFinite());
- EXPECT_FALSE(Decimal::Zero(kNegative).IsInfinity());
- EXPECT_FALSE(Decimal::Zero(kNegative).IsNaN());
- EXPECT_FALSE(Decimal::Zero(kNegative).IsPositive());
- EXPECT_TRUE(Decimal::Zero(kNegative).IsNegative());
- EXPECT_FALSE(Decimal::Zero(kNegative).IsSpecial());
- EXPECT_TRUE(Decimal::Zero(kNegative).IsZero());
-
- EXPECT_TRUE(Decimal(123).IsFinite());
- EXPECT_FALSE(Decimal(123).IsInfinity());
- EXPECT_FALSE(Decimal(123).IsNaN());
- EXPECT_TRUE(Decimal(123).IsPositive());
- EXPECT_FALSE(Decimal(123).IsNegative());
- EXPECT_FALSE(Decimal(123).IsSpecial());
- EXPECT_FALSE(Decimal(123).IsZero());
-
- EXPECT_TRUE(Decimal(-123).IsFinite());
- EXPECT_FALSE(Decimal(-123).IsInfinity());
- EXPECT_FALSE(Decimal(-123).IsNaN());
- EXPECT_FALSE(Decimal(-123).IsPositive());
- EXPECT_TRUE(Decimal(-123).IsNegative());
- EXPECT_FALSE(Decimal(-123).IsSpecial());
- EXPECT_FALSE(Decimal(-123).IsZero());
-}
-
-TEST_F(DecimalTest, PredicatesSpecialValues) {
- EXPECT_FALSE(Decimal::Infinity(kPositive).IsFinite());
- EXPECT_TRUE(Decimal::Infinity(kPositive).IsInfinity());
- EXPECT_FALSE(Decimal::Infinity(kPositive).IsNaN());
- EXPECT_TRUE(Decimal::Infinity(kPositive).IsPositive());
- EXPECT_FALSE(Decimal::Infinity(kPositive).IsNegative());
- EXPECT_TRUE(Decimal::Infinity(kPositive).IsSpecial());
- EXPECT_FALSE(Decimal::Infinity(kPositive).IsZero());
-
- EXPECT_FALSE(Decimal::Infinity(kNegative).IsFinite());
- EXPECT_TRUE(Decimal::Infinity(kNegative).IsInfinity());
- EXPECT_FALSE(Decimal::Infinity(kNegative).IsNaN());
- EXPECT_FALSE(Decimal::Infinity(kNegative).IsPositive());
- EXPECT_TRUE(Decimal::Infinity(kNegative).IsNegative());
- EXPECT_TRUE(Decimal::Infinity(kNegative).IsSpecial());
- EXPECT_FALSE(Decimal::Infinity(kNegative).IsZero());
-
- EXPECT_FALSE(Decimal::Nan().IsFinite());
- EXPECT_FALSE(Decimal::Nan().IsInfinity());
- EXPECT_TRUE(Decimal::Nan().IsNaN());
- EXPECT_TRUE(Decimal::Nan().IsSpecial());
- EXPECT_FALSE(Decimal::Nan().IsZero());
-}
-
-// LayoutTests/fast/forms/number/number-stepup-stepdown-from-renderer
-TEST_F(DecimalTest, RealWorldExampleNumberStepUpStepDownFromRenderer) {
- EXPECT_DECIMAL_STREQ("10", StepDown("0", "100", "10", "19", 1));
- EXPECT_DECIMAL_STREQ("90", StepUp("0", "99", "10", "89", 1));
- EXPECT_DECIMAL_STREQ(
- "1", StepUp("0", "1", "0.33333333333333333", "0", 3)); // step=1/3
- EXPECT_DECIMAL_STREQ("0.01", StepUp("0", "0.01", "0.0033333333333333333", "0",
- 3)); // step=1/300
- EXPECT_DECIMAL_STREQ(
- "1", StepUp("0", "1", "0.003921568627450980", "0", 255)); // step=1/255
- EXPECT_DECIMAL_STREQ("1", StepUp("0", "1", "0.1", "0", 10));
-}
-
-TEST_F(DecimalTest, RealWorldExampleNumberStepUpStepDownFromRendererRounding) {
- EXPECT_DECIMAL_STREQ("5.015", StepUp("0", "100", "0.005", "5.005", 2));
- EXPECT_DECIMAL_STREQ("5.06", StepUp("0", "100", "0.005", "5.005", 11));
- EXPECT_DECIMAL_STREQ("5.065", StepUp("0", "100", "0.005", "5.005", 12));
-
- EXPECT_DECIMAL_STREQ("5.015", StepUp("4", "9", "0.005", "5.005", 2));
- EXPECT_DECIMAL_STREQ("5.06", StepUp("4", "9", "0.005", "5.005", 11));
- EXPECT_DECIMAL_STREQ("5.065", StepUp("4", "9", "0.005", "5.005", 12));
-}
-
-TEST_F(DecimalTest, RealWorldExampleRangeStepUpStepDown) {
- EXPECT_DECIMAL_STREQ("1e+38", StepUp("0", "1E38", "1", "1E38", 9));
- EXPECT_DECIMAL_STREQ("1e+38", StepDown("0", "1E38", "1", "1E38", 9));
-}
-
-TEST_F(DecimalTest, Remainder) {
- EXPECT_EQ(Encode(21, -1, kPositive), Encode(21, -1, kPositive).Remainder(3));
- EXPECT_EQ(Decimal(1), Decimal(10).Remainder(3));
- EXPECT_EQ(Decimal(1), Decimal(10).Remainder(-3));
- EXPECT_EQ(Encode(1, 0, kNegative), Decimal(-10).Remainder(3));
- EXPECT_EQ(Decimal(-1), Decimal(-10).Remainder(-3));
- EXPECT_EQ(Encode(2, -1, kPositive), Encode(102, -1, kPositive).Remainder(1));
- EXPECT_EQ(Encode(1, -1, kPositive),
- Decimal(10).Remainder(Encode(3, -1, kPositive)));
- EXPECT_EQ(Decimal(1),
- Encode(36, -1, kPositive).Remainder(Encode(13, -1, kPositive)));
- EXPECT_EQ(Encode(1, 86, kPositive),
- (Encode(1234, 100, kPositive).Remainder(Decimal(3))));
- EXPECT_EQ(Decimal(500), (Decimal(500).Remainder(1000)));
- EXPECT_EQ(Decimal(-500), (Decimal(-500).Remainder(1000)));
-}
-
-TEST_F(DecimalTest, RemainderBigExponent) {
- EXPECT_EQ(Encode(0, 1022, kPositive),
- Encode(1, 1022, kPositive).Remainder(Encode(1, 0, kPositive)));
- EXPECT_EQ(Encode(0, 1022, kPositive),
- Encode(1, 1022, kPositive).Remainder(Encode(1, 1022, kPositive)));
- EXPECT_EQ(Decimal::Infinity(kPositive),
- Encode(1, 1022, kPositive).Remainder(Encode(1, -1000, kPositive)));
-}
-
-TEST_F(DecimalTest, RemainderSmallExponent) {
- EXPECT_EQ(Encode(1, -1022, kPositive),
- Encode(1, -1022, kPositive).Remainder(Encode(1, 0, kPositive)));
- EXPECT_EQ(Encode(0, -1022, kPositive),
- Encode(1, -1022, kPositive).Remainder(Encode(1, -1022, kPositive)));
-}
-
-TEST_F(DecimalTest, RemainderSpecialValues) {
- EXPECT_EQ(Decimal::Infinity(kPositive),
- Decimal::Infinity(kPositive).Remainder(1));
- EXPECT_EQ(Decimal::Infinity(kNegative),
- Decimal::Infinity(kNegative).Remainder(1));
- EXPECT_EQ(Decimal::Nan(), Decimal::Nan().Remainder(1));
-
- EXPECT_EQ(Decimal::Infinity(kNegative),
- Decimal::Infinity(kPositive).Remainder(-1));
- EXPECT_EQ(Decimal::Infinity(kPositive),
- Decimal::Infinity(kNegative).Remainder(-1));
- EXPECT_EQ(Decimal::Nan(), Decimal::Nan().Remainder(-1));
-
- EXPECT_EQ(Decimal::Infinity(kPositive),
- Decimal::Infinity(kPositive).Remainder(3));
- EXPECT_EQ(Decimal::Infinity(kNegative),
- Decimal::Infinity(kNegative).Remainder(3));
- EXPECT_EQ(Decimal::Nan(), Decimal::Nan().Remainder(3));
-
- EXPECT_EQ(Decimal::Infinity(kNegative),
- Decimal::Infinity(kPositive).Remainder(-1));
- EXPECT_EQ(Decimal::Infinity(kPositive),
- Decimal::Infinity(kNegative).Remainder(-1));
- EXPECT_EQ(Decimal::Nan(), Decimal::Nan().Remainder(-1));
-
- EXPECT_EQ(Decimal::Nan(), Decimal(1).Remainder(Decimal::Infinity(kPositive)));
- EXPECT_EQ(Decimal::Nan(), Decimal(1).Remainder(Decimal::Infinity(kNegative)));
- EXPECT_EQ(Decimal::Nan(), Decimal(1).Remainder(Decimal::Nan()));
-}
-
-TEST_F(DecimalTest, Round) {
- EXPECT_EQ(Decimal(1), (Decimal(9) / Decimal(10)).Round());
- EXPECT_EQ(Decimal(25), (Decimal(5) / FromString("0.200")).Round());
- EXPECT_EQ(Decimal(3), (Decimal(5) / Decimal(2)).Round());
- EXPECT_EQ(Decimal(1), (Decimal(2) / Decimal(3)).Round());
- EXPECT_EQ(Decimal(3), (Decimal(10) / Decimal(3)).Round());
- EXPECT_EQ(Decimal(3), (Decimal(1) / FromString("0.3")).Round());
- EXPECT_EQ(Decimal(10), (Decimal(1) / FromString("0.1")).Round());
- EXPECT_EQ(Decimal(5), (Decimal(1) / FromString("0.2")).Round());
- EXPECT_EQ(Decimal(10), (FromString("10.2") / 1).Round());
- EXPECT_EQ(Encode(1234, 100, kPositive), Encode(1234, 100, kPositive).Round());
-
- EXPECT_EQ(Decimal(2), Encode(190002, -5, kPositive).Round());
- EXPECT_EQ(Decimal(2), Encode(150002, -5, kPositive).Round());
- EXPECT_EQ(Decimal(2), Encode(150000, -5, kPositive).Round());
- EXPECT_EQ(Decimal(12), Encode(12492, -3, kPositive).Round());
- EXPECT_EQ(Decimal(13), Encode(12502, -3, kPositive).Round());
-
- EXPECT_EQ(Decimal(-2), Encode(190002, -5, kNegative).Round());
- EXPECT_EQ(Decimal(-2), Encode(150002, -5, kNegative).Round());
- EXPECT_EQ(Decimal(-2), Encode(150000, -5, kNegative).Round());
- EXPECT_EQ(Decimal(-12), Encode(12492, -3, kNegative).Round());
- EXPECT_EQ(Decimal(-13), Encode(12502, -3, kNegative).Round());
-}
-
-TEST_F(DecimalTest, RoundSpecialValues) {
- EXPECT_EQ(Decimal::Infinity(kPositive), Decimal::Infinity(kPositive).Round());
- EXPECT_EQ(Decimal::Infinity(kNegative), Decimal::Infinity(kNegative).Round());
- EXPECT_EQ(Decimal::Nan(), Decimal::Nan().Round());
-}
-
-TEST_F(DecimalTest, Subtract) {
- EXPECT_EQ(Encode(0, 0, kPositive), Decimal(0) - Decimal(0));
- EXPECT_EQ(Encode(3, 0, kPositive), Decimal(2) - Decimal(-1));
- EXPECT_EQ(Encode(3, 0, kNegative), Decimal(-1) - Decimal(2));
- EXPECT_EQ(Encode(98, 0, kPositive), Decimal(99) - Decimal(1));
- EXPECT_EQ(Encode(0, 0, kPositive), Decimal(-50) - Decimal(-50));
- EXPECT_EQ(Encode(UINT64_C(1000000000000000), 35, kPositive),
- Encode(1, 50, kPositive) - Decimal(1));
- EXPECT_EQ(Encode(UINT64_C(1000000000000000), 35, kNegative),
- Decimal(1) - Encode(1, 50, kPositive));
-}
-
-TEST_F(DecimalTest, SubtractBigExponent) {
- EXPECT_EQ(Encode(1, 1022, kPositive),
- Encode(1, 1022, kPositive) - Encode(1, 0, kPositive));
- EXPECT_EQ(Encode(0, 0, kPositive),
- Encode(1, 1022, kPositive) - Encode(1, 1022, kPositive));
- EXPECT_EQ(Encode(1, 1022, kPositive),
- Encode(1, 1022, kPositive) + Encode(1, -1000, kPositive));
-}
-
-TEST_F(DecimalTest, SubtractSmallExponent) {
- EXPECT_EQ(Encode(UINT64_C(10000000000000000), -16, kNegative),
- Encode(1, -1022, kPositive) - Encode(1, 0, kPositive));
- EXPECT_EQ(Encode(0, 0, kPositive),
- Encode(1, -1022, kPositive) - Encode(1, -1022, kPositive));
-}
-
-TEST_F(DecimalTest, SubtractSpecialValues) {
- const Decimal infinity(Decimal::Infinity(kPositive));
- const Decimal minus_infinity(Decimal::Infinity(kNegative));
- const Decimal na_n(Decimal::Nan());
- const Decimal ten(10);
-
- EXPECT_EQ(na_n, infinity - infinity);
- EXPECT_EQ(infinity, infinity - minus_infinity);
- EXPECT_EQ(minus_infinity, minus_infinity - infinity);
- EXPECT_EQ(na_n, minus_infinity - minus_infinity);
-
- EXPECT_EQ(infinity, infinity - ten);
- EXPECT_EQ(minus_infinity, ten - infinity);
- EXPECT_EQ(minus_infinity, minus_infinity - ten);
- EXPECT_EQ(infinity, ten - minus_infinity);
-
- EXPECT_EQ(na_n, na_n - na_n);
- EXPECT_EQ(na_n, na_n - ten);
- EXPECT_EQ(na_n, ten - na_n);
-
- EXPECT_EQ(na_n, na_n - infinity);
- EXPECT_EQ(na_n, na_n - minus_infinity);
- EXPECT_EQ(na_n, infinity - na_n);
- EXPECT_EQ(na_n, minus_infinity - na_n);
-}
-
-TEST_F(DecimalTest, ToDouble) {
- EXPECT_EQ(0.0, Encode(0, 0, kPositive).ToDouble());
- EXPECT_EQ(-0.0, Encode(0, 0, kNegative).ToDouble());
-
- EXPECT_EQ(1.0, Encode(1, 0, kPositive).ToDouble());
- EXPECT_EQ(-1.0, Encode(1, 0, kNegative).ToDouble());
-
- EXPECT_EQ(0.1, Encode(1, -1, kPositive).ToDouble());
- EXPECT_EQ(-0.1, Encode(1, -1, kNegative).ToDouble());
- EXPECT_EQ(0.3, Encode(3, -1, kPositive).ToDouble());
- EXPECT_EQ(-0.3, Encode(3, -1, kNegative).ToDouble());
- EXPECT_EQ(0.6, Encode(6, -1, kPositive).ToDouble());
- EXPECT_EQ(-0.6, Encode(6, -1, kNegative).ToDouble());
- EXPECT_EQ(0.7, Encode(7, -1, kPositive).ToDouble());
- EXPECT_EQ(-0.7, Encode(7, -1, kNegative).ToDouble());
-
- EXPECT_EQ(0.01, Encode(1, -2, kPositive).ToDouble());
- EXPECT_EQ(0.001, Encode(1, -3, kPositive).ToDouble());
- EXPECT_EQ(0.0001, Encode(1, -4, kPositive).ToDouble());
- EXPECT_EQ(0.00001, Encode(1, -5, kPositive).ToDouble());
-
- EXPECT_EQ(1e+308, Encode(1, 308, kPositive).ToDouble());
- EXPECT_EQ(1e-307, Encode(1, -307, kPositive).ToDouble());
-
- EXPECT_TRUE(std::isinf(Encode(1, 1000, kPositive).ToDouble()));
- EXPECT_EQ(0.0, Encode(1, -1000, kPositive).ToDouble());
-}
-
-TEST_F(DecimalTest, ToDoubleSpecialValues) {
- EXPECT_TRUE(std::isinf(Decimal::Infinity(Decimal::kPositive).ToDouble()));
- EXPECT_TRUE(std::isinf(Decimal::Infinity(Decimal::kNegative).ToDouble()));
- EXPECT_TRUE(std::isnan(Decimal::Nan().ToDouble()));
-}
-
-TEST_F(DecimalTest, ToString) {
- EXPECT_DECIMAL_STREQ("0", Decimal::Zero(kPositive));
- EXPECT_DECIMAL_STREQ("-0", Decimal::Zero(kNegative));
- EXPECT_DECIMAL_STREQ("1", Decimal(1));
- EXPECT_DECIMAL_STREQ("-1", Decimal(-1));
- EXPECT_DECIMAL_STREQ("1234567", Decimal(1234567));
- EXPECT_DECIMAL_STREQ("-1234567", Decimal(-1234567));
- EXPECT_DECIMAL_STREQ("0.5", Encode(5, -1, kPositive));
- EXPECT_DECIMAL_STREQ("-0.5", Encode(5, -1, kNegative));
- EXPECT_DECIMAL_STREQ("12.345", Encode(12345, -3, kPositive));
- EXPECT_DECIMAL_STREQ("-12.345", Encode(12345, -3, kNegative));
- EXPECT_DECIMAL_STREQ("0.12345", Encode(12345, -5, kPositive));
- EXPECT_DECIMAL_STREQ("-0.12345", Encode(12345, -5, kNegative));
- EXPECT_DECIMAL_STREQ("50", Encode(50, 0, kPositive));
- EXPECT_DECIMAL_STREQ("-50", Encode(50, 0, kNegative));
- EXPECT_DECIMAL_STREQ("5e+1", Encode(5, 1, kPositive));
- EXPECT_DECIMAL_STREQ("-5e+1", Encode(5, 1, kNegative));
- EXPECT_DECIMAL_STREQ("5.678e+103", Encode(5678, 100, kPositive));
- EXPECT_DECIMAL_STREQ("-5.678e+103", Encode(5678, 100, kNegative));
- EXPECT_DECIMAL_STREQ("5.678e-97", Encode(5678, -100, kPositive));
- EXPECT_DECIMAL_STREQ("-5.678e-97", Encode(5678, -100, kNegative));
- EXPECT_DECIMAL_STREQ("8639999913600001",
- Encode(UINT64_C(8639999913600001), 0, kPositive));
- EXPECT_DECIMAL_STREQ(
- "9007199254740991",
- Encode((static_cast<uint64_t>(1) << DBL_MANT_DIG) - 1, 0, kPositive));
- EXPECT_DECIMAL_STREQ("99999999999999999",
- Encode(UINT64_C(99999999999999999), 0, kPositive));
- EXPECT_DECIMAL_STREQ("9.9999999999999999e+17",
- Encode(UINT64_C(99999999999999999), 1, kPositive));
- EXPECT_DECIMAL_STREQ("9.9999999999999999e+18",
- Encode(UINT64_C(99999999999999999), 2, kPositive));
- EXPECT_DECIMAL_STREQ("1e+16",
- Encode(UINT64_C(99999999999999999), -1, kPositive));
- EXPECT_DECIMAL_STREQ("1000000000000000",
- Encode(UINT64_C(99999999999999999), -2, kPositive));
- EXPECT_DECIMAL_STREQ("1",
- Encode(UINT64_C(99999999999999999), -17, kPositive));
- EXPECT_DECIMAL_STREQ("0.001",
- Encode(UINT64_C(99999999999999999), -20, kPositive));
- EXPECT_DECIMAL_STREQ("1e-83",
- Encode(UINT64_C(99999999999999999), -100, kPositive));
-}
-
-TEST_F(DecimalTest, ToStringSpecialValues) {
- EXPECT_DECIMAL_STREQ("Infinity", Decimal::Infinity(kPositive));
- EXPECT_DECIMAL_STREQ("-Infinity", Decimal::Infinity(kNegative));
- EXPECT_DECIMAL_STREQ("NaN", Decimal::Nan());
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/drag_image.cc b/chromium/third_party/blink/renderer/platform/drag_image.cc
index 7354e4f82ec..8a15a24519e 100644
--- a/chromium/third_party/blink/renderer/platform/drag_image.cc
+++ b/chromium/third_party/blink/renderer/platform/drag_image.cc
@@ -260,7 +260,11 @@ std::unique_ptr<DragImage> DragImage::Create(const KURL& url,
scaled_image_size.Scale(device_scale_factor);
std::unique_ptr<CanvasResourceProvider> resource_provider(
CanvasResourceProvider::Create(
- scaled_image_size, CanvasResourceProvider::kSoftwareResourceUsage));
+ scaled_image_size, CanvasResourceProvider::kSoftwareResourceUsage,
+ nullptr, // context_provider_wrapper
+ 0, // msaa_sample_count
+ CanvasColorParams(), CanvasResourceProvider::kDefaultPresentationMode,
+ nullptr)); // canvas_resource_dispatcher
if (!resource_provider)
return nullptr;
@@ -284,7 +288,7 @@ std::unique_ptr<DragImage> DragImage::Create(const KURL& url,
url_string = StringTruncator::CenterTruncate(
url_string, image_size.Width() - (kDragLabelBorderX * 2.0f),
url_font);
- IntPoint text_pos(
+ FloatPoint text_pos(
kDragLabelBorderX,
image_size.Height() -
(kLabelBorderYOffset + url_font_data->GetFontMetrics().Descent()));
diff --git a/chromium/third_party/blink/renderer/platform/drag_image_test.cc b/chromium/third_party/blink/renderer/platform/drag_image_test.cc
index 9bbf3a09151..173177f259e 100644
--- a/chromium/third_party/blink/renderer/platform/drag_image_test.cc
+++ b/chromium/third_party/blink/renderer/platform/drag_image_test.cc
@@ -69,8 +69,8 @@ class TestImage : public Image {
// Image pure virtual stub.
}
- void Draw(PaintCanvas*,
- const PaintFlags&,
+ void Draw(cc::PaintCanvas*,
+ const cc::PaintFlags&,
const FloatRect&,
const FloatRect&,
RespectImageOrientationEnum,
diff --git a/chromium/third_party/blink/renderer/platform/event_dispatch_forbidden_scope.cc b/chromium/third_party/blink/renderer/platform/event_dispatch_forbidden_scope.cc
deleted file mode 100644
index 9dfab394c7a..00000000000
--- a/chromium/third_party/blink/renderer/platform/event_dispatch_forbidden_scope.cc
+++ /dev/null
@@ -1,13 +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/platform/event_dispatch_forbidden_scope.h"
-
-namespace blink {
-
-#if DCHECK_IS_ON()
-unsigned EventDispatchForbiddenScope::count_ = 0;
-#endif // DECHECK_IS_ON()
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h b/chromium/third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h
deleted file mode 100644
index 385807ee887..00000000000
--- a/chromium/third_party/blink/renderer/platform/event_dispatch_forbidden_scope.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_EVENT_DISPATCH_FORBIDDEN_SCOPE_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_EVENT_DISPATCH_FORBIDDEN_SCOPE_H_
-
-#include "base/auto_reset.h"
-#include "base/macros.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-
-namespace blink {
-
-#if DCHECK_IS_ON()
-
-class EventDispatchForbiddenScope {
- STACK_ALLOCATED();
- DISALLOW_COPY_AND_ASSIGN(EventDispatchForbiddenScope);
-
- public:
- EventDispatchForbiddenScope() {
- DCHECK(IsMainThread());
- ++count_;
- }
-
- ~EventDispatchForbiddenScope() {
- DCHECK(IsMainThread());
- DCHECK(count_);
- --count_;
- }
-
- static bool IsEventDispatchForbidden() {
- if (!IsMainThread())
- return false;
- return count_;
- }
-
- class AllowUserAgentEvents {
- STACK_ALLOCATED();
-
- public:
- AllowUserAgentEvents() : change_(&count_, 0) { DCHECK(IsMainThread()); }
-
- ~AllowUserAgentEvents() { DCHECK(!count_); }
-
- base::AutoReset<unsigned> change_;
- };
-
- private:
- PLATFORM_EXPORT static unsigned count_;
-};
-
-#else
-
-class EventDispatchForbiddenScope {
- STACK_ALLOCATED();
- DISALLOW_COPY_AND_ASSIGN(EventDispatchForbiddenScope);
-
- public:
- EventDispatchForbiddenScope() {}
-
- class AllowUserAgentEvents {
- public:
- AllowUserAgentEvents() {}
- };
-};
-
-#endif // DCHECK_IS_ON()
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_EVENT_DISPATCH_FORBIDDEN_SCOPE_H_
diff --git a/chromium/third_party/blink/renderer/platform/exported/DEPS b/chromium/third_party/blink/renderer/platform/exported/DEPS
new file mode 100644
index 00000000000..7e486bb11c3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/exported/DEPS
@@ -0,0 +1,7 @@
+
+include_rules = [
+ "+net/cookies/canonical_cookie.h",
+ "+net/cookies/cookie_constants.h",
+ "+net/cookies/canonical_cookie.h",
+ "+net/cookies/cookie_constants.h",
+]
diff --git a/chromium/third_party/blink/renderer/platform/exported/OWNERS b/chromium/third_party/blink/renderer/platform/exported/OWNERS
new file mode 100644
index 00000000000..fa5061455f4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/exported/OWNERS
@@ -0,0 +1 @@
+per-file web_rtc_*=hbos@chromium.org
diff --git a/chromium/third_party/blink/renderer/platform/exported/platform.cc b/chromium/third_party/blink/renderer/platform/exported/platform.cc
index d7019cbeeff..848cda38f0b 100644
--- a/chromium/third_party/blink/renderer/platform/exported/platform.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/platform.cc
@@ -40,7 +40,6 @@
#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/modules/webmidi/web_midi_accessor.h"
#include "third_party/blink/public/platform/web_canvas_capture_handler.h"
-#include "third_party/blink/public/platform/web_gesture_curve.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
#include "third_party/blink/public/platform/web_image_capture_frame_grabber.h"
#include "third_party/blink/public/platform/web_media_recorder_handler.h"
@@ -65,6 +64,7 @@
#include "third_party/blink/renderer/platform/partition_alloc_memory_dump_provider.h"
#include "third_party/blink/renderer/platform/web_task_runner.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/webrtc/api/rtpparameters.h"
namespace blink {
@@ -126,7 +126,6 @@ void Platform::Initialize(Platform* platform) {
MemoryCoordinator::Initialize();
if (base::ThreadTaskRunnerHandle::IsSet()) {
base::trace_event::MemoryDumpProvider::Options options;
- options.supports_heap_profiling = true;
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
BlinkGCMemoryDumpProvider::Instance(), "BlinkGC",
base::ThreadTaskRunnerHandle::Get(), options);
@@ -144,11 +143,9 @@ void Platform::Initialize(Platform* platform) {
if (g_platform->main_thread_) {
DCHECK(!g_gc_task_runner);
g_gc_task_runner = new GCTaskRunner(g_platform->main_thread_);
- base::trace_event::MemoryDumpProvider::Options heap_profiling_options;
- heap_profiling_options.supports_heap_profiling = true;
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
PartitionAllocMemoryDumpProvider::Instance(), "PartitionAlloc",
- base::ThreadTaskRunnerHandle::Get(), heap_profiling_options);
+ base::ThreadTaskRunnerHandle::Get());
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
FontCacheMemoryDumpProvider::Instance(), "FontCaches",
base::ThreadTaskRunnerHandle::Get());
@@ -216,20 +213,13 @@ Platform::CreateOffscreenGraphicsContext3DProvider(
const WebURL& top_document_url,
Platform::GraphicsInfo*) {
return nullptr;
-};
+}
std::unique_ptr<WebGraphicsContext3DProvider>
Platform::CreateSharedOffscreenGraphicsContext3DProvider() {
return nullptr;
}
-std::unique_ptr<WebGestureCurve> Platform::CreateFlingAnimationCurve(
- WebGestureDevice device_source,
- const WebFloatPoint& velocity,
- const WebSize& cumulative_scroll) {
- return nullptr;
-}
-
std::unique_ptr<WebRTCPeerConnectionHandler>
Platform::CreateRTCPeerConnectionHandler(
WebRTCPeerConnectionHandlerClient*,
@@ -247,8 +237,7 @@ Platform::CreateRTCCertificateGenerator() {
return nullptr;
}
-std::unique_ptr<WebMediaStreamCenter> Platform::CreateMediaStreamCenter(
- WebMediaStreamCenterClient*) {
+std::unique_ptr<WebMediaStreamCenter> Platform::CreateMediaStreamCenter() {
return nullptr;
}
@@ -269,4 +258,14 @@ Platform::CreateImageCaptureFrameGrabber() {
return nullptr;
}
+std::unique_ptr<webrtc::RtpCapabilities> Platform::GetRtpSenderCapabilities(
+ const WebString& kind) {
+ return nullptr;
+}
+
+std::unique_ptr<webrtc::RtpCapabilities> Platform::GetRtpReceiverCapabilities(
+ const WebString& kind) {
+ return nullptr;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_active_gesture_animation.cc b/chromium/third_party/blink/renderer/platform/exported/web_active_gesture_animation.cc
deleted file mode 100644
index b12a86bde76..00000000000
--- a/chromium/third_party/blink/renderer/platform/exported/web_active_gesture_animation.cc
+++ /dev/null
@@ -1,63 +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:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/platform/exported/web_active_gesture_animation.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/memory/ptr_util.h"
-#include "third_party/blink/public/platform/web_gesture_curve.h"
-#include "third_party/blink/public/platform/web_gesture_curve_target.h"
-
-namespace blink {
-
-std::unique_ptr<WebActiveGestureAnimation>
-WebActiveGestureAnimation::CreateWithTimeOffset(
- std::unique_ptr<WebGestureCurve> curve,
- WebGestureCurveTarget* target,
- base::TimeTicks start_time) {
- return base::WrapUnique(
- new WebActiveGestureAnimation(std::move(curve), target, start_time));
-}
-
-WebActiveGestureAnimation::~WebActiveGestureAnimation() = default;
-
-WebActiveGestureAnimation::WebActiveGestureAnimation(
- std::unique_ptr<WebGestureCurve> curve,
- WebGestureCurveTarget* target,
- base::TimeTicks start_time)
- : start_time_(start_time), curve_(std::move(curve)), target_(target) {}
-
-bool WebActiveGestureAnimation::Animate(base::TimeTicks time) {
- // All WebGestureCurves assume zero-based time, so we subtract
- // the animation start time before passing to the curve.
- // TODO(dcheng): WebGestureCurve should be using base::TimeDelta to represent
- // this.
- return curve_->AdvanceAndApplyToTarget((time - start_time_).InSecondsF(),
- target_);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_active_gesture_animation.h b/chromium/third_party/blink/renderer/platform/exported/web_active_gesture_animation.h
deleted file mode 100644
index 1b5f6b121c9..00000000000
--- a/chromium/third_party/blink/renderer/platform/exported/web_active_gesture_animation.h
+++ /dev/null
@@ -1,71 +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:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_EXPORTED_WEB_ACTIVE_GESTURE_ANIMATION_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_EXPORTED_WEB_ACTIVE_GESTURE_ANIMATION_H_
-
-#include <memory>
-#include "base/time/time.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
-
-namespace blink {
-
-class WebGestureCurve;
-class WebGestureCurveTarget;
-
-// Implements a gesture animation (fling scroll, etc.) using a curve with a
-// generic interface to define the animation parameters as a function of time,
-// and applies the animation to a target, again via a generic interface. It is
-// assumed that animate() is called on a more-or-less regular basis by the
-// owner.
-class PLATFORM_EXPORT WebActiveGestureAnimation {
- USING_FAST_MALLOC(WebActiveGestureAnimation);
- WTF_MAKE_NONCOPYABLE(WebActiveGestureAnimation);
-
- public:
- static std::unique_ptr<WebActiveGestureAnimation> CreateWithTimeOffset(
- std::unique_ptr<WebGestureCurve>,
- WebGestureCurveTarget*,
- base::TimeTicks start_time);
- ~WebActiveGestureAnimation();
-
- bool Animate(base::TimeTicks);
-
- private:
- // Assumes a valid WebGestureCurveTarget that outlives the animation.
- WebActiveGestureAnimation(std::unique_ptr<WebGestureCurve>,
- WebGestureCurveTarget*,
- base::TimeTicks start_time);
-
- base::TimeTicks start_time_;
- std::unique_ptr<WebGestureCurve> curve_;
- WebGestureCurveTarget* target_;
-};
-
-} // namespace blink
-
-#endif
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_canonical_cookie.cc b/chromium/third_party/blink/renderer/platform/exported/web_canonical_cookie.cc
new file mode 100644
index 00000000000..bfd464b8c6e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/exported/web_canonical_cookie.cc
@@ -0,0 +1,161 @@
+// 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/public/platform/web_canonical_cookie.h"
+
+#include <memory>
+#include <vector>
+
+#include "net/cookies/canonical_cookie.h"
+#include "net/cookies/cookie_constants.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+#include "url/gurl.h"
+
+// Assumptions made by static_casts used in this file.
+STATIC_ASSERT_ENUM(net::CookieSameSite::NO_RESTRICTION,
+ network::mojom::CookieSameSite::NO_RESTRICTION);
+STATIC_ASSERT_ENUM(net::CookieSameSite::LAX_MODE,
+ network::mojom::CookieSameSite::LAX_MODE);
+STATIC_ASSERT_ENUM(net::CookieSameSite::STRICT_MODE,
+ network::mojom::CookieSameSite::STRICT_MODE);
+STATIC_ASSERT_ENUM(net::CookieSameSite::DEFAULT_MODE,
+ blink::WebCanonicalCookie::kDefaultSameSiteMode);
+
+STATIC_ASSERT_ENUM(net::CookiePriority::COOKIE_PRIORITY_LOW,
+ network::mojom::CookiePriority::LOW);
+STATIC_ASSERT_ENUM(net::CookiePriority::COOKIE_PRIORITY_MEDIUM,
+ network::mojom::CookiePriority::MEDIUM);
+STATIC_ASSERT_ENUM(net::CookiePriority::COOKIE_PRIORITY_HIGH,
+ network::mojom::CookiePriority::HIGH);
+STATIC_ASSERT_ENUM(net::CookiePriority::COOKIE_PRIORITY_DEFAULT,
+ blink::WebCanonicalCookie::kDefaultPriority);
+
+namespace blink {
+
+namespace {
+
+net::CanonicalCookie ToNetCanonicalCookie(const WebCanonicalCookie& cookie) {
+ net::CanonicalCookie net_cookie(
+ cookie.Name().Utf8(), cookie.Value().Utf8(), cookie.Domain().Utf8(),
+ cookie.Path().Utf8(), cookie.CreationDate(), cookie.ExpiryDate(),
+ cookie.LastAccessDate(), cookie.IsSecure(), cookie.IsHttpOnly(),
+ static_cast<net::CookieSameSite>(cookie.SameSite()),
+ static_cast<net::CookiePriority>(cookie.Priority()));
+ DCHECK(net_cookie.IsCanonical());
+ return net_cookie;
+}
+
+} // namespace
+
+WebCanonicalCookie::WebCanonicalCookie() = default;
+
+WebCanonicalCookie::WebCanonicalCookie(WebString name,
+ WebString value,
+ WebString domain,
+ WebString path,
+ base::Time creation,
+ base::Time expiration,
+ base::Time last_access,
+ bool is_secure,
+ bool is_http_only,
+ network::mojom::CookieSameSite same_site,
+ network::mojom::CookiePriority priority)
+ : name_(std::move(name)),
+ value_(std::move(value)),
+ domain_(std::move(domain)),
+ path_(std::move(path)),
+ creation_(creation),
+ expiration_(expiration),
+ last_access_(last_access),
+ is_secure_(is_secure),
+ is_http_only_(is_http_only),
+ same_site_(same_site),
+ priority_(priority) {
+ DCHECK(ToNetCanonicalCookie(*this).IsCanonical());
+}
+
+WebCanonicalCookie::WebCanonicalCookie(const WebCanonicalCookie& other) =
+ default;
+
+WebCanonicalCookie& WebCanonicalCookie::operator=(
+ const WebCanonicalCookie& other) = default;
+
+WebCanonicalCookie::~WebCanonicalCookie() = default;
+
+// static
+String WebCanonicalCookie::BuildCookieLine(
+ const Vector<WebCanonicalCookie>& cookies) {
+ std::vector<net::CanonicalCookie> copy;
+ copy.reserve(cookies.size());
+ for (const auto& cookie : cookies)
+ copy.push_back(ToNetCanonicalCookie(cookie));
+ return WebString::FromUTF8(net::CanonicalCookie::BuildCookieLine(copy));
+}
+
+namespace {
+
+// TODO(crbug.com/851889): WebURL::operator GURL() is only available if
+// !INSIDE_BLINK. Remove ToGURL() when this changes.
+GURL ToGURL(const WebURL& url) {
+ return url.IsNull()
+ ? GURL()
+ : GURL(url.GetString().Utf8(), url.GetParsed(), url.IsValid());
+}
+
+} // namespace
+
+// static
+base::Optional<WebCanonicalCookie> WebCanonicalCookie::Create(
+ const WebURL& url,
+ const WebString& cookie_line,
+ base::Time creation_time) {
+ net::CookieOptions options;
+ std::unique_ptr<net::CanonicalCookie> cookie = net::CanonicalCookie::Create(
+ ToGURL(url), cookie_line.Utf8(), creation_time, options);
+ if (!cookie)
+ return base::nullopt;
+ return WebCanonicalCookie(
+ WebString::FromUTF8(cookie->Name()), WebString::FromUTF8(cookie->Value()),
+ WebString::FromUTF8(cookie->Domain()),
+ WebString::FromUTF8(cookie->Path()), cookie->CreationDate(),
+ cookie->ExpiryDate(), cookie->LastAccessDate(), cookie->IsSecure(),
+ cookie->IsHttpOnly(),
+ static_cast<network::mojom::CookieSameSite>(cookie->SameSite()),
+ static_cast<network::mojom::CookiePriority>(cookie->Priority()));
+}
+
+// static
+base::Optional<WebCanonicalCookie> WebCanonicalCookie::Create(
+ WebString name,
+ WebString value,
+ WebString domain,
+ WebString path,
+ base::Time creation,
+ base::Time expiration,
+ base::Time last_access,
+ bool is_secure,
+ bool is_http_only,
+ network::mojom::CookieSameSite same_site,
+ network::mojom::CookiePriority priority) {
+ net::CanonicalCookie net_cookie(name.Utf8(), value.Utf8(), domain.Utf8(),
+ path.Utf8(), creation, expiration,
+ last_access, is_secure, is_http_only,
+ static_cast<net::CookieSameSite>(same_site),
+ static_cast<net::CookiePriority>(priority));
+ if (!net_cookie.IsCanonical())
+ return base::nullopt;
+
+ return WebCanonicalCookie(std::move(name), std::move(value),
+ std::move(domain), std::move(path), creation,
+ expiration, last_access, is_secure, is_http_only,
+ same_site, priority);
+}
+
+constexpr const network::mojom::CookieSameSite
+ WebCanonicalCookie::kDefaultSameSiteMode;
+constexpr const network::mojom::CookiePriority
+ WebCanonicalCookie::kDefaultPriority;
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_canonical_cookie_test.cc b/chromium/third_party/blink/renderer/platform/exported/web_canonical_cookie_test.cc
new file mode 100644
index 00000000000..71d59fd8998
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/exported/web_canonical_cookie_test.cc
@@ -0,0 +1,114 @@
+// 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/public/platform/web_canonical_cookie.h"
+
+#include <initializer_list>
+
+#include "base/optional.h"
+#include "base/time/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+TEST(WebCanonicalCookieTest, Defaults) {
+ WebCanonicalCookie cookie;
+ EXPECT_EQ(WebString(), cookie.Name());
+ EXPECT_EQ(WebString(), cookie.Value());
+ EXPECT_EQ(WebString(), cookie.Domain());
+ EXPECT_EQ(WebString(), cookie.Path());
+ EXPECT_EQ(base::Time(), cookie.CreationDate());
+ EXPECT_EQ(base::Time(), cookie.ExpiryDate());
+ EXPECT_EQ(base::Time(), cookie.LastAccessDate());
+ EXPECT_FALSE(cookie.IsSecure());
+ EXPECT_FALSE(cookie.IsHttpOnly());
+ EXPECT_EQ(WebCanonicalCookie::kDefaultSameSiteMode, cookie.SameSite());
+ EXPECT_EQ(WebCanonicalCookie::kDefaultPriority, cookie.Priority());
+}
+
+TEST(WebCanonicalCookieTest, CreationFailure) {
+ const WebURL url(KURL("http://example.com"));
+
+ // Invalid cookie lines cause nullopt to be returned.
+ EXPECT_FALSE(
+ WebCanonicalCookie::Create(url, "\x01", base::Time::Now()).has_value());
+
+ // Invalid names cause nullopt to be returned.
+ EXPECT_FALSE(WebCanonicalCookie::Create(
+ "\x01", "value", "domain", "/path", base::Time::Now(),
+ base::Time::Now(), base::Time::Now(), false, false,
+ WebCanonicalCookie::kDefaultSameSiteMode,
+ WebCanonicalCookie::kDefaultPriority)
+ .has_value());
+}
+
+TEST(WebCanonicalCookieTest, Properties) {
+ const base::Time t1 = base::Time::FromDoubleT(1);
+ const base::Time t2 = base::Time::FromDoubleT(2);
+ const base::Time t3 = base::Time::FromDoubleT(3);
+ ASSERT_NE(t1, t2);
+ ASSERT_NE(t1, t3);
+ ASSERT_NE(t2, t3);
+
+ base::Optional<WebCanonicalCookie> cookie_opt = WebCanonicalCookie::Create(
+ "name", "value", "domain", "/path", t1, t2, t3, true, true,
+ network::mojom::CookieSameSite::STRICT_MODE,
+ network::mojom::CookiePriority::HIGH);
+ ASSERT_TRUE(cookie_opt);
+ WebCanonicalCookie& cookie = cookie_opt.value();
+
+ EXPECT_EQ("name", cookie.Name());
+ EXPECT_EQ("value", cookie.Value());
+ EXPECT_EQ("domain", cookie.Domain());
+ EXPECT_EQ("/path", cookie.Path());
+ EXPECT_EQ(t1, cookie.CreationDate());
+ EXPECT_EQ(t2, cookie.ExpiryDate());
+ EXPECT_EQ(t3, cookie.LastAccessDate());
+ EXPECT_TRUE(cookie.IsSecure());
+ EXPECT_TRUE(cookie.IsHttpOnly());
+ EXPECT_EQ(network::mojom::CookieSameSite::STRICT_MODE, cookie.SameSite());
+ EXPECT_EQ(network::mojom::CookiePriority::HIGH, cookie.Priority());
+
+ // Exercise WebCookieSameSite values.
+ for (auto same_site : {network::mojom::CookieSameSite::NO_RESTRICTION,
+ network::mojom::CookieSameSite::LAX_MODE,
+ network::mojom::CookieSameSite::STRICT_MODE,
+ WebCanonicalCookie::kDefaultSameSiteMode}) {
+ EXPECT_EQ(same_site,
+ WebCanonicalCookie::Create("name", "value", "domain", "/path", t1,
+ t2, t3, false, false, same_site,
+ WebCanonicalCookie::kDefaultPriority)
+ ->SameSite());
+ }
+
+ // Exercise WebCookiePriority values.
+ for (auto priority : {network::mojom::CookiePriority::LOW,
+ network::mojom::CookiePriority::MEDIUM,
+ network::mojom::CookiePriority::HIGH,
+ WebCanonicalCookie::kDefaultPriority}) {
+ EXPECT_EQ(priority,
+ WebCanonicalCookie::Create(
+ "name", "value", "domain", "/path", t1, t2, t3, false, false,
+ WebCanonicalCookie::kDefaultSameSiteMode, priority)
+ ->Priority());
+ }
+}
+
+TEST(WebCanonicalCookieTest, BuildLine) {
+ const WebURL url(KURL("http://example.com"));
+ Vector<WebCanonicalCookie> cookies;
+
+ cookies.push_back(
+ WebCanonicalCookie::Create(url, "a=1", base::Time::Now()).value());
+ EXPECT_EQ("a=1", WebCanonicalCookie::BuildCookieLine(cookies));
+
+ cookies.push_back(
+ WebCanonicalCookie::Create(url, "b=2", base::Time::Now()).value());
+ EXPECT_EQ("a=1; b=2", WebCanonicalCookie::BuildCookieLine(cookies));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_cors.cc b/chromium/third_party/blink/renderer/platform/exported/web_cors.cc
index a1582c0b86d..eab6b54b207 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_cors.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_cors.cc
@@ -129,7 +129,7 @@ class HTTPHeaderNameListParser {
} // namespace
-base::Optional<CORSError> HandleRedirect(
+base::Optional<network::CORSErrorStatus> HandleRedirect(
WebSecurityOrigin& current_security_origin,
WebURLRequest& new_request,
const WebURL redirect_response_url,
@@ -148,10 +148,10 @@ base::Optional<CORSError> HandleRedirect(
base::Optional<CORSError> redirect_error =
CORS::CheckRedirectLocation(new_url);
if (redirect_error)
- return redirect_error;
+ return network::CORSErrorStatus(*redirect_error);
KURL redirect_response_kurl = redirect_response_url;
- base::Optional<CORSError> access_error =
+ base::Optional<network::CORSErrorStatus> access_error =
CORS::CheckAccess(redirect_response_kurl, redirect_response_status_code,
redirect_response_header.GetHTTPHeaderMap(),
credentials_mode, *current_security_origin.Get());
@@ -163,7 +163,7 @@ base::Optional<CORSError> HandleRedirect(
// Set request's origin to a globally unique identifier as specified in
// the step 10 in https://fetch.spec.whatwg.org/#http-redirect-fetch.
if (!last_origin->CanRequest(new_url)) {
- options.security_origin = SecurityOrigin::CreateUnique();
+ options.security_origin = SecurityOrigin::CreateUniqueOpaque();
new_security_origin = options.security_origin;
}
}
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_cursor_info.cc b/chromium/third_party/blink/renderer/platform/exported/web_cursor_info.cc
index 1d0d5bb473a..be87059c40e 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_cursor_info.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_cursor_info.cc
@@ -34,11 +34,18 @@
namespace blink {
+static SkBitmap GetCursorBitmap(const Cursor& cursor) {
+ if (!cursor.GetImage())
+ return {};
+ return cursor.GetImage()->AsSkBitmapForCurrentFrame(
+ kDoNotRespectImageOrientation);
+}
+
WebCursorInfo::WebCursorInfo(const Cursor& cursor)
: type(static_cast<Type>(cursor.GetType())),
hot_spot(cursor.HotSpot()),
image_scale_factor(cursor.ImageScaleFactor()),
- custom_image(cursor.GetImage())
+ custom_image(GetCursorBitmap(cursor))
#ifdef WIN32
,
external_handle(0)
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_data.cc b/chromium/third_party/blink/renderer/platform/exported/web_data.cc
index 41858db01a8..c09b94b79ed 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_data.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_data.cc
@@ -32,6 +32,8 @@
#include "third_party/blink/renderer/platform/shared_buffer.h"
+#include <vector>
+
namespace blink {
void WebData::Reset() {
@@ -53,7 +55,20 @@ size_t WebData::size() const {
}
size_t WebData::GetSomeData(const char*& data, size_t position) const {
- return private_.IsNull() ? 0 : private_->GetSomeData(data, position);
+ data = nullptr;
+ if (private_.IsNull())
+ return 0;
+ const auto it = private_->GetIteratorAt(position);
+ if (it == private_->cend())
+ return 0;
+ data = it->data();
+ return it->size();
+}
+
+WebVector<char> WebData::Copy() const {
+ return private_.IsNull()
+ ? WebVector<char>()
+ : WebVector<char>(private_->CopyAs<std::vector<char>>());
}
WebData::WebData(scoped_refptr<SharedBuffer> buffer)
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_font.cc b/chromium/third_party/blink/renderer/platform/exported/web_font.cc
index cd9169f805a..4e1dd3cee3e 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_font.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_font.cc
@@ -77,7 +77,7 @@ float WebFont::XHeight() const {
return font_data ? font_data->GetFontMetrics().XHeight() : 0;
}
-void WebFont::DrawText(WebCanvas* canvas,
+void WebFont::DrawText(cc::PaintCanvas* canvas,
const WebTextRun& run,
const WebFloatPoint& left_baseline,
SkColor color,
@@ -108,7 +108,8 @@ int WebFont::CalculateWidth(const WebTextRun& run) const {
}
int WebFont::OffsetForPosition(const WebTextRun& run, float position) const {
- return private_->GetFont().OffsetForPosition(run, position, true);
+ return private_->GetFont().OffsetForPosition(
+ run, position, IncludePartialGlyphs, DontBreakGlyphs);
}
WebFloatRect WebFont::SelectionRectForText(const WebTextRun& run,
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_image.cc b/chromium/third_party/blink/renderer/platform/exported/web_image.cc
index 628998b47c4..923da0d5953 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_image.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_image.cc
@@ -35,21 +35,20 @@
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/public/platform/web_size.h"
-#include "third_party/blink/renderer/platform/drag_image.h"
-#include "third_party/blink/renderer/platform/graphics/bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/skia/include/core/SkImage.h"
namespace blink {
-WebImage WebImage::FromData(const WebData& data, const WebSize& desired_size) {
+SkBitmap WebImage::FromData(const WebData& data, const WebSize& desired_size) {
+ const bool data_complete = true;
std::unique_ptr<ImageDecoder> decoder(ImageDecoder::Create(
- data, true, ImageDecoder::kAlphaPremultiplied, ColorBehavior::Ignore()));
+ data, data_complete, ImageDecoder::kAlphaPremultiplied,
+ ImageDecoder::kDefaultBitDepth, ColorBehavior::Ignore()));
if (!decoder || !decoder->IsSizeAvailable())
- return WebImage();
+ return {};
// Frames are arranged by decreasing size, then decreasing bit depth.
// Pick the frame closest to |desiredSize|'s area without being smaller,
@@ -75,25 +74,29 @@ WebImage WebImage::FromData(const WebData& data, const WebSize& desired_size) {
}
ImageFrame* frame = decoder->DecodeFrameBufferAtIndex(index);
- return (frame && !decoder->Failed()) ? WebImage(frame->Bitmap()) : WebImage();
+ if (!frame || decoder->Failed())
+ return {};
+ return frame->Bitmap();
}
-WebVector<WebImage> WebImage::FramesFromData(const WebData& data) {
+WebVector<SkBitmap> WebImage::FramesFromData(const WebData& data) {
// This is to protect from malicious images. It should be big enough that it's
// never hit in practice.
const size_t kMaxFrameCount = 8;
+ const bool data_complete = true;
std::unique_ptr<ImageDecoder> decoder(ImageDecoder::Create(
- data, true, ImageDecoder::kAlphaPremultiplied, ColorBehavior::Ignore()));
+ data, data_complete, ImageDecoder::kAlphaPremultiplied,
+ ImageDecoder::kDefaultBitDepth, ColorBehavior::Ignore()));
if (!decoder || !decoder->IsSizeAvailable())
- return WebVector<WebImage>();
+ return {};
// Frames are arranged by decreasing size, then decreasing bit depth.
// Keep the first frame at every size, has the highest bit depth.
const size_t frame_count = decoder->FrameCount();
IntSize last_size;
- Vector<WebImage> frames;
+ WebVector<SkBitmap> frames;
for (size_t i = 0; i < std::min(frame_count, kMaxFrameCount); ++i) {
const IntSize frame_size = decoder->FrameSizeAtIndex(i);
if (frame_size == last_size)
@@ -106,7 +109,7 @@ WebVector<WebImage> WebImage::FramesFromData(const WebData& data) {
SkBitmap bitmap = frame->Bitmap();
if (!bitmap.isNull() && frame->GetStatus() == ImageFrame::kFrameComplete)
- frames.push_back(WebImage(bitmap));
+ frames.emplace_back(std::move(bitmap));
}
return frames;
@@ -114,23 +117,25 @@ WebVector<WebImage> WebImage::FramesFromData(const WebData& data) {
WebVector<WebImage::AnimationFrame> WebImage::AnimationFromData(
const WebData& data) {
+ const bool data_complete = true;
std::unique_ptr<ImageDecoder> decoder(ImageDecoder::Create(
- data, true, ImageDecoder::kAlphaPremultiplied, ColorBehavior::Ignore()));
+ data, data_complete, ImageDecoder::kAlphaPremultiplied,
+ ImageDecoder::kDefaultBitDepth, ColorBehavior::Ignore()));
if (!decoder || !decoder->IsSizeAvailable() || decoder->FrameCount() == 0)
- return WebVector<WebImage::AnimationFrame>();
+ return {};
const size_t frame_count = decoder->FrameCount();
IntSize last_size = decoder->FrameSizeAtIndex(0);
- Vector<WebImage::AnimationFrame> frames;
- frames.ReserveCapacity(frame_count);
+ WebVector<WebImage::AnimationFrame> frames;
+ frames.reserve(frame_count);
for (size_t i = 0; i < frame_count; ++i) {
// If frame size changes, this is most likely not an animation and is
// instead an image with multiple versions at different resolutions. If
// that's the case, return only the first frame (or no frames if we failed
// decoding the first one).
if (last_size != decoder->FrameSizeAtIndex(i)) {
- frames.resize(frames.IsEmpty() ? 0 : 1);
+ frames.resize(frames.empty() ? 0 : 1);
return frames;
}
last_size = decoder->FrameSizeAtIndex(i);
@@ -149,47 +154,10 @@ WebVector<WebImage::AnimationFrame> WebImage::AnimationFromData(
AnimationFrame output;
output.bitmap = bitmap;
output.duration = frame->Duration();
- frames.push_back(output);
+ frames.emplace_back(std::move(output));
}
return frames;
}
-void WebImage::Reset() {
- bitmap_.reset();
-}
-
-void WebImage::Assign(const WebImage& image) {
- bitmap_ = image.bitmap_;
-}
-
-bool WebImage::IsNull() const {
- return bitmap_.isNull();
-}
-
-WebSize WebImage::Size() const {
- return WebSize(bitmap_.width(), bitmap_.height());
-}
-
-WebImage::WebImage(scoped_refptr<Image> image,
- RespectImageOrientationEnum should_respect_image_orientation) {
- if (!image)
- return;
-
- PaintImage paint_image = image->PaintImageForCurrentFrame();
- if (!paint_image)
- return;
-
- if (should_respect_image_orientation == kRespectImageOrientation &&
- image->IsBitmapImage()) {
- ImageOrientation orientation = ToBitmapImage(image.get())->CurrentFrameOrientation();
- paint_image = DragImage::ResizeAndOrientImage(paint_image, orientation);
- if (!paint_image)
- return;
- }
-
- if (sk_sp<SkImage> sk_image = paint_image.GetSkImage())
- sk_image->asLegacyBitmap(&bitmap_);
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_image_test.cc b/chromium/third_party/blink/renderer/platform/exported/web_image_test.cc
index 1c5a40e70d0..89b8a8a4b9d 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_image_test.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_image_test.cc
@@ -48,24 +48,24 @@ TEST(WebImageTest, PNGImage) {
scoped_refptr<SharedBuffer> data = ReadFile("white-1x1.png");
ASSERT_TRUE(data.get());
- WebImage image = WebImage::FromData(WebData(data), WebSize());
- EXPECT_TRUE(image.Size() == WebSize(1, 1));
- EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255),
- image.GetSkBitmap().getColor(0, 0));
+ SkBitmap image = WebImage::FromData(WebData(data), WebSize());
+ EXPECT_EQ(image.width(), 1);
+ EXPECT_EQ(image.height(), 1);
+ EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255), image.getColor(0, 0));
}
TEST(WebImageTest, ICOImage) {
scoped_refptr<SharedBuffer> data = ReadFile("black-and-white.ico");
ASSERT_TRUE(data.get());
- WebVector<WebImage> images = WebImage::FramesFromData(WebData(data));
+ WebVector<SkBitmap> images = WebImage::FramesFromData(WebData(data));
ASSERT_EQ(2u, images.size());
- EXPECT_TRUE(images[0].Size() == WebSize(2, 2));
- EXPECT_TRUE(images[1].Size() == WebSize(1, 1));
- EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255),
- images[0].GetSkBitmap().getColor(0, 0));
- EXPECT_EQ(SkColorSetARGB(255, 0, 0, 0),
- images[1].GetSkBitmap().getColor(0, 0));
+ EXPECT_EQ(images[0].width(), 2);
+ EXPECT_EQ(images[0].height(), 2);
+ EXPECT_EQ(images[1].width(), 1);
+ EXPECT_EQ(images[1].height(), 1);
+ EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255), images[0].getColor(0, 0));
+ EXPECT_EQ(SkColorSetARGB(255, 0, 0, 0), images[1].getColor(0, 0));
}
TEST(WebImageTest, ICOValidHeaderMissingBitmap) {
@@ -73,18 +73,18 @@ TEST(WebImageTest, ICOValidHeaderMissingBitmap) {
ReadFile("valid_header_missing_bitmap.ico");
ASSERT_TRUE(data.get());
- WebVector<WebImage> images = WebImage::FramesFromData(WebData(data));
- ASSERT_TRUE(images.IsEmpty());
+ WebVector<SkBitmap> images = WebImage::FramesFromData(WebData(data));
+ ASSERT_TRUE(images.empty());
}
TEST(WebImageTest, BadImage) {
const char kBadImage[] = "hello world";
- WebVector<WebImage> images = WebImage::FramesFromData(WebData(kBadImage));
+ WebVector<SkBitmap> images = WebImage::FramesFromData(WebData(kBadImage));
ASSERT_EQ(0u, images.size());
- WebImage image = WebImage::FromData(WebData(kBadImage), WebSize());
- EXPECT_TRUE(image.GetSkBitmap().empty());
- EXPECT_TRUE(image.GetSkBitmap().isNull());
+ SkBitmap image = WebImage::FromData(WebData(kBadImage), WebSize());
+ EXPECT_TRUE(image.empty());
+ EXPECT_TRUE(image.isNull());
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_media_constraints.cc b/chromium/third_party/blink/renderer/platform/exported/web_media_constraints.cc
index 62855e89d10..c379548df3e 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_media_constraints.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_media_constraints.cc
@@ -73,6 +73,7 @@ void MaybeEmitNamedBoolean(StringBuilder& builder,
} // namespace
const char kEchoCancellationTypeBrowser[] = "browser";
+const char kEchoCancellationTypeAec3[] = "aec3";
const char kEchoCancellationTypeSystem[] = "system";
class WebMediaConstraintsPrivate final
@@ -377,8 +378,6 @@ WebMediaTrackConstraintSet::WebMediaTrackConstraintSet()
goog_highpass_filter("googHighpassFilter"),
goog_typing_noise_detection("googTypingNoiseDetection"),
goog_experimental_noise_suppression("googExperimentalNoiseSuppression"),
- goog_beamforming("googBeamforming"),
- goog_array_geometry("googArrayGeometry"),
goog_audio_mirroring("googAudioMirroring"),
goog_da_echo_cancellation("googDAEchoCancellation"),
goog_noise_reduction("googNoiseReduction"),
@@ -441,8 +440,6 @@ std::vector<const BaseConstraint*> WebMediaTrackConstraintSet::AllConstraints()
&goog_highpass_filter,
&goog_typing_noise_detection,
&goog_experimental_noise_suppression,
- &goog_beamforming,
- &goog_array_geometry,
&goog_audio_mirroring,
&goog_da_echo_cancellation,
&goog_noise_reduction,
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_media_stream.cc b/chromium/third_party/blink/renderer/platform/exported/web_media_stream.cc
index 79491ffcb1a..839af49e861 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_media_stream.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_media_stream.cc
@@ -52,22 +52,20 @@ int WebMediaStream::UniqueId() const {
return private_->UniqueId();
}
-void WebMediaStream::AudioTracks(
- WebVector<WebMediaStreamTrack>& web_tracks) const {
+WebVector<WebMediaStreamTrack> WebMediaStream::AudioTracks() const {
size_t number_of_tracks = private_->NumberOfAudioComponents();
WebVector<WebMediaStreamTrack> result(number_of_tracks);
for (size_t i = 0; i < number_of_tracks; ++i)
result[i] = private_->AudioComponent(i);
- web_tracks.Swap(result);
+ return result;
}
-void WebMediaStream::VideoTracks(
- WebVector<WebMediaStreamTrack>& web_tracks) const {
+WebVector<WebMediaStreamTrack> WebMediaStream::VideoTracks() const {
size_t number_of_tracks = private_->NumberOfVideoComponents();
WebVector<WebMediaStreamTrack> result(number_of_tracks);
for (size_t i = 0; i < number_of_tracks; ++i)
result[i] = private_->VideoComponent(i);
- web_tracks.Swap(result);
+ return result;
}
WebMediaStreamTrack WebMediaStream::GetAudioTrack(
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_prerendering_support.cc b/chromium/third_party/blink/renderer/platform/exported/web_prerendering_support.cc
index c05a368ef48..edc12ec2d3c 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_prerendering_support.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_prerendering_support.cc
@@ -34,14 +34,17 @@ namespace blink {
WebPrerenderingSupport* WebPrerenderingSupport::platform_ = nullptr;
+// static
void WebPrerenderingSupport::Initialize(WebPrerenderingSupport* platform) {
platform_ = platform;
}
+// static
void WebPrerenderingSupport::Shutdown() {
platform_ = nullptr;
}
+// static
WebPrerenderingSupport* WebPrerenderingSupport::Current() {
return platform_;
}
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_rtc_rtp_transceiver.cc b/chromium/third_party/blink/renderer/platform/exported/web_rtc_rtp_transceiver.cc
new file mode 100644
index 00000000000..e84f55ab58b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/exported/web_rtc_rtp_transceiver.cc
@@ -0,0 +1,11 @@
+// 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/public/platform/web_rtc_rtp_transceiver.h"
+
+namespace blink {
+
+WebRTCRtpTransceiver::~WebRTCRtpTransceiver() = default;
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/chromium/third_party/blink/renderer/platform/exported/web_runtime_features.cc
index 78bbbc5b4bc..e3383f473da 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_runtime_features.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -35,6 +35,14 @@
namespace blink {
+void WebRuntimeFeatures::EnableBlinkHeapIncrementalMarking(bool enable) {
+ RuntimeEnabledFeatures::SetHeapIncrementalMarkingEnabled(enable);
+}
+
+void WebRuntimeFeatures::EnableBloatedRendererDetection(bool enable) {
+ RuntimeEnabledFeatures::SetBloatedRendererDetectionEnabled(enable);
+}
+
void WebRuntimeFeatures::EnableExperimentalFeatures(bool enable) {
RuntimeEnabledFeatures::SetExperimentalFeaturesEnabled(enable);
}
@@ -68,8 +76,8 @@ void WebRuntimeFeatures::EnableOriginTrialControlledFeatures(bool enable) {
RuntimeEnabledFeatures::SetOriginTrialControlledFeaturesEnabled(enable);
}
-void WebRuntimeFeatures::EnableOriginManifest(bool enable) {
- RuntimeEnabledFeatures::SetOriginManifestEnabled(enable);
+void WebRuntimeFeatures::EnableOriginPolicy(bool enable) {
+ RuntimeEnabledFeatures::SetOriginPolicyEnabled(enable);
}
void WebRuntimeFeatures::EnableOutOfBlinkCORS(bool enable) {
@@ -80,6 +88,14 @@ void WebRuntimeFeatures::EnableAccelerated2dCanvas(bool enable) {
RuntimeEnabledFeatures::SetAccelerated2dCanvasEnabled(enable);
}
+void WebRuntimeFeatures::EnableAccessibilityObjectModel(bool enable) {
+ RuntimeEnabledFeatures::SetAccessibilityObjectModelEnabled(enable);
+}
+
+void WebRuntimeFeatures::EnableAdTagging(bool enable) {
+ RuntimeEnabledFeatures::SetAdTaggingEnabled(enable);
+}
+
void WebRuntimeFeatures::EnableAllowActivationDelegationAttr(bool enable) {
RuntimeEnabledFeatures::SetAllowActivationDelegationAttrEnabled(enable);
}
@@ -112,6 +128,10 @@ void WebRuntimeFeatures::EnableCSSHexAlphaColor(bool enable) {
RuntimeEnabledFeatures::SetCSSHexAlphaColorEnabled(enable);
}
+void WebRuntimeFeatures::EnableCSSFragmentIdentifiers(bool enable) {
+ RuntimeEnabledFeatures::SetCSSFragmentIdentifiersEnabled(enable);
+}
+
void WebRuntimeFeatures::EnableScrollTopLeftInterop(bool enable) {
RuntimeEnabledFeatures::SetScrollTopLeftInteropEnabled(enable);
}
@@ -160,18 +180,22 @@ void WebRuntimeFeatures::EnableInputMultipleFieldsUI(bool enable) {
RuntimeEnabledFeatures::SetInputMultipleFieldsUIEnabled(enable);
}
-void WebRuntimeFeatures::EnableIntersectionObserverGeometryMapper(bool enable) {
- RuntimeEnabledFeatures::SetIntersectionObserverGeometryMapperEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableLayeredAPI(bool enable) {
RuntimeEnabledFeatures::SetLayeredAPIEnabled(enable);
}
+void WebRuntimeFeatures::EnableLayoutNG(bool enable) {
+ RuntimeEnabledFeatures::SetLayoutNGEnabled(enable);
+}
+
void WebRuntimeFeatures::EnableLazyFrameLoading(bool enable) {
RuntimeEnabledFeatures::SetLazyFrameLoadingEnabled(enable);
}
+void WebRuntimeFeatures::EnableLazyFrameVisibleLoadTimeMetrics(bool enable) {
+ RuntimeEnabledFeatures::SetLazyFrameVisibleLoadTimeMetricsEnabled(enable);
+}
+
void WebRuntimeFeatures::EnableLazyParseCSS(bool enable) {
RuntimeEnabledFeatures::SetLazyParseCSSEnabled(enable);
}
@@ -212,6 +236,10 @@ void WebRuntimeFeatures::EnableNavigatorContentUtils(bool enable) {
RuntimeEnabledFeatures::SetNavigatorContentUtilsEnabled(enable);
}
+void WebRuntimeFeatures::EnableNestedWorkers(bool enable) {
+ RuntimeEnabledFeatures::SetNestedWorkersEnabled(enable);
+}
+
void WebRuntimeFeatures::EnableNetInfoDownlinkMax(bool enable) {
RuntimeEnabledFeatures::SetNetInfoDownlinkMaxEnabled(enable);
}
@@ -240,6 +268,10 @@ void WebRuntimeFeatures::EnableOverflowIconsForMediaControls(bool enable) {
RuntimeEnabledFeatures::SetOverflowIconsForMediaControlsEnabled(enable);
}
+void WebRuntimeFeatures::EnablePageLifecycle(bool enable) {
+ RuntimeEnabledFeatures::SetPageLifecycleEnabled(enable);
+}
+
void WebRuntimeFeatures::EnablePagePopup(bool enable) {
RuntimeEnabledFeatures::SetPagePopupEnabled(enable);
}
@@ -268,6 +300,10 @@ void WebRuntimeFeatures::EnablePictureInPicture(bool enable) {
RuntimeEnabledFeatures::SetPictureInPictureEnabled(enable);
}
+void WebRuntimeFeatures::EnablePictureInPictureAPI(bool enable) {
+ RuntimeEnabledFeatures::SetPictureInPictureAPIEnabled(enable);
+}
+
void WebRuntimeFeatures::EnablePreloadDefaultIsMetadata(bool enable) {
RuntimeEnabledFeatures::SetPreloadDefaultIsMetadataEnabled(enable);
}
@@ -296,8 +332,8 @@ void WebRuntimeFeatures::EnableTouchEventFeatureDetection(bool enable) {
RuntimeEnabledFeatures::SetTouchEventFeatureDetectionEnabled(enable);
}
-void WebRuntimeFeatures::EnableTouchpadAndWheelScrollLatching(bool enable) {
- RuntimeEnabledFeatures::SetTouchpadAndWheelScrollLatchingEnabled(enable);
+void WebRuntimeFeatures::EnableWebGL2ComputeContext(bool enable) {
+ RuntimeEnabledFeatures::SetWebGL2ComputeContextEnabled(enable);
}
void WebRuntimeFeatures::EnableWebGLDraftExtensions(bool enable) {
@@ -352,6 +388,10 @@ void WebRuntimeFeatures::EnableWebShare(bool enable) {
RuntimeEnabledFeatures::SetWebShareEnabled(enable);
}
+void WebRuntimeFeatures::EnableWebGPU(bool enable) {
+ RuntimeEnabledFeatures::SetWebGPUEnabled(enable);
+}
+
void WebRuntimeFeatures::EnableWebVR(bool enable) {
RuntimeEnabledFeatures::SetWebVREnabled(enable);
}
@@ -466,10 +506,6 @@ void WebRuntimeFeatures::EnableLazyInitializeMediaControls(bool enable) {
RuntimeEnabledFeatures::SetLazyInitializeMediaControlsEnabled(enable);
}
-void WebRuntimeFeatures::EnableClientHintsPersistent(bool enable) {
- RuntimeEnabledFeatures::SetClientHintsPersistentEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableMediaEngagementBypassAutoplayPolicies(
bool enable) {
RuntimeEnabledFeatures::SetMediaEngagementBypassAutoplayPoliciesEnabled(
@@ -492,10 +528,6 @@ void WebRuntimeFeatures::EnableStopInBackground(bool enable) {
RuntimeEnabledFeatures::SetStopInBackgroundEnabled(enable);
}
-void WebRuntimeFeatures::EnableStopLoadingInBackground(bool enable) {
- RuntimeEnabledFeatures::SetStopLoadingInBackgroundEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableStopNonTimersInBackground(bool enable) {
RuntimeEnabledFeatures::SetStopNonTimersInBackgroundEnabled(enable);
}
@@ -504,10 +536,6 @@ void WebRuntimeFeatures::EnablePWAFullCodeCache(bool enable) {
RuntimeEnabledFeatures::SetPWAFullCodeCacheEnabled(enable);
}
-void WebRuntimeFeatures::EnableMojoBlobURLs(bool enable) {
- RuntimeEnabledFeatures::SetMojoBlobURLsEnabled(enable);
-}
-
void WebRuntimeFeatures::EnableOffMainThreadWebSocket(bool enable) {
RuntimeEnabledFeatures::SetOffMainThreadWebSocketEnabled(enable);
}
@@ -516,12 +544,16 @@ void WebRuntimeFeatures::EnableExperimentalProductivityFeatures(bool enable) {
RuntimeEnabledFeatures::SetExperimentalProductivityFeaturesEnabled(enable);
}
-void WebRuntimeFeatures::EnableDisplayCutoutViewportFit(bool enable) {
- RuntimeEnabledFeatures::SetDisplayCutoutViewportFitEnabled(enable);
+void WebRuntimeFeatures::EnableDisplayCutoutAPI(bool enable) {
+ RuntimeEnabledFeatures::SetDisplayCutoutAPIEnabled(enable);
}
void WebRuntimeFeatures::EnableAutoplayIgnoresWebAudio(bool enable) {
RuntimeEnabledFeatures::SetAutoplayIgnoresWebAudioEnabled(enable);
}
+void WebRuntimeFeatures::EnableMediaControlsExpandGesture(bool enable) {
+ RuntimeEnabledFeatures::SetMediaControlsExpandGestureEnabled(enable);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_security_origin.cc b/chromium/third_party/blink/renderer/platform/exported/web_security_origin.cc
index 003b6a1e754..b27ecac4625 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_security_origin.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_security_origin.cc
@@ -45,8 +45,8 @@ WebSecurityOrigin WebSecurityOrigin::Create(const WebURL& url) {
return WebSecurityOrigin(SecurityOrigin::Create(url));
}
-WebSecurityOrigin WebSecurityOrigin::CreateUnique() {
- return WebSecurityOrigin(SecurityOrigin::CreateUnique());
+WebSecurityOrigin WebSecurityOrigin::CreateUniqueOpaque() {
+ return WebSecurityOrigin(SecurityOrigin::CreateUniqueOpaque());
}
void WebSecurityOrigin::Reset() {
@@ -77,9 +77,9 @@ unsigned short WebSecurityOrigin::EffectivePort() const {
return private_->EffectivePort();
}
-bool WebSecurityOrigin::IsUnique() const {
+bool WebSecurityOrigin::IsOpaque() const {
DCHECK(private_);
- return private_->IsUnique();
+ return private_->IsOpaque();
}
bool WebSecurityOrigin::CanAccess(const WebSecurityOrigin& other) const {
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_service_worker_installed_scripts_manager.cc b/chromium/third_party/blink/renderer/platform/exported/web_service_worker_installed_scripts_manager.cc
index 7ed3c333392..389e12f08f7 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_service_worker_installed_scripts_manager.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_service_worker_installed_scripts_manager.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/public/platform/modules/serviceworker/web_service_worker_installed_scripts_manager.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_installed_scripts_manager.h"
#include <memory>
#include <utility>
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_service_worker_request.cc b/chromium/third_party/blink/renderer/platform/exported/web_service_worker_request.cc
index a55f8834fa6..ba0a0c6d25a 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_service_worker_request.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_service_worker_request.cc
@@ -2,8 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "third_party/blink/public/platform/modules/serviceworker/web_service_worker_request.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_request.h"
+#include "third_party/blink/public/platform/web_http_body.h"
#include "third_party/blink/public/platform/web_http_header_visitor.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url_request.h"
@@ -39,6 +40,7 @@ class WebServiceWorkerRequestPrivate
bool keepalive_ = false;
WebString client_id_;
bool is_reload_ = false;
+ bool is_history_navigation_ = false;
};
WebServiceWorkerRequest::WebServiceWorkerRequest()
@@ -250,4 +252,12 @@ bool WebServiceWorkerRequest::IsReload() const {
return private_->is_reload_;
}
+void WebServiceWorkerRequest::SetIsHistoryNavigation(bool b) {
+ private_->is_history_navigation_ = b;
+}
+
+bool WebServiceWorkerRequest::IsHistoryNavigation() const {
+ return private_->is_history_navigation_;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_service_worker_response.cc b/chromium/third_party/blink/renderer/platform/exported/web_service_worker_response.cc
index 90cf2254a39..414a82a02c5 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_service_worker_response.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_service_worker_response.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/public/platform/modules/serviceworker/web_service_worker_response.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_response.h"
#include "third_party/blink/public/platform/web_http_header_visitor.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_service_worker_stream_handle.cc b/chromium/third_party/blink/renderer/platform/exported/web_service_worker_stream_handle.cc
index fa0b64f3b8e..3ebc5f3303e 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_service_worker_stream_handle.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_service_worker_stream_handle.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/public/platform/modules/serviceworker/web_service_worker_stream_handle.h"
+#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_stream_handle.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_surface_layer_bridge.cc b/chromium/third_party/blink/renderer/platform/exported/web_surface_layer_bridge.cc
index e434b442c5b..8910562d6d8 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_surface_layer_bridge.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_surface_layer_bridge.cc
@@ -11,8 +11,10 @@ namespace blink {
std::unique_ptr<WebSurfaceLayerBridge> WebSurfaceLayerBridge::Create(
WebLayerTreeView* layer_tree_view,
- WebSurfaceLayerBridgeObserver* observer) {
- return std::make_unique<SurfaceLayerBridge>(layer_tree_view, observer);
+ WebSurfaceLayerBridgeObserver* observer,
+ cc::UpdateSubmissionStateCB update_submission_state_callback) {
+ return std::make_unique<SurfaceLayerBridge>(
+ layer_tree_view, observer, std::move(update_submission_state_callback));
}
WebSurfaceLayerBridge::~WebSurfaceLayerBridge() = default;
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_url_request.cc b/chromium/third_party/blink/renderer/platform/exported/web_url_request.cc
index 632bf7f2566..0a8f1173569 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_url_request.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_url_request.cc
@@ -31,11 +31,14 @@
#include "third_party/blink/public/platform/web_url_request.h"
#include <memory>
+#include "base/time/time.h"
#include "third_party/blink/public/platform/web_http_body.h"
#include "third_party/blink/public/platform/web_http_header_visitor.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
+#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
@@ -122,7 +125,7 @@ void WebURLRequest::SetCacheMode(mojom::FetchCacheMode cache_mode) {
resource_request_->SetCacheMode(cache_mode);
}
-double WebURLRequest::TimeoutInterval() const {
+base::TimeDelta WebURLRequest::TimeoutInterval() const {
return resource_request_->TimeoutInterval();
}
@@ -251,14 +254,6 @@ void WebURLRequest::SetAppCacheHostID(int app_cache_host_id) {
resource_request_->SetAppCacheHostID(app_cache_host_id);
}
-bool WebURLRequest::DownloadToFile() const {
- return resource_request_->DownloadToFile();
-}
-
-void WebURLRequest::SetDownloadToFile(bool download_to_file) {
- resource_request_->SetDownloadToFile(download_to_file);
-}
-
bool WebURLRequest::PassResponsePipeToClient() const {
return resource_request_->DownloadToBlob();
}
@@ -375,14 +370,6 @@ void WebURLRequest::SetWasDiscarded(bool was_discarded) {
resource_request_->SetWasDiscarded(was_discarded);
}
-double WebURLRequest::UiStartTime() const {
- return resource_request_->UiStartTime();
-}
-
-void WebURLRequest::SetUiStartTime(double time_seconds) {
- resource_request_->SetUIStartTime(time_seconds);
-}
-
bool WebURLRequest::IsExternalRequest() const {
return resource_request_->IsExternalRequest();
}
@@ -397,22 +384,6 @@ void WebURLRequest::SetNavigationStartTime(
resource_request_->SetNavigationStartTime(navigation_start_seconds);
}
-void WebURLRequest::SetIsSameDocumentNavigation(bool is_same_document) {
- resource_request_->SetIsSameDocumentNavigation(is_same_document);
-}
-
-WebURLRequest::InputToLoadPerfMetricReportPolicy
-WebURLRequest::InputPerfMetricReportPolicy() const {
- return static_cast<WebURLRequest::InputToLoadPerfMetricReportPolicy>(
- resource_request_->InputPerfMetricReportPolicy());
-}
-
-void WebURLRequest::SetInputPerfMetricReportPolicy(
- WebURLRequest::InputToLoadPerfMetricReportPolicy policy) {
- resource_request_->SetInputPerfMetricReportPolicy(
- static_cast<blink::InputToLoadPerfMetricReportPolicy>(policy));
-}
-
base::Optional<WebString> WebURLRequest::GetSuggestedFilename() const {
if (!resource_request_->GetSuggestedFilename().has_value())
return base::Optional<WebString>();
@@ -428,6 +399,31 @@ const WebContentSecurityPolicyList& WebURLRequest::GetNavigationCSP() const {
return resource_request_->GetInitiatorCSP();
}
+void WebURLRequest::SetUpgradeIfInsecure(bool upgrade_if_insecure) {
+ resource_request_->SetUpgradeIfInsecure(upgrade_if_insecure);
+}
+
+bool WebURLRequest::UpgradeIfInsecure() const {
+ return resource_request_->UpgradeIfInsecure();
+}
+
+bool WebURLRequest::SupportsAsyncRevalidation() const {
+ return resource_request_->AllowsStaleResponse();
+}
+
+const base::Optional<base::UnguessableToken>& WebURLRequest::GetDevToolsToken()
+ const {
+ return resource_request_->GetDevToolsToken();
+}
+
+void WebURLRequest::SetOriginPolicy(const WebString& policy) {
+ resource_request_->SetOriginPolicy(policy);
+}
+
+const WebString WebURLRequest::GetOriginPolicy() const {
+ return resource_request_->GetOriginPolicy();
+}
+
const ResourceRequest& WebURLRequest::ToResourceRequest() const {
DCHECK(resource_request_);
return *resource_request_;
diff --git a/chromium/third_party/blink/renderer/platform/exported/web_url_response.cc b/chromium/third_party/blink/renderer/platform/exported/web_url_response.cc
index 26f131d1ea0..eee8ae58c69 100644
--- a/chromium/third_party/blink/renderer/platform/exported/web_url_response.cc
+++ b/chromium/third_party/blink/renderer/platform/exported/web_url_response.cc
@@ -70,28 +70,16 @@ class URLResponseExtraDataContainer : public ResourceResponse::ExtraData {
} // namespace
-// The purpose of this struct is to permit allocating a ResourceResponse on the
-// heap, which is otherwise disallowed by the DISALLOW_NEW_EXCEPT_PLACEMENT_NEW
-// annotation on ResourceResponse.
-struct WebURLResponse::ResourceResponseContainer {
- ResourceResponseContainer() = default;
-
- explicit ResourceResponseContainer(const ResourceResponse& r)
- : resource_response(r) {}
-
- ResourceResponse resource_response;
-};
-
WebURLResponse::~WebURLResponse() = default;
WebURLResponse::WebURLResponse()
- : owned_resource_response_(new ResourceResponseContainer()),
- resource_response_(&owned_resource_response_->resource_response) {}
+ : owned_resource_response_(std::make_unique<ResourceResponse>()),
+ resource_response_(owned_resource_response_.get()) {}
WebURLResponse::WebURLResponse(const WebURLResponse& r)
: owned_resource_response_(
- new ResourceResponseContainer(*r.resource_response_)),
- resource_response_(&owned_resource_response_->resource_response) {}
+ std::make_unique<ResourceResponse>(*r.resource_response_)),
+ resource_response_(owned_resource_response_.get()) {}
WebURLResponse::WebURLResponse(const WebURL& url) : WebURLResponse() {
SetURL(url);
@@ -385,14 +373,6 @@ void WebURLResponse::SetDidServiceWorkerNavigationPreload(bool value) {
resource_response_->SetDidServiceWorkerNavigationPreload(value);
}
-WebString WebURLResponse::DownloadFilePath() const {
- return resource_response_->DownloadedFilePath();
-}
-
-void WebURLResponse::SetDownloadFilePath(const WebString& download_file_path) {
- resource_response_->SetDownloadedFilePath(download_file_path);
-}
-
WebString WebURLResponse::RemoteIPAddress() const {
return resource_response_->RemoteIPAddress();
}
@@ -451,6 +431,10 @@ void WebURLResponse::SetConnectionInfo(
resource_response_->SetConnectionInfo(connection_info);
}
+void WebURLResponse::SetAsyncRevalidationRequested(bool requested) {
+ resource_response_->SetAsyncRevalidationRequested(requested);
+}
+
WebURLResponse::WebURLResponse(ResourceResponse& r) : resource_response_(&r) {}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/feature_policy/feature_policy.cc b/chromium/third_party/blink/renderer/platform/feature_policy/feature_policy.cc
index b7c27b6ad28..79d0ba67f18 100644
--- a/chromium/third_party/blink/renderer/platform/feature_policy/feature_policy.cc
+++ b/chromium/third_party/blink/renderer/platform/feature_policy/feature_policy.cc
@@ -3,6 +3,8 @@
#include "third_party/blink/renderer/platform/feature_policy/feature_policy.h"
+#include <algorithm>
+
#include "third_party/blink/renderer/platform/json/json_values.h"
#include "third_party/blink/renderer/platform/network/http_parsers.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -38,7 +40,7 @@ ParsedFeaturePolicy ParseFeaturePolicy(
scoped_refptr<const SecurityOrigin> src_origin,
Vector<String>* messages,
const FeatureNameMap& feature_names) {
- ParsedFeaturePolicy whitelists;
+ ParsedFeaturePolicy allowlists;
BitVector features_specified(
static_cast<int>(mojom::FeaturePolicyFeature::kMaxValue));
@@ -72,8 +74,8 @@ ParsedFeaturePolicy ParseFeaturePolicy(
if (features_specified.QuickGet(static_cast<int>(feature)))
continue;
- ParsedFeaturePolicyDeclaration whitelist;
- whitelist.feature = feature;
+ ParsedFeaturePolicyDeclaration allowlist;
+ allowlist.feature = feature;
features_specified.QuickSet(static_cast<int>(feature));
std::vector<url::Origin> origins;
// If a policy entry has no (optional) values (e,g,
@@ -86,10 +88,10 @@ ParsedFeaturePolicy ParseFeaturePolicy(
if (tokens.size() == 1) {
if (!src_origin) {
origins.push_back(self_origin->ToUrlOrigin());
- } else if (!src_origin->IsUnique()) {
+ } else if (!src_origin->IsOpaque()) {
origins.push_back(src_origin->ToUrlOrigin());
} else {
- whitelist.matches_opaque_src = true;
+ allowlist.matches_opaque_src = true;
}
}
@@ -109,15 +111,15 @@ ParsedFeaturePolicy ParseFeaturePolicy(
// opaque origin of the frame, which is not known yet. In this case,
// the |matches_opaque_src| flag on the declaration is set, rather
// than adding an origin to the allowlist.
- if (src_origin->IsUnique()) {
- whitelist.matches_opaque_src = true;
+ if (src_origin->IsOpaque()) {
+ allowlist.matches_opaque_src = true;
} else {
origins.push_back(src_origin->ToUrlOrigin());
}
} else if (EqualIgnoringASCIICase(tokens[i], "'none'")) {
continue;
} else if (tokens[i] == "*") {
- whitelist.matches_all_origins = true;
+ allowlist.matches_all_origins = true;
break;
} else {
url::Origin target_origin = url::Origin::Create(
@@ -128,76 +130,110 @@ ParsedFeaturePolicy ParseFeaturePolicy(
messages->push_back("Unrecognized origin: '" + tokens[i] + "'.");
}
}
- whitelist.origins = origins;
- whitelists.push_back(whitelist);
+ allowlist.origins = origins;
+ allowlists.push_back(allowlist);
}
}
- return whitelists;
+ return allowlists;
}
-bool IsSupportedInFeaturePolicy(mojom::FeaturePolicyFeature feature) {
- switch (feature) {
- case mojom::FeaturePolicyFeature::kFullscreen:
- case mojom::FeaturePolicyFeature::kPayment:
- case mojom::FeaturePolicyFeature::kUsb:
- case mojom::FeaturePolicyFeature::kWebVr:
- case mojom::FeaturePolicyFeature::kAccelerometer:
- case mojom::FeaturePolicyFeature::kAmbientLightSensor:
- case mojom::FeaturePolicyFeature::kGyroscope:
- case mojom::FeaturePolicyFeature::kMagnetometer:
- case mojom::FeaturePolicyFeature::kPictureInPicture:
- case mojom::FeaturePolicyFeature::kSyncXHR:
- return true;
- case mojom::FeaturePolicyFeature::kUnsizedMedia:
- case mojom::FeaturePolicyFeature::kVerticalScroll:
- case mojom::FeaturePolicyFeature::kLegacyImageFormats:
- case mojom::FeaturePolicyFeature::kImageCompression:
- case mojom::FeaturePolicyFeature::kDocumentStreamInsertion:
- case mojom::FeaturePolicyFeature::kMaxDownscalingImage:
- return RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled();
- default:
- return false;
- }
+bool IsFeatureDeclared(mojom::FeaturePolicyFeature feature,
+ const ParsedFeaturePolicy& policy) {
+ return std::any_of(policy.begin(), policy.end(),
+ [feature](const auto& declaration) {
+ return declaration.feature == feature;
+ });
+}
+
+bool RemoveFeatureIfPresent(mojom::FeaturePolicyFeature feature,
+ ParsedFeaturePolicy& policy) {
+ auto new_end = std::remove_if(policy.begin(), policy.end(),
+ [feature](const auto& declaration) {
+ return declaration.feature == feature;
+ });
+ if (new_end == policy.end())
+ return false;
+ policy.erase(new_end, policy.end());
+ return true;
+}
+
+bool DisallowFeatureIfNotPresent(mojom::FeaturePolicyFeature feature,
+ ParsedFeaturePolicy& policy) {
+ if (IsFeatureDeclared(feature, policy))
+ return false;
+ ParsedFeaturePolicyDeclaration allowlist;
+ allowlist.feature = feature;
+ allowlist.matches_all_origins = false;
+ allowlist.matches_opaque_src = false;
+ policy.push_back(allowlist);
+ return true;
}
+bool AllowFeatureEverywhereIfNotPresent(mojom::FeaturePolicyFeature feature,
+ ParsedFeaturePolicy& policy) {
+ if (IsFeatureDeclared(feature, policy))
+ return false;
+ ParsedFeaturePolicyDeclaration allowlist;
+ allowlist.feature = feature;
+ allowlist.matches_all_origins = true;
+ allowlist.matches_opaque_src = true;
+ policy.push_back(allowlist);
+ return true;
+}
+
+void DisallowFeature(mojom::FeaturePolicyFeature feature,
+ ParsedFeaturePolicy& policy) {
+ RemoveFeatureIfPresent(feature, policy);
+ DisallowFeatureIfNotPresent(feature, policy);
+}
+
+void AllowFeatureEverywhere(mojom::FeaturePolicyFeature feature,
+ ParsedFeaturePolicy& policy) {
+ RemoveFeatureIfPresent(feature, policy);
+ AllowFeatureEverywhereIfNotPresent(feature, policy);
+}
+
+// This method defines the feature names which will be recognized by the parser
+// for the Feature-Policy HTTP header and the <iframe> "allow" attribute, as
+// well as the features which will be recognized by the document or iframe
+// policy object.
+//
+// Features which are implemented behind a flag should generally also have the
+// same flag controlling whether they are in this map. Note that features which
+// are shipping as part of an origin trial should add their feature names to
+// this map unconditionally, as the trial token could be added after the HTTP
+// header needs to be parsed. This also means that top-level documents which
+// simply want to embed another page which uses an origin trial feature, without
+// using the feature themselves, can use feature policy to allow use of the
+// feature in subframes. (The framed document will still require a valid origin
+// trial token to use the feature in this scenario.)
const FeatureNameMap& GetDefaultFeatureNameMap() {
DEFINE_STATIC_LOCAL(FeatureNameMap, default_feature_name_map, ());
if (default_feature_name_map.IsEmpty()) {
- default_feature_name_map.Set("fullscreen",
- mojom::FeaturePolicyFeature::kFullscreen);
- default_feature_name_map.Set("payment",
- mojom::FeaturePolicyFeature::kPayment);
- default_feature_name_map.Set("usb", mojom::FeaturePolicyFeature::kUsb);
default_feature_name_map.Set("camera",
mojom::FeaturePolicyFeature::kCamera);
default_feature_name_map.Set("encrypted-media",
mojom::FeaturePolicyFeature::kEncryptedMedia);
- default_feature_name_map.Set("microphone",
- mojom::FeaturePolicyFeature::kMicrophone);
- default_feature_name_map.Set("speaker",
- mojom::FeaturePolicyFeature::kSpeaker);
+ default_feature_name_map.Set("fullscreen",
+ mojom::FeaturePolicyFeature::kFullscreen);
default_feature_name_map.Set("geolocation",
mojom::FeaturePolicyFeature::kGeolocation);
+ default_feature_name_map.Set("microphone",
+ mojom::FeaturePolicyFeature::kMicrophone);
default_feature_name_map.Set("midi",
mojom::FeaturePolicyFeature::kMidiFeature);
+ default_feature_name_map.Set("speaker",
+ mojom::FeaturePolicyFeature::kSpeaker);
default_feature_name_map.Set("sync-xhr",
mojom::FeaturePolicyFeature::kSyncXHR);
+ // Under origin trial: Should be made conditional on WebVR and WebXR
+ // runtime flags once it is out of trial.
default_feature_name_map.Set("vr", mojom::FeaturePolicyFeature::kWebVr);
- default_feature_name_map.Set("accelerometer",
- mojom::FeaturePolicyFeature::kAccelerometer);
- default_feature_name_map.Set(
- "ambient-light-sensor",
- mojom::FeaturePolicyFeature::kAmbientLightSensor);
- default_feature_name_map.Set("gyroscope",
- mojom::FeaturePolicyFeature::kGyroscope);
- default_feature_name_map.Set("magnetometer",
- mojom::FeaturePolicyFeature::kMagnetometer);
- default_feature_name_map.Set("picture-in-picture",
- mojom::FeaturePolicyFeature::kPictureInPicture);
if (RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled()) {
- default_feature_name_map.Set(
- "document-stream-insertion",
- mojom::FeaturePolicyFeature::kDocumentStreamInsertion);
+ default_feature_name_map.Set("animations",
+ mojom::FeaturePolicyFeature::kAnimations);
+ default_feature_name_map.Set("document-write",
+ mojom::FeaturePolicyFeature::kDocumentWrite);
default_feature_name_map.Set(
"image-compression", mojom::FeaturePolicyFeature::kImageCompression);
default_feature_name_map.Set(
@@ -206,25 +242,39 @@ const FeatureNameMap& GetDefaultFeatureNameMap() {
default_feature_name_map.Set(
"max-downscaling-image",
mojom::FeaturePolicyFeature::kMaxDownscalingImage);
- default_feature_name_map.Set("sync-script",
- mojom::FeaturePolicyFeature::kSyncScript);
default_feature_name_map.Set("unsized-media",
mojom::FeaturePolicyFeature::kUnsizedMedia);
default_feature_name_map.Set(
"vertical-scroll", mojom::FeaturePolicyFeature::kVerticalScroll);
- }
- if (RuntimeEnabledFeatures::FeaturePolicyExperimentalFeaturesEnabled()) {
- default_feature_name_map.Set("animations",
- mojom::FeaturePolicyFeature::kAnimations);
- default_feature_name_map.Set(
- "cookie", mojom::FeaturePolicyFeature::kDocumentCookie);
- default_feature_name_map.Set(
- "domain", mojom::FeaturePolicyFeature::kDocumentDomain);
+ default_feature_name_map.Set("sync-script",
+ mojom::FeaturePolicyFeature::kSyncScript);
}
if (RuntimeEnabledFeatures::FeaturePolicyAutoplayFeatureEnabled()) {
default_feature_name_map.Set("autoplay",
mojom::FeaturePolicyFeature::kAutoplay);
}
+ if (RuntimeEnabledFeatures::PaymentRequestEnabled()) {
+ default_feature_name_map.Set("payment",
+ mojom::FeaturePolicyFeature::kPayment);
+ }
+ if (RuntimeEnabledFeatures::PictureInPictureAPIEnabled()) {
+ default_feature_name_map.Set(
+ "picture-in-picture", mojom::FeaturePolicyFeature::kPictureInPicture);
+ }
+ if (RuntimeEnabledFeatures::SensorEnabled()) {
+ default_feature_name_map.Set("accelerometer",
+ mojom::FeaturePolicyFeature::kAccelerometer);
+ default_feature_name_map.Set(
+ "ambient-light-sensor",
+ mojom::FeaturePolicyFeature::kAmbientLightSensor);
+ default_feature_name_map.Set("gyroscope",
+ mojom::FeaturePolicyFeature::kGyroscope);
+ default_feature_name_map.Set("magnetometer",
+ mojom::FeaturePolicyFeature::kMagnetometer);
+ }
+ if (RuntimeEnabledFeatures::WebUSBEnabled()) {
+ default_feature_name_map.Set("usb", mojom::FeaturePolicyFeature::kUsb);
+ }
}
return default_feature_name_map;
}
diff --git a/chromium/third_party/blink/renderer/platform/feature_policy/feature_policy.h b/chromium/third_party/blink/renderer/platform/feature_policy/feature_policy.h
index 0176ce83cbe..05c3737a1d3 100644
--- a/chromium/third_party/blink/renderer/platform/feature_policy/feature_policy.h
+++ b/chromium/third_party/blink/renderer/platform/feature_policy/feature_policy.h
@@ -24,7 +24,7 @@ namespace blink {
typedef HashMap<String, mojom::FeaturePolicyFeature> FeatureNameMap;
PLATFORM_EXPORT const FeatureNameMap& GetDefaultFeatureNameMap();
-// Converts a header policy string into a vector of whitelists, one for each
+// Converts a header policy string into a vector of allowlists, one for each
// feature specified. Unrecognized features are filtered out. If |messages|
// is not null, then any message in the input will cause a warning message to be
// appended to it.
@@ -35,7 +35,7 @@ ParseFeaturePolicyHeader(const String& policy,
scoped_refptr<const SecurityOrigin>,
Vector<String>* messages);
-// Converts a container policy string into a vector of whitelists, given self
+// Converts a container policy string into a vector of allowlists, given self
// and src origins provided, one for each feature specified. Unrecognized
// features are filtered out. If |messages| is not null, then any message in the
// input will cause as warning message to be appended to it.
@@ -47,7 +47,7 @@ ParseFeaturePolicyAttribute(const String& policy,
scoped_refptr<const SecurityOrigin> src_origin,
Vector<String>* messages);
-// Converts a feature policy string into a vector of whitelists (see comments
+// Converts a feature policy string into a vector of allowlists (see comments
// above), with an explicit FeatureNameMap. This algorithm is called by both
// header policy parsing and container policy parsing. |self_origin| and
// |src_origin| are both nullable.
@@ -58,9 +58,37 @@ ParseFeaturePolicy(const String& policy,
Vector<String>* messages,
const FeatureNameMap& feature_names);
-// Verifies whether feature policy is enabled and |feature| is supported in
-// feature policy.
-PLATFORM_EXPORT bool IsSupportedInFeaturePolicy(mojom::FeaturePolicyFeature);
+// Returns true iff any declaration in the policy is for the given feature.
+PLATFORM_EXPORT bool IsFeatureDeclared(mojom::FeaturePolicyFeature,
+ const ParsedFeaturePolicy&);
+
+// Removes any declaration in the policy for the given feature. Returns true if
+// the policy was modified.
+PLATFORM_EXPORT bool RemoveFeatureIfPresent(mojom::FeaturePolicyFeature,
+ ParsedFeaturePolicy&);
+
+// If no declaration in the policy exists already for the feature, adds a
+// declaration which disallows the feature in all origins. Returns true if the
+// policy was modified.
+PLATFORM_EXPORT bool DisallowFeatureIfNotPresent(mojom::FeaturePolicyFeature,
+ ParsedFeaturePolicy&);
+
+// If no declaration in the policy exists already for the feature, adds a
+// declaration which allows the feature in all origins. Returns true if the
+// policy was modified.
+PLATFORM_EXPORT bool AllowFeatureEverywhereIfNotPresent(
+ mojom::FeaturePolicyFeature,
+ ParsedFeaturePolicy&);
+
+// Replaces any existing declarations in the policy for the given feature with
+// a declaration which disallows the feature in all origins.
+PLATFORM_EXPORT void DisallowFeature(mojom::FeaturePolicyFeature,
+ ParsedFeaturePolicy&);
+
+// Replaces any existing declarations in the policy for the given feature with
+// a declaration which allows the feature in all origins.
+PLATFORM_EXPORT void AllowFeatureEverywhere(mojom::FeaturePolicyFeature,
+ ParsedFeaturePolicy&);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/feature_policy/feature_policy_test.cc b/chromium/third_party/blink/renderer/platform/feature_policy/feature_policy_test.cc
index 8701132aaa3..9234b3355be 100644
--- a/chromium/third_party/blink/renderer/platform/feature_policy/feature_policy_test.cc
+++ b/chromium/third_party/blink/renderer/platform/feature_policy/feature_policy_test.cc
@@ -56,11 +56,11 @@ const char* const kInvalidPolicies[] = {
} // namespace
-class FeaturePolicyTest : public testing::Test {
+class FeaturePolicyParserTest : public testing::Test {
protected:
- FeaturePolicyTest() = default;
+ FeaturePolicyParserTest() = default;
- ~FeaturePolicyTest() override = default;
+ ~FeaturePolicyParserTest() override = default;
scoped_refptr<const SecurityOrigin> origin_a_ =
SecurityOrigin::CreateFromString(ORIGIN_A);
@@ -79,7 +79,7 @@ class FeaturePolicyTest : public testing::Test {
{"geolocation", blink::mojom::FeaturePolicyFeature::kGeolocation}};
};
-TEST_F(FeaturePolicyTest, ParseValidPolicy) {
+TEST_F(FeaturePolicyParserTest, ParseValidPolicy) {
Vector<String> messages;
for (const char* policy_string : kValidPolicies) {
messages.clear();
@@ -89,7 +89,7 @@ TEST_F(FeaturePolicyTest, ParseValidPolicy) {
}
}
-TEST_F(FeaturePolicyTest, ParseInvalidPolicy) {
+TEST_F(FeaturePolicyParserTest, ParseInvalidPolicy) {
Vector<String> messages;
for (const char* policy_string : kInvalidPolicies) {
messages.clear();
@@ -99,7 +99,7 @@ TEST_F(FeaturePolicyTest, ParseInvalidPolicy) {
}
}
-TEST_F(FeaturePolicyTest, PolicyParsedCorrectly) {
+TEST_F(FeaturePolicyParserTest, PolicyParsedCorrectly) {
Vector<String> messages;
// Empty policy.
@@ -212,10 +212,11 @@ TEST_F(FeaturePolicyTest, PolicyParsedCorrectly) {
parsed_policy[2].origins[0].IsSameOriginWith(expected_url_origin_a_));
}
-TEST_F(FeaturePolicyTest, PolicyParsedCorrectlyForOpaqueOrigins) {
+TEST_F(FeaturePolicyParserTest, PolicyParsedCorrectlyForOpaqueOrigins) {
Vector<String> messages;
- scoped_refptr<SecurityOrigin> opaque_origin = SecurityOrigin::CreateUnique();
+ scoped_refptr<SecurityOrigin> opaque_origin =
+ SecurityOrigin::CreateUniqueOpaque();
// Empty policy.
ParsedFeaturePolicy parsed_policy =
@@ -290,4 +291,212 @@ TEST_F(FeaturePolicyTest, PolicyParsedCorrectlyForOpaqueOrigins) {
parsed_policy[0].origins[0].IsSameOriginWith(expected_url_origin_b_));
}
+// Test policy mutation methods
+class FeaturePolicyMutationTest : public testing::Test {
+ protected:
+ FeaturePolicyMutationTest() = default;
+
+ ~FeaturePolicyMutationTest() override = default;
+
+ url::Origin url_origin_a_ = url::Origin::Create(GURL(ORIGIN_A));
+ url::Origin url_origin_b_ = url::Origin::Create(GURL(ORIGIN_B));
+ url::Origin url_origin_c_ = url::Origin::Create(GURL(ORIGIN_C));
+
+ // Returns true if the policy contains a declaration for the feature which
+ // allows it in all origins.
+ bool IsFeatureAllowedEverywhere(mojom::FeaturePolicyFeature feature,
+ const ParsedFeaturePolicy& policy) {
+ const auto& result = std::find_if(policy.begin(), policy.end(),
+ [feature](const auto& declaration) {
+ return declaration.feature == feature;
+ });
+ if (result == policy.end())
+ return false;
+
+ return result->feature == feature && result->matches_all_origins &&
+ result->matches_opaque_src && result->origins.empty();
+ }
+
+ // Returns true if the policy contains a declaration for the feature which
+ // disallows it in all origins.
+ bool IsFeatureDisallowedEverywhere(mojom::FeaturePolicyFeature feature,
+ const ParsedFeaturePolicy& policy) {
+ const auto& result = std::find_if(policy.begin(), policy.end(),
+ [feature](const auto& declaration) {
+ return declaration.feature == feature;
+ });
+ if (result == policy.end())
+ return false;
+
+ return result->feature == feature && !result->matches_all_origins &&
+ !result->matches_opaque_src && result->origins.empty();
+ }
+
+ ParsedFeaturePolicy test_policy = {{mojom::FeaturePolicyFeature::kFullscreen,
+ false,
+ false,
+ {url_origin_a_, url_origin_b_}},
+ {mojom::FeaturePolicyFeature::kGeolocation,
+ false,
+ false,
+ {url_origin_a_}}};
+ ParsedFeaturePolicy empty_policy = {};
+};
+TEST_F(FeaturePolicyMutationTest, TestIsFeatureDeclared) {
+ EXPECT_TRUE(
+ IsFeatureDeclared(mojom::FeaturePolicyFeature::kFullscreen, test_policy));
+ EXPECT_TRUE(IsFeatureDeclared(mojom::FeaturePolicyFeature::kGeolocation,
+ test_policy));
+ EXPECT_FALSE(
+ IsFeatureDeclared(mojom::FeaturePolicyFeature::kUsb, test_policy));
+ EXPECT_FALSE(
+ IsFeatureDeclared(mojom::FeaturePolicyFeature::kNotFound, test_policy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestIsFeatureDeclaredWithEmptyPolicy) {
+ EXPECT_FALSE(IsFeatureDeclared(mojom::FeaturePolicyFeature::kFullscreen,
+ empty_policy));
+ EXPECT_FALSE(
+ IsFeatureDeclared(mojom::FeaturePolicyFeature::kNotFound, empty_policy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestRemoveAbsentFeature) {
+ ASSERT_EQ(2UL, test_policy.size());
+ EXPECT_FALSE(
+ IsFeatureDeclared(mojom::FeaturePolicyFeature::kPayment, test_policy));
+ EXPECT_FALSE(RemoveFeatureIfPresent(mojom::FeaturePolicyFeature::kPayment,
+ test_policy));
+ ASSERT_EQ(2UL, test_policy.size());
+ EXPECT_FALSE(
+ IsFeatureDeclared(mojom::FeaturePolicyFeature::kPayment, test_policy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestRemoveFromEmptyPolicy) {
+ ASSERT_EQ(0UL, empty_policy.size());
+ EXPECT_FALSE(RemoveFeatureIfPresent(mojom::FeaturePolicyFeature::kPayment,
+ test_policy));
+ ASSERT_EQ(0UL, empty_policy.size());
+}
+
+TEST_F(FeaturePolicyMutationTest, TestRemoveFeatureIfPresent) {
+ ASSERT_EQ(2UL, test_policy.size());
+ EXPECT_TRUE(
+ IsFeatureDeclared(mojom::FeaturePolicyFeature::kFullscreen, test_policy));
+ EXPECT_TRUE(RemoveFeatureIfPresent(mojom::FeaturePolicyFeature::kFullscreen,
+ test_policy));
+ EXPECT_EQ(1UL, test_policy.size());
+ EXPECT_FALSE(
+ IsFeatureDeclared(mojom::FeaturePolicyFeature::kFullscreen, test_policy));
+
+ // Attempt to remove the feature again
+ EXPECT_FALSE(RemoveFeatureIfPresent(mojom::FeaturePolicyFeature::kFullscreen,
+ test_policy));
+ EXPECT_EQ(1UL, test_policy.size());
+ EXPECT_FALSE(
+ IsFeatureDeclared(mojom::FeaturePolicyFeature::kFullscreen, test_policy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestRemoveFeatureIfPresentOnSecondFeature) {
+ ASSERT_EQ(2UL, test_policy.size());
+ EXPECT_TRUE(IsFeatureDeclared(mojom::FeaturePolicyFeature::kGeolocation,
+ test_policy));
+ EXPECT_TRUE(RemoveFeatureIfPresent(mojom::FeaturePolicyFeature::kGeolocation,
+ test_policy));
+ ASSERT_EQ(1UL, test_policy.size());
+ EXPECT_FALSE(IsFeatureDeclared(mojom::FeaturePolicyFeature::kGeolocation,
+ test_policy));
+
+ // Attempt to remove the feature again
+ EXPECT_FALSE(RemoveFeatureIfPresent(mojom::FeaturePolicyFeature::kGeolocation,
+ test_policy));
+ EXPECT_EQ(1UL, test_policy.size());
+ EXPECT_FALSE(IsFeatureDeclared(mojom::FeaturePolicyFeature::kGeolocation,
+ test_policy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestRemoveAllFeatures) {
+ ASSERT_EQ(2UL, test_policy.size());
+ EXPECT_TRUE(RemoveFeatureIfPresent(mojom::FeaturePolicyFeature::kFullscreen,
+ test_policy));
+ EXPECT_TRUE(RemoveFeatureIfPresent(mojom::FeaturePolicyFeature::kGeolocation,
+ test_policy));
+ EXPECT_EQ(0UL, test_policy.size());
+ EXPECT_FALSE(
+ IsFeatureDeclared(mojom::FeaturePolicyFeature::kFullscreen, test_policy));
+ EXPECT_FALSE(IsFeatureDeclared(mojom::FeaturePolicyFeature::kGeolocation,
+ test_policy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestDisallowIfNotPresent) {
+ ParsedFeaturePolicy copy = test_policy;
+ // Try to disallow a feature which already exists
+ EXPECT_FALSE(DisallowFeatureIfNotPresent(
+ mojom::FeaturePolicyFeature::kFullscreen, copy));
+ ASSERT_EQ(copy, test_policy);
+
+ // Disallow a new feature
+ EXPECT_TRUE(
+ DisallowFeatureIfNotPresent(mojom::FeaturePolicyFeature::kPayment, copy));
+ EXPECT_EQ(3UL, copy.size());
+ // Verify that the feature is, in fact, now disallowed everywhere
+ EXPECT_TRUE(IsFeatureDisallowedEverywhere(
+ mojom::FeaturePolicyFeature::kPayment, copy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestAllowEverywhereIfNotPresent) {
+ ParsedFeaturePolicy copy = test_policy;
+ // Try to allow a feature which already exists
+ EXPECT_FALSE(AllowFeatureEverywhereIfNotPresent(
+ mojom::FeaturePolicyFeature::kFullscreen, copy));
+ ASSERT_EQ(copy, test_policy);
+
+ // Allow a new feature
+ EXPECT_TRUE(AllowFeatureEverywhereIfNotPresent(
+ mojom::FeaturePolicyFeature::kPayment, copy));
+ EXPECT_EQ(3UL, copy.size());
+ // Verify that the feature is, in fact, allowed everywhere
+ EXPECT_TRUE(
+ IsFeatureAllowedEverywhere(mojom::FeaturePolicyFeature::kPayment, copy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestDisallowUnconditionally) {
+ // Try to disallow a feature which already exists
+ DisallowFeature(mojom::FeaturePolicyFeature::kFullscreen, test_policy);
+ // Should not have changed the number of declarations
+ EXPECT_EQ(2UL, test_policy.size());
+ // Verify that the feature is, in fact, now disallowed everywhere
+ EXPECT_TRUE(IsFeatureDisallowedEverywhere(
+ mojom::FeaturePolicyFeature::kFullscreen, test_policy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestDisallowNewFeatureUnconditionally) {
+ // Try to disallow a feature which does not yet exist
+ DisallowFeature(mojom::FeaturePolicyFeature::kPayment, test_policy);
+ // Should have added a new declaration
+ EXPECT_EQ(3UL, test_policy.size());
+ // Verify that the feature is, in fact, now disallowed everywhere
+ EXPECT_TRUE(IsFeatureDisallowedEverywhere(
+ mojom::FeaturePolicyFeature::kPayment, test_policy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestAllowUnconditionally) {
+ // Try to allow a feature which already exists
+ AllowFeatureEverywhere(mojom::FeaturePolicyFeature::kFullscreen, test_policy);
+ // Should not have changed the number of declarations
+ EXPECT_EQ(2UL, test_policy.size());
+ // Verify that the feature is, in fact, now allowed everywhere
+ EXPECT_TRUE(IsFeatureAllowedEverywhere(
+ mojom::FeaturePolicyFeature::kFullscreen, test_policy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestAllowNewFeatureUnconditionally) {
+ // Try to allow a feature which does not yet exist
+ AllowFeatureEverywhere(mojom::FeaturePolicyFeature::kPayment, test_policy);
+ // Should have added a new declaration
+ EXPECT_EQ(3UL, test_policy.size());
+ // Verify that the feature is, in fact, now allowed everywhere
+ EXPECT_TRUE(IsFeatureAllowedEverywhere(mojom::FeaturePolicyFeature::kPayment,
+ test_policy));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/DEPS b/chromium/third_party/blink/renderer/platform/fonts/DEPS
index baf61469c1b..98ddf831ee0 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/DEPS
+++ b/chromium/third_party/blink/renderer/platform/fonts/DEPS
@@ -14,7 +14,6 @@ include_rules = [
"+third_party/blink/renderer/platform/histogram.h",
"+third_party/blink/renderer/platform/instrumentation",
"+third_party/blink/renderer/platform/language.h",
- "+third_party/blink/renderer/platform/layout_locale.h",
"+third_party/blink/renderer/platform/layout_test_support.h",
"+third_party/blink/renderer/platform/layout_unit.h",
"+third_party/blink/renderer/platform/mac/version_util_mac.h",
diff --git a/chromium/third_party/blink/renderer/platform/fonts/README.md b/chromium/third_party/blink/renderer/platform/fonts/README.md
index 7891fbad18a..c926090d963 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/README.md
+++ b/chromium/third_party/blink/renderer/platform/fonts/README.md
@@ -227,8 +227,8 @@ shaping.
The text shaping implementation is
in
-[shaping/harf_buzz_shaper.h](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.h) and
-[shaping/harf_buzz_shaper.cc](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.cc)
+[shaping/harfbuzz_shaper.h](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h) and
+[shaping/harfbuzz_shaper.cc](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc)
Shaping text runs is split into several
stages: [Run segmentation](#Run-Segmentation), shaping the initial segment
diff --git a/chromium/third_party/blink/renderer/platform/fonts/accept_languages_resolver.cc b/chromium/third_party/blink/renderer/platform/fonts/accept_languages_resolver.cc
deleted file mode 100644
index 3939b0cfd25..00000000000
--- a/chromium/third_party/blink/renderer/platform/fonts/accept_languages_resolver.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/fonts/accept_languages_resolver.h"
-
-#include "third_party/blink/renderer/platform/fonts/font_global_context.h"
-#include "third_party/blink/renderer/platform/layout_locale.h"
-
-namespace blink {
-
-void AcceptLanguagesResolver::AcceptLanguagesChanged(
- const String& accept_languages) {
- String& current_value = FontGlobalContext::CurrentAcceptLanguages();
- if (current_value == accept_languages)
- return;
-
- current_value = accept_languages;
- FontGlobalContext::InvalidateLocaleForHan();
-}
-
-const LayoutLocale* AcceptLanguagesResolver::LocaleForHan() {
- return LocaleForHanFromAcceptLanguages(
- FontGlobalContext::CurrentAcceptLanguages());
-}
-
-const LayoutLocale* AcceptLanguagesResolver::LocaleForHanFromAcceptLanguages(
- const String& accept_languages) {
- // Use the first acceptLanguages that can disambiguate.
- Vector<String> languages;
- accept_languages.Split(',', languages);
- for (String token : languages) {
- token = token.StripWhiteSpace();
- const LayoutLocale* locale = LayoutLocale::Get(AtomicString(token));
- if (locale->HasScriptForHan())
- return locale;
- }
-
- return nullptr;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/accept_languages_resolver.h b/chromium/third_party/blink/renderer/platform/fonts/accept_languages_resolver.h
deleted file mode 100644
index f664ecbf87e..00000000000
--- a/chromium/third_party/blink/renderer/platform/fonts/accept_languages_resolver.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_ACCEPT_LANGUAGES_RESOLVER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_ACCEPT_LANGUAGES_RESOLVER_H_
-
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-#include <unicode/uscript.h>
-
-namespace blink {
-
-class LayoutLocale;
-
-class PLATFORM_EXPORT AcceptLanguagesResolver {
- public:
- static void AcceptLanguagesChanged(const String&);
-
- static const LayoutLocale* LocaleForHan();
- static const LayoutLocale* LocaleForHanFromAcceptLanguages(const String&);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_ACCEPT_LANGUAGES_RESOLVER_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/accept_languages_resolver_test.cc b/chromium/third_party/blink/renderer/platform/fonts/accept_languages_resolver_test.cc
deleted file mode 100644
index ef0be29cc5e..00000000000
--- a/chromium/third_party/blink/renderer/platform/fonts/accept_languages_resolver_test.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/fonts/accept_languages_resolver.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/layout_locale.h"
-
-namespace blink {
-
-TEST(AcceptLanguagesResolverTest, AcceptLanguagesChanged) {
- struct {
- const char* accept_languages;
- UScriptCode script;
- const char* locale;
- } tests[] = {
- // Non-Han script cases.
- {nullptr, USCRIPT_COMMON, nullptr},
- {"", USCRIPT_COMMON, nullptr},
- {"en-US", USCRIPT_COMMON, nullptr},
- {",en-US", USCRIPT_COMMON, nullptr},
-
- // Single value cases.
- {"ja-JP", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp"},
- {"ko-KR", USCRIPT_HANGUL, "ko-kr"},
- {"zh-CN", USCRIPT_SIMPLIFIED_HAN, "zh-Hans"},
- {"zh-HK", USCRIPT_TRADITIONAL_HAN, "zh-Hant"},
- {"zh-TW", USCRIPT_TRADITIONAL_HAN, "zh-Hant"},
-
- // Language only.
- {"ja", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp"},
- {"ko", USCRIPT_HANGUL, "ko-kr"},
- {"zh", USCRIPT_SIMPLIFIED_HAN, "zh-Hans"},
-
- // Unusual combinations.
- {"en-JP", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp"},
-
- // Han scripts not in the first item.
- {"en-US,ja-JP", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp"},
- {"en-US,en-JP", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp"},
-
- // Multiple Han scripts. The first one wins.
- {"ja-JP,zh-CN", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp"},
- {"zh-TW,ja-JP", USCRIPT_TRADITIONAL_HAN, "zh-Hant"},
- };
-
- for (const auto& test : tests) {
- const LayoutLocale* locale =
- AcceptLanguagesResolver::LocaleForHanFromAcceptLanguages(
- test.accept_languages);
-
- if (test.script == USCRIPT_COMMON) {
- EXPECT_EQ(nullptr, locale) << test.accept_languages;
- continue;
- }
-
- ASSERT_NE(nullptr, locale) << test.accept_languages;
- EXPECT_EQ(test.script, locale->GetScriptForHan()) << test.accept_languages;
- EXPECT_STRCASEEQ(test.locale, locale->LocaleForHanForSkFontMgr())
- << test.accept_languages;
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android.cc b/chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android.cc
index 57966613684..6c8efc827f5 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android.cc
@@ -35,8 +35,8 @@
#include "third_party/blink/renderer/platform/fonts/font_face_creation_params.h"
#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
#include "third_party/blink/renderer/platform/language.h"
+#include "third_party/skia/include/core/SkFontMgr.h"
#include "third_party/skia/include/core/SkTypeface.h"
-#include "third_party/skia/include/ports/SkFontMgr.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android_test.cc b/chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android_test.cc
index 0148a6771d7..efe8ddc64ef 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/android/font_cache_android_test.cc
@@ -4,12 +4,19 @@
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
+#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
namespace blink {
-TEST(FontCacheAndroid, fallbackFontForCharacter) {
+// TODO(crbug.com/850794): Reenable this.
+#if defined(OS_ANDROID)
+#define MAYBE_fallbackFontForCharacter DISABLED_fallbackFontForCharacter
+#else
+#define MAYBE_fallbackFontForCharacter fallbackFontForCharacter
+#endif
+TEST(FontCacheAndroid, MAYBE_fallbackFontForCharacter) {
// A Latin character in the common locale system font, but not in the
// Chinese locale-preferred font.
const UChar32 kTestChar = 228;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/cursor_position_test.cc b/chromium/third_party/blink/renderer/platform/fonts/cursor_position_test.cc
new file mode 100644
index 00000000000..2ffd9a83713
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/cursor_position_test.cc
@@ -0,0 +1,457 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/file_path_conversion.h"
+#include "third_party/blink/public/platform/web_string.h"
+#include "third_party/blink/renderer/platform/fonts/font.h"
+#include "third_party/blink/renderer/platform/fonts/font_description.h"
+#include "third_party/blink/renderer/platform/testing/font_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+
+using blink::test::CreateTestFont;
+
+namespace blink {
+
+class CursorPositionTest : public ::testing::Test {
+ public:
+ enum FontName {
+ ahem,
+ amiri,
+ megalopolis,
+ roboto,
+ };
+
+ float GetWidth(FontName font_name,
+ const String& text,
+ bool ltr,
+ int start = 0,
+ int end = -1) {
+ FontDescription::VariantLigatures ligatures(
+ FontDescription::kEnabledLigaturesState);
+ Font font = CreateTestFont("TestFont",
+ test::PlatformTestDataPath(font_path[font_name]),
+ 100, &ligatures);
+ TextRun text_run(
+ text, /* xpos */ 0, /* expansion */ 0,
+ TextRun::kAllowTrailingExpansion | TextRun::kForbidLeadingExpansion,
+ ltr ? TextDirection::kLtr : TextDirection::kRtl, false);
+
+ if (end == -1)
+ end = text_run.length();
+ DCHECK_GE(start, 0);
+ DCHECK_LE(start, static_cast<int>(text_run.length()));
+ DCHECK_GE(end, -1);
+ DCHECK_LE(end, static_cast<int>(text_run.length()));
+ FloatRect rect =
+ font.SelectionRectForText(text_run, FloatPoint(), 12, start, end);
+ return rect.Width();
+ }
+
+ int GetCharacter(FontName font_name,
+ const String& text,
+ bool ltr,
+ float position,
+ bool partial) {
+ FontDescription::VariantLigatures ligatures(
+ FontDescription::kEnabledLigaturesState);
+ Font font = CreateTestFont("TestFont",
+ test::PlatformTestDataPath(font_path[font_name]),
+ 100, &ligatures);
+ TextRun text_run(
+ text, /* xpos */ 0, /* expansion */ 0,
+ TextRun::kAllowTrailingExpansion | TextRun::kForbidLeadingExpansion,
+ ltr ? TextDirection::kLtr : TextDirection::kRtl, false);
+
+ return font.OffsetForPosition(
+ text_run, position, partial ? IncludePartialGlyphs : OnlyFullGlyphs,
+ BreakGlyphs);
+ }
+
+ private:
+ std::map<FontName, String> font_path = {
+ {ahem, "Ahem.woff"},
+ {amiri, "third_party/Amiri/amiri_arabic.woff2"},
+ {megalopolis, "third_party/MEgalopolis/MEgalopolisExtra.woff"},
+ {roboto, "third_party/Roboto/roboto-regular.woff2"},
+ };
+};
+
+TEST_F(CursorPositionTest, LTRMouse) {
+ EXPECT_EQ(GetCharacter(ahem, "X", true, 0, false), 0);
+ EXPECT_EQ(GetCharacter(ahem, "X", true, 0, true), 0);
+ EXPECT_EQ(GetCharacter(ahem, "X", true, 10, false), 0);
+ EXPECT_EQ(GetCharacter(ahem, "X", true, 10, true), 0);
+ EXPECT_EQ(GetCharacter(ahem, "X", true, 60, false), 0);
+ EXPECT_EQ(GetCharacter(ahem, "X", true, 60, true), 1);
+ EXPECT_EQ(GetCharacter(ahem, "X", true, 100, false), 1);
+ EXPECT_EQ(GetCharacter(ahem, "X", true, 100, true), 1);
+
+ EXPECT_EQ(GetCharacter(ahem, "XXX", true, 10, false), 0);
+ EXPECT_EQ(GetCharacter(ahem, "XXX", true, 10, true), 0);
+ EXPECT_EQ(GetCharacter(ahem, "XXX", true, 60, false), 0);
+ EXPECT_EQ(GetCharacter(ahem, "XXX", true, 60, true), 1);
+ EXPECT_EQ(GetCharacter(ahem, "XXX", true, 100, true), 1);
+ EXPECT_EQ(GetCharacter(ahem, "XXX", true, 100, false), 1);
+ EXPECT_EQ(GetCharacter(ahem, "XXX", true, 125, true), 1);
+ EXPECT_EQ(GetCharacter(ahem, "XXX", true, 125, true), 1);
+ EXPECT_EQ(GetCharacter(ahem, "XXX", true, 151, false), 1);
+ EXPECT_EQ(GetCharacter(ahem, "XXX", true, 151, true), 2);
+ EXPECT_EQ(GetCharacter(ahem, "XXX", true, 175, false), 1);
+ EXPECT_EQ(GetCharacter(ahem, "XXX", true, 175, true), 2);
+}
+
+TEST_F(CursorPositionTest, LTRLigatureMouse) {
+ const float kFUWidth = GetWidth(megalopolis, "FU", true);
+ const float kRAWidth = GetWidth(megalopolis, "RA", true);
+
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth / 4 - 1, false),
+ 0);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth / 4 - 1, true), 0);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth / 4 + 1, false),
+ 0);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth / 4 + 1, true), 1);
+
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth / 2 - 1, false),
+ 0);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth / 2 - 1, true), 1);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth / 2 + 1, false),
+ 1);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth / 2 + 1, true), 1);
+
+ EXPECT_EQ(
+ GetCharacter(megalopolis, "FURA", true, kFUWidth * 3 / 4 - 1, false), 1);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth * 3 / 4 - 1, true),
+ 1);
+ EXPECT_EQ(
+ GetCharacter(megalopolis, "FURA", true, kFUWidth * 3 / 4 + 1, false), 1);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth * 3 / 4 + 1, true),
+ 2);
+
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth - 1, false), 1);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth - 1, true), 2);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + 1, false), 2);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + 1, true), 2);
+
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth / 4 - 1,
+ false),
+ 2);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth / 4 - 1,
+ true),
+ 2);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth / 4 + 1,
+ false),
+ 2);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth / 4 + 1,
+ true),
+ 3);
+
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth / 2 - 1,
+ false),
+ 2);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth / 2 - 1,
+ true),
+ 3);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth / 2 + 1,
+ false),
+ 3);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth / 2 + 1,
+ true),
+ 3);
+
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true,
+ kFUWidth + kRAWidth * 3 / 4 - 1, false),
+ 3);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true,
+ kFUWidth + kRAWidth * 3 / 4 - 1, true),
+ 3);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true,
+ kFUWidth + kRAWidth * 3 / 4 + 1, false),
+ 3);
+ EXPECT_EQ(GetCharacter(megalopolis, "FURA", true,
+ kFUWidth + kRAWidth * 3 / 4 + 1, true),
+ 4);
+
+ EXPECT_EQ(
+ GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth - 1, false),
+ 3);
+ EXPECT_EQ(
+ GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth - 1, true),
+ 4);
+ EXPECT_EQ(
+ GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth + 1, false),
+ 4);
+ EXPECT_EQ(
+ GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth + 1, true),
+ 4);
+}
+
+TEST_F(CursorPositionTest, RTLMouse) {
+ // The widths below are from the final shaped version, not from the single
+ // characters. They were extracted with "hb-shape --font-size=100"
+
+ EXPECT_EQ(GetCharacter(ahem, "X", false, 0, false), 1);
+ EXPECT_EQ(GetCharacter(ahem, "X", false, 0, true), 1);
+ EXPECT_EQ(GetCharacter(ahem, "X", false, 10, false), 0);
+ EXPECT_EQ(GetCharacter(ahem, "X", false, 10, true), 1);
+ EXPECT_EQ(GetCharacter(ahem, "X", false, 49, false), 0);
+ EXPECT_EQ(GetCharacter(ahem, "X", false, 49, true), 1);
+ EXPECT_EQ(GetCharacter(ahem, "X", false, 51, false), 0);
+ EXPECT_EQ(GetCharacter(ahem, "X", false, 51, true), 0);
+ EXPECT_EQ(GetCharacter(ahem, "X", false, 60, false), 0);
+ EXPECT_EQ(GetCharacter(ahem, "X", false, 60, true), 0);
+ EXPECT_EQ(GetCharacter(ahem, "X", false, 100, false), 0);
+ EXPECT_EQ(GetCharacter(ahem, "X", false, 100, true), 0);
+
+ const float kAloneTaWidth = GetWidth(amiri, u"ت", false);
+ EXPECT_EQ(GetCharacter(amiri, u"ت", false, 0, false), 1);
+ EXPECT_EQ(GetCharacter(amiri, u"ت", false, 0, true), 1);
+ EXPECT_EQ(GetCharacter(amiri, u"ت", false, kAloneTaWidth / 4, false), 0);
+ EXPECT_EQ(GetCharacter(amiri, u"ت", false, kAloneTaWidth / 4, true), 1);
+ EXPECT_EQ(GetCharacter(amiri, u"ت", false, kAloneTaWidth * 2 / 3, false), 0);
+ EXPECT_EQ(GetCharacter(amiri, u"ت", false, kAloneTaWidth * 2 / 3, true), 0);
+ EXPECT_EQ(GetCharacter(amiri, u"ت", false, 2 * kAloneTaWidth, false), 0);
+ EXPECT_EQ(GetCharacter(amiri, u"ت", false, 2 * kAloneTaWidth, true), 0);
+
+ const float kAboveTaWidth = 10;
+ const float kAboveKhaWidth = 55;
+ EXPECT_EQ(GetCharacter(amiri, u"تخ", false, 0, false), 2);
+ EXPECT_EQ(GetCharacter(amiri, u"تخ", false, 0, true), 2);
+ EXPECT_EQ(GetCharacter(amiri, u"تخ", false, kAboveTaWidth / 4, false), 1);
+ EXPECT_EQ(GetCharacter(amiri, u"تخ", false, kAboveTaWidth / 4, true), 2);
+ EXPECT_EQ(GetCharacter(amiri, u"تخ", false, kAboveTaWidth * 2 / 3, false), 1);
+ EXPECT_EQ(GetCharacter(amiri, u"تخ", false, kAboveTaWidth * 2 / 3, true), 1);
+ EXPECT_EQ(GetCharacter(amiri, u"تخ", false, kAboveTaWidth + 1, false), 0);
+ EXPECT_EQ(GetCharacter(amiri, u"تخ", false, kAboveTaWidth + 1, true), 1);
+ EXPECT_EQ(GetCharacter(amiri, u"تخ", false,
+ kAboveTaWidth + kAboveKhaWidth / 4, false),
+ 0);
+ EXPECT_EQ(GetCharacter(amiri, u"تخ", false,
+ kAboveTaWidth + kAboveKhaWidth / 4, true),
+ 1);
+ EXPECT_EQ(GetCharacter(amiri, u"تخ", false,
+ kAboveTaWidth + kAboveKhaWidth * 2 / 3, false),
+ 0);
+ EXPECT_EQ(GetCharacter(amiri, u"تخ", false,
+ kAboveTaWidth + kAboveKhaWidth * 2 / 3, true),
+ 0);
+ EXPECT_EQ(GetCharacter(amiri, u"تخ", false,
+ kAboveTaWidth + kAboveKhaWidth + 1, false),
+ 0);
+ EXPECT_EQ(GetCharacter(amiri, u"تخ", false,
+ kAboveTaWidth + kAboveKhaWidth + 1, true),
+ 0);
+ EXPECT_EQ(GetCharacter(amiri, u"تخ", false,
+ 2 * (kAboveTaWidth + kAboveKhaWidth), false),
+ 0);
+ EXPECT_EQ(GetCharacter(amiri, u"تخ", false,
+ 2 * (kAboveTaWidth + kAboveKhaWidth), true),
+ 0);
+}
+
+TEST_F(CursorPositionTest, RTLLigatureMouse) {
+ const float kFUWidth = GetWidth(megalopolis, "FU", true);
+ const float kRAWidth = GetWidth(megalopolis, "RA", true);
+
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth / 4 - 1, false),
+ 3);
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth / 4 - 1, true),
+ 4);
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth / 4 + 1, false),
+ 3);
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth / 4 + 1, true),
+ 3);
+
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth / 2 - 1, false),
+ 3);
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth / 2 - 1, true),
+ 3);
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth / 2 + 1, false),
+ 2);
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth / 2 + 1, true),
+ 3);
+
+ EXPECT_EQ(
+ GetCharacter(megalopolis, "ARUF", false, kFUWidth * 3 / 4 - 1, false), 2);
+ EXPECT_EQ(
+ GetCharacter(megalopolis, "ARUF", false, kFUWidth * 3 / 4 - 1, true), 3);
+ EXPECT_EQ(
+ GetCharacter(megalopolis, "ARUF", false, kFUWidth * 3 / 4 + 1, false), 2);
+ EXPECT_EQ(
+ GetCharacter(megalopolis, "ARUF", false, kFUWidth * 3 / 4 + 1, true), 2);
+
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth - 1, false), 2);
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth - 1, true), 2);
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth + 1, false), 1);
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth + 1, true), 2);
+
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
+ kFUWidth + kRAWidth / 4 - 1, false),
+ 1);
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
+ kFUWidth + kRAWidth / 4 - 1, true),
+ 2);
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
+ kFUWidth + kRAWidth / 4 + 1, false),
+ 1);
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
+ kFUWidth + kRAWidth / 4 + 1, true),
+ 1);
+
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
+ kFUWidth + kRAWidth / 2 - 1, false),
+ 1);
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
+ kFUWidth + kRAWidth / 2 - 1, true),
+ 1);
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
+ kFUWidth + kRAWidth / 2 + 1, false),
+ 0);
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
+ kFUWidth + kRAWidth / 2 + 1, true),
+ 1);
+
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
+ kFUWidth + kRAWidth * 3 / 4 - 1, false),
+ 0);
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
+ kFUWidth + kRAWidth * 3 / 4 - 1, true),
+ 1);
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
+ kFUWidth + kRAWidth * 3 / 4 + 1, false),
+ 0);
+ EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
+ kFUWidth + kRAWidth * 3 / 4 + 1, true),
+ 0);
+
+ EXPECT_EQ(
+ GetCharacter(megalopolis, "ARUF", false, kFUWidth + kRAWidth - 1, false),
+ 0);
+ EXPECT_EQ(
+ GetCharacter(megalopolis, "ARUF", false, kFUWidth + kRAWidth - 1, true),
+ 0);
+ EXPECT_EQ(
+ GetCharacter(megalopolis, "ARUF", false, kFUWidth + kRAWidth + 1, false),
+ 0);
+ EXPECT_EQ(
+ GetCharacter(megalopolis, "ARUF", false, kFUWidth + kRAWidth + 1, true),
+ 0);
+}
+
+TEST_F(CursorPositionTest, LTRText) {
+ EXPECT_EQ(GetWidth(ahem, "X", true, 0, 1), 100);
+
+ EXPECT_EQ(GetWidth(ahem, "XXX", true, 0, 1), 100);
+ EXPECT_EQ(GetWidth(ahem, "XXX", true, 0, 2), 200);
+ EXPECT_EQ(GetWidth(ahem, "XXX", true, 0, 3), 300);
+ EXPECT_EQ(GetWidth(ahem, "XXX", true, 1, 2), 100);
+ EXPECT_EQ(GetWidth(ahem, "XXX", true, 1, 3), 200);
+ EXPECT_EQ(GetWidth(ahem, "XXX", true, 2, 3), 100);
+}
+
+TEST_F(CursorPositionTest, LTRLigature) {
+ const float kFUWidth = GetWidth(megalopolis, "FU", true);
+ const float kRAWidth = GetWidth(megalopolis, "RA", true);
+
+ EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 0, 1), kFUWidth / 2, 1.0);
+ EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 0, 2), kFUWidth, 1.0);
+ EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 0, 3),
+ kFUWidth + kRAWidth / 2, 1.0);
+ EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 0, 4), kFUWidth + kRAWidth,
+ 1.0);
+
+ EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 1, 2), kFUWidth / 2, 1.0);
+ EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 1, 3),
+ kFUWidth / 2 + kRAWidth / 2, 1.0);
+ EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 1, 4),
+ kFUWidth / 2 + kRAWidth, 1.0);
+
+ EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 2, 3), kRAWidth / 2, 1.0);
+ EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 2, 4), kRAWidth, 1.0);
+
+ EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 3, 4), kRAWidth / 2, 1.0);
+
+ const float kFFIWidth = GetWidth(roboto, "ffi", true);
+ const float kFFWidth = GetWidth(roboto, "ff", true);
+ const float kIWidth = GetWidth(roboto, u"î", true);
+
+ EXPECT_NEAR(GetWidth(roboto, "ffi", true, 0, 1), kFFIWidth / 3.0, 1.0);
+ EXPECT_NEAR(GetWidth(roboto, "ffi", true, 0, 2), kFFIWidth * 2.0 / 3.0, 1.0);
+ EXPECT_NEAR(GetWidth(roboto, "ffi", true, 0, 3), kFFIWidth, 1.0);
+ EXPECT_NEAR(GetWidth(roboto, "ffi", true, 1, 2), kFFIWidth / 3.0, 1.0);
+ EXPECT_NEAR(GetWidth(roboto, "ffi", true, 1, 3), kFFIWidth * 2.0 / 3.0, 1.0);
+ EXPECT_NEAR(GetWidth(roboto, "ffi", true, 2, 3), kFFIWidth / 3.0, 1.0);
+
+ EXPECT_NEAR(GetWidth(roboto, u"ffî", true, 0, 1), kFFWidth / 2.0, 1.0);
+ EXPECT_NEAR(GetWidth(roboto, u"ffî", true, 0, 2), kFFWidth, 1.0);
+ EXPECT_NEAR(GetWidth(roboto, u"ffî", true, 0, 3), kFFWidth + kIWidth, 1.0);
+ EXPECT_NEAR(GetWidth(roboto, u"ffî", true, 1, 2), kFFWidth / 2.0, 1.0);
+ EXPECT_NEAR(GetWidth(roboto, u"ffî", true, 1, 3), kFFWidth / 2.0 + kIWidth,
+ 1.0);
+ EXPECT_NEAR(GetWidth(roboto, u"ffî", true, 2, 3), kIWidth, 1.0);
+}
+
+TEST_F(CursorPositionTest, RTLText) {
+ // The widths below are from the final shaped version, not from the single
+ // characters. They were extracted with "hb-shape --font-size=100"
+
+ EXPECT_EQ(GetWidth(amiri, u"ت", false, 0, 1), 93);
+
+ const float kAboveKhaWidth = 55;
+ const float kAboveTaWidth = 10;
+ EXPECT_NEAR(GetWidth(amiri, u"تخ", false, 0, 1), kAboveKhaWidth, 1.0);
+ EXPECT_NEAR(GetWidth(amiri, u"تخ", false, 0, 2),
+ kAboveKhaWidth + kAboveTaWidth, 1.0);
+ EXPECT_NEAR(GetWidth(amiri, u"تخ", false, 1, 2), kAboveTaWidth, 1.0);
+
+ const float kTaWidth = 75;
+ const float kKhaWidth = 7;
+ const float kLamWidth = 56;
+ const float kAlifWidth = 22;
+ EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 0, 1), kAlifWidth, 1.0);
+ EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 0, 2), kAlifWidth + kLamWidth,
+ 1.0);
+ EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 0, 3),
+ kAlifWidth + kLamWidth + kKhaWidth, 1.0);
+ EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 0, 4),
+ kAlifWidth + kLamWidth + kKhaWidth + kTaWidth, 1.0);
+ EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 1, 2), kLamWidth, 1.0);
+ EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 1, 3), kLamWidth + kKhaWidth,
+ 1.0);
+ EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 1, 4),
+ kLamWidth + kKhaWidth + kTaWidth, 1.0);
+ EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 2, 3), kKhaWidth, 1.0);
+ EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 2, 4), kKhaWidth + kTaWidth, 1.0);
+ EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 3, 4), kTaWidth, 1.0);
+
+ const float kMeemWidth = GetWidth(amiri, u"م", false);
+ EXPECT_EQ(GetWidth(amiri, u"مَ", false, 0, 1), kMeemWidth);
+ EXPECT_EQ(GetWidth(amiri, u"مَ", false, 0, 2), kMeemWidth);
+ EXPECT_EQ(GetWidth(amiri, u"مَ", false, 1, 2), kMeemWidth);
+}
+
+TEST_F(CursorPositionTest, RTLLigature) {
+ const float kFUWidth = GetWidth(megalopolis, "FU", true);
+ const float kRAWidth = GetWidth(megalopolis, "RA", true);
+
+ EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 0, 1), kRAWidth / 2, 1.0);
+ EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 0, 2), kRAWidth, 1.0);
+ EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 0, 3),
+ kRAWidth + kFUWidth / 2, 1.0);
+ EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 0, 4), kRAWidth + kFUWidth,
+ 1.0);
+
+ EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 1, 2), kRAWidth / 2, 1.0);
+ EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 1, 3),
+ kRAWidth / 2 + kFUWidth / 2, 1.0);
+ EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 1, 4),
+ kRAWidth / 2 + kFUWidth, 1.0);
+
+ EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 2, 3), kFUWidth / 2, 1.0);
+ EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 2, 4), kFUWidth, 1.0);
+
+ EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 3, 4), kFUWidth / 2, 1.0);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font.cc b/chromium/third_party/blink/renderer/platform/fonts/font.cc
index dad2347e3e7..140c9e34153 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font.cc
@@ -108,7 +108,7 @@ void Font::Update(FontSelector* font_selector) const {
namespace {
-void DrawBlobs(PaintCanvas* canvas,
+void DrawBlobs(cc::PaintCanvas* canvas,
const PaintFlags& flags,
const ShapeResultBloberizer::BlobBuffer& blobs,
const FloatPoint& point) {
@@ -129,7 +129,7 @@ void DrawBlobs(PaintCanvas* canvas,
} // anonymous ns
-void Font::DrawText(PaintCanvas* canvas,
+void Font::DrawText(cc::PaintCanvas* canvas,
const TextRunPaintInfo& run_info,
const FloatPoint& point,
float device_scale_factor,
@@ -147,7 +147,7 @@ void Font::DrawText(PaintCanvas* canvas,
DrawBlobs(canvas, flags, bloberizer.Blobs(), point);
}
-void Font::DrawText(PaintCanvas* canvas,
+void Font::DrawText(cc::PaintCanvas* canvas,
const NGTextFragmentPaintInfo& text_info,
const FloatPoint& point,
float device_scale_factor,
@@ -163,7 +163,7 @@ void Font::DrawText(PaintCanvas* canvas,
DrawBlobs(canvas, flags, bloberizer.Blobs(), point);
}
-bool Font::DrawBidiText(PaintCanvas* canvas,
+bool Font::DrawBidiText(cc::PaintCanvas* canvas,
const TextRunPaintInfo& run_info,
const FloatPoint& point,
CustomFontNotReadyAction custom_font_not_ready_action,
@@ -219,7 +219,7 @@ bool Font::DrawBidiText(PaintCanvas* canvas,
return true;
}
-void Font::DrawEmphasisMarks(PaintCanvas* canvas,
+void Font::DrawEmphasisMarks(cc::PaintCanvas* canvas,
const TextRunPaintInfo& run_info,
const AtomicString& mark,
const FloatPoint& point,
@@ -242,7 +242,7 @@ void Font::DrawEmphasisMarks(PaintCanvas* canvas,
DrawBlobs(canvas, flags, bloberizer.Blobs(), point);
}
-void Font::DrawEmphasisMarks(PaintCanvas* canvas,
+void Font::DrawEmphasisMarks(cc::PaintCanvas* canvas,
const NGTextFragmentPaintInfo& text_info,
const AtomicString& mark,
const FloatPoint& point,
@@ -380,19 +380,21 @@ FloatRect Font::SelectionRectForText(const TextRun& run,
FloatRect(point.X() + range.start, point.Y(), range.Width(), height));
}
-FloatRect Font::BoundingBox(const TextRun& run) const {
+FloatRect Font::BoundingBox(const TextRun& run, int from, int to) const {
+ to = (to == -1 ? run.length() : to);
FontCachePurgePreventer purge_preventer;
CachingWordShaper shaper(*this);
- CharacterRange range = shaper.GetCharacterRange(run, 0, run.length());
+ CharacterRange range = shaper.GetCharacterRange(run, from, to);
return FloatRect(range.start, -range.ascent, range.Width(), range.Height());
}
int Font::OffsetForPosition(const TextRun& run,
float x_float,
- bool include_partial_glyphs) const {
+ IncludePartialGlyphsOption partial_glyphs,
+ BreakGlyphsOption break_glyphs) const {
FontCachePurgePreventer purge_preventer;
CachingWordShaper shaper(*this);
- return shaper.OffsetForPosition(run, x_float, include_partial_glyphs);
+ return shaper.OffsetForPosition(run, x_float, partial_glyphs, break_glyphs);
}
ShapeCache* Font::GetShapeCache() const {
@@ -505,6 +507,18 @@ Vector<CharacterRange> Font::IndividualCharacterRanges(
return ranges;
}
+void Font::ExpandRangeToIncludePartialGlyphs(const TextRun& text_run,
+ int* from,
+ int* to) const {
+ TextRunPaintInfo run_info(text_run);
+ run_info.from = *from;
+ run_info.to = *to;
+ CachingWordShaper word_shaper(*this);
+ ShapeResultBuffer buffer;
+ word_shaper.FillResultBuffer(run_info, &buffer);
+ buffer.ExpandRangeToIncludePartialGlyphs(from, to);
+}
+
LayoutUnit Font::TabWidth(const TabSize& tab_size, LayoutUnit position) const {
const SimpleFontData* font_data = PrimaryFont();
if (!font_data)
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font.h b/chromium/third_party/blink/renderer/platform/fonts/font.h
index 225a28a2044..de3a27cbd69 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font.h
@@ -29,8 +29,6 @@
#include "third_party/blink/renderer/platform/fonts/font_fallback_list.h"
#include "third_party/blink/renderer/platform/fonts/font_fallback_priority.h"
#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_flags.h"
#include "third_party/blink/renderer/platform/layout_unit.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/text/tab_size.h"
@@ -44,6 +42,11 @@
// To avoid conflicts with the CreateWindow macro from the Windows SDK...
#undef DrawText
+namespace cc {
+class PaintCanvas;
+class PaintFlags;
+} // namespace cc
+
namespace blink {
struct CharacterRange;
@@ -81,34 +84,34 @@ class PLATFORM_EXPORT Font {
kDoNotPaintIfFontNotReady,
kUseFallbackIfFontNotReady
};
- void DrawText(PaintCanvas*,
+ void DrawText(cc::PaintCanvas*,
const TextRunPaintInfo&,
const FloatPoint&,
float device_scale_factor,
- const PaintFlags&) const;
- void DrawText(PaintCanvas*,
+ const cc::PaintFlags&) const;
+ void DrawText(cc::PaintCanvas*,
const NGTextFragmentPaintInfo&,
const FloatPoint&,
float device_scale_factor,
- const PaintFlags&) const;
- bool DrawBidiText(PaintCanvas*,
+ const cc::PaintFlags&) const;
+ bool DrawBidiText(cc::PaintCanvas*,
const TextRunPaintInfo&,
const FloatPoint&,
CustomFontNotReadyAction,
float device_scale_factor,
- const PaintFlags&) const;
- void DrawEmphasisMarks(PaintCanvas*,
+ const cc::PaintFlags&) const;
+ void DrawEmphasisMarks(cc::PaintCanvas*,
const TextRunPaintInfo&,
const AtomicString& mark,
const FloatPoint&,
float device_scale_factor,
- const PaintFlags&) const;
- void DrawEmphasisMarks(PaintCanvas*,
+ const cc::PaintFlags&) const;
+ void DrawEmphasisMarks(cc::PaintCanvas*,
const NGTextFragmentPaintInfo&,
const AtomicString& mark,
const FloatPoint&,
float device_scale_factor,
- const PaintFlags&) const;
+ const cc::PaintFlags&) const;
struct TextIntercept {
float begin_, end_;
@@ -119,16 +122,15 @@ class PLATFORM_EXPORT Font {
// a multiple of two, and is at most the number of glyphs * 2 in the TextRun
// part of TextRunPaintInfo. Specify bounds for the upper and lower extend of
// a line crossing through the text, parallel to the baseline.
- // TODO(drott): crbug.com/655154 Fix this for
- // upright in vertical.
+ // TODO(drott): crbug.com/655154 Fix this for upright in vertical.
void GetTextIntercepts(const TextRunPaintInfo&,
float device_scale_factor,
- const PaintFlags&,
+ const cc::PaintFlags&,
const std::tuple<float, float>& bounds,
Vector<TextIntercept>&) const;
void GetTextIntercepts(const NGTextFragmentPaintInfo&,
float device_scale_factor,
- const PaintFlags&,
+ const cc::PaintFlags&,
const std::tuple<float, float>& bounds,
Vector<TextIntercept>&) const;
@@ -141,18 +143,23 @@ class PLATFORM_EXPORT Font {
int OffsetForPosition(const TextRun&,
float position,
- bool include_partial_glyphs) const;
+ IncludePartialGlyphsOption,
+ BreakGlyphsOption) const;
FloatRect SelectionRectForText(const TextRun&,
const FloatPoint&,
int h,
int from = 0,
int to = -1) const;
- FloatRect BoundingBox(const TextRun&) const;
+ FloatRect BoundingBox(const TextRun&, int from = 0, int to = -1) const;
CharacterRange GetCharacterRange(const TextRun&,
unsigned from,
unsigned to) const;
Vector<CharacterRange> IndividualCharacterRanges(const TextRun&) const;
+ void ExpandRangeToIncludePartialGlyphs(const TextRun&,
+ int* from,
+ int* to) const;
+
// Metrics that we query the FontFallbackList for.
float SpaceWidth() const {
DCHECK(PrimaryFont());
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_cache.cc b/chromium/third_party/blink/renderer/platform/fonts/font_cache.cc
index c4b0b4afd9c..ac44cca505d 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_cache.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_cache.cc
@@ -38,7 +38,6 @@
#include "build/build_config.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/font_family_names.h"
-#include "third_party/blink/renderer/platform/fonts/accept_languages_resolver.h"
#include "third_party/blink/renderer/platform/fonts/alternate_font_family.h"
#include "third_party/blink/renderer/platform/fonts/font_cache_client.h"
#include "third_party/blink/renderer/platform/fonts/font_cache_key.h"
@@ -54,6 +53,7 @@
#include "third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/text/layout_locale.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
@@ -65,10 +65,13 @@ namespace blink {
SkFontMgr* FontCache::static_font_manager_ = nullptr;
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+float FontCache::device_scale_factor_ = 1.0;
+#endif
+
#if defined(OS_WIN)
bool FontCache::antialiased_text_enabled_ = false;
bool FontCache::lcd_text_enabled_ = false;
-float FontCache::device_scale_factor_ = 1.0;
bool FontCache::use_skia_font_fallback_ = false;
#endif // defined(OS_WIN)
@@ -210,7 +213,7 @@ void FontCache::SetFontManager(sk_sp<SkFontMgr> font_manager) {
}
void FontCache::AcceptLanguagesChanged(const String& accept_languages) {
- AcceptLanguagesResolver::AcceptLanguagesChanged(accept_languages);
+ LayoutLocale::AcceptLanguagesChanged(accept_languages);
GetFontCache()->InvalidateShapeCache();
}
@@ -283,7 +286,14 @@ scoped_refptr<SimpleFontData> FontCache::FallbackFontForCharacter(
UChar32 lookup_char,
const SimpleFontData* font_data_to_substitute,
FontFallbackPriority fallback_priority) {
- if (Character::IsUnassignedOrPrivateUse(lookup_char))
+ // In addition to PUA, do not perform fallback for non-characters either. Some
+ // of these are sentinel characters to detect encodings and do appear on
+ // websites. More details on
+ // http://www.unicode.org/faq/private_use.html#nonchar1 - See also
+ // crbug.com/862352 where performing fallback for U+FFFE causes a memory
+ // regression.
+ if (Character::IsPrivateUse(lookup_char) ||
+ Character::IsNonCharacter(lookup_char))
return nullptr;
return PlatformFallbackFontForCharacter(
description, lookup_char, font_data_to_substitute, fallback_priority);
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_cache.h b/chromium/third_party/blink/renderer/platform/fonts/font_cache.h
index 0b081b4afae..81020921035 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_cache.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_cache.h
@@ -53,10 +53,9 @@
#include "third_party/blink/renderer/platform/wtf/text/cstring.h"
#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/skia/include/core/SkFontMgr.h"
#include "third_party/skia/include/core/SkRefCnt.h"
-#include "SkFontMgr.h"
-
class SkString;
class SkTypeface;
@@ -157,6 +156,15 @@ class PLATFORM_EXPORT FontCache {
sk_sp<SkFontMgr> FontManager() { return font_manager_; }
static void SetFontManager(sk_sp<SkFontMgr>);
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+ // These are needed for calling QueryRenderStyleForStrike, since
+ // gfx::GetFontRenderParams makes distinctions based on DSF.
+ static float DeviceScaleFactor() { return device_scale_factor_; }
+ static void SetDeviceScaleFactor(float device_scale_factor) {
+ device_scale_factor_ = device_scale_factor;
+ }
+#endif
+
#if !defined(OS_MACOSX)
static const AtomicString& SystemFontFamily();
#else
@@ -172,14 +180,10 @@ class PLATFORM_EXPORT FontCache {
// related to FontCache. Move it somewhere else, e.g. to WebThemeEngine.
static bool AntialiasedTextEnabled() { return antialiased_text_enabled_; }
static bool LcdTextEnabled() { return lcd_text_enabled_; }
- static float DeviceScaleFactor() { return device_scale_factor_; }
static void SetAntialiasedTextEnabled(bool enabled) {
antialiased_text_enabled_ = enabled;
}
static void SetLCDTextEnabled(bool enabled) { lcd_text_enabled_ = enabled; }
- static void SetDeviceScaleFactor(float device_scale_factor) {
- device_scale_factor_ = device_scale_factor;
- }
static void AddSideloadedFontForTesting(sk_sp<SkTypeface>);
// Functions to cache and retrieve the system font metrics.
static void SetMenuFontMetrics(const wchar_t* family_name,
@@ -308,7 +312,6 @@ class PLATFORM_EXPORT FontCache {
#if defined(OS_WIN)
static bool antialiased_text_enabled_;
static bool lcd_text_enabled_;
- static float device_scale_factor_;
static HashMap<String, sk_sp<SkTypeface>>* sideloaded_fonts_;
// The system font metrics cache.
static AtomicString* menu_font_family_name_;
@@ -324,6 +327,10 @@ class PLATFORM_EXPORT FontCache {
bool is_test_font_mgr_ = false;
#endif // defined(OS_WIN)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+ static float device_scale_factor_;
+#endif
+
unsigned short generation_ = 0;
bool platform_init_ = false;
Persistent<HeapHashSet<WeakMember<FontCacheClient>>> font_cache_clients_;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_cache_key.h b/chromium/third_party/blink/renderer/platform/fonts/font_cache_key.h
index 305c1b0a47f..5c0c209237a 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_cache_key.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_cache_key.h
@@ -49,22 +49,31 @@ struct FontCacheKey {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
public:
- FontCacheKey() : creation_params_(), font_size_(0), options_(0) {}
+ FontCacheKey()
+ : creation_params_(),
+ font_size_(0),
+ options_(0),
+ device_scale_factor_(0) {}
FontCacheKey(FontFaceCreationParams creation_params,
float font_size,
unsigned options,
+ float device_scale_factor,
scoped_refptr<FontVariationSettings> variation_settings)
: creation_params_(creation_params),
font_size_(font_size * kFontSizePrecisionMultiplier),
options_(options),
+ device_scale_factor_(device_scale_factor),
variation_settings_(std::move(variation_settings)) {}
FontCacheKey(WTF::HashTableDeletedValueType)
: font_size_(HashTableDeletedSize()) {}
unsigned GetHash() const {
- unsigned hash_codes[4] = {
+ // Convert from float with 3 digit precision before hashing.
+ unsigned device_scale_factor_hash = device_scale_factor_ * 1000;
+ unsigned hash_codes[5] = {
creation_params_.GetHash(), font_size_, options_,
+ device_scale_factor_hash,
variation_settings_ ? variation_settings_->GetHash() : 0};
return StringHasher::HashMemory<sizeof(hash_codes)>(hash_codes);
}
@@ -72,6 +81,7 @@ struct FontCacheKey {
bool operator==(const FontCacheKey& other) const {
return creation_params_ == other.creation_params_ &&
font_size_ == other.font_size_ && options_ == other.options_ &&
+ device_scale_factor_ == other.device_scale_factor_ &&
variation_settings_ == other.variation_settings_;
}
@@ -89,6 +99,11 @@ struct FontCacheKey {
FontFaceCreationParams creation_params_;
unsigned font_size_;
unsigned options_;
+ // FontCacheKey is the key to retrieve FontPlatformData entries from the
+ // FontCache. FontPlatformData queries the platform's font render style, which
+ // is dependent on the device scale factor. That's why we need
+ // device_scale_factor_ to be a part of computing the cache key.
+ float device_scale_factor_;
scoped_refptr<FontVariationSettings> variation_settings_;
};
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_cache_test.cc b/chromium/third_party/blink/renderer/platform/fonts/font_cache_test.cc
index a4b69a38a04..b8b1c50ee64 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_cache_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_cache_test.cc
@@ -35,7 +35,7 @@ TEST(FontCache, NoFallbackForPrivateUseArea) {
FontDescription font_description;
font_description.SetGenericFamily(FontDescription::kStandardFamily);
for (UChar32 character : {0xE000, 0xE401, 0xE402, 0xE403, 0xF8FF, 0xF0000,
- 0xFAAAA, 0xFFFFF, 0x100000, 0x10AAAA, 0x10FFFF}) {
+ 0xFAAAA, 0x100000, 0x10AAAA}) {
scoped_refptr<SimpleFontData> font_data =
font_cache->FallbackFontForCharacter(font_description, character,
nullptr);
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_custom_platform_data.h b/chromium/third_party/blink/renderer/platform/fonts/font_custom_platform_data.h
index 491b1b0b666..826258026f9 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_custom_platform_data.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_custom_platform_data.h
@@ -41,6 +41,7 @@
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/skia/include/core/SkRefCnt.h"
+#include "third_party/skia/include/core/SkString.h"
class SkTypeface;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_description.cc b/chromium/third_party/blink/renderer/platform/fonts/font_description.cc
index 156431f82cd..32d2a97d5a2 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_description.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_description.cc
@@ -28,6 +28,7 @@
*/
#include "third_party/blink/renderer/platform/fonts/font_description.h"
+#include "build/build_config.h"
#include "third_party/blink/public/platform/web_font_description.h"
#include "third_party/blink/renderer/platform/language.h"
@@ -37,6 +38,10 @@
#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+#include "third_party/blink/renderer/platform/fonts/font_cache.h"
+#endif
+
namespace blink {
struct SameSizeAsFontDescription {
@@ -217,9 +222,14 @@ FontCacheKey FontDescription::CacheKey(
static_cast<unsigned>(fields_.orientation_) << 1 | // bit 2-3
static_cast<unsigned>(fields_.subpixel_text_position_); // bit 1
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+ float device_scale_factor_for_key = FontCache::DeviceScaleFactor();
+#else
+ float device_scale_factor_for_key = 1.0f;
+#endif
FontCacheKey cache_key(creation_params, EffectiveFontSize(),
options | font_selection_request_.GetHash() << 8,
- variation_settings_);
+ device_scale_factor_for_key, variation_settings_);
return cache_key;
}
@@ -359,6 +369,17 @@ SkFontStyle FontDescription::SkiaFontStyle() const {
return SkFontStyle(skia_weight, skia_width, slant);
}
+int FontDescription::MinimumPrefixWidthToHyphenate() const {
+ // If the maximum width available for the prefix before the hyphen is small,
+ // then it is very unlikely that an hyphenation opportunity exists, so do not
+ // bother to look for it. These are heuristic numbers for performance added
+ // in http://wkb.ug/45606
+ const int kMinimumPrefixWidthNumerator = 5;
+ const int kMinimumPrefixWidthDenominator = 4;
+ return ComputedPixelSize() * kMinimumPrefixWidthNumerator /
+ kMinimumPrefixWidthDenominator;
+}
+
String FontDescription::ToString(GenericFamilyType familyType) {
switch (familyType) {
case GenericFamilyType::kNoFamily:
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_description.h b/chromium/third_party/blink/renderer/platform/fonts/font_description.h
index 0af519e4154..140e099364f 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_description.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_description.h
@@ -40,7 +40,7 @@
#include "third_party/blink/renderer/platform/fonts/opentype/font_settings.h"
#include "third_party/blink/renderer/platform/fonts/text_rendering_mode.h"
#include "third_party/blink/renderer/platform/fonts/typesetting_features.h"
-#include "third_party/blink/renderer/platform/layout_locale.h"
+#include "third_party/blink/renderer/platform/text/layout_locale.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
@@ -336,6 +336,8 @@ class PLATFORM_EXPORT FontDescription {
SkFontStyle SkiaFontStyle() const;
+ int MinimumPrefixWidthToHyphenate() const;
+
String ToString() const;
private:
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_global_context.cc b/chromium/third_party/blink/renderer/platform/fonts/font_global_context.cc
index e90f6d72a80..bbdabeddf37 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_global_context.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_global_context.cc
@@ -5,7 +5,6 @@
#include "third_party/blink/renderer/platform/fonts/font_global_context.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
namespace blink {
@@ -19,12 +18,7 @@ FontGlobalContext* FontGlobalContext::Get(CreateIfNeeded create_if_needed) {
return *font_persistent;
}
-FontGlobalContext::FontGlobalContext()
- : harfbuzz_font_funcs_(nullptr),
- default_locale_(nullptr),
- system_locale_(nullptr),
- default_locale_for_han_(nullptr),
- has_default_locale_for_han_(false) {}
+FontGlobalContext::FontGlobalContext() : harfbuzz_font_funcs_(nullptr) {}
void FontGlobalContext::ClearMemory() {
if (!Get(kDoNotCreate))
@@ -35,11 +29,6 @@ void FontGlobalContext::ClearMemory() {
void FontGlobalContext::ClearForTesting() {
FontGlobalContext* ctx = Get();
- ctx->default_locale_ = nullptr;
- ctx->system_locale_ = nullptr;
- ctx->default_locale_for_han_ = nullptr;
- ctx->has_default_locale_for_han_ = false;
- ctx->layout_locale_map_.clear();
ctx->font_cache_.Invalidate();
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_global_context.h b/chromium/third_party/blink/renderer/platform/fonts/font_global_context.h
index 256d435dc8e..928df28d42d 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_global_context.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_global_context.h
@@ -6,23 +6,16 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_GLOBAL_CONTEXT_H_
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_font_cache.h"
-#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/hash_map.h"
-#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
-#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
+#include "third_party/blink/renderer/platform/text/layout_locale.h"
struct hb_font_funcs_t;
namespace blink {
-class LayoutLocale;
class FontCache;
-using LayoutLocaleMap =
- HashMap<AtomicString, scoped_refptr<LayoutLocale>, CaseFoldingHash>;
-
enum CreateIfNeeded { kDoNotCreate, kCreate };
// FontGlobalContext contains non-thread-safe, thread-specific data used for
@@ -36,7 +29,7 @@ class PLATFORM_EXPORT FontGlobalContext {
static inline FontCache& GetFontCache() { return Get()->font_cache_; }
static inline HarfBuzzFontCache& GetHarfBuzzFontCache() {
- return Get()->harf_buzz_font_cache_;
+ return Get()->harfbuzz_font_cache_;
}
static hb_font_funcs_t* GetHarfBuzzFontFuncs() {
@@ -47,46 +40,6 @@ class PLATFORM_EXPORT FontGlobalContext {
Get()->harfbuzz_font_funcs_ = funcs;
}
- static inline LayoutLocaleMap& GetLayoutLocaleMap() {
- return Get()->layout_locale_map_;
- }
-
- static inline const LayoutLocale* GetDefaultLayoutLocale() {
- return Get()->default_locale_;
- }
- static inline void SetDefaultLayoutLocale(const LayoutLocale* locale) {
- Get()->default_locale_ = locale;
- }
- static inline const LayoutLocale* GetSystemLayoutLocale() {
- return Get()->system_locale_;
- }
- static inline void SetSystemLayoutLocale(const LayoutLocale* locale) {
- Get()->system_locale_ = locale;
- }
-
- static inline const LayoutLocale* GetDefaultLocaleForHan() {
- FontGlobalContext* ctx = Get();
- DCHECK(ctx->has_default_locale_for_han_);
- return ctx->default_locale_for_han_;
- }
- static inline void SetDefaultLocaleForHan(const LayoutLocale* locale) {
- FontGlobalContext* ctx = Get();
- ctx->default_locale_for_han_ = locale;
- ctx->has_default_locale_for_han_ = true;
- }
- static inline void InvalidateLocaleForHan() {
- FontGlobalContext* ctx = Get();
- ctx->default_locale_for_han_ = nullptr;
- ctx->has_default_locale_for_han_ = false;
- }
- static inline bool HasDefaultLocaleForHan() {
- return Get()->has_default_locale_for_han_;
- }
-
- static inline String& CurrentAcceptLanguages() {
- return Get()->current_accept_languages_;
- }
-
// Called by MemoryCoordinator to clear memory.
static void ClearMemory();
@@ -99,18 +52,8 @@ class PLATFORM_EXPORT FontGlobalContext {
~FontGlobalContext() = default;
FontCache font_cache_;
-
- HarfBuzzFontCache harf_buzz_font_cache_;
-
+ HarfBuzzFontCache harfbuzz_font_cache_;
hb_font_funcs_t* harfbuzz_font_funcs_;
-
- LayoutLocaleMap layout_locale_map_;
- const LayoutLocale* default_locale_;
- const LayoutLocale* system_locale_;
- const LayoutLocale* default_locale_for_han_;
- bool has_default_locale_for_han_;
-
- String current_accept_languages_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_platform_data.cc b/chromium/third_party/blink/renderer/platform/fonts/font_platform_data.cc
index de02c36d6fe..51a6adf7a3c 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_platform_data.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_platform_data.cc
@@ -27,11 +27,10 @@
#include "third_party/blink/public/platform/linux/web_sandbox_support.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_face.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/layout_test_support.h"
#include "third_party/blink/renderer/platform/text/character.h"
-#include "third_party/blink/renderer/platform/wtf/byte_swap.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
@@ -101,7 +100,7 @@ FontPlatformData::FontPlatformData(const FontPlatformData& source)
#if !defined(OS_WIN) && !defined(OS_MACOSX)
style_(source.style_),
#endif
- harf_buzz_face_(nullptr),
+ harfbuzz_face_(nullptr),
is_hash_table_deleted_value_(false)
#if defined(OS_WIN)
,
@@ -194,7 +193,7 @@ const FontPlatformData& FontPlatformData::operator=(
synthetic_bold_ = other.synthetic_bold_;
synthetic_italic_ = other.synthetic_italic_;
avoid_embedded_bitmaps_ = other.avoid_embedded_bitmaps_;
- harf_buzz_face_ = nullptr;
+ harfbuzz_face_ = nullptr;
orientation_ = other.orientation_;
#if !defined(OS_WIN) && !defined(OS_MACOSX)
style_ = other.style_;
@@ -248,11 +247,11 @@ SkTypeface* FontPlatformData::Typeface() const {
}
HarfBuzzFace* FontPlatformData::GetHarfBuzzFace() const {
- if (!harf_buzz_face_)
- harf_buzz_face_ =
+ if (!harfbuzz_face_)
+ harfbuzz_face_ =
HarfBuzzFace::Create(const_cast<FontPlatformData*>(this), UniqueID());
- return harf_buzz_face_.get();
+ return harfbuzz_face_.get();
}
bool FontPlatformData::HasSpaceInLigaturesOrKerning(
@@ -301,16 +300,15 @@ WebFontRenderStyle FontPlatformData::QuerySystemRenderStyle(
SkFontStyle font_style) {
WebFontRenderStyle result;
-#if !defined(OS_ANDROID)
+#if !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
// If the font name is missing (i.e. probably a web font) or the sandbox is
// disabled, use the system defaults.
if (family.length() && Platform::Current()->GetSandboxSupport()) {
bool is_bold = font_style.weight() >= SkFontStyle::kSemiBold_Weight;
bool is_italic = font_style.slant() != SkFontStyle::kUpright_Slant;
- const int size_and_style = (((int)text_size) << 2) | (((int)is_bold) << 1) |
- (((int)is_italic) << 0);
Platform::Current()->GetSandboxSupport()->GetWebFontRenderStyleForStrike(
- family.data(), size_and_style, &result);
+ family.data(), text_size, is_bold, is_italic,
+ FontCache::DeviceScaleFactor(), &result);
}
#endif
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_platform_data.h b/chromium/third_party/blink/renderer/platform/fonts/font_platform_data.h
index dd5762f82a8..df741b2668d 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_platform_data.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_platform_data.h
@@ -192,7 +192,7 @@ class PLATFORM_EXPORT FontPlatformData {
WebFontRenderStyle style_;
#endif
- mutable scoped_refptr<HarfBuzzFace> harf_buzz_face_;
+ mutable scoped_refptr<HarfBuzzFace> harfbuzz_face_;
bool is_hash_table_deleted_value_;
#if defined(OS_WIN)
// TODO(https://crbug.com/808221): Replace |paint_text_flags_| with |style_|.
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_test.cc b/chromium/third_party/blink/renderer/platform/fonts/font_test.cc
index c4d1db5f42f..ceb0542e3d9 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_test.cc
@@ -15,7 +15,27 @@ using blink::test::CreateTestFont;
namespace blink {
-TEST(FontTest, TextIntercepts) {
+class FontTest : public ::testing::Test {
+ public:
+ Vector<int> GetExpandedRange(const String& text, bool ltr, int from, int to) {
+ FontDescription::VariantLigatures ligatures(
+ FontDescription::kEnabledLigaturesState);
+ Font font = CreateTestFont(
+ "roboto",
+ test::PlatformTestDataPath("third_party/Roboto/roboto-regular.woff2"),
+ 100, &ligatures);
+
+ TextRun text_run(
+ text, /* xpos */ 0, /* expansion */ 0,
+ TextRun::kAllowTrailingExpansion | TextRun::kForbidLeadingExpansion,
+ ltr ? TextDirection::kLtr : TextDirection::kRtl, false);
+
+ font.ExpandRangeToIncludePartialGlyphs(text_run, &from, &to);
+ return Vector<int>({from, to});
+ }
+};
+
+TEST_F(FontTest, TextIntercepts) {
Font font =
CreateTestFont("Ahem", test::PlatformTestDataPath("Ahem.woff"), 16);
// A sequence of LATIN CAPITAL LETTER E WITH ACUTE and LATIN SMALL LETTER P
@@ -48,4 +68,22 @@ TEST(FontTest, TextIntercepts) {
}
}
+TEST_F(FontTest, ExpandRange) {
+ // "ffi" is a ligature, therefore a single glyph. Any range that includes one
+ // of the letters must be expanded to all of them.
+ EXPECT_EQ(GetExpandedRange("efficient", true, 0, 1), Vector<int>({0, 1}));
+ EXPECT_EQ(GetExpandedRange("efficient", true, 0, 2), Vector<int>({0, 4}));
+ EXPECT_EQ(GetExpandedRange("efficient", true, 3, 4), Vector<int>({1, 4}));
+ EXPECT_EQ(GetExpandedRange("efficient", true, 4, 6), Vector<int>({4, 6}));
+ EXPECT_EQ(GetExpandedRange("efficient", true, 6, 7), Vector<int>({6, 7}));
+ EXPECT_EQ(GetExpandedRange("efficient", true, 0, 9), Vector<int>({0, 9}));
+
+ EXPECT_EQ(GetExpandedRange("tneiciffe", false, 0, 1), Vector<int>({0, 1}));
+ EXPECT_EQ(GetExpandedRange("tneiciffe", false, 0, 2), Vector<int>({0, 2}));
+ EXPECT_EQ(GetExpandedRange("tneiciffe", false, 3, 4), Vector<int>({3, 4}));
+ EXPECT_EQ(GetExpandedRange("tneiciffe", false, 4, 6), Vector<int>({4, 8}));
+ EXPECT_EQ(GetExpandedRange("tneiciffe", false, 6, 7), Vector<int>({5, 8}));
+ EXPECT_EQ(GetExpandedRange("tneiciffe", false, 0, 9), Vector<int>({0, 9}));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/font_vertical_position_type.h b/chromium/third_party/blink/renderer/platform/fonts/font_vertical_position_type.h
index 7e05ad49e8c..4a6e86d1c41 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/font_vertical_position_type.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/font_vertical_position_type.h
@@ -20,6 +20,14 @@ enum class FontVerticalPositionType {
BottomOfEmHeight
};
+// Returns whether the position type is CSS "line-over"; i.e., ascender side
+// or "top" side of a line box.
+// https://drafts.csswg.org/css-writing-modes-3/#line-over
+inline bool IsLineOverSide(FontVerticalPositionType type) {
+ return type == FontVerticalPositionType::TextTop ||
+ type == FontVerticalPositionType::TopOfEmHeight;
+}
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_FONT_VERTICAL_POSITION_TYPE_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm b/chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm
index 4c06fbbbb3f..e792e97d015 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm
+++ b/chromium/third_party/blink/renderer/platform/fonts/mac/font_cache_mac.mm
@@ -33,6 +33,7 @@
#include <memory>
#include "base/location.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/platform/font_family_names.h"
#include "third_party/blink/renderer/platform/fonts/font_description.h"
#include "third_party/blink/renderer/platform/fonts/font_face_creation_params.h"
diff --git a/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm b/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm
index 129804a9669..11368b4b87b 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm
+++ b/chromium/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm
@@ -29,7 +29,7 @@
#import "third_party/blink/public/platform/platform.h"
#import "third_party/blink/renderer/platform/fonts/font.h"
#import "third_party/blink/renderer/platform/fonts/opentype/font_settings.h"
-#import "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_face.h"
+#import "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h"
#import "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#import "third_party/blink/renderer/platform/layout_test_support.h"
#import "third_party/blink/renderer/platform/wtf/retain_ptr.h"
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.cc b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.cc
index 5b5ec7dedde..3365749c759 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.cc
@@ -7,16 +7,16 @@
namespace blink {
OpenTypeCapsSupport::OpenTypeCapsSupport()
- : harf_buzz_face_(nullptr),
+ : harfbuzz_face_(nullptr),
requested_caps_(FontDescription::kCapsNormal),
font_support_(FontSupport::kFull),
caps_synthesis_(CapsSynthesis::kNone) {}
OpenTypeCapsSupport::OpenTypeCapsSupport(
- const HarfBuzzFace* harf_buzz_face,
+ const HarfBuzzFace* harfbuzz_face,
FontDescription::FontVariantCaps requested_caps,
hb_script_t script)
- : harf_buzz_face_(harf_buzz_face),
+ : harfbuzz_face_(harfbuzz_face),
requested_caps_(requested_caps),
font_support_(FontSupport::kFull),
caps_synthesis_(CapsSynthesis::kNone) {
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h
index 16dd277863e..841e465c8a1 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h
@@ -7,8 +7,8 @@
#include "third_party/blink/renderer/platform/fonts/font_description.h"
#include "third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/case_mapping_harf_buzz_buffer_filler.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_face.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h"
#include "third_party/blink/renderer/platform/fonts/small_caps_iterator.h"
#include <hb.h>
@@ -32,7 +32,7 @@ class PLATFORM_EXPORT OpenTypeCapsSupport {
void DetermineFontSupport(hb_script_t);
bool SupportsOpenTypeFeature(hb_script_t, uint32_t tag) const;
- const HarfBuzzFace* harf_buzz_face_;
+ const HarfBuzzFace* harfbuzz_face_;
FontDescription::FontVariantCaps requested_caps_;
enum class FontSupport {
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support_mpl.cc b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support_mpl.cc
index 41feeb4d1b3..0e0a808ac1c 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support_mpl.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support_mpl.cc
@@ -15,7 +15,7 @@ namespace blink {
bool OpenTypeCapsSupport::SupportsOpenTypeFeature(hb_script_t script,
uint32_t tag) const {
hb_face_t* face = hb_font_get_face(
- harf_buzz_face_->GetScaledFont(nullptr, HarfBuzzFace::NoVerticalLayout));
+ harfbuzz_face_->GetScaledFont(nullptr, HarfBuzzFace::NoVerticalLayout));
DCHECK(face);
DCHECK(
diff --git a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_types.h b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_types.h
index 607959e7fbc..d605c176897 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_types.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/opentype/open_type_types.h
@@ -25,7 +25,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_OPENTYPE_OPEN_TYPE_TYPES_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_OPENTYPE_OPEN_TYPE_TYPES_H_
-#include "third_party/blink/renderer/platform/wtf/byte_order.h"
+#include "base/sys_byteorder.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -33,29 +33,33 @@ namespace OpenType {
struct Int16 {
DISALLOW_NEW();
- Int16(int16_t u) : v(htons(static_cast<uint16_t>(u))) {}
- operator int16_t() const { return static_cast<int16_t>(ntohs(v)); }
+ Int16(int16_t u) : v(base::HostToNet16(static_cast<uint16_t>(u))) {}
+ operator int16_t() const {
+ return static_cast<int16_t>(base::NetToHost16(v));
+ }
uint16_t v; // in BigEndian
};
struct UInt16 {
DISALLOW_NEW();
- UInt16(uint16_t u) : v(htons(u)) {}
- operator uint16_t() const { return ntohs(v); }
+ UInt16(uint16_t u) : v(base::HostToNet16(u)) {}
+ operator uint16_t() const { return base::NetToHost16(v); }
uint16_t v; // in BigEndian
};
struct Int32 {
DISALLOW_NEW();
- Int32(int32_t u) : v(htonl(static_cast<uint32_t>(u))) {}
- operator int32_t() const { return static_cast<int32_t>(ntohl(v)); }
+ Int32(int32_t u) : v(base::HostToNet32(static_cast<uint32_t>(u))) {}
+ operator int32_t() const {
+ return static_cast<int32_t>(base::NetToHost32(v));
+ }
uint32_t v; // in BigEndian
};
struct UInt32 {
DISALLOW_NEW();
- UInt32(uint32_t u) : v(htonl(u)) {}
- operator uint32_t() const { return ntohl(v); }
+ UInt32(uint32_t u) : v(base::HostToNet32(u)) {}
+ operator uint32_t() const { return base::NetToHost32(v); }
uint32_t v; // in BigEndian
};
diff --git a/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.cc b/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.cc
index 96d52776100..ca054ad8f38 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.cc
@@ -12,11 +12,12 @@ namespace blink {
typedef ScriptData::PairedBracketType PairedBracketType;
-const int ScriptData::kMaxScriptCount = 20;
+constexpr int ScriptRunIterator::kMaxScriptCount;
+constexpr int ScriptData::kMaxScriptCount;
ScriptData::~ScriptData() = default;
-void ICUScriptData::GetScripts(UChar32 ch, Vector<UScriptCode>& dst) const {
+void ICUScriptData::GetScripts(UChar32 ch, UScriptCodeList& dst) const {
ICUError status;
// Leave room to insert primary script. It's not strictly necessary but
// it ensures that the result won't ever be greater than kMaxScriptCount,
@@ -119,6 +120,8 @@ ScriptRunIterator::ScriptRunIterator(const UChar* text,
: text_(text),
length_(length),
brackets_fixup_depth_(0),
+ next_set_(std::make_unique<UScriptCodeList>()),
+ ahead_set_(std::make_unique<UScriptCodeList>()),
// The initial value of m_aheadCharacter is not used.
ahead_character_(0),
ahead_pos_(0),
@@ -134,7 +137,7 @@ ScriptRunIterator::ScriptRunIterator(const UChar* text,
// chosing the script of the first consumed character.
current_set_.push_back(USCRIPT_COMMON);
U16_NEXT(text_, ahead_pos_, length_, ahead_character_);
- script_data_->GetScripts(ahead_character_, ahead_set_);
+ script_data_->GetScripts(ahead_character_, *ahead_set_);
}
}
@@ -164,7 +167,7 @@ bool ScriptRunIterator::Consume(unsigned& limit, UScriptCode& script) {
limit = pos;
script = ResolveCurrentScript();
FixupStack(script);
- current_set_ = next_set_;
+ current_set_ = *next_set_;
return true;
}
}
@@ -193,8 +196,8 @@ void ScriptRunIterator::CloseBracket(UChar32 ch) {
if (it->ch == target) {
// Have a match, use open paren's resolved script.
UScriptCode script = it->script;
- next_set_.clear();
- next_set_.push_back(script);
+ next_set_->clear();
+ next_set_->push_back(script);
// And pop stack to this point.
int num_popped = std::distance(brackets_.rbegin(), it);
@@ -221,7 +224,7 @@ void ScriptRunIterator::CloseBracket(UChar32 ch) {
// common, and there is no common preferred script and next has a preferred
// script, set the common preferred script to that of next.
bool ScriptRunIterator::MergeSets() {
- if (next_set_.IsEmpty() || current_set_.IsEmpty()) {
+ if (next_set_->IsEmpty() || current_set_.IsEmpty()) {
return false;
}
@@ -233,24 +236,24 @@ bool ScriptRunIterator::MergeSets() {
// If next is common or inherited, the only thing that might change
// is the common preferred script.
- if (next_set_.at(0) <= USCRIPT_INHERITED) {
- if (next_set_.size() == 2 && priority_script <= USCRIPT_INHERITED &&
+ if (next_set_->at(0) <= USCRIPT_INHERITED) {
+ if (next_set_->size() == 2 && priority_script <= USCRIPT_INHERITED &&
common_preferred_ == USCRIPT_COMMON) {
- common_preferred_ = next_set_.at(1);
+ common_preferred_ = next_set_->at(1);
}
return true;
}
// If current is common or inherited, use the next script set.
if (priority_script <= USCRIPT_INHERITED) {
- current_set_ = next_set_;
+ current_set_ = *next_set_;
return true;
}
// Neither is common or inherited. If current is a singleton,
// just see if it exists in the next set. This is the common case.
- auto* next_it = next_set_.begin();
- auto* next_end = next_set_.end();
+ auto* next_it = next_set_->begin();
+ auto* next_end = next_set_->end();
if (current_set_it == current_end) {
return std::find(next_it, next_end, priority_script) != next_end;
}
@@ -326,7 +329,7 @@ bool ScriptRunIterator::Fetch(size_t* pos, UChar32* ch) {
*pos = ahead_pos_ - (ahead_character_ >= 0x10000 ? 2 : 1);
*ch = ahead_character_;
- next_set_.swap(ahead_set_);
+ std::swap(next_set_, ahead_set_);
if (ahead_pos_ == length_) {
// No more data to fetch, but last character still needs to be
// processed. Advance m_aheadPos so that next time we will know
@@ -336,22 +339,22 @@ bool ScriptRunIterator::Fetch(size_t* pos, UChar32* ch) {
}
U16_NEXT(text_, ahead_pos_, length_, ahead_character_);
- script_data_->GetScripts(ahead_character_, ahead_set_);
- if (ahead_set_.IsEmpty()) {
+ script_data_->GetScripts(ahead_character_, *ahead_set_);
+ if (ahead_set_->IsEmpty()) {
// No scripts for this character. This has already been logged, so
// we just terminate processing this text.
return false;
}
- if (ahead_set_[0] == USCRIPT_INHERITED && ahead_set_.size() > 1) {
- if (next_set_[0] == USCRIPT_COMMON) {
+ if ((*ahead_set_)[0] == USCRIPT_INHERITED && ahead_set_->size() > 1) {
+ if ((*next_set_)[0] == USCRIPT_COMMON) {
// Overwrite the next set with the non-inherited portion of the set.
- next_set_ = ahead_set_;
- next_set_.EraseAt(0);
+ *next_set_ = *ahead_set_;
+ next_set_->EraseAt(0);
// Discard the remaining values, we'll inherit.
- ahead_set_.resize(1);
+ ahead_set_->resize(1);
} else {
// Else, this applies to anything.
- ahead_set_.resize(1);
+ ahead_set_->resize(1);
}
}
return true;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.h b/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.h
index 7c4ce650762..6fc60952c87 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator.h
@@ -33,6 +33,9 @@ class PLATFORM_EXPORT ScriptRunIterator {
bool Consume(unsigned& limit, UScriptCode&);
+ static constexpr int kMaxScriptCount = 20;
+ using UScriptCodeList = Vector<UScriptCode, kMaxScriptCount>;
+
private:
struct BracketRec {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
@@ -56,9 +59,12 @@ class PLATFORM_EXPORT ScriptRunIterator {
// excessively large when processing long runs of text.
static const int kMaxBrackets = 32;
- Vector<UScriptCode> current_set_;
- Vector<UScriptCode> next_set_;
- Vector<UScriptCode> ahead_set_;
+ UScriptCodeList current_set_;
+ // Because next_set_ and ahead_set_ are swapped as we consume characters, and
+ // swapping inlined vector is not cheap, next_set_ and ahead_set_ are
+ // pointers.
+ std::unique_ptr<UScriptCodeList> next_set_;
+ std::unique_ptr<UScriptCodeList> ahead_set_;
UChar32 ahead_character_;
size_t ahead_pos_;
@@ -90,9 +96,10 @@ class PLATFORM_EXPORT ScriptData {
kBracketTypeCount
};
- static const int kMaxScriptCount;
+ static constexpr int kMaxScriptCount = ScriptRunIterator::kMaxScriptCount;
+ using UScriptCodeList = ScriptRunIterator::UScriptCodeList;
- virtual void GetScripts(UChar32, Vector<UScriptCode>& dst) const = 0;
+ virtual void GetScripts(UChar32, UScriptCodeList& dst) const = 0;
virtual UChar32 GetPairedBracket(UChar32) const = 0;
@@ -105,7 +112,7 @@ class PLATFORM_EXPORT ICUScriptData : public ScriptData {
static const ICUScriptData* Instance();
- void GetScripts(UChar32, Vector<UScriptCode>& dst) const override;
+ void GetScripts(UChar32, UScriptCodeList& dst) const override;
UChar32 GetPairedBracket(UChar32) const override;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator_test.cc b/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator_test.cc
index bf289de297c..a8ffd210ca1 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/script_run_iterator_test.cc
@@ -34,7 +34,7 @@ class MockScriptData : public ScriptData {
return &mock_script_data;
}
- void GetScripts(UChar32 ch, Vector<UScriptCode>& dst) const override {
+ void GetScripts(UChar32 ch, UScriptCodeList& dst) const override {
DCHECK_GE(ch, kMockCharMin);
DCHECK_LT(ch, kMockCharLimit);
@@ -663,7 +663,7 @@ TEST_F(ScriptRunIteratorICUDataTest, ValidateICUMaxScriptExtensions) {
TEST_F(ScriptRunIteratorICUDataTest, ICUDataGetScriptsReturnsAllExtensions) {
int max_extensions;
UChar32 cp = GetACharWithMaxExtensions(&max_extensions);
- Vector<UScriptCode> extensions;
+ ScriptData::UScriptCodeList extensions;
ICUScriptData::Instance()->GetScripts(cp, extensions);
// It's possible that GetScripts adds the primary script to the list of
@@ -673,7 +673,7 @@ TEST_F(ScriptRunIteratorICUDataTest, ICUDataGetScriptsReturnsAllExtensions) {
}
TEST_F(ScriptRunIteratorICUDataTest, CommonHaveNoMoreThanOneExtension) {
- Vector<UScriptCode> extensions;
+ ScriptData::UScriptCodeList extensions;
for (UChar32 cp = 0; cp < 0x110000; ++cp) {
ICUScriptData::Instance()->GetScripts(cp, extensions);
UScriptCode primary = extensions.at(0);
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.cc
index 0c56ee41fa9..939164e1199 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.cc
@@ -4,7 +4,7 @@
#include "third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h"
namespace blink {
@@ -15,10 +15,8 @@ scoped_refptr<const ShapeResult> CachingWordShapeIterator::ShapeWordWithoutSpaci
if (cache_entry && cache_entry->shape_result_)
return cache_entry->shape_result_;
- unsigned word_length = 0;
- std::unique_ptr<UChar[]> word_text = word_run.NormalizedUTF16(&word_length);
-
- HarfBuzzShaper shaper(word_text.get(), word_length);
+ const String word_text = word_run.NormalizedUTF16();
+ HarfBuzzShaper shaper(word_text);
scoped_refptr<const ShapeResult> shape_result =
shaper.Shape(font, word_run.Direction());
if (!shape_result)
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc
index 0006c16dc46..aab219b6acf 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc
@@ -27,7 +27,7 @@
#include "third_party/blink/renderer/platform/fonts/character_range.h"
#include "third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_cache.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h"
#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
@@ -80,13 +80,15 @@ static inline float ShapeResultsForRun(ShapeCache* shape_cache,
return total_width;
}
-int CachingWordShaper::OffsetForPosition(const TextRun& run,
- float target_x,
- bool include_partial_glyphs) {
+int CachingWordShaper::OffsetForPosition(
+ const TextRun& run,
+ float target_x,
+ IncludePartialGlyphsOption partial_glyphs,
+ BreakGlyphsOption break_glyphs) {
ShapeResultBuffer buffer;
ShapeResultsForRun(GetShapeCache(), &font_, run, &buffer);
- return buffer.OffsetForPosition(run, target_x, include_partial_glyphs);
+ return buffer.OffsetForPosition(run, target_x, partial_glyphs, break_glyphs);
}
void CachingWordShaper::FillResultBuffer(const TextRunPaintInfo& run_info,
@@ -101,7 +103,7 @@ CharacterRange CachingWordShaper::GetCharacterRange(const TextRun& run,
ShapeResultBuffer buffer;
float total_width = ShapeResultsForRun(GetShapeCache(), &font_, run, &buffer);
- return buffer.GetCharacterRange(run.Direction(), total_width, from, to);
+ return buffer.GetCharacterRange(total_width, run.Direction(), from, to);
}
Vector<CharacterRange> CachingWordShaper::IndividualCharacterRanges(
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h
index ab719be4b34..1adfe2208e0 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h
@@ -55,7 +55,8 @@ class PLATFORM_EXPORT CachingWordShaper final {
FloatRect* glyph_bounds);
int OffsetForPosition(const TextRun&,
float target_x,
- bool include_partial_glyphs);
+ IncludePartialGlyphsOption,
+ BreakGlyphsOption);
void FillResultBuffer(const TextRunPaintInfo&, ShapeResultBuffer*);
CharacterRange GetCharacterRange(const TextRun&, unsigned from, unsigned to);
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harf_buzz_buffer_filler.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harf_buzz_buffer_filler.cc
deleted file mode 100644
index 54ce1d432b1..00000000000
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harf_buzz_buffer_filler.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/fonts/shaping/case_mapping_harf_buzz_buffer_filler.h"
-
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-static const uint16_t* ToUint16(const UChar* src) {
- // FIXME: This relies on undefined behavior however it works on the
- // current versions of all compilers we care about and avoids making
- // a copy of the string.
- static_assert(sizeof(UChar) == sizeof(uint16_t),
- "UChar should be the same size as uint16_t");
- return reinterpret_cast<const uint16_t*>(src);
-}
-
-CaseMappingHarfBuzzBufferFiller::CaseMappingHarfBuzzBufferFiller(
- CaseMapIntend case_map_intend,
- AtomicString locale,
- hb_buffer_t* harf_buzz_buffer,
- const UChar* buffer,
- unsigned buffer_length,
- unsigned start_index,
- unsigned num_characters)
- : harf_buzz_buffer_(harf_buzz_buffer) {
- if (case_map_intend == CaseMapIntend::kKeepSameCase) {
- hb_buffer_add_utf16(harf_buzz_buffer_, ToUint16(buffer), buffer_length,
- start_index, num_characters);
- } else {
- String case_mapped_text;
- if (case_map_intend == CaseMapIntend::kUpperCase) {
- case_mapped_text = String(buffer, buffer_length).UpperUnicode(locale);
- } else {
- case_mapped_text = String(buffer, buffer_length).LowerUnicode(locale);
- }
-
- if (case_mapped_text.length() != buffer_length) {
- FillSlowCase(case_map_intend, locale, buffer, buffer_length, start_index,
- num_characters);
- return;
- }
-
- DCHECK_EQ(case_mapped_text.length(), buffer_length);
- DCHECK(!case_mapped_text.Is8Bit());
- hb_buffer_add_utf16(harf_buzz_buffer_,
- ToUint16(case_mapped_text.Characters16()),
- buffer_length, start_index, num_characters);
- }
-}
-
-// TODO(drott): crbug.com/623940 Fix lack of context sensitive case mapping
-// here.
-void CaseMappingHarfBuzzBufferFiller::FillSlowCase(
- CaseMapIntend case_map_intend,
- AtomicString locale,
- const UChar* buffer,
- unsigned buffer_length,
- unsigned start_index,
- unsigned num_characters) {
- // Record pre-context.
- hb_buffer_add_utf16(harf_buzz_buffer_, ToUint16(buffer), buffer_length,
- start_index, 0);
-
- for (unsigned char_index = start_index;
- char_index < start_index + num_characters;) {
- unsigned new_char_index = char_index;
- U16_FWD_1(buffer, new_char_index, num_characters);
- String char_by_char(&buffer[char_index], new_char_index - char_index);
- String case_mapped_char;
- if (case_map_intend == CaseMapIntend::kUpperCase)
- case_mapped_char = char_by_char.UpperUnicode(locale);
- else
- case_mapped_char = char_by_char.LowerUnicode(locale);
-
- for (unsigned j = 0; j < case_mapped_char.length();) {
- UChar32 codepoint = 0;
- U16_NEXT(case_mapped_char.Characters16(), j, case_mapped_char.length(),
- codepoint);
- // Add all characters of the case mapping result at the same cluster
- // position.
- hb_buffer_add(harf_buzz_buffer_, codepoint, char_index);
- }
- char_index = new_char_index;
- }
-
- // Record post-context
- hb_buffer_add_utf16(harf_buzz_buffer_, ToUint16(buffer), buffer_length,
- start_index + num_characters, 0);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harf_buzz_buffer_filler.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harf_buzz_buffer_filler.h
deleted file mode 100644
index ef32b1e61ea..00000000000
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harf_buzz_buffer_filler.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_CASE_MAPPING_HARF_BUZZ_BUFFER_FILLER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_CASE_MAPPING_HARF_BUZZ_BUFFER_FILLER_H_
-
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
-
-#include <hb.h>
-
-namespace blink {
-
-enum class CaseMapIntend { kKeepSameCase, kUpperCase, kLowerCase };
-
-class CaseMappingHarfBuzzBufferFiller {
- STACK_ALLOCATED();
-
- public:
- CaseMappingHarfBuzzBufferFiller(CaseMapIntend,
- AtomicString locale,
- hb_buffer_t* harf_buzz_buffer,
- const UChar* buffer,
- unsigned buffer_length,
- unsigned start_index,
- unsigned num_characters);
-
- private:
- void FillSlowCase(CaseMapIntend,
- AtomicString locale,
- const UChar* buffer,
- unsigned buffer_length,
- unsigned start_index,
- unsigned num_characters);
- hb_buffer_t* harf_buzz_buffer_;
-};
-
-} // namespace blink
-
-#endif
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.cc
new file mode 100644
index 00000000000..2ab8d8c22be
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.cc
@@ -0,0 +1,94 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.h"
+
+namespace blink {
+
+static const uint16_t* ToUint16(const UChar* src) {
+ // FIXME: This relies on undefined behavior however it works on the
+ // current versions of all compilers we care about and avoids making
+ // a copy of the string.
+ static_assert(sizeof(UChar) == sizeof(uint16_t),
+ "UChar should be the same size as uint16_t");
+ return reinterpret_cast<const uint16_t*>(src);
+}
+
+CaseMappingHarfBuzzBufferFiller::CaseMappingHarfBuzzBufferFiller(
+ CaseMapIntend case_map_intend,
+ AtomicString locale,
+ hb_buffer_t* harfbuzz_buffer,
+ const String& text,
+ unsigned start_index,
+ unsigned num_characters)
+ : harfbuzz_buffer_(harfbuzz_buffer) {
+ if (case_map_intend == CaseMapIntend::kKeepSameCase) {
+ if (text.Is8Bit()) {
+ hb_buffer_add_latin1(harfbuzz_buffer_, text.Characters8(), text.length(),
+ start_index, num_characters);
+ } else {
+ hb_buffer_add_utf16(harfbuzz_buffer_, ToUint16(text.Characters16()),
+ text.length(), start_index, num_characters);
+ }
+ } else {
+ String case_mapped_text = case_map_intend == CaseMapIntend::kUpperCase
+ ? text.UpperUnicode(locale)
+ : text.LowerUnicode(locale);
+ case_mapped_text.Ensure16Bit();
+
+ if (case_mapped_text.length() != text.length()) {
+ FillSlowCase(case_map_intend, locale, text.Characters16(), text.length(),
+ start_index, num_characters);
+ return;
+ }
+
+ DCHECK_EQ(case_mapped_text.length(), text.length());
+ DCHECK(!case_mapped_text.Is8Bit());
+ hb_buffer_add_utf16(harfbuzz_buffer_,
+ ToUint16(case_mapped_text.Characters16()),
+ text.length(), start_index, num_characters);
+ }
+}
+
+// TODO(drott): crbug.com/623940 Fix lack of context sensitive case mapping
+// here.
+void CaseMappingHarfBuzzBufferFiller::FillSlowCase(
+ CaseMapIntend case_map_intend,
+ AtomicString locale,
+ const UChar* buffer,
+ unsigned buffer_length,
+ unsigned start_index,
+ unsigned num_characters) {
+ // Record pre-context.
+ hb_buffer_add_utf16(harfbuzz_buffer_, ToUint16(buffer), buffer_length,
+ start_index, 0);
+
+ for (unsigned char_index = start_index;
+ char_index < start_index + num_characters;) {
+ unsigned new_char_index = char_index;
+ U16_FWD_1(buffer, new_char_index, num_characters);
+ String char_by_char(&buffer[char_index], new_char_index - char_index);
+ String case_mapped_char;
+ if (case_map_intend == CaseMapIntend::kUpperCase)
+ case_mapped_char = char_by_char.UpperUnicode(locale);
+ else
+ case_mapped_char = char_by_char.LowerUnicode(locale);
+
+ for (unsigned j = 0; j < case_mapped_char.length();) {
+ UChar32 codepoint = 0;
+ U16_NEXT(case_mapped_char.Characters16(), j, case_mapped_char.length(),
+ codepoint);
+ // Add all characters of the case mapping result at the same cluster
+ // position.
+ hb_buffer_add(harfbuzz_buffer_, codepoint, char_index);
+ }
+ char_index = new_char_index;
+ }
+
+ // Record post-context
+ hb_buffer_add_utf16(harfbuzz_buffer_, ToUint16(buffer), buffer_length,
+ start_index + num_characters, 0);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.h
new file mode 100644
index 00000000000..e67c7704fbd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.h
@@ -0,0 +1,42 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_CASE_MAPPING_HARFBUZZ_BUFFER_FILLER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_CASE_MAPPING_HARFBUZZ_BUFFER_FILLER_H_
+
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+#include <hb.h>
+
+namespace blink {
+
+enum class CaseMapIntend { kKeepSameCase, kUpperCase, kLowerCase };
+
+class CaseMappingHarfBuzzBufferFiller {
+ STACK_ALLOCATED();
+
+ public:
+ CaseMappingHarfBuzzBufferFiller(CaseMapIntend,
+ AtomicString locale,
+ hb_buffer_t* harfbuzz_buffer,
+ const String& text,
+ unsigned start_index,
+ unsigned num_characters);
+
+ private:
+ void FillSlowCase(CaseMapIntend,
+ AtomicString locale,
+ const UChar* buffer,
+ unsigned buffer_length,
+ unsigned start_index,
+ unsigned num_characters);
+ hb_buffer_t* harfbuzz_buffer_;
+};
+
+} // namespace blink
+
+#endif
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_face.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_face.cc
deleted file mode 100644
index 74aa4743f32..00000000000
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_face.cc
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- * Copyright (c) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_face.h"
-
-#include <memory>
-
-#include "build/build_config.h"
-#include "third_party/blink/renderer/platform/fonts/font_cache.h"
-#include "third_party/blink/renderer/platform/fonts/font_global_context.h"
-#include "third_party/blink/renderer/platform/fonts/font_platform_data.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_font_cache.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.h"
-#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
-#include "third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h"
-#include "third_party/blink/renderer/platform/fonts/unicode_range_set.h"
-#include "third_party/blink/renderer/platform/histogram.h"
-#include "third_party/blink/renderer/platform/resolution_units.h"
-#include "third_party/blink/renderer/platform/wtf/hash_map.h"
-#include "third_party/blink/renderer/platform/wtf/math_extras.h"
-
-#include <hb-ot.h>
-#include <hb.h>
-#if defined(OS_MACOSX)
-#include <hb-coretext.h>
-#endif
-
-#include <SkPaint.h>
-#include <SkPath.h>
-#include <SkPoint.h>
-#include <SkRect.h>
-#include <SkStream.h>
-#include <SkTypeface.h>
-
-namespace blink {
-
-void HbFontDeleter::operator()(hb_font_t* font) {
- if (font)
- hb_font_destroy(font);
-}
-
-void HbFaceDeleter::operator()(hb_face_t* face) {
- if (face)
- hb_face_destroy(face);
-}
-
-struct HbSetDeleter {
- void operator()(hb_set_t* set) {
- if (set)
- hb_set_destroy(set);
- }
-};
-
-using HbSetUniquePtr = std::unique_ptr<hb_set_t, HbSetDeleter>;
-
-static scoped_refptr<HbFontCacheEntry> CreateHbFontCacheEntry(hb_face_t*);
-
-HarfBuzzFace::HarfBuzzFace(FontPlatformData* platform_data, uint64_t unique_id)
- : platform_data_(platform_data), unique_id_(unique_id) {
- HarfBuzzFontCache::AddResult result =
- FontGlobalContext::GetHarfBuzzFontCache().insert(unique_id_, nullptr);
- if (result.is_new_entry) {
- HbFaceUniquePtr face(CreateFace());
- result.stored_value->value = CreateHbFontCacheEntry(face.get());
- }
- result.stored_value->value->AddRef();
- unscaled_font_ = result.stored_value->value->HbFont();
- harf_buzz_font_data_ = result.stored_value->value->HbFontData();
-}
-
-HarfBuzzFace::~HarfBuzzFace() {
- HarfBuzzFontCache::iterator result =
- FontGlobalContext::GetHarfBuzzFontCache().find(unique_id_);
- SECURITY_DCHECK(result != FontGlobalContext::GetHarfBuzzFontCache().end());
- DCHECK(!result.Get()->value->HasOneRef());
- result.Get()->value->Release();
- if (result.Get()->value->HasOneRef())
- FontGlobalContext::GetHarfBuzzFontCache().erase(unique_id_);
-}
-
-static hb_bool_t HarfBuzzGetGlyph(hb_font_t* hb_font,
- void* font_data,
- hb_codepoint_t unicode,
- hb_codepoint_t variation_selector,
- hb_codepoint_t* glyph,
- void* user_data) {
- HarfBuzzFontData* hb_font_data =
- reinterpret_cast<HarfBuzzFontData*>(font_data);
-
- CHECK(hb_font_data);
- if (hb_font_data->range_set_ && !hb_font_data->range_set_->Contains(unicode))
- return false;
-
- return hb_font_get_glyph(hb_font_get_parent(hb_font), unicode,
- variation_selector, glyph);
-}
-
-static hb_position_t HarfBuzzGetGlyphHorizontalAdvance(hb_font_t* hb_font,
- void* font_data,
- hb_codepoint_t glyph,
- void* user_data) {
- HarfBuzzFontData* hb_font_data =
- reinterpret_cast<HarfBuzzFontData*>(font_data);
- hb_position_t advance = 0;
-
- SkiaTextMetrics(&hb_font_data->paint_)
- .GetGlyphWidthForHarfBuzz(glyph, &advance);
- return advance;
-}
-
-static hb_bool_t HarfBuzzGetGlyphVerticalOrigin(hb_font_t* hb_font,
- void* font_data,
- hb_codepoint_t glyph,
- hb_position_t* x,
- hb_position_t* y,
- void* user_data) {
- HarfBuzzFontData* hb_font_data =
- reinterpret_cast<HarfBuzzFontData*>(font_data);
- scoped_refptr<OpenTypeVerticalData> vertical_data =
- hb_font_data->VerticalData();
- if (!vertical_data)
- return false;
-
- float result[] = {0, 0};
- Glyph the_glyph = glyph;
- vertical_data->GetVerticalTranslationsForGlyphs(hb_font_data->paint_,
- &the_glyph, 1, result);
- *x = SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(-result[0]);
- *y = SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(-result[1]);
- return true;
-}
-
-static hb_position_t HarfBuzzGetGlyphVerticalAdvance(hb_font_t* hb_font,
- void* font_data,
- hb_codepoint_t glyph,
- void* user_data) {
- HarfBuzzFontData* hb_font_data =
- reinterpret_cast<HarfBuzzFontData*>(font_data);
- scoped_refptr<OpenTypeVerticalData> vertical_data =
- hb_font_data->VerticalData();
- if (!vertical_data) {
- return SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(
- hb_font_data->height_fallback_);
- }
-
- Glyph the_glyph = glyph;
- float advance_height = -vertical_data->AdvanceHeight(the_glyph);
- return SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(
- SkFloatToScalar(advance_height));
-}
-
-static hb_position_t HarfBuzzGetGlyphHorizontalKerning(
- hb_font_t*,
- void* font_data,
- hb_codepoint_t left_glyph,
- hb_codepoint_t right_glyph,
- void*) {
- HarfBuzzFontData* hb_font_data =
- reinterpret_cast<HarfBuzzFontData*>(font_data);
- if (hb_font_data->paint_.isVerticalText()) {
- // We don't support cross-stream kerning
- return 0;
- }
-
- SkTypeface* typeface = hb_font_data->paint_.getTypeface();
-
- const uint16_t glyphs[2] = {static_cast<uint16_t>(left_glyph),
- static_cast<uint16_t>(right_glyph)};
- int32_t kerning_adjustments[1] = {0};
-
- if (typeface->getKerningPairAdjustments(glyphs, 2, kerning_adjustments)) {
- SkScalar upm = SkIntToScalar(typeface->getUnitsPerEm());
- SkScalar size = hb_font_data->paint_.getTextSize();
- return SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(
- SkIntToScalar(kerning_adjustments[0]) * size / upm);
- }
-
- return 0;
-}
-
-static hb_bool_t HarfBuzzGetGlyphExtents(hb_font_t* hb_font,
- void* font_data,
- hb_codepoint_t glyph,
- hb_glyph_extents_t* extents,
- void* user_data) {
- HarfBuzzFontData* hb_font_data =
- reinterpret_cast<HarfBuzzFontData*>(font_data);
-
- SkiaTextMetrics(&hb_font_data->paint_)
- .GetGlyphExtentsForHarfBuzz(glyph, extents);
- return true;
-}
-
-static inline bool TableHasSpace(hb_face_t* face,
- hb_set_t* glyphs,
- hb_tag_t tag,
- hb_codepoint_t space) {
- unsigned count = hb_ot_layout_table_get_lookup_count(face, tag);
- for (unsigned i = 0; i < count; i++) {
- hb_ot_layout_lookup_collect_glyphs(face, tag, i, glyphs, glyphs, glyphs,
- nullptr);
- if (hb_set_has(glyphs, space))
- return true;
- }
- return false;
-}
-
-static bool GetSpaceGlyph(hb_font_t* font, hb_codepoint_t& space) {
- return hb_font_get_nominal_glyph(font, kSpaceCharacter, &space);
-}
-
-bool HarfBuzzFace::HasSpaceInLigaturesOrKerning(TypesettingFeatures features) {
- const hb_codepoint_t kInvalidCodepoint = static_cast<hb_codepoint_t>(-1);
- hb_codepoint_t space = kInvalidCodepoint;
-
- HbSetUniquePtr glyphs(hb_set_create());
-
- // Check whether computing is needed and compute for gpos/gsub.
- if (features & kKerning &&
- harf_buzz_font_data_->space_in_gpos_ ==
- HarfBuzzFontData::SpaceGlyphInOpenTypeTables::Unknown) {
- if (space == kInvalidCodepoint && !GetSpaceGlyph(unscaled_font_, space))
- return false;
- // Compute for gpos.
- hb_face_t* face = hb_font_get_face(unscaled_font_);
- DCHECK(face);
- harf_buzz_font_data_->space_in_gpos_ =
- hb_ot_layout_has_positioning(face) &&
- TableHasSpace(face, glyphs.get(), HB_OT_TAG_GPOS, space)
- ? HarfBuzzFontData::SpaceGlyphInOpenTypeTables::Present
- : HarfBuzzFontData::SpaceGlyphInOpenTypeTables::NotPresent;
- }
-
- hb_set_clear(glyphs.get());
-
- if (features & kLigatures &&
- harf_buzz_font_data_->space_in_gsub_ ==
- HarfBuzzFontData::SpaceGlyphInOpenTypeTables::Unknown) {
- if (space == kInvalidCodepoint && !GetSpaceGlyph(unscaled_font_, space))
- return false;
- // Compute for gpos.
- hb_face_t* face = hb_font_get_face(unscaled_font_);
- DCHECK(face);
- harf_buzz_font_data_->space_in_gsub_ =
- hb_ot_layout_has_substitution(face) &&
- TableHasSpace(face, glyphs.get(), HB_OT_TAG_GSUB, space)
- ? HarfBuzzFontData::SpaceGlyphInOpenTypeTables::Present
- : HarfBuzzFontData::SpaceGlyphInOpenTypeTables::NotPresent;
- }
-
- return (features & kKerning &&
- harf_buzz_font_data_->space_in_gpos_ ==
- HarfBuzzFontData::SpaceGlyphInOpenTypeTables::Present) ||
- (features & kLigatures &&
- harf_buzz_font_data_->space_in_gsub_ ==
- HarfBuzzFontData::SpaceGlyphInOpenTypeTables::Present);
-}
-
-unsigned HarfBuzzFace::UnitsPerEmFromHeadTable() {
- hb_face_t* face = hb_font_get_face(unscaled_font_);
- return hb_face_get_upem(face);
-}
-
-bool HarfBuzzFace::ShouldSubpixelPosition() {
- return harf_buzz_font_data_->paint_.isSubpixelText();
-}
-
-static hb_font_funcs_t* HarfBuzzSkiaGetFontFuncs() {
- hb_font_funcs_t* funcs = FontGlobalContext::GetHarfBuzzFontFuncs();
-
- // We don't set callback functions which we can't support.
- // HarfBuzz will use the fallback implementation if they aren't set.
- if (!funcs) {
- funcs = hb_font_funcs_create();
- hb_font_funcs_set_glyph_func(funcs, HarfBuzzGetGlyph, nullptr, nullptr);
- hb_font_funcs_set_glyph_h_advance_func(
- funcs, HarfBuzzGetGlyphHorizontalAdvance, nullptr, nullptr);
- hb_font_funcs_set_glyph_h_kerning_func(
- funcs, HarfBuzzGetGlyphHorizontalKerning, nullptr, nullptr);
- hb_font_funcs_set_glyph_v_advance_func(
- funcs, HarfBuzzGetGlyphVerticalAdvance, nullptr, nullptr);
- hb_font_funcs_set_glyph_v_origin_func(funcs, HarfBuzzGetGlyphVerticalOrigin,
- nullptr, nullptr);
- hb_font_funcs_set_glyph_extents_func(funcs, HarfBuzzGetGlyphExtents,
- nullptr, nullptr);
- hb_font_funcs_make_immutable(funcs);
- FontGlobalContext::SetHarfBuzzFontFuncs(funcs);
- }
- DCHECK(funcs);
- return funcs;
-}
-
-static hb_blob_t* HarfBuzzSkiaGetTable(hb_face_t* face,
- hb_tag_t tag,
- void* user_data) {
- SkTypeface* typeface = reinterpret_cast<SkTypeface*>(user_data);
-
- const size_t table_size = typeface->getTableSize(tag);
- if (!table_size) {
- return nullptr;
- }
-
- char* buffer = reinterpret_cast<char*>(WTF::Partitions::FastMalloc(
- table_size, WTF_HEAP_PROFILER_TYPE_NAME(HarfBuzzFontData)));
- if (!buffer)
- return nullptr;
- size_t actual_size = typeface->getTableData(tag, 0, table_size, buffer);
- if (table_size != actual_size) {
- WTF::Partitions::FastFree(buffer);
- return nullptr;
- }
- return hb_blob_create(const_cast<char*>(buffer), table_size,
- HB_MEMORY_MODE_WRITABLE, buffer,
- WTF::Partitions::FastFree);
-}
-
-static void DeleteTypefaceStream(void* stream_asset_ptr) {
- SkStreamAsset* stream_asset =
- reinterpret_cast<SkStreamAsset*>(stream_asset_ptr);
- delete stream_asset;
-}
-
-hb_face_t* HarfBuzzFace::CreateFace() {
-#if defined(OS_MACOSX)
- // hb_face_t needs to be instantiated using the CoreText constructor for
- // compatibility with AAT font, in which case HarfBuzz' CoreText backend is
- // used. If we encounter a FreeType backed SkTypeface, for variable fonts on
- // Mac OS < 10.12, follow the regular OpenType-only codepath below.
- if (platform_data_->CgFont()) {
- hb_face_t* face = hb_coretext_face_create(platform_data_->CgFont());
- DCHECK(face);
- return face;
- }
-#endif
- hb_face_t* face = nullptr;
-
- DEFINE_THREAD_SAFE_STATIC_LOCAL(BooleanHistogram, zero_copy_success_histogram,
- ("Blink.Fonts.HarfBuzzFaceZeroCopyAccess"));
- SkTypeface* typeface = platform_data_->Typeface();
- CHECK(typeface);
- int ttc_index = 0;
- SkStreamAsset* typeface_stream = typeface->openStream(&ttc_index);
- if (typeface_stream && typeface_stream->getMemoryBase()) {
- std::unique_ptr<hb_blob_t, void (*)(hb_blob_t*)> face_blob(
- hb_blob_create(
- reinterpret_cast<const char*>(typeface_stream->getMemoryBase()),
- typeface_stream->getLength(), HB_MEMORY_MODE_READONLY,
- typeface_stream, DeleteTypefaceStream),
- hb_blob_destroy);
- face = hb_face_create(face_blob.get(), ttc_index);
- }
-
- // Fallback to table copies if there is no in-memory access.
- if (!face) {
- face = hb_face_create_for_tables(HarfBuzzSkiaGetTable,
- platform_data_->Typeface(), nullptr);
- zero_copy_success_histogram.Count(false);
- } else {
- zero_copy_success_histogram.Count(true);
- }
-
- DCHECK(face);
- return face;
-}
-
-scoped_refptr<HbFontCacheEntry> CreateHbFontCacheEntry(hb_face_t* face) {
- HbFontUniquePtr ot_font(hb_font_create(face));
- hb_ot_font_set_funcs(ot_font.get());
- // Creating a sub font means that non-available functions
- // are found from the parent.
- hb_font_t* unscaled_font = hb_font_create_sub_font(ot_font.get());
- scoped_refptr<HbFontCacheEntry> cache_entry =
- HbFontCacheEntry::Create(unscaled_font);
- hb_font_set_funcs(unscaled_font, HarfBuzzSkiaGetFontFuncs(),
- cache_entry->HbFontData(), nullptr);
- return cache_entry;
-}
-
-static_assert(
- std::is_same<decltype(SkFontArguments::VariationPosition::Coordinate::axis),
- decltype(hb_variation_t::tag)>::value &&
- std::is_same<
- decltype(SkFontArguments::VariationPosition::Coordinate::value),
- decltype(hb_variation_t::value)>::value &&
- sizeof(SkFontArguments::VariationPosition::Coordinate) ==
- sizeof(hb_variation_t),
- "Skia and HarfBuzz Variation parameter types must match in structure and "
- "size.");
-
-hb_font_t* HarfBuzzFace::GetScaledFont(
- scoped_refptr<UnicodeRangeSet> range_set,
- VerticalLayoutCallbacks vertical_layout) const {
- PaintFont paint_font;
- platform_data_->SetupPaintFont(&paint_font);
- paint_font.SetTextEncoding(SkPaint::kGlyphID_TextEncoding);
- harf_buzz_font_data_->range_set_ = std::move(range_set);
- harf_buzz_font_data_->UpdateFallbackMetricsAndScale(
- *platform_data_, paint_font.ToSkPaint(), vertical_layout);
-
- int scale =
- SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(platform_data_->size());
- hb_font_set_scale(unscaled_font_, scale, scale);
- hb_font_set_ptem(unscaled_font_, platform_data_->size() / kCssPixelsPerPoint);
-
- SkTypeface* typeface = harf_buzz_font_data_->paint_.getTypeface();
- int axis_count = typeface->getVariationDesignPosition(nullptr, 0);
- if (axis_count > 0) {
- Vector<SkFontArguments::VariationPosition::Coordinate> axis_values;
- axis_values.resize(axis_count);
- if (typeface->getVariationDesignPosition(axis_values.data(),
- axis_values.size()) > 0) {
- hb_font_set_variations(
- unscaled_font_, reinterpret_cast<hb_variation_t*>(axis_values.data()),
- axis_values.size());
- }
- }
-
- return unscaled_font_;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_face.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_face.h
deleted file mode 100644
index 35d81feda56..00000000000
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_face.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARF_BUZZ_FACE_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARF_BUZZ_FACE_H_
-
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/platform/fonts/typesetting_features.h"
-#include "third_party/blink/renderer/platform/fonts/unicode_range_set.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/hash_map.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
-#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
-#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
-
-#include <hb.h>
-
-namespace blink {
-
-class FontPlatformData;
-struct HarfBuzzFontData;
-
-class HarfBuzzFace : public RefCounted<HarfBuzzFace> {
- WTF_MAKE_NONCOPYABLE(HarfBuzzFace);
-
- public:
- static scoped_refptr<HarfBuzzFace> Create(FontPlatformData* platform_data,
- uint64_t unique_id) {
- return base::AdoptRef(new HarfBuzzFace(platform_data, unique_id));
- }
- ~HarfBuzzFace();
-
- enum VerticalLayoutCallbacks { PrepareForVerticalLayout, NoVerticalLayout };
-
- // In order to support the restricting effect of unicode-range optionally a
- // range restriction can be passed in, which will restrict which glyphs we
- // return in the harfBuzzGetGlyph function.
- hb_font_t* GetScaledFont(scoped_refptr<UnicodeRangeSet>,
- VerticalLayoutCallbacks) const;
-
- bool HasSpaceInLigaturesOrKerning(TypesettingFeatures);
- unsigned UnitsPerEmFromHeadTable();
-
- bool ShouldSubpixelPosition();
-
- private:
- HarfBuzzFace(FontPlatformData*, uint64_t);
-
- hb_face_t* CreateFace();
- void PrepareHarfBuzzFontData();
-
- FontPlatformData* platform_data_;
- uint64_t unique_id_;
- hb_font_t* unscaled_font_;
- HarfBuzzFontData* harf_buzz_font_data_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARF_BUZZ_FACE_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_font_cache.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_font_cache.h
deleted file mode 100644
index a25f2532a92..00000000000
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_font_cache.h
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARF_BUZZ_FONT_CACHE_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARF_BUZZ_FONT_CACHE_H_
-
-#include <memory>
-#include "third_party/blink/renderer/platform/fonts/font_metrics.h"
-#include "third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_face.h"
-#include "third_party/blink/renderer/platform/fonts/unicode_range_set.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-
-struct hb_font_t;
-struct hb_face_t;
-
-namespace blink {
-
-struct HbFontDeleter {
- void operator()(hb_font_t* font);
-};
-
-using HbFontUniquePtr = std::unique_ptr<hb_font_t, HbFontDeleter>;
-
-struct HbFaceDeleter {
- void operator()(hb_face_t* face);
-};
-
-using HbFaceUniquePtr = std::unique_ptr<hb_face_t, HbFaceDeleter>;
-
-const unsigned kInvalidFallbackMetricsValue = static_cast<unsigned>(-1);
-
-// struct to carry user-pointer data for hb_font_t callback
-// functions/operations, that require information related to a font scaled to a
-// particular size.
-struct HarfBuzzFontData {
- USING_FAST_MALLOC(HarfBuzzFontData);
- WTF_MAKE_NONCOPYABLE(HarfBuzzFontData);
-
- public:
- HarfBuzzFontData()
- : paint_(),
- space_in_gpos_(SpaceGlyphInOpenTypeTables::Unknown),
- space_in_gsub_(SpaceGlyphInOpenTypeTables::Unknown),
- vertical_data_(nullptr),
- range_set_(nullptr) {}
-
- // The vertical origin and vertical advance functions in HarfBuzzFace require
- // the ascent and height metrics as fallback in case no specific vertical
- // layout information is found from the font.
- void UpdateFallbackMetricsAndScale(
- const FontPlatformData& platform_data,
- const SkPaint& paint,
- HarfBuzzFace::VerticalLayoutCallbacks vertical_layout) {
- float ascent = 0;
- float descent = 0;
- unsigned dummy_ascent_inflation = 0;
- unsigned dummy_descent_inflation = 0;
-
- paint_ = paint;
-
- if (UNLIKELY(vertical_layout == HarfBuzzFace::PrepareForVerticalLayout)) {
- FontMetrics::AscentDescentWithHacks(
- ascent, descent, dummy_ascent_inflation, dummy_descent_inflation,
- platform_data, paint);
- ascent_fallback_ = ascent;
- // Simulate the rounding that FontMetrics does so far for returning the
- // integer Height()
- height_fallback_ = lroundf(ascent) + lroundf(descent);
-
- int units_per_em =
- platform_data.GetHarfBuzzFace()->UnitsPerEmFromHeadTable();
- if (!units_per_em) {
- DLOG(ERROR)
- << "Units per EM is 0 for font used in vertical writing mode.";
- }
- size_per_unit_ = platform_data.size() / (units_per_em ? units_per_em : 1);
- } else {
- ascent_fallback_ = kInvalidFallbackMetricsValue;
- height_fallback_ = kInvalidFallbackMetricsValue;
- size_per_unit_ = kInvalidFallbackMetricsValue;
- }
- }
-
- scoped_refptr<OpenTypeVerticalData> VerticalData() {
- if (!vertical_data_) {
- DCHECK_NE(ascent_fallback_, kInvalidFallbackMetricsValue);
- DCHECK_NE(height_fallback_, kInvalidFallbackMetricsValue);
- DCHECK_NE(size_per_unit_, kInvalidFallbackMetricsValue);
-
- vertical_data_ =
- OpenTypeVerticalData::CreateUnscaled(paint_.refTypeface());
- }
- vertical_data_->SetScaleAndFallbackMetrics(size_per_unit_, ascent_fallback_,
- height_fallback_);
- return vertical_data_;
- }
-
- SkPaint paint_;
-
- // Capture these scaled fallback metrics from FontPlatformData so that a
- // OpenTypeVerticalData object can be constructed from them when needed.
- float size_per_unit_;
- float ascent_fallback_;
- float height_fallback_;
-
- enum class SpaceGlyphInOpenTypeTables { Unknown, Present, NotPresent };
-
- SpaceGlyphInOpenTypeTables space_in_gpos_;
- SpaceGlyphInOpenTypeTables space_in_gsub_;
-
- scoped_refptr<OpenTypeVerticalData> vertical_data_;
- scoped_refptr<UnicodeRangeSet> range_set_;
-};
-
-// Though we have FontCache class, which provides the cache mechanism for
-// WebKit's font objects, we also need additional caching layer for HarfBuzz to
-// reduce the number of hb_font_t objects created. Without it, we would create
-// an hb_font_t object for every FontPlatformData object. But insted, we only
-// need one for each unique SkTypeface.
-// FIXME, crbug.com/609099: We should fix the FontCache to only keep one
-// FontPlatformData object independent of size, then consider using this here.
-class HbFontCacheEntry : public RefCounted<HbFontCacheEntry> {
- public:
- static scoped_refptr<HbFontCacheEntry> Create(hb_font_t* hb_font) {
- DCHECK(hb_font);
- return base::AdoptRef(new HbFontCacheEntry(hb_font));
- }
-
- hb_font_t* HbFont() { return hb_font_.get(); }
- HarfBuzzFontData* HbFontData() { return hb_font_data_.get(); }
-
- private:
- explicit HbFontCacheEntry(hb_font_t* font)
- : hb_font_(HbFontUniquePtr(font)),
- hb_font_data_(std::make_unique<HarfBuzzFontData>()){};
-
- HbFontUniquePtr hb_font_;
- std::unique_ptr<HarfBuzzFontData> hb_font_data_;
-};
-
-typedef HashMap<uint64_t,
- scoped_refptr<HbFontCacheEntry>,
- WTF::IntHash<uint64_t>,
- WTF::UnsignedWithZeroKeyHashTraits<uint64_t>>
- HarfBuzzFontCache;
-
-} // namespace blink
-
-#endif
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.cc
deleted file mode 100644
index 352e502dd47..00000000000
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.cc
+++ /dev/null
@@ -1,974 +0,0 @@
-/*
- * Copyright (c) 2012 Google Inc. All rights reserved.
- * Copyright (C) 2013 BlackBerry Limited. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.h"
-
-#include <hb.h>
-#include <unicode/uchar.h>
-#include <unicode/uscript.h>
-#include <algorithm>
-#include <memory>
-#include <utility>
-
-#include "base/memory/ptr_util.h"
-#include "third_party/blink/renderer/platform/fonts/font.h"
-#include "third_party/blink/renderer/platform/fonts/font_description.h"
-#include "third_party/blink/renderer/platform/fonts/font_fallback_iterator.h"
-#include "third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/case_mapping_harf_buzz_buffer_filler.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_face.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h"
-#include "third_party/blink/renderer/platform/fonts/small_caps_iterator.h"
-#include "third_party/blink/renderer/platform/fonts/utf16_text_iterator.h"
-#include "third_party/blink/renderer/platform/wtf/compiler.h"
-#include "third_party/blink/renderer/platform/wtf/deque.h"
-#include "third_party/blink/renderer/platform/wtf/math_extras.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
-#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
-
-namespace blink {
-
-namespace {
-
-#if DCHECK_IS_ON()
-// Check if the ShapeResult has the specified range.
-// |text| and |font| are only for logging.
-void CheckShapeResultRange(const ShapeResult* result,
- unsigned start,
- unsigned end,
- const UChar* text,
- const Font* font) {
- DCHECK_LE(start, end);
- unsigned length = end - start;
- if (length == result->NumCharacters() &&
- (!length || (start == result->StartIndexForResult() &&
- end == result->EndIndexForResult())))
- return;
-
- // Log font-family/size as specified.
- StringBuilder log;
- log.Append("Font='");
- const FontDescription& font_description = font->GetFontDescription();
- for (const FontFamily* family = &font_description.Family();;) {
- log.Append(family->Family());
- family = family->Next();
- if (!family)
- break;
- log.Append(", ");
- }
- log.Append(String::Format("', %f", font_description.ComputedSize()));
-
- // Log the primary font with its family name in the font file.
- const SimpleFontData* font_data = font->PrimaryFont();
- if (font_data) {
- const SkTypeface* typeface = font_data->PlatformData().Typeface();
- SkString family_name;
- typeface->getFamilyName(&family_name);
- log.Append(", primary=");
- log.Append(family_name.c_str());
- }
-
- // Log the text to shape.
- log.Append(String::Format(": %u-%u -> %u-%u:", start, end,
- result->StartIndexForResult(),
- result->EndIndexForResult()));
- for (unsigned i = start; i < end; ++i)
- log.Append(String::Format(" %02X", text[i]));
-
- log.Append(", result=");
- result->ToString(&log);
-
- NOTREACHED() << log.ToString();
-}
-#endif
-
-} // namespace
-
-enum ReshapeQueueItemAction { kReshapeQueueNextFont, kReshapeQueueRange };
-
-struct ReshapeQueueItem {
- DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
- ReshapeQueueItemAction action_;
- unsigned start_index_;
- unsigned num_characters_;
- ReshapeQueueItem(ReshapeQueueItemAction action, unsigned start, unsigned num)
- : action_(action), start_index_(start), num_characters_(num){};
-};
-
-template <typename T>
-class HarfBuzzScopedPtr {
- STACK_ALLOCATED();
- WTF_MAKE_NONCOPYABLE(HarfBuzzScopedPtr);
-
- public:
- typedef void (*DestroyFunction)(T*);
-
- HarfBuzzScopedPtr(T* ptr, DestroyFunction destroy)
- : ptr_(ptr), destroy_(destroy) {
- DCHECK(destroy_);
- }
- ~HarfBuzzScopedPtr() {
- if (ptr_)
- (*destroy_)(ptr_);
- }
-
- T* Get() { return ptr_; }
- void Set(T* ptr) { ptr_ = ptr; }
-
- private:
- T* ptr_;
- DestroyFunction destroy_;
-};
-
-HarfBuzzShaper::HarfBuzzShaper(const UChar* text, unsigned length)
- : text_(text), text_length_(length) {}
-
-using FeaturesVector = Vector<hb_feature_t, 6>;
-struct RangeData {
- hb_buffer_t* buffer;
- const Font* font;
- TextDirection text_direction;
- unsigned start;
- unsigned end;
- FeaturesVector font_features;
- Deque<ReshapeQueueItem> reshape_queue;
-
- hb_direction_t HarfBuzzDirection(CanvasRotationInVertical canvas_rotation) {
- FontOrientation orientation = font->GetFontDescription().Orientation();
- hb_direction_t direction =
- IsVerticalAnyUpright(orientation) &&
- (canvas_rotation ==
- CanvasRotationInVertical::kRotateCanvasUpright)
- ? HB_DIRECTION_TTB
- : HB_DIRECTION_LTR;
- return text_direction == TextDirection::kRtl
- ? HB_DIRECTION_REVERSE(direction)
- : direction;
- }
-};
-
-struct BufferSlice {
- unsigned start_character_index;
- unsigned num_characters;
- unsigned start_glyph_index;
- unsigned num_glyphs;
-};
-
-namespace {
-
-// A port of hb_icu_script_to_script because harfbuzz on CrOS is built
-// without hb-icu. See http://crbug.com/356929
-static inline hb_script_t ICUScriptToHBScript(UScriptCode script) {
- if (UNLIKELY(script == USCRIPT_INVALID_CODE))
- return HB_SCRIPT_INVALID;
-
- return hb_script_from_string(uscript_getShortName(script), -1);
-}
-
-void RoundHarfBuzzPosition(hb_position_t* value) {
- if ((*value) & 0xFFFF) {
- // There is a non-zero fractional part in the 16.16 value.
- *value = static_cast<hb_position_t>(
- round(static_cast<float>(*value) / (1 << 16)))
- << 16;
- }
-}
-
-void RoundHarfBuzzBufferPositions(hb_buffer_t* buffer) {
- unsigned int len;
- hb_glyph_position_t* glyph_positions =
- hb_buffer_get_glyph_positions(buffer, &len);
- for (unsigned int i = 0; i < len; i++) {
- hb_glyph_position_t* pos = &glyph_positions[i];
- RoundHarfBuzzPosition(&pos->x_offset);
- RoundHarfBuzzPosition(&pos->y_offset);
- RoundHarfBuzzPosition(&pos->x_advance);
- RoundHarfBuzzPosition(&pos->y_advance);
- }
-}
-
-inline bool ShapeRange(hb_buffer_t* buffer,
- hb_feature_t* font_features,
- unsigned font_features_size,
- const SimpleFontData* current_font,
- scoped_refptr<UnicodeRangeSet> current_font_range_set,
- UScriptCode current_run_script,
- hb_direction_t direction,
- hb_language_t language) {
- const FontPlatformData* platform_data = &(current_font->PlatformData());
- HarfBuzzFace* face = platform_data->GetHarfBuzzFace();
- if (!face) {
- DLOG(ERROR) << "Could not create HarfBuzzFace from FontPlatformData.";
- return false;
- }
-
- hb_buffer_set_language(buffer, language);
- hb_buffer_set_script(buffer, ICUScriptToHBScript(current_run_script));
- hb_buffer_set_direction(buffer, direction);
-
- hb_font_t* hb_font =
- face->GetScaledFont(std::move(current_font_range_set),
- HB_DIRECTION_IS_VERTICAL(direction)
- ? HarfBuzzFace::PrepareForVerticalLayout
- : HarfBuzzFace::NoVerticalLayout);
- hb_shape(hb_font, buffer, font_features, font_features_size);
-
- // We cannot round all glyph positions during hb_shape because the
- // hb_font_funcs_set_glyph_h_kerning_func only works for legacy kerning.
- // OpenType uses gpos tables for kerning and harfbuzz does not call
- // the callback to let us round as we go.
- // Without this rounding, we get inconsistent spacing between kern points
- // if subpixel positioning is disabled.
- // See http://crbug.com/740385.
- if (!face->ShouldSubpixelPosition())
- RoundHarfBuzzBufferPositions(buffer);
-
- return true;
-}
-
-BufferSlice ComputeSlice(RangeData* range_data,
- const ReshapeQueueItem& current_queue_item,
- const hb_glyph_info_t* glyph_info,
- unsigned num_glyphs,
- unsigned old_glyph_index,
- unsigned new_glyph_index) {
- // Compute the range indices of consecutive shaped or .notdef glyphs.
- // Cluster information for RTL runs becomes reversed, e.g. glyph 0
- // has cluster index 5 in a run of 6 characters.
- BufferSlice result;
- result.start_glyph_index = old_glyph_index;
- result.num_glyphs = new_glyph_index - old_glyph_index;
-
- if (HB_DIRECTION_IS_FORWARD(hb_buffer_get_direction(range_data->buffer))) {
- result.start_character_index = glyph_info[old_glyph_index].cluster;
- if (new_glyph_index == num_glyphs) {
- // Clamp the end offsets of the queue item to the offsets representing
- // the shaping window.
- unsigned shape_end =
- std::min(range_data->end, current_queue_item.start_index_ +
- current_queue_item.num_characters_);
- result.num_characters = shape_end - result.start_character_index;
- } else {
- result.num_characters =
- glyph_info[new_glyph_index].cluster - result.start_character_index;
- }
- } else {
- // Direction Backwards
- result.start_character_index = glyph_info[new_glyph_index - 1].cluster;
- if (old_glyph_index == 0) {
- // Clamp the end offsets of the queue item to the offsets representing
- // the shaping window.
- unsigned shape_end =
- std::min(range_data->end, current_queue_item.start_index_ +
- current_queue_item.num_characters_);
- result.num_characters = shape_end - result.start_character_index;
- } else {
- result.num_characters = glyph_info[old_glyph_index - 1].cluster -
- glyph_info[new_glyph_index - 1].cluster;
- }
- }
-
- return result;
-}
-
-void QueueCharacters(RangeData* range_data,
- const SimpleFontData* current_font,
- bool& font_cycle_queued,
- const BufferSlice& slice) {
- if (!font_cycle_queued) {
- range_data->reshape_queue.push_back(
- ReshapeQueueItem(kReshapeQueueNextFont, 0, 0));
- font_cycle_queued = true;
- }
-
- DCHECK(slice.num_characters);
- range_data->reshape_queue.push_back(ReshapeQueueItem(
- kReshapeQueueRange, slice.start_character_index, slice.num_characters));
-}
-
-CanvasRotationInVertical CanvasRotationForRun(
- FontOrientation font_orientation,
- OrientationIterator::RenderOrientation render_orientation) {
- if (font_orientation == FontOrientation::kVerticalUpright ||
- (font_orientation == FontOrientation::kVerticalMixed &&
- render_orientation == OrientationIterator::kOrientationKeep))
- return CanvasRotationInVertical::kRotateCanvasUpright;
- return CanvasRotationInVertical::kRegular;
-}
-
-} // namespace
-
-void HarfBuzzShaper::CommitGlyphs(RangeData* range_data,
- const SimpleFontData* current_font,
- UScriptCode current_run_script,
- CanvasRotationInVertical canvas_rotation,
- bool is_last_resort,
- const BufferSlice& slice,
- ShapeResult* shape_result) const {
- hb_direction_t direction = range_data->HarfBuzzDirection(canvas_rotation);
- // Here we need to specify glyph positions.
- ShapeResult::RunInfo* run = new ShapeResult::RunInfo(
- current_font, direction, canvas_rotation,
- ICUScriptToHBScript(current_run_script), slice.start_character_index,
- slice.num_glyphs, slice.num_characters);
- shape_result->InsertRun(base::WrapUnique(run), slice.start_glyph_index,
- slice.num_glyphs, range_data->buffer);
- if (is_last_resort)
- range_data->font->ReportNotDefGlyph();
-}
-
-void HarfBuzzShaper::ExtractShapeResults(
- RangeData* range_data,
- bool& font_cycle_queued,
- const ReshapeQueueItem& current_queue_item,
- const SimpleFontData* current_font,
- UScriptCode current_run_script,
- CanvasRotationInVertical canvas_rotation,
- bool is_last_resort,
- ShapeResult* shape_result) const {
- enum ClusterResult { kShaped, kNotDef, kUnknown };
- ClusterResult current_cluster_result = kUnknown;
- ClusterResult previous_cluster_result = kUnknown;
- unsigned previous_cluster = 0;
- unsigned current_cluster = 0;
-
- // Find first notdef glyph in buffer.
- unsigned num_glyphs = hb_buffer_get_length(range_data->buffer);
- hb_glyph_info_t* glyph_info =
- hb_buffer_get_glyph_infos(range_data->buffer, nullptr);
-
- unsigned last_change_glyph_index = 0;
- unsigned previous_cluster_start_glyph_index = 0;
-
- if (!num_glyphs)
- return;
-
- for (unsigned glyph_index = 0; glyph_index < num_glyphs; ++glyph_index) {
- // We proceed by full clusters and determine a shaping result - either
- // kShaped or kNotDef for each cluster.
- ClusterResult glyph_result =
- glyph_info[glyph_index].codepoint == 0 ? kNotDef : kShaped;
- previous_cluster = current_cluster;
- current_cluster = glyph_info[glyph_index].cluster;
-
- if (current_cluster != previous_cluster) {
- // We are transitioning to a new cluster (whose shaping result state we
- // have not looked at yet). This means the cluster we just looked at is
- // completely analysed and we can determine whether it was fully shaped
- // and whether that means a state change to the cluster before that one.
- if ((previous_cluster_result != current_cluster_result) &&
- previous_cluster_result != kUnknown) {
- BufferSlice slice = ComputeSlice(
- range_data, current_queue_item, glyph_info, num_glyphs,
- last_change_glyph_index, previous_cluster_start_glyph_index);
- // If the most recent cluster is shaped and there is a state change,
- // it means the previous ones were unshaped, so we queue them, unless
- // we're using the last resort font.
- if (current_cluster_result == kShaped && !is_last_resort) {
- QueueCharacters(range_data, current_font, font_cycle_queued, slice);
- } else {
- // If the most recent cluster is unshaped and there is a state
- // change, it means the previous one(s) were shaped, so we commit
- // the glyphs. We also commit when we've reached the last resort
- // font.
- CommitGlyphs(range_data, current_font, current_run_script,
- canvas_rotation, is_last_resort, slice, shape_result);
- }
- last_change_glyph_index = previous_cluster_start_glyph_index;
- }
-
- // No state change happened, continue.
- previous_cluster_result = current_cluster_result;
- previous_cluster_start_glyph_index = glyph_index;
- // Reset current cluster result.
- current_cluster_result = glyph_result;
- } else {
- // Update and merge current cluster result.
- current_cluster_result =
- glyph_result == kShaped && (current_cluster_result == kShaped ||
- current_cluster_result == kUnknown)
- ? kShaped
- : kNotDef;
- }
- }
-
- // End of the run.
- if (current_cluster_result != previous_cluster_result &&
- previous_cluster_result != kUnknown && !is_last_resort) {
- // The last cluster in the run still had shaping status different from
- // the cluster(s) before it, we need to submit one shaped and one
- // unshaped segment.
- if (current_cluster_result == kShaped) {
- BufferSlice slice = ComputeSlice(
- range_data, current_queue_item, glyph_info, num_glyphs,
- last_change_glyph_index, previous_cluster_start_glyph_index);
- QueueCharacters(range_data, current_font, font_cycle_queued, slice);
- slice =
- ComputeSlice(range_data, current_queue_item, glyph_info, num_glyphs,
- previous_cluster_start_glyph_index, num_glyphs);
- CommitGlyphs(range_data, current_font, current_run_script,
- canvas_rotation, is_last_resort, slice, shape_result);
- } else {
- BufferSlice slice = ComputeSlice(
- range_data, current_queue_item, glyph_info, num_glyphs,
- last_change_glyph_index, previous_cluster_start_glyph_index);
- CommitGlyphs(range_data, current_font, current_run_script,
- canvas_rotation, is_last_resort, slice, shape_result);
- slice =
- ComputeSlice(range_data, current_queue_item, glyph_info, num_glyphs,
- previous_cluster_start_glyph_index, num_glyphs);
- QueueCharacters(range_data, current_font, font_cycle_queued, slice);
- }
- } else {
- // There hasn't been a state change for the last cluster, so we can just
- // either commit or queue what we have up until here.
- BufferSlice slice =
- ComputeSlice(range_data, current_queue_item, glyph_info, num_glyphs,
- last_change_glyph_index, num_glyphs);
- if (current_cluster_result == kNotDef && !is_last_resort) {
- QueueCharacters(range_data, current_font, font_cycle_queued, slice);
- } else {
- CommitGlyphs(range_data, current_font, current_run_script,
- canvas_rotation, is_last_resort, slice, shape_result);
- }
- }
-}
-
-bool HarfBuzzShaper::CollectFallbackHintChars(
- const Deque<ReshapeQueueItem>& reshape_queue,
- Vector<UChar32>& hint) const {
- if (!reshape_queue.size())
- return false;
-
- hint.clear();
-
- size_t num_chars_added = 0;
- for (auto it = reshape_queue.begin(); it != reshape_queue.end(); ++it) {
- if (it->action_ == kReshapeQueueNextFont)
- break;
-
- UChar32 hint_char;
- CHECK_LE((it->start_index_ + it->num_characters_), text_length_);
- UTF16TextIterator iterator(text_ + it->start_index_, it->num_characters_);
- while (iterator.Consume(hint_char)) {
- hint.push_back(hint_char);
- num_chars_added++;
- iterator.Advance();
- }
- }
- return num_chars_added > 0;
-}
-
-namespace {
-
-void SplitUntilNextCaseChange(
- const UChar* normalized_buffer,
- Deque<blink::ReshapeQueueItem>* queue,
- blink::ReshapeQueueItem& current_queue_item,
- SmallCapsIterator::SmallCapsBehavior& small_caps_behavior) {
- unsigned num_characters_until_case_change = 0;
- SmallCapsIterator small_caps_iterator(
- normalized_buffer + current_queue_item.start_index_,
- current_queue_item.num_characters_);
- small_caps_iterator.Consume(&num_characters_until_case_change,
- &small_caps_behavior);
- if (num_characters_until_case_change > 0 &&
- num_characters_until_case_change < current_queue_item.num_characters_) {
- queue->push_front(blink::ReshapeQueueItem(
- blink::ReshapeQueueItemAction::kReshapeQueueRange,
- current_queue_item.start_index_ + num_characters_until_case_change,
- current_queue_item.num_characters_ - num_characters_until_case_change));
- current_queue_item.num_characters_ = num_characters_until_case_change;
- }
-}
-
-hb_feature_t CreateFeature(hb_tag_t tag, uint32_t value = 0) {
- return {tag, value, 0 /* start */, static_cast<unsigned>(-1) /* end */};
-}
-
-// TODO(kojii): crbug.com/762493 This list is getting long enough to extract out
-// of HarfBuzzShaper.cpp.
-void SetFontFeatures(const Font* font, FeaturesVector* features) {
- const FontDescription& description = font->GetFontDescription();
-
- static hb_feature_t no_kern = CreateFeature(HB_TAG('k', 'e', 'r', 'n'));
- static hb_feature_t no_vkrn = CreateFeature(HB_TAG('v', 'k', 'r', 'n'));
- switch (description.GetKerning()) {
- case FontDescription::kNormalKerning:
- // kern/vkrn are enabled by default
- break;
- case FontDescription::kNoneKerning:
- features->push_back(description.IsVerticalAnyUpright() ? no_vkrn
- : no_kern);
- break;
- case FontDescription::kAutoKerning:
- break;
- }
-
- static hb_feature_t no_clig = CreateFeature(HB_TAG('c', 'l', 'i', 'g'));
- static hb_feature_t no_liga = CreateFeature(HB_TAG('l', 'i', 'g', 'a'));
- switch (description.CommonLigaturesState()) {
- case FontDescription::kDisabledLigaturesState:
- features->push_back(no_liga);
- features->push_back(no_clig);
- break;
- case FontDescription::kEnabledLigaturesState:
- // liga and clig are on by default
- break;
- case FontDescription::kNormalLigaturesState:
- break;
- }
- static hb_feature_t dlig = CreateFeature(HB_TAG('d', 'l', 'i', 'g'), 1);
- switch (description.DiscretionaryLigaturesState()) {
- case FontDescription::kDisabledLigaturesState:
- // dlig is off by default
- break;
- case FontDescription::kEnabledLigaturesState:
- features->push_back(dlig);
- break;
- case FontDescription::kNormalLigaturesState:
- break;
- }
- static hb_feature_t hlig = CreateFeature(HB_TAG('h', 'l', 'i', 'g'), 1);
- switch (description.HistoricalLigaturesState()) {
- case FontDescription::kDisabledLigaturesState:
- // hlig is off by default
- break;
- case FontDescription::kEnabledLigaturesState:
- features->push_back(hlig);
- break;
- case FontDescription::kNormalLigaturesState:
- break;
- }
- static hb_feature_t no_calt = CreateFeature(HB_TAG('c', 'a', 'l', 't'));
- switch (description.ContextualLigaturesState()) {
- case FontDescription::kDisabledLigaturesState:
- features->push_back(no_calt);
- break;
- case FontDescription::kEnabledLigaturesState:
- // calt is on by default
- break;
- case FontDescription::kNormalLigaturesState:
- break;
- }
-
- static hb_feature_t hwid = CreateFeature(HB_TAG('h', 'w', 'i', 'd'), 1);
- static hb_feature_t twid = CreateFeature(HB_TAG('t', 'w', 'i', 'd'), 1);
- static hb_feature_t qwid = CreateFeature(HB_TAG('q', 'w', 'i', 'd'), 1);
- switch (description.WidthVariant()) {
- case kHalfWidth:
- features->push_back(hwid);
- break;
- case kThirdWidth:
- features->push_back(twid);
- break;
- case kQuarterWidth:
- features->push_back(qwid);
- break;
- case kRegularWidth:
- break;
- }
-
- // font-variant-east-asian:
- const FontVariantEastAsian east_asian = description.VariantEastAsian();
- if (UNLIKELY(!east_asian.IsAllNormal())) {
- static hb_feature_t jp78 = CreateFeature(HB_TAG('j', 'p', '7', '8'), 1);
- static hb_feature_t jp83 = CreateFeature(HB_TAG('j', 'p', '8', '3'), 1);
- static hb_feature_t jp90 = CreateFeature(HB_TAG('j', 'p', '9', '0'), 1);
- static hb_feature_t jp04 = CreateFeature(HB_TAG('j', 'p', '0', '4'), 1);
- static hb_feature_t smpl = CreateFeature(HB_TAG('s', 'm', 'p', 'l'), 1);
- static hb_feature_t trad = CreateFeature(HB_TAG('t', 'r', 'a', 'd'), 1);
- switch (east_asian.Form()) {
- case FontVariantEastAsian::kNormalForm:
- break;
- case FontVariantEastAsian::kJis78:
- features->push_back(jp78);
- break;
- case FontVariantEastAsian::kJis83:
- features->push_back(jp83);
- break;
- case FontVariantEastAsian::kJis90:
- features->push_back(jp90);
- break;
- case FontVariantEastAsian::kJis04:
- features->push_back(jp04);
- break;
- case FontVariantEastAsian::kSimplified:
- features->push_back(smpl);
- break;
- case FontVariantEastAsian::kTraditional:
- features->push_back(trad);
- break;
- default:
- NOTREACHED();
- }
- static hb_feature_t fwid = CreateFeature(HB_TAG('f', 'w', 'i', 'd'), 1);
- static hb_feature_t pwid = CreateFeature(HB_TAG('p', 'w', 'i', 'd'), 1);
- switch (east_asian.Width()) {
- case FontVariantEastAsian::kNormalWidth:
- break;
- case FontVariantEastAsian::kFullWidth:
- features->push_back(fwid);
- break;
- case FontVariantEastAsian::kProportionalWidth:
- features->push_back(pwid);
- break;
- default:
- NOTREACHED();
- }
- static hb_feature_t ruby = CreateFeature(HB_TAG('r', 'u', 'b', 'y'), 1);
- if (east_asian.Ruby())
- features->push_back(ruby);
- }
-
- // font-variant-numeric:
- static hb_feature_t lnum = CreateFeature(HB_TAG('l', 'n', 'u', 'm'), 1);
- if (description.VariantNumeric().NumericFigureValue() ==
- FontVariantNumeric::kLiningNums)
- features->push_back(lnum);
-
- static hb_feature_t onum = CreateFeature(HB_TAG('o', 'n', 'u', 'm'), 1);
- if (description.VariantNumeric().NumericFigureValue() ==
- FontVariantNumeric::kOldstyleNums)
- features->push_back(onum);
-
- static hb_feature_t pnum = CreateFeature(HB_TAG('p', 'n', 'u', 'm'), 1);
- if (description.VariantNumeric().NumericSpacingValue() ==
- FontVariantNumeric::kProportionalNums)
- features->push_back(pnum);
- static hb_feature_t tnum = CreateFeature(HB_TAG('t', 'n', 'u', 'm'), 1);
- if (description.VariantNumeric().NumericSpacingValue() ==
- FontVariantNumeric::kTabularNums)
- features->push_back(tnum);
-
- static hb_feature_t afrc = CreateFeature(HB_TAG('a', 'f', 'r', 'c'), 1);
- if (description.VariantNumeric().NumericFractionValue() ==
- FontVariantNumeric::kStackedFractions)
- features->push_back(afrc);
- static hb_feature_t frac = CreateFeature(HB_TAG('f', 'r', 'a', 'c'), 1);
- if (description.VariantNumeric().NumericFractionValue() ==
- FontVariantNumeric::kDiagonalFractions)
- features->push_back(frac);
-
- static hb_feature_t ordn = CreateFeature(HB_TAG('o', 'r', 'd', 'n'), 1);
- if (description.VariantNumeric().OrdinalValue() ==
- FontVariantNumeric::kOrdinalOn)
- features->push_back(ordn);
-
- static hb_feature_t zero = CreateFeature(HB_TAG('z', 'e', 'r', 'o'), 1);
- if (description.VariantNumeric().SlashedZeroValue() ==
- FontVariantNumeric::kSlashedZeroOn)
- features->push_back(zero);
-
- FontFeatureSettings* settings = description.FeatureSettings();
- if (!settings)
- return;
-
- // TODO(drott): crbug.com/450619 Implement feature resolution instead of
- // just appending the font-feature-settings.
- unsigned num_features = settings->size();
- for (unsigned i = 0; i < num_features; ++i) {
- hb_feature_t feature;
- const AtomicString& tag = settings->at(i).Tag();
- feature.tag = HB_TAG(tag[0], tag[1], tag[2], tag[3]);
- feature.value = settings->at(i).Value();
- feature.start = 0;
- feature.end = static_cast<unsigned>(-1);
- features->push_back(feature);
- }
-}
-
-class CapsFeatureSettingsScopedOverlay final {
- STACK_ALLOCATED();
-
- public:
- CapsFeatureSettingsScopedOverlay(FeaturesVector*,
- FontDescription::FontVariantCaps);
- CapsFeatureSettingsScopedOverlay() = delete;
- ~CapsFeatureSettingsScopedOverlay();
-
- private:
- void OverlayCapsFeatures(FontDescription::FontVariantCaps);
- void PrependCounting(const hb_feature_t&);
- FeaturesVector* features_;
- size_t count_features_;
-};
-
-CapsFeatureSettingsScopedOverlay::CapsFeatureSettingsScopedOverlay(
- FeaturesVector* features,
- FontDescription::FontVariantCaps variant_caps)
- : features_(features), count_features_(0) {
- OverlayCapsFeatures(variant_caps);
-}
-
-void CapsFeatureSettingsScopedOverlay::OverlayCapsFeatures(
- FontDescription::FontVariantCaps variant_caps) {
- static hb_feature_t smcp = CreateFeature(HB_TAG('s', 'm', 'c', 'p'), 1);
- static hb_feature_t pcap = CreateFeature(HB_TAG('p', 'c', 'a', 'p'), 1);
- static hb_feature_t c2sc = CreateFeature(HB_TAG('c', '2', 's', 'c'), 1);
- static hb_feature_t c2pc = CreateFeature(HB_TAG('c', '2', 'p', 'c'), 1);
- static hb_feature_t unic = CreateFeature(HB_TAG('u', 'n', 'i', 'c'), 1);
- static hb_feature_t titl = CreateFeature(HB_TAG('t', 'i', 't', 'l'), 1);
- if (variant_caps == FontDescription::kSmallCaps ||
- variant_caps == FontDescription::kAllSmallCaps) {
- PrependCounting(smcp);
- if (variant_caps == FontDescription::kAllSmallCaps) {
- PrependCounting(c2sc);
- }
- }
- if (variant_caps == FontDescription::kPetiteCaps ||
- variant_caps == FontDescription::kAllPetiteCaps) {
- PrependCounting(pcap);
- if (variant_caps == FontDescription::kAllPetiteCaps) {
- PrependCounting(c2pc);
- }
- }
- if (variant_caps == FontDescription::kUnicase) {
- PrependCounting(unic);
- }
- if (variant_caps == FontDescription::kTitlingCaps) {
- PrependCounting(titl);
- }
-}
-
-void CapsFeatureSettingsScopedOverlay::PrependCounting(
- const hb_feature_t& feature) {
- features_->push_front(feature);
- count_features_++;
-}
-
-CapsFeatureSettingsScopedOverlay::~CapsFeatureSettingsScopedOverlay() {
- features_->EraseAt(0, count_features_);
-}
-
-} // namespace
-
-void HarfBuzzShaper::ShapeSegment(RangeData* range_data,
- RunSegmenter::RunSegmenterRange segment,
- ShapeResult* result) const {
- DCHECK(result);
- DCHECK(range_data->buffer);
-
- const Font* font = range_data->font;
- const FontDescription& font_description = font->GetFontDescription();
- const hb_language_t language =
- font_description.LocaleOrDefault().HarfbuzzLanguage();
- bool needs_caps_handling =
- font_description.VariantCaps() != FontDescription::kCapsNormal;
- OpenTypeCapsSupport caps_support;
-
- scoped_refptr<FontFallbackIterator> fallback_iterator =
- font->CreateFontFallbackIterator(segment.font_fallback_priority);
-
- range_data->reshape_queue.push_back(
- ReshapeQueueItem(kReshapeQueueNextFont, 0, 0));
- range_data->reshape_queue.push_back(ReshapeQueueItem(
- kReshapeQueueRange, segment.start, segment.end - segment.start));
-
- bool font_cycle_queued = false;
- Vector<UChar32> fallback_chars_hint;
- scoped_refptr<FontDataForRangeSet> current_font_data_for_range_set;
- while (range_data->reshape_queue.size()) {
- ReshapeQueueItem current_queue_item = range_data->reshape_queue.TakeFirst();
-
- if (current_queue_item.action_ == kReshapeQueueNextFont) {
- // For now, we're building a character list with which we probe
- // for needed fonts depending on the declared unicode-range of a
- // segmented CSS font. Alternatively, we can build a fake font
- // for the shaper and check whether any glyphs were found, or
- // define a new API on the shaper which will give us coverage
- // information?
- if (!CollectFallbackHintChars(range_data->reshape_queue,
- fallback_chars_hint)) {
- // Give up shaping since we cannot retrieve a font fallback
- // font without a hintlist.
- range_data->reshape_queue.clear();
- break;
- }
-
- current_font_data_for_range_set =
- fallback_iterator->Next(fallback_chars_hint);
- if (!current_font_data_for_range_set->FontData()) {
- DCHECK(!range_data->reshape_queue.size());
- break;
- }
- font_cycle_queued = false;
- continue;
- }
-
- const SimpleFontData* font_data =
- current_font_data_for_range_set->FontData();
- SmallCapsIterator::SmallCapsBehavior small_caps_behavior =
- SmallCapsIterator::kSmallCapsSameCase;
- if (needs_caps_handling) {
- caps_support = OpenTypeCapsSupport(
- font_data->PlatformData().GetHarfBuzzFace(),
- font_description.VariantCaps(), ICUScriptToHBScript(segment.script));
- if (caps_support.NeedsRunCaseSplitting()) {
- SplitUntilNextCaseChange(text_, &range_data->reshape_queue,
- current_queue_item, small_caps_behavior);
- // Skip queue items generated by SplitUntilNextCaseChange that do not
- // contribute to the shape result if the range_data restricts shaping to
- // a substring.
- if (range_data->start >= current_queue_item.start_index_ +
- current_queue_item.num_characters_ ||
- range_data->end <= current_queue_item.start_index_)
- continue;
- }
- }
-
- DCHECK(current_queue_item.num_characters_);
- const SimpleFontData* small_caps_adjusted_font =
- needs_caps_handling &&
- caps_support.NeedsSyntheticFont(small_caps_behavior)
- ? font_data->SmallCapsFontData(font_description).get()
- : font_data;
-
- CaseMapIntend case_map_intend = CaseMapIntend::kKeepSameCase;
- if (needs_caps_handling)
- case_map_intend = caps_support.NeedsCaseChange(small_caps_behavior);
-
- // Clamp the start and end offsets of the queue item to the offsets
- // representing the shaping window.
- unsigned shape_start =
- std::max(range_data->start, current_queue_item.start_index_);
- unsigned shape_end =
- std::min(range_data->end, current_queue_item.start_index_ +
- current_queue_item.num_characters_);
- DCHECK_GT(shape_end, shape_start);
-
- CaseMappingHarfBuzzBufferFiller(
- case_map_intend, font_description.LocaleOrDefault(), range_data->buffer,
- text_, text_length_, shape_start, shape_end - shape_start);
-
- CanvasRotationInVertical canvas_rotation = CanvasRotationForRun(
- small_caps_adjusted_font->PlatformData().Orientation(),
- segment.render_orientation);
-
- CapsFeatureSettingsScopedOverlay caps_overlay(
- &range_data->font_features,
- caps_support.FontFeatureToUse(small_caps_behavior));
- hb_direction_t direction = range_data->HarfBuzzDirection(canvas_rotation);
-
- if (!ShapeRange(range_data->buffer,
- range_data->font_features.IsEmpty()
- ? nullptr
- : range_data->font_features.data(),
- range_data->font_features.size(), small_caps_adjusted_font,
- current_font_data_for_range_set->Ranges(), segment.script,
- direction, language))
- DLOG(ERROR) << "Shaping range failed.";
-
- ExtractShapeResults(range_data, font_cycle_queued, current_queue_item,
- small_caps_adjusted_font, segment.script,
- canvas_rotation, !fallback_iterator->HasNext(), result);
-
- hb_buffer_reset(range_data->buffer);
- }
-}
-
-// Get a RunSegmenter for the specified range and FontOrientation.
-//
-// Because RunSegmenter needs pre-context but is foward-only, it needs to start
-// from the beginning for each range. By caching the last-used RunSegmenter,
-// when caller shapes multiple ranges of a string incrementally, we can re-use
-// existing instance and avoid scanning from the beginning.
-RunSegmenter* HarfBuzzShaper::CachedRunSegmenter(
- unsigned start,
- unsigned end,
- FontOrientation orientation) const {
- if (!run_segmenter_.has_value() || run_segmenter_->HasProgressedPast(start) ||
- !run_segmenter_->Supports(orientation)) {
- // RunSegmenter is not created yet, or existing instance cannot be reused
- // for the new range. Create a new instance.
- //
- // Run segmentation needs to operate on the entire string, regardless of the
- // shaping window (defined by the start and end parameters).
- run_segmenter_.emplace(text_, text_length_, orientation);
- }
- return &run_segmenter_.value();
-}
-
-scoped_refptr<ShapeResult> HarfBuzzShaper::Shape(const Font* font,
- TextDirection direction,
- unsigned start,
- unsigned end) const {
- DCHECK(end >= start);
- DCHECK(end <= text_length_);
-
- unsigned length = end - start;
- scoped_refptr<ShapeResult> result = ShapeResult::Create(font, length, direction);
- HarfBuzzScopedPtr<hb_buffer_t> buffer(hb_buffer_create(), hb_buffer_destroy);
- RunSegmenter* run_segmenter =
- CachedRunSegmenter(start, end, font->GetFontDescription().Orientation());
-
- RangeData range_data;
- range_data.buffer = buffer.Get();
- range_data.font = font;
- range_data.text_direction = direction;
- range_data.start = start;
- range_data.end = end;
- SetFontFeatures(font, &range_data.font_features);
-
- RunSegmenter::RunSegmenterRange segment_range = RunSegmenter::NullRange();
- for (unsigned run_segmenter_start = start;
- run_segmenter->ConsumePast(run_segmenter_start, &segment_range);
- run_segmenter_start = segment_range.end) {
- // Only shape segments overlapping with the range indicated by start and
- // end. Not only those strictly within.
- if (start < segment_range.end && end > segment_range.start)
- ShapeSegment(&range_data, segment_range, result.get());
-
- // Break if beyond the requested range. Because RunSegmenter is
- // incremental, further ranges are not needed. This also allows reusing
- // the segmenter state for next incremental calls.
- if (segment_range.end >= end)
- break;
- }
-
- // Ensure we have at least one run for StartIndexForResult().
- if (UNLIKELY(result->runs_.IsEmpty() && start))
- result->InsertRunForIndex(start);
-
-#if DCHECK_IS_ON()
- if (result)
- CheckShapeResultRange(result.get(), start, end, text_, font);
-#endif
-
- return result;
-}
-
-scoped_refptr<ShapeResult> HarfBuzzShaper::Shape(const Font* font,
- TextDirection direction) const {
- return Shape(font, direction, 0, text_length_);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.h
deleted file mode 100644
index 1f0de3eee16..00000000000
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARF_BUZZ_SHAPER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARF_BUZZ_SHAPER_H_
-
-#include "base/optional.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-class Font;
-class SimpleFontData;
-class HarfBuzzShaper;
-struct ReshapeQueueItem;
-struct RangeData;
-struct BufferSlice;
-
-enum class FontOrientation;
-
-class PLATFORM_EXPORT HarfBuzzShaper final {
- public:
- HarfBuzzShaper(const UChar*, unsigned length);
-
- // Shape a range, defined by the start and end parameters, of the string
- // supplied to the constructor.
- // The start and end positions should represent boundaries where a break may
- // occur, such as at the beginning or end of lines or at element boundaries.
- // If given arbitrary positions the results are not guaranteed to be correct.
- // May be called multiple times; font and direction may vary between calls.
- scoped_refptr<ShapeResult> Shape(const Font*,
- TextDirection,
- unsigned start,
- unsigned end) const;
-
- // Shape the entire string with a single font and direction.
- // Equivalent to calling the range version with a start offset of zero and an
- // end offset equal to the length.
- scoped_refptr<ShapeResult> Shape(const Font*, TextDirection) const;
-
- const UChar* GetText() const { return text_; }
- unsigned TextLength() const { return text_length_; }
-
- ~HarfBuzzShaper() = default;
-
- private:
-
- // Shapes a single seqment, as identified by the RunSegmenterRange parameter,
- // one or more times taking font fallback into account. The start and end
- // parameters are for the entire text run, not the segment, and are used to
- // determine pre- and post-context for shaping.
- void ShapeSegment(RangeData*,
- RunSegmenter::RunSegmenterRange,
- ShapeResult*) const;
-
- void ExtractShapeResults(RangeData*,
- bool& font_cycle_queued,
- const ReshapeQueueItem&,
- const SimpleFontData*,
- UScriptCode,
- CanvasRotationInVertical,
- bool is_last_resort,
- ShapeResult*) const;
-
- bool CollectFallbackHintChars(const Deque<ReshapeQueueItem>&,
- Vector<UChar32>& hint) const;
-
- void CommitGlyphs(RangeData*,
- const SimpleFontData* current_font,
- UScriptCode current_run_script,
- CanvasRotationInVertical,
- bool is_last_resort,
- const BufferSlice&,
- ShapeResult*) const;
-
- RunSegmenter* CachedRunSegmenter(unsigned start,
- unsigned end,
- FontOrientation) const;
-
- const UChar* text_;
- unsigned text_length_;
-
- // Cache an instnace of |RunSegmenter|. See |CachedRunSegmenter()|.
- mutable base::Optional<RunSegmenter> run_segmenter_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARF_BUZZ_SHAPER_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper_fuzzer.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper_fuzzer.cc
deleted file mode 100644
index 7778209f5a8..00000000000
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper_fuzzer.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/fonts/font.h"
-#include "third_party/blink/renderer/platform/fonts/font_cache.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.h"
-#include "third_party/blink/renderer/platform/testing/blink_fuzzer_test_support.h"
-
-#include <stddef.h>
-#include <stdint.h>
-#include <unicode/ustring.h>
-
-namespace blink {
-
-constexpr size_t kMaxInputLength = 256;
-
-// TODO crbug.com/771901: BlinkFuzzerTestSupport should also initialize the
-// custom fontconfig configuration that we use for content_shell.
-int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- static BlinkFuzzerTestSupport fuzzer_support = BlinkFuzzerTestSupport();
- constexpr int32_t kDestinationCapacity = 2 * kMaxInputLength;
- int32_t converted_length = 0;
- UChar converted_input_buffer[kDestinationCapacity] = {0};
- UErrorCode error_code = U_ZERO_ERROR;
-
- // Discard trailing bytes.
- u_strFromUTF32(converted_input_buffer, kDestinationCapacity,
- &converted_length, reinterpret_cast<const UChar32*>(data),
- size / sizeof(UChar32), &error_code);
- if (U_FAILURE(error_code))
- return 0;
-
- FontCachePurgePreventer font_cache_purge_preventer;
- FontDescription font_description;
- Font font(font_description);
- // Set font size to something other than the default 0 size in
- // FontDescription, 16 matches the default text size in HTML.
- font_description.SetComputedSize(16.0f);
- // Only look for system fonts for now.
- font.Update(nullptr);
-
- HarfBuzzShaper shaper(converted_input_buffer, converted_length);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
- return 0;
-}
-
-} // namespace blink
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- return blink::LLVMFuzzerTestOneInput(data, size);
-}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper_test.cc
deleted file mode 100644
index da081011960..00000000000
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper_test.cc
+++ /dev/null
@@ -1,1371 +0,0 @@
-// Copyright (c) 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.h"
-
-#include <unicode/uscript.h>
-
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/fonts/font.h"
-#include "third_party/blink/renderer/platform/fonts/font_cache.h"
-#include "third_party/blink/renderer/platform/fonts/font_test_utilities.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_test_info.h"
-#include "third_party/blink/renderer/platform/layout_test_support.h"
-#include "third_party/blink/renderer/platform/testing/font_test_helpers.h"
-#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
-#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
-#include "third_party/blink/renderer/platform/text/text_run.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-class HarfBuzzShaperTest : public testing::Test {
- protected:
- void SetUp() override {
- font_description.SetComputedSize(12.0);
- font = Font(font_description);
- font.Update(nullptr);
- }
-
- void TearDown() override {}
-
- Font CreateAhem(float size) {
- FontDescription::VariantLigatures ligatures;
- return blink::test::CreateTestFont(
- "Ahem", blink::test::PlatformTestDataPath("Ahem.woff"), size,
- &ligatures);
- }
-
- scoped_refptr<ShapeResult> SplitRun(scoped_refptr<ShapeResult> shape_result,
- unsigned offset) {
- unsigned length = shape_result->NumCharacters();
- scoped_refptr<ShapeResult> run2 = shape_result->SubRange(offset, length);
- shape_result = shape_result->SubRange(0, offset);
- run2->CopyRange(offset, length, shape_result.get());
- return shape_result;
- }
-
- FontCachePurgePreventer font_cache_purge_preventer;
- FontDescription font_description;
- Font font;
- unsigned start_index = 0;
- unsigned num_characters = 0;
- unsigned num_glyphs = 0;
- hb_script_t script = HB_SCRIPT_INVALID;
-};
-
-class ScopedSubpixelOverride {
- public:
- ScopedSubpixelOverride(bool b) {
- prev_layout_test_ = LayoutTestSupport::IsRunningLayoutTest();
- prev_subpixel_allowed_ =
- LayoutTestSupport::IsTextSubpixelPositioningAllowedForTest();
- prev_antialias_ = LayoutTestSupport::IsFontAntialiasingEnabledForTest();
- prev_fd_subpixel_ = FontDescription::SubpixelPositioning();
-
- // This is required for all LayoutTestSupport settings to have effects.
- LayoutTestSupport::SetIsRunningLayoutTest(true);
-
- if (b) {
- // Allow subpixel positioning.
- LayoutTestSupport::SetTextSubpixelPositioningAllowedForTest(true);
-
- // Now, enable subpixel positioning in platform-specific ways.
-
- // Mac always enables subpixel positioning.
-
- // On Windows, subpixel positioning also requires antialiasing.
- LayoutTestSupport::SetFontAntialiasingEnabledForTest(true);
-
- // On platforms other than Windows and Mac this needs to be set as
- // well.
- FontDescription::SetSubpixelPositioning(true);
- } else {
- // Explicitly disallow all subpixel positioning.
- LayoutTestSupport::SetTextSubpixelPositioningAllowedForTest(false);
- }
- }
- ~ScopedSubpixelOverride() {
- FontDescription::SetSubpixelPositioning(prev_fd_subpixel_);
- LayoutTestSupport::SetFontAntialiasingEnabledForTest(prev_antialias_);
- LayoutTestSupport::SetTextSubpixelPositioningAllowedForTest(
- prev_subpixel_allowed_);
- LayoutTestSupport::SetIsRunningLayoutTest(prev_layout_test_);
-
- // Fonts cached with a different subpixel positioning state are not
- // automatically invalidated and need to be cleared between test
- // runs.
- FontCache::GetFontCache()->Invalidate();
- }
-
- private:
- bool prev_layout_test_;
- bool prev_subpixel_allowed_;
- bool prev_antialias_;
- bool prev_fd_subpixel_;
-};
-
-class ShapeParameterTest : public HarfBuzzShaperTest,
- public testing::WithParamInterface<TextDirection> {
- protected:
- scoped_refptr<ShapeResult> ShapeWithParameter(HarfBuzzShaper* shaper) {
- TextDirection direction = GetParam();
- return shaper->Shape(&font, direction);
- }
-};
-
-INSTANTIATE_TEST_CASE_P(HarfBuzzShaperTest,
- ShapeParameterTest,
- testing::Values(TextDirection::kLtr,
- TextDirection::kRtl));
-
-static inline ShapeResultTestInfo* TestInfo(scoped_refptr<ShapeResult>& result) {
- return static_cast<ShapeResultTestInfo*>(result.get());
-}
-
-TEST_F(HarfBuzzShaperTest, MutableUnique) {
- scoped_refptr<ShapeResult> result =
- ShapeResult::Create(&font, 0, TextDirection::kLtr);
- EXPECT_TRUE(result->HasOneRef());
-
- // At this point, |result| has only one ref count.
- scoped_refptr<ShapeResult> result2 = result->MutableUnique();
- EXPECT_EQ(result.get(), result2.get());
- EXPECT_FALSE(result2->HasOneRef());
-
- // Since |result| has 2 ref counts, it should return a clone.
- scoped_refptr<ShapeResult> result3 = result->MutableUnique();
- EXPECT_NE(result.get(), result3.get());
- EXPECT_TRUE(result3->HasOneRef());
-}
-
-TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsLatin) {
- String latin_common = To16Bit("ABC DEF.", 8);
- HarfBuzzShaper shaper(latin_common.Characters16(), 8);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
-
- EXPECT_EQ(1u, TestInfo(result)->NumberOfRunsForTesting());
- ASSERT_TRUE(
- TestInfo(result)->RunInfoForTesting(0, start_index, num_glyphs, script));
- EXPECT_EQ(0u, start_index);
- EXPECT_EQ(8u, num_glyphs);
- EXPECT_EQ(HB_SCRIPT_LATIN, script);
-}
-
-TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsLeadingCommon) {
- String leading_common = To16Bit("... test", 8);
- HarfBuzzShaper shaper(leading_common.Characters16(), 8);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
-
- EXPECT_EQ(1u, TestInfo(result)->NumberOfRunsForTesting());
- ASSERT_TRUE(
- TestInfo(result)->RunInfoForTesting(0, start_index, num_glyphs, script));
- EXPECT_EQ(0u, start_index);
- EXPECT_EQ(8u, num_glyphs);
- EXPECT_EQ(HB_SCRIPT_LATIN, script);
-}
-
-TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsUnicodeVariants) {
- struct {
- const char* name;
- UChar string[4];
- unsigned length;
- hb_script_t script;
- } testlist[] = {
- {"Standard Variants text style", {0x30, 0xFE0E}, 2, HB_SCRIPT_COMMON},
- {"Standard Variants emoji style", {0x203C, 0xFE0F}, 2, HB_SCRIPT_COMMON},
- {"Standard Variants of Ideograph", {0x4FAE, 0xFE00}, 2, HB_SCRIPT_HAN},
- {"Ideographic Variants", {0x3402, 0xDB40, 0xDD00}, 3, HB_SCRIPT_HAN},
- {"Not-defined Variants", {0x41, 0xDB40, 0xDDEF}, 3, HB_SCRIPT_LATIN},
- };
- for (auto& test : testlist) {
- HarfBuzzShaper shaper(test.string, test.length);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
-
- EXPECT_EQ(1u, TestInfo(result)->NumberOfRunsForTesting()) << test.name;
- ASSERT_TRUE(
- TestInfo(result)->RunInfoForTesting(0, start_index, num_glyphs, script))
- << test.name;
- EXPECT_EQ(0u, start_index) << test.name;
- if (num_glyphs == 2) {
-// If the specified VS is not in the font, it's mapped to .notdef.
-// then hb_ot_hide_default_ignorables() swaps it to a space with zero-advance.
-// http://lists.freedesktop.org/archives/harfbuzz/2015-May/004888.html
-#if !defined(OS_MACOSX)
- EXPECT_EQ(TestInfo(result)->FontDataForTesting(0)->SpaceGlyph(),
- TestInfo(result)->GlyphForTesting(0, 1))
- << test.name;
-#endif
- EXPECT_EQ(0.f, TestInfo(result)->AdvanceForTesting(0, 1)) << test.name;
- } else {
- EXPECT_EQ(1u, num_glyphs) << test.name;
- }
- EXPECT_EQ(test.script, script) << test.name;
- }
-}
-
-TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsDevanagariCommon) {
- UChar devanagari_common_string[] = {0x915, 0x94d, 0x930, 0x28, 0x20, 0x29};
- String devanagari_common_latin(devanagari_common_string, 6);
- HarfBuzzShaper shaper(devanagari_common_latin.Characters16(), 6);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
-
- EXPECT_EQ(2u, TestInfo(result)->NumberOfRunsForTesting());
- ASSERT_TRUE(
- TestInfo(result)->RunInfoForTesting(0, start_index, num_glyphs, script));
- EXPECT_EQ(0u, start_index);
- EXPECT_EQ(1u, num_glyphs);
- EXPECT_EQ(HB_SCRIPT_DEVANAGARI, script);
-
- ASSERT_TRUE(
- TestInfo(result)->RunInfoForTesting(1, start_index, num_glyphs, script));
- EXPECT_EQ(3u, start_index);
- EXPECT_EQ(3u, num_glyphs);
- EXPECT_EQ(HB_SCRIPT_DEVANAGARI, script);
-}
-
-TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsDevanagariCommonLatinCommon) {
- UChar devanagari_common_latin_string[] = {0x915, 0x94d, 0x930, 0x20,
- 0x61, 0x62, 0x2E};
- HarfBuzzShaper shaper(devanagari_common_latin_string, 7);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
-
- EXPECT_EQ(3u, TestInfo(result)->NumberOfRunsForTesting());
- ASSERT_TRUE(
- TestInfo(result)->RunInfoForTesting(0, start_index, num_glyphs, script));
- EXPECT_EQ(0u, start_index);
- EXPECT_EQ(1u, num_glyphs);
- EXPECT_EQ(HB_SCRIPT_DEVANAGARI, script);
-
- ASSERT_TRUE(
- TestInfo(result)->RunInfoForTesting(1, start_index, num_glyphs, script));
- EXPECT_EQ(3u, start_index);
- EXPECT_EQ(1u, num_glyphs);
- EXPECT_EQ(HB_SCRIPT_DEVANAGARI, script);
-
- ASSERT_TRUE(
- TestInfo(result)->RunInfoForTesting(2, start_index, num_glyphs, script));
- EXPECT_EQ(4u, start_index);
- EXPECT_EQ(3u, num_glyphs);
- EXPECT_EQ(HB_SCRIPT_LATIN, script);
-}
-
-TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabicThaiHanLatin) {
- UChar mixed_string[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62};
- HarfBuzzShaper shaper(mixed_string, 6);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
-
- EXPECT_EQ(4u, TestInfo(result)->NumberOfRunsForTesting());
- ASSERT_TRUE(
- TestInfo(result)->RunInfoForTesting(0, start_index, num_glyphs, script));
- EXPECT_EQ(0u, start_index);
- EXPECT_EQ(3u, num_glyphs);
- EXPECT_EQ(HB_SCRIPT_ARABIC, script);
-
- ASSERT_TRUE(
- TestInfo(result)->RunInfoForTesting(1, start_index, num_glyphs, script));
- EXPECT_EQ(3u, start_index);
- EXPECT_EQ(1u, num_glyphs);
- EXPECT_EQ(HB_SCRIPT_THAI, script);
-
- ASSERT_TRUE(
- TestInfo(result)->RunInfoForTesting(2, start_index, num_glyphs, script));
- EXPECT_EQ(4u, start_index);
- EXPECT_EQ(1u, num_glyphs);
- EXPECT_EQ(HB_SCRIPT_HAN, script);
-
- ASSERT_TRUE(
- TestInfo(result)->RunInfoForTesting(3, start_index, num_glyphs, script));
- EXPECT_EQ(5u, start_index);
- EXPECT_EQ(1u, num_glyphs);
- EXPECT_EQ(HB_SCRIPT_LATIN, script);
-}
-
-TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabicThaiHanLatinTwice) {
- UChar mixed_string[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62};
- HarfBuzzShaper shaper(mixed_string, 6);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
- EXPECT_EQ(4u, TestInfo(result)->NumberOfRunsForTesting());
-
- // Shape again on the same shape object and check the number of runs.
- // Should be equal if no state was retained between shape calls.
- scoped_refptr<ShapeResult> result2 = shaper.Shape(&font, TextDirection::kLtr);
- EXPECT_EQ(4u, TestInfo(result2)->NumberOfRunsForTesting());
-}
-
-TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabic) {
- UChar arabic_string[] = {0x628, 0x64A, 0x629};
- HarfBuzzShaper shaper(arabic_string, 3);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kRtl);
-
- EXPECT_EQ(1u, TestInfo(result)->NumberOfRunsForTesting());
- ASSERT_TRUE(
- TestInfo(result)->RunInfoForTesting(0, start_index, num_glyphs, script));
- EXPECT_EQ(0u, start_index);
- EXPECT_EQ(3u, num_glyphs);
- EXPECT_EQ(HB_SCRIPT_ARABIC, script);
-}
-
-// This is a simplified test and doesn't accuratly reflect how the shape range
-// is to be used. If you instead of the string you imagine the following HTML:
-// <div>Hello <span>World</span>!</div>
-// It better reflects the intended use where the range given to each shape call
-// corresponds to the text content of a TextNode.
-TEST_F(HarfBuzzShaperTest, ShapeLatinSegment) {
- String string = To16Bit("Hello World!", 12);
- TextDirection direction = TextDirection::kLtr;
-
- HarfBuzzShaper shaper(string.Characters16(), 12);
- scoped_refptr<ShapeResult> combined = shaper.Shape(&font, direction);
- scoped_refptr<ShapeResult> first = shaper.Shape(&font, direction, 0, 6);
- scoped_refptr<ShapeResult> second = shaper.Shape(&font, direction, 6, 11);
- scoped_refptr<ShapeResult> third = shaper.Shape(&font, direction, 11, 12);
-
- ASSERT_TRUE(TestInfo(first)->RunInfoForTesting(0, start_index, num_characters,
- num_glyphs, script));
- EXPECT_EQ(0u, start_index);
- EXPECT_EQ(6u, num_characters);
- ASSERT_TRUE(TestInfo(second)->RunInfoForTesting(
- 0, start_index, num_characters, num_glyphs, script));
- EXPECT_EQ(6u, start_index);
- EXPECT_EQ(5u, num_characters);
- ASSERT_TRUE(TestInfo(third)->RunInfoForTesting(0, start_index, num_characters,
- num_glyphs, script));
- EXPECT_EQ(11u, start_index);
- EXPECT_EQ(1u, num_characters);
-
- HarfBuzzShaper shaper2(string.Characters16(), 6);
- scoped_refptr<ShapeResult> first_reference = shaper2.Shape(&font, direction);
-
- HarfBuzzShaper shaper3(string.Characters16() + 6, 5);
- scoped_refptr<ShapeResult> second_reference = shaper3.Shape(&font, direction);
-
- HarfBuzzShaper shaper4(string.Characters16() + 11, 1);
- scoped_refptr<ShapeResult> third_reference = shaper4.Shape(&font, direction);
-
- // Width of each segment should be the same when shaped using start and end
- // offset as it is when shaping the three segments using separate shaper
- // instances.
- // A full pixel is needed for tolerance to account for kerning on some
- // platforms.
- ASSERT_NEAR(first_reference->Width(), first->Width(), 1);
- ASSERT_NEAR(second_reference->Width(), second->Width(), 1);
- ASSERT_NEAR(third_reference->Width(), third->Width(), 1);
-
- // Width of shape results for the entire string should match the combined
- // shape results from the three segments.
- float total_width = first->Width() + second->Width() + third->Width();
- ASSERT_NEAR(combined->Width(), total_width, 1);
-}
-
-// Represents the case where a part of a cluster has a different color.
-// <div>0x647<span style="color: red;">0x64A</span></div>
-// This test requires context-aware shaping which hasn't been implemented yet.
-// See crbug.com/689155
-TEST_F(HarfBuzzShaperTest, DISABLED_ShapeArabicWithContext) {
- UChar arabic_string[] = {0x647, 0x64A};
- HarfBuzzShaper shaper(arabic_string, 2);
-
- scoped_refptr<ShapeResult> combined = shaper.Shape(&font, TextDirection::kRtl);
-
- scoped_refptr<ShapeResult> first = shaper.Shape(&font, TextDirection::kRtl, 0, 1);
- scoped_refptr<ShapeResult> second = shaper.Shape(&font, TextDirection::kRtl, 1, 2);
-
- // Combined width should be the same when shaping the two characters
- // separately as when shaping them combined.
- ASSERT_NEAR(combined->Width(), first->Width() + second->Width(), 0.1);
-}
-
-TEST_F(HarfBuzzShaperTest, ShapeVerticalUpright) {
- font_description.SetOrientation(FontOrientation::kVerticalUpright);
- font = Font(font_description);
- font.Update(nullptr);
-
- // This string should create 2 runs, ideographic and Latin, both in upright.
- String string(u"\u65E5\u65E5\u65E5lllll");
- TextDirection direction = TextDirection::kLtr;
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-
- // Check width and bounds are not too much different. ".1" is heuristic.
- EXPECT_NEAR(result->Width(), result->Bounds().Width(), result->Width() * .1);
-
- // Shape each run and merge them using CopyRange. Bounds() should match.
- scoped_refptr<ShapeResult> result1 = shaper.Shape(&font, direction, 0, 3);
- scoped_refptr<ShapeResult> result2 =
- shaper.Shape(&font, direction, 3, string.length());
-
- scoped_refptr<ShapeResult> composite_result =
- ShapeResult::Create(&font, 0, direction);
- result1->CopyRange(0, 3, composite_result.get());
- result2->CopyRange(3, string.length(), composite_result.get());
-
- EXPECT_EQ(result->Bounds(), composite_result->Bounds());
-}
-
-TEST_F(HarfBuzzShaperTest, RangeShapeSmallCaps) {
- // Test passes if no assertion is hit of the ones below, but also the newly
- // introduced one in HarfBuzzShaper::ShapeSegment: DCHECK_GT(shape_end,
- // shape_start) is not hit.
- FontDescription font_description;
- font_description.SetVariantCaps(FontDescription::kSmallCaps);
- font_description.SetComputedSize(12.0);
- Font font(font_description);
- font.Update(nullptr);
-
- // Shaping index 2 to 3 means that case splitting for small caps splits before
- // character index 2 since the initial 'a' needs to be uppercased, but the
- // space character does not need to be uppercased. This triggered
- // crbug.com/817271.
- String string(u"a aa");
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result =
- shaper.Shape(&font, TextDirection::kLtr, 2, 3);
- EXPECT_EQ(1u, result->NumCharacters());
-
- string = u"aa a";
- HarfBuzzShaper shaper_two(string.Characters16(), string.length());
- result = shaper_two.Shape(&font, TextDirection::kLtr, 3, 4);
- EXPECT_EQ(1u, result->NumCharacters());
-
- string = u"a aa";
- HarfBuzzShaper shaper_three(string.Characters16(), string.length());
- result = shaper_three.Shape(&font, TextDirection::kLtr, 1, 2);
- EXPECT_EQ(1u, result->NumCharacters());
-
- string = u"aa aa aa aa aa aa aa aa aa aa";
- HarfBuzzShaper shaper_four(string.Characters16(), string.length());
- result = shaper_four.Shape(&font, TextDirection::kLtr, 21, 23);
- EXPECT_EQ(2u, result->NumCharacters());
-
- string = u"aa aa aa aa aa aa aa aa aa aa";
- HarfBuzzShaper shaper_five(string.Characters16(), string.length());
- result = shaper_five.Shape(&font, TextDirection::kLtr, 27, 29);
- EXPECT_EQ(2u, result->NumCharacters());
-}
-
-TEST_F(HarfBuzzShaperTest, ShapeVerticalMixed) {
- font_description.SetOrientation(FontOrientation::kVerticalMixed);
- font = Font(font_description);
- font.Update(nullptr);
-
- // This string should create 2 runs, ideographic in upright and Latin in
- // rotated horizontal.
- String string(u"\u65E5\u65E5\u65E5lllll");
- TextDirection direction = TextDirection::kLtr;
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-
- // Check width and bounds are not too much different. ".1" is heuristic.
- EXPECT_NEAR(result->Width(), result->Bounds().Width(), result->Width() * .1);
-
- // Shape each run and merge them using CopyRange. Bounds() should match.
- scoped_refptr<ShapeResult> result1 = shaper.Shape(&font, direction, 0, 3);
- scoped_refptr<ShapeResult> result2 =
- shaper.Shape(&font, direction, 3, string.length());
-
- scoped_refptr<ShapeResult> composite_result =
- ShapeResult::Create(&font, 0, direction);
- result1->CopyRange(0, 3, composite_result.get());
- result2->CopyRange(3, string.length(), composite_result.get());
-
- EXPECT_EQ(result->Bounds(), composite_result->Bounds());
-}
-
-TEST_P(ShapeParameterTest, MissingGlyph) {
- // U+FFF0 is not assigned as of Unicode 10.0.
- String string(
- u"\uFFF0"
- u"Hello");
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = ShapeWithParameter(&shaper);
- EXPECT_EQ(0u, result->StartIndexForResult());
- EXPECT_EQ(string.length(), result->EndIndexForResult());
-}
-
-TEST_P(ShapeParameterTest, ZeroWidthSpace) {
- UChar string[] = {kZeroWidthSpaceCharacter,
- kZeroWidthSpaceCharacter,
- 0x0627,
- 0x0631,
- 0x062F,
- 0x0648,
- kZeroWidthSpaceCharacter,
- kZeroWidthSpaceCharacter};
- const unsigned length = arraysize(string);
- HarfBuzzShaper shaper(string, length);
- scoped_refptr<ShapeResult> result = ShapeWithParameter(&shaper);
- EXPECT_EQ(0u, result->StartIndexForResult());
- EXPECT_EQ(length, result->EndIndexForResult());
-#if DCHECK_IS_ON()
- result->CheckConsistency();
-#endif
-}
-
-TEST_F(HarfBuzzShaperTest, NegativeLetterSpacing) {
- String string(u"Hello");
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
- float width = result->Width();
- FloatRect bounds = result->Bounds();
-
- ShapeResultSpacing<String> spacing(string);
- FontDescription font_description;
- font_description.SetLetterSpacing(-5);
- spacing.SetSpacing(font_description);
- result->ApplySpacing(spacing);
-
- EXPECT_EQ(5 * 5, width - result->Width());
- EXPECT_EQ(5 * 4 - 1, bounds.Width() - result->Bounds().Width());
-}
-
-TEST_F(HarfBuzzShaperTest, NegativeLetterSpacingTo0) {
- String string(u"00000");
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
- float char_width = result->Width() / string.length();
-
- ShapeResultSpacing<String> spacing(string);
- FontDescription font_description;
- font_description.SetLetterSpacing(-char_width);
- spacing.SetSpacing(font_description);
- result->ApplySpacing(spacing);
-
- // EXPECT_EQ(0.0f, result->Width());
- EXPECT_NEAR(0.0f, result->Bounds().X(), 1);
- // Because all characters are at 0, the glyph bounds must be the char_width.
- // Allow being larger because accurate width requires re-measuring each glyph.
- EXPECT_GE(result->Bounds().MaxX(), char_width);
- EXPECT_LE(result->Bounds().MaxX(), char_width * 1.2);
-}
-
-TEST_F(HarfBuzzShaperTest, NegativeLetterSpacingToNegative) {
- String string(u"00000");
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
- float char_width = result->Width() / string.length();
-
- ShapeResultSpacing<String> spacing(string);
- FontDescription font_description;
- font_description.SetLetterSpacing(-2 * char_width);
- spacing.SetSpacing(font_description);
- result->ApplySpacing(spacing);
-
- // CSS does not allow negative width, it should be clampled to 0.
- // EXPECT_EQ(0.0f, result->Width());
- // Glyph bounding box should overflow to the left.
- EXPECT_EQ(-char_width * string.length(), result->Bounds().X());
- // MaxX() should be char_width. Allow being larger.
- EXPECT_GE(result->Bounds().MaxX(), char_width);
-}
-
-static struct OffsetForPositionTestData {
- float position;
- unsigned offset_ltr;
- unsigned offset_rtl;
- unsigned hit_test_ltr;
- unsigned hit_test_rtl;
- unsigned fit_ltr_ltr;
- unsigned fit_ltr_rtl;
- unsigned fit_rtl_ltr;
- unsigned fit_rtl_rtl;
-} offset_for_position_fixed_pitch_test_data[] = {
- // The left edge.
- {-1, 0, 5, 0, 5, 0, 0, 5, 5},
- {0, 0, 5, 0, 5, 0, 0, 5, 5},
- // Hit test should round to the nearest glyph at the middle of a glyph.
- {4, 0, 4, 0, 5, 0, 1, 5, 4},
- {6, 0, 4, 1, 4, 0, 1, 5, 4},
- // Glyph boundary between the 1st and the 2nd glyph.
- // Avoid testing "10.0" to avoid rounding differences on Windows.
- {9.9, 0, 4, 1, 4, 0, 1, 5, 4},
- {10.1, 1, 3, 1, 4, 1, 2, 4, 3},
- // Run boundary is at position 20. The 1st run has 2 characters.
- {14, 1, 3, 1, 4, 1, 2, 4, 3},
- {16, 1, 3, 2, 3, 1, 2, 4, 3},
- {20.1, 2, 2, 2, 3, 2, 3, 3, 2},
- {24, 2, 2, 2, 3, 2, 3, 3, 2},
- {26, 2, 2, 3, 2, 2, 3, 3, 2},
- // The end of the ShapeResult. The result has 5 characters.
- {44, 4, 0, 4, 1, 4, 5, 1, 0},
- {46, 4, 0, 5, 0, 4, 5, 1, 0},
- {50, 5, 0, 5, 0, 5, 5, 0, 0},
- // Beyond the right edge of the ShapeResult.
- {51, 5, 0, 5, 0, 5, 5, 0, 0},
-};
-
-std::ostream& operator<<(std::ostream& ostream,
- const OffsetForPositionTestData& data) {
- return ostream << data.position;
-}
-
-class OffsetForPositionTest
- : public HarfBuzzShaperTest,
- public testing::WithParamInterface<OffsetForPositionTestData> {};
-
-INSTANTIATE_TEST_CASE_P(
- HarfBuzzShaperTest,
- OffsetForPositionTest,
- testing::ValuesIn(offset_for_position_fixed_pitch_test_data));
-
-TEST_P(OffsetForPositionTest, Data) {
- auto data = GetParam();
- String string(u"01234");
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- Font ahem = CreateAhem(10);
- scoped_refptr<ShapeResult> result =
- SplitRun(shaper.Shape(&ahem, TextDirection::kLtr), 2);
- EXPECT_EQ(data.offset_ltr, result->OffsetForPosition(data.position, false));
- EXPECT_EQ(data.hit_test_ltr, result->OffsetForPosition(data.position, true));
- EXPECT_EQ(data.fit_ltr_ltr,
- result->OffsetToFit(data.position, TextDirection::kLtr));
- EXPECT_EQ(data.fit_ltr_rtl,
- result->OffsetToFit(data.position, TextDirection::kRtl));
-
- result = SplitRun(shaper.Shape(&ahem, TextDirection::kRtl), 3);
- EXPECT_EQ(data.offset_rtl, result->OffsetForPosition(data.position, false));
- EXPECT_EQ(data.hit_test_rtl, result->OffsetForPosition(data.position, true));
- EXPECT_EQ(data.fit_rtl_ltr,
- result->OffsetToFit(data.position, TextDirection::kLtr));
- EXPECT_EQ(data.fit_rtl_rtl,
- result->OffsetToFit(data.position, TextDirection::kRtl));
-}
-
-TEST_F(HarfBuzzShaperTest, PositionForOffsetLatin) {
- String string = To16Bit("Hello World!", 12);
- TextDirection direction = TextDirection::kLtr;
-
- HarfBuzzShaper shaper(string.Characters16(), 12);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
- scoped_refptr<ShapeResult> first = shaper.Shape(&font, direction, 0, 5); // Hello
- scoped_refptr<ShapeResult> second = shaper.Shape(&font, direction, 6, 11); // World
-
- EXPECT_EQ(0.0f, result->PositionForOffset(0));
- ASSERT_NEAR(first->Width(), result->PositionForOffset(5), 1);
- ASSERT_NEAR(second->Width(),
- result->PositionForOffset(11) - result->PositionForOffset(6), 1);
- ASSERT_NEAR(result->Width(), result->PositionForOffset(12), 0.1);
-}
-
-TEST_F(HarfBuzzShaperTest, PositionForOffsetArabic) {
- UChar arabic_string[] = {0x628, 0x64A, 0x629};
- TextDirection direction = TextDirection::kRtl;
-
- HarfBuzzShaper shaper(arabic_string, 3);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-
- EXPECT_EQ(0.0f, result->PositionForOffset(3));
- ASSERT_NEAR(result->Width(), result->PositionForOffset(0), 0.1);
-}
-
-TEST_F(HarfBuzzShaperTest, EmojiZWJSequence) {
- UChar emoji_zwj_sequence[] = {0x270C, 0x200D, 0xD83C, 0xDFFF,
- 0x270C, 0x200D, 0xD83C, 0xDFFC};
- TextDirection direction = TextDirection::kLtr;
-
- HarfBuzzShaper shaper(emoji_zwj_sequence, arraysize(emoji_zwj_sequence));
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-}
-
-// A Value-Parameterized Test class to test OffsetForPosition() with
-// |include_partial_glyphs| parameter.
-class IncludePartialGlyphs : public HarfBuzzShaperTest,
- public testing::WithParamInterface<bool> {};
-
-INSTANTIATE_TEST_CASE_P(OffsetForPositionTest,
- IncludePartialGlyphs,
- testing::Bool());
-
-TEST_P(IncludePartialGlyphs, OffsetForPositionMatchesPositionForOffsetLatin) {
- String string = To16Bit("Hello World!", 12);
- TextDirection direction = TextDirection::kLtr;
-
- HarfBuzzShaper shaper(string.Characters16(), 12);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-
- bool include_partial_glyphs = GetParam();
- EXPECT_EQ(0u, result->OffsetForPosition(result->PositionForOffset(0),
- include_partial_glyphs));
- EXPECT_EQ(1u, result->OffsetForPosition(result->PositionForOffset(1),
- include_partial_glyphs));
- EXPECT_EQ(2u, result->OffsetForPosition(result->PositionForOffset(2),
- include_partial_glyphs));
- EXPECT_EQ(3u, result->OffsetForPosition(result->PositionForOffset(3),
- include_partial_glyphs));
- EXPECT_EQ(4u, result->OffsetForPosition(result->PositionForOffset(4),
- include_partial_glyphs));
- EXPECT_EQ(5u, result->OffsetForPosition(result->PositionForOffset(5),
- include_partial_glyphs));
- EXPECT_EQ(6u, result->OffsetForPosition(result->PositionForOffset(6),
- include_partial_glyphs));
- EXPECT_EQ(7u, result->OffsetForPosition(result->PositionForOffset(7),
- include_partial_glyphs));
- EXPECT_EQ(8u, result->OffsetForPosition(result->PositionForOffset(8),
- include_partial_glyphs));
- EXPECT_EQ(9u, result->OffsetForPosition(result->PositionForOffset(9),
- include_partial_glyphs));
- EXPECT_EQ(10u, result->OffsetForPosition(result->PositionForOffset(10),
- include_partial_glyphs));
- EXPECT_EQ(11u, result->OffsetForPosition(result->PositionForOffset(11),
- include_partial_glyphs));
- EXPECT_EQ(12u, result->OffsetForPosition(result->PositionForOffset(12),
- include_partial_glyphs));
-}
-
-TEST_P(IncludePartialGlyphs, OffsetForPositionMatchesPositionForOffsetArabic) {
- UChar arabic_string[] = {0x628, 0x64A, 0x629};
- TextDirection direction = TextDirection::kRtl;
-
- HarfBuzzShaper shaper(arabic_string, 3);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-
- bool include_partial_glyphs = GetParam();
- EXPECT_EQ(0u, result->OffsetForPosition(result->PositionForOffset(0),
- include_partial_glyphs));
- EXPECT_EQ(1u, result->OffsetForPosition(result->PositionForOffset(1),
- include_partial_glyphs));
- EXPECT_EQ(2u, result->OffsetForPosition(result->PositionForOffset(2),
- include_partial_glyphs));
- EXPECT_EQ(3u, result->OffsetForPosition(result->PositionForOffset(3),
- include_partial_glyphs));
-}
-
-TEST_P(IncludePartialGlyphs, OffsetForPositionMatchesPositionForOffsetMixed) {
- UChar mixed_string[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62};
- HarfBuzzShaper shaper(mixed_string, 6);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
-
- bool include_partial_glyphs = GetParam();
- EXPECT_EQ(0u, result->OffsetForPosition(result->PositionForOffset(0),
- include_partial_glyphs));
- EXPECT_EQ(1u, result->OffsetForPosition(result->PositionForOffset(1),
- include_partial_glyphs));
- EXPECT_EQ(2u, result->OffsetForPosition(result->PositionForOffset(2),
- include_partial_glyphs));
- EXPECT_EQ(3u, result->OffsetForPosition(result->PositionForOffset(3),
- include_partial_glyphs));
- EXPECT_EQ(4u, result->OffsetForPosition(result->PositionForOffset(4),
- include_partial_glyphs));
- EXPECT_EQ(5u, result->OffsetForPosition(result->PositionForOffset(5),
- include_partial_glyphs));
- EXPECT_EQ(6u, result->OffsetForPosition(result->PositionForOffset(6),
- include_partial_glyphs));
-}
-
-TEST_F(HarfBuzzShaperTest, PositionForOffsetMissingGlyph) {
- String string(u"\u0633\u0644\u0627\u0645");
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kRtl);
- // Because the offset 1 and 2 should form a ligature, SubRange(2, 4) creates a
- // ShapeResult that does not have its first glyph.
- result = result->SubRange(2, 4);
- result->PositionForOffset(0);
- // Pass if |PositionForOffset| does not crash.
-}
-
-static struct ShapeResultCopyRangeTestData {
- const char16_t* string;
- TextDirection direction;
- unsigned break_point;
-} shape_result_copy_range_test_data[] = {
- {u"ABC", TextDirection::kLtr, 1},
- {u"\u0648\u0644\u064A", TextDirection::kRtl, 1},
- // These strings creates 3 runs. Split it in the middle of 2nd run.
- {u"\u65E5Hello\u65E5\u65E5", TextDirection::kLtr, 3},
- {u"\u0648\u0644\u064A AB \u0628\u062A", TextDirection::kRtl, 5}};
-
-std::ostream& operator<<(std::ostream& ostream,
- const ShapeResultCopyRangeTestData& data) {
- return ostream << String(data.string) << " @ " << data.break_point << ", "
- << data.direction;
-}
-
-class ShapeResultCopyRangeTest
- : public HarfBuzzShaperTest,
- public testing::WithParamInterface<ShapeResultCopyRangeTestData> {};
-
-INSTANTIATE_TEST_CASE_P(HarfBuzzShaperTest,
- ShapeResultCopyRangeTest,
- testing::ValuesIn(shape_result_copy_range_test_data));
-
-// Split a ShapeResult and combine them should match to the original result.
-TEST_P(ShapeResultCopyRangeTest, Split) {
- const auto& test_data = GetParam();
- String string(test_data.string);
- TextDirection direction = test_data.direction;
-
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-
- // Split the result.
- scoped_refptr<ShapeResult> result1 = ShapeResult::Create(&font, 0, direction);
- result->CopyRange(0, test_data.break_point, result1.get());
- EXPECT_EQ(test_data.break_point, result1->NumCharacters());
- EXPECT_EQ(0u, result1->StartIndexForResult());
- EXPECT_EQ(test_data.break_point, result1->EndIndexForResult());
-
- scoped_refptr<ShapeResult> result2 = ShapeResult::Create(&font, 0, direction);
- result->CopyRange(test_data.break_point, string.length(), result2.get());
- EXPECT_EQ(string.length() - test_data.break_point, result2->NumCharacters());
- EXPECT_EQ(test_data.break_point, result2->StartIndexForResult());
- EXPECT_EQ(string.length(), result2->EndIndexForResult());
-
- // Combine them.
- scoped_refptr<ShapeResult> composite_result =
- ShapeResult::Create(&font, 0, direction);
- result1->CopyRange(0, test_data.break_point, composite_result.get());
- result2->CopyRange(0, string.length(), composite_result.get());
- EXPECT_EQ(string.length(), composite_result->NumCharacters());
-
- // Test character indexes match.
- Vector<unsigned> expected_character_indexes =
- TestInfo(result)->CharacterIndexesForTesting();
- Vector<unsigned> composite_character_indexes =
- TestInfo(result)->CharacterIndexesForTesting();
- EXPECT_EQ(expected_character_indexes, composite_character_indexes);
-}
-
-// Shape ranges and combine them shold match to the result of shaping the whole
-// string.
-TEST_P(ShapeResultCopyRangeTest, ShapeRange) {
- const auto& test_data = GetParam();
- String string(test_data.string);
- TextDirection direction = test_data.direction;
-
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-
- // Shape each range.
- scoped_refptr<ShapeResult> result1 =
- shaper.Shape(&font, direction, 0, test_data.break_point);
- EXPECT_EQ(test_data.break_point, result1->NumCharacters());
- scoped_refptr<ShapeResult> result2 =
- shaper.Shape(&font, direction, test_data.break_point, string.length());
- EXPECT_EQ(string.length() - test_data.break_point, result2->NumCharacters());
-
- // Combine them.
- scoped_refptr<ShapeResult> composite_result =
- ShapeResult::Create(&font, 0, direction);
- result1->CopyRange(0, test_data.break_point, composite_result.get());
- result2->CopyRange(0, string.length(), composite_result.get());
- EXPECT_EQ(string.length(), composite_result->NumCharacters());
-
- // Test character indexes match.
- Vector<unsigned> expected_character_indexes =
- TestInfo(result)->CharacterIndexesForTesting();
- Vector<unsigned> composite_character_indexes =
- TestInfo(result)->CharacterIndexesForTesting();
- EXPECT_EQ(expected_character_indexes, composite_character_indexes);
-}
-
-TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeIntoLatin) {
- String string = To16Bit("Testing ShapeResult::createSubRun", 33);
- TextDirection direction = TextDirection::kLtr;
-
- HarfBuzzShaper shaper(string.Characters16(), 33);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-
- scoped_refptr<ShapeResult> composite_result =
- ShapeResult::Create(&font, 0, direction);
- result->CopyRange(0, 10, composite_result.get());
- result->CopyRange(10, 20, composite_result.get());
- result->CopyRange(20, 30, composite_result.get());
- result->CopyRange(30, 33, composite_result.get());
-
- EXPECT_EQ(result->NumCharacters(), composite_result->NumCharacters());
- EXPECT_EQ(result->SnappedWidth(), composite_result->SnappedWidth());
- EXPECT_EQ(result->Bounds(), composite_result->Bounds());
- EXPECT_EQ(result->SnappedStartPositionForOffset(0),
- composite_result->SnappedStartPositionForOffset(0));
- EXPECT_EQ(result->SnappedStartPositionForOffset(15),
- composite_result->SnappedStartPositionForOffset(15));
- EXPECT_EQ(result->SnappedStartPositionForOffset(30),
- composite_result->SnappedStartPositionForOffset(30));
- EXPECT_EQ(result->SnappedStartPositionForOffset(33),
- composite_result->SnappedStartPositionForOffset(33));
-}
-
-TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeIntoArabicThaiHanLatin) {
- UChar mixed_string[] = {0x628, 0x20, 0x64A, 0x629, 0x20, 0xE20, 0x65E5, 0x62};
- TextDirection direction = TextDirection::kLtr;
-
- HarfBuzzShaper shaper(mixed_string, 8);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-
- // Check width and bounds are not too much different. ".2" is heuristic.
- EXPECT_NEAR(result->Width(), result->Bounds().Width(), result->Width() * .2);
-
- scoped_refptr<ShapeResult> composite_result =
- ShapeResult::Create(&font, 0, direction);
- result->CopyRange(0, 4, composite_result.get());
- result->CopyRange(4, 6, composite_result.get());
- result->CopyRange(6, 8, composite_result.get());
-
- EXPECT_EQ(result->NumCharacters(), composite_result->NumCharacters());
- EXPECT_EQ(result->SnappedWidth(), composite_result->SnappedWidth());
- EXPECT_TRUE(composite_result->Bounds().Contains(result->Bounds()))
- << composite_result->Bounds() << "/" << result->Bounds();
- EXPECT_EQ(result->SnappedStartPositionForOffset(0),
- composite_result->SnappedStartPositionForOffset(0));
- EXPECT_EQ(result->SnappedStartPositionForOffset(1),
- composite_result->SnappedStartPositionForOffset(1));
- EXPECT_EQ(result->SnappedStartPositionForOffset(2),
- composite_result->SnappedStartPositionForOffset(2));
- EXPECT_EQ(result->SnappedStartPositionForOffset(3),
- composite_result->SnappedStartPositionForOffset(3));
- EXPECT_EQ(result->SnappedStartPositionForOffset(4),
- composite_result->SnappedStartPositionForOffset(4));
- EXPECT_EQ(result->SnappedStartPositionForOffset(5),
- composite_result->SnappedStartPositionForOffset(5));
- EXPECT_EQ(result->SnappedStartPositionForOffset(6),
- composite_result->SnappedStartPositionForOffset(6));
- EXPECT_EQ(result->SnappedStartPositionForOffset(7),
- composite_result->SnappedStartPositionForOffset(7));
- EXPECT_EQ(result->SnappedStartPositionForOffset(8),
- composite_result->SnappedStartPositionForOffset(8));
-}
-
-TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeAcrossRuns) {
- // Create 3 runs:
- // [0]: 1 character.
- // [1]: 5 characters.
- // [2]: 2 character.
- String mixed_string(u"\u65E5Hello\u65E5\u65E5");
- TextDirection direction = TextDirection::kLtr;
- HarfBuzzShaper shaper(mixed_string.Characters16(), mixed_string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-
- // Check width and bounds are not too much different. ".1" is heuristic.
- EXPECT_NEAR(result->Width(), result->Bounds().Width(), result->Width() * .1);
-
- // CopyRange(5, 7) should copy 1 character from [1] and 1 from [2].
- scoped_refptr<ShapeResult> target = ShapeResult::Create(&font, 0, direction);
- result->CopyRange(5, 7, target.get());
- EXPECT_EQ(2u, target->NumCharacters());
-}
-
-TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeSegmentGlyphBoundingBox) {
- String string(u"THello worldL");
- TextDirection direction = TextDirection::kLtr;
-
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result1 = shaper.Shape(&font, direction, 0, 6);
- scoped_refptr<ShapeResult> result2 =
- shaper.Shape(&font, direction, 6, string.length());
-
- scoped_refptr<ShapeResult> composite_result =
- ShapeResult::Create(&font, 0, direction);
- result1->CopyRange(0, 6, composite_result.get());
- result2->CopyRange(6, string.length(), composite_result.get());
-
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
- EXPECT_EQ(result->Bounds(), composite_result->Bounds());
-
- // Check width and bounds are not too much different. ".1" is heuristic.
- EXPECT_NEAR(result->Width(), result->Bounds().Width(), result->Width() * .1);
-}
-
-TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeBoundsLtr) {
- String string(u". ");
- TextDirection direction = TextDirection::kLtr;
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-
- // Because a space character does not have ink, the bounds of "." should be
- // the same as the bounds of ". ".
- scoped_refptr<ShapeResult> sub_range = result->SubRange(0, 1);
- EXPECT_EQ(sub_range->Bounds().Width(), result->Bounds().Width());
-}
-
-TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeBoundsRtl) {
- String string(u". ");
- TextDirection direction = TextDirection::kRtl;
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-
- // Because a space character does not have ink, the bounds of "." should be
- // the same as the bounds of ". ".
- scoped_refptr<ShapeResult> sub_range = result->SubRange(0, 1);
- EXPECT_EQ(sub_range->Bounds().Width(), result->Bounds().Width());
-}
-
-TEST_F(HarfBuzzShaperTest, SubRange) {
- String string(u"Hello world");
- TextDirection direction = TextDirection::kRtl;
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-
- scoped_refptr<ShapeResult> sub_range = result->SubRange(4, 7);
- DCHECK_EQ(4u, sub_range->StartIndexForResult());
- DCHECK_EQ(7u, sub_range->EndIndexForResult());
- DCHECK_EQ(3u, sub_range->NumCharacters());
- DCHECK_EQ(result->Direction(), sub_range->Direction());
-}
-
-TEST_F(HarfBuzzShaperTest, SafeToBreakLatinCommonLigatures) {
- FontDescription::VariantLigatures ligatures;
- ligatures.common = FontDescription::kEnabledLigaturesState;
-
- // MEgalopolis Extra has a lot of ligatures which this test relies on.
- Font testFont = blink::test::CreateTestFont(
- "MEgalopolis",
- blink::test::PlatformTestDataPath(
- "third_party/MEgalopolis/MEgalopolisExtra.woff"),
- 16, &ligatures);
-
- String string = To16Bit("ffi ff", 6);
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&testFont, TextDirection::kLtr);
-
- EXPECT_EQ(0u, result->NextSafeToBreakOffset(0)); // At start of string.
- EXPECT_EQ(3u, result->NextSafeToBreakOffset(1)); // At end of "ffi" ligature.
- EXPECT_EQ(3u, result->NextSafeToBreakOffset(2)); // At end of "ffi" ligature.
- EXPECT_EQ(3u, result->NextSafeToBreakOffset(3)); // At end of "ffi" ligature.
- EXPECT_EQ(4u, result->NextSafeToBreakOffset(4)); // After space.
- EXPECT_EQ(6u, result->NextSafeToBreakOffset(5)); // At end of "ff" ligature.
- EXPECT_EQ(6u, result->NextSafeToBreakOffset(6)); // At end of "ff" ligature.
-
- // Verify safe to break information in copied results to ensure that both
- // copying and multi-run break information works.
- scoped_refptr<ShapeResult> copied_result =
- ShapeResult::Create(&testFont, 0, TextDirection::kLtr);
- result->CopyRange(0, 3, copied_result.get());
- result->CopyRange(3, string.length(), copied_result.get());
-
- EXPECT_EQ(0u, copied_result->NextSafeToBreakOffset(0));
- EXPECT_EQ(3u, copied_result->NextSafeToBreakOffset(1));
- EXPECT_EQ(3u, copied_result->NextSafeToBreakOffset(2));
- EXPECT_EQ(3u, copied_result->NextSafeToBreakOffset(3));
- EXPECT_EQ(4u, copied_result->NextSafeToBreakOffset(4));
- EXPECT_EQ(6u, copied_result->NextSafeToBreakOffset(5));
- EXPECT_EQ(6u, copied_result->NextSafeToBreakOffset(6));
-}
-
-TEST_F(HarfBuzzShaperTest, SafeToBreakPreviousLatinCommonLigatures) {
- FontDescription::VariantLigatures ligatures;
- ligatures.common = FontDescription::kEnabledLigaturesState;
-
- // MEgalopolis Extra has a lot of ligatures which this test relies on.
- Font testFont = blink::test::CreateTestFont(
- "MEgalopolis",
- blink::test::PlatformTestDataPath(
- "third_party/MEgalopolis/MEgalopolisExtra.woff"),
- 16, &ligatures);
-
- String string = To16Bit("ffi ff", 6);
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&testFont, TextDirection::kLtr);
-
- EXPECT_EQ(6u, result->PreviousSafeToBreakOffset(6)); // At end of "ff" liga.
- EXPECT_EQ(4u, result->PreviousSafeToBreakOffset(5)); // At end of "ff" liga.
- EXPECT_EQ(4u, result->PreviousSafeToBreakOffset(4)); // After space.
- EXPECT_EQ(3u, result->PreviousSafeToBreakOffset(3)); // At end of "ffi" liga.
- EXPECT_EQ(0u, result->PreviousSafeToBreakOffset(2)); // At start of string.
- EXPECT_EQ(0u, result->PreviousSafeToBreakOffset(1)); // At start of string.
- EXPECT_EQ(0u, result->PreviousSafeToBreakOffset(0)); // At start of string.
-
- // Verify safe to break information in copied results to ensure that both
- // copying and multi-run break information works.
- scoped_refptr<ShapeResult> copied_result =
- ShapeResult::Create(&testFont, 0, TextDirection::kLtr);
- result->CopyRange(0, 3, copied_result.get());
- result->CopyRange(3, string.length(), copied_result.get());
-
- EXPECT_EQ(6u, copied_result->PreviousSafeToBreakOffset(6));
- EXPECT_EQ(4u, copied_result->PreviousSafeToBreakOffset(5));
- EXPECT_EQ(4u, copied_result->PreviousSafeToBreakOffset(4));
- EXPECT_EQ(3u, copied_result->PreviousSafeToBreakOffset(3));
- EXPECT_EQ(0u, copied_result->PreviousSafeToBreakOffset(2));
- EXPECT_EQ(0u, copied_result->PreviousSafeToBreakOffset(1));
- EXPECT_EQ(0u, copied_result->PreviousSafeToBreakOffset(0));
-}
-
-TEST_F(HarfBuzzShaperTest, SafeToBreakLatinDiscretionaryLigatures) {
- FontDescription::VariantLigatures ligatures;
- ligatures.common = FontDescription::kEnabledLigaturesState;
- ligatures.discretionary = FontDescription::kEnabledLigaturesState;
-
- // MEgalopolis Extra has a lot of ligatures which this test relies on.
- Font testFont = blink::test::CreateTestFont(
- "MEgalopolis",
- blink::test::PlatformTestDataPath(
- "third_party/MEgalopolis/MEgalopolisExtra.woff"),
- 16, &ligatures);
-
- // RA and CA form ligatures, most glyph pairs have kerning.
- String string(u"ABRACADABRA");
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&testFont, TextDirection::kLtr);
- EXPECT_EQ(6u, result->NextSafeToBreakOffset(1)); // After CA ligature.
- EXPECT_EQ(6u, result->NextSafeToBreakOffset(6)); // After CA ligature.
- EXPECT_EQ(11u, result->NextSafeToBreakOffset(7)); // At end of string.
- EXPECT_EQ(11u, result->NextSafeToBreakOffset(9)); // At end of string.
- EXPECT_EQ(11u, result->NextSafeToBreakOffset(10)); // At end of string.
-
- // Add zero-width spaces at the safe to break offsets.
- String refString(u"ABRACA\u200BDAB\u200BRA");
- HarfBuzzShaper refShaper(refString.Characters16(), refString.length());
- scoped_refptr<ShapeResult> referenceResult =
- refShaper.Shape(&testFont, TextDirection::kLtr);
-
- // Results should be identical if it truly is safe to break at the designated
- // safe-to-break offsets
- EXPECT_EQ(result->SnappedWidth(), referenceResult->SnappedWidth());
- EXPECT_EQ(result->Bounds(), referenceResult->Bounds());
- EXPECT_EQ(result->SnappedStartPositionForOffset(0),
- referenceResult->SnappedStartPositionForOffset(0));
- EXPECT_EQ(result->SnappedStartPositionForOffset(1),
- referenceResult->SnappedStartPositionForOffset(1));
- EXPECT_EQ(result->SnappedStartPositionForOffset(2),
- referenceResult->SnappedStartPositionForOffset(2));
- EXPECT_EQ(result->SnappedStartPositionForOffset(3),
- referenceResult->SnappedStartPositionForOffset(3));
- EXPECT_EQ(result->SnappedStartPositionForOffset(4),
- referenceResult->SnappedStartPositionForOffset(4));
- EXPECT_EQ(result->SnappedStartPositionForOffset(5),
- referenceResult->SnappedStartPositionForOffset(5));
-
- // First zero-width space is at position 6 so the the matching character in
- // the reference results is 7.
- EXPECT_EQ(result->SnappedStartPositionForOffset(6),
- referenceResult->SnappedStartPositionForOffset(7));
- EXPECT_EQ(result->SnappedStartPositionForOffset(7),
- referenceResult->SnappedStartPositionForOffset(8));
- EXPECT_EQ(result->SnappedStartPositionForOffset(8),
- referenceResult->SnappedStartPositionForOffset(9));
-
- // Second zero-width space is at position 9 so the the matching character in
- // the reference results is 11.
- EXPECT_EQ(result->SnappedStartPositionForOffset(9),
- referenceResult->SnappedStartPositionForOffset(11));
- EXPECT_EQ(result->SnappedStartPositionForOffset(10),
- referenceResult->SnappedStartPositionForOffset(12));
-}
-
-// TODO(layout-dev): This test fails on Mac due to AAT shaping.
-TEST_F(HarfBuzzShaperTest, DISABLED_SafeToBreakArabicCommonLigatures) {
- FontDescription::VariantLigatures ligatures;
- ligatures.common = FontDescription::kEnabledLigaturesState;
-
- // كسر الاختبار
- String string(
- u"\u0643\u0633\u0631\u0020\u0627\u0644\u0627\u062E\u062A\u0628\u0627"
- u"\u0631");
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kRtl);
-
- // Safe to break at 0, 3, 4, 5, 7, and 11.
- EXPECT_EQ(0u, result->NextSafeToBreakOffset(0));
- EXPECT_EQ(3u, result->NextSafeToBreakOffset(1));
- EXPECT_EQ(3u, result->NextSafeToBreakOffset(2));
- EXPECT_EQ(3u, result->NextSafeToBreakOffset(3));
- EXPECT_EQ(4u, result->NextSafeToBreakOffset(4));
- EXPECT_EQ(5u, result->NextSafeToBreakOffset(5));
- EXPECT_EQ(7u, result->NextSafeToBreakOffset(6));
- EXPECT_EQ(7u, result->NextSafeToBreakOffset(7));
- EXPECT_EQ(11u, result->NextSafeToBreakOffset(8));
- EXPECT_EQ(11u, result->NextSafeToBreakOffset(9));
- EXPECT_EQ(11u, result->NextSafeToBreakOffset(10));
- EXPECT_EQ(11u, result->NextSafeToBreakOffset(11));
- EXPECT_EQ(12u, result->NextSafeToBreakOffset(12));
-}
-
-// TODO(layout-dev): Expand RTL test coverage and add tests for mixed
-// directionality strings.
-
-// Test when some characters are missing in |runs_|.
-// RTL on Mac may not have runs for all characters. crbug.com/774034
-TEST_P(ShapeParameterTest, SafeToBreakMissingRun) {
- TextDirection direction = GetParam();
- scoped_refptr<ShapeResult> result = ShapeResult::Create(&font, 7, direction);
- result->InsertRunForTesting(2, 1, direction, {0});
- result->InsertRunForTesting(3, 3, direction, {0, 1});
- // The character index 7 is missing.
- result->InsertRunForTesting(8, 2, direction, {0});
-
- EXPECT_EQ(2u, result->NextSafeToBreakOffset(2));
- EXPECT_EQ(3u, result->NextSafeToBreakOffset(3));
- EXPECT_EQ(4u, result->NextSafeToBreakOffset(4));
- EXPECT_EQ(6u, result->NextSafeToBreakOffset(5));
- EXPECT_EQ(6u, result->NextSafeToBreakOffset(6));
- EXPECT_EQ(8u, result->NextSafeToBreakOffset(7));
- EXPECT_EQ(8u, result->NextSafeToBreakOffset(8));
- EXPECT_EQ(10u, result->NextSafeToBreakOffset(9));
-
- EXPECT_EQ(2u, result->PreviousSafeToBreakOffset(2));
- EXPECT_EQ(3u, result->PreviousSafeToBreakOffset(3));
- EXPECT_EQ(4u, result->PreviousSafeToBreakOffset(4));
- EXPECT_EQ(4u, result->PreviousSafeToBreakOffset(5));
- EXPECT_EQ(6u, result->PreviousSafeToBreakOffset(6));
- EXPECT_EQ(6u, result->PreviousSafeToBreakOffset(7));
- EXPECT_EQ(8u, result->PreviousSafeToBreakOffset(8));
- EXPECT_EQ(8u, result->PreviousSafeToBreakOffset(9));
-}
-
-// Call this to ensure your test string has some kerning going on.
-static bool KerningIsHappening(const FontDescription& font_description,
- TextDirection direction,
- const String& str) {
- FontDescription no_kern = font_description;
- no_kern.SetKerning(FontDescription::kNoneKerning);
-
- FontDescription kern = font_description;
- kern.SetKerning(FontDescription::kAutoKerning);
-
- Font font_no_kern(no_kern);
- font_no_kern.Update(nullptr);
-
- Font font_kern(kern);
- font_kern.Update(nullptr);
-
- HarfBuzzShaper shaper(str.Characters16(), str.length());
-
- scoped_refptr<ShapeResult> result_no_kern =
- shaper.Shape(&font_no_kern, direction);
- scoped_refptr<ShapeResult> result_kern = shaper.Shape(&font_kern, direction);
-
- for (unsigned i = 0; i < str.length(); i++) {
- if (result_no_kern->PositionForOffset(i) !=
- result_kern->PositionForOffset(i))
- return true;
- }
- return false;
-}
-
-TEST_F(HarfBuzzShaperTest, KerningIsHappeningWorks) {
- EXPECT_TRUE(
- KerningIsHappening(font_description, TextDirection::kLtr, u"AVOID"));
- EXPECT_FALSE(
- KerningIsHappening(font_description, TextDirection::kLtr, u"NOID"));
-
- // We won't kern vertically with the default font.
- font_description.SetOrientation(FontOrientation::kVerticalUpright);
-
- EXPECT_FALSE(
- KerningIsHappening(font_description, TextDirection::kLtr, u"AVOID"));
- EXPECT_FALSE(
- KerningIsHappening(font_description, TextDirection::kLtr, u"NOID"));
-}
-
-TEST_F(HarfBuzzShaperTest,
- ShapeHorizontalWithoutSubpixelPositionWithoutKerningIsRounded) {
- ScopedSubpixelOverride subpixel_override(false);
-
- String string(u"NOID");
- TextDirection direction = TextDirection::kLtr;
- ASSERT_FALSE(KerningIsHappening(font_description, direction, string));
-
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-
- for (unsigned i = 0; i < string.length(); i++) {
- float position = result->PositionForOffset(i);
- EXPECT_EQ(round(position), position)
- << "Position not rounded at offset " << i;
- }
-}
-
-TEST_F(HarfBuzzShaperTest,
- ShapeHorizontalWithSubpixelPositionWithoutKerningIsNotRounded) {
- ScopedSubpixelOverride subpixel_override(true);
-
- String string(u"NOID");
- TextDirection direction = TextDirection::kLtr;
- ASSERT_FALSE(KerningIsHappening(font_description, direction, string));
-
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-
- for (unsigned i = 0; i < string.length(); i++) {
- float position = result->PositionForOffset(i);
- if (round(position) != position)
- return;
- }
-
- EXPECT_TRUE(false) << "No unrounded positions found";
-}
-
-TEST_F(HarfBuzzShaperTest,
- ShapeHorizontalWithoutSubpixelPositionWithKerningIsRounded) {
- ScopedSubpixelOverride subpixel_override(false);
-
- String string(u"AVOID");
- TextDirection direction = TextDirection::kLtr;
- ASSERT_TRUE(KerningIsHappening(font_description, direction, string));
-
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-
- for (unsigned i = 0; i < string.length(); i++) {
- float position = result->PositionForOffset(i);
- EXPECT_EQ(round(position), position)
- << "Position not rounded at offset " << i;
- }
-}
-
-TEST_F(HarfBuzzShaperTest,
- ShapeHorizontalWithSubpixelPositionWithKerningIsNotRounded) {
- ScopedSubpixelOverride subpixel_override(true);
-
- String string(u"AVOID");
- TextDirection direction = TextDirection::kLtr;
- ASSERT_TRUE(KerningIsHappening(font_description, direction, string));
-
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-
- for (unsigned i = 0; i < string.length(); i++) {
- float position = result->PositionForOffset(i);
- if (round(position) != position)
- return;
- }
-
- EXPECT_TRUE(false) << "No unrounded positions found";
-}
-
-TEST_F(HarfBuzzShaperTest, ShapeVerticalWithoutSubpixelPositionIsRounded) {
- ScopedSubpixelOverride subpixel_override(false);
-
- font_description.SetOrientation(FontOrientation::kVerticalUpright);
- font = Font(font_description);
- font.Update(nullptr);
-
- String string(u"\u65E5\u65E5\u65E5");
- TextDirection direction = TextDirection::kLtr;
-
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-
- for (unsigned i = 0; i < string.length(); i++) {
- float position = result->PositionForOffset(i);
- EXPECT_EQ(round(position), position)
- << "Position not rounded at offset " << i;
- }
-}
-
-TEST_F(HarfBuzzShaperTest, ShapeVerticalWithSubpixelPositionIsRounded) {
- ScopedSubpixelOverride subpixel_override(true);
-
- font_description.SetOrientation(FontOrientation::kVerticalUpright);
- font = Font(font_description);
- font.Update(nullptr);
-
- String string(u"\u65E5\u65E5\u65E5");
- TextDirection direction = TextDirection::kLtr;
-
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
-
- // Vertical text is never subpixel positioned.
- for (unsigned i = 0; i < string.length(); i++) {
- float position = result->PositionForOffset(i);
- EXPECT_EQ(round(position), position)
- << "Position not rounded at offset " << i;
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc
new file mode 100644
index 00000000000..264a94398a9
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.cc
@@ -0,0 +1,448 @@
+/*
+ * Copyright (c) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h"
+
+#include <memory>
+
+#include "build/build_config.h"
+#include "third_party/blink/renderer/platform/fonts/font_cache.h"
+#include "third_party/blink/renderer/platform/fonts/font_global_context.h"
+#include "third_party/blink/renderer/platform/fonts/font_platform_data.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h"
+#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
+#include "third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h"
+#include "third_party/blink/renderer/platform/fonts/unicode_range_set.h"
+#include "third_party/blink/renderer/platform/histogram.h"
+#include "third_party/blink/renderer/platform/resolution_units.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/math_extras.h"
+
+#include <hb-ot.h>
+#include <hb.h>
+#if defined(OS_MACOSX)
+#include <hb-coretext.h>
+#endif
+
+#include <SkPaint.h>
+#include <SkPath.h>
+#include <SkPoint.h>
+#include <SkRect.h>
+#include <SkStream.h>
+#include <SkTypeface.h>
+
+namespace blink {
+
+void HbFontDeleter::operator()(hb_font_t* font) {
+ if (font)
+ hb_font_destroy(font);
+}
+
+void HbFaceDeleter::operator()(hb_face_t* face) {
+ if (face)
+ hb_face_destroy(face);
+}
+
+struct HbSetDeleter {
+ void operator()(hb_set_t* set) {
+ if (set)
+ hb_set_destroy(set);
+ }
+};
+
+using HbSetUniquePtr = std::unique_ptr<hb_set_t, HbSetDeleter>;
+
+static scoped_refptr<HbFontCacheEntry> CreateHbFontCacheEntry(hb_face_t*);
+
+HarfBuzzFace::HarfBuzzFace(FontPlatformData* platform_data, uint64_t unique_id)
+ : platform_data_(platform_data), unique_id_(unique_id) {
+ HarfBuzzFontCache::AddResult result =
+ FontGlobalContext::GetHarfBuzzFontCache().insert(unique_id_, nullptr);
+ if (result.is_new_entry) {
+ HbFaceUniquePtr face(CreateFace());
+ result.stored_value->value = CreateHbFontCacheEntry(face.get());
+ }
+ result.stored_value->value->AddRef();
+ unscaled_font_ = result.stored_value->value->HbFont();
+ harfbuzz_font_data_ = result.stored_value->value->HbFontData();
+}
+
+HarfBuzzFace::~HarfBuzzFace() {
+ HarfBuzzFontCache::iterator result =
+ FontGlobalContext::GetHarfBuzzFontCache().find(unique_id_);
+ SECURITY_DCHECK(result != FontGlobalContext::GetHarfBuzzFontCache().end());
+ DCHECK(!result.Get()->value->HasOneRef());
+ result.Get()->value->Release();
+ if (result.Get()->value->HasOneRef())
+ FontGlobalContext::GetHarfBuzzFontCache().erase(unique_id_);
+}
+
+static hb_bool_t HarfBuzzGetGlyph(hb_font_t* hb_font,
+ void* font_data,
+ hb_codepoint_t unicode,
+ hb_codepoint_t variation_selector,
+ hb_codepoint_t* glyph,
+ void* user_data) {
+ HarfBuzzFontData* hb_font_data =
+ reinterpret_cast<HarfBuzzFontData*>(font_data);
+
+ CHECK(hb_font_data);
+ if (hb_font_data->range_set_ && !hb_font_data->range_set_->Contains(unicode))
+ return false;
+
+ return hb_font_get_glyph(hb_font_get_parent(hb_font), unicode,
+ variation_selector, glyph);
+}
+
+static hb_position_t HarfBuzzGetGlyphHorizontalAdvance(hb_font_t* hb_font,
+ void* font_data,
+ hb_codepoint_t glyph,
+ void* user_data) {
+ HarfBuzzFontData* hb_font_data =
+ reinterpret_cast<HarfBuzzFontData*>(font_data);
+ hb_position_t advance = 0;
+
+ SkiaTextMetrics(&hb_font_data->paint_)
+ .GetGlyphWidthForHarfBuzz(glyph, &advance);
+ return advance;
+}
+
+static hb_bool_t HarfBuzzGetGlyphVerticalOrigin(hb_font_t* hb_font,
+ void* font_data,
+ hb_codepoint_t glyph,
+ hb_position_t* x,
+ hb_position_t* y,
+ void* user_data) {
+ HarfBuzzFontData* hb_font_data =
+ reinterpret_cast<HarfBuzzFontData*>(font_data);
+ scoped_refptr<OpenTypeVerticalData> vertical_data =
+ hb_font_data->VerticalData();
+ if (!vertical_data)
+ return false;
+
+ float result[] = {0, 0};
+ Glyph the_glyph = glyph;
+ vertical_data->GetVerticalTranslationsForGlyphs(hb_font_data->paint_,
+ &the_glyph, 1, result);
+ *x = SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(-result[0]);
+ *y = SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(-result[1]);
+ return true;
+}
+
+static hb_position_t HarfBuzzGetGlyphVerticalAdvance(hb_font_t* hb_font,
+ void* font_data,
+ hb_codepoint_t glyph,
+ void* user_data) {
+ HarfBuzzFontData* hb_font_data =
+ reinterpret_cast<HarfBuzzFontData*>(font_data);
+ scoped_refptr<OpenTypeVerticalData> vertical_data =
+ hb_font_data->VerticalData();
+ if (!vertical_data) {
+ return SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(
+ hb_font_data->height_fallback_);
+ }
+
+ Glyph the_glyph = glyph;
+ float advance_height = -vertical_data->AdvanceHeight(the_glyph);
+ return SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(
+ SkFloatToScalar(advance_height));
+}
+
+static hb_position_t HarfBuzzGetGlyphHorizontalKerning(
+ hb_font_t*,
+ void* font_data,
+ hb_codepoint_t left_glyph,
+ hb_codepoint_t right_glyph,
+ void*) {
+ HarfBuzzFontData* hb_font_data =
+ reinterpret_cast<HarfBuzzFontData*>(font_data);
+ if (hb_font_data->paint_.isVerticalText()) {
+ // We don't support cross-stream kerning
+ return 0;
+ }
+
+ SkTypeface* typeface = hb_font_data->paint_.getTypeface();
+
+ const uint16_t glyphs[2] = {static_cast<uint16_t>(left_glyph),
+ static_cast<uint16_t>(right_glyph)};
+ int32_t kerning_adjustments[1] = {0};
+
+ if (typeface->getKerningPairAdjustments(glyphs, 2, kerning_adjustments)) {
+ SkScalar upm = SkIntToScalar(typeface->getUnitsPerEm());
+ SkScalar size = hb_font_data->paint_.getTextSize();
+ return SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(
+ SkIntToScalar(kerning_adjustments[0]) * size / upm);
+ }
+
+ return 0;
+}
+
+static hb_bool_t HarfBuzzGetGlyphExtents(hb_font_t* hb_font,
+ void* font_data,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t* extents,
+ void* user_data) {
+ HarfBuzzFontData* hb_font_data =
+ reinterpret_cast<HarfBuzzFontData*>(font_data);
+
+ SkiaTextMetrics(&hb_font_data->paint_)
+ .GetGlyphExtentsForHarfBuzz(glyph, extents);
+ return true;
+}
+
+static inline bool TableHasSpace(hb_face_t* face,
+ hb_set_t* glyphs,
+ hb_tag_t tag,
+ hb_codepoint_t space) {
+ unsigned count = hb_ot_layout_table_get_lookup_count(face, tag);
+ for (unsigned i = 0; i < count; i++) {
+ hb_ot_layout_lookup_collect_glyphs(face, tag, i, glyphs, glyphs, glyphs,
+ nullptr);
+ if (hb_set_has(glyphs, space))
+ return true;
+ }
+ return false;
+}
+
+static bool GetSpaceGlyph(hb_font_t* font, hb_codepoint_t& space) {
+ return hb_font_get_nominal_glyph(font, kSpaceCharacter, &space);
+}
+
+bool HarfBuzzFace::HasSpaceInLigaturesOrKerning(TypesettingFeatures features) {
+ const hb_codepoint_t kInvalidCodepoint = static_cast<hb_codepoint_t>(-1);
+ hb_codepoint_t space = kInvalidCodepoint;
+
+ HbSetUniquePtr glyphs(hb_set_create());
+
+ // Check whether computing is needed and compute for gpos/gsub.
+ if (features & kKerning &&
+ harfbuzz_font_data_->space_in_gpos_ ==
+ HarfBuzzFontData::SpaceGlyphInOpenTypeTables::Unknown) {
+ if (space == kInvalidCodepoint && !GetSpaceGlyph(unscaled_font_, space))
+ return false;
+ // Compute for gpos.
+ hb_face_t* face = hb_font_get_face(unscaled_font_);
+ DCHECK(face);
+ harfbuzz_font_data_->space_in_gpos_ =
+ hb_ot_layout_has_positioning(face) &&
+ TableHasSpace(face, glyphs.get(), HB_OT_TAG_GPOS, space)
+ ? HarfBuzzFontData::SpaceGlyphInOpenTypeTables::Present
+ : HarfBuzzFontData::SpaceGlyphInOpenTypeTables::NotPresent;
+ }
+
+ hb_set_clear(glyphs.get());
+
+ if (features & kLigatures &&
+ harfbuzz_font_data_->space_in_gsub_ ==
+ HarfBuzzFontData::SpaceGlyphInOpenTypeTables::Unknown) {
+ if (space == kInvalidCodepoint && !GetSpaceGlyph(unscaled_font_, space))
+ return false;
+ // Compute for gpos.
+ hb_face_t* face = hb_font_get_face(unscaled_font_);
+ DCHECK(face);
+ harfbuzz_font_data_->space_in_gsub_ =
+ hb_ot_layout_has_substitution(face) &&
+ TableHasSpace(face, glyphs.get(), HB_OT_TAG_GSUB, space)
+ ? HarfBuzzFontData::SpaceGlyphInOpenTypeTables::Present
+ : HarfBuzzFontData::SpaceGlyphInOpenTypeTables::NotPresent;
+ }
+
+ return (features & kKerning &&
+ harfbuzz_font_data_->space_in_gpos_ ==
+ HarfBuzzFontData::SpaceGlyphInOpenTypeTables::Present) ||
+ (features & kLigatures &&
+ harfbuzz_font_data_->space_in_gsub_ ==
+ HarfBuzzFontData::SpaceGlyphInOpenTypeTables::Present);
+}
+
+unsigned HarfBuzzFace::UnitsPerEmFromHeadTable() {
+ hb_face_t* face = hb_font_get_face(unscaled_font_);
+ return hb_face_get_upem(face);
+}
+
+bool HarfBuzzFace::ShouldSubpixelPosition() {
+ return harfbuzz_font_data_->paint_.isSubpixelText();
+}
+
+static hb_font_funcs_t* HarfBuzzSkiaGetFontFuncs() {
+ hb_font_funcs_t* funcs = FontGlobalContext::GetHarfBuzzFontFuncs();
+
+ // We don't set callback functions which we can't support.
+ // HarfBuzz will use the fallback implementation if they aren't set.
+ if (!funcs) {
+ funcs = hb_font_funcs_create();
+ hb_font_funcs_set_glyph_func(funcs, HarfBuzzGetGlyph, nullptr, nullptr);
+ hb_font_funcs_set_glyph_h_advance_func(
+ funcs, HarfBuzzGetGlyphHorizontalAdvance, nullptr, nullptr);
+ hb_font_funcs_set_glyph_h_kerning_func(
+ funcs, HarfBuzzGetGlyphHorizontalKerning, nullptr, nullptr);
+ hb_font_funcs_set_glyph_v_advance_func(
+ funcs, HarfBuzzGetGlyphVerticalAdvance, nullptr, nullptr);
+ hb_font_funcs_set_glyph_v_origin_func(funcs, HarfBuzzGetGlyphVerticalOrigin,
+ nullptr, nullptr);
+ hb_font_funcs_set_glyph_extents_func(funcs, HarfBuzzGetGlyphExtents,
+ nullptr, nullptr);
+ hb_font_funcs_make_immutable(funcs);
+ FontGlobalContext::SetHarfBuzzFontFuncs(funcs);
+ }
+ DCHECK(funcs);
+ return funcs;
+}
+
+static hb_blob_t* HarfBuzzSkiaGetTable(hb_face_t* face,
+ hb_tag_t tag,
+ void* user_data) {
+ SkTypeface* typeface = reinterpret_cast<SkTypeface*>(user_data);
+
+ const size_t table_size = typeface->getTableSize(tag);
+ if (!table_size) {
+ return nullptr;
+ }
+
+ char* buffer = reinterpret_cast<char*>(WTF::Partitions::FastMalloc(
+ table_size, WTF_HEAP_PROFILER_TYPE_NAME(HarfBuzzFontData)));
+ if (!buffer)
+ return nullptr;
+ size_t actual_size = typeface->getTableData(tag, 0, table_size, buffer);
+ if (table_size != actual_size) {
+ WTF::Partitions::FastFree(buffer);
+ return nullptr;
+ }
+ return hb_blob_create(const_cast<char*>(buffer), table_size,
+ HB_MEMORY_MODE_WRITABLE, buffer,
+ WTF::Partitions::FastFree);
+}
+
+static void DeleteTypefaceStream(void* stream_asset_ptr) {
+ SkStreamAsset* stream_asset =
+ reinterpret_cast<SkStreamAsset*>(stream_asset_ptr);
+ delete stream_asset;
+}
+
+hb_face_t* HarfBuzzFace::CreateFace() {
+#if defined(OS_MACOSX)
+ // hb_face_t needs to be instantiated using the CoreText constructor for
+ // compatibility with AAT font, in which case HarfBuzz' CoreText backend is
+ // used. If we encounter a FreeType backed SkTypeface, for variable fonts on
+ // Mac OS < 10.12, follow the regular OpenType-only codepath below.
+ if (platform_data_->CgFont()) {
+ hb_face_t* face = hb_coretext_face_create(platform_data_->CgFont());
+ DCHECK(face);
+ return face;
+ }
+#endif
+ hb_face_t* face = nullptr;
+
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(BooleanHistogram, zero_copy_success_histogram,
+ ("Blink.Fonts.HarfBuzzFaceZeroCopyAccess"));
+ SkTypeface* typeface = platform_data_->Typeface();
+ CHECK(typeface);
+ int ttc_index = 0;
+ SkStreamAsset* typeface_stream = typeface->openStream(&ttc_index);
+ if (typeface_stream && typeface_stream->getMemoryBase()) {
+ std::unique_ptr<hb_blob_t, void (*)(hb_blob_t*)> face_blob(
+ hb_blob_create(
+ reinterpret_cast<const char*>(typeface_stream->getMemoryBase()),
+ typeface_stream->getLength(), HB_MEMORY_MODE_READONLY,
+ typeface_stream, DeleteTypefaceStream),
+ hb_blob_destroy);
+ face = hb_face_create(face_blob.get(), ttc_index);
+ }
+
+ // Fallback to table copies if there is no in-memory access.
+ if (!face) {
+ face = hb_face_create_for_tables(HarfBuzzSkiaGetTable,
+ platform_data_->Typeface(), nullptr);
+ zero_copy_success_histogram.Count(false);
+ } else {
+ zero_copy_success_histogram.Count(true);
+ }
+
+ DCHECK(face);
+ return face;
+}
+
+scoped_refptr<HbFontCacheEntry> CreateHbFontCacheEntry(hb_face_t* face) {
+ HbFontUniquePtr ot_font(hb_font_create(face));
+ hb_ot_font_set_funcs(ot_font.get());
+ // Creating a sub font means that non-available functions
+ // are found from the parent.
+ hb_font_t* unscaled_font = hb_font_create_sub_font(ot_font.get());
+ scoped_refptr<HbFontCacheEntry> cache_entry =
+ HbFontCacheEntry::Create(unscaled_font);
+ hb_font_set_funcs(unscaled_font, HarfBuzzSkiaGetFontFuncs(),
+ cache_entry->HbFontData(), nullptr);
+ return cache_entry;
+}
+
+static_assert(
+ std::is_same<decltype(SkFontArguments::VariationPosition::Coordinate::axis),
+ decltype(hb_variation_t::tag)>::value &&
+ std::is_same<
+ decltype(SkFontArguments::VariationPosition::Coordinate::value),
+ decltype(hb_variation_t::value)>::value &&
+ sizeof(SkFontArguments::VariationPosition::Coordinate) ==
+ sizeof(hb_variation_t),
+ "Skia and HarfBuzz Variation parameter types must match in structure and "
+ "size.");
+
+hb_font_t* HarfBuzzFace::GetScaledFont(
+ scoped_refptr<UnicodeRangeSet> range_set,
+ VerticalLayoutCallbacks vertical_layout) const {
+ PaintFont paint_font;
+ platform_data_->SetupPaintFont(&paint_font);
+ paint_font.SetTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ harfbuzz_font_data_->range_set_ = std::move(range_set);
+ harfbuzz_font_data_->UpdateFallbackMetricsAndScale(
+ *platform_data_, paint_font.ToSkPaint(), vertical_layout);
+
+ int scale =
+ SkiaTextMetrics::SkiaScalarToHarfBuzzPosition(platform_data_->size());
+ hb_font_set_scale(unscaled_font_, scale, scale);
+ hb_font_set_ptem(unscaled_font_, platform_data_->size() / kCssPixelsPerPoint);
+
+ SkTypeface* typeface = harfbuzz_font_data_->paint_.getTypeface();
+ int axis_count = typeface->getVariationDesignPosition(nullptr, 0);
+ if (axis_count > 0) {
+ Vector<SkFontArguments::VariationPosition::Coordinate> axis_values;
+ axis_values.resize(axis_count);
+ if (typeface->getVariationDesignPosition(axis_values.data(),
+ axis_values.size()) > 0) {
+ hb_font_set_variations(
+ unscaled_font_, reinterpret_cast<hb_variation_t*>(axis_values.data()),
+ axis_values.size());
+ }
+ }
+
+ return unscaled_font_;
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h
new file mode 100644
index 00000000000..a2343852a90
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARFBUZZ_FACE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARFBUZZ_FACE_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/renderer/platform/fonts/typesetting_features.h"
+#include "third_party/blink/renderer/platform/fonts/unicode_range_set.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
+#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
+#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
+
+#include <hb.h>
+
+namespace blink {
+
+class FontPlatformData;
+struct HarfBuzzFontData;
+
+class HarfBuzzFace : public RefCounted<HarfBuzzFace> {
+ WTF_MAKE_NONCOPYABLE(HarfBuzzFace);
+
+ public:
+ static scoped_refptr<HarfBuzzFace> Create(FontPlatformData* platform_data,
+ uint64_t unique_id) {
+ return base::AdoptRef(new HarfBuzzFace(platform_data, unique_id));
+ }
+ ~HarfBuzzFace();
+
+ enum VerticalLayoutCallbacks { PrepareForVerticalLayout, NoVerticalLayout };
+
+ // In order to support the restricting effect of unicode-range optionally a
+ // range restriction can be passed in, which will restrict which glyphs we
+ // return in the harfBuzzGetGlyph function.
+ hb_font_t* GetScaledFont(scoped_refptr<UnicodeRangeSet>,
+ VerticalLayoutCallbacks) const;
+
+ bool HasSpaceInLigaturesOrKerning(TypesettingFeatures);
+ unsigned UnitsPerEmFromHeadTable();
+
+ bool ShouldSubpixelPosition();
+
+ private:
+ HarfBuzzFace(FontPlatformData*, uint64_t);
+
+ hb_face_t* CreateFace();
+ void PrepareHarfBuzzFontData();
+
+ FontPlatformData* platform_data_;
+ uint64_t unique_id_;
+ hb_font_t* unscaled_font_;
+ HarfBuzzFontData* harfbuzz_font_data_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARFBUZZ_FACE_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h
new file mode 100644
index 00000000000..83865f784bb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_font_cache.h
@@ -0,0 +1,151 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARFBUZZ_FONT_CACHE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARFBUZZ_FONT_CACHE_H_
+
+#include <memory>
+#include "third_party/blink/renderer/platform/fonts/font_metrics.h"
+#include "third_party/blink/renderer/platform/fonts/opentype/open_type_vertical_data.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h"
+#include "third_party/blink/renderer/platform/fonts/unicode_range_set.h"
+#include "third_party/blink/renderer/platform/wtf/assertions.h"
+
+struct hb_font_t;
+struct hb_face_t;
+
+namespace blink {
+
+struct HbFontDeleter {
+ void operator()(hb_font_t* font);
+};
+
+using HbFontUniquePtr = std::unique_ptr<hb_font_t, HbFontDeleter>;
+
+struct HbFaceDeleter {
+ void operator()(hb_face_t* face);
+};
+
+using HbFaceUniquePtr = std::unique_ptr<hb_face_t, HbFaceDeleter>;
+
+const unsigned kInvalidFallbackMetricsValue = static_cast<unsigned>(-1);
+
+// struct to carry user-pointer data for hb_font_t callback
+// functions/operations, that require information related to a font scaled to a
+// particular size.
+struct HarfBuzzFontData {
+ USING_FAST_MALLOC(HarfBuzzFontData);
+ WTF_MAKE_NONCOPYABLE(HarfBuzzFontData);
+
+ public:
+ HarfBuzzFontData()
+ : paint_(),
+ space_in_gpos_(SpaceGlyphInOpenTypeTables::Unknown),
+ space_in_gsub_(SpaceGlyphInOpenTypeTables::Unknown),
+ vertical_data_(nullptr),
+ range_set_(nullptr) {}
+
+ // The vertical origin and vertical advance functions in HarfBuzzFace require
+ // the ascent and height metrics as fallback in case no specific vertical
+ // layout information is found from the font.
+ void UpdateFallbackMetricsAndScale(
+ const FontPlatformData& platform_data,
+ const SkPaint& paint,
+ HarfBuzzFace::VerticalLayoutCallbacks vertical_layout) {
+ float ascent = 0;
+ float descent = 0;
+ unsigned dummy_ascent_inflation = 0;
+ unsigned dummy_descent_inflation = 0;
+
+ paint_ = paint;
+
+ if (UNLIKELY(vertical_layout == HarfBuzzFace::PrepareForVerticalLayout)) {
+ FontMetrics::AscentDescentWithHacks(
+ ascent, descent, dummy_ascent_inflation, dummy_descent_inflation,
+ platform_data, paint);
+ ascent_fallback_ = ascent;
+ // Simulate the rounding that FontMetrics does so far for returning the
+ // integer Height()
+ height_fallback_ = lroundf(ascent) + lroundf(descent);
+
+ int units_per_em =
+ platform_data.GetHarfBuzzFace()->UnitsPerEmFromHeadTable();
+ if (!units_per_em) {
+ DLOG(ERROR)
+ << "Units per EM is 0 for font used in vertical writing mode.";
+ }
+ size_per_unit_ = platform_data.size() / (units_per_em ? units_per_em : 1);
+ } else {
+ ascent_fallback_ = kInvalidFallbackMetricsValue;
+ height_fallback_ = kInvalidFallbackMetricsValue;
+ size_per_unit_ = kInvalidFallbackMetricsValue;
+ }
+ }
+
+ scoped_refptr<OpenTypeVerticalData> VerticalData() {
+ if (!vertical_data_) {
+ DCHECK_NE(ascent_fallback_, kInvalidFallbackMetricsValue);
+ DCHECK_NE(height_fallback_, kInvalidFallbackMetricsValue);
+ DCHECK_NE(size_per_unit_, kInvalidFallbackMetricsValue);
+
+ vertical_data_ =
+ OpenTypeVerticalData::CreateUnscaled(paint_.refTypeface());
+ }
+ vertical_data_->SetScaleAndFallbackMetrics(size_per_unit_, ascent_fallback_,
+ height_fallback_);
+ return vertical_data_;
+ }
+
+ SkPaint paint_;
+
+ // Capture these scaled fallback metrics from FontPlatformData so that a
+ // OpenTypeVerticalData object can be constructed from them when needed.
+ float size_per_unit_;
+ float ascent_fallback_;
+ float height_fallback_;
+
+ enum class SpaceGlyphInOpenTypeTables { Unknown, Present, NotPresent };
+
+ SpaceGlyphInOpenTypeTables space_in_gpos_;
+ SpaceGlyphInOpenTypeTables space_in_gsub_;
+
+ scoped_refptr<OpenTypeVerticalData> vertical_data_;
+ scoped_refptr<UnicodeRangeSet> range_set_;
+};
+
+// Though we have FontCache class, which provides the cache mechanism for
+// WebKit's font objects, we also need additional caching layer for HarfBuzz to
+// reduce the number of hb_font_t objects created. Without it, we would create
+// an hb_font_t object for every FontPlatformData object. But insted, we only
+// need one for each unique SkTypeface.
+// FIXME, crbug.com/609099: We should fix the FontCache to only keep one
+// FontPlatformData object independent of size, then consider using this here.
+class HbFontCacheEntry : public RefCounted<HbFontCacheEntry> {
+ public:
+ static scoped_refptr<HbFontCacheEntry> Create(hb_font_t* hb_font) {
+ DCHECK(hb_font);
+ return base::AdoptRef(new HbFontCacheEntry(hb_font));
+ }
+
+ hb_font_t* HbFont() { return hb_font_.get(); }
+ HarfBuzzFontData* HbFontData() { return hb_font_data_.get(); }
+
+ private:
+ explicit HbFontCacheEntry(hb_font_t* font)
+ : hb_font_(HbFontUniquePtr(font)),
+ hb_font_data_(std::make_unique<HarfBuzzFontData>()){};
+
+ HbFontUniquePtr hb_font_;
+ std::unique_ptr<HarfBuzzFontData> hb_font_data_;
+};
+
+typedef HashMap<uint64_t,
+ scoped_refptr<HbFontCacheEntry>,
+ WTF::IntHash<uint64_t>,
+ WTF::UnsignedWithZeroKeyHashTraits<uint64_t>>
+ HarfBuzzFontCache;
+
+} // namespace blink
+
+#endif
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc
new file mode 100644
index 00000000000..1666578e0dc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc
@@ -0,0 +1,1017 @@
+/*
+ * Copyright (c) 2012 Google Inc. All rights reserved.
+ * Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h"
+
+#include <hb.h>
+#include <unicode/uchar.h>
+#include <unicode/uscript.h>
+#include <algorithm>
+#include <memory>
+#include <utility>
+
+#include "base/memory/ptr_util.h"
+#include "third_party/blink/renderer/platform/fonts/font.h"
+#include "third_party/blink/renderer/platform/fonts/font_description.h"
+#include "third_party/blink/renderer/platform/fonts/font_fallback_iterator.h"
+#include "third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h"
+#include "third_party/blink/renderer/platform/fonts/small_caps_iterator.h"
+#include "third_party/blink/renderer/platform/fonts/utf16_text_iterator.h"
+#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
+#include "third_party/blink/renderer/platform/wtf/compiler.h"
+#include "third_party/blink/renderer/platform/wtf/deque.h"
+#include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
+#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
+
+namespace blink {
+
+namespace {
+
+#if DCHECK_IS_ON()
+// Check if the ShapeResult has the specified range.
+// |text| and |font| are only for logging.
+void CheckShapeResultRange(const ShapeResult* result,
+ unsigned start,
+ unsigned end,
+ const String& text,
+ const Font* font) {
+ DCHECK_LE(start, end);
+ unsigned length = end - start;
+ if (length == result->NumCharacters() &&
+ (!length || (start == result->StartIndexForResult() &&
+ end == result->EndIndexForResult())))
+ return;
+
+ // Log font-family/size as specified.
+ StringBuilder log;
+ log.Append("Font='");
+ const FontDescription& font_description = font->GetFontDescription();
+ for (const FontFamily* family = &font_description.Family();;) {
+ log.Append(family->Family());
+ family = family->Next();
+ if (!family)
+ break;
+ log.Append(", ");
+ }
+ log.Append(String::Format("', %f", font_description.ComputedSize()));
+
+ // Log the primary font with its family name in the font file.
+ const SimpleFontData* font_data = font->PrimaryFont();
+ if (font_data) {
+ const SkTypeface* typeface = font_data->PlatformData().Typeface();
+ SkString family_name;
+ typeface->getFamilyName(&family_name);
+ log.Append(", primary=");
+ log.Append(family_name.c_str());
+ }
+
+ // Log the text to shape.
+ log.Append(String::Format(": %u-%u -> %u-%u:", start, end,
+ result->StartIndexForResult(),
+ result->EndIndexForResult()));
+ for (unsigned i = start; i < end; ++i)
+ log.Append(String::Format(" %02X", text[i]));
+
+ log.Append(", result=");
+ result->ToString(&log);
+
+ NOTREACHED() << log.ToString();
+}
+#endif
+
+} // namespace
+
+enum ReshapeQueueItemAction { kReshapeQueueNextFont, kReshapeQueueRange };
+
+struct ReshapeQueueItem {
+ DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
+ ReshapeQueueItemAction action_;
+ unsigned start_index_;
+ unsigned num_characters_;
+ ReshapeQueueItem(ReshapeQueueItemAction action, unsigned start, unsigned num)
+ : action_(action), start_index_(start), num_characters_(num){};
+};
+
+template <typename T>
+class HarfBuzzScopedPtr {
+ STACK_ALLOCATED();
+ WTF_MAKE_NONCOPYABLE(HarfBuzzScopedPtr);
+
+ public:
+ typedef void (*DestroyFunction)(T*);
+
+ HarfBuzzScopedPtr(T* ptr, DestroyFunction destroy)
+ : ptr_(ptr), destroy_(destroy) {
+ DCHECK(destroy_);
+ }
+ ~HarfBuzzScopedPtr() {
+ if (ptr_)
+ (*destroy_)(ptr_);
+ }
+
+ T* Get() { return ptr_; }
+ void Set(T* ptr) { ptr_ = ptr; }
+
+ private:
+ T* ptr_;
+ DestroyFunction destroy_;
+};
+
+HarfBuzzShaper::HarfBuzzShaper(const String& text) : text_(text) {}
+
+using FeaturesVector = Vector<hb_feature_t, 6>;
+struct RangeData {
+ hb_buffer_t* buffer;
+ const Font* font;
+ TextDirection text_direction;
+ unsigned start;
+ unsigned end;
+ FeaturesVector font_features;
+ Deque<ReshapeQueueItem> reshape_queue;
+
+ hb_direction_t HarfBuzzDirection(CanvasRotationInVertical canvas_rotation) {
+ FontOrientation orientation = font->GetFontDescription().Orientation();
+ hb_direction_t direction =
+ IsVerticalAnyUpright(orientation) &&
+ (canvas_rotation ==
+ CanvasRotationInVertical::kRotateCanvasUpright)
+ ? HB_DIRECTION_TTB
+ : HB_DIRECTION_LTR;
+ return text_direction == TextDirection::kRtl
+ ? HB_DIRECTION_REVERSE(direction)
+ : direction;
+ }
+};
+
+struct BufferSlice {
+ unsigned start_character_index;
+ unsigned num_characters;
+ unsigned start_glyph_index;
+ unsigned num_glyphs;
+};
+
+namespace {
+
+// A port of hb_icu_script_to_script because harfbuzz on CrOS is built
+// without hb-icu. See http://crbug.com/356929
+static inline hb_script_t ICUScriptToHBScript(UScriptCode script) {
+ if (UNLIKELY(script == USCRIPT_INVALID_CODE))
+ return HB_SCRIPT_INVALID;
+
+ return hb_script_from_string(uscript_getShortName(script), -1);
+}
+
+void RoundHarfBuzzPosition(hb_position_t* value) {
+ if ((*value) & 0xFFFF) {
+ // There is a non-zero fractional part in the 16.16 value.
+ *value = static_cast<hb_position_t>(
+ round(static_cast<float>(*value) / (1 << 16)))
+ << 16;
+ }
+}
+
+void RoundHarfBuzzBufferPositions(hb_buffer_t* buffer) {
+ unsigned int len;
+ hb_glyph_position_t* glyph_positions =
+ hb_buffer_get_glyph_positions(buffer, &len);
+ for (unsigned int i = 0; i < len; i++) {
+ hb_glyph_position_t* pos = &glyph_positions[i];
+ RoundHarfBuzzPosition(&pos->x_offset);
+ RoundHarfBuzzPosition(&pos->y_offset);
+ RoundHarfBuzzPosition(&pos->x_advance);
+ RoundHarfBuzzPosition(&pos->y_advance);
+ }
+}
+
+inline bool ShapeRange(hb_buffer_t* buffer,
+ hb_feature_t* font_features,
+ unsigned font_features_size,
+ const SimpleFontData* current_font,
+ scoped_refptr<UnicodeRangeSet> current_font_range_set,
+ UScriptCode current_run_script,
+ hb_direction_t direction,
+ hb_language_t language) {
+ const FontPlatformData* platform_data = &(current_font->PlatformData());
+ HarfBuzzFace* face = platform_data->GetHarfBuzzFace();
+ if (!face) {
+ DLOG(ERROR) << "Could not create HarfBuzzFace from FontPlatformData.";
+ return false;
+ }
+
+ hb_buffer_set_language(buffer, language);
+ hb_buffer_set_script(buffer, ICUScriptToHBScript(current_run_script));
+ hb_buffer_set_direction(buffer, direction);
+
+ hb_font_t* hb_font =
+ face->GetScaledFont(std::move(current_font_range_set),
+ HB_DIRECTION_IS_VERTICAL(direction)
+ ? HarfBuzzFace::PrepareForVerticalLayout
+ : HarfBuzzFace::NoVerticalLayout);
+ hb_shape(hb_font, buffer, font_features, font_features_size);
+
+ // We cannot round all glyph positions during hb_shape because the
+ // hb_font_funcs_set_glyph_h_kerning_func only works for legacy kerning.
+ // OpenType uses gpos tables for kerning and harfbuzz does not call
+ // the callback to let us round as we go.
+ // Without this rounding, we get inconsistent spacing between kern points
+ // if subpixel positioning is disabled.
+ // See http://crbug.com/740385.
+ if (!face->ShouldSubpixelPosition())
+ RoundHarfBuzzBufferPositions(buffer);
+
+ return true;
+}
+
+BufferSlice ComputeSlice(RangeData* range_data,
+ const ReshapeQueueItem& current_queue_item,
+ const hb_glyph_info_t* glyph_info,
+ unsigned num_glyphs,
+ unsigned old_glyph_index,
+ unsigned new_glyph_index) {
+ // Compute the range indices of consecutive shaped or .notdef glyphs.
+ // Cluster information for RTL runs becomes reversed, e.g. glyph 0
+ // has cluster index 5 in a run of 6 characters.
+ BufferSlice result;
+ result.start_glyph_index = old_glyph_index;
+ result.num_glyphs = new_glyph_index - old_glyph_index;
+
+ if (HB_DIRECTION_IS_FORWARD(hb_buffer_get_direction(range_data->buffer))) {
+ result.start_character_index = glyph_info[old_glyph_index].cluster;
+ if (new_glyph_index == num_glyphs) {
+ // Clamp the end offsets of the queue item to the offsets representing
+ // the shaping window.
+ unsigned shape_end =
+ std::min(range_data->end, current_queue_item.start_index_ +
+ current_queue_item.num_characters_);
+ result.num_characters = shape_end - result.start_character_index;
+ } else {
+ result.num_characters =
+ glyph_info[new_glyph_index].cluster - result.start_character_index;
+ }
+ } else {
+ // Direction Backwards
+ result.start_character_index = glyph_info[new_glyph_index - 1].cluster;
+ if (old_glyph_index == 0) {
+ // Clamp the end offsets of the queue item to the offsets representing
+ // the shaping window.
+ unsigned shape_end =
+ std::min(range_data->end, current_queue_item.start_index_ +
+ current_queue_item.num_characters_);
+ result.num_characters = shape_end - result.start_character_index;
+ } else {
+ result.num_characters = glyph_info[old_glyph_index - 1].cluster -
+ glyph_info[new_glyph_index - 1].cluster;
+ }
+ }
+
+ return result;
+}
+
+void QueueCharacters(RangeData* range_data,
+ const SimpleFontData* current_font,
+ bool& font_cycle_queued,
+ const BufferSlice& slice) {
+ if (!font_cycle_queued) {
+ range_data->reshape_queue.push_back(
+ ReshapeQueueItem(kReshapeQueueNextFont, 0, 0));
+ font_cycle_queued = true;
+ }
+
+ DCHECK(slice.num_characters);
+ range_data->reshape_queue.push_back(ReshapeQueueItem(
+ kReshapeQueueRange, slice.start_character_index, slice.num_characters));
+}
+
+CanvasRotationInVertical CanvasRotationForRun(
+ FontOrientation font_orientation,
+ OrientationIterator::RenderOrientation render_orientation) {
+ if (font_orientation == FontOrientation::kVerticalUpright ||
+ (font_orientation == FontOrientation::kVerticalMixed &&
+ render_orientation == OrientationIterator::kOrientationKeep))
+ return CanvasRotationInVertical::kRotateCanvasUpright;
+ return CanvasRotationInVertical::kRegular;
+}
+
+} // namespace
+
+void HarfBuzzShaper::CommitGlyphs(RangeData* range_data,
+ const SimpleFontData* current_font,
+ UScriptCode current_run_script,
+ CanvasRotationInVertical canvas_rotation,
+ bool is_last_resort,
+ const BufferSlice& slice,
+ ShapeResult* shape_result) const {
+ hb_direction_t direction = range_data->HarfBuzzDirection(canvas_rotation);
+ hb_script_t script = ICUScriptToHBScript(current_run_script);
+ // Here we need to specify glyph positions.
+ BufferSlice next_slice;
+ for (const BufferSlice* current_slice = &slice;;) {
+ Vector<unsigned> graphemes;
+ GraphemesClusterList(text_, current_slice->start_character_index,
+ current_slice->num_characters, &graphemes);
+ ShapeResult::RunInfo* run = new ShapeResult::RunInfo(
+ current_font, direction, canvas_rotation, script,
+ current_slice->start_character_index, current_slice->num_glyphs,
+ current_slice->num_characters, graphemes);
+ shape_result->InsertRun(base::WrapUnique(run),
+ current_slice->start_glyph_index,
+ current_slice->num_glyphs, range_data->buffer);
+ unsigned num_glyphs_inserted = run->NumGlyphs();
+ if (num_glyphs_inserted == current_slice->num_glyphs)
+ break;
+ // If the slice exceeds the limit a RunInfo can store, create another
+ // RunInfo for the rest of the slice.
+ DCHECK_GT(current_slice->num_characters, run->num_characters_);
+ DCHECK_GT(current_slice->num_glyphs, num_glyphs_inserted);
+ next_slice = {current_slice->start_character_index + run->num_characters_,
+ current_slice->num_characters - run->num_characters_,
+ current_slice->start_glyph_index + num_glyphs_inserted,
+ current_slice->num_glyphs - num_glyphs_inserted};
+ current_slice = &next_slice;
+ }
+ if (is_last_resort)
+ range_data->font->ReportNotDefGlyph();
+}
+
+void HarfBuzzShaper::ExtractShapeResults(
+ RangeData* range_data,
+ bool& font_cycle_queued,
+ const ReshapeQueueItem& current_queue_item,
+ const SimpleFontData* current_font,
+ UScriptCode current_run_script,
+ CanvasRotationInVertical canvas_rotation,
+ bool is_last_resort,
+ ShapeResult* shape_result) const {
+ enum ClusterResult { kShaped, kNotDef, kUnknown };
+ ClusterResult current_cluster_result = kUnknown;
+ ClusterResult previous_cluster_result = kUnknown;
+ unsigned previous_cluster = 0;
+ unsigned current_cluster = 0;
+
+ // Find first notdef glyph in buffer.
+ unsigned num_glyphs = hb_buffer_get_length(range_data->buffer);
+ hb_glyph_info_t* glyph_info =
+ hb_buffer_get_glyph_infos(range_data->buffer, nullptr);
+
+ unsigned last_change_glyph_index = 0;
+ unsigned previous_cluster_start_glyph_index = 0;
+
+ if (!num_glyphs)
+ return;
+
+ for (unsigned glyph_index = 0; glyph_index < num_glyphs; ++glyph_index) {
+ // We proceed by full clusters and determine a shaping result - either
+ // kShaped or kNotDef for each cluster.
+ ClusterResult glyph_result =
+ glyph_info[glyph_index].codepoint == 0 ? kNotDef : kShaped;
+ previous_cluster = current_cluster;
+ current_cluster = glyph_info[glyph_index].cluster;
+
+ if (current_cluster != previous_cluster) {
+ // We are transitioning to a new cluster (whose shaping result state we
+ // have not looked at yet). This means the cluster we just looked at is
+ // completely analysed and we can determine whether it was fully shaped
+ // and whether that means a state change to the cluster before that one.
+ if ((previous_cluster_result != current_cluster_result) &&
+ previous_cluster_result != kUnknown) {
+ BufferSlice slice = ComputeSlice(
+ range_data, current_queue_item, glyph_info, num_glyphs,
+ last_change_glyph_index, previous_cluster_start_glyph_index);
+ // If the most recent cluster is shaped and there is a state change,
+ // it means the previous ones were unshaped, so we queue them, unless
+ // we're using the last resort font.
+ if (current_cluster_result == kShaped && !is_last_resort) {
+ QueueCharacters(range_data, current_font, font_cycle_queued, slice);
+ } else {
+ // If the most recent cluster is unshaped and there is a state
+ // change, it means the previous one(s) were shaped, so we commit
+ // the glyphs. We also commit when we've reached the last resort
+ // font.
+ CommitGlyphs(range_data, current_font, current_run_script,
+ canvas_rotation, is_last_resort, slice, shape_result);
+ }
+ last_change_glyph_index = previous_cluster_start_glyph_index;
+ }
+
+ // No state change happened, continue.
+ previous_cluster_result = current_cluster_result;
+ previous_cluster_start_glyph_index = glyph_index;
+ // Reset current cluster result.
+ current_cluster_result = glyph_result;
+ } else {
+ // Update and merge current cluster result.
+ current_cluster_result =
+ glyph_result == kShaped && (current_cluster_result == kShaped ||
+ current_cluster_result == kUnknown)
+ ? kShaped
+ : kNotDef;
+ }
+ }
+
+ // End of the run.
+ if (current_cluster_result != previous_cluster_result &&
+ previous_cluster_result != kUnknown && !is_last_resort) {
+ // The last cluster in the run still had shaping status different from
+ // the cluster(s) before it, we need to submit one shaped and one
+ // unshaped segment.
+ if (current_cluster_result == kShaped) {
+ BufferSlice slice = ComputeSlice(
+ range_data, current_queue_item, glyph_info, num_glyphs,
+ last_change_glyph_index, previous_cluster_start_glyph_index);
+ QueueCharacters(range_data, current_font, font_cycle_queued, slice);
+ slice =
+ ComputeSlice(range_data, current_queue_item, glyph_info, num_glyphs,
+ previous_cluster_start_glyph_index, num_glyphs);
+ CommitGlyphs(range_data, current_font, current_run_script,
+ canvas_rotation, is_last_resort, slice, shape_result);
+ } else {
+ BufferSlice slice = ComputeSlice(
+ range_data, current_queue_item, glyph_info, num_glyphs,
+ last_change_glyph_index, previous_cluster_start_glyph_index);
+ CommitGlyphs(range_data, current_font, current_run_script,
+ canvas_rotation, is_last_resort, slice, shape_result);
+ slice =
+ ComputeSlice(range_data, current_queue_item, glyph_info, num_glyphs,
+ previous_cluster_start_glyph_index, num_glyphs);
+ QueueCharacters(range_data, current_font, font_cycle_queued, slice);
+ }
+ } else {
+ // There hasn't been a state change for the last cluster, so we can just
+ // either commit or queue what we have up until here.
+ BufferSlice slice =
+ ComputeSlice(range_data, current_queue_item, glyph_info, num_glyphs,
+ last_change_glyph_index, num_glyphs);
+ if (current_cluster_result == kNotDef && !is_last_resort) {
+ QueueCharacters(range_data, current_font, font_cycle_queued, slice);
+ } else {
+ CommitGlyphs(range_data, current_font, current_run_script,
+ canvas_rotation, is_last_resort, slice, shape_result);
+ }
+ }
+}
+
+bool HarfBuzzShaper::CollectFallbackHintChars(
+ const Deque<ReshapeQueueItem>& reshape_queue,
+ Vector<UChar32>& hint) const {
+ if (!reshape_queue.size())
+ return false;
+
+ // Clear without releasing the capacity to avoid reallocations.
+ hint.resize(0);
+
+ size_t num_chars_added = 0;
+ for (auto it = reshape_queue.begin(); it != reshape_queue.end(); ++it) {
+ if (it->action_ == kReshapeQueueNextFont)
+ break;
+
+ CHECK_LE((it->start_index_ + it->num_characters_), text_.length());
+ if (text_.Is8Bit()) {
+ for (unsigned i = 0; i < it->num_characters_; i++) {
+ hint.push_back(text_[it->start_index_ + i]);
+ num_chars_added++;
+ }
+ continue;
+ }
+
+ UChar32 hint_char;
+ UTF16TextIterator iterator(text_.Characters16() + it->start_index_,
+ it->num_characters_);
+ while (iterator.Consume(hint_char)) {
+ hint.push_back(hint_char);
+ num_chars_added++;
+ iterator.Advance();
+ }
+ }
+ return num_chars_added > 0;
+}
+
+namespace {
+
+void SplitUntilNextCaseChange(
+ const String& text,
+ Deque<blink::ReshapeQueueItem>* queue,
+ blink::ReshapeQueueItem& current_queue_item,
+ SmallCapsIterator::SmallCapsBehavior& small_caps_behavior) {
+ // TODO(layout-dev): Add support for latin-1 to SmallCapsIterator.
+ const UChar* normalized_buffer;
+ base::Optional<String> utf16_text;
+ if (text.Is8Bit()) {
+ utf16_text.emplace(text);
+ utf16_text->Ensure16Bit();
+ normalized_buffer = utf16_text->Characters16();
+ } else {
+ normalized_buffer = text.Characters16();
+ }
+
+ unsigned num_characters_until_case_change = 0;
+ SmallCapsIterator small_caps_iterator(
+ normalized_buffer + current_queue_item.start_index_,
+ current_queue_item.num_characters_);
+ small_caps_iterator.Consume(&num_characters_until_case_change,
+ &small_caps_behavior);
+ if (num_characters_until_case_change > 0 &&
+ num_characters_until_case_change < current_queue_item.num_characters_) {
+ queue->push_front(blink::ReshapeQueueItem(
+ blink::ReshapeQueueItemAction::kReshapeQueueRange,
+ current_queue_item.start_index_ + num_characters_until_case_change,
+ current_queue_item.num_characters_ - num_characters_until_case_change));
+ current_queue_item.num_characters_ = num_characters_until_case_change;
+ }
+}
+
+hb_feature_t CreateFeature(hb_tag_t tag, uint32_t value = 0) {
+ return {tag, value, 0 /* start */, static_cast<unsigned>(-1) /* end */};
+}
+
+// TODO(kojii): crbug.com/762493 This list is getting long enough to extract out
+// of HarfBuzzShaper.cpp.
+void SetFontFeatures(const Font* font, FeaturesVector* features) {
+ const FontDescription& description = font->GetFontDescription();
+
+ static hb_feature_t no_kern = CreateFeature(HB_TAG('k', 'e', 'r', 'n'));
+ static hb_feature_t no_vkrn = CreateFeature(HB_TAG('v', 'k', 'r', 'n'));
+ switch (description.GetKerning()) {
+ case FontDescription::kNormalKerning:
+ // kern/vkrn are enabled by default
+ break;
+ case FontDescription::kNoneKerning:
+ features->push_back(description.IsVerticalAnyUpright() ? no_vkrn
+ : no_kern);
+ break;
+ case FontDescription::kAutoKerning:
+ break;
+ }
+
+ static hb_feature_t no_clig = CreateFeature(HB_TAG('c', 'l', 'i', 'g'));
+ static hb_feature_t no_liga = CreateFeature(HB_TAG('l', 'i', 'g', 'a'));
+ switch (description.CommonLigaturesState()) {
+ case FontDescription::kDisabledLigaturesState:
+ features->push_back(no_liga);
+ features->push_back(no_clig);
+ break;
+ case FontDescription::kEnabledLigaturesState:
+ // liga and clig are on by default
+ break;
+ case FontDescription::kNormalLigaturesState:
+ break;
+ }
+ static hb_feature_t dlig = CreateFeature(HB_TAG('d', 'l', 'i', 'g'), 1);
+ switch (description.DiscretionaryLigaturesState()) {
+ case FontDescription::kDisabledLigaturesState:
+ // dlig is off by default
+ break;
+ case FontDescription::kEnabledLigaturesState:
+ features->push_back(dlig);
+ break;
+ case FontDescription::kNormalLigaturesState:
+ break;
+ }
+ static hb_feature_t hlig = CreateFeature(HB_TAG('h', 'l', 'i', 'g'), 1);
+ switch (description.HistoricalLigaturesState()) {
+ case FontDescription::kDisabledLigaturesState:
+ // hlig is off by default
+ break;
+ case FontDescription::kEnabledLigaturesState:
+ features->push_back(hlig);
+ break;
+ case FontDescription::kNormalLigaturesState:
+ break;
+ }
+ static hb_feature_t no_calt = CreateFeature(HB_TAG('c', 'a', 'l', 't'));
+ switch (description.ContextualLigaturesState()) {
+ case FontDescription::kDisabledLigaturesState:
+ features->push_back(no_calt);
+ break;
+ case FontDescription::kEnabledLigaturesState:
+ // calt is on by default
+ break;
+ case FontDescription::kNormalLigaturesState:
+ break;
+ }
+
+ static hb_feature_t hwid = CreateFeature(HB_TAG('h', 'w', 'i', 'd'), 1);
+ static hb_feature_t twid = CreateFeature(HB_TAG('t', 'w', 'i', 'd'), 1);
+ static hb_feature_t qwid = CreateFeature(HB_TAG('q', 'w', 'i', 'd'), 1);
+ switch (description.WidthVariant()) {
+ case kHalfWidth:
+ features->push_back(hwid);
+ break;
+ case kThirdWidth:
+ features->push_back(twid);
+ break;
+ case kQuarterWidth:
+ features->push_back(qwid);
+ break;
+ case kRegularWidth:
+ break;
+ }
+
+ // font-variant-east-asian:
+ const FontVariantEastAsian east_asian = description.VariantEastAsian();
+ if (UNLIKELY(!east_asian.IsAllNormal())) {
+ static hb_feature_t jp78 = CreateFeature(HB_TAG('j', 'p', '7', '8'), 1);
+ static hb_feature_t jp83 = CreateFeature(HB_TAG('j', 'p', '8', '3'), 1);
+ static hb_feature_t jp90 = CreateFeature(HB_TAG('j', 'p', '9', '0'), 1);
+ static hb_feature_t jp04 = CreateFeature(HB_TAG('j', 'p', '0', '4'), 1);
+ static hb_feature_t smpl = CreateFeature(HB_TAG('s', 'm', 'p', 'l'), 1);
+ static hb_feature_t trad = CreateFeature(HB_TAG('t', 'r', 'a', 'd'), 1);
+ switch (east_asian.Form()) {
+ case FontVariantEastAsian::kNormalForm:
+ break;
+ case FontVariantEastAsian::kJis78:
+ features->push_back(jp78);
+ break;
+ case FontVariantEastAsian::kJis83:
+ features->push_back(jp83);
+ break;
+ case FontVariantEastAsian::kJis90:
+ features->push_back(jp90);
+ break;
+ case FontVariantEastAsian::kJis04:
+ features->push_back(jp04);
+ break;
+ case FontVariantEastAsian::kSimplified:
+ features->push_back(smpl);
+ break;
+ case FontVariantEastAsian::kTraditional:
+ features->push_back(trad);
+ break;
+ default:
+ NOTREACHED();
+ }
+ static hb_feature_t fwid = CreateFeature(HB_TAG('f', 'w', 'i', 'd'), 1);
+ static hb_feature_t pwid = CreateFeature(HB_TAG('p', 'w', 'i', 'd'), 1);
+ switch (east_asian.Width()) {
+ case FontVariantEastAsian::kNormalWidth:
+ break;
+ case FontVariantEastAsian::kFullWidth:
+ features->push_back(fwid);
+ break;
+ case FontVariantEastAsian::kProportionalWidth:
+ features->push_back(pwid);
+ break;
+ default:
+ NOTREACHED();
+ }
+ static hb_feature_t ruby = CreateFeature(HB_TAG('r', 'u', 'b', 'y'), 1);
+ if (east_asian.Ruby())
+ features->push_back(ruby);
+ }
+
+ // font-variant-numeric:
+ static hb_feature_t lnum = CreateFeature(HB_TAG('l', 'n', 'u', 'm'), 1);
+ if (description.VariantNumeric().NumericFigureValue() ==
+ FontVariantNumeric::kLiningNums)
+ features->push_back(lnum);
+
+ static hb_feature_t onum = CreateFeature(HB_TAG('o', 'n', 'u', 'm'), 1);
+ if (description.VariantNumeric().NumericFigureValue() ==
+ FontVariantNumeric::kOldstyleNums)
+ features->push_back(onum);
+
+ static hb_feature_t pnum = CreateFeature(HB_TAG('p', 'n', 'u', 'm'), 1);
+ if (description.VariantNumeric().NumericSpacingValue() ==
+ FontVariantNumeric::kProportionalNums)
+ features->push_back(pnum);
+ static hb_feature_t tnum = CreateFeature(HB_TAG('t', 'n', 'u', 'm'), 1);
+ if (description.VariantNumeric().NumericSpacingValue() ==
+ FontVariantNumeric::kTabularNums)
+ features->push_back(tnum);
+
+ static hb_feature_t afrc = CreateFeature(HB_TAG('a', 'f', 'r', 'c'), 1);
+ if (description.VariantNumeric().NumericFractionValue() ==
+ FontVariantNumeric::kStackedFractions)
+ features->push_back(afrc);
+ static hb_feature_t frac = CreateFeature(HB_TAG('f', 'r', 'a', 'c'), 1);
+ if (description.VariantNumeric().NumericFractionValue() ==
+ FontVariantNumeric::kDiagonalFractions)
+ features->push_back(frac);
+
+ static hb_feature_t ordn = CreateFeature(HB_TAG('o', 'r', 'd', 'n'), 1);
+ if (description.VariantNumeric().OrdinalValue() ==
+ FontVariantNumeric::kOrdinalOn)
+ features->push_back(ordn);
+
+ static hb_feature_t zero = CreateFeature(HB_TAG('z', 'e', 'r', 'o'), 1);
+ if (description.VariantNumeric().SlashedZeroValue() ==
+ FontVariantNumeric::kSlashedZeroOn)
+ features->push_back(zero);
+
+ FontFeatureSettings* settings = description.FeatureSettings();
+ if (!settings)
+ return;
+
+ // TODO(drott): crbug.com/450619 Implement feature resolution instead of
+ // just appending the font-feature-settings.
+ unsigned num_features = settings->size();
+ for (unsigned i = 0; i < num_features; ++i) {
+ hb_feature_t feature;
+ const AtomicString& tag = settings->at(i).Tag();
+ feature.tag = HB_TAG(tag[0], tag[1], tag[2], tag[3]);
+ feature.value = settings->at(i).Value();
+ feature.start = 0;
+ feature.end = static_cast<unsigned>(-1);
+ features->push_back(feature);
+ }
+}
+
+class CapsFeatureSettingsScopedOverlay final {
+ STACK_ALLOCATED();
+
+ public:
+ CapsFeatureSettingsScopedOverlay(FeaturesVector*,
+ FontDescription::FontVariantCaps);
+ CapsFeatureSettingsScopedOverlay() = delete;
+ ~CapsFeatureSettingsScopedOverlay();
+
+ private:
+ void OverlayCapsFeatures(FontDescription::FontVariantCaps);
+ void PrependCounting(const hb_feature_t&);
+ FeaturesVector* features_;
+ size_t count_features_;
+};
+
+CapsFeatureSettingsScopedOverlay::CapsFeatureSettingsScopedOverlay(
+ FeaturesVector* features,
+ FontDescription::FontVariantCaps variant_caps)
+ : features_(features), count_features_(0) {
+ OverlayCapsFeatures(variant_caps);
+}
+
+void CapsFeatureSettingsScopedOverlay::OverlayCapsFeatures(
+ FontDescription::FontVariantCaps variant_caps) {
+ static hb_feature_t smcp = CreateFeature(HB_TAG('s', 'm', 'c', 'p'), 1);
+ static hb_feature_t pcap = CreateFeature(HB_TAG('p', 'c', 'a', 'p'), 1);
+ static hb_feature_t c2sc = CreateFeature(HB_TAG('c', '2', 's', 'c'), 1);
+ static hb_feature_t c2pc = CreateFeature(HB_TAG('c', '2', 'p', 'c'), 1);
+ static hb_feature_t unic = CreateFeature(HB_TAG('u', 'n', 'i', 'c'), 1);
+ static hb_feature_t titl = CreateFeature(HB_TAG('t', 'i', 't', 'l'), 1);
+ if (variant_caps == FontDescription::kSmallCaps ||
+ variant_caps == FontDescription::kAllSmallCaps) {
+ PrependCounting(smcp);
+ if (variant_caps == FontDescription::kAllSmallCaps) {
+ PrependCounting(c2sc);
+ }
+ }
+ if (variant_caps == FontDescription::kPetiteCaps ||
+ variant_caps == FontDescription::kAllPetiteCaps) {
+ PrependCounting(pcap);
+ if (variant_caps == FontDescription::kAllPetiteCaps) {
+ PrependCounting(c2pc);
+ }
+ }
+ if (variant_caps == FontDescription::kUnicase) {
+ PrependCounting(unic);
+ }
+ if (variant_caps == FontDescription::kTitlingCaps) {
+ PrependCounting(titl);
+ }
+}
+
+void CapsFeatureSettingsScopedOverlay::PrependCounting(
+ const hb_feature_t& feature) {
+ features_->push_front(feature);
+ count_features_++;
+}
+
+CapsFeatureSettingsScopedOverlay::~CapsFeatureSettingsScopedOverlay() {
+ features_->EraseAt(0, count_features_);
+}
+
+} // namespace
+
+void HarfBuzzShaper::ShapeSegment(
+ RangeData* range_data,
+ const RunSegmenter::RunSegmenterRange& segment,
+ ShapeResult* result) const {
+ DCHECK(result);
+ DCHECK(range_data->buffer);
+
+ const Font* font = range_data->font;
+ const FontDescription& font_description = font->GetFontDescription();
+ const hb_language_t language =
+ font_description.LocaleOrDefault().HarfbuzzLanguage();
+ bool needs_caps_handling =
+ font_description.VariantCaps() != FontDescription::kCapsNormal;
+ OpenTypeCapsSupport caps_support;
+
+ scoped_refptr<FontFallbackIterator> fallback_iterator =
+ font->CreateFontFallbackIterator(segment.font_fallback_priority);
+
+ range_data->reshape_queue.push_back(
+ ReshapeQueueItem(kReshapeQueueNextFont, 0, 0));
+ range_data->reshape_queue.push_back(ReshapeQueueItem(
+ kReshapeQueueRange, segment.start, segment.end - segment.start));
+
+ bool font_cycle_queued = false;
+ Vector<UChar32> fallback_chars_hint;
+ // Reserve enough capacity to avoid multiple reallocations.
+ // TODO(kojii): Should review if we really need to collect all characters.
+ // crbug.com/848295
+ fallback_chars_hint.ReserveInitialCapacity(range_data->end -
+ range_data->start);
+ scoped_refptr<FontDataForRangeSet> current_font_data_for_range_set;
+ while (range_data->reshape_queue.size()) {
+ ReshapeQueueItem current_queue_item = range_data->reshape_queue.TakeFirst();
+
+ if (current_queue_item.action_ == kReshapeQueueNextFont) {
+ // For now, we're building a character list with which we probe
+ // for needed fonts depending on the declared unicode-range of a
+ // segmented CSS font. Alternatively, we can build a fake font
+ // for the shaper and check whether any glyphs were found, or
+ // define a new API on the shaper which will give us coverage
+ // information?
+ if (!CollectFallbackHintChars(range_data->reshape_queue,
+ fallback_chars_hint)) {
+ // Give up shaping since we cannot retrieve a font fallback
+ // font without a hintlist.
+ range_data->reshape_queue.clear();
+ break;
+ }
+
+ current_font_data_for_range_set =
+ fallback_iterator->Next(fallback_chars_hint);
+ if (!current_font_data_for_range_set->FontData()) {
+ DCHECK(!range_data->reshape_queue.size());
+ break;
+ }
+ font_cycle_queued = false;
+ continue;
+ }
+
+ const SimpleFontData* font_data =
+ current_font_data_for_range_set->FontData();
+ SmallCapsIterator::SmallCapsBehavior small_caps_behavior =
+ SmallCapsIterator::kSmallCapsSameCase;
+ if (needs_caps_handling) {
+ caps_support = OpenTypeCapsSupport(
+ font_data->PlatformData().GetHarfBuzzFace(),
+ font_description.VariantCaps(), ICUScriptToHBScript(segment.script));
+ if (caps_support.NeedsRunCaseSplitting()) {
+ SplitUntilNextCaseChange(text_, &range_data->reshape_queue,
+ current_queue_item, small_caps_behavior);
+ // Skip queue items generated by SplitUntilNextCaseChange that do not
+ // contribute to the shape result if the range_data restricts shaping to
+ // a substring.
+ if (range_data->start >= current_queue_item.start_index_ +
+ current_queue_item.num_characters_ ||
+ range_data->end <= current_queue_item.start_index_)
+ continue;
+ }
+ }
+
+ DCHECK(current_queue_item.num_characters_);
+ const SimpleFontData* adjusted_font = font_data;
+
+ // Clamp the start and end offsets of the queue item to the offsets
+ // representing the shaping window.
+ unsigned shape_start =
+ std::max(range_data->start, current_queue_item.start_index_);
+ unsigned shape_end =
+ std::min(range_data->end, current_queue_item.start_index_ +
+ current_queue_item.num_characters_);
+ DCHECK_GT(shape_end, shape_start);
+
+ CaseMapIntend case_map_intend = CaseMapIntend::kKeepSameCase;
+ if (needs_caps_handling) {
+ case_map_intend = caps_support.NeedsCaseChange(small_caps_behavior);
+ if (caps_support.NeedsSyntheticFont(small_caps_behavior))
+ adjusted_font = font_data->SmallCapsFontData(font_description).get();
+ }
+
+ CaseMappingHarfBuzzBufferFiller(
+ case_map_intend, font_description.LocaleOrDefault(), range_data->buffer,
+ text_, shape_start, shape_end - shape_start);
+
+ CanvasRotationInVertical canvas_rotation =
+ CanvasRotationForRun(adjusted_font->PlatformData().Orientation(),
+ segment.render_orientation);
+
+ CapsFeatureSettingsScopedOverlay caps_overlay(
+ &range_data->font_features,
+ caps_support.FontFeatureToUse(small_caps_behavior));
+ hb_direction_t direction = range_data->HarfBuzzDirection(canvas_rotation);
+
+ if (!ShapeRange(range_data->buffer,
+ range_data->font_features.IsEmpty()
+ ? nullptr
+ : range_data->font_features.data(),
+ range_data->font_features.size(), adjusted_font,
+ current_font_data_for_range_set->Ranges(), segment.script,
+ direction, language))
+ DLOG(ERROR) << "Shaping range failed.";
+
+ ExtractShapeResults(range_data, font_cycle_queued, current_queue_item,
+ adjusted_font, segment.script, canvas_rotation,
+ !fallback_iterator->HasNext(), result);
+
+ hb_buffer_reset(range_data->buffer);
+ }
+}
+
+scoped_refptr<ShapeResult> HarfBuzzShaper::Shape(
+ const Font* font,
+ TextDirection direction,
+ unsigned start,
+ unsigned end,
+ const RunSegmenter::RunSegmenterRange* pre_segmented) const {
+ DCHECK_GE(end, start);
+ DCHECK_LE(end, text_.length());
+ DCHECK(!pre_segmented ||
+ (start >= pre_segmented->start && end <= pre_segmented->end));
+
+ unsigned length = end - start;
+ scoped_refptr<ShapeResult> result =
+ ShapeResult::Create(font, length, direction);
+ HarfBuzzScopedPtr<hb_buffer_t> buffer(hb_buffer_create(), hb_buffer_destroy);
+
+ RangeData range_data;
+ range_data.buffer = buffer.Get();
+ range_data.font = font;
+ range_data.text_direction = direction;
+ range_data.start = start;
+ range_data.end = end;
+ SetFontFeatures(font, &range_data.font_features);
+
+ if (pre_segmented) {
+ ShapeSegment(&range_data, *pre_segmented, result.get());
+
+ } else if (text_.Is8Bit()) {
+ // 8-bit text is guaranteed to horizontal latin-1.
+ RunSegmenter::RunSegmenterRange segment_range = {
+ start, end, USCRIPT_LATIN, OrientationIterator::kOrientationKeep,
+ FontFallbackPriority::kText};
+ ShapeSegment(&range_data, segment_range, result.get());
+
+ } else {
+ // Run segmentation needs to operate on the entire string, regardless of the
+ // shaping window (defined by the start and end parameters).
+ DCHECK(!text_.Is8Bit());
+ RunSegmenter run_segmenter(text_.Characters16(), text_.length(),
+ font->GetFontDescription().Orientation());
+ RunSegmenter::RunSegmenterRange segment_range = RunSegmenter::NullRange();
+ while (run_segmenter.Consume(&segment_range)) {
+ // Only shape segments overlapping with the range indicated by start and
+ // end. Not only those strictly within.
+ if (start < segment_range.end && end > segment_range.start)
+ ShapeSegment(&range_data, segment_range, result.get());
+
+ // Break if beyond the requested range. Because RunSegmenter is
+ // incremental, further ranges are not needed. This also allows reusing
+ // the segmenter state for next incremental calls.
+ if (segment_range.end >= end)
+ break;
+ }
+ }
+
+ // Ensure we have at least one run for StartIndexForResult().
+ if (UNLIKELY(result->runs_.IsEmpty() && start))
+ result->InsertRunForIndex(start);
+
+#if DCHECK_IS_ON()
+ if (result)
+ CheckShapeResultRange(result.get(), start, end, text_, font);
+#endif
+
+ return result;
+}
+
+scoped_refptr<ShapeResult> HarfBuzzShaper::Shape(
+ const Font* font,
+ TextDirection direction) const {
+ return Shape(font, direction, 0, text_.length());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h
new file mode 100644
index 00000000000..a65259f230d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARFBUZZ_SHAPER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARFBUZZ_SHAPER_H_
+
+#include "third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+class Font;
+class SimpleFontData;
+class HarfBuzzShaper;
+struct ReshapeQueueItem;
+struct RangeData;
+struct BufferSlice;
+
+class PLATFORM_EXPORT HarfBuzzShaper final {
+ public:
+ HarfBuzzShaper(const String&);
+
+ // Shape a range, defined by the start and end parameters, of the string
+ // supplied to the constructor.
+ // The start and end positions should represent boundaries where a break may
+ // occur, such as at the beginning or end of lines or at element boundaries.
+ // If given arbitrary positions the results are not guaranteed to be correct.
+ // May be called multiple times; font and direction may vary between calls.
+ //
+ // If |pre_segmented| is given, it is assumed that the string is already
+ // segmented. Otherwise the string is segmented into runs before shaping.
+ scoped_refptr<ShapeResult> Shape(
+ const Font*,
+ TextDirection,
+ unsigned start,
+ unsigned end,
+ const RunSegmenter::RunSegmenterRange* pre_segmented = nullptr) const;
+
+ // Shape the entire string with a single font and direction.
+ // Equivalent to calling the range version with a start offset of zero and an
+ // end offset equal to the length.
+ scoped_refptr<ShapeResult> Shape(const Font*, TextDirection) const;
+
+ const String& GetText() const { return text_; }
+ unsigned TextLength() const { return text_.length(); }
+
+ ~HarfBuzzShaper() = default;
+
+ private:
+ // Shapes a single seqment, as identified by the RunSegmenterRange parameter,
+ // one or more times taking font fallback into account. The start and end
+ // parameters are for the entire text run, not the segment, and are used to
+ // determine pre- and post-context for shaping.
+ void ShapeSegment(RangeData*,
+ const RunSegmenter::RunSegmenterRange&,
+ ShapeResult*) const;
+
+ void ExtractShapeResults(RangeData*,
+ bool& font_cycle_queued,
+ const ReshapeQueueItem&,
+ const SimpleFontData*,
+ UScriptCode,
+ CanvasRotationInVertical,
+ bool is_last_resort,
+ ShapeResult*) const;
+
+ bool CollectFallbackHintChars(const Deque<ReshapeQueueItem>&,
+ Vector<UChar32>& hint) const;
+
+ void CommitGlyphs(RangeData*,
+ const SimpleFontData* current_font,
+ UScriptCode current_run_script,
+ CanvasRotationInVertical,
+ bool is_last_resort,
+ const BufferSlice&,
+ ShapeResult*) const;
+
+ const String text_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_HARFBUZZ_SHAPER_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_fuzzer.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_fuzzer.cc
new file mode 100644
index 00000000000..186cb357c9c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_fuzzer.cc
@@ -0,0 +1,52 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/fonts/font.h"
+#include "third_party/blink/renderer/platform/fonts/font_cache.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h"
+#include "third_party/blink/renderer/platform/testing/blink_fuzzer_test_support.h"
+
+#include <stddef.h>
+#include <stdint.h>
+#include <unicode/ustring.h>
+
+namespace blink {
+
+constexpr size_t kMaxInputLength = 256;
+
+// TODO crbug.com/771901: BlinkFuzzerTestSupport should also initialize the
+// custom fontconfig configuration that we use for content_shell.
+int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ static BlinkFuzzerTestSupport fuzzer_support = BlinkFuzzerTestSupport();
+ constexpr int32_t kDestinationCapacity = 2 * kMaxInputLength;
+ int32_t converted_length = 0;
+ UChar converted_input_buffer[kDestinationCapacity] = {0};
+ UErrorCode error_code = U_ZERO_ERROR;
+
+ // Discard trailing bytes.
+ u_strFromUTF32(converted_input_buffer, kDestinationCapacity,
+ &converted_length, reinterpret_cast<const UChar32*>(data),
+ size / sizeof(UChar32), &error_code);
+ if (U_FAILURE(error_code))
+ return 0;
+
+ FontCachePurgePreventer font_cache_purge_preventer;
+ FontDescription font_description;
+ Font font(font_description);
+ // Set font size to something other than the default 0 size in
+ // FontDescription, 16 matches the default text size in HTML.
+ font_description.SetComputedSize(16.0f);
+ // Only look for system fonts for now.
+ font.Update(nullptr);
+
+ HarfBuzzShaper shaper(String(converted_input_buffer, converted_length));
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
+ return 0;
+}
+
+} // namespace blink
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ return blink::LLVMFuzzerTestOneInput(data, size);
+}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc
new file mode 100644
index 00000000000..8c96a9bbd52
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper_test.cc
@@ -0,0 +1,1514 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h"
+
+#include <unicode/uscript.h>
+
+#include "base/stl_util.h"
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/fonts/font.h"
+#include "third_party/blink/renderer/platform/fonts/font_cache.h"
+#include "third_party/blink/renderer/platform/fonts/font_test_utilities.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_test_info.h"
+#include "third_party/blink/renderer/platform/layout_test_support.h"
+#include "third_party/blink/renderer/platform/testing/font_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
+#include "third_party/blink/renderer/platform/text/text_run.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+class HarfBuzzShaperTest : public testing::Test {
+ protected:
+ void SetUp() override {
+ font_description.SetComputedSize(12.0);
+ font = Font(font_description);
+ font.Update(nullptr);
+ }
+
+ void TearDown() override {}
+
+ Font CreateAhem(float size) {
+ FontDescription::VariantLigatures ligatures;
+ return blink::test::CreateTestFont(
+ "Ahem", blink::test::PlatformTestDataPath("Ahem.woff"), size,
+ &ligatures);
+ }
+
+ scoped_refptr<ShapeResult> SplitRun(scoped_refptr<ShapeResult> shape_result,
+ unsigned offset) {
+ unsigned length = shape_result->NumCharacters();
+ scoped_refptr<ShapeResult> run2 = shape_result->SubRange(offset, length);
+ shape_result = shape_result->SubRange(0, offset);
+ run2->CopyRange(offset, length, shape_result.get());
+ return shape_result;
+ }
+
+ FontCachePurgePreventer font_cache_purge_preventer;
+ FontDescription font_description;
+ Font font;
+ unsigned start_index = 0;
+ unsigned num_characters = 0;
+ unsigned num_glyphs = 0;
+ hb_script_t script = HB_SCRIPT_INVALID;
+};
+
+class ScopedSubpixelOverride {
+ public:
+ ScopedSubpixelOverride(bool b) {
+ prev_layout_test_ = LayoutTestSupport::IsRunningLayoutTest();
+ prev_subpixel_allowed_ =
+ LayoutTestSupport::IsTextSubpixelPositioningAllowedForTest();
+ prev_antialias_ = LayoutTestSupport::IsFontAntialiasingEnabledForTest();
+ prev_fd_subpixel_ = FontDescription::SubpixelPositioning();
+
+ // This is required for all LayoutTestSupport settings to have effects.
+ LayoutTestSupport::SetIsRunningLayoutTest(true);
+
+ if (b) {
+ // Allow subpixel positioning.
+ LayoutTestSupport::SetTextSubpixelPositioningAllowedForTest(true);
+
+ // Now, enable subpixel positioning in platform-specific ways.
+
+ // Mac always enables subpixel positioning.
+
+ // On Windows, subpixel positioning also requires antialiasing.
+ LayoutTestSupport::SetFontAntialiasingEnabledForTest(true);
+
+ // On platforms other than Windows and Mac this needs to be set as
+ // well.
+ FontDescription::SetSubpixelPositioning(true);
+ } else {
+ // Explicitly disallow all subpixel positioning.
+ LayoutTestSupport::SetTextSubpixelPositioningAllowedForTest(false);
+ }
+ }
+ ~ScopedSubpixelOverride() {
+ FontDescription::SetSubpixelPositioning(prev_fd_subpixel_);
+ LayoutTestSupport::SetFontAntialiasingEnabledForTest(prev_antialias_);
+ LayoutTestSupport::SetTextSubpixelPositioningAllowedForTest(
+ prev_subpixel_allowed_);
+ LayoutTestSupport::SetIsRunningLayoutTest(prev_layout_test_);
+
+ // Fonts cached with a different subpixel positioning state are not
+ // automatically invalidated and need to be cleared between test
+ // runs.
+ FontCache::GetFontCache()->Invalidate();
+ }
+
+ private:
+ bool prev_layout_test_;
+ bool prev_subpixel_allowed_;
+ bool prev_antialias_;
+ bool prev_fd_subpixel_;
+};
+
+class ShapeParameterTest : public HarfBuzzShaperTest,
+ public testing::WithParamInterface<TextDirection> {
+ protected:
+ scoped_refptr<ShapeResult> ShapeWithParameter(HarfBuzzShaper* shaper) {
+ TextDirection direction = GetParam();
+ return shaper->Shape(&font, direction);
+ }
+};
+
+INSTANTIATE_TEST_CASE_P(HarfBuzzShaperTest,
+ ShapeParameterTest,
+ testing::Values(TextDirection::kLtr,
+ TextDirection::kRtl));
+
+static inline ShapeResultTestInfo* TestInfo(
+ scoped_refptr<ShapeResult>& result) {
+ return static_cast<ShapeResultTestInfo*>(result.get());
+}
+
+TEST_F(HarfBuzzShaperTest, MutableUnique) {
+ scoped_refptr<ShapeResult> result =
+ ShapeResult::Create(&font, 0, TextDirection::kLtr);
+ EXPECT_TRUE(result->HasOneRef());
+
+ // At this point, |result| has only one ref count.
+ scoped_refptr<ShapeResult> result2 = result->MutableUnique();
+ EXPECT_EQ(result.get(), result2.get());
+ EXPECT_FALSE(result2->HasOneRef());
+
+ // Since |result| has 2 ref counts, it should return a clone.
+ scoped_refptr<ShapeResult> result3 = result->MutableUnique();
+ EXPECT_NE(result.get(), result3.get());
+ EXPECT_TRUE(result3->HasOneRef());
+}
+
+TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsLatin) {
+ String latin_common = To16Bit("ABC DEF.", 8);
+ HarfBuzzShaper shaper(latin_common);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
+
+ EXPECT_EQ(1u, TestInfo(result)->NumberOfRunsForTesting());
+ ASSERT_TRUE(
+ TestInfo(result)->RunInfoForTesting(0, start_index, num_glyphs, script));
+ EXPECT_EQ(0u, start_index);
+ EXPECT_EQ(8u, num_glyphs);
+ EXPECT_EQ(HB_SCRIPT_LATIN, script);
+}
+
+TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsLeadingCommon) {
+ String leading_common = To16Bit("... test", 8);
+ HarfBuzzShaper shaper(leading_common);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
+
+ EXPECT_EQ(1u, TestInfo(result)->NumberOfRunsForTesting());
+ ASSERT_TRUE(
+ TestInfo(result)->RunInfoForTesting(0, start_index, num_glyphs, script));
+ EXPECT_EQ(0u, start_index);
+ EXPECT_EQ(8u, num_glyphs);
+ EXPECT_EQ(HB_SCRIPT_LATIN, script);
+}
+
+TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsUnicodeVariants) {
+ struct {
+ const char* name;
+ UChar string[4];
+ unsigned length;
+ hb_script_t script;
+ } testlist[] = {
+ {"Standard Variants text style", {0x30, 0xFE0E}, 2, HB_SCRIPT_COMMON},
+ {"Standard Variants emoji style", {0x203C, 0xFE0F}, 2, HB_SCRIPT_COMMON},
+ {"Standard Variants of Ideograph", {0x4FAE, 0xFE00}, 2, HB_SCRIPT_HAN},
+ {"Ideographic Variants", {0x3402, 0xDB40, 0xDD00}, 3, HB_SCRIPT_HAN},
+ {"Not-defined Variants", {0x41, 0xDB40, 0xDDEF}, 3, HB_SCRIPT_LATIN},
+ };
+ for (auto& test : testlist) {
+ HarfBuzzShaper shaper(test.string);
+ scoped_refptr<ShapeResult> result =
+ shaper.Shape(&font, TextDirection::kLtr);
+
+ EXPECT_EQ(1u, TestInfo(result)->NumberOfRunsForTesting()) << test.name;
+ ASSERT_TRUE(
+ TestInfo(result)->RunInfoForTesting(0, start_index, num_glyphs, script))
+ << test.name;
+ EXPECT_EQ(0u, start_index) << test.name;
+ if (num_glyphs == 2) {
+// If the specified VS is not in the font, it's mapped to .notdef.
+// then hb_ot_hide_default_ignorables() swaps it to a space with zero-advance.
+// http://lists.freedesktop.org/archives/harfbuzz/2015-May/004888.html
+#if !defined(OS_MACOSX)
+ EXPECT_EQ(TestInfo(result)->FontDataForTesting(0)->SpaceGlyph(),
+ TestInfo(result)->GlyphForTesting(0, 1))
+ << test.name;
+#endif
+ EXPECT_EQ(0.f, TestInfo(result)->AdvanceForTesting(0, 1)) << test.name;
+ } else {
+ EXPECT_EQ(1u, num_glyphs) << test.name;
+ }
+ EXPECT_EQ(test.script, script) << test.name;
+ }
+}
+
+TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsDevanagariCommon) {
+ UChar devanagari_common_string[] = {0x915, 0x94d, 0x930, 0x28, 0x20, 0x29};
+ String devanagari_common_latin(devanagari_common_string, 6);
+ HarfBuzzShaper shaper(devanagari_common_latin);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
+
+ EXPECT_EQ(2u, TestInfo(result)->NumberOfRunsForTesting());
+ ASSERT_TRUE(
+ TestInfo(result)->RunInfoForTesting(0, start_index, num_glyphs, script));
+ EXPECT_EQ(0u, start_index);
+ EXPECT_EQ(1u, num_glyphs);
+ EXPECT_EQ(HB_SCRIPT_DEVANAGARI, script);
+
+ ASSERT_TRUE(
+ TestInfo(result)->RunInfoForTesting(1, start_index, num_glyphs, script));
+ EXPECT_EQ(3u, start_index);
+ EXPECT_EQ(3u, num_glyphs);
+ EXPECT_EQ(HB_SCRIPT_DEVANAGARI, script);
+}
+
+TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsDevanagariCommonLatinCommon) {
+ UChar devanagari_common_latin_string[] = {0x915, 0x94d, 0x930, 0x20,
+ 0x61, 0x62, 0x2E};
+ HarfBuzzShaper shaper(String(devanagari_common_latin_string, 7));
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
+
+ EXPECT_EQ(3u, TestInfo(result)->NumberOfRunsForTesting());
+ ASSERT_TRUE(
+ TestInfo(result)->RunInfoForTesting(0, start_index, num_glyphs, script));
+ EXPECT_EQ(0u, start_index);
+ EXPECT_EQ(1u, num_glyphs);
+ EXPECT_EQ(HB_SCRIPT_DEVANAGARI, script);
+
+ ASSERT_TRUE(
+ TestInfo(result)->RunInfoForTesting(1, start_index, num_glyphs, script));
+ EXPECT_EQ(3u, start_index);
+ EXPECT_EQ(1u, num_glyphs);
+ EXPECT_EQ(HB_SCRIPT_DEVANAGARI, script);
+
+ ASSERT_TRUE(
+ TestInfo(result)->RunInfoForTesting(2, start_index, num_glyphs, script));
+ EXPECT_EQ(4u, start_index);
+ EXPECT_EQ(3u, num_glyphs);
+ EXPECT_EQ(HB_SCRIPT_LATIN, script);
+}
+
+TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabicThaiHanLatin) {
+ UChar mixed_string[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62};
+ HarfBuzzShaper shaper(String(mixed_string, 6));
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
+
+ EXPECT_EQ(4u, TestInfo(result)->NumberOfRunsForTesting());
+ ASSERT_TRUE(
+ TestInfo(result)->RunInfoForTesting(0, start_index, num_glyphs, script));
+ EXPECT_EQ(0u, start_index);
+ EXPECT_EQ(3u, num_glyphs);
+ EXPECT_EQ(HB_SCRIPT_ARABIC, script);
+
+ ASSERT_TRUE(
+ TestInfo(result)->RunInfoForTesting(1, start_index, num_glyphs, script));
+ EXPECT_EQ(3u, start_index);
+ EXPECT_EQ(1u, num_glyphs);
+ EXPECT_EQ(HB_SCRIPT_THAI, script);
+
+ ASSERT_TRUE(
+ TestInfo(result)->RunInfoForTesting(2, start_index, num_glyphs, script));
+ EXPECT_EQ(4u, start_index);
+ EXPECT_EQ(1u, num_glyphs);
+ EXPECT_EQ(HB_SCRIPT_HAN, script);
+
+ ASSERT_TRUE(
+ TestInfo(result)->RunInfoForTesting(3, start_index, num_glyphs, script));
+ EXPECT_EQ(5u, start_index);
+ EXPECT_EQ(1u, num_glyphs);
+ EXPECT_EQ(HB_SCRIPT_LATIN, script);
+}
+
+TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabicThaiHanLatinTwice) {
+ UChar mixed_string[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62};
+ HarfBuzzShaper shaper(String(mixed_string, 6));
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
+ EXPECT_EQ(4u, TestInfo(result)->NumberOfRunsForTesting());
+
+ // Shape again on the same shape object and check the number of runs.
+ // Should be equal if no state was retained between shape calls.
+ scoped_refptr<ShapeResult> result2 = shaper.Shape(&font, TextDirection::kLtr);
+ EXPECT_EQ(4u, TestInfo(result2)->NumberOfRunsForTesting());
+}
+
+TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabic) {
+ UChar arabic_string[] = {0x628, 0x64A, 0x629};
+ HarfBuzzShaper shaper(String(arabic_string, 3));
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kRtl);
+
+ EXPECT_EQ(1u, TestInfo(result)->NumberOfRunsForTesting());
+ ASSERT_TRUE(
+ TestInfo(result)->RunInfoForTesting(0, start_index, num_glyphs, script));
+ EXPECT_EQ(0u, start_index);
+ EXPECT_EQ(3u, num_glyphs);
+ EXPECT_EQ(HB_SCRIPT_ARABIC, script);
+}
+
+// This is a simplified test and doesn't accuratly reflect how the shape range
+// is to be used. If you instead of the string you imagine the following HTML:
+// <div>Hello <span>World</span>!</div>
+// It better reflects the intended use where the range given to each shape call
+// corresponds to the text content of a TextNode.
+TEST_F(HarfBuzzShaperTest, ShapeLatinSegment) {
+ String string("Hello World!", 12u);
+ TextDirection direction = TextDirection::kLtr;
+
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> combined = shaper.Shape(&font, direction);
+ scoped_refptr<ShapeResult> first = shaper.Shape(&font, direction, 0, 6);
+ scoped_refptr<ShapeResult> second = shaper.Shape(&font, direction, 6, 11);
+ scoped_refptr<ShapeResult> third = shaper.Shape(&font, direction, 11, 12);
+
+ ASSERT_TRUE(TestInfo(first)->RunInfoForTesting(0, start_index, num_characters,
+ num_glyphs, script));
+ EXPECT_EQ(0u, start_index);
+ EXPECT_EQ(6u, num_characters);
+ ASSERT_TRUE(TestInfo(second)->RunInfoForTesting(
+ 0, start_index, num_characters, num_glyphs, script));
+ EXPECT_EQ(6u, start_index);
+ EXPECT_EQ(5u, num_characters);
+ ASSERT_TRUE(TestInfo(third)->RunInfoForTesting(0, start_index, num_characters,
+ num_glyphs, script));
+ EXPECT_EQ(11u, start_index);
+ EXPECT_EQ(1u, num_characters);
+
+ HarfBuzzShaper shaper2(string.Substring(0, 6));
+ scoped_refptr<ShapeResult> first_reference = shaper2.Shape(&font, direction);
+
+ HarfBuzzShaper shaper3(string.Substring(6, 5));
+ scoped_refptr<ShapeResult> second_reference = shaper3.Shape(&font, direction);
+
+ HarfBuzzShaper shaper4(string.Substring(11, 1));
+ scoped_refptr<ShapeResult> third_reference = shaper4.Shape(&font, direction);
+
+ // Width of each segment should be the same when shaped using start and end
+ // offset as it is when shaping the three segments using separate shaper
+ // instances.
+ // A full pixel is needed for tolerance to account for kerning on some
+ // platforms.
+ ASSERT_NEAR(first_reference->Width(), first->Width(), 1);
+ ASSERT_NEAR(second_reference->Width(), second->Width(), 1);
+ ASSERT_NEAR(third_reference->Width(), third->Width(), 1);
+
+ // Width of shape results for the entire string should match the combined
+ // shape results from the three segments.
+ float total_width = first->Width() + second->Width() + third->Width();
+ ASSERT_NEAR(combined->Width(), total_width, 1);
+}
+
+// Represents the case where a part of a cluster has a different color.
+// <div>0x647<span style="color: red;">0x64A</span></div>
+// This test requires context-aware shaping which hasn't been implemented yet.
+// See crbug.com/689155
+TEST_F(HarfBuzzShaperTest, DISABLED_ShapeArabicWithContext) {
+ UChar arabic_string[] = {0x647, 0x64A};
+ HarfBuzzShaper shaper(String(arabic_string, 2));
+
+ scoped_refptr<ShapeResult> combined =
+ shaper.Shape(&font, TextDirection::kRtl);
+
+ scoped_refptr<ShapeResult> first =
+ shaper.Shape(&font, TextDirection::kRtl, 0, 1);
+ scoped_refptr<ShapeResult> second =
+ shaper.Shape(&font, TextDirection::kRtl, 1, 2);
+
+ // Combined width should be the same when shaping the two characters
+ // separately as when shaping them combined.
+ ASSERT_NEAR(combined->Width(), first->Width() + second->Width(), 0.1);
+}
+
+TEST_F(HarfBuzzShaperTest, ShapeVerticalUpright) {
+ font_description.SetOrientation(FontOrientation::kVerticalUpright);
+ font = Font(font_description);
+ font.Update(nullptr);
+
+ // This string should create 2 runs, ideographic and Latin, both in upright.
+ String string(u"\u65E5\u65E5\u65E5lllll");
+ TextDirection direction = TextDirection::kLtr;
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+
+ // Check width and bounds are not too much different. ".1" is heuristic.
+ EXPECT_NEAR(result->Width(), result->Bounds().Width(), result->Width() * .1);
+
+ // Shape each run and merge them using CopyRange. Bounds() should match.
+ scoped_refptr<ShapeResult> result1 = shaper.Shape(&font, direction, 0, 3);
+ scoped_refptr<ShapeResult> result2 =
+ shaper.Shape(&font, direction, 3, string.length());
+
+ scoped_refptr<ShapeResult> composite_result =
+ ShapeResult::Create(&font, 0, direction);
+ result1->CopyRange(0, 3, composite_result.get());
+ result2->CopyRange(3, string.length(), composite_result.get());
+
+ EXPECT_EQ(result->Bounds(), composite_result->Bounds());
+}
+
+TEST_F(HarfBuzzShaperTest, RangeShapeSmallCaps) {
+ // Test passes if no assertion is hit of the ones below, but also the newly
+ // introduced one in HarfBuzzShaper::ShapeSegment: DCHECK_GT(shape_end,
+ // shape_start) is not hit.
+ FontDescription font_description;
+ font_description.SetVariantCaps(FontDescription::kSmallCaps);
+ font_description.SetComputedSize(12.0);
+ Font font(font_description);
+ font.Update(nullptr);
+
+ // Shaping index 2 to 3 means that case splitting for small caps splits before
+ // character index 2 since the initial 'a' needs to be uppercased, but the
+ // space character does not need to be uppercased. This triggered
+ // crbug.com/817271.
+ String string(u"a aa");
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result =
+ shaper.Shape(&font, TextDirection::kLtr, 2, 3);
+ EXPECT_EQ(1u, result->NumCharacters());
+
+ string = u"aa a";
+ HarfBuzzShaper shaper_two(string);
+ result = shaper_two.Shape(&font, TextDirection::kLtr, 3, 4);
+ EXPECT_EQ(1u, result->NumCharacters());
+
+ string = u"a aa";
+ HarfBuzzShaper shaper_three(string);
+ result = shaper_three.Shape(&font, TextDirection::kLtr, 1, 2);
+ EXPECT_EQ(1u, result->NumCharacters());
+
+ string = u"aa aa aa aa aa aa aa aa aa aa";
+ HarfBuzzShaper shaper_four(string);
+ result = shaper_four.Shape(&font, TextDirection::kLtr, 21, 23);
+ EXPECT_EQ(2u, result->NumCharacters());
+
+ string = u"aa aa aa aa aa aa aa aa aa aa";
+ HarfBuzzShaper shaper_five(string);
+ result = shaper_five.Shape(&font, TextDirection::kLtr, 27, 29);
+ EXPECT_EQ(2u, result->NumCharacters());
+}
+
+TEST_F(HarfBuzzShaperTest, ShapeVerticalMixed) {
+ font_description.SetOrientation(FontOrientation::kVerticalMixed);
+ font = Font(font_description);
+ font.Update(nullptr);
+
+ // This string should create 2 runs, ideographic in upright and Latin in
+ // rotated horizontal.
+ String string(u"\u65E5\u65E5\u65E5lllll");
+ TextDirection direction = TextDirection::kLtr;
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+
+ // Check width and bounds are not too much different. ".1" is heuristic.
+ EXPECT_NEAR(result->Width(), result->Bounds().Width(), result->Width() * .1);
+
+ // Shape each run and merge them using CopyRange. Bounds() should match.
+ scoped_refptr<ShapeResult> result1 = shaper.Shape(&font, direction, 0, 3);
+ scoped_refptr<ShapeResult> result2 =
+ shaper.Shape(&font, direction, 3, string.length());
+
+ scoped_refptr<ShapeResult> composite_result =
+ ShapeResult::Create(&font, 0, direction);
+ result1->CopyRange(0, 3, composite_result.get());
+ result2->CopyRange(3, string.length(), composite_result.get());
+
+ EXPECT_EQ(result->Bounds(), composite_result->Bounds());
+}
+
+TEST_P(ShapeParameterTest, MissingGlyph) {
+ // U+FFF0 is not assigned as of Unicode 10.0.
+ String string(
+ u"\uFFF0"
+ u"Hello");
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = ShapeWithParameter(&shaper);
+ EXPECT_EQ(0u, result->StartIndexForResult());
+ EXPECT_EQ(string.length(), result->EndIndexForResult());
+}
+
+TEST_P(ShapeParameterTest, ZeroWidthSpace) {
+ UChar string[] = {kZeroWidthSpaceCharacter,
+ kZeroWidthSpaceCharacter,
+ 0x0627,
+ 0x0631,
+ 0x062F,
+ 0x0648,
+ kZeroWidthSpaceCharacter,
+ kZeroWidthSpaceCharacter};
+ const unsigned length = base::size(string);
+ HarfBuzzShaper shaper(String(string, length));
+ scoped_refptr<ShapeResult> result = ShapeWithParameter(&shaper);
+ EXPECT_EQ(0u, result->StartIndexForResult());
+ EXPECT_EQ(length, result->EndIndexForResult());
+#if DCHECK_IS_ON()
+ result->CheckConsistency();
+#endif
+}
+
+TEST_F(HarfBuzzShaperTest, NegativeLetterSpacing) {
+ String string(u"Hello");
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
+ float width = result->Width();
+ FloatRect bounds = result->Bounds();
+
+ ShapeResultSpacing<String> spacing(string);
+ FontDescription font_description;
+ font_description.SetLetterSpacing(-5);
+ spacing.SetSpacing(font_description);
+ result->ApplySpacing(spacing);
+
+ EXPECT_EQ(5 * 5, width - result->Width());
+ EXPECT_EQ(5 * 4 - 1, bounds.Width() - result->Bounds().Width());
+}
+
+TEST_F(HarfBuzzShaperTest, NegativeLetterSpacingTo0) {
+ String string(u"00000");
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
+ float char_width = result->Width() / string.length();
+
+ ShapeResultSpacing<String> spacing(string);
+ FontDescription font_description;
+ font_description.SetLetterSpacing(-char_width);
+ spacing.SetSpacing(font_description);
+ result->ApplySpacing(spacing);
+
+ // EXPECT_EQ(0.0f, result->Width());
+ EXPECT_NEAR(0.0f, result->Bounds().X(), 1);
+ // Because all characters are at 0, the glyph bounds must be the char_width.
+ // Allow being larger because accurate width requires re-measuring each glyph.
+ EXPECT_GE(result->Bounds().MaxX(), char_width);
+ EXPECT_LE(result->Bounds().MaxX(), char_width * 1.2);
+}
+
+TEST_F(HarfBuzzShaperTest, NegativeLetterSpacingToNegative) {
+ String string(u"00000");
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
+ float char_width = result->Width() / string.length();
+
+ ShapeResultSpacing<String> spacing(string);
+ FontDescription font_description;
+ font_description.SetLetterSpacing(-2 * char_width);
+ spacing.SetSpacing(font_description);
+ result->ApplySpacing(spacing);
+
+ // CSS does not allow negative width, it should be clampled to 0.
+ // EXPECT_EQ(0.0f, result->Width());
+ // Glyph bounding box should overflow to the left.
+ EXPECT_EQ(-char_width * string.length(), result->Bounds().X());
+ // MaxX() should be char_width. Allow being larger.
+ EXPECT_GE(result->Bounds().MaxX(), char_width);
+}
+
+static struct GlyphDataRangeTestData {
+ const char16_t* text;
+ TextDirection direction;
+ unsigned run_index;
+ unsigned start_offset;
+ unsigned end_offset;
+ unsigned start_glyph;
+ unsigned end_glyph;
+} glyph_data_range_test_data[] = {
+ // Hebrew, taken from fast/text/selection/hebrew-selection.html
+ // The two code points form a grapheme cluster, which produces two glyphs.
+ // Character index array should be [0, 0].
+ {u"\u05E9\u05B0", TextDirection::kRtl, 0, 0, 1, 0, 2},
+#if !defined(OS_MACOSX)
+ // ZWJ tests taken from fast/text/international/zerowidthjoiner.html
+ // Character index array should be [6, 3, 3, 3, 0, 0, 0].
+ // Mac shapes differently and that glyph index expectations do not match.
+ {u"\u0639\u200D\u200D\u0639\u200D\u200D\u0639", TextDirection::kRtl, 0, 0,
+ 1, 4, 7},
+ {u"\u0639\u200D\u200D\u0639\u200D\u200D\u0639", TextDirection::kRtl, 0, 2,
+ 5, 1, 4},
+ {u"\u0639\u200D\u200D\u0639\u200D\u200D\u0639", TextDirection::kRtl, 0, 4,
+ 7, 0, 1},
+#endif
+};
+
+std::ostream& operator<<(std::ostream& ostream,
+ const GlyphDataRangeTestData& data) {
+ return ostream << data.text;
+}
+
+class GlyphDataRangeTest
+ : public HarfBuzzShaperTest,
+ public testing::WithParamInterface<GlyphDataRangeTestData> {};
+
+INSTANTIATE_TEST_CASE_P(HarfBuzzShaperTest,
+ GlyphDataRangeTest,
+ testing::ValuesIn(glyph_data_range_test_data));
+
+TEST_P(GlyphDataRangeTest, Data) {
+ auto data = GetParam();
+ String string(data.text);
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, data.direction);
+
+ auto& run = TestInfo(result)->RunInfoForTesting(data.run_index);
+ auto glyphs = run.FindGlyphDataRange(data.start_offset, data.end_offset);
+ unsigned start_glyph = std::distance(run.glyph_data_.begin(), glyphs.begin);
+ EXPECT_EQ(data.start_glyph, start_glyph);
+ unsigned end_glyph = std::distance(run.glyph_data_.begin(), glyphs.end);
+ EXPECT_EQ(data.end_glyph, end_glyph);
+}
+
+static struct OffsetForPositionTestData {
+ float position;
+ unsigned offset_ltr;
+ unsigned offset_rtl;
+ unsigned hit_test_ltr;
+ unsigned hit_test_rtl;
+ unsigned fit_ltr_ltr;
+ unsigned fit_ltr_rtl;
+ unsigned fit_rtl_ltr;
+ unsigned fit_rtl_rtl;
+} offset_for_position_fixed_pitch_test_data[] = {
+ // The left edge.
+ {-1, 0, 5, 0, 5, 0, 0, 5, 5},
+ {0, 0, 5, 0, 5, 0, 0, 5, 5},
+ // Hit test should round to the nearest glyph at the middle of a glyph.
+ {4, 0, 4, 0, 5, 0, 1, 5, 4},
+ {6, 0, 4, 1, 4, 0, 1, 5, 4},
+ // Glyph boundary between the 1st and the 2nd glyph.
+ // Avoid testing "10.0" to avoid rounding differences on Windows.
+ {9.9, 0, 4, 1, 4, 0, 1, 5, 4},
+ {10.1, 1, 3, 1, 4, 1, 2, 4, 3},
+ // Run boundary is at position 20. The 1st run has 2 characters.
+ {14, 1, 3, 1, 4, 1, 2, 4, 3},
+ {16, 1, 3, 2, 3, 1, 2, 4, 3},
+ {20.1, 2, 2, 2, 3, 2, 3, 3, 2},
+ {24, 2, 2, 2, 3, 2, 3, 3, 2},
+ {26, 2, 2, 3, 2, 2, 3, 3, 2},
+ // The end of the ShapeResult. The result has 5 characters.
+ {44, 4, 0, 4, 1, 4, 5, 1, 0},
+ {46, 4, 0, 5, 0, 4, 5, 1, 0},
+ {50, 5, 0, 5, 0, 5, 5, 0, 0},
+ // Beyond the right edge of the ShapeResult.
+ {51, 5, 0, 5, 0, 5, 5, 0, 0},
+};
+
+std::ostream& operator<<(std::ostream& ostream,
+ const OffsetForPositionTestData& data) {
+ return ostream << data.position;
+}
+
+class OffsetForPositionTest
+ : public HarfBuzzShaperTest,
+ public testing::WithParamInterface<OffsetForPositionTestData> {};
+
+INSTANTIATE_TEST_CASE_P(
+ HarfBuzzShaperTest,
+ OffsetForPositionTest,
+ testing::ValuesIn(offset_for_position_fixed_pitch_test_data));
+
+TEST_P(OffsetForPositionTest, Data) {
+ auto data = GetParam();
+ String string(u"01234");
+ HarfBuzzShaper shaper(string);
+ Font ahem = CreateAhem(10);
+ scoped_refptr<ShapeResult> result =
+ SplitRun(shaper.Shape(&ahem, TextDirection::kLtr), 2);
+ EXPECT_EQ(data.offset_ltr,
+ result->OffsetForPosition(data.position, OnlyFullGlyphs,
+ DontBreakGlyphs));
+ EXPECT_EQ(data.hit_test_ltr,
+ result->OffsetForPosition(data.position, IncludePartialGlyphs,
+ DontBreakGlyphs));
+ EXPECT_EQ(data.fit_ltr_ltr,
+ result->OffsetToFit(data.position, TextDirection::kLtr));
+ EXPECT_EQ(data.fit_ltr_rtl,
+ result->OffsetToFit(data.position, TextDirection::kRtl));
+
+ result = SplitRun(shaper.Shape(&ahem, TextDirection::kRtl), 3);
+ EXPECT_EQ(data.offset_rtl,
+ result->OffsetForPosition(data.position, OnlyFullGlyphs,
+ DontBreakGlyphs));
+ EXPECT_EQ(data.hit_test_rtl,
+ result->OffsetForPosition(data.position, IncludePartialGlyphs,
+ DontBreakGlyphs));
+ EXPECT_EQ(data.fit_rtl_ltr,
+ result->OffsetToFit(data.position, TextDirection::kLtr));
+ EXPECT_EQ(data.fit_rtl_rtl,
+ result->OffsetToFit(data.position, TextDirection::kRtl));
+}
+
+TEST_F(HarfBuzzShaperTest, PositionForOffsetLatin) {
+ String string = To16Bit("Hello World!", 12);
+ TextDirection direction = TextDirection::kLtr;
+
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+ scoped_refptr<ShapeResult> first =
+ shaper.Shape(&font, direction, 0, 5); // Hello
+ scoped_refptr<ShapeResult> second =
+ shaper.Shape(&font, direction, 6, 11); // World
+
+ EXPECT_EQ(0.0f, result->PositionForOffset(0));
+ ASSERT_NEAR(first->Width(), result->PositionForOffset(5), 1);
+ ASSERT_NEAR(second->Width(),
+ result->PositionForOffset(11) - result->PositionForOffset(6), 1);
+ ASSERT_NEAR(result->Width(), result->PositionForOffset(12), 0.1);
+}
+
+TEST_F(HarfBuzzShaperTest, PositionForOffsetArabic) {
+ UChar arabic_string[] = {0x628, 0x64A, 0x629};
+ TextDirection direction = TextDirection::kRtl;
+
+ HarfBuzzShaper shaper(String(arabic_string, 3));
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+
+ EXPECT_EQ(0.0f, result->PositionForOffset(3));
+ ASSERT_NEAR(result->Width(), result->PositionForOffset(0), 0.1);
+}
+
+TEST_F(HarfBuzzShaperTest, EmojiZWJSequence) {
+ UChar emoji_zwj_sequence[] = {0x270C, 0x200D, 0xD83C, 0xDFFF,
+ 0x270C, 0x200D, 0xD83C, 0xDFFC};
+ TextDirection direction = TextDirection::kLtr;
+
+ HarfBuzzShaper shaper(
+ String(emoji_zwj_sequence, base::size(emoji_zwj_sequence)));
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+}
+
+// A Value-Parameterized Test class to test OffsetForPosition() with
+// |include_partial_glyphs| parameter.
+class IncludePartialGlyphsTest : public HarfBuzzShaperTest,
+ public ::testing::WithParamInterface<bool> {};
+
+INSTANTIATE_TEST_CASE_P(OffsetForPositionTest,
+ IncludePartialGlyphsTest,
+ ::testing::Bool());
+
+TEST_P(IncludePartialGlyphsTest,
+ OffsetForPositionMatchesPositionForOffsetLatin) {
+ String string = To16Bit("Hello World!", 12);
+ TextDirection direction = TextDirection::kLtr;
+
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+
+ bool include_partial_glyphs = GetParam();
+ IncludePartialGlyphsOption partial =
+ include_partial_glyphs ? IncludePartialGlyphs : OnlyFullGlyphs;
+
+ EXPECT_EQ(0u, result->OffsetForPosition(result->PositionForOffset(0), partial,
+ DontBreakGlyphs));
+ EXPECT_EQ(1u, result->OffsetForPosition(result->PositionForOffset(1), partial,
+ DontBreakGlyphs));
+ EXPECT_EQ(2u, result->OffsetForPosition(result->PositionForOffset(2), partial,
+ DontBreakGlyphs));
+ EXPECT_EQ(3u, result->OffsetForPosition(result->PositionForOffset(3), partial,
+ DontBreakGlyphs));
+ EXPECT_EQ(4u, result->OffsetForPosition(result->PositionForOffset(4), partial,
+ DontBreakGlyphs));
+ EXPECT_EQ(5u, result->OffsetForPosition(result->PositionForOffset(5), partial,
+ DontBreakGlyphs));
+ EXPECT_EQ(6u, result->OffsetForPosition(result->PositionForOffset(6), partial,
+ DontBreakGlyphs));
+ EXPECT_EQ(7u, result->OffsetForPosition(result->PositionForOffset(7), partial,
+ DontBreakGlyphs));
+ EXPECT_EQ(8u, result->OffsetForPosition(result->PositionForOffset(8), partial,
+ DontBreakGlyphs));
+ EXPECT_EQ(9u, result->OffsetForPosition(result->PositionForOffset(9), partial,
+ DontBreakGlyphs));
+ EXPECT_EQ(10u, result->OffsetForPosition(result->PositionForOffset(10),
+ partial, DontBreakGlyphs));
+ EXPECT_EQ(11u, result->OffsetForPosition(result->PositionForOffset(11),
+ partial, DontBreakGlyphs));
+ EXPECT_EQ(12u, result->OffsetForPosition(result->PositionForOffset(12),
+ partial, DontBreakGlyphs));
+}
+
+TEST_P(IncludePartialGlyphsTest,
+ OffsetForPositionMatchesPositionForOffsetArabic) {
+ UChar arabic_string[] = {0x628, 0x64A, 0x629};
+ TextDirection direction = TextDirection::kRtl;
+
+ HarfBuzzShaper shaper(String(arabic_string, 3));
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+
+ bool include_partial_glyphs = GetParam();
+ IncludePartialGlyphsOption partial =
+ include_partial_glyphs ? IncludePartialGlyphs : OnlyFullGlyphs;
+
+ EXPECT_EQ(0u, result->OffsetForPosition(result->PositionForOffset(0), partial,
+ DontBreakGlyphs));
+ EXPECT_EQ(1u, result->OffsetForPosition(result->PositionForOffset(1), partial,
+ DontBreakGlyphs));
+ EXPECT_EQ(2u, result->OffsetForPosition(result->PositionForOffset(2), partial,
+ DontBreakGlyphs));
+ EXPECT_EQ(3u, result->OffsetForPosition(result->PositionForOffset(3), partial,
+ DontBreakGlyphs));
+}
+
+TEST_P(IncludePartialGlyphsTest,
+ OffsetForPositionMatchesPositionForOffsetMixed) {
+ UChar mixed_string[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62};
+ HarfBuzzShaper shaper(String(mixed_string, 6));
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
+
+ bool include_partial_glyphs = GetParam();
+ IncludePartialGlyphsOption partial =
+ include_partial_glyphs ? IncludePartialGlyphs : OnlyFullGlyphs;
+
+ EXPECT_EQ(0u, result->OffsetForPosition(result->PositionForOffset(0), partial,
+ DontBreakGlyphs));
+ EXPECT_EQ(1u, result->OffsetForPosition(result->PositionForOffset(1), partial,
+ DontBreakGlyphs));
+ EXPECT_EQ(2u, result->OffsetForPosition(result->PositionForOffset(2), partial,
+ DontBreakGlyphs));
+ EXPECT_EQ(3u, result->OffsetForPosition(result->PositionForOffset(3), partial,
+ DontBreakGlyphs));
+ EXPECT_EQ(4u, result->OffsetForPosition(result->PositionForOffset(4), partial,
+ DontBreakGlyphs));
+ EXPECT_EQ(5u, result->OffsetForPosition(result->PositionForOffset(5), partial,
+ DontBreakGlyphs));
+ EXPECT_EQ(6u, result->OffsetForPosition(result->PositionForOffset(6), partial,
+ DontBreakGlyphs));
+}
+
+TEST_F(HarfBuzzShaperTest, CachedOffsetPositionMappingForOffsetLatin) {
+ String string = To16Bit("Hello World!", 12);
+ TextDirection direction = TextDirection::kLtr;
+
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> sr = shaper.Shape(&font, direction);
+ sr->EnsurePositionData();
+
+ EXPECT_EQ(0u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(0)));
+ EXPECT_EQ(1u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(1)));
+ EXPECT_EQ(2u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(2)));
+ EXPECT_EQ(3u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(3)));
+ EXPECT_EQ(4u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(4)));
+ EXPECT_EQ(5u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(5)));
+ EXPECT_EQ(6u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(6)));
+ EXPECT_EQ(7u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(7)));
+ EXPECT_EQ(8u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(8)));
+ EXPECT_EQ(9u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(9)));
+ EXPECT_EQ(10u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(10)));
+ EXPECT_EQ(11u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(11)));
+ EXPECT_EQ(12u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(12)));
+}
+
+TEST_F(HarfBuzzShaperTest, CachedOffsetPositionMappingArabic) {
+ UChar arabic_string[] = {0x628, 0x64A, 0x629};
+ TextDirection direction = TextDirection::kRtl;
+
+ HarfBuzzShaper shaper(String(arabic_string, 3));
+ scoped_refptr<ShapeResult> sr = shaper.Shape(&font, direction);
+ sr->EnsurePositionData();
+
+ EXPECT_EQ(0u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(0)));
+ EXPECT_EQ(1u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(1)));
+ EXPECT_EQ(2u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(2)));
+ EXPECT_EQ(3u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(3)));
+}
+
+TEST_F(HarfBuzzShaperTest, CachedOffsetPositionMappingMixed) {
+ UChar mixed_string[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62};
+ HarfBuzzShaper shaper(String(mixed_string, 6));
+ scoped_refptr<ShapeResult> sr = shaper.Shape(&font, TextDirection::kLtr);
+ sr->EnsurePositionData();
+
+ EXPECT_EQ(0u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(0)));
+ EXPECT_EQ(1u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(1)));
+ EXPECT_EQ(2u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(2)));
+ EXPECT_EQ(3u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(3)));
+ EXPECT_EQ(4u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(4)));
+ EXPECT_EQ(5u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(5)));
+ EXPECT_EQ(6u, sr->CachedOffsetForPosition(sr->CachedPositionForOffset(6)));
+}
+
+TEST_F(HarfBuzzShaperTest, PositionForOffsetMissingGlyph) {
+ String string(u"\u0633\u0644\u0627\u0645");
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kRtl);
+ // Because the offset 1 and 2 should form a ligature, SubRange(2, 4) creates a
+ // ShapeResult that does not have its first glyph.
+ result = result->SubRange(2, 4);
+ result->PositionForOffset(0);
+ // Pass if |PositionForOffset| does not crash.
+}
+
+static struct ShapeResultCopyRangeTestData {
+ const char16_t* string;
+ TextDirection direction;
+ unsigned break_point;
+} shape_result_copy_range_test_data[] = {
+ {u"ABC", TextDirection::kLtr, 1},
+ {u"\u0648\u0644\u064A", TextDirection::kRtl, 1},
+ // These strings creates 3 runs. Split it in the middle of 2nd run.
+ {u"\u65E5Hello\u65E5\u65E5", TextDirection::kLtr, 3},
+ {u"\u0648\u0644\u064A AB \u0628\u062A", TextDirection::kRtl, 5}};
+
+std::ostream& operator<<(std::ostream& ostream,
+ const ShapeResultCopyRangeTestData& data) {
+ return ostream << String(data.string) << " @ " << data.break_point << ", "
+ << data.direction;
+}
+
+class ShapeResultCopyRangeTest
+ : public HarfBuzzShaperTest,
+ public testing::WithParamInterface<ShapeResultCopyRangeTestData> {};
+
+INSTANTIATE_TEST_CASE_P(HarfBuzzShaperTest,
+ ShapeResultCopyRangeTest,
+ testing::ValuesIn(shape_result_copy_range_test_data));
+
+// Split a ShapeResult and combine them should match to the original result.
+TEST_P(ShapeResultCopyRangeTest, Split) {
+ const auto& test_data = GetParam();
+ String string(test_data.string);
+ TextDirection direction = test_data.direction;
+
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+
+ // Split the result.
+ scoped_refptr<ShapeResult> result1 = ShapeResult::Create(&font, 0, direction);
+ result->CopyRange(0, test_data.break_point, result1.get());
+ EXPECT_EQ(test_data.break_point, result1->NumCharacters());
+ EXPECT_EQ(0u, result1->StartIndexForResult());
+ EXPECT_EQ(test_data.break_point, result1->EndIndexForResult());
+
+ scoped_refptr<ShapeResult> result2 = ShapeResult::Create(&font, 0, direction);
+ result->CopyRange(test_data.break_point, string.length(), result2.get());
+ EXPECT_EQ(string.length() - test_data.break_point, result2->NumCharacters());
+ EXPECT_EQ(test_data.break_point, result2->StartIndexForResult());
+ EXPECT_EQ(string.length(), result2->EndIndexForResult());
+
+ // Combine them.
+ scoped_refptr<ShapeResult> composite_result =
+ ShapeResult::Create(&font, 0, direction);
+ result1->CopyRange(0, test_data.break_point, composite_result.get());
+ result2->CopyRange(0, string.length(), composite_result.get());
+ EXPECT_EQ(string.length(), composite_result->NumCharacters());
+
+ // Test character indexes match.
+ Vector<unsigned> expected_character_indexes =
+ TestInfo(result)->CharacterIndexesForTesting();
+ Vector<unsigned> composite_character_indexes =
+ TestInfo(result)->CharacterIndexesForTesting();
+ EXPECT_EQ(expected_character_indexes, composite_character_indexes);
+}
+
+// Shape ranges and combine them shold match to the result of shaping the whole
+// string.
+TEST_P(ShapeResultCopyRangeTest, ShapeRange) {
+ const auto& test_data = GetParam();
+ String string(test_data.string);
+ TextDirection direction = test_data.direction;
+
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+
+ // Shape each range.
+ scoped_refptr<ShapeResult> result1 =
+ shaper.Shape(&font, direction, 0, test_data.break_point);
+ EXPECT_EQ(test_data.break_point, result1->NumCharacters());
+ scoped_refptr<ShapeResult> result2 =
+ shaper.Shape(&font, direction, test_data.break_point, string.length());
+ EXPECT_EQ(string.length() - test_data.break_point, result2->NumCharacters());
+
+ // Combine them.
+ scoped_refptr<ShapeResult> composite_result =
+ ShapeResult::Create(&font, 0, direction);
+ result1->CopyRange(0, test_data.break_point, composite_result.get());
+ result2->CopyRange(0, string.length(), composite_result.get());
+ EXPECT_EQ(string.length(), composite_result->NumCharacters());
+
+ // Test character indexes match.
+ Vector<unsigned> expected_character_indexes =
+ TestInfo(result)->CharacterIndexesForTesting();
+ Vector<unsigned> composite_character_indexes =
+ TestInfo(result)->CharacterIndexesForTesting();
+ EXPECT_EQ(expected_character_indexes, composite_character_indexes);
+}
+
+TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeIntoLatin) {
+ String string = To16Bit("Testing ShapeResult::createSubRun", 33);
+ TextDirection direction = TextDirection::kLtr;
+
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+
+ scoped_refptr<ShapeResult> composite_result =
+ ShapeResult::Create(&font, 0, direction);
+ result->CopyRange(0, 10, composite_result.get());
+ result->CopyRange(10, 20, composite_result.get());
+ result->CopyRange(20, 30, composite_result.get());
+ result->CopyRange(30, 33, composite_result.get());
+
+ EXPECT_EQ(result->NumCharacters(), composite_result->NumCharacters());
+ EXPECT_EQ(result->SnappedWidth(), composite_result->SnappedWidth());
+ EXPECT_EQ(result->Bounds(), composite_result->Bounds());
+ EXPECT_EQ(result->SnappedStartPositionForOffset(0),
+ composite_result->SnappedStartPositionForOffset(0));
+ EXPECT_EQ(result->SnappedStartPositionForOffset(15),
+ composite_result->SnappedStartPositionForOffset(15));
+ EXPECT_EQ(result->SnappedStartPositionForOffset(30),
+ composite_result->SnappedStartPositionForOffset(30));
+ EXPECT_EQ(result->SnappedStartPositionForOffset(33),
+ composite_result->SnappedStartPositionForOffset(33));
+}
+
+TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeIntoArabicThaiHanLatin) {
+ UChar mixed_string[] = {0x628, 0x20, 0x64A, 0x629, 0x20, 0xE20, 0x65E5, 0x62};
+ TextDirection direction = TextDirection::kLtr;
+
+ HarfBuzzShaper shaper(String(mixed_string, 8));
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+
+ // Check width and bounds are not too much different. ".2" is heuristic.
+ EXPECT_NEAR(result->Width(), result->Bounds().Width(), result->Width() * .2);
+
+ scoped_refptr<ShapeResult> composite_result =
+ ShapeResult::Create(&font, 0, direction);
+ result->CopyRange(0, 4, composite_result.get());
+ result->CopyRange(4, 6, composite_result.get());
+ result->CopyRange(6, 8, composite_result.get());
+
+ EXPECT_EQ(result->NumCharacters(), composite_result->NumCharacters());
+ EXPECT_EQ(result->SnappedWidth(), composite_result->SnappedWidth());
+ EXPECT_TRUE(composite_result->Bounds().Contains(result->Bounds()))
+ << composite_result->Bounds() << "/" << result->Bounds();
+ EXPECT_EQ(result->SnappedStartPositionForOffset(0),
+ composite_result->SnappedStartPositionForOffset(0));
+ EXPECT_EQ(result->SnappedStartPositionForOffset(1),
+ composite_result->SnappedStartPositionForOffset(1));
+ EXPECT_EQ(result->SnappedStartPositionForOffset(2),
+ composite_result->SnappedStartPositionForOffset(2));
+ EXPECT_EQ(result->SnappedStartPositionForOffset(3),
+ composite_result->SnappedStartPositionForOffset(3));
+ EXPECT_EQ(result->SnappedStartPositionForOffset(4),
+ composite_result->SnappedStartPositionForOffset(4));
+ EXPECT_EQ(result->SnappedStartPositionForOffset(5),
+ composite_result->SnappedStartPositionForOffset(5));
+ EXPECT_EQ(result->SnappedStartPositionForOffset(6),
+ composite_result->SnappedStartPositionForOffset(6));
+ EXPECT_EQ(result->SnappedStartPositionForOffset(7),
+ composite_result->SnappedStartPositionForOffset(7));
+ EXPECT_EQ(result->SnappedStartPositionForOffset(8),
+ composite_result->SnappedStartPositionForOffset(8));
+}
+
+TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeAcrossRuns) {
+ // Create 3 runs:
+ // [0]: 1 character.
+ // [1]: 5 characters.
+ // [2]: 2 character.
+ String mixed_string(u"\u65E5Hello\u65E5\u65E5");
+ TextDirection direction = TextDirection::kLtr;
+ HarfBuzzShaper shaper(mixed_string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+
+ // Check width and bounds are not too much different. ".1" is heuristic.
+ EXPECT_NEAR(result->Width(), result->Bounds().Width(), result->Width() * .1);
+
+ // CopyRange(5, 7) should copy 1 character from [1] and 1 from [2].
+ scoped_refptr<ShapeResult> target = ShapeResult::Create(&font, 0, direction);
+ result->CopyRange(5, 7, target.get());
+ EXPECT_EQ(2u, target->NumCharacters());
+}
+
+TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeSegmentGlyphBoundingBox) {
+ String string(u"THello worldL");
+ TextDirection direction = TextDirection::kLtr;
+
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result1 = shaper.Shape(&font, direction, 0, 6);
+ scoped_refptr<ShapeResult> result2 =
+ shaper.Shape(&font, direction, 6, string.length());
+
+ scoped_refptr<ShapeResult> composite_result =
+ ShapeResult::Create(&font, 0, direction);
+ result1->CopyRange(0, 6, composite_result.get());
+ result2->CopyRange(6, string.length(), composite_result.get());
+
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+ EXPECT_EQ(result->Bounds(), composite_result->Bounds());
+
+ // Check width and bounds are not too much different. ".1" is heuristic.
+ EXPECT_NEAR(result->Width(), result->Bounds().Width(), result->Width() * .1);
+}
+
+TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeBoundsLtr) {
+ String string(u". ");
+ TextDirection direction = TextDirection::kLtr;
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+
+ // Because a space character does not have ink, the bounds of "." should be
+ // the same as the bounds of ". ".
+ scoped_refptr<ShapeResult> sub_range = result->SubRange(0, 1);
+ EXPECT_EQ(sub_range->Bounds().Width(), result->Bounds().Width());
+}
+
+TEST_F(HarfBuzzShaperTest, ShapeResultCopyRangeBoundsRtl) {
+ String string(u". ");
+ TextDirection direction = TextDirection::kRtl;
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+
+ // Because a space character does not have ink, the bounds of "." should be
+ // the same as the bounds of ". ".
+ scoped_refptr<ShapeResult> sub_range = result->SubRange(0, 1);
+ EXPECT_EQ(sub_range->Bounds().Width(), result->Bounds().Width());
+}
+
+TEST_F(HarfBuzzShaperTest, SubRange) {
+ String string(u"Hello world");
+ TextDirection direction = TextDirection::kRtl;
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+
+ scoped_refptr<ShapeResult> sub_range = result->SubRange(4, 7);
+ DCHECK_EQ(4u, sub_range->StartIndexForResult());
+ DCHECK_EQ(7u, sub_range->EndIndexForResult());
+ DCHECK_EQ(3u, sub_range->NumCharacters());
+ DCHECK_EQ(result->Direction(), sub_range->Direction());
+}
+
+TEST_F(HarfBuzzShaperTest, SafeToBreakLatinCommonLigatures) {
+ FontDescription::VariantLigatures ligatures;
+ ligatures.common = FontDescription::kEnabledLigaturesState;
+
+ // MEgalopolis Extra has a lot of ligatures which this test relies on.
+ Font testFont = blink::test::CreateTestFont(
+ "MEgalopolis",
+ blink::test::PlatformTestDataPath(
+ "third_party/MEgalopolis/MEgalopolisExtra.woff"),
+ 16, &ligatures);
+
+ String string = To16Bit("ffi ff", 6);
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result =
+ shaper.Shape(&testFont, TextDirection::kLtr);
+
+ EXPECT_EQ(0u, result->NextSafeToBreakOffset(0)); // At start of string.
+ EXPECT_EQ(3u, result->NextSafeToBreakOffset(1)); // At end of "ffi" ligature.
+ EXPECT_EQ(3u, result->NextSafeToBreakOffset(2)); // At end of "ffi" ligature.
+ EXPECT_EQ(3u, result->NextSafeToBreakOffset(3)); // At end of "ffi" ligature.
+ EXPECT_EQ(4u, result->NextSafeToBreakOffset(4)); // After space.
+ EXPECT_EQ(6u, result->NextSafeToBreakOffset(5)); // At end of "ff" ligature.
+ EXPECT_EQ(6u, result->NextSafeToBreakOffset(6)); // At end of "ff" ligature.
+
+ // Verify safe to break information in copied results to ensure that both
+ // copying and multi-run break information works.
+ scoped_refptr<ShapeResult> copied_result =
+ ShapeResult::Create(&testFont, 0, TextDirection::kLtr);
+ result->CopyRange(0, 3, copied_result.get());
+ result->CopyRange(3, string.length(), copied_result.get());
+
+ EXPECT_EQ(0u, copied_result->NextSafeToBreakOffset(0));
+ EXPECT_EQ(3u, copied_result->NextSafeToBreakOffset(1));
+ EXPECT_EQ(3u, copied_result->NextSafeToBreakOffset(2));
+ EXPECT_EQ(3u, copied_result->NextSafeToBreakOffset(3));
+ EXPECT_EQ(4u, copied_result->NextSafeToBreakOffset(4));
+ EXPECT_EQ(6u, copied_result->NextSafeToBreakOffset(5));
+ EXPECT_EQ(6u, copied_result->NextSafeToBreakOffset(6));
+}
+
+TEST_F(HarfBuzzShaperTest, SafeToBreakPreviousLatinCommonLigatures) {
+ FontDescription::VariantLigatures ligatures;
+ ligatures.common = FontDescription::kEnabledLigaturesState;
+
+ // MEgalopolis Extra has a lot of ligatures which this test relies on.
+ Font testFont = blink::test::CreateTestFont(
+ "MEgalopolis",
+ blink::test::PlatformTestDataPath(
+ "third_party/MEgalopolis/MEgalopolisExtra.woff"),
+ 16, &ligatures);
+
+ String string = To16Bit("ffi ff", 6);
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result =
+ shaper.Shape(&testFont, TextDirection::kLtr);
+
+ EXPECT_EQ(6u, result->PreviousSafeToBreakOffset(6)); // At end of "ff" liga.
+ EXPECT_EQ(4u, result->PreviousSafeToBreakOffset(5)); // At end of "ff" liga.
+ EXPECT_EQ(4u, result->PreviousSafeToBreakOffset(4)); // After space.
+ EXPECT_EQ(3u, result->PreviousSafeToBreakOffset(3)); // At end of "ffi" liga.
+ EXPECT_EQ(0u, result->PreviousSafeToBreakOffset(2)); // At start of string.
+ EXPECT_EQ(0u, result->PreviousSafeToBreakOffset(1)); // At start of string.
+ EXPECT_EQ(0u, result->PreviousSafeToBreakOffset(0)); // At start of string.
+
+ // Verify safe to break information in copied results to ensure that both
+ // copying and multi-run break information works.
+ scoped_refptr<ShapeResult> copied_result =
+ ShapeResult::Create(&testFont, 0, TextDirection::kLtr);
+ result->CopyRange(0, 3, copied_result.get());
+ result->CopyRange(3, string.length(), copied_result.get());
+
+ EXPECT_EQ(6u, copied_result->PreviousSafeToBreakOffset(6));
+ EXPECT_EQ(4u, copied_result->PreviousSafeToBreakOffset(5));
+ EXPECT_EQ(4u, copied_result->PreviousSafeToBreakOffset(4));
+ EXPECT_EQ(3u, copied_result->PreviousSafeToBreakOffset(3));
+ EXPECT_EQ(0u, copied_result->PreviousSafeToBreakOffset(2));
+ EXPECT_EQ(0u, copied_result->PreviousSafeToBreakOffset(1));
+ EXPECT_EQ(0u, copied_result->PreviousSafeToBreakOffset(0));
+}
+
+TEST_F(HarfBuzzShaperTest, SafeToBreakLatinDiscretionaryLigatures) {
+ FontDescription::VariantLigatures ligatures;
+ ligatures.common = FontDescription::kEnabledLigaturesState;
+ ligatures.discretionary = FontDescription::kEnabledLigaturesState;
+
+ // MEgalopolis Extra has a lot of ligatures which this test relies on.
+ Font testFont = blink::test::CreateTestFont(
+ "MEgalopolis",
+ blink::test::PlatformTestDataPath(
+ "third_party/MEgalopolis/MEgalopolisExtra.woff"),
+ 16, &ligatures);
+
+ // RA and CA form ligatures, most glyph pairs have kerning.
+ String string(u"ABRACADABRA");
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result =
+ shaper.Shape(&testFont, TextDirection::kLtr);
+ EXPECT_EQ(6u, result->NextSafeToBreakOffset(1)); // After CA ligature.
+ EXPECT_EQ(6u, result->NextSafeToBreakOffset(6)); // After CA ligature.
+ EXPECT_EQ(11u, result->NextSafeToBreakOffset(7)); // At end of string.
+ EXPECT_EQ(11u, result->NextSafeToBreakOffset(9)); // At end of string.
+ EXPECT_EQ(11u, result->NextSafeToBreakOffset(10)); // At end of string.
+
+ // Add zero-width spaces at the safe to break offsets.
+ String refString(u"ABRACA\u200BDAB\u200BRA");
+ HarfBuzzShaper refShaper(refString);
+ scoped_refptr<ShapeResult> referenceResult =
+ refShaper.Shape(&testFont, TextDirection::kLtr);
+
+ // Results should be identical if it truly is safe to break at the designated
+ // safe-to-break offsets
+ EXPECT_EQ(result->SnappedWidth(), referenceResult->SnappedWidth());
+ EXPECT_EQ(result->Bounds(), referenceResult->Bounds());
+ EXPECT_EQ(result->SnappedStartPositionForOffset(0),
+ referenceResult->SnappedStartPositionForOffset(0));
+ EXPECT_EQ(result->SnappedStartPositionForOffset(1),
+ referenceResult->SnappedStartPositionForOffset(1));
+ EXPECT_EQ(result->SnappedStartPositionForOffset(2),
+ referenceResult->SnappedStartPositionForOffset(2));
+ EXPECT_EQ(result->SnappedStartPositionForOffset(3),
+ referenceResult->SnappedStartPositionForOffset(3));
+ EXPECT_EQ(result->SnappedStartPositionForOffset(4),
+ referenceResult->SnappedStartPositionForOffset(4));
+ EXPECT_EQ(result->SnappedStartPositionForOffset(5),
+ referenceResult->SnappedStartPositionForOffset(5));
+
+ // First zero-width space is at position 6 so the the matching character in
+ // the reference results is 7.
+ EXPECT_EQ(result->SnappedStartPositionForOffset(6),
+ referenceResult->SnappedStartPositionForOffset(7));
+ EXPECT_EQ(result->SnappedStartPositionForOffset(7),
+ referenceResult->SnappedStartPositionForOffset(8));
+ EXPECT_EQ(result->SnappedStartPositionForOffset(8),
+ referenceResult->SnappedStartPositionForOffset(9));
+
+ // Second zero-width space is at position 9 so the the matching character in
+ // the reference results is 11.
+ EXPECT_EQ(result->SnappedStartPositionForOffset(9),
+ referenceResult->SnappedStartPositionForOffset(11));
+ EXPECT_EQ(result->SnappedStartPositionForOffset(10),
+ referenceResult->SnappedStartPositionForOffset(12));
+}
+
+// TODO(layout-dev): This test fails on Mac due to AAT shaping.
+TEST_F(HarfBuzzShaperTest, DISABLED_SafeToBreakArabicCommonLigatures) {
+ FontDescription::VariantLigatures ligatures;
+ ligatures.common = FontDescription::kEnabledLigaturesState;
+
+ // كسر الاختبار
+ String string(
+ u"\u0643\u0633\u0631\u0020\u0627\u0644\u0627\u062E\u062A\u0628\u0627"
+ u"\u0631");
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kRtl);
+
+ // Safe to break at 0, 3, 4, 5, 7, and 11.
+ EXPECT_EQ(0u, result->NextSafeToBreakOffset(0));
+ EXPECT_EQ(3u, result->NextSafeToBreakOffset(1));
+ EXPECT_EQ(3u, result->NextSafeToBreakOffset(2));
+ EXPECT_EQ(3u, result->NextSafeToBreakOffset(3));
+ EXPECT_EQ(4u, result->NextSafeToBreakOffset(4));
+ EXPECT_EQ(5u, result->NextSafeToBreakOffset(5));
+ EXPECT_EQ(7u, result->NextSafeToBreakOffset(6));
+ EXPECT_EQ(7u, result->NextSafeToBreakOffset(7));
+ EXPECT_EQ(11u, result->NextSafeToBreakOffset(8));
+ EXPECT_EQ(11u, result->NextSafeToBreakOffset(9));
+ EXPECT_EQ(11u, result->NextSafeToBreakOffset(10));
+ EXPECT_EQ(11u, result->NextSafeToBreakOffset(11));
+ EXPECT_EQ(12u, result->NextSafeToBreakOffset(12));
+}
+
+// TODO(layout-dev): Expand RTL test coverage and add tests for mixed
+// directionality strings.
+
+// Test when some characters are missing in |runs_|.
+// RTL on Mac may not have runs for all characters. crbug.com/774034
+TEST_P(ShapeParameterTest, DISABLED_SafeToBreakMissingRun) {
+ TextDirection direction = GetParam();
+ scoped_refptr<ShapeResult> result = ShapeResult::Create(&font, 8, direction);
+ result->InsertRunForTesting(2, 1, direction, {0});
+ result->InsertRunForTesting(3, 3, direction, {0, 1});
+ // The character index 6 and 7 is missing.
+ result->InsertRunForTesting(8, 2, direction, {0});
+#if DCHECK_IS_ON()
+ result->CheckConsistency();
+#endif
+
+ EXPECT_EQ(2u, result->StartIndexForResult());
+ EXPECT_EQ(10u, result->EndIndexForResult());
+
+ EXPECT_EQ(2u, result->NextSafeToBreakOffset(2));
+ EXPECT_EQ(3u, result->NextSafeToBreakOffset(3));
+ EXPECT_EQ(4u, result->NextSafeToBreakOffset(4));
+ EXPECT_EQ(6u, result->NextSafeToBreakOffset(5));
+ EXPECT_EQ(6u, result->NextSafeToBreakOffset(6));
+ EXPECT_EQ(8u, result->NextSafeToBreakOffset(7));
+ EXPECT_EQ(8u, result->NextSafeToBreakOffset(8));
+ EXPECT_EQ(10u, result->NextSafeToBreakOffset(9));
+
+ EXPECT_EQ(2u, result->PreviousSafeToBreakOffset(2));
+ EXPECT_EQ(3u, result->PreviousSafeToBreakOffset(3));
+ EXPECT_EQ(4u, result->PreviousSafeToBreakOffset(4));
+ EXPECT_EQ(4u, result->PreviousSafeToBreakOffset(5));
+ EXPECT_EQ(6u, result->PreviousSafeToBreakOffset(6));
+ EXPECT_EQ(6u, result->PreviousSafeToBreakOffset(7));
+ EXPECT_EQ(8u, result->PreviousSafeToBreakOffset(8));
+ EXPECT_EQ(8u, result->PreviousSafeToBreakOffset(9));
+}
+
+// Call this to ensure your test string has some kerning going on.
+static bool KerningIsHappening(const FontDescription& font_description,
+ TextDirection direction,
+ const String& str) {
+ FontDescription no_kern = font_description;
+ no_kern.SetKerning(FontDescription::kNoneKerning);
+
+ FontDescription kern = font_description;
+ kern.SetKerning(FontDescription::kAutoKerning);
+
+ Font font_no_kern(no_kern);
+ font_no_kern.Update(nullptr);
+
+ Font font_kern(kern);
+ font_kern.Update(nullptr);
+
+ HarfBuzzShaper shaper(str);
+
+ scoped_refptr<ShapeResult> result_no_kern =
+ shaper.Shape(&font_no_kern, direction);
+ scoped_refptr<ShapeResult> result_kern = shaper.Shape(&font_kern, direction);
+
+ for (unsigned i = 0; i < str.length(); i++) {
+ if (result_no_kern->PositionForOffset(i) !=
+ result_kern->PositionForOffset(i))
+ return true;
+ }
+ return false;
+}
+
+TEST_F(HarfBuzzShaperTest, KerningIsHappeningWorks) {
+ EXPECT_TRUE(
+ KerningIsHappening(font_description, TextDirection::kLtr, u"AVOID"));
+ EXPECT_FALSE(
+ KerningIsHappening(font_description, TextDirection::kLtr, u"NOID"));
+
+ // We won't kern vertically with the default font.
+ font_description.SetOrientation(FontOrientation::kVerticalUpright);
+
+ EXPECT_FALSE(
+ KerningIsHappening(font_description, TextDirection::kLtr, u"AVOID"));
+ EXPECT_FALSE(
+ KerningIsHappening(font_description, TextDirection::kLtr, u"NOID"));
+}
+
+TEST_F(HarfBuzzShaperTest,
+ ShapeHorizontalWithoutSubpixelPositionWithoutKerningIsRounded) {
+ ScopedSubpixelOverride subpixel_override(false);
+
+ String string(u"NOID");
+ TextDirection direction = TextDirection::kLtr;
+ ASSERT_FALSE(KerningIsHappening(font_description, direction, string));
+
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+
+ for (unsigned i = 0; i < string.length(); i++) {
+ float position = result->PositionForOffset(i);
+ EXPECT_EQ(round(position), position)
+ << "Position not rounded at offset " << i;
+ }
+}
+
+TEST_F(HarfBuzzShaperTest,
+ ShapeHorizontalWithSubpixelPositionWithoutKerningIsNotRounded) {
+ ScopedSubpixelOverride subpixel_override(true);
+
+ String string(u"NOID");
+ TextDirection direction = TextDirection::kLtr;
+ ASSERT_FALSE(KerningIsHappening(font_description, direction, string));
+
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+
+ for (unsigned i = 0; i < string.length(); i++) {
+ float position = result->PositionForOffset(i);
+ if (round(position) != position)
+ return;
+ }
+
+ EXPECT_TRUE(false) << "No unrounded positions found";
+}
+
+TEST_F(HarfBuzzShaperTest,
+ ShapeHorizontalWithoutSubpixelPositionWithKerningIsRounded) {
+ ScopedSubpixelOverride subpixel_override(false);
+
+ String string(u"AVOID");
+ TextDirection direction = TextDirection::kLtr;
+ ASSERT_TRUE(KerningIsHappening(font_description, direction, string));
+
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+
+ for (unsigned i = 0; i < string.length(); i++) {
+ float position = result->PositionForOffset(i);
+ EXPECT_EQ(round(position), position)
+ << "Position not rounded at offset " << i;
+ }
+}
+
+TEST_F(HarfBuzzShaperTest,
+ ShapeHorizontalWithSubpixelPositionWithKerningIsNotRounded) {
+ ScopedSubpixelOverride subpixel_override(true);
+
+ String string(u"AVOID");
+ TextDirection direction = TextDirection::kLtr;
+ ASSERT_TRUE(KerningIsHappening(font_description, direction, string));
+
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+
+ for (unsigned i = 0; i < string.length(); i++) {
+ float position = result->PositionForOffset(i);
+ if (round(position) != position)
+ return;
+ }
+
+ EXPECT_TRUE(false) << "No unrounded positions found";
+}
+
+TEST_F(HarfBuzzShaperTest, ShapeVerticalWithoutSubpixelPositionIsRounded) {
+ ScopedSubpixelOverride subpixel_override(false);
+
+ font_description.SetOrientation(FontOrientation::kVerticalUpright);
+ font = Font(font_description);
+ font.Update(nullptr);
+
+ String string(u"\u65E5\u65E5\u65E5");
+ TextDirection direction = TextDirection::kLtr;
+
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+
+ for (unsigned i = 0; i < string.length(); i++) {
+ float position = result->PositionForOffset(i);
+ EXPECT_EQ(round(position), position)
+ << "Position not rounded at offset " << i;
+ }
+}
+
+TEST_F(HarfBuzzShaperTest, ShapeVerticalWithSubpixelPositionIsRounded) {
+ ScopedSubpixelOverride subpixel_override(true);
+
+ font_description.SetOrientation(FontOrientation::kVerticalUpright);
+ font = Font(font_description);
+ font.Update(nullptr);
+
+ String string(u"\u65E5\u65E5\u65E5");
+ TextDirection direction = TextDirection::kLtr;
+
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+
+ // Vertical text is never subpixel positioned.
+ for (unsigned i = 0; i < string.length(); i++) {
+ float position = result->PositionForOffset(i);
+ EXPECT_EQ(round(position), position)
+ << "Position not rounded at offset " << i;
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.cc
index e3a4b5bba8d..b6c634c08be 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.cc
@@ -74,34 +74,9 @@ void RunSegmenter::ConsumeSymbolsIteratorPastLastSplit() {
}
}
-bool RunSegmenter::Supports(FontOrientation orientation) const {
- bool needs_orientation_iterator =
- orientation == FontOrientation::kVerticalMixed;
- return (needs_orientation_iterator == !!orientation_iterator_.get());
-}
-
-bool RunSegmenter::HasProgressedPast(unsigned start) const {
- return candidate_range_.start > start;
-}
-
-bool RunSegmenter::ConsumePast(unsigned start, RunSegmenterRange* next_range) {
- DCHECK(!HasProgressedPast(start));
- while (true) {
- // Check the candidate range first, before checking |at_end_| because
- // |Consume()| sets |at_end_| even when the current range is valid.
- if (candidate_range_.start <= start && start < candidate_range_.end) {
- *next_range = candidate_range_;
- return true;
- }
-
- if (!Consume())
- return false;
- }
-}
-
// Consume the input until the next range. Returns false if no more ranges are
// available.
-bool RunSegmenter::Consume() {
+bool RunSegmenter::Consume(RunSegmenterRange* next_range) {
if (at_end_)
return false;
@@ -126,6 +101,7 @@ bool RunSegmenter::Consume() {
candidate_range_.start = candidate_range_.end;
candidate_range_.end = last_split_;
+ *next_range = candidate_range_;
at_end_ = last_split_ == buffer_size_;
return true;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h
index c006aefdc5f..86bfc774f28 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h
@@ -39,20 +39,7 @@ class PLATFORM_EXPORT RunSegmenter {
// Initialize a RunSegmenter.
RunSegmenter(const UChar* buffer, unsigned buffer_size, FontOrientation);
- // Returns true if the internal state is past |start|. RunSegmenter is forward
- // incremental that once it's past a point, it cannot be used for text before
- // it. On the ohter hand, if it's not, caller can use the existing instance.
- bool HasProgressedPast(unsigned start) const;
-
- // Returns true if this instance supports the specified FontOrientation.
- bool Supports(FontOrientation) const;
-
- // Advance to the range that includes |start| and return the range. Returns
- // false if there are no such ranges.
- //
- // Callers need to update |start| of the next call to the previous range end
- // when they need next range.
- bool ConsumePast(unsigned start, RunSegmenterRange*);
+ bool Consume(RunSegmenterRange*);
static RunSegmenterRange NullRange() {
return {0, 0, USCRIPT_INVALID_CODE, OrientationIterator::kOrientationKeep,
@@ -63,7 +50,6 @@ class PLATFORM_EXPORT RunSegmenter {
void ConsumeOrientationIteratorPastLastSplit();
void ConsumeScriptIteratorPastLastSplit();
void ConsumeSymbolsIteratorPastLastSplit();
- bool Consume();
unsigned buffer_size_;
RunSegmenterRange candidate_range_;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter_test.cc
index caf858e62c1..20c9d582be1 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/run_segmenter_test.cc
@@ -57,13 +57,19 @@ class RunSegmenterTest : public testing::Test {
VerifyRuns(&run_segmenter, expect);
}
+ void CheckRunsMixed(const Vector<SegmenterTestRun>& runs) {
+ CheckRuns(runs, FontOrientation::kVerticalMixed);
+ }
+
+ void CheckRunsHorizontal(const Vector<SegmenterTestRun>& runs) {
+ CheckRuns(runs, FontOrientation::kHorizontal);
+ }
+
void VerifyRuns(RunSegmenter* run_segmenter,
const Vector<SegmenterExpectedRun>& expect) {
RunSegmenter::RunSegmenterRange segmenter_range;
unsigned long run_count = 0;
- for (unsigned run_segmenter_start = 0;
- run_segmenter->ConsumePast(run_segmenter_start, &segmenter_range);
- run_segmenter_start = segmenter_range.end) {
+ while (run_segmenter->Consume(&segmenter_range)) {
ASSERT_LT(run_count, expect.size());
ASSERT_EQ(expect[run_count].start, segmenter_range.start);
ASSERT_EQ(expect[run_count].limit, segmenter_range.end);
@@ -78,27 +84,13 @@ class RunSegmenterTest : public testing::Test {
}
};
-// Some of our compilers cannot initialize a vector from an array yet.
-#define DECLARE_SEGMENTER_RUNSVECTOR(...) \
- static const SegmenterTestRun kRunsArray[] = __VA_ARGS__; \
- Vector<SegmenterTestRun> runs; \
- runs.Append(kRunsArray, sizeof(kRunsArray) / sizeof(*kRunsArray));
-
-#define CHECK_RUNS_MIXED(...) \
- DECLARE_SEGMENTER_RUNSVECTOR(__VA_ARGS__); \
- CheckRuns(runs, FontOrientation::kVerticalMixed);
-
-#define CHECK_RUNS_HORIZONTAL(...) \
- DECLARE_SEGMENTER_RUNSVECTOR(__VA_ARGS__); \
- CheckRuns(runs, FontOrientation::kHorizontal);
-
TEST_F(RunSegmenterTest, Empty) {
String empty(g_empty_string16_bit);
RunSegmenter::RunSegmenterRange segmenter_range = {
0, 0, USCRIPT_INVALID_CODE, OrientationIterator::kOrientationKeep};
RunSegmenter run_segmenter(empty.Characters16(), empty.length(),
FontOrientation::kVerticalMixed);
- DCHECK(!run_segmenter.ConsumePast(0, &segmenter_range));
+ DCHECK(!run_segmenter.Consume(&segmenter_range));
ASSERT_EQ(segmenter_range.start, 0u);
ASSERT_EQ(segmenter_range.end, 0u);
ASSERT_EQ(segmenter_range.script, USCRIPT_INVALID_CODE);
@@ -109,19 +101,19 @@ TEST_F(RunSegmenterTest, Empty) {
}
TEST_F(RunSegmenterTest, LatinPunctuationSideways) {
- CHECK_RUNS_MIXED({{"Abc.;?Xyz", USCRIPT_LATIN,
- OrientationIterator::kOrientationRotateSideways,
- FontFallbackPriority::kText}});
+ CheckRunsMixed({{"Abc.;?Xyz", USCRIPT_LATIN,
+ OrientationIterator::kOrientationRotateSideways,
+ FontFallbackPriority::kText}});
}
TEST_F(RunSegmenterTest, OneSpace) {
- CHECK_RUNS_MIXED(
+ CheckRunsMixed(
{{" ", USCRIPT_COMMON, OrientationIterator::kOrientationRotateSideways,
FontFallbackPriority::kText}});
}
TEST_F(RunSegmenterTest, ArabicHangul) {
- CHECK_RUNS_MIXED(
+ CheckRunsMixed(
{{"نص", USCRIPT_ARABIC, OrientationIterator::kOrientationRotateSideways,
FontFallbackPriority::kText},
{"키스의", USCRIPT_HANGUL, OrientationIterator::kOrientationKeep,
@@ -129,7 +121,7 @@ TEST_F(RunSegmenterTest, ArabicHangul) {
}
TEST_F(RunSegmenterTest, JapaneseHindiEmojiMix) {
- CHECK_RUNS_MIXED(
+ CheckRunsMixed(
{{"百家姓", USCRIPT_HAN, OrientationIterator::kOrientationKeep,
FontFallbackPriority::kText},
{"ऋषियों", USCRIPT_DEVANAGARI,
@@ -144,13 +136,13 @@ TEST_F(RunSegmenterTest, JapaneseHindiEmojiMix) {
}
TEST_F(RunSegmenterTest, CombiningCirlce) {
- CHECK_RUNS_HORIZONTAL(
+ CheckRunsHorizontal(
{{"◌́◌̀◌̈◌̂◌̄◌̊", USCRIPT_COMMON, OrientationIterator::kOrientationKeep,
FontFallbackPriority::kText}});
}
TEST_F(RunSegmenterTest, HangulSpace) {
- CHECK_RUNS_MIXED(
+ CheckRunsMixed(
{{"키스의", USCRIPT_HANGUL, OrientationIterator::kOrientationKeep,
FontFallbackPriority::kText},
{" ", USCRIPT_HANGUL, OrientationIterator::kOrientationRotateSideways,
@@ -160,19 +152,18 @@ TEST_F(RunSegmenterTest, HangulSpace) {
}
TEST_F(RunSegmenterTest, TechnicalCommonUpright) {
- CHECK_RUNS_MIXED(
- {{"⌀⌁⌂", USCRIPT_COMMON, OrientationIterator::kOrientationKeep,
- FontFallbackPriority::kText}});
+ CheckRunsMixed({{"⌀⌁⌂", USCRIPT_COMMON, OrientationIterator::kOrientationKeep,
+ FontFallbackPriority::kText}});
}
TEST_F(RunSegmenterTest, PunctuationCommonSideways) {
- CHECK_RUNS_MIXED(
+ CheckRunsMixed(
{{".…¡", USCRIPT_COMMON, OrientationIterator::kOrientationRotateSideways,
FontFallbackPriority::kText}});
}
TEST_F(RunSegmenterTest, JapanesePunctuationMixedInside) {
- CHECK_RUNS_MIXED(
+ CheckRunsMixed(
{{"いろはに", USCRIPT_HIRAGANA, OrientationIterator::kOrientationKeep,
FontFallbackPriority::kText},
{".…¡", USCRIPT_HIRAGANA,
@@ -183,19 +174,19 @@ TEST_F(RunSegmenterTest, JapanesePunctuationMixedInside) {
}
TEST_F(RunSegmenterTest, JapanesePunctuationMixedInsideHorizontal) {
- CHECK_RUNS_HORIZONTAL(
+ CheckRunsHorizontal(
{{"いろはに.…¡ほへと", USCRIPT_HIRAGANA,
OrientationIterator::kOrientationKeep, FontFallbackPriority::kText}});
}
TEST_F(RunSegmenterTest, PunctuationDevanagariCombining) {
- CHECK_RUNS_HORIZONTAL(
+ CheckRunsHorizontal(
{{"क+े", USCRIPT_DEVANAGARI, OrientationIterator::kOrientationKeep,
FontFallbackPriority::kText}});
}
TEST_F(RunSegmenterTest, EmojiZWJSequences) {
- CHECK_RUNS_HORIZONTAL(
+ CheckRunsHorizontal(
{{"👩‍👩‍👧‍👦👩‍❤️‍💋‍👨", USCRIPT_LATIN,
OrientationIterator::kOrientationKeep,
FontFallbackPriority::kEmojiEmoji},
@@ -208,7 +199,7 @@ TEST_F(RunSegmenterTest, EmojiZWJSequences) {
}
TEST_F(RunSegmenterTest, JapaneseLetterlikeEnd) {
- CHECK_RUNS_MIXED(
+ CheckRunsMixed(
{{"いろは", USCRIPT_HIRAGANA, OrientationIterator::kOrientationKeep,
FontFallbackPriority::kText},
{"ℐℒℐℒℐℒℐℒℐℒℐℒℐℒ", USCRIPT_HIRAGANA,
@@ -217,7 +208,7 @@ TEST_F(RunSegmenterTest, JapaneseLetterlikeEnd) {
}
TEST_F(RunSegmenterTest, JapaneseCase) {
- CHECK_RUNS_MIXED(
+ CheckRunsMixed(
{{"いろは", USCRIPT_HIRAGANA, OrientationIterator::kOrientationKeep,
FontFallbackPriority::kText},
{"aaAA", USCRIPT_LATIN, OrientationIterator::kOrientationRotateSideways,
@@ -227,13 +218,13 @@ TEST_F(RunSegmenterTest, JapaneseCase) {
}
TEST_F(RunSegmenterTest, DingbatsMiscSymbolsModifier) {
- CHECK_RUNS_HORIZONTAL({{"⛹🏻✍🏻✊🏼", USCRIPT_COMMON,
- OrientationIterator::kOrientationKeep,
- FontFallbackPriority::kEmojiEmoji}});
+ CheckRunsHorizontal({{"⛹🏻✍🏻✊🏼", USCRIPT_COMMON,
+ OrientationIterator::kOrientationKeep,
+ FontFallbackPriority::kEmojiEmoji}});
}
TEST_F(RunSegmenterTest, ArmenianCyrillicCase) {
- CHECK_RUNS_HORIZONTAL(
+ CheckRunsHorizontal(
{{"աբգ", USCRIPT_ARMENIAN, OrientationIterator::kOrientationKeep,
FontFallbackPriority::kText},
{"αβγ", USCRIPT_GREEK, OrientationIterator::kOrientationKeep,
@@ -243,36 +234,22 @@ TEST_F(RunSegmenterTest, ArmenianCyrillicCase) {
}
TEST_F(RunSegmenterTest, EmojiSubdivisionFlags) {
- CHECK_RUNS_HORIZONTAL(
+ CheckRunsHorizontal(
{{"🏴󠁧󠁢󠁷󠁬󠁳󠁿🏴󠁧󠁢󠁳󠁣󠁴󠁿🏴󠁧󠁢"
"󠁥󠁮󠁧󠁿",
USCRIPT_COMMON, OrientationIterator::kOrientationKeep,
FontFallbackPriority::kEmojiEmoji}});
}
-// Test ConsumePast with |start| advances to the run that includes |start|.
-TEST_F(RunSegmenterTest, PastFirstRun) {
- String text(u"αβγあいうabc");
- RunSegmenter run_segmenter(text.Characters16(), text.length(),
- FontOrientation::kHorizontal);
- RunSegmenter::RunSegmenterRange segmenter_range;
- EXPECT_TRUE(run_segmenter.ConsumePast(7, &segmenter_range));
- EXPECT_EQ(segmenter_range.start, 6u);
- EXPECT_EQ(segmenter_range.end, 9u);
- EXPECT_EQ(segmenter_range.script, USCRIPT_LATIN);
- EXPECT_EQ(segmenter_range.render_orientation,
- OrientationIterator::kOrientationKeep);
- EXPECT_EQ(segmenter_range.font_fallback_priority,
- FontFallbackPriority::kText);
-}
-
-// Test ConsumePast with |start| larger than buffer size returns false.
-TEST_F(RunSegmenterTest, PastBufferLength) {
- String text(u"abc");
- RunSegmenter run_segmenter(text.Characters16(), text.length(),
- FontOrientation::kHorizontal);
- RunSegmenter::RunSegmenterRange segmenter_range;
- EXPECT_FALSE(run_segmenter.ConsumePast(4, &segmenter_range));
+TEST_F(RunSegmenterTest, NonEmojiPresentationSymbols) {
+ CheckRunsHorizontal(
+ {{u8"\U00002626\U0000262a\U00002638\U0000271d\U00002721", USCRIPT_COMMON,
+ OrientationIterator::kOrientationKeep,
+ FontFallbackPriority::kEmojiText},
+ {u8"\U00002627\U00002628\U00002629\U0000262b\U0000262c\U00002670"
+ "\U00002671\U0000271f\U00002720",
+ USCRIPT_COMMON, OrientationIterator::kOrientationKeep,
+ FontFallbackPriority::kText}});
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
index 50e7d5789bb..5d23754b831 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
@@ -37,6 +37,8 @@
#include <memory>
#include <utility>
+#include "base/containers/adapters.h"
+#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/platform/fonts/character_range.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h"
@@ -46,11 +48,22 @@
namespace blink {
+constexpr unsigned HarfBuzzRunGlyphData::kMaxCharacterIndex;
+
unsigned ShapeResult::RunInfo::NextSafeToBreakOffset(unsigned offset) const {
DCHECK_LE(offset, num_characters_);
- for (unsigned i = 0; i < safe_break_offsets_.size(); i++) {
- if (safe_break_offsets_[i] >= offset)
- return safe_break_offsets_[i];
+ if (!Rtl()) {
+ for (const auto& glyph_data : glyph_data_) {
+ if (glyph_data.safe_to_break_before &&
+ glyph_data.character_index >= offset)
+ return glyph_data.character_index;
+ }
+ } else {
+ for (const auto& glyph_data : base::Reversed(glyph_data_)) {
+ if (glyph_data.safe_to_break_before &&
+ glyph_data.character_index >= offset)
+ return glyph_data.character_index;
+ }
}
// Next safe break is at the end of the run.
@@ -61,10 +74,18 @@ unsigned ShapeResult::RunInfo::PreviousSafeToBreakOffset(
unsigned offset) const {
if (offset >= num_characters_)
return num_characters_;
-
- for (unsigned i = safe_break_offsets_.size(); i > 0; i--) {
- if (safe_break_offsets_[i - 1] <= offset)
- return safe_break_offsets_[i - 1];
+ if (!Rtl()) {
+ for (const auto& glyph_data : base::Reversed(glyph_data_)) {
+ if (glyph_data.safe_to_break_before &&
+ glyph_data.character_index <= offset)
+ return glyph_data.character_index;
+ }
+ } else {
+ for (const auto& glyph_data : glyph_data_) {
+ if (glyph_data.safe_to_break_before &&
+ glyph_data.character_index <= offset)
+ return glyph_data.character_index;
+ }
}
// Next safe break is at the start of the run.
@@ -80,100 +101,234 @@ float ShapeResult::RunInfo::XPositionForVisualOffset(
return XPositionForOffset(offset, adjust_mid_cluster);
}
+unsigned ShapeResult::RunInfo::NumGraphemes(unsigned start,
+ unsigned end) const {
+ if (graphemes_.size() == 0 || start >= num_characters_)
+ return 0;
+ DCHECK_LT(start, end);
+ DCHECK_LE(end, num_characters_);
+ return graphemes_[end - 1] - graphemes_[start] + 1;
+}
+
+// XPositionForOffset returns the X position (in layout space) from the
+// beginning of the run to the beginning of the cluster of glyphs for X
+// character.
+// For RTL, beginning means the right most side of the cluster.
+// Characters may spawn multiple glyphs.
+// In the case that multiple characters form a Unicode grapheme cluster, we
+// distribute the width of the grapheme cluster among the number of cursor
+// positions returned by cursor-based TextBreakIterator.
float ShapeResult::RunInfo::XPositionForOffset(
unsigned offset,
AdjustMidCluster adjust_mid_cluster) const {
DCHECK_LE(offset, num_characters_);
const unsigned num_glyphs = glyph_data_.size();
- unsigned glyph_index = 0;
- float position = 0;
- if (Rtl()) {
- while (glyph_index < num_glyphs &&
- glyph_data_[glyph_index].character_index > offset) {
- position += glyph_data_[glyph_index].advance;
- ++glyph_index;
- }
- // If |glyph_index| is at the end, the glyph for |offset| is missing, along
- // with all glyphs before it. We can't adjust position to the start
- // direction.
- if (glyph_index == num_glyphs)
- return position;
- // Adjust offset if it's not on the cluster boundary. In RTL, this means
- // that the adjusted position is the left side of the character.
- if (adjust_mid_cluster == AdjustMidCluster::kToEnd &&
- glyph_data_[glyph_index].character_index < offset) {
- return position;
- }
- // For RTL, we need to return the right side boundary of the character.
- // Add advance of glyphs which are part of the character.
- while (glyph_index < num_glyphs - 1 &&
- glyph_data_[glyph_index].character_index ==
- glyph_data_[glyph_index + 1].character_index) {
- position += glyph_data_[glyph_index].advance;
- ++glyph_index;
+
+ // In this context, a glyph sequence is a sequence of glyphs that shares the
+ // same character_index and therefore represent the same interval of source
+ // characters. glyph_sequence_start marks the character index at the beginning
+ // of the interval of characters for which this glyph sequence was formed as
+ // the result of shaping; glyph_sequence_end marks the end of the interval of
+ // characters for which this glyph sequence was formed. [glyph_sequence_start,
+ // glyph_sequence_end) is inclusive on the start for the range of characters
+ // of the current sequence we are visiting.
+ unsigned glyph_sequence_start = 0;
+ unsigned glyph_sequence_end = num_characters_;
+ // the advance of the current glyph sequence.
+ float glyph_sequence_advance = 0.0;
+ // the accumulated advance up to the current glyph sequence.
+ float accumulated_position = 0;
+
+ if (!Rtl()) {
+ for (unsigned i = 0; i < num_glyphs; ++i) {
+ unsigned current_glyph_char_index = glyph_data_[i].character_index;
+ // If this glyph is still part of the same glyph sequence for the grapheme
+ // cluster at character index glyph_sequence_start, add its advance to the
+ // glyph_sequence's advance.
+ if (glyph_sequence_start == current_glyph_char_index) {
+ glyph_sequence_advance += glyph_data_[i].advance;
+ continue;
+ }
+
+ // We are about to move out of a glyph sequence that contains offset, so
+ // the current glyph sequence is the one we are looking for.
+ if (glyph_sequence_start <= offset && offset < current_glyph_char_index) {
+ glyph_sequence_end = current_glyph_char_index;
+ break;
+ }
+
+ glyph_sequence_start = current_glyph_char_index;
+ // Since we always update glyph_sequence_end when we break, set this to
+ // last_character in case this is the final iteration of the loop.
+ glyph_sequence_end = num_characters_;
+ accumulated_position += glyph_sequence_advance;
+ glyph_sequence_advance = glyph_data_[i].advance;
}
- position += glyph_data_[glyph_index].advance;
+
} else {
- while (glyph_index < num_glyphs &&
- glyph_data_[glyph_index].character_index < offset) {
- position += glyph_data_[glyph_index].advance;
- ++glyph_index;
- }
- // Adjust offset if it's not on the cluster boundary.
- if (adjust_mid_cluster == AdjustMidCluster::kToStart && glyph_index &&
- (glyph_index < num_glyphs ? glyph_data_[glyph_index].character_index
- : num_characters_) > offset) {
- offset = glyph_data_[--glyph_index].character_index;
- for (; glyph_data_[glyph_index].character_index == offset;
- --glyph_index) {
- position -= glyph_data_[glyph_index].advance;
- if (!glyph_index)
- break;
+ glyph_sequence_start = glyph_sequence_end = num_characters_;
+
+ for (unsigned i = 0; i < num_glyphs; ++i) {
+ unsigned current_glyph_char_index = glyph_data_[i].character_index;
+ // If this glyph is still part of the same glyph sequence for the grapheme
+ // cluster at character index glyph_sequence_start, add its advance to the
+ // glyph_sequence's advance.
+ if (glyph_sequence_start == current_glyph_char_index) {
+ glyph_sequence_advance += glyph_data_[i].advance;
+ continue;
}
+
+ // We are about to move out of a glyph sequence that contains offset, so
+ // the current glyph sequence is the one we are looking for.
+ if (glyph_sequence_start <= offset && offset < glyph_sequence_end) {
+ break;
+ }
+
+ glyph_sequence_end = glyph_sequence_start;
+ glyph_sequence_start = current_glyph_char_index;
+ accumulated_position += glyph_sequence_advance;
+ glyph_sequence_advance = glyph_data_[i].advance;
}
}
- return position;
+
+ // This is the character position inside the glyph sequence.
+ unsigned pos = offset - glyph_sequence_start;
+
+ // We calculate the number of Unicode grapheme clusters (actually cursor
+ // position stops) on the subset of characters. We use this to divide
+ // glyph_sequence_advance by the number of unicode grapheme clusters this
+ // glyph sequence was shaped for, and thus linearly interpolate the cursor
+ // position based on accumulated position and a fraction of
+ // glyph_sequence_advance.
+ unsigned graphemes = NumGraphemes(glyph_sequence_start, glyph_sequence_end);
+ if (graphemes > 1) {
+ DCHECK_GE(glyph_sequence_end, glyph_sequence_start);
+ unsigned size = glyph_sequence_end - glyph_sequence_start;
+ unsigned place = graphemes * pos / size;
+ pos -= place;
+ glyph_sequence_advance = glyph_sequence_advance / graphemes;
+ if (Rtl()) {
+ accumulated_position += glyph_sequence_advance * (graphemes - place - 1);
+ } else {
+ accumulated_position += glyph_sequence_advance * place;
+ }
+ }
+
+ // Re-adapt based on adjust_mid_cluster. On LTR, if we want AdjustToEnd and
+ // offset is not at the beginning, we need to jump to the right side of the
+ // grapheme. On RTL, if we want AdjustToStart and offset is not at the end, we
+ // need to jump to the left side of the grapheme.
+ if (!Rtl() && adjust_mid_cluster == AdjustMidCluster::kToEnd && pos != 0) {
+ accumulated_position += glyph_sequence_advance;
+ } else if (Rtl() && adjust_mid_cluster == AdjustMidCluster::kToEnd &&
+ pos != 0) {
+ accumulated_position -= glyph_sequence_advance;
+ }
+
+ if (Rtl()) {
+ // For RTL, we return the right side.
+ accumulated_position += glyph_sequence_advance;
+ }
+
+ return accumulated_position;
}
+// In some ways, CharacterIndexForXPosition is the reverse of
+// XPositionForOffset. Given a target pixel distance on screen space, returns a
+// character index for the end of the interval that would be included within
+// that space. @break_glyphs_option controls wether we use grapheme information
+// to break glyphs into grapheme clusters and return character that are a part
+// of a glyph.
void ShapeResult::RunInfo::CharacterIndexForXPosition(
float target_x,
+ BreakGlyphsOption break_glyphs_option,
GlyphIndexResult* result) const {
DCHECK(target_x >= 0 && target_x <= width_);
const unsigned num_glyphs = glyph_data_.size();
- float current_x = 0;
- unsigned glyph_index = 0;
-
- while (true) {
- unsigned current_character_index = glyph_data_[glyph_index].character_index;
- float current_advance = glyph_data_[glyph_index].advance;
- unsigned next_glyph_index = glyph_index + 1;
- while (next_glyph_index < num_glyphs &&
- current_character_index ==
- glyph_data_[next_glyph_index].character_index)
- current_advance += glyph_data_[next_glyph_index++].advance;
- float next_x = current_x + current_advance;
- if (target_x < next_x || next_glyph_index == num_glyphs) {
- result->glyph_index = glyph_index;
- result->next_glyph_index = next_glyph_index;
- result->character_index = current_character_index;
- result->origin_x = current_x;
- result->advance = current_advance;
- return;
+
+ result->origin_x = 0;
+ unsigned glyph_sequence_start = 0;
+ unsigned glyph_sequence_end = num_characters_;
+ result->advance = 0.0;
+
+ // on RTL, we start on the last index.
+ if (Rtl()) {
+ glyph_sequence_start = glyph_sequence_end = num_characters_;
+ }
+
+ for (unsigned i = 0; i < num_glyphs; ++i) {
+ unsigned current_glyph_char_index = glyph_data_[i].character_index;
+ // If the glyph is part of the same sequence, we just accumulate the
+ // advance.
+ if (glyph_sequence_start == current_glyph_char_index) {
+ result->advance += glyph_data_[i].advance;
+ continue;
}
- current_x = next_x;
- glyph_index = next_glyph_index;
+
+ // Since we are about to move to the next sequence of glyphs, check if
+ // the target falls inside it, if it does, we found our sequence.
+ if (result->origin_x + result->advance > target_x) {
+ if (!Rtl()) {
+ glyph_sequence_end = current_glyph_char_index;
+ }
+ break;
+ }
+
+ // Move to the next sequence, update accumulated_x.
+ if (Rtl()) {
+ // Notice that on RTL, as we move to our next sequence, we already know
+ // both bounds. Nonetheless, we still need to move forward so we can
+ // capture all glyphs of this sequence.
+ glyph_sequence_end = glyph_sequence_start;
+ }
+ glyph_sequence_start = current_glyph_char_index;
+ result->origin_x += result->advance;
+ result->advance = glyph_data_[i].advance;
+ }
+
+ // At this point, we have [glyph_sequence_start, glyph_sequence_end)
+ // representing a sequence of glyphs, of size glyph_sequence_advance. We
+ // linearly interpolate how much space each character takes, and reduce the
+ // sequence to only match the character size.
+ if (break_glyphs_option == BreakGlyphs) {
+ int graphemes = NumGraphemes(glyph_sequence_start, glyph_sequence_end);
+ if (graphemes > 1) {
+ float unit_size = result->advance / graphemes;
+ unsigned step = floor((target_x - result->origin_x) / unit_size);
+ unsigned glyph_length = glyph_sequence_end - glyph_sequence_start;
+ unsigned final_size = floor(glyph_length / graphemes);
+ result->origin_x += unit_size * step;
+ if (!Rtl()) {
+ glyph_sequence_start += step;
+ glyph_sequence_end = glyph_sequence_start + final_size;
+ } else {
+ glyph_sequence_end -= step;
+ glyph_sequence_start = glyph_sequence_end - final_size;
+ }
+ result->advance = unit_size;
+ }
+ }
+
+ if (!Rtl()) {
+ result->left_character_index = glyph_sequence_start;
+ result->right_character_index = glyph_sequence_end;
+ } else {
+ result->left_character_index = glyph_sequence_end;
+ result->right_character_index = glyph_sequence_start;
}
- NOTREACHED();
}
void HarfBuzzRunGlyphData::SetGlyphAndPositions(uint16_t glyph_id,
uint16_t character_index,
float advance,
- const FloatSize& offset) {
+ const FloatSize& offset,
+ bool safe_to_break_before) {
glyph = glyph_id;
+ DCHECK_LE(character_index, kMaxCharacterIndex);
this->character_index = character_index;
this->advance = advance;
this->offset = offset;
+ this->safe_to_break_before = safe_to_break_before;
}
ShapeResult::ShapeResult(const SimpleFontData* font_data,
@@ -298,107 +453,111 @@ unsigned ShapeResult::PreviousSafeToBreakOffset(unsigned index) const {
return StartIndexForResult();
}
-// Returns the offset of the character of |result| for LTR.
-unsigned ShapeResult::OffsetLtr(const GlyphIndexResult& result) const {
- DCHECK(IsLtr(Direction()));
- return result.characters_on_left_runs + result.character_index;
-}
-
-// Returns the offset of the character of |result| for RTL.
-unsigned ShapeResult::OffsetRtl(const GlyphIndexResult& result, float x) const {
- DCHECK(IsRtl(Direction()));
- if (!result.IsInRun())
- return NumCharacters() - result.characters_on_left_runs;
- // In RTL, the boundary belongs to the left character. This subtle difference
- // allows round trips between OffsetForPoint and PointForOffset.
- if (UNLIKELY(x == result.origin_x))
- return OffsetLeftRtl(result);
- return NumCharacters() - result.characters_on_left_runs -
- runs_[result.run_index]->num_characters_ + result.character_index;
-}
-
-// Returns the offset of the character on the right of |result| for LTR.
-unsigned ShapeResult::OffsetRightLtr(const GlyphIndexResult& result) const {
- DCHECK(IsLtr(Direction()));
- if (result.run_index >= runs_.size())
- return NumCharacters();
- const RunInfo& run = *runs_[result.run_index];
- return result.characters_on_left_runs +
- (result.next_glyph_index < run.glyph_data_.size()
- ? run.glyph_data_[result.next_glyph_index].character_index
- : run.num_characters_);
-}
-
-// Returns the offset of the character on the left of |result| for RTL.
-unsigned ShapeResult::OffsetLeftRtl(const GlyphIndexResult& result) const {
- DCHECK(IsRtl(Direction()));
- if (!result.glyph_index)
- return NumCharacters() - result.characters_on_left_runs;
- const RunInfo& run = *runs_[result.run_index];
- return NumCharacters() - result.characters_on_left_runs -
- run.num_characters_ +
- run.glyph_data_[result.glyph_index - 1].character_index;
-}
-
// If the position is outside of the result, returns the start or the end offset
// depends on the position.
void ShapeResult::OffsetForPosition(float target_x,
+ BreakGlyphsOption break_glyphs_option,
GlyphIndexResult* result) const {
- if (target_x <= 0)
+ if (target_x <= 0) {
+ if (Rtl()) {
+ result->left_character_index = result->right_character_index =
+ NumCharacters();
+ }
return;
+ }
- unsigned characters_so_far = 0;
+ unsigned characters_so_far = Rtl() ? NumCharacters() : 0;
float current_x = 0;
+
for (unsigned i = 0; i < runs_.size(); ++i) {
const RunInfo* run = runs_[i].get();
if (!run)
continue;
+ if (Rtl())
+ characters_so_far -= runs_[i]->num_characters_;
float next_x = current_x + run->width_;
float offset_for_run = target_x - current_x;
if (offset_for_run >= 0 && offset_for_run < run->width_) {
// The x value in question is within this script run.
- run->CharacterIndexForXPosition(offset_for_run, result);
+ run->CharacterIndexForXPosition(offset_for_run, break_glyphs_option,
+ result);
result->run_index = i;
result->characters_on_left_runs = characters_so_far;
+ if (Rtl()) {
+ result->left_character_index =
+ characters_so_far + result->left_character_index;
+ result->right_character_index =
+ characters_so_far + result->right_character_index;
+ DCHECK_LE(result->left_character_index, NumCharacters() + 1);
+ DCHECK_LE(result->right_character_index, NumCharacters());
+ } else {
+ result->left_character_index += characters_so_far;
+ result->right_character_index += characters_so_far;
+ DCHECK_LE(result->left_character_index, NumCharacters());
+ DCHECK_LE(result->right_character_index, NumCharacters() + 1);
+ }
result->origin_x += current_x;
- DCHECK_LE(result->characters_on_left_runs + result->character_index,
- NumCharacters());
return;
}
- characters_so_far += run->num_characters_;
+ if (!Rtl())
+ characters_so_far += run->num_characters_;
current_x = next_x;
}
- result->run_index = runs_.size();
+ if (Rtl()) {
+ result->left_character_index = 0;
+ result->right_character_index = 0;
+ } else {
+ result->left_character_index += characters_so_far;
+ result->right_character_index += characters_so_far;
+ }
+
+ result->run_index = runs_.size() - 1;
result->characters_on_left_runs = characters_so_far;
+
+ DCHECK_LE(result->left_character_index, NumCharacters());
+ DCHECK_LE(result->right_character_index, NumCharacters() + 1);
}
-unsigned ShapeResult::OffsetForPosition(float x) const {
+unsigned ShapeResult::OffsetForPosition(
+ float x,
+ BreakGlyphsOption break_glyphs_option) const {
GlyphIndexResult result;
- OffsetForPosition(x, &result);
- return IsLtr(Direction()) ? OffsetLtr(result) : OffsetRtl(result, x);
+ OffsetForPosition(x, break_glyphs_option, &result);
+
+ // For LTR, the offset is always the left one.
+ if (!Rtl())
+ return result.left_character_index;
+
+ // For RTL the offset is the right one, except that the interval is open
+ // on other side. So in case we are exactly at the boundary, we return the
+ // left index.
+ if (x == result.origin_x)
+ return result.left_character_index;
+ return result.right_character_index;
}
-unsigned ShapeResult::OffsetForHitTest(float x) const {
+unsigned ShapeResult::OffsetForHitTest(
+ float x,
+ BreakGlyphsOption break_glyphs_option) const {
GlyphIndexResult result;
- OffsetForPosition(x, &result);
- if (IsLtr(Direction())) {
- if (result.IsInRun() && x > result.origin_x + result.advance / 2)
- return OffsetRightLtr(result);
- return OffsetLtr(result);
- }
- if (result.IsInRun() && x <= result.origin_x + result.advance / 2)
- return OffsetLeftRtl(result);
- return OffsetRtl(result, x);
+ OffsetForPosition(x, break_glyphs_option, &result);
+
+ if (x - result.origin_x <= result.advance / 2)
+ return result.left_character_index;
+ return result.right_character_index;
}
unsigned ShapeResult::OffsetToFit(float x, TextDirection line_direction) const {
GlyphIndexResult result;
- OffsetForPosition(x, &result);
- if (IsLtr(line_direction)) {
- return IsLtr(Direction()) ? OffsetLtr(result) : OffsetLeftRtl(result);
- }
- return IsRtl(Direction()) ? OffsetRtl(result, x) : OffsetRightLtr(result);
+ OffsetForPosition(x, DontBreakGlyphs, &result);
+
+ if (IsLtr(line_direction))
+ return result.left_character_index;
+
+ if (x == result.origin_x && IsRtl(Direction()))
+ return result.left_character_index;
+ return result.right_character_index;
}
float ShapeResult::PositionForOffset(
@@ -656,15 +815,15 @@ template <bool is_horizontal_run>
void ShapeResult::ComputeGlyphPositions(ShapeResult::RunInfo* run,
unsigned start_glyph,
unsigned num_glyphs,
- hb_buffer_t* harf_buzz_buffer) {
+ hb_buffer_t* harfbuzz_buffer) {
DCHECK_EQ(is_horizontal_run, run->IsHorizontal());
const SimpleFontData& current_font_data = *run->font_data_;
const hb_glyph_info_t* glyph_infos =
- hb_buffer_get_glyph_infos(harf_buzz_buffer, nullptr);
+ hb_buffer_get_glyph_infos(harfbuzz_buffer, nullptr);
const hb_glyph_position_t* glyph_positions =
- hb_buffer_get_glyph_positions(harf_buzz_buffer, nullptr);
+ hb_buffer_get_glyph_positions(harfbuzz_buffer, nullptr);
const unsigned start_cluster =
- HB_DIRECTION_IS_FORWARD(hb_buffer_get_direction(harf_buzz_buffer))
+ HB_DIRECTION_IS_FORWARD(hb_buffer_get_direction(harfbuzz_buffer))
? glyph_infos[start_glyph].cluster
: glyph_infos[start_glyph + num_glyphs - 1].cluster;
@@ -675,9 +834,6 @@ void ShapeResult::ComputeGlyphPositions(ShapeResult::RunInfo* run,
GlyphBoundsAccumulator bounds(width_);
bool has_vertical_offsets = !is_horizontal_run;
- // Because we reverse this later, it must be empty at this point.
- DCHECK(run->safe_break_offsets_.IsEmpty());
-
// HarfBuzz returns result in visual order, no need to flip for RTL.
for (unsigned i = 0; i < num_glyphs; ++i) {
uint16_t glyph = glyph_infos[start_glyph + i].codepoint;
@@ -695,18 +851,23 @@ void ShapeResult::ComputeGlyphPositions(ShapeResult::RunInfo* run,
uint16_t character_index =
glyph_infos[start_glyph + i].cluster - start_cluster;
+ if (UNLIKELY(character_index > HarfBuzzRunGlyphData::kMaxCharacterIndex)) {
+ // If the character index exceeds the limit, abort and shrink the run to
+ // what are actually stored.
+ run->num_characters_ = character_index;
+ run->glyph_data_.Shrink(i);
+ break;
+ }
HarfBuzzRunGlyphData& glyph_data = run->glyph_data_[i];
- glyph_data.SetGlyphAndPositions(glyph, character_index, advance, offset);
+ glyph_data.SetGlyphAndPositions(
+ glyph, character_index, advance, offset,
+ IsSafeToBreakBefore(glyph_infos + start_glyph, num_glyphs, i));
total_advance += advance;
has_vertical_offsets |= (offset.Height() != 0);
bounds.Unite<is_horizontal_run>(
glyph_data, current_font_data.BoundsForGlyph(glyph_data.glyph));
bounds.origin += advance;
-
- // Check if it is safe to break without reshaping before the cluster.
- if (IsSafeToBreakBefore(glyph_infos + start_glyph, num_glyphs, i))
- run->safe_break_offsets_.push_back(character_index);
}
run->width_ = std::max(0.0f, total_advance);
@@ -715,15 +876,12 @@ void ShapeResult::ComputeGlyphPositions(ShapeResult::RunInfo* run,
if (!is_horizontal_run)
bounds.ConvertVerticalRunToLogical(current_font_data.GetFontMetrics());
glyph_bounding_box_.Unite(bounds.bounds);
-
- if (UNLIKELY(run->Rtl()))
- run->safe_break_offsets_.Reverse();
}
void ShapeResult::InsertRun(std::unique_ptr<ShapeResult::RunInfo> run_to_insert,
unsigned start_glyph,
unsigned num_glyphs,
- hb_buffer_t* harf_buzz_buffer) {
+ hb_buffer_t* harfbuzz_buffer) {
DCHECK_GT(num_glyphs, 0u);
std::unique_ptr<ShapeResult::RunInfo> run(std::move(run_to_insert));
DCHECK_EQ(num_glyphs, run->glyph_data_.size());
@@ -733,15 +891,15 @@ void ShapeResult::InsertRun(std::unique_ptr<ShapeResult::RunInfo> run_to_insert,
// cases, no adjustments are needed because |glyph_bounding_box_| is in
// logical coordinates and uses alphabetic baseline.
ComputeGlyphPositions<true>(run.get(), start_glyph, num_glyphs,
- harf_buzz_buffer);
+ harfbuzz_buffer);
} else {
// Inserting a vertical run to a vertical result.
ComputeGlyphPositions<false>(run.get(), start_glyph, num_glyphs,
- harf_buzz_buffer);
+ harfbuzz_buffer);
}
width_ += run->width_;
- num_glyphs_ += num_glyphs;
- DCHECK_GE(num_glyphs_, num_glyphs);
+ num_glyphs_ += run->NumGlyphs();
+ DCHECK_GE(num_glyphs_, run->NumGlyphs());
InsertRun(std::move(run));
}
@@ -776,22 +934,33 @@ void ShapeResult::InsertRun(std::unique_ptr<ShapeResult::RunInfo> run) {
// synthesize a run without glyphs.
void ShapeResult::InsertRunForIndex(unsigned start_character_index) {
DCHECK(runs_.IsEmpty());
+ // TODO(fserb): do we need the proper graphemes?
+ Vector<unsigned> graphemes;
runs_.push_back(std::make_unique<RunInfo>(
primary_font_.get(), !Rtl() ? HB_DIRECTION_LTR : HB_DIRECTION_RTL,
CanvasRotationInVertical::kRegular, HB_SCRIPT_UNKNOWN,
- start_character_index, 0, num_characters_));
+ start_character_index, 0, num_characters_, graphemes));
}
ShapeResult::RunInfo* ShapeResult::InsertRunForTesting(
unsigned start_index,
unsigned num_characters,
TextDirection direction,
- Vector<uint16_t> safe_break_offsets) {
+ Vector<uint16_t> safe_break_offsets,
+ Vector<unsigned> graphemes) {
std::unique_ptr<RunInfo> run = std::make_unique<ShapeResult::RunInfo>(
nullptr, IsLtr(direction) ? HB_DIRECTION_LTR : HB_DIRECTION_RTL,
- CanvasRotationInVertical::kRegular, HB_SCRIPT_COMMON, start_index, 0,
- num_characters);
- run->safe_break_offsets_.AppendVector(safe_break_offsets);
+ CanvasRotationInVertical::kRegular, HB_SCRIPT_COMMON, start_index,
+ num_characters, num_characters, std::move(graphemes));
+ unsigned i = 0;
+ for (auto& glyph_data : run->glyph_data_)
+ glyph_data.SetGlyphAndPositions(0, i++, 0, FloatSize(), false);
+ for (uint16_t offset : safe_break_offsets)
+ run->glyph_data_[offset].safe_to_break_before = true;
+ // RTL runs have glyphs in the descending order of character_index.
+ if (Rtl())
+ run->glyph_data_.Reverse();
+ num_glyphs_ += run->NumGlyphs();
RunInfo* run_ptr = run.get();
InsertRun(std::move(run));
return run_ptr;
@@ -832,7 +1001,7 @@ float ShapeResult::LineLeftBounds() const {
const RunInfo& run = *runs_.front();
const bool is_horizontal_run = run.IsHorizontal();
const SimpleFontData& font_data = *run.font_data_;
- DCHECK(!run.glyph_data_.IsEmpty()) << ToString();
+ DCHECK(!run.glyph_data_.IsEmpty()) << *this;
const unsigned character_index = run.glyph_data_.front().character_index;
GlyphBoundsAccumulator bounds(0.f);
for (const auto& glyph : run.glyph_data_) {
@@ -853,12 +1022,10 @@ float ShapeResult::LineRightBounds() const {
const RunInfo& run = *runs_.back();
const bool is_horizontal_run = run.IsHorizontal();
const SimpleFontData& font_data = *run.font_data_;
- DCHECK(!run.glyph_data_.IsEmpty()) << ToString();
+ DCHECK(!run.glyph_data_.IsEmpty()) << *this;
const unsigned character_index = run.glyph_data_.back().character_index;
GlyphBoundsAccumulator bounds(width_);
- for (auto glyph_it = run.glyph_data_.rbegin();
- glyph_it != run.glyph_data_.rend(); ++glyph_it) {
- const auto& glyph = *glyph_it;
+ for (const auto& glyph : base::Reversed(run.glyph_data_)) {
if (character_index != glyph.character_index)
break;
bounds.origin -= glyph.advance;
@@ -986,25 +1153,28 @@ void ShapeResult::CheckConsistency() const {
return;
}
- unsigned index = StartIndexForResult();
+ const unsigned start_index = StartIndexForResult();
+ unsigned index = start_index;
unsigned num_glyphs = 0;
if (!Rtl()) {
for (const auto& run : runs_) {
- DCHECK_EQ(index, run->start_index_);
- index += run->num_characters_;
+ // Characters maybe missing, but must be in increasing order.
+ DCHECK_GE(run->start_index_, index);
+ index = run->start_index_ + run->num_characters_;
num_glyphs += run->glyph_data_.size();
}
} else {
// RTL on Mac may not have runs for the all characters. crbug.com/774034
index = runs_.back()->start_index_;
- for (auto it = runs_.rbegin(); it != runs_.rend(); ++it) {
- const auto& run = *it;
- DCHECK_EQ(index, run->start_index_);
- index += run->num_characters_;
+ for (const auto& run : base::Reversed(runs_)) {
+ DCHECK_GE(run->start_index_, index);
+ index = run->start_index_ + run->num_characters_;
num_glyphs += run->glyph_data_.size();
}
}
- DCHECK_EQ(index, EndIndexForResult());
+ const unsigned end_index = EndIndexForResult();
+ DCHECK_LE(index, end_index);
+ DCHECK_EQ(end_index - start_index, num_characters_);
DCHECK_EQ(num_glyphs, num_glyphs_);
}
#endif
@@ -1017,19 +1187,20 @@ scoped_refptr<ShapeResult> ShapeResult::CreateForTabulationCharacters(
const SimpleFontData* font_data = font->PrimaryFont();
// Tab characters are always LTR or RTL, not TTB, even when
// isVerticalAnyUpright().
+ // We don't pass proper graphemes for tabulation.
+ Vector<unsigned> graphemes;
std::unique_ptr<ShapeResult::RunInfo> run = std::make_unique<RunInfo>(
font_data, text_run.Rtl() ? HB_DIRECTION_RTL : HB_DIRECTION_LTR,
- CanvasRotationInVertical::kRegular, HB_SCRIPT_COMMON, 0, count, count);
+ CanvasRotationInVertical::kRegular, HB_SCRIPT_COMMON, 0, count, count,
+ graphemes);
float position = text_run.XPos() + position_offset;
float start_position = position;
for (unsigned i = 0; i < count; i++) {
float advance = font->TabWidth(font_data, text_run.GetTabSize(), position);
HarfBuzzRunGlyphData& glyph_data = run->glyph_data_[i];
glyph_data.SetGlyphAndPositions(font_data->SpaceGlyph(), i, advance,
- FloatSize());
+ FloatSize(), true);
- // Assume it's safe to break after a tab character.
- run->safe_break_offsets_.push_back(glyph_data.character_index);
position += advance;
}
run->width_ = position - start_position;
@@ -1088,4 +1259,212 @@ String ShapeResult::ToString() const {
return output.ToString();
}
+std::ostream& operator<<(std::ostream& ostream,
+ const ShapeResult& shape_result) {
+ return ostream << shape_result.ToString();
+}
+
+template <bool rtl>
+void ShapeResult::ComputePositionData() const {
+ auto& data = character_position_->data_;
+ unsigned start_offset = StartIndexForResult();
+ unsigned next_character_index;
+ float run_advance;
+
+ if (!rtl) {
+ next_character_index = 0;
+ run_advance = 0;
+ } else {
+ DCHECK_GE(EndIndexForResult(), start_offset + 1);
+ next_character_index = EndIndexForResult() - (start_offset + 1);
+ run_advance = width_;
+ }
+
+ for (const auto& run : runs_) {
+ if (!run)
+ continue;
+
+ float total_advance = run_advance;
+ for (const auto& glyph_data : run->glyph_data_) {
+ DCHECK_GE(run->start_index_ + glyph_data.character_index, start_offset);
+ unsigned character_index =
+ run->start_index_ + glyph_data.character_index - start_offset;
+
+ // Multiple glyphs may have the same character index and not all character
+ // indices may have glyphs.
+ // For character indices without glyps set the x-position to that of the
+ // nearest preceding glyph.
+ if (!rtl) {
+ for (unsigned i = next_character_index; i < character_index; i++) {
+ DCHECK_LT(i, num_characters_);
+ data[i] = {total_advance, false};
+ }
+
+ // TODO(layout-dev): This is a bit of a hack, need to represent next
+ // better for RTL. Perhaps by storing last index instead and subtracting
+ // one here instead.
+ } else if (next_character_index != static_cast<unsigned>(-1)) {
+ for (unsigned i = next_character_index; i > character_index; i--) {
+ DCHECK_LT(i, num_characters_);
+ data[i] = {total_advance, false};
+ }
+ }
+
+ // For glyphs with the same character index the last logical one wins.
+ // This is the last visual one in LTR, no need to do anything speical.
+ // For RTL this is the first visual one so skip subsequent ones with the
+ // same character index.
+ if (rtl && next_character_index + 1 == character_index)
+ continue;
+
+ // For glyphs with the same character index in LTR take the advance from
+ // the last one but the safe to break flag from the first.
+ DCHECK_LT(character_index, num_characters_);
+ bool safe_to_break =
+ next_character_index > character_index
+ ? data[next_character_index - 1].safe_to_break_before
+ : glyph_data.safe_to_break_before;
+ data[character_index] = {total_advance, safe_to_break};
+
+ total_advance += glyph_data.advance;
+ next_character_index = character_index + (!rtl ? 1 : -1);
+ }
+ if (!rtl)
+ run_advance += run->width_;
+ else
+ run_advance -= run->width_;
+ }
+
+ character_position_->start_offset_ = start_offset;
+}
+
+void ShapeResult::EnsurePositionData() const {
+ if (character_position_)
+ return;
+
+ character_position_ =
+ std::make_unique<CharacterPositionData>(num_characters_, width_);
+ if (Direction() == TextDirection::kLtr)
+ ComputePositionData<false>();
+ else
+ ComputePositionData<true>();
+}
+
+unsigned ShapeResult::CachedOffsetForPosition(float x) const {
+ // TODO(layout-dev): Remove once CharacterPositionData::OffsetForPosition
+ // properly supports RTL.
+ if (Rtl())
+ return OffsetForPosition(x, DontBreakGlyphs);
+
+ DCHECK(character_position_);
+ return character_position_->OffsetForPosition(x);
+}
+
+float ShapeResult::CachedPositionForOffset(unsigned offset) const {
+ // TODO(layout-dev): Remove once CharacterPositionData::PositionForOffset
+ // properly supports RTL.
+ if (Rtl())
+ return PositionForOffset(offset);
+
+ DCHECK(character_position_);
+ return character_position_->PositionForOffset(offset);
+}
+
+unsigned ShapeResult::CachedNextSafeToBreakOffset(unsigned offset) const {
+ if (Rtl())
+ return NextSafeToBreakOffset(offset);
+
+ DCHECK(character_position_);
+ return character_position_->NextSafeToBreakOffset(offset);
+}
+
+unsigned ShapeResult::CachedPreviousSafeToBreakOffset(unsigned offset) const {
+ if (Rtl())
+ return PreviousSafeToBreakOffset(offset);
+
+ DCHECK(character_position_);
+ return character_position_->PreviousSafeToBreakOffset(offset);
+}
+
+// TODO(eae): Might be worth trying to set midpoint to ~50% more than the number
+// of characters in the previous line for the first try. Would cut the number
+// of tries in the majority of cases for long strings.
+unsigned ShapeResult::CharacterPositionData::OffsetForPosition(float x) const {
+ // At or before start, return offset *before* the first character.
+ if (x <= 0)
+ return 0;
+
+ // At or beyond the end, return offset *after* the last character.
+ if (x >= width_)
+ return data_.size();
+
+ // Do a binary search to find the largest x-position that is less than or
+ // equal to the supplied x value.
+ unsigned length = data_.size();
+ unsigned low = 0;
+ unsigned high = length - 1;
+ while (low <= high) {
+ unsigned midpoint = low + (high - low) / 2;
+ if (data_[midpoint].x_position <= x &&
+ (midpoint + 1 == length || data_[midpoint + 1].x_position > x)) {
+ return midpoint;
+ }
+ if (x < data_[midpoint].x_position)
+ high = midpoint - 1;
+ else
+ low = midpoint + 1;
+ }
+
+ return 0;
+}
+
+float ShapeResult::CharacterPositionData::PositionForOffset(
+ unsigned offset) const {
+ DCHECK_GT(data_.size(), 0u);
+ if (offset >= data_.size())
+ return width_;
+ return data_[offset].x_position;
+}
+
+unsigned ShapeResult::CharacterPositionData::NextSafeToBreakOffset(
+ unsigned offset) const {
+ DCHECK_LE(start_offset_, offset);
+ unsigned adjusted_offset = offset - start_offset_;
+ DCHECK_LT(adjusted_offset, data_.size());
+
+ // Assume it is always safe to break at the start. While not strictly correct
+ // the text has already been segmented at that offset. This also matches the
+ // non-CharacterPositionData implementation.
+ if (adjusted_offset == 0)
+ return start_offset_;
+
+ unsigned length = data_.size();
+ for (unsigned i = adjusted_offset; i < length; i++) {
+ if (data_[i].safe_to_break_before)
+ return start_offset_ + i;
+ }
+
+ // Next safe break is at the end of the run.
+ return start_offset_ + length;
+}
+
+unsigned ShapeResult::CharacterPositionData::PreviousSafeToBreakOffset(
+ unsigned offset) const {
+ DCHECK_LE(start_offset_, offset);
+ unsigned adjusted_offset = offset - start_offset_;
+ DCHECK_LT(adjusted_offset, data_.size());
+
+ // Assume it is always safe to break at the end of the run.
+ if (adjusted_offset >= data_.size())
+ return start_offset_ + data_.size();
+
+ for (unsigned i = adjusted_offset + 1; i > 0; i--) {
+ if (data_[i - 1].safe_to_break_before)
+ return start_offset_ + (i - 1);
+ }
+
+ // Previous safe break is at the start of the run.
+ return 0;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
index 2505db6c7fd..926faed4e2b 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
@@ -61,6 +61,28 @@ enum class AdjustMidCluster {
kToStart
};
+struct ShapeResultCharacterData {
+ DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
+ float x_position;
+ unsigned safe_to_break_before : 1;
+};
+
+// There are two options for how OffsetForPosition behaves:
+// IncludePartialGlyphs - decides what to do when the position hits more than
+// 50% of the glyph. If enabled, we count that glyph, if disable we don't.
+enum IncludePartialGlyphsOption {
+ OnlyFullGlyphs,
+ IncludePartialGlyphs,
+};
+
+// BreakGlyphs - allows OffsetForPosition to consider graphemes separations
+// inside a glyph. It allows the function to return a point inside a glyph when
+// multiple graphemes share a glyph (for example, in a ligature)
+enum BreakGlyphsOption {
+ DontBreakGlyphs,
+ BreakGlyphs,
+};
+
class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
public:
static scoped_refptr<ShapeResult> Create(const Font* font,
@@ -68,6 +90,9 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
TextDirection direction) {
return base::AdoptRef(new ShapeResult(font, num_characters, direction));
}
+ static scoped_refptr<ShapeResult> Create(const ShapeResult& other) {
+ return base::AdoptRef(new ShapeResult(other));
+ }
static scoped_refptr<ShapeResult> CreateForTabulationCharacters(
const Font*,
const TextRun&,
@@ -109,23 +134,30 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
// break without reshaping.
// The |offset| given and the return value is for the original string, between
// |StartIndexForResult| and |EndIndexForResult|.
+ // TODO(eae): Remove these ones the cached versions are used everywhere.
unsigned NextSafeToBreakOffset(unsigned offset) const;
unsigned PreviousSafeToBreakOffset(unsigned offset) const;
- // Returns the offset whose (origin, origin+advance) contains |x|.
- unsigned OffsetForPosition(float x) const;
+ // Returns the offset, relative to StartIndexForResult, whose (origin,
+ // origin+advance) contains |x|.
+ unsigned OffsetForPosition(float x, BreakGlyphsOption) const;
// Returns the offset whose glyph boundary is nearest to |x|. Depends on
// whether |x| is on the left-half or the right-half of the glyph, it
// determines the left-boundary or the right-boundary, then computes the
// offset from the bidi direction.
- unsigned OffsetForHitTest(float x) const;
+ unsigned OffsetForHitTest(float x, BreakGlyphsOption) const;
// Returns the offset that can fit to between |x| and the left or the right
// edge. The side of the edge is determined by |line_direction|.
unsigned OffsetToFit(float x, TextDirection line_direction) const;
- unsigned OffsetForPosition(float x, bool include_partial_glyphs) const {
- return !include_partial_glyphs ? OffsetForPosition(x) : OffsetForHitTest(x);
+ unsigned OffsetForPosition(float x,
+ IncludePartialGlyphsOption include_partial_glyphs,
+ BreakGlyphsOption break_glyphs_option) const {
+ return include_partial_glyphs == OnlyFullGlyphs
+ ? OffsetForPosition(x, break_glyphs_option)
+ : OffsetForHitTest(x, break_glyphs_option);
}
+ // Returns the position for a given offset, relative to StartIndexForResult.
float PositionForOffset(unsigned offset,
AdjustMidCluster = AdjustMidCluster::kToEnd) const;
LayoutUnit SnappedStartPositionForOffset(unsigned offset) const {
@@ -135,6 +167,23 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
return LayoutUnit::FromFloatCeil(PositionForOffset(offset));
}
+ // Computes and caches a position data object as needed.
+ void EnsurePositionData() const;
+
+ // Fast versions of OffsetForPosition and PositionForOffset that operates on
+ // a cache (that needs to be pre-computed using EnsurePositionData) and that
+ // does not take partial glyphs into account.
+ unsigned CachedOffsetForPosition(float x) const;
+ float CachedPositionForOffset(unsigned offset) const;
+
+ // Returns the next or previous offsets respectively at which it is safe to
+ // break without reshaping. Operates on a cache (that needs to be pre-computed
+ // using EnsurePositionData) and does not take partial glyphs into account.
+ // The |offset| given and the return value is for the original string, between
+ // |StartIndexForResult| and |EndIndexForResult|.
+ unsigned CachedNextSafeToBreakOffset(unsigned offset) const;
+ unsigned CachedPreviousSafeToBreakOffset(unsigned offset) const;
+
// Apply spacings (letter-spacing, word-spacing, and justification) as
// configured to |ShapeResultSpacing|.
// |text_start_offset| adjusts the character index in the ShapeResult before
@@ -168,7 +217,8 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
RunInfo* InsertRunForTesting(unsigned start_index,
unsigned num_characters,
TextDirection,
- Vector<uint16_t> safe_break_offsets = {});
+ Vector<uint16_t> safe_break_offsets = {},
+ Vector<unsigned> graphemes = {});
#if DCHECK_IS_ON()
void CheckConsistency() const;
#endif
@@ -184,9 +234,6 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
return base::AdoptRef(
new ShapeResult(font_data, num_characters, direction));
}
- static scoped_refptr<ShapeResult> Create(const ShapeResult& other) {
- return base::AdoptRef(new ShapeResult(other));
- }
struct GlyphIndexResult {
STACK_ALLOCATED();
@@ -194,26 +241,55 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
unsigned run_index = 0;
// The total number of characters of runs_[0..run_index - 1].
unsigned characters_on_left_runs = 0;
- unsigned character_index = 0;
- unsigned glyph_index = 0;
- // |next_glyph_index| may not be |glyph_index| + 1 when a cluster is of
- // multiple glyphs; i.e., ligatures or combining glyphs.
- unsigned next_glyph_index = 0;
+
+ // Those are the left and right character indexes of the group of glyphs
+ // that were selected by OffsetForPosition.
+ unsigned left_character_index = 0;
+ unsigned right_character_index = 0;
+
// The glyph origin of the glyph.
float origin_x = 0;
// The advance of the glyph.
float advance = 0;
-
- // True if the position was found on a run. False otherwise.
- bool IsInRun() const { return next_glyph_index; }
};
- unsigned OffsetLtr(const GlyphIndexResult&) const;
- unsigned OffsetRtl(const GlyphIndexResult&, float x) const;
- unsigned OffsetRightLtr(const GlyphIndexResult&) const;
- unsigned OffsetLeftRtl(const GlyphIndexResult&) const;
+ void OffsetForPosition(float target_x,
+ BreakGlyphsOption,
+ GlyphIndexResult*) const;
+
+ // Helper class storing a map between offsets and x-positions.
+ // Unlike the RunInfo and GlyphData structures in ShapeResult, which operates
+ // in glyph order, this class stores a map between character index and the
+ // total accumulated advance for each character. Allowing constant time
+ // mapping from character index to x-position and O(log n) time, using binary
+ // search, from x-position to character index.
+ class CharacterPositionData {
+ public:
+ CharacterPositionData(unsigned num_characters, float width)
+ : data_(num_characters), width_(width) {}
+
+ // Returns the next or previous offsets respectively at which it is safe to
+ // break without reshaping.
+ unsigned NextSafeToBreakOffset(unsigned offset) const;
+ unsigned PreviousSafeToBreakOffset(unsigned offset) const;
+
+ // Returns the offset of the last character that fully fits before the given
+ // x-position.
+ unsigned OffsetForPosition(float x) const;
+
+ // Returns the x-position for a given offset.
+ float PositionForOffset(unsigned offset) const;
+
+ private:
+ Vector<ShapeResultCharacterData> data_;
+ unsigned start_offset_;
+ float width_;
+
+ friend class ShapeResult;
+ };
- void OffsetForPosition(float target_x, GlyphIndexResult*) const;
+ template <bool>
+ void ComputePositionData() const;
template <typename TextContainerType>
void ApplySpacingImpl(ShapeResultSpacing<TextContainerType>&,
@@ -238,6 +314,7 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
FloatRect glyph_bounding_box_;
Vector<std::unique_ptr<RunInfo>> runs_;
scoped_refptr<const SimpleFontData> primary_font_;
+ mutable std::unique_ptr<CharacterPositionData> character_position_;
unsigned num_characters_;
unsigned num_glyphs_ : 30;
@@ -255,6 +332,8 @@ class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
friend class ShapeResultBloberizer;
};
+PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, const ShapeResult&);
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPE_RESULT_H_
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc
index 23511eaa6c2..1800d807bdc 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h"
#include "third_party/blink/renderer/platform/fonts/character_range.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h"
#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
@@ -27,6 +28,13 @@ CharacterRange ShapeResultBuffer::GetCharacterRange(
return GetCharacterRangeInternal(results, direction, total_width, from, to);
}
+CharacterRange ShapeResultBuffer::GetCharacterRange(float total_width,
+ TextDirection direction,
+ unsigned from,
+ unsigned to) const {
+ return GetCharacterRangeInternal(results_, direction, total_width, from, to);
+}
+
CharacterRange ShapeResultBuffer::GetCharacterRangeInternal(
const Vector<scoped_refptr<const ShapeResult>, 64>& results,
TextDirection direction,
@@ -123,13 +131,6 @@ CharacterRange ShapeResultBuffer::GetCharacterRangeInternal(
return CharacterRange(to_x, from_x, -min_y, max_y);
}
-CharacterRange ShapeResultBuffer::GetCharacterRange(TextDirection direction,
- float total_width,
- unsigned from,
- unsigned to) const {
- return GetCharacterRangeInternal(results_, direction, total_width, from, to);
-}
-
void ShapeResultBuffer::AddRunInfoRanges(const ShapeResult::RunInfo& run_info,
float offset,
Vector<CharacterRange>& ranges) {
@@ -172,9 +173,11 @@ Vector<CharacterRange> ShapeResultBuffer::IndividualCharacterRanges(
return ranges;
}
-int ShapeResultBuffer::OffsetForPosition(const TextRun& run,
- float target_x,
- bool include_partial_glyphs) const {
+int ShapeResultBuffer::OffsetForPosition(
+ const TextRun& run,
+ float target_x,
+ IncludePartialGlyphsOption partial_glyphs,
+ BreakGlyphsOption break_glyphs) const {
unsigned total_offset;
if (run.Rtl()) {
total_offset = run.length();
@@ -184,8 +187,8 @@ int ShapeResultBuffer::OffsetForPosition(const TextRun& run,
continue;
total_offset -= word_result->NumCharacters();
if (target_x >= 0 && target_x <= word_result->Width()) {
- int offset_for_word =
- word_result->OffsetForPosition(target_x, include_partial_glyphs);
+ int offset_for_word = word_result->OffsetForPosition(
+ target_x, partial_glyphs, break_glyphs);
return total_offset + offset_for_word;
}
target_x -= word_result->Width();
@@ -195,8 +198,8 @@ int ShapeResultBuffer::OffsetForPosition(const TextRun& run,
for (const auto& word_result : results_) {
if (!word_result)
continue;
- int offset_for_word =
- word_result->OffsetForPosition(target_x, include_partial_glyphs);
+ int offset_for_word = word_result->OffsetForPosition(
+ target_x, partial_glyphs, break_glyphs);
DCHECK_GE(offset_for_word, 0);
total_offset += offset_for_word;
if (target_x >= 0 && target_x <= word_result->Width())
@@ -207,6 +210,20 @@ int ShapeResultBuffer::OffsetForPosition(const TextRun& run,
return total_offset;
}
+void ShapeResultBuffer::ExpandRangeToIncludePartialGlyphs(int* from,
+ int* to) const {
+ int offset = 0;
+ for (unsigned j = 0; j < results_.size(); j++) {
+ const scoped_refptr<const ShapeResult> result = results_[j];
+ for (unsigned i = 0; i < result->runs_.size(); i++) {
+ if (!result->runs_[i])
+ continue;
+ result->runs_[i]->ExpandRangeToIncludePartialGlyphs(offset, from, to);
+ offset += result->runs_[i]->num_characters_;
+ }
+ }
+}
+
Vector<ShapeResult::RunFontData> ShapeResultBuffer::GetRunFontData() const {
Vector<ShapeResult::RunFontData> font_data;
for (const auto& result : results_)
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h
index af1b66e9703..ace7dcd7b48 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h
@@ -33,11 +33,12 @@ class PLATFORM_EXPORT ShapeResultBuffer {
bool HasVerticalOffsets() const { return has_vertical_offsets_; }
- int OffsetForPosition(const TextRun&,
+ int OffsetForPosition(const TextRun& run,
float target_x,
- bool include_partial_glyphs) const;
- CharacterRange GetCharacterRange(TextDirection,
- float total_width,
+ IncludePartialGlyphsOption,
+ BreakGlyphsOption) const;
+ CharacterRange GetCharacterRange(float total_width,
+ TextDirection,
unsigned from,
unsigned to) const;
Vector<CharacterRange> IndividualCharacterRanges(TextDirection,
@@ -53,6 +54,8 @@ class PLATFORM_EXPORT ShapeResultBuffer {
GlyphData EmphasisMarkGlyphData(const FontDescription&) const;
+ void ExpandRangeToIncludePartialGlyphs(int* from, int* to) const;
+
private:
friend class ShapeResultBloberizer;
static CharacterRange GetCharacterRangeInternal(
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h
index 38a9178c6e1..3609c766682 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h
@@ -37,22 +37,30 @@
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
class SimpleFontData;
+// This struct should be TriviallyCopyable so that std::copy() is equivalent to
+// memcpy.
struct HarfBuzzRunGlyphData {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
+
+ static constexpr unsigned kMaxCharacterIndex = (1 << 15) - 1;
+
uint16_t glyph;
- uint16_t character_index;
+ unsigned character_index : 15;
+ unsigned safe_to_break_before : 1;
float advance;
FloatSize offset;
void SetGlyphAndPositions(uint16_t glyph_id,
uint16_t character_index,
float advance,
- const FloatSize& offset);
+ const FloatSize& offset,
+ bool safe_to_break_before);
};
struct ShapeResult::RunInfo {
@@ -65,12 +73,14 @@ struct ShapeResult::RunInfo {
hb_script_t script,
unsigned start_index,
unsigned num_glyphs,
- unsigned num_characters)
+ unsigned num_characters,
+ Vector<unsigned> graphemes)
: font_data_(const_cast<SimpleFontData*>(font)),
direction_(dir),
canvas_rotation_(canvas_rotation),
script_(script),
glyph_data_(num_glyphs),
+ graphemes_(graphemes),
start_index_(start_index),
num_characters_(num_characters),
width_(0.0f) {}
@@ -81,10 +91,12 @@ struct ShapeResult::RunInfo {
canvas_rotation_(other.canvas_rotation_),
script_(other.script_),
glyph_data_(other.glyph_data_),
+ graphemes_(other.graphemes_),
start_index_(other.start_index_),
num_characters_(other.num_characters_),
width_(other.width_) {}
+ unsigned NumGlyphs() const { return glyph_data_.size(); }
bool Rtl() const { return HB_DIRECTION_IS_BACKWARD(direction_); }
bool IsHorizontal() const { return HB_DIRECTION_IS_HORIZONTAL(direction_); }
CanvasRotationInVertical CanvasRotation() const { return canvas_rotation_; }
@@ -92,66 +104,100 @@ struct ShapeResult::RunInfo {
unsigned PreviousSafeToBreakOffset(unsigned) const;
float XPositionForVisualOffset(unsigned, AdjustMidCluster) const;
float XPositionForOffset(unsigned, AdjustMidCluster) const;
- void CharacterIndexForXPosition(float, GlyphIndexResult*) const;
+ void CharacterIndexForXPosition(float,
+ BreakGlyphsOption,
+ GlyphIndexResult*) const;
+ void SetGlyphAndPositions(unsigned index,
+ uint16_t glyph_id,
+ float advance,
+ float offset_x,
+ float offset_y);
size_t GlyphToCharacterIndex(size_t i) const {
return start_index_ + glyph_data_[i].character_index;
}
+ unsigned NumGraphemes(unsigned start, unsigned end) const;
+
// For memory reporting.
size_t ByteSize() const {
return sizeof(this) + glyph_data_.size() * sizeof(HarfBuzzRunGlyphData);
}
+ // Represents a range of HarfBuzzRunGlyphData. |begin| and |end| follow the
+ // iterator pattern; i.e., |begin| is lower or equal to |end| in the address
+ // space regardless of LTR/RTL. |begin| is inclusive, |end| is exclusive.
+ struct GlyphDataRange {
+ HarfBuzzRunGlyphData* begin;
+ HarfBuzzRunGlyphData* end;
+ };
+
+ // Find the range of HarfBuzzRunGlyphData for the specified character index
+ // range. This function uses binary search twice, hence O(2 log n).
+ GlyphDataRange FindGlyphDataRange(unsigned start_character_index,
+ unsigned end_character_index) {
+ const auto comparer = [](const HarfBuzzRunGlyphData& glyph_data,
+ unsigned index) {
+ return glyph_data.character_index < index;
+ };
+ if (!Rtl()) {
+ HarfBuzzRunGlyphData* start_glyph =
+ std::lower_bound(glyph_data_.begin(), glyph_data_.end(),
+ start_character_index, comparer);
+ if (UNLIKELY(start_glyph == glyph_data_.end()))
+ return {nullptr, nullptr};
+ HarfBuzzRunGlyphData* end_glyph = std::lower_bound(
+ start_glyph, glyph_data_.end(), end_character_index, comparer);
+ return {start_glyph, end_glyph};
+ }
+
+ // RTL needs to use reverse iterators because there maybe multiple glyphs
+ // for a character, and we want to find the first one in the logical order.
+ auto start_glyph =
+ std::lower_bound(glyph_data_.rbegin(), glyph_data_.rend(),
+ start_character_index, comparer);
+ if (UNLIKELY(start_glyph == glyph_data_.rend()))
+ return {nullptr, nullptr};
+ auto end_glyph = std::lower_bound(start_glyph, glyph_data_.rend(),
+ end_character_index, comparer);
+ // Convert reverse iterators to pointers. Then increment to make |begin|
+ // inclusive and |end| exclusive.
+ return {&*end_glyph + 1, &*start_glyph + 1};
+ }
+
// Creates a new RunInfo instance representing a subset of the current run.
std::unique_ptr<RunInfo> CreateSubRun(unsigned start, unsigned end) {
DCHECK(end > start);
unsigned number_of_characters = std::min(end - start, num_characters_);
+ auto glyphs = FindGlyphDataRange(start, end);
+ unsigned number_of_glyphs = std::distance(glyphs.begin, glyphs.end);
- // This ends up looping over the glyphs twice if we don't know the glyph
- // count up front. Once to count the number of glyphs and allocate the new
- // RunInfo object and then a second time to copy the glyphs over.
- // TODO: Compared to the cost of allocation and copying the extra loop is
- // probably fine but we might want to try to eliminate it if we can.
- unsigned number_of_glyphs;
- if (start == 0 && end == num_characters_) {
- number_of_glyphs = glyph_data_.size();
- } else {
- number_of_glyphs = 0;
- ForEachGlyphInRange(
- 0, start_index_ + start, start_index_ + end, 0,
- [&](const HarfBuzzRunGlyphData&, float, uint16_t) -> bool {
- number_of_glyphs++;
- return true;
- });
+ Vector<unsigned> sub_graphemes;
+ if (graphemes_.size()) {
+ sub_graphemes.resize(number_of_characters);
+ for (unsigned i = 0; i < number_of_characters; ++i) {
+ sub_graphemes[i] = graphemes_[start + i];
+ }
}
auto run = std::make_unique<RunInfo>(
font_data_.get(), direction_, canvas_rotation_, script_,
- start_index_ + start, number_of_glyphs, number_of_characters);
+ start_index_ + start, number_of_glyphs, number_of_characters,
+ std::move(sub_graphemes));
+
+ static_assert(base::is_trivially_copyable<HarfBuzzRunGlyphData>::value,
+ "HarfBuzzRunGlyphData should be trivially copyable");
+ std::copy(glyphs.begin, glyphs.end, run->glyph_data_.begin());
- unsigned sub_glyph_index = 0;
float total_advance = 0;
- ForEachGlyphInRange(
- 0, start_index_ + start, start_index_ + end, 0,
- [&](const HarfBuzzRunGlyphData& glyph_data, float, uint16_t) -> bool {
- HarfBuzzRunGlyphData& sub_glyph = run->glyph_data_[sub_glyph_index++];
- sub_glyph.glyph = glyph_data.glyph;
- sub_glyph.character_index = glyph_data.character_index - start;
- sub_glyph.advance = glyph_data.advance;
- sub_glyph.offset = glyph_data.offset;
- total_advance += glyph_data.advance;
- return true;
- });
+ for (HarfBuzzRunGlyphData& glyph_data : run->glyph_data_) {
+ glyph_data.character_index -= start;
+ total_advance += glyph_data.advance;
+ }
run->width_ = total_advance;
run->num_characters_ = number_of_characters;
- for (unsigned i = 0; i < safe_break_offsets_.size(); i++) {
- if (safe_break_offsets_[i] >= start && safe_break_offsets_[i] <= end)
- run->safe_break_offsets_.push_back(safe_break_offsets_[i] - start);
- }
-
return run;
}
@@ -189,7 +235,7 @@ struct ShapeResult::RunInfo {
initial_advance,
[&](const HarfBuzzRunGlyphData& glyph_data,
float total_advance) -> bool {
- const uint16_t character_index =
+ const unsigned character_index =
start_index_ + glyph_data.character_index + index_offset;
if (character_index < from) {
@@ -209,6 +255,36 @@ struct ShapeResult::RunInfo {
});
}
+ void ExpandRangeToIncludePartialGlyphs(int offset, int* from, int* to) const {
+ int start = !Rtl() ? offset : (offset + num_characters_);
+ int end = offset + num_characters_;
+
+ for (unsigned i = 0; i < glyph_data_.size(); ++i) {
+ int index = offset + glyph_data_[i].character_index;
+ if (start == index)
+ continue;
+
+ if (!Rtl())
+ end = index;
+
+ if (end > *from && start < *to) {
+ *from = std::min(*from, start);
+ *to = std::max(*to, end);
+ }
+
+ if (!Rtl())
+ end = num_characters_;
+ else
+ end = start;
+ start = index;
+ }
+
+ if (end > *from && start < *to) {
+ *from = std::min(*from, start);
+ *to = std::max(*to, end);
+ }
+ }
+
scoped_refptr<SimpleFontData> font_data_;
hb_direction_t direction_;
// For upright-in-vertical we need to tell the ShapeResultBloberizer to rotate
@@ -216,9 +292,11 @@ struct ShapeResult::RunInfo {
CanvasRotationInVertical canvas_rotation_;
hb_script_t script_;
Vector<HarfBuzzRunGlyphData> glyph_data_;
- // List of character indecies before which it's safe to break without
- // reshaping.
- Vector<uint16_t> safe_break_offsets_;
+
+ // graphemes_[i] is the number of graphemes up to (and including) the ith
+ // character in the run.
+ Vector<unsigned> graphemes_;
+
unsigned start_index_;
unsigned num_characters_;
float width_;
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_test_info.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_test_info.cc
index a0bef42a0bf..29dfd4406b8 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_test_info.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_test_info.cc
@@ -13,6 +13,11 @@ unsigned ShapeResultTestInfo::NumberOfRunsForTesting() const {
return runs_.size();
}
+ShapeResult::RunInfo& ShapeResultTestInfo::RunInfoForTesting(
+ unsigned run_index) const {
+ return *runs_[run_index];
+}
+
bool ShapeResultTestInfo::RunInfoForTesting(unsigned run_index,
unsigned& start_index,
unsigned& num_characters,
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_test_info.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_test_info.h
index 4ac24e0755d..f659681dec1 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_test_info.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shape_result_test_info.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPE_RESULT_TEST_INFO_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPE_RESULT_TEST_INFO_H_
-#include "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h"
#include <hb.h>
@@ -15,6 +15,7 @@ namespace blink {
class PLATFORM_EXPORT ShapeResultTestInfo : public ShapeResult {
public:
unsigned NumberOfRunsForTesting() const;
+ ShapeResult::RunInfo& RunInfoForTesting(unsigned run_index) const;
bool RunInfoForTesting(unsigned run_index,
unsigned& start_index,
unsigned& num_glyphs,
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc
index 6454534bcc3..a7cd5af2461 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.cc
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h"
#include "third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h"
@@ -16,13 +16,15 @@ namespace blink {
ShapingLineBreaker::ShapingLineBreaker(
const HarfBuzzShaper* shaper,
const Font* font,
- const ShapeResult* result,
+ scoped_refptr<const ShapeResult> result,
const LazyLineBreakIterator* break_iterator,
+ const RunSegmenter::RunSegmenterRange* pre_segmented,
ShapeResultSpacing<String>* spacing,
const Hyphenation* hyphenation)
: shaper_(shaper),
font_(font),
result_(result),
+ pre_segmented_(pre_segmented),
break_iterator_(break_iterator),
spacing_(spacing),
hyphenation_(hyphenation),
@@ -30,6 +32,11 @@ ShapingLineBreaker::ShapingLineBreaker(
// ShapeResultSpacing is stateful when it has expansions. We may use it in
// arbitrary order that it cannot have expansions.
DCHECK(!spacing_ || !spacing_->HasExpansion());
+
+ // Line breaking performance relies on high-performance x-position to
+ // character offset lookup. Ensure that the desired cache has been computed.
+ DCHECK(result_);
+ result_->EnsurePositionData();
}
namespace {
@@ -103,16 +110,15 @@ unsigned ShapingLineBreaker::Hyphenate(unsigned offset,
}
}
-unsigned ShapingLineBreaker::Hyphenate(unsigned offset,
- unsigned start,
- bool backwards,
- bool* is_hyphenated) const {
- DCHECK(is_hyphenated && !*is_hyphenated);
+ShapingLineBreaker::BreakOpportunity ShapingLineBreaker::Hyphenate(
+ unsigned offset,
+ unsigned start,
+ bool backwards) const {
const String& text = GetText();
unsigned word_end = break_iterator_->NextBreakOpportunity(offset);
if (word_end == offset) {
DCHECK_EQ(offset, break_iterator_->PreviousBreakOpportunity(offset, start));
- return word_end;
+ return {word_end, false};
}
unsigned previous_break_opportunity =
break_iterator_->PreviousBreakOpportunity(offset, start);
@@ -125,61 +131,57 @@ unsigned ShapingLineBreaker::Hyphenate(unsigned offset,
if (offset >= word_start &&
ShouldHyphenate(text, previous_break_opportunity, word_end)) {
unsigned prefix_length = Hyphenate(offset, word_start, word_end, backwards);
- if (prefix_length) {
- *is_hyphenated = true;
- return word_start + prefix_length;
- }
+ if (prefix_length)
+ return {word_start + prefix_length, true};
}
- return backwards ? previous_break_opportunity : word_end;
+ return {backwards ? previous_break_opportunity : word_end, false};
}
-unsigned ShapingLineBreaker::PreviousBreakOpportunity(
- unsigned offset,
- unsigned start,
- bool* is_hyphenated) const {
- DCHECK(is_hyphenated && !*is_hyphenated);
+ShapingLineBreaker::BreakOpportunity
+ShapingLineBreaker::PreviousBreakOpportunity(unsigned offset,
+ unsigned start) const {
if (UNLIKELY(!IsSoftHyphenEnabled())) {
const String& text = GetText();
for (;; offset--) {
offset = break_iterator_->PreviousBreakOpportunity(offset, start);
if (offset <= start || offset >= text.length() ||
text[offset - 1] != kSoftHyphenCharacter)
- return offset;
+ return {offset, false};
}
}
if (UNLIKELY(hyphenation_))
- return Hyphenate(offset, start, true, is_hyphenated);
+ return Hyphenate(offset, start, true);
- return break_iterator_->PreviousBreakOpportunity(offset, start);
+ return {break_iterator_->PreviousBreakOpportunity(offset, start), false};
}
-unsigned ShapingLineBreaker::NextBreakOpportunity(unsigned offset,
- unsigned start,
- bool* is_hyphenated) const {
- DCHECK(is_hyphenated && !*is_hyphenated);
+ShapingLineBreaker::BreakOpportunity ShapingLineBreaker::NextBreakOpportunity(
+ unsigned offset,
+ unsigned start) const {
if (UNLIKELY(!IsSoftHyphenEnabled())) {
const String& text = GetText();
for (;; offset++) {
offset = break_iterator_->NextBreakOpportunity(offset);
if (offset >= text.length() || text[offset - 1] != kSoftHyphenCharacter)
- return offset;
+ return {offset, false};
}
}
if (UNLIKELY(hyphenation_))
- return Hyphenate(offset, start, false, is_hyphenated);
+ return Hyphenate(offset, start, false);
- return break_iterator_->NextBreakOpportunity(offset);
+ return {break_iterator_->NextBreakOpportunity(offset), false};
}
inline scoped_refptr<ShapeResult> ShapingLineBreaker::Shape(TextDirection direction,
unsigned start,
unsigned end) {
if (!spacing_ || !spacing_->HasSpacing())
- return shaper_->Shape(font_, direction, start, end);
+ return shaper_->Shape(font_, direction, start, end, pre_segmented_);
- scoped_refptr<ShapeResult> result = shaper_->Shape(font_, direction, start, end);
+ scoped_refptr<ShapeResult> result =
+ shaper_->Shape(font_, direction, start, end, pre_segmented_);
result->ApplySpacing(*spacing_);
return result;
}
@@ -213,10 +215,10 @@ inline scoped_refptr<ShapeResult> ShapingLineBreaker::Shape(TextDirection direct
// If we further assume that the font kerns with space then even though it's a
// valid break opportunity reshaping is required as the combined width of the
// two segments "Line " and "breaking" may be different from "Line breaking".
-scoped_refptr<ShapeResult> ShapingLineBreaker::ShapeLine(
+scoped_refptr<const ShapeResult> ShapingLineBreaker::ShapeLine(
unsigned start,
LayoutUnit available_space,
- bool start_should_be_safe,
+ unsigned options,
ShapingLineBreaker::Result* result_out) {
DCHECK_GE(available_space, LayoutUnit(0));
unsigned range_start = result_->StartIndexForResult();
@@ -227,7 +229,8 @@ scoped_refptr<ShapeResult> ShapingLineBreaker::ShapeLine(
const String& text = GetText();
// The start position in the original shape results.
- float start_position_float = result_->PositionForOffset(start - range_start);
+ float start_position_float =
+ result_->CachedPositionForOffset(start - range_start);
TextDirection direction = result_->Direction();
LayoutUnit start_position = SnapStart(start_position_float, direction);
@@ -238,103 +241,115 @@ scoped_refptr<ShapeResult> ShapingLineBreaker::ShapeLine(
FlipRtl(available_space, direction);
DCHECK_GE(FlipRtl(end_position - start_position, direction), LayoutUnit(0));
unsigned candidate_break =
- result_->OffsetForPosition(end_position, false) + range_start;
+ result_->CachedOffsetForPosition(end_position) + range_start;
- unsigned first_safe =
- start_should_be_safe ? result_->NextSafeToBreakOffset(start) : start;
+ unsigned first_safe = (options & kDontReshapeStart)
+ ? start
+ : result_->CachedNextSafeToBreakOffset(start);
DCHECK_GE(first_safe, start);
if (candidate_break >= range_end) {
// The |result_| does not have glyphs to fill the available space,
// and thus unable to compute. Return the result up to range_end.
DCHECK_EQ(candidate_break, range_end);
result_out->break_offset = range_end;
- return ShapeToEnd(start, first_safe, range_end);
+ return ShapeToEnd(start, first_safe, range_start, range_end);
}
// candidate_break should be >= start, but rounding errors can chime in when
// comparing floats. See ShapeLineZeroAvailableWidth on Linux/Mac.
candidate_break = std::max(candidate_break, start);
- unsigned break_opportunity = PreviousBreakOpportunity(
- candidate_break, start, &result_out->is_hyphenated);
- if (break_opportunity <= start) {
+ // If there are no break opportunity before candidate_break, overflow.
+ // Find the next break opportunity after the candidate_break.
+ BreakOpportunity break_opportunity =
+ PreviousBreakOpportunity(candidate_break, start);
+ bool is_overflow = break_opportunity.offset <= start;
+ if (is_overflow) {
+ if (options & kNoResultIfOverflow)
+ return nullptr;
break_opportunity =
- NextBreakOpportunity(std::max(candidate_break, start + 1), start,
- &result_out->is_hyphenated);
+ NextBreakOpportunity(std::max(candidate_break, start + 1), start);
// |range_end| may not be a break opportunity, but this function cannot
// measure beyond it.
- if (break_opportunity >= range_end) {
+ if (break_opportunity.offset >= range_end) {
result_out->break_offset = range_end;
- return ShapeToEnd(start, first_safe, range_end);
+ return ShapeToEnd(start, first_safe, range_start, range_end);
}
}
- DCHECK_GT(break_opportunity, start);
+ DCHECK_GT(break_opportunity.offset, start);
// If the start offset is not at a safe-to-break boundary the content between
// the start and the next safe-to-break boundary needs to be reshaped and the
// available space adjusted to take the reshaping into account.
- scoped_refptr<ShapeResult> line_start_result;
+ scoped_refptr<const ShapeResult> line_start_result;
if (first_safe != start) {
- if (first_safe >= break_opportunity) {
+ if (first_safe >= break_opportunity.offset) {
// There is no safe-to-break, reshape the whole range.
- result_out->break_offset = break_opportunity;
- return Shape(direction, start, break_opportunity);
+ result_out->break_offset = break_opportunity.offset;
+ return Shape(direction, start, break_opportunity.offset);
}
- LayoutUnit original_width =
- FlipRtl(SnapEnd(result_->PositionForOffset(first_safe - range_start),
- direction) -
- start_position,
- direction);
+ LayoutUnit original_width = FlipRtl(
+ SnapEnd(result_->CachedPositionForOffset(first_safe - range_start),
+ direction) -
+ start_position,
+ direction);
line_start_result = Shape(direction, start, first_safe);
available_space += line_start_result->SnappedWidth() - original_width;
}
+ DCHECK_GE(first_safe, start);
+ DCHECK_LE(first_safe, break_opportunity.offset);
- scoped_refptr<ShapeResult> line_end_result;
- unsigned last_safe = break_opportunity;
- while (break_opportunity > start) {
+ scoped_refptr<const ShapeResult> line_end_result;
+ unsigned last_safe = break_opportunity.offset;
+ if (break_opportunity.offset > start) {
// If the previous valid break opportunity is not at a safe-to-break
// boundary reshape between the safe-to-break offset and the valid break
// offset. If the resulting width exceeds the available space the
// preceding boundary is tried until the available space is sufficient.
- unsigned previous_safe =
- std::max(result_->PreviousSafeToBreakOffset(break_opportunity), start);
- DCHECK_LE(previous_safe, break_opportunity);
- if (previous_safe != break_opportunity) {
- LayoutUnit safe_position = SnapStart(
- result_->PositionForOffset(previous_safe - range_start), direction);
- while (break_opportunity > previous_safe && previous_safe >= start) {
- DCHECK_LE(break_opportunity, range_end);
- line_end_result = Shape(direction, previous_safe, break_opportunity);
- if (line_end_result->SnappedWidth() <=
- FlipRtl(end_position - safe_position, direction))
- break;
- // Doesn't fit after the reshape. Try previous break opportunity, or
- // overflow if there were none.
- bool is_previous_break_opportunity_hyphenated = false;
- unsigned previous_break_opportunity =
- PreviousBreakOpportunity(break_opportunity - 1, start,
- &is_previous_break_opportunity_hyphenated);
- if (previous_break_opportunity <= start)
- break;
- break_opportunity = previous_break_opportunity;
- result_out->is_hyphenated = is_previous_break_opportunity_hyphenated;
- line_end_result = nullptr;
+ while (true) {
+ DCHECK_LE(first_safe, break_opportunity.offset);
+ last_safe = std::max(
+ result_->CachedPreviousSafeToBreakOffset(break_opportunity.offset),
+ first_safe);
+ DCHECK_LE(last_safe, break_opportunity.offset);
+ DCHECK_GE(last_safe, first_safe);
+ if (last_safe == break_opportunity.offset)
+ break;
+ DCHECK_LE(break_opportunity.offset, range_end);
+ if (is_overflow) {
+ line_end_result = Shape(direction, last_safe, break_opportunity.offset);
+ break;
}
+ LayoutUnit safe_position = SnapStart(
+ result_->CachedPositionForOffset(last_safe - range_start), direction);
+ line_end_result = Shape(direction, last_safe, break_opportunity.offset);
+ if (line_end_result->SnappedWidth() <=
+ FlipRtl(end_position - safe_position, direction))
+ break;
+
+ // Doesn't fit after the reshape. Try the previous break opportunity.
+ line_end_result = nullptr;
+ break_opportunity =
+ PreviousBreakOpportunity(break_opportunity.offset - 1, start);
+ if (break_opportunity.offset > start)
+ continue;
+
+ // No suitable break opportunity, not exceeding the available space,
+ // found. Any break opportunities beyond candidate_break won't fit
+ // either because the ShapeResult has the full context.
+ // This line will overflow, but there are multiple choices to break,
+ // because none can fit. The one after candidate_break is better for
+ // ligatures, but the one before is better for kernings.
+ break_opportunity = PreviousBreakOpportunity(candidate_break, start);
+ // Loop once more to compute last_safe for the new break opportunity.
+ is_overflow = true;
}
-
- if (break_opportunity > start) {
- last_safe = previous_safe;
- break;
- }
-
- // No suitable break opportunity, not exceeding the available space,
- // found. Choose the next valid one even though it will overflow.
- break_opportunity = NextBreakOpportunity(candidate_break, start,
- &result_out->is_hyphenated);
- // |range_end| may not be a break opportunity, but this function cannot
- // measure beyond it.
- break_opportunity = std::min(break_opportunity, range_end);
}
+ DCHECK_GE(break_opportunity.offset, last_safe);
+ DCHECK_EQ(break_opportunity.offset - start,
+ (line_start_result ? line_start_result->NumCharacters() : 0) +
+ (last_safe > first_safe ? last_safe - first_safe : 0) +
+ (line_end_result ? line_end_result->NumCharacters() : 0));
// Create shape results for the line by copying from the re-shaped result (if
// reshaping was needed) and the original shape results.
@@ -347,43 +362,49 @@ scoped_refptr<ShapeResult> ShapingLineBreaker::ShapeLine(
if (line_end_result)
line_end_result->CopyRange(last_safe, max_length, line_result.get());
- DCHECK_GT(break_opportunity, start);
- // TODO(layout-dev): This hits on Mac and Mac only for a number of tests in
- // virtual/layout_ng/external/wpt/css/CSS2/floats-clear/.
- // DCHECK_EQ(std::min(break_opportunity, range_end) - start,
- // line_result->NumCharacters());
+ DCHECK_GT(break_opportunity.offset, start);
+ DCHECK_LE(break_opportunity.offset, range_end);
+ DCHECK_EQ(break_opportunity.offset - start, line_result->NumCharacters());
- result_out->break_offset = break_opportunity;
- if (!result_out->is_hyphenated &&
- text[break_opportunity - 1] == kSoftHyphenCharacter)
- result_out->is_hyphenated = true;
+ result_out->break_offset = break_opportunity.offset;
+ result_out->is_hyphenated =
+ break_opportunity.is_hyphenated ||
+ text[break_opportunity.offset - 1] == kSoftHyphenCharacter;
return line_result;
}
// Shape from the specified offset to the end of the ShapeResult.
// If |start| is safe-to-break, this copies the subset of the result.
-scoped_refptr<ShapeResult> ShapingLineBreaker::ShapeToEnd(unsigned start,
- unsigned first_safe,
- unsigned range_end) {
- DCHECK_GE(start, result_->StartIndexForResult());
+scoped_refptr<const ShapeResult> ShapingLineBreaker::ShapeToEnd(
+ unsigned start,
+ unsigned first_safe,
+ unsigned range_start,
+ unsigned range_end) {
+ DCHECK(result_);
+ DCHECK_EQ(range_start, result_->StartIndexForResult());
+ DCHECK_EQ(range_end, result_->EndIndexForResult());
+ DCHECK_GE(start, range_start);
DCHECK_LT(start, range_end);
DCHECK_GE(first_safe, start);
- DCHECK_EQ(range_end, result_->EndIndexForResult());
+
+ // If |start| is at the start of the range the entire result object may be
+ // reused, which avoids creating an extra copy an the sub-range logic.
+ if (start == range_start)
+ return result_;
// If |start| is safe-to-break, no reshape is needed.
- if (first_safe == start) {
+ if (start == first_safe)
return result_->SubRange(start, range_end);
- }
// If no safe-to-break offset is found in range, reshape the entire range.
TextDirection direction = result_->Direction();
- if (first_safe >= range_end) {
+ if (first_safe >= range_end)
return Shape(direction, start, range_end);
- }
// Otherwise reshape to |first_safe|, then copy the rest.
scoped_refptr<ShapeResult> line_result = Shape(direction, start, first_safe);
result_->CopyRange(first_safe, range_end, line_result.get());
+ DCHECK_EQ(range_end - start, line_result->NumCharacters());
return line_result;
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h b/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h
index 361527543ed..d06cc93ae58 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPING_LINE_BREAKER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_SHAPING_LINE_BREAKER_H_
+#include "third_party/blink/renderer/platform/fonts/shaping/run_segmenter.h"
#include "third_party/blink/renderer/platform/layout_unit.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/text/text_direction.h"
@@ -35,10 +36,15 @@ class PLATFORM_EXPORT ShapingLineBreaker final {
STACK_ALLOCATED();
public:
+ // Construct a ShapingLineBreaker.
+ //
+ // When the ShapeResult is from a RunSegmenterRange, giving it can skip
+ // running RunSegmenter for much better performance.
ShapingLineBreaker(const HarfBuzzShaper*,
const Font*,
- const ShapeResult*,
+ scoped_refptr<const ShapeResult>,
const LazyLineBreakIterator*,
+ const RunSegmenter::RunSegmenterRange* = nullptr,
ShapeResultSpacing<String>* = nullptr,
const Hyphenation* = nullptr);
~ShapingLineBreaker() = default;
@@ -59,16 +65,25 @@ class PLATFORM_EXPORT ShapingLineBreaker final {
// Shapes a line of text by finding a valid and appropriate break opportunity
// based on the shaping results for the entire paragraph.
- // |start_should_be_safe| is true for the beginning of each wrapped line, but
- // is false for subsequent ShapeResults.
- scoped_refptr<ShapeResult> ShapeLine(unsigned start_offset,
- LayoutUnit available_space,
- bool start_should_be_safe,
- Result* result_out);
- scoped_refptr<ShapeResult> ShapeLine(unsigned start_offset,
- LayoutUnit available_space,
- Result* result_out) {
- return ShapeLine(start_offset, available_space, true, result_out);
+ enum Options {
+ kDefaultOptions = 0,
+ // Disable reshpaing the start edge even if the start offset is not safe-
+ // to-break. Set if this is not at the start edge of a wrapped line.
+ kDontReshapeStart = 1,
+ // Returns nullptr if this line overflows. When the word is very long, such
+ // as URL or data, creating ShapeResult is expensive. Set this option to
+ // suppress if ShapeResult is not needed when this line overflows.
+ kNoResultIfOverflow = 2,
+ };
+ scoped_refptr<const ShapeResult> ShapeLine(unsigned start_offset,
+ LayoutUnit available_space,
+ unsigned options,
+ Result* result_out);
+ scoped_refptr<const ShapeResult> ShapeLine(unsigned start_offset,
+ LayoutUnit available_space,
+ Result* result_out) {
+ return ShapeLine(start_offset, available_space, kDefaultOptions,
+ result_out);
}
// Disable breaking at soft hyphens (U+00AD).
@@ -78,29 +93,34 @@ class PLATFORM_EXPORT ShapingLineBreaker final {
private:
const String& GetText() const;
- unsigned PreviousBreakOpportunity(unsigned offset,
- unsigned start,
- bool* is_hyphenated) const;
- unsigned NextBreakOpportunity(unsigned offset,
- unsigned start,
- bool* is_hyphenated) const;
- unsigned Hyphenate(unsigned offset,
- unsigned start,
- bool backwards,
- bool* is_hyphenated) const;
+ // Represents a break opportunity offset and its properties.
+ struct BreakOpportunity {
+ STACK_ALLOCATED();
+
+ unsigned offset;
+ bool is_hyphenated;
+ };
+ BreakOpportunity PreviousBreakOpportunity(unsigned offset,
+ unsigned start) const;
+ BreakOpportunity NextBreakOpportunity(unsigned offset, unsigned start) const;
+ BreakOpportunity Hyphenate(unsigned offset,
+ unsigned start,
+ bool backwards) const;
unsigned Hyphenate(unsigned offset,
unsigned word_start,
unsigned word_end,
bool backwards) const;
scoped_refptr<ShapeResult> Shape(TextDirection, unsigned start, unsigned end);
- scoped_refptr<ShapeResult> ShapeToEnd(unsigned start,
- unsigned first_safe,
- unsigned range_end);
+ scoped_refptr<const ShapeResult> ShapeToEnd(unsigned start,
+ unsigned first_safe,
+ unsigned range_start,
+ unsigned range_end);
const HarfBuzzShaper* shaper_;
const Font* font_;
- const ShapeResult* result_;
+ scoped_refptr<const ShapeResult> result_;
+ const RunSegmenter::RunSegmenterRange* pre_segmented_;
const LazyLineBreakIterator* break_iterator_;
// TODO(kojii): ShapeResultSpacing is not const because it's stateful when it
// has expansions. Split spacing and expansions to make this const.
diff --git a/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker_test.cc b/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker_test.cc
index 30cb27dbf6b..16b10a59128 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/shaping/shaping_line_breaker_test.cc
@@ -20,12 +20,12 @@ namespace blink {
namespace {
-scoped_refptr<ShapeResult> ShapeLine(ShapingLineBreaker* breaker,
- unsigned start_offset,
- LayoutUnit available_space,
- unsigned* break_offset) {
+scoped_refptr<const ShapeResult> ShapeLine(ShapingLineBreaker* breaker,
+ unsigned start_offset,
+ LayoutUnit available_space,
+ unsigned* break_offset) {
ShapingLineBreaker::Result result;
- scoped_refptr<ShapeResult> shape_result =
+ scoped_refptr<const ShapeResult> shape_result =
breaker->ShapeLine(start_offset, available_space, &result);
*break_offset = result.break_offset;
return shape_result;
@@ -48,8 +48,7 @@ class ShapingLineBreakerTest : public testing::Test {
const String& string) {
Vector<unsigned> break_positions;
for (unsigned i = 0; i <= string.length(); i++) {
- bool is_hyphenated = false;
- unsigned next = breaker.NextBreakOpportunity(i, 0, &is_hyphenated);
+ unsigned next = breaker.NextBreakOpportunity(i, 0).offset;
if (break_positions.IsEmpty() || break_positions.back() != next)
break_positions.push_back(next);
}
@@ -61,9 +60,7 @@ class ShapingLineBreakerTest : public testing::Test {
const String& string) {
Vector<unsigned> break_positions;
for (unsigned i = string.length(); i; i--) {
- bool is_hyphenated = false;
- unsigned previous =
- breaker.PreviousBreakOpportunity(i, 0, &is_hyphenated);
+ unsigned previous = breaker.PreviousBreakOpportunity(i, 0).offset;
if (previous &&
(break_positions.IsEmpty() || break_positions.back() != previous))
break_positions.push_back(previous);
@@ -88,27 +85,31 @@ TEST_F(ShapingLineBreakerTest, ShapeLineLatin) {
LazyLineBreakIterator break_iterator(string, "en-US", LineBreakType::kNormal);
TextDirection direction = TextDirection::kLtr;
- HarfBuzzShaper shaper(string.Characters16(), 56);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<const ShapeResult> result = shaper.Shape(&font, direction);
// "Test run with multiple"
- scoped_refptr<ShapeResult> first4 = shaper.Shape(&font, direction, 0, 22);
+ scoped_refptr<const ShapeResult> first4 =
+ shaper.Shape(&font, direction, 0, 22);
ASSERT_LT(first4->SnappedWidth(), result->SnappedWidth());
// "Test run with"
- scoped_refptr<ShapeResult> first3 = shaper.Shape(&font, direction, 0, 13);
+ scoped_refptr<const ShapeResult> first3 =
+ shaper.Shape(&font, direction, 0, 13);
ASSERT_LT(first3->SnappedWidth(), first4->SnappedWidth());
// "Test run"
- scoped_refptr<ShapeResult> first2 = shaper.Shape(&font, direction, 0, 8);
+ scoped_refptr<const ShapeResult> first2 =
+ shaper.Shape(&font, direction, 0, 8);
ASSERT_LT(first2->SnappedWidth(), first3->SnappedWidth());
// "Test"
- scoped_refptr<ShapeResult> first1 = shaper.Shape(&font, direction, 0, 4);
+ scoped_refptr<const ShapeResult> first1 =
+ shaper.Shape(&font, direction, 0, 4);
ASSERT_LT(first1->SnappedWidth(), first2->SnappedWidth());
ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
- scoped_refptr<ShapeResult> line;
+ scoped_refptr<const ShapeResult> line;
unsigned break_offset = 0;
// Test the case where the entire string fits.
@@ -160,10 +161,11 @@ TEST_F(ShapingLineBreakerTest, ShapeLineLatinMultiLine) {
LazyLineBreakIterator break_iterator(string, "en-US", LineBreakType::kNormal);
TextDirection direction = TextDirection::kLtr;
- HarfBuzzShaper shaper(string.Characters16(), 24);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
- scoped_refptr<ShapeResult> first = shaper.Shape(&font, direction, 0, 4);
- scoped_refptr<ShapeResult> mid_third = shaper.Shape(&font, direction, 0, 16);
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<const ShapeResult> result = shaper.Shape(&font, direction);
+ scoped_refptr<const ShapeResult> first = shaper.Shape(&font, direction, 0, 4);
+ scoped_refptr<const ShapeResult> mid_third =
+ shaper.Shape(&font, direction, 0, 16);
ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
unsigned break_offset = 0;
@@ -187,12 +189,13 @@ TEST_F(ShapingLineBreakerTest, ShapeLineLatinBreakAll) {
LineBreakType::kBreakAll);
TextDirection direction = TextDirection::kLtr;
- HarfBuzzShaper shaper(string.Characters16(), 29);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
- scoped_refptr<ShapeResult> midpoint = shaper.Shape(&font, direction, 0, 16);
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<const ShapeResult> result = shaper.Shape(&font, direction);
+ scoped_refptr<const ShapeResult> midpoint =
+ shaper.Shape(&font, direction, 0, 16);
ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
- scoped_refptr<ShapeResult> line;
+ scoped_refptr<const ShapeResult> line;
unsigned break_offset = 0;
line = ShapeLine(&breaker, 0, midpoint->SnappedWidth(), &break_offset);
@@ -209,11 +212,11 @@ TEST_F(ShapingLineBreakerTest, ShapeLineZeroAvailableWidth) {
LazyLineBreakIterator break_iterator(string, "en-US", LineBreakType::kNormal);
TextDirection direction = TextDirection::kLtr;
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<const ShapeResult> result = shaper.Shape(&font, direction);
ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
- scoped_refptr<ShapeResult> line;
+ scoped_refptr<const ShapeResult> line;
unsigned break_offset = 0;
LayoutUnit zero(0);
@@ -239,23 +242,24 @@ TEST_F(ShapingLineBreakerTest, DISABLED_ShapeLineArabicThaiHanLatin) {
LineBreakType::kNormal);
TextDirection direction = TextDirection::kRtl;
- HarfBuzzShaper shaper(mixed_string, 8);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
- scoped_refptr<ShapeResult> words[] = {shaper.Shape(&font, direction, 0, 1),
- shaper.Shape(&font, direction, 2, 4),
- shaper.Shape(&font, direction, 5, 6),
- shaper.Shape(&font, direction, 6, 7),
- shaper.Shape(&font, direction, 7, 8)};
+ HarfBuzzShaper shaper(mixed_string);
+ scoped_refptr<const ShapeResult> result = shaper.Shape(&font, direction);
+ scoped_refptr<const ShapeResult> words[] = {
+ shaper.Shape(&font, direction, 0, 1),
+ shaper.Shape(&font, direction, 2, 4),
+ shaper.Shape(&font, direction, 5, 6),
+ shaper.Shape(&font, direction, 6, 7),
+ shaper.Shape(&font, direction, 7, 8)};
auto* const longest_word =
std::max_element(std::begin(words), std::end(words),
- [](const scoped_refptr<ShapeResult>& a,
- const scoped_refptr<ShapeResult>& b) {
+ [](const scoped_refptr<const ShapeResult>& a,
+ const scoped_refptr<const ShapeResult>& b) {
return a->SnappedWidth() < b->SnappedWidth();
});
LayoutUnit longest_word_width = (*longest_word)->SnappedWidth();
ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
- scoped_refptr<ShapeResult> line;
+ scoped_refptr<const ShapeResult> line;
unsigned break_offset = 0;
ShapeLine(&breaker, 0, longest_word_width, &break_offset);
@@ -279,11 +283,12 @@ TEST_F(ShapingLineBreakerTest, ShapeLineRangeEndMidWord) {
LazyLineBreakIterator break_iterator(string, "en-US", LineBreakType::kNormal);
TextDirection direction = TextDirection::kLtr;
- HarfBuzzShaper shaper(string.Characters16(), string.length());
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction, 0, 2);
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<const ShapeResult> result =
+ shaper.Shape(&font, direction, 0, 2);
ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
- scoped_refptr<ShapeResult> line;
+ scoped_refptr<const ShapeResult> line;
unsigned break_offset = 0;
line = ShapeLine(&breaker, 0, LayoutUnit::Max(), &break_offset);
@@ -314,7 +319,12 @@ TEST_P(BreakOpportunityTest, Next) {
const BreakOpportunityTestData& data = GetParam();
String string(data.string);
LazyLineBreakIterator break_iterator(string);
- ShapingLineBreaker breaker(nullptr, &font, nullptr, &break_iterator);
+
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<const ShapeResult> result =
+ shaper.Shape(&font, TextDirection::kLtr);
+
+ ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
EXPECT_THAT(BreakPositionsByNext(breaker, string),
testing::ElementsAreArray(data.break_positions));
@@ -330,7 +340,11 @@ TEST_P(BreakOpportunityTest, Previous) {
const BreakOpportunityTestData& data = GetParam();
String string(data.string);
LazyLineBreakIterator break_iterator(string);
- ShapingLineBreaker breaker(nullptr, &font, nullptr, &break_iterator);
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<const ShapeResult> result =
+ shaper.Shape(&font, TextDirection::kLtr);
+
+ ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
EXPECT_THAT(BreakPositionsByPrevious(breaker, string),
testing::ElementsAreArray(data.break_positions));
diff --git a/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.cc b/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.cc
index 189a92dd684..4b93a924162 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.cc
@@ -40,13 +40,13 @@
#include "SkTypes.h"
#include "base/memory/ptr_util.h"
+#include "base/sys_byteorder.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/font_family_names.h"
#include "third_party/blink/renderer/platform/fonts/font_description.h"
#include "third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
-#include "third_party/blink/renderer/platform/wtf/byte_order.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
@@ -280,8 +280,8 @@ static std::pair<int16_t, int16_t> TypoAscenderAndDescender(
size_t size = typeface->getTableData(SkSetFourByteTag('O', 'S', '/', '2'), 68,
sizeof(buffer), buffer);
if (size == sizeof(buffer)) {
- return std::make_pair(static_cast<int16_t>(ntohs(buffer[0])),
- -static_cast<int16_t>(ntohs(buffer[1])));
+ return std::make_pair(static_cast<int16_t>(base::NetToHost16(buffer[0])),
+ -static_cast<int16_t>(base::NetToHost16(buffer[1])));
}
return std::make_pair(0, 0);
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.h b/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.h
index f1a8a20d626..0c159ad6161 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/simple_font_data.h
@@ -37,6 +37,7 @@
#include "third_party/blink/renderer/platform/fonts/font_metrics.h"
#include "third_party/blink/renderer/platform/fonts/font_platform_data.h"
#include "third_party/blink/renderer/platform/fonts/font_vertical_position_type.h"
+#include "third_party/blink/renderer/platform/fonts/glyph.h"
#include "third_party/blink/renderer/platform/fonts/typesetting_features.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/platform_export.h"
diff --git a/chromium/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc b/chromium/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc
index 9b6f99ce9e5..5781cafc4ff 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/skia/font_cache_skia.cc
@@ -34,10 +34,6 @@
#include <memory>
#include <utility>
-#include "SkFontMgr.h"
-#include "SkStream.h"
-#include "SkTypeface.h"
-
#include "build/build_config.h"
#include "third_party/blink/public/platform/linux/web_sandbox_support.h"
#include "third_party/blink/public/platform/platform.h"
@@ -53,6 +49,9 @@
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/text/cstring.h"
+#include "third_party/skia/include/core/SkFontMgr.h"
+#include "third_party/skia/include/core/SkStream.h"
+#include "third_party/skia/include/core/SkTypeface.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/fonts/symbols_iterator_test.cc b/chromium/third_party/blink/renderer/platform/fonts/symbols_iterator_test.cc
index 19553e6868a..7abfaf8ea30 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/symbols_iterator_test.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/symbols_iterator_test.cc
@@ -53,16 +53,6 @@ class SymbolsIteratorTest : public testing::Test {
}
};
-// Some of our compilers cannot initialize a vector from an array yet.
-#define DECLARE_FALLBACK_RUNSVECTOR(...) \
- static const FallbackTestRun kRunsArray[] = __VA_ARGS__; \
- Vector<FallbackTestRun> runs; \
- runs.Append(kRunsArray, sizeof(kRunsArray) / sizeof(*kRunsArray));
-
-#define CHECK_RUNS(...) \
- DECLARE_FALLBACK_RUNSVECTOR(__VA_ARGS__); \
- CheckRuns(runs);
-
TEST_F(SymbolsIteratorTest, Empty) {
String empty(g_empty_string16_bit);
SymbolsIterator symbols_iterator(empty.Characters16(), empty.length());
@@ -74,92 +64,92 @@ TEST_F(SymbolsIteratorTest, Empty) {
}
TEST_F(SymbolsIteratorTest, Space) {
- CHECK_RUNS({{" ", FontFallbackPriority::kText}});
+ CheckRuns({{" ", FontFallbackPriority::kText}});
}
TEST_F(SymbolsIteratorTest, Latin) {
- CHECK_RUNS({{"Aa", FontFallbackPriority::kText}});
+ CheckRuns({{"Aa", FontFallbackPriority::kText}});
}
TEST_F(SymbolsIteratorTest, LatinColorEmojiTextEmoji) {
- CHECK_RUNS({{"a", FontFallbackPriority::kText},
- {"⌚", FontFallbackPriority::kEmojiEmoji},
- {"☎", FontFallbackPriority::kEmojiText}});
+ CheckRuns({{"a", FontFallbackPriority::kText},
+ {"⌚", FontFallbackPriority::kEmojiEmoji},
+ {"☎", FontFallbackPriority::kEmojiText}});
}
TEST_F(SymbolsIteratorTest, IgnoreVSInMath) {
- CHECK_RUNS({{"⊆⊇⊈\xEF\xB8\x8E⊙⊚⊚", FontFallbackPriority::kText}});
+ CheckRuns({{u8"⊆⊇⊈\U0000FE0E⊙⊚⊚", FontFallbackPriority::kText}});
}
TEST_F(SymbolsIteratorTest, IgnoreVS15InText) {
- CHECK_RUNS({{"abcdef\xEF\xB8\x8Eghji", FontFallbackPriority::kText}});
+ CheckRuns({{u8"abcdef\U0000FE0Eghji", FontFallbackPriority::kText}});
}
TEST_F(SymbolsIteratorTest, IgnoreVS16InText) {
- CHECK_RUNS({{"abcdef\xEF\xB8\x8Fghji", FontFallbackPriority::kText}});
+ CheckRuns({{u8"abcdef\U0000FE0Fghji", FontFallbackPriority::kText}});
}
TEST_F(SymbolsIteratorTest, AllHexValuesText) {
// Helps with detecting incorrect emoji pattern definitions which are
// missing a \U000... prefix for example.
- CHECK_RUNS({{"abcdef0123456789ABCDEF", FontFallbackPriority::kText}});
+ CheckRuns({{"abcdef0123456789ABCDEF", FontFallbackPriority::kText}});
}
TEST_F(SymbolsIteratorTest, NumbersAndHashNormalAndEmoji) {
- CHECK_RUNS({{"0123456789#*", FontFallbackPriority::kText},
- {"0⃣1⃣2⃣3⃣4⃣5⃣6⃣7⃣8⃣9⃣*⃣", FontFallbackPriority::kEmojiEmoji},
- {"0123456789#*", FontFallbackPriority::kText}});
+ CheckRuns({{"0123456789#*", FontFallbackPriority::kText},
+ {"0⃣1⃣2⃣3⃣4⃣5⃣6⃣7⃣8⃣9⃣*⃣", FontFallbackPriority::kEmojiEmoji},
+ {"0123456789#*", FontFallbackPriority::kText}});
}
TEST_F(SymbolsIteratorTest, VS16onDigits) {
- CHECK_RUNS({{"#", FontFallbackPriority::kText},
- {"#\uFE0F#\uFE0F\u20E3", FontFallbackPriority::kEmojiEmoji},
- {"#", FontFallbackPriority::kText}});
+ CheckRuns({{"#", FontFallbackPriority::kText},
+ {"#\uFE0F#\uFE0F\u20E3", FontFallbackPriority::kEmojiEmoji},
+ {"#", FontFallbackPriority::kText}});
}
TEST_F(SymbolsIteratorTest, SingleFlag) {
- CHECK_RUNS({{"🇺", FontFallbackPriority::kText}});
+ CheckRuns({{"🇺", FontFallbackPriority::kText}});
}
TEST_F(SymbolsIteratorTest, CombiningCircle) {
- CHECK_RUNS({{"◌́◌̀◌̈◌̂◌̄◌̊", FontFallbackPriority::kText}});
+ CheckRuns({{"◌́◌̀◌̈◌̂◌̄◌̊", FontFallbackPriority::kText}});
}
TEST_F(SymbolsIteratorTest, CombiningEnclosingCircleBackslash) {
- CHECK_RUNS({{"A⃠B⃠C⃠", FontFallbackPriority::kText},
- {"🚷🚯🚱🔞📵🚭🚫", FontFallbackPriority::kEmojiEmoji},
- {"🎙⃠", FontFallbackPriority::kEmojiText},
- {"📸⃠🔫⃠", FontFallbackPriority::kEmojiEmoji},
- {"a⃠b⃠c⃠", FontFallbackPriority::kText}});
+ CheckRuns({{"A⃠B⃠C⃠", FontFallbackPriority::kText},
+ {"🚷🚯🚱🔞📵🚭🚫", FontFallbackPriority::kEmojiEmoji},
+ {"🎙⃠", FontFallbackPriority::kEmojiText},
+ {"📸⃠🔫⃠", FontFallbackPriority::kEmojiEmoji},
+ {"a⃠b⃠c⃠", FontFallbackPriority::kText}});
}
// TODO: Perhaps check for invalid country indicator combinations?
TEST_F(SymbolsIteratorTest, FlagsVsNonFlags) {
- CHECK_RUNS({{"🇺🇸🇸", FontFallbackPriority::kEmojiEmoji}, // "US"
- {"abc", FontFallbackPriority::kText},
- {"🇺🇸", FontFallbackPriority::kEmojiEmoji},
- {"a🇿", FontFallbackPriority::kText}});
+ CheckRuns({{"🇺🇸🇸", FontFallbackPriority::kEmojiEmoji}, // "US"
+ {"abc", FontFallbackPriority::kText},
+ {"🇺🇸", FontFallbackPriority::kEmojiEmoji},
+ {"a🇿", FontFallbackPriority::kText}});
}
TEST_F(SymbolsIteratorTest, EmojiVS15) {
// A VS15 after the anchor must trigger text display.
- CHECK_RUNS({{"⚓\xEF\xB8\x8E", FontFallbackPriority::kEmojiText},
- {"⛵", FontFallbackPriority::kEmojiEmoji}});
+ CheckRuns({{"⚓\U0000FE0E", FontFallbackPriority::kEmojiText},
+ {"⛵", FontFallbackPriority::kEmojiEmoji}});
}
TEST_F(SymbolsIteratorTest, EmojiZWSSequences) {
- CHECK_RUNS({{"👩‍👩‍👧‍👦👩‍❤️‍💋‍👨",
- FontFallbackPriority::kEmojiEmoji},
- {"abcd", FontFallbackPriority::kText},
- {"👩‍👩‍", FontFallbackPriority::kEmojiEmoji},
- {"efgh", FontFallbackPriority::kText}});
+ CheckRuns({{"👩‍👩‍👧‍👦👩‍❤️‍💋‍👨",
+ FontFallbackPriority::kEmojiEmoji},
+ {"abcd", FontFallbackPriority::kText},
+ {"👩‍👩‍", FontFallbackPriority::kEmojiEmoji},
+ {"efgh", FontFallbackPriority::kText}});
}
TEST_F(SymbolsIteratorTest, AllEmojiZWSSequences) {
// clang-format gets confused by Emojis, http://llvm.org/PR30530
// clang-format off
- CHECK_RUNS(
+ CheckRuns(
{{"💏👩‍❤️‍💋‍👨👨‍❤️‍💋‍👨👩‍❤️‍💋‍👩💑👩‍❤️‍👨👨‍❤"
"️"
"‍👨👩‍❤️"
@@ -176,51 +166,50 @@ TEST_F(SymbolsIteratorTest, AllEmojiZWSSequences) {
}
TEST_F(SymbolsIteratorTest, ModifierPlusGender) {
- CHECK_RUNS({{"⛹🏻‍♂", FontFallbackPriority::kEmojiEmoji}});
+ CheckRuns({{"⛹🏻‍♂", FontFallbackPriority::kEmojiEmoji}});
}
TEST_F(SymbolsIteratorTest, TextMemberZwjSequence) {
- CHECK_RUNS({{"👨‍⚕", FontFallbackPriority::kEmojiEmoji}});
+ CheckRuns({{"👨‍⚕", FontFallbackPriority::kEmojiEmoji}});
}
TEST_F(SymbolsIteratorTest, FacepalmCartwheelShrugModifierFemale) {
- CHECK_RUNS({{"🤦‍♀🤸‍♀🤷‍♀🤷🏾‍♀",
- FontFallbackPriority::kEmojiEmoji}});
+ CheckRuns({{"🤦‍♀🤸‍♀🤷‍♀🤷🏾‍♀",
+ FontFallbackPriority::kEmojiEmoji}});
}
TEST_F(SymbolsIteratorTest, AesculapiusMaleFemalEmoji) {
// Emoji Data 4 has upgraded those three characters to Emoji.
- CHECK_RUNS({{"a", FontFallbackPriority::kText},
- {"⚕♀♂", FontFallbackPriority::kEmojiText}});
+ CheckRuns({{"a", FontFallbackPriority::kText},
+ {"⚕♀♂", FontFallbackPriority::kEmojiText}});
}
TEST_F(SymbolsIteratorTest, EyeSpeechBubble) {
- CHECK_RUNS({{"👁‍🗨", FontFallbackPriority::kEmojiEmoji}});
+ CheckRuns({{"👁‍🗨", FontFallbackPriority::kEmojiEmoji}});
}
TEST_F(SymbolsIteratorTest, Modifier) {
- CHECK_RUNS({{"👶🏿", FontFallbackPriority::kEmojiEmoji}});
+ CheckRuns({{"👶🏿", FontFallbackPriority::kEmojiEmoji}});
}
TEST_F(SymbolsIteratorTest, DingbatsMiscSymbolsModifier) {
- CHECK_RUNS({{"⛹🏻✍🏻✊🏼", FontFallbackPriority::kEmojiEmoji}});
+ CheckRuns({{"⛹🏻✍🏻✊🏼", FontFallbackPriority::kEmojiEmoji}});
}
TEST_F(SymbolsIteratorTest, ExtraZWJPrefix) {
- CHECK_RUNS({{"\xE2\x80\x8D", FontFallbackPriority::kText},
- {"\xF0\x9F\x91\xA9\xE2\x80\x8D\xE2"
- "\x9D\xA4\xEF\xB8\x8F\xE2\x80\x8D"
- "\xF0\x9F\x92\x8B\xE2\x80\x8D\xF0\x9F\x91\xA8",
- FontFallbackPriority::kEmojiEmoji}});
+ CheckRuns({{u8"\U0000200D", FontFallbackPriority::kText},
+ {u8"\U0001F469\U0000200D\U00002764\U0000FE0F\U0000200D\U0001F48B"
+ u8"\U0000200D\U0001F468",
+ FontFallbackPriority::kEmojiEmoji}});
}
TEST_F(SymbolsIteratorTest, Arrows) {
- CHECK_RUNS({{"x→←x←↑↓→", FontFallbackPriority::kText}});
+ CheckRuns({{"x→←x←↑↓→", FontFallbackPriority::kText}});
}
TEST_F(SymbolsIteratorTest, JudgePilot) {
- CHECK_RUNS({{"👨‍⚖️👩‍⚖️👨🏼‍⚖️👩🏼‍⚖️",
- FontFallbackPriority::kEmojiEmoji}});
+ CheckRuns({{"👨‍⚖️👩‍⚖️👨🏼‍⚖️👩🏼‍⚖️",
+ FontFallbackPriority::kEmojiEmoji}});
}
// Extracted from http://unicode.org/emoji/charts/emoji-released.html for Emoji
@@ -230,148 +219,198 @@ TEST_F(SymbolsIteratorTest, JudgePilot) {
// cannot form the right glyph from the emoji font. Running this as one run in
// one test ensures that the new emoji form an unbroken emoji-type sequence.
TEST_F(SymbolsIteratorTest, Emoji5AdditionsExceptFlags) {
- CHECK_RUNS(
- {{"\xF0\x9F\xA7\x94\xF0\x9F\x8F\xBB\xF0\x9F\xA7\x94\xF0\x9F\x8F\xBC\xF0"
- "\x9F\xA7\x94\xF0\x9F\x8F\xBD\xF0\x9F\xA7\x94\xF0\x9F\x8F\xBE\xF0\x9F"
- "\xA7\x94\xF0\x9F\x8F\xBF\xF0\x9F\xA4\xB1\xF0\x9F\xA4\xB1\xF0\x9F\x8F"
- "\xBB\xF0\x9F\xA4\xB1\xF0\x9F\x8F\xBC\xF0\x9F\xA4\xB1\xF0\x9F\x8F\xBD"
- "\xF0\x9F\xA4\xB1\xF0\x9F\x8F\xBE\xF0\x9F\xA4\xB1\xF0\x9F\x8F\xBF\xF0"
- "\x9F\xA7\x99\xF0\x9F\xA7\x99\xF0\x9F\x8F\xBB\xF0\x9F\xA7\x99\xF0\x9F"
- "\x8F\xBC\xF0\x9F\xA7\x99\xF0\x9F\x8F\xBD\xF0\x9F\xA7\x99\xF0\x9F\x8F"
- "\xBE\xF0\x9F\xA7\x99\xF0\x9F\x8F\xBF\xF0\x9F\xA7\x99\xE2\x80\x8D\xE2"
- "\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x99\xF0\x9F\x8F\xBB\xE2\x80\x8D\xE2"
- "\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x99\xF0\x9F\x8F\xBC\xE2\x80\x8D\xE2"
- "\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x99\xF0\x9F\x8F\xBD\xE2\x80\x8D\xE2"
- "\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x99\xF0\x9F\x8F\xBE\xE2\x80\x8D\xE2"
- "\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x99\xF0\x9F\x8F\xBF\xE2\x80\x8D\xE2"
- "\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x99\xE2\x80\x8D\xE2\x99\x82\xEF\xB8"
- "\x8F\xF0\x9F\xA7\x99\xF0\x9F\x8F\xBB\xE2\x80\x8D\xE2\x99\x82\xEF\xB8"
- "\x8F\xF0\x9F\xA7\x99\xF0\x9F\x8F\xBC\xE2\x80\x8D\xE2\x99\x82\xEF\xB8"
- "\x8F\xF0\x9F\xA7\x99\xF0\x9F\x8F\xBD\xE2\x80\x8D\xE2\x99\x82\xEF\xB8"
- "\x8F\xF0\x9F\xA7\x99\xF0\x9F\x8F\xBE\xE2\x80\x8D\xE2\x99\x82\xEF\xB8"
- "\x8F\xF0\x9F\xA7\x99\xF0\x9F\x8F\xBF\xE2\x80\x8D\xE2\x99\x82\xEF\xB8"
- "\x8F\xF0\x9F\xA7\x9A\xF0\x9F\xA7\x9A\xF0\x9F\x8F\xBB\xF0\x9F\xA7\x9A"
- "\xF0\x9F\x8F\xBC\xF0\x9F\xA7\x9A\xF0\x9F\x8F\xBD\xF0\x9F\xA7\x9A\xF0"
- "\x9F\x8F\xBE\xF0\x9F\xA7\x9A\xF0\x9F\x8F\xBF\xF0\x9F\xA7\x9A\xE2\x80"
- "\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9A\xF0\x9F\x8F\xBB\xE2\x80"
- "\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9A\xF0\x9F\x8F\xBC\xE2\x80"
- "\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9A\xF0\x9F\x8F\xBD\xE2\x80"
- "\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9A\xF0\x9F\x8F\xBE\xE2\x80"
- "\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9A\xF0\x9F\x8F\xBF\xE2\x80"
- "\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9A\xE2\x80\x8D\xE2\x99\x82"
- "\xEF\xB8\x8F\xF0\x9F\xA7\x9A\xF0\x9F\x8F\xBB\xE2\x80\x8D\xE2\x99\x82"
- "\xEF\xB8\x8F\xF0\x9F\xA7\x9A\xF0\x9F\x8F\xBC\xE2\x80\x8D\xE2\x99\x82"
- "\xEF\xB8\x8F\xF0\x9F\xA7\x9A\xF0\x9F\x8F\xBD\xE2\x80\x8D\xE2\x99\x82"
- "\xEF\xB8\x8F\xF0\x9F\xA7\x9A\xF0\x9F\x8F\xBE\xE2\x80\x8D\xE2\x99\x82"
- "\xEF\xB8\x8F\xF0\x9F\xA7\x9A\xF0\x9F\x8F\xBF\xE2\x80\x8D\xE2\x99\x82"
- "\xEF\xB8\x8F\xF0\x9F\xA7\x9B\xF0\x9F\xA7\x9B\xF0\x9F\x8F\xBB\xF0\x9F"
- "\xA7\x9B\xF0\x9F\x8F\xBC\xF0\x9F\xA7\x9B\xF0\x9F\x8F\xBD\xF0\x9F\xA7"
- "\x9B\xF0\x9F\x8F\xBE\xF0\x9F\xA7\x9B\xF0\x9F\x8F\xBF\xF0\x9F\xA7\x9B"
- "\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9B\xF0\x9F\x8F\xBB"
- "\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9B\xF0\x9F\x8F\xBC"
- "\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9B\xF0\x9F\x8F\xBD"
- "\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9B\xF0\x9F\x8F\xBE"
- "\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9B\xF0\x9F\x8F\xBF"
- "\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9B\xE2\x80\x8D\xE2"
- "\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x9B\xF0\x9F\x8F\xBB\xE2\x80\x8D\xE2"
- "\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x9B\xF0\x9F\x8F\xBC\xE2\x80\x8D\xE2"
- "\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x9B\xF0\x9F\x8F\xBD\xE2\x80\x8D\xE2"
- "\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x9B\xF0\x9F\x8F\xBE\xE2\x80\x8D\xE2"
- "\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x9B\xF0\x9F\x8F\xBF\xE2\x80\x8D\xE2"
- "\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x9C\xF0\x9F\xA7\x9C\xF0\x9F\x8F\xBB"
- "\xF0\x9F\xA7\x9C\xF0\x9F\x8F\xBC\xF0\x9F\xA7\x9C\xF0\x9F\x8F\xBD\xF0"
- "\x9F\xA7\x9C\xF0\x9F\x8F\xBE\xF0\x9F\xA7\x9C\xF0\x9F\x8F\xBF\xF0\x9F"
- "\xA7\x9C\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9C\xF0\x9F"
- "\x8F\xBB\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9C\xF0\x9F"
- "\x8F\xBC\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9C\xF0\x9F"
- "\x8F\xBD\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9C\xF0\x9F"
- "\x8F\xBE\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9C\xF0\x9F"
- "\x8F\xBF\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9C\xE2\x80"
- "\x8D\xE2\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x9C\xF0\x9F\x8F\xBB\xE2\x80"
- "\x8D\xE2\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x9C\xF0\x9F\x8F\xBC\xE2\x80"
- "\x8D\xE2\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x9C\xF0\x9F\x8F\xBD\xE2\x80"
- "\x8D\xE2\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x9C\xF0\x9F\x8F\xBE\xE2\x80"
- "\x8D\xE2\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x9C\xF0\x9F\x8F\xBF\xE2\x80"
- "\x8D\xE2\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x9D\xF0\x9F\xA7\x9D\xF0\x9F"
- "\x8F\xBB\xF0\x9F\xA7\x9D\xF0\x9F\x8F\xBC\xF0\x9F\xA7\x9D\xF0\x9F\x8F"
- "\xBD\xF0\x9F\xA7\x9D\xF0\x9F\x8F\xBE\xF0\x9F\xA7\x9D\xF0\x9F\x8F\xBF"
- "\xF0\x9F\xA7\x9D\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9D"
- "\xF0\x9F\x8F\xBB\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9D"
- "\xF0\x9F\x8F\xBC\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9D"
- "\xF0\x9F\x8F\xBD\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9D"
- "\xF0\x9F\x8F\xBE\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9D"
- "\xF0\x9F\x8F\xBF\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9D"
- "\xE2\x80\x8D\xE2\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x9D\xF0\x9F\x8F\xBB"
- "\xE2\x80\x8D\xE2\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x9D\xF0\x9F\x8F\xBC"
- "\xE2\x80\x8D\xE2\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x9D\xF0\x9F\x8F\xBD"
- "\xE2\x80\x8D\xE2\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x9D\xF0\x9F\x8F\xBE"
- "\xE2\x80\x8D\xE2\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x9D\xF0\x9F\x8F\xBF"
- "\xE2\x80\x8D\xE2\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x9E\xF0\x9F\xA7\x9E"
- "\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9E\xE2\x80\x8D\xE2"
- "\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x9F\xF0\x9F\xA7\x9F\xE2\x80\x8D\xE2"
- "\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x9F\xE2\x80\x8D\xE2\x99\x82\xEF\xB8"
- "\x8F\xF0\x9F\xA7\x96\xF0\x9F\xA7\x96\xF0\x9F\x8F\xBB\xF0\x9F\xA7\x96"
- "\xF0\x9F\x8F\xBC\xF0\x9F\xA7\x96\xF0\x9F\x8F\xBD\xF0\x9F\xA7\x96\xF0"
- "\x9F\x8F\xBE\xF0\x9F\xA7\x96\xF0\x9F\x8F\xBF\xF0\x9F\xA7\x96\xE2\x80"
- "\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x96\xF0\x9F\x8F\xBB\xE2\x80"
- "\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x96\xF0\x9F\x8F\xBC\xE2\x80"
- "\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x96\xF0\x9F\x8F\xBD\xE2\x80"
- "\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x96\xF0\x9F\x8F\xBE\xE2\x80"
- "\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x96\xF0\x9F\x8F\xBF\xE2\x80"
- "\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x96\xE2\x80\x8D\xE2\x99\x82"
- "\xEF\xB8\x8F\xF0\x9F\xA7\x96\xF0\x9F\x8F\xBB\xE2\x80\x8D\xE2\x99\x82"
- "\xEF\xB8\x8F\xF0\x9F\xA7\x96\xF0\x9F\x8F\xBC\xE2\x80\x8D\xE2\x99\x82"
- "\xEF\xB8\x8F\xF0\x9F\xA7\x96\xF0\x9F\x8F\xBD\xE2\x80\x8D\xE2\x99\x82"
- "\xEF\xB8\x8F\xF0\x9F\xA7\x96\xF0\x9F\x8F\xBE\xE2\x80\x8D\xE2\x99\x82"
- "\xEF\xB8\x8F\xF0\x9F\xA7\x96\xF0\x9F\x8F\xBF\xE2\x80\x8D\xE2\x99\x82"
- "\xEF\xB8\x8F\xF0\x9F\xA7\x97\xF0\x9F\xA7\x97\xF0\x9F\x8F\xBB\xF0\x9F"
- "\xA7\x97\xF0\x9F\x8F\xBC\xF0\x9F\xA7\x97\xF0\x9F\x8F\xBD\xF0\x9F\xA7"
- "\x97\xF0\x9F\x8F\xBE\xF0\x9F\xA7\x97\xF0\x9F\x8F\xBF\xF0\x9F\xA7\x97"
- "\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x97\xF0\x9F\x8F\xBB"
- "\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x97\xF0\x9F\x8F\xBC"
- "\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x97\xF0\x9F\x8F\xBD"
- "\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x97\xF0\x9F\x8F\xBE"
- "\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x97\xF0\x9F\x8F\xBF"
- "\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x97\xE2\x80\x8D\xE2"
- "\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x97\xF0\x9F\x8F\xBB\xE2\x80\x8D\xE2"
- "\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x97\xF0\x9F\x8F\xBC\xE2\x80\x8D\xE2"
- "\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x97\xF0\x9F\x8F\xBD\xE2\x80\x8D\xE2"
- "\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x97\xF0\x9F\x8F\xBE\xE2\x80\x8D\xE2"
- "\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x97\xF0\x9F\x8F\xBF\xE2\x80\x8D\xE2"
- "\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x98\xF0\x9F\xA7\x98\xF0\x9F\x8F\xBB"
- "\xF0\x9F\xA7\x98\xF0\x9F\x8F\xBC\xF0\x9F\xA7\x98\xF0\x9F\x8F\xBD\xF0"
- "\x9F\xA7\x98\xF0\x9F\x8F\xBE\xF0\x9F\xA7\x98\xF0\x9F\x8F\xBF\xF0\x9F"
- "\xA7\x98\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x98\xF0\x9F"
- "\x8F\xBB\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x98\xF0\x9F"
- "\x8F\xBC\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x98\xF0\x9F"
- "\x8F\xBD\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x98\xF0\x9F"
- "\x8F\xBE\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x98\xF0\x9F"
- "\x8F\xBF\xE2\x80\x8D\xE2\x99\x80\xEF\xB8\x8F\xF0\x9F\xA7\x98\xE2\x80"
- "\x8D\xE2\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x98\xF0\x9F\x8F\xBB\xE2\x80"
- "\x8D\xE2\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x98\xF0\x9F\x8F\xBC\xE2\x80"
- "\x8D\xE2\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x98\xF0\x9F\x8F\xBD\xE2\x80"
- "\x8D\xE2\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x98\xF0\x9F\x8F\xBE\xE2\x80"
- "\x8D\xE2\x99\x82\xEF\xB8\x8F\xF0\x9F\xA7\x98\xF0\x9F\x8F\xBF\xE2\x80"
- "\x8D\xE2\x99\x82\xEF\xB8\x8F\xF0\x9F\xA4\x9F\xF0\x9F\xA4\x9F\xF0\x9F"
- "\x8F\xBB\xF0\x9F\xA4\x9F\xF0\x9F\x8F\xBC\xF0\x9F\xA4\x9F\xF0\x9F\x8F"
- "\xBD\xF0\x9F\xA4\x9F\xF0\x9F\x8F\xBE\xF0\x9F\xA4\x9F\xF0\x9F\x8F\xBF"
- "\xF0\x9F\xA4\xB2\xF0\x9F\xA4\xB2\xF0\x9F\x8F\xBB\xF0\x9F\xA4\xB2\xF0"
- "\x9F\x8F\xBC\xF0\x9F\xA4\xB2\xF0\x9F\x8F\xBD\xF0\x9F\xA4\xB2\xF0\x9F"
- "\x8F\xBE\xF0\x9F\xA4\xB2\xF0\x9F\x8F\xBF\xF0\x9F\xA7\xA0\xF0\x9F\xA7"
- "\xA1\xF0\x9F\xA7\xA3\xF0\x9F\xA7\xA4\xF0\x9F\xA7\xA5\xF0\x9F\xA7\xA6"
- "\xF0\x9F\xA7\xA2\xF0\x9F\xA6\x93\xF0\x9F\xA6\x92\xF0\x9F\xA6\x94\xF0"
- "\x9F\xA6\x95\xF0\x9F\xA6\x96\xF0\x9F\xA6\x97\xF0\x9F\xA5\xA5\xF0\x9F"
- "\xA5\xA6\xF0\x9F\xA5\xA8\xF0\x9F\xA5\xA9\xF0\x9F\xA5\xAA\xF0\x9F\xA5"
- "\xA3\xF0\x9F\xA5\xAB\xF0\x9F\xA5\x9F\xF0\x9F\xA5\xA0\xF0\x9F\xA5\xA1"
- "\xF0\x9F\xA5\xA7\xF0\x9F\xA5\xA4\xF0\x9F\xA5\xA2\xF0\x9F\x9B\xB8\xF0"
- "\x9F\x9B\xB7\xF0\x9F\xA5\x8C",
+ CheckRuns(
+ {{u8"\U0001F9D4\U0001F3FB\U0001F9D4\U0001F3FC\U0001F9D4\U0001F3FD"
+ u8"\U0001F9D4\U0001F3FE\U0001F9D4\U0001F3FF\U0001F931\U0001F931"
+ u8"\U0001F3FB\U0001F931\U0001F3FC\U0001F931\U0001F3FD\U0001F931"
+ u8"\U0001F3FE\U0001F931\U0001F3FF\U0001F9D9\U0001F9D9\U0001F3FB"
+ u8"\U0001F9D9\U0001F3FC\U0001F9D9\U0001F3FD\U0001F9D9\U0001F3FE"
+ u8"\U0001F9D9\U0001F3FF\U0001F9D9\U0000200D\U00002640\U0000FE0F"
+ u8"\U0001F9D9\U0001F3FB\U0000200D\U00002640\U0000FE0F\U0001F9D9"
+ u8"\U0001F3FC\U0000200D\U00002640\U0000FE0F\U0001F9D9\U0001F3FD"
+ u8"\U0000200D\U00002640\U0000FE0F\U0001F9D9\U0001F3FE\U0000200D"
+ u8"\U00002640\U0000FE0F\U0001F9D9\U0001F3FF\U0000200D\U00002640"
+ u8"\U0000FE0F\U0001F9D9\U0000200D\U00002642\U0000FE0F\U0001F9D9"
+ u8"\U0001F3FB\U0000200D\U00002642\U0000FE0F\U0001F9D9\U0001F3FC"
+ u8"\U0000200D\U00002642\U0000FE0F\U0001F9D9\U0001F3FD\U0000200D"
+ u8"\U00002642\U0000FE0F\U0001F9D9\U0001F3FE\U0000200D\U00002642"
+ u8"\U0000FE0F\U0001F9D9\U0001F3FF\U0000200D\U00002642\U0000FE0F"
+ u8"\U0001F9DA\U0001F9DA\U0001F3FB\U0001F9DA\U0001F3FC\U0001F9DA"
+ u8"\U0001F3FD\U0001F9DA\U0001F3FE\U0001F9DA\U0001F3FF\U0001F9DA"
+ u8"\U0000200D\U00002640\U0000FE0F\U0001F9DA\U0001F3FB\U0000200D"
+ u8"\U00002640\U0000FE0F\U0001F9DA\U0001F3FC\U0000200D\U00002640"
+ u8"\U0000FE0F\U0001F9DA\U0001F3FD\U0000200D\U00002640\U0000FE0F"
+ u8"\U0001F9DA\U0001F3FE\U0000200D\U00002640\U0000FE0F\U0001F9DA"
+ u8"\U0001F3FF\U0000200D\U00002640\U0000FE0F\U0001F9DA\U0000200D"
+ u8"\U00002642\U0000FE0F\U0001F9DA\U0001F3FB\U0000200D\U00002642"
+ u8"\U0000FE0F\U0001F9DA\U0001F3FC\U0000200D\U00002642\U0000FE0F"
+ u8"\U0001F9DA\U0001F3FD\U0000200D\U00002642\U0000FE0F\U0001F9DA"
+ u8"\U0001F3FE\U0000200D\U00002642\U0000FE0F\U0001F9DA\U0001F3FF"
+ u8"\U0000200D\U00002642\U0000FE0F\U0001F9DB\U0001F9DB\U0001F3FB"
+ u8"\U0001F9DB\U0001F3FC\U0001F9DB\U0001F3FD\U0001F9DB\U0001F3FE"
+ u8"\U0001F9DB\U0001F3FF\U0001F9DB\U0000200D\U00002640\U0000FE0F"
+ u8"\U0001F9DB\U0001F3FB\U0000200D\U00002640\U0000FE0F\U0001F9DB"
+ u8"\U0001F3FC\U0000200D\U00002640\U0000FE0F\U0001F9DB\U0001F3FD"
+ u8"\U0000200D\U00002640\U0000FE0F\U0001F9DB\U0001F3FE\U0000200D"
+ u8"\U00002640\U0000FE0F\U0001F9DB\U0001F3FF\U0000200D\U00002640"
+ u8"\U0000FE0F\U0001F9DB\U0000200D\U00002642\U0000FE0F\U0001F9DB"
+ u8"\U0001F3FB\U0000200D\U00002642\U0000FE0F\U0001F9DB\U0001F3FC"
+ u8"\U0000200D\U00002642\U0000FE0F\U0001F9DB\U0001F3FD\U0000200D"
+ u8"\U00002642\U0000FE0F\U0001F9DB\U0001F3FE\U0000200D\U00002642"
+ u8"\U0000FE0F\U0001F9DB\U0001F3FF\U0000200D\U00002642\U0000FE0F"
+ u8"\U0001F9DC\U0001F9DC\U0001F3FB\U0001F9DC\U0001F3FC\U0001F9DC"
+ u8"\U0001F3FD\U0001F9DC\U0001F3FE\U0001F9DC\U0001F3FF\U0001F9DC"
+ u8"\U0000200D\U00002640\U0000FE0F\U0001F9DC\U0001F3FB\U0000200D"
+ u8"\U00002640\U0000FE0F\U0001F9DC\U0001F3FC\U0000200D\U00002640"
+ u8"\U0000FE0F\U0001F9DC\U0001F3FD\U0000200D\U00002640\U0000FE0F"
+ u8"\U0001F9DC\U0001F3FE\U0000200D\U00002640\U0000FE0F\U0001F9DC"
+ u8"\U0001F3FF\U0000200D\U00002640\U0000FE0F\U0001F9DC\U0000200D"
+ u8"\U00002642\U0000FE0F\U0001F9DC\U0001F3FB\U0000200D\U00002642"
+ u8"\U0000FE0F\U0001F9DC\U0001F3FC\U0000200D\U00002642\U0000FE0F"
+ u8"\U0001F9DC\U0001F3FD\U0000200D\U00002642\U0000FE0F\U0001F9DC"
+ u8"\U0001F3FE\U0000200D\U00002642\U0000FE0F\U0001F9DC\U0001F3FF"
+ u8"\U0000200D\U00002642\U0000FE0F\U0001F9DD\U0001F9DD\U0001F3FB"
+ u8"\U0001F9DD\U0001F3FC\U0001F9DD\U0001F3FD\U0001F9DD\U0001F3FE"
+ u8"\U0001F9DD\U0001F3FF\U0001F9DD\U0000200D\U00002640\U0000FE0F"
+ u8"\U0001F9DD\U0001F3FB\U0000200D\U00002640\U0000FE0F\U0001F9DD"
+ u8"\U0001F3FC\U0000200D\U00002640\U0000FE0F\U0001F9DD\U0001F3FD"
+ u8"\U0000200D\U00002640\U0000FE0F\U0001F9DD\U0001F3FE\U0000200D"
+ u8"\U00002640\U0000FE0F\U0001F9DD\U0001F3FF\U0000200D\U00002640"
+ u8"\U0000FE0F\U0001F9DD\U0000200D\U00002642\U0000FE0F\U0001F9DD"
+ u8"\U0001F3FB\U0000200D\U00002642\U0000FE0F\U0001F9DD\U0001F3FC"
+ u8"\U0000200D\U00002642\U0000FE0F\U0001F9DD\U0001F3FD\U0000200D"
+ u8"\U00002642\U0000FE0F\U0001F9DD\U0001F3FE\U0000200D\U00002642"
+ u8"\U0000FE0F\U0001F9DD\U0001F3FF\U0000200D\U00002642\U0000FE0F"
+ u8"\U0001F9DE\U0001F9DE\U0000200D\U00002640\U0000FE0F\U0001F9DE"
+ u8"\U0000200D\U00002642\U0000FE0F\U0001F9DF\U0001F9DF\U0000200D"
+ u8"\U00002640\U0000FE0F\U0001F9DF\U0000200D\U00002642\U0000FE0F"
+ u8"\U0001F9D6\U0001F9D6\U0001F3FB\U0001F9D6\U0001F3FC\U0001F9D6"
+ u8"\U0001F3FD\U0001F9D6\U0001F3FE\U0001F9D6\U0001F3FF\U0001F9D6"
+ u8"\U0000200D\U00002640\U0000FE0F\U0001F9D6\U0001F3FB\U0000200D"
+ u8"\U00002640\U0000FE0F\U0001F9D6\U0001F3FC\U0000200D\U00002640"
+ u8"\U0000FE0F\U0001F9D6\U0001F3FD\U0000200D\U00002640\U0000FE0F"
+ u8"\U0001F9D6\U0001F3FE\U0000200D\U00002640\U0000FE0F\U0001F9D6"
+ u8"\U0001F3FF\U0000200D\U00002640\U0000FE0F\U0001F9D6\U0000200D"
+ u8"\U00002642\U0000FE0F\U0001F9D6\U0001F3FB\U0000200D\U00002642"
+ u8"\U0000FE0F\U0001F9D6\U0001F3FC\U0000200D\U00002642\U0000FE0F"
+ u8"\U0001F9D6\U0001F3FD\U0000200D\U00002642\U0000FE0F\U0001F9D6"
+ u8"\U0001F3FE\U0000200D\U00002642\U0000FE0F\U0001F9D6\U0001F3FF"
+ u8"\U0000200D\U00002642\U0000FE0F\U0001F9D7\U0001F9D7\U0001F3FB"
+ u8"\U0001F9D7\U0001F3FC\U0001F9D7\U0001F3FD\U0001F9D7\U0001F3FE"
+ u8"\U0001F9D7\U0001F3FF\U0001F9D7\U0000200D\U00002640\U0000FE0F"
+ u8"\U0001F9D7\U0001F3FB\U0000200D\U00002640\U0000FE0F\U0001F9D7"
+ u8"\U0001F3FC\U0000200D\U00002640\U0000FE0F\U0001F9D7\U0001F3FD"
+ u8"\U0000200D\U00002640\U0000FE0F\U0001F9D7\U0001F3FE\U0000200D"
+ u8"\U00002640\U0000FE0F\U0001F9D7\U0001F3FF\U0000200D\U00002640"
+ u8"\U0000FE0F\U0001F9D7\U0000200D\U00002642\U0000FE0F\U0001F9D7"
+ u8"\U0001F3FB\U0000200D\U00002642\U0000FE0F\U0001F9D7\U0001F3FC"
+ u8"\U0000200D\U00002642\U0000FE0F\U0001F9D7\U0001F3FD\U0000200D"
+ u8"\U00002642\U0000FE0F\U0001F9D7\U0001F3FE\U0000200D\U00002642"
+ u8"\U0000FE0F\U0001F9D7\U0001F3FF\U0000200D\U00002642\U0000FE0F"
+ u8"\U0001F9D8\U0001F9D8\U0001F3FB\U0001F9D8\U0001F3FC\U0001F9D8"
+ u8"\U0001F3FD\U0001F9D8\U0001F3FE\U0001F9D8\U0001F3FF\U0001F9D8"
+ u8"\U0000200D\U00002640\U0000FE0F\U0001F9D8\U0001F3FB\U0000200D"
+ u8"\U00002640\U0000FE0F\U0001F9D8\U0001F3FC\U0000200D\U00002640"
+ u8"\U0000FE0F\U0001F9D8\U0001F3FD\U0000200D\U00002640\U0000FE0F"
+ u8"\U0001F9D8\U0001F3FE\U0000200D\U00002640\U0000FE0F\U0001F9D8"
+ u8"\U0001F3FF\U0000200D\U00002640\U0000FE0F\U0001F9D8\U0000200D"
+ u8"\U00002642\U0000FE0F\U0001F9D8\U0001F3FB\U0000200D\U00002642"
+ u8"\U0000FE0F\U0001F9D8\U0001F3FC\U0000200D\U00002642\U0000FE0F"
+ u8"\U0001F9D8\U0001F3FD\U0000200D\U00002642\U0000FE0F\U0001F9D8"
+ u8"\U0001F3FE\U0000200D\U00002642\U0000FE0F\U0001F9D8\U0001F3FF"
+ u8"\U0000200D\U00002642\U0000FE0F\U0001F91F\U0001F91F\U0001F3FB"
+ u8"\U0001F91F\U0001F3FC\U0001F91F\U0001F3FD\U0001F91F\U0001F3FE"
+ u8"\U0001F91F\U0001F3FF\U0001F932\U0001F932\U0001F3FB\U0001F932"
+ u8"\U0001F3FC\U0001F932\U0001F3FD\U0001F932\U0001F3FE\U0001F932"
+ u8"\U0001F3FF\U0001F9E0\U0001F9E1\U0001F9E3\U0001F9E4\U0001F9E5"
+ u8"\U0001F9E6\U0001F9E2\U0001F993\U0001F992\U0001F994\U0001F995"
+ u8"\U0001F996\U0001F997\U0001F965\U0001F966\U0001F968\U0001F969"
+ u8"\U0001F96A\U0001F963\U0001F96B\U0001F95F\U0001F960\U0001F961"
+ u8"\U0001F967\U0001F964\U0001F962\U0001F6F8\U0001F6F7\U0001F94C",
FontFallbackPriority::kEmojiEmoji}});
}
TEST_F(SymbolsIteratorTest, EmojiSubdivisionFlags) {
- CHECK_RUNS(
+ CheckRuns(
{{"🏴󠁧󠁢󠁷󠁬󠁳󠁿🏴󠁧󠁢󠁳󠁣󠁴󠁿🏴󠁧󠁢",
FontFallbackPriority::kEmojiEmoji}});
}
+// Extracted from http://unicode.org/emoji/charts/emoji-released.html for Emoji
+// v11, removed U+265F Chess Pawn and U+267E as they do not have default emoji
+// presentation.
+TEST_F(SymbolsIteratorTest, Emoji11Additions) {
+ CheckRuns(
+ {{u8"\U0001F970\U0001F975\U0001F976\U0001F973\U0001F974\U0001F97A"
+ u8"\U0001F468\U0000200D\U0001F9B0\U0001F468\U0001F3FB\U0000200D"
+ u8"\U0001F9B0\U0001F468\U0001F3FC\U0000200D\U0001F9B0\U0001F468"
+ u8"\U0001F3FD\U0000200D\U0001F9B0\U0001F468\U0001F3FE\U0000200D"
+ u8"\U0001F9B0\U0001F468\U0001F3FF\U0000200D\U0001F9B0\U0001F468"
+ u8"\U0000200D\U0001F9B1\U0001F468\U0001F3FB\U0000200D\U0001F9B1"
+ u8"\U0001F468\U0001F3FC\U0000200D\U0001F9B1\U0001F468\U0001F3FD"
+ u8"\U0000200D\U0001F9B1\U0001F468\U0001F3FE\U0000200D\U0001F9B1"
+ u8"\U0001F468\U0001F3FF\U0000200D\U0001F9B1\U0001F468\U0000200D"
+ u8"\U0001F9B3\U0001F468\U0001F3FB\U0000200D\U0001F9B3\U0001F468"
+ u8"\U0001F3FC\U0000200D\U0001F9B3\U0001F468\U0001F3FD\U0000200D"
+ u8"\U0001F9B3\U0001F468\U0001F3FE\U0000200D\U0001F9B3\U0001F468"
+ u8"\U0001F3FF\U0000200D\U0001F9B3\U0001F468\U0000200D\U0001F9B2"
+ u8"\U0001F468\U0001F3FB\U0000200D\U0001F9B2\U0001F468\U0001F3FC"
+ u8"\U0000200D\U0001F9B2\U0001F468\U0001F3FD\U0000200D\U0001F9B2"
+ u8"\U0001F468\U0001F3FE\U0000200D\U0001F9B2\U0001F468\U0001F3FF"
+ u8"\U0000200D\U0001F9B2\U0001F469\U0000200D\U0001F9B0\U0001F469"
+ u8"\U0001F3FB\U0000200D\U0001F9B0\U0001F469\U0001F3FC\U0000200D"
+ u8"\U0001F9B0\U0001F469\U0001F3FD\U0000200D\U0001F9B0\U0001F469"
+ u8"\U0001F3FE\U0000200D\U0001F9B0\U0001F469\U0001F3FF\U0000200D"
+ u8"\U0001F9B0\U0001F469\U0000200D\U0001F9B1\U0001F469\U0001F3FB"
+ u8"\U0000200D\U0001F9B1\U0001F469\U0001F3FC\U0000200D\U0001F9B1"
+ u8"\U0001F469\U0001F3FD\U0000200D\U0001F9B1\U0001F469\U0001F3FE"
+ u8"\U0000200D\U0001F9B1\U0001F469\U0001F3FF\U0000200D\U0001F9B1"
+ u8"\U0001F469\U0000200D\U0001F9B3\U0001F469\U0001F3FB\U0000200D"
+ u8"\U0001F9B3\U0001F469\U0001F3FC\U0000200D\U0001F9B3\U0001F469"
+ u8"\U0001F3FD\U0000200D\U0001F9B3\U0001F469\U0001F3FE\U0000200D"
+ u8"\U0001F9B3\U0001F469\U0001F3FF\U0000200D\U0001F9B3\U0001F469"
+ u8"\U0000200D\U0001F9B2\U0001F469\U0001F3FB\U0000200D\U0001F9B2"
+ u8"\U0001F469\U0001F3FC\U0000200D\U0001F9B2\U0001F469\U0001F3FD"
+ u8"\U0000200D\U0001F9B2\U0001F469\U0001F3FE\U0000200D\U0001F9B2"
+ u8"\U0001F469\U0001F3FF\U0000200D\U0001F9B2\U0001F9B8\U0001F9B8"
+ u8"\U0001F3FB\U0001F9B8\U0001F3FC\U0001F9B8\U0001F3FD\U0001F9B8"
+ u8"\U0001F3FE\U0001F9B8\U0001F3FF\U0001F9B8\U0000200D\U00002640"
+ u8"\U0000FE0F\U0001F9B8\U0001F3FB\U0000200D\U00002640\U0000FE0F"
+ u8"\U0001F9B8\U0001F3FC\U0000200D\U00002640\U0000FE0F\U0001F9B8"
+ u8"\U0001F3FD\U0000200D\U00002640\U0000FE0F\U0001F9B8\U0001F3FE"
+ u8"\U0000200D\U00002640\U0000FE0F\U0001F9B8\U0001F3FF\U0000200D"
+ u8"\U00002640\U0000FE0F\U0001F9B8\U0000200D\U00002642\U0000FE0F"
+ u8"\U0001F9B8\U0001F3FB\U0000200D\U00002642\U0000FE0F\U0001F9B8"
+ u8"\U0001F3FC\U0000200D\U00002642\U0000FE0F\U0001F9B8\U0001F3FD"
+ u8"\U0000200D\U00002642\U0000FE0F\U0001F9B8\U0001F3FE\U0000200D"
+ u8"\U00002642\U0000FE0F\U0001F9B8\U0001F3FF\U0000200D\U00002642"
+ u8"\U0000FE0F\U0001F9B9\U0001F9B9\U0001F3FB\U0001F9B9\U0001F3FC"
+ u8"\U0001F9B9\U0001F3FD\U0001F9B9\U0001F3FE\U0001F9B9\U0001F3FF"
+ u8"\U0001F9B9\U0000200D\U00002640\U0000FE0F\U0001F9B9\U0001F3FB"
+ u8"\U0000200D\U00002640\U0000FE0F\U0001F9B9\U0001F3FC\U0000200D"
+ u8"\U00002640\U0000FE0F\U0001F9B9\U0001F3FD\U0000200D\U00002640"
+ u8"\U0000FE0F\U0001F9B9\U0001F3FE\U0000200D\U00002640\U0000FE0F"
+ u8"\U0001F9B9\U0001F3FF\U0000200D\U00002640\U0000FE0F\U0001F9B9"
+ u8"\U0000200D\U00002642\U0000FE0F\U0001F9B9\U0001F3FB\U0000200D"
+ u8"\U00002642\U0000FE0F\U0001F9B9\U0001F3FC\U0000200D\U00002642"
+ u8"\U0000FE0F\U0001F9B9\U0001F3FD\U0000200D\U00002642\U0000FE0F"
+ u8"\U0001F9B9\U0001F3FE\U0000200D\U00002642\U0000FE0F\U0001F9B9"
+ u8"\U0001F3FF\U0000200D\U00002642\U0000FE0F\U0001F9B5\U0001F9B5"
+ u8"\U0001F3FB\U0001F9B5\U0001F3FC\U0001F9B5\U0001F3FD\U0001F9B5"
+ u8"\U0001F3FE\U0001F9B5\U0001F3FF\U0001F9B6\U0001F9B6\U0001F3FB"
+ u8"\U0001F9B6\U0001F3FC\U0001F9B6\U0001F3FD\U0001F9B6\U0001F3FE"
+ u8"\U0001F9B6\U0001F3FF\U0001F9B4\U0001F9B7\U0001F9B0\U0001F9B1"
+ u8"\U0001F9B3\U0001F9B2\U0001F97D\U0001F97C\U0001F97E\U0001F97F"
+ u8"\U0001F99D\U0001F999\U0001F99B\U0001F998\U0001F9A1\U0001F9A2"
+ u8"\U0001F99A\U0001F99C\U0001F99E\U0001F99F\U0001F9A0\U0001F96D"
+ u8"\U0001F96C\U0001F96F\U0001F9C2\U0001F96E\U0001F9C1\U0001F9ED"
+ u8"\U0001F9F1\U0001F6F9\U0001F9F3\U0001F9E8\U0001F9E7\U0001F94E"
+ u8"\U0001F94F\U0001F94D\U0001F9FF\U0001F9E9\U0001F9F8\U0001F9F5"
+ u8"\U0001F9F6\U0001F9EE\U0001F9FE\U0001F9F0\U0001F9F2\U0001F9EA"
+ u8"\U0001F9EB\U0001F9EC\U0001F9F4\U0001F9F7\U0001F9F9\U0001F9FA"
+ u8"\U0001F9FB\U0001F9FC\U0001F9FD\U0001F9EF\U0001F3F4\U0000200D"
+ u8"\U00002620\U0000FE0F",
+ FontFallbackPriority::kEmojiEmoji}});
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/fonts/vdmx_parser.cc b/chromium/third_party/blink/renderer/platform/fonts/vdmx_parser.cc
index 2df7be8d424..cb178d56fec 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/vdmx_parser.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/vdmx_parser.cc
@@ -30,8 +30,8 @@
#include "third_party/blink/renderer/platform/fonts/vdmx_parser.h"
+#include "base/sys_byteorder.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/byte_order.h"
#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include <stdlib.h>
@@ -72,7 +72,7 @@ class Buffer {
if (offset_ + sizeof(uint16_t) > length_)
return false;
memcpy(value, buffer_ + offset_, sizeof(uint16_t));
- *value = ntohs(*value);
+ *value = base::NetToHost16(*value);
offset_ += sizeof(uint16_t);
return true;
}
diff --git a/chromium/third_party/blink/renderer/platform/fonts/web_font_typeface_factory.h b/chromium/third_party/blink/renderer/platform/fonts/web_font_typeface_factory.h
index bd2854a279f..89aac4d88ed 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/web_font_typeface_factory.h
+++ b/chromium/third_party/blink/renderer/platform/fonts/web_font_typeface_factory.h
@@ -5,7 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_WEB_FONT_TYPEFACE_FACTORY_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_WEB_FONT_TYPEFACE_FACTORY_H_
-#include "third_party/skia/include/ports/SkFontMgr.h"
+#include "third_party/skia/include/core/SkFontMgr.h"
#include "build/build_config.h"
#if defined(OS_WIN) || defined(OS_MACOSX)
diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc b/chromium/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc
index 03dad0c36b1..539575b81ba 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc
@@ -34,8 +34,6 @@
#include <memory>
#include <utility>
-#include "SkFontMgr.h"
-#include "SkTypeface_win.h"
#include "base/debug/alias.h"
#include "third_party/blink/renderer/platform/fonts/bitmap_glyphs_blacklist.h"
#include "third_party/blink/renderer/platform/fonts/font_description.h"
@@ -44,6 +42,8 @@
#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
#include "third_party/blink/renderer/platform/fonts/win/font_fallback_win.h"
#include "third_party/blink/renderer/platform/language.h"
+#include "third_party/skia/include/core/SkFontMgr.h"
+#include "third_party/skia/include/ports/SkTypeface_win.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc b/chromium/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc
index 319f7290a2f..ecb970bdd70 100644
--- a/chromium/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc
+++ b/chromium/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc
@@ -33,13 +33,14 @@
#include <unicode/uchar.h>
#include <limits>
-#include "SkFontMgr.h"
-#include "SkTypeface.h"
+
#include "third_party/blink/renderer/platform/fonts/font_cache.h"
#include "third_party/blink/renderer/platform/text/icu_error.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/skia/include/core/SkFontMgr.h"
+#include "third_party/skia/include/core/SkTypeface.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/geometry/double_size.h b/chromium/third_party/blink/renderer/platform/geometry/double_size.h
index 273c50e55aa..917c81c4c52 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/double_size.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/double_size.h
@@ -21,7 +21,8 @@ class PLATFORM_EXPORT DoubleSize {
public:
DoubleSize() : width_(0), height_(0) {}
DoubleSize(double width, double height) : width_(width), height_(height) {}
- DoubleSize(const IntSize& p) : width_(p.Width()), height_(p.Height()) {}
+ explicit DoubleSize(const IntSize& p)
+ : width_(p.Width()), height_(p.Height()) {}
DoubleSize(const FloatSize& s) : width_(s.Width()), height_(s.Height()) {}
explicit DoubleSize(const LayoutSize&);
@@ -87,13 +88,12 @@ inline IntSize FlooredIntSize(const DoubleSize& p) {
}
inline IntSize RoundedIntSize(const DoubleSize& p) {
- return IntSize(clampTo<int>(roundf(p.Width())),
- clampTo<int>(roundf(p.Height())));
+ return IntSize(clampTo<int>(round(p.Width())),
+ clampTo<int>(round(p.Height())));
}
inline IntSize ExpandedIntSize(const DoubleSize& p) {
- return IntSize(clampTo<int>(ceilf(p.Width())),
- clampTo<int>(ceilf(p.Height())));
+ return IntSize(clampTo<int>(ceil(p.Width())), clampTo<int>(ceil(p.Height())));
}
inline FloatSize ToFloatSize(const DoubleSize& p) {
diff --git a/chromium/third_party/blink/renderer/platform/geometry/float_point.cc b/chromium/third_party/blink/renderer/platform/geometry/float_point.cc
index 75a820a3dcf..fda6393e485 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_point.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_point.cc
@@ -116,6 +116,10 @@ FloatPoint::operator gfx::ScrollOffset() const {
return gfx::ScrollOffset(x_, y_);
}
+FloatPoint::operator gfx::Vector2dF() const {
+ return gfx::Vector2dF(x_, y_);
+}
+
std::ostream& operator<<(std::ostream& ostream, const FloatPoint& point) {
return ostream << point.ToString();
}
diff --git a/chromium/third_party/blink/renderer/platform/geometry/float_point.h b/chromium/third_party/blink/renderer/platform/geometry/float_point.h
index fcabd69402c..e2f0565f8d2 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_point.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_point.h
@@ -47,6 +47,7 @@ struct SkPoint;
namespace gfx {
class PointF;
class ScrollOffset;
+class Vector2dF;
}
namespace blink {
@@ -63,7 +64,7 @@ class PLATFORM_EXPORT FloatPoint {
public:
FloatPoint() : x_(0), y_(0) {}
FloatPoint(float x, float y) : x_(x), y_(y) {}
- FloatPoint(const IntPoint&);
+ explicit FloatPoint(const IntPoint&);
explicit FloatPoint(const SkPoint&);
explicit FloatPoint(const DoublePoint&);
explicit FloatPoint(const LayoutPoint&);
@@ -135,6 +136,7 @@ class PLATFORM_EXPORT FloatPoint {
operator gfx::PointF() const;
explicit operator gfx::ScrollOffset() const;
+ explicit operator gfx::Vector2dF() const;
String ToString() const;
diff --git a/chromium/third_party/blink/renderer/platform/geometry/float_polygon.cc b/chromium/third_party/blink/renderer/platform/geometry/float_polygon.cc
index 2b348616915..eacb6ba0ce9 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_polygon.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_polygon.cc
@@ -85,7 +85,7 @@ static unsigned FindNextEdgeVertexIndex(const FloatPolygon& polygon,
return vertex_index2;
}
-FloatPolygon::FloatPolygon(std::unique_ptr<Vector<FloatPoint>> vertices)
+FloatPolygon::FloatPolygon(Vector<FloatPoint> vertices)
: vertices_(std::move(vertices)) {
unsigned n_vertices = NumberOfVertices();
edges_.resize(n_vertices);
diff --git a/chromium/third_party/blink/renderer/platform/geometry/float_polygon.h b/chromium/third_party/blink/renderer/platform/geometry/float_polygon.h
index d478d96d830..87ac5353089 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_polygon.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_polygon.h
@@ -30,7 +30,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GEOMETRY_FLOAT_POLYGON_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GEOMETRY_FLOAT_POLYGON_H_
-#include <memory>
#include "third_party/blink/renderer/platform/geometry/float_point.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/pod_interval_tree.h"
@@ -52,12 +51,10 @@ class PLATFORM_EXPORT FloatPolygon {
WTF_MAKE_NONCOPYABLE(FloatPolygon);
public:
- explicit FloatPolygon(std::unique_ptr<Vector<FloatPoint>> vertices);
+ explicit FloatPolygon(Vector<FloatPoint> vertices);
- const FloatPoint& VertexAt(unsigned index) const {
- return (*vertices_)[index];
- }
- unsigned NumberOfVertices() const { return vertices_->size(); }
+ const FloatPoint& VertexAt(unsigned index) const { return vertices_[index]; }
+ unsigned NumberOfVertices() const { return vertices_.size(); }
const FloatPolygonEdge& EdgeAt(unsigned index) const { return edges_[index]; }
unsigned NumberOfEdges() const { return edges_.size(); }
@@ -74,7 +71,7 @@ class PLATFORM_EXPORT FloatPolygon {
typedef PODInterval<float, FloatPolygonEdge*> EdgeInterval;
typedef PODIntervalTree<float, FloatPolygonEdge*> EdgeIntervalTree;
- std::unique_ptr<Vector<FloatPoint>> vertices_;
+ Vector<FloatPoint> vertices_;
FloatRect bounding_box_;
bool empty_;
Vector<FloatPolygonEdge> edges_;
diff --git a/chromium/third_party/blink/renderer/platform/geometry/float_polygon_test.cc b/chromium/third_party/blink/renderer/platform/geometry/float_polygon_test.cc
index c15f0c997e5..03aac2d3b4c 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_polygon_test.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_polygon_test.cc
@@ -41,10 +41,9 @@ class FloatPolygonTestValue {
public:
FloatPolygonTestValue(const float* coordinates, unsigned coordinates_length) {
DCHECK(!(coordinates_length % 2));
- std::unique_ptr<Vector<FloatPoint>> vertices =
- std::make_unique<Vector<FloatPoint>>(coordinates_length / 2);
+ Vector<FloatPoint> vertices(coordinates_length / 2);
for (unsigned i = 0; i < coordinates_length; i += 2)
- (*vertices)[i / 2] = FloatPoint(coordinates[i], coordinates[i + 1]);
+ vertices[i / 2] = FloatPoint(coordinates[i], coordinates[i + 1]);
polygon_ = std::make_unique<FloatPolygon>(std::move(vertices));
}
diff --git a/chromium/third_party/blink/renderer/platform/geometry/float_quad.h b/chromium/third_party/blink/renderer/platform/geometry/float_quad.h
index b392aa72297..26922ce6f55 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_quad.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_quad.h
@@ -61,6 +61,12 @@ class PLATFORM_EXPORT FloatQuad {
p3_(in_rect.MaxX(), in_rect.MaxY()),
p4_(in_rect.X(), in_rect.MaxY()) {}
+ explicit FloatQuad(const IntRect& in_rect)
+ : p1_(in_rect.Location()),
+ p2_(in_rect.MaxX(), in_rect.Y()),
+ p3_(in_rect.MaxX(), in_rect.MaxY()),
+ p4_(in_rect.X(), in_rect.MaxY()) {}
+
// Converts from an array of four SkPoints, as from SkMatrix::mapRectToQuad.
explicit FloatQuad(const SkPoint (&)[4]);
diff --git a/chromium/third_party/blink/renderer/platform/geometry/float_rect.cc b/chromium/third_party/blink/renderer/platform/geometry/float_rect.cc
index 34741d1b592..95fe5b7c933 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_rect.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_rect.cc
@@ -116,6 +116,17 @@ bool FloatRect::Intersects(const FloatRect& other) const {
other.X() < MaxX() && Y() < other.MaxY() && other.Y() < MaxY();
}
+bool FloatRect::Intersects(const IntRect& other) const {
+ // Checking emptiness handles negative widths as well as zero.
+ return !IsEmpty() && !other.IsEmpty() && X() < other.MaxX() &&
+ other.X() < MaxX() && Y() < other.MaxY() && other.Y() < MaxY();
+}
+
+bool FloatRect::Contains(const IntRect& other) const {
+ return X() <= other.X() && MaxX() >= other.MaxX() && Y() <= other.Y() &&
+ MaxY() >= other.MaxY();
+}
+
bool FloatRect::Contains(const FloatRect& other) const {
return X() <= other.X() && MaxX() >= other.MaxX() && Y() <= other.Y() &&
MaxY() >= other.MaxY();
@@ -129,6 +140,23 @@ bool FloatRect::Contains(const FloatPoint& point,
MaxY() > point.Y();
}
+void FloatRect::Intersect(const IntRect& other) {
+ float left = std::max(X(), static_cast<float>(other.X()));
+ float top = std::max(Y(), static_cast<float>(other.Y()));
+ float right = std::min(MaxX(), static_cast<float>(other.MaxX()));
+ float bottom = std::min(MaxY(), static_cast<float>(other.MaxY()));
+
+ // Return a clean empty rectangle for non-intersecting cases.
+ if (left >= right || top >= bottom) {
+ left = 0;
+ top = 0;
+ right = 0;
+ bottom = 0;
+ }
+
+ SetLocationAndSizeFromEdges(left, top, right, bottom);
+}
+
void FloatRect::Intersect(const FloatRect& other) {
float left = std::max(X(), other.X());
float top = std::max(Y(), other.Y());
diff --git a/chromium/third_party/blink/renderer/platform/geometry/float_rect.h b/chromium/third_party/blink/renderer/platform/geometry/float_rect.h
index 26f2628e00f..3434286b5af 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_rect.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_rect.h
@@ -67,7 +67,7 @@ class PLATFORM_EXPORT FloatRect {
: location_(location), size_(size) {}
FloatRect(float x, float y, float width, float height)
: location_(FloatPoint(x, y)), size_(FloatSize(width, height)) {}
- FloatRect(const IntRect&);
+ explicit FloatRect(const IntRect&);
explicit FloatRect(const LayoutRect&);
FloatRect(const SkRect&);
@@ -136,10 +136,13 @@ class PLATFORM_EXPORT FloatRect {
location_.Y() + size_.Height());
} // typically bottomRight
+ bool Intersects(const IntRect&) const;
bool Intersects(const FloatRect&) const;
+ bool Contains(const IntRect&) const;
bool Contains(const FloatRect&) const;
bool Contains(const FloatPoint&, ContainsMode = kInsideOrOnStroke) const;
+ void Intersect(const IntRect&);
void Intersect(const FloatRect&);
// Set this rect to be the intersection of itself and the argument rect
// using edge-inclusive geometry. If the two rectangles overlap but the
diff --git a/chromium/third_party/blink/renderer/platform/geometry/float_rect_test.cc b/chromium/third_party/blink/renderer/platform/geometry/float_rect_test.cc
index 982e7a989a7..d2f6098b2d8 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_rect_test.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_rect_test.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
+#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
#include "third_party/blink/renderer/platform/geometry/geometry_test_helpers.h"
@@ -134,7 +135,13 @@ TEST(FloatRectTest, SquaredDistanceToTest) {
r1.SquaredDistanceTo(p24), 50000.f);
}
-TEST(FloatRectTest, ToString) {
+// TODO(crbug.com/851414): Reenable this.
+#if defined(OS_ANDROID)
+#define MAYBE_ToString DISABLED_ToString
+#else
+#define MAYBE_ToString ToString
+#endif
+TEST(FloatRectTest, MAYBE_ToString) {
FloatRect empty_rect = FloatRect();
EXPECT_EQ("0,0 0x0", empty_rect.ToString());
diff --git a/chromium/third_party/blink/renderer/platform/geometry/float_rounded_rect.cc b/chromium/third_party/blink/renderer/platform/geometry/float_rounded_rect.cc
index 59bcb6bd797..62e832ae63a 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_rounded_rect.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_rounded_rect.cc
@@ -42,6 +42,9 @@ FloatRoundedRect::FloatRoundedRect(float x, float y, float width, float height)
FloatRoundedRect::FloatRoundedRect(const FloatRect& rect, const Radii& radii)
: rect_(rect), radii_(radii) {}
+FloatRoundedRect::FloatRoundedRect(const IntRect& rect, const Radii& radii)
+ : rect_(FloatRect(rect)), radii_(radii) {}
+
FloatRoundedRect::FloatRoundedRect(const FloatRect& rect,
const FloatSize& top_left,
const FloatSize& top_right,
diff --git a/chromium/third_party/blink/renderer/platform/geometry/float_rounded_rect.h b/chromium/third_party/blink/renderer/platform/geometry/float_rounded_rect.h
index 13aef593cca..edd2c533fb9 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/float_rounded_rect.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/float_rounded_rect.h
@@ -111,6 +111,7 @@ class PLATFORM_EXPORT FloatRoundedRect {
FloatRoundedRect() = default;
explicit FloatRoundedRect(const FloatRect&, const Radii& = Radii());
+ explicit FloatRoundedRect(const IntRect&, const Radii& = Radii());
FloatRoundedRect(float x, float y, float width, float height);
FloatRoundedRect(const FloatRect&,
const FloatSize& top_left,
diff --git a/chromium/third_party/blink/renderer/platform/geometry/int_point.cc b/chromium/third_party/blink/renderer/platform/geometry/int_point.cc
index 5efff72f178..d824e84f698 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/int_point.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/int_point.cc
@@ -18,6 +18,10 @@ IntPoint::operator gfx::Point() const {
return gfx::Point(X(), Y());
}
+IntPoint::operator gfx::Vector2d() const {
+ return gfx::Vector2d(X(), Y());
+}
+
String IntPoint::ToString() const {
return String::Format("%d,%d", X(), Y());
}
diff --git a/chromium/third_party/blink/renderer/platform/geometry/int_point.h b/chromium/third_party/blink/renderer/platform/geometry/int_point.h
index 14ca3909828..95b7daf655d 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/int_point.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/int_point.h
@@ -45,6 +45,7 @@ typedef struct CGPoint CGPoint;
namespace gfx {
class Point;
+class Vector2d;
}
namespace blink {
@@ -105,6 +106,9 @@ class PLATFORM_EXPORT IntPoint {
#endif
operator gfx::Point() const;
+ // IntPoint is used as an offset, but outside blink, the Vector2d type is used
+ // for offsets instead. Addition of Point+Vector2d gives an offseted Point.
+ explicit operator gfx::Vector2d() const;
String ToString() const;
diff --git a/chromium/third_party/blink/renderer/platform/geometry/int_rect.cc b/chromium/third_party/blink/renderer/platform/geometry/int_rect.cc
index cf792014c06..55406add1eb 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/int_rect.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/int_rect.cc
@@ -25,9 +25,9 @@
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
+#include "base/numerics/checked_math.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
#include "third_party/blink/renderer/platform/wtf/text/text_stream.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -199,7 +199,7 @@ String IntRect::ToString() const {
}
bool IntRect::IsValid() const {
- CheckedNumeric<int> max = location_.X();
+ base::CheckedNumeric<int> max = location_.X();
max += size_.Width();
if (!max.IsValid())
return false;
diff --git a/chromium/third_party/blink/renderer/platform/geometry/layout_rect_outsets.cc b/chromium/third_party/blink/renderer/platform/geometry/layout_rect_outsets.cc
index 2a4a35e7f34..8c14be5d286 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/layout_rect_outsets.cc
+++ b/chromium/third_party/blink/renderer/platform/geometry/layout_rect_outsets.cc
@@ -32,6 +32,7 @@
#include <algorithm>
#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
@@ -49,4 +50,16 @@ void LayoutRectOutsets::Unite(const LayoutRectOutsets& other) {
left_ = std::max(left_, other.left_);
}
+std::ostream& operator<<(std::ostream& ostream,
+ const LayoutRectOutsets& outsets) {
+ return ostream << outsets.ToString();
+}
+
+String LayoutRectOutsets::ToString() const {
+ return String::Format(
+ "top %s; right %s; bottom %s; left %s", Top().ToString().Ascii().data(),
+ Right().ToString().Ascii().data(), Bottom().ToString().Ascii().data(),
+ Left().ToString().Ascii().data());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/geometry/layout_rect_outsets.h b/chromium/third_party/blink/renderer/platform/geometry/layout_rect_outsets.h
index e25a64b84b6..6086d2cfa42 100644
--- a/chromium/third_party/blink/renderer/platform/geometry/layout_rect_outsets.h
+++ b/chromium/third_party/blink/renderer/platform/geometry/layout_rect_outsets.h
@@ -97,6 +97,8 @@ class PLATFORM_EXPORT LayoutRectOutsets {
Bottom() == other.Bottom() && Left() == other.Left();
}
+ String ToString() const;
+
private:
LayoutUnit top_;
LayoutUnit right_;
@@ -145,6 +147,9 @@ inline LayoutRectOutsets EnclosingLayoutRectOutsets(
LayoutUnit::FromFloatCeil(rect.Left()));
}
+PLATFORM_EXPORT std::ostream& operator<<(std::ostream&,
+ const LayoutRectOutsets&);
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GEOMETRY_LAYOUT_RECT_OUTSETS_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/DEPS b/chromium/third_party/blink/renderer/platform/graphics/DEPS
index 9ab46b30e19..0ef1e730698 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/DEPS
+++ b/chromium/third_party/blink/renderer/platform/graphics/DEPS
@@ -16,8 +16,8 @@ include_rules = [
"+base/threading/thread.h",
"+base/threading/thread_checker.h",
"+cc",
+ "+components/viz/client",
"+components/viz/common",
- "+components/viz/test/fake_external_begin_frame_source.h",
"+gpu/config",
"+gpu/command_buffer/client/gles2_interface.h",
"+gpu/command_buffer/client/gpu_memory_buffer_manager.h",
@@ -25,6 +25,7 @@ include_rules = [
"+gpu/command_buffer/common/capabilities.h",
"+gpu/command_buffer/common/mailbox.h",
"+gpu/command_buffer/common/sync_token.h",
+ "+gpu/ipc/common/mailbox.mojom-blink.h",
"+media/base/media_switches.h",
"+media/base/video_frame.h",
"+media/renderers/video_resource_updater.h",
@@ -35,7 +36,6 @@ include_rules = [
"+third_party/blink/renderer/platform/bindings",
"+third_party/blink/renderer/platform/cpu/mips/common_macros_msa.h",
"+third_party/blink/renderer/platform/cross_thread_functional.h",
- "+third_party/blink/renderer/platform/decimal.h",
"+third_party/blink/renderer/platform/drag_image.h",
"+third_party/blink/renderer/platform/fonts",
"+third_party/blink/renderer/platform/graphics",
diff --git a/chromium/third_party/blink/renderer/platform/graphics/OWNERS b/chromium/third_party/blink/renderer/platform/graphics/OWNERS
index 7d080e35715..e6a353e2042 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/graphics/OWNERS
@@ -3,6 +3,7 @@
chrishtr@chromium.org
flackr@chromium.org
fmalita@chromium.org
+fserb@chromium.org
jbroman@chromium.org
junov@chromium.org
kbr@chromium.org
diff --git a/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc b/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
index 3598106da0b..67e5e3fa159 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
@@ -214,8 +214,8 @@ PaintImage AcceleratedStaticBitmapImage::PaintImageForCurrentFrame() {
.TakePaintImage();
}
-void AcceleratedStaticBitmapImage::Draw(PaintCanvas* canvas,
- const PaintFlags& flags,
+void AcceleratedStaticBitmapImage::Draw(cc::PaintCanvas* canvas,
+ const cc::PaintFlags& flags,
const FloatRect& dst_rect,
const FloatRect& src_rect,
RespectImageOrientationEnum,
@@ -262,6 +262,8 @@ void AcceleratedStaticBitmapImage::CreateImageFromMailboxIfNeeded() {
void AcceleratedStaticBitmapImage::EnsureMailbox(MailboxSyncMode mode,
GLenum filter) {
if (!texture_holder_->IsMailboxTextureHolder()) {
+ TRACE_EVENT0("blink", "AcceleratedStaticBitmapImage::EnsureMailbox");
+
if (!original_skia_image_) {
// To ensure that the texture resource stays alive we only really need
// to retain the source SkImage until the mailbox is consumed, but this
@@ -277,7 +279,7 @@ void AcceleratedStaticBitmapImage::EnsureMailbox(MailboxSyncMode mode,
void AcceleratedStaticBitmapImage::Transfer() {
CheckThread();
- EnsureMailbox(kUnverifiedSyncToken, GL_NEAREST);
+ EnsureMailbox(kVerifiedSyncToken, GL_NEAREST);
detach_thread_at_next_check_ = true;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h b/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h
index 422c2683f55..1c8feeefe29 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h
@@ -10,6 +10,7 @@
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
+#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/texture_holder.h"
@@ -44,12 +45,11 @@ class PLATFORM_EXPORT AcceleratedStaticBitmapImage final
scoped_refptr<StaticBitmapImage> MakeAccelerated(
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_wrapper)
override {
- NOTREACHED(); // IsTextureBacked() is already true.
- return nullptr;
+ return this;
}
- void Draw(PaintCanvas*,
- const PaintFlags&,
+ void Draw(cc::PaintCanvas*,
+ const cc::PaintFlags&,
const FloatRect& dst_rect,
const FloatRect& src_rect,
RespectImageOrientationEnum,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image_test.cc b/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image_test.cc
index ca4a16c2f59..c806f7ee73b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image_test.cc
@@ -2,12 +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/platform/graphics/accelerated_static_bitmap_image.h"
+
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
#include "third_party/blink/renderer/platform/graphics/test/fake_gles2_interface.h"
#include "third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/skia/include/core/SkSurface.h"
using testing::ElementsAreArray;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc b/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc
index cbc01649eab..f6a0cca44e1 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.cc
@@ -76,8 +76,9 @@ void BeginFrameProvider::CreateCompositorFrameSinkIfNeeded() {
void BeginFrameProvider::RequestBeginFrame() {
requested_needs_begin_frame_ = true;
- if (needs_begin_frame_)
+ if (needs_begin_frame_) {
return;
+ }
CreateCompositorFrameSinkIfNeeded();
@@ -87,11 +88,10 @@ void BeginFrameProvider::RequestBeginFrame() {
void BeginFrameProvider::OnBeginFrame(const viz::BeginFrameArgs& args) {
// If there was no need for a BeginFrame, just skip it.
- if (needs_begin_frame_) {
+ if (needs_begin_frame_ && requested_needs_begin_frame_) {
requested_needs_begin_frame_ = false;
-
begin_frame_client_->BeginFrame();
-
+ } else {
if (!requested_needs_begin_frame_) {
needs_begin_frame_ = false;
compositor_frame_sink_->SetNeedsBeginFrame(false);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.h b/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.h
index 6138658c20d..f1f211ed0e8 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/begin_frame_provider.h
@@ -41,13 +41,9 @@ class PLATFORM_EXPORT BeginFrameProvider
const WTF::Vector<viz::ReturnedResource>& resources) final {
NOTIMPLEMENTED();
}
- void DidPresentCompositorFrame(uint32_t presentation_token,
- mojo_base::mojom::blink::TimeTicksPtr,
- WTF::TimeDelta refresh,
- uint32_t flags) final {
- NOTIMPLEMENTED();
- }
- void DidDiscardCompositorFrame(uint32_t presentation_token) final {
+ void DidPresentCompositorFrame(
+ uint32_t presentation_token,
+ ::gfx::mojom::blink::PresentationFeedbackPtr feedback) final {
NOTIMPLEMENTED();
}
void OnBeginFrame(const viz::BeginFrameArgs&) final;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc
index edb6ebfcde3..8bf47e9b7b7 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.cc
@@ -210,7 +210,7 @@ String BitmapImage::FilenameExtension() const {
}
void BitmapImage::Draw(
- PaintCanvas* canvas,
+ cc::PaintCanvas* canvas,
const PaintFlags& flags,
const FloatRect& dst_rect,
const FloatRect& src_rect,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.h b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.h
index 76c65e58d16..8aabf7fbe9e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image.h
@@ -121,8 +121,8 @@ class PLATFORM_EXPORT BitmapImage final : public Image {
BitmapImage(const SkBitmap&, ImageObserver* = nullptr);
BitmapImage(ImageObserver* = nullptr, bool is_multi_part = false);
- void Draw(PaintCanvas*,
- const PaintFlags&,
+ void Draw(cc::PaintCanvas*,
+ const cc::PaintFlags&,
const FloatRect& dst_rect,
const FloatRect& src_rect,
RespectImageOrientationEnum,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc
index 4eca0007073..30a73bb3b88 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/bitmap_image_test.cc
@@ -32,6 +32,7 @@
#include "base/test/simple_test_tick_clock.h"
#include "cc/paint/skia_paint_canvas.h"
+#include "cc/tiles/mipmap_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h"
@@ -504,6 +505,22 @@ TEST_F(BitmapImageTest, GIFRepetitionCount) {
EXPECT_EQ(paint_image.FrameCount(), 3u);
}
+TEST_F(BitmapImageTest, DecoderAndCacheMipLevels) {
+ // Tests that the supported sizes from the decoder match the mip level sizes
+ // in cc.
+ LoadImage("/images/resources/cat.jpg");
+ auto paint_image = image_->PaintImageForCurrentFrame();
+ // Jpeg decoder supports upto 1/8 downscales, or mip level 3.
+ for (int mip_level = 0; mip_level < 4; ++mip_level) {
+ SCOPED_TRACE(mip_level);
+ SkISize scaled_size = gfx::SizeToSkISize(cc::MipMapUtil::GetSizeForLevel(
+ gfx::Size(paint_image.width(), paint_image.height()), mip_level));
+ SkISize supported_size = paint_image.GetSupportedDecodeSize(scaled_size);
+ EXPECT_EQ(gfx::SkISizeToSize(supported_size),
+ gfx::SkISizeToSize(scaled_size));
+ }
+}
+
class BitmapImageTestWithMockDecoder : public BitmapImageTest,
public MockImageDecoderClient {
public:
diff --git a/chromium/third_party/blink/renderer/platform/graphics/box_reflection.cc b/chromium/third_party/blink/renderer/platform/graphics/box_reflection.cc
index 56d3336fceb..9cb3d82ab3e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/box_reflection.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/box_reflection.cc
@@ -12,6 +12,22 @@
namespace blink {
+BoxReflection::BoxReflection(ReflectionDirection direction, float offset)
+ : BoxReflection(direction, offset, nullptr, FloatRect()) {}
+
+BoxReflection::BoxReflection(ReflectionDirection direction,
+ float offset,
+ sk_sp<PaintRecord> mask,
+ const FloatRect& mask_bounds)
+ : direction_(direction),
+ offset_(offset),
+ mask_(std::move(mask)),
+ mask_bounds_(mask_bounds) {}
+
+BoxReflection::BoxReflection(const BoxReflection& reflection) = default;
+
+BoxReflection::~BoxReflection() = default;
+
SkMatrix BoxReflection::ReflectionMatrix() const {
SkMatrix flip_matrix;
switch (direction_) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/box_reflection.h b/chromium/third_party/blink/renderer/platform/graphics/box_reflection.h
index f0b351fcdca..18650041552 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/box_reflection.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/box_reflection.h
@@ -6,14 +6,20 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_BOX_REFLECTION_H_
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_record.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/skia/include/core/SkRefCnt.h"
class SkMatrix;
+namespace cc {
+class PaintOpBuffer;
+using PaintRecord = PaintOpBuffer;
+} // namespace cc
+
namespace blink {
+using cc::PaintRecord;
+
// A reflection, as created by -webkit-box-reflect. Consists of:
// * a direction (either vertical or horizontal)
// * an offset to be applied to the reflection after flipping about the
@@ -29,17 +35,13 @@ class PLATFORM_EXPORT BoxReflection {
kHorizontalReflection,
};
- BoxReflection(ReflectionDirection direction, float offset)
- : BoxReflection(direction, offset, nullptr, FloatRect()) {}
-
+ BoxReflection(ReflectionDirection direction, float offset);
BoxReflection(ReflectionDirection direction,
float offset,
sk_sp<PaintRecord> mask,
- const FloatRect& mask_bounds)
- : direction_(direction),
- offset_(offset),
- mask_(std::move(mask)),
- mask_bounds_(mask_bounds) {}
+ const FloatRect& mask_bounds);
+ BoxReflection(const BoxReflection& reflection);
+ ~BoxReflection();
ReflectionDirection Direction() const { return direction_; }
float Offset() const { return offset_; }
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
index f03d90ef1e9..678a5ed2f72 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
@@ -61,14 +61,11 @@ enum {
namespace blink {
Canvas2DLayerBridge::Canvas2DLayerBridge(const IntSize& size,
- int msaa_sample_count,
AccelerationMode acceleration_mode,
const CanvasColorParams& color_params)
: logger_(std::make_unique<Logger>()),
- msaa_sample_count_(msaa_sample_count),
bytes_allocated_(0),
have_recorded_draw_commands_(false),
- filter_quality_(kLow_SkFilterQuality),
is_hidden_(false),
is_deferral_enabled_(true),
software_rendering_while_hidden_(false),
@@ -85,13 +82,12 @@ Canvas2DLayerBridge::Canvas2DLayerBridge(const IntSize& size,
// Clear the background transparent or opaque. Similar code at
// CanvasResourceProvider::Clear().
if (IsValid()) {
- DCHECK(!resource_provider_);
DCHECK(recorder_);
recorder_->getRecordingCanvas()->clear(
color_params_.GetOpacityMode() == kOpaque ? SK_ColorBLACK
: SK_ColorTRANSPARENT);
+ DidDraw(FloatRect(FloatPoint(0, 0), FloatSize(size_)));
}
- DidDraw(FloatRect(FloatPoint(0, 0), FloatSize(size_)));
}
Canvas2DLayerBridge::~Canvas2DLayerBridge() {
@@ -119,7 +115,7 @@ Canvas2DLayerBridge::~Canvas2DLayerBridge() {
void Canvas2DLayerBridge::StartRecording() {
DCHECK(is_deferral_enabled_);
recorder_ = std::make_unique<PaintRecorder>();
- PaintCanvas* canvas =
+ cc::PaintCanvas* canvas =
recorder_->beginRecording(size_.Width(), size_.Height());
// Always save an initial frame, to support resetting the top level matrix
// and clip.
@@ -137,7 +133,9 @@ void Canvas2DLayerBridge::SetLoggerForTesting(std::unique_ptr<Logger> logger) {
}
void Canvas2DLayerBridge::ResetResourceProvider() {
- resource_provider_.reset();
+ if (resource_host_) {
+ resource_host_->ReplaceResourceProvider(nullptr);
+ }
}
bool Canvas2DLayerBridge::ShouldAccelerate(AccelerationHint hint) const {
@@ -170,8 +168,8 @@ bool Canvas2DLayerBridge::IsAccelerated() const {
return false;
if (software_rendering_while_hidden_)
return false;
- if (resource_provider_)
- return resource_provider_->IsAccelerated();
+ if (resource_host_ && resource_host_->ResourceProvider())
+ return resource_host_->ResourceProvider()->IsAccelerated();
// Whether or not to accelerate is not yet resolved. Determine whether
// immediate presentation of the canvas would result in the canvas being
@@ -181,7 +179,7 @@ bool Canvas2DLayerBridge::IsAccelerated() const {
}
static void HibernateWrapper(base::WeakPtr<Canvas2DLayerBridge> bridge,
- double /*idleDeadline*/) {
+ TimeTicks /*idleDeadline*/) {
if (bridge) {
bridge->Hibernate();
} else {
@@ -194,7 +192,7 @@ static void HibernateWrapper(base::WeakPtr<Canvas2DLayerBridge> bridge,
static void HibernateWrapperForTesting(
base::WeakPtr<Canvas2DLayerBridge> bridge) {
- HibernateWrapper(bridge, 0);
+ HibernateWrapper(std::move(bridge), TimeTicks());
}
void Canvas2DLayerBridge::Hibernate() {
@@ -203,7 +201,7 @@ void Canvas2DLayerBridge::Hibernate() {
hibernation_scheduled_ = false;
- if (!resource_provider_) {
+ if (!resource_host_ || !resource_host_->ResourceProvider()) {
logger_->ReportHibernationEvent(kHibernationAbortedBecauseNoSurface);
return;
}
@@ -242,7 +240,8 @@ void Canvas2DLayerBridge::Hibernate() {
DCHECK(!have_recorded_draw_commands_);
SkPaint copy_paint;
copy_paint.setBlendMode(SkBlendMode::kSrc);
- scoped_refptr<StaticBitmapImage> snapshot = resource_provider_->Snapshot();
+ scoped_refptr<StaticBitmapImage> snapshot =
+ resource_host_->ResourceProvider()->Snapshot();
temp_hibernation_surface->getCanvas()->drawImage(
snapshot->PaintImageForCurrentFrame().GetSkImage(), 0, 0, &copy_paint);
hibernation_image_ = temp_hibernation_surface->makeImageSnapshot();
@@ -266,15 +265,27 @@ void Canvas2DLayerBridge::ReportResourceProviderCreationFailure() {
}
}
+CanvasResourceProvider* Canvas2DLayerBridge::ResourceProvider() const {
+ return resource_host_ ? resource_host_->ResourceProvider() : nullptr;
+}
+
CanvasResourceProvider* Canvas2DLayerBridge::GetOrCreateResourceProvider(
AccelerationHint hint) {
+ DCHECK(resource_host_);
+ CanvasResourceProvider* resource_provider = ResourceProvider();
+
if (context_lost_) {
- DCHECK(!resource_provider_);
+ DCHECK(!resource_provider);
return nullptr;
}
- if (resource_provider_)
- return resource_provider_.get();
+ if (resource_provider && resource_provider->IsValid()) {
+ // If resource provider is accelerated, a layer should already exist.
+ // If not, it could mean that the resource provider was create without
+ // going through this method, which is bad.
+ DCHECK(!IsAccelerated() || !!layer_);
+ return resource_provider;
+ }
if (layer_ && !IsHibernating() && hint == kPreferAcceleration &&
acceleration_mode_ != kDisableAcceleration) {
@@ -287,37 +298,27 @@ CanvasResourceProvider* Canvas2DLayerBridge::GetOrCreateResourceProvider(
want_acceleration = false;
software_rendering_while_hidden_ = true;
}
+ AccelerationHint adjusted_hint =
+ want_acceleration ? kPreferAcceleration : kPreferNoAcceleration;
- CanvasResourceProvider::ResourceUsage usage =
- want_acceleration
- ? CanvasResourceProvider::kAcceleratedCompositedResourceUsage
- : CanvasResourceProvider::kSoftwareCompositedResourceUsage;
-
- resource_provider_ = CanvasResourceProvider::Create(
- size_, usage, SharedGpuContext::ContextProviderWrapper(),
- msaa_sample_count_, color_params_);
+ resource_provider =
+ resource_host_->GetOrCreateCanvasResourceProvider(adjusted_hint);
- if (resource_provider_) {
- // Always save an initial frame, to support resetting the top level matrix
- // and clip.
- resource_provider_->Canvas()->save();
- resource_provider_->SetFilterQuality(filter_quality_);
- resource_provider_->SetResourceRecyclingEnabled(!IsHidden());
- } else {
+ if (!resource_provider)
ReportResourceProviderCreationFailure();
- }
- if (resource_provider_ && resource_provider_->IsAccelerated() && !layer_) {
+ if (resource_provider && IsAccelerated() && !layer_) {
layer_ = cc::TextureLayer::CreateForMailbox(this);
layer_->SetIsDrawable(true);
layer_->SetContentsOpaque(ColorParams().GetOpacityMode() == kOpaque);
layer_->SetBlendBackgroundColor(ColorParams().GetOpacityMode() != kOpaque);
- layer_->SetNearestNeighbor(filter_quality_ == kNone_SkFilterQuality);
+ layer_->SetNearestNeighbor(resource_host_->FilterQuality() ==
+ kNone_SkFilterQuality);
GraphicsLayer::RegisterContentsLayer(layer_.get());
}
- if (resource_provider_ && IsHibernating()) {
- if (resource_provider_->IsAccelerated()) {
+ if (resource_provider && IsHibernating()) {
+ if (resource_provider->IsAccelerated()) {
logger_->ReportHibernationEvent(kHibernationEndedNormally);
} else {
if (IsHidden()) {
@@ -328,21 +329,19 @@ CanvasResourceProvider* Canvas2DLayerBridge::GetOrCreateResourceProvider(
}
}
- cc::PaintFlags copy_paint;
+ PaintFlags copy_paint;
copy_paint.setBlendMode(SkBlendMode::kSrc);
PaintImageBuilder builder = PaintImageBuilder::WithDefault();
builder.set_image(hibernation_image_, PaintImage::GetNextContentId());
builder.set_id(PaintImage::GetNextId());
- resource_provider_->Canvas()->drawImage(builder.TakePaintImage(), 0, 0,
- &copy_paint);
+ resource_provider->Canvas()->drawImage(builder.TakePaintImage(), 0, 0,
+ &copy_paint);
hibernation_image_.reset();
if (resource_host_) {
- resource_host_->UpdateMemoryUsage();
-
if (!is_deferral_enabled_) {
resource_host_->RestoreCanvasMatrixClipStack(
- resource_provider_->Canvas());
+ resource_provider->Canvas());
}
// shouldBeDirectComposited() may have changed.
@@ -350,13 +349,15 @@ CanvasResourceProvider* Canvas2DLayerBridge::GetOrCreateResourceProvider(
}
}
- return resource_provider_.get();
+ return resource_provider;
}
-PaintCanvas* Canvas2DLayerBridge::Canvas() {
+cc::PaintCanvas* Canvas2DLayerBridge::Canvas() {
+ DCHECK(resource_host_);
if (!is_deferral_enabled_) {
- GetOrCreateResourceProvider();
- return resource_provider_ ? resource_provider_->Canvas() : nullptr;
+ if (GetOrCreateResourceProvider())
+ return ResourceProvider()->Canvas();
+ return nullptr;
}
return recorder_->getRecordingCanvas();
}
@@ -371,7 +372,7 @@ void Canvas2DLayerBridge::DisableDeferral(DisableDeferralReason reason) {
// required multiple times per frame, the repeated flushing of deferred
// commands would cause significant overhead, so it is better to just stop
// trying to defer altogether.
- if (!is_deferral_enabled_)
+ if (!is_deferral_enabled_ || !resource_host_)
return;
DEFINE_STATIC_LOCAL(EnumerationHistogram, gpu_disabled_histogram,
@@ -388,15 +389,14 @@ void Canvas2DLayerBridge::DisableDeferral(DisableDeferralReason reason) {
is_deferral_enabled_ = false;
recorder_.reset();
// install the current matrix/clip stack onto the immediate canvas
- GetOrCreateResourceProvider();
- if (resource_host_ && resource_provider_)
- resource_host_->RestoreCanvasMatrixClipStack(resource_provider_->Canvas());
+ if (GetOrCreateResourceProvider())
+ resource_host_->RestoreCanvasMatrixClipStack(ResourceProvider()->Canvas());
}
-void Canvas2DLayerBridge::SetFilterQuality(SkFilterQuality filter_quality) {
- filter_quality_ = filter_quality;
- if (resource_provider_)
- resource_provider_->SetFilterQuality(filter_quality);
+void Canvas2DLayerBridge::UpdateFilterQuality() {
+ SkFilterQuality filter_quality = resource_host_->FilterQuality();
+ if (GetOrCreateResourceProvider())
+ ResourceProvider()->SetFilterQuality(filter_quality);
if (layer_)
layer_->SetNearestNeighbor(filter_quality == kNone_SkFilterQuality);
}
@@ -406,11 +406,11 @@ void Canvas2DLayerBridge::SetIsHidden(bool hidden) {
return;
is_hidden_ = hidden;
- if (resource_provider_)
- resource_provider_->SetResourceRecyclingEnabled(!IsHidden());
+ if (ResourceProvider())
+ ResourceProvider()->SetResourceRecyclingEnabled(!IsHidden());
- if (CANVAS2D_HIBERNATION_ENABLED && resource_provider_ && IsHidden() &&
- !hibernation_scheduled_) {
+ if (CANVAS2D_HIBERNATION_ENABLED && ResourceProvider() && IsAccelerated() &&
+ IsHidden() && !hibernation_scheduled_) {
if (layer_)
layer_->ClearTexture();
logger_->ReportHibernationEvent(kHibernationScheduled);
@@ -427,29 +427,28 @@ void Canvas2DLayerBridge::SetIsHidden(bool hidden) {
}
if (!IsHidden() && software_rendering_while_hidden_) {
FlushRecording();
- cc::PaintFlags copy_paint;
+ PaintFlags copy_paint;
copy_paint.setBlendMode(SkBlendMode::kSrc);
std::unique_ptr<CanvasResourceProvider> old_resource_provider =
- std::move(resource_provider_);
- ResetResourceProvider();
+ resource_host_->ReplaceResourceProvider(nullptr);
software_rendering_while_hidden_ = false;
GetOrCreateResourceProvider(kPreferAccelerationAfterVisibilityChange);
- if (resource_provider_) {
+ if (ResourceProvider()) {
if (old_resource_provider) {
cc::PaintImage snapshot =
old_resource_provider->Snapshot()->PaintImageForCurrentFrame();
- resource_provider_->Canvas()->drawImage(snapshot, 0, 0, &copy_paint);
+ ResourceProvider()->Canvas()->drawImage(snapshot, 0, 0, &copy_paint);
}
if (resource_host_ && !is_deferral_enabled_) {
resource_host_->RestoreCanvasMatrixClipStack(
- resource_provider_->Canvas());
+ ResourceProvider()->Canvas());
}
} else {
// New resource provider could not be created. Stay with old one.
- resource_provider_ = std::move(old_resource_provider);
+ resource_host_->ReplaceResourceProvider(std::move(old_resource_provider));
}
}
if (!IsHidden() && IsHibernating()) {
@@ -473,10 +472,11 @@ bool Canvas2DLayerBridge::WritePixels(const SkImageInfo& orig_info,
SkipQueuedDrawCommands();
} else {
FlushRecording();
+ if (!GetOrCreateResourceProvider())
+ return false;
}
- GetOrCreateResourceProvider()->WritePixels(orig_info, pixels, row_bytes, x,
- y);
+ ResourceProvider()->WritePixels(orig_info, pixels, row_bytes, x, y);
DidDraw(FloatRect(x, y, orig_info.width(), orig_info.height()));
return true;
@@ -500,7 +500,7 @@ void Canvas2DLayerBridge::FlushRecording() {
if (have_recorded_draw_commands_ && GetOrCreateResourceProvider()) {
TRACE_EVENT0("cc", "Canvas2DLayerBridge::flushRecording");
- PaintCanvas* canvas = GetOrCreateResourceProvider()->Canvas();
+ cc::PaintCanvas* canvas = ResourceProvider()->Canvas();
{
sk_sp<PaintRecord> recording = recorder_->finishRecordingAsPicture();
canvas->drawPicture(recording);
@@ -508,7 +508,10 @@ void Canvas2DLayerBridge::FlushRecording() {
// Rastering the recording would have locked images, since we've flushed
// all recorded ops, we should relase all locked images as well.
- GetOrCreateResourceProvider()->ReleaseLockedImages();
+ // A new null check on the resource provider is necessary just in case
+ // the playback crashed the context.
+ if (GetOrCreateResourceProvider())
+ ResourceProvider()->ReleaseLockedImages();
if (is_deferral_enabled_)
StartRecording();
@@ -527,8 +530,8 @@ bool Canvas2DLayerBridge::CheckResourceProviderValid() {
return true;
if (context_lost_)
return false;
- if (resource_provider_ && resource_provider_->IsAccelerated() &&
- resource_provider_->IsGpuContextLost()) {
+ if (ResourceProvider() && IsAccelerated() &&
+ ResourceProvider()->IsGpuContextLost()) {
context_lost_ = true;
ResetResourceProvider();
if (resource_host_)
@@ -537,16 +540,14 @@ bool Canvas2DLayerBridge::CheckResourceProviderValid() {
CanvasMetrics::kAccelerated2DCanvasGPUContextLost);
return false;
}
- if (!GetOrCreateResourceProvider())
- return false;
- return resource_provider_.get();
+ return !!GetOrCreateResourceProvider();
}
bool Canvas2DLayerBridge::Restore() {
DCHECK(context_lost_);
if (!IsAccelerated())
return false;
- DCHECK(!resource_provider_);
+ DCHECK(!ResourceProvider());
gpu::gles2::GLES2Interface* shared_gl = nullptr;
layer_->ClearTexture();
@@ -556,11 +557,8 @@ bool Canvas2DLayerBridge::Restore() {
shared_gl = context_provider_wrapper->ContextProvider()->ContextGL();
if (shared_gl && shared_gl->GetGraphicsResetStatusKHR() == GL_NO_ERROR) {
- std::unique_ptr<CanvasResourceProvider> resource_provider =
- CanvasResourceProvider::Create(
- size_, CanvasResourceProvider::kAcceleratedCompositedResourceUsage,
- std::move(context_provider_wrapper), msaa_sample_count_,
- color_params_);
+ CanvasResourceProvider* resource_provider =
+ resource_host_->GetOrCreateCanvasResourceProvider(kPreferAcceleration);
if (!resource_provider)
ReportResourceProviderCreationFailure();
@@ -569,17 +567,18 @@ bool Canvas2DLayerBridge::Restore() {
// non-accelerated, which would be tricky due to changes to the layer tree,
// which can only happen at specific times during the document lifecycle.
// Therefore, we can only accept the restored surface if it is accelerated.
- if (resource_provider && resource_provider->IsAccelerated()) {
- resource_provider_ = std::move(resource_provider);
+ if (resource_provider && !IsAccelerated()) {
+ resource_host_->ReplaceResourceProvider(nullptr);
// FIXME: draw sad canvas picture into new buffer crbug.com/243842
+ } else {
+ context_lost_ = false;
}
- context_lost_ = false;
}
if (resource_host_)
resource_host_->UpdateMemoryUsage();
- return resource_provider_.get();
+ return ResourceProvider();
}
bool Canvas2DLayerBridge::PrepareTransferableResource(
@@ -602,18 +601,19 @@ bool Canvas2DLayerBridge::PrepareTransferableResource(
if (!IsValid())
return false;
+ FlushRecording();
+
// If the context is lost, we don't know if we should be producing GPU or
// software frames, until we get a new context, since the compositor will
// be trying to get a new context and may change modes.
if (!GetOrCreateResourceProvider())
return false;
- FlushRecording();
- scoped_refptr<CanvasResource> frame = resource_provider_->ProduceFrame();
+ scoped_refptr<CanvasResource> frame = ResourceProvider()->ProduceFrame();
if (frame && frame->IsValid()) {
// Note frame is kept alive via a reference kept in out_release_callback.
- bool success =
- frame->PrepareTransferableResource(out_resource, out_release_callback);
+ bool success = frame->PrepareTransferableResource(
+ out_resource, out_release_callback, kUnverifiedSyncToken);
return success;
}
return false;
@@ -631,14 +631,14 @@ void Canvas2DLayerBridge::DidDraw(const FloatRect& rect) {
if (is_deferral_enabled_) {
have_recorded_draw_commands_ = true;
IntRect pixel_bounds = EnclosingIntRect(rect);
- CheckedNumeric<int> pixel_bounds_size = pixel_bounds.Width();
+ base::CheckedNumeric<int> pixel_bounds_size = pixel_bounds.Width();
pixel_bounds_size *= pixel_bounds.Height();
recording_pixel_count_ += pixel_bounds_size;
if (!recording_pixel_count_.IsValid()) {
DisableDeferral(kDisableDeferralReasonExpensiveOverdrawHeuristic);
return;
}
- CheckedNumeric<int> threshold_size = size_.Width();
+ base::CheckedNumeric<int> threshold_size = size_.Width();
threshold_size *= size_.Height();
threshold_size *= CanvasHeuristicParameters::kExpensiveOverdrawThreshold;
if (!threshold_size.IsValid()) {
@@ -662,7 +662,7 @@ void Canvas2DLayerBridge::FinalizeFrame() {
++frames_since_last_commit_;
if (frames_since_last_commit_ >= 2) {
- GetOrCreateResourceProvider()->FlushSkia();
+ ResourceProvider()->FlushSkia();
if (IsAccelerated()) {
if (!rate_limiter_) {
rate_limiter_ =
@@ -689,10 +689,15 @@ scoped_refptr<StaticBitmapImage> Canvas2DLayerBridge::NewImageSnapshot(
return StaticBitmapImage::Create(hibernation_image_);
if (!IsValid())
return nullptr;
+ // GetOrCreateResourceProvider needs to be called before FlushRecording, to
+ // make sure "hint" is properly taken into account, as well as after
+ // FlushRecording, in case the playback crashed the GPU context.
if (!GetOrCreateResourceProvider(hint))
return nullptr;
FlushRecording();
- return GetOrCreateResourceProvider()->Snapshot();
+ if (!GetOrCreateResourceProvider(hint))
+ return nullptr;
+ return ResourceProvider()->Snapshot();
}
void Canvas2DLayerBridge::WillOverwriteCanvas() {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h b/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h
index d9eba20732a..a22973eb878 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.h
@@ -28,8 +28,10 @@
#include <memory>
+#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
+#include "base/numerics/checked_math.h"
#include "build/build_config.h"
#include "cc/layers/texture_layer_client.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
@@ -40,9 +42,7 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/skia/include/core/SkRefCnt.h"
@@ -58,7 +58,6 @@ class TextureLayer;
namespace blink {
class Canvas2DLayerBridgeTest;
-class CanvasResourceProvider;
class SharedContextRateLimiter;
class StaticBitmapImage;
@@ -74,7 +73,6 @@ class StaticBitmapImage;
#define CANVAS2D_BACKGROUND_RENDER_SWITCH_TO_CPU 0
class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
- WTF_MAKE_NONCOPYABLE(Canvas2DLayerBridge);
public:
enum AccelerationMode {
@@ -84,7 +82,6 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
};
Canvas2DLayerBridge(const IntSize&,
- int msaa_sample_count,
AccelerationMode,
const CanvasColorParams&);
@@ -104,7 +101,7 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
cc::Layer* Layer();
bool Restore();
void DisableDeferral(DisableDeferralReason);
- void SetFilterQuality(SkFilterQuality);
+ void UpdateFilterQuality();
// virtual for unit testing
virtual void WillOverwriteCanvas();
@@ -112,7 +109,7 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
virtual void DidRestoreCanvasMatrixClipStack(cc::PaintCanvas*) {}
virtual bool IsAccelerated() const;
- PaintCanvas* Canvas();
+ cc::PaintCanvas* Canvas();
bool IsValid() const;
bool WritePixels(const SkImageInfo&,
const void* pixels,
@@ -127,7 +124,7 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
}
void Hibernate();
- bool IsHibernating() const { return hibernation_image_; }
+ bool IsHibernating() const { return hibernation_image_ != nullptr; }
const CanvasColorParams& ColorParams() const { return color_params_; }
bool HasRecordedDrawCommands() { return have_recorded_draw_commands_; }
@@ -164,16 +161,14 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
};
void SetLoggerForTesting(std::unique_ptr<Logger>);
- CanvasResourceProvider* GetResourceProvider() const {
- return resource_provider_.get();
- }
CanvasResourceProvider* GetOrCreateResourceProvider(
AccelerationHint = kPreferAcceleration);
- void ResetResourceProvider();
+ CanvasResourceProvider* ResourceProvider() const;
private:
bool IsHidden() { return is_hidden_; }
bool CheckResourceProviderValid();
+ void ResetResourceProvider();
void StartRecording();
void SkipQueuedDrawCommands();
@@ -182,7 +177,6 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
bool ShouldAccelerate(AccelerationHint) const;
- std::unique_ptr<CanvasResourceProvider> resource_provider_;
std::unique_ptr<PaintRecorder> recorder_;
sk_sp<SkImage> hibernation_image_;
scoped_refptr<cc::TextureLayer> layer_;
@@ -192,7 +186,6 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
int frames_since_last_commit_ = 0;
size_t bytes_allocated_;
bool have_recorded_draw_commands_;
- SkFilterQuality filter_quality_;
bool is_hidden_;
bool is_deferral_enabled_;
bool software_rendering_while_hidden_;
@@ -208,7 +201,7 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
AccelerationMode acceleration_mode_;
CanvasColorParams color_params_;
IntSize size_;
- CheckedNumeric<int> recording_pixel_count_;
+ base::CheckedNumeric<int> recording_pixel_count_;
enum SnapshotState {
kInitialSnapshotState,
@@ -220,6 +213,8 @@ class PLATFORM_EXPORT Canvas2DLayerBridge : public cc::TextureLayerClient {
CanvasResourceHost* resource_host_;
base::WeakPtrFactory<Canvas2DLayerBridge> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(Canvas2DLayerBridge);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
index 0dc24d3a986..ae95ae9ccf1 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge_test.cc
@@ -37,8 +37,10 @@
#include "components/viz/common/resources/single_release_callback.h"
#include "components/viz/common/resources/transferable_resource.h"
#include "components/viz/test/test_gpu_memory_buffer_manager.h"
+#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/capabilities.h"
+#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
@@ -49,6 +51,7 @@
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_flags.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
+#include "third_party/blink/renderer/platform/graphics/test/fake_canvas_resource_host.h"
#include "third_party/blink/renderer/platform/graphics/test/fake_gles2_interface.h"
#include "third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h"
#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_wrapper.h"
@@ -74,28 +77,6 @@ namespace blink {
namespace {
-class Canvas2DLayerBridgePtr {
- public:
- Canvas2DLayerBridgePtr() = default;
- Canvas2DLayerBridgePtr(std::unique_ptr<Canvas2DLayerBridge> layer_bridge)
- : layer_bridge_(std::move(layer_bridge)) {}
-
- ~Canvas2DLayerBridgePtr() { Clear(); }
-
- void Clear() { layer_bridge_.reset(); }
-
- void operator=(std::unique_ptr<Canvas2DLayerBridge> layer_bridge) {
- DCHECK(!layer_bridge_); // Existing ref must be removed with Clear()
- layer_bridge_ = std::move(layer_bridge);
- }
-
- Canvas2DLayerBridge* operator->() { return layer_bridge_.get(); }
- Canvas2DLayerBridge* Get() { return layer_bridge_.get(); }
-
- private:
- std::unique_ptr<Canvas2DLayerBridge> layer_bridge_;
-};
-
class MockGLES2InterfaceWithImageSupport : public FakeGLES2Interface {
public:
MOCK_METHOD0(Flush, void());
@@ -105,8 +86,8 @@ class MockGLES2InterfaceWithImageSupport : public FakeGLES2Interface {
MOCK_METHOD2(GenTextures, void(GLsizei, GLuint*));
MOCK_METHOD2(DeleteTextures, void(GLsizei, const GLuint*));
// Fake
- void GenMailboxCHROMIUM(GLbyte* name) override {
- name[0] = 1; // Make non-zero mailbox names
+ void ProduceTextureDirectCHROMIUM(GLuint texture, GLbyte* mailbox) override {
+ mailbox[0] = 1; // Make non-zero mailbox names
}
};
@@ -166,19 +147,30 @@ class ImageTrackingDecodeCache : public cc::StubDecodeCache {
bool disallow_cache_use_ = false;
};
+class MockCanvasResourceHost : public blink::FakeCanvasResourceHost {
+ public:
+ MockCanvasResourceHost(const IntSize& size) : FakeCanvasResourceHost(size) {}
+ MOCK_CONST_METHOD1(RestoreCanvasMatrixClipStack, void(cc::PaintCanvas*));
+};
+
} // anonymous namespace
class Canvas2DLayerBridgeTest : public Test {
public:
std::unique_ptr<Canvas2DLayerBridge> MakeBridge(
const IntSize& size,
- Canvas2DLayerBridge::AccelerationMode acceleration_mode) {
+ Canvas2DLayerBridge::AccelerationMode acceleration_mode,
+ const CanvasColorParams& color_params) {
std::unique_ptr<Canvas2DLayerBridge> bridge =
- std::make_unique<Canvas2DLayerBridge>(size, 0, acceleration_mode,
- CanvasColorParams());
+ std::make_unique<Canvas2DLayerBridge>(size, acceleration_mode,
+ color_params);
bridge->DontUseIdleSchedulingForTesting();
+ if (!host_)
+ host_ = std::make_unique<MockCanvasResourceHost>(size);
+ bridge->SetCanvasResourceHost(host_.get());
return bridge;
}
+
void SetUp() override {
auto factory = [](FakeGLES2Interface* gl, ImageTrackingDecodeCache* cache,
bool* gpu_compositing_disabled)
@@ -189,263 +181,223 @@ class Canvas2DLayerBridgeTest : public Test {
SharedGpuContext::SetContextProviderFactoryForTesting(WTF::BindRepeating(
factory, WTF::Unretained(&gl_), WTF::Unretained(&image_decode_cache_)));
}
+
void TearDown() override { SharedGpuContext::ResetForTesting(); }
+ MockCanvasResourceHost* Host() {
+ DCHECK(host_);
+ return host_.get();
+ }
+
protected:
MockGLES2InterfaceWithImageSupport gl_;
ImageTrackingDecodeCache image_decode_cache_;
+ std::unique_ptr<MockCanvasResourceHost> host_;
+};
- void FullLifecycleTest() {
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 150), 0, Canvas2DLayerBridge::kDisableAcceleration,
- CanvasColorParams()));
-
- GrBackendTexture backend_texture =
- bridge->NewImageSnapshot(kPreferAcceleration)
- ->PaintImageForCurrentFrame()
- .GetSkImage()
- ->getBackendTexture(true);
-
- EXPECT_FALSE(backend_texture.isValid());
- bridge.Clear();
- }
+TEST_F(Canvas2DLayerBridgeTest, DisableAcceleration) {
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 150), Canvas2DLayerBridge::kDisableAcceleration,
+ CanvasColorParams());
- void FallbackToSoftwareIfContextLost() {
- gl_.SetIsContextLost(true);
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 150), 0, Canvas2DLayerBridge::kEnableAcceleration,
- CanvasColorParams()));
- EXPECT_TRUE(bridge->IsValid());
- EXPECT_FALSE(bridge->IsAccelerated());
- }
+ GrBackendTexture backend_texture =
+ bridge->NewImageSnapshot(kPreferAcceleration)
+ ->PaintImageForCurrentFrame()
+ .GetSkImage()
+ ->getBackendTexture(true);
- void FallbackToSoftwareOnFailedTextureAlloc() {
- {
- // No fallback case.
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 150), 0, Canvas2DLayerBridge::kEnableAcceleration,
- CanvasColorParams()));
- EXPECT_TRUE(bridge->IsValid());
- EXPECT_TRUE(bridge->IsAccelerated());
- scoped_refptr<StaticBitmapImage> snapshot =
- bridge->NewImageSnapshot(kPreferAcceleration);
- EXPECT_TRUE(bridge->IsAccelerated());
- EXPECT_TRUE(snapshot->IsTextureBacked());
- }
+ EXPECT_FALSE(backend_texture.isValid());
+}
- {
- // Fallback case.
- GrContext* gr = SharedGpuContext::ContextProviderWrapper()
- ->ContextProvider()
- ->GetGrContext();
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 150), 0, Canvas2DLayerBridge::kEnableAcceleration,
- CanvasColorParams()));
- EXPECT_TRUE(bridge->IsValid());
- EXPECT_TRUE(bridge->IsAccelerated()); // We don't yet know that
- // allocation will fail.
- // This will cause SkSurface_Gpu creation to fail without
- // Canvas2DLayerBridge otherwise detecting that anything was disabled.
- gr->abandonContext();
- scoped_refptr<StaticBitmapImage> snapshot =
- bridge->NewImageSnapshot(kPreferAcceleration);
- EXPECT_FALSE(bridge->IsAccelerated());
- EXPECT_FALSE(snapshot->IsTextureBacked());
- }
- }
+TEST_F(Canvas2DLayerBridgeTest, NoDrawOnContextLost) {
+ std::unique_ptr<Canvas2DLayerBridge> bridge = MakeBridge(
+ IntSize(300, 150), Canvas2DLayerBridge::kForceAccelerationForTesting,
+ CanvasColorParams());
+ EXPECT_TRUE(bridge->IsValid());
+ PaintFlags flags;
+ uint32_t gen_id = bridge->GetOrCreateResourceProvider()->ContentUniqueID();
+ bridge->Canvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
+ EXPECT_EQ(gen_id, bridge->GetOrCreateResourceProvider()->ContentUniqueID());
+ gl_.SetIsContextLost(true);
+ EXPECT_EQ(nullptr, bridge->GetOrCreateResourceProvider());
+ // The following passes by not crashing
+ bridge->NewImageSnapshot(kPreferAcceleration);
+}
- void NoDrawOnContextLostTest() {
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 150), 0, Canvas2DLayerBridge::kForceAccelerationForTesting,
- CanvasColorParams()));
- EXPECT_TRUE(bridge->IsValid());
- PaintFlags flags;
- uint32_t gen_id = bridge->GetOrCreateResourceProvider()->ContentUniqueID();
- bridge->Canvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
- EXPECT_EQ(gen_id, bridge->GetOrCreateResourceProvider()->ContentUniqueID());
- gl_.SetIsContextLost(true);
- EXPECT_EQ(gen_id, bridge->GetOrCreateResourceProvider()->ContentUniqueID());
- bridge->Canvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
- EXPECT_EQ(gen_id, bridge->GetOrCreateResourceProvider()->ContentUniqueID());
- // This results in the internal surface being torn down in response to the
- // context loss.
- EXPECT_FALSE(bridge->IsValid());
- EXPECT_EQ(nullptr, bridge->GetOrCreateResourceProvider());
- // The following passes by not crashing
- bridge->Canvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
- bridge->NewImageSnapshot(kPreferAcceleration);
- }
+TEST_F(Canvas2DLayerBridgeTest, PrepareMailboxWhenContextIsLost) {
+ std::unique_ptr<Canvas2DLayerBridge> bridge = MakeBridge(
+ IntSize(300, 150), Canvas2DLayerBridge::kForceAccelerationForTesting,
+ CanvasColorParams());
- void PrepareMailboxWhenContextIsLost() {
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 150), 0, Canvas2DLayerBridge::kForceAccelerationForTesting,
- CanvasColorParams()));
+ EXPECT_TRUE(bridge->IsAccelerated());
+ bridge->FinalizeFrame(); // Trigger the creation of a backing store
+ // When the context is lost we are not sure if we should still be producing
+ // GL frames for the compositor or not, so fail to generate frames.
+ gl_.SetIsContextLost(true);
- EXPECT_TRUE(bridge->IsAccelerated());
- bridge->FinalizeFrame(); // Trigger the creation of a backing store
- // When the context is lost we are not sure if we should still be producing
- // GL frames for the compositor or not, so fail to generate frames.
- gl_.SetIsContextLost(true);
+ viz::TransferableResource resource;
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback;
+ EXPECT_FALSE(bridge->PrepareTransferableResource(nullptr, &resource,
+ &release_callback));
+}
- viz::TransferableResource resource;
- std::unique_ptr<viz::SingleReleaseCallback> release_callback;
- EXPECT_FALSE(bridge->PrepareTransferableResource(nullptr, &resource,
- &release_callback));
- }
+TEST_F(Canvas2DLayerBridgeTest,
+ PrepareMailboxWhenContextIsLostWithFailedRestore) {
+ std::unique_ptr<Canvas2DLayerBridge> bridge = MakeBridge(
+ IntSize(300, 150), Canvas2DLayerBridge::kForceAccelerationForTesting,
+ CanvasColorParams());
- void PrepareMailboxWhenContextIsLostWithFailedRestore() {
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 150), 0, Canvas2DLayerBridge::kForceAccelerationForTesting,
- CanvasColorParams()));
+ bridge->GetOrCreateResourceProvider();
+ EXPECT_TRUE(bridge->IsValid());
+ // When the context is lost we are not sure if we should still be producing
+ // GL frames for the compositor or not, so fail to generate frames.
+ gl_.SetIsContextLost(true);
+ EXPECT_FALSE(bridge->IsValid());
- bridge->GetOrCreateResourceProvider();
- EXPECT_TRUE(bridge->IsValid());
- // When the context is lost we are not sure if we should still be producing
- // GL frames for the compositor or not, so fail to generate frames.
- gl_.SetIsContextLost(true);
- EXPECT_FALSE(bridge->IsValid());
+ // Restoration will fail because
+ // Platform::createSharedOffscreenGraphicsContext3DProvider() is stubbed
+ // in unit tests. This simulates what would happen when attempting to
+ // restore while the GPU process is down.
+ bridge->Restore();
- // Restoration will fail because
- // Platform::createSharedOffscreenGraphicsContext3DProvider() is stubbed
- // in unit tests. This simulates what would happen when attempting to
- // restore while the GPU process is down.
- bridge->Restore();
+ viz::TransferableResource resource;
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback;
+ EXPECT_FALSE(bridge->PrepareTransferableResource(nullptr, &resource,
+ &release_callback));
+}
+TEST_F(Canvas2DLayerBridgeTest, PrepareMailboxAndLoseResource) {
+ // Prepare a mailbox, then report the resource as lost.
+ // This test passes by not crashing and not triggering assertions.
+ {
+ std::unique_ptr<Canvas2DLayerBridge> bridge = MakeBridge(
+ IntSize(300, 150), Canvas2DLayerBridge::kForceAccelerationForTesting,
+ CanvasColorParams());
+ bridge->FinalizeFrame();
viz::TransferableResource resource;
std::unique_ptr<viz::SingleReleaseCallback> release_callback;
- EXPECT_FALSE(bridge->PrepareTransferableResource(nullptr, &resource,
- &release_callback));
+ EXPECT_TRUE(bridge->PrepareTransferableResource(nullptr, &resource,
+ &release_callback));
+
+ bool lost_resource = true;
+ release_callback->Run(gpu::SyncToken(), lost_resource);
}
- void ReleaseCallbackWithNullContextProviderWrapperTest() {
+ // Retry with mailbox released while bridge destruction is in progress.
+ {
viz::TransferableResource resource;
std::unique_ptr<viz::SingleReleaseCallback> release_callback;
{
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 150), 0,
- Canvas2DLayerBridge::kForceAccelerationForTesting,
- CanvasColorParams()));
+ std::unique_ptr<Canvas2DLayerBridge> bridge = MakeBridge(
+ IntSize(300, 150), Canvas2DLayerBridge::kForceAccelerationForTesting,
+ CanvasColorParams());
bridge->FinalizeFrame();
- EXPECT_TRUE(bridge->PrepareTransferableResource(nullptr, &resource,
- &release_callback));
+ bridge->PrepareTransferableResource(nullptr, &resource,
+ &release_callback);
+ // |bridge| goes out of scope and would normally be destroyed, but
+ // object is kept alive by self references.
}
+ // This should cause the bridge to be destroyed.
bool lost_resource = true;
- gl_.SetIsContextLost(true);
- // Get a new context provider so that the WeakPtr to the old one is null.
- // This is the test to make sure that ReleaseMailboxImageResource() handles
- // null context_provider_wrapper properly.
- SharedGpuContext::ContextProviderWrapper();
+ // Before fixing crbug.com/411864, the following line would cause a memory
+ // use after free that sometimes caused a crash in normal builds and
+ // crashed consistently with ASAN.
release_callback->Run(gpu::SyncToken(), lost_resource);
}
-
- void PrepareMailboxAndLoseResourceTest() {
- // Prepare a mailbox, then report the resource as lost.
- // This test passes by not crashing and not triggering assertions.
- {
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 150), 0,
- Canvas2DLayerBridge::kForceAccelerationForTesting,
- CanvasColorParams()));
- bridge->FinalizeFrame();
- viz::TransferableResource resource;
- std::unique_ptr<viz::SingleReleaseCallback> release_callback;
- EXPECT_TRUE(bridge->PrepareTransferableResource(nullptr, &resource,
- &release_callback));
-
- bool lost_resource = true;
- release_callback->Run(gpu::SyncToken(), lost_resource);
- }
-
- // Retry with mailbox released while bridge destruction is in progress.
- {
- viz::TransferableResource resource;
- std::unique_ptr<viz::SingleReleaseCallback> release_callback;
-
- {
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 150), 0,
- Canvas2DLayerBridge::kForceAccelerationForTesting,
- CanvasColorParams()));
- bridge->FinalizeFrame();
- bridge->PrepareTransferableResource(nullptr, &resource,
- &release_callback);
- // |bridge| goes out of scope and would normally be destroyed, but
- // object is kept alive by self references.
- }
-
- // This should cause the bridge to be destroyed.
- bool lost_resource = true;
- // Before fixing crbug.com/411864, the following line would cause a memory
- // use after free that sometimes caused a crash in normal builds and
- // crashed consistently with ASAN.
- release_callback->Run(gpu::SyncToken(), lost_resource);
- }
- }
-
- void AccelerationHintTest() {
- {
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
- CanvasColorParams()));
- PaintFlags flags;
- bridge->Canvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
- scoped_refptr<StaticBitmapImage> image =
- bridge->NewImageSnapshot(kPreferAcceleration);
- EXPECT_TRUE(bridge->IsValid());
- EXPECT_TRUE(bridge->IsAccelerated());
- }
-
- {
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
- CanvasColorParams()));
- PaintFlags flags;
- bridge->Canvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
- scoped_refptr<StaticBitmapImage> image =
- bridge->NewImageSnapshot(kPreferNoAcceleration);
- EXPECT_TRUE(bridge->IsValid());
- EXPECT_FALSE(bridge->IsAccelerated());
- }
- }
-};
-
-TEST_F(Canvas2DLayerBridgeTest, FullLifecycleSingleThreaded) {
- FullLifecycleTest();
}
-TEST_F(Canvas2DLayerBridgeTest, NoDrawOnContextLost) {
- NoDrawOnContextLostTest();
-}
-
-TEST_F(Canvas2DLayerBridgeTest, PrepareMailboxWhenContextIsLost) {
- PrepareMailboxWhenContextIsLost();
-}
-
-TEST_F(Canvas2DLayerBridgeTest,
- PrepareMailboxWhenContextIsLostWithFailedRestore) {
- PrepareMailboxWhenContextIsLostWithFailedRestore();
-}
+TEST_F(Canvas2DLayerBridgeTest, ReleaseCallbackWithNullContextProviderWrapper) {
+ viz::TransferableResource resource;
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback;
-TEST_F(Canvas2DLayerBridgeTest, PrepareMailboxAndLoseResource) {
- PrepareMailboxAndLoseResourceTest();
-}
+ {
+ std::unique_ptr<Canvas2DLayerBridge> bridge = MakeBridge(
+ IntSize(300, 150), Canvas2DLayerBridge::kForceAccelerationForTesting,
+ CanvasColorParams());
+ bridge->FinalizeFrame();
+ EXPECT_TRUE(bridge->PrepareTransferableResource(nullptr, &resource,
+ &release_callback));
+ }
-TEST_F(Canvas2DLayerBridgeTest, ReleaseCallbackWithNullContextProviderWrapper) {
- ReleaseCallbackWithNullContextProviderWrapperTest();
+ bool lost_resource = true;
+ gl_.SetIsContextLost(true);
+ // Get a new context provider so that the WeakPtr to the old one is null.
+ // This is the test to make sure that ReleaseMailboxImageResource() handles
+ // null context_provider_wrapper properly.
+ SharedGpuContext::ContextProviderWrapper();
+ release_callback->Run(gpu::SyncToken(), lost_resource);
}
TEST_F(Canvas2DLayerBridgeTest, AccelerationHint) {
- AccelerationHintTest();
+ {
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ CanvasColorParams());
+ PaintFlags flags;
+ bridge->Canvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
+ scoped_refptr<StaticBitmapImage> image =
+ bridge->NewImageSnapshot(kPreferAcceleration);
+ EXPECT_TRUE(bridge->IsValid());
+ EXPECT_TRUE(bridge->IsAccelerated());
+ }
+
+ {
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ CanvasColorParams());
+ PaintFlags flags;
+ bridge->Canvas()->drawRect(SkRect::MakeXYWH(0, 0, 1, 1), flags);
+ scoped_refptr<StaticBitmapImage> image =
+ bridge->NewImageSnapshot(kPreferNoAcceleration);
+ EXPECT_TRUE(bridge->IsValid());
+ EXPECT_FALSE(bridge->IsAccelerated());
+ }
}
TEST_F(Canvas2DLayerBridgeTest, FallbackToSoftwareIfContextLost) {
- FallbackToSoftwareIfContextLost();
+ gl_.SetIsContextLost(true);
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 150), Canvas2DLayerBridge::kEnableAcceleration,
+ CanvasColorParams());
+ EXPECT_TRUE(bridge->IsValid());
+ EXPECT_FALSE(bridge->IsAccelerated());
}
TEST_F(Canvas2DLayerBridgeTest, FallbackToSoftwareOnFailedTextureAlloc) {
- FallbackToSoftwareOnFailedTextureAlloc();
+ {
+ // No fallback case.
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 150), Canvas2DLayerBridge::kEnableAcceleration,
+ CanvasColorParams());
+ EXPECT_TRUE(bridge->IsValid());
+ EXPECT_TRUE(bridge->IsAccelerated());
+ scoped_refptr<StaticBitmapImage> snapshot =
+ bridge->NewImageSnapshot(kPreferAcceleration);
+ EXPECT_TRUE(bridge->IsAccelerated());
+ EXPECT_TRUE(snapshot->IsTextureBacked());
+ }
+
+ {
+ // Fallback case.
+ GrContext* gr = SharedGpuContext::ContextProviderWrapper()
+ ->ContextProvider()
+ ->GetGrContext();
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 150), Canvas2DLayerBridge::kEnableAcceleration,
+ CanvasColorParams());
+ EXPECT_TRUE(bridge->IsValid());
+ EXPECT_TRUE(bridge->IsAccelerated()); // We don't yet know that
+ // allocation will fail.
+ // This will cause SkSurface_Gpu creation to fail without
+ // Canvas2DLayerBridge otherwise detecting that anything was disabled.
+ gr->abandonContext();
+ scoped_refptr<StaticBitmapImage> snapshot =
+ bridge->NewImageSnapshot(kPreferAcceleration);
+ EXPECT_FALSE(bridge->IsAccelerated());
+ EXPECT_FALSE(snapshot->IsTextureBacked());
+ }
}
class MockLogger : public Canvas2DLayerBridge::Logger {
@@ -456,15 +408,7 @@ class MockLogger : public Canvas2DLayerBridge::Logger {
~MockLogger() override = default;
};
-class MockCanvasResourceHost : public CanvasResourceHost {
- public:
- void NotifyGpuContextLost() override {}
- void SetNeedsCompositingUpdate() override {}
- void UpdateMemoryUsage() override {}
- MOCK_CONST_METHOD1(RestoreCanvasMatrixClipStack, void(PaintCanvas*));
-};
-
-void DrawSomething(Canvas2DLayerBridgePtr& bridge) {
+void DrawSomething(Canvas2DLayerBridge* bridge) {
bridge->DidDraw(FloatRect(0, 0, 1, 1));
bridge->FinalizeFrame();
// Grabbing an image forces a flush
@@ -478,11 +422,12 @@ TEST_F(Canvas2DLayerBridgeTest, DISABLED_HibernationLifeCycle)
#endif
{
ScopedTestingPlatformSupport<FakePlatformSupport> platform;
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
- CanvasColorParams()));
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ CanvasColorParams());
bridge->DontUseIdleSchedulingForTesting();
- DrawSomething(bridge);
+ DrawSomething(bridge.get());
+ EXPECT_TRUE(bridge->IsAccelerated());
// Register an alternate Logger for tracking hibernation events
std::unique_ptr<MockLogger> mock_logger = std::make_unique<MockLogger>();
@@ -523,11 +468,11 @@ TEST_F(Canvas2DLayerBridgeTest, DISABLED_HibernationReEntry)
#endif
{
ScopedTestingPlatformSupport<FakePlatformSupport> platform;
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
- CanvasColorParams()));
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ CanvasColorParams());
bridge->DontUseIdleSchedulingForTesting();
- DrawSomething(bridge);
+ DrawSomething(bridge.get());
// Register an alternate Logger for tracking hibernation events
std::unique_ptr<MockLogger> mock_logger = std::make_unique<MockLogger>();
@@ -573,16 +518,14 @@ TEST_F(Canvas2DLayerBridgeTest,
#endif
{
ScopedTestingPlatformSupport<FakePlatformSupport> platform;
- MockCanvasResourceHost mock_host;
- EXPECT_CALL(mock_host, RestoreCanvasMatrixClipStack(_)).Times(AnyNumber());
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
- CanvasColorParams()));
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ CanvasColorParams());
+ EXPECT_CALL(*Host(), RestoreCanvasMatrixClipStack(_)).Times(AnyNumber());
- bridge->SetCanvasResourceHost(&mock_host);
bridge->DontUseIdleSchedulingForTesting();
- DrawSomething(bridge);
+ DrawSomething(bridge.get());
bridge->DisableDeferral(kDisableDeferralReasonUnknown);
// Register an alternate Logger for tracking hibernation events
@@ -598,7 +541,7 @@ TEST_F(Canvas2DLayerBridgeTest,
bridge->SetIsHidden(true);
platform->RunUntilIdle();
testing::Mock::VerifyAndClearExpectations(mock_logger_ptr);
- testing::Mock::VerifyAndClearExpectations(&mock_host);
+ testing::Mock::VerifyAndClearExpectations(host_.get());
EXPECT_FALSE(bridge->IsAccelerated());
EXPECT_TRUE(bridge->IsHibernating());
EXPECT_TRUE(bridge->IsValid());
@@ -607,11 +550,11 @@ TEST_F(Canvas2DLayerBridgeTest,
EXPECT_CALL(
*mock_logger_ptr,
ReportHibernationEvent(Canvas2DLayerBridge::kHibernationEndedNormally));
- EXPECT_CALL(mock_host, RestoreCanvasMatrixClipStack(_))
+ EXPECT_CALL(*Host(), RestoreCanvasMatrixClipStack(_))
.Times(AtLeast(1)); // Because deferred rendering is disabled
bridge->SetIsHidden(false);
testing::Mock::VerifyAndClearExpectations(mock_logger_ptr);
- testing::Mock::VerifyAndClearExpectations(&mock_host);
+ testing::Mock::VerifyAndClearExpectations(Host());
EXPECT_TRUE(bridge->IsAccelerated());
EXPECT_FALSE(bridge->IsHibernating());
EXPECT_TRUE(bridge->IsValid());
@@ -624,11 +567,11 @@ TEST_F(Canvas2DLayerBridgeTest, DISABLED_BackgroundRenderingWhileHibernating)
#endif
{
ScopedTestingPlatformSupport<FakePlatformSupport> platform;
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
- CanvasColorParams()));
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ CanvasColorParams());
bridge->DontUseIdleSchedulingForTesting();
- DrawSomething(bridge);
+ DrawSomething(bridge.get());
// Register an alternate Logger for tracking hibernation events
std::unique_ptr<MockLogger> mock_logger = std::make_unique<MockLogger>();
@@ -652,7 +595,7 @@ TEST_F(Canvas2DLayerBridgeTest, DISABLED_BackgroundRenderingWhileHibernating)
ReportHibernationEvent(
Canvas2DLayerBridge::
kHibernationEndedWithSwitchToBackgroundRendering));
- DrawSomething(bridge);
+ DrawSomething(bridge.get());
testing::Mock::VerifyAndClearExpectations(mock_logger_ptr);
EXPECT_FALSE(bridge->IsAccelerated());
EXPECT_FALSE(bridge->IsHibernating());
@@ -677,15 +620,12 @@ TEST_F(
#endif
{
ScopedTestingPlatformSupport<FakePlatformSupport> platform;
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
- CanvasColorParams()));
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ CanvasColorParams());
bridge->DontUseIdleSchedulingForTesting();
- DrawSomething(bridge);
- MockCanvasResourceHost mock_canvas_resource_host;
- EXPECT_CALL(mock_canvas_resource_host, RestoreCanvasMatrixClipStack(_))
- .Times(AnyNumber());
- bridge->SetCanvasResourceHost(&mock_canvas_resource_host);
+ DrawSomething(bridge.get());
+ EXPECT_CALL(*Host(), RestoreCanvasMatrixClipStack(_)).Times(AnyNumber());
bridge->DisableDeferral(kDisableDeferralReasonUnknown);
// Register an alternate Logger for tracking hibernation events
@@ -701,7 +641,7 @@ TEST_F(
bridge->SetIsHidden(true);
platform->RunUntilIdle();
testing::Mock::VerifyAndClearExpectations(mock_logger_ptr);
- testing::Mock::VerifyAndClearExpectations(&mock_canvas_resource_host);
+ testing::Mock::VerifyAndClearExpectations(Host());
EXPECT_FALSE(bridge->IsAccelerated());
EXPECT_TRUE(bridge->IsHibernating());
EXPECT_TRUE(bridge->IsValid());
@@ -711,21 +651,19 @@ TEST_F(
ReportHibernationEvent(
Canvas2DLayerBridge::
kHibernationEndedWithSwitchToBackgroundRendering));
- EXPECT_CALL(mock_canvas_resource_host, RestoreCanvasMatrixClipStack(_))
- .Times(AtLeast(1));
- DrawSomething(bridge);
+ EXPECT_CALL(*Host(), RestoreCanvasMatrixClipStack(_)).Times(AtLeast(1));
+ DrawSomething(bridge.get());
testing::Mock::VerifyAndClearExpectations(mock_logger_ptr);
- testing::Mock::VerifyAndClearExpectations(&mock_canvas_resource_host);
+ testing::Mock::VerifyAndClearExpectations(Host());
EXPECT_FALSE(bridge->IsAccelerated());
EXPECT_FALSE(bridge->IsHibernating());
EXPECT_TRUE(bridge->IsValid());
// Unhide
- EXPECT_CALL(mock_canvas_resource_host, RestoreCanvasMatrixClipStack(_))
- .Times(AtLeast(1));
+ EXPECT_CALL(*Host(), RestoreCanvasMatrixClipStack(_)).Times(AtLeast(1));
bridge->SetIsHidden(false);
testing::Mock::VerifyAndClearExpectations(mock_logger_ptr);
- testing::Mock::VerifyAndClearExpectations(&mock_canvas_resource_host);
+ testing::Mock::VerifyAndClearExpectations(Host());
EXPECT_TRUE(
bridge->IsAccelerated()); // Becoming visible causes switch back to GPU
EXPECT_FALSE(bridge->IsHibernating());
@@ -740,16 +678,13 @@ TEST_F(Canvas2DLayerBridgeTest,
#endif
{
ScopedTestingPlatformSupport<FakePlatformSupport> platform;
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
- CanvasColorParams()));
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ CanvasColorParams());
bridge->DontUseIdleSchedulingForTesting();
- DrawSomething(bridge);
+ DrawSomething(bridge.get());
- MockCanvasResourceHost mock_canvas_resource_host;
- EXPECT_CALL(mock_canvas_resource_host, RestoreCanvasMatrixClipStack(_))
- .Times(AnyNumber());
- bridge->SetCanvasResourceHost(&mock_canvas_resource_host);
+ EXPECT_CALL(*Host(), RestoreCanvasMatrixClipStack(_)).Times(AnyNumber());
// Register an alternate Logger for tracking hibernation events
std::unique_ptr<MockLogger> mock_logger = std::make_unique<MockLogger>();
@@ -764,7 +699,7 @@ TEST_F(Canvas2DLayerBridgeTest,
bridge->SetIsHidden(true);
platform->RunUntilIdle();
testing::Mock::VerifyAndClearExpectations(mock_logger_ptr);
- testing::Mock::VerifyAndClearExpectations(&mock_canvas_resource_host);
+ testing::Mock::VerifyAndClearExpectations(Host());
EXPECT_FALSE(bridge->IsAccelerated());
EXPECT_TRUE(bridge->IsHibernating());
EXPECT_TRUE(bridge->IsValid());
@@ -774,30 +709,27 @@ TEST_F(Canvas2DLayerBridgeTest,
ReportHibernationEvent(
Canvas2DLayerBridge::
kHibernationEndedWithSwitchToBackgroundRendering));
- EXPECT_CALL(mock_canvas_resource_host, RestoreCanvasMatrixClipStack(_))
- .Times(AtLeast(1));
+ EXPECT_CALL(*Host(), RestoreCanvasMatrixClipStack(_)).Times(AtLeast(1));
bridge->DisableDeferral(kDisableDeferralReasonUnknown);
testing::Mock::VerifyAndClearExpectations(mock_logger_ptr);
- testing::Mock::VerifyAndClearExpectations(&mock_canvas_resource_host);
+ testing::Mock::VerifyAndClearExpectations(Host());
EXPECT_FALSE(bridge->IsAccelerated());
EXPECT_FALSE(bridge->IsHibernating());
EXPECT_TRUE(bridge->IsValid());
// Unhide
- EXPECT_CALL(mock_canvas_resource_host, RestoreCanvasMatrixClipStack(_))
- .Times(AtLeast(1));
+ EXPECT_CALL(*Host(), RestoreCanvasMatrixClipStack(_)).Times(AtLeast(1));
bridge->SetIsHidden(false);
testing::Mock::VerifyAndClearExpectations(mock_logger_ptr);
- testing::Mock::VerifyAndClearExpectations(&mock_canvas_resource_host);
+ testing::Mock::VerifyAndClearExpectations(Host());
EXPECT_TRUE(
bridge->IsAccelerated()); // Becoming visible causes switch back to GPU
EXPECT_FALSE(bridge->IsHibernating());
EXPECT_TRUE(bridge->IsValid());
- EXPECT_CALL(mock_canvas_resource_host, RestoreCanvasMatrixClipStack(_))
- .Times(AnyNumber());
- bridge.Clear();
- testing::Mock::VerifyAndClearExpectations(&mock_canvas_resource_host);
+ EXPECT_CALL(*Host(), RestoreCanvasMatrixClipStack(_)).Times(AnyNumber());
+ bridge.reset();
+ testing::Mock::VerifyAndClearExpectations(Host());
}
#if CANVAS2D_HIBERNATION_ENABLED
@@ -807,11 +739,11 @@ TEST_F(Canvas2DLayerBridgeTest, DISABLED_TeardownWhileHibernating)
#endif
{
ScopedTestingPlatformSupport<FakePlatformSupport> platform;
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
- CanvasColorParams()));
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ CanvasColorParams());
bridge->DontUseIdleSchedulingForTesting();
- DrawSomething(bridge);
+ DrawSomething(bridge.get());
// Register an alternate Logger for tracking hibernation events
std::unique_ptr<MockLogger> mock_logger = std::make_unique<MockLogger>();
@@ -834,7 +766,7 @@ TEST_F(Canvas2DLayerBridgeTest, DISABLED_TeardownWhileHibernating)
EXPECT_CALL(*mock_logger_ptr,
ReportHibernationEvent(
Canvas2DLayerBridge::kHibernationEndedWithTeardown));
- bridge.Clear();
+ bridge.reset();
testing::Mock::VerifyAndClearExpectations(mock_logger_ptr);
}
@@ -845,11 +777,11 @@ TEST_F(Canvas2DLayerBridgeTest, DISABLED_SnapshotWhileHibernating)
#endif
{
ScopedTestingPlatformSupport<FakePlatformSupport> platform;
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
- CanvasColorParams()));
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ CanvasColorParams());
bridge->DontUseIdleSchedulingForTesting();
- DrawSomething(bridge);
+ DrawSomething(bridge.get());
// Register an alternate Logger for tracking hibernation events
std::unique_ptr<MockLogger> mock_logger = std::make_unique<MockLogger>();
@@ -894,11 +826,11 @@ TEST_F(Canvas2DLayerBridgeTest, DISABLED_TeardownWhileHibernationIsPending)
#endif
{
ScopedTestingPlatformSupport<FakePlatformSupport> platform;
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
- CanvasColorParams()));
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ CanvasColorParams());
bridge->DontUseIdleSchedulingForTesting();
- DrawSomething(bridge);
+ DrawSomething(bridge.get());
// Register an alternate Logger for tracking hibernation events
std::unique_ptr<MockLogger> mock_logger = std::make_unique<MockLogger>();
@@ -910,7 +842,7 @@ TEST_F(Canvas2DLayerBridgeTest, DISABLED_TeardownWhileHibernationIsPending)
*mock_logger_ptr,
ReportHibernationEvent(Canvas2DLayerBridge::kHibernationScheduled));
bridge->SetIsHidden(true);
- bridge.Clear();
+ bridge.reset();
// In production, we would expect a
// HibernationAbortedDueToDestructionWhileHibernatePending event to be
// fired, but that signal is lost in the unit test due to no longer having
@@ -928,11 +860,11 @@ TEST_F(Canvas2DLayerBridgeTest,
#endif
{
ScopedTestingPlatformSupport<FakePlatformSupport> platform;
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
- CanvasColorParams()));
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ CanvasColorParams());
bridge->DontUseIdleSchedulingForTesting();
- DrawSomething(bridge);
+ DrawSomething(bridge.get());
// Register an alternate Logger for tracking hibernation events
std::unique_ptr<MockLogger> mock_logger = std::make_unique<MockLogger>();
@@ -964,11 +896,11 @@ TEST_F(Canvas2DLayerBridgeTest, DISABLED_HibernationAbortedDueToLostContext)
#endif
{
ScopedTestingPlatformSupport<FakePlatformSupport> platform;
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
- CanvasColorParams()));
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ CanvasColorParams());
bridge->DontUseIdleSchedulingForTesting();
- DrawSomething(bridge);
+ DrawSomething(bridge.get());
// Register an alternate Logger for tracking hibernation events
std::unique_ptr<MockLogger> mock_logger = std::make_unique<MockLogger>();
@@ -999,11 +931,11 @@ TEST_F(Canvas2DLayerBridgeTest, DISABLED_PrepareMailboxWhileHibernating)
#endif
{
ScopedTestingPlatformSupport<FakePlatformSupport> platform;
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
- CanvasColorParams()));
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ CanvasColorParams());
bridge->DontUseIdleSchedulingForTesting();
- DrawSomething(bridge);
+ DrawSomething(bridge.get());
// Register an alternate Logger for tracking hibernation events
std::unique_ptr<MockLogger> mock_logger = std::make_unique<MockLogger>();
@@ -1031,7 +963,7 @@ TEST_F(Canvas2DLayerBridgeTest, DISABLED_PrepareMailboxWhileHibernating)
EXPECT_CALL(*mock_logger_ptr,
ReportHibernationEvent(
Canvas2DLayerBridge::kHibernationEndedWithTeardown));
- bridge.Clear();
+ bridge.reset();
testing::Mock::VerifyAndClearExpectations(mock_logger_ptr);
}
@@ -1042,10 +974,10 @@ TEST_F(Canvas2DLayerBridgeTest, DISABLED_PrepareMailboxWhileBackgroundRendering)
#endif
{
ScopedTestingPlatformSupport<FakePlatformSupport> platform;
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
- CanvasColorParams()));
- DrawSomething(bridge);
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ CanvasColorParams());
+ DrawSomething(bridge.get());
// Register an alternate Logger for tracking hibernation events
std::unique_ptr<MockLogger> mock_logger = std::make_unique<MockLogger>();
@@ -1068,7 +1000,7 @@ TEST_F(Canvas2DLayerBridgeTest, DISABLED_PrepareMailboxWhileBackgroundRendering)
ReportHibernationEvent(
Canvas2DLayerBridge::
kHibernationEndedWithSwitchToBackgroundRendering));
- DrawSomething(bridge);
+ DrawSomething(bridge.get());
testing::Mock::VerifyAndClearExpectations(mock_logger_ptr);
EXPECT_FALSE(bridge->IsAccelerated());
EXPECT_FALSE(bridge->IsHibernating());
@@ -1099,23 +1031,38 @@ TEST_F(Canvas2DLayerBridgeTest, GpuMemoryBufferRecycling) {
constexpr GLuint texture_id2 = 2;
constexpr GLuint image_id1 = 3;
constexpr GLuint image_id2 = 4;
+ const GLuint texture_target = gpu::GetPlatformSpecificTextureTarget();
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 150), 0, Canvas2DLayerBridge::kForceAccelerationForTesting,
- CanvasColorParams()));
+ std::unique_ptr<Canvas2DLayerBridge> bridge = MakeBridge(
+ IntSize(300, 150), Canvas2DLayerBridge::kForceAccelerationForTesting,
+ CanvasColorParams());
testing::Mock::VerifyAndClearExpectations(&gl_);
EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id1));
EXPECT_CALL(gl_, GenTextures(1, _)).WillOnce(SetArgPointee<1>(texture_id1));
- DrawSomething(bridge);
+ if (texture_target == GL_TEXTURE_EXTERNAL_OES) {
+ constexpr GLuint image_2d_id_for_copy = 17;
+ EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _))
+ .WillOnce(Return(image_2d_id_for_copy));
+ EXPECT_CALL(gl_, GenTextures(1, _));
+ EXPECT_CALL(gl_, DestroyImageCHROMIUM(image_2d_id_for_copy));
+ }
+ DrawSomething(bridge.get());
bridge->PrepareTransferableResource(nullptr, &resource1, &release_callback1);
testing::Mock::VerifyAndClearExpectations(&gl_);
EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id2));
EXPECT_CALL(gl_, GenTextures(1, _)).WillOnce(SetArgPointee<1>(texture_id2));
- DrawSomething(bridge);
+ if (texture_target == GL_TEXTURE_EXTERNAL_OES) {
+ constexpr GLuint image_2d_id_for_copy = 19;
+ EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _))
+ .WillOnce(Return(image_2d_id_for_copy));
+ EXPECT_CALL(gl_, GenTextures(1, _));
+ EXPECT_CALL(gl_, DestroyImageCHROMIUM(image_2d_id_for_copy));
+ }
+ DrawSomething(bridge.get());
bridge->PrepareTransferableResource(nullptr, &resource2, &release_callback2);
testing::Mock::VerifyAndClearExpectations(&gl_);
@@ -1142,7 +1089,7 @@ TEST_F(Canvas2DLayerBridgeTest, GpuMemoryBufferRecycling) {
EXPECT_CALL(gl_, DeleteTextures(1, Pointee(texture_id1))).Times(1);
EXPECT_CALL(gl_, DestroyImageCHROMIUM(image_id2)).Times(1);
EXPECT_CALL(gl_, DeleteTextures(1, Pointee(texture_id2))).Times(1);
- bridge.Clear();
+ bridge.reset();
testing::Mock::VerifyAndClearExpectations(&gl_);
}
@@ -1164,23 +1111,38 @@ TEST_F(Canvas2DLayerBridgeTest, NoGpuMemoryBufferRecyclingWhenPageHidden) {
constexpr GLuint texture_id2 = 2;
constexpr GLuint image_id1 = 3;
constexpr GLuint image_id2 = 4;
+ const GLuint texture_target = gpu::GetPlatformSpecificTextureTarget();
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 150), 0, Canvas2DLayerBridge::kForceAccelerationForTesting,
- CanvasColorParams()));
+ std::unique_ptr<Canvas2DLayerBridge> bridge = MakeBridge(
+ IntSize(300, 150), Canvas2DLayerBridge::kForceAccelerationForTesting,
+ CanvasColorParams());
testing::Mock::VerifyAndClearExpectations(&gl_);
EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id1));
EXPECT_CALL(gl_, GenTextures(1, _)).WillOnce(SetArgPointee<1>(texture_id1));
- DrawSomething(bridge);
+ if (texture_target == GL_TEXTURE_EXTERNAL_OES) {
+ constexpr GLuint image_2d_id_for_copy = 17;
+ EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _))
+ .WillOnce(Return(image_2d_id_for_copy));
+ EXPECT_CALL(gl_, GenTextures(1, _));
+ EXPECT_CALL(gl_, DestroyImageCHROMIUM(image_2d_id_for_copy));
+ }
+ DrawSomething(bridge.get());
bridge->PrepareTransferableResource(nullptr, &resource1, &release_callback1);
testing::Mock::VerifyAndClearExpectations(&gl_);
EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id2));
EXPECT_CALL(gl_, GenTextures(1, _)).WillOnce(SetArgPointee<1>(texture_id2));
- DrawSomething(bridge);
+ if (texture_target == GL_TEXTURE_EXTERNAL_OES) {
+ constexpr GLuint image_2d_id_for_copy = 19;
+ EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _))
+ .WillOnce(Return(image_2d_id_for_copy));
+ EXPECT_CALL(gl_, GenTextures(1, _));
+ EXPECT_CALL(gl_, DestroyImageCHROMIUM(image_2d_id_for_copy));
+ }
+ DrawSomething(bridge.get());
bridge->PrepareTransferableResource(nullptr, &resource2, &release_callback2);
testing::Mock::VerifyAndClearExpectations(&gl_);
@@ -1224,16 +1186,25 @@ TEST_F(Canvas2DLayerBridgeTest, ReleaseGpuMemoryBufferAfterBridgeDestroyed) {
std::unique_ptr<viz::SingleReleaseCallback> release_callback;
constexpr GLuint texture_id = 1;
constexpr GLuint image_id = 2;
+ const GLuint texture_target = gpu::GetPlatformSpecificTextureTarget();
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 150), 0, Canvas2DLayerBridge::kForceAccelerationForTesting,
- CanvasColorParams()));
+ std::unique_ptr<Canvas2DLayerBridge> bridge = MakeBridge(
+ IntSize(300, 150), Canvas2DLayerBridge::kForceAccelerationForTesting,
+ CanvasColorParams());
testing::Mock::VerifyAndClearExpectations(&gl_);
EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id));
EXPECT_CALL(gl_, GenTextures(1, _)).WillOnce(SetArgPointee<1>(texture_id));
- DrawSomething(bridge);
+
+ if (texture_target == GL_TEXTURE_EXTERNAL_OES) {
+ constexpr GLuint image_2d_id_for_copy = 17;
+ EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _))
+ .WillOnce(Return(image_2d_id_for_copy));
+ EXPECT_CALL(gl_, GenTextures(1, _));
+ EXPECT_CALL(gl_, DestroyImageCHROMIUM(image_2d_id_for_copy));
+ }
+ DrawSomething(bridge.get());
bridge->PrepareTransferableResource(nullptr, &resource, &release_callback);
testing::Mock::VerifyAndClearExpectations(&gl_);
@@ -1241,7 +1212,7 @@ TEST_F(Canvas2DLayerBridgeTest, ReleaseGpuMemoryBufferAfterBridgeDestroyed) {
// Tearing down the bridge does not destroy unreleased resources.
EXPECT_CALL(gl_, DestroyImageCHROMIUM(_)).Times(0);
EXPECT_CALL(gl_, DeleteTextures(_, _)).Times(0);
- bridge.Clear();
+ bridge.reset();
testing::Mock::VerifyAndClearExpectations(&gl_);
@@ -1259,9 +1230,9 @@ TEST_F(Canvas2DLayerBridgeTest, EnsureCCImageCacheUse) {
CanvasColorParams(kSRGBCanvasColorSpace, kF16CanvasPixelFormat, kOpaque);
ASSERT_FALSE(color_params.NeedsSkColorSpaceXformCanvas());
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
- color_params));
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ color_params);
gfx::ColorSpace expected_color_space = gfx::ColorSpace::CreateSRGB();
std::vector<cc::DrawImage> images = {
cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)),
@@ -1285,9 +1256,9 @@ TEST_F(Canvas2DLayerBridgeTest, EnsureCCImageCacheUseWithColorConversion) {
kRGBA8CanvasPixelFormat, kOpaque);
ASSERT_TRUE(color_params.NeedsSkColorSpaceXformCanvas());
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
- color_params));
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ color_params);
std::vector<cc::DrawImage> images = {
cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)),
SkIRect::MakeWH(10, 10), kNone_SkFilterQuality,
@@ -1309,9 +1280,9 @@ TEST_F(Canvas2DLayerBridgeTest, ImagesLockedUntilCacheLimit) {
// Disable deferral so we can inspect the cache state as we use the canvas.
auto color_params =
CanvasColorParams(kSRGBCanvasColorSpace, kF16CanvasPixelFormat, kOpaque);
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
- color_params));
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ color_params);
bridge->DisableDeferral(DisableDeferralReason::kDisableDeferralReasonUnknown);
std::vector<cc::DrawImage> images = {
@@ -1341,16 +1312,36 @@ TEST_F(Canvas2DLayerBridgeTest, ImagesLockedUntilCacheLimit) {
EXPECT_EQ(image_decode_cache_.num_locked_images(), 0);
}
+TEST_F(Canvas2DLayerBridgeTest, QueuesCleanupTaskForLockedImages) {
+ // Disable deferral so we can inspect the cache state as we use the canvas.
+ auto color_params =
+ CanvasColorParams(kSRGBCanvasColorSpace, kF16CanvasPixelFormat, kOpaque);
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ color_params);
+ bridge->DisableDeferral(DisableDeferralReason::kDisableDeferralReasonUnknown);
+
+ auto image =
+ cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)),
+ SkIRect::MakeWH(10, 10), kNone_SkFilterQuality,
+ SkMatrix::I(), 0u, color_params.GetStorageGfxColorSpace());
+ bridge->Canvas()->drawImage(image.paint_image(), 0u, 0u, nullptr);
+ EXPECT_EQ(image_decode_cache_.num_locked_images(), 1);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(image_decode_cache_.num_locked_images(), 0);
+}
+
TEST_F(Canvas2DLayerBridgeTest, ImageCacheOnContextLost) {
// Disable deferral so we use the raster canvas directly.
auto color_params =
CanvasColorParams(kSRGBCanvasColorSpace, kF16CanvasPixelFormat, kOpaque);
- Canvas2DLayerBridgePtr bridge(std::make_unique<Canvas2DLayerBridge>(
- IntSize(300, 300), 0, Canvas2DLayerBridge::kEnableAcceleration,
- color_params));
+ std::unique_ptr<Canvas2DLayerBridge> bridge =
+ MakeBridge(IntSize(300, 300), Canvas2DLayerBridge::kEnableAcceleration,
+ color_params);
bridge->DisableDeferral(DisableDeferralReason::kDisableDeferralReasonUnknown);
- cc::PaintFlags flags;
+ PaintFlags flags;
std::vector<cc::DrawImage> images = {
cc::DrawImage(cc::CreateDiscardablePaintImage(gfx::Size(10, 10)),
SkIRect::MakeWH(10, 10), kNone_SkFilterQuality,
@@ -1361,7 +1352,7 @@ TEST_F(Canvas2DLayerBridgeTest, ImageCacheOnContextLost) {
bridge->Canvas()->drawImage(images[0].paint_image(), 0u, 0u, nullptr);
// Lose the context and ensure that the image provider is not used.
- bridge->GetResourceProvider()->OnContextDestroyed();
+ bridge->ResourceProvider()->OnContextDestroyed();
// We should unref all images on the cache when the context is destroyed.
EXPECT_EQ(image_decode_cache_.num_locked_images(), 0);
image_decode_cache_.set_disallow_cache_use(true);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
index ad8322a4417..cbbafe32f1b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
@@ -43,32 +43,36 @@ CanvasColorParams::CanvasColorParams(CanvasColorSpace color_space,
pixel_format_(pixel_format),
opacity_mode_(opacity_mode) {}
-CanvasColorParams::CanvasColorParams(const SkImageInfo& info) {
+CanvasColorParams::CanvasColorParams(const sk_sp<SkColorSpace> color_space,
+ SkColorType color_type) {
color_space_ = kSRGBCanvasColorSpace;
pixel_format_ = kRGBA8CanvasPixelFormat;
// When there is no color space information, the SkImage is in legacy mode and
// the color type is kN32_SkColorType (which translates to kRGBA8 canvas pixel
// format).
- if (!info.colorSpace())
+ if (!color_space)
return;
// kSRGBCanvasColorSpace covers sRGB and linear-rgb. We need to check for
// Rec2020 and P3.
if (SkColorSpace::Equals(
- info.colorSpace(),
+ color_space.get(),
SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma,
SkColorSpace::kRec2020_Gamut)
.get()))
color_space_ = kRec2020CanvasColorSpace;
else if (SkColorSpace::Equals(
- info.colorSpace(),
+ color_space.get(),
SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma,
SkColorSpace::kDCIP3_D65_Gamut)
.get()))
color_space_ = kP3CanvasColorSpace;
- if (info.colorType() == kRGBA_F16_SkColorType)
+ if (color_type == kRGBA_F16_SkColorType)
pixel_format_ = kF16CanvasPixelFormat;
}
+CanvasColorParams::CanvasColorParams(const SkImageInfo& info)
+ : CanvasColorParams(info.refColorSpace(), info.colorType()) {}
+
void CanvasColorParams::SetCanvasColorSpace(CanvasColorSpace color_space) {
color_space_ = color_space;
}
@@ -192,17 +196,28 @@ gfx::BufferFormat CanvasColorParams::GetBufferFormat() const {
return kN32BufferFormat;
}
-GLenum CanvasColorParams::GLInternalFormat() const {
+GLenum CanvasColorParams::GLUnsizedInternalFormat() const {
// TODO(junov): try GL_RGB when opacity_mode_ == kOpaque
static_assert(kN32_SkColorType == kRGBA_8888_SkColorType ||
kN32_SkColorType == kBGRA_8888_SkColorType,
"Unexpected kN32_SkColorType value.");
- constexpr GLenum kN32GLInternalBufferFormat =
+ constexpr GLenum kN32GLUnsizedInternalBufferFormat =
kN32_SkColorType == kRGBA_8888_SkColorType ? GL_RGBA : GL_BGRA_EXT;
if (pixel_format_ == kF16CanvasPixelFormat)
return GL_RGBA;
- return kN32GLInternalBufferFormat;
+ return kN32GLUnsizedInternalBufferFormat;
+}
+
+GLenum CanvasColorParams::GLSizedInternalFormat() const {
+ static_assert(kN32_SkColorType == kRGBA_8888_SkColorType ||
+ kN32_SkColorType == kBGRA_8888_SkColorType,
+ "Unexpected kN32_SkColorType value.");
+ constexpr GLenum kN32GLSizedInternalBufferFormat =
+ kN32_SkColorType == kRGBA_8888_SkColorType ? GL_RGBA8 : GL_BGRA8_EXT;
+ if (pixel_format_ == kF16CanvasPixelFormat)
+ return GL_RGBA16F;
+ return kN32GLSizedInternalBufferFormat;
}
GLenum CanvasColorParams::GLType() const {
@@ -218,4 +233,17 @@ GLenum CanvasColorParams::GLType() const {
return GL_UNSIGNED_BYTE;
}
+viz::ResourceFormat CanvasColorParams::TransferableResourceFormat() const {
+ switch (pixel_format_) {
+ case kRGBA8CanvasPixelFormat:
+ return viz::RGBA_8888;
+ case kF16CanvasPixelFormat:
+ return viz::RGBA_F16;
+ default:
+ break;
+ }
+ NOTREACHED();
+ return viz::RGBA_8888;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.h b/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.h
index f3d91d44f93..5b433cd44e6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_color_params.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CANVAS_COLOR_PARAMS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CANVAS_COLOR_PARAMS_H_
+#include "components/viz/common/resources/resource_format.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/skia/include/core/SkColorSpace.h"
@@ -41,6 +42,8 @@ class PLATFORM_EXPORT CanvasColorParams {
// The default constructor will create an output-blended 8-bit surface.
CanvasColorParams();
CanvasColorParams(CanvasColorSpace, CanvasPixelFormat, OpacityMode);
+ explicit CanvasColorParams(const sk_sp<SkColorSpace> color_space,
+ SkColorType color_type);
explicit CanvasColorParams(const SkImageInfo&);
CanvasColorSpace ColorSpace() const { return color_space_; }
CanvasPixelFormat PixelFormat() const { return pixel_format_; }
@@ -85,9 +88,12 @@ class PLATFORM_EXPORT CanvasColorParams {
// Gpu memory buffer parameters
gfx::BufferFormat GetBufferFormat() const;
- uint32_t GLInternalFormat() const;
+ uint32_t GLSizedInternalFormat() const; // For GLES2, use Unsized
+ uint32_t GLUnsizedInternalFormat() const;
uint32_t GLType() const;
+ viz::ResourceFormat TransferableResourceFormat() const;
+
private:
CanvasColorSpace color_space_ = kSRGBCanvasColorSpace;
CanvasPixelFormat pixel_format_ = kRGBA8CanvasPixelFormat;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc
index a2c2b26f473..72b2aa728e9 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -4,40 +4,62 @@
#include "third_party/blink/renderer/platform/graphics/canvas_resource.h"
+#include "components/viz/common/resources/bitmap_allocation.h"
#include "components/viz/common/resources/single_release_callback.h"
#include "components/viz/common/resources/transferable_resource.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/skia/include/gpu/GrContext.h"
+#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/color_space.h"
namespace blink {
+// TODO(danakj): One day the gpu::mojom::Mailbox type should be shared with
+// blink directly and we won't need to use gpu::mojom::blink::Mailbox, nor the
+// conversion through WTF::Vector.
+gpu::mojom::blink::MailboxPtr SharedBitmapIdToGpuMailboxPtr(
+ const viz::SharedBitmapId& id) {
+ WTF::Vector<int8_t> name(GL_MAILBOX_SIZE_CHROMIUM);
+ for (int i = 0; i < GL_MAILBOX_SIZE_CHROMIUM; ++i)
+ name[i] = id.name[i];
+ return {base::in_place, name};
+}
+
CanvasResource::CanvasResource(base::WeakPtr<CanvasResourceProvider> provider,
SkFilterQuality filter_quality,
const CanvasColorParams& color_params)
: provider_(std::move(provider)),
filter_quality_(filter_quality),
- color_params_(color_params) {}
-
-CanvasResource::~CanvasResource() {
- // Sync token should have been waited on in sub-class implementation of
- // Abandon().
- DCHECK(!sync_token_for_release_.HasData());
-}
-
-bool CanvasResource::IsBitmap() {
- return false;
+ color_params_(color_params) {
+ thread_of_origin_ = Platform::Current()->CurrentThread()->ThreadId();
}
-scoped_refptr<StaticBitmapImage> CanvasResource::Bitmap() {
- NOTREACHED();
- return nullptr;
+CanvasResource::~CanvasResource() {
+#if DCHECK_IS_ON()
+ DCHECK(did_call_on_destroy_);
+#endif
+}
+
+void CanvasResource::OnDestroy() {
+ if (thread_of_origin_ != Platform::Current()->CurrentThread()->ThreadId()) {
+ // Destroyed on wrong thread. This can happen when the thread of origin was
+ // torn down, in which case the GPU context owning any underlying resources
+ // no longer exists.
+ Abandon();
+ } else {
+ TearDown();
+ }
+#if DCHECK_IS_ON()
+ did_call_on_destroy_ = true;
+#endif
}
gpu::gles2::GLES2Interface* CanvasResource::ContextGL() const {
@@ -46,16 +68,12 @@ gpu::gles2::GLES2Interface* CanvasResource::ContextGL() const {
return ContextProviderWrapper()->ContextProvider()->ContextGL();
}
-void CanvasResource::SetSyncTokenForRelease(const gpu::SyncToken& token) {
- sync_token_for_release_ = token;
-}
-
-void CanvasResource::WaitSyncTokenBeforeRelease() {
- auto* gl = ContextGL();
- if (sync_token_for_release_.HasData() && gl) {
- gl->WaitSyncTokenCHROMIUM(sync_token_for_release_.GetData());
+void CanvasResource::WaitSyncToken(const gpu::SyncToken& sync_token) {
+ if (sync_token.HasData()) {
+ auto* gl = ContextGL();
+ if (gl)
+ gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
}
- sync_token_for_release_.Clear();
}
static void ReleaseFrameResources(
@@ -63,7 +81,7 @@ static void ReleaseFrameResources(
scoped_refptr<CanvasResource> resource,
const gpu::SyncToken& sync_token,
bool lost_resource) {
- resource->SetSyncTokenForRelease(sync_token);
+ resource->WaitSyncToken(sync_token);
if (lost_resource) {
resource->Abandon();
}
@@ -74,18 +92,36 @@ static void ReleaseFrameResources(
bool CanvasResource::PrepareTransferableResource(
viz::TransferableResource* out_resource,
- std::unique_ptr<viz::SingleReleaseCallback>* out_callback) {
+ std::unique_ptr<viz::SingleReleaseCallback>* out_callback,
+ MailboxSyncMode sync_mode) {
DCHECK(IsValid());
- // This should never be called on unaccelerated canvases (for now).
+ DCHECK(out_callback);
+ scoped_refptr<CanvasResource> this_ref(this);
+ auto func = WTF::Bind(&ReleaseFrameResources, provider_,
+ WTF::Passed(std::move(this_ref)));
+ *out_callback = viz::SingleReleaseCallback::Create(std::move(func));
+
+ if (out_resource) {
+ if (SupportsAcceleratedCompositing()) {
+ return PrepareAcceleratedTransferableResource(out_resource, sync_mode);
+ }
- // Gpu compositing is a prerequisite for accelerated 2D canvas
- // TODO: For WebGL to use this, we must add software composing support.
+ return PrepareUnacceleratedTransferableResource(out_resource);
+ }
+ return true;
+}
+
+bool CanvasResource::PrepareAcceleratedTransferableResource(
+ viz::TransferableResource* out_resource,
+ MailboxSyncMode sync_mode) {
+ TRACE_EVENT0("blink",
+ "CanvasResource::PrepareAcceleratedTransferableResource");
+ // Gpu compositing is a prerequisite for compositing an accelerated resource
DCHECK(SharedGpuContext::IsGpuCompositingEnabled());
auto* gl = ContextGL();
DCHECK(gl);
-
- const gpu::Mailbox& mailbox = GetOrCreateGpuMailbox();
+ const gpu::Mailbox& mailbox = GetOrCreateGpuMailbox(sync_mode);
if (mailbox.IsZero())
return false;
@@ -94,11 +130,25 @@ bool CanvasResource::PrepareTransferableResource(
IsOverlayCandidate());
out_resource->color_space = color_params_.GetSamplerGfxColorSpace();
+ out_resource->format = color_params_.TransferableResourceFormat();
+ out_resource->read_lock_fences_enabled = NeedsReadLockFences();
+
+ return true;
+}
+
+bool CanvasResource::PrepareUnacceleratedTransferableResource(
+ viz::TransferableResource* out_resource) {
+ TRACE_EVENT0("blink",
+ "CanvasResource::PrepareUnacceleratedTransferableResource");
+ const gpu::Mailbox& mailbox = GetOrCreateGpuMailbox(kVerifiedSyncToken);
+ if (mailbox.IsZero())
+ return false;
+
+ *out_resource = viz::TransferableResource::MakeSoftware(
+ mailbox, gfx::Size(Size()), color_params_.TransferableResourceFormat());
+
+ out_resource->color_space = color_params_.GetSamplerGfxColorSpace();
- scoped_refptr<CanvasResource> this_ref(this);
- auto func = WTF::Bind(&ReleaseFrameResources, provider_,
- WTF::Passed(std::move(this_ref)));
- *out_callback = viz::SingleReleaseCallback::Create(std::move(func));
return true;
}
@@ -123,6 +173,10 @@ CanvasResourceBitmap::CanvasResourceBitmap(
: CanvasResource(std::move(provider), filter_quality, color_params),
image_(std::move(image)) {}
+CanvasResourceBitmap::~CanvasResourceBitmap() {
+ OnDestroy();
+}
+
scoped_refptr<CanvasResourceBitmap> CanvasResourceBitmap::Create(
scoped_refptr<StaticBitmapImage> image,
base::WeakPtr<CanvasResourceProvider> provider,
@@ -151,6 +205,9 @@ scoped_refptr<CanvasResource> CanvasResourceBitmap::MakeAccelerated(
context_provider_wrapper) {
if (IsAccelerated())
return base::WrapRefCounted(this);
+
+ TRACE_EVENT0("blink", "CanvasResourceBitmap::MakeAccelerated");
+
if (!context_provider_wrapper)
return nullptr;
scoped_refptr<StaticBitmapImage> accelerated_image =
@@ -168,6 +225,9 @@ scoped_refptr<CanvasResource> CanvasResourceBitmap::MakeAccelerated(
scoped_refptr<CanvasResource> CanvasResourceBitmap::MakeUnaccelerated() {
if (!IsAccelerated())
return base::WrapRefCounted(this);
+
+ TRACE_EVENT0("blink", "CanvasResourceBitmap::MakeUnaccelerated");
+
scoped_refptr<StaticBitmapImage> unaccelerated_image =
image_->MakeUnaccelerated();
// passing nullptr for the resource provider argument creates an orphan
@@ -179,10 +239,6 @@ scoped_refptr<CanvasResource> CanvasResourceBitmap::MakeUnaccelerated() {
}
void CanvasResourceBitmap::TearDown() {
- WaitSyncTokenBeforeRelease();
- // We must not disassociate the mailbox from the texture object here because
- // the texture may be recycled by skia and the associated cached mailbox
- // stored by GraphicsContext3DUtils.cpp must remain valid.
image_ = nullptr;
}
@@ -196,17 +252,14 @@ GLenum CanvasResourceBitmap::TextureTarget() const {
return GL_TEXTURE_2D;
}
-bool CanvasResourceBitmap::IsBitmap() {
- return true;
-}
-
scoped_refptr<StaticBitmapImage> CanvasResourceBitmap::Bitmap() {
return image_;
}
-const gpu::Mailbox& CanvasResourceBitmap::GetOrCreateGpuMailbox() {
+const gpu::Mailbox& CanvasResourceBitmap::GetOrCreateGpuMailbox(
+ MailboxSyncMode sync_mode) {
DCHECK(image_); // Calling code should check IsValid() before calling this.
- image_->EnsureMailbox(kUnverifiedSyncToken, GLFilter());
+ image_->EnsureMailbox(sync_mode, GLFilter());
return image_->GetMailbox();
}
@@ -214,11 +267,26 @@ bool CanvasResourceBitmap::HasGpuMailbox() const {
return image_ && image_->HasMailbox();
}
-const gpu::SyncToken& CanvasResourceBitmap::GetSyncToken() {
+const gpu::SyncToken CanvasResourceBitmap::GetSyncToken() {
DCHECK(image_); // Calling code should check IsValid() before calling this.
return image_->GetSyncToken();
}
+void CanvasResourceBitmap::Transfer() {
+ DCHECK(image_); // Calling code should check IsValid() before calling this.
+ return image_->Transfer();
+}
+
+bool CanvasResourceBitmap::OriginClean() const {
+ DCHECK(image_);
+ return image_->OriginClean();
+}
+
+void CanvasResourceBitmap::SetOriginClean(bool value) {
+ DCHECK(image_);
+ image_->SetOriginClean(value);
+}
+
base::WeakPtr<WebGraphicsContext3DProviderWrapper>
CanvasResourceBitmap::ContextProviderWrapper() const {
if (!image_)
@@ -226,6 +294,12 @@ CanvasResourceBitmap::ContextProviderWrapper() const {
return image_->ContextProviderWrapper();
}
+void CanvasResourceBitmap::TakeSkImage(sk_sp<SkImage> image) {
+ DCHECK(IsAccelerated() == image->isTextureBacked());
+ image_ =
+ StaticBitmapImage::Create(std::move(image), ContextProviderWrapper());
+}
+
// CanvasResourceGpuMemoryBuffer
//==============================================================================
@@ -234,44 +308,73 @@ CanvasResourceGpuMemoryBuffer::CanvasResourceGpuMemoryBuffer(
const CanvasColorParams& color_params,
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
base::WeakPtr<CanvasResourceProvider> provider,
- SkFilterQuality filter_quality)
- : CanvasResource(provider, filter_quality, color_params),
+ SkFilterQuality filter_quality,
+ bool is_accelerated)
+ : CanvasResource(std::move(provider), filter_quality, color_params),
context_provider_wrapper_(std::move(context_provider_wrapper)),
- color_params_(color_params) {
+ is_accelerated_(is_accelerated) {
if (!context_provider_wrapper_)
return;
auto* gl = context_provider_wrapper_->ContextProvider()->ContextGL();
auto* gr = context_provider_wrapper_->ContextProvider()->GetGrContext();
if (!gl || !gr)
return;
+
+ gfx::BufferUsage buffer_usage;
+ if (is_accelerated) {
+ buffer_usage = gfx::BufferUsage::SCANOUT;
+ } else {
+ buffer_usage = gfx::BufferUsage::SCANOUT_CPU_READ_WRITE;
+ }
+
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager =
Platform::Current()->GetGpuMemoryBufferManager();
if (!gpu_memory_buffer_manager)
return;
gpu_memory_buffer_ = gpu_memory_buffer_manager->CreateGpuMemoryBuffer(
- gfx::Size(size.Width(), size.Height()),
- color_params_.GetBufferFormat(), // Use format
- gfx::BufferUsage::SCANOUT, gpu::kNullSurfaceHandle);
+ gfx::Size(size.Width(), size.Height()), ColorParams().GetBufferFormat(),
+ buffer_usage, gpu::kNullSurfaceHandle);
if (!gpu_memory_buffer_) {
return;
}
+ gpu_memory_buffer_->SetColorSpace(color_params.GetStorageGfxColorSpace());
+
image_id_ = gl->CreateImageCHROMIUM(gpu_memory_buffer_->AsClientBuffer(),
size.Width(), size.Height(),
- color_params_.GLInternalFormat());
+ ColorParams().GLUnsizedInternalFormat());
if (!image_id_) {
gpu_memory_buffer_ = nullptr;
return;
}
-
- gpu_memory_buffer_->SetColorSpace(color_params.GetStorageGfxColorSpace());
gl->GenTextures(1, &texture_id_);
const GLenum target = TextureTarget();
gl->BindTexture(target, texture_id_);
+ // TODO(mcasas): consider making |image_id_| a local variable and balancing
+ // BindTexImage2DCHROMIUM() with DestroyImageCHROMIUM(), leaving |texture_id_|
+ // to keep alive the Image2DCHROMIUM.
gl->BindTexImage2DCHROMIUM(target, image_id_);
+
+ if (is_accelerated_ && target == GL_TEXTURE_EXTERNAL_OES) {
+ // We can't CopyTextureCHROMIUM() into a GL_TEXTURE_EXTERNAL_OES; create
+ // another image and bind a GL_TEXTURE_2D texture to it.
+ const GLuint image_2d_id_for_copy = gl->CreateImageCHROMIUM(
+ gpu_memory_buffer_->AsClientBuffer(), size.Width(), size.Height(),
+ ColorParams().GLUnsizedInternalFormat());
+
+ gl->GenTextures(1, &texture_2d_id_for_copy_);
+ gl->BindTexture(GL_TEXTURE_2D, texture_2d_id_for_copy_);
+ gl->BindTexImage2DCHROMIUM(GL_TEXTURE_2D, image_2d_id_for_copy);
+
+ gl->DestroyImageCHROMIUM(image_2d_id_for_copy);
+ }
}
CanvasResourceGpuMemoryBuffer::~CanvasResourceGpuMemoryBuffer() {
- TearDown();
+ OnDestroy();
+}
+
+bool CanvasResourceGpuMemoryBuffer::IsValid() const {
+ return !!context_provider_wrapper_ && image_id_;
}
GLenum CanvasResourceGpuMemoryBuffer::TextureTarget() const {
@@ -289,37 +392,55 @@ CanvasResourceGpuMemoryBuffer::Create(
const CanvasColorParams& color_params,
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
base::WeakPtr<CanvasResourceProvider> provider,
- SkFilterQuality filter_quality) {
+ SkFilterQuality filter_quality,
+ bool is_accelerated) {
+ TRACE_EVENT0("blink", "CanvasResourceGpuMemoryBuffer::Create");
+
scoped_refptr<CanvasResourceGpuMemoryBuffer> resource =
AdoptRef(new CanvasResourceGpuMemoryBuffer(
- size, color_params, std::move(context_provider_wrapper), provider,
- filter_quality));
+ size, color_params, std::move(context_provider_wrapper),
+ std::move(provider), filter_quality, is_accelerated));
if (resource->IsValid())
return resource;
return nullptr;
}
void CanvasResourceGpuMemoryBuffer::TearDown() {
- WaitSyncTokenBeforeRelease();
- if (!context_provider_wrapper_ || !image_id_)
- return;
- auto* gl = context_provider_wrapper_->ContextProvider()->ContextGL();
- if (gl && image_id_)
- gl->DestroyImageCHROMIUM(image_id_);
- if (gl && texture_id_)
- gl->DeleteTextures(1, &texture_id_);
+ // Unref should result in destruction.
+ DCHECK(!surface_ || surface_->unique());
+
+ surface_ = nullptr;
+ if (context_provider_wrapper_ && image_id_) {
+ auto* gl = ContextGL();
+ if (gl && image_id_)
+ gl->DestroyImageCHROMIUM(image_id_);
+ if (gl && texture_id_)
+ gl->DeleteTextures(1, &texture_id_);
+ if (gl && texture_2d_id_for_copy_)
+ gl->DeleteTextures(1, &texture_2d_id_for_copy_);
+ }
+ image_id_ = 0;
+ texture_id_ = 0;
+ texture_2d_id_for_copy_ = 0;
+ gpu_memory_buffer_ = nullptr;
+}
+
+void CanvasResourceGpuMemoryBuffer::Abandon() {
+ surface_ = nullptr;
image_id_ = 0;
texture_id_ = 0;
+ texture_2d_id_for_copy_ = 0;
gpu_memory_buffer_ = nullptr;
}
-const gpu::Mailbox& CanvasResourceGpuMemoryBuffer::GetOrCreateGpuMailbox() {
+const gpu::Mailbox& CanvasResourceGpuMemoryBuffer::GetOrCreateGpuMailbox(
+ MailboxSyncMode sync_mode) {
auto* gl = ContextGL();
DCHECK(gl); // caller should already have early exited if !gl.
if (gpu_mailbox_.IsZero() && gl) {
- gl->GenMailboxCHROMIUM(gpu_mailbox_.name);
gl->ProduceTextureDirectCHROMIUM(texture_id_, gpu_mailbox_.name);
mailbox_needs_new_sync_token_ = true;
+ mailbox_sync_mode_ = sync_mode;
}
return gpu_mailbox_;
}
@@ -328,12 +449,16 @@ bool CanvasResourceGpuMemoryBuffer::HasGpuMailbox() const {
return !gpu_mailbox_.IsZero();
}
-const gpu::SyncToken& CanvasResourceGpuMemoryBuffer::GetSyncToken() {
+const gpu::SyncToken CanvasResourceGpuMemoryBuffer::GetSyncToken() {
if (mailbox_needs_new_sync_token_) {
auto* gl = ContextGL();
DCHECK(gl); // caller should already have early exited if !gl.
mailbox_needs_new_sync_token_ = false;
- gl->GenUnverifiedSyncTokenCHROMIUM(sync_token_.GetData());
+ if (mailbox_sync_mode_ == kVerifiedSyncToken) {
+ gl->GenSyncTokenCHROMIUM(sync_token_.GetData());
+ } else {
+ gl->GenUnverifiedSyncTokenCHROMIUM(sync_token_.GetData());
+ }
}
return sync_token_;
}
@@ -341,19 +466,218 @@ const gpu::SyncToken& CanvasResourceGpuMemoryBuffer::GetSyncToken() {
void CanvasResourceGpuMemoryBuffer::CopyFromTexture(GLuint source_texture,
GLenum format,
GLenum type) {
+ DCHECK(is_accelerated_);
if (!IsValid())
return;
+ TRACE_EVENT0("blink", "CanvasResourceGpuMemoryBuffer::CopyFromTexture");
+ GLenum target = TextureTarget();
+ GLuint texture_id = texture_id_;
+
+ if (texture_2d_id_for_copy_) {
+ // We can't CopyTextureCHROMIUM() into a GL_TEXTURE_EXTERNAL_OES; use
+ // instead GL_TEXTURE_2D for the CopyTextureChromium().
+ target = GL_TEXTURE_2D;
+ texture_id = texture_2d_id_for_copy_;
+ }
+
ContextGL()->CopyTextureCHROMIUM(
- source_texture, 0 /*sourceLevel*/, TextureTarget(), texture_id_,
- 0 /*destLevel*/, format, type, false /*unpackFlipY*/,
- false /*unpackPremultiplyAlpha*/, false /*unpackUnmultiplyAlpha*/);
+ source_texture, 0 /*sourceLevel*/, target, texture_id, 0 /*destLevel*/,
+ format, type, false /*unpackFlipY*/, false /*unpackPremultiplyAlpha*/,
+ false /*unpackUnmultiplyAlpha*/);
+
mailbox_needs_new_sync_token_ = true;
}
+void CanvasResourceGpuMemoryBuffer::TakeSkImage(sk_sp<SkImage> image) {
+ TRACE_EVENT0("blink", "CanvasResourceGpuMemoryBuffer::CopyFromTexture");
+
+ WillPaint();
+ if (!surface_)
+ return;
+ surface_->getCanvas()->drawImage(image, 0, 0);
+ DidPaint();
+}
+
+void CanvasResourceGpuMemoryBuffer::WillPaint() {
+ if (!IsValid()) {
+ surface_ = nullptr;
+ return;
+ }
+
+ TRACE_EVENT1("blink", "CanvasResourceGpuMemoryBuffer::WillPaint",
+ "accelerated", is_accelerated_);
+
+ if (is_accelerated_) {
+ if (!surface_) { // When accelerated it is okay to re-use previous
+ // SkSurface
+ GrGLTextureInfo texture_info;
+ texture_info.fTarget = TextureTarget();
+ texture_info.fID = texture_id_;
+ texture_info.fFormat =
+ ColorParams().GLSizedInternalFormat(); // unsized format
+ GrBackendTexture backend_texture(Size().Width(), Size().Height(),
+ GrMipMapped::kNo, texture_info);
+ constexpr int sample_count = 0;
+ surface_ = SkSurface::MakeFromBackendTextureAsRenderTarget(
+ GetGrContext(), backend_texture, kTopLeft_GrSurfaceOrigin,
+ sample_count, ColorParams().GetSkColorType(),
+ ColorParams().GetSkColorSpace(), nullptr /*surface props*/);
+ }
+ } else {
+ gpu_memory_buffer_->Map();
+ void* buffer_base_address = gpu_memory_buffer_->memory(0);
+ if (!surface_ || buffer_base_address != buffer_base_address_) {
+ buffer_base_address_ = buffer_base_address;
+ SkImageInfo image_info = SkImageInfo::Make(
+ Size().Width(), Size().Height(), ColorParams().GetSkColorType(),
+ ColorParams().GetSkAlphaType(), ColorParams().GetSkColorSpace());
+ surface_ = SkSurface::MakeRasterDirect(image_info, buffer_base_address_,
+ gpu_memory_buffer_->stride(0));
+ }
+ }
+
+ DCHECK(surface_);
+}
+
+void CanvasResourceGpuMemoryBuffer::DidPaint() {
+ TRACE_EVENT1("blink", "CanvasResourceGpuMemoryBuffer::DidPaint",
+ "accelerated", is_accelerated_);
+
+ if (is_accelerated_) {
+ auto* gr = context_provider_wrapper_->ContextProvider()->GetGrContext();
+ if (gr)
+ gr->flush();
+ mailbox_needs_new_sync_token_ = true;
+ } else {
+ gpu_memory_buffer_->Unmap();
+ }
+}
+
base::WeakPtr<WebGraphicsContext3DProviderWrapper>
CanvasResourceGpuMemoryBuffer::ContextProviderWrapper() const {
return context_provider_wrapper_;
}
+scoped_refptr<StaticBitmapImage> CanvasResourceGpuMemoryBuffer::Bitmap() {
+ WillPaint();
+ scoped_refptr<StaticBitmapImage> bitmap = StaticBitmapImage::Create(
+ surface_->makeImageSnapshot(), ContextProviderWrapper());
+ DidPaint();
+ bitmap->SetOriginClean(is_origin_clean_);
+ return bitmap;
+}
+
+// CanvasResourceSharedBitmap
+//==============================================================================
+
+CanvasResourceSharedBitmap::CanvasResourceSharedBitmap(
+ const IntSize& size,
+ const CanvasColorParams& color_params,
+ base::WeakPtr<CanvasResourceProvider> provider,
+ SkFilterQuality filter_quality)
+ : CanvasResource(std::move(provider), filter_quality, color_params),
+ size_(size) {
+ shared_memory_ = viz::bitmap_allocation::AllocateMappedBitmap(
+ gfx::Size(Size()), ColorParams().TransferableResourceFormat());
+
+ if (!IsValid())
+ return;
+
+ shared_bitmap_id_ = viz::SharedBitmap::GenerateId();
+
+ CanvasResourceDispatcher* resource_dispatcher =
+ Provider() ? Provider()->ResourceDispatcher() : nullptr;
+ if (resource_dispatcher) {
+ resource_dispatcher->DidAllocateSharedBitmap(
+ viz::bitmap_allocation::DuplicateAndCloseMappedBitmap(
+ shared_memory_.get(), gfx::Size(Size()),
+ ColorParams().TransferableResourceFormat()),
+ SharedBitmapIdToGpuMailboxPtr(shared_bitmap_id_));
+ }
+}
+
+CanvasResourceSharedBitmap::~CanvasResourceSharedBitmap() {
+ OnDestroy();
+}
+
+bool CanvasResourceSharedBitmap::IsValid() const {
+ return !!shared_memory_;
+}
+
+IntSize CanvasResourceSharedBitmap::Size() const {
+ return size_;
+}
+
+scoped_refptr<StaticBitmapImage> CanvasResourceSharedBitmap::Bitmap() {
+ if (!IsValid())
+ return nullptr;
+ // Construct an SkImage that references the shared memory buffer.
+ // The release callback holds a reference to |this| to ensure that the
+ // canvas resource that owns the shared memory stays alive at least until
+ // the SkImage is destroyed.
+ SkImageInfo image_info = SkImageInfo::Make(
+ Size().Width(), Size().Height(), ColorParams().GetSkColorType(),
+ ColorParams().GetSkAlphaType(), ColorParams().GetSkColorSpace());
+ SkPixmap pixmap(image_info, shared_memory_->memory(),
+ image_info.minRowBytes());
+ this->AddRef();
+ sk_sp<SkImage> sk_image = SkImage::MakeFromRaster(
+ pixmap,
+ [](const void*, SkImage::ReleaseContext resource_to_unref) {
+ static_cast<CanvasResourceSharedBitmap*>(resource_to_unref)->Release();
+ },
+ this);
+ auto image = StaticBitmapImage::Create(sk_image);
+ image->SetOriginClean(is_origin_clean_);
+ return image;
+}
+
+scoped_refptr<CanvasResourceSharedBitmap> CanvasResourceSharedBitmap::Create(
+ const IntSize& size,
+ const CanvasColorParams& color_params,
+ base::WeakPtr<CanvasResourceProvider> provider,
+ SkFilterQuality filter_quality) {
+ scoped_refptr<CanvasResourceSharedBitmap> resource =
+ AdoptRef(new CanvasResourceSharedBitmap(
+ size, color_params, std::move(provider), filter_quality));
+ if (resource->IsValid())
+ return resource;
+ return nullptr;
+}
+
+void CanvasResourceSharedBitmap::TearDown() {
+ CanvasResourceDispatcher* resource_dispatcher =
+ Provider() ? Provider()->ResourceDispatcher() : nullptr;
+ if (resource_dispatcher && !shared_bitmap_id_.IsZero()) {
+ resource_dispatcher->DidDeleteSharedBitmap(
+ SharedBitmapIdToGpuMailboxPtr(shared_bitmap_id_));
+ }
+ shared_memory_ = nullptr;
+}
+
+void CanvasResourceSharedBitmap::Abandon() {
+ shared_memory_ = nullptr;
+}
+
+const gpu::Mailbox& CanvasResourceSharedBitmap::GetOrCreateGpuMailbox(
+ MailboxSyncMode sync_mode) {
+ return shared_bitmap_id_;
+}
+
+bool CanvasResourceSharedBitmap::HasGpuMailbox() const {
+ return !shared_bitmap_id_.IsZero();
+}
+
+void CanvasResourceSharedBitmap::TakeSkImage(sk_sp<SkImage> image) {
+ SkImageInfo image_info = SkImageInfo::Make(
+ Size().Width(), Size().Height(), ColorParams().GetSkColorType(),
+ ColorParams().GetSkAlphaType(),
+ ColorParams().GetSkColorSpaceForSkSurfaces());
+
+ bool read_pixels_successful = image->readPixels(
+ image_info, shared_memory_->memory(), image_info.minRowBytes(), 0, 0);
+ DCHECK(read_pixels_successful);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.h b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.h
index 69f6a596359..9c2fac8f64f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource.h
@@ -2,14 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/logging.h"
#include "base/memory/weak_ptr.h"
+#include "components/viz/common/resources/shared_bitmap.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/sync_token.h"
+#include "gpu/ipc/common/mailbox.mojom-blink.h"
+#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/graphics/canvas_color_params.h"
#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_wrapper.h"
-#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
+#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CANVAS_RESOURCE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CANVAS_RESOURCE_H_
@@ -20,6 +24,12 @@ class GpuMemoryBuffer;
} // namespace gfx
+namespace base {
+
+class SharedMemory;
+
+} // namespace base
+
namespace viz {
class SingleReleaseCallback;
@@ -32,51 +42,79 @@ namespace blink {
class CanvasResourceProvider;
class StaticBitmapImage;
+// TODO(danakj): One day the gpu::mojom::Mailbox type should be shared with
+// blink directly and we won't need to use gpu::mojom::blink::Mailbox, nor the
+// conversion through WTF::Vector.
+gpu::mojom::blink::MailboxPtr SharedBitmapIdToGpuMailboxPtr(
+ const viz::SharedBitmapId& id);
+
// Generic resource interface, used for locking (RAII) and recycling pixel
// buffers of any type.
-class PLATFORM_EXPORT CanvasResource : public WTF::RefCounted<CanvasResource> {
+class PLATFORM_EXPORT CanvasResource
+ : public WTF::ThreadSafeRefCounted<CanvasResource> {
public:
virtual ~CanvasResource();
- virtual void Abandon() = 0;
+ virtual void Abandon() { TearDown(); }
virtual bool IsRecycleable() const = 0;
virtual bool IsAccelerated() const = 0;
+ virtual bool SupportsAcceleratedCompositing() const = 0;
virtual bool IsValid() const = 0;
+ virtual bool NeedsReadLockFences() const { return false; }
virtual IntSize Size() const = 0;
- virtual const gpu::Mailbox& GetOrCreateGpuMailbox() = 0;
- virtual const gpu::SyncToken& GetSyncToken() = 0;
- bool PrepareTransferableResource(
- viz::TransferableResource* out_resource,
- std::unique_ptr<viz::SingleReleaseCallback>* out_callback);
- void SetSyncTokenForRelease(const gpu::SyncToken&);
+ virtual const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) = 0;
+ virtual void Transfer() {}
+ virtual const gpu::SyncToken GetSyncToken() {
+ NOTREACHED();
+ return gpu::SyncToken();
+ }
+ bool PrepareTransferableResource(viz::TransferableResource*,
+ std::unique_ptr<viz::SingleReleaseCallback>*,
+ MailboxSyncMode);
+ void WaitSyncToken(const gpu::SyncToken&);
virtual scoped_refptr<CanvasResource> MakeAccelerated(
base::WeakPtr<WebGraphicsContext3DProviderWrapper>) = 0;
virtual scoped_refptr<CanvasResource> MakeUnaccelerated() = 0;
- virtual bool IsBitmap();
- virtual scoped_refptr<StaticBitmapImage> Bitmap();
- void WaitSyncTokenBeforeRelease();
+ virtual bool OriginClean() const = 0;
+ virtual void SetOriginClean(bool) = 0;
+ virtual scoped_refptr<StaticBitmapImage> Bitmap() = 0;
virtual void CopyFromTexture(GLuint source_texture,
GLenum format,
GLenum type) {
NOTREACHED();
}
+ // Only CanvasResourceProvider and derivatives should call this.
+ virtual void TakeSkImage(sk_sp<SkImage> image) = 0;
+
protected:
CanvasResource(base::WeakPtr<CanvasResourceProvider>,
SkFilterQuality,
const CanvasColorParams&);
- virtual GLenum TextureTarget() const = 0;
+
+ virtual GLenum TextureTarget() const {
+ NOTREACHED();
+ return 0;
+ }
virtual bool IsOverlayCandidate() const { return false; }
virtual bool HasGpuMailbox() const = 0;
+ virtual void TearDown() = 0;
gpu::gles2::GLES2Interface* ContextGL() const;
GLenum GLFilter() const;
GrContext* GetGrContext() const;
virtual base::WeakPtr<WebGraphicsContext3DProviderWrapper>
- ContextProviderWrapper() const = 0;
- void PrepareTransferableResourceCommon(
+ ContextProviderWrapper() const {
+ NOTREACHED();
+ return nullptr;
+ }
+ bool PrepareAcceleratedTransferableResource(
viz::TransferableResource* out_resource,
- std::unique_ptr<viz::SingleReleaseCallback>* out_callback);
+ MailboxSyncMode);
+ bool PrepareUnacceleratedTransferableResource(
+ viz::TransferableResource* out_resource);
SkFilterQuality FilterQuality() const { return filter_quality_; }
const CanvasColorParams& ColorParams() const { return color_params_; }
+ void OnDestroy();
+ CanvasResourceProvider* Provider() { return provider_.get(); }
private:
// Sync token that was provided when resource was released
@@ -84,6 +122,10 @@ class PLATFORM_EXPORT CanvasResource : public WTF::RefCounted<CanvasResource> {
base::WeakPtr<CanvasResourceProvider> provider_;
SkFilterQuality filter_quality_;
CanvasColorParams color_params_;
+ blink::PlatformThreadId thread_of_origin_;
+#if DCHECK_IS_ON()
+ bool did_call_on_destroy_ = false;
+#endif
};
// Resource type for skia Bitmaps (RAM and texture backed)
@@ -94,29 +136,34 @@ class PLATFORM_EXPORT CanvasResourceBitmap final : public CanvasResource {
base::WeakPtr<CanvasResourceProvider>,
SkFilterQuality,
const CanvasColorParams&);
- ~CanvasResourceBitmap() override { Abandon(); }
+ ~CanvasResourceBitmap() override;
// Not recyclable: Skia handles texture recycling internally and bitmaps are
// cheap to allocate.
bool IsRecycleable() const final { return false; }
bool IsAccelerated() const final;
+ bool SupportsAcceleratedCompositing() const override {
+ return IsAccelerated();
+ }
bool IsValid() const final;
- void Abandon() final { TearDown(); }
IntSize Size() const final;
- bool IsBitmap() final;
+ void Transfer() final;
scoped_refptr<StaticBitmapImage> Bitmap() final;
+ bool OriginClean() const final;
+ void SetOriginClean(bool value) final;
scoped_refptr<CanvasResource> MakeAccelerated(
base::WeakPtr<WebGraphicsContext3DProviderWrapper>) final;
scoped_refptr<CanvasResource> MakeUnaccelerated() final;
+ void TakeSkImage(sk_sp<SkImage> image) final;
private:
- void TearDown();
+ void TearDown() override;
GLenum TextureTarget() const final;
base::WeakPtr<WebGraphicsContext3DProviderWrapper> ContextProviderWrapper()
const override;
- const gpu::Mailbox& GetOrCreateGpuMailbox() override;
+ const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) override;
bool HasGpuMailbox() const override;
- const gpu::SyncToken& GetSyncToken() override;
+ const gpu::SyncToken GetSyncToken() override;
CanvasResourceBitmap(scoped_refptr<StaticBitmapImage>,
base::WeakPtr<CanvasResourceProvider>,
@@ -135,52 +182,120 @@ class PLATFORM_EXPORT CanvasResourceGpuMemoryBuffer final
const CanvasColorParams&,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
base::WeakPtr<CanvasResourceProvider>,
- SkFilterQuality);
+ SkFilterQuality,
+ bool is_accelerated);
~CanvasResourceGpuMemoryBuffer() override;
bool IsRecycleable() const final { return IsValid(); }
- bool IsAccelerated() const final { return true; }
- bool IsValid() const override {
- return context_provider_wrapper_ && image_id_;
- }
+ bool IsAccelerated() const final { return is_accelerated_; }
+ bool IsValid() const override;
+ bool SupportsAcceleratedCompositing() const override { return true; }
+ bool NeedsReadLockFences() const final { return true; }
+ bool OriginClean() const final { return is_origin_clean_; }
+ void SetOriginClean(bool value) final { is_origin_clean_ = value; }
scoped_refptr<CanvasResource> MakeAccelerated(
base::WeakPtr<WebGraphicsContext3DProviderWrapper>) final {
- return base::WrapRefCounted(this);
+ NOTREACHED();
+ return nullptr;
};
scoped_refptr<CanvasResource> MakeUnaccelerated() final {
NOTREACHED();
return nullptr;
}
- void Abandon() final { TearDown(); }
+ void Abandon() final;
IntSize Size() const final;
+ void TakeSkImage(sk_sp<SkImage> image) final;
+ void CopyFromTexture(GLuint source_texture,
+ GLenum format,
+ GLenum type) override;
+ scoped_refptr<StaticBitmapImage> Bitmap() override;
private:
- void TearDown();
+ void TearDown() override;
GLenum TextureTarget() const final;
bool IsOverlayCandidate() const final { return true; }
- const gpu::Mailbox& GetOrCreateGpuMailbox() override;
+ const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) override;
bool HasGpuMailbox() const override;
- const gpu::SyncToken& GetSyncToken() override;
+ const gpu::SyncToken GetSyncToken() override;
base::WeakPtr<WebGraphicsContext3DProviderWrapper> ContextProviderWrapper()
const override;
- void CopyFromTexture(GLuint source_texture,
- GLenum format,
- GLenum type) override;
+ void WillPaint();
+ void DidPaint();
CanvasResourceGpuMemoryBuffer(
const IntSize&,
const CanvasColorParams&,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
base::WeakPtr<CanvasResourceProvider>,
- SkFilterQuality);
+ SkFilterQuality,
+ bool is_accelerated);
gpu::Mailbox gpu_mailbox_;
gpu::SyncToken sync_token_;
bool mailbox_needs_new_sync_token_ = false;
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper_;
std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer_;
+ void* buffer_base_address_ = nullptr;
+ sk_sp<SkSurface> surface_;
GLuint image_id_ = 0;
GLuint texture_id_ = 0;
- CanvasColorParams color_params_;
+ MailboxSyncMode mailbox_sync_mode_ = kVerifiedSyncToken;
+ bool is_accelerated_;
+ bool is_origin_clean_ = true;
+
+ // GL_TEXTURE_2D view of |gpu_memory_buffer_| for CopyFromTexture(); only used
+ // if TextureTarget() is GL_TEXTURE_EXTERNAL_OES.
+ GLuint texture_2d_id_for_copy_ = 0;
+};
+
+// Resource type for SharedBitmaps
+class PLATFORM_EXPORT CanvasResourceSharedBitmap final : public CanvasResource {
+ public:
+ static scoped_refptr<CanvasResourceSharedBitmap> Create(
+ const IntSize&,
+ const CanvasColorParams&,
+ base::WeakPtr<CanvasResourceProvider>,
+ SkFilterQuality);
+ ~CanvasResourceSharedBitmap() override;
+ bool IsRecycleable() const final { return IsValid(); }
+ bool IsAccelerated() const final { return false; }
+ bool IsValid() const final;
+ bool SupportsAcceleratedCompositing() const final { return false; }
+ bool NeedsReadLockFences() const final { return false; }
+ scoped_refptr<CanvasResource> MakeAccelerated(
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper>) final {
+ NOTREACHED();
+ return nullptr;
+ };
+ scoped_refptr<CanvasResource> MakeUnaccelerated() final {
+ NOTREACHED();
+ return nullptr;
+ }
+ void Abandon() final;
+ IntSize Size() const final;
+ void TakeSkImage(sk_sp<SkImage> image) final;
+ void CopyFromTexture(GLuint source_texture,
+ GLenum format,
+ GLenum type) override {
+ NOTREACHED();
+ }
+ scoped_refptr<StaticBitmapImage> Bitmap() final;
+ bool OriginClean() const final { return is_origin_clean_; }
+ void SetOriginClean(bool flag) final { is_origin_clean_ = flag; }
+
+ private:
+ void TearDown() override;
+ const gpu::Mailbox& GetOrCreateGpuMailbox(MailboxSyncMode) override;
+ bool HasGpuMailbox() const override;
+
+ CanvasResourceSharedBitmap(const IntSize&,
+ const CanvasColorParams&,
+ base::WeakPtr<CanvasResourceProvider>,
+ SkFilterQuality);
+
+ viz::SharedBitmapId shared_bitmap_id_;
+ std::unique_ptr<base::SharedMemory> shared_memory_;
+ IntSize size_;
+ bool is_origin_clean_ = true;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
new file mode 100644
index 00000000000..829faff22c6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.cc
@@ -0,0 +1,488 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h"
+
+#include <memory>
+#include "base/single_thread_task_runner.h"
+#include "components/viz/common/quads/compositor_frame.h"
+#include "components/viz/common/quads/texture_draw_quad.h"
+#include "components/viz/common/resources/resource_format.h"
+#include "third_party/blink/public/platform/interface_provider.h"
+#include "third_party/blink/public/platform/modules/frame_sinks/embedded_frame_sink.mojom-blink.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
+#include "third_party/blink/renderer/platform/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/graphics/canvas_resource.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
+#include "third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.h"
+#include "third_party/blink/renderer/platform/histogram.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
+#include "third_party/blink/renderer/platform/web_task_runner.h"
+
+namespace blink {
+
+enum {
+ kMaxPendingCompositorFrames = 2,
+ kMaxUnreclaimedPlaceholderFrames = 3,
+};
+
+CanvasResourceDispatcher::CanvasResourceDispatcher(
+ CanvasResourceDispatcherClient* client,
+ uint32_t client_id,
+ uint32_t sink_id,
+ int canvas_id,
+ const IntSize& size)
+ : frame_sink_id_(viz::FrameSinkId(client_id, sink_id)),
+ size_(size),
+ change_size_for_next_commit_(false),
+ needs_begin_frame_(false),
+ binding_(this),
+ placeholder_canvas_id_(canvas_id),
+ num_unreclaimed_frames_posted_(0),
+ client_(client),
+ weak_ptr_factory_(this) {
+ if (frame_sink_id_.is_valid()) {
+ // Only frameless canvas pass an invalid frame sink id; we don't create
+ // mojo channel for this special case.
+ DCHECK(!sink_.is_bound());
+ mojom::blink::EmbeddedFrameSinkProviderPtr provider;
+ Platform::Current()->GetInterfaceProvider()->GetInterface(
+ mojo::MakeRequest(&provider));
+ DCHECK(provider);
+
+ binding_.Bind(mojo::MakeRequest(&client_ptr_));
+ provider->CreateCompositorFrameSink(frame_sink_id_, std::move(client_ptr_),
+ mojo::MakeRequest(&sink_));
+ }
+ offscreen_canvas_resource_provider_ =
+ std::make_unique<OffscreenCanvasResourceProvider>(size_.Width(),
+ size_.Height(), this);
+}
+
+CanvasResourceDispatcher::~CanvasResourceDispatcher() = default;
+
+namespace {
+
+void UpdatePlaceholderImage(
+ base::WeakPtr<CanvasResourceDispatcher> dispatcher,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ int placeholder_canvas_id,
+ scoped_refptr<blink::CanvasResource> image,
+ viz::ResourceId resource_id) {
+ DCHECK(IsMainThread());
+ OffscreenCanvasPlaceholder* placeholder_canvas =
+ OffscreenCanvasPlaceholder::GetPlaceholderById(placeholder_canvas_id);
+ if (placeholder_canvas) {
+ placeholder_canvas->SetPlaceholderFrame(
+ std::move(image), std::move(dispatcher), std::move(task_runner),
+ resource_id);
+ }
+}
+
+} // namespace
+
+void CanvasResourceDispatcher::PostImageToPlaceholderIfNotBlocked(
+ scoped_refptr<CanvasResource> image,
+ viz::ResourceId resource_id) {
+ if (placeholder_canvas_id_ == kInvalidPlaceholderCanvasId) {
+ offscreen_canvas_resource_provider_->ReclaimResource(resource_id);
+ return;
+ }
+ // Determines whether the main thread may be blocked. If unblocked, post the
+ // image. Otherwise, save the image and do not post it.
+ if (num_unreclaimed_frames_posted_ < kMaxUnreclaimedPlaceholderFrames) {
+ this->PostImageToPlaceholder(std::move(image), resource_id);
+ num_unreclaimed_frames_posted_++;
+ } else {
+ DCHECK(num_unreclaimed_frames_posted_ == kMaxUnreclaimedPlaceholderFrames);
+ if (latest_unposted_image_) {
+ // The previous unposted image becomes obsolete now.
+ offscreen_canvas_resource_provider_->ReclaimResource(
+ latest_unposted_resource_id_);
+ }
+
+ latest_unposted_image_ = std::move(image);
+ latest_unposted_resource_id_ = resource_id;
+ }
+}
+
+void CanvasResourceDispatcher::PostImageToPlaceholder(
+ scoped_refptr<CanvasResource> image,
+ viz::ResourceId resource_id) {
+ scoped_refptr<base::SingleThreadTaskRunner> dispatcher_task_runner =
+ Platform::Current()->CurrentThread()->GetTaskRunner();
+
+ // After this point, |image| can only be used on the main thread, until it
+ // is returned.
+ image->Transfer();
+
+ PostCrossThreadTask(
+ *Platform::Current()->MainThread()->Scheduler()->CompositorTaskRunner(),
+ FROM_HERE,
+ CrossThreadBind(UpdatePlaceholderImage, this->GetWeakPtr(),
+ WTF::Passed(std::move(dispatcher_task_runner)),
+ placeholder_canvas_id_, std::move(image), resource_id));
+}
+
+void CanvasResourceDispatcher::DispatchFrameSync(
+ scoped_refptr<StaticBitmapImage> image,
+ base::TimeTicks commit_start_time,
+ const SkIRect& damage_rect) {
+ scoped_refptr<CanvasResource> canvas_resource = CanvasResourceBitmap::Create(
+ std::move(image),
+ nullptr, // Resource provider not specified -> recycling will not work
+ kLow_SkFilterQuality, CanvasColorParams());
+
+ viz::CompositorFrame frame;
+ if (!PrepareFrame(std::move(canvas_resource), commit_start_time, damage_rect,
+ &frame))
+ return;
+
+ pending_compositor_frames_++;
+ WTF::Vector<viz::ReturnedResource> resources;
+ sink_->SubmitCompositorFrameSync(
+ parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
+ std::move(frame), nullptr, 0, &resources);
+ DidReceiveCompositorFrameAck(resources);
+}
+
+void CanvasResourceDispatcher::DispatchFrame(
+ scoped_refptr<StaticBitmapImage> image,
+ base::TimeTicks commit_start_time,
+ const SkIRect& damage_rect) {
+ scoped_refptr<CanvasResource> canvas_resource = CanvasResourceBitmap::Create(
+ std::move(image),
+ nullptr, // Resource provider not specified -> recycling will not work
+ kLow_SkFilterQuality, CanvasColorParams());
+
+ viz::CompositorFrame frame;
+ if (!PrepareFrame(std::move(canvas_resource), commit_start_time, damage_rect,
+ &frame))
+ return;
+
+ pending_compositor_frames_++;
+ sink_->SubmitCompositorFrame(
+ parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
+ std::move(frame), nullptr, 0);
+}
+
+bool CanvasResourceDispatcher::PrepareFrame(
+ scoped_refptr<CanvasResource> canvas_resource,
+ base::TimeTicks commit_start_time,
+ const SkIRect& damage_rect,
+ viz::CompositorFrame* frame) {
+ if (!canvas_resource || !VerifyImageSize(canvas_resource->Size()))
+ return false;
+
+ offscreen_canvas_resource_provider_->IncNextResourceId();
+
+ // For frameless canvas, we don't get a valid frame_sink_id and should drop.
+ if (!frame_sink_id_.is_valid()) {
+ PostImageToPlaceholderIfNotBlocked(
+ std::move(canvas_resource),
+ offscreen_canvas_resource_provider_->GetNextResourceId());
+ return false;
+ }
+
+ // TODO(crbug.com/652931): update the device_scale_factor
+ frame->metadata.device_scale_factor = 1.0f;
+ if (current_begin_frame_ack_.sequence_number ==
+ viz::BeginFrameArgs::kInvalidFrameNumber) {
+ // TODO(eseckler): This shouldn't be necessary when OffscreenCanvas no
+ // longer submits CompositorFrames without prior BeginFrame.
+ current_begin_frame_ack_ = viz::BeginFrameAck::CreateManualAckWithDamage();
+ } else {
+ current_begin_frame_ack_.has_damage = true;
+ }
+ frame->metadata.begin_frame_ack = current_begin_frame_ack_;
+
+ const gfx::Rect bounds(size_.Width(), size_.Height());
+ const int kRenderPassId = 1;
+ bool is_clipped = false;
+ // TODO(crbug.com/705019): optimize for contexts that have {alpha: false}
+ bool are_contents_opaque = false;
+ std::unique_ptr<viz::RenderPass> pass = viz::RenderPass::Create();
+ pass->SetNew(kRenderPassId, bounds,
+ gfx::Rect(damage_rect.x(), damage_rect.y(), damage_rect.width(),
+ damage_rect.height()),
+ gfx::Transform());
+
+ viz::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
+ sqs->SetAll(gfx::Transform(), bounds, bounds, bounds, is_clipped,
+ are_contents_opaque, 1.f, SkBlendMode::kSrcOver, 0);
+
+ viz::TransferableResource resource;
+
+ bool yflipped = false;
+ OffscreenCanvasCommitType commit_type;
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ EnumerationHistogram, commit_type_histogram,
+ ("OffscreenCanvas.CommitType", kOffscreenCanvasCommitTypeCount));
+ if (canvas_resource->IsAccelerated()) {
+ // While |image| is texture backed, it could be generated with "software
+ // rendering" aka swiftshader. If the compositor is not also using
+ // swiftshader, then we could not give a swiftshader based texture
+ // to the compositor. However in that case, IsGpuCompositingEnabled() will
+ // also be false, so we will avoid doing so.
+ if (SharedGpuContext::IsGpuCompositingEnabled()) {
+ // Case 1: both canvas and compositor are gpu accelerated.
+ commit_type = kCommitGPUCanvasGPUCompositing;
+ offscreen_canvas_resource_provider_
+ ->SetTransferableResourceToStaticBitmapImage(&resource,
+ canvas_resource);
+ yflipped = true;
+ } else {
+ // Case 2: canvas is accelerated but gpu compositing is disabled.
+ commit_type = kCommitGPUCanvasSoftwareCompositing;
+ offscreen_canvas_resource_provider_
+ ->SetTransferableResourceToSharedBitmap(resource,
+ canvas_resource->Bitmap());
+ }
+ } else {
+ if (SharedGpuContext::IsGpuCompositingEnabled()) {
+ // Case 3: canvas is not gpu-accelerated, but compositor is.
+ commit_type = kCommitSoftwareCanvasGPUCompositing;
+ scoped_refptr<CanvasResource> accelerated_resource =
+ canvas_resource->MakeAccelerated(
+ SharedGpuContext::ContextProviderWrapper());
+ if (!accelerated_resource)
+ return false;
+ offscreen_canvas_resource_provider_
+ ->SetTransferableResourceToStaticBitmapImage(&resource,
+ accelerated_resource);
+ } else {
+ // Case 4: both canvas and compositor are not gpu accelerated.
+ commit_type = kCommitSoftwareCanvasSoftwareCompositing;
+ offscreen_canvas_resource_provider_
+ ->SetTransferableResourceToSharedBitmap(resource,
+ canvas_resource->Bitmap());
+ }
+ }
+
+ commit_type_histogram.Count(commit_type);
+
+ PostImageToPlaceholderIfNotBlocked(
+ std::move(canvas_resource),
+ offscreen_canvas_resource_provider_->GetNextResourceId());
+
+ frame->resource_list.push_back(std::move(resource));
+
+ viz::TextureDrawQuad* quad =
+ pass->CreateAndAppendDrawQuad<viz::TextureDrawQuad>();
+ gfx::Size rect_size(size_.Width(), size_.Height());
+
+ // TODO(crbug.com/705019): optimize for contexts that have {alpha: false}
+ const bool kNeedsBlending = true;
+
+ // TODO(crbug.com/645993): this should be inherited from WebGL context's
+ // creation settings.
+ const bool kPremultipliedAlpha = true;
+ const gfx::PointF uv_top_left(0.f, 0.f);
+ const gfx::PointF uv_bottom_right(1.f, 1.f);
+ float vertex_opacity[4] = {1.f, 1.f, 1.f, 1.f};
+ // TODO(crbug.com/645994): this should be true when using style
+ // "image-rendering: pixelated".
+ // TODO(crbug.com/645590): filter should respect the image-rendering CSS
+ // property of associated canvas element.
+ const bool kNearestNeighbor = false;
+ quad->SetAll(sqs, bounds, bounds, kNeedsBlending, resource.id, gfx::Size(),
+ kPremultipliedAlpha, uv_top_left, uv_bottom_right,
+ SK_ColorTRANSPARENT, vertex_opacity, yflipped, kNearestNeighbor,
+ false);
+
+ frame->render_pass_list.push_back(std::move(pass));
+
+ base::TimeDelta elapsed_time = WTF::CurrentTimeTicks() - commit_start_time;
+
+ switch (commit_type) {
+ case kCommitGPUCanvasGPUCompositing:
+ if (IsMainThread()) {
+ DEFINE_STATIC_LOCAL(
+ CustomCountHistogram, commit_gpu_canvas_gpu_compositing_main_timer,
+ ("Blink.Canvas.OffscreenCommit.GPUCanvasGPUCompositingMain", 0,
+ 10000000, 50));
+ commit_gpu_canvas_gpu_compositing_main_timer.CountMicroseconds(
+ elapsed_time);
+ } else {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ CustomCountHistogram,
+ commit_gpu_canvas_gpu_compositing_worker_timer,
+ ("Blink.Canvas.OffscreenCommit.GPUCanvasGPUCompositingWorker", 0,
+ 10000000, 50));
+ commit_gpu_canvas_gpu_compositing_worker_timer.CountMicroseconds(
+ elapsed_time);
+ }
+ break;
+ case kCommitGPUCanvasSoftwareCompositing:
+ if (IsMainThread()) {
+ DEFINE_STATIC_LOCAL(
+ CustomCountHistogram,
+ commit_gpu_canvas_software_compositing_main_timer,
+ ("Blink.Canvas.OffscreenCommit.GPUCanvasSoftwareCompositingMain", 0,
+ 10000000, 50));
+ commit_gpu_canvas_software_compositing_main_timer.CountMicroseconds(
+ elapsed_time);
+ } else {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ CustomCountHistogram,
+ commit_gpu_canvas_software_compositing_worker_timer,
+ ("Blink.Canvas.OffscreenCommit."
+ "GPUCanvasSoftwareCompositingWorker",
+ 0, 10000000, 50));
+ commit_gpu_canvas_software_compositing_worker_timer.CountMicroseconds(
+ elapsed_time);
+ }
+ break;
+ case kCommitSoftwareCanvasGPUCompositing:
+ if (IsMainThread()) {
+ DEFINE_STATIC_LOCAL(
+ CustomCountHistogram,
+ commit_software_canvas_gpu_compositing_main_timer,
+ ("Blink.Canvas.OffscreenCommit.SoftwareCanvasGPUCompositingMain", 0,
+ 10000000, 50));
+ commit_software_canvas_gpu_compositing_main_timer.CountMicroseconds(
+ elapsed_time);
+ } else {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ CustomCountHistogram,
+ commit_software_canvas_gpu_compositing_worker_timer,
+ ("Blink.Canvas.OffscreenCommit."
+ "SoftwareCanvasGPUCompositingWorker",
+ 0, 10000000, 50));
+ commit_software_canvas_gpu_compositing_worker_timer.CountMicroseconds(
+ elapsed_time);
+ }
+ break;
+ case kCommitSoftwareCanvasSoftwareCompositing:
+ if (IsMainThread()) {
+ DEFINE_STATIC_LOCAL(
+ CustomCountHistogram,
+ commit_software_canvas_software_compositing_main_timer,
+ ("Blink.Canvas.OffscreenCommit."
+ "SoftwareCanvasSoftwareCompositingMain",
+ 0, 10000000, 50));
+ commit_software_canvas_software_compositing_main_timer
+ .CountMicroseconds(elapsed_time);
+ } else {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ CustomCountHistogram,
+ commit_software_canvas_software_compositing_worker_timer,
+ ("Blink.Canvas.OffscreenCommit."
+ "SoftwareCanvasSoftwareCompositingWorker",
+ 0, 10000000, 50));
+ commit_software_canvas_software_compositing_worker_timer
+ .CountMicroseconds(elapsed_time);
+ }
+ break;
+ case kOffscreenCanvasCommitTypeCount:
+ NOTREACHED();
+ }
+
+ if (change_size_for_next_commit_) {
+ parent_local_surface_id_allocator_.GenerateId();
+ change_size_for_next_commit_ = false;
+ }
+
+ return true;
+}
+
+void CanvasResourceDispatcher::DidReceiveCompositorFrameAck(
+ const WTF::Vector<viz::ReturnedResource>& resources) {
+ ReclaimResources(resources);
+ pending_compositor_frames_--;
+ DCHECK_GE(pending_compositor_frames_, 0);
+}
+
+void CanvasResourceDispatcher::DidPresentCompositorFrame(
+ uint32_t presentation_token,
+ ::gfx::mojom::blink::PresentationFeedbackPtr feedback) {
+ NOTIMPLEMENTED();
+}
+
+void CanvasResourceDispatcher::SetNeedsBeginFrame(bool needs_begin_frame) {
+ if (needs_begin_frame_ == needs_begin_frame)
+ return;
+ needs_begin_frame_ = needs_begin_frame;
+ if (!suspend_animation_)
+ SetNeedsBeginFrameInternal();
+}
+
+void CanvasResourceDispatcher::SetSuspendAnimation(bool suspend_animation) {
+ if (suspend_animation_ == suspend_animation)
+ return;
+ suspend_animation_ = suspend_animation;
+ if (needs_begin_frame_)
+ SetNeedsBeginFrameInternal();
+}
+
+void CanvasResourceDispatcher::SetNeedsBeginFrameInternal() {
+ if (sink_) {
+ sink_->SetNeedsBeginFrame(needs_begin_frame_ && !suspend_animation_);
+ }
+}
+
+void CanvasResourceDispatcher::OnBeginFrame(
+ const viz::BeginFrameArgs& begin_frame_args) {
+ current_begin_frame_ack_ = viz::BeginFrameAck(begin_frame_args, false);
+ if (pending_compositor_frames_ >= kMaxPendingCompositorFrames ||
+ (begin_frame_args.type == viz::BeginFrameArgs::MISSED &&
+ base::TimeTicks::Now() > begin_frame_args.deadline)) {
+ sink_->DidNotProduceFrame(current_begin_frame_ack_);
+ return;
+ }
+
+ if (Client())
+ Client()->BeginFrame();
+ // TODO(eseckler): Tell |m_sink| if we did not draw during the BeginFrame.
+ current_begin_frame_ack_.sequence_number =
+ viz::BeginFrameArgs::kInvalidFrameNumber;
+}
+
+void CanvasResourceDispatcher::ReclaimResources(
+ const WTF::Vector<viz::ReturnedResource>& resources) {
+ offscreen_canvas_resource_provider_->ReclaimResources(resources);
+}
+
+void CanvasResourceDispatcher::ReclaimResource(viz::ResourceId resource_id) {
+ offscreen_canvas_resource_provider_->ReclaimResource(resource_id);
+ num_unreclaimed_frames_posted_--;
+
+ // The main thread has become unblocked recently and we have an image that
+ // have not been posted yet.
+ if (latest_unposted_image_) {
+ DCHECK(num_unreclaimed_frames_posted_ ==
+ kMaxUnreclaimedPlaceholderFrames - 1);
+ PostImageToPlaceholderIfNotBlocked(std::move(latest_unposted_image_),
+ latest_unposted_resource_id_);
+ latest_unposted_resource_id_ = 0;
+ }
+}
+
+bool CanvasResourceDispatcher::VerifyImageSize(const IntSize image_size) {
+ if (image_size == size_)
+ return true;
+ return false;
+}
+
+void CanvasResourceDispatcher::Reshape(const IntSize& size) {
+ if (size_ != size) {
+ size_ = size;
+ offscreen_canvas_resource_provider_->Reshape(size_.Width(), size_.Height());
+ change_size_for_next_commit_ = true;
+ }
+}
+
+void CanvasResourceDispatcher::DidAllocateSharedBitmap(
+ mojo::ScopedSharedBufferHandle buffer,
+ ::gpu::mojom::blink::MailboxPtr id) {
+ sink_->DidAllocateSharedBitmap(std::move(buffer), std::move(id));
+}
+
+void CanvasResourceDispatcher::DidDeleteSharedBitmap(
+ ::gpu::mojom::blink::MailboxPtr id) {
+ sink_->DidDeleteSharedBitmap(std::move(id));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h
new file mode 100644
index 00000000000..d2afb6a9098
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h
@@ -0,0 +1,136 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CANVAS_RESOURCE_DISPATCHER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CANVAS_RESOURCE_DISPATCHER_H_
+
+#include <memory>
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/common/resources/resource_id.h"
+#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom-blink.h"
+#include "third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.h"
+#include "third_party/blink/renderer/platform/wtf/compiler.h"
+
+namespace blink {
+
+class CanvasResource;
+
+class CanvasResourceDispatcherClient {
+ public:
+ virtual void BeginFrame() = 0;
+};
+
+class PLATFORM_EXPORT CanvasResourceDispatcher
+ : public viz::mojom::blink::CompositorFrameSinkClient {
+ public:
+ base::WeakPtr<CanvasResourceDispatcher> GetWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+ }
+
+ CanvasResourceDispatcherClient* Client() { return client_; }
+
+ enum {
+ kInvalidPlaceholderCanvasId = -1,
+ };
+
+ CanvasResourceDispatcher(CanvasResourceDispatcherClient*,
+ uint32_t client_id,
+ uint32_t sink_id,
+ int placeholder_canvas_id,
+ const IntSize&);
+
+ ~CanvasResourceDispatcher() override;
+ void SetNeedsBeginFrame(bool);
+ void SetSuspendAnimation(bool);
+ bool NeedsBeginFrame() const { return needs_begin_frame_; }
+ bool IsAnimationSuspended() const { return suspend_animation_; }
+ void DispatchFrame(scoped_refptr<StaticBitmapImage>,
+ base::TimeTicks commit_start_time,
+ const SkIRect& damage_rect);
+ void ReclaimResource(viz::ResourceId);
+ void DispatchFrameSync(scoped_refptr<StaticBitmapImage>,
+ base::TimeTicks commit_start_time,
+ const SkIRect& damage_rect);
+
+ void Reshape(const IntSize&);
+
+ // viz::mojom::blink::CompositorFrameSinkClient implementation.
+ void DidReceiveCompositorFrameAck(
+ const WTF::Vector<viz::ReturnedResource>& resources) final;
+ void DidPresentCompositorFrame(
+ uint32_t presentation_token,
+ ::gfx::mojom::blink::PresentationFeedbackPtr feedback) final;
+ void OnBeginFrame(const viz::BeginFrameArgs&) final;
+ void OnBeginFramePausedChanged(bool paused) final{};
+ void ReclaimResources(
+ const WTF::Vector<viz::ReturnedResource>& resources) final;
+
+ void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer,
+ ::gpu::mojom::blink::MailboxPtr id);
+ void DidDeleteSharedBitmap(::gpu::mojom::blink::MailboxPtr id);
+
+ // This enum is used in histogram, so it should be append-only.
+ enum OffscreenCanvasCommitType {
+ kCommitGPUCanvasGPUCompositing = 0,
+ kCommitGPUCanvasSoftwareCompositing = 1,
+ kCommitSoftwareCanvasGPUCompositing = 2,
+ kCommitSoftwareCanvasSoftwareCompositing = 3,
+ kOffscreenCanvasCommitTypeCount,
+
+ };
+
+ private:
+ friend class CanvasResourceDispatcherTest;
+
+ bool PrepareFrame(scoped_refptr<CanvasResource>,
+ base::TimeTicks commit_start_time,
+ const SkIRect& damage_rect,
+ viz::CompositorFrame* frame);
+
+ // Surface-related
+ viz::ParentLocalSurfaceIdAllocator parent_local_surface_id_allocator_;
+ const viz::FrameSinkId frame_sink_id_;
+
+ IntSize size_;
+ bool change_size_for_next_commit_;
+ bool suspend_animation_ = false;
+ bool needs_begin_frame_ = false;
+ int pending_compositor_frames_ = 0;
+
+ void SetNeedsBeginFrameInternal();
+
+ bool VerifyImageSize(const IntSize);
+ void PostImageToPlaceholderIfNotBlocked(scoped_refptr<CanvasResource>,
+ viz::ResourceId resource_id);
+ // virtual for testing
+ virtual void PostImageToPlaceholder(scoped_refptr<CanvasResource>,
+ viz::ResourceId resource_id);
+
+ viz::mojom::blink::CompositorFrameSinkPtr sink_;
+ mojo::Binding<viz::mojom::blink::CompositorFrameSinkClient> binding_;
+ viz::mojom::blink::CompositorFrameSinkClientPtr client_ptr_;
+
+ int placeholder_canvas_id_;
+
+ // The latest_unposted_resource_id_ always refers to the Id of the frame
+ // resource used by the latest_unposted_image_.
+ scoped_refptr<CanvasResource> latest_unposted_image_;
+ viz::ResourceId latest_unposted_resource_id_;
+ unsigned num_unreclaimed_frames_posted_;
+
+ viz::BeginFrameAck current_begin_frame_ack_;
+
+ CanvasResourceDispatcherClient* client_;
+
+ std::unique_ptr<OffscreenCanvasResourceProvider>
+ offscreen_canvas_resource_provider_;
+
+ base::WeakPtrFactory<CanvasResourceDispatcher> weak_ptr_factory_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_OFFSCREEN_CANVAS_FRAME_DISPATCHER_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.cc
new file mode 100644
index 00000000000..f7c20310f27
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.cc
@@ -0,0 +1,30 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/graphics/canvas_resource_host.h"
+
+#include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
+
+namespace blink {
+
+CanvasResourceProvider* CanvasResourceHost::ResourceProvider() const {
+ return resource_provider_.get();
+}
+
+std::unique_ptr<CanvasResourceProvider>
+CanvasResourceHost::ReplaceResourceProvider(
+ std::unique_ptr<CanvasResourceProvider> new_resource_provider) {
+ std::unique_ptr<CanvasResourceProvider> old_resource_provider =
+ std::move(resource_provider_);
+ resource_provider_ = std::move(new_resource_provider);
+ UpdateMemoryUsage();
+ return old_resource_provider;
+}
+
+void CanvasResourceHost::DiscardResourceProvider() {
+ resource_provider_ = nullptr;
+ UpdateMemoryUsage();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.h b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.h
index a4518f8155a..99f178d6d28 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_host.h
@@ -5,18 +5,40 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CANVAS_RESOURCE_HOST_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CANVAS_RESOURCE_HOST_H_
+#include <memory>
+
+#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/platform_export.h"
+namespace cc {
+class PaintCanvas;
+}
+
namespace blink {
+class CanvasResourceProvider;
class PLATFORM_EXPORT CanvasResourceHost {
public:
virtual ~CanvasResourceHost() = default;
virtual void NotifyGpuContextLost() = 0;
virtual void SetNeedsCompositingUpdate() = 0;
- virtual void RestoreCanvasMatrixClipStack(PaintCanvas*) const = 0;
+ virtual void RestoreCanvasMatrixClipStack(cc::PaintCanvas*) const = 0;
virtual void UpdateMemoryUsage() = 0;
+ virtual CanvasResourceProvider* GetOrCreateCanvasResourceProvider(
+ AccelerationHint hint) = 0;
+
+ virtual SkFilterQuality FilterQuality() const = 0;
+
+ CanvasResourceProvider* ResourceProvider() const;
+
+ std::unique_ptr<CanvasResourceProvider> ReplaceResourceProvider(
+ std::unique_ptr<CanvasResourceProvider>);
+
+ virtual void DiscardResourceProvider();
+
+ private:
+ std::unique_ptr<CanvasResourceProvider> resource_provider_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
index e62cc06d337..88422541d51 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -6,15 +6,19 @@
#include "cc/paint/decode_stashing_image_provider.h"
#include "cc/paint/skia_paint_canvas.h"
+#include "components/viz/common/resources/resource_format_utils.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/common/capabilities.h"
#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
#include "gpu/config/gpu_driver_bug_workaround_type.h"
#include "gpu/config/gpu_feature_info.h"
+#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/canvas_heuristic_parameters.h"
+#include "third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
+#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/skia/include/core/SkColorSpaceXformCanvas.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
@@ -36,16 +40,19 @@ class CanvasResourceProviderTexture : public CanvasResourceProvider {
unsigned msaa_sample_count,
const CanvasColorParams color_params,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>
- context_provider_wrapper)
+ context_provider_wrapper,
+ base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher)
: CanvasResourceProvider(size,
color_params,
- std::move(context_provider_wrapper)),
+ std::move(context_provider_wrapper),
+ std::move(resource_dispatcher)),
msaa_sample_count_(msaa_sample_count) {}
~CanvasResourceProviderTexture() override = default;
bool IsValid() const final { return GetSkSurface() && !IsGpuContextLost(); }
bool IsAccelerated() const final { return true; }
+ bool SupportsDirectCompositing() const override { return true; }
GLuint GetBackingTextureHandleForOverwrite() override {
GrBackendTexture backend_texture = GetSkSurface()->getBackendTexture(
@@ -60,6 +67,7 @@ class CanvasResourceProviderTexture : public CanvasResourceProvider {
protected:
scoped_refptr<CanvasResource> ProduceFrame() override {
+ TRACE_EVENT0("blink", "CanvasResourceProviderTexture::ProduceFrame");
DCHECK(GetSkSurface());
if (IsGpuContextLost())
@@ -101,6 +109,8 @@ class CanvasResourceProviderTexture : public CanvasResourceProvider {
}
sk_sp<SkSurface> CreateSkSurface() const override {
+ TRACE_EVENT0("blink", "CanvasResourceProviderTexture::CreateSkSurface");
+
if (IsGpuContextLost())
return nullptr;
auto* gr = GetGrContext();
@@ -132,22 +142,32 @@ class CanvasResourceProviderTextureGpuMemoryBuffer final
unsigned msaa_sample_count,
const CanvasColorParams color_params,
base::WeakPtr<WebGraphicsContext3DProviderWrapper>
- context_provider_wrapper)
+ context_provider_wrapper,
+ base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher)
: CanvasResourceProviderTexture(size,
msaa_sample_count,
color_params,
- std::move(context_provider_wrapper)) {}
+ std::move(context_provider_wrapper),
+ std::move(resource_dispatcher)) {}
~CanvasResourceProviderTextureGpuMemoryBuffer() override = default;
+ bool SupportsDirectCompositing() const override { return true; }
private:
scoped_refptr<CanvasResource> CreateResource() final {
+ TRACE_EVENT0(
+ "blink",
+ "CanvasResourceProviderTextureGpuMemoreBuffer::CreateResource");
+ constexpr bool is_accelerated = true;
return CanvasResourceGpuMemoryBuffer::Create(
Size(), ColorParams(), ContextProviderWrapper(), CreateWeakPtr(),
- FilterQuality());
+ FilterQuality(), is_accelerated);
}
scoped_refptr<CanvasResource> ProduceFrame() final {
+ TRACE_EVENT0("blink",
+ "CanvasResourceProviderTextureGpuMemoreBuffer::ProduceFrame");
+
DCHECK(GetSkSurface());
if (IsGpuContextLost())
@@ -173,40 +193,11 @@ class CanvasResourceProviderTextureGpuMemoryBuffer final
GLuint skia_texture_id = info.fID;
output_resource->CopyFromTexture(skia_texture_id,
- ColorParams().GLInternalFormat(),
+ ColorParams().GLUnsizedInternalFormat(),
ColorParams().GLType());
return output_resource;
}
-
- void RecycleResource(scoped_refptr<CanvasResource> resource) override {
- DCHECK(resource->HasOneRef());
- if (resource_recycling_enabled_)
- recycled_resources_.push_back(std::move(resource));
- }
-
- void SetResourceRecyclingEnabled(bool value) override {
- resource_recycling_enabled_ = value;
- if (!resource_recycling_enabled_)
- ClearRecycledResources();
- }
-
- void ClearRecycledResources() { recycled_resources_.clear(); }
-
- scoped_refptr<CanvasResource> NewOrRecycledResource() {
- if (recycled_resources_.size()) {
- scoped_refptr<CanvasResource> resource =
- std::move(recycled_resources_.back());
- recycled_resources_.pop_back();
- // Recycling implies releasing the old content
- resource->WaitSyncTokenBeforeRelease();
- return resource;
- }
- return CreateResource();
- }
-
- WTF::Vector<scoped_refptr<CanvasResource>> recycled_resources_;
- bool resource_recycling_enabled_ = true;
};
// CanvasResourceProviderBitmap
@@ -215,26 +206,33 @@ class CanvasResourceProviderTextureGpuMemoryBuffer final
// * Renders to a skia RAM-backed bitmap
// * Mailboxing is not supported : cannot be directly composited
-class CanvasResourceProviderBitmap final : public CanvasResourceProvider {
+class CanvasResourceProviderBitmap : public CanvasResourceProvider {
public:
- CanvasResourceProviderBitmap(const IntSize& size,
- const CanvasColorParams color_params)
+ CanvasResourceProviderBitmap(
+ const IntSize& size,
+ const CanvasColorParams color_params,
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper>
+ context_provider_wrapper,
+ base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher)
: CanvasResourceProvider(size,
color_params,
- nullptr /*context_provider_wrapper*/) {}
+ std::move(context_provider_wrapper),
+ std::move(resource_dispatcher)) {}
~CanvasResourceProviderBitmap() override = default;
bool IsValid() const final { return GetSkSurface(); }
bool IsAccelerated() const final { return false; }
+ bool SupportsDirectCompositing() const override { return false; }
private:
- scoped_refptr<CanvasResource> ProduceFrame() final {
- NOTREACHED(); // Not directly compositable.
- return nullptr;
+ scoped_refptr<CanvasResource> ProduceFrame() override {
+ return nullptr; // Does not support direct compositing
}
sk_sp<SkSurface> CreateSkSurface() const override {
+ TRACE_EVENT0("blink", "CanvasResourceProviderBitmap::CreateSkSurface");
+
SkImageInfo info = SkImageInfo::Make(
Size().Width(), Size().Height(), ColorParams().GetSkColorType(),
kPremul_SkAlphaType, ColorParams().GetSkColorSpaceForSkSurfaces());
@@ -242,16 +240,131 @@ class CanvasResourceProviderBitmap final : public CanvasResourceProvider {
}
};
+// CanvasResourceProviderRamGpuMemoryBuffer
+//==============================================================================
+//
+// * Renders to a ram memory buffer managed by skia
+// * Uses GpuMemoryBuffer to pass frames to the compositor
+// * Layers are overlay candidates
+
+class CanvasResourceProviderRamGpuMemoryBuffer final
+ : public CanvasResourceProviderBitmap {
+ public:
+ CanvasResourceProviderRamGpuMemoryBuffer(
+ const IntSize& size,
+ const CanvasColorParams color_params,
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper>
+ context_provider_wrapper,
+ base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher)
+ : CanvasResourceProviderBitmap(size,
+ color_params,
+ std::move(context_provider_wrapper),
+ std::move(resource_dispatcher)) {}
+
+ ~CanvasResourceProviderRamGpuMemoryBuffer() override = default;
+ bool SupportsDirectCompositing() const override { return true; }
+
+ private:
+ scoped_refptr<CanvasResource> CreateResource() final {
+ TRACE_EVENT0("blink",
+ "CanvasResourceProviderRamGpuMemoryBuffer::CreateResource");
+
+ constexpr bool is_accelerated = false;
+ return CanvasResourceGpuMemoryBuffer::Create(
+ Size(), ColorParams(), ContextProviderWrapper(), CreateWeakPtr(),
+ FilterQuality(), is_accelerated);
+ }
+
+ scoped_refptr<CanvasResource> ProduceFrame() final {
+ TRACE_EVENT0("blink",
+ "CanvasResourceProviderRamGpuMemoryBuffer::ProduceFrame");
+
+ DCHECK(GetSkSurface());
+
+ scoped_refptr<CanvasResource> output_resource = NewOrRecycledResource();
+ if (!output_resource) {
+ // Not compositable without a GpuMemoryBuffer
+ return nullptr;
+ }
+
+ sk_sp<SkImage> image = GetSkSurface()->makeImageSnapshot();
+ if (!image)
+ return nullptr;
+ DCHECK(!image->isTextureBacked());
+
+ output_resource->TakeSkImage(std::move(image));
+
+ return output_resource;
+ }
+};
+
+// CanvasResourceProviderSharedBitmap
+//==============================================================================
+//
+// * Renders to a shared memory bitmap
+// * Uses SharedBitmaps to pass frames directly to the compositor
+
+class CanvasResourceProviderSharedBitmap : public CanvasResourceProviderBitmap {
+ public:
+ CanvasResourceProviderSharedBitmap(
+ const IntSize& size,
+ const CanvasColorParams color_params,
+ base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher)
+ : CanvasResourceProviderBitmap(size,
+ color_params,
+ nullptr, // context_provider_wrapper
+ std::move(resource_dispatcher)) {
+ DCHECK(ResourceDispatcher());
+ }
+ ~CanvasResourceProviderSharedBitmap() override = default;
+ bool SupportsDirectCompositing() const override { return true; }
+
+ private:
+ scoped_refptr<CanvasResource> CreateResource() final {
+ CanvasColorParams color_params = ColorParams();
+ if (!IsBitmapFormatSupported(color_params.TransferableResourceFormat())) {
+ // If the rendering format is not supported, downgrate to 8-bits.
+ // TODO(junov): Should we try 12-12-12-12 and 10-10-10-2?
+ color_params.SetCanvasPixelFormat(kRGBA8CanvasPixelFormat);
+ }
+
+ return CanvasResourceSharedBitmap::Create(Size(), color_params,
+ CreateWeakPtr(), FilterQuality());
+ }
+
+ scoped_refptr<CanvasResource> ProduceFrame() final {
+ DCHECK(GetSkSurface());
+ scoped_refptr<CanvasResource> output_resource = NewOrRecycledResource();
+ if (!output_resource) {
+ // Not compositable without a SharedBitmap
+ return nullptr;
+ }
+
+ sk_sp<SkImage> image = GetSkSurface()->makeImageSnapshot();
+ if (!image)
+ return nullptr;
+ DCHECK(!image->isTextureBacked());
+
+ output_resource->TakeSkImage(std::move(image));
+
+ return output_resource;
+ }
+};
+
// CanvasResourceProvider base class implementation
//==============================================================================
enum ResourceType {
kTextureGpuMemoryBufferResourceType,
+ kRamGpuMemoryBufferResourceType,
+ kSharedBitmapResourceType,
kTextureResourceType,
kBitmapResourceType,
};
constexpr ResourceType kSoftwareCompositedFallbackList[] = {
+ kRamGpuMemoryBufferResourceType, kSharedBitmapResourceType,
+ // Fallback to no direct compositing support
kBitmapResourceType,
};
@@ -260,11 +373,16 @@ constexpr ResourceType kSoftwareFallbackList[] = {
};
constexpr ResourceType kAcceleratedFallbackList[] = {
- kTextureResourceType, kBitmapResourceType,
+ kTextureResourceType,
+ // Fallback to software
+ kBitmapResourceType,
};
constexpr ResourceType kAcceleratedCompositedFallbackList[] = {
kTextureGpuMemoryBufferResourceType, kTextureResourceType,
+ // Fallback to software composited
+ kRamGpuMemoryBufferResourceType, kSharedBitmapResourceType,
+ // Fallback to no direct compositing support
kBitmapResourceType,
};
@@ -273,7 +391,9 @@ std::unique_ptr<CanvasResourceProvider> CanvasResourceProvider::Create(
ResourceUsage usage,
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
unsigned msaa_sample_count,
- const CanvasColorParams& colorParams) {
+ const CanvasColorParams& color_params,
+ PresentationMode presentation_mode,
+ base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher) {
const ResourceType* resource_type_fallback_list = nullptr;
size_t list_length = 0;
@@ -298,37 +418,68 @@ std::unique_ptr<CanvasResourceProvider> CanvasResourceProvider::Create(
std::unique_ptr<CanvasResourceProvider> provider;
for (size_t i = 0; i < list_length; ++i) {
+ // Note: We are deliberately not using std::move() on
+ // context_provider_wrapper and resource_dispatcher to ensure that the
+ // pointers remain valid for the next iteration of this loop if necessary.
switch (resource_type_fallback_list[i]) {
case kTextureGpuMemoryBufferResourceType:
- DCHECK(SharedGpuContext::IsGpuCompositingEnabled());
- if (!RuntimeEnabledFeatures::Canvas2dImageChromiumEnabled())
- break;
-
+ if (!SharedGpuContext::IsGpuCompositingEnabled())
+ continue;
+ if (presentation_mode !=
+ CanvasResourceProvider::kAllowImageChromiumPresentationMode)
+ continue;
+ if (!context_provider_wrapper)
+ continue;
if (!gpu::IsImageFromGpuMemoryBufferFormatSupported(
- colorParams.GetBufferFormat(),
+ color_params.GetBufferFormat(),
context_provider_wrapper->ContextProvider()
->GetCapabilities())) {
continue;
}
if (!gpu::IsImageSizeValidForGpuMemoryBufferFormat(
- gfx::Size(size), colorParams.GetBufferFormat())) {
+ gfx::Size(size), color_params.GetBufferFormat())) {
continue;
}
DCHECK(gpu::IsImageFormatCompatibleWithGpuMemoryBufferFormat(
- colorParams.GLInternalFormat(), colorParams.GetBufferFormat()));
-
+ color_params.GLUnsizedInternalFormat(),
+ color_params.GetBufferFormat()));
provider =
std::make_unique<CanvasResourceProviderTextureGpuMemoryBuffer>(
- size, msaa_sample_count, colorParams, context_provider_wrapper);
+ size, msaa_sample_count, color_params, context_provider_wrapper,
+ resource_dispatcher);
+ break;
+ case kRamGpuMemoryBufferResourceType:
+ if (!SharedGpuContext::IsGpuCompositingEnabled())
+ continue;
+ if (presentation_mode != kAllowImageChromiumPresentationMode)
+ continue;
+ if (!context_provider_wrapper)
+ continue;
+ if (!Platform::Current()->GetGpuMemoryBufferManager())
+ continue;
+ if (!gpu::IsImageSizeValidForGpuMemoryBufferFormat(
+ gfx::Size(size), color_params.GetBufferFormat())) {
+ continue;
+ }
+ provider = std::make_unique<CanvasResourceProviderRamGpuMemoryBuffer>(
+ size, color_params, context_provider_wrapper, resource_dispatcher);
+ break;
+ case kSharedBitmapResourceType:
+ if (!resource_dispatcher)
+ continue;
+ provider = std::make_unique<CanvasResourceProviderSharedBitmap>(
+ size, color_params, resource_dispatcher);
break;
case kTextureResourceType:
- DCHECK(SharedGpuContext::IsGpuCompositingEnabled());
+ if (!context_provider_wrapper)
+ continue;
provider = std::make_unique<CanvasResourceProviderTexture>(
- size, msaa_sample_count, colorParams, context_provider_wrapper);
+ size, msaa_sample_count, color_params, context_provider_wrapper,
+ resource_dispatcher);
break;
case kBitmapResourceType:
- provider =
- std::make_unique<CanvasResourceProviderBitmap>(size, colorParams);
+ provider = std::make_unique<CanvasResourceProviderBitmap>(
+ size, color_params, context_provider_wrapper, resource_dispatcher);
break;
}
if (provider && provider->IsValid())
@@ -343,7 +494,8 @@ CanvasResourceProvider::CanvasImageProvider::CanvasImageProvider(
const gfx::ColorSpace& target_color_space)
: playback_image_provider_(cache,
target_color_space,
- cc::PlaybackImageProvider::Settings()) {}
+ cc::PlaybackImageProvider::Settings()),
+ weak_factory_(this) {}
CanvasResourceProvider::CanvasImageProvider::~CanvasImageProvider() = default;
@@ -355,7 +507,9 @@ CanvasResourceProvider::CanvasImageProvider::GetDecodedDrawImage(
if (!scoped_decoded_image.needs_unlock())
return scoped_decoded_image;
- if (!scoped_decoded_image.decoded_image().is_budgeted()) {
+ constexpr int kMaxLockedImagesCount = 500;
+ if (!scoped_decoded_image.decoded_image().is_budgeted() ||
+ locked_images_.size() > kMaxLockedImagesCount) {
// If we have exceeded the budget, ReleaseLockedImages any locked decodes.
ReleaseLockedImages();
}
@@ -375,14 +529,22 @@ void CanvasResourceProvider::CanvasImageProvider::ReleaseLockedImages() {
void CanvasResourceProvider::CanvasImageProvider::CanUnlockImage(
ScopedDecodedDrawImage image) {
+ if (locked_images_.empty()) {
+ Platform::Current()->CurrentThread()->GetTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce(&CanvasImageProvider::ReleaseLockedImages,
+ weak_factory_.GetWeakPtr()));
+ }
+
locked_images_.push_back(std::move(image));
}
CanvasResourceProvider::CanvasResourceProvider(
const IntSize& size,
const CanvasColorParams& color_params,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper)
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
+ base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher)
: context_provider_wrapper_(std::move(context_provider_wrapper)),
+ resource_dispatcher_(resource_dispatcher),
size_(size),
color_params_(color_params),
snapshot_paint_image_id_(cc::PaintImage::GetNextId()),
@@ -402,8 +564,10 @@ SkSurface* CanvasResourceProvider::GetSkSurface() const {
return surface_.get();
}
-PaintCanvas* CanvasResourceProvider::Canvas() {
+cc::PaintCanvas* CanvasResourceProvider::Canvas() {
if (!canvas_) {
+ TRACE_EVENT0("blink", "CanvasResourceProvider::Canvas");
+
DCHECK(!canvas_image_provider_);
gfx::ColorSpace target_color_space =
@@ -496,11 +660,6 @@ void CanvasResourceProvider::FlushSkia() const {
GetSkSurface()->flush();
}
-void CanvasResourceProvider::RecycleResource(scoped_refptr<CanvasResource>) {
- // To be implemented in subclasses that use resource recycling.
- NOTREACHED();
-}
-
bool CanvasResourceProvider::IsGpuContextLost() const {
auto* gl = ContextGL();
return !gl || gl->GetGraphicsResetStatusKHR() != GL_NO_ERROR;
@@ -511,6 +670,8 @@ bool CanvasResourceProvider::WritePixels(const SkImageInfo& orig_info,
size_t row_bytes,
int x,
int y) {
+ TRACE_EVENT0("blink", "CanvasResourceProvider::WritePixels");
+
DCHECK(IsValid());
return GetSkSurface()->getCanvas()->writePixels(orig_info, pixels, row_bytes,
x, y);
@@ -545,9 +706,37 @@ scoped_refptr<CanvasResource> CanvasResourceProvider::CreateResource() {
}
cc::ImageDecodeCache* CanvasResourceProvider::ImageDecodeCache() {
- if (context_provider_wrapper_)
+ if (IsAccelerated() && context_provider_wrapper_)
return context_provider_wrapper_->ContextProvider()->ImageDecodeCache();
return &Image::SharedCCDecodeCache();
}
+void CanvasResourceProvider::RecycleResource(
+ scoped_refptr<CanvasResource> resource) {
+ // Need to check HasOneRef() because if there are outstanding references to
+ // the resource, it cannot be safely recycled.
+ if (resource->HasOneRef() && resource_recycling_enabled_)
+ recycled_resources_.push_back(std::move(resource));
+}
+
+void CanvasResourceProvider::SetResourceRecyclingEnabled(bool value) {
+ resource_recycling_enabled_ = value;
+ if (!resource_recycling_enabled_)
+ ClearRecycledResources();
+}
+
+void CanvasResourceProvider::ClearRecycledResources() {
+ recycled_resources_.clear();
+}
+
+scoped_refptr<CanvasResource> CanvasResourceProvider::NewOrRecycledResource() {
+ if (recycled_resources_.size()) {
+ scoped_refptr<CanvasResource> resource =
+ std::move(recycled_resources_.back());
+ recycled_resources_.pop_back();
+ return resource;
+ }
+ return CreateResource();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
index c68faf8cf55..b4a546d4c03 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_provider.h
@@ -5,16 +5,17 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CANVAS_RESOURCE_PROVIDER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_CANVAS_RESOURCE_PROVIDER_H_
+#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "cc/paint/skia_paint_canvas.h"
#include "cc/raster/playback_image_provider.h"
+#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom-blink.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/graphics/canvas_color_params.h"
#include "third_party/blink/renderer/platform/graphics/canvas_resource.h"
#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_wrapper.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/khronos/GLES2/gl2.h"
@@ -38,7 +39,7 @@ class GLES2Interface;
namespace blink {
-class StaticBitmapImage;
+class CanvasResourceDispatcher;
class WebGraphicsContext3DProviderWrapper;
// CanvasResourceProvider
@@ -58,7 +59,6 @@ class WebGraphicsContext3DProviderWrapper;
class PLATFORM_EXPORT CanvasResourceProvider
: public WebGraphicsContext3DProviderWrapper::DestructionObserver {
- WTF_MAKE_NONCOPYABLE(CanvasResourceProvider);
public:
enum ResourceUsage {
@@ -68,12 +68,19 @@ class PLATFORM_EXPORT CanvasResourceProvider
kAcceleratedCompositedResourceUsage,
};
+ enum PresentationMode {
+ kDefaultPresentationMode, // GPU Texture or shared memory bitmap
+ kAllowImageChromiumPresentationMode // Use CHROMIUM_image gl extension
+ };
+
static std::unique_ptr<CanvasResourceProvider> Create(
const IntSize&,
ResourceUsage,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper> = nullptr,
- unsigned msaa_sample_count = 0,
- const CanvasColorParams& = CanvasColorParams());
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
+ unsigned msaa_sample_count,
+ const CanvasColorParams&,
+ PresentationMode,
+ base::WeakPtr<CanvasResourceDispatcher>);
// Use this method for capturing a frame that is intended to be displayed via
// the compositor. Cases that need to acquire a snaptshot that is not destined
@@ -92,10 +99,16 @@ class PLATFORM_EXPORT CanvasResourceProvider
const IntSize& Size() const { return size_; }
virtual bool IsValid() const = 0;
virtual bool IsAccelerated() const = 0;
+ virtual bool SupportsDirectCompositing() const = 0;
uint32_t ContentUniqueID() const;
+ CanvasResourceDispatcher* ResourceDispatcher() {
+ return resource_dispatcher_.get();
+ }
- virtual void RecycleResource(scoped_refptr<CanvasResource>);
- virtual void SetResourceRecyclingEnabled(bool) {}
+ void RecycleResource(scoped_refptr<CanvasResource>);
+ void SetResourceRecyclingEnabled(bool);
+ void ClearRecycledResources();
+ scoped_refptr<CanvasResource> NewOrRecycledResource();
SkSurface* GetSkSurface() const;
bool IsGpuContextLost() const;
@@ -108,6 +121,10 @@ class PLATFORM_EXPORT CanvasResourceProvider
NOTREACHED();
return 0;
}
+ virtual void* GetPixelBufferAddressForOverwrite() {
+ NOTREACHED();
+ return nullptr;
+ }
void Clear();
~CanvasResourceProvider() override;
@@ -128,7 +145,8 @@ class PLATFORM_EXPORT CanvasResourceProvider
CanvasResourceProvider(const IntSize&,
const CanvasColorParams&,
- base::WeakPtr<WebGraphicsContext3DProviderWrapper>);
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper>,
+ base::WeakPtr<CanvasResourceDispatcher>);
private:
class CanvasImageProvider : public cc::ImageProvider {
@@ -147,6 +165,8 @@ class PLATFORM_EXPORT CanvasResourceProvider
std::vector<ScopedDecodedDrawImage> locked_images_;
cc::PlaybackImageProvider playback_image_provider_;
+
+ base::WeakPtrFactory<CanvasImageProvider> weak_factory_;
};
virtual sk_sp<SkSurface> CreateSkSurface() const = 0;
@@ -154,6 +174,7 @@ class PLATFORM_EXPORT CanvasResourceProvider
cc::ImageDecodeCache* ImageDecodeCache();
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper_;
+ base::WeakPtr<CanvasResourceDispatcher> resource_dispatcher_;
IntSize size_;
CanvasColorParams color_params_;
base::Optional<CanvasImageProvider> canvas_image_provider_;
@@ -167,7 +188,12 @@ class PLATFORM_EXPORT CanvasResourceProvider
cc::PaintImage::kInvalidContentId;
uint32_t snapshot_sk_image_id_ = 0u;
+ WTF::Vector<scoped_refptr<CanvasResource>> recycled_resources_;
+ bool resource_recycling_enabled_ = true;
+
base::WeakPtrFactory<CanvasResourceProvider> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(CanvasResourceProvider);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_test.cc b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_test.cc
index a042c27bfcf..f27b5bf8901 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/canvas_resource_test.cc
@@ -5,7 +5,10 @@
#include "third_party/blink/renderer/platform/graphics/canvas_resource.h"
#include "base/run_loop.h"
+#include "components/viz/common/resources/single_release_callback.h"
+#include "components/viz/common/resources/transferable_resource.h"
#include "components/viz/test/test_gpu_memory_buffer_manager.h"
+#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -18,6 +21,7 @@
#include "third_party/skia/include/core/SkSurface.h"
using testing::_;
+using testing::AtLeast;
using testing::Pointee;
using testing::Return;
using testing::SetArrayArgument;
@@ -27,9 +31,9 @@ namespace blink {
class MockGLES2InterfaceWithMailboxSupport : public FakeGLES2Interface {
public:
- MOCK_METHOD2(ProduceTextureDirectCHROMIUM, void(GLuint, const GLbyte*));
- MOCK_METHOD1(GenMailboxCHROMIUM, void(GLbyte*));
+ MOCK_METHOD2(ProduceTextureDirectCHROMIUM, void(GLuint, GLbyte*));
MOCK_METHOD1(GenUnverifiedSyncTokenCHROMIUM, void(GLbyte*));
+ MOCK_METHOD1(GenSyncTokenCHROMIUM, void(GLbyte*));
MOCK_METHOD4(CreateImageCHROMIUM,
GLuint(ClientBuffer, GLsizei, GLsizei, GLenum));
MOCK_METHOD2(BindTexture, void(GLenum, GLuint));
@@ -100,13 +104,12 @@ TEST_F(CanvasResourceTest, SkiaResourceNoMailboxLeak) {
gpu::Mailbox test_mailbox;
test_mailbox.name[0] = 1;
- EXPECT_CALL(gl_, GenMailboxCHROMIUM(_))
- .WillOnce(SetArrayArgument<0>(
+ EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, _))
+ .WillOnce(SetArrayArgument<1>(
test_mailbox.name, test_mailbox.name + GL_MAILBOX_SIZE_CHROMIUM));
EXPECT_CALL(gl_, BindTexture(GL_TEXTURE_2D, _)).Times(2);
- EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, _));
EXPECT_CALL(gl_, GenUnverifiedSyncTokenCHROMIUM(_));
- resource->GetOrCreateGpuMailbox();
+ resource->GetOrCreateGpuMailbox(kUnverifiedSyncToken);
testing::Mock::VerifyAndClearExpectations(&gl_);
@@ -134,14 +137,21 @@ TEST_F(CanvasResourceTest, GpuMemoryBufferSyncTokenRefresh) {
ScopedTestingPlatformSupport<FakeCanvasResourcePlatformSupport> platform;
constexpr GLuint image_id = 1;
+ const GLuint texture_target = gpu::GetPlatformSpecificTextureTarget();
EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id));
- EXPECT_CALL(gl_, BindTexture(gpu::GetPlatformSpecificTextureTarget(), _));
+ EXPECT_CALL(gl_, BindTexture(texture_target, _));
+ if (texture_target == GL_TEXTURE_EXTERNAL_OES) {
+ constexpr GLuint image_2d_id = 2;
+ EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _))
+ .WillOnce(Return(image_2d_id));
+ EXPECT_CALL(gl_, BindTexture(GL_TEXTURE_2D, _));
+ }
scoped_refptr<CanvasResource> resource =
CanvasResourceGpuMemoryBuffer::Create(
IntSize(10, 10), CanvasColorParams(),
SharedGpuContext::ContextProviderWrapper(),
nullptr, // Resource provider
- kLow_SkFilterQuality);
+ kLow_SkFilterQuality, true /*is_accelerated*/);
EXPECT_TRUE(bool(resource));
@@ -149,16 +159,15 @@ TEST_F(CanvasResourceTest, GpuMemoryBufferSyncTokenRefresh) {
gpu::Mailbox test_mailbox;
test_mailbox.name[0] = 1;
- EXPECT_CALL(gl_, GenMailboxCHROMIUM(_))
- .WillOnce(SetArrayArgument<0>(
+ EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, _))
+ .WillOnce(SetArrayArgument<1>(
test_mailbox.name, test_mailbox.name + GL_MAILBOX_SIZE_CHROMIUM));
- EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, _));
- resource->GetOrCreateGpuMailbox();
+ resource->GetOrCreateGpuMailbox(kVerifiedSyncToken);
testing::Mock::VerifyAndClearExpectations(&gl_);
const gpu::SyncToken reference_token1 = GenTestSyncToken(1);
- EXPECT_CALL(gl_, GenUnverifiedSyncTokenCHROMIUM(_))
+ EXPECT_CALL(gl_, GenSyncTokenCHROMIUM(_))
.WillOnce(SetArrayArgument<0>(
reinterpret_cast<const GLbyte*>(&reference_token1),
reinterpret_cast<const GLbyte*>(&reference_token1 + 1)));
@@ -169,9 +178,9 @@ TEST_F(CanvasResourceTest, GpuMemoryBufferSyncTokenRefresh) {
// Grabbing the mailbox again without making any changes must not result in
// a sync token refresh
- EXPECT_CALL(gl_, GenMailboxCHROMIUM(_)).Times(0);
- EXPECT_CALL(gl_, GenUnverifiedSyncTokenCHROMIUM(_)).Times(0);
- resource->GetOrCreateGpuMailbox();
+ EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, _)).Times(0);
+ EXPECT_CALL(gl_, GenSyncTokenCHROMIUM(_)).Times(0);
+ resource->GetOrCreateGpuMailbox(kVerifiedSyncToken);
actual_token = resource->GetSyncToken();
EXPECT_EQ(actual_token, reference_token1);
@@ -179,15 +188,15 @@ TEST_F(CanvasResourceTest, GpuMemoryBufferSyncTokenRefresh) {
// Grabbing the mailbox again after a content change must result in
// a sync token refresh, but the mailbox gets re-used.
- EXPECT_CALL(gl_, GenMailboxCHROMIUM(_)).Times(0);
+ EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, _)).Times(0);
const gpu::SyncToken reference_token2 = GenTestSyncToken(2);
- EXPECT_CALL(gl_, GenUnverifiedSyncTokenCHROMIUM(_))
+ EXPECT_CALL(gl_, GenSyncTokenCHROMIUM(_))
.WillOnce(SetArrayArgument<0>(
reinterpret_cast<const GLbyte*>(&reference_token2),
reinterpret_cast<const GLbyte*>(&reference_token2 + 1)));
resource->CopyFromTexture(1, // source texture id
GL_RGBA, GL_UNSIGNED_BYTE);
- resource->GetOrCreateGpuMailbox();
+ resource->GetOrCreateGpuMailbox(kVerifiedSyncToken);
actual_token = resource->GetSyncToken();
EXPECT_EQ(actual_token, reference_token2);
@@ -293,4 +302,128 @@ TEST_F(CanvasResourceTest, MakeUnacceleratedFromAcceleratedResource) {
EXPECT_FALSE(new_resource->IsAccelerated());
}
+void PaintToCanvasResource(CanvasResource* canvas_resource) {
+ SkImageInfo image_info = SkImageInfo::MakeN32(
+ canvas_resource->Size().Width(), canvas_resource->Size().Height(),
+ kPremul_SkAlphaType, SkColorSpace::MakeSRGB());
+ sk_sp<SkSurface> surface = SkSurface::MakeRaster(image_info);
+ SkPaint paint;
+ paint.setColor(SK_ColorYELLOW);
+ surface->getCanvas()->drawRect(SkRect::MakeXYWH(0, 0, 10, 10), paint);
+ canvas_resource->TakeSkImage(surface->makeImageSnapshot());
+}
+
+TEST_F(CanvasResourceTest, RamGpuMemoryBuffer_ResourcePreparation) {
+ testing::InSequence s;
+ ScopedTestingPlatformSupport<FakeCanvasResourcePlatformSupport> platform;
+
+ EXPECT_TRUE(!!context_provider_wrapper_);
+ constexpr GLuint image_id = 1;
+ EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id));
+ EXPECT_CALL(gl_, BindTexture(gpu::GetPlatformSpecificTextureTarget(), _));
+
+ constexpr bool is_accelerated = false;
+ scoped_refptr<CanvasResource> canvas_resource =
+ CanvasResourceGpuMemoryBuffer::Create(
+ IntSize(10, 10), CanvasColorParams(), context_provider_wrapper_,
+ nullptr /*CanvasResourceProvider*/, kLow_SkFilterQuality,
+ is_accelerated);
+
+ EXPECT_TRUE(!!canvas_resource);
+ testing::Mock::VerifyAndClearExpectations(&gl_);
+
+ if (canvas_resource) {
+ gpu::Mailbox test_mailbox;
+ test_mailbox.name[0] = 1;
+ EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, _))
+ .WillOnce(SetArrayArgument<1>(
+ test_mailbox.name, test_mailbox.name + GL_MAILBOX_SIZE_CHROMIUM));
+
+ PaintToCanvasResource(canvas_resource.get());
+
+ viz::TransferableResource transferable_resource;
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback;
+
+ bool success = canvas_resource->PrepareTransferableResource(
+ &transferable_resource, &release_callback, kUnverifiedSyncToken);
+
+ EXPECT_TRUE(success);
+
+ release_callback->Run(gpu::SyncToken(), false);
+ }
+}
+
+TEST_F(CanvasResourceTest, GpuMemoryBuffer_accelerated_8bit) {
+ testing::InSequence s;
+ ScopedTestingPlatformSupport<FakeCanvasResourcePlatformSupport> platform;
+ EXPECT_TRUE(!!context_provider_wrapper_);
+
+ constexpr GLuint image_id = 1;
+ EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id));
+ EXPECT_CALL(gl_, BindTexture(_, _));
+
+ if (gpu::GetPlatformSpecificTextureTarget() == GL_TEXTURE_EXTERNAL_OES) {
+ constexpr GLuint second_image_id = 2;
+ EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _))
+ .WillOnce(Return(second_image_id));
+ EXPECT_CALL(gl_, BindTexture(_, _));
+ }
+
+ constexpr bool is_accelerated = true;
+ scoped_refptr<CanvasResource> canvas_resource =
+ CanvasResourceGpuMemoryBuffer::Create(
+ IntSize(10, 10), CanvasColorParams(), context_provider_wrapper_,
+ nullptr /*CanvasResourceProvider*/, kLow_SkFilterQuality,
+ is_accelerated);
+
+ EXPECT_TRUE(!!canvas_resource);
+}
+
+TEST_F(CanvasResourceTest, GpuMemoryBuffer_accelerated_float16) {
+ testing::InSequence s;
+ ScopedTestingPlatformSupport<FakeCanvasResourcePlatformSupport> platform;
+ EXPECT_TRUE(!!context_provider_wrapper_);
+
+ constexpr GLuint image_id = 1;
+ EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _)).WillOnce(Return(image_id));
+ EXPECT_CALL(gl_, BindTexture(_, _));
+
+ if (gpu::GetPlatformSpecificTextureTarget() == GL_TEXTURE_EXTERNAL_OES) {
+ constexpr GLuint second_image_id = 2;
+ EXPECT_CALL(gl_, CreateImageCHROMIUM(_, _, _, _))
+ .WillOnce(Return(second_image_id));
+ EXPECT_CALL(gl_, BindTexture(_, _));
+ }
+
+ constexpr bool is_accelerated = true;
+ scoped_refptr<CanvasResource> canvas_resource =
+ CanvasResourceGpuMemoryBuffer::Create(
+ IntSize(10, 10),
+ CanvasColorParams(kSRGBCanvasColorSpace, kF16CanvasPixelFormat,
+ kNonOpaque),
+ context_provider_wrapper_, nullptr /*CanvasResourceProvider*/,
+ kLow_SkFilterQuality, is_accelerated);
+
+ EXPECT_TRUE(!!canvas_resource);
+}
+
+TEST_F(CanvasResourceTest, PrepareTransferableResource_SharedBitmap) {
+ testing::InSequence s;
+ ScopedTestingPlatformSupport<FakeCanvasResourcePlatformSupport> platform;
+ scoped_refptr<CanvasResource> canvas_resource =
+ CanvasResourceSharedBitmap::Create(IntSize(10, 10), CanvasColorParams(),
+ nullptr, // CanvasResourceProvider
+ kLow_SkFilterQuality);
+ EXPECT_TRUE(!!canvas_resource);
+ viz::TransferableResource resource;
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback;
+ bool success = canvas_resource->PrepareTransferableResource(
+ &resource, &release_callback, kUnverifiedSyncToken);
+
+ EXPECT_TRUE(success);
+ EXPECT_TRUE(resource.is_software);
+
+ release_callback->Run(gpu::SyncToken(), false);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/color.cc b/chromium/third_party/blink/renderer/platform/graphics/color.cc
index ee2e59ab0e5..fdf5deae86b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/color.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/color.cc
@@ -26,9 +26,9 @@
#include "third_party/blink/renderer/platform/graphics/color.h"
#include "build/build_config.h"
-#include "third_party/blink/renderer/platform/decimal.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/decimal.h"
#include "third_party/blink/renderer/platform/wtf/dtoa.h"
#include "third_party/blink/renderer/platform/wtf/hex_number.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
@@ -49,29 +49,24 @@ const RGBA32 Color::kLightGray;
const RGBA32 Color::kTransparent;
#endif
-static const RGBA32 kLightenedBlack = 0xFF545454;
-static const RGBA32 kDarkenedWhite = 0xFFABABAB;
+namespace {
-RGBA32 MakeRGB(int r, int g, int b) {
- return 0xFF000000 | clampTo(r, 0, 255) << 16 | clampTo(g, 0, 255) << 8 |
- clampTo(b, 0, 255);
-}
-
-RGBA32 MakeRGBA(int r, int g, int b, int a) {
- return clampTo(a, 0, 255) << 24 | clampTo(r, 0, 255) << 16 |
- clampTo(g, 0, 255) << 8 | clampTo(b, 0, 255);
-}
+const RGBA32 kLightenedBlack = 0xFF545454;
+const RGBA32 kDarkenedWhite = 0xFFABABAB;
-static int ColorFloatToRGBAByte(float f) {
- return clampTo(static_cast<int>(lroundf(255.0f * f)), 0, 255);
-}
+const int kCStartAlpha = 153; // 60%
+const int kCEndAlpha = 204; // 80%;
+const int kCAlphaIncrement = 17; // Increments in between.
-RGBA32 MakeRGBA32FromFloats(float r, float g, float b, float a) {
- return ColorFloatToRGBAByte(a) << 24 | ColorFloatToRGBAByte(r) << 16 |
- ColorFloatToRGBAByte(g) << 8 | ColorFloatToRGBAByte(b);
+int BlendComponent(int c, int a) {
+ // We use white.
+ float alpha = a / 255.0f;
+ int white_blend = 255 - a;
+ c -= white_blend;
+ return static_cast<int>(c / alpha);
}
-static double CalcHue(double temp1, double temp2, double hue_val) {
+double CalcHue(double temp1, double temp2, double hue_val) {
if (hue_val < 0.0)
hue_val += 6.0;
else if (hue_val >= 6.0)
@@ -85,48 +80,15 @@ static double CalcHue(double temp1, double temp2, double hue_val) {
return temp1;
}
-// Explanation of this algorithm can be found in the CSS Color 4 Module
-// specification at https://drafts.csswg.org/css-color-4/#hsl-to-rgb with
-// further explanation available at http://en.wikipedia.org/wiki/HSL_color_space
-
-// Hue is in the range of 0 to 6.0, the remainder are in the range 0 to 1.0
-RGBA32 MakeRGBAFromHSLA(double hue,
- double saturation,
- double lightness,
- double alpha) {
- const double scale_factor = 255.0;
-
- if (!saturation) {
- int grey_value = static_cast<int>(round(lightness * scale_factor));
- return MakeRGBA(grey_value, grey_value, grey_value,
- static_cast<int>(round(alpha * scale_factor)));
- }
-
- double temp2 = lightness <= 0.5
- ? lightness * (1.0 + saturation)
- : lightness + saturation - lightness * saturation;
- double temp1 = 2.0 * lightness - temp2;
-
- return MakeRGBA(
- static_cast<int>(round(CalcHue(temp1, temp2, hue + 2.0) * scale_factor)),
- static_cast<int>(round(CalcHue(temp1, temp2, hue) * scale_factor)),
- static_cast<int>(round(CalcHue(temp1, temp2, hue - 2.0) * scale_factor)),
- static_cast<int>(round(alpha * scale_factor)));
-}
-
-RGBA32 MakeRGBAFromCMYKA(float c, float m, float y, float k, float a) {
- double colors = 1 - k;
- int r = static_cast<int>(nextafter(256, 0) * (colors * (1 - c)));
- int g = static_cast<int>(nextafter(256, 0) * (colors * (1 - m)));
- int b = static_cast<int>(nextafter(256, 0) * (colors * (1 - y)));
- return MakeRGBA(r, g, b, static_cast<float>(nextafter(256, 0) * a));
+int ColorFloatToRGBAByte(float f) {
+ return clampTo(static_cast<int>(lroundf(255.0f * f)), 0, 255);
}
// originally moved here from the CSS parser
template <typename CharacterType>
-static inline bool ParseHexColorInternal(const CharacterType* name,
- unsigned length,
- RGBA32& rgb) {
+inline bool ParseHexColorInternal(const CharacterType* name,
+ unsigned length,
+ RGBA32& rgb) {
if (length != 3 && length != 4 && length != 6 && length != 8)
return false;
if ((length == 8 || length == 4) &&
@@ -163,6 +125,75 @@ static inline bool ParseHexColorInternal(const CharacterType* name,
return true;
}
+inline const NamedColor* FindNamedColor(const String& name) {
+ char buffer[64]; // easily big enough for the longest color name
+ unsigned length = name.length();
+ if (length > sizeof(buffer) - 1)
+ return nullptr;
+ for (unsigned i = 0; i < length; ++i) {
+ UChar c = name[i];
+ if (!c || c > 0x7F)
+ return nullptr;
+ buffer[i] = ToASCIILower(static_cast<char>(c));
+ }
+ buffer[length] = '\0';
+ return FindColor(buffer, length);
+}
+
+} // namespace
+
+RGBA32 MakeRGB(int r, int g, int b) {
+ return 0xFF000000 | clampTo(r, 0, 255) << 16 | clampTo(g, 0, 255) << 8 |
+ clampTo(b, 0, 255);
+}
+
+RGBA32 MakeRGBA(int r, int g, int b, int a) {
+ return clampTo(a, 0, 255) << 24 | clampTo(r, 0, 255) << 16 |
+ clampTo(g, 0, 255) << 8 | clampTo(b, 0, 255);
+}
+
+RGBA32 MakeRGBA32FromFloats(float r, float g, float b, float a) {
+ return ColorFloatToRGBAByte(a) << 24 | ColorFloatToRGBAByte(r) << 16 |
+ ColorFloatToRGBAByte(g) << 8 | ColorFloatToRGBAByte(b);
+}
+
+// Explanation of this algorithm can be found in the CSS Color 4 Module
+// specification at https://drafts.csswg.org/css-color-4/#hsl-to-rgb with
+// further explanation available at http://en.wikipedia.org/wiki/HSL_color_space
+
+// Hue is in the range of 0 to 6.0, the remainder are in the range 0 to 1.0
+RGBA32 MakeRGBAFromHSLA(double hue,
+ double saturation,
+ double lightness,
+ double alpha) {
+ const double scale_factor = 255.0;
+
+ if (!saturation) {
+ int grey_value = static_cast<int>(round(lightness * scale_factor));
+ return MakeRGBA(grey_value, grey_value, grey_value,
+ static_cast<int>(round(alpha * scale_factor)));
+ }
+
+ double temp2 = lightness <= 0.5
+ ? lightness * (1.0 + saturation)
+ : lightness + saturation - lightness * saturation;
+ double temp1 = 2.0 * lightness - temp2;
+
+ return MakeRGBA(
+ static_cast<int>(round(CalcHue(temp1, temp2, hue + 2.0) * scale_factor)),
+ static_cast<int>(round(CalcHue(temp1, temp2, hue) * scale_factor)),
+ static_cast<int>(round(CalcHue(temp1, temp2, hue - 2.0) * scale_factor)),
+ static_cast<int>(round(alpha * scale_factor)));
+}
+
+RGBA32 MakeRGBAFromCMYKA(float c, float m, float y, float k, float a) {
+ double colors = 1 - k;
+ int r = static_cast<int>(nextafter(256, 0) * (colors * (1 - c)));
+ int g = static_cast<int>(nextafter(256, 0) * (colors * (1 - m)));
+ int b = static_cast<int>(nextafter(256, 0) * (colors * (1 - y)));
+ return MakeRGBA(r, g, b, static_cast<float>(nextafter(256, 0) * a));
+}
+
bool Color::ParseHexColor(const LChar* name, unsigned length, RGBA32& rgb) {
return ParseHexColorInternal(name, length, rgb);
}
@@ -266,21 +297,6 @@ String Color::NameForLayoutTreeAsText() const {
return String::Format("#%02X%02X%02X", Red(), Green(), Blue());
}
-static inline const NamedColor* FindNamedColor(const String& name) {
- char buffer[64]; // easily big enough for the longest color name
- unsigned length = name.length();
- if (length > sizeof(buffer) - 1)
- return nullptr;
- for (unsigned i = 0; i < length; ++i) {
- UChar c = name[i];
- if (!c || c > 0x7F)
- return nullptr;
- buffer[i] = ToASCIILower(static_cast<char>(c));
- }
- buffer[length] = '\0';
- return FindColor(buffer, length);
-}
-
bool Color::SetNamedColor(const String& name) {
const NamedColor* found_color = FindNamedColor(name);
color_ = found_color ? found_color->argb_value : 0;
@@ -334,18 +350,6 @@ Color Color::CombineWithAlpha(float other_alpha) const {
return rgb_only | ColorFloatToRGBAByte(override_alpha) << 24;
}
-static int BlendComponent(int c, int a) {
- // We use white.
- float alpha = a / 255.0f;
- int white_blend = 255 - a;
- c -= white_blend;
- return static_cast<int>(c / alpha);
-}
-
-const int kCStartAlpha = 153; // 60%
-const int kCEndAlpha = 204; // 80%;
-const int kCAlphaIncrement = 17; // Increments in between.
-
Color Color::Blend(const Color& source) const {
if (!Alpha() || !source.HasAlpha())
return source;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc b/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc
index bd0d4c5fc2d..be9982fb790 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.cc
@@ -4,8 +4,8 @@
#include "third_party/blink/renderer/platform/graphics/color_correction_test_utils.h"
+#include "base/sys_byteorder.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/wtf/byte_swap.h"
namespace blink {
@@ -144,7 +144,7 @@ bool ColorCorrectionTestUtils::ConvertPixelsToColorSpaceAndPixelFormatForTest(
src_color_format =
SkColorSpaceXform::ColorFormat::kRGBA_U16_BE_ColorFormat;
for (int i = 0; i < num_elements; i++)
- *(u16_buffer + i) = WTF::Bswap16(*(u16_buffer + i));
+ u16_buffer[i] = base::ByteSwap(u16_buffer[i]);
break;
case kFloat32ArrayStorageFormat:
@@ -186,9 +186,108 @@ bool ColorCorrectionTestUtils::ConvertPixelsToColorSpaceAndPixelFormatForTest(
if (src_storage_format == kUint16ArrayStorageFormat) {
for (int i = 0; i < num_elements; i++)
- *(u16_buffer + i) = WTF::Bswap16(*(u16_buffer + i));
+ u16_buffer[i] = base::ByteSwap(u16_buffer[i]);
}
return conversion_result;
}
+bool ColorCorrectionTestUtils::MatchColorSpace(
+ SkColorSpace* src_color_space,
+ SkColorSpace* dst_color_space,
+ float xyz_d50_component_tolerance) {
+ if ((!src_color_space && dst_color_space) ||
+ (src_color_space && !dst_color_space))
+ return false;
+ if (src_color_space) {
+ const SkMatrix44* src_matrix = src_color_space->toXYZD50();
+ const SkMatrix44* dst_matrix = dst_color_space->toXYZD50();
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ if (fabs(src_matrix->get(i, j) - dst_matrix->get(i, j)) >
+ xyz_d50_component_tolerance) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+bool ColorCorrectionTestUtils::MatchSkImages(sk_sp<SkImage> src_image,
+ sk_sp<SkImage> dst_image,
+ unsigned uint8_tolerance,
+ float f16_tolerance,
+ float xyz_d50_component_tolerance,
+ bool compare_alpha) {
+ if ((!src_image && dst_image) || (src_image && !dst_image))
+ return false;
+ if (!src_image)
+ return true;
+ if ((src_image->width() != dst_image->width()) ||
+ (src_image->height() != dst_image->height())) {
+ return false;
+ }
+
+ if (compare_alpha && src_image->alphaType() != dst_image->alphaType())
+ return false;
+ if (src_image->makeRasterImage()->colorType() !=
+ dst_image->makeRasterImage()->colorType()) {
+ return false;
+ }
+ if (!MatchColorSpace(src_image->colorSpace(), dst_image->colorSpace(),
+ xyz_d50_component_tolerance)) {
+ return false;
+ }
+
+ bool test_passed = true;
+ int num_pixels = src_image->width() * src_image->height();
+ int num_components = compare_alpha ? 4 : 3;
+
+ SkImageInfo src_info = SkImageInfo::Make(
+ src_image->width(), src_image->height(), kN32_SkColorType,
+ src_image->alphaType(), src_image->refColorSpace());
+
+ SkImageInfo dst_info = SkImageInfo::Make(
+ dst_image->width(), dst_image->height(), kN32_SkColorType,
+ src_image->alphaType(), dst_image->refColorSpace());
+
+ if (src_image->colorType() != kRGBA_F16_SkColorType) {
+ std::unique_ptr<uint8_t[]> src_pixels(new uint8_t[num_pixels * 4]());
+ std::unique_ptr<uint8_t[]> dst_pixels(new uint8_t[num_pixels * 4]());
+
+ src_image->readPixels(src_info, src_pixels.get(), src_info.minRowBytes(), 0,
+ 0);
+ dst_image->readPixels(dst_info, dst_pixels.get(), dst_info.minRowBytes(), 0,
+ 0);
+
+ for (int i = 0; test_passed && i < num_pixels; i++) {
+ for (int j = 0; j < num_components; j++) {
+ test_passed &= IsNearlyTheSame(src_pixels[i * 4 + j],
+ dst_pixels[i * 4 + j], uint8_tolerance);
+ }
+ }
+ return test_passed;
+ }
+
+ std::unique_ptr<uint16_t[]> src_pixels(new uint16_t[num_pixels * 4]());
+ std::unique_ptr<uint16_t[]> dst_pixels(new uint16_t[num_pixels * 4]());
+
+ src_info = src_info.makeColorType(kRGBA_F16_SkColorType);
+ dst_info = dst_info.makeColorType(kRGBA_F16_SkColorType);
+
+ src_image->readPixels(src_info, src_pixels.get(), src_info.minRowBytes(), 0,
+ 0);
+ dst_image->readPixels(dst_info, dst_pixels.get(), dst_info.minRowBytes(), 0,
+ 0);
+
+ for (int i = 0; test_passed && i < num_pixels; i++) {
+ for (int j = 0; j < num_components; j++) {
+ test_passed &=
+ IsNearlyTheSame(Float16ToFloat(src_pixels[i * 4 + j]),
+ Float16ToFloat(dst_pixels[i * 4 + j]), f16_tolerance);
+ }
+ }
+ return test_passed;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.h b/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.h
index 294b15964aa..aa8aae80411 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/color_correction_test_utils.h
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/skia/include/core/SkColorSpaceXform.h"
+#include "third_party/skia/include/core/SkImage.h"
namespace blink {
@@ -43,6 +44,17 @@ class ColorCorrectionTestUtils {
std::unique_ptr<uint8_t[]>& converted_pixels,
SkColorSpaceXform::ColorFormat color_format_for_f16_canvas);
+ static bool MatchColorSpace(SkColorSpace* src_color_space,
+ SkColorSpace* dst_color_space,
+ float xyz_d50_component_tolerance);
+
+ static bool MatchSkImages(sk_sp<SkImage> src_image,
+ sk_sp<SkImage> dst_image,
+ unsigned uint8_tolerance,
+ float f16_tolerance,
+ float xyz_d50_component_tolerance,
+ bool compare_alpha);
+
private:
static bool IsNearlyTheSame(float expected, float actual, float tolerance);
};
diff --git a/chromium/third_party/blink/renderer/platform/graphics/color_space_profile_data.cc b/chromium/third_party/blink/renderer/platform/graphics/color_space_profile_data.cc
index 1a1c6f5f65c..c814699c9c7 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/color_space_profile_data.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/color_space_profile_data.cc
@@ -4,7 +4,8 @@
#include "third_party/blink/renderer/platform/graphics/color_space_profile_data.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "base/logging.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
struct bt709ColorProfile {
static char* data() // BT.709 HDTV ITU
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper_test.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper_test.cc
index 96707191331..44ffb1a6f6e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper_test.cc
@@ -27,27 +27,29 @@ class ChunkToLayerMapperTest : public testing::Test {
// A state containing arbitrary values which should not affect test results
// if the state is used as a layer state.
PropertyTreeState LayerState() {
- DEFINE_STATIC_REF(
- TransformPaintPropertyNode, transform,
- CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix().Translate(123, 456),
- FloatPoint3D(1, 2, 3)));
- DEFINE_STATIC_REF(ClipPaintPropertyNode, clip,
- CreateClip(ClipPaintPropertyNode::Root(), transform,
- FloatRoundedRect(12, 34, 56, 78)));
- DEFINE_STATIC_REF(
- EffectPaintPropertyNode, effect,
- EffectPaintPropertyNode::Create(
- EffectPaintPropertyNode::Root(),
- EffectPaintPropertyNode::State{
- transform, clip, kColorFilterLuminanceToAlpha,
- CompositorFilterOperations(), 0.789f, SkBlendMode::kSrcIn}));
- return PropertyTreeState(transform, clip, effect);
+ if (!layer_transform_) {
+ layer_transform_ =
+ CreateTransform(t0(), TransformationMatrix().Translate(123, 456),
+ FloatPoint3D(1, 2, 3));
+ layer_clip_ = CreateClip(c0(), layer_transform_.get(),
+ FloatRoundedRect(12, 34, 56, 78));
+ layer_effect_ = EffectPaintPropertyNode::Create(
+ e0(), EffectPaintPropertyNode::State{
+ layer_transform_.get(), layer_clip_.get(),
+ kColorFilterLuminanceToAlpha, CompositorFilterOperations(),
+ 0.789f, SkBlendMode::kSrcIn});
+ }
+ return PropertyTreeState(layer_transform_.get(), layer_clip_.get(),
+ layer_effect_.get());
}
bool HasFilterThatMovesPixels(const ChunkToLayerMapper& mapper) {
return mapper.has_filter_that_moves_pixels_;
}
+
+ scoped_refptr<TransformPaintPropertyNode> layer_transform_;
+ scoped_refptr<ClipPaintPropertyNode> layer_clip_;
+ scoped_refptr<EffectPaintPropertyNode> layer_effect_;
};
TEST_F(ChunkToLayerMapperTest, OneChunkUsingLayerState) {
@@ -92,9 +94,9 @@ TEST_F(ChunkToLayerMapperTest, TwoChunkUsingLayerState) {
TEST_F(ChunkToLayerMapperTest, TwoChunkSameState) {
ChunkToLayerMapper mapper(LayerState(), gfx::Vector2dF(10, 20));
- auto transform = CreateTransform(LayerState().Transform(),
+ auto transform = CreateTransform(*LayerState().Transform(),
TransformationMatrix().Scale(2));
- auto clip = CreateClip(LayerState().Clip(), LayerState().Transform(),
+ auto clip = CreateClip(*LayerState().Clip(), LayerState().Transform(),
FloatRoundedRect(10, 10, 100, 100));
auto* effect = LayerState().Effect();
auto chunk1 = Chunk(PropertyTreeState(transform.get(), clip.get(), effect));
@@ -123,16 +125,16 @@ TEST_F(ChunkToLayerMapperTest, TwoChunkSameState) {
TEST_F(ChunkToLayerMapperTest, TwoChunkDifferentState) {
ChunkToLayerMapper mapper(LayerState(), gfx::Vector2dF(10, 20));
- auto transform1 = CreateTransform(LayerState().Transform(),
+ auto transform1 = CreateTransform(*LayerState().Transform(),
TransformationMatrix().Scale(2));
- auto clip1 = CreateClip(LayerState().Clip(), LayerState().Transform(),
+ auto clip1 = CreateClip(*LayerState().Clip(), LayerState().Transform(),
FloatRoundedRect(10, 10, 100, 100));
auto* effect = LayerState().Effect();
auto chunk1 = Chunk(PropertyTreeState(transform1.get(), clip1.get(), effect));
auto transform2 =
- CreateTransform(transform1, TransformationMatrix().Translate(20, 30));
- auto clip2 = CreateClip(LayerState().Clip(), transform2,
+ CreateTransform(*transform1, TransformationMatrix().Translate(20, 30));
+ auto clip2 = CreateClip(*LayerState().Clip(), transform2.get(),
FloatRoundedRect(0, 0, 20, 20));
auto chunk2 = Chunk(PropertyTreeState(transform2.get(), clip2.get(), effect));
@@ -165,13 +167,13 @@ TEST_F(ChunkToLayerMapperTest, SlowPath) {
// Chunk2 has a blur filter. Should use the slow path.
CompositorFilterOperations filter2;
filter2.AppendBlurFilter(20);
- auto effect2 = CreateFilterEffect(LayerState().Effect(), std::move(filter2));
+ auto effect2 = CreateFilterEffect(*LayerState().Effect(), std::move(filter2));
auto chunk2 = Chunk(PropertyTreeState(LayerState().Transform(),
LayerState().Clip(), effect2.get()));
// Chunk3 has a different effect which inherits from chunk2's effect.
// Should use the slow path.
- auto effect3 = CreateOpacityEffect(effect2, 1.f);
+ auto effect3 = CreateOpacityEffect(*effect2, 1.f);
auto chunk3 = Chunk(PropertyTreeState(LayerState().Transform(),
LayerState().Clip(), effect3.get()));
@@ -179,7 +181,7 @@ TEST_F(ChunkToLayerMapperTest, SlowPath) {
// Should use the fast path.
CompositorFilterOperations filter4;
filter4.AppendOpacityFilter(0.5);
- auto effect4 = CreateFilterEffect(LayerState().Effect(), std::move(filter4));
+ auto effect4 = CreateFilterEffect(*LayerState().Effect(), std::move(filter4));
auto chunk4 = Chunk(PropertyTreeState(LayerState().Transform(),
LayerState().Clip(), effect4.get()));
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/composited_layer_raster_invalidator.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/composited_layer_raster_invalidator.cc
deleted file mode 100644
index f6df3bc1161..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/composited_layer_raster_invalidator.cc
+++ /dev/null
@@ -1,337 +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/platform/graphics/compositing/composited_layer_raster_invalidator.h"
-
-#include <algorithm>
-#include <memory>
-#include <utility>
-
-#include "third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
-
-namespace blink {
-
-void CompositedLayerRasterInvalidator::SetTracksRasterInvalidations(
- bool should_track) {
- if (should_track) {
- if (!tracking_info_)
- tracking_info_ = std::make_unique<RasterInvalidationTrackingInfo>();
- tracking_info_->tracking.ClearInvalidations();
- for (const auto& info : paint_chunks_info_) {
- tracking_info_->old_client_debug_names.Set(&info.id.client,
- info.id.client.DebugName());
- }
- } else if (!RasterInvalidationTracking::ShouldAlwaysTrack()) {
- tracking_info_ = nullptr;
- } else if (tracking_info_) {
- tracking_info_->tracking.ClearInvalidations();
- }
-}
-
-size_t CompositedLayerRasterInvalidator::MatchNewChunkToOldChunk(
- const PaintChunk& new_chunk,
- size_t old_index) {
- for (size_t i = old_index; i < paint_chunks_info_.size(); i++) {
- if (paint_chunks_info_[i].Matches(new_chunk))
- return i;
- }
- for (size_t i = 0; i < old_index; i++) {
- if (paint_chunks_info_[i].Matches(new_chunk))
- return i;
- }
- return kNotFound;
-}
-
-static bool ApproximatelyEqual(const SkMatrix& a, const SkMatrix& b) {
- static constexpr float kTolerance = 1e-5f;
- for (int i = 0; i < 9; i++) {
- if (std::abs(a[i] - b[i]) > kTolerance)
- return false;
- }
- return true;
-}
-
-PaintInvalidationReason
-CompositedLayerRasterInvalidator::ChunkPropertiesChanged(
- const RefCountedPropertyTreeState& new_chunk_state,
- const PaintChunkInfo& new_chunk,
- const PaintChunkInfo& old_chunk,
- const PropertyTreeState& layer_state) const {
- // Special case for transform changes because we may create or delete some
- // transform nodes when no raster invalidation is needed. For example, when
- // a composited layer previously not transformed now gets transformed.
- // Check for real accumulated transform change instead.
- if (!ApproximatelyEqual(new_chunk.chunk_to_layer_transform,
- old_chunk.chunk_to_layer_transform))
- return PaintInvalidationReason::kPaintProperty;
-
- // Treat the chunk property as changed if the effect node pointer is
- // different, or the effect node's value changed between the layer state and
- // the chunk state.
- if (new_chunk_state.Effect() != old_chunk.effect_state ||
- new_chunk_state.Effect()->Changed(*layer_state.Effect()))
- return PaintInvalidationReason::kPaintProperty;
-
- // Check for accumulated clip rect change, if the clip rects are tight.
- if (new_chunk.chunk_to_layer_clip.IsTight() &&
- old_chunk.chunk_to_layer_clip.IsTight()) {
- if (new_chunk.chunk_to_layer_clip == old_chunk.chunk_to_layer_clip)
- return PaintInvalidationReason::kNone;
- // Ignore differences out of the current layer bounds.
- if (ClipByLayerBounds(new_chunk.chunk_to_layer_clip.Rect()) ==
- ClipByLayerBounds(old_chunk.chunk_to_layer_clip.Rect()))
- return PaintInvalidationReason::kNone;
- return PaintInvalidationReason::kIncremental;
- }
-
- // Otherwise treat the chunk property as changed if the clip node pointer is
- // different, or the clip node's value changed between the layer state and the
- // chunk state.
- if (new_chunk_state.Clip() != old_chunk.clip_state ||
- new_chunk_state.Clip()->Changed(*layer_state.Clip()))
- return PaintInvalidationReason::kPaintProperty;
-
- return PaintInvalidationReason::kNone;
-}
-
-// Generates raster invalidations by checking changes (appearing, disappearing,
-// reordering, property changes) of chunks. The logic is similar to
-// PaintController::GenerateRasterInvalidations(). The complexity is between
-// O(n) and O(m*n) where m and n are the numbers of old and new chunks,
-// respectively. Normally both m and n are small numbers. The best caseis that
-// all old chunks have matching new chunks in the same order. The worst case is
-// that no matching chunks except the first one (which always matches otherwise
-// we won't reuse the CompositedLayerRasterInvalidator), which is rare. In
-// common cases that most of the chunks can be matched in-order, the complexity
-// is slightly larger than O(n).
-void CompositedLayerRasterInvalidator::GenerateRasterInvalidations(
- const PaintArtifact& paint_artifact,
- const PaintChunkSubset& new_chunks,
- const PropertyTreeState& layer_state,
- const FloatSize& visual_rect_subpixel_offset,
- Vector<PaintChunkInfo>& new_chunks_info) {
- ChunkToLayerMapper mapper(layer_state, layer_bounds_.OffsetFromOrigin(),
- visual_rect_subpixel_offset);
- Vector<bool> old_chunks_matched;
- old_chunks_matched.resize(paint_chunks_info_.size());
- size_t old_index = 0;
- size_t max_matched_old_index = 0;
- for (const auto& new_chunk : new_chunks) {
- mapper.SwitchToChunk(new_chunk);
- auto& new_chunk_info =
- new_chunks_info.emplace_back(*this, mapper, new_chunk);
-
- if (!new_chunk.is_cacheable) {
- FullyInvalidateNewChunk(new_chunk_info,
- PaintInvalidationReason::kChunkUncacheable);
- continue;
- }
-
- size_t matched_old_index = MatchNewChunkToOldChunk(new_chunk, old_index);
- if (matched_old_index == kNotFound) {
- // The new chunk doesn't match any old chunk.
- FullyInvalidateNewChunk(new_chunk_info,
- PaintInvalidationReason::kChunkAppeared);
- continue;
- }
-
- DCHECK(!old_chunks_matched[matched_old_index]);
- old_chunks_matched[matched_old_index] = true;
-
- auto& old_chunk_info = paint_chunks_info_[matched_old_index];
- // Clip the old chunk bounds by the new layer bounds.
- old_chunk_info.bounds_in_layer =
- ClipByLayerBounds(old_chunk_info.bounds_in_layer);
-
- PaintInvalidationReason reason =
- matched_old_index < max_matched_old_index
- ? PaintInvalidationReason::kChunkReordered
- : ChunkPropertiesChanged(new_chunk.properties, new_chunk_info,
- old_chunk_info, layer_state);
-
- if (IsFullPaintInvalidationReason(reason)) {
- // Invalidate both old and new bounds of the chunk if the chunk's paint
- // properties changed, or is moved backward and may expose area that was
- // previously covered by it.
- FullyInvalidateChunk(old_chunk_info, new_chunk_info, reason);
- // Ignore the display item raster invalidations because we have fully
- // invalidated the chunk.
- } else {
- // We may have ignored tiny changes of transform, in which case we should
- // use the old chunk_to_layer_transform for later comparison to correctly
- // invalidate animating transform in tiny increments when the accumulated
- // change exceeds the tolerance.
- new_chunk_info.chunk_to_layer_transform =
- old_chunk_info.chunk_to_layer_transform;
-
- if (reason == PaintInvalidationReason::kIncremental)
- IncrementallyInvalidateChunk(old_chunk_info, new_chunk_info);
-
- // Add the raster invalidations found by PaintController within the chunk.
- AddDisplayItemRasterInvalidations(paint_artifact, new_chunk, mapper);
- }
-
- old_index = matched_old_index + 1;
- if (old_index == paint_chunks_info_.size())
- old_index = 0;
- max_matched_old_index = std::max(max_matched_old_index, matched_old_index);
- }
-
- // Invalidate remaining unmatched (disappeared or uncacheable) old chunks.
- for (size_t i = 0; i < paint_chunks_info_.size(); ++i) {
- if (old_chunks_matched[i])
- continue;
- FullyInvalidateOldChunk(paint_chunks_info_[i],
- paint_chunks_info_[i].is_cacheable
- ? PaintInvalidationReason::kChunkDisappeared
- : PaintInvalidationReason::kChunkUncacheable);
- }
-}
-
-void CompositedLayerRasterInvalidator::AddDisplayItemRasterInvalidations(
- const PaintArtifact& paint_artifact,
- const PaintChunk& chunk,
- const ChunkToLayerMapper& mapper) {
- const auto* rects = paint_artifact.GetRasterInvalidationRects(chunk);
- if (!rects || rects->IsEmpty())
- return;
-
- const auto* tracking = paint_artifact.GetRasterInvalidationTracking(chunk);
- DCHECK(!tracking || tracking->IsEmpty() || tracking->size() == rects->size());
-
- for (size_t i = 0; i < rects->size(); ++i) {
- auto rect = ClipByLayerBounds(mapper.MapVisualRect((*rects)[i]));
- if (rect.IsEmpty())
- continue;
- raster_invalidation_function_(rect);
-
- if (tracking && !tracking->IsEmpty()) {
- const auto& info = (*tracking)[i];
- tracking_info_->tracking.AddInvalidation(
- info.client, info.client_debug_name, rect, info.reason);
- }
- }
-}
-
-void CompositedLayerRasterInvalidator::IncrementallyInvalidateChunk(
- const PaintChunkInfo& old_chunk,
- const PaintChunkInfo& new_chunk) {
- SkRegion diff(old_chunk.bounds_in_layer);
- diff.op(new_chunk.bounds_in_layer, SkRegion::kXOR_Op);
- for (SkRegion::Iterator it(diff); !it.done(); it.next()) {
- const SkIRect& r = it.rect();
- AddRasterInvalidation(IntRect(r.x(), r.y(), r.width(), r.height()),
- &new_chunk.id.client,
- PaintInvalidationReason::kIncremental);
- }
-}
-
-void CompositedLayerRasterInvalidator::FullyInvalidateChunk(
- const PaintChunkInfo& old_chunk,
- const PaintChunkInfo& new_chunk,
- PaintInvalidationReason reason) {
- FullyInvalidateOldChunk(old_chunk, reason);
- if (old_chunk.bounds_in_layer != new_chunk.bounds_in_layer)
- FullyInvalidateNewChunk(new_chunk, reason);
-}
-
-void CompositedLayerRasterInvalidator::FullyInvalidateNewChunk(
- const PaintChunkInfo& info,
- PaintInvalidationReason reason) {
- AddRasterInvalidation(info.bounds_in_layer, &info.id.client, reason);
-}
-
-void CompositedLayerRasterInvalidator::FullyInvalidateOldChunk(
- const PaintChunkInfo& info,
- PaintInvalidationReason reason) {
- String debug_name;
- if (tracking_info_)
- debug_name = tracking_info_->old_client_debug_names.at(&info.id.client);
- AddRasterInvalidation(info.bounds_in_layer, &info.id.client, reason,
- &debug_name);
-}
-
-void CompositedLayerRasterInvalidator::AddRasterInvalidation(
- const IntRect& rect,
- const DisplayItemClient* client,
- PaintInvalidationReason reason,
- const String* debug_name) {
- raster_invalidation_function_(rect);
- if (tracking_info_) {
- tracking_info_->tracking.AddInvalidation(
- client, debug_name ? *debug_name : client->DebugName(), rect, reason);
- }
-}
-
-RasterInvalidationTracking& CompositedLayerRasterInvalidator::EnsureTracking() {
- if (!tracking_info_)
- tracking_info_ = std::make_unique<RasterInvalidationTrackingInfo>();
- return tracking_info_->tracking;
-}
-
-void CompositedLayerRasterInvalidator::Generate(
- const PaintArtifact& paint_artifact,
- const gfx::Rect& layer_bounds,
- const PropertyTreeState& layer_state,
- const FloatSize& visual_rect_subpixel_offset) {
- Generate(paint_artifact, paint_artifact.PaintChunks(), layer_bounds,
- layer_state, visual_rect_subpixel_offset);
-}
-
-void CompositedLayerRasterInvalidator::Generate(
- const PaintArtifact& paint_artifact,
- const PaintChunkSubset& paint_chunks,
- const gfx::Rect& layer_bounds,
- const PropertyTreeState& layer_state,
- const FloatSize& visual_rect_subpixel_offset) {
- if (RuntimeEnabledFeatures::DisableRasterInvalidationEnabled())
- return;
-
- if (RasterInvalidationTracking::ShouldAlwaysTrack())
- EnsureTracking();
-
- if (tracking_info_) {
- for (const auto& chunk : paint_chunks) {
- tracking_info_->new_client_debug_names.insert(
- &chunk.id.client, chunk.id.client.DebugName());
- }
- }
-
- bool layer_bounds_was_empty = layer_bounds_.IsEmpty();
- layer_bounds_ = layer_bounds;
-
- Vector<PaintChunkInfo> new_chunks_info;
- new_chunks_info.ReserveCapacity(paint_chunks.size());
-
- if (layer_bounds_was_empty || layer_bounds_.IsEmpty()) {
- // No raster invalidation is needed if either the old bounds or the new
- // bounds is empty, but we still need to update new_chunks_info for the
- // next cycle.
- ChunkToLayerMapper mapper(layer_state, layer_bounds.OffsetFromOrigin(),
- visual_rect_subpixel_offset);
- for (const auto& chunk : paint_chunks) {
- mapper.SwitchToChunk(chunk);
- new_chunks_info.emplace_back(*this, mapper, chunk);
- }
- } else {
- GenerateRasterInvalidations(paint_artifact, paint_chunks, layer_state,
- visual_rect_subpixel_offset, new_chunks_info);
- }
-
- paint_chunks_info_ = std::move(new_chunks_info);
-
- if (tracking_info_) {
- tracking_info_->old_client_debug_names =
- std::move(tracking_info_->new_client_debug_names);
- }
-}
-
-size_t CompositedLayerRasterInvalidator::ApproximateUnsharedMemoryUsage()
- const {
- return sizeof(*this) + paint_chunks_info_.capacity() * sizeof(PaintChunkInfo);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/composited_layer_raster_invalidator.h b/chromium/third_party/blink/renderer/platform/graphics/compositing/composited_layer_raster_invalidator.h
deleted file mode 100644
index cdf1dafe1fd..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/composited_layer_raster_invalidator.h
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_COMPOSITING_COMPOSITED_LAYER_RASTER_INVALIDATOR_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_COMPOSITING_COMPOSITED_LAYER_RASTER_INVALIDATOR_H_
-
-#include "third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.h"
-#include "third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_chunk.h"
-#include "third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h"
-#include "third_party/blink/renderer/platform/wtf/hash_map.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-class PaintArtifact;
-class PaintChunkSubset;
-class IntRect;
-
-class PLATFORM_EXPORT CompositedLayerRasterInvalidator {
- public:
- using RasterInvalidationFunction = std::function<void(const IntRect&)>;
-
- CompositedLayerRasterInvalidator(
- RasterInvalidationFunction raster_invalidation_function)
- : raster_invalidation_function_(raster_invalidation_function) {}
-
- void SetTracksRasterInvalidations(bool);
- RasterInvalidationTracking* GetTracking() const {
- return tracking_info_ ? &tracking_info_->tracking : nullptr;
- }
-
- RasterInvalidationTracking& EnsureTracking();
-
- // Generate raster invalidations for all of the paint chunks in the paint
- // artifact.
- void Generate(const PaintArtifact&,
- const gfx::Rect& layer_bounds,
- const PropertyTreeState& layer_state,
- const FloatSize& visual_rect_subpixel_offset = FloatSize());
-
- // Generate raster invalidations for a subset of the paint chunks in the
- // paint artifact.
- void Generate(const PaintArtifact&,
- const PaintChunkSubset&,
- const gfx::Rect& layer_bounds,
- const PropertyTreeState& layer_state,
- const FloatSize& visual_rect_subpixel_offset = FloatSize());
-
- bool Matches(const PaintChunk& paint_chunk) const {
- return paint_chunks_info_.size() && paint_chunks_info_[0].is_cacheable &&
- paint_chunk.Matches(paint_chunks_info_[0].id);
- }
-
- const gfx::Rect& LayerBounds() const { return layer_bounds_; }
-
- size_t ApproximateUnsharedMemoryUsage() const;
-
- private:
- friend class CompositedLayerRasterInvalidatorTest;
-
- struct PaintChunkInfo {
- PaintChunkInfo(const CompositedLayerRasterInvalidator& invalidator,
- const ChunkToLayerMapper& mapper,
- const PaintChunk& chunk)
- : id(chunk.id),
- clip_state(chunk.properties.Clip()),
- effect_state(chunk.properties.Effect()),
- is_cacheable(chunk.is_cacheable),
- bounds_in_layer(invalidator.ClipByLayerBounds(
- mapper.MapVisualRect(chunk.bounds))),
- chunk_to_layer_clip(mapper.ClipRect()),
- chunk_to_layer_transform(
- TransformationMatrix::ToSkMatrix44(mapper.Transform())) {}
-
- bool Matches(const PaintChunk& new_chunk) const {
- return is_cacheable && new_chunk.Matches(id);
- }
-
- PaintChunk::Id id;
- // These two pointers are for property change detection. The pointed
- // property nodes can be freed after this structure is created. As newly
- // created property nodes always have Changed() flag set, it's not a problem
- // that a new node is created at the address pointed by these pointers.
- const void* clip_state;
- const void* effect_state;
- bool is_cacheable;
- IntRect bounds_in_layer;
- FloatClipRect chunk_to_layer_clip;
- SkMatrix chunk_to_layer_transform;
- };
-
- void GenerateRasterInvalidations(const PaintArtifact&,
- const PaintChunkSubset&,
- const PropertyTreeState& layer_state,
- const FloatSize& visual_rect_subpixel_offset,
- Vector<PaintChunkInfo>& new_chunks_info);
- size_t MatchNewChunkToOldChunk(const PaintChunk& new_chunk, size_t old_index);
- void AddDisplayItemRasterInvalidations(const PaintArtifact&,
- const PaintChunk&,
- const ChunkToLayerMapper&);
- void IncrementallyInvalidateChunk(const PaintChunkInfo& old_chunk,
- const PaintChunkInfo& new_chunk);
- void FullyInvalidateChunk(const PaintChunkInfo& old_chunk,
- const PaintChunkInfo& new_chunk,
- PaintInvalidationReason);
- ALWAYS_INLINE void FullyInvalidateNewChunk(const PaintChunkInfo&,
- PaintInvalidationReason);
- ALWAYS_INLINE void FullyInvalidateOldChunk(const PaintChunkInfo&,
- PaintInvalidationReason);
- ALWAYS_INLINE void AddRasterInvalidation(const IntRect&,
- const DisplayItemClient*,
- PaintInvalidationReason,
- const String* debug_name = nullptr);
- PaintInvalidationReason ChunkPropertiesChanged(
- const RefCountedPropertyTreeState& new_chunk_state,
- const PaintChunkInfo& new_chunk,
- const PaintChunkInfo& old_chunk,
- const PropertyTreeState& layer_state) const;
-
- // Clip a rect in the layer space by the layer bounds.
- template <typename Rect>
- Rect ClipByLayerBounds(const Rect& r) const {
- return Intersection(
- r, Rect(0, 0, layer_bounds_.width(), layer_bounds_.height()));
- }
-
- RasterInvalidationFunction raster_invalidation_function_;
- gfx::Rect layer_bounds_;
- Vector<PaintChunkInfo> paint_chunks_info_;
-
- struct RasterInvalidationTrackingInfo {
- using ClientDebugNamesMap = HashMap<const DisplayItemClient*, String>;
- ClientDebugNamesMap new_client_debug_names;
- ClientDebugNamesMap old_client_debug_names;
- RasterInvalidationTracking tracking;
- };
- std::unique_ptr<RasterInvalidationTrackingInfo> tracking_info_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_COMPOSITING_COMPOSITED_LAYER_RASTER_INVALIDATOR_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/composited_layer_raster_invalidator_test.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/composited_layer_raster_invalidator_test.cc
deleted file mode 100644
index c12c25ee260..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/composited_layer_raster_invalidator_test.cc
+++ /dev/null
@@ -1,681 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/compositing/composited_layer_raster_invalidator.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
-#include "third_party/blink/renderer/platform/testing/fake_display_item_client.h"
-#include "third_party/blink/renderer/platform/testing/paint_property_test_helpers.h"
-#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
-#include "third_party/blink/renderer/platform/wtf/dtoa/utils.h"
-
-namespace blink {
-
-static const IntRect kDefaultLayerBounds(-9999, -7777, 18888, 16666);
-
-class CompositedLayerRasterInvalidatorTest
- : public testing::Test,
- private ScopedSlimmingPaintV2ForTest {
- public:
- CompositedLayerRasterInvalidatorTest() : ScopedSlimmingPaintV2ForTest(true) {}
-
- static PropertyTreeState DefaultPropertyTreeState() {
- return PropertyTreeState::Root();
- }
-
- CompositedLayerRasterInvalidatorTest& Chunk(int type) {
- DEFINE_STATIC_LOCAL(FakeDisplayItemClient, fake_client, ());
- fake_client.ClearIsJustCreated();
- // The enum arithmetics and magic numbers are to produce different values
- // of paint chunk and raster invalidation properties.
- PaintChunk::Id id(fake_client, static_cast<DisplayItem::Type>(
- DisplayItem::kDrawingFirst + type));
- data_.chunks.emplace_back(0, 0, id, DefaultPropertyTreeState());
- data_.chunks.back().bounds =
- FloatRect(type * 110, type * 220, type * 220 + 200, type * 110 + 200);
- return *this;
- }
-
- CompositedLayerRasterInvalidatorTest& Properties(
- const TransformPaintPropertyNode* t,
- const ClipPaintPropertyNode* c = ClipPaintPropertyNode::Root(),
- const EffectPaintPropertyNode* e = EffectPaintPropertyNode::Root()) {
- auto& state = data_.chunks.back().properties;
- state.SetTransform(t);
- state.SetClip(c);
- state.SetEffect(e);
- return *this;
- }
-
- CompositedLayerRasterInvalidatorTest& Properties(
- const RefCountedPropertyTreeState& state) {
- data_.chunks.back().properties = state;
- return *this;
- }
-
- CompositedLayerRasterInvalidatorTest& Uncacheable() {
- data_.chunks.back().is_cacheable = false;
- return *this;
- }
-
- CompositedLayerRasterInvalidatorTest& Bounds(const FloatRect& bounds) {
- data_.chunks.back().bounds = bounds;
- return *this;
- }
-
- CompositedLayerRasterInvalidatorTest& RasterInvalidationCount(int count) {
- size_t size = data_.chunks.size();
- DCHECK_GT(size, 0u);
- data_.raster_invalidation_rects.resize(size);
- data_.raster_invalidation_trackings.resize(size);
- int index = static_cast<int>(size - 1);
- for (int i = 0; i < count; ++i) {
- IntRect rect(index * 11, index * 22, index * 22 + 100 + i,
- index * 11 + 100 + i);
- data_.raster_invalidation_rects.back().push_back(FloatRect(rect));
- data_.raster_invalidation_trackings.back().push_back(
- RasterInvalidationInfo{
- &data_.chunks.back().id.client, "Test", rect,
- static_cast<PaintInvalidationReason>(
- static_cast<int>(PaintInvalidationReason::kFull) + index +
- i)});
- }
- return *this;
- }
-
- PaintArtifact Build() {
- return PaintArtifact(DisplayItemList(0), std::move(data_));
- }
-
- static const Vector<RasterInvalidationInfo> TrackedRasterInvalidations(
- CompositedLayerRasterInvalidator& invalidator) {
- DCHECK(invalidator.GetTracking());
- return invalidator.GetTracking()->Invalidations();
- }
-
- static IntRect ChunkRectToLayer(const FloatRect& rect,
- const IntPoint& chunk_offset_from_layer) {
- FloatRect r = rect;
- r.MoveBy(chunk_offset_from_layer);
- return EnclosingIntRect(r);
- }
-
- CompositedLayerRasterInvalidator::RasterInvalidationFunction
- kNoopRasterInvalidation = [this](const IntRect& rect) {};
-
- PaintChunksAndRasterInvalidations data_;
-};
-
-#define EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, invalidation_index, \
- artifact, chunk_index) \
- do { \
- const auto& chunk = (artifact).PaintChunks()[chunk_index]; \
- const auto* rects = (artifact).GetRasterInvalidationRects(chunk); \
- ASSERT_TRUE(rects); \
- const auto* tracking = (artifact).GetRasterInvalidationTracking(chunk); \
- ASSERT_TRUE(tracking); \
- for (size_t i = 0; i < rects->size(); ++i) { \
- SCOPED_TRACE(invalidation_index + i); \
- const auto& info = (invalidations)[invalidation_index + i]; \
- EXPECT_EQ( \
- ChunkRectToLayer((*rects)[i], -kDefaultLayerBounds.Location()), \
- info.rect); \
- EXPECT_EQ(&chunk.id.client, info.client); \
- EXPECT_EQ((*tracking)[i].reason, info.reason); \
- } \
- } while (false)
-
-#define EXPECT_CHUNK_INVALIDATION_WITH_LAYER_OFFSET( \
- invalidations, index, chunk, expected_reason, layer_offset) \
- do { \
- const auto& info = (invalidations)[index]; \
- EXPECT_EQ(ChunkRectToLayer((chunk).bounds, layer_offset), info.rect); \
- EXPECT_EQ(&(chunk).id.client, info.client); \
- EXPECT_EQ(expected_reason, info.reason); \
- } while (false)
-
-#define EXPECT_CHUNK_INVALIDATION(invalidations, index, chunk, reason) \
- EXPECT_CHUNK_INVALIDATION_WITH_LAYER_OFFSET( \
- invalidations, index, chunk, reason, -kDefaultLayerBounds.Location())
-
-#define EXPECT_INCREMENTAL_INVALIDATION(invalidations, index, chunk, \
- chunk_rect) \
- do { \
- const auto& info = (invalidations)[index]; \
- EXPECT_EQ(ChunkRectToLayer(chunk_rect, -kDefaultLayerBounds.Location()), \
- info.rect); \
- EXPECT_EQ(&(chunk).id.client, info.client); \
- EXPECT_EQ(PaintInvalidationReason::kIncremental, info.reason); \
- } while (false)
-
-TEST_F(CompositedLayerRasterInvalidatorTest, LayerBounds) {
- CompositedLayerRasterInvalidator invalidator(kNoopRasterInvalidation);
- invalidator.SetTracksRasterInvalidations(true);
- auto artifact = Chunk(0).Build();
-
- invalidator.Generate(artifact, kDefaultLayerBounds,
- DefaultPropertyTreeState());
- // No raster invalidations needed for a new layer.
- EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
-
- invalidator.Generate(artifact, kDefaultLayerBounds,
- DefaultPropertyTreeState());
- // No raster invalidations needed if layer origin doesn't change.
- EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
-
- auto new_layer_bounds = kDefaultLayerBounds;
- new_layer_bounds.Move(66, 77);
- invalidator.Generate(artifact, new_layer_bounds, DefaultPropertyTreeState());
- // Change of layer origin causes change of chunk0's transform to layer.
- const auto& invalidations = TrackedRasterInvalidations(invalidator);
- ASSERT_EQ(2u, invalidations.size());
- EXPECT_CHUNK_INVALIDATION(invalidations, 0, artifact.PaintChunks()[0],
- PaintInvalidationReason::kPaintProperty);
- EXPECT_CHUNK_INVALIDATION_WITH_LAYER_OFFSET(
- invalidations, 1, artifact.PaintChunks()[0],
- PaintInvalidationReason::kPaintProperty, -new_layer_bounds.Location());
-}
-
-TEST_F(CompositedLayerRasterInvalidatorTest, ReorderChunks) {
- CompositedLayerRasterInvalidator invalidator(kNoopRasterInvalidation);
- auto artifact = Chunk(0).Chunk(1).Chunk(2).Build();
- invalidator.SetTracksRasterInvalidations(true);
- invalidator.Generate(artifact, kDefaultLayerBounds,
- DefaultPropertyTreeState());
- EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
-
- // Swap chunk 1 and 2. All chunks have their own local raster invalidations.
- auto new_artifact = Chunk(0)
- .RasterInvalidationCount(2)
- .Chunk(2)
- .RasterInvalidationCount(4)
- .Chunk(1)
- .RasterInvalidationCount(3)
- .Bounds(FloatRect(11, 22, 33, 44))
- .Build();
- invalidator.Generate(new_artifact, kDefaultLayerBounds,
- DefaultPropertyTreeState());
- const auto& invalidations = TrackedRasterInvalidations(invalidator);
- ASSERT_EQ(8u, invalidations.size());
- // The first chunk should always match because otherwise we won't reuse the
- // CompositedLayerRasterInvalidator (which is according to the first chunk's
- // id). For matched chunk, we issue raster invalidations if any found by
- // PaintController.
- EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 0, new_artifact, 0);
- EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 2, new_artifact, 1);
- // Invalidated new chunk 2's old (as chunks[1]) and new (as new_artifact[2])
- // bounds.
- EXPECT_CHUNK_INVALIDATION(invalidations, 6, artifact.PaintChunks()[1],
- PaintInvalidationReason::kChunkReordered);
- EXPECT_CHUNK_INVALIDATION(invalidations, 7, new_artifact.PaintChunks()[2],
- PaintInvalidationReason::kChunkReordered);
-}
-
-TEST_F(CompositedLayerRasterInvalidatorTest, ReorderChunkSubsequences) {
- CompositedLayerRasterInvalidator invalidator(kNoopRasterInvalidation);
- auto artifact = Chunk(0).Chunk(1).Chunk(2).Chunk(3).Chunk(4).Build();
- invalidator.SetTracksRasterInvalidations(true);
- invalidator.Generate(artifact, kDefaultLayerBounds,
- DefaultPropertyTreeState());
- EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
-
- // Swap chunk (1,2) and (3,4). All chunks have their own local raster
- // invalidations.
- auto new_artifact = Chunk(0)
- .RasterInvalidationCount(2)
- .Chunk(3)
- .RasterInvalidationCount(3)
- .Chunk(4)
- .RasterInvalidationCount(4)
- .Chunk(1)
- .RasterInvalidationCount(1)
- .Bounds(FloatRect(11, 22, 33, 44))
- .Chunk(2)
- .RasterInvalidationCount(2)
- .Build();
- invalidator.Generate(new_artifact, kDefaultLayerBounds,
- DefaultPropertyTreeState());
- const auto& invalidations = TrackedRasterInvalidations(invalidator);
- ASSERT_EQ(12u, invalidations.size());
- // The first chunk should always match because otherwise we won't reuse the
- // CompositedLayerRasterInvalidator (which is according to the first chunk's
- // id). For matched chunk, we issue raster invalidations if any found by
- // PaintController.
- EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 0, new_artifact, 0);
- EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 2, new_artifact, 1);
- EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 5, new_artifact, 2);
- // Invalidated new chunk 3's old (as chunks[1]) and new (as new_artifact[3])
- // bounds.
- EXPECT_CHUNK_INVALIDATION(invalidations, 9, artifact.PaintChunks()[1],
- PaintInvalidationReason::kChunkReordered);
- EXPECT_CHUNK_INVALIDATION(invalidations, 10, new_artifact.PaintChunks()[3],
- PaintInvalidationReason::kChunkReordered);
- // Invalidated new chunk 4's new bounds. Didn't invalidate old bounds because
- // it's the same as the new bounds.
- EXPECT_CHUNK_INVALIDATION(invalidations, 11, new_artifact.PaintChunks()[4],
- PaintInvalidationReason::kChunkReordered);
-}
-
-TEST_F(CompositedLayerRasterInvalidatorTest, AppearAndDisappear) {
- CompositedLayerRasterInvalidator invalidator(kNoopRasterInvalidation);
- auto artifact = Chunk(0).Chunk(1).Chunk(2).Build();
- invalidator.SetTracksRasterInvalidations(true);
- invalidator.Generate(artifact, kDefaultLayerBounds,
- DefaultPropertyTreeState());
- EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
-
- // Chunk 1 and 2 disappeared, 3 and 4 appeared. All chunks have their own
- // local raster invalidations.
- auto new_artifact = Chunk(0)
- .RasterInvalidationCount(2)
- .Chunk(3)
- .RasterInvalidationCount(3)
- .Chunk(4)
- .RasterInvalidationCount(3)
- .Build();
- invalidator.Generate(new_artifact, kDefaultLayerBounds,
- DefaultPropertyTreeState());
- const auto& invalidations = TrackedRasterInvalidations(invalidator);
- ASSERT_EQ(6u, invalidations.size());
- EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 0, new_artifact, 0);
- EXPECT_CHUNK_INVALIDATION(invalidations, 2, new_artifact.PaintChunks()[1],
- PaintInvalidationReason::kChunkAppeared);
- EXPECT_CHUNK_INVALIDATION(invalidations, 3, new_artifact.PaintChunks()[2],
- PaintInvalidationReason::kChunkAppeared);
- EXPECT_CHUNK_INVALIDATION(invalidations, 4, artifact.PaintChunks()[1],
- PaintInvalidationReason::kChunkDisappeared);
- EXPECT_CHUNK_INVALIDATION(invalidations, 5, artifact.PaintChunks()[2],
- PaintInvalidationReason::kChunkDisappeared);
-}
-
-TEST_F(CompositedLayerRasterInvalidatorTest, AppearAtEnd) {
- CompositedLayerRasterInvalidator invalidator(kNoopRasterInvalidation);
- auto artifact = Chunk(0).Build();
- invalidator.SetTracksRasterInvalidations(true);
- invalidator.Generate(artifact, kDefaultLayerBounds,
- DefaultPropertyTreeState());
- EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
-
- auto new_artifact = Chunk(0)
- .RasterInvalidationCount(2)
- .Chunk(1)
- .RasterInvalidationCount(3)
- .Chunk(2)
- .RasterInvalidationCount(3)
- .Build();
- invalidator.Generate(new_artifact, kDefaultLayerBounds,
- DefaultPropertyTreeState());
- const auto& invalidations = TrackedRasterInvalidations(invalidator);
- ASSERT_EQ(4u, invalidations.size());
- EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 0, new_artifact, 0);
- EXPECT_CHUNK_INVALIDATION(invalidations, 2, new_artifact.PaintChunks()[1],
- PaintInvalidationReason::kChunkAppeared);
- EXPECT_CHUNK_INVALIDATION(invalidations, 3, new_artifact.PaintChunks()[2],
- PaintInvalidationReason::kChunkAppeared);
-}
-
-TEST_F(CompositedLayerRasterInvalidatorTest, UncacheableChunks) {
- CompositedLayerRasterInvalidator invalidator(kNoopRasterInvalidation);
- auto artifact = Chunk(0).Chunk(1).Uncacheable().Chunk(2).Build();
-
- invalidator.SetTracksRasterInvalidations(true);
- invalidator.Generate(artifact, kDefaultLayerBounds,
- DefaultPropertyTreeState());
- EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
-
- auto new_artifact = Chunk(0)
- .RasterInvalidationCount(2)
- .Chunk(2)
- .RasterInvalidationCount(3)
- .Chunk(1)
- .RasterInvalidationCount(3)
- .Uncacheable()
- .Build();
- invalidator.Generate(new_artifact, kDefaultLayerBounds,
- DefaultPropertyTreeState());
- const auto& invalidations = TrackedRasterInvalidations(invalidator);
- ASSERT_EQ(7u, invalidations.size());
- EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 0, new_artifact, 0);
- EXPECT_DISPLAY_ITEM_INVALIDATIONS(invalidations, 2, new_artifact, 1);
- EXPECT_CHUNK_INVALIDATION(invalidations, 5, new_artifact.PaintChunks()[2],
- PaintInvalidationReason::kChunkUncacheable);
- EXPECT_CHUNK_INVALIDATION(invalidations, 6, artifact.PaintChunks()[1],
- PaintInvalidationReason::kChunkUncacheable);
-}
-
-// Tests the path based on ClipPaintPropertyNode::Changed().
-TEST_F(CompositedLayerRasterInvalidatorTest, ClipPropertyChangeRounded) {
- CompositedLayerRasterInvalidator invalidator(kNoopRasterInvalidation);
- FloatRoundedRect::Radii radii(FloatSize(1, 2), FloatSize(2, 3),
- FloatSize(3, 4), FloatSize(4, 5));
- FloatRoundedRect clip_rect(FloatRect(-1000, -1000, 2000, 2000), radii);
- scoped_refptr<ClipPaintPropertyNode> clip0 =
- CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(), clip_rect);
- scoped_refptr<ClipPaintPropertyNode> clip2 =
- CreateClip(clip0, TransformPaintPropertyNode::Root(), clip_rect);
-
- PropertyTreeState layer_state(TransformPaintPropertyNode::Root(), clip0.get(),
- EffectPaintPropertyNode::Root());
- auto artifact =
- Chunk(0)
- .Properties(layer_state)
- .Chunk(1)
- .Properties(layer_state)
- .Chunk(2)
- .Properties(TransformPaintPropertyNode::Root(), clip2.get())
- .Build();
-
- GeometryMapperClipCache::ClearCache();
- invalidator.SetTracksRasterInvalidations(true);
- invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
- EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
-
- // Change both clip0 and clip2.
- auto new_artifact = Chunk(0)
- .Properties(artifact.PaintChunks()[0].properties)
- .Chunk(1)
- .Properties(artifact.PaintChunks()[1].properties)
- .Chunk(2)
- .Properties(artifact.PaintChunks()[2].properties)
- .Build();
- FloatRoundedRect new_clip_rect(FloatRect(-2000, -2000, 4000, 4000), radii);
- clip0->Update(clip0->Parent(),
- ClipPaintPropertyNode::State{clip0->LocalTransformSpace(),
- new_clip_rect});
- clip2->Update(clip2->Parent(),
- ClipPaintPropertyNode::State{clip2->LocalTransformSpace(),
- new_clip_rect});
-
- GeometryMapperClipCache::ClearCache();
- invalidator.Generate(new_artifact, kDefaultLayerBounds, layer_state);
- const auto& invalidations = TrackedRasterInvalidations(invalidator);
- ASSERT_EQ(1u, invalidations.size());
- // Property change in the layer state should not trigger raster invalidation.
- // |clip2| change should trigger raster invalidation.
- EXPECT_CHUNK_INVALIDATION(invalidations, 0, new_artifact.PaintChunks()[2],
- PaintInvalidationReason::kPaintProperty);
- invalidator.SetTracksRasterInvalidations(false);
- clip2->ClearChangedToRoot();
-
- // Change chunk1's properties to use a different property tree state.
- auto new_artifact1 = Chunk(0)
- .Properties(artifact.PaintChunks()[0].properties)
- .Chunk(1)
- .Properties(artifact.PaintChunks()[2].properties)
- .Chunk(2)
- .Properties(artifact.PaintChunks()[2].properties)
- .Build();
-
- GeometryMapperClipCache::ClearCache();
- invalidator.SetTracksRasterInvalidations(true);
- invalidator.Generate(new_artifact1, kDefaultLayerBounds, layer_state);
- const auto& invalidations1 = TrackedRasterInvalidations(invalidator);
- ASSERT_EQ(1u, invalidations1.size());
- EXPECT_CHUNK_INVALIDATION(invalidations1, 0, new_artifact1.PaintChunks()[1],
- PaintInvalidationReason::kPaintProperty);
- invalidator.SetTracksRasterInvalidations(false);
-}
-
-// Tests the path detecting change of PaintChunkInfo::chunk_to_layer_clip.
-TEST_F(CompositedLayerRasterInvalidatorTest, ClipPropertyChangeSimple) {
- CompositedLayerRasterInvalidator invalidator(kNoopRasterInvalidation);
- FloatRoundedRect clip_rect(-1000, -1000, 2000, 2000);
- scoped_refptr<ClipPaintPropertyNode> clip0 =
- CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(), clip_rect);
- scoped_refptr<ClipPaintPropertyNode> clip1 =
- CreateClip(clip0, TransformPaintPropertyNode::Root(), clip_rect);
-
- PropertyTreeState layer_state = PropertyTreeState::Root();
- auto artifact =
- Chunk(0)
- .Properties(TransformPaintPropertyNode::Root(), clip0.get())
- .Bounds(clip_rect.Rect())
- .Chunk(1)
- .Properties(TransformPaintPropertyNode::Root(), clip1.get())
- .Bounds(clip_rect.Rect())
- .Build();
-
- GeometryMapperClipCache::ClearCache();
- invalidator.SetTracksRasterInvalidations(true);
- invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
- EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
-
- // Change clip1 to bigger, which is still bound by clip0, resulting no actual
- // visual change.
- FloatRoundedRect new_clip_rect1(-2000, -2000, 4000, 4000);
- clip1->Update(clip1->Parent(),
- ClipPaintPropertyNode::State{clip1->LocalTransformSpace(),
- new_clip_rect1});
- auto new_artifact1 = Chunk(0)
- .Properties(artifact.PaintChunks()[0].properties)
- .Bounds(artifact.PaintChunks()[0].bounds)
- .Chunk(1)
- .Properties(artifact.PaintChunks()[1].properties)
- .Bounds(artifact.PaintChunks()[1].bounds)
- .Build();
-
- GeometryMapperClipCache::ClearCache();
- invalidator.Generate(new_artifact1, kDefaultLayerBounds, layer_state);
- EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
- clip1->ClearChangedToRoot();
-
- // Change clip1 to smaller.
- FloatRoundedRect new_clip_rect2(-500, -500, 1000, 1000);
- clip1->Update(clip1->Parent(),
- ClipPaintPropertyNode::State{clip1->LocalTransformSpace(),
- new_clip_rect2});
- auto new_artifact2 = Chunk(0)
- .Properties(artifact.PaintChunks()[0].properties)
- .Bounds(artifact.PaintChunks()[0].bounds)
- .Chunk(1)
- .Properties(artifact.PaintChunks()[1].properties)
- .Bounds(new_clip_rect2.Rect())
- .Build();
-
- GeometryMapperClipCache::ClearCache();
- invalidator.Generate(new_artifact2, kDefaultLayerBounds, layer_state);
- const auto& invalidations = TrackedRasterInvalidations(invalidator);
- ASSERT_EQ(4u, invalidations.size());
- // |clip1| change should trigger incremental raster invalidation.
- EXPECT_INCREMENTAL_INVALIDATION(invalidations, 0,
- new_artifact2.PaintChunks()[1],
- IntRect(-1000, -1000, 2000, 500));
- EXPECT_INCREMENTAL_INVALIDATION(invalidations, 1,
- new_artifact2.PaintChunks()[1],
- IntRect(-1000, -500, 500, 1000));
- EXPECT_INCREMENTAL_INVALIDATION(invalidations, 2,
- new_artifact2.PaintChunks()[1],
- IntRect(500, -500, 500, 1000));
- EXPECT_INCREMENTAL_INVALIDATION(invalidations, 3,
- new_artifact2.PaintChunks()[1],
- IntRect(-1000, 500, 2000, 500));
- invalidator.SetTracksRasterInvalidations(false);
- clip1->ClearChangedToRoot();
-
- // Change clip1 bigger at one side.
- FloatRoundedRect new_clip_rect3(-500, -500, 2000, 1000);
- clip1->Update(clip1->Parent(),
- ClipPaintPropertyNode::State{clip1->LocalTransformSpace(),
- new_clip_rect3});
- auto new_artifact3 = Chunk(0)
- .Properties(artifact.PaintChunks()[0].properties)
- .Bounds(artifact.PaintChunks()[0].bounds)
- .Chunk(1)
- .Properties(artifact.PaintChunks()[1].properties)
- .Bounds(new_clip_rect3.Rect())
- .Build();
-
- GeometryMapperClipCache::ClearCache();
- invalidator.SetTracksRasterInvalidations(true);
- invalidator.Generate(new_artifact3, kDefaultLayerBounds, layer_state);
- const auto& invalidations1 = TrackedRasterInvalidations(invalidator);
- ASSERT_EQ(1u, invalidations1.size());
- // |clip1| change should trigger incremental raster invalidation.
- EXPECT_INCREMENTAL_INVALIDATION(invalidations1, 0,
- new_artifact3.PaintChunks()[1],
- IntRect(500, -500, 500, 1000));
- invalidator.SetTracksRasterInvalidations(false);
- clip1->ClearChangedToRoot();
-}
-
-TEST_F(CompositedLayerRasterInvalidatorTest, TransformPropertyChange) {
- CompositedLayerRasterInvalidator invalidator(kNoopRasterInvalidation);
-
- auto layer_transform = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix().Scale(5));
- auto transform0 = CreateTransform(layer_transform,
- TransformationMatrix().Translate(10, 20));
- auto transform1 =
- CreateTransform(transform0, TransformationMatrix().Translate(-50, -60));
-
- PropertyTreeState layer_state(layer_transform.get(),
- ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root());
- auto artifact = Chunk(0)
- .Properties(transform0.get())
- .Chunk(1)
- .Properties(transform1.get())
- .Build();
-
- GeometryMapperTransformCache::ClearCache();
- invalidator.SetTracksRasterInvalidations(true);
- invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
- EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
-
- // Change layer_transform should not cause raster invalidation in the layer.
- layer_transform->Update(
- layer_transform->Parent(),
- TransformPaintPropertyNode::State{TransformationMatrix().Scale(10)});
- auto new_artifact = Chunk(0)
- .Properties(artifact.PaintChunks()[0].properties)
- .Chunk(1)
- .Properties(artifact.PaintChunks()[1].properties)
- .Build();
-
- GeometryMapperTransformCache::ClearCache();
- invalidator.Generate(new_artifact, kDefaultLayerBounds, layer_state);
- EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
-
- // Inserting another node between layer_transform and transform0 and letting
- // the new node become the transform of the layer state should not cause
- // raster invalidation in the layer. This simulates a composited layer is
- // scrolled from its original location.
- auto new_layer_transform = CreateTransform(
- layer_transform, TransformationMatrix().Translate(-100, -200));
- layer_state = PropertyTreeState(new_layer_transform.get(),
- ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root());
- transform0->Update(new_layer_transform,
- TransformPaintPropertyNode::State{transform0->Matrix()});
- auto new_artifact1 = Chunk(0)
- .Properties(artifact.PaintChunks()[0].properties)
- .Chunk(1)
- .Properties(artifact.PaintChunks()[1].properties)
- .Build();
-
- GeometryMapperTransformCache::ClearCache();
- invalidator.Generate(new_artifact1, kDefaultLayerBounds, layer_state);
- EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
-
- // Removing transform nodes above the layer state should not cause raster
- // invalidation in the layer.
- layer_state = DefaultPropertyTreeState();
- transform0->Update(layer_state.Transform(),
- TransformPaintPropertyNode::State{transform0->Matrix()});
- auto new_artifact2 = Chunk(0)
- .Properties(artifact.PaintChunks()[0].properties)
- .Chunk(1)
- .Properties(artifact.PaintChunks()[1].properties)
- .Build();
-
- GeometryMapperTransformCache::ClearCache();
- invalidator.Generate(new_artifact2, kDefaultLayerBounds, layer_state);
- EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
-
- // Change transform0 and transform1, while keeping the combined transform0
- // and transform1 unchanged for chunk 2. We should invalidate only chunk 0
- // for changed paint property.
- transform0->Update(
- layer_state.Transform(),
- TransformPaintPropertyNode::State{
- TransformationMatrix(transform0->Matrix()).Translate(20, 30)});
- transform1->Update(
- transform0,
- TransformPaintPropertyNode::State{
- TransformationMatrix(transform1->Matrix()).Translate(-20, -30)});
- auto new_artifact3 = Chunk(0)
- .Properties(artifact.PaintChunks()[0].properties)
- .Chunk(1)
- .Properties(artifact.PaintChunks()[1].properties)
- .Build();
-
- GeometryMapperTransformCache::ClearCache();
- invalidator.Generate(new_artifact3, kDefaultLayerBounds, layer_state);
- const auto& invalidations = TrackedRasterInvalidations(invalidator);
- ASSERT_EQ(2u, invalidations.size());
- EXPECT_CHUNK_INVALIDATION_WITH_LAYER_OFFSET(
- invalidations, 0, new_artifact3.PaintChunks()[0],
- PaintInvalidationReason::kPaintProperty,
- -kDefaultLayerBounds.Location() + IntSize(10, 20));
- EXPECT_CHUNK_INVALIDATION_WITH_LAYER_OFFSET(
- invalidations, 1, new_artifact3.PaintChunks()[0],
- PaintInvalidationReason::kPaintProperty,
- -kDefaultLayerBounds.Location() + IntSize(30, 50));
- invalidator.SetTracksRasterInvalidations(false);
-}
-
-TEST_F(CompositedLayerRasterInvalidatorTest, TransformPropertyTinyChange) {
- CompositedLayerRasterInvalidator invalidator(kNoopRasterInvalidation);
-
- auto layer_transform = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix().Scale(5));
- auto chunk_transform = CreateTransform(
- layer_transform, TransformationMatrix().Translate(10, 20));
-
- PropertyTreeState layer_state(layer_transform.get(),
- ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root());
- auto artifact = Chunk(0).Properties(chunk_transform.get()).Build();
-
- GeometryMapperTransformCache::ClearCache();
- invalidator.SetTracksRasterInvalidations(true);
- invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
- EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
-
- // Change chunk_transform by tiny difference, which should be ignored.
- chunk_transform->Update(layer_state.Transform(),
- TransformPaintPropertyNode::State{
- TransformationMatrix(chunk_transform->Matrix())
- .Translate(0.0000001, -0.0000001)
- .Scale(1.0000001)
- .Rotate(0.0000001)});
- auto new_artifact = Chunk(0).Properties(chunk_transform.get()).Build();
-
- GeometryMapperTransformCache::ClearCache();
- invalidator.Generate(new_artifact, kDefaultLayerBounds, layer_state);
- EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
-
- // Tiny differences should accumulate and cause invalidation when the
- // accumulation is large enough.
- bool invalidated = false;
- for (int i = 0; i < 100 && !invalidated; i++) {
- chunk_transform->Update(layer_state.Transform(),
- TransformPaintPropertyNode::State{
- TransformationMatrix(chunk_transform->Matrix())
- .Translate(0.0000001, -0.0000001)
- .Scale(1.0000001)
- .Rotate(0.0000001)});
- auto new_artifact = Chunk(0).Properties(chunk_transform.get()).Build();
-
- GeometryMapperTransformCache::ClearCache();
- invalidator.Generate(new_artifact, kDefaultLayerBounds, layer_state);
- invalidated = !TrackedRasterInvalidations(invalidator).IsEmpty();
- }
- EXPECT_TRUE(invalidated);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
index 7b8194422f1..e3429e1aa20 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "base/optional.h"
#include "base/trace_event/trace_event_argument.h"
+#include "cc/paint/paint_flags.h"
#include "cc/paint/paint_op_buffer.h"
#include "third_party/blink/renderer/platform/geometry/geometry_as_json.h"
#include "third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h"
@@ -179,13 +180,18 @@ static SkColor DisplayItemBackgroundColor(const DisplayItem& item) {
}
scoped_refptr<cc::PictureLayer> ContentLayerClientImpl::UpdateCcPictureLayer(
- const PaintArtifact& paint_artifact,
+ scoped_refptr<const PaintArtifact> paint_artifact,
const PaintChunkSubset& paint_chunks,
const gfx::Rect& layer_bounds,
const PropertyTreeState& layer_state) {
+ if (paint_chunks[0].is_cacheable)
+ id_.emplace(paint_chunks[0].id);
+ else
+ id_ = base::nullopt;
+
// TODO(wangxianzhu): Avoid calling DebugName() in official release build.
debug_name_ = paint_chunks[0].id.client.DebugName();
- const auto& display_item_list = paint_artifact.GetDisplayItemList();
+ const auto& display_item_list = paint_artifact->GetDisplayItemList();
#if DCHECK_IS_ON()
paint_chunk_debug_data_ = JSONArray::Create();
@@ -193,7 +199,7 @@ scoped_refptr<cc::PictureLayer> ContentLayerClientImpl::UpdateCcPictureLayer(
auto json = JSONObject::Create();
json->SetString("data", chunk.ToString());
json->SetArray("displayItems",
- paint_artifact.GetDisplayItemList().SubsequenceAsJSON(
+ paint_artifact->GetDisplayItemList().SubsequenceAsJSON(
chunk.begin_index, chunk.end_index,
DisplayItemList::kSkipNonDrawings |
DisplayItemList::kShownOnlyDisplayItemTypes));
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h b/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h
index d29639e8cda..18f8981984d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/content_layer_client_impl.h
@@ -5,14 +5,14 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_COMPOSITING_CONTENT_LAYER_CLIENT_IMPL_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_COMPOSITING_CONTENT_LAYER_CLIENT_IMPL_H_
+#include "base/macros.h"
#include "cc/layers/content_layer_client.h"
#include "cc/layers/layer_client.h"
#include "cc/layers/picture_layer.h"
-#include "third_party/blink/renderer/platform/graphics/compositing/composited_layer_raster_invalidator.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer_client.h"
+#include "third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -24,7 +24,6 @@ class PaintChunkSubset;
class PLATFORM_EXPORT ContentLayerClientImpl : public cc::ContentLayerClient,
public cc::LayerClient {
- WTF_MAKE_NONCOPYABLE(ContentLayerClientImpl);
USING_FAST_MALLOC(ContentLayerClientImpl);
public:
@@ -50,12 +49,8 @@ class PLATFORM_EXPORT ContentLayerClientImpl : public cc::ContentLayerClient,
cc::Layer*) override;
void DidChangeScrollbarsHiddenIfOverlay(bool) override {}
- void SetTracksRasterInvalidations(bool should_track) {
- raster_invalidator_.SetTracksRasterInvalidations(should_track);
- }
-
bool Matches(const PaintChunk& paint_chunk) const {
- return raster_invalidator_.Matches(paint_chunk);
+ return id_ && paint_chunk.Matches(*id_);
}
struct LayerAsJSONContext {
@@ -70,15 +65,18 @@ class PLATFORM_EXPORT ContentLayerClientImpl : public cc::ContentLayerClient,
std::unique_ptr<JSONObject> LayerAsJSON(LayerAsJSONContext&) const;
scoped_refptr<cc::PictureLayer> UpdateCcPictureLayer(
- const PaintArtifact&,
+ scoped_refptr<const PaintArtifact>,
const PaintChunkSubset&,
const gfx::Rect& layer_bounds,
const PropertyTreeState&);
+ RasterInvalidator& GetRasterInvalidator() { return raster_invalidator_; }
+
private:
+ base::Optional<PaintChunk::Id> id_;
scoped_refptr<cc::PictureLayer> cc_picture_layer_;
scoped_refptr<cc::DisplayItemList> cc_display_item_list_;
- CompositedLayerRasterInvalidator raster_invalidator_;
+ RasterInvalidator raster_invalidator_;
PropertyTreeState layer_state_;
String debug_name_;
@@ -87,6 +85,8 @@ class PLATFORM_EXPORT ContentLayerClientImpl : public cc::ContentLayerClient,
#endif
base::WeakPtrFactory<ContentLayerClientImpl> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ContentLayerClientImpl);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
index 6756dda99da..7d8fccdbb83 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.cc
@@ -20,6 +20,7 @@
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_flags.h"
#include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h"
#include "third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h"
#include "third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h"
@@ -66,7 +67,7 @@ void PaintArtifactCompositor::EnableExtraDataForTesting() {
void PaintArtifactCompositor::SetTracksRasterInvalidations(bool should_track) {
for (auto& client : content_layer_clients_)
- client->SetTracksRasterInvalidations(should_track);
+ client->GetRasterInvalidator().SetTracksRasterInvalidations(should_track);
}
void PaintArtifactCompositor::WillBeRemovedFromFrame() {
@@ -128,7 +129,6 @@ static scoped_refptr<cc::Layer> ForeignLayerForPaintChunk(
static_cast<gfx::Size>(foreign_layer_display_item.Bounds()))
<< "\n layer bounds: " << layer->bounds().ToString()
<< "\n display item bounds: " << foreign_layer_display_item.Bounds();
- DCHECK(layer->DrawsContent());
return layer;
}
@@ -220,26 +220,27 @@ PaintArtifactCompositor::ClientForPaintChunk(const PaintChunk& paint_chunk) {
}
auto client = std::make_unique<ContentLayerClientImpl>();
- client->SetTracksRasterInvalidations(tracks_raster_invalidations_);
+ client->GetRasterInvalidator().SetTracksRasterInvalidations(
+ tracks_raster_invalidations_);
return client;
}
scoped_refptr<cc::Layer>
PaintArtifactCompositor::CompositedLayerForPendingLayer(
- const PaintArtifact& paint_artifact,
+ scoped_refptr<const PaintArtifact> paint_artifact,
const PendingLayer& pending_layer,
gfx::Vector2dF& layer_offset,
Vector<std::unique_ptr<ContentLayerClientImpl>>& new_content_layer_clients,
Vector<scoped_refptr<cc::Layer>>& new_scroll_hit_test_layers) {
auto paint_chunks =
- paint_artifact.GetPaintChunkSubset(pending_layer.paint_chunk_indices);
+ paint_artifact->GetPaintChunkSubset(pending_layer.paint_chunk_indices);
DCHECK(paint_chunks.size());
const PaintChunk& first_paint_chunk = paint_chunks[0];
DCHECK(first_paint_chunk.size());
// If the paint chunk is a foreign layer, just return that layer.
if (scoped_refptr<cc::Layer> foreign_layer = ForeignLayerForPaintChunk(
- paint_artifact, first_paint_chunk, layer_offset)) {
+ *paint_artifact, first_paint_chunk, layer_offset)) {
DCHECK_EQ(paint_chunks.size(), 1u);
if (extra_data_for_testing_enabled_)
extra_data_for_testing_->content_layers.push_back(foreign_layer);
@@ -248,7 +249,7 @@ PaintArtifactCompositor::CompositedLayerForPendingLayer(
// If the paint chunk is a scroll hit test layer, lookup/create the layer.
if (scoped_refptr<cc::Layer> scroll_layer = ScrollHitTestLayerForPendingLayer(
- paint_artifact, pending_layer, layer_offset)) {
+ *paint_artifact, pending_layer, layer_offset)) {
new_scroll_hit_test_layers.push_back(scroll_layer);
if (extra_data_for_testing_enabled_)
extra_data_for_testing_->scroll_hit_test_layers.push_back(scroll_layer);
@@ -397,16 +398,12 @@ static const EffectPaintPropertyNode* StrictChildOfAlongPath(
bool PaintArtifactCompositor::MightOverlap(const PendingLayer& layer_a,
const PendingLayer& layer_b) {
- PropertyTreeState root_property_tree_state(TransformPaintPropertyNode::Root(),
- ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root());
-
FloatClipRect bounds_a(layer_a.bounds);
- GeometryMapper::LocalToAncestorVisualRect(layer_a.property_tree_state,
- root_property_tree_state, bounds_a);
+ GeometryMapper::LocalToAncestorVisualRect(
+ layer_a.property_tree_state, PropertyTreeState::Root(), bounds_a);
FloatClipRect bounds_b(layer_b.bounds);
- GeometryMapper::LocalToAncestorVisualRect(layer_b.property_tree_state,
- root_property_tree_state, bounds_b);
+ GeometryMapper::LocalToAncestorVisualRect(
+ layer_b.property_tree_state, PropertyTreeState::Root(), bounds_b);
return bounds_a.Rect().Intersects(bounds_b.Rect());
}
@@ -575,8 +572,8 @@ void PaintArtifactCompositor::CollectPendingLayers(
Vector<PendingLayer>& pending_layers) {
Vector<PaintChunk>::const_iterator cursor =
paint_artifact.PaintChunks().begin();
- LayerizeGroup(paint_artifact, pending_layers,
- *EffectPaintPropertyNode::Root(), cursor);
+ LayerizeGroup(paint_artifact, pending_layers, EffectPaintPropertyNode::Root(),
+ cursor);
DCHECK_EQ(paint_artifact.PaintChunks().end(), cursor);
}
@@ -623,7 +620,7 @@ class SynthesizedClip : private cc::ContentLayerClient {
if (local_rrect_ != new_local_rrect || path_in_layer_changed) {
layer_->SetNeedsDisplay();
}
- layer_->set_offset_to_transform_parent(new_layer_origin);
+ layer_->SetOffsetToTransformParent(new_layer_origin);
layer_->SetBounds(gfx::Size(layer_bounds.Width(), layer_bounds.Height()));
layer_origin_ = new_layer_origin;
@@ -645,7 +642,7 @@ class SynthesizedClip : private cc::ContentLayerClient {
PaintingControlSetting) final {
auto cc_list = base::MakeRefCounted<cc::DisplayItemList>(
cc::DisplayItemList::kTopLevelDisplayItemList);
- cc::PaintFlags flags;
+ PaintFlags flags;
flags.setAntiAlias(true);
cc_list->StartPaint();
if (!path_) {
@@ -696,8 +693,9 @@ cc::Layer* PaintArtifactCompositor::CreateOrReuseSynthesizedClipLayer(
}
void PaintArtifactCompositor::Update(
- const PaintArtifact& paint_artifact,
- CompositorElementIdSet& composited_element_ids) {
+ scoped_refptr<const PaintArtifact> paint_artifact,
+ CompositorElementIdSet& composited_element_ids,
+ TransformPaintPropertyNode* viewport_scale_node) {
DCHECK(root_layer_);
// The tree will be null after detaching and this update can be ignored.
@@ -706,6 +704,12 @@ void PaintArtifactCompositor::Update(
if (!host)
return;
+ // When using BlinkGenPropertyTrees, the compositor accepts a list of layers
+ // and property trees instead of building property trees. This DCHECK ensures
+ // we have not forgotten to set |use_layer_lists|.
+ DCHECK(!RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled() ||
+ host->GetSettings().use_layer_lists);
+
if (extra_data_for_testing_enabled_)
extra_data_for_testing_.reset(new ExtraDataForTesting);
@@ -717,7 +721,15 @@ void PaintArtifactCompositor::Update(
root_layer_.get(),
g_s_property_tree_sequence_number);
Vector<PendingLayer, 0> pending_layers;
- CollectPendingLayers(paint_artifact, pending_layers);
+ CollectPendingLayers(*paint_artifact, pending_layers);
+
+ // The page scale layer would create this below but we need to use the
+ // special EnsureCompositorPageScaleTransformNode method since the transform
+ // created in a different way so we call it here.
+ if (viewport_scale_node) {
+ property_tree_manager.EnsureCompositorPageScaleTransformNode(
+ viewport_scale_node);
+ }
Vector<std::unique_ptr<ContentLayerClientImpl>> new_content_layer_clients;
new_content_layer_clients.ReserveCapacity(pending_layers.size());
@@ -754,11 +766,11 @@ void PaintArtifactCompositor::Update(
// The compositor scroll node is not directly stored in the property tree
// state but can be created via the scroll offset translation node.
const auto& scroll_translation =
- ScrollTranslationForPendingLayer(paint_artifact, pending_layer);
+ ScrollTranslationForPendingLayer(*paint_artifact, pending_layer);
int scroll_id =
property_tree_manager.EnsureCompositorScrollNode(&scroll_translation);
- layer->set_offset_to_transform_parent(layer_offset);
+ layer->SetOffsetToTransformParent(layer_offset);
// Get the compositor element id for the layer. Scrollable layers are only
// associated with scroll element ids which are set in
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
index fc97de0b4da..a26044688b6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor.h
@@ -8,13 +8,13 @@
#include <memory>
#include "base/callback.h"
+#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer_client.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace cc {
@@ -45,7 +45,6 @@ struct PaintChunk;
class PLATFORM_EXPORT PaintArtifactCompositor final
: private PropertyTreeManagerClient {
USING_FAST_MALLOC(PaintArtifactCompositor);
- WTF_MAKE_NONCOPYABLE(PaintArtifactCompositor);
public:
~PaintArtifactCompositor();
@@ -61,17 +60,13 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
//
// Populates |composited_element_ids| with the CompositorElementId of all
// animations for which we saw a paint chunk and created a layer.
- void Update(const PaintArtifact&,
- CompositorElementIdSet& composited_element_ids);
+ void Update(scoped_refptr<const PaintArtifact>,
+ CompositorElementIdSet& composited_element_ids,
+ TransformPaintPropertyNode* viewport_scale_node);
// The root layer of the tree managed by this object.
cc::Layer* RootLayer() const { return root_layer_.get(); }
- // Wraps RootLayer(), so that it can be attached as a child of another
- // cc::Layer.
- // TODO(danakj): Remove this, use RootLayer() directly.
- cc::Layer* GetCcLayer() const { return root_layer_.get(); }
-
// Returns extra information recorded during unit tests.
// While not part of the normal output of this class, this provides a simple
// way of locating the layers of interest, since there are still a slew of
@@ -169,7 +164,7 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
// paint chunk to align the bounding box to (0, 0) and return the actual
// origin of the paint chunk in the |layerOffset| outparam.
scoped_refptr<cc::Layer> CompositedLayerForPendingLayer(
- const PaintArtifact&,
+ scoped_refptr<const PaintArtifact>,
const PendingLayer&,
gfx::Vector2dF& layer_offset,
Vector<std::unique_ptr<ContentLayerClientImpl>>&
@@ -225,6 +220,8 @@ class PLATFORM_EXPORT PaintArtifactCompositor final
friend class StubChromeClientForSPv2;
friend class PaintArtifactCompositorTest;
+
+ DISALLOW_COPY_AND_ASSIGN(PaintArtifactCompositor);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
index f215b498529..d5a63eba9f7 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_artifact_compositor_test.cc
@@ -6,10 +6,14 @@
#include <memory>
+#include "base/memory/ptr_util.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "cc/layers/layer.h"
+#include "cc/test/fake_impl_task_runner_provider.h"
#include "cc/test/fake_layer_tree_frame_sink.h"
+#include "cc/test/fake_layer_tree_host_client.h"
+#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/geometry_test_utils.h"
#include "cc/trees/clip_node.h"
#include "cc/trees/effect_node.h"
@@ -23,11 +27,11 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
#include "third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.h"
#include "third_party/blink/renderer/platform/testing/fake_display_item_client.h"
+#include "third_party/blink/renderer/platform/testing/layer_tree_host_embedder.h"
#include "third_party/blink/renderer/platform/testing/paint_property_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/picture_matchers.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/test_paint_artifact.h"
-#include "third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
@@ -49,19 +53,6 @@ gfx::Transform Translation(SkMScalar x, SkMScalar y) {
return transform;
}
-class WebLayerTreeViewWithLayerTreeFrameSink
- : public WebLayerTreeViewImplForTesting {
- public:
- WebLayerTreeViewWithLayerTreeFrameSink(const cc::LayerTreeSettings& settings)
- : WebLayerTreeViewImplForTesting(settings) {}
-
- // cc::LayerTreeHostClient
- void RequestNewLayerTreeFrameSink() override {
- GetLayerTreeHost()->SetLayerTreeFrameSink(
- cc::FakeLayerTreeFrameSink::Create3d());
- }
-};
-
class FakeScrollClient {
public:
FakeScrollClient() : did_scroll_count(0) {}
@@ -80,7 +71,7 @@ class PaintArtifactCompositorTest : public testing::Test,
protected:
PaintArtifactCompositorTest()
: ScopedSlimmingPaintV2ForTest(true),
- task_runner_(new base::TestSimpleTaskRunner),
+ task_runner_(base::MakeRefCounted<base::TestSimpleTaskRunner>()),
task_runner_handle_(task_runner_) {}
void SetUp() override {
@@ -90,14 +81,15 @@ class PaintArtifactCompositorTest : public testing::Test,
&FakeScrollClient::DidScroll, WTF::Unretained(&scroll_client_)));
paint_artifact_compositor_->EnableExtraDataForTesting();
- cc::LayerTreeSettings settings =
- WebLayerTreeViewImplForTesting::DefaultLayerTreeSettings();
- settings.single_thread_proxy_scheduler = false;
- settings.use_layer_lists = true;
- web_layer_tree_view_ =
- std::make_unique<WebLayerTreeViewWithLayerTreeFrameSink>(settings);
- web_layer_tree_view_->SetRootLayer(
- paint_artifact_compositor_->GetCcLayer());
+ // Uses a LayerTreeHostClient that will make a LayerTreeFrameSink to allow
+ // the compositor to run and submit frames.
+ layer_tree_ = std::make_unique<LayerTreeHostEmbedder>(
+ &layer_tree_host_client_,
+ /*single_thread_client=*/nullptr,
+ /*use_layer_lists=*/true);
+ layer_tree_host_client_.SetLayerTreeHost(layer_tree_->layer_tree_host());
+ layer_tree_->layer_tree_host()->SetRootLayer(
+ paint_artifact_compositor_->RootLayer());
}
void TearDown() override {
@@ -106,46 +98,52 @@ class PaintArtifactCompositorTest : public testing::Test,
WillBeRemovedFromFrame();
}
- const cc::PropertyTrees& GetPropertyTrees() {
- return *web_layer_tree_view_->GetLayerTreeHost()->property_trees();
+ cc::PropertyTrees& GetPropertyTrees() {
+ return *layer_tree_->layer_tree_host()->property_trees();
+ }
+
+ const cc::TransformNode& GetTransformNode(const cc::Layer* layer) {
+ auto* property_trees = layer_tree_->layer_tree_host()->property_trees();
+ return *property_trees->transform_tree.Node(layer->transform_tree_index());
}
const cc::LayerTreeHost& GetLayerTreeHost() {
- return *web_layer_tree_view_->GetLayerTreeHost();
+ return *layer_tree_->layer_tree_host();
}
int ElementIdToEffectNodeIndex(CompositorElementId element_id) {
- return web_layer_tree_view_->GetLayerTreeHost()
- ->property_trees()
- ->element_id_to_effect_node_index[element_id];
+ auto* property_trees = layer_tree_->layer_tree_host()->property_trees();
+ return property_trees->element_id_to_effect_node_index[element_id];
}
int ElementIdToTransformNodeIndex(CompositorElementId element_id) {
- return web_layer_tree_view_->GetLayerTreeHost()
- ->property_trees()
- ->element_id_to_transform_node_index[element_id];
+ auto* property_trees = layer_tree_->layer_tree_host()->property_trees();
+ return property_trees->element_id_to_transform_node_index[element_id];
}
int ElementIdToScrollNodeIndex(CompositorElementId element_id) {
- return web_layer_tree_view_->GetLayerTreeHost()
- ->property_trees()
- ->element_id_to_scroll_node_index[element_id];
+ auto* property_trees = layer_tree_->layer_tree_host()->property_trees();
+ return property_trees->element_id_to_scroll_node_index[element_id];
}
- const cc::TransformNode& GetTransformNode(const cc::Layer* layer) {
- return *GetPropertyTrees().transform_tree.Node(
- layer->transform_tree_index());
- }
-
- void Update(const PaintArtifact& artifact) {
+ void Update(scoped_refptr<const PaintArtifact> artifact) {
CompositorElementIdSet element_ids;
Update(artifact, element_ids);
}
- void Update(const PaintArtifact& artifact,
+ void Update(scoped_refptr<const PaintArtifact> artifact,
CompositorElementIdSet& element_ids) {
- paint_artifact_compositor_->Update(artifact, element_ids);
- web_layer_tree_view_->GetLayerTreeHost()->LayoutAndUpdateLayers();
+ // Pass nullptr for the visual viewport paint property nodes since we're
+ // really just checking the internals of PaintArtifactCompositor.
+ Update(artifact, element_ids, nullptr);
+ }
+
+ void Update(scoped_refptr<const PaintArtifact> artifact,
+ CompositorElementIdSet& element_ids,
+ TransformPaintPropertyNode* viewport_scale_transform_node) {
+ paint_artifact_compositor_->Update(artifact, element_ids,
+ viewport_scale_transform_node);
+ layer_tree_->layer_tree_host()->LayoutAndUpdateLayers();
}
void WillBeRemovedFromFrame() {
@@ -197,22 +195,17 @@ class PaintArtifactCompositorTest : public testing::Test,
}
void AddSimpleRectChunk(TestPaintArtifact& artifact) {
- artifact
- .Chunk(TransformPaintPropertyNode::Root(),
- ClipPaintPropertyNode::Root(), EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack);
+ artifact.Chunk().RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack);
}
- void CreateSimpleArtifactWithOpacity(TestPaintArtifact& artifact,
- float opacity,
- bool include_preceding_chunk,
- bool include_subsequent_chunk) {
+ void UpdateWithArtifactWithOpacity(float opacity,
+ bool include_preceding_chunk,
+ bool include_subsequent_chunk) {
+ TestPaintArtifact artifact;
if (include_preceding_chunk)
AddSimpleRectChunk(artifact);
- auto effect = CreateOpacityEffect(EffectPaintPropertyNode::Root(), opacity);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(),
- ClipPaintPropertyNode::Root(), effect)
+ auto effect = CreateOpacityEffect(e0(), opacity);
+ artifact.Chunk(t0(), c0(), *effect)
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
if (include_subsequent_chunk)
AddSimpleRectChunk(artifact);
@@ -232,32 +225,20 @@ class PaintArtifactCompositorTest : public testing::Test,
std::unique_ptr<PaintArtifactCompositor> paint_artifact_compositor_;
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
base::ThreadTaskRunnerHandle task_runner_handle_;
- std::unique_ptr<WebLayerTreeViewWithLayerTreeFrameSink> web_layer_tree_view_;
+ cc::FakeLayerTreeHostClient layer_tree_host_client_;
+ std::unique_ptr<LayerTreeHostEmbedder> layer_tree_;
};
const auto kNotScrollingOnMain = MainThreadScrollingReason::kNotScrollingOnMain;
-// Convenient shorthands.
-const TransformPaintPropertyNode* t0() {
- return TransformPaintPropertyNode::Root();
-}
-const ClipPaintPropertyNode* c0() {
- return ClipPaintPropertyNode::Root();
-}
-const EffectPaintPropertyNode* e0() {
- return EffectPaintPropertyNode::Root();
-}
-
TEST_F(PaintArtifactCompositorTest, EmptyPaintArtifact) {
- PaintArtifact empty_artifact;
- Update(empty_artifact);
+ Update(PaintArtifact::Empty());
EXPECT_TRUE(RootLayer()->children().empty());
}
TEST_F(PaintArtifactCompositorTest, OneChunkWithAnOffset) {
TestPaintArtifact artifact;
- artifact.Chunk(PropertyTreeState::Root())
- .RectDrawing(FloatRect(50, -50, 100, 100), Color::kWhite);
+ artifact.Chunk().RectDrawing(FloatRect(50, -50, 100, 100), Color::kWhite);
Update(artifact.Build());
ASSERT_EQ(1u, ContentLayerCount());
@@ -271,22 +252,15 @@ TEST_F(PaintArtifactCompositorTest, OneChunkWithAnOffset) {
TEST_F(PaintArtifactCompositorTest, OneTransform) {
// A 90 degree clockwise rotation about (100, 100).
- auto transform = CreateTransform(
- TransformPaintPropertyNode::Root(), TransformationMatrix().Rotate(90),
- FloatPoint3D(100, 100, 0), CompositingReason::k3DTransform);
+ auto transform = CreateTransform(t0(), TransformationMatrix().Rotate(90),
+ FloatPoint3D(100, 100, 0),
+ CompositingReason::k3DTransform);
TestPaintArtifact artifact;
- artifact
- .Chunk(transform, ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(*transform, c0(), e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kGray);
- artifact
- .Chunk(transform, ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kGray);
+ artifact.Chunk(*transform, c0(), e0())
.RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack);
Update(artifact.Build());
@@ -317,21 +291,17 @@ TEST_F(PaintArtifactCompositorTest, OneTransform) {
TEST_F(PaintArtifactCompositorTest, TransformCombining) {
// A translation by (5, 5) within a 2x scale about (10, 10).
- auto transform1 = CreateTransform(
- TransformPaintPropertyNode::Root(), TransformationMatrix().Scale(2),
- FloatPoint3D(10, 10, 0), CompositingReason::k3DTransform);
+ auto transform1 =
+ CreateTransform(t0(), TransformationMatrix().Scale(2),
+ FloatPoint3D(10, 10, 0), CompositingReason::k3DTransform);
auto transform2 =
- CreateTransform(transform1, TransformationMatrix().Translate(5, 5),
+ CreateTransform(*transform1, TransformationMatrix().Translate(5, 5),
FloatPoint3D(), CompositingReason::k3DTransform);
TestPaintArtifact artifact;
- artifact
- .Chunk(transform1, ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(*transform1, c0(), e0())
.RectDrawing(FloatRect(0, 0, 300, 200), Color::kWhite);
- artifact
- .Chunk(transform2, ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(*transform2, c0(), e0())
.RectDrawing(FloatRect(0, 0, 300, 200), Color::kBlack);
Update(artifact.Build());
@@ -363,29 +333,23 @@ TEST_F(PaintArtifactCompositorTest, BackfaceVisibility) {
backface_hidden_state.backface_visibility =
TransformPaintPropertyNode::BackfaceVisibility::kHidden;
auto backface_hidden_transform = TransformPaintPropertyNode::Create(
- TransformPaintPropertyNode::Root(), std::move(backface_hidden_state));
+ t0(), std::move(backface_hidden_state));
auto backface_inherited_transform = TransformPaintPropertyNode::Create(
- backface_hidden_transform, TransformPaintPropertyNode::State{});
+ *backface_hidden_transform, TransformPaintPropertyNode::State{});
TransformPaintPropertyNode::State backface_visible_state;
backface_visible_state.backface_visibility =
TransformPaintPropertyNode::BackfaceVisibility::kVisible;
auto backface_visible_transform = TransformPaintPropertyNode::Create(
- backface_hidden_transform, std::move(backface_visible_state));
+ *backface_hidden_transform, std::move(backface_visible_state));
TestPaintArtifact artifact;
- artifact
- .Chunk(backface_hidden_transform, ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(*backface_hidden_transform, c0(), e0())
.RectDrawing(FloatRect(0, 0, 300, 200), Color::kWhite);
- artifact
- .Chunk(backface_inherited_transform, ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(*backface_inherited_transform, c0(), e0())
.RectDrawing(FloatRect(100, 100, 100, 100), Color::kBlack);
- artifact
- .Chunk(backface_visible_transform, ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(*backface_visible_transform, c0(), e0())
.RectDrawing(FloatRect(0, 0, 300, 200), Color::kDarkGray);
Update(artifact.Build());
@@ -408,20 +372,17 @@ TEST_F(PaintArtifactCompositorTest, FlattensInheritedTransform) {
// transform node flattens the transform. This is because Blink's notion of
// flattening determines whether content within the node's local transform
// is flattened, while cc's notion applies in the parent's coordinate space.
- auto transform1 = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix());
+ auto transform1 = CreateTransform(t0(), TransformationMatrix());
auto transform2 =
- CreateTransform(transform1, TransformationMatrix().Rotate3d(0, 45, 0));
+ CreateTransform(*transform1, TransformationMatrix().Rotate3d(0, 45, 0));
TransformPaintPropertyNode::State transform3_state;
transform3_state.matrix = TransformationMatrix().Rotate3d(0, 45, 0);
transform3_state.flattens_inherited_transform = transform_is_flattened;
auto transform3 = TransformPaintPropertyNode::Create(
- transform2, std::move(transform3_state));
+ *transform2, std::move(transform3_state));
TestPaintArtifact artifact;
- artifact
- .Chunk(transform3, ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(*transform3, c0(), e0())
.RectDrawing(FloatRect(0, 0, 300, 200), Color::kWhite);
Update(artifact.Build());
@@ -456,41 +417,32 @@ TEST_F(PaintArtifactCompositorTest, FlattensInheritedTransform) {
TEST_F(PaintArtifactCompositorTest, SortingContextID) {
// Has no 3D rendering context.
- auto transform1 = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix());
+ auto transform1 = CreateTransform(t0(), TransformationMatrix());
// Establishes a 3D rendering context.
TransformPaintPropertyNode::State transform2_3_state;
transform2_3_state.rendering_context_id = 1;
transform2_3_state.direct_compositing_reasons =
CompositingReason::k3DTransform;
auto transform2 = TransformPaintPropertyNode::Create(
- transform1, std::move(transform2_3_state));
+ *transform1, std::move(transform2_3_state));
// Extends the 3D rendering context of transform2.
auto transform3 = TransformPaintPropertyNode::Create(
- transform2, std::move(transform2_3_state));
+ *transform2, std::move(transform2_3_state));
// Establishes a 3D rendering context distinct from transform2.
TransformPaintPropertyNode::State transform4_state;
transform4_state.rendering_context_id = 2;
transform4_state.direct_compositing_reasons = CompositingReason::k3DTransform;
auto transform4 = TransformPaintPropertyNode::Create(
- transform2, std::move(transform4_state));
+ *transform2, std::move(transform4_state));
TestPaintArtifact artifact;
- artifact
- .Chunk(transform1, ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(*transform1, c0(), e0())
.RectDrawing(FloatRect(0, 0, 300, 200), Color::kWhite);
- artifact
- .Chunk(transform2, ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(*transform2, c0(), e0())
.RectDrawing(FloatRect(0, 0, 300, 200), Color::kLightGray);
- artifact
- .Chunk(transform3, ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(*transform3, c0(), e0())
.RectDrawing(FloatRect(0, 0, 300, 200), Color::kDarkGray);
- artifact
- .Chunk(transform4, ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(*transform4, c0(), e0())
.RectDrawing(FloatRect(0, 0, 300, 200), Color::kBlack);
Update(artifact.Build());
@@ -540,14 +492,10 @@ TEST_F(PaintArtifactCompositorTest, SortingContextID) {
}
TEST_F(PaintArtifactCompositorTest, OneClip) {
- auto clip = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(100, 100, 300, 200));
+ auto clip = CreateClip(c0(), &t0(), FloatRoundedRect(100, 100, 300, 200));
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), clip,
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(t0(), *clip, e0())
.RectDrawing(FloatRect(220, 80, 300, 200), Color::kBlack);
Update(artifact.Build());
@@ -568,30 +516,19 @@ TEST_F(PaintArtifactCompositorTest, OneClip) {
}
TEST_F(PaintArtifactCompositorTest, NestedClips) {
- auto clip1 = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(100, 100, 700, 700),
+ auto clip1 = CreateClip(c0(), &t0(), FloatRoundedRect(100, 100, 700, 700),
CompositingReason::kOverflowScrollingTouch);
- auto clip2 = CreateClip(clip1, TransformPaintPropertyNode::Root(),
- FloatRoundedRect(200, 200, 700, 700),
+ auto clip2 = CreateClip(*clip1, &t0(), FloatRoundedRect(200, 200, 700, 700),
CompositingReason::kOverflowScrollingTouch);
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), clip1,
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(t0(), *clip1, e0())
.RectDrawing(FloatRect(300, 350, 100, 100), Color::kWhite);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), clip2,
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(t0(), *clip2, e0())
.RectDrawing(FloatRect(300, 350, 100, 100), Color::kLightGray);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), clip1,
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(t0(), *clip1, e0())
.RectDrawing(FloatRect(300, 350, 100, 100), Color::kDarkGray);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), clip2,
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(t0(), *clip2, e0())
.RectDrawing(FloatRect(300, 350, 100, 100), Color::kBlack);
Update(artifact.Build());
@@ -639,16 +576,12 @@ TEST_F(PaintArtifactCompositorTest, NestedClips) {
TEST_F(PaintArtifactCompositorTest, DeeplyNestedClips) {
Vector<scoped_refptr<ClipPaintPropertyNode>> clips;
for (unsigned i = 1; i <= 10; i++) {
- clips.push_back(CreateClip(
- clips.IsEmpty() ? ClipPaintPropertyNode::Root() : clips.back(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(5 * i, 0, 100, 200 - 10 * i)));
+ clips.push_back(CreateClip(clips.IsEmpty() ? c0() : *clips.back(), &t0(),
+ FloatRoundedRect(5 * i, 0, 100, 200 - 10 * i)));
}
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), clips.back(),
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(t0(), *clips.back(), e0())
.RectDrawing(FloatRect(0, 0, 200, 200), Color::kWhite);
Update(artifact.Build());
@@ -674,22 +607,16 @@ TEST_F(PaintArtifactCompositorTest, DeeplyNestedClips) {
}
TEST_F(PaintArtifactCompositorTest, SiblingClips) {
- auto common_clip = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(0, 0, 800, 600));
- auto clip1 = CreateClip(common_clip, TransformPaintPropertyNode::Root(),
- FloatRoundedRect(0, 0, 400, 600));
- auto clip2 = CreateClip(common_clip, TransformPaintPropertyNode::Root(),
- FloatRoundedRect(400, 0, 400, 600));
+ auto common_clip = CreateClip(c0(), &t0(), FloatRoundedRect(0, 0, 800, 600));
+ auto clip1 =
+ CreateClip(*common_clip, &t0(), FloatRoundedRect(0, 0, 400, 600));
+ auto clip2 =
+ CreateClip(*common_clip, &t0(), FloatRoundedRect(400, 0, 400, 600));
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), clip1,
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(t0(), *clip1, e0())
.RectDrawing(FloatRect(0, 0, 640, 480), Color::kWhite);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), clip2,
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(t0(), *clip2, e0())
.RectDrawing(FloatRect(0, 0, 640, 480), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(2u, ContentLayerCount());
@@ -731,19 +658,13 @@ TEST_F(PaintArtifactCompositorTest, ForeignLayerPassesThrough) {
layer->SetBounds(gfx::Size(400, 300));
TestPaintArtifact test_artifact;
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- test_artifact.Chunk(PropertyTreeState::Root())
- .ForeignLayer(FloatPoint(50, 60), IntSize(400, 300), layer);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kGray);
-
- const PaintArtifact& artifact = test_artifact.Build();
- ASSERT_EQ(3u, artifact.PaintChunks().size());
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk().ForeignLayer(FloatPoint(50, 60), IntSize(400, 300),
+ layer);
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kGray);
+
+ auto artifact = test_artifact.Build();
+ ASSERT_EQ(3u, artifact->PaintChunks().size());
Update(artifact);
ASSERT_EQ(3u, ContentLayerCount());
@@ -754,29 +675,22 @@ TEST_F(PaintArtifactCompositorTest, ForeignLayerPassesThrough) {
TEST_F(PaintArtifactCompositorTest, EffectTreeConversion) {
EffectPaintPropertyNode::State effect1_state;
- effect1_state.local_transform_space = TransformPaintPropertyNode::Root();
- effect1_state.output_clip = ClipPaintPropertyNode::Root();
+ effect1_state.local_transform_space = &t0();
+ effect1_state.output_clip = &c0();
effect1_state.opacity = 0.5;
effect1_state.direct_compositing_reasons = CompositingReason::kAll;
effect1_state.compositor_element_id = CompositorElementId(2);
- auto effect1 = EffectPaintPropertyNode::Create(
- EffectPaintPropertyNode::Root(), std::move(effect1_state));
- auto effect2 = CreateOpacityEffect(effect1, 0.3, CompositingReason::kAll);
- auto effect3 = CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.2,
- CompositingReason::kAll);
+ auto effect1 =
+ EffectPaintPropertyNode::Create(e0(), std::move(effect1_state));
+ auto effect2 = CreateOpacityEffect(*effect1, 0.3, CompositingReason::kAll);
+ auto effect3 = CreateOpacityEffect(e0(), 0.2, CompositingReason::kAll);
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- effect2.get())
+ artifact.Chunk(t0(), c0(), *effect2)
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- effect1.get())
+ artifact.Chunk(t0(), c0(), *effect1)
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- effect3.get())
+ artifact.Chunk(t0(), c0(), *effect3)
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
Update(artifact.Build());
@@ -784,13 +698,13 @@ TEST_F(PaintArtifactCompositorTest, EffectTreeConversion) {
const cc::EffectTree& effect_tree = GetPropertyTrees().effect_tree;
// Node #0 reserved for null; #1 for root render surface; #2 for
- // EffectPaintPropertyNode::root(), plus 3 nodes for those created by
+ // e0(), plus 3 nodes for those created by
// this test.
ASSERT_EQ(5u, effect_tree.size());
const cc::EffectNode& converted_root_effect = *effect_tree.Node(1);
EXPECT_EQ(-1, converted_root_effect.parent_id);
- EXPECT_EQ(CompositorElementIdFromUniqueObjectId(1).ToInternalValue(),
+ EXPECT_EQ(CompositorElementIdFromUniqueObjectId(1).GetInternalValue(),
converted_root_effect.stable_id);
const cc::EffectNode& converted_effect1 = *effect_tree.Node(2);
@@ -830,7 +744,7 @@ static ScrollPaintPropertyNode::State ScrollState2() {
}
static scoped_refptr<ScrollPaintPropertyNode> CreateScroll(
- scoped_refptr<const ScrollPaintPropertyNode> parent,
+ const ScrollPaintPropertyNode& parent,
const ScrollPaintPropertyNode::State& state_arg,
MainThreadScrollingReasons main_thread_scrolling_reasons =
MainThreadScrollingReason::kNotScrollingOnMain,
@@ -860,17 +774,11 @@ TEST_F(PaintArtifactCompositorTest, OneScrollNode) {
CompositorElementId scroll_element_id = ScrollElementId(2);
auto scroll = CreateScroll(ScrollPaintPropertyNode::Root(), ScrollState1(),
kNotScrollingOnMain, scroll_element_id);
- auto scroll_translation =
- CreateScrollTranslation(TransformPaintPropertyNode::Root(), 7, 9, scroll);
+ auto scroll_translation = CreateScrollTranslation(t0(), 7, 9, *scroll);
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .ScrollHitTest(scroll_translation);
- artifact
- .Chunk(scroll_translation, ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ artifact.Chunk().ScrollHitTest(*scroll_translation);
+ artifact.Chunk(*scroll_translation, c0(), e0())
.RectDrawing(FloatRect(-110, 12, 170, 19), Color::kWhite);
Update(artifact.Build());
@@ -920,20 +828,16 @@ TEST_F(PaintArtifactCompositorTest, OneScrollNode) {
TEST_F(PaintArtifactCompositorTest, TransformUnderScrollNode) {
auto scroll = CreateScroll(ScrollPaintPropertyNode::Root(), ScrollState1());
- auto scroll_translation =
- CreateScrollTranslation(TransformPaintPropertyNode::Root(), 7, 9, scroll);
+ auto scroll_translation = CreateScrollTranslation(t0(), 7, 9, *scroll);
auto transform =
- CreateTransform(scroll_translation, TransformationMatrix(),
+ CreateTransform(*scroll_translation, TransformationMatrix(),
FloatPoint3D(), CompositingReason::k3DTransform);
TestPaintArtifact artifact;
- artifact
- .Chunk(scroll_translation, ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(*scroll_translation, c0(), e0())
.RectDrawing(FloatRect(-20, 4, 60, 8), Color::kBlack)
- .Chunk(transform, ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ .Chunk(*transform, c0(), e0())
.RectDrawing(FloatRect(1, -30, 5, 70), Color::kWhite);
Update(artifact.Build());
@@ -969,7 +873,7 @@ TEST_F(PaintArtifactCompositorTest, TransformUnderScrollNode) {
}
TEST_F(PaintArtifactCompositorTest, NestedScrollNodes) {
- auto effect = CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.5);
+ auto effect = CreateOpacityEffect(e0(), 0.5);
CompositorElementId scroll_element_id_a = ScrollElementId(2);
auto scroll_a = CreateScroll(
@@ -977,27 +881,22 @@ TEST_F(PaintArtifactCompositorTest, NestedScrollNodes) {
MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects,
scroll_element_id_a);
auto scroll_translation_a = CreateScrollTranslation(
- TransformPaintPropertyNode::Root(), 11, 13, scroll_a,
- CompositingReason::kLayerForScrollingContents);
+ t0(), 11, 13, *scroll_a, CompositingReason::kLayerForScrollingContents);
CompositorElementId scroll_element_id_b = ScrollElementId(3);
- auto scroll_b = CreateScroll(scroll_a, ScrollState2(), kNotScrollingOnMain,
+ auto scroll_b = CreateScroll(*scroll_a, ScrollState2(), kNotScrollingOnMain,
scroll_element_id_b);
auto scroll_translation_b =
- CreateScrollTranslation(scroll_translation_a, 37, 41, scroll_b);
+ CreateScrollTranslation(*scroll_translation_a, 37, 41, *scroll_b);
TestPaintArtifact artifact;
- artifact.Chunk(scroll_translation_a, ClipPaintPropertyNode::Root(), effect)
+ artifact.Chunk(*scroll_translation_a, c0(), *effect)
.RectDrawing(FloatRect(7, 11, 13, 17), Color::kWhite);
- artifact
- .Chunk(scroll_translation_a->Parent(), ClipPaintPropertyNode::Root(),
- effect)
- .ScrollHitTest(scroll_translation_a);
- artifact.Chunk(scroll_translation_b, ClipPaintPropertyNode::Root(), effect)
+ artifact.Chunk(*scroll_translation_a->Parent(), c0(), *effect)
+ .ScrollHitTest(*scroll_translation_a);
+ artifact.Chunk(*scroll_translation_b, c0(), *effect)
.RectDrawing(FloatRect(1, 2, 3, 5), Color::kWhite);
- artifact
- .Chunk(scroll_translation_b->Parent(), ClipPaintPropertyNode::Root(),
- effect)
- .ScrollHitTest(scroll_translation_b);
+ artifact.Chunk(*scroll_translation_b->Parent(), c0(), *effect)
+ .ScrollHitTest(*scroll_translation_b);
Update(artifact.Build());
const cc::ScrollTree& scroll_tree = GetPropertyTrees().scroll_tree;
@@ -1028,29 +927,24 @@ TEST_F(PaintArtifactCompositorTest, NestedScrollNodes) {
}
TEST_F(PaintArtifactCompositorTest, ScrollHitTestLayerOrder) {
- auto clip = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(0, 0, 100, 100));
+ auto clip = CreateClip(c0(), &t0(), FloatRoundedRect(0, 0, 100, 100));
CompositorElementId scroll_element_id = ScrollElementId(2);
auto scroll = CreateScroll(ScrollPaintPropertyNode::Root(), ScrollState1(),
kNotScrollingOnMain, scroll_element_id);
- auto scroll_translation =
- CreateScrollTranslation(TransformPaintPropertyNode::Root(), 7, 9, scroll,
- CompositingReason::kWillChangeCompositingHint);
+ auto scroll_translation = CreateScrollTranslation(
+ t0(), 7, 9, *scroll, CompositingReason::kWillChangeCompositingHint);
auto transform = CreateTransform(
- scroll_translation, TransformationMatrix().Translate(5, 5),
+ *scroll_translation, TransformationMatrix().Translate(5, 5),
FloatPoint3D(), CompositingReason::k3DTransform);
TestPaintArtifact artifact;
- artifact.Chunk(scroll_translation, clip, EffectPaintPropertyNode::Root())
+ artifact.Chunk(*scroll_translation, *clip, e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- artifact
- .Chunk(scroll_translation->Parent(), clip,
- EffectPaintPropertyNode::Root())
- .ScrollHitTest(scroll_translation);
- artifact.Chunk(transform, clip, EffectPaintPropertyNode::Root())
+ artifact.Chunk(*scroll_translation->Parent(), *clip, e0())
+ .ScrollHitTest(*scroll_translation);
+ artifact.Chunk(*transform, *clip, e0())
.RectDrawing(FloatRect(0, 0, 50, 50), Color::kBlack);
Update(artifact.Build());
@@ -1072,35 +966,27 @@ TEST_F(PaintArtifactCompositorTest, ScrollHitTestLayerOrder) {
}
TEST_F(PaintArtifactCompositorTest, NestedScrollHitTestLayerOrder) {
- auto clip_1 = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(0, 0, 100, 100));
+ auto clip_1 = CreateClip(c0(), &t0(), FloatRoundedRect(0, 0, 100, 100));
CompositorElementId scroll_1_element_id = ScrollElementId(1);
auto scroll_1 = CreateScroll(ScrollPaintPropertyNode::Root(), ScrollState1(),
kNotScrollingOnMain, scroll_1_element_id);
auto scroll_translation_1 = CreateScrollTranslation(
- TransformPaintPropertyNode::Root(), 7, 9, scroll_1,
- CompositingReason::kWillChangeCompositingHint);
+ t0(), 7, 9, *scroll_1, CompositingReason::kWillChangeCompositingHint);
- auto clip_2 =
- CreateClip(clip_1, scroll_translation_1, FloatRoundedRect(0, 0, 50, 50));
+ auto clip_2 = CreateClip(*clip_1, scroll_translation_1.get(),
+ FloatRoundedRect(0, 0, 50, 50));
CompositorElementId scroll_2_element_id = ScrollElementId(2);
auto scroll_2 = CreateScroll(ScrollPaintPropertyNode::Root(), ScrollState2(),
kNotScrollingOnMain, scroll_2_element_id);
auto scroll_translation_2 = CreateScrollTranslation(
- TransformPaintPropertyNode::Root(), 0, 0, scroll_2,
- CompositingReason::kWillChangeCompositingHint);
+ t0(), 0, 0, *scroll_2, CompositingReason::kWillChangeCompositingHint);
TestPaintArtifact artifact;
- artifact
- .Chunk(scroll_translation_1->Parent(), clip_1->Parent(),
- EffectPaintPropertyNode::Root())
- .ScrollHitTest(scroll_translation_1);
- artifact
- .Chunk(scroll_translation_2->Parent(), clip_2->Parent(),
- EffectPaintPropertyNode::Root())
- .ScrollHitTest(scroll_translation_2);
- artifact.Chunk(scroll_translation_2, clip_2, EffectPaintPropertyNode::Root())
+ artifact.Chunk(*scroll_translation_1->Parent(), *clip_1->Parent(), e0())
+ .ScrollHitTest(*scroll_translation_1);
+ artifact.Chunk(*scroll_translation_2->Parent(), *clip_2->Parent(), e0())
+ .ScrollHitTest(*scroll_translation_2);
+ artifact.Chunk(*scroll_translation_2, *clip_2, e0())
.RectDrawing(FloatRect(0, 0, 50, 50), Color::kWhite);
Update(artifact.Build());
@@ -1138,24 +1024,18 @@ TEST_F(PaintArtifactCompositorTest, AncestorScrollNodes) {
auto scroll_a = CreateScroll(ScrollPaintPropertyNode::Root(), ScrollState1(),
kNotScrollingOnMain, scroll_element_id_a);
auto scroll_translation_a = CreateScrollTranslation(
- TransformPaintPropertyNode::Root(), 11, 13, scroll_a,
- CompositingReason::kLayerForScrollingContents);
+ t0(), 11, 13, *scroll_a, CompositingReason::kLayerForScrollingContents);
CompositorElementId scroll_element_id_b = ScrollElementId(3);
- auto scroll_b = CreateScroll(scroll_a, ScrollState2(), kNotScrollingOnMain,
+ auto scroll_b = CreateScroll(*scroll_a, ScrollState2(), kNotScrollingOnMain,
scroll_element_id_b);
auto scroll_translation_b =
- CreateScrollTranslation(scroll_translation_a, 37, 41, scroll_b);
+ CreateScrollTranslation(*scroll_translation_a, 37, 41, *scroll_b);
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .ScrollHitTest(scroll_translation_b);
- artifact
- .Chunk(scroll_translation_b, ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .ScrollHitTest(scroll_translation_a);
+ artifact.Chunk().ScrollHitTest(*scroll_translation_b);
+ artifact.Chunk(*scroll_translation_b, c0(), e0())
+ .ScrollHitTest(*scroll_translation_a);
Update(artifact.Build());
const cc::ScrollTree& scroll_tree = GetPropertyTrees().scroll_tree;
@@ -1192,17 +1072,11 @@ TEST_F(PaintArtifactCompositorTest, AncestorScrollNodes) {
TEST_F(PaintArtifactCompositorTest, MergeSimpleChunks) {
TestPaintArtifact test_artifact;
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
- const PaintArtifact& artifact = test_artifact.Build();
- ASSERT_EQ(2u, artifact.PaintChunks().size());
+ auto artifact = test_artifact.Build();
+ ASSERT_EQ(2u, artifact->PaintChunks().size());
Update(artifact);
ASSERT_EQ(1u, ContentLayerCount());
@@ -1220,27 +1094,17 @@ TEST_F(PaintArtifactCompositorTest, MergeSimpleChunks) {
}
TEST_F(PaintArtifactCompositorTest, MergeClip) {
- auto clip = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(10, 20, 50, 60));
+ auto clip = CreateClip(c0(), &t0(), FloatRoundedRect(10, 20, 50, 60));
TestPaintArtifact test_artifact;
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), clip.get(),
- EffectPaintPropertyNode::Root())
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk(t0(), *clip, e0())
.RectDrawing(FloatRect(0, 0, 200, 300), Color::kBlack);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 300, 400), Color::kGray);
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 300, 400), Color::kGray);
- const PaintArtifact& artifact = test_artifact.Build();
+ auto artifact = test_artifact.Build();
- ASSERT_EQ(3u, artifact.PaintChunks().size());
+ ASSERT_EQ(3u, artifact->PaintChunks().size());
Update(artifact);
ASSERT_EQ(1u, ContentLayerCount());
{
@@ -1260,26 +1124,18 @@ TEST_F(PaintArtifactCompositorTest, MergeClip) {
}
TEST_F(PaintArtifactCompositorTest, Merge2DTransform) {
- auto transform = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix().Translate(50, 50),
- FloatPoint3D(100, 100, 0));
+ auto transform =
+ CreateTransform(t0(), TransformationMatrix().Translate(50, 50),
+ FloatPoint3D(100, 100, 0));
TestPaintArtifact test_artifact;
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- test_artifact
- .Chunk(transform.get(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk(*transform, c0(), e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
- const PaintArtifact& artifact = test_artifact.Build();
- ASSERT_EQ(3u, artifact.PaintChunks().size());
+ auto artifact = test_artifact.Build();
+ ASSERT_EQ(3u, artifact->PaintChunks().size());
Update(artifact);
ASSERT_EQ(1u, ContentLayerCount());
@@ -1300,28 +1156,22 @@ TEST_F(PaintArtifactCompositorTest, Merge2DTransform) {
}
TEST_F(PaintArtifactCompositorTest, Merge2DTransformDirectAncestor) {
- auto transform = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix(), FloatPoint3D(),
+ auto transform = CreateTransform(t0(), TransformationMatrix(), FloatPoint3D(),
CompositingReason::k3DTransform);
-
auto transform2 =
- CreateTransform(transform.get(), TransformationMatrix().Translate(50, 50),
+ CreateTransform(*transform, TransformationMatrix().Translate(50, 50),
FloatPoint3D(100, 100, 0));
TestPaintArtifact test_artifact;
- test_artifact
- .Chunk(transform.get(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ test_artifact.Chunk(*transform, c0(), e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
// The second chunk can merge into the first because it has a descendant
// state of the first's transform and no direct compositing reason.
- test_artifact
- .Chunk(transform2.get(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ test_artifact.Chunk(*transform2, c0(), e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- const PaintArtifact& artifact = test_artifact.Build();
- ASSERT_EQ(2u, artifact.PaintChunks().size());
+ auto artifact = test_artifact.Build();
+ ASSERT_EQ(2u, artifact->PaintChunks().size());
Update(artifact);
ASSERT_EQ(1u, ContentLayerCount());
{
@@ -1339,26 +1189,17 @@ TEST_F(PaintArtifactCompositorTest, Merge2DTransformDirectAncestor) {
}
TEST_F(PaintArtifactCompositorTest, MergeTransformOrigin) {
- auto transform = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix().Rotate(45),
+ auto transform = CreateTransform(t0(), TransformationMatrix().Rotate(45),
FloatPoint3D(100, 100, 0));
TestPaintArtifact test_artifact;
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- test_artifact
- .Chunk(transform.get(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk(*transform, c0(), e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
- const PaintArtifact& artifact = test_artifact.Build();
- ASSERT_EQ(3u, artifact.PaintChunks().size());
+ auto artifact = test_artifact.Build();
+ ASSERT_EQ(3u, artifact->PaintChunks().size());
Update(artifact);
ASSERT_EQ(1u, ContentLayerCount());
{
@@ -1379,24 +1220,16 @@ TEST_F(PaintArtifactCompositorTest, MergeTransformOrigin) {
TEST_F(PaintArtifactCompositorTest, MergeOpacity) {
float opacity = 2.0 / 255.0;
- auto effect = CreateOpacityEffect(EffectPaintPropertyNode::Root(), opacity);
+ auto effect = CreateOpacityEffect(e0(), opacity);
TestPaintArtifact test_artifact;
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- effect.get())
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk(t0(), c0(), *effect)
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
- const PaintArtifact& artifact = test_artifact.Build();
- ASSERT_EQ(3u, artifact.PaintChunks().size());
+ auto artifact = test_artifact.Build();
+ ASSERT_EQ(3u, artifact->PaintChunks().size());
Update(artifact);
ASSERT_EQ(1u, ContentLayerCount());
{
@@ -1419,32 +1252,22 @@ TEST_F(PaintArtifactCompositorTest, MergeOpacity) {
TEST_F(PaintArtifactCompositorTest, MergeNested) {
// Tests merging of an opacity effect, inside of a clip, inside of a
// transform.
-
- auto transform = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix().Translate(50, 50),
- FloatPoint3D(100, 100, 0));
-
- auto clip = CreateClip(ClipPaintPropertyNode::Root(), transform.get(),
- FloatRoundedRect(10, 20, 50, 60));
-
+ auto transform =
+ CreateTransform(t0(), TransformationMatrix().Translate(50, 50),
+ FloatPoint3D(100, 100, 0));
+ auto clip =
+ CreateClip(c0(), transform.get(), FloatRoundedRect(10, 20, 50, 60));
float opacity = 2.0 / 255.0;
- auto effect = CreateOpacityEffect(EffectPaintPropertyNode::Root(), transform,
- clip, opacity);
+ auto effect = CreateOpacityEffect(e0(), transform.get(), clip.get(), opacity);
TestPaintArtifact test_artifact;
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- test_artifact.Chunk(transform.get(), clip.get(), effect.get())
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk(*transform, *clip, *effect)
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
- const PaintArtifact& artifact = test_artifact.Build();
- ASSERT_EQ(3u, artifact.PaintChunks().size());
+ auto artifact = test_artifact.Build();
+ ASSERT_EQ(3u, artifact->PaintChunks().size());
Update(artifact);
ASSERT_EQ(1u, ContentLayerCount());
{
@@ -1468,34 +1291,23 @@ TEST_F(PaintArtifactCompositorTest, ClipPushedUp) {
// Tests merging of an element which has a clipapplied to it,
// but has an ancestor transform of them. This can happen for fixed-
// or absolute-position elements which escape scroll transforms.
-
- auto transform = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix().Translate(20, 25),
- FloatPoint3D(100, 100, 0));
-
+ auto transform =
+ CreateTransform(t0(), TransformationMatrix().Translate(20, 25),
+ FloatPoint3D(100, 100, 0));
auto transform2 =
- CreateTransform(transform.get(), TransformationMatrix().Translate(20, 25),
+ CreateTransform(*transform, TransformationMatrix().Translate(20, 25),
FloatPoint3D(100, 100, 0));
-
- auto clip = CreateClip(ClipPaintPropertyNode::Root(), transform2.get(),
- FloatRoundedRect(10, 20, 50, 60));
+ auto clip =
+ CreateClip(c0(), transform2.get(), FloatRoundedRect(10, 20, 50, 60));
TestPaintArtifact test_artifact;
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), clip.get(),
- EffectPaintPropertyNode::Root())
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk(t0(), *clip, e0())
.RectDrawing(FloatRect(0, 0, 300, 400), Color::kBlack);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
- const PaintArtifact& artifact = test_artifact.Build();
- ASSERT_EQ(3u, artifact.PaintChunks().size());
+ auto artifact = test_artifact.Build();
+ ASSERT_EQ(3u, artifact->PaintChunks().size());
Update(artifact);
ASSERT_EQ(1u, ContentLayerCount());
{
@@ -1518,39 +1330,30 @@ TEST_F(PaintArtifactCompositorTest, ClipPushedUp) {
// TODO(crbug.com/696842): The effect refuses to "decomposite" because it's in
// a deeper transform space than its chunk. We should allow decomposite if
// the two transform nodes share the same direct compositing ancestor.
-TEST_F(PaintArtifactCompositorTest, EffectPushedUp_DISABLED) {
+TEST_F(PaintArtifactCompositorTest, DISABLED_EffectPushedUp) {
// Tests merging of an element which has an effect applied to it,
// but has an ancestor transform of them. This can happen for fixed-
// or absolute-position elements which escape scroll transforms.
- auto transform = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix().Translate(20, 25),
- FloatPoint3D(100, 100, 0));
+ auto transform =
+ CreateTransform(t0(), TransformationMatrix().Translate(20, 25),
+ FloatPoint3D(100, 100, 0));
auto transform2 =
- CreateTransform(transform.get(), TransformationMatrix().Translate(20, 25),
+ CreateTransform(*transform, TransformationMatrix().Translate(20, 25),
FloatPoint3D(100, 100, 0));
float opacity = 2.0 / 255.0;
- auto effect = CreateOpacityEffect(EffectPaintPropertyNode::Root(), transform2,
- ClipPaintPropertyNode::Root(), opacity);
+ auto effect = CreateOpacityEffect(e0(), transform2.get(), &c0(), opacity);
TestPaintArtifact test_artifact;
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- effect.get())
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk(t0(), c0(), *effect)
.RectDrawing(FloatRect(0, 0, 300, 400), Color::kBlack);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
- const PaintArtifact& artifact = test_artifact.Build();
- ASSERT_EQ(3u, artifact.PaintChunks().size());
+ auto artifact = test_artifact.Build();
+ ASSERT_EQ(3u, artifact->PaintChunks().size());
Update(artifact);
ASSERT_EQ(1u, ContentLayerCount());
{
@@ -1572,41 +1375,31 @@ TEST_F(PaintArtifactCompositorTest, EffectPushedUp_DISABLED) {
// TODO(crbug.com/696842): The effect refuses to "decomposite" because it's in
// a deeper transform space than its chunk. We should allow decomposite if
// the two transform nodes share the same direct compositing ancestor.
-TEST_F(PaintArtifactCompositorTest, EffectAndClipPushedUp_DISABLED) {
+TEST_F(PaintArtifactCompositorTest, DISABLED_EffectAndClipPushedUp) {
// Tests merging of an element which has an effect applied to it,
// but has an ancestor transform of them. This can happen for fixed-
// or absolute-position elements which escape scroll transforms.
-
- auto transform = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix().Translate(20, 25),
- FloatPoint3D(100, 100, 0));
-
+ auto transform =
+ CreateTransform(t0(), TransformationMatrix().Translate(20, 25),
+ FloatPoint3D(100, 100, 0));
auto transform2 =
- CreateTransform(transform.get(), TransformationMatrix().Translate(20, 25),
+ CreateTransform(*transform, TransformationMatrix().Translate(20, 25),
FloatPoint3D(100, 100, 0));
-
- auto clip = CreateClip(ClipPaintPropertyNode::Root(), transform.get(),
- FloatRoundedRect(10, 20, 50, 60));
+ auto clip =
+ CreateClip(c0(), transform.get(), FloatRoundedRect(10, 20, 50, 60));
float opacity = 2.0 / 255.0;
- auto effect = CreateOpacityEffect(EffectPaintPropertyNode::Root(), transform2,
- clip, opacity);
+ auto effect =
+ CreateOpacityEffect(e0(), transform2.get(), clip.get(), opacity);
TestPaintArtifact test_artifact;
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), clip.get(), effect.get())
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk(t0(), *clip, *effect)
.RectDrawing(FloatRect(0, 0, 300, 400), Color::kBlack);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
- const PaintArtifact& artifact = test_artifact.Build();
- ASSERT_EQ(3u, artifact.PaintChunks().size());
+ auto artifact = test_artifact.Build();
+ ASSERT_EQ(3u, artifact->PaintChunks().size());
Update(artifact);
ASSERT_EQ(1u, ContentLayerCount());
{
@@ -1630,31 +1423,18 @@ TEST_F(PaintArtifactCompositorTest, EffectAndClipPushedUp_DISABLED) {
TEST_F(PaintArtifactCompositorTest, ClipAndEffectNoTransform) {
// Tests merging of an element which has a clip and effect in the root
// transform space.
-
- auto clip = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(10, 20, 50, 60));
-
+ auto clip = CreateClip(c0(), &t0(), FloatRoundedRect(10, 20, 50, 60));
float opacity = 2.0 / 255.0;
- auto effect =
- CreateOpacityEffect(EffectPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(), clip, opacity);
+ auto effect = CreateOpacityEffect(e0(), &t0(), clip.get(), opacity);
TestPaintArtifact test_artifact;
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), clip.get(), effect.get())
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk(t0(), *clip, *effect)
.RectDrawing(FloatRect(0, 0, 300, 400), Color::kBlack);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
- const PaintArtifact& artifact = test_artifact.Build();
- ASSERT_EQ(3u, artifact.PaintChunks().size());
+ auto artifact = test_artifact.Build();
+ ASSERT_EQ(3u, artifact->PaintChunks().size());
Update(artifact);
ASSERT_EQ(1u, ContentLayerCount());
{
@@ -1676,30 +1456,17 @@ TEST_F(PaintArtifactCompositorTest, ClipAndEffectNoTransform) {
TEST_F(PaintArtifactCompositorTest, TwoClips) {
// Tests merging of an element which has two clips in the root
// transform space.
-
- auto clip = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(20, 30, 10, 20));
-
- auto clip2 = CreateClip(clip.get(), TransformPaintPropertyNode::Root(),
- FloatRoundedRect(10, 20, 50, 60));
+ auto clip = CreateClip(c0(), &t0(), FloatRoundedRect(20, 30, 10, 20));
+ auto clip2 = CreateClip(*clip, &t0(), FloatRoundedRect(10, 20, 50, 60));
TestPaintArtifact test_artifact;
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), clip2.get(),
- EffectPaintPropertyNode::Root())
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk(t0(), *clip2, e0())
.RectDrawing(FloatRect(0, 0, 300, 400), Color::kBlack);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
- const PaintArtifact& artifact = test_artifact.Build();
- ASSERT_EQ(3u, artifact.PaintChunks().size());
+ auto artifact = test_artifact.Build();
+ ASSERT_EQ(3u, artifact->PaintChunks().size());
Update(artifact);
ASSERT_EQ(1u, ContentLayerCount());
{
@@ -1719,30 +1486,21 @@ TEST_F(PaintArtifactCompositorTest, TwoClips) {
}
TEST_F(PaintArtifactCompositorTest, TwoTransformsClipBetween) {
- auto transform = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix().Translate(20, 25),
- FloatPoint3D(100, 100, 0));
- auto clip = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(0, 0, 50, 60));
+ auto transform =
+ CreateTransform(t0(), TransformationMatrix().Translate(20, 25),
+ FloatPoint3D(100, 100, 0));
+ auto clip = CreateClip(c0(), &t0(), FloatRoundedRect(0, 0, 50, 60));
auto transform2 =
- CreateTransform(transform.get(), TransformationMatrix().Translate(20, 25),
+ CreateTransform(*transform, TransformationMatrix().Translate(20, 25),
FloatPoint3D(100, 100, 0));
TestPaintArtifact test_artifact;
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- test_artifact
- .Chunk(transform2.get(), clip.get(), EffectPaintPropertyNode::Root())
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk(*transform2, *clip, e0())
.RectDrawing(FloatRect(0, 0, 300, 400), Color::kBlack);
- test_artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
- const PaintArtifact& artifact = test_artifact.Build();
- ASSERT_EQ(3u, artifact.PaintChunks().size());
+ auto artifact = test_artifact.Build();
+ ASSERT_EQ(3u, artifact->PaintChunks().size());
Update(artifact);
ASSERT_EQ(1u, ContentLayerCount());
{
@@ -1760,23 +1518,18 @@ TEST_F(PaintArtifactCompositorTest, TwoTransformsClipBetween) {
}
TEST_F(PaintArtifactCompositorTest, OverlapTransform) {
- auto transform = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix().Translate(50, 50),
- FloatPoint3D(100, 100, 0),
- CompositingReason::k3DTransform);
+ auto transform = CreateTransform(
+ t0(), TransformationMatrix().Translate(50, 50), FloatPoint3D(100, 100, 0),
+ CompositingReason::k3DTransform);
TestPaintArtifact test_artifact;
- test_artifact.Chunk(PropertyTreeState::Root())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- test_artifact
- .Chunk(transform.get(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
+ test_artifact.Chunk(*transform, c0(), e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- test_artifact.Chunk(PropertyTreeState::Root())
- .RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 200, 300), Color::kGray);
- const PaintArtifact& artifact = test_artifact.Build();
- ASSERT_EQ(3u, artifact.PaintChunks().size());
+ auto artifact = test_artifact.Build();
+ ASSERT_EQ(3u, artifact->PaintChunks().size());
Update(artifact);
// The third paint chunk overlaps the second but can't merge due to
// incompatible transform. The second paint chunk can't merge into the first
@@ -1797,18 +1550,17 @@ TEST_F(PaintArtifactCompositorTest, MightOverlap) {
EXPECT_TRUE(MightOverlap(pending_layer, pending_layer2));
}
- auto transform = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix().Translate(99, 0),
- FloatPoint3D(100, 100, 0));
+ auto transform = CreateTransform(
+ t0(), TransformationMatrix().Translate(99, 0), FloatPoint3D(100, 100, 0));
{
paint_chunk2.properties.SetTransform(transform.get());
PendingLayer pending_layer2(paint_chunk2, 1, false);
EXPECT_TRUE(MightOverlap(pending_layer, pending_layer2));
}
- auto transform2 = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix().Translate(100, 0),
- FloatPoint3D(100, 100, 0));
+ auto transform2 =
+ CreateTransform(t0(), TransformationMatrix().Translate(100, 0),
+ FloatPoint3D(100, 100, 0));
{
paint_chunk2.properties.SetTransform(transform2.get());
PendingLayer pending_layer2(paint_chunk2, 1, false);
@@ -1851,14 +1603,12 @@ TEST_F(PaintArtifactCompositorTest, PendingLayer) {
}
TEST_F(PaintArtifactCompositorTest, PendingLayerWithGeometry) {
- auto transform = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix().Translate(20, 25),
- FloatPoint3D(100, 100, 0));
+ auto transform =
+ CreateTransform(t0(), TransformationMatrix().Translate(20, 25),
+ FloatPoint3D(100, 100, 0));
PaintChunk chunk1 = DefaultChunk();
- chunk1.properties = PropertyTreeState(TransformPaintPropertyNode::Root(),
- ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root());
+ chunk1.properties = PropertyTreeState::Root();
chunk1.bounds = FloatRect(0, 0, 30, 40);
PendingLayer pending_layer(chunk1, 0, false);
@@ -1867,7 +1617,7 @@ TEST_F(PaintArtifactCompositorTest, PendingLayerWithGeometry) {
PaintChunk chunk2 = DefaultChunk();
chunk2.properties = chunk1.properties;
- chunk2.properties.SetTransform(transform);
+ chunk2.properties.SetTransform(transform.get());
chunk2.bounds = FloatRect(0, 0, 50, 60);
pending_layer.Merge(PendingLayer(chunk2, 1, false));
@@ -1876,11 +1626,9 @@ TEST_F(PaintArtifactCompositorTest, PendingLayerWithGeometry) {
// TODO(crbug.com/701991):
// The test is disabled because opaque rect mapping is not implemented yet.
-TEST_F(PaintArtifactCompositorTest, PendingLayerKnownOpaque_DISABLED) {
+TEST_F(PaintArtifactCompositorTest, DISABLED_PendingLayerKnownOpaque) {
PaintChunk chunk1 = DefaultChunk();
- chunk1.properties = PropertyTreeState(TransformPaintPropertyNode::Root(),
- ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root());
+ chunk1.properties = PropertyTreeState::Root();
chunk1.bounds = FloatRect(0, 0, 30, 40);
chunk1.known_to_be_opaque = false;
PendingLayer pending_layer(chunk1, 0, false);
@@ -1910,13 +1658,12 @@ TEST_F(PaintArtifactCompositorTest, PendingLayerKnownOpaque_DISABLED) {
scoped_refptr<EffectPaintPropertyNode> CreateSampleEffectNodeWithElementId() {
EffectPaintPropertyNode::State state;
- state.local_transform_space = TransformPaintPropertyNode::Root();
- state.output_clip = ClipPaintPropertyNode::Root();
+ state.local_transform_space = &t0();
+ state.output_clip = &c0();
state.opacity = 2.0 / 255.0;
state.direct_compositing_reasons = CompositingReason::kActiveOpacityAnimation;
state.compositor_element_id = CompositorElementId(2);
- return EffectPaintPropertyNode::Create(EffectPaintPropertyNode::Root(),
- std::move(state));
+ return EffectPaintPropertyNode::Create(e0(), std::move(state));
}
scoped_refptr<TransformPaintPropertyNode>
@@ -1926,16 +1673,13 @@ CreateSampleTransformNodeWithElementId() {
state.origin = FloatPoint3D(100, 100, 0);
state.direct_compositing_reasons = CompositingReason::k3DTransform;
state.compositor_element_id = CompositorElementId(3);
- return TransformPaintPropertyNode::Create(TransformPaintPropertyNode::Root(),
- std::move(state));
+ return TransformPaintPropertyNode::Create(t0(), std::move(state));
}
TEST_F(PaintArtifactCompositorTest, TransformWithElementId) {
auto transform = CreateSampleTransformNodeWithElementId();
TestPaintArtifact artifact;
- artifact
- .Chunk(transform, ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(*transform, c0(), e0())
.RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack);
Update(artifact.Build());
@@ -1946,9 +1690,7 @@ TEST_F(PaintArtifactCompositorTest, TransformWithElementId) {
TEST_F(PaintArtifactCompositorTest, EffectWithElementId) {
auto effect = CreateSampleEffectNodeWithElementId();
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- effect.get())
+ artifact.Chunk(t0(), c0(), *effect)
.RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack);
Update(artifact.Build());
@@ -1956,27 +1698,22 @@ TEST_F(PaintArtifactCompositorTest, EffectWithElementId) {
}
TEST_F(PaintArtifactCompositorTest, CompositedLuminanceMask) {
- auto masked =
- CreateOpacityEffect(EffectPaintPropertyNode::Root(), 1.0,
- CompositingReason::kIsolateCompositedDescendants);
+ auto masked = CreateOpacityEffect(
+ e0(), 1.0, CompositingReason::kIsolateCompositedDescendants);
EffectPaintPropertyNode::State masking_state;
- masking_state.local_transform_space = TransformPaintPropertyNode::Root();
- masking_state.output_clip = ClipPaintPropertyNode::Root();
+ masking_state.local_transform_space = &t0();
+ masking_state.output_clip = &c0();
masking_state.color_filter = kColorFilterLuminanceToAlpha;
masking_state.blend_mode = SkBlendMode::kDstIn;
masking_state.direct_compositing_reasons =
CompositingReason::kSquashingDisallowed;
auto masking =
- EffectPaintPropertyNode::Create(masked, std::move(masking_state));
+ EffectPaintPropertyNode::Create(*masked, std::move(masking_state));
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- masked.get())
+ artifact.Chunk(t0(), c0(), *masked)
.RectDrawing(FloatRect(100, 100, 200, 200), Color::kGray);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- masking.get())
+ artifact.Chunk(t0(), c0(), *masking)
.RectDrawing(FloatRect(150, 150, 100, 100), Color::kWhite);
Update(artifact.Build());
ASSERT_EQ(2u, ContentLayerCount());
@@ -2007,24 +1744,19 @@ TEST_F(PaintArtifactCompositorTest, CompositedLuminanceMask) {
TEST_F(PaintArtifactCompositorTest, UpdateProducesNewSequenceNumber) {
// A 90 degree clockwise rotation about (100, 100).
- auto transform = CreateTransform(
- TransformPaintPropertyNode::Root(), TransformationMatrix().Rotate(90),
- FloatPoint3D(100, 100, 0), CompositingReason::k3DTransform);
-
- auto clip = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(100, 100, 300, 200));
-
- auto effect = CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.5);
+ auto transform = CreateTransform(t0(), TransformationMatrix().Rotate(90),
+ FloatPoint3D(100, 100, 0),
+ CompositingReason::k3DTransform);
+ auto clip = CreateClip(c0(), &t0(), FloatRoundedRect(100, 100, 300, 200));
+ auto effect = CreateOpacityEffect(e0(), 0.5);
- TestPaintArtifact artifact;
- artifact.Chunk(transform, clip, effect)
+ TestPaintArtifact test_artifact;
+ test_artifact.Chunk(*transform, *clip, *effect)
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kWhite);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 100, 100), Color::kGray);
- Update(artifact.Build());
+ test_artifact.Chunk().RectDrawing(FloatRect(0, 0, 100, 100), Color::kGray);
+ auto artifact = test_artifact.Build();
+
+ Update(artifact);
// Two content layers for the differentiated rect drawings and three dummy
// layers for each of the transform, clip and effect nodes.
@@ -2035,7 +1767,7 @@ TEST_F(PaintArtifactCompositorTest, UpdateProducesNewSequenceNumber) {
EXPECT_EQ(sequence_number, layer->property_tree_sequence_number());
}
- Update(artifact.Build());
+ Update(artifact);
EXPECT_EQ(2u, RootLayer()->children().size());
sequence_number++;
@@ -2044,7 +1776,7 @@ TEST_F(PaintArtifactCompositorTest, UpdateProducesNewSequenceNumber) {
EXPECT_EQ(sequence_number, layer->property_tree_sequence_number());
}
- Update(artifact.Build());
+ Update(artifact);
EXPECT_EQ(2u, RootLayer()->children().size());
sequence_number++;
@@ -2057,19 +1789,11 @@ TEST_F(PaintArtifactCompositorTest, UpdateProducesNewSequenceNumber) {
TEST_F(PaintArtifactCompositorTest, DecompositeClip) {
// A clipped paint chunk that gets merged into a previous layer should
// only contribute clipped bounds to the layer bound.
-
- auto clip = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(75, 75, 100, 100));
+ auto clip = CreateClip(c0(), &t0(), FloatRoundedRect(75, 75, 100, 100));
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(50, 50, 100, 100), Color::kGray);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), clip.get(),
- EffectPaintPropertyNode::Root())
+ artifact.Chunk().RectDrawing(FloatRect(50, 50, 100, 100), Color::kGray);
+ artifact.Chunk(t0(), *clip, e0())
.RectDrawing(FloatRect(100, 100, 100, 100), Color::kGray);
Update(artifact.Build());
ASSERT_EQ(1u, ContentLayerCount());
@@ -2084,21 +1808,13 @@ TEST_F(PaintArtifactCompositorTest, DecompositeEffect) {
// group compositing descendants should not be composited and can merge
// with other chunks.
- auto effect = CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.5);
+ auto effect = CreateOpacityEffect(e0(), 0.5);
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(50, 25, 100, 100), Color::kGray);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- effect.get())
+ artifact.Chunk().RectDrawing(FloatRect(50, 25, 100, 100), Color::kGray);
+ artifact.Chunk(t0(), c0(), *effect)
.RectDrawing(FloatRect(25, 75, 100, 100), Color::kGray);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(75, 75, 100, 100), Color::kGray);
+ artifact.Chunk().RectDrawing(FloatRect(75, 75, 100, 100), Color::kGray);
Update(artifact.Build());
ASSERT_EQ(1u, ContentLayerCount());
@@ -2110,22 +1826,13 @@ TEST_F(PaintArtifactCompositorTest, DecompositeEffect) {
TEST_F(PaintArtifactCompositorTest, DirectlyCompositedEffect) {
// An effect node with direct compositing shall be composited.
- auto effect = CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.5f,
- CompositingReason::kAll);
+ auto effect = CreateOpacityEffect(e0(), 0.5f, CompositingReason::kAll);
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(50, 25, 100, 100), Color::kGray);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- effect.get())
+ artifact.Chunk().RectDrawing(FloatRect(50, 25, 100, 100), Color::kGray);
+ artifact.Chunk(t0(), c0(), *effect)
.RectDrawing(FloatRect(25, 75, 100, 100), Color::kGray);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(75, 75, 100, 100), Color::kGray);
+ artifact.Chunk().RectDrawing(FloatRect(75, 75, 100, 100), Color::kGray);
Update(artifact.Build());
ASSERT_EQ(3u, ContentLayerCount());
@@ -2152,23 +1859,15 @@ TEST_F(PaintArtifactCompositorTest, DecompositeDeepEffect) {
// A paint chunk may enter multiple level effects with or without compositing
// reasons. This test verifies we still decomposite effects without a direct
// reason, but stop at a directly composited effect.
- auto effect1 = CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.1f);
- auto effect2 = CreateOpacityEffect(effect1, 0.2f, CompositingReason::kAll);
- auto effect3 = CreateOpacityEffect(effect2, 0.3f);
+ auto effect1 = CreateOpacityEffect(e0(), 0.1f);
+ auto effect2 = CreateOpacityEffect(*effect1, 0.2f, CompositingReason::kAll);
+ auto effect3 = CreateOpacityEffect(*effect2, 0.3f);
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(50, 25, 100, 100), Color::kGray);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- effect3.get())
+ artifact.Chunk().RectDrawing(FloatRect(50, 25, 100, 100), Color::kGray);
+ artifact.Chunk(t0(), c0(), *effect3)
.RectDrawing(FloatRect(25, 75, 100, 100), Color::kGray);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(75, 75, 100, 100), Color::kGray);
+ artifact.Chunk().RectDrawing(FloatRect(75, 75, 100, 100), Color::kGray);
Update(artifact.Build());
ASSERT_EQ(3u, ContentLayerCount());
@@ -2197,21 +1896,15 @@ TEST_F(PaintArtifactCompositorTest, DecompositeDeepEffect) {
TEST_F(PaintArtifactCompositorTest, IndirectlyCompositedEffect) {
// An effect node without direct compositing still needs to be composited
// for grouping, if some chunks need to be composited.
- auto effect = CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.5f);
- auto transform = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix(), FloatPoint3D(),
+ auto effect = CreateOpacityEffect(e0(), 0.5f);
+ auto transform = CreateTransform(t0(), TransformationMatrix(), FloatPoint3D(),
CompositingReason::k3DTransform);
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(50, 25, 100, 100), Color::kGray);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- effect.get())
+ artifact.Chunk().RectDrawing(FloatRect(50, 25, 100, 100), Color::kGray);
+ artifact.Chunk(t0(), c0(), *effect)
.RectDrawing(FloatRect(25, 75, 100, 100), Color::kGray);
- artifact.Chunk(transform.get(), ClipPaintPropertyNode::Root(), effect.get())
+ artifact.Chunk(*transform, c0(), *effect)
.RectDrawing(FloatRect(75, 75, 100, 100), Color::kGray);
Update(artifact.Build());
ASSERT_EQ(3u, ContentLayerCount());
@@ -2238,34 +1931,24 @@ TEST_F(PaintArtifactCompositorTest, IndirectlyCompositedEffect) {
TEST_F(PaintArtifactCompositorTest, DecompositedEffectNotMergingDueToOverlap) {
// This tests an effect that doesn't need to be composited, but needs
// separate backing due to overlap with a previous composited effect.
- auto effect1 = CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.1f);
- auto effect2 = CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.2f);
- auto transform = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix(), FloatPoint3D(),
+ auto effect1 = CreateOpacityEffect(e0(), 0.1f);
+ auto effect2 = CreateOpacityEffect(e0(), 0.2f);
+ auto transform = CreateTransform(t0(), TransformationMatrix(), FloatPoint3D(),
CompositingReason::k3DTransform);
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
- .RectDrawing(FloatRect(0, 0, 50, 50), Color::kGray);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- effect1.get())
+ artifact.Chunk().RectDrawing(FloatRect(0, 0, 50, 50), Color::kGray);
+ artifact.Chunk(t0(), c0(), *effect1)
.RectDrawing(FloatRect(100, 0, 50, 50), Color::kGray);
// This chunk has a transform that must be composited, thus causing effect1
// to be composited too.
- artifact.Chunk(transform.get(), ClipPaintPropertyNode::Root(), effect1.get())
+ artifact.Chunk(*transform, c0(), *effect1)
.RectDrawing(FloatRect(200, 0, 50, 50), Color::kGray);
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- effect2.get())
+ artifact.Chunk(t0(), c0(), *effect2)
.RectDrawing(FloatRect(200, 100, 50, 50), Color::kGray);
// This chunk overlaps with the 2nd chunk, but is seemingly safe to merge.
// However because effect1 gets composited due to a composited transform,
// we can't merge with effect1 nor skip it to merge with the first chunk.
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- effect2.get())
+ artifact.Chunk(t0(), c0(), *effect2)
.RectDrawing(FloatRect(100, 0, 50, 50), Color::kGray);
Update(artifact.Build());
@@ -2299,12 +1982,9 @@ TEST_F(PaintArtifactCompositorTest, UpdatePopulatesCompositedElementIds) {
auto transform = CreateSampleTransformNodeWithElementId();
auto effect = CreateSampleEffectNodeWithElementId();
TestPaintArtifact artifact;
- artifact
- .Chunk(transform, ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(*transform, c0(), e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack)
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- effect.get())
+ .Chunk(t0(), c0(), *effect)
.RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack);
CompositorElementIdSet composited_element_ids;
@@ -2318,105 +1998,100 @@ TEST_F(PaintArtifactCompositorTest, UpdatePopulatesCompositedElementIds) {
}
TEST_F(PaintArtifactCompositorTest, SkipChunkWithOpacityZero) {
- {
- TestPaintArtifact artifact;
- CreateSimpleArtifactWithOpacity(artifact, 0, false, false);
- ASSERT_EQ(0u, ContentLayerCount());
- }
- {
- TestPaintArtifact artifact;
- CreateSimpleArtifactWithOpacity(artifact, 0, true, false);
- ASSERT_EQ(1u, ContentLayerCount());
- }
- {
- TestPaintArtifact artifact;
- CreateSimpleArtifactWithOpacity(artifact, 0, true, true);
- ASSERT_EQ(1u, ContentLayerCount());
- }
- {
- TestPaintArtifact artifact;
- CreateSimpleArtifactWithOpacity(artifact, 0, false, true);
- ASSERT_EQ(1u, ContentLayerCount());
- }
+ UpdateWithArtifactWithOpacity(0, false, false);
+ ASSERT_EQ(0u, ContentLayerCount());
+}
+
+TEST_F(PaintArtifactCompositorTest,
+ SkipChunkWithOpacityZeroWithPrecedingChunk) {
+ UpdateWithArtifactWithOpacity(0, true, false);
+ ASSERT_EQ(1u, ContentLayerCount());
+}
+
+TEST_F(PaintArtifactCompositorTest, SkipChunkWithOpacityZeroSubsequentChunk) {
+ UpdateWithArtifactWithOpacity(0, false, true);
+ ASSERT_EQ(1u, ContentLayerCount());
+}
+
+TEST_F(PaintArtifactCompositorTest,
+ SkipChunkWithOpacityZeroWithPrecedingAndSubsequentChunk) {
+ UpdateWithArtifactWithOpacity(0, true, true);
+ ASSERT_EQ(1u, ContentLayerCount());
}
TEST_F(PaintArtifactCompositorTest, SkipChunkWithTinyOpacity) {
- {
- TestPaintArtifact artifact;
- CreateSimpleArtifactWithOpacity(artifact, 0.0003f, false, false);
- ASSERT_EQ(0u, ContentLayerCount());
- }
- {
- TestPaintArtifact artifact;
- CreateSimpleArtifactWithOpacity(artifact, 0.0003f, true, false);
- ASSERT_EQ(1u, ContentLayerCount());
- }
- {
- TestPaintArtifact artifact;
- CreateSimpleArtifactWithOpacity(artifact, 0.0003f, true, true);
- ASSERT_EQ(1u, ContentLayerCount());
- }
- {
- TestPaintArtifact artifact;
- CreateSimpleArtifactWithOpacity(artifact, 0.0003f, false, true);
- ASSERT_EQ(1u, ContentLayerCount());
- }
+ UpdateWithArtifactWithOpacity(0.0003f, false, false);
+ ASSERT_EQ(0u, ContentLayerCount());
+}
+
+TEST_F(PaintArtifactCompositorTest,
+ SkipChunkWithTinyOpacityWithPrecedingChunk) {
+ UpdateWithArtifactWithOpacity(0.0003f, true, false);
+ ASSERT_EQ(1u, ContentLayerCount());
+}
+
+TEST_F(PaintArtifactCompositorTest, SkipChunkWithTinyOpacitySubsequentChunk) {
+ UpdateWithArtifactWithOpacity(0.0003f, false, true);
+ ASSERT_EQ(1u, ContentLayerCount());
+}
+
+TEST_F(PaintArtifactCompositorTest,
+ SkipChunkWithTinyOpacityWithPrecedingAndSubsequentChunk) {
+ UpdateWithArtifactWithOpacity(0.0003f, true, true);
+ ASSERT_EQ(1u, ContentLayerCount());
}
TEST_F(PaintArtifactCompositorTest, DontSkipChunkWithMinimumOpacity) {
- {
- TestPaintArtifact artifact;
- CreateSimpleArtifactWithOpacity(artifact, 0.0004f, false, false);
- ASSERT_EQ(1u, ContentLayerCount());
- }
- {
- TestPaintArtifact artifact;
- CreateSimpleArtifactWithOpacity(artifact, 0.0004f, true, false);
- ASSERT_EQ(1u, ContentLayerCount());
- }
- {
- TestPaintArtifact artifact;
- CreateSimpleArtifactWithOpacity(artifact, 0.0004f, true, true);
- ASSERT_EQ(1u, ContentLayerCount());
- }
- {
- TestPaintArtifact artifact;
- CreateSimpleArtifactWithOpacity(artifact, 0.0004f, false, true);
- ASSERT_EQ(1u, ContentLayerCount());
- }
+ UpdateWithArtifactWithOpacity(0.0004f, false, false);
+ ASSERT_EQ(1u, ContentLayerCount());
+}
+
+TEST_F(PaintArtifactCompositorTest,
+ DontSkipChunkWithMinimumOpacityWithPrecedingChunk) {
+ UpdateWithArtifactWithOpacity(0.0004f, true, false);
+ ASSERT_EQ(1u, ContentLayerCount());
+}
+
+TEST_F(PaintArtifactCompositorTest,
+ DontSkipChunkWithMinimumOpacitySubsequentChunk) {
+ UpdateWithArtifactWithOpacity(0.0004f, false, true);
+ ASSERT_EQ(1u, ContentLayerCount());
+}
+
+TEST_F(PaintArtifactCompositorTest,
+ DontSkipChunkWithMinimumOpacityWithPrecedingAndSubsequentChunk) {
+ UpdateWithArtifactWithOpacity(0.0004f, true, true);
+ ASSERT_EQ(1u, ContentLayerCount());
}
TEST_F(PaintArtifactCompositorTest, DontSkipChunkWithAboveMinimumOpacity) {
- {
- TestPaintArtifact artifact;
- CreateSimpleArtifactWithOpacity(artifact, 0.3f, false, false);
- ASSERT_EQ(1u, ContentLayerCount());
- }
- {
- TestPaintArtifact artifact;
- CreateSimpleArtifactWithOpacity(artifact, 0.3f, true, false);
- ASSERT_EQ(1u, ContentLayerCount());
- }
- {
- TestPaintArtifact artifact;
- CreateSimpleArtifactWithOpacity(artifact, 0.3f, true, true);
- ASSERT_EQ(1u, ContentLayerCount());
- }
- {
- TestPaintArtifact artifact;
- CreateSimpleArtifactWithOpacity(artifact, 0.3f, false, true);
- ASSERT_EQ(1u, ContentLayerCount());
- }
+ UpdateWithArtifactWithOpacity(0.3f, false, false);
+ ASSERT_EQ(1u, ContentLayerCount());
+}
+
+TEST_F(PaintArtifactCompositorTest,
+ DontSkipChunkWithAboveMinimumOpacityWithPrecedingChunk) {
+ UpdateWithArtifactWithOpacity(0.3f, true, false);
+ ASSERT_EQ(1u, ContentLayerCount());
+}
+
+TEST_F(PaintArtifactCompositorTest,
+ DontSkipChunkWithAboveMinimumOpacitySubsequentChunk) {
+ UpdateWithArtifactWithOpacity(0.3f, false, true);
+ ASSERT_EQ(1u, ContentLayerCount());
+}
+
+TEST_F(PaintArtifactCompositorTest,
+ DontSkipChunkWithAboveMinimumOpacityWithPrecedingAndSubsequentChunk) {
+ UpdateWithArtifactWithOpacity(0.3f, true, true);
+ ASSERT_EQ(1u, ContentLayerCount());
}
TEST_F(PaintArtifactCompositorTest,
DontSkipChunkWithTinyOpacityAndDirectCompositingReason) {
- auto effect = CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.0001f,
- CompositingReason::kCanvas);
+ auto effect = CreateOpacityEffect(e0(), 0.0001f, CompositingReason::kCanvas);
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- effect)
+ artifact.Chunk(t0(), c0(), *effect)
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(1u, ContentLayerCount());
@@ -2424,14 +2099,12 @@ TEST_F(PaintArtifactCompositorTest,
TEST_F(PaintArtifactCompositorTest,
SkipChunkWithTinyOpacityAndVisibleChildEffectNode) {
- auto tiny_effect = CreateOpacityEffect(EffectPaintPropertyNode::Root(),
- 0.0001f, CompositingReason::kNone);
+ auto tiny_effect =
+ CreateOpacityEffect(e0(), 0.0001f, CompositingReason::kNone);
auto visible_effect =
- CreateOpacityEffect(tiny_effect, 0.5f, CompositingReason::kNone);
+ CreateOpacityEffect(*tiny_effect, 0.5f, CompositingReason::kNone);
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- visible_effect)
+ artifact.Chunk(t0(), c0(), *visible_effect)
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(0u, ContentLayerCount());
@@ -2440,13 +2113,11 @@ TEST_F(PaintArtifactCompositorTest,
TEST_F(
PaintArtifactCompositorTest,
DontSkipChunkWithTinyOpacityAndVisibleChildEffectNodeWithCompositingParent) {
- auto tiny_effect = CreateOpacityEffect(EffectPaintPropertyNode::Root(),
- 0.0001f, CompositingReason::kCanvas);
- auto visible_effect = CreateOpacityEffect(tiny_effect, 0.5f);
+ auto tiny_effect =
+ CreateOpacityEffect(e0(), 0.0001f, CompositingReason::kCanvas);
+ auto visible_effect = CreateOpacityEffect(*tiny_effect, 0.5f);
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- visible_effect)
+ artifact.Chunk(t0(), c0(), *visible_effect)
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(1u, ContentLayerCount());
@@ -2454,14 +2125,11 @@ TEST_F(
TEST_F(PaintArtifactCompositorTest,
SkipChunkWithTinyOpacityAndVisibleChildEffectNodeWithCompositingChild) {
- auto tiny_effect =
- CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.0001f);
+ auto tiny_effect = CreateOpacityEffect(e0(), 0.0001f);
auto visible_effect =
- CreateOpacityEffect(tiny_effect, 0.5f, CompositingReason::kCanvas);
+ CreateOpacityEffect(*tiny_effect, 0.5f, CompositingReason::kCanvas);
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- visible_effect)
+ artifact.Chunk(t0(), c0(), *visible_effect)
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(0u, ContentLayerCount());
@@ -2473,9 +2141,7 @@ TEST_F(PaintArtifactCompositorTest, UpdateManagesLayerElementIds) {
{
TestPaintArtifact artifact;
- artifact
- .Chunk(transform, ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())
+ artifact.Chunk(*transform, c0(), e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
@@ -2498,11 +2164,11 @@ TEST_F(PaintArtifactCompositorTest, SynthesizedClipSimple) {
FloatSize corner(5, 5);
FloatRoundedRect rrect(FloatRect(50, 50, 300, 200), corner, corner, corner,
corner);
- auto c1 = CreateClip(c0(), t0(), rrect,
+ auto c1 = CreateClip(c0(), &t0(), rrect,
CompositingReason::kWillChangeCompositingHint);
TestPaintArtifact artifact;
- artifact.Chunk(t0(), c1, e0())
+ artifact.Chunk(t0(), *c1, e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
@@ -2547,12 +2213,12 @@ TEST_F(PaintArtifactCompositorTest,
SynthesizedClipIndirectlyCompositedClipPath) {
// This tests the case that a clip node needs to be synthesized due to
// applying clip path to a composited effect.
- auto c1 = CreateClipPathClip(c0(), t0(), FloatRoundedRect(50, 50, 300, 200));
- auto e1 = CreateOpacityEffect(e0(), t0(), c1, 1,
+ auto c1 = CreateClipPathClip(c0(), &t0(), FloatRoundedRect(50, 50, 300, 200));
+ auto e1 = CreateOpacityEffect(e0(), &t0(), c1.get(), 1,
CompositingReason::kWillChangeCompositingHint);
TestPaintArtifact artifact;
- artifact.Chunk(t0(), c1, e1)
+ artifact.Chunk(t0(), *c1, *e1)
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
@@ -2607,13 +2273,13 @@ TEST_F(PaintArtifactCompositorTest, SynthesizedClipContiguous) {
FloatSize corner(5, 5);
FloatRoundedRect rrect(FloatRect(50, 50, 300, 200), corner, corner, corner,
corner);
- auto c1 = CreateClip(c0(), t0(), rrect,
+ auto c1 = CreateClip(c0(), &t0(), rrect,
CompositingReason::kWillChangeCompositingHint);
TestPaintArtifact artifact;
- artifact.Chunk(t0(), c1, e0())
+ artifact.Chunk(t0(), *c1, e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- artifact.Chunk(t1, c1, e0())
+ artifact.Chunk(*t1, *c1, e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
@@ -2676,15 +2342,15 @@ TEST_F(PaintArtifactCompositorTest, SynthesizedClipDiscontiguous) {
FloatSize corner(5, 5);
FloatRoundedRect rrect(FloatRect(50, 50, 300, 200), corner, corner, corner,
corner);
- auto c1 = CreateClip(c0(), t0(), rrect,
+ auto c1 = CreateClip(c0(), &t0(), rrect,
CompositingReason::kWillChangeCompositingHint);
TestPaintArtifact artifact;
- artifact.Chunk(t0(), c1, e0())
+ artifact.Chunk(t0(), *c1, e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- artifact.Chunk(t1, c0(), e0())
+ artifact.Chunk(*t1, c0(), e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- artifact.Chunk(t0(), c1, e0())
+ artifact.Chunk(t0(), *c1, e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
@@ -2765,18 +2431,17 @@ TEST_F(PaintArtifactCompositorTest, SynthesizedClipAcrossChildEffect) {
FloatSize corner(5, 5);
FloatRoundedRect rrect(FloatRect(50, 50, 300, 200), corner, corner, corner,
corner);
- auto c1 = CreateClip(c0(), t0(), rrect,
+ auto c1 = CreateClip(c0(), &t0(), rrect,
CompositingReason::kWillChangeCompositingHint);
-
- auto e1 = CreateOpacityEffect(e0(), t0(), c1, 1,
+ auto e1 = CreateOpacityEffect(e0(), &t0(), c1.get(), 1,
CompositingReason::kWillChangeCompositingHint);
TestPaintArtifact artifact;
- artifact.Chunk(t0(), c1, e0())
+ artifact.Chunk(t0(), *c1, e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- artifact.Chunk(t0(), c1, e1)
+ artifact.Chunk(t0(), *c1, *e1)
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- artifact.Chunk(t0(), c1, e0())
+ artifact.Chunk(t0(), *c1, e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
@@ -2836,7 +2501,7 @@ TEST_F(PaintArtifactCompositorTest, SynthesizedClipRespectOutputClip) {
FloatSize corner(5, 5);
FloatRoundedRect rrect(FloatRect(50, 50, 300, 200), corner, corner, corner,
corner);
- auto c1 = CreateClip(c0(), t0(), rrect,
+ auto c1 = CreateClip(c0(), &t0(), rrect,
CompositingReason::kWillChangeCompositingHint);
CompositorFilterOperations non_trivial_filter;
@@ -2845,11 +2510,11 @@ TEST_F(PaintArtifactCompositorTest, SynthesizedClipRespectOutputClip) {
CompositingReason::kWillChangeCompositingHint);
TestPaintArtifact artifact;
- artifact.Chunk(t0(), c1, e0())
+ artifact.Chunk(t0(), *c1, e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- artifact.Chunk(t0(), c1, e1)
+ artifact.Chunk(t0(), *c1, *e1)
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- artifact.Chunk(t0(), c1, e0())
+ artifact.Chunk(t0(), *c1, e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
@@ -2941,23 +2606,23 @@ TEST_F(PaintArtifactCompositorTest, SynthesizedClipDelegateBlending) {
FloatSize corner(5, 5);
FloatRoundedRect rrect(FloatRect(50, 50, 300, 200), corner, corner, corner,
corner);
- auto c1 = CreateClip(c0(), t0(), rrect,
+ auto c1 = CreateClip(c0(), &t0(), rrect,
CompositingReason::kWillChangeCompositingHint);
EffectPaintPropertyNode::State e1_state;
- e1_state.local_transform_space = t0();
- e1_state.output_clip = c1;
+ e1_state.local_transform_space = &t0();
+ e1_state.output_clip = c1.get();
e1_state.blend_mode = SkBlendMode::kMultiply;
e1_state.direct_compositing_reasons =
CompositingReason::kWillChangeCompositingHint;
auto e1 = EffectPaintPropertyNode::Create(e0(), std::move(e1_state));
TestPaintArtifact artifact;
- artifact.Chunk(t0(), c1, e0())
+ artifact.Chunk(t0(), *c1, e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- artifact.Chunk(t0(), c1, e1)
+ artifact.Chunk(t0(), *c1, *e1)
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
- artifact.Chunk(t0(), c1, e0())
+ artifact.Chunk(t0(), *c1, e0())
.RectDrawing(FloatRect(0, 0, 100, 100), Color::kBlack);
Update(artifact.Build());
@@ -3045,9 +2710,7 @@ TEST_F(PaintArtifactCompositorTest, SynthesizedClipDelegateBlending) {
TEST_F(PaintArtifactCompositorTest, WillBeRemovedFromFrame) {
auto effect = CreateSampleEffectNodeWithElementId();
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- effect.get())
+ artifact.Chunk(t0(), c0(), *effect)
.RectDrawing(FloatRect(100, 100, 200, 100), Color::kBlack);
Update(artifact.Build());
@@ -3060,8 +2723,7 @@ TEST_F(PaintArtifactCompositorTest, WillBeRemovedFromFrame) {
TEST_F(PaintArtifactCompositorTest, ContentsNonOpaque) {
TestPaintArtifact artifact;
- artifact.Chunk(PropertyTreeState::Root())
- .RectDrawing(FloatRect(100, 100, 200, 200), Color::kBlack);
+ artifact.Chunk().RectDrawing(FloatRect(100, 100, 200, 200), Color::kBlack);
Update(artifact.Build());
ASSERT_EQ(1u, ContentLayerCount());
EXPECT_FALSE(ContentLayerAt(0)->contents_opaque());
@@ -3069,7 +2731,7 @@ TEST_F(PaintArtifactCompositorTest, ContentsNonOpaque) {
TEST_F(PaintArtifactCompositorTest, ContentsOpaque) {
TestPaintArtifact artifact;
- artifact.Chunk(PropertyTreeState::Root())
+ artifact.Chunk()
.RectDrawing(FloatRect(100, 100, 200, 200), Color::kBlack)
.KnownToBeOpaque();
Update(artifact.Build());
@@ -3079,7 +2741,7 @@ TEST_F(PaintArtifactCompositorTest, ContentsOpaque) {
TEST_F(PaintArtifactCompositorTest, ContentsOpaqueSubpixel) {
TestPaintArtifact artifact;
- artifact.Chunk(PropertyTreeState::Root())
+ artifact.Chunk()
.RectDrawing(FloatRect(100.5, 100.5, 200, 200), Color::kBlack)
.KnownToBeOpaque();
Update(artifact.Build());
@@ -3090,10 +2752,10 @@ TEST_F(PaintArtifactCompositorTest, ContentsOpaqueSubpixel) {
TEST_F(PaintArtifactCompositorTest, ContentsOpaqueUnitedNonOpaque) {
TestPaintArtifact artifact;
- artifact.Chunk(PropertyTreeState::Root())
+ artifact.Chunk()
.RectDrawing(FloatRect(100, 100, 200, 200), Color::kBlack)
.KnownToBeOpaque()
- .Chunk(PropertyTreeState::Root())
+ .Chunk()
.RectDrawing(FloatRect(200, 200, 200, 200), Color::kBlack)
.KnownToBeOpaque();
Update(artifact.Build());
@@ -3104,10 +2766,10 @@ TEST_F(PaintArtifactCompositorTest, ContentsOpaqueUnitedNonOpaque) {
TEST_F(PaintArtifactCompositorTest, ContentsOpaqueUnitedOpaque1) {
TestPaintArtifact artifact;
- artifact.Chunk(PropertyTreeState::Root())
+ artifact.Chunk()
.RectDrawing(FloatRect(100, 100, 300, 300), Color::kBlack)
.KnownToBeOpaque()
- .Chunk(PropertyTreeState::Root())
+ .Chunk()
.RectDrawing(FloatRect(200, 200, 200, 200), Color::kBlack)
.KnownToBeOpaque();
Update(artifact.Build());
@@ -3118,10 +2780,10 @@ TEST_F(PaintArtifactCompositorTest, ContentsOpaqueUnitedOpaque1) {
TEST_F(PaintArtifactCompositorTest, ContentsOpaqueUnitedOpaque2) {
TestPaintArtifact artifact;
- artifact.Chunk(PropertyTreeState::Root())
+ artifact.Chunk()
.RectDrawing(FloatRect(100, 100, 200, 200), Color::kBlack)
.KnownToBeOpaque()
- .Chunk(PropertyTreeState::Root())
+ .Chunk()
.RectDrawing(FloatRect(100, 100, 300, 300), Color::kBlack)
.KnownToBeOpaque();
Update(artifact.Build());
@@ -3135,18 +2797,12 @@ TEST_F(PaintArtifactCompositorTest, ContentsOpaqueUnitedOpaque2) {
TEST_F(PaintArtifactCompositorTest, DecompositeEffectWithNoOutputClip) {
// This test verifies effect nodes with no output clip correctly decomposites
// if there is no compositing reasons.
- auto clip1 = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(75, 75, 100, 100));
-
- auto effect1 =
- CreateOpacityEffect(EffectPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(), nullptr, 0.5);
+ auto clip1 = CreateClip(c0(), &t0(), FloatRoundedRect(75, 75, 100, 100));
+ auto effect1 = CreateOpacityEffect(e0(), &t0(), nullptr, 0.5);
TestPaintArtifact artifact;
- artifact.Chunk(PropertyTreeState::Root())
- .RectDrawing(FloatRect(50, 50, 100, 100), Color::kGray);
- artifact.Chunk(TransformPaintPropertyNode::Root(), clip1.get(), effect1.get())
+ artifact.Chunk().RectDrawing(FloatRect(50, 50, 100, 100), Color::kGray);
+ artifact.Chunk(t0(), *clip1, *effect1)
.RectDrawing(FloatRect(100, 100, 100, 100), Color::kGray);
Update(artifact.Build());
ASSERT_EQ(1u, ContentLayerCount());
@@ -3160,20 +2816,15 @@ TEST_F(PaintArtifactCompositorTest, DecompositeEffectWithNoOutputClip) {
TEST_F(PaintArtifactCompositorTest, CompositedEffectWithNoOutputClip) {
// This test verifies effect nodes with no output clip but has compositing
// reason correctly squash children chunks and assign clip node.
- auto clip1 = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(75, 75, 100, 100));
+ auto clip1 = CreateClip(c0(), &t0(), FloatRoundedRect(75, 75, 100, 100));
- auto effect1 = CreateOpacityEffect(EffectPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- nullptr, 0.5, CompositingReason::kAll);
+ auto effect1 =
+ CreateOpacityEffect(e0(), &t0(), nullptr, 0.5, CompositingReason::kAll);
TestPaintArtifact artifact;
- artifact
- .Chunk(TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- effect1.get())
+ artifact.Chunk(t0(), c0(), *effect1)
.RectDrawing(FloatRect(50, 50, 100, 100), Color::kGray);
- artifact.Chunk(TransformPaintPropertyNode::Root(), clip1.get(), effect1.get())
+ artifact.Chunk(t0(), *clip1, *effect1)
.RectDrawing(FloatRect(100, 100, 100, 100), Color::kGray);
Update(artifact.Build());
ASSERT_EQ(1u, ContentLayerCount());
@@ -3186,15 +2837,18 @@ TEST_F(PaintArtifactCompositorTest, CompositedEffectWithNoOutputClip) {
}
TEST_F(PaintArtifactCompositorTest, LayerRasterInvalidationWithClip) {
+ cc::FakeImplTaskRunnerProvider task_runner_provider_;
+ cc::TestTaskGraphRunner task_graph_runner_;
+ cc::FakeLayerTreeHostImpl host_impl(&task_runner_provider_,
+ &task_graph_runner_);
+
// The layer's painting is initially not clipped.
- auto clip = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(10, 20, 300, 400));
+ auto clip = CreateClip(c0(), &t0(), FloatRoundedRect(10, 20, 300, 400));
TestPaintArtifact artifact1;
- artifact1
- .Chunk(TransformPaintPropertyNode::Root(), clip,
- EffectPaintPropertyNode::Root())
+ artifact1.Chunk(t0(), *clip, e0())
.RectDrawing(FloatRect(50, 50, 200, 200), Color::kBlack);
+ artifact1.Client(0).Validate();
+ artifact1.Client(1).Validate();
Update(artifact1.Build());
ASSERT_EQ(1u, ContentLayerCount());
@@ -3205,15 +2859,17 @@ TEST_F(PaintArtifactCompositorTest, LayerRasterInvalidationWithClip) {
layer->GetPicture(),
Pointee(DrawsRectangle(FloatRect(0, 0, 200, 200), Color::kBlack)));
- // The layer's painting overflows the left, top, right edges of the clip .
- TestPaintArtifact artifact2;
- artifact2
- .Chunk(artifact1.Client(0), TransformPaintPropertyNode::Root(), clip,
- EffectPaintPropertyNode::Root())
- .RectDrawing(artifact1.Client(1), FloatRect(0, 0, 400, 200),
- Color::kBlack);
- layer->ResetNeedsDisplayForTesting();
- Update(artifact2.Build());
+ // The layer's painting overflows the left, top, right edges of the clip.
+ auto artifact2 = TestPaintArtifact()
+ .Chunk(artifact1.Client(0))
+ .Properties(t0(), *clip, e0())
+ .RectDrawing(artifact1.Client(1),
+ FloatRect(0, 0, 400, 200), Color::kBlack)
+ .Build();
+ // Simluate commit to the compositor thread.
+ layer->PushPropertiesTo(
+ layer->CreateLayerImpl(host_impl.active_tree()).get());
+ Update(artifact2);
ASSERT_EQ(1u, ContentLayerCount());
ASSERT_EQ(layer, ContentLayerAt(0));
@@ -3226,14 +2882,17 @@ TEST_F(PaintArtifactCompositorTest, LayerRasterInvalidationWithClip) {
Pointee(DrawsRectangle(FloatRect(0, 0, 390, 180), Color::kBlack)));
// The layer's painting overflows all edges of the clip.
- TestPaintArtifact artifact3;
- artifact3
- .Chunk(artifact1.Client(0), TransformPaintPropertyNode::Root(), clip,
- EffectPaintPropertyNode::Root())
- .RectDrawing(artifact1.Client(1), FloatRect(-100, -200, 500, 800),
- Color::kBlack);
- layer->ResetNeedsDisplayForTesting();
- Update(artifact3.Build());
+ auto artifact3 =
+ TestPaintArtifact()
+ .Chunk(artifact1.Client(0))
+ .Properties(t0(), *clip, e0())
+ .RectDrawing(artifact1.Client(1), FloatRect(-100, -200, 500, 800),
+ Color::kBlack)
+ .Build();
+ // Simluate commit to the compositor thread.
+ layer->PushPropertiesTo(
+ layer->CreateLayerImpl(host_impl.active_tree()).get());
+ Update(artifact3);
ASSERT_EQ(1u, ContentLayerCount());
ASSERT_EQ(layer, ContentLayerAt(0));
@@ -3247,4 +2906,30 @@ TEST_F(PaintArtifactCompositorTest, LayerRasterInvalidationWithClip) {
Pointee(DrawsRectangle(FloatRect(0, 0, 390, 580), Color::kBlack)));
}
+// Test that PaintArtifactCompositor creates the correct nodes for the visual
+// viewport's page scale and scroll layers to support pinch-zooming.
+TEST_F(PaintArtifactCompositorTest, CreatesViewportNodes) {
+ TransformationMatrix matrix;
+ matrix.Scale(2);
+ TransformPaintPropertyNode::State transform_state{matrix, FloatPoint3D()};
+ transform_state.compositor_element_id =
+ CompositorElementIdFromUniqueObjectId(1);
+
+ auto scale_transform_node = TransformPaintPropertyNode::Create(
+ TransformPaintPropertyNode::Root(), std::move(transform_state));
+
+ TestPaintArtifact artifact;
+ CompositorElementIdSet element_ids;
+ Update(artifact.Build(), element_ids, scale_transform_node.get());
+
+ cc::TransformTree& transform_tree = GetPropertyTrees().transform_tree;
+ cc::TransformNode* cc_transform_node = transform_tree.FindNodeFromElementId(
+ transform_state.compositor_element_id);
+ EXPECT_TRUE(cc_transform_node);
+ EXPECT_EQ(TransformationMatrix::ToTransform(matrix),
+ cc_transform_node->post_local);
+ EXPECT_TRUE(cc_transform_node->local.IsIdentity());
+ EXPECT_TRUE(cc_transform_node->pre_local.IsIdentity());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
index 47f5994fc88..1b80b0a7702 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
@@ -480,7 +480,7 @@ void ConversionContext::StartEffect(const EffectPaintPropertyNode* effect) {
auto alpha =
static_cast<uint8_t>(gfx::ToFlooredInt(255 * effect->Opacity()));
if (has_other_effects) {
- cc::PaintFlags flags;
+ PaintFlags flags;
flags.setBlendMode(effect->BlendMode());
flags.setAlpha(alpha);
flags.setColorFilter(GraphicsContext::WebCoreColorFilterToSkiaColorFilter(
@@ -504,7 +504,7 @@ void ConversionContext::StartEffect(const EffectPaintPropertyNode* effect) {
// The size parameter is only used to computed the origin of zoom
// operation, which we never generate.
gfx::SizeF empty;
- cc::PaintFlags filter_flags;
+ PaintFlags filter_flags;
filter_flags.setImageFilter(cc::RenderSurfaceFilters::BuildImageFilter(
effect->Filter().AsCcFilterOperations(), empty));
save_layer_id = cc_list_.push<cc::SaveLayerOp>(nullptr, &filter_flags);
@@ -654,7 +654,7 @@ void ConversionContext::Convert(const PaintChunkSubset& paint_chunks,
// "draw" this record in order to ensure that the effect has correct
// visual rects.
if ((!record || record->size() == 0) &&
- chunk_state.Effect() == EffectPaintPropertyNode::Root()) {
+ chunk_state.Effect() == &EffectPaintPropertyNode::Root()) {
continue;
}
@@ -683,8 +683,6 @@ void PaintChunksToCcLayer::ConvertInto(
const FloatSize& visual_rect_subpixel_offset,
const DisplayItemList& display_items,
cc::DisplayItemList& cc_list) {
- if (RuntimeEnabledFeatures::DisablePaintChunksToCcLayerEnabled())
- return;
ConversionContext(layer_state, layer_offset, visual_rect_subpixel_offset,
cc_list)
.Convert(paint_chunks, display_items);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc
index 6fc715970d6..dd452218a15 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer_test.cc
@@ -7,6 +7,7 @@
#include <initializer_list>
#include "cc/paint/display_item_list.h"
+#include "cc/paint/paint_flags.h"
#include "cc/paint/paint_op_buffer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -148,17 +149,6 @@ class PaintRecordMatcher
EXPECT_EQ(SkRRect(r), clip_op->rrect); \
} while (false)
-// Convenient shorthands.
-const TransformPaintPropertyNode* t0() {
- return TransformPaintPropertyNode::Root();
-}
-const ClipPaintPropertyNode* c0() {
- return ClipPaintPropertyNode::Root();
-}
-const EffectPaintPropertyNode* e0() {
- return EffectPaintPropertyNode::Root();
-}
-
PaintChunk::Id DefaultId() {
DEFINE_STATIC_LOCAL(FakeDisplayItemClient, fake_client,
("FakeDisplayItemClient", LayoutRect(0, 0, 100, 100)));
@@ -170,9 +160,9 @@ struct TestChunks {
DisplayItemList items = DisplayItemList(0);
// Add a paint chunk with a non-empty paint record and given property nodes.
- void AddChunk(const TransformPaintPropertyNode* t,
- const ClipPaintPropertyNode* c,
- const EffectPaintPropertyNode* e,
+ void AddChunk(const TransformPaintPropertyNode& t,
+ const ClipPaintPropertyNode& c,
+ const EffectPaintPropertyNode& e,
const FloatRect& bounds = FloatRect(0, 0, 100, 100)) {
auto record = sk_make_sp<PaintRecord>();
record->push<cc::DrawRectOp>(bounds, cc::PaintFlags());
@@ -181,14 +171,14 @@ struct TestChunks {
// Add a paint chunk with a given paint record and property nodes.
void AddChunk(sk_sp<PaintRecord> record,
- const TransformPaintPropertyNode* t,
- const ClipPaintPropertyNode* c,
- const EffectPaintPropertyNode* e,
+ const TransformPaintPropertyNode& t,
+ const ClipPaintPropertyNode& c,
+ const EffectPaintPropertyNode& e,
const FloatRect& bounds = FloatRect(0, 0, 100, 100)) {
size_t i = items.size();
items.AllocateAndConstruct<DrawingDisplayItem>(
DefaultId().client, DefaultId().type, std::move(record));
- chunks.emplace_back(i, i + 1, DefaultId(), PropertyTreeState(t, c, e));
+ chunks.emplace_back(i, i + 1, DefaultId(), PropertyTreeState(&t, &c, &e));
chunks.back().bounds = bounds;
}
};
@@ -197,12 +187,12 @@ TEST_F(PaintChunksToCcLayerTest, EffectGroupingSimple) {
// This test verifies effects are applied as a group.
auto e1 = CreateOpacityEffect(e0(), 0.5f);
TestChunks chunks;
- chunks.AddChunk(t0(), c0(), e1.get(), FloatRect(0, 0, 50, 50));
- chunks.AddChunk(t0(), c0(), e1.get(), FloatRect(20, 20, 70, 70));
+ chunks.AddChunk(t0(), c0(), *e1, FloatRect(0, 0, 50, 50));
+ chunks.AddChunk(t0(), c0(), *e1, FloatRect(20, 20, 70, 70));
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c0(), e0()), gfx::Vector2dF(),
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(
@@ -217,15 +207,15 @@ TEST_F(PaintChunksToCcLayerTest, EffectGroupingSimple) {
TEST_F(PaintChunksToCcLayerTest, EffectGroupingNested) {
// This test verifies nested effects are grouped properly.
auto e1 = CreateOpacityEffect(e0(), 0.5f);
- auto e2 = CreateOpacityEffect(e1, 0.5f);
- auto e3 = CreateOpacityEffect(e1, 0.5f);
+ auto e2 = CreateOpacityEffect(*e1, 0.5f);
+ auto e3 = CreateOpacityEffect(*e1, 0.5f);
TestChunks chunks;
- chunks.AddChunk(t0(), c0(), e2.get());
- chunks.AddChunk(t0(), c0(), e3.get(), FloatRect(111, 222, 333, 444));
+ chunks.AddChunk(t0(), c0(), *e2);
+ chunks.AddChunk(t0(), c0(), *e3, FloatRect(111, 222, 333, 444));
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c0(), e0()), gfx::Vector2dF(),
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(
@@ -246,19 +236,19 @@ TEST_F(PaintChunksToCcLayerTest, EffectGroupingNested) {
TEST_F(PaintChunksToCcLayerTest, EffectFilterGroupingNestedWithTransforms) {
// This test verifies nested effects with transforms are grouped properly.
auto t1 = CreateTransform(t0(), TransformationMatrix().Scale(2.f));
- auto t2 = CreateTransform(t1, TransformationMatrix().Translate(-50, -50));
- auto e1 = CreateOpacityEffect(e0(), t2, c0(), 0.5);
+ auto t2 = CreateTransform(*t1, TransformationMatrix().Translate(-50, -50));
+ auto e1 = CreateOpacityEffect(e0(), t2.get(), &c0(), 0.5);
CompositorFilterOperations filter;
filter.AppendBlurFilter(5);
- auto e2 = CreateFilterEffect(e1, filter, FloatPoint(60, 60));
+ auto e2 = CreateFilterEffect(*e1, filter, FloatPoint(60, 60));
TestChunks chunks;
- chunks.AddChunk(t2.get(), c0(), e1.get(), FloatRect(0, 0, 50, 50));
- chunks.AddChunk(t1.get(), c0(), e2.get(), FloatRect(20, 20, 70, 70));
+ chunks.AddChunk(*t2, c0(), *e1, FloatRect(0, 0, 50, 50));
+ chunks.AddChunk(*t1, c0(), *e2, FloatRect(20, 20, 70, 70));
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c0(), e0()), gfx::Vector2dF(),
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(
@@ -296,22 +286,22 @@ TEST_F(PaintChunksToCcLayerTest, InterleavedClipEffect) {
// ConversionContext.
// Refer to PaintChunksToCcLayer.cpp for detailed explanation.
// (Search "State management example".)
- auto c1 = CreateClip(c0(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
- auto c2 = CreateClip(c1, t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
- auto c3 = CreateClip(c2, t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
- auto c4 = CreateClip(c3, t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
- auto e1 = CreateOpacityEffect(e0(), t0(), c2, 0.5);
- auto e2 = CreateOpacityEffect(e1, t0(), c4, 0.5);
+ auto c1 = CreateClip(c0(), &t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+ auto c2 = CreateClip(*c1, &t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+ auto c3 = CreateClip(*c2, &t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+ auto c4 = CreateClip(*c3, &t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+ auto e1 = CreateOpacityEffect(e0(), &t0(), c2.get(), 0.5);
+ auto e2 = CreateOpacityEffect(*e1, &t0(), c4.get(), 0.5);
TestChunks chunks;
- chunks.AddChunk(t0(), c2.get(), e0());
- chunks.AddChunk(t0(), c3.get(), e0());
- chunks.AddChunk(t0(), c4.get(), e2.get(), FloatRect(0, 0, 50, 50));
- chunks.AddChunk(t0(), c3.get(), e1.get(), FloatRect(20, 20, 70, 70));
- chunks.AddChunk(t0(), c4.get(), e0());
+ chunks.AddChunk(t0(), *c2, e0());
+ chunks.AddChunk(t0(), *c3, e0());
+ chunks.AddChunk(t0(), *c4, *e2, FloatRect(0, 0, 50, 50));
+ chunks.AddChunk(t0(), *c3, *e1, FloatRect(20, 20, 70, 70));
+ chunks.AddChunk(t0(), *c4, e0());
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c0(), e0()), gfx::Vector2dF(),
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(*output, PaintRecordMatcher::Make(
@@ -350,13 +340,13 @@ TEST_F(PaintChunksToCcLayerTest, ClipSpaceInversion) {
// <div style="position:fixed;">Clipped but not scroll along.</div>
// </div>
auto t1 = CreateTransform(t0(), TransformationMatrix().Scale(2.f));
- auto c1 = CreateClip(c0(), t1, FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+ auto c1 = CreateClip(c0(), t1.get(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
TestChunks chunks;
- chunks.AddChunk(t0(), c1.get(), e0());
+ chunks.AddChunk(t0(), *c1, e0());
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c0(), e0()), gfx::Vector2dF(),
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(*output,
@@ -378,14 +368,14 @@ TEST_F(PaintChunksToCcLayerTest, OpacityEffectSpaceInversion) {
// </div>
// </div>
auto t1 = CreateTransform(t0(), TransformationMatrix().Scale(2.f));
- auto e1 = CreateOpacityEffect(e0(), t1, c0(), 0.5);
+ auto e1 = CreateOpacityEffect(e0(), t1.get(), &c0(), 0.5);
TestChunks chunks;
- chunks.AddChunk(t0(), c0(), e1.get());
- chunks.AddChunk(t1.get(), c0(), e1.get());
+ chunks.AddChunk(t0(), c0(), *e1);
+ chunks.AddChunk(*t1, c0(), *e1);
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c0(), e0()), gfx::Vector2dF(),
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(*output,
@@ -414,13 +404,14 @@ TEST_F(PaintChunksToCcLayerTest, FilterEffectSpaceInversion) {
auto t1 = CreateTransform(t0(), TransformationMatrix().Scale(2.f));
CompositorFilterOperations filter;
filter.AppendBlurFilter(5);
- auto e1 = CreateFilterEffect(e0(), t1, c0(), filter, FloatPoint(66, 88));
+ auto e1 =
+ CreateFilterEffect(e0(), t1.get(), &c0(), filter, FloatPoint(66, 88));
TestChunks chunks;
- chunks.AddChunk(t0(), c0(), e1.get());
+ chunks.AddChunk(t0(), c0(), *e1);
auto output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c0(), e0()), gfx::Vector2dF(),
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(
@@ -447,10 +438,10 @@ TEST_F(PaintChunksToCcLayerTest, NonRootLayerSimple) {
// This test verifies a layer with composited property state does not
// apply properties again internally.
auto t1 = CreateTransform(t0(), TransformationMatrix().Scale(2.f));
- auto c1 = CreateClip(c0(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+ auto c1 = CreateClip(c0(), &t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
auto e1 = CreateOpacityEffect(e0(), 0.5f);
TestChunks chunks;
- chunks.AddChunk(t1.get(), c1.get(), e1.get());
+ chunks.AddChunk(*t1, *c1, *e1);
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
@@ -465,10 +456,10 @@ TEST_F(PaintChunksToCcLayerTest, NonRootLayerTransformEscape) {
// This test verifies chunks that have a shallower transform state than the
// layer can still be painted.
auto t1 = CreateTransform(t0(), TransformationMatrix().Scale(2.f));
- auto c1 = CreateClip(c0(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+ auto c1 = CreateClip(c0(), &t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
auto e1 = CreateOpacityEffect(e0(), 0.5f);
TestChunks chunks;
- chunks.AddChunk(t0(), c1.get(), e1.get());
+ chunks.AddChunk(t0(), *c1, *e1);
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
@@ -485,16 +476,16 @@ TEST_F(PaintChunksToCcLayerTest, NonRootLayerTransformEscape) {
TEST_F(PaintChunksToCcLayerTest, EffectWithNoOutputClip) {
// This test verifies effect with no output clip can be correctly processed.
- auto c1 = CreateClip(c0(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
- auto c2 = CreateClip(c1, t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
- auto e1 = CreateOpacityEffect(e0(), t0(), nullptr, 0.5);
+ auto c1 = CreateClip(c0(), &t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+ auto c2 = CreateClip(*c1, &t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+ auto e1 = CreateOpacityEffect(e0(), &t0(), nullptr, 0.5);
TestChunks chunks;
- chunks.AddChunk(t0(), c2.get(), e1.get());
+ chunks.AddChunk(t0(), *c2, *e1);
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c1.get(), e0()),
+ chunks.chunks, PropertyTreeState(&t0(), c1.get(), &e0()),
gfx::Vector2dF(), chunks.items,
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -511,16 +502,16 @@ TEST_F(PaintChunksToCcLayerTest, EffectWithNoOutputClip) {
TEST_F(PaintChunksToCcLayerTest,
EffectWithNoOutputClipNestedInDecompositedEffect) {
- auto c1 = CreateClip(c0(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+ auto c1 = CreateClip(c0(), &t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
auto e1 = CreateOpacityEffect(e0(), 0.5);
- auto e2 = CreateOpacityEffect(e1, t0(), nullptr, 0.5);
+ auto e2 = CreateOpacityEffect(*e1, &t0(), nullptr, 0.5);
TestChunks chunks;
- chunks.AddChunk(t0(), c1.get(), e2.get());
+ chunks.AddChunk(t0(), *c1, *e2);
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c0(), e0()), gfx::Vector2dF(),
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
EXPECT_THAT(
@@ -539,16 +530,16 @@ TEST_F(PaintChunksToCcLayerTest,
TEST_F(PaintChunksToCcLayerTest,
EffectWithNoOutputClipNestedInCompositedEffect) {
- auto c1 = CreateClip(c0(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+ auto c1 = CreateClip(c0(), &t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
auto e1 = CreateOpacityEffect(e0(), 0.5);
- auto e2 = CreateOpacityEffect(e1, t0(), nullptr, 0.5);
+ auto e2 = CreateOpacityEffect(*e1, &t0(), nullptr, 0.5);
TestChunks chunks;
- chunks.AddChunk(t0(), c1.get(), e2.get());
+ chunks.AddChunk(t0(), *c1, *e2);
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c0(), e1.get()),
+ chunks.chunks, PropertyTreeState(&t0(), &c0(), e1.get()),
gfx::Vector2dF(), chunks.items,
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -565,16 +556,16 @@ TEST_F(PaintChunksToCcLayerTest,
TEST_F(PaintChunksToCcLayerTest,
EffectWithNoOutputClipNestedInCompositedEffectAndClip) {
- auto c1 = CreateClip(c0(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+ auto c1 = CreateClip(c0(), &t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
auto e1 = CreateOpacityEffect(e0(), 0.5);
- auto e2 = CreateOpacityEffect(e1, t0(), nullptr, 0.5);
+ auto e2 = CreateOpacityEffect(*e1, &t0(), nullptr, 0.5);
TestChunks chunks;
- chunks.AddChunk(t0(), c1.get(), e2.get());
+ chunks.AddChunk(t0(), *c1, *e2);
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c1.get(), e1.get()),
+ chunks.chunks, PropertyTreeState(&t0(), c1.get(), e1.get()),
gfx::Vector2dF(), chunks.items,
cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -590,15 +581,15 @@ TEST_F(PaintChunksToCcLayerTest, VisualRect) {
auto layer_transform =
CreateTransform(t0(), TransformationMatrix().Scale(20));
auto chunk_transform = CreateTransform(
- layer_transform, TransformationMatrix().Translate(50, 100));
+ *layer_transform, TransformationMatrix().Translate(50, 100));
TestChunks chunks;
- chunks.AddChunk(chunk_transform.get(), c0(), e0());
+ chunks.AddChunk(*chunk_transform, c0(), e0());
auto cc_list = base::MakeRefCounted<cc::DisplayItemList>(
cc::DisplayItemList::kTopLevelDisplayItemList);
PaintChunksToCcLayer::ConvertInto(
- chunks.chunks, PropertyTreeState(layer_transform.get(), c0(), e0()),
+ chunks.chunks, PropertyTreeState(layer_transform.get(), &c0(), &e0()),
gfx::Vector2dF(100, 200), FloatSize(), chunks.items, *cc_list);
EXPECT_EQ(gfx::Rect(-50, -100, 100, 100), cc_list->VisualRectForTesting(4));
@@ -614,15 +605,15 @@ TEST_F(PaintChunksToCcLayerTest, VisualRect) {
}
TEST_F(PaintChunksToCcLayerTest, NoncompositedClipPath) {
- auto c1 = CreateClipPathClip(c0(), t0(), FloatRoundedRect(1, 2, 3, 4));
+ auto c1 = CreateClipPathClip(c0(), &t0(), FloatRoundedRect(1, 2, 3, 4));
TestChunks chunks;
- chunks.AddChunk(t0(), c1.get(), e0());
+ chunks.AddChunk(t0(), *c1, e0());
auto cc_list = base::MakeRefCounted<cc::DisplayItemList>(
cc::DisplayItemList::kTopLevelDisplayItemList);
- PaintChunksToCcLayer::ConvertInto(
- chunks.chunks, PropertyTreeState(t0(), c0(), e0()), gfx::Vector2dF(),
- FloatSize(), chunks.items, *cc_list);
+ PaintChunksToCcLayer::ConvertInto(chunks.chunks, PropertyTreeState::Root(),
+ gfx::Vector2dF(), FloatSize(), chunks.items,
+ *cc_list);
EXPECT_THAT(
*cc_list->ReleaseAsRecord(),
@@ -634,22 +625,22 @@ TEST_F(PaintChunksToCcLayerTest, NoncompositedClipPath) {
}
TEST_F(PaintChunksToCcLayerTest, EmptyClipsAreElided) {
- auto c1 = CreateClip(c0(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
- auto c1c2 = CreateClip(c1, t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
- auto c2 = CreateClip(c0(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+ auto c1 = CreateClip(c0(), &t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+ auto c1c2 = CreateClip(*c1, &t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+ auto c2 = CreateClip(c0(), &t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
TestChunks chunks;
- chunks.AddChunk(nullptr, t0(), c1.get(), e0());
- chunks.AddChunk(nullptr, t0(), c1c2.get(), e0());
- chunks.AddChunk(nullptr, t0(), c1c2.get(), e0());
- chunks.AddChunk(nullptr, t0(), c1c2.get(), e0());
- chunks.AddChunk(nullptr, t0(), c1.get(), e0());
+ chunks.AddChunk(nullptr, t0(), *c1, e0());
+ chunks.AddChunk(nullptr, t0(), *c1c2, e0());
+ chunks.AddChunk(nullptr, t0(), *c1c2, e0());
+ chunks.AddChunk(nullptr, t0(), *c1c2, e0());
+ chunks.AddChunk(nullptr, t0(), *c1, e0());
// D1
- chunks.AddChunk(t0(), c2.get(), e0());
+ chunks.AddChunk(t0(), *c2, e0());
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c0(), e0()), gfx::Vector2dF(),
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -663,23 +654,23 @@ TEST_F(PaintChunksToCcLayerTest, EmptyClipsAreElided) {
}
TEST_F(PaintChunksToCcLayerTest, NonEmptyClipsAreStored) {
- auto c1 = CreateClip(c0(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
- auto c1c2 = CreateClip(c1, t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
- auto c2 = CreateClip(c0(), t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+ auto c1 = CreateClip(c0(), &t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+ auto c1c2 = CreateClip(*c1, &t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
+ auto c2 = CreateClip(c0(), &t0(), FloatRoundedRect(0.f, 0.f, 1.f, 1.f));
TestChunks chunks;
- chunks.AddChunk(nullptr, t0(), c1.get(), e0());
- chunks.AddChunk(nullptr, t0(), c1c2.get(), e0());
- chunks.AddChunk(nullptr, t0(), c1c2.get(), e0());
+ chunks.AddChunk(nullptr, t0(), *c1, e0());
+ chunks.AddChunk(nullptr, t0(), *c1c2, e0());
+ chunks.AddChunk(nullptr, t0(), *c1c2, e0());
// D1
- chunks.AddChunk(t0(), c1c2.get(), e0());
- chunks.AddChunk(nullptr, t0(), c1.get(), e0());
+ chunks.AddChunk(t0(), *c1c2, e0());
+ chunks.AddChunk(nullptr, t0(), *c1, e0());
// D2
- chunks.AddChunk(t0(), c2.get(), e0());
+ chunks.AddChunk(t0(), *c2, e0());
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c0(), e0()), gfx::Vector2dF(),
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -699,11 +690,11 @@ TEST_F(PaintChunksToCcLayerTest, EmptyEffectsAreStored) {
TestChunks chunks;
chunks.AddChunk(nullptr, t0(), c0(), e0());
- chunks.AddChunk(nullptr, t0(), c0(), e1.get());
+ chunks.AddChunk(nullptr, t0(), c0(), *e1);
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c0(), e0()), gfx::Vector2dF(),
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -717,20 +708,20 @@ TEST_F(PaintChunksToCcLayerTest, EmptyEffectsAreStored) {
TEST_F(PaintChunksToCcLayerTest, CombineClips) {
FloatRoundedRect clip_rect(0, 0, 100, 100);
auto t1 = CreateTransform(t0(), TransformationMatrix().Scale(2.f));
- auto c1 = CreateClip(c0(), t0(), clip_rect);
- auto c2 = CreateClip(c1, t0(), clip_rect);
- auto c3 = CreateClip(c2, t1, clip_rect);
- auto c4 = CreateClip(c3, t1, clip_rect);
- auto c5 = CreateClipPathClip(c4, t1, clip_rect);
- auto c6 = CreateClip(c5, t1, clip_rect);
+ auto c1 = CreateClip(c0(), &t0(), clip_rect);
+ auto c2 = CreateClip(*c1, &t0(), clip_rect);
+ auto c3 = CreateClip(*c2, t1.get(), clip_rect);
+ auto c4 = CreateClip(*c3, t1.get(), clip_rect);
+ auto c5 = CreateClipPathClip(*c4, t1.get(), clip_rect);
+ auto c6 = CreateClip(*c5, t1.get(), clip_rect);
TestChunks chunks;
- chunks.AddChunk(t1.get(), c6.get(), e0());
- chunks.AddChunk(t1.get(), c3.get(), e0());
+ chunks.AddChunk(*t1, *c6, e0());
+ chunks.AddChunk(*t1, *c3, e0());
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c0(), e0()), gfx::Vector2dF(),
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -803,20 +794,20 @@ TEST_F(PaintChunksToCcLayerTest, CombineClipsWithRoundedRects) {
FloatRoundedRect small_rounded_clip_rect(FloatRect(0, 0, 100, 100), corner,
corner, corner, corner);
- auto c1 = CreateClip(c0(), t0(), clip_rect);
- auto c2 = CreateClip(c1, t0(), small_rounded_clip_rect);
- auto c3 = CreateClip(c2, t0(), clip_rect);
- auto c4 = CreateClip(c3, t0(), big_rounded_clip_rect);
- auto c5 = CreateClip(c4, t0(), clip_rect);
- auto c6 = CreateClip(c5, t0(), big_rounded_clip_rect);
- auto c7 = CreateClip(c6, t0(), small_rounded_clip_rect);
+ auto c1 = CreateClip(c0(), &t0(), clip_rect);
+ auto c2 = CreateClip(*c1, &t0(), small_rounded_clip_rect);
+ auto c3 = CreateClip(*c2, &t0(), clip_rect);
+ auto c4 = CreateClip(*c3, &t0(), big_rounded_clip_rect);
+ auto c5 = CreateClip(*c4, &t0(), clip_rect);
+ auto c6 = CreateClip(*c5, &t0(), big_rounded_clip_rect);
+ auto c7 = CreateClip(*c6, &t0(), small_rounded_clip_rect);
TestChunks chunks;
- chunks.AddChunk(t0(), c7.get(), e0());
+ chunks.AddChunk(t0(), *c7, e0());
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c0(), e0()), gfx::Vector2dF(),
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -844,21 +835,21 @@ TEST_F(PaintChunksToCcLayerTest, CombineClipsWithRoundedRects) {
TEST_F(PaintChunksToCcLayerTest, ChunksSamePropertyTreeState) {
auto t1 = CreateTransform(t0(), TransformationMatrix().Scale(2.f));
- auto t2 = CreateTransform(t1, TransformationMatrix().Scale(3.f));
- auto c1 = CreateClip(c0(), t1, FloatRoundedRect(0, 0, 100, 100));
+ auto t2 = CreateTransform(*t1, TransformationMatrix().Scale(3.f));
+ auto c1 = CreateClip(c0(), t1.get(), FloatRoundedRect(0, 0, 100, 100));
TestChunks chunks;
chunks.AddChunk(t0(), c0(), e0());
- chunks.AddChunk(t1.get(), c0(), e0());
- chunks.AddChunk(t1.get(), c0(), e0());
- chunks.AddChunk(t1.get(), c1.get(), e0());
- chunks.AddChunk(t1.get(), c1.get(), e0());
- chunks.AddChunk(t2.get(), c1.get(), e0());
- chunks.AddChunk(t2.get(), c1.get(), e0());
+ chunks.AddChunk(*t1, c0(), e0());
+ chunks.AddChunk(*t1, c0(), e0());
+ chunks.AddChunk(*t1, *c1, e0());
+ chunks.AddChunk(*t1, *c1, e0());
+ chunks.AddChunk(*t2, *c1, e0());
+ chunks.AddChunk(*t2, *c1, e0());
sk_sp<PaintRecord> output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c0(), e0()), gfx::Vector2dF(),
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -881,23 +872,23 @@ TEST_F(PaintChunksToCcLayerTest, ChunksSamePropertyTreeState) {
TEST_F(PaintChunksToCcLayerTest, NoOpForIdentityTransforms) {
auto t1 = CreateTransform(t0(), TransformationMatrix());
- auto t2 = CreateTransform(t1, TransformationMatrix());
- auto t3 = CreateTransform(t2, TransformationMatrix());
- auto c1 = CreateClip(c0(), t2, FloatRoundedRect(0, 0, 100, 100));
- auto c2 = CreateClip(c1, t3, FloatRoundedRect(0, 0, 200, 50));
+ auto t2 = CreateTransform(*t1, TransformationMatrix());
+ auto t3 = CreateTransform(*t2, TransformationMatrix());
+ auto c1 = CreateClip(c0(), t2.get(), FloatRoundedRect(0, 0, 100, 100));
+ auto c2 = CreateClip(*c1, t3.get(), FloatRoundedRect(0, 0, 200, 50));
TestChunks chunks;
chunks.AddChunk(t0(), c0(), e0());
- chunks.AddChunk(t1.get(), c0(), e0());
+ chunks.AddChunk(*t1, c0(), e0());
chunks.AddChunk(t0(), c0(), e0());
- chunks.AddChunk(t1.get(), c0(), e0());
- chunks.AddChunk(t2.get(), c0(), e0());
- chunks.AddChunk(t1.get(), c0(), e0());
- chunks.AddChunk(t1.get(), c2.get(), e0());
+ chunks.AddChunk(*t1, c0(), e0());
+ chunks.AddChunk(*t2, c0(), e0());
+ chunks.AddChunk(*t1, c0(), e0());
+ chunks.AddChunk(*t1, *c2, e0());
auto output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c0(), e0()), gfx::Vector2dF(),
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -916,17 +907,17 @@ TEST_F(PaintChunksToCcLayerTest, NoOpForIdentityTransforms) {
TEST_F(PaintChunksToCcLayerTest, EffectsWithSameTransform) {
auto t1 = CreateTransform(t0(), TransformationMatrix().Scale(2));
- auto e1 = CreateOpacityEffect(e0(), t1, c0(), 0.1f);
- auto e2 = CreateOpacityEffect(e0(), t1, c0(), 0.2f);
+ auto e1 = CreateOpacityEffect(e0(), t1.get(), &c0(), 0.1f);
+ auto e2 = CreateOpacityEffect(e0(), t1.get(), &c0(), 0.2f);
TestChunks chunks;
chunks.AddChunk(t0(), c0(), e0());
- chunks.AddChunk(t1.get(), c0(), e1.get());
- chunks.AddChunk(t1.get(), c0(), e2.get());
+ chunks.AddChunk(*t1, c0(), *e1);
+ chunks.AddChunk(*t1, c0(), *e2);
auto output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c0(), e0()), gfx::Vector2dF(),
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
@@ -945,17 +936,17 @@ TEST_F(PaintChunksToCcLayerTest, EffectsWithSameTransform) {
TEST_F(PaintChunksToCcLayerTest, NestedEffectsWithSameTransform) {
auto t1 = CreateTransform(t0(), TransformationMatrix().Scale(2));
- auto e1 = CreateOpacityEffect(e0(), t1, c0(), 0.1f);
- auto e2 = CreateOpacityEffect(e1, t1, c0(), 0.2f);
+ auto e1 = CreateOpacityEffect(e0(), t1.get(), &c0(), 0.1f);
+ auto e2 = CreateOpacityEffect(*e1, t1.get(), &c0(), 0.2f);
TestChunks chunks;
chunks.AddChunk(t0(), c0(), e0());
- chunks.AddChunk(t1.get(), c0(), e1.get());
- chunks.AddChunk(t1.get(), c0(), e2.get());
+ chunks.AddChunk(*t1, c0(), *e1);
+ chunks.AddChunk(*t1, c0(), *e2);
auto output =
PaintChunksToCcLayer::Convert(
- chunks.chunks, PropertyTreeState(t0(), c0(), e0()), gfx::Vector2dF(),
+ chunks.chunks, PropertyTreeState::Root(), gfx::Vector2dF(),
chunks.items, cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
->ReleaseAsRecord();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc b/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
index 403b74ed641..b2d0209c85e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.cc
@@ -91,7 +91,7 @@ void PropertyTreeManager::SetupRootTransformNode() {
transform_tree.SetFromScreen(kRealRootNodeId, from_screen);
transform_tree.set_needs_update(true);
- transform_node_map_.Set(TransformPaintPropertyNode::Root(),
+ transform_node_map_.Set(&TransformPaintPropertyNode::Root(),
transform_node.id);
root_layer_->SetTransformTreeIndex(transform_node.id);
}
@@ -109,7 +109,7 @@ void PropertyTreeManager::SetupRootClipNode() {
gfx::SizeF(root_layer_->layer_tree_host()->device_viewport_size()));
clip_node.transform_id = kRealRootNodeId;
- clip_node_map_.Set(ClipPaintPropertyNode::Root(), clip_node.id);
+ clip_node_map_.Set(&ClipPaintPropertyNode::Root(), clip_node.id);
root_layer_->SetClipTreeIndex(clip_node.id);
}
@@ -125,7 +125,7 @@ void PropertyTreeManager::SetupRootEffectNode() {
static UniqueObjectId unique_id = NewUniqueObjectId();
effect_node.stable_id =
- CompositorElementIdFromUniqueObjectId(unique_id).ToInternalValue();
+ CompositorElementIdFromUniqueObjectId(unique_id).GetInternalValue();
effect_node.transform_id = kRealRootNodeId;
effect_node.clip_id = kSecondaryRootNodeId;
effect_node.has_render_surface = true;
@@ -133,7 +133,7 @@ void PropertyTreeManager::SetupRootEffectNode() {
current_effect_id_ = effect_node.id;
current_effect_type_ = CcEffectType::kEffect;
- current_effect_ = EffectPaintPropertyNode::Root();
+ current_effect_ = &EffectPaintPropertyNode::Root();
current_clip_ = current_effect_->OutputClip();
}
@@ -146,7 +146,7 @@ void PropertyTreeManager::SetupRootScrollNode() {
DCHECK_EQ(scroll_node.id, kSecondaryRootNodeId);
scroll_node.transform_id = kSecondaryRootNodeId;
- scroll_node_map_.Set(ScrollPaintPropertyNode::Root(), scroll_node.id);
+ scroll_node_map_.Set(&ScrollPaintPropertyNode::Root(), scroll_node.id);
root_layer_->SetScrollTreeIndex(scroll_node.id);
}
@@ -184,6 +184,7 @@ int PropertyTreeManager::EnsureCompositorTransformNode(
if (compositor_element_id) {
property_trees_.element_id_to_transform_node_index[compositor_element_id] =
id;
+ compositor_node.element_id = compositor_element_id;
}
// If this transform is a scroll offset translation, create the associated
@@ -212,6 +213,21 @@ int PropertyTreeManager::EnsureCompositorTransformNode(
return id;
}
+void PropertyTreeManager::EnsureCompositorPageScaleTransformNode(
+ const TransformPaintPropertyNode* node) {
+ int id = EnsureCompositorTransformNode(node);
+ DCHECK(GetTransformTree().Node(id));
+ cc::TransformNode& compositor_node = *GetTransformTree().Node(id);
+
+ // The page scale node is special because its transform matrix is assumed to
+ // be in the post_local matrix by the compositor. There should be no
+ // translation from the origin so we clear the other matrices.
+ DCHECK(node->Origin() == FloatPoint3D());
+ compositor_node.post_local.matrix() = compositor_node.local.matrix();
+ compositor_node.pre_local.matrix().setIdentity();
+ compositor_node.local.matrix().setIdentity();
+}
+
int PropertyTreeManager::EnsureCompositorClipNode(
const ClipPaintPropertyNode* clip_node) {
DCHECK(clip_node);
@@ -263,6 +279,10 @@ void PropertyTreeManager::CreateCompositorScrollNode(
scroll_node->UserScrollableHorizontal();
compositor_node.user_scrollable_vertical =
scroll_node->UserScrollableVertical();
+ compositor_node.scrolls_inner_viewport = scroll_node->ScrollsInnerViewport();
+ compositor_node.scrolls_outer_viewport = scroll_node->ScrollsOuterViewport();
+ compositor_node.max_scroll_offset_affected_by_page_scale =
+ scroll_node->MaxScrollOffsetAffectedByPageScale();
compositor_node.main_thread_scrolling_reasons =
scroll_node->GetMainThreadScrollingReasons();
@@ -305,17 +325,16 @@ void PropertyTreeManager::EmitClipMaskLayer() {
// See PropertyTreeManager::SynthesizeCcEffectsForClipsIfNeeded().
DCHECK_EQ(static_cast<uint64_t>(cc::EffectNode::INVALID_STABLE_ID),
mask_isolation.stable_id);
- mask_isolation.stable_id = mask_isolation_id.ToInternalValue();
+ mask_isolation.stable_id = mask_isolation_id.GetInternalValue();
cc::EffectNode& mask_effect = *GetEffectTree().Node(
GetEffectTree().Insert(cc::EffectNode(), current_effect_id_));
- mask_effect.stable_id = mask_effect_id.ToInternalValue();
+ mask_effect.stable_id = mask_effect_id.GetInternalValue();
mask_effect.clip_id = clip_id;
mask_effect.has_render_surface = true;
mask_effect.blend_mode = SkBlendMode::kDstIn;
- const TransformPaintPropertyNode* clip_space =
- current_clip_->LocalTransformSpace();
+ const auto* clip_space = current_clip_->LocalTransformSpace();
root_layer_->AddChild(mask_layer);
mask_layer->set_property_tree_sequence_number(sequence_number_);
mask_layer->SetTransformTreeIndex(EnsureCompositorTransformNode(clip_space));
@@ -559,7 +578,7 @@ bool PropertyTreeManager::BuildEffectNodesRecursively(
cc::EffectNode& effect_node = *GetEffectTree().Node(
GetEffectTree().Insert(cc::EffectNode(), current_effect_id_));
effect_node.stable_id =
- next_effect->GetCompositorElementId().ToInternalValue();
+ next_effect->GetCompositorElementId().GetInternalValue();
effect_node.clip_id = output_clip_id;
// Every effect is supposed to have render surface enabled for grouping,
// but we can get away without one if the effect is opacity-only and has only
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h b/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h
index 50c8ba8792c..d9299f93fb6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h
@@ -5,10 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_COMPOSITING_PROPERTY_TREE_MANAGER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_COMPOSITING_PROPERTY_TREE_MANAGER_H_
+#include "base/macros.h"
#include "third_party/blink/renderer/platform/graphics/compositor_element_id.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/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/skia/include/core/SkBlendMode.h"
@@ -40,7 +40,6 @@ class PropertyTreeManagerClient {
// Mutates a cc property tree to reflect Blink paint property tree
// state. Intended for use by PaintArtifactCompositor.
class PropertyTreeManager {
- WTF_MAKE_NONCOPYABLE(PropertyTreeManager);
public:
PropertyTreeManager(PropertyTreeManagerClient&,
@@ -99,6 +98,9 @@ class PropertyTreeManager {
int EnsureCompositorScrollNode(
const TransformPaintPropertyNode* scroll_offset_translation);
+ void EnsureCompositorPageScaleTransformNode(
+ const TransformPaintPropertyNode*);
+
// This function is expected to be invoked right before emitting each layer.
// It keeps track of the nesting of clip and effects, output a composited
// effect node whenever an effect is entered, or a non-trivial clip is
@@ -185,6 +187,8 @@ class PropertyTreeManager {
#if DCHECK_IS_ON()
HashSet<const EffectPaintPropertyNode*> effect_nodes_converted_;
#endif
+
+ DISALLOW_COPY_AND_ASSIGN(PropertyTreeManager);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h b/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h
index 4e8166c7f60..30e174d5109 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositing_reasons.h
@@ -124,11 +124,16 @@ class PLATFORM_EXPORT CompositingReason {
k3DTransform | kBackfaceVisibilityHidden | kComboActiveAnimation |
kTransitionProperty | kWillChangeCompositingHint | kBackdropFilter,
- kComboAllDirectReasons =
- kComboAllDirectStyleDeterminedReasons | kVideo | kCanvas | kPlugin |
- kIFrame | kScrollDependentPosition | kOverflowScrollingTouch |
- kOverflowScrollingParent | kOutOfFlowClipping | kVideoOverlay |
- kRootScroller,
+ kComboAllDirectNonStyleDeterminedReasons =
+ kVideo | kCanvas | kPlugin | kIFrame | kOverflowScrollingParent |
+ kOutOfFlowClipping | kVideoOverlay | kRoot | kRootScroller |
+ kScrollDependentPosition | kScrollTimelineTarget,
+
+ kComboAllDirectReasons = kComboAllDirectStyleDeterminedReasons |
+ kComboAllDirectNonStyleDeterminedReasons,
+
+ kComboAllCompositedScrollingDeterminedReasons =
+ kScrollDependentPosition | kOverflowScrollingTouch,
kComboCompositedDescendants =
kTransformWithCompositedDescendants | kIsolateCompositedDescendants |
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositor_animator.h b/chromium/third_party/blink/renderer/platform/graphics/compositor_animator.h
index f23806bfd5c..5c5bbf9c050 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositor_animator.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositor_animator.h
@@ -13,9 +13,12 @@ namespace blink {
class PLATFORM_EXPORT CompositorAnimator : public GarbageCollectedMixin {
public:
+ virtual ~CompositorAnimator() = default;
+
+ virtual int GetScopeId() const = 0;
// Runs the animation frame callback.
- virtual std::unique_ptr<CompositorMutatorOutputState> Mutate(
- const CompositorMutatorInputState&) = 0;
+ virtual std::unique_ptr<AnimationWorkletOutput> Mutate(
+ std::unique_ptr<AnimationWorkletInput>) = 0;
void Trace(blink::Visitor* visitor) override {}
};
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositor_animators_state.h b/chromium/third_party/blink/renderer/platform/graphics/compositor_animators_state.h
index 549a1aefbe3..42e1b7f61b1 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositor_animators_state.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositor_animators_state.h
@@ -9,9 +9,12 @@
namespace blink {
+using AnimationWorkletInput = cc::AnimationWorkletInput;
+using AnimationWorkletOutput = cc::AnimationWorkletOutput;
using CompositorMutatorInputState = cc::MutatorInputState;
using CompositorMutatorOutputState = cc::MutatorOutputState;
+using WorkletAnimationId = cc::WorkletAnimationId;
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.cc b/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.cc
index 271bf44f49c..3d01b478ffa 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.cc
@@ -33,7 +33,9 @@ CompositorElementId PLATFORM_EXPORT CompositorElementIdFromUniqueObjectId(
namespace_id == CompositorElementIdNamespace::kScroll ||
namespace_id == CompositorElementIdNamespace::kEffectFilter ||
namespace_id == CompositorElementIdNamespace::kEffectMask ||
- namespace_id == CompositorElementIdNamespace::kEffectClipPath);
+ namespace_id == CompositorElementIdNamespace::kEffectClipPath ||
+ namespace_id == CompositorElementIdNamespace::kVerticalScrollbar ||
+ namespace_id == CompositorElementIdNamespace::kHorizontalScrollbar);
return CreateCompositorElementId(id, namespace_id);
}
@@ -52,7 +54,7 @@ CompositorElementIdFromUniqueObjectId(UniqueObjectId id) {
CompositorElementIdNamespace NamespaceFromCompositorElementId(
CompositorElementId element_id) {
return static_cast<CompositorElementIdNamespace>(
- element_id.ToInternalValue() %
+ element_id.GetInternalValue() %
static_cast<uint64_t>(
CompositorElementIdNamespace::kMaxRepresentableNamespaceId));
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.h b/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.h
index d3c2d94c15b..34532cac3d4 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id.h
@@ -13,7 +13,7 @@
namespace blink {
-const int kCompositorNamespaceBitCount = 3;
+const int kCompositorNamespaceBitCount = 4;
enum class CompositorElementIdNamespace {
kPrimary,
@@ -23,6 +23,8 @@ enum class CompositorElementIdNamespace {
kEffectFilter,
kEffectMask,
kEffectClipPath,
+ kVerticalScrollbar,
+ kHorizontalScrollbar,
// A sentinel to indicate the maximum representable namespace id
// (the maximum is one less than this value).
kMaxRepresentableNamespaceId = 1 << kCompositorNamespaceBitCount
@@ -55,7 +57,7 @@ CompositorElementId PLATFORM_EXPORT CompositorElementIdFromDOMNodeId(DOMNodeId);
// Blink's hash functions with Blink specific data structures.
struct CompositorElementIdHash {
static unsigned GetHash(const CompositorElementId& key) {
- return WTF::HashInt(static_cast<cc::ElementIdType>(key.ToInternalValue()));
+ return WTF::HashInt(static_cast<cc::ElementIdType>(key.GetInternalValue()));
}
static bool Equal(const CompositorElementId& a,
const CompositorElementId& b) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id_test.cc b/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id_test.cc
index 7cd8ca3c557..c3aeb9d4c9e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositor_element_id_test.cc
@@ -11,7 +11,7 @@ namespace blink {
class CompositorElementIdTest : public testing::Test {};
uint64_t IdFromCompositorElementId(CompositorElementId element_id) {
- return element_id.ToInternalValue() >> kCompositorNamespaceBitCount;
+ return element_id.GetInternalValue() >> kCompositorNamespaceBitCount;
}
TEST_F(CompositorElementIdTest, EncodeDecode) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.cc b/chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.cc
index 3689a83b474..f3706413a90 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.cc
@@ -113,25 +113,6 @@ bool CompositorFilterOperations::operator==(
filter_operations_ == o.filter_operations_;
}
-bool CompositorFilterOperations::EqualsIgnoringReferenceFilters(
- const CompositorFilterOperations& o) const {
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
- size_t size = filter_operations_.size();
- if (size != o.filter_operations_.size() || reference_box_ != o.reference_box_)
- return false;
- for (size_t i = 0; i < size; ++i) {
- const auto& operation = filter_operations_.at(i);
- if (operation.type() == cc::FilterOperation::REFERENCE) {
- if (o.filter_operations_.at(i).type() != cc::FilterOperation::REFERENCE)
- return false;
- continue;
- }
- if (operation != o.filter_operations_.at(i))
- return false;
- }
- return true;
-}
-
String CompositorFilterOperations::ToString() const {
return filter_operations_.ToString().c_str();
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.h b/chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.h
index e26aff40aaf..bfb58a14b10 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositor_filter_operations.h
@@ -57,8 +57,6 @@ class PLATFORM_EXPORT CompositorFilterOperations {
return !(*this == o);
}
- bool EqualsIgnoringReferenceFilters(const CompositorFilterOperations&) const;
-
String ToString() const;
private:
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_client.h b/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_client.h
index 77e0819d92a..827aba8df8d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_client.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_client.h
@@ -18,7 +18,7 @@ class PLATFORM_EXPORT CompositorMutatorClient : public cc::LayerTreeMutator {
explicit CompositorMutatorClient(std::unique_ptr<CompositorMutatorImpl>);
~CompositorMutatorClient() override;
- void SetMutationUpdate(std::unique_ptr<cc::MutatorOutputState>);
+ virtual void SetMutationUpdate(std::unique_ptr<cc::MutatorOutputState>);
// cc::LayerTreeMutator
void SetClient(cc::LayerTreeMutatorClient*) override;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_impl.cc b/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_impl.cc
index 1e52422195c..0cee0139e45 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_impl.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/platform/graphics/compositor_mutator_impl.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/graphics/compositor_animator.h"
#include "third_party/blink/renderer/platform/graphics/compositor_mutator_client.h"
@@ -39,67 +40,81 @@ std::unique_ptr<CompositorMutatorClient> CompositorMutatorImpl::CreateClient(
}
void CompositorMutatorImpl::Mutate(
- std::unique_ptr<CompositorMutatorInputState> state) {
+ std::unique_ptr<CompositorMutatorInputState> mutator_input) {
TRACE_EVENT0("cc", "CompositorMutatorImpl::mutate");
DCHECK(mutator_queue_->BelongsToCurrentThread());
- if (animators_.IsEmpty())
+ if (animator_map_.IsEmpty())
return;
- DCHECK(!animator_queue_->BelongsToCurrentThread());
DCHECK(client_);
- using Outputs = Vector<std::unique_ptr<CompositorMutatorOutputState>>;
- Outputs outputs;
- outputs.ReserveInitialCapacity(animators_.size());
-
- WaitableEvent done;
- PostCrossThreadTask(
- *animator_queue_, FROM_HERE,
- CrossThreadBind(
- [](const CompositorAnimators* animators,
- std::unique_ptr<CompositorMutatorInputState> state,
- std::unique_ptr<AutoSignal> completion, Outputs* output) {
- for (CompositorAnimator* animator : *animators)
- output->push_back(animator->Mutate(*state));
- },
- CrossThreadUnretained(&animators_), WTF::Passed(std::move(state)),
- WTF::Passed(std::make_unique<AutoSignal>(&done)),
- CrossThreadUnretained(&outputs)));
- // At some point the AutoSignal(&done) gets destroyed and unblocks us.
- done.Wait();
+ Vector<std::unique_ptr<CompositorMutatorOutputState>> outputs(
+ animator_map_.size());
+ Vector<WaitableEvent> done_events(animator_map_.size());
+
+ int index = 0;
+ for (auto& pair : animator_map_) {
+ CompositorAnimator* animator = pair.key;
+ scoped_refptr<base::SingleThreadTaskRunner> animator_queue = pair.value;
+
+ std::unique_ptr<AnimationWorkletInput> animator_input =
+ mutator_input->TakeWorkletState(animator->GetScopeId());
+
+ DCHECK(!animator_queue->BelongsToCurrentThread());
+ std::unique_ptr<AutoSignal> done =
+ std::make_unique<AutoSignal>(&done_events[index]);
+ std::unique_ptr<CompositorMutatorOutputState>& output = outputs[index];
+
+ if (animator_input) {
+ PostCrossThreadTask(
+ *animator_queue, FROM_HERE,
+ CrossThreadBind(
+ [](CompositorAnimator* animator,
+ std::unique_ptr<AnimationWorkletInput> input,
+ std::unique_ptr<AutoSignal> completion,
+ std::unique_ptr<CompositorMutatorOutputState>* output) {
+ *output = animator->Mutate(std::move(input));
+ },
+ WrapCrossThreadWeakPersistent(animator),
+ WTF::Passed(std::move(animator_input)),
+ WTF::Passed(std::move(done)), CrossThreadUnretained(&output)));
+ }
+ index++;
+ }
+
+ for (WaitableEvent& event : done_events) {
+ event.Wait();
+ }
for (auto& output : outputs) {
+ // Animator that has no input does not produce any output.
+ if (!output)
+ continue;
client_->SetMutationUpdate(std::move(output));
}
}
void CompositorMutatorImpl::RegisterCompositorAnimator(
CrossThreadPersistent<CompositorAnimator> animator,
- scoped_refptr<base::SingleThreadTaskRunner> queue) {
+ scoped_refptr<base::SingleThreadTaskRunner> animator_runner) {
TRACE_EVENT0("cc", "CompositorMutatorImpl::RegisterCompositorAnimator");
DCHECK(animator);
DCHECK(mutator_queue_->BelongsToCurrentThread());
- if (animators_.IsEmpty()) {
- animator_queue_ = std::move(queue);
- } else {
- DCHECK_EQ(queue, animator_queue_);
- }
- animators_.insert(animator);
+ animator_map_.insert(animator, animator_runner);
}
void CompositorMutatorImpl::UnregisterCompositorAnimator(
CrossThreadPersistent<CompositorAnimator> animator) {
TRACE_EVENT0("cc", "CompositorMutatorImpl::UnregisterCompositorAnimator");
-
DCHECK(animator);
DCHECK(mutator_queue_->BelongsToCurrentThread());
- animators_.erase(animator);
+ animator_map_.erase(animator);
}
bool CompositorMutatorImpl::HasAnimators() {
- return !animators_.IsEmpty();
+ return !animator_map_.IsEmpty();
}
CompositorMutatorImpl::AutoSignal::AutoSignal(WaitableEvent* event)
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_impl.h b/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_impl.h
index fccc38928e4..3c589b49009 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_impl.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_impl.h
@@ -60,11 +60,11 @@ class PLATFORM_EXPORT CompositorMutatorImpl final : public CompositorMutator {
void SetClient(CompositorMutatorClient* client) { client_ = client; }
private:
- using CompositorAnimators =
- HashSet<CrossThreadPersistent<CompositorAnimator>>;
+ using CompositorAnimatorToTaskRunnerMap =
+ HashMap<CrossThreadPersistent<CompositorAnimator>,
+ scoped_refptr<base::SingleThreadTaskRunner>>;
class AutoSignal {
- WTF_MAKE_NONCOPYABLE(AutoSignal);
public:
explicit AutoSignal(WaitableEvent*);
@@ -72,11 +72,13 @@ class PLATFORM_EXPORT CompositorMutatorImpl final : public CompositorMutator {
private:
WaitableEvent* event_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutoSignal);
};
// The AnimationWorkletProxyClientImpls are also owned by the WorkerClients
// dictionary.
- CompositorAnimators animators_;
+ CompositorAnimatorToTaskRunnerMap animator_map_;
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() {
return mutator_queue_;
@@ -84,9 +86,6 @@ class PLATFORM_EXPORT CompositorMutatorImpl final : public CompositorMutator {
scoped_refptr<base::SingleThreadTaskRunner> mutator_queue_;
- // Currently we only support a single queue for animators.
- scoped_refptr<base::SingleThreadTaskRunner> animator_queue_;
-
// The CompositorMutatorClient owns (std::unique_ptr) us, so this pointer is
// valid as long as this class exists.
CompositorMutatorClient* client_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_impl_test.cc b/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_impl_test.cc
new file mode 100644
index 00000000000..b7b432051b6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/compositor_mutator_impl_test.cc
@@ -0,0 +1,290 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/graphics/compositor_mutator_impl.h"
+
+#include "base/single_thread_task_runner.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_thread.h"
+#include "third_party/blink/public/platform/web_thread_type.h"
+#include "third_party/blink/renderer/platform/graphics/compositor_animator.h"
+#include "third_party/blink/renderer/platform/graphics/compositor_mutator_client.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
+
+#include <memory>
+
+using ::testing::_;
+using ::testing::Mock;
+using ::testing::StrictMock;
+using ::testing::Return;
+using ::testing::Truly;
+
+// This test uses actual threads since mutator logic requires it. This means we
+// have dependency on Blink platform to create threads.
+
+namespace blink {
+namespace {
+
+std::unique_ptr<WebThread> CreateThread(const char* name) {
+ return Platform::Current()->CreateThread(
+ WebThreadCreationParams(WebThreadType::kTestThread)
+ .SetThreadNameForTest(name));
+}
+
+class MockCompositorAnimator
+ : public GarbageCollectedFinalized<MockCompositorAnimator>,
+ public CompositorAnimator {
+ USING_GARBAGE_COLLECTED_MIXIN(MockCompositorAnimator);
+
+ public:
+ MockCompositorAnimator(
+ scoped_refptr<base::SingleThreadTaskRunner> expected_runner)
+ : expected_runner_(expected_runner) {}
+
+ ~MockCompositorAnimator() override {}
+
+ std::unique_ptr<AnimationWorkletOutput> Mutate(
+ std::unique_ptr<AnimationWorkletInput> input) override {
+ return std::unique_ptr<AnimationWorkletOutput>(MutateRef(*input));
+ }
+
+ MOCK_CONST_METHOD0(GetScopeId, int());
+ MOCK_METHOD1(MutateRef,
+ AnimationWorkletOutput*(const AnimationWorkletInput&));
+
+ scoped_refptr<base::SingleThreadTaskRunner> expected_runner_;
+};
+
+class MockCompositorMutatorClient : public CompositorMutatorClient {
+ public:
+ MockCompositorMutatorClient(std::unique_ptr<CompositorMutatorImpl> mutator)
+ : CompositorMutatorClient(std::move(mutator)) {}
+ ~MockCompositorMutatorClient() override {}
+ // gmock cannot mock methods with move-only args so we forward it to ourself.
+ void SetMutationUpdate(
+ std::unique_ptr<cc::MutatorOutputState> output_state) override {
+ SetMutationUpdateRef(output_state.get());
+ }
+
+ MOCK_METHOD1(SetMutationUpdateRef,
+ void(cc::MutatorOutputState* output_state));
+};
+
+class CompositorMutatorImplTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ auto mutator = std::make_unique<CompositorMutatorImpl>();
+ mutator_ = mutator.get();
+ client_ =
+ std::make_unique<::testing::StrictMock<MockCompositorMutatorClient>>(
+ std::move(mutator));
+ }
+
+ void TearDown() override { mutator_ = nullptr; }
+
+ std::unique_ptr<::testing::StrictMock<MockCompositorMutatorClient>> client_;
+ CompositorMutatorImpl* mutator_;
+};
+
+std::unique_ptr<CompositorMutatorInputState> CreateTestMutatorInput() {
+ AnimationWorkletInput::AddAndUpdateState state1{
+ {11, 1}, "test1", 5000, nullptr};
+
+ AnimationWorkletInput::AddAndUpdateState state2{
+ {22, 2}, "test2", 5000, nullptr};
+
+ auto input = std::make_unique<CompositorMutatorInputState>();
+ input->Add(std::move(state1));
+ input->Add(std::move(state2));
+
+ return input;
+}
+
+bool OnlyIncludesAnimation1(const AnimationWorkletInput& in) {
+ return in.added_and_updated_animations.size() == 1 &&
+ in.added_and_updated_animations[0].worklet_animation_id.animation_id ==
+ 1;
+}
+
+TEST_F(CompositorMutatorImplTest,
+ RegisteredAnimatorShouldOnlyReceiveInputForItself) {
+ std::unique_ptr<WebThread> first_thread = CreateThread("FirstThread");
+ MockCompositorAnimator* first_animator =
+ new ::testing::StrictMock<MockCompositorAnimator>(
+ first_thread->GetTaskRunner());
+
+ mutator_->RegisterCompositorAnimator(first_animator,
+ first_thread->GetTaskRunner());
+
+ EXPECT_CALL(*first_animator, GetScopeId()).Times(1).WillOnce(Return(11));
+ EXPECT_CALL(*first_animator, MutateRef(Truly(OnlyIncludesAnimation1)))
+ .Times(1)
+ .WillOnce(Return(new AnimationWorkletOutput()));
+ EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(1);
+
+ mutator_->Mutate(CreateTestMutatorInput());
+}
+
+TEST_F(CompositorMutatorImplTest,
+ RegisteredAnimatorShouldNotBeMutatedWhenNoInput) {
+ std::unique_ptr<WebThread> first_thread = CreateThread("FirstThread");
+ MockCompositorAnimator* first_animator =
+ new ::testing::StrictMock<MockCompositorAnimator>(
+ first_thread->GetTaskRunner());
+
+ mutator_->RegisterCompositorAnimator(first_animator,
+ first_thread->GetTaskRunner());
+
+ EXPECT_CALL(*first_animator, GetScopeId()).Times(1).WillOnce(Return(11));
+ EXPECT_CALL(*first_animator, MutateRef(_)).Times(0);
+ EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(0);
+
+ AnimationWorkletInput::AddAndUpdateState state2{
+ {22, 2}, "test2", 5000, nullptr};
+
+ auto input = std::make_unique<CompositorMutatorInputState>();
+ input->Add(std::move(state2));
+
+ mutator_->Mutate(std::move(input));
+}
+
+TEST_F(CompositorMutatorImplTest,
+ MutationUpdateIsNotInvokedWithNoRegisteredAnimators) {
+ EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(0);
+ std::unique_ptr<CompositorMutatorInputState> input =
+ std::make_unique<CompositorMutatorInputState>();
+ mutator_->Mutate(std::move(input));
+}
+
+TEST_F(CompositorMutatorImplTest, MutationUpdateIsNotInvokedWithNullOutput) {
+ // Create a thread to run animator tasks.
+ std::unique_ptr<WebThread> first_thread =
+ CreateThread("FirstAnimationThread");
+ MockCompositorAnimator* first_animator =
+ new ::testing::StrictMock<MockCompositorAnimator>(
+ first_thread->GetTaskRunner());
+
+ mutator_->RegisterCompositorAnimator(first_animator,
+ first_thread->GetTaskRunner());
+ EXPECT_CALL(*first_animator, GetScopeId()).Times(1).WillOnce(Return(11));
+ EXPECT_CALL(*first_animator, MutateRef(_)).Times(1).WillOnce(Return(nullptr));
+ EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(0);
+ mutator_->Mutate(CreateTestMutatorInput());
+}
+
+TEST_F(CompositorMutatorImplTest,
+ MutationUpdateIsInvokedCorrectlyWithSingleRegisteredAnimator) {
+ // Create a thread to run animator tasks.
+ std::unique_ptr<WebThread> first_thread =
+ CreateThread("FirstAnimationThread");
+ MockCompositorAnimator* first_animator =
+ new ::testing::StrictMock<MockCompositorAnimator>(
+ first_thread->GetTaskRunner());
+
+ mutator_->RegisterCompositorAnimator(first_animator,
+ first_thread->GetTaskRunner());
+ EXPECT_CALL(*first_animator, GetScopeId()).Times(1).WillOnce(Return(11));
+ EXPECT_CALL(*first_animator, MutateRef(_))
+ .Times(1)
+ .WillOnce(Return(new AnimationWorkletOutput()));
+ EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(1);
+ mutator_->Mutate(CreateTestMutatorInput());
+
+ // The above call blocks on animator threads running their tasks so we can
+ // safely verify here.
+ Mock::VerifyAndClearExpectations(client_.get());
+
+ // Ensure animator is not invoked after unregistration.
+ EXPECT_CALL(*first_animator, MutateRef(_)).Times(0);
+ EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(0);
+ mutator_->UnregisterCompositorAnimator(first_animator);
+
+ mutator_->Mutate(CreateTestMutatorInput());
+ Mock::VerifyAndClearExpectations(client_.get());
+}
+
+TEST_F(CompositorMutatorImplTest,
+ MutationUpdateInvokedCorrectlyWithTwoRegisteredAnimatorsOnSameThread) {
+ std::unique_ptr<WebThread> first_thread =
+ CreateThread("FirstAnimationThread");
+ MockCompositorAnimator* first_animator =
+ new ::testing::StrictMock<MockCompositorAnimator>(
+ first_thread->GetTaskRunner());
+ MockCompositorAnimator* second_animator =
+ new ::testing::StrictMock<MockCompositorAnimator>(
+ first_thread->GetTaskRunner());
+
+ mutator_->RegisterCompositorAnimator(first_animator,
+ first_thread->GetTaskRunner());
+ mutator_->RegisterCompositorAnimator(second_animator,
+ first_thread->GetTaskRunner());
+
+ EXPECT_CALL(*first_animator, GetScopeId()).Times(1).WillOnce(Return(11));
+ EXPECT_CALL(*first_animator, MutateRef(_))
+ .Times(1)
+ .WillOnce(Return(new AnimationWorkletOutput()));
+ EXPECT_CALL(*second_animator, GetScopeId()).Times(1).WillOnce(Return(22));
+ EXPECT_CALL(*second_animator, MutateRef(_))
+ .Times(1)
+ .WillOnce(Return(new AnimationWorkletOutput()));
+
+ EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(2);
+ mutator_->Mutate(CreateTestMutatorInput());
+}
+
+TEST_F(
+ CompositorMutatorImplTest,
+ MutationUpdateInvokedCorrectlyWithTwoRegisteredAnimatorsOnDifferentThreads) {
+ std::unique_ptr<WebThread> first_thread =
+ CreateThread("FirstAnimationThread");
+ MockCompositorAnimator* first_animator =
+ new ::testing::StrictMock<MockCompositorAnimator>(
+ first_thread->GetTaskRunner());
+
+ std::unique_ptr<WebThread> second_thread =
+ CreateThread("SecondAnimationThread");
+ MockCompositorAnimator* second_animator =
+ new ::testing::StrictMock<MockCompositorAnimator>(
+ second_thread->GetTaskRunner());
+
+ mutator_->RegisterCompositorAnimator(first_animator,
+ first_thread->GetTaskRunner());
+ mutator_->RegisterCompositorAnimator(second_animator,
+ second_thread->GetTaskRunner());
+
+ EXPECT_CALL(*first_animator, GetScopeId()).Times(1).WillOnce(Return(11));
+ EXPECT_CALL(*first_animator, MutateRef(_))
+ .Times(1)
+ .WillOnce(Return(new AnimationWorkletOutput()));
+ EXPECT_CALL(*second_animator, GetScopeId()).Times(1).WillOnce(Return(22));
+ EXPECT_CALL(*second_animator, MutateRef(_))
+ .Times(1)
+ .WillOnce(Return(new AnimationWorkletOutput()));
+ EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(2);
+ mutator_->Mutate(CreateTestMutatorInput());
+
+ // The above call blocks on animator threads running their tasks so we can
+ // safely verify here.
+ Mock::VerifyAndClearExpectations(client_.get());
+
+ // Ensure animator is not invoked after unregistration.
+ mutator_->UnregisterCompositorAnimator(first_animator);
+
+ EXPECT_CALL(*first_animator, GetScopeId()).Times(0);
+ EXPECT_CALL(*first_animator, MutateRef(_)).Times(0);
+ EXPECT_CALL(*second_animator, GetScopeId()).Times(1).WillOnce(Return(22));
+ EXPECT_CALL(*second_animator, MutateRef(_))
+ .Times(1)
+ .WillOnce(Return(new AnimationWorkletOutput()));
+ EXPECT_CALL(*client_, SetMutationUpdateRef(_)).Times(1);
+ mutator_->Mutate(CreateTestMutatorInput());
+ Mock::VerifyAndClearExpectations(client_.get());
+}
+
+} // namespace
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.cc b/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.cc
index ef305ab3554..984f1b1544a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.cc
@@ -6,6 +6,8 @@
#include <algorithm>
#include <memory>
+
+#include "base/macros.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
#include "third_party/blink/renderer/platform/wtf/container_annotations.h"
@@ -17,7 +19,6 @@ namespace blink {
static const unsigned kDefaultInitialBufferSize = 32;
class ContiguousContainerBase::Buffer {
- WTF_MAKE_NONCOPYABLE(Buffer);
USING_FAST_MALLOC(Buffer);
public:
@@ -60,6 +61,8 @@ class ContiguousContainerBase::Buffer {
char* begin_;
char* end_;
size_t capacity_;
+
+ DISALLOW_COPY_AND_ASSIGN(Buffer);
};
ContiguousContainerBase::ContiguousContainerBase(size_t max_object_size)
diff --git a/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.h b/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.h
index 6ad356600ac..d551da78b00 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/contiguous_container.h
@@ -9,12 +9,13 @@
#include <iterator>
#include <memory>
#include <utility>
+
#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/alignment.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/compiler.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/type_traits.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -40,7 +41,6 @@ namespace blink {
class PLATFORM_EXPORT ContiguousContainerBase {
DISALLOW_NEW();
- WTF_MAKE_NONCOPYABLE(ContiguousContainerBase);
protected:
explicit ContiguousContainerBase(size_t max_object_size);
@@ -76,6 +76,8 @@ class PLATFORM_EXPORT ContiguousContainerBase {
Vector<std::unique_ptr<Buffer>> buffers_;
unsigned end_index_;
size_t max_object_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(ContiguousContainerBase);
};
// For most cases, no alignment stricter than pointer alignment is required. If
diff --git a/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.cc b/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.cc
index 2f481cb7421..45501625ff7 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.cc
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
namespace blink {
@@ -42,7 +43,7 @@ CrossfadeGeneratedImage::CrossfadeGeneratedImage(
percentage_(percentage),
crossfade_size_(crossfade_size) {}
-void CrossfadeGeneratedImage::DrawCrossfade(PaintCanvas* canvas,
+void CrossfadeGeneratedImage::DrawCrossfade(cc::PaintCanvas* canvas,
const PaintFlags& flags,
ImageClampingMode clamp_mode,
ImageDecodingMode decode_mode) {
@@ -75,7 +76,7 @@ void CrossfadeGeneratedImage::DrawCrossfade(PaintCanvas* canvas,
kDoNotRespectImageOrientation, clamp_mode, decode_mode);
}
-void CrossfadeGeneratedImage::Draw(PaintCanvas* canvas,
+void CrossfadeGeneratedImage::Draw(cc::PaintCanvas* canvas,
const PaintFlags& flags,
const FloatRect& dst_rect,
const FloatRect& src_rect,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.h b/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.h
index 4fc129564ab..53bad76b190 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/crossfade_generated_image.h
@@ -53,8 +53,8 @@ class PLATFORM_EXPORT CrossfadeGeneratedImage final : public GeneratedImage {
IntSize Size() const override { return FlooredIntSize(crossfade_size_); }
protected:
- void Draw(PaintCanvas*,
- const PaintFlags&,
+ void Draw(cc::PaintCanvas*,
+ const cc::PaintFlags&,
const FloatRect&,
const FloatRect&,
RespectImageOrientationEnum,
@@ -69,8 +69,8 @@ class PLATFORM_EXPORT CrossfadeGeneratedImage final : public GeneratedImage {
const FloatSize&);
private:
- void DrawCrossfade(PaintCanvas*,
- const PaintFlags&,
+ void DrawCrossfade(cc::PaintCanvas*,
+ const cc::PaintFlags&,
ImageClampingMode,
ImageDecodingMode);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc b/chromium/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc
index 3a8baa8ce3f..3af4ecede7a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc
@@ -44,11 +44,12 @@ DecodingImageGenerator::CreateAsSkImageGenerator(sk_sp<SkData> data) {
scoped_refptr<SegmentReader> segment_reader =
SegmentReader::CreateFromSkData(std::move(data));
// We just need the size of the image, so we have to temporarily create an
- // ImageDecoder. Since we only need the size, the premul and gamma settings
- // don't really matter.
+ // ImageDecoder. Since we only need the size, the premul, high bit depth and
+ // gamma settings don't really matter.
+ const bool data_complete = true;
std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
- segment_reader, true, ImageDecoder::kAlphaPremultiplied,
- ColorBehavior::TransformToSRGB());
+ segment_reader, data_complete, ImageDecoder::kAlphaPremultiplied,
+ ImageDecoder::kDefaultBitDepth, ColorBehavior::Ignore());
if (!decoder || !decoder->IsSizeAvailable())
return nullptr;
@@ -159,10 +160,7 @@ bool DecodingImageGenerator::GetPixels(const SkImageInfo& dst_info,
TRACE_EVENT0("blink", "DecodingImageGenerator::getPixels - apply xform");
SkPixmap src(decode_info, pixels, row_bytes);
- // kIgnore ensures that we perform the premultiply (if necessary) in the dst
- // space.
- const bool converted = src.readPixels(dst_info, pixels, row_bytes, 0, 0,
- SkTransferFunctionBehavior::kIgnore);
+ const bool converted = src.readPixels(dst_info, pixels, row_bytes);
DCHECK(converted);
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/decoding_image_generator.h b/chromium/third_party/blink/renderer/platform/graphics/decoding_image_generator.h
index 1058d2c61d1..3a0b8eedcd7 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/decoding_image_generator.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/decoding_image_generator.h
@@ -26,12 +26,12 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_DECODING_IMAGE_GENERATOR_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_DECODING_IMAGE_GENERATOR_H_
+#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_image.h"
#include "third_party/blink/renderer/platform/image-decoders/segment_reader.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/skia/include/core/SkImageInfo.h"
class SkData;
@@ -46,7 +46,6 @@ class ImageFrameGenerator;
class PLATFORM_EXPORT DecodingImageGenerator final
: public PaintImageGenerator {
USING_FAST_MALLOC(DecodingImageGenerator);
- WTF_MAKE_NONCOPYABLE(DecodingImageGenerator);
public:
// Aside from tests, this is used to create a decoder from SkData in Skia
@@ -95,6 +94,8 @@ class PLATFORM_EXPORT DecodingImageGenerator final
const bool all_data_received_;
bool can_yuv_decode_;
const PaintImage::ContentId complete_frame_content_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(DecodingImageGenerator);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.cc b/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.cc
index b500aea830d..dd920efe545 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.cc
@@ -28,6 +28,7 @@
#include <memory>
#include <utility>
+#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/platform/graphics/decoding_image_generator.h"
#include "third_party/blink/renderer/platform/graphics/image_decoding_store.h"
@@ -42,7 +43,6 @@ namespace blink {
struct DeferredFrameData {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
- WTF_MAKE_NONCOPYABLE(DeferredFrameData);
public:
DeferredFrameData()
@@ -52,6 +52,9 @@ struct DeferredFrameData {
ImageOrientation orientation_;
TimeDelta duration_;
bool is_received_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DeferredFrameData);
};
std::unique_ptr<DeferredImageDecoder> DeferredImageDecoder::Create(
@@ -60,7 +63,8 @@ std::unique_ptr<DeferredImageDecoder> DeferredImageDecoder::Create(
ImageDecoder::AlphaOption alpha_option,
const ColorBehavior& color_behavior) {
std::unique_ptr<ImageDecoder> metadata_decoder =
- ImageDecoder::Create(data, data_complete, alpha_option, color_behavior);
+ ImageDecoder::Create(data, data_complete, alpha_option,
+ ImageDecoder::kDefaultBitDepth, color_behavior);
if (!metadata_decoder)
return nullptr;
@@ -170,12 +174,11 @@ void DeferredImageDecoder::SetDataInternal(scoped_refptr<SharedBuffer> data,
if (!rw_buffer_)
rw_buffer_ = std::make_unique<SkRWBuffer>(data->size());
- const char* segment = nullptr;
- for (size_t length = data->GetSomeData(segment, rw_buffer_->size()); length;
- length = data->GetSomeData(segment, rw_buffer_->size())) {
- DCHECK_GE(data->size(), rw_buffer_->size() + length);
- const size_t remaining = data->size() - rw_buffer_->size() - length;
- rw_buffer_->append(segment, length, remaining);
+ for (auto it = data->GetIteratorAt(rw_buffer_->size()); it != data->cend();
+ ++it) {
+ DCHECK_GE(data->size(), rw_buffer_->size() + it->size());
+ const size_t remaining = data->size() - rw_buffer_->size() - it->size();
+ rw_buffer_->append(it->data(), it->size(), remaining);
}
}
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.h b/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.h
index 552f47248c1..225c5268c7e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder.h
@@ -27,6 +27,8 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_DEFERRED_IMAGE_DECODER_H_
#include <memory>
+
+#include "base/macros.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_image.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
@@ -45,7 +47,6 @@ class SharedBuffer;
struct DeferredFrameData;
class PLATFORM_EXPORT DeferredImageDecoder final {
- WTF_MAKE_NONCOPYABLE(DeferredImageDecoder);
USING_FAST_MALLOC(DeferredImageDecoder);
public:
@@ -112,6 +113,8 @@ class PLATFORM_EXPORT DeferredImageDecoder final {
// Caches frame state information.
Vector<DeferredFrameData> frame_data_;
scoped_refptr<ImageFrameGenerator> frame_generator_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeferredImageDecoder);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test.cc b/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test.cc
index 6cde411d473..a65acf537fe 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test.cc
@@ -167,7 +167,7 @@ TEST_F(DeferredImageDecoderTest, drawIntoPaintRecord) {
EXPECT_EQ(1, image.height());
PaintRecorder recorder;
- PaintCanvas* temp_canvas = recorder.beginRecording(100, 100);
+ cc::PaintCanvas* temp_canvas = recorder.beginRecording(100, 100);
temp_canvas->drawImage(image, 0, 0);
sk_sp<PaintRecord> record = recorder.finishRecordingAsPicture();
EXPECT_EQ(0, decode_request_count_);
@@ -184,7 +184,7 @@ TEST_F(DeferredImageDecoderTest, drawIntoPaintRecordProgressive) {
// Received only half the file.
lazy_decoder_->SetData(partial_data, false);
PaintRecorder recorder;
- PaintCanvas* temp_canvas = recorder.beginRecording(100, 100);
+ cc::PaintCanvas* temp_canvas = recorder.beginRecording(100, 100);
PaintImage image =
CreatePaintImageAtIndex(0, PaintImage::CompletionState::PARTIALLY_DONE);
temp_canvas->drawImage(image, 0, 0);
@@ -200,7 +200,7 @@ TEST_F(DeferredImageDecoderTest, drawIntoPaintRecordProgressive) {
EXPECT_EQ(SkColorSetARGB(255, 255, 255, 255), bitmap_.getColor(0, 0));
}
-static void RasterizeMain(PaintCanvas* canvas, sk_sp<PaintRecord> record) {
+static void RasterizeMain(cc::PaintCanvas* canvas, sk_sp<PaintRecord> record) {
canvas->drawPicture(record);
}
@@ -218,7 +218,7 @@ TEST_F(DeferredImageDecoderTest, MAYBE_decodeOnOtherThread) {
EXPECT_EQ(1, image.height());
PaintRecorder recorder;
- PaintCanvas* temp_canvas = recorder.beginRecording(100, 100);
+ cc::PaintCanvas* temp_canvas = recorder.beginRecording(100, 100);
temp_canvas->drawImage(image, 0, 0);
sk_sp<PaintRecord> record = recorder.finishRecordingAsPicture();
EXPECT_EQ(0, decode_request_count_);
@@ -313,7 +313,7 @@ TEST_F(DeferredImageDecoderTest, decodedSize) {
// The following code should not fail any assert.
PaintRecorder recorder;
- PaintCanvas* temp_canvas = recorder.beginRecording(100, 100);
+ cc::PaintCanvas* temp_canvas = recorder.beginRecording(100, 100);
temp_canvas->drawImage(image, 0, 0);
sk_sp<PaintRecord> record = recorder.finishRecordingAsPicture();
EXPECT_EQ(0, decode_request_count_);
@@ -379,8 +379,8 @@ TEST_F(DeferredImageDecoderTest, data) {
lazy_decoder_->SetData(original_buffer, false);
scoped_refptr<SharedBuffer> new_buffer = lazy_decoder_->Data();
EXPECT_EQ(original_buffer->size(), new_buffer->size());
- const Vector<char> original_data = original_buffer->Copy();
- const Vector<char> new_data = new_buffer->Copy();
+ const Vector<char> original_data = original_buffer->CopyAs<Vector<char>>();
+ const Vector<char> new_data = new_buffer->CopyAs<Vector<char>>();
EXPECT_EQ(0, std::memcmp(original_data.data(), new_data.data(),
new_buffer->size()));
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test_wo_platform.cc b/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test_wo_platform.cc
index b649be2fcbe..d689fdf7f7b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test_wo_platform.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/deferred_image_decoder_test_wo_platform.cc
@@ -43,7 +43,7 @@ sk_sp<SkImage> CreateFrameAtIndex(DeferredImageDecoder* decoder, size_t index) {
static void MixImages(const char* file_name,
size_t bytes_for_first_frame,
size_t later_frame) {
- const Vector<char> file = ReadFile(file_name)->Copy();
+ const Vector<char> file = ReadFile(file_name)->CopyAs<Vector<char>>();
scoped_refptr<SharedBuffer> partial_file =
SharedBuffer::Create(file.data(), bytes_for_first_frame);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/draw_looper_builder.h b/chromium/third_party/blink/renderer/platform/graphics/draw_looper_builder.h
index 7d532552348..5f14c5215c3 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/draw_looper_builder.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/draw_looper_builder.h
@@ -32,9 +32,10 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_DRAW_LOOPER_BUILDER_H_
#include <memory>
+
+#include "base/macros.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/effects/SkLayerDrawLooper.h"
@@ -46,9 +47,6 @@ class Color;
class FloatSize;
class PLATFORM_EXPORT DrawLooperBuilder final {
- // Implementing the copy constructor properly would require writing code to
- // copy the underlying SkLayerDrawLooper::Builder.
- WTF_MAKE_NONCOPYABLE(DrawLooperBuilder);
STACK_ALLOCATED();
public:
@@ -74,6 +72,10 @@ class PLATFORM_EXPORT DrawLooperBuilder final {
private:
SkLayerDrawLooper::Builder sk_draw_looper_builder_;
+
+ // Implementing the copy constructor properly would require writing code to
+ // copy the underlying SkLayerDrawLooper::Builder.
+ DISALLOW_COPY_AND_ASSIGN(DrawLooperBuilder);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.cc
index 78384c99086..a1046f3fd5f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_color_matrix.cc
@@ -84,8 +84,8 @@ static void SaturateMatrix(float s, SkScalar matrix[kColorMatrixSize]) {
}
static void HueRotateMatrix(float hue, SkScalar matrix[kColorMatrixSize]) {
- float cos_hue = cosf(hue * piFloat / 180);
- float sin_hue = sinf(hue * piFloat / 180);
+ float cos_hue = cosf(hue * kPiFloat / 180);
+ float sin_hue = sinf(hue * kPiFloat / 180);
matrix[0] = 0.213f + cos_hue * 0.787f - sin_hue * 0.213f;
matrix[1] = 0.715f - cos_hue * 0.715f - sin_hue * 0.715f;
matrix[2] = 0.072f - cos_hue * 0.072f + sin_hue * 0.928f;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc
index c09fd849111..181432ee635 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_convolve_matrix.cc
@@ -26,8 +26,8 @@
#include <memory>
#include "SkMatrixConvolutionImageFilter.h"
+#include "base/numerics/checked_math.h"
#include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
#include "third_party/blink/renderer/platform/wtf/text/text_stream.h"
namespace blink {
@@ -65,7 +65,7 @@ FloatRect FEConvolveMatrix::MapEffect(const FloatRect& rect) const {
if (!ParametersValid())
return rect;
FloatRect result = rect;
- result.MoveBy(-target_offset_);
+ result.MoveBy(FloatPoint(-target_offset_));
result.Expand(FloatSize(kernel_size_));
return result;
}
@@ -123,7 +123,7 @@ bool FEConvolveMatrix::ParametersValid() const {
if (kernel_size_.IsEmpty())
return false;
uint64_t kernel_area = kernel_size_.Area();
- if (!CheckedNumeric<int>(kernel_area).IsValid())
+ if (!base::CheckedNumeric<int>(kernel_area).IsValid())
return false;
if (SafeCast<size_t>(kernel_area) != kernel_matrix_.size())
return false;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.cc
index f04200b8805..53325c61361 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/fe_gaussian_blur.cc
@@ -37,7 +37,7 @@ namespace {
inline unsigned ApproximateBoxWidth(float s) {
return static_cast<unsigned>(
- floorf(s * (3 / 4.f * sqrtf(twoPiFloat)) + 0.5f));
+ floorf(s * (3 / 4.f * sqrtf(kTwoPiFloat)) + 0.5f));
}
IntSize CalculateKernelSize(const FloatSize& std) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/filter.h b/chromium/third_party/blink/renderer/platform/graphics/filters/filter.h
index cb5ae4db283..0eda8102d1e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/filter.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/filter.h
@@ -21,12 +21,12 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_FILTERS_FILTER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_FILTERS_FILTER_H_
+#include "base/macros.h"
#include "third_party/blink/renderer/platform/geometry/float_point_3d.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
namespace blink {
@@ -34,7 +34,6 @@ class SourceGraphic;
class FilterEffect;
class PLATFORM_EXPORT Filter final : public GarbageCollected<Filter> {
- WTF_MAKE_NONCOPYABLE(Filter);
public:
enum UnitScaling { kUserSpace, kBoundingBox };
@@ -81,6 +80,8 @@ class PLATFORM_EXPORT Filter final : public GarbageCollected<Filter> {
Member<SourceGraphic> source_graphic_;
Member<FilterEffect> last_effect_;
+
+ DISALLOW_COPY_AND_ASSIGN(Filter);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.h b/chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.h
index 70856a53280..688ad342ef4 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/filter_effect.h
@@ -23,6 +23,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_FILTERS_FILTER_EFFECT_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_FILTERS_FILTER_EFFECT_H_
+#include "base/macros.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
@@ -31,7 +32,6 @@
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -50,7 +50,6 @@ enum FilterEffectType {
class PLATFORM_EXPORT FilterEffect
: public GarbageCollectedFinalized<FilterEffect> {
- WTF_MAKE_NONCOPYABLE(FilterEffect);
public:
virtual ~FilterEffect();
@@ -166,6 +165,8 @@ class PLATFORM_EXPORT FilterEffect
InterpolationSpace operating_interpolation_space_;
sk_sp<PaintFilter> image_filters_[4];
+
+ DISALLOW_COPY_AND_ASSIGN(FilterEffect);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/light_source.h b/chromium/third_party/blink/renderer/platform/graphics/filters/light_source.h
index 46dc4958716..7bed4021570 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/light_source.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/light_source.h
@@ -24,11 +24,11 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_FILTERS_LIGHT_SOURCE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_FILTERS_LIGHT_SOURCE_H_
+#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/geometry/float_point_3d.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
namespace blink {
@@ -36,7 +36,6 @@ namespace blink {
enum LightType { LS_DISTANT, LS_POINT, LS_SPOT };
class PLATFORM_EXPORT LightSource : public RefCounted<LightSource> {
- WTF_MAKE_NONCOPYABLE(LightSource);
public:
LightSource(LightType type) : type_(type) {}
@@ -55,6 +54,8 @@ class PLATFORM_EXPORT LightSource : public RefCounted<LightSource> {
private:
LightType type_;
+
+ DISALLOW_COPY_AND_ASSIGN(LightSource);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/filters/source_graphic.cc b/chromium/third_party/blink/renderer/platform/graphics/filters/source_graphic.cc
index d06b534ddfa..bb5d23d7229 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/filters/source_graphic.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/filters/source_graphic.cc
@@ -36,7 +36,7 @@ SourceGraphic* SourceGraphic::Create(Filter* filter) {
}
FloatRect SourceGraphic::MapInputs(const FloatRect& rect) const {
- return !source_rect_.IsEmpty() ? source_rect_ : rect;
+ return !source_rect_.IsEmpty() ? FloatRect(source_rect_) : rect;
}
void SourceGraphic::SetSourceRect(const IntRect& source_rect) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/PRESUBMIT.py b/chromium/third_party/blink/renderer/platform/graphics/gpu/PRESUBMIT.py
new file mode 100644
index 00000000000..2efada7170d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/PRESUBMIT.py
@@ -0,0 +1,24 @@
+# Copyright (c) 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.
+
+"""Top-level presubmit script for third_party/blink/renderer/platform/graphics/gpu.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details about the presubmit API built into depot_tools.
+"""
+
+
+def PostUploadHook(cl, change, output_api): # pylint: disable=C0103,W0613
+ """git cl upload will call this hook after the issue is created/modified.
+
+ This hook modifies the CL description in order to run extra GPU
+ tests (in particular, WebXR and WebVR browser tests) in addition
+ to the regular CQ try bots. This test suite is too large to run
+ against all Chromium commits, but should be run against changes
+ likely to affect these tests.
+ """
+ return output_api.EnsureCQIncludeTrybotsAreAdded(
+ cl,
+ ['luci.chromium.try:win_optional_gpu_tests_rel'],
+ 'Automatically added optional GPU tests to run on CQ.')
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
index 29a1b56cbbd..7658bd05636 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -34,10 +34,11 @@
#include <memory>
#include <utility>
+#include "base/numerics/checked_math.h"
#include "build/build_config.h"
#include "cc/layers/texture_layer.h"
-#include "components/viz/common/quads/shared_bitmap.h"
#include "components/viz/common/resources/bitmap_allocation.h"
+#include "components/viz/common/resources/shared_bitmap.h"
#include "components/viz/common/resources/transferable_resource.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
@@ -54,7 +55,7 @@
#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_wrapper.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h"
#include "third_party/skia/include/core/SkColorSpaceXform.h"
#include "third_party/skia/include/core/SkSurface.h"
@@ -91,7 +92,7 @@ scoped_refptr<DrawingBuffer> DrawingBuffer::Create(
return nullptr;
}
- CheckedNumeric<int> data_size = color_params.BytesPerPixel();
+ base::CheckedNumeric<int> data_size = color_params.BytesPerPixel();
data_size *= size.Width();
data_size *= size.Height();
if (!data_size.IsValid() ||
@@ -238,6 +239,10 @@ DrawingBuffer::ContextProviderWeakPtr() {
return context_provider_->GetWeakPtr();
}
+const DrawingBuffer::WebGLContextLimits& DrawingBuffer::webgl_context_limits() {
+ return webgl_context_limits_;
+}
+
void DrawingBuffer::SetIsHidden(bool hidden) {
if (is_hidden_ == hidden)
return;
@@ -435,8 +440,6 @@ void DrawingBuffer::FinishPrepareTransferableResourceGpu(
// Put colorBufferForMailbox into its mailbox, and populate its
// produceSyncToken with that point.
{
- gl_->ProduceTextureDirectCHROMIUM(color_buffer_for_mailbox->texture_id,
- color_buffer_for_mailbox->mailbox.name);
// It's critical to order the execution of this context's work relative
// to other contexts, in particular the compositor. Previously this
// used to be a Flush, and there was a bug that we didn't flush before
@@ -629,7 +632,8 @@ DrawingBuffer::ColorBuffer::ColorBuffer(
texture_id(texture_id),
image_id(image_id),
gpu_memory_buffer(std::move(gpu_memory_buffer)) {
- drawing_buffer->ContextGL()->GenMailboxCHROMIUM(mailbox.name);
+ gpu::gles2::GLES2Interface* gl = drawing_buffer->ContextGL();
+ gl->ProduceTextureDirectCHROMIUM(texture_id, mailbox.name);
}
DrawingBuffer::ColorBuffer::~ColorBuffer() {
@@ -698,19 +702,47 @@ bool DrawingBuffer::Initialize(const IntSize& size, bool use_multisampling) {
gl_->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size_);
+ auto webgl_preferences =
+ ContextProvider()->GetGpuFeatureInfo().webgl_preferences;
+ webgl_context_limits_.max_active_webgl_contexts =
+ webgl_preferences.max_active_webgl_contexts;
+ webgl_context_limits_.max_active_webgl_contexts_on_worker =
+ webgl_preferences.max_active_webgl_contexts_on_worker;
+
int max_sample_count = 0;
- anti_aliasing_mode_ = kNone;
- if (use_multisampling) {
- gl_->GetIntegerv(GL_MAX_SAMPLES_ANGLE, &max_sample_count);
- anti_aliasing_mode_ = kMSAAExplicitResolve;
- if (extensions_util_->SupportsExtension(
- "GL_EXT_multisampled_render_to_texture")) {
- anti_aliasing_mode_ = kMSAAImplicitResolve;
- } else if (extensions_util_->SupportsExtension(
- "GL_CHROMIUM_screen_space_antialiasing")) {
- anti_aliasing_mode_ = kScreenSpaceAntialiasing;
+ gl_->GetIntegerv(GL_MAX_SAMPLES_ANGLE, &max_sample_count);
+ if (webgl_preferences.anti_aliasing_mode ==
+ gpu::kAntialiasingModeUnspecified) {
+ if (use_multisampling) {
+ anti_aliasing_mode_ = gpu::kAntialiasingModeMSAAExplicitResolve;
+ if (extensions_util_->SupportsExtension(
+ "GL_EXT_multisampled_render_to_texture")) {
+ anti_aliasing_mode_ = gpu::kAntialiasingModeMSAAImplicitResolve;
+ } else if (extensions_util_->SupportsExtension(
+ "GL_CHROMIUM_screen_space_antialiasing") &&
+ !ContextProvider()->GetGpuFeatureInfo().IsWorkaroundEnabled(
+ gpu::DISABLE_FRAMEBUFFER_CMAA)) {
+ anti_aliasing_mode_ = gpu::kAntialiasingModeScreenSpaceAntialiasing;
+ }
+ } else {
+ anti_aliasing_mode_ = gpu::kAntialiasingModeNone;
+ max_sample_count = 0;
}
+ } else {
+ if ((webgl_preferences.anti_aliasing_mode ==
+ gpu::kAntialiasingModeMSAAImplicitResolve &&
+ !extensions_util_->SupportsExtension(
+ "GL_EXT_multisampled_render_to_texture")) ||
+ (webgl_preferences.anti_aliasing_mode ==
+ gpu::kAntialiasingModeScreenSpaceAntialiasing &&
+ !extensions_util_->SupportsExtension(
+ "GL_CHROMIUM_screen_space_antialiasing"))) {
+ DLOG(ERROR) << "Invalid anti-aliasing mode specified.";
+ return false;
+ }
+ anti_aliasing_mode_ = webgl_preferences.anti_aliasing_mode;
}
+
// TODO(dshwang): Enable storage textures on all platforms. crbug.com/557848
// The Linux ATI bot fails
// WebglConformance.conformance_textures_misc_tex_image_webgl, so use storage
@@ -719,14 +751,10 @@ bool DrawingBuffer::Initialize(const IntSize& size, bool use_multisampling) {
storage_texture_supported_ =
(webgl_version_ > kWebGL1 ||
extensions_util_->SupportsExtension("GL_EXT_texture_storage")) &&
- anti_aliasing_mode_ == kScreenSpaceAntialiasing;
- // Performance regreses by 30% in WebGL apps for AMD Stoney
- // if sample count is 8x
- if (ContextProvider()->GetGpuFeatureInfo().IsWorkaroundEnabled(
- gpu::MAX_MSAA_SAMPLE_COUNT_4))
- sample_count_ = std::min(4, max_sample_count);
- else
- sample_count_ = std::min(8, max_sample_count);
+ anti_aliasing_mode_ == gpu::kAntialiasingModeScreenSpaceAntialiasing;
+
+ sample_count_ = std::min(
+ static_cast<int>(webgl_preferences.msaa_sample_count), max_sample_count);
texture_target_ = GL_TEXTURE_2D;
#if defined(OS_MACOSX)
@@ -829,17 +857,19 @@ bool DrawingBuffer::CopyToPlatformTexture(gpu::gles2::GLES2Interface* dst_gl,
mailbox = front_color_buffer_->mailbox;
produce_sync_token = front_color_buffer_->produce_sync_token;
} else {
- src_gl->GenMailboxCHROMIUM(mailbox.name);
if (premultiplied_alpha_false_texture_) {
// If this texture exists, then it holds the rendering results at this
// point, rather than back_color_buffer_. back_color_buffer_ receives the
// contents of this texture later, premultiplying alpha into the color
- // channels.
- src_gl->ProduceTextureDirectCHROMIUM(premultiplied_alpha_false_texture_,
- mailbox.name);
+ // channels. We lazily produce a mailbox for it.
+ if (premultiplied_alpha_false_mailbox_.IsZero()) {
+ src_gl->ProduceTextureDirectCHROMIUM(
+ premultiplied_alpha_false_texture_,
+ premultiplied_alpha_false_mailbox_.name);
+ }
+ mailbox = premultiplied_alpha_false_mailbox_;
} else {
- src_gl->ProduceTextureDirectCHROMIUM(back_color_buffer_->texture_id,
- mailbox.name);
+ mailbox = back_color_buffer_->mailbox;
}
src_gl->GenUnverifiedSyncTokenCHROMIUM(produce_sync_token.GetData());
}
@@ -930,8 +960,10 @@ void DrawingBuffer::BeginDestruction() {
if (depth_stencil_buffer_)
gl_->DeleteRenderbuffers(1, &depth_stencil_buffer_);
- if (premultiplied_alpha_false_texture_)
+ if (premultiplied_alpha_false_texture_) {
gl_->DeleteTextures(1, &premultiplied_alpha_false_texture_);
+ premultiplied_alpha_false_mailbox_.SetZero();
+ }
size_ = IntSize();
@@ -965,6 +997,7 @@ bool DrawingBuffer::ResizeDefaultFramebuffer(const IntSize& size) {
// TODO(kbr): unify with code in CreateColorBuffer.
if (premultiplied_alpha_false_texture_) {
gl_->DeleteTextures(1, &premultiplied_alpha_false_texture_);
+ premultiplied_alpha_false_mailbox_.SetZero();
premultiplied_alpha_false_texture_ = 0;
}
gl_->GenTextures(1, &premultiplied_alpha_false_texture_);
@@ -1032,11 +1065,12 @@ bool DrawingBuffer::ResizeDefaultFramebuffer(const IntSize& size) {
if (!depth_stencil_buffer_)
gl_->GenRenderbuffers(1, &depth_stencil_buffer_);
gl_->BindRenderbuffer(GL_RENDERBUFFER, depth_stencil_buffer_);
- if (anti_aliasing_mode_ == kMSAAImplicitResolve) {
+ if (anti_aliasing_mode_ == gpu::kAntialiasingModeMSAAImplicitResolve) {
gl_->RenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, sample_count_,
GL_DEPTH24_STENCIL8_OES,
size.Width(), size.Height());
- } else if (anti_aliasing_mode_ == kMSAAExplicitResolve) {
+ } else if (anti_aliasing_mode_ ==
+ gpu::kAntialiasingModeMSAAExplicitResolve) {
gl_->RenderbufferStorageMultisampleCHROMIUM(
GL_RENDERBUFFER, sample_count_, GL_DEPTH24_STENCIL8_OES, size.Width(),
size.Height());
@@ -1191,12 +1225,13 @@ void DrawingBuffer::ResolveMultisampleFramebufferInternal() {
}
gl_->BindFramebuffer(GL_FRAMEBUFFER, fbo_);
- if (anti_aliasing_mode_ == kScreenSpaceAntialiasing)
+ if (anti_aliasing_mode_ == gpu::kAntialiasingModeScreenSpaceAntialiasing)
gl_->ApplyScreenSpaceAntialiasingCHROMIUM();
}
void DrawingBuffer::ResolveIfNeeded() {
- if (anti_aliasing_mode_ != kNone && !contents_change_resolved_)
+ if (anti_aliasing_mode_ != gpu::kAntialiasingModeNone &&
+ !contents_change_resolved_)
ResolveMultisampleFramebufferInternal();
contents_change_resolved_ = true;
}
@@ -1217,7 +1252,7 @@ void DrawingBuffer::RestoreAllState() {
}
bool DrawingBuffer::Multisample() const {
- return anti_aliasing_mode_ != kNone;
+ return anti_aliasing_mode_ != gpu::kAntialiasingModeNone;
}
void DrawingBuffer::Bind(GLenum target) {
@@ -1231,7 +1266,7 @@ scoped_refptr<Uint8Array> DrawingBuffer::PaintRenderingResultsToDataArray(
int width = Size().Width();
int height = Size().Height();
- CheckedNumeric<int> data_size = 4;
+ base::CheckedNumeric<int> data_size = 4;
data_size *= width;
data_size *= height;
if (RuntimeEnabledFeatures::CanvasColorManagementEnabled() &&
@@ -1483,7 +1518,7 @@ void DrawingBuffer::AttachColorBufferToReadFramebuffer() {
gl_->BindTexture(texture_target, id);
- if (anti_aliasing_mode_ == kMSAAImplicitResolve) {
+ if (anti_aliasing_mode_ == gpu::kAntialiasingModeMSAAImplicitResolve) {
gl_->FramebufferTexture2DMultisampleEXT(
GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_target, id, 0,
sample_count_);
@@ -1494,7 +1529,7 @@ void DrawingBuffer::AttachColorBufferToReadFramebuffer() {
}
bool DrawingBuffer::WantExplicitResolve() {
- return anti_aliasing_mode_ == kMSAAExplicitResolve;
+ return anti_aliasing_mode_ == gpu::kAntialiasingModeMSAAExplicitResolve;
}
bool DrawingBuffer::WantDepthOrStencil() {
@@ -1513,7 +1548,7 @@ bool DrawingBuffer::SetupRGBEmulationForBlitFramebuffer(
return false;
}
- if (anti_aliasing_mode_ != kNone)
+ if (anti_aliasing_mode_ != gpu::kAntialiasingModeNone)
return false;
bool has_emulated_rgb = !allocate_alpha_channel_ && have_alpha_channel_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
index 092f0bb2b7c..f65927d8d15 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
@@ -33,17 +33,18 @@
#include <memory>
+#include "base/macros.h"
#include "cc/layers/texture_layer_client.h"
#include "cc/resources/cross_thread_shared_bitmap.h"
#include "cc/resources/shared_bitmap_id_registrar.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/sync_token.h"
+#include "gpu/config/gpu_feature_info.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types_3d.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/khronos/GLES2/gl2.h"
@@ -75,7 +76,6 @@ class WebGraphicsContext3DProviderWrapper;
// publish its rendering results to a cc::Layer for compositing.
class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
public RefCounted<DrawingBuffer> {
- WTF_MAKE_NONCOPYABLE(DrawingBuffer);
public:
class Client {
@@ -96,6 +96,11 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
virtual void DrawingBufferClientRestorePixelPackBufferBinding() = 0;
};
+ struct WebGLContextLimits {
+ uint32_t max_active_webgl_contexts = 0;
+ uint32_t max_active_webgl_contexts_on_worker = 0;
+ };
+
enum PreserveDrawingBuffer {
kPreserve,
kDiscard,
@@ -103,6 +108,7 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
enum WebGLVersion {
kWebGL1,
kWebGL2,
+ kWebGL2Compute,
};
enum ChromiumImageUsage {
@@ -201,6 +207,7 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
Client* client() { return client_; }
WebGLVersion webgl_version() const { return webgl_version_; }
bool destroyed() const { return destruction_in_progress_; }
+ const WebGLContextLimits& webgl_context_limits();
// cc::TextureLayerClient implementation.
bool PrepareTransferableResource(
@@ -232,7 +239,7 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
int SampleCount() const { return sample_count_; }
bool ExplicitResolveOfMultisampleData() const {
- return anti_aliasing_mode_ == kMSAAExplicitResolve;
+ return anti_aliasing_mode_ == gpu::kAntialiasingModeMSAAExplicitResolve;
}
// Rebind the read and draw framebuffers that WebGL is expecting.
@@ -365,7 +372,7 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
gpu::SyncToken receive_sync_token;
private:
- WTF_MAKE_NONCOPYABLE(ColorBuffer);
+ DISALLOW_COPY_AND_ASSIGN(ColorBuffer);
};
// The same as clearFramebuffers(), but leaves GL state dirty.
@@ -467,6 +474,7 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
const PreserveDrawingBuffer preserve_drawing_buffer_;
const WebGLVersion webgl_version_;
+ WebGLContextLimits webgl_context_limits_;
std::unique_ptr<WebGraphicsContext3DProviderWrapper> context_provider_;
// Lifetime is tied to the m_contextProvider.
@@ -514,6 +522,10 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
// channels when copying into the GMB.
GLuint premultiplied_alpha_false_texture_ = 0;
+ // A mailbox for the premultiplied_alpha_false_texture_, created lazily if we
+ // need to produce it.
+ gpu::Mailbox premultiplied_alpha_false_mailbox_;
+
// When wantExplicitResolve() returns false, the target of all draw and
// read operations. When wantExplicitResolve() returns true, the target of
// all read operations.
@@ -548,14 +560,7 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
const gfx::ColorSpace storage_color_space_;
const gfx::ColorSpace sampler_color_space_;
- enum AntialiasingMode {
- kNone,
- kMSAAImplicitResolve,
- kMSAAExplicitResolve,
- kScreenSpaceAntialiasing,
- };
-
- AntialiasingMode anti_aliasing_mode_ = kNone;
+ gpu::AntialiasingMode anti_aliasing_mode_ = gpu::kAntialiasingModeNone;
bool use_half_float_storage_ = false;
@@ -589,6 +594,8 @@ class PLATFORM_EXPORT DrawingBuffer : public cc::TextureLayerClient,
// A release callback that is run when the previouis image passed to
// OffscreenCanvas::Commit() is no longer needed.
std::unique_ptr<viz::SingleReleaseCallback> previous_image_release_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(DrawingBuffer);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h
index 3982c821752..2cdc932901a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h
@@ -38,7 +38,6 @@ class WebGraphicsContext3DProviderForTests
: gl_(std::move(gl)) {}
gpu::gles2::GLES2Interface* ContextGL() override { return gl_.get(); }
- bool IsSoftwareRendering() const override { return false; }
// Not used by WebGL code.
GrContext* GetGrContext() override { return nullptr; }
@@ -197,13 +196,9 @@ class GLES2InterfaceForTests : public gpu::gles2::GLES2InterfaceStub,
}
}
- void GenMailboxCHROMIUM(GLbyte* mailbox) override {
+ void ProduceTextureDirectCHROMIUM(GLuint texture, GLbyte* mailbox) override {
++current_mailbox_byte_;
memset(mailbox, current_mailbox_byte_, GL_MAILBOX_SIZE_CHROMIUM);
- }
-
- void ProduceTextureDirectCHROMIUM(GLuint texture,
- const GLbyte* mailbox) override {
if (!create_image_chromium_fail_) {
ASSERT_TRUE(texture_sizes_.Contains(texture));
most_recently_produced_size_ = texture_sizes_.at(texture);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h
index f220a21eb4e..8ef40f8317c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h
@@ -6,10 +6,11 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_EXTENSIONS_3D_UTIL_H_
#include <memory>
+
+#include "base/macros.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/khronos/GLES2/gl2.h"
@@ -24,7 +25,6 @@ namespace blink {
class PLATFORM_EXPORT Extensions3DUtil final {
USING_FAST_MALLOC(Extensions3DUtil);
- WTF_MAKE_NONCOPYABLE(Extensions3DUtil);
public:
// Creates a new Extensions3DUtil. If the passed GLES2Interface has been
@@ -48,6 +48,8 @@ class PLATFORM_EXPORT Extensions3DUtil final {
HashSet<String> enabled_extensions_;
HashSet<String> requestable_extensions_;
bool is_valid_;
+
+ DISALLOW_COPY_AND_ASSIGN(Extensions3DUtil);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.cc
index 5ba8ed67981..b1b4dcb12f1 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.cc
@@ -5,7 +5,10 @@
#include "third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/config/gpu_feature_info.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_wrapper.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/skia/include/core/SkImage.h"
#include "third_party/skia/include/gpu/GrContext.h"
@@ -48,11 +51,21 @@ void GraphicsContext3DUtils::GetMailboxForSkImage(gpu::Mailbox& out_mailbox,
DCHECK(gl);
GrTexture* gr_texture = image->getTexture();
DCHECK(gr == gr_texture->getContext());
+
+ GrBackendTexture backend_texture = image->getBackendTexture(true);
+ DCHECK(backend_texture.isValid());
+
+ GrGLTextureInfo info;
+ bool result = backend_texture.getGLTextureInfo(&info);
+ DCHECK(result);
+
+ GLuint texture_id = info.fID;
+
auto it = cached_mailboxes_.find(gr_texture);
if (it != cached_mailboxes_.end()) {
out_mailbox = it->value;
} else {
- gl->GenMailboxCHROMIUM(out_mailbox.name);
+ gl->ProduceTextureDirectCHROMIUM(texture_id, out_mailbox.name);
GrTextureMailboxReleaseProcData* release_proc_data =
new GrTextureMailboxReleaseProcData();
@@ -61,27 +74,33 @@ void GraphicsContext3DUtils::GetMailboxForSkImage(gpu::Mailbox& out_mailbox,
gr_texture->setRelease(GrTextureMailboxReleaseProc, release_proc_data);
cached_mailboxes_.insert(gr_texture, out_mailbox);
}
-
- GrBackendTexture backend_texture = image->getBackendTexture(true);
- DCHECK(backend_texture.isValid());
-
- GrGLTextureInfo info;
- bool result = backend_texture.getGLTextureInfo(&info);
- DCHECK(result);
-
- GLuint texture_id = info.fID;
gl->BindTexture(GL_TEXTURE_2D, texture_id);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
gl->BindTexture(GL_TEXTURE_2D, 0);
- gl->ProduceTextureDirectCHROMIUM(texture_id, out_mailbox.name);
- image->getTexture()->textureParamsModified();
+ gr_texture->textureParamsModified();
}
void GraphicsContext3DUtils::RemoveCachedMailbox(GrTexture* gr_texture) {
cached_mailboxes_.erase(gr_texture);
}
+bool GraphicsContext3DUtils::Accelerated2DCanvasFeatureEnabled() {
+ // Don't use accelerated canvas if compositor is in software mode.
+ if (!SharedGpuContext::IsGpuCompositingEnabled())
+ return false;
+
+ if (!RuntimeEnabledFeatures::Accelerated2dCanvasEnabled())
+ return false;
+
+ DCHECK(context_provider_wrapper_);
+ const gpu::GpuFeatureInfo& gpu_feature_info =
+ context_provider_wrapper_->ContextProvider()->GetGpuFeatureInfo();
+ return gpu::kGpuFeatureStatusEnabled ==
+ gpu_feature_info
+ .status_values[gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS];
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.h
index d88bef383ab..54b117b39bb 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/graphics_context_3d_utils.h
@@ -36,6 +36,8 @@ class PLATFORM_EXPORT GraphicsContext3DUtils {
GLenum filter);
void RemoveCachedMailbox(GrTexture*);
+ bool Accelerated2DCanvasFeatureEnabled();
+
private:
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper_;
WTF::HashMap<GrTexture*, gpu::Mailbox> cached_mailboxes_;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
index 8f6c3f88718..10ff62ac177 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
@@ -6,8 +6,8 @@
#include "cc/layers/texture_layer.h"
#include "cc/resources/cross_thread_shared_bitmap.h"
-#include "components/viz/common/quads/shared_bitmap.h"
#include "components/viz/common/resources/bitmap_allocation.h"
+#include "components/viz/common/resources/shared_bitmap.h"
#include "components/viz/common/resources/transferable_resource.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/blink/public/platform/platform.h"
@@ -19,6 +19,7 @@
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "ui/gfx/geometry/size.h"
namespace blink {
@@ -75,7 +76,7 @@ void ImageLayerBridge::SetUV(const FloatPoint& left_top,
void ImageLayerBridge::Dispose() {
if (layer_) {
GraphicsLayer::UnregisterContentsLayer(layer_.get());
- layer_->ClearTexture();
+ layer_->ClearClient();
layer_ = nullptr;
}
image_ = nullptr;
@@ -108,20 +109,12 @@ bool ImageLayerBridge::PrepareTransferableResource(
// flipped.
layer_->SetFlipped(gpu_image);
- scoped_refptr<StaticBitmapImage> image_for_compositor;
-
- // Upload to a texture if the compositor is expecting one.
- if (gpu_compositing && !image_->IsTextureBacked()) {
- image_for_compositor =
+ if (gpu_compositing) {
+ scoped_refptr<StaticBitmapImage> image_for_compositor =
image_->MakeAccelerated(SharedGpuContext::ContextProviderWrapper());
- } else if (!gpu_compositing && image_->IsTextureBacked()) {
- image_for_compositor = image_->MakeUnaccelerated();
- } else {
- image_for_compositor = image_;
- }
- DCHECK_EQ(image_for_compositor->IsTextureBacked(), gpu_compositing);
+ if (!image_for_compositor)
+ return false;
- if (gpu_compositing) {
uint32_t filter =
filter_quality_ == kNone_SkFilterQuality ? GL_NEAREST : GL_LINEAR;
image_for_compositor->EnsureMailbox(kUnverifiedSyncToken, filter);
@@ -133,13 +126,17 @@ bool ImageLayerBridge::PrepareTransferableResource(
WrapWeakPersistent(this), std::move(image_for_compositor));
*out_release_callback = viz::SingleReleaseCallback::Create(std::move(func));
} else {
- sk_sp<SkImage> sk_image =
- image_for_compositor->PaintImageForCurrentFrame().GetSkImage();
+ // Readback if needed and retain the readback in image_ to prevent future
+ // readbacks
+ image_ = image_->MakeUnaccelerated();
+ if (!image_)
+ return false;
+
+ sk_sp<SkImage> sk_image = image_->PaintImageForCurrentFrame().GetSkImage();
if (!sk_image)
return false;
- const gfx::Size size(image_for_compositor->width(),
- image_for_compositor->height());
+ const gfx::Size size(image_->width(), image_->height());
viz::ResourceFormat resource_format = viz::RGBA_8888;
if (sk_image->colorType() == SkColorType::kRGBA_F16_SkColorType)
resource_format = viz::RGBA_F16;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h
index 2b274d4b5fa..6f33ac4c629 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.h
@@ -7,6 +7,7 @@
#include <memory>
+#include "base/macros.h"
#include "cc/layers/texture_layer_client.h"
#include "cc/resources/shared_bitmap_id_registrar.h"
#include "components/viz/common/resources/resource_format.h"
@@ -31,7 +32,6 @@ namespace blink {
class PLATFORM_EXPORT ImageLayerBridge
: public GarbageCollectedFinalized<ImageLayerBridge>,
public cc::TextureLayerClient {
- WTF_MAKE_NONCOPYABLE(ImageLayerBridge);
public:
ImageLayerBridge(OpacityMode);
@@ -98,6 +98,8 @@ class PLATFORM_EXPORT ImageLayerBridge
bool disposed_ = false;
bool has_presented_since_last_set_image_ = false;
OpacityMode opacity_mode_ = kNonOpaque;
+
+ DISALLOW_COPY_AND_ASSIGN(ImageLayerBridge);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_context_rate_limiter.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_context_rate_limiter.h
index 86b0a6c0209..0a13f77583d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_context_rate_limiter.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_context_rate_limiter.h
@@ -6,10 +6,11 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_SHARED_CONTEXT_RATE_LIMITER_H_
#include <memory>
+
+#include "base/macros.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
namespace blink {
@@ -37,7 +38,6 @@ class WebGraphicsContext3DProvider;
class SharedContextRateLimiter final {
USING_FAST_MALLOC(SharedContextRateLimiter);
- WTF_MAKE_NONCOPYABLE(SharedContextRateLimiter);
public:
static std::unique_ptr<SharedContextRateLimiter> Create(
@@ -52,6 +52,8 @@ class SharedContextRateLimiter final {
Deque<GLuint> queries_;
unsigned max_pending_ticks_;
bool can_use_sync_queries_;
+
+ DISALLOW_COPY_AND_ASSIGN(SharedContextRateLimiter);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.cc
index fe1ff3529c5..d122cbf8c34 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.cc
@@ -10,6 +10,7 @@
#include "gpu/config/gpu_feature_info.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
+#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/waitable_event.h"
#include "third_party/blink/renderer/platform/web_task_runner.h"
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc
index 55858bbac7e..3eed0a6c437 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc
@@ -14,8 +14,10 @@
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/test/fake_gles2_interface.h"
#include "third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/khronos/GLES2/gl2ext.h"
+using testing::_;
using testing::Test;
namespace blink {
@@ -46,7 +48,7 @@ class SharedGpuContextTest
class MailboxMockGLES2Interface : public FakeGLES2Interface {
public:
- MOCK_METHOD1(GenMailboxCHROMIUM, void(GLbyte*));
+ MOCK_METHOD2(ProduceTextureDirectCHROMIUM, void(GLuint, GLbyte*));
MOCK_METHOD1(GenSyncTokenCHROMIUM, void(GLbyte*));
MOCK_METHOD1(GenUnverifiedSyncTokenCHROMIUM, void(GLbyte*));
};
@@ -114,7 +116,11 @@ TEST_F(SharedGpuContextTest, AccelerateImageBufferSurfaceAutoRecovery) {
std::unique_ptr<CanvasResourceProvider> resource_provider =
CanvasResourceProvider::Create(
size, CanvasResourceProvider::kAcceleratedResourceUsage,
- SharedGpuContext::ContextProviderWrapper());
+ SharedGpuContext::ContextProviderWrapper(),
+ 0, // msaa_sample_count
+ CanvasColorParams(), CanvasResourceProvider::kDefaultPresentationMode,
+ nullptr // canvas_resource_dispatcher
+ );
EXPECT_TRUE(resource_provider && resource_provider->IsValid());
EXPECT_TRUE(SharedGpuContext::IsValidWithoutRestoring());
}
@@ -128,9 +134,7 @@ TEST_F(SharedGpuContextTest, Canvas2DLayerBridgeAutoRecovery) {
CanvasColorParams color_params;
std::unique_ptr<Canvas2DLayerBridge> bridge =
std::make_unique<Canvas2DLayerBridge>(
- size, 0,
- /*msaa sample count*/ Canvas2DLayerBridge::kEnableAcceleration,
- color_params);
+ size, Canvas2DLayerBridge::kEnableAcceleration, color_params);
EXPECT_TRUE(bridge->IsAccelerated());
EXPECT_TRUE(SharedGpuContext::IsValidWithoutRestoring());
}
@@ -155,7 +159,11 @@ TEST_F(BadSharedGpuContextTest, AccelerateImageBufferSurfaceCreationFails) {
std::unique_ptr<CanvasResourceProvider> resource_provider =
CanvasResourceProvider::Create(
size, CanvasResourceProvider::kAcceleratedResourceUsage,
- SharedGpuContext::ContextProviderWrapper());
+ SharedGpuContext::ContextProviderWrapper(),
+ 0, // msaa_sample_count
+ CanvasColorParams(), CanvasResourceProvider::kDefaultPresentationMode,
+ nullptr // canvas_resource_dispatcher
+ );
EXPECT_FALSE(!resource_provider);
}
@@ -173,7 +181,7 @@ TEST_F(SoftwareCompositingTest, CompositingMode) {
class FakeMailboxGenerator {
public:
- void GenMailbox(GLbyte* name) { *name = counter_++; }
+ void ProduceTexture(GLuint texture, GLbyte* name) { *name = counter_++; }
GLbyte counter_ = 1;
};
@@ -183,7 +191,11 @@ TEST_F(MailboxSharedGpuContextTest, MailboxCaching) {
std::unique_ptr<CanvasResourceProvider> resource_provider =
CanvasResourceProvider::Create(
size, CanvasResourceProvider::kAcceleratedResourceUsage,
- SharedGpuContext::ContextProviderWrapper());
+ SharedGpuContext::ContextProviderWrapper(),
+ 0, // msaa_sample_count
+ CanvasColorParams(), CanvasResourceProvider::kDefaultPresentationMode,
+ nullptr // canvas_resource_dispatcher
+ );
EXPECT_TRUE(resource_provider && resource_provider->IsValid());
scoped_refptr<StaticBitmapImage> image = resource_provider->Snapshot();
testing::Mock::VerifyAndClearExpectations(&gl_);
@@ -192,10 +204,10 @@ TEST_F(MailboxSharedGpuContextTest, MailboxCaching) {
gpu::Mailbox mailbox;
mailbox.name[0] = 0;
- EXPECT_CALL(gl_, GenMailboxCHROMIUM(mailbox.name))
+ EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, mailbox.name))
.Times(1)
.WillOnce(testing::Invoke(&mailboxGenerator,
- &FakeMailboxGenerator::GenMailbox));
+ &FakeMailboxGenerator::ProduceTexture));
SharedGpuContext::ContextProviderWrapper()->Utils()->GetMailboxForSkImage(
mailbox, image->PaintImageForCurrentFrame().GetSkImage(), GL_NEAREST);
@@ -204,8 +216,8 @@ TEST_F(MailboxSharedGpuContextTest, MailboxCaching) {
testing::Mock::VerifyAndClearExpectations(&gl_);
- EXPECT_CALL(gl_, GenMailboxCHROMIUM(mailbox.name))
- .Times(0); // GenMailboxCHROMIUM must not be called!
+ EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, mailbox.name))
+ .Times(0); // ProduceTextureDirectCHROMIUM must not be called!
mailbox.name[0] = 0;
SharedGpuContext::ContextProviderWrapper()->Utils()->GetMailboxForSkImage(
@@ -220,7 +232,11 @@ TEST_F(MailboxSharedGpuContextTest, MailboxCacheSurvivesSkiaRecycling) {
std::unique_ptr<CanvasResourceProvider> resource_provider =
CanvasResourceProvider::Create(
size, CanvasResourceProvider::kAcceleratedResourceUsage,
- SharedGpuContext::ContextProviderWrapper());
+ SharedGpuContext::ContextProviderWrapper(),
+ 0, // msaa_sample_count
+ CanvasColorParams(), CanvasResourceProvider::kDefaultPresentationMode,
+ nullptr // canvas_resource_dispatcher
+ );
EXPECT_TRUE(resource_provider && resource_provider->IsValid());
scoped_refptr<StaticBitmapImage> image = resource_provider->Snapshot();
testing::Mock::VerifyAndClearExpectations(&gl_);
@@ -229,10 +245,10 @@ TEST_F(MailboxSharedGpuContextTest, MailboxCacheSurvivesSkiaRecycling) {
gpu::Mailbox mailbox;
mailbox.name[0] = 0;
- EXPECT_CALL(gl_, GenMailboxCHROMIUM(mailbox.name))
+ EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, mailbox.name))
.Times(1)
.WillOnce(testing::Invoke(&mailboxGenerator,
- &FakeMailboxGenerator::GenMailbox));
+ &FakeMailboxGenerator::ProduceTexture));
SharedGpuContext::ContextProviderWrapper()->Utils()->GetMailboxForSkImage(
mailbox, image->PaintImageForCurrentFrame().GetSkImage(), GL_NEAREST);
@@ -249,14 +265,19 @@ TEST_F(MailboxSharedGpuContextTest, MailboxCacheSurvivesSkiaRecycling) {
// Re-creating surface should recycle the old GrTexture inside skia
resource_provider = CanvasResourceProvider::Create(
size, CanvasResourceProvider::kAcceleratedResourceUsage,
- SharedGpuContext::ContextProviderWrapper());
+ SharedGpuContext::ContextProviderWrapper(),
+ 0, // msaa_sample_count
+ CanvasColorParams(), CanvasResourceProvider::kDefaultPresentationMode,
+ nullptr // canvas_resource_dispatcher
+ );
+
EXPECT_TRUE(resource_provider && resource_provider->IsValid());
image = resource_provider->Snapshot();
testing::Mock::VerifyAndClearExpectations(&gl_);
- EXPECT_CALL(gl_, GenMailboxCHROMIUM(mailbox.name))
- .Times(0); // GenMailboxCHROMIUM must not be called!
+ EXPECT_CALL(gl_, ProduceTextureDirectCHROMIUM(_, mailbox.name))
+ .Times(0); // ProduceTextureDirectCHROMIUM must not be called!
mailbox.name[0] = 0;
SharedGpuContext::ContextProviderWrapper()->Utils()->GetMailboxForSkImage(
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc
index bdaa943e701..4631eb4eff0 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h"
#include <memory>
+#include "base/numerics/checked_math.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/graphics/cpu/arm/webgl_image_conversion_neon.h"
#include "third_party/blink/renderer/platform/graphics/cpu/mips/webgl_image_conversion_msa.h"
@@ -12,7 +13,6 @@
#include "third_party/blink/renderer/platform/graphics/image_observer.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
#include "third_party/skia/include/core/SkImage.h"
namespace blink {
@@ -2703,14 +2703,15 @@ GLenum WebGLImageConversion::ComputeImageSizeInBytes(
&components_per_pixel))
return GL_INVALID_ENUM;
unsigned bytes_per_group = bytes_per_component * components_per_pixel;
- CheckedNumeric<uint32_t> checked_value = static_cast<uint32_t>(row_length);
+ base::CheckedNumeric<uint32_t> checked_value =
+ static_cast<uint32_t>(row_length);
checked_value *= bytes_per_group;
if (!checked_value.IsValid())
return GL_INVALID_VALUE;
unsigned last_row_size;
if (params.row_length > 0 && params.row_length != width) {
- CheckedNumeric<uint32_t> tmp = width;
+ base::CheckedNumeric<uint32_t> tmp = width;
tmp *= bytes_per_group;
if (!tmp.IsValid())
return GL_INVALID_VALUE;
@@ -2720,7 +2721,8 @@ GLenum WebGLImageConversion::ComputeImageSizeInBytes(
}
unsigned padding = 0;
- CheckedNumeric<uint32_t> checked_residual = checked_value % params.alignment;
+ base::CheckedNumeric<uint32_t> checked_residual =
+ checked_value % params.alignment;
if (!checked_residual.IsValid()) {
return GL_INVALID_VALUE;
}
@@ -2733,7 +2735,7 @@ GLenum WebGLImageConversion::ComputeImageSizeInBytes(
return GL_INVALID_VALUE;
unsigned padded_row_size = checked_value.ValueOrDie();
- CheckedNumeric<uint32_t> rows = image_height;
+ base::CheckedNumeric<uint32_t> rows = image_height;
rows *= (depth - 1);
// Last image is not affected by IMAGE_HEIGHT parameter.
rows += height;
@@ -2748,9 +2750,9 @@ GLenum WebGLImageConversion::ComputeImageSizeInBytes(
if (padding_in_bytes)
*padding_in_bytes = padding;
- CheckedNumeric<uint32_t> skip_size = 0;
+ base::CheckedNumeric<uint32_t> skip_size = 0;
if (params.skip_images > 0) {
- CheckedNumeric<uint32_t> tmp = padded_row_size;
+ base::CheckedNumeric<uint32_t> tmp = padded_row_size;
tmp *= image_height;
tmp *= params.skip_images;
if (!tmp.IsValid())
@@ -2758,14 +2760,14 @@ GLenum WebGLImageConversion::ComputeImageSizeInBytes(
skip_size += tmp.ValueOrDie();
}
if (params.skip_rows > 0) {
- CheckedNumeric<uint32_t> tmp = padded_row_size;
+ base::CheckedNumeric<uint32_t> tmp = padded_row_size;
tmp *= params.skip_rows;
if (!tmp.IsValid())
return GL_INVALID_VALUE;
skip_size += tmp.ValueOrDie();
}
if (params.skip_pixels > 0) {
- CheckedNumeric<uint32_t> tmp = bytes_per_group;
+ base::CheckedNumeric<uint32_t> tmp = bytes_per_group;
tmp *= params.skip_pixels;
if (!tmp.IsValid())
return GL_INVALID_VALUE;
@@ -2811,8 +2813,10 @@ void WebGLImageConversion::ImageExtractor::ExtractImage(
(has_alpha && !premultiply_alpha)) &&
image_->Data()) {
// Attempt to get raw unpremultiplied image data.
+ const bool data_complete = true;
std::unique_ptr<ImageDecoder> decoder(ImageDecoder::Create(
- image_->Data(), true, ImageDecoder::kAlphaNotPremultiplied,
+ image_->Data(), data_complete, ImageDecoder::kAlphaNotPremultiplied,
+ ImageDecoder::kDefaultBitDepth,
ignore_color_space ? ColorBehavior::Ignore()
: ColorBehavior::TransformToSRGB()));
if (!decoder || !decoder->FrameCount())
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h
index 10ee7d4d309..cd954650e92 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_WEBGL_IMAGE_CONVERSION_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_WEBGL_IMAGE_CONVERSION_H_
+#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
@@ -129,7 +130,6 @@ class PLATFORM_EXPORT WebGLImageConversion final {
class PLATFORM_EXPORT ImageExtractor final {
STACK_ALLOCATED();
- WTF_MAKE_NONCOPYABLE(ImageExtractor);
public:
ImageExtractor(Image*,
@@ -162,6 +162,8 @@ class PLATFORM_EXPORT WebGLImageConversion final {
DataFormat image_source_format_;
AlphaOp alpha_op_;
unsigned image_source_unpack_alignment_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImageExtractor);
};
// Computes the components per pixel and bytes per component
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
index 08c8e3376a5..10739aae009 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
@@ -23,6 +23,10 @@ XRFrameTransport::~XRFrameTransport() {
void XRFrameTransport::PresentChange() {
frame_copier_ = nullptr;
+
+ // Ensure we don't wait for a frame separator fence when rapidly exiting and
+ // re-entering presentation, cf. https://crbug.com/855722.
+ waiting_for_previous_frame_fence_ = false;
}
void XRFrameTransport::SetTransportOptions(
@@ -30,12 +34,10 @@ void XRFrameTransport::SetTransportOptions(
transport_options_ = std::move(transport_options);
}
-device::mojom::blink::VRSubmitFrameClientPtr
-XRFrameTransport::GetSubmitFrameClient() {
- device::mojom::blink::VRSubmitFrameClientPtr submit_frame_client;
+void XRFrameTransport::BindSubmitFrameClient(
+ device::mojom::blink::VRSubmitFrameClientRequest request) {
submit_frame_client_binding_.Close();
- submit_frame_client_binding_.Bind(mojo::MakeRequest(&submit_frame_client));
- return submit_frame_client;
+ submit_frame_client_binding_.Bind(std::move(request));
}
bool XRFrameTransport::DrawingIntoSharedBuffer() {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h
index f2c88fafb57..1af00bceb4f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.h
@@ -35,7 +35,8 @@ class PLATFORM_EXPORT XRFrameTransport final
explicit XRFrameTransport();
~XRFrameTransport() override;
- device::mojom::blink::VRSubmitFrameClientPtr GetSubmitFrameClient();
+ void BindSubmitFrameClient(
+ device::mojom::blink::VRSubmitFrameClientRequest request);
void PresentChange();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc
index 73f10fcb8f4..ab0754787ba 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.cc
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h"
#include "third_party/blink/renderer/platform/graphics/gpu/extensions_3d_util.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/skia/include/core/SkSurface.h"
namespace blink {
@@ -23,7 +24,8 @@ XRWebGLDrawingBuffer::ColorBuffer::ColorBuffer(
const IntSize& size,
GLuint texture_id)
: drawing_buffer(drawing_buffer), size(size), texture_id(texture_id) {
- drawing_buffer->ContextGL()->GenMailboxCHROMIUM(mailbox.name);
+ gpu::gles2::GLES2Interface* gl = drawing_buffer->ContextGL();
+ gl->ProduceTextureDirectCHROMIUM(texture_id, mailbox.name);
}
XRWebGLDrawingBuffer::ColorBuffer::~ColorBuffer() {
@@ -113,6 +115,12 @@ XRWebGLDrawingBuffer::XRWebGLDrawingBuffer(DrawingBuffer* drawing_buffer,
alpha_(want_alpha_channel),
multiview_(false) {}
+void XRWebGLDrawingBuffer::BeginDestruction() {
+ back_color_buffer_ = nullptr;
+ front_color_buffer_ = nullptr;
+ recycled_color_buffer_queue_.clear();
+}
+
// TODO(bajones): The GL resources allocated in this function are leaking. Add
// a way to clean up the buffers when the layer is GCed or the session ends.
bool XRWebGLDrawingBuffer::Initialize(const IntSize& size,
@@ -280,12 +288,13 @@ void XRWebGLDrawingBuffer::UseSharedBuffer(
framebuffer_complete_checked_for_sharedbuffer_ = true;
}
- if (discard_framebuffer_supported_) {
- const GLenum kAttachments[3] = {GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT,
- GL_STENCIL_ATTACHMENT};
- gl->DiscardFramebufferEXT(GL_FRAMEBUFFER, 3, kAttachments);
+ if (WantExplicitResolve()) {
+ // Bind the drawing framebuffer if it wasn't bound previously.
+ gl->BindFramebuffer(GL_FRAMEBUFFER, framebuffer_);
}
+ ClearBoundFramebuffer();
+
DrawingBuffer::Client* client = drawing_buffer_->client();
if (!client)
return;
@@ -298,19 +307,14 @@ void XRWebGLDrawingBuffer::DoneWithSharedBuffer() {
BindAndResolveDestinationFramebuffer();
gpu::gles2::GLES2Interface* gl = drawing_buffer_->ContextGL();
+
+ // Discard the depth and stencil attachments since we're done with them.
+ // Don't discard the color buffer, we do need this rendered into the
+ // shared buffer.
if (discard_framebuffer_supported_) {
- // Discard the depth and stencil attachments since we're done with them.
- // Don't discard the color buffer, we do need this rendered into the
- // shared buffer.
- if (WantExplicitResolve()) {
- gl->BindFramebuffer(GL_FRAMEBUFFER, resolved_framebuffer_);
- } else {
- gl->BindFramebuffer(GL_FRAMEBUFFER, framebuffer_);
- }
- const GLenum kAttachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
- gl->DiscardFramebufferEXT(GL_FRAMEBUFFER,
- sizeof(kAttachments) / sizeof(kAttachments[0]),
- kAttachments);
+ const GLenum kAttachments[3] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
+ gl->BindFramebuffer(GL_FRAMEBUFFER, framebuffer_);
+ gl->DiscardFramebufferEXT(GL_FRAMEBUFFER, 2, kAttachments);
}
// Always bind to the default framebuffer as a hint to the GPU to start
@@ -328,6 +332,37 @@ void XRWebGLDrawingBuffer::DoneWithSharedBuffer() {
client->DrawingBufferClientRestoreFramebufferBinding();
}
+void XRWebGLDrawingBuffer::ClearBoundFramebuffer() {
+ gpu::gles2::GLES2Interface* gl = drawing_buffer_->ContextGL();
+
+ GLbitfield clear_bits = GL_COLOR_BUFFER_BIT;
+ gl->ColorMask(true, true, true, true);
+ gl->ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+ if (depth_) {
+ clear_bits |= GL_DEPTH_BUFFER_BIT;
+ gl->DepthMask(true);
+ gl->ClearDepthf(1.0f);
+ }
+
+ if (stencil_) {
+ clear_bits |= GL_STENCIL_BUFFER_BIT;
+ gl->StencilMaskSeparate(GL_FRONT, true);
+ gl->ClearStencil(0);
+ }
+
+ gl->Disable(GL_SCISSOR_TEST);
+
+ gl->Clear(clear_bits);
+
+ DrawingBuffer::Client* client = drawing_buffer_->client();
+ if (!client)
+ return;
+
+ client->DrawingBufferClientRestoreScissorTest();
+ client->DrawingBufferClientRestoreMaskAndClearValues();
+}
+
void XRWebGLDrawingBuffer::Resize(const IntSize& new_size) {
IntSize adjusted_size = AdjustSize(new_size);
@@ -537,12 +572,13 @@ void XRWebGLDrawingBuffer::SwapColorBuffers() {
framebuffer_complete_checked_for_swap_ = true;
}
- if (discard_framebuffer_supported_) {
- const GLenum kAttachments[3] = {GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT,
- GL_STENCIL_ATTACHMENT};
- gl->DiscardFramebufferEXT(GL_FRAMEBUFFER, 3, kAttachments);
+ if (WantExplicitResolve()) {
+ // Bind the drawing framebuffer if it wasn't bound previously.
+ gl->BindFramebuffer(GL_FRAMEBUFFER, framebuffer_);
}
+ ClearBoundFramebuffer();
+
client->DrawingBufferClientRestoreFramebufferBinding();
}
@@ -560,7 +596,6 @@ XRWebGLDrawingBuffer::TransferToStaticBitmapImage(
buffer = front_color_buffer_;
- gl->ProduceTextureDirectCHROMIUM(buffer->texture_id, buffer->mailbox.name);
gl->GenUnverifiedSyncTokenCHROMIUM(buffer->produce_sync_token.GetData());
// This should only fail if the context is lost during the buffer swap.
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h
index 8a14d3426ab..3003a125de1 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/xr_webgl_drawing_buffer.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_XR_WEBGL_DRAWING_BUFFER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GPU_XR_WEBGL_DRAWING_BUFFER_H_
+#include "base/macros.h"
#include "cc/layers/texture_layer_client.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
@@ -12,7 +13,6 @@
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
namespace blink {
@@ -63,13 +63,18 @@ class PLATFORM_EXPORT XRWebGLDrawingBuffer
void UseSharedBuffer(const gpu::MailboxHolder&);
void DoneWithSharedBuffer();
+ // Prepare for destruction by breaking reference loops. This must be called to
+ // avoid memory leaks, drawing buffer and color buffers are refcounted and
+ // store references to each other.
+ void BeginDestruction();
+
private:
struct ColorBuffer : public RefCounted<ColorBuffer> {
ColorBuffer(XRWebGLDrawingBuffer*, const IntSize&, GLuint texture_id);
~ColorBuffer();
// The owning XRWebGLDrawingBuffer. Note that DrawingBuffer is explicitly
- // destroyed by the beginDestruction method, which will eventually drain all
+ // destroyed by the BeginDestruction method, which will eventually drain all
// of its ColorBuffers.
scoped_refptr<XRWebGLDrawingBuffer> drawing_buffer;
const IntSize size;
@@ -86,7 +91,7 @@ class PLATFORM_EXPORT XRWebGLDrawingBuffer
gpu::SyncToken receive_sync_token;
private:
- WTF_MAKE_NONCOPYABLE(ColorBuffer);
+ DISALLOW_COPY_AND_ASSIGN(ColorBuffer);
};
XRWebGLDrawingBuffer(DrawingBuffer*,
@@ -108,6 +113,8 @@ class PLATFORM_EXPORT XRWebGLDrawingBuffer
void BindAndResolveDestinationFramebuffer();
void SwapColorBuffers();
+ void ClearBoundFramebuffer();
+
void MailboxReleased(scoped_refptr<ColorBuffer>,
const gpu::SyncToken&,
bool lost_resource);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gradient.h b/chromium/third_party/blink/renderer/platform/graphics/gradient.h
index 20f5231a3fd..62b8c35488d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gradient.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gradient.h
@@ -29,13 +29,13 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GRADIENT_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GRADIENT_H_
+#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_flags.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_shader.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/skia/include/core/SkRefCnt.h"
@@ -48,7 +48,6 @@ namespace blink {
class FloatPoint;
class PLATFORM_EXPORT Gradient : public RefCounted<Gradient> {
- WTF_MAKE_NONCOPYABLE(Gradient);
public:
enum class Type { kLinear, kRadial, kConic };
@@ -128,6 +127,8 @@ class PLATFORM_EXPORT Gradient : public RefCounted<Gradient> {
bool stops_sorted_;
mutable sk_sp<PaintShader> cached_shader_;
+
+ DISALLOW_COPY_AND_ASSIGN(Gradient);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.cc b/chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.cc
index ebd3afe54aa..f9fd7b25ee8 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.cc
@@ -31,7 +31,7 @@
namespace blink {
-void GradientGeneratedImage::Draw(PaintCanvas* canvas,
+void GradientGeneratedImage::Draw(cc::PaintCanvas* canvas,
const PaintFlags& flags,
const FloatRect& dest_rect,
const FloatRect& src_rect,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.h b/chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.h
index ce79328d42b..eeadaf627ef 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gradient_generated_image.h
@@ -46,7 +46,7 @@ class PLATFORM_EXPORT GradientGeneratedImage final : public GeneratedImage {
bool ApplyShader(PaintFlags&, const SkMatrix&) override;
protected:
- void Draw(PaintCanvas*,
+ void Draw(cc::PaintCanvas*,
const PaintFlags&,
const FloatRect&,
const FloatRect&,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc b/chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc
index 9aea136fcc4..7661ef3c2f3 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_context.cc
@@ -36,6 +36,7 @@
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
#include "third_party/blink/renderer/platform/graphics/interpolation_space.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.h"
@@ -67,12 +68,12 @@ GraphicsContext::GraphicsContext(PaintController& paint_controller,
#if DCHECK_IS_ON()
layer_count_(0),
disable_destruction_checks_(false),
- in_drawing_recorder_(false),
#endif
disabled_state_(disable_context_or_painting),
device_scale_factor_(1.0f),
printing_(false),
- has_meta_data_(!!meta_data) {
+ has_meta_data_(!!meta_data),
+ in_drawing_recorder_(false) {
if (meta_data)
meta_data_ = *meta_data;
@@ -192,13 +193,11 @@ void GraphicsContext::RestoreLayer() {
canvas_->restore();
}
-#if DCHECK_IS_ON()
void GraphicsContext::SetInDrawingRecorder(bool val) {
// Nested drawing recorers are not allowed.
DCHECK(!val || !in_drawing_recorder_);
in_drawing_recorder_ = val;
}
-#endif
void GraphicsContext::SetShadow(
const FloatSize& offset,
@@ -628,8 +627,8 @@ void GraphicsContext::DrawLine(const IntPoint& point1, const IntPoint& point2) {
if (pen_style == kNoStroke)
return;
- FloatPoint p1 = point1;
- FloatPoint p2 = point2;
+ FloatPoint p1 = FloatPoint(point1);
+ FloatPoint p2 = FloatPoint(point2);
bool is_vertical_line = (p1.X() == p2.X());
int width = roundf(StrokeThickness());
@@ -877,7 +876,7 @@ void GraphicsContext::DrawImage(
if (ContextDisabled() || !image)
return;
- const FloatRect src = src_ptr ? *src_ptr : image->Rect();
+ const FloatRect src = src_ptr ? *src_ptr : FloatRect(image->Rect());
PaintFlags image_flags = ImmutableState()->FillFlags();
image_flags.setBlendMode(op);
@@ -909,7 +908,8 @@ void GraphicsContext::DrawImageRRect(
DCHECK(dest.IsRenderable());
- const FloatRect visible_src = Intersection(src_rect, image->Rect());
+ const FloatRect visible_src =
+ Intersection(src_rect, FloatRect(image->Rect()));
if (dest.IsEmpty() || visible_src.IsEmpty())
return;
@@ -970,15 +970,16 @@ SkFilterQuality GraphicsContext::ComputeFilterQuality(
}
void GraphicsContext::DrawTiledImage(Image* image,
- const FloatRect& dest_rect,
- const FloatPoint& src_point,
+ const FloatSize& unsnapped_subset_size,
+ const FloatRect& snapped_paint_rect,
+ const FloatPoint& unsnapped_phase,
const FloatSize& tile_size,
SkBlendMode op,
const FloatSize& repeat_spacing) {
if (ContextDisabled() || !image)
return;
- image->DrawTiledBackground(*this, dest_rect, src_point, tile_size, op,
- repeat_spacing);
+ image->DrawTiledBackground(*this, unsnapped_subset_size, snapped_paint_rect,
+ unsnapped_phase, tile_size, op, repeat_spacing);
paint_controller_.SetImagePainted();
}
@@ -1044,6 +1045,16 @@ void GraphicsContext::FillPath(const Path& path_to_fill) {
DrawPath(path_to_fill.GetSkPath(), ImmutableState()->FillFlags());
}
+void GraphicsContext::FillRect(const IntRect& rect) {
+ FillRect(FloatRect(rect));
+}
+
+void GraphicsContext::FillRect(const IntRect& rect,
+ const Color& color,
+ SkBlendMode xfer_mode) {
+ FillRect(FloatRect(rect), color, xfer_mode);
+}
+
void GraphicsContext::FillRect(const FloatRect& rect) {
if (ContextDisabled())
return;
@@ -1097,47 +1108,33 @@ bool IsSimpleDRRect(const FloatRoundedRect& outer,
!WebCoreFloatNearlyEqual(stroke_size.Width(),
outer.Rect().MaxX() - inner.Rect().MaxX()) ||
!WebCoreFloatNearlyEqual(stroke_size.Height(),
- outer.Rect().MaxY() - inner.Rect().MaxY()))
+ outer.Rect().MaxY() - inner.Rect().MaxY())) {
return false;
+ }
- // and
- // 2) the inner radii are not constrained
- const FloatRoundedRect::Radii& o_radii = outer.GetRadii();
- const FloatRoundedRect::Radii& i_radii = inner.GetRadii();
- if (!WebCoreFloatNearlyEqual(o_radii.TopLeft().Width() - stroke_size.Width(),
- i_radii.TopLeft().Width()) ||
- !WebCoreFloatNearlyEqual(
- o_radii.TopLeft().Height() - stroke_size.Height(),
- i_radii.TopLeft().Height()) ||
- !WebCoreFloatNearlyEqual(o_radii.TopRight().Width() - stroke_size.Width(),
- i_radii.TopRight().Width()) ||
- !WebCoreFloatNearlyEqual(
- o_radii.TopRight().Height() - stroke_size.Height(),
- i_radii.TopRight().Height()) ||
- !WebCoreFloatNearlyEqual(
- o_radii.BottomRight().Width() - stroke_size.Width(),
- i_radii.BottomRight().Width()) ||
- !WebCoreFloatNearlyEqual(
- o_radii.BottomRight().Height() - stroke_size.Height(),
- i_radii.BottomRight().Height()) ||
- !WebCoreFloatNearlyEqual(
- o_radii.BottomLeft().Width() - stroke_size.Width(),
- i_radii.BottomLeft().Width()) ||
- !WebCoreFloatNearlyEqual(
- o_radii.BottomLeft().Height() - stroke_size.Height(),
- i_radii.BottomLeft().Height()))
- return false;
+ const auto& is_simple_corner = [&stroke_size](const FloatSize& outer,
+ const FloatSize& inner) {
+ // trivial/zero-radius corner
+ if (outer.IsZero() && inner.IsZero())
+ return true;
- // We also ignore DRRects with a very thick relative stroke (shapes which are
- // mostly filled by the stroke): Skia's stroke outline can diverge
- // significantly from the outer/inner contours in some edge cases, so we fall
- // back to drawDRRect() instead.
- const float kMaxStrokeToSizeRatio = 0.75f;
- if (2 * stroke_size.Width() / outer.Rect().Width() > kMaxStrokeToSizeRatio ||
- 2 * stroke_size.Height() / outer.Rect().Height() > kMaxStrokeToSizeRatio)
- return false;
+ // and
+ // 2) all corners are isotropic
+ // and
+ // 3) the inner radii are not constrained
+ return WebCoreFloatNearlyEqual(outer.Width(), outer.Height()) &&
+ WebCoreFloatNearlyEqual(inner.Width(), inner.Height()) &&
+ WebCoreFloatNearlyEqual(outer.Width(),
+ inner.Width() + stroke_size.Width());
+ };
+
+ const auto& o_radii = outer.GetRadii();
+ const auto& i_radii = inner.GetRadii();
- return true;
+ return is_simple_corner(o_radii.TopLeft(), i_radii.TopLeft()) &&
+ is_simple_corner(o_radii.TopRight(), i_radii.TopRight()) &&
+ is_simple_corner(o_radii.BottomRight(), i_radii.BottomRight()) &&
+ is_simple_corner(o_radii.BottomLeft(), i_radii.BottomLeft());
}
} // anonymous namespace
@@ -1323,7 +1320,7 @@ void GraphicsContext::SetURLForRect(const KURL& link,
DCHECK(canvas_);
sk_sp<SkData> url(SkData::MakeWithCString(link.GetString().Utf8().data()));
- canvas_->Annotate(PaintCanvas::AnnotationType::URL, dest_rect,
+ canvas_->Annotate(cc::PaintCanvas::AnnotationType::URL, dest_rect,
std::move(url));
}
@@ -1334,7 +1331,7 @@ void GraphicsContext::SetURLFragmentForRect(const String& dest_name,
DCHECK(canvas_);
sk_sp<SkData> sk_dest_name(SkData::MakeWithCString(dest_name.Utf8().data()));
- canvas_->Annotate(PaintCanvas::AnnotationType::LINK_TO_DESTINATION, rect,
+ canvas_->Annotate(cc::PaintCanvas::AnnotationType::LINK_TO_DESTINATION, rect,
std::move(sk_dest_name));
}
@@ -1346,7 +1343,7 @@ void GraphicsContext::SetURLDestinationLocation(const String& name,
SkRect rect = SkRect::MakeXYWH(location.X(), location.Y(), 0, 0);
sk_sp<SkData> sk_name(SkData::MakeWithCString(name.Utf8().data()));
- canvas_->Annotate(PaintCanvas::AnnotationType::NAMED_DESTINATION, rect,
+ canvas_->Annotate(cc::PaintCanvas::AnnotationType::NAMED_DESTINATION, rect,
std::move(sk_name));
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_context.h b/chromium/third_party/blink/renderer/platform/graphics/graphics_context.h
index 961d4a9961d..bcde7276eff 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_context.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_context.h
@@ -29,6 +29,8 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GRAPHICS_CONTEXT_H_
#include <memory>
+
+#include "base/macros.h"
#include "third_party/blink/renderer/platform/fonts/font.h"
#include "third_party/blink/renderer/platform/graphics/dash_array.h"
#include "third_party/blink/renderer/platform/graphics/draw_looper_builder.h"
@@ -43,7 +45,6 @@
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/skia/include/core/SkClipOp.h"
#include "third_party/skia/include/core/SkMetaData.h"
#include "third_party/skia/include/core/SkRefCnt.h"
@@ -62,7 +63,6 @@ class Path;
struct TextRunPaintInfo;
class PLATFORM_EXPORT GraphicsContext {
- WTF_MAKE_NONCOPYABLE(GraphicsContext);
USING_FAST_MALLOC(GraphicsContext);
public:
@@ -78,8 +78,8 @@ class PLATFORM_EXPORT GraphicsContext {
~GraphicsContext();
- PaintCanvas* Canvas() { return canvas_; }
- const PaintCanvas* Canvas() const { return canvas_; }
+ cc::PaintCanvas* Canvas() { return canvas_; }
+ const cc::PaintCanvas* Canvas() const { return canvas_; }
PaintController& GetPaintController() { return paint_controller_; }
const PaintController& GetPaintController() const {
@@ -189,6 +189,10 @@ class PLATFORM_EXPORT GraphicsContext {
void FillEllipse(const FloatRect&);
void StrokeEllipse(const FloatRect&);
+ void FillRect(const IntRect&);
+ void FillRect(const IntRect&,
+ const Color&,
+ SkBlendMode = SkBlendMode::kSrcOver);
void FillRect(const FloatRect&);
void FillRect(const FloatRect&,
const Color&,
@@ -219,12 +223,15 @@ class PLATFORM_EXPORT GraphicsContext {
const FloatRect& src_rect,
SkBlendMode = SkBlendMode::kSrcOver,
RespectImageOrientationEnum = kDoNotRespectImageOrientation);
+ // Used for background image
void DrawTiledImage(Image*,
- const FloatRect& dest_rect,
- const FloatPoint& src_point,
+ const FloatSize& unsnapped_subset_size,
+ const FloatRect& snapped_paint_rect,
+ const FloatPoint& unsnapped_phase,
const FloatSize& tile_size,
SkBlendMode = SkBlendMode::kSrcOver,
const FloatSize& repeat_spacing = FloatSize());
+ // Used for border image
void DrawTiledImage(Image*,
const FloatRect& dest_rect,
const FloatRect& src_rect,
@@ -389,9 +396,8 @@ class PLATFORM_EXPORT GraphicsContext {
static int FocusRingOutsetExtent(int offset, int width);
-#if DCHECK_IS_ON()
void SetInDrawingRecorder(bool);
-#endif
+ bool InDrawingRecorder() const { return in_drawing_recorder_; }
static sk_sp<SkColorFilter> WebCoreColorFilterToSkiaColorFilter(ColorFilter);
@@ -465,7 +471,7 @@ class PLATFORM_EXPORT GraphicsContext {
PaintFlags ApplyHighContrastFilter(const PaintFlags* input) const;
// null indicates painting is contextDisabled. Never delete this object.
- PaintCanvas* canvas_;
+ cc::PaintCanvas* canvas_;
PaintController& paint_controller_;
@@ -487,7 +493,6 @@ class PLATFORM_EXPORT GraphicsContext {
#if DCHECK_IS_ON()
int layer_count_;
bool disable_destruction_checks_;
- bool in_drawing_recorder_;
#endif
const DisabledMode disabled_state_;
@@ -500,6 +505,9 @@ class PLATFORM_EXPORT GraphicsContext {
unsigned printing_ : 1;
unsigned has_meta_data_ : 1;
+ unsigned in_drawing_recorder_ : 1;
+
+ DISALLOW_COPY_AND_ASSIGN(GraphicsContext);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_context_state.h b/chromium/third_party/blink/renderer/platform/graphics/graphics_context_state.h
index cbe5e352c88..abeb92c7f0e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_context_state.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_context_state.h
@@ -37,7 +37,6 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_flags.h"
#include "third_party/blink/renderer/platform/graphics/stroke_data.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/skia/include/core/SkColorFilter.h"
#include "third_party/skia/include/core/SkRefCnt.h"
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h b/chromium/third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h
index f7ca44839fd..72768f14712 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h
@@ -29,16 +29,15 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GRAPHICS_CONTEXT_STATE_SAVER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GRAPHICS_CONTEXT_STATE_SAVER_H_
+#include "base/macros.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
namespace blink {
class PLATFORM_EXPORT GraphicsContextStateSaver final {
USING_FAST_MALLOC(GraphicsContextStateSaver);
- WTF_MAKE_NONCOPYABLE(GraphicsContextStateSaver);
public:
GraphicsContextStateSaver(GraphicsContext& context,
@@ -77,6 +76,8 @@ class PLATFORM_EXPORT GraphicsContextStateSaver final {
private:
GraphicsContext& context_;
bool save_and_restore_;
+
+ DISALLOW_COPY_AND_ASSIGN(GraphicsContextStateSaver);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_context_test.cc b/chromium/third_party/blink/renderer/platform/graphics/graphics_context_test.cc
index 02042667031..61186735384 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_context_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_context_test.cc
@@ -26,8 +26,10 @@
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include <memory>
+#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/graphics/bitmap_image.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record.h"
#include "third_party/blink/renderer/platform/graphics/path.h"
@@ -173,7 +175,13 @@ class GraphicsContextHighConstrastTest : public testing::Test {
// This is just a baseline test, compare against the other variants
// of the test below, where high contrast mode is enabled.
-TEST_F(GraphicsContextHighConstrastTest, NoHighContrast) {
+// TODO(crbug.com/850782): Reenable this.
+#if defined(OS_ANDROID)
+#define MAYBE_NoHighContrast DISABLED_NoHighContrast
+#else
+#define MAYBE_NoHighContrast NoHighContrast
+#endif
+TEST_F(GraphicsContextHighConstrastTest, MAYBE_NoHighContrast) {
DrawColorsToContext();
EXPECT_EQ(0xff000000, *bitmap_.getAddr32(0, 0));
@@ -182,7 +190,13 @@ TEST_F(GraphicsContextHighConstrastTest, NoHighContrast) {
EXPECT_EQ(0xff808080, *bitmap_.getAddr32(3, 0));
}
-TEST_F(GraphicsContextHighConstrastTest, HighContrastOff) {
+// TODO(crbug.com/850782): Reenable this.
+#if defined(OS_ANDROID)
+#define MAYBE_HighContrastOff DISABLED_HighContrastOff
+#else
+#define MAYBE_HighContrastOff HighContrastOff
+#endif
+TEST_F(GraphicsContextHighConstrastTest, MAYBE_HighContrastOff) {
HighContrastSettings settings;
settings.mode = HighContrastMode::kOff;
settings.grayscale = false;
@@ -199,7 +213,13 @@ TEST_F(GraphicsContextHighConstrastTest, HighContrastOff) {
// Simple invert for testing. Each color component |c|
// is replaced with |255 - c| for easy testing.
-TEST_F(GraphicsContextHighConstrastTest, SimpleInvertForTesting) {
+// TODO(crbug.com/850782): Reenable this.
+#if defined(OS_ANDROID)
+#define MAYBE_SimpleInvertForTesting DISABLED_SimpleInvertForTesting
+#else
+#define MAYBE_SimpleInvertForTesting SimpleInvertForTesting
+#endif
+TEST_F(GraphicsContextHighConstrastTest, MAYBE_SimpleInvertForTesting) {
HighContrastSettings settings;
settings.mode = HighContrastMode::kSimpleInvertForTesting;
settings.grayscale = false;
@@ -215,7 +235,13 @@ TEST_F(GraphicsContextHighConstrastTest, SimpleInvertForTesting) {
}
// Invert brightness (with gamma correction).
-TEST_F(GraphicsContextHighConstrastTest, InvertBrightness) {
+// TODO(crbug.com/850782): Reenable this.
+#if defined(OS_ANDROID)
+#define MAYBE_InvertBrightness DISABLED_InvertBrightness
+#else
+#define MAYBE_InvertBrightness InvertBrightness
+#endif
+TEST_F(GraphicsContextHighConstrastTest, MAYBE_InvertBrightness) {
HighContrastSettings settings;
settings.mode = HighContrastMode::kInvertBrightness;
settings.grayscale = false;
@@ -231,7 +257,13 @@ TEST_F(GraphicsContextHighConstrastTest, InvertBrightness) {
}
// Invert lightness (in HSL space).
-TEST_F(GraphicsContextHighConstrastTest, InvertLightness) {
+// TODO(crbug.com/850782): Reenable this.
+#if defined(OS_ANDROID)
+#define MAYBE_InvertLightness DISABLED_InvertLightness
+#else
+#define MAYBE_InvertLightness InvertLightness
+#endif
+TEST_F(GraphicsContextHighConstrastTest, MAYBE_InvertLightness) {
HighContrastSettings settings;
settings.mode = HighContrastMode::kInvertLightness;
settings.grayscale = false;
@@ -262,7 +294,13 @@ TEST_F(GraphicsContextHighConstrastTest, InvertLightnessPlusGrayscale) {
EXPECT_EQ(0xffdddddd, *bitmap_.getAddr32(3, 0));
}
-TEST_F(GraphicsContextHighConstrastTest, InvertLightnessPlusContrast) {
+// TODO(crbug.com/850782): Reenable this.
+#if defined(OS_ANDROID)
+#define MAYBE_InvertLightnessPlusContrast DISABLED_InvertLightnessPlusContrast
+#else
+#define MAYBE_InvertLightnessPlusContrast InvertLightnessPlusContrast
+#endif
+TEST_F(GraphicsContextHighConstrastTest, MAYBE_InvertLightnessPlusContrast) {
HighContrastSettings settings;
settings.mode = HighContrastMode::kInvertLightness;
settings.grayscale = false;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc
index b42248de806..07dc0da01aa 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -45,11 +45,9 @@
#include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
#include "third_party/blink/renderer/platform/drag_image.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
-#include "third_party/blink/renderer/platform/geometry/geometry_as_json.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/geometry/region.h"
#include "third_party/blink/renderer/platform/graphics/bitmap_image.h"
-#include "third_party/blink/renderer/platform/graphics/compositing/composited_layer_raster_invalidator.h"
#include "third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h"
#include "third_party/blink/renderer/platform/graphics/compositor_filter_operations.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
@@ -60,11 +58,10 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h"
#include "third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h"
+#include "third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
-#include "third_party/blink/renderer/platform/json/json_values.h"
#include "third_party/blink/renderer/platform/scroll/scroll_snap_data.h"
-#include "third_party/blink/renderer/platform/scroll/scrollable_area.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/math_extras.h"
@@ -106,7 +103,6 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient& client)
paint_count_(0),
contents_layer_(nullptr),
contents_layer_id_(0),
- scrollable_area_(nullptr),
rendering_context3d_(0),
weak_ptr_factory_(this) {
#if DCHECK_IS_ON()
@@ -136,13 +132,9 @@ GraphicsLayer::~GraphicsLayer() {
}
LayoutRect GraphicsLayer::VisualRect() const {
- LayoutRect bounds = LayoutRect(FloatPoint(), Size());
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- DCHECK(layer_state_);
- bounds.MoveBy(layer_state_->offset);
- } else {
- bounds.Move(OffsetFromLayoutObjectWithSubpixelAccumulation());
- }
+ LayoutRect bounds = LayoutRect(LayoutPoint(), LayoutSize(Size()));
+ DCHECK(layer_state_);
+ bounds.MoveBy(layer_state_->offset);
return bounds;
}
@@ -264,24 +256,16 @@ void GraphicsLayer::RemoveFromParent() {
CcLayer()->RemoveFromParent();
}
-void GraphicsLayer::SetOffsetFromLayoutObject(
- const IntSize& offset,
- ShouldSetNeedsDisplay should_set_needs_display) {
- SetOffsetDoubleFromLayoutObject(offset);
-}
-
-void GraphicsLayer::SetOffsetDoubleFromLayoutObject(
- const DoubleSize& offset,
- ShouldSetNeedsDisplay should_set_needs_display) {
+void GraphicsLayer::SetOffsetFromLayoutObject(const IntSize& offset) {
if (offset == offset_from_layout_object_)
return;
offset_from_layout_object_ = offset;
- CcLayer()->SetFiltersOrigin(FloatPoint() - ToFloatSize(offset));
+ CcLayer()->SetFiltersOrigin(FloatPoint() -
+ FloatSize(offset_from_layout_object_));
// If the compositing layer offset changes, we need to repaint.
- if (should_set_needs_display == kSetNeedsDisplay)
- SetNeedsDisplay();
+ SetNeedsDisplay();
}
LayoutSize GraphicsLayer::OffsetFromLayoutObjectWithSubpixelAccumulation()
@@ -297,26 +281,15 @@ void GraphicsLayer::PaintRecursively() {
Vector<GraphicsLayer*> repainted_layers;
PaintRecursivelyInternal(repainted_layers);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- // Notify the controllers that the artifact has been pushed and some
- // lifecycle state can be freed (such as raster invalidations).
- for (auto* layer : repainted_layers)
- layer->GetPaintController().FinishCycle();
- }
-
+ // Notify the controllers that the artifact has been pushed and some
+ // lifecycle state can be freed (such as raster invalidations).
+ for (auto* layer : repainted_layers) {
#if DCHECK_IS_ON()
- if (VLOG_IS_ON(2)) {
- static String s_previous_tree;
- LayerTreeFlags flags = VLOG_IS_ON(3) ? 0xffffffff : kOutputAsLayerTree;
- String new_tree = GetLayerTreeAsTextForTesting(flags);
- if (new_tree != s_previous_tree) {
- LOG(ERROR) << "After GraphicsLayer::PaintRecursively()\n"
- << "GraphicsLayer tree:\n"
- << new_tree.Utf8().data();
- s_previous_tree = new_tree;
- }
- }
+ if (VLOG_IS_ON(2))
+ LOG(ERROR) << "FinishCycle for GraphicsLayer: " << layer->DebugName();
#endif
+ layer->GetPaintController().FinishCycle();
+ }
}
void GraphicsLayer::PaintRecursivelyInternal(
@@ -340,7 +313,7 @@ bool GraphicsLayer::Paint(const IntRect* interest_rect,
#if !DCHECK_IS_ON()
// TODO(crbug.com/853096): Investigate why we can ever reach here without
// a valid layer state. Seems to only happen on Android builds.
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() && !layer_state_)
+ if (!layer_state_)
return false;
#endif
@@ -356,14 +329,12 @@ bool GraphicsLayer::Paint(const IntRect* interest_rect,
}
#endif
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- DCHECK(layer_state_) << "No layer state for GraphicsLayer: " << DebugName();
- // Generate raster invalidations for SPv175 (but not SPv2).
- IntRect layer_bounds(layer_state_->offset, ExpandedIntSize(Size()));
- EnsureRasterInvalidator().Generate(GetPaintController().GetPaintArtifact(),
- layer_bounds, layer_state_->state,
- VisualRectSubpixelOffset());
- }
+ DCHECK(layer_state_) << "No layer state for GraphicsLayer: " << DebugName();
+ // Generate raster invalidations for SPv1.
+ IntRect layer_bounds(layer_state_->offset, Size());
+ EnsureRasterInvalidator().Generate(
+ GetPaintController().GetPaintArtifactShared(), layer_bounds,
+ layer_state_->state, VisualRectSubpixelOffset(), this);
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() &&
DrawsContent()) {
@@ -372,9 +343,8 @@ bool GraphicsLayer::Paint(const IntRect* interest_rect,
InterestRect());
if (auto record = tracking.UnderInvalidationRecord()) {
// Add the under-invalidation overlay onto the painted result.
- GetPaintController().AppendDebugDrawingAfterCommit(
- *this, std::move(record),
- layer_state_ ? &layer_state_->state : nullptr);
+ GetPaintController().AppendDebugDrawingAfterCommit(std::move(record),
+ layer_state_->state);
// Ensure the compositor will raster the under-invalidation overlay.
layer_->SetNeedsDisplay();
}
@@ -409,11 +379,9 @@ bool GraphicsLayer::PaintWithoutCommit(
}
GraphicsContext context(GetPaintController(), disabled_mode, nullptr);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- DCHECK(layer_state_) << "No layer state for GraphicsLayer: " << DebugName();
- GetPaintController().UpdateCurrentPaintChunkProperties(base::nullopt,
- layer_state_->state);
- }
+ DCHECK(layer_state_) << "No layer state for GraphicsLayer: " << DebugName();
+ GetPaintController().UpdateCurrentPaintChunkProperties(base::nullopt,
+ layer_state_->state);
previous_interest_rect_ = *interest_rect;
client_.PaintContents(this, context, painting_phase_, *interest_rect);
@@ -557,9 +525,9 @@ void GraphicsLayer::SetupContentsLayer(cc::Layer* contents_layer) {
// Insert the content layer first. Video elements require this, because they
// have shadow content that must display in front of the video.
layer_->InsertChild(contents_layer_, 0);
- cc::Layer* border_cc_layer = contents_clipping_mask_layer_
- ? contents_clipping_mask_layer_->CcLayer()
- : nullptr;
+ cc::PictureLayer* border_cc_layer =
+ contents_clipping_mask_layer_ ? contents_clipping_mask_layer_->CcLayer()
+ : nullptr;
contents_layer_->SetMaskLayer(border_cc_layer);
contents_layer_->Set3dSortingContextId(rendering_context3d_);
@@ -593,10 +561,10 @@ cc::Layer* GraphicsLayer::ContentsLayerIfRegistered() {
return contents_layer_;
}
-CompositedLayerRasterInvalidator& GraphicsLayer::EnsureRasterInvalidator() {
+RasterInvalidator& GraphicsLayer::EnsureRasterInvalidator() {
if (!raster_invalidator_) {
- raster_invalidator_ = std::make_unique<CompositedLayerRasterInvalidator>(
- [this](const IntRect& r) { SetNeedsDisplayInRectInternal(r); });
+ raster_invalidator_ = std::make_unique<RasterInvalidator>(
+ [this](const IntRect& r) { SetNeedsDisplayInRect(r); });
raster_invalidator_->SetTracksRasterInvalidations(
client_.IsTrackingRasterInvalidations());
}
@@ -609,9 +577,6 @@ void GraphicsLayer::UpdateTrackingRasterInvalidations() {
EnsureRasterInvalidator().SetTracksRasterInvalidations(true);
else if (raster_invalidator_)
raster_invalidator_->SetTracksRasterInvalidations(false);
-
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() && paint_controller_)
- paint_controller_->SetTracksRasterInvalidations(should_track);
}
void GraphicsLayer::ResetTrackedRasterInvalidations() {
@@ -636,333 +601,13 @@ void GraphicsLayer::TrackRasterInvalidation(const DisplayItemClient& client,
if (RasterInvalidationTracking::ShouldAlwaysTrack())
EnsureRasterInvalidator().EnsureTracking();
- // For SPv175, this only tracks invalidations that the cc::Layer is fully
- // invalidated directly, e.g. from SetContentsNeedsDisplay(), etc.
+ // This only tracks invalidations that the cc::Layer is fully invalidated
+ // directly, e.g. from SetContentsNeedsDisplay(), etc. Other raster
+ // invalidations are tracked in RasterInvalidator.
if (auto* tracking = GetRasterInvalidationTracking())
tracking->AddInvalidation(&client, client.DebugName(), rect, reason);
}
-static String PointerAsString(const void* ptr) {
- WTF::TextStream ts;
- ts << ptr;
- return ts.Release();
-}
-
-class GraphicsLayer::LayersAsJSONArray {
- public:
- LayersAsJSONArray(LayerTreeFlags flags)
- : flags_(flags),
- next_transform_id_(1),
- layers_json_(JSONArray::Create()),
- transforms_json_(JSONArray::Create()) {}
-
- // Outputs the layer tree rooted at |layer| as a JSON array, in paint order,
- // and the transform tree also as a JSON array.
- std::unique_ptr<JSONObject> operator()(const GraphicsLayer& layer) {
- auto json = JSONObject::Create();
- Walk(layer, 0, FloatPoint());
- json->SetArray("layers", std::move(layers_json_));
- if (transforms_json_->size())
- json->SetArray("transforms", std::move(transforms_json_));
- return json;
- }
-
- JSONObject* AddTransformJSON(int& transform_id) {
- auto transform_json = JSONObject::Create();
- int parent_transform_id = transform_id;
- transform_id = next_transform_id_++;
- transform_json->SetInteger("id", transform_id);
- if (parent_transform_id)
- transform_json->SetInteger("parent", parent_transform_id);
- auto* result = transform_json.get();
- transforms_json_->PushObject(std::move(transform_json));
- return result;
- }
-
- static FloatPoint ScrollPosition(const GraphicsLayer& layer) {
- if (const auto* scrollable_area = layer.GetScrollableArea())
- return scrollable_area->ScrollPosition();
- return FloatPoint();
- }
-
- void AddLayer(const GraphicsLayer& layer,
- int& transform_id,
- FloatPoint& position) {
- FloatPoint scroll_position = ScrollPosition(layer);
- if (scroll_position != FloatPoint()) {
- // Output scroll position as a transform.
- auto* scroll_translate_json = AddTransformJSON(transform_id);
- scroll_translate_json->SetArray(
- "transform", TransformAsJSONArray(TransformationMatrix().Translate(
- -scroll_position.X(), -scroll_position.Y())));
- layer.AddFlattenInheritedTransformJSON(*scroll_translate_json);
- }
-
- if (!layer.transform_.IsIdentity() || layer.rendering_context3d_ ||
- layer.GetCompositingReasons() & CompositingReason::k3DTransform) {
- if (position != FloatPoint()) {
- // Output position offset as a transform.
- auto* position_translate_json = AddTransformJSON(transform_id);
- position_translate_json->SetArray(
- "transform", TransformAsJSONArray(TransformationMatrix().Translate(
- position.X(), position.Y())));
- layer.AddFlattenInheritedTransformJSON(*position_translate_json);
- if (layer.Parent() && !layer.Parent()->should_flatten_transform_) {
- position_translate_json->SetBoolean("flattenInheritedTransform",
- false);
- }
- position = FloatPoint();
- }
-
- if (!layer.transform_.IsIdentity() || layer.rendering_context3d_) {
- auto* transform_json = AddTransformJSON(transform_id);
- layer.AddTransformJSONProperties(*transform_json,
- rendering_context_map_);
- }
- }
-
- auto json =
- layer.LayerAsJSONInternal(flags_, rendering_context_map_, position);
- if (transform_id)
- json->SetInteger("transform", transform_id);
- layers_json_->PushObject(std::move(json));
- }
-
- void Walk(const GraphicsLayer& layer,
- int parent_transform_id,
- const FloatPoint& parent_position) {
- FloatPoint position = parent_position + layer.position_;
- int transform_id = parent_transform_id;
- AddLayer(layer, transform_id, position);
- for (auto* const child : layer.children_)
- Walk(*child, transform_id, position);
- }
-
- private:
- LayerTreeFlags flags_;
- int next_transform_id_;
- RenderingContextMap rendering_context_map_;
- std::unique_ptr<JSONArray> layers_json_;
- std::unique_ptr<JSONArray> transforms_json_;
-};
-
-std::unique_ptr<JSONObject> GraphicsLayer::LayerTreeAsJSON(
- LayerTreeFlags flags) const {
- if (flags & kOutputAsLayerTree) {
- RenderingContextMap rendering_context_map;
- return LayerTreeAsJSONInternal(flags, rendering_context_map);
- }
-
- return LayersAsJSONArray(flags)(*this);
-}
-
-// This is the SPv1 version of ContentLayerClientImpl::LayerAsJSON().
-std::unique_ptr<JSONObject> GraphicsLayer::LayerAsJSONInternal(
- LayerTreeFlags flags,
- RenderingContextMap& rendering_context_map,
- const FloatPoint& position) const {
- std::unique_ptr<JSONObject> json = JSONObject::Create();
-
- if (flags & kLayerTreeIncludesDebugInfo)
- json->SetString("this", PointerAsString(this));
-
- json->SetString("name", DebugName());
-
- if (position != FloatPoint())
- json->SetArray("position", PointAsJSONArray(position));
-
- if (flags & kLayerTreeIncludesDebugInfo &&
- offset_from_layout_object_ != DoubleSize()) {
- json->SetArray("offsetFromLayoutObject",
- SizeAsJSONArray(offset_from_layout_object_));
- }
-
- if (size_ != IntSize())
- json->SetArray("bounds", SizeAsJSONArray(size_));
-
- if (opacity_ != 1)
- json->SetDouble("opacity", opacity_);
-
- if (blend_mode_ != BlendMode::kNormal) {
- json->SetString("blendMode",
- CompositeOperatorName(kCompositeSourceOver, blend_mode_));
- }
-
- if (is_root_for_isolated_group_)
- json->SetBoolean("isolate", true);
-
- if (contents_opaque_)
- json->SetBoolean("contentsOpaque", true);
-
- if (!draws_content_)
- json->SetBoolean("drawsContent", false);
-
- if (!contents_visible_)
- json->SetBoolean("contentsVisible", false);
-
- if (!backface_visibility_)
- json->SetString("backfaceVisibility", "hidden");
-
- if (flags & kLayerTreeIncludesDebugInfo)
- json->SetString("client", PointerAsString(&client_));
-
- if (background_color_.Alpha()) {
- json->SetString("backgroundColor",
- background_color_.NameForLayoutTreeAsText());
- }
-
- if (flags & kOutputAsLayerTree) {
- AddTransformJSONProperties(*json, rendering_context_map);
- if (!should_flatten_transform_)
- json->SetBoolean("shouldFlattenTransform", false);
- if (scrollable_area_ &&
- scrollable_area_->ScrollPosition() != FloatPoint()) {
- json->SetArray("scrollPosition",
- PointAsJSONArray(scrollable_area_->ScrollPosition()));
- }
- }
-
- if ((flags & kLayerTreeIncludesPaintInvalidations) &&
- client_.IsTrackingRasterInvalidations() &&
- GetRasterInvalidationTracking())
- GetRasterInvalidationTracking()->AsJSON(json.get());
-
- if ((flags & kLayerTreeIncludesPaintingPhases) && painting_phase_) {
- std::unique_ptr<JSONArray> painting_phases_json = JSONArray::Create();
- if (painting_phase_ & kGraphicsLayerPaintBackground)
- painting_phases_json->PushString("GraphicsLayerPaintBackground");
- if (painting_phase_ & kGraphicsLayerPaintForeground)
- painting_phases_json->PushString("GraphicsLayerPaintForeground");
- if (painting_phase_ & kGraphicsLayerPaintMask)
- painting_phases_json->PushString("GraphicsLayerPaintMask");
- if (painting_phase_ & kGraphicsLayerPaintChildClippingMask)
- painting_phases_json->PushString("GraphicsLayerPaintChildClippingMask");
- if (painting_phase_ & kGraphicsLayerPaintAncestorClippingMask)
- painting_phases_json->PushString(
- "GraphicsLayerPaintAncestorClippingMask");
- if (painting_phase_ & kGraphicsLayerPaintOverflowContents)
- painting_phases_json->PushString("GraphicsLayerPaintOverflowContents");
- if (painting_phase_ & kGraphicsLayerPaintCompositedScroll)
- painting_phases_json->PushString("GraphicsLayerPaintCompositedScroll");
- if (painting_phase_ & kGraphicsLayerPaintDecoration)
- painting_phases_json->PushString("GraphicsLayerPaintDecoration");
- json->SetArray("paintingPhases", std::move(painting_phases_json));
- }
-
- if (flags & kLayerTreeIncludesClipAndScrollParents) {
- if (has_scroll_parent_)
- json->SetBoolean("hasScrollParent", true);
- if (has_clip_parent_)
- json->SetBoolean("hasClipParent", true);
- }
-
- if (flags &
- (kLayerTreeIncludesDebugInfo | kLayerTreeIncludesCompositingReasons)) {
- bool debug = flags & kLayerTreeIncludesDebugInfo;
- {
- std::unique_ptr<JSONArray> compositing_reasons_json = JSONArray::Create();
- auto names = debug ? CompositingReason::Descriptions(compositing_reasons_)
- : CompositingReason::ShortNames(compositing_reasons_);
- for (const char* name : names)
- compositing_reasons_json->PushString(name);
- json->SetArray("compositingReasons", std::move(compositing_reasons_json));
- }
- {
- std::unique_ptr<JSONArray> squashing_disallowed_reasons_json =
- JSONArray::Create();
- auto names = debug ? SquashingDisallowedReason::Descriptions(
- squashing_disallowed_reasons_)
- : SquashingDisallowedReason::ShortNames(
- squashing_disallowed_reasons_);
- for (const char* name : names)
- squashing_disallowed_reasons_json->PushString(name);
- json->SetArray("squashingDisallowedReasons",
- std::move(squashing_disallowed_reasons_json));
- }
- }
-
- if (mask_layer_) {
- std::unique_ptr<JSONArray> mask_layer_json = JSONArray::Create();
- mask_layer_json->PushObject(mask_layer_->LayerAsJSONInternal(
- flags, rendering_context_map, mask_layer_->position_));
- json->SetArray("maskLayer", std::move(mask_layer_json));
- }
-
- if (contents_clipping_mask_layer_) {
- std::unique_ptr<JSONArray> contents_clipping_mask_layer_json =
- JSONArray::Create();
- contents_clipping_mask_layer_json->PushObject(
- contents_clipping_mask_layer_->LayerAsJSONInternal(
- flags, rendering_context_map,
- contents_clipping_mask_layer_->position_));
- json->SetArray("contentsClippingMaskLayer",
- std::move(contents_clipping_mask_layer_json));
- }
-
- if (layer_state_ && (flags & (kLayerTreeIncludesDebugInfo |
- kLayerTreeIncludesPaintRecords))) {
- json->SetString("layerState", layer_state_->state.ToString());
- json->SetValue("layerOffset", PointAsJSONArray(layer_state_->offset));
- }
-
-#if DCHECK_IS_ON()
- if (DrawsContent() && (flags & kLayerTreeIncludesPaintRecords))
- json->SetValue("paintRecord", RecordAsJSON(*CapturePaintRecord()));
-#endif
-
- return json;
-}
-
-std::unique_ptr<JSONObject> GraphicsLayer::LayerTreeAsJSONInternal(
- LayerTreeFlags flags,
- RenderingContextMap& rendering_context_map) const {
- std::unique_ptr<JSONObject> json =
- LayerAsJSONInternal(flags, rendering_context_map, position_);
-
- if (children_.size()) {
- std::unique_ptr<JSONArray> children_json = JSONArray::Create();
- for (size_t i = 0; i < children_.size(); i++) {
- children_json->PushObject(
- children_[i]->LayerTreeAsJSONInternal(flags, rendering_context_map));
- }
- json->SetArray("children", std::move(children_json));
- }
-
- return json;
-}
-
-void GraphicsLayer::AddTransformJSONProperties(
- JSONObject& json,
- RenderingContextMap& rendering_context_map) const {
- if (!transform_.IsIdentity())
- json.SetArray("transform", TransformAsJSONArray(transform_));
-
- if (!transform_.IsIdentityOrTranslation())
- json.SetArray("origin", PointAsJSONArray(transform_origin_));
-
- AddFlattenInheritedTransformJSON(json);
-
- if (rendering_context3d_) {
- auto it = rendering_context_map.find(rendering_context3d_);
- int context_id = rendering_context_map.size() + 1;
- if (it == rendering_context_map.end())
- rendering_context_map.Set(rendering_context3d_, context_id);
- else
- context_id = it->value;
-
- json.SetInteger("renderingContext", context_id);
- }
-}
-
-void GraphicsLayer::AddFlattenInheritedTransformJSON(JSONObject& json) const {
- if (Parent() && !Parent()->should_flatten_transform_)
- json.SetBoolean("flattenInheritedTransform", false);
-}
-
-String GraphicsLayer::GetLayerTreeAsTextForTesting(LayerTreeFlags flags) const {
- return LayerTreeAsJSON(flags)->ToPrettyJSONString();
-}
-
String GraphicsLayer::DebugName(cc::Layer* layer) const {
if (layer->id() == contents_layer_id_)
return "ContentsLayer for " + client_.DebugName(this);
@@ -999,8 +644,7 @@ void GraphicsLayer::SetSize(const IntSize& size) {
size_ = clamped_size;
- // Invalidate the layer as a DisplayItemClient.
- SetDisplayItemsUncached();
+ Invalidate(PaintInvalidationReason::kIncremental); // as DisplayItemClient.
layer_->SetBounds(static_cast<gfx::Size>(size_));
// Note that we don't resize m_contentsLayer. It's up the caller to do that.
@@ -1115,7 +759,7 @@ void GraphicsLayer::SetContentsClippingMaskLayer(
cc::Layer* contents_layer = ContentsLayerIfRegistered();
if (!contents_layer)
return;
- cc::Layer* contents_clipping_mask_cc_layer =
+ cc::PictureLayer* contents_clipping_mask_cc_layer =
contents_clipping_mask_layer_ ? contents_clipping_mask_layer_->CcLayer()
: nullptr;
contents_layer->SetMaskLayer(contents_clipping_mask_cc_layer);
@@ -1158,7 +802,7 @@ void GraphicsLayer::SetContentsNeedsDisplay() {
if (cc::Layer* contents_layer = ContentsLayerIfRegistered()) {
contents_layer->SetNeedsDisplay();
TrackRasterInvalidation(*this, contents_rect_,
- PaintInvalidationReason::kFull);
+ PaintInvalidationReason::kFullLayer);
}
}
@@ -1166,33 +810,20 @@ void GraphicsLayer::SetNeedsDisplay() {
if (!DrawsContent())
return;
- // TODO(chrishtr): Stop invalidating the rects once
- // FrameView::paintRecursively() does so.
layer_->SetNeedsDisplay();
for (size_t i = 0; i < link_highlights_.size(); ++i)
link_highlights_[i]->Invalidate();
- GetPaintController().InvalidateAll();
-
- TrackRasterInvalidation(*this, IntRect(IntPoint(), size_),
- PaintInvalidationReason::kFull);
-}
-DISABLE_CFI_PERF
-void GraphicsLayer::SetNeedsDisplayInRect(
- const IntRect& rect,
- PaintInvalidationReason invalidation_reason,
- const DisplayItemClient& client) {
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
- if (!DrawsContent())
- return;
+ GetPaintController().InvalidateAll();
- if (!ScopedSetNeedsDisplayInRectForTrackingOnly::s_enabled_)
- SetNeedsDisplayInRectInternal(rect);
+ if (raster_invalidator_)
+ raster_invalidator_->ClearOldStates();
- TrackRasterInvalidation(client, rect, invalidation_reason);
+ TrackRasterInvalidation(*this, IntRect(IntPoint(), size_),
+ PaintInvalidationReason::kFullLayer);
}
-void GraphicsLayer::SetNeedsDisplayInRectInternal(const IntRect& rect) {
+void GraphicsLayer::SetNeedsDisplayInRect(const IntRect& rect) {
DCHECK(DrawsContent());
layer_->SetNeedsDisplayRect(rect);
@@ -1258,7 +889,7 @@ void GraphicsLayer::SetContentsToImage(
/*prevent_contents_opaque_changes=*/true);
}
-cc::Layer* GraphicsLayer::CcLayer() const {
+cc::PictureLayer* GraphicsLayer::CcLayer() const {
return layer_.get();
}
@@ -1299,16 +930,6 @@ void GraphicsLayer::RemoveLinkHighlight(LinkHighlight* link_highlight) {
UpdateChildList();
}
-void GraphicsLayer::SetScrollableArea(ScrollableArea* scrollable_area) {
- if (scrollable_area_ == scrollable_area)
- return;
- scrollable_area_ = scrollable_area;
-}
-
-void GraphicsLayer::ScrollableAreaDisposed() {
- scrollable_area_.Clear();
-}
-
std::unique_ptr<base::trace_event::TracedValue> GraphicsLayer::TakeDebugInfo(
cc::Layer* layer) {
auto traced_value = std::make_unique<base::trace_event::TracedValue>();
@@ -1340,19 +961,13 @@ std::unique_ptr<base::trace_event::TracedValue> GraphicsLayer::TakeDebugInfo(
}
void GraphicsLayer::DidChangeScrollbarsHiddenIfOverlay(bool hidden) {
- if (scrollable_area_)
- scrollable_area_->SetScrollbarsHiddenIfOverlay(hidden);
+ client_.SetOverlayScrollbarsHidden(hidden);
}
PaintController& GraphicsLayer::GetPaintController() const {
CHECK(DrawsContent());
- if (!paint_controller_) {
+ if (!paint_controller_)
paint_controller_ = PaintController::Create();
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- paint_controller_->SetTracksRasterInvalidations(
- client_.IsTrackingRasterInvalidations());
- }
- }
return *paint_controller_;
}
@@ -1373,24 +988,17 @@ sk_sp<PaintRecord> GraphicsLayer::CapturePaintRecord() const {
if (client_.ShouldThrottleRendering())
return sk_sp<PaintRecord>(new PaintRecord);
- FloatRect bounds(IntRect(IntPoint(0, 0), ExpandedIntSize(Size())));
+ FloatRect bounds(IntRect(IntPoint(), Size()));
GraphicsContext graphics_context(GetPaintController());
graphics_context.BeginRecording(bounds);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- DCHECK(layer_state_) << "No layer state for GraphicsLayer: " << DebugName();
- GetPaintController().GetPaintArtifact().Replay(
- graphics_context, layer_state_->state, layer_state_->offset);
- } else {
- GetPaintController().GetPaintArtifact().Replay(graphics_context,
- PropertyTreeState::Root());
- }
+ DCHECK(layer_state_) << "No layer state for GraphicsLayer: " << DebugName();
+ GetPaintController().GetPaintArtifact().Replay(
+ graphics_context, layer_state_->state, layer_state_->offset);
return graphics_context.EndRecording();
}
void GraphicsLayer::SetLayerState(const PropertyTreeState& layer_state,
const IntPoint& layer_offset) {
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
-
if (!layer_state_) {
layer_state_ =
std::make_unique<LayerState>(LayerState{layer_state, layer_offset});
@@ -1400,6 +1008,17 @@ void GraphicsLayer::SetLayerState(const PropertyTreeState& layer_state,
layer_state_->offset = layer_offset;
}
+void GraphicsLayer::SetContentsLayerState(const PropertyTreeState& layer_state,
+ const IntPoint& layer_offset) {
+ if (!contents_layer_state_) {
+ contents_layer_state_ =
+ std::make_unique<LayerState>(LayerState{layer_state, layer_offset});
+ return;
+ }
+ contents_layer_state_->state = layer_state;
+ contents_layer_state_->offset = layer_offset;
+}
+
scoped_refptr<cc::DisplayItemList> GraphicsLayer::PaintContentsToDisplayList(
PaintingControlSetting painting_control) {
TRACE_EVENT0("blink,benchmark", "GraphicsLayer::PaintContents");
@@ -1436,19 +1055,12 @@ scoped_refptr<cc::DisplayItemList> GraphicsLayer::PaintContentsToDisplayList(
auto display_list = base::MakeRefCounted<cc::DisplayItemList>();
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- DCHECK(layer_state_) << "No layer state for GraphicsLayer: " << DebugName();
- PaintChunksToCcLayer::ConvertInto(
- GetPaintController().PaintChunks(), layer_state_->state,
- gfx::Vector2dF(layer_state_->offset.X(), layer_state_->offset.Y()),
- VisualRectSubpixelOffset(),
- paint_controller.GetPaintArtifact().GetDisplayItemList(),
- *display_list);
- } else {
- paint_controller.GetPaintArtifact().AppendToDisplayItemList(
- FloatSize(OffsetFromLayoutObjectWithSubpixelAccumulation()),
- *display_list);
- }
+ DCHECK(layer_state_) << "No layer state for GraphicsLayer: " << DebugName();
+ PaintChunksToCcLayer::ConvertInto(
+ GetPaintController().PaintChunks(), layer_state_->state,
+ gfx::Vector2dF(layer_state_->offset.X(), layer_state_->offset.Y()),
+ VisualRectSubpixelOffset(),
+ paint_controller.GetPaintArtifact().GetDisplayItemList(), *display_list);
paint_controller.SetDisplayItemConstructionIsDisabled(false);
paint_controller.SetSubsequenceCachingIsDisabled(false);
@@ -1474,29 +1086,4 @@ FloatSize GraphicsLayer::VisualRectSubpixelOffset() const {
return FloatSize();
}
-bool ScopedSetNeedsDisplayInRectForTrackingOnly::s_enabled_ = false;
-
} // namespace blink
-
-#if DCHECK_IS_ON()
-void showGraphicsLayerTree(const blink::GraphicsLayer* layer) {
- if (!layer) {
- LOG(ERROR) << "Cannot showGraphicsLayerTree for (nil).";
- return;
- }
-
- String output = layer->GetLayerTreeAsTextForTesting(0xffffffff);
- LOG(ERROR) << output.Utf8().data();
-}
-
-void showGraphicsLayers(const blink::GraphicsLayer* layer) {
- if (!layer) {
- LOG(ERROR) << "Cannot showGraphicsLayers for (nil).";
- return;
- }
-
- String output = layer->GetLayerTreeAsTextForTesting(
- 0xffffffff & ~blink::kOutputAsLayerTree);
- LOG(ERROR) << output.Utf8().data();
-}
-#endif
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h
index 2108bee42bc..f675e99e840 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer.h
@@ -29,10 +29,13 @@
#include <memory>
+#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "cc/input/overscroll_behavior.h"
+#include "cc/input/scroll_snap_data.h"
#include "cc/layers/content_layer_client.h"
#include "cc/layers/layer_client.h"
+#include "cc/layers/layer_sticky_position_constraint.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
#include "third_party/blink/renderer/platform/geometry/float_point_3d.h"
#include "third_party/blink/renderer/platform/geometry/float_size.h"
@@ -64,13 +67,11 @@ class PictureLayer;
namespace blink {
class CompositorFilterOperations;
-class CompositedLayerRasterInvalidator;
class Image;
-class JSONObject;
class LinkHighlight;
class PaintController;
class RasterInvalidationTracking;
-class ScrollableArea;
+class RasterInvalidator;
typedef Vector<GraphicsLayer*, 64> GraphicsLayerVector;
@@ -79,7 +80,6 @@ typedef Vector<GraphicsLayer*, 64> GraphicsLayerVector;
class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
public DisplayItemClient,
private cc::ContentLayerClient {
- WTF_MAKE_NONCOPYABLE(GraphicsLayer);
USING_FAST_MALLOC(GraphicsLayer);
public:
@@ -95,6 +95,9 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
CompositingReasons GetCompositingReasons() const {
return compositing_reasons_;
}
+ SquashingDisallowedReasons GetSquashingDisallowedReasons() const {
+ return squashing_disallowed_reasons_;
+ }
void SetSquashingDisallowedReasons(SquashingDisallowedReasons reasons) {
squashing_disallowed_reasons_ = reasons;
}
@@ -123,25 +126,13 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
}
void SetContentsClippingMaskLayer(GraphicsLayer*);
- enum ShouldSetNeedsDisplay { kDontSetNeedsDisplay, kSetNeedsDisplay };
-
// The offset is the origin of the layoutObject minus the origin of the
// graphics layer (so either zero or negative).
IntSize OffsetFromLayoutObject() const {
- return FlooredIntSize(offset_from_layout_object_);
- }
- void SetOffsetFromLayoutObject(const IntSize&,
- ShouldSetNeedsDisplay = kSetNeedsDisplay);
- LayoutSize OffsetFromLayoutObjectWithSubpixelAccumulation() const;
-
- // The double version is only used in updateScrollingLayerGeometry() for
- // detecting a scroll offset change at floating point precision.
- DoubleSize OffsetDoubleFromLayoutObject() const {
return offset_from_layout_object_;
}
- void SetOffsetDoubleFromLayoutObject(
- const DoubleSize&,
- ShouldSetNeedsDisplay = kSetNeedsDisplay);
+ void SetOffsetFromLayoutObject(const IntSize&);
+ LayoutSize OffsetFromLayoutObjectWithSubpixelAccumulation() const;
// The position of the layer (the location of its top-left corner in its
// parent).
@@ -163,6 +154,8 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
bool MasksToBounds() const;
void SetMasksToBounds(bool);
+ bool IsRootForIsolatedGroup() const { return is_root_for_isolated_group_; }
+
bool DrawsContent() const { return draws_content_; }
void SetDrawsContent(bool);
@@ -185,9 +178,12 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
bool BackfaceVisibility() const { return backface_visibility_; }
void SetBackfaceVisibility(bool visible);
+ bool ShouldFlattenTransform() const { return should_flatten_transform_; }
+
float Opacity() const { return opacity_; }
void SetOpacity(float);
+ BlendMode GetBlendMode() const { return blend_mode_; }
void SetBlendMode(BlendMode);
void SetIsRootForIsolatedGroup(bool);
@@ -208,11 +204,6 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
void SetPaintingPhase(GraphicsLayerPaintingPhase);
void SetNeedsDisplay();
- // Mark the given rect (in layer coords) as needing display. Never goes deep.
- void SetNeedsDisplayInRect(const IntRect&,
- PaintInvalidationReason,
- const DisplayItemClient&);
-
void SetContentsNeedsDisplay();
// Set that the position/size of the contents (image or video).
@@ -235,7 +226,7 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
cc::Layer* ContentsLayer() const { return contents_layer_; }
// For hosting this GraphicsLayer in a native layer hierarchy.
- cc::Layer* CcLayer() const;
+ cc::PictureLayer* CcLayer() const;
int PaintCount() const { return paint_count_; }
@@ -244,8 +235,6 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
// returned string.
String GetLayerTreeAsTextForTesting(LayerTreeFlags = kLayerTreeNormal) const;
- std::unique_ptr<JSONObject> LayerTreeAsJSON(LayerTreeFlags) const;
-
void UpdateTrackingRasterInvalidations();
void ResetTrackedRasterInvalidations();
bool HasTrackedRasterInvalidations() const;
@@ -260,10 +249,7 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
unsigned NumLinkHighlights() { return link_highlights_.size(); }
LinkHighlight* GetLinkHighlight(int i) { return link_highlights_[i]; }
- void SetScrollableArea(ScrollableArea*);
- ScrollableArea* GetScrollableArea() const { return scrollable_area_; }
-
- void ScrollableAreaDisposed();
+ int GetRenderingContext3D() const { return rendering_context3d_; }
cc::PictureLayer* ContentLayer() const { return layer_.get(); }
@@ -299,12 +285,24 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
void SetIsResizedByBrowserControls(bool);
void SetIsContainerForFixedPositionLayers(bool);
+ bool HasLayerState() const { return layer_state_.get(); }
void SetLayerState(const PropertyTreeState&, const IntPoint& layer_offset);
const PropertyTreeState& GetPropertyTreeState() const {
return layer_state_->state;
}
IntPoint GetOffsetFromTransformNode() const { return layer_state_->offset; }
+ void SetContentsLayerState(const PropertyTreeState&,
+ const IntPoint& layer_offset);
+ const PropertyTreeState& GetContentsPropertyTreeState() const {
+ return contents_layer_state_ ? contents_layer_state_->state
+ : GetPropertyTreeState();
+ }
+ IntPoint GetContentsOffsetFromTransformNode() const {
+ return contents_layer_state_ ? contents_layer_state_->offset
+ : GetOffsetFromTransformNode();
+ }
+
// Capture the last painted result into a PaintRecord. This GraphicsLayer
// must DrawsContent. The result is never nullptr.
sk_sp<PaintRecord> CapturePaintRecord() const;
@@ -313,9 +311,11 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
needs_check_raster_invalidation_ = true;
}
+ bool HasScrollParent() const { return has_scroll_parent_; }
+ bool HasClipParent() const { return has_clip_parent_; }
+
protected:
String DebugName(cc::Layer*) const;
- bool ShouldFlattenTransform() const { return should_flatten_transform_; }
explicit GraphicsLayer(GraphicsLayerClient&);
@@ -359,27 +359,15 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
cc::Layer* ContentsLayerIfRegistered();
void SetContentsLayer(cc::Layer*);
- typedef HashMap<int, int> RenderingContextMap;
- std::unique_ptr<JSONObject> LayerTreeAsJSONInternal(
- LayerTreeFlags,
- RenderingContextMap&) const;
- std::unique_ptr<JSONObject> LayerAsJSONInternal(
- LayerTreeFlags,
- RenderingContextMap&,
- const FloatPoint& position) const;
- void AddTransformJSONProperties(JSONObject&, RenderingContextMap&) const;
- void AddFlattenInheritedTransformJSON(JSONObject&) const;
- class LayersAsJSONArray;
-
- CompositedLayerRasterInvalidator& EnsureRasterInvalidator();
- void SetNeedsDisplayInRectInternal(const IntRect&);
+ RasterInvalidator& EnsureRasterInvalidator();
+ void SetNeedsDisplayInRect(const IntRect&);
FloatSize VisualRectSubpixelOffset() const;
GraphicsLayerClient& client_;
// Offset from the owning layoutObject
- DoubleSize offset_from_layout_object_;
+ IntSize offset_from_layout_object_;
// Position is relative to the parent GraphicsLayer
FloatPoint position_;
@@ -436,7 +424,6 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
Vector<LinkHighlight*> link_highlights_;
- WeakPersistent<ScrollableArea> scrollable_area_;
int rendering_context3d_;
CompositingReasons compositing_reasons_ = CompositingReason::kNone;
@@ -453,38 +440,17 @@ class PLATFORM_EXPORT GraphicsLayer : public cc::LayerClient,
IntPoint offset;
};
std::unique_ptr<LayerState> layer_state_;
+ std::unique_ptr<LayerState> contents_layer_state_;
- std::unique_ptr<CompositedLayerRasterInvalidator> raster_invalidator_;
+ std::unique_ptr<RasterInvalidator> raster_invalidator_;
base::WeakPtrFactory<GraphicsLayer> weak_ptr_factory_;
FRIEND_TEST_ALL_PREFIXES(CompositingLayerPropertyUpdaterTest, MaskLayerState);
-};
-// ObjectPaintInvalidatorWithContext::InvalidatePaintRectangleWithContext uses
-// this to reduce differences between layout test results of SPv1 and SPv2.
-class PLATFORM_EXPORT ScopedSetNeedsDisplayInRectForTrackingOnly {
- public:
- ScopedSetNeedsDisplayInRectForTrackingOnly() {
- DCHECK(!s_enabled_);
- s_enabled_ = true;
- }
- ~ScopedSetNeedsDisplayInRectForTrackingOnly() {
- DCHECK(s_enabled_);
- s_enabled_ = false;
- }
-
- private:
- friend class GraphicsLayer;
- static bool s_enabled_;
+ DISALLOW_COPY_AND_ASSIGN(GraphicsLayer);
};
} // namespace blink
-#if DCHECK_IS_ON()
-// Outside the blink namespace for ease of invocation from gdb.
-void PLATFORM_EXPORT showGraphicsLayerTree(const blink::GraphicsLayer*);
-void PLATFORM_EXPORT showGraphicsLayers(const blink::GraphicsLayer*);
-#endif
-
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_GRAPHICS_LAYER_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_client.h b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_client.h
index 11e38dc4927..7561489f69c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_client.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_client.h
@@ -35,6 +35,7 @@ namespace blink {
class GraphicsContext;
class GraphicsLayer;
class IntRect;
+class ScrollableArea;
enum GraphicsLayerPaintingPhaseFlags {
kGraphicsLayerPaintBackground = (1 << 0),
@@ -94,8 +95,15 @@ class PLATFORM_EXPORT GraphicsLayerClient {
virtual bool IsTrackingRasterInvalidations() const { return false; }
+ virtual void SetOverlayScrollbarsHidden(bool) {}
+
virtual String DebugName(const GraphicsLayer*) const = 0;
+ virtual const ScrollableArea* GetScrollableAreaForTesting(
+ const GraphicsLayer*) const {
+ return nullptr;
+ }
+
#if DCHECK_IS_ON()
// CompositedLayerMapping overrides this to verify that it is not
// currently painting contents. An ASSERT fails, if it is.
diff --git a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc
index 0f9b03a07da..b4aaadae26a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/graphics_layer_test.cc
@@ -28,10 +28,11 @@
#include <memory>
#include <utility>
-#include "cc/layers/layer.h"
+#include "cc/layers/picture_layer.h"
+#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/mutator_host.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/web_layer_tree_view.h"
#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_client.h"
@@ -44,14 +45,12 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h"
#include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h"
#include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
-#include "third_party/blink/renderer/platform/graphics/test/fake_scrollable_area.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
-#include "third_party/blink/renderer/platform/scroll/scrollable_area.h"
#include "third_party/blink/renderer/platform/testing/fake_graphics_layer.h"
#include "third_party/blink/renderer/platform/testing/fake_graphics_layer_client.h"
+#include "third_party/blink/renderer/platform/testing/layer_tree_host_embedder.h"
#include "third_party/blink/renderer/platform/testing/paint_property_test_helpers.h"
#include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
-#include "third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.h"
#include "third_party/blink/renderer/platform/transforms/matrix_3d_transform_operation.h"
#include "third_party/blink/renderer/platform/transforms/rotate_transform_operation.h"
#include "third_party/blink/renderer/platform/transforms/translate_transform_operation.h"
@@ -71,42 +70,44 @@ class GraphicsLayerTest : public testing::Test, public PaintTestConfigurations {
page_scale_layer_->AddChild(graphics_layer_.get());
graphics_layer_->CcLayer()->SetScrollable(clip_layer_->CcLayer()->bounds());
cc_layer_ = graphics_layer_->CcLayer();
- layer_tree_view_ = std::make_unique<WebLayerTreeViewImplForTesting>();
- DCHECK(layer_tree_view_);
- layer_tree_view_->SetRootLayer(clip_layer_->CcLayer());
- WebLayerTreeView::ViewportLayers viewport_layers;
+ layer_tree_ = std::make_unique<LayerTreeHostEmbedder>();
+ layer_tree_->layer_tree_host()->SetRootLayer(clip_layer_->CcLayer());
+ cc::LayerTreeHost::ViewportLayers viewport_layers;
viewport_layers.overscroll_elasticity = scroll_elasticity_layer_->CcLayer();
viewport_layers.page_scale = page_scale_layer_->CcLayer();
viewport_layers.inner_viewport_container = clip_layer_->CcLayer();
viewport_layers.inner_viewport_scroll = graphics_layer_->CcLayer();
- layer_tree_view_->RegisterViewportLayers(viewport_layers);
- layer_tree_view_->SetViewportSize(WebSize(1, 1));
+ layer_tree_->layer_tree_host()->RegisterViewportLayers(viewport_layers);
+ layer_tree_->layer_tree_host()->SetViewportSizeAndScale(
+ gfx::Size(1, 1), /*device_scale_factor=*/1.f, viz::LocalSurfaceId());
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- graphics_layer_->SetLayerState(
- PropertyTreeState(PropertyTreeState::Root()), IntPoint());
- }
+ graphics_layer_->SetLayerState(PropertyTreeState(PropertyTreeState::Root()),
+ IntPoint());
}
- ~GraphicsLayerTest() override {
- graphics_layer_.reset();
- layer_tree_view_.reset();
- }
+ ~GraphicsLayerTest() = default;
- WebLayerTreeView* LayerTreeView() { return layer_tree_view_.get(); }
+ cc::LayerTreeHost* layer_tree_host() {
+ return layer_tree_->layer_tree_host();
+ }
+ cc::AnimationHost* animation_host() { return layer_tree_->animation_host(); }
protected:
bool PaintWithoutCommit(GraphicsLayer& layer, const IntRect* interest_rect) {
return layer.PaintWithoutCommit(interest_rect);
}
- const CompositedLayerRasterInvalidator* GetInternalRasterInvalidator(
+ void CommitAndFinishCycle(GraphicsLayer& layer) {
+ layer.GetPaintController().CommitNewDisplayItems();
+ layer.GetPaintController().FinishCycle();
+ }
+
+ const RasterInvalidator* GetInternalRasterInvalidator(
const GraphicsLayer& layer) {
return layer.raster_invalidator_.get();
}
- CompositedLayerRasterInvalidator& EnsureRasterInvalidator(
- GraphicsLayer& layer) {
+ RasterInvalidator& EnsureRasterInvalidator(GraphicsLayer& layer) {
return layer.EnsureRasterInvalidator();
}
@@ -123,13 +124,12 @@ class GraphicsLayerTest : public testing::Test, public PaintTestConfigurations {
FakeGraphicsLayerClient client_;
private:
- std::unique_ptr<WebLayerTreeViewImplForTesting> layer_tree_view_;
+ std::unique_ptr<LayerTreeHostEmbedder> layer_tree_;
};
INSTANTIATE_TEST_CASE_P(All,
GraphicsLayerTest,
testing::Values(0,
- kSlimmingPaintV175,
kBlinkGenPropertyTrees));
class AnimationForTesting : public CompositorAnimationClient {
@@ -146,7 +146,15 @@ class AnimationForTesting : public CompositorAnimationClient {
};
TEST_P(GraphicsLayerTest, updateLayerShouldFlattenTransformWithAnimations) {
- ASSERT_FALSE(cc_layer_->HasTickingAnimationForTesting());
+ // TODO(bokan): This test doesn't yet work in blink-gen-property-trees
+ // because cc::Layers can't set an element id in that mode. We fail at
+ // AttachElement since the element id is invalid. https://crbug.com/836897.
+ if (RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled())
+ return;
+
+ cc::MutatorHost* mutator = layer_tree_host()->mutator_host();
+ EXPECT_FALSE(
+ mutator->HasTickingKeyframeModelForTesting(cc_layer_->element_id()));
std::unique_ptr<CompositorFloatAnimationCurve> curve =
CompositorFloatAnimationCurve::Create();
@@ -163,7 +171,7 @@ TEST_P(GraphicsLayerTest, updateLayerShouldFlattenTransformWithAnimations) {
CompositorAnimationTimeline::Create();
AnimationForTesting animation;
- CompositorAnimationHost host(LayerTreeView()->CompositorAnimationHost());
+ CompositorAnimationHost host(animation_host());
host.AddTimeline(*compositor_timeline);
compositor_timeline->AnimationAttached(animation);
@@ -176,23 +184,27 @@ TEST_P(GraphicsLayerTest, updateLayerShouldFlattenTransformWithAnimations) {
animation.GetCompositorAnimation()->AddKeyframeModel(
std::move(float_keyframe_model));
- ASSERT_TRUE(cc_layer_->HasTickingAnimationForTesting());
+ EXPECT_TRUE(
+ mutator->HasTickingKeyframeModelForTesting(cc_layer_->element_id()));
graphics_layer_->SetShouldFlattenTransform(false);
cc_layer_ = graphics_layer_->CcLayer();
ASSERT_TRUE(cc_layer_);
- ASSERT_TRUE(cc_layer_->HasTickingAnimationForTesting());
+ EXPECT_TRUE(
+ mutator->HasTickingKeyframeModelForTesting(cc_layer_->element_id()));
animation.GetCompositorAnimation()->RemoveKeyframeModel(keyframe_model_id);
- ASSERT_FALSE(cc_layer_->HasTickingAnimationForTesting());
+ EXPECT_FALSE(
+ mutator->HasTickingKeyframeModelForTesting(cc_layer_->element_id()));
graphics_layer_->SetShouldFlattenTransform(true);
cc_layer_ = graphics_layer_->CcLayer();
ASSERT_TRUE(cc_layer_);
- ASSERT_FALSE(cc_layer_->HasTickingAnimationForTesting());
+ EXPECT_FALSE(
+ mutator->HasTickingKeyframeModelForTesting(cc_layer_->element_id()));
animation.GetCompositorAnimation()->DetachElement();
ASSERT_FALSE(animation.GetCompositorAnimation()->IsElementAttached());
@@ -204,36 +216,33 @@ TEST_P(GraphicsLayerTest, updateLayerShouldFlattenTransformWithAnimations) {
TEST_P(GraphicsLayerTest, Paint) {
IntRect interest_rect(1, 2, 3, 4);
EXPECT_TRUE(PaintWithoutCommit(*graphics_layer_, &interest_rect));
- graphics_layer_->GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle(*graphics_layer_);
client_.SetNeedsRepaint(true);
EXPECT_TRUE(PaintWithoutCommit(*graphics_layer_, &interest_rect));
- graphics_layer_->GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle(*graphics_layer_);
client_.SetNeedsRepaint(false);
EXPECT_FALSE(PaintWithoutCommit(*graphics_layer_, &interest_rect));
interest_rect.Move(IntSize(10, 20));
EXPECT_TRUE(PaintWithoutCommit(*graphics_layer_, &interest_rect));
- graphics_layer_->GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle(*graphics_layer_);
EXPECT_FALSE(PaintWithoutCommit(*graphics_layer_, &interest_rect));
graphics_layer_->SetNeedsDisplay();
EXPECT_TRUE(PaintWithoutCommit(*graphics_layer_, &interest_rect));
- graphics_layer_->GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle(*graphics_layer_);
EXPECT_FALSE(PaintWithoutCommit(*graphics_layer_, &interest_rect));
}
TEST_P(GraphicsLayerTest, PaintRecursively) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
IntRect interest_rect(1, 2, 3, 4);
- auto* transform_root = TransformPaintPropertyNode::Root();
+ const auto& transform_root = TransformPaintPropertyNode::Root();
auto transform1 =
CreateTransform(transform_root, TransformationMatrix().Translate(10, 20));
auto transform2 =
- CreateTransform(transform1, TransformationMatrix().Scale(2));
+ CreateTransform(*transform1, TransformationMatrix().Scale(2));
client_.SetPainter([&](const GraphicsLayer* layer, GraphicsContext& context,
GraphicsLayerPaintingPhase, const IntRect&) {
@@ -256,13 +265,13 @@ TEST_P(GraphicsLayerTest, PaintRecursively) {
transform1->Update(transform_root,
TransformPaintPropertyNode::State{
TransformationMatrix().Translate(20, 30)});
- EXPECT_TRUE(transform1->Changed(*transform_root));
- EXPECT_TRUE(transform2->Changed(*transform_root));
+ EXPECT_TRUE(transform1->Changed(transform_root));
+ EXPECT_TRUE(transform2->Changed(transform_root));
client_.SetNeedsRepaint(true);
graphics_layer_->PaintRecursively();
- EXPECT_FALSE(transform1->Changed(*transform_root));
- EXPECT_FALSE(transform2->Changed(*transform_root));
+ EXPECT_FALSE(transform1->Changed(transform_root));
+ EXPECT_FALSE(transform2->Changed(transform_root));
}
TEST_P(GraphicsLayerTest, SetDrawsContentFalse) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image.cc b/chromium/third_party/blink/renderer/platform/graphics/image.cc
index f803141e166..883b046672e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/image.cc
@@ -26,10 +26,12 @@
#include "third_party/blink/renderer/platform/graphics/image.h"
+#include "base/numerics/checked_math.h"
#include "build/build_config.h"
#include "cc/tiles/software_image_decode_cache.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_data.h"
+#include "third_party/blink/renderer/platform/drag_image.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/float_size.h"
@@ -46,7 +48,6 @@
#include "third_party/blink/renderer/platform/length.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/skia/include/core/SkImage.h"
@@ -115,45 +116,68 @@ String Image::FilenameExtension() const {
return String();
}
+// TODO(schenney): Lift this code, with the calculations for subsetting the
+// image and the like, up the stack into a BackgroundPainter.
void Image::DrawTiledBackground(GraphicsContext& ctxt,
- const FloatRect& dest_rect,
- const FloatPoint& src_point,
- const FloatSize& scaled_tile_size,
+ const FloatSize& unsnapped_subset_size,
+ const FloatRect& snapped_paint_rect,
+ const FloatPoint& phase,
+ const FloatSize& tile_size,
SkBlendMode op,
const FloatSize& repeat_spacing) {
- if (scaled_tile_size.IsEmpty())
+ if (tile_size.IsEmpty())
return;
+ // Use the intrinsic size of the image if it has one, otherwise force the
+ // generated image to be the tile size.
FloatSize intrinsic_tile_size(Size());
+ FloatSize scale(1, 1);
if (HasRelativeSize()) {
- intrinsic_tile_size.SetWidth(scaled_tile_size.Width());
- intrinsic_tile_size.SetHeight(scaled_tile_size.Height());
+ intrinsic_tile_size.SetWidth(tile_size.Width());
+ intrinsic_tile_size.SetHeight(tile_size.Height());
+ } else {
+ scale = FloatSize(tile_size.Width() / intrinsic_tile_size.Width(),
+ tile_size.Height() / intrinsic_tile_size.Height());
}
- const FloatSize scale(
- scaled_tile_size.Width() / intrinsic_tile_size.Width(),
- scaled_tile_size.Height() / intrinsic_tile_size.Height());
-
- const FloatRect one_tile_rect = ComputeTileContaining(
- dest_rect.Location(), scaled_tile_size, src_point, repeat_spacing);
+ const FloatRect one_tile_rect = ComputePhaseForBackground(
+ snapped_paint_rect.Location(), tile_size, phase, repeat_spacing);
// Check and see if a single draw of the image can cover the entire area we
- // are supposed to tile.
- if (one_tile_rect.Contains(dest_rect)) {
- const FloatRect visible_src_rect =
- ComputeSubsetForTile(one_tile_rect, dest_rect, intrinsic_tile_size);
- ctxt.DrawImage(this, kSyncDecode, dest_rect, &visible_src_rect, op,
+ // are supposed to tile. The dest_rect_for_subset must use the same
+ // location that was used in ComputePhaseForBackground and the unsnapped
+ // destination rect in order to correctly evaluate the subset size and
+ // location in the presence of border snapping and zoom.
+ FloatRect dest_rect_for_subset(snapped_paint_rect.Location(),
+ unsnapped_subset_size);
+ if (one_tile_rect.Contains(dest_rect_for_subset)) {
+ FloatRect visible_src_rect = ComputeSubsetForBackground(
+ one_tile_rect, dest_rect_for_subset, intrinsic_tile_size);
+ // Round to avoid filtering pulling in neighboring pixels, for the
+ // common case of sprite maps.
+ // TODO(schenney): Snapping at this level is a problem for cases where we
+ // might be animating background-position to pan over an image. Ideally we
+ // would either snap only if close to integral, or move snapping
+ // calculations up the stack.
+ visible_src_rect = FloatRect(RoundedIntRect(visible_src_rect));
+ ctxt.DrawImage(this, kSyncDecode, snapped_paint_rect, &visible_src_rect, op,
kDoNotRespectImageOrientation);
return;
}
+ // Note that this tile rect the image's pre-scaled size.
FloatRect tile_rect(FloatPoint(), intrinsic_tile_size);
- DrawPattern(ctxt, tile_rect, scale, one_tile_rect.Location(), op, dest_rect,
- repeat_spacing);
+ // This call takes the unscaled image, applies the given scale, and paints
+ // it into the snapped_dest_rect using phase from one_tile_rect and the
+ // given repeat spacing. Note the phase is already scaled.
+ DrawPattern(ctxt, tile_rect, scale, one_tile_rect.Location(), op,
+ snapped_paint_rect, repeat_spacing);
StartAnimation();
}
+// TODO(schenney): Lift this code, with the calculations for subsetting the
+// image and the like, up the stack into a border painting class.
void Image::DrawTiledBorder(GraphicsContext& ctxt,
const FloatRect& dst_rect,
const FloatRect& src_rect,
@@ -269,7 +293,7 @@ sk_sp<PaintShader> CreatePatternShader(const PaintImage& image,
image.height() + spacing.Height());
PaintRecorder recorder;
- PaintCanvas* canvas = recorder.beginRecording(tile_rect);
+ cc::PaintCanvas* canvas = recorder.beginRecording(tile_rect);
canvas->drawImage(image, 0, 0, &paint);
return PaintShader::MakePaintRecord(recorder.finishRecordingAsPicture(),
@@ -289,49 +313,53 @@ SkShader::TileMode ComputeTileMode(float left,
void Image::DrawPattern(GraphicsContext& context,
const FloatRect& float_src_rect,
- const FloatSize& scale,
+ const FloatSize& scale_src_to_dest,
const FloatPoint& phase,
SkBlendMode composite_op,
const FloatRect& dest_rect,
const FloatSize& repeat_spacing) {
TRACE_EVENT0("skia", "Image::drawPattern");
+ if (dest_rect.IsEmpty())
+ return; // nothing to draw
+
PaintImage image = PaintImageForCurrentFrame();
if (!image)
- return;
-
- FloatRect norm_src_rect = float_src_rect;
+ return; // nothing to draw
- norm_src_rect.Intersect(FloatRect(0, 0, image.width(), image.height()));
- if (dest_rect.IsEmpty() || norm_src_rect.IsEmpty())
+ // The subset_rect is in source image space, unscaled.
+ IntRect subset_rect = EnclosingIntRect(float_src_rect);
+ subset_rect.Intersect(IntRect(0, 0, image.width(), image.height()));
+ if (subset_rect.IsEmpty())
return; // nothing to draw
SkMatrix local_matrix;
// We also need to translate it such that the origin of the pattern is the
- // origin of the destination rect, which is what WebKit expects. Skia uses
- // the coordinate system origin as the base for the pattern. If WebKit wants
+ // origin of the destination rect, which is what Blink expects. Skia uses
+ // the coordinate system origin as the base for the pattern. If Blink wants
// a shifted image, it will shift it from there using the localMatrix.
- const float adjusted_x = phase.X() + norm_src_rect.X() * scale.Width();
- const float adjusted_y = phase.Y() + norm_src_rect.Y() * scale.Height();
+ const float adjusted_x =
+ phase.X() + subset_rect.X() * scale_src_to_dest.Width();
+ const float adjusted_y =
+ phase.Y() + subset_rect.Y() * scale_src_to_dest.Height();
local_matrix.setTranslate(SkFloatToScalar(adjusted_x),
SkFloatToScalar(adjusted_y));
- // Because no resizing occurred, the shader transform should be
- // set to the pattern's transform, which just includes scale.
- local_matrix.preScale(scale.Width(), scale.Height());
+ // Apply the scale to have the subset correctly fill the destination.
+ local_matrix.preScale(scale_src_to_dest.Width(), scale_src_to_dest.Height());
// Fetch this now as subsetting may swap the image.
auto image_id = image.GetSkImage()->uniqueID();
image = PaintImageBuilder::WithCopy(std::move(image))
- .make_subset(EnclosingIntRect(norm_src_rect))
+ .make_subset(subset_rect)
.TakePaintImage();
if (!image)
return;
const FloatSize tile_size(
- image.width() * scale.Width() + repeat_spacing.Width(),
- image.height() * scale.Height() + repeat_spacing.Height());
+ image.width() * scale_src_to_dest.Width() + repeat_spacing.Width(),
+ image.height() * scale_src_to_dest.Height() + repeat_spacing.Height());
const auto tmx = ComputeTileMode(dest_rect.X(), dest_rect.MaxX(), adjusted_x,
adjusted_x + tile_size.Width());
const auto tmy = ComputeTileMode(dest_rect.Y(), dest_rect.MaxY(), adjusted_y,
@@ -341,13 +369,13 @@ void Image::DrawPattern(GraphicsContext& context,
flags.setColor(SK_ColorBLACK);
flags.setBlendMode(composite_op);
flags.setFilterQuality(
- context.ComputeFilterQuality(this, dest_rect, norm_src_rect));
+ context.ComputeFilterQuality(this, dest_rect, FloatRect(subset_rect)));
flags.setAntiAlias(context.ShouldAntialias());
- flags.setShader(
- CreatePatternShader(image, local_matrix, flags,
- FloatSize(repeat_spacing.Width() / scale.Width(),
- repeat_spacing.Height() / scale.Height()),
- tmx, tmy));
+ flags.setShader(CreatePatternShader(
+ image, local_matrix, flags,
+ FloatSize(repeat_spacing.Width() / scale_src_to_dest.Width(),
+ repeat_spacing.Height() / scale_src_to_dest.Height()),
+ tmx, tmy));
// If the shader could not be instantiated (e.g. non-invertible matrix),
// draw transparent.
// Note: we can't simply bail, because of arbitrary blend mode.
@@ -395,32 +423,55 @@ bool Image::ApplyShader(PaintFlags& flags, const SkMatrix& local_matrix) {
return true;
}
-FloatRect Image::ComputeTileContaining(const FloatPoint& point,
- const FloatSize& tile_size,
- const FloatPoint& tile_phase,
- const FloatSize& tile_spacing) {
- const FloatSize actual_tile_size(tile_size + tile_spacing);
+FloatRect Image::ComputePhaseForBackground(const FloatPoint& destination_offset,
+ const FloatSize& size,
+ const FloatPoint& phase,
+ const FloatSize& spacing) {
+ const FloatSize step_per_tile(size + spacing);
return FloatRect(
- FloatPoint(point.X() + fmodf(-tile_phase.X(), actual_tile_size.Width()),
- point.Y() + fmodf(-tile_phase.Y(), actual_tile_size.Height())),
- tile_size);
+ FloatPoint(
+ destination_offset.X() + fmodf(-phase.X(), step_per_tile.Width()),
+ destination_offset.Y() + fmodf(-phase.Y(), step_per_tile.Height())),
+ size);
}
-FloatRect Image::ComputeSubsetForTile(const FloatRect& tile,
- const FloatRect& dest,
- const FloatSize& image_size) {
- DCHECK(tile.Contains(dest));
+FloatRect Image::ComputeSubsetForBackground(const FloatRect& phase_and_size,
+ const FloatRect& subset,
+ const FloatSize& intrinsic_size) {
+ // TODO(schenney): Re-enable this after determining why it fails for
+ // SPv2, and maybe other cases.
+ // DCHECK(phase_and_size.Contains(subset));
+
+ const FloatSize scale(phase_and_size.Width() / intrinsic_size.Width(),
+ phase_and_size.Height() / intrinsic_size.Height());
+ return FloatRect((subset.X() - phase_and_size.X()) / scale.Width(),
+ (subset.Y() - phase_and_size.Y()) / scale.Height(),
+ subset.Width() / scale.Width(),
+ subset.Height() / scale.Height());
+}
- const FloatSize scale(tile.Width() / image_size.Width(),
- tile.Height() / image_size.Height());
+SkBitmap Image::AsSkBitmapForCurrentFrame(
+ RespectImageOrientationEnum should_respect_image_orientation) {
+ PaintImage paint_image = PaintImageForCurrentFrame();
+ if (!paint_image)
+ return {};
+
+ if (should_respect_image_orientation == kRespectImageOrientation &&
+ IsBitmapImage()) {
+ ImageOrientation orientation =
+ ToBitmapImage(this)->CurrentFrameOrientation();
+ paint_image = DragImage::ResizeAndOrientImage(paint_image, orientation);
+ if (!paint_image)
+ return {};
+ }
- FloatRect subset = dest;
- subset.SetX((dest.X() - tile.X()) / scale.Width());
- subset.SetY((dest.Y() - tile.Y()) / scale.Height());
- subset.SetWidth(dest.Width() / scale.Width());
- subset.SetHeight(dest.Height() / scale.Height());
+ sk_sp<SkImage> sk_image = paint_image.GetSkImage();
+ if (!sk_image)
+ return {};
- return subset;
+ SkBitmap bitmap;
+ sk_image->asLegacyBitmap(&bitmap);
+ return bitmap;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image.h b/chromium/third_party/blink/renderer/platform/graphics/image.h
index 35e9e3f431e..7524079f269 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/image.h
@@ -27,6 +27,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_IMAGE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_IMAGE_H_
+#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
@@ -39,7 +40,6 @@
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
#include "third_party/skia/include/core/SkRefCnt.h"
@@ -47,9 +47,9 @@
class SkMatrix;
namespace cc {
-class ImageDecodeCache;
class PaintCanvas;
class PaintFlags;
+class ImageDecodeCache;
} // namespace cc
namespace blink {
@@ -63,15 +63,11 @@ class KURL;
class WebGraphicsContext3DProvider;
class WebGraphicsContext3DProviderWrapper;
-using cc::PaintCanvas;
-using cc::PaintFlags;
-
class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
friend class GeneratedImage;
friend class CrossfadeGeneratedImage;
friend class GradientGeneratedImage;
friend class GraphicsContext;
- WTF_MAKE_NONCOPYABLE(Image);
public:
virtual ~Image();
@@ -203,15 +199,15 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
kDoNotClampImageToSourceRect
};
- virtual void Draw(PaintCanvas*,
- const PaintFlags&,
+ virtual void Draw(cc::PaintCanvas*,
+ const cc::PaintFlags&,
const FloatRect& dst_rect,
const FloatRect& src_rect,
RespectImageOrientationEnum,
ImageClampingMode,
ImageDecodingMode) = 0;
- virtual bool ApplyShader(PaintFlags&, const SkMatrix& local_matrix);
+ virtual bool ApplyShader(cc::PaintFlags&, const SkMatrix& local_matrix);
// Use ContextProvider() for immediate use only, use
// ContextProviderWrapper() to obtain a retainable reference. Note:
@@ -224,20 +220,32 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
return nullptr;
}
- // Compute the tile which contains a given point (assuming a repeating tile
- // grid). The point and returned value are in destination grid space.
- static FloatRect ComputeTileContaining(const FloatPoint&,
- const FloatSize& tile_size,
- const FloatPoint& tile_phase,
- const FloatSize& tile_spacing);
-
- // Compute the image subset which gets mapped onto |dest|, when the whole
- // image is drawn into |tile|. Assumes |tile| contains |dest|. The tile rect
- // is in destination grid space while the return value is in image coordinate
- // space.
- static FloatRect ComputeSubsetForTile(const FloatRect& tile,
- const FloatRect& dest,
- const FloatSize& image_size);
+ // Given the |size| that the whole image should draw at, and the
+ // input phase requested by the content, and the space between repeated tiles,
+ // return a rectangle with |size| and a location that respects
+ // the phase but is no more than one size + space in magnitude. In practice,
+ // this means that if there is no repeating the returned rect would contain
+ // the destination_offset location. The destination_offset passed here must
+ // exactly match the location of the subset in a following call to
+ // ComputeSubsetForBackground.
+ static FloatRect ComputePhaseForBackground(
+ const FloatPoint& destination_offset,
+ const FloatSize& size,
+ const FloatPoint& phase,
+ const FloatSize& spacing);
+
+ // Compute the image subset, in intrinsic image coordinates, that gets mapped
+ // onto the |subset|, when the whole image would be drawn with phase
+ // and size given by |phase_and_size|. Assumes
+ // |phase_and_size| contains |subset|. The location
+ // of the requested subset should be the painting snapped location, or
+ // whatever was used as a destination_offset in ComputePhaseForBackground.
+ // It is used to undo the offset added in ComputePhaseForBackground. The size
+ // of requested subset should be the unsnapped size so that the computed
+ // scale and location in the source image can be correctly determined.
+ static FloatRect ComputeSubsetForBackground(const FloatRect& phase_and_size,
+ const FloatRect& subset,
+ const FloatSize& intrinsic_size);
virtual sk_sp<PaintRecord> PaintRecordForContainer(
const KURL& url,
@@ -261,15 +269,28 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
PaintImage::Id paint_image_id() const { return stable_image_id_; }
+ // Returns an SkBitmap that is a copy of the image's current frame.
+ SkBitmap AsSkBitmapForCurrentFrame(RespectImageOrientationEnum);
+
protected:
Image(ImageObserver* = nullptr, bool is_multipart = false);
+ // The unsnapped_subset_size should be the target painting area implied by the
+ // content, without any snapping applied. It is necessary to correctly
+ // compute the subset of the source image to paint into the destination.
+ // The snapped_paint_rect should be the target destination for painting into.
+ // The phase is never snapped.
+ // The tile_size is the total image size. The mapping from this size
+ // to the unsnapped_dest_rect size defines the scaling of the image for
+ // sprite computation.
void DrawTiledBackground(GraphicsContext&,
- const FloatRect& dst_rect,
- const FloatPoint& src_point,
+ const FloatSize& unsnapped_subset_size,
+ const FloatRect& snapped_paint_rect,
+ const FloatPoint& phase,
const FloatSize& tile_size,
SkBlendMode,
const FloatSize& repeat_spacing);
+
void DrawTiledBorder(GraphicsContext&,
const FloatRect& dst_rect,
const FloatRect& src_rect,
@@ -307,6 +328,8 @@ class PLATFORM_EXPORT Image : public ThreadSafeRefCounted<Image> {
PaintImage::Id stable_image_id_;
const bool is_multipart_;
HighContrastClassification high_contrast_classification_;
+
+ DISALLOW_COPY_AND_ASSIGN(Image);
};
#define DEFINE_IMAGE_TYPE_CASTS(typeName) \
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image_data_buffer.cc b/chromium/third_party/blink/renderer/platform/graphics/image_data_buffer.cc
index 40687fdf81f..c3d7df4e8cb 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image_data_buffer.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/image_data_buffer.cc
@@ -133,14 +133,6 @@ bool ImageDataBuffer::EncodeImageInternal(const String& mime_type,
SkJpegEncoder::Options options;
options.fQuality = ImageEncoder::ComputeJpegQuality(quality);
options.fAlphaOption = SkJpegEncoder::AlphaOption::kBlendOnBlack;
- // When the gamma is linear (which is always the case with currently
- // supported color spaces in F16 format), it does not matter whether we use
- // kRespect or kIgnore, but the JPEG encoder does not support kIgnore with
- // F16 for some reason, so we switch to kRespect in that case, with no
- // consequence on the encoded output.
- options.fBlendBehavior = pixmap.colorType() == kRGBA_F16_SkColorType
- ? SkTransferFunctionBehavior::kRespect
- : SkTransferFunctionBehavior::kIgnore;
if (options.fQuality == 100) {
options.fDownsample = SkJpegEncoder::Downsample::k444;
}
@@ -148,8 +140,7 @@ bool ImageDataBuffer::EncodeImageInternal(const String& mime_type,
}
if (mime_type == "image/webp") {
- SkWebpEncoder::Options options = ImageEncoder::ComputeWebpOptions(
- quality, SkTransferFunctionBehavior::kIgnore);
+ SkWebpEncoder::Options options = ImageEncoder::ComputeWebpOptions(quality);
return ImageEncoder::Encode(encoded_image, pixmap, options);
}
@@ -157,7 +148,6 @@ bool ImageDataBuffer::EncodeImageInternal(const String& mime_type,
SkPngEncoder::Options options;
options.fFilterFlags = SkPngEncoder::FilterFlag::kSub;
options.fZLibLevel = 3;
- options.fUnpremulBehavior = SkTransferFunctionBehavior::kIgnore;
return ImageEncoder::Encode(encoded_image, pixmap, options);
}
@@ -173,8 +163,7 @@ String ImageDataBuffer::ToDataURL(const String& mime_type,
if (pixmap.colorSpace()) {
if (!pixmap.colorSpace()->isSRGB()) {
skia_image = SkImage::MakeFromRaster(pixmap, nullptr, nullptr);
- skia_image = skia_image->makeColorSpace(
- SkColorSpace::MakeSRGB(), SkTransferFunctionBehavior::kIgnore);
+ skia_image = skia_image->makeColorSpace(SkColorSpace::MakeSRGB());
skia_image->peekPixels(&pixmap);
}
pixmap.setColorSpace(nullptr);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image_decoding_store.h b/chromium/third_party/blink/renderer/platform/graphics/image_decoding_store.h
index 3ea28831cc8..77cd5bf9c17 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image_decoding_store.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/image_decoding_store.h
@@ -31,6 +31,7 @@
#include "SkSize.h"
#include "SkTypes.h"
+#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/platform/graphics/image_frame_generator.h"
#include "third_party/blink/renderer/platform/graphics/skia/sk_size_hash.h"
@@ -72,7 +73,6 @@ static inline bool operator!=(const DecoderCacheKey& a,
// Base class for all cache entries.
class CacheEntry : public DoublyLinkedListNode<CacheEntry> {
USING_FAST_MALLOC(CacheEntry);
- WTF_MAKE_NONCOPYABLE(CacheEntry);
friend class WTF::DoublyLinkedListNode<CacheEntry>;
public:
@@ -108,6 +108,8 @@ class CacheEntry : public DoublyLinkedListNode<CacheEntry> {
private:
CacheEntry* prev_;
CacheEntry* next_;
+
+ DISALLOW_COPY_AND_ASSIGN(CacheEntry);
};
class DecoderCacheEntry final : public CacheEntry {
@@ -231,7 +233,6 @@ namespace blink {
class PLATFORM_EXPORT ImageDecodingStore final {
USING_FAST_MALLOC(ImageDecodingStore);
- WTF_MAKE_NONCOPYABLE(ImageDecodingStore);
public:
static std::unique_ptr<ImageDecodingStore> Create() {
@@ -332,6 +333,8 @@ class PLATFORM_EXPORT ImageDecodingStore final {
// This mutex also protects calls to underlying skBitmap's
// lockPixels()/unlockPixels() as they are not threadsafe.
Mutex mutex_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImageDecodingStore);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image_frame_generator.cc b/chromium/third_party/blink/renderer/platform/graphics/image_frame_generator.cc
index e7fe70ee12d..660c7551498 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image_frame_generator.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/image_frame_generator.cc
@@ -29,6 +29,7 @@
#include <utility>
#include "SkData.h"
+#include "base/macros.h"
#include "third_party/blink/renderer/platform/graphics/image_decoding_store.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -71,7 +72,6 @@ static bool CompatibleInfo(const SkImageInfo& src, const SkImageInfo& dst) {
// decoding.
class ExternalMemoryAllocator final : public SkBitmap::Allocator {
USING_FAST_MALLOC(ExternalMemoryAllocator);
- WTF_MAKE_NONCOPYABLE(ExternalMemoryAllocator);
public:
ExternalMemoryAllocator(const SkImageInfo& info,
@@ -94,6 +94,8 @@ class ExternalMemoryAllocator final : public SkBitmap::Allocator {
SkImageInfo info_;
void* pixels_;
size_t row_bytes_;
+
+ DISALLOW_COPY_AND_ASSIGN(ExternalMemoryAllocator);
};
static bool UpdateYUVComponentSizes(ImageDecoder* decoder,
@@ -164,9 +166,14 @@ bool ImageFrameGenerator::DecodeAndScale(
// returning (i.e. a pointer to |pixels|) and therefore 2) should not live
// longer than the call to the current method.
ExternalMemoryAllocator external_allocator(info, pixels, row_bytes);
- SkBitmap bitmap =
- TryToResumeDecode(data, all_data_received, index, scaled_size,
- external_allocator, alpha_option);
+ ImageDecoder::HighBitDepthDecodingOption high_bit_depth_decoding_option =
+ ImageDecoder::kDefaultBitDepth;
+ if (info.colorType() == kRGBA_F16_SkColorType) {
+ high_bit_depth_decoding_option = ImageDecoder::kHighBitDepthToHalfFloat;
+ }
+ SkBitmap bitmap = TryToResumeDecode(
+ data, all_data_received, index, scaled_size, external_allocator,
+ alpha_option, high_bit_depth_decoding_option);
DCHECK(external_allocator.unique()); // Verify we have the only ref-count.
if (bitmap.isNull())
@@ -200,8 +207,10 @@ bool ImageFrameGenerator::DecodeToYUV(SegmentReader* data,
return false;
}
+ const bool data_complete = true;
std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
- data, true, ImageDecoder::kAlphaPremultiplied, decoder_color_behavior_);
+ data, data_complete, ImageDecoder::kAlphaPremultiplied,
+ ImageDecoder::kDefaultBitDepth, decoder_color_behavior_);
// getYUVComponentSizes was already called and was successful, so
// ImageDecoder::create must succeed.
DCHECK(decoder);
@@ -228,7 +237,8 @@ SkBitmap ImageFrameGenerator::TryToResumeDecode(
size_t index,
const SkISize& scaled_size,
SkBitmap::Allocator& allocator,
- ImageDecoder::AlphaOption alpha_option) {
+ ImageDecoder::AlphaOption alpha_option,
+ ImageDecoder::HighBitDepthDecodingOption high_bit_depth_decoding_option) {
#if DCHECK_IS_ON()
DCHECK(decode_mutex_.Locked());
#endif
@@ -242,9 +252,9 @@ SkBitmap ImageFrameGenerator::TryToResumeDecode(
DCHECK(!resume_decoding || decoder);
bool used_external_allocator = false;
- ImageFrame* current_frame =
- Decode(data, all_data_received, index, &decoder, allocator, alpha_option,
- scaled_size, used_external_allocator);
+ ImageFrame* current_frame = Decode(
+ data, all_data_received, index, &decoder, allocator, alpha_option,
+ high_bit_depth_decoding_option, scaled_size, used_external_allocator);
if (!decoder)
return SkBitmap();
@@ -314,14 +324,16 @@ void ImageFrameGenerator::SetHasAlpha(size_t index, bool has_alpha) {
has_alpha_[index] = has_alpha;
}
-ImageFrame* ImageFrameGenerator::Decode(SegmentReader* data,
- bool all_data_received,
- size_t index,
- ImageDecoder** decoder,
- SkBitmap::Allocator& allocator,
- ImageDecoder::AlphaOption alpha_option,
- const SkISize& scaled_size,
- bool& used_external_allocator) {
+ImageFrame* ImageFrameGenerator::Decode(
+ SegmentReader* data,
+ bool all_data_received,
+ size_t index,
+ ImageDecoder** decoder,
+ SkBitmap::Allocator& allocator,
+ ImageDecoder::AlphaOption alpha_option,
+ ImageDecoder::HighBitDepthDecodingOption high_bit_depth_decoding_option,
+ const SkISize& scaled_size,
+ bool& used_external_allocator) {
#if DCHECK_IS_ON()
DCHECK(decode_mutex_.Locked());
#endif
@@ -341,6 +353,7 @@ ImageFrame* ImageFrameGenerator::Decode(SegmentReader* data,
if (!*decoder) {
*decoder = ImageDecoder::Create(data, all_data_received, alpha_option,
+ high_bit_depth_decoding_option,
decoder_color_behavior_, scaled_size)
.release();
// The newly created decoder just grabbed the data. No need to reset it.
@@ -413,8 +426,10 @@ bool ImageFrameGenerator::GetYUVComponentSizes(SegmentReader* data,
if (yuv_decoding_failed_)
return false;
+ const bool data_complete = true;
std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
- data, true, ImageDecoder::kAlphaPremultiplied, decoder_color_behavior_);
+ data, data_complete, ImageDecoder::kAlphaPremultiplied,
+ ImageDecoder::kDefaultBitDepth, decoder_color_behavior_);
if (!decoder)
return false;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image_frame_generator.h b/chromium/third_party/blink/renderer/platform/graphics/image_frame_generator.h
index d7449212fb4..0e972e53142 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image_frame_generator.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/image_frame_generator.h
@@ -27,12 +27,13 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_IMAGE_FRAME_GENERATOR_H_
#include <memory>
+
+#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
#include "third_party/blink/renderer/platform/image-decoders/segment_reader.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
@@ -49,17 +50,18 @@ class ImageDecoder;
class PLATFORM_EXPORT ImageDecoderFactory {
USING_FAST_MALLOC(ImageDecoderFactory);
- WTF_MAKE_NONCOPYABLE(ImageDecoderFactory);
public:
ImageDecoderFactory() = default;
virtual ~ImageDecoderFactory() = default;
virtual std::unique_ptr<ImageDecoder> Create() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ImageDecoderFactory);
};
class PLATFORM_EXPORT ImageFrameGenerator final
: public ThreadSafeRefCounted<ImageFrameGenerator> {
- WTF_MAKE_NONCOPYABLE(ImageFrameGenerator);
public:
static scoped_refptr<ImageFrameGenerator> Create(
@@ -131,7 +133,8 @@ class PLATFORM_EXPORT ImageFrameGenerator final
size_t index,
const SkISize& scaled_size,
SkBitmap::Allocator&,
- ImageDecoder::AlphaOption);
+ ImageDecoder::AlphaOption,
+ ImageDecoder::HighBitDepthDecodingOption);
// This method should only be called while decode_mutex_ is locked.
// Returns a pointer to frame |index|'s ImageFrame, if available.
// Sets |used_external_allocator| to true if the the image was decoded into
@@ -142,6 +145,7 @@ class PLATFORM_EXPORT ImageFrameGenerator final
ImageDecoder**,
SkBitmap::Allocator& external_allocator,
ImageDecoder::AlphaOption,
+ ImageDecoder::HighBitDepthDecodingOption,
const SkISize& scaled_size,
bool& used_external_allocator);
@@ -164,6 +168,8 @@ class PLATFORM_EXPORT ImageFrameGenerator final
// Protect concurrent access to has_alpha_.
Mutex alpha_mutex_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImageFrameGenerator);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image_layer_chromium_test.cc b/chromium/third_party/blink/renderer/platform/graphics/image_layer_chromium_test.cc
index 01342d3ac8c..25de4618f8a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image_layer_chromium_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/image_layer_chromium_test.cc
@@ -27,6 +27,7 @@
#include <memory>
+#include "cc/layers/picture_layer.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/testing/fake_graphics_layer.h"
@@ -52,7 +53,7 @@ class TestImage : public Image {
// Image pure virtual stub.
}
- void Draw(PaintCanvas*,
+ void Draw(cc::PaintCanvas*,
const PaintFlags&,
const FloatRect&,
const FloatRect&,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/image_pattern.cc b/chromium/third_party/blink/renderer/platform/graphics/image_pattern.cc
index 2eb7a86108b..62a2e0e25d6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/image_pattern.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/image_pattern.cc
@@ -60,7 +60,7 @@ sk_sp<PaintShader> ImagePattern::CreateShader(const SkMatrix& local_matrix) {
PaintRecorder recorder;
auto* canvas = recorder.beginRecording(tile_bounds);
- PaintFlags paint;
+ cc::PaintFlags paint;
paint.setBlendMode(SkBlendMode::kSrc);
canvas->drawImage(tile_image_, border_pixel_x, border_pixel_y, &paint);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/intercepting_canvas.h b/chromium/third_party/blink/renderer/platform/graphics/intercepting_canvas.h
index 1b30367aebd..482a437fdfb 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/intercepting_canvas.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/intercepting_canvas.h
@@ -34,20 +34,17 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_record.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
namespace blink {
class InterceptingCanvasBase : public SkCanvas {
- WTF_MAKE_NONCOPYABLE(InterceptingCanvasBase);
public:
template <typename DerivedCanvas>
class CanvasInterceptorBase {
STACK_ALLOCATED();
- WTF_MAKE_NONCOPYABLE(CanvasInterceptorBase);
protected:
CanvasInterceptorBase(InterceptingCanvasBase* canvas) : canvas_(canvas) {
@@ -63,6 +60,9 @@ class InterceptingCanvasBase : public SkCanvas {
DerivedCanvas* Canvas() { return static_cast<DerivedCanvas*>(canvas_); }
bool TopLevelCall() const { return canvas_->CallNestingDepth() == 1; }
InterceptingCanvasBase* canvas_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CanvasInterceptorBase);
};
void ResetStepCount() { call_count_ = 0; }
@@ -158,6 +158,8 @@ class InterceptingCanvasBase : public SkCanvas {
private:
unsigned call_nesting_depth_;
unsigned call_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(InterceptingCanvasBase);
};
template <typename DerivedCanvas>
diff --git a/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.cc b/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.cc
index b5fa145035f..09dbc7eb337 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/logging_canvas.cc
@@ -31,12 +31,12 @@
#include "third_party/blink/renderer/platform/graphics/logging_canvas.h"
#include <unicode/unistr.h>
+#include "base/sys_byteorder.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/graphics/skia/image_pixel_locker.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/image-encoders/image_encoder.h"
-#include "third_party/blink/renderer/platform/wtf/byte_swap.h"
#include "third_party/blink/renderer/platform/wtf/hex_number.h"
#include "third_party/blink/renderer/platform/wtf/text/base64.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
@@ -273,7 +273,6 @@ std::unique_ptr<JSONObject> ObjectForBitmapData(const SkBitmap& bitmap) {
SkPngEncoder::Options options;
options.fFilterFlags = SkPngEncoder::FilterFlag::kSub;
options.fZLibLevel = 3;
- options.fUnpremulBehavior = SkTransferFunctionBehavior::kIgnore;
if (!ImageEncoder::Encode(&output, src, options)) {
return nullptr;
}
@@ -520,8 +519,9 @@ String StringForUTF32LEText(const void* text, size_t byte_length) {
// Swap LE to BE
size_t char_length = length / sizeof(UChar32);
WTF::Vector<UChar32> utf32be(char_length);
+ const UChar32* utf32le = static_cast<const UChar32*>(text);
for (size_t i = 0; i < char_length; ++i)
- utf32be[i] = WTF::Bswap32(static_cast<UChar32*>(text)[i]);
+ utf32be[i] = base::ByteSwap(utf32le[i]);
utf16 = icu::UnicodeString::fromUTF32(utf32be.data(),
static_cast<int32_t>(byte_length));
#else
diff --git a/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc b/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc
index fa33e6641e0..b2722c92dfe 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.cc
@@ -82,6 +82,8 @@ void MailboxTextureHolder::Sync(MailboxSyncMode mode) {
if (!ContextProviderWrapper() || IsAbandoned())
return;
+ TRACE_EVENT0("blink", "MailboxTextureHolder::Sync");
+
gpu::gles2::GLES2Interface* gl =
ContextProviderWrapper()->ContextProvider()->ContextGL();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h b/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h
index 58a17c894e7..1b20e1493a4 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h
@@ -7,6 +7,7 @@
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
#include "third_party/blink/renderer/platform/graphics/texture_holder.h"
#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_wrapper.h"
diff --git a/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher.cc b/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher.cc
deleted file mode 100644
index 4772ef9271a..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher.cc
+++ /dev/null
@@ -1,483 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher.h"
-
-#include <memory>
-#include "base/single_thread_task_runner.h"
-#include "components/viz/common/quads/compositor_frame.h"
-#include "components/viz/common/quads/texture_draw_quad.h"
-#include "components/viz/common/resources/resource_format.h"
-#include "third_party/blink/public/platform/interface_provider.h"
-#include "third_party/blink/public/platform/modules/frame_sinks/embedded_frame_sink.mojom-blink.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
-#include "third_party/blink/renderer/platform/cross_thread_functional.h"
-#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
-#include "third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.h"
-#include "third_party/blink/renderer/platform/histogram.h"
-#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
-#include "third_party/blink/renderer/platform/web_task_runner.h"
-
-namespace blink {
-
-enum {
- kMaxPendingCompositorFrames = 2,
- kMaxUnreclaimedPlaceholderFrames = 3,
-};
-
-OffscreenCanvasFrameDispatcher::OffscreenCanvasFrameDispatcher(
- OffscreenCanvasFrameDispatcherClient* client,
- uint32_t client_id,
- uint32_t sink_id,
- int canvas_id,
- const IntSize& size)
- : frame_sink_id_(viz::FrameSinkId(client_id, sink_id)),
- size_(size),
- change_size_for_next_commit_(false),
- needs_begin_frame_(false),
- binding_(this),
- placeholder_canvas_id_(canvas_id),
- num_unreclaimed_frames_posted_(0),
- client_(client),
- weak_ptr_factory_(this) {
- if (frame_sink_id_.is_valid()) {
- // Only frameless canvas pass an invalid frame sink id; we don't create
- // mojo channel for this special case.
- DCHECK(!sink_.is_bound());
- mojom::blink::EmbeddedFrameSinkProviderPtr provider;
- Platform::Current()->GetInterfaceProvider()->GetInterface(
- mojo::MakeRequest(&provider));
- DCHECK(provider);
-
- binding_.Bind(mojo::MakeRequest(&client_ptr_));
- provider->CreateCompositorFrameSink(frame_sink_id_, std::move(client_ptr_),
- mojo::MakeRequest(&sink_));
- }
- offscreen_canvas_resource_provider_ =
- std::make_unique<OffscreenCanvasResourceProvider>(size_.Width(),
- size_.Height(), this);
-}
-
-OffscreenCanvasFrameDispatcher::~OffscreenCanvasFrameDispatcher() = default;
-
-namespace {
-
-void UpdatePlaceholderImage(
- base::WeakPtr<OffscreenCanvasFrameDispatcher> dispatcher,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- int placeholder_canvas_id,
- scoped_refptr<blink::StaticBitmapImage> image,
- viz::ResourceId resource_id) {
- DCHECK(IsMainThread());
- OffscreenCanvasPlaceholder* placeholder_canvas =
- OffscreenCanvasPlaceholder::GetPlaceholderById(placeholder_canvas_id);
- if (placeholder_canvas) {
- placeholder_canvas->SetPlaceholderFrame(
- std::move(image), std::move(dispatcher), std::move(task_runner),
- resource_id);
- }
-}
-
-} // namespace
-
-void OffscreenCanvasFrameDispatcher::PostImageToPlaceholderIfNotBlocked(
- scoped_refptr<StaticBitmapImage> image,
- viz::ResourceId resource_id) {
- if (placeholder_canvas_id_ == kInvalidPlaceholderCanvasId) {
- offscreen_canvas_resource_provider_->ReclaimResource(resource_id);
- return;
- }
- // Determines whether the main thread may be blocked. If unblocked, post the
- // image. Otherwise, save the image and do not post it.
- if (num_unreclaimed_frames_posted_ < kMaxUnreclaimedPlaceholderFrames) {
- // After this point, |image| can only be used on the main thread, until it
- // is returned.
- image->Transfer();
- this->PostImageToPlaceholder(std::move(image), resource_id);
- num_unreclaimed_frames_posted_++;
- } else {
- DCHECK(num_unreclaimed_frames_posted_ == kMaxUnreclaimedPlaceholderFrames);
- if (latest_unposted_image_) {
- // The previous unposted image becomes obsolete now.
- offscreen_canvas_resource_provider_->ReclaimResource(
- latest_unposted_resource_id_);
- }
-
- latest_unposted_image_ = std::move(image);
- latest_unposted_resource_id_ = resource_id;
- }
-}
-
-void OffscreenCanvasFrameDispatcher::PostImageToPlaceholder(
- scoped_refptr<StaticBitmapImage> image,
- viz::ResourceId resource_id) {
- scoped_refptr<base::SingleThreadTaskRunner> dispatcher_task_runner =
- Platform::Current()->CurrentThread()->GetTaskRunner();
-
- PostCrossThreadTask(
- *Platform::Current()->MainThread()->Scheduler()->CompositorTaskRunner(),
- FROM_HERE,
- CrossThreadBind(UpdatePlaceholderImage, this->GetWeakPtr(),
- WTF::Passed(std::move(dispatcher_task_runner)),
- placeholder_canvas_id_, std::move(image), resource_id));
-}
-
-void OffscreenCanvasFrameDispatcher::DispatchFrameSync(
- scoped_refptr<StaticBitmapImage> image,
- double commit_start_time,
- const SkIRect& damage_rect) {
- viz::CompositorFrame frame;
- if (!PrepareFrame(std::move(image), commit_start_time, damage_rect, &frame))
- return;
-
- pending_compositor_frames_++;
- WTF::Vector<viz::ReturnedResource> resources;
- sink_->SubmitCompositorFrameSync(
- parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
- std::move(frame), nullptr, 0, &resources);
- DidReceiveCompositorFrameAck(resources);
-}
-
-void OffscreenCanvasFrameDispatcher::DispatchFrame(
- scoped_refptr<StaticBitmapImage> image,
- double commit_start_time,
- const SkIRect& damage_rect) {
- viz::CompositorFrame frame;
- if (!PrepareFrame(std::move(image), commit_start_time, damage_rect, &frame))
- return;
-
- pending_compositor_frames_++;
- sink_->SubmitCompositorFrame(
- parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
- std::move(frame), nullptr, 0);
-}
-
-bool OffscreenCanvasFrameDispatcher::PrepareFrame(
- scoped_refptr<StaticBitmapImage> image,
- double commit_start_time,
- const SkIRect& damage_rect,
- viz::CompositorFrame* frame) {
- if (!image || !VerifyImageSize(image->Size()))
- return false;
-
- offscreen_canvas_resource_provider_->IncNextResourceId();
-
- // For frameless canvas, we don't get a valid frame_sink_id and should drop.
- if (!frame_sink_id_.is_valid()) {
- PostImageToPlaceholderIfNotBlocked(
- std::move(image),
- offscreen_canvas_resource_provider_->GetNextResourceId());
- return false;
- }
-
- // TODO(crbug.com/652931): update the device_scale_factor
- frame->metadata.device_scale_factor = 1.0f;
- if (current_begin_frame_ack_.sequence_number ==
- viz::BeginFrameArgs::kInvalidFrameNumber) {
- // TODO(eseckler): This shouldn't be necessary when OffscreenCanvas no
- // longer submits CompositorFrames without prior BeginFrame.
- current_begin_frame_ack_ = viz::BeginFrameAck::CreateManualAckWithDamage();
- } else {
- current_begin_frame_ack_.has_damage = true;
- }
- frame->metadata.begin_frame_ack = current_begin_frame_ack_;
-
- const gfx::Rect bounds(size_.Width(), size_.Height());
- const int kRenderPassId = 1;
- bool is_clipped = false;
- // TODO(crbug.com/705019): optimize for contexts that have {alpha: false}
- bool are_contents_opaque = false;
- std::unique_ptr<viz::RenderPass> pass = viz::RenderPass::Create();
- pass->SetNew(kRenderPassId, bounds,
- gfx::Rect(damage_rect.x(), damage_rect.y(), damage_rect.width(),
- damage_rect.height()),
- gfx::Transform());
-
- viz::SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
- sqs->SetAll(gfx::Transform(), bounds, bounds, bounds, is_clipped,
- are_contents_opaque, 1.f, SkBlendMode::kSrcOver, 0);
-
- viz::TransferableResource resource;
- offscreen_canvas_resource_provider_->TransferResource(&resource);
-
- bool yflipped = false;
- OffscreenCanvasCommitType commit_type;
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- EnumerationHistogram, commit_type_histogram,
- ("OffscreenCanvas.CommitType", kOffscreenCanvasCommitTypeCount));
- if (image->IsTextureBacked()) {
- // While |image| is texture backed, it could be generated with "software
- // rendering" aka swiftshader. If the compositor is not also using
- // swiftshader, then we could not give a swiftshader based texture
- // to the compositor. However in that case, IsGpuCompositingEnabled() will
- // also be false, so we will avoid doing so.
- if (SharedGpuContext::IsGpuCompositingEnabled()) {
- // Case 1: both canvas and compositor are gpu accelerated.
- commit_type = kCommitGPUCanvasGPUCompositing;
- offscreen_canvas_resource_provider_
- ->SetTransferableResourceToStaticBitmapImage(resource, image);
- yflipped = true;
- } else {
- // Case 2: canvas is accelerated but gpu compositing is disabled.
- commit_type = kCommitGPUCanvasSoftwareCompositing;
- offscreen_canvas_resource_provider_
- ->SetTransferableResourceToSharedBitmap(resource, image);
- }
- } else {
- if (SharedGpuContext::IsGpuCompositingEnabled()) {
- // Case 3: canvas is not gpu-accelerated, but compositor is.
- commit_type = kCommitSoftwareCanvasGPUCompositing;
- scoped_refptr<StaticBitmapImage> accelerated_image =
- image->MakeAccelerated(SharedGpuContext::ContextProviderWrapper());
- if (!accelerated_image)
- return false;
- offscreen_canvas_resource_provider_
- ->SetTransferableResourceToStaticBitmapImage(resource,
- accelerated_image);
- } else {
- // Case 4: both canvas and compositor are not gpu accelerated.
- commit_type = kCommitSoftwareCanvasSoftwareCompositing;
- offscreen_canvas_resource_provider_
- ->SetTransferableResourceToSharedBitmap(resource, image);
- }
- }
-
- commit_type_histogram.Count(commit_type);
-
- PostImageToPlaceholderIfNotBlocked(
- std::move(image),
- offscreen_canvas_resource_provider_->GetNextResourceId());
-
- frame->resource_list.push_back(std::move(resource));
-
- viz::TextureDrawQuad* quad =
- pass->CreateAndAppendDrawQuad<viz::TextureDrawQuad>();
- gfx::Size rect_size(size_.Width(), size_.Height());
-
- // TODO(crbug.com/705019): optimize for contexts that have {alpha: false}
- const bool kNeedsBlending = true;
-
- // TODO(crbug.com/645993): this should be inherited from WebGL context's
- // creation settings.
- const bool kPremultipliedAlpha = true;
- const gfx::PointF uv_top_left(0.f, 0.f);
- const gfx::PointF uv_bottom_right(1.f, 1.f);
- float vertex_opacity[4] = {1.f, 1.f, 1.f, 1.f};
- // TODO(crbug.com/645994): this should be true when using style
- // "image-rendering: pixelated".
- // TODO(crbug.com/645590): filter should respect the image-rendering CSS
- // property of associated canvas element.
- const bool kNearestNeighbor = false;
- quad->SetAll(sqs, bounds, bounds, kNeedsBlending, resource.id, gfx::Size(),
- kPremultipliedAlpha, uv_top_left, uv_bottom_right,
- SK_ColorTRANSPARENT, vertex_opacity, yflipped, kNearestNeighbor,
- false);
-
- frame->render_pass_list.push_back(std::move(pass));
-
- double elapsed_time = WTF::CurrentTimeTicksInSeconds() - commit_start_time;
-
- switch (commit_type) {
- case kCommitGPUCanvasGPUCompositing:
- if (IsMainThread()) {
- DEFINE_STATIC_LOCAL(
- CustomCountHistogram, commit_gpu_canvas_gpu_compositing_main_timer,
- ("Blink.Canvas.OffscreenCommit.GPUCanvasGPUCompositingMain", 0,
- 10000000, 50));
- commit_gpu_canvas_gpu_compositing_main_timer.Count(elapsed_time *
- 1000000.0);
- } else {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram,
- commit_gpu_canvas_gpu_compositing_worker_timer,
- ("Blink.Canvas.OffscreenCommit.GPUCanvasGPUCompositingWorker", 0,
- 10000000, 50));
- commit_gpu_canvas_gpu_compositing_worker_timer.Count(elapsed_time *
- 1000000.0);
- }
- break;
- case kCommitGPUCanvasSoftwareCompositing:
- if (IsMainThread()) {
- DEFINE_STATIC_LOCAL(
- CustomCountHistogram,
- commit_gpu_canvas_software_compositing_main_timer,
- ("Blink.Canvas.OffscreenCommit.GPUCanvasSoftwareCompositingMain", 0,
- 10000000, 50));
- commit_gpu_canvas_software_compositing_main_timer.Count(elapsed_time *
- 1000000.0);
- } else {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram,
- commit_gpu_canvas_software_compositing_worker_timer,
- ("Blink.Canvas.OffscreenCommit."
- "GPUCanvasSoftwareCompositingWorker",
- 0, 10000000, 50));
- commit_gpu_canvas_software_compositing_worker_timer.Count(elapsed_time *
- 1000000.0);
- }
- break;
- case kCommitSoftwareCanvasGPUCompositing:
- if (IsMainThread()) {
- DEFINE_STATIC_LOCAL(
- CustomCountHistogram,
- commit_software_canvas_gpu_compositing_main_timer,
- ("Blink.Canvas.OffscreenCommit.SoftwareCanvasGPUCompositingMain", 0,
- 10000000, 50));
- commit_software_canvas_gpu_compositing_main_timer.Count(elapsed_time *
- 1000000.0);
- } else {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram,
- commit_software_canvas_gpu_compositing_worker_timer,
- ("Blink.Canvas.OffscreenCommit."
- "SoftwareCanvasGPUCompositingWorker",
- 0, 10000000, 50));
- commit_software_canvas_gpu_compositing_worker_timer.Count(elapsed_time *
- 1000000.0);
- }
- break;
- case kCommitSoftwareCanvasSoftwareCompositing:
- if (IsMainThread()) {
- DEFINE_STATIC_LOCAL(
- CustomCountHistogram,
- commit_software_canvas_software_compositing_main_timer,
- ("Blink.Canvas.OffscreenCommit."
- "SoftwareCanvasSoftwareCompositingMain",
- 0, 10000000, 50));
- commit_software_canvas_software_compositing_main_timer.Count(
- elapsed_time * 1000000.0);
- } else {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram,
- commit_software_canvas_software_compositing_worker_timer,
- ("Blink.Canvas.OffscreenCommit."
- "SoftwareCanvasSoftwareCompositingWorker",
- 0, 10000000, 50));
- commit_software_canvas_software_compositing_worker_timer.Count(
- elapsed_time * 1000000.0);
- }
- break;
- case kOffscreenCanvasCommitTypeCount:
- NOTREACHED();
- }
-
- if (change_size_for_next_commit_) {
- parent_local_surface_id_allocator_.GenerateId();
- change_size_for_next_commit_ = false;
- }
-
- return true;
-}
-
-void OffscreenCanvasFrameDispatcher::DidReceiveCompositorFrameAck(
- const WTF::Vector<viz::ReturnedResource>& resources) {
- ReclaimResources(resources);
- pending_compositor_frames_--;
- DCHECK_GE(pending_compositor_frames_, 0);
-}
-
-void OffscreenCanvasFrameDispatcher::DidPresentCompositorFrame(
- uint32_t presentation_token,
- mojo_base::mojom::blink::TimeTicksPtr time,
- WTF::TimeDelta refresh,
- uint32_t flags) {
- NOTIMPLEMENTED();
-}
-
-void OffscreenCanvasFrameDispatcher::DidDiscardCompositorFrame(
- uint32_t presentation_token) {
- NOTIMPLEMENTED();
-}
-
-void OffscreenCanvasFrameDispatcher::SetNeedsBeginFrame(
- bool needs_begin_frame) {
- if (needs_begin_frame_ == needs_begin_frame)
- return;
- needs_begin_frame_ = needs_begin_frame;
- if (!suspend_animation_)
- SetNeedsBeginFrameInternal();
-}
-
-void OffscreenCanvasFrameDispatcher::SetSuspendAnimation(
- bool suspend_animation) {
- if (suspend_animation_ == suspend_animation)
- return;
- suspend_animation_ = suspend_animation;
- if (needs_begin_frame_)
- SetNeedsBeginFrameInternal();
-}
-
-void OffscreenCanvasFrameDispatcher::SetNeedsBeginFrameInternal() {
- if (sink_) {
- sink_->SetNeedsBeginFrame(needs_begin_frame_ && !suspend_animation_);
- }
-}
-
-void OffscreenCanvasFrameDispatcher::OnBeginFrame(
- const viz::BeginFrameArgs& begin_frame_args) {
- DCHECK(Client());
-
- current_begin_frame_ack_ = viz::BeginFrameAck(
- begin_frame_args.source_id, begin_frame_args.sequence_number, false);
- if (pending_compositor_frames_ >= kMaxPendingCompositorFrames ||
- (begin_frame_args.type == viz::BeginFrameArgs::MISSED &&
- base::TimeTicks::Now() > begin_frame_args.deadline)) {
- sink_->DidNotProduceFrame(current_begin_frame_ack_);
- return;
- }
-
- Client()->BeginFrame();
- // TODO(eseckler): Tell |m_sink| if we did not draw during the BeginFrame.
- current_begin_frame_ack_.sequence_number =
- viz::BeginFrameArgs::kInvalidFrameNumber;
-}
-
-void OffscreenCanvasFrameDispatcher::ReclaimResources(
- const WTF::Vector<viz::ReturnedResource>& resources) {
- offscreen_canvas_resource_provider_->ReclaimResources(resources);
-}
-
-void OffscreenCanvasFrameDispatcher::ReclaimResource(
- viz::ResourceId resource_id) {
- offscreen_canvas_resource_provider_->ReclaimResource(resource_id);
- num_unreclaimed_frames_posted_--;
-
- // The main thread has become unblocked recently and we have an image that
- // have not been posted yet.
- if (latest_unposted_image_) {
- DCHECK(num_unreclaimed_frames_posted_ ==
- kMaxUnreclaimedPlaceholderFrames - 1);
- PostImageToPlaceholderIfNotBlocked(std::move(latest_unposted_image_),
- latest_unposted_resource_id_);
- latest_unposted_resource_id_ = 0;
- }
-}
-
-bool OffscreenCanvasFrameDispatcher::VerifyImageSize(const IntSize image_size) {
- if (image_size == size_)
- return true;
- return false;
-}
-
-void OffscreenCanvasFrameDispatcher::Reshape(const IntSize& size) {
- if (size_ != size) {
- size_ = size;
- offscreen_canvas_resource_provider_->Reshape(size_.Width(), size_.Height());
- change_size_for_next_commit_ = true;
- }
-}
-
-void OffscreenCanvasFrameDispatcher::DidAllocateSharedBitmap(
- mojo::ScopedSharedBufferHandle buffer,
- ::gpu::mojom::blink::MailboxPtr id) {
- sink_->DidAllocateSharedBitmap(std::move(buffer), std::move(id));
-}
-
-void OffscreenCanvasFrameDispatcher::DidDeleteSharedBitmap(
- ::gpu::mojom::blink::MailboxPtr id) {
- sink_->DidDeleteSharedBitmap(std::move(id));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher.h b/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher.h
deleted file mode 100644
index 557e0a3b230..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher.h
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_OFFSCREEN_CANVAS_FRAME_DISPATCHER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_OFFSCREEN_CANVAS_FRAME_DISPATCHER_H_
-
-#include <memory>
-#include "components/viz/common/frame_sinks/begin_frame_args.h"
-#include "components/viz/common/resources/resource_id.h"
-#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom-blink.h"
-#include "third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.h"
-#include "third_party/blink/renderer/platform/wtf/compiler.h"
-
-namespace blink {
-
-class OffscreenCanvasFrameDispatcherClient {
- public:
- virtual void BeginFrame() = 0;
-};
-
-class PLATFORM_EXPORT OffscreenCanvasFrameDispatcher
- : public viz::mojom::blink::CompositorFrameSinkClient {
- public:
- base::WeakPtr<OffscreenCanvasFrameDispatcher> GetWeakPtr() {
- return weak_ptr_factory_.GetWeakPtr();
- }
-
- OffscreenCanvasFrameDispatcherClient* Client() { return client_; }
-
- enum {
- kInvalidPlaceholderCanvasId = -1,
- };
-
- OffscreenCanvasFrameDispatcher(OffscreenCanvasFrameDispatcherClient*,
- uint32_t client_id,
- uint32_t sink_id,
- int placeholder_canvas_id,
- const IntSize&);
-
- ~OffscreenCanvasFrameDispatcher() override;
- void SetNeedsBeginFrame(bool);
- void SetSuspendAnimation(bool);
- bool NeedsBeginFrame() const { return needs_begin_frame_; }
- bool IsAnimationSuspended() const { return suspend_animation_; }
- void DispatchFrame(scoped_refptr<StaticBitmapImage>,
- double commit_start_time,
- const SkIRect& damage_rect);
- void ReclaimResource(viz::ResourceId);
- void DispatchFrameSync(scoped_refptr<StaticBitmapImage>,
- double commit_start_time,
- const SkIRect& damage_rect);
-
- void Reshape(const IntSize&);
-
- // viz::mojom::blink::CompositorFrameSinkClient implementation.
- void DidReceiveCompositorFrameAck(
- const WTF::Vector<viz::ReturnedResource>& resources) final;
- void DidPresentCompositorFrame(uint32_t presentation_token,
- mojo_base::mojom::blink::TimeTicksPtr,
- WTF::TimeDelta refresh,
- uint32_t flags) final;
- void DidDiscardCompositorFrame(uint32_t presentation_token) final;
- void OnBeginFrame(const viz::BeginFrameArgs&) final;
- void OnBeginFramePausedChanged(bool paused) final{};
- void ReclaimResources(
- const WTF::Vector<viz::ReturnedResource>& resources) final;
-
- void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer,
- ::gpu::mojom::blink::MailboxPtr id);
- void DidDeleteSharedBitmap(::gpu::mojom::blink::MailboxPtr id);
-
- // This enum is used in histogram, so it should be append-only.
- enum OffscreenCanvasCommitType {
- kCommitGPUCanvasGPUCompositing = 0,
- kCommitGPUCanvasSoftwareCompositing = 1,
- kCommitSoftwareCanvasGPUCompositing = 2,
- kCommitSoftwareCanvasSoftwareCompositing = 3,
- kOffscreenCanvasCommitTypeCount,
-
- };
-
- private:
- friend class OffscreenCanvasFrameDispatcherTest;
-
- bool PrepareFrame(scoped_refptr<StaticBitmapImage>,
- double commit_start_time,
- const SkIRect& damage_rect,
- viz::CompositorFrame* frame);
-
- // Surface-related
- viz::ParentLocalSurfaceIdAllocator parent_local_surface_id_allocator_;
- const viz::FrameSinkId frame_sink_id_;
-
- IntSize size_;
- bool change_size_for_next_commit_;
- bool suspend_animation_ = false;
- bool needs_begin_frame_ = false;
- int pending_compositor_frames_ = 0;
-
- void SetNeedsBeginFrameInternal();
-
- bool VerifyImageSize(const IntSize);
- void PostImageToPlaceholderIfNotBlocked(scoped_refptr<StaticBitmapImage>,
- viz::ResourceId resource_id);
- // virtual for testing
- virtual void PostImageToPlaceholder(scoped_refptr<StaticBitmapImage>,
- viz::ResourceId resource_id);
-
- viz::mojom::blink::CompositorFrameSinkPtr sink_;
- mojo::Binding<viz::mojom::blink::CompositorFrameSinkClient> binding_;
- viz::mojom::blink::CompositorFrameSinkClientPtr client_ptr_;
-
- int placeholder_canvas_id_;
-
- // The latest_unposted_resource_id_ always refers to the Id of the frame
- // resource used by the latest_unposted_image_.
- scoped_refptr<StaticBitmapImage> latest_unposted_image_;
- viz::ResourceId latest_unposted_resource_id_;
- unsigned num_unreclaimed_frames_posted_;
-
- viz::BeginFrameAck current_begin_frame_ack_;
-
- OffscreenCanvasFrameDispatcherClient* client_;
-
- std::unique_ptr<OffscreenCanvasResourceProvider>
- offscreen_canvas_resource_provider_;
-
- base::WeakPtrFactory<OffscreenCanvasFrameDispatcher> weak_ptr_factory_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_OFFSCREEN_CANVAS_FRAME_DISPATCHER_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher_test.cc b/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher_test.cc
index f0906bf72f3..86812fcecd3 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher_test.cc
@@ -2,13 +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/platform/graphics/offscreen_canvas_frame_dispatcher.h"
+#include "third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h"
#include <memory>
#include "base/test/simple_test_tick_clock.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/graphics/canvas_resource.h"
#include "third_party/skia/include/core/SkSurface.h"
using testing::_;
@@ -16,17 +17,16 @@ using testing::Mock;
namespace blink {
-class MockOffscreenCanvasFrameDispatcher
- : public OffscreenCanvasFrameDispatcher {
+class MockCanvasResourceDispatcher : public CanvasResourceDispatcher {
public:
- MockOffscreenCanvasFrameDispatcher()
- : OffscreenCanvasFrameDispatcher(nullptr, 0, 0, 0, {10, 10}) {}
+ MockCanvasResourceDispatcher()
+ : CanvasResourceDispatcher(nullptr, 0, 0, 0, {10, 10}) {}
MOCK_METHOD2(PostImageToPlaceholder,
- void(scoped_refptr<StaticBitmapImage>, unsigned resource_id));
+ void(scoped_refptr<CanvasResource>, unsigned resource_id));
};
-class OffscreenCanvasFrameDispatcherTest : public testing::Test {
+class CanvasResourceDispatcherTest : public testing::Test {
public:
void DispatchOneFrame();
OffscreenCanvasResourceProvider* GetResourceProvider() {
@@ -37,7 +37,7 @@ class OffscreenCanvasFrameDispatcherTest : public testing::Test {
return dispatcher_->num_unreclaimed_frames_posted_;
}
- StaticBitmapImage* GetLatestUnpostedImage() {
+ CanvasResource* GetLatestUnpostedImage() {
return dispatcher_->latest_unposted_image_.get();
}
@@ -46,25 +46,25 @@ class OffscreenCanvasFrameDispatcherTest : public testing::Test {
}
protected:
- OffscreenCanvasFrameDispatcherTest() {
- dispatcher_ = std::make_unique<MockOffscreenCanvasFrameDispatcher>();
+ CanvasResourceDispatcherTest() {
+ dispatcher_ = std::make_unique<MockCanvasResourceDispatcher>();
}
- MockOffscreenCanvasFrameDispatcher* Dispatcher() { return dispatcher_.get(); }
+ MockCanvasResourceDispatcher* Dispatcher() { return dispatcher_.get(); }
private:
scoped_refptr<StaticBitmapImage> PrepareStaticBitmapImage();
- std::unique_ptr<MockOffscreenCanvasFrameDispatcher> dispatcher_;
+ std::unique_ptr<MockCanvasResourceDispatcher> dispatcher_;
};
-void OffscreenCanvasFrameDispatcherTest::DispatchOneFrame() {
+void CanvasResourceDispatcherTest::DispatchOneFrame() {
sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(10, 10);
dispatcher_->DispatchFrame(
- StaticBitmapImage::Create(surface->makeImageSnapshot()), 0.0,
- SkIRect::MakeEmpty());
+ StaticBitmapImage::Create(surface->makeImageSnapshot()),
+ base::TimeTicks(), SkIRect::MakeEmpty());
}
-TEST_F(OffscreenCanvasFrameDispatcherTest, PlaceholderRunsNormally) {
+TEST_F(CanvasResourceDispatcherTest, PlaceholderRunsNormally) {
/* We allow OffscreenCanvas to post up to 3 frames without hearing a response
* from placeholder. */
// Post first frame
@@ -110,7 +110,7 @@ TEST_F(OffscreenCanvasFrameDispatcherTest, PlaceholderRunsNormally) {
EXPECT_EQ(0u, GetNumUnreclaimedFramesPosted());
}
-TEST_F(OffscreenCanvasFrameDispatcherTest, PlaceholderBeingBlocked) {
+TEST_F(CanvasResourceDispatcherTest, PlaceholderBeingBlocked) {
/* When main thread is blocked, attempting to post more than 3 frames will
* result in only 3 PostImageToPlaceholder. The latest unposted image will
* be saved. */
@@ -138,7 +138,7 @@ TEST_F(OffscreenCanvasFrameDispatcherTest, PlaceholderBeingBlocked) {
Mock::VerifyAndClearExpectations(Dispatcher());
/* When main thread becomes unblocked, the first reclaim called by placeholder
- * will trigger OffscreenCanvasFrameDispatcher to post the last saved image.
+ * will trigger CanvasResourceDispatcher to post the last saved image.
* Resource reclaim happens in the same order as frame posting. */
unsigned reclaim_resource_id = 1u;
EXPECT_CALL(*(Dispatcher()), PostImageToPlaceholder(_, post_resource_id));
diff --git a/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.cc b/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.cc
index d46bf03849b..d92901f961c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.cc
@@ -6,8 +6,8 @@
#include "base/single_thread_task_runner.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
-#include "third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher.h"
-#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
+#include "third_party/blink/renderer/platform/graphics/canvas_resource.h"
+#include "third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h"
#include "third_party/blink/renderer/platform/web_task_runner.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
@@ -22,8 +22,8 @@ PlaceholderIdMap& placeholderRegistry() {
}
void releaseFrameToDispatcher(
- base::WeakPtr<blink::OffscreenCanvasFrameDispatcher> dispatcher,
- scoped_refptr<blink::Image> oldImage,
+ base::WeakPtr<blink::CanvasResourceDispatcher> dispatcher,
+ scoped_refptr<blink::CanvasResource> oldImage,
viz::ResourceId resourceId) {
oldImage = nullptr; // Needed to unref'ed on the right thread
if (dispatcher) {
@@ -32,7 +32,7 @@ void releaseFrameToDispatcher(
}
void SetSuspendAnimation(
- base::WeakPtr<blink::OffscreenCanvasFrameDispatcher> dispatcher,
+ base::WeakPtr<blink::CanvasResourceDispatcher> dispatcher,
bool suspend) {
if (dispatcher) {
dispatcher->SetSuspendAnimation(suspend);
@@ -71,8 +71,8 @@ void OffscreenCanvasPlaceholder::UnregisterPlaceholder() {
}
void OffscreenCanvasPlaceholder::SetPlaceholderFrame(
- scoped_refptr<StaticBitmapImage> new_frame,
- base::WeakPtr<OffscreenCanvasFrameDispatcher> dispatcher,
+ scoped_refptr<CanvasResource> new_frame,
+ base::WeakPtr<CanvasResourceDispatcher> dispatcher,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
viz::ResourceId resource_id) {
DCHECK(IsPlaceholderRegistered());
@@ -97,6 +97,7 @@ void OffscreenCanvasPlaceholder::SetPlaceholderFrame(
void OffscreenCanvasPlaceholder::ReleasePlaceholderFrame() {
DCHECK(IsPlaceholderRegistered());
if (placeholder_frame_) {
+ DCHECK(frame_dispatcher_task_runner_);
placeholder_frame_->Transfer();
PostCrossThreadTask(
*frame_dispatcher_task_runner_, FROM_HERE,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.h b/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.h
index 9db25c5ad8a..799f2c0891c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_placeholder.h
@@ -14,18 +14,17 @@
namespace blink {
-class OffscreenCanvasFrameDispatcher;
-class StaticBitmapImage;
+class CanvasResource;
+class CanvasResourceDispatcher;
class PLATFORM_EXPORT OffscreenCanvasPlaceholder {
public:
~OffscreenCanvasPlaceholder();
- virtual void SetPlaceholderFrame(
- scoped_refptr<StaticBitmapImage>,
- base::WeakPtr<OffscreenCanvasFrameDispatcher>,
- scoped_refptr<base::SingleThreadTaskRunner>,
- viz::ResourceId resource_id);
+ virtual void SetPlaceholderFrame(scoped_refptr<CanvasResource>,
+ base::WeakPtr<CanvasResourceDispatcher>,
+ scoped_refptr<base::SingleThreadTaskRunner>,
+ viz::ResourceId resource_id);
void ReleasePlaceholderFrame();
void SetSuspendOffscreenCanvasAnimation(bool);
@@ -35,7 +34,7 @@ class PLATFORM_EXPORT OffscreenCanvasPlaceholder {
void RegisterPlaceholder(unsigned placeholder_id);
void UnregisterPlaceholder();
- const scoped_refptr<StaticBitmapImage>& PlaceholderFrame() const {
+ const scoped_refptr<CanvasResource>& PlaceholderFrame() const {
return placeholder_frame_;
}
@@ -46,8 +45,8 @@ class PLATFORM_EXPORT OffscreenCanvasPlaceholder {
private:
bool PostSetSuspendAnimationToOffscreenCanvasThread(bool suspend);
- scoped_refptr<StaticBitmapImage> placeholder_frame_;
- base::WeakPtr<OffscreenCanvasFrameDispatcher> frame_dispatcher_;
+ scoped_refptr<CanvasResource> placeholder_frame_;
+ base::WeakPtr<CanvasResourceDispatcher> frame_dispatcher_;
scoped_refptr<base::SingleThreadTaskRunner> frame_dispatcher_task_runner_;
viz::ResourceId placeholder_frame_resource_id_ = 0;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.cc b/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.cc
index 8c140158bfd..a99595fbae4 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.cc
@@ -6,15 +6,17 @@
#include "base/memory/shared_memory.h"
#include "base/numerics/checked_math.h"
-#include "components/viz/common/quads/shared_bitmap.h"
#include "components/viz/common/resources/bitmap_allocation.h"
+#include "components/viz/common/resources/shared_bitmap.h"
+#include "components/viz/common/resources/single_release_callback.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/capabilities.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
+#include "third_party/blink/renderer/platform/graphics/canvas_resource.h"
+#include "third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher.h"
#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
-#include "third_party/blink/renderer/platform/graphics/offscreen_canvas_frame_dispatcher.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer.h"
#include "third_party/blink/renderer/platform/wtf/typed_arrays/uint8_array.h"
@@ -25,27 +27,12 @@
#include "third_party/skia/include/core/SkSwizzle.h"
#include "third_party/skia/include/gpu/GrContext.h"
-namespace {
-
-// TODO(danakj): One day the gpu::mojom::Mailbox type should be shared with
-// blink directly and we won't need to use gpu::mojom::blink::Mailbox, nor the
-// conversion through WTF::Vector.
-gpu::mojom::blink::MailboxPtr SharedBitmapIdToGpuMailboxPtr(
- const viz::SharedBitmapId& id) {
- WTF::Vector<int8_t> name(GL_MAILBOX_SIZE_CHROMIUM);
- for (int i = 0; i < GL_MAILBOX_SIZE_CHROMIUM; ++i)
- name[i] = id.name[i];
- return {base::in_place, name};
-}
-
-} // namespace
-
namespace blink {
OffscreenCanvasResourceProvider::OffscreenCanvasResourceProvider(
int width,
int height,
- OffscreenCanvasFrameDispatcher* frame_dispatcher)
+ CanvasResourceDispatcher* frame_dispatcher)
: frame_dispatcher_(frame_dispatcher), width_(width), height_(height) {}
OffscreenCanvasResourceProvider::~OffscreenCanvasResourceProvider() = default;
@@ -59,18 +46,6 @@ OffscreenCanvasResourceProvider::CreateOrRecycleFrameResource() {
return std::make_unique<FrameResource>();
}
-void OffscreenCanvasResourceProvider::TransferResource(
- viz::TransferableResource* resource) {
- resource->id = next_resource_id_;
- resource->format = viz::ResourceFormat::RGBA_8888;
- resource->size = gfx::Size(width_, height_);
- // This indicates the filtering on the resource inherently, not the desired
- // filtering effect on the quad.
- resource->filter = GL_NEAREST;
- // TODO(crbug.com/646022): making this overlay-able.
- resource->is_overlay_candidate = false;
-}
-
void OffscreenCanvasResourceProvider::SetTransferableResourceToSharedBitmap(
viz::TransferableResource& resource,
scoped_refptr<StaticBitmapImage> image) {
@@ -116,27 +91,35 @@ void OffscreenCanvasResourceProvider::SetTransferableResourceToSharedBitmap(
resource.mailbox_holder.mailbox = frame_resource->shared_bitmap_id;
resource.mailbox_holder.texture_target = 0;
resource.is_software = true;
+ resource.id = next_resource_id_;
+ resource.format = viz::ResourceFormat::RGBA_8888;
+ resource.size = gfx::Size(width_, height_);
+ // This indicates the filtering on the resource inherently, not the desired
+ // filtering effect on the quad.
+ resource.filter = GL_NEAREST;
+ // TODO(crbug.com/646022): making this overlay-able.
+ resource.is_overlay_candidate = false;
resources_.insert(next_resource_id_, std::move(frame_resource));
}
void OffscreenCanvasResourceProvider::
SetTransferableResourceToStaticBitmapImage(
- viz::TransferableResource& resource,
- scoped_refptr<StaticBitmapImage> image) {
- DCHECK(image->IsTextureBacked());
+ viz::TransferableResource* out_resource,
+ scoped_refptr<CanvasResource> image) {
+ DCHECK(image->IsAccelerated());
DCHECK(image->IsValid());
- image->EnsureMailbox(kVerifiedSyncToken, GL_LINEAR);
- resource.mailbox_holder = gpu::MailboxHolder(
- image->GetMailbox(), image->GetSyncToken(), GL_TEXTURE_2D);
- resource.read_lock_fences_enabled = false;
- resource.is_software = false;
std::unique_ptr<FrameResource> frame_resource =
CreateOrRecycleFrameResource();
- frame_resource->provider = this;
- frame_resource->image = std::move(image);
+ // TODO(junov): Using verified sync tokens for each offscreencanvas is
+ // suboptimal in the case where there are multiple offscreen canvases
+ // commiting frames. Would be more efficient to batch the verifications.
+ image->PrepareTransferableResource(
+ out_resource, &frame_resource->release_callback, kVerifiedSyncToken);
+ out_resource->id = next_resource_id_;
+
resources_.insert(next_resource_id_, std::move(frame_resource));
}
@@ -149,13 +132,8 @@ void OffscreenCanvasResourceProvider::ReclaimResources(
if (it == resources_.end())
continue;
- if (it->value->image && it->value->image->ContextProviderWrapper() &&
- resource.sync_token.HasData()) {
- it->value->image->ContextProviderWrapper()
- ->ContextProvider()
- ->ContextGL()
- ->WaitSyncTokenCHROMIUM(resource.sync_token.GetConstData());
- }
+ it->value->sync_token = resource.sync_token;
+ it->value->is_lost = resource.lost;
ReclaimResourceInternal(it);
}
}
@@ -172,17 +150,26 @@ void OffscreenCanvasResourceProvider::ReclaimResourceInternal(
if (it->value->spare_lock) {
it->value->spare_lock = false;
} else {
- // Really reclaim the resources.
+ if (it->value->release_callback) {
+ it->value->release_callback->Run(it->value->sync_token,
+ it->value->is_lost);
+ }
+ // Recycle resource.
recyclable_resource_ = std::move(it->value);
- // Release SkImage immediately since it is not recyclable.
- recyclable_resource_->image = nullptr;
+ recyclable_resource_->release_callback = nullptr;
+ recyclable_resource_->sync_token.Clear();
+ recyclable_resource_->is_lost = false;
resources_.erase(it);
}
}
OffscreenCanvasResourceProvider::FrameResource::~FrameResource() {
- provider->frame_dispatcher_->DidDeleteSharedBitmap(
- SharedBitmapIdToGpuMailboxPtr(shared_bitmap_id));
+ if (release_callback)
+ release_callback->Run(sync_token, is_lost);
+ if (provider && !shared_bitmap_id.IsZero()) {
+ provider->frame_dispatcher_->DidDeleteSharedBitmap(
+ SharedBitmapIdToGpuMailboxPtr(shared_bitmap_id));
+ }
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.h b/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.h
index b8932cb9cb9..a1615b377bb 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/offscreen_canvas_resource_provider.h
@@ -14,6 +14,7 @@ class SharedMemory;
}
namespace viz {
+class SingleReleaseCallback;
namespace mojom {
namespace blink {
class CompositorFrameSink;
@@ -23,7 +24,8 @@ class CompositorFrameSink;
namespace blink {
-class OffscreenCanvasFrameDispatcher;
+class CanvasResource;
+class CanvasResourceDispatcher;
class PLATFORM_EXPORT OffscreenCanvasResourceProvider {
public:
@@ -32,16 +34,15 @@ class PLATFORM_EXPORT OffscreenCanvasResourceProvider {
// display compositor.
OffscreenCanvasResourceProvider(int width,
int height,
- OffscreenCanvasFrameDispatcher*);
+ CanvasResourceDispatcher*);
~OffscreenCanvasResourceProvider();
- void TransferResource(viz::TransferableResource*);
void SetTransferableResourceToSharedBitmap(viz::TransferableResource&,
scoped_refptr<StaticBitmapImage>);
void SetTransferableResourceToStaticBitmapImage(
- viz::TransferableResource&,
- scoped_refptr<StaticBitmapImage>);
+ viz::TransferableResource* out_resource,
+ scoped_refptr<CanvasResource>);
void ReclaimResource(unsigned resource_id);
void ReclaimResources(const WTF::Vector<viz::ReturnedResource>& resources);
@@ -62,10 +63,6 @@ class PLATFORM_EXPORT OffscreenCanvasResourceProvider {
// TODO(junov): What does this do?
bool spare_lock = true;
- // Holds the backing for a gpu-backed resource. The Mailbox() of the image
- // is given to the display compositor to present it.
- scoped_refptr<StaticBitmapImage> image;
-
// Holds the backing for a software-backed resource.
std::unique_ptr<base::SharedMemory> shared_memory;
// The id given to the display compositor to display a software-backed
@@ -75,6 +72,9 @@ class PLATFORM_EXPORT OffscreenCanvasResourceProvider {
// Back-pointer to the OffscreenCanvasResourceProvider. FrameResource does
// not outlive the provider.
OffscreenCanvasResourceProvider* provider = nullptr;
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback;
+ gpu::SyncToken sync_token;
+ bool is_lost = false;
};
using ResourceMap = HashMap<unsigned, std::unique_ptr<FrameResource>>;
@@ -83,7 +83,7 @@ class PLATFORM_EXPORT OffscreenCanvasResourceProvider {
std::unique_ptr<FrameResource> CreateOrRecycleFrameResource();
void ReclaimResourceInternal(const ResourceMap::iterator&);
- OffscreenCanvasFrameDispatcher* frame_dispatcher_;
+ CanvasResourceDispatcher* frame_dispatcher_;
int width_;
int height_;
unsigned next_resource_id_ = 0;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/clip_display_item.cc
deleted file mode 100644
index 0d64b57d11c..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_display_item.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/paint/clip_display_item.h"
-
-#include "cc/paint/display_item_list.h"
-#include "third_party/blink/renderer/platform/geometry/float_rounded_rect.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/skia/include/core/SkScalar.h"
-
-namespace blink {
-
-void ClipDisplayItem::Replay(GraphicsContext& context) const {
- context.Save();
-
- // RoundedInnerRectClipper only cares about rounded-rect clips,
- // and passes an "infinite" rect clip; there is no reason to apply this clip.
- // TODO(fmalita): convert RoundedInnerRectClipper to a better suited
- // DisplayItem so we don't have to special-case its semantics.
- if (clip_rect_ != LayoutRect::InfiniteIntRect())
- context.ClipRect(clip_rect_, kAntiAliased);
-
- for (const FloatRoundedRect& rounded_rect : rounded_rect_clips_)
- context.ClipRoundedRect(rounded_rect);
-}
-
-void ClipDisplayItem::AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList& list) const {
- list.StartPaint();
- list.push<cc::SaveOp>();
- list.push<cc::ClipRectOp>(clip_rect_, SkClipOp::kIntersect,
- /*antialias=*/true);
- for (const FloatRoundedRect& rrect : rounded_rect_clips_) {
- SkRRect skrrect = rrect;
- if (skrrect.isRect()) {
- list.push<cc::ClipRectOp>(skrrect.rect(), SkClipOp::kIntersect,
- /*antialias=*/true);
- } else {
- list.push<cc::ClipRRectOp>(skrrect, SkClipOp::kIntersect,
- /*antialias=*/true);
- }
- }
- list.EndPaintOfPairedBegin();
-}
-
-void EndClipDisplayItem::Replay(GraphicsContext& context) const {
- context.Restore();
-}
-
-void EndClipDisplayItem::AppendToDisplayItemList(
- const FloatSize&,
- cc::DisplayItemList& list) const {
- list.StartPaint();
- list.push<cc::RestoreOp>();
- list.EndPaintOfPairedEnd();
-}
-
-#if DCHECK_IS_ON()
-void ClipDisplayItem::PropertiesAsJSON(JSONObject& json) const {
- DisplayItem::PropertiesAsJSON(json);
- json.SetString("clipRect", clip_rect_.ToString());
-}
-#endif
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/clip_display_item.h
deleted file mode 100644
index 006f66bc935..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_display_item.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_DISPLAY_ITEM_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_DISPLAY_ITEM_H_
-
-#include "SkRegion.h"
-#include "third_party/blink/renderer/platform/geometry/float_rounded_rect.h"
-#include "third_party/blink/renderer/platform/geometry/int_rect.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT ClipDisplayItem final : public PairedBeginDisplayItem {
- public:
- ClipDisplayItem(const DisplayItemClient& client,
- Type type,
- const IntRect& clip_rect)
- : PairedBeginDisplayItem(client, type, sizeof(*this)),
- clip_rect_(clip_rect) {
- DCHECK(IsClipType(type));
- }
-
- ClipDisplayItem(const DisplayItemClient& client,
- Type type,
- const IntRect& clip_rect,
- Vector<FloatRoundedRect>& rounded_rect_clips)
- : ClipDisplayItem(client, type, clip_rect) {
- rounded_rect_clips_.swap(rounded_rect_clips);
- }
-
- void Replay(GraphicsContext&) const override;
- void AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
- void PropertiesAsJSON(JSONObject&) const override;
-#endif
- bool Equals(const DisplayItem& other) const final {
- return DisplayItem::Equals(other) &&
- clip_rect_ ==
- static_cast<const ClipDisplayItem&>(other).clip_rect_ &&
- rounded_rect_clips_ ==
- static_cast<const ClipDisplayItem&>(other).rounded_rect_clips_;
- }
-
- const IntRect clip_rect_;
- Vector<FloatRoundedRect> rounded_rect_clips_;
-};
-
-class PLATFORM_EXPORT EndClipDisplayItem final : public PairedEndDisplayItem {
- public:
- EndClipDisplayItem(const DisplayItemClient& client, Type type)
- : PairedEndDisplayItem(client, type, sizeof(*this)) {
- DCHECK(IsEndClipType(type));
- }
-
- void Replay(GraphicsContext&) const override;
- void AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
- bool IsEndAndPairedWith(DisplayItem::Type other_type) const final {
- return DisplayItem::IsClipType(other_type);
- }
-#endif
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_DISPLAY_ITEM_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.cc
index 2f4ae851bbe..3714f0011e0 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.cc
@@ -5,22 +5,40 @@
#include "third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
+#include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h"
namespace blink {
-ClipPaintPropertyNode* ClipPaintPropertyNode::Root() {
+const ClipPaintPropertyNode& ClipPaintPropertyNode::Root() {
DEFINE_STATIC_REF(
ClipPaintPropertyNode, root,
- (ClipPaintPropertyNode::Create(
- nullptr, State{TransformPaintPropertyNode::Root(),
+ base::AdoptRef(new ClipPaintPropertyNode(
+ nullptr, State{&TransformPaintPropertyNode::Root(),
FloatRoundedRect(LayoutRect::InfiniteIntRect())})));
- return root;
+ return *root;
+}
+
+bool ClipPaintPropertyNode::Changed(
+ const PropertyTreeState& relative_to_state,
+ const TransformPaintPropertyNode* transform_not_to_check) const {
+ for (const auto* node = this; node && node != relative_to_state.Clip();
+ node = node->Parent()) {
+ if (node->NodeChanged())
+ return true;
+ if (node->LocalTransformSpace() != transform_not_to_check &&
+ node->LocalTransformSpace()->Changed(*relative_to_state.Transform()))
+ return true;
+ }
+
+ return false;
}
std::unique_ptr<JSONObject> ClipPaintPropertyNode::ToJSON() const {
auto json = JSONObject::Create();
if (Parent())
json->SetString("parent", String::Format("%p", Parent()));
+ if (NodeChanged())
+ json->SetBoolean("changed", true);
json->SetString("localTransformSpace",
String::Format("%p", state_.local_transform_space.get()));
json->SetString("rect", state_.clip_rect.ToString());
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h b/chromium/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h
index 1702e55b189..1e8cc85a5d8 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_PAINT_PROPERTY_NODE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_PAINT_PROPERTY_NODE_H_
+#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "third_party/blink/renderer/platform/geometry/float_rounded_rect.h"
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper_clip_cache.h"
@@ -16,6 +17,7 @@
namespace blink {
class GeometryMapperClipCache;
+class PropertyTreeState;
// A clip rect created by a css property such as "overflow" or "clip".
// Along with a reference to the transform space the clip rect is based on,
@@ -53,18 +55,16 @@ class PLATFORM_EXPORT ClipPaintPropertyNode
};
// This node is really a sentinel, and does not represent a real clip space.
- static ClipPaintPropertyNode* Root();
+ static const ClipPaintPropertyNode& Root();
static scoped_refptr<ClipPaintPropertyNode> Create(
- scoped_refptr<const ClipPaintPropertyNode> parent,
+ const ClipPaintPropertyNode& parent,
State&& state) {
- return base::AdoptRef(
- new ClipPaintPropertyNode(std::move(parent), std::move(state)));
+ return base::AdoptRef(new ClipPaintPropertyNode(&parent, std::move(state)));
}
- bool Update(scoped_refptr<const ClipPaintPropertyNode> parent,
- State&& state) {
- bool parent_changed = SetParent(parent);
+ bool Update(const ClipPaintPropertyNode& parent, State&& state) {
+ bool parent_changed = SetParent(&parent);
if (state == state_)
return parent_changed;
@@ -73,9 +73,17 @@ class PLATFORM_EXPORT ClipPaintPropertyNode
return true;
}
- bool EqualIgnoringHitTestRects(
- scoped_refptr<const ClipPaintPropertyNode> parent,
- const State& state) const {
+ // Checks if the accumulated clip from |this| to |relative_to_state.Clip()|
+ // has changed in the space of |relative_to_state.Transform()|. We check for
+ // changes of not only clip nodes, but also LocalTransformSpace relative to
+ // |relative_to_state.Transform()| of the clip nodes. |transform_not_to_check|
+ // specifies a transform node that the caller has checked or will check its
+ // change in other ways and this function should treat it as unchanged.
+ bool Changed(const PropertyTreeState& relative_to_state,
+ const TransformPaintPropertyNode* transform_not_to_check) const;
+
+ bool EqualIgnoringHitTestRects(const ClipPaintPropertyNode* parent,
+ const State& state) const {
return parent == Parent() && state_.EqualIgnoringHitTestRects(state);
}
@@ -115,9 +123,8 @@ class PLATFORM_EXPORT ClipPaintPropertyNode
size_t CacheMemoryUsageInBytes() const;
private:
- ClipPaintPropertyNode(scoped_refptr<const ClipPaintPropertyNode> parent,
- State&& state)
- : PaintPropertyNode(std::move(parent)), state_(std::move(state)) {}
+ ClipPaintPropertyNode(const ClipPaintPropertyNode* parent, State&& state)
+ : PaintPropertyNode(parent), state_(std::move(state)) {}
// For access to GetClipCache();
friend class GeometryMapper;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_path_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/clip_path_display_item.cc
deleted file mode 100644
index ee7c9fe9f6b..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_path_display_item.cc
+++ /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.
-
-#include "third_party/blink/renderer/platform/graphics/paint/clip_path_display_item.h"
-
-#include "cc/paint/display_item_list.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/path.h"
-#include "third_party/skia/include/core/SkScalar.h"
-
-namespace blink {
-
-void BeginClipPathDisplayItem::Replay(GraphicsContext& context) const {
- context.Save();
- context.ClipPath(clip_path_, kAntiAliased);
-}
-
-void BeginClipPathDisplayItem::AppendToDisplayItemList(
- const FloatSize&,
- cc::DisplayItemList& list) const {
- list.StartPaint();
- list.push<cc::SaveOp>();
- list.push<cc::ClipPathOp>(clip_path_, SkClipOp::kIntersect,
- /*antialias=*/true);
- list.EndPaintOfPairedBegin();
-}
-
-void EndClipPathDisplayItem::Replay(GraphicsContext& context) const {
- context.Restore();
-}
-
-void EndClipPathDisplayItem::AppendToDisplayItemList(
- const FloatSize&,
- cc::DisplayItemList& list) const {
- list.StartPaint();
- list.push<cc::RestoreOp>();
- list.EndPaintOfPairedEnd();
-}
-
-#if DCHECK_IS_ON()
-void BeginClipPathDisplayItem::PropertiesAsJSON(JSONObject& json) const {
- DisplayItem::PropertiesAsJSON(json);
- json.SetInteger("pathVerbs", clip_path_.countVerbs());
- json.SetInteger("pathPoints", clip_path_.countPoints());
- json.SetString("windRule",
- clip_path_.getFillType() == SkPath::kWinding_FillType
- ? "nonzero"
- : "evenodd");
-}
-
-#endif
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_path_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/clip_path_display_item.h
deleted file mode 100644
index b8ce24ab04d..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_path_display_item.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_PATH_DISPLAY_ITEM_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_PATH_DISPLAY_ITEM_H_
-
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/graphics/path.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/skia/include/core/SkPath.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT BeginClipPathDisplayItem final
- : public PairedBeginDisplayItem {
- public:
- BeginClipPathDisplayItem(const DisplayItemClient& client,
- const Path& clip_path)
- : PairedBeginDisplayItem(client, kBeginClipPath, sizeof(*this)),
- clip_path_(clip_path.GetSkPath()) {}
-
- void Replay(GraphicsContext&) const override;
- void AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
- void PropertiesAsJSON(JSONObject&) const override;
-#endif
- bool Equals(const DisplayItem& other) const final {
- return DisplayItem::Equals(other) &&
- clip_path_ ==
- static_cast<const BeginClipPathDisplayItem&>(other).clip_path_;
- }
-
- const SkPath clip_path_;
-};
-
-class PLATFORM_EXPORT EndClipPathDisplayItem final
- : public PairedEndDisplayItem {
- public:
- EndClipPathDisplayItem(const DisplayItemClient& client)
- : PairedEndDisplayItem(client, kEndClipPath, sizeof(*this)) {}
-
- void Replay(GraphicsContext&) const override;
- void AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
- bool IsEndAndPairedWith(DisplayItem::Type other_type) const final {
- return other_type == kBeginClipPath;
- }
-#endif
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_PATH_DISPLAY_ITEM_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_path_recorder.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/clip_path_recorder.cc
deleted file mode 100644
index 926a68aa003..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_path_recorder.cc
+++ /dev/null
@@ -1,29 +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/platform/graphics/paint/clip_path_recorder.h"
-
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_path_display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-
-namespace blink {
-
-ClipPathRecorder::ClipPathRecorder(GraphicsContext& context,
- const DisplayItemClient& client,
- const Path& clip_path)
- : context_(context), client_(client) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
- context_.GetPaintController().CreateAndAppend<BeginClipPathDisplayItem>(
- client_, clip_path);
-}
-
-ClipPathRecorder::~ClipPathRecorder() {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
- context_.GetPaintController().EndItem<EndClipPathDisplayItem>(client_);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_path_recorder.h b/chromium/third_party/blink/renderer/platform/graphics/paint/clip_path_recorder.h
deleted file mode 100644
index 97c7bc175b7..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_path_recorder.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_PATH_RECORDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_PATH_RECORDER_H_
-
-#include "third_party/blink/renderer/platform/graphics/paint/display_item_client.h"
-#include "third_party/blink/renderer/platform/graphics/path.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
-
-namespace blink {
-
-class GraphicsContext;
-
-class PLATFORM_EXPORT ClipPathRecorder {
- USING_FAST_MALLOC(ClipPathRecorder);
- WTF_MAKE_NONCOPYABLE(ClipPathRecorder);
-
- public:
- ClipPathRecorder(GraphicsContext&, const DisplayItemClient&, const Path&);
- ~ClipPathRecorder();
-
- private:
- GraphicsContext& context_;
- const DisplayItemClient& client_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_PATH_RECORDER_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_recorder.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/clip_recorder.cc
deleted file mode 100644
index 848fc7ecf47..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_recorder.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
-
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-
-namespace blink {
-
-ClipRecorder::ClipRecorder(GraphicsContext& context,
- const DisplayItemClient& client,
- DisplayItem::Type type,
- const IntRect& clip_rect)
- : client_(client), context_(context), type_(type) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
- context_.GetPaintController().CreateAndAppend<ClipDisplayItem>(client_, type,
- clip_rect);
-}
-
-ClipRecorder::~ClipRecorder() {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
- context_.GetPaintController().EndItem<EndClipDisplayItem>(
- client_, DisplayItem::ClipTypeToEndClipType(type_));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_recorder.h b/chromium/third_party/blink/renderer/platform/graphics/paint/clip_recorder.h
deleted file mode 100644
index a17c1d65b89..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/clip_recorder.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_RECORDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_RECORDER_H_
-
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
-
-namespace blink {
-
-class GraphicsContext;
-
-class PLATFORM_EXPORT ClipRecorder {
- DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
- WTF_MAKE_NONCOPYABLE(ClipRecorder);
-
- public:
- ClipRecorder(GraphicsContext&,
- const DisplayItemClient&,
- DisplayItem::Type,
- const IntRect& clip_rect);
- ~ClipRecorder();
-
- private:
- const DisplayItemClient& client_;
- GraphicsContext& context_;
- DisplayItem::Type type_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_RECORDER_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/compositing_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/compositing_display_item.cc
deleted file mode 100644
index 48b9c4f627b..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/compositing_display_item.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/paint/compositing_display_item.h"
-
-#include "cc/paint/display_item_list.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
-
-namespace blink {
-
-void BeginCompositingDisplayItem::Replay(GraphicsContext& context) const {
- context.BeginLayer(opacity_, xfer_mode_, has_bounds_ ? &bounds_ : nullptr,
- color_filter_);
-}
-
-void BeginCompositingDisplayItem::AppendToDisplayItemList(
- const FloatSize&,
- cc::DisplayItemList& list) const {
- DCHECK_GE(opacity_, 0.f);
- DCHECK_LE(opacity_, 1.f);
-
- // TODO(ajuma): This should really be rounding instead of flooring the alpha
- // value, but that breaks slimming paint reftests.
- auto alpha = static_cast<uint8_t>(gfx::ToFlooredInt(255 * opacity_));
- sk_sp<SkColorFilter> color_filter =
- GraphicsContext::WebCoreColorFilterToSkiaColorFilter(color_filter_);
- SkRect sk_bounds = bounds_;
- SkRect* maybe_bounds = has_bounds_ ? &sk_bounds : nullptr;
-
- if (xfer_mode_ == SkBlendMode::kSrcOver && !color_filter) {
- list.StartPaint();
- list.push<cc::SaveLayerAlphaOp>(maybe_bounds, alpha, false);
- if (maybe_bounds) {
- list.push<cc::ClipRectOp>(sk_bounds, SkClipOp::kIntersect, false);
- }
- list.EndPaintOfPairedBegin();
- return;
- }
-
- cc::PaintFlags flags;
- flags.setBlendMode(xfer_mode_);
- flags.setAlpha(alpha);
- flags.setColorFilter(std::move(color_filter));
-
- list.StartPaint();
- list.push<cc::SaveLayerOp>(maybe_bounds, &flags);
- if (maybe_bounds) {
- list.push<cc::ClipRectOp>(sk_bounds, SkClipOp::kIntersect, false);
- }
- list.EndPaintOfPairedBegin();
-}
-
-#if DCHECK_IS_ON()
-void BeginCompositingDisplayItem::PropertiesAsJSON(JSONObject& json) const {
- DisplayItem::PropertiesAsJSON(json);
- json.SetInteger("xferMode", static_cast<int>(xfer_mode_));
- json.SetDouble("opacity", opacity_);
- if (has_bounds_)
- json.SetString("bounds", bounds_.ToString());
-}
-#endif
-
-void EndCompositingDisplayItem::Replay(GraphicsContext& context) const {
- context.EndLayer();
-}
-
-void EndCompositingDisplayItem::AppendToDisplayItemList(
- const FloatSize&,
- cc::DisplayItemList& list) const {
- list.StartPaint();
- list.push<cc::RestoreOp>();
- list.EndPaintOfPairedEnd();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/compositing_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/compositing_display_item.h
deleted file mode 100644
index fb2e26c413f..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/compositing_display_item.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_COMPOSITING_DISPLAY_ITEM_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_COMPOSITING_DISPLAY_ITEM_H_
-
-#include "third_party/blink/renderer/platform/geometry/float_rect.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/skia/include/core/SkBlendMode.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT BeginCompositingDisplayItem final
- : public PairedBeginDisplayItem {
- public:
- BeginCompositingDisplayItem(const DisplayItemClient& client,
- const SkBlendMode xfer_mode,
- const float opacity,
- const FloatRect* bounds,
- ColorFilter color_filter = kColorFilterNone)
- : PairedBeginDisplayItem(client, kBeginCompositing, sizeof(*this)),
- xfer_mode_(xfer_mode),
- opacity_(opacity),
- has_bounds_(bounds),
- color_filter_(color_filter) {
- if (bounds)
- bounds_ = FloatRect(*bounds);
- }
-
- void Replay(GraphicsContext&) const override;
- void AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
- void PropertiesAsJSON(JSONObject&) const override;
-#endif
- bool Equals(const DisplayItem& other) const final {
- return DisplayItem::Equals(other) &&
- xfer_mode_ == static_cast<const BeginCompositingDisplayItem&>(other)
- .xfer_mode_ &&
- opacity_ == static_cast<const BeginCompositingDisplayItem&>(other)
- .opacity_ &&
- has_bounds_ == static_cast<const BeginCompositingDisplayItem&>(other)
- .has_bounds_ &&
- bounds_ ==
- static_cast<const BeginCompositingDisplayItem&>(other).bounds_ &&
- color_filter_ ==
- static_cast<const BeginCompositingDisplayItem&>(other)
- .color_filter_;
- }
-
- const SkBlendMode xfer_mode_;
- const float opacity_;
- bool has_bounds_;
- FloatRect bounds_;
- ColorFilter color_filter_;
-};
-
-class PLATFORM_EXPORT EndCompositingDisplayItem final
- : public PairedEndDisplayItem {
- public:
- EndCompositingDisplayItem(const DisplayItemClient& client)
- : PairedEndDisplayItem(client, kEndCompositing, sizeof(*this)) {}
-
- void Replay(GraphicsContext&) const override;
- void AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
- bool IsEndAndPairedWith(DisplayItem::Type other_type) const final {
- return other_type == kBeginCompositing;
- }
-#endif
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_COMPOSITING_DISPLAY_ITEM_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/compositing_recorder.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/compositing_recorder.cc
deleted file mode 100644
index 7ea95979dca..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/compositing_recorder.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/paint/compositing_recorder.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/compositing_display_item.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 {
-
-CompositingRecorder::CompositingRecorder(GraphicsContext& graphics_context,
- const DisplayItemClient& client,
- const SkBlendMode xfer_mode,
- const float opacity,
- const FloatRect* bounds,
- ColorFilter color_filter)
- : client_(client), graphics_context_(graphics_context) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
- graphics_context.GetPaintController()
- .CreateAndAppend<BeginCompositingDisplayItem>(client_, xfer_mode, opacity,
- bounds, color_filter);
-}
-
-CompositingRecorder::~CompositingRecorder() {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
- graphics_context_.GetPaintController().EndItem<EndCompositingDisplayItem>(
- client_);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/compositing_recorder.h b/chromium/third_party/blink/renderer/platform/graphics/paint/compositing_recorder.h
deleted file mode 100644
index 33895697af1..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/compositing_recorder.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_COMPOSITING_RECORDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_COMPOSITING_RECORDER_H_
-
-#include "third_party/blink/renderer/platform/geometry/float_rect.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/skia/include/core/SkBlendMode.h"
-
-namespace blink {
-
-class GraphicsContext;
-
-class PLATFORM_EXPORT CompositingRecorder {
- USING_FAST_MALLOC(CompositingRecorder);
-
- public:
- // If bounds is provided, the content will be explicitly clipped to those
- // bounds.
- CompositingRecorder(GraphicsContext&,
- const DisplayItemClient&,
- const SkBlendMode,
- const float opacity,
- const FloatRect* bounds = nullptr,
- ColorFilter = kColorFilterNone);
-
- ~CompositingRecorder();
-
- private:
- const DisplayItemClient& client_;
- GraphicsContext& graphics_context_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_COMPOSITING_RECORDER_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.h b/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.h
index 324659b3d2b..bde6db06165 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect.h
@@ -41,6 +41,8 @@ class PLATFORM_EXPORT CullRect {
const IntRect& overflow_clip_rect,
const AffineTransform& local_to_parent_transform);
+ const IntRect& Rect() const { return rect_; }
+
String ToString() const { return rect_.ToString(); }
private:
@@ -50,18 +52,7 @@ class PLATFORM_EXPORT CullRect {
friend class CullRectTest;
- // TODO(chrishtr): temporary while we implement CullRect everywhere.
- friend class FramePainter;
- friend class GridPainter;
- friend class SVGForeignObjectPainter;
- friend class SVGInlineTextBoxPainter;
- friend class SVGPaintContext;
- friend class SVGRootInlineBoxPainter;
- friend class SVGShapePainter;
- friend class TableRowPainter;
friend class TableSectionPainter;
- friend class ThemePainterMac;
- friend class WebPluginContainerImpl;
};
inline bool operator==(const CullRect& a, const CullRect& b) {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect_test.cc
index c543a274bbc..2690dd8e06a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/cull_rect_test.cc
@@ -36,7 +36,7 @@ TEST_F(CullRectTest, IntersectsCullRectWithTransform) {
AffineTransform transform;
transform.Translate(-2, -2);
- EXPECT_TRUE(cull_rect.IntersectsCullRect(transform, IntRect(51, 51, 1, 1)));
+ EXPECT_TRUE(cull_rect.IntersectsCullRect(transform, FloatRect(51, 51, 1, 1)));
EXPECT_FALSE(cull_rect.IntersectsCullRect(IntRect(52, 52, 1, 1)));
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.cc
index 7fd7f5ae3be..307b7b6d922 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.cc
@@ -43,10 +43,8 @@ static WTF::String PaintPhaseAsDebugString(int paint_phase) {
return "PaintPhaseSelection";
case 9:
return "PaintPhaseTextClip";
- case 10:
- return "PaintPhaseMask";
case DisplayItem::kPaintPhaseMax:
- return "PaintPhaseClippingMask";
+ return "PaintPhaseMask";
default:
NOTREACHED();
return "Unknown";
@@ -72,6 +70,8 @@ static WTF::String SpecialDrawingTypeAsDebugString(DisplayItem::Type type) {
switch (type) {
DEBUG_STRING_CASE(BoxDecorationBackground);
DEBUG_STRING_CASE(Caret);
+ DEBUG_STRING_CASE(CapsLockIndicator);
+ DEBUG_STRING_CASE(ClippingMask);
DEBUG_STRING_CASE(ColumnRules);
DEBUG_STRING_CASE(DebugDrawing);
DEBUG_STRING_CASE(DocumentBackground);
@@ -81,6 +81,7 @@ static WTF::String SpecialDrawingTypeAsDebugString(DisplayItem::Type type) {
DEBUG_STRING_CASE(SVGImage);
DEBUG_STRING_CASE(LinkHighlight);
DEBUG_STRING_CASE(ImageAreaFocusRing);
+ DEBUG_STRING_CASE(OverflowControls);
DEBUG_STRING_CASE(PageOverlay);
DEBUG_STRING_CASE(PopupContainerBorder);
DEBUG_STRING_CASE(PopupListBoxBackground);
@@ -109,6 +110,7 @@ static WTF::String SpecialDrawingTypeAsDebugString(DisplayItem::Type type) {
DEBUG_STRING_CASE(WebPlugin);
DEBUG_STRING_CASE(WebFont);
DEBUG_STRING_CASE(ReflectionMask);
+ DEBUG_STRING_CASE(HitTest);
DEFAULT_CASE;
}
@@ -130,50 +132,6 @@ static String ForeignLayerTypeAsDebugString(DisplayItem::Type type) {
}
}
-static String ScrollHitTestTypeAsDebugString(DisplayItem::Type type) {
- switch (type) {
- DEBUG_STRING_CASE(ScrollHitTest);
- DEFAULT_CASE;
- }
-}
-
-static WTF::String ClipTypeAsDebugString(DisplayItem::Type type) {
- PAINT_PHASE_BASED_DEBUG_STRINGS(ClipBox);
- PAINT_PHASE_BASED_DEBUG_STRINGS(ClipColumnBounds);
- PAINT_PHASE_BASED_DEBUG_STRINGS(ClipLayerFragment);
-
- switch (type) {
- DEBUG_STRING_CASE(ClipFileUploadControlRect);
- DEBUG_STRING_CASE(ClipFrameToVisibleContentRect);
- DEBUG_STRING_CASE(ClipFrameScrollbars);
- DEBUG_STRING_CASE(ClipLayerBackground);
- DEBUG_STRING_CASE(ClipLayerColumnBounds);
- DEBUG_STRING_CASE(ClipLayerFilter);
- DEBUG_STRING_CASE(ClipLayerForeground);
- DEBUG_STRING_CASE(ClipLayerParent);
- DEBUG_STRING_CASE(ClipLayerOverflowControls);
- DEBUG_STRING_CASE(ClipPopupListBoxFrame);
- DEBUG_STRING_CASE(ClipScrollbarsToBoxBounds);
- DEBUG_STRING_CASE(ClipSelectionImage);
- DEFAULT_CASE;
- }
-}
-
-static String ScrollTypeAsDebugString(DisplayItem::Type type) {
- PAINT_PHASE_BASED_DEBUG_STRINGS(Scroll);
- switch (type) {
- DEBUG_STRING_CASE(ScrollOverflowControls);
- DEFAULT_CASE;
- }
-}
-
-static String Transform3DTypeAsDebugString(DisplayItem::Type type) {
- switch (type) {
- DEBUG_STRING_CASE(Transform3DElementTransform);
- DEFAULT_CASE;
- }
-}
-
WTF::String DisplayItem::TypeAsDebugString(Type type) {
if (IsDrawingType(type))
return DrawingTypeAsDebugString(type);
@@ -181,43 +139,13 @@ WTF::String DisplayItem::TypeAsDebugString(Type type) {
if (IsForeignLayerType(type))
return ForeignLayerTypeAsDebugString(type);
- if (IsClipType(type))
- return ClipTypeAsDebugString(type);
- if (IsEndClipType(type))
- return "End" + ClipTypeAsDebugString(endClipTypeToClipType(type));
-
- PAINT_PHASE_BASED_DEBUG_STRINGS(FloatClip);
- if (type == kFloatClipClipPathBounds)
- return "FloatClipClipPathBounds";
- if (IsEndFloatClipType(type))
- return "End" + TypeAsDebugString(endFloatClipTypeToFloatClipType(type));
-
- if (IsScrollType(type))
- return ScrollTypeAsDebugString(type);
- if (IsEndScrollType(type))
- return "End" + ScrollTypeAsDebugString(endScrollTypeToScrollType(type));
-
+ PAINT_PHASE_BASED_DEBUG_STRINGS(Clip);
+ PAINT_PHASE_BASED_DEBUG_STRINGS(Scroll);
PAINT_PHASE_BASED_DEBUG_STRINGS(SVGTransform);
PAINT_PHASE_BASED_DEBUG_STRINGS(SVGEffect);
- if (IsTransform3DType(type))
- return Transform3DTypeAsDebugString(type);
- if (IsEndTransform3DType(type))
- return "End" + Transform3DTypeAsDebugString(
- endTransform3DTypeToTransform3DType(type));
-
- if (IsScrollHitTestType(type))
- return ScrollHitTestTypeAsDebugString(type);
-
switch (type) {
- DEBUG_STRING_CASE(BeginFilter);
- DEBUG_STRING_CASE(EndFilter);
- DEBUG_STRING_CASE(BeginCompositing);
- DEBUG_STRING_CASE(EndCompositing);
- DEBUG_STRING_CASE(BeginTransform);
- DEBUG_STRING_CASE(EndTransform);
- DEBUG_STRING_CASE(BeginClipPath);
- DEBUG_STRING_CASE(EndClipPath);
+ DEBUG_STRING_CASE(ScrollHitTest);
DEBUG_STRING_CASE(LayerChunkBackground);
DEBUG_STRING_CASE(LayerChunkNegativeZOrderChildren);
DEBUG_STRING_CASE(LayerChunkDescendantBackgrounds);
@@ -243,8 +171,6 @@ void DisplayItem::PropertiesAsJSON(JSONObject& json) const {
json.SetString("visualRect", VisualRect().ToString());
if (OutsetForRasterEffects())
json.SetDouble("outset", OutsetForRasterEffects());
- if (skipped_cache_)
- json.SetBoolean("skippedCache", true);
}
#endif
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.h
index 430a896e2f5..be665246f7b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item.h
@@ -12,7 +12,6 @@
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#if DCHECK_IS_ON()
#include "third_party/blink/renderer/platform/json/json_values.h"
@@ -35,7 +34,7 @@ class PLATFORM_EXPORT DisplayItem {
public:
enum {
// Must be kept in sync with core/paint/PaintPhase.h.
- kPaintPhaseMax = 11,
+ kPaintPhaseMax = 10,
};
// A display item type uniquely identifies a display item of a client.
@@ -58,24 +57,14 @@ class PLATFORM_EXPORT DisplayItem {
// <Category>[<Subset>]PaintPhaseFirst + PaintPhaseMax;
// - DEFINE_PAINT_PHASE_CONVERSION_METHOD(<Category>[<Subset>]) to define
// paintPhaseTo<Category>[<Subset>]Type(PaintPhase) method.
- //
- // A category can be derived from another category, containing types each of
- // which corresponds to a value of the latter category:
- // - In enum Type:
- // - enum value <Category>First;
- // - enum value <Category>Last =
- // <Category>First + <BaseCategory>Last - <BaseCategory>First;
- // - DEFINE_CONVERSION_METHODS(<Category>,
- // <category>,
- // <BaseCategory>,
- // <baseCategory>)
- // to define methods to convert types between the categories.
enum Type {
kDrawingFirst,
kDrawingPaintPhaseFirst = kDrawingFirst,
kDrawingPaintPhaseLast = kDrawingFirst + kPaintPhaseMax,
kBoxDecorationBackground,
+ kCapsLockIndicator,
kCaret,
+ kClippingMask,
kColumnRules,
kDebugDrawing,
kDocumentBackground,
@@ -85,6 +74,7 @@ class PLATFORM_EXPORT DisplayItem {
kSVGImage,
kLinkHighlight,
kImageAreaFocusRing,
+ kOverflowControls,
kPageOverlay,
kPopupContainerBorder,
kPopupListBoxBackground,
@@ -113,7 +103,12 @@ class PLATFORM_EXPORT DisplayItem {
kWebPlugin,
kWebFont,
kReflectionMask,
- kDrawingLast = kReflectionMask,
+ // Compositor hit testing requires that layers are created and sized to
+ // include content that does not paint. Hit test display items ensure
+ // a layer exists and is sized properly even if no content would otherwise
+ // be painted.
+ kHitTest,
+ kDrawingLast = kHitTest,
kForeignLayerFirst,
kForeignLayerCanvas = kForeignLayerFirst,
@@ -123,47 +118,11 @@ class PLATFORM_EXPORT DisplayItem {
kForeignLayerContentsWrapper,
kForeignLayerLast = kForeignLayerContentsWrapper,
- kClipFirst,
- kClipBoxPaintPhaseFirst = kClipFirst,
- kClipBoxPaintPhaseLast = kClipBoxPaintPhaseFirst + kPaintPhaseMax,
- kClipColumnBoundsPaintPhaseFirst,
- kClipColumnBoundsPaintPhaseLast =
- kClipColumnBoundsPaintPhaseFirst + kPaintPhaseMax,
- kClipLayerFragmentPaintPhaseFirst,
- kClipLayerFragmentPaintPhaseLast =
- kClipLayerFragmentPaintPhaseFirst + kPaintPhaseMax,
- kClipFileUploadControlRect,
- kClipFrameToVisibleContentRect,
- kClipFrameScrollbars,
- kClipLayerBackground,
- kClipLayerColumnBounds,
- kClipLayerFilter,
- kClipLayerForeground,
- kClipLayerParent,
- kClipLayerOverflowControls,
- kClipPopupListBoxFrame,
- kClipScrollbarsToBoxBounds,
- kClipSelectionImage,
- kClipLast = kClipSelectionImage,
-
- kEndClipFirst,
- kEndClipLast = kEndClipFirst + kClipLast - kClipFirst,
-
- kFloatClipFirst,
- kFloatClipPaintPhaseFirst = kFloatClipFirst,
- kFloatClipPaintPhaseLast = kFloatClipFirst + kPaintPhaseMax,
- kFloatClipClipPathBounds,
- kFloatClipLast = kFloatClipClipPathBounds,
- kEndFloatClipFirst,
- kEndFloatClipLast = kEndFloatClipFirst + kFloatClipLast - kFloatClipFirst,
-
- kScrollFirst,
- kScrollPaintPhaseFirst = kScrollFirst,
+ kClipPaintPhaseFirst,
+ kClipPaintPhaseLast = kClipPaintPhaseFirst + kPaintPhaseMax,
+
+ kScrollPaintPhaseFirst,
kScrollPaintPhaseLast = kScrollPaintPhaseFirst + kPaintPhaseMax,
- kScrollOverflowControls,
- kScrollLast = kScrollOverflowControls,
- kEndScrollFirst,
- kEndScrollLast = kEndScrollFirst + kScrollLast - kScrollFirst,
kSVGTransformPaintPhaseFirst,
kSVGTransformPaintPhaseLast = kSVGTransformPaintPhaseFirst + kPaintPhaseMax,
@@ -171,21 +130,6 @@ class PLATFORM_EXPORT DisplayItem {
kSVGEffectPaintPhaseFirst,
kSVGEffectPaintPhaseLast = kSVGEffectPaintPhaseFirst + kPaintPhaseMax,
- kTransform3DFirst,
- kTransform3DElementTransform = kTransform3DFirst,
- kTransform3DLast = kTransform3DElementTransform,
- kEndTransform3DFirst,
- kEndTransform3DLast =
- kEndTransform3DFirst + kTransform3DLast - kTransform3DFirst,
-
- kBeginFilter,
- kEndFilter,
- kBeginCompositing,
- kEndCompositing,
- kBeginTransform,
- kEndTransform,
- kBeginClipPath,
- kEndClipPath,
kScrollHitTest,
kLayerChunkBackground,
@@ -199,6 +143,8 @@ class PLATFORM_EXPORT DisplayItem {
kTypeLast = kUninitializedType
};
+ // Some fields are copied from |client|, because we need to access them in
+ // later paint cycles when |client| may have been destroyed.
DisplayItem(const DisplayItemClient& client, Type type, size_t derived_size)
: client_(&client),
visual_rect_(client.VisualRect()),
@@ -206,7 +152,8 @@ class PLATFORM_EXPORT DisplayItem {
type_(type),
derived_size_(derived_size),
fragment_(0),
- skipped_cache_(false),
+ // TODO(pdr): Should this return true for IsScrollHitTestType too?
+ is_cacheable_(client.IsCacheable() && IsDrawingType(type)),
is_tombstone_(false) {
// |derived_size| must fit in |derived_size_|.
// If it doesn't, enlarge |derived_size_| and fix this assert.
@@ -268,11 +215,6 @@ class PLATFORM_EXPORT DisplayItem {
fragment_ = fragment;
}
- // For PaintController only. Painters should use DisplayItemCacheSkipper
- // instead.
- void SetSkippedCache() { skipped_cache_ = true; }
- bool SkippedCache() const { return skipped_cache_; }
-
// Appends this display item to the cc::DisplayItemList, if applicable.
// |visual_rect_offset| is the offset between the space of the GraphicsLayer
// which owns the display item and the coordinate space of VisualRect().
@@ -287,28 +229,6 @@ class PLATFORM_EXPORT DisplayItem {
} \
bool Is##Category() const { return Is##Category##Type(GetType()); }
-#define DEFINE_CONVERSION_METHODS(Category1, category1, Category2, category2) \
- static Type Category1##TypeTo##Category2##Type(Type type) { \
- static_assert(k##Category1##Last - k##Category1##First == \
- k##Category2##Last - k##Category2##First, \
- "Categories " #Category1 " and " #Category2 \
- " should have same number of enum values. See comments of " \
- "DisplayItem::Type"); \
- DCHECK(Is##Category1##Type(type)); \
- return static_cast<Type>(type - k##Category1##First + \
- k##Category2##First); \
- } \
- static Type category2##TypeTo##Category1##Type(Type type) { \
- DCHECK(Is##Category2##Type(type)); \
- return static_cast<Type>(type - k##Category2##First + \
- k##Category1##First); \
- }
-
-#define DEFINE_PAIRED_CATEGORY_METHODS(Category, category) \
- DEFINE_CATEGORY_METHODS(Category) \
- DEFINE_CATEGORY_METHODS(End##Category) \
- DEFINE_CONVERSION_METHODS(Category, category, End##Category, end##Category)
-
#define DEFINE_PAINT_PHASE_CONVERSION_METHOD(Category) \
static Type PaintPhaseTo##Category##Type(PaintPhase paint_phase) { \
static_assert( \
@@ -325,47 +245,20 @@ class PLATFORM_EXPORT DisplayItem {
DEFINE_CATEGORY_METHODS(ForeignLayer)
- DEFINE_PAIRED_CATEGORY_METHODS(Clip, clip)
- DEFINE_PAINT_PHASE_CONVERSION_METHOD(ClipLayerFragment)
- DEFINE_PAINT_PHASE_CONVERSION_METHOD(ClipBox)
- DEFINE_PAINT_PHASE_CONVERSION_METHOD(ClipColumnBounds)
-
- DEFINE_PAIRED_CATEGORY_METHODS(FloatClip, floatClip)
- DEFINE_PAINT_PHASE_CONVERSION_METHOD(FloatClip)
-
- DEFINE_PAIRED_CATEGORY_METHODS(Scroll, scroll)
+ DEFINE_PAINT_PHASE_CONVERSION_METHOD(Clip)
DEFINE_PAINT_PHASE_CONVERSION_METHOD(Scroll)
-
DEFINE_PAINT_PHASE_CONVERSION_METHOD(SVGTransform)
DEFINE_PAINT_PHASE_CONVERSION_METHOD(SVGEffect)
- DEFINE_PAIRED_CATEGORY_METHODS(Transform3D, transform3D)
-
- static bool IsScrollHitTestType(Type type) { return type == kScrollHitTest; }
- bool IsScrollHitTest() const { return IsScrollHitTestType(GetType()); }
+ bool IsScrollHitTest() const { return type_ == kScrollHitTest; }
- // TODO(pdr): Should this return true for IsScrollHitTestType too?
- static bool IsCacheableType(Type type) { return IsDrawingType(type); }
- bool IsCacheable() const {
- return !SkippedCache() && IsCacheableType(GetType());
- }
-
- virtual bool IsBegin() const { return false; }
- virtual bool IsEnd() const { return false; }
-
-#if DCHECK_IS_ON()
- virtual bool IsEndAndPairedWith(DisplayItem::Type other_type) const {
- return false;
- }
-#endif
+ bool IsCacheable() const { return is_cacheable_; }
virtual bool Equals(const DisplayItem& other) const {
// Failure of this DCHECK would cause bad casts in subclasses.
SECURITY_CHECK(!is_tombstone_);
return client_ == other.client_ && type_ == other.type_ &&
- fragment_ == other.fragment_ &&
- derived_size_ == other.derived_size_ &&
- skipped_cache_ == other.skipped_cache_;
+ fragment_ == other.fragment_ && derived_size_ == other.derived_size_;
}
// True if this DisplayItem is the tombstone/"dead display item" as part of
@@ -389,7 +282,7 @@ class PLATFORM_EXPORT DisplayItem {
// The default DisplayItem constructor is only used by ContiguousContainer::
// AppendByMoving() where a tombstone DisplayItem is constructed at the source
// location. Only set is_tombstone_ to true, leaving other fields as-is so
- // that we can get their original values for debugging. |visual_rect_| and
+ // that we can get their original values. |visual_rect_| and
// |outset_for_raster_effects_| are special, see DisplayItemList::
// AppendByMoving().
DisplayItem() : is_tombstone_(true) {}
@@ -402,7 +295,7 @@ class PLATFORM_EXPORT DisplayItem {
unsigned type_ : 8;
unsigned derived_size_ : 8; // size of the actual derived class
unsigned fragment_ : 14;
- unsigned skipped_cache_ : 1;
+ unsigned is_cacheable_ : 1;
unsigned is_tombstone_ : 1;
};
@@ -414,36 +307,6 @@ inline bool operator!=(const DisplayItem::Id& a, const DisplayItem::Id& b) {
return !(a == b);
}
-class PLATFORM_EXPORT PairedBeginDisplayItem : public DisplayItem {
- protected:
- PairedBeginDisplayItem(const DisplayItemClient& client,
- Type type,
- size_t derived_size)
- : DisplayItem(client, type, derived_size) {
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
- }
-
- private:
- bool IsBegin() const final { return true; }
-};
-
-class PLATFORM_EXPORT PairedEndDisplayItem : public DisplayItem {
- protected:
- PairedEndDisplayItem(const DisplayItemClient& client,
- Type type,
- size_t derived_size)
- : DisplayItem(client, type, derived_size) {
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
- }
-
-#if DCHECK_IS_ON()
- bool IsEndAndPairedWith(DisplayItem::Type other_type) const override = 0;
-#endif
-
- private:
- bool IsEnd() const final { return true; }
-};
-
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_DISPLAY_ITEM_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h
index 17ec4e8148e..b2c7eb6c39e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h
@@ -5,16 +5,15 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_DISPLAY_ITEM_CACHE_SKIPPER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_DISPLAY_ITEM_CACHE_SKIPPER_H_
+#include "base/macros.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
namespace blink {
class DisplayItemCacheSkipper final {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
- WTF_MAKE_NONCOPYABLE(DisplayItemCacheSkipper);
public:
DisplayItemCacheSkipper(GraphicsContext& context) : context_(context) {
@@ -26,6 +25,8 @@ class DisplayItemCacheSkipper final {
private:
GraphicsContext& context_;
+
+ DISALLOW_COPY_AND_ASSIGN(DisplayItemCacheSkipper);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_client.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_client.cc
index 5fac148c2da..c739385ef21 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_client.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_client.cc
@@ -11,21 +11,17 @@
namespace blink {
-DisplayItemClient::CacheGenerationOrInvalidationReason::ValueType
- DisplayItemClient::CacheGenerationOrInvalidationReason::next_generation_ =
- kFirstValidGeneration;
-
#if DCHECK_IS_ON()
HashSet<const DisplayItemClient*>* g_live_display_item_clients = nullptr;
-DisplayItemClient::DisplayItemClient() {
+void DisplayItemClient::OnCreate() {
if (!g_live_display_item_clients)
g_live_display_item_clients = new HashSet<const DisplayItemClient*>();
g_live_display_item_clients->insert(this);
}
-DisplayItemClient::~DisplayItemClient() {
+void DisplayItemClient::OnDestroy() {
g_live_display_item_clients->erase(this);
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_client.h b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_client.h
index 680e5f33f0f..cda00f638cc 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_client.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_client.h
@@ -17,20 +17,26 @@ namespace blink {
// DisplayItemClient object should live at least longer than the document cycle
// in which its display items are created during painting. After the document
// cycle, a pointer/reference to DisplayItemClient should be no longer
-// dereferenced unless we can make sure the client is still valid.
+// dereferenced unless we can make sure the client is still alive.
class PLATFORM_EXPORT DisplayItemClient {
public:
+ DisplayItemClient()
+ : paint_invalidation_reason_(PaintInvalidationReason::kJustCreated) {
#if DCHECK_IS_ON()
- DisplayItemClient();
- virtual ~DisplayItemClient();
+ OnCreate();
+#endif
+ }
+ virtual ~DisplayItemClient() {
+#if DCHECK_IS_ON()
+ OnDestroy();
+#endif
+ }
+#if DCHECK_IS_ON()
// Tests if this DisplayItemClient object has been created and has not been
// deleted yet.
bool IsAlive() const;
static String SafeDebugName(const DisplayItemClient&, bool known_to_be_safe);
-#else
- DisplayItemClient() {}
- virtual ~DisplayItemClient() {}
#endif
virtual String DebugName() const = 0;
@@ -46,13 +52,14 @@ class PLATFORM_EXPORT DisplayItemClient {
// effects that might expand the rastered pixel area.
virtual float VisualRectOutsetForRasterEffects() const { return 0; }
- // The rect that needs to be invalidated partially in this client. It's in the
- // same coordinate space as VisualRect().
- virtual LayoutRect PartialInvalidationRect() const { return LayoutRect(); }
+ // The rect that needs to be invalidated partially for rasterization in this
+ // client. It's in the same coordinate space as VisualRect().
+ virtual LayoutRect PartialInvalidationVisualRect() const {
+ return LayoutRect();
+ }
- // Called by PaintController::CommitNewDisplayItems() for all clients after
- // painting.
- virtual void ClearPartialInvalidationRect() const {}
+ // Called by PaintController::FinishCycle() for all clients after painting.
+ virtual void ClearPartialInvalidationVisualRect() const {}
// This is declared here instead of in LayoutObject for verifying the
// condition in DrawingRecorder.
@@ -73,107 +80,54 @@ class PLATFORM_EXPORT DisplayItemClient {
// paint new display items that are not cached or to no longer paint some
// cached display items without calling this method.
// See PaintController::ClientCacheIsValid() for more details.
- void SetDisplayItemsUncached(
+ void Invalidate(
PaintInvalidationReason reason = PaintInvalidationReason::kFull) const {
- cache_generation_or_invalidation_reason_.Invalidate(reason);
+ // If a full invalidation reason is already set, do not overwrite it with
+ // a new reason.
+ if (IsFullPaintInvalidationReason(GetPaintInvalidationReason()) &&
+ // However, kUncacheable overwrites any other reason.
+ reason != PaintInvalidationReason::kUncacheable)
+ return;
+ paint_invalidation_reason_ = reason;
}
PaintInvalidationReason GetPaintInvalidationReason() const {
- return cache_generation_or_invalidation_reason_
- .GetPaintInvalidationReason();
+ return paint_invalidation_reason_;
}
// A client is considered "just created" if its display items have never been
- // committed.
+ // validated by any PaintController since it's created.
bool IsJustCreated() const {
- return cache_generation_or_invalidation_reason_.IsJustCreated();
+ return paint_invalidation_reason_ == PaintInvalidationReason::kJustCreated;
}
- void ClearIsJustCreated() const {
- cache_generation_or_invalidation_reason_.ClearIsJustCreated();
+
+ // Whether the client is cacheable. The uncacheable status is set when the
+ // client produces any display items that skipped caching of any
+ // PaintController.
+ bool IsCacheable() const {
+ return paint_invalidation_reason_ != PaintInvalidationReason::kUncacheable;
+ }
+
+ // True if the client's display items are cached in PaintControllers without
+ // needing to update.
+ bool IsValid() const {
+ return paint_invalidation_reason_ == PaintInvalidationReason::kNone;
}
private:
friend class FakeDisplayItemClient;
friend class PaintController;
- // Holds a unique cache generation id of DisplayItemClients and
- // PaintControllers, or PaintInvalidationReason if the DisplayItemClient or
- // PaintController is invalidated.
- //
- // A paint controller sets its cache generation to
- // DisplayItemCacheGeneration::next() at the end of each
- // commitNewDisplayItems, and updates the cache generation of each client with
- // cached drawings by calling DisplayItemClient::setDisplayItemsCached(). A
- // display item is treated as validly cached in a paint controller if its
- // cache generation matches the paint controller's cache generation.
- //
- // SPv1 only: If a display item is painted on multiple paint controllers,
- // because cache generations are unique, the client's cache generation matches
- // the last paint controller only. The client will be treated as invalid on
- // other paint controllers regardless if it's validly cached by these paint
- // controllers. This situation is very rare (about 0.07% of clients were
- // painted on multiple paint controllers) so the performance penalty is
- // trivial.
- class PLATFORM_EXPORT CacheGenerationOrInvalidationReason {
- DISALLOW_NEW();
-
- public:
- CacheGenerationOrInvalidationReason() : value_(kJustCreated) {}
-
- void Invalidate(
- PaintInvalidationReason reason = PaintInvalidationReason::kFull) {
- if (value_ != kJustCreated)
- value_ = static_cast<ValueType>(reason);
- }
-
- static CacheGenerationOrInvalidationReason Next() {
- // In case the value overflowed in the previous call.
- if (next_generation_ < kFirstValidGeneration)
- next_generation_ = kFirstValidGeneration;
- return CacheGenerationOrInvalidationReason(next_generation_++);
- }
-
- bool Matches(const CacheGenerationOrInvalidationReason& other) const {
- return value_ >= kFirstValidGeneration &&
- other.value_ >= kFirstValidGeneration && value_ == other.value_;
- }
-
- PaintInvalidationReason GetPaintInvalidationReason() const {
- if (value_ == kJustCreated)
- return PaintInvalidationReason::kAppeared;
- if (value_ < kJustCreated)
- return static_cast<PaintInvalidationReason>(value_);
- return PaintInvalidationReason::kNone;
- }
-
- bool IsJustCreated() const { return value_ == kJustCreated; }
- void ClearIsJustCreated() {
- value_ = static_cast<ValueType>(PaintInvalidationReason::kFull);
- }
-
- private:
- typedef uint32_t ValueType;
- explicit CacheGenerationOrInvalidationReason(ValueType value)
- : value_(value) {}
-
- static const ValueType kJustCreated =
- static_cast<ValueType>(PaintInvalidationReason::kMax) + 1;
- static const ValueType kFirstValidGeneration =
- static_cast<ValueType>(PaintInvalidationReason::kMax) + 2;
- static ValueType next_generation_;
- ValueType value_;
- };
-
- bool DisplayItemsAreCached(CacheGenerationOrInvalidationReason other) const {
- return cache_generation_or_invalidation_reason_.Matches(other);
- }
- void SetDisplayItemsCached(
- CacheGenerationOrInvalidationReason cache_generation) const {
- cache_generation_or_invalidation_reason_ = cache_generation;
+ void Validate() const {
+ paint_invalidation_reason_ = PaintInvalidationReason::kNone;
}
- mutable CacheGenerationOrInvalidationReason
- cache_generation_or_invalidation_reason_;
+#if DCHECK_IS_ON()
+ void OnCreate();
+ void OnDestroy();
+#endif
+
+ mutable PaintInvalidationReason paint_invalidation_reason_;
DISALLOW_COPY_AND_ASSIGN(DisplayItemClient);
};
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.cc
index c072a60cf6b..6bd2940d364 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.cc
@@ -55,7 +55,7 @@ void DisplayItemList::AppendSubsequenceAsJSON(size_t begin_index,
item.PropertiesAsJSON(*json);
}
-#ifndef NDEBUG
+#if DCHECK_IS_ON()
if ((flags & kShowPaintRecords) && item.IsDrawing()) {
const auto& drawing_item = static_cast<const DrawingDisplayItem&>(item);
if (const auto* record = drawing_item.GetPaintRecord().get())
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.h b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.h
index 4b60c7c9dc8..5a6df085081 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_list.h
@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/platform/graphics/contiguous_container.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.h"
+#include "third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h"
#include "third_party/blink/renderer/platform/wtf/alignment.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
@@ -18,12 +18,11 @@ struct PaintChunk;
// kDisplayItemAlignment must be a multiple of alignof(derived display item) for
// each derived display item; the ideal value is the least common multiple.
-// Currently the limiting factor is TransformationMatrix (in
-// BeginTransform3DDisplayItem), which requests 16-byte alignment.
+// The validity of kDisplayItemAlignment and kMaximumDisplayItemSize are checked
+// in PaintController::CreateAndAppend().
static const size_t kDisplayItemAlignment =
- WTF_ALIGN_OF(BeginTransform3DDisplayItem);
-static const size_t kMaximumDisplayItemSize =
- sizeof(BeginTransform3DDisplayItem);
+ WTF_ALIGN_OF(ForeignLayerDisplayItem);
+static const size_t kMaximumDisplayItemSize = sizeof(ForeignLayerDisplayItem);
// A container for a list of display items.
class PLATFORM_EXPORT DisplayItemList
@@ -57,19 +56,6 @@ class PLATFORM_EXPORT DisplayItemList
return result;
}
- // This is used by PaintUnderInvalidationChecking in SPv1 to restore a
- // paired-begin display item that was moved to the new display item list then
- // was removed because the pair is a no-op. This ensures that we won't compare
- // the next new display item against the tombstone display item.
- void RestoreTombstone(size_t index, DisplayItem& item) {
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
- DCHECK((*this)[index].IsTombstone());
- SECURITY_CHECK((*this)[index].DerivedSize() == item.DerivedSize());
- memcpy(static_cast<void*>(&(*this)[index]), static_cast<void*>(&item),
- item.DerivedSize());
- new (&item) DisplayItem;
- }
-
// Useful for iterating with a range-based for loop.
template <typename Iterator>
class Range {
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.cc
new file mode 100644
index 00000000000..58061814186
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.cc
@@ -0,0 +1,255 @@
+// 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/platform/graphics/paint/display_item_raster_invalidator.h"
+
+#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
+
+namespace blink {
+
+void DisplayItemRasterInvalidator::Generate() {
+ struct OldAndNewDisplayItems {
+ const FloatRect* old_visual_rect = nullptr;
+ const FloatRect* new_visual_rect = nullptr;
+ PaintInvalidationReason reason = PaintInvalidationReason::kNone;
+ };
+ // If there are multiple display items changed for a client, the map will
+ // store only one (pair) of them because we only need the visual rect and the
+ // the multiple items have the same visual rect.
+ HashMap<const DisplayItemClient*, OldAndNewDisplayItems>
+ clients_to_invalidate;
+
+ Vector<bool> old_display_items_matched;
+ old_display_items_matched.resize(old_chunk_.size());
+ size_t next_old_item_to_match = old_chunk_.begin_index;
+ size_t max_cached_old_index = next_old_item_to_match;
+
+ for (const auto& new_item :
+ new_paint_artifact_.GetDisplayItemList().ItemsInPaintChunk(new_chunk_)) {
+ size_t matched_old_index =
+ MatchNewDisplayItemInOldChunk(new_item, next_old_item_to_match);
+ if (matched_old_index == kNotFound) {
+ if (new_item.DrawsContent()) {
+ // Will invalidate for the new display item which doesn't match any old
+ // display item.
+ auto& value = clients_to_invalidate
+ .insert(&new_item.Client(), OldAndNewDisplayItems())
+ .stored_value->value;
+ if (!value.new_visual_rect) {
+ value.new_visual_rect = &new_item.VisualRect();
+ value.reason = new_item.Client().IsCacheable()
+ ? PaintInvalidationReason::kAppeared
+ : PaintInvalidationReason::kUncacheable;
+ }
+ }
+ continue;
+ }
+
+ auto reason = new_item.Client().GetPaintInvalidationReason();
+ if (!IsFullPaintInvalidationReason(reason) &&
+ matched_old_index < max_cached_old_index) {
+ // |new_item| has been moved above other cached items.
+ reason = PaintInvalidationReason::kReordered;
+ }
+
+ const auto& old_item =
+ old_paint_artifact_.GetDisplayItemList()[matched_old_index];
+ if (reason != PaintInvalidationReason::kNone &&
+ (old_item.DrawsContent() || new_item.DrawsContent())) {
+ // The display item reordered, skipped cache or changed. Will invalidate
+ // for both the old and new display items.
+ auto& value = clients_to_invalidate
+ .insert(&new_item.Client(), OldAndNewDisplayItems())
+ .stored_value->value;
+ if (old_item.IsTombstone() || old_item.DrawsContent())
+ value.old_visual_rect = &old_item.VisualRect();
+ if (new_item.DrawsContent())
+ value.new_visual_rect = &new_item.VisualRect();
+ value.reason = reason;
+ }
+
+ size_t offset = matched_old_index - old_chunk_.begin_index;
+ DCHECK(!old_display_items_matched[offset]);
+ old_display_items_matched[offset] = true;
+
+ // |old_item.IsTombstone()| is true means that |new_item| was copied from
+ // cached |old_item|.
+ if (old_item.IsTombstone())
+ max_cached_old_index = std::max(max_cached_old_index, matched_old_index);
+ }
+
+ // Invalidate remaining unmatched (disappeared or uncacheable) old items.
+ for (size_t i = old_chunk_.begin_index; i < old_chunk_.end_index; ++i) {
+ if (old_display_items_matched[i - old_chunk_.begin_index])
+ continue;
+
+ const auto& old_item = old_paint_artifact_.GetDisplayItemList()[i];
+ if (old_item.DrawsContent() || old_item.IsTombstone()) {
+ clients_to_invalidate.insert(&old_item.Client(), OldAndNewDisplayItems())
+ .stored_value->value.old_visual_rect = &old_item.VisualRect();
+ }
+ }
+
+ for (const auto& item : clients_to_invalidate) {
+ GenerateRasterInvalidation(*item.key, item.value.old_visual_rect,
+ item.value.new_visual_rect, item.value.reason);
+ }
+}
+
+size_t DisplayItemRasterInvalidator::MatchNewDisplayItemInOldChunk(
+ const DisplayItem& new_item,
+ size_t& next_old_item_to_match) {
+ if (!new_item.IsCacheable())
+ return kNotFound;
+ for (; next_old_item_to_match < old_chunk_.end_index;
+ next_old_item_to_match++) {
+ const auto& old_item =
+ old_paint_artifact_.GetDisplayItemList()[next_old_item_to_match];
+ if (!old_item.IsCacheable())
+ continue;
+ if (old_item.GetId() == new_item.GetId())
+ return next_old_item_to_match++;
+ // Add the skipped old item into index.
+ old_display_items_index_.insert(&old_item.Client(), Vector<size_t>())
+ .stored_value->value.push_back(next_old_item_to_match);
+ }
+
+ // Didn't find matching old item in sequential matching. Look up the index.
+ auto it = old_display_items_index_.find(&new_item.Client());
+ if (it == old_display_items_index_.end())
+ return kNotFound;
+ for (size_t i : it->value) {
+ const auto& old_item = old_paint_artifact_.GetDisplayItemList()[i];
+ if (old_item.GetId() == new_item.GetId())
+ return i;
+ }
+ return kNotFound;
+}
+
+void DisplayItemRasterInvalidator::AddRasterInvalidation(
+ const DisplayItemClient& client,
+ const FloatRect& rect,
+ PaintInvalidationReason reason,
+ RasterInvalidator::ClientIsOldOrNew old_or_new) {
+ IntRect r = invalidator_.ClipByLayerBounds(mapper_.MapVisualRect(rect));
+ if (r.IsEmpty())
+ return;
+
+ invalidator_.AddRasterInvalidation(r, client, reason, old_or_new);
+}
+
+void DisplayItemRasterInvalidator::GenerateRasterInvalidation(
+ const DisplayItemClient& client,
+ const FloatRect* old_visual_rect,
+ const FloatRect* new_visual_rect,
+ PaintInvalidationReason reason) {
+ if (!new_visual_rect || new_visual_rect->IsEmpty()) {
+ if (old_visual_rect && !old_visual_rect->IsEmpty()) {
+ AddRasterInvalidation(client, *old_visual_rect,
+ PaintInvalidationReason::kDisappeared,
+ kClientIsOld);
+ }
+ return;
+ }
+
+ if (!old_visual_rect || old_visual_rect->IsEmpty()) {
+ AddRasterInvalidation(client, *new_visual_rect,
+ PaintInvalidationReason::kAppeared, kClientIsNew);
+ return;
+ }
+
+ if (client.IsJustCreated()) {
+ // The old client has been deleted and the new client happens to be at the
+ // same address. They have no relationship.
+ AddRasterInvalidation(client, *old_visual_rect,
+ PaintInvalidationReason::kDisappeared, kClientIsOld);
+ AddRasterInvalidation(client, *new_visual_rect,
+ PaintInvalidationReason::kAppeared, kClientIsNew);
+ return;
+ }
+
+ if (IsFullPaintInvalidationReason(reason)) {
+ GenerateFullRasterInvalidation(client, *old_visual_rect, *new_visual_rect,
+ reason);
+ return;
+ }
+
+ GenerateIncrementalRasterInvalidation(client, *old_visual_rect,
+ *new_visual_rect);
+
+ LayoutRect partial_rect = client.PartialInvalidationVisualRect();
+ if (!partial_rect.IsEmpty()) {
+ AddRasterInvalidation(client, FloatRect(partial_rect), reason,
+ kClientIsNew);
+ }
+}
+
+static FloatRect ComputeRightDelta(const FloatPoint& location,
+ const FloatSize& old_size,
+ const FloatSize& new_size) {
+ float delta = new_size.Width() - old_size.Width();
+ if (delta > 0) {
+ return FloatRect(location.X() + old_size.Width(), location.Y(), delta,
+ new_size.Height());
+ }
+ if (delta < 0) {
+ return FloatRect(location.X() + new_size.Width(), location.Y(), -delta,
+ old_size.Height());
+ }
+ return FloatRect();
+}
+
+static FloatRect ComputeBottomDelta(const FloatPoint& location,
+ const FloatSize& old_size,
+ const FloatSize& new_size) {
+ float delta = new_size.Height() - old_size.Height();
+ if (delta > 0) {
+ return FloatRect(location.X(), location.Y() + old_size.Height(),
+ new_size.Width(), delta);
+ }
+ if (delta < 0) {
+ return FloatRect(location.X(), location.Y() + new_size.Height(),
+ old_size.Width(), -delta);
+ }
+ return FloatRect();
+}
+
+void DisplayItemRasterInvalidator::GenerateIncrementalRasterInvalidation(
+ const DisplayItemClient& client,
+ const FloatRect& old_visual_rect,
+ const FloatRect& new_visual_rect) {
+ DCHECK(old_visual_rect.Location() == new_visual_rect.Location());
+
+ FloatRect right_delta =
+ ComputeRightDelta(new_visual_rect.Location(), old_visual_rect.Size(),
+ new_visual_rect.Size());
+ if (!right_delta.IsEmpty()) {
+ AddRasterInvalidation(client, right_delta,
+ PaintInvalidationReason::kIncremental, kClientIsNew);
+ }
+
+ FloatRect bottom_delta =
+ ComputeBottomDelta(new_visual_rect.Location(), old_visual_rect.Size(),
+ new_visual_rect.Size());
+ if (!bottom_delta.IsEmpty()) {
+ AddRasterInvalidation(client, bottom_delta,
+ PaintInvalidationReason::kIncremental, kClientIsNew);
+ }
+}
+
+void DisplayItemRasterInvalidator::GenerateFullRasterInvalidation(
+ const DisplayItemClient& client,
+ const FloatRect& old_visual_rect,
+ const FloatRect& new_visual_rect,
+ PaintInvalidationReason reason) {
+ if (!new_visual_rect.Contains(old_visual_rect)) {
+ AddRasterInvalidation(client, old_visual_rect, reason, kClientIsNew);
+ if (old_visual_rect.Contains(new_visual_rect))
+ return;
+ }
+
+ AddRasterInvalidation(client, new_visual_rect, reason, kClientIsNew);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.h b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.h
new file mode 100644
index 00000000000..310efb3bd21
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.h
@@ -0,0 +1,70 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_DISPLAY_ITEM_RASTER_INVALIDATOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_DISPLAY_ITEM_RASTER_INVALIDATOR_H_
+
+#include "third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h"
+
+namespace blink {
+
+// Generates raster invalidation for changed display items in a chunk.
+class DisplayItemRasterInvalidator {
+ public:
+ DisplayItemRasterInvalidator(RasterInvalidator& invalidator,
+ const PaintArtifact& old_paint_artifact,
+ const PaintArtifact& new_paint_artifact,
+ const PaintChunk& old_chunk,
+ const PaintChunk& new_chunk,
+ const ChunkToLayerMapper& mapper)
+ : invalidator_(invalidator),
+ old_paint_artifact_(old_paint_artifact),
+ new_paint_artifact_(new_paint_artifact),
+ old_chunk_(old_chunk),
+ new_chunk_(new_chunk),
+ mapper_(mapper) {
+ DCHECK(old_chunk_.Matches(new_chunk_));
+ }
+
+ void Generate();
+
+ private:
+ static const auto kClientIsOld = RasterInvalidator::kClientIsOld;
+ static const auto kClientIsNew = RasterInvalidator::kClientIsNew;
+
+ ALWAYS_INLINE void AddRasterInvalidation(const DisplayItemClient&,
+ const FloatRect&,
+ PaintInvalidationReason,
+ RasterInvalidator::ClientIsOldOrNew);
+ ALWAYS_INLINE size_t
+ MatchNewDisplayItemInOldChunk(const DisplayItem& new_item,
+ size_t& next_old_item_to_match);
+ ALWAYS_INLINE void GenerateRasterInvalidation(
+ const DisplayItemClient&,
+ const FloatRect* old_visual_rect,
+ const FloatRect* new_visual_rect,
+ PaintInvalidationReason);
+ ALWAYS_INLINE void GenerateIncrementalRasterInvalidation(
+ const DisplayItemClient&,
+ const FloatRect& old_visual_rect,
+ const FloatRect& new_visual_rect);
+ ALWAYS_INLINE void GenerateFullRasterInvalidation(
+ const DisplayItemClient&,
+ const FloatRect& old_visual_rect,
+ const FloatRect& new_visual_rect,
+ PaintInvalidationReason reason);
+
+ RasterInvalidator& invalidator_;
+ const PaintArtifact& old_paint_artifact_;
+ const PaintArtifact& new_paint_artifact_;
+ const PaintChunk& old_chunk_;
+ const PaintChunk& new_chunk_;
+ const ChunkToLayerMapper& mapper_;
+ // Maps clients to indices of display items in old_chunk_.
+ HashMap<const DisplayItemClient*, Vector<size_t>> old_display_items_index_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_DISPLAY_ITEM_PAINT_RASTER_INVALIDATOR_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc
new file mode 100644
index 00000000000..97ffe553cd1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc
@@ -0,0 +1,639 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.h"
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h"
+#include "third_party/blink/renderer/platform/testing/paint_property_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/test_paint_artifact.h"
+
+namespace blink {
+
+using ::testing::UnorderedElementsAre;
+
+class DisplayItemRasterInvalidatorTest : public PaintControllerTestBase {
+ protected:
+ DisplayItemRasterInvalidatorTest() : invalidator_([](const IntRect&) {}) {}
+
+ Vector<RasterInvalidationInfo> GenerateRasterInvalidations() {
+ GetPaintController().CommitNewDisplayItems();
+ invalidator_.Generate(
+ GetPaintController().GetPaintArtifactShared(),
+ // The layer rect is big enough not to clip display item raster
+ // invalidation rects.
+ IntRect(0, 0, 20000, 20000), PropertyTreeState::Root());
+ GetPaintController().FinishCycle();
+
+ if (invalidator_.GetTracking())
+ return invalidator_.GetTracking()->Invalidations();
+ return Vector<RasterInvalidationInfo>();
+ }
+
+ // In this file, DisplayItemRasterInvalidator is tested through
+ // RasterInvalidator.
+ RasterInvalidator invalidator_;
+};
+
+TEST_F(DisplayItemRasterInvalidatorTest, RemoveItemInMiddle) {
+ FakeDisplayItemClient first("first", LayoutRect(100, 100, 300, 300));
+ FakeDisplayItemClient second("second", LayoutRect(100, 100, 200, 200));
+ GraphicsContext context(GetPaintController());
+
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 300, 300));
+ DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 200, 200));
+ DrawRect(context, first, kForegroundType, FloatRect(100, 100, 300, 300));
+ GenerateRasterInvalidations();
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 300, 300));
+ DrawRect(context, first, kForegroundType, FloatRect(100, 100, 300, 300));
+
+ EXPECT_THAT(GenerateRasterInvalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ &second, "second", IntRect(100, 100, 200, 200),
+ PaintInvalidationReason::kDisappeared}));
+ invalidator_.SetTracksRasterInvalidations(false);
+}
+
+TEST_F(DisplayItemRasterInvalidatorTest, SwapOrder) {
+ FakeDisplayItemClient first("first", LayoutRect(100, 100, 100, 100));
+ FakeDisplayItemClient second("second", LayoutRect(100, 100, 50, 200));
+ FakeDisplayItemClient unaffected("unaffected", LayoutRect(300, 300, 10, 10));
+ GraphicsContext context(GetPaintController());
+
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, first, kForegroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 50, 200));
+ DrawRect(context, second, kForegroundType, FloatRect(100, 100, 50, 200));
+ DrawRect(context, unaffected, kBackgroundType, FloatRect(300, 300, 10, 10));
+ DrawRect(context, unaffected, kForegroundType, FloatRect(300, 300, 10, 10));
+ GenerateRasterInvalidations();
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ InitRootChunk();
+ DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 50, 200));
+ DrawRect(context, second, kForegroundType, FloatRect(100, 100, 50, 200));
+ DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, first, kForegroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, unaffected, kBackgroundType, FloatRect(300, 300, 10, 10));
+ DrawRect(context, unaffected, kForegroundType, FloatRect(300, 300, 10, 10));
+
+ EXPECT_THAT(GenerateRasterInvalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ &first, "first", IntRect(100, 100, 100, 100),
+ PaintInvalidationReason::kReordered}));
+ invalidator_.SetTracksRasterInvalidations(false);
+}
+
+TEST_F(DisplayItemRasterInvalidatorTest, SwapOrderAndInvalidateFirst) {
+ FakeDisplayItemClient first("first", LayoutRect(100, 100, 100, 100));
+ FakeDisplayItemClient second("second", LayoutRect(100, 100, 50, 200));
+ FakeDisplayItemClient unaffected("unaffected", LayoutRect(300, 300, 10, 10));
+ GraphicsContext context(GetPaintController());
+
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 50, 200));
+ DrawRect(context, unaffected, kBackgroundType, FloatRect(300, 300, 10, 10));
+ GenerateRasterInvalidations();
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ InitRootChunk();
+ first.Invalidate(PaintInvalidationReason::kOutline);
+ DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 50, 200));
+ DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, unaffected, kBackgroundType, FloatRect(300, 300, 10, 10));
+
+ EXPECT_THAT(GenerateRasterInvalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ &first, "first", IntRect(100, 100, 100, 100),
+ PaintInvalidationReason::kOutline}));
+ invalidator_.SetTracksRasterInvalidations(false);
+}
+
+TEST_F(DisplayItemRasterInvalidatorTest, SwapOrderAndInvalidateSecond) {
+ FakeDisplayItemClient first("first", LayoutRect(100, 100, 100, 100));
+ FakeDisplayItemClient second("second", LayoutRect(100, 100, 50, 200));
+ FakeDisplayItemClient unaffected("unaffected", LayoutRect(300, 300, 10, 10));
+ GraphicsContext context(GetPaintController());
+
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 50, 200));
+ DrawRect(context, unaffected, kBackgroundType, FloatRect(300, 300, 10, 10));
+ GenerateRasterInvalidations();
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ InitRootChunk();
+ second.Invalidate(PaintInvalidationReason::kOutline);
+ DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 50, 200));
+ DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, unaffected, kBackgroundType, FloatRect(300, 300, 10, 10));
+
+ EXPECT_THAT(GenerateRasterInvalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ &second, "second", IntRect(100, 100, 50, 200),
+ PaintInvalidationReason::kOutline}));
+ invalidator_.SetTracksRasterInvalidations(false);
+}
+
+TEST_F(DisplayItemRasterInvalidatorTest, SwapOrderWithIncrementalInvalidation) {
+ FakeDisplayItemClient first("first", LayoutRect(100, 100, 100, 100));
+ FakeDisplayItemClient second("second", LayoutRect(100, 100, 50, 200));
+ FakeDisplayItemClient unaffected("unaffected", LayoutRect(300, 300, 10, 10));
+ GraphicsContext context(GetPaintController());
+
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 50, 200));
+ DrawRect(context, unaffected, kBackgroundType, FloatRect(300, 300, 10, 10));
+ GenerateRasterInvalidations();
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ InitRootChunk();
+ first.SetVisualRect(LayoutRect(100, 100, 200, 100));
+ first.Invalidate(PaintInvalidationReason::kIncremental);
+ DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 50, 200));
+ DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, unaffected, kBackgroundType, FloatRect(300, 300, 10, 10));
+
+ // Incremental invalidation is not applicable when the item is reordered.
+ EXPECT_THAT(GenerateRasterInvalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ &first, "first", IntRect(100, 100, 200, 100),
+ PaintInvalidationReason::kReordered}));
+ invalidator_.SetTracksRasterInvalidations(false);
+}
+
+TEST_F(DisplayItemRasterInvalidatorTest, NewItemInMiddle) {
+ FakeDisplayItemClient first("first", LayoutRect(100, 100, 100, 100));
+ FakeDisplayItemClient second("second", LayoutRect(100, 100, 50, 200));
+ FakeDisplayItemClient third("third", LayoutRect(125, 100, 200, 50));
+ GraphicsContext context(GetPaintController());
+
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 50, 200));
+ GenerateRasterInvalidations();
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, third, kBackgroundType, FloatRect(125, 100, 200, 50));
+ DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 50, 200));
+
+ EXPECT_THAT(GenerateRasterInvalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ &third, "third", IntRect(125, 100, 200, 50),
+ PaintInvalidationReason::kAppeared}));
+ invalidator_.SetTracksRasterInvalidations(false);
+}
+
+TEST_F(DisplayItemRasterInvalidatorTest, Incremental) {
+ LayoutRect initial_rect(100, 100, 100, 100);
+ std::unique_ptr<FakeDisplayItemClient> clients[6];
+ for (size_t i = 0; i < base::size(clients); i++) {
+ clients[i] = std::make_unique<FakeDisplayItemClient>(
+ String::Format("%zu", i), initial_rect);
+ }
+ GraphicsContext context(GetPaintController());
+
+ InitRootChunk();
+
+ for (auto& client : clients)
+ DrawRect(context, *client, kBackgroundType, FloatRect(initial_rect));
+ GenerateRasterInvalidations();
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ InitRootChunk();
+ clients[0]->SetVisualRect(LayoutRect(100, 100, 150, 100));
+ clients[1]->SetVisualRect(LayoutRect(100, 100, 100, 150));
+ clients[2]->SetVisualRect(LayoutRect(100, 100, 150, 80));
+ clients[3]->SetVisualRect(LayoutRect(100, 100, 80, 150));
+ clients[4]->SetVisualRect(LayoutRect(100, 100, 150, 150));
+ clients[5]->SetVisualRect(LayoutRect(100, 100, 80, 80));
+ for (auto& client : clients) {
+ client->Invalidate(PaintInvalidationReason::kIncremental);
+ DrawRect(context, *client, kBackgroundType,
+ FloatRect(client->VisualRect()));
+ }
+
+ EXPECT_THAT(GenerateRasterInvalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{clients[0].get(), "0",
+ IntRect(200, 100, 50, 100),
+ PaintInvalidationReason::kIncremental},
+ RasterInvalidationInfo{clients[1].get(), "1",
+ IntRect(100, 200, 100, 50),
+ PaintInvalidationReason::kIncremental},
+ RasterInvalidationInfo{clients[2].get(), "2",
+ IntRect(200, 100, 50, 80),
+ PaintInvalidationReason::kIncremental},
+ RasterInvalidationInfo{clients[2].get(), "2",
+ IntRect(100, 180, 100, 20),
+ PaintInvalidationReason::kIncremental},
+ RasterInvalidationInfo{clients[3].get(), "3",
+ IntRect(180, 100, 20, 100),
+ PaintInvalidationReason::kIncremental},
+ RasterInvalidationInfo{clients[3].get(), "3",
+ IntRect(100, 200, 80, 50),
+ PaintInvalidationReason::kIncremental},
+ RasterInvalidationInfo{clients[4].get(), "4",
+ IntRect(200, 100, 50, 150),
+ PaintInvalidationReason::kIncremental},
+ RasterInvalidationInfo{clients[4].get(), "4",
+ IntRect(100, 200, 150, 50),
+ PaintInvalidationReason::kIncremental},
+ RasterInvalidationInfo{clients[5].get(), "5",
+ IntRect(180, 100, 20, 100),
+ PaintInvalidationReason::kIncremental},
+ RasterInvalidationInfo{
+ clients[5].get(), "5", IntRect(100, 180, 100, 20),
+ PaintInvalidationReason::kIncremental}));
+ invalidator_.SetTracksRasterInvalidations(false);
+}
+
+TEST_F(DisplayItemRasterInvalidatorTest, AddRemoveFirstAndInvalidateSecond) {
+ FakeDisplayItemClient chunk("chunk");
+ FakeDisplayItemClient first("first", LayoutRect(100, 100, 150, 150));
+ FakeDisplayItemClient second("second", LayoutRect(200, 200, 50, 50));
+ GraphicsContext context(GetPaintController());
+
+ InitRootChunk();
+ DrawRect(context, second, kBackgroundType, FloatRect(200, 200, 50, 50));
+ DrawRect(context, second, kForegroundType, FloatRect(200, 200, 50, 50));
+ GenerateRasterInvalidations();
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ InitRootChunk();
+ first.Invalidate();
+ second.Invalidate();
+ second.SetVisualRect(LayoutRect(150, 250, 100, 100));
+ DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 150, 150));
+ DrawRect(context, first, kForegroundType, FloatRect(100, 100, 150, 150));
+ DrawRect(context, second, kBackgroundType, FloatRect(150, 250, 100, 100));
+ DrawRect(context, second, kForegroundType, FloatRect(150, 250, 100, 100));
+ EXPECT_EQ(0, NumCachedNewItems());
+
+ EXPECT_THAT(
+ GenerateRasterInvalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{&first, "first", IntRect(100, 100, 150, 150),
+ PaintInvalidationReason::kAppeared},
+ RasterInvalidationInfo{&second, "second", IntRect(200, 200, 50, 50),
+ PaintInvalidationReason::kFull},
+ RasterInvalidationInfo{&second, "second", IntRect(150, 250, 100, 100),
+ PaintInvalidationReason::kFull}));
+ invalidator_.SetTracksRasterInvalidations(false);
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ InitRootChunk();
+ DrawRect(context, second, kBackgroundType, FloatRect(150, 250, 100, 100));
+ DrawRect(context, second, kForegroundType, FloatRect(150, 250, 100, 100));
+
+ EXPECT_THAT(GenerateRasterInvalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ &first, "first", IntRect(100, 100, 150, 150),
+ PaintInvalidationReason::kDisappeared}));
+ invalidator_.SetTracksRasterInvalidations(false);
+}
+
+TEST_F(DisplayItemRasterInvalidatorTest, InvalidateFirstAndAddRemoveSecond) {
+ FakeDisplayItemClient first("first", LayoutRect(100, 100, 150, 150));
+ FakeDisplayItemClient second("second", LayoutRect(200, 200, 50, 50));
+ GraphicsContext context(GetPaintController());
+
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 150, 150));
+ DrawRect(context, first, kForegroundType, FloatRect(100, 100, 150, 150));
+ GenerateRasterInvalidations();
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ InitRootChunk();
+ first.Invalidate();
+ first.SetVisualRect(LayoutRect(150, 150, 100, 100));
+ second.Invalidate();
+ DrawRect(context, first, kBackgroundType, FloatRect(150, 150, 100, 100));
+ DrawRect(context, first, kForegroundType, FloatRect(150, 150, 100, 100));
+ DrawRect(context, second, kBackgroundType, FloatRect(200, 200, 50, 50));
+ DrawRect(context, second, kForegroundType, FloatRect(200, 200, 50, 50));
+
+ EXPECT_THAT(
+ GenerateRasterInvalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{&first, "first", IntRect(100, 100, 150, 150),
+ PaintInvalidationReason::kFull},
+ RasterInvalidationInfo{&second, "second", IntRect(200, 200, 50, 50),
+ PaintInvalidationReason::kAppeared}));
+ invalidator_.SetTracksRasterInvalidations(false);
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ InitRootChunk();
+ first.Invalidate();
+ first.SetVisualRect(LayoutRect(100, 100, 150, 150));
+ second.Invalidate();
+ DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 150, 150));
+ DrawRect(context, first, kForegroundType, FloatRect(100, 100, 150, 150));
+
+ EXPECT_THAT(
+ GenerateRasterInvalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{&first, "first", IntRect(100, 100, 150, 150),
+ PaintInvalidationReason::kFull},
+ RasterInvalidationInfo{&second, "second", IntRect(200, 200, 50, 50),
+ PaintInvalidationReason::kDisappeared}));
+ invalidator_.SetTracksRasterInvalidations(false);
+}
+
+TEST_F(DisplayItemRasterInvalidatorTest, SwapOrderWithChildren) {
+ FakeDisplayItemClient container1("container1",
+ LayoutRect(100, 100, 100, 100));
+ FakeDisplayItemClient content1("content1", LayoutRect(100, 100, 50, 200));
+ FakeDisplayItemClient container2("container2",
+ LayoutRect(100, 200, 100, 100));
+ FakeDisplayItemClient content2("content2", LayoutRect(100, 200, 50, 200));
+ GraphicsContext context(GetPaintController());
+
+ InitRootChunk();
+ DrawRect(context, container1, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, FloatRect(100, 100, 50, 200));
+ DrawRect(context, content1, kForegroundType, FloatRect(100, 100, 50, 200));
+ DrawRect(context, container1, kForegroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, container2, kBackgroundType, FloatRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType, FloatRect(100, 200, 50, 200));
+ DrawRect(context, content2, kForegroundType, FloatRect(100, 200, 50, 200));
+ DrawRect(context, container2, kForegroundType, FloatRect(100, 200, 100, 100));
+ GenerateRasterInvalidations();
+
+ // Simulate the situation when |container1| gets a z-index that is greater
+ // than that of |container2|.
+ invalidator_.SetTracksRasterInvalidations(true);
+ InitRootChunk();
+ DrawRect(context, container2, kBackgroundType, FloatRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType, FloatRect(100, 200, 50, 200));
+ DrawRect(context, content2, kForegroundType, FloatRect(100, 200, 50, 200));
+ DrawRect(context, container2, kForegroundType, FloatRect(100, 200, 100, 100));
+ DrawRect(context, container1, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, FloatRect(100, 100, 50, 200));
+ DrawRect(context, content1, kForegroundType, FloatRect(100, 100, 50, 200));
+ DrawRect(context, container1, kForegroundType, FloatRect(100, 100, 100, 100));
+
+ EXPECT_THAT(GenerateRasterInvalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{&container1, "container1",
+ IntRect(100, 100, 100, 100),
+ PaintInvalidationReason::kReordered},
+ RasterInvalidationInfo{&content1, "content1",
+ IntRect(100, 100, 50, 200),
+ PaintInvalidationReason::kReordered}));
+ invalidator_.SetTracksRasterInvalidations(false);
+}
+
+TEST_F(DisplayItemRasterInvalidatorTest, SwapOrderWithChildrenAndInvalidation) {
+ FakeDisplayItemClient container1("container1",
+ LayoutRect(100, 100, 100, 100));
+ FakeDisplayItemClient content1("content1", LayoutRect(100, 100, 50, 200));
+ FakeDisplayItemClient container2("container2",
+ LayoutRect(100, 200, 100, 100));
+ FakeDisplayItemClient content2("content2", LayoutRect(100, 200, 50, 200));
+ GraphicsContext context(GetPaintController());
+
+ InitRootChunk();
+ DrawRect(context, container1, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, FloatRect(100, 100, 50, 200));
+ DrawRect(context, content1, kForegroundType, FloatRect(100, 100, 50, 200));
+ DrawRect(context, container1, kForegroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, container2, kBackgroundType, FloatRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType, FloatRect(100, 200, 50, 200));
+ DrawRect(context, content2, kForegroundType, FloatRect(100, 200, 50, 200));
+ DrawRect(context, container2, kForegroundType, FloatRect(100, 200, 100, 100));
+ GenerateRasterInvalidations();
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ InitRootChunk();
+ // Simulate the situation when |container1| gets a z-index that is greater
+ // than that of |container2|, and |container1| is invalidated.
+ container2.Invalidate();
+ DrawRect(context, container2, kBackgroundType, FloatRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType, FloatRect(100, 200, 50, 200));
+ DrawRect(context, content2, kForegroundType, FloatRect(100, 200, 50, 200));
+ DrawRect(context, container2, kForegroundType, FloatRect(100, 200, 100, 100));
+ DrawRect(context, container1, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, FloatRect(100, 100, 50, 200));
+ DrawRect(context, content1, kForegroundType, FloatRect(100, 100, 50, 200));
+ DrawRect(context, container1, kForegroundType, FloatRect(100, 100, 100, 100));
+
+ EXPECT_THAT(GenerateRasterInvalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{&container1, "container1",
+ IntRect(100, 100, 100, 100),
+ PaintInvalidationReason::kReordered},
+ RasterInvalidationInfo{&content1, "content1",
+ IntRect(100, 100, 50, 200),
+ PaintInvalidationReason::kReordered},
+ RasterInvalidationInfo{&container2, "container2",
+ IntRect(100, 200, 100, 100),
+ PaintInvalidationReason::kFull}));
+ invalidator_.SetTracksRasterInvalidations(false);
+}
+
+TEST_F(DisplayItemRasterInvalidatorTest, SwapOrderCrossingChunks) {
+ FakeDisplayItemClient container1("container1",
+ LayoutRect(100, 100, 100, 100));
+ FakeDisplayItemClient content1("content1", LayoutRect(100, 100, 50, 200));
+ FakeDisplayItemClient container2("container2",
+ LayoutRect(100, 200, 100, 100));
+ FakeDisplayItemClient content2("content2", LayoutRect(100, 200, 50, 200));
+ GraphicsContext context(GetPaintController());
+
+ auto container1_effect = CreateOpacityEffect(e0(), 0.5);
+ auto container1_properties = DefaultPaintChunkProperties();
+ container1_properties.SetEffect(container1_effect.get());
+
+ auto container2_effect = CreateOpacityEffect(e0(), 0.5);
+ auto container2_properties = DefaultPaintChunkProperties();
+ container2_properties.SetEffect(container2_effect.get());
+
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ PaintChunk::Id(container1, kBackgroundType), container1_properties);
+ DrawRect(context, container1, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, FloatRect(100, 100, 50, 200));
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ PaintChunk::Id(container2, kBackgroundType), container2_properties);
+ DrawRect(context, container2, kBackgroundType, FloatRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType, FloatRect(100, 200, 50, 200));
+ GenerateRasterInvalidations();
+
+ // Move content2 into container1, without invalidation.
+ invalidator_.SetTracksRasterInvalidations(true);
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ PaintChunk::Id(container1, kBackgroundType), container1_properties);
+ DrawRect(context, container1, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, FloatRect(100, 100, 50, 200));
+ DrawRect(context, content2, kBackgroundType, FloatRect(100, 200, 50, 200));
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ PaintChunk::Id(container2, kBackgroundType), container2_properties);
+ DrawRect(context, container2, kBackgroundType, FloatRect(100, 200, 100, 100));
+
+ EXPECT_THAT(GenerateRasterInvalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{&content2, "content2",
+ IntRect(100, 200, 50, 200),
+ PaintInvalidationReason::kDisappeared},
+ RasterInvalidationInfo{&content2, "content2",
+ IntRect(100, 200, 50, 200),
+ PaintInvalidationReason::kAppeared}));
+ invalidator_.SetTracksRasterInvalidations(false);
+}
+
+TEST_F(DisplayItemRasterInvalidatorTest, SkipCache) {
+ FakeDisplayItemClient multicol("multicol", LayoutRect(100, 100, 200, 200));
+ FakeDisplayItemClient content("content", LayoutRect(100, 100, 100, 100));
+ GraphicsContext context(GetPaintController());
+
+ InitRootChunk();
+ FloatRect rect1(100, 100, 50, 50);
+ FloatRect rect2(150, 100, 50, 50);
+ FloatRect rect3(200, 100, 50, 50);
+
+ DrawRect(context, multicol, kBackgroundType, FloatRect(100, 200, 100, 100));
+ GetPaintController().BeginSkippingCache();
+ DrawRect(context, content, kForegroundType, rect1);
+ DrawRect(context, content, kForegroundType, rect2);
+ GetPaintController().EndSkippingCache();
+ GenerateRasterInvalidations();
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ InitRootChunk();
+ // Draw again with nothing invalidated.
+ EXPECT_TRUE(ClientCacheIsValid(multicol));
+ DrawRect(context, multicol, kBackgroundType, FloatRect(100, 200, 100, 100));
+
+ GetPaintController().BeginSkippingCache();
+ DrawRect(context, content, kForegroundType, rect1);
+ DrawRect(context, content, kForegroundType, rect2);
+ GetPaintController().EndSkippingCache();
+
+ EXPECT_THAT(GenerateRasterInvalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ &content, "content", IntRect(100, 100, 100, 100),
+ PaintInvalidationReason::kUncacheable}));
+ invalidator_.SetTracksRasterInvalidations(false);
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ InitRootChunk();
+ // Now the multicol becomes 3 columns and repaints.
+ multicol.Invalidate();
+ DrawRect(context, multicol, kBackgroundType, FloatRect(100, 100, 100, 100));
+
+ GetPaintController().BeginSkippingCache();
+ DrawRect(context, content, kForegroundType, rect1);
+ DrawRect(context, content, kForegroundType, rect2);
+ DrawRect(context, content, kForegroundType, rect3);
+ GetPaintController().EndSkippingCache();
+
+ EXPECT_THAT(GenerateRasterInvalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{&multicol, "multicol",
+ IntRect(100, 100, 200, 200),
+ PaintInvalidationReason::kFull},
+ RasterInvalidationInfo{
+ &content, "content", IntRect(100, 100, 100, 100),
+ PaintInvalidationReason::kUncacheable}));
+ invalidator_.SetTracksRasterInvalidations(false);
+}
+
+TEST_F(DisplayItemRasterInvalidatorTest, PartialSkipCache) {
+ FakeDisplayItemClient content("content", LayoutRect(100, 100, 250, 250));
+ GraphicsContext context(GetPaintController());
+
+ FloatRect rect1(100, 100, 50, 50);
+ FloatRect rect2(150, 100, 50, 50);
+ FloatRect rect3(200, 100, 50, 50);
+
+ InitRootChunk();
+ DrawRect(context, content, kBackgroundType, rect1);
+ GetPaintController().BeginSkippingCache();
+ DrawRect(context, content, kForegroundType, rect2);
+ GetPaintController().EndSkippingCache();
+ DrawRect(context, content, kForegroundType, rect3);
+ GenerateRasterInvalidations();
+
+ invalidator_.SetTracksRasterInvalidations(true);
+ InitRootChunk();
+ // Draw again with nothing invalidated.
+ DrawRect(context, content, kBackgroundType, rect1);
+ GetPaintController().BeginSkippingCache();
+ DrawRect(context, content, kForegroundType, rect2);
+ GetPaintController().EndSkippingCache();
+ DrawRect(context, content, kForegroundType, rect3);
+
+ EXPECT_THAT(GenerateRasterInvalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ &content, "content", IntRect(100, 100, 250, 250),
+ PaintInvalidationReason::kUncacheable}));
+ invalidator_.SetTracksRasterInvalidations(false);
+}
+
+TEST_F(DisplayItemRasterInvalidatorTest, Partial) {
+ FakeDisplayItemClient client("client", LayoutRect(100, 100, 300, 300));
+ GraphicsContext context(GetPaintController());
+
+ InitRootChunk();
+ DrawRect(context, client, kBackgroundType, FloatRect(100, 100, 300, 300));
+ GenerateRasterInvalidations();
+
+ // Test partial rect invalidation without other invalidations.
+ invalidator_.SetTracksRasterInvalidations(true);
+ InitRootChunk();
+ client.SetPartialInvalidationVisualRect(LayoutRect(150, 160, 170, 180));
+ DrawRect(context, client, kBackgroundType, FloatRect(100, 100, 300, 300));
+
+ // Partial invalidation.
+ EXPECT_THAT(GenerateRasterInvalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ &client, "client", IntRect(150, 160, 170, 180),
+ PaintInvalidationReason::kRectangle}));
+ EXPECT_EQ(LayoutRect(), client.PartialInvalidationVisualRect());
+ invalidator_.SetTracksRasterInvalidations(false);
+
+ // Test partial rect invalidation with full invalidation.
+ invalidator_.SetTracksRasterInvalidations(true);
+ InitRootChunk();
+ client.SetPartialInvalidationVisualRect(LayoutRect(150, 160, 170, 180));
+ client.Invalidate();
+ DrawRect(context, client, kBackgroundType, FloatRect(100, 100, 300, 300));
+
+ // Partial invalidation is shadowed by full invalidation.
+ EXPECT_THAT(GenerateRasterInvalidations(),
+ UnorderedElementsAre(RasterInvalidationInfo{
+ &client, "client", IntRect(100, 100, 300, 300),
+ PaintInvalidationReason::kFull}));
+ EXPECT_EQ(LayoutRect(), client.PartialInvalidationVisualRect());
+ invalidator_.SetTracksRasterInvalidations(false);
+
+ // Test partial rect invalidation with incremental invalidation.
+ invalidator_.SetTracksRasterInvalidations(true);
+ InitRootChunk();
+ client.SetPartialInvalidationVisualRect(LayoutRect(150, 160, 170, 180));
+ client.SetVisualRect(LayoutRect(100, 100, 300, 400));
+ DrawRect(context, client, kBackgroundType, FloatRect(100, 100, 300, 400));
+
+ // Both partial invalidation and incremental invalidation.
+ EXPECT_THAT(
+ GenerateRasterInvalidations(),
+ UnorderedElementsAre(
+ RasterInvalidationInfo{&client, "client", IntRect(150, 160, 170, 180),
+ PaintInvalidationReason::kRectangle},
+ RasterInvalidationInfo{&client, "client", IntRect(100, 400, 300, 100),
+ PaintInvalidationReason::kIncremental}));
+ invalidator_.SetTracksRasterInvalidations(false);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc
index e26780fc64f..a9bf22f86f7 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item.cc
@@ -42,18 +42,6 @@ void DrawingDisplayItem::PropertiesAsJSON(JSONObject& json) const {
}
#endif
-static bool RecordsEqual(sk_sp<const PaintRecord> record1,
- sk_sp<const PaintRecord> record2,
- const FloatRect& bounds) {
- if (record1->size() != record2->size())
- return false;
-
- // TODO(enne): PaintRecord should have an operator==
- sk_sp<SkData> data1 = ToSkPicture(record1, bounds)->serialize();
- sk_sp<SkData> data2 = ToSkPicture(record2, bounds)->serialize();
- return data1->equals(data2.get());
-}
-
static SkBitmap RecordToBitmap(sk_sp<const PaintRecord> record,
const IntRect& bounds) {
SkBitmap bitmap;
@@ -107,7 +95,7 @@ bool DrawingDisplayItem::Equals(const DisplayItem& other) const {
if (bounds != other_bounds)
return false;
- if (RecordsEqual(record, other_record, FloatRect(bounds)))
+ if (*record == *other_record)
return true;
// Sometimes the client may produce different records for the same visual
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item_test.cc
index 319b420d613..36d2fab5b7c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_display_item_test.cc
@@ -7,6 +7,7 @@
#include "cc/paint/display_item_list.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_flags.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/testing/fake_display_item_client.h"
@@ -24,7 +25,7 @@ class DrawingDisplayItemTest : public testing::Test {
static sk_sp<PaintRecord> CreateRectRecord(const FloatRect& record_bounds) {
PaintRecorder recorder;
- PaintCanvas* canvas =
+ cc::PaintCanvas* canvas =
recorder.beginRecording(record_bounds.Width(), record_bounds.Height());
canvas->drawRect(record_bounds, PaintFlags());
return recorder.finishRecordingAsPicture();
@@ -35,7 +36,7 @@ static sk_sp<PaintRecord> CreateRectRecordWithTranslate(
float dx,
float dy) {
PaintRecorder recorder;
- PaintCanvas* canvas =
+ cc::PaintCanvas* canvas =
recorder.beginRecording(record_bounds.Width(), record_bounds.Height());
canvas->save();
canvas->translate(dx, dy);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.cc
index b42de3e1340..323eb4aef18 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.cc
@@ -41,10 +41,7 @@ DrawingRecorder::DrawingRecorder(GraphicsContext& context,
DCHECK(DisplayItem::IsDrawingType(display_item_type));
-#if DCHECK_IS_ON()
context.SetInDrawingRecorder(true);
-#endif
-
context.BeginRecording(FloatRect());
}
@@ -52,9 +49,9 @@ DrawingRecorder::~DrawingRecorder() {
if (context_.GetPaintController().DisplayItemConstructionIsDisabled())
return;
-#if DCHECK_IS_ON()
context_.SetInDrawingRecorder(false);
+#if DCHECK_IS_ON()
if (!g_list_modification_check_disabled) {
DCHECK(initial_display_item_list_size_ ==
context_.GetPaintController().NewDisplayItemList().size());
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h
index f4afbeff75d..129ddf24cc3 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h
@@ -8,13 +8,13 @@
#include "third_party/blink/renderer/platform/platform_export.h"
#include "base/auto_reset.h"
+#include "base/macros.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
namespace blink {
@@ -22,7 +22,6 @@ class GraphicsContext;
class PLATFORM_EXPORT DrawingRecorder final {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
- WTF_MAKE_NONCOPYABLE(DrawingRecorder);
public:
static bool UseCachedDrawingIfPossible(GraphicsContext& context,
@@ -69,18 +68,21 @@ class PLATFORM_EXPORT DrawingRecorder final {
// Ensures the list size does not change during the recorder's scope.
size_t initial_display_item_list_size_;
#endif
+
+ DISALLOW_COPY_AND_ASSIGN(DrawingRecorder);
};
#if DCHECK_IS_ON()
class DisableListModificationCheck {
STACK_ALLOCATED();
- WTF_MAKE_NONCOPYABLE(DisableListModificationCheck);
public:
DisableListModificationCheck();
private:
base::AutoReset<bool> disabler_;
+
+ DISALLOW_COPY_AND_ASSIGN(DisableListModificationCheck);
};
#endif // DCHECK_IS_ON()
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder_test.cc
index 4882dba1339..37f21620734 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/drawing_recorder_test.cc
@@ -22,7 +22,7 @@ TEST_F(DrawingRecorderTest, Nothing) {
GraphicsContext context(GetPaintController());
InitRootChunk();
DrawNothing(context, client, kForegroundType);
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 1,
TestDisplayItem(client, kForegroundType));
EXPECT_FALSE(static_cast<const DrawingDisplayItem&>(
@@ -35,7 +35,7 @@ TEST_F(DrawingRecorderTest, Rect) {
GraphicsContext context(GetPaintController());
InitRootChunk();
DrawRect(context, client, kForegroundType, kBounds);
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 1,
TestDisplayItem(client, kForegroundType));
}
@@ -46,7 +46,7 @@ TEST_F(DrawingRecorderTest, Cached) {
InitRootChunk();
DrawNothing(context, client, kBackgroundType);
DrawRect(context, client, kForegroundType, kBounds);
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
TestDisplayItem(client, kBackgroundType),
@@ -58,28 +58,12 @@ TEST_F(DrawingRecorderTest, Cached) {
EXPECT_EQ(2, NumCachedNewItems());
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
TestDisplayItem(client, kBackgroundType),
TestDisplayItem(client, kForegroundType));
}
-template <typename T>
-FloatRect DrawAndGetCullRect(PaintController& controller,
- const DisplayItemClient& client,
- const T& bounds) {
- {
- // Draw some things which will produce a non-null picture.
- GraphicsContext context(controller);
- DrawingRecorder recorder(context, client, kBackgroundType, bounds);
- context.DrawRect(EnclosedIntRect(FloatRect(bounds)));
- }
- controller.CommitNewDisplayItems();
- const auto& drawing = static_cast<const DrawingDisplayItem&>(
- controller.GetDisplayItemList()[0]);
- return FloatRect(drawing.VisualRect());
-}
-
} // namespace
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.cc
index 70852c21b84..29802333851 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.cc
@@ -4,14 +4,16 @@
#include "third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h"
+#include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h"
+
namespace blink {
-EffectPaintPropertyNode* EffectPaintPropertyNode::Root() {
+const EffectPaintPropertyNode& EffectPaintPropertyNode::Root() {
DEFINE_STATIC_REF(EffectPaintPropertyNode, root,
- (EffectPaintPropertyNode::Create(
- nullptr, State{TransformPaintPropertyNode::Root(),
- ClipPaintPropertyNode::Root()})));
- return root;
+ base::AdoptRef(new EffectPaintPropertyNode(
+ nullptr, State{&TransformPaintPropertyNode::Root(),
+ &ClipPaintPropertyNode::Root()})));
+ return *root;
}
FloatRect EffectPaintPropertyNode::MapRect(const FloatRect& input_rect) const {
@@ -22,10 +24,30 @@ FloatRect EffectPaintPropertyNode::MapRect(const FloatRect& input_rect) const {
return result;
}
+bool EffectPaintPropertyNode::Changed(
+ const PropertyTreeState& relative_to_state,
+ const TransformPaintPropertyNode* transform_not_to_check) const {
+ for (const auto* node = this; node && node != relative_to_state.Effect();
+ node = node->Parent()) {
+ if (node->NodeChanged())
+ return true;
+ if (node->HasFilterThatMovesPixels() &&
+ node->LocalTransformSpace() != transform_not_to_check &&
+ node->LocalTransformSpace()->Changed(*relative_to_state.Transform()))
+ return true;
+ // We don't check for change of OutputClip here to avoid N^3 complexity.
+ // The caller should check for clip change in other ways.
+ }
+
+ return false;
+}
+
std::unique_ptr<JSONObject> EffectPaintPropertyNode::ToJSON() const {
auto json = JSONObject::Create();
if (Parent())
json->SetString("parent", String::Format("%p", Parent()));
+ if (NodeChanged())
+ json->SetBoolean("changed", true);
json->SetString("localTransformSpace",
String::Format("%p", state_.local_transform_space.get()));
json->SetString("outputClip", String::Format("%p", state_.output_clip.get()));
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h b/chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h
index fea3860261a..54c773fa07e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/effect_paint_property_node.h
@@ -5,7 +5,6 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_EFFECT_PAINT_PROPERTY_NODE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_EFFECT_PAINT_PROPERTY_NODE_H_
-#include "cc/layers/layer.h"
#include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
#include "third_party/blink/renderer/platform/graphics/compositor_filter_operations.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
@@ -16,6 +15,8 @@
namespace blink {
+class PropertyTreeState;
+
// Effect nodes are abstraction of isolated groups, along with optional effects
// that can be applied to the composited output of the group.
//
@@ -63,18 +64,17 @@ class PLATFORM_EXPORT EffectPaintPropertyNode
};
// This node is really a sentinel, and does not represent a real effect.
- static EffectPaintPropertyNode* Root();
+ static const EffectPaintPropertyNode& Root();
static scoped_refptr<EffectPaintPropertyNode> Create(
- scoped_refptr<const EffectPaintPropertyNode> parent,
+ const EffectPaintPropertyNode& parent,
State&& state) {
return base::AdoptRef(
- new EffectPaintPropertyNode(std::move(parent), std::move(state)));
+ new EffectPaintPropertyNode(&parent, std::move(state)));
}
- bool Update(scoped_refptr<const EffectPaintPropertyNode> parent,
- State&& state) {
- bool parent_changed = SetParent(parent);
+ bool Update(const EffectPaintPropertyNode& parent, State&& state) {
+ bool parent_changed = SetParent(&parent);
if (state == state_)
return parent_changed;
@@ -83,6 +83,17 @@ class PLATFORM_EXPORT EffectPaintPropertyNode
return true;
}
+ // Checks if the accumulated effect from |this| to |relative_to_state
+ // .Effect()| has changed in the space of |relative_to_state.Transform()|.
+ // We check for changes of not only effect nodes, but also LocalTransformSpace
+ // relative to |relative_to_state.Transform()| of the effect nodes having
+ // filters that move pixels. Change of OutputClip is not checked and the
+ // caller should check in other ways. |transform_not_to_check| specifies the
+ // transform node that the caller has checked or will check its change in
+ // other ways and this function should treat it as unchanged.
+ bool Changed(const PropertyTreeState& relative_to_state,
+ const TransformPaintPropertyNode* transform_not_to_check) const;
+
const TransformPaintPropertyNode* LocalTransformSpace() const {
return state_.local_transform_space.get();
}
@@ -138,9 +149,8 @@ class PLATFORM_EXPORT EffectPaintPropertyNode
size_t TreeMemoryUsageInBytes() const;
private:
- EffectPaintPropertyNode(scoped_refptr<const EffectPaintPropertyNode> parent,
- State&& state)
- : PaintPropertyNode(std::move(parent)), state_(std::move(state)) {}
+ EffectPaintPropertyNode(const EffectPaintPropertyNode* parent, State&& state)
+ : PaintPropertyNode(parent), state_(std::move(state)) {}
State state_;
};
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/filter_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/filter_display_item.cc
deleted file mode 100644
index 88a5b4de076..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/filter_display_item.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/paint/filter_display_item.h"
-
-#include "cc/paint/display_item_list.h"
-#include "cc/paint/render_surface_filters.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "ui/gfx/geometry/point_f.h"
-#include "ui/gfx/geometry/rect_f.h"
-
-namespace blink {
-
-void BeginFilterDisplayItem::Replay(GraphicsContext& context) const {
- FloatRect image_filter_bounds(bounds_);
- image_filter_bounds.Move(-origin_.X(), -origin_.Y());
- context.Save();
- context.Translate(origin_.X(), origin_.Y());
- context.BeginLayer(1, SkBlendMode::kSrcOver, &image_filter_bounds,
- kColorFilterNone, image_filter_);
- context.Translate(-origin_.X(), -origin_.Y());
-}
-
-void BeginFilterDisplayItem::AppendToDisplayItemList(
- const FloatSize&,
- cc::DisplayItemList& list) const {
- list.StartPaint();
-
- // TODO(danakj): Skip the save+translate+restore if the origin is 0,0. This
- // should be easier to do when this code is part of the blink DisplayItem
- // which can keep related state.
- list.push<cc::SaveOp>();
- list.push<cc::TranslateOp>(origin_.X(), origin_.Y());
-
- cc::PaintFlags flags;
- flags.setImageFilter(cc::RenderSurfaceFilters::BuildImageFilter(
- compositor_filter_operations_.AsCcFilterOperations(),
- static_cast<gfx::SizeF>(bounds_.Size())));
-
- SkRect layer_bounds = bounds_;
- layer_bounds.offset(-origin_.X(), -origin_.Y());
- list.push<cc::SaveLayerOp>(&layer_bounds, &flags);
- list.push<cc::TranslateOp>(-origin_.X(), -origin_.Y());
-
- list.EndPaintOfPairedBegin(EnclosingIntRect(bounds_));
-}
-
-bool BeginFilterDisplayItem::DrawsContent() const {
- // Skia cannot currently tell us if a filter will draw content,
- // even when no input primitives are drawn.
- return true;
-}
-
-#if DCHECK_IS_ON()
-void BeginFilterDisplayItem::PropertiesAsJSON(JSONObject& json) const {
- DisplayItem::PropertiesAsJSON(json);
- json.SetString("filterBounds", bounds_.ToString());
-}
-#endif
-
-void EndFilterDisplayItem::Replay(GraphicsContext& context) const {
- context.EndLayer();
- context.Restore();
-}
-
-void EndFilterDisplayItem::AppendToDisplayItemList(
- const FloatSize&,
- cc::DisplayItemList& list) const {
- list.StartPaint();
- list.push<cc::RestoreOp>(); // For SaveLayerOp.
- list.push<cc::RestoreOp>(); // For SaveOp.
- list.EndPaintOfPairedEnd();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/filter_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/filter_display_item.h
deleted file mode 100644
index ce9bc179b4a..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/filter_display_item.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_FILTER_DISPLAY_ITEM_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_FILTER_DISPLAY_ITEM_H_
-
-#include <memory>
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/platform/geometry/float_rect.h"
-#include "third_party/blink/renderer/platform/graphics/compositor_filter_operations.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT BeginFilterDisplayItem final
- : public PairedBeginDisplayItem {
- public:
- BeginFilterDisplayItem(const DisplayItemClient& client,
- sk_sp<PaintFilter> image_filter,
- const FloatRect& bounds,
- const FloatPoint& origin,
- CompositorFilterOperations filter_operations)
- : PairedBeginDisplayItem(client, kBeginFilter, sizeof(*this)),
- image_filter_(std::move(image_filter)),
- compositor_filter_operations_(std::move(filter_operations)),
- bounds_(bounds),
- origin_(origin) {}
-
- void Replay(GraphicsContext&) const override;
- void AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList&) const override;
- bool DrawsContent() const override;
-
- private:
-#if DCHECK_IS_ON()
- void PropertiesAsJSON(JSONObject&) const override;
-#endif
- bool Equals(const DisplayItem& other) const final {
- if (!DisplayItem::Equals(other))
- return false;
- const auto& other_item = static_cast<const BeginFilterDisplayItem&>(other);
- // Ignores changes of reference filters because PaintFilter doesn't have
- // an equality operator.
- return bounds_ == other_item.bounds_ && origin_ == other_item.origin_ &&
- compositor_filter_operations_.EqualsIgnoringReferenceFilters(
- other_item.compositor_filter_operations_);
- }
-
- // FIXME: m_imageFilter should be replaced with m_webFilterOperations when
- // copying data to the compositor.
- sk_sp<PaintFilter> image_filter_;
- CompositorFilterOperations compositor_filter_operations_;
- const FloatRect bounds_;
- const FloatPoint origin_;
-};
-
-class PLATFORM_EXPORT EndFilterDisplayItem final : public PairedEndDisplayItem {
- public:
- EndFilterDisplayItem(const DisplayItemClient& client)
- : PairedEndDisplayItem(client, kEndFilter, sizeof(*this)) {}
-
- void Replay(GraphicsContext&) const override;
- void AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
- bool IsEndAndPairedWith(DisplayItem::Type other_type) const final {
- return other_type == kBeginFilter;
- }
-#endif
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_FILTER_DISPLAY_ITEM_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_display_item.cc
deleted file mode 100644
index 6b6843efaaf..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_display_item.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/paint/float_clip_display_item.h"
-
-#include "cc/paint/display_item_list.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/skia/include/core/SkScalar.h"
-#include "ui/gfx/geometry/rect_f.h"
-
-namespace blink {
-
-void FloatClipDisplayItem::Replay(GraphicsContext& context) const {
- context.Save();
- context.ClipRect(clip_rect_, kAntiAliased);
-}
-
-void FloatClipDisplayItem::AppendToDisplayItemList(
- const FloatSize&,
- cc::DisplayItemList& list) const {
- list.StartPaint();
- list.push<cc::SaveOp>();
- list.push<cc::ClipRectOp>(clip_rect_, SkClipOp::kIntersect,
- /*antialias=*/true);
- list.EndPaintOfPairedBegin();
-}
-
-void EndFloatClipDisplayItem::Replay(GraphicsContext& context) const {
- context.Restore();
-}
-
-void EndFloatClipDisplayItem::AppendToDisplayItemList(
- const FloatSize&,
- cc::DisplayItemList& list) const {
- list.StartPaint();
- list.push<cc::RestoreOp>();
- list.EndPaintOfPairedEnd();
-}
-
-#if DCHECK_IS_ON()
-void FloatClipDisplayItem::PropertiesAsJSON(JSONObject& json) const {
- DisplayItem::PropertiesAsJSON(json);
- json.SetString("floatClipRect", clip_rect_.ToString());
-}
-#endif
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_display_item.h
deleted file mode 100644
index 66f15e9edc3..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/float_clip_display_item.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_FLOAT_CLIP_DISPLAY_ITEM_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_FLOAT_CLIP_DISPLAY_ITEM_H_
-
-#include "third_party/blink/renderer/platform/geometry/float_rect.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT FloatClipDisplayItem final
- : public PairedBeginDisplayItem {
- public:
- FloatClipDisplayItem(const DisplayItemClient& client,
- Type type,
- const FloatRect& clip_rect)
- : PairedBeginDisplayItem(client, type, sizeof(*this)),
- clip_rect_(clip_rect) {
- DCHECK(IsFloatClipType(type));
- }
-
- void Replay(GraphicsContext&) const override;
- void AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
- void PropertiesAsJSON(JSONObject&) const override;
-#endif
- bool Equals(const DisplayItem& other) const final {
- return DisplayItem::Equals(other) &&
- clip_rect_ ==
- static_cast<const FloatClipDisplayItem&>(other).clip_rect_;
- }
-
- const FloatRect clip_rect_;
-};
-
-class PLATFORM_EXPORT EndFloatClipDisplayItem final
- : public PairedEndDisplayItem {
- public:
- EndFloatClipDisplayItem(const DisplayItemClient& client, Type type)
- : PairedEndDisplayItem(client, type, sizeof(*this)) {
- DCHECK(IsEndFloatClipType(type));
- }
-
- void Replay(GraphicsContext&) const override;
- void AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
- bool IsEndAndPairedWith(DisplayItem::Type other_type) const final {
- return DisplayItem::IsFloatClipType(other_type);
- }
-#endif
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_FLOAT_CLIP_DISPLAY_ITEM_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h
index b65bab8bd11..6d7e51e1d34 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h
@@ -5,14 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_FOREIGN_LAYER_DISPLAY_ITEM_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_FOREIGN_LAYER_DISPLAY_ITEM_H_
-#include "base/memory/ref_counted.h"
+#include "cc/layers/layer.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-namespace cc {
-class Layer;
-}
-
namespace blink {
class GraphicsContext;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc
index fba18feb109..ae00c4dc841 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper.cc
@@ -101,7 +101,7 @@ GeometryMapper::SourceToDestinationProjectionInternal(
// Case 3: Compute:
// flatten(destination_to_screen)^-1 * flatten(source_to_screen)
- const auto* root = TransformPaintPropertyNode::Root();
+ const auto* root = &TransformPaintPropertyNode::Root();
success = true;
if (source == root)
return destination_cache.projection_from_screen();
@@ -134,10 +134,11 @@ bool GeometryMapper::LocalToAncestorVisualRect(
OverlayScrollbarClipBehavior clip_behavior,
InclusiveIntersectOrNot inclusive_behavior) {
bool success = false;
- return LocalToAncestorVisualRectInternal(local_state, ancestor_state,
- mapping_rect, clip_behavior,
- inclusive_behavior, success);
+ bool result = LocalToAncestorVisualRectInternal(local_state, ancestor_state,
+ mapping_rect, clip_behavior,
+ inclusive_behavior, success);
DCHECK(success);
+ return result;
}
bool GeometryMapper::PointVisibleInAncestorSpace(
@@ -213,12 +214,12 @@ bool GeometryMapper::LocalToAncestorVisualRectInternal(
}
if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
- // On SPv1* we may fail when the paint invalidation container creates an
+ // On SPv1 we may fail when the paint invalidation container creates an
// overflow clip (in ancestor_state) which is not in localState of an
// out-of-flow positioned descendant. See crbug.com/513108 and layout test
// compositing/overflow/handle-non-ancestor-clip-parent.html (run with
// --enable-prefer-compositing-to-lcd-text) for details.
- // Ignore it for SPv1* for now.
+ // Ignore it for SPv1 for now.
success = true;
rect_to_map.ClearIsTight();
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc
index 58e7eac21bf..9eef0c8f4e0 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/geometry_mapper_test.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
-
+#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/geometry/geometry_test_helpers.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
@@ -157,8 +157,7 @@ TEST_P(GeometryMapperTest, Root) {
}
TEST_P(GeometryMapperTest, IdentityTransform) {
- auto transform = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix());
+ auto transform = CreateTransform(t0(), TransformationMatrix());
local_state.SetTransform(transform.get());
input_rect = FloatRect(0, 0, 100, 100);
@@ -169,8 +168,7 @@ TEST_P(GeometryMapperTest, IdentityTransform) {
TEST_P(GeometryMapperTest, TranslationTransform) {
expected_transform = TransformationMatrix().Translate(20, 10);
- auto transform =
- CreateTransform(TransformPaintPropertyNode::Root(), expected_transform);
+ auto transform = CreateTransform(t0(), expected_transform);
local_state.SetTransform(transform.get());
input_rect = FloatRect(0, 0, 100, 100);
@@ -179,15 +177,13 @@ TEST_P(GeometryMapperTest, TranslationTransform) {
CHECK_MAPPINGS();
FloatRect rect = expected_transformed_rect;
- GeometryMapper::SourceToDestinationRect(TransformPaintPropertyNode::Root(),
- local_state.Transform(), rect);
+ GeometryMapper::SourceToDestinationRect(&t0(), local_state.Transform(), rect);
EXPECT_FLOAT_RECT_NEAR(input_rect, rect);
}
TEST_P(GeometryMapperTest, RotationAndScaleTransform) {
expected_transform = TransformationMatrix().Rotate(45).Scale(2);
- auto transform =
- CreateTransform(TransformPaintPropertyNode::Root(), expected_transform);
+ auto transform = CreateTransform(t0(), expected_transform);
local_state.SetTransform(transform.get());
input_rect = FloatRect(0, 0, 100, 100);
@@ -199,8 +195,8 @@ TEST_P(GeometryMapperTest, RotationAndScaleTransform) {
TEST_P(GeometryMapperTest, RotationAndScaleTransformWithTransformOrigin) {
expected_transform = TransformationMatrix().Rotate(45).Scale(2);
- auto transform = CreateTransform(TransformPaintPropertyNode::Root(),
- expected_transform, FloatPoint3D(50, 50, 0));
+ auto transform =
+ CreateTransform(t0(), expected_transform, FloatPoint3D(50, 50, 0));
local_state.SetTransform(transform.get());
input_rect = FloatRect(0, 0, 100, 100);
@@ -213,11 +209,10 @@ TEST_P(GeometryMapperTest, RotationAndScaleTransformWithTransformOrigin) {
TEST_P(GeometryMapperTest, NestedTransforms) {
auto rotate_transform = TransformationMatrix().Rotate(45);
- auto transform1 =
- CreateTransform(TransformPaintPropertyNode::Root(), rotate_transform);
+ auto transform1 = CreateTransform(t0(), rotate_transform);
auto scale_transform = TransformationMatrix().Scale(2);
- auto transform2 = CreateTransform(transform1, scale_transform);
+ auto transform2 = CreateTransform(*transform1, scale_transform);
local_state.SetTransform(transform2.get());
input_rect = FloatRect(0, 0, 100, 100);
@@ -231,14 +226,14 @@ TEST_P(GeometryMapperTest, NestedTransforms) {
TEST_P(GeometryMapperTest, NestedTransformsFlattening) {
TransformPaintPropertyNode::State rotate_transform;
rotate_transform.matrix.Rotate3d(45, 0, 0);
- auto transform1 = TransformPaintPropertyNode::Create(
- TransformPaintPropertyNode::Root(), std::move(rotate_transform));
+ auto transform1 =
+ TransformPaintPropertyNode::Create(t0(), std::move(rotate_transform));
TransformPaintPropertyNode::State inverse_rotate_transform;
inverse_rotate_transform.matrix.Rotate3d(-45, 0, 0);
inverse_rotate_transform.flattens_inherited_transform = true;
auto transform2 = TransformPaintPropertyNode::Create(
- transform1, std::move(inverse_rotate_transform));
+ *transform1, std::move(inverse_rotate_transform));
local_state.SetTransform(transform2.get());
input_rect = FloatRect(0, 0, 100, 100);
@@ -254,11 +249,10 @@ TEST_P(GeometryMapperTest, NestedTransformsFlattening) {
TEST_P(GeometryMapperTest, NestedTransformsScaleAndTranslation) {
auto scale_transform = TransformationMatrix().Scale(2);
- auto transform1 =
- CreateTransform(TransformPaintPropertyNode::Root(), scale_transform);
+ auto transform1 = CreateTransform(t0(), scale_transform);
auto translate_transform = TransformationMatrix().Translate(100, 0);
- auto transform2 = CreateTransform(transform1, translate_transform);
+ auto transform2 = CreateTransform(*transform1, translate_transform);
local_state.SetTransform(transform2.get());
input_rect = FloatRect(0, 0, 100, 100);
@@ -272,12 +266,11 @@ TEST_P(GeometryMapperTest, NestedTransformsScaleAndTranslation) {
}
TEST_P(GeometryMapperTest, NestedTransformsIntermediateDestination) {
- auto rotate_transform = TransformationMatrix().Rotate(45);
- auto transform1 =
- CreateTransform(TransformPaintPropertyNode::Root(), rotate_transform);
+ auto translate_transform = TransformationMatrix().Translate(10, 20);
+ auto transform1 = CreateTransform(t0(), translate_transform);
- auto scale_transform = TransformationMatrix().Translate(10, 20);
- auto transform2 = CreateTransform(transform1, scale_transform);
+ auto scale_transform = TransformationMatrix().Scale(3);
+ auto transform2 = CreateTransform(*transform1, scale_transform);
local_state.SetTransform(transform2.get());
ancestor_state.SetTransform(transform1.get());
@@ -286,13 +279,12 @@ TEST_P(GeometryMapperTest, NestedTransformsIntermediateDestination) {
input_rect = FloatRect(0, 0, 100, 100);
expected_transformed_rect = expected_transform.MapRect(input_rect);
expected_visual_rect = FloatClipRect(expected_transformed_rect);
+ expected_visual_rect.ClearIsTight();
CHECK_MAPPINGS();
}
TEST_P(GeometryMapperTest, SimpleClip) {
- auto clip = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(10, 10, 50, 50));
+ auto clip = CreateClip(c0(), &t0(), FloatRoundedRect(10, 10, 50, 50));
local_state.SetClip(clip.get());
input_rect = FloatRect(0, 0, 100, 100);
@@ -304,12 +296,11 @@ TEST_P(GeometryMapperTest, SimpleClip) {
TEST_P(GeometryMapperTest, SimpleClipOverlayScrollbars) {
ClipPaintPropertyNode::State clip_state;
- clip_state.local_transform_space = TransformPaintPropertyNode::Root();
+ clip_state.local_transform_space = &t0();
clip_state.clip_rect = FloatRoundedRect(10, 10, 50, 50);
clip_state.clip_rect_excluding_overlay_scrollbars =
FloatRoundedRect(10, 10, 45, 43);
- auto clip = ClipPaintPropertyNode::Create(ClipPaintPropertyNode::Root(),
- std::move(clip_state));
+ auto clip = ClipPaintPropertyNode::Create(c0(), std::move(clip_state));
local_state.SetClip(clip.get());
input_rect = FloatRect(0, 0, 100, 100);
@@ -344,12 +335,7 @@ TEST_P(GeometryMapperTest, SimpleClipOverlayScrollbars) {
}
TEST_P(GeometryMapperTest, SimpleClipInclusiveIntersect) {
- ClipPaintPropertyNode::State clip_state;
- clip_state.local_transform_space = TransformPaintPropertyNode::Root();
- clip_state.clip_rect = FloatRoundedRect(10, 10, 50, 50);
- auto clip = ClipPaintPropertyNode::Create(ClipPaintPropertyNode::Root(),
- std::move(clip_state));
-
+ auto clip = CreateClip(c0(), &t0(), FloatRoundedRect(10, 10, 50, 50));
local_state.SetClip(clip.get());
FloatClipRect actual_clip_rect(FloatRect(60, 10, 10, 10));
@@ -372,8 +358,7 @@ TEST_P(GeometryMapperTest, RoundedClip) {
FloatRoundedRect rect(FloatRect(10, 10, 50, 50),
FloatRoundedRect::Radii(FloatSize(1, 1), FloatSize(),
FloatSize(), FloatSize()));
- auto clip = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(), rect);
+ auto clip = CreateClip(c0(), &t0(), rect);
local_state.SetClip(clip.get());
input_rect = FloatRect(0, 0, 100, 100);
@@ -388,9 +373,7 @@ TEST_P(GeometryMapperTest, ClipPath) {
FloatRoundedRect rect(FloatRect(10, 10, 50, 50),
FloatRoundedRect::Radii(FloatSize(1, 1), FloatSize(),
FloatSize(), FloatSize()));
- auto clip = CreateClipPathClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(10, 10, 50, 50));
+ auto clip = CreateClipPathClip(c0(), &t0(), FloatRoundedRect(10, 10, 50, 50));
local_state.SetClip(clip.get());
input_rect = FloatRect(0, 0, 100, 100);
@@ -407,11 +390,8 @@ TEST_P(GeometryMapperTest, TwoClips) {
FloatRoundedRect::Radii(FloatSize(1, 1), FloatSize(), FloatSize(),
FloatSize()));
- auto clip1 = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(), clip_rect1);
-
- auto clip2 = CreateClip(clip1, TransformPaintPropertyNode::Root(),
- FloatRoundedRect(10, 10, 50, 50));
+ auto clip1 = CreateClip(c0(), &t0(), clip_rect1);
+ auto clip2 = CreateClip(*clip1, &t0(), FloatRoundedRect(10, 10, 50, 50));
local_state.SetClip(clip2.get());
input_rect = FloatRect(0, 0, 100, 100);
@@ -428,19 +408,16 @@ TEST_P(GeometryMapperTest, TwoClips) {
}
TEST_P(GeometryMapperTest, TwoClipsTransformAbove) {
- auto transform = CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix());
+ auto transform = CreateTransform(t0(), TransformationMatrix());
FloatRoundedRect clip_rect1(
FloatRect(10, 10, 50, 50),
FloatRoundedRect::Radii(FloatSize(1, 1), FloatSize(), FloatSize(),
FloatSize()));
- auto clip1 =
- CreateClip(ClipPaintPropertyNode::Root(), transform.get(), clip_rect1);
-
+ auto clip1 = CreateClip(c0(), transform.get(), clip_rect1);
auto clip2 =
- CreateClip(clip1, transform.get(), FloatRoundedRect(10, 10, 30, 40));
+ CreateClip(*clip1, transform.get(), FloatRoundedRect(10, 10, 30, 40));
local_state.SetClip(clip2.get());
input_rect = FloatRect(0, 0, 100, 100);
@@ -459,10 +436,9 @@ TEST_P(GeometryMapperTest, TwoClipsTransformAbove) {
TEST_P(GeometryMapperTest, ClipBeforeTransform) {
expected_transform = TransformationMatrix().Rotate(45);
- auto transform =
- CreateTransform(TransformPaintPropertyNode::Root(), expected_transform);
- auto clip = CreateClip(ClipPaintPropertyNode::Root(), transform.get(),
- FloatRoundedRect(10, 10, 50, 50));
+ auto transform = CreateTransform(t0(), expected_transform);
+ auto clip =
+ CreateClip(c0(), transform.get(), FloatRoundedRect(10, 10, 50, 50));
local_state.SetClip(clip.get());
local_state.SetTransform(transform.get());
@@ -480,11 +456,8 @@ TEST_P(GeometryMapperTest, ClipBeforeTransform) {
TEST_P(GeometryMapperTest, ClipAfterTransform) {
expected_transform = TransformationMatrix().Rotate(45);
- auto transform =
- CreateTransform(TransformPaintPropertyNode::Root(), expected_transform);
- auto clip = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(10, 10, 200, 200));
+ auto transform = CreateTransform(t0(), expected_transform);
+ auto clip = CreateClip(c0(), &t0(), FloatRoundedRect(10, 10, 200, 200));
local_state.SetClip(clip.get());
local_state.SetTransform(transform.get());
@@ -500,16 +473,11 @@ TEST_P(GeometryMapperTest, ClipAfterTransform) {
}
TEST_P(GeometryMapperTest, TwoClipsWithTransformBetween) {
- auto clip1 = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(10, 10, 200, 200));
-
+ auto clip1 = CreateClip(c0(), &t0(), FloatRoundedRect(10, 10, 200, 200));
expected_transform = TransformationMatrix().Rotate(45);
- auto transform =
- CreateTransform(TransformPaintPropertyNode::Root(), expected_transform);
-
+ auto transform = CreateTransform(t0(), expected_transform);
auto clip2 =
- CreateClip(clip1, transform.get(), FloatRoundedRect(10, 10, 200, 200));
+ CreateClip(*clip1, transform.get(), FloatRoundedRect(10, 10, 200, 200));
input_rect = FloatRect(0, 0, 100, 100);
expected_transformed_rect = expected_transform.MapRect(input_rect);
@@ -553,12 +521,10 @@ TEST_P(GeometryMapperTest, SiblingTransforms) {
// These transforms are siblings. Thus mapping from one to the other requires
// going through the root.
auto rotate_transform1 = TransformationMatrix().Rotate(45);
- auto transform1 =
- CreateTransform(TransformPaintPropertyNode::Root(), rotate_transform1);
+ auto transform1 = CreateTransform(t0(), rotate_transform1);
auto rotate_transform2 = TransformationMatrix().Rotate(-45);
- auto transform2 =
- CreateTransform(TransformPaintPropertyNode::Root(), rotate_transform2);
+ auto transform2 = CreateTransform(t0(), rotate_transform2);
auto transform1_state = PropertyTreeState::Root();
transform1_state.SetTransform(transform1.get());
@@ -597,15 +563,13 @@ TEST_P(GeometryMapperTest, SiblingTransformsWithClip) {
// These transforms are siblings. Thus mapping from one to the other requires
// going through the root.
auto rotate_transform1 = TransformationMatrix().Rotate(45);
- auto transform1 =
- CreateTransform(TransformPaintPropertyNode::Root(), rotate_transform1);
+ auto transform1 = CreateTransform(t0(), rotate_transform1);
auto rotate_transform2 = TransformationMatrix().Rotate(-45);
- auto transform2 =
- CreateTransform(TransformPaintPropertyNode::Root(), rotate_transform2);
+ auto transform2 = CreateTransform(t0(), rotate_transform2);
- auto clip = CreateClip(ClipPaintPropertyNode::Root(), transform2.get(),
- FloatRoundedRect(10, 20, 30, 40));
+ auto clip =
+ CreateClip(c0(), transform2.get(), FloatRoundedRect(10, 20, 30, 40));
auto transform1_state = PropertyTreeState::Root();
transform1_state.SetTransform(transform1.get());
@@ -619,7 +583,7 @@ TEST_P(GeometryMapperTest, SiblingTransformsWithClip) {
LocalToAncestorVisualRectInternal(transform1_state, transform2_and_clip_state,
result, success);
// Fails, because the clip of the destination state is not an ancestor of the
- // clip of the source state. A known bug in SPv1* would make such query,
+ // clip of the source state. A known bug in SPv1 would make such query,
// in such case, no clips are applied.
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
EXPECT_FALSE(success);
@@ -642,24 +606,22 @@ TEST_P(GeometryMapperTest, SiblingTransformsWithClip) {
TEST_P(GeometryMapperTest, FilterWithClipsAndTransforms) {
auto transform_above_effect =
- CreateTransform(TransformPaintPropertyNode::Root(),
- TransformationMatrix().Translate(40, 50));
+ CreateTransform(t0(), TransformationMatrix().Translate(40, 50));
auto transform_below_effect = CreateTransform(
- transform_above_effect, TransformationMatrix().Translate(20, 30));
+ *transform_above_effect, TransformationMatrix().Translate(20, 30));
// This clip is between transformAboveEffect and the effect.
- auto clip_above_effect =
- CreateClip(ClipPaintPropertyNode::Root(), transform_above_effect,
- FloatRoundedRect(-100, -100, 200, 200));
+ auto clip_above_effect = CreateClip(c0(), transform_above_effect.get(),
+ FloatRoundedRect(-100, -100, 200, 200));
// This clip is between the effect and transformBelowEffect.
- auto clip_below_effect = CreateClip(clip_above_effect, transform_above_effect,
- FloatRoundedRect(10, 10, 100, 100));
+ auto clip_below_effect =
+ CreateClip(*clip_above_effect, transform_above_effect.get(),
+ FloatRoundedRect(10, 10, 100, 100));
CompositorFilterOperations filters;
filters.AppendBlurFilter(20);
- auto effect =
- CreateFilterEffect(EffectPaintPropertyNode::Root(),
- transform_above_effect, clip_above_effect, filters);
+ auto effect = CreateFilterEffect(e0(), transform_above_effect.get(),
+ clip_above_effect.get(), filters);
local_state = PropertyTreeState(transform_below_effect.get(),
clip_below_effect.get(), effect.get());
@@ -694,8 +656,7 @@ TEST_P(GeometryMapperTest, ReflectionWithPaintOffset) {
CompositorFilterOperations filters;
filters.AppendReferenceFilter(PaintFilterBuilder::BuildBoxReflectFilter(
BoxReflection(BoxReflection::kHorizontalReflection, 0), nullptr));
- auto effect = CreateFilterEffect(EffectPaintPropertyNode::Root(), filters,
- FloatPoint(100, 100));
+ auto effect = CreateFilterEffect(e0(), filters, FloatPoint(100, 100));
local_state.SetEffect(effect.get());
input_rect = FloatRect(100, 100, 50, 50);
@@ -708,15 +669,12 @@ TEST_P(GeometryMapperTest, ReflectionWithPaintOffset) {
}
TEST_P(GeometryMapperTest, InvertedClip) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
+ // This test is invalid for SPv2.
+ if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
return;
- auto clip = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(10, 10, 50, 50));
-
- PropertyTreeState dest(TransformPaintPropertyNode::Root(), clip.get(),
- EffectPaintPropertyNode::Root());
+ auto clip = CreateClip(c0(), &t0(), FloatRoundedRect(10, 10, 50, 50));
+ PropertyTreeState dest(&t0(), clip.get(), &e0());
FloatClipRect visual_rect(FloatRect(0, 0, 10, 200));
GeometryMapper::LocalToAncestorVisualRect(PropertyTreeState::Root(), dest,
@@ -730,16 +688,10 @@ TEST_P(GeometryMapperTest, InvertedClip) {
}
TEST_P(GeometryMapperTest, PointVisibleInAncestorSpaceSimpleClip) {
- auto clip = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(10, 10, 50, 50));
+ auto clip = CreateClip(c0(), &t0(), FloatRoundedRect(10, 10, 50, 50));
- PropertyTreeState local_state(TransformPaintPropertyNode::Root(), clip.get(),
- EffectPaintPropertyNode::Root());
-
- PropertyTreeState ancestor_state(TransformPaintPropertyNode::Root(),
- ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root());
+ PropertyTreeState local_state(&t0(), clip.get(), &e0());
+ PropertyTreeState ancestor_state = PropertyTreeState::Root();
EXPECT_TRUE(GeometryMapper::PointVisibleInAncestorSpace(
local_state, ancestor_state, FloatPoint(30, 30)));
@@ -756,15 +708,10 @@ TEST_P(GeometryMapperTest, PointVisibleInAncestorSpaceRoundedClip) {
FloatRoundedRect::Radii radii;
radii.SetTopLeft(FloatSize(8, 8));
clip_rect.SetRadii(radii);
- auto clip = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(), clip_rect);
+ auto clip = CreateClip(c0(), &t0(), clip_rect);
- PropertyTreeState local_state(TransformPaintPropertyNode::Root(), clip.get(),
- EffectPaintPropertyNode::Root());
-
- PropertyTreeState ancestor_state(TransformPaintPropertyNode::Root(),
- ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root());
+ PropertyTreeState local_state(&t0(), clip.get(), &e0());
+ PropertyTreeState ancestor_state = PropertyTreeState::Root();
EXPECT_TRUE(GeometryMapper::PointVisibleInAncestorSpace(
local_state, ancestor_state, FloatPoint(30, 30)));
@@ -786,18 +733,13 @@ TEST_P(GeometryMapperTest, PointVisibleInAncestorSpaceClipPath) {
path->AddLineTo(FloatPoint(10, 10));
ClipPaintPropertyNode::State state;
- state.local_transform_space = TransformPaintPropertyNode::Root();
+ state.local_transform_space = &t0();
state.clip_rect = FloatRoundedRect(FloatRect(0, 0, 500, 500));
state.clip_path = base::AdoptRef(path);
- auto clip = ClipPaintPropertyNode::Create(ClipPaintPropertyNode::Root(),
- std::move(state));
+ auto clip = ClipPaintPropertyNode::Create(c0(), std::move(state));
- PropertyTreeState local_state(TransformPaintPropertyNode::Root(), clip.get(),
- EffectPaintPropertyNode::Root());
-
- PropertyTreeState ancestor_state(TransformPaintPropertyNode::Root(),
- ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root());
+ PropertyTreeState local_state(&t0(), clip.get(), &e0());
+ PropertyTreeState ancestor_state = PropertyTreeState::Root();
EXPECT_TRUE(GeometryMapper::PointVisibleInAncestorSpace(
local_state, ancestor_state, FloatPoint(30, 30)));
@@ -810,21 +752,13 @@ TEST_P(GeometryMapperTest, PointVisibleInAncestorSpaceClipPath) {
}
TEST_P(GeometryMapperTest, PointVisibleInAncestorSpaceSimpleClipWithTransform) {
- TransformPaintPropertyNode::State translate_transform;
- translate_transform.matrix.Translate(10, 10);
- auto transform = TransformPaintPropertyNode::Create(
- TransformPaintPropertyNode::Root(), std::move(translate_transform));
-
- auto clip = CreateClip(ClipPaintPropertyNode::Root(),
- TransformPaintPropertyNode::Root(),
- FloatRoundedRect(FloatRect(20, 20, 50, 50)));
-
- PropertyTreeState local_state(transform.get(), clip.get(),
- EffectPaintPropertyNode::Root());
+ auto transform =
+ CreateTransform(t0(), TransformationMatrix().Translate(10, 10));
+ auto clip =
+ CreateClip(c0(), &t0(), FloatRoundedRect(FloatRect(20, 20, 50, 50)));
- PropertyTreeState ancestor_state(TransformPaintPropertyNode::Root(),
- ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root());
+ PropertyTreeState local_state(transform.get(), clip.get(), &e0());
+ PropertyTreeState ancestor_state = PropertyTreeState::Root();
EXPECT_TRUE(GeometryMapper::PointVisibleInAncestorSpace(
local_state, ancestor_state, FloatPoint(30, 30)));
@@ -837,10 +771,8 @@ TEST_P(GeometryMapperTest, PointVisibleInAncestorSpaceSimpleClipWithTransform) {
}
TEST_P(GeometryMapperTest, PointVisibleInAncestorSpaceClipPathWithTransform) {
- TransformPaintPropertyNode::State translate_transform;
- translate_transform.matrix.Translate(10, 10);
- auto transform = TransformPaintPropertyNode::Create(
- TransformPaintPropertyNode::Root(), std::move(translate_transform));
+ auto transform =
+ CreateTransform(t0(), TransformationMatrix().Translate(10, 10));
RefCountedPath* path = new RefCountedPath;
path->MoveTo(FloatPoint(20, 20));
@@ -850,18 +782,13 @@ TEST_P(GeometryMapperTest, PointVisibleInAncestorSpaceClipPathWithTransform) {
path->AddLineTo(FloatPoint(20, 20));
ClipPaintPropertyNode::State state;
- state.local_transform_space = TransformPaintPropertyNode::Root();
+ state.local_transform_space = &t0();
state.clip_rect = FloatRoundedRect(FloatRect(0, 0, 500, 500));
state.clip_path = base::AdoptRef(path);
- auto clip = ClipPaintPropertyNode::Create(ClipPaintPropertyNode::Root(),
- std::move(state));
+ auto clip = ClipPaintPropertyNode::Create(c0(), std::move(state));
- PropertyTreeState local_state(transform.get(), clip.get(),
- EffectPaintPropertyNode::Root());
-
- PropertyTreeState ancestor_state(TransformPaintPropertyNode::Root(),
- ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root());
+ PropertyTreeState local_state(transform.get(), clip.get(), &e0());
+ PropertyTreeState ancestor_state = PropertyTreeState::Root();
EXPECT_TRUE(GeometryMapper::PointVisibleInAncestorSpace(
local_state, ancestor_state, FloatPoint(30, 30)));
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.cc
new file mode 100644
index 00000000000..521bc105320
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.cc
@@ -0,0 +1,32 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/graphics/paint/hit_test_data.h"
+
+#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
+#include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
+
+namespace blink {
+
+void HitTestData::RecordTouchActionRect(GraphicsContext& context,
+ const DisplayItemClient& client,
+ const TouchActionRect& action) {
+ DCHECK(RuntimeEnabledFeatures::PaintTouchActionRectsEnabled());
+
+ PaintController& paint_controller = context.GetPaintController();
+ if (paint_controller.DisplayItemConstructionIsDisabled())
+ return;
+
+ // A display item must be created to ensure a paint chunk exists. For example,
+ // without this, an empty div with a transform will incorrectly use the
+ // parent paint chunk instead of creating a new one.
+ paint_controller.CreateAndAppend<DrawingDisplayItem>(
+ client, DisplayItem::kHitTest, nullptr, false);
+
+ auto& chunk = paint_controller.CurrentPaintChunk();
+ chunk.EnsureHitTestData().touch_action_rects.push_back(action);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.h b/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.h
index 48d154d8fca..c3303700fd2 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/hit_test_data.h
@@ -12,28 +12,40 @@
namespace blink {
+class DisplayItemClient;
+class GraphicsContext;
+
+using TouchActionRects = Vector<TouchActionRect>;
+
struct PLATFORM_EXPORT HitTestData {
+ // TODO(pdr): Is |border_rect| needed?
FloatRect border_rect;
- TouchActionRect touch_action_rect =
- TouchActionRect(LayoutRect(), cc::kTouchActionNone);
+ TouchActionRects touch_action_rects;
Region wheel_event_handler_region;
Region non_fast_scrollable_region;
HitTestData() = default;
HitTestData(const HitTestData& other)
: border_rect(other.border_rect),
- touch_action_rect(other.touch_action_rect),
+ touch_action_rects(other.touch_action_rects),
wheel_event_handler_region(other.wheel_event_handler_region),
non_fast_scrollable_region(other.non_fast_scrollable_region) {}
bool operator==(const HitTestData& rhs) const {
return border_rect == rhs.border_rect &&
- touch_action_rect == rhs.touch_action_rect &&
+ touch_action_rects == rhs.touch_action_rects &&
wheel_event_handler_region == rhs.wheel_event_handler_region &&
non_fast_scrollable_region == rhs.non_fast_scrollable_region;
}
bool operator!=(const HitTestData& rhs) const { return !(*this == rhs); }
+
+ // Records a display item for hit testing to ensure a paint chunk exists and
+ // is sized to include touch action rects, then adds the touch action rect to
+ // |HitTestData.touch_action_rects|.
+ static void RecordTouchActionRect(GraphicsContext&,
+ const DisplayItemClient&,
+ const TouchActionRect&);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
index bc8a9648f61..d1366a474bc 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.cc
@@ -19,11 +19,11 @@ namespace {
void ComputeChunkBoundsAndOpaqueness(const DisplayItemList& display_items,
Vector<PaintChunk>& paint_chunks) {
- // This happens in tests testing paint chunks without display items.
- if (display_items.IsEmpty())
- return;
-
for (PaintChunk& chunk : paint_chunks) {
+ // This happens in tests testing paint chunks without display items.
+ if (!chunk.size())
+ continue;
+
FloatRect bounds;
SkRegion known_to_be_opaque_region;
for (const DisplayItem& item : display_items.ItemsInPaintChunk(chunk)) {
@@ -49,41 +49,29 @@ void ComputeChunkBoundsAndOpaqueness(const DisplayItemList& display_items,
PaintArtifact::PaintArtifact() : display_item_list_(0) {}
PaintArtifact::PaintArtifact(DisplayItemList display_items,
- PaintChunksAndRasterInvalidations data)
- : display_item_list_(std::move(display_items)),
- chunks_and_invalidations_(std::move(data)) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- ComputeChunkBoundsAndOpaqueness(display_item_list_,
- chunks_and_invalidations_.chunks);
- }
+ Vector<PaintChunk> chunks)
+ : display_item_list_(std::move(display_items)), chunks_(std::move(chunks)) {
+ ComputeChunkBoundsAndOpaqueness(display_item_list_, chunks_);
}
-PaintArtifact::PaintArtifact(PaintArtifact&& source)
- : display_item_list_(std::move(source.display_item_list_)),
- chunks_and_invalidations_(std::move(source.chunks_and_invalidations_)) {}
-
PaintArtifact::~PaintArtifact() = default;
-PaintArtifact& PaintArtifact::operator=(PaintArtifact&& source) {
- display_item_list_ = std::move(source.display_item_list_);
- chunks_and_invalidations_ = std::move(source.chunks_and_invalidations_);
- return *this;
+scoped_refptr<PaintArtifact> PaintArtifact::Create(
+ DisplayItemList display_items,
+ Vector<PaintChunk> chunks) {
+ return base::AdoptRef(
+ new PaintArtifact(std::move(display_items), std::move(chunks)));
}
-void PaintArtifact::Reset() {
- display_item_list_.Clear();
- chunks_and_invalidations_.Clear();
+scoped_refptr<PaintArtifact> PaintArtifact::Empty() {
+ DEFINE_STATIC_REF(PaintArtifact, empty, base::AdoptRef(new PaintArtifact()));
+ return empty;
}
size_t PaintArtifact::ApproximateUnsharedMemoryUsage() const {
- // This function must be called after a full document life cycle update,
- // when we have cleared raster invalidation information.
- DCHECK(chunks_and_invalidations_.raster_invalidation_rects.IsEmpty());
- DCHECK(chunks_and_invalidations_.raster_invalidation_trackings.IsEmpty());
size_t total_size = sizeof(*this) + display_item_list_.MemoryUsageInBytes() +
- chunks_and_invalidations_.chunks.capacity() *
- sizeof(chunks_and_invalidations_.chunks[0]);
- for (const auto& chunk : chunks_and_invalidations_.chunks)
+ chunks_.capacity() * sizeof(chunks_[0]);
+ for (const auto& chunk : chunks_)
total_size += chunk.MemoryUsageInBytes();
return total_size;
}
@@ -91,21 +79,13 @@ size_t PaintArtifact::ApproximateUnsharedMemoryUsage() const {
void PaintArtifact::Replay(GraphicsContext& graphics_context,
const PropertyTreeState& replay_state,
const IntPoint& offset) const {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- DCHECK(offset == IntPoint());
- TRACE_EVENT0("blink,benchmark", "PaintArtifact::replay");
- for (const DisplayItem& display_item : display_item_list_)
- display_item.Replay(graphics_context);
- } else {
- Replay(*graphics_context.Canvas(), replay_state, offset);
- }
+ Replay(*graphics_context.Canvas(), replay_state, offset);
}
-void PaintArtifact::Replay(PaintCanvas& canvas,
+void PaintArtifact::Replay(cc::PaintCanvas& canvas,
const PropertyTreeState& replay_state,
const IntPoint& offset) const {
TRACE_EVENT0("blink,benchmark", "PaintArtifact::replay");
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
scoped_refptr<cc::DisplayItemList> display_item_list =
PaintChunksToCcLayer::Convert(
PaintChunks(), replay_state, gfx::Vector2dF(offset.X(), offset.Y()),
@@ -123,12 +103,10 @@ void PaintArtifact::AppendToDisplayItemList(const FloatSize& visual_rect_offset,
}
void PaintArtifact::FinishCycle() {
- for (auto& chunk : chunks_and_invalidations_.chunks) {
+ for (auto& chunk : chunks_) {
chunk.client_is_just_created = false;
chunk.properties.ClearChangedToRoot();
}
- chunks_and_invalidations_.raster_invalidation_rects.clear();
- chunks_and_invalidations_.raster_invalidation_trackings.clear();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
index d181e81a28a..6214baea2f2 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_artifact.h
@@ -5,68 +5,43 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_PAINT_ARTIFACT_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_PAINT_ARTIFACT_H_
+#include "base/macros.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item_list.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_chunk.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h"
-#include "third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
-namespace blink {
+namespace cc {
+class PaintCanvas;
+}
+namespace blink {
class GraphicsContext;
class PaintChunkSubset;
-using ChunkRasterInvalidationRects = Vector<FloatRect, 2>;
-using ChunkRasterInvalidationTracking = Vector<RasterInvalidationInfo>;
-
-struct PaintChunksAndRasterInvalidations {
- void Clear() {
- chunks.clear();
- raster_invalidation_rects.clear();
- raster_invalidation_trackings.clear();
- }
-
- Vector<PaintChunk> chunks;
- Vector<ChunkRasterInvalidationRects> raster_invalidation_rects;
- Vector<ChunkRasterInvalidationTracking> raster_invalidation_trackings;
-};
-
-// The output of painting, consisting of
-// - display item list (in DisplayItemList),
-// - paint chunks and their paint invalidations (in
-// PaintChunksAndRasterInvalidations).
+// The output of painting, consisting of display item list (in DisplayItemList)
+// and paint chunks.
//
// Display item list and paint chunks not only represent the output of the
// current painting, but also serve as cache of individual display items and
// paint chunks for later paintings as long as the display items and chunks are
// valid.
//
-// Raster invalidations are consumed by CompositedLayerRasterInvalidator and
-// will be cleared after a cycle is complete via |FinishCycle()|.
-//
// It represents a particular state of the world, and should be immutable
// (const) to most of its users.
//
// Unless its dangerous accessors are used, it promises to be in a reasonable
// state (e.g. chunk bounding boxes computed).
-//
-// Reminder: moved-from objects may not be in a known state. They can only
-// safely be assigned to or destroyed.
-class PLATFORM_EXPORT PaintArtifact final {
- DISALLOW_NEW();
- WTF_MAKE_NONCOPYABLE(PaintArtifact);
-
+class PLATFORM_EXPORT PaintArtifact final : public RefCounted<PaintArtifact> {
public:
- PaintArtifact();
- PaintArtifact(DisplayItemList, PaintChunksAndRasterInvalidations);
- PaintArtifact(PaintArtifact&&);
- ~PaintArtifact();
+ static scoped_refptr<PaintArtifact> Create(DisplayItemList,
+ Vector<PaintChunk>);
+
+ static scoped_refptr<PaintArtifact> Empty();
- PaintArtifact& operator=(PaintArtifact&&);
+ ~PaintArtifact();
bool IsEmpty() const { return display_item_list_.IsEmpty(); }
@@ -75,10 +50,8 @@ class PLATFORM_EXPORT PaintArtifact final {
return display_item_list_;
}
- Vector<PaintChunk>& PaintChunks() { return chunks_and_invalidations_.chunks; }
- const Vector<PaintChunk>& PaintChunks() const {
- return chunks_and_invalidations_.chunks;
- }
+ Vector<PaintChunk>& PaintChunks() { return chunks_; }
+ const Vector<PaintChunk>& PaintChunks() const { return chunks_; }
PaintChunkSubset GetPaintChunkSubset(
const Vector<size_t>& subset_indices) const {
@@ -90,22 +63,19 @@ class PLATFORM_EXPORT PaintArtifact final {
return FindChunkInVectorByDisplayItemIndex(PaintChunks(), index);
}
- // Resets to an empty paint artifact.
- void Reset();
-
// Returns the approximate memory usage, excluding memory likely to be
// shared with the embedder after copying to cc::DisplayItemList.
size_t ApproximateUnsharedMemoryUsage() const;
- // Draws the paint artifact to a GraphicsContext.
- // In SPv175+ mode, replays into the ancestor state given by |replay_state|.
+ // Draws the paint artifact to a GraphicsContext, into the ancestor state
+ // given by |replay_state|.
void Replay(GraphicsContext&,
const PropertyTreeState& replay_state,
const IntPoint& offset = IntPoint()) const;
// Draws the paint artifact to a PaintCanvas, into the ancestor state given
- // by |replay_state|. For SPv175+ only.
- void Replay(PaintCanvas&,
+ // by |replay_state|.
+ void Replay(cc::PaintCanvas&,
const PropertyTreeState& replay_state,
const IntPoint& offset = IntPoint()) const;
@@ -113,44 +83,19 @@ class PLATFORM_EXPORT PaintArtifact final {
void AppendToDisplayItemList(const FloatSize& visual_rect_offset,
cc::DisplayItemList& display_list) const;
- const ChunkRasterInvalidationRects* GetRasterInvalidationRects(
- size_t chunk_index) const {
- return chunk_index <
- chunks_and_invalidations_.raster_invalidation_rects.size()
- ? &chunks_and_invalidations_
- .raster_invalidation_rects[chunk_index]
- : nullptr;
- }
-
- const ChunkRasterInvalidationRects* GetRasterInvalidationRects(
- const PaintChunk& chunk) const {
- return GetRasterInvalidationRects(
- &chunk - &chunks_and_invalidations_.chunks.front());
- }
-
- const ChunkRasterInvalidationTracking* GetRasterInvalidationTracking(
- size_t chunk_index) const {
- return chunk_index < chunks_and_invalidations_.raster_invalidation_trackings
- .size()
- ? &chunks_and_invalidations_
- .raster_invalidation_trackings[chunk_index]
- : nullptr;
- }
-
- const ChunkRasterInvalidationTracking* GetRasterInvalidationTracking(
- const PaintChunk& chunk) const {
- return GetRasterInvalidationTracking(
- &chunk - &chunks_and_invalidations_.chunks.front());
- }
-
// Called when the caller finishes updating a full document life cycle.
// Will cleanup data (e.g. raster invalidations) that will no longer be used
// for the next cycle, and update status to be ready for the next cycle.
void FinishCycle();
private:
+ PaintArtifact();
+ PaintArtifact(DisplayItemList, Vector<PaintChunk>);
+
DisplayItemList display_item_list_;
- PaintChunksAndRasterInvalidations chunks_and_invalidations_;
+ Vector<PaintChunk> chunks_;
+
+ DISALLOW_COPY_AND_ASSIGN(PaintArtifact);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_canvas.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_canvas.h
index 1b65ffd7783..464d353e01d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_canvas.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_canvas.h
@@ -9,7 +9,6 @@
#include "cc/paint/skia_paint_canvas.h"
namespace blink {
-using cc::PaintCanvas;
using cc::SkiaPaintCanvas;
using cc::PaintCanvasAutoRestore;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.cc
index 10489b4bab8..fe337c41e3f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.cc
@@ -31,12 +31,10 @@ String PaintChunk::ToString() const {
known_to_be_opaque);
if (hit_test_data) {
ret_val.append(String::Format(
- ", border_rect=(%s), touch_action_rect=((%s), %s), "
+ ", border_rect=(%s), touch_action_rects=(%zu), "
"wheel_event_handler_region=(%s) non_fast_scrollable_region=(%s))",
hit_test_data->border_rect.ToString().Ascii().data(),
- hit_test_data->touch_action_rect.rect.ToString().Ascii().data(),
- TouchActionToString(
- hit_test_data->touch_action_rect.whitelisted_touch_action),
+ hit_test_data->touch_action_rects.size(),
hit_test_data->wheel_event_handler_region.Bounds()
.ToString()
.Ascii()
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h
index 4504b5e2ae2..21fa83c348c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk.h
@@ -23,30 +23,22 @@ namespace blink {
//
// This is expected to be owned by the paint artifact which also owns the
// related drawings.
-//
-// This is a Slimming Paint v175+ class.
struct PLATFORM_EXPORT PaintChunk {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
using Id = DisplayItem::Id;
- enum Cacheable {
- kCacheable,
- kUncacheable,
- };
-
PaintChunk(size_t begin,
size_t end,
const Id& id,
- const PropertyTreeState& props,
- Cacheable cacheable = kCacheable)
+ const PropertyTreeState& props)
: begin_index(begin),
end_index(end),
id(id),
properties(props),
outset_for_raster_effects(0),
known_to_be_opaque(false),
- is_cacheable(cacheable == kCacheable),
+ is_cacheable(id.client.IsCacheable()),
client_is_just_created(id.client.IsJustCreated()),
hit_test_data(nullptr) {}
@@ -80,10 +72,15 @@ struct PLATFORM_EXPORT PaintChunk {
return *hit_test_data.get();
}
+ HitTestData* GetHitTestData() const { return hit_test_data.get(); }
+
size_t MemoryUsageInBytes() const {
size_t total_size = sizeof(*this);
- if (hit_test_data)
+ if (hit_test_data) {
total_size += sizeof(*hit_test_data);
+ total_size += hit_test_data->touch_action_rects.capacity() *
+ sizeof(TouchActionRect);
+ }
return total_size;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h
index 6004a2299d5..15d9ef5932a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h
@@ -26,6 +26,7 @@ class PaintChunkSubset {
class Iterator {
public:
const PaintChunk& operator*() const { return subset_[offset_]; }
+ const PaintChunk* operator->() const { return &subset_[offset_]; }
bool operator!=(const Iterator& other) const {
DCHECK_EQ(&subset_, &other.subset_);
return offset_ != other.offset_;
@@ -35,6 +36,9 @@ class PaintChunkSubset {
return *this;
}
+ // The index in the whole paint chunks set.
+ size_t OriginalIndex() const { return subset_.OriginalIndex(offset_); }
+
private:
friend class PaintChunkSubset;
Iterator(const PaintChunkSubset& subset, size_t offset)
@@ -52,8 +56,15 @@ class PaintChunkSubset {
return subset_indices_ ? subset_indices_->size() : chunks_.size();
}
- const PaintChunk& operator[](int i) const {
- return chunks_[subset_indices_ ? (*subset_indices_)[i] : i];
+ // |i| is an index in the subset.
+ const PaintChunk& operator[](size_t i) const {
+ return chunks_[OriginalIndex(i)];
+ }
+
+ // |i| is an index in the subset.
+ // Returns the index in the whole paint chunks set.
+ size_t OriginalIndex(size_t i) const {
+ return subset_indices_ ? (*subset_indices_)[i] : i;
}
private:
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk_test.cc
index 486b9c24691..a977a3f44ba 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunk_test.cc
@@ -13,7 +13,7 @@ namespace blink {
TEST(PaintChunkTest, MatchesSame) {
auto properties = PropertyTreeState::Root();
FakeDisplayItemClient client;
- client.UpdateCacheGeneration();
+ client.Validate();
DisplayItem::Id id(client, DisplayItem::kDrawingFirst);
EXPECT_TRUE(PaintChunk(0, 1, id, properties)
.Matches(PaintChunk(0, 1, id, properties)));
@@ -22,7 +22,7 @@ TEST(PaintChunkTest, MatchesSame) {
TEST(PaintChunkTest, MatchesEqual) {
auto properties = PropertyTreeState::Root();
FakeDisplayItemClient client;
- client.UpdateCacheGeneration();
+ client.Validate();
DisplayItem::Id id(client, DisplayItem::kDrawingFirst);
DisplayItem::Id id_equal = id;
EXPECT_TRUE(PaintChunk(0, 1, id, properties)
@@ -34,11 +34,11 @@ TEST(PaintChunkTest, MatchesEqual) {
TEST(PaintChunkTest, IdNotMatches) {
auto properties = PropertyTreeState::Root();
FakeDisplayItemClient client1;
- client1.UpdateCacheGeneration();
+ client1.Validate();
DisplayItem::Id id1(client1, DisplayItem::kDrawingFirst);
FakeDisplayItemClient client2;
- client2.UpdateCacheGeneration();
+ client2.Validate();
DisplayItem::Id id2(client2, DisplayItem::kDrawingFirst);
EXPECT_FALSE(PaintChunk(0, 1, id2, properties)
.Matches(PaintChunk(0, 1, id1, properties)));
@@ -47,16 +47,10 @@ TEST(PaintChunkTest, IdNotMatches) {
TEST(PaintChunkTest, IdNotMatchesUncacheable) {
auto properties = PropertyTreeState::Root();
FakeDisplayItemClient client;
- client.UpdateCacheGeneration();
+ client.Invalidate(PaintInvalidationReason::kUncacheable);
DisplayItem::Id id(client, DisplayItem::kDrawingFirst);
- EXPECT_FALSE(PaintChunk(0, 1, id, properties, PaintChunk::kUncacheable)
+ EXPECT_FALSE(PaintChunk(0, 1, id, properties)
.Matches(PaintChunk(0, 1, id, properties)));
- EXPECT_FALSE(
- PaintChunk(0, 1, id, properties)
- .Matches(PaintChunk(0, 1, id, properties, PaintChunk::kUncacheable)));
- EXPECT_FALSE(
- PaintChunk(0, 1, id, properties, PaintChunk::kUncacheable)
- .Matches(PaintChunk(0, 1, id, properties, PaintChunk::kUncacheable)));
}
TEST(PaintChunkTest, IdNotMatchesJustCreated) {
@@ -65,7 +59,7 @@ TEST(PaintChunkTest, IdNotMatchesJustCreated) {
client.emplace();
EXPECT_TRUE(client->IsJustCreated());
// Invalidation won't change the "just created" status.
- client->SetDisplayItemsUncached();
+ client->Invalidate();
EXPECT_TRUE(client->IsJustCreated());
DisplayItem::Id id(*client, DisplayItem::kDrawingFirst);
@@ -74,7 +68,7 @@ TEST(PaintChunkTest, IdNotMatchesJustCreated) {
EXPECT_FALSE(PaintChunk(0, 1, id, properties)
.Matches(PaintChunk(0, 1, id, properties)));
- client->UpdateCacheGeneration();
+ client->Validate();
EXPECT_TRUE(PaintChunk(0, 1, id, properties)
.Matches(PaintChunk(0, 1, id, properties)));
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.cc
index d07e470b9cb..c6db1e55eb0 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.cc
@@ -4,8 +4,6 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_chunker.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-
namespace blink {
static const PropertyTreeState& UninitializedProperties() {
@@ -23,14 +21,13 @@ bool PaintChunker::IsInInitialState() const {
if (current_properties_ != UninitializedProperties())
return false;
- DCHECK(data_.chunks.IsEmpty());
+ DCHECK(chunks_.IsEmpty());
return true;
}
void PaintChunker::UpdateCurrentPaintChunkProperties(
const base::Optional<PaintChunk::Id>& chunk_id,
const PropertyTreeState& properties) {
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
// If properties are the same, continue to use the previously set
// |next_chunk_id_| because the id of the outer painting is likely to be
// more stable to reduce invalidation because of chunk id changes.
@@ -51,7 +48,6 @@ void PaintChunker::ForceNewChunk() {
}
bool PaintChunker::IncrementDisplayItemIndex(const DisplayItem& item) {
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
// Property nodes should never be null because they should either be set to
// properties created by a LayoutObject/FrameView, or be set to a non-null
// root node. If these DCHECKs are hit we are missing a call to update the
@@ -65,7 +61,7 @@ bool PaintChunker::IncrementDisplayItemIndex(const DisplayItem& item) {
force_new_chunk_ = true;
size_t new_chunk_begin_index;
- if (data_.chunks.IsEmpty()) {
+ if (chunks_.IsEmpty()) {
new_chunk_begin_index = 0;
} else {
auto& last_chunk = LastChunk();
@@ -81,11 +77,9 @@ bool PaintChunker::IncrementDisplayItemIndex(const DisplayItem& item) {
new_chunk_begin_index = last_chunk.end_index;
}
- auto cacheable =
- item.SkippedCache() ? PaintChunk::kUncacheable : PaintChunk::kCacheable;
- data_.chunks.emplace_back(new_chunk_begin_index, new_chunk_begin_index + 1,
- next_chunk_id_ ? *next_chunk_id_ : item.GetId(),
- current_properties_, cacheable);
+ chunks_.emplace_back(new_chunk_begin_index, new_chunk_begin_index + 1,
+ next_chunk_id_ ? *next_chunk_id_ : item.GetId(),
+ current_properties_);
next_chunk_id_ = base::nullopt;
// When forcing a new chunk, we still need to force new chunk for the next
@@ -96,27 +90,11 @@ bool PaintChunker::IncrementDisplayItemIndex(const DisplayItem& item) {
return true;
}
-void PaintChunker::TrackRasterInvalidation(const PaintChunk& chunk,
- const RasterInvalidationInfo& info) {
- size_t index = ChunkIndex(chunk);
- auto& trackings = data_.raster_invalidation_trackings;
- if (trackings.size() <= index)
- trackings.resize(index + 1);
- trackings[index].push_back(info);
-}
-
-void PaintChunker::Clear() {
- data_.Clear();
- next_chunk_id_ = base::nullopt;
- current_properties_ = UninitializedProperties();
-}
-
-PaintChunksAndRasterInvalidations PaintChunker::ReleaseData() {
+Vector<PaintChunk> PaintChunker::ReleasePaintChunks() {
next_chunk_id_ = base::nullopt;
current_properties_ = UninitializedProperties();
- data_.chunks.ShrinkToFit();
- data_.raster_invalidation_rects.ShrinkToFit();
- return std::move(data_);
+ chunks_.ShrinkToFit();
+ return std::move(chunks_);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.h
index 17fdb5b9d85..8a0f11ad98b 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_PAINT_CHUNKER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_PAINT_CHUNKER_H_
+#include "base/macros.h"
#include "base/optional.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
@@ -12,7 +13,6 @@
#include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -22,7 +22,6 @@ namespace blink {
// display list with identical properties.
class PLATFORM_EXPORT PaintChunker final {
DISALLOW_NEW();
- WTF_MAKE_NONCOPYABLE(PaintChunker);
public:
PaintChunker();
@@ -41,45 +40,32 @@ class PLATFORM_EXPORT PaintChunker final {
// Returns true if a new chunk is created.
bool IncrementDisplayItemIndex(const DisplayItem&);
- const Vector<PaintChunk>& PaintChunks() const { return data_.chunks; }
+ const Vector<PaintChunk>& PaintChunks() const { return chunks_; }
- PaintChunk& PaintChunkAt(size_t i) { return data_.chunks[i]; }
+ PaintChunk& PaintChunkAt(size_t i) { return chunks_[i]; }
size_t LastChunkIndex() const {
- return data_.chunks.IsEmpty() ? kNotFound : data_.chunks.size() - 1;
+ return chunks_.IsEmpty() ? kNotFound : chunks_.size() - 1;
}
- PaintChunk& LastChunk() { return data_.chunks.back(); }
+ PaintChunk& LastChunk() { return chunks_.back(); }
PaintChunk& FindChunkByDisplayItemIndex(size_t index) {
- auto* chunk = FindChunkInVectorByDisplayItemIndex(data_.chunks, index);
- DCHECK(chunk != data_.chunks.end());
+ auto* chunk = FindChunkInVectorByDisplayItemIndex(chunks_, index);
+ DCHECK(chunk != chunks_.end());
return *chunk;
}
- void AddRasterInvalidation(const PaintChunk& chunk, const FloatRect& rect) {
- size_t index = ChunkIndex(chunk);
- auto& rects = data_.raster_invalidation_rects;
- if (rects.size() <= index)
- rects.resize(index + 1);
- rects[index].push_back(rect);
- }
-
- void TrackRasterInvalidation(const PaintChunk&,
- const RasterInvalidationInfo&);
-
- void Clear();
-
// Releases the generated paint chunk list and raster invalidations and
// resets the state of this object.
- PaintChunksAndRasterInvalidations ReleaseData();
+ Vector<PaintChunk> ReleasePaintChunks();
private:
size_t ChunkIndex(const PaintChunk& chunk) const {
- size_t index = &chunk - &data_.chunks.front();
- DCHECK_LT(index, data_.chunks.size());
+ size_t index = &chunk - &chunks_.front();
+ DCHECK_LT(index, chunks_.size());
return index;
}
- PaintChunksAndRasterInvalidations data_;
+ Vector<PaintChunk> chunks_;
// The id specified by UpdateCurrentPaintChunkProperties(). If it is not
// nullopt, we will use it as the id of the next new chunk. Otherwise we will
@@ -95,6 +81,8 @@ class PLATFORM_EXPORT PaintChunker final {
// the item following a forced chunk. PaintController also forces new chunks
// before and after subsequences by calling ForceNewChunk().
bool force_new_chunk_;
+
+ DISALLOW_COPY_AND_ASSIGN(PaintChunker);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc
index 074f9f87d14..04f41a4c614 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_chunker_test.cc
@@ -7,7 +7,6 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/testing/paint_property_test_helpers.h"
-#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
using testing::ElementsAre;
@@ -15,11 +14,7 @@ namespace blink {
namespace {
-class PaintChunkerTest : public testing::Test,
- private ScopedSlimmingPaintV175ForTest {
- public:
- PaintChunkerTest() : ScopedSlimmingPaintV175ForTest(true) {}
-
+class PaintChunkerTest : public testing::Test {
protected:
class TestDisplayItemClient : public DisplayItemClient {
String DebugName() const final { return "Test"; }
@@ -55,8 +50,8 @@ TEST_F(PaintChunkerTest, Empty) {
PaintChunker chunker;
EXPECT_TRUE(chunker.PaintChunks().IsEmpty());
- auto chunks_data = chunker.ReleaseData();
- EXPECT_TRUE(chunks_data.chunks.IsEmpty());
+ auto chunks = chunker.ReleasePaintChunks();
+ EXPECT_TRUE(chunks.IsEmpty());
}
TEST_F(PaintChunkerTest, SingleNonEmptyRange) {
@@ -70,11 +65,10 @@ TEST_F(PaintChunkerTest, SingleNonEmptyRange) {
EXPECT_EQ(chunks.size(), 1u);
EXPECT_EQ(chunks[0], PaintChunk(0, 2, id, DefaultPaintChunkProperties()));
- auto chunks_data = chunker.ReleaseData();
+ auto chunks1 = chunker.ReleasePaintChunks();
EXPECT_TRUE(chunker.PaintChunks().IsEmpty());
- EXPECT_EQ(chunks_data.chunks.size(), 1u);
- EXPECT_EQ(chunks_data.chunks[0],
- PaintChunk(0, 2, id, DefaultPaintChunkProperties()));
+ EXPECT_EQ(chunks1.size(), 1u);
+ EXPECT_EQ(chunks1[0], PaintChunk(0, 2, id, DefaultPaintChunkProperties()));
}
TEST_F(PaintChunkerTest, SamePropertiesTwiceCombineIntoOneChunk) {
@@ -90,11 +84,10 @@ TEST_F(PaintChunkerTest, SamePropertiesTwiceCombineIntoOneChunk) {
EXPECT_EQ(chunks.size(), 1u);
EXPECT_EQ(chunks[0], PaintChunk(0, 3, id, DefaultPaintChunkProperties()));
- auto chunks_data = chunker.ReleaseData();
+ auto chunks1 = chunker.ReleasePaintChunks();
EXPECT_TRUE(chunker.PaintChunks().IsEmpty());
- EXPECT_EQ(chunks_data.chunks.size(), 1u);
- EXPECT_EQ(chunks_data.chunks[0],
- PaintChunk(0, 3, id, DefaultPaintChunkProperties()));
+ EXPECT_EQ(chunks1.size(), 1u);
+ EXPECT_EQ(chunks1[0], PaintChunk(0, 3, id, DefaultPaintChunkProperties()));
}
TEST_F(PaintChunkerTest, BuildMultipleChunksWithSinglePropertyChanging) {
@@ -105,7 +98,7 @@ TEST_F(PaintChunkerTest, BuildMultipleChunksWithSinglePropertyChanging) {
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
auto simple_transform_node = CreateTransform(
- nullptr, TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
+ t0(), TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
auto simple_transform = DefaultPaintChunkProperties();
simple_transform.SetTransform(simple_transform_node.get());
@@ -114,7 +107,7 @@ TEST_F(PaintChunkerTest, BuildMultipleChunksWithSinglePropertyChanging) {
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
auto another_transform_node = CreateTransform(
- nullptr, TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
+ t0(), TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
auto another_transform = DefaultPaintChunkProperties();
another_transform.SetTransform(another_transform_node.get());
PaintChunk::Id id3(client_, DisplayItemType(3));
@@ -135,7 +128,7 @@ TEST_F(PaintChunkerTest, BuildMultipleChunksWithDifferentPropertyChanges) {
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
auto simple_transform_node = CreateTransform(
- nullptr, TransformationMatrix(0, 0, 0, 0, 0, 0), FloatPoint3D(9, 8, 7));
+ t0(), TransformationMatrix(0, 0, 0, 0, 0, 0), FloatPoint3D(9, 8, 7));
auto simple_transform = DefaultPaintChunkProperties();
simple_transform.SetTransform(simple_transform_node.get());
PaintChunk::Id id2(client_, DisplayItemType(2));
@@ -143,8 +136,7 @@ TEST_F(PaintChunkerTest, BuildMultipleChunksWithDifferentPropertyChanges) {
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
- auto simple_effect_node =
- CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.5f);
+ auto simple_effect_node = CreateOpacityEffect(e0(), 0.5f);
auto simple_transform_and_effect = DefaultPaintChunkProperties();
simple_transform_and_effect.SetTransform(simple_transform_node.get());
simple_transform_and_effect.SetEffect(simple_effect_node.get());
@@ -154,11 +146,10 @@ TEST_F(PaintChunkerTest, BuildMultipleChunksWithDifferentPropertyChanges) {
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
auto new_transform_node = CreateTransform(
- nullptr, TransformationMatrix(1, 1, 0, 0, 0, 0), FloatPoint3D(9, 8, 7));
+ t0(), TransformationMatrix(1, 1, 0, 0, 0, 0), FloatPoint3D(9, 8, 7));
auto simple_transform_and_effect_with_updated_transform =
DefaultPaintChunkProperties();
- auto new_effect_node =
- CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.5f);
+ auto new_effect_node = CreateOpacityEffect(e0(), 0.5f);
simple_transform_and_effect_with_updated_transform.SetTransform(
new_transform_node.get());
simple_transform_and_effect_with_updated_transform.SetEffect(
@@ -205,7 +196,7 @@ TEST_F(PaintChunkerTest, BuildChunksFromNestedTransforms) {
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
auto simple_transform_node = CreateTransform(
- nullptr, TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
+ t0(), TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
auto simple_transform = DefaultPaintChunkProperties();
simple_transform.SetTransform(simple_transform_node.get());
PaintChunk::Id id2(client_, DisplayItemType(2));
@@ -234,14 +225,14 @@ TEST_F(PaintChunkerTest, ChangingPropertiesWithoutItems) {
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
auto first_transform_node = CreateTransform(
- nullptr, TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
+ t0(), TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
auto first_transform = DefaultPaintChunkProperties();
first_transform.SetTransform(first_transform_node.get());
PaintChunk::Id id2(client_, DisplayItemType(2));
chunker.UpdateCurrentPaintChunkProperties(base::nullopt, first_transform);
auto second_transform_node = CreateTransform(
- nullptr, TransformationMatrix(9, 8, 7, 6, 5, 4), FloatPoint3D(3, 2, 1));
+ t0(), TransformationMatrix(9, 8, 7, 6, 5, 4), FloatPoint3D(3, 2, 1));
auto second_transform = DefaultPaintChunkProperties();
second_transform.SetTransform(second_transform_node.get());
PaintChunk::Id id3(client_, DisplayItemType(3));
@@ -412,20 +403,21 @@ TEST_F(PaintChunkerTest, ChunkIdsSkippingCache) {
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
auto simple_transform_node = CreateTransform(
- nullptr, TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
+ t0(), TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
auto simple_transform = DefaultPaintChunkProperties();
simple_transform.SetTransform(simple_transform_node.get());
- PaintChunk::Id id2(client_, DisplayItemType(2));
+
+ TestDisplayItemClient uncacheable_client;
+ uncacheable_client.Invalidate(PaintInvalidationReason::kUncacheable);
+ PaintChunk::Id id2(uncacheable_client, DisplayItemType(2));
chunker.UpdateCurrentPaintChunkProperties(id2, simple_transform);
- TestChunkerDisplayItem uncacheable_item(client_);
- uncacheable_item.SetSkippedCache();
+ TestChunkerDisplayItem uncacheable_item(uncacheable_client);
chunker.IncrementDisplayItemIndex(uncacheable_item);
chunker.IncrementDisplayItemIndex(TestChunkerDisplayItem(client_));
TestDisplayItemRequiringSeparateChunk uncacheable_separate_chunk_item(
- client_);
- uncacheable_separate_chunk_item.SetSkippedCache();
+ uncacheable_client);
chunker.IncrementDisplayItemIndex(uncacheable_separate_chunk_item);
TestChunkerDisplayItem after_separate_chunk(client_, DisplayItemType(3));
@@ -439,14 +431,18 @@ TEST_F(PaintChunkerTest, ChunkIdsSkippingCache) {
const auto& chunks = chunker.PaintChunks();
EXPECT_EQ(chunks.size(), 5u);
EXPECT_EQ(chunks[0], PaintChunk(0, 2, id1, DefaultPaintChunkProperties()));
- EXPECT_EQ(chunks[1],
- PaintChunk(2, 4, id2, simple_transform, PaintChunk::kUncacheable));
+ EXPECT_TRUE(chunks[0].is_cacheable);
+ EXPECT_EQ(chunks[1], PaintChunk(2, 4, id2, simple_transform));
+ EXPECT_FALSE(chunks[1].is_cacheable);
EXPECT_EQ(chunks[2], PaintChunk(4, 5, uncacheable_separate_chunk_item.GetId(),
- simple_transform, PaintChunk::kUncacheable));
+ simple_transform));
+ EXPECT_FALSE(chunks[2].is_cacheable);
EXPECT_EQ(chunks[3],
PaintChunk(5, 6, after_separate_chunk.GetId(), simple_transform));
+ EXPECT_TRUE(chunks[3].is_cacheable);
EXPECT_EQ(chunks[4], PaintChunk(6, 7, after_restore.GetId(),
DefaultPaintChunkProperties()));
+ EXPECT_TRUE(chunks[4].is_cacheable);
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc
index 16706fcb86f..abaa96b51bb 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc
@@ -6,42 +6,27 @@
#include <memory>
#include "base/auto_reset.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/graphics/logging_canvas.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
namespace blink {
-void PaintController::SetTracksRasterInvalidations(bool value) {
- if (value) {
- raster_invalidation_tracking_info_ =
- std::make_unique<RasterInvalidationTrackingInfo>();
-
- // This is called just after a full document cycle update, so all clients in
- // current_paint_artifact_ should be still alive.
- DCHECK(new_display_item_list_.IsEmpty());
- for (const auto& item : current_paint_artifact_.GetDisplayItemList()) {
- raster_invalidation_tracking_info_->old_client_debug_names.Set(
- &item.Client(), item.Client().DebugName());
- }
- } else if (!RasterInvalidationTracking::ShouldAlwaysTrack()) {
- raster_invalidation_tracking_info_ = nullptr;
- }
-}
-
-void PaintController::EnsureRasterInvalidationTracking() {
- if (!raster_invalidation_tracking_info_) {
- raster_invalidation_tracking_info_ =
- std::make_unique<RasterInvalidationTrackingInfo>();
- }
+PaintController::PaintController(Usage usage)
+ : usage_(usage),
+ current_paint_artifact_(PaintArtifact::Empty()),
+ new_display_item_list_(0) {
+ // frame_first_paints_ should have one null frame since the beginning, so
+ // that PaintController is robust even if it paints outside of BeginFrame
+ // and EndFrame cycles. It will also enable us to combine the first paint
+ // data in this PaintController into another PaintController on which we
+ // replay the recorded results in the future.
+ frame_first_paints_.push_back(FrameFirstPaint(nullptr));
}
-const PaintArtifact& PaintController::GetPaintArtifact() const {
+PaintController::~PaintController() {
+ // New display items should be committed before PaintController is destroyed.
DCHECK(new_display_item_list_.IsEmpty());
- DCHECK(new_paint_chunks_.IsInInitialState());
- return current_paint_artifact_;
}
bool PaintController::UseCachedDrawingIfPossible(
@@ -49,6 +34,9 @@ bool PaintController::UseCachedDrawingIfPossible(
DisplayItem::Type type) {
DCHECK(DisplayItem::IsDrawingType(type));
+ if (usage_ == kTransient)
+ return false;
+
if (DisplayItemConstructionIsDisabled())
return false;
@@ -73,7 +61,7 @@ bool PaintController::UseCachedDrawingIfPossible(
EnsureNewDisplayItemListInitialCapacity();
// Visual rect can change without needing invalidation of the client, e.g.
// when ancestor clip changes. Update the visual rect to the current value.
- current_paint_artifact_.GetDisplayItemList()[cached_item].UpdateVisualRect();
+ current_paint_artifact_->GetDisplayItemList()[cached_item].UpdateVisualRect();
if (!RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled())
ProcessNewItem(MoveItemFromCurrentListToNewList(cached_item));
@@ -99,6 +87,9 @@ bool PaintController::UseCachedDrawingIfPossible(
bool PaintController::UseCachedSubsequenceIfPossible(
const DisplayItemClient& client) {
+ if (usage_ == kTransient)
+ return false;
+
if (DisplayItemConstructionIsDisabled() || SubsequenceCachingIsDisabled())
return false;
@@ -119,7 +110,7 @@ bool PaintController::UseCachedSubsequenceIfPossible(
return false;
}
- if (current_paint_artifact_.GetDisplayItemList()[markers->start]
+ if (current_paint_artifact_->GetDisplayItemList()[markers->start]
.IsTombstone()) {
// The subsequence has already been copied, indicating that the same client
// created multiple subsequences. If DCHECK_IS_ON(), then we should have
@@ -209,57 +200,6 @@ void PaintController::EndSubsequence(const DisplayItemClient& client,
<< "Multiple subsequences for client: " << client.DebugName();
new_cached_subsequences_.insert(&client, SubsequenceMarkers(start, end));
- last_cached_subsequence_end_ = end;
-}
-
-bool PaintController::LastDisplayItemIsNoopBegin() const {
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
-
- if (new_display_item_list_.IsEmpty())
- return false;
-
- const auto& last_display_item = new_display_item_list_.Last();
- return last_display_item.IsBegin() && !last_display_item.DrawsContent();
-}
-
-bool PaintController::LastDisplayItemIsSubsequenceEnd() const {
- return !new_cached_subsequences_.IsEmpty() &&
- last_cached_subsequence_end_ == new_display_item_list_.size();
-}
-
-void PaintController::RemoveLastDisplayItem() {
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
-
- if (new_display_item_list_.IsEmpty())
- return;
-
-#if DCHECK_IS_ON()
- // Also remove the index pointing to the removed display item.
- IndicesByClientMap::iterator it = new_display_item_indices_by_client_.find(
- &new_display_item_list_.Last().Client());
- if (it != new_display_item_indices_by_client_.end()) {
- Vector<size_t>& indices = it->value;
- if (!indices.IsEmpty() &&
- indices.back() == (new_display_item_list_.size() - 1))
- indices.pop_back();
- }
-#endif
-
- if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() &&
- IsCheckingUnderInvalidation()) {
- if (skipped_probable_under_invalidation_count_) {
- --skipped_probable_under_invalidation_count_;
- } else {
- DCHECK(under_invalidation_checking_begin_);
- --under_invalidation_checking_begin_;
- // The old display item is a tombstone because it was matched by the begin
- // display item being removed. Restore the tombstone so that we can match
- // the next new display item against it.
- current_paint_artifact_.GetDisplayItemList().RestoreTombstone(
- under_invalidation_checking_begin_, new_display_item_list_.Last());
- }
- }
- new_display_item_list_.RemoveLast();
}
const DisplayItem* PaintController::LastDisplayItem(unsigned offset) {
@@ -271,49 +211,31 @@ const DisplayItem* PaintController::LastDisplayItem(unsigned offset) {
void PaintController::ProcessNewItem(DisplayItem& display_item) {
DCHECK(!construction_disabled_);
- if (IsSkippingCache())
- display_item.SetSkippedCache();
-
- if (raster_invalidation_tracking_info_) {
- raster_invalidation_tracking_info_->new_client_debug_names.insert(
- &display_item.Client(), display_item.Client().DebugName());
+ if (IsSkippingCache()) {
+ DCHECK_EQ(usage_, kMultiplePaints);
+ display_item.Client().Invalidate(PaintInvalidationReason::kUncacheable);
}
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- size_t last_chunk_index = new_paint_chunks_.LastChunkIndex();
- bool chunk_added =
- new_paint_chunks_.IncrementDisplayItemIndex(display_item);
- auto& last_chunk = new_paint_chunks_.LastChunk();
-
#if DCHECK_IS_ON()
- if (chunk_added && last_chunk.is_cacheable) {
- AddToIndicesByClientMap(last_chunk.id.client,
- new_paint_chunks_.LastChunkIndex(),
- new_paint_chunk_indices_by_client_);
- }
+ bool chunk_added =
#endif
-
- if (chunk_added && last_chunk_index != kNotFound) {
- DCHECK(last_chunk_index != new_paint_chunks_.LastChunkIndex());
- GenerateRasterInvalidations(
- new_paint_chunks_.PaintChunkAt(last_chunk_index));
- }
-
- last_chunk.outset_for_raster_effects =
- std::max(last_chunk.outset_for_raster_effects,
- display_item.OutsetForRasterEffects());
- }
+ new_paint_chunks_.IncrementDisplayItemIndex(display_item);
+ auto& last_chunk = new_paint_chunks_.LastChunk();
#if DCHECK_IS_ON()
- // Verify noop begin/end pairs have been removed.
- if (new_display_item_list_.size() >= 2 && display_item.IsEnd()) {
- const auto& begin_display_item =
- new_display_item_list_[new_display_item_list_.size() - 2];
- if (begin_display_item.IsBegin() && !begin_display_item.DrawsContent())
- DCHECK(!display_item.IsEndAndPairedWith(begin_display_item.GetType()));
+ if (chunk_added && last_chunk.is_cacheable) {
+ AddToIndicesByClientMap(last_chunk.id.client,
+ new_paint_chunks_.LastChunkIndex(),
+ new_paint_chunk_indices_by_client_);
}
+#endif
- if (display_item.IsCacheable()) {
+ last_chunk.outset_for_raster_effects =
+ std::max(last_chunk.outset_for_raster_effects,
+ display_item.OutsetForRasterEffects());
+
+#if DCHECK_IS_ON()
+ if (usage_ == kMultiplePaints && !IsSkippingCache()) {
size_t index = FindMatchingItemFromIndex(
display_item.GetId(), new_display_item_indices_by_client_,
new_display_item_list_);
@@ -331,7 +253,8 @@ void PaintController::ProcessNewItem(DisplayItem& display_item) {
}
#endif // DCHECK_IS_ON()
- if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled())
+ if (usage_ == kMultiplePaints &&
+ RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled())
CheckUnderInvalidation();
if (!frame_first_paints_.back().first_painted && display_item.IsDrawing() &&
@@ -346,11 +269,8 @@ void PaintController::ProcessNewItem(DisplayItem& display_item) {
}
DisplayItem& PaintController::MoveItemFromCurrentListToNewList(size_t index) {
- items_moved_into_new_list_.resize(
- current_paint_artifact_.GetDisplayItemList().size());
- items_moved_into_new_list_[index] = new_display_item_list_.size();
return new_display_item_list_.AppendByMoving(
- current_paint_artifact_.GetDisplayItemList()[index]);
+ current_paint_artifact_->GetDisplayItemList()[index]);
}
void PaintController::InvalidateAll() {
@@ -362,15 +282,15 @@ void PaintController::InvalidateAllInternal() {
// TODO(wangxianzhu): Rename this to InvalidateAllForTesting() for SPv2.
// Can only be called during layout/paintInvalidation, not during painting.
DCHECK(new_display_item_list_.IsEmpty());
- current_paint_artifact_.Reset();
- current_cache_generation_.Invalidate();
+ current_paint_artifact_ = PaintArtifact::Empty();
+ current_cached_subsequences_.clear();
+ cache_is_all_invalid_ = true;
}
bool PaintController::CacheIsAllInvalid() const {
DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
- return current_paint_artifact_.IsEmpty() &&
- current_cache_generation_.GetPaintInvalidationReason() !=
- PaintInvalidationReason::kNone;
+ DCHECK(!cache_is_all_invalid_ || current_paint_artifact_->IsEmpty());
+ return cache_is_all_invalid_;
}
bool PaintController::ClientCacheIsValid(
@@ -378,9 +298,9 @@ bool PaintController::ClientCacheIsValid(
#if DCHECK_IS_ON()
DCHECK(client.IsAlive());
#endif
- if (IsSkippingCache())
+ if (IsSkippingCache() || cache_is_all_invalid_)
return false;
- return client.DisplayItemsAreCached(current_cache_generation_);
+ return client.IsValid();
}
size_t PaintController::FindMatchingItemFromIndex(
@@ -419,31 +339,27 @@ void PaintController::AddToIndicesByClientMap(const DisplayItemClient& client,
size_t PaintController::FindCachedItem(const DisplayItem::Id& id) {
DCHECK(ClientCacheIsValid(id.client));
- // Try to find the item sequentially first. This is fast if the current list
- // and the new list are in the same order around the new item. If found, we
- // don't need to update and lookup the index.
- for (size_t i = next_item_to_match_;
- i < current_paint_artifact_.GetDisplayItemList().size(); ++i) {
+ if (next_item_to_match_ <
+ current_paint_artifact_->GetDisplayItemList().size()) {
+ // If current_list[next_item_to_match_] matches the new item, we don't need
+ // to update and lookup the index, which is fast. This is the common case
+ // that the current list and the new list are in the same order around the
+ // new item.
+ const DisplayItem& item =
+ current_paint_artifact_->GetDisplayItemList()[next_item_to_match_];
// We encounter an item that has already been copied which indicates we
// can't do sequential matching.
- const DisplayItem& item = current_paint_artifact_.GetDisplayItemList()[i];
- if (item.IsTombstone())
- break;
- if (id == item.GetId()) {
+ if (!item.IsTombstone() && id == item.GetId()) {
#if DCHECK_IS_ON()
++num_sequential_matches_;
#endif
- return i;
+ return next_item_to_match_;
}
- // We encounter a different cacheable item which also indicates we can't do
- // sequential matching.
- if (item.IsCacheable())
- break;
}
size_t found_index =
FindMatchingItemFromIndex(id, out_of_order_item_indices_,
- current_paint_artifact_.GetDisplayItemList());
+ current_paint_artifact_->GetDisplayItemList());
if (found_index != kNotFound) {
#if DCHECK_IS_ON()
++num_out_of_order_matches_;
@@ -458,8 +374,8 @@ size_t PaintController::FindCachedItem(const DisplayItem::Id& id) {
size_t PaintController::FindOutOfOrderCachedItemForward(
const DisplayItem::Id& id) {
for (size_t i = next_item_to_index_;
- i < current_paint_artifact_.GetDisplayItemList().size(); ++i) {
- const DisplayItem& item = current_paint_artifact_.GetDisplayItemList()[i];
+ i < current_paint_artifact_->GetDisplayItemList().size(); ++i) {
+ const DisplayItem& item = current_paint_artifact_->GetDisplayItemList()[i];
if (item.IsTombstone())
continue;
if (id == item.GetId()) {
@@ -473,6 +389,7 @@ size_t PaintController::FindOutOfOrderCachedItemForward(
++num_indexed_items_;
#endif
AddToIndicesByClientMap(item.Client(), i, out_of_order_item_indices_);
+ next_item_to_index_ = i + 1;
}
}
@@ -501,40 +418,28 @@ void PaintController::CopyCachedSubsequence(size_t begin_index,
size_t end_index) {
DCHECK(!RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled());
- base::AutoReset<size_t> subsequence_begin_index(
- &current_cached_subsequence_begin_index_in_new_list_,
- new_display_item_list_.size());
- DisplayItem* cached_item =
- &current_paint_artifact_.GetDisplayItemList()[begin_index];
-
- Vector<PaintChunk>::const_iterator cached_chunk;
- base::Optional<PropertyTreeState> properties_before_subsequence;
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- cached_chunk =
- current_paint_artifact_.FindChunkByDisplayItemIndex(begin_index);
- DCHECK(cached_chunk != current_paint_artifact_.PaintChunks().end());
-
- properties_before_subsequence =
- new_paint_chunks_.CurrentPaintChunkProperties();
- UpdateCurrentPaintChunkPropertiesUsingIdWithFragment(
- cached_chunk->id, cached_chunk->properties.GetPropertyTreeState());
- } else {
- // Avoid uninitialized variable error on Windows.
- cached_chunk = current_paint_artifact_.PaintChunks().begin();
- }
+ const DisplayItem* cached_item =
+ &current_paint_artifact_->GetDisplayItemList()[begin_index];
+
+ auto* cached_chunk =
+ current_paint_artifact_->FindChunkByDisplayItemIndex(begin_index);
+ DCHECK(cached_chunk != current_paint_artifact_->PaintChunks().end());
+ auto properties_before_subsequence =
+ new_paint_chunks_.CurrentPaintChunkProperties();
+ UpdateCurrentPaintChunkPropertiesUsingIdWithFragment(
+ cached_chunk->id, cached_chunk->properties.GetPropertyTreeState());
for (size_t current_index = begin_index; current_index < end_index;
++current_index) {
- cached_item = &current_paint_artifact_.GetDisplayItemList()[current_index];
+ cached_item = &current_paint_artifact_->GetDisplayItemList()[current_index];
SECURITY_CHECK(!cached_item->IsTombstone());
#if DCHECK_IS_ON()
DCHECK(cached_item->Client().IsAlive());
#endif
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- current_index == cached_chunk->end_index) {
+ if (current_index == cached_chunk->end_index) {
++cached_chunk;
- DCHECK(cached_chunk != current_paint_artifact_.PaintChunks().end());
+ DCHECK(cached_chunk != current_paint_artifact_->PaintChunks().end());
new_paint_chunks_.ForceNewChunk();
UpdateCurrentPaintChunkPropertiesUsingIdWithFragment(
cached_chunk->id, cached_chunk->properties.GetPropertyTreeState());
@@ -554,39 +459,35 @@ void PaintController::CopyCachedSubsequence(size_t begin_index,
#endif
ProcessNewItem(MoveItemFromCurrentListToNewList(current_index));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- DCHECK((!new_paint_chunks_.LastChunk().is_cacheable &&
- !cached_chunk->is_cacheable) ||
- new_paint_chunks_.LastChunk().Matches(*cached_chunk));
- }
+ DCHECK((!new_paint_chunks_.LastChunk().is_cacheable &&
+ !cached_chunk->is_cacheable) ||
+ new_paint_chunks_.LastChunk().Matches(*cached_chunk));
}
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
under_invalidation_checking_end_ = end_index;
DCHECK(IsCheckingUnderInvalidation());
- } else if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
+ } else {
// Restore properties and force new chunk for any trailing display items
// after the cached subsequence without new properties.
new_paint_chunks_.ForceNewChunk();
UpdateCurrentPaintChunkProperties(base::nullopt,
- *properties_before_subsequence);
+ properties_before_subsequence);
}
}
void PaintController::ResetCurrentListIndices() {
next_item_to_match_ = 0;
next_item_to_index_ = 0;
- next_chunk_to_match_ = 0;
under_invalidation_checking_begin_ = 0;
under_invalidation_checking_end_ = 0;
- skipped_probable_under_invalidation_count_ = 0;
}
DISABLE_CFI_PERF
void PaintController::CommitNewDisplayItems() {
TRACE_EVENT2("blink,benchmark", "PaintController::commitNewDisplayItems",
"current_display_list_size",
- (int)current_paint_artifact_.GetDisplayItemList().size(),
+ (int)current_paint_artifact_->GetDisplayItemList().size(),
"num_non_cached_new_items",
(int)new_display_item_list_.size() - num_cached_new_items_);
@@ -596,64 +497,21 @@ void PaintController::CommitNewDisplayItems() {
new_paint_chunk_indices_by_client_.clear();
#endif
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
- !new_display_item_list_.IsEmpty())
- GenerateRasterInvalidations(new_paint_chunks_.LastChunk());
-
- auto old_cache_generation = current_cache_generation_;
- current_cache_generation_ =
- DisplayItemClient::CacheGenerationOrInvalidationReason::Next();
+ cache_is_all_invalid_ = false;
+ committed_ = true;
new_cached_subsequences_.swap(current_cached_subsequences_);
new_cached_subsequences_.clear();
- last_cached_subsequence_end_ = 0;
- for (auto& item : current_cached_subsequences_)
- item.key->SetDisplayItemsCached(current_cache_generation_);
-
- Vector<const DisplayItemClient*> skipped_cache_clients;
- for (const auto& item : new_display_item_list_) {
- const auto& client = item.Client();
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- client.ClearPartialInvalidationRect();
-
- if (item.IsCacheable()) {
- client.SetDisplayItemsCached(current_cache_generation_);
- } else {
- if (client.IsJustCreated())
- client.ClearIsJustCreated();
- if (item.SkippedCache())
- skipped_cache_clients.push_back(&item.Client());
- }
- }
-
- for (auto* client : skipped_cache_clients) {
- // Set client uncached only if it is cached by this PaintController. The
- // client may be still validly cached in another PaintController which
- // should not be affected by skipping cache in this PaintController.
- if (client->DisplayItemsAreCached(old_cache_generation) ||
- // The client was set cached because it just painted some cacheable
- // items in this PaintController. Need to set it uncached.
- client->DisplayItemsAreCached(current_cache_generation_))
- client->SetDisplayItemsUncached();
- }
// The new list will not be appended to again so we can release unused memory.
new_display_item_list_.ShrinkToFit();
- current_paint_artifact_ = PaintArtifact(std::move(new_display_item_list_),
- new_paint_chunks_.ReleaseData());
+ current_paint_artifact_ =
+ PaintArtifact::Create(std::move(new_display_item_list_),
+ new_paint_chunks_.ReleasePaintChunks());
ResetCurrentListIndices();
out_of_order_item_indices_.clear();
- out_of_order_chunk_indices_.clear();
- items_moved_into_new_list_.clear();
-
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- for (const auto& chunk : current_paint_artifact_.PaintChunks()) {
- if (chunk.id.client.IsJustCreated())
- chunk.id.client.ClearIsJustCreated();
- }
- }
// We'll allocate the initial buffer when we start the next paint.
new_display_item_list_ = DisplayItemList(0);
@@ -663,16 +521,41 @@ void PaintController::CommitNewDisplayItems() {
num_out_of_order_matches_ = 0;
num_indexed_items_ = 0;
#endif
+}
- if (raster_invalidation_tracking_info_) {
- raster_invalidation_tracking_info_->old_client_debug_names.clear();
- std::swap(raster_invalidation_tracking_info_->old_client_debug_names,
- raster_invalidation_tracking_info_->new_client_debug_names);
+void PaintController::FinishCycle() {
+ if (usage_ == kTransient)
+ return;
+
+ DCHECK(new_display_item_list_.IsEmpty());
+ DCHECK(new_paint_chunks_.IsInInitialState());
+
+ if (committed_) {
+ committed_ = false;
+
+ // Validate display item clients that have validly cached subsequence or
+ // display items in this PaintController.
+ for (auto& item : current_cached_subsequences_) {
+ if (item.key->IsCacheable())
+ item.key->Validate();
+ }
+ for (const auto& item : current_paint_artifact_->GetDisplayItemList()) {
+ const auto& client = item.Client();
+ client.ClearPartialInvalidationVisualRect();
+ if (client.IsCacheable())
+ client.Validate();
+ }
+ for (const auto& chunk : current_paint_artifact_->PaintChunks()) {
+ if (chunk.id.client.IsCacheable())
+ chunk.id.client.Validate();
+ }
}
+ current_paint_artifact_->FinishCycle();
+
#if DCHECK_IS_ON()
if (VLOG_IS_ON(2)) {
- LOG(ERROR) << "PaintController::CommitNewDisplayItems() done";
+ LOG(ERROR) << "PaintController::FinishCycle() done";
if (VLOG_IS_ON(3))
ShowDebugDataWithRecords();
else
@@ -681,30 +564,15 @@ void PaintController::CommitNewDisplayItems() {
#endif
}
-void PaintController::FinishCycle() {
- DCHECK(new_display_item_list_.IsEmpty());
- DCHECK(new_paint_chunks_.IsInInitialState());
-
- current_paint_artifact_.FinishCycle();
-}
-
size_t PaintController::ApproximateUnsharedMemoryUsage() const {
size_t memory_usage = sizeof(*this);
// Memory outside this class due to current_paint_artifact_.
- memory_usage += current_paint_artifact_.ApproximateUnsharedMemoryUsage() -
- sizeof(current_paint_artifact_);
+ memory_usage += current_paint_artifact_->ApproximateUnsharedMemoryUsage();
- // TODO(jbroman): If display items begin to have significant external memory
- // usage that's not shared with the embedder, we should account for it here.
- //
// External objects, shared with the embedder, such as PaintRecord, should be
// excluded to avoid double counting. It is the embedder's responsibility to
// count such objects.
- //
- // At time of writing, the only known case of unshared external memory was
- // the rounded clips vector in ClipDisplayItem, which is not expected to
- // contribute significantly to memory usage.
// Memory outside this class due to new_display_item_list_.
DCHECK(new_display_item_list_.IsEmpty());
@@ -721,314 +589,35 @@ size_t PaintController::ApproximateUnsharedMemoryUsage() const {
return memory_usage;
}
+namespace {
+
+class DebugDrawingClient final : public DisplayItemClient {
+ public:
+ DebugDrawingClient() { Invalidate(PaintInvalidationReason::kUncacheable); }
+ String DebugName() const final { return "DebugDrawing"; }
+ LayoutRect VisualRect() const final {
+ return LayoutRect(LayoutRect::InfiniteIntRect());
+ }
+};
+
+} // anonymous namespace
+
void PaintController::AppendDebugDrawingAfterCommit(
- const DisplayItemClient& display_item_client,
sk_sp<const PaintRecord> record,
- const PropertyTreeState* property_tree_state) {
+ const PropertyTreeState& property_tree_state) {
+ DEFINE_STATIC_LOCAL(DebugDrawingClient, debug_drawing_client, ());
+
DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
DCHECK(new_display_item_list_.IsEmpty());
- auto& display_item_list = current_paint_artifact_.GetDisplayItemList();
+ auto& display_item_list = current_paint_artifact_->GetDisplayItemList();
auto& display_item =
display_item_list.AllocateAndConstruct<DrawingDisplayItem>(
- display_item_client, DisplayItem::kDebugDrawing, std::move(record));
- display_item.SetSkippedCache();
-
- if (property_tree_state) {
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
- // Create a PaintChunk for the debug drawing.
- current_paint_artifact_.PaintChunks().emplace_back(
- display_item_list.size() - 1, display_item_list.size(),
- display_item.GetId(), *property_tree_state);
- }
-}
-
-void PaintController::GenerateRasterInvalidations(PaintChunk& new_chunk) {
- if (RuntimeEnabledFeatures::DisableRasterInvalidationEnabled())
- return;
-
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
- if (new_chunk.begin_index >=
- current_cached_subsequence_begin_index_in_new_list_)
- return;
-
- // Uncacheable chunks will be invalidated in ContentLayerClientImpl.
- if (!new_chunk.is_cacheable)
- return;
-
- // Try to match old chunk sequentially first.
- const auto& old_chunks = current_paint_artifact_.PaintChunks();
- while (next_chunk_to_match_ < old_chunks.size()) {
- const PaintChunk& old_chunk = old_chunks[next_chunk_to_match_];
- if (new_chunk.Matches(old_chunk)) {
- GenerateRasterInvalidationsComparingChunks(new_chunk, old_chunk);
- ++next_chunk_to_match_;
- return;
- }
-
- // Add skipped old chunks into the index.
- if (old_chunk.is_cacheable) {
- auto it = out_of_order_chunk_indices_.find(&old_chunk.id.client);
- Vector<size_t>& indices =
- it == out_of_order_chunk_indices_.end()
- ? out_of_order_chunk_indices_
- .insert(&old_chunk.id.client, Vector<size_t>())
- .stored_value->value
- : it->value;
- indices.push_back(next_chunk_to_match_);
- }
- ++next_chunk_to_match_;
- }
-
- // Sequential matching reaches the end. Find from the out-of-order index.
- auto it = out_of_order_chunk_indices_.find(&new_chunk.id.client);
- if (it != out_of_order_chunk_indices_.end()) {
- for (size_t i : it->value) {
- if (new_chunk.Matches(old_chunks[i])) {
- GenerateRasterInvalidationsComparingChunks(new_chunk, old_chunks[i]);
- return;
- }
- }
- }
-}
-
-void PaintController::AddRasterInvalidation(const DisplayItemClient& client,
- PaintChunk& chunk,
- const FloatRect& rect,
- PaintInvalidationReason reason) {
- new_paint_chunks_.AddRasterInvalidation(chunk, rect);
- if (RasterInvalidationTracking::ShouldAlwaysTrack())
- EnsureRasterInvalidationTracking();
- if (raster_invalidation_tracking_info_)
- TrackRasterInvalidation(client, chunk, reason);
-}
-
-void PaintController::TrackRasterInvalidation(const DisplayItemClient& client,
- PaintChunk& chunk,
- PaintInvalidationReason reason) {
- DCHECK(raster_invalidation_tracking_info_);
-
- RasterInvalidationInfo info;
- info.client = &client;
- if (reason == PaintInvalidationReason::kNone) {
- // The client was validated by another PaintController, but not valid in
- // this PaintController.
- DCHECK(!ClientCacheIsValid(client));
- info.reason = PaintInvalidationReason::kFull;
- } else {
- info.reason = reason;
- }
-
- if (reason == PaintInvalidationReason::kDisappeared) {
- info.client_debug_name =
- raster_invalidation_tracking_info_->old_client_debug_names.at(&client);
- } else {
- info.client_debug_name = client.DebugName();
- }
-
- new_paint_chunks_.TrackRasterInvalidation(chunk, info);
-}
-
-void PaintController::GenerateRasterInvalidationsComparingChunks(
- PaintChunk& new_chunk,
- const PaintChunk& old_chunk) {
- DCHECK(RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
-
- // TODO(wangxianzhu): Optimize paint offset change.
-
- struct OldAndNewDisplayItems {
- const DisplayItem* old_item = nullptr;
- const DisplayItem* new_item = nullptr;
- };
- HashMap<const DisplayItemClient*, OldAndNewDisplayItems>
- clients_to_invalidate;
-
- size_t highest_moved_to_index = 0;
- // Find clients to invalidate the old visual rects from the old chunk.
- for (size_t old_index = old_chunk.begin_index;
- old_index < old_chunk.end_index; ++old_index) {
- const DisplayItem& old_item =
- current_paint_artifact_.GetDisplayItemList()[old_index];
- const DisplayItemClient* client_to_invalidate_old_visual_rect = nullptr;
-
- if (old_item.IsTombstone()) {
- // old_item has been moved into new_display_item_list_ as a cached item.
- size_t moved_to_index = items_moved_into_new_list_[old_index];
- if (new_display_item_list_[moved_to_index].DrawsContent()) {
- if (moved_to_index < new_chunk.begin_index ||
- moved_to_index >= new_chunk.end_index) {
- // The item has been moved into another chunk, so need to invalidate
- // it in the chunk into which the item was moved.
- const auto& new_item = new_display_item_list_[moved_to_index];
- PaintChunk& moved_to_chunk =
- new_paint_chunks_.FindChunkByDisplayItemIndex(moved_to_index);
- AddRasterInvalidation(new_item.Client(), moved_to_chunk,
- new_item.VisualRect(),
- PaintInvalidationReason::kAppeared);
- // And invalidate the old visual rect in this chunk.
- client_to_invalidate_old_visual_rect = &new_item.Client();
- } else if (moved_to_index < highest_moved_to_index) {
- // The item has been moved behind other cached items, so need to
- // invalidate the area that is probably exposed by the item moved
- // earlier.
- client_to_invalidate_old_visual_rect =
- &new_display_item_list_[moved_to_index].Client();
- } else {
- highest_moved_to_index = moved_to_index;
- }
- }
- } else if (old_item.DrawsContent()) {
- // old_item has either changed or disappeared.
- client_to_invalidate_old_visual_rect = &old_item.Client();
- }
-
- if (client_to_invalidate_old_visual_rect) {
- clients_to_invalidate
- .insert(client_to_invalidate_old_visual_rect, OldAndNewDisplayItems())
- .stored_value->value.old_item = &old_item;
- }
- }
-
- // Find clients to invalidate the new visual rects from the new chunk.
- for (size_t new_index = new_chunk.begin_index;
- new_index < new_chunk.end_index; ++new_index) {
- const DisplayItem& new_item = new_display_item_list_[new_index];
- if (new_item.DrawsContent() && !ClientCacheIsValid(new_item.Client())) {
- clients_to_invalidate.insert(&new_item.Client(), OldAndNewDisplayItems())
- .stored_value->value.new_item = &new_item;
- }
- }
-
- for (const auto& item : clients_to_invalidate) {
- GenerateRasterInvalidation(*item.key, new_chunk, item.value.old_item,
- item.value.new_item);
- }
-}
-
-void PaintController::GenerateRasterInvalidation(
- const DisplayItemClient& client,
- PaintChunk& chunk,
- const DisplayItem* old_item,
- const DisplayItem* new_item) {
- if (!new_item || new_item->VisualRect().IsEmpty()) {
- if (old_item && !old_item->VisualRect().IsEmpty()) {
- AddRasterInvalidation(client, chunk, old_item->VisualRect(),
- PaintInvalidationReason::kDisappeared);
- }
- return;
- }
+ debug_drawing_client, DisplayItem::kDebugDrawing, std::move(record));
- DCHECK(&client == &new_item->Client());
- if (!old_item || old_item->VisualRect().IsEmpty()) {
- AddRasterInvalidation(client, chunk, new_item->VisualRect(),
- PaintInvalidationReason::kAppeared);
- return;
- }
-
- if (client.IsJustCreated()) {
- // The old client has been deleted and the new client happens to be at the
- // same address. They have no relationship.
- AddRasterInvalidation(client, chunk, old_item->VisualRect(),
- PaintInvalidationReason::kDisappeared);
- AddRasterInvalidation(client, chunk, new_item->VisualRect(),
- PaintInvalidationReason::kAppeared);
- return;
- }
-
- auto reason = client.GetPaintInvalidationReason();
- bool partial_raster_invalidation =
- RuntimeEnabledFeatures::PartialRasterInvalidationEnabled() &&
- (reason == PaintInvalidationReason::kRectangle ||
- reason == PaintInvalidationReason::kSelection);
- if ((!partial_raster_invalidation &&
- reason != PaintInvalidationReason::kIncremental) ||
- // Need full invalidation when visual rect location changed.
- old_item->VisualRect().Location() != new_item->VisualRect().Location()) {
- GenerateFullRasterInvalidation(chunk, *old_item, *new_item);
- return;
- }
-
- GenerateIncrementalRasterInvalidation(chunk, *old_item, *new_item);
-
- if (RuntimeEnabledFeatures::PartialRasterInvalidationEnabled()) {
- auto partial_rect = client.PartialInvalidationRect();
- if (!partial_rect.IsEmpty())
- AddRasterInvalidation(client, chunk, FloatRect(partial_rect), reason);
- }
-}
-
-static FloatRect ComputeRightDelta(const FloatPoint& location,
- const FloatSize& old_size,
- const FloatSize& new_size) {
- float delta = new_size.Width() - old_size.Width();
- if (delta > 0) {
- return FloatRect(location.X() + old_size.Width(), location.Y(), delta,
- new_size.Height());
- }
- if (delta < 0) {
- return FloatRect(location.X() + new_size.Width(), location.Y(), -delta,
- old_size.Height());
- }
- return FloatRect();
-}
-
-static FloatRect ComputeBottomDelta(const FloatPoint& location,
- const FloatSize& old_size,
- const FloatSize& new_size) {
- float delta = new_size.Height() - old_size.Height();
- if (delta > 0) {
- return FloatRect(location.X(), location.Y() + old_size.Height(),
- new_size.Width(), delta);
- }
- if (delta < 0) {
- return FloatRect(location.X(), location.Y() + new_size.Height(),
- old_size.Width(), -delta);
- }
- return FloatRect();
-}
-
-void PaintController::GenerateIncrementalRasterInvalidation(
- PaintChunk& chunk,
- const DisplayItem& old_item,
- const DisplayItem& new_item) {
- DCHECK(&old_item.Client() == &new_item.Client());
- FloatRect old_visual_rect(old_item.VisualRect());
- FloatRect new_visual_rect(new_item.VisualRect());
- DCHECK(old_visual_rect.Location() == new_visual_rect.Location());
-
- FloatRect right_delta =
- ComputeRightDelta(new_visual_rect.Location(), old_visual_rect.Size(),
- new_visual_rect.Size());
- if (!right_delta.IsEmpty()) {
- AddRasterInvalidation(new_item.Client(), chunk, right_delta,
- PaintInvalidationReason::kIncremental);
- }
-
- FloatRect bottom_delta =
- ComputeBottomDelta(new_visual_rect.Location(), old_visual_rect.Size(),
- new_visual_rect.Size());
- if (!bottom_delta.IsEmpty()) {
- AddRasterInvalidation(new_item.Client(), chunk, bottom_delta,
- PaintInvalidationReason::kIncremental);
- }
-}
-
-void PaintController::GenerateFullRasterInvalidation(
- PaintChunk& chunk,
- const DisplayItem& old_item,
- const DisplayItem& new_item) {
- DCHECK(&old_item.Client() == &new_item.Client());
- FloatRect old_visual_rect(old_item.VisualRect());
- FloatRect new_visual_rect(new_item.VisualRect());
-
- if (!new_visual_rect.Contains(old_visual_rect)) {
- AddRasterInvalidation(new_item.Client(), chunk, old_visual_rect,
- new_item.Client().GetPaintInvalidationReason());
- if (old_visual_rect.Contains(new_visual_rect))
- return;
- }
-
- AddRasterInvalidation(new_item.Client(), chunk, new_visual_rect,
- new_item.Client().GetPaintInvalidationReason());
+ // Create a PaintChunk for the debug drawing.
+ current_paint_artifact_->PaintChunks().emplace_back(
+ display_item_list.size() - 1, display_item_list.size(),
+ display_item.GetId(), property_tree_state);
}
void PaintController::ShowUnderInvalidationError(
@@ -1083,13 +672,13 @@ void PaintController::ShowSequenceUnderInvalidationError(
}
void PaintController::CheckUnderInvalidation() {
+ DCHECK_EQ(usage_, kMultiplePaints);
DCHECK(RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled());
if (!IsCheckingUnderInvalidation())
return;
- const DisplayItem& new_item = new_display_item_list_.Last();
- if (new_item.SkippedCache()) {
+ if (IsSkippingCache()) {
// We allow cache skipping and temporary under-invalidation in cached
// subsequences. See the usage of DisplayItemCacheSkipper in BoxPainter.
under_invalidation_checking_end_ = 0;
@@ -1099,43 +688,21 @@ void PaintController::CheckUnderInvalidation() {
return;
}
- size_t old_item_index = under_invalidation_checking_begin_ +
- skipped_probable_under_invalidation_count_;
+ const DisplayItem& new_item = new_display_item_list_.Last();
+ size_t old_item_index = under_invalidation_checking_begin_;
DisplayItem* old_item =
- old_item_index < current_paint_artifact_.GetDisplayItemList().size()
- ? &current_paint_artifact_.GetDisplayItemList()[old_item_index]
+ old_item_index < current_paint_artifact_->GetDisplayItemList().size()
+ ? &current_paint_artifact_->GetDisplayItemList()[old_item_index]
: nullptr;
- bool old_and_new_equal = (old_item && new_item.Equals(*old_item));
- if (!old_and_new_equal) {
- if (new_item.IsBegin()) {
- // Temporarily skip mismatching begin display item which may be removed
- // when we remove a no-op pair.
- ++skipped_probable_under_invalidation_count_;
- return;
- }
- if (new_item.IsDrawing() &&
- skipped_probable_under_invalidation_count_ == 1) {
- DCHECK_GE(new_display_item_list_.size(), 2u);
- if (new_display_item_list_[new_display_item_list_.size() - 2].GetType() ==
- DisplayItem::kBeginCompositing) {
- // This might be a drawing item between a pair of begin/end compositing
- // display items that will be folded into a single drawing display item.
- ++skipped_probable_under_invalidation_count_;
- return;
- }
- }
- }
-
- if (skipped_probable_under_invalidation_count_ || !old_and_new_equal) {
+ if (!old_item || !new_item.Equals(*old_item)) {
// If we ever skipped reporting any under-invalidations, report the earliest
// one.
ShowUnderInvalidationError(
"under-invalidation: display item changed",
- new_display_item_list_[new_display_item_list_.size() -
- skipped_probable_under_invalidation_count_ - 1],
+ new_display_item_list_.Last(),
&current_paint_artifact_
- .GetDisplayItemList()[under_invalidation_checking_begin_]);
+ ->GetDisplayItemList()[under_invalidation_checking_begin_]);
CHECK(false);
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
index e9a8e1d3e39..c64e6fbb576 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
@@ -8,6 +8,7 @@
#include <memory>
#include <utility>
+#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/geometry/layout_point.h"
@@ -17,8 +18,6 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_chunk.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_chunker.h"
-#include "third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h"
-#include "third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/alignment.h"
@@ -52,20 +51,26 @@ struct FrameFirstPaint {
// a final paint artifact when complete. This class includes logic for caching,
// cache invalidation, and merging.
class PLATFORM_EXPORT PaintController {
- WTF_MAKE_NONCOPYABLE(PaintController);
USING_FAST_MALLOC(PaintController);
public:
- static std::unique_ptr<PaintController> Create() {
- return base::WrapUnique(new PaintController());
- }
+ enum Usage {
+ // The PaintController will be used for multiple paint cycles. It caches
+ // display item and subsequence of the previous paint which can be used in
+ // subsequent paints.
+ kMultiplePaints,
+ // The PaintController will be used for one paint cycle only. It doesn't
+ // cache or invalidate cache.
+ kTransient,
+ };
- ~PaintController() {
- // New display items should be committed before PaintController is
- // destructed.
- DCHECK(new_display_item_list_.IsEmpty());
+ static std::unique_ptr<PaintController> Create(
+ Usage usage = kMultiplePaints) {
+ return base::WrapUnique(new PaintController(usage));
}
+ ~PaintController();
+
// For SPv1 only.
void InvalidateAll();
bool CacheIsAllInvalid() const;
@@ -73,7 +78,7 @@ class PLATFORM_EXPORT PaintController {
// These methods are called during painting.
// Provide a new set of paint chunk properties to apply to recorded display
- // items, for Slimming Paint v175+.
+ // items.
void UpdateCurrentPaintChunkProperties(
const base::Optional<PaintChunk::Id>& id,
const PropertyTreeState& properties) {
@@ -94,6 +99,8 @@ class PLATFORM_EXPORT PaintController {
return new_paint_chunks_.CurrentPaintChunkProperties();
}
+ PaintChunk& CurrentPaintChunk() { return new_paint_chunks_.LastChunk(); }
+
void ForceNewChunk(const DisplayItemClient& client, DisplayItem::Type type) {
new_paint_chunks_.ForceNewChunk();
new_paint_chunks_.UpdateCurrentPaintChunkProperties(
@@ -107,6 +114,9 @@ class PLATFORM_EXPORT PaintController {
static_assert(
sizeof(DisplayItemClass) <= kMaximumDisplayItemSize,
"DisplayItem subclass is larger than kMaximumDisplayItemSize.");
+ static_assert(kDisplayItemAlignment % WTF_ALIGN_OF(DisplayItemClass) == 0,
+ "DisplayItem subclass alignment is not a factor of "
+ "kDisplayItemAlignment.");
if (DisplayItemConstructionIsDisabled())
return;
@@ -119,23 +129,6 @@ class PLATFORM_EXPORT PaintController {
ProcessNewItem(display_item);
}
- // Creates and appends an ending display item to pair with a preceding
- // beginning item iff the display item actually draws content. For no-op
- // items, rather than creating an ending item, the begin item will
- // instead be removed, thereby maintaining brevity of the list. If display
- // item construction is disabled, no list mutations will be performed.
- template <typename DisplayItemClass, typename... Args>
- void EndItem(Args&&... args) {
- DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
-
- if (DisplayItemConstructionIsDisabled())
- return;
- if (LastDisplayItemIsNoopBegin())
- RemoveLastDisplayItem();
- else
- CreateAndAppend<DisplayItemClass>(std::forward<Args>(args)...);
- }
-
// Tries to find the cached drawing display item corresponding to the given
// parameters. If found, appends the cached display item to the new display
// list and returns true. Otherwise returns false.
@@ -151,23 +144,31 @@ class PLATFORM_EXPORT PaintController {
// BeginSubsequence().
void EndSubsequence(const DisplayItemClient&, size_t start);
- // True if the last display item is a begin that doesn't draw content.
- void RemoveLastDisplayItem();
const DisplayItem* LastDisplayItem(unsigned offset);
- void BeginSkippingCache() { ++skipping_cache_count_; }
+ void BeginSkippingCache() {
+ if (usage_ == kTransient)
+ return;
+ ++skipping_cache_count_;
+ }
void EndSkippingCache() {
+ if (usage_ == kTransient)
+ return;
DCHECK(skipping_cache_count_ > 0);
--skipping_cache_count_;
}
bool IsSkippingCache() const { return skipping_cache_count_; }
- // Must be called when a painting is finished.
+ // Must be called when a painting is finished. Updates the current paint
+ // artifact with the new paintings.
void CommitNewDisplayItems();
// Called when the caller finishes updating a full document life cycle.
// The PaintController will cleanup data that will no longer be used for the
// next cycle, and update status to be ready for the next cycle.
+ // It updates caching status of DisplayItemClients, so if there are
+ // DisplayItemClients painting on multiple PaintControllers, we should call
+ // there FinishCycle() at the same time to ensure consistent caching status.
void FinishCycle();
// Returns the approximate memory usage, excluding memory likely to be
@@ -176,7 +177,15 @@ class PLATFORM_EXPORT PaintController {
size_t ApproximateUnsharedMemoryUsage() const;
// Get the artifact generated after the last commit.
- const PaintArtifact& GetPaintArtifact() const;
+ const PaintArtifact& GetPaintArtifact() const {
+ DCHECK(new_display_item_list_.IsEmpty());
+ DCHECK(new_paint_chunks_.IsInInitialState());
+ DCHECK(current_paint_artifact_);
+ return *current_paint_artifact_;
+ }
+ scoped_refptr<const PaintArtifact> GetPaintArtifactShared() const {
+ return base::WrapRefCounted(&GetPaintArtifact());
+ }
const DisplayItemList& GetDisplayItemList() const {
return GetPaintArtifact().GetDisplayItemList();
}
@@ -184,13 +193,17 @@ class PLATFORM_EXPORT PaintController {
return GetPaintArtifact().PaintChunks();
}
- // For micro benchmarking of record time.
+ // For micro benchmarking of record time. If true, display item construction
+ // is disabled to isolate the costs of construction in performance metrics.
bool DisplayItemConstructionIsDisabled() const {
return construction_disabled_;
}
- void SetDisplayItemConstructionIsDisabled(const bool disable) {
+ void SetDisplayItemConstructionIsDisabled(bool disable) {
construction_disabled_ = disable;
}
+
+ // For micro benchmarking of record time. If true, subsequence caching is
+ // disabled to test the cost of display item caching.
bool SubsequenceCachingIsDisabled() const {
return subsequence_caching_disabled_;
}
@@ -206,19 +219,14 @@ class PLATFORM_EXPORT PaintController {
// the last CommitNewDisplayItems(). Use with care.
DisplayItemList& NewDisplayItemList() { return new_display_item_list_; }
- void AppendDebugDrawingAfterCommit(const DisplayItemClient&,
- sk_sp<const PaintRecord>,
- const PropertyTreeState*);
+ void AppendDebugDrawingAfterCommit(sk_sp<const PaintRecord>,
+ const PropertyTreeState&);
#if DCHECK_IS_ON()
void ShowDebugData() const;
void ShowDebugDataWithRecords() const;
#endif
- void SetTracksRasterInvalidations(bool);
-
- bool LastDisplayItemIsSubsequenceEnd() const;
-
void BeginFrame(const void* frame);
FrameFirstPaint EndFrame(const void* frame);
@@ -228,36 +236,12 @@ class PLATFORM_EXPORT PaintController {
unsigned CurrentFragment() const { return current_fragment_; }
void SetCurrentFragment(unsigned fragment) { current_fragment_ = fragment; }
- protected:
- PaintController()
- : new_display_item_list_(0),
- construction_disabled_(false),
- subsequence_caching_disabled_(false),
- skipping_cache_count_(0),
- num_cached_new_items_(0),
- current_cached_subsequence_begin_index_in_new_list_(kNotFound),
-#if DCHECK_IS_ON()
- num_sequential_matches_(0),
- num_out_of_order_matches_(0),
- num_indexed_items_(0),
-#endif
- under_invalidation_checking_begin_(0),
- under_invalidation_checking_end_(0),
- last_cached_subsequence_end_(0),
- current_fragment_(0) {
- ResetCurrentListIndices();
- // frame_first_paints_ should have one null frame since the beginning, so
- // that PaintController is robust even if it paints outside of BeginFrame
- // and EndFrame cycles. It will also enable us to combine the first paint
- // data in this PaintController into another PaintController on which we
- // replay the recorded results in the future.
- frame_first_paints_.push_back(FrameFirstPaint(nullptr));
- }
-
private:
friend class PaintControllerTestBase;
friend class PaintControllerPaintTestBase;
+ PaintController(Usage);
+
// True if all display items associated with the client are validly cached.
// However, the current algorithm allows the following situations even if
// ClientCacheIsValid() is true for a client during painting:
@@ -273,16 +257,14 @@ class PLATFORM_EXPORT PaintController {
void InvalidateAllForTesting() { InvalidateAllInternal(); }
void InvalidateAllInternal();
- bool LastDisplayItemIsNoopBegin() const;
-
void EnsureNewDisplayItemListInitialCapacity() {
if (new_display_item_list_.IsEmpty()) {
// TODO(wangxianzhu): Consider revisiting this heuristic.
- new_display_item_list_ =
- DisplayItemList(current_paint_artifact_.GetDisplayItemList().IsEmpty()
- ? kInitialDisplayItemListCapacityBytes
- : current_paint_artifact_.GetDisplayItemList()
- .UsedCapacityInBytes());
+ new_display_item_list_ = DisplayItemList(
+ current_paint_artifact_->GetDisplayItemList().IsEmpty()
+ ? kInitialDisplayItemListCapacityBytes
+ : current_paint_artifact_->GetDisplayItemList()
+ .UsedCapacityInBytes());
}
}
@@ -317,29 +299,6 @@ class PLATFORM_EXPORT PaintController {
// newly created, or is changed causing the previous indices to be invalid.
void ResetCurrentListIndices();
- void GenerateRasterInvalidations(PaintChunk& new_chunk);
- void GenerateRasterInvalidationsComparingChunks(PaintChunk& new_chunk,
- const PaintChunk& old_chunk);
- inline void GenerateRasterInvalidation(const DisplayItemClient&,
- PaintChunk&,
- const DisplayItem* old_item,
- const DisplayItem* new_item);
- inline void GenerateIncrementalRasterInvalidation(
- PaintChunk&,
- const DisplayItem& old_item,
- const DisplayItem& new_item);
- inline void GenerateFullRasterInvalidation(PaintChunk&,
- const DisplayItem& old_item,
- const DisplayItem& new_item);
- inline void AddRasterInvalidation(const DisplayItemClient&,
- PaintChunk&,
- const FloatRect&,
- PaintInvalidationReason);
- void EnsureRasterInvalidationTracking();
- void TrackRasterInvalidation(const DisplayItemClient&,
- PaintChunk&,
- PaintInvalidationReason);
-
// The following two methods are for checking under-invalidations
// (when RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled).
void ShowUnderInvalidationError(const char* reason,
@@ -374,34 +333,28 @@ class PLATFORM_EXPORT PaintController {
void ShowDebugDataInternal(DisplayItemList::JsonFlags) const;
#endif
- // The last complete paint artifact.
- // In SPv2, this includes paint chunks as well as display items.
- PaintArtifact current_paint_artifact_;
+ Usage usage_;
+
+ // The last paint artifact after CommitNewDisplayItems().
+ // It includes paint chunks as well as display items.
+ scoped_refptr<PaintArtifact> current_paint_artifact_;
// Data being used to build the next paint artifact.
DisplayItemList new_display_item_list_;
PaintChunker new_paint_chunks_;
- // Stores indices into new_display_item_list_ for display items that have been
- // moved from current_paint_artifact_.GetDisplayItemList(), indexed by the
- // positions of the display items before the move. The values are undefined
- // for display items that are not moved.
- Vector<size_t> items_moved_into_new_list_;
-
- // Allows display item construction to be disabled to isolate the costs of
- // construction in performance metrics.
- bool construction_disabled_;
+ bool construction_disabled_ = false;
+ bool subsequence_caching_disabled_ = false;
- // Allows subsequence caching to be disabled to test the cost of display item
- // caching.
- bool subsequence_caching_disabled_;
+ bool cache_is_all_invalid_ = true;
+ bool committed_ = false;
// A stack recording current frames' first paints.
Vector<FrameFirstPaint> frame_first_paints_;
- int skipping_cache_count_;
+ int skipping_cache_count_ = 0;
- int num_cached_new_items_;
+ int num_cached_new_items_ = 0;
// Stores indices to valid cacheable display items in
// current_paint_artifact_.GetDisplayItemList() that have not been matched by
@@ -415,28 +368,16 @@ class PLATFORM_EXPORT PaintController {
IndicesByClientMap out_of_order_item_indices_;
// The next item in the current list for sequential match.
- size_t next_item_to_match_;
+ size_t next_item_to_match_ = 0;
// The next item in the current list to be indexed for out-of-order cache
// requests.
- size_t next_item_to_index_;
-
- // Similar to out_of_order_item_indices_ but
- // - the indices are chunk indices in current_paint_artifacts_.PaintChunks();
- // - chunks are matched not only for requests of cached display items, but
- // also non-cached display items.
- IndicesByClientMap out_of_order_chunk_indices_;
-
- size_t current_cached_subsequence_begin_index_in_new_list_;
- size_t next_chunk_to_match_;
-
- DisplayItemClient::CacheGenerationOrInvalidationReason
- current_cache_generation_;
+ size_t next_item_to_index_ = 0;
#if DCHECK_IS_ON()
- int num_sequential_matches_;
- int num_out_of_order_matches_;
- int num_indexed_items_;
+ int num_sequential_matches_ = 0;
+ int num_out_of_order_matches_ = 0;
+ int num_indexed_items_ = 0;
// This is used to check duplicated ids during CreateAndAppend().
IndicesByClientMap new_display_item_indices_by_client_;
@@ -450,32 +391,22 @@ class PLATFORM_EXPORT PaintController {
// end of the cached drawing or subsequence in the current list. The functions
// return false to let the client do actual painting, and PaintController will
// check if the actual painting results are the same as the cached.
- size_t under_invalidation_checking_begin_;
- size_t under_invalidation_checking_end_;
+ size_t under_invalidation_checking_begin_ = 0;
+ size_t under_invalidation_checking_end_ = 0;
- // Number of probable under-invalidations that have been skipped temporarily
- // because the mismatching display items may be removed in the future because
- // of no-op pairs or compositing folding.
- int skipped_probable_under_invalidation_count_;
String under_invalidation_message_prefix_;
- struct RasterInvalidationTrackingInfo {
- using ClientDebugNamesMap = HashMap<const DisplayItemClient*, String>;
- ClientDebugNamesMap new_client_debug_names;
- ClientDebugNamesMap old_client_debug_names;
- };
- std::unique_ptr<RasterInvalidationTrackingInfo>
- raster_invalidation_tracking_info_;
-
using CachedSubsequenceMap =
HashMap<const DisplayItemClient*, SubsequenceMarkers>;
CachedSubsequenceMap current_cached_subsequences_;
CachedSubsequenceMap new_cached_subsequences_;
- size_t last_cached_subsequence_end_;
+ size_t last_cached_subsequence_end_ = 0;
- unsigned current_fragment_;
+ unsigned current_fragment_ = 0;
class DisplayItemListAsJSON;
+
+ DISALLOW_COPY_AND_ASSIGN(PaintController);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_debug_data.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_debug_data.cc
index 3a7daf0a4a2..8f70d35bb2e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_debug_data.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_debug_data.cc
@@ -77,10 +77,8 @@ PaintController::DisplayItemListAsJSON::SubsequenceAsJSONObjectRecursive() {
json_object->SetString("subsequence",
String::Format("client: %p ", subsequence.client) +
ClientName(*subsequence.client));
- json_object->SetArray(
- RuntimeEnabledFeatures::SlimmingPaintV175Enabled() ? "chunks"
- : "displayItems",
- SubsequenceAsJSONArrayRecursive(subsequence.start, subsequence.end));
+ json_object->SetArray("chunks", SubsequenceAsJSONArrayRecursive(
+ subsequence.start, subsequence.end));
return json_object;
}
@@ -115,15 +113,17 @@ void PaintController::DisplayItemListAsJSON::AppendSubsequenceAsJSON(
size_t end_item,
JSONArray& json_array) {
DCHECK(end_item > start_item);
-
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- list_.AppendSubsequenceAsJSON(start_item, end_item, flags_, json_array);
+ if (current_chunk_ == chunks_.end()) {
+ // We are in the middle of painting with incomplete chunks.
+ auto json_object = JSONObject::Create();
+ json_object->SetString("chunk", "incomplete");
+ json_object->SetArray(
+ "displayItems", list_.SubsequenceAsJSON(start_item, end_item, flags_));
+ json_array.PushObject(std::move(json_object));
return;
}
- DCHECK(current_chunk_ != chunks_.end());
DCHECK(current_chunk_->begin_index == start_item);
-
while (current_chunk_ != chunks_.end() &&
current_chunk_->end_index <= end_item) {
const auto& chunk = *current_chunk_;
@@ -154,9 +154,9 @@ void PaintController::ShowDebugDataInternal(
DisplayItemList::JsonFlags flags) const {
LOG(ERROR) << "current display item list: "
<< DisplayItemListAsJSON(
- current_paint_artifact_.GetDisplayItemList(),
+ current_paint_artifact_->GetDisplayItemList(),
current_cached_subsequences_,
- current_paint_artifact_.PaintChunks(), flags)
+ current_paint_artifact_->PaintChunks(), flags)
.ToString()
.Utf8()
.data();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc
index ca3bad069f9..be7dd5659c4 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc
@@ -6,10 +6,6 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_path_display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_path_recorder.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
-#include "third_party/blink/renderer/platform/graphics/paint/compositing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
@@ -19,9 +15,6 @@
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/testing/paint_test_configurations.h"
-using testing::ElementsAre;
-using testing::UnorderedElementsAre;
-
namespace blink {
// Tests using this class will be tested with under-invalidation-checking
@@ -34,11 +27,9 @@ INSTANTIATE_TEST_CASE_P(
All,
PaintControllerTest,
testing::Values(0,
- kSlimmingPaintV175,
kBlinkGenPropertyTrees,
kSlimmingPaintV2,
kUnderInvalidationChecking,
- kSlimmingPaintV175 | kUnderInvalidationChecking,
kBlinkGenPropertyTrees | kUnderInvalidationChecking,
kSlimmingPaintV2 | kUnderInvalidationChecking));
@@ -47,28 +38,13 @@ TEST_P(PaintControllerTest, NestedRecorders) {
FakeDisplayItemClient client("client", LayoutRect(100, 100, 200, 200));
InitRootChunk();
- {
- ClipRecorder clip_recorder(context, client, kClipType,
- IntRect(100, 100, 50, 50));
- DrawRect(context, client, kBackgroundType, FloatRect(100, 100, 200, 200));
- }
- GetPaintController().CommitNewDisplayItems();
+ DrawRect(context, client, kBackgroundType, FloatRect(100, 100, 200, 200));
+ CommitAndFinishCycle();
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 1,
- TestDisplayItem(client, kBackgroundType));
+ EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 1,
+ TestDisplayItem(client, kBackgroundType));
- EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
- // Raster invalidation for the whole chunk will be issued during
- // PaintArtifactCompositor::Update().
- EXPECT_FALSE(GetRasterInvalidationRects(0));
- } else {
- EXPECT_DISPLAY_LIST(
- GetPaintController().GetDisplayItemList(), 3,
- TestDisplayItem(client, kClipType),
- TestDisplayItem(client, kBackgroundType),
- TestDisplayItem(client, DisplayItem::ClipTypeToEndClipType(kClipType)));
- }
+ EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
}
TEST_P(PaintControllerTest, UpdateBasic) {
@@ -83,22 +59,16 @@ TEST_P(PaintControllerTest, UpdateBasic) {
EXPECT_EQ(0, NumCachedNewItems());
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 3,
TestDisplayItem(first, kBackgroundType),
TestDisplayItem(second, kBackgroundType),
TestDisplayItem(first, kForegroundType));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
- // Raster invalidation for the whole chunk will be issued during
- // PaintArtifactCompositor::Update().
- EXPECT_FALSE(GetRasterInvalidationRects(0));
-
- InitRootChunk();
- }
+ EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+ InitRootChunk();
DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 300, 300));
DrawRect(context, first, kForegroundType, FloatRect(100, 100, 300, 300));
@@ -109,18 +79,13 @@ TEST_P(PaintControllerTest, UpdateBasic) {
EXPECT_EQ(1, NumIndexedItems());
#endif
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
TestDisplayItem(first, kBackgroundType),
TestDisplayItem(first, kForegroundType));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
- EXPECT_THAT(*GetRasterInvalidationRects(0),
- // |second| disappeared from the chunk.
- UnorderedElementsAre(FloatRect(100, 100, 200, 200)));
- }
+ EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
}
TEST_P(PaintControllerTest, UpdateSwapOrder) {
@@ -136,7 +101,7 @@ TEST_P(PaintControllerTest, UpdateSwapOrder) {
DrawRect(context, second, kForegroundType, FloatRect(100, 100, 50, 200));
DrawRect(context, unaffected, kBackgroundType, FloatRect(300, 300, 10, 10));
DrawRect(context, unaffected, kForegroundType, FloatRect(300, 300, 10, 10));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 6,
TestDisplayItem(first, kBackgroundType),
@@ -161,7 +126,7 @@ TEST_P(PaintControllerTest, UpdateSwapOrder) {
EXPECT_EQ(2, NumIndexedItems()); // first
#endif
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 6,
TestDisplayItem(second, kBackgroundType),
@@ -171,12 +136,7 @@ TEST_P(PaintControllerTest, UpdateSwapOrder) {
TestDisplayItem(unaffected, kBackgroundType),
TestDisplayItem(unaffected, kForegroundType));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
- EXPECT_THAT(*GetRasterInvalidationRects(0),
- // Bounds of |second| (old and new are the same).
- UnorderedElementsAre(FloatRect(100, 100, 50, 200)));
- }
+ EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
}
TEST_P(PaintControllerTest, UpdateSwapOrderWithInvalidation) {
@@ -192,7 +152,7 @@ TEST_P(PaintControllerTest, UpdateSwapOrderWithInvalidation) {
DrawRect(context, second, kForegroundType, FloatRect(100, 100, 50, 200));
DrawRect(context, unaffected, kBackgroundType, FloatRect(300, 300, 10, 10));
DrawRect(context, unaffected, kForegroundType, FloatRect(300, 300, 10, 10));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 6,
TestDisplayItem(first, kBackgroundType),
@@ -203,7 +163,7 @@ TEST_P(PaintControllerTest, UpdateSwapOrderWithInvalidation) {
TestDisplayItem(unaffected, kForegroundType));
InitRootChunk();
- first.SetDisplayItemsUncached();
+ first.Invalidate();
DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 50, 200));
DrawRect(context, second, kForegroundType, FloatRect(100, 100, 50, 200));
DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 100, 100));
@@ -218,7 +178,7 @@ TEST_P(PaintControllerTest, UpdateSwapOrderWithInvalidation) {
EXPECT_EQ(2, NumIndexedItems());
#endif
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 6,
TestDisplayItem(second, kBackgroundType),
@@ -228,14 +188,7 @@ TEST_P(PaintControllerTest, UpdateSwapOrderWithInvalidation) {
TestDisplayItem(unaffected, kBackgroundType),
TestDisplayItem(unaffected, kForegroundType));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
- EXPECT_THAT(*GetRasterInvalidationRects(0),
- // Bounds of |first| (old and new are the same).
- UnorderedElementsAre(FloatRect(100, 100, 100, 100)));
- // No need to invalidate raster of |second|, because the client (|first|)
- // which swapped order with it has been invalidated.
- }
+ EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
}
TEST_P(PaintControllerTest, UpdateNewItemInMiddle) {
@@ -247,7 +200,7 @@ TEST_P(PaintControllerTest, UpdateNewItemInMiddle) {
DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 100, 100));
DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 50, 200));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
TestDisplayItem(first, kBackgroundType),
@@ -266,19 +219,14 @@ TEST_P(PaintControllerTest, UpdateNewItemInMiddle) {
EXPECT_EQ(0, NumIndexedItems());
#endif
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 3,
TestDisplayItem(first, kBackgroundType),
TestDisplayItem(third, kBackgroundType),
TestDisplayItem(second, kBackgroundType));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
- EXPECT_THAT(*GetRasterInvalidationRects(0),
- // |third| newly appeared in the chunk.
- UnorderedElementsAre(FloatRect(125, 100, 200, 50)));
- }
+ EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
}
TEST_P(PaintControllerTest, UpdateInvalidationWithPhases) {
@@ -294,7 +242,7 @@ TEST_P(PaintControllerTest, UpdateInvalidationWithPhases) {
DrawRect(context, first, kForegroundType, FloatRect(100, 100, 100, 100));
DrawRect(context, second, kForegroundType, FloatRect(100, 100, 50, 200));
DrawRect(context, third, kForegroundType, FloatRect(300, 100, 50, 50));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 6,
TestDisplayItem(first, kBackgroundType),
@@ -306,7 +254,7 @@ TEST_P(PaintControllerTest, UpdateInvalidationWithPhases) {
InitRootChunk();
- second.SetDisplayItemsUncached();
+ second.Invalidate();
DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 100, 100));
DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 50, 200));
DrawRect(context, third, kBackgroundType, FloatRect(300, 100, 50, 50));
@@ -321,7 +269,7 @@ TEST_P(PaintControllerTest, UpdateInvalidationWithPhases) {
EXPECT_EQ(2, NumIndexedItems());
#endif
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 6,
TestDisplayItem(first, kBackgroundType),
@@ -331,18 +279,10 @@ TEST_P(PaintControllerTest, UpdateInvalidationWithPhases) {
TestDisplayItem(second, kForegroundType),
TestDisplayItem(third, kForegroundType));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
- EXPECT_THAT(*GetRasterInvalidationRects(0),
- // Bounds of |second| (old and new are the same).
- UnorderedElementsAre(FloatRect(100, 100, 50, 200)));
- }
+ EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
}
TEST_P(PaintControllerTest, IncrementalRasterInvalidation) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
LayoutRect initial_rect(100, 100, 100, 100);
std::unique_ptr<FakeDisplayItemClient> clients[6];
for (auto& client : clients)
@@ -353,7 +293,7 @@ TEST_P(PaintControllerTest, IncrementalRasterInvalidation) {
for (auto& client : clients)
DrawRect(context, *client, kBackgroundType, FloatRect(initial_rect));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
InitRootChunk();
clients[0]->SetVisualRect(LayoutRect(100, 100, 150, 100));
@@ -363,26 +303,13 @@ TEST_P(PaintControllerTest, IncrementalRasterInvalidation) {
clients[4]->SetVisualRect(LayoutRect(100, 100, 150, 150));
clients[5]->SetVisualRect(LayoutRect(100, 100, 80, 80));
for (auto& client : clients) {
- client->SetDisplayItemsUncached(PaintInvalidationReason::kIncremental);
+ client->Invalidate(PaintInvalidationReason::kIncremental);
DrawRect(context, *client, kBackgroundType,
FloatRect(client->VisualRect()));
}
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
- EXPECT_THAT(*GetRasterInvalidationRects(0),
- UnorderedElementsAre(FloatRect(200, 100, 50, 100), // 0: right
- FloatRect(100, 200, 100, 50), // 1: bottom
- FloatRect(200, 100, 50, 80), // 2: right
- FloatRect(100, 180, 100, 20), // 2: bottom
- FloatRect(180, 100, 20, 100), // 3: right
- FloatRect(100, 200, 80, 50), // 3: bottom
- FloatRect(200, 100, 50, 150), // 4: right
- FloatRect(100, 200, 150, 50), // 4: bottom
- FloatRect(180, 100, 20, 100), // 5: right
- FloatRect(100, 180, 100, 20))); // 5: bottom
-
- InitRootChunk();
}
TEST_P(PaintControllerTest, UpdateAddFirstOverlap) {
@@ -393,7 +320,7 @@ TEST_P(PaintControllerTest, UpdateAddFirstOverlap) {
DrawRect(context, second, kBackgroundType, FloatRect(200, 200, 50, 50));
DrawRect(context, second, kForegroundType, FloatRect(200, 200, 50, 50));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
TestDisplayItem(second, kBackgroundType),
@@ -401,15 +328,15 @@ TEST_P(PaintControllerTest, UpdateAddFirstOverlap) {
InitRootChunk();
- first.SetDisplayItemsUncached();
- second.SetDisplayItemsUncached();
+ first.Invalidate();
+ second.Invalidate();
second.SetVisualRect(LayoutRect(150, 250, 100, 100));
DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 150, 150));
DrawRect(context, first, kForegroundType, FloatRect(100, 100, 150, 150));
DrawRect(context, second, kBackgroundType, FloatRect(150, 250, 100, 100));
DrawRect(context, second, kForegroundType, FloatRect(150, 250, 100, 100));
EXPECT_EQ(0, NumCachedNewItems());
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 4,
TestDisplayItem(first, kBackgroundType),
@@ -417,19 +344,9 @@ TEST_P(PaintControllerTest, UpdateAddFirstOverlap) {
TestDisplayItem(second, kBackgroundType),
TestDisplayItem(second, kForegroundType));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
- EXPECT_THAT(
- *GetRasterInvalidationRects(0),
- UnorderedElementsAre(
- // |first| newly appeared in the chunk.
- FloatRect(100, 100, 150, 150),
- // Old and new bounds of |second|.
- FloatRect(200, 200, 50, 50), FloatRect(150, 250, 100, 100)));
-
- InitRootChunk();
- }
+ EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+ InitRootChunk();
DrawRect(context, second, kBackgroundType, FloatRect(150, 250, 100, 100));
DrawRect(context, second, kForegroundType, FloatRect(150, 250, 100, 100));
@@ -440,18 +357,13 @@ TEST_P(PaintControllerTest, UpdateAddFirstOverlap) {
EXPECT_EQ(2, NumIndexedItems());
#endif
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
TestDisplayItem(second, kBackgroundType),
TestDisplayItem(second, kForegroundType));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
- EXPECT_THAT(*GetRasterInvalidationRects(0),
- // |first| disappeared from the chunk.
- UnorderedElementsAre(FloatRect(100, 100, 150, 150)));
- }
+ EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
}
TEST_P(PaintControllerTest, UpdateAddLastOverlap) {
@@ -462,7 +374,7 @@ TEST_P(PaintControllerTest, UpdateAddLastOverlap) {
DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 150, 150));
DrawRect(context, first, kForegroundType, FloatRect(100, 100, 150, 150));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
TestDisplayItem(first, kBackgroundType),
@@ -470,15 +382,15 @@ TEST_P(PaintControllerTest, UpdateAddLastOverlap) {
InitRootChunk();
- first.SetDisplayItemsUncached();
+ first.Invalidate();
first.SetVisualRect(LayoutRect(150, 150, 100, 100));
- second.SetDisplayItemsUncached();
+ second.Invalidate();
DrawRect(context, first, kBackgroundType, FloatRect(150, 150, 100, 100));
DrawRect(context, first, kForegroundType, FloatRect(150, 150, 100, 100));
DrawRect(context, second, kBackgroundType, FloatRect(200, 200, 50, 50));
DrawRect(context, second, kForegroundType, FloatRect(200, 200, 50, 50));
EXPECT_EQ(0, NumCachedNewItems());
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 4,
TestDisplayItem(first, kBackgroundType),
@@ -486,154 +398,33 @@ TEST_P(PaintControllerTest, UpdateAddLastOverlap) {
TestDisplayItem(second, kBackgroundType),
TestDisplayItem(second, kForegroundType));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
- EXPECT_THAT(*GetRasterInvalidationRects(0),
- UnorderedElementsAre(
- // The bigger of old and new bounds of |first|.
- FloatRect(100, 100, 150, 150),
- // |second| newly appeared in the chunk.
- FloatRect(200, 200, 50, 50)));
-
- InitRootChunk();
- }
+ EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
- first.SetDisplayItemsUncached();
+ InitRootChunk();
+ first.Invalidate();
first.SetVisualRect(LayoutRect(100, 100, 150, 150));
- second.SetDisplayItemsUncached();
+ second.Invalidate();
DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 150, 150));
DrawRect(context, first, kForegroundType, FloatRect(100, 100, 150, 150));
EXPECT_EQ(0, NumCachedNewItems());
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
TestDisplayItem(first, kBackgroundType),
TestDisplayItem(first, kForegroundType));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
- EXPECT_THAT(*GetRasterInvalidationRects(0),
- UnorderedElementsAre(
- // The bigger of old and new bounds of |first|.
- FloatRect(100, 100, 150, 150),
- // |second| disappeared from the chunk.
- FloatRect(200, 200, 50, 50)));
- }
-}
-
-TEST_P(PaintControllerTest, UpdateClip) {
- FakeDisplayItemClient first("first", LayoutRect(100, 100, 150, 150));
- FakeDisplayItemClient second("second", LayoutRect(100, 100, 200, 200));
- GraphicsContext context(GetPaintController());
-
- scoped_refptr<ClipPaintPropertyNode> clip =
- CreateClip(nullptr, nullptr, FloatRoundedRect(1, 1, 2, 2));
-
- {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- PaintChunk::Id id(first, kClipType);
- auto properties = DefaultPaintChunkProperties();
- properties.SetClip(clip.get());
- GetPaintController().UpdateCurrentPaintChunkProperties(id, properties);
- }
- ClipRecorder clip_recorder(context, first, kClipType, IntRect(1, 1, 2, 2));
- DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 150, 150));
- DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 200, 200));
- }
- GetPaintController().CommitNewDisplayItems();
-
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
- TestDisplayItem(first, kBackgroundType),
- TestDisplayItem(second, kBackgroundType));
-
- InitRootChunk();
- } else {
- EXPECT_DISPLAY_LIST(
- GetPaintController().GetDisplayItemList(), 4,
- TestDisplayItem(first, kClipType),
- TestDisplayItem(first, kBackgroundType),
- TestDisplayItem(second, kBackgroundType),
- TestDisplayItem(first, DisplayItem::ClipTypeToEndClipType(kClipType)));
- }
-
- first.SetDisplayItemsUncached();
- DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 150, 150));
- DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 200, 200));
-
- EXPECT_EQ(1, NumCachedNewItems());
-#if DCHECK_IS_ON()
- EXPECT_EQ(1, NumSequentialMatches());
- EXPECT_EQ(0, NumOutOfOrderMatches());
- EXPECT_EQ(1, NumIndexedItems());
-#endif
-
- GetPaintController().CommitNewDisplayItems();
-
- EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
- TestDisplayItem(first, kBackgroundType),
- TestDisplayItem(second, kBackgroundType));
-
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
- // This is a new chunk. Raster invalidation for the whole chunk will be
- // issued during PaintArtifactCompositor::Update().
- EXPECT_FALSE(GetRasterInvalidationRects(0));
-
- InitRootChunk();
- }
-
- second.SetDisplayItemsUncached();
- DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 150, 150));
-
- scoped_refptr<ClipPaintPropertyNode> clip2 =
- CreateClip(nullptr, nullptr, FloatRoundedRect(1, 1, 2, 2));
-
- {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- PaintChunk::Id id(second, kClipType);
- auto properties = DefaultPaintChunkProperties();
- properties.SetClip(clip2.get());
- GetPaintController().UpdateCurrentPaintChunkProperties(id, properties);
- }
- ClipRecorder clip_recorder(context, second, kClipType, IntRect(1, 1, 2, 2));
- DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 200, 200));
- }
- GetPaintController().CommitNewDisplayItems();
-
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
- TestDisplayItem(first, kBackgroundType),
- TestDisplayItem(second, kBackgroundType));
-
- EXPECT_EQ(2u, GetPaintController().PaintChunks().size());
- EXPECT_THAT(*GetRasterInvalidationRects(0),
- // |second| disappeared from the first chunk.
- UnorderedElementsAre(FloatRect(100, 100, 200, 200)));
- // This is a new chunk. Raster invalidation for the whole chunk will be
- // issued during PaintArtifactCompositor::Update().
- EXPECT_FALSE(GetRasterInvalidationRects(1));
- } else {
- EXPECT_DISPLAY_LIST(
- GetPaintController().GetDisplayItemList(), 4,
- TestDisplayItem(first, kBackgroundType),
- TestDisplayItem(second, kClipType),
- TestDisplayItem(second, kBackgroundType),
- TestDisplayItem(second, DisplayItem::ClipTypeToEndClipType(kClipType)));
- }
+ EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
}
TEST_P(PaintControllerTest, CachedDisplayItems) {
FakeDisplayItemClient first("first");
FakeDisplayItemClient second("second");
GraphicsContext context(GetPaintController());
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- InitRootChunk();
- }
+ InitRootChunk();
DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 150, 150));
DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 150, 150));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
TestDisplayItem(first, kBackgroundType),
@@ -649,16 +440,14 @@ TEST_P(PaintControllerTest, CachedDisplayItems) {
GetPaintController().GetDisplayItemList()[1])
.GetPaintRecord();
- first.SetDisplayItemsUncached();
+ first.Invalidate();
EXPECT_FALSE(ClientCacheIsValid(first));
EXPECT_TRUE(ClientCacheIsValid(second));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- InitRootChunk();
- }
+ InitRootChunk();
DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 150, 150));
DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 150, 150));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
TestDisplayItem(first, kBackgroundType),
@@ -701,7 +490,7 @@ TEST_P(PaintControllerTest, UpdateSwapOrderWithChildren) {
DrawRect(context, content2, kBackgroundType, FloatRect(100, 200, 50, 200));
DrawRect(context, content2, kForegroundType, FloatRect(100, 200, 50, 200));
DrawRect(context, container2, kForegroundType, FloatRect(100, 200, 100, 100));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 8,
TestDisplayItem(container1, kBackgroundType),
@@ -725,7 +514,7 @@ TEST_P(PaintControllerTest, UpdateSwapOrderWithChildren) {
DrawRect(context, content1, kBackgroundType, FloatRect(100, 100, 50, 200));
DrawRect(context, content1, kForegroundType, FloatRect(100, 100, 50, 200));
DrawRect(context, container1, kForegroundType, FloatRect(100, 100, 100, 100));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 8,
TestDisplayItem(container2, kBackgroundType),
@@ -737,16 +526,7 @@ TEST_P(PaintControllerTest, UpdateSwapOrderWithChildren) {
TestDisplayItem(content1, kForegroundType),
TestDisplayItem(container1, kForegroundType));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
- EXPECT_THAT(
- *GetRasterInvalidationRects(0),
- UnorderedElementsAre(
- // Bounds of |container2| which was moved behind |container1|.
- FloatRect(100, 200, 100, 100),
- // Bounds of |content2| which was moved along with |container2|.
- FloatRect(100, 200, 50, 200)));
- }
+ EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
}
TEST_P(PaintControllerTest, UpdateSwapOrderWithChildrenAndInvalidation) {
@@ -767,7 +547,7 @@ TEST_P(PaintControllerTest, UpdateSwapOrderWithChildrenAndInvalidation) {
DrawRect(context, content2, kBackgroundType, FloatRect(100, 200, 50, 200));
DrawRect(context, content2, kForegroundType, FloatRect(100, 200, 50, 200));
DrawRect(context, container2, kForegroundType, FloatRect(100, 200, 100, 100));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 8,
TestDisplayItem(container1, kBackgroundType),
@@ -783,7 +563,7 @@ TEST_P(PaintControllerTest, UpdateSwapOrderWithChildrenAndInvalidation) {
// Simulate the situation when |container1| gets a z-index that is greater
// than that of |container2|, and |container1| is invalidated.
- container1.SetDisplayItemsUncached();
+ container1.Invalidate();
DrawRect(context, container2, kBackgroundType, FloatRect(100, 200, 100, 100));
DrawRect(context, content2, kBackgroundType, FloatRect(100, 200, 50, 200));
DrawRect(context, content2, kForegroundType, FloatRect(100, 200, 50, 200));
@@ -792,7 +572,7 @@ TEST_P(PaintControllerTest, UpdateSwapOrderWithChildrenAndInvalidation) {
DrawRect(context, content1, kBackgroundType, FloatRect(100, 100, 50, 200));
DrawRect(context, content1, kForegroundType, FloatRect(100, 100, 50, 200));
DrawRect(context, container1, kForegroundType, FloatRect(100, 100, 100, 100));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 8,
TestDisplayItem(container2, kBackgroundType),
@@ -804,23 +584,11 @@ TEST_P(PaintControllerTest, UpdateSwapOrderWithChildrenAndInvalidation) {
TestDisplayItem(content1, kForegroundType),
TestDisplayItem(container1, kForegroundType));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
- EXPECT_THAT(
- *GetRasterInvalidationRects(0),
- UnorderedElementsAre(
- // Bounds of |container1| (old and new are the same).
- FloatRect(100, 100, 100, 100),
- // Bounds of |container2| which was moved behind |container1|.
- FloatRect(100, 200, 100, 100),
- // Bounds of |content2| which was moved along with |container2|.
- FloatRect(100, 200, 50, 200)));
- }
+ EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
}
TEST_P(PaintControllerTest, CachedSubsequenceForcePaintChunk) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() ||
- RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled())
+ if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled())
return;
GraphicsContext context(GetPaintController());
@@ -848,7 +616,7 @@ TEST_P(PaintControllerTest, CachedSubsequenceForcePaintChunk) {
DrawRect(context, root, kForegroundType, FloatRect(100, 100, 100, 100));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
// Even though the paint properties match, |container| should receive its
// own PaintChunk because it created a subsequence.
@@ -865,7 +633,7 @@ TEST_P(PaintControllerTest, CachedSubsequenceForcePaintChunk) {
DrawRect(context, root, kBackgroundType, FloatRect(100, 100, 100, 100));
EXPECT_TRUE(GetPaintController().UseCachedSubsequenceIfPossible(container));
DrawRect(context, root, kForegroundType, FloatRect(100, 100, 100, 100));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
// |container| should still receive its own PaintChunk because it is a cached
// subsequence.
@@ -887,21 +655,18 @@ TEST_P(PaintControllerTest, CachedSubsequenceSwapOrder) {
FakeDisplayItemClient content2("content2", LayoutRect(100, 200, 50, 200));
GraphicsContext context(GetPaintController());
- auto container1_effect =
- CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.5);
+ auto container1_effect = CreateOpacityEffect(e0(), 0.5);
auto container1_properties = DefaultPaintChunkProperties();
container1_properties.SetEffect(container1_effect.get());
- auto container2_effect =
- CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.5);
+ auto container2_effect = CreateOpacityEffect(e0(), 0.5);
auto container2_properties = DefaultPaintChunkProperties();
container2_properties.SetEffect(container2_effect.get());
{
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- GetPaintController().UpdateCurrentPaintChunkProperties(
- PaintChunk::Id(container1, kBackgroundType), container1_properties);
- }
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ PaintChunk::Id(container1, kBackgroundType), container1_properties);
+
SubsequenceRecorder r(context, container1);
DrawRect(context, container1, kBackgroundType,
FloatRect(100, 100, 100, 100));
@@ -911,10 +676,9 @@ TEST_P(PaintControllerTest, CachedSubsequenceSwapOrder) {
FloatRect(100, 100, 100, 100));
}
{
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- GetPaintController().UpdateCurrentPaintChunkProperties(
- PaintChunk::Id(container2, kBackgroundType), container2_properties);
- }
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ PaintChunk::Id(container2, kBackgroundType), container2_properties);
+
SubsequenceRecorder r(context, container2);
DrawRect(context, container2, kBackgroundType,
FloatRect(100, 200, 100, 100));
@@ -923,7 +687,7 @@ TEST_P(PaintControllerTest, CachedSubsequenceSwapOrder) {
DrawRect(context, container2, kForegroundType,
FloatRect(100, 200, 100, 100));
}
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 8,
TestDisplayItem(container1, kBackgroundType),
@@ -946,17 +710,11 @@ TEST_P(PaintControllerTest, CachedSubsequenceSwapOrder) {
EXPECT_EQ(4u, markers->start);
EXPECT_EQ(8u, markers->end);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(2u, GetPaintController().PaintChunks().size());
- EXPECT_EQ(PaintChunk::Id(container1, kBackgroundType),
- GetPaintController().PaintChunks()[0].id);
- EXPECT_EQ(PaintChunk::Id(container2, kBackgroundType),
- GetPaintController().PaintChunks()[1].id);
- // Raster invalidation for the whole chunks will be issued during
- // PaintArtifactCompositor::Update().
- EXPECT_FALSE(GetRasterInvalidationRects(0));
- EXPECT_FALSE(GetRasterInvalidationRects(1));
- }
+ EXPECT_EQ(2u, GetPaintController().PaintChunks().size());
+ EXPECT_EQ(PaintChunk::Id(container1, kBackgroundType),
+ GetPaintController().PaintChunks()[0].id);
+ EXPECT_EQ(PaintChunk::Id(container2, kBackgroundType),
+ GetPaintController().PaintChunks()[1].id);
// Simulate the situation when |container1| gets a z-index that is greater
// than that of |container2|.
@@ -967,11 +725,10 @@ TEST_P(PaintControllerTest, CachedSubsequenceSwapOrder) {
EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
context, container2));
{
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- PaintChunk::Id id(container2, kBackgroundType);
- GetPaintController().UpdateCurrentPaintChunkProperties(
- id, container2_properties);
- }
+ PaintChunk::Id id(container2, kBackgroundType);
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ id, container2_properties);
+
SubsequenceRecorder r(context, container2);
DrawRect(context, container2, kBackgroundType,
FloatRect(100, 200, 100, 100));
@@ -985,11 +742,10 @@ TEST_P(PaintControllerTest, CachedSubsequenceSwapOrder) {
EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
context, container1));
{
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- PaintChunk::Id id(container1, kBackgroundType);
- GetPaintController().UpdateCurrentPaintChunkProperties(
- id, container1_properties);
- }
+ PaintChunk::Id id(container1, kBackgroundType);
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ id, container1_properties);
+
SubsequenceRecorder r(context, container1);
DrawRect(context, container1, kBackgroundType,
FloatRect(100, 100, 100, 100));
@@ -1014,7 +770,7 @@ TEST_P(PaintControllerTest, CachedSubsequenceSwapOrder) {
EXPECT_EQ(0, NumIndexedItems());
#endif
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 8,
TestDisplayItem(container2, kBackgroundType),
@@ -1036,16 +792,11 @@ TEST_P(PaintControllerTest, CachedSubsequenceSwapOrder) {
EXPECT_EQ(4u, markers->start);
EXPECT_EQ(8u, markers->end);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(2u, GetPaintController().PaintChunks().size());
- EXPECT_EQ(PaintChunk::Id(container2, kBackgroundType),
- GetPaintController().PaintChunks()[0].id);
- EXPECT_EQ(PaintChunk::Id(container1, kBackgroundType),
- GetPaintController().PaintChunks()[1].id);
- // Swapping order of chunks should not invalidate anything.
- EXPECT_FALSE(GetRasterInvalidationRects(0));
- EXPECT_FALSE(GetRasterInvalidationRects(1));
- }
+ EXPECT_EQ(2u, GetPaintController().PaintChunks().size());
+ EXPECT_EQ(PaintChunk::Id(container2, kBackgroundType),
+ GetPaintController().PaintChunks()[0].id);
+ EXPECT_EQ(PaintChunk::Id(container1, kBackgroundType),
+ GetPaintController().PaintChunks()[1].id);
}
TEST_P(PaintControllerTest, CachedSubsequenceAndDisplayItemsSwapOrder) {
@@ -1069,7 +820,7 @@ TEST_P(PaintControllerTest, CachedSubsequenceAndDisplayItemsSwapOrder) {
FloatRect(100, 200, 100, 100));
}
DrawRect(context, content1, kForegroundType, FloatRect(100, 100, 50, 200));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 6,
TestDisplayItem(content1, kBackgroundType),
@@ -1122,7 +873,7 @@ TEST_P(PaintControllerTest, CachedSubsequenceAndDisplayItemsSwapOrder) {
EXPECT_EQ(0, NumIndexedItems());
#endif
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 6,
TestDisplayItem(container2, kBackgroundType),
@@ -1139,9 +890,6 @@ TEST_P(PaintControllerTest, CachedSubsequenceAndDisplayItemsSwapOrder) {
}
TEST_P(PaintControllerTest, CachedSubsequenceContainingFragments) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
GraphicsContext context(GetPaintController());
FakeDisplayItemClient root("root");
constexpr size_t kFragmentCount = 3;
@@ -1167,7 +915,7 @@ TEST_P(PaintControllerTest, CachedSubsequenceContainingFragments) {
paint_container();
DrawRect(context, root, kForegroundType, FloatRect(100, 100, 100, 100));
}
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
auto check_paint_results = [this, &root, &container]() {
const auto& chunks = GetPaintController().PaintChunks();
@@ -1202,7 +950,7 @@ TEST_P(PaintControllerTest, CachedSubsequenceContainingFragments) {
}
DrawRect(context, root, kForegroundType, FloatRect(100, 100, 100, 100));
}
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
// The second paint should produce the exactly same results.
check_paint_results();
@@ -1217,35 +965,23 @@ TEST_P(PaintControllerTest, UpdateSwapOrderCrossingChunks) {
FakeDisplayItemClient content2("content2", LayoutRect(100, 200, 50, 200));
GraphicsContext context(GetPaintController());
- auto container1_effect =
- CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.5);
+ auto container1_effect = CreateOpacityEffect(e0(), 0.5);
auto container1_properties = DefaultPaintChunkProperties();
container1_properties.SetEffect(container1_effect.get());
- auto container2_effect =
- CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.5);
+ auto container2_effect = CreateOpacityEffect(e0(), 0.5);
auto container2_properties = DefaultPaintChunkProperties();
container2_properties.SetEffect(container2_effect.get());
- {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- GetPaintController().UpdateCurrentPaintChunkProperties(
- PaintChunk::Id(container1, kBackgroundType), container1_properties);
- }
- DrawRect(context, container1, kBackgroundType,
- FloatRect(100, 100, 100, 100));
- DrawRect(context, content1, kBackgroundType, FloatRect(100, 100, 50, 200));
- }
- {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- GetPaintController().UpdateCurrentPaintChunkProperties(
- PaintChunk::Id(container2, kBackgroundType), container2_properties);
- }
- DrawRect(context, container2, kBackgroundType,
- FloatRect(100, 200, 100, 100));
- DrawRect(context, content2, kBackgroundType, FloatRect(100, 200, 50, 200));
- }
- GetPaintController().CommitNewDisplayItems();
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ PaintChunk::Id(container1, kBackgroundType), container1_properties);
+ DrawRect(context, container1, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, content1, kBackgroundType, FloatRect(100, 100, 50, 200));
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ PaintChunk::Id(container2, kBackgroundType), container2_properties);
+ DrawRect(context, container2, kBackgroundType, FloatRect(100, 200, 100, 100));
+ DrawRect(context, content2, kBackgroundType, FloatRect(100, 200, 50, 200));
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 4,
TestDisplayItem(container1, kBackgroundType),
@@ -1253,30 +989,20 @@ TEST_P(PaintControllerTest, UpdateSwapOrderCrossingChunks) {
TestDisplayItem(container2, kBackgroundType),
TestDisplayItem(content2, kBackgroundType));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(2u, GetPaintController().PaintChunks().size());
- EXPECT_EQ(PaintChunk::Id(container1, kBackgroundType),
- GetPaintController().PaintChunks()[0].id);
- EXPECT_EQ(PaintChunk::Id(container2, kBackgroundType),
- GetPaintController().PaintChunks()[1].id);
- // Raster invalidation for the whole chunks will be issued during
- // PaintArtifactCompositor::Update().
- EXPECT_FALSE(GetRasterInvalidationRects(0));
- EXPECT_FALSE(GetRasterInvalidationRects(1));
- }
+ EXPECT_EQ(2u, GetPaintController().PaintChunks().size());
+ EXPECT_EQ(PaintChunk::Id(container1, kBackgroundType),
+ GetPaintController().PaintChunks()[0].id);
+ EXPECT_EQ(PaintChunk::Id(container2, kBackgroundType),
+ GetPaintController().PaintChunks()[1].id);
// Move content2 into container1, without invalidation.
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- GetPaintController().UpdateCurrentPaintChunkProperties(
- PaintChunk::Id(container1, kBackgroundType), container1_properties);
- }
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ PaintChunk::Id(container1, kBackgroundType), container1_properties);
DrawRect(context, container1, kBackgroundType, FloatRect(100, 100, 100, 100));
DrawRect(context, content1, kBackgroundType, FloatRect(100, 100, 50, 200));
DrawRect(context, content2, kBackgroundType, FloatRect(100, 200, 50, 200));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- GetPaintController().UpdateCurrentPaintChunkProperties(
- PaintChunk::Id(container2, kBackgroundType), container2_properties);
- }
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ PaintChunk::Id(container2, kBackgroundType), container2_properties);
DrawRect(context, container2, kBackgroundType, FloatRect(100, 200, 100, 100));
EXPECT_EQ(4, NumCachedNewItems());
@@ -1286,7 +1012,7 @@ TEST_P(PaintControllerTest, UpdateSwapOrderCrossingChunks) {
EXPECT_EQ(1, NumIndexedItems());
#endif
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 4,
TestDisplayItem(container1, kBackgroundType),
@@ -1294,18 +1020,11 @@ TEST_P(PaintControllerTest, UpdateSwapOrderCrossingChunks) {
TestDisplayItem(content2, kBackgroundType),
TestDisplayItem(container2, kBackgroundType));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(2u, GetPaintController().PaintChunks().size());
- EXPECT_EQ(PaintChunk::Id(container1, kBackgroundType),
- GetPaintController().PaintChunks()[0].id);
- EXPECT_EQ(PaintChunk::Id(container2, kBackgroundType),
- GetPaintController().PaintChunks()[1].id);
- // |content2| is invalidated raster on both the old chunk and the new chunk.
- EXPECT_THAT(*GetRasterInvalidationRects(0),
- UnorderedElementsAre(FloatRect(100, 200, 50, 200)));
- EXPECT_THAT(*GetRasterInvalidationRects(1),
- UnorderedElementsAre(FloatRect(100, 200, 50, 200)));
- }
+ EXPECT_EQ(2u, GetPaintController().PaintChunks().size());
+ EXPECT_EQ(PaintChunk::Id(container1, kBackgroundType),
+ GetPaintController().PaintChunks()[0].id);
+ EXPECT_EQ(PaintChunk::Id(container2, kBackgroundType),
+ GetPaintController().PaintChunks()[1].id);
}
TEST_P(PaintControllerTest, OutOfOrderNoCrash) {
@@ -1326,7 +1045,7 @@ TEST_P(PaintControllerTest, OutOfOrderNoCrash) {
DrawRect(context, client, kType3, FloatRect(100, 100, 50, 200));
DrawRect(context, client, kType4, FloatRect(100, 100, 100, 100));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
InitRootChunk();
DrawRect(context, client, kType2, FloatRect(100, 100, 50, 200));
@@ -1334,7 +1053,7 @@ TEST_P(PaintControllerTest, OutOfOrderNoCrash) {
DrawRect(context, client, kType1, FloatRect(100, 100, 100, 100));
DrawRect(context, client, kType4, FloatRect(100, 100, 100, 100));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
}
TEST_P(PaintControllerTest, CachedNestedSubsequenceUpdate) {
@@ -1346,77 +1065,63 @@ TEST_P(PaintControllerTest, CachedNestedSubsequenceUpdate) {
FakeDisplayItemClient content2("content2", LayoutRect(100, 200, 50, 200));
GraphicsContext context(GetPaintController());
- auto container1_effect =
- CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.5);
+ auto container1_effect = CreateOpacityEffect(e0(), 0.5);
auto container1_background_properties = DefaultPaintChunkProperties();
container1_background_properties.SetEffect(container1_effect.get());
auto container1_foreground_properties = DefaultPaintChunkProperties();
container1_foreground_properties.SetEffect(container1_effect.get());
- auto content1_effect =
- CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.6);
+ auto content1_effect = CreateOpacityEffect(e0(), 0.6);
auto content1_properties = DefaultPaintChunkProperties();
content1_properties.SetEffect(content1_effect.get());
- auto container2_effect =
- CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.7);
+ auto container2_effect = CreateOpacityEffect(e0(), 0.7);
auto container2_background_properties = DefaultPaintChunkProperties();
container2_background_properties.SetEffect(container2_effect.get());
- auto content2_effect =
- CreateOpacityEffect(EffectPaintPropertyNode::Root(), 0.8);
+ auto content2_effect = CreateOpacityEffect(e0(), 0.8);
auto content2_properties = DefaultPaintChunkProperties();
content2_properties.SetEffect(content2_effect.get());
{
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- GetPaintController().UpdateCurrentPaintChunkProperties(
- PaintChunk::Id(container1, kBackgroundType),
- container1_background_properties);
- }
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ PaintChunk::Id(container1, kBackgroundType),
+ container1_background_properties);
SubsequenceRecorder r(context, container1);
DrawRect(context, container1, kBackgroundType,
FloatRect(100, 100, 100, 100));
{
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- GetPaintController().UpdateCurrentPaintChunkProperties(
- PaintChunk::Id(content1, kBackgroundType), content1_properties);
- }
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ PaintChunk::Id(content1, kBackgroundType), content1_properties);
SubsequenceRecorder r(context, content1);
DrawRect(context, content1, kBackgroundType,
FloatRect(100, 100, 50, 200));
DrawRect(context, content1, kForegroundType,
FloatRect(100, 100, 50, 200));
}
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- GetPaintController().UpdateCurrentPaintChunkProperties(
- PaintChunk::Id(container1, kForegroundType),
- container1_foreground_properties);
- }
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ PaintChunk::Id(container1, kForegroundType),
+ container1_foreground_properties);
DrawRect(context, container1, kForegroundType,
FloatRect(100, 100, 100, 100));
}
{
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- GetPaintController().UpdateCurrentPaintChunkProperties(
- PaintChunk::Id(container2, kBackgroundType),
- container2_background_properties);
- }
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ PaintChunk::Id(container2, kBackgroundType),
+ container2_background_properties);
SubsequenceRecorder r(context, container2);
DrawRect(context, container2, kBackgroundType,
FloatRect(100, 200, 100, 100));
{
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- GetPaintController().UpdateCurrentPaintChunkProperties(
- PaintChunk::Id(content2, kBackgroundType), content2_properties);
- }
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ PaintChunk::Id(content2, kBackgroundType), content2_properties);
SubsequenceRecorder r(context, content2);
DrawRect(context, content2, kBackgroundType,
FloatRect(100, 200, 50, 200));
}
}
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 6,
TestDisplayItem(container1, kBackgroundType),
@@ -1446,45 +1151,34 @@ TEST_P(PaintControllerTest, CachedNestedSubsequenceUpdate) {
EXPECT_EQ(5u, markers->start);
EXPECT_EQ(6u, markers->end);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(5u, GetPaintController().PaintChunks().size());
- EXPECT_EQ(PaintChunk::Id(container1, kBackgroundType),
- GetPaintController().PaintChunks()[0].id);
- EXPECT_EQ(PaintChunk::Id(content1, kBackgroundType),
- GetPaintController().PaintChunks()[1].id);
- EXPECT_EQ(PaintChunk::Id(container1, kForegroundType),
- GetPaintController().PaintChunks()[2].id);
- EXPECT_EQ(PaintChunk::Id(container2, kBackgroundType),
- GetPaintController().PaintChunks()[3].id);
- EXPECT_EQ(PaintChunk::Id(content2, kBackgroundType),
- GetPaintController().PaintChunks()[4].id);
- // Raster invalidation for the whole chunks will be issued during
- // PaintArtifactCompositor::Update().
- EXPECT_FALSE(GetRasterInvalidationRects(0));
- EXPECT_FALSE(GetRasterInvalidationRects(1));
- EXPECT_FALSE(GetRasterInvalidationRects(2));
- EXPECT_FALSE(GetRasterInvalidationRects(3));
- EXPECT_FALSE(GetRasterInvalidationRects(4));
- }
+ EXPECT_EQ(5u, GetPaintController().PaintChunks().size());
+ EXPECT_EQ(PaintChunk::Id(container1, kBackgroundType),
+ GetPaintController().PaintChunks()[0].id);
+ EXPECT_EQ(PaintChunk::Id(content1, kBackgroundType),
+ GetPaintController().PaintChunks()[1].id);
+ EXPECT_EQ(PaintChunk::Id(container1, kForegroundType),
+ GetPaintController().PaintChunks()[2].id);
+ EXPECT_EQ(PaintChunk::Id(container2, kBackgroundType),
+ GetPaintController().PaintChunks()[3].id);
+ EXPECT_EQ(PaintChunk::Id(content2, kBackgroundType),
+ GetPaintController().PaintChunks()[4].id);
// Invalidate container1 but not content1.
- container1.SetDisplayItemsUncached();
+ container1.Invalidate();
// Container2 itself now becomes empty (but still has the 'content2' child),
// and chooses not to output subsequence info.
- container2.SetDisplayItemsUncached();
- content2.SetDisplayItemsUncached();
+ container2.Invalidate();
+ content2.Invalidate();
EXPECT_FALSE(
SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, container2));
EXPECT_FALSE(
SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, content2));
// Content2 now outputs foreground only.
{
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- GetPaintController().UpdateCurrentPaintChunkProperties(
- PaintChunk::Id(content2, kForegroundType), content2_properties);
- }
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ PaintChunk::Id(content2, kForegroundType), content2_properties);
SubsequenceRecorder r(context, content2);
DrawRect(context, content2, kForegroundType, FloatRect(100, 200, 50, 200));
}
@@ -1500,10 +1194,8 @@ TEST_P(PaintControllerTest, CachedNestedSubsequenceUpdate) {
// expected to create the same painting as in the previous paint.
EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
context, content1));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
GetPaintController().UpdateCurrentPaintChunkProperties(
PaintChunk::Id(content1, kBackgroundType), content1_properties);
- }
SubsequenceRecorder r(context, content1);
DrawRect(context, content1, kBackgroundType,
FloatRect(100, 100, 50, 200));
@@ -1513,11 +1205,9 @@ TEST_P(PaintControllerTest, CachedNestedSubsequenceUpdate) {
EXPECT_TRUE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
context, content1));
}
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- GetPaintController().UpdateCurrentPaintChunkProperties(
- PaintChunk::Id(container1, kForegroundType),
- container1_foreground_properties);
- }
+ GetPaintController().UpdateCurrentPaintChunkProperties(
+ PaintChunk::Id(container1, kForegroundType),
+ container1_foreground_properties);
DrawRect(context, container1, kForegroundType,
FloatRect(100, 100, 100, 100));
}
@@ -1529,7 +1219,7 @@ TEST_P(PaintControllerTest, CachedNestedSubsequenceUpdate) {
EXPECT_EQ(0, NumIndexedItems());
#endif
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 4,
TestDisplayItem(content2, kForegroundType),
@@ -1552,23 +1242,13 @@ TEST_P(PaintControllerTest, CachedNestedSubsequenceUpdate) {
EXPECT_EQ(1u, markers->start);
EXPECT_EQ(3u, markers->end);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(3u, GetPaintController().PaintChunks().size());
- EXPECT_EQ(PaintChunk::Id(content2, kForegroundType),
- GetPaintController().PaintChunks()[0].id);
- EXPECT_EQ(PaintChunk::Id(content1, kBackgroundType),
- GetPaintController().PaintChunks()[1].id);
- EXPECT_EQ(PaintChunk::Id(container1, kForegroundType),
- GetPaintController().PaintChunks()[2].id);
- // This is a new chunk. Raster invalidation of the whole chunk will be
- // issued during PaintArtifactCompositor::Update().
- EXPECT_TRUE(GetRasterInvalidationRects(0)->IsEmpty());
- // This chunk didn't change.
- EXPECT_TRUE(GetRasterInvalidationRects(1)->IsEmpty());
- // |container1| is invalidated.
- EXPECT_THAT(*GetRasterInvalidationRects(2),
- UnorderedElementsAre(FloatRect(100, 100, 100, 100)));
- }
+ EXPECT_EQ(3u, GetPaintController().PaintChunks().size());
+ EXPECT_EQ(PaintChunk::Id(content2, kForegroundType),
+ GetPaintController().PaintChunks()[0].id);
+ EXPECT_EQ(PaintChunk::Id(content1, kBackgroundType),
+ GetPaintController().PaintChunks()[1].id);
+ EXPECT_EQ(PaintChunk::Id(container1, kForegroundType),
+ GetPaintController().PaintChunks()[2].id);
}
TEST_P(PaintControllerTest, SkipCache) {
@@ -1588,7 +1268,7 @@ TEST_P(PaintControllerTest, SkipCache) {
DrawRect(context, content, kForegroundType, rect2);
GetPaintController().EndSkippingCache();
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 3,
TestDisplayItem(multicol, kBackgroundType),
@@ -1604,15 +1284,9 @@ TEST_P(PaintControllerTest, SkipCache) {
.GetPaintRecord();
EXPECT_NE(record1, record2);
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
- // Raster invalidation for the whole chunk will be issued during
- // PaintArtifactCompositor::Update().
- EXPECT_FALSE(GetRasterInvalidationRects(0));
-
- InitRootChunk();
- }
+ EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+ InitRootChunk();
// Draw again with nothing invalidated.
EXPECT_TRUE(ClientCacheIsValid(multicol));
DrawRect(context, multicol, kBackgroundType, FloatRect(100, 200, 100, 100));
@@ -1629,7 +1303,7 @@ TEST_P(PaintControllerTest, SkipCache) {
EXPECT_EQ(0, NumIndexedItems());
#endif
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 3,
TestDisplayItem(multicol, kBackgroundType),
@@ -1642,17 +1316,11 @@ TEST_P(PaintControllerTest, SkipCache) {
GetPaintController().GetDisplayItemList()[2])
.GetPaintRecord());
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
- EXPECT_THAT(*GetRasterInvalidationRects(0),
- // Bounds of |content| (old and new are the same);
- UnorderedElementsAre(FloatRect(100, 100, 100, 100)));
-
- InitRootChunk();
- }
+ EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+ InitRootChunk();
// Now the multicol becomes 3 columns and repaints.
- multicol.SetDisplayItemsUncached();
+ multicol.Invalidate();
DrawRect(context, multicol, kBackgroundType, FloatRect(100, 100, 100, 100));
GetPaintController().BeginSkippingCache();
@@ -1674,17 +1342,9 @@ TEST_P(PaintControllerTest, SkipCache) {
GetPaintController().NewDisplayItemList()[2])
.GetPaintRecord());
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
- EXPECT_THAT(*GetRasterInvalidationRects(0),
- UnorderedElementsAre(
- // Bounds of |multicol| (old and new are the same);
- FloatRect(100, 100, 200, 200),
- // Bounds of |content| (old and new are the same);
- FloatRect(100, 100, 100, 100)));
- }
+ EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
}
TEST_P(PaintControllerTest, PartialSkipCache) {
@@ -1702,7 +1362,7 @@ TEST_P(PaintControllerTest, PartialSkipCache) {
GetPaintController().EndSkippingCache();
DrawRect(context, content, kForegroundType, rect3);
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 3,
TestDisplayItem(content, kBackgroundType),
@@ -1724,7 +1384,7 @@ TEST_P(PaintControllerTest, PartialSkipCache) {
// Content's cache is invalid because it has display items skipped cache.
EXPECT_FALSE(ClientCacheIsValid(content));
- EXPECT_EQ(PaintInvalidationReason::kFull,
+ EXPECT_EQ(PaintInvalidationReason::kUncacheable,
content.GetPaintInvalidationReason());
InitRootChunk();
@@ -1742,7 +1402,7 @@ TEST_P(PaintControllerTest, PartialSkipCache) {
EXPECT_EQ(0, NumIndexedItems());
#endif
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 3,
TestDisplayItem(content, kBackgroundType),
@@ -1759,70 +1419,15 @@ TEST_P(PaintControllerTest, PartialSkipCache) {
.GetPaintRecord());
}
-TEST_P(PaintControllerTest, OptimizeNoopPairs) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- FakeDisplayItemClient first("first");
- FakeDisplayItemClient second("second");
- FakeDisplayItemClient third("third");
-
- GraphicsContext context(GetPaintController());
- DrawRect(context, first, kBackgroundType, FloatRect(0, 0, 100, 100));
- {
- ClipPathRecorder clip_recorder(context, second, Path());
- DrawRect(context, second, kBackgroundType, FloatRect(0, 0, 100, 100));
- }
- DrawRect(context, third, kBackgroundType, FloatRect(0, 0, 100, 100));
-
- GetPaintController().CommitNewDisplayItems();
- EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 5,
- TestDisplayItem(first, kBackgroundType),
- TestDisplayItem(second, DisplayItem::kBeginClipPath),
- TestDisplayItem(second, kBackgroundType),
- TestDisplayItem(second, DisplayItem::kEndClipPath),
- TestDisplayItem(third, kBackgroundType));
-
- DrawRect(context, first, kBackgroundType, FloatRect(0, 0, 100, 100));
- {
- ClipRecorder clip_recorder(context, second, kClipType, IntRect(1, 1, 2, 2));
- // Do not draw anything for second.
- }
- DrawRect(context, third, kBackgroundType, FloatRect(0, 0, 100, 100));
- GetPaintController().CommitNewDisplayItems();
-
- // Empty clips should have been optimized out.
- EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
- TestDisplayItem(first, kBackgroundType),
- TestDisplayItem(third, kBackgroundType));
-
- second.SetDisplayItemsUncached();
- DrawRect(context, first, kBackgroundType, FloatRect(0, 0, 100, 100));
- {
- ClipRecorder clip_recorder(context, second, kClipType, IntRect(1, 1, 2, 2));
- {
- ClipPathRecorder clip_path_recorder(context, second, Path());
- // Do not draw anything for second.
- }
- }
- DrawRect(context, third, kBackgroundType, FloatRect(0, 0, 100, 100));
- GetPaintController().CommitNewDisplayItems();
-
- // Empty clips should have been optimized out.
- EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
- TestDisplayItem(first, kBackgroundType),
- TestDisplayItem(third, kBackgroundType));
-}
TEST_P(PaintControllerTest, SmallPaintControllerHasOnePaintChunk) {
- ScopedSlimmingPaintV2ForTest enable_s_pv2(true);
FakeDisplayItemClient client("test client");
InitRootChunk();
GraphicsContext context(GetPaintController());
DrawRect(context, client, kBackgroundType, FloatRect(0, 0, 100, 100));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
const auto& paint_chunks = GetPaintController().PaintChunks();
ASSERT_EQ(1u, paint_chunks.size());
EXPECT_EQ(0u, paint_chunks[0].begin_index);
@@ -1893,81 +1498,18 @@ TEST_P(PaintControllerTest, BeginAndEndFrame) {
EXPECT_FALSE(result.image_painted);
}
-TEST_P(PaintControllerTest, PartialInvalidation) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- FakeDisplayItemClient client("client", LayoutRect(100, 100, 300, 300));
- GraphicsContext context(GetPaintController());
-
- // Test partial rect invalidation in a new chunk.
- InitRootChunk();
- client.SetPartialInvalidationRect(LayoutRect(200, 200, 100, 100));
- DrawRect(context, client, kBackgroundType, FloatRect(100, 100, 300, 300));
- GetPaintController().CommitNewDisplayItems();
- ASSERT_EQ(1u, GetPaintController().PaintChunks().size());
- // Raster invalidation for the whole new chunk will be issued during
- // PaintArtifactCompositor::Update().
- EXPECT_FALSE(GetRasterInvalidationRects(0));
- EXPECT_EQ(LayoutRect(), client.PartialInvalidationRect());
-
- // Test partial rect invalidation without other invalidations.
- InitRootChunk();
- client.SetPartialInvalidationRect(LayoutRect(150, 160, 170, 180));
- DrawRect(context, client, kBackgroundType, FloatRect(100, 100, 300, 300));
- GetPaintController().CommitNewDisplayItems();
- ASSERT_EQ(1u, GetPaintController().PaintChunks().size());
- EXPECT_THAT(*GetRasterInvalidationRects(0),
- // Partial invalidation.
- UnorderedElementsAre(
- RuntimeEnabledFeatures::PartialRasterInvalidationEnabled()
- ? FloatRect(150, 160, 170, 180)
- : FloatRect(100, 100, 300, 300)));
- EXPECT_EQ(LayoutRect(), client.PartialInvalidationRect());
-
- // Test partial rect invalidation with full invalidation.
- InitRootChunk();
- client.SetPartialInvalidationRect(LayoutRect(150, 160, 170, 180));
- client.SetDisplayItemsUncached();
- DrawRect(context, client, kBackgroundType, FloatRect(100, 100, 300, 300));
- GetPaintController().CommitNewDisplayItems();
- ASSERT_EQ(1u, GetPaintController().PaintChunks().size());
- EXPECT_THAT(*GetRasterInvalidationRects(0),
- // Partial invalidation is shadowed by full invalidation.
- UnorderedElementsAre(FloatRect(100, 100, 300, 300)));
- EXPECT_EQ(LayoutRect(), client.PartialInvalidationRect());
-
- // Test partial rect invalidation with incremental invalidation.
- InitRootChunk();
- client.SetPartialInvalidationRect(LayoutRect(150, 160, 170, 180));
- client.SetVisualRect(LayoutRect(100, 100, 300, 400));
- DrawRect(context, client, kBackgroundType, FloatRect(100, 100, 300, 400));
- GetPaintController().CommitNewDisplayItems();
- ASSERT_EQ(1u, GetPaintController().PaintChunks().size());
- if (RuntimeEnabledFeatures::PartialRasterInvalidationEnabled()) {
- EXPECT_THAT(*GetRasterInvalidationRects(0),
- // Both partial invalidation and incremental invalidation.
- UnorderedElementsAre(FloatRect(100, 400, 300, 100),
- FloatRect(150, 160, 170, 180)));
- } else {
- EXPECT_THAT(*GetRasterInvalidationRects(0),
- UnorderedElementsAre(FloatRect(100, 100, 300, 400)));
- }
- EXPECT_EQ(LayoutRect(), client.PartialInvalidationRect());
-}
-
TEST_P(PaintControllerTest, InvalidateAll) {
if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled())
return;
EXPECT_TRUE(GetPaintController().CacheIsAllInvalid());
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_TRUE(GetPaintController().GetPaintArtifact().IsEmpty());
EXPECT_FALSE(GetPaintController().CacheIsAllInvalid());
InvalidateAll();
EXPECT_TRUE(GetPaintController().CacheIsAllInvalid());
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_TRUE(GetPaintController().GetPaintArtifact().IsEmpty());
EXPECT_FALSE(GetPaintController().CacheIsAllInvalid());
@@ -1976,7 +1518,7 @@ TEST_P(PaintControllerTest, InvalidateAll) {
InitRootChunk();
DrawRect(context, client, kBackgroundType, FloatRect(1, 2, 3, 4));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_FALSE(GetPaintController().GetPaintArtifact().IsEmpty());
EXPECT_FALSE(GetPaintController().CacheIsAllInvalid());
@@ -1985,6 +1527,81 @@ TEST_P(PaintControllerTest, InvalidateAll) {
EXPECT_TRUE(GetPaintController().CacheIsAllInvalid());
}
+TEST_P(PaintControllerTest, InsertValidItemInFront) {
+ FakeDisplayItemClient first("first", LayoutRect(100, 100, 300, 300));
+ FakeDisplayItemClient second("second", LayoutRect(100, 100, 200, 200));
+ FakeDisplayItemClient third("third", LayoutRect(100, 100, 100, 100));
+ FakeDisplayItemClient fourth("fourth", LayoutRect(100, 100, 50, 50));
+ GraphicsContext context(GetPaintController());
+
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 300, 300));
+ DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 200, 200));
+ DrawRect(context, third, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, fourth, kBackgroundType, FloatRect(100, 100, 50, 50));
+
+ EXPECT_EQ(0, NumCachedNewItems());
+ CommitAndFinishCycle();
+ EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 4,
+ TestDisplayItem(first, kBackgroundType),
+ TestDisplayItem(second, kBackgroundType),
+ TestDisplayItem(third, kBackgroundType),
+ TestDisplayItem(fourth, kBackgroundType));
+ EXPECT_TRUE(first.IsValid());
+ EXPECT_TRUE(second.IsValid());
+ EXPECT_TRUE(third.IsValid());
+ EXPECT_TRUE(fourth.IsValid());
+
+ // Simulate that a composited scrolling element is scrolled down, and "first"
+ // and "second" are scrolled out of the interest rect.
+ InitRootChunk();
+ DrawRect(context, third, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, fourth, kBackgroundType, FloatRect(100, 100, 50, 50));
+
+ EXPECT_EQ(2, NumCachedNewItems());
+#if DCHECK_IS_ON()
+ EXPECT_EQ(2, NumSequentialMatches());
+ EXPECT_EQ(0, NumOutOfOrderMatches());
+ // We indexed "first" and "second" when finding the cached item for "third".
+ EXPECT_EQ(2, NumIndexedItems());
+#endif
+
+ CommitAndFinishCycle();
+ EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
+ TestDisplayItem(third, kBackgroundType),
+ TestDisplayItem(fourth, kBackgroundType));
+ EXPECT_TRUE(first.IsValid());
+ EXPECT_TRUE(second.IsValid());
+ EXPECT_TRUE(third.IsValid());
+ EXPECT_TRUE(fourth.IsValid());
+
+ // Simulate "first" and "second" are scrolled back into the interest rect.
+ InitRootChunk();
+ DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 300, 300));
+ DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 200, 200));
+ DrawRect(context, third, kBackgroundType, FloatRect(100, 100, 100, 100));
+ DrawRect(context, fourth, kBackgroundType, FloatRect(100, 100, 50, 50));
+
+ EXPECT_EQ(2, NumCachedNewItems());
+#if DCHECK_IS_ON()
+ EXPECT_EQ(2, NumSequentialMatches());
+ EXPECT_EQ(0, NumOutOfOrderMatches());
+ // We indexed "third" and "fourth" when finding the cached item for "first".
+ EXPECT_EQ(2, NumIndexedItems());
+#endif
+
+ CommitAndFinishCycle();
+ EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 4,
+ TestDisplayItem(first, kBackgroundType),
+ TestDisplayItem(second, kBackgroundType),
+ TestDisplayItem(third, kBackgroundType),
+ TestDisplayItem(fourth, kBackgroundType));
+ EXPECT_TRUE(first.IsValid());
+ EXPECT_TRUE(second.IsValid());
+ EXPECT_TRUE(third.IsValid());
+ EXPECT_TRUE(fourth.IsValid());
+}
+
// Death tests don't work properly on Android.
#if defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
@@ -2002,7 +1619,7 @@ TEST_P(PaintControllerTest, DuplicatedSubsequences) {
SubsequenceRecorder r(context, client);
DrawRect(context, client, kForegroundType, FloatRect(100, 100, 100, 100));
}
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
};
#if DCHECK_IS_ON()
@@ -2028,7 +1645,7 @@ TEST_P(PaintControllerTest, DuplicatedSubsequences) {
SubsequenceRecorder r(context, client);
DrawRect(context, client, kForegroundType, FloatRect(100, 100, 100, 100));
}
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
}
class PaintControllerUnderInvalidationTest
@@ -2052,13 +1669,13 @@ class PaintControllerUnderInvalidationTest
first.SetVisualRect(LayoutRect(100, 100, 300, 300));
DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 300, 300));
DrawRect(context, first, kForegroundType, FloatRect(100, 100, 300, 300));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
InitRootChunk();
first.SetVisualRect(LayoutRect(200, 200, 300, 300));
DrawRect(context, first, kBackgroundType, FloatRect(200, 200, 300, 300));
DrawRect(context, first, kForegroundType, FloatRect(100, 100, 300, 300));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
}
void TestMoreDrawing() {
@@ -2067,12 +1684,12 @@ class PaintControllerUnderInvalidationTest
InitRootChunk();
DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 300, 300));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
InitRootChunk();
DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 300, 300));
DrawRect(context, first, kForegroundType, FloatRect(100, 100, 300, 300));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
}
void TestLessDrawing() {
@@ -2082,48 +1699,11 @@ class PaintControllerUnderInvalidationTest
InitRootChunk();
DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 300, 300));
DrawRect(context, first, kForegroundType, FloatRect(100, 100, 300, 300));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
InitRootChunk();
DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 300, 300));
- GetPaintController().CommitNewDisplayItems();
- }
-
- void TestNoopPairsInSubsequence() {
- EXPECT_FALSE(GetPaintController().LastDisplayItemIsSubsequenceEnd());
-
- FakeDisplayItemClient container("container");
- GraphicsContext context(GetPaintController());
-
- InitRootChunk();
- {
- SubsequenceRecorder r(context, container);
- DrawRect(context, container, kBackgroundType,
- FloatRect(100, 100, 100, 100));
- }
- GetPaintController().CommitNewDisplayItems();
-
- InitRootChunk();
- EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
- context, container));
- {
- // Generate some no-op pairs which should not affect under-invalidation
- // checking.
- ClipRecorder r1(context, container, kClipType, IntRect(1, 1, 9, 9));
- ClipRecorder r2(context, container, kClipType, IntRect(1, 1, 2, 2));
- ClipRecorder r3(context, container, kClipType, IntRect(1, 1, 3, 3));
- ClipPathRecorder r4(context, container, Path());
- }
- {
- EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
- context, container));
- SubsequenceRecorder r(context, container);
- DrawRect(context, container, kBackgroundType,
- FloatRect(100, 100, 100, 100));
- }
- EXPECT_TRUE(GetPaintController().LastDisplayItemIsSubsequenceEnd());
-
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
}
void TestChangeDrawingInSubsequence() {
@@ -2136,7 +1716,7 @@ class PaintControllerUnderInvalidationTest
DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 300, 300));
DrawRect(context, first, kForegroundType, FloatRect(100, 100, 300, 300));
}
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
InitRootChunk();
{
@@ -2147,7 +1727,7 @@ class PaintControllerUnderInvalidationTest
DrawRect(context, first, kBackgroundType, FloatRect(200, 200, 300, 300));
DrawRect(context, first, kForegroundType, FloatRect(100, 100, 300, 300));
}
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
}
void TestMoreDrawingInSubsequence() {
@@ -2159,7 +1739,7 @@ class PaintControllerUnderInvalidationTest
SubsequenceRecorder r(context, first);
DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 300, 300));
}
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
InitRootChunk();
{
@@ -2169,7 +1749,7 @@ class PaintControllerUnderInvalidationTest
DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 300, 300));
DrawRect(context, first, kForegroundType, FloatRect(100, 100, 300, 300));
}
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
}
void TestLessDrawingInSubsequence() {
@@ -2182,7 +1762,7 @@ class PaintControllerUnderInvalidationTest
DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 300, 300));
DrawRect(context, first, kForegroundType, FloatRect(100, 100, 300, 300));
}
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
InitRootChunk();
{
@@ -2191,35 +1771,7 @@ class PaintControllerUnderInvalidationTest
SubsequenceRecorder r(context, first);
DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 300, 300));
}
- GetPaintController().CommitNewDisplayItems();
- }
-
- void TestChangeNonDrawingInSubsequence() {
- FakeDisplayItemClient container("container");
- FakeDisplayItemClient content("content");
- GraphicsContext context(GetPaintController());
-
- InitRootChunk();
- {
- SubsequenceRecorder r(context, container);
- { ClipPathRecorder clip_path_recorder(context, container, Path()); }
- ClipRecorder clip(context, container, kClipType, IntRect(1, 1, 9, 9));
- DrawRect(context, content, kBackgroundType,
- FloatRect(100, 100, 300, 300));
- }
- GetPaintController().CommitNewDisplayItems();
-
- InitRootChunk();
- {
- EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
- context, container));
- SubsequenceRecorder r(context, container);
- { ClipPathRecorder clip_path_recorder(context, container, Path()); }
- ClipRecorder clip(context, container, kClipType, IntRect(1, 1, 30, 30));
- DrawRect(context, content, kBackgroundType,
- FloatRect(100, 100, 300, 300));
- }
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
}
void TestInvalidationInSubsequence() {
@@ -2233,9 +1785,9 @@ class PaintControllerUnderInvalidationTest
DrawRect(context, content, kBackgroundType,
FloatRect(100, 100, 300, 300));
}
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
- content.SetDisplayItemsUncached();
+ content.Invalidate();
InitRootChunk();
// Leave container not invalidated.
{
@@ -2245,7 +1797,7 @@ class PaintControllerUnderInvalidationTest
DrawRect(context, content, kBackgroundType,
FloatRect(100, 100, 300, 300));
}
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
}
void TestSubsequenceBecomesEmpty() {
@@ -2257,7 +1809,7 @@ class PaintControllerUnderInvalidationTest
SubsequenceRecorder r(context, target);
DrawRect(context, target, kBackgroundType, FloatRect(100, 100, 300, 300));
}
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
InitRootChunk();
{
@@ -2265,7 +1817,7 @@ class PaintControllerUnderInvalidationTest
SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, target));
SubsequenceRecorder r(context, target);
}
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
}
};
@@ -2285,11 +1837,6 @@ TEST_F(PaintControllerUnderInvalidationTest, LessDrawing) {
TestLessDrawing();
}
-TEST_F(PaintControllerUnderInvalidationTest, NoopPairsInSubsequence) {
- // This should not die.
- TestNoopPairsInSubsequence();
-}
-
TEST_F(PaintControllerUnderInvalidationTest, ChangeDrawingInSubsequence) {
EXPECT_DEATH(TestChangeDrawingInSubsequence(),
"In cached subsequence for first.*"
@@ -2307,14 +1854,6 @@ TEST_F(PaintControllerUnderInvalidationTest, LessDrawingInSubsequence) {
"under-invalidation: new subsequence wrong length");
}
-TEST_F(PaintControllerUnderInvalidationTest, ChangeNonDrawingInSubsequence) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
- EXPECT_DEATH(TestChangeNonDrawingInSubsequence(),
- "In cached subsequence for first.*"
- "under-invalidation: new subsequence wrong length");
-}
-
TEST_F(PaintControllerUnderInvalidationTest, InvalidationInSubsequence) {
// We allow invalidated display item clients as long as they would produce the
// same display items. The cases of changed display items are tested by other
@@ -2343,7 +1882,7 @@ TEST_F(PaintControllerUnderInvalidationTest, SkipCacheInSubsequence) {
}
DrawRect(context, content, kForegroundType, FloatRect(200, 200, 400, 400));
}
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
InitRootChunk();
{
@@ -2357,7 +1896,7 @@ TEST_F(PaintControllerUnderInvalidationTest, SkipCacheInSubsequence) {
}
DrawRect(context, content, kForegroundType, FloatRect(200, 200, 400, 400));
}
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
}
TEST_F(PaintControllerUnderInvalidationTest,
@@ -2375,7 +1914,7 @@ TEST_F(PaintControllerUnderInvalidationTest,
DrawRect(context, container, kForegroundType,
FloatRect(100, 100, 300, 300));
}
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
InitRootChunk();
{
@@ -2390,51 +1929,7 @@ TEST_F(PaintControllerUnderInvalidationTest,
DrawRect(context, container, kForegroundType,
FloatRect(100, 100, 300, 300));
}
- GetPaintController().CommitNewDisplayItems();
-}
-
-TEST_F(PaintControllerUnderInvalidationTest,
- PairAfterNoopPairInCachedSubsequence) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
- return;
-
- FakeDisplayItemClient client("client");
- GraphicsContext context(GetPaintController());
-
- {
- SubsequenceRecorder subsequence_recorder(context, client);
- {
- ClipRecorder clip_recorder(context, client, kClipType,
- IntRect(100, 100, 50, 50));
- }
- {
- ClipRecorder clip_recorder(context, client, kClipType,
- IntRect(100, 100, 50, 50));
- DrawRect(context, client, kBackgroundType, FloatRect(100, 100, 200, 200));
- }
- }
- GetPaintController().CommitNewDisplayItems();
- EXPECT_DISPLAY_LIST(
- GetPaintController().GetDisplayItemList(), 3,
- TestDisplayItem(client, kClipType),
- TestDisplayItem(client, kBackgroundType),
- TestDisplayItem(client, DisplayItem::ClipTypeToEndClipType(kClipType)));
-
- {
- EXPECT_FALSE(
- SubsequenceRecorder::UseCachedSubsequenceIfPossible(context, client));
- SubsequenceRecorder subsequence_recorder(context, client);
- {
- ClipRecorder clip_recorder(context, client, kClipType,
- IntRect(100, 100, 50, 50));
- }
- {
- ClipRecorder clip_recorder(context, client, kClipType,
- IntRect(100, 100, 50, 50));
- DrawRect(context, client, kBackgroundType, FloatRect(100, 100, 200, 200));
- }
- }
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
}
#endif // defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h
index e7a0d4c4b83..2ec882b5332 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h
@@ -6,7 +6,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_PAINT_CONTROLLER_TEST_H_
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.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/testing/fake_display_item_client.h"
@@ -43,11 +42,10 @@ class PaintControllerTestBase : public testing::Test {
context.DrawRect(RoundedIntRect(FloatRect(bounds)));
}
- void InitRootChunk() {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- GetPaintController().UpdateCurrentPaintChunkProperties(
- root_paint_chunk_id_, DefaultPaintChunkProperties());
- }
+ void InitRootChunk() { InitRootChunk(GetPaintController()); }
+ void InitRootChunk(PaintController& paint_controller) {
+ paint_controller.UpdateCurrentPaintChunkProperties(
+ root_paint_chunk_id_, DefaultPaintChunkProperties());
}
protected:
@@ -69,6 +67,11 @@ class PaintControllerTestBase : public testing::Test {
void InvalidateAll() { paint_controller_->InvalidateAllForTesting(); }
+ void CommitAndFinishCycle() {
+ paint_controller_->CommitNewDisplayItems();
+ paint_controller_->FinishCycle();
+ }
+
using SubsequenceMarkers = PaintController::SubsequenceMarkers;
SubsequenceMarkers* GetSubsequenceMarkers(const DisplayItemClient& client) {
return paint_controller_->GetSubsequenceMarkers(client);
@@ -83,11 +86,6 @@ class PaintControllerTestBase : public testing::Test {
return ClientCacheIsValid(*paint_controller_, client);
}
- const ChunkRasterInvalidationRects* GetRasterInvalidationRects(size_t i) {
- return GetPaintController().GetPaintArtifact().GetRasterInvalidationRects(
- i);
- }
-
private:
FakeDisplayItemClient root_paint_property_client_;
PaintChunk::Id root_paint_chunk_id_;
@@ -133,7 +131,7 @@ const DisplayItem::Type kForegroundType =
const DisplayItem::Type kDocumentBackgroundType =
DisplayItem::kDocumentBackground;
const DisplayItem::Type kScrollHitTestType = DisplayItem::kScrollHitTest;
-const DisplayItem::Type kClipType = DisplayItem::kClipFirst;
+const DisplayItem::Type kClipType = DisplayItem::kClipPaintPhaseFirst;
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node.h
index cd010c4c3c5..ab428286fbc 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node.h
@@ -69,30 +69,6 @@ class PaintPropertyNode : public RefCounted<NodeType> {
return true;
}
- // TODO(wangxianzhu): Changed() and ClearChangedToRoot() are inefficient
- // due to the tree walks. Optimize this if this affects overall performance.
-
- // Returns true if any node (excluding the lowest common ancestor of
- // |relative_to_node| and |this|) is marked changed along the shortest path
- // from |this| to |relative_to_node|.
- bool Changed(const NodeType& relative_to_node) const {
- if (this == &relative_to_node)
- return false;
-
- bool changed = false;
- for (const auto* n = this; n; n = n->Parent()) {
- if (n == &relative_to_node)
- return changed;
- if (n->changed_)
- changed = true;
- }
-
- // We reach here if |relative_to_node| is not an ancestor of |this|.
- const auto& lca = LowestCommonAncestor(static_cast<const NodeType&>(*this),
- relative_to_node);
- return Changed(lca) || relative_to_node.Changed(lca);
- }
-
void ClearChangedToRoot() const {
for (auto* n = this; n; n = n->Parent())
n->changed_ = false;
@@ -115,23 +91,25 @@ class PaintPropertyNode : public RefCounted<NodeType> {
#endif
protected:
- PaintPropertyNode(scoped_refptr<const NodeType> parent)
- : parent_(std::move(parent)) {}
+ PaintPropertyNode(const NodeType* parent) : parent_(parent) {}
- bool SetParent(scoped_refptr<const NodeType> parent) {
+ bool SetParent(const NodeType* parent) {
DCHECK(!IsRoot());
DCHECK(parent != this);
if (parent == parent_)
return false;
SetChanged();
- parent_ = std::move(parent);
+ parent_ = parent;
return true;
}
void SetChanged() { changed_ = true; }
+ bool NodeChanged() const { return changed_; }
private:
+ friend class PaintPropertyNodeTest;
+
scoped_refptr<const NodeType> parent_;
mutable bool changed_ = true;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node_test.cc
index 88820aa6095..516fbce1011 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_property_node_test.cc
@@ -5,145 +5,397 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_property_node.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/geometry/float_rounded_rect.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_paint_property_node.h"
+#include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h"
#include "third_party/blink/renderer/platform/testing/paint_property_test_helpers.h"
namespace blink {
class PaintPropertyNodeTest : public testing::Test {
protected:
- void SetUp() override {
- root = ClipPaintPropertyNode::Root();
- node = CreateClip(root, nullptr, FloatRoundedRect());
- child1 = CreateClip(node, nullptr, FloatRoundedRect());
- child2 = CreateClip(node, nullptr, FloatRoundedRect());
- grandchild1 = CreateClip(child1, nullptr, FloatRoundedRect());
- grandchild2 = CreateClip(child2, nullptr, FloatRoundedRect());
+ template <typename NodeType>
+ struct Tree {
+ const NodeType* root;
+ scoped_refptr<NodeType> ancestor;
+ scoped_refptr<NodeType> child1;
+ scoped_refptr<NodeType> child2;
+ scoped_refptr<NodeType> grandchild1;
+ scoped_refptr<NodeType> grandchild2;
+ };
+ void SetUp() override {
// root
// |
- // node
+ // ancestor
// / \
// child1 child2
// | |
// grandchild1 grandchild2
+
+ transform.root = &TransformPaintPropertyNode::Root();
+ transform.ancestor =
+ CreateTransform(*transform.root, TransformationMatrix());
+ transform.child1 =
+ CreateTransform(*transform.ancestor, TransformationMatrix());
+ transform.child2 =
+ CreateTransform(*transform.ancestor, TransformationMatrix());
+ transform.grandchild1 =
+ CreateTransform(*transform.child1, TransformationMatrix());
+ transform.grandchild2 =
+ CreateTransform(*transform.child2, TransformationMatrix());
+
+ clip.root = &ClipPaintPropertyNode::Root();
+ clip.ancestor =
+ CreateClip(*clip.root, transform.ancestor.get(), FloatRoundedRect());
+ clip.child1 =
+ CreateClip(*clip.ancestor, transform.child1.get(), FloatRoundedRect());
+ clip.child2 =
+ CreateClip(*clip.ancestor, transform.child2.get(), FloatRoundedRect());
+ clip.grandchild1 = CreateClip(*clip.child1, transform.grandchild1.get(),
+ FloatRoundedRect());
+ clip.grandchild2 = CreateClip(*clip.child2, transform.grandchild2.get(),
+ FloatRoundedRect());
+
+ effect.root = &EffectPaintPropertyNode::Root();
+ effect.ancestor = CreateOpacityEffect(
+ *effect.root, transform.ancestor.get(), clip.ancestor.get(), 0.5);
+ effect.child1 = CreateOpacityEffect(
+ *effect.ancestor, transform.child1.get(), clip.child1.get(), 0.5);
+ effect.child2 = CreateOpacityEffect(
+ *effect.ancestor, transform.child2.get(), clip.child2.get(), 0.5);
+ effect.grandchild1 =
+ CreateOpacityEffect(*effect.child1, transform.grandchild1.get(),
+ clip.grandchild1.get(), 0.5);
+ effect.grandchild2 =
+ CreateOpacityEffect(*effect.child2, transform.grandchild2.get(),
+ clip.grandchild2.get(), 0.5);
+ }
+
+ template <typename NodeType>
+ void ResetAllChanged(Tree<NodeType>& tree) {
+ tree.grandchild1->ClearChangedToRoot();
+ tree.grandchild2->ClearChangedToRoot();
}
void ResetAllChanged() {
- grandchild1->ClearChangedToRoot();
- grandchild2->ClearChangedToRoot();
+ ResetAllChanged(transform);
+ ResetAllChanged(clip);
+ ResetAllChanged(effect);
}
- static void Update(scoped_refptr<ClipPaintPropertyNode> node,
- scoped_refptr<const ClipPaintPropertyNode> new_parent,
- const FloatRoundedRect& new_clip_rect) {
- node->Update(std::move(new_parent),
- ClipPaintPropertyNode::State{nullptr, new_clip_rect});
+ template <typename NodeType>
+ void ExpectInitialState(const Tree<NodeType>& tree) {
+ EXPECT_TRUE(tree.root->NodeChanged());
+ EXPECT_TRUE(tree.ancestor->NodeChanged());
+ EXPECT_TRUE(tree.child1->NodeChanged());
+ EXPECT_TRUE(tree.child2->NodeChanged());
+ EXPECT_TRUE(tree.grandchild1->NodeChanged());
+ EXPECT_TRUE(tree.grandchild2->NodeChanged());
}
- void ExpectInitialState() {
- EXPECT_FALSE(root->Changed(*root));
- EXPECT_TRUE(node->Changed(*root));
- EXPECT_TRUE(child1->Changed(*node));
- EXPECT_TRUE(child2->Changed(*node));
- EXPECT_TRUE(grandchild1->Changed(*child1));
- EXPECT_TRUE(grandchild2->Changed(*child2));
+ template <typename NodeType>
+ void ExpectUnchangedState(const Tree<NodeType>& tree) {
+ EXPECT_FALSE(tree.root->NodeChanged());
+ EXPECT_FALSE(tree.ancestor->NodeChanged());
+ EXPECT_FALSE(tree.child1->NodeChanged());
+ EXPECT_FALSE(tree.child2->NodeChanged());
+ EXPECT_FALSE(tree.grandchild1->NodeChanged());
+ EXPECT_FALSE(tree.grandchild2->NodeChanged());
}
void ExpectUnchangedState() {
- EXPECT_FALSE(root->Changed(*root));
- EXPECT_FALSE(node->Changed(*root));
- EXPECT_FALSE(child1->Changed(*root));
- EXPECT_FALSE(child2->Changed(*root));
- EXPECT_FALSE(grandchild1->Changed(*root));
- EXPECT_FALSE(grandchild2->Changed(*root));
+ ExpectUnchangedState(transform);
+ ExpectUnchangedState(clip);
+ ExpectUnchangedState(effect);
}
- scoped_refptr<ClipPaintPropertyNode> root;
- scoped_refptr<ClipPaintPropertyNode> node;
- scoped_refptr<ClipPaintPropertyNode> child1;
- scoped_refptr<ClipPaintPropertyNode> child2;
- scoped_refptr<ClipPaintPropertyNode> grandchild1;
- scoped_refptr<ClipPaintPropertyNode> grandchild2;
+ Tree<TransformPaintPropertyNode> transform;
+ Tree<ClipPaintPropertyNode> clip;
+ Tree<EffectPaintPropertyNode> effect;
};
+#define STATE(node) \
+ PropertyTreeState(&*transform.node, &*clip.node, &*effect.node)
+
TEST_F(PaintPropertyNodeTest, LowestCommonAncestor) {
- EXPECT_EQ(node, &LowestCommonAncestor(*node, *node));
- EXPECT_EQ(root, &LowestCommonAncestor(*root, *root));
+ EXPECT_EQ(transform.ancestor,
+ &LowestCommonAncestor(*transform.ancestor, *transform.ancestor));
+ EXPECT_EQ(transform.root,
+ &LowestCommonAncestor(*transform.root, *transform.root));
- EXPECT_EQ(node, &LowestCommonAncestor(*grandchild1, *grandchild2));
- EXPECT_EQ(node, &LowestCommonAncestor(*grandchild1, *child2));
- EXPECT_EQ(root, &LowestCommonAncestor(*grandchild1, *root));
- EXPECT_EQ(child1, &LowestCommonAncestor(*grandchild1, *child1));
+ EXPECT_EQ(transform.ancestor, &LowestCommonAncestor(*transform.grandchild1,
+ *transform.grandchild2));
+ EXPECT_EQ(transform.ancestor,
+ &LowestCommonAncestor(*transform.grandchild1, *transform.child2));
+ EXPECT_EQ(transform.root,
+ &LowestCommonAncestor(*transform.grandchild1, *transform.root));
+ EXPECT_EQ(transform.child1,
+ &LowestCommonAncestor(*transform.grandchild1, *transform.child1));
- EXPECT_EQ(node, &LowestCommonAncestor(*grandchild2, *grandchild1));
- EXPECT_EQ(node, &LowestCommonAncestor(*grandchild2, *child1));
- EXPECT_EQ(root, &LowestCommonAncestor(*grandchild2, *root));
- EXPECT_EQ(child2, &LowestCommonAncestor(*grandchild2, *child2));
+ EXPECT_EQ(transform.ancestor, &LowestCommonAncestor(*transform.grandchild2,
+ *transform.grandchild1));
+ EXPECT_EQ(transform.ancestor,
+ &LowestCommonAncestor(*transform.grandchild2, *transform.child1));
+ EXPECT_EQ(transform.root,
+ &LowestCommonAncestor(*transform.grandchild2, *transform.root));
+ EXPECT_EQ(transform.child2,
+ &LowestCommonAncestor(*transform.grandchild2, *transform.child2));
- EXPECT_EQ(node, &LowestCommonAncestor(*child1, *child2));
- EXPECT_EQ(node, &LowestCommonAncestor(*child2, *child1));
+ EXPECT_EQ(transform.ancestor,
+ &LowestCommonAncestor(*transform.child1, *transform.child2));
+ EXPECT_EQ(transform.ancestor,
+ &LowestCommonAncestor(*transform.child2, *transform.child1));
}
TEST_F(PaintPropertyNodeTest, InitialStateAndReset) {
- ExpectInitialState();
+ ExpectInitialState(transform);
+ ResetAllChanged(transform);
+ ExpectUnchangedState(transform);
+}
+
+TEST_F(PaintPropertyNodeTest, TransformChangeAncestor) {
+ ResetAllChanged();
+ ExpectUnchangedState();
+ transform.ancestor->Update(*transform.root,
+ TransformPaintPropertyNode::State{
+ TransformationMatrix().Translate(1, 2)});
+
+ // Test descendant->Changed(ancestor).
+ EXPECT_TRUE(transform.ancestor->Changed(*transform.root));
+ EXPECT_FALSE(transform.ancestor->Changed(*transform.ancestor));
+ EXPECT_TRUE(transform.child1->Changed(*transform.root));
+ EXPECT_FALSE(transform.child1->Changed(*transform.ancestor));
+ EXPECT_TRUE(transform.grandchild1->Changed(*transform.root));
+ EXPECT_FALSE(transform.grandchild1->Changed(*transform.ancestor));
+
+ // Test property->Changed(non-ancestor-property). Should combine the changed
+ // flags of the two paths to the root.
+ EXPECT_TRUE(transform.grandchild1->Changed(*transform.child2));
+ EXPECT_TRUE(transform.grandchild1->Changed(*transform.grandchild2));
+
+ ResetAllChanged();
+ ExpectUnchangedState();
+}
+
+TEST_F(PaintPropertyNodeTest, ClipChangeAncestor) {
+ ResetAllChanged();
+ ExpectUnchangedState();
+ clip.ancestor->Update(
+ *clip.root, ClipPaintPropertyNode::State{transform.ancestor.get(),
+ FloatRoundedRect(1, 2, 3, 4)});
+
+ // Test descendant->Changed(ancestor).
+ EXPECT_TRUE(clip.ancestor->Changed(STATE(root), nullptr));
+ EXPECT_FALSE(clip.ancestor->Changed(STATE(ancestor), nullptr));
+ EXPECT_TRUE(clip.child1->Changed(STATE(root), nullptr));
+ EXPECT_FALSE(clip.child1->Changed(STATE(ancestor), nullptr));
+ EXPECT_TRUE(clip.grandchild1->Changed(STATE(root), nullptr));
+ EXPECT_FALSE(clip.grandchild1->Changed(STATE(ancestor), nullptr));
+
+ // Test property->Changed(non-ancestor-property).
+ // Simply walk to the root.
+ EXPECT_TRUE(clip.grandchild1->Changed(STATE(child2), nullptr));
+ EXPECT_TRUE(clip.grandchild1->Changed(STATE(grandchild2), nullptr));
+
+ ResetAllChanged();
+ ExpectUnchangedState();
+}
+
+TEST_F(PaintPropertyNodeTest, EffectChangeAncestor) {
+ ResetAllChanged();
+ ExpectUnchangedState();
+ EffectPaintPropertyNode::State state{transform.ancestor.get(),
+ clip.ancestor.get()};
+ state.opacity = 0.9;
+ effect.ancestor->Update(*effect.root, std::move(state));
+
+ // Test descendant->Changed(ancestor).
+ EXPECT_TRUE(effect.ancestor->Changed(STATE(root), nullptr));
+ EXPECT_FALSE(effect.ancestor->Changed(STATE(ancestor), nullptr));
+ EXPECT_TRUE(effect.child1->Changed(STATE(root), nullptr));
+ EXPECT_FALSE(effect.child1->Changed(STATE(ancestor), nullptr));
+ EXPECT_TRUE(effect.grandchild1->Changed(STATE(root), nullptr));
+ EXPECT_FALSE(effect.grandchild1->Changed(STATE(ancestor), nullptr));
+
+ // Test property->Changed(non-ancestor-property).
+ // Simply walk to the root.
+ EXPECT_TRUE(effect.grandchild1->Changed(STATE(child2), nullptr));
+ EXPECT_TRUE(effect.grandchild1->Changed(STATE(grandchild2), nullptr));
+
ResetAllChanged();
ExpectUnchangedState();
}
-TEST_F(PaintPropertyNodeTest, ChangeNode) {
+TEST_F(PaintPropertyNodeTest, TransformChangeOneChild) {
ResetAllChanged();
- Update(node, root, FloatRoundedRect(1, 2, 3, 4));
- EXPECT_TRUE(node->Changed(*root));
- EXPECT_FALSE(node->Changed(*node));
- EXPECT_TRUE(child1->Changed(*root));
- EXPECT_FALSE(child1->Changed(*node));
- EXPECT_TRUE(grandchild1->Changed(*root));
- EXPECT_FALSE(grandchild1->Changed(*node));
+ ExpectUnchangedState();
+ transform.child1->Update(*transform.ancestor,
+ TransformPaintPropertyNode::State{
+ TransformationMatrix().Translate(1, 2)});
+
+ // Test descendant->Changed(ancestor).
+ EXPECT_FALSE(transform.ancestor->Changed(*transform.root));
+ EXPECT_FALSE(transform.ancestor->Changed(*transform.ancestor));
+ EXPECT_TRUE(transform.child1->Changed(*transform.root));
+ EXPECT_TRUE(transform.child1->Changed(*transform.ancestor));
+ EXPECT_TRUE(transform.grandchild1->Changed(*transform.ancestor));
+ EXPECT_FALSE(transform.grandchild1->Changed(*transform.child1));
+ EXPECT_FALSE(transform.child2->Changed(*transform.ancestor));
+ EXPECT_FALSE(transform.grandchild2->Changed(*transform.ancestor));
- EXPECT_FALSE(grandchild1->Changed(*child2));
- EXPECT_FALSE(grandchild1->Changed(*grandchild2));
+ // Test property->Changed(non-ancestor-property). Need to combine the changed
+ // flags of the two paths to the root.
+ EXPECT_TRUE(transform.child2->Changed(*transform.child1));
+ EXPECT_TRUE(transform.child1->Changed(*transform.child2));
+ EXPECT_TRUE(transform.child2->Changed(*transform.grandchild1));
+ EXPECT_TRUE(transform.child1->Changed(*transform.grandchild2));
+ EXPECT_TRUE(transform.grandchild1->Changed(*transform.child2));
+ EXPECT_TRUE(transform.grandchild1->Changed(*transform.grandchild2));
+ EXPECT_TRUE(transform.grandchild2->Changed(*transform.child1));
+ EXPECT_TRUE(transform.grandchild2->Changed(*transform.grandchild1));
ResetAllChanged();
ExpectUnchangedState();
}
-TEST_F(PaintPropertyNodeTest, ChangeOneChild) {
+TEST_F(PaintPropertyNodeTest, ClipChangeOneChild) {
ResetAllChanged();
- Update(child1, node, FloatRoundedRect(1, 2, 3, 4));
- EXPECT_FALSE(node->Changed(*root));
- EXPECT_FALSE(node->Changed(*node));
- EXPECT_TRUE(child1->Changed(*root));
- EXPECT_TRUE(child1->Changed(*node));
- EXPECT_TRUE(grandchild1->Changed(*node));
- EXPECT_FALSE(grandchild1->Changed(*child1));
- EXPECT_FALSE(child2->Changed(*node));
- EXPECT_FALSE(grandchild2->Changed(*node));
+ ExpectUnchangedState();
+ clip.child1->Update(
+ *clip.root, ClipPaintPropertyNode::State{transform.ancestor.get(),
+ FloatRoundedRect(1, 2, 3, 4)});
- EXPECT_TRUE(child2->Changed(*child1));
- EXPECT_TRUE(child1->Changed(*child2));
- EXPECT_TRUE(child2->Changed(*grandchild1));
- EXPECT_TRUE(child1->Changed(*grandchild2));
- EXPECT_TRUE(grandchild1->Changed(*child2));
- EXPECT_TRUE(grandchild1->Changed(*grandchild2));
- EXPECT_TRUE(grandchild2->Changed(*child1));
- EXPECT_TRUE(grandchild2->Changed(*grandchild1));
+ // Test descendant->Changed(ancestor).
+ EXPECT_FALSE(clip.ancestor->Changed(STATE(root), nullptr));
+ EXPECT_FALSE(clip.ancestor->Changed(STATE(ancestor), nullptr));
+ EXPECT_TRUE(clip.child1->Changed(STATE(root), nullptr));
+ EXPECT_TRUE(clip.child1->Changed(STATE(ancestor), nullptr));
+ EXPECT_TRUE(clip.grandchild1->Changed(STATE(ancestor), nullptr));
+ EXPECT_FALSE(clip.grandchild1->Changed(STATE(child1), nullptr));
+ EXPECT_FALSE(clip.child2->Changed(STATE(ancestor), nullptr));
+ EXPECT_FALSE(clip.grandchild2->Changed(STATE(ancestor), nullptr));
+
+ // Test property->Changed(non-ancestor-property).
+ // Simply walk to the root, regardless of relative_to_state's path.
+ EXPECT_FALSE(clip.child2->Changed(STATE(child1), nullptr));
+ EXPECT_TRUE(clip.child1->Changed(STATE(child2), nullptr));
+ EXPECT_FALSE(clip.child2->Changed(STATE(grandchild1), nullptr));
+ EXPECT_TRUE(clip.child1->Changed(STATE(grandchild2), nullptr));
+ EXPECT_TRUE(clip.grandchild1->Changed(STATE(child2), nullptr));
+ EXPECT_TRUE(clip.grandchild1->Changed(STATE(grandchild2), nullptr));
+ EXPECT_FALSE(clip.grandchild2->Changed(STATE(child1), nullptr));
+ EXPECT_FALSE(clip.grandchild2->Changed(STATE(grandchild1), nullptr));
ResetAllChanged();
ExpectUnchangedState();
}
-TEST_F(PaintPropertyNodeTest, Reparent) {
+TEST_F(PaintPropertyNodeTest, EffectChangeOneChild) {
+ ResetAllChanged();
+ ExpectUnchangedState();
+ EffectPaintPropertyNode::State state{transform.ancestor.get(),
+ clip.ancestor.get()};
+ state.opacity = 0.9;
+ effect.child1->Update(*effect.root, std::move(state));
+
+ // Test descendant->Changed(ancestor).
+ EXPECT_FALSE(effect.ancestor->Changed(STATE(root), nullptr));
+ EXPECT_FALSE(effect.ancestor->Changed(STATE(ancestor), nullptr));
+ EXPECT_TRUE(effect.child1->Changed(STATE(root), nullptr));
+ EXPECT_TRUE(effect.child1->Changed(STATE(ancestor), nullptr));
+ EXPECT_TRUE(effect.grandchild1->Changed(STATE(ancestor), nullptr));
+ EXPECT_FALSE(effect.grandchild1->Changed(STATE(child1), nullptr));
+ EXPECT_FALSE(effect.child2->Changed(STATE(ancestor), nullptr));
+ EXPECT_FALSE(effect.grandchild2->Changed(STATE(ancestor), nullptr));
+
+ // Test property->Changed(non-ancestor-property).
+ // Simply walk to the root, regardless of relative_to_state's path.
+ EXPECT_FALSE(effect.child2->Changed(STATE(child1), nullptr));
+ EXPECT_TRUE(effect.child1->Changed(STATE(child2), nullptr));
+ EXPECT_FALSE(effect.child2->Changed(STATE(grandchild1), nullptr));
+ EXPECT_TRUE(effect.child1->Changed(STATE(grandchild2), nullptr));
+ EXPECT_TRUE(effect.grandchild1->Changed(STATE(child2), nullptr));
+ EXPECT_TRUE(effect.grandchild1->Changed(STATE(grandchild2), nullptr));
+ EXPECT_FALSE(effect.grandchild2->Changed(STATE(child1), nullptr));
+ EXPECT_FALSE(effect.grandchild2->Changed(STATE(grandchild1), nullptr));
+
ResetAllChanged();
- Update(child1, child2, FloatRoundedRect(1, 2, 3, 4));
- EXPECT_FALSE(node->Changed(*root));
- EXPECT_TRUE(child1->Changed(*node));
- EXPECT_TRUE(child1->Changed(*child2));
- EXPECT_FALSE(child2->Changed(*node));
- EXPECT_TRUE(grandchild1->Changed(*node));
- EXPECT_FALSE(grandchild1->Changed(*child1));
- EXPECT_TRUE(grandchild1->Changed(*child2));
+ ExpectUnchangedState();
+}
+
+TEST_F(PaintPropertyNodeTest, TransformReparent) {
+ ResetAllChanged();
+ ExpectUnchangedState();
+ transform.child1->Update(*transform.child2,
+ TransformPaintPropertyNode::State{
+ TransformationMatrix().Translate(1, 2)});
+ EXPECT_FALSE(transform.ancestor->Changed(*transform.root));
+ EXPECT_TRUE(transform.child1->Changed(*transform.ancestor));
+ EXPECT_TRUE(transform.child1->Changed(*transform.child2));
+ EXPECT_FALSE(transform.child2->Changed(*transform.ancestor));
+ EXPECT_TRUE(transform.grandchild1->Changed(*transform.ancestor));
+ EXPECT_FALSE(transform.grandchild1->Changed(*transform.child1));
+ EXPECT_TRUE(transform.grandchild1->Changed(*transform.child2));
+
+ ResetAllChanged();
+ ExpectUnchangedState();
+}
+
+TEST_F(PaintPropertyNodeTest, ClipLocalTransformSpaceChange) {
+ ResetAllChanged();
+ ExpectUnchangedState();
+ transform.child1->Update(*transform.ancestor,
+ TransformPaintPropertyNode::State{
+ TransformationMatrix().Translate(1, 2)});
+
+ EXPECT_FALSE(clip.ancestor->Changed(STATE(root), nullptr));
+ EXPECT_FALSE(clip.ancestor->Changed(STATE(ancestor), nullptr));
+ EXPECT_TRUE(clip.child1->Changed(STATE(root), nullptr));
+ EXPECT_TRUE(clip.child1->Changed(STATE(ancestor), nullptr));
+ EXPECT_TRUE(clip.grandchild1->Changed(STATE(ancestor), nullptr));
+ EXPECT_FALSE(clip.grandchild1->Changed(STATE(child1), nullptr));
+
+ // Test with transform_not_to_check.
+ EXPECT_FALSE(clip.child1->Changed(STATE(root), transform.child1.get()));
+ EXPECT_FALSE(clip.child1->Changed(STATE(ancestor), transform.child1.get()));
+ EXPECT_TRUE(
+ clip.grandchild1->Changed(STATE(ancestor), transform.child1.get()));
+ EXPECT_TRUE(clip.child1->Changed(STATE(root), transform.ancestor.get()));
+ EXPECT_TRUE(clip.child1->Changed(STATE(ancestor), transform.ancestor.get()));
+ EXPECT_TRUE(
+ clip.grandchild1->Changed(STATE(ancestor), transform.ancestor.get()));
+
+ ResetAllChanged();
+ ExpectUnchangedState();
+}
+
+TEST_F(PaintPropertyNodeTest, EffectLocalTransformSpaceChange) {
+ // Let effect.child1 have pixel-moving filter.
+ EffectPaintPropertyNode::State state{transform.child1.get(),
+ clip.child1.get()};
+ state.filter.AppendBlurFilter(20);
+ effect.child1->Update(*effect.ancestor, std::move(state));
+
+ ResetAllChanged();
+ ExpectUnchangedState();
+ transform.ancestor->Update(*transform.root,
+ TransformPaintPropertyNode::State{
+ TransformationMatrix().Translate(1, 2)});
+
+ EXPECT_FALSE(effect.ancestor->Changed(STATE(root), nullptr));
+ EXPECT_FALSE(effect.ancestor->Changed(STATE(ancestor), nullptr));
+ EXPECT_TRUE(effect.child1->Changed(STATE(root), nullptr));
+ EXPECT_FALSE(effect.child1->Changed(STATE(ancestor), nullptr));
+ EXPECT_TRUE(effect.grandchild1->Changed(STATE(root), nullptr));
+ EXPECT_FALSE(effect.grandchild1->Changed(STATE(ancestor), nullptr));
+ EXPECT_FALSE(effect.grandchild1->Changed(STATE(child1), nullptr));
+ // Effects without self or ancestor pixel-moving filter are not affected by
+ // change of LocalTransformSpace.
+ EXPECT_FALSE(effect.child2->Changed(STATE(root), nullptr));
+ EXPECT_FALSE(effect.grandchild2->Changed(STATE(root), nullptr));
+
+ // Test with transform_not_to_check.
+ EXPECT_FALSE(effect.child1->Changed(STATE(root), transform.child1.get()));
+ EXPECT_TRUE(effect.child1->Changed(STATE(root), transform.ancestor.get()));
ResetAllChanged();
ExpectUnchangedState();
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc
index ddf2f3433c1..239f61dc8c5 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.cc
@@ -22,14 +22,13 @@ PaintRecordBuilder::PaintRecordBuilder(SkMetaData* meta_data,
if (paint_controller) {
paint_controller_ = paint_controller;
} else {
- own_paint_controller_ = PaintController::Create();
+ own_paint_controller_ =
+ PaintController::Create(PaintController::kTransient);
paint_controller_ = own_paint_controller_.get();
}
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- paint_controller_->UpdateCurrentPaintChunkProperties(
- base::nullopt, PropertyTreeState::Root());
- }
+ paint_controller_->UpdateCurrentPaintChunkProperties(
+ base::nullopt, PropertyTreeState::Root());
const HighContrastSettings* high_contrast_settings =
containing_context ? &containing_context->high_contrast_settings()
@@ -43,27 +42,24 @@ PaintRecordBuilder::PaintRecordBuilder(SkMetaData* meta_data,
context_->SetDeviceScaleFactor(containing_context->DeviceScaleFactor());
context_->SetPrinting(containing_context->Printing());
}
-
- if (!paint_controller)
- cache_skipper_.emplace(*context_);
}
+PaintRecordBuilder::~PaintRecordBuilder() = default;
+
sk_sp<PaintRecord> PaintRecordBuilder::EndRecording(
const PropertyTreeState& replay_state) {
context_->BeginRecording(FloatRect());
paint_controller_->CommitNewDisplayItems();
+ paint_controller_->FinishCycle();
paint_controller_->GetPaintArtifact().Replay(*context_, replay_state);
return context_->EndRecording();
}
-void PaintRecordBuilder::EndRecording(PaintCanvas& canvas,
+void PaintRecordBuilder::EndRecording(cc::PaintCanvas& canvas,
const PropertyTreeState& replay_state) {
- if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- canvas.drawPicture(EndRecording());
- } else {
- paint_controller_->CommitNewDisplayItems();
- paint_controller_->GetPaintArtifact().Replay(canvas, replay_state);
- }
+ paint_controller_->CommitNewDisplayItems();
+ paint_controller_->FinishCycle();
+ paint_controller_->GetPaintArtifact().Replay(canvas, replay_state);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h
index 9365ce05d7b..2ddaae4f2f8 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h
@@ -7,56 +7,53 @@
#include <memory>
+#include "base/macros.h"
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item_client.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record.h"
#include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/skia/include/core/SkRefCnt.h"
class SkMetaData;
-namespace blink {
+namespace cc {
+class PaintCanvas;
+}
+namespace blink {
class GraphicsContext;
class PaintController;
-// TODO(enne): rename this class to not be named SkPicture
-// When slimming paint ships we can remove this PaintRecord abstraction and
-// rely on PaintController here.
class PLATFORM_EXPORT PaintRecordBuilder final : public DisplayItemClient {
- WTF_MAKE_NONCOPYABLE(PaintRecordBuilder);
public:
- // Constructs a new builder for the resulting recorded picture. If |metadata|
+ // Constructs a new builder for the resulting paint record. If |metadata|
// is specified, that metadata is propagated to the builder's internal canvas.
// If |containing_context| is specified, the device scale factor, printing,
// and disabled state are propagated to the builder's internal context.
// If a PaintController is passed, it is used as the PaintController for
// painting the picture (and hence we can use its cache). Otherwise, a new
- // PaintController is used for the duration of the picture building, which
- // therefore has no caching.
- // In SPv175+ mode, resets paint chunks to PropertyTreeState::Root()
- // before beginning to record.
- PaintRecordBuilder(SkMetaData* = nullptr,
+ // transient PaintController is used for the duration of the picture building,
+ // which therefore has no caching. It also resets paint chunk state to
+ // PropertyTreeState::Root() before beginning to record.
+ PaintRecordBuilder(SkMetaData* metadata = nullptr,
GraphicsContext* containing_context = nullptr,
PaintController* = nullptr);
+ ~PaintRecordBuilder() override;
GraphicsContext& Context() { return *context_; }
// Returns a PaintRecord capturing all drawing performed on the builder's
- // context since construction.
- // In SPv175+ mode, replays into the ancestor state given by |replay_state|.
+ // context since construction, into the ancestor state given by
+ // |replay_state|.
sk_sp<PaintRecord> EndRecording(
const PropertyTreeState& replay_state = PropertyTreeState::Root());
- // Replays the recording directly into the given canvas.
- // In SPv175+ mode, replays into the ancestor state given by |replay_state|.
+ // Replays the recording directly into the given canvas, in the ancestor
+ // state given by |replay_state|.
void EndRecording(
- PaintCanvas&,
+ cc::PaintCanvas&,
const PropertyTreeState& replay_state = PropertyTreeState::Root());
// DisplayItemClient methods
@@ -67,7 +64,8 @@ class PLATFORM_EXPORT PaintRecordBuilder final : public DisplayItemClient {
PaintController* paint_controller_;
std::unique_ptr<PaintController> own_paint_controller_;
std::unique_ptr<GraphicsContext> context_;
- base::Optional<DisplayItemCacheSkipper> cache_skipper_;
+
+ DISALLOW_COPY_AND_ASSIGN(PaintRecordBuilder);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder_test.cc
index ec9bd09306e..baac60ed768 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/paint_record_builder_test.cc
@@ -34,10 +34,7 @@ TEST_F(PaintRecordBuilderTest, TransientPaintController) {
}
TEST_F(PaintRecordBuilderTest, LastingPaintController) {
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- GetPaintController().UpdateCurrentPaintChunkProperties(
- base::nullopt, PropertyTreeState::Root());
- }
+ InitRootChunk();
PaintRecordBuilder builder(nullptr, nullptr, &GetPaintController());
auto& context = builder.Context();
@@ -58,11 +55,7 @@ TEST_F(PaintRecordBuilderTest, LastingPaintController) {
TestDisplayItem(client, kBackgroundType),
TestDisplayItem(client, kForegroundType));
- if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
- GetPaintController().UpdateCurrentPaintChunkProperties(
- base::nullopt, PropertyTreeState::Root());
- }
-
+ InitRootChunk();
EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(context, client,
kBackgroundType));
EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(context, client,
@@ -83,11 +76,11 @@ TEST_F(PaintRecordBuilderTest, TransientAndAnotherPaintController) {
FakeDisplayItemClient client("client", LayoutRect(10, 10, 20, 20));
DrawRect(context, client, kBackgroundType, FloatRect(10, 10, 20, 20));
DrawRect(context, client, kForegroundType, FloatRect(15, 15, 10, 10));
- GetPaintController().CommitNewDisplayItems();
+ CommitAndFinishCycle();
EXPECT_DISPLAY_LIST(GetPaintController().GetDisplayItemList(), 2,
TestDisplayItem(client, kBackgroundType),
TestDisplayItem(client, kForegroundType));
- EXPECT_TRUE(ClientCacheIsValid(client));
+ // EXPECT_TRUE(ClientCacheIsValid(client));
PaintRecordBuilder builder;
EXPECT_NE(&builder.Context().GetPaintController(), &GetPaintController());
@@ -97,9 +90,9 @@ TEST_F(PaintRecordBuilderTest, TransientAndAnotherPaintController) {
// The transient PaintController in PaintRecordBuilder doesn't affect the
// client's cache status in another PaintController.
- EXPECT_TRUE(ClientCacheIsValid(client));
- EXPECT_FALSE(
- ClientCacheIsValid(builder.Context().GetPaintController(), client));
+ // EXPECT_TRUE(ClientCacheIsValid(client));
+ // EXPECT_FALSE(
+ // ClientCacheIsValid(builder.Context().GetPaintController(), client));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc
index 736b61c2c61..8b0bfc878e9 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state.cc
@@ -10,11 +10,10 @@ namespace blink {
const PropertyTreeState& PropertyTreeState::Root() {
DEFINE_STATIC_LOCAL(
- std::unique_ptr<PropertyTreeState>, root,
- (std::make_unique<PropertyTreeState>(TransformPaintPropertyNode::Root(),
- ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())));
- return *root;
+ PropertyTreeState, root,
+ (&TransformPaintPropertyNode::Root(), &ClipPaintPropertyNode::Root(),
+ &EffectPaintPropertyNode::Root()));
+ return root;
}
const CompositorElementId PropertyTreeState::GetCompositorElementId(
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state_test.cc
index 26bf33b13ae..52027813c4d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/property_tree_state_test.cc
@@ -29,40 +29,38 @@ CreateEffectWithCompositorElementId(
}
TEST_F(PropertyTreeStateTest, CompositorElementIdNoElementIdOnAnyNode) {
- PropertyTreeState state(TransformPaintPropertyNode::Root(),
- ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root());
EXPECT_EQ(CompositorElementId(),
- state.GetCompositorElementId(CompositorElementIdSet()));
+ PropertyTreeState::Root().GetCompositorElementId(
+ CompositorElementIdSet()));
}
TEST_F(PropertyTreeStateTest, CompositorElementIdWithElementIdOnTransformNode) {
CompositorElementId expected_compositor_element_id = CompositorElementId(2);
- scoped_refptr<TransformPaintPropertyNode> transform =
+ auto transform =
CreateTransformWithCompositorElementId(expected_compositor_element_id);
- PropertyTreeState state(transform.get(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root());
+ PropertyTreeState state(transform.get(), &ClipPaintPropertyNode::Root(),
+ &EffectPaintPropertyNode::Root());
EXPECT_EQ(expected_compositor_element_id,
state.GetCompositorElementId(CompositorElementIdSet()));
}
TEST_F(PropertyTreeStateTest, CompositorElementIdWithElementIdOnEffectNode) {
CompositorElementId expected_compositor_element_id = CompositorElementId(2);
- scoped_refptr<EffectPaintPropertyNode> effect =
+ auto effect =
CreateEffectWithCompositorElementId(expected_compositor_element_id);
- PropertyTreeState state(TransformPaintPropertyNode::Root(),
- ClipPaintPropertyNode::Root(), effect.get());
+ PropertyTreeState state(&TransformPaintPropertyNode::Root(),
+ &ClipPaintPropertyNode::Root(), effect.get());
EXPECT_EQ(expected_compositor_element_id,
state.GetCompositorElementId(CompositorElementIdSet()));
}
TEST_F(PropertyTreeStateTest, CompositorElementIdWithElementIdOnMultipleNodes) {
CompositorElementId expected_compositor_element_id = CompositorElementId(2);
- scoped_refptr<TransformPaintPropertyNode> transform =
+ auto transform =
CreateTransformWithCompositorElementId(expected_compositor_element_id);
- scoped_refptr<EffectPaintPropertyNode> effect =
+ auto effect =
CreateEffectWithCompositorElementId(expected_compositor_element_id);
- PropertyTreeState state(transform.get(), ClipPaintPropertyNode::Root(),
+ PropertyTreeState state(transform.get(), &ClipPaintPropertyNode::Root(),
effect.get());
EXPECT_EQ(expected_compositor_element_id,
state.GetCompositorElementId(CompositorElementIdSet()));
@@ -71,11 +69,11 @@ TEST_F(PropertyTreeStateTest, CompositorElementIdWithElementIdOnMultipleNodes) {
TEST_F(PropertyTreeStateTest, CompositorElementIdWithDifferingElementIds) {
CompositorElementId first_compositor_element_id = CompositorElementId(2);
CompositorElementId second_compositor_element_id = CompositorElementId(3);
- scoped_refptr<TransformPaintPropertyNode> transform =
+ auto transform =
CreateTransformWithCompositorElementId(first_compositor_element_id);
- scoped_refptr<EffectPaintPropertyNode> effect =
+ auto effect =
CreateEffectWithCompositorElementId(second_compositor_element_id);
- PropertyTreeState state(transform.get(), ClipPaintPropertyNode::Root(),
+ PropertyTreeState state(transform.get(), &ClipPaintPropertyNode::Root(),
effect.get());
CompositorElementIdSet composited_element_ids;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.cc
index 4cf2f05cb2e..4f3e4ac3f31 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.cc
@@ -247,7 +247,8 @@ void RasterInvalidationTracking::CheckUnderInvalidations(
auto* canvas = recorder.getRecordingCanvas();
if (under_invalidation_record_)
canvas->drawPicture(std::move(under_invalidation_record_));
- canvas->drawBitmap(new_bitmap, rect.X(), rect.Y());
+ canvas->drawImage(cc::PaintImage::CreateFromBitmap(std::move(new_bitmap)),
+ rect.X(), rect.Y());
under_invalidation_record_ = recorder.finishRecordingAsPicture();
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h
index 00ffa55fcec..04e2760dec6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h
@@ -26,6 +26,7 @@ class DisplayItemClient;
struct RasterInvalidationInfo {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
+
// This is for comparison only. Don't dereference because the client may have
// died.
const DisplayItemClient* client = nullptr;
@@ -36,6 +37,22 @@ struct RasterInvalidationInfo {
PaintInvalidationReason reason = PaintInvalidationReason::kFull;
};
+inline bool operator==(const RasterInvalidationInfo& a,
+ const RasterInvalidationInfo& b) {
+ return a.client == b.client && a.client_debug_name == b.client_debug_name &&
+ a.rect == b.rect && a.reason == b.reason;
+}
+inline bool operator!=(const RasterInvalidationInfo& a,
+ const RasterInvalidationInfo& b) {
+ return !(a == b);
+}
+
+inline std::ostream& operator<<(std::ostream& os,
+ const RasterInvalidationInfo& info) {
+ return os << info.client << ":" << info.client_debug_name
+ << " rect=" << info.rect << " reason=" << info.reason;
+}
+
struct RasterUnderInvalidation {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
int x;
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc
new file mode 100644
index 00000000000..e33be29d177
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.cc
@@ -0,0 +1,359 @@
+// 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/platform/graphics/paint/raster_invalidator.h"
+
+#include <algorithm>
+#include <memory>
+#include <utility>
+
+#include "third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.h"
+#include "third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator.h"
+#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
+
+namespace blink {
+
+void RasterInvalidator::UpdateClientDebugNames(
+ const PaintArtifact& paint_artifact,
+ const PaintChunkSubset& paint_chunks) {
+ DCHECK(tracking_info_);
+ auto& debug_names = tracking_info_->old_client_debug_names;
+ debug_names.clear();
+ for (const auto& chunk : paint_chunks) {
+ debug_names.insert(&chunk.id.client, chunk.id.client.DebugName());
+ for (const auto& item :
+ paint_artifact.GetDisplayItemList().ItemsInPaintChunk(chunk))
+ debug_names.insert(&item.Client(), item.Client().DebugName());
+ }
+}
+
+void RasterInvalidator::SetTracksRasterInvalidations(bool should_track) {
+ if (should_track) {
+ if (!tracking_info_)
+ tracking_info_ = std::make_unique<RasterInvalidationTrackingInfo>();
+ tracking_info_->tracking.ClearInvalidations();
+
+ // This is called just after a full document cycle update, so all clients in
+ // old_paint_artifact_ should be still alive.
+ if (old_paint_artifact_) {
+ UpdateClientDebugNames(*old_paint_artifact_,
+ old_paint_artifact_->PaintChunks());
+ }
+ } else if (!RasterInvalidationTracking::ShouldAlwaysTrack()) {
+ tracking_info_ = nullptr;
+ } else if (tracking_info_) {
+ tracking_info_->tracking.ClearInvalidations();
+ }
+}
+
+const PaintChunk& RasterInvalidator::GetOldChunk(size_t index) const {
+ DCHECK(old_paint_artifact_);
+ const auto& old_chunk_info = old_paint_chunks_info_[index];
+ const auto& old_chunk =
+ old_paint_artifact_
+ ->PaintChunks()[old_chunk_info.index_in_paint_artifact];
+#if DCHECK_IS_ON()
+ DCHECK(old_chunk.id == old_chunk_info.id);
+#endif
+ return old_chunk;
+}
+
+size_t RasterInvalidator::MatchNewChunkToOldChunk(const PaintChunk& new_chunk,
+ size_t old_index) const {
+ for (size_t i = old_index; i < old_paint_chunks_info_.size(); i++) {
+ if (new_chunk.Matches(GetOldChunk(i)))
+ return i;
+ }
+ for (size_t i = 0; i < old_index; i++) {
+ if (new_chunk.Matches(GetOldChunk(i)))
+ return i;
+ }
+ return kNotFound;
+}
+
+static bool ApproximatelyEqual(const SkMatrix& a, const SkMatrix& b) {
+ static constexpr float kTolerance = 1e-5f;
+ for (int i = 0; i < 9; i++) {
+ auto difference = std::abs(a[i] - b[i]);
+ // Check for absolute difference.
+ if (difference > kTolerance)
+ return false;
+ // For scale components, also check for relative difference.
+ if ((i == 0 || i == 4 || i == 9) &&
+ difference > (std::abs(a[i]) + std::abs(b[i])) * kTolerance)
+ return false;
+ }
+ return true;
+}
+
+PaintInvalidationReason RasterInvalidator::ChunkPropertiesChanged(
+ const RefCountedPropertyTreeState& new_chunk_state,
+ const RefCountedPropertyTreeState& old_chunk_state,
+ const PaintChunkInfo& new_chunk_info,
+ const PaintChunkInfo& old_chunk_info,
+ const PropertyTreeState& layer_state) const {
+ // Special case for transform changes because we may create or delete some
+ // transform nodes when no raster invalidation is needed. For example, when
+ // a composited layer previously not transformed now gets transformed.
+ // Check for real accumulated transform change instead.
+ if (!ApproximatelyEqual(new_chunk_info.chunk_to_layer_transform,
+ old_chunk_info.chunk_to_layer_transform))
+ return PaintInvalidationReason::kPaintProperty;
+
+ // Treat the chunk property as changed if the effect node pointer is
+ // different, or the effect node's value changed between the layer state and
+ // the chunk state.
+ if (new_chunk_state.Effect() != old_chunk_state.Effect() ||
+ new_chunk_state.Effect()->Changed(layer_state,
+ new_chunk_state.Transform()))
+ return PaintInvalidationReason::kPaintProperty;
+
+ // Check for accumulated clip rect change, if the clip rects are tight.
+ if (new_chunk_info.chunk_to_layer_clip.IsTight() &&
+ old_chunk_info.chunk_to_layer_clip.IsTight()) {
+ if (new_chunk_info.chunk_to_layer_clip ==
+ old_chunk_info.chunk_to_layer_clip)
+ return PaintInvalidationReason::kNone;
+ // Ignore differences out of the current layer bounds.
+ if (ClipByLayerBounds(new_chunk_info.chunk_to_layer_clip.Rect()) ==
+ ClipByLayerBounds(old_chunk_info.chunk_to_layer_clip.Rect()))
+ return PaintInvalidationReason::kNone;
+ return PaintInvalidationReason::kIncremental;
+ }
+
+ // Otherwise treat the chunk property as changed if the clip node pointer is
+ // different, or the clip node's value changed between the layer state and the
+ // chunk state.
+ if (new_chunk_state.Clip() != old_chunk_state.Clip() ||
+ new_chunk_state.Clip()->Changed(layer_state, new_chunk_state.Transform()))
+ return PaintInvalidationReason::kPaintProperty;
+
+ return PaintInvalidationReason::kNone;
+}
+
+// Generates raster invalidations by checking changes (appearing, disappearing,
+// reordering, property changes) of chunks. The logic is similar to
+// PaintController::GenerateRasterInvalidations(). The complexity is between
+// O(n) and O(m*n) where m and n are the numbers of old and new chunks,
+// respectively. Normally both m and n are small numbers. The best caseis that
+// all old chunks have matching new chunks in the same order. The worst case is
+// that no matching chunks except the first one (which always matches otherwise
+// we won't reuse the RasterInvalidator), which is rare. In
+// common cases that most of the chunks can be matched in-order, the complexity
+// is slightly larger than O(n).
+void RasterInvalidator::GenerateRasterInvalidations(
+ const PaintArtifact& new_paint_artifact,
+ const PaintChunkSubset& new_chunks,
+ const PropertyTreeState& layer_state,
+ const FloatSize& visual_rect_subpixel_offset,
+ Vector<PaintChunkInfo>& new_chunks_info) {
+ ChunkToLayerMapper mapper(layer_state, layer_bounds_.OffsetFromOrigin(),
+ visual_rect_subpixel_offset);
+ Vector<bool> old_chunks_matched;
+ old_chunks_matched.resize(old_paint_chunks_info_.size());
+ size_t old_index = 0;
+ size_t max_matched_old_index = 0;
+ for (auto it = new_chunks.begin(); it != new_chunks.end(); ++it) {
+ const auto& new_chunk = *it;
+ mapper.SwitchToChunk(new_chunk);
+ auto& new_chunk_info = new_chunks_info.emplace_back(*this, mapper, it);
+
+ if (!new_chunk.is_cacheable) {
+ AddRasterInvalidation(new_chunk_info.bounds_in_layer, new_chunk.id.client,
+ PaintInvalidationReason::kChunkUncacheable,
+ kClientIsNew);
+ continue;
+ }
+
+ size_t matched_old_index = MatchNewChunkToOldChunk(new_chunk, old_index);
+ if (matched_old_index == kNotFound) {
+ // The new chunk doesn't match any old chunk.
+ AddRasterInvalidation(new_chunk_info.bounds_in_layer, new_chunk.id.client,
+ PaintInvalidationReason::kChunkAppeared,
+ kClientIsNew);
+ continue;
+ }
+
+ DCHECK(!old_chunks_matched[matched_old_index]);
+ old_chunks_matched[matched_old_index] = true;
+
+ auto& old_chunk_info = old_paint_chunks_info_[matched_old_index];
+ const auto& old_chunk = GetOldChunk(matched_old_index);
+ // Clip the old chunk bounds by the new layer bounds.
+ old_chunk_info.bounds_in_layer =
+ ClipByLayerBounds(old_chunk_info.bounds_in_layer);
+
+ PaintInvalidationReason reason =
+ matched_old_index < max_matched_old_index
+ ? PaintInvalidationReason::kChunkReordered
+ : ChunkPropertiesChanged(new_chunk.properties, old_chunk.properties,
+ new_chunk_info, old_chunk_info,
+ layer_state);
+
+ if (IsFullPaintInvalidationReason(reason)) {
+ // Invalidate both old and new bounds of the chunk if the chunk's paint
+ // properties changed, or is moved backward and may expose area that was
+ // previously covered by it.
+ AddRasterInvalidation(old_chunk_info.bounds_in_layer, new_chunk.id.client,
+ reason, kClientIsNew);
+ if (old_chunk_info.bounds_in_layer != new_chunk_info.bounds_in_layer) {
+ AddRasterInvalidation(new_chunk_info.bounds_in_layer,
+ new_chunk.id.client, reason, kClientIsNew);
+ }
+ // Ignore the display item raster invalidations because we have fully
+ // invalidated the chunk.
+ } else {
+ // We may have ignored tiny changes of transform, in which case we should
+ // use the old chunk_to_layer_transform for later comparison to correctly
+ // invalidate animating transform in tiny increments when the accumulated
+ // change exceeds the tolerance.
+ new_chunk_info.chunk_to_layer_transform =
+ old_chunk_info.chunk_to_layer_transform;
+
+ if (reason == PaintInvalidationReason::kIncremental) {
+ IncrementallyInvalidateChunk(old_chunk_info, new_chunk_info,
+ new_chunk.id.client);
+ }
+
+ if (&new_paint_artifact != old_paint_artifact_) {
+ DisplayItemRasterInvalidator(*this, *old_paint_artifact_,
+ new_paint_artifact, old_chunk, new_chunk,
+ mapper)
+ .Generate();
+ }
+ }
+
+ old_index = matched_old_index + 1;
+ if (old_index == old_paint_chunks_info_.size())
+ old_index = 0;
+ max_matched_old_index = std::max(max_matched_old_index, matched_old_index);
+ }
+
+ // Invalidate remaining unmatched (disappeared or uncacheable) old chunks.
+ for (size_t i = 0; i < old_paint_chunks_info_.size(); ++i) {
+ if (old_chunks_matched[i])
+ continue;
+
+ const auto& old_chunk = GetOldChunk(i);
+ auto reason = old_chunk.is_cacheable
+ ? PaintInvalidationReason::kChunkDisappeared
+ : PaintInvalidationReason::kChunkUncacheable;
+ AddRasterInvalidation(old_paint_chunks_info_[i].bounds_in_layer,
+ old_chunk.id.client, reason, kClientIsOld);
+ }
+}
+
+void RasterInvalidator::IncrementallyInvalidateChunk(
+ const PaintChunkInfo& old_chunk_info,
+ const PaintChunkInfo& new_chunk_info,
+ const DisplayItemClient& client) {
+ SkRegion diff(old_chunk_info.bounds_in_layer);
+ diff.op(new_chunk_info.bounds_in_layer, SkRegion::kXOR_Op);
+ for (SkRegion::Iterator it(diff); !it.done(); it.next()) {
+ const SkIRect& r = it.rect();
+ AddRasterInvalidation(IntRect(r.x(), r.y(), r.width(), r.height()), client,
+ PaintInvalidationReason::kIncremental, kClientIsNew);
+ }
+}
+
+void RasterInvalidator::TrackRasterInvalidation(const IntRect& rect,
+ const DisplayItemClient& client,
+ PaintInvalidationReason reason,
+ ClientIsOldOrNew old_or_new) {
+ DCHECK(tracking_info_);
+ String debug_name = old_or_new == kClientIsOld
+ ? tracking_info_->old_client_debug_names.at(&client)
+ : client.DebugName();
+ tracking_info_->tracking.AddInvalidation(&client, debug_name, rect, reason);
+}
+
+RasterInvalidationTracking& RasterInvalidator::EnsureTracking() {
+ if (!tracking_info_)
+ tracking_info_ = std::make_unique<RasterInvalidationTrackingInfo>();
+ return tracking_info_->tracking;
+}
+
+void RasterInvalidator::Generate(
+ scoped_refptr<const PaintArtifact> new_paint_artifact,
+ const gfx::Rect& layer_bounds,
+ const PropertyTreeState& layer_state,
+ const FloatSize& visual_rect_subpixel_offset,
+ const DisplayItemClient* layer_client) {
+ Generate(new_paint_artifact, new_paint_artifact->PaintChunks(), layer_bounds,
+ layer_state, visual_rect_subpixel_offset, layer_client);
+}
+
+void RasterInvalidator::Generate(
+ scoped_refptr<const PaintArtifact> new_paint_artifact,
+ const PaintChunkSubset& paint_chunks,
+ const gfx::Rect& layer_bounds,
+ const PropertyTreeState& layer_state,
+ const FloatSize& visual_rect_subpixel_offset,
+ const DisplayItemClient* layer_client) {
+ if (RasterInvalidationTracking::ShouldAlwaysTrack())
+ EnsureTracking();
+
+ bool layer_bounds_was_empty = layer_bounds_.IsEmpty();
+ layer_bounds_ = layer_bounds;
+
+ Vector<PaintChunkInfo> new_chunks_info;
+ new_chunks_info.ReserveCapacity(paint_chunks.size());
+
+ if (layer_bounds_was_empty || layer_bounds_.IsEmpty()) {
+ // No raster invalidation is needed if either the old bounds or the new
+ // bounds is empty, but we still need to update new_chunks_info for the
+ // next cycle.
+ ChunkToLayerMapper mapper(layer_state, layer_bounds.OffsetFromOrigin(),
+ visual_rect_subpixel_offset);
+ for (auto it = paint_chunks.begin(); it != paint_chunks.end(); ++it) {
+ mapper.SwitchToChunk(*it);
+ new_chunks_info.emplace_back(*this, mapper, it);
+ }
+
+ if (tracking_info_ && layer_bounds_was_empty && !layer_bounds.IsEmpty() &&
+ paint_chunks.size()) {
+ TrackImplicitFullLayerInvalidation(
+ layer_client ? *layer_client : paint_chunks[0].id.client);
+ }
+ } else {
+ GenerateRasterInvalidations(*new_paint_artifact, paint_chunks, layer_state,
+ visual_rect_subpixel_offset, new_chunks_info);
+ }
+
+ if (tracking_info_)
+ UpdateClientDebugNames(*new_paint_artifact, paint_chunks);
+
+ old_paint_chunks_info_ = std::move(new_chunks_info);
+ old_paint_artifact_ = std::move(new_paint_artifact);
+}
+
+void RasterInvalidator::TrackImplicitFullLayerInvalidation(
+ const DisplayItemClient& layer_client) {
+ DCHECK(tracking_info_);
+
+ // Early return if we have already invalidated the whole layer.
+ IntRect full_layer_rect(0, 0, layer_bounds_.width(), layer_bounds_.height());
+ for (const auto& invalidation : tracking_info_->tracking.Invalidations()) {
+ if (invalidation.rect.Contains(full_layer_rect))
+ return;
+ }
+
+ tracking_info_->tracking.AddInvalidation(
+ &layer_client, layer_client.DebugName(), full_layer_rect,
+ PaintInvalidationReason::kFullLayer);
+}
+
+size_t RasterInvalidator::ApproximateUnsharedMemoryUsage() const {
+ return sizeof(*this) +
+ old_paint_chunks_info_.capacity() * sizeof(PaintChunkInfo);
+}
+
+void RasterInvalidator::ClearOldStates() {
+ old_paint_artifact_ = nullptr;
+ old_paint_chunks_info_.clear();
+ layer_bounds_ = gfx::Rect();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h
new file mode 100644
index 00000000000..9a59ad6e61c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h
@@ -0,0 +1,158 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_RASTER_INVALIDATOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_RASTER_INVALIDATOR_H_
+
+#include "third_party/blink/renderer/platform/graphics/compositing/chunk_to_layer_mapper.h"
+#include "third_party/blink/renderer/platform/graphics/paint/float_clip_rect.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_chunk.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_chunk_subset.h"
+#include "third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+class PaintArtifact;
+class IntRect;
+
+class PLATFORM_EXPORT RasterInvalidator {
+ public:
+ using RasterInvalidationFunction = std::function<void(const IntRect&)>;
+
+ RasterInvalidator(RasterInvalidationFunction raster_invalidation_function)
+ : raster_invalidation_function_(raster_invalidation_function) {}
+
+ void SetTracksRasterInvalidations(bool);
+ RasterInvalidationTracking* GetTracking() const {
+ return tracking_info_ ? &tracking_info_->tracking : nullptr;
+ }
+
+ RasterInvalidationTracking& EnsureTracking();
+
+ // Generate raster invalidations for all of the changed paint chunks and
+ // display items in the paint artifact.
+ void Generate(scoped_refptr<const PaintArtifact>,
+ const gfx::Rect& layer_bounds,
+ const PropertyTreeState& layer_state,
+ const FloatSize& visual_rect_subpixel_offset = FloatSize(),
+ const DisplayItemClient* layer_client = nullptr);
+
+ // Generate raster invalidations for a subset of the paint chunks in the
+ // paint artifact.
+ void Generate(scoped_refptr<const PaintArtifact>,
+ const PaintChunkSubset&,
+ const gfx::Rect& layer_bounds,
+ const PropertyTreeState& layer_state,
+ const FloatSize& visual_rect_subpixel_offset = FloatSize(),
+ const DisplayItemClient* layer_client = nullptr);
+
+ const gfx::Rect& LayerBounds() const { return layer_bounds_; }
+
+ size_t ApproximateUnsharedMemoryUsage() const;
+
+ void ClearOldStates();
+
+ private:
+ friend class DisplayItemRasterInvalidator;
+ friend class RasterInvalidatorTest;
+
+ void UpdateClientDebugNames(const PaintArtifact&, const PaintChunkSubset&);
+
+ struct PaintChunkInfo {
+ PaintChunkInfo(const RasterInvalidator& invalidator,
+ const ChunkToLayerMapper& mapper,
+ PaintChunkSubset::Iterator chunk_it)
+ : index_in_paint_artifact(chunk_it.OriginalIndex()),
+#if DCHECK_IS_ON()
+ id(chunk_it->id),
+#endif
+ bounds_in_layer(invalidator.ClipByLayerBounds(
+ mapper.MapVisualRect(chunk_it->bounds))),
+ chunk_to_layer_clip(mapper.ClipRect()),
+ chunk_to_layer_transform(
+ TransformationMatrix::ToSkMatrix44(mapper.Transform())) {
+ }
+
+ // The index of the chunk in the PaintArtifact. It may be different from
+ // the index of this PaintChunkInfo in paint_chunks_info_ when a subset of
+ // the paint chunks is handled by the RasterInvalidator.
+ size_t index_in_paint_artifact;
+
+#if DCHECK_IS_ON()
+ PaintChunk::Id id;
+#endif
+
+ IntRect bounds_in_layer;
+ FloatClipRect chunk_to_layer_clip;
+ SkMatrix chunk_to_layer_transform;
+ };
+
+ void GenerateRasterInvalidations(const PaintArtifact&,
+ const PaintChunkSubset&,
+ const PropertyTreeState& layer_state,
+ const FloatSize& visual_rect_subpixel_offset,
+ Vector<PaintChunkInfo>& new_chunks_info);
+
+ ALWAYS_INLINE const PaintChunk& GetOldChunk(size_t index) const;
+ ALWAYS_INLINE size_t MatchNewChunkToOldChunk(const PaintChunk& new_chunk,
+ size_t old_index) const;
+
+ ALWAYS_INLINE void IncrementallyInvalidateChunk(
+ const PaintChunkInfo& old_chunk_info,
+ const PaintChunkInfo& new_chunk_info,
+ const DisplayItemClient&);
+
+ // |old_or_new| indicates if |client| is known to be new (alive) and we can
+ // get DebugName() directly or should get from |tracking_info_
+ // ->old_client_debug_names|.
+ enum ClientIsOldOrNew { kClientIsOld, kClientIsNew };
+ void AddRasterInvalidation(const IntRect& rect,
+ const DisplayItemClient& client,
+ PaintInvalidationReason reason,
+ ClientIsOldOrNew old_or_new) {
+ if (rect.IsEmpty())
+ return;
+ raster_invalidation_function_(rect);
+ if (tracking_info_)
+ TrackRasterInvalidation(rect, client, reason, old_or_new);
+ }
+ void TrackRasterInvalidation(const IntRect&,
+ const DisplayItemClient&,
+ PaintInvalidationReason,
+ ClientIsOldOrNew);
+
+ ALWAYS_INLINE PaintInvalidationReason
+ ChunkPropertiesChanged(const RefCountedPropertyTreeState& new_chunk_state,
+ const RefCountedPropertyTreeState& old_chunk_state,
+ const PaintChunkInfo& new_chunk_info,
+ const PaintChunkInfo& old_chunk_info,
+ const PropertyTreeState& layer_state) const;
+
+ // Clip a rect in the layer space by the layer bounds.
+ template <typename Rect>
+ Rect ClipByLayerBounds(const Rect& r) const {
+ return Intersection(
+ r, Rect(0, 0, layer_bounds_.width(), layer_bounds_.height()));
+ }
+
+ void TrackImplicitFullLayerInvalidation(const DisplayItemClient&);
+
+ RasterInvalidationFunction raster_invalidation_function_;
+ gfx::Rect layer_bounds_;
+ Vector<PaintChunkInfo> old_paint_chunks_info_;
+ scoped_refptr<const PaintArtifact> old_paint_artifact_;
+
+ struct RasterInvalidationTrackingInfo {
+ using ClientDebugNamesMap = HashMap<const DisplayItemClient*, String>;
+ ClientDebugNamesMap old_client_debug_names;
+ RasterInvalidationTracking tracking;
+ };
+ std::unique_ptr<RasterInvalidationTrackingInfo> tracking_info_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_RASTER_INVALIDATOR_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator_test.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator_test.cc
new file mode 100644
index 00000000000..7f8306e2703
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/raster_invalidator_test.cc
@@ -0,0 +1,691 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/graphics/paint/raster_invalidator.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
+#include "third_party/blink/renderer/platform/testing/paint_property_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/test_paint_artifact.h"
+
+namespace blink {
+
+static const IntRect kDefaultLayerBounds(-9999, -7777, 18888, 16666);
+
+class RasterInvalidatorTest : public testing::Test {
+ public:
+ static PropertyTreeState DefaultPropertyTreeState() {
+ return PropertyTreeState::Root();
+ }
+
+ void ClearGeometryMapperCache() {
+ GeometryMapperTransformCache::ClearCache();
+ GeometryMapperClipCache::ClearCache();
+ }
+
+ void SetUp() override { ClearGeometryMapperCache(); }
+ void TearDown() override { ClearGeometryMapperCache(); }
+
+ void FinishCycle(PaintArtifact& artifact) {
+ artifact.FinishCycle();
+ ClearGeometryMapperCache();
+ }
+
+ static const Vector<RasterInvalidationInfo> TrackedRasterInvalidations(
+ RasterInvalidator& invalidator) {
+ DCHECK(invalidator.GetTracking());
+ return invalidator.GetTracking()->Invalidations();
+ }
+
+ static IntRect ChunkRectToLayer(
+ const FloatRect& rect,
+ const IntPoint& layer_offset,
+ std::function<void(FloatRect&)> mapper = nullptr) {
+ FloatRect r = rect;
+ if (mapper)
+ mapper(r);
+ r.MoveBy(FloatPoint(layer_offset));
+ return EnclosingIntRect(r);
+ }
+
+ RasterInvalidator::RasterInvalidationFunction kNoopRasterInvalidation =
+ [](const IntRect& rect) {};
+};
+
+#define EXPECT_CHUNK_INVALIDATION_CUSTOM( \
+ invalidations, index, chunk, expected_reason, layer_offset, mapper) \
+ do { \
+ const auto& info = (invalidations)[index]; \
+ EXPECT_EQ(ChunkRectToLayer((chunk).bounds, layer_offset, mapper), \
+ info.rect); \
+ EXPECT_EQ(&(chunk).id.client, info.client); \
+ EXPECT_EQ(expected_reason, info.reason); \
+ } while (false)
+
+#define EXPECT_CHUNK_INVALIDATION(invalidations, index, chunk, reason) \
+ EXPECT_CHUNK_INVALIDATION_CUSTOM(invalidations, index, chunk, reason, \
+ -kDefaultLayerBounds.Location(), nullptr)
+
+#define EXPECT_INCREMENTAL_INVALIDATION(invalidations, index, chunk, \
+ chunk_rect) \
+ do { \
+ const auto& info = (invalidations)[index]; \
+ EXPECT_EQ(ChunkRectToLayer(chunk_rect, -kDefaultLayerBounds.Location()), \
+ info.rect); \
+ EXPECT_EQ(&(chunk).id.client, info.client); \
+ EXPECT_EQ(PaintInvalidationReason::kIncremental, info.reason); \
+ } while (false)
+
+TEST_F(RasterInvalidatorTest, ImplicitFullLayerInvalidation) {
+ RasterInvalidator invalidator(kNoopRasterInvalidation);
+ auto artifact = TestPaintArtifact().Chunk(0).Build();
+
+ invalidator.SetTracksRasterInvalidations(true);
+ invalidator.Generate(artifact, kDefaultLayerBounds,
+ DefaultPropertyTreeState());
+ const auto& invalidations = TrackedRasterInvalidations(invalidator);
+ ASSERT_EQ(1u, invalidations.size());
+ EXPECT_EQ(IntRect(IntPoint(), kDefaultLayerBounds.Size()),
+ invalidations[0].rect);
+ EXPECT_EQ(PaintInvalidationReason::kFullLayer, invalidations[0].reason);
+ FinishCycle(*artifact);
+ invalidator.SetTracksRasterInvalidations(false);
+}
+
+TEST_F(RasterInvalidatorTest, LayerBounds) {
+ RasterInvalidator invalidator(kNoopRasterInvalidation);
+ auto artifact = TestPaintArtifact().Chunk(0).Build();
+
+ invalidator.Generate(artifact, kDefaultLayerBounds,
+ DefaultPropertyTreeState());
+ FinishCycle(*artifact);
+
+ invalidator.SetTracksRasterInvalidations(true);
+ invalidator.Generate(artifact, kDefaultLayerBounds,
+ DefaultPropertyTreeState());
+ // No raster invalidations needed if layer origin doesn't change.
+ EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
+
+ auto new_layer_bounds = kDefaultLayerBounds;
+ new_layer_bounds.Move(66, 77);
+ invalidator.Generate(artifact, new_layer_bounds, DefaultPropertyTreeState());
+ // Change of layer origin causes change of chunk0's transform to layer.
+ const auto& invalidations = TrackedRasterInvalidations(invalidator);
+ ASSERT_EQ(2u, invalidations.size());
+ EXPECT_CHUNK_INVALIDATION(invalidations, 0, artifact->PaintChunks()[0],
+ PaintInvalidationReason::kPaintProperty);
+ EXPECT_CHUNK_INVALIDATION_CUSTOM(invalidations, 1, artifact->PaintChunks()[0],
+ PaintInvalidationReason::kPaintProperty,
+ -new_layer_bounds.Location(), nullptr);
+ FinishCycle(*artifact);
+}
+
+TEST_F(RasterInvalidatorTest, ReorderChunks) {
+ RasterInvalidator invalidator(kNoopRasterInvalidation);
+ auto artifact = TestPaintArtifact().Chunk(0).Chunk(1).Chunk(2).Build();
+ invalidator.Generate(artifact, kDefaultLayerBounds,
+ DefaultPropertyTreeState());
+ FinishCycle(*artifact);
+
+ // Swap chunk 1 and 2.
+ invalidator.SetTracksRasterInvalidations(true);
+ auto new_artifact = TestPaintArtifact()
+ .Chunk(0)
+ .Chunk(2)
+ .Chunk(1)
+ .Bounds(FloatRect(11, 22, 33, 44))
+ .Build();
+ invalidator.Generate(new_artifact, kDefaultLayerBounds,
+ DefaultPropertyTreeState());
+ const auto& invalidations = TrackedRasterInvalidations(invalidator);
+ ASSERT_EQ(2u, invalidations.size());
+ // Invalidated new chunk 2's old (as artifact->PaintChunks()[1]) and new
+ // (as new_artifact->PaintChunks()[2]) bounds.
+ EXPECT_CHUNK_INVALIDATION(invalidations, 0, artifact->PaintChunks()[1],
+ PaintInvalidationReason::kChunkReordered);
+ EXPECT_CHUNK_INVALIDATION(invalidations, 1, new_artifact->PaintChunks()[2],
+ PaintInvalidationReason::kChunkReordered);
+ FinishCycle(*new_artifact);
+}
+
+TEST_F(RasterInvalidatorTest, ReorderChunkSubsequences) {
+ RasterInvalidator invalidator(kNoopRasterInvalidation);
+ auto artifact =
+ TestPaintArtifact().Chunk(0).Chunk(1).Chunk(2).Chunk(3).Chunk(4).Build();
+ invalidator.Generate(artifact, kDefaultLayerBounds,
+ DefaultPropertyTreeState());
+ FinishCycle(*artifact);
+
+ // Swap chunk (1,2) and (3,4).
+ invalidator.SetTracksRasterInvalidations(true);
+ auto new_artifact = TestPaintArtifact()
+ .Chunk(0)
+ .Chunk(3)
+ .Chunk(4)
+ .Chunk(1)
+ .Bounds(FloatRect(11, 22, 33, 44))
+ .Chunk(2)
+ .Build();
+ invalidator.Generate(new_artifact, kDefaultLayerBounds,
+ DefaultPropertyTreeState());
+ const auto& invalidations = TrackedRasterInvalidations(invalidator);
+ ASSERT_EQ(3u, invalidations.size());
+ // Invalidated new chunk 3's old (as artifact->PaintChunks()[1] and new
+ // (as new_artifact->PaintChunks()[3]) bounds.
+ EXPECT_CHUNK_INVALIDATION(invalidations, 0, artifact->PaintChunks()[1],
+ PaintInvalidationReason::kChunkReordered);
+ EXPECT_CHUNK_INVALIDATION(invalidations, 1, new_artifact->PaintChunks()[3],
+ PaintInvalidationReason::kChunkReordered);
+ // Invalidated new chunk 4's new bounds. Didn't invalidate old bounds because
+ // it's the same as the new bounds.
+ EXPECT_CHUNK_INVALIDATION(invalidations, 2, new_artifact->PaintChunks()[4],
+ PaintInvalidationReason::kChunkReordered);
+ FinishCycle(*new_artifact);
+}
+
+TEST_F(RasterInvalidatorTest, ChunkAppearAndDisappear) {
+ RasterInvalidator invalidator(kNoopRasterInvalidation);
+ auto artifact = TestPaintArtifact().Chunk(0).Chunk(1).Chunk(2).Build();
+ invalidator.Generate(artifact, kDefaultLayerBounds,
+ DefaultPropertyTreeState());
+ FinishCycle(*artifact);
+
+ // Chunk 1 and 2 disappeared, 3 and 4 appeared.
+ invalidator.SetTracksRasterInvalidations(true);
+ auto new_artifact = TestPaintArtifact().Chunk(0).Chunk(3).Chunk(4).Build();
+ invalidator.Generate(new_artifact, kDefaultLayerBounds,
+ DefaultPropertyTreeState());
+ const auto& invalidations = TrackedRasterInvalidations(invalidator);
+ ASSERT_EQ(4u, invalidations.size());
+ EXPECT_CHUNK_INVALIDATION(invalidations, 0, new_artifact->PaintChunks()[1],
+ PaintInvalidationReason::kChunkAppeared);
+ EXPECT_CHUNK_INVALIDATION(invalidations, 1, new_artifact->PaintChunks()[2],
+ PaintInvalidationReason::kChunkAppeared);
+ EXPECT_CHUNK_INVALIDATION(invalidations, 2, artifact->PaintChunks()[1],
+ PaintInvalidationReason::kChunkDisappeared);
+ EXPECT_CHUNK_INVALIDATION(invalidations, 3, artifact->PaintChunks()[2],
+ PaintInvalidationReason::kChunkDisappeared);
+ FinishCycle(*new_artifact);
+}
+
+TEST_F(RasterInvalidatorTest, ChunkAppearAtEnd) {
+ RasterInvalidator invalidator(kNoopRasterInvalidation);
+ auto artifact = TestPaintArtifact().Chunk(0).Build();
+ invalidator.Generate(artifact, kDefaultLayerBounds,
+ DefaultPropertyTreeState());
+ FinishCycle(*artifact);
+
+ invalidator.SetTracksRasterInvalidations(true);
+ auto new_artifact = TestPaintArtifact().Chunk(0).Chunk(1).Chunk(2).Build();
+ invalidator.Generate(new_artifact, kDefaultLayerBounds,
+ DefaultPropertyTreeState());
+ const auto& invalidations = TrackedRasterInvalidations(invalidator);
+ ASSERT_EQ(2u, invalidations.size());
+ EXPECT_CHUNK_INVALIDATION(invalidations, 0, new_artifact->PaintChunks()[1],
+ PaintInvalidationReason::kChunkAppeared);
+ EXPECT_CHUNK_INVALIDATION(invalidations, 1, new_artifact->PaintChunks()[2],
+ PaintInvalidationReason::kChunkAppeared);
+ FinishCycle(*new_artifact);
+}
+
+TEST_F(RasterInvalidatorTest, UncacheableChunks) {
+ RasterInvalidator invalidator(kNoopRasterInvalidation);
+ auto artifact =
+ TestPaintArtifact().Chunk(0).Chunk(1).Uncacheable().Chunk(2).Build();
+
+ invalidator.Generate(artifact, kDefaultLayerBounds,
+ DefaultPropertyTreeState());
+ FinishCycle(*artifact);
+
+ invalidator.SetTracksRasterInvalidations(true);
+ auto new_artifact =
+ TestPaintArtifact().Chunk(0).Chunk(2).Chunk(1).Uncacheable().Build();
+ invalidator.Generate(new_artifact, kDefaultLayerBounds,
+ DefaultPropertyTreeState());
+ const auto& invalidations = TrackedRasterInvalidations(invalidator);
+ ASSERT_EQ(2u, invalidations.size());
+ EXPECT_CHUNK_INVALIDATION(invalidations, 0, new_artifact->PaintChunks()[2],
+ PaintInvalidationReason::kChunkUncacheable);
+ EXPECT_CHUNK_INVALIDATION(invalidations, 1, artifact->PaintChunks()[1],
+ PaintInvalidationReason::kChunkUncacheable);
+ FinishCycle(*new_artifact);
+}
+
+// Tests the path based on ClipPaintPropertyNode::Changed().
+TEST_F(RasterInvalidatorTest, ClipPropertyChangeRounded) {
+ RasterInvalidator invalidator(kNoopRasterInvalidation);
+ FloatRoundedRect::Radii radii(FloatSize(1, 2), FloatSize(2, 3),
+ FloatSize(3, 4), FloatSize(4, 5));
+ FloatRoundedRect clip_rect(FloatRect(-1000, -1000, 2000, 2000), radii);
+ auto clip0 = CreateClip(c0(), &t0(), clip_rect);
+ auto clip2 = CreateClip(*clip0, &t0(), clip_rect);
+
+ PropertyTreeState layer_state(&t0(), clip0.get(), &e0());
+ auto artifact = TestPaintArtifact()
+ .Chunk(0)
+ .Properties(layer_state)
+ .Chunk(1)
+ .Properties(layer_state)
+ .Chunk(2)
+ .Properties(t0(), *clip2, e0())
+ .Build();
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ FinishCycle(*artifact);
+
+ // Change both clip0 and clip2.
+ invalidator.SetTracksRasterInvalidations(true);
+ FloatRoundedRect new_clip_rect(FloatRect(-2000, -2000, 4000, 4000), radii);
+ clip0->Update(*clip0->Parent(),
+ ClipPaintPropertyNode::State{clip0->LocalTransformSpace(),
+ new_clip_rect});
+ clip2->Update(*clip2->Parent(),
+ ClipPaintPropertyNode::State{clip2->LocalTransformSpace(),
+ new_clip_rect});
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ const auto& invalidations = TrackedRasterInvalidations(invalidator);
+ ASSERT_EQ(1u, invalidations.size());
+ // Property change in the layer state should not trigger raster invalidation.
+ // |clip2| change should trigger raster invalidation.
+ EXPECT_CHUNK_INVALIDATION(invalidations, 0, artifact->PaintChunks()[2],
+ PaintInvalidationReason::kPaintProperty);
+ invalidator.SetTracksRasterInvalidations(false);
+ FinishCycle(*artifact);
+
+ // Change chunk1's properties to use a different property tree state.
+ auto new_artifact1 = TestPaintArtifact()
+ .Chunk(0)
+ .Properties(artifact->PaintChunks()[0].properties)
+ .Chunk(1)
+ .Properties(artifact->PaintChunks()[2].properties)
+ .Chunk(2)
+ .Properties(artifact->PaintChunks()[2].properties)
+ .Build();
+
+ invalidator.SetTracksRasterInvalidations(true);
+ invalidator.Generate(new_artifact1, kDefaultLayerBounds, layer_state);
+ const auto& invalidations1 = TrackedRasterInvalidations(invalidator);
+ ASSERT_EQ(1u, invalidations1.size());
+ EXPECT_CHUNK_INVALIDATION(invalidations1, 0, new_artifact1->PaintChunks()[1],
+ PaintInvalidationReason::kPaintProperty);
+ invalidator.SetTracksRasterInvalidations(false);
+ FinishCycle(*new_artifact1);
+}
+
+// Tests the path detecting change of PaintChunkInfo::chunk_to_layer_clip.
+TEST_F(RasterInvalidatorTest, ClipPropertyChangeSimple) {
+ RasterInvalidator invalidator(kNoopRasterInvalidation);
+ FloatRoundedRect clip_rect(-1000, -1000, 2000, 2000);
+ auto clip0 = CreateClip(c0(), &t0(), clip_rect);
+ auto clip1 = CreateClip(*clip0, &t0(), clip_rect);
+
+ PropertyTreeState layer_state = PropertyTreeState::Root();
+ auto artifact = TestPaintArtifact()
+ .Chunk(0)
+ .Properties(t0(), *clip0, e0())
+ .Bounds(clip_rect.Rect())
+ .Chunk(1)
+ .Properties(t0(), *clip1, e0())
+ .Bounds(clip_rect.Rect())
+ .Build();
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ FinishCycle(*artifact);
+
+ // Change clip1 to bigger, which is still bound by clip0, resulting no actual
+ // visual change.
+ invalidator.SetTracksRasterInvalidations(true);
+ FloatRoundedRect new_clip_rect1(-2000, -2000, 4000, 4000);
+ clip1->Update(*clip1->Parent(),
+ ClipPaintPropertyNode::State{clip1->LocalTransformSpace(),
+ new_clip_rect1});
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
+ FinishCycle(*artifact);
+
+ // Change clip1 to smaller.
+ FloatRoundedRect new_clip_rect2(-500, -500, 1000, 1000);
+ clip1->Update(*clip1->Parent(),
+ ClipPaintPropertyNode::State{clip1->LocalTransformSpace(),
+ new_clip_rect2});
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ const auto& invalidations = TrackedRasterInvalidations(invalidator);
+ ASSERT_EQ(4u, invalidations.size());
+ // |clip1| change should trigger incremental raster invalidation.
+ EXPECT_INCREMENTAL_INVALIDATION(invalidations, 0, artifact->PaintChunks()[1],
+ FloatRect(-1000, -1000, 2000, 500));
+ EXPECT_INCREMENTAL_INVALIDATION(invalidations, 1, artifact->PaintChunks()[1],
+ FloatRect(-1000, -500, 500, 1000));
+ EXPECT_INCREMENTAL_INVALIDATION(invalidations, 2, artifact->PaintChunks()[1],
+ FloatRect(500, -500, 500, 1000));
+ EXPECT_INCREMENTAL_INVALIDATION(invalidations, 3, artifact->PaintChunks()[1],
+ FloatRect(-1000, 500, 2000, 500));
+ invalidator.SetTracksRasterInvalidations(false);
+ FinishCycle(*artifact);
+
+ // Change clip1 bigger at one side.
+ FloatRoundedRect new_clip_rect3(-500, -500, 2000, 1000);
+ clip1->Update(*clip1->Parent(),
+ ClipPaintPropertyNode::State{clip1->LocalTransformSpace(),
+ new_clip_rect3});
+
+ invalidator.SetTracksRasterInvalidations(true);
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ const auto& invalidations1 = TrackedRasterInvalidations(invalidator);
+ ASSERT_EQ(1u, invalidations1.size());
+ // |clip1| change should trigger incremental raster invalidation.
+ EXPECT_INCREMENTAL_INVALIDATION(invalidations1, 0, artifact->PaintChunks()[1],
+ FloatRect(500, -500, 500, 1000));
+ invalidator.SetTracksRasterInvalidations(false);
+ FinishCycle(*artifact);
+}
+
+TEST_F(RasterInvalidatorTest, ClipLocalTransformSpaceChange) {
+ RasterInvalidator invalidator(kNoopRasterInvalidation);
+
+ auto t1 = CreateTransform(t0(), TransformationMatrix());
+ auto t2 = CreateTransform(*t1, TransformationMatrix());
+
+ FloatRoundedRect::Radii radii(FloatSize(1, 2), FloatSize(2, 3),
+ FloatSize(3, 4), FloatSize(4, 5));
+ FloatRoundedRect clip_rect(FloatRect(-1000, -1000, 2000, 2000), radii);
+ auto c1 = CreateClip(c0(), t1.get(), clip_rect);
+
+ PropertyTreeState layer_state(&t0(), &c0(), &e0());
+ auto artifact =
+ TestPaintArtifact().Chunk(0).Properties(*t2, *c1, e0()).Build();
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ FinishCycle(*artifact);
+
+ // Change both t1 and t2 but keep t1*t2 unchanged, to test change of
+ // LocalTransformSpace of c1.
+ invalidator.SetTracksRasterInvalidations(true);
+ t1->Update(t0(), TransformPaintPropertyNode::State{
+ TransformationMatrix().Translate(-10, -20)});
+ t2->Update(*t1, TransformPaintPropertyNode::State{
+ TransformationMatrix().Translate(10, 20)});
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ const auto& invalidations = TrackedRasterInvalidations(invalidator);
+ ASSERT_EQ(1u, invalidations.size());
+ EXPECT_CHUNK_INVALIDATION(invalidations, 0, artifact->PaintChunks()[0],
+ PaintInvalidationReason::kPaintProperty);
+ invalidator.SetTracksRasterInvalidations(false);
+}
+
+// This is based on ClipLocalTransformSpaceChange, but tests the no-invalidation
+// path by letting the clip's LocalTransformSpace be the same as the chunk's
+// transform.
+TEST_F(RasterInvalidatorTest, ClipLocalTransformSpaceChangeNoInvalidation) {
+ RasterInvalidator invalidator(kNoopRasterInvalidation);
+
+ auto t1 = CreateTransform(t0(), TransformationMatrix());
+ auto t2 = CreateTransform(*t1, TransformationMatrix());
+
+ FloatRoundedRect::Radii radii(FloatSize(1, 2), FloatSize(2, 3),
+ FloatSize(3, 4), FloatSize(4, 5));
+ FloatRoundedRect clip_rect(FloatRect(-1000, -1000, 2000, 2000), radii);
+ // This set is different from ClipLocalTransformSpaceChange.
+ auto c1 = CreateClip(c0(), t2.get(), clip_rect);
+
+ PropertyTreeState layer_state(&t0(), &c0(), &e0());
+ auto artifact =
+ TestPaintArtifact().Chunk(0).Properties(*t2, *c1, e0()).Build();
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ FinishCycle(*artifact);
+
+ // Change both t1 and t2 but keep t1*t2 unchanged.
+ invalidator.SetTracksRasterInvalidations(true);
+ t1->Update(t0(), TransformPaintPropertyNode::State{
+ TransformationMatrix().Translate(-10, -20)});
+ t2->Update(*t1, TransformPaintPropertyNode::State{
+ TransformationMatrix().Translate(10, 20)});
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
+ FinishCycle(*artifact);
+}
+
+TEST_F(RasterInvalidatorTest, TransformPropertyChange) {
+ RasterInvalidator invalidator(kNoopRasterInvalidation);
+
+ auto layer_transform = CreateTransform(t0(), TransformationMatrix().Scale(5));
+ auto transform0 = CreateTransform(*layer_transform,
+ TransformationMatrix().Translate(10, 20));
+ auto transform1 =
+ CreateTransform(*transform0, TransformationMatrix().Translate(-50, -60));
+
+ PropertyTreeState layer_state(layer_transform.get(), &c0(), &e0());
+ auto artifact = TestPaintArtifact()
+ .Chunk(0)
+ .Properties(*transform0, c0(), e0())
+ .Chunk(1)
+ .Properties(*transform1, c0(), e0())
+ .Build();
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ FinishCycle(*artifact);
+
+ // Change layer_transform should not cause raster invalidation in the layer.
+ invalidator.SetTracksRasterInvalidations(true);
+ layer_transform->Update(
+ *layer_transform->Parent(),
+ TransformPaintPropertyNode::State{TransformationMatrix().Scale(10)});
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
+ FinishCycle(*artifact);
+
+ // Inserting another node between layer_transform and transform0 and letting
+ // the new node become the transform of the layer state should not cause
+ // raster invalidation in the layer. This simulates a composited layer is
+ // scrolled from its original location.
+ auto new_layer_transform = CreateTransform(
+ *layer_transform, TransformationMatrix().Translate(-100, -200));
+ layer_state = PropertyTreeState(new_layer_transform.get(), &c0(), &e0());
+ transform0->Update(*new_layer_transform,
+ TransformPaintPropertyNode::State{transform0->Matrix()});
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
+ FinishCycle(*artifact);
+
+ // Removing transform nodes above the layer state should not cause raster
+ // invalidation in the layer.
+ layer_state = DefaultPropertyTreeState();
+ transform0->Update(*layer_state.Transform(),
+ TransformPaintPropertyNode::State{transform0->Matrix()});
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
+ FinishCycle(*artifact);
+
+ // Change transform0 and transform1, while keeping the combined transform0
+ // and transform1 unchanged for chunk 2. We should invalidate only chunk 0
+ // for changed paint property.
+ transform0->Update(
+ *layer_state.Transform(),
+ TransformPaintPropertyNode::State{
+ TransformationMatrix(transform0->Matrix()).Translate(20, 30)});
+ transform1->Update(
+ *transform0,
+ TransformPaintPropertyNode::State{
+ TransformationMatrix(transform1->Matrix()).Translate(-20, -30)});
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ const auto& invalidations = TrackedRasterInvalidations(invalidator);
+ ASSERT_EQ(2u, invalidations.size());
+ auto mapper0 = [](FloatRect& r) { r.Move(10, 20); };
+ EXPECT_CHUNK_INVALIDATION_CUSTOM(invalidations, 0, artifact->PaintChunks()[0],
+ PaintInvalidationReason::kPaintProperty,
+ -kDefaultLayerBounds.Location(), mapper0);
+ auto mapper1 = [](FloatRect& r) { r.Move(30, 50); };
+ EXPECT_CHUNK_INVALIDATION_CUSTOM(invalidations, 1, artifact->PaintChunks()[0],
+ PaintInvalidationReason::kPaintProperty,
+ -kDefaultLayerBounds.Location(), mapper1);
+ invalidator.SetTracksRasterInvalidations(false);
+ FinishCycle(*artifact);
+}
+
+TEST_F(RasterInvalidatorTest, TransformPropertyTinyChange) {
+ RasterInvalidator invalidator(kNoopRasterInvalidation);
+
+ auto layer_transform = CreateTransform(t0(), TransformationMatrix().Scale(5));
+ auto chunk_transform = CreateTransform(
+ *layer_transform, TransformationMatrix().Translate(10, 20));
+
+ PropertyTreeState layer_state(layer_transform.get(), &c0(), &e0());
+ auto artifact = TestPaintArtifact()
+ .Chunk(0)
+ .Properties(*chunk_transform, c0(), e0())
+ .Build();
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ FinishCycle(*artifact);
+
+ // Change chunk_transform by tiny difference, which should be ignored.
+ invalidator.SetTracksRasterInvalidations(true);
+ chunk_transform->Update(*layer_state.Transform(),
+ TransformPaintPropertyNode::State{
+ TransformationMatrix(chunk_transform->Matrix())
+ .Translate(0.0000001, -0.0000001)
+ .Scale(1.0000001)
+ .Rotate(0.0000001)});
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
+ FinishCycle(*artifact);
+
+ // Tiny differences should accumulate and cause invalidation when the
+ // accumulation is large enough.
+ bool invalidated = false;
+ for (int i = 0; i < 100 && !invalidated; i++) {
+ chunk_transform->Update(*layer_state.Transform(),
+ TransformPaintPropertyNode::State{
+ TransformationMatrix(chunk_transform->Matrix())
+ .Translate(0.0000001, -0.0000001)
+ .Scale(1.0000001)
+ .Rotate(0.0000001)});
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ invalidated = !TrackedRasterInvalidations(invalidator).IsEmpty();
+ FinishCycle(*artifact);
+ }
+ EXPECT_TRUE(invalidated);
+}
+
+TEST_F(RasterInvalidatorTest, TransformPropertyTinyChangeScale) {
+ RasterInvalidator invalidator(kNoopRasterInvalidation);
+
+ auto layer_transform = CreateTransform(t0(), TransformationMatrix().Scale(5));
+ auto chunk_transform =
+ CreateTransform(*layer_transform, TransformationMatrix().Scale(1e-6));
+ FloatRect chunk_bounds(0, 0, 10000000, 10000000);
+
+ PropertyTreeState layer_state(layer_transform.get(), &c0(), &e0());
+ auto artifact = TestPaintArtifact()
+ .Chunk(0)
+ .Properties(*chunk_transform, c0(), e0())
+ .Bounds(chunk_bounds)
+ .Build();
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ FinishCycle(*artifact);
+
+ // Scale change from 1e-6 to 2e-6 should be treated as significant.
+ invalidator.SetTracksRasterInvalidations(true);
+ chunk_transform->Update(
+ *layer_state.Transform(),
+ TransformPaintPropertyNode::State{TransformationMatrix().Scale(2e-6)});
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ EXPECT_FALSE(TrackedRasterInvalidations(invalidator).IsEmpty());
+ invalidator.SetTracksRasterInvalidations(false);
+ FinishCycle(*artifact);
+
+ // Scale change from 2e-6 to 2e-6 + 1e-15 should be ignored.
+ invalidator.SetTracksRasterInvalidations(true);
+ chunk_transform->Update(*layer_state.Transform(),
+ TransformPaintPropertyNode::State{
+ TransformationMatrix().Scale(2e-6 + 1e-15)});
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
+ invalidator.SetTracksRasterInvalidations(false);
+ FinishCycle(*artifact);
+}
+
+TEST_F(RasterInvalidatorTest, EffectLocalTransformSpaceChange) {
+ RasterInvalidator invalidator(kNoopRasterInvalidation);
+
+ auto t1 = CreateTransform(t0(), TransformationMatrix());
+ auto t2 = CreateTransform(*t1, TransformationMatrix());
+ CompositorFilterOperations filter;
+ filter.AppendBlurFilter(20);
+ auto e1 = CreateFilterEffect(e0(), t1.get(), &c0(), filter);
+
+ PropertyTreeState layer_state(&t0(), &c0(), &e0());
+ auto artifact =
+ TestPaintArtifact().Chunk(0).Properties(*t2, c0(), *e1).Build();
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ FinishCycle(*artifact);
+
+ // Change both t1 and t2 but keep t1*t2 unchanged, to test change of
+ // LocalTransformSpace of e1.
+ invalidator.SetTracksRasterInvalidations(true);
+ t1->Update(t0(), TransformPaintPropertyNode::State{
+ TransformationMatrix().Translate(-10, -20)});
+ t2->Update(*t1, TransformPaintPropertyNode::State{
+ TransformationMatrix().Translate(10, 20)});
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ const auto& invalidations = TrackedRasterInvalidations(invalidator);
+ ASSERT_EQ(1u, invalidations.size());
+ auto mapper = [](FloatRect& r) { r.Inflate(60); };
+ EXPECT_CHUNK_INVALIDATION_CUSTOM(invalidations, 0, artifact->PaintChunks()[0],
+ PaintInvalidationReason::kPaintProperty,
+ -kDefaultLayerBounds.Location(), mapper);
+ invalidator.SetTracksRasterInvalidations(false);
+ FinishCycle(*artifact);
+}
+
+// This is based on EffectLocalTransformSpaceChange, but tests the no-
+// invalidation path by letting the effect's LocalTransformSpace be the same as
+// the chunk's transform.
+TEST_F(RasterInvalidatorTest, EffectLocalTransformSpaceChangeNoInvalidation) {
+ RasterInvalidator invalidator(kNoopRasterInvalidation);
+
+ auto t1 = CreateTransform(t0(), TransformationMatrix());
+ auto t2 = CreateTransform(*t1, TransformationMatrix());
+ // This setup is different from EffectLocalTransformSpaceChange.
+ CompositorFilterOperations filter;
+ filter.AppendBlurFilter(20);
+ auto e1 = CreateFilterEffect(e0(), t2.get(), &c0(), filter);
+
+ PropertyTreeState layer_state(&t0(), &c0(), &e0());
+ auto artifact =
+ TestPaintArtifact().Chunk(0).Properties(*t2, c0(), *e1).Build();
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ FinishCycle(*artifact);
+
+ // Change both t1 and t2 but keep t1*t2 unchanged.
+ invalidator.SetTracksRasterInvalidations(true);
+ t1->Update(t0(), TransformPaintPropertyNode::State{
+ TransformationMatrix().Translate(-10, -20)});
+ t2->Update(*t1, TransformPaintPropertyNode::State{
+ TransformationMatrix().Translate(10, 20)});
+
+ invalidator.Generate(artifact, kDefaultLayerBounds, layer_state);
+ EXPECT_TRUE(TrackedRasterInvalidations(invalidator).IsEmpty());
+ FinishCycle(*artifact);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/ref_counted_property_tree_state.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/ref_counted_property_tree_state.cc
index 1003213e594..43fb4206792 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/ref_counted_property_tree_state.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/ref_counted_property_tree_state.cc
@@ -12,8 +12,8 @@ const RefCountedPropertyTreeState& RefCountedPropertyTreeState::Root() {
DEFINE_STATIC_LOCAL(
std::unique_ptr<RefCountedPropertyTreeState>, root,
(std::make_unique<RefCountedPropertyTreeState>(
- TransformPaintPropertyNode::Root(), ClipPaintPropertyNode::Root(),
- EffectPaintPropertyNode::Root())));
+ &TransformPaintPropertyNode::Root(), &ClipPaintPropertyNode::Root(),
+ &EffectPaintPropertyNode::Root())));
return *root;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_display_item_fragment.h b/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_display_item_fragment.h
index d0cef181f33..792cf122951 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_display_item_fragment.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_display_item_fragment.h
@@ -5,16 +5,15 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCOPED_DISPLAY_ITEM_FRAGMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCOPED_DISPLAY_ITEM_FRAGMENT_H_
+#include "base/macros.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
namespace blink {
class ScopedDisplayItemFragment final {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
- WTF_MAKE_NONCOPYABLE(ScopedDisplayItemFragment);
public:
ScopedDisplayItemFragment(GraphicsContext& context, unsigned fragment)
@@ -29,6 +28,8 @@ class ScopedDisplayItemFragment final {
private:
GraphicsContext& context_;
unsigned original_fragment_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedDisplayItemFragment);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h b/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h
index 4a7d064377e..2522ea2818a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h
@@ -5,19 +5,18 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCOPED_PAINT_CHUNK_PROPERTIES_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCOPED_PAINT_CHUNK_PROPERTIES_H_
+#include "base/macros.h"
#include "base/optional.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_chunk.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
namespace blink {
class ScopedPaintChunkProperties {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
- WTF_MAKE_NONCOPYABLE(ScopedPaintChunkProperties);
public:
// Use new PropertyTreeState for the scope.
@@ -104,6 +103,8 @@ class ScopedPaintChunkProperties {
PaintController& paint_controller_;
PropertyTreeState previous_properties_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedPaintChunkProperties);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_display_item.cc
deleted file mode 100644
index 673094d245b..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_display_item.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/paint/scroll_display_item.h"
-
-#include "cc/paint/display_item_list.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-
-namespace blink {
-
-void BeginScrollDisplayItem::Replay(GraphicsContext& context) const {
- context.Save();
- context.Translate(-current_offset_.Width(), -current_offset_.Height());
-}
-
-void BeginScrollDisplayItem::AppendToDisplayItemList(
- const FloatSize&,
- cc::DisplayItemList& list) const {
- list.StartPaint();
- list.push<cc::SaveOp>();
- list.push<cc::TranslateOp>(static_cast<float>(-current_offset_.Width()),
- static_cast<float>(-current_offset_.Height()));
- list.EndPaintOfPairedBegin();
-}
-
-#if DCHECK_IS_ON()
-void BeginScrollDisplayItem::PropertiesAsJSON(JSONObject& json) const {
- PairedBeginDisplayItem::PropertiesAsJSON(json);
- json.SetString("currentOffset", current_offset_.ToString());
-}
-#endif
-
-void EndScrollDisplayItem::Replay(GraphicsContext& context) const {
- context.Restore();
-}
-
-void EndScrollDisplayItem::AppendToDisplayItemList(
- const FloatSize&,
- cc::DisplayItemList& list) const {
- list.StartPaint();
- list.push<cc::RestoreOp>();
- list.EndPaintOfPairedEnd();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_display_item.h
deleted file mode 100644
index c4136bbebb2..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_display_item.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCROLL_DISPLAY_ITEM_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCROLL_DISPLAY_ITEM_H_
-
-#include "third_party/blink/renderer/platform/geometry/int_size.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT BeginScrollDisplayItem final
- : public PairedBeginDisplayItem {
- public:
- BeginScrollDisplayItem(const DisplayItemClient& client,
- Type type,
- const IntSize& current_offset)
- : PairedBeginDisplayItem(client, type, sizeof(*this)),
- current_offset_(current_offset) {
- DCHECK(IsScrollType(type));
- }
-
- void Replay(GraphicsContext&) const override;
- void AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList&) const override;
-
- const IntSize& CurrentOffset() const { return current_offset_; }
-
- private:
-#if DCHECK_IS_ON()
- void PropertiesAsJSON(JSONObject&) const final;
-#endif
- bool Equals(const DisplayItem& other) const final {
- return DisplayItem::Equals(other) &&
- current_offset_ == static_cast<const BeginScrollDisplayItem&>(other)
- .current_offset_;
- }
-
- const IntSize current_offset_;
-};
-
-class PLATFORM_EXPORT EndScrollDisplayItem final : public PairedEndDisplayItem {
- public:
- EndScrollDisplayItem(const DisplayItemClient& client, Type type)
- : PairedEndDisplayItem(client, type, sizeof(*this)) {
- DCHECK(IsEndScrollType(type));
- }
-
- void Replay(GraphicsContext&) const override;
- void AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
- bool IsEndAndPairedWith(DisplayItem::Type other_type) const final {
- return DisplayItem::IsScrollType(other_type);
- }
-#endif
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCROLL_DISPLAY_ITEM_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc
index 8426d1f928c..aa79d6d87d4 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.cc
@@ -12,14 +12,12 @@ namespace blink {
ScrollHitTestDisplayItem::ScrollHitTestDisplayItem(
const DisplayItemClient& client,
- Type type,
- scoped_refptr<const TransformPaintPropertyNode> scroll_offset_node)
- : DisplayItem(client, type, sizeof(*this)),
- scroll_offset_node_(std::move(scroll_offset_node)) {
+ const TransformPaintPropertyNode& scroll_offset_node)
+ : DisplayItem(client, kScrollHitTest, sizeof(*this)),
+ scroll_offset_node_(scroll_offset_node) {
DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
- DCHECK(IsScrollHitTestType(type));
// The scroll offset transform node should have an associated scroll node.
- DCHECK(scroll_offset_node_->ScrollNode());
+ DCHECK(scroll_offset_node_.ScrollNode());
}
ScrollHitTestDisplayItem::~ScrollHitTestDisplayItem() = default;
@@ -44,27 +42,26 @@ bool ScrollHitTestDisplayItem::Equals(const DisplayItem& other) const {
void ScrollHitTestDisplayItem::PropertiesAsJSON(JSONObject& json) const {
DisplayItem::PropertiesAsJSON(json);
json.SetString("scrollOffsetNode",
- String::Format("%p", scroll_offset_node_.get()));
+ String::Format("%p", &scroll_offset_node_));
}
#endif
void ScrollHitTestDisplayItem::Record(
GraphicsContext& context,
const DisplayItemClient& client,
- DisplayItem::Type type,
- scoped_refptr<const TransformPaintPropertyNode> scroll_offset_node) {
+ const TransformPaintPropertyNode& scroll_offset_node) {
PaintController& paint_controller = context.GetPaintController();
// The scroll hit test should be in the non-scrolled transform space and
// therefore should not be scrolled by the associated scroll offset.
DCHECK_NE(paint_controller.CurrentPaintChunkProperties().Transform(),
- scroll_offset_node.get());
+ &scroll_offset_node);
if (paint_controller.DisplayItemConstructionIsDisabled())
return;
paint_controller.CreateAndAppend<ScrollHitTestDisplayItem>(
- client, type, std::move(scroll_offset_node));
+ client, scroll_offset_node);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h
index fb9b5cd7a02..4642790e9f8 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h
@@ -26,12 +26,11 @@ class PLATFORM_EXPORT ScrollHitTestDisplayItem final : public DisplayItem {
public:
ScrollHitTestDisplayItem(
const DisplayItemClient&,
- Type,
- scoped_refptr<const TransformPaintPropertyNode> scroll_offset_node);
+ const TransformPaintPropertyNode& scroll_offset_node);
~ScrollHitTestDisplayItem() override;
const TransformPaintPropertyNode& scroll_offset_node() const {
- return *scroll_offset_node_;
+ return scroll_offset_node_;
}
// DisplayItem
@@ -46,18 +45,16 @@ class PLATFORM_EXPORT ScrollHitTestDisplayItem final : public DisplayItem {
// Create and append a ScrollHitTestDisplayItem onto the context. This is
// similar to a recorder class (e.g., DrawingRecorder) but just emits a single
// item.
- static void Record(
- GraphicsContext&,
- const DisplayItemClient&,
- DisplayItem::Type,
- scoped_refptr<const TransformPaintPropertyNode> scroll_offset_node);
+ static void Record(GraphicsContext&,
+ const DisplayItemClient&,
+ const TransformPaintPropertyNode& scroll_offset_node);
private:
const ScrollPaintPropertyNode& scroll_node() const {
- return *scroll_offset_node_->ScrollNode();
+ return *scroll_offset_node_.ScrollNode();
}
- scoped_refptr<const TransformPaintPropertyNode> scroll_offset_node_;
+ const TransformPaintPropertyNode& scroll_offset_node_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.cc
index 0329c33a0f4..743ab2ccf8c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.cc
@@ -6,10 +6,11 @@
namespace blink {
-ScrollPaintPropertyNode* ScrollPaintPropertyNode::Root() {
- DEFINE_STATIC_REF(ScrollPaintPropertyNode, root,
- (ScrollPaintPropertyNode::Create(nullptr, State{})));
- return root;
+const ScrollPaintPropertyNode& ScrollPaintPropertyNode::Root() {
+ DEFINE_STATIC_REF(
+ ScrollPaintPropertyNode, root,
+ base::AdoptRef(new ScrollPaintPropertyNode(nullptr, State{})));
+ return *root;
}
std::unique_ptr<JSONObject> ScrollPaintPropertyNode::ToJSON() const {
@@ -33,6 +34,12 @@ std::unique_ptr<JSONObject> ScrollPaintPropertyNode::ToJSON() const {
MainThreadScrollingReason::AsText(state_.main_thread_scrolling_reasons)
.c_str());
}
+ if (state_.scrolls_inner_viewport)
+ json->SetString("scrollsInnerViewport", "true");
+ if (state_.scrolls_outer_viewport)
+ json->SetString("scrollsOuterViewport", "true");
+ if (state_.max_scroll_offset_affected_by_page_scale)
+ json->SetString("maxScrollOffsetAffectedByPageScale", "true");
if (state_.compositor_element_id) {
json->SetString("compositorElementId",
state_.compositor_element_id.ToString().c_str());
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.h b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.h
index 80bdd359d10..e4b93dfbd2a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/scroll_paint_property_node.h
@@ -39,6 +39,9 @@ class PLATFORM_EXPORT ScrollPaintPropertyNode
IntRect contents_rect;
bool user_scrollable_horizontal = false;
bool user_scrollable_vertical = false;
+ bool scrolls_inner_viewport = false;
+ bool scrolls_outer_viewport = false;
+ bool max_scroll_offset_affected_by_page_scale = false;
MainThreadScrollingReasons main_thread_scrolling_reasons =
MainThreadScrollingReason::kNotScrollingOnMain;
// The scrolling element id is stored directly on the scroll node and not on
@@ -50,24 +53,27 @@ class PLATFORM_EXPORT ScrollPaintPropertyNode
contents_rect == o.contents_rect &&
user_scrollable_horizontal == o.user_scrollable_horizontal &&
user_scrollable_vertical == o.user_scrollable_vertical &&
+ scrolls_inner_viewport == o.scrolls_inner_viewport &&
+ scrolls_outer_viewport == o.scrolls_outer_viewport &&
+ max_scroll_offset_affected_by_page_scale ==
+ o.max_scroll_offset_affected_by_page_scale &&
main_thread_scrolling_reasons == o.main_thread_scrolling_reasons &&
compositor_element_id == o.compositor_element_id;
}
};
// This node is really a sentinel, and does not represent a real scroll.
- static ScrollPaintPropertyNode* Root();
+ static const ScrollPaintPropertyNode& Root();
static scoped_refptr<ScrollPaintPropertyNode> Create(
- scoped_refptr<const ScrollPaintPropertyNode> parent,
+ const ScrollPaintPropertyNode& parent,
State&& state) {
return base::AdoptRef(
- new ScrollPaintPropertyNode(std::move(parent), std::move(state)));
+ new ScrollPaintPropertyNode(&parent, std::move(state)));
}
- bool Update(scoped_refptr<const ScrollPaintPropertyNode> parent,
- State&& state) {
- bool parent_changed = SetParent(parent);
+ bool Update(const ScrollPaintPropertyNode& parent, State&& state) {
+ bool parent_changed = SetParent(&parent);
if (state == state_)
return parent_changed;
@@ -93,6 +99,11 @@ class PLATFORM_EXPORT ScrollPaintPropertyNode
bool UserScrollableVertical() const {
return state_.user_scrollable_vertical;
}
+ bool ScrollsInnerViewport() const { return state_.scrolls_inner_viewport; }
+ bool ScrollsOuterViewport() const { return state_.scrolls_outer_viewport; }
+ bool MaxScrollOffsetAffectedByPageScale() const {
+ return state_.max_scroll_offset_affected_by_page_scale;
+ }
// Return reason bitfield with values from cc::MainThreadScrollingReason.
MainThreadScrollingReasons GetMainThreadScrollingReasons() const {
@@ -132,9 +143,8 @@ class PLATFORM_EXPORT ScrollPaintPropertyNode
std::unique_ptr<JSONObject> ToJSON() const;
private:
- ScrollPaintPropertyNode(scoped_refptr<const ScrollPaintPropertyNode> parent,
- State&& state)
- : PaintPropertyNode(std::move(parent)), state_(std::move(state)) {
+ ScrollPaintPropertyNode(const ScrollPaintPropertyNode* parent, State&& state)
+ : PaintPropertyNode(parent), state_(std::move(state)) {
Validate();
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/subsequence_recorder.h b/chromium/third_party/blink/renderer/platform/graphics/paint/subsequence_recorder.h
index d5609bec997..8cc4af20c08 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/subsequence_recorder.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/subsequence_recorder.h
@@ -5,11 +5,11 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SUBSEQUENCE_RECORDER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SUBSEQUENCE_RECORDER_H_
+#include "base/macros.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
namespace blink {
@@ -28,7 +28,6 @@ class PaintController;
//
class SubsequenceRecorder final {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
- WTF_MAKE_NONCOPYABLE(SubsequenceRecorder);
public:
static bool UseCachedSubsequenceIfPossible(GraphicsContext& context,
@@ -53,6 +52,8 @@ class SubsequenceRecorder final {
PaintController& paint_controller_;
const DisplayItemClient& client_;
size_t start_;
+
+ DISALLOW_COPY_AND_ASSIGN(SubsequenceRecorder);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.cc
deleted file mode 100644
index 91f9a1e2525..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.h"
-
-#include "cc/paint/display_item_list.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
-
-namespace blink {
-
-void BeginTransform3DDisplayItem::Replay(GraphicsContext& context) const {
- TransformationMatrix transform(transform_);
- transform.ApplyTransformOrigin(transform_origin_);
- context.Save();
- context.ConcatCTM(transform.ToAffineTransform());
-}
-
-void BeginTransform3DDisplayItem::AppendToDisplayItemList(
- const FloatSize&,
- cc::DisplayItemList& list) const {
- // TODO(jbroman): The compositor will need the transform origin separately.
- TransformationMatrix transform(transform_);
- transform.ApplyTransformOrigin(transform_origin_);
-
- list.StartPaint();
- list.push<cc::SaveOp>();
- if (!transform.IsIdentity()) {
- list.push<cc::ConcatOp>(
- static_cast<SkMatrix>(TransformationMatrix::ToSkMatrix44(transform)));
- }
- list.EndPaintOfPairedBegin();
-}
-
-#if DCHECK_IS_ON()
-void BeginTransform3DDisplayItem::PropertiesAsJSON(JSONObject& json) const {
- PairedBeginDisplayItem::PropertiesAsJSON(json);
- json.SetString("transform", transform_.ToString());
- json.SetString("origin", transform_origin_.ToString());
-}
-#endif
-
-void EndTransform3DDisplayItem::Replay(GraphicsContext& context) const {
- context.Restore();
-}
-
-void EndTransform3DDisplayItem::AppendToDisplayItemList(
- const FloatSize&,
- cc::DisplayItemList& list) const {
- list.StartPaint();
- list.push<cc::RestoreOp>();
- list.EndPaintOfPairedEnd();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.h
deleted file mode 100644
index df63b22f978..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_TRANSFORM_3D_DISPLAY_ITEM_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_TRANSFORM_3D_DISPLAY_ITEM_H_
-
-#include "third_party/blink/renderer/platform/geometry/float_point_3d.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT BeginTransform3DDisplayItem final
- : public PairedBeginDisplayItem {
- public:
- BeginTransform3DDisplayItem(const DisplayItemClient& client,
- Type type,
- const TransformationMatrix& transform,
- const FloatPoint3D& transform_origin)
- : PairedBeginDisplayItem(client, type, sizeof(*this)),
- transform_(transform),
- transform_origin_(transform_origin) {
- DCHECK(DisplayItem::IsTransform3DType(type));
- }
-
- void Replay(GraphicsContext&) const override;
- void AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList&) const override;
-
- const TransformationMatrix& Transform() const { return transform_; }
- const FloatPoint3D& TransformOrigin() const { return transform_origin_; }
-
- private:
-#if DCHECK_IS_ON()
- void PropertiesAsJSON(JSONObject&) const final;
-#endif
- bool Equals(const DisplayItem& other) const final {
- return DisplayItem::Equals(other) &&
- transform_ == static_cast<const BeginTransform3DDisplayItem&>(other)
- .transform_ &&
- transform_origin_ ==
- static_cast<const BeginTransform3DDisplayItem&>(other)
- .transform_origin_;
- }
-
- const TransformationMatrix transform_;
- const FloatPoint3D transform_origin_;
-};
-
-class PLATFORM_EXPORT EndTransform3DDisplayItem final
- : public PairedEndDisplayItem {
- public:
- EndTransform3DDisplayItem(const DisplayItemClient& client, Type type)
- : PairedEndDisplayItem(client, type, sizeof(*this)) {
- DCHECK(DisplayItem::IsEndTransform3DType(type));
- }
-
- void Replay(GraphicsContext&) const override;
- void AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
- bool IsEndAndPairedWith(DisplayItem::Type other_type) const final {
- return DisplayItem::Transform3DTypeToEndTransform3DType(other_type) ==
- GetType();
- }
-#endif
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_TRANSFORM_3D_DISPLAY_ITEM_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/transform_display_item.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/transform_display_item.cc
deleted file mode 100644
index e0d45085f61..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/transform_display_item.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/paint/transform_display_item.h"
-
-#include "cc/paint/display_item_list.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
-
-namespace blink {
-
-void BeginTransformDisplayItem::Replay(GraphicsContext& context) const {
- context.Save();
- context.ConcatCTM(transform_);
-}
-
-void BeginTransformDisplayItem::AppendToDisplayItemList(
- const FloatSize&,
- cc::DisplayItemList& list) const {
- list.StartPaint();
- list.push<cc::SaveOp>();
- if (!transform_.IsIdentity())
- list.push<cc::ConcatOp>(AffineTransformToSkMatrix(transform_));
- list.EndPaintOfPairedBegin();
-}
-
-#if DCHECK_IS_ON()
-void BeginTransformDisplayItem::PropertiesAsJSON(JSONObject& json) const {
- PairedBeginDisplayItem::PropertiesAsJSON(json);
- json.SetString("transform", transform_.ToString());
-}
-#endif
-
-void EndTransformDisplayItem::Replay(GraphicsContext& context) const {
- context.Restore();
-}
-
-void EndTransformDisplayItem::AppendToDisplayItemList(
- const FloatSize&,
- cc::DisplayItemList& list) const {
- list.StartPaint();
- list.push<cc::RestoreOp>();
- list.EndPaintOfPairedEnd();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/transform_display_item.h b/chromium/third_party/blink/renderer/platform/graphics/paint/transform_display_item.h
deleted file mode 100644
index a684f7b7f10..00000000000
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/transform_display_item.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_TRANSFORM_DISPLAY_ITEM_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_TRANSFORM_DISPLAY_ITEM_H_
-
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT BeginTransformDisplayItem final
- : public PairedBeginDisplayItem {
- public:
- BeginTransformDisplayItem(const DisplayItemClient& client,
- const AffineTransform& transform)
- : PairedBeginDisplayItem(client, kBeginTransform, sizeof(*this)),
- transform_(transform) {}
-
- void Replay(GraphicsContext&) const override;
- void AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList&) const override;
-
- const AffineTransform& Transform() const { return transform_; }
-
- private:
-#if DCHECK_IS_ON()
- void PropertiesAsJSON(JSONObject&) const final;
-#endif
- bool Equals(const DisplayItem& other) const final {
- return DisplayItem::Equals(other) &&
- transform_ ==
- static_cast<const BeginTransformDisplayItem&>(other).transform_;
- }
-
- const AffineTransform transform_;
-};
-
-class PLATFORM_EXPORT EndTransformDisplayItem final
- : public PairedEndDisplayItem {
- public:
- EndTransformDisplayItem(const DisplayItemClient& client)
- : PairedEndDisplayItem(client, kEndTransform, sizeof(*this)) {}
-
- void Replay(GraphicsContext&) const override;
- void AppendToDisplayItemList(const FloatSize&,
- cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
- bool IsEndAndPairedWith(DisplayItem::Type other_type) const final {
- return other_type == kBeginTransform;
- }
-#endif
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_TRANSFORM_DISPLAY_ITEM_H_
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.cc b/chromium/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.cc
index cc75a09fe68..80a709bd278 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.cc
@@ -8,15 +8,15 @@ namespace blink {
// The root of the transform tree. The root transform node references the root
// scroll node.
-TransformPaintPropertyNode* TransformPaintPropertyNode::Root() {
+const TransformPaintPropertyNode& TransformPaintPropertyNode::Root() {
DEFINE_STATIC_REF(
TransformPaintPropertyNode, root,
base::AdoptRef(new TransformPaintPropertyNode(
nullptr,
State{TransformationMatrix(), FloatPoint3D(), false,
BackfaceVisibility::kVisible, 0, CompositingReason::kNone,
- CompositorElementId(), ScrollPaintPropertyNode::Root()})));
- return root;
+ CompositorElementId(), &ScrollPaintPropertyNode::Root()})));
+ return *root;
}
const TransformPaintPropertyNode&
@@ -31,10 +31,26 @@ TransformPaintPropertyNode::NearestScrollTranslationNode() const {
return *transform;
}
+bool TransformPaintPropertyNode::Changed(
+ const TransformPaintPropertyNode& relative_to_node) const {
+ for (const auto* node = this; node; node = node->Parent()) {
+ if (node == &relative_to_node)
+ return false;
+ if (node->NodeChanged())
+ return true;
+ }
+
+ // |this| is not a descendant of |relative_to_node|. We have seen no changed
+ // flag from |this| to the root. Now check |relative_to_node| to the root.
+ return relative_to_node.Changed(Root());
+}
+
std::unique_ptr<JSONObject> TransformPaintPropertyNode::ToJSON() const {
auto json = JSONObject::Create();
if (Parent())
json->SetString("parent", String::Format("%p", Parent()));
+ if (NodeChanged())
+ json->SetBoolean("changed", true);
if (!state_.matrix.IsIdentity())
json->SetString("matrix", state_.matrix.ToString());
if (!state_.matrix.IsIdentityOrTranslation())
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h b/chromium/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h
index 9e33f591430..6de51874451 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h
@@ -63,18 +63,17 @@ class PLATFORM_EXPORT TransformPaintPropertyNode
// This node is really a sentinel, and does not represent a real transform
// space.
- static TransformPaintPropertyNode* Root();
+ static const TransformPaintPropertyNode& Root();
static scoped_refptr<TransformPaintPropertyNode> Create(
- scoped_refptr<const TransformPaintPropertyNode> parent,
+ const TransformPaintPropertyNode& parent,
State&& state) {
return base::AdoptRef(
- new TransformPaintPropertyNode(std::move(parent), std::move(state)));
+ new TransformPaintPropertyNode(&parent, std::move(state)));
}
- bool Update(scoped_refptr<const TransformPaintPropertyNode> parent,
- State&& state) {
- bool parent_changed = SetParent(parent);
+ bool Update(const TransformPaintPropertyNode& parent, State&& state) {
+ bool parent_changed = SetParent(&parent);
if (state == state_)
return parent_changed;
@@ -84,6 +83,12 @@ class PLATFORM_EXPORT TransformPaintPropertyNode
return true;
}
+ // If |relative_to_node| is an ancestor of |this|, returns true if any node is
+ // marked changed along the path from |this| to |relative_to_node| (not
+ // included). Otherwise returns the combined changed status of the paths
+ // from |this| and |relative_to_node| to the root.
+ bool Changed(const TransformPaintPropertyNode& relative_to_node) const;
+
const TransformationMatrix& Matrix() const { return state_.matrix; }
const FloatPoint3D& Origin() const { return state_.origin; }
@@ -147,10 +152,9 @@ class PLATFORM_EXPORT TransformPaintPropertyNode
size_t CacheMemoryUsageInBytes() const;
private:
- TransformPaintPropertyNode(
- scoped_refptr<const TransformPaintPropertyNode> parent,
- State&& state)
- : PaintPropertyNode(std::move(parent)), state_(std::move(state)) {
+ TransformPaintPropertyNode(const TransformPaintPropertyNode* parent,
+ State&& state)
+ : PaintPropertyNode(parent), state_(std::move(state)) {
Validate();
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.cc b/chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.cc
index e09c3b5e8fb..45dbceb5bad 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.cc
@@ -6,11 +6,12 @@
#include "third_party/blink/renderer/platform/geometry/float_rect.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record.h"
namespace blink {
-void PaintGeneratedImage::Draw(PaintCanvas* canvas,
+void PaintGeneratedImage::Draw(cc::PaintCanvas* canvas,
const PaintFlags& flags,
const FloatRect& dest_rect,
const FloatRect& src_rect,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.h b/chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.h
index 074b828cdc6..06fb89c4dd4 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint_generated_image.h
@@ -21,8 +21,8 @@ class PLATFORM_EXPORT PaintGeneratedImage : public GeneratedImage {
~PaintGeneratedImage() override = default;
protected:
- void Draw(PaintCanvas*,
- const PaintFlags&,
+ void Draw(cc::PaintCanvas*,
+ const cc::PaintFlags&,
const FloatRect&,
const FloatRect&,
RespectImageOrientationEnum,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.cc b/chromium/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.cc
index e2d2623ab27..37861d191bd 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.cc
@@ -16,6 +16,8 @@ const char* PaintInvalidationReasonToString(PaintInvalidationReason reason) {
return "incremental";
case PaintInvalidationReason::kRectangle:
return "invalidate paint rectangle";
+ case PaintInvalidationReason::kHitTest:
+ return "hit testing change";
case PaintInvalidationReason::kFull:
return "full";
case PaintInvalidationReason::kStyle:
@@ -50,6 +52,12 @@ const char* PaintInvalidationReasonToString(PaintInvalidationReason reason) {
return "DocumentMarker change";
case PaintInvalidationReason::kImage:
return "image";
+ case PaintInvalidationReason::kUncacheable:
+ return "uncacheable";
+ case PaintInvalidationReason::kJustCreated:
+ return "just created";
+ case PaintInvalidationReason::kReordered:
+ return "reordered";
case PaintInvalidationReason::kChunkAppeared:
return "chunk appeared";
case PaintInvalidationReason::kChunkDisappeared:
@@ -60,6 +68,8 @@ const char* PaintInvalidationReasonToString(PaintInvalidationReason reason) {
return "chunk reordered";
case PaintInvalidationReason::kPaintProperty:
return "paint property change";
+ case PaintInvalidationReason::kFullLayer:
+ return "full layer";
case PaintInvalidationReason::kForTesting:
return "for testing";
case PaintInvalidationReason::kDelayedFull:
diff --git a/chromium/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h b/chromium/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h
index 43b9c79d6aa..8afacba30df 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h
@@ -7,23 +7,29 @@
#include <iosfwd>
#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
-enum class PaintInvalidationReason : unsigned {
+enum class PaintInvalidationReason : uint8_t {
kNone,
kIncremental,
kRectangle,
+ kSelection,
+ // Hit test changes do not require raster invalidation.
+ kHitTest,
// The following reasons will all cause full paint invalidation.
- kFull, // Any unspecified reason of full invalidation.
+ // Any unspecified reason of full invalidation.
+ kFull,
kStyle,
- kGeometry, // Layout or visual geometry change.
+ // Layout or visual geometry change.
+ kGeometry,
kCompositing,
kAppeared,
kDisappeared,
kScroll,
- kScrollControl, // scroll bars, scroll corner, etc.
- kSelection,
+ // Scroll bars, scroll corner, etc.
+ kScrollControl,
kOutline,
kSubtree,
kSVGResource,
@@ -32,11 +38,18 @@ enum class PaintInvalidationReason : unsigned {
kCaret,
kDocumentMarker,
kImage,
+ kUncacheable,
+ // The initial PaintInvalidationReason of a DisplayItemClient.
+ kJustCreated,
+ kReordered,
kChunkAppeared,
kChunkDisappeared,
kChunkUncacheable,
kChunkReordered,
kPaintProperty,
+ // For tracking of direct raster invalidation of full composited layers. The
+ // invalidation may be implicit, e.g. when a layer is created.
+ kFullLayer,
kForTesting,
// kDelayedFull means that kFull is needed in order to fully paint the
// content, but that painting of the object can be delayed until a future
@@ -51,6 +64,10 @@ PLATFORM_EXPORT const char* PaintInvalidationReasonToString(
PaintInvalidationReason);
inline bool IsFullPaintInvalidationReason(PaintInvalidationReason reason) {
+ // LayoutNG fully invalidates selections on NGPaintFragments.
+ // TODO(wangxianzhu): Move kSelection after kFull for LayoutNG.
+ if (RuntimeEnabledFeatures::LayoutNGEnabled())
+ return reason >= PaintInvalidationReason::kSelection;
return reason >= PaintInvalidationReason::kFull;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/path.cc b/chromium/third_party/blink/renderer/platform/graphics/path.cc
index 3a90e063342..1da4c73fe4e 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/path.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/path.cc
@@ -353,7 +353,7 @@ void Path::AddEllipse(const FloatPoint& p,
bool anticlockwise) {
DCHECK(EllipseIsRenderable(start_angle, end_angle));
DCHECK_GE(start_angle, 0);
- DCHECK_LT(start_angle, twoPiFloat);
+ DCHECK_LT(start_angle, kTwoPiFloat);
DCHECK((anticlockwise && (start_angle - end_angle) >= 0) ||
(!anticlockwise && (end_angle - start_angle) >= 0));
@@ -367,8 +367,8 @@ void Path::AddEllipse(const FloatPoint& p,
cy + radius_y_scalar);
float sweep = end_angle - start_angle;
- SkScalar start_degrees = WebCoreFloatToSkScalar(start_angle * 180 / piFloat);
- SkScalar sweep_degrees = WebCoreFloatToSkScalar(sweep * 180 / piFloat);
+ SkScalar start_degrees = WebCoreFloatToSkScalar(start_angle * 180 / kPiFloat);
+ SkScalar sweep_degrees = WebCoreFloatToSkScalar(sweep * 180 / kPiFloat);
SkScalar s360 = SkIntToScalar(360);
// We can't use SkPath::addOval(), because addOval() makes a new sub-path.
@@ -415,7 +415,7 @@ void Path::AddEllipse(const FloatPoint& p,
bool anticlockwise) {
DCHECK(EllipseIsRenderable(start_angle, end_angle));
DCHECK_GE(start_angle, 0);
- DCHECK_LT(start_angle, twoPiFloat);
+ DCHECK_LT(start_angle, kTwoPiFloat);
DCHECK((anticlockwise && (start_angle - end_angle) >= 0) ||
(!anticlockwise && (end_angle - start_angle) >= 0));
@@ -535,8 +535,9 @@ bool Path::IntersectPath(const Path& other) {
}
bool EllipseIsRenderable(float start_angle, float end_angle) {
- return (std::abs(end_angle - start_angle) < twoPiFloat) ||
- WebCoreFloatNearlyEqual(std::abs(end_angle - start_angle), twoPiFloat);
+ return (std::abs(end_angle - start_angle) < kTwoPiFloat) ||
+ WebCoreFloatNearlyEqual(std::abs(end_angle - start_angle),
+ kTwoPiFloat);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/path.h b/chromium/third_party/blink/renderer/platform/graphics/path.h
index 058fc75be98..395e02313a4 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/path.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/path.h
@@ -199,13 +199,13 @@ class PLATFORM_EXPORT Path {
SkPath path_;
};
-class PLATFORM_EXPORT RefCountedPath : public Path,
+class PLATFORM_EXPORT RefCountedPath : public blink::Path,
public RefCounted<RefCountedPath> {
USING_FAST_MALLOC(RefCountedPath);
public:
template <typename... Args>
- RefCountedPath(Args&&... args) : Path(std::forward<Args>(args)...) {}
+ RefCountedPath(Args&&... args) : blink::Path(std::forward<Args>(args)...) {}
};
// Only used for DCHECKs
diff --git a/chromium/third_party/blink/renderer/platform/graphics/pattern.h b/chromium/third_party/blink/renderer/platform/graphics/pattern.h
index 72bb655b20a..821b360ebaa 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/pattern.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/pattern.h
@@ -29,12 +29,12 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PATTERN_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PATTERN_H_
+#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_shader.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
#include "third_party/skia/include/core/SkRefCnt.h"
@@ -43,7 +43,6 @@ class SkMatrix;
namespace blink {
class PLATFORM_EXPORT Pattern : public RefCounted<Pattern> {
- WTF_MAKE_NONCOPYABLE(Pattern);
public:
enum RepeatMode {
@@ -62,7 +61,7 @@ class PLATFORM_EXPORT Pattern : public RefCounted<Pattern> {
RepeatMode = kRepeatModeXY);
virtual ~Pattern();
- void ApplyToFlags(PaintFlags&, const SkMatrix&);
+ void ApplyToFlags(cc::PaintFlags&, const SkMatrix&);
bool IsRepeatX() const { return repeat_mode_ & kRepeatModeX; }
bool IsRepeatY() const { return repeat_mode_ & kRepeatModeY; }
@@ -78,6 +77,9 @@ class PLATFORM_EXPORT Pattern : public RefCounted<Pattern> {
Pattern(RepeatMode);
mutable sk_sp<PaintShader> cached_shader_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Pattern);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/picture_snapshot.cc b/chromium/third_party/blink/renderer/platform/graphics/picture_snapshot.cc
index 4e674990b21..20da31898b3 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/picture_snapshot.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/picture_snapshot.cc
@@ -88,9 +88,9 @@ bool PictureSnapshot::IsEmpty() const {
return picture_->cullRect().isEmpty();
}
-std::unique_ptr<Vector<char>> PictureSnapshot::Replay(unsigned from_step,
- unsigned to_step,
- double scale) const {
+Vector<char> PictureSnapshot::Replay(unsigned from_step,
+ unsigned to_step,
+ double scale) const {
const SkIRect bounds = picture_->cullRect().roundOut();
int width = ceil(scale * bounds.width());
int height = ceil(scale * bounds.height());
@@ -113,7 +113,7 @@ std::unique_ptr<Vector<char>> PictureSnapshot::Replay(unsigned from_step,
canvas.ResetStepCount();
picture_->playback(&canvas, &canvas);
}
- std::unique_ptr<Vector<char>> base64_data = std::make_unique<Vector<char>>();
+ Vector<char> base64_data;
Vector<char> encoded_image;
SkPixmap src;
@@ -123,37 +123,34 @@ std::unique_ptr<Vector<char>> PictureSnapshot::Replay(unsigned from_step,
SkPngEncoder::Options options;
options.fFilterFlags = SkPngEncoder::FilterFlag::kSub;
options.fZLibLevel = 3;
- options.fUnpremulBehavior = SkTransferFunctionBehavior::kIgnore;
if (!ImageEncoder::Encode(
reinterpret_cast<Vector<unsigned char>*>(&encoded_image), src,
options)) {
- return nullptr;
+ return Vector<char>();
}
- Base64Encode(encoded_image, *base64_data);
+ Base64Encode(encoded_image, base64_data);
return base64_data;
}
-std::unique_ptr<PictureSnapshot::Timings> PictureSnapshot::Profile(
+Vector<Vector<TimeDelta>> PictureSnapshot::Profile(
unsigned min_repeat_count,
- double min_duration,
+ TimeDelta min_duration,
const FloatRect* clip_rect) const {
- std::unique_ptr<PictureSnapshot::Timings> timings =
- std::make_unique<PictureSnapshot::Timings>();
- timings->ReserveCapacity(min_repeat_count);
+ Vector<Vector<TimeDelta>> timings;
+ timings.ReserveInitialCapacity(min_repeat_count);
const SkIRect bounds = picture_->cullRect().roundOut();
SkBitmap bitmap;
bitmap.allocPixels(
SkImageInfo::MakeN32Premul(bounds.width(), bounds.height()));
bitmap.eraseARGB(0, 0, 0, 0);
- double now = WTF::CurrentTimeTicksInSeconds();
- double stop_time = now + min_duration;
+ TimeTicks now = WTF::CurrentTimeTicks();
+ TimeTicks stop_time = now + min_duration;
for (unsigned step = 0; step < min_repeat_count || now < stop_time; ++step) {
- timings->push_back(Vector<double>());
- Vector<double>* current_timings = &timings->back();
- if (timings->size() > 1)
- current_timings->ReserveCapacity(timings->begin()->size());
+ Vector<TimeDelta> current_timings;
+ if (!timings.IsEmpty())
+ current_timings.ReserveInitialCapacity(timings.front().size());
ProfilingCanvas canvas(bitmap);
if (clip_rect) {
canvas.clipRect(SkRect::MakeXYWH(clip_rect->X(), clip_rect->Y(),
@@ -161,9 +158,10 @@ std::unique_ptr<PictureSnapshot::Timings> PictureSnapshot::Profile(
clip_rect->Height()));
canvas.ResetStepCount();
}
- canvas.SetTimings(current_timings);
+ canvas.SetTimings(&current_timings);
picture_->playback(&canvas);
- now = WTF::CurrentTimeTicksInSeconds();
+ timings.push_back(std::move(current_timings));
+ now = WTF::CurrentTimeTicks();
}
return timings;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/picture_snapshot.h b/chromium/third_party/blink/renderer/platform/graphics/picture_snapshot.h
index 6a7b1ae4b6b..aa9cbb1d27f 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/picture_snapshot.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/picture_snapshot.h
@@ -33,10 +33,12 @@
#include <memory>
+#include "base/macros.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/json/json_values.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
+#include "third_party/blink/renderer/platform/wtf/time.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "third_party/skia/include/core/SkRefCnt.h"
@@ -46,11 +48,8 @@ namespace blink {
class FloatRect;
class PLATFORM_EXPORT PictureSnapshot : public RefCounted<PictureSnapshot> {
- WTF_MAKE_NONCOPYABLE(PictureSnapshot);
public:
- typedef Vector<Vector<double>> Timings;
-
struct TilePictureStream : RefCounted<TilePictureStream> {
FloatPoint layer_offset;
Vector<char> data;
@@ -61,12 +60,12 @@ class PLATFORM_EXPORT PictureSnapshot : public RefCounted<PictureSnapshot> {
PictureSnapshot(sk_sp<const SkPicture>);
- std::unique_ptr<Vector<char>> Replay(unsigned from_step = 0,
- unsigned to_step = 0,
- double scale = 1.0) const;
- std::unique_ptr<Timings> Profile(unsigned min_iterations,
- double min_duration,
- const FloatRect* clip_rect) const;
+ Vector<char> Replay(unsigned from_step = 0,
+ unsigned to_step = 0,
+ double scale = 1.0) const;
+ Vector<Vector<TimeDelta>> Profile(unsigned min_iterations,
+ TimeDelta min_duration,
+ const FloatRect* clip_rect) const;
std::unique_ptr<JSONArray> SnapshotCommandLog() const;
bool IsEmpty() const;
@@ -74,6 +73,8 @@ class PLATFORM_EXPORT PictureSnapshot : public RefCounted<PictureSnapshot> {
std::unique_ptr<SkBitmap> CreateBitmap() const;
sk_sp<const SkPicture> picture_;
+
+ DISALLOW_COPY_AND_ASSIGN(PictureSnapshot);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc b/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc
index 904e6231373..56f3a93554d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.cc
@@ -46,7 +46,10 @@ constexpr int kTextPaddingY = 9;
constexpr int kFontSize = 14;
-void DrawIcon(PaintCanvas* canvas, const PaintFlags& flags, float x, float y) {
+void DrawIcon(cc::PaintCanvas* canvas,
+ const PaintFlags& flags,
+ float x,
+ float y) {
DEFINE_STATIC_REF(Image, icon_image,
(Image::LoadPlatformResource("placeholderIcon")));
DCHECK(!icon_image->IsNull());
@@ -58,10 +61,10 @@ void DrawIcon(PaintCanvas* canvas, const PaintFlags& flags, float x, float y) {
canvas->drawImageRect(icon_image->PaintImageForCurrentFrame(),
IntRect(IntPoint::Zero(), icon_image->Size()),
FloatRect(x, y, kIconWidth, kIconHeight), &flags,
- PaintCanvas::kFast_SrcRectConstraint);
+ cc::PaintCanvas::kFast_SrcRectConstraint);
}
-void DrawCenteredIcon(PaintCanvas* canvas,
+void DrawCenteredIcon(cc::PaintCanvas* canvas,
const PaintFlags& flags,
const FloatRect& dest_rect) {
DrawIcon(canvas, flags,
@@ -232,7 +235,7 @@ PaintImage PlaceholderImage::PaintImageForCurrentFrame() {
.TakePaintImage();
}
-void PlaceholderImage::Draw(PaintCanvas* canvas,
+void PlaceholderImage::Draw(cc::PaintCanvas* canvas,
const PaintFlags& base_flags,
const FloatRect& dest_rect,
const FloatRect& src_rect,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.h b/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.h
index 00dd9ee06d5..6bafd3224ce 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/placeholder_image.h
@@ -39,8 +39,8 @@ class PLATFORM_EXPORT PlaceholderImage final : public Image {
IntSize Size() const override;
- void Draw(PaintCanvas*,
- const PaintFlags&,
+ void Draw(cc::PaintCanvas*,
+ const cc::PaintFlags&,
const FloatRect& dest_rect,
const FloatRect& src_rect,
RespectImageOrientationEnum,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/profiling_canvas.cc b/chromium/third_party/blink/renderer/platform/graphics/profiling_canvas.cc
index 694ef3108f1..e412208240d 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/profiling_canvas.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/profiling_canvas.cc
@@ -36,13 +36,12 @@ namespace blink {
CanvasInterceptor<ProfilingCanvas>::CanvasInterceptor(
InterceptingCanvasBase* canvas)
- : CanvasInterceptorBase(canvas),
- start_time_(WTF::CurrentTimeTicksInSeconds()) {}
+ : CanvasInterceptorBase(canvas), start_time_(WTF::CurrentTimeTicks()) {}
CanvasInterceptor<ProfilingCanvas>::~CanvasInterceptor() {
if (!TopLevelCall())
return;
- double delta = WTF::CurrentTimeTicksInSeconds() - start_time_;
+ TimeDelta delta = WTF::CurrentTimeTicks() - start_time_;
if (auto* timings = Canvas()->timings_) {
DCHECK_EQ(timings->size(), Canvas()->CallCount());
timings->push_back(delta);
@@ -52,7 +51,7 @@ CanvasInterceptor<ProfilingCanvas>::~CanvasInterceptor() {
ProfilingCanvas::ProfilingCanvas(SkBitmap bitmap)
: InterceptingCanvas(bitmap), timings_(nullptr) {}
-void ProfilingCanvas::SetTimings(Vector<double>* timings) {
+void ProfilingCanvas::SetTimings(Vector<TimeDelta>* timings) {
timings_ = timings;
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/profiling_canvas.h b/chromium/third_party/blink/renderer/platform/graphics/profiling_canvas.h
index 5d67b563f1a..0099134ffac 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/profiling_canvas.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/profiling_canvas.h
@@ -32,6 +32,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PROFILING_CANVAS_H_
#include "third_party/blink/renderer/platform/graphics/intercepting_canvas.h"
+#include "third_party/blink/renderer/platform/wtf/time.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
@@ -46,18 +47,18 @@ class CanvasInterceptor<ProfilingCanvas>
~CanvasInterceptor();
private:
- double start_time_;
+ TimeTicks start_time_;
};
class ProfilingCanvas : public InterceptingCanvas<ProfilingCanvas> {
public:
explicit ProfilingCanvas(SkBitmap);
- void SetTimings(Vector<double>*);
+ void SetTimings(Vector<TimeDelta>*);
private:
friend class CanvasInterceptor<ProfilingCanvas>;
- Vector<double>* timings_;
+ Vector<TimeDelta>* timings_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/skia/image_pixel_locker.h b/chromium/third_party/blink/renderer/platform/graphics/skia/image_pixel_locker.h
index fe40364d77b..bd7dff3f464 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/skia/image_pixel_locker.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/skia/image_pixel_locker.h
@@ -5,10 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_SKIA_IMAGE_PIXEL_LOCKER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_SKIA_IMAGE_PIXEL_LOCKER_H_
+#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkRefCnt.h"
@@ -18,7 +18,6 @@ namespace blink {
class ImagePixelLocker final {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
- WTF_MAKE_NONCOPYABLE(ImagePixelLocker);
public:
ImagePixelLocker(sk_sp<const SkImage>, SkAlphaType, SkColorType);
@@ -29,6 +28,8 @@ class ImagePixelLocker final {
const sk_sp<const SkImage> image_;
const void* pixels_;
Vector<char> pixel_storage_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImagePixelLocker);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc b/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc
index efa048b0b98..3dff61d9010 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.cc
@@ -41,82 +41,82 @@
namespace blink {
-static const struct CompositOpToSkBlendMode {
- CompositeOperator composit_op;
- SkBlendMode xfermode_mode;
-} kGMapCompositOpsToSkBlendMode[] = {
- {kCompositeClear, SkBlendMode::kClear},
- {kCompositeCopy, SkBlendMode::kSrc},
- {kCompositeSourceOver, SkBlendMode::kSrcOver},
- {kCompositeSourceIn, SkBlendMode::kSrcIn},
- {kCompositeSourceOut, SkBlendMode::kSrcOut},
- {kCompositeSourceAtop, SkBlendMode::kSrcATop},
- {kCompositeDestinationOver, SkBlendMode::kDstOver},
- {kCompositeDestinationIn, SkBlendMode::kDstIn},
- {kCompositeDestinationOut, SkBlendMode::kDstOut},
- {kCompositeDestinationAtop, SkBlendMode::kDstATop},
- {kCompositeXOR, SkBlendMode::kXor},
- {kCompositePlusLighter, SkBlendMode::kPlus}};
-
-// Keep this array in sync with the BlendMode enum in
-// platform/graphics/graphics_types.h.
-static const SkBlendMode kGMapBlendOpsToSkBlendMode[] = {
- SkBlendMode::kSrcOver, // BlendMode::kNormal
- SkBlendMode::kMultiply, // BlendMode::kMultiply
- SkBlendMode::kScreen, // BlendMode::kScreen
- SkBlendMode::kOverlay, // BlendMode::kOverlay
- SkBlendMode::kDarken, // BlendMode::kDarken
- SkBlendMode::kLighten, // BlendMode::kLighten
- SkBlendMode::kColorDodge, // BlendMode::kColorDodge
- SkBlendMode::kColorBurn, // BlendMode::kColorBurn
- SkBlendMode::kHardLight, // BlendMode::kHardLight
- SkBlendMode::kSoftLight, // BlendMode::kSoftLight
- SkBlendMode::kDifference, // BlendMode::kDifference
- SkBlendMode::kExclusion, // BlendMode::kExclusion
- SkBlendMode::kHue, // BlendMode::kHue
- SkBlendMode::kSaturation, // BlendMode::kSaturation
- SkBlendMode::kColor, // BlendMode::kColor
- SkBlendMode::kLuminosity // BlendMode::kLuminosity
-};
-
SkBlendMode WebCoreCompositeToSkiaComposite(CompositeOperator op,
BlendMode blend_mode) {
- DCHECK(op == kCompositeSourceOver || blend_mode == BlendMode::kNormal);
if (blend_mode != BlendMode::kNormal) {
- if (static_cast<uint8_t>(blend_mode) >=
- SK_ARRAY_COUNT(kGMapBlendOpsToSkBlendMode)) {
- SkDEBUGF(
- ("GraphicsContext::setPlatformCompositeOperation unknown "
- "BlendMode %d\n",
- blend_mode));
- return SkBlendMode::kSrcOver;
- }
- return kGMapBlendOpsToSkBlendMode[static_cast<uint8_t>(blend_mode)];
+ DCHECK(op == kCompositeSourceOver);
+ return WebCoreBlendModeToSkBlendMode(blend_mode);
}
- const CompositOpToSkBlendMode* table = kGMapCompositOpsToSkBlendMode;
- if (static_cast<uint8_t>(op) >=
- SK_ARRAY_COUNT(kGMapCompositOpsToSkBlendMode)) {
- SkDEBUGF(
- ("GraphicsContext::setPlatformCompositeOperation unknown "
- "CompositeOperator %d\n",
- op));
- return SkBlendMode::kSrcOver;
+ switch (op) {
+ case kCompositeClear:
+ return SkBlendMode::kClear;
+ case kCompositeCopy:
+ return SkBlendMode::kSrc;
+ case kCompositeSourceOver:
+ return SkBlendMode::kSrcOver;
+ case kCompositeSourceIn:
+ return SkBlendMode::kSrcIn;
+ case kCompositeSourceOut:
+ return SkBlendMode::kSrcOut;
+ case kCompositeSourceAtop:
+ return SkBlendMode::kSrcATop;
+ case kCompositeDestinationOver:
+ return SkBlendMode::kDstOver;
+ case kCompositeDestinationIn:
+ return SkBlendMode::kDstIn;
+ case kCompositeDestinationOut:
+ return SkBlendMode::kDstOut;
+ case kCompositeDestinationAtop:
+ return SkBlendMode::kDstATop;
+ case kCompositeXOR:
+ return SkBlendMode::kXor;
+ case kCompositePlusLighter:
+ return SkBlendMode::kPlus;
}
- SkASSERT(table[static_cast<uint8_t>(op)].composit_op == op);
- return table[static_cast<uint8_t>(op)].xfermode_mode;
+
+ NOTREACHED();
+ return SkBlendMode::kSrcOver;
}
SkBlendMode WebCoreBlendModeToSkBlendMode(BlendMode blend_mode) {
- if (static_cast<uint8_t>(blend_mode) >=
- SK_ARRAY_COUNT(kGMapBlendOpsToSkBlendMode)) {
- SkDEBUGF(
- ("GraphicsContext::setPlatformCompositeOperation unknown "
- "BlendMode %d\n",
- blend_mode));
- return SkBlendMode::kSrcOver;
+ switch (blend_mode) {
+ case BlendMode::kNormal:
+ return SkBlendMode::kSrcOver;
+ case BlendMode::kMultiply:
+ return SkBlendMode::kMultiply;
+ case BlendMode::kScreen:
+ return SkBlendMode::kScreen;
+ case BlendMode::kOverlay:
+ return SkBlendMode::kOverlay;
+ case BlendMode::kDarken:
+ return SkBlendMode::kDarken;
+ case BlendMode::kLighten:
+ return SkBlendMode::kLighten;
+ case BlendMode::kColorDodge:
+ return SkBlendMode::kColorDodge;
+ case BlendMode::kColorBurn:
+ return SkBlendMode::kColorBurn;
+ case BlendMode::kHardLight:
+ return SkBlendMode::kHardLight;
+ case BlendMode::kSoftLight:
+ return SkBlendMode::kSoftLight;
+ case BlendMode::kDifference:
+ return SkBlendMode::kDifference;
+ case BlendMode::kExclusion:
+ return SkBlendMode::kExclusion;
+ case BlendMode::kHue:
+ return SkBlendMode::kHue;
+ case BlendMode::kSaturation:
+ return SkBlendMode::kSaturation;
+ case BlendMode::kColor:
+ return SkBlendMode::kColor;
+ case BlendMode::kLuminosity:
+ return SkBlendMode::kLuminosity;
}
- return kGMapBlendOpsToSkBlendMode[static_cast<uint8_t>(blend_mode)];
+
+ NOTREACHED();
+ return SkBlendMode::kSrcOver;
}
CompositeOperator CompositeOperatorFromSkBlendMode(SkBlendMode blend_mode) {
@@ -343,7 +343,7 @@ gfx::ColorSpace SkColorSpaceToGfxColorSpace(
template <typename PrimitiveType>
void DrawFocusRingPrimitive(const PrimitiveType&,
- PaintCanvas*,
+ cc::PaintCanvas*,
const PaintFlags&,
float corner_radius) {
NOTREACHED(); // Missing an explicit specialization?
@@ -351,7 +351,7 @@ void DrawFocusRingPrimitive(const PrimitiveType&,
template <>
void DrawFocusRingPrimitive<SkRect>(const SkRect& rect,
- PaintCanvas* canvas,
+ cc::PaintCanvas* canvas,
const PaintFlags& flags,
float corner_radius) {
SkRRect rrect;
@@ -362,7 +362,7 @@ void DrawFocusRingPrimitive<SkRect>(const SkRect& rect,
template <>
void DrawFocusRingPrimitive<SkPath>(const SkPath& path,
- PaintCanvas* canvas,
+ cc::PaintCanvas* canvas,
const PaintFlags& flags,
float corner_radius) {
PaintFlags path_flags = flags;
@@ -373,7 +373,7 @@ void DrawFocusRingPrimitive<SkPath>(const SkPath& path,
template <typename PrimitiveType>
void DrawPlatformFocusRing(const PrimitiveType& primitive,
- PaintCanvas* canvas,
+ cc::PaintCanvas* canvas,
SkColor color,
float width) {
PaintFlags flags;
@@ -400,11 +400,11 @@ void DrawPlatformFocusRing(const PrimitiveType& primitive,
}
template void PLATFORM_EXPORT DrawPlatformFocusRing<SkRect>(const SkRect&,
- PaintCanvas*,
+ cc::PaintCanvas*,
SkColor,
float width);
template void PLATFORM_EXPORT DrawPlatformFocusRing<SkPath>(const SkPath&,
- PaintCanvas*,
+ cc::PaintCanvas*,
SkColor,
float width);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.h b/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
index d34ca3cac4e..4d7816c2faf 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
@@ -34,6 +34,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_SKIA_SKIA_UTILS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_SKIA_SKIA_UTILS_H_
+#include "cc/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
#include "third_party/blink/renderer/platform/graphics/image.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -132,16 +133,16 @@ inline SkScalar SkBlurRadiusToSigma(SkScalar radius) {
template <typename PrimitiveType>
void DrawPlatformFocusRing(const PrimitiveType&,
- PaintCanvas*,
+ cc::PaintCanvas*,
SkColor,
float width);
// TODO(fmalita): remove in favor of direct SrcRectConstraint use.
-inline PaintCanvas::SrcRectConstraint WebCoreClampingModeToSkiaRectConstraint(
- Image::ImageClampingMode clamp_mode) {
+inline cc::PaintCanvas::SrcRectConstraint
+WebCoreClampingModeToSkiaRectConstraint(Image::ImageClampingMode clamp_mode) {
return clamp_mode == Image::kClampImageToSourceRect
- ? PaintCanvas::kStrict_SrcRectConstraint
- : PaintCanvas::kFast_SrcRectConstraint;
+ ? cc::PaintCanvas::kStrict_SrcRectConstraint
+ : cc::PaintCanvas::kFast_SrcRectConstraint;
}
// Skia's smart pointer APIs are preferable over their legacy raw pointer
diff --git a/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.h b/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.h
index 0cd6ea15413..9ccde9d01c5 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/skia_texture_holder.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_SKIA_TEXTURE_HOLDER_H_
#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
#include "third_party/blink/renderer/platform/graphics/texture_holder.h"
#include "third_party/blink/renderer/platform/platform_export.h"
diff --git a/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc b/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
index 8f87d6b29fe..e200c1f0bf1 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
@@ -4,13 +4,13 @@
#include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
+#include "base/numerics/checked_math.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/image_observer.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_image.h"
#include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h"
-#include "third_party/blink/renderer/platform/wtf/checked_numeric.h"
#include "third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkImage.h"
@@ -62,7 +62,7 @@ scoped_refptr<StaticBitmapImage> StaticBitmapImage::Create(
return Create(SkImage::MakeFromRaster(pixmap, nullptr, nullptr));
}
-void StaticBitmapImage::DrawHelper(PaintCanvas* canvas,
+void StaticBitmapImage::DrawHelper(cc::PaintCanvas* canvas,
const PaintFlags& flags,
const FloatRect& dst_rect,
const FloatRect& src_rect,
@@ -79,8 +79,7 @@ void StaticBitmapImage::DrawHelper(PaintCanvas* canvas,
}
scoped_refptr<StaticBitmapImage> StaticBitmapImage::ConvertToColorSpace(
- sk_sp<SkColorSpace> target,
- SkTransferFunctionBehavior transfer_function_behavior) {
+ sk_sp<SkColorSpace> target) {
sk_sp<SkImage> skia_image = PaintImageForCurrentFrame().GetSkImage();
sk_sp<SkColorSpace> src_color_space = skia_image->refColorSpace();
if (!src_color_space.get())
@@ -91,14 +90,8 @@ scoped_refptr<StaticBitmapImage> StaticBitmapImage::ConvertToColorSpace(
if (SkColorSpace::Equals(src_color_space.get(), dst_color_space.get()))
return this;
- // crbug.com/844145: Remove this when GPU-backed SkImage supports color
- // covnersion for kRespect TransferFnBehavior (skia:6553).
- if (skia_image->isTextureBacked() &&
- transfer_function_behavior == SkTransferFunctionBehavior::kRespect) {
- skia_image = skia_image->makeNonTextureImage();
- }
sk_sp<SkImage> converted_skia_image =
- skia_image->makeColorSpace(dst_color_space, transfer_function_behavior);
+ skia_image->makeColorSpace(dst_color_space);
DCHECK(converted_skia_image.get());
DCHECK(skia_image.get() != converted_skia_image.get());
@@ -115,7 +108,7 @@ bool StaticBitmapImage::ConvertToArrayBufferContents(
const CanvasColorParams& color_params,
bool is_accelerated) {
uint8_t bytes_per_pixel = color_params.BytesPerPixel();
- CheckedNumeric<int> data_size = bytes_per_pixel;
+ base::CheckedNumeric<int> data_size = bytes_per_pixel;
data_size *= rect.Size().Area();
if (!data_size.IsValid() ||
data_size.ValueOrDie() > v8::TypedArray::kMaxLength)
diff --git a/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.h b/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.h
index 5a596f14221..0f3d63acb7a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/static_bitmap_image.h
@@ -113,9 +113,7 @@ class PLATFORM_EXPORT StaticBitmapImage : public Image {
// Methods have exactly the same implementation for all sub-classes
bool OriginClean() const { return is_origin_clean_; }
void SetOriginClean(bool flag) { is_origin_clean_ = flag; }
- scoped_refptr<StaticBitmapImage> ConvertToColorSpace(
- sk_sp<SkColorSpace>,
- SkTransferFunctionBehavior);
+ scoped_refptr<StaticBitmapImage> ConvertToColorSpace(sk_sp<SkColorSpace>);
static bool ConvertToArrayBufferContents(
scoped_refptr<StaticBitmapImage> src_image,
@@ -126,8 +124,8 @@ class PLATFORM_EXPORT StaticBitmapImage : public Image {
protected:
// Helper for sub-classes
- void DrawHelper(PaintCanvas*,
- const PaintFlags&,
+ void DrawHelper(cc::PaintCanvas*,
+ const cc::PaintFlags&,
const FloatRect&,
const FloatRect&,
ImageClampingMode,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc b/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc
index f07c3a9c77f..3aa75b4dea6 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/platform/graphics/surface_layer_bridge.h"
+#include <utility>
+
#include "base/feature_list.h"
#include "cc/layers/layer.h"
#include "cc/layers/solid_color_layer.h"
@@ -21,9 +23,13 @@
namespace blink {
-SurfaceLayerBridge::SurfaceLayerBridge(WebLayerTreeView* layer_tree_view,
- WebSurfaceLayerBridgeObserver* observer)
+SurfaceLayerBridge::SurfaceLayerBridge(
+ WebLayerTreeView* layer_tree_view,
+ WebSurfaceLayerBridgeObserver* observer,
+ cc::UpdateSubmissionStateCB update_submission_state_callback)
: observer_(observer),
+ update_submission_state_callback_(
+ std::move(update_submission_state_callback)),
binding_(this),
frame_sink_id_(Platform::Current()->GenerateFrameSinkId()),
parent_frame_sink_id_(layer_tree_view ? layer_tree_view->GetFrameSinkId()
@@ -40,72 +46,106 @@ SurfaceLayerBridge::SurfaceLayerBridge(WebLayerTreeView* layer_tree_view,
std::move(client));
}
-SurfaceLayerBridge::~SurfaceLayerBridge() {
- observer_ = nullptr;
+SurfaceLayerBridge::~SurfaceLayerBridge() = default;
+
+void SurfaceLayerBridge::CreateSolidColorLayer() {
+ // TODO(lethalantidote): Remove this logic. It should be covered by setting
+ // the layer's opacity to false.
+ solid_color_layer_ = cc::SolidColorLayer::Create();
+ solid_color_layer_->SetBackgroundColor(SK_ColorTRANSPARENT);
+ if (observer_)
+ observer_->RegisterContentsLayer(solid_color_layer_.get());
+}
+
+void SurfaceLayerBridge::OnFirstSurfaceActivation(
+ const viz::SurfaceInfo& surface_info) {
+ DCHECK(surface_info.is_valid());
+
+ surface_activated_ = true;
+ if (solid_color_layer_) {
+ if (observer_)
+ observer_->UnregisterContentsLayer(solid_color_layer_.get());
+ solid_color_layer_->RemoveFromParent();
+ solid_color_layer_ = nullptr;
+ }
+ if (!surface_layer_) {
+ // This covers non-video cases, where we don't create the SurfaceLayer
+ // early.
+ // TODO(lethalantidote): Eliminate this case. Once you do that, you can
+ // also just store the surface_id and not the frame_sink_id.
+ CreateSurfaceLayer();
+ }
+
+ current_surface_id_ = surface_info.id();
+
+ surface_layer_->SetPrimarySurfaceId(surface_info.id(),
+ cc::DeadlinePolicy::UseDefaultDeadline());
+ surface_layer_->SetFallbackSurfaceId(surface_info.id());
+
+ if (observer_) {
+ observer_->OnWebLayerUpdated();
+ observer_->OnSurfaceIdUpdated(surface_info.id());
+ }
+
+ surface_layer_->SetContentsOpaque(opaque_);
+}
+
+cc::Layer* SurfaceLayerBridge::GetCcLayer() const {
+ if (surface_layer_)
+ return surface_layer_.get();
+
+ return solid_color_layer_.get();
+}
+
+const viz::FrameSinkId& SurfaceLayerBridge::GetFrameSinkId() const {
+ return frame_sink_id_;
}
void SurfaceLayerBridge::ClearSurfaceId() {
current_surface_id_ = viz::SurfaceId();
- cc::SurfaceLayer* surface_layer =
- static_cast<cc::SurfaceLayer*>(cc_layer_.get());
- if (!surface_layer)
+ if (!surface_layer_)
return;
// We reset the Ids if we lose the context_provider (case: GPU process ended)
// If we destroyed the surface_layer before that point, we need not update
// the ids.
- surface_layer->SetPrimarySurfaceId(viz::SurfaceId(),
- cc::DeadlinePolicy::UseDefaultDeadline());
- surface_layer->SetFallbackSurfaceId(viz::SurfaceId());
+ surface_layer_->SetPrimarySurfaceId(viz::SurfaceId(),
+ cc::DeadlinePolicy::UseDefaultDeadline());
+ surface_layer_->SetFallbackSurfaceId(viz::SurfaceId());
}
-void SurfaceLayerBridge::CreateSolidColorLayer() {
- cc_layer_ = cc::SolidColorLayer::Create();
- cc_layer_->SetBackgroundColor(SK_ColorTRANSPARENT);
-
- if (observer_)
- observer_->RegisterContentsLayer(cc_layer_.get());
+void SurfaceLayerBridge::SetContentsOpaque(bool opaque) {
+ // If the surface isn't activated, we have nothing to show, do not change
+ // opacity (defaults to false on surface_layer creation).
+ if (surface_layer_ && surface_activated_)
+ surface_layer_->SetContentsOpaque(opaque);
+ opaque_ = opaque;
}
-void SurfaceLayerBridge::OnFirstSurfaceActivation(
- const viz::SurfaceInfo& surface_info) {
- if (!current_surface_id_.is_valid() && surface_info.is_valid()) {
- // First time a SurfaceId is received.
- current_surface_id_ = surface_info.id();
- if (cc_layer_) {
- if (observer_)
- observer_->UnregisterContentsLayer(cc_layer_.get());
- cc_layer_->RemoveFromParent();
- }
-
- scoped_refptr<cc::SurfaceLayer> surface_layer = cc::SurfaceLayer::Create();
- surface_layer->SetPrimarySurfaceId(
- surface_info.id(), cc::DeadlinePolicy::UseDefaultDeadline());
- surface_layer->SetFallbackSurfaceId(surface_info.id());
- surface_layer->SetStretchContentToFillBounds(true);
- surface_layer->SetIsDrawable(true);
- cc_layer_ = surface_layer;
+void SurfaceLayerBridge::CreateSurfaceLayer() {
+ surface_layer_ = cc::SurfaceLayer::Create(update_submission_state_callback_);
- if (observer_)
- observer_->RegisterContentsLayer(cc_layer_.get());
- } else if (current_surface_id_ != surface_info.id()) {
- // A different SurfaceId is received, prompting change to existing
- // SurfaceLayer.
- current_surface_id_ = surface_info.id();
- cc::SurfaceLayer* surface_layer =
- static_cast<cc::SurfaceLayer*>(cc_layer_.get());
- surface_layer->SetPrimarySurfaceId(
- surface_info.id(), cc::DeadlinePolicy::UseDefaultDeadline());
- surface_layer->SetFallbackSurfaceId(surface_info.id());
- }
+ // This surface_id is essentially just a placeholder for the real one we will
+ // get in OnFirstSurfaceActivation. We need it so that we properly get a
+ // WillDraw, which then pushes the first compositor frame.
+ current_surface_id_ = viz::SurfaceId(
+ frame_sink_id_,
+ parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId());
+
+ surface_layer_->SetPrimarySurfaceId(current_surface_id_,
+ cc::DeadlinePolicy::UseDefaultDeadline());
+
+ surface_layer_->SetStretchContentToFillBounds(true);
+ surface_layer_->SetIsDrawable(true);
+ surface_layer_->SetMayContainVideo(true);
if (observer_) {
- observer_->OnWebLayerUpdated();
- observer_->OnSurfaceIdUpdated(surface_info.id());
+ observer_->RegisterContentsLayer(surface_layer_.get());
}
-
- cc_layer_->SetBounds(surface_info.size_in_pixels());
+ // We ignore our opacity until we are sure that we have something to show,
+ // as indicated by getting an OnFirstSurfaceActivation call.
+ surface_layer_->SetContentsOpaque(false);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.h b/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.h
index e2c931c524d..120b32a6a04 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/surface_layer_bridge.h
@@ -8,6 +8,7 @@
#include <memory>
#include "base/memory/scoped_refptr.h"
+#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "third_party/blink/public/platform/modules/frame_sinks/embedded_frame_sink.mojom-blink.h"
@@ -15,7 +16,8 @@
#include "third_party/blink/renderer/platform/platform_export.h"
namespace cc {
-class Layer;
+class SolidColorLayer;
+class SurfaceLayer;
} // namespace cc
namespace viz {
@@ -32,7 +34,10 @@ class PLATFORM_EXPORT SurfaceLayerBridge
: public blink::mojom::blink::EmbeddedFrameSinkClient,
public WebSurfaceLayerBridge {
public:
- SurfaceLayerBridge(WebLayerTreeView*, WebSurfaceLayerBridgeObserver*);
+ SurfaceLayerBridge(
+ WebLayerTreeView*,
+ WebSurfaceLayerBridgeObserver*,
+ cc::UpdateSubmissionStateCB update_submission_state_callback);
~SurfaceLayerBridge() override;
void CreateSolidColorLayer();
@@ -41,23 +46,31 @@ class PLATFORM_EXPORT SurfaceLayerBridge
void OnFirstSurfaceActivation(const viz::SurfaceInfo&) override;
// Implementation of WebSurfaceLayerBridge.
- cc::Layer* GetCcLayer() const override { return cc_layer_.get(); }
+ cc::Layer* GetCcLayer() const override;
+ const viz::FrameSinkId& GetFrameSinkId() const override;
void ClearSurfaceId() override;
+ void SetContentsOpaque(bool) override;
+ void CreateSurfaceLayer() override;
- const viz::FrameSinkId& GetFrameSinkId() const override {
- return frame_sink_id_;
+ const viz::SurfaceId& GetSurfaceId() const override {
+ return current_surface_id_;
}
private:
- scoped_refptr<cc::Layer> cc_layer_;
+ scoped_refptr<cc::SurfaceLayer> surface_layer_;
+ scoped_refptr<cc::SolidColorLayer> solid_color_layer_;
+ // The |observer_| handles unregistering the contents layer on its own.
WebSurfaceLayerBridgeObserver* observer_;
-
+ cc::UpdateSubmissionStateCB update_submission_state_callback_;
+ viz::ParentLocalSurfaceIdAllocator parent_local_surface_id_allocator_;
mojo::Binding<blink::mojom::blink::EmbeddedFrameSinkClient> binding_;
const viz::FrameSinkId frame_sink_id_;
viz::SurfaceId current_surface_id_;
const viz::FrameSinkId parent_frame_sink_id_;
+ bool opaque_ = false;
+ bool surface_activated_ = false;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.cc b/chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.cc
index 45048ff77db..f82ee1e8274 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.cc
@@ -74,8 +74,8 @@ bool UnacceleratedStaticBitmapImage::CurrentFrameKnownToBeOpaque() {
return paint_image_.GetSkImage()->isOpaque();
}
-void UnacceleratedStaticBitmapImage::Draw(PaintCanvas* canvas,
- const PaintFlags& flags,
+void UnacceleratedStaticBitmapImage::Draw(cc::PaintCanvas* canvas,
+ const cc::PaintFlags& flags,
const FloatRect& dst_rect,
const FloatRect& src_rect,
RespectImageOrientationEnum,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h b/chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h
index fbd2ededff0..160999257cf 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h
@@ -24,8 +24,8 @@ class PLATFORM_EXPORT UnacceleratedStaticBitmapImage final
base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_wrapper)
override;
- void Draw(PaintCanvas*,
- const PaintFlags&,
+ void Draw(cc::PaintCanvas*,
+ const cc::PaintFlags&,
const FloatRect& dst_rect,
const FloatRect& src_rect,
RespectImageOrientationEnum,
diff --git a/chromium/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.cc b/chromium/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.cc
index 76a6dd3c515..6a0023a8bcc 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.cc
@@ -7,14 +7,14 @@
#include <memory>
#include "base/bind.h"
#include "base/trace_event/trace_event.h"
-#include "cc/resources/layer_tree_resource_provider.h"
-#include "cc/resources/video_resource_updater.h"
+#include "components/viz/client/client_resource_provider.h"
#include "components/viz/common/gpu/context_provider.h"
#include "components/viz/common/quads/render_pass.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/texture_draw_quad.h"
#include "components/viz/common/quads/yuv_video_draw_quad.h"
#include "media/base/video_frame.h"
+#include "media/renderers/video_resource_updater.h"
namespace blink {
@@ -22,14 +22,19 @@ VideoFrameResourceProvider::VideoFrameResourceProvider(
const cc::LayerTreeSettings& settings)
: settings_(settings) {}
-VideoFrameResourceProvider::~VideoFrameResourceProvider() = default;
+VideoFrameResourceProvider::~VideoFrameResourceProvider() {
+ // Drop all resources before closing the ClientResourceProvider.
+ resource_updater_ = nullptr;
+ if (resource_provider_)
+ resource_provider_->ShutdownAndReleaseAllResources();
+}
void VideoFrameResourceProvider::Initialize(
viz::ContextProvider* media_context_provider,
viz::SharedBitmapReporter* shared_bitmap_reporter) {
context_provider_ = media_context_provider;
- resource_provider_ = std::make_unique<cc::LayerTreeResourceProvider>(
- media_context_provider, true);
+ resource_provider_ = std::make_unique<viz::ClientResourceProvider>(
+ /*delegated_sync_points_required=*/true);
int max_texture_size;
if (context_provider_) {
@@ -40,7 +45,7 @@ void VideoFrameResourceProvider::Initialize(
max_texture_size = 16 * 1024;
}
- resource_updater_ = std::make_unique<cc::VideoResourceUpdater>(
+ resource_updater_ = std::make_unique<media::VideoResourceUpdater>(
media_context_provider, shared_bitmap_reporter, resource_provider_.get(),
settings_.use_stream_video_draw_quad,
settings_.resource_settings.use_gpu_memory_buffer_resources,
@@ -48,7 +53,10 @@ void VideoFrameResourceProvider::Initialize(
}
void VideoFrameResourceProvider::OnContextLost() {
+ // Drop all resources before closing the ClientResourceProvider.
resource_updater_ = nullptr;
+ if (resource_provider_)
+ resource_provider_->ShutdownAndReleaseAllResources();
resource_provider_ = nullptr;
context_provider_ = nullptr;
}
@@ -56,7 +64,8 @@ void VideoFrameResourceProvider::OnContextLost() {
void VideoFrameResourceProvider::AppendQuads(
viz::RenderPass* render_pass,
scoped_refptr<media::VideoFrame> frame,
- media::VideoRotation rotation) {
+ media::VideoRotation rotation,
+ bool is_opaque) {
TRACE_EVENT0("media", "VideoFrameResourceProvider::AppendQuads");
DCHECK(resource_updater_);
DCHECK(resource_provider_);
@@ -85,7 +94,6 @@ void VideoFrameResourceProvider::AppendQuads(
resource_updater_->ObtainFrameResources(frame);
// TODO(lethalantidote) : update with true value;
- bool contents_opaque = true;
gfx::Rect visible_layer_rect = gfx::Rect(rotated_size);
gfx::Rect clip_rect = gfx::Rect(frame->coded_size());
bool is_clipped = false;
@@ -98,7 +106,7 @@ void VideoFrameResourceProvider::AppendQuads(
resource_updater_->AppendQuads(render_pass, std::move(frame), transform,
rotated_size, visible_layer_rect, clip_rect,
- is_clipped, contents_opaque, draw_opacity,
+ is_clipped, is_opaque, draw_opacity,
sorting_context_id, visible_quad_rect);
}
diff --git a/chromium/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.h b/chromium/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.h
index 8f785932895..b689026e27c 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/video_frame_resource_provider.h
@@ -6,14 +6,17 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_VIDEO_FRAME_RESOURCE_PROVIDER_H_
#include "base/memory/weak_ptr.h"
-#include "cc/resources/layer_tree_resource_provider.h"
-#include "cc/resources/video_resource_updater.h"
#include "cc/trees/layer_tree_settings.h"
-#include "components/viz/common/resources/shared_bitmap_reporter.h"
-#include "media/base/video_frame.h"
+#include "components/viz/client/client_resource_provider.h"
+#include "components/viz/client/shared_bitmap_reporter.h"
#include "third_party/blink/public/platform/web_video_frame_submitter.h"
#include "third_party/blink/renderer/platform/platform_export.h"
+namespace media {
+class VideoFrame;
+class VideoResourceUpdater;
+} // namespace media
+
namespace viz {
class RenderPass;
}
@@ -34,7 +37,8 @@ class PLATFORM_EXPORT VideoFrameResourceProvider {
virtual void Initialize(viz::ContextProvider*, viz::SharedBitmapReporter*);
virtual void AppendQuads(viz::RenderPass*,
scoped_refptr<media::VideoFrame>,
- media::VideoRotation);
+ media::VideoRotation,
+ bool is_opaque);
virtual void ReleaseFrameResources();
// Once the context is lost, we must call Initialize again before we can
@@ -54,8 +58,8 @@ class PLATFORM_EXPORT VideoFrameResourceProvider {
WebContextProviderCallback context_provider_callback_;
viz::ContextProvider* context_provider_;
- std::unique_ptr<cc::LayerTreeResourceProvider> resource_provider_;
- std::unique_ptr<cc::VideoResourceUpdater> resource_updater_;
+ std::unique_ptr<viz::ClientResourceProvider> resource_provider_;
+ std::unique_ptr<media::VideoResourceUpdater> resource_updater_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc b/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
index d72158a7300..50950be7494 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
@@ -4,37 +4,27 @@
#include "third_party/blink/renderer/platform/graphics/video_frame_submitter.h"
+#include <vector>
+
#include "base/task_runner.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "cc/paint/filter_operations.h"
-#include "cc/resources/video_resource_updater.h"
#include "cc/scheduler/video_frame_controller.h"
#include "components/viz/common/resources/resource_id.h"
#include "components/viz/common/resources/returned_resource.h"
-#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "media/base/video_frame.h"
#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom-blink.h"
#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/modules/frame_sinks/embedded_frame_sink.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/graphics/canvas_resource.h"
namespace blink {
namespace {
-// TODO(danakj): One day the gpu::mojom::Mailbox type should be shared with
-// blink directly and we won't need to use gpu::mojom::blink::Mailbox, nor the
-// conversion through WTF::Vector.
-gpu::mojom::blink::MailboxPtr SharedBitmapIdToGpuMailboxPtr(
- const viz::SharedBitmapId& id) {
- WTF::Vector<int8_t> name(GL_MAILBOX_SIZE_CHROMIUM);
- for (int i = 0; i < GL_MAILBOX_SIZE_CHROMIUM; ++i)
- name[i] = id.name[i];
- return {base::in_place, name};
-}
-
// Delay to retry getting the context_provider.
constexpr int kGetContextProviderRetryMS = 150;
@@ -60,17 +50,47 @@ void VideoFrameSubmitter::SetRotation(media::VideoRotation rotation) {
rotation_ = rotation;
}
+void VideoFrameSubmitter::SetIsOpaque(bool is_opaque) {
+ if (is_opaque_ == is_opaque)
+ return;
+
+ is_opaque_ = is_opaque;
+ UpdateSubmissionStateInternal();
+}
+
void VideoFrameSubmitter::EnableSubmission(
- viz::FrameSinkId id,
+ viz::SurfaceId surface_id,
WebFrameSinkDestroyedCallback frame_sink_destroyed_callback) {
// TODO(lethalantidote): Set these fields earlier in the constructor. Will
// need to construct VideoFrameSubmitter later in order to do this.
- frame_sink_id_ = id;
+ frame_sink_id_ = surface_id.frame_sink_id();
frame_sink_destroyed_callback_ = frame_sink_destroyed_callback;
+ child_local_surface_id_allocator_.UpdateFromParent(
+ surface_id.local_surface_id());
if (resource_provider_->IsInitialized())
StartSubmitting();
}
+void VideoFrameSubmitter::UpdateSubmissionState(bool should_submit) {
+ should_submit_internal_ = should_submit;
+ UpdateSubmissionStateInternal();
+}
+
+void VideoFrameSubmitter::SetForceSubmit(bool force_submit) {
+ force_submit_ = force_submit;
+ UpdateSubmissionStateInternal();
+}
+
+void VideoFrameSubmitter::UpdateSubmissionStateInternal() {
+ if (compositor_frame_sink_) {
+ compositor_frame_sink_->SetNeedsBeginFrame(IsDrivingFrameUpdates());
+ if (ShouldSubmit())
+ SubmitSingleFrame();
+ else if (!frame_size_.IsEmpty())
+ SubmitEmptyFrame();
+ }
+}
+
void VideoFrameSubmitter::StopUsingProvider() {
DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
if (is_rendering_)
@@ -83,12 +103,8 @@ void VideoFrameSubmitter::StopRendering() {
DCHECK(is_rendering_);
DCHECK(provider_);
- if (compositor_frame_sink_) {
- // Push out final frame.
- SubmitSingleFrame();
- compositor_frame_sink_->SetNeedsBeginFrame(false);
- }
is_rendering_ = false;
+ UpdateSubmissionStateInternal();
}
void VideoFrameSubmitter::SubmitSingleFrame() {
@@ -100,11 +116,25 @@ void VideoFrameSubmitter::SubmitSingleFrame() {
viz::BeginFrameAck current_begin_frame_ack =
viz::BeginFrameAck::CreateManualAckWithDamage();
scoped_refptr<media::VideoFrame> video_frame = provider_->GetCurrentFrame();
- base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&VideoFrameSubmitter::SubmitFrame,
- weak_ptr_factory_.GetWeakPtr(),
- current_begin_frame_ack, video_frame));
- provider_->PutCurrentFrame();
+ if (video_frame) {
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(base::IgnoreResult(&VideoFrameSubmitter::SubmitFrame),
+ weak_ptr_factory_.GetWeakPtr(), current_begin_frame_ack,
+ video_frame));
+ provider_->PutCurrentFrame();
+ }
+}
+
+bool VideoFrameSubmitter::ShouldSubmit() const {
+ return should_submit_internal_ || force_submit_;
+}
+
+bool VideoFrameSubmitter::IsDrivingFrameUpdates() const {
+ // We drive frame updates only when we believe that something is consuming
+ // them. This is different than VideoLayer, which drives updates any time
+ // they're in the layer tree.
+ return is_rendering_ && ShouldSubmit();
}
void VideoFrameSubmitter::DidReceiveFrame() {
@@ -121,9 +151,10 @@ void VideoFrameSubmitter::DidReceiveFrame() {
void VideoFrameSubmitter::StartRendering() {
DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
DCHECK(!is_rendering_);
- if (compositor_frame_sink_)
- compositor_frame_sink_->SetNeedsBeginFrame(true);
is_rendering_ = true;
+
+ if (compositor_frame_sink_)
+ compositor_frame_sink_->SetNeedsBeginFrame(is_rendering_ && ShouldSubmit());
}
void VideoFrameSubmitter::Initialize(cc::VideoFrameProvider* provider) {
@@ -178,42 +209,46 @@ void VideoFrameSubmitter::StartSubmitting() {
frame_sink_id_, std::move(client),
mojo::MakeRequest(&compositor_frame_sink_));
- if (is_rendering_)
- compositor_frame_sink_->SetNeedsBeginFrame(true);
+ compositor_frame_sink_.set_connection_error_handler(base::BindOnce(
+ &VideoFrameSubmitter::OnContextLost, base::Unretained(this)));
- scoped_refptr<media::VideoFrame> video_frame = provider_->GetCurrentFrame();
- if (video_frame) {
- viz::BeginFrameAck current_begin_frame_ack =
- viz::BeginFrameAck::CreateManualAckWithDamage();
- base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&VideoFrameSubmitter::SubmitFrame,
- weak_ptr_factory_.GetWeakPtr(),
- current_begin_frame_ack, video_frame));
- provider_->PutCurrentFrame();
- }
+ UpdateSubmissionStateInternal();
}
-void VideoFrameSubmitter::SubmitFrame(
- viz::BeginFrameAck begin_frame_ack,
+bool VideoFrameSubmitter::SubmitFrame(
+ const viz::BeginFrameAck& begin_frame_ack,
scoped_refptr<media::VideoFrame> video_frame) {
TRACE_EVENT0("media", "VideoFrameSubmitter::SubmitFrame");
+ DCHECK(video_frame);
DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
- DCHECK(compositor_frame_sink_);
+ if (!compositor_frame_sink_ || !ShouldSubmit())
+ return false;
+
+ if (frame_size_ != gfx::Rect(video_frame->coded_size())) {
+ if (!frame_size_.IsEmpty())
+ child_local_surface_id_allocator_.GenerateId();
+ frame_size_ = gfx::Rect(video_frame->coded_size());
+ }
viz::CompositorFrame compositor_frame;
std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create();
- render_pass->SetNew(1, gfx::Rect(video_frame->coded_size()),
- gfx::Rect(video_frame->coded_size()), gfx::Transform());
+ render_pass->SetNew(1, frame_size_, frame_size_, gfx::Transform());
render_pass->filters = cc::FilterOperations();
- resource_provider_->AppendQuads(render_pass.get(), video_frame, rotation_);
+ resource_provider_->AppendQuads(render_pass.get(), video_frame, rotation_,
+ is_opaque_);
compositor_frame.metadata.begin_frame_ack = begin_frame_ack;
+ // We don't assume that the ack is marked as having damage. However, we're
+ // definitely emitting a CompositorFrame that damages the entire surface.
+ compositor_frame.metadata.begin_frame_ack.has_damage = true;
compositor_frame.metadata.device_scale_factor = 1;
compositor_frame.metadata.may_contain_video = true;
std::vector<viz::ResourceId> resources;
- for (auto* quad : render_pass->quad_list) {
- for (viz::ResourceId resource_id : quad->resources) {
+ DCHECK_LE(render_pass->quad_list.size(), 1u);
+ if (!render_pass->quad_list.empty()) {
+ for (viz::ResourceId resource_id :
+ render_pass->quad_list.front()->resources) {
resources.push_back(resource_id);
}
}
@@ -221,16 +256,37 @@ void VideoFrameSubmitter::SubmitFrame(
&compositor_frame.resource_list);
compositor_frame.render_pass_list.push_back(std::move(render_pass));
- if (compositor_frame.size_in_pixels() != current_size_in_pixels_) {
- parent_local_surface_id_allocator_.GenerateId();
- current_size_in_pixels_ = compositor_frame.size_in_pixels();
- }
-
// TODO(lethalantidote): Address third/fourth arg in SubmitCompositorFrame.
compositor_frame_sink_->SubmitCompositorFrame(
- parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
+ child_local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
std::move(compositor_frame), nullptr, 0);
resource_provider_->ReleaseFrameResources();
+
+ waiting_for_compositor_ack_ = true;
+ return true;
+}
+
+void VideoFrameSubmitter::SubmitEmptyFrame() {
+ TRACE_EVENT0("media", "VideoFrameSubmitter::SubmitEmptyFrame");
+ DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
+ DCHECK(compositor_frame_sink_ && !ShouldSubmit());
+ DCHECK(!frame_size_.IsEmpty());
+
+ viz::CompositorFrame compositor_frame;
+
+ compositor_frame.metadata.begin_frame_ack =
+ viz::BeginFrameAck::CreateManualAckWithDamage();
+ compositor_frame.metadata.device_scale_factor = 1;
+ compositor_frame.metadata.may_contain_video = true;
+
+ std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create();
+ render_pass->SetNew(1, frame_size_, frame_size_, gfx::Transform());
+ compositor_frame.render_pass_list.push_back(std::move(render_pass));
+
+ compositor_frame_sink_->SubmitCompositorFrame(
+ child_local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
+ std::move(compositor_frame), nullptr, 0);
+ waiting_for_compositor_ack_ = true;
}
void VideoFrameSubmitter::OnBeginFrame(const viz::BeginFrameArgs& args) {
@@ -243,20 +299,33 @@ void VideoFrameSubmitter::OnBeginFrame(const viz::BeginFrameArgs& args) {
return;
}
- current_begin_frame_ack.has_damage = true;
-
+ // Update the current frame, even if we haven't gotten an ack for a previous
+ // frame yet. That probably signals a dropped frame, and this will let the
+ // provider know that it happened, since we won't PutCurrentFrame this one.
+ // Note that we should DidNotProduceFrame with or without the ack.
if (!provider_ ||
!provider_->UpdateCurrentFrame(args.frame_time + args.interval,
- args.frame_time + 2 * args.interval) ||
- !is_rendering_) {
+ args.frame_time + 2 * args.interval)) {
compositor_frame_sink_->DidNotProduceFrame(current_begin_frame_ack);
return;
}
scoped_refptr<media::VideoFrame> video_frame = provider_->GetCurrentFrame();
- SubmitFrame(current_begin_frame_ack, video_frame);
+ // We do have a new frame that we could display. See if we're supposed to
+ // actually submit a frame or not, and try to submit one.
+ if (!is_rendering_ || waiting_for_compositor_ack_ ||
+ !SubmitFrame(current_begin_frame_ack, std::move(video_frame))) {
+ compositor_frame_sink_->DidNotProduceFrame(current_begin_frame_ack);
+ return;
+ }
+
+ // We submitted a frame!
+ // We still signal PutCurrentFrame here, rather than on the ack, so that it
+ // lines up with the correct frame. Otherwise, any intervening calls to
+ // OnBeginFrame => UpdateCurrentFrame will cause the put to signal that the
+ // later frame was displayed.
provider_->PutCurrentFrame();
}
@@ -269,20 +338,33 @@ void VideoFrameSubmitter::OnContextLost() {
if (binding_.is_bound())
binding_.Unbind();
- compositor_frame_sink_.reset();
- context_provider_->RemoveObserver(this);
- context_provider_ = nullptr;
+ if (context_provider_) {
+ context_provider_->RemoveObserver(this);
+ context_provider_ = nullptr;
+ }
+ waiting_for_compositor_ack_ = false;
resource_provider_->OnContextLost();
+
+ // |compositor_frame_sink_| should be reset last.
+ compositor_frame_sink_.reset();
+
context_provider_callback_.Run(
base::BindOnce(&VideoFrameSubmitter::OnReceivedContextProvider,
weak_ptr_factory_.GetWeakPtr()));
+
+ // We need to trigger another submit so that surface_id's get propagated
+ // correctly. If we don't, we don't get any more signals to update the
+ // submission state.
+ should_submit_internal_ = true;
}
void VideoFrameSubmitter::DidReceiveCompositorFrameAck(
const WTF::Vector<viz::ReturnedResource>& resources) {
DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
ReclaimResources(resources);
+
+ waiting_for_compositor_ack_ = false;
}
void VideoFrameSubmitter::ReclaimResources(
@@ -296,12 +378,7 @@ void VideoFrameSubmitter::ReclaimResources(
void VideoFrameSubmitter::DidPresentCompositorFrame(
uint32_t presentation_token,
- mojo_base::mojom::blink::TimeTicksPtr time,
- WTF::TimeDelta refresh,
- uint32_t flags) {}
-
-void VideoFrameSubmitter::DidDiscardCompositorFrame(
- uint32_t presentation_token) {}
+ ::gfx::mojom::blink::PresentationFeedbackPtr feedback) {}
void VideoFrameSubmitter::DidAllocateSharedBitmap(
mojo::ScopedSharedBufferHandle buffer,
@@ -317,4 +394,11 @@ void VideoFrameSubmitter::DidDeleteSharedBitmap(const viz::SharedBitmapId& id) {
SharedBitmapIdToGpuMailboxPtr(id));
}
+void VideoFrameSubmitter::SetSurfaceIdForTesting(
+ const viz::SurfaceId& surface_id) {
+ frame_sink_id_ = surface_id.frame_sink_id();
+ child_local_surface_id_allocator_.UpdateFromParent(
+ surface_id.local_surface_id());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.h b/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.h
index f6facc2a2a8..8b558645d38 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter.h
@@ -5,12 +5,15 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_VIDEO_FRAME_SUBMITTER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_VIDEO_FRAME_SUBMITTER_H_
+#include <memory>
+#include <utility>
+
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
+#include "components/viz/client/shared_bitmap_reporter.h"
#include "components/viz/common/gpu/context_provider.h"
-#include "components/viz/common/quads/shared_bitmap.h"
-#include "components/viz/common/resources/shared_bitmap_reporter.h"
-#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
+#include "components/viz/common/resources/shared_bitmap.h"
+#include "components/viz/common/surfaces/child_local_surface_id_allocator.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/buffer.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom-blink.h"
@@ -22,10 +25,11 @@
namespace blink {
// This single-threaded class facilitates the communication between the media
-// stack and mojo, providing compositor frames containing video frames to the
-// |compositor_frame_sink_|. This class has dependencies on classes that use
-// the media thread's OpenGL ContextProvider, and thus, besides construction,
-// should be consistently ran from the same media SingleThreadTaskRunner.
+// stack and browser renderer, providing compositor frames containing video
+// frames and corresponding resources to the |compositor_frame_sink_|. This
+// class has dependencies on classes that use the media thread's OpenGL
+// ContextProvider, and thus, besides construction, should be consistently ran
+// from the same media SingleThreadTaskRunner.
class PLATFORM_EXPORT VideoFrameSubmitter
: public WebVideoFrameSubmitter,
public viz::ContextLostObserver,
@@ -37,14 +41,11 @@ class PLATFORM_EXPORT VideoFrameSubmitter
~VideoFrameSubmitter() override;
- bool Rendering() { return is_rendering_; };
+ bool Rendering() { return is_rendering_; }
cc::VideoFrameProvider* Provider() { return provider_; }
mojo::Binding<viz::mojom::blink::CompositorFrameSinkClient>* Binding() {
return &binding_;
}
- void SetSink(viz::mojom::blink::CompositorFrameSinkPtr* sink) {
- compositor_frame_sink_ = std::move(*sink);
- }
void OnReceivedContextProvider(
bool,
@@ -55,12 +56,15 @@ class PLATFORM_EXPORT VideoFrameSubmitter
void StartRendering() override;
void StopRendering() override;
void DidReceiveFrame() override;
+ bool IsDrivingFrameUpdates() const override;
// WebVideoFrameSubmitter implementation.
void Initialize(cc::VideoFrameProvider*) override;
void SetRotation(media::VideoRotation) override;
- void EnableSubmission(viz::FrameSinkId,
- WebFrameSinkDestroyedCallback) override;
+ void SetIsOpaque(bool) override;
+ void EnableSubmission(viz::SurfaceId, WebFrameSinkDestroyedCallback) override;
+ void UpdateSubmissionState(bool is_visible) override;
+ void SetForceSubmit(bool) override;
// viz::ContextLostObserver implementation.
void OnContextLost() override;
@@ -68,11 +72,9 @@ class PLATFORM_EXPORT VideoFrameSubmitter
// cc::mojom::CompositorFrameSinkClient implementation.
void DidReceiveCompositorFrameAck(
const WTF::Vector<viz::ReturnedResource>& resources) override;
- void DidPresentCompositorFrame(uint32_t presentation_token,
- mojo_base::mojom::blink::TimeTicksPtr,
- WTF::TimeDelta refresh,
- uint32_t flags) final;
- void DidDiscardCompositorFrame(uint32_t presentation_token) final;
+ void DidPresentCompositorFrame(
+ uint32_t presentation_token,
+ ::gfx::mojom::blink::PresentationFeedbackPtr feedback) final;
void OnBeginFrame(const viz::BeginFrameArgs&) override;
void OnBeginFramePausedChanged(bool paused) override {}
void ReclaimResources(
@@ -83,9 +85,27 @@ class PLATFORM_EXPORT VideoFrameSubmitter
const viz::SharedBitmapId&) override;
void DidDeleteSharedBitmap(const viz::SharedBitmapId&) override;
+ void SetCompositorFrameSinkPtrForTesting(
+ viz::mojom::blink::CompositorFrameSinkPtr* sink) {
+ compositor_frame_sink_ = std::move(*sink);
+ }
+
+ void SetSurfaceIdForTesting(const viz::SurfaceId&);
+
private:
+ FRIEND_TEST_ALL_PREFIXES(VideoFrameSubmitterTest, ContextLostDuringSubmit);
+ FRIEND_TEST_ALL_PREFIXES(VideoFrameSubmitterTest,
+ ShouldSubmitPreventsSubmission);
+ FRIEND_TEST_ALL_PREFIXES(VideoFrameSubmitterTest,
+ SetForceSubmitForcesSubmission);
+ FRIEND_TEST_ALL_PREFIXES(VideoFrameSubmitterTest,
+ FrameSizeChangeUpdatesLocalSurfaceId);
+
void StartSubmitting();
- void SubmitFrame(viz::BeginFrameAck, scoped_refptr<media::VideoFrame>);
+ void UpdateSubmissionStateInternal();
+ // Returns whether a frame was submitted.
+ bool SubmitFrame(const viz::BeginFrameAck&, scoped_refptr<media::VideoFrame>);
+ void SubmitEmptyFrame();
// Pulls frame and submits it to compositor.
// Used in cases like PaintSingleFrame, which occurs before video rendering
@@ -93,19 +113,37 @@ class PLATFORM_EXPORT VideoFrameSubmitter
// ending rendering.
void SubmitSingleFrame();
+ // Return whether the submitter should submit frames based on its current
+ // state.
+ bool ShouldSubmit() const;
+
cc::VideoFrameProvider* provider_ = nullptr;
scoped_refptr<ui::ContextProviderCommandBuffer> context_provider_;
viz::mojom::blink::CompositorFrameSinkPtr compositor_frame_sink_;
mojo::Binding<viz::mojom::blink::CompositorFrameSinkClient> binding_;
- viz::ParentLocalSurfaceIdAllocator parent_local_surface_id_allocator_;
WebContextProviderCallback context_provider_callback_;
std::unique_ptr<VideoFrameResourceProvider> resource_provider_;
WebFrameSinkDestroyedCallback frame_sink_destroyed_callback_;
- viz::FrameSinkId frame_sink_id_;
+ bool waiting_for_compositor_ack_ = false;
bool is_rendering_;
+ // If we are not on screen, we should not submit.
+ bool should_submit_internal_ = false;
+ // Whether frames should always be submitted, even if we're not visible.
+ bool force_submit_ = false;
media::VideoRotation rotation_;
- gfx::Size current_size_in_pixels_;
+ bool is_opaque_ = true;
+
+ viz::FrameSinkId frame_sink_id_;
+
+ // Size of the video frame being submitted. It is set the first time a frame
+ // is submitted. Every time there is a change in the video frame size, the
+ // child component of the LocalSurfaceId will be updated.
+ gfx::Rect frame_size_;
+
+ // Used to updated the LocalSurfaceId when detecting a change in video frame
+ // size.
+ viz::ChildLocalSurfaceIdAllocator child_local_surface_id_allocator_;
THREAD_CHECKER(media_thread_checker_);
diff --git a/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc b/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
index 674465d8bf8..f4071fd2310 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
@@ -25,6 +25,7 @@
#include "third_party/blink/renderer/platform/wtf/functional.h"
using testing::_;
+using testing::AnyNumber;
using testing::Return;
using testing::StrictMock;
@@ -110,10 +111,11 @@ class MockVideoFrameResourceProvider
MOCK_METHOD2(Initialize,
void(viz::ContextProvider*, viz::SharedBitmapReporter*));
- MOCK_METHOD3(AppendQuads,
+ MOCK_METHOD4(AppendQuads,
void(viz::RenderPass*,
scoped_refptr<media::VideoFrame>,
- media::VideoRotation));
+ media::VideoRotation,
+ bool));
MOCK_METHOD0(ReleaseFrameResources, void());
MOCK_METHOD2(PrepareSendToParent,
void(const std::vector<viz::ResourceId>&,
@@ -157,7 +159,15 @@ class VideoFrameSubmitterTest : public testing::Test {
viz::mojom::blink::CompositorFrameSinkRequest request =
mojo::MakeRequest(&submitter_sink);
sink_ = std::make_unique<StrictMock<MockCompositorFrameSink>>(&request);
- submitter_->SetSink(&submitter_sink);
+
+ // By setting the submission state before we set the sink, we can make
+ // testing easier without having to worry about the first sent frame.
+ submitter_->UpdateSubmissionState(true);
+ submitter_->SetCompositorFrameSinkPtrForTesting(&submitter_sink);
+ submitter_->SetSurfaceIdForTesting(viz::SurfaceId(
+ viz::FrameSinkId(1, 1),
+ viz::LocalSurfaceId(11,
+ base::UnguessableToken::Deserialize(0x111111, 0))));
}
protected:
@@ -216,7 +226,7 @@ TEST_F(VideoFrameSubmitterTest,
EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
EXPECT_CALL(*provider_, PutCurrentFrame());
EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
- EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _));
+ EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
@@ -254,7 +264,7 @@ TEST_F(VideoFrameSubmitterTest, DidReceiveFrameSubmitsFrame) {
gfx::Size(8, 8), base::TimeDelta())));
EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
EXPECT_CALL(*provider_, PutCurrentFrame());
- EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _));
+ EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
@@ -262,6 +272,120 @@ TEST_F(VideoFrameSubmitterTest, DidReceiveFrameSubmitsFrame) {
scoped_task_environment_.RunUntilIdle();
}
+TEST_F(VideoFrameSubmitterTest, ShouldSubmitPreventsSubmission) {
+ MakeSubmitter();
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
+ submitter_->UpdateSubmissionState(false);
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_FALSE(submitter_->ShouldSubmit());
+
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
+ submitter_->StartRendering();
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
+ EXPECT_CALL(*provider_, GetCurrentFrame())
+ .WillOnce(Return(media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
+ gfx::Size(8, 8), base::TimeDelta())));
+ EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
+ EXPECT_CALL(*provider_, PutCurrentFrame());
+ EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
+ EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
+ EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
+ submitter_->UpdateSubmissionState(true);
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_TRUE(submitter_->ShouldSubmit());
+
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
+ EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
+ EXPECT_CALL(*provider_, GetCurrentFrame()).Times(0);
+ submitter_->UpdateSubmissionState(false);
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_FALSE(submitter_->ShouldSubmit());
+
+ EXPECT_CALL(*provider_, GetCurrentFrame())
+ .WillOnce(Return(media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
+ gfx::Size(8, 8), base::TimeDelta())));
+ EXPECT_CALL(*provider_, PutCurrentFrame());
+
+ submitter_->SubmitSingleFrame();
+}
+
+// Tests that when set to true SetForceSubmit forces frame submissions.
+// regardless of the internal submit state.
+TEST_F(VideoFrameSubmitterTest, SetForceSubmitForcesSubmission) {
+ MakeSubmitter();
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
+ submitter_->UpdateSubmissionState(false);
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_FALSE(submitter_->ShouldSubmit());
+
+ EXPECT_CALL(*provider_, GetCurrentFrame())
+ .WillOnce(Return(media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
+ gfx::Size(8, 8), base::TimeDelta())));
+ EXPECT_CALL(*provider_, PutCurrentFrame());
+ submitter_->SetForceSubmit(true);
+ EXPECT_TRUE(submitter_->ShouldSubmit());
+
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
+ EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
+ EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
+ EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
+ EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
+ submitter_->StartRendering();
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
+ EXPECT_CALL(*provider_, GetCurrentFrame())
+ .WillOnce(Return(media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
+ gfx::Size(8, 8), base::TimeDelta())));
+ EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
+ EXPECT_CALL(*provider_, PutCurrentFrame());
+ EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
+ EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
+ EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
+ submitter_->UpdateSubmissionState(true);
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_TRUE(submitter_->ShouldSubmit());
+
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
+ EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
+ EXPECT_CALL(*provider_, PutCurrentFrame());
+ EXPECT_CALL(*provider_, GetCurrentFrame())
+ .WillOnce(Return(media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
+ gfx::Size(8, 8), base::TimeDelta())));
+ EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
+ EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
+ EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
+ submitter_->UpdateSubmissionState(false);
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_TRUE(submitter_->ShouldSubmit());
+
+ EXPECT_CALL(*provider_, GetCurrentFrame())
+ .WillOnce(Return(media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
+ gfx::Size(8, 8), base::TimeDelta())));
+ EXPECT_CALL(*provider_, PutCurrentFrame());
+
+ submitter_->SubmitSingleFrame();
+}
+
TEST_F(VideoFrameSubmitterTest, RotationInformationPassedToResourceProvider) {
// Check to see if rotation is communicated pre-rendering.
MakeSubmitter();
@@ -278,13 +402,19 @@ TEST_F(VideoFrameSubmitterTest, RotationInformationPassedToResourceProvider) {
EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
EXPECT_CALL(*provider_, PutCurrentFrame());
EXPECT_CALL(*resource_provider_,
- AppendQuads(_, _, media::VideoRotation::VIDEO_ROTATION_90));
+ AppendQuads(_, _, media::VideoRotation::VIDEO_ROTATION_90, _));
EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
submitter_->DidReceiveFrame();
scoped_task_environment_.RunUntilIdle();
+ {
+ WTF::Vector<viz::ReturnedResource> resources;
+ EXPECT_CALL(*resource_provider_, ReceiveReturnsFromParent(_));
+ submitter_->DidReceiveCompositorFrameAck(resources);
+ }
+
// Check to see if an update to rotation just before rendering is
// communicated.
submitter_->SetRotation(media::VideoRotation::VIDEO_ROTATION_180);
@@ -293,6 +423,12 @@ TEST_F(VideoFrameSubmitterTest, RotationInformationPassedToResourceProvider) {
submitter_->StartRendering();
scoped_task_environment_.RunUntilIdle();
+ {
+ WTF::Vector<viz::ReturnedResource> resources;
+ EXPECT_CALL(*resource_provider_, ReceiveReturnsFromParent(_));
+ submitter_->DidReceiveCompositorFrameAck(resources);
+ }
+
EXPECT_CALL(*provider_, UpdateCurrentFrame(_, _)).WillOnce(Return(true));
EXPECT_CALL(*provider_, GetCurrentFrame())
.WillOnce(Return(media::VideoFrame::CreateFrame(
@@ -301,7 +437,7 @@ TEST_F(VideoFrameSubmitterTest, RotationInformationPassedToResourceProvider) {
EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
EXPECT_CALL(*provider_, PutCurrentFrame());
EXPECT_CALL(*resource_provider_,
- AppendQuads(_, _, media::VideoRotation::VIDEO_ROTATION_180));
+ AppendQuads(_, _, media::VideoRotation::VIDEO_ROTATION_180, _));
EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
@@ -310,6 +446,12 @@ TEST_F(VideoFrameSubmitterTest, RotationInformationPassedToResourceProvider) {
submitter_->OnBeginFrame(args);
scoped_task_environment_.RunUntilIdle();
+ {
+ WTF::Vector<viz::ReturnedResource> resources;
+ EXPECT_CALL(*resource_provider_, ReceiveReturnsFromParent(_));
+ submitter_->DidReceiveCompositorFrameAck(resources);
+ }
+
// Check to see if changing rotation while rendering is handled.
submitter_->SetRotation(media::VideoRotation::VIDEO_ROTATION_270);
@@ -321,7 +463,7 @@ TEST_F(VideoFrameSubmitterTest, RotationInformationPassedToResourceProvider) {
EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
EXPECT_CALL(*provider_, PutCurrentFrame());
EXPECT_CALL(*resource_provider_,
- AppendQuads(_, _, media::VideoRotation::VIDEO_ROTATION_270));
+ AppendQuads(_, _, media::VideoRotation::VIDEO_ROTATION_270, _));
EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
@@ -329,6 +471,139 @@ TEST_F(VideoFrameSubmitterTest, RotationInformationPassedToResourceProvider) {
scoped_task_environment_.RunUntilIdle();
}
+TEST_F(VideoFrameSubmitterTest, IsOpaquePassedToResourceProvider) {
+ // Check to see if is_opaque is communicated pre-rendering.
+ MakeSubmitter();
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_FALSE(submitter_->Rendering());
+
+ // We submit a frame on opacity change.
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
+ EXPECT_CALL(*provider_, GetCurrentFrame())
+ .WillOnce(Return(media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
+ gfx::Size(8, 8), base::TimeDelta())));
+ EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
+ EXPECT_CALL(*provider_, PutCurrentFrame());
+ EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
+ EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
+ EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
+
+ submitter_->SetIsOpaque(false);
+ scoped_task_environment_.RunUntilIdle();
+
+ {
+ WTF::Vector<viz::ReturnedResource> resources;
+ EXPECT_CALL(*resource_provider_, ReceiveReturnsFromParent(_));
+ submitter_->DidReceiveCompositorFrameAck(resources);
+ }
+
+ EXPECT_CALL(*provider_, GetCurrentFrame())
+ .WillOnce(Return(media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
+ gfx::Size(8, 8), base::TimeDelta())));
+ EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
+ EXPECT_CALL(*provider_, PutCurrentFrame());
+ EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, false));
+ EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
+ EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
+
+ submitter_->DidReceiveFrame();
+ scoped_task_environment_.RunUntilIdle();
+
+ {
+ WTF::Vector<viz::ReturnedResource> resources;
+ EXPECT_CALL(*resource_provider_, ReceiveReturnsFromParent(_));
+ submitter_->DidReceiveCompositorFrameAck(resources);
+ }
+
+ // Check to see if an update to is_opaque just before rendering is
+ // communicated.
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
+ EXPECT_CALL(*provider_, GetCurrentFrame())
+ .WillOnce(Return(media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
+ gfx::Size(8, 8), base::TimeDelta())));
+ EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
+ EXPECT_CALL(*provider_, PutCurrentFrame());
+ EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
+ EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
+ EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
+ submitter_->SetIsOpaque(true);
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
+ submitter_->StartRendering();
+ scoped_task_environment_.RunUntilIdle();
+
+ {
+ WTF::Vector<viz::ReturnedResource> resources;
+ EXPECT_CALL(*resource_provider_, ReceiveReturnsFromParent(_));
+ submitter_->DidReceiveCompositorFrameAck(resources);
+ }
+
+ EXPECT_CALL(*provider_, UpdateCurrentFrame(_, _)).WillOnce(Return(true));
+ EXPECT_CALL(*provider_, GetCurrentFrame())
+ .WillOnce(Return(media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
+ gfx::Size(8, 8), base::TimeDelta())));
+ EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
+ EXPECT_CALL(*provider_, PutCurrentFrame());
+ EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, true));
+ EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
+ EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
+
+ viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs(
+ BEGINFRAME_FROM_HERE, now_src_.get());
+ submitter_->OnBeginFrame(args);
+ scoped_task_environment_.RunUntilIdle();
+
+ {
+ WTF::Vector<viz::ReturnedResource> resources;
+ EXPECT_CALL(*resource_provider_, ReceiveReturnsFromParent(_));
+ submitter_->DidReceiveCompositorFrameAck(resources);
+ }
+
+ // Check to see if changing is_opaque while rendering is handled.
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
+ EXPECT_CALL(*provider_, GetCurrentFrame())
+ .WillOnce(Return(media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
+ gfx::Size(8, 8), base::TimeDelta())));
+ EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _)).Times(1);
+ EXPECT_CALL(*provider_, PutCurrentFrame());
+ EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
+ EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
+ EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
+
+ submitter_->SetIsOpaque(false);
+ scoped_task_environment_.RunUntilIdle();
+
+ {
+ WTF::Vector<viz::ReturnedResource> resources;
+ EXPECT_CALL(*resource_provider_, ReceiveReturnsFromParent(_));
+ submitter_->DidReceiveCompositorFrameAck(resources);
+ }
+
+ EXPECT_CALL(*provider_, UpdateCurrentFrame(_, _)).WillOnce(Return(true));
+ EXPECT_CALL(*provider_, GetCurrentFrame())
+ .WillOnce(Return(media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
+ gfx::Size(8, 8), base::TimeDelta())));
+ EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
+ EXPECT_CALL(*provider_, PutCurrentFrame());
+ EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, false));
+ EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
+ EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
+
+ submitter_->OnBeginFrame(args);
+ scoped_task_environment_.RunUntilIdle();
+
+ // Updating |is_opaque_| with the same value should not cause a frame submit.
+ submitter_->SetIsOpaque(false);
+}
+
TEST_F(VideoFrameSubmitterTest, OnBeginFrameSubmitsFrame) {
MakeSubmitter();
scoped_task_environment_.RunUntilIdle();
@@ -345,7 +620,7 @@ TEST_F(VideoFrameSubmitterTest, OnBeginFrameSubmitsFrame) {
gfx::Size(8, 8), base::TimeDelta())));
EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
EXPECT_CALL(*provider_, PutCurrentFrame());
- EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _));
+ EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
@@ -386,6 +661,9 @@ TEST_F(VideoFrameSubmitterTest, NoUpdateOnFrameDoesNotProduceFrame) {
MakeSubmitter();
scoped_task_environment_.RunUntilIdle();
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
+ submitter_->StartRendering();
+
EXPECT_CALL(*provider_, UpdateCurrentFrame(_, _)).WillOnce(Return(false));
EXPECT_CALL(*sink_, DidNotProduceFrame(_));
@@ -399,7 +677,9 @@ TEST_F(VideoFrameSubmitterTest, NotRenderingDoesNotProduceFrame) {
MakeSubmitter();
scoped_task_environment_.RunUntilIdle();
- EXPECT_CALL(*provider_, UpdateCurrentFrame(_, _)).WillOnce(Return(true));
+ // We don't care if UpdateCurrentFrame is called or not; it doesn't matter
+ // if we're not rendering.
+ EXPECT_CALL(*provider_, UpdateCurrentFrame(_, _)).Times(AnyNumber());
EXPECT_CALL(*sink_, DidNotProduceFrame(_));
viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs(
@@ -418,4 +698,149 @@ TEST_F(VideoFrameSubmitterTest, ReturnsResourceOnCompositorAck) {
scoped_task_environment_.RunUntilIdle();
}
+// Tests that after submitting a frame, no frame will be submitted until an ACK
+// was received. This is tested by simulating another BeginFrame message.
+TEST_F(VideoFrameSubmitterTest, WaitingForAckPreventsNewFrame) {
+ MakeSubmitter();
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
+
+ submitter_->StartRendering();
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_CALL(*provider_, UpdateCurrentFrame(_, _))
+ .Times(1)
+ .WillOnce(Return(true));
+
+ EXPECT_CALL(*provider_, GetCurrentFrame())
+ .Times(1)
+ .WillOnce(Return(media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
+ gfx::Size(8, 8), base::TimeDelta())));
+
+ EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
+ EXPECT_CALL(*provider_, PutCurrentFrame());
+ EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
+ EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
+ EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
+
+ viz::BeginFrameArgs args = begin_frame_source_->CreateBeginFrameArgs(
+ BEGINFRAME_FROM_HERE, now_src_.get());
+ submitter_->OnBeginFrame(args);
+ scoped_task_environment_.RunUntilIdle();
+
+ // DidNotProduceFrame should be called because no frame will be submitted
+ // given that the ACK is still pending.
+ EXPECT_CALL(*sink_, DidNotProduceFrame(_)).Times(1);
+
+ // UpdateCurrentFrame should still be called, however, so that the compositor
+ // knows that we missed a frame.
+ EXPECT_CALL(*provider_, UpdateCurrentFrame(_, _)).Times(1);
+
+ std::unique_ptr<base::SimpleTestTickClock> new_time =
+ std::make_unique<base::SimpleTestTickClock>();
+ args = begin_frame_source_->CreateBeginFrameArgs(BEGINFRAME_FROM_HERE,
+ new_time.get());
+ submitter_->OnBeginFrame(args);
+ scoped_task_environment_.RunUntilIdle();
+}
+
+// Test that no crash happens if the context is lost during a frame submission.
+TEST_F(VideoFrameSubmitterTest, ContextLostDuringSubmit) {
+ MakeSubmitter();
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
+
+ submitter_->StartRendering();
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_CALL(*provider_, GetCurrentFrame())
+ .WillOnce(Return(media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
+ gfx::Size(8, 8), base::TimeDelta())));
+ EXPECT_CALL(*provider_, PutCurrentFrame());
+
+ // This will post a task that will later call SubmitFrame(). The call will
+ // happen after OnContextLost().
+ submitter_->SubmitSingleFrame();
+
+ submitter_->OnContextLost();
+
+ scoped_task_environment_.RunUntilIdle();
+}
+
+// Test the behaviour of the ChildLocalSurfaceIdAllocator instance. It checks
+// that the LocalSurfaceId is propoerly set at creation and updated when the
+// video frames change.
+TEST_F(VideoFrameSubmitterTest, FrameSizeChangeUpdatesLocalSurfaceId) {
+ MakeSubmitter();
+ scoped_task_environment_.RunUntilIdle();
+
+ {
+ viz::LocalSurfaceId local_surface_id =
+ submitter_->child_local_surface_id_allocator_
+ .GetCurrentLocalSurfaceId();
+ EXPECT_TRUE(local_surface_id.is_valid());
+ EXPECT_EQ(11u, local_surface_id.parent_sequence_number());
+ EXPECT_EQ(viz::kInitialChildSequenceNumber,
+ local_surface_id.child_sequence_number());
+ EXPECT_TRUE(submitter_->frame_size_.IsEmpty());
+ }
+
+ EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
+
+ submitter_->StartRendering();
+ scoped_task_environment_.RunUntilIdle();
+
+ EXPECT_CALL(*provider_, GetCurrentFrame())
+ .WillOnce(Return(media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
+ gfx::Size(8, 8), base::TimeDelta())));
+ EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
+ EXPECT_CALL(*provider_, PutCurrentFrame());
+ EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
+ EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
+ EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
+
+ submitter_->SubmitSingleFrame();
+ scoped_task_environment_.RunUntilIdle();
+
+ {
+ viz::LocalSurfaceId local_surface_id =
+ submitter_->child_local_surface_id_allocator_
+ .GetCurrentLocalSurfaceId();
+ EXPECT_TRUE(local_surface_id.is_valid());
+ EXPECT_EQ(11u, local_surface_id.parent_sequence_number());
+ EXPECT_EQ(viz::kInitialChildSequenceNumber,
+ local_surface_id.child_sequence_number());
+ EXPECT_EQ(gfx::Rect(8, 8), submitter_->frame_size_);
+ }
+
+ EXPECT_CALL(*provider_, GetCurrentFrame())
+ .WillOnce(Return(media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_YV12, gfx::Size(2, 2), gfx::Rect(gfx::Size(2, 2)),
+ gfx::Size(2, 2), base::TimeDelta())));
+ EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
+ EXPECT_CALL(*provider_, PutCurrentFrame());
+ EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _, _));
+ EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
+ EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
+
+ submitter_->SubmitSingleFrame();
+ scoped_task_environment_.RunUntilIdle();
+
+ {
+ viz::LocalSurfaceId local_surface_id =
+ submitter_->child_local_surface_id_allocator_
+ .GetCurrentLocalSurfaceId();
+ EXPECT_TRUE(local_surface_id.is_valid());
+ EXPECT_EQ(11u, local_surface_id.parent_sequence_number());
+ EXPECT_EQ(viz::kInitialChildSequenceNumber + 1,
+ local_surface_id.child_sequence_number());
+ EXPECT_EQ(gfx::Rect(2, 2), submitter_->frame_size_);
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/BUILD.gn b/chromium/third_party/blink/renderer/platform/heap/BUILD.gn
index b889f9297d0..3859f8c0600 100644
--- a/chromium/third_party/blink/renderer/platform/heap/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/heap/BUILD.gn
@@ -120,9 +120,11 @@ jumbo_source_set("blink_heap_unittests_sources") {
"heap_test_utilities.h",
"heap_traits_test.cc",
"incremental_marking_test.cc",
+ "name_trait_test.cc",
"object_start_bitmap_test.cc",
"persistent_test.cc",
"run_all_tests.cc",
+ "thread_state_scheduling_test.cc",
"worklist_test.cc",
]
diff --git a/chromium/third_party/blink/renderer/platform/heap/blink_gc.h b/chromium/third_party/blink/renderer/platform/heap/blink_gc.h
index 887425e50cf..e4dd72eb15b 100644
--- a/chromium/third_party/blink/renderer/platform/heap/blink_gc.h
+++ b/chromium/third_party/blink/renderer/platform/heap/blink_gc.h
@@ -17,7 +17,6 @@ namespace blink {
class HeapObjectHeader;
class MarkingVisitor;
class Visitor;
-class ScriptWrappableVisitor;
using Address = uint8_t*;
@@ -25,7 +24,6 @@ using FinalizationCallback = void (*)(void*);
using VisitorCallback = void (*)(Visitor*, void*);
using MarkingVisitorCallback = void (*)(MarkingVisitor*, void*);
using TraceCallback = VisitorCallback;
-using TraceWrappersCallback = void (*)(ScriptWrappableVisitor*, void*);
using WeakCallback = VisitorCallback;
using EphemeronCallback = VisitorCallback;
using NameCallback = const char* (*)(const void* self);
@@ -95,7 +93,7 @@ class PLATFORM_EXPORT BlinkGC final {
kEagerSweeping,
};
- enum GCReason {
+ enum class GCReason {
kIdleGC = 0,
kPreciseGC = 1,
kConservativeGC = 2,
@@ -104,7 +102,9 @@ class PLATFORM_EXPORT BlinkGC final {
kPageNavigationGC = 5,
kThreadTerminationGC = 6,
kTesting = 7,
- kLastGCReason = kTesting,
+ kIncrementalIdleGC = 8,
+ kIncrementalV8FollowupGC = 9,
+ kMaxValue = kIncrementalV8FollowupGC,
};
enum ArenaIndices {
diff --git a/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.cc b/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.cc
index 53df6c751e6..deae8e957e9 100644
--- a/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.cc
@@ -52,7 +52,7 @@ bool BlinkGCMemoryDumpProvider::OnMemoryDump(
if (level_of_detail == MemoryDumpLevelOfDetail::DETAILED) {
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kTakeSnapshot,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
}
DumpMemoryTotals(memory_dump);
@@ -76,7 +76,6 @@ void BlinkGCMemoryDumpProvider::ClearProcessDumpForCurrentGC() {
BlinkGCMemoryDumpProvider::BlinkGCMemoryDumpProvider()
: current_process_memory_dump_(new base::trace_event::ProcessMemoryDump(
- nullptr,
{base::trace_event::MemoryDumpLevelOfDetail::DETAILED})) {}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider_test.cc b/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider_test.cc
index 26209a0c80b..bd590dd3bd5 100644
--- a/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider_test.cc
@@ -15,7 +15,7 @@ TEST(BlinkGCDumpProviderTest, MemoryDump) {
base::trace_event::MemoryDumpArgs args = {
base::trace_event::MemoryDumpLevelOfDetail::DETAILED};
std::unique_ptr<base::trace_event::ProcessMemoryDump> dump(
- new base::trace_event::ProcessMemoryDump(nullptr, args));
+ new base::trace_event::ProcessMemoryDump(args));
BlinkGCMemoryDumpProvider::Instance()->OnMemoryDump(args, dump.get());
DCHECK(dump->GetAllocatorDump("blink_gc"));
DCHECK(dump->GetAllocatorDump("blink_gc/allocated_objects"));
diff --git a/chromium/third_party/blink/renderer/platform/heap/garbage_collected.h b/chromium/third_party/blink/renderer/platform/heap/garbage_collected.h
index d7f66a87004..3111f5c7f4a 100644
--- a/chromium/third_party/blink/renderer/platform/heap/garbage_collected.h
+++ b/chromium/third_party/blink/renderer/platform/heap/garbage_collected.h
@@ -54,12 +54,6 @@ struct TraceDescriptor {
bool can_trace_eagerly;
};
-struct TraceWrapperDescriptor {
- STACK_ALLOCATED();
- void* base_object_payload;
- TraceWrappersCallback trace_wrappers_callback;
-};
-
// The GarbageCollectedMixin interface and helper macro
// USING_GARBAGE_COLLECTED_MIXIN can be used to automatically define
// TraceTrait/ObjectAliveTrait on non-leftmost deriving classes
@@ -112,9 +106,6 @@ class PLATFORM_EXPORT GarbageCollectedMixin {
virtual TraceDescriptor GetTraceDescriptor() const {
return {BlinkGC::kNotFullyConstructedObject, nullptr, false};
}
- virtual TraceWrapperDescriptor GetTraceWrapperDescriptor() const {
- return {BlinkGC::kNotFullyConstructedObject, nullptr};
- }
};
#define DEFINE_GARBAGE_COLLECTED_MIXIN_METHODS(TYPE) \
@@ -132,11 +123,6 @@ class PLATFORM_EXPORT GarbageCollectedMixin {
TraceTrait<TYPE>::Trace, TraceEagerlyTrait<TYPE>::value}; \
} \
\
- TraceWrapperDescriptor GetTraceWrapperDescriptor() const override { \
- return {const_cast<TYPE*>(static_cast<const TYPE*>(this)), \
- TraceTrait<TYPE>::TraceWrappers}; \
- } \
- \
private:
// A C++ object's vptr will be initialized to its leftmost base's vtable after
@@ -245,7 +231,6 @@ class GarbageCollectedMixinConstructorMarker
public: \
HeapObjectHeader* GetHeapObjectHeader() const override = 0; \
TraceDescriptor GetTraceDescriptor() const override = 0; \
- TraceWrapperDescriptor GetTraceWrapperDescriptor() const override = 0; \
\
private: \
using merge_garbage_collected_mixins_requires_semicolon = void
diff --git a/chromium/third_party/blink/renderer/platform/heap/gc_info.h b/chromium/third_party/blink/renderer/platform/heap/gc_info.h
index c3290ff97e2..b6e7e42f512 100644
--- a/chromium/third_party/blink/renderer/platform/heap/gc_info.h
+++ b/chromium/third_party/blink/renderer/platform/heap/gc_info.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_GC_INFO_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_GC_INFO_H_
+#include "base/gtest_prod_util.h"
#include "third_party/blink/renderer/platform/heap/finalizer_traits.h"
#include "third_party/blink/renderer/platform/heap/name_traits.h"
#include "third_party/blink/renderer/platform/heap/visitor.h"
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap.cc b/chromium/third_party/blink/renderer/platform/heap/heap.cc
index f71f7abc09a..7688dfb5f79 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap.cc
@@ -60,73 +60,6 @@ namespace blink {
HeapAllocHooks::AllocationHook* HeapAllocHooks::allocation_hook_ = nullptr;
HeapAllocHooks::FreeHook* HeapAllocHooks::free_hook_ = nullptr;
-ThreadHeapStats::ThreadHeapStats()
- : allocated_space_(0),
- allocated_object_size_(0),
- object_size_at_last_gc_(0),
- marked_object_size_(0),
- marked_object_size_at_last_complete_sweep_(0),
- wrapper_count_(0),
- wrapper_count_at_last_gc_(0),
- collected_wrapper_count_(0),
- partition_alloc_size_at_last_gc_(
- WTF::Partitions::TotalSizeOfCommittedPages()),
- estimated_marking_time_per_byte_(0.0) {}
-
-double ThreadHeapStats::EstimatedMarkingTime() {
- // Use 8 ms as initial estimated marking time.
- // 8 ms is long enough for low-end mobile devices to mark common
- // real-world object graphs.
- if (estimated_marking_time_per_byte_ == 0)
- return 0.008;
-
- // Assuming that the collection rate of this GC will be mostly equal to
- // the collection rate of the last GC, estimate the marking time of this GC.
- return estimated_marking_time_per_byte_ *
- (AllocatedObjectSize() + MarkedObjectSize());
-}
-
-void ThreadHeapStats::Reset() {
- object_size_at_last_gc_ = allocated_object_size_ + marked_object_size_;
- partition_alloc_size_at_last_gc_ =
- WTF::Partitions::TotalSizeOfCommittedPages();
- allocated_object_size_ = 0;
- marked_object_size_ = 0;
- wrapper_count_at_last_gc_ = wrapper_count_;
- collected_wrapper_count_ = 0;
-}
-
-void ThreadHeapStats::IncreaseAllocatedObjectSize(size_t delta) {
- allocated_object_size_ += delta;
- ProcessHeap::IncreaseTotalAllocatedObjectSize(delta);
-}
-
-void ThreadHeapStats::DecreaseAllocatedObjectSize(size_t delta) {
- allocated_object_size_ -= delta;
- ProcessHeap::DecreaseTotalAllocatedObjectSize(delta);
-}
-
-void ThreadHeapStats::IncreaseMarkedObjectSize(size_t delta) {
- marked_object_size_ += delta;
- ProcessHeap::IncreaseTotalMarkedObjectSize(delta);
-}
-
-void ThreadHeapStats::IncreaseAllocatedSpace(size_t delta) {
- allocated_space_ += delta;
- ProcessHeap::IncreaseTotalAllocatedSpace(delta);
-}
-
-void ThreadHeapStats::DecreaseAllocatedSpace(size_t delta) {
- allocated_space_ -= delta;
- ProcessHeap::DecreaseTotalAllocatedSpace(delta);
-}
-
-double ThreadHeapStats::LiveObjectRateSinceLastGC() const {
- if (ObjectSizeAtLastGC() > 0)
- return static_cast<double>(MarkedObjectSize()) / ObjectSizeAtLastGC();
- return 0.0;
-}
-
ThreadHeap::ThreadHeap(ThreadState* thread_state)
: thread_state_(thread_state),
heap_stats_collector_(std::make_unique<ThreadHeapStatsCollector>()),
@@ -157,6 +90,31 @@ ThreadHeap::~ThreadHeap() {
delete arenas_[i];
}
+void ThreadHeap::IncreaseAllocatedObjectSize(size_t bytes) {
+ stats_collector()->IncreaseAllocatedObjectSize(bytes);
+ ProcessHeap::IncreaseTotalAllocatedObjectSize(bytes);
+}
+
+void ThreadHeap::DecreaseAllocatedObjectSize(size_t bytes) {
+ stats_collector()->DecreaseAllocatedObjectSize(bytes);
+ ProcessHeap::DecreaseTotalAllocatedObjectSize(bytes);
+}
+
+void ThreadHeap::IncreaseMarkedObjectSize(size_t bytes) {
+ stats_collector()->IncreaseMarkedObjectSize(bytes);
+ ProcessHeap::IncreaseTotalMarkedObjectSize(bytes);
+}
+
+void ThreadHeap::IncreaseAllocatedSpace(size_t bytes) {
+ stats_collector()->IncreaseAllocatedSpace(bytes);
+ ProcessHeap::IncreaseTotalAllocatedSpace(bytes);
+}
+
+void ThreadHeap::DecreaseAllocatedSpace(size_t bytes) {
+ stats_collector()->DecreaseAllocatedSpace(bytes);
+ ProcessHeap::DecreaseTotalAllocatedSpace(bytes);
+}
+
Address ThreadHeap::CheckAndMarkPointer(MarkingVisitor* visitor,
Address address) {
DCHECK(thread_state_->InAtomicMarkingPause());
@@ -236,7 +194,7 @@ void ThreadHeap::DecommitCallbackStacks() {
HeapCompact* ThreadHeap::Compaction() {
if (!compaction_)
- compaction_ = HeapCompact::Create();
+ compaction_ = HeapCompact::Create(this);
return compaction_.get();
}
@@ -255,14 +213,15 @@ void ThreadHeap::RegisterMovingObjectCallback(MovableReference reference,
}
void ThreadHeap::ProcessMarkingStack(Visitor* visitor) {
- bool complete = AdvanceMarkingStackProcessing(
- visitor, std::numeric_limits<double>::infinity());
+ bool complete = AdvanceMarkingStackProcessing(visitor, TimeTicks::Max());
CHECK(complete);
}
void ThreadHeap::MarkNotFullyConstructedObjects(Visitor* visitor) {
- TRACE_EVENT0("blink_gc", "ThreadHeap::MarkNotFullyConstructedObjects");
DCHECK(!thread_state_->IsIncrementalMarking());
+ ThreadHeapStatsCollector::Scope stats_scope(
+ stats_collector(),
+ ThreadHeapStatsCollector::kMarkNotFullyConstructedObjects);
NotFullyConstructedItem item;
while (
@@ -275,7 +234,9 @@ void ThreadHeap::MarkNotFullyConstructedObjects(Visitor* visitor) {
void ThreadHeap::InvokeEphemeronCallbacks(Visitor* visitor) {
// Mark any strong pointers that have now become reachable in ephemeron maps.
- TRACE_EVENT0("blink_gc", "ThreadHeap::InvokeEphemeronCallbacks");
+ ThreadHeapStatsCollector::Scope stats_scope(
+ stats_collector(),
+ ThreadHeapStatsCollector::kMarkInvokeEphemeronCallbacks);
// Avoid supporting a subtle scheme that allows insertion while iterating
// by just creating temporary lists for iteration and sinking.
@@ -296,21 +257,22 @@ void ThreadHeap::InvokeEphemeronCallbacks(Visitor* visitor) {
}
bool ThreadHeap::AdvanceMarkingStackProcessing(Visitor* visitor,
- double deadline_seconds) {
+ TimeTicks deadline) {
const size_t kDeadlineCheckInterval = 2500;
size_t processed_callback_count = 0;
// Ephemeron fixed point loop.
do {
{
// Iteratively mark all objects that are reachable from the objects
- // currently pushed onto the marking stack.
- TRACE_EVENT0("blink_gc", "ThreadHeap::processMarkingStackSingleThreaded");
+ // currently pushed onto the marking worklist.
+ ThreadHeapStatsCollector::Scope stats_scope(
+ stats_collector(), ThreadHeapStatsCollector::kMarkProcessWorklist);
MarkingItem item;
while (marking_worklist_->Pop(WorklistTaskId::MainThread, &item)) {
item.callback(visitor, item.object);
processed_callback_count++;
if (processed_callback_count % kDeadlineCheckInterval == 0) {
- if (deadline_seconds <= CurrentTimeTicksInSeconds()) {
+ if (deadline <= CurrentTimeTicks()) {
return false;
}
}
@@ -325,8 +287,8 @@ bool ThreadHeap::AdvanceMarkingStackProcessing(Visitor* visitor,
}
void ThreadHeap::WeakProcessing(Visitor* visitor) {
- TRACE_EVENT0("blink_gc", "ThreadHeap::WeakProcessing");
- double start_time = WTF::CurrentTimeTicksInMilliseconds();
+ ThreadHeapStatsCollector::Scope stats_scope(
+ stats_collector(), ThreadHeapStatsCollector::kMarkWeakProcessing);
// Weak processing may access unmarked objects but are forbidden from
// ressurecting them.
@@ -340,13 +302,6 @@ void ThreadHeap::WeakProcessing(Visitor* visitor) {
}
// Weak callbacks should not add any new objects for marking.
DCHECK(marking_worklist_->IsGlobalEmpty());
-
- double time_for_weak_processing =
- WTF::CurrentTimeTicksInMilliseconds() - start_time;
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram, weak_processing_time_histogram,
- ("BlinkGC.TimeForGlobalWeakProcessing", 1, 10 * 1000, 50));
- weak_processing_time_histogram.Count(time_for_weak_processing);
}
void ThreadHeap::VerifyMarking() {
@@ -355,84 +310,6 @@ void ThreadHeap::VerifyMarking() {
}
}
-void ThreadHeap::ReportMemoryUsageHistogram() {
- static size_t supported_max_size_in_mb = 4 * 1024;
- static size_t observed_max_size_in_mb = 0;
-
- // We only report the memory in the main thread.
- if (!IsMainThread())
- return;
- // +1 is for rounding up the sizeInMB.
- size_t size_in_mb =
- ThreadState::Current()->Heap().HeapStats().AllocatedSpace() / 1024 /
- 1024 +
- 1;
- if (size_in_mb >= supported_max_size_in_mb)
- size_in_mb = supported_max_size_in_mb - 1;
- if (size_in_mb > observed_max_size_in_mb) {
- // Send a UseCounter only when we see the highest memory usage
- // we've ever seen.
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- EnumerationHistogram, commited_size_histogram,
- ("BlinkGC.CommittedSize", supported_max_size_in_mb));
- commited_size_histogram.Count(size_in_mb);
- observed_max_size_in_mb = size_in_mb;
- }
-}
-
-void ThreadHeap::ReportMemoryUsageForTracing() {
- bool gc_tracing_enabled;
- TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
- &gc_tracing_enabled);
- if (!gc_tracing_enabled)
- return;
-
- ThreadHeap& heap = ThreadState::Current()->Heap();
- // These values are divided by 1024 to avoid overflow in practical cases
- // (TRACE_COUNTER values are 32-bit ints).
- // They are capped to INT_MAX just in case.
- TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
- "ThreadHeap::allocatedObjectSizeKB",
- std::min(heap.HeapStats().AllocatedObjectSize() / 1024,
- static_cast<size_t>(INT_MAX)));
- TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
- "ThreadHeap::markedObjectSizeKB",
- std::min(heap.HeapStats().MarkedObjectSize() / 1024,
- static_cast<size_t>(INT_MAX)));
- TRACE_COUNTER1(
- TRACE_DISABLED_BY_DEFAULT("blink_gc"),
- "ThreadHeap::markedObjectSizeAtLastCompleteSweepKB",
- std::min(heap.HeapStats().MarkedObjectSizeAtLastCompleteSweep() / 1024,
- static_cast<size_t>(INT_MAX)));
- TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
- "ThreadHeap::allocatedSpaceKB",
- std::min(heap.HeapStats().AllocatedSpace() / 1024,
- static_cast<size_t>(INT_MAX)));
- TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
- "ThreadHeap::objectSizeAtLastGCKB",
- std::min(heap.HeapStats().ObjectSizeAtLastGC() / 1024,
- static_cast<size_t>(INT_MAX)));
- TRACE_COUNTER1(
- TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadHeap::wrapperCount",
- std::min(heap.HeapStats().WrapperCount(), static_cast<size_t>(INT_MAX)));
- TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
- "ThreadHeap::wrapperCountAtLastGC",
- std::min(heap.HeapStats().WrapperCountAtLastGC(),
- static_cast<size_t>(INT_MAX)));
- TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
- "ThreadHeap::collectedWrapperCount",
- std::min(heap.HeapStats().CollectedWrapperCount(),
- static_cast<size_t>(INT_MAX)));
- TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
- "ThreadHeap::partitionAllocSizeAtLastGCKB",
- std::min(heap.HeapStats().PartitionAllocSizeAtLastGC() / 1024,
- static_cast<size_t>(INT_MAX)));
- TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
- "Partitions::totalSizeOfCommittedPagesKB",
- std::min(WTF::Partitions::TotalSizeOfCommittedPages() / 1024,
- static_cast<size_t>(INT_MAX)));
-}
-
size_t ThreadHeap::ObjectPayloadSizeForTesting() {
ThreadState::AtomicPauseScope atomic_pause_scope(thread_state_);
size_t object_payload_size = 0;
@@ -448,14 +325,16 @@ size_t ThreadHeap::ObjectPayloadSizeForTesting() {
}
void ThreadHeap::VisitPersistentRoots(Visitor* visitor) {
+ ThreadHeapStatsCollector::Scope stats_scope(
+ stats_collector(), ThreadHeapStatsCollector::kVisitPersistentRoots);
DCHECK(thread_state_->InAtomicMarkingPause());
- TRACE_EVENT0("blink_gc", "ThreadHeap::visitPersistentRoots");
thread_state_->VisitPersistents(visitor);
}
void ThreadHeap::VisitStackRoots(MarkingVisitor* visitor) {
+ ThreadHeapStatsCollector::Scope stats_scope(
+ stats_collector(), ThreadHeapStatsCollector::kVisitStackRoots);
DCHECK(thread_state_->InAtomicMarkingPause());
- TRACE_EVENT0("blink_gc", "ThreadHeap::visitStackRoots");
address_cache_->FlushIfDirty();
address_cache_->EnableLookup();
thread_state_->VisitStack(visitor);
@@ -470,20 +349,8 @@ BasePage* ThreadHeap::LookupPageForAddress(Address address) {
return nullptr;
}
-void ThreadHeap::ResetHeapCounters() {
- DCHECK(thread_state_->InAtomicMarkingPause());
-
- ThreadHeap::ReportMemoryUsageForTracing();
-
- ProcessHeap::DecreaseTotalAllocatedObjectSize(stats_.AllocatedObjectSize());
- ProcessHeap::DecreaseTotalMarkedObjectSize(stats_.MarkedObjectSize());
-
- stats_.Reset();
-}
-
void ThreadHeap::MakeConsistentForGC() {
DCHECK(thread_state_->InAtomicMarkingPause());
- TRACE_EVENT0("blink_gc", "ThreadHeap::MakeConsistentForGC");
for (int i = 0; i < BlinkGC::kNumberOfArenas; ++i)
arenas_[i]->MakeConsistentForGC();
}
@@ -498,6 +365,8 @@ void ThreadHeap::Compact() {
if (!Compaction()->IsCompacting())
return;
+ ThreadHeapStatsCollector::Scope stats_scope(
+ stats_collector(), ThreadHeapStatsCollector::kAtomicPhaseCompaction);
// Compaction is done eagerly and before the mutator threads get
// to run again. Doing it lazily is problematic, as the mutator's
// references to live objects could suddenly be invalidated by
@@ -588,8 +457,10 @@ void ThreadHeap::PromptlyFreed(size_t gc_info_index) {
#if defined(ADDRESS_SANITIZER)
void ThreadHeap::PoisonAllHeaps() {
- RecursiveMutexLocker persistent_lock(
- ProcessHeap::CrossThreadPersistentMutex());
+ // This lock must be held because other threads may access cross-thread
+ // persistents and should not observe them in a poisoned state.
+ MutexLocker lock(ProcessHeap::CrossThreadPersistentMutex());
+
// Poisoning all unmarked objects in the other arenas.
for (int i = 1; i < BlinkGC::kNumberOfArenas; i++)
arenas_[i]->PoisonArena();
@@ -601,8 +472,10 @@ void ThreadHeap::PoisonAllHeaps() {
}
void ThreadHeap::PoisonEagerArena() {
- RecursiveMutexLocker persistent_lock(
- ProcessHeap::CrossThreadPersistentMutex());
+ // This lock must be held because other threads may access cross-thread
+ // persistents and should not observe them in a poisoned state.
+ MutexLocker lock(ProcessHeap::CrossThreadPersistentMutex());
+
arenas_[BlinkGC::kEagerSweepArenaIndex]->PoisonArena();
// CrossThreadPersistents in unmarked objects may be accessed from other
// threads (e.g. in CrossThreadPersistentRegion::shouldTracePersistent) and
@@ -704,15 +577,14 @@ void ThreadHeap::TakeSnapshot(SnapshotType type) {
->AddOwnershipEdge(classes_dump->guid(), heaps_dump->guid());
}
-bool ThreadHeap::AdvanceLazySweep(double deadline_seconds) {
+bool ThreadHeap::AdvanceLazySweep(TimeTicks deadline) {
for (int i = 0; i < BlinkGC::kNumberOfArenas; i++) {
// lazySweepWithDeadline() won't check the deadline until it sweeps
// 10 pages. So we give a small slack for safety.
- double slack = 0.001;
- double remaining_budget =
- deadline_seconds - slack - CurrentTimeTicksInSeconds();
- if (remaining_budget <= 0 ||
- !arenas_[i]->LazySweepWithDeadline(deadline_seconds)) {
+ TimeDelta slack = TimeDelta::FromSecondsD(0.001);
+ TimeDelta remaining_budget = deadline - slack - CurrentTimeTicks();
+ if (remaining_budget <= TimeDelta() ||
+ !arenas_[i]->LazySweepWithDeadline(deadline)) {
return false;
}
}
@@ -728,7 +600,7 @@ void ThreadHeap::WriteBarrier(void* value) {
BasePage* const page = PageFromObject(value);
HeapObjectHeader* const header =
page->IsLargeObjectPage()
- ? static_cast<LargeObjectPage*>(page)->GetHeapObjectHeader()
+ ? static_cast<LargeObjectPage*>(page)->ObjectHeader()
: static_cast<NormalPage*>(page)->FindHeaderFromAddress(
reinterpret_cast<Address>(const_cast<void*>(value)));
if (header->IsMarked())
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap.h b/chromium/third_party/blink/renderer/platform/heap/heap.h
index f4d3bfc9aef..1623c4188ce 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap.h
+++ b/chromium/third_party/blink/renderer/platform/heap/heap.h
@@ -31,6 +31,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_HEAP_H_
+#include <limits>
#include <memory>
#include "base/macros.h"
@@ -147,61 +148,6 @@ class ObjectAliveTrait<T, true> {
}
};
-// Stats for the heap.
-class ThreadHeapStats {
- USING_FAST_MALLOC(ThreadHeapStats);
-
- public:
- ThreadHeapStats();
- void SetMarkedObjectSizeAtLastCompleteSweep(size_t size) {
- marked_object_size_at_last_complete_sweep_ = size;
- }
- size_t MarkedObjectSizeAtLastCompleteSweep() {
- return marked_object_size_at_last_complete_sweep_;
- }
- void IncreaseAllocatedObjectSize(size_t delta);
- void DecreaseAllocatedObjectSize(size_t delta);
- size_t AllocatedObjectSize() { return allocated_object_size_; }
- void IncreaseMarkedObjectSize(size_t delta);
- size_t MarkedObjectSize() const { return marked_object_size_; }
- void IncreaseAllocatedSpace(size_t delta);
- void DecreaseAllocatedSpace(size_t delta);
- size_t AllocatedSpace() { return allocated_space_; }
- size_t ObjectSizeAtLastGC() const { return object_size_at_last_gc_; }
- double LiveObjectRateSinceLastGC() const;
- void IncreaseWrapperCount(size_t delta) { wrapper_count_ += delta; }
- void DecreaseWrapperCount(size_t delta) { wrapper_count_ -= delta; }
- size_t WrapperCount() { return AcquireLoad(&wrapper_count_); }
- size_t WrapperCountAtLastGC() { return wrapper_count_at_last_gc_; }
- void IncreaseCollectedWrapperCount(size_t delta) {
- collected_wrapper_count_ += delta;
- }
- size_t CollectedWrapperCount() { return collected_wrapper_count_; }
- size_t PartitionAllocSizeAtLastGC() {
- return partition_alloc_size_at_last_gc_;
- }
- void SetEstimatedMarkingTimePerByte(double estimated_marking_time_per_byte) {
- estimated_marking_time_per_byte_ = estimated_marking_time_per_byte;
- }
- double EstimatedMarkingTimePerByte() const {
- return estimated_marking_time_per_byte_;
- }
- double EstimatedMarkingTime();
- void Reset();
-
- private:
- size_t allocated_space_;
- size_t allocated_object_size_;
- size_t object_size_at_last_gc_;
- size_t marked_object_size_;
- size_t marked_object_size_at_last_complete_sweep_;
- size_t wrapper_count_;
- size_t wrapper_count_at_last_gc_;
- size_t collected_wrapper_count_;
- size_t partition_alloc_size_at_last_gc_;
- double estimated_marking_time_per_byte_;
-};
-
class PLATFORM_EXPORT ThreadHeap {
public:
explicit ThreadHeap(ThreadState*);
@@ -245,8 +191,6 @@ class PLATFORM_EXPORT ThreadHeap {
StackFrameDepth& GetStackFrameDepth() { return stack_frame_depth_; }
- ThreadHeapStats& HeapStats() { return stats_; }
-
MarkingWorklist* GetMarkingWorklist() const {
return marking_worklist_.get();
}
@@ -346,7 +290,7 @@ class PLATFORM_EXPORT ThreadHeap {
void ProcessMarkingStack(Visitor*);
void WeakProcessing(Visitor*);
void MarkNotFullyConstructedObjects(Visitor*);
- bool AdvanceMarkingStackProcessing(Visitor*, double deadline_seconds);
+ bool AdvanceMarkingStackProcessing(Visitor*, TimeTicks deadline);
void VerifyMarking();
// Conservatively checks whether an address is a pointer in any of the
@@ -369,9 +313,6 @@ class PLATFORM_EXPORT ThreadHeap {
// heap-page if one exists.
BasePage* LookupPageForAddress(Address);
- static void ReportMemoryUsageHistogram();
- static void ReportMemoryUsageForTracing();
-
HeapCompact* Compaction();
// Get one of the heap structures for this thread.
@@ -446,7 +387,7 @@ class PLATFORM_EXPORT ThreadHeap {
void Compact();
- bool AdvanceLazySweep(double deadline_seconds);
+ bool AdvanceLazySweep(TimeTicks deadline);
void PrepareForSweep();
void RemoveAllPages();
@@ -459,6 +400,12 @@ class PLATFORM_EXPORT ThreadHeap {
return heap_stats_collector_.get();
}
+ void IncreaseAllocatedObjectSize(size_t);
+ void DecreaseAllocatedObjectSize(size_t);
+ void IncreaseMarkedObjectSize(size_t);
+ void IncreaseAllocatedSpace(size_t);
+ void DecreaseAllocatedSpace(size_t);
+
#if defined(ADDRESS_SANITIZER)
void PoisonEagerArena();
void PoisonAllHeaps();
@@ -476,9 +423,6 @@ class PLATFORM_EXPORT ThreadHeap {
#endif
private:
- // Reset counters that track live and allocated-since-last-GC sizes.
- void ResetHeapCounters();
-
static int ArenaIndexForObjectSize(size_t);
void CommitCallbackStacks();
@@ -491,7 +435,6 @@ class PLATFORM_EXPORT ThreadHeap {
void WriteBarrier(void* value);
ThreadState* thread_state_;
- ThreadHeapStats stats_;
std::unique_ptr<ThreadHeapStatsCollector> heap_stats_collector_;
std::unique_ptr<RegionTree> region_tree_;
std::unique_ptr<AddressCache> address_cache_;
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_allocator.h b/chromium/third_party/blink/renderer/platform/heap/heap_allocator.h
index 814264b9de3..ab841704e2e 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_allocator.h
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_allocator.h
@@ -168,6 +168,10 @@ class PLATFORM_EXPORT HeapAllocator {
return ThreadState::Current()->IsObjectResurrectionForbidden();
}
+ static bool IsSweepForbidden() {
+ return ThreadState::Current()->SweepForbidden();
+ }
+
template <typename T>
static bool IsHeapObjectAlive(T* object) {
return ThreadHeap::IsHeapObjectAlive(object);
@@ -501,6 +505,7 @@ class HeapHashCountedSet
template <typename T, size_t inlineCapacity = 0>
class HeapVector : public Vector<T, inlineCapacity, HeapAllocator> {
IS_GARBAGE_COLLECTED_TYPE();
+ using Base = Vector<T, inlineCapacity, HeapAllocator>;
public:
HeapVector() {
@@ -509,6 +514,30 @@ class HeapVector : public Vector<T, inlineCapacity, HeapAllocator> {
"instead of HeapVector<>");
}
+ void* operator new(size_t size) {
+ static_assert(
+ inlineCapacity == 0 || !VectorTraits<T>::kNeedsDestruction,
+ "on-heap HeapVector<Persistent<>> should not have an inline capacity");
+ return Base::operator new(size);
+ }
+ void operator delete(void* p) { return Base::operator delete(p); };
+ void* operator new[](size_t size) {
+ static_assert(
+ inlineCapacity == 0 || !VectorTraits<T>::kNeedsDestruction,
+ "on-heap HeapVector<Persistent<>> should not have an inline capacity");
+ return Base::operator new[](size);
+ }
+ void operator delete[](void* p) { return Base::operator delete[](p); };
+ void* operator new(size_t size, NotNullTag null_tag, void* location) {
+ static_assert(
+ inlineCapacity == 0 || !VectorTraits<T>::kNeedsDestruction,
+ "on-heap HeapVector<Persistent<>> should not have an inline capacity");
+ return Base::operator new(size, null_tag, location);
+ }
+ void* operator new(size_t size, void* location) {
+ return Base::operator new(size, location);
+ }
+
explicit HeapVector(size_t size)
: Vector<T, inlineCapacity, HeapAllocator>(size) {}
@@ -523,6 +552,7 @@ class HeapVector : public Vector<T, inlineCapacity, HeapAllocator> {
template <typename T, size_t inlineCapacity = 0>
class HeapDeque : public Deque<T, inlineCapacity, HeapAllocator> {
IS_GARBAGE_COLLECTED_TYPE();
+ using Base = Deque<T, inlineCapacity, HeapAllocator>;
public:
HeapDeque() {
@@ -531,6 +561,30 @@ class HeapDeque : public Deque<T, inlineCapacity, HeapAllocator> {
"of HeapDeque<>");
}
+ void* operator new(size_t size) {
+ static_assert(
+ inlineCapacity == 0 || !VectorTraits<T>::kNeedsDestruction,
+ "on-heap HeapDeque<Persistent<>> should not have an inline capacity");
+ return Base::operator new(size);
+ }
+ void operator delete(void* p) { return Base::operator delete(p); };
+ void* operator new[](size_t size) {
+ static_assert(
+ inlineCapacity == 0 || !VectorTraits<T>::kNeedsDestruction,
+ "on-heap HeapDequer<Persistent<>> should not have an inline capacity");
+ return Base::operator new[](size);
+ }
+ void operator delete[](void* p) { return Base::operator delete[](p); };
+ void* operator new(size_t size, NotNullTag null_tag, void* location) {
+ static_assert(
+ inlineCapacity == 0 || !VectorTraits<T>::kNeedsDestruction,
+ "on-heap HeapDeque<Persistent<>> should not have an inline capacity");
+ return Base::operator new(size, null_tag, location);
+ }
+ void* operator new(size_t size, void* location) {
+ return Base::operator new(size, location);
+ }
+
explicit HeapDeque(size_t size)
: Deque<T, inlineCapacity, HeapAllocator>(size) {}
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_compact.cc b/chromium/third_party/blink/renderer/platform/heap/heap_compact.cc
index 7bff2f4046b..4594fbfd18a 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_compact.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_compact.cc
@@ -8,6 +8,7 @@
#include "base/memory/ptr_util.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h"
#include "third_party/blink/renderer/platform/heap/sparse_heap_bitmap.h"
#include "third_party/blink/renderer/platform/histogram.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -256,14 +257,12 @@ class HeapCompact::MovableObjectFixups final {
std::unique_ptr<SparseHeapBitmap> interiors_;
};
-HeapCompact::HeapCompact()
- : do_compact_(false),
+HeapCompact::HeapCompact(ThreadHeap* heap)
+ : heap_(heap),
+ do_compact_(false),
gc_count_since_last_compaction_(0),
free_list_size_(0),
- compactable_arenas_(0u),
- freed_pages_(0),
- freed_size_(0),
- start_compaction_time_ms_(0) {
+ compactable_arenas_(0u) {
// The heap compaction implementation assumes the contiguous range,
//
// [Vector1ArenaIndex, HashTableArenaIndex]
@@ -298,14 +297,15 @@ bool HeapCompact::ShouldCompact(ThreadHeap* heap,
if (!RuntimeEnabledFeatures::HeapCompactionEnabled())
return false;
- LOG_HEAP_COMPACTION() << "shouldCompact(): gc=" << reason
+ LOG_HEAP_COMPACTION() << "shouldCompact(): gc=" << static_cast<int>(reason)
<< " count=" << gc_count_since_last_compaction_
<< " free=" << free_list_size_;
gc_count_since_last_compaction_++;
// It is only safe to compact during non-conservative GCs.
// TODO: for the main thread, limit this further to only idle GCs.
- if (reason != BlinkGC::kIdleGC && reason != BlinkGC::kPreciseGC &&
- reason != BlinkGC::kForcedGC)
+ if (reason != BlinkGC::GCReason::kIdleGC &&
+ reason != BlinkGC::GCReason::kPreciseGC &&
+ reason != BlinkGC::GCReason::kForcedGC)
return false;
// If the GCing thread requires a stack scan, do not compact.
@@ -330,7 +330,7 @@ bool HeapCompact::ShouldCompact(ThreadHeap* heap,
// TODO: add some form of compaction overhead estimate to the marking
// time estimate.
- UpdateHeapResidency(heap);
+ UpdateHeapResidency();
#if STRESS_TEST_HEAP_COMPACTION
// Exercise the handling of object movement by compacting as
@@ -348,8 +348,6 @@ void HeapCompact::Initialize(ThreadState* state) {
DCHECK(RuntimeEnabledFeatures::HeapCompactionEnabled());
LOG_HEAP_COMPACTION() << "Compacting: free=" << free_list_size_;
do_compact_ = true;
- freed_pages_ = 0;
- freed_size_ = 0;
fixups_.reset();
gc_count_since_last_compaction_ = 0;
force_compaction_gc_ = false;
@@ -371,7 +369,7 @@ void HeapCompact::RegisterMovingObjectCallback(MovableReference reference,
Fixups().AddFixupCallback(reference, callback, callback_data);
}
-void HeapCompact::UpdateHeapResidency(ThreadHeap* heap) {
+void HeapCompact::UpdateHeapResidency() {
size_t total_arena_size = 0;
size_t total_free_list_size = 0;
@@ -381,7 +379,7 @@ void HeapCompact::UpdateHeapResidency(ThreadHeap* heap) {
#endif
for (int i = BlinkGC::kVector1ArenaIndex; i <= BlinkGC::kHashTableArenaIndex;
++i) {
- NormalPageArena* arena = static_cast<NormalPageArena*>(heap->Arena(i));
+ NormalPageArena* arena = static_cast<NormalPageArena*>(heap_->Arena(i));
size_t arena_size = arena->ArenaSize();
size_t free_list_size = arena->FreeListSize();
total_arena_size += arena_size;
@@ -412,8 +410,8 @@ void HeapCompact::FinishedArenaCompaction(NormalPageArena* arena,
if (!do_compact_)
return;
- freed_pages_ += freed_pages;
- freed_size_ += freed_size;
+ heap_->stats_collector()->IncreaseCompactionFreedPages(freed_pages);
+ heap_->stats_collector()->IncreaseCompactionFreedSize(freed_size);
}
void HeapCompact::Relocate(Address from, Address to) {
@@ -424,9 +422,6 @@ void HeapCompact::Relocate(Address from, Address to) {
void HeapCompact::StartThreadCompaction() {
if (!do_compact_)
return;
-
- if (!start_compaction_time_ms_)
- start_compaction_time_ms_ = WTF::CurrentTimeTicksInMilliseconds();
}
void HeapCompact::FinishThreadCompaction() {
@@ -439,28 +434,6 @@ void HeapCompact::FinishThreadCompaction() {
#endif
fixups_.reset();
do_compact_ = false;
-
- double time_for_heap_compaction =
- WTF::CurrentTimeTicksInMilliseconds() - start_compaction_time_ms_;
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram, time_for_heap_compaction_histogram,
- ("BlinkGC.TimeForHeapCompaction", 1, 10 * 1000, 50));
- time_for_heap_compaction_histogram.Count(time_for_heap_compaction);
- start_compaction_time_ms_ = 0;
-
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram, object_size_freed_by_heap_compaction,
- ("BlinkGC.ObjectSizeFreedByHeapCompaction", 1, 4 * 1024 * 1024, 50));
- object_size_freed_by_heap_compaction.Count(freed_size_ / 1024);
-
-#if DEBUG_LOG_HEAP_COMPACTION_RUNNING_TIME
- LOG_HEAP_COMPACTION_INTERNAL()
- << "Compaction stats: time=" << time_for_heap_compaction
- << "ms, pages freed=" << freed_pages_ << ", size=" << freed_size_;
-#else
- LOG_HEAP_COMPACTION() << "Compaction stats: freed pages=" << freed_pages_
- << " size=" << freed_size_;
-#endif
}
void HeapCompact::AddCompactingPage(BasePage* page) {
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_compact.h b/chromium/third_party/blink/renderer/platform/heap/heap_compact.h
index 30d489ef7f2..dc32e77b229 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_compact.h
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_compact.h
@@ -42,8 +42,8 @@ class ThreadHeap;
class PLATFORM_EXPORT HeapCompact final {
public:
- static std::unique_ptr<HeapCompact> Create() {
- return base::WrapUnique(new HeapCompact);
+ static std::unique_ptr<HeapCompact> Create(ThreadHeap* heap) {
+ return base::WrapUnique(new HeapCompact(heap));
}
~HeapCompact();
@@ -129,13 +129,13 @@ class PLATFORM_EXPORT HeapCompact final {
private:
class MovableObjectFixups;
- HeapCompact();
+ explicit HeapCompact(ThreadHeap*);
// Sample the amount of fragmentation and heap memory currently residing
// on the freelists of the arenas we're able to compact. The computed
// numbers will be subsequently used to determine if a heap compaction
// is on order (shouldCompact().)
- void UpdateHeapResidency(ThreadHeap*);
+ void UpdateHeapResidency();
// Parameters controlling when compaction should be done:
@@ -146,6 +146,8 @@ class PLATFORM_EXPORT HeapCompact final {
// should be considered.
static const size_t kFreeListSizeThreshold = 512 * 1024;
+ ThreadHeap* const heap_;
+
MovableObjectFixups& Fixups();
std::unique_ptr<MovableObjectFixups> fixups_;
@@ -162,13 +164,6 @@ class PLATFORM_EXPORT HeapCompact final {
// the range of BlinkGC::ArenaIndices.
unsigned compactable_arenas_;
- // Stats, number of (complete) pages freed/decommitted +
- // bytes freed (which will include partial pages.)
- size_t freed_pages_;
- size_t freed_size_;
-
- double start_compaction_time_ms_;
-
static bool force_compaction_gc_;
};
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_page.cc b/chromium/third_party/blink/renderer/platform/heap/heap_page.cc
index 27ef4c5e141..47b4c3d7fed 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_page.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_page.cc
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/platform/heap/heap_page.h"
+#include "base/allocator/partition_allocator/page_allocator.h"
#include "base/auto_reset.h"
#include "base/trace_event/process_memory_dump.h"
#include "third_party/blink/public/platform/platform.h"
@@ -275,26 +276,22 @@ Address BaseArena::LazySweep(size_t allocation_size, size_t gc_info_index) {
ScriptForbiddenScope script_forbidden;
result = LazySweepPages(allocation_size, gc_info_index);
}
- ThreadHeap::ReportMemoryUsageForTracing();
return result;
}
void BaseArena::SweepUnsweptPage() {
BasePage* page = first_unswept_page_;
- if (page->IsEmpty()) {
- page->Unlink(&first_unswept_page_);
+ const bool is_empty = page->Sweep();
+ page->Unlink(&first_unswept_page_);
+ if (is_empty) {
page->RemoveFromHeap();
} else {
- // Sweep a page and move the page from m_firstUnsweptPages to
- // m_firstPages.
- page->Sweep();
- page->Unlink(&first_unswept_page_);
page->Link(&first_page_);
page->MarkAsSwept();
}
}
-bool BaseArena::LazySweepWithDeadline(double deadline_seconds) {
+bool BaseArena::LazySweepWithDeadline(TimeTicks deadline) {
// It might be heavy to call
// Platform::current()->monotonicallyIncreasingTimeSeconds() per page (i.e.,
// 128 KB sweep or one LargeObject sweep), so we check the deadline per 10
@@ -317,9 +314,8 @@ bool BaseArena::LazySweepWithDeadline(double deadline_seconds) {
while (!SweepingCompleted()) {
SweepUnsweptPage();
if (page_count % kDeadlineCheckInterval == 0) {
- if (deadline_seconds <= CurrentTimeTicksInSeconds()) {
+ if (deadline <= CurrentTimeTicks()) {
// Deadline has come.
- ThreadHeap::ReportMemoryUsageForTracing();
if (normal_arena)
normal_arena->SetIsLazySweeping(false);
return SweepingCompleted();
@@ -327,7 +323,6 @@ bool BaseArena::LazySweepWithDeadline(double deadline_seconds) {
}
page_count++;
}
- ThreadHeap::ReportMemoryUsageForTracing();
if (normal_arena)
normal_arena->SetIsLazySweeping(false);
return true;
@@ -344,7 +339,6 @@ void BaseArena::CompleteSweep() {
while (!SweepingCompleted()) {
SweepUnsweptPage();
}
- ThreadHeap::ReportMemoryUsageForTracing();
}
Address BaseArena::AllocateLargeObject(size_t allocation_size,
@@ -507,11 +501,6 @@ void NormalPageArena::SweepAndCompact() {
while (!SweepingCompleted()) {
BasePage* page = first_unswept_page_;
- if (page->IsEmpty()) {
- page->Unlink(&first_unswept_page_);
- page->RemoveFromHeap();
- continue;
- }
// Large objects do not belong to this arena.
DCHECK(!page->IsLargeObjectPage());
NormalPage* normal_page = static_cast<NormalPage*>(page);
@@ -698,7 +687,7 @@ void NormalPageArena::AllocatePage() {
new (page_memory->WritableStart()) NormalPage(page_memory, this);
page->Link(&first_page_);
- GetThreadState()->Heap().HeapStats().IncreaseAllocatedSpace(page->size());
+ GetThreadState()->Heap().IncreaseAllocatedSpace(page->size());
#if DCHECK_IS_ON() || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER)
// Allow the following addToFreeList() to add the newly allocated memory
// to the free list.
@@ -712,7 +701,7 @@ void NormalPageArena::AllocatePage() {
}
void NormalPageArena::FreePage(NormalPage* page) {
- GetThreadState()->Heap().HeapStats().DecreaseAllocatedSpace(page->size());
+ GetThreadState()->Heap().DecreaseAllocatedSpace(page->size());
PageMemory* memory = page->Storage();
page->~NormalPage();
@@ -776,7 +765,7 @@ void NormalPageArena::PromptlyFreeObjectInFreeList(HeapObjectHeader* header,
// coalescing.
header->Unmark();
}
- GetThreadState()->Heap().HeapStats().DecreaseAllocatedObjectSize(size);
+ GetThreadState()->Heap().DecreaseAllocatedObjectSize(size);
}
bool NormalPageArena::ExpandObject(HeapObjectHeader* header, size_t new_size) {
@@ -839,17 +828,13 @@ Address NormalPageArena::LazySweepPages(size_t allocation_size,
Address result = nullptr;
while (!SweepingCompleted()) {
BasePage* page = first_unswept_page_;
- if (page->IsEmpty()) {
- page->Unlink(&first_unswept_page_);
+ const bool is_empty = page->Sweep();
+ page->Unlink(&first_unswept_page_);
+ if (is_empty) {
page->RemoveFromHeap();
} else {
- // Sweep a page and move the page from m_firstUnsweptPages to
- // m_firstPages.
- page->Sweep();
- page->Unlink(&first_unswept_page_);
page->Link(&first_page_);
page->MarkAsSwept();
-
// For NormalPage, stop lazy sweeping once we find a slot to
// allocate a new object.
result = AllocateFromFreeList(allocation_size, gc_info_index);
@@ -868,18 +853,19 @@ void NormalPageArena::SetRemainingAllocationSize(
// - if previous alloc checkpoint is larger, allocation size has increased.
// - if smaller, a net reduction in size since last call to
// updateRemainingAllocationSize().
- if (last_remaining_allocation_size_ > remaining_allocation_size_)
- GetThreadState()->Heap().HeapStats().IncreaseAllocatedObjectSize(
+ if (last_remaining_allocation_size_ > remaining_allocation_size_) {
+ GetThreadState()->Heap().IncreaseAllocatedObjectSize(
last_remaining_allocation_size_ - remaining_allocation_size_);
- else if (last_remaining_allocation_size_ != remaining_allocation_size_)
- GetThreadState()->Heap().HeapStats().DecreaseAllocatedObjectSize(
+ } else if (last_remaining_allocation_size_ != remaining_allocation_size_) {
+ GetThreadState()->Heap().DecreaseAllocatedObjectSize(
remaining_allocation_size_ - last_remaining_allocation_size_);
+ }
last_remaining_allocation_size_ = remaining_allocation_size_;
}
void NormalPageArena::UpdateRemainingAllocationSize() {
if (last_remaining_allocation_size_ > RemainingAllocationSize()) {
- GetThreadState()->Heap().HeapStats().IncreaseAllocatedObjectSize(
+ GetThreadState()->Heap().IncreaseAllocatedObjectSize(
last_remaining_allocation_size_ - RemainingAllocationSize());
last_remaining_allocation_size_ = RemainingAllocationSize();
}
@@ -1042,23 +1028,20 @@ Address LargeObjectArena::DoAllocateLargeObjectPage(size_t allocation_size,
large_object->Link(&first_page_);
- GetThreadState()->Heap().HeapStats().IncreaseAllocatedSpace(
- large_object->size());
- GetThreadState()->Heap().HeapStats().IncreaseAllocatedObjectSize(
- large_object->size());
+ GetThreadState()->Heap().IncreaseAllocatedSpace(large_object->size());
+ GetThreadState()->Heap().IncreaseAllocatedObjectSize(
+ large_object->PayloadSize());
return result;
}
void LargeObjectArena::FreeLargeObjectPage(LargeObjectPage* object) {
ASAN_UNPOISON_MEMORY_REGION(object->Payload(), object->PayloadSize());
- object->GetHeapObjectHeader()->Finalize(object->Payload(),
- object->PayloadSize());
- GetThreadState()->Heap().HeapStats().DecreaseAllocatedSpace(object->size());
+ object->ObjectHeader()->Finalize(object->Payload(), object->PayloadSize());
+ GetThreadState()->Heap().DecreaseAllocatedSpace(object->size());
// Unpoison the object header and allocationGranularity bytes after the
// object before freeing.
- ASAN_UNPOISON_MEMORY_REGION(object->GetHeapObjectHeader(),
- sizeof(HeapObjectHeader));
+ ASAN_UNPOISON_MEMORY_REGION(object->ObjectHeader(), sizeof(HeapObjectHeader));
ASAN_UNPOISON_MEMORY_REGION(object->GetAddress() + object->size(),
kAllocationGranularity);
@@ -1073,22 +1056,19 @@ Address LargeObjectArena::LazySweepPages(size_t allocation_size,
size_t swept_size = 0;
while (!SweepingCompleted()) {
BasePage* page = first_unswept_page_;
- if (page->IsEmpty()) {
- swept_size += static_cast<LargeObjectPage*>(page)->PayloadSize();
- page->Unlink(&first_unswept_page_);
+ const bool is_empty = page->Sweep();
+ page->Unlink(&first_unswept_page_);
+ if (is_empty) {
+ swept_size += static_cast<LargeObjectPage*>(page)->ObjectSize();
page->RemoveFromHeap();
// For LargeObjectPage, stop lazy sweeping once we have swept
- // more than allocationSize bytes.
+ // more than |allocation_size| bytes.
if (swept_size >= allocation_size) {
result = DoAllocateLargeObjectPage(allocation_size, gc_info_index);
DCHECK(result);
break;
}
} else {
- // Sweep a page and move the page from m_firstUnsweptPages to
- // m_firstPages.
- page->Sweep();
- page->Unlink(&first_unswept_page_);
page->Link(&first_page_);
page->MarkAsSwept();
}
@@ -1166,11 +1146,10 @@ void FreeList::AddToFreeList(Address address, size_t size) {
#if DCHECK_IS_ON() || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) || \
defined(MEMORY_SANITIZER)
NO_SANITIZE_MEMORY
-void NEVER_INLINE
-FreeList::GetAllowedAndForbiddenCounts(Address address,
- size_t size,
- size_t& allowed_count,
- size_t& forbidden_count) {
+void NOINLINE FreeList::GetAllowedAndForbiddenCounts(Address address,
+ size_t size,
+ size_t& allowed_count,
+ size_t& forbidden_count) {
for (size_t i = sizeof(FreeListEntry); i < size; i++) {
if (address[i] == kReuseAllowedZapValue)
allowed_count++;
@@ -1183,7 +1162,7 @@ FreeList::GetAllowedAndForbiddenCounts(Address address,
NO_SANITIZE_ADDRESS
NO_SANITIZE_MEMORY
-void NEVER_INLINE FreeList::ZapFreedMemory(Address address, size_t size) {
+void NOINLINE FreeList::ZapFreedMemory(Address address, size_t size) {
for (size_t i = 0; i < size; i++) {
// See the comment in addToFreeList().
if (address[i] != kReuseAllowedZapValue)
@@ -1191,8 +1170,7 @@ void NEVER_INLINE FreeList::ZapFreedMemory(Address address, size_t size) {
}
}
-void NEVER_INLINE FreeList::CheckFreedMemoryIsZapped(Address address,
- size_t size) {
+void NOINLINE FreeList::CheckFreedMemoryIsZapped(Address address, size_t size) {
for (size_t i = 0; i < size; i++) {
DCHECK(address[i] == kReuseAllowedZapValue ||
address[i] == kReuseForbiddenZapValue);
@@ -1312,11 +1290,6 @@ size_t NormalPage::ObjectPayloadSizeForTesting() {
return object_payload_size;
}
-bool NormalPage::IsEmpty() {
- HeapObjectHeader* header = reinterpret_cast<HeapObjectHeader*>(Payload());
- return header->IsFree() && header->size() == PayloadSize();
-}
-
void NormalPage::RemoveFromHeap() {
ArenaForNormalPage()->FreePage(this);
}
@@ -1324,16 +1297,17 @@ void NormalPage::RemoveFromHeap() {
#if !DCHECK_IS_ON() && !defined(LEAK_SANITIZER) && !defined(ADDRESS_SANITIZER)
static void DiscardPages(Address begin, Address end) {
uintptr_t begin_address =
- WTF::RoundUpToSystemPage(reinterpret_cast<uintptr_t>(begin));
+ base::RoundUpToSystemPage(reinterpret_cast<uintptr_t>(begin));
uintptr_t end_address =
- WTF::RoundDownToSystemPage(reinterpret_cast<uintptr_t>(end));
- if (begin_address < end_address)
- WTF::DiscardSystemPages(reinterpret_cast<void*>(begin_address),
- end_address - begin_address);
+ base::RoundDownToSystemPage(reinterpret_cast<uintptr_t>(end));
+ if (begin_address < end_address) {
+ base::DiscardSystemPages(reinterpret_cast<void*>(begin_address),
+ end_address - begin_address);
+ }
}
#endif
-void NormalPage::Sweep() {
+bool NormalPage::Sweep() {
object_start_bit_map()->Clear();
size_t marked_object_size = 0;
Address start_of_gap = Payload();
@@ -1389,7 +1363,10 @@ void NormalPage::Sweep() {
marked_object_size += size;
start_of_gap = header_address;
}
- if (start_of_gap != PayloadEnd()) {
+ // Only add the memory to the free list if the page is not completely empty
+ // and we are not at the end of the page. Empty pages are not added to the
+ // free list as the pages are removed immediately.
+ if (start_of_gap != Payload() && start_of_gap != PayloadEnd()) {
page_arena->AddToFreeList(start_of_gap, PayloadEnd() - start_of_gap);
#if !DCHECK_IS_ON() && !defined(LEAK_SANITIZER) && !defined(ADDRESS_SANITIZER)
if (MemoryCoordinator::IsLowEndDevice())
@@ -1398,11 +1375,12 @@ void NormalPage::Sweep() {
}
if (marked_object_size) {
- page_arena->GetThreadState()->Heap().HeapStats().IncreaseMarkedObjectSize(
+ page_arena->GetThreadState()->Heap().IncreaseMarkedObjectSize(
marked_object_size);
}
VerifyObjectStartBitmapIsConsistentWithPayload();
+ return start_of_gap == Payload();
}
void NormalPage::SweepAndCompact(CompactionContext& context) {
@@ -1500,7 +1478,7 @@ void NormalPage::SweepAndCompact(CompactionContext& context) {
DCHECK(allocation_point <= current_page->PayloadSize());
}
if (marked_object_size) {
- page_arena->GetThreadState()->Heap().HeapStats().IncreaseMarkedObjectSize(
+ page_arena->GetThreadState()->Heap().IncreaseMarkedObjectSize(
marked_object_size);
}
@@ -1574,20 +1552,23 @@ void NormalPage::PoisonUnmarkedObjects() {
void NormalPage::VerifyObjectStartBitmapIsConsistentWithPayload() {
#if DCHECK_IS_ON()
- Address current_allocation_point =
- ArenaForNormalPage()->CurrentAllocationPoint();
- DCHECK(!current_allocation_point ||
- (PageFromObject(current_allocation_point) != this));
-
HeapObjectHeader* current_header =
reinterpret_cast<HeapObjectHeader*>(Payload());
- object_start_bit_map()->Iterate([&current_header](Address object_address) {
+ object_start_bit_map()->Iterate([this,
+ &current_header](Address object_address) {
const HeapObjectHeader* object_header =
reinterpret_cast<HeapObjectHeader*>(object_address);
DCHECK_EQ(object_header, current_header);
DCHECK(object_header->IsValidOrZapped());
current_header = reinterpret_cast<HeapObjectHeader*>(object_address +
object_header->size());
+ // Skip over allocation area.
+ if (reinterpret_cast<Address>(current_header) ==
+ ArenaForNormalPage()->CurrentAllocationPoint()) {
+ current_header = reinterpret_cast<HeapObjectHeader*>(
+ ArenaForNormalPage()->CurrentAllocationPoint() +
+ ArenaForNormalPage()->RemainingAllocationSize());
+ }
});
#endif // DCHECK_IS_ON()
}
@@ -1699,9 +1680,9 @@ bool NormalPage::Contains(Address addr) {
LargeObjectPage::LargeObjectPage(PageMemory* storage,
BaseArena* arena,
- size_t payload_size)
+ size_t object_size)
: BasePage(storage, arena),
- payload_size_(payload_size)
+ object_size_(object_size)
#ifdef ANNOTATE_CONTIGUOUS_CONTAINER
,
is_vector_backing_page_(false)
@@ -1713,29 +1694,28 @@ size_t LargeObjectPage::ObjectPayloadSizeForTesting() {
return PayloadSize();
}
-bool LargeObjectPage::IsEmpty() {
- return !GetHeapObjectHeader()->IsMarked();
-}
-
void LargeObjectPage::RemoveFromHeap() {
static_cast<LargeObjectArena*>(Arena())->FreeLargeObjectPage(this);
}
-void LargeObjectPage::Sweep() {
- GetHeapObjectHeader()->Unmark();
- Arena()->GetThreadState()->Heap().HeapStats().IncreaseMarkedObjectSize(
- size());
+bool LargeObjectPage::Sweep() {
+ if (!ObjectHeader()->IsMarked()) {
+ return true;
+ }
+ ObjectHeader()->Unmark();
+ Arena()->GetThreadState()->Heap().IncreaseMarkedObjectSize(size());
+ return false;
}
void LargeObjectPage::MakeConsistentForMutator() {
- HeapObjectHeader* header = GetHeapObjectHeader();
+ HeapObjectHeader* header = ObjectHeader();
if (header->IsMarked())
header->Unmark();
}
#if defined(ADDRESS_SANITIZER)
void LargeObjectPage::PoisonUnmarkedObjects() {
- HeapObjectHeader* header = GetHeapObjectHeader();
+ HeapObjectHeader* header = ObjectHeader();
if (!header->IsMarked())
ASAN_POISON_MEMORY_REGION(header->Payload(), header->PayloadSize());
}
@@ -1749,7 +1729,7 @@ void LargeObjectPage::TakeSnapshot(
size_t dead_size = 0;
size_t live_count = 0;
size_t dead_count = 0;
- HeapObjectHeader* header = GetHeapObjectHeader();
+ HeapObjectHeader* header = ObjectHeader();
size_t gc_info_index = header->GcInfoIndex();
size_t payload_size = header->PayloadSize();
if (header->IsMarked()) {
@@ -1777,4 +1757,75 @@ bool LargeObjectPage::Contains(Address object) {
}
#endif
+ALWAYS_INLINE uint32_t RotateLeft16(uint32_t x) {
+#if defined(COMPILER_MSVC)
+ return _lrotr(x, 16);
+#else
+ // http://blog.regehr.org/archives/1063
+ return (x << 16) | (x >> (-16 & 31));
+#endif
+}
+
+uint32_t ComputeRandomMagic() {
+// Ignore C4319: It is OK to 0-extend into the high-order bits of the uintptr_t
+// on 64-bit, in this case.
+#if defined(COMPILER_MSVC)
+#pragma warning(push)
+#pragma warning(disable : 4319)
+#endif
+
+ // Get an ASLR'd address from one of our own DLLs/.sos, and then another from
+ // a system DLL/.so:
+
+ const uint32_t random1 = ~(RotateLeft16(reinterpret_cast<uintptr_t>(
+ base::trace_event::MemoryAllocatorDump::kNameSize)));
+
+#if defined(OS_WIN)
+ uintptr_t random2 = reinterpret_cast<uintptr_t>(::ReadFile);
+#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
+ uintptr_t random2 = reinterpret_cast<uintptr_t>(::read);
+#else
+#error platform not supported
+#endif
+
+#if defined(ARCH_CPU_64_BITS)
+ static_assert(sizeof(uintptr_t) == sizeof(uint64_t),
+ "uintptr_t is not uint64_t");
+ // Shift in some high-order bits.
+ random2 = random2 >> 16;
+#elif defined(ARCH_CPU_32_BITS)
+ // Although we don't use heap metadata canaries on 32-bit due to memory
+ // pressure, keep this code around just in case we do, someday.
+ static_assert(sizeof(uintptr_t) == sizeof(uint32_t),
+ "uintptr_t is not uint32_t");
+#else
+#error architecture not supported
+#endif
+
+ random2 = ~(RotateLeft16(random2));
+
+ // Combine the 2 values:
+ const uint32_t random = (random1 & 0x0000FFFFUL) |
+ (static_cast<uint32_t>(random2) & 0xFFFF0000UL);
+
+#if defined(COMPILER_MSVC)
+#pragma warning(pop)
+#endif
+
+ return random;
+}
+
+#if defined(ARCH_CPU_64_BITS)
+// Returns a random magic value.
+uint32_t HeapObjectHeader::GetMagic() {
+ static const uint32_t magic = ComputeRandomMagic() ^ 0x6e0b6ead;
+ return magic;
+}
+#endif // defined(ARCH_CPU_64_BITS)
+
+uint32_t BasePage::GetMagic() {
+ static const uint32_t magic = ComputeRandomMagic() ^ 0xba5e4a9e;
+ return magic;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_page.h b/chromium/third_party/blink/renderer/platform/heap/heap_page.h
index f9e45bc4d7c..b697773664e 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_page.h
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_page.h
@@ -33,7 +33,6 @@
#include <stdint.h>
#include "base/bits.h"
-#include "base/trace_event/memory_allocator_dump.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/heap/blink_gc.h"
#include "third_party/blink/renderer/platform/heap/gc_info.h"
@@ -47,6 +46,12 @@
#include "third_party/blink/renderer/platform/wtf/container_annotations.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
+namespace base {
+namespace trace_event {
+class MemoryAllocatorDump;
+} // namespace trace_event
+} // namespace base
+
namespace blink {
// TODO(palmer): Document the reason for 17.
@@ -136,7 +141,7 @@ class BaseArena;
// should be fast and small, and should have the benefit of requiring
// attackers to discover and use 2 independent weak infoleak bugs, or 1
// arbitrary infoleak bug (used twice).
-inline uint32_t GetRandomMagic();
+uint32_t ComputeRandomMagic();
// HeapObjectHeader is a 64-bit (64-bit platforms) or 32-bit (32-bit platforms)
// object that has the following layout:
@@ -154,7 +159,7 @@ inline uint32_t GetRandomMagic();
// object is guaranteed to be aligned on a kAllocationGranularity-byte
// boundary.
// - For large objects, |size| is 0. The actual size of a large object is
-// stored in |LargeObjectPage::payload_size_|.
+// stored in |LargeObjectPage::PayloadSize()|.
// - 1 bit used to mark DOM trees for V8.
// - 14 bits are enough for |gc_info_index| because there are fewer than 2^14
// types in Blink.
@@ -247,7 +252,7 @@ class PLATFORM_EXPORT HeapObjectHeader {
#if defined(ARCH_CPU_64_BITS)
// Returns a random magic value.
- uint32_t GetMagic() const { return GetRandomMagic() ^ 0x6e0b6ead; }
+ static uint32_t GetMagic();
uint32_t magic_;
#endif // defined(ARCH_CPU_64_BITS)
@@ -368,9 +373,10 @@ class BasePage {
// defined as non-virtual methods on |NormalPage| and |LargeObjectPage|. The
// following methods are not performance-sensitive.
virtual size_t ObjectPayloadSizeForTesting() = 0;
- virtual bool IsEmpty() = 0;
virtual void RemoveFromHeap() = 0;
- virtual void Sweep() = 0;
+ // Sweeps a page. Returns true when that page is empty and false otherwise.
+ // Does not create free list entries for empty pages.
+ virtual bool Sweep() = 0;
virtual void MakeConsistentForMutator() = 0;
#if defined(ADDRESS_SANITIZER)
@@ -418,7 +424,7 @@ class BasePage {
private:
// Returns a random magic value.
- uint32_t GetMagic() const { return GetRandomMagic() ^ 0xba5e4a9e; }
+ PLATFORM_EXPORT static uint32_t GetMagic();
uint32_t const magic_;
PageMemory* const storage_;
@@ -504,9 +510,8 @@ class PLATFORM_EXPORT NormalPage final : public BasePage {
}
size_t ObjectPayloadSizeForTesting() override;
- bool IsEmpty() override;
void RemoveFromHeap() override;
- void Sweep() override;
+ bool Sweep() override;
void MakeConsistentForMutator() override;
#if defined(ADDRESS_SANITIZER)
void PoisonUnmarkedObjects() override;
@@ -579,68 +584,88 @@ class PLATFORM_EXPORT NormalPage final : public BasePage {
// object.
class LargeObjectPage final : public BasePage {
public:
+ static size_t PageHeaderSize() {
+ // Compute the amount of padding we have to add to a header to make the size
+ // of the header plus the padding a multiple of 8 bytes.
+ size_t padding_size =
+ (sizeof(LargeObjectPage) + kAllocationGranularity -
+ (sizeof(HeapObjectHeader) % kAllocationGranularity)) %
+ kAllocationGranularity;
+ return sizeof(LargeObjectPage) + padding_size;
+ }
+
LargeObjectPage(PageMemory*, BaseArena*, size_t);
// LargeObjectPage has the following memory layout:
+ // this -> +------------------+
+ // | Header | PageHeaderSize()
+ // ObjectHeader() -> +------------------+
+ // | HeapObjectHeader | sizeof(HeapObjectHeader)
+ // Payload() -> +------------------+
+ // | Object payload | PayloadSize()
+ // | |
+ // PayloadEnd() -> +------------------+
//
- // | metadata | HeapObjectHeader | payload |
- //
- // LargeObjectPage::PayloadSize returns the size of HeapObjectHeader and the
- // object payload. HeapObjectHeader::PayloadSize returns just the size of the
- // payload.
- Address Payload() { return GetHeapObjectHeader()->Payload(); }
- size_t PayloadSize() { return payload_size_; }
+ // ObjectSize(): PayloadSize() + sizeof(HeapObjectHeader)
+ // size(): ObjectSize() + PageHeaderSize()
+
+ HeapObjectHeader* ObjectHeader() {
+ Address header_address = GetAddress() + PageHeaderSize();
+ return reinterpret_cast<HeapObjectHeader*>(header_address);
+ }
+
+ // Returns the size of the page that is allocatable for objects. This differs
+ // from PayloadSize() as it also includes the HeapObjectHeader.
+ size_t ObjectSize() const { return object_size_; }
+
+ // Returns the size of the page including the header.
+ size_t size() override { return PageHeaderSize() + object_size_; }
+
+ // Returns the payload start of the underlying object.
+ Address Payload() { return ObjectHeader()->Payload(); }
+
+ // Returns the payload size of the underlying object.
+ size_t PayloadSize() { return object_size_ - sizeof(HeapObjectHeader); }
+
+ // Points to the payload end of the underlying object.
Address PayloadEnd() { return Payload() + PayloadSize(); }
+
bool ContainedInObjectPayload(Address address) {
return Payload() <= address && address < PayloadEnd();
}
size_t ObjectPayloadSizeForTesting() override;
- bool IsEmpty() override;
void RemoveFromHeap() override;
- void Sweep() override;
+ bool Sweep() override;
void MakeConsistentForMutator() override;
-#if defined(ADDRESS_SANITIZER)
- void PoisonUnmarkedObjects() override;
-#endif
void TakeSnapshot(base::trace_event::MemoryAllocatorDump*,
ThreadState::GCSnapshotInfo&,
HeapSnapshotInfo&) override;
+
+ bool IsLargeObjectPage() override { return true; }
+
+ void VerifyMarking() override {}
+
+#if defined(ADDRESS_SANITIZER)
+ void PoisonUnmarkedObjects() override;
+#endif
+
#if DCHECK_IS_ON()
// Returns true for any address that is on one of the pages that this large
// object uses. That ensures that we can use a negative result to populate the
// negative page cache.
bool Contains(Address) override;
#endif
- size_t size() override {
- return PageHeaderSize() + sizeof(HeapObjectHeader) + payload_size_;
- }
- static size_t PageHeaderSize() {
- // Compute the amount of padding we have to add to a header to make the size
- // of the header plus the padding a multiple of 8 bytes.
- size_t padding_size =
- (sizeof(LargeObjectPage) + kAllocationGranularity -
- (sizeof(HeapObjectHeader) % kAllocationGranularity)) %
- kAllocationGranularity;
- return sizeof(LargeObjectPage) + padding_size;
- }
- bool IsLargeObjectPage() override { return true; }
-
- HeapObjectHeader* GetHeapObjectHeader() {
- Address header_address = GetAddress() + PageHeaderSize();
- return reinterpret_cast<HeapObjectHeader*>(header_address);
- }
#ifdef ANNOTATE_CONTIGUOUS_CONTAINER
void SetIsVectorBackingPage() { is_vector_backing_page_ = true; }
bool IsVectorBackingPage() const { return is_vector_backing_page_; }
#endif
- void VerifyMarking() override {}
-
private:
- size_t payload_size_;
+ // The size of the underlying object including HeapObjectHeader.
+ size_t object_size_;
#ifdef ANNOTATE_CONTIGUOUS_CONTAINER
bool is_vector_backing_page_;
#endif
@@ -717,7 +742,7 @@ class PLATFORM_EXPORT BaseArena {
void SweepUnsweptPage();
// Returns true if we have swept all pages within the deadline. Returns false
// otherwise.
- bool LazySweepWithDeadline(double deadline_seconds);
+ bool LazySweepWithDeadline(TimeTicks deadline);
void CompleteSweep();
ThreadState* GetThreadState() { return thread_state_; }
@@ -869,8 +894,8 @@ PLATFORM_EXPORT ALWAYS_INLINE BasePage* PageFromObject(const void* object) {
NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::size() const {
size_t result = encoded_ & kHeaderSizeMask;
- // Large objects should not refer to header->size(). The actual size of a
- // large object is stored in |LargeObjectPage::payload_size_|.
+ // Large objects should not refer to header->size() but use
+ // LargeObjectPage::PayloadSize().
DCHECK(result != kLargeObjectSizeInHeader);
DCHECK(!PageFromObject(this)->IsLargeObjectPage());
return result;
@@ -912,8 +937,7 @@ NO_SANITIZE_ADDRESS inline size_t HeapObjectHeader::PayloadSize() {
size_t size = encoded_ & kHeaderSizeMask;
if (UNLIKELY(size == kLargeObjectSizeInHeader)) {
DCHECK(PageFromObject(this)->IsLargeObjectPage());
- return static_cast<LargeObjectPage*>(PageFromObject(this))->PayloadSize() -
- sizeof(HeapObjectHeader);
+ return static_cast<LargeObjectPage*>(PageFromObject(this))->PayloadSize();
}
DCHECK(!PageFromObject(this)->IsLargeObjectPage());
return size - sizeof(HeapObjectHeader);
@@ -931,64 +955,6 @@ inline void HeapObjectHeader::CheckFromPayload(const void* payload) {
(void)FromPayload(payload);
}
-ALWAYS_INLINE uint32_t RotateLeft16(uint32_t x) {
-#if defined(COMPILER_MSVC)
- return _lrotr(x, 16);
-#else
- // http://blog.regehr.org/archives/1063
- return (x << 16) | (x >> (-16 & 31));
-#endif
-}
-
-inline uint32_t GetRandomMagic() {
-// Ignore C4319: It is OK to 0-extend into the high-order bits of the uintptr_t
-// on 64-bit, in this case.
-#if defined(COMPILER_MSVC)
-#pragma warning(push)
-#pragma warning(disable : 4319)
-#endif
-
- // Get an ASLR'd address from one of our own DLLs/.sos, and then another from
- // a system DLL/.so:
-
- const uint32_t random1 = ~(RotateLeft16(reinterpret_cast<uintptr_t>(
- base::trace_event::MemoryAllocatorDump::kNameSize)));
-
-#if defined(OS_WIN)
- uintptr_t random2 = reinterpret_cast<uintptr_t>(::ReadFile);
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- uintptr_t random2 = reinterpret_cast<uintptr_t>(::read);
-#else
-#error platform not supported
-#endif
-
-#if defined(ARCH_CPU_64_BITS)
- static_assert(sizeof(uintptr_t) == sizeof(uint64_t),
- "uintptr_t is not uint64_t");
- // Shift in some high-order bits.
- random2 = random2 >> 16;
-#elif defined(ARCH_CPU_32_BITS)
- // Although we don't use heap metadata canaries on 32-bit due to memory
- // pressure, keep this code around just in case we do, someday.
- static_assert(sizeof(uintptr_t) == sizeof(uint32_t),
- "uintptr_t is not uint32_t");
-#else
-#error architecture not supported
-#endif
-
- random2 = ~(RotateLeft16(random2));
-
- // Combine the 2 values:
- const uint32_t random = (random1 & 0x0000FFFFUL) |
- (static_cast<uint32_t>(random2) & 0xFFFF0000UL);
-
-#if defined(COMPILER_MSVC)
-#pragma warning(pop)
-#endif
-
- return random;
-}
-
NO_SANITIZE_ADDRESS inline bool HeapObjectHeader::IsWrapperHeaderMarked()
const {
CheckHeader();
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.cc b/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.cc
index b55da843c98..7e6c95857c2 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.cc
@@ -5,47 +5,142 @@
#include "third_party/blink/renderer/platform/heap/heap_stats_collector.h"
#include "base/logging.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
namespace blink {
-void ThreadHeapStatsCollector::IncreaseMarkedObjectSize(size_t size) {
+void ThreadHeapStatsCollector::IncreaseMarkedObjectSize(size_t bytes) {
DCHECK(is_started_);
- current_.marked_object_size += size;
+ current_.marked_bytes += bytes;
}
-void ThreadHeapStatsCollector::Start(BlinkGC::GCReason reason) {
+void ThreadHeapStatsCollector::IncreaseCompactionFreedSize(size_t bytes) {
+ DCHECK(is_started_);
+ current_.compaction_freed_bytes += bytes;
+}
+
+void ThreadHeapStatsCollector::IncreaseCompactionFreedPages(size_t pages) {
+ DCHECK(is_started_);
+ current_.compaction_freed_pages += pages;
+}
+
+void ThreadHeapStatsCollector::IncreaseAllocatedObjectSize(size_t bytes) {
+ // The current GC may not have been started. This is ok as recording considers
+ // the whole time range between garbage collections.
+ allocated_bytes_since_prev_gc_ += bytes;
+}
+
+void ThreadHeapStatsCollector::DecreaseAllocatedObjectSize(size_t bytes) {
+ // See IncreaseAllocatedObjectSize.
+ allocated_bytes_since_prev_gc_ -= bytes;
+}
+
+void ThreadHeapStatsCollector::IncreaseAllocatedSpace(size_t bytes) {
+ allocated_space_bytes_ += bytes;
+}
+
+void ThreadHeapStatsCollector::DecreaseAllocatedSpace(size_t bytes) {
+ allocated_space_bytes_ -= bytes;
+}
+
+void ThreadHeapStatsCollector::IncreaseWrapperCount(size_t count) {
+ wrapper_count_ += count;
+}
+
+void ThreadHeapStatsCollector::DecreaseWrapperCount(size_t count) {
+ wrapper_count_ -= count;
+}
+
+void ThreadHeapStatsCollector::IncreaseCollectedWrapperCount(size_t count) {
+ collected_wrapper_count_ += count;
+}
+
+void ThreadHeapStatsCollector::NotifyMarkingStarted(BlinkGC::GCReason reason) {
DCHECK(!is_started_);
+ DCHECK_EQ(0.0, current_.marking_time_in_ms());
is_started_ = true;
current_.reason = reason;
}
-void ThreadHeapStatsCollector::Stop() {
+void ThreadHeapStatsCollector::NotifyMarkingCompleted() {
+ current_.object_size_in_bytes_before_sweeping = object_size_in_bytes();
+ current_.allocated_space_in_bytes_before_sweeping = allocated_space_bytes();
+ current_.partition_alloc_bytes_before_sweeping =
+ WTF::Partitions::TotalSizeOfCommittedPages();
+ current_.wrapper_count_before_sweeping = wrapper_count_;
+ allocated_bytes_since_prev_gc_ = 0;
+ collected_wrapper_count_ = 0;
+}
+
+void ThreadHeapStatsCollector::NotifySweepingCompleted() {
is_started_ = false;
+ current_.live_object_rate =
+ current_.object_size_in_bytes_before_sweeping
+ ? static_cast<double>(current().marked_bytes) /
+ current_.object_size_in_bytes_before_sweeping
+ : 0.0;
previous_ = std::move(current_);
- current_.reset();
+ // Reset the current state.
+ static_assert(!std::is_polymorphic<Event>::value,
+ "Event should not be polymorphic");
+ memset(&current_, 0, sizeof(current_));
+}
+
+void ThreadHeapStatsCollector::UpdateReason(BlinkGC::GCReason reason) {
+ current_.reason = reason;
}
-void ThreadHeapStatsCollector::Event::reset() {
- marked_object_size = 0;
- memset(scope_data, 0, sizeof(scope_data));
- reason = BlinkGC::kTesting;
+size_t ThreadHeapStatsCollector::object_size_in_bytes() const {
+ return previous().marked_bytes + allocated_bytes_since_prev_gc_;
+}
+
+double ThreadHeapStatsCollector::estimated_marking_time_in_seconds() const {
+ // Assume 8ms time for an initial heap. 8 ms is long enough for low-end mobile
+ // devices to mark common real-world object graphs.
+ constexpr double kInitialMarkingTimeInSeconds = 0.008;
+
+ const double prev_marking_speed =
+ previous().marking_time_in_bytes_per_second();
+ return prev_marking_speed ? prev_marking_speed * object_size_in_bytes()
+ : kInitialMarkingTimeInSeconds;
+}
+
+TimeDelta ThreadHeapStatsCollector::estimated_marking_time() const {
+ return TimeDelta::FromSecondsD(estimated_marking_time_in_seconds());
}
double ThreadHeapStatsCollector::Event::marking_time_in_ms() const {
- return scope_data[kIncrementalMarkingStartMarking] +
- scope_data[kIncrementalMarkingStep] +
- scope_data[kIncrementalMarkingFinalizeMarking] +
- scope_data[kAtomicPhaseMarking];
+ return (scope_data[kIncrementalMarkingStartMarking] +
+ scope_data[kIncrementalMarkingStep] +
+ scope_data[kIncrementalMarkingFinalizeMarking] +
+ scope_data[kAtomicPhaseMarking])
+ .InMillisecondsF();
}
-double ThreadHeapStatsCollector::Event::marking_time_per_byte_in_s() const {
- return marked_object_size ? marking_time_in_ms() / 1000 / marked_object_size
- : 0.0;
+double ThreadHeapStatsCollector::Event::marking_time_in_bytes_per_second()
+ const {
+ return marked_bytes ? marking_time_in_ms() / 1000 / marked_bytes : 0.0;
}
-double ThreadHeapStatsCollector::Event::sweeping_time_in_ms() const {
+TimeDelta ThreadHeapStatsCollector::Event::sweeping_time() const {
return scope_data[kCompleteSweep] + scope_data[kEagerSweep] +
scope_data[kLazySweepInIdle] + scope_data[kLazySweepOnAllocation];
}
+size_t ThreadHeapStatsCollector::allocated_bytes_since_prev_gc() const {
+ return allocated_bytes_since_prev_gc_;
+}
+
+size_t ThreadHeapStatsCollector::allocated_space_bytes() const {
+ return allocated_space_bytes_;
+}
+
+size_t ThreadHeapStatsCollector::collected_wrapper_count() const {
+ return collected_wrapper_count_;
+}
+
+size_t ThreadHeapStatsCollector::wrapper_count() const {
+ return wrapper_count_;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.h b/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.h
index c94e8d9e14d..30ee866cc63 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.h
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector.h
@@ -18,15 +18,17 @@ namespace blink {
//
// Usage:
// ThreadHeapStatsCollector stats_collector;
-// stats_collector.Start(<BlinkGC::GCReason>);
+// stats_collector.NotifyMarkingStarted(<BlinkGC::GCReason>);
// // Use tracer.
-// // Current event is available using stats_collector.current().
-// stats_collector.Stop();
+// stats_collector.NotifySweepingFinished();
// // Previous event is available using stats_collector.previous().
class PLATFORM_EXPORT ThreadHeapStatsCollector {
public:
// These ids will form human readable names when used in Scopes.
enum Id {
+ kAtomicPhase,
+ kAtomicPhaseCompaction,
+ kAtomicPhaseMarking,
kCompleteSweep,
kEagerSweep,
kIncrementalMarkingStartMarking,
@@ -36,13 +38,24 @@ class PLATFORM_EXPORT ThreadHeapStatsCollector {
kInvokePreFinalizers,
kLazySweepInIdle,
kLazySweepOnAllocation,
- kAtomicPhaseMarking,
+ kMarkInvokeEphemeronCallbacks,
+ kMarkProcessWorklist,
+ kMarkNotFullyConstructedObjects,
+ kMarkWeakProcessing,
+ kVisitCrossThreadPersistents,
kVisitDOMWrappers,
- kNumScopeIds,
+ kVisitPersistentRoots,
+ kVisitPersistents,
+ kVisitStackRoots,
+ kLastScopeId = kVisitStackRoots,
};
static const char* ToString(Id id) {
switch (id) {
+ case Id::kAtomicPhase:
+ return "BlinkGC.AtomicPhase";
+ case Id::kAtomicPhaseCompaction:
+ return "BlinkGC.AtomicPhaseCompaction";
case Id::kAtomicPhaseMarking:
return "BlinkGC.AtomicPhaseMarking";
case Id::kCompleteSweep:
@@ -63,15 +76,29 @@ class PLATFORM_EXPORT ThreadHeapStatsCollector {
return "BlinkGC.LazySweepInIdle";
case Id::kLazySweepOnAllocation:
return "BlinkGC.LazySweepOnAllocation";
+ case Id::kMarkInvokeEphemeronCallbacks:
+ return "BlinkGC.MarkInvokeEphemeronCallbacks";
+ case Id::kMarkNotFullyConstructedObjects:
+ return "BlinkGC.MarkNotFullyConstructedObjects";
+ case Id::kMarkProcessWorklist:
+ return "BlinkGC.MarkProcessWorklist";
+ case Id::kMarkWeakProcessing:
+ return "BlinkGC.MarkWeakProcessing";
+ case Id::kVisitCrossThreadPersistents:
+ return "BlinkGC.VisitCrossThreadPersistents";
case Id::kVisitDOMWrappers:
return "BlinkGC.VisitDOMWrappers";
- case Id::kNumScopeIds:
- break;
+ case Id::kVisitPersistentRoots:
+ return "BlinkGC.VisitPersistentRoots";
+ case Id::kVisitPersistents:
+ return "BlinkGC.VisitPersistents";
+ case Id::kVisitStackRoots:
+ return "BlinkGC.VisitStackRoots";
}
- CHECK(false);
- return nullptr;
}
+ static constexpr int kNumScopeIds = kLastScopeId + 1;
+
enum TraceDefaultBehavior {
kEnabled,
kDisabled,
@@ -81,23 +108,23 @@ class PLATFORM_EXPORT ThreadHeapStatsCollector {
// the corresponding ThreadHeapStatsCollector.
template <TraceDefaultBehavior default_behavior = kDisabled>
class PLATFORM_EXPORT InternalScope {
+ DISALLOW_NEW();
+ DISALLOW_COPY_AND_ASSIGN(InternalScope);
+
public:
template <typename... Args>
- InternalScope(ThreadHeapStatsCollector* tracer, Id id, Args... args)
- : tracer_(tracer),
- start_time_(WTF::CurrentTimeTicksInMilliseconds()),
- id_(id) {
+ inline InternalScope(ThreadHeapStatsCollector* tracer, Id id, Args... args)
+ : tracer_(tracer), start_time_(WTF::CurrentTimeTicks()), id_(id) {
StartTrace(args...);
}
- ~InternalScope() {
+ inline ~InternalScope() {
TRACE_EVENT_END0(TraceCategory(), ToString(id_));
- tracer_->IncreaseScopeTime(
- id_, WTF::CurrentTimeTicksInMilliseconds() - start_time_);
+ tracer_->IncreaseScopeTime(id_, WTF::CurrentTimeTicks() - start_time_);
}
private:
- static const char* TraceCategory() {
+ constexpr static const char* TraceCategory() {
return default_behavior == kEnabled
? "blink_gc"
: TRACE_DISABLED_BY_DEFAULT("blink_gc");
@@ -116,43 +143,113 @@ class PLATFORM_EXPORT ThreadHeapStatsCollector {
}
ThreadHeapStatsCollector* const tracer_;
- const double start_time_;
+ const TimeTicks start_time_;
const Id id_;
};
using Scope = InternalScope<kDisabled>;
using EnabledScope = InternalScope<kEnabled>;
+ // POD to hold interesting data accumulated during a garbage collection cycle.
+ // The event is always fully polulated when looking at previous events but
+ // is only be partially populated when looking at the current event. See
+ // members on when they are available.
struct PLATFORM_EXPORT Event {
- void reset();
-
double marking_time_in_ms() const;
- double marking_time_per_byte_in_s() const;
- double sweeping_time_in_ms() const;
+ double marking_time_in_bytes_per_second() const;
+ TimeDelta sweeping_time() const;
- size_t marked_object_size = 0;
- double scope_data[kNumScopeIds] = {0};
+ // Marked bytes collected during sweeping.
+ size_t marked_bytes = 0;
+ size_t compaction_freed_bytes = 0;
+ size_t compaction_freed_pages = 0;
+ TimeDelta scope_data[kNumScopeIds];
BlinkGC::GCReason reason;
+ size_t object_size_in_bytes_before_sweeping = 0;
+ size_t allocated_space_in_bytes_before_sweeping = 0;
+ size_t partition_alloc_bytes_before_sweeping = 0;
+ double live_object_rate = 0;
+ size_t wrapper_count_before_sweeping = 0;
};
- void Start(BlinkGC::GCReason);
- void Stop();
+ // Indicates a new garbage collection cycle.
+ void NotifyMarkingStarted(BlinkGC::GCReason);
+
+ // Indicates that marking of the current garbage collection cycle is
+ // completed.
+ void NotifyMarkingCompleted();
- void IncreaseScopeTime(Id id, double time) {
+ // Indicates the end of a garbage collection cycle. This means that sweeping
+ // is finished at this point.
+ void NotifySweepingCompleted();
+
+ void IncreaseScopeTime(Id id, TimeDelta time) {
DCHECK(is_started_);
current_.scope_data[id] += time;
}
+ void UpdateReason(BlinkGC::GCReason);
void IncreaseMarkedObjectSize(size_t);
+ void IncreaseCompactionFreedSize(size_t);
+ void IncreaseCompactionFreedPages(size_t);
+ void IncreaseAllocatedObjectSize(size_t);
+ void DecreaseAllocatedObjectSize(size_t);
+ void IncreaseAllocatedSpace(size_t);
+ void DecreaseAllocatedSpace(size_t);
+ void IncreaseWrapperCount(size_t);
+ void DecreaseWrapperCount(size_t);
+ void IncreaseCollectedWrapperCount(size_t);
+
+ // Size of objects on the heap. Based on marked bytes in the previous cycle
+ // and newly allocated bytes since the previous cycle.
+ size_t object_size_in_bytes() const;
+
+ // Estimated marking time in seconds. Based on marked bytes and mark speed in
+ // the previous cycle assuming that the collection rate of the current cycle
+ // is similar to the rate of the last GC.
+ double estimated_marking_time_in_seconds() const;
+ TimeDelta estimated_marking_time() const;
+
+ size_t allocated_bytes_since_prev_gc() const;
+
+ size_t allocated_space_bytes() const;
+
+ size_t wrapper_count() const;
+ size_t collected_wrapper_count() const;
bool is_started() const { return is_started_; }
- const Event& current() const { return current_; }
+
+ // Statistics for the previously running garbage collection.
const Event& previous() const { return previous_; }
+ TimeDelta marking_time_so_far() const {
+ return TimeDelta::FromMilliseconds(current_.marking_time_in_ms());
+ }
+
private:
+ // Statistics for the currently running garbage collection. Note that the
+ // Event may not be fully populated yet as some phase may not have been run.
+ const Event& current() const { return current_; }
+
Event current_;
Event previous_;
+
+ // Allocated bytes since the last garbage collection. These bytes are reset
+ // after marking as they should be accounted in marked_bytes then (which are
+ // only available after sweeping though).
+ size_t allocated_bytes_since_prev_gc_ = 0;
+
+ // Allocated space in bytes for all arenas.
+ size_t allocated_space_bytes_ = 0;
+
+ size_t wrapper_count_ = 0;
+ size_t collected_wrapper_count_ = 0;
+
bool is_started_ = false;
+
+ FRIEND_TEST_ALL_PREFIXES(ThreadHeapStatsCollectorTest, InitialEmpty);
+ FRIEND_TEST_ALL_PREFIXES(ThreadHeapStatsCollectorTest, IncreaseScopeTime);
+ FRIEND_TEST_ALL_PREFIXES(ThreadHeapStatsCollectorTest, StopResetsCurrent);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector_test.cc b/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector_test.cc
index b85a3fb3f6f..a80200ec60f 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_stats_collector_test.cc
@@ -14,51 +14,60 @@ namespace blink {
TEST(ThreadHeapStatsCollectorTest, InitialEmpty) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.Start(BlinkGC::kTesting);
- for (int i = 0; i < ThreadHeapStatsCollector::Id::kNumScopeIds; i++) {
- EXPECT_DOUBLE_EQ(0.0, stats_collector.current().scope_data[i]);
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ for (int i = 0; i < ThreadHeapStatsCollector::kNumScopeIds; i++) {
+ EXPECT_EQ(TimeDelta(), stats_collector.current().scope_data[i]);
}
- stats_collector.Stop();
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.NotifySweepingCompleted();
}
TEST(ThreadHeapStatsCollectorTest, IncreaseScopeTime) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.Start(BlinkGC::kTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
stats_collector.IncreaseScopeTime(
- ThreadHeapStatsCollector::kIncrementalMarkingStep, 1.0);
- EXPECT_DOUBLE_EQ(
- 1.0, stats_collector.current()
- .scope_data[ThreadHeapStatsCollector::kIncrementalMarkingStep]);
+ ThreadHeapStatsCollector::kIncrementalMarkingStep,
+ TimeDelta::FromMilliseconds(1));
+ EXPECT_EQ(TimeDelta::FromMilliseconds(1),
+ stats_collector.current()
+ .scope_data[ThreadHeapStatsCollector::kIncrementalMarkingStep]);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.NotifySweepingCompleted();
}
TEST(ThreadHeapStatsCollectorTest, StopMovesCurrentToPrevious) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.Start(BlinkGC::kTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
stats_collector.IncreaseScopeTime(
- ThreadHeapStatsCollector::kIncrementalMarkingStep, 1.0);
- stats_collector.Stop();
- EXPECT_DOUBLE_EQ(
- 1.0, stats_collector.previous()
- .scope_data[ThreadHeapStatsCollector::kIncrementalMarkingStep]);
+ ThreadHeapStatsCollector::kIncrementalMarkingStep,
+ TimeDelta::FromMilliseconds(1));
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.NotifySweepingCompleted();
+ EXPECT_EQ(TimeDelta::FromMilliseconds(1),
+ stats_collector.previous()
+ .scope_data[ThreadHeapStatsCollector::kIncrementalMarkingStep]);
}
TEST(ThreadHeapStatsCollectorTest, StopResetsCurrent) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.Start(BlinkGC::kTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
stats_collector.IncreaseScopeTime(
- ThreadHeapStatsCollector::kIncrementalMarkingStep, 1.0);
- stats_collector.Stop();
- EXPECT_DOUBLE_EQ(
- 0.0, stats_collector.current()
- .scope_data[ThreadHeapStatsCollector::kIncrementalMarkingStep]);
+ ThreadHeapStatsCollector::kIncrementalMarkingStep,
+ TimeDelta::FromMilliseconds(1));
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.NotifySweepingCompleted();
+ EXPECT_EQ(TimeDelta(),
+ stats_collector.current()
+ .scope_data[ThreadHeapStatsCollector::kIncrementalMarkingStep]);
}
TEST(ThreadHeapStatsCollectorTest, StartStop) {
ThreadHeapStatsCollector stats_collector;
EXPECT_FALSE(stats_collector.is_started());
- stats_collector.Start(BlinkGC::kTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
EXPECT_TRUE(stats_collector.is_started());
- stats_collector.Stop();
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.NotifySweepingCompleted();
EXPECT_FALSE(stats_collector.is_started());
}
@@ -68,69 +77,339 @@ TEST(ThreadHeapStatsCollectorTest, ScopeToString) {
ThreadHeapStatsCollector::kIncrementalMarkingStartMarking));
}
+TEST(ThreadHeapStatsCollectorTest, UpdateReason) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.UpdateReason(BlinkGC::GCReason::kForcedGC);
+ stats_collector.NotifySweepingCompleted();
+ EXPECT_EQ(BlinkGC::GCReason::kForcedGC, stats_collector.previous().reason);
+}
+
+TEST(ThreadHeapStatsCollectorTest, InitialEstimatedObjectSizeInBytes) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ EXPECT_EQ(0u, stats_collector.object_size_in_bytes());
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.NotifySweepingCompleted();
+}
+
+TEST(ThreadHeapStatsCollectorTest, EstimatedObjectSizeInBytesNoMarkedBytes) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.IncreaseAllocatedObjectSize(512);
+ EXPECT_EQ(512u, stats_collector.object_size_in_bytes());
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.NotifySweepingCompleted();
+}
+
+TEST(ThreadHeapStatsCollectorTest, EstimatedObjectSizeInBytesWithMarkedBytes) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.IncreaseMarkedObjectSize(128);
+ stats_collector.NotifySweepingCompleted();
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.IncreaseAllocatedObjectSize(512);
+ EXPECT_EQ(640u, stats_collector.object_size_in_bytes());
+ stats_collector.NotifySweepingCompleted();
+}
+
+TEST(ThreadHeapStatsCollectorTest,
+ EstimatedObjectSizeInBytesDoNotCountCurrentlyMarkedBytes) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.IncreaseMarkedObjectSize(128);
+ stats_collector.NotifySweepingCompleted();
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.IncreaseMarkedObjectSize(128);
+ // Currently marked bytes should not account to the estimated object size.
+ stats_collector.IncreaseAllocatedObjectSize(512);
+ EXPECT_EQ(640u, stats_collector.object_size_in_bytes());
+ stats_collector.NotifySweepingCompleted();
+}
+
+TEST(ThreadHeapStatsCollectorTest, PreInitializedEstimatedMarkingTime) {
+ // Checks that a marking time estimate can be retrieved before the first
+ // garbage collection triggers.
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ EXPECT_LT(0u, stats_collector.estimated_marking_time_in_seconds());
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.NotifySweepingCompleted();
+}
+
+TEST(ThreadHeapStatsCollectorTest, EstimatedMarkingTime1) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.IncreaseScopeTime(
+ ThreadHeapStatsCollector::kAtomicPhaseMarking, TimeDelta::FromSeconds(1));
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.IncreaseMarkedObjectSize(1024);
+ stats_collector.NotifySweepingCompleted();
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ EXPECT_DOUBLE_EQ(1.0, stats_collector.estimated_marking_time_in_seconds());
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.NotifySweepingCompleted();
+}
+
+TEST(ThreadHeapStatsCollectorTest, EstimatedMarkingTime2) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.IncreaseScopeTime(
+ ThreadHeapStatsCollector::kAtomicPhaseMarking, TimeDelta::FromSeconds(1));
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.IncreaseMarkedObjectSize(1024);
+ stats_collector.NotifySweepingCompleted();
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.IncreaseAllocatedObjectSize(512);
+ EXPECT_DOUBLE_EQ(1.5, stats_collector.estimated_marking_time_in_seconds());
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.NotifySweepingCompleted();
+}
+
+TEST(ThreadHeapStatsCollectorTest, AllocatedSpaceInBytesInitialZero) {
+ ThreadHeapStatsCollector stats_collector;
+ EXPECT_EQ(0u, stats_collector.allocated_space_bytes());
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ EXPECT_EQ(0u, stats_collector.allocated_space_bytes());
+ stats_collector.NotifyMarkingCompleted();
+ EXPECT_EQ(0u, stats_collector.allocated_space_bytes());
+ stats_collector.NotifySweepingCompleted();
+ EXPECT_EQ(0u, stats_collector.allocated_space_bytes());
+}
+
+TEST(ThreadHeapStatsCollectorTest, AllocatedSpaceInBytesIncrease) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.IncreaseAllocatedSpace(1024);
+ EXPECT_EQ(1024u, stats_collector.allocated_space_bytes());
+}
+
+TEST(ThreadHeapStatsCollectorTest, AllocatedSpaceInBytesDecrease) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.IncreaseAllocatedSpace(1024);
+ stats_collector.DecreaseAllocatedSpace(1024);
+ EXPECT_EQ(0u, stats_collector.allocated_space_bytes());
+}
+
// =============================================================================
// ThreadHeapStatsCollector::Event. ============================================
// =============================================================================
-TEST(ThreadHeapStatsCollectorTest, EventMarkedObjectSize) {
+TEST(ThreadHeapStatsCollectorTest, EventPrevGCMarkedObjectSize) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.Start(BlinkGC::kTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
stats_collector.IncreaseMarkedObjectSize(1024);
- stats_collector.Stop();
- EXPECT_EQ(1024u, stats_collector.previous().marked_object_size);
+ stats_collector.NotifySweepingCompleted();
+ EXPECT_EQ(1024u, stats_collector.previous().marked_bytes);
}
TEST(ThreadHeapStatsCollectorTest, EventMarkingTimeInMsFromIncrementalGC) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.Start(BlinkGC::kTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
stats_collector.IncreaseScopeTime(
- ThreadHeapStatsCollector::kIncrementalMarkingStartMarking, 7.0);
+ ThreadHeapStatsCollector::kIncrementalMarkingStartMarking,
+ TimeDelta::FromMilliseconds(7));
stats_collector.IncreaseScopeTime(
- ThreadHeapStatsCollector::kIncrementalMarkingStep, 2.0);
+ ThreadHeapStatsCollector::kIncrementalMarkingStep,
+ TimeDelta::FromMilliseconds(2));
stats_collector.IncreaseScopeTime(
- ThreadHeapStatsCollector::kIncrementalMarkingFinalizeMarking, 1.0);
+ ThreadHeapStatsCollector::kIncrementalMarkingFinalizeMarking,
+ TimeDelta::FromMilliseconds(1));
// Ignore the full finalization.
stats_collector.IncreaseScopeTime(
- ThreadHeapStatsCollector::kIncrementalMarkingFinalize, 3.0);
- stats_collector.Stop();
+ ThreadHeapStatsCollector::kIncrementalMarkingFinalize,
+ TimeDelta::FromMilliseconds(3));
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.NotifySweepingCompleted();
EXPECT_DOUBLE_EQ(10.0, stats_collector.previous().marking_time_in_ms());
}
TEST(ThreadHeapStatsCollectorTest, EventMarkingTimeInMsFromFullGC) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.Start(BlinkGC::kTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
stats_collector.IncreaseScopeTime(
- ThreadHeapStatsCollector::kAtomicPhaseMarking, 11.0);
- stats_collector.Stop();
+ ThreadHeapStatsCollector::kAtomicPhaseMarking,
+ TimeDelta::FromMilliseconds(11));
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.NotifySweepingCompleted();
EXPECT_DOUBLE_EQ(11.0, stats_collector.previous().marking_time_in_ms());
}
TEST(ThreadHeapStatsCollectorTest, EventMarkingTimePerByteInS) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.Start(BlinkGC::kTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
stats_collector.IncreaseMarkedObjectSize(1000);
stats_collector.IncreaseScopeTime(
- ThreadHeapStatsCollector::kAtomicPhaseMarking, 1000.0);
- stats_collector.Stop();
- EXPECT_DOUBLE_EQ(.001,
- stats_collector.previous().marking_time_per_byte_in_s());
+ ThreadHeapStatsCollector::kAtomicPhaseMarking, TimeDelta::FromSeconds(1));
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.NotifySweepingCompleted();
+ EXPECT_DOUBLE_EQ(
+ .001, stats_collector.previous().marking_time_in_bytes_per_second());
}
-TEST(ThreadHeapStatsCollectorTest, SweepingTimeInMs) {
+TEST(ThreadHeapStatsCollectorTest, EventSweepingTimeInMs) {
ThreadHeapStatsCollector stats_collector;
- stats_collector.Start(BlinkGC::kTesting);
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
stats_collector.IncreaseScopeTime(ThreadHeapStatsCollector::kLazySweepInIdle,
- 1.0);
+ TimeDelta::FromMilliseconds(1));
stats_collector.IncreaseScopeTime(ThreadHeapStatsCollector::kLazySweepInIdle,
- 2.0);
+ TimeDelta::FromMilliseconds(2));
stats_collector.IncreaseScopeTime(ThreadHeapStatsCollector::kLazySweepInIdle,
- 3.0);
+ TimeDelta::FromMilliseconds(3));
stats_collector.IncreaseScopeTime(
- ThreadHeapStatsCollector::kLazySweepOnAllocation, 4.0);
+ ThreadHeapStatsCollector::kLazySweepOnAllocation,
+ TimeDelta::FromMilliseconds(4));
stats_collector.IncreaseScopeTime(ThreadHeapStatsCollector::kCompleteSweep,
- 5.0);
- stats_collector.Stop();
- EXPECT_DOUBLE_EQ(15.0, stats_collector.previous().sweeping_time_in_ms());
+ TimeDelta::FromMilliseconds(5));
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.NotifySweepingCompleted();
+ EXPECT_EQ(TimeDelta::FromMilliseconds(15),
+ stats_collector.previous().sweeping_time());
+}
+
+TEST(ThreadHeapStatsCollectorTest, EventCompactionFreedBytes) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.IncreaseCompactionFreedSize(512);
+ stats_collector.NotifySweepingCompleted();
+ EXPECT_EQ(512u, stats_collector.previous().compaction_freed_bytes);
+}
+
+TEST(ThreadHeapStatsCollectorTest, EventCompactionFreedPages) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.IncreaseCompactionFreedPages(3);
+ stats_collector.NotifySweepingCompleted();
+ EXPECT_EQ(3u, stats_collector.previous().compaction_freed_pages);
+}
+
+TEST(ThreadHeapStatsCollectorTest, EventInitialEstimatedLiveObjectRate) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.IncreaseMarkedObjectSize(128);
+ stats_collector.NotifySweepingCompleted();
+ EXPECT_DOUBLE_EQ(0.0, stats_collector.previous().live_object_rate);
+}
+
+TEST(ThreadHeapStatsCollectorTest,
+ EventEstimatedLiveObjectRateSameMarkedBytes) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.IncreaseMarkedObjectSize(128);
+ stats_collector.NotifySweepingCompleted();
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.IncreaseMarkedObjectSize(128);
+ stats_collector.NotifySweepingCompleted();
+ EXPECT_DOUBLE_EQ(1.0, stats_collector.previous().live_object_rate);
+}
+
+TEST(ThreadHeapStatsCollectorTest,
+ EventEstimatedLiveObjectRateHalfMarkedBytes) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.IncreaseMarkedObjectSize(256);
+ stats_collector.NotifySweepingCompleted();
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.IncreaseMarkedObjectSize(128);
+ stats_collector.NotifySweepingCompleted();
+ EXPECT_DOUBLE_EQ(0.5, stats_collector.previous().live_object_rate);
+}
+
+TEST(ThreadHeapStatsCollectorTest, EventEstimatedLiveObjectRateNoMarkedBytes) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.IncreaseMarkedObjectSize(256);
+ stats_collector.NotifySweepingCompleted();
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifySweepingCompleted();
+ EXPECT_DOUBLE_EQ(0.0, stats_collector.previous().live_object_rate);
+}
+
+TEST(ThreadHeapStatsCollectorTest,
+ EventEstimatedLiveObjectRateWithAllocatedBytes1) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.IncreaseMarkedObjectSize(128);
+ stats_collector.NotifySweepingCompleted();
+ stats_collector.IncreaseAllocatedObjectSize(128);
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.IncreaseMarkedObjectSize(128);
+ stats_collector.NotifySweepingCompleted();
+ EXPECT_DOUBLE_EQ(.5, stats_collector.previous().live_object_rate);
+}
+
+TEST(ThreadHeapStatsCollectorTest,
+ EventEstimatedLiveObjectRateWithAllocatedBytes2) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.NotifySweepingCompleted();
+ stats_collector.IncreaseAllocatedObjectSize(128);
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.IncreaseMarkedObjectSize(128);
+ stats_collector.NotifySweepingCompleted();
+ EXPECT_DOUBLE_EQ(1.0, stats_collector.previous().live_object_rate);
+}
+
+TEST(ThreadHeapStatsCollectorTest,
+ EventEstimatedLiveObjectRateWithAllocatedBytes3) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.NotifySweepingCompleted();
+ EXPECT_DOUBLE_EQ(0, stats_collector.previous().live_object_rate);
+}
+
+TEST(ThreadHeapStatsCollectorTest,
+ EventEstimatedLiveObjectRateWithAllocatedBytes4) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.IncreaseMarkedObjectSize(128);
+ stats_collector.NotifySweepingCompleted();
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.NotifySweepingCompleted();
+ EXPECT_DOUBLE_EQ(0, stats_collector.previous().live_object_rate);
+}
+
+TEST(ThreadHeapStatsCollectorTest, EventAllocatedSpaceBeforeSweeping1) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.IncreaseAllocatedSpace(1024);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.IncreaseAllocatedSpace(2048);
+ stats_collector.NotifySweepingCompleted();
+ EXPECT_EQ(
+ 1024u,
+ stats_collector.previous().allocated_space_in_bytes_before_sweeping);
+}
+
+TEST(ThreadHeapStatsCollectorTest, EventAllocatedSpaceBeforeSweeping2) {
+ ThreadHeapStatsCollector stats_collector;
+ stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting);
+ stats_collector.IncreaseAllocatedSpace(1024);
+ stats_collector.NotifyMarkingCompleted();
+ stats_collector.DecreaseAllocatedSpace(1024);
+ stats_collector.NotifySweepingCompleted();
+ EXPECT_EQ(
+ 1024u,
+ stats_collector.previous().allocated_space_in_bytes_before_sweeping);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_test.cc b/chromium/third_party/blink/renderer/platform/heap/heap_test.cc
index dc938b32d50..031cfc109a6 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_test.cc
@@ -37,6 +37,7 @@
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/platform/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/heap/address_cache.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
@@ -64,7 +65,7 @@ class IntWrapper : public GarbageCollectedFinalized<IntWrapper> {
public:
static IntWrapper* Create(int x) { return new IntWrapper(x); }
- virtual ~IntWrapper() { ++destructor_calls_; }
+ virtual ~IntWrapper() { AtomicIncrement(&destructor_calls_); }
static int destructor_calls_;
void Trace(blink::Visitor* visitor) {}
@@ -364,21 +365,20 @@ class TestGCMarkingScope : public TestGCCollectGarbageScope {
public:
explicit TestGCMarkingScope(BlinkGC::StackState state)
: TestGCCollectGarbageScope(state),
- atomic_pause_scope_(ThreadState::Current()),
- persistent_lock_(ProcessHeap::CrossThreadPersistentMutex()) {
- ThreadState::Current()->Heap().stats_collector()->Start(BlinkGC::kTesting);
- ThreadState::Current()->MarkPhasePrologue(state, BlinkGC::kAtomicMarking,
- BlinkGC::kPreciseGC);
+ atomic_pause_scope_(ThreadState::Current()) {
+ ThreadState::Current()->Heap().stats_collector()->NotifyMarkingStarted(
+ BlinkGC::GCReason::kTesting);
+ ThreadState::Current()->AtomicPausePrologue(state, BlinkGC::kAtomicMarking,
+ BlinkGC::GCReason::kPreciseGC);
}
~TestGCMarkingScope() {
ThreadState::Current()->MarkPhaseEpilogue(BlinkGC::kAtomicMarking);
- ThreadState::Current()->PreSweep(BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping);
+ ThreadState::Current()->AtomicPauseEpilogue(BlinkGC::kAtomicMarking,
+ BlinkGC::kEagerSweeping);
}
private:
ThreadState::AtomicPauseScope atomic_pause_scope_;
- RecursiveMutexLocker persistent_lock_;
};
class TestGCScope : public TestGCMarkingScope {
@@ -510,7 +510,7 @@ class ThreadedTesterBase {
*threads.back()->GetTaskRunner(), FROM_HERE,
CrossThreadBind(ThreadFunc, CrossThreadUnretained(tester)));
}
- while (tester->threads_to_finish_) {
+ while (AcquireLoad(&tester->threads_to_finish_)) {
test::YieldCurrentThread();
}
delete tester;
@@ -528,7 +528,7 @@ class ThreadedTesterBase {
virtual ~ThreadedTesterBase() = default;
inline bool Done() const {
- return gc_count_ >= kNumberOfThreads * kGcPerThread;
+ return AcquireLoad(&gc_count_) >= kNumberOfThreads * kGcPerThread;
}
volatile int gc_count_;
@@ -1741,7 +1741,7 @@ TEST(HeapTest, BasicFunctionality) {
size_t base_level = initial_object_payload_size;
bool test_pages_allocated = !base_level;
if (test_pages_allocated)
- EXPECT_EQ(heap.HeapStats().AllocatedSpace(), 0ul);
+ EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes());
// This allocates objects on the general heap which should add a page of
// memory.
@@ -1756,8 +1756,10 @@ TEST(HeapTest, BasicFunctionality) {
CheckWithSlack(base_level + total, heap.ObjectPayloadSizeForTesting(),
slack);
- if (test_pages_allocated)
- EXPECT_EQ(heap.HeapStats().AllocatedSpace(), kBlinkPageSize * 2);
+ if (test_pages_allocated) {
+ EXPECT_EQ(kBlinkPageSize * 2,
+ heap.stats_collector()->allocated_space_bytes());
+ }
EXPECT_EQ(alloc32->Get(0), 40);
EXPECT_EQ(alloc32->Get(31), 40);
@@ -1778,7 +1780,7 @@ TEST(HeapTest, BasicFunctionality) {
size_t base_level = heap.ObjectPayloadSizeForTesting();
bool test_pages_allocated = !base_level;
if (test_pages_allocated)
- EXPECT_EQ(heap.HeapStats().AllocatedSpace(), 0ul);
+ EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes());
size_t big = 1008;
Persistent<DynamicallySizedObject> big_area =
@@ -1798,8 +1800,10 @@ TEST(HeapTest, BasicFunctionality) {
slack += 4;
CheckWithSlack(base_level + total, heap.ObjectPayloadSizeForTesting(),
slack);
- if (test_pages_allocated)
- EXPECT_EQ(0ul, heap.HeapStats().AllocatedSpace() & (kBlinkPageSize - 1));
+ if (test_pages_allocated) {
+ EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes() &
+ (kBlinkPageSize - 1));
+ }
}
{
@@ -1814,15 +1818,19 @@ TEST(HeapTest, BasicFunctionality) {
total += 96;
CheckWithSlack(base_level + total, heap.ObjectPayloadSizeForTesting(),
slack);
- if (test_pages_allocated)
- EXPECT_EQ(0ul, heap.HeapStats().AllocatedSpace() & (kBlinkPageSize - 1));
+ if (test_pages_allocated) {
+ EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes() &
+ (kBlinkPageSize - 1));
+ }
}
ClearOutOldGarbage();
total -= 96;
slack -= 8;
- if (test_pages_allocated)
- EXPECT_EQ(0ul, heap.HeapStats().AllocatedSpace() & (kBlinkPageSize - 1));
+ if (test_pages_allocated) {
+ EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes() &
+ (kBlinkPageSize - 1));
+ }
// Clear the persistent, so that the big area will be garbage collected.
big_area.Release();
@@ -1831,12 +1839,16 @@ TEST(HeapTest, BasicFunctionality) {
total -= big;
slack -= 4;
CheckWithSlack(base_level + total, heap.ObjectPayloadSizeForTesting(), slack);
- if (test_pages_allocated)
- EXPECT_EQ(0ul, heap.HeapStats().AllocatedSpace() & (kBlinkPageSize - 1));
+ if (test_pages_allocated) {
+ EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes() &
+ (kBlinkPageSize - 1));
+ }
CheckWithSlack(base_level + total, heap.ObjectPayloadSizeForTesting(), slack);
- if (test_pages_allocated)
- EXPECT_EQ(0ul, heap.HeapStats().AllocatedSpace() & (kBlinkPageSize - 1));
+ if (test_pages_allocated) {
+ EXPECT_EQ(0ul, heap.stats_collector()->allocated_space_bytes() &
+ (kBlinkPageSize - 1));
+ }
for (size_t i = 0; i < persistent_count; i++) {
delete persistents[i];
@@ -1947,7 +1959,7 @@ TEST(HeapTest, LazySweepingPages) {
SimpleFinalizedObject::Create();
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kLazySweeping, BlinkGC::kForcedGC);
+ BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGC);
EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_);
for (int i = 0; i < 10000; i++)
SimpleFinalizedObject::Create();
@@ -1975,7 +1987,7 @@ TEST(HeapTest, LazySweepingLargeObjectPages) {
LargeHeapObject::Create();
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kLazySweeping, BlinkGC::kForcedGC);
+ BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGC);
EXPECT_EQ(0, LargeHeapObject::destructor_calls_);
for (int i = 0; i < 10; i++) {
LargeHeapObject::Create();
@@ -1986,7 +1998,7 @@ TEST(HeapTest, LazySweepingLargeObjectPages) {
EXPECT_EQ(10, LargeHeapObject::destructor_calls_);
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kLazySweeping, BlinkGC::kForcedGC);
+ BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGC);
EXPECT_EQ(10, LargeHeapObject::destructor_calls_);
PreciselyCollectGarbage();
EXPECT_EQ(22, LargeHeapObject::destructor_calls_);
@@ -2060,7 +2072,7 @@ TEST(HeapTest, EagerlySweepingPages) {
SimpleFinalizedObjectInstanceOfTemplate::Create();
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kLazySweeping, BlinkGC::kForcedGC);
+ BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGC);
EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_);
EXPECT_EQ(100, SimpleFinalizedEagerObject::destructor_calls_);
EXPECT_EQ(100, SimpleFinalizedObjectInstanceOfTemplate::destructor_calls_);
@@ -2310,7 +2322,8 @@ TEST(HeapTest, LargeHeapObjects) {
ThreadHeap& heap = ThreadState::Current()->Heap();
ClearOutOldGarbage();
size_t initial_object_payload_size = heap.ObjectPayloadSizeForTesting();
- size_t initial_allocated_space = heap.HeapStats().AllocatedSpace();
+ size_t initial_allocated_space =
+ heap.stats_collector()->allocated_space_bytes();
IntWrapper::destructor_calls_ = 0;
LargeHeapObject::destructor_calls_ = 0;
{
@@ -2323,14 +2336,15 @@ TEST(HeapTest, LargeHeapObjects) {
reinterpret_cast<char*>(object.Get()) + sizeof(LargeHeapObject) - 1));
#endif
ClearOutOldGarbage();
- size_t after_allocation = heap.HeapStats().AllocatedSpace();
+ size_t after_allocation = heap.stats_collector()->allocated_space_bytes();
{
object->Set(0, 'a');
EXPECT_EQ('a', object->Get(0));
object->Set(object->length() - 1, 'b');
EXPECT_EQ('b', object->Get(object->length() - 1));
size_t expected_large_heap_object_payload_size =
- ThreadHeap::AllocationSizeFromSize(sizeof(LargeHeapObject));
+ ThreadHeap::AllocationSizeFromSize(sizeof(LargeHeapObject)) -
+ sizeof(HeapObjectHeader);
size_t expected_object_payload_size =
expected_large_heap_object_payload_size + sizeof(IntWrapper);
size_t actual_object_payload_size =
@@ -2354,14 +2368,16 @@ TEST(HeapTest, LargeHeapObjects) {
object = LargeHeapObject::Create();
}
ClearOutOldGarbage();
- EXPECT_TRUE(heap.HeapStats().AllocatedSpace() == after_allocation);
+ EXPECT_EQ(after_allocation,
+ heap.stats_collector()->allocated_space_bytes());
EXPECT_EQ(10, IntWrapper::destructor_calls_);
EXPECT_EQ(10, LargeHeapObject::destructor_calls_);
}
ClearOutOldGarbage();
EXPECT_TRUE(initial_object_payload_size ==
heap.ObjectPayloadSizeForTesting());
- EXPECT_TRUE(initial_allocated_space == heap.HeapStats().AllocatedSpace());
+ EXPECT_EQ(initial_allocated_space,
+ heap.stats_collector()->allocated_space_bytes());
EXPECT_EQ(11, IntWrapper::destructor_calls_);
EXPECT_EQ(11, LargeHeapObject::destructor_calls_);
PreciselyCollectGarbage();
@@ -4873,7 +4889,7 @@ TEST(HeapTest, NeedsAdjustPointer) {
// class Mixin : public GarbageCollectedMixin {};
static_assert(NeedsAdjustPointer<Mixin>::value,
"A Mixin pointer needs adjustment");
- static_assert(NeedsAdjustPointer<Mixin>::value,
+ static_assert(NeedsAdjustPointer<const Mixin>::value,
"A const Mixin pointer needs adjustment");
// class SimpleObject : public GarbageCollected<SimpleObject> {};
@@ -5815,11 +5831,6 @@ TEST(HeapTest, GarbageCollectionDuringMixinConstruction) {
a->Verify();
}
-static RecursiveMutex& GetRecursiveMutex() {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(RecursiveMutex, recursive_mutex, ());
- return recursive_mutex;
-}
-
class DestructorLockingObject
: public GarbageCollectedFinalized<DestructorLockingObject> {
public:
@@ -5828,7 +5839,6 @@ class DestructorLockingObject
}
virtual ~DestructorLockingObject() {
- RecursiveMutexLocker lock(GetRecursiveMutex());
++destructor_calls_;
}
@@ -6305,7 +6315,7 @@ enum GrowthDirection {
kGrowsTowardsLower,
};
-NEVER_INLINE NO_SANITIZE_ADDRESS GrowthDirection StackGrowthDirection() {
+NOINLINE NO_SANITIZE_ADDRESS GrowthDirection StackGrowthDirection() {
// Disable ASan, otherwise its stack checking (use-after-return) will
// confuse the direction check.
static char* previous = nullptr;
@@ -6487,7 +6497,7 @@ void WorkerThreadMainForCrossThreadWeakPersistentTest(
// Step 4: Run a GC.
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
WakeMainThread();
ParkWorkerThread();
@@ -6524,23 +6534,15 @@ TEST(HeapTest, CrossThreadWeakPersistent) {
CrossThreadWeakPersistent<DestructorLockingObject>
cross_thread_weak_persistent(object);
object = nullptr;
- {
- RecursiveMutexLocker recursive_mutex_locker(GetRecursiveMutex());
- EXPECT_EQ(0, DestructorLockingObject::destructor_calls_);
- }
+ EXPECT_EQ(0, DestructorLockingObject::destructor_calls_);
- {
- // Pretend we have no pointers on stack during the step 4.
- WakeWorkerThread();
- ParkMainThread();
- }
+ // Pretend we have no pointers on stack during the step 4.
+ WakeWorkerThread();
+ ParkMainThread();
// Step 5: Make sure the weak persistent is cleared.
EXPECT_FALSE(cross_thread_weak_persistent.Get());
- {
- RecursiveMutexLocker recursive_mutex_locker(GetRecursiveMutex());
- EXPECT_EQ(1, DestructorLockingObject::destructor_calls_);
- }
+ EXPECT_EQ(1, DestructorLockingObject::destructor_calls_);
WakeWorkerThread();
ParkMainThread();
@@ -6880,4 +6882,83 @@ TEST(HeapTest, PersistentHeapVectorCopyAssignment) {
PreciselyCollectGarbage();
}
+TEST(HeapTest, PromptlyFreeStackAllocatedHeapVector) {
+ NormalPageArena* normal_arena;
+ Address before;
+ {
+ HeapVector<Member<IntWrapper>> vector;
+ vector.push_back(new IntWrapper(0));
+ NormalPage* normal_page =
+ static_cast<NormalPage*>(PageFromObject(vector.data()));
+ normal_arena = normal_page->ArenaForNormalPage();
+ CHECK(normal_arena);
+ before = normal_arena->CurrentAllocationPoint();
+ }
+ Address after = normal_arena->CurrentAllocationPoint();
+ // We check the allocation point to see if promptly freed
+ EXPECT_NE(after, before);
+}
+
+TEST(HeapTest, PromptlyFreeStackAllocatedHeapDeque) {
+ NormalPageArena* normal_arena;
+ Address before;
+ {
+ HeapDeque<Member<IntWrapper>> deque;
+ deque.push_back(new IntWrapper(0));
+ NormalPage* normal_page =
+ static_cast<NormalPage*>(PageFromObject(&deque.front()));
+ normal_arena = normal_page->ArenaForNormalPage();
+ CHECK(normal_arena);
+ before = normal_arena->CurrentAllocationPoint();
+ }
+ Address after = normal_arena->CurrentAllocationPoint();
+ // We check the allocation point to see if promptly freed
+ EXPECT_NE(after, before);
+}
+
+TEST(HeapTest, PromptlyFreeStackAllocatedHeapHashSet) {
+ NormalPageArena* normal_arena = static_cast<NormalPageArena*>(
+ ThreadState::Current()->Heap().Arena(BlinkGC::kHashTableArenaIndex));
+ CHECK(normal_arena);
+ Address before;
+ {
+ HeapHashSet<Member<IntWrapper>> hash_set;
+ hash_set.insert(new IntWrapper(0));
+ before = normal_arena->CurrentAllocationPoint();
+ }
+ Address after = normal_arena->CurrentAllocationPoint();
+ // We check the allocation point to see if promptly freed
+ EXPECT_NE(after, before);
+}
+
+TEST(HeapTest, PromptlyFreeStackAllocatedHeapListHashSet) {
+ NormalPageArena* normal_arena = static_cast<NormalPageArena*>(
+ ThreadState::Current()->Heap().Arena(BlinkGC::kHashTableArenaIndex));
+ CHECK(normal_arena);
+ Address before;
+ {
+ HeapListHashSet<Member<IntWrapper>> list_hash_set;
+ list_hash_set.insert(new IntWrapper(0));
+ before = normal_arena->CurrentAllocationPoint();
+ }
+ Address after = normal_arena->CurrentAllocationPoint();
+ // We check the allocation point to see if promptly freed
+ EXPECT_NE(after, before);
+}
+
+TEST(HeapTest, PromptlyFreeStackAllocatedHeapLinkedHashSet) {
+ NormalPageArena* normal_arena = static_cast<NormalPageArena*>(
+ ThreadState::Current()->Heap().Arena(BlinkGC::kHashTableArenaIndex));
+ CHECK(normal_arena);
+ Address before;
+ {
+ HeapLinkedHashSet<Member<IntWrapper>> linked_hash_set;
+ linked_hash_set.insert(new IntWrapper(0));
+ before = normal_arena->CurrentAllocationPoint();
+ }
+ Address after = normal_arena->CurrentAllocationPoint();
+ // We check the allocation point to see if promptly freed
+ EXPECT_NE(after, before);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.cc b/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.cc
index afe0188157f..0a374c1de60 100644
--- a/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/heap_test_utilities.cc
@@ -13,13 +13,13 @@ namespace blink {
void PreciselyCollectGarbage() {
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
}
void ConservativelyCollectGarbage() {
ThreadState::Current()->CollectGarbage(
BlinkGC::kHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
}
// Do several GCs to make sure that later GCs don't free up old memory from
diff --git a/chromium/third_party/blink/renderer/platform/heap/incremental_marking_test.cc b/chromium/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
index 49c4fa7f0a0..16123472b26 100644
--- a/chromium/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
@@ -72,7 +72,7 @@ class BackingVisitor : public Visitor {
void Visit(const TraceWrapperV8Reference<v8::Value>&) final {}
void Visit(DOMWrapperMap<ScriptWrappable>*,
const ScriptWrappable* key) final {}
- void Visit(void*, TraceWrapperDescriptor) final {}
+ void VisitWithWrappers(void*, TraceDescriptor) final {}
private:
std::vector<void*>* objects_;
@@ -844,10 +844,11 @@ template <typename Container>
void Move() {
Object* obj = Object::Create();
Container container1;
+ Container container2;
container1.insert(obj);
{
ExpectWriteBarrierFires scope(ThreadState::Current(), {obj});
- Container container2(std::move(container1));
+ container2 = std::move(container1);
}
}
@@ -1059,7 +1060,7 @@ TEST(IncrementalMarkingTest, HeapLinkedHashSetMove) {
TEST(IncrementalMarkingTest, HeapLinkedHashSetSwap) {
Swap<HeapLinkedHashSet<Member<Object>>>();
// Weak references are strongified for the current cycle.
- Move<HeapLinkedHashSet<WeakMember<Object>>>();
+ Swap<HeapLinkedHashSet<WeakMember<Object>>>();
}
// =============================================================================
@@ -1482,7 +1483,6 @@ TEST(IncrementalMarkingTest, HeapHashMapCopyValuesToVectorMember) {
// don't free marked backings.
TEST(IncrementalMarkingTest, DISABLED_WeakHashMapPromptlyFreeDisabled) {
ThreadState* state = ThreadState::Current();
- state->SetGCState(ThreadState::kIncrementalMarkingStartScheduled);
state->SetGCState(ThreadState::kIncrementalMarkingStepScheduled);
Persistent<Object> obj1 = Object::Create();
NormalPageArena* arena = static_cast<NormalPageArena*>(
@@ -1601,13 +1601,12 @@ class IncrementalMarkingTestDriver {
}
void Start() {
- thread_state_->ScheduleIncrementalMarkingStart();
- thread_state_->RunScheduledGC(BlinkGC::kNoHeapPointersOnStack);
+ thread_state_->IncrementalMarkingStart(BlinkGC::GCReason::kTesting);
}
bool SingleStep() {
CHECK(thread_state_->IsIncrementalMarking());
- if (thread_state_->GcState() ==
+ if (thread_state_->GetGCState() ==
ThreadState::kIncrementalMarkingStepScheduled) {
thread_state_->RunScheduledGC(BlinkGC::kNoHeapPointersOnStack);
return true;
@@ -1625,7 +1624,7 @@ class IncrementalMarkingTestDriver {
CHECK(thread_state_->IsIncrementalMarking());
FinishSteps();
CHECK_EQ(ThreadState::kIncrementalMarkingFinalizeScheduled,
- thread_state_->GcState());
+ thread_state_->GetGCState());
thread_state_->RunScheduledGC(BlinkGC::kNoHeapPointersOnStack);
CHECK(!thread_state_->IsIncrementalMarking());
thread_state_->CompleteSweep();
diff --git a/chromium/third_party/blink/renderer/platform/heap/marking_verifier.h b/chromium/third_party/blink/renderer/platform/heap/marking_verifier.h
index 1d9d67a51a5..d5b01125efe 100644
--- a/chromium/third_party/blink/renderer/platform/heap/marking_verifier.h
+++ b/chromium/third_party/blink/renderer/platform/heap/marking_verifier.h
@@ -58,7 +58,7 @@ class MarkingVerifier final : public Visitor {
void Visit(const TraceWrapperV8Reference<v8::Value>&) final {}
void Visit(DOMWrapperMap<ScriptWrappable>*,
const ScriptWrappable* key) final {}
- void Visit(void*, TraceWrapperDescriptor) final {}
+ void VisitWithWrappers(void*, TraceDescriptor) final {}
private:
void VerifyChild(void* base_object_payload) {
diff --git a/chromium/third_party/blink/renderer/platform/heap/marking_visitor.cc b/chromium/third_party/blink/renderer/platform/heap/marking_visitor.cc
index 101f45e633a..eb320b74f4f 100644
--- a/chromium/third_party/blink/renderer/platform/heap/marking_visitor.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/marking_visitor.cc
@@ -46,7 +46,7 @@ void MarkingVisitor::ConservativelyMarkAddress(BasePage* page,
#endif
HeapObjectHeader* const header =
page->IsLargeObjectPage()
- ? static_cast<LargeObjectPage*>(page)->GetHeapObjectHeader()
+ ? static_cast<LargeObjectPage*>(page)->ObjectHeader()
: static_cast<NormalPage*>(page)->FindHeaderFromAddress(address);
if (!header)
return;
@@ -61,7 +61,7 @@ void MarkingVisitor::ConservativelyMarkAddress(
DCHECK(page->Contains(address));
HeapObjectHeader* const header =
page->IsLargeObjectPage()
- ? static_cast<LargeObjectPage*>(page)->GetHeapObjectHeader()
+ ? static_cast<LargeObjectPage*>(page)->ObjectHeader()
: static_cast<NormalPage*>(page)->FindHeaderFromAddress(address);
if (!header)
return;
diff --git a/chromium/third_party/blink/renderer/platform/heap/marking_visitor.h b/chromium/third_party/blink/renderer/platform/heap/marking_visitor.h
index 0c5c362d40d..24ae2cedb3e 100644
--- a/chromium/third_party/blink/renderer/platform/heap/marking_visitor.h
+++ b/chromium/third_party/blink/renderer/platform/heap/marking_visitor.h
@@ -109,7 +109,7 @@ class PLATFORM_EXPORT MarkingVisitor final : public Visitor {
desc.callback);
}
- void Visit(void*, TraceWrapperDescriptor) final {
+ void VisitWithWrappers(void*, TraceDescriptor) final {
// Ignore as the object is also passed to Visit(void*, TraceDescriptor).
}
diff --git a/chromium/third_party/blink/renderer/platform/heap/name_trait_test.cc b/chromium/third_party/blink/renderer/platform/heap/name_trait_test.cc
new file mode 100644
index 00000000000..4e4a43bfb4a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/heap/name_trait_test.cc
@@ -0,0 +1,44 @@
+// 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 <string.h>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+#include "third_party/blink/renderer/platform/heap/name_traits.h"
+
+namespace blink {
+
+namespace {
+
+class ClassWithoutName {
+ public:
+ ClassWithoutName() = default;
+};
+
+class ClassWithName : public NameClient {
+ public:
+ ClassWithName(const char* name) : name_(name) {}
+
+ const char* NameInHeapSnapshot() const final { return name_; };
+
+ private:
+ const char* name_;
+};
+
+} // namespace
+
+TEST(NameTraitTest, DefaultName) {
+ ClassWithoutName no_name;
+ const char* name = NameTrait<ClassWithoutName>::GetName(&no_name);
+ EXPECT_EQ(0, strcmp(name, "InternalNode"));
+}
+
+TEST(NameTraitTest, CustomName) {
+ ClassWithName with_name("CustomName");
+ const char* name = NameTrait<ClassWithName>::GetName(&with_name);
+ EXPECT_EQ(0, strcmp(name, "CustomName"));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/name_traits.h b/chromium/third_party/blink/renderer/platform/heap/name_traits.h
index bb16f206efa..d1261815876 100644
--- a/chromium/third_party/blink/renderer/platform/heap/name_traits.h
+++ b/chromium/third_party/blink/renderer/platform/heap/name_traits.h
@@ -5,7 +5,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_NAME_TRAITS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_NAME_TRAITS_H_
-#include "third_party/blink/renderer/platform/bindings/trace_wrapper_base.h"
+#include "third_party/blink/renderer/platform/bindings/name_client.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
namespace blink {
@@ -19,7 +20,7 @@ class NameTrait {
}
private:
- static const char* GetNameFor(const TraceWrapperBase* wrapper_tracable) {
+ static const char* GetNameFor(const NameClient* wrapper_tracable) {
return wrapper_tracable->NameInHeapSnapshot();
}
diff --git a/chromium/third_party/blink/renderer/platform/heap/page_memory.cc b/chromium/third_party/blink/renderer/platform/heap/page_memory.cc
index bdf575e3871..3f6a7180f5a 100644
--- a/chromium/third_party/blink/renderer/platform/heap/page_memory.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/page_memory.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/platform/heap/page_memory.h"
#include "base/allocator/partition_allocator/oom.h"
+#include "base/allocator/partition_allocator/page_allocator.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/wtf/address_sanitizer.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
@@ -13,18 +14,18 @@
namespace blink {
void MemoryRegion::Release() {
- WTF::FreePages(base_, size_);
+ base::FreePages(base_, size_);
}
bool MemoryRegion::Commit() {
- CHECK(WTF::RecommitSystemPages(base_, size_, WTF::PageReadWrite));
- return WTF::SetSystemPagesAccess(base_, size_, WTF::PageReadWrite);
+ CHECK(base::RecommitSystemPages(base_, size_, base::PageReadWrite));
+ return base::SetSystemPagesAccess(base_, size_, base::PageReadWrite);
}
void MemoryRegion::Decommit() {
ASAN_UNPOISON_MEMORY_REGION(base_, size_);
- WTF::DecommitSystemPages(base_, size_);
- CHECK(WTF::SetSystemPagesAccess(base_, size_, WTF::PageInaccessible));
+ base::DecommitSystemPages(base_, size_);
+ CHECK(base::SetSystemPagesAccess(base_, size_, base::PageInaccessible));
}
PageMemoryRegion::PageMemoryRegion(Address base,
@@ -48,14 +49,14 @@ PageMemoryRegion::~PageMemoryRegion() {
void PageMemoryRegion::PageDeleted(Address page) {
MarkPageUnused(page);
- if (!AtomicDecrement(&num_pages_))
+ if (!num_pages_.Decrement())
delete this;
}
// TODO(haraken): Like partitionOutOfMemoryWithLotsOfUncommitedPages(),
// we should probably have a way to distinguish physical memory OOM from
// virtual address space OOM.
-static NEVER_INLINE void BlinkGCOutOfMemory() {
+static NOINLINE void BlinkGCOutOfMemory() {
OOM_CRASH();
}
@@ -63,10 +64,9 @@ PageMemoryRegion* PageMemoryRegion::Allocate(size_t size,
unsigned num_pages,
RegionTree* region_tree) {
// Round size up to the allocation granularity.
- size = (size + WTF::kPageAllocationGranularityOffsetMask) &
- WTF::kPageAllocationGranularityBaseMask;
+ size = base::RoundUpToPageAllocationGranularity(size);
Address base = static_cast<Address>(
- WTF::AllocPages(nullptr, size, kBlinkPageSize, WTF::PageInaccessible));
+ base::AllocPages(nullptr, size, kBlinkPageSize, base::PageInaccessible));
if (!base)
BlinkGCOutOfMemory();
return new PageMemoryRegion(base, size, num_pages, region_tree);
@@ -154,16 +154,12 @@ PageMemory* PageMemory::SetupPageMemoryInRegion(PageMemoryRegion* region,
return new PageMemory(region, MemoryRegion(payload_address, payload_size));
}
-static size_t RoundToOsPageSize(size_t size) {
- return (size + WTF::kSystemPageSize - 1) & ~(WTF::kSystemPageSize - 1);
-}
-
PageMemory* PageMemory::Allocate(size_t payload_size, RegionTree* region_tree) {
DCHECK_GT(payload_size, 0u);
// Virtual memory allocation routines operate in OS page sizes.
// Round up the requested size to nearest os page size.
- payload_size = RoundToOsPageSize(payload_size);
+ payload_size = base::RoundUpToSystemPage(payload_size);
// Overallocate by 2 times OS page size to have space for a
// guard page at the beginning and end of blink heap page.
diff --git a/chromium/third_party/blink/renderer/platform/heap/page_memory.h b/chromium/third_party/blink/renderer/platform/heap/page_memory.h
index 1fbed846fee..ba5cc051d3e 100644
--- a/chromium/third_party/blink/renderer/platform/heap/page_memory.h
+++ b/chromium/third_party/blink/renderer/platform/heap/page_memory.h
@@ -5,10 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_PAGE_MEMORY_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_PAGE_MEMORY_H_
+#include "base/atomic_ref_count.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/heap/heap_page.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/compiler.h"
@@ -101,7 +101,7 @@ class PageMemoryRegion : public MemoryRegion {
// A thread owns a page, but not a region. Represent the in-use
// bitmap such that thread non-interference comes for free.
bool in_use_[kBlinkPagesPerRegion];
- int num_pages_;
+ base::AtomicRefCount num_pages_;
RegionTree* region_tree_;
};
diff --git a/chromium/third_party/blink/renderer/platform/heap/persistent.h b/chromium/third_party/blink/renderer/platform/heap/persistent.h
index 2d4eb64969c..0b62143ad41 100644
--- a/chromium/third_party/blink/renderer/platform/heap/persistent.h
+++ b/chromium/third_party/blink/renderer/platform/heap/persistent.h
@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_PERSISTENT_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_PERSISTENT_H_
+#include "base/bind.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/heap/member.h"
#include "third_party/blink/renderer/platform/heap/persistent_node.h"
@@ -175,6 +176,22 @@ class PersistentBase {
return this;
}
+ NO_SANITIZE_ADDRESS
+ void ClearWithLockHeld() {
+ static_assert(
+ crossThreadnessConfiguration == kCrossThreadPersistentConfiguration,
+ "This Persistent does not require the cross-thread lock.");
+#if DCHECK_IS_ON()
+ DCHECK(ProcessHeap::CrossThreadPersistentMutex().Locked());
+#endif
+ raw_ = nullptr;
+ CrossThreadPersistentRegion& region =
+ weaknessConfiguration == kWeakPersistentConfiguration
+ ? ProcessHeap::GetCrossThreadWeakPersistentRegion()
+ : ProcessHeap::GetCrossThreadPersistentRegion();
+ region.FreePersistentNode(persistent_node_);
+ }
+
protected:
NO_SANITIZE_ADDRESS
T* AtomicGet() {
@@ -186,8 +203,7 @@ class PersistentBase {
NO_SANITIZE_ADDRESS
void Assign(T* ptr) {
if (crossThreadnessConfiguration == kCrossThreadPersistentConfiguration) {
- RecursiveMutexLocker persistent_lock(
- ProcessHeap::CrossThreadPersistentMutex());
+ MutexLocker persistent_lock(ProcessHeap::CrossThreadPersistentMutex());
raw_ = ptr;
} else {
raw_ = ptr;
@@ -227,6 +243,7 @@ class PersistentBase {
weaknessConfiguration == kWeakPersistentConfiguration
? ProcessHeap::GetCrossThreadWeakPersistentRegion()
: ProcessHeap::GetCrossThreadPersistentRegion();
+ MutexLocker lock(ProcessHeap::CrossThreadPersistentMutex());
region.AllocatePersistentNode(persistent_node_, this, trace_callback);
return;
}
@@ -250,6 +267,7 @@ class PersistentBase {
weaknessConfiguration == kWeakPersistentConfiguration
? ProcessHeap::GetCrossThreadWeakPersistentRegion()
: ProcessHeap::GetCrossThreadPersistentRegion();
+ MutexLocker lock(ProcessHeap::CrossThreadPersistentMutex());
region.FreePersistentNode(persistent_node_);
}
return;
@@ -312,7 +330,29 @@ class PersistentBase {
Base* persistent = reinterpret_cast<Base*>(persistent_pointer);
T* object = persistent->Get();
if (object && !ObjectAliveTrait<T>::IsHeapObjectAlive(object))
- persistent->Clear();
+ ClearWeakPersistent(persistent);
+ }
+
+ static void ClearWeakPersistent(
+ PersistentBase<std::remove_const_t<T>,
+ kWeakPersistentConfiguration,
+ kCrossThreadPersistentConfiguration>* persistent) {
+#if DCHECK_IS_ON()
+ DCHECK(ProcessHeap::CrossThreadPersistentMutex().Locked());
+#endif
+ persistent->ClearWithLockHeld();
+ }
+
+ static void ClearWeakPersistent(
+ PersistentBase<std::remove_const_t<T>,
+ kWeakPersistentConfiguration,
+ kSingleThreadPersistentConfiguration>* persistent) {
+ persistent->Clear();
+ }
+
+ template <typename BadPersistent>
+ static void ClearWeakPersistent(BadPersistent* non_weak_persistent) {
+ NOTREACHED();
}
// m_raw is accessed most, so put it at the first field.
@@ -852,8 +892,6 @@ template <typename T>
struct BindUnwrapTraits<blink::CrossThreadWeakPersistent<T>> {
static blink::CrossThreadPersistent<T> Unwrap(
const blink::CrossThreadWeakPersistent<T>& wrapped) {
- WTF::RecursiveMutexLocker persistent_lock(
- blink::ProcessHeap::CrossThreadPersistentMutex());
return blink::CrossThreadPersistent<T>(wrapped.Get());
}
};
diff --git a/chromium/third_party/blink/renderer/platform/heap/persistent_node.cc b/chromium/third_party/blink/renderer/platform/heap/persistent_node.cc
index 013939ad924..e822627907c 100644
--- a/chromium/third_party/blink/renderer/platform/heap/persistent_node.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/persistent_node.cc
@@ -167,9 +167,9 @@ void CrossThreadPersistentRegion::PrepareForThreadStateTermination(
// For heaps belonging to a thread that's detaching, any cross-thread
// persistents pointing into them needs to be disabled. Do that by clearing
// out the underlying heap reference.
- RecursiveMutexLocker lock(ProcessHeap::CrossThreadPersistentMutex());
+ MutexLocker lock(ProcessHeap::CrossThreadPersistentMutex());
- PersistentNodeSlots* slots = persistent_region_->slots_;
+ PersistentNodeSlots* slots = persistent_region_.slots_;
while (slots) {
for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) {
if (slots->slot_[i].IsUnused())
@@ -187,7 +187,7 @@ void CrossThreadPersistentRegion::PrepareForThreadStateTermination(
BasePage* page = PageFromObject(raw_object);
DCHECK(page);
if (page->Arena()->GetThreadState() == thread_state) {
- persistent->Clear();
+ persistent->ClearWithLockHeld();
DCHECK(slots->slot_[i].IsUnused());
}
}
@@ -197,9 +197,11 @@ void CrossThreadPersistentRegion::PrepareForThreadStateTermination(
#if defined(ADDRESS_SANITIZER)
void CrossThreadPersistentRegion::UnpoisonCrossThreadPersistents() {
- RecursiveMutexLocker lock(ProcessHeap::CrossThreadPersistentMutex());
+#if DCHECK_IS_ON()
+ DCHECK(ProcessHeap::CrossThreadPersistentMutex().Locked());
+#endif
int persistent_count = 0;
- for (PersistentNodeSlots* slots = persistent_region_->slots_; slots;
+ for (PersistentNodeSlots* slots = persistent_region_.slots_; slots;
slots = slots->next_) {
for (int i = 0; i < PersistentNodeSlots::kSlotCount; ++i) {
const PersistentNode& node = slots->slot_[i];
@@ -211,7 +213,7 @@ void CrossThreadPersistentRegion::UnpoisonCrossThreadPersistents() {
}
}
#if DCHECK_IS_ON()
- DCHECK_EQ(persistent_count, persistent_region_->persistent_count_);
+ DCHECK_EQ(persistent_count, persistent_region_.persistent_count_);
#endif
}
#endif
diff --git a/chromium/third_party/blink/renderer/platform/heap/persistent_node.h b/chromium/third_party/blink/renderer/platform/heap/persistent_node.h
index 666b81926b0..1255bf444ad 100644
--- a/chromium/third_party/blink/renderer/platform/heap/persistent_node.h
+++ b/chromium/third_party/blink/renderer/platform/heap/persistent_node.h
@@ -165,24 +165,26 @@ class PLATFORM_EXPORT PersistentRegion final {
#endif
};
+// Protected by ProcessHeap::CrossThreadPersistentMutex.
class CrossThreadPersistentRegion final {
USING_FAST_MALLOC(CrossThreadPersistentRegion);
public:
- CrossThreadPersistentRegion()
- : persistent_region_(std::make_unique<PersistentRegion>()) {}
-
void AllocatePersistentNode(PersistentNode*& persistent_node,
void* self,
TraceCallback trace) {
- RecursiveMutexLocker lock(ProcessHeap::CrossThreadPersistentMutex());
+#if DCHECK_IS_ON()
+ DCHECK(ProcessHeap::CrossThreadPersistentMutex().Locked());
+#endif
PersistentNode* node =
- persistent_region_->AllocatePersistentNode(self, trace);
+ persistent_region_.AllocatePersistentNode(self, trace);
ReleaseStore(reinterpret_cast<void* volatile*>(&persistent_node), node);
}
void FreePersistentNode(PersistentNode*& persistent_node) {
- RecursiveMutexLocker lock(ProcessHeap::CrossThreadPersistentMutex());
+#if DCHECK_IS_ON()
+ DCHECK(ProcessHeap::CrossThreadPersistentMutex().Locked());
+#endif
// When the thread that holds the heap object that the cross-thread
// persistent shuts down, prepareForThreadStateTermination() will clear out
// the associated CrossThreadPersistent<> and PersistentNode so as to avoid
@@ -195,7 +197,7 @@ class CrossThreadPersistentRegion final {
// check for this.
if (!persistent_node)
return;
- persistent_region_->FreePersistentNode(persistent_node);
+ persistent_region_.FreePersistentNode(persistent_node);
ReleaseStore(reinterpret_cast<void* volatile*>(&persistent_node), nullptr);
}
@@ -204,7 +206,7 @@ class CrossThreadPersistentRegion final {
#if DCHECK_IS_ON()
DCHECK(ProcessHeap::CrossThreadPersistentMutex().Locked());
#endif
- persistent_region_->TracePersistentNodes(
+ persistent_region_.TracePersistentNodes(
visitor, CrossThreadPersistentRegion::ShouldTracePersistentNode);
}
@@ -222,13 +224,7 @@ class CrossThreadPersistentRegion final {
// We don't make CrossThreadPersistentRegion inherit from PersistentRegion
// because we don't want to virtualize performance-sensitive methods
// such as PersistentRegion::allocate/freePersistentNode.
- std::unique_ptr<PersistentRegion> persistent_region_;
-
- // Recursive as prepareForThreadStateTermination() clears a PersistentNode's
- // associated Persistent<> -- it in turn freeing the PersistentNode. And both
- // CrossThreadPersistentRegion operations need a lock on the region before
- // mutating.
- RecursiveMutex mutex_;
+ PersistentRegion persistent_region_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/process_heap.cc b/chromium/third_party/blink/renderer/platform/heap/process_heap.cc
index 6bf558e3acb..a8fcc0a46e6 100644
--- a/chromium/third_party/blink/renderer/platform/heap/process_heap.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/process_heap.cc
@@ -54,8 +54,8 @@ CrossThreadPersistentRegion& ProcessHeap::GetCrossThreadWeakPersistentRegion() {
return persistent_region;
}
-RecursiveMutex& ProcessHeap::CrossThreadPersistentMutex() {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(RecursiveMutex, mutex, ());
+Mutex& ProcessHeap::CrossThreadPersistentMutex() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, mutex, ());
return mutex;
}
diff --git a/chromium/third_party/blink/renderer/platform/heap/process_heap.h b/chromium/third_party/blink/renderer/platform/heap/process_heap.h
index 70f42f2d287..f119f058d23 100644
--- a/chromium/third_party/blink/renderer/platform/heap/process_heap.h
+++ b/chromium/third_party/blink/renderer/platform/heap/process_heap.h
@@ -32,12 +32,7 @@ class PLATFORM_EXPORT ProcessHeap {
// - Iteration and processing of weak cross-thread Persistents. The lock
// needs to span both operations as iteration of weak persistents only
// registers memory regions that are then processed afterwards.
- //
- // Recursive as PrepareForThreadStateTermination() clears a PersistentNode's
- // associated Persistent<> -- it in turn freeing the PersistentNode. And both
- // CrossThreadPersistentRegion operations need a lock on the region before
- // mutating.
- static RecursiveMutex& CrossThreadPersistentMutex();
+ static Mutex& CrossThreadPersistentMutex();
static void IncreaseTotalAllocatedObjectSize(size_t delta) {
AtomicAdd(&total_allocated_object_size_, static_cast<long>(delta));
diff --git a/chromium/third_party/blink/renderer/platform/heap/self_keep_alive.h b/chromium/third_party/blink/renderer/platform/heap/self_keep_alive.h
index 5e60054db89..f6626451180 100644
--- a/chromium/third_party/blink/renderer/platform/heap/self_keep_alive.h
+++ b/chromium/third_party/blink/renderer/platform/heap/self_keep_alive.h
@@ -15,29 +15,27 @@ namespace blink {
// themselves temporarily alive and cannot rely on there being some
// external reference in that interval:
//
-// class Opener {
-// public:
-// ...
-// void open()
-// {
-// // Retain a self-reference while in an open()ed state:
-// m_keepAlive = this;
-// ....
-// }
+// class Opener : public GarbageCollected<Opener> {
+// public:
+// ...
+// void Open() {
+// // Retain a self-reference while in an Open()ed state:
+// keep_alive_ = this;
+// ....
+// }
//
-// void close()
-// {
-// // Clear self-reference that ensured we were kept alive while opened.
-// m_keepAlive.clear();
-// ....
-// }
+// void Close() {
+// // Clear self-reference that ensured we were kept alive while opened.
+// keep_alive_.Clear();
+// ....
+// }
//
-// private:
-// ...
-// SelfKeepAlive m_keepAlive;
+// private:
+// ...
+// SelfKeepAlive<Opener> keep_alive_;
// };
//
-// The responsibility to call clear() in a timely fashion resides with the
+// The responsibility to call Clear() in a timely fashion resides with the
// implementation of the object.
//
//
diff --git a/chromium/third_party/blink/renderer/platform/heap/stack_frame_depth.cc b/chromium/third_party/blink/renderer/platform/heap/stack_frame_depth.cc
index e6237ed57cd..93ba8e28ecb 100644
--- a/chromium/third_party/blink/renderer/platform/heap/stack_frame_depth.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/stack_frame_depth.cc
@@ -19,9 +19,9 @@ namespace blink {
static const char* g_avoid_optimization = nullptr;
-// NEVER_INLINE ensures that |dummy| array on configureLimit() is not optimized
+// NOINLINE ensures that |dummy| array on configureLimit() is not optimized
// away, and the stack frame base register is adjusted |kSafeStackFrameSize|.
-NEVER_INLINE static uintptr_t CurrentStackFrameBaseOnCallee(const char* dummy) {
+NOINLINE static uintptr_t CurrentStackFrameBaseOnCallee(const char* dummy) {
g_avoid_optimization = dummy;
return StackFrameDepth::CurrentStackFrame();
}
diff --git a/chromium/third_party/blink/renderer/platform/heap/thread_state.cc b/chromium/third_party/blink/renderer/platform/heap/thread_state.cc
index 6a8b96996f2..94c2171db9f 100644
--- a/chromium/third_party/blink/renderer/platform/heap/thread_state.cc
+++ b/chromium/third_party/blink/renderer/platform/heap/thread_state.cc
@@ -30,8 +30,6 @@
#include "third_party/blink/renderer/platform/heap/thread_state.h"
-#include <v8.h>
-
#include <algorithm>
#include <iomanip>
#include <limits>
@@ -39,6 +37,7 @@
#include "base/atomicops.h"
#include "base/location.h"
+#include "base/numerics/safe_conversions.h"
#include "base/trace_event/process_memory_dump.h"
#include "build/build_config.h"
#include "third_party/blink/public/platform/platform.h"
@@ -58,11 +57,11 @@
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h"
-#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
#include "third_party/blink/renderer/platform/wtf/stack_util.h"
#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
+#include "v8/include/v8.h"
#if defined(OS_WIN)
#include <stddef.h>
@@ -83,34 +82,39 @@ namespace blink {
WTF::ThreadSpecific<ThreadState*>* ThreadState::thread_specific_ = nullptr;
uint8_t ThreadState::main_thread_state_storage_[sizeof(ThreadState)];
+namespace {
+
const size_t kDefaultAllocatedObjectSizeThreshold = 100 * 1024;
// Duration of one incremental marking step. Should be short enough that it
// doesn't cause jank even though it is scheduled as a normal task.
-const double kIncrementalMarkingStepDurationInSeconds = 0.001;
+constexpr TimeDelta kDefaultIncrementalMarkingStepDuration =
+ TimeDelta::FromMilliseconds(2);
constexpr size_t kMaxTerminationGCLoops = 20;
-namespace {
-
const char* GcReasonString(BlinkGC::GCReason reason) {
switch (reason) {
- case BlinkGC::kIdleGC:
+ case BlinkGC::GCReason::kIdleGC:
return "IdleGC";
- case BlinkGC::kPreciseGC:
+ case BlinkGC::GCReason::kPreciseGC:
return "PreciseGC";
- case BlinkGC::kConservativeGC:
+ case BlinkGC::GCReason::kConservativeGC:
return "ConservativeGC";
- case BlinkGC::kForcedGC:
+ case BlinkGC::GCReason::kForcedGC:
return "ForcedGC";
- case BlinkGC::kMemoryPressureGC:
+ case BlinkGC::GCReason::kMemoryPressureGC:
return "MemoryPressureGC";
- case BlinkGC::kPageNavigationGC:
+ case BlinkGC::GCReason::kPageNavigationGC:
return "PageNavigationGC";
- case BlinkGC::kThreadTerminationGC:
+ case BlinkGC::GCReason::kThreadTerminationGC:
return "ThreadTerminationGC";
- case BlinkGC::kTesting:
+ case BlinkGC::GCReason::kTesting:
return "TestingGC";
+ case BlinkGC::GCReason::kIncrementalIdleGC:
+ return "IncrementalIdleGC";
+ case BlinkGC::GCReason::kIncrementalV8FollowupGC:
+ return "IncrementalV8FollowupGC";
}
return "<Unknown>";
}
@@ -147,6 +151,14 @@ const char* StackStateString(BlinkGC::StackState state) {
return "<Unknown>";
}
+// Helper function to convert a byte count to a KB count, capping at
+// INT_MAX if the number is larger than that.
+constexpr size_t CappedSizeInKB(size_t size_in_bytes) {
+ const size_t size_in_kb = size_in_bytes / 1024;
+ const size_t limit = std::numeric_limits<int>::max();
+ return size_in_kb > limit ? limit : size_in_kb;
+}
+
} // namespace
ThreadState::ThreadState()
@@ -165,6 +177,8 @@ ThreadState::ThreadState()
gc_mixin_marker_(nullptr),
gc_state_(kNoGCScheduled),
gc_phase_(GCPhase::kNone),
+ reason_for_scheduled_gc_(BlinkGC::GCReason::kMaxValue),
+ should_optimize_for_load_time_(false),
isolate_(nullptr),
trace_dom_wrappers_(nullptr),
invalidate_dead_objects_in_wrappers_marking_deque_(nullptr),
@@ -188,8 +202,8 @@ ThreadState::ThreadState()
ThreadState::~ThreadState() {
DCHECK(CheckThread());
if (IsMainThread())
- DCHECK_EQ(Heap().HeapStats().AllocatedSpace(), 0u);
- CHECK(GcState() == ThreadState::kNoGCScheduled);
+ DCHECK_EQ(0u, Heap().stats_collector()->allocated_space_bytes());
+ CHECK(GetGCState() == ThreadState::kNoGCScheduled);
**thread_specific_ = nullptr;
}
@@ -197,6 +211,16 @@ ThreadState::~ThreadState() {
void ThreadState::AttachMainThread() {
thread_specific_ = new WTF::ThreadSpecific<ThreadState*>();
new (main_thread_state_storage_) ThreadState();
+
+ // PpapiThread doesn't set the current thread.
+ WebThread* current_thread = Platform::Current()->CurrentThread();
+ if (current_thread) {
+ ThreadScheduler* scheduler = current_thread->Scheduler();
+ // Some binaries do not have a scheduler (e.g.
+ // v8_context_snapshot_generator)
+ if (scheduler)
+ scheduler->AddRAILModeObserver(MainThreadState());
+ }
}
void ThreadState::AttachCurrentThread() {
@@ -214,6 +238,10 @@ void ThreadState::RunTerminationGC() {
DCHECK(!IsMainThread());
DCHECK(CheckThread());
+ if (IsMarkingInProgress()) {
+ IncrementalMarkingFinalize();
+ }
+
// Finish sweeping.
CompleteSweep();
@@ -231,7 +259,8 @@ void ThreadState::RunTerminationGC() {
DCHECK_GE(current_count, 0);
while (current_count != old_count) {
CollectGarbage(BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kThreadTerminationGC);
+ BlinkGC::kEagerSweeping,
+ BlinkGC::GCReason::kThreadTerminationGC);
// Release the thread-local static persistents that were
// instantiated while running the termination GC.
ReleaseStaticPersistentNodes();
@@ -249,7 +278,8 @@ void ThreadState::RunTerminationGC() {
i++) {
GetPersistentRegion()->PrepareForThreadStateTermination();
CollectGarbage(BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kThreadTerminationGC);
+ BlinkGC::kEagerSweeping,
+ BlinkGC::GCReason::kThreadTerminationGC);
}
}
@@ -257,7 +287,7 @@ void ThreadState::RunTerminationGC() {
// All of pre-finalizers should be consumed.
DCHECK(ordered_pre_finalizers_.IsEmpty());
- CHECK_EQ(GcState(), kNoGCScheduled);
+ CHECK_EQ(GetGCState(), kNoGCScheduled);
Heap().RemoveAllPages();
}
@@ -338,12 +368,18 @@ void ThreadState::VisitStack(MarkingVisitor* visitor) {
void ThreadState::VisitPersistents(Visitor* visitor) {
{
+ ThreadHeapStatsCollector::Scope stats_scope(
+ Heap().stats_collector(),
+ ThreadHeapStatsCollector::kVisitCrossThreadPersistents);
// See ProcessHeap::CrossThreadPersistentMutex().
- RecursiveMutexLocker persistent_lock(
- ProcessHeap::CrossThreadPersistentMutex());
+ MutexLocker persistent_lock(ProcessHeap::CrossThreadPersistentMutex());
ProcessHeap::GetCrossThreadPersistentRegion().TracePersistentNodes(visitor);
}
- persistent_region_->TracePersistentNodes(visitor);
+ {
+ ThreadHeapStatsCollector::Scope stats_scope(
+ Heap().stats_collector(), ThreadHeapStatsCollector::kVisitPersistents);
+ persistent_region_->TracePersistentNodes(visitor);
+ }
if (trace_dom_wrappers_) {
ThreadHeapStatsCollector::Scope stats_scope(
Heap().stats_collector(), ThreadHeapStatsCollector::kVisitDOMWrappers);
@@ -364,40 +400,42 @@ ThreadState::GCSnapshotInfo::GCSnapshotInfo(size_t num_object_types)
dead_size(Vector<size_t>(num_object_types)) {}
size_t ThreadState::TotalMemorySize() {
- return heap_->HeapStats().AllocatedObjectSize() +
- heap_->HeapStats().MarkedObjectSize() +
+ return heap_->stats_collector()->object_size_in_bytes() +
WTF::Partitions::TotalSizeOfCommittedPages();
}
size_t ThreadState::EstimatedLiveSize(size_t estimation_base_size,
size_t size_at_last_gc) {
- if (heap_->HeapStats().WrapperCountAtLastGC() == 0)
+ const ThreadHeapStatsCollector& stats_collector = *heap_->stats_collector();
+ const ThreadHeapStatsCollector::Event& prev = stats_collector.previous();
+
+ if (prev.wrapper_count_before_sweeping == 0)
return estimation_base_size;
// (estimated size) = (estimation base size) - (heap size at the last GC) /
// (# of persistent handles at the last GC) *
- // (# of persistent handles collected since the last GC);
+ // (# of persistent handles collected since the last GC)
size_t size_retained_by_collected_persistents = static_cast<size_t>(
- 1.0 * size_at_last_gc / heap_->HeapStats().WrapperCountAtLastGC() *
- heap_->HeapStats().CollectedWrapperCount());
+ 1.0 * size_at_last_gc / prev.wrapper_count_before_sweeping *
+ stats_collector.collected_wrapper_count());
if (estimation_base_size < size_retained_by_collected_persistents)
return 0;
return estimation_base_size - size_retained_by_collected_persistents;
}
double ThreadState::HeapGrowingRate() {
- size_t current_size = heap_->HeapStats().AllocatedObjectSize() +
- heap_->HeapStats().MarkedObjectSize();
- size_t estimated_size = EstimatedLiveSize(
- heap_->HeapStats().MarkedObjectSizeAtLastCompleteSweep(),
- heap_->HeapStats().MarkedObjectSizeAtLastCompleteSweep());
+ const size_t current_size = heap_->stats_collector()->object_size_in_bytes();
+ // TODO(mlippautz): Clarify those two parameters below.
+ const size_t estimated_size =
+ EstimatedLiveSize(heap_->stats_collector()->previous().marked_bytes,
+ heap_->stats_collector()->previous().marked_bytes);
// If the estimatedSize is 0, we set a high growing rate to trigger a GC.
double growing_rate =
estimated_size > 0 ? 1.0 * current_size / estimated_size : 100;
TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
"ThreadState::heapEstimatedSizeKB",
- std::min(estimated_size / 1024, static_cast<size_t>(INT_MAX)));
+ CappedSizeInKB(estimated_size));
TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
"ThreadState::heapGrowingRate",
static_cast<int>(100 * growing_rate));
@@ -407,14 +445,16 @@ double ThreadState::HeapGrowingRate() {
double ThreadState::PartitionAllocGrowingRate() {
size_t current_size = WTF::Partitions::TotalSizeOfCommittedPages();
size_t estimated_size = EstimatedLiveSize(
- current_size, heap_->HeapStats().PartitionAllocSizeAtLastGC());
+ current_size, heap_->stats_collector()
+ ->previous()
+ .partition_alloc_bytes_before_sweeping);
// If the estimatedSize is 0, we set a high growing rate to trigger a GC.
double growing_rate =
estimated_size > 0 ? 1.0 * current_size / estimated_size : 100;
TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
"ThreadState::partitionAllocEstimatedSizeKB",
- std::min(estimated_size / 1024, static_cast<size_t>(INT_MAX)));
+ CappedSizeInKB(estimated_size));
TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
"ThreadState::partitionAllocGrowingRate",
static_cast<int>(100 * growing_rate));
@@ -428,7 +468,7 @@ bool ThreadState::JudgeGCThreshold(size_t allocated_object_size_threshold,
double heap_growing_rate_threshold) {
// If the allocated object size or the total memory size is small, don't
// trigger a GC.
- if (heap_->HeapStats().AllocatedObjectSize() <
+ if (heap_->stats_collector()->allocated_bytes_since_prev_gc() <
allocated_object_size_threshold ||
TotalMemorySize() < total_memory_size_threshold)
return false;
@@ -443,19 +483,8 @@ bool ThreadState::JudgeGCThreshold(size_t allocated_object_size_threshold,
PartitionAllocGrowingRate() >= heap_growing_rate_threshold;
}
-bool ThreadState::ShouldScheduleIncrementalMarking() const {
-#if BUILDFLAG(BLINK_HEAP_INCREMENTAL_MARKING)
- // TODO(mlippautz): For now only schedule incremental marking if
- // the runtime stress flag is provided.
- return GcState() == kNoGCScheduled &&
- RuntimeEnabledFeatures::HeapIncrementalMarkingStressEnabled();
-#else
- return false;
-#endif // BUILDFLAG(BLINK_HEAP_INCREMENTAL_MARKING)
-}
-
bool ThreadState::ShouldScheduleIdleGC() {
- if (GcState() != kNoGCScheduled)
+ if (GetGCState() != kNoGCScheduled)
return false;
return JudgeGCThreshold(kDefaultAllocatedObjectSizeThreshold, 1024 * 1024,
1.5);
@@ -494,25 +523,37 @@ void ThreadState::ScheduleV8FollowupGCIfNeeded(BlinkGC::V8GCType gc_type) {
VLOG(2) << "[state:" << this << "] ScheduleV8FollowupGCIfNeeded: v8_gc_type="
<< ((gc_type == BlinkGC::kV8MajorGC) ? "MajorGC" : "MinorGC");
DCHECK(CheckThread());
- DCHECK_EQ(BlinkGC::kV8MajorGC, gc_type);
- ThreadHeap::ReportMemoryUsageForTracing();
if (IsGCForbidden())
return;
// This completeSweep() will do nothing in common cases since we've
// called completeSweep() before V8 starts minor/major GCs.
- CompleteSweep();
- DCHECK(!IsSweepingInProgress());
- DCHECK(!SweepForbidden());
+ if (gc_type == BlinkGC::kV8MajorGC) {
+ // TODO(ulan): Try removing this for Major V8 GC too.
+ CompleteSweep();
+ DCHECK(!IsSweepingInProgress());
+ DCHECK(!SweepForbidden());
+ }
- if (ShouldForceMemoryPressureGC() || ShouldScheduleV8FollowupGC()) {
- VLOG(2) << "[state:" << this << "] "
- << "ScheduleV8FollowupGCIfNeeded: Scheduled precise GC";
- SchedulePreciseGC();
+ if ((gc_type == BlinkGC::kV8MajorGC && ShouldForceMemoryPressureGC()) ||
+ ShouldScheduleV8FollowupGC()) {
+ // When we want to optimize for load time, we should prioritize throughput
+ // over latency and not do incremental marking.
+ if (RuntimeEnabledFeatures::HeapIncrementalMarkingEnabled() &&
+ !should_optimize_for_load_time_) {
+ VLOG(2) << "[state:" << this << "] "
+ << "ScheduleV8FollowupGCIfNeeded: Scheduled incremental v8 "
+ "followup GC";
+ ScheduleIncrementalGC(BlinkGC::GCReason::kIncrementalV8FollowupGC);
+ } else {
+ VLOG(2) << "[state:" << this << "] "
+ << "ScheduleV8FollowupGCIfNeeded: Scheduled precise GC";
+ SchedulePreciseGC();
+ }
return;
}
- if (ShouldScheduleIdleGC()) {
+ if (gc_type == BlinkGC::kV8MajorGC && ShouldScheduleIdleGC()) {
VLOG(2) << "[state:" << this << "] "
<< "ScheduleV8FollowupGCIfNeeded: Scheduled idle GC";
ScheduleIdleGC();
@@ -538,7 +579,6 @@ void ThreadState::SchedulePageNavigationGCIfNeeded(
<< "estimatedRemovalRatio=" << std::setprecision(2)
<< estimated_removal_ratio;
DCHECK(CheckThread());
- ThreadHeap::ReportMemoryUsageForTracing();
if (IsGCForbidden())
return;
@@ -554,7 +594,8 @@ void ThreadState::SchedulePageNavigationGCIfNeeded(
VLOG(2) << "[state:" << this << "] "
<< "SchedulePageNavigationGCIfNeeded: Scheduled memory pressure GC";
CollectGarbage(BlinkGC::kHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kLazySweeping, BlinkGC::kMemoryPressureGC);
+ BlinkGC::kLazySweeping,
+ BlinkGC::GCReason::kMemoryPressureGC);
return;
}
if (ShouldSchedulePageNavigationGC(estimated_removal_ratio)) {
@@ -570,10 +611,17 @@ void ThreadState::SchedulePageNavigationGC() {
SetGCState(kPageNavigationGCScheduled);
}
+void ThreadState::ScheduleFullGC() {
+ DCHECK(CheckThread());
+ CompleteSweep();
+ SetGCState(kFullGCScheduled);
+}
+
void ThreadState::ScheduleGCIfNeeded() {
VLOG(2) << "[state:" << this << "] ScheduleGCIfNeeded";
DCHECK(CheckThread());
- ThreadHeap::ReportMemoryUsageForTracing();
+
+ UpdateIncrementalMarkingStepDuration();
// Allocation is allowed during sweeping, but those allocations should not
// trigger nested GCs.
@@ -588,7 +636,8 @@ void ThreadState::ScheduleGCIfNeeded() {
VLOG(2) << "[state:" << this << "] "
<< "ScheduleGCIfNeeded: Scheduled memory pressure GC";
CollectGarbage(BlinkGC::kHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kLazySweeping, BlinkGC::kMemoryPressureGC);
+ BlinkGC::kLazySweeping,
+ BlinkGC::GCReason::kMemoryPressureGC);
return;
}
}
@@ -599,7 +648,8 @@ void ThreadState::ScheduleGCIfNeeded() {
VLOG(2) << "[state:" << this << "] "
<< "ScheduleGCIfNeeded: Scheduled conservative GC";
CollectGarbage(BlinkGC::kHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kLazySweeping, BlinkGC::kConservativeGC);
+ BlinkGC::kLazySweeping,
+ BlinkGC::GCReason::kConservativeGC);
return;
}
}
@@ -611,11 +661,15 @@ void ThreadState::ScheduleGCIfNeeded() {
return;
}
- if (ShouldScheduleIncrementalMarking()) {
+#if BUILDFLAG(BLINK_HEAP_INCREMENTAL_MARKING)
+ if (GetGCState() == kNoGCScheduled &&
+ RuntimeEnabledFeatures::HeapIncrementalMarkingStressEnabled()) {
VLOG(2) << "[state:" << this << "] "
- << "ScheduleGCIfNeeded: Scheduled incremental marking";
- ScheduleIncrementalMarkingStart();
+ << "ScheduleGCIfNeeded: Scheduled incremental marking for testing";
+ IncrementalMarkingStart(BlinkGC::GCReason::kTesting);
+ return;
}
+#endif
}
ThreadState* ThreadState::FromObject(const void* object) {
@@ -626,39 +680,44 @@ ThreadState* ThreadState::FromObject(const void* object) {
return page->Arena()->GetThreadState();
}
-void ThreadState::PerformIdleGC(double deadline_seconds) {
+void ThreadState::PerformIdleGC(TimeTicks deadline) {
DCHECK(CheckThread());
DCHECK(Platform::Current()->CurrentThread()->Scheduler());
- if (GcState() != kIdleGCScheduled)
+ if (GetGCState() != kIdleGCScheduled)
return;
if (IsGCForbidden()) {
// If GC is forbidden at this point, try again.
- ScheduleIdleGC();
+ RescheduleIdleGC();
return;
}
- double idle_delta_in_seconds = deadline_seconds - CurrentTimeTicksInSeconds();
- if (idle_delta_in_seconds <= heap_->HeapStats().EstimatedMarkingTime() &&
+ TimeDelta estimated_marking_time =
+ heap_->stats_collector()->estimated_marking_time();
+ if ((deadline - CurrentTimeTicks()) <= estimated_marking_time &&
!Platform::Current()
->CurrentThread()
->Scheduler()
->CanExceedIdleDeadlineIfRequired()) {
// If marking is estimated to take longer than the deadline and we can't
// exceed the deadline, then reschedule for the next idle period.
- ScheduleIdleGC();
+ RescheduleIdleGC();
+ return;
+ }
+
+#if BUILDFLAG(BLINK_HEAP_INCREMENTAL_MARKING)
+ if (RuntimeEnabledFeatures::HeapIncrementalMarkingEnabled()) {
+ IncrementalMarkingStart(BlinkGC::GCReason::kIncrementalIdleGC);
return;
}
+#endif
- TRACE_EVENT2("blink_gc", "ThreadState::performIdleGC", "idleDeltaInSeconds",
- idle_delta_in_seconds, "estimatedMarkingTime",
- heap_->HeapStats().EstimatedMarkingTime());
CollectGarbage(BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kLazySweeping, BlinkGC::kIdleGC);
+ BlinkGC::kLazySweeping, BlinkGC::GCReason::kIdleGC);
}
-void ThreadState::PerformIdleLazySweep(double deadline_seconds) {
+void ThreadState::PerformIdleLazySweep(TimeTicks deadline) {
DCHECK(CheckThread());
// If we are not in a sweeping phase, there is nothing to do here.
@@ -680,8 +739,8 @@ void ThreadState::PerformIdleLazySweep(double deadline_seconds) {
SweepForbiddenScope scope(this);
ThreadHeapStatsCollector::EnabledScope stats_scope(
Heap().stats_collector(), ThreadHeapStatsCollector::kLazySweepInIdle,
- "idleDeltaInSeconds", deadline_seconds - CurrentTimeTicksInSeconds());
- sweep_completed = Heap().AdvanceLazySweep(deadline_seconds);
+ "idleDeltaInSeconds", (deadline - CurrentTimeTicks()).InSecondsF());
+ sweep_completed = Heap().AdvanceLazySweep(deadline);
// We couldn't finish the sweeping within the deadline.
// We request another idle task for the remaining sweeping.
if (!sweep_completed)
@@ -692,42 +751,38 @@ void ThreadState::PerformIdleLazySweep(double deadline_seconds) {
PostSweep();
}
-void ThreadState::ScheduleIncrementalMarkingStart() {
- // TODO(mlippautz): Incorporate incremental sweeping into incremental steps.
- if (IsSweepingInProgress())
- CompleteSweep();
-
- SetGCState(kIncrementalMarkingStartScheduled);
-}
-
void ThreadState::ScheduleIncrementalMarkingStep() {
CHECK(!IsSweepingInProgress());
-
SetGCState(kIncrementalMarkingStepScheduled);
}
void ThreadState::ScheduleIncrementalMarkingFinalize() {
CHECK(!IsSweepingInProgress());
-
SetGCState(kIncrementalMarkingFinalizeScheduled);
}
void ThreadState::ScheduleIdleGC() {
- SetGCState(kIdleGCScheduled);
- if (IsSweepingInProgress())
- return;
// Some threads (e.g. PPAPI thread) don't have a scheduler.
// Also some tests can call Platform::SetCurrentPlatformForTesting() at any
- // time, so we need to check for the scheduler here instead of
- // ScheduleIdleGC().
- if (!Platform::Current()->CurrentThread()->Scheduler()) {
- SetGCState(kNoGCScheduled);
+ // time, so we need to check if it exists.
+ if (!Platform::Current()->CurrentThread()->Scheduler())
return;
- }
+ // Idle GC has the lowest priority so do not schedule if a GC is already
+ // scheduled or if marking is in progress.
+ if (GetGCState() != kNoGCScheduled)
+ return;
+ CompleteSweep();
+ SetGCState(kIdleGCScheduled);
Platform::Current()->CurrentThread()->Scheduler()->PostNonNestableIdleTask(
FROM_HERE, WTF::Bind(&ThreadState::PerformIdleGC, WTF::Unretained(this)));
}
+void ThreadState::RescheduleIdleGC() {
+ DCHECK_EQ(kIdleGCScheduled, GetGCState());
+ SetGCState(kNoGCScheduled);
+ ScheduleIdleGC();
+}
+
void ThreadState::ScheduleIdleLazySweep() {
// Some threads (e.g. PPAPI thread) don't have a scheduler.
if (!Platform::Current()->CurrentThread()->Scheduler())
@@ -740,9 +795,21 @@ void ThreadState::ScheduleIdleLazySweep() {
void ThreadState::SchedulePreciseGC() {
DCHECK(CheckThread());
+ CompleteSweep();
SetGCState(kPreciseGCScheduled);
}
+void ThreadState::ScheduleIncrementalGC(BlinkGC::GCReason reason) {
+ DCHECK(CheckThread());
+ // Schedule an incremental GC only when no GC is scheduled or an idle GC is
+ // scheduled. Otherwise, already scheduled GCs should be prioritized.
+ if (GetGCState() == kNoGCScheduled || GetGCState() == kIdleGCScheduled) {
+ CompleteSweep();
+ reason_for_scheduled_gc_ = reason;
+ SetGCState(kIncrementalGCScheduled);
+ }
+}
+
namespace {
#define UNEXPECTED_GCSTATE(s) \
@@ -756,10 +823,10 @@ void UnexpectedGCState(ThreadState::GCState gc_state) {
UNEXPECTED_GCSTATE(kIdleGCScheduled);
UNEXPECTED_GCSTATE(kPreciseGCScheduled);
UNEXPECTED_GCSTATE(kFullGCScheduled);
- UNEXPECTED_GCSTATE(kIncrementalMarkingStartScheduled);
UNEXPECTED_GCSTATE(kIncrementalMarkingStepScheduled);
UNEXPECTED_GCSTATE(kIncrementalMarkingFinalizeScheduled);
UNEXPECTED_GCSTATE(kPageNavigationGCScheduled);
+ UNEXPECTED_GCSTATE(kIncrementalGCScheduled);
}
}
@@ -779,18 +846,16 @@ void ThreadState::SetGCState(GCState gc_state) {
gc_state_ == kNoGCScheduled || gc_state_ == kIdleGCScheduled ||
gc_state_ == kPreciseGCScheduled || gc_state_ == kFullGCScheduled ||
gc_state_ == kPageNavigationGCScheduled ||
- gc_state_ == kIncrementalMarkingStartScheduled ||
gc_state_ == kIncrementalMarkingStepScheduled ||
- gc_state_ == kIncrementalMarkingFinalizeScheduled);
- break;
- case kIncrementalMarkingStartScheduled:
- DCHECK(CheckThread());
- VERIFY_STATE_TRANSITION(gc_state_ == kNoGCScheduled);
+ gc_state_ == kIncrementalMarkingFinalizeScheduled ||
+ gc_state_ == kIncrementalGCScheduled);
break;
case kIncrementalMarkingStepScheduled:
DCHECK(CheckThread());
- VERIFY_STATE_TRANSITION(gc_state_ == kIncrementalMarkingStartScheduled ||
- gc_state_ == kIncrementalMarkingStepScheduled);
+ VERIFY_STATE_TRANSITION(gc_state_ == kNoGCScheduled ||
+ gc_state_ == kIncrementalMarkingStepScheduled ||
+ gc_state_ == kIdleGCScheduled ||
+ gc_state_ == kIncrementalGCScheduled);
break;
case kIncrementalMarkingFinalizeScheduled:
DCHECK(CheckThread());
@@ -798,20 +863,29 @@ void ThreadState::SetGCState(GCState gc_state) {
break;
case kFullGCScheduled:
case kPageNavigationGCScheduled:
- // These GCs should not be scheduled while sweeping is in progress.
- DCHECK(!IsSweepingInProgress());
- FALLTHROUGH;
- case kIdleGCScheduled:
case kPreciseGCScheduled:
DCHECK(CheckThread());
+ DCHECK(!IsSweepingInProgress());
VERIFY_STATE_TRANSITION(
gc_state_ == kNoGCScheduled || gc_state_ == kIdleGCScheduled ||
- gc_state_ == kIncrementalMarkingStartScheduled ||
gc_state_ == kIncrementalMarkingStepScheduled ||
gc_state_ == kIncrementalMarkingFinalizeScheduled ||
gc_state_ == kPreciseGCScheduled || gc_state_ == kFullGCScheduled ||
- gc_state_ == kPageNavigationGCScheduled);
- CompleteSweep();
+ gc_state_ == kPageNavigationGCScheduled ||
+ gc_state_ == kIncrementalGCScheduled);
+ break;
+ case kIdleGCScheduled:
+ DCHECK(CheckThread());
+ DCHECK(!IsMarkingInProgress());
+ DCHECK(!IsSweepingInProgress());
+ VERIFY_STATE_TRANSITION(gc_state_ == kNoGCScheduled);
+ break;
+ case kIncrementalGCScheduled:
+ DCHECK(CheckThread());
+ DCHECK(!IsMarkingInProgress());
+ DCHECK(!IsSweepingInProgress());
+ VERIFY_STATE_TRANSITION(gc_state_ == kNoGCScheduled ||
+ gc_state_ == kIdleGCScheduled);
break;
default:
NOTREACHED();
@@ -849,37 +923,47 @@ void ThreadState::RunScheduledGC(BlinkGC::StackState stack_state) {
if (IsGCForbidden())
return;
- switch (GcState()) {
+ switch (GetGCState()) {
case kFullGCScheduled:
CollectAllGarbage();
break;
case kPreciseGCScheduled:
CollectGarbage(BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kLazySweeping, BlinkGC::kPreciseGC);
+ BlinkGC::kLazySweeping, BlinkGC::GCReason::kPreciseGC);
break;
case kPageNavigationGCScheduled:
CollectGarbage(BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kPageNavigationGC);
+ BlinkGC::kEagerSweeping,
+ BlinkGC::GCReason::kPageNavigationGC);
break;
case kIdleGCScheduled:
// Idle time GC will be scheduled by Blink Scheduler.
break;
- case kIncrementalMarkingStartScheduled:
- IncrementalMarkingStart();
- break;
case kIncrementalMarkingStepScheduled:
IncrementalMarkingStep();
break;
case kIncrementalMarkingFinalizeScheduled:
IncrementalMarkingFinalize();
break;
+ case kIncrementalGCScheduled:
+ IncrementalMarkingStart(reason_for_scheduled_gc_);
+ break;
default:
break;
}
}
-void ThreadState::PreSweep(BlinkGC::MarkingType marking_type,
- BlinkGC::SweepingType sweeping_type) {
+void ThreadState::FinishSnapshot() {
+ // Force setting NoGCScheduled to circumvent checkThread()
+ // in setGCState().
+ gc_state_ = kNoGCScheduled;
+ SetGCPhase(GCPhase::kSweeping);
+ SetGCPhase(GCPhase::kNone);
+ Heap().stats_collector()->NotifySweepingCompleted();
+}
+
+void ThreadState::AtomicPauseEpilogue(BlinkGC::MarkingType marking_type,
+ BlinkGC::SweepingType sweeping_type) {
DCHECK(InAtomicMarkingPause());
DCHECK(CheckThread());
Heap().PrepareForSweep();
@@ -894,13 +978,6 @@ void ThreadState::PreSweep(BlinkGC::MarkingType marking_type,
Heap().MakeConsistentForMutator();
Heap().TakeSnapshot(ThreadHeap::SnapshotType::kFreelistSnapshot);
-
- // Force setting NoGCScheduled to circumvent checkThread()
- // in setGCState().
- gc_state_ = kNoGCScheduled;
- SetGCPhase(GCPhase::kSweeping);
- SetGCPhase(GCPhase::kNone);
- Heap().stats_collector()->Stop();
return;
}
@@ -981,90 +1058,161 @@ BlinkGCObserver::~BlinkGCObserver() {
namespace {
+// Update trace counters with statistics from the current and previous garbage
+// collection cycle. We allow emitting current values here since these values
+// can be useful for inspecting traces.
+void UpdateTraceCounters(const ThreadHeapStatsCollector& stats_collector) {
+ bool gc_tracing_enabled;
+ TRACE_EVENT_CATEGORY_GROUP_ENABLED(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
+ &gc_tracing_enabled);
+ if (!gc_tracing_enabled)
+ return;
+
+ // Previous garbage collection cycle values.
+ const ThreadHeapStatsCollector::Event& event = stats_collector.previous();
+ const int collection_rate_percent =
+ static_cast<int>(100 * (1.0 - event.live_object_rate));
+ TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
+ "BlinkGC.CollectionRate", collection_rate_percent);
+ TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
+ "BlinkGC.MarkedObjectSizeAtLastCompleteSweepKB",
+ CappedSizeInKB(event.marked_bytes));
+ TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
+ "BlinkGC.ObjectSizeAtLastGCKB",
+ CappedSizeInKB(event.object_size_in_bytes_before_sweeping));
+ TRACE_COUNTER1(
+ TRACE_DISABLED_BY_DEFAULT("blink_gc"), "BlinkGC.AllocatedSpaceAtLastGCKB",
+ CappedSizeInKB(event.allocated_space_in_bytes_before_sweeping));
+ TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
+ "BlinkGC.PartitionAllocSizeAtLastGCKB",
+ CappedSizeInKB(event.partition_alloc_bytes_before_sweeping));
+ TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
+ "BlinkGC.WrapperCountAtLastGC",
+ event.wrapper_count_before_sweeping);
+
+ // Current values.
+ TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
+ "BlinkGC.AllocatedSpaceKB",
+ CappedSizeInKB(stats_collector.allocated_space_bytes()));
+ TRACE_COUNTER1(
+ TRACE_DISABLED_BY_DEFAULT("blink_gc"),
+ "BlinkGC.AllocatedObjectSizeSincePreviousGCKB",
+ CappedSizeInKB(stats_collector.allocated_bytes_since_prev_gc()));
+ TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
+ "PartitionAlloc.TotalSizeOfCommittedPagesKB",
+ CappedSizeInKB(WTF::Partitions::TotalSizeOfCommittedPages()));
+ TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "BlinkGC.WrapperCount",
+ stats_collector.wrapper_count());
+ TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
+ "BlinkGC.CollectedWrapperCount",
+ stats_collector.collected_wrapper_count());
+}
+
+// Update histograms with statistics from the previous garbage collection cycle.
+// Anything that is part of a histogram should have a well-defined lifetime wrt.
+// to a garbage collection cycle.
void UpdateHistograms(const ThreadHeapStatsCollector::Event& event) {
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- EnumerationHistogram, gc_reason_histogram,
- ("BlinkGC.GCReason", BlinkGC::kLastGCReason + 1));
- gc_reason_histogram.Count(event.reason);
+ UMA_HISTOGRAM_ENUMERATION("BlinkGC.GCReason", event.reason);
// TODO(mlippautz): Update name of this histogram.
- DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, marking_time_histogram,
- ("BlinkGC.CollectGarbage", 0, 10 * 1000, 50));
- marking_time_histogram.Count(event.marking_time_in_ms());
+ UMA_HISTOGRAM_TIMES(
+ "BlinkGC.CollectGarbage",
+ event.scope_data[ThreadHeapStatsCollector::kAtomicPhaseMarking]);
- DEFINE_STATIC_LOCAL(CustomCountHistogram, complete_sweep_histogram,
- ("BlinkGC.CompleteSweep", 1, 10 * 1000, 50));
- complete_sweep_histogram.Count(
+ UMA_HISTOGRAM_TIMES(
+ "BlinkGC.AtomicPhaseMarking",
+ event.scope_data[ThreadHeapStatsCollector::kAtomicPhaseMarking]);
+
+ UMA_HISTOGRAM_TIMES(
+ "BlinkGC.CompleteSweep",
event.scope_data[ThreadHeapStatsCollector::kCompleteSweep]);
- DEFINE_STATIC_LOCAL(CustomCountHistogram, time_for_sweep_histogram,
- ("BlinkGC.TimeForSweepingAllObjects", 1, 10 * 1000, 50));
- time_for_sweep_histogram.Count(event.sweeping_time_in_ms());
+ UMA_HISTOGRAM_TIMES("BlinkGC.TimeForSweepingAllObjects",
+ event.sweeping_time());
- DEFINE_STATIC_LOCAL(
- CustomCountHistogram, pre_finalizers_histogram,
- ("BlinkGC.TimeForInvokingPreFinalizers", 1, 10 * 1000, 50));
- pre_finalizers_histogram.Count(
+ UMA_HISTOGRAM_TIMES(
+ "BlinkGC.TimeForInvokingPreFinalizers",
event.scope_data[ThreadHeapStatsCollector::kInvokePreFinalizers]);
+
+ UMA_HISTOGRAM_TIMES(
+ "BlinkGC.TimeForHeapCompaction",
+ event.scope_data[ThreadHeapStatsCollector::kAtomicPhaseCompaction]);
+
+ DEFINE_STATIC_LOCAL(
+ CustomCountHistogram, object_size_freed_by_heap_compaction,
+ ("BlinkGC.ObjectSizeFreedByHeapCompaction", 1, 4 * 1024 * 1024, 50));
+ object_size_freed_by_heap_compaction.Count(
+ CappedSizeInKB(event.compaction_freed_bytes));
+
+ UMA_HISTOGRAM_TIMES(
+ "BlinkGC.TimeForGlobalWeakProcessing",
+ event.scope_data[ThreadHeapStatsCollector::kMarkWeakProcessing]);
+
+ DEFINE_STATIC_LOCAL(CustomCountHistogram, object_size_before_gc_histogram,
+ ("BlinkGC.ObjectSizeBeforeGC", 1, 4 * 1024 * 1024, 50));
+ object_size_before_gc_histogram.Count(
+ CappedSizeInKB(event.object_size_in_bytes_before_sweeping));
+ DEFINE_STATIC_LOCAL(CustomCountHistogram, object_size_after_gc_histogram,
+ ("BlinkGC.ObjectSizeAfterGC", 1, 4 * 1024 * 1024, 50));
+ object_size_after_gc_histogram.Count(CappedSizeInKB(event.marked_bytes));
+
+ const int collection_rate_percent =
+ static_cast<int>(100 * (1.0 - event.live_object_rate));
+ DEFINE_STATIC_LOCAL(CustomCountHistogram, collection_rate_histogram,
+ ("BlinkGC.CollectionRate", 1, 100, 20));
+ collection_rate_histogram.Count(collection_rate_percent);
+
+ // Per GCReason metrics.
+ switch (event.reason) {
+#define COUNT_BY_GC_REASON(reason) \
+ case BlinkGC::GCReason::k##reason: { \
+ UMA_HISTOGRAM_TIMES( \
+ "BlinkGC.AtomicPhaseMarking_" #reason, \
+ event.scope_data[ThreadHeapStatsCollector::kAtomicPhaseMarking]); \
+ DEFINE_STATIC_LOCAL(CustomCountHistogram, collection_rate_histogram, \
+ ("BlinkGC.CollectionRate_" #reason, 1, 100, 20)); \
+ collection_rate_histogram.Count(collection_rate_percent); \
+ break; \
+ }
+
+ COUNT_BY_GC_REASON(IdleGC)
+ COUNT_BY_GC_REASON(PreciseGC)
+ COUNT_BY_GC_REASON(ConservativeGC)
+ COUNT_BY_GC_REASON(ForcedGC)
+ COUNT_BY_GC_REASON(MemoryPressureGC)
+ COUNT_BY_GC_REASON(PageNavigationGC)
+ COUNT_BY_GC_REASON(ThreadTerminationGC)
+ COUNT_BY_GC_REASON(Testing)
+ COUNT_BY_GC_REASON(IncrementalIdleGC)
+ COUNT_BY_GC_REASON(IncrementalV8FollowupGC)
+
+#undef COUNT_BY_GC_REASON
+ }
+
+ static constexpr size_t kSupportedMaxSizeInMB = 4 * 1024;
+ static size_t max_committed_size_in_mb = 0;
+
+ // +1 for rounding up the size to the next MB.
+ size_t size_in_mb =
+ event.allocated_space_in_bytes_before_sweeping / 1024 / 1024 + 1;
+ if (size_in_mb >= kSupportedMaxSizeInMB)
+ size_in_mb = kSupportedMaxSizeInMB - 1;
+ if (size_in_mb > max_committed_size_in_mb) {
+ // Only update the counter for the maximum value.
+ DEFINE_STATIC_LOCAL(EnumerationHistogram, commited_size_histogram,
+ ("BlinkGC.CommittedSize", kSupportedMaxSizeInMB));
+ commited_size_histogram.Count(size_in_mb);
+ max_committed_size_in_mb = size_in_mb;
+ }
}
} // namespace
void ThreadState::PostSweep() {
DCHECK(CheckThread());
- ThreadHeap::ReportMemoryUsageForTracing();
-
- if (IsMainThread()) {
- ThreadHeapStats& stats = heap_->HeapStats();
- double collection_rate = 1.0 - stats.LiveObjectRateSinceLastGC();
- TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
- "ThreadState::collectionRate",
- static_cast<int>(100 * collection_rate));
-
- VLOG(1) << "[state:" << this << "]"
- << " PostSweep: collection_rate: " << std::setprecision(2)
- << (100 * collection_rate) << "%";
-
- stats.SetMarkedObjectSizeAtLastCompleteSweep(stats.MarkedObjectSize());
-
- stats.SetEstimatedMarkingTimePerByte(
- stats.MarkedObjectSize()
- ? (current_gc_data_.marking_time_in_milliseconds / 1000 /
- stats.MarkedObjectSize())
- : 0);
-
- DEFINE_STATIC_LOCAL(CustomCountHistogram, object_size_before_gc_histogram,
- ("BlinkGC.ObjectSizeBeforeGC", 1, 4 * 1024 * 1024, 50));
- object_size_before_gc_histogram.Count(stats.ObjectSizeAtLastGC() / 1024);
- DEFINE_STATIC_LOCAL(CustomCountHistogram, object_size_after_gc_histogram,
- ("BlinkGC.ObjectSizeAfterGC", 1, 4 * 1024 * 1024, 50));
- object_size_after_gc_histogram.Count(stats.MarkedObjectSize() / 1024);
- DEFINE_STATIC_LOCAL(CustomCountHistogram, collection_rate_histogram,
- ("BlinkGC.CollectionRate", 1, 100, 20));
- collection_rate_histogram.Count(static_cast<int>(100 * collection_rate));
-
-#define COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(GCReason) \
- case BlinkGC::k##GCReason: { \
- DEFINE_STATIC_LOCAL(CustomCountHistogram, histogram, \
- ("BlinkGC.CollectionRate_" #GCReason, 1, 100, 20)); \
- histogram.Count(static_cast<int>(100 * collection_rate)); \
- break; \
- }
-
- switch (current_gc_data_.reason) {
- COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(IdleGC)
- COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(PreciseGC)
- COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(ConservativeGC)
- COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(ForcedGC)
- COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(MemoryPressureGC)
- COUNT_COLLECTION_RATE_HISTOGRAM_BY_GC_REASON(PageNavigationGC)
- default:
- break;
- }
- }
SetGCPhase(GCPhase::kNone);
- if (GcState() == kIdleGCScheduled)
+ if (GetGCState() == kIdleGCScheduled)
ScheduleIdleGC();
gc_age_++;
@@ -1072,14 +1220,15 @@ void ThreadState::PostSweep() {
for (auto* const observer : observers_)
observer->OnCompleteSweepDone();
- Heap().stats_collector()->Stop();
+ Heap().stats_collector()->NotifySweepingCompleted();
if (IsMainThread())
UpdateHistograms(Heap().stats_collector()->previous());
+ // Emit trace counters for all threads.
+ UpdateTraceCounters(*Heap().stats_collector());
}
void ThreadState::SafePoint(BlinkGC::StackState stack_state) {
DCHECK(CheckThread());
- ThreadHeap::ReportMemoryUsageForTracing();
RunScheduledGC(stack_state);
stack_state_ = BlinkGC::kHeapPointersOnStack;
@@ -1157,8 +1306,8 @@ void ThreadState::ReportMemoryToV8() {
if (!isolate_)
return;
- size_t current_heap_size = heap_->HeapStats().AllocatedObjectSize() +
- heap_->HeapStats().MarkedObjectSize();
+ const size_t current_heap_size =
+ heap_->stats_collector()->object_size_in_bytes();
int64_t diff = static_cast<int64_t>(current_heap_size) -
static_cast<int64_t>(reported_memory_to_v8_);
isolate_->AdjustAmountOfExternalAllocatedMemory(diff);
@@ -1296,20 +1445,23 @@ void ThreadState::DisableWrapperTracingBarrier() {
SetWrapperTracing(false);
}
-void ThreadState::IncrementalMarkingStart() {
+void ThreadState::IncrementalMarkingStart(BlinkGC::GCReason reason) {
VLOG(2) << "[state:" << this << "] "
<< "IncrementalMarking: Start";
+ DCHECK(!IsMarkingInProgress());
CompleteSweep();
- // TODO(mlippautz): Replace this with a proper reason once incremental marking
- // is actually scheduled in production.
- Heap().stats_collector()->Start(BlinkGC::kTesting);
+ Heap().stats_collector()->NotifyMarkingStarted(reason);
{
ThreadHeapStatsCollector::Scope stats_scope(
Heap().stats_collector(),
- ThreadHeapStatsCollector::kIncrementalMarkingStartMarking);
+ ThreadHeapStatsCollector::kIncrementalMarkingStartMarking, "reason",
+ GcReasonString(reason));
AtomicPauseScope atomic_pause_scope(this);
+ next_incremental_marking_step_duration_ =
+ kDefaultIncrementalMarkingStepDuration;
+ previous_incremental_marking_time_left_ = TimeDelta::Max();
MarkPhasePrologue(BlinkGC::kNoHeapPointersOnStack,
- BlinkGC::kIncrementalMarking, BlinkGC::kTesting);
+ BlinkGC::kIncrementalMarking, reason);
MarkPhaseVisitRoots();
EnableIncrementalMarkingBarrier();
ScheduleIncrementalMarkingStep();
@@ -1326,7 +1478,7 @@ void ThreadState::IncrementalMarkingStep() {
AtomicPauseScope atomic_pause_scope(this);
DCHECK(IsMarkingInProgress());
bool complete = MarkPhaseAdvanceMarking(
- CurrentTimeTicksInSeconds() + kIncrementalMarkingStepDurationInSeconds);
+ CurrentTimeTicks() + next_incremental_marking_step_duration_);
if (complete)
ScheduleIncrementalMarkingFinalize();
else
@@ -1335,30 +1487,15 @@ void ThreadState::IncrementalMarkingStep() {
}
void ThreadState::IncrementalMarkingFinalize() {
- {
- ThreadHeapStatsCollector::Scope stats_scope(
- Heap().stats_collector(),
- ThreadHeapStatsCollector::kIncrementalMarkingFinalize);
- VLOG(2) << "[state:" << this << "] "
- << "IncrementalMarking: Finalize";
- SetGCState(kNoGCScheduled);
- DisableIncrementalMarkingBarrier();
- AtomicPauseScope atomic_pause_scope(this);
- DCHECK(IsMarkingInProgress());
- {
- ThreadHeapStatsCollector::Scope stats_scope(
- Heap().stats_collector(),
- ThreadHeapStatsCollector::kIncrementalMarkingFinalizeMarking);
- MarkPhaseVisitRoots();
- bool complete =
- MarkPhaseAdvanceMarking(std::numeric_limits<double>::infinity());
- CHECK(complete);
- MarkPhaseEpilogue(current_gc_data_.marking_type);
- }
- PreSweep(current_gc_data_.marking_type, BlinkGC::kLazySweeping);
- DCHECK(IsSweepingInProgress());
- DCHECK_EQ(GcState(), kNoGCScheduled);
- }
+ ThreadHeapStatsCollector::Scope stats_scope(
+ Heap().stats_collector(),
+ ThreadHeapStatsCollector::kIncrementalMarkingFinalize);
+ VLOG(2) << "[state:" << this << "] "
+ << "IncrementalMarking: Finalize";
+ // Call into the regular bottleneck instead of the internal version to get
+ // UMA accounting and allow follow up GCs if necessary.
+ CollectGarbage(BlinkGC::kNoHeapPointersOnStack, BlinkGC::kIncrementalMarking,
+ BlinkGC::kLazySweeping, current_gc_data_.reason);
}
void ThreadState::CollectGarbage(BlinkGC::StackState stack_state,
@@ -1372,46 +1509,96 @@ void ThreadState::CollectGarbage(BlinkGC::StackState stack_state,
if (SweepForbidden())
return;
- double start_total_collect_garbage_time =
- WTF::CurrentTimeTicksInMilliseconds();
+ TimeTicks start_total_collect_garbage_time = WTF::CurrentTimeTicks();
RUNTIME_CALL_TIMER_SCOPE_IF_ISOLATE_EXISTS(
GetIsolate(), RuntimeCallStats::CounterId::kCollectGarbage);
const bool was_incremental_marking = IsMarkingInProgress();
if (was_incremental_marking) {
- // Set stack state in case we are starting a Conservative GC while
- // incremental marking is in progress.
- current_gc_data_.stack_state = stack_state;
- IncrementalMarkingFinalize();
+ SetGCState(kNoGCScheduled);
+ DisableIncrementalMarkingBarrier();
+ DCHECK(IsMarkingInProgress());
+ RunAtomicPause(stack_state, marking_type, sweeping_type, reason);
}
// We don't want floating garbage for the specific garbage collection types
// mentioned below. In this case we will follow up with a regular full
// garbage collection.
- const bool should_do_full_gc = !was_incremental_marking ||
- reason == BlinkGC::kForcedGC ||
- reason == BlinkGC::kMemoryPressureGC ||
- reason == BlinkGC::kThreadTerminationGC;
+ const bool should_do_full_gc =
+ !was_incremental_marking || reason == BlinkGC::GCReason::kForcedGC ||
+ reason == BlinkGC::GCReason::kMemoryPressureGC ||
+ reason == BlinkGC::GCReason::kThreadTerminationGC;
if (should_do_full_gc) {
CompleteSweep();
SetGCState(kNoGCScheduled);
- Heap().stats_collector()->Start(reason);
+ Heap().stats_collector()->NotifyMarkingStarted(reason);
+ RunAtomicPause(stack_state, marking_type, sweeping_type, reason);
+ }
+
+ const TimeDelta total_collect_garbage_time =
+ WTF::CurrentTimeTicks() - start_total_collect_garbage_time;
+ UMA_HISTOGRAM_TIMES("BlinkGC.TimeForTotalCollectGarbage",
+ total_collect_garbage_time);
+
+#define COUNT_BY_GC_REASON(reason) \
+ case BlinkGC::GCReason::k##reason: { \
+ UMA_HISTOGRAM_TIMES("BlinkGC.TimeForTotalCollectGarbage_" #reason, \
+ total_collect_garbage_time); \
+ break; \
+ }
+
+ switch (reason) {
+ COUNT_BY_GC_REASON(IdleGC)
+ COUNT_BY_GC_REASON(PreciseGC)
+ COUNT_BY_GC_REASON(ConservativeGC)
+ COUNT_BY_GC_REASON(ForcedGC)
+ COUNT_BY_GC_REASON(MemoryPressureGC)
+ COUNT_BY_GC_REASON(PageNavigationGC)
+ COUNT_BY_GC_REASON(ThreadTerminationGC)
+ COUNT_BY_GC_REASON(Testing)
+ COUNT_BY_GC_REASON(IncrementalIdleGC)
+ COUNT_BY_GC_REASON(IncrementalV8FollowupGC)
+ }
+#undef COUNT_BY_GC_REASON
+
+ VLOG(1) << "[state:" << this << "]"
+ << " CollectGarbage: time: " << std::setprecision(2)
+ << total_collect_garbage_time.InMillisecondsF() << "ms"
+ << " stack: " << StackStateString(stack_state)
+ << " marking: " << MarkingTypeString(marking_type)
+ << " sweeping: " << SweepingTypeString(sweeping_type)
+ << " reason: " << GcReasonString(reason);
+}
+
+void ThreadState::RunAtomicPause(BlinkGC::StackState stack_state,
+ BlinkGC::MarkingType marking_type,
+ BlinkGC::SweepingType sweeping_type,
+ BlinkGC::GCReason reason) {
+ {
+ ThreadHeapStatsCollector::EnabledScope stats1(
+ Heap().stats_collector(), ThreadHeapStatsCollector::kAtomicPhase);
AtomicPauseScope atomic_pause_scope(this);
{
- ThreadHeapStatsCollector::EnabledScope stats_scope(
+ ThreadHeapStatsCollector::EnabledScope stats2(
Heap().stats_collector(),
ThreadHeapStatsCollector::kAtomicPhaseMarking, "lazySweeping",
sweeping_type == BlinkGC::kLazySweeping ? "yes" : "no", "gcReason",
GcReasonString(reason));
- MarkPhasePrologue(stack_state, marking_type, reason);
+ AtomicPausePrologue(stack_state, marking_type, reason);
MarkPhaseVisitRoots();
- CHECK(MarkPhaseAdvanceMarking(std::numeric_limits<double>::infinity()));
+ CHECK(MarkPhaseAdvanceMarking(TimeTicks::Max()));
MarkPhaseEpilogue(marking_type);
}
- PreSweep(marking_type, sweeping_type);
+ AtomicPauseEpilogue(marking_type, sweeping_type);
}
-
+ if (marking_type == BlinkGC::kTakeSnapshot) {
+ FinishSnapshot();
+ CHECK(!IsSweepingInProgress());
+ CHECK_EQ(GetGCState(), kNoGCScheduled);
+ return;
+ }
+ DCHECK(IsSweepingInProgress());
if (sweeping_type == BlinkGC::kEagerSweeping) {
// Eager sweeping should happen only in testing.
CompleteSweep();
@@ -1420,48 +1607,53 @@ void ThreadState::CollectGarbage(BlinkGC::StackState stack_state,
// The default behavior is lazy sweeping.
ScheduleIdleLazySweep();
}
+}
- double total_collect_garbage_time =
- WTF::CurrentTimeTicksInMilliseconds() - start_total_collect_garbage_time;
- DEFINE_THREAD_SAFE_STATIC_LOCAL(
- CustomCountHistogram, time_for_total_collect_garbage_histogram,
- ("BlinkGC.TimeForTotalCollectGarbage", 1, 10 * 1000, 50));
- time_for_total_collect_garbage_histogram.Count(total_collect_garbage_time);
- VLOG(1) << "[state:" << this << "]"
- << " CollectGarbage: time: " << std::setprecision(2)
- << total_collect_garbage_time << "ms"
- << " stack: " << StackStateString(stack_state)
- << " marking: " << MarkingTypeString(marking_type)
- << " sweeping: " << SweepingTypeString(sweeping_type)
- << " reason: " << GcReasonString(reason);
+namespace {
+
+MarkingVisitor::MarkingMode GetMarkingMode(bool should_compact,
+ bool create_snapshot) {
+ CHECK(!should_compact || !create_snapshot);
+ return (create_snapshot)
+ ? MarkingVisitor::kSnapshotMarking
+ : (should_compact) ? MarkingVisitor::kGlobalMarkingWithCompaction
+ : MarkingVisitor::kGlobalMarking;
}
+} // namespace
+
void ThreadState::MarkPhasePrologue(BlinkGC::StackState stack_state,
BlinkGC::MarkingType marking_type,
BlinkGC::GCReason reason) {
SetGCPhase(GCPhase::kMarking);
Heap().CommitCallbackStacks();
+ const bool take_snapshot = marking_type == BlinkGC::kTakeSnapshot;
+ const bool should_compact =
+ !take_snapshot && Heap().Compaction()->ShouldCompact(
+ &Heap(), stack_state, marking_type, reason);
+
+ current_gc_data_.visitor = MarkingVisitor::Create(
+ this, GetMarkingMode(should_compact, take_snapshot));
current_gc_data_.stack_state = stack_state;
current_gc_data_.marking_type = marking_type;
current_gc_data_.reason = reason;
- current_gc_data_.marking_time_in_milliseconds = 0;
- if (marking_type == BlinkGC::kTakeSnapshot) {
- current_gc_data_.visitor =
- MarkingVisitor::Create(this, MarkingVisitor::kSnapshotMarking);
+ if (should_compact)
+ Heap().Compaction()->Initialize(this);
+}
+
+void ThreadState::AtomicPausePrologue(BlinkGC::StackState stack_state,
+ BlinkGC::MarkingType marking_type,
+ BlinkGC::GCReason reason) {
+ if (IsMarkingInProgress()) {
+ // Incremental marking is already in progress. Only update the state
+ // that is necessary to update.
+ current_gc_data_.reason = reason;
+ current_gc_data_.stack_state = stack_state;
+ Heap().stats_collector()->UpdateReason(reason);
} else {
- DCHECK(marking_type == BlinkGC::kAtomicMarking ||
- marking_type == BlinkGC::kIncrementalMarking);
- if (Heap().Compaction()->ShouldCompact(&Heap(), stack_state, marking_type,
- reason)) {
- Heap().Compaction()->Initialize(this);
- current_gc_data_.visitor = MarkingVisitor::Create(
- this, MarkingVisitor::kGlobalMarkingWithCompaction);
- } else {
- current_gc_data_.visitor =
- MarkingVisitor::Create(this, MarkingVisitor::kGlobalMarking);
- }
+ MarkPhasePrologue(stack_state, marking_type, reason);
}
if (marking_type == BlinkGC::kTakeSnapshot)
@@ -1473,14 +1665,9 @@ void ThreadState::MarkPhasePrologue(BlinkGC::StackState stack_state,
DCHECK(InAtomicMarkingPause());
Heap().MakeConsistentForGC();
Heap().ClearArenaAges();
-
- if (marking_type != BlinkGC::kTakeSnapshot)
- Heap().ResetHeapCounters();
}
void ThreadState::MarkPhaseVisitRoots() {
- double start_time = WTF::CurrentTimeTicksInMilliseconds();
-
// StackFrameDepth should be disabled so we don't trace most of the object
// graph in one incremental marking step.
DCHECK(!Heap().GetStackFrameDepth().IsEnabled());
@@ -1493,22 +1680,13 @@ void ThreadState::MarkPhaseVisitRoots() {
SafePointScope safe_point_scope(current_gc_data_.stack_state, this);
Heap().VisitStackRoots(current_gc_data_.visitor.get());
}
- current_gc_data_.marking_time_in_milliseconds +=
- WTF::CurrentTimeTicksInMilliseconds() - start_time;
}
-bool ThreadState::MarkPhaseAdvanceMarking(double deadline_seconds) {
- double start_time = WTF::CurrentTimeTicksInMilliseconds();
-
+bool ThreadState::MarkPhaseAdvanceMarking(TimeTicks deadline) {
StackFrameDepthScope stack_depth_scope(&Heap().GetStackFrameDepth());
-
// 3. Transitive closure to trace objects including ephemerons.
- bool complete = Heap().AdvanceMarkingStackProcessing(
- current_gc_data_.visitor.get(), deadline_seconds);
-
- current_gc_data_.marking_time_in_milliseconds +=
- WTF::CurrentTimeTicksInMilliseconds() - start_time;
- return complete;
+ return Heap().AdvanceMarkingStackProcessing(current_gc_data_.visitor.get(),
+ deadline);
}
bool ThreadState::ShouldVerifyMarking() const {
@@ -1524,13 +1702,11 @@ void ThreadState::MarkPhaseEpilogue(BlinkGC::MarkingType marking_type) {
Visitor* visitor = current_gc_data_.visitor.get();
// Finish marking of not-fully-constructed objects.
Heap().MarkNotFullyConstructedObjects(visitor);
- CHECK(Heap().AdvanceMarkingStackProcessing(
- visitor, std::numeric_limits<double>::infinity()));
+ CHECK(Heap().AdvanceMarkingStackProcessing(visitor, TimeTicks::Max()));
{
// See ProcessHeap::CrossThreadPersistentMutex().
- RecursiveMutexLocker persistent_lock(
- ProcessHeap::CrossThreadPersistentMutex());
+ MutexLocker persistent_lock(ProcessHeap::CrossThreadPersistentMutex());
VisitWeakPersistents(visitor);
Heap().WeakProcessing(visitor);
}
@@ -1541,7 +1717,11 @@ void ThreadState::MarkPhaseEpilogue(BlinkGC::MarkingType marking_type) {
if (ShouldVerifyMarking())
VerifyMarking(marking_type);
- ThreadHeap::ReportMemoryUsageHistogram();
+ ProcessHeap::DecreaseTotalAllocatedObjectSize(
+ Heap().stats_collector()->allocated_bytes_since_prev_gc());
+ ProcessHeap::DecreaseTotalMarkedObjectSize(
+ Heap().stats_collector()->previous().marked_bytes);
+ Heap().stats_collector()->NotifyMarkingCompleted();
WTF::Partitions::ReportMemoryUsageHistogram();
if (invalidate_dead_objects_in_wrappers_marking_deque_)
@@ -1573,12 +1753,26 @@ void ThreadState::CollectAllGarbage() {
size_t previous_live_objects = 0;
for (int i = 0; i < 5; ++i) {
CollectGarbage(BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
- size_t live_objects = Heap().HeapStats().MarkedObjectSize();
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
+ const size_t live_objects =
+ Heap().stats_collector()->previous().marked_bytes;
if (live_objects == previous_live_objects)
break;
previous_live_objects = live_objects;
}
}
+void ThreadState::UpdateIncrementalMarkingStepDuration() {
+ if (!IsIncrementalMarking())
+ return;
+ TimeDelta time_left = Heap().stats_collector()->estimated_marking_time() -
+ Heap().stats_collector()->marking_time_so_far();
+ // Increase step size if estimated time left is increasing.
+ if (previous_incremental_marking_time_left_ < time_left) {
+ constexpr double ratio = 2.0;
+ next_incremental_marking_step_duration_ *= ratio;
+ }
+ previous_incremental_marking_time_left_ = time_left;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/thread_state.h b/chromium/third_party/blink/renderer/platform/heap/thread_state.h
index 58949fd544d..0060c09e379 100644
--- a/chromium/third_party/blink/renderer/platform/heap/thread_state.h
+++ b/chromium/third_party/blink/renderer/platform/heap/thread_state.h
@@ -35,21 +35,21 @@
#include "base/atomicops.h"
#include "base/macros.h"
-#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
#include "third_party/blink/renderer/platform/heap/blink_gc.h"
#include "third_party/blink/renderer/platform/heap/threading_traits.h"
#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/wtf/address_sanitizer.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/blink/renderer/platform/wtf/functional.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/thread_specific.h"
#include "third_party/blink/renderer/platform/wtf/threading.h"
#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
+#include "third_party/blink/renderer/platform/wtf/time.h"
namespace v8 {
class Isolate;
@@ -138,7 +138,8 @@ class PLATFORM_EXPORT BlinkGCObserver {
ThreadState* thread_state_;
};
-class PLATFORM_EXPORT ThreadState {
+class PLATFORM_EXPORT ThreadState final
+ : scheduler::WebThreadScheduler::RAILModeObserver {
USING_FAST_MALLOC(ThreadState);
public:
@@ -146,12 +147,12 @@ class PLATFORM_EXPORT ThreadState {
enum GCState {
kNoGCScheduled,
kIdleGCScheduled,
- kIncrementalMarkingStartScheduled,
kIncrementalMarkingStepScheduled,
kIncrementalMarkingFinalizeScheduled,
kPreciseGCScheduled,
kFullGCScheduled,
kPageNavigationGCScheduled,
+ kIncrementalGCScheduled,
};
// The phase that the GC is in. The GCPhase will not return kNone for mutators
@@ -266,20 +267,22 @@ class PLATFORM_EXPORT ThreadState {
// in the dangling pointer situation.
void RunTerminationGC();
- void PerformIdleGC(double deadline_seconds);
- void PerformIdleLazySweep(double deadline_seconds);
+ void PerformIdleGC(TimeTicks deadline);
+ void PerformIdleLazySweep(TimeTicks deadline);
void ScheduleIdleGC();
void ScheduleIdleLazySweep();
void SchedulePreciseGC();
+ void ScheduleIncrementalGC(BlinkGC::GCReason);
void ScheduleV8FollowupGCIfNeeded(BlinkGC::V8GCType);
void SchedulePageNavigationGCIfNeeded(float estimated_removal_ratio);
void SchedulePageNavigationGC();
+ void ScheduleFullGC();
void ScheduleGCIfNeeded();
void PostIdleGCTask();
void WillStartV8GC(BlinkGC::V8GCType);
void SetGCState(GCState);
- GCState GcState() const { return gc_state_; }
+ GCState GetGCState() const { return gc_state_; }
void SetGCPhase(GCPhase);
bool IsMarkingInProgress() const { return gc_phase_ == GCPhase::kMarking; }
bool IsSweepingInProgress() const { return gc_phase_ == GCPhase::kSweeping; }
@@ -288,38 +291,18 @@ class PLATFORM_EXPORT ThreadState {
void DisableWrapperTracingBarrier();
// Incremental GC.
-
- void ScheduleIncrementalMarkingStart();
void ScheduleIncrementalMarkingStep();
void ScheduleIncrementalMarkingFinalize();
- void IncrementalMarkingStart();
+ void IncrementalMarkingStart(BlinkGC::GCReason);
void IncrementalMarkingStep();
void IncrementalMarkingFinalize();
void EnableIncrementalMarkingBarrier();
void DisableIncrementalMarkingBarrier();
- // A GC runs in the following sequence.
- //
- // 1) preGC() is called.
- // 2) ThreadHeap::collectGarbage() is called. This marks live objects.
- // 3) postGC() is called. This does thread-local weak processing.
- // 4) preSweep() is called. This does pre-finalization, eager sweeping and
- // heap compaction.
- // 4) Lazy sweeping sweeps heaps incrementally. completeSweep() may be called
- // to complete the sweeping.
- // 5) postSweep() is called.
- void MarkPhasePrologue(BlinkGC::StackState,
- BlinkGC::MarkingType,
- BlinkGC::GCReason);
- void MarkPhaseVisitRoots();
- bool MarkPhaseAdvanceMarking(double deadline_seconds);
- void MarkPhaseEpilogue(BlinkGC::MarkingType);
- void VerifyMarking(BlinkGC::MarkingType);
-
void CompleteSweep();
- void PreSweep(BlinkGC::MarkingType, BlinkGC::SweepingType);
+ void FinishSnapshot();
void PostSweep();
// Support for disallowing allocation. Mainly used for sanity
@@ -586,12 +569,19 @@ class PLATFORM_EXPORT ThreadState {
MarkingVisitor* CurrentVisitor() { return current_gc_data_.visitor.get(); }
+ // Implementation for RAILModeObserver
+ void OnRAILModeChanged(v8::RAILMode new_mode) override {
+ should_optimize_for_load_time_ = new_mode == v8::RAILMode::PERFORMANCE_LOAD;
+ }
+
private:
// Needs to set up visitor for testing purposes.
friend class incremental_marking_test::IncrementalMarkingScope;
friend class incremental_marking_test::IncrementalMarkingTestDriver;
template <typename T>
friend class PrefinalizerRegistration;
+ friend class TestGCMarkingScope;
+ friend class ThreadStateSchedulingTest;
// Number of ThreadState's that are currently in incremental marking. The
// counter is incremented by one when some ThreadState enters incremental
@@ -602,7 +592,25 @@ class PLATFORM_EXPORT ThreadState {
static base::subtle::AtomicWord wrapper_tracing_counter_;
ThreadState();
- ~ThreadState();
+ ~ThreadState() override;
+
+ // The version is needed to be able to start incremental marking.
+ void MarkPhasePrologue(BlinkGC::StackState,
+ BlinkGC::MarkingType,
+ BlinkGC::GCReason);
+ void AtomicPausePrologue(BlinkGC::StackState,
+ BlinkGC::MarkingType,
+ BlinkGC::GCReason);
+ void AtomicPauseEpilogue(BlinkGC::MarkingType, BlinkGC::SweepingType);
+ void MarkPhaseEpilogue(BlinkGC::MarkingType);
+ void MarkPhaseVisitRoots();
+ bool MarkPhaseAdvanceMarking(TimeTicks deadline);
+ void VerifyMarking(BlinkGC::MarkingType);
+
+ void RunAtomicPause(BlinkGC::StackState,
+ BlinkGC::MarkingType,
+ BlinkGC::SweepingType,
+ BlinkGC::GCReason);
void ClearSafePointScopeMarker() {
safe_point_stack_copy_.clear();
@@ -621,7 +629,7 @@ class PLATFORM_EXPORT ThreadState {
// collect garbage at this point.
bool ShouldScheduleIdleGC();
bool ShouldForceConservativeGC();
- bool ShouldScheduleIncrementalMarking() const;
+ bool ShouldScheduleIncrementalMarking();
// V8 minor or major GC is likely to drop a lot of references to objects
// on Oilpan's heap. We give a chance to schedule a GC.
bool ShouldScheduleV8FollowupGC();
@@ -631,6 +639,8 @@ class PLATFORM_EXPORT ThreadState {
// longer necessary due to the navigation.
bool ShouldSchedulePageNavigationGC(float estimated_removal_ratio);
+ void RescheduleIdleGC();
+
// Internal helpers to handle memory pressure conditions.
// Returns true if memory use is in a near-OOM state
@@ -651,6 +661,8 @@ class PLATFORM_EXPORT ThreadState {
void RunScheduledGC(BlinkGC::StackState);
+ void UpdateIncrementalMarkingStepDuration();
+
void EagerSweep();
void InvokePreFinalizers();
@@ -699,10 +711,16 @@ class PLATFORM_EXPORT ThreadState {
bool object_resurrection_forbidden_;
bool in_atomic_pause_;
+ TimeDelta next_incremental_marking_step_duration_;
+ TimeDelta previous_incremental_marking_time_left_;
+
GarbageCollectedMixinConstructorMarkerBase* gc_mixin_marker_;
GCState gc_state_;
GCPhase gc_phase_;
+ BlinkGC::GCReason reason_for_scheduled_gc_;
+
+ bool should_optimize_for_load_time_;
using PreFinalizerCallback = bool (*)(void*);
using PreFinalizer = std::pair<void*, PreFinalizerCallback>;
@@ -744,7 +762,6 @@ class PLATFORM_EXPORT ThreadState {
BlinkGC::StackState stack_state;
BlinkGC::MarkingType marking_type;
BlinkGC::GCReason reason;
- double marking_time_in_milliseconds;
std::unique_ptr<MarkingVisitor> visitor;
};
GCData current_gc_data_;
diff --git a/chromium/third_party/blink/renderer/platform/heap/thread_state_scheduling_test.cc b/chromium/third_party/blink/renderer/platform/heap/thread_state_scheduling_test.cc
new file mode 100644
index 00000000000..a4818fdb32a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/heap/thread_state_scheduling_test.cc
@@ -0,0 +1,236 @@
+// 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 "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/heap/heap_test_utilities.h"
+#include "third_party/blink/renderer/platform/heap/thread_state.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+
+namespace blink {
+
+class ThreadStateSchedulingTest : public testing::Test {
+ public:
+ void SetUp() override {
+ state_ = ThreadState::Current();
+ ClearOutOldGarbage();
+ initial_gc_age_ = state_->GcAge();
+ }
+
+ void TearDown() override {
+ features_backup_.Restore();
+ PreciselyCollectGarbage();
+ EXPECT_EQ(ThreadState::kNoGCScheduled, state_->GetGCState());
+ EXPECT_FALSE(state_->IsMarkingInProgress());
+ EXPECT_FALSE(state_->IsSweepingInProgress());
+ }
+
+ void StartIncrementalMarkingForIdleGC() {
+ RuntimeEnabledFeatures::SetHeapIncrementalMarkingEnabled(true);
+ EXPECT_EQ(ThreadState::kNoGCScheduled, state_->GetGCState());
+ state_->ScheduleIdleGC();
+ RunIdleGCTask();
+ EXPECT_EQ(ThreadState::kIncrementalMarkingStepScheduled,
+ state_->GetGCState());
+ EXPECT_TRUE(state_->IsMarkingInProgress());
+ }
+
+ void RunIdleGCTask() {
+ // Simulate running idle GC task, instead of actually running the posted
+ // task.
+ EXPECT_EQ(ThreadState::kIdleGCScheduled, state_->GetGCState());
+ state_->PerformIdleGC(TimeTicks::Max());
+ }
+
+ void StartLazySweepingForPreciseGC() {
+ EXPECT_EQ(ThreadState::kNoGCScheduled, state_->GetGCState());
+ state_->SchedulePreciseGC();
+ EXPECT_EQ(ThreadState::kPreciseGCScheduled, state_->GetGCState());
+ RunScheduledGC(BlinkGC::kNoHeapPointersOnStack);
+ EXPECT_TRUE(state_->IsSweepingInProgress());
+ EXPECT_EQ(ThreadState::kNoGCScheduled, state_->GetGCState());
+ }
+
+ void RunScheduledGC(BlinkGC::StackState stack_state) {
+ state_->RunScheduledGC(stack_state);
+ }
+
+ // Counter that is incremented when sweep finishes.
+ int GCCount() { return state_->GcAge() - initial_gc_age_; }
+
+ ThreadState* state() { return state_; }
+
+ private:
+ ThreadState* state_;
+ int initial_gc_age_;
+ RuntimeEnabledFeatures::Backup features_backup_;
+};
+
+TEST_F(ThreadStateSchedulingTest, ScheduleIdleGCAgain) {
+ ThreadStateSchedulingTest* test = this;
+
+ EXPECT_EQ(ThreadState::kNoGCScheduled, test->state()->GetGCState());
+ test->state()->ScheduleIdleGC();
+ EXPECT_EQ(ThreadState::kIdleGCScheduled, test->state()->GetGCState());
+
+ // Calling ScheduleIdleGC() while an idle GC is scheduled will do nothing.
+ test->state()->ScheduleIdleGC();
+
+ EXPECT_EQ(ThreadState::kIdleGCScheduled, test->state()->GetGCState());
+ EXPECT_EQ(0, test->GCCount());
+}
+
+TEST_F(ThreadStateSchedulingTest, ScheduleIncrementalV8FollowupGCAgain) {
+ ThreadStateSchedulingTest* test = this;
+
+ EXPECT_EQ(ThreadState::kNoGCScheduled, test->state()->GetGCState());
+ test->state()->ScheduleIncrementalGC(
+ BlinkGC::GCReason::kIncrementalV8FollowupGC);
+ EXPECT_EQ(ThreadState::kIncrementalGCScheduled, test->state()->GetGCState());
+
+ // Calling ScheduleIncrementalV8FollowupGC() while one is already scheduled
+ // will do nothing.
+ test->state()->ScheduleIncrementalGC(
+ BlinkGC::GCReason::kIncrementalV8FollowupGC);
+
+ EXPECT_EQ(ThreadState::kIncrementalGCScheduled, test->state()->GetGCState());
+ EXPECT_EQ(0, test->GCCount());
+}
+
+TEST_F(ThreadStateSchedulingTest, ScheduleIdleGCWhileIncrementalMarking) {
+ ThreadStateSchedulingTest* test = this;
+
+ test->StartIncrementalMarkingForIdleGC();
+
+ EXPECT_TRUE(test->state()->IsMarkingInProgress());
+ EXPECT_EQ(ThreadState::kIncrementalMarkingStepScheduled,
+ test->state()->GetGCState());
+
+ // Calling ScheduleIdleGC() while an idle GC is scheduled should do nothing.
+ test->state()->ScheduleIdleGC();
+
+ EXPECT_TRUE(test->state()->IsMarkingInProgress());
+ EXPECT_EQ(ThreadState::kIncrementalMarkingStepScheduled,
+ test->state()->GetGCState());
+}
+
+TEST_F(ThreadStateSchedulingTest, ScheduleIdleGCWhileLazySweeping) {
+ ThreadStateSchedulingTest* test = this;
+
+ test->StartLazySweepingForPreciseGC();
+
+ test->state()->ScheduleIdleGC();
+
+ // Scheduling an idle GC should finish lazy sweeping.
+ EXPECT_FALSE(test->state()->IsSweepingInProgress());
+ EXPECT_EQ(ThreadState::kIdleGCScheduled, test->state()->GetGCState());
+}
+
+TEST_F(ThreadStateSchedulingTest, SchedulePreciseGCWhileLazySweeping) {
+ ThreadStateSchedulingTest* test = this;
+
+ test->StartLazySweepingForPreciseGC();
+
+ test->state()->SchedulePreciseGC();
+
+ // Scheduling a precise GC should finish lazy sweeping.
+ EXPECT_FALSE(test->state()->IsSweepingInProgress());
+ EXPECT_EQ(ThreadState::kPreciseGCScheduled, test->state()->GetGCState());
+}
+
+TEST_F(ThreadStateSchedulingTest,
+ ScheduleIncrementalV8FollowupGCWhileLazySweeping) {
+ ThreadStateSchedulingTest* test = this;
+
+ test->StartLazySweepingForPreciseGC();
+
+ test->state()->ScheduleIncrementalGC(
+ BlinkGC::GCReason::kIncrementalV8FollowupGC);
+
+ // Scheduling a IncrementalV8FollowupGC should finish lazy sweeping.
+ EXPECT_FALSE(test->state()->IsSweepingInProgress());
+ EXPECT_EQ(ThreadState::kIncrementalGCScheduled, test->state()->GetGCState());
+}
+
+TEST_F(ThreadStateSchedulingTest, SchedulePreciseGCWhileIncrementalMarking) {
+ ThreadStateSchedulingTest* test = this;
+
+ test->StartIncrementalMarkingForIdleGC();
+
+ test->state()->SchedulePreciseGC();
+
+ // Scheduling a precise GC should cancel incremental marking tasks.
+ EXPECT_EQ(ThreadState::kPreciseGCScheduled, test->state()->GetGCState());
+
+ EXPECT_EQ(0, test->GCCount());
+ test->RunScheduledGC(BlinkGC::kNoHeapPointersOnStack);
+ EXPECT_TRUE(test->state()->IsSweepingInProgress());
+ EXPECT_EQ(ThreadState::kNoGCScheduled, test->state()->GetGCState());
+
+ // Running the precise GC should simply finish the incremental marking idle GC
+ // (not run another GC).
+ EXPECT_EQ(0, test->GCCount());
+ test->state()->CompleteSweep();
+ EXPECT_EQ(1, test->GCCount());
+}
+
+TEST_F(ThreadStateSchedulingTest,
+ ScheduleIncrementalV8FollowupGCWhileIncrementalMarking) {
+ ThreadStateSchedulingTest* test = this;
+
+ test->StartIncrementalMarkingForIdleGC();
+
+ test->state()->ScheduleIncrementalGC(
+ BlinkGC::GCReason::kIncrementalV8FollowupGC);
+
+ // Scheduling a precise GC should not cancel incremental marking tasks.
+ EXPECT_EQ(ThreadState::kIncrementalMarkingStepScheduled,
+ test->state()->GetGCState());
+}
+
+TEST_F(ThreadStateSchedulingTest, ScheduleIdleGCWhileGCForbidden) {
+ ThreadStateSchedulingTest* test = this;
+
+ test->state()->ScheduleIdleGC();
+ EXPECT_EQ(ThreadState::kIdleGCScheduled, test->state()->GetGCState());
+
+ ThreadState::GCForbiddenScope gc_forbidden_scope(test->state());
+ test->RunIdleGCTask();
+
+ // Starting an idle GC while GC is forbidden should reschedule it.
+ EXPECT_EQ(ThreadState::kIdleGCScheduled, test->state()->GetGCState());
+}
+
+TEST_F(ThreadStateSchedulingTest,
+ ScheduleIncrementalV8FollowupGCWhileGCForbidden) {
+ ThreadStateSchedulingTest* test = this;
+
+ EXPECT_EQ(ThreadState::kNoGCScheduled, test->state()->GetGCState());
+ test->state()->ScheduleIncrementalGC(
+ BlinkGC::GCReason::kIncrementalV8FollowupGC);
+ EXPECT_EQ(ThreadState::kIncrementalGCScheduled, test->state()->GetGCState());
+
+ ThreadState::GCForbiddenScope gc_forbidden_scope(test->state());
+ test->RunScheduledGC(BlinkGC::kNoHeapPointersOnStack);
+
+ // Starting an IncrementalV8FollowupGC while GC is forbidden should do
+ // nothing.
+ EXPECT_EQ(ThreadState::kIncrementalGCScheduled, test->state()->GetGCState());
+ EXPECT_EQ(0, GCCount());
+}
+
+TEST_F(ThreadStateSchedulingTest, RunIncrementalV8FollowupGC) {
+ ThreadStateSchedulingTest* test = this;
+
+ EXPECT_EQ(ThreadState::kNoGCScheduled, test->state()->GetGCState());
+ test->state()->ScheduleIncrementalGC(
+ BlinkGC::GCReason::kIncrementalV8FollowupGC);
+ EXPECT_EQ(ThreadState::kIncrementalGCScheduled, test->state()->GetGCState());
+
+ test->RunScheduledGC(BlinkGC::kNoHeapPointersOnStack);
+
+ EXPECT_EQ(ThreadState::kIncrementalMarkingStepScheduled,
+ test->state()->GetGCState());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/heap/trace_traits.h b/chromium/third_party/blink/renderer/platform/heap/trace_traits.h
index 87c81a07824..9ac4c315e2b 100644
--- a/chromium/third_party/blink/renderer/platform/heap/trace_traits.h
+++ b/chromium/third_party/blink/renderer/platform/heap/trace_traits.h
@@ -54,10 +54,6 @@ class AdjustPointerTrait<T, false> {
return {self, TraceTrait<T>::Trace, TraceEagerlyTrait<T>::value};
}
- static TraceWrapperDescriptor GetTraceWrapperDescriptor(void* self) {
- return {self, TraceTrait<T>::TraceWrappers};
- }
-
static HeapObjectHeader* GetHeapObjectHeader(void* self) {
#if DCHECK_IS_ON()
HeapObjectHeader::CheckFromPayload(self);
@@ -76,11 +72,6 @@ class AdjustPointerTrait<T, true> {
return self->GetTraceDescriptor();
}
- static TraceWrapperDescriptor GetTraceWrapperDescriptor(const T* self) {
- DCHECK(self);
- return self->GetTraceWrapperDescriptor();
- }
-
static HeapObjectHeader* GetHeapObjectHeader(const T* self) {
DCHECK(self);
return self->GetHeapObjectHeader();
@@ -191,17 +182,11 @@ class TraceTrait {
return AdjustPointerTrait<T>::GetTraceDescriptor(static_cast<T*>(self));
}
- static TraceWrapperDescriptor GetTraceWrapperDescriptor(void* self) {
- return AdjustPointerTrait<T>::GetTraceWrapperDescriptor(
- static_cast<T*>(self));
- }
-
static HeapObjectHeader* GetHeapObjectHeader(void* self) {
return AdjustPointerTrait<T>::GetHeapObjectHeader(static_cast<T*>(self));
}
static void Trace(Visitor*, void* self);
- static void TraceWrappers(ScriptWrappableVisitor*, void*);
};
template <typename T>
@@ -213,14 +198,6 @@ void TraceTrait<T>::Trace(Visitor* visitor, void* self) {
static_cast<T*>(self)->Trace(visitor);
}
-template <typename T>
-void TraceTrait<T>::TraceWrappers(ScriptWrappableVisitor* visitor, void* self) {
- static_assert(sizeof(T), "type needs to be defined");
- static_assert(IsGarbageCollectedType<T>::value,
- "only objects deriving from GarbageCollected can be used");
- visitor->DispatchTraceWrappers(static_cast<T*>(self));
-}
-
template <typename T, typename Traits>
struct TraceTrait<HeapVectorBacking<T, Traits>> {
STATIC_ONLY(TraceTrait);
diff --git a/chromium/third_party/blink/renderer/platform/heap/visitor.h b/chromium/third_party/blink/renderer/platform/heap/visitor.h
index ee3ad9dc49a..9b9ba505449 100644
--- a/chromium/third_party/blink/renderer/platform/heap/visitor.h
+++ b/chromium/third_party/blink/renderer/platform/heap/visitor.h
@@ -228,8 +228,8 @@ class PLATFORM_EXPORT Visitor {
// the TraceDescriptor versions.
Visit(const_cast<void*>(reinterpret_cast<const void*>(t)),
TraceDescriptorFor(t));
- Visit(const_cast<void*>(reinterpret_cast<const void*>(t)),
- TraceWrapperDescriptorFor(t));
+ VisitWithWrappers(const_cast<void*>(reinterpret_cast<const void*>(t)),
+ TraceDescriptorFor(t));
}
void Trace(DOMWrapperMap<ScriptWrappable>* wrapper_map,
@@ -248,9 +248,7 @@ class PLATFORM_EXPORT Visitor {
virtual void Visit(void*, TraceDescriptor) = 0;
// Subgraph of objects that are interested in wrappers. Note that the same
// object is also passed to Visit(void*, TraceDescriptor).
- // TODO(mlippautz): Remove this visit method once wrapper tracing also uses
- // Trace() instead of TraceWrappers().
- virtual void Visit(void*, TraceWrapperDescriptor) = 0;
+ virtual void VisitWithWrappers(void*, TraceDescriptor) = 0;
// Visits an object through a weak reference.
virtual void VisitWeak(void*, void**, TraceDescriptor, WeakCallback) = 0;
@@ -298,12 +296,6 @@ class PLATFORM_EXPORT Visitor {
return TraceTrait<T>::GetTraceDescriptor(const_cast<T*>(traceable));
}
- template <typename T>
- static inline TraceWrapperDescriptor TraceWrapperDescriptorFor(
- const T* traceable) {
- return TraceTrait<T>::GetTraceWrapperDescriptor(const_cast<T*>(traceable));
- }
-
private:
template <typename T>
static void HandleWeakCell(Visitor* self, void*);
diff --git a/chromium/third_party/blink/renderer/platform/histogram.cc b/chromium/third_party/blink/renderer/platform/histogram.cc
index 18ddfca5c99..72ed849a524 100644
--- a/chromium/third_party/blink/renderer/platform/histogram.cc
+++ b/chromium/third_party/blink/renderer/platform/histogram.cc
@@ -6,6 +6,7 @@
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
+#include "base/numerics/safe_conversions.h"
namespace blink {
@@ -25,6 +26,11 @@ void CustomCountHistogram::Count(base::HistogramBase::Sample sample) {
histogram_->Add(sample);
}
+void CustomCountHistogram::CountMicroseconds(base::TimeDelta delta) {
+ Count(base::saturated_cast<base::HistogramBase::Sample>(
+ delta.InMicroseconds()));
+}
+
BooleanHistogram::BooleanHistogram(const char* name)
: CustomCountHistogram(base::BooleanHistogram::FactoryGet(
name,
diff --git a/chromium/third_party/blink/renderer/platform/histogram.h b/chromium/third_party/blink/renderer/platform/histogram.h
index fe3c09c920d..b380122df87 100644
--- a/chromium/third_party/blink/renderer/platform/histogram.h
+++ b/chromium/third_party/blink/renderer/platform/histogram.h
@@ -26,6 +26,7 @@ class PLATFORM_EXPORT CustomCountHistogram {
base::HistogramBase::Sample max,
int32_t bucket_count);
void Count(base::HistogramBase::Sample);
+ void CountMicroseconds(base::TimeDelta);
protected:
explicit CustomCountHistogram(base::HistogramBase*);
@@ -69,7 +70,7 @@ class PLATFORM_EXPORT ScopedUsHistogramTimer {
: start_time_(CurrentTimeTicks()), counter_(counter) {}
~ScopedUsHistogramTimer() {
- counter_.Count((CurrentTimeTicks() - start_time_).InMicroseconds());
+ counter_.CountMicroseconds(CurrentTimeTicks() - start_time_);
}
private:
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder.cc b/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder.cc
index 613de9cc507..3f2201736d2 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder.cc
@@ -43,7 +43,10 @@ static const size_t kSizeOfFileHeader = 14;
BMPImageDecoder::BMPImageDecoder(AlphaOption alpha_option,
const ColorBehavior& color_behavior,
size_t max_decoded_bytes)
- : ImageDecoder(alpha_option, color_behavior, max_decoded_bytes),
+ : ImageDecoder(alpha_option,
+ ImageDecoder::kDefaultBitDepth,
+ color_behavior,
+ max_decoded_bytes),
decoded_offset_(0) {}
BMPImageDecoder::~BMPImageDecoder() = default;
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder.cc b/chromium/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder.cc
index d7e37fe2be8..860215b58e7 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder.cc
@@ -35,7 +35,10 @@ namespace blink {
GIFImageDecoder::GIFImageDecoder(AlphaOption alpha_option,
const ColorBehavior& color_behavior,
size_t max_decoded_bytes)
- : ImageDecoder(alpha_option, color_behavior, max_decoded_bytes),
+ : ImageDecoder(alpha_option,
+ ImageDecoder::kDefaultBitDepth,
+ color_behavior,
+ max_decoded_bytes),
repetition_count_(kAnimationLoopOnce) {}
GIFImageDecoder::~GIFImageDecoder() = default;
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder_test.cc b/chromium/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder_test.cc
index 1991f29bb08..289241fba6f 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder_test.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder_test.cc
@@ -146,7 +146,7 @@ TEST(GIFImageDecoderTest, parseByteByByte) {
std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
const Vector<char> data =
- ReadFile(kLayoutTestResourcesDir, "animated.gif")->Copy();
+ ReadFile(kLayoutTestResourcesDir, "animated.gif")->CopyAs<Vector<char>>();
size_t frame_count = 0;
@@ -195,7 +195,7 @@ TEST(GIFImageDecoderTest, allDataReceivedTruncation) {
std::unique_ptr<ImageDecoder> decoder = CreateDecoder();
const Vector<char> data =
- ReadFile(kLayoutTestResourcesDir, "animated.gif")->Copy();
+ ReadFile(kLayoutTestResourcesDir, "animated.gif")->CopyAs<Vector<char>>();
ASSERT_GE(data.size(), 10u);
scoped_refptr<SharedBuffer> temp_data =
@@ -232,7 +232,7 @@ TEST(GIFImageDecoderTest, frameIsCompleteLoading) {
scoped_refptr<SharedBuffer> data_buffer =
ReadFile(kLayoutTestResourcesDir, "animated.gif");
ASSERT_TRUE(data_buffer.get());
- const Vector<char> data = data_buffer->Copy();
+ const Vector<char> data = data_buffer->CopyAs<Vector<char>>();
ASSERT_GE(data.size(), 10u);
scoped_refptr<SharedBuffer> temp_data =
@@ -356,7 +356,7 @@ TEST(GIFImageDecoderTest, firstFrameHasGreaterSizeThanScreenSize) {
const Vector<char> full_data =
ReadFile(kDecodersTestingDir,
"first-frame-has-greater-size-than-screen-size.gif")
- ->Copy();
+ ->CopyAs<Vector<char>>();
std::unique_ptr<ImageDecoder> decoder;
IntSize frame_size;
@@ -388,7 +388,7 @@ TEST(GIFImageDecoderTest, bitmapAlphaType) {
scoped_refptr<SharedBuffer> full_data_buffer =
ReadFile(kDecodersTestingDir, "radient.gif");
ASSERT_TRUE(full_data_buffer.get());
- const Vector<char> full_data = full_data_buffer->Copy();
+ const Vector<char> full_data = full_data_buffer->CopyAs<Vector<char>>();
// Empirically chosen truncation size:
// a) large enough to produce a partial frame &&
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/ico/ico_image_decoder.cc b/chromium/third_party/blink/renderer/platform/image-decoders/ico/ico_image_decoder.cc
index 9a52f370cf2..79c81f135b2 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/ico/ico_image_decoder.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/ico/ico_image_decoder.cc
@@ -44,7 +44,10 @@ static const size_t kSizeOfDirEntry = 16;
ICOImageDecoder::ICOImageDecoder(AlphaOption alpha_option,
const ColorBehavior& color_behavior,
size_t max_decoded_bytes)
- : ImageDecoder(alpha_option, color_behavior, max_decoded_bytes),
+ : ImageDecoder(alpha_option,
+ ImageDecoder::kDefaultBitDepth,
+ color_behavior,
+ max_decoded_bytes),
fast_reader_(nullptr),
decoded_offset_(0),
dir_entries_count_(0),
@@ -213,8 +216,8 @@ bool ICOImageDecoder::DecodeAtIndex(size_t index) {
AlphaOption alpha_option =
premultiply_alpha_ ? kAlphaPremultiplied : kAlphaNotPremultiplied;
png_decoders_[index] = std::make_unique<PNGImageDecoder>(
- alpha_option, color_behavior_, max_decoded_bytes_,
- dir_entry.image_offset_);
+ alpha_option, ImageDecoder::kDefaultBitDepth, color_behavior_,
+ max_decoded_bytes_, dir_entry.image_offset_);
SetDataForPNGDecoderAtIndex(index);
}
auto* png_decoder = png_decoders_[index].get();
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/ico/ico_image_decoder_test.cc b/chromium/third_party/blink/renderer/platform/image-decoders/ico/ico_image_decoder_test.cc
index d17bcef08f3..73b499cc425 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/ico/ico_image_decoder_test.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/ico/ico_image_decoder_test.cc
@@ -21,7 +21,7 @@ std::unique_ptr<ImageDecoder> CreateICODecoder() {
TEST(ICOImageDecoderTests, trunctedIco) {
const Vector<char> data =
- ReadFile("/images/resources/png-in-ico.ico")->Copy();
+ ReadFile("/images/resources/png-in-ico.ico")->CopyAs<Vector<char>>();
ASSERT_FALSE(data.IsEmpty());
scoped_refptr<SharedBuffer> truncated_data =
@@ -39,7 +39,7 @@ TEST(ICOImageDecoderTests, trunctedIco) {
TEST(ICOImageDecoderTests, errorInPngInIco) {
const Vector<char> data =
- ReadFile("/images/resources/png-in-ico.ico")->Copy();
+ ReadFile("/images/resources/png-in-ico.ico")->CopyAs<Vector<char>>();
ASSERT_FALSE(data.IsEmpty());
// Modify the file to have a broken CRC in IHDR.
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder.cc b/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder.cc
index b7730cabc07..0f7452007d2 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder.cc
@@ -69,6 +69,7 @@ std::unique_ptr<ImageDecoder> ImageDecoder::Create(
scoped_refptr<SegmentReader> data,
bool data_complete,
AlphaOption alpha_option,
+ HighBitDepthDecodingOption high_bit_depth_decoding_option,
const ColorBehavior& color_behavior,
const SkISize& desired_size) {
// At least kLongestSignatureLength bytes are needed to sniff the signature.
@@ -97,8 +98,9 @@ std::unique_ptr<ImageDecoder> ImageDecoder::Create(
decoder.reset(
new JPEGImageDecoder(alpha_option, color_behavior, max_decoded_bytes));
} else if (MatchesPNGSignature(contents)) {
- decoder.reset(
- new PNGImageDecoder(alpha_option, color_behavior, max_decoded_bytes));
+ decoder.reset(new PNGImageDecoder(alpha_option,
+ high_bit_depth_decoding_option,
+ color_behavior, max_decoded_bytes));
} else if (MatchesGIFSignature(contents)) {
decoder.reset(
new GIFImageDecoder(alpha_option, color_behavior, max_decoded_bytes));
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder.h b/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder.h
index 8390adbb08c..dff162eb87c 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder.h
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder.h
@@ -117,6 +117,12 @@ class PLATFORM_EXPORT ImageDecoder {
Platform::kNoDecodedImageByteLimit;
enum AlphaOption { kAlphaPremultiplied, kAlphaNotPremultiplied };
+ enum HighBitDepthDecodingOption {
+ // Decode everything to 8-8-8-8 pixel format (kN32 channel order).
+ kDefaultBitDepth,
+ // Decode high bit depth images to half float pixel format.
+ kHighBitDepthToHalfFloat
+ };
virtual ~ImageDecoder() = default;
@@ -128,16 +134,19 @@ class PLATFORM_EXPORT ImageDecoder {
scoped_refptr<SegmentReader> data,
bool data_complete,
AlphaOption,
+ HighBitDepthDecodingOption,
const ColorBehavior&,
const SkISize& desired_size = SkISize::MakeEmpty());
static std::unique_ptr<ImageDecoder> Create(
scoped_refptr<SharedBuffer> data,
bool data_complete,
AlphaOption alpha_option,
+ HighBitDepthDecodingOption high_bit_depth_decoding_option,
const ColorBehavior& color_behavior,
const SkISize& desired_size = SkISize::MakeEmpty()) {
return Create(SegmentReader::CreateFromSharedBuffer(std::move(data)),
- data_complete, alpha_option, color_behavior, desired_size);
+ data_complete, alpha_option, high_bit_depth_decoding_option,
+ color_behavior, desired_size);
}
virtual String FilenameExtension() const = 0;
@@ -316,9 +325,11 @@ class PLATFORM_EXPORT ImageDecoder {
protected:
ImageDecoder(AlphaOption alpha_option,
+ HighBitDepthDecodingOption high_bit_depth_decoding_option,
const ColorBehavior& color_behavior,
size_t max_decoded_bytes)
: premultiply_alpha_(alpha_option == kAlphaPremultiplied),
+ high_bit_depth_decoding_option_(high_bit_depth_decoding_option),
color_behavior_(color_behavior),
max_decoded_bytes_(max_decoded_bytes),
purge_aggressively_(false) {}
@@ -398,6 +409,7 @@ class PLATFORM_EXPORT ImageDecoder {
scoped_refptr<SegmentReader> data_; // The encoded data.
Vector<ImageFrame, 1> frame_buffer_cache_;
const bool premultiply_alpha_;
+ const HighBitDepthDecodingOption high_bit_depth_decoding_option_;
const ColorBehavior color_behavior_;
ImageOrientation orientation_;
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder_test.cc b/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder_test.cc
index 3c7d25bec40..c6fc45b2a42 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder_test.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder_test.cc
@@ -41,6 +41,7 @@ class TestImageDecoder : public ImageDecoder {
public:
TestImageDecoder()
: ImageDecoder(kAlphaNotPremultiplied,
+ ImageDecoder::kDefaultBitDepth,
ColorBehavior::TransformToSRGB(),
kNoDecodedImageByteLimit) {}
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder_test_helpers.cc b/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder_test_helpers.cc
index 25eb1ee6ad5..74ffbd0a8e7 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder_test_helpers.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/image_decoder_test_helpers.cc
@@ -64,7 +64,7 @@ void TestByteByByteDecode(DecoderCreator create_decoder,
SharedBuffer* shared_data,
size_t expected_frame_count,
int expected_repetition_count) {
- const Vector<char> data = shared_data->Copy();
+ const Vector<char> data = shared_data->CopyAs<Vector<char>>();
Vector<unsigned> baseline_hashes;
CreateDecodingBaseline(create_decoder, shared_data, &baseline_hashes);
@@ -124,7 +124,7 @@ void TestByteByByteDecode(DecoderCreator create_decoder,
static void TestMergeBuffer(DecoderCreator create_decoder,
SharedBuffer* shared_data) {
const unsigned hash = CreateDecodingBaseline(create_decoder, shared_data);
- const Vector<char> data = shared_data->Copy();
+ const Vector<char> data = shared_data->CopyAs<Vector<char>>();
// In order to do any verification, this test needs to move the data owned
// by the SharedBuffer. A way to guarantee that is to create a new one, and
@@ -210,7 +210,7 @@ static void TestDecodeAfterReallocatingData(DecoderCreator create_decoder,
size_t frame_count = decoder->FrameCount();
// ... and then decode frames from 'reallocated_data'.
- Vector<char> copy = data->Copy();
+ Vector<char> copy = data->CopyAs<Vector<char>>();
scoped_refptr<SharedBuffer> reallocated_data =
SharedBuffer::AdoptVector(copy);
ASSERT_TRUE(reallocated_data.get());
@@ -235,7 +235,7 @@ static void TestByteByByteSizeAvailable(DecoderCreator create_decoder,
// the data to check that IsSizeAvailable() changes state only when that
// offset is reached. Also check other decoder state.
scoped_refptr<SharedBuffer> temp_data = SharedBuffer::Create();
- const Vector<char> source_buffer = data->Copy();
+ const Vector<char> source_buffer = data->CopyAs<Vector<char>>();
const char* source = source_buffer.data();
for (size_t length = 1; length <= frame_offset; ++length) {
temp_data->Append(source++, 1u);
@@ -263,7 +263,7 @@ static void TestByteByByteSizeAvailable(DecoderCreator create_decoder,
static void TestProgressiveDecoding(DecoderCreator create_decoder,
SharedBuffer* full_buffer,
size_t increment) {
- const Vector<char> full_data = full_buffer->Copy();
+ const Vector<char> full_data = full_buffer->CopyAs<Vector<char>>();
const size_t full_length = full_data.size();
std::unique_ptr<ImageDecoder> decoder;
@@ -308,7 +308,7 @@ static void TestProgressiveDecoding(DecoderCreator create_decoder,
void TestUpdateRequiredPreviousFrameAfterFirstDecode(
DecoderCreator create_decoder,
SharedBuffer* full_buffer) {
- const Vector<char> full_data = full_buffer->Copy();
+ const Vector<char> full_data = full_buffer->CopyAs<Vector<char>>();
std::unique_ptr<ImageDecoder> decoder = create_decoder();
// Give it data that is enough to parse but not decode in order to check the
@@ -342,7 +342,7 @@ void TestUpdateRequiredPreviousFrameAfterFirstDecode(
void TestResumePartialDecodeAfterClearFrameBufferCache(
DecoderCreator create_decoder,
SharedBuffer* full_buffer) {
- const Vector<char> full_data = full_buffer->Copy();
+ const Vector<char> full_data = full_buffer->CopyAs<Vector<char>>();
Vector<unsigned> baseline_hashes;
CreateDecodingBaseline(create_decoder, full_buffer, &baseline_hashes);
size_t frame_count = baseline_hashes.size();
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/image_frame.cc b/chromium/third_party/blink/renderer/platform/image-decoders/image_frame.cc
index e92d01e5ba7..b93d6f17e85 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/image_frame.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/image_frame.cc
@@ -28,12 +28,17 @@
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkColorSpaceXform.h"
+#include "third_party/skia/include/core/SkImage.h"
+#include "third_party/skia/include/core/SkSurface.h"
namespace blink {
ImageFrame::ImageFrame()
: allocator_(nullptr),
has_alpha_(true),
+ pixel_format_(kN32),
status_(kFrameEmpty),
disposal_method_(kDisposeNotSpecified),
alpha_blend_source_(kBlendAtopPreviousFrame),
@@ -59,6 +64,7 @@ ImageFrame& ImageFrame::operator=(const ImageFrame& other) {
// Be sure that this is called after we've called SetStatus(), since we
// look at our status to know what to do with the alpha value.
SetHasAlpha(other.HasAlpha());
+ pixel_format_ = other.pixel_format_;
SetRequiredPreviousFrameIndex(other.RequiredPreviousFrameIndex());
return *this;
}
@@ -107,17 +113,16 @@ bool ImageFrame::AllocatePixelData(int new_width,
// AllocatePixelData() should only be called once.
DCHECK(!Width() && !Height());
- bitmap_.setInfo(SkImageInfo::MakeN32(
+ SkImageInfo info = SkImageInfo::MakeN32(
new_width, new_height,
premultiply_alpha_ ? kPremul_SkAlphaType : kUnpremul_SkAlphaType,
- std::move(color_space)));
+ std::move(color_space));
+ if (pixel_format_ == kRGBA_F16)
+ info = info.makeColorType(kRGBA_F16_SkColorType);
+ bitmap_.setInfo(info);
return bitmap_.tryAllocPixels(allocator_);
}
-bool ImageFrame::HasAlpha() const {
- return has_alpha_;
-}
-
sk_sp<SkImage> ImageFrame::FinalizePixelsAndGetImage() {
DCHECK_EQ(kFrameComplete, status_);
bitmap_.setImmutable();
@@ -152,6 +157,58 @@ void ImageFrame::ZeroFillFrameRect(const IntRect& rect) {
SetHasAlpha(true);
}
+void ImageFrame::SetRGBAPremultiplyF16Buffer(PixelDataF16* dst,
+ PixelDataF16* src,
+ size_t num_pixels) {
+ sk_sp<SkColorSpace> color_space = SkColorSpace::MakeSRGBLinear();
+ auto color_format = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat;
+ SkColorSpaceXform::Apply(color_space.get(), color_format, dst,
+ color_space.get(), color_format, src, num_pixels,
+ SkColorSpaceXform::AlphaOp::kPremul_AlphaOp);
+}
+
+void ImageFrame::SetPixelsOpaqueF16Buffer(PixelDataF16* dst,
+ PixelDataF16* src,
+ size_t num_pixels) {
+ // We set the alpha half float to 0x3c00, which is equal to 1.
+ while (num_pixels-- > 0)
+ *dst++ = (*src++ & 0x0000ffffffffffff) | 0x3c00000000000000;
+}
+
+static void BlendRGBAF16Buffer(ImageFrame::PixelDataF16* dst,
+ ImageFrame::PixelDataF16* src,
+ size_t num_pixels,
+ SkAlphaType dst_alpha_type) {
+ // Source is always unpremul, but the blending result might be premul or
+ // unpremul, depending on the alpha type of the destination pixel passed to
+ // this function.
+ SkImageInfo info =
+ SkImageInfo::Make(num_pixels, 1, kRGBA_F16_SkColorType, dst_alpha_type,
+ SkColorSpace::MakeSRGBLinear());
+ sk_sp<SkSurface> surface =
+ SkSurface::MakeRasterDirect(info, dst, info.minRowBytes());
+
+ SkPixmap src_pixmap(info.makeAlphaType(kUnpremul_SkAlphaType), src,
+ info.minRowBytes());
+ sk_sp<SkImage> src_image =
+ SkImage::MakeFromRaster(src_pixmap, nullptr, nullptr);
+
+ surface->getCanvas()->drawImage(src_image, 0, 0);
+ surface->flush();
+}
+
+void ImageFrame::BlendRGBARawF16Buffer(PixelDataF16* dst,
+ PixelDataF16* src,
+ size_t num_pixels) {
+ BlendRGBAF16Buffer(dst, src, num_pixels, kUnpremul_SkAlphaType);
+}
+
+void ImageFrame::BlendRGBAPremultipliedF16Buffer(PixelDataF16* dst,
+ PixelDataF16* src,
+ size_t num_pixels) {
+ BlendRGBAF16Buffer(dst, src, num_pixels, kPremul_SkAlphaType);
+}
+
static uint8_t BlendChannel(uint8_t src,
uint8_t src_a,
uint8_t dst,
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/image_frame.h b/chromium/third_party/blink/renderer/platform/image-decoders/image_frame.h
index f67a5309479..0aec08ec956 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/image_frame.h
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/image_frame.h
@@ -46,6 +46,7 @@ class PLATFORM_EXPORT ImageFrame final {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
public:
+ enum PixelFormat { kN32, kRGBA_F16 };
enum Status { kFrameEmpty, kFramePartial, kFrameComplete };
enum DisposalMethod {
// If you change the numeric values of these, make sure you audit
@@ -74,11 +75,16 @@ class PLATFORM_EXPORT ImageFrame final {
kBlendAtopBgcolor,
};
typedef uint32_t PixelData;
+ typedef uint64_t PixelDataF16;
typedef WebVector<char> ICCProfile;
ImageFrame();
+ ImageFrame(PixelFormat pixel_format) : ImageFrame() {
+ pixel_format_ = pixel_format;
+ }
+
// The assignment operator reads has_alpha_ (inside SetStatus()) before it
// sets it (in SetHasAlpha()). This doesn't cause any problems, since the
// SetHasAlpha() call ensures all state is set correctly, but it means we
@@ -109,6 +115,7 @@ class PLATFORM_EXPORT ImageFrame final {
// same X-coordinates on each subsequent row up to but not including
// end_y.
void CopyRowNTimes(int start_x, int end_x, int start_y, int end_y) {
+ DCHECK(pixel_format_ == kN32);
DCHECK_LT(start_x, Width());
DCHECK_LE(end_x, Width());
DCHECK_LT(start_y, Height());
@@ -125,7 +132,8 @@ class PLATFORM_EXPORT ImageFrame final {
// allocation succeeded.
bool AllocatePixelData(int new_width, int new_height, sk_sp<SkColorSpace>);
- bool HasAlpha() const;
+ bool HasAlpha() const { return has_alpha_; }
+ PixelFormat GetPixelFormat() const { return pixel_format_; }
const IntRect& OriginalFrameRect() const { return original_frame_rect_; }
Status GetStatus() const { return status_; }
TimeDelta Duration() const { return duration_; }
@@ -174,7 +182,18 @@ class PLATFORM_EXPORT ImageFrame final {
required_previous_frame_index_ = previous_frame_index;
}
- inline PixelData* GetAddr(int x, int y) { return bitmap_.getAddr32(x, y); }
+ inline PixelData* GetAddr(int x, int y) {
+ DCHECK(pixel_format_ == kN32);
+ return bitmap_.getAddr32(x, y);
+ }
+
+ inline PixelDataF16* GetAddrF16(int x, int y) {
+ DCHECK(pixel_format_ == kRGBA_F16);
+ SkPixmap pixmap;
+ if (!bitmap_.peekPixels(&pixmap))
+ NOTREACHED();
+ return pixmap.writable_addr64(x, y);
+ }
inline void SetRGBA(int x,
int y,
@@ -182,6 +201,7 @@ class PLATFORM_EXPORT ImageFrame final {
unsigned g,
unsigned b,
unsigned a) {
+ DCHECK(pixel_format_ == kN32);
SetRGBA(GetAddr(x, y), r, g, b, a);
}
@@ -190,6 +210,7 @@ class PLATFORM_EXPORT ImageFrame final {
unsigned g,
unsigned b,
unsigned a) {
+ DCHECK(pixel_format_ == kN32);
if (premultiply_alpha_)
SetRGBAPremultiply(dest, r, g, b, a);
else
@@ -213,6 +234,10 @@ class PLATFORM_EXPORT ImageFrame final {
*dest = SkPackARGB32NoCheck(a, r, g, b);
}
+ static void SetRGBAPremultiplyF16Buffer(PixelDataF16* dst,
+ PixelDataF16* src,
+ size_t num_pixels);
+
static inline void SetRGBARaw(PixelData* dest,
unsigned r,
unsigned g,
@@ -221,6 +246,10 @@ class PLATFORM_EXPORT ImageFrame final {
*dest = SkPackARGB32NoCheck(a, r, g, b);
}
+ static void SetPixelsOpaqueF16Buffer(PixelDataF16* dst,
+ PixelDataF16* src,
+ size_t num_pixels);
+
// Blend the RGBA pixel provided by |red|, |green|, |blue| and |alpha| over
// the pixel in |dest|, without premultiplication, and overwrite |dest| with
// the result.
@@ -230,6 +259,10 @@ class PLATFORM_EXPORT ImageFrame final {
unsigned blue,
unsigned alpha);
+ static void BlendRGBARawF16Buffer(PixelDataF16* dst,
+ PixelDataF16* src,
+ size_t num_pixels);
+
// Blend the pixel, without premultiplication, in |src| over |dst| and
// overwrite |src| with the result.
static void BlendSrcOverDstRaw(PixelData* src, PixelData dst);
@@ -247,7 +280,8 @@ class PLATFORM_EXPORT ImageFrame final {
if (a == 0x0)
return;
- // If the new pixel is opaque, no need for blending - just write the pixel.
+ // If the new pixel is opaque, no need for blending - just write the
+ // pixel.
if (a == 0xFF) {
SetRGBAPremultiply(dest, r, g, b, a);
return;
@@ -258,6 +292,10 @@ class PLATFORM_EXPORT ImageFrame final {
*dest = SkPMSrcOver(src, *dest);
}
+ static void BlendRGBAPremultipliedF16Buffer(PixelDataF16* dst,
+ PixelDataF16* src,
+ size_t num_pixels);
+
// Blend the pixel in |src| over |dst| and overwrite |src| with the result.
static inline void BlendSrcOverDstPremultiplied(PixelData* src,
PixelData dst) {
@@ -281,6 +319,7 @@ class PLATFORM_EXPORT ImageFrame final {
SkBitmap bitmap_;
SkBitmap::Allocator* allocator_;
bool has_alpha_;
+ PixelFormat pixel_format_;
// This will always just be the entire buffer except for GIF or WebP
// frames whose original rect was smaller than the overall image size.
IntRect original_frame_rect_;
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/image_frame_test.cc b/chromium/third_party/blink/renderer/platform/image-decoders/image_frame_test.cc
new file mode 100644
index 00000000000..07a506ac694
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/image_frame_test.cc
@@ -0,0 +1,183 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/image-decoders/image_frame.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkColorSpaceXform.h"
+
+namespace blink {
+namespace {
+
+// Needed for ImageFrame::SetMemoryAllocator, but still does the default
+// allocation.
+class TestAllocator final : public SkBitmap::Allocator {
+ bool allocPixelRef(SkBitmap* dst) override { return dst->tryAllocPixels(); }
+};
+
+class ImageFrameTest : public testing::Test {
+ public:
+ void SetUp() override {
+ src_8888_a = 0x80;
+ src_8888_r = 0x40;
+ src_8888_g = 0x50;
+ src_8888_b = 0x60;
+ src_8888 = SkPackARGB32(src_8888_a, src_8888_r, src_8888_g, src_8888_b);
+ dst_8888 = SkPackARGB32(0xA0, 0x60, 0x70, 0x80);
+
+ typedef SkColorSpaceXform::ColorFormat ColorFormat;
+ color_format_8888 = ColorFormat::kBGRA_8888_ColorFormat;
+ if (kN32_SkColorType == kRGBA_8888_SkColorType)
+ color_format_8888 = ColorFormat::kRGBA_8888_ColorFormat;
+ color_format_f16 = ColorFormat::kRGBA_F16_ColorFormat;
+ color_format_f32 = ColorFormat::kRGBA_F32_ColorFormat;
+
+ sk_sp<SkColorSpace> srgb_linear = SkColorSpace::MakeSRGBLinear();
+ SkColorSpaceXform::Apply(srgb_linear.get(), color_format_f16, &src_f16,
+ srgb_linear.get(), color_format_8888, &src_8888, 1,
+ SkColorSpaceXform::AlphaOp::kPreserve_AlphaOp);
+ SkColorSpaceXform::Apply(srgb_linear.get(), color_format_f16, &dst_f16,
+ srgb_linear.get(), color_format_8888, &dst_8888, 1,
+ SkColorSpaceXform::AlphaOp::kPreserve_AlphaOp);
+ }
+
+ protected:
+ const float color_compoenent_tolerance = 0.01;
+ unsigned src_8888_a, src_8888_r, src_8888_g, src_8888_b;
+ ImageFrame::PixelData src_8888, dst_8888;
+ ImageFrame::PixelDataF16 src_f16, dst_f16;
+ SkColorSpaceXform::ColorFormat color_format_8888, color_format_f16,
+ color_format_f32;
+
+ void ConvertN32ToF32(float* dst, ImageFrame::PixelData src) {
+ sk_sp<SkColorSpace> srgb_linear = SkColorSpace::MakeSRGBLinear();
+ SkColorSpaceXform::Apply(srgb_linear.get(), color_format_f32, dst,
+ srgb_linear.get(), color_format_8888, &src, 1,
+ SkColorSpaceXform::AlphaOp::kPreserve_AlphaOp);
+ }
+
+ void ConvertF16ToF32(float* dst, ImageFrame::PixelDataF16 src) {
+ sk_sp<SkColorSpace> srgb_linear = SkColorSpace::MakeSRGBLinear();
+ SkColorSpaceXform::Apply(srgb_linear.get(), color_format_f32, dst,
+ srgb_linear.get(), color_format_f16, &src, 1,
+ SkColorSpaceXform::AlphaOp::kPreserve_AlphaOp);
+ }
+};
+
+TEST_F(ImageFrameTest, TestF16API) {
+ ImageFrame::PixelFormat kN32 = ImageFrame::PixelFormat::kN32;
+ ImageFrame::PixelFormat kRGBA_F16 = ImageFrame::PixelFormat::kRGBA_F16;
+
+ ImageFrame frame_no_pixel_format;
+ ASSERT_EQ(kN32, frame_no_pixel_format.GetPixelFormat());
+
+ ImageFrame frame_pixel_format_n32(kN32);
+ ASSERT_EQ(kN32, frame_pixel_format_n32.GetPixelFormat());
+
+ ImageFrame frame_pixel_format_f16(kRGBA_F16);
+ ASSERT_EQ(kRGBA_F16, frame_pixel_format_f16.GetPixelFormat());
+
+ ImageFrame frame_copy_ctor_n32(frame_pixel_format_n32);
+ ASSERT_EQ(kN32, frame_copy_ctor_n32.GetPixelFormat());
+
+ ImageFrame frame_copy_ctor_f16(frame_pixel_format_f16);
+ ASSERT_EQ(kRGBA_F16, frame_copy_ctor_f16.GetPixelFormat());
+
+ ImageFrame frame_test_assignment;
+ frame_test_assignment = frame_pixel_format_n32;
+ ASSERT_EQ(kN32, frame_test_assignment.GetPixelFormat());
+ frame_test_assignment = frame_pixel_format_f16;
+ ASSERT_EQ(kRGBA_F16, frame_test_assignment.GetPixelFormat());
+
+ SkBitmap bitmap(frame_pixel_format_f16.Bitmap());
+ ASSERT_EQ(0, bitmap.width());
+ ASSERT_EQ(0, bitmap.height());
+ ASSERT_EQ(nullptr, bitmap.colorSpace());
+
+ TestAllocator allocator;
+ frame_pixel_format_f16.SetMemoryAllocator(&allocator);
+ sk_sp<SkColorSpace> srgb_linear = SkColorSpace::MakeSRGBLinear();
+
+ ASSERT_TRUE(frame_pixel_format_f16.AllocatePixelData(2, 2, srgb_linear));
+ bitmap = frame_pixel_format_f16.Bitmap();
+ ASSERT_EQ(2, bitmap.width());
+ ASSERT_EQ(2, bitmap.height());
+ ASSERT_TRUE(SkColorSpace::Equals(srgb_linear.get(), bitmap.colorSpace()));
+}
+
+TEST_F(ImageFrameTest, SetRGBAPremultiplyF16Buffer) {
+ ImageFrame::PixelDataF16 premul_f16;
+ ImageFrame::SetRGBAPremultiplyF16Buffer(&premul_f16, &src_f16, 1);
+
+ float f32_from_src_f16[4];
+ ConvertF16ToF32(f32_from_src_f16, src_f16);
+ for (int i = 0; i < 3; i++)
+ f32_from_src_f16[i] *= f32_from_src_f16[3];
+
+ float f32_from_premul_f16[4];
+ ConvertF16ToF32(f32_from_premul_f16, premul_f16);
+
+ for (int i = 0; i < 4; i++) {
+ ASSERT_TRUE(fabs(f32_from_src_f16[i] - f32_from_premul_f16[i]) <
+ color_compoenent_tolerance);
+ }
+}
+
+TEST_F(ImageFrameTest, SetPixelsOpaqueF16Buffer) {
+ ImageFrame::PixelDataF16 opaque_f16;
+ ImageFrame::SetPixelsOpaqueF16Buffer(&opaque_f16, &src_f16, 1);
+
+ float f32_from_src_f16[4];
+ ConvertF16ToF32(f32_from_src_f16, src_f16);
+
+ float f32_from_opaque_f16[4];
+ ConvertF16ToF32(f32_from_opaque_f16, opaque_f16);
+
+ for (int i = 0; i < 3; i++)
+ ASSERT_EQ(f32_from_src_f16[i], f32_from_opaque_f16[i]);
+ ASSERT_EQ(1.0f, f32_from_opaque_f16[3]);
+}
+
+TEST_F(ImageFrameTest, BlendRGBARawF16Buffer) {
+ ImageFrame::PixelData blended_8888(dst_8888);
+ ImageFrame::BlendRGBARaw(&blended_8888, src_8888_r, src_8888_g, src_8888_b,
+ src_8888_a);
+
+ ImageFrame::PixelDataF16 blended_f16 = dst_f16;
+ ImageFrame::BlendRGBARawF16Buffer(&blended_f16, &src_f16, 1);
+
+ float f32_from_blended_8888[4];
+ ConvertN32ToF32(f32_from_blended_8888, blended_8888);
+
+ float f32_from_blended_f16[4];
+ ConvertF16ToF32(f32_from_blended_f16, blended_f16);
+
+ for (int i = 0; i < 4; i++) {
+ ASSERT_TRUE(fabs(f32_from_blended_8888[i] - f32_from_blended_f16[i]) <
+ color_compoenent_tolerance);
+ }
+}
+
+TEST_F(ImageFrameTest, BlendRGBAPremultipliedF16Buffer) {
+ ImageFrame::PixelData blended_8888(dst_8888);
+ ImageFrame::BlendRGBAPremultiplied(&blended_8888, src_8888_r, src_8888_g,
+ src_8888_b, src_8888_a);
+
+ ImageFrame::PixelDataF16 blended_f16 = dst_f16;
+ ImageFrame::BlendRGBAPremultipliedF16Buffer(&blended_f16, &src_f16, 1);
+
+ float f32_from_blended_8888[4];
+ ConvertN32ToF32(f32_from_blended_8888, blended_8888);
+
+ float f32_from_blended_f16[4];
+ ConvertF16ToF32(f32_from_blended_f16, blended_f16);
+
+ for (int i = 0; i < 4; i++) {
+ ASSERT_TRUE(fabs(f32_from_blended_8888[i] - f32_from_blended_f16[i]) <
+ color_compoenent_tolerance);
+ }
+}
+
+} // namespace
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc b/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
index e3e3173bec4..a1e440f6eed 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
@@ -752,7 +752,10 @@ void term_source(j_decompress_ptr jd) {
JPEGImageDecoder::JPEGImageDecoder(AlphaOption alpha_option,
const ColorBehavior& color_behavior,
size_t max_decoded_bytes)
- : ImageDecoder(alpha_option, color_behavior, max_decoded_bytes) {}
+ : ImageDecoder(alpha_option,
+ ImageDecoder::kDefaultBitDepth,
+ color_behavior,
+ max_decoded_bytes) {}
JPEGImageDecoder::~JPEGImageDecoder() = default;
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.cc b/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.cc
index e6f8d772540..67e0bba5e71 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.cc
@@ -46,11 +46,16 @@
namespace blink {
-PNGImageDecoder::PNGImageDecoder(AlphaOption alpha_option,
- const ColorBehavior& color_behavior,
- size_t max_decoded_bytes,
- size_t offset)
- : ImageDecoder(alpha_option, color_behavior, max_decoded_bytes),
+PNGImageDecoder::PNGImageDecoder(
+ AlphaOption alpha_option,
+ HighBitDepthDecodingOption high_bit_depth_decoding_option,
+ const ColorBehavior& color_behavior,
+ size_t max_decoded_bytes,
+ size_t offset)
+ : ImageDecoder(alpha_option,
+ high_bit_depth_decoding_option,
+ color_behavior,
+ max_decoded_bytes),
offset_(offset),
current_frame_(0),
// It would be logical to default to kAnimationNone, but BitmapImage uses
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.h b/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.h
index 26403d3585f..a82f8a0028f 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.h
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.h
@@ -38,6 +38,7 @@ class PLATFORM_EXPORT PNGImageDecoder final : public ImageDecoder {
public:
PNGImageDecoder(AlphaOption,
+ HighBitDepthDecodingOption,
const ColorBehavior&,
size_t max_decoded_bytes,
size_t offset = 0);
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder_test.cc b/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder_test.cc
index aa0310bad62..c24afa1ab12 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder_test.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/png/png_image_decoder_test.cc
@@ -35,8 +35,8 @@ namespace {
std::unique_ptr<ImageDecoder> CreatePNGDecoder(
ImageDecoder::AlphaOption alpha_option) {
return std::make_unique<PNGImageDecoder>(
- alpha_option, ColorBehavior::TransformToSRGB(),
- ImageDecoder::kNoDecodedImageByteLimit);
+ alpha_option, ImageDecoder::kDefaultBitDepth,
+ ColorBehavior::TransformToSRGB(), ImageDecoder::kNoDecodedImageByteLimit);
}
std::unique_ptr<ImageDecoder> CreatePNGDecoder() {
@@ -914,8 +914,9 @@ TEST(AnimatedPNGTests, Offset) {
// Use the same defaults as CreatePNGDecoder, except use the (arbitrary)
// non-zero offset.
auto decoder = std::make_unique<PNGImageDecoder>(
- ImageDecoder::kAlphaNotPremultiplied, ColorBehavior::TransformToSRGB(),
- ImageDecoder::kNoDecodedImageByteLimit, kOffset);
+ ImageDecoder::kAlphaNotPremultiplied, ImageDecoder::kDefaultBitDepth,
+ ColorBehavior::TransformToSRGB(), ImageDecoder::kNoDecodedImageByteLimit,
+ kOffset);
decoder->SetData(data, true);
ASSERT_EQ(kExpectedFrameCount, decoder->FrameCount());
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/segment_reader.cc b/chromium/third_party/blink/renderer/platform/image-decoders/segment_reader.cc
index 7ce0ba3acba..7f95a2734f4 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/segment_reader.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/segment_reader.cc
@@ -40,7 +40,12 @@ size_t SharedBufferSegmentReader::size() const {
size_t SharedBufferSegmentReader::GetSomeData(const char*& data,
size_t position) const {
- return shared_buffer_->GetSomeData(data, position);
+ data = nullptr;
+ auto it = shared_buffer_->GetIteratorAt(position);
+ if (it == shared_buffer_->cend())
+ return 0;
+ data = it->data();
+ return it->size();
}
sk_sp<SkData> SharedBufferSegmentReader::GetAsSkData() const {
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.cc b/chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.cc
index e5da242e0ba..24d59cb1161 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.cc
@@ -122,7 +122,10 @@ namespace blink {
WEBPImageDecoder::WEBPImageDecoder(AlphaOption alpha_option,
const ColorBehavior& color_behavior,
size_t max_decoded_bytes)
- : ImageDecoder(alpha_option, color_behavior, max_decoded_bytes),
+ : ImageDecoder(alpha_option,
+ ImageDecoder::kDefaultBitDepth,
+ color_behavior,
+ max_decoded_bytes),
decoder_(nullptr),
format_flags_(0),
frame_background_has_alpha_(false),
diff --git a/chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder_test.cc b/chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder_test.cc
index 83bac77afde..3b7b8dc7b51 100644
--- a/chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder_test.cc
+++ b/chromium/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder_test.cc
@@ -279,7 +279,8 @@ TEST(AnimatedWebPTests, truncatedInBetweenFrame) {
std::unique_ptr<ImageDecoder> decoder = CreateWEBPDecoder();
const Vector<char> full_data =
- ReadFile("/images/resources/invalid-animated-webp4.webp")->Copy();
+ ReadFile("/images/resources/invalid-animated-webp4.webp")
+ ->CopyAs<Vector<char>>();
scoped_refptr<SharedBuffer> data =
SharedBuffer::Create(full_data.data(), full_data.size() - 1);
decoder->SetData(data.get(), false);
@@ -301,7 +302,7 @@ TEST(AnimatedWebPTests, reproCrash) {
scoped_refptr<SharedBuffer> full_data_buffer =
ReadFile("/images/resources/invalid_vp8_vp8x.webp");
ASSERT_TRUE(full_data_buffer.get());
- const Vector<char> full_data = full_data_buffer->Copy();
+ const Vector<char> full_data = full_data_buffer->CopyAs<Vector<char>>();
// Parse partial data up to which error in bitstream is not detected.
const size_t kPartialSize = 32768;
@@ -336,7 +337,7 @@ TEST(AnimatedWebPTests, frameIsCompleteAndDuration) {
scoped_refptr<SharedBuffer> data_buffer =
ReadFile("/images/resources/webp-animated.webp");
ASSERT_TRUE(data_buffer.get());
- const Vector<char> data = data_buffer->Copy();
+ const Vector<char> data = data_buffer->CopyAs<Vector<char>>();
ASSERT_GE(data.size(), 10u);
scoped_refptr<SharedBuffer> temp_data =
diff --git a/chromium/third_party/blink/renderer/platform/image-encoders/image_encoder.cc b/chromium/third_party/blink/renderer/platform/image-encoders/image_encoder.cc
index 0c7f14c7c0e..b564b1ccb7e 100644
--- a/chromium/third_party/blink/renderer/platform/image-encoders/image_encoder.cc
+++ b/chromium/third_party/blink/renderer/platform/image-encoders/image_encoder.cc
@@ -4,6 +4,17 @@
#include "third_party/blink/renderer/platform/image-encoders/image_encoder.h"
+#include "build/build_config.h"
+
+#if defined(OS_WIN)
+#include <basetsd.h> // Included before jpeglib.h because of INT32 clash
+#endif // OS_WIN
+#include <stdio.h> // Needed by jpeglib.h
+
+#include "jpeglib.h" // for JPEG_MAX_DIMENSION
+
+#include "third_party/libwebp/src/webp/encode.h" // for WEBP_MAX_DIMENSION
+
namespace blink {
bool ImageEncoder::Encode(Vector<unsigned char>* dst,
@@ -76,11 +87,8 @@ int ImageEncoder::ComputeJpegQuality(double quality) {
return compression_quality;
}
-SkWebpEncoder::Options ImageEncoder::ComputeWebpOptions(
- double quality,
- SkTransferFunctionBehavior unpremulBehavior) {
+SkWebpEncoder::Options ImageEncoder::ComputeWebpOptions(double quality) {
SkWebpEncoder::Options options;
- options.fUnpremulBehavior = unpremulBehavior;
if (quality == 1.0) {
// Choose a lossless encode. When performing a lossless encode, higher
diff --git a/chromium/third_party/blink/renderer/platform/image-encoders/image_encoder.h b/chromium/third_party/blink/renderer/platform/image-encoders/image_encoder.h
index 0d1460f3482..3822c4a8d22 100644
--- a/chromium/third_party/blink/renderer/platform/image-encoders/image_encoder.h
+++ b/chromium/third_party/blink/renderer/platform/image-encoders/image_encoder.h
@@ -7,8 +7,6 @@
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
-#include "third_party/libjpeg/jpeglib.h" // for JPEG_MAX_DIMENSION
-#include "third_party/libwebp/src/webp/encode.h" // for WEBP_MAX_DIMENSION
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/encode/SkJpegEncoder.h"
#include "third_party/skia/include/encode/SkPngEncoder.h"
@@ -87,9 +85,7 @@ class PLATFORM_EXPORT ImageEncoder {
* is out of range, this will perform a lossy encode with the default
* value (80).
*/
- static SkWebpEncoder::Options ComputeWebpOptions(
- double quality,
- SkTransferFunctionBehavior unpremulBehavior);
+ static SkWebpEncoder::Options ComputeWebpOptions(double quality);
private:
ImageEncoder(Vector<unsigned char>* dst) : dst_(dst) {}
diff --git a/chromium/third_party/blink/renderer/platform/instance_counters.h b/chromium/third_party/blink/renderer/platform/instance_counters.h
index 137a40bd10a..b8384c5a304 100644
--- a/chromium/third_party/blink/renderer/platform/instance_counters.h
+++ b/chromium/third_party/blink/renderer/platform/instance_counters.h
@@ -34,6 +34,7 @@
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/atomics.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.cc b/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.cc
index b3f6767abfa..9a7de51a816 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.cc
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.cc
@@ -62,4 +62,10 @@ void RendererResourceCoordinator::SetMainThreadTaskLoadIsLow(
service_->SetMainThreadTaskLoadIsLow(main_thread_task_load_is_low);
}
+void RendererResourceCoordinator::OnRendererIsBloated() {
+ if (!service_)
+ return;
+ service_->OnRendererIsBloated();
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h b/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h
index 049c20663eb..4c0e9c114a1 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h
@@ -30,6 +30,7 @@ class PLATFORM_EXPORT RendererResourceCoordinator
void SetExpectedTaskQueueingDuration(base::TimeDelta);
void SetMainThreadTaskLoadIsLow(bool);
+ void OnRendererIsBloated();
protected:
RendererResourceCoordinator();
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.cc b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.cc
index 33d96ca67a7..21c82cd046f 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.cc
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.cc
@@ -10,7 +10,6 @@
#include "base/memory/discardable_memory.h"
#include "base/memory/ptr_util.h"
#include "base/strings/stringprintf.h"
-#include "base/trace_event/heap_profiler_heap_dump_writer.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event_argument.h"
#include "base/trace_event/trace_event_memory_overhead.h"
@@ -22,7 +21,6 @@ namespace blink {
WebProcessMemoryDump::WebProcessMemoryDump()
: owned_process_memory_dump_(new base::trace_event::ProcessMemoryDump(
- nullptr,
{base::trace_event::MemoryDumpLevelOfDetail::DETAILED})),
process_memory_dump_(owned_process_memory_dump_.get()),
level_of_detail_(base::trace_event::MemoryDumpLevelOfDetail::DETAILED) {}
diff --git a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump_test.cc b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump_test.cc
index ac618b1cf1a..b1d03c00f05 100644
--- a/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump_test.cc
+++ b/chromium/third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump_test.cc
@@ -61,8 +61,6 @@ TEST(WebProcessMemoryDumpTest, IntegrationTest) {
// Check that calling serialization routines doesn't cause a crash.
wpmd2->process_memory_dump()->SerializeAllocatorDumpsInto(traced_value.get());
- wpmd2->process_memory_dump()->SerializeHeapProfilerDumpsInto(
- traced_value.get());
// Free the |wpmd2| to check that the memory ownership of the two MAD(s)
// has been transferred to |wpmd1|.
@@ -85,8 +83,6 @@ TEST(WebProcessMemoryDumpTest, IntegrationTest) {
// Check that calling serialization routines doesn't cause a crash.
traced_value.reset(new base::trace_event::TracedValue);
wpmd1->process_memory_dump()->SerializeAllocatorDumpsInto(traced_value.get());
- wpmd1->process_memory_dump()->SerializeHeapProfilerDumpsInto(
- traced_value.get());
// Check that clear() actually works.
wpmd1->Clear();
@@ -97,8 +93,6 @@ TEST(WebProcessMemoryDumpTest, IntegrationTest) {
// Check that calling serialization routines doesn't cause a crash.
traced_value.reset(new base::trace_event::TracedValue);
wpmd1->process_memory_dump()->SerializeAllocatorDumpsInto(traced_value.get());
- wpmd1->process_memory_dump()->SerializeHeapProfilerDumpsInto(
- traced_value.get());
// Check if a WebMemoryAllocatorDump created with guid, has correct guid.
blink::WebMemoryAllocatorDumpGuid guid =
diff --git a/chromium/third_party/blink/renderer/platform/json/DEPS b/chromium/third_party/blink/renderer/platform/json/DEPS
index ab2653f09b5..0479b9d3798 100644
--- a/chromium/third_party/blink/renderer/platform/json/DEPS
+++ b/chromium/third_party/blink/renderer/platform/json/DEPS
@@ -6,7 +6,6 @@ include_rules = [
"+third_party/blink/renderer/platform/json",
# Dependencies.
- "+third_party/blink/renderer/platform/decimal.h",
"+third_party/blink/renderer/platform/platform_export.h",
"+third_party/blink/renderer/platform/testing",
"+third_party/blink/renderer/platform/wtf",
diff --git a/chromium/third_party/blink/renderer/platform/json/json_parser.cc b/chromium/third_party/blink/renderer/platform/json/json_parser.cc
index a90acd2e0d8..71be020f3ed 100644
--- a/chromium/third_party/blink/renderer/platform/json/json_parser.cc
+++ b/chromium/third_party/blink/renderer/platform/json/json_parser.cc
@@ -4,8 +4,9 @@
#include "third_party/blink/renderer/platform/json/json_parser.h"
-#include "third_party/blink/renderer/platform/decimal.h"
+#include "base/numerics/safe_conversions.h"
#include "third_party/blink/renderer/platform/json/json_values.h"
+#include "third_party/blink/renderer/platform/wtf/decimal.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/string_to_number.h"
@@ -15,6 +16,52 @@ namespace {
const int kMaxStackLimit = 1000;
+using Error = JSONParseErrorType;
+
+String FormatErrorMessage(Error error, int line, int column) {
+ String text;
+ switch (error) {
+ case Error::kNoError:
+ NOTREACHED();
+ return "";
+ case Error::kUnexpectedToken:
+ text = "Unexpected token.";
+ break;
+ case Error::kSyntaxError:
+ text = "Syntax error.";
+ break;
+ case Error::kInvalidEscape:
+ text = "Invalid escape sequence.";
+ break;
+ case Error::kTooMuchNesting:
+ text = "Too much nesting.";
+ break;
+ case Error::kUnexpectedDataAfterRoot:
+ text = "Unexpected data after root element.";
+ break;
+ case Error::kUnsupportedEncoding:
+ text =
+ "Unsupported encoding. JSON and all string literals must contain "
+ "valid Unicode characters.";
+ break;
+ }
+ return "Line: " + String::Number(line) +
+ ", column: " + String::Number(column) + ", " + text;
+}
+
+// Note: all parsing functions take a |cursor| parameter which is
+// where they start parsing from.
+// If the parsing succeeds, |cursor| will point to the position
+// right after the parsed value, "consuming" some portion of the input.
+// If the parsing fails, |cursor| will point to the error position.
+
+template <typename CharType>
+struct Cursor {
+ int line;
+ const CharType* line_start;
+ const CharType* pos;
+};
+
enum Token {
kObjectBegin,
kObjectEnd,
@@ -27,131 +74,134 @@ enum Token {
kNullToken,
kListSeparator,
kObjectPairSeparator,
- kInvalidToken,
};
template <typename CharType>
-bool ParseConstToken(const CharType* start,
- const CharType* end,
- const CharType** token_end,
- const char* token) {
- while (start < end && *token != '\0' && *start++ == *token++) {
+Error ParseConstToken(Cursor<CharType>* cursor,
+ const CharType* end,
+ const char* token) {
+ const CharType* token_start = cursor->pos;
+ while (cursor->pos < end && *token != '\0' && *(cursor->pos++) == *token++) {
+ }
+ if (*token != '\0') {
+ cursor->pos = token_start;
+ return Error::kSyntaxError;
}
- if (*token != '\0')
- return false;
- *token_end = start;
- return true;
+ return Error::kNoError;
}
template <typename CharType>
-bool ReadInt(const CharType* start,
- const CharType* end,
- const CharType** token_end,
- bool can_have_leading_zeros) {
- if (start == end)
- return false;
- bool have_leading_zero = '0' == *start;
+Error ReadInt(Cursor<CharType>* cursor,
+ const CharType* end,
+ bool can_have_leading_zeros) {
+ if (cursor->pos == end)
+ return Error::kSyntaxError;
+ const CharType* start_ptr = cursor->pos;
+ bool have_leading_zero = '0' == *(cursor->pos);
int length = 0;
- while (start < end && '0' <= *start && *start <= '9') {
- ++start;
+ while (cursor->pos < end && '0' <= *(cursor->pos) && *(cursor->pos) <= '9') {
+ ++(cursor->pos);
++length;
}
if (!length)
- return false;
- if (!can_have_leading_zeros && length > 1 && have_leading_zero)
- return false;
- *token_end = start;
- return true;
+ return Error::kSyntaxError;
+ if (!can_have_leading_zeros && length > 1 && have_leading_zero) {
+ cursor->pos = start_ptr + 1;
+ return Error::kSyntaxError;
+ }
+ return Error::kNoError;
}
template <typename CharType>
-bool ParseNumberToken(const CharType* start,
- const CharType* end,
- const CharType** token_end) {
+Error ParseNumberToken(Cursor<CharType>* cursor, const CharType* end) {
// We just grab the number here. We validate the size in DecodeNumber.
// According to RFC4627, a valid number is: [minus] int [frac] [exp]
- if (start == end)
- return false;
- CharType c = *start;
- if ('-' == c)
- ++start;
-
- if (!ReadInt(start, end, &start, false))
- return false;
- if (start == end) {
- *token_end = start;
- return true;
- }
+ if (cursor->pos == end)
+ return Error::kSyntaxError;
+ if (*(cursor->pos) == '-')
+ ++(cursor->pos);
+
+ Error error = ReadInt(cursor, end, false);
+ if (error != Error::kNoError)
+ return error;
+
+ if (cursor->pos == end)
+ return Error::kNoError;
// Optional fraction part
- c = *start;
+ CharType c = *(cursor->pos);
if ('.' == c) {
- ++start;
- if (!ReadInt(start, end, &start, true))
- return false;
- if (start == end) {
- *token_end = start;
- return true;
- }
- c = *start;
+ ++(cursor->pos);
+ error = ReadInt(cursor, end, true);
+ if (error != Error::kNoError)
+ return error;
+ if (cursor->pos == end)
+ return Error::kNoError;
+ c = *(cursor->pos);
}
// Optional exponent part
if ('e' == c || 'E' == c) {
- ++start;
- if (start == end)
- return false;
- c = *start;
+ ++(cursor->pos);
+ if (cursor->pos == end)
+ return Error::kSyntaxError;
+ c = *(cursor->pos);
if ('-' == c || '+' == c) {
- ++start;
- if (start == end)
- return false;
+ ++(cursor->pos);
+ if (cursor->pos == end)
+ return Error::kSyntaxError;
}
- if (!ReadInt(start, end, &start, true))
- return false;
+ error = ReadInt(cursor, end, true);
+ if (error != Error::kNoError)
+ return error;
}
- *token_end = start;
- return true;
+ return Error::kNoError;
}
template <typename CharType>
-bool ReadHexDigits(const CharType* start,
- const CharType* end,
- const CharType** token_end,
- int digits) {
- if (end - start < digits)
- return false;
+Error ReadHexDigits(Cursor<CharType>* cursor, const CharType* end, int digits) {
+ const CharType* token_start = cursor->pos;
+ if (end - cursor->pos < digits)
+ return Error::kInvalidEscape;
for (int i = 0; i < digits; ++i) {
- CharType c = *start++;
+ CharType c = *(cursor->pos)++;
if (!(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') ||
- ('A' <= c && c <= 'F')))
- return false;
+ ('A' <= c && c <= 'F'))) {
+ cursor->pos = token_start;
+ return Error::kInvalidEscape;
+ }
}
- *token_end = start;
- return true;
+ return Error::kNoError;
}
template <typename CharType>
-bool ParseStringToken(const CharType* start,
- const CharType* end,
- const CharType** token_end) {
- while (start < end) {
- CharType c = *start++;
+Error ParseStringToken(Cursor<CharType>* cursor, const CharType* end) {
+ if (cursor->pos == end)
+ return Error::kSyntaxError;
+ if (*(cursor->pos) != '"')
+ return Error::kSyntaxError;
+ ++(cursor->pos);
+ while (cursor->pos < end) {
+ CharType c = *(cursor->pos)++;
if ('\\' == c) {
- if (start == end)
- return false;
- c = *start++;
+ if (cursor->pos == end)
+ return Error::kInvalidEscape;
+ c = *(cursor->pos)++;
// Make sure the escaped char is valid.
switch (c) {
- case 'x':
- if (!ReadHexDigits(start, end, &start, 2))
- return false;
+ case 'x': {
+ Error error = ReadHexDigits(cursor, end, 2);
+ if (error != Error::kNoError)
+ return error;
break;
- case 'u':
- if (!ReadHexDigits(start, end, &start, 4))
- return false;
+ }
+ case 'u': {
+ Error error = ReadHexDigits(cursor, end, 4);
+ if (error != Error::kNoError)
+ return error;
break;
+ }
case '\\':
case '/':
case 'b':
@@ -163,117 +213,130 @@ bool ParseStringToken(const CharType* start,
case '"':
break;
default:
- return false;
+ return Error::kInvalidEscape;
}
+ } else if (c < 0x20) {
+ return Error::kSyntaxError;
} else if ('"' == c) {
- *token_end = start;
- return true;
+ return Error::kNoError;
}
}
- return false;
+ return Error::kSyntaxError;
}
template <typename CharType>
-bool SkipComment(const CharType* start,
- const CharType* end,
- const CharType** comment_end) {
- if (start == end)
- return false;
+Error SkipComment(Cursor<CharType>* cursor, const CharType* end) {
+ const CharType* pos = cursor->pos;
+ if (pos == end)
+ return Error::kSyntaxError;
- if (*start != '/' || start + 1 >= end)
- return false;
- ++start;
+ if (*pos != '/' || pos + 1 >= end)
+ return Error::kSyntaxError;
+ ++pos;
- if (*start == '/') {
+ if (*pos == '/') {
// Single line comment, read to newline.
- for (++start; start < end; ++start) {
- if (*start == '\n' || *start == '\r') {
- *comment_end = start + 1;
- return true;
+ for (++pos; pos < end; ++pos) {
+ if (*pos == '\n') {
+ cursor->line++;
+ cursor->pos = pos + 1;
+ cursor->line_start = cursor->pos;
+ return Error::kNoError;
}
}
- *comment_end = end;
+ cursor->pos = end;
// Comment reaches end-of-input, which is fine.
- return true;
+ return Error::kNoError;
}
- if (*start == '*') {
+ if (*pos == '*') {
CharType previous = '\0';
// Block comment, read until end marker.
- for (++start; start < end; previous = *start++) {
- if (previous == '*' && *start == '/') {
- *comment_end = start + 1;
- return true;
+ for (++pos; pos < end; previous = *pos++) {
+ if (*pos == '\n') {
+ cursor->line++;
+ cursor->line_start = pos + 1;
+ }
+ if (previous == '*' && *pos == '/') {
+ cursor->pos = pos + 1;
+ return Error::kNoError;
}
}
// Block comment must close before end-of-input.
- return false;
+ return Error::kSyntaxError;
}
- return false;
+ return Error::kSyntaxError;
}
template <typename CharType>
-void SkipWhitespaceAndComments(const CharType* start,
- const CharType* end,
- const CharType** whitespace_end) {
- while (start < end) {
- if (IsSpaceOrNewline(*start)) {
- ++start;
- } else if (*start == '/') {
- const CharType* comment_end;
- if (!SkipComment(start, end, &comment_end))
- break;
- start = comment_end;
+Error SkipWhitespaceAndComments(Cursor<CharType>* cursor, const CharType* end) {
+ while (cursor->pos < end) {
+ CharType c = *(cursor->pos);
+ if (c == '\n') {
+ cursor->line++;
+ ++(cursor->pos);
+ cursor->line_start = cursor->pos;
+ } else if (c == ' ' || c == '\n' || c == '\r' || c == '\t') {
+ ++(cursor->pos);
+ } else if (c == '/') {
+ Error error = SkipComment(cursor, end);
+ if (error != Error::kNoError)
+ return error;
} else {
break;
}
}
- *whitespace_end = start;
+ return Error::kNoError;
}
template <typename CharType>
-Token ParseToken(const CharType* start,
+Error ParseToken(Cursor<CharType>* cursor,
const CharType* end,
- const CharType** token_start,
- const CharType** token_end) {
- SkipWhitespaceAndComments(start, end, token_start);
- start = *token_start;
+ Token* token,
+ Cursor<CharType>* token_start) {
+ Error error = SkipWhitespaceAndComments(cursor, end);
+ if (error != Error::kNoError)
+ return error;
+ *token_start = *cursor;
- if (start == end)
- return kInvalidToken;
+ if (cursor->pos == end)
+ return Error::kSyntaxError;
- switch (*start) {
+ switch (*(cursor->pos)) {
case 'n':
- if (ParseConstToken(start, end, token_end, kJSONNullString))
- return kNullToken;
- break;
+ *token = kNullToken;
+ return ParseConstToken(cursor, end, kJSONNullString);
case 't':
- if (ParseConstToken(start, end, token_end, kJSONTrueString))
- return kBoolTrue;
- break;
+ *token = kBoolTrue;
+ return ParseConstToken(cursor, end, kJSONTrueString);
case 'f':
- if (ParseConstToken(start, end, token_end, kJSONFalseString))
- return kBoolFalse;
- break;
+ *token = kBoolFalse;
+ return ParseConstToken(cursor, end, kJSONFalseString);
case '[':
- *token_end = start + 1;
- return kArrayBegin;
+ ++(cursor->pos);
+ *token = kArrayBegin;
+ return Error::kNoError;
case ']':
- *token_end = start + 1;
- return kArrayEnd;
+ ++(cursor->pos);
+ *token = kArrayEnd;
+ return Error::kNoError;
case ',':
- *token_end = start + 1;
- return kListSeparator;
+ ++(cursor->pos);
+ *token = kListSeparator;
+ return Error::kNoError;
case '{':
- *token_end = start + 1;
- return kObjectBegin;
+ ++(cursor->pos);
+ *token = kObjectBegin;
+ return Error::kNoError;
case '}':
- *token_end = start + 1;
- return kObjectEnd;
+ ++(cursor->pos);
+ *token = kObjectEnd;
+ return Error::kNoError;
case ':':
- *token_end = start + 1;
- return kObjectPairSeparator;
+ ++(cursor->pos);
+ *token = kObjectPairSeparator;
+ return Error::kNoError;
case '0':
case '1':
case '2':
@@ -285,15 +348,14 @@ Token ParseToken(const CharType* start,
case '8':
case '9':
case '-':
- if (ParseNumberToken(start, end, token_end))
- return kNumber;
- break;
+ *token = kNumber;
+ return ParseNumberToken(cursor, end);
case '"':
- if (ParseStringToken(start + 1, end, token_end))
- return kStringLiteral;
- break;
+ *token = kStringLiteral;
+ return ParseStringToken(cursor, end);
}
- return kInvalidToken;
+
+ return Error::kSyntaxError;
}
template <typename CharType>
@@ -309,22 +371,38 @@ inline int HexToInt(CharType c) {
}
template <typename CharType>
-bool DecodeString(const CharType* start,
- const CharType* end,
- StringBuilder* output) {
- while (start < end) {
- UChar c = *start++;
+Error DecodeString(Cursor<CharType>* cursor,
+ const CharType* end,
+ String* output) {
+ if (cursor->pos + 1 > end - 1)
+ return Error::kSyntaxError;
+ if (cursor->pos + 1 == end - 1) {
+ *output = "";
+ return Error::kNoError;
+ }
+
+ const CharType* string_start = cursor->pos;
+ StringBuilder buffer;
+ buffer.ReserveCapacity(end - cursor->pos - 2);
+
+ cursor->pos++;
+ while (cursor->pos < end - 1) {
+ UChar c = *(cursor->pos)++;
+ if (c == '\n') {
+ cursor->line++;
+ cursor->line_start = cursor->pos;
+ }
if ('\\' != c) {
- output->Append(c);
+ buffer.Append(c);
continue;
}
- if (start == end)
- return false;
- c = *start++;
+ if (cursor->pos == end - 1)
+ return Error::kInvalidEscape;
+ c = *(cursor->pos)++;
if (c == 'x') {
// \x is not supported.
- return false;
+ return Error::kInvalidEscape;
}
switch (c) {
@@ -351,194 +429,243 @@ bool DecodeString(const CharType* start,
c = '\v';
break;
case 'u':
- c = (HexToInt(*start) << 12) + (HexToInt(*(start + 1)) << 8) +
- (HexToInt(*(start + 2)) << 4) + HexToInt(*(start + 3));
- start += 4;
+ c = (HexToInt(*(cursor->pos)) << 12) +
+ (HexToInt(*(cursor->pos + 1)) << 8) +
+ (HexToInt(*(cursor->pos + 2)) << 4) + HexToInt(*(cursor->pos + 3));
+ cursor->pos += 4;
break;
default:
- return false;
+ return Error::kInvalidEscape;
}
- output->Append(c);
- }
- return true;
-}
-
-template <typename CharType>
-bool DecodeString(const CharType* start, const CharType* end, String* output) {
- if (start == end) {
- *output = "";
- return true;
+ buffer.Append(c);
}
- if (start > end)
- return false;
- StringBuilder buffer;
- buffer.ReserveCapacity(end - start);
- if (!DecodeString(start, end, &buffer))
- return false;
*output = buffer.ToString();
+
// Validate constructed utf16 string.
- if (output->Utf8(kStrictUTF8Conversion).IsNull())
- return false;
- return true;
+ if (output->Utf8(kStrictUTF8Conversion).IsNull()) {
+ cursor->pos = string_start;
+ return Error::kUnsupportedEncoding;
+ }
+ return Error::kNoError;
}
template <typename CharType>
-std::unique_ptr<JSONValue> BuildValue(const CharType* start,
- const CharType* end,
- const CharType** value_token_end,
- int max_depth) {
+Error BuildValue(Cursor<CharType>* cursor,
+ const CharType* end,
+ int max_depth,
+ std::unique_ptr<JSONValue>* result) {
if (max_depth == 0)
- return nullptr;
+ return Error::kTooMuchNesting;
+
+ Cursor<CharType> token_start;
+ Token token;
+ Error error = ParseToken(cursor, end, &token, &token_start);
+ if (error != Error::kNoError)
+ return error;
- std::unique_ptr<JSONValue> result;
- const CharType* token_start;
- const CharType* token_end;
- Token token = ParseToken(start, end, &token_start, &token_end);
switch (token) {
- case kInvalidToken:
- return nullptr;
case kNullToken:
- result = JSONValue::Null();
+ *result = JSONValue::Null();
break;
case kBoolTrue:
- result = JSONBasicValue::Create(true);
+ *result = JSONBasicValue::Create(true);
break;
case kBoolFalse:
- result = JSONBasicValue::Create(false);
+ *result = JSONBasicValue::Create(false);
break;
case kNumber: {
bool ok;
- double value =
- CharactersToDouble(token_start, token_end - token_start, &ok);
+ double value = CharactersToDouble(token_start.pos,
+ cursor->pos - token_start.pos, &ok);
if (Decimal::FromDouble(value).IsInfinity())
ok = false;
- if (!ok)
- return nullptr;
- int number = static_cast<int>(value);
- if (number == value)
- result = JSONBasicValue::Create(number);
+ if (!ok) {
+ *cursor = token_start;
+ return Error::kSyntaxError;
+ }
+ if (base::IsValueInRangeForNumericType<int>(value) &&
+ static_cast<int>(value) == value)
+ *result = JSONBasicValue::Create(static_cast<int>(value));
else
- result = JSONBasicValue::Create(value);
+ *result = JSONBasicValue::Create(value);
break;
}
case kStringLiteral: {
String value;
- bool ok = DecodeString(token_start + 1, token_end - 1, &value);
- if (!ok)
- return nullptr;
- result = JSONString::Create(value);
+ error = DecodeString(&token_start, cursor->pos, &value);
+ if (error != Error::kNoError) {
+ *cursor = token_start;
+ return error;
+ }
+ *result = JSONString::Create(value);
break;
}
case kArrayBegin: {
std::unique_ptr<JSONArray> array = JSONArray::Create();
- start = token_end;
- token = ParseToken(start, end, &token_start, &token_end);
+ Cursor<CharType> before_token = *cursor;
+ error = ParseToken(cursor, end, &token, &token_start);
+ if (error != Error::kNoError)
+ return error;
while (token != kArrayEnd) {
- std::unique_ptr<JSONValue> array_node =
- BuildValue(start, end, &token_end, max_depth - 1);
- if (!array_node)
- return nullptr;
+ *cursor = before_token;
+ std::unique_ptr<JSONValue> array_node;
+ error = BuildValue(cursor, end, max_depth - 1, &array_node);
+ if (error != Error::kNoError)
+ return error;
array->PushValue(std::move(array_node));
// After a list value, we expect a comma or the end of the list.
- start = token_end;
- token = ParseToken(start, end, &token_start, &token_end);
+ error = ParseToken(cursor, end, &token, &token_start);
+ if (error != Error::kNoError)
+ return error;
if (token == kListSeparator) {
- start = token_end;
- token = ParseToken(start, end, &token_start, &token_end);
- if (token == kArrayEnd)
- return nullptr;
+ before_token = *cursor;
+ error = ParseToken(cursor, end, &token, &token_start);
+ if (error != Error::kNoError)
+ return error;
+ if (token == kArrayEnd) {
+ *cursor = token_start;
+ return Error::kUnexpectedToken;
+ }
} else if (token != kArrayEnd) {
// Unexpected value after list value. Bail out.
- return nullptr;
+ *cursor = token_start;
+ return Error::kUnexpectedToken;
}
}
- if (token != kArrayEnd)
- return nullptr;
- result = std::move(array);
+ if (token != kArrayEnd) {
+ *cursor = token_start;
+ return Error::kUnexpectedToken;
+ }
+ *result = std::move(array);
break;
}
case kObjectBegin: {
std::unique_ptr<JSONObject> object = JSONObject::Create();
- start = token_end;
- token = ParseToken(start, end, &token_start, &token_end);
+ error = ParseToken(cursor, end, &token, &token_start);
+ if (error != Error::kNoError)
+ return error;
while (token != kObjectEnd) {
- if (token != kStringLiteral)
- return nullptr;
+ if (token != kStringLiteral) {
+ *cursor = token_start;
+ return Error::kUnexpectedToken;
+ }
String key;
- if (!DecodeString(token_start + 1, token_end - 1, &key))
- return nullptr;
- start = token_end;
-
- token = ParseToken(start, end, &token_start, &token_end);
- if (token != kObjectPairSeparator)
- return nullptr;
- start = token_end;
-
- std::unique_ptr<JSONValue> value =
- BuildValue(start, end, &token_end, max_depth - 1);
- if (!value)
- return nullptr;
+ error = DecodeString(&token_start, cursor->pos, &key);
+ if (error != Error::kNoError) {
+ *cursor = token_start;
+ return error;
+ }
+
+ error = ParseToken(cursor, end, &token, &token_start);
+ if (token != kObjectPairSeparator) {
+ *cursor = token_start;
+ return Error::kUnexpectedToken;
+ }
+
+ std::unique_ptr<JSONValue> value;
+ error = BuildValue(cursor, end, max_depth - 1, &value);
+ if (error != Error::kNoError)
+ return error;
object->SetValue(key, std::move(value));
- start = token_end;
// After a key/value pair, we expect a comma or the end of the
// object.
- token = ParseToken(start, end, &token_start, &token_end);
+ error = ParseToken(cursor, end, &token, &token_start);
+ if (error != Error::kNoError)
+ return error;
if (token == kListSeparator) {
- start = token_end;
- token = ParseToken(start, end, &token_start, &token_end);
- if (token == kObjectEnd)
- return nullptr;
+ error = ParseToken(cursor, end, &token, &token_start);
+ if (error != Error::kNoError)
+ return error;
+ if (token == kObjectEnd) {
+ *cursor = token_start;
+ return Error::kUnexpectedToken;
+ }
} else if (token != kObjectEnd) {
// Unexpected value after last object value. Bail out.
- return nullptr;
+ *cursor = token_start;
+ return Error::kUnexpectedToken;
}
}
- if (token != kObjectEnd)
- return nullptr;
- result = std::move(object);
+ if (token != kObjectEnd) {
+ *cursor = token_start;
+ return Error::kUnexpectedToken;
+ }
+ *result = std::move(object);
break;
}
default:
// We got a token that's not a value.
- return nullptr;
+ *cursor = token_start;
+ return Error::kUnexpectedToken;
}
- SkipWhitespaceAndComments(token_end, end, value_token_end);
- return result;
+ return SkipWhitespaceAndComments(cursor, end);
}
template <typename CharType>
-std::unique_ptr<JSONValue> ParseJSONInternal(const CharType* start,
- unsigned length,
- int max_depth) {
- const CharType* end = start + length;
- const CharType* token_end;
- std::unique_ptr<JSONValue> value =
- BuildValue(start, end, &token_end, max_depth);
- if (!value || token_end != end)
- return nullptr;
- return value;
+JSONParseError ParseJSONInternal(const CharType* start_ptr,
+ unsigned length,
+ int max_depth,
+ std::unique_ptr<JSONValue>* result) {
+ Cursor<CharType> cursor;
+ cursor.pos = start_ptr;
+ cursor.line = 0;
+ cursor.line_start = start_ptr;
+ const CharType* end = start_ptr + length;
+ JSONParseError error;
+ error.type = BuildValue(&cursor, end, max_depth, result);
+ error.line = cursor.line;
+ error.column = cursor.pos - cursor.line_start;
+ if (error.type != Error::kNoError) {
+ *result = nullptr;
+ } else if (cursor.pos != end) {
+ error.type = Error::kUnexpectedDataAfterRoot;
+ *result = nullptr;
+ }
+ return error;
}
} // anonymous namespace
-std::unique_ptr<JSONValue> ParseJSON(const String& json) {
- return ParseJSON(json, kMaxStackLimit);
+std::unique_ptr<JSONValue> ParseJSON(const String& json,
+ JSONParseError* opt_error) {
+ return ParseJSON(json, kMaxStackLimit, opt_error);
}
-std::unique_ptr<JSONValue> ParseJSON(const String& json, int max_depth) {
- if (json.IsEmpty())
- return nullptr;
+std::unique_ptr<JSONValue> ParseJSON(const String& json,
+ int max_depth,
+ JSONParseError* opt_error) {
if (max_depth < 0)
max_depth = 0;
if (max_depth > kMaxStackLimit)
max_depth = kMaxStackLimit;
- if (json.Is8Bit())
- return ParseJSONInternal(json.Characters8(), json.length(), max_depth);
- return ParseJSONInternal(json.Characters16(), json.length(), max_depth);
+
+ std::unique_ptr<JSONValue> result;
+ JSONParseError error;
+
+ if (json.IsEmpty()) {
+ error.type = Error::kSyntaxError;
+ error.line = 0;
+ error.column = 0;
+ } else if (json.Is8Bit()) {
+ error = ParseJSONInternal(json.Characters8(), json.length(), max_depth,
+ &result);
+ } else {
+ error = ParseJSONInternal(json.Characters16(), json.length(), max_depth,
+ &result);
+ }
+
+ if (opt_error) {
+ error.line++;
+ error.column++;
+ if (error.type != Error::kNoError)
+ error.message = FormatErrorMessage(error.type, error.line, error.column);
+ *opt_error = error;
+ }
+ return result;
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/json/json_parser.h b/chromium/third_party/blink/renderer/platform/json/json_parser.h
index b8e1383108c..43f434e87bc 100644
--- a/chromium/third_party/blink/renderer/platform/json/json_parser.h
+++ b/chromium/third_party/blink/renderer/platform/json/json_parser.h
@@ -14,10 +14,35 @@ namespace blink {
class JSONValue;
-PLATFORM_EXPORT std::unique_ptr<JSONValue> ParseJSON(const String& json);
-
-PLATFORM_EXPORT std::unique_ptr<JSONValue> ParseJSON(const String& json,
- int max_depth);
+enum class JSONParseErrorType {
+ kNoError,
+ kUnexpectedToken,
+ kSyntaxError,
+ kInvalidEscape,
+ kTooMuchNesting,
+ kUnexpectedDataAfterRoot,
+ kUnsupportedEncoding,
+};
+
+struct PLATFORM_EXPORT JSONParseError {
+ JSONParseErrorType type;
+ int line;
+ int column;
+ String message;
+};
+
+// Parses |json| string and returns a value it represents.
+// In case of parsing failure, returns nullptr.
+// Optional error struct may be passed in, which will contain
+// error details or |kNoError| if parsing succeeded.
+PLATFORM_EXPORT std::unique_ptr<JSONValue> ParseJSON(
+ const String& json,
+ JSONParseError* opt_error = nullptr);
+
+PLATFORM_EXPORT std::unique_ptr<JSONValue> ParseJSON(
+ const String& json,
+ int max_depth,
+ JSONParseError* opt_error = nullptr);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/json/json_parser_test.cc b/chromium/third_party/blink/renderer/platform/json/json_parser_test.cc
index 32141dc5a83..f07f78b103c 100644
--- a/chromium/third_party/blink/renderer/platform/json/json_parser_test.cc
+++ b/chromium/third_party/blink/renderer/platform/json/json_parser_test.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/json/json_parser.h"
+#include "base/stl_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/json/json_values.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
@@ -11,20 +12,45 @@
namespace blink {
TEST(JSONParserTest, Reading) {
+ JSONParseError error;
JSONValue* tmp_value;
std::unique_ptr<JSONValue> root;
std::unique_ptr<JSONValue> root2;
String str_val;
int int_val = 0;
+ // Successfull parsing returns kNoError.
+ root = ParseJSON("1", &error);
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(JSONParseErrorType::kNoError, error.type);
+ root = ParseJSON("\"string\"", &error);
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(JSONParseErrorType::kNoError, error.type);
+ root = ParseJSON("[]", &error);
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(JSONParseErrorType::kNoError, error.type);
+ root = ParseJSON("{}", &error);
+ ASSERT_TRUE(root.get());
+ EXPECT_EQ(JSONParseErrorType::kNoError, error.type);
+
// some whitespace checking
- root = ParseJSON(" null ");
+ root = ParseJSON(" null ", &error);
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeNull, root->GetType());
+ EXPECT_EQ(JSONParseErrorType::kNoError, error.type);
// Invalid JSON string
- root = ParseJSON("nu");
+ root = ParseJSON("nu", &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
+
+ // Error reporting
+ root = ParseJSON("\n\n nu", &error);
+ EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 3, column: 3, Syntax error.", error.message);
+ EXPECT_EQ(JSONParseErrorType::kSyntaxError, error.type);
+ EXPECT_EQ(3, error.line);
+ EXPECT_EQ(3, error.column);
// Simple bool
root = ParseJSON("true ");
@@ -32,8 +58,9 @@ TEST(JSONParserTest, Reading) {
EXPECT_EQ(JSONValue::kTypeBoolean, root->GetType());
// Embedded comment
- root = ParseJSON("40 /*/");
- EXPECT_FALSE(root.get());
+ root = ParseJSON("40 /*/", &error);
+ // EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 4, Syntax error.", error.message);
root = ParseJSON("/* comment */null");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeNull, root->GetType());
@@ -94,12 +121,16 @@ TEST(JSONParserTest, Reading) {
EXPECT_EQ(43, int_val);
// According to RFC4627, oct, hex, and leading zeros are invalid JSON.
- root = ParseJSON("043");
+ root = ParseJSON("043", &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("0x43");
+ EXPECT_EQ("Line: 1, column: 2, Syntax error.", error.message);
+ root = ParseJSON("0x43", &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("00");
+ EXPECT_EQ("Line: 1, column: 2, Unexpected data after root element.",
+ error.message);
+ root = ParseJSON("00", &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 2, Syntax error.", error.message);
// Test 0 (which needs to be special cased because of the leading zero
// clause).
@@ -170,36 +201,52 @@ TEST(JSONParserTest, Reading) {
EXPECT_DOUBLE_EQ(1.0, double_val);
// Fractional parts must have a digit before and after the decimal point.
- root = ParseJSON("1.");
+ root = ParseJSON("1.", &error);
EXPECT_FALSE(root.get());
- root = ParseJSON(".1");
+ EXPECT_EQ("Line: 1, column: 3, Syntax error.", error.message);
+ root = ParseJSON(".1", &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("1.e10");
+ EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
+ root = ParseJSON("1.e10", &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 3, Syntax error.", error.message);
// Exponent must have a digit following the 'e'.
- root = ParseJSON("1e");
+ root = ParseJSON("1e", &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("1E");
+ EXPECT_EQ("Line: 1, column: 3, Syntax error.", error.message);
+ root = ParseJSON("1E", &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("1e1.");
+ EXPECT_EQ("Line: 1, column: 3, Syntax error.", error.message);
+ root = ParseJSON("1e1.", &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("1e1.0");
+ EXPECT_EQ("Line: 1, column: 4, Unexpected data after root element.",
+ error.message);
+ root = ParseJSON("1e1.0", &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 4, Unexpected data after root element.",
+ error.message);
// INF/-INF/NaN are not valid
- root = ParseJSON("NaN");
+ root = ParseJSON("NaN", &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("nan");
+ EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
+ root = ParseJSON("nan", &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("inf");
+ EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
+ root = ParseJSON("inf", &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
// Invalid number formats
- root = ParseJSON("4.3.1");
+ root = ParseJSON("4.3.1", &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("4e3.1");
+ EXPECT_EQ("Line: 1, column: 4, Unexpected data after root element.",
+ error.message);
+ root = ParseJSON("4e3.1", &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 4, Unexpected data after root element.",
+ error.message);
// Test string parser
root = ParseJSON("\"hello world\"");
@@ -223,18 +270,54 @@ TEST(JSONParserTest, Reading) {
EXPECT_EQ(" \"\\/\b\f\n\r\t\v", str_val);
// Test hex and unicode escapes including the null character.
- root = ParseJSON("\"\\x41\\x00\\u1234\"");
+ root = ParseJSON("\"\\x41\\x00\\u1234\"", &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 4, Invalid escape sequence.", error.message);
// Test invalid strings
- root = ParseJSON("\"no closing quote");
+ root = ParseJSON("\"no closing quote", &error);
+ EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 18, Syntax error.", error.message);
+ root = ParseJSON("\"\\z invalid escape char\"", &error);
+ EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 4, Invalid escape sequence.", error.message);
+ root = ParseJSON("\"not enough escape chars\\u123\"", &error);
+ EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 27, Invalid escape sequence.", error.message);
+ root = ParseJSON("\"extra backslash at end of input\\\"", &error);
+ EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 35, Syntax error.", error.message);
+ root = ParseJSON("\"a\"extra data", &error);
+ EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 4, Unexpected data after root element.",
+ error.message);
+
+ // Bare control characters (including newlines) are not permitted in string
+ // literals.
+ root = ParseJSON("\"\n\"", &error);
+ EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 3, Syntax error.", error.message);
+ root = ParseJSON("[\"\n\"]", &error);
+ EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 4, Syntax error.", error.message);
+ root = ParseJSON("{\"\n\": true}", &error);
+ EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 4, Syntax error.", error.message);
+ root = ParseJSON("{\"key\": \"\n\"}", &error);
+ EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 11, Syntax error.", error.message);
+ root = ParseJSON("\"\x1b\"", &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("\"\\z invalid escape char\"");
+ EXPECT_EQ("Line: 1, column: 3, Syntax error.", error.message);
+ root = ParseJSON("[\"\x07\"]", &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("\"not enough escape chars\\u123\"");
+ EXPECT_EQ("Line: 1, column: 4, Syntax error.", error.message);
+ root = ParseJSON("{\"\x09\": true}", &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("\"extra backslash at end of input\\\"");
+ EXPECT_EQ("Line: 1, column: 4, Syntax error.", error.message);
+ root = ParseJSON("{\"key\": \"\x01\"}", &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 11, Syntax error.", error.message);
// Basic array
root = ParseJSON("[true, false, null]");
@@ -261,20 +344,24 @@ TEST(JSONParserTest, Reading) {
EXPECT_EQ(4U, list->size());
// Invalid, missing close brace.
- root = ParseJSON("[[true], [], [false, [], [null]], null");
+ root = ParseJSON("[[true], [], [false, [], [null]], null", &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 39, Syntax error.", error.message);
// Invalid, too many commas
- root = ParseJSON("[true,, null]");
+ root = ParseJSON("[true,, null]", &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 7, Unexpected token.", error.message);
// Invalid, no commas
- root = ParseJSON("[true null]");
+ root = ParseJSON("[true null]", &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 7, Unexpected token.", error.message);
// Invalid, trailing comma
- root = ParseJSON("[true,]");
+ root = ParseJSON("[true,]", &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 7, Unexpected token.", error.message);
root = ParseJSON("[true]");
ASSERT_TRUE(root.get());
@@ -290,14 +377,18 @@ TEST(JSONParserTest, Reading) {
EXPECT_TRUE(bool_value);
// Don't allow empty elements.
- root = ParseJSON("[,]");
+ root = ParseJSON("[,]", &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("[true,,]");
+ EXPECT_EQ("Line: 1, column: 2, Unexpected token.", error.message);
+ root = ParseJSON("[true,,]", &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("[,true,]");
+ EXPECT_EQ("Line: 1, column: 7, Unexpected token.", error.message);
+ root = ParseJSON("[,true,]", &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("[true,,false]");
+ EXPECT_EQ("Line: 1, column: 2, Unexpected token.", error.message);
+ root = ParseJSON("[true,,false]", &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 7, Unexpected token.", error.message);
// Test objects
root = ParseJSON("{}");
@@ -337,6 +428,33 @@ TEST(JSONParserTest, Reading) {
ASSERT_TRUE(root2.get());
EXPECT_EQ(root->ToJSONString(), root2->ToJSONString());
+ // Test that allowed whitespace is limited to TAB, CR, LF and SP. There are
+ // several other Unicode characters defined as whitespace, so a selection of
+ // them are tested to ensure that they are not allowed.
+ // U+0009 CHARACTER TABULATION is allowed
+ root = ParseJSON("\t{\t\"key\"\t:\t[\t\"value1\"\t,\t\"value2\"\t]\t}\t");
+ ASSERT_TRUE(root.get());
+ // U+000A LINE FEED is allowed
+ root = ParseJSON("\n{\n\"key\"\n:\n[\n\"value1\"\n,\n\"value2\"\n]\n}\n");
+ ASSERT_TRUE(root.get());
+ // U+000D CARRIAGE RETURN is allowed
+ root = ParseJSON("\r{\r\"key\"\r:\r[\r\"value1\"\r,\r\"value2\"\r]\r}\r");
+ ASSERT_TRUE(root.get());
+ // U+0020 SPACE is allowed
+ root = ParseJSON(" { \"key\" : [ \"value1\" , \"value2\" ] } ");
+ ASSERT_TRUE(root.get());
+ // U+000B LINE TABULATION is not allowed
+ root = ParseJSON("[\x0b\"value\"]");
+ ASSERT_FALSE(root.get());
+ // U+00A0 NO-BREAK SPACE is not allowed
+ UChar invalid_space_1[] = {0x5b, 0x00a0, 0x5d}; // [<U+00A0>]
+ root = ParseJSON(String(invalid_space_1, base::size(invalid_space_1)));
+ ASSERT_FALSE(root.get());
+ // U+3000 IDEOGRAPHIC SPACE is not allowed
+ UChar invalid_space_2[] = {0x5b, 0x3000, 0x5d}; // [<U+3000>]
+ root = ParseJSON(String(invalid_space_2, base::size(invalid_space_2)));
+ ASSERT_FALSE(root.get());
+
// Test nesting
root = ParseJSON("{\"inner\":{\"array\":[true]},\"false\":false,\"d\":{}}");
ASSERT_TRUE(root.get());
@@ -388,30 +506,38 @@ TEST(JSONParserTest, Reading) {
EXPECT_FALSE(root.get());
// Invalid, keys must be quoted
- root = ParseJSON("{foo:true}");
+ root = ParseJSON("{foo:true}", &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 2, Syntax error.", error.message);
// Invalid, trailing comma
- root = ParseJSON("{\"a\":true,}");
+ root = ParseJSON("{\"a\":true,}", &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 11, Unexpected token.", error.message);
// Invalid, too many commas
- root = ParseJSON("{\"a\":true,,\"b\":false}");
+ root = ParseJSON("{\"a\":true,,\"b\":false}", &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 11, Unexpected token.", error.message);
// Invalid, no separator
- root = ParseJSON("{\"a\" \"b\"}");
+ root = ParseJSON("{\"a\" \"b\"}", &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 6, Unexpected token.", error.message);
// Invalid, lone comma.
- root = ParseJSON("{,}");
+ root = ParseJSON("{,}", &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("{\"a\":true,,}");
+ EXPECT_EQ("Line: 1, column: 2, Unexpected token.", error.message);
+ root = ParseJSON("{\"a\":true,,}", &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("{,\"a\":true}");
+ EXPECT_EQ("Line: 1, column: 11, Unexpected token.", error.message);
+ root = ParseJSON("{,\"a\":true}", &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("{\"a\":true,,\"b\":false}");
+ EXPECT_EQ("Line: 1, column: 2, Unexpected token.", error.message);
+ root = ParseJSON("{\"a\":true,,\"b\":false}", &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 11, Unexpected token.", error.message);
// Test stack overflow
StringBuilder evil;
@@ -420,8 +546,9 @@ TEST(JSONParserTest, Reading) {
evil.Append('[');
for (int i = 0; i < 1000000; ++i)
evil.Append(']');
- root = ParseJSON(evil.ToString());
+ root = ParseJSON(evil.ToString(), &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 1001, Too much nesting.", error.message);
// A few thousand adjacent lists is fine.
StringBuilder not_evil;
@@ -438,8 +565,9 @@ TEST(JSONParserTest, Reading) {
EXPECT_EQ(5001U, list->size());
// Test utf8 encoded input
- root = ParseJSON("\"\\xe7\\xbd\\x91\\xe9\\xa1\\xb5\"");
+ root = ParseJSON("\"\\xe7\\xbd\\x91\\xe9\\xa1\\xb5\"", &error);
ASSERT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 4, Invalid escape sequence.", error.message);
// Test utf16 encoded strings.
root = ParseJSON("\"\\u20ac3,14\"");
@@ -447,17 +575,44 @@ TEST(JSONParserTest, Reading) {
EXPECT_EQ(JSONValue::kTypeString, root->GetType());
EXPECT_TRUE(root->AsString(&str_val));
UChar tmp2[] = {0x20ac, 0x33, 0x2c, 0x31, 0x34};
- EXPECT_EQ(String(tmp2, arraysize(tmp2)), str_val);
+ EXPECT_EQ(String(tmp2, base::size(tmp2)), str_val);
root = ParseJSON("\"\\ud83d\\udca9\\ud83d\\udc6c\"");
ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeString, root->GetType());
EXPECT_TRUE(root->AsString(&str_val));
UChar tmp3[] = {0xd83d, 0xdca9, 0xd83d, 0xdc6c};
- EXPECT_EQ(String(tmp3, arraysize(tmp3)), str_val);
+ EXPECT_EQ(String(tmp3, base::size(tmp3)), str_val);
+
+ // Invalid unicode in a string literal after applying escape sequences.
+ root = ParseJSON("\n\n \"\\ud800\"", &error);
+ EXPECT_FALSE(root.get());
+ EXPECT_EQ(
+ "Line: 3, column: 5, Unsupported encoding. JSON and all string literals "
+ "must contain valid Unicode characters.",
+ error.message);
+
+ // Invalid unicode in a JSON itself.
+ UChar tmp4[] = {0x22, 0xd800, 0x22}; // "?"
+ root = ParseJSON(String(tmp4, base::size(tmp4)), &error);
+ EXPECT_FALSE(root.get());
+ EXPECT_EQ(
+ "Line: 1, column: 1, Unsupported encoding. JSON and all string literals "
+ "must contain valid Unicode characters.",
+ error.message);
+
+ // Invalid unicode in a JSON itself.
+ UChar tmp5[] = {0x7b, 0x22, 0xd800, 0x22, 0x3a, 0x31, 0x7d}; // {"?":1}
+ root = ParseJSON(String(tmp5, base::size(tmp5)), &error);
+ EXPECT_FALSE(root.get());
+ EXPECT_EQ(
+ "Line: 1, column: 2, Unsupported encoding. JSON and all string literals "
+ "must contain valid Unicode characters.",
+ error.message);
// Test literal root objects.
root = ParseJSON("null");
+ ASSERT_TRUE(root.get());
EXPECT_EQ(JSONValue::kTypeNull, root->GetType());
root = ParseJSON("true");
@@ -481,7 +636,7 @@ TEST(JSONParserTest, InvalidSanity) {
"/* test *", "{\"foo\"", "{\"foo\":", " [", "\"\\u123g\"", "{\n\"eh:\n}",
"////", "*/**/", "/**/", "/*/", "//**/", "\"\\"};
- for (size_t i = 0; i < arraysize(kInvalidJson); ++i) {
+ for (size_t i = 0; i < base::size(kInvalidJson); ++i) {
std::unique_ptr<JSONValue> result = ParseJSON(kInvalidJson[i]);
EXPECT_FALSE(result.get());
}
@@ -491,6 +646,7 @@ TEST(JSONParserTest, InvalidSanity) {
// cannot be extended past that maximum.
TEST(JSONParserTest, LimitedDepth) {
std::unique_ptr<JSONValue> root;
+ JSONParseError error;
// Test cases. Each pair is a JSON string, and the minimum depth required
// to successfully parse that string.
@@ -516,12 +672,15 @@ TEST(JSONParserTest, LimitedDepth) {
}
// Test that everything fails to parse with depth 0
- root = ParseJSON("", 0);
+ root = ParseJSON("", 0, &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("", -1);
+ EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
+ root = ParseJSON("", -1, &error);
EXPECT_FALSE(root.get());
- root = ParseJSON("true", 0);
+ EXPECT_EQ("Line: 1, column: 1, Syntax error.", error.message);
+ root = ParseJSON("true", 0, &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 1, Too much nesting.", error.message);
// Test that the limit can be set to the constant maximum.
StringBuilder evil;
@@ -541,10 +700,12 @@ TEST(JSONParserTest, LimitedDepth) {
evil.Append('[');
for (int i = 0; i < 1001; ++i)
evil.Append(']');
- root = ParseJSON(evil.ToString());
+ root = ParseJSON(evil.ToString(), &error);
EXPECT_FALSE(root.get());
- root = ParseJSON(evil.ToString(), 1001);
+ EXPECT_EQ("Line: 1, column: 1001, Too much nesting.", error.message);
+ root = ParseJSON(evil.ToString(), 1001, &error);
EXPECT_FALSE(root.get());
+ EXPECT_EQ("Line: 1, column: 1001, Too much nesting.", error.message);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/json/json_values.cc b/chromium/third_party/blink/renderer/platform/json/json_values.cc
index 0ccaad7fc7f..01a55db1377 100644
--- a/chromium/third_party/blink/renderer/platform/json/json_values.cc
+++ b/chromium/third_party/blink/renderer/platform/json/json_values.cc
@@ -32,7 +32,8 @@
#include <algorithm>
#include <cmath>
-#include "third_party/blink/renderer/platform/decimal.h"
+
+#include "third_party/blink/renderer/platform/wtf/decimal.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
diff --git a/chromium/third_party/blink/renderer/platform/kill_ring.h b/chromium/third_party/blink/renderer/platform/kill_ring.h
deleted file mode 100644
index d675e9cfdee..00000000000
--- a/chromium/third_party/blink/renderer/platform/kill_ring.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_KILL_RING_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_KILL_RING_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT KillRing {
- USING_FAST_MALLOC(KillRing);
-
- public:
- KillRing() = default;
- void Append(const String&);
- void Prepend(const String&);
- String Yank();
- void StartNewSequence();
- void SetToYankedState();
-
- DISALLOW_COPY_AND_ASSIGN(KillRing);
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_KILL_RING_H_
diff --git a/chromium/third_party/blink/renderer/platform/kill_ring_none.cc b/chromium/third_party/blink/renderer/platform/kill_ring_none.cc
deleted file mode 100644
index 94bcf1e3d42..00000000000
--- a/chromium/third_party/blink/renderer/platform/kill_ring_none.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/platform/kill_ring.h"
-
-namespace blink {
-
-void KillRing::Append(const String&) {}
-
-void KillRing::Prepend(const String&) {}
-
-String KillRing::Yank() {
- return String();
-}
-
-void KillRing::StartNewSequence() {}
-
-void KillRing::SetToYankedState() {}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/layout_locale.cc b/chromium/third_party/blink/renderer/platform/layout_locale.cc
deleted file mode 100644
index 7fb1f9cfc10..00000000000
--- a/chromium/third_party/blink/renderer/platform/layout_locale.cc
+++ /dev/null
@@ -1,226 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/layout_locale.h"
-
-#include "third_party/blink/renderer/platform/fonts/accept_languages_resolver.h"
-#include "third_party/blink/renderer/platform/fonts/font_global_context.h"
-#include "third_party/blink/renderer/platform/language.h"
-#include "third_party/blink/renderer/platform/text/icu_error.h"
-#include "third_party/blink/renderer/platform/text/locale_to_script_mapping.h"
-#include "third_party/blink/renderer/platform/wtf/hash_map.h"
-#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
-
-#include <hb.h>
-#include <unicode/locid.h>
-
-namespace blink {
-
-static hb_language_t ToHarfbuzLanguage(const AtomicString& locale) {
- CString locale_as_latin1 = locale.Latin1();
- return hb_language_from_string(locale_as_latin1.data(),
- locale_as_latin1.length());
-}
-
-// SkFontMgr requires script-based locale names, like "zh-Hant" and "zh-Hans",
-// instead of "zh-CN" and "zh-TW".
-static const char* ToSkFontMgrLocale(UScriptCode script) {
- switch (script) {
- case USCRIPT_KATAKANA_OR_HIRAGANA:
- return "ja-JP";
- case USCRIPT_HANGUL:
- return "ko-KR";
- case USCRIPT_SIMPLIFIED_HAN:
- return "zh-Hans";
- case USCRIPT_TRADITIONAL_HAN:
- return "zh-Hant";
- default:
- return nullptr;
- }
-}
-
-const char* LayoutLocale::LocaleForSkFontMgr() const {
- if (string_for_sk_font_mgr_.IsNull()) {
- string_for_sk_font_mgr_ = ToSkFontMgrLocale(script_);
- if (string_for_sk_font_mgr_.IsNull())
- string_for_sk_font_mgr_ = string_.Ascii();
- }
- return string_for_sk_font_mgr_.data();
-}
-
-void LayoutLocale::ComputeScriptForHan() const {
- if (IsUnambiguousHanScript(script_)) {
- script_for_han_ = script_;
- has_script_for_han_ = true;
- return;
- }
-
- script_for_han_ = ScriptCodeForHanFromSubtags(string_);
- if (script_for_han_ == USCRIPT_COMMON)
- script_for_han_ = USCRIPT_SIMPLIFIED_HAN;
- else
- has_script_for_han_ = true;
- DCHECK(IsUnambiguousHanScript(script_for_han_));
-}
-
-UScriptCode LayoutLocale::GetScriptForHan() const {
- if (script_for_han_ == USCRIPT_COMMON)
- ComputeScriptForHan();
- return script_for_han_;
-}
-
-bool LayoutLocale::HasScriptForHan() const {
- if (script_for_han_ == USCRIPT_COMMON)
- ComputeScriptForHan();
- return has_script_for_han_;
-}
-
-const LayoutLocale* LayoutLocale::LocaleForHan(
- const LayoutLocale* content_locale) {
- if (content_locale && content_locale->HasScriptForHan())
- return content_locale;
-
- if (FontGlobalContext::HasDefaultLocaleForHan())
- return FontGlobalContext::GetDefaultLocaleForHan();
-
- const LayoutLocale* default_for_han;
- if (const LayoutLocale* locale = AcceptLanguagesResolver::LocaleForHan())
- default_for_han = locale;
- else if (GetDefault().HasScriptForHan())
- default_for_han = &GetDefault();
- else if (GetSystem().HasScriptForHan())
- default_for_han = &GetSystem();
- else
- default_for_han = nullptr;
- FontGlobalContext::SetDefaultLocaleForHan(default_for_han);
- return default_for_han;
-}
-
-const char* LayoutLocale::LocaleForHanForSkFontMgr() const {
- const char* locale = ToSkFontMgrLocale(GetScriptForHan());
- DCHECK(locale);
- return locale;
-}
-
-LayoutLocale::LayoutLocale(const AtomicString& locale)
- : string_(locale),
- harfbuzz_language_(ToHarfbuzLanguage(locale)),
- script_(LocaleToScriptCodeForFontSelection(locale)),
- script_for_han_(USCRIPT_COMMON),
- has_script_for_han_(false),
- hyphenation_computed_(false) {}
-
-const LayoutLocale* LayoutLocale::Get(const AtomicString& locale) {
- if (locale.IsNull())
- return nullptr;
-
- auto result = FontGlobalContext::GetLayoutLocaleMap().insert(locale, nullptr);
- if (result.is_new_entry)
- result.stored_value->value = base::AdoptRef(new LayoutLocale(locale));
- return result.stored_value->value.get();
-}
-
-const LayoutLocale& LayoutLocale::GetDefault() {
- if (const LayoutLocale* locale = FontGlobalContext::GetDefaultLayoutLocale())
- return *locale;
-
- AtomicString language = DefaultLanguage();
- const LayoutLocale* locale =
- LayoutLocale::Get(!language.IsEmpty() ? language : "en");
- FontGlobalContext::SetDefaultLayoutLocale(locale);
- return *locale;
-}
-
-const LayoutLocale& LayoutLocale::GetSystem() {
- if (const LayoutLocale* locale = FontGlobalContext::GetSystemLayoutLocale())
- return *locale;
-
- // Platforms such as Windows can give more information than the default
- // locale, such as "en-JP" for English speakers in Japan.
- String name = icu::Locale::getDefault().getName();
- const LayoutLocale* locale =
- LayoutLocale::Get(AtomicString(name.Replace('_', '-')));
- FontGlobalContext::SetSystemLayoutLocale(locale);
- return *locale;
-}
-
-scoped_refptr<LayoutLocale> LayoutLocale::CreateForTesting(
- const AtomicString& locale) {
- return base::AdoptRef(new LayoutLocale(locale));
-}
-
-Hyphenation* LayoutLocale::GetHyphenation() const {
- if (hyphenation_computed_)
- return hyphenation_.get();
-
- hyphenation_computed_ = true;
- hyphenation_ = Hyphenation::PlatformGetHyphenation(LocaleString());
- return hyphenation_.get();
-}
-
-void LayoutLocale::SetHyphenationForTesting(
- const AtomicString& locale_string,
- scoped_refptr<Hyphenation> hyphenation) {
- const LayoutLocale& locale = ValueOrDefault(Get(locale_string));
- locale.hyphenation_computed_ = true;
- locale.hyphenation_ = std::move(hyphenation);
-}
-
-AtomicString LayoutLocale::LocaleWithBreakKeyword(
- LineBreakIteratorMode mode) const {
- if (string_.IsEmpty())
- return string_;
-
- // uloc_setKeywordValue_58 has a problem to handle "@" in the original
- // string. crbug.com/697859
- if (string_.Contains('@'))
- return string_;
-
- CString utf8_locale = string_.Utf8();
- Vector<char> buffer(utf8_locale.length() + 11, 0);
- memcpy(buffer.data(), utf8_locale.data(), utf8_locale.length());
-
- const char* keyword_value = nullptr;
- switch (mode) {
- default:
- NOTREACHED();
- FALLTHROUGH;
- case LineBreakIteratorMode::kDefault:
- // nullptr will cause any existing values to be removed.
- break;
- case LineBreakIteratorMode::kNormal:
- keyword_value = "normal";
- break;
- case LineBreakIteratorMode::kStrict:
- keyword_value = "strict";
- break;
- case LineBreakIteratorMode::kLoose:
- keyword_value = "loose";
- break;
- }
-
- ICUError status;
- int32_t length_needed = uloc_setKeywordValue(
- "lb", keyword_value, buffer.data(), buffer.size(), &status);
- if (U_SUCCESS(status))
- return AtomicString::FromUTF8(buffer.data(), length_needed);
-
- if (status == U_BUFFER_OVERFLOW_ERROR) {
- buffer.Grow(length_needed + 1);
- memset(buffer.data() + utf8_locale.length(), 0,
- buffer.size() - utf8_locale.length());
- status = U_ZERO_ERROR;
- int32_t length_needed2 = uloc_setKeywordValue(
- "lb", keyword_value, buffer.data(), buffer.size(), &status);
- DCHECK_EQ(length_needed, length_needed2);
- if (U_SUCCESS(status) && length_needed == length_needed2)
- return AtomicString::FromUTF8(buffer.data(), length_needed);
- }
-
- NOTREACHED();
- return string_;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/layout_locale.h b/chromium/third_party/blink/renderer/platform/layout_locale.h
deleted file mode 100644
index ffbcea9d9ba..00000000000
--- a/chromium/third_party/blink/renderer/platform/layout_locale.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LAYOUT_LOCALE_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LAYOUT_LOCALE_H_
-
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/text/hyphenation.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
-#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
-
-#include <unicode/uscript.h>
-
-struct hb_language_impl_t;
-
-namespace blink {
-
-class Hyphenation;
-
-enum class LineBreakIteratorMode { kDefault, kNormal, kStrict, kLoose };
-
-class PLATFORM_EXPORT LayoutLocale : public RefCounted<LayoutLocale> {
- public:
- static const LayoutLocale* Get(const AtomicString& locale);
- static const LayoutLocale& GetDefault();
- static const LayoutLocale& GetSystem();
- static const LayoutLocale& ValueOrDefault(const LayoutLocale* locale) {
- return locale ? *locale : GetDefault();
- }
-
- bool operator==(const LayoutLocale& other) const {
- return string_ == other.string_;
- }
- bool operator!=(const LayoutLocale& other) const {
- return string_ != other.string_;
- }
-
- const AtomicString& LocaleString() const { return string_; }
- static const AtomicString& LocaleString(const LayoutLocale* locale) {
- return locale ? locale->string_ : g_null_atom;
- }
- operator const AtomicString&() const { return string_; }
- CString Ascii() const { return string_.Ascii(); }
-
- const hb_language_impl_t* HarfbuzzLanguage() const {
- return harfbuzz_language_;
- }
- const char* LocaleForSkFontMgr() const;
- UScriptCode GetScript() const { return script_; }
-
- // Disambiguation of the Unified Han Ideographs.
- UScriptCode GetScriptForHan() const;
- bool HasScriptForHan() const;
- static const LayoutLocale* LocaleForHan(const LayoutLocale*);
- const char* LocaleForHanForSkFontMgr() const;
-
- Hyphenation* GetHyphenation() const;
-
- AtomicString LocaleWithBreakKeyword(LineBreakIteratorMode) const;
-
- static scoped_refptr<LayoutLocale> CreateForTesting(const AtomicString&);
- static void SetHyphenationForTesting(const AtomicString&,
- scoped_refptr<Hyphenation>);
-
- private:
- explicit LayoutLocale(const AtomicString&);
-
- void ComputeScriptForHan() const;
-
- AtomicString string_;
- mutable CString string_for_sk_font_mgr_;
- mutable scoped_refptr<Hyphenation> hyphenation_;
-
- // hb_language_t is defined in hb.h, which not all files can include.
- const hb_language_impl_t* harfbuzz_language_;
-
- UScriptCode script_;
- mutable UScriptCode script_for_han_;
-
- mutable unsigned has_script_for_han_ : 1;
- mutable unsigned hyphenation_computed_ : 1;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LAYOUT_LOCALE_H_
diff --git a/chromium/third_party/blink/renderer/platform/layout_locale_test.cc b/chromium/third_party/blink/renderer/platform/layout_locale_test.cc
deleted file mode 100644
index 2791c1144ae..00000000000
--- a/chromium/third_party/blink/renderer/platform/layout_locale_test.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/layout_locale.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/fonts/font_global_context.h"
-
-namespace blink {
-
-TEST(LayoutLocaleTest, Get) {
- FontGlobalContext::ClearForTesting();
-
- EXPECT_EQ(nullptr, LayoutLocale::Get(g_null_atom));
-
- EXPECT_EQ(g_empty_atom, LayoutLocale::Get(g_empty_atom)->LocaleString());
-
- EXPECT_STRCASEEQ("en-us",
- LayoutLocale::Get("en-us")->LocaleString().Ascii().data());
- EXPECT_STRCASEEQ("ja-jp",
- LayoutLocale::Get("ja-jp")->LocaleString().Ascii().data());
-
- FontGlobalContext::ClearForTesting();
-}
-
-TEST(LayoutLocaleTest, GetCaseInsensitive) {
- const LayoutLocale* en_us = LayoutLocale::Get("en-us");
- EXPECT_EQ(en_us, LayoutLocale::Get("en-US"));
-}
-
-TEST(LayoutLocaleTest, ScriptTest) {
- // Test combinations of BCP 47 locales.
- // https://tools.ietf.org/html/bcp47
- struct {
- const char* locale;
- UScriptCode script;
- bool has_script_for_han;
- UScriptCode script_for_han;
- } tests[] = {
- {"en-US", USCRIPT_LATIN},
-
- // Common lang-script.
- {"en-Latn", USCRIPT_LATIN},
- {"ar-Arab", USCRIPT_ARABIC},
-
- // Common lang-region in East Asia.
- {"ja-JP", USCRIPT_KATAKANA_OR_HIRAGANA, true},
- {"ko-KR", USCRIPT_HANGUL, true},
- {"zh", USCRIPT_SIMPLIFIED_HAN, true},
- {"zh-CN", USCRIPT_SIMPLIFIED_HAN, true},
- {"zh-HK", USCRIPT_TRADITIONAL_HAN, true},
- {"zh-MO", USCRIPT_TRADITIONAL_HAN, true},
- {"zh-SG", USCRIPT_SIMPLIFIED_HAN, true},
- {"zh-TW", USCRIPT_TRADITIONAL_HAN, true},
-
- // Encompassed languages within the Chinese macrolanguage.
- // Both "lang" and "lang-extlang" should work.
- {"nan", USCRIPT_TRADITIONAL_HAN, true},
- {"wuu", USCRIPT_SIMPLIFIED_HAN, true},
- {"yue", USCRIPT_TRADITIONAL_HAN, true},
- {"zh-nan", USCRIPT_TRADITIONAL_HAN, true},
- {"zh-wuu", USCRIPT_SIMPLIFIED_HAN, true},
- {"zh-yue", USCRIPT_TRADITIONAL_HAN, true},
-
- // Script has priority over other subtags.
- {"zh-Hant", USCRIPT_TRADITIONAL_HAN, true},
- {"en-Hans", USCRIPT_SIMPLIFIED_HAN, true},
- {"en-Hant", USCRIPT_TRADITIONAL_HAN, true},
- {"en-Hans-TW", USCRIPT_SIMPLIFIED_HAN, true},
- {"en-Hant-CN", USCRIPT_TRADITIONAL_HAN, true},
- {"wuu-Hant", USCRIPT_TRADITIONAL_HAN, true},
- {"yue-Hans", USCRIPT_SIMPLIFIED_HAN, true},
- {"zh-wuu-Hant", USCRIPT_TRADITIONAL_HAN, true},
- {"zh-yue-Hans", USCRIPT_SIMPLIFIED_HAN, true},
-
- // Lang has priority over region.
- // icu::Locale::getDefault() returns other combinations if, for instnace,
- // English Windows with the display language set to Japanese.
- {"ja", USCRIPT_KATAKANA_OR_HIRAGANA, true},
- {"ja-US", USCRIPT_KATAKANA_OR_HIRAGANA, true},
- {"ko", USCRIPT_HANGUL, true},
- {"ko-US", USCRIPT_HANGUL, true},
- {"wuu-TW", USCRIPT_SIMPLIFIED_HAN, true},
- {"yue-CN", USCRIPT_TRADITIONAL_HAN, true},
- {"zh-wuu-TW", USCRIPT_SIMPLIFIED_HAN, true},
- {"zh-yue-CN", USCRIPT_TRADITIONAL_HAN, true},
-
- // Region should not affect script, but it can influence scriptForHan.
- {"en-CN", USCRIPT_LATIN, false},
- {"en-HK", USCRIPT_LATIN, true, USCRIPT_TRADITIONAL_HAN},
- {"en-MO", USCRIPT_LATIN, true, USCRIPT_TRADITIONAL_HAN},
- {"en-SG", USCRIPT_LATIN, false},
- {"en-TW", USCRIPT_LATIN, true, USCRIPT_TRADITIONAL_HAN},
- {"en-JP", USCRIPT_LATIN, true, USCRIPT_KATAKANA_OR_HIRAGANA},
- {"en-KR", USCRIPT_LATIN, true, USCRIPT_HANGUL},
-
- // Multiple regions are invalid, but it can still give hints for the font
- // selection.
- {"en-US-JP", USCRIPT_LATIN, true, USCRIPT_KATAKANA_OR_HIRAGANA},
- };
-
- for (const auto& test : tests) {
- scoped_refptr<LayoutLocale> locale =
- LayoutLocale::CreateForTesting(test.locale);
- EXPECT_EQ(test.script, locale->GetScript()) << test.locale;
- EXPECT_EQ(test.has_script_for_han, locale->HasScriptForHan())
- << test.locale;
- if (!test.has_script_for_han) {
- EXPECT_EQ(USCRIPT_SIMPLIFIED_HAN, locale->GetScriptForHan())
- << test.locale;
- } else if (test.script_for_han) {
- EXPECT_EQ(test.script_for_han, locale->GetScriptForHan()) << test.locale;
- } else {
- EXPECT_EQ(test.script, locale->GetScriptForHan()) << test.locale;
- }
- }
-}
-
-TEST(LayoutLocaleTest, BreakKeyword) {
- struct {
- const char* expected;
- const char* locale;
- LineBreakIteratorMode mode;
- } tests[] = {
- {nullptr, nullptr, LineBreakIteratorMode::kDefault},
- {"", "", LineBreakIteratorMode::kDefault},
- {nullptr, nullptr, LineBreakIteratorMode::kStrict},
- {"", "", LineBreakIteratorMode::kStrict},
- {"ja", "ja", LineBreakIteratorMode::kDefault},
- {"ja@lb=normal", "ja", LineBreakIteratorMode::kNormal},
- {"ja@lb=strict", "ja", LineBreakIteratorMode::kStrict},
- {"ja@lb=loose", "ja", LineBreakIteratorMode::kLoose},
- };
- for (const auto& test : tests) {
- scoped_refptr<LayoutLocale> locale =
- LayoutLocale::CreateForTesting(test.locale);
- EXPECT_EQ(test.expected, locale->LocaleWithBreakKeyword(test.mode))
- << String::Format("'%s' with line-break %d should be '%s'", test.locale,
- static_cast<int>(test.mode), test.expected);
- }
-}
-
-TEST(LayoutLocaleTest, ExistingKeywordName) {
- const char* tests[] = {
- "en@x=", "en@lb=xyz", "en@ =",
- };
- for (auto* const test : tests) {
- scoped_refptr<LayoutLocale> locale = LayoutLocale::CreateForTesting(test);
- EXPECT_EQ(test,
- locale->LocaleWithBreakKeyword(LineBreakIteratorMode::kNormal));
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/layout_unit.h b/chromium/third_party/blink/renderer/platform/layout_unit.h
index 7291a446f42..7865a05d174 100644
--- a/chromium/third_party/blink/renderer/platform/layout_unit.h
+++ b/chromium/third_party/blink/renderer/platform/layout_unit.h
@@ -192,6 +192,13 @@ class LayoutUnit {
static float Epsilon() { return 1.0f / kFixedPointDenominator; }
+ LayoutUnit AddEpsilon() const {
+ LayoutUnit return_value;
+ return_value.SetRawValue(
+ value_ < std::numeric_limits<int>::max() ? value_ + 1 : value_);
+ return return_value;
+ }
+
static const LayoutUnit Max() {
LayoutUnit m;
m.value_ = std::numeric_limits<int>::max();
@@ -583,17 +590,18 @@ inline LayoutUnit operator-(const LayoutUnit& a) {
return return_val;
}
-// For returning the remainder after a division with integer results.
+// Returns the remainder after a division with integer results.
+// This calculates the modulo so that:
+// a = static_cast<int>(a / b) * b + IntMod(a, b).
inline LayoutUnit IntMod(const LayoutUnit& a, const LayoutUnit& b) {
- // This calculates the modulo so that: a = static_cast<int>(a / b) * b +
- // intMod(a, b).
LayoutUnit return_val;
return_val.SetRawValue(a.RawValue() % b.RawValue());
return return_val;
}
-inline LayoutUnit operator%(const LayoutUnit& a, const LayoutUnit& b) {
- // This calculates the modulo so that: a = (a / b) * b + a % b.
+// Returns the remainder after a division with LayoutUnit results.
+// This calculates the modulo so that: a = (a / b) * b + LayoutMod(a, b).
+inline LayoutUnit LayoutMod(const LayoutUnit& a, const LayoutUnit& b) {
LayoutUnit return_val;
long long raw_val =
(static_cast<long long>(kFixedPointDenominator) * a.RawValue()) %
@@ -602,12 +610,8 @@ inline LayoutUnit operator%(const LayoutUnit& a, const LayoutUnit& b) {
return return_val;
}
-inline LayoutUnit operator%(const LayoutUnit& a, int b) {
- return a % LayoutUnit(b);
-}
-
-inline LayoutUnit operator%(int a, const LayoutUnit& b) {
- return LayoutUnit(a) % b;
+inline LayoutUnit LayoutMod(const LayoutUnit& a, int b) {
+ return LayoutMod(a, LayoutUnit(b));
}
inline LayoutUnit& operator+=(LayoutUnit& a, const LayoutUnit& b) {
@@ -697,15 +701,6 @@ inline LayoutUnit AbsoluteValue(const LayoutUnit& value) {
return value.Abs();
}
-inline LayoutUnit LayoutMod(const LayoutUnit& numerator,
- const LayoutUnit& denominator) {
- return numerator % denominator;
-}
-
-inline LayoutUnit LayoutMod(const LayoutUnit& numerator, int denominator) {
- return numerator % LayoutUnit(denominator);
-}
-
inline bool IsIntegerValue(const LayoutUnit value) {
return value.ToInt() == value;
}
diff --git a/chromium/third_party/blink/renderer/platform/layout_unit_test.cc b/chromium/third_party/blink/renderer/platform/layout_unit_test.cc
index 9545139af4b..5eadbe8ed19 100644
--- a/chromium/third_party/blink/renderer/platform/layout_unit_test.cc
+++ b/chromium/third_party/blink/renderer/platform/layout_unit_test.cc
@@ -295,4 +295,29 @@ TEST(LayoutUnitTest, LayoutUnitPlusPlus) {
EXPECT_EQ(LayoutUnit::Max(), LayoutUnit(LayoutUnit::Max())++);
}
+TEST(LayoutUnitTest, IntMod) {
+ EXPECT_EQ(LayoutUnit(5), IntMod(LayoutUnit(55), LayoutUnit(10)));
+ EXPECT_EQ(LayoutUnit(5), IntMod(LayoutUnit(55), LayoutUnit(-10)));
+ EXPECT_EQ(LayoutUnit(-5), IntMod(LayoutUnit(-55), LayoutUnit(10)));
+ EXPECT_EQ(LayoutUnit(-5), IntMod(LayoutUnit(-55), LayoutUnit(-10)));
+ EXPECT_EQ(LayoutUnit(1.5), IntMod(LayoutUnit(7.5), LayoutUnit(3)));
+ EXPECT_EQ(LayoutUnit(1.25), IntMod(LayoutUnit(7.5), LayoutUnit(3.125)));
+ EXPECT_EQ(LayoutUnit(), IntMod(LayoutUnit(7.5), LayoutUnit(2.5)));
+ EXPECT_EQ(LayoutUnit(), IntMod(LayoutUnit(), LayoutUnit(123)));
+}
+
+TEST(LayoutUnitTest, LayoutMod) {
+#define CHECK_LAYOUT_MOD(a, b) EXPECT_EQ(a, (a / b) * b + LayoutMod(a, b))
+ CHECK_LAYOUT_MOD(LayoutUnit(55), LayoutUnit(10));
+ CHECK_LAYOUT_MOD(LayoutUnit(1234), LayoutUnit(789));
+ CHECK_LAYOUT_MOD(LayoutUnit::Max(), LayoutUnit::Max());
+ CHECK_LAYOUT_MOD(LayoutUnit::Max(), LayoutUnit::Min());
+ CHECK_LAYOUT_MOD(LayoutUnit::Min(), LayoutUnit::Max());
+ CHECK_LAYOUT_MOD(LayoutUnit::Min(), LayoutUnit::Min());
+
+ EXPECT_EQ(LayoutUnit(), LayoutMod(LayoutUnit(123), 2));
+ EXPECT_EQ(LayoutUnit(LayoutUnit::Epsilon()),
+ LayoutMod(LayoutUnit(123 + LayoutUnit::Epsilon()), 2));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/lifecycle_context_test.cc b/chromium/third_party/blink/renderer/platform/lifecycle_context_test.cc
index e14ba8373b8..1ee87524dc6 100644
--- a/chromium/third_party/blink/renderer/platform/lifecycle_context_test.cc
+++ b/chromium/third_party/blink/renderer/platform/lifecycle_context_test.cc
@@ -28,6 +28,7 @@
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/lifecycle_notifier.h"
#include "third_party/blink/renderer/platform/lifecycle_observer.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
namespace blink {
@@ -44,6 +45,9 @@ class DummyContext final
void Trace(blink::Visitor* visitor) override {
LifecycleNotifier<DummyContext, TestingObserver>::Trace(visitor);
}
+
+ // Make the protected method public for testing.
+ using LifecycleNotifier<DummyContext, TestingObserver>::ForEachObserver;
};
class TestingObserver final
@@ -90,7 +94,7 @@ class TestingObserver final
bool context_destroyed_called_;
};
-TEST(LifecycleContextTest, shouldObserveContextDestroyed) {
+TEST(LifecycleContextTest, ShouldObserveContextDestroyed) {
DummyContext* context = DummyContext::Create();
Persistent<TestingObserver> observer = TestingObserver::Create(context);
@@ -103,7 +107,7 @@ TEST(LifecycleContextTest, shouldObserveContextDestroyed) {
EXPECT_TRUE(observer->ContextDestroyedCalled());
}
-TEST(LifecycleContextTest, shouldNotObserveContextDestroyedIfUnobserve) {
+TEST(LifecycleContextTest, ShouldNotObserveContextDestroyedIfUnobserve) {
DummyContext* context = DummyContext::Create();
Persistent<TestingObserver> observer = TestingObserver::Create(context);
observer->Unobserve();
@@ -114,7 +118,7 @@ TEST(LifecycleContextTest, shouldNotObserveContextDestroyedIfUnobserve) {
EXPECT_FALSE(observer->ContextDestroyedCalled());
}
-TEST(LifecycleContextTest, observerRemovedDuringNotifyDestroyed) {
+TEST(LifecycleContextTest, ObserverRemovedDuringNotifyDestroyed) {
DummyContext* context = DummyContext::Create();
Persistent<TestingObserver> observer = TestingObserver::Create(context);
TestingObserver* inner_observer = TestingObserver::Create(context);
@@ -135,4 +139,49 @@ TEST(LifecycleContextTest, observerRemovedDuringNotifyDestroyed) {
EXPECT_TRUE(observer->ContextDestroyedCalled());
}
+// This is a regression test for http://crbug.com/854639.
+TEST(LifecycleContextTest, ShouldNotHitCFICheckOnIncrementalMarking) {
+ bool was_enabled = RuntimeEnabledFeatures::HeapIncrementalMarkingEnabled();
+ RuntimeEnabledFeatures::SetHeapIncrementalMarkingEnabled(true);
+ ThreadState* thread_state = ThreadState::Current();
+ thread_state->IncrementalMarkingStart(BlinkGC::GCReason::kTesting);
+
+ DummyContext* context = DummyContext::Create();
+
+ // This should not cause a CFI check failure.
+ Persistent<TestingObserver> observer = TestingObserver::Create(context);
+
+ EXPECT_FALSE(observer->ContextDestroyedCalled());
+ context->NotifyContextDestroyed();
+ EXPECT_TRUE(observer->ContextDestroyedCalled());
+ context = nullptr;
+
+ while (thread_state->GetGCState() ==
+ ThreadState::kIncrementalMarkingStepScheduled)
+ thread_state->IncrementalMarkingStep();
+ thread_state->IncrementalMarkingFinalize();
+
+ RuntimeEnabledFeatures::SetHeapIncrementalMarkingEnabled(was_enabled);
+}
+
+TEST(LifecycleContextTest, ForEachObserver) {
+ Persistent<DummyContext> context = DummyContext::Create();
+ Persistent<TestingObserver> observer = TestingObserver::Create(context);
+
+ HeapVector<Member<TestingObserver>> seen_observers;
+ context->ForEachObserver(
+ [&](TestingObserver* observer) { seen_observers.push_back(observer); });
+
+ ASSERT_EQ(1u, seen_observers.size());
+ EXPECT_EQ(observer.Get(), seen_observers[0].Get());
+
+ seen_observers.clear();
+ observer.Clear();
+ ThreadState::Current()->CollectAllGarbage();
+
+ context->ForEachObserver(
+ [&](TestingObserver* observer) { seen_observers.push_back(observer); });
+ ASSERT_EQ(0u, seen_observers.size());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/lifecycle_notifier.h b/chromium/third_party/blink/renderer/platform/lifecycle_notifier.h
index c1f3b60b94d..668002ef099 100644
--- a/chromium/third_party/blink/renderer/platform/lifecycle_notifier.h
+++ b/chromium/third_party/blink/renderer/platform/lifecycle_notifier.h
@@ -33,20 +33,22 @@
namespace blink {
+class LifecycleObserverBase;
+
template <typename T, typename Observer>
class LifecycleNotifier : public GarbageCollectedMixin {
public:
virtual ~LifecycleNotifier();
- void AddObserver(Observer*);
- void RemoveObserver(Observer*);
+ void AddObserver(LifecycleObserverBase*);
+ void RemoveObserver(LifecycleObserverBase*);
- // notifyContextDestroyed() should be explicitly dispatched from an
- // observed context to detach its observers, and if the observer kind
- // requires it, notify each observer by invoking contextDestroyed().
+ // NotifyContextDestroyed() should be explicitly dispatched from an
+ // observed context to detach its observers and, if the observer kind
+ // requires it, notify each observer by invoking ContextDestroyed().
//
- // When contextDestroyed() is called, it is supplied the context as
- // an argument, but the observer's lifecycleContext() is still valid
+ // When ContextDestroyed() is called, it is supplied the context as
+ // an argument, but the observer's LifecycleContext() is still valid
// and safe to use while handling the notification.
virtual void NotifyContextDestroyed();
@@ -61,19 +63,51 @@ class LifecycleNotifier : public GarbageCollectedMixin {
T* Context() { return static_cast<T*>(this); }
- using ObserverSet = HeapHashSet<WeakMember<Observer>>;
+ // Safely iterate over the registered lifecycle observers.
+ //
+ // Adding or removing observers is not allowed during iteration. The callable
+ // will only be called synchronously inside ForEachObserver().
+ //
+ // Sample usage:
+ // ForEachObserver([](ObserverType* observer) {
+ // observer->SomeMethod();
+ // });
+ template <typename ForEachCallable>
+ void ForEachObserver(const ForEachCallable& callable) const {
+ base::AutoReset<IterationState> scope(&iteration_state_, kAllowingNone);
+ for (LifecycleObserverBase* observer_base : observers_) {
+ Observer* observer = static_cast<Observer*>(observer_base);
+ callable(observer);
+ }
+ }
+
+ // ForEachObserver() variant that does not protect against memory corruption.
+ //
+ // Only used by SynchronousMutationNotifier::NotifyUpdateCharacterData. See
+ // implementation comment for why it is necessary.
+ //
+ // TODO(crbug.com/862900): Fix SynchronousMutationNotifier and remove this.
+ template <typename ForEachCallable>
+ void ForEachObserverWithoutChecks(const ForEachCallable& callable) const {
+ for (LifecycleObserverBase* observer_base : observers_) {
+ Observer* observer = static_cast<Observer*>(observer_base);
+ callable(observer);
+ }
+ }
+
+ private:
+ using ObserverSet = HeapHashSet<WeakMember<LifecycleObserverBase>>;
enum IterationState {
kAllowingNone = 0,
kAllowingAddition = 1,
kAllowingRemoval = 2,
kNotIterating = kAllowingAddition | kAllowingRemoval,
- kAllowPendingRemoval = 4,
};
// Iteration state is recorded while iterating the observer set,
// optionally barring add or remove mutations.
- IterationState iteration_state_;
+ mutable IterationState iteration_state_;
ObserverSet observers_;
};
@@ -135,7 +169,8 @@ inline void LifecycleNotifier<T, Observer>::NotifyContextDestroyed() {
base::AutoReset<IterationState> scope(&iteration_state_, kAllowingRemoval);
ObserverSet observers;
observers_.swap(observers);
- for (Observer* observer : observers) {
+ for (LifecycleObserverBase* observer_base : observers) {
+ Observer* observer = static_cast<Observer*>(observer_base);
DCHECK(observer->LifecycleContext() == Context());
ContextDestroyedNotifier<Observer, T>::Call(observer, Context());
observer->ClearContext();
@@ -143,19 +178,15 @@ inline void LifecycleNotifier<T, Observer>::NotifyContextDestroyed() {
}
template <typename T, typename Observer>
-inline void LifecycleNotifier<T, Observer>::AddObserver(Observer* observer) {
+inline void LifecycleNotifier<T, Observer>::AddObserver(
+ LifecycleObserverBase* observer) {
CHECK(iteration_state_ & kAllowingAddition);
observers_.insert(observer);
}
template <typename T, typename Observer>
-inline void LifecycleNotifier<T, Observer>::RemoveObserver(Observer* observer) {
- // If immediate removal isn't currently allowed,
- // |observer| is recorded for pending removal.
- if (iteration_state_ & kAllowPendingRemoval) {
- observers_.insert(observer);
- return;
- }
+inline void LifecycleNotifier<T, Observer>::RemoveObserver(
+ LifecycleObserverBase* observer) {
CHECK(iteration_state_ & kAllowingRemoval);
observers_.erase(observer);
}
diff --git a/chromium/third_party/blink/renderer/platform/lifecycle_observer.h b/chromium/third_party/blink/renderer/platform/lifecycle_observer.h
index 785bab5cfa3..491550573f6 100644
--- a/chromium/third_party/blink/renderer/platform/lifecycle_observer.h
+++ b/chromium/third_party/blink/renderer/platform/lifecycle_observer.h
@@ -34,8 +34,10 @@ namespace blink {
template <typename Context, typename Observer>
class LifecycleNotifier;
+class LifecycleObserverBase : public GarbageCollectedMixin {};
+
template <typename Context, typename Observer>
-class LifecycleObserver : public GarbageCollectedMixin {
+class LifecycleObserver : public LifecycleObserverBase {
public:
void Trace(blink::Visitor* visitor) override {
visitor->Trace(lifecycle_context_);
@@ -64,15 +66,13 @@ inline void LifecycleObserver<Context, Observer>::SetContext(Context* context) {
return;
if (lifecycle_context_) {
- static_cast<Notifier*>(lifecycle_context_)
- ->RemoveObserver(static_cast<Observer*>(this));
+ static_cast<Notifier*>(lifecycle_context_)->RemoveObserver(this);
}
lifecycle_context_ = context;
if (lifecycle_context_) {
- static_cast<Notifier*>(lifecycle_context_)
- ->AddObserver(static_cast<Observer*>(this));
+ static_cast<Notifier*>(lifecycle_context_)->AddObserver(this);
}
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/BUILD.gn b/chromium/third_party/blink/renderer/platform/loader/BUILD.gn
index 0ce462242b6..2e0307462b4 100644
--- a/chromium/third_party/blink/renderer/platform/loader/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/loader/BUILD.gn
@@ -42,6 +42,7 @@ blink_platform_sources("loader") {
"fetch/raw_resource.h",
"fetch/resource.cc",
"fetch/resource.h",
+ "fetch/resource_client.cc",
"fetch/resource_client.h",
"fetch/resource_client_walker.h",
"fetch/resource_error.cc",
@@ -71,6 +72,8 @@ blink_platform_sources("loader") {
"fetch/script_fetch_options.h",
"fetch/source_keyed_cached_metadata_handler.cc",
"fetch/source_keyed_cached_metadata_handler.h",
+ "fetch/stale_revalidation_resource_client.cc",
+ "fetch/stale_revalidation_resource_client.h",
"fetch/substitute_data.h",
"fetch/text_resource_decoder_options.cc",
"fetch/text_resource_decoder_options.h",
diff --git a/chromium/third_party/blink/renderer/platform/loader/DEPS b/chromium/third_party/blink/renderer/platform/loader/DEPS
index ebdf6764fc2..624703cb663 100644
--- a/chromium/third_party/blink/renderer/platform/loader/DEPS
+++ b/chromium/third_party/blink/renderer/platform/loader/DEPS
@@ -16,7 +16,6 @@ include_rules = [
"+third_party/blink/renderer/platform/cross_thread_copier.h",
"+third_party/blink/renderer/platform/cross_thread_functional.h",
"+third_party/blink/renderer/platform/crypto.h",
- "+third_party/blink/renderer/platform/decimal.h",
"+third_party/blink/renderer/platform/exported",
"+third_party/blink/renderer/platform/heap",
"+third_party/blink/renderer/platform/histogram.h",
diff --git a/chromium/third_party/blink/renderer/platform/loader/cors/cors.cc b/chromium/third_party/blink/renderer/platform/loader/cors/cors.cc
index ff219bdaad9..07a52467ced 100644
--- a/chromium/third_party/blink/renderer/platform/loader/cors/cors.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/cors/cors.cc
@@ -4,7 +4,9 @@
#include "third_party/blink/renderer/platform/loader/cors/cors.h"
+#include <memory>
#include <string>
+#include <utility>
#include "services/network/public/cpp/cors/cors.h"
#include "services/network/public/cpp/cors/preflight_cache.h"
@@ -68,7 +70,7 @@ std::unique_ptr<net::HttpRequestHeaders> CreateNetHttpRequestHeaders(
namespace CORS {
-base::Optional<network::mojom::CORSError> CheckAccess(
+base::Optional<network::CORSErrorStatus> CheckAccess(
const KURL& response_url,
const int response_status_code,
const HTTPHeaderMap& response_header,
@@ -85,7 +87,7 @@ base::Optional<network::mojom::CORSError> CheckAccess(
!privilege->block_local_access_from_local_origin_);
}
-base::Optional<network::mojom::CORSError> CheckPreflightAccess(
+base::Optional<network::CORSErrorStatus> CheckPreflightAccess(
const KURL& response_url,
const int response_status_code,
const HTTPHeaderMap& response_header,
@@ -121,7 +123,7 @@ base::Optional<network::mojom::CORSError> CheckPreflight(
return network::cors::CheckPreflight(preflight_response_status_code);
}
-base::Optional<network::mojom::CORSError> CheckExternalPreflight(
+base::Optional<network::CORSErrorStatus> CheckExternalPreflight(
const HTTPHeaderMap& response_header) {
return network::cors::CheckExternalPreflight(GetHeaderValue(
response_header, HTTPNames::Access_Control_Allow_External));
diff --git a/chromium/third_party/blink/renderer/platform/loader/cors/cors.h b/chromium/third_party/blink/renderer/platform/loader/cors/cors.h
index e50bd9dcfd9..80304420294 100644
--- a/chromium/third_party/blink/renderer/platform/loader/cors/cors.h
+++ b/chromium/third_party/blink/renderer/platform/loader/cors/cors.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_CORS_CORS_H_
#include "base/optional.h"
+#include "services/network/public/cpp/cors/cors_error_status.h"
#include "services/network/public/mojom/cors.mojom-shared.h"
#include "services/network/public/mojom/fetch_api.mojom-shared.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -23,14 +24,14 @@ namespace CORS {
// Thin wrapper functions below are for calling ::network::cors functions from
// Blink core. Once Out-of-renderer CORS is enabled, following functions will
// be removed.
-PLATFORM_EXPORT base::Optional<network::mojom::CORSError> CheckAccess(
+PLATFORM_EXPORT base::Optional<network::CORSErrorStatus> CheckAccess(
const KURL&,
const int response_status_code,
const HTTPHeaderMap&,
network::mojom::FetchCredentialsMode,
const SecurityOrigin&);
-PLATFORM_EXPORT base::Optional<network::mojom::CORSError> CheckPreflightAccess(
+PLATFORM_EXPORT base::Optional<network::CORSErrorStatus> CheckPreflightAccess(
const KURL&,
const int response_status_code,
const HTTPHeaderMap&,
@@ -43,8 +44,8 @@ PLATFORM_EXPORT base::Optional<network::mojom::CORSError> CheckRedirectLocation(
PLATFORM_EXPORT base::Optional<network::mojom::CORSError> CheckPreflight(
const int preflight_response_status_code);
-PLATFORM_EXPORT base::Optional<network::mojom::CORSError>
-CheckExternalPreflight(const HTTPHeaderMap&);
+PLATFORM_EXPORT base::Optional<network::CORSErrorStatus> CheckExternalPreflight(
+ const HTTPHeaderMap&);
PLATFORM_EXPORT bool IsCORSEnabledRequestMode(network::mojom::FetchRequestMode);
diff --git a/chromium/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc b/chromium/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc
index 03a485a9552..961b7677d39 100644
--- a/chromium/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/cors/cors_error_string.cc
@@ -4,8 +4,6 @@
#include "third_party/blink/renderer/platform/loader/cors/cors_error_string.h"
-#include "third_party/blink/renderer/platform/network/http_header_map.h"
-#include "third_party/blink/renderer/platform/network/http_names.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
@@ -29,7 +27,7 @@ bool IsInterestingStatusCode(int status_code) {
ErrorParameter CreateWrongParameter(network::mojom::CORSError error) {
return ErrorParameter(
error, GetInvalidURL(), GetInvalidURL(), 0 /* status_code */,
- HTTPHeaderMap(), *SecurityOrigin::CreateUnique(),
+ *SecurityOrigin::CreateUniqueOpaque(),
WebURLRequest::kRequestContextUnspecified, String(), true);
}
@@ -41,21 +39,11 @@ ErrorParameter ErrorParameter::Create(
const KURL& first_url,
const KURL& second_url,
const int status_code,
- const HTTPHeaderMap& header_map,
const SecurityOrigin& origin,
const WebURLRequest::RequestContext context) {
- String hint;
- switch (error_status.cors_error) {
- case network::mojom::CORSError::kMethodDisallowedByPreflightResponse:
- case network::mojom::CORSError::kHeaderDisallowedByPreflightResponse:
- DCHECK(!error_status.failed_parameter.empty());
- hint = String(error_status.failed_parameter.c_str());
- break;
- default:
- break;
- }
return ErrorParameter(error_status.cors_error, first_url, second_url,
- status_code, header_map, origin, context, hint, false);
+ status_code, origin, context,
+ String(error_status.failed_parameter.c_str()), false);
}
// static
@@ -63,7 +51,7 @@ ErrorParameter ErrorParameter::CreateForDisallowedByMode(
const KURL& request_url) {
return ErrorParameter(network::mojom::CORSError::kDisallowedByMode,
request_url, GetInvalidURL(), 0 /* status_code */,
- HTTPHeaderMap(), *SecurityOrigin::CreateUnique(),
+ *SecurityOrigin::CreateUniqueOpaque(),
WebURLRequest::kRequestContextUnspecified, String(),
false);
}
@@ -72,22 +60,21 @@ ErrorParameter ErrorParameter::CreateForDisallowedByMode(
ErrorParameter ErrorParameter::CreateForInvalidResponse(
const KURL& request_url,
const SecurityOrigin& origin) {
- return ErrorParameter(
- network::mojom::CORSError::kInvalidResponse, request_url, GetInvalidURL(),
- 0 /* status_code */, HTTPHeaderMap(), origin,
- WebURLRequest::kRequestContextUnspecified, String(), false);
+ return ErrorParameter(network::mojom::CORSError::kInvalidResponse,
+ request_url, GetInvalidURL(), 0 /* status_code */,
+ origin, WebURLRequest::kRequestContextUnspecified,
+ String(), false);
}
// static
ErrorParameter ErrorParameter::CreateForAccessCheck(
- const network::mojom::CORSError error,
+ const network::CORSErrorStatus& error_status,
const KURL& request_url,
int response_status_code,
- const HTTPHeaderMap& response_header_map,
const SecurityOrigin& origin,
const WebURLRequest::RequestContext context,
const KURL& redirect_url) {
- switch (error) {
+ switch (error_status.cors_error) {
case network::mojom::CORSError::kInvalidResponse:
case network::mojom::CORSError::kWildcardOriginNotAllowed:
case network::mojom::CORSError::kMissingAllowOriginHeader:
@@ -101,13 +88,14 @@ ErrorParameter ErrorParameter::CreateForAccessCheck(
case network::mojom::CORSError::kPreflightInvalidAllowOriginValue:
case network::mojom::CORSError::kPreflightAllowOriginMismatch:
case network::mojom::CORSError::kPreflightInvalidAllowCredentials:
- return ErrorParameter(error, request_url, redirect_url,
- response_status_code, response_header_map, origin,
- context, String(), false);
+ return ErrorParameter(error_status.cors_error, request_url, redirect_url,
+ response_status_code, origin, context,
+ String(error_status.failed_parameter.c_str()),
+ false);
default:
NOTREACHED();
}
- return CreateWrongParameter(error);
+ return CreateWrongParameter(error_status.cors_error);
}
// static
@@ -115,7 +103,7 @@ ErrorParameter ErrorParameter::CreateForPreflightStatusCheck(
int response_status_code) {
return ErrorParameter(network::mojom::CORSError::kPreflightInvalidStatus,
GetInvalidURL(), GetInvalidURL(), response_status_code,
- HTTPHeaderMap(), *SecurityOrigin::CreateUnique(),
+ *SecurityOrigin::CreateUniqueOpaque(),
WebURLRequest::kRequestContextUnspecified, String(),
false);
}
@@ -124,25 +112,25 @@ ErrorParameter ErrorParameter::CreateForPreflightStatusCheck(
ErrorParameter ErrorParameter::CreateForDisallowedRedirect() {
return ErrorParameter(
network::mojom::CORSError::kPreflightDisallowedRedirect, GetInvalidURL(),
- GetInvalidURL(), 0, HTTPHeaderMap(), *SecurityOrigin::CreateUnique(),
+ GetInvalidURL(), 0, *SecurityOrigin::CreateUniqueOpaque(),
WebURLRequest::kRequestContextUnspecified, String(), false);
}
// static
ErrorParameter ErrorParameter::CreateForExternalPreflightCheck(
- const network::mojom::CORSError error,
- const HTTPHeaderMap& response_header_map) {
- switch (error) {
+ const network::CORSErrorStatus& error) {
+ switch (error.cors_error) {
case network::mojom::CORSError::kPreflightMissingAllowExternal:
case network::mojom::CORSError::kPreflightInvalidAllowExternal:
- return ErrorParameter(
- error, GetInvalidURL(), GetInvalidURL(), 0 /* status_code */,
- response_header_map, *SecurityOrigin::CreateUnique(),
- WebURLRequest::kRequestContextUnspecified, String(), false);
+ return ErrorParameter(error.cors_error, GetInvalidURL(), GetInvalidURL(),
+ 0 /* status_code */,
+ *SecurityOrigin::CreateUniqueOpaque(),
+ WebURLRequest::kRequestContextUnspecified,
+ error.failed_parameter.c_str(), false);
default:
NOTREACHED();
}
- return CreateWrongParameter(error);
+ return CreateWrongParameter(error.cors_error);
}
// static
@@ -156,7 +144,7 @@ ErrorParameter ErrorParameter::CreateForPreflightResponseCheck(
case network::mojom::CORSError::kHeaderDisallowedByPreflightResponse:
return ErrorParameter(
error, GetInvalidURL(), GetInvalidURL(), 0 /* status_code */,
- HTTPHeaderMap(), *SecurityOrigin::CreateUnique(),
+ *SecurityOrigin::CreateUniqueOpaque(),
WebURLRequest::kRequestContextUnspecified, hint, false);
default:
NOTREACHED();
@@ -174,7 +162,7 @@ ErrorParameter ErrorParameter::CreateForRedirectCheck(
case network::mojom::CORSError::kRedirectContainsCredentials:
return ErrorParameter(
error, request_url, redirect_url, 0 /* status_code */,
- HTTPHeaderMap(), *SecurityOrigin::CreateUnique(),
+ *SecurityOrigin::CreateUniqueOpaque(),
WebURLRequest::kRequestContextUnspecified, String(), false);
default:
NOTREACHED();
@@ -186,7 +174,6 @@ ErrorParameter::ErrorParameter(const network::mojom::CORSError error,
const KURL& first_url,
const KURL& second_url,
const int status_code,
- const HTTPHeaderMap& header_map,
const SecurityOrigin& origin,
const WebURLRequest::RequestContext context,
const String& hint,
@@ -195,7 +182,6 @@ ErrorParameter::ErrorParameter(const network::mojom::CORSError error,
first_url(first_url),
second_url(second_url),
status_code(status_code),
- header_map(header_map),
origin(origin),
context(context),
hint(hint),
@@ -209,6 +195,9 @@ String GetErrorString(const ErrorParameter& param) {
static const char kPreflightInformation[] =
"Response to preflight request doesn't pass access control check: ";
+ using CORSError = network::mojom::CORSError;
+ const auto& hint = param.hint;
+
if (param.unknown)
return String::Format("CORS error, code %d", static_cast<int>(param.error));
@@ -221,24 +210,23 @@ String GetErrorString(const ErrorParameter& param) {
: String();
switch (param.error) {
- case network::mojom::CORSError::kDisallowedByMode:
+ case CORSError::kDisallowedByMode:
return String::Format(
"Failed to load '%s': Cross origin requests are not allowed by "
"request mode.",
param.first_url.GetString().Utf8().data());
- case network::mojom::CORSError::kInvalidResponse:
+ case CORSError::kInvalidResponse:
return String::Format(
"%sInvalid response. Origin '%s' is therefore not allowed access.",
redirect_denied.Utf8().data(), param.origin.ToString().Utf8().data());
- case network::mojom::CORSError::kWildcardOriginNotAllowed:
- case network::mojom::CORSError::kPreflightWildcardOriginNotAllowed:
+ case CORSError::kWildcardOriginNotAllowed:
+ case CORSError::kPreflightWildcardOriginNotAllowed:
return String::Format(
"%s%sThe value of the 'Access-Control-Allow-Origin' header in the "
"response must not be the wildcard '*' when the request's "
"credentials mode is 'include'. Origin '%s' is therefore not allowed "
"access.%s",
- param.error ==
- network::mojom::CORSError::kPreflightWildcardOriginNotAllowed
+ param.error == CORSError::kPreflightWildcardOriginNotAllowed
? kPreflightInformation
: "",
redirect_denied.Utf8().data(), param.origin.ToString().Utf8().data(),
@@ -246,14 +234,13 @@ String GetErrorString(const ErrorParameter& param) {
? " The credentials mode of requests initiated by the "
"XMLHttpRequest is controlled by the withCredentials attribute."
: "");
- case network::mojom::CORSError::kMissingAllowOriginHeader:
- case network::mojom::CORSError::kPreflightMissingAllowOriginHeader:
+ case CORSError::kMissingAllowOriginHeader:
+ case CORSError::kPreflightMissingAllowOriginHeader:
return String::Format(
"%s%sNo 'Access-Control-Allow-Origin' header is present on the "
"requested resource. Origin '%s' is therefore not allowed access."
"%s%s",
- param.error ==
- network::mojom::CORSError::kPreflightMissingAllowOriginHeader
+ param.error == CORSError::kPreflightMissingAllowOriginHeader
? kPreflightInformation
: "",
redirect_denied.Utf8().data(), param.origin.ToString().Utf8().data(),
@@ -267,124 +254,106 @@ String GetErrorString(const ErrorParameter& param) {
? " If an opaque response serves your needs, set the request's "
"mode to 'no-cors' to fetch the resource with CORS disabled."
: "");
- case network::mojom::CORSError::kMultipleAllowOriginValues:
- case network::mojom::CORSError::kPreflightMultipleAllowOriginValues:
+ case CORSError::kMultipleAllowOriginValues:
+ case CORSError::kPreflightMultipleAllowOriginValues:
return String::Format(
"%s%sThe 'Access-Control-Allow-Origin' header contains multiple "
"values '%s', but only one is allowed. Origin '%s' is therefore not "
"allowed access.%s",
- param.error ==
- network::mojom::CORSError::kPreflightMultipleAllowOriginValues
+ param.error == CORSError::kPreflightMultipleAllowOriginValues
? kPreflightInformation
: "",
- redirect_denied.Utf8().data(),
- param.header_map.Get(HTTPNames::Access_Control_Allow_Origin)
- .Utf8()
- .data(),
+ redirect_denied.Utf8().data(), hint.Utf8().data(),
param.origin.ToString().Utf8().data(),
param.context == WebURLRequest::kRequestContextFetch
? kNoCorsInformation
: "");
- case network::mojom::CORSError::kInvalidAllowOriginValue:
- case network::mojom::CORSError::kPreflightInvalidAllowOriginValue:
+ case CORSError::kInvalidAllowOriginValue:
+ case CORSError::kPreflightInvalidAllowOriginValue:
return String::Format(
"%s%sThe 'Access-Control-Allow-Origin' header contains the invalid "
"value '%s'. Origin '%s' is therefore not allowed access.%s",
- param.error ==
- network::mojom::CORSError::kPreflightInvalidAllowOriginValue
+ param.error == CORSError::kPreflightInvalidAllowOriginValue
? kPreflightInformation
: "",
- redirect_denied.Utf8().data(),
- param.header_map.Get(HTTPNames::Access_Control_Allow_Origin)
- .Utf8()
- .data(),
+ redirect_denied.Utf8().data(), hint.Utf8().data(),
param.origin.ToString().Utf8().data(),
param.context == WebURLRequest::kRequestContextFetch
? kNoCorsInformation
: "");
- case network::mojom::CORSError::kAllowOriginMismatch:
- case network::mojom::CORSError::kPreflightAllowOriginMismatch:
+ case CORSError::kAllowOriginMismatch:
+ case CORSError::kPreflightAllowOriginMismatch:
return String::Format(
"%s%sThe 'Access-Control-Allow-Origin' header has a value '%s' that "
"is not equal to the supplied origin. Origin '%s' is therefore not "
"allowed access.%s",
- param.error ==
- network::mojom::CORSError::kPreflightAllowOriginMismatch
+ param.error == CORSError::kPreflightAllowOriginMismatch
? kPreflightInformation
: "",
- redirect_denied.Utf8().data(),
- param.header_map.Get(HTTPNames::Access_Control_Allow_Origin)
- .Utf8()
- .data(),
+ redirect_denied.Utf8().data(), hint.Utf8().data(),
param.origin.ToString().Utf8().data(),
param.context == WebURLRequest::kRequestContextFetch
? kNoCorsInformation
: "");
- case network::mojom::CORSError::kInvalidAllowCredentials:
- case network::mojom::CORSError::kPreflightInvalidAllowCredentials:
+ case CORSError::kInvalidAllowCredentials:
+ case CORSError::kPreflightInvalidAllowCredentials:
return String::Format(
"%s%sThe value of the 'Access-Control-Allow-Credentials' header in "
"the response is '%s' which must be 'true' when the request's "
"credentials mode is 'include'. Origin '%s' is therefore not allowed "
"access.%s",
- param.error ==
- network::mojom::CORSError::kPreflightInvalidAllowCredentials
+ param.error == CORSError::kPreflightInvalidAllowCredentials
? kPreflightInformation
: "",
- redirect_denied.Utf8().data(),
- param.header_map.Get(HTTPNames::Access_Control_Allow_Credentials)
- .Utf8()
- .data(),
+ redirect_denied.Utf8().data(), hint.Utf8().data(),
param.origin.ToString().Utf8().data(),
(param.context == WebURLRequest::kRequestContextXMLHttpRequest
? " The credentials mode of requests initiated by the "
"XMLHttpRequest is controlled by the withCredentials "
"attribute."
: ""));
- case network::mojom::CORSError::kPreflightInvalidStatus:
+ case CORSError::kPreflightInvalidStatus:
return String("Response for preflight does not have HTTP ok status.");
- case network::mojom::CORSError::kPreflightDisallowedRedirect:
+ case CORSError::kPreflightDisallowedRedirect:
return String("Response for preflight is invalid (redirect)");
- case network::mojom::CORSError::kPreflightMissingAllowExternal:
+ case CORSError::kPreflightMissingAllowExternal:
return String(
"No 'Access-Control-Allow-External' header was present in the "
"preflight response for this external request (This is an "
"experimental header which is defined in "
"'https://wicg.github.io/cors-rfc1918/').");
- case network::mojom::CORSError::kPreflightInvalidAllowExternal:
+ case CORSError::kPreflightInvalidAllowExternal:
return String::Format(
"The 'Access-Control-Allow-External' header in the preflight "
"response for this external request had a value of '%s', not 'true' "
"(This is an experimental header which is defined in "
"'https://wicg.github.io/cors-rfc1918/').",
- param.header_map.Get(HTTPNames::Access_Control_Allow_External)
- .Utf8()
- .data());
- case network::mojom::CORSError::kInvalidAllowMethodsPreflightResponse:
+ hint.Utf8().data());
+ case CORSError::kInvalidAllowMethodsPreflightResponse:
return String(
"Cannot parse Access-Control-Allow-Methods response header field in "
"preflight response.");
- case network::mojom::CORSError::kInvalidAllowHeadersPreflightResponse:
+ case CORSError::kInvalidAllowHeadersPreflightResponse:
return String(
"Cannot parse Access-Control-Allow-Headers response header field in "
"preflight response.");
- case network::mojom::CORSError::kMethodDisallowedByPreflightResponse:
+ case CORSError::kMethodDisallowedByPreflightResponse:
return String::Format(
"Method %s is not allowed by Access-Control-Allow-Methods in "
"preflight response.",
- param.hint.Utf8().data());
- case network::mojom::CORSError::kHeaderDisallowedByPreflightResponse:
+ hint.Utf8().data());
+ case CORSError::kHeaderDisallowedByPreflightResponse:
return String::Format(
"Request header field %s is not allowed by "
"Access-Control-Allow-Headers in preflight response.",
- param.hint.Utf8().data());
- case network::mojom::CORSError::kRedirectDisallowedScheme:
+ hint.Utf8().data());
+ case CORSError::kRedirectDisallowedScheme:
return String::Format(
"%sRedirect location '%s' has a disallowed scheme for cross-origin "
"requests.",
redirect_denied.Utf8().data(),
param.second_url.GetString().Utf8().data());
- case network::mojom::CORSError::kRedirectContainsCredentials:
+ case CORSError::kRedirectContainsCredentials:
return String::Format(
"%sRedirect location '%s' contains a username and password, which is "
"disallowed for cross-origin requests.",
diff --git a/chromium/third_party/blink/renderer/platform/loader/cors/cors_error_string.h b/chromium/third_party/blink/renderer/platform/loader/cors/cors_error_string.h
index 35dab0a940c..6f6396beca2 100644
--- a/chromium/third_party/blink/renderer/platform/loader/cors/cors_error_string.h
+++ b/chromium/third_party/blink/renderer/platform/loader/cors/cors_error_string.h
@@ -14,7 +14,6 @@
namespace blink {
-class HTTPHeaderMap;
class SecurityOrigin;
// CORS error strings related utility functions.
@@ -28,7 +27,6 @@ struct PLATFORM_EXPORT ErrorParameter {
const KURL& first_url,
const KURL& second_url,
const int status_code,
- const HTTPHeaderMap&,
const SecurityOrigin&,
const WebURLRequest::RequestContext);
@@ -43,10 +41,9 @@ struct PLATFORM_EXPORT ErrorParameter {
// |error| for redirect check needs to specify a valid |redirect_url|. The
// |redirect_url| can be omitted not to include redirect related information.
static ErrorParameter CreateForAccessCheck(
- const network::mojom::CORSError,
+ const network::CORSErrorStatus&,
const KURL& request_url,
int response_status_code,
- const HTTPHeaderMap& response_header_map,
const SecurityOrigin&,
const WebURLRequest::RequestContext,
const KURL& redirect_url = KURL());
@@ -61,8 +58,7 @@ struct PLATFORM_EXPORT ErrorParameter {
// Creates an ErrorParameter for an error that CORS::CheckExternalPreflight()
// returns.
static ErrorParameter CreateForExternalPreflightCheck(
- const network::mojom::CORSError,
- const HTTPHeaderMap& response_header_map);
+ const network::CORSErrorStatus&);
// Creates an ErrorParameter for an error that is related to CORS-preflight
// response checks.
@@ -84,7 +80,6 @@ struct PLATFORM_EXPORT ErrorParameter {
const KURL& first_url,
const KURL& second_url,
const int status_code,
- const HTTPHeaderMap&,
const SecurityOrigin&,
const WebURLRequest::RequestContext,
const String& hint,
@@ -95,10 +90,10 @@ struct PLATFORM_EXPORT ErrorParameter {
const KURL& first_url;
const KURL& second_url;
const int status_code;
- const HTTPHeaderMap& header_map;
const SecurityOrigin& origin;
const WebURLRequest::RequestContext context;
- const String& hint;
+ // Do not use a reference here. See https://crbug.com/851419.
+ const String hint;
// Set to true when an ErrorParameter was created in a wrong way. Used in
// GetErrorString() to be robust for coding errors.
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc
index 6a3d226f8d3..961f89d9ffc 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.cc
@@ -6,11 +6,11 @@
#include "base/macros.h"
#include "third_party/blink/public/common/client_hints/client_hints.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_response.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/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
namespace blink {
@@ -72,12 +72,9 @@ void ClientHintsPreferences::UpdateFromAcceptClientHintsHeader(
if (header_value.IsEmpty())
return;
- // If the persistent client hint feature is enabled, then client hints
- // should be allowed only on secure URLs.
- if (blink::RuntimeEnabledFeatures::ClientHintsPersistentEnabled() &&
- !IsClientHintsAllowed(url)) {
+ // Client hints should be allowed only on secure URLs.
+ if (!IsClientHintsAllowed(url))
return;
- }
WebEnabledClientHints new_enabled_types;
@@ -101,43 +98,25 @@ void ClientHintsPreferences::UpdateFromAcceptClientHintsHeader(
}
}
-// static
-void ClientHintsPreferences::UpdatePersistentHintsFromHeaders(
- const ResourceResponse& response,
- Context* context,
- WebEnabledClientHints& enabled_hints,
- TimeDelta* persist_duration) {
- *persist_duration = base::TimeDelta();
-
- if (response.WasCached())
- return;
-
- String accept_ch_header_value =
- response.HttpHeaderField(HTTPNames::Accept_CH);
- String accept_ch_lifetime_header_value =
- response.HttpHeaderField(HTTPNames::Accept_CH_Lifetime);
-
- if (!RuntimeEnabledFeatures::ClientHintsPersistentEnabled() ||
- accept_ch_header_value.IsEmpty() ||
- accept_ch_lifetime_header_value.IsEmpty()) {
+void ClientHintsPreferences::UpdateFromAcceptClientHintsLifetimeHeader(
+ const String& header_value,
+ const KURL& url,
+ Context* context) {
+ if (header_value.IsEmpty())
return;
- }
- const KURL url = response.Url();
+ // Client hints should be allowed only on secure URLs.
if (!IsClientHintsAllowed(url))
return;
bool conversion_ok = false;
- int64_t persist_duration_seconds =
- accept_ch_lifetime_header_value.ToInt64Strict(&conversion_ok);
+ int64_t persist_duration_seconds = header_value.ToInt64Strict(&conversion_ok);
if (!conversion_ok || persist_duration_seconds <= 0)
return;
- *persist_duration = TimeDelta::FromSeconds(persist_duration_seconds);
+ persist_duration_ = TimeDelta::FromSeconds(persist_duration_seconds);
if (context)
context->CountPersistentClientHintHeaders();
-
- ParseAcceptChHeader(accept_ch_header_value, enabled_hints);
}
// static
@@ -147,4 +126,12 @@ bool ClientHintsPreferences::IsClientHintsAllowed(const KURL& url) {
SecurityOrigin::Create(url)->IsLocalhost());
}
+WebEnabledClientHints ClientHintsPreferences::GetWebEnabledClientHints() const {
+ return enabled_hints_;
+}
+
+base::TimeDelta ClientHintsPreferences::GetPersistDuration() const {
+ return persist_duration_;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h b/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h
index 6900745d56e..270f8bfd8cd 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h
@@ -14,7 +14,6 @@
namespace blink {
class KURL;
-class ResourceResponse;
// TODO (tbansal): Remove PLATFORM_EXPORT, and pass WebClientHintsType
// everywhere.
@@ -50,26 +49,25 @@ class PLATFORM_EXPORT ClientHintsPreferences {
enabled_hints_.SetIsEnabled(type, true);
}
- // Parses the client hints headers, and populates |enabled_hints| with the
- // client hint preferences that should be persisted for |persist_duration|.
- // |persist_duration| should be non-null.
- // If there are no client hints that need to be persisted,
- // |persist_duration| is not set, otherwise it is set to the duration for
- // which the client hint preferences should be persisted.
- // UpdatePersistentHintsFromHeaders may be called for all responses
- // received (including subresources). |context| may be null.
- static void UpdatePersistentHintsFromHeaders(
- const ResourceResponse&,
- Context*,
- WebEnabledClientHints& enabled_hints,
- TimeDelta* persist_duration);
+ // Parses the accept-ch-lifetime header, and populates |this| with the client
+ // hints persistence duration. |url| is the URL of the resource whose response
+ // included the |header_value|. |context| may be null. If client hints are not
+ // allowed for |url|, then |this| would not be updated.
+ void UpdateFromAcceptClientHintsLifetimeHeader(const String& header_value,
+ const KURL& url,
+ Context* context);
// Returns true if client hints are allowed for the provided KURL. Client
// hints are allowed only on HTTP URLs that belong to secure contexts.
static bool IsClientHintsAllowed(const KURL&);
+ WebEnabledClientHints GetWebEnabledClientHints() const;
+
+ base::TimeDelta GetPersistDuration() const;
+
private:
WebEnabledClientHints enabled_hints_;
+ base::TimeDelta persist_duration_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc
index dde2ec04ca4..67dc2fa7390 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/client_hints_preferences_test.cc
@@ -82,6 +82,58 @@ TEST_F(ClientHintsPreferencesTest, BasicSecure) {
}
}
+// Verify that the set of enabled client hints is updated every time Update*()
+// methods are called.
+TEST_F(ClientHintsPreferencesTest, SecureEnabledTypesAreUpdated) {
+ ClientHintsPreferences preferences;
+ const KURL kurl(String::FromUTF8("https://www.google.com/"));
+ preferences.UpdateFromAcceptClientHintsHeader("rtt, downlink", kurl, nullptr);
+
+ EXPECT_EQ(base::TimeDelta(), preferences.GetPersistDuration());
+ EXPECT_FALSE(
+ preferences.ShouldSend(mojom::WebClientHintsType::kResourceWidth));
+ EXPECT_FALSE(preferences.ShouldSend(mojom::WebClientHintsType::kDpr));
+ EXPECT_FALSE(
+ preferences.ShouldSend(mojom::WebClientHintsType::kViewportWidth));
+ EXPECT_TRUE(preferences.ShouldSend(mojom::WebClientHintsType::kRtt));
+ EXPECT_TRUE(preferences.ShouldSend(mojom::WebClientHintsType::kDownlink));
+ EXPECT_FALSE(preferences.ShouldSend(mojom::WebClientHintsType::kEct));
+
+ // Calling UpdateFromAcceptClientHintsHeader with empty header should have
+ // no impact on client hint preferences.
+ preferences.UpdateFromAcceptClientHintsHeader("", kurl, nullptr);
+ EXPECT_EQ(base::TimeDelta(), preferences.GetPersistDuration());
+ EXPECT_FALSE(
+ preferences.ShouldSend(mojom::WebClientHintsType::kResourceWidth));
+ EXPECT_TRUE(preferences.ShouldSend(mojom::WebClientHintsType::kRtt));
+ EXPECT_TRUE(preferences.ShouldSend(mojom::WebClientHintsType::kDownlink));
+ EXPECT_FALSE(preferences.ShouldSend(mojom::WebClientHintsType::kEct));
+
+ // Calling UpdateFromAcceptClientHintsHeader with an invalid header should
+ // have no impact on client hint preferences.
+ preferences.UpdateFromAcceptClientHintsHeader("foobar", kurl, nullptr);
+ EXPECT_EQ(base::TimeDelta(), preferences.GetPersistDuration());
+ EXPECT_FALSE(
+ preferences.ShouldSend(mojom::WebClientHintsType::kResourceWidth));
+ EXPECT_TRUE(preferences.ShouldSend(mojom::WebClientHintsType::kRtt));
+ EXPECT_TRUE(preferences.ShouldSend(mojom::WebClientHintsType::kDownlink));
+ EXPECT_FALSE(preferences.ShouldSend(mojom::WebClientHintsType::kEct));
+
+ // Calling UpdateFromAcceptClientHintsHeader with "width" header should
+ // have no impact on already enabled client hint preferences.
+ preferences.UpdateFromAcceptClientHintsHeader("width", kurl, nullptr);
+ EXPECT_EQ(base::TimeDelta(), preferences.GetPersistDuration());
+ EXPECT_TRUE(
+ preferences.ShouldSend(mojom::WebClientHintsType::kResourceWidth));
+ EXPECT_TRUE(preferences.ShouldSend(mojom::WebClientHintsType::kRtt));
+ EXPECT_TRUE(preferences.ShouldSend(mojom::WebClientHintsType::kDownlink));
+ EXPECT_FALSE(preferences.ShouldSend(mojom::WebClientHintsType::kEct));
+
+ preferences.UpdateFromAcceptClientHintsLifetimeHeader("1000", kurl, nullptr);
+ EXPECT_EQ(base::TimeDelta::FromSeconds(1000),
+ preferences.GetPersistDuration());
+}
+
TEST_F(ClientHintsPreferencesTest, Insecure) {
for (const auto& use_secure_url : {false, true}) {
ClientHintsPreferences preferences;
@@ -94,64 +146,83 @@ TEST_F(ClientHintsPreferencesTest, Insecure) {
}
}
-TEST_F(ClientHintsPreferencesTest, PersistentHints) {
+// Verify that the client hints header and the lifetime header is parsed
+// correctly.
+TEST_F(ClientHintsPreferencesTest, ParseHeaders) {
struct TestCase {
- bool enable_persistent_runtime_feature;
const char* accept_ch_header_value;
const char* accept_lifetime_header_value;
int64_t expect_persist_duration_seconds;
+ bool expect_device_memory;
+ bool expect_width;
+ bool expect_dpr;
+ bool expect_viewport_width;
+ bool expect_rtt;
+ bool expect_downlink;
+ bool expect_ect;
} test_cases[] = {
- {true, "width, dpr, viewportWidth", "", 0},
- {true, "width, dpr, viewportWidth", "-1000", 0},
- {true, "width, dpr, viewportWidth", "1000s", 0},
- {true, "width, dpr, viewportWidth", "1000.5", 0},
- {false, "width, dpr, viewportWidth", "1000", 0},
- {true, "width, dpr, rtt, downlink, ect", "1000", 1000},
+ {"width, dpr, viewportWidth", "", 0, false, true, true, false, false,
+ false, false},
+ {"width, dpr, viewportWidth", "-1000", 0, false, true, true, false, false,
+ false, false},
+ {"width, dpr, viewportWidth", "1000s", 0, false, true, true, false, false,
+ false, false},
+ {"width, dpr, viewportWidth", "1000.5", 0, false, true, true, false,
+ false, false, false},
+ {"width, dpr, rtt, downlink, ect", "1000", 1000, false, true, true, false,
+ true, true, true},
+ {"device-memory", "-1000", 0, true, false, false, false, false, false,
+ false},
+ {"dpr rtt", "1000", 1000, false, false, false, false, false, false,
+ false},
};
for (const auto& test : test_cases) {
- WebRuntimeFeatures::EnableClientHintsPersistent(
- test.enable_persistent_runtime_feature);
- WebEnabledClientHints enabled_types;
- TimeDelta persist_duration;
+ ClientHintsPreferences preferences;
+ WebEnabledClientHints enabled_types =
+ preferences.GetWebEnabledClientHints();
+ EXPECT_FALSE(
+ enabled_types.IsEnabled(mojom::WebClientHintsType::kDeviceMemory));
+ EXPECT_FALSE(enabled_types.IsEnabled(mojom::WebClientHintsType::kDpr));
+ EXPECT_FALSE(
+ enabled_types.IsEnabled(mojom::WebClientHintsType::kResourceWidth));
+ EXPECT_FALSE(
+ enabled_types.IsEnabled(mojom::WebClientHintsType::kViewportWidth));
+ EXPECT_FALSE(enabled_types.IsEnabled(mojom::WebClientHintsType::kRtt));
+ EXPECT_FALSE(enabled_types.IsEnabled(mojom::WebClientHintsType::kDownlink));
+ EXPECT_FALSE(enabled_types.IsEnabled(mojom::WebClientHintsType::kEct));
+ TimeDelta persist_duration = preferences.GetPersistDuration();
+ EXPECT_EQ(base::TimeDelta(), persist_duration);
const KURL kurl(String::FromUTF8("https://www.google.com/"));
+ preferences.UpdateFromAcceptClientHintsHeader(test.accept_ch_header_value,
+ kurl, nullptr);
+ preferences.UpdateFromAcceptClientHintsLifetimeHeader(
+ test.accept_lifetime_header_value, kurl, nullptr);
- ResourceResponse response(kurl);
- response.SetHTTPHeaderField(HTTPNames::Accept_CH,
- test.accept_ch_header_value);
- response.SetHTTPHeaderField(HTTPNames::Accept_CH_Lifetime,
- test.accept_lifetime_header_value);
+ enabled_types = preferences.GetWebEnabledClientHints();
+ persist_duration = preferences.GetPersistDuration();
- ClientHintsPreferences::UpdatePersistentHintsFromHeaders(
- response, nullptr, enabled_types, &persist_duration);
EXPECT_EQ(test.expect_persist_duration_seconds,
persist_duration.InSeconds());
- if (test.expect_persist_duration_seconds > 0) {
- EXPECT_FALSE(
- enabled_types.IsEnabled(mojom::WebClientHintsType::kDeviceMemory));
- EXPECT_TRUE(enabled_types.IsEnabled(mojom::WebClientHintsType::kDpr));
- EXPECT_TRUE(
- enabled_types.IsEnabled(mojom::WebClientHintsType::kResourceWidth));
- EXPECT_FALSE(
- enabled_types.IsEnabled(mojom::WebClientHintsType::kViewportWidth));
- EXPECT_TRUE(enabled_types.IsEnabled(mojom::WebClientHintsType::kRtt));
- EXPECT_TRUE(
- enabled_types.IsEnabled(mojom::WebClientHintsType::kDownlink));
- EXPECT_TRUE(enabled_types.IsEnabled(mojom::WebClientHintsType::kEct));
- } else {
- EXPECT_FALSE(
- enabled_types.IsEnabled(mojom::WebClientHintsType::kDeviceMemory));
- EXPECT_FALSE(enabled_types.IsEnabled(mojom::WebClientHintsType::kDpr));
- EXPECT_FALSE(
- enabled_types.IsEnabled(mojom::WebClientHintsType::kResourceWidth));
- EXPECT_FALSE(
- enabled_types.IsEnabled(mojom::WebClientHintsType::kViewportWidth));
- EXPECT_FALSE(enabled_types.IsEnabled(mojom::WebClientHintsType::kRtt));
- EXPECT_FALSE(
- enabled_types.IsEnabled(mojom::WebClientHintsType::kDownlink));
- EXPECT_FALSE(enabled_types.IsEnabled(mojom::WebClientHintsType::kEct));
- }
+
+ EXPECT_EQ(
+ test.expect_device_memory,
+ enabled_types.IsEnabled(mojom::WebClientHintsType::kDeviceMemory));
+ EXPECT_EQ(test.expect_dpr,
+ enabled_types.IsEnabled(mojom::WebClientHintsType::kDpr));
+ EXPECT_EQ(
+ test.expect_width,
+ enabled_types.IsEnabled(mojom::WebClientHintsType::kResourceWidth));
+ EXPECT_EQ(
+ test.expect_viewport_width,
+ enabled_types.IsEnabled(mojom::WebClientHintsType::kViewportWidth));
+ EXPECT_EQ(test.expect_rtt,
+ enabled_types.IsEnabled(mojom::WebClientHintsType::kRtt));
+ EXPECT_EQ(test.expect_downlink,
+ enabled_types.IsEnabled(mojom::WebClientHintsType::kDownlink));
+ EXPECT_EQ(test.expect_ect,
+ enabled_types.IsEnabled(mojom::WebClientHintsType::kEct));
}
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc
index 345744206a4..2eb30104d4c 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.cc
@@ -86,8 +86,6 @@ void FetchContext::DispatchDidReceiveData(unsigned long, const char*, int) {}
void FetchContext::DispatchDidReceiveEncodedData(unsigned long, int) {}
-void FetchContext::DispatchDidDownloadData(unsigned long, int, int) {}
-
void FetchContext::DispatchDidDownloadToBlob(unsigned long identifier,
BlobDataHandle*) {}
@@ -112,7 +110,7 @@ void FetchContext::DidLoadResource(Resource*) {}
void FetchContext::AddResourceTiming(const ResourceTimingInfo&) {}
-void FetchContext::AddWarningConsoleMessage(const String&, LogSource) const {}
+void FetchContext::AddInfoConsoleMessage(const String&, LogSource) const {}
void FetchContext::AddErrorConsoleMessage(const String&, LogSource) const {}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.h b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
index 5ed4a1b91eb..1b713826046 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
@@ -31,12 +31,16 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_FETCH_CONTEXT_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_FETCH_CONTEXT_H_
+#include <memory>
+
#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "services/network/public/mojom/request_context_frame_type.mojom-shared.h"
+#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-blink.h"
#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
+#include "third_party/blink/public/platform/scheduler/web_resource_loading_task_runner_handle.h"
#include "third_party/blink/public/platform/web_application_cache_host.h"
#include "third_party/blink/public/platform/web_url_loader.h"
#include "third_party/blink/public/platform/web_url_request.h"
@@ -81,13 +85,14 @@ class PLATFORM_EXPORT FetchContext
// This enum corresponds to blink::MessageSource. We have this not to
// introduce any dependency to core/.
//
- // Currently only kJSMessageSource is used, but not to impress readers that
- // AddConsoleMessage() call from FetchContext() should always use it, which is
- // not true, we ask users of the Add.*ConsoleMessage() methods to explicitly
- // specify the MessageSource to use.
+ // Currently only kJSMessageSource, kSecurityMessageSource and
+ // kOtherMessageSource are used, but not to impress readers that
+ // AddConsoleMessage() call from FetchContext() should always use them,
+ // which is not true, we ask users of the Add.*ConsoleMessage() methods
+ // to explicitly specify the MessageSource to use.
//
// Extend this when needed.
- enum LogSource { kJSSource };
+ enum LogSource { kJSSource, kSecuritySource, kOtherSource };
static FetchContext& NullInstance();
@@ -118,7 +123,7 @@ class PLATFORM_EXPORT FetchContext
ResourceLoadPriority,
int intra_priority_value);
- // This internally dispatches WebFrameClient::willSendRequest and hooks
+ // This internally dispatches WebLocalFrameClient::willSendRequest and hooks
// request interceptors like ServiceWorker and ApplicationCache.
// This may modify the request.
enum class RedirectType { kForRedirect, kNotForRedirect };
@@ -148,16 +153,13 @@ class PLATFORM_EXPORT FetchContext
int data_length);
virtual void DispatchDidReceiveEncodedData(unsigned long identifier,
int encoded_data_length);
- virtual void DispatchDidDownloadData(unsigned long identifier,
- int data_length,
- int encoded_data_length);
virtual void DispatchDidDownloadToBlob(unsigned long identifier,
BlobDataHandle*);
virtual void DispatchDidFinishLoading(unsigned long identifier,
TimeTicks finish_time,
int64_t encoded_data_length,
int64_t decoded_body_length,
- bool blocked_cross_site_document);
+ bool should_report_corb_blocking);
virtual void DispatchDidFail(const KURL&,
unsigned long identifier,
const ResourceError&,
@@ -194,13 +196,11 @@ class PLATFORM_EXPORT FetchContext
ResourceRequest::RedirectStatus) const {
return ResourceRequestBlockedReason::kOther;
}
- virtual base::Optional<ResourceRequestBlockedReason> CheckResponseNosniff(
- WebURLRequest::RequestContext,
- const ResourceResponse&) const {
- return ResourceRequestBlockedReason::kOther;
- }
- virtual bool IsControlledByServiceWorker() const { return false; }
+ virtual blink::mojom::ControllerServiceWorkerMode
+ IsControlledByServiceWorker() const {
+ return blink::mojom::ControllerServiceWorkerMode::kNoController;
+ }
virtual int64_t ServiceWorkerID() const { return -1; }
virtual int ApplicationCacheHostID() const {
return WebApplicationCacheHost::kAppCacheNoHostId;
@@ -213,7 +213,7 @@ class PLATFORM_EXPORT FetchContext
return false;
}
- virtual void AddWarningConsoleMessage(const String&, LogSource) const;
+ virtual void AddInfoConsoleMessage(const String&, LogSource) const;
virtual void AddErrorConsoleMessage(const String&, LogSource) const;
virtual const SecurityOrigin* GetSecurityOrigin() const { return nullptr; }
@@ -234,7 +234,6 @@ class PLATFORM_EXPORT FetchContext
virtual std::unique_ptr<WebURLLoader> CreateURLLoader(
const ResourceRequest&,
- scoped_refptr<base::SingleThreadTaskRunner>,
const ResourceLoaderOptions&) {
NOTREACHED();
return nullptr;
@@ -262,6 +261,16 @@ class PLATFORM_EXPORT FetchContext
return Platform::Current()->CurrentThread()->GetTaskRunner();
}
+ // TODO(altimin): This is used when creating a URLLoader, and
+ // FetchContext::GetLoadingTaskRunner is used whenever asynchronous tasks
+ // around resource loading are posted. Modify the code so that all
+ // the tasks related to loading a resource use the resource loader handle's
+ // task runner.
+ virtual std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
+ CreateResourceLoadingTaskRunnerHandle() {
+ return nullptr;
+ }
+
// Called when the underlying context is detached. Note that some
// FetchContexts continue working after detached (e.g., for fetch() operations
// with "keepalive" specified).
@@ -283,6 +292,9 @@ class PLATFORM_EXPORT FetchContext
return false;
}
+ // Called when IdlenessDetector emits its network idle signal.
+ virtual void DispatchNetworkQuiet() {}
+
protected:
FetchContext();
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.json5 b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.json5
index d2d2aac3a55..e7c2bb03ec4 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.json5
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.json5
@@ -5,17 +5,21 @@
},
data: [
+ "audio",
"beacon",
"css",
"document",
"icon",
"internal",
+ "fetch",
"link",
+ "other",
"ping",
"processinginstruction",
- "texttrack",
+ "track",
"uacss",
"violationreport",
+ "video",
"xml",
"xmlhttprequest",
],
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
index 3948868c91e..5e41c9089be 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
@@ -139,6 +139,11 @@ class PLATFORM_EXPORT FetchParameters {
options_.initiator_info.is_link_preload = is_link_preload;
}
+ bool IsStaleRevalidation() const { return is_stale_revalidation_; }
+ void SetStaleRevalidation(bool is_stale_revalidation) {
+ is_stale_revalidation_ = is_stale_revalidation;
+ }
+
void SetContentSecurityCheck(
ContentSecurityPolicyDisposition content_security_policy_option) {
options_.content_security_policy_option = content_security_policy_option;
@@ -206,6 +211,7 @@ class PLATFORM_EXPORT FetchParameters {
ResourceWidth resource_width_;
ClientHintsPreferences client_hint_preferences_;
PlaceholderImageRequestType placeholder_image_request_type_;
+ bool is_stale_revalidation_ = false;
};
// This class is needed to copy a FetchParameters across threads, because it
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc
index c3d91db16b8..136b6ed11ac 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.cc
@@ -332,11 +332,10 @@ MemoryCache::Statistics MemoryCache::GetStatistics() const {
return stats;
}
-void MemoryCache::EvictResources(EvictResourcePolicy policy) {
+void MemoryCache::EvictResources() {
for (auto resource_map_iter = resource_maps_.begin();
resource_map_iter != resource_maps_.end();) {
ResourceMap* resources = resource_map_iter->value.Get();
- HeapVector<Member<MemoryCacheEntry>> unused_preloads;
for (auto resource_iter = resources->begin();
resource_iter != resources->end();
resource_iter = resources->begin()) {
@@ -345,25 +344,10 @@ void MemoryCache::EvictResources(EvictResourcePolicy policy) {
DCHECK(resource_iter->value->GetResource());
Resource* resource = resource_iter->value->GetResource();
DCHECK(resource);
- if (policy != kEvictAllResources && resource->IsUnusedPreload()) {
- // Store unused preloads aside, so they could be added back later.
- // That is in order to avoid the performance impact of iterating over
- // the same resource multiple times.
- unused_preloads.push_back(resource_iter->value.Get());
- }
RemoveInternal(resources, resource_iter);
}
- for (const auto& unused_preload : unused_preloads) {
- AddInternal(resources, unused_preload);
- }
- // We may iterate multiple times over resourceMaps with unused preloads.
- // That's extremely unlikely to have any real-life performance impact.
- if (!resources->size()) {
- resource_maps_.erase(resource_map_iter);
- resource_map_iter = resource_maps_.begin();
- } else {
- ++resource_map_iter;
- }
+ resource_maps_.erase(resource_map_iter);
+ resource_map_iter = resource_maps_.begin();
}
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.h b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.h
index bd63614edc1..950ae3f9c3f 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache.h
@@ -138,8 +138,7 @@ class PLATFORM_EXPORT MemoryCache final
max_prune_deferral_delay_ = seconds;
}
- enum EvictResourcePolicy { kEvictAllResources, kDoNotEvictUnusedPreloads };
- void EvictResources(EvictResourcePolicy = kEvictAllResources);
+ void EvictResources();
void Prune();
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc
index 75a0e6c10dd..56f751b6b3c 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_correctness_test.cc
@@ -108,7 +108,7 @@ class MemoryCacheCorrectnessTest : public testing::Test {
MockFetchContext* context =
MockFetchContext::Create(MockFetchContext::kShouldNotLoadNewResource);
- security_origin_ = SecurityOrigin::CreateUnique();
+ security_origin_ = SecurityOrigin::CreateUniqueOpaque();
context->SetSecurityOrigin(security_origin_);
fetcher_ = ResourceFetcher::Create(context);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc
index d107d869f93..126def7914a 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc
@@ -30,6 +30,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
+#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/loader/fetch/raw_resource.h"
@@ -128,7 +129,13 @@ TEST_F(MemoryCacheTest, CapacityAccounting) {
EXPECT_EQ(kTotalCapacity, GetMemoryCache()->Capacity());
}
-TEST_F(MemoryCacheTest, VeryLargeResourceAccounting) {
+// TODO(crbug.com/850788): Reenable this.
+#if defined(OS_ANDROID)
+#define MAYBE_VeryLargeResourceAccounting DISABLED_VeryLargeResourceAccounting
+#else
+#define MAYBE_VeryLargeResourceAccounting VeryLargeResourceAccounting
+#endif
+TEST_F(MemoryCacheTest, MAYBE_VeryLargeResourceAccounting) {
const size_t kSizeMax = ~static_cast<size_t>(0);
const size_t kTotalCapacity = kSizeMax / 4;
const size_t kResourceSize1 = kSizeMax / 16;
@@ -227,11 +234,26 @@ static void TestResourcePruningAtEndOfTask(ResourceFetcher* fetcher,
// Verified that when ordering a prune in a runLoop task, the prune
// is deferred to the end of the task.
-TEST_F(MemoryCacheTest, ResourcePruningAtEndOfTask_Basic) {
+// TODO(crbug.com/850788): Reenable this.
+#if defined(OS_ANDROID)
+#define MAYBE_ResourcePruningAtEndOfTask_Basic \
+ DISABLED_ResourcePruningAtEndOfTask_Basic
+#else
+#define MAYBE_ResourcePruningAtEndOfTask_Basic ResourcePruningAtEndOfTask_Basic
+#endif
+TEST_F(MemoryCacheTest, MAYBE_ResourcePruningAtEndOfTask_Basic) {
TestResourcePruningAtEndOfTask(fetcher_, "", "");
}
-TEST_F(MemoryCacheTest, ResourcePruningAtEndOfTask_MultipleResourceMaps) {
+// TODO(crbug.com/850788): Reenable this.
+#if defined(OS_ANDROID)
+#define MAYBE_ResourcePruningAtEndOfTask_MultipleResourceMaps \
+ DISABLED_ResourcePruningAtEndOfTask_MultipleResourceMaps
+#else
+#define MAYBE_ResourcePruningAtEndOfTask_MultipleResourceMaps \
+ ResourcePruningAtEndOfTask_MultipleResourceMaps
+#endif
+TEST_F(MemoryCacheTest, MAYBE_ResourcePruningAtEndOfTask_MultipleResourceMaps) {
{
TestResourcePruningAtEndOfTask(fetcher_, "foo", "");
GetMemoryCache()->EvictResources();
@@ -301,7 +323,7 @@ static void TestClientRemoval(ResourceFetcher* fetcher,
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
// Resources are garbage-collected (WeakMemoryCache) and thus removed
// from MemoryCache.
EXPECT_FALSE(resource1_weak);
@@ -309,11 +331,25 @@ static void TestClientRemoval(ResourceFetcher* fetcher,
EXPECT_EQ(0u, GetMemoryCache()->size());
}
-TEST_F(MemoryCacheTest, ClientRemoval_Basic) {
+// TODO(crbug.com/850788): Reenable this.
+#if defined(OS_ANDROID)
+#define MAYBE_ClientRemoval_Basic DISABLED_ClientRemoval_Basic
+#else
+#define MAYBE_ClientRemoval_Basic ClientRemoval_Basic
+#endif
+TEST_F(MemoryCacheTest, MAYBE_ClientRemoval_Basic) {
TestClientRemoval(fetcher_, "", "");
}
-TEST_F(MemoryCacheTest, ClientRemoval_MultipleResourceMaps) {
+// TODO(crbug.com/850788): Reenable this.
+#if defined(OS_ANDROID)
+#define MAYBE_ClientRemoval_MultipleResourceMaps \
+ DISABLED_ClientRemoval_MultipleResourceMaps
+#else
+#define MAYBE_ClientRemoval_MultipleResourceMaps \
+ ClientRemoval_MultipleResourceMaps
+#endif
+TEST_F(MemoryCacheTest, MAYBE_ClientRemoval_MultipleResourceMaps) {
{
TestClientRemoval(fetcher_, "foo", "");
GetMemoryCache()->EvictResources();
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc
index 309a75c3ef5..22802033079 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.cc
@@ -41,10 +41,11 @@
namespace blink {
RawResource* RawResource::FetchSynchronously(FetchParameters& params,
- ResourceFetcher* fetcher) {
+ ResourceFetcher* fetcher,
+ RawResourceClient* client) {
params.MakeSynchronous();
return ToRawResource(fetcher->RequestResource(
- params, RawResourceFactory(Resource::kRaw), nullptr));
+ params, RawResourceFactory(Resource::kRaw), client));
}
RawResource* RawResource::FetchImport(FetchParameters& params,
@@ -251,8 +252,6 @@ void RawResource::DidSendData(unsigned long long bytes_sent,
}
void RawResource::DidDownloadData(int data_length) {
- downloaded_file_length_ =
- (downloaded_file_length_ ? *downloaded_file_length_ : 0) + data_length;
ResourceClientWalker<RawResourceClient> w(Clients());
while (RawResourceClient* c = w.Next())
c->DataDownloaded(this, data_length);
@@ -314,10 +313,8 @@ bool RawResource::MatchPreload(const FetchParameters& params,
std::move(producer), task_runner);
if (Data()) {
- Data()->ForEachSegment(
- [this](const char* segment, size_t size, size_t offset) -> bool {
- return data_pipe_writer_->Write(segment, size);
- });
+ for (const auto& span : *Data())
+ data_pipe_writer_->Write(span.data(), span.size());
}
SetDataBufferingPolicy(kDoNotBufferData);
@@ -338,8 +335,7 @@ static bool ShouldIgnoreHeaderForCacheReuse(AtomicString header_name) {
DEFINE_STATIC_LOCAL(
HashSet<AtomicString>, headers,
({"Cache-Control", "If-Modified-Since", "If-None-Match", "Origin",
- "Pragma", "Purpose", "Referer", "User-Agent",
- HTTPNames::X_DevTools_Emulate_Network_Conditions_Client_Id}));
+ "Pragma", "Purpose", "Referer", "User-Agent"}));
return headers.Contains(header_name);
}
@@ -401,61 +397,61 @@ RawResourceClientStateChecker::RawResourceClientStateChecker()
RawResourceClientStateChecker::~RawResourceClientStateChecker() = default;
-NEVER_INLINE void RawResourceClientStateChecker::WillAddClient() {
+NOINLINE void RawResourceClientStateChecker::WillAddClient() {
SECURITY_CHECK(state_ == kNotAddedAsClient);
state_ = kStarted;
}
-NEVER_INLINE void RawResourceClientStateChecker::WillRemoveClient() {
+NOINLINE void RawResourceClientStateChecker::WillRemoveClient() {
SECURITY_CHECK(state_ != kNotAddedAsClient);
state_ = kNotAddedAsClient;
}
-NEVER_INLINE void RawResourceClientStateChecker::RedirectReceived() {
+NOINLINE void RawResourceClientStateChecker::RedirectReceived() {
SECURITY_CHECK(state_ == kStarted);
}
-NEVER_INLINE void RawResourceClientStateChecker::RedirectBlocked() {
+NOINLINE void RawResourceClientStateChecker::RedirectBlocked() {
SECURITY_CHECK(state_ == kStarted);
state_ = kRedirectBlocked;
}
-NEVER_INLINE void RawResourceClientStateChecker::DataSent() {
+NOINLINE void RawResourceClientStateChecker::DataSent() {
SECURITY_CHECK(state_ == kStarted);
}
-NEVER_INLINE void RawResourceClientStateChecker::ResponseReceived() {
+NOINLINE void RawResourceClientStateChecker::ResponseReceived() {
SECURITY_CHECK(state_ == kStarted);
state_ = kResponseReceived;
}
-NEVER_INLINE void RawResourceClientStateChecker::SetSerializedCachedMetadata() {
+NOINLINE void RawResourceClientStateChecker::SetSerializedCachedMetadata() {
SECURITY_CHECK(state_ == kResponseReceived);
state_ = kSetSerializedCachedMetadata;
}
-NEVER_INLINE void RawResourceClientStateChecker::DataReceived() {
+NOINLINE void RawResourceClientStateChecker::DataReceived() {
SECURITY_CHECK(state_ == kResponseReceived ||
state_ == kSetSerializedCachedMetadata ||
state_ == kDataReceived);
state_ = kDataReceived;
}
-NEVER_INLINE void RawResourceClientStateChecker::DataDownloaded() {
+NOINLINE void RawResourceClientStateChecker::DataDownloaded() {
SECURITY_CHECK(state_ == kResponseReceived ||
state_ == kSetSerializedCachedMetadata ||
state_ == kDataDownloaded);
state_ = kDataDownloaded;
}
-NEVER_INLINE void RawResourceClientStateChecker::DidDownloadToBlob() {
+NOINLINE void RawResourceClientStateChecker::DidDownloadToBlob() {
SECURITY_CHECK(state_ == kResponseReceived ||
state_ == kSetSerializedCachedMetadata ||
state_ == kDataDownloaded);
state_ = kDidDownloadToBlob;
}
-NEVER_INLINE void RawResourceClientStateChecker::NotifyFinished(
+NOINLINE void RawResourceClientStateChecker::NotifyFinished(
Resource* resource) {
SECURITY_CHECK(state_ != kNotAddedAsClient);
SECURITY_CHECK(state_ != kNotifyFinished);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.h b/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.h
index 25777998d67..950e634af33 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource.h
@@ -43,7 +43,9 @@ class SourceKeyedCachedMetadataHandler;
class PLATFORM_EXPORT RawResource final : public Resource {
public:
- static RawResource* FetchSynchronously(FetchParameters&, ResourceFetcher*);
+ static RawResource* FetchSynchronously(FetchParameters&,
+ ResourceFetcher*,
+ RawResourceClient* = nullptr);
static RawResource* Fetch(FetchParameters&,
ResourceFetcher*,
RawResourceClient*);
@@ -91,9 +93,6 @@ class PLATFORM_EXPORT RawResource final : public Resource {
// keyed by the source code of the script.
SourceKeyedCachedMetadataHandler* CacheHandler();
- base::Optional<int64_t> DownloadedFileLength() const {
- return downloaded_file_length_;
- }
scoped_refptr<BlobDataHandle> DownloadedBlob() const {
return downloaded_blob_;
}
@@ -134,7 +133,6 @@ class PLATFORM_EXPORT RawResource final : public Resource {
base::SingleThreadTaskRunner*) override;
void NotifyFinished() override;
- base::Optional<int64_t> downloaded_file_length_;
scoped_refptr<BlobDataHandle> downloaded_blob_;
// Used for preload matching.
@@ -144,13 +142,15 @@ class PLATFORM_EXPORT RawResource final : public Resource {
// TODO(yhirano): Recover #if ENABLE_SECURITY_ASSERT when we stop adding
// RawResources to MemoryCache.
-inline bool IsRawResource(const Resource& resource) {
- Resource::Type type = resource.GetType();
+inline bool IsRawResource(Resource::Type type) {
return type == Resource::kMainResource || type == Resource::kRaw ||
type == Resource::kTextTrack || type == Resource::kAudio ||
type == Resource::kVideo || type == Resource::kManifest ||
type == Resource::kImportResource;
}
+inline bool IsRawResource(const Resource& resource) {
+ return IsRawResource(resource.GetType());
+}
inline RawResource* ToRawResource(Resource* resource) {
SECURITY_DCHECK(!resource || IsRawResource(*resource));
return static_cast<RawResource*>(resource);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc
index 9d75c8fb7b4..44799f2a130 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/raw_resource_test.cc
@@ -66,7 +66,7 @@ TEST_F(RawResourceTest, DontIgnoreAcceptForCacheReuse) {
jpeg_request.SetHTTPAccept("image/jpeg");
scoped_refptr<const SecurityOrigin> source_origin =
- SecurityOrigin::CreateUnique();
+ SecurityOrigin::CreateUniqueOpaque();
RawResource* jpeg_resource(
RawResource::CreateForTest(jpeg_request, Resource::kRaw));
@@ -214,17 +214,4 @@ TEST_F(RawResourceTest, RemoveClientDuringCallback) {
EXPECT_FALSE(raw->IsAlive());
}
-TEST_F(RawResourceTest,
- CanReuseDevToolsEmulateNetworkConditionsClientIdHeader) {
- scoped_refptr<const SecurityOrigin> source_origin =
- SecurityOrigin::CreateUnique();
- ResourceRequest request("data:text/html,");
- request.SetHTTPHeaderField(
- HTTPNames::X_DevTools_Emulate_Network_Conditions_Client_Id, "Foo");
- Resource* raw = RawResource::CreateForTest(request, Resource::kRaw);
- raw->SetSourceOrigin(source_origin);
- EXPECT_TRUE(raw->CanReuse(FetchParameters(ResourceRequest("data:text/html,")),
- source_origin));
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc
index 0dbbd999d45..97a1597f54d 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource.cc
@@ -224,7 +224,6 @@ void Resource::SetLoader(ResourceLoader* loader) {
CHECK(!loader_);
DCHECK(StillNeedsLoad());
loader_ = loader;
- status_ = ResourceStatus::kPending;
}
void Resource::CheckResourceIntegrity() {
@@ -336,6 +335,26 @@ void Resource::SetDataBufferingPolicy(
SetEncodedSize(0);
}
+static bool NeedsSynchronousCacheHit(Resource::Type type,
+ const ResourceLoaderOptions& options) {
+ // Synchronous requests must always succeed or fail synchronously.
+ if (options.synchronous_policy == kRequestSynchronously)
+ return true;
+ // Some resources types default to return data synchronously. For most of
+ // these, it's because there are layout tests that expect data to return
+ // synchronously in case of cache hit. In the case of fonts, there was a
+ // performance regression.
+ // FIXME: Get to the point where we don't need to special-case sync/async
+ // behavior for different resource types.
+ if (type == Resource::kCSSStyleSheet)
+ return true;
+ if (type == Resource::kScript)
+ return true;
+ if (type == Resource::kFont)
+ return true;
+ return false;
+}
+
void Resource::FinishAsError(const ResourceError& error,
base::SingleThreadTaskRunner* task_runner) {
error_ = error;
@@ -344,6 +363,7 @@ void Resource::FinishAsError(const ResourceError& error,
if (IsMainThread())
GetMemoryCache()->Remove(this);
+ bool failed_during_start = status_ == ResourceStatus::kNotStarted;
if (!ErrorOccurred())
SetStatus(ResourceStatus::kLoadError);
DCHECK(ErrorOccurred());
@@ -351,7 +371,20 @@ void Resource::FinishAsError(const ResourceError& error,
loader_ = nullptr;
CheckResourceIntegrity();
TriggerNotificationForFinishObservers(task_runner);
- NotifyFinished();
+
+ // Most resource types don't expect to succeed or fail inside
+ // ResourceFetcher::RequestResource(). If the request does complete
+ // immediately, the convention is to notify the client asynchronously
+ // unless the type is exempted for historical reasons (mostly due to
+ // performance implications to making those notifications asynchronous).
+ // So if this is an immediate failure (i.e., before NotifyStartLoad()),
+ // post a task if the Resource::Type supports it.
+ if (failed_during_start && !NeedsSynchronousCacheHit(GetType(), options_)) {
+ task_runner->PostTask(FROM_HERE, WTF::Bind(&Resource::NotifyFinished,
+ WrapWeakPersistent(this)));
+ } else {
+ NotifyFinished();
+ }
}
void Resource::Finish(TimeTicks load_finish_time,
@@ -372,12 +405,12 @@ AtomicString Resource::HttpContentType() const {
bool Resource::PassesAccessControlCheck(
const SecurityOrigin& security_origin) const {
- base::Optional<network::mojom::CORSError> cors_error = CORS::CheckAccess(
+ base::Optional<network::CORSErrorStatus> cors_status = CORS::CheckAccess(
GetResponse().Url(), GetResponse().HttpStatusCode(),
GetResponse().HttpHeaderFields(),
LastResourceRequest().GetFetchCredentialsMode(), security_origin);
- return !cors_error;
+ return !cors_status;
}
bool Resource::MustRefetchDueToIntegrityMetadata(
@@ -437,6 +470,7 @@ static double FreshnessLifetime(const ResourceResponse& response,
}
static bool CanUseResponse(const ResourceResponse& response,
+ bool allow_stale,
double response_timestamp) {
if (response.IsNull())
return false;
@@ -459,8 +493,11 @@ static bool CanUseResponse(const ResourceResponse& response,
return false;
}
- return CurrentAge(response, response_timestamp) <=
- FreshnessLifetime(response, response_timestamp);
+ double max_life = FreshnessLifetime(response, response_timestamp);
+ if (allow_stale)
+ max_life += response.CacheControlStaleWhileRevalidate();
+
+ return CurrentAge(response, response_timestamp) <= max_life;
}
const ResourceRequest& Resource::LastResourceRequest() const {
@@ -565,13 +602,12 @@ String Resource::ReasonNotDeletable() const {
void Resource::DidAddClient(ResourceClient* c) {
if (scoped_refptr<SharedBuffer> data = Data()) {
- data->ForEachSegment([this, &c](const char* segment, size_t segment_size,
- size_t segment_offset) -> bool {
- c->DataReceived(this, segment, segment_size);
-
+ for (const auto& span : *data) {
+ c->DataReceived(this, span.data(), span.size());
// Stop pushing data if the client removed itself.
- return HasClient(c);
- });
+ if (!HasClient(c))
+ break;
+ }
}
if (!HasClient(c))
return;
@@ -584,22 +620,6 @@ void Resource::DidAddClient(ResourceClient* c) {
}
}
-static bool TypeNeedsSynchronousCacheHit(Resource::Type type) {
- // Some resources types default to return data synchronously. For most of
- // these, it's because there are layout tests that expect data to return
- // synchronously in case of cache hit. In the case of fonts, there was a
- // performance regression.
- // FIXME: Get to the point where we don't need to special-case sync/async
- // behavior for different resource types.
- if (type == Resource::kCSSStyleSheet)
- return true;
- if (type == Resource::kScript)
- return true;
- if (type == Resource::kFont)
- return true;
- return false;
-}
-
void Resource::WillAddClientOrObserver() {
if (!HasClientsOrObservers()) {
is_alive_ = true;
@@ -620,7 +640,7 @@ void Resource::AddClient(ResourceClient* client,
// If an error has occurred or we have existing data to send to the new client
// and the resource type supports it, send it asynchronously.
if ((ErrorOccurred() || !GetResponse().IsNull()) &&
- !TypeNeedsSynchronousCacheHit(GetType())) {
+ !NeedsSynchronousCacheHit(GetType(), options_)) {
clients_awaiting_callback_.insert(client);
if (!async_finish_pending_clients_task_.IsActive()) {
async_finish_pending_clients_task_ = PostCancellableTask(
@@ -1017,7 +1037,8 @@ bool Resource::MatchPreload(const FetchParameters& params,
bool Resource::CanReuseRedirectChain() const {
for (auto& redirect : redirect_chain_) {
- if (!CanUseResponse(redirect.redirect_response_, response_timestamp_))
+ if (!CanUseResponse(redirect.redirect_response_, false /*allow_stale*/,
+ response_timestamp_))
return false;
if (redirect.request_.CacheControlContainsNoCache() ||
redirect.request_.CacheControlContainsNoStore())
@@ -1051,12 +1072,49 @@ bool Resource::MustReloadDueToVaryHeader(
return false;
}
-bool Resource::MustRevalidateDueToCacheHeaders() const {
- return !CanUseResponse(GetResponse(), response_timestamp_) ||
+bool Resource::MustRevalidateDueToCacheHeaders(bool allow_stale) const {
+ return !CanUseResponse(GetResponse(), allow_stale, response_timestamp_) ||
GetResourceRequest().CacheControlContainsNoCache() ||
GetResourceRequest().CacheControlContainsNoStore();
}
+static bool ShouldRevalidateStaleResponse(const ResourceRequest& request,
+ const ResourceResponse& response,
+ double response_timestamp) {
+ double staleness = response.CacheControlStaleWhileRevalidate();
+ if (staleness == 0)
+ return false;
+
+ return CurrentAge(response, response_timestamp) >
+ FreshnessLifetime(response, response_timestamp);
+}
+
+bool Resource::ShouldRevalidateStaleResponse() const {
+ for (auto& redirect : redirect_chain_) {
+ // Use |response_timestamp_| since we don't store the timestamp
+ // of each redirect response.
+ if (blink::ShouldRevalidateStaleResponse(redirect.request_,
+ redirect.redirect_response_,
+ response_timestamp_)) {
+ return true;
+ }
+ }
+
+ return blink::ShouldRevalidateStaleResponse(
+ GetResourceRequest(), GetResponse(), response_timestamp_);
+}
+
+bool Resource::StaleRevalidationRequested() const {
+ if (GetResponse().AsyncRevalidationRequested())
+ return true;
+
+ for (auto& redirect : redirect_chain_) {
+ if (redirect.redirect_response_.AsyncRevalidationRequested())
+ return true;
+ }
+ return false;
+}
+
bool Resource::CanUseCacheValidator() const {
if (IsLoading() || ErrorOccurred())
return false;
@@ -1089,6 +1147,8 @@ void Resource::DidChangePriority(ResourceLoadPriority load_priority,
// TODO(toyoshim): Consider to generate automatically. https://crbug.com/675515.
static const char* InitiatorTypeNameToString(
const AtomicString& initiator_type_name) {
+ if (initiator_type_name == FetchInitiatorTypeNames::audio)
+ return "Audio";
if (initiator_type_name == FetchInitiatorTypeNames::css)
return "CSS resource";
if (initiator_type_name == FetchInitiatorTypeNames::document)
@@ -1097,21 +1157,27 @@ static const char* InitiatorTypeNameToString(
return "Icon";
if (initiator_type_name == FetchInitiatorTypeNames::internal)
return "Internal resource";
+ if (initiator_type_name == FetchInitiatorTypeNames::fetch)
+ return "Fetch";
if (initiator_type_name == FetchInitiatorTypeNames::link)
return "Link element resource";
+ if (initiator_type_name == FetchInitiatorTypeNames::other)
+ return "Other resource";
if (initiator_type_name == FetchInitiatorTypeNames::processinginstruction)
return "Processing instruction";
- if (initiator_type_name == FetchInitiatorTypeNames::texttrack)
- return "Text track";
+ if (initiator_type_name == FetchInitiatorTypeNames::track)
+ return "Track";
if (initiator_type_name == FetchInitiatorTypeNames::uacss)
return "User Agent CSS resource";
+ if (initiator_type_name == FetchInitiatorTypeNames::video)
+ return "Video";
if (initiator_type_name == FetchInitiatorTypeNames::xml)
return "XML resource";
if (initiator_type_name == FetchInitiatorTypeNames::xmlhttprequest)
return "XMLHttpRequest";
static_assert(
- FetchInitiatorTypeNames::FetchInitiatorTypeNamesCount == 13,
+ FetchInitiatorTypeNames::FetchInitiatorTypeNamesCount == 17,
"New FetchInitiatorTypeNames should be handled correctly here.");
return "Resource";
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h
index c6159e3d9d3..eb30e6a033a 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource.h
@@ -261,12 +261,25 @@ class PLATFORM_EXPORT Resource : public GarbageCollectedFinalized<Resource>,
base::SingleThreadTaskRunner*);
bool CanReuseRedirectChain() const;
- bool MustRevalidateDueToCacheHeaders() const;
+ bool MustRevalidateDueToCacheHeaders(bool allow_stale) const;
+ bool ShouldRevalidateStaleResponse() const;
virtual bool CanUseCacheValidator() const;
bool IsCacheValidator() const { return is_revalidating_; }
bool HasCacheControlNoStoreHeader() const;
bool MustReloadDueToVaryHeader(const ResourceRequest& new_request) const;
+ // Returns true if any response returned from the upstream in the redirect
+ // chain is stale and requires triggering async stale revalidation. Once
+ // revalidation is started SetStaleRevalidationStarted() should be called.
+ bool StaleRevalidationRequested() const;
+
+ // Set that stale revalidation has been started so that subsequent
+ // requests won't trigger it again. When stale revalidation is completed
+ // this resource will be removed from the MemoryCache so there is no
+ // need to reset it back to false.
+ bool StaleRevalidationStarted() const { return stale_revalidation_started_; }
+ void SetStaleRevalidationStarted() { stale_revalidation_started_ = true; }
+
const IntegrityMetadataSet& IntegrityMetadata() const {
return options_.integrity_metadata;
}
@@ -346,7 +359,10 @@ class PLATFORM_EXPORT Resource : public GarbageCollectedFinalized<Resource>,
// Used to notify ImageResourceContent of the start of actual loading.
// JavaScript calls or client/observer notifications are disallowed inside
// NotifyStartLoad().
- virtual void NotifyStartLoad() {}
+ virtual void NotifyStartLoad() {
+ CHECK_EQ(status_, ResourceStatus::kNotStarted);
+ status_ = ResourceStatus::kPending;
+ }
static const char* ResourceTypeToString(
Type,
@@ -513,6 +529,7 @@ class PLATFORM_EXPORT Resource : public GarbageCollectedFinalized<Resource>,
bool is_add_remove_client_prohibited_;
bool is_revalidation_start_forbidden_ = false;
bool is_unused_preload_ = false;
+ bool stale_revalidation_started_ = false;
ResourceIntegrityDisposition integrity_disposition_;
SubresourceIntegrity::ReportInfo integrity_report_info_;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_client.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_client.cc
new file mode 100644
index 00000000000..cc5b402427a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_client.cc
@@ -0,0 +1,50 @@
+/*
+ Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
+ Copyright (C) 2001 Dirk Mueller <mueller@kde.org>
+ Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All
+ rights reserved.
+
+ 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.
+
+ This class provides all functionality needed for loading images, style
+ sheets and html pages from the web. It has a memory cache for these objects.
+*/
+
+#include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
+
+#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
+
+namespace blink {
+
+void ResourceClient::Trace(Visitor* visitor) {
+ visitor->Trace(resource_);
+}
+
+void ResourceClient::SetResource(Resource* new_resource,
+ base::SingleThreadTaskRunner* task_runner) {
+ if (new_resource == resource_)
+ return;
+
+ // Some ResourceClient implementations reenter this so we need to
+ // prevent double removal.
+ if (Resource* old_resource = resource_.Release())
+ old_resource->RemoveClient(this);
+ resource_ = new_resource;
+ if (resource_)
+ resource_->AddClient(this, task_runner);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_client.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_client.h
index f4476b61496..b9527200db3 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_client.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_client.h
@@ -27,13 +27,18 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_CLIENT_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/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+namespace base {
+class SingleThreadTaskRunner;
+}
+
namespace blink {
+class Resource;
+
class PLATFORM_EXPORT ResourceClient : public GarbageCollectedMixin {
USING_PRE_FINALIZER(ResourceClient, ClearResource);
@@ -69,7 +74,7 @@ class PLATFORM_EXPORT ResourceClient : public GarbageCollectedMixin {
// Name for debugging, e.g. shown in memory-infra.
virtual String DebugName() const = 0;
- void Trace(blink::Visitor* visitor) override { visitor->Trace(resource_); }
+ void Trace(Visitor* visitor) override;
protected:
ResourceClient() = default;
@@ -81,29 +86,13 @@ class PLATFORM_EXPORT ResourceClient : public GarbageCollectedMixin {
// non-null Resource*. ResourceClient subclasses are responsible for calling
// ClearResource().
friend class ResourceFetcher;
- // TODO(japhet): There isn't a clean way for SVGResourceClients to determine
- // whether SVGElementProxy is holding a Resource that it should register with,
- // so SVGElementProxy handles it for those clients. SVGResourceClients should
- // have a better way to register themselves as clients. crbug.com/789198
- friend class SVGElementProxy;
// CSSFontFaceSrcValue only ever requests a Resource once, and acts as an
// intermediate caching layer of sorts. It needs to be able to register
// additional clients.
friend class CSSFontFaceSrcValue;
void SetResource(Resource* new_resource,
- base::SingleThreadTaskRunner* task_runner) {
- if (new_resource == resource_)
- return;
-
- // Some ResourceClient implementations reenter this so
- // we need to prevent double removal.
- if (Resource* old_resource = resource_.Release())
- old_resource->RemoveClient(this);
- resource_ = new_resource;
- if (resource_)
- resource_->AddClient(this, task_runner);
- }
+ base::SingleThreadTaskRunner* task_runner);
Member<Resource> resource_;
};
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.cc
index 9a84d2c09d3..788f95b599f 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.cc
@@ -55,7 +55,7 @@ ResourceError ResourceError::CancelledDueToAccessCheckError(
ResourceRequestBlockedReason blocked_reason) {
ResourceError error = CancelledError(url);
error.is_access_check_ = true;
- error.should_collapse_initiator_ =
+ error.blocked_by_subresource_filter_ =
blocked_reason == ResourceRequestBlockedReason::kSubresourceFilter;
return error;
}
@@ -171,6 +171,12 @@ bool ResourceError::WasBlockedByResponse() const {
return error_code_ == net::ERR_BLOCKED_BY_RESPONSE;
}
+bool ResourceError::ShouldCollapseInitiator() const {
+ return blocked_by_subresource_filter_ ||
+ GetResourceRequestBlockedReason() ==
+ ResourceRequestBlockedReason::kCollapsedByClient;
+}
+
base::Optional<ResourceRequestBlockedReason>
ResourceError::GetResourceRequestBlockedReason() const {
if (error_code_ != net::ERR_BLOCKED_BY_CLIENT &&
@@ -207,6 +213,9 @@ String DescriptionForBlockedByClientOrResponse(int error, int extended_error) {
case ResourceRequestBlockedReason::kContentType:
detail = "ContentType";
break;
+ case ResourceRequestBlockedReason::kCollapsedByClient:
+ detail = "Collapsed";
+ break;
}
return WebString::FromASCII(net::ErrorToString(error) + "." + detail);
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.h
index 894622598b3..5aaaa0c37f5 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_error.h
@@ -80,7 +80,7 @@ class PLATFORM_EXPORT ResourceError final {
bool IsTimeout() const;
bool IsCacheMiss() const;
bool WasBlockedByResponse() const;
- bool ShouldCollapseInitiator() const { return should_collapse_initiator_; }
+ bool ShouldCollapseInitiator() const;
base::Optional<ResourceRequestBlockedReason> GetResourceRequestBlockedReason()
const;
@@ -104,7 +104,7 @@ class PLATFORM_EXPORT ResourceError final {
String localized_description_;
bool is_access_check_ = false;
bool has_copy_in_cache_ = false;
- bool should_collapse_initiator_ = false;
+ bool blocked_by_subresource_filter_ = false;
base::Optional<network::CORSErrorStatus> cors_error_status_;
};
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
index 8bd77ea2f64..dd3ff0fd819 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -48,9 +48,11 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loading_log.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
+#include "third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h"
#include "third_party/blink/renderer/platform/loader/fetch/unique_identifier.h"
#include "third_party/blink/renderer/platform/mhtml/archive_resource.h"
#include "third_party/blink/renderer/platform/mhtml/mhtml_archive.h"
+#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
#include "third_party/blink/renderer/platform/network/network_instrumentation.h"
#include "third_party/blink/renderer/platform/network/network_utils.h"
#include "third_party/blink/renderer/platform/probe/platform_probes.h"
@@ -177,6 +179,9 @@ ResourceLoadPriority AdjustPriorityWithPriorityHint(
mojom::FetchImportanceMode importance_mode =
resource_request.GetFetchImportanceMode();
+ DCHECK(importance_mode == mojom::FetchImportanceMode::kImportanceAuto ||
+ RuntimeEnabledFeatures::PriorityHintsEnabled());
+
ResourceLoadPriority new_priority = priority_so_far;
switch (importance_mode) {
@@ -274,10 +279,8 @@ ResourceLoadPriority ResourceFetcher::ComputeLoadPriority(
priority = ResourceLoadPriority::kVeryLow;
}
- if (RuntimeEnabledFeatures::PriorityHintsEnabled()) {
- priority = AdjustPriorityWithPriorityHint(priority, type, resource_request,
- defer_option, is_link_preload);
- }
+ priority = AdjustPriorityWithPriorityHint(priority, type, resource_request,
+ defer_option, is_link_preload);
// A manually set priority acts as a floor. This is used to ensure that
// synchronous requests are always given the highest possible priority, as
@@ -356,7 +359,8 @@ ResourceFetcher::ResourceFetcher(FetchContext* new_context)
auto_load_images_(true),
images_enabled_(true),
allow_stale_resources_(false),
- image_fetched_(false) {
+ image_fetched_(false),
+ stale_while_revalidate_enabled_(false) {
InstanceCounters::IncrementCounter(InstanceCounters::kResourceFetcherCounter);
if (IsMainThread())
MainThreadFetchersSet().insert(this);
@@ -367,6 +371,8 @@ ResourceFetcher::~ResourceFetcher() {
}
Resource* ResourceFetcher::CachedResource(const KURL& resource_url) const {
+ if (resource_url.IsEmpty())
+ return nullptr;
KURL url = MemoryCache::RemoveFragmentIdentifierIfNeeded(resource_url);
const WeakMember<Resource>& resource = cached_resources_map_.at(url);
return resource.Get();
@@ -385,7 +391,8 @@ void ResourceFetcher::ClearResourcesFromPreviousFetcher() {
resources_from_previous_fetcher_.clear();
}
-bool ResourceFetcher::IsControlledByServiceWorker() const {
+blink::mojom::ControllerServiceWorkerMode
+ResourceFetcher::IsControlledByServiceWorker() const {
return Context().IsControlledByServiceWorker();
}
@@ -537,9 +544,8 @@ Resource* ResourceFetcher::ResourceForStaticData(
Resource* resource = factory.Create(
params.GetResourceRequest(), params.Options(), params.DecoderOptions());
- // FIXME: We should provide a body stream here.
- resource->SetStatus(ResourceStatus::kPending);
resource->NotifyStartLoad();
+ // FIXME: We should provide a body stream here.
resource->ResponseReceived(response, nullptr);
resource->SetDataBufferingPolicy(kBufferData);
if (data->size())
@@ -558,11 +564,12 @@ Resource* ResourceFetcher::ResourceForStaticData(
Resource* ResourceFetcher::ResourceForBlockedRequest(
const FetchParameters& params,
const ResourceFactory& factory,
- ResourceRequestBlockedReason blocked_reason) {
+ ResourceRequestBlockedReason blocked_reason,
+ ResourceClient* client) {
Resource* resource = factory.Create(
params.GetResourceRequest(), params.Options(), params.DecoderOptions());
- resource->SetStatus(ResourceStatus::kPending);
- resource->NotifyStartLoad();
+ if (client)
+ client->SetResource(resource, Context().GetLoadingTaskRunner().get());
resource->SetSourceOrigin(GetSourceOrigin(params.Options()));
resource->FinishAsError(ResourceError::CancelledDueToAccessCheckError(
params.Url(), blocked_reason),
@@ -592,6 +599,11 @@ void ResourceFetcher::UpdateMemoryCacheStats(Resource* resource,
if (is_static_data)
return;
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ BooleanHistogram, resource_histogram,
+ ("Blink.ResourceFetcher.StaleWhileRevalidate"));
+ resource_histogram.Count(params.IsStaleRevalidation());
+
if (params.IsSpeculativePreload() || params.IsLinkPreload()) {
DEFINE_RESOURCE_HISTOGRAM("Preload.");
} else {
@@ -678,6 +690,18 @@ base::Optional<ResourceRequestBlockedReason> ResourceFetcher::PrepareRequest(
if (resource_type == Resource::kLinkPrefetch)
resource_request.SetHTTPHeaderField(HTTPNames::Purpose, "prefetch");
+ // Indicate whether the network stack can return a stale resource. If a
+ // stale resource is returned a StaleRevalidation request will be scheduled.
+ // Explicitly disallow stale responses for fetchers that don't have SWR
+ // enabled (via origin trial), non-GET requests and resource requests that
+ // are raw. We are explicitly excluding RawResources here to avoid
+ // unintentional SWR, as bugs around RawResources tend to be complicated and
+ // critical.
+ resource_request.SetAllowStaleResponse(
+ stale_while_revalidate_enabled_ &&
+ resource_request.HttpMethod() == HTTPNames::GET &&
+ !IsRawResource(resource_type) && !params.IsStaleRevalidation());
+
Context().AddAdditionalRequestHeaders(
resource_request, (resource_type == Resource::kMainResource)
? kFetchMainResource
@@ -701,7 +725,7 @@ base::Optional<ResourceRequestBlockedReason> ResourceFetcher::PrepareRequest(
return blocked_reason;
const scoped_refptr<const SecurityOrigin>& origin = options.security_origin;
- if (origin && !origin->IsUnique() &&
+ if (origin && !origin->IsOpaque() &&
!origin->IsSameSchemeHostPort(Context().GetSecurityOrigin())) {
// |options.security_origin| may differ from the document's origin if
// this is a fetch initiated by an isolated world execution context, with a
@@ -749,22 +773,6 @@ Resource* ResourceFetcher::RequestResource(
const ResourceFactory& factory,
ResourceClient* client,
const SubstituteData& substitute_data) {
- // Only async requests get ResourceClient callbacks, so sync requests
- // shouldn't provide a client.
- DCHECK(!client ||
- params.Options().synchronous_policy == kRequestAsynchronously);
- Resource* resource =
- RequestResourceInternal(params, factory, substitute_data);
- DCHECK(resource);
- if (client)
- client->SetResource(resource, Context().GetLoadingTaskRunner().get());
- return resource;
-}
-
-Resource* ResourceFetcher::RequestResourceInternal(
- FetchParameters& params,
- const ResourceFactory& factory,
- const SubstituteData& substitute_data) {
unsigned long identifier = CreateUniqueIdentifier();
ResourceRequest& resource_request = params.MutableResourceRequest();
network_instrumentation::ScopedResourceLoadTracker
@@ -789,8 +797,10 @@ Resource* ResourceFetcher::RequestResourceInternal(
base::Optional<ResourceRequestBlockedReason> blocked_reason =
PrepareRequest(params, factory, substitute_data, identifier);
- if (blocked_reason)
- return ResourceForBlockedRequest(params, factory, blocked_reason.value());
+ if (blocked_reason) {
+ return ResourceForBlockedRequest(params, factory, blocked_reason.value(),
+ client);
+ }
Resource::Type resource_type = factory.GetType();
@@ -805,7 +815,8 @@ Resource* ResourceFetcher::RequestResourceInternal(
bool is_data_url = resource_request.Url().ProtocolIsData();
bool is_static_data = is_data_url || substitute_data.IsValid() || archive_;
- if (is_static_data) {
+ bool is_stale_revalidation = params.IsStaleRevalidation();
+ if (!is_stale_revalidation && is_static_data) {
resource = ResourceForStaticData(params, factory, substitute_data);
if (resource) {
policy =
@@ -815,12 +826,12 @@ Resource* ResourceFetcher::RequestResourceInternal(
// in the case of data URLs which might have resources such as fonts that
// need to be decoded only on demand. These data URLs are allowed to be
// processed using the normal ResourceFetcher machinery.
- return ResourceForBlockedRequest(params, factory,
- ResourceRequestBlockedReason::kOther);
+ return ResourceForBlockedRequest(
+ params, factory, ResourceRequestBlockedReason::kOther, client);
}
}
- if (!resource) {
+ if (!is_stale_revalidation && !resource) {
resource = MatchPreload(params, resource_type);
if (resource) {
policy = kUse;
@@ -850,6 +861,11 @@ Resource* ResourceFetcher::RequestResourceInternal(
InitializeRevalidation(resource_request, resource);
break;
case kUse:
+ if (resource_request.AllowsStaleResponse() &&
+ resource->ShouldRevalidateStaleResponse()) {
+ ScheduleStaleRevalidate(resource);
+ }
+
if (resource->IsLinkPreload() && !params.IsLinkPreload())
resource->SetLinkPreload(false);
break;
@@ -861,6 +877,9 @@ Resource* ResourceFetcher::RequestResourceInternal(
if (policy != kUse)
resource->SetIdentifier(identifier);
+ if (client)
+ client->SetResource(resource, Context().GetLoadingTaskRunner().get());
+
// TODO(yoav): It is not clear why preloads are exempt from this check. Can we
// remove the exemption?
if (!params.IsSpeculativePreload() || policy != kUse) {
@@ -879,8 +898,10 @@ Resource* ResourceFetcher::RequestResourceInternal(
// If only the fragment identifiers differ, it is the same resource.
DCHECK(EqualIgnoringFragmentIdentifier(resource->Url(), params.Url()));
RequestLoadStarted(identifier, resource, params, policy, is_static_data);
- cached_resources_map_.Set(
- MemoryCache::RemoveFragmentIdentifierIfNeeded(params.Url()), resource);
+ if (!is_stale_revalidation) {
+ cached_resources_map_.Set(
+ MemoryCache::RemoveFragmentIdentifierIfNeeded(params.Url()), resource);
+ }
document_resources_.insert(resource);
// Returns with an existing resource if the resource does not need to start
@@ -918,7 +939,8 @@ void ResourceFetcher::InitializeRevalidation(
DCHECK(resource->IsLoaded());
DCHECK(resource->CanUseCacheValidator());
DCHECK(!resource->IsCacheValidator());
- DCHECK(!Context().IsControlledByServiceWorker());
+ DCHECK(Context().IsControlledByServiceWorker() ==
+ blink::mojom::ControllerServiceWorkerMode::kNoController);
// RawResource doesn't support revalidation.
CHECK(!IsRawResource(*resource));
@@ -965,7 +987,7 @@ Resource* ResourceFetcher::CreateResourceForLoading(
const FetchParameters& params,
const ResourceFactory& factory) {
const String cache_identifier = GetCacheIdentifier();
- DCHECK(!IsMainThread() ||
+ DCHECK(!IsMainThread() || params.IsStaleRevalidation() ||
!GetMemoryCache()->ResourceForURL(params.GetResourceRequest().Url(),
cache_identifier));
@@ -1037,10 +1059,9 @@ void ResourceFetcher::RecordResourceTimingOnRedirect(
}
static bool IsDownloadOrStreamRequest(const ResourceRequest& request) {
- // Never use cache entries for DownloadToFile / UseStreamOnResponse requests.
+ // Never use cache entries for DownloadToBlob / UseStreamOnResponse requests.
// The data will be delivered through other paths.
- return request.DownloadToFile() || request.DownloadToBlob() ||
- request.UseStreamOnResponse();
+ return request.DownloadToBlob() || request.UseStreamOnResponse();
}
Resource* ResourceFetcher::MatchPreload(const FetchParameters& params,
@@ -1062,7 +1083,7 @@ Resource* ResourceFetcher::MatchPreload(const FetchParameters& params,
}
const ResourceRequest& request = params.GetResourceRequest();
- if (request.DownloadToFile() || request.DownloadToBlob())
+ if (request.DownloadToBlob())
return nullptr;
if (IsImageResourceDisallowedToBeReused(*resource) ||
@@ -1081,6 +1102,7 @@ void ResourceFetcher::InsertAsPreloadIfNecessary(Resource* resource,
Resource::Type type) {
if (!params.IsSpeculativePreload() && !params.IsLinkPreload())
return;
+ DCHECK(!params.IsStaleRevalidation());
// CSP layout tests verify that preloads are subject to access checks by
// seeing if they are in the `preload started` list. Therefore do not add
// them to the list if the load is immediately denied.
@@ -1274,7 +1296,8 @@ ResourceFetcher::DetermineRevalidationPolicyInternal(
// Check if the cache headers requires us to revalidate (cache expiration for
// example).
if (request.GetCacheMode() == mojom::FetchCacheMode::kValidateCache ||
- existing_resource.MustRevalidateDueToCacheHeaders() ||
+ existing_resource.MustRevalidateDueToCacheHeaders(
+ request.AllowsStaleResponse()) ||
request.CacheControlContainsNoCache()) {
// Revalidation is harmful for non-matched preloads because it may lead to
// sharing one preloaded resource among multiple ResourceFetchers.
@@ -1285,8 +1308,14 @@ ResourceFetcher::DetermineRevalidationPolicyInternal(
// is controlled by the ServiceWorker, we choose the Reload policy because
// the revalidation headers should not be exposed to the
// ServiceWorker.(crbug.com/429570)
+ //
+ // TODO(falken): If the controller has no fetch event handler, we probably
+ // can treat it as not being controlled in the S13nSW case. In the
+ // non-S13nSW, we don't know what controller the request will ultimately go
+ // to (due to skipWaiting) so be conservative.
if (existing_resource.CanUseCacheValidator() &&
- !Context().IsControlledByServiceWorker()) {
+ Context().IsControlledByServiceWorker() ==
+ blink::mojom::ControllerServiceWorkerMode::kNoController) {
// If the resource is already a cache validator but not started yet, the
// |Use| policy should be applied to subsequent requests.
if (existing_resource.IsCacheValidator()) {
@@ -1409,18 +1438,14 @@ void ResourceFetcher::ClearPreloads(ClearPreloadsPolicy policy) {
matched_preloads_.clear();
}
-void ResourceFetcher::WarnUnusedPreloads() {
+Vector<KURL> ResourceFetcher::GetUrlsOfUnusedPreloads() {
+ Vector<KURL> urls;
for (const auto& pair : preloads_) {
Resource* resource = pair.value;
- if (resource && resource->IsLinkPreload() && resource->IsUnusedPreload()) {
- Context().AddWarningConsoleMessage(
- "The resource " + resource->Url().GetString() +
- " was preloaded using link preload but not used within a few " +
- "seconds from the window's load event. Please make sure it has " +
- "an appropriate `as` value and it is preloaded intentionally.",
- FetchContext::kJSSource);
- }
+ if (resource && resource->IsLinkPreload() && resource->IsUnusedPreload())
+ urls.push_back(resource->Url());
}
+ return urls;
}
ArchiveResource* ResourceFetcher::CreateArchive(Resource* resource) {
@@ -1459,7 +1484,7 @@ void ResourceFetcher::HandleLoaderFinish(Resource* resource,
TimeTicks finish_time,
LoaderFinishType type,
uint32_t inflight_keepalive_bytes,
- bool blocked_cross_site_document) {
+ bool should_report_corb_blocking) {
DCHECK(resource);
DCHECK_LE(inflight_keepalive_bytes, inflight_keepalive_bytes_);
@@ -1514,11 +1539,24 @@ void ResourceFetcher::HandleLoaderFinish(Resource* resource,
resource->VirtualTimePauser().UnpauseVirtualTime();
Context().DispatchDidFinishLoading(
resource->Identifier(), finish_time, encoded_data_length,
- resource->GetResponse().DecodedBodyLength(), blocked_cross_site_document);
+ resource->GetResponse().DecodedBodyLength(), should_report_corb_blocking);
- if (type == kDidFinishLoading)
+ if (type == kDidFinishLoading) {
resource->Finish(finish_time, Context().GetLoadingTaskRunner().get());
+ // Since this resource came from the network stack we only schedule a stale
+ // while revalidate request if the network asked us to. If we called
+ // ShouldRevalidateStaleResponse here then the resource would be checking
+ // the freshness based on current time. It is possible that the resource
+ // is fresh at the time of the network stack handling but not at the time
+ // handling here and we should not be forcing a revalidation in that case.
+ // eg. network stack returning a resource with max-age=0.
+ if (resource->GetResourceRequest().AllowsStaleResponse() &&
+ resource->StaleRevalidationRequested()) {
+ ScheduleStaleRevalidate(resource);
+ }
+ }
+
HandleLoadCompletion(resource);
}
@@ -1620,15 +1658,21 @@ bool ResourceFetcher::StartLoad(Resource* resource) {
non_blocking_loaders_.insert(loader);
StorePerformanceTimingInitiatorInformation(resource);
+ }
+
+ loader->Start();
+
+ {
+ Resource::RevalidationStartForbiddenScope
+ revalidation_start_forbidden_scope(resource);
+ ScriptForbiddenScope script_forbidden_scope;
// NotifyStartLoad() shouldn't cause AddClient/RemoveClient().
Resource::ProhibitAddRemoveClientInScope
prohibit_add_remove_client_in_scope(resource);
-
- resource->NotifyStartLoad();
+ if (!resource->IsLoaded())
+ resource->NotifyStartLoad();
}
-
- loader->Start();
return true;
}
@@ -1690,11 +1734,17 @@ void ResourceFetcher::ReloadLoFiImages() {
}
String ResourceFetcher::GetCacheIdentifier() const {
- if (Context().IsControlledByServiceWorker())
+ if (Context().IsControlledByServiceWorker() !=
+ blink::mojom::ControllerServiceWorkerMode::kNoController)
return String::Number(Context().ServiceWorkerID());
return MemoryCache::DefaultCacheIdentifier();
}
+void ResourceFetcher::OnNetworkQuiet() {
+ Context().DispatchNetworkQuiet();
+ scheduler_->OnNetworkQuiet();
+}
+
void ResourceFetcher::EmulateLoadStartedForInspector(
Resource* resource,
const KURL& url,
@@ -1721,6 +1771,10 @@ void ResourceFetcher::PrepareForLeakDetection() {
StopFetchingIncludingKeepaliveLoaders();
}
+void ResourceFetcher::SetStaleWhileRevalidateEnabled(bool enabled) {
+ stale_while_revalidate_enabled_ = enabled;
+}
+
void ResourceFetcher::StopFetchingInternal(StopFetchingTarget target) {
// TODO(toyoshim): May want to suspend scheduler while canceling loaders so
// that the cancellations below do not awake unnecessary scheduling.
@@ -1749,6 +1803,28 @@ void ResourceFetcher::StopFetchingIncludingKeepaliveLoaders() {
StopFetchingInternal(StopFetchingTarget::kIncludingKeepaliveLoaders);
}
+void ResourceFetcher::ScheduleStaleRevalidate(Resource* stale_resource) {
+ if (stale_resource->StaleRevalidationStarted())
+ return;
+ stale_resource->SetStaleRevalidationStarted();
+ Context().GetLoadingTaskRunner()->PostTask(
+ FROM_HERE,
+ WTF::Bind(&ResourceFetcher::RevalidateStaleResource,
+ WrapWeakPersistent(this), WrapPersistent(stale_resource)));
+}
+
+void ResourceFetcher::RevalidateStaleResource(Resource* stale_resource) {
+ // Creating FetchParams from Resource::GetResourceRequest doesn't create
+ // the exact same request as the original one, while for revalidation
+ // purpose this is probably fine.
+ // TODO(dtapuska): revisit this when we have a better way to re-dispatch
+ // requests.
+ FetchParameters params(stale_resource->GetResourceRequest());
+ params.SetStaleRevalidation(true);
+ RawResource::Fetch(params, this,
+ new StaleRevalidationResourceClient(stale_resource));
+}
+
void ResourceFetcher::Trace(blink::Visitor* visitor) {
visitor->Trace(context_);
visitor->Trace(scheduler_);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
index 872bf01d629..e127d40507a 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
@@ -28,6 +28,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_FETCHER_H_
#include <memory>
+#include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom-blink.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_context.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_info.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
@@ -55,10 +56,14 @@ class ResourceTimingInfo;
// enforces a bunch of security checks and rules for resource revalidation. Its
// lifetime is roughly per-DocumentLoader, in that it is generally created in
// the DocumentLoader constructor and loses its ability to generate network
-// requests when the DocumentLoader is destroyed. Documents also hold a pointer
-// to ResourceFetcher for their lifetime (and will create one if they are
-// initialized without a LocalFrame), so a Document can keep a ResourceFetcher
-// alive past detach if scripts still reference the Document.
+// requests when the DocumentLoader is destroyed.
+//
+// It is also created for workers and worklets.
+//
+// Documents also hold a pointer to ResourceFetcher for their lifetime (and will
+// create one if they are initialized without a LocalFrame), so a Document can
+// keep a ResourceFetcher alive past detach if scripts still reference the
+// Document.
class PLATFORM_EXPORT ResourceFetcher
: public GarbageCollectedFinalized<ResourceFetcher> {
WTF_MAKE_NONCOPYABLE(ResourceFetcher);
@@ -119,8 +124,7 @@ class PLATFORM_EXPORT ResourceFetcher
int CountPreloads() const { return preloads_.size(); }
void ClearPreloads(ClearPreloadsPolicy = kClearAllPreloads);
- void LogPreloadStats(ClearPreloadsPolicy);
- void WarnUnusedPreloads();
+ Vector<KURL> GetUrlsOfUnusedPreloads();
MHTMLArchive* Archive() const { return archive_.Get(); }
ArchiveResource* CreateArchive(Resource*);
@@ -137,11 +141,11 @@ class PLATFORM_EXPORT ResourceFetcher
TimeTicks finish_time,
LoaderFinishType,
uint32_t inflight_keepalive_bytes,
- bool blocked_cross_site_document);
+ bool should_report_corb_blocking);
void HandleLoaderError(Resource*,
const ResourceError&,
uint32_t inflight_keepalive_bytes);
- bool IsControlledByServiceWorker() const;
+ blink::mojom::ControllerServiceWorkerMode IsControlledByServiceWorker() const;
String GetCacheIdentifier() const;
@@ -163,7 +167,7 @@ class PLATFORM_EXPORT ResourceFetcher
void RemovePreload(Resource*);
void LoosenLoadThrottlingPolicy() { scheduler_->LoosenThrottlingPolicy(); }
- void OnNetworkQuiet() { scheduler_->OnNetworkQuiet(); }
+ void OnNetworkQuiet();
// Workaround for https://crbug.com/666214.
// TODO(hiroshige): Remove this hack.
@@ -177,6 +181,8 @@ class PLATFORM_EXPORT ResourceFetcher
// counting.
void PrepareForLeakDetection();
+ void SetStaleWhileRevalidateEnabled(bool enabled);
+
using ResourceFetcherSet = PersistentHeapHashSet<WeakMember<ResourceFetcher>>;
static const ResourceFetcherSet& MainThreadFetchers();
@@ -207,9 +213,6 @@ class PLATFORM_EXPORT ResourceFetcher
FetchParameters::SpeculativePreloadType::kNotSpeculative,
bool is_link_preload = false);
- Resource* RequestResourceInternal(FetchParameters&,
- const ResourceFactory&,
- const SubstituteData&);
base::Optional<ResourceRequestBlockedReason> PrepareRequest(
FetchParameters&,
const ResourceFactory&,
@@ -221,7 +224,8 @@ class PLATFORM_EXPORT ResourceFetcher
const SubstituteData&);
Resource* ResourceForBlockedRequest(const FetchParameters&,
const ResourceFactory&,
- ResourceRequestBlockedReason);
+ ResourceRequestBlockedReason,
+ ResourceClient*);
Resource* MatchPreload(const FetchParameters& params, Resource::Type);
void InsertAsPreloadIfNecessary(Resource*,
@@ -279,6 +283,9 @@ class PLATFORM_EXPORT ResourceFetcher
const ResourceFactory&,
bool is_static_data) const;
+ void ScheduleStaleRevalidate(Resource* stale_resource);
+ void RevalidateStaleResource(Resource* stale_resource);
+
Member<FetchContext> context_;
Member<ResourceLoadScheduler> scheduler_;
@@ -314,11 +321,12 @@ class PLATFORM_EXPORT ResourceFetcher
uint32_t inflight_keepalive_bytes_ = 0;
- // 28 bits left
+ // 27 bits left
bool auto_load_images_ : 1;
bool images_enabled_ : 1;
bool allow_stale_resources_ : 1;
bool image_fetched_ : 1;
+ bool stale_while_revalidate_enabled_ : 1;
static constexpr uint32_t kKeepaliveInflightBytesQuota = 64 * 1024;
};
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
index c39486b7e6c..635c78ca44e 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
@@ -32,6 +32,7 @@
#include <memory>
#include "base/optional.h"
+#include "build/build_config.h"
#include "services/network/public/mojom/request_context_frame_type.mojom-shared.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom-shared.h"
@@ -155,7 +156,7 @@ TEST_F(ResourceFetcherTest, UseExistingResource) {
TEST_F(ResourceFetcherTest, WillSendRequestAdBit) {
// Add a resource to the memory cache.
scoped_refptr<const SecurityOrigin> source_origin =
- SecurityOrigin::CreateUnique();
+ SecurityOrigin::CreateUniqueOpaque();
Context()->SetSecurityOrigin(source_origin);
KURL url("http://127.0.0.1:8000/foo.html");
Resource* resource = RawResource::CreateForTest(url, Resource::kRaw);
@@ -185,7 +186,7 @@ TEST_F(ResourceFetcherTest, WillSendRequestAdBit) {
TEST_F(ResourceFetcherTest, Vary) {
scoped_refptr<const SecurityOrigin> source_origin =
- SecurityOrigin::CreateUnique();
+ SecurityOrigin::CreateUniqueOpaque();
Context()->SetSecurityOrigin(source_origin);
KURL url("http://127.0.0.1:8000/foo.html");
@@ -249,7 +250,7 @@ TEST_F(ResourceFetcherTest, NavigationTimingInfo) {
TEST_F(ResourceFetcherTest, VaryOnBack) {
scoped_refptr<const SecurityOrigin> source_origin =
- SecurityOrigin::CreateUnique();
+ SecurityOrigin::CreateUniqueOpaque();
Context()->SetSecurityOrigin(source_origin);
ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
@@ -338,7 +339,7 @@ class RequestSameResourceOnComplete
TEST_F(ResourceFetcherTest, RevalidateWhileFinishingLoading) {
scoped_refptr<const SecurityOrigin> source_origin =
- SecurityOrigin::CreateUnique();
+ SecurityOrigin::CreateUniqueOpaque();
Context()->SetSecurityOrigin(source_origin);
KURL url("http://127.0.0.1:8000/foo.png");
@@ -359,7 +360,13 @@ TEST_F(ResourceFetcherTest, RevalidateWhileFinishingLoading) {
EXPECT_TRUE(client->NotifyFinishedCalled());
}
-TEST_F(ResourceFetcherTest, DontReuseMediaDataUrl) {
+// TODO(crbug.com/850785): Reenable this.
+#if defined(OS_ANDROID)
+#define MAYBE_DontReuseMediaDataUrl DISABLED_DontReuseMediaDataUrl
+#else
+#define MAYBE_DontReuseMediaDataUrl DontReuseMediaDataUrl
+#endif
+TEST_F(ResourceFetcherTest, MAYBE_DontReuseMediaDataUrl) {
ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
ResourceRequest request(KURL("data:text/html,foo"));
request.SetRequestContext(WebURLRequest::kRequestContextVideo);
@@ -754,7 +761,7 @@ TEST_F(ResourceFetcherTest, SpeculativePreloadShouldBePromotedToLinkePreload) {
TEST_F(ResourceFetcherTest, Revalidate304) {
scoped_refptr<const SecurityOrigin> source_origin =
- SecurityOrigin::CreateUnique();
+ SecurityOrigin::CreateUniqueOpaque();
Context()->SetSecurityOrigin(source_origin);
KURL url("http://127.0.0.1:8000/foo.html");
@@ -803,7 +810,13 @@ TEST_F(ResourceFetcherTest, LinkPreloadResourceMultipleFetchersAndMove) {
platform_->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
}
-TEST_F(ResourceFetcherTest, ContentTypeDataURL) {
+// TODO(crbug.com/850785): Reenable this.
+#if defined(OS_ANDROID)
+#define MAYBE_ContentTypeDataURL DISABLED_ContentTypeDataURL
+#else
+#define MAYBE_ContentTypeDataURL ContentTypeDataURL
+#endif
+TEST_F(ResourceFetcherTest, MAYBE_ContentTypeDataURL) {
ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
FetchParameters fetch_params{ResourceRequest("data:text/testmimetype,foo")};
Resource* resource = MockResource::Fetch(fetch_params, fetcher, nullptr);
@@ -851,4 +864,66 @@ TEST_F(ResourceFetcherTest, ContentIdURL) {
}
}
+TEST_F(ResourceFetcherTest, StaleWhileRevalidate) {
+ scoped_refptr<const SecurityOrigin> source_origin =
+ SecurityOrigin::CreateUniqueOpaque();
+ Context()->SetSecurityOrigin(source_origin);
+ ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
+
+ KURL url("http://127.0.0.1:8000/foo.html");
+ FetchParameters fetch_params{ResourceRequest(url)};
+
+ ResourceResponse response(url);
+ response.SetHTTPStatusCode(200);
+ response.SetHTTPHeaderField(HTTPNames::Cache_Control,
+ "max-age=0, stale-while-revalidate=40");
+
+ RegisterMockedURLLoadWithCustomResponse(url, response);
+ Resource* resource = MockResource::Fetch(fetch_params, fetcher, nullptr);
+ ASSERT_TRUE(resource);
+
+ platform_->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ EXPECT_TRUE(resource->IsLoaded());
+ EXPECT_TRUE(GetMemoryCache()->Contains(resource));
+
+ fetcher->SetStaleWhileRevalidateEnabled(true);
+ ResourceRequest resource_request(url);
+ resource_request.SetRequestContext(WebURLRequest::kRequestContextInternal);
+ fetch_params = FetchParameters(resource_request);
+ Resource* new_resource = MockResource::Fetch(fetch_params, fetcher, nullptr);
+ EXPECT_EQ(resource, new_resource);
+ platform_->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ EXPECT_TRUE(resource->IsLoaded());
+
+ // Advance the clock, make sure the original resource gets removed from the
+ // memory cache after the revalidation completes.
+ platform_->AdvanceClockSeconds(1);
+ ResourceResponse revalidate_response(url);
+ revalidate_response.SetHTTPStatusCode(200);
+ platform_->GetURLLoaderMockFactory()->UnregisterURL(url);
+ RegisterMockedURLLoadWithCustomResponse(url, revalidate_response);
+ new_resource = MockResource::Fetch(fetch_params, fetcher, nullptr);
+ EXPECT_EQ(resource, new_resource);
+ EXPECT_TRUE(GetMemoryCache()->Contains(resource));
+ platform_->RunUntilIdle();
+ platform_->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+ EXPECT_FALSE(GetMemoryCache()->Contains(resource));
+}
+
+TEST_F(ResourceFetcherTest, CachedResourceShouldNotCrashByNullURL) {
+ ResourceFetcher* fetcher = ResourceFetcher::Create(Context());
+
+ // Make sure |cached_resources_map_| is not empty, so that HashMap lookup
+ // won't take a fast path.
+ KURL url("http://127.0.0.1:8000/foo.html");
+ ResourceResponse response(url);
+ response.SetHTTPStatusCode(200);
+ RegisterMockedURLLoadWithCustomResponse(url, response);
+ FetchParameters fetch_params{ResourceRequest(url)};
+ MockResource::Fetch(fetch_params, fetcher, nullptr);
+ ASSERT_NE(fetcher->CachedResource(url), nullptr);
+
+ ASSERT_EQ(fetcher->CachedResource(KURL()), nullptr);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc
index e0ca9c25153..a010169b9a7 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.cc
@@ -18,8 +18,8 @@ namespace blink {
namespace {
-// Field trial name.
-const char kResourceLoadSchedulerTrial[] = "ResourceLoadScheduler";
+// Field trial name for throttling.
+const char kResourceLoadThrottlingTrial[] = "ResourceLoadScheduler";
// Field trial parameter names.
// Note: bg_limit is supported on m61+, but bg_sub_limit is only on m63+.
@@ -44,11 +44,10 @@ constexpr int32_t kReportBucketCount = 25;
constexpr char kRendererSideResourceScheduler[] =
"RendererSideResourceScheduler";
-// These values are copied from resource_scheduler.cc, but the meaning is a bit
-// different because ResourceScheduler counts the running delayable requests
-// while ResourceLoadScheduler counts all the running requests.
-constexpr size_t kTightLimitForRendererSideResourceScheduler = 1u;
-constexpr size_t kLimitForRendererSideResourceScheduler = 10u;
+// Used in the tight mode (see the header file for details).
+constexpr size_t kTightLimitForRendererSideResourceScheduler = 2u;
+// Used in the normal mode (see the header file for details).
+constexpr size_t kLimitForRendererSideResourceScheduler = 1024u;
constexpr char kTightLimitForRendererSideResourceSchedulerName[] =
"tight_limit";
@@ -96,7 +95,7 @@ size_t GetOutstandingThrottledLimit(FetchContext* context) {
return ResourceLoadScheduler::kOutstandingUnlimited;
uint32_t main_frame_limit = GetFieldTrialUint32Param(
- kResourceLoadSchedulerTrial, kOutstandingLimitForBackgroundMainFrameName,
+ kResourceLoadThrottlingTrial, kOutstandingLimitForBackgroundMainFrameName,
kOutstandingLimitForBackgroundFrameDefault);
if (context->IsMainFrame())
return main_frame_limit;
@@ -104,7 +103,7 @@ size_t GetOutstandingThrottledLimit(FetchContext* context) {
// We do not have a fixed default limit for sub-frames, but use the limit for
// the main frame so that it works as how previous versions that haven't
// consider sub-frames' specific limit work.
- return GetFieldTrialUint32Param(kResourceLoadSchedulerTrial,
+ return GetFieldTrialUint32Param(kResourceLoadThrottlingTrial,
kOutstandingLimitForBackgroundSubFrameName,
main_frame_limit);
}
@@ -115,6 +114,10 @@ int TakeWholeKilobytes(int64_t& bytes) {
return kilobytes;
}
+bool IsResourceLoadThrottlingEnabled() {
+ return RuntimeEnabledFeatures::ResourceLoadSchedulerEnabled();
+}
+
} // namespace
// A class to gather throttling and traffic information to report histograms.
@@ -124,7 +127,7 @@ class ResourceLoadScheduler::TrafficMonitor {
~TrafficMonitor();
// Notified when the ThrottlingState is changed.
- void OnThrottlingStateChanged(FrameScheduler::ThrottlingState);
+ void OnLifecycleStateChanged(scheduler::SchedulingLifecycleState);
// Reports resource request completion.
void Report(const ResourceLoadScheduler::TrafficReportHints&);
@@ -137,8 +140,8 @@ class ResourceLoadScheduler::TrafficMonitor {
const WeakPersistent<FetchContext> context_; // NOT OWNED
- FrameScheduler::ThrottlingState current_state_ =
- FrameScheduler::ThrottlingState::kStopped;
+ scheduler::SchedulingLifecycleState current_state_ =
+ scheduler::SchedulingLifecycleState::kStopped;
size_t total_throttled_request_count_ = 0;
size_t total_throttled_traffic_bytes_ = 0;
@@ -171,8 +174,8 @@ ResourceLoadScheduler::TrafficMonitor::~TrafficMonitor() {
ReportAll();
}
-void ResourceLoadScheduler::TrafficMonitor::OnThrottlingStateChanged(
- FrameScheduler::ThrottlingState state) {
+void ResourceLoadScheduler::TrafficMonitor::OnLifecycleStateChanged(
+ scheduler::SchedulingLifecycleState state) {
current_state_ = state;
throttling_state_change_count_++;
}
@@ -224,8 +227,8 @@ void ResourceLoadScheduler::TrafficMonitor::Report(
kMaximumReportSize1G, kReportBucketCount));
switch (current_state_) {
- case FrameScheduler::ThrottlingState::kThrottled:
- case FrameScheduler::ThrottlingState::kHidden:
+ case scheduler::SchedulingLifecycleState::kThrottled:
+ case scheduler::SchedulingLifecycleState::kHidden:
if (is_main_frame_) {
request_count_by_circumstance.Count(
ToSample(ReportCircumstance::kMainframeThrottled));
@@ -241,7 +244,7 @@ void ResourceLoadScheduler::TrafficMonitor::Report(
total_throttled_traffic_bytes_ += hints.encoded_data_length();
total_throttled_decoded_bytes_ += hints.decoded_body_length();
break;
- case FrameScheduler::ThrottlingState::kNotThrottled:
+ case scheduler::SchedulingLifecycleState::kNotThrottled:
if (is_main_frame_) {
request_count_by_circumstance.Count(
ToSample(ReportCircumstance::kMainframeNotThrottled));
@@ -261,7 +264,7 @@ void ResourceLoadScheduler::TrafficMonitor::Report(
total_not_throttled_traffic_bytes_ += hints.encoded_data_length();
total_not_throttled_decoded_bytes_ += hints.decoded_body_length();
break;
- case FrameScheduler::ThrottlingState::kStopped:
+ case scheduler::SchedulingLifecycleState::kStopped:
break;
}
@@ -392,33 +395,21 @@ ResourceLoadScheduler::ResourceLoadScheduler(FetchContext* context)
traffic_monitor_ =
std::make_unique<ResourceLoadScheduler::TrafficMonitor>(context_);
- if (!RuntimeEnabledFeatures::ResourceLoadSchedulerEnabled() &&
- !Platform::Current()->IsRendererSideResourceSchedulerEnabled()) {
- // Initialize TrafficMonitor's state to be |kNotThrottled| so that it
- // reports metrics in a reasonable state group.
- traffic_monitor_->OnThrottlingStateChanged(
- FrameScheduler::ThrottlingState::kNotThrottled);
- return;
- }
-
auto* scheduler = context->GetFrameScheduler();
if (!scheduler)
return;
- if (Platform::Current()->IsRendererSideResourceSchedulerEnabled()) {
- policy_ = context->InitialLoadThrottlingPolicy();
- normal_outstanding_limit_ =
- GetFieldTrialUint32Param(kRendererSideResourceScheduler,
- kLimitForRendererSideResourceSchedulerName,
- kLimitForRendererSideResourceScheduler);
- tight_outstanding_limit_ = GetFieldTrialUint32Param(
- kRendererSideResourceScheduler,
- kTightLimitForRendererSideResourceSchedulerName,
- kTightLimitForRendererSideResourceScheduler);
- }
-
- is_enabled_ = true;
- scheduler_observer_handle_ = scheduler->AddThrottlingObserver(
+ policy_ = context->InitialLoadThrottlingPolicy();
+ normal_outstanding_limit_ =
+ GetFieldTrialUint32Param(kRendererSideResourceScheduler,
+ kLimitForRendererSideResourceSchedulerName,
+ kLimitForRendererSideResourceScheduler);
+ tight_outstanding_limit_ =
+ GetFieldTrialUint32Param(kRendererSideResourceScheduler,
+ kTightLimitForRendererSideResourceSchedulerName,
+ kTightLimitForRendererSideResourceScheduler);
+
+ scheduler_observer_handle_ = scheduler->AddLifecycleObserver(
FrameScheduler::ObserverType::kLoader, this);
}
@@ -466,44 +457,57 @@ void ResourceLoadScheduler::Request(ResourceLoadSchedulerClient* client,
if (is_shutdown_)
return;
- if (!Platform::Current()->IsRendererSideResourceSchedulerEnabled()) {
- // Prioritization is effectively disabled as we use the constant priority.
- priority = ResourceLoadPriority::kMedium;
- intra_priority = 0;
- }
-
- if (!is_enabled_ || option == ThrottleOption::kCanNotBeThrottled ||
- !IsThrottablePriority(priority)) {
+ // Check if the request can be throttled.
+ ClientIdWithPriority request_info(*id, priority, intra_priority);
+ if (!IsClientDelayable(request_info, option)) {
Run(*id, client, false);
return;
}
- pending_requests_.emplace(*id, priority, intra_priority);
+ DCHECK(ThrottleOption::kStoppable == option ||
+ ThrottleOption::kThrottleable == option);
+ pending_requests_[option].insert(request_info);
pending_request_map_.insert(
- *id, new ClientWithPriority(client, priority, intra_priority));
+ *id, new ClientInfo(client, option, priority, intra_priority));
+
+ // Remember the ClientId since MaybeRun() below may destruct the caller
+ // instance and |id| may be inaccessible after the call.
+ ResourceLoadScheduler::ClientId client_id = *id;
MaybeRun();
+
+ if (IsThrottledState() &&
+ pending_request_map_.find(client_id) != pending_request_map_.end()) {
+ // Note that this doesn't show the message when a frame is stopped (vs.
+ // this DOES when throttled).
+ context_->AddInfoConsoleMessage(
+ "Active resource loading counts reached to a per-frame limit while the "
+ "tab is in background. Network requests will be delayed until a "
+ "previous loading finishes, or the tab is foregrounded. See "
+ "https://www.chromestatus.com/feature/5527160148197376 for more "
+ "details",
+ FetchContext::kOtherSource);
+ }
}
void ResourceLoadScheduler::SetPriority(ClientId client_id,
ResourceLoadPriority priority,
int intra_priority) {
- if (!Platform::Current()->IsRendererSideResourceSchedulerEnabled())
- return;
-
auto client_it = pending_request_map_.find(client_id);
if (client_it == pending_request_map_.end())
return;
- auto it = pending_requests_.find(ClientIdWithPriority(
+ auto& throttle_option_queue = pending_requests_[client_it->value->option];
+
+ auto it = throttle_option_queue.find(ClientIdWithPriority(
client_id, client_it->value->priority, client_it->value->intra_priority));
- DCHECK(it != pending_requests_.end());
- pending_requests_.erase(it);
+ DCHECK(it != throttle_option_queue.end());
+ throttle_option_queue.erase(it);
client_it->value->priority = priority;
client_it->value->intra_priority = intra_priority;
- pending_requests_.emplace(client_id, priority, intra_priority);
+ throttle_option_queue.emplace(client_id, priority, intra_priority);
MaybeRun();
}
@@ -517,7 +521,7 @@ bool ResourceLoadScheduler::Release(
if (running_requests_.find(id) != running_requests_.end()) {
running_requests_.erase(id);
- running_throttlable_requests_.erase(id);
+ running_throttleable_requests_.erase(id);
if (traffic_monitor_)
traffic_monitor_->Report(hints);
@@ -594,50 +598,56 @@ void ResourceLoadScheduler::OnNetworkQuiet() {
}
}
-bool ResourceLoadScheduler::IsThrottablePriority(
- ResourceLoadPriority priority) const {
- if (!Platform::Current()->IsRendererSideResourceSchedulerEnabled())
- return true;
-
- if (RuntimeEnabledFeatures::ResourceLoadSchedulerEnabled()) {
- // If this scheduler is throttled by the associated FrameScheduler,
- // consider every prioritiy as throttlable.
- const auto state = frame_scheduler_throttling_state_;
- if (state == FrameScheduler::ThrottlingState::kHidden ||
- state == FrameScheduler::ThrottlingState::kThrottled ||
- state == FrameScheduler::ThrottlingState::kStopped) {
- return true;
- }
+bool ResourceLoadScheduler::IsClientDelayable(const ClientIdWithPriority& info,
+ ThrottleOption option) const {
+ const bool throttleable = option == ThrottleOption::kThrottleable &&
+ info.priority < ResourceLoadPriority::kHigh;
+ const bool stoppable = option != ThrottleOption::kCanNotBeStoppedOrThrottled;
+
+ // Also takes the lifecycle state of the associated FrameScheduler
+ // into account to determine if the request should be throttled
+ // regardless of the priority.
+ switch (frame_scheduler_lifecycle_state_) {
+ case scheduler::SchedulingLifecycleState::kNotThrottled:
+ return throttleable;
+ case scheduler::SchedulingLifecycleState::kHidden:
+ case scheduler::SchedulingLifecycleState::kThrottled:
+ if (IsResourceLoadThrottlingEnabled())
+ return option == ThrottleOption::kThrottleable;
+ return throttleable;
+ case scheduler::SchedulingLifecycleState::kStopped:
+ return stoppable;
}
- return priority < ResourceLoadPriority::kHigh;
+ NOTREACHED() << static_cast<int>(frame_scheduler_lifecycle_state_);
+ return throttleable;
}
-void ResourceLoadScheduler::OnThrottlingStateChanged(
- FrameScheduler::ThrottlingState state) {
- if (frame_scheduler_throttling_state_ == state)
+void ResourceLoadScheduler::OnLifecycleStateChanged(
+ scheduler::SchedulingLifecycleState state) {
+ if (frame_scheduler_lifecycle_state_ == state)
return;
if (traffic_monitor_)
- traffic_monitor_->OnThrottlingStateChanged(state);
+ traffic_monitor_->OnLifecycleStateChanged(state);
- frame_scheduler_throttling_state_ = state;
+ frame_scheduler_lifecycle_state_ = state;
switch (state) {
- case FrameScheduler::ThrottlingState::kHidden:
- case FrameScheduler::ThrottlingState::kThrottled:
+ case scheduler::SchedulingLifecycleState::kHidden:
+ case scheduler::SchedulingLifecycleState::kThrottled:
if (throttling_history_ == ThrottlingHistory::kInitial)
throttling_history_ = ThrottlingHistory::kThrottled;
else if (throttling_history_ == ThrottlingHistory::kNotThrottled)
throttling_history_ = ThrottlingHistory::kPartiallyThrottled;
break;
- case FrameScheduler::ThrottlingState::kNotThrottled:
+ case scheduler::SchedulingLifecycleState::kNotThrottled:
if (throttling_history_ == ThrottlingHistory::kInitial)
throttling_history_ = ThrottlingHistory::kNotThrottled;
else if (throttling_history_ == ThrottlingHistory::kThrottled)
throttling_history_ = ThrottlingHistory::kPartiallyThrottled;
break;
- case FrameScheduler::ThrottlingState::kStopped:
+ case scheduler::SchedulingLifecycleState::kStopped:
throttling_history_ = ThrottlingHistory::kStopped;
break;
}
@@ -650,35 +660,71 @@ ResourceLoadScheduler::ClientId ResourceLoadScheduler::GenerateClientId() {
return id;
}
+bool ResourceLoadScheduler::GetNextPendingRequest(ClientId* id) {
+ bool needs_throttling =
+ running_throttleable_requests_.size() >= GetOutstandingLimit();
+
+ auto& stoppable_queue = pending_requests_[ThrottleOption::kStoppable];
+ auto& throttleable_queue = pending_requests_[ThrottleOption::kThrottleable];
+
+ // Check if stoppable or throttleable requests are allowed to be run.
+ auto stoppable_it = stoppable_queue.begin();
+ bool has_runnable_stoppable_request =
+ stoppable_it != stoppable_queue.end() &&
+ (!IsClientDelayable(*stoppable_it, ThrottleOption::kStoppable) ||
+ !needs_throttling);
+
+ auto throttleable_it = throttleable_queue.begin();
+ bool has_runnable_throttleable_request =
+ throttleable_it != throttleable_queue.end() &&
+ (!IsClientDelayable(*throttleable_it, ThrottleOption::kThrottleable) ||
+ !needs_throttling);
+
+ if (!has_runnable_throttleable_request && !has_runnable_stoppable_request)
+ return false;
+
+ // If both requests are allowed to be run, run the high priority requests
+ // first.
+ ClientIdWithPriority::Compare compare;
+ bool use_stoppable = has_runnable_stoppable_request &&
+ (!has_runnable_throttleable_request ||
+ compare(*stoppable_it, *throttleable_it));
+
+ // Remove the iterator from the correct set of pending_requests_.
+ if (use_stoppable) {
+ *id = stoppable_it->client_id;
+ stoppable_queue.erase(stoppable_it);
+ return true;
+ }
+ *id = throttleable_it->client_id;
+ throttleable_queue.erase(throttleable_it);
+ return true;
+}
+
void ResourceLoadScheduler::MaybeRun() {
// Requests for keep-alive loaders could be remained in the pending queue,
// but ignore them once Shutdown() is called.
if (is_shutdown_)
return;
- while (!pending_requests_.empty()) {
- if (IsThrottablePriority(pending_requests_.begin()->priority) &&
- running_throttlable_requests_.size() >= GetOutstandingLimit()) {
- break;
- }
-
- ClientId id = pending_requests_.begin()->client_id;
- pending_requests_.erase(pending_requests_.begin());
+ ClientId id = kInvalidClientId;
+ while (GetNextPendingRequest(&id)) {
auto found = pending_request_map_.find(id);
if (found == pending_request_map_.end())
continue; // Already released.
ResourceLoadSchedulerClient* client = found->value->client;
+ ThrottleOption option = found->value->option;
pending_request_map_.erase(found);
- Run(id, client, true);
+ Run(id, client, option == ThrottleOption::kThrottleable);
}
}
void ResourceLoadScheduler::Run(ResourceLoadScheduler::ClientId id,
ResourceLoadSchedulerClient* client,
- bool throttlable) {
+ bool throttleable) {
running_requests_.insert(id);
- if (throttlable)
- running_throttlable_requests_.insert(id);
+ if (throttleable)
+ running_throttleable_requests_.insert(id);
if (running_requests_.size() > maximum_running_requests_seen_) {
maximum_running_requests_seen_ = running_requests_.size();
}
@@ -688,16 +734,15 @@ void ResourceLoadScheduler::Run(ResourceLoadScheduler::ClientId id,
size_t ResourceLoadScheduler::GetOutstandingLimit() const {
size_t limit = kOutstandingUnlimited;
- switch (frame_scheduler_throttling_state_) {
- case FrameScheduler::ThrottlingState::kHidden:
- case FrameScheduler::ThrottlingState::kThrottled:
+ switch (frame_scheduler_lifecycle_state_) {
+ case scheduler::SchedulingLifecycleState::kHidden:
+ case scheduler::SchedulingLifecycleState::kThrottled:
limit = std::min(limit, outstanding_limit_for_throttled_frame_scheduler_);
break;
- case FrameScheduler::ThrottlingState::kNotThrottled:
+ case scheduler::SchedulingLifecycleState::kNotThrottled:
break;
- case FrameScheduler::ThrottlingState::kStopped:
- if (RuntimeEnabledFeatures::ResourceLoadSchedulerEnabled())
- limit = 0;
+ case scheduler::SchedulingLifecycleState::kStopped:
+ limit = 0;
break;
}
@@ -712,4 +757,16 @@ size_t ResourceLoadScheduler::GetOutstandingLimit() const {
return limit;
}
+bool ResourceLoadScheduler::IsThrottledState() const {
+ switch (frame_scheduler_lifecycle_state_) {
+ case scheduler::SchedulingLifecycleState::kHidden:
+ case scheduler::SchedulingLifecycleState::kThrottled:
+ return true;
+ case scheduler::SchedulingLifecycleState::kStopped:
+ case scheduler::SchedulingLifecycleState::kNotThrottled:
+ break;
+ }
+ return false;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h
index c7c0553d382..17f7c7d82f2 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h
@@ -5,7 +5,9 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_LOAD_SCHEDULER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_LOAD_SCHEDULER_H_
+#include <map>
#include <set>
+
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
@@ -41,22 +43,28 @@ class PLATFORM_EXPORT ResourceLoadSchedulerClient
// - When Release() is called with kReleaseAndSchedule
// - When OnThrottlingStateChanged() is called
//
-// A ResourceLoadScheduler determines if a request can be throttable or not, and
-// keeps track of pending throttable requests with priority information (i.e.,
-// ResourceLoadPriority accompanied with an integer called "intra-priority").
-// Here are the general principles:
+// A ResourceLoadScheduler determines if a request can be throttleable or not,
+// and keeps track of pending throttleable requests with priority information
+// (i.e., ResourceLoadPriority accompanied with an integer called
+// "intra-priority"). Here are the general principles:
// - A ResourceLoadScheduler does not throttle requests that cannot be
-// throttable. It will call client's Run() method as soon as possible.
-// - A ResourceLoadScheduler determines whether a request can be throttable by
-// seeing Request()'s ThrottleOption argument and requests' priority
+// throttleable. It will call client's Run() method as soon as possible.
+// - A ResourceLoadScheduler determines whether a request can be throttleable
+// by seeing Request()'s ThrottleOption argument and requests' priority
// information. Requests' priority information can be modified via
// SetPriority().
// - A ResourceLoadScheulder won't initiate a new resource loading which can
-// be throttable when there are active resource loading activities more than
-// its internal threshold (i.e., what GetOutstandingLimit() returns)".
+// be throttleable when there are more active throttleable requests loading
+// activities more than its internal threshold (i.e., what
+// GetOutstandingLimit() returns)".
//
-// By default, ResourceLoadScheduler is disabled, which means it doesn't
-// throttle any resource loading requests.
+// ResourceLoadScheduler has two modes each of which has its own threshold.
+// - Tight mode (used until the frame sees a <body> element):
+// ResourceLoadScheduler considers a request throttleable if its priority
+// is less than |kHigh|.
+// - Normal mode:
+// ResourceLoadScheduler considers a request throttleable if its priority
+// is less than |kMedium|.
//
// Here are running experiments (as of M65):
// - "ResourceLoadScheduler"
@@ -65,27 +73,24 @@ class PLATFORM_EXPORT ResourceLoadSchedulerClient
// - Resource loading requests are throttled when the frame is in a
// background tab. It has different thresholds for the main frame
// and sub frames. When the frame has been background for more than five
-// minutes, all throttable resource loading requests are throttled
+// minutes, all throttleable resource loading requests are throttled
// indefinitely (i.e., threshold is zero in such a circumstance).
-// - RendererSideResourceScheduler
-// ResourceLoadScheduler has two modes each of which has its own threshold.
-// - Tight mode (used until the frame sees a <body> element):
-// ResourceLoadScheduler considers a request throttable if its priority
-// is less than |kHigh|.
-// - Normal mode:
-// ResourceLoadScheduler considers a request throttable if its priority
-// is less than |kMedium|.
class PLATFORM_EXPORT ResourceLoadScheduler final
: public GarbageCollectedFinalized<ResourceLoadScheduler>,
public FrameScheduler::Observer {
WTF_MAKE_NONCOPYABLE(ResourceLoadScheduler);
public:
- // An option to use in calling Request(). If kCanNotBeThrottled is specified,
- // the request should be granted and Run() should be called synchronously.
- // Otherwise, OnRequestGranted() could be called later when other outstanding
- // requests are finished.
- enum class ThrottleOption { kCanBeThrottled, kCanNotBeThrottled };
+ // An option to use in calling Request(). If kCanNotBeStoppedOrThrottled is
+ // specified, the request should be granted and Run() should be called
+ // synchronously. If kStoppable is specified, Run() will be called immediately
+ // unless resource loading is stopped. Otherwise, OnRequestGranted() could be
+ // called later when other outstanding requests are finished.
+ enum class ThrottleOption {
+ kThrottleable = 0,
+ kStoppable = 1,
+ kCanNotBeStoppedOrThrottled = 2,
+ };
// An option to use in calling Release(). If kReleaseOnly is specified,
// the specified request should be released, but no other requests should
@@ -190,12 +195,8 @@ class PLATFORM_EXPORT ResourceLoadScheduler final
void OnNetworkQuiet();
- // Returns whether we can throttle a request with the given priority.
- // This function returns false when RendererSideResourceScheduler is disabled.
- bool IsThrottablePriority(ResourceLoadPriority) const;
-
// FrameScheduler::Observer overrides:
- void OnThrottlingStateChanged(FrameScheduler::ThrottlingState) override;
+ void OnLifecycleStateChanged(scheduler::SchedulingLifecycleState) override;
private:
class TrafficMonitor;
@@ -225,19 +226,32 @@ class PLATFORM_EXPORT ResourceLoadScheduler final
const int intra_priority;
};
- struct ClientWithPriority : public GarbageCollected<ClientWithPriority> {
- ClientWithPriority(ResourceLoadSchedulerClient* client,
- ResourceLoadPriority priority,
- int intra_priority)
- : client(client), priority(priority), intra_priority(intra_priority) {}
+ struct ClientInfo : public GarbageCollected<ClientInfo> {
+ ClientInfo(ResourceLoadSchedulerClient* client,
+ ThrottleOption option,
+ ResourceLoadPriority priority,
+ int intra_priority)
+ : client(client),
+ option(option),
+ priority(priority),
+ intra_priority(intra_priority) {}
void Trace(blink::Visitor* visitor) { visitor->Trace(client); }
Member<ResourceLoadSchedulerClient> client;
+ ThrottleOption option;
ResourceLoadPriority priority;
int intra_priority;
};
+ // Gets the highest priority pending request that is allowed to be run.
+ bool GetNextPendingRequest(ClientId* id);
+
+ // Returns whether we can throttle a request with the given client info based
+ // on life cycle state.
+ bool IsClientDelayable(const ClientIdWithPriority& info,
+ ThrottleOption option) const;
+
ResourceLoadScheduler(FetchContext*);
// Generates the next ClientId.
@@ -247,18 +261,16 @@ class PLATFORM_EXPORT ResourceLoadScheduler final
void MaybeRun();
// Grants a client to run,
- void Run(ClientId, ResourceLoadSchedulerClient*, bool throttlable);
+ void Run(ClientId, ResourceLoadSchedulerClient*, bool throttleable);
size_t GetOutstandingLimit() const;
+ bool IsThrottledState() const;
+
// A flag to indicate an internal running state.
// TODO(toyoshim): We may want to use enum once we start to have more states.
bool is_shutdown_ = false;
- // A mutable flag to indicate if the throttling and scheduling are enabled.
- // Can be modified by field trial flags or for testing.
- bool is_enabled_ = false;
-
ThrottlingPolicy policy_ = ThrottlingPolicy::kNormal;
// ResourceLoadScheduler threshold values for various circumstances. Some
@@ -280,7 +292,7 @@ class PLATFORM_EXPORT ResourceLoadScheduler final
// Holds clients that were granted and are running.
HashSet<ClientId> running_requests_;
- HashSet<ClientId> running_throttlable_requests_;
+ HashSet<ClientId> running_throttleable_requests_;
// Largest number of running requests seen so far.
unsigned maximum_running_requests_seen_ = 0;
@@ -293,13 +305,15 @@ class PLATFORM_EXPORT ResourceLoadScheduler final
kStopped,
};
ThrottlingHistory throttling_history_ = ThrottlingHistory::kInitial;
- FrameScheduler::ThrottlingState frame_scheduler_throttling_state_ =
- FrameScheduler::ThrottlingState::kNotThrottled;
+ scheduler::SchedulingLifecycleState frame_scheduler_lifecycle_state_ =
+ scheduler::SchedulingLifecycleState::kNotThrottled;
// Holds clients that haven't been granted, and are waiting for a grant.
- HeapHashMap<ClientId, Member<ClientWithPriority>> pending_request_map_;
+ HeapHashMap<ClientId, Member<ClientInfo>> pending_request_map_;
// We use std::set here because WTF doesn't have its counterpart.
- std::set<ClientIdWithPriority, ClientIdWithPriority::Compare>
+ // This tracks two sets of requests, throttleable and stoppable.
+ std::map<ThrottleOption,
+ std::set<ClientIdWithPriority, ClientIdWithPriority::Compare>>
pending_requests_;
// Holds an internal class instance to monitor and report traffic.
@@ -309,7 +323,7 @@ class PLATFORM_EXPORT ResourceLoadScheduler final
Member<FetchContext> context_;
// Handle to throttling observer.
- std::unique_ptr<FrameScheduler::ThrottlingObserverHandle>
+ std::unique_ptr<FrameScheduler::LifecycleObserverHandle>
scheduler_observer_handle_;
};
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc
index 059d772e417..49d1ca91613 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler_test.cc
@@ -17,9 +17,29 @@ class MockClient final : public GarbageCollectedFinalized<MockClient>,
USING_GARBAGE_COLLECTED_MIXIN(MockClient);
public:
+ // A delegate that can be used to determine the order clients were run in.
+ class MockClientDelegate {
+ public:
+ MockClientDelegate() = default;
+ ~MockClientDelegate() = default;
+
+ void NotifyRun(MockClient* client) { client_order_.push_back(client); }
+
+ // The call order that hte clients ran in.
+ const std::vector<MockClient*>& client_order() { return client_order_; }
+
+ private:
+ std::vector<MockClient*> client_order_;
+ };
+
~MockClient() = default;
+ void SetDelegate(MockClientDelegate* delegate) { delegate_ = delegate; }
+
void Run() override {
+ if (delegate_) {
+ delegate_->NotifyRun(this);
+ }
EXPECT_FALSE(was_run_);
was_run_ = true;
}
@@ -30,6 +50,7 @@ class MockClient final : public GarbageCollectedFinalized<MockClient>,
}
private:
+ MockClientDelegate* delegate_;
bool was_run_ = false;
};
@@ -61,61 +82,90 @@ class ResourceLoadSchedulerTest : public testing::Test {
Persistent<ResourceLoadScheduler> scheduler_;
};
-class RendererSideResourceSchedulerTest : public testing::Test {
- public:
- using ThrottleOption = ResourceLoadScheduler::ThrottleOption;
- class TestingPlatformSupport : public ::blink::TestingPlatformSupport {
- public:
- bool IsRendererSideResourceSchedulerEnabled() const override {
- return true;
- }
- };
+TEST_F(ResourceLoadSchedulerTest, StopStoppableRequest) {
+ Scheduler()->OnLifecycleStateChanged(
+ scheduler::SchedulingLifecycleState::kStopped);
+ // A request that disallows throttling should be queued.
+ MockClient* client1 = new MockClient;
+ ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
+ Scheduler()->Request(client1, ThrottleOption::kThrottleable,
+ ResourceLoadPriority::kMedium, 0 /* intra_priority */,
+ &id1);
+ EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
+ EXPECT_FALSE(client1->WasRun());
- void SetUp() override {
- DCHECK(RuntimeEnabledFeatures::ResourceLoadSchedulerEnabled());
- scheduler_ = ResourceLoadScheduler::Create(
- MockFetchContext::Create(MockFetchContext::kShouldNotLoadNewResource));
- Scheduler()->SetOutstandingLimitForTesting(1);
- }
- void TearDown() override { Scheduler()->Shutdown(); }
+ // Another request that disallows throttling, but allows stopping should also
+ // be queued.
+ MockClient* client2 = new MockClient;
+ ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
+ Scheduler()->Request(client2, ThrottleOption::kStoppable,
+ ResourceLoadPriority::kMedium, 0 /* intra_priority */,
+ &id2);
+ EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
+ EXPECT_FALSE(client2->WasRun());
- ResourceLoadScheduler* Scheduler() { return scheduler_; }
+ // Another request that disallows throttling and stopping also should be run
+ // even it makes the outstanding number reaches to the limit.
+ MockClient* client3 = new MockClient;
+ ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
+ Scheduler()->Request(client3, ThrottleOption::kCanNotBeStoppedOrThrottled,
+ ResourceLoadPriority::kMedium, 0 /* intra_priority */,
+ &id3);
+ EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
+ EXPECT_TRUE(client3->WasRun());
- bool Release(ResourceLoadScheduler::ClientId client) {
- return Scheduler()->Release(
- client, ResourceLoadScheduler::ReleaseOption::kReleaseOnly,
- ResourceLoadScheduler::TrafficReportHints::InvalidInstance());
- }
+ // Call Release() with different options just in case.
+ EXPECT_TRUE(Release(id1));
+ EXPECT_TRUE(ReleaseAndSchedule(id2));
+ EXPECT_TRUE(ReleaseAndSchedule(id3));
- private:
- ScopedTestingPlatformSupport<TestingPlatformSupport>
- testing_platform_support_;
- Persistent<ResourceLoadScheduler> scheduler_;
-};
+ // Should not succeed to call with the same ID twice.
+ EXPECT_FALSE(Release(id1));
+
+ // Should not succeed to call with the invalid ID or unused ID.
+ EXPECT_FALSE(Release(ResourceLoadScheduler::kInvalidClientId));
+
+ EXPECT_FALSE(Release(static_cast<ResourceLoadScheduler::ClientId>(774)));
+}
-TEST_F(ResourceLoadSchedulerTest, Bypass) {
- // A request that disallows throttling should be ran synchronously.
+TEST_F(ResourceLoadSchedulerTest, ThrottleThrottleableRequest) {
+ Scheduler()->OnLifecycleStateChanged(
+ scheduler::SchedulingLifecycleState::kThrottled);
+
+ Scheduler()->SetOutstandingLimitForTesting(0);
+ // A request that allows throttling should be queued.
MockClient* client1 = new MockClient;
ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client1, ThrottleOption::kCanNotBeThrottled,
+ Scheduler()->Request(client1, ThrottleOption::kThrottleable,
ResourceLoadPriority::kMedium, 0 /* intra_priority */,
&id1);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
- EXPECT_TRUE(client1->WasRun());
+ EXPECT_FALSE(client1->WasRun());
- // Another request that disallows throttling also should be ran even it makes
+ // Another request that disallows throttling also should be run even it makes
// the outstanding number reaches to the limit.
MockClient* client2 = new MockClient;
ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client2, ThrottleOption::kCanNotBeThrottled,
+ Scheduler()->Request(client2, ThrottleOption::kStoppable,
ResourceLoadPriority::kMedium, 0 /* intra_priority */,
&id2);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
EXPECT_TRUE(client2->WasRun());
+ // Another request that disallows stopping should be run even it makes the
+ // outstanding number reaches to the limit.
+ MockClient* client3 = new MockClient;
+ ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
+ Scheduler()->Request(client3, ThrottleOption::kCanNotBeStoppedOrThrottled,
+ ResourceLoadPriority::kMedium, 0 /* intra_priority */,
+ &id3);
+ EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
+ EXPECT_TRUE(client3->WasRun());
+
// Call Release() with different options just in case.
EXPECT_TRUE(Release(id1));
EXPECT_TRUE(ReleaseAndSchedule(id2));
+ EXPECT_TRUE(ReleaseAndSchedule(id3));
// Should not succeed to call with the same ID twice.
EXPECT_FALSE(Release(id1));
@@ -130,7 +180,7 @@ TEST_F(ResourceLoadSchedulerTest, Throttled) {
// The first request should be ran synchronously.
MockClient* client1 = new MockClient;
ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client1, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client1, ThrottleOption::kThrottleable,
ResourceLoadPriority::kMedium, 0 /* intra_priority */,
&id1);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
@@ -139,7 +189,7 @@ TEST_F(ResourceLoadSchedulerTest, Throttled) {
// Another request should be throttled until the first request calls Release.
MockClient* client2 = new MockClient;
ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client2, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client2, ThrottleOption::kThrottleable,
ResourceLoadPriority::kMedium, 0 /* intra_priority */,
&id2);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
@@ -148,7 +198,7 @@ TEST_F(ResourceLoadSchedulerTest, Throttled) {
// Two more requests.
MockClient* client3 = new MockClient;
ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client3, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client3, ThrottleOption::kThrottleable,
ResourceLoadPriority::kMedium, 0 /* intra_priority */,
&id3);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
@@ -156,7 +206,7 @@ TEST_F(ResourceLoadSchedulerTest, Throttled) {
MockClient* client4 = new MockClient;
ResourceLoadScheduler::ClientId id4 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client4, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client4, ThrottleOption::kThrottleable,
ResourceLoadPriority::kMedium, 0 /* intra_priority */,
&id4);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id4);
@@ -182,7 +232,7 @@ TEST_F(ResourceLoadSchedulerTest, Unthrottle) {
// Push three requests.
MockClient* client1 = new MockClient;
ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client1, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client1, ThrottleOption::kThrottleable,
ResourceLoadPriority::kMedium, 0 /* intra_priority */,
&id1);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
@@ -190,7 +240,7 @@ TEST_F(ResourceLoadSchedulerTest, Unthrottle) {
MockClient* client2 = new MockClient;
ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client2, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client2, ThrottleOption::kThrottleable,
ResourceLoadPriority::kMedium, 0 /* intra_priority */,
&id2);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
@@ -198,7 +248,7 @@ TEST_F(ResourceLoadSchedulerTest, Unthrottle) {
MockClient* client3 = new MockClient;
ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client3, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client3, ThrottleOption::kThrottleable,
ResourceLoadPriority::kMedium, 0 /* intra_priority */,
&id3);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
@@ -219,7 +269,7 @@ TEST_F(ResourceLoadSchedulerTest, Stopped) {
// Push three requests.
MockClient* client1 = new MockClient;
ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client1, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client1, ThrottleOption::kThrottleable,
ResourceLoadPriority::kMedium, 0 /* intra_priority */,
&id1);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
@@ -227,7 +277,7 @@ TEST_F(ResourceLoadSchedulerTest, Stopped) {
MockClient* client2 = new MockClient;
ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client2, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client2, ThrottleOption::kThrottleable,
ResourceLoadPriority::kMedium, 0 /* intra_priority */,
&id2);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
@@ -235,7 +285,7 @@ TEST_F(ResourceLoadSchedulerTest, Stopped) {
MockClient* client3 = new MockClient;
ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client3, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client3, ThrottleOption::kThrottleable,
ResourceLoadPriority::kMedium, 0 /* intra_priority */,
&id3);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
@@ -257,134 +307,172 @@ TEST_F(ResourceLoadSchedulerTest, Stopped) {
EXPECT_TRUE(Release(id2));
}
-TEST_F(ResourceLoadSchedulerTest, PriotrityIsNotConsidered) {
+TEST_F(ResourceLoadSchedulerTest, PriorityIsConsidered) {
// Push three requests.
MockClient* client1 = new MockClient;
Scheduler()->SetOutstandingLimitForTesting(0);
ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client1, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client1, ThrottleOption::kThrottleable,
ResourceLoadPriority::kLowest, 10 /* intra_priority */,
&id1);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
MockClient* client2 = new MockClient;
ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client2, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client2, ThrottleOption::kThrottleable,
ResourceLoadPriority::kLow, 1 /* intra_priority */,
&id2);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
MockClient* client3 = new MockClient;
ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client3, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client3, ThrottleOption::kThrottleable,
ResourceLoadPriority::kLow, 3 /* intra_priority */,
&id3);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
+ MockClient* client4 = new MockClient;
+ ResourceLoadScheduler::ClientId id4 = ResourceLoadScheduler::kInvalidClientId;
+ Scheduler()->Request(client4, ThrottleOption::kThrottleable,
+ ResourceLoadPriority::kHigh, 0 /* intra_priority */,
+ &id4);
+ EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id4);
+
EXPECT_FALSE(client1->WasRun());
EXPECT_FALSE(client2->WasRun());
EXPECT_FALSE(client3->WasRun());
+ EXPECT_TRUE(client4->WasRun());
+ // Client 4 does not count against the limit as it was not delayable when it
+ // was created.
Scheduler()->SetOutstandingLimitForTesting(1);
- EXPECT_TRUE(client1->WasRun());
+ EXPECT_FALSE(client1->WasRun());
EXPECT_FALSE(client2->WasRun());
- EXPECT_FALSE(client3->WasRun());
+ EXPECT_TRUE(client3->WasRun());
+ EXPECT_TRUE(client4->WasRun());
Scheduler()->SetOutstandingLimitForTesting(2);
+ EXPECT_FALSE(client1->WasRun());
+ EXPECT_TRUE(client2->WasRun());
+ EXPECT_TRUE(client3->WasRun());
+ EXPECT_TRUE(client4->WasRun());
+
+ Scheduler()->SetOutstandingLimitForTesting(3);
+
EXPECT_TRUE(client1->WasRun());
EXPECT_TRUE(client2->WasRun());
- EXPECT_FALSE(client3->WasRun());
+ EXPECT_TRUE(client3->WasRun());
+ EXPECT_TRUE(client4->WasRun());
- // Release all.
+ // Release the rest.
+ EXPECT_TRUE(Release(id4));
EXPECT_TRUE(Release(id3));
EXPECT_TRUE(Release(id2));
EXPECT_TRUE(Release(id1));
}
-TEST_F(RendererSideResourceSchedulerTest, PriorityIsConsidered) {
- // Push three requests.
+TEST_F(ResourceLoadSchedulerTest, AllowedRequestsRunInPriorityOrder) {
+ Scheduler()->OnLifecycleStateChanged(
+ scheduler::SchedulingLifecycleState::kStopped);
+ Scheduler()->SetOutstandingLimitForTesting(0);
+
+ MockClient::MockClientDelegate delegate;
+ // Push two requests.
+ MockClient* client1 = new MockClient;
+ MockClient* client2 = new MockClient;
+
+ client1->SetDelegate(&delegate);
+ client2->SetDelegate(&delegate);
+
+ ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
+ Scheduler()->Request(client1, ThrottleOption::kStoppable,
+ ResourceLoadPriority::kLowest, 10 /* intra_priority */,
+ &id1);
+ EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
+
+ ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
+ Scheduler()->Request(client2, ThrottleOption::kThrottleable,
+ ResourceLoadPriority::kHigh, 1 /* intra_priority */,
+ &id2);
+ EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
+
+ EXPECT_FALSE(client1->WasRun());
+ EXPECT_FALSE(client2->WasRun());
+
+ Scheduler()->SetOutstandingLimitForTesting(1);
+
+ Scheduler()->OnLifecycleStateChanged(
+ scheduler::SchedulingLifecycleState::kThrottled);
+
+ EXPECT_TRUE(client1->WasRun());
+ EXPECT_TRUE(client2->WasRun());
+
+ // Verify high priority request ran first.
+ std::vector<MockClient*> order = delegate.client_order();
+ EXPECT_EQ(order[0], client2);
+ EXPECT_EQ(order[1], client1);
+
+ // Release all.
+ EXPECT_TRUE(Release(id1));
+ EXPECT_TRUE(Release(id2));
+}
+
+TEST_F(ResourceLoadSchedulerTest, StoppableRequestResumesWhenThrottled) {
+ Scheduler()->OnLifecycleStateChanged(
+ scheduler::SchedulingLifecycleState::kStopped);
+ // Push two requests.
MockClient* client1 = new MockClient;
Scheduler()->SetOutstandingLimitForTesting(0);
ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client1, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client1, ThrottleOption::kStoppable,
ResourceLoadPriority::kLowest, 10 /* intra_priority */,
&id1);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
MockClient* client2 = new MockClient;
ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client2, ThrottleOption::kCanBeThrottled,
- ResourceLoadPriority::kLow, 1 /* intra_priority */,
+ Scheduler()->Request(client2, ThrottleOption::kThrottleable,
+ ResourceLoadPriority::kHigh, 1 /* intra_priority */,
&id2);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
MockClient* client3 = new MockClient;
ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client3, ThrottleOption::kCanBeThrottled,
- ResourceLoadPriority::kLow, 3 /* intra_priority */,
+ Scheduler()->Request(client3, ThrottleOption::kStoppable,
+ ResourceLoadPriority::kLowest, 10 /* intra_priority */,
&id3);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
- MockClient* client4 = new MockClient;
- ResourceLoadScheduler::ClientId id4 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client4, ThrottleOption::kCanBeThrottled,
- ResourceLoadPriority::kHigh, 0 /* intra_priority */,
- &id4);
- EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id4);
-
EXPECT_FALSE(client1->WasRun());
EXPECT_FALSE(client2->WasRun());
EXPECT_FALSE(client3->WasRun());
- EXPECT_TRUE(client4->WasRun());
- Scheduler()->SetOutstandingLimitForTesting(1);
+ Scheduler()->OnLifecycleStateChanged(
+ scheduler::SchedulingLifecycleState::kThrottled);
- EXPECT_FALSE(client1->WasRun());
+ EXPECT_TRUE(client1->WasRun());
EXPECT_FALSE(client2->WasRun());
EXPECT_TRUE(client3->WasRun());
- EXPECT_TRUE(client4->WasRun());
- Scheduler()->SetOutstandingLimitForTesting(2);
+ Scheduler()->SetOutstandingLimitForTesting(1);
- EXPECT_FALSE(client1->WasRun());
+ EXPECT_TRUE(client1->WasRun());
EXPECT_TRUE(client2->WasRun());
EXPECT_TRUE(client3->WasRun());
- EXPECT_TRUE(client4->WasRun());
// Release all.
- EXPECT_TRUE(Release(id4));
- EXPECT_TRUE(Release(id3));
- EXPECT_TRUE(Release(id2));
EXPECT_TRUE(Release(id1));
+ EXPECT_TRUE(Release(id2));
+ EXPECT_TRUE(Release(id3));
}
-TEST_F(RendererSideResourceSchedulerTest, IsThrottablePriority) {
- EXPECT_TRUE(
- Scheduler()->IsThrottablePriority(ResourceLoadPriority::kVeryLow));
- EXPECT_TRUE(Scheduler()->IsThrottablePriority(ResourceLoadPriority::kLow));
- EXPECT_TRUE(Scheduler()->IsThrottablePriority(ResourceLoadPriority::kMedium));
- EXPECT_FALSE(Scheduler()->IsThrottablePriority(ResourceLoadPriority::kHigh));
- EXPECT_FALSE(
- Scheduler()->IsThrottablePriority(ResourceLoadPriority::kVeryHigh));
-
- Scheduler()->LoosenThrottlingPolicy();
-
- EXPECT_TRUE(
- Scheduler()->IsThrottablePriority(ResourceLoadPriority::kVeryLow));
- EXPECT_TRUE(Scheduler()->IsThrottablePriority(ResourceLoadPriority::kLow));
- EXPECT_TRUE(Scheduler()->IsThrottablePriority(ResourceLoadPriority::kMedium));
- EXPECT_FALSE(Scheduler()->IsThrottablePriority(ResourceLoadPriority::kHigh));
- EXPECT_FALSE(
- Scheduler()->IsThrottablePriority(ResourceLoadPriority::kVeryHigh));
-}
-
-TEST_F(RendererSideResourceSchedulerTest, SetPriority) {
+TEST_F(ResourceLoadSchedulerTest, SetPriority) {
// Start with the normal scheduling policy.
Scheduler()->LoosenThrottlingPolicy();
// Push three requests.
@@ -393,21 +481,21 @@ TEST_F(RendererSideResourceSchedulerTest, SetPriority) {
Scheduler()->SetOutstandingLimitForTesting(0);
ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client1, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client1, ThrottleOption::kThrottleable,
ResourceLoadPriority::kLowest, 0 /* intra_priority */,
&id1);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
MockClient* client2 = new MockClient;
ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client2, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client2, ThrottleOption::kThrottleable,
ResourceLoadPriority::kLow, 5 /* intra_priority */,
&id2);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
MockClient* client3 = new MockClient;
ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client3, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client3, ThrottleOption::kThrottleable,
ResourceLoadPriority::kLow, 10 /* intra_priority */,
&id3);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
@@ -440,34 +528,34 @@ TEST_F(RendererSideResourceSchedulerTest, SetPriority) {
EXPECT_TRUE(Release(id1));
}
-TEST_F(RendererSideResourceSchedulerTest, LoosenThrottlingPolicy) {
+TEST_F(ResourceLoadSchedulerTest, LoosenThrottlingPolicy) {
MockClient* client1 = new MockClient;
Scheduler()->SetOutstandingLimitForTesting(0, 0);
ResourceLoadScheduler::ClientId id1 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client1, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client1, ThrottleOption::kThrottleable,
ResourceLoadPriority::kLowest, 0 /* intra_priority */,
&id1);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id1);
MockClient* client2 = new MockClient;
ResourceLoadScheduler::ClientId id2 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client2, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client2, ThrottleOption::kThrottleable,
ResourceLoadPriority::kLowest, 0 /* intra_priority */,
&id2);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id2);
MockClient* client3 = new MockClient;
ResourceLoadScheduler::ClientId id3 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client3, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client3, ThrottleOption::kThrottleable,
ResourceLoadPriority::kLowest, 0 /* intra_priority */,
&id3);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id3);
MockClient* client4 = new MockClient;
ResourceLoadScheduler::ClientId id4 = ResourceLoadScheduler::kInvalidClientId;
- Scheduler()->Request(client4, ThrottleOption::kCanBeThrottled,
+ Scheduler()->Request(client4, ThrottleOption::kThrottleable,
ResourceLoadPriority::kLowest, 0 /* intra_priority */,
&id4);
EXPECT_NE(ResourceLoadScheduler::kInvalidClientId, id4);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
index 218972f8b0c..cc52420a1cf 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -34,6 +34,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_cors.h"
#include "third_party/blink/public/platform/web_data.h"
+#include "third_party/blink/public/platform/web_security_origin.h"
#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/platform/web_url_response.h"
@@ -45,6 +46,9 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.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/network/mime/mime_type_registry.h"
#include "third_party/blink/renderer/platform/network/network_instrumentation.h"
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
@@ -58,9 +62,15 @@ namespace blink {
namespace {
bool IsThrottlableRequestContext(WebURLRequest::RequestContext context) {
+ // Requests that could run long should not be throttled as they
+ // may stay there forever and avoid other requests from making
+ // progress.
+ // See https://crbug.com/837771 for the sample breakages.
return context != WebURLRequest::kRequestContextEventSource &&
context != WebURLRequest::kRequestContextFetch &&
- context != WebURLRequest::kRequestContextXMLHttpRequest;
+ context != WebURLRequest::kRequestContextXMLHttpRequest &&
+ context != WebURLRequest::kRequestContextVideo &&
+ context != WebURLRequest::kRequestContextAudio;
}
} // namespace
@@ -105,18 +115,25 @@ void ResourceLoader::Trace(blink::Visitor* visitor) {
void ResourceLoader::Start() {
const ResourceRequest& request = resource_->GetResourceRequest();
ActivateCacheAwareLoadingIfNeeded(request);
- loader_ = Context().CreateURLLoader(request, Context().GetLoadingTaskRunner(),
- resource_->Options());
+ loader_ = Context().CreateURLLoader(request, resource_->Options());
DCHECK_EQ(ResourceLoadScheduler::kInvalidClientId, scheduler_client_id_);
- auto throttle_option = ResourceLoadScheduler::ThrottleOption::kCanBeThrottled;
-
- // Synchronous requests should not work with a throttling. Also, disables
- // throttling for the case that can be used for aka long-polling requests.
- // We also disable throttling for non-http[s] requests.
+ auto throttle_option = ResourceLoadScheduler::ThrottleOption::kThrottleable;
+
+ // Synchronous requests should not work with throttling or stopping. Also,
+ // disables throttling for the case that can be used for aka long-polling
+ // requests, but allows stopping for long-polling requests.
+ // Top level frame main resource loads are also not throttleable or
+ // stoppable. We also disable throttling and stopping for non-http[s]
+ // requests.
if (resource_->Options().synchronous_policy == kRequestSynchronously ||
- !IsThrottlableRequestContext(request.GetRequestContext()) ||
+ (request.GetFrameType() ==
+ network::mojom::RequestContextFrameType::kTopLevel &&
+ resource_->GetType() == Resource::kMainResource) ||
!request.Url().ProtocolIsInHTTPFamily()) {
- throttle_option = ResourceLoadScheduler::ThrottleOption::kCanNotBeThrottled;
+ throttle_option =
+ ResourceLoadScheduler::ThrottleOption::kCanNotBeStoppedOrThrottled;
+ } else if (!IsThrottlableRequestContext(request.GetRequestContext())) {
+ throttle_option = ResourceLoadScheduler::ThrottleOption::kStoppable;
}
scheduler_->Request(this, throttle_option, request.Priority(),
@@ -170,8 +187,7 @@ void ResourceLoader::Release(
void ResourceLoader::Restart(const ResourceRequest& request) {
CHECK_EQ(resource_->Options().synchronous_policy, kRequestAsynchronously);
- loader_ = Context().CreateURLLoader(request, Context().GetLoadingTaskRunner(),
- resource_->Options());
+ loader_ = Context().CreateURLLoader(request, resource_->Options());
StartWith(request);
}
@@ -308,7 +324,7 @@ bool ResourceLoader::WillFollowRedirect(
scoped_refptr<const SecurityOrigin> source_origin = GetSourceOrigin();
WebSecurityOrigin source_web_origin(source_origin.get());
WrappedResourceRequest new_request_wrapper(*new_request);
- base::Optional<network::mojom::CORSError> cors_error =
+ base::Optional<network::CORSErrorStatus> cors_error =
WebCORS::HandleRedirect(
source_web_origin, new_request_wrapper, redirect_response.Url(),
redirect_response.HttpStatusCode(),
@@ -320,10 +336,8 @@ bool ResourceLoader::WillFollowRedirect(
if (!unused_preload) {
Context().AddErrorConsoleMessage(
CORS::GetErrorString(CORS::ErrorParameter::Create(
- network::CORSErrorStatus(*cors_error),
- redirect_response.Url(), new_url,
- redirect_response.HttpStatusCode(),
- redirect_response.HttpHeaderFields(), *source_origin.get(),
+ *cors_error, redirect_response.Url(), new_url,
+ redirect_response.HttpStatusCode(), *source_origin.get(),
resource_->LastResourceRequest().GetRequestContext())),
FetchContext::kJSSource);
}
@@ -481,7 +495,7 @@ CORSStatus ResourceLoader::DetermineCORSStatus(const ResourceResponse& response,
? resource_->GetResponse()
: response;
- base::Optional<network::mojom::CORSError> cors_error = CORS::CheckAccess(
+ base::Optional<network::CORSErrorStatus> cors_error = CORS::CheckAccess(
response_for_access_control.Url(),
response_for_access_control.HttpStatusCode(),
response_for_access_control.HttpHeaderFields(),
@@ -500,9 +514,8 @@ CORSStatus ResourceLoader::DetermineCORSStatus(const ResourceResponse& response,
error_msg.Append(source_origin->ToString());
error_msg.Append("' has been blocked by CORS policy: ");
error_msg.Append(CORS::GetErrorString(CORS::ErrorParameter::Create(
- network::CORSErrorStatus(*cors_error), initial_request.Url(), KURL(),
- response_for_access_control.HttpStatusCode(),
- response_for_access_control.HttpHeaderFields(), *source_origin,
+ *cors_error, initial_request.Url(), KURL(),
+ response_for_access_control.HttpStatusCode(), *source_origin,
initial_request.GetRequestContext())));
return CORSStatus::kFailed;
@@ -545,7 +558,7 @@ void ResourceLoader::DidReceiveResponse(
? resource_->GetResponse()
: response;
base::Optional<ResourceRequestBlockedReason> blocked_reason =
- Context().CheckResponseNosniff(request_context, nosniffed_response);
+ CheckResponseNosniff(request_context, nosniffed_response);
if (blocked_reason) {
HandleError(ResourceError::CancelledDueToAccessCheckError(
response.Url(), blocked_reason.value()));
@@ -653,12 +666,6 @@ void ResourceLoader::DidStartLoadingResponseBody(
WrapWeakPersistent(this)));
}
-void ResourceLoader::DidDownloadData(int length, int encoded_data_length) {
- Context().DispatchDidDownloadData(resource_->Identifier(), length,
- encoded_data_length);
- resource_->DidDownloadData(length);
-}
-
void ResourceLoader::DidReceiveData(const char* data, int length) {
CHECK_GE(length, 0);
@@ -686,14 +693,14 @@ void ResourceLoader::DidFinishLoading(TimeTicks finish_time,
int64_t encoded_data_length,
int64_t encoded_body_length,
int64_t decoded_body_length,
- bool blocked_cross_site_document) {
+ bool should_report_corb_blocking) {
resource_->SetEncodedDataLength(encoded_data_length);
resource_->SetEncodedBodyLength(encoded_body_length);
resource_->SetDecodedBodyLength(decoded_body_length);
if (is_downloading_to_blob_ && !blob_finished_ && blob_response_started_) {
load_did_finish_before_blob_ =
- DeferedFinishLoadingInfo{finish_time, blocked_cross_site_document};
+ DeferedFinishLoadingInfo{finish_time, should_report_corb_blocking};
return;
}
@@ -708,7 +715,7 @@ void ResourceLoader::DidFinishLoading(TimeTicks finish_time,
fetcher_->HandleLoaderFinish(
resource_.Get(), finish_time, ResourceFetcher::kDidFinishLoading,
- inflight_keepalive_bytes_, blocked_cross_site_document);
+ inflight_keepalive_bytes_, should_report_corb_blocking);
}
void ResourceLoader::DidFail(const WebURLError& error,
@@ -751,11 +758,10 @@ void ResourceLoader::RequestSynchronously(const ResourceRequest& request) {
WebData data_out;
int64_t encoded_data_length = WebURLLoaderClient::kUnknownEncodedDataLength;
int64_t encoded_body_length = 0;
- base::Optional<int64_t> downloaded_file_length;
WebBlobInfo downloaded_blob;
loader_->LoadSynchronously(request_in, this, response_out, error_out,
data_out, encoded_data_length, encoded_body_length,
- downloaded_file_length, downloaded_blob);
+ downloaded_blob);
// A message dispatched while synchronously fetching the resource
// can bring about the cancellation of this load.
@@ -779,26 +785,16 @@ void ResourceLoader::RequestSynchronously(const ResourceRequest& request) {
if (data_out.size()) {
data_out.ForEachSegment([this](const char* segment, size_t segment_size,
size_t segment_offset) {
- Context().DispatchDidReceiveData(resource_->Identifier(), segment,
- segment_size);
+ DidReceiveData(segment, segment_size);
return true;
});
- resource_->SetResourceBuffer(data_out);
}
- if (downloaded_file_length) {
- DCHECK(request.DownloadToFile());
- DidDownloadData(*downloaded_file_length, encoded_body_length);
- }
if (request.DownloadToBlob()) {
auto blob = downloaded_blob.GetBlobHandle();
- if (blob) {
- Context().DispatchDidReceiveData(resource_->Identifier(), nullptr,
- blob->size());
- resource_->DidDownloadData(blob->size());
- }
- Context().DispatchDidDownloadToBlob(resource_->Identifier(), blob.get());
- resource_->DidDownloadToBlob(blob);
+ if (blob)
+ OnProgress(blob->size());
+ FinishedCreatingBlob(blob);
}
DidFinishLoading(CurrentTimeTicks(), encoded_data_length, encoded_body_length,
decoded_body_length, false);
@@ -806,6 +802,7 @@ void ResourceLoader::RequestSynchronously(const ResourceRequest& request) {
void ResourceLoader::Dispose() {
loader_ = nullptr;
+ progress_binding_.Close();
// Release() should be called to release |scheduler_client_id_| beforehand in
// DidFinishLoading() or DidFail(), but when a timer to call Cancel() is
@@ -838,8 +835,10 @@ void ResourceLoader::ActivateCacheAwareLoadingIfNeeded(
return;
// Don't activate if the page is controlled by service worker.
- if (fetcher_->IsControlledByServiceWorker())
+ if (fetcher_->IsControlledByServiceWorker() !=
+ blink::mojom::ControllerServiceWorkerMode::kNoController) {
return;
+ }
is_cache_aware_loading_activated_ = true;
}
@@ -880,8 +879,35 @@ void ResourceLoader::FinishedCreatingBlob(
DidFinishLoading(load_did_finish_before_blob_->finish_time,
response.EncodedDataLength(), response.EncodedBodyLength(),
response.DecodedBodyLength(),
- load_did_finish_before_blob_->blocked_cross_site_document);
+ load_did_finish_before_blob_->should_report_corb_blocking);
}
}
+base::Optional<ResourceRequestBlockedReason>
+ResourceLoader::CheckResponseNosniff(
+ WebURLRequest::RequestContext request_context,
+ const ResourceResponse& response) const {
+ bool sniffing_allowed =
+ ParseContentTypeOptionsHeader(response.HttpHeaderField(
+ HTTPNames::X_Content_Type_Options)) != kContentTypeOptionsNosniff;
+ if (sniffing_allowed)
+ return base::nullopt;
+
+ String mime_type = response.HttpContentType();
+ if (request_context == WebURLRequest::kRequestContextStyle &&
+ !MIMETypeRegistry::IsSupportedStyleSheetMIMEType(mime_type)) {
+ Context().AddErrorConsoleMessage(
+ "Refused to apply style from '" + response.Url().ElidedString() +
+ "' because its MIME type ('" + mime_type + "') " +
+ "is not a supported stylesheet MIME type, and strict MIME checking "
+ "is enabled.",
+ FetchContext::kSecuritySource);
+ return ResourceRequestBlockedReason::kContentType;
+ }
+ // TODO(mkwst): Move the 'nosniff' bit of 'AllowedByNosniff::MimeTypeAsScript'
+ // here alongside the style checks, and put its use counters somewhere else.
+
+ return base::nullopt;
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
index db929e18b96..0d10f6e645a 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
@@ -119,12 +119,11 @@ class PLATFORM_EXPORT ResourceLoader final
void DidReceiveTransferSizeUpdate(int transfer_size_diff) override;
void DidStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override;
- void DidDownloadData(int, int) override;
void DidFinishLoading(TimeTicks finish_time,
int64_t encoded_data_length,
int64_t encoded_body_length,
int64_t decoded_body_length,
- bool blocked_cross_site_document) override;
+ bool should_report_corb_blocking) override;
void DidFail(const WebURLError&,
int64_t encoded_data_length,
int64_t encoded_body_length,
@@ -175,6 +174,10 @@ class PLATFORM_EXPORT ResourceLoader final
void OnProgress(uint64_t delta) override;
void FinishedCreatingBlob(const scoped_refptr<BlobDataHandle>&);
+ base::Optional<ResourceRequestBlockedReason> CheckResponseNosniff(
+ WebURLRequest::RequestContext,
+ const ResourceResponse&) const;
+
std::unique_ptr<WebURLLoader> loader_;
ResourceLoadScheduler::ClientId scheduler_client_id_;
Member<ResourceFetcher> fetcher_;
@@ -194,7 +197,7 @@ class PLATFORM_EXPORT ResourceLoader final
// when the blob is finished too.
struct DeferedFinishLoadingInfo {
TimeTicks finish_time;
- bool blocked_cross_site_document;
+ bool should_report_corb_blocking;
};
base::Optional<DeferedFinishLoadingInfo> load_did_finish_before_blob_;
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
index 875d723b823..aabeebe9b41 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
@@ -28,7 +28,9 @@
#include <memory>
+#include "base/unguessable_token.h"
#include "third_party/blink/public/platform/web_url_request.h"
+#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
#include "third_party/blink/renderer/platform/network/network_utils.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -36,7 +38,8 @@
namespace blink {
-double ResourceRequest::default_timeout_interval_ = INT_MAX;
+base::TimeDelta ResourceRequest::default_timeout_interval_ =
+ base::TimeDelta::Max();
ResourceRequest::ResourceRequest() : ResourceRequest(NullURL()) {}
@@ -52,11 +55,11 @@ ResourceRequest::ResourceRequest(const KURL& url)
report_upload_progress_(false),
report_raw_headers_(false),
has_user_gesture_(false),
- download_to_file_(false),
download_to_blob_(false),
use_stream_on_response_(false),
keepalive_(false),
should_reset_app_cache_(false),
+ allow_stale_response_(false),
cache_mode_(mojom::FetchCacheMode::kDefault),
skip_service_worker_(false),
priority_(ResourceLoadPriority::kLowest),
@@ -75,13 +78,9 @@ ResourceRequest::ResourceRequest(const KURL& url)
did_set_http_referrer_(false),
check_for_browser_side_navigation_(true),
was_discarded_(false),
- ui_start_time_(0),
is_external_request_(false),
cors_preflight_policy_(
network::mojom::CORSPreflightPolicy::kConsiderPreflight),
- is_same_document_navigation_(false),
- input_perf_metric_report_policy_(
- InputToLoadPerfMetricReportPolicy::kNoReport),
redirect_status_(RedirectStatus::kNoRedirect) {}
ResourceRequest::ResourceRequest(CrossThreadResourceRequestData* data)
@@ -98,7 +97,6 @@ ResourceRequest::ResourceRequest(CrossThreadResourceRequestData* data)
SetAllowStoredCredentials(data->allow_stored_credentials_);
SetReportUploadProgress(data->report_upload_progress_);
SetHasUserGesture(data->has_user_gesture_);
- SetDownloadToFile(data->download_to_file_);
SetDownloadToBlob(data->download_to_blob_);
SetUseStreamOnResponse(data->use_stream_on_response_);
SetKeepalive(data->keepalive_);
@@ -119,18 +117,20 @@ ResourceRequest::ResourceRequest(CrossThreadResourceRequestData* data)
referrer_policy_ = data->referrer_policy_;
did_set_http_referrer_ = data->did_set_http_referrer_;
check_for_browser_side_navigation_ = data->check_for_browser_side_navigation_;
- ui_start_time_ = data->ui_start_time_;
is_external_request_ = data->is_external_request_;
cors_preflight_policy_ = data->cors_preflight_policy_;
- input_perf_metric_report_policy_ = data->input_perf_metric_report_policy_;
redirect_status_ = data->redirect_status_;
suggested_filename_ = data->suggested_filename_;
is_ad_resource_ = data->is_ad_resource_;
SetInitiatorCSP(data->navigation_csp_);
+ upgrade_if_insecure_ = data->upgrade_if_insecure_;
+ devtools_token_ = data->devtools_token_;
}
ResourceRequest::ResourceRequest(const ResourceRequest&) = default;
+ResourceRequest::~ResourceRequest() = default;
+
ResourceRequest& ResourceRequest::operator=(const ResourceRequest&) = default;
std::unique_ptr<ResourceRequest> ResourceRequest::CreateRedirectRequest(
@@ -152,7 +152,6 @@ std::unique_ptr<ResourceRequest> ResourceRequest::CreateRedirectRequest(
request->SetRedirectStatus(RedirectStatus::kFollowedRedirect);
// Copy from parameters for |this|.
- request->SetDownloadToFile(DownloadToFile());
request->SetDownloadToBlob(DownloadToBlob());
request->SetUseStreamOnResponse(UseStreamOnResponse());
request->SetRequestContext(GetRequestContext());
@@ -171,6 +170,7 @@ std::unique_ptr<ResourceRequest> ResourceRequest::CreateRedirectRequest(
if (IsAdResource())
request->SetIsAdResource();
request->SetInitiatorCSP(GetInitiatorCSP());
+ request->SetUpgradeIfInsecure(UpgradeIfInsecure());
return request;
}
@@ -194,7 +194,6 @@ std::unique_ptr<CrossThreadResourceRequestData> ResourceRequest::CopyData()
data->allow_stored_credentials_ = allow_stored_credentials_;
data->report_upload_progress_ = report_upload_progress_;
data->has_user_gesture_ = has_user_gesture_;
- data->download_to_file_ = download_to_file_;
data->download_to_blob_ = download_to_blob_;
data->use_stream_on_response_ = use_stream_on_response_;
data->keepalive_ = keepalive_;
@@ -215,15 +214,15 @@ std::unique_ptr<CrossThreadResourceRequestData> ResourceRequest::CopyData()
data->referrer_policy_ = referrer_policy_;
data->did_set_http_referrer_ = did_set_http_referrer_;
data->check_for_browser_side_navigation_ = check_for_browser_side_navigation_;
- data->ui_start_time_ = ui_start_time_;
data->is_external_request_ = is_external_request_;
data->cors_preflight_policy_ = cors_preflight_policy_;
- data->input_perf_metric_report_policy_ = input_perf_metric_report_policy_;
data->redirect_status_ = redirect_status_;
data->suggested_filename_ = suggested_filename_;
data->is_ad_resource_ = is_ad_resource_;
data->navigation_csp_ = initiator_csp_;
+ data->upgrade_if_insecure_ = upgrade_if_insecure_;
+ data->devtools_token_ = devtools_token_;
return data;
}
@@ -255,11 +254,12 @@ void ResourceRequest::SetCacheMode(mojom::FetchCacheMode cache_mode) {
cache_mode_ = cache_mode;
}
-double ResourceRequest::TimeoutInterval() const {
+base::TimeDelta ResourceRequest::TimeoutInterval() const {
return timeout_interval_;
}
-void ResourceRequest::SetTimeoutInterval(double timout_interval_seconds) {
+void ResourceRequest::SetTimeoutInterval(
+ base::TimeDelta timout_interval_seconds) {
timeout_interval_ = timout_interval_seconds;
}
@@ -473,4 +473,8 @@ bool ResourceRequest::NeedsHTTPOrigin() const {
return true;
}
+CrossThreadResourceRequestData::CrossThreadResourceRequestData() = default;
+
+CrossThreadResourceRequestData::~CrossThreadResourceRequestData() = default;
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h
index d71f7802808..cc93416d2e6 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request.h
@@ -29,7 +29,10 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_RESOURCE_REQUEST_H_
#include <memory>
+#include "base/macros.h"
#include "base/optional.h"
+#include "base/time/time.h"
+#include "base/unguessable_token.h"
#include "services/network/public/mojom/cors.mojom-blink.h"
#include "services/network/public/mojom/fetch_api.mojom-blink.h"
#include "services/network/public/mojom/request_context_frame_type.mojom-shared.h"
@@ -39,23 +42,18 @@
#include "third_party/blink/public/platform/web_content_security_policy_struct.h"
#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_load_priority.h"
-#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
#include "third_party/blink/renderer/platform/network/http_header_map.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/weborigin/referrer.h"
-#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
+#include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink {
-enum InputToLoadPerfMetricReportPolicy : uint8_t {
- kNoReport, // Don't report metrics for this ResourceRequest.
- kReportLink, // Report metrics for this request as initiated by a link click.
- kReportIntent, // Report metrics for this request as initiated by an intent.
-};
-
+class EncodedFormData;
+class SecurityOrigin;
struct CrossThreadResourceRequestData;
// A ResourceRequest is a "request" object for ResourceLoader. Conceptually
@@ -84,6 +82,8 @@ class PLATFORM_EXPORT ResourceRequest final {
ResourceRequest(const ResourceRequest&);
ResourceRequest& operator=(const ResourceRequest&);
+ ~ResourceRequest();
+
// Constructs a new ResourceRequest for a redirect from this instance.
std::unique_ptr<ResourceRequest> CreateRedirectRequest(
const KURL& new_url,
@@ -106,8 +106,8 @@ class PLATFORM_EXPORT ResourceRequest final {
mojom::FetchCacheMode GetCacheMode() const;
void SetCacheMode(mojom::FetchCacheMode);
- double TimeoutInterval() const; // May return 0 when using platform default.
- void SetTimeoutInterval(double);
+ base::TimeDelta TimeoutInterval() const;
+ void SetTimeoutInterval(base::TimeDelta);
const KURL& SiteForCookies() const;
void SetSiteForCookies(const KURL&);
@@ -205,12 +205,6 @@ class PLATFORM_EXPORT ResourceRequest final {
bool HasUserGesture() const { return has_user_gesture_; }
void SetHasUserGesture(bool);
- // True if request should be downloaded to file.
- bool DownloadToFile() const { return download_to_file_; }
- void SetDownloadToFile(bool download_to_file) {
- download_to_file_ = download_to_file;
- }
-
// True if request shuold be downloaded to blob.
bool DownloadToBlob() const { return download_to_blob_; }
void SetDownloadToBlob(bool download_to_blob) {
@@ -329,11 +323,6 @@ class PLATFORM_EXPORT ResourceRequest final {
bool WasDiscarded() const { return was_discarded_; }
void SetWasDiscarded(bool was_discarded) { was_discarded_ = was_discarded; }
- double UiStartTime() const { return ui_start_time_; }
- void SetUIStartTime(double ui_start_time_seconds) {
- ui_start_time_ = ui_start_time_seconds;
- }
-
// https://wicg.github.io/cors-rfc1918/#external-request
bool IsExternalRequest() const { return is_external_request_; }
void SetExternalRequestStateFromRequestorAddressSpace(mojom::IPAddressSpace);
@@ -345,14 +334,6 @@ class PLATFORM_EXPORT ResourceRequest final {
cors_preflight_policy_ = policy;
}
- InputToLoadPerfMetricReportPolicy InputPerfMetricReportPolicy() const {
- return input_perf_metric_report_policy_;
- }
- void SetInputPerfMetricReportPolicy(
- InputToLoadPerfMetricReportPolicy input_perf_metric_report_policy) {
- input_perf_metric_report_policy_ = input_perf_metric_report_policy;
- }
-
void SetRedirectStatus(RedirectStatus status) { redirect_status_ = status; }
RedirectStatus GetRedirectStatus() const { return redirect_status_; }
@@ -366,11 +347,6 @@ class PLATFORM_EXPORT ResourceRequest final {
void SetNavigationStartTime(TimeTicks);
TimeTicks NavigationStartTime() const { return navigation_start_; }
- void SetIsSameDocumentNavigation(bool is_same_document) {
- is_same_document_navigation_ = is_same_document;
- }
- bool IsSameDocumentNavigation() const { return is_same_document_navigation_; }
-
void SetIsAdResource() { is_ad_resource_ = true; }
bool IsAdResource() const { return is_ad_resource_; }
@@ -381,6 +357,25 @@ class PLATFORM_EXPORT ResourceRequest final {
return initiator_csp_;
}
+ void SetUpgradeIfInsecure(bool upgrade_if_insecure) {
+ upgrade_if_insecure_ = upgrade_if_insecure;
+ }
+ bool UpgradeIfInsecure() const { return upgrade_if_insecure_; }
+
+ void SetAllowStaleResponse(bool value) { allow_stale_response_ = value; }
+ bool AllowsStaleResponse() const { return allow_stale_response_; }
+
+ const base::Optional<base::UnguessableToken>& GetDevToolsToken() const {
+ return devtools_token_;
+ }
+ void SetDevToolsToken(
+ const base::Optional<base::UnguessableToken>& devtools_token) {
+ devtools_token_ = devtools_token;
+ }
+
+ void SetOriginPolicy(const String& policy) { origin_policy_ = policy; }
+ const String& GetOriginPolicy() const { return origin_policy_; }
+
private:
using SharableExtraData =
base::RefCountedData<std::unique_ptr<WebURLRequest::ExtraData>>;
@@ -390,8 +385,8 @@ class PLATFORM_EXPORT ResourceRequest final {
bool NeedsHTTPOrigin() const;
KURL url_;
- double timeout_interval_; // 0 is a magic value for platform default on
- // platforms that have one.
+ // TimeDelta::Max() represents the default timeout on platforms that have one.
+ base::TimeDelta timeout_interval_;
KURL site_for_cookies_;
// The SecurityOrigin specified by the ResourceLoaderOptions in case e.g.
@@ -408,11 +403,11 @@ class PLATFORM_EXPORT ResourceRequest final {
bool report_upload_progress_ : 1;
bool report_raw_headers_ : 1;
bool has_user_gesture_ : 1;
- bool download_to_file_ : 1;
bool download_to_blob_ : 1;
bool use_stream_on_response_ : 1;
bool keepalive_ : 1;
bool should_reset_app_cache_ : 1;
+ bool allow_stale_response_ : 1;
mojom::FetchCacheMode cache_mode_;
bool skip_service_worker_ : 1;
ResourceLoadPriority priority_;
@@ -433,22 +428,24 @@ class PLATFORM_EXPORT ResourceRequest final {
bool did_set_http_referrer_;
bool check_for_browser_side_navigation_;
bool was_discarded_;
- double ui_start_time_;
bool is_external_request_;
network::mojom::CORSPreflightPolicy cors_preflight_policy_;
- bool is_same_document_navigation_;
- InputToLoadPerfMetricReportPolicy input_perf_metric_report_policy_;
RedirectStatus redirect_status_;
base::Optional<String> suggested_filename_;
mutable CacheControlHeader cache_control_header_cache_;
- static double default_timeout_interval_;
+ static base::TimeDelta default_timeout_interval_;
TimeTicks navigation_start_;
bool is_ad_resource_ = false;
WebContentSecurityPolicyList initiator_csp_;
+
+ bool upgrade_if_insecure_ = false;
+
+ base::Optional<base::UnguessableToken> devtools_token_;
+ String origin_policy_;
};
// This class is needed to copy a ResourceRequest across threads, because it
@@ -459,16 +456,18 @@ class PLATFORM_EXPORT ResourceRequest final {
// threads (e.g., AtomicString)
// - Non-simple members need explicit copying (e.g., String::IsolatedCopy,
// KURL::Copy) rather than the copy constructor or the assignment operator.
-struct CrossThreadResourceRequestData {
- WTF_MAKE_NONCOPYABLE(CrossThreadResourceRequestData);
+struct PLATFORM_EXPORT CrossThreadResourceRequestData {
+ DISALLOW_COPY_AND_ASSIGN(CrossThreadResourceRequestData);
USING_FAST_MALLOC(CrossThreadResourceRequestData);
public:
- CrossThreadResourceRequestData() = default;
+ CrossThreadResourceRequestData();
+ ~CrossThreadResourceRequestData();
+
KURL url_;
mojom::FetchCacheMode cache_mode_;
- double timeout_interval_;
+ base::TimeDelta timeout_interval_;
KURL site_for_cookies_;
scoped_refptr<const SecurityOrigin> requestor_origin_;
@@ -478,7 +477,6 @@ struct CrossThreadResourceRequestData {
bool allow_stored_credentials_;
bool report_upload_progress_;
bool has_user_gesture_;
- bool download_to_file_;
bool download_to_blob_;
bool skip_service_worker_;
bool use_stream_on_response_;
@@ -500,14 +498,14 @@ struct CrossThreadResourceRequestData {
ReferrerPolicy referrer_policy_;
bool did_set_http_referrer_;
bool check_for_browser_side_navigation_;
- double ui_start_time_;
bool is_external_request_;
network::mojom::CORSPreflightPolicy cors_preflight_policy_;
- InputToLoadPerfMetricReportPolicy input_perf_metric_report_policy_;
ResourceRequest::RedirectStatus redirect_status_;
base::Optional<String> suggested_filename_;
bool is_ad_resource_;
WebContentSecurityPolicyList navigation_csp_;
+ bool upgrade_if_insecure_;
+ base::Optional<base::UnguessableToken> devtools_token_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request_test.cc
index 0c00adaf85c..b9aa59f9adc 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_request_test.cc
@@ -18,7 +18,7 @@ TEST(ResourceRequestTest, CrossThreadResourceRequestData) {
ResourceRequest original;
original.SetURL(KURL("http://www.example.com/test.htm"));
original.SetCacheMode(mojom::FetchCacheMode::kDefault);
- original.SetTimeoutInterval(10);
+ original.SetTimeoutInterval(base::TimeDelta::FromSeconds(10));
original.SetSiteForCookies(KURL("http://www.example.com/first_party.htm"));
original.SetRequestorOrigin(
SecurityOrigin::Create(KURL("http://www.example.com/first_party.htm")));
@@ -33,7 +33,7 @@ TEST(ResourceRequestTest, CrossThreadResourceRequestData) {
original.SetAllowStoredCredentials(false);
original.SetReportUploadProgress(false);
original.SetHasUserGesture(false);
- original.SetDownloadToFile(false);
+ original.SetDownloadToBlob(false);
original.SetSkipServiceWorker(false);
original.SetFetchRequestMode(network::mojom::FetchRequestMode::kCORS);
original.SetFetchCredentialsMode(
@@ -49,7 +49,7 @@ TEST(ResourceRequestTest, CrossThreadResourceRequestData) {
EXPECT_STREQ("http://www.example.com/test.htm",
original.Url().GetString().Utf8().data());
EXPECT_EQ(mojom::FetchCacheMode::kDefault, original.GetCacheMode());
- EXPECT_EQ(10, original.TimeoutInterval());
+ EXPECT_EQ(base::TimeDelta::FromSeconds(10), original.TimeoutInterval());
EXPECT_STREQ("http://www.example.com/first_party.htm",
original.SiteForCookies().GetString().Utf8().data());
EXPECT_STREQ("www.example.com",
@@ -63,7 +63,7 @@ TEST(ResourceRequestTest, CrossThreadResourceRequestData) {
EXPECT_FALSE(original.AllowStoredCredentials());
EXPECT_FALSE(original.ReportUploadProgress());
EXPECT_FALSE(original.HasUserGesture());
- EXPECT_FALSE(original.DownloadToFile());
+ EXPECT_FALSE(original.DownloadToBlob());
EXPECT_FALSE(original.GetSkipServiceWorker());
EXPECT_EQ(network::mojom::FetchRequestMode::kCORS,
original.GetFetchRequestMode());
@@ -85,7 +85,7 @@ TEST(ResourceRequestTest, CrossThreadResourceRequestData) {
EXPECT_STREQ("http://www.example.com/test.htm",
copy1.Url().GetString().Utf8().data());
EXPECT_EQ(mojom::FetchCacheMode::kDefault, copy1.GetCacheMode());
- EXPECT_EQ(10, copy1.TimeoutInterval());
+ EXPECT_EQ(base::TimeDelta::FromSeconds(10), copy1.TimeoutInterval());
EXPECT_STREQ("http://www.example.com/first_party.htm",
copy1.SiteForCookies().GetString().Utf8().data());
EXPECT_STREQ("www.example.com",
@@ -97,7 +97,7 @@ TEST(ResourceRequestTest, CrossThreadResourceRequestData) {
EXPECT_FALSE(copy1.AllowStoredCredentials());
EXPECT_FALSE(copy1.ReportUploadProgress());
EXPECT_FALSE(copy1.HasUserGesture());
- EXPECT_FALSE(copy1.DownloadToFile());
+ EXPECT_FALSE(copy1.DownloadToBlob());
EXPECT_FALSE(copy1.GetSkipServiceWorker());
EXPECT_EQ(network::mojom::FetchRequestMode::kCORS,
copy1.GetFetchRequestMode());
@@ -116,7 +116,7 @@ TEST(ResourceRequestTest, CrossThreadResourceRequestData) {
copy1.SetAllowStoredCredentials(true);
copy1.SetReportUploadProgress(true);
copy1.SetHasUserGesture(true);
- copy1.SetDownloadToFile(true);
+ copy1.SetDownloadToBlob(true);
copy1.SetSkipServiceWorker(true);
copy1.SetFetchRequestMode(network::mojom::FetchRequestMode::kNoCORS);
copy1.SetFetchCredentialsMode(network::mojom::FetchCredentialsMode::kInclude);
@@ -126,7 +126,7 @@ TEST(ResourceRequestTest, CrossThreadResourceRequestData) {
EXPECT_TRUE(copy2.AllowStoredCredentials());
EXPECT_TRUE(copy2.ReportUploadProgress());
EXPECT_TRUE(copy2.HasUserGesture());
- EXPECT_TRUE(copy2.DownloadToFile());
+ EXPECT_TRUE(copy2.DownloadToBlob());
EXPECT_TRUE(copy2.GetSkipServiceWorker());
EXPECT_EQ(network::mojom::FetchRequestMode::kNoCORS,
copy1.GetFetchRequestMode());
@@ -158,4 +158,19 @@ TEST(ResourceRequestTest, SetIsAdResource) {
EXPECT_TRUE(redirect_request->IsAdResource());
}
+TEST(ResourceRequestTest, UpgradeIfInsecureAcrossRedirects) {
+ ResourceRequest original;
+ EXPECT_FALSE(original.UpgradeIfInsecure());
+ original.SetUpgradeIfInsecure(true);
+ EXPECT_TRUE(original.UpgradeIfInsecure());
+
+ // Should persist across redirects.
+ std::unique_ptr<ResourceRequest> redirect_request =
+ original.CreateRedirectRequest(
+ KURL("https://example.test/redirect"), original.HttpMethod(),
+ original.SiteForCookies(), original.HttpReferrer(),
+ original.GetReferrerPolicy(), original.GetSkipServiceWorker());
+ EXPECT_TRUE(redirect_request->UpgradeIfInsecure());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
index 6e6281a18b5..8771ae8787b 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.cc
@@ -115,6 +115,7 @@ ResourceResponse::ResourceResponse(CrossThreadResourceResponseData* data)
data->was_fallback_required_by_service_worker_;
did_service_worker_navigation_preload_ =
data->did_service_worker_navigation_preload_;
+ async_revalidation_requested_ = data->async_revalidation_requested_;
response_type_via_service_worker_ = data->response_type_via_service_worker_;
security_style_ = data->security_style_;
security_details_.protocol = data->security_details_.protocol;
@@ -141,8 +142,6 @@ ResourceResponse::ResourceResponse(CrossThreadResourceResponseData* data)
encoded_data_length_ = data->encoded_data_length_;
encoded_body_length_ = data->encoded_body_length_;
decoded_body_length_ = data->decoded_body_length_;
- downloaded_file_path_ = data->downloaded_file_path_;
- downloaded_file_handle_ = data->downloaded_file_handle_;
// Bug https://bugs.webkit.org/show_bug.cgi?id=60397 this doesn't support
// whatever values may be present in the opaque m_extraData structure.
@@ -178,6 +177,7 @@ std::unique_ptr<CrossThreadResourceResponseData> ResourceResponse::CopyData()
was_fallback_required_by_service_worker_;
data->did_service_worker_navigation_preload_ =
did_service_worker_navigation_preload_;
+ data->async_revalidation_requested_ = async_revalidation_requested_;
data->response_type_via_service_worker_ = response_type_via_service_worker_;
data->security_style_ = security_style_;
data->security_details_.protocol = security_details_.protocol.IsolatedCopy();
@@ -211,8 +211,6 @@ std::unique_ptr<CrossThreadResourceResponseData> ResourceResponse::CopyData()
data->encoded_data_length_ = encoded_data_length_;
data->encoded_body_length_ = encoded_body_length_;
data->decoded_body_length_ = decoded_body_length_;
- data->downloaded_file_path_ = downloaded_file_path_.IsolatedCopy();
- data->downloaded_file_handle_ = downloaded_file_handle_;
// Bug https://bugs.webkit.org/show_bug.cgi?id=60397 this doesn't support
// whatever values may be present in the opaque m_extraData structure.
@@ -406,6 +404,19 @@ double ResourceResponse::CacheControlMaxAge() const {
return cache_control_header_.max_age;
}
+double ResourceResponse::CacheControlStaleWhileRevalidate() const {
+ if (!cache_control_header_.parsed) {
+ cache_control_header_ = ParseCacheControlDirectives(
+ http_header_fields_.Get(kCacheControlHeader),
+ http_header_fields_.Get(kPragmaHeader));
+ }
+ if (!std::isfinite(cache_control_header_.stale_while_revalidate) ||
+ cache_control_header_.stale_while_revalidate < 0) {
+ return 0;
+ }
+ return cache_control_header_.stale_while_revalidate;
+}
+
static double ParseDateValueInHeader(const HTTPHeaderMap& headers,
const AtomicString& header_name) {
const AtomicString& header_value = headers.Get(header_name);
@@ -563,20 +574,6 @@ void ResourceResponse::SetDecodedBodyLength(long long value) {
decoded_body_length_ = value;
}
-void ResourceResponse::SetDownloadedFilePath(
- const String& downloaded_file_path) {
- downloaded_file_path_ = downloaded_file_path;
- if (downloaded_file_path_.IsEmpty()) {
- downloaded_file_handle_ = nullptr;
- return;
- }
- // TODO(dmurph): Investigate whether we need the mimeType on this blob.
- std::unique_ptr<BlobData> blob_data =
- BlobData::CreateForFileWithUnknownSize(downloaded_file_path_);
- blob_data->DetachFromCurrentThread();
- downloaded_file_handle_ = BlobDataHandle::Create(std::move(blob_data), -1);
-}
-
void ResourceResponse::AppendRedirectResponse(
const ResourceResponse& response) {
redirect_responses_.push_back(response);
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h
index d25f83dfaba..05ba71260d8 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_response.h
@@ -61,8 +61,6 @@ struct CrossThreadResourceResponseData;
// member variable to this class, do not forget to add the corresponding
// one in CrossThreadResourceResponseData and write copying logic.
class PLATFORM_EXPORT ResourceResponse final {
- DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
-
public:
enum HTTPVersion : uint8_t {
kHTTPVersionUnknown,
@@ -222,6 +220,8 @@ class PLATFORM_EXPORT ResourceResponse final {
double Age() const;
double Expires() const;
double LastModified() const;
+ // Will always return values >= 0.
+ double CacheControlStaleWhileRevalidate() const;
unsigned ConnectionID() const;
void SetConnectionID(unsigned);
@@ -390,9 +390,6 @@ class PLATFORM_EXPORT ResourceResponse final {
long long DecodedBodyLength() const { return decoded_body_length_; }
void SetDecodedBodyLength(long long value);
- const String& DownloadedFilePath() const { return downloaded_file_path_; }
- void SetDownloadedFilePath(const String&);
-
// Extra data associated with this response.
ExtraData* GetExtraData() const { return extra_data_.get(); }
void SetExtraData(scoped_refptr<ExtraData> extra_data) {
@@ -412,6 +409,14 @@ class PLATFORM_EXPORT ResourceResponse final {
}
void AppendRedirectResponse(const ResourceResponse&);
+ bool AsyncRevalidationRequested() const {
+ return async_revalidation_requested_;
+ }
+
+ void SetAsyncRevalidationRequested(bool requested) {
+ async_revalidation_requested_ = requested;
+ }
+
// This method doesn't compare the all members.
static bool Compare(const ResourceResponse&, const ResourceResponse&);
@@ -474,6 +479,10 @@ class PLATFORM_EXPORT ResourceResponse final {
// the request for this resource.
bool did_service_worker_navigation_preload_ = false;
+ // True if this resource is stale and needs async revalidation. Will only
+ // possibly be set if the load_flags indicated SUPPORT_ASYNC_REVALIDATION.
+ bool async_revalidation_requested_ = false;
+
// The type of the response which was returned by the ServiceWorker.
network::mojom::FetchResponseType response_type_via_service_worker_ =
network::mojom::FetchResponseType::kDefault;
@@ -545,13 +554,6 @@ class PLATFORM_EXPORT ResourceResponse final {
// removed.
long long decoded_body_length_ = 0;
- // The downloaded file path if the load streamed to a file.
- String downloaded_file_path_;
-
- // The handle to the downloaded file to ensure the underlying file will not
- // be deleted.
- scoped_refptr<BlobDataHandle> downloaded_file_handle_;
-
// ExtraData associated with the response.
scoped_refptr<ExtraData> extra_data_;
@@ -610,14 +612,13 @@ struct CrossThreadResourceResponseData {
Vector<KURL> url_list_via_service_worker_;
String cache_storage_cache_name_;
bool did_service_worker_navigation_preload_;
+ bool async_revalidation_requested_;
Time response_time_;
String remote_ip_address_;
unsigned short remote_port_;
long long encoded_data_length_;
long long encoded_body_length_;
long long decoded_body_length_;
- String downloaded_file_path_;
- scoped_refptr<BlobDataHandle> downloaded_file_handle_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_test.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_test.cc
index 453c1c32137..b70b58bc65f 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/resource_test.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/resource_test.cc
@@ -421,4 +421,70 @@ TEST(ResourceTest, RedirectDuringRevalidation) {
EXPECT_FALSE(resource->IsAlive());
}
+TEST(ResourceTest, StaleWhileRevalidateCacheControl) {
+ ScopedTestingPlatformSupport<MockPlatform> mock;
+ const KURL url("http://127.0.0.1:8000/foo.html");
+ ResourceResponse response(url);
+ response.SetHTTPStatusCode(200);
+ response.SetHTTPHeaderField(HTTPNames::Cache_Control,
+ "max-age=0, stale-while-revalidate=40");
+
+ MockResource* resource = MockResource::Create(url);
+ resource->ResponseReceived(response, nullptr);
+ resource->FinishForTest();
+
+ EXPECT_FALSE(resource->MustRevalidateDueToCacheHeaders(false));
+ EXPECT_FALSE(resource->MustRevalidateDueToCacheHeaders(true));
+ EXPECT_FALSE(resource->ShouldRevalidateStaleResponse());
+
+ mock->AdvanceClockSeconds(1);
+ EXPECT_TRUE(resource->MustRevalidateDueToCacheHeaders(false));
+ EXPECT_FALSE(resource->MustRevalidateDueToCacheHeaders(true));
+ EXPECT_TRUE(resource->ShouldRevalidateStaleResponse());
+
+ mock->AdvanceClockSeconds(40);
+ EXPECT_TRUE(resource->MustRevalidateDueToCacheHeaders(false));
+ EXPECT_TRUE(resource->MustRevalidateDueToCacheHeaders(true));
+ EXPECT_TRUE(resource->ShouldRevalidateStaleResponse());
+}
+
+TEST(ResourceTest, StaleWhileRevalidateCacheControlWithRedirect) {
+ ScopedTestingPlatformSupport<MockPlatform> mock;
+ const KURL url("http://127.0.0.1:8000/foo.html");
+ const KURL redirect_target_url("http://127.0.0.1:8000/food.html");
+ ResourceResponse response(url);
+ response.SetHTTPHeaderField(HTTPNames::Cache_Control, "max-age=50");
+ response.SetHTTPStatusCode(200);
+
+ // The revalidating request is redirected.
+ ResourceResponse redirect_response(url);
+ redirect_response.SetHTTPHeaderField(
+ "location", AtomicString(redirect_target_url.GetString()));
+ redirect_response.SetHTTPStatusCode(302);
+ redirect_response.SetHTTPHeaderField(HTTPNames::Cache_Control,
+ "max-age=0, stale-while-revalidate=40");
+ redirect_response.SetAsyncRevalidationRequested(true);
+ ResourceRequest redirected_revalidating_request(redirect_target_url);
+
+ MockResource* resource = MockResource::Create(url);
+ resource->WillFollowRedirect(redirected_revalidating_request,
+ redirect_response);
+ resource->ResponseReceived(response, nullptr);
+ resource->FinishForTest();
+
+ EXPECT_FALSE(resource->MustRevalidateDueToCacheHeaders(false));
+ EXPECT_FALSE(resource->MustRevalidateDueToCacheHeaders(true));
+ EXPECT_FALSE(resource->ShouldRevalidateStaleResponse());
+
+ mock->AdvanceClockSeconds(41);
+
+ // MustRevalidateDueToCacheHeaders only looks at the stored response not
+ // any redirects but ShouldRevalidate and AsyncRevalidationRequest look
+ // at the entire redirect chain.
+ EXPECT_FALSE(resource->MustRevalidateDueToCacheHeaders(false));
+ EXPECT_FALSE(resource->MustRevalidateDueToCacheHeaders(true));
+ EXPECT_TRUE(resource->ShouldRevalidateStaleResponse());
+ EXPECT_TRUE(resource->StaleRevalidationRequested());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h b/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h
index 57883285a4a..6aec651490b 100644
--- a/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h
@@ -10,6 +10,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/integrity_metadata.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/weborigin/referrer_policy.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -29,18 +30,21 @@ class PLATFORM_EXPORT ScriptFetchOptions final {
// is "omit"." [spec text]
ScriptFetchOptions()
: parser_state_(ParserDisposition::kNotParserInserted),
- credentials_mode_(network::mojom::FetchCredentialsMode::kOmit) {}
+ credentials_mode_(network::mojom::FetchCredentialsMode::kOmit),
+ referrer_policy_(kReferrerPolicyDefault) {}
ScriptFetchOptions(const String& nonce,
const IntegrityMetadataSet& integrity_metadata,
const String& integrity_attribute,
ParserDisposition parser_state,
- network::mojom::FetchCredentialsMode credentials_mode)
+ network::mojom::FetchCredentialsMode credentials_mode,
+ ReferrerPolicy referrer_policy)
: nonce_(nonce),
integrity_metadata_(integrity_metadata),
integrity_attribute_(integrity_attribute),
parser_state_(parser_state),
- credentials_mode_(credentials_mode) {}
+ credentials_mode_(credentials_mode),
+ referrer_policy_(referrer_policy) {}
~ScriptFetchOptions() = default;
const String& Nonce() const { return nonce_; }
@@ -54,6 +58,7 @@ class PLATFORM_EXPORT ScriptFetchOptions final {
network::mojom::FetchCredentialsMode CredentialsMode() const {
return credentials_mode_;
}
+ ReferrerPolicy GetReferrerPolicy() const { return referrer_policy_; }
// https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-classic-script
// Steps 1 and 3.
@@ -75,6 +80,9 @@ class PLATFORM_EXPORT ScriptFetchOptions final {
// https://html.spec.whatwg.org/multipage/webappapis.html#concept-script-fetch-options-credentials
const network::mojom::FetchCredentialsMode credentials_mode_;
+
+ // https://html.spec.whatwg.org/multipage/webappapis.html#concept-script-fetch-options-referrer-policy
+ const ReferrerPolicy referrer_policy_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc b/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc
new file mode 100644
index 00000000000..9a63f9b5e24
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc
@@ -0,0 +1,41 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h"
+
+#include "base/metrics/histogram_macros.h"
+#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
+
+namespace blink {
+
+StaleRevalidationResourceClient::StaleRevalidationResourceClient(
+ Resource* stale_resource)
+ : start_time_(CurrentTimeTicks()), stale_resource_(stale_resource) {}
+
+StaleRevalidationResourceClient::~StaleRevalidationResourceClient() = default;
+
+void StaleRevalidationResourceClient::NotifyFinished(Resource* resource) {
+ // After the load is finished
+ if (stale_resource_ && IsMainThread())
+ GetMemoryCache()->Remove(stale_resource_);
+ ClearResource();
+
+ TimeTicks finish_time = resource->LoadFinishTime();
+ if (!finish_time.is_null()) {
+ UMA_HISTOGRAM_LONG_TIMES(
+ "Blink.ResourceFetcher.StaleWhileRevalidateDuration",
+ finish_time - start_time_);
+ }
+}
+
+void StaleRevalidationResourceClient::Trace(blink::Visitor* visitor) {
+ visitor->Trace(stale_resource_);
+ RawResourceClient::Trace(visitor);
+}
+
+String StaleRevalidationResourceClient::DebugName() const {
+ return "StaleRevalidation";
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h b/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h
new file mode 100644
index 00000000000..6a7b729faa6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.h
@@ -0,0 +1,41 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_STALE_REVALIDATION_RESOURCE_CLIENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_STALE_REVALIDATION_RESOURCE_CLIENT_H_
+
+#include "third_party/blink/renderer/platform/loader/fetch/raw_resource.h"
+
+namespace blink {
+
+// Stale Revalidation Resources are requests to the network stack without the
+// allow staleness bit set on. This should cause the network stack's http cache
+// to revalidate the resource. When the request has been completed the original
+// resource will be removed from the memory cache.
+class StaleRevalidationResourceClient
+ : public GarbageCollectedFinalized<StaleRevalidationResourceClient>,
+ public RawResourceClient {
+ USING_GARBAGE_COLLECTED_MIXIN(StaleRevalidationResourceClient);
+
+ public:
+ explicit StaleRevalidationResourceClient(Resource* stale_resource);
+ ~StaleRevalidationResourceClient() override;
+
+ // RawResourceClient overloads.
+ void NotifyFinished(Resource* resource) override;
+ void Trace(blink::Visitor* visitor) override;
+ String DebugName() const override;
+
+ private:
+ base::TimeTicks start_time_;
+ // |stale_resource_| is the original resource that will be removed from the
+ // MemoryCache when this revalidation request is completed. Note that it is
+ // different than the active resource for this resource client which accessed
+ // via |GetResource()|.
+ WeakMember<Resource> stale_resource_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_LOADER_FETCH_STALE_REVALIDATION_RESOURCE_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/fetch_testing_platform_support.cc b/chromium/third_party/blink/renderer/platform/loader/testing/fetch_testing_platform_support.cc
index ac86a8cca00..5bf93981f03 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/fetch_testing_platform_support.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/fetch_testing_platform_support.cc
@@ -12,6 +12,7 @@
#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
#include "third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h"
#include "third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
#include "third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.h"
namespace blink {
@@ -29,7 +30,8 @@ FetchTestingPlatformSupport::~FetchTestingPlatformSupport() {
MockFetchContext* FetchTestingPlatformSupport::Context() {
if (!context_) {
context_ =
- MockFetchContext::Create(MockFetchContext::kShouldLoadNewResource);
+ MockFetchContext::Create(MockFetchContext::kShouldLoadNewResource,
+ scheduler_->DefaultTaskRunner());
}
return context_;
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h b/chromium/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
index b22a12df81a..a2e6067e25c 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
@@ -86,11 +86,6 @@ class MockFetchContext : public FetchContext {
ResourceRequest::RedirectStatus redirect_status) const override {
return base::nullopt;
}
- base::Optional<ResourceRequestBlockedReason> CheckResponseNosniff(
- WebURLRequest::RequestContext,
- const ResourceResponse&) const override {
- return base::nullopt;
- }
bool ShouldLoadNewResource(Resource::Type) const override {
return load_policy_ == kShouldLoadNewResource;
}
@@ -102,14 +97,14 @@ class MockFetchContext : public FetchContext {
std::unique_ptr<WebURLLoader> CreateURLLoader(
const ResourceRequest& request,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
const ResourceLoaderOptions&) override {
if (!url_loader_factory_) {
url_loader_factory_ =
Platform::Current()->CreateDefaultURLLoaderFactory();
}
WrappedResourceRequest wrapped(request);
- return url_loader_factory_->CreateURLLoader(wrapped, task_runner);
+ return url_loader_factory_->CreateURLLoader(
+ wrapped, CreateResourceLoadingTaskRunnerHandle());
}
ResourceLoadScheduler::ThrottlingPolicy InitialLoadThrottlingPolicy()
@@ -125,6 +120,12 @@ class MockFetchContext : public FetchContext {
return frame_scheduler_->GetTaskRunner(TaskType::kInternalTest);
}
+ std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>
+ CreateResourceLoadingTaskRunnerHandle() override {
+ return scheduler::WebResourceLoadingTaskRunnerHandle::CreateUnprioritized(
+ GetLoadingTaskRunner());
+ }
+
private:
class MockFrameScheduler final : public scheduler::FakeFrameScheduler {
public:
@@ -147,7 +148,7 @@ class MockFetchContext : public FetchContext {
runner_(loading_task_runner
? std::move(loading_task_runner)
: base::MakeRefCounted<scheduler::FakeTaskRunner>()),
- security_origin_(SecurityOrigin::CreateUnique()),
+ security_origin_(SecurityOrigin::CreateUniqueOpaque()),
frame_scheduler_(new MockFrameScheduler(runner_)),
complete_(false),
transfer_size_(-1) {}
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.cc b/chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.cc
index 3297570e76a..674b46921af 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.cc
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.cc
@@ -17,7 +17,7 @@ WebURLLoaderFactoryWithMock::~WebURLLoaderFactoryWithMock() = default;
std::unique_ptr<WebURLLoader> WebURLLoaderFactoryWithMock::CreateURLLoader(
const WebURLRequest& request,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>) {
return mock_factory_->CreateURLLoader(nullptr);
}
diff --git a/chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.h b/chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.h
index 3949dfb1182..fb02d9e0c80 100644
--- a/chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.h
+++ b/chromium/third_party/blink/renderer/platform/loader/testing/web_url_loader_factory_with_mock.h
@@ -21,7 +21,8 @@ class WebURLLoaderFactoryWithMock : public WebURLLoaderFactory {
std::unique_ptr<WebURLLoader> CreateURLLoader(
const WebURLRequest&,
- scoped_refptr<base::SingleThreadTaskRunner>) override;
+ std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle>)
+ override;
private:
// Not owned. The mock factory should outlive |this|.
diff --git a/chromium/third_party/blink/renderer/platform/long_task_detector.cc b/chromium/third_party/blink/renderer/platform/long_task_detector.cc
index 57ee22627ff..c4b1dc858c1 100644
--- a/chromium/third_party/blink/renderer/platform/long_task_detector.cc
+++ b/chromium/third_party/blink/renderer/platform/long_task_detector.cc
@@ -9,6 +9,8 @@
namespace blink {
+constexpr base::TimeDelta LongTaskDetector::kLongTaskThreshold;
+
// static
LongTaskDetector& LongTaskDetector::Instance() {
DEFINE_STATIC_LOCAL(Persistent<LongTaskDetector>, long_task_detector,
@@ -36,13 +38,13 @@ void LongTaskDetector::UnregisterObserver(LongTaskObserver* observer) {
}
}
-void LongTaskDetector::DidProcessTask(double start_time, double end_time) {
- if ((end_time - start_time) < LongTaskDetector::kLongTaskThresholdSeconds)
+void LongTaskDetector::DidProcessTask(base::TimeTicks start_time,
+ base::TimeTicks end_time) {
+ if ((end_time - start_time) < LongTaskDetector::kLongTaskThreshold)
return;
for (auto& observer : observers_) {
- observer->OnLongTaskDetected(TimeTicksFromSeconds(start_time),
- TimeTicksFromSeconds(end_time));
+ observer->OnLongTaskDetected(start_time, end_time);
}
}
diff --git a/chromium/third_party/blink/renderer/platform/long_task_detector.h b/chromium/third_party/blink/renderer/platform/long_task_detector.h
index d4ecc9af7a3..8c0a19ac8f5 100644
--- a/chromium/third_party/blink/renderer/platform/long_task_detector.h
+++ b/chromium/third_party/blink/renderer/platform/long_task_detector.h
@@ -5,10 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_LONG_TASK_DETECTOR_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_LONG_TASK_DETECTOR_H_
+#include "base/task/sequence_manager/task_time_observer.h"
#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_time_observer.h"
#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
@@ -39,16 +39,18 @@ class PLATFORM_EXPORT LongTaskDetector final
void Trace(blink::Visitor*);
- static constexpr double kLongTaskThresholdSeconds = 0.05;
+ static constexpr base::TimeDelta kLongTaskThreshold =
+ base::TimeDelta::FromMilliseconds(50);
private:
LongTaskDetector();
// scheduler::TaskTimeObserver implementation
- void WillProcessTask(double start_time) override {}
- void DidProcessTask(double start_time, double end_time) override;
+ void WillProcessTask(base::TimeTicks start_time) override {}
+ void DidProcessTask(base::TimeTicks start_time,
+ base::TimeTicks end_time) override;
- HeapHashSet<WeakMember<LongTaskObserver>> observers_;
+ HeapHashSet<Member<LongTaskObserver>> observers_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/long_task_detector_test.cc b/chromium/third_party/blink/renderer/platform/long_task_detector_test.cc
index 0758c7c07a8..bae1d360e32 100644
--- a/chromium/third_party/blink/renderer/platform/long_task_detector_test.cc
+++ b/chromium/third_party/blink/renderer/platform/long_task_detector_test.cc
@@ -35,9 +35,9 @@ class TestLongTaskObserver :
class LongTaskDetectorTest : public testing::Test {
public:
// Public because it's executed on a task queue.
- void DummyTaskWithDuration(double duration_seconds) {
+ void DummyTaskWithDuration(base::TimeDelta duration) {
dummy_task_start_time_ = CurrentTimeTicks();
- platform_->AdvanceClockSeconds(duration_seconds);
+ platform_->AdvanceClock(duration);
dummy_task_end_time_ = CurrentTimeTicks();
}
@@ -52,11 +52,11 @@ class LongTaskDetectorTest : public testing::Test {
TimeTicks DummyTaskEndTime() { return dummy_task_end_time_; }
- void SimulateTask(double duration_seconds) {
+ void SimulateTask(base::TimeDelta duration) {
PostCrossThreadTask(
*platform_->CurrentThread()->GetTaskRunner(), FROM_HERE,
CrossThreadBind(&LongTaskDetectorTest::DummyTaskWithDuration,
- CrossThreadUnretained(this), duration_seconds));
+ CrossThreadUnretained(this), duration));
platform_->RunUntilIdle();
}
@@ -70,18 +70,21 @@ class LongTaskDetectorTest : public testing::Test {
TEST_F(LongTaskDetectorTest, DeliversLongTaskNotificationOnlyWhenRegistered) {
TestLongTaskObserver* long_task_observer = new TestLongTaskObserver();
- SimulateTask(LongTaskDetector::kLongTaskThresholdSeconds + 0.01);
+ SimulateTask(LongTaskDetector::kLongTaskThreshold +
+ base::TimeDelta::FromMilliseconds(10));
EXPECT_EQ(long_task_observer->last_long_task_end, TimeTicks());
LongTaskDetector::Instance().RegisterObserver(long_task_observer);
- SimulateTask(LongTaskDetector::kLongTaskThresholdSeconds + 0.01);
+ SimulateTask(LongTaskDetector::kLongTaskThreshold +
+ base::TimeDelta::FromMilliseconds(10));
TimeTicks long_task_end_when_registered = DummyTaskEndTime();
EXPECT_EQ(long_task_observer->last_long_task_start, DummyTaskStartTime());
EXPECT_EQ(long_task_observer->last_long_task_end,
long_task_end_when_registered);
LongTaskDetector::Instance().UnregisterObserver(long_task_observer);
- SimulateTask(LongTaskDetector::kLongTaskThresholdSeconds + 0.01);
+ SimulateTask(LongTaskDetector::kLongTaskThreshold +
+ base::TimeDelta::FromMilliseconds(10));
// Check that we have a long task after unregistering observer.
ASSERT_FALSE(long_task_end_when_registered == DummyTaskEndTime());
EXPECT_EQ(long_task_observer->last_long_task_end,
@@ -91,10 +94,12 @@ TEST_F(LongTaskDetectorTest, DeliversLongTaskNotificationOnlyWhenRegistered) {
TEST_F(LongTaskDetectorTest, DoesNotGetNotifiedOfShortTasks) {
TestLongTaskObserver* long_task_observer = new TestLongTaskObserver();
LongTaskDetector::Instance().RegisterObserver(long_task_observer);
- SimulateTask(LongTaskDetector::kLongTaskThresholdSeconds - 0.01);
+ SimulateTask(LongTaskDetector::kLongTaskThreshold -
+ base::TimeDelta::FromMilliseconds(10));
EXPECT_EQ(long_task_observer->last_long_task_end, TimeTicks());
- SimulateTask(LongTaskDetector::kLongTaskThresholdSeconds + 0.01);
+ SimulateTask(LongTaskDetector::kLongTaskThreshold +
+ base::TimeDelta::FromMilliseconds(10));
EXPECT_EQ(long_task_observer->last_long_task_end, DummyTaskEndTime());
LongTaskDetector::Instance().UnregisterObserver(long_task_observer);
}
@@ -104,7 +109,8 @@ TEST_F(LongTaskDetectorTest, RegisterSameObserverTwice) {
LongTaskDetector::Instance().RegisterObserver(long_task_observer);
LongTaskDetector::Instance().RegisterObserver(long_task_observer);
- SimulateTask(LongTaskDetector::kLongTaskThresholdSeconds + 0.01);
+ SimulateTask(LongTaskDetector::kLongTaskThreshold +
+ base::TimeDelta::FromMilliseconds(10));
TimeTicks long_task_end_when_registered = DummyTaskEndTime();
EXPECT_EQ(long_task_observer->last_long_task_start, DummyTaskStartTime());
EXPECT_EQ(long_task_observer->last_long_task_end,
@@ -113,7 +119,8 @@ TEST_F(LongTaskDetectorTest, RegisterSameObserverTwice) {
LongTaskDetector::Instance().UnregisterObserver(long_task_observer);
// Should only need to unregister once even after we called RegisterObserver
// twice.
- SimulateTask(LongTaskDetector::kLongTaskThresholdSeconds + 0.01);
+ SimulateTask(LongTaskDetector::kLongTaskThreshold +
+ base::TimeDelta::FromMilliseconds(10));
ASSERT_FALSE(long_task_end_when_registered == DummyTaskEndTime());
EXPECT_EQ(long_task_observer->last_long_task_end,
long_task_end_when_registered);
diff --git a/chromium/third_party/blink/renderer/platform/mac/DEPS b/chromium/third_party/blink/renderer/platform/mac/DEPS
index 5047015afce..b3290217b08 100644
--- a/chromium/third_party/blink/renderer/platform/mac/DEPS
+++ b/chromium/third_party/blink/renderer/platform/mac/DEPS
@@ -6,11 +6,11 @@ include_rules = [
"+third_party/blink/renderer/platform/mac",
# Dependencies.
+ "+cc/paint",
"+third_party/blink/renderer/platform/animation/timing_function.h",
"+third_party/blink/renderer/platform/geometry",
"+third_party/blink/renderer/platform/graphics",
"+third_party/blink/renderer/platform/heap",
- "+third_party/blink/renderer/platform/kill_ring.h",
"+third_party/blink/renderer/platform/platform_export.h",
"+third_party/blink/renderer/platform/runtime_enabled_features.h",
"+third_party/blink/renderer/platform/scheduler",
diff --git a/chromium/third_party/blink/renderer/platform/mac/graphics_context_canvas.h b/chromium/third_party/blink/renderer/platform/mac/graphics_context_canvas.h
index 437044de936..6d60f2bf1c1 100644
--- a/chromium/third_party/blink/renderer/platform/mac/graphics_context_canvas.h
+++ b/chromium/third_party/blink/renderer/platform/mac/graphics_context_canvas.h
@@ -7,12 +7,15 @@
#include <ApplicationServices/ApplicationServices.h>
-#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/skia/include/core/SkBitmap.h"
struct SkIRect;
+namespace cc {
+class PaintCanvas;
+}
+
namespace blink {
// Creates a bridge for painting into a PaintCanvas with a CGContext.
@@ -26,7 +29,7 @@ class PLATFORM_EXPORT GraphicsContextCanvas {
// The |paint_rect| is in canvas device space. The CgContext is set
// up to be in exactly the same space as the canvas is at construction
// time.
- GraphicsContextCanvas(PaintCanvas*,
+ GraphicsContextCanvas(cc::PaintCanvas*,
const SkIRect& paint_rect,
SkScalar bitmap_scale_factor = 1);
~GraphicsContextCanvas();
@@ -36,7 +39,7 @@ class PLATFORM_EXPORT GraphicsContextCanvas {
private:
void ReleaseIfNeeded();
- PaintCanvas* canvas_;
+ cc::PaintCanvas* canvas_;
CGContextRef cg_context_;
SkBitmap offscreen_;
diff --git a/chromium/third_party/blink/renderer/platform/mac/graphics_context_canvas.mm b/chromium/third_party/blink/renderer/platform/mac/graphics_context_canvas.mm
index 73936289674..2ce49b3d592 100644
--- a/chromium/third_party/blink/renderer/platform/mac/graphics_context_canvas.mm
+++ b/chromium/third_party/blink/renderer/platform/mac/graphics_context_canvas.mm
@@ -7,13 +7,14 @@
#import <AppKit/AppKit.h>
#import <CoreGraphics/CoreGraphics.h>
+#include "cc/paint/paint_canvas.h"
#include "skia/ext/skia_utils_mac.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/retain_ptr.h"
namespace blink {
-GraphicsContextCanvas::GraphicsContextCanvas(PaintCanvas* canvas,
+GraphicsContextCanvas::GraphicsContextCanvas(cc::PaintCanvas* canvas,
const SkIRect& paint_rect,
SkScalar bitmap_scale_factor)
: canvas_(canvas),
@@ -37,7 +38,8 @@ void GraphicsContextCanvas::ReleaseIfNeeded() {
canvas_->setMatrix(SkMatrix::I()); // Reset back to device space.
canvas_->translate(paint_rect_.x(), paint_rect_.y());
canvas_->scale(1.f / bitmap_scale_factor_, 1.f / bitmap_scale_factor_);
- canvas_->drawBitmap(offscreen_, 0, 0);
+ canvas_->drawImage(cc::PaintImage::CreateFromBitmap(std::move(offscreen_)), 0,
+ 0);
canvas_->restore();
CGContextRelease(cg_context_);
diff --git a/chromium/third_party/blink/renderer/platform/mac/graphics_context_canvas_test.mm b/chromium/third_party/blink/renderer/platform/mac/graphics_context_canvas_test.mm
index 6c2f820c8bd..20905d9cee4 100644
--- a/chromium/third_party/blink/renderer/platform/mac/graphics_context_canvas_test.mm
+++ b/chromium/third_party/blink/renderer/platform/mac/graphics_context_canvas_test.mm
@@ -2,9 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "third_party/blink/renderer/platform/mac/graphics_context_canvas.h"
#include "skia/ext/skia_utils_mac.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/mac/graphics_context_canvas.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/mac/kill_ring_mac.mm b/chromium/third_party/blink/renderer/platform/mac/kill_ring_mac.mm
deleted file mode 100644
index 98dea7c4c3c..00000000000
--- a/chromium/third_party/blink/renderer/platform/mac/kill_ring_mac.mm
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 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 GOOGLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import "third_party/blink/renderer/platform/kill_ring.h"
-
-namespace blink {
-
-extern "C" {
-
-// Kill ring calls. Would be better to use NSKillRing.h, but that's not
-// available as API or SPI.
-
-void _NSInitializeKillRing();
-void _NSAppendToKillRing(NSString*);
-void _NSPrependToKillRing(NSString*);
-NSString* _NSYankFromKillRing();
-void _NSNewKillRingSequence();
-void _NSSetKillRingToYankedState();
-}
-
-static void InitializeKillRingIfNeeded() {
- static bool initialized_kill_ring = false;
- if (!initialized_kill_ring) {
- initialized_kill_ring = true;
- _NSInitializeKillRing();
- }
-}
-
-void KillRing::Append(const String& string) {
- InitializeKillRingIfNeeded();
- _NSAppendToKillRing(string);
-}
-
-void KillRing::Prepend(const String& string) {
- InitializeKillRingIfNeeded();
- _NSPrependToKillRing(string);
-}
-
-String KillRing::Yank() {
- InitializeKillRingIfNeeded();
- return _NSYankFromKillRing();
-}
-
-void KillRing::StartNewSequence() {
- InitializeKillRingIfNeeded();
- _NSNewKillRingSequence();
-}
-
-void KillRing::SetToYankedState() {
- InitializeKillRingIfNeeded();
- _NSSetKillRingToYankedState();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mac/local_current_graphics_context.h b/chromium/third_party/blink/renderer/platform/mac/local_current_graphics_context.h
index bf4ba51c701..abd16b1c8fe 100644
--- a/chromium/third_party/blink/renderer/platform/mac/local_current_graphics_context.h
+++ b/chromium/third_party/blink/renderer/platform/mac/local_current_graphics_context.h
@@ -21,15 +21,17 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MAC_LOCAL_CURRENT_GRAPHICS_CONTEXT_H_
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/mac/graphics_context_canvas.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
OBJC_CLASS NSGraphicsContext;
-namespace blink {
+namespace cc {
+class PaintCanvas;
+}
+namespace blink {
class GraphicsContext;
// This class automatically saves and restores the current NSGraphicsContext for
@@ -39,14 +41,14 @@ class PLATFORM_EXPORT LocalCurrentGraphicsContext {
public:
LocalCurrentGraphicsContext(GraphicsContext&, const IntRect& dirty_rect);
- LocalCurrentGraphicsContext(PaintCanvas*,
+ LocalCurrentGraphicsContext(cc::PaintCanvas*,
float device_scale_factor,
const IntRect& dirty_rect);
~LocalCurrentGraphicsContext();
CGContextRef CgContext();
private:
- PaintCanvas* saved_canvas_;
+ cc::PaintCanvas* saved_canvas_;
NSGraphicsContext* saved_ns_graphics_context_;
bool did_set_graphics_context_;
IntRect inflated_dirty_rect_;
diff --git a/chromium/third_party/blink/renderer/platform/mac/local_current_graphics_context.mm b/chromium/third_party/blink/renderer/platform/mac/local_current_graphics_context.mm
index 1c9a7900d49..350c68d84d8 100644
--- a/chromium/third_party/blink/renderer/platform/mac/local_current_graphics_context.mm
+++ b/chromium/third_party/blink/renderer/platform/mac/local_current_graphics_context.mm
@@ -37,7 +37,7 @@ LocalCurrentGraphicsContext::LocalCurrentGraphicsContext(
static const int kMaxDirtyRectPixelSize = 10000;
-static SkIRect LocalToClampedDeviceRect(PaintCanvas* canvas,
+static SkIRect LocalToClampedDeviceRect(cc::PaintCanvas* canvas,
const IntRect& local) {
const SkMatrix& matrix = canvas->getTotalMatrix();
SkRect device;
@@ -55,7 +55,7 @@ static SkIRect LocalToClampedDeviceRect(PaintCanvas* canvas,
}
LocalCurrentGraphicsContext::LocalCurrentGraphicsContext(
- PaintCanvas* canvas,
+ cc::PaintCanvas* canvas,
float device_scale_factor,
const IntRect& dirty_rect)
: did_set_graphics_context_(false),
diff --git a/chromium/third_party/blink/renderer/platform/mac/scroll_animator_mac.mm b/chromium/third_party/blink/renderer/platform/mac/scroll_animator_mac.mm
index 4b87883d49f..84f2c3ef4e0 100644
--- a/chromium/third_party/blink/renderer/platform/mac/scroll_animator_mac.mm
+++ b/chromium/third_party/blink/renderer/platform/mac/scroll_animator_mac.mm
@@ -799,7 +799,7 @@ void ScrollAnimatorMac::ImmediateScrollTo(const ScrollOffset& new_offset) {
ScrollOffset adjusted_offset = AdjustScrollOffsetIfNecessary(new_offset);
bool offset_changed = adjusted_offset != current_offset_;
- if (!offset_changed && !GetScrollableArea()->ScrollOriginChanged())
+ if (!offset_changed)
return;
ScrollOffset delta = adjusted_offset - current_offset_;
diff --git a/chromium/third_party/blink/renderer/platform/mac/theme_mac.h b/chromium/third_party/blink/renderer/platform/mac/theme_mac.h
index ac60fc68067..4548eee57be 100644
--- a/chromium/third_party/blink/renderer/platform/mac/theme_mac.h
+++ b/chromium/third_party/blink/renderer/platform/mac/theme_mac.h
@@ -96,7 +96,7 @@ class ThemeMac : public Theme {
float zoom_factor);
static PLATFORM_EXPORT const IntSize* CheckboxSizes();
static PLATFORM_EXPORT const int* CheckboxMargins(NSControlSize);
- static PLATFORM_EXPORT NSView* EnsuredView(ScrollableArea*);
+ static PLATFORM_EXPORT NSView* EnsuredView(const IntSize&);
static PLATFORM_EXPORT const IntSize* RadioSizes();
static PLATFORM_EXPORT const int* RadioMargins(NSControlSize);
diff --git a/chromium/third_party/blink/renderer/platform/mac/theme_mac.mm b/chromium/third_party/blink/renderer/platform/mac/theme_mac.mm
index 2fb60f36bdf..b5308fdeeed 100644
--- a/chromium/third_party/blink/renderer/platform/mac/theme_mac.mm
+++ b/chromium/third_party/blink/renderer/platform/mac/theme_mac.mm
@@ -154,11 +154,10 @@ static void UpdateStates(NSCell* cell, ControlStates states) {
}
// Return a fake NSView whose sole purpose is to tell AppKit that it's flipped.
-NSView* ThemeMac::EnsuredView(ScrollableArea* scrollable_area) {
+NSView* ThemeMac::EnsuredView(const IntSize& size) {
// Use a fake flipped view.
static NSView* flipped_view = [[BlinkFlippedControl alloc] init];
- [flipped_view
- setFrameSize:NSSizeFromCGSize(CGSize(scrollable_area->ContentsSize()))];
+ [flipped_view setFrameSize:NSSizeFromCGSize(CGSize(size))];
return flipped_view;
}
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_center.cc b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_center.cc
index 8641d27b88b..7e6ff05cd7a 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_center.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_center.cc
@@ -39,7 +39,6 @@
#include "third_party/blink/public/platform/web_media_stream.h"
#include "third_party/blink/public/platform/web_media_stream_center.h"
#include "third_party/blink/public/platform/web_media_stream_source.h"
-#include "third_party/blink/public/platform/web_media_stream_track.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h"
#include "third_party/blink/renderer/platform/mediastream/media_stream_web_audio_source.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
@@ -53,7 +52,7 @@ MediaStreamCenter& MediaStreamCenter::Instance() {
}
MediaStreamCenter::MediaStreamCenter()
- : private_(Platform::Current()->CreateMediaStreamCenter(this)) {}
+ : private_(Platform::Current()->CreateMediaStreamCenter()) {}
MediaStreamCenter::~MediaStreamCenter() = default;
@@ -113,11 +112,11 @@ void MediaStreamCenter::DidStopMediaStreamSource(MediaStreamSource* source) {
private_->DidStopMediaStreamSource(source);
}
-void MediaStreamCenter::StopLocalMediaStream(const WebMediaStream& web_stream) {
- MediaStreamDescriptor* stream = web_stream;
- MediaStreamDescriptorClient* client = stream->Client();
- if (client)
- client->StreamEnded();
+void MediaStreamCenter::GetSourceSettings(
+ MediaStreamSource* source,
+ WebMediaStreamTrack::Settings& settings) {
+ if (private_)
+ private_->GetSourceSettings(source, settings);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_center.h b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_center.h
index d6d8a3bef7c..48fb098e8e2 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_center.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_center.h
@@ -35,7 +35,7 @@
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/public/platform/web_media_stream_center_client.h"
+#include "third_party/blink/public/platform/web_media_stream_track.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
@@ -47,15 +47,13 @@ class AudioSourceProvider;
class MediaStreamComponent;
class MediaStreamDescriptor;
class MediaStreamSource;
-class WebMediaStream;
class WebMediaStreamCenter;
-class PLATFORM_EXPORT MediaStreamCenter final
- : public WebMediaStreamCenterClient {
+class PLATFORM_EXPORT MediaStreamCenter {
USING_FAST_MALLOC(MediaStreamCenter);
public:
- ~MediaStreamCenter() override;
+ ~MediaStreamCenter();
static MediaStreamCenter& Instance();
@@ -71,8 +69,7 @@ class PLATFORM_EXPORT MediaStreamCenter final
void DidStopMediaStreamSource(MediaStreamSource*);
- // blink::WebMediaStreamCenterClient
- void StopLocalMediaStream(const WebMediaStream&) override;
+ void GetSourceSettings(MediaStreamSource*, WebMediaStreamTrack::Settings&);
private:
MediaStreamCenter();
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.cc b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.cc
index 257aea2f362..0eeed8b76b6 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_component.cc
@@ -104,6 +104,7 @@ void MediaStreamComponent::SetContentHint(
break;
case WebMediaStreamTrack::ContentHintType::kVideoMotion:
case WebMediaStreamTrack::ContentHintType::kVideoDetail:
+ case WebMediaStreamTrack::ContentHintType::kVideoText:
DCHECK_EQ(MediaStreamSource::kTypeVideo, Source()->GetType());
break;
}
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.cc b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.cc
index d2373f3638b..cae016b4f06 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.cc
@@ -109,14 +109,14 @@ void MediaStreamDescriptor::RemoveComponent(MediaStreamComponent* component) {
void MediaStreamDescriptor::AddRemoteTrack(MediaStreamComponent* component) {
if (client_)
- client_->AddTrackByComponent(component);
+ client_->AddTrackByComponentAndFireEvents(component);
else
AddComponent(component);
}
void MediaStreamDescriptor::RemoveRemoteTrack(MediaStreamComponent* component) {
if (client_)
- client_->RemoveTrackByComponent(component);
+ client_->RemoveTrackByComponentAndFireEvents(component);
else
RemoveComponent(component);
}
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h
index 7f12f285f9c..aed544e029b 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h
@@ -49,8 +49,8 @@ class PLATFORM_EXPORT MediaStreamDescriptorClient
virtual ~MediaStreamDescriptorClient() = default;
virtual void StreamEnded() = 0;
- virtual void AddTrackByComponent(MediaStreamComponent*) = 0;
- virtual void RemoveTrackByComponent(MediaStreamComponent*) = 0;
+ virtual void AddTrackByComponentAndFireEvents(MediaStreamComponent*) = 0;
+ virtual void RemoveTrackByComponentAndFireEvents(MediaStreamComponent*) = 0;
void Trace(blink::Visitor* visitor) override {}
};
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.cc b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.cc
index 816dfda39ab..9f6364b1e58 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.cc
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.cc
@@ -29,6 +29,8 @@
*/
#include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
+
+#include "third_party/blink/renderer/platform/mediastream/media_stream_center.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink {
@@ -130,12 +132,17 @@ void MediaStreamSource::GetSettings(WebMediaStreamTrack::Settings& settings) {
settings.echo_cancellation = false;
settings.echo_cancellation_type.Reset();
break;
- case EchoCancellationMode::kSoftware:
+ case EchoCancellationMode::kBrowser:
settings.echo_cancellation = true;
settings.echo_cancellation_type =
WebString::FromASCII(blink::kEchoCancellationTypeBrowser);
break;
- case EchoCancellationMode::kHardware:
+ case EchoCancellationMode::kAec3:
+ settings.echo_cancellation = true;
+ settings.echo_cancellation_type =
+ WebString::FromASCII(blink::kEchoCancellationTypeAec3);
+ break;
+ case EchoCancellationMode::kSystem:
settings.echo_cancellation = true;
settings.echo_cancellation_type =
WebString::FromASCII(blink::kEchoCancellationTypeSystem);
@@ -146,6 +153,8 @@ void MediaStreamSource::GetSettings(WebMediaStreamTrack::Settings& settings) {
settings.auto_gain_control = *auto_gain_control_;
if (noise_supression_)
settings.noise_supression = *noise_supression_;
+
+ MediaStreamCenter::Instance().GetSourceSettings(this, settings);
}
void MediaStreamSource::SetAudioFormat(size_t number_of_channels,
@@ -179,9 +188,11 @@ STATIC_ASSERT_ENUM(WebMediaStreamSource::kReadyStateEnded,
MediaStreamSource::kReadyStateEnded);
STATIC_ASSERT_ENUM(WebMediaStreamSource::EchoCancellationMode::kDisabled,
MediaStreamSource::EchoCancellationMode::kDisabled);
-STATIC_ASSERT_ENUM(WebMediaStreamSource::EchoCancellationMode::kSoftware,
- MediaStreamSource::EchoCancellationMode::kSoftware);
-STATIC_ASSERT_ENUM(WebMediaStreamSource::EchoCancellationMode::kHardware,
- MediaStreamSource::EchoCancellationMode::kHardware);
+STATIC_ASSERT_ENUM(WebMediaStreamSource::EchoCancellationMode::kBrowser,
+ MediaStreamSource::EchoCancellationMode::kBrowser);
+STATIC_ASSERT_ENUM(WebMediaStreamSource::EchoCancellationMode::kAec3,
+ MediaStreamSource::EchoCancellationMode::kAec3);
+STATIC_ASSERT_ENUM(WebMediaStreamSource::EchoCancellationMode::kSystem,
+ MediaStreamSource::EchoCancellationMode::kSystem);
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.h b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.h
index 9d9d40fc693..dfc765b830d 100644
--- a/chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.h
+++ b/chromium/third_party/blink/renderer/platform/mediastream/media_stream_source.h
@@ -72,7 +72,7 @@ class PLATFORM_EXPORT MediaStreamSource final
kReadyStateEnded = 2
};
- enum class EchoCancellationMode { kDisabled, kSoftware, kHardware };
+ enum class EchoCancellationMode { kDisabled, kBrowser, kAec3, kSystem };
static MediaStreamSource* Create(const String& id,
StreamType,
diff --git a/chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.cc b/chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.cc
index 94fd391718c..3432b8f168b 100644
--- a/chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.cc
+++ b/chromium/third_party/blink/renderer/platform/mhtml/mhtml_archive.cc
@@ -194,7 +194,9 @@ MHTMLArchive* MHTMLArchive::Create(const KURL& url,
else
archive->AddSubresource(resources[i].Get());
}
- return archive;
+ if (archive->MainResource())
+ return archive;
+ return nullptr;
}
bool MHTMLArchive::CanLoadArchive(const KURL& url) {
@@ -302,12 +304,8 @@ void MHTMLArchive::GenerateMHTMLPart(const String& boundary,
output_buffer.Append(ascii_string.data(), ascii_string.length());
if (!strcmp(content_encoding, kBinary)) {
- const char* data;
- size_t position = 0;
- while (size_t length = resource.data->GetSomeData(data, position)) {
- output_buffer.Append(data, length);
- position += length;
- }
+ for (const auto& span : *resource.data)
+ output_buffer.Append(span.data(), span.size());
} else {
// FIXME: ideally we would encode the content as a stream without having to
// fetch it all.
diff --git a/chromium/third_party/blink/renderer/platform/mojo/DEPS b/chromium/third_party/blink/renderer/platform/mojo/DEPS
index de0e119d9dc..645db84ec00 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/DEPS
+++ b/chromium/third_party/blink/renderer/platform/mojo/DEPS
@@ -15,6 +15,7 @@ include_rules = [
"+mojo/public/cpp/bindings/binding.h",
"+mojo/public/mojom/base/string16.mojom-blink.h",
"+services/network/public/mojom/fetch_api.mojom-blink.h",
+ "+services/network/public/mojom/restricted_cookie_manager.mojom-blink.h",
"+skia/public/interfaces/bitmap_skbitmap_struct_traits.h",
"+third_party/blink/renderer/platform/blob/blob_data.h",
diff --git a/chromium/third_party/blink/renderer/platform/mojo/blink_typemaps.gni b/chromium/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
index 7312847bb4f..6dfcdcb1580 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
+++ b/chromium/third_party/blink/renderer/platform/mojo/blink_typemaps.gni
@@ -11,6 +11,7 @@ typemaps = [
"//third_party/blink/renderer/platform/blob/serialized_blob.typemap",
"//third_party/blink/renderer/platform/mojo/big_buffer.typemap",
"//third_party/blink/renderer/platform/mojo/big_string.typemap",
+ "//third_party/blink/renderer/platform/mojo/canonical_cookie.typemap",
"//third_party/blink/renderer/platform/mojo/file.typemap",
"//third_party/blink/renderer/platform/mojo/geometry.typemap",
"//third_party/blink/renderer/platform/mojo/kurl.typemap",
diff --git a/chromium/third_party/blink/renderer/platform/mojo/canonical_cookie.typemap b/chromium/third_party/blink/renderer/platform/mojo/canonical_cookie.typemap
new file mode 100644
index 00000000000..3cddb9536de
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/mojo/canonical_cookie.typemap
@@ -0,0 +1,14 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+mojom = "//services/network/public/mojom/cookie_manager.mojom"
+public_headers =
+ [ "//third_party/blink/public/platform/web_canonical_cookie.h" ]
+traits_headers = [
+ "//third_party/blink/renderer/platform/mojo/canonical_cookie_mojom_traits.h",
+]
+deps = [
+ "//mojo/public/cpp/bindings",
+]
+type_mappings = [ "network.mojom.CanonicalCookie=::blink::WebCanonicalCookie" ]
diff --git a/chromium/third_party/blink/renderer/platform/mojo/canonical_cookie_mojom_traits.cc b/chromium/third_party/blink/renderer/platform/mojo/canonical_cookie_mojom_traits.cc
new file mode 100644
index 00000000000..2890d794561
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/mojo/canonical_cookie_mojom_traits.cc
@@ -0,0 +1,142 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/mojo/canonical_cookie_mojom_traits.h"
+
+#include "base/optional.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
+#include "mojo/public/cpp/bindings/string_traits_wtf.h"
+#include "third_party/blink/renderer/platform/wtf/assertions.h"
+
+namespace mojo {
+
+// static
+WTF::String StructTraits<
+ network::mojom::CanonicalCookieDataView,
+ blink::WebCanonicalCookie>::name(const blink::WebCanonicalCookie& c) {
+ return c.Name();
+}
+
+// static
+WTF::String StructTraits<
+ network::mojom::CanonicalCookieDataView,
+ blink::WebCanonicalCookie>::value(const blink::WebCanonicalCookie& c) {
+ return c.Value();
+}
+
+// static
+WTF::String StructTraits<
+ network::mojom::CanonicalCookieDataView,
+ blink::WebCanonicalCookie>::domain(const blink::WebCanonicalCookie& c) {
+ return c.Domain();
+}
+
+// static
+WTF::String StructTraits<
+ network::mojom::CanonicalCookieDataView,
+ blink::WebCanonicalCookie>::path(const blink::WebCanonicalCookie& c) {
+ return c.Path();
+}
+
+// static
+base::Time StructTraits<
+ network::mojom::CanonicalCookieDataView,
+ blink::WebCanonicalCookie>::creation(const blink::WebCanonicalCookie& c) {
+ return c.CreationDate();
+}
+
+// static
+base::Time StructTraits<
+ network::mojom::CanonicalCookieDataView,
+ blink::WebCanonicalCookie>::expiry(const blink::WebCanonicalCookie& c) {
+ return c.ExpiryDate();
+}
+
+// static
+base::Time StructTraits<network::mojom::CanonicalCookieDataView,
+ blink::WebCanonicalCookie>::
+ last_access(const blink::WebCanonicalCookie& c) {
+ return c.LastAccessDate();
+}
+
+// static
+bool StructTraits<
+ network::mojom::CanonicalCookieDataView,
+ blink::WebCanonicalCookie>::secure(const blink::WebCanonicalCookie& c) {
+ return c.IsSecure();
+}
+// static
+bool StructTraits<
+ network::mojom::CanonicalCookieDataView,
+ blink::WebCanonicalCookie>::httponly(const blink::WebCanonicalCookie& c) {
+ return c.IsHttpOnly();
+}
+
+// static
+network::mojom::CookieSameSite
+StructTraits<network::mojom::CanonicalCookieDataView,
+ blink::WebCanonicalCookie>::
+ site_restrictions(const blink::WebCanonicalCookie& c) {
+ return c.SameSite();
+}
+
+// static
+network::mojom::CookiePriority StructTraits<
+ network::mojom::CanonicalCookieDataView,
+ blink::WebCanonicalCookie>::priority(const blink::WebCanonicalCookie& c) {
+ return c.Priority();
+}
+
+// static
+bool StructTraits<network::mojom::CanonicalCookieDataView,
+ blink::WebCanonicalCookie>::
+ Read(network::mojom::CanonicalCookieDataView cookie,
+ blink::WebCanonicalCookie* out) {
+ WTF::String name;
+ if (!cookie.ReadName(&name))
+ return false;
+
+ WTF::String value;
+ if (!cookie.ReadValue(&value))
+ return false;
+
+ WTF::String domain;
+ if (!cookie.ReadDomain(&domain))
+ return false;
+
+ WTF::String path;
+ if (!cookie.ReadPath(&path))
+ return false;
+
+ base::Time creation;
+ if (!cookie.ReadCreation(&creation))
+ return false;
+
+ base::Time expiry;
+ if (!cookie.ReadExpiry(&expiry))
+ return false;
+
+ base::Time last_access;
+ if (!cookie.ReadLastAccess(&last_access))
+ return false;
+
+ network::mojom::CookieSameSite site_restrictions;
+ if (!cookie.ReadSiteRestrictions(&site_restrictions))
+ return false;
+
+ network::mojom::CookiePriority priority;
+ if (!cookie.ReadPriority(&priority))
+ return false;
+
+ base::Optional<blink::WebCanonicalCookie> created =
+ blink::WebCanonicalCookie::Create(
+ name, value, domain, path, creation, expiry, last_access,
+ cookie.secure(), cookie.httponly(), site_restrictions, priority);
+ if (!created)
+ return false;
+ *out = std::move(created).value();
+ return true;
+}
+
+} // namespace mojo
diff --git a/chromium/third_party/blink/renderer/platform/mojo/canonical_cookie_mojom_traits.h b/chromium/third_party/blink/renderer/platform/mojo/canonical_cookie_mojom_traits.h
new file mode 100644
index 00000000000..cbb61baa785
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/mojo/canonical_cookie_mojom_traits.h
@@ -0,0 +1,39 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_CANONICAL_COOKIE_MOJOM_TRAITS_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_CANONICAL_COOKIE_MOJOM_TRAITS_H_
+
+#include "base/time/time.h"
+#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "services/network/public/mojom/restricted_cookie_manager.mojom-blink.h"
+#include "third_party/blink/public/platform/web_canonical_cookie.h"
+#include "third_party/blink/public/platform/web_string.h"
+
+namespace mojo {
+
+template <>
+struct PLATFORM_EXPORT StructTraits<network::mojom::CanonicalCookieDataView,
+ blink::WebCanonicalCookie> {
+ static WTF::String name(const blink::WebCanonicalCookie& c);
+ static WTF::String value(const blink::WebCanonicalCookie& c);
+ static WTF::String domain(const blink::WebCanonicalCookie& c);
+ static WTF::String path(const blink::WebCanonicalCookie& c);
+ static base::Time creation(const blink::WebCanonicalCookie& c);
+ static base::Time expiry(const blink::WebCanonicalCookie& c);
+ static base::Time last_access(const blink::WebCanonicalCookie& c);
+ static bool secure(const blink::WebCanonicalCookie& c);
+ static bool httponly(const blink::WebCanonicalCookie& c);
+ static network::mojom::CookieSameSite site_restrictions(
+ const blink::WebCanonicalCookie& c);
+ static network::mojom::CookiePriority priority(
+ const blink::WebCanonicalCookie& c);
+
+ static bool Read(network::mojom::CanonicalCookieDataView cookie,
+ blink::WebCanonicalCookie* out);
+};
+
+} // namespace mojo
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_MOJO_CANONICAL_COOKIE_MOJOM_TRAITS_H_
diff --git a/chromium/third_party/blink/renderer/platform/mojo/fetch_api_request_struct_traits.cc b/chromium/third_party/blink/renderer/platform/mojo/fetch_api_request_struct_traits.cc
index 2d2ee6b8d27..0583d269d4c 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/fetch_api_request_struct_traits.cc
+++ b/chromium/third_party/blink/renderer/platform/mojo/fetch_api_request_struct_traits.cc
@@ -306,6 +306,7 @@ bool StructTraits<blink::mojom::FetchAPIRequestDataView,
out->SetKeepalive(data.keepalive());
out->SetClientId(clientId);
out->SetIsReload(data.is_reload());
+ out->SetIsHistoryNavigation(data.is_history_navigation());
return true;
}
diff --git a/chromium/third_party/blink/renderer/platform/mojo/fetch_api_request_struct_traits.h b/chromium/third_party/blink/renderer/platform/mojo/fetch_api_request_struct_traits.h
index 108156cc814..d1e2c222696 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/fetch_api_request_struct_traits.h
+++ b/chromium/third_party/blink/renderer/platform/mojo/fetch_api_request_struct_traits.h
@@ -86,6 +86,11 @@ struct StructTraits<::blink::mojom::FetchAPIRequestDataView,
return request.IsReload();
}
+ static bool is_history_navigation(
+ const ::blink::WebServiceWorkerRequest& request) {
+ return request.IsHistoryNavigation();
+ }
+
static bool Read(::blink::mojom::FetchAPIRequestDataView,
::blink::WebServiceWorkerRequest* output);
};
diff --git a/chromium/third_party/blink/renderer/platform/mojo/kurl_security_origin_test.cc b/chromium/third_party/blink/renderer/platform/mojo/kurl_security_origin_test.cc
index e776e7040ad..db429023d83 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/kurl_security_origin_test.cc
+++ b/chromium/third_party/blink/renderer/platform/mojo/kurl_security_origin_test.cc
@@ -79,11 +79,12 @@ TEST(KURLSecurityOriginStructTraitsTest, Basic) {
scoped_refptr<const SecurityOrigin> output;
EXPECT_TRUE(proxy->BounceOrigin(non_unique, &output));
EXPECT_TRUE(non_unique->IsSameSchemeHostPort(output.get()));
- EXPECT_FALSE(output->IsUnique());
+ EXPECT_FALSE(output->IsOpaque());
- scoped_refptr<const SecurityOrigin> unique = SecurityOrigin::CreateUnique();
+ scoped_refptr<const SecurityOrigin> unique =
+ SecurityOrigin::CreateUniqueOpaque();
EXPECT_TRUE(proxy->BounceOrigin(unique, &output));
- EXPECT_TRUE(output->IsUnique());
+ EXPECT_TRUE(output->IsOpaque());
}
} // namespace url
diff --git a/chromium/third_party/blink/renderer/platform/mojo/security_origin_struct_traits.h b/chromium/third_party/blink/renderer/platform/mojo/security_origin_struct_traits.h
index 5aeaa5fc872..3785ab703b9 100644
--- a/chromium/third_party/blink/renderer/platform/mojo/security_origin_struct_traits.h
+++ b/chromium/third_party/blink/renderer/platform/mojo/security_origin_struct_traits.h
@@ -28,12 +28,12 @@ struct StructTraits<url::mojom::blink::Origin::DataView,
}
static bool unique(
const scoped_refptr<const ::blink::SecurityOrigin>& origin) {
- return origin->IsUnique();
+ return origin->IsOpaque();
}
static bool Read(url::mojom::blink::Origin::DataView data,
scoped_refptr<const ::blink::SecurityOrigin>* out) {
if (data.unique()) {
- *out = ::blink::SecurityOrigin::CreateUnique();
+ *out = ::blink::SecurityOrigin::CreateUniqueOpaque();
} else {
WTF::String scheme;
WTF::String host;
@@ -45,7 +45,7 @@ struct StructTraits<url::mojom::blink::Origin::DataView,
// If a unique origin was created, but the unique flag wasn't set, then
// the values provided to 'create' were invalid.
- if (!data.unique() && (*out)->IsUnique())
+ if (!data.unique() && (*out)->IsOpaque())
return false;
return true;
diff --git a/chromium/third_party/blink/renderer/platform/network/BUILD.gn b/chromium/third_party/blink/renderer/platform/network/BUILD.gn
index c1d09ff49af..c8925e32880 100644
--- a/chromium/third_party/blink/renderer/platform/network/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/network/BUILD.gn
@@ -62,10 +62,6 @@ blink_platform_sources("network") {
"parsed_content_type.h",
"server_timing_header.cc",
"server_timing_header.h",
- "web_socket_handshake_request.cc",
- "web_socket_handshake_request.h",
- "web_socket_handshake_response.cc",
- "web_socket_handshake_response.h",
]
sources += get_target_outputs(":http_names")
diff --git a/chromium/third_party/blink/renderer/platform/network/http_header_map.h b/chromium/third_party/blink/renderer/platform/network/http_header_map.h
index 9c4825e0eaf..12a2e012492 100644
--- a/chromium/third_party/blink/renderer/platform/network/http_header_map.h
+++ b/chromium/third_party/blink/renderer/platform/network/http_header_map.h
@@ -29,6 +29,7 @@
#include <memory>
#include <utility>
+#include "third_party/blink/renderer/platform/network/http_parsers.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
@@ -69,9 +70,13 @@ class PLATFORM_EXPORT HTTPHeaderMap final {
return headers_.at(k);
}
AddResult Set(const AtomicString& k, const AtomicString& v) {
+ SECURITY_DCHECK(!k.Contains('\n') && !k.Contains('\r'));
+ SECURITY_DCHECK(!v.Contains('\n') && !v.Contains('\r'));
return headers_.Set(k, v);
}
AddResult Add(const AtomicString& k, const AtomicString& v) {
+ SECURITY_DCHECK(!k.Contains('\n') && !k.Contains('\r'));
+ SECURITY_DCHECK(!v.Contains('\n') && !v.Contains('\r'));
return headers_.insert(k, v);
}
void Remove(const AtomicString& k) { headers_.erase(k); }
diff --git a/chromium/third_party/blink/renderer/platform/network/http_names.json5 b/chromium/third_party/blink/renderer/platform/network/http_names.json5
index 2ef7f762a8d..c50743eb5d0 100644
--- a/chromium/third_party/blink/renderer/platform/network/http_names.json5
+++ b/chromium/third_party/blink/renderer/platform/network/http_names.json5
@@ -65,7 +65,6 @@
"Vary",
"X-Content-Type-Options",
"X-DNS-Prefetch-Control",
- "X-DevTools-Emulate-Network-Conditions-Client-Id",
"X-Frame-Options",
"X-SourceMap",
"X-XSS-Protection",
diff --git a/chromium/third_party/blink/renderer/platform/network/http_parsers.cc b/chromium/third_party/blink/renderer/platform/network/http_parsers.cc
index fafbf62abd2..ff198ca43ce 100644
--- a/chromium/third_party/blink/renderer/platform/network/http_parsers.cc
+++ b/chromium/third_party/blink/renderer/platform/network/http_parsers.cc
@@ -48,6 +48,7 @@
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace blink {
@@ -507,11 +508,14 @@ CacheControlHeader ParseCacheControlDirectives(
CacheControlHeader cache_control_header;
cache_control_header.parsed = true;
cache_control_header.max_age = std::numeric_limits<double>::quiet_NaN();
+ cache_control_header.stale_while_revalidate =
+ std::numeric_limits<double>::quiet_NaN();
static const char kNoCacheDirective[] = "no-cache";
static const char kNoStoreDirective[] = "no-store";
static const char kMustRevalidateDirective[] = "must-revalidate";
static const char kMaxAgeDirective[] = "max-age";
+ static const char kStaleWhileRevalidateDirective[] = "stale-while-revalidate";
if (!cache_control_value.IsEmpty()) {
Vector<std::pair<String, String>> directives;
@@ -540,6 +544,17 @@ CacheControlHeader ParseCacheControlDirectives(
double max_age = directives[i].second.ToDouble(&ok);
if (ok)
cache_control_header.max_age = max_age;
+ } else if (DeprecatedEqualIgnoringCase(directives[i].first,
+ kStaleWhileRevalidateDirective)) {
+ if (!std::isnan(cache_control_header.stale_while_revalidate)) {
+ // First stale-while-revalidate directive wins if there are multiple
+ // ones.
+ continue;
+ }
+ bool ok;
+ double stale_while_revalidate = directives[i].second.ToDouble(&ok);
+ if (ok)
+ cache_control_header.stale_while_revalidate = stale_while_revalidate;
}
}
}
diff --git a/chromium/third_party/blink/renderer/platform/network/http_parsers.h b/chromium/third_party/blink/renderer/platform/network/http_parsers.h
index 8420bb37b72..7232cc34a63 100644
--- a/chromium/third_party/blink/renderer/platform/network/http_parsers.h
+++ b/chromium/third_party/blink/renderer/platform/network/http_parsers.h
@@ -72,13 +72,15 @@ struct CacheControlHeader {
bool contains_no_store : 1;
bool contains_must_revalidate : 1;
double max_age;
+ double stale_while_revalidate;
CacheControlHeader()
: parsed(false),
contains_no_cache(false),
contains_no_store(false),
contains_must_revalidate(false),
- max_age(0.0) {}
+ max_age(0.0),
+ stale_while_revalidate(0.0) {}
};
using ServerTimingHeaderVector = Vector<std::unique_ptr<ServerTimingHeader>>;
diff --git a/chromium/third_party/blink/renderer/platform/network/http_parsers_test.cc b/chromium/third_party/blink/renderer/platform/network/http_parsers_test.cc
index 1951a112128..358a4cd1ed8 100644
--- a/chromium/third_party/blink/renderer/platform/network/http_parsers_test.cc
+++ b/chromium/third_party/blink/renderer/platform/network/http_parsers_test.cc
@@ -22,6 +22,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_TRUE(std::isnan(header.max_age));
+ EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = ParseCacheControlDirectives("no-cache no-store", AtomicString());
EXPECT_TRUE(header.parsed);
@@ -29,6 +30,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_TRUE(std::isnan(header.max_age));
+ EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header =
ParseCacheControlDirectives("no-store must-revalidate", AtomicString());
@@ -37,6 +39,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_TRUE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_TRUE(std::isnan(header.max_age));
+ EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = ParseCacheControlDirectives("max-age=0", AtomicString());
EXPECT_TRUE(header.parsed);
@@ -44,6 +47,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_EQ(0.0, header.max_age);
+ EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = ParseCacheControlDirectives("max-age", AtomicString());
EXPECT_TRUE(header.parsed);
@@ -51,6 +55,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_TRUE(std::isnan(header.max_age));
+ EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = ParseCacheControlDirectives("max-age=0 no-cache", AtomicString());
EXPECT_TRUE(header.parsed);
@@ -58,6 +63,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_EQ(0.0, header.max_age);
+ EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = ParseCacheControlDirectives("no-cache=foo", AtomicString());
EXPECT_TRUE(header.parsed);
@@ -65,6 +71,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_TRUE(std::isnan(header.max_age));
+ EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = ParseCacheControlDirectives("nonsense", AtomicString());
EXPECT_TRUE(header.parsed);
@@ -72,6 +79,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_TRUE(std::isnan(header.max_age));
+ EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = ParseCacheControlDirectives("\rno-cache\n\t\v\0\b", AtomicString());
EXPECT_TRUE(header.parsed);
@@ -79,6 +87,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_TRUE(std::isnan(header.max_age));
+ EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = ParseCacheControlDirectives(" no-cache ", AtomicString());
EXPECT_TRUE(header.parsed);
@@ -86,6 +95,7 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_TRUE(std::isnan(header.max_age));
+ EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
header = ParseCacheControlDirectives(AtomicString(), "no-cache");
EXPECT_TRUE(header.parsed);
@@ -93,6 +103,16 @@ TEST(HTTPParsersTest, ParseCacheControl) {
EXPECT_FALSE(header.contains_no_store);
EXPECT_FALSE(header.contains_must_revalidate);
EXPECT_TRUE(std::isnan(header.max_age));
+ EXPECT_TRUE(std::isnan(header.stale_while_revalidate));
+
+ header = ParseCacheControlDirectives(
+ "stale-while-revalidate=2,stale-while-revalidate=3", AtomicString());
+ EXPECT_TRUE(header.parsed);
+ EXPECT_FALSE(header.contains_no_cache);
+ EXPECT_FALSE(header.contains_no_store);
+ EXPECT_FALSE(header.contains_must_revalidate);
+ EXPECT_TRUE(std::isnan(header.max_age));
+ EXPECT_EQ(2.0, header.stale_while_revalidate);
}
TEST(HTTPParsersTest, CommaDelimitedHeaderSet) {
@@ -128,7 +148,7 @@ TEST(HTTPParsersTest, HTTPToken) {
EXPECT_FALSE(blink::IsValidHTTPToken("t a"));
EXPECT_FALSE(blink::IsValidHTTPToken("()"));
EXPECT_FALSE(blink::IsValidHTTPToken("(foobar)"));
- EXPECT_FALSE(blink::IsValidHTTPToken(String("\0", 1)));
+ EXPECT_FALSE(blink::IsValidHTTPToken(String("\0", 1u)));
EXPECT_FALSE(blink::IsValidHTTPToken(String(kHiraganaA)));
}
diff --git a/chromium/third_party/blink/renderer/platform/network/network_state_notifier.cc b/chromium/third_party/blink/renderer/platform/network/network_state_notifier.cc
index e14b462091f..4a22c312362 100644
--- a/chromium/third_party/blink/renderer/platform/network/network_state_notifier.cc
+++ b/chromium/third_party/blink/renderer/platform/network/network_state_notifier.cc
@@ -36,6 +36,7 @@
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
#include "third_party/blink/renderer/platform/wtf/threading.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/network/network_utils.cc b/chromium/third_party/blink/renderer/platform/network/network_utils.cc
index 3a5bce276ca..a0c34aefe7e 100644
--- a/chromium/third_party/blink/renderer/platform/network/network_utils.cc
+++ b/chromium/third_party/blink/renderer/platform/network/network_utils.cc
@@ -10,6 +10,7 @@
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/base/url_util.h"
#include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
#include "net/url_request/url_request_data_job.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
#include "third_party/blink/public/platform/url_conversion.h"
@@ -127,6 +128,13 @@ bool IsLegacySymantecCertError(int error_code) {
return error_code == net::ERR_CERT_SYMANTEC_LEGACY;
}
+String GenerateAcceptLanguageHeader(const String& lang) {
+ CString cstring(lang.Utf8());
+ std::string string(cstring.data(), cstring.length());
+ return WebString::FromUTF8(
+ net::HttpUtil::GenerateAcceptLanguageHeader(string));
+}
+
} // NetworkUtils
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/network/network_utils.h b/chromium/third_party/blink/renderer/platform/network/network_utils.h
index 2fc4d824929..30afc6127a9 100644
--- a/chromium/third_party/blink/renderer/platform/network/network_utils.h
+++ b/chromium/third_party/blink/renderer/platform/network/network_utils.h
@@ -44,6 +44,8 @@ PLATFORM_EXPORT bool IsCertificateTransparencyRequiredError(int);
PLATFORM_EXPORT bool IsLegacySymantecCertError(int);
+PLATFORM_EXPORT String GenerateAcceptLanguageHeader(const String&);
+
} // NetworkUtils
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/network/web_socket_handshake_request.cc b/chromium/third_party/blink/renderer/platform/network/web_socket_handshake_request.cc
deleted file mode 100644
index 794c6d00583..00000000000
--- a/chromium/third_party/blink/renderer/platform/network/web_socket_handshake_request.cc
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/platform/network/web_socket_handshake_request.h"
-
-namespace blink {
-
-WebSocketHandshakeRequest::WebSocketHandshakeRequest(const KURL& url)
- : url_(url) {}
-
-WebSocketHandshakeRequest::WebSocketHandshakeRequest() = default;
-
-WebSocketHandshakeRequest::WebSocketHandshakeRequest(
- const WebSocketHandshakeRequest& request)
- : url_(request.url_),
- header_fields_(request.header_fields_),
- headers_text_(request.headers_text_) {}
-
-WebSocketHandshakeRequest::~WebSocketHandshakeRequest() = default;
-
-void WebSocketHandshakeRequest::AddAndMergeHeader(HTTPHeaderMap* map,
- const AtomicString& name,
- const AtomicString& value) {
- HTTPHeaderMap::AddResult result = map->Add(name, value);
- if (!result.is_new_entry) {
- // Inspector expects the "\n" separated format.
- result.stored_value->value =
- result.stored_value->value + "\n" + String(value);
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/network/web_socket_handshake_request.h b/chromium/third_party/blink/renderer/platform/network/web_socket_handshake_request.h
deleted file mode 100644
index de485d2265f..00000000000
--- a/chromium/third_party/blink/renderer/platform/network/web_socket_handshake_request.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_WEB_SOCKET_HANDSHAKE_REQUEST_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_WEB_SOCKET_HANDSHAKE_REQUEST_H_
-
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/platform/network/http_header_map.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-class HTTPHeaderMap;
-
-class PLATFORM_EXPORT WebSocketHandshakeRequest final
- : public RefCounted<WebSocketHandshakeRequest> {
- public:
- static scoped_refptr<WebSocketHandshakeRequest> Create(const KURL& url) {
- return base::AdoptRef(new WebSocketHandshakeRequest(url));
- }
- static scoped_refptr<WebSocketHandshakeRequest> Create() {
- return base::AdoptRef(new WebSocketHandshakeRequest);
- }
- static scoped_refptr<WebSocketHandshakeRequest> Create(
- const WebSocketHandshakeRequest& request) {
- return base::AdoptRef(new WebSocketHandshakeRequest(request));
- }
- virtual ~WebSocketHandshakeRequest();
-
- void AddAndMergeHeader(const AtomicString& name, const AtomicString& value) {
- AddAndMergeHeader(&header_fields_, name, value);
- }
-
- // Merges the existing value with |value| in |map| if |map| already has
- // |name|. Associates |value| with |name| in |map| otherwise.
- // This function builds data for inspector.
- static void AddAndMergeHeader(HTTPHeaderMap* /* map */,
- const AtomicString& name,
- const AtomicString& value);
-
- void AddHeaderField(const AtomicString& name, const AtomicString& value) {
- header_fields_.Add(name, value);
- }
-
- KURL Url() const { return url_; }
- void SetURL(const KURL& url) { url_ = url; }
- const HTTPHeaderMap& HeaderFields() const { return header_fields_; }
- const String& HeadersText() const { return headers_text_; }
- void SetHeadersText(const String& text) { headers_text_ = text; }
-
- private:
- WebSocketHandshakeRequest(const KURL&);
- WebSocketHandshakeRequest();
- WebSocketHandshakeRequest(const WebSocketHandshakeRequest&);
-
- KURL url_;
- HTTPHeaderMap header_fields_;
- String headers_text_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_WEB_SOCKET_HANDSHAKE_REQUEST_H_
diff --git a/chromium/third_party/blink/renderer/platform/network/web_socket_handshake_response.cc b/chromium/third_party/blink/renderer/platform/network/web_socket_handshake_response.cc
deleted file mode 100644
index c3080a57a8b..00000000000
--- a/chromium/third_party/blink/renderer/platform/network/web_socket_handshake_response.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/platform/network/web_socket_handshake_response.h"
-
-#include "third_party/blink/renderer/platform/network/web_socket_handshake_request.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
-
-namespace blink {
-
-WebSocketHandshakeResponse::WebSocketHandshakeResponse() = default;
-
-WebSocketHandshakeResponse::~WebSocketHandshakeResponse() = default;
-
-int WebSocketHandshakeResponse::StatusCode() const {
- return status_code_;
-}
-
-void WebSocketHandshakeResponse::SetStatusCode(int status_code) {
- DCHECK_GE(status_code, 100);
- DCHECK_LT(status_code, 600);
- status_code_ = status_code;
-}
-
-const String& WebSocketHandshakeResponse::StatusText() const {
- return status_text_;
-}
-
-void WebSocketHandshakeResponse::SetStatusText(const String& status_text) {
- status_text_ = status_text;
-}
-
-const HTTPHeaderMap& WebSocketHandshakeResponse::HeaderFields() const {
- return header_fields_;
-}
-
-void WebSocketHandshakeResponse::AddHeaderField(const AtomicString& name,
- const AtomicString& value) {
- WebSocketHandshakeRequest::AddAndMergeHeader(&header_fields_, name, value);
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/network/web_socket_handshake_response.h b/chromium/third_party/blink/renderer/platform/network/web_socket_handshake_response.h
deleted file mode 100644
index 6bfa40338a5..00000000000
--- a/chromium/third_party/blink/renderer/platform/network/web_socket_handshake_response.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_WEB_SOCKET_HANDSHAKE_RESPONSE_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_WEB_SOCKET_HANDSHAKE_RESPONSE_H_
-
-#include "third_party/blink/renderer/platform/network/http_header_map.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT WebSocketHandshakeResponse final {
- public:
- WebSocketHandshakeResponse();
- ~WebSocketHandshakeResponse();
-
- int StatusCode() const;
- void SetStatusCode(int);
- const String& StatusText() const;
- void SetStatusText(const String&);
- const HTTPHeaderMap& HeaderFields() const;
- void AddHeaderField(const AtomicString& name, const AtomicString& value);
- const String& HeadersText() const { return headers_text_; }
- void SetHeadersText(const String& text) { headers_text_ = text; }
-
- private:
- int status_code_;
- String status_text_;
- HTTPHeaderMap header_fields_;
- String headers_text_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_NETWORK_WEB_SOCKET_HANDSHAKE_RESPONSE_H_
diff --git a/chromium/third_party/blink/renderer/platform/partition_alloc_memory_dump_provider.cc b/chromium/third_party/blink/renderer/platform/partition_alloc_memory_dump_provider.cc
index 276b9f0d165..80aed077cc1 100644
--- a/chromium/third_party/blink/renderer/platform/partition_alloc_memory_dump_provider.cc
+++ b/chromium/third_party/blink/renderer/platform/partition_alloc_memory_dump_provider.cc
@@ -6,6 +6,7 @@
#include <unordered_map>
+#include "base/allocator/partition_allocator/partition_alloc.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/process_memory_dump.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
@@ -26,7 +27,7 @@ std::string GetPartitionDumpName(const char* partition_name) {
// This class is used to invert the dependency of PartitionAlloc on the
// PartitionAllocMemoryDumpProvider. This implements an interface that will
// be called with memory statistics for each bucket in the allocator.
-class PartitionStatsDumperImpl final : public WTF::PartitionStatsDumper {
+class PartitionStatsDumperImpl final : public base::PartitionStatsDumper {
DISALLOW_NEW();
WTF_MAKE_NONCOPYABLE(PartitionStatsDumperImpl);
@@ -38,10 +39,10 @@ class PartitionStatsDumperImpl final : public WTF::PartitionStatsDumper {
// PartitionStatsDumper implementation.
void PartitionDumpTotals(const char* partition_name,
- const WTF::PartitionMemoryStats*) override;
+ const base::PartitionMemoryStats*) override;
void PartitionsDumpBucketStats(
const char* partition_name,
- const WTF::PartitionBucketMemoryStats*) override;
+ const base::PartitionBucketMemoryStats*) override;
size_t TotalActiveBytes() const { return total_active_bytes_; }
@@ -53,7 +54,7 @@ class PartitionStatsDumperImpl final : public WTF::PartitionStatsDumper {
void PartitionStatsDumperImpl::PartitionDumpTotals(
const char* partition_name,
- const WTF::PartitionMemoryStats* memory_stats) {
+ const base::PartitionMemoryStats* memory_stats) {
total_active_bytes_ += memory_stats->total_active_bytes;
std::string dump_name = GetPartitionDumpName(partition_name);
base::trace_event::MemoryAllocatorDump* allocator_dump =
@@ -74,7 +75,7 @@ void PartitionStatsDumperImpl::PartitionDumpTotals(
void PartitionStatsDumperImpl::PartitionsDumpBucketStats(
const char* partition_name,
- const WTF::PartitionBucketMemoryStats* memory_stats) {
+ const base::PartitionBucketMemoryStats* memory_stats) {
DCHECK(memory_stats->is_valid);
std::string dump_name = GetPartitionDumpName(partition_name);
if (memory_stats->is_direct_map) {
diff --git a/chromium/third_party/blink/renderer/platform/platform_export.h b/chromium/third_party/blink/renderer/platform/platform_export.h
index 50043a2b2c6..3f10b841f93 100644
--- a/chromium/third_party/blink/renderer/platform/platform_export.h
+++ b/chromium/third_party/blink/renderer/platform/platform_export.h
@@ -32,20 +32,6 @@
//
// - PLATFORM_EXPORT
// Exports non-template symbols.
-//
-// - PLATFORM_TEMPLATE_CLASS_EXPORT
-// Exports an entire definition of class template.
-//
-// - PLATFORM_EXTERN_TEMPLATE_EXPORT
-// Applicable to template declarations (except for definitions). The
-// corresponding definition must come along with PLATFORM_TEMPLATE_EXPORT.
-// Template specialization uses this macro to declare that such a
-// specialization exists without providing an actual definition.
-//
-// - PLATFORM_TEMPLATE_EXPORT
-// Applicable to template definitions whose declarations are annotated
-// with PLATFORM_EXTERN_TEMPLATE_EXPORT. Template specialization uses this
-// macro to provide an actual definition.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_PLATFORM_EXPORT_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PLATFORM_EXPORT_H_
@@ -84,44 +70,4 @@
#endif // !defined(COMPONENT_BUILD)
-//
-// PLATFORM_TEMPLATE_CLASS_EXPORT
-// PLATFORM_EXTERN_TEMPLATE_EXPORT
-// PLATFORM_TEMPLATE_EXPORT
-//
-#if BLINK_PLATFORM_IMPLEMENTATION
-
-#if defined(COMPILER_MSVC)
-#define PLATFORM_TEMPLATE_CLASS_EXPORT
-#define PLATFORM_EXTERN_TEMPLATE_EXPORT PLATFORM_EXPORT
-#define PLATFORM_TEMPLATE_EXPORT PLATFORM_EXPORT
-#endif
-
-#if defined(COMPILER_GCC)
-#define PLATFORM_TEMPLATE_CLASS_EXPORT PLATFORM_EXPORT
-#define PLATFORM_EXTERN_TEMPLATE_EXPORT PLATFORM_EXPORT
-#define PLATFORM_TEMPLATE_EXPORT
-#endif
-
-#else // BLINK_PLATFORM_IMPLEMENTATION
-
-#define PLATFORM_TEMPLATE_CLASS_EXPORT
-#define PLATFORM_EXTERN_TEMPLATE_EXPORT PLATFORM_EXPORT
-#define PLATFORM_TEMPLATE_EXPORT
-
-#endif // BLINK_PLATFORM_IMPLEMENTATION
-
-#if defined(COMPILER_MSVC)
-// MSVC Compiler warning C4275:
-// non dll-interface class 'Bar' used as base for dll-interface class 'Foo'.
-// Note that this is intended to be used only when no access to the base class'
-// static data is done through derived classes or inline methods. For more info,
-// see http://msdn.microsoft.com/en-us/library/3tdb471s(VS.80).aspx
-//
-// This pragma will allow exporting a class that inherits from a non-exported
-// base class, anywhere in the Blink platform component. This is only
-// a problem when using the MSVC compiler on Windows.
-#pragma warning(suppress : 4275)
-#endif
-
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_PLATFORM_EXPORT_H_
diff --git a/chromium/third_party/blink/renderer/platform/plugins/DEPS b/chromium/third_party/blink/renderer/platform/plugins/DEPS
index ad511e473b0..5bd20835334 100644
--- a/chromium/third_party/blink/renderer/platform/plugins/DEPS
+++ b/chromium/third_party/blink/renderer/platform/plugins/DEPS
@@ -12,3 +12,9 @@ include_rules = [
"+third_party/blink/renderer/platform/weborigin",
"+third_party/blink/renderer/platform/wtf",
]
+
+specific_include_rules = {
+ ".*_test\.cc": [
+ "+third_party/blink/renderer/platform/testing",
+ ],
+}
diff --git a/chromium/third_party/blink/renderer/platform/plugins/plugin_data.cc b/chromium/third_party/blink/renderer/platform/plugins/plugin_data.cc
index 73d10a188b2..02d54d5f2db 100644
--- a/chromium/third_party/blink/renderer/platform/plugins/plugin_data.cc
+++ b/chromium/third_party/blink/renderer/platform/plugins/plugin_data.cc
@@ -23,9 +23,11 @@
#include "third_party/blink/renderer/platform/plugins/plugin_data.h"
+#include "third_party/blink/public/mojom/plugins/plugin_registry.mojom-blink.h"
+#include "third_party/blink/public/platform/file_path_conversion.h"
+#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_security_origin.h"
-#include "third_party/blink/renderer/platform/plugins/plugin_list_builder.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
namespace blink {
@@ -82,21 +84,41 @@ void PluginData::Trace(blink::Visitor* visitor) {
// static
void PluginData::RefreshBrowserSidePluginCache() {
- PluginListBuilder builder(nullptr);
- Platform::Current()->GetPluginList(true, WebSecurityOrigin::CreateUnique(),
- &builder);
+ mojom::blink::PluginRegistryPtr registry;
+ Platform::Current()->GetInterfaceProvider()->GetInterface(
+ mojo::MakeRequest(&registry));
+ Vector<mojom::blink::PluginInfoPtr> plugins;
+ registry->GetPlugins(true, SecurityOrigin::CreateUniqueOpaque(), &plugins);
}
void PluginData::UpdatePluginList(const SecurityOrigin* main_frame_origin) {
ResetPluginData();
main_frame_origin_ = main_frame_origin;
- PluginListBuilder builder(&plugins_);
- Platform::Current()->GetPluginList(
- false, WebSecurityOrigin(main_frame_origin_), &builder);
- for (PluginInfo* plugin_info : plugins_) {
- for (MimeClassInfo* mime_class_info : plugin_info->mimes_)
- mimes_.push_back(mime_class_info);
+ // TODO(jbroman): Remove this. It is intended only as a minimal fix to restore
+ // previous behavior about origins that url::Origin rejects. This triggers the
+ // code which maps such origins to url::Origin(), a unique origin.
+ // https://crbug.com/862282
+ scoped_refptr<const SecurityOrigin> legacy_origin =
+ SecurityOrigin::CreateFromUrlOrigin(main_frame_origin->ToUrlOrigin());
+
+ mojom::blink::PluginRegistryPtr registry;
+ Platform::Current()->GetInterfaceProvider()->GetInterface(
+ mojo::MakeRequest(&registry));
+ Vector<mojom::blink::PluginInfoPtr> plugins;
+ registry->GetPlugins(false, legacy_origin, &plugins);
+ for (const auto& plugin : plugins) {
+ auto* plugin_info =
+ new PluginInfo(plugin->name, FilePathToWebString(plugin->filename),
+ plugin->description, plugin->background_color);
+ plugins_.push_back(plugin_info);
+ for (const auto& mime : plugin->mime_types) {
+ auto* mime_info =
+ new MimeClassInfo(mime->mime_type, mime->description, *plugin_info);
+ mime_info->extensions_ = mime->file_extensions;
+ plugin_info->AddMimeType(mime_info);
+ mimes_.push_back(mime_info);
+ }
}
std::sort(
diff --git a/chromium/third_party/blink/renderer/platform/plugins/plugin_data_test.cc b/chromium/third_party/blink/renderer/platform/plugins/plugin_data_test.cc
new file mode 100644
index 00000000000..44d8d15e7d3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/plugins/plugin_data_test.cc
@@ -0,0 +1,65 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/plugins/plugin_data.h"
+
+#include "base/test/scoped_task_environment.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/plugins/plugin_registry.mojom-blink.h"
+#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+
+using testing::Eq;
+using testing::Property;
+
+namespace blink {
+namespace {
+
+class MockPluginRegistry : public mojom::blink::PluginRegistry {
+ public:
+ void GetPlugins(bool refresh,
+ const scoped_refptr<const SecurityOrigin>& origin,
+ GetPluginsCallback callback) override {
+ DidGetPlugins(refresh, *origin);
+ std::move(callback).Run(Vector<mojom::blink::PluginInfoPtr>());
+ }
+
+ MOCK_METHOD2(DidGetPlugins, void(bool, const SecurityOrigin&));
+};
+
+// This behavior may be temporary, as it's odd for such origins to be treated as
+// non-unique in Blink and unique in the browser. https://crbug.com/862282
+TEST(PluginDataTest, NonStandardUrlSchemeRequestsPluginsWithUniqueOrigin) {
+ base::test::ScopedTaskEnvironment scoped_task_environment;
+ MockPluginRegistry mock_plugin_registry;
+ mojo::Binding<mojom::blink::PluginRegistry> registry_binding(
+ &mock_plugin_registry);
+ TestingPlatformSupport::ScopedOverrideMojoInterface override_plugin_registry(
+ WTF::BindRepeating(
+ [](mojo::Binding<mojom::blink::PluginRegistry>* registry_binding,
+ const char* interface, mojo::ScopedMessagePipeHandle pipe) {
+ if (!strcmp(interface, mojom::blink::PluginRegistry::Name_)) {
+ registry_binding->Bind(
+ mojom::blink::PluginRegistryRequest(std::move(pipe)));
+ return;
+ }
+ },
+ WTF::Unretained(&registry_binding)));
+
+ EXPECT_CALL(
+ mock_plugin_registry,
+ DidGetPlugins(false, Property(&SecurityOrigin::IsOpaque, Eq(true))));
+
+ scoped_refptr<SecurityOrigin> non_standard_origin =
+ SecurityOrigin::CreateFromString("nonstandard:foo/bar");
+ EXPECT_FALSE(non_standard_origin->IsOpaque());
+ auto* plugin_data = PluginData::Create();
+ plugin_data->UpdatePluginList(non_standard_origin.get());
+}
+
+} // namespace
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/plugins/plugin_list_builder.cc b/chromium/third_party/blink/renderer/platform/plugins/plugin_list_builder.cc
deleted file mode 100644
index 806586e6cf3..00000000000
--- a/chromium/third_party/blink/renderer/platform/plugins/plugin_list_builder.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/renderer/platform/plugins/plugin_list_builder.h"
-
-#include "third_party/blink/public/platform/web_string.h"
-
-namespace blink {
-
-void PluginListBuilder::AddPlugin(const WebString& name,
- const WebString& description,
- const WebString& file_name,
- SkColor background_color) {
- if (results_) {
- results_->push_back(
- new PluginInfo(name, file_name, description, background_color));
- }
-}
-
-void PluginListBuilder::AddMediaTypeToLastPlugin(const WebString& name,
- const WebString& description) {
- if (results_) {
- MimeClassInfo* info =
- new MimeClassInfo(name, description, *results_->back());
- results_->back()->AddMimeType(info);
- }
-}
-
-void PluginListBuilder::AddFileExtensionToLastMediaType(
- const WebString& extension) {
- if (results_) {
- MimeClassInfo& info = *results_->back()->mimes_.back();
- info.extensions_.push_back(extension);
- }
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/plugins/plugin_list_builder.h b/chromium/third_party/blink/renderer/platform/plugins/plugin_list_builder.h
deleted file mode 100644
index c4d181a8c37..00000000000
--- a/chromium/third_party/blink/renderer/platform/plugins/plugin_list_builder.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_PLUGINS_PLUGIN_LIST_BUILDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PLUGINS_PLUGIN_LIST_BUILDER_H_
-
-#include "third_party/blink/public/platform/web_plugin_list_builder.h"
-#include "third_party/blink/renderer/platform/plugins/plugin_data.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-class PluginListBuilder final : public WebPluginListBuilder {
- STACK_ALLOCATED();
-
- public:
- PluginListBuilder(HeapVector<Member<PluginInfo>>* results)
- : results_(results) {}
-
- // WebPluginListBuilder methods:
- void AddPlugin(const WebString& name,
- const WebString& description,
- const WebString& file_name,
- SkColor background_color) override;
- void AddMediaTypeToLastPlugin(const WebString& name,
- const WebString& description) override;
- void AddFileExtensionToLastMediaType(const WebString& extension) override;
-
- private:
- HeapVector<Member<PluginInfo>>* results_;
-};
-
-} // namespace blink
-
-#endif
diff --git a/chromium/third_party/blink/renderer/platform/plugins/plugin_script_forbidden_scope.cc b/chromium/third_party/blink/renderer/platform/plugins/plugin_script_forbidden_scope.cc
index abdcc8b53eb..cfe8439f01a 100644
--- a/chromium/third_party/blink/renderer/platform/plugins/plugin_script_forbidden_scope.cc
+++ b/chromium/third_party/blink/renderer/platform/plugins/plugin_script_forbidden_scope.cc
@@ -4,7 +4,8 @@
#include "third_party/blink/renderer/platform/plugins/plugin_script_forbidden_scope.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "base/logging.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/png_fuzzer.cc b/chromium/third_party/blink/renderer/platform/png_fuzzer.cc
index 9d3f7d779eb..8bd18d633b7 100644
--- a/chromium/third_party/blink/renderer/platform/png_fuzzer.cc
+++ b/chromium/third_party/blink/renderer/platform/png_fuzzer.cc
@@ -34,8 +34,8 @@ namespace blink {
std::unique_ptr<ImageDecoder> CreateDecoder(
ImageDecoder::AlphaOption alpha_option) {
return std::make_unique<PNGImageDecoder>(
- alpha_option, ColorBehavior::TransformToSRGB(),
- ImageDecoder::kNoDecodedImageByteLimit);
+ alpha_option, ImageDecoder::kDefaultBitDepth,
+ ColorBehavior::TransformToSRGB(), ImageDecoder::kNoDecodedImageByteLimit);
}
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
diff --git a/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 86a111ef2db..7fa2c263589 100644
--- a/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/chromium/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -76,6 +76,10 @@
status: "experimental",
},
{
+ name: "AdTagging",
+ status: "test",
+ },
+ {
name: "AllowActivationDelegationAttr",
},
{
@@ -92,10 +96,6 @@
status: "experimental",
},
{
- name: "AsyncCookies",
- status: "experimental",
- },
- {
name: "AudioOutputDevices",
status: "stable",
},
@@ -105,7 +105,6 @@
},
{
name: "AudioWorklet",
- depends_on: ["Worklet"],
status: "stable",
},
{
@@ -115,6 +114,7 @@
{
// Flag set by the media::kAutoplayIgnoreWebAudio feature flag.
name: "AutoplayIgnoresWebAudio",
+ settable_from_internals: true,
},
{
name: "AutoplayMutedVideos",
@@ -139,6 +139,11 @@
status: "experimental",
},
{
+ // Detects bloated renderers even if the uptime is small.
+ // Useful for local testing, not intended for production.
+ name: "BloatedRendererDetectionSkipUptimeCheck",
+ },
+ {
name: "BlockCredentialedSubresources",
status: "stable",
},
@@ -197,10 +202,6 @@
status: "experimental",
},
{
- name: "ClientHintsPersistent",
- status: "stable",
- },
- {
name: "ClientPlaceholdersForServerLoFi",
},
{
@@ -225,15 +226,16 @@
status: "experimental",
},
{
- name: "ConicGradient",
+ name: "ConstructableStylesheets",
status: "experimental",
},
{
- name: "ConstructableStylesheets",
+ name: "ContextMenu",
status: "experimental",
},
{
- name: "ContextMenu",
+ name: "CookieStore",
+ origin_trial_feature_name: "CookieStore",
status: "experimental",
},
{
@@ -257,6 +259,10 @@
status: "stable",
},
{
+ name: "CSSEnvironmentVariables",
+ status: "stable",
+ },
+ {
name: "CSSFocusVisible",
status: "experimental",
},
@@ -265,12 +271,15 @@
status: "experimental",
},
{
+ name: "CSSFragmentIdentifiers"
+ },
+ {
name: "CSSHexAlphaColor",
status: "stable",
},
{
name: "CSSInBodyDoesNotBlockPaint",
- status: "experimental",
+ status: "stable",
},
{
name: "CSSIndependentTransformProperties",
@@ -281,6 +290,10 @@
status: "experimental",
},
{
+ name: "CSSLogical",
+ status: "experimental",
+ },
+ {
name: "CSSMaskSourceType",
status: "experimental",
},
@@ -308,14 +321,14 @@
name: "CSSOverscrollBehavior",
status: "stable",
},
- {
- name: "CSSPaintAPI",
- depends_on: ["Worklet"],
- status: "stable",
- },
+ // Do not ship CSSPaintAPIArguments without shipping CSSVariables2 first.
+ //
+ // CSSPaintAPIArguments depends on parts of the the 'CSS Properties and
+ // Values API Level 1', specification (section 'Supported syntax strings').
+ // That specification is implemented behind the runtime enabled feature
+ // CSSVariables2.
{
name: "CSSPaintAPIArguments",
- depends_on: ["CSSPaintAPI"],
status: "experimental",
},
{
@@ -328,7 +341,7 @@
},
{
name: "CSSScrollSnapPoints",
- status: "experimental",
+ status: "stable",
},
{
name: "CSSSnapSize",
@@ -339,10 +352,6 @@
status: "stable",
},
{
- name: "CSSTypedOM",
- status: "stable",
- },
- {
name: "CSSVariables2",
status: "experimental",
},
@@ -354,10 +363,6 @@
name: "CustomElementDefaultStyle",
status: "experimental",
},
- {
- name: "CustomElementsBuiltin",
- status: "stable",
- },
// Introduced this flag as stable so web developers can test their sites
// without native Custom Elements v0 support.
{
@@ -377,7 +382,7 @@
},
{
name: "DeprecationReporting",
- status: "experimental",
+ status: "stable",
},
{
name: "DesktopCaptureDisableLocalEchoControl",
@@ -393,13 +398,7 @@
status: "experimental",
},
{
- name: "DisablePaintChunksToCcLayer",
- },
- {
- name: "DisableRasterInvalidation",
- },
- {
- name: "DisplayCutoutViewportFit",
+ name: "DisplayCutoutAPI",
settable_from_internals: true,
},
{
@@ -420,10 +419,15 @@
status: "stable",
},
{
- name: "EncryptedMediaHdcpPolicyCheck",
+ name: "EncryptedMediaEncryptionSchemeQuery",
status: "test",
},
{
+ name: "EncryptedMediaHdcpPolicyCheck",
+ origin_trial_feature_name: "EncryptedMediaHdcpPolicyCheck",
+ status: "experimental",
+ },
+ {
name: "EventTiming",
origin_trial_feature_name: "EventTiming",
status: "experimental",
@@ -454,6 +458,14 @@
status: "experimental"
},
{
+ // Enables the attribute performance.shouldYield in windows. This
+ // attribute indicates that the frame should pause its current task so
+ // that the browser can perform some high priority work. See
+ // https://crbug.com/836310.
+ name: "ExperimentalShouldYield",
+ status: "experimental"
+ },
+ {
name: "ExperimentalV8Extras",
status: "experimental",
},
@@ -477,33 +489,18 @@
status: "stable"
},
{
- name: "FeaturePolicyExperimentalFeatures",
- status: "experimental"
- },
- {
name: "FeaturePolicyForPermissions",
status: "stable"
},
{
name: "FeaturePolicyJavaScriptInterface",
+ origin_trial_feature_name: "FeaturePolicyJSAPI",
status: "experimental"
},
{
name: "FeaturePolicyVibrateFeature"
},
{
- name: "FetchRequestCache",
- status: "stable",
- },
- {
- name: "FetchRequestKeepalive",
- status: "stable",
- },
- {
- name: "FetchRequestSignal",
- status: "stable",
- },
- {
name: "FileSystem",
status: "stable",
},
@@ -556,7 +553,6 @@
},
{
name: "GamepadExtensions",
- origin_trial_feature_name: "WebVR1.1M62",
status: "experimental",
},
{
@@ -589,7 +585,7 @@
},
{
name: "IdleTimeColdModeSpellChecking",
- status: "experimental",
+ status: "stable",
},
{
name: "ImageDecodingAttribute",
@@ -606,7 +602,7 @@
},
{
name: "IncrementalShadowDOM",
- status: "experimental",
+ status: "stable",
},
{
name: "InertAttribute",
@@ -622,10 +618,12 @@
status: "experimental",
},
{
- name: "IntersectionObserverGeometryMapper",
+ name: "IntersectionObserverV2",
+ settable_from_internals: true,
},
{
- name: "IntersectionObserverV2",
+ name: "InterventionReporting",
+ status: "experimental",
},
{
// Tracks "jank" from layout objects changing their visual location
@@ -638,12 +636,8 @@
status: "stable",
},
{
- name: "KeyboardLock",
- status: "stable",
- },
- {
name: "KeyboardMap",
- status: "experimental",
+ status: "stable",
},
{
name: "LangAttributeAwareFormControlUI",
@@ -664,11 +658,15 @@
},
{
name: "LayoutNGFragmentCaching",
+ implied_by: ["LayoutNG"],
},
{
name: "LazyFrameLoading",
},
{
+ name: "LazyFrameVisibleLoadTimeMetrics",
+ },
+ {
name: "LazyInitializeMediaControls",
// This is enabled by features::kLazyInitializeMediaControls.
},
@@ -677,10 +675,6 @@
status: "experimental",
},
{
- name: "LoadingWithMojo",
- status: "stable",
- },
- {
name: "LongTaskObserver",
status: "stable",
},
@@ -721,6 +715,9 @@
name: "MediaCastOverlayButton",
},
{
+ name: "MediaControlsExpandGesture"
+ },
+ {
name: "MediaControlsOverlayPlayButton",
settable_from_internals: true,
},
@@ -780,9 +777,6 @@
name: "ModuleScriptsImportMetaUrl",
},
{
- name: "MojoBlobURLs",
- },
- {
name: "MojoJS",
status: "test",
},
@@ -804,12 +798,16 @@
status: "stable",
},
{
+ name: "NestedWorkers",
+ status: "stable",
+ },
+ {
name: "NetInfoDownlink",
status: "stable",
},
{
name: "NetInfoDownlinkHeader",
- status: "experimental",
+ status: "stable",
},
{
name: "NetInfoDownlinkMax",
@@ -821,7 +819,7 @@
},
{
name: "NetInfoEffectiveTypeHeader",
- status: "experimental",
+ status: "stable",
},
{
name: "NetInfoRtt",
@@ -829,7 +827,7 @@
},
{
name: "NetInfoRttHeader",
- status: "experimental",
+ status: "stable",
},
{
name: "NetInfoSaveData",
@@ -868,11 +866,15 @@
},
{
name: "OffscreenCanvas",
+ status: "stable",
+ },
+ {
+ name: "OffscreenCanvasCommit",
status: "experimental",
},
{
name: "OffscreenCanvasText",
- status: "experimental",
+ status: "stable",
},
{
name: "OnDeviceChange",
@@ -882,7 +884,7 @@
name: "OrientationEvent",
},
{
- name: "OriginManifest",
+ name: "OriginPolicy",
status: "test",
},
{
@@ -924,12 +926,13 @@
name: "PagePopup",
status: "stable",
},
+ // Compute touch action rects in paint instead of ScrollingCoordinator.
{
- name: "PaintUnderInvalidationChecking",
- settable_from_internals: true,
+ name: "PaintTouchActionRects",
},
{
- name: "PartialRasterInvalidation",
+ name: "PaintUnderInvalidationChecking",
+ settable_from_internals: true,
},
{
name: "PassiveDocumentEventListeners",
@@ -956,6 +959,10 @@
status: "stable",
},
{
+ name: "PaymentRetry",
+ status: "experimental",
+ },
+ {
name: "PerformanceNavigationTiming2",
status: "stable",
},
@@ -979,10 +986,13 @@
name: "PictureInPicture",
settable_from_internals: true,
},
+ // Picture-in-Picture API is disabled by default on Android.
{
name: "PictureInPictureAPI",
- origin_trial_feature_name: "PictureInPictureAPI",
- origin_trial_os: ["chromeos", "linux", "macosx", "win"],
+ status: "stable",
+ },
+ {
+ name: "PictureInPictureControl",
status: "experimental",
},
{
@@ -1056,7 +1066,12 @@
},
{
name: "ReportingObserver",
- status: "experimental",
+ implied_by: ["DeprecationReporting", "InterventionReporting"],
+ status: "stable",
+ },
+ {
+ name: "RequestIsHistoryNavigation",
+ status: "stable",
},
{
name: "RequireCSSExtensionForFile",
@@ -1078,12 +1093,6 @@
name: "RestrictCanRequestURLCharacterSet",
status: "stable",
},
- // Handles frame scrolling via the root PaintLayer instead of the FrameView.
- // The master bug for the root layer scrolling project is crbug.com/417782.
- {
- name: "RootLayerScrolling",
- status: "stable",
- },
{
name: "RtcPeerConnectionId",
origin_trial_feature_name: "RtcPeerConnectionId",
@@ -1135,8 +1144,7 @@
},
{
name: "Sensor",
- origin_trial_feature_name: "GenericSensor",
- status: "experimental",
+ status: "stable",
},
{
name: "SensorExtraClasses",
@@ -1186,11 +1194,6 @@
status: "experimental",
},
{
- name: "SlimmingPaintV175",
- status: "stable",
- implied_by: ["BlinkGenPropertyTrees", "SlimmingPaintV2", "LayoutNG"],
- },
- {
name: "SlimmingPaintV2",
},
{
@@ -1217,11 +1220,12 @@
status: "experimental",
},
{
- name: "StopInBackground",
- status: "test",
+ name: "StaleWhileRevalidate",
+ origin_trial_feature_name: "StaleWhileRevalidate",
+ status: "experimental",
},
{
- name: "StopLoadingInBackground",
+ name: "StopInBackground",
status: "test",
},
{
@@ -1229,6 +1233,10 @@
status: "test",
},
{
+ name: "TextUnderlinePositionLeftRight",
+ status: "experimental",
+ },
+ {
name: "TimerThrottlingForBackgroundTabs",
status: "stable",
},
@@ -1274,6 +1282,10 @@
status: "stable",
},
{
+ name: "UserActivationAPI",
+ status: "experimental",
+ },
+ {
name: "UserActivationV2",
},
{
@@ -1334,25 +1346,31 @@
status: "experimental",
},
{
+ name: "WebGL2ComputeContext",
+ status: "experimental",
+ },
+ {
name: "WebGLDraftExtensions",
status: "experimental",
},
{
name: "WebGLImageChromium",
},
+ // WebGPU adds a large attack surface area to the GPU process and allows
+ // running arbitrary programs on the GPU (compute shaders), which may
+ // perform arbitrary read/writes of GPU memory if not properly sandboxed.
+ // That's why it is marked as "test" and not enabled as part of the
+ // --enable-experimental-web-platform-features flag.
{
- name: "WebLocksAPI",
- origin_trial_feature_name: "WebLocksAPI",
- status: "experimental",
+ name: "WebGPU",
+ status: "test",
},
{
- name: "WebNFC",
- status: "experimental",
+ name: "WebLocksAPI",
+ status: "stable",
},
{
- name: "WebRtcVaapiHWVP8Encoding",
- origin_trial_feature_name: "WebRtcVaapiHWVP8Encoding",
- origin_trial_os: ["chromeos"],
+ name: "WebNFC",
status: "experimental",
},
// WebShare is enabled by default on Android.
@@ -1365,13 +1383,17 @@
status: "stable",
},
{
- name: "WebUSBOnDedicatedAndSharedWorkers",
+ name: "WebUSBOnDedicatedWorkers",
+ status: "experimental",
+ depends_on: ["WebUSB"],
+ },
+ {
+ name: "WebUSBOnSharedWorkers",
status: "test",
depends_on: ["WebUSB"],
},
{
name: "WebVR",
- origin_trial_feature_name: "WebVR1.1M62",
status: "experimental",
},
{
@@ -1380,7 +1402,7 @@
},
{
name: "WebXR",
- origin_trial_feature_name: "WebXRDevice",
+ origin_trial_feature_name: "WebXRDeviceM69",
status: "experimental",
},
// Subset of the GamepadExtensions wanted for WebXR, which expose VR controller
@@ -1394,6 +1416,11 @@
},
{
name: "WebXRHitTest",
+ status: "experimental"
+ },
+ {
+ name: "WindowPostMessageOptions",
+ status: "experimental",
},
{
name: "WorkerNosniffBlock",
@@ -1405,10 +1432,6 @@
implied_by: ["WorkerNosniffBlock"],
},
{
- name: "Worklet",
- status: "stable",
- },
- {
name: "WorkStealingInScriptRunner",
status: "experimental",
},
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn b/chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn
index 6b3edf24340..eb785992cbe 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/scheduler/BUILD.gn
@@ -4,52 +4,12 @@
import("//build/config/jumbo.gni")
import("//third_party/blink/renderer/platform/platform.gni")
+import("//third_party/protobuf/proto_library.gni")
+import("//testing/libfuzzer/fuzzer_test.gni")
blink_platform_sources("scheduler") {
sources = [
- "base/enqueue_order.cc",
- "base/enqueue_order.h",
- "base/graceful_queue_shutdown_helper.cc",
- "base/graceful_queue_shutdown_helper.h",
- "base/intrusive_heap.h",
- "base/moveable_auto_lock.h",
- "base/real_time_domain.cc",
- "base/real_time_domain.h",
- "base/task_queue.cc",
- "base/task_queue.h",
- "base/task_queue_impl.cc",
- "base/task_queue_impl.h",
- "base/task_queue_manager.h",
- "base/task_queue_manager_impl.cc",
- "base/task_queue_manager_impl.h",
- "base/task_queue_selector.cc",
- "base/task_queue_selector.h",
- "base/task_queue_selector_logic.h",
- "base/task_time_observer.h",
- "base/thread_controller_impl.cc",
- "base/thread_controller_impl.h",
- "base/time_domain.cc",
- "base/time_domain.h",
- "base/virtual_time_domain.cc",
- "base/virtual_time_domain.h",
- "base/work_queue.cc",
- "base/work_queue.h",
- "base/work_queue_sets.cc",
- "base/work_queue_sets.h",
- "child/cancelable_closure_holder.cc",
- "child/cancelable_closure_holder.h",
- "child/compositor_metrics_helper.cc",
- "child/compositor_metrics_helper.h",
- "child/default_params.h",
"child/features.h",
- "child/idle_canceled_delayed_task_sweeper.cc",
- "child/idle_canceled_delayed_task_sweeper.h",
- "child/idle_helper.cc",
- "child/idle_helper.h",
- "child/metrics_helper.cc",
- "child/metrics_helper.h",
- "child/page_visibility_state.cc",
- "child/page_visibility_state.h",
"child/pollable_thread_safe_flag.cc",
"child/pollable_thread_safe_flag.h",
"child/process_state.cc",
@@ -60,16 +20,19 @@ blink_platform_sources("scheduler") {
"child/webthread_base.cc",
"child/webthread_impl_for_worker_scheduler.cc",
"child/webthread_impl_for_worker_scheduler.h",
- "child/worker_metrics_helper.cc",
- "child/worker_metrics_helper.h",
- "child/worker_scheduler.cc",
- "child/worker_scheduler.h",
- "child/worker_scheduler_proxy.cc",
- "child/worker_scheduler_proxy.h",
- "child/worker_task_queue.cc",
- "child/worker_task_queue.h",
+ "common/background_scheduler.cc",
+ "common/cancelable_closure_holder.cc",
+ "common/cancelable_closure_holder.h",
+ "common/frame_or_worker_scheduler.cc",
+ "common/idle_canceled_delayed_task_sweeper.cc",
+ "common/idle_canceled_delayed_task_sweeper.h",
+ "common/idle_helper.cc",
+ "common/idle_helper.h",
+ "common/metrics_helper.cc",
+ "common/metrics_helper.h",
"common/scheduler_helper.cc",
"common/scheduler_helper.h",
+ "common/scheduling_lifecycle_state.cc",
"common/thread_scheduler.cc",
"common/throttling/budget_pool.cc",
"common/throttling/budget_pool.h",
@@ -81,6 +44,11 @@ blink_platform_sources("scheduler") {
"common/throttling/throttled_time_domain.h",
"common/throttling/wake_up_budget_pool.cc",
"common/throttling/wake_up_budget_pool.h",
+ "common/total_duration_metric_reporter.cc",
+ "common/total_duration_metric_reporter.h",
+ "common/unprioritized_resource_loading_task_runner_handle.cc",
+ "common/unprioritized_resource_loading_task_runner_handle.h",
+ "common/web_resource_loading_task_runner_handle.cc",
"common/web_thread_scheduler.cc",
"main_thread/auto_advancing_virtual_time_domain.cc",
"main_thread/auto_advancing_virtual_time_domain.h",
@@ -90,6 +58,8 @@ blink_platform_sources("scheduler") {
"main_thread/frame_origin_type.h",
"main_thread/frame_scheduler_impl.cc",
"main_thread/frame_scheduler_impl.h",
+ "main_thread/frame_task_queue_controller.cc",
+ "main_thread/frame_task_queue_controller.h",
"main_thread/idle_time_estimator.cc",
"main_thread/idle_time_estimator.h",
"main_thread/main_thread_metrics_helper.cc",
@@ -102,30 +72,36 @@ blink_platform_sources("scheduler") {
"main_thread/main_thread_task_queue.h",
"main_thread/page_scheduler_impl.cc",
"main_thread/page_scheduler_impl.h",
+ "main_thread/page_visibility_state.cc",
+ "main_thread/page_visibility_state.h",
+ "main_thread/prioritize_compositing_after_input_experiment.cc",
+ "main_thread/prioritize_compositing_after_input_experiment.h",
"main_thread/queueing_time_estimator.cc",
"main_thread/queueing_time_estimator.h",
"main_thread/render_widget_signals.cc",
"main_thread/render_widget_signals.h",
+ "main_thread/resource_loading_task_runner_handle_impl.cc",
+ "main_thread/resource_loading_task_runner_handle_impl.h",
"main_thread/task_cost_estimator.cc",
"main_thread/task_cost_estimator.h",
"main_thread/use_case.h",
"main_thread/user_model.cc",
"main_thread/user_model.h",
- "main_thread/web_main_thread_scheduler.cc",
"main_thread/web_render_widget_scheduling_state.cc",
+ "public/background_scheduler.h",
"public/frame_or_worker_scheduler.h",
"public/frame_scheduler.h",
- "public/non_main_thread_scheduler.h",
+ "public/page_lifecycle_state.h",
"public/page_scheduler.h",
+ "public/scheduling_lifecycle_state.h",
"public/thread_scheduler.h",
- "public/web_main_thread_scheduler.h",
+ "public/worker_scheduler.h",
"renderer/frame_status.cc",
"renderer/frame_status.h",
"renderer/web_scoped_virtual_time_pauser.cc",
"renderer/webthread_impl_for_renderer_scheduler.cc",
"renderer/webthread_impl_for_renderer_scheduler.h",
"util/aggregated_metric_reporter.h",
- "util/task_duration_metric_reporter.cc",
"util/task_duration_metric_reporter.h",
"util/thread_cpu_throttler.cc",
"util/thread_cpu_throttler.h",
@@ -136,11 +112,21 @@ blink_platform_sources("scheduler") {
"util/tracing_helper.h",
"utility/webthread_impl_for_utility_thread.cc",
"utility/webthread_impl_for_utility_thread.h",
+ "worker/compositor_metrics_helper.cc",
+ "worker/compositor_metrics_helper.h",
"worker/compositor_thread_scheduler.cc",
"worker/compositor_thread_scheduler.h",
- "worker/non_main_thread_scheduler.cc",
"worker/non_main_thread_scheduler_helper.cc",
"worker/non_main_thread_scheduler_helper.h",
+ "worker/non_main_thread_scheduler_impl.cc",
+ "worker/non_main_thread_scheduler_impl.h",
+ "worker/non_main_thread_task_queue.cc",
+ "worker/non_main_thread_task_queue.h",
+ "worker/worker_metrics_helper.cc",
+ "worker/worker_metrics_helper.h",
+ "worker/worker_scheduler.cc",
+ "worker/worker_scheduler_proxy.cc",
+ "worker/worker_scheduler_proxy.h",
"worker/worker_thread_scheduler.cc",
"worker/worker_thread_scheduler.h",
]
@@ -159,26 +145,20 @@ jumbo_source_set("test_support") {
testonly = true
sources = [
- "base/test/task_queue_manager_for_test.cc",
- "base/test/task_queue_manager_for_test.h",
- "base/test/test_count_uses_time_source.cc",
- "base/test/test_count_uses_time_source.h",
- "base/test/test_task_queue.cc",
- "base/test/test_task_queue.h",
- "base/test/test_task_time_observer.h",
"test/fake_frame_scheduler.h",
"test/fake_page_scheduler.h",
"test/fake_renderer_scheduler.cc",
"test/fake_task_runner.cc",
"test/fake_task_runner.h",
- "test/lazy_thread_controller_for_test.cc",
- "test/lazy_thread_controller_for_test.h",
"test/renderer_scheduler_test_support.cc",
+ "test/test_queueing_time_estimator_client.cc",
+ "test/test_queueing_time_estimator_client.h",
]
deps = [
"//base",
"//base/test:test_support",
+ "//third_party/blink/public/mojom:mojom_platform_blink__generator",
]
configs += [ "//third_party/blink/renderer/platform:blink_platform_config" ]
@@ -188,24 +168,19 @@ jumbo_source_set("unit_tests") {
testonly = true
sources = [
- "base/intrusive_heap_unittest.cc",
- "base/task_queue_manager_impl_unittest.cc",
- "base/task_queue_selector_unittest.cc",
- "base/time_domain_unittest.cc",
- "base/work_queue_sets_unittest.cc",
- "base/work_queue_unittest.cc",
- "child/idle_canceled_delayed_task_sweeper_unittest.cc",
- "child/idle_helper_unittest.cc",
- "child/metrics_helper_unittest.cc",
"child/webthread_impl_for_worker_scheduler_unittest.cc",
- "child/worker_scheduler_proxy_unittest.cc",
- "child/worker_scheduler_unittest.cc",
+ "common/background_scheduler_unittest.cc",
+ "common/idle_canceled_delayed_task_sweeper_unittest.cc",
+ "common/idle_helper_unittest.cc",
+ "common/metrics_helper_unittest.cc",
"common/scheduler_helper_unittest.cc",
"common/throttling/budget_pool_unittest.cc",
"common/throttling/task_queue_throttler_unittest.cc",
+ "common/total_duration_metric_reporter_unittest.cc",
"main_thread/auto_advancing_virtual_time_domain_unittest.cc",
"main_thread/deadline_task_runner_unittest.cc",
"main_thread/frame_scheduler_impl_unittest.cc",
+ "main_thread/frame_task_queue_controller_unittest.cc",
"main_thread/idle_time_estimator_unittest.cc",
"main_thread/main_thread_metrics_helper_unittest.cc",
"main_thread/main_thread_scheduler_impl_unittest.cc",
@@ -215,17 +190,17 @@ jumbo_source_set("unit_tests") {
"main_thread/task_cost_estimator_unittest.cc",
"main_thread/user_model_unittest.cc",
"renderer/webthread_impl_for_renderer_scheduler_unittest.cc",
- "util/task_duration_metric_reporter_unittest.cc",
"util/thread_load_tracker_unittest.cc",
"util/tracing_helper_unittest.cc",
+ "worker/compositor_thread_scheduler_unittest.cc",
+ "worker/worker_scheduler_proxy_unittest.cc",
+ "worker/worker_scheduler_unittest.cc",
"worker/worker_thread_scheduler_unittest.cc",
]
deps = [
"//base",
"//base/test:test_support",
- "//components/viz/common",
- "//components/viz/test:test_support",
"//testing/gmock",
"//testing/gtest",
"//third_party/blink/public:test_support",
@@ -238,7 +213,7 @@ source_set("perf_tests") {
testonly = true
sources = [
- "base/task_queue_manager_perftest.cc",
+ "test/queueing_time_estimator_perf_test.cc",
]
deps = [
@@ -247,7 +222,57 @@ source_set("perf_tests") {
"//testing/gmock",
"//testing/gtest",
"//testing/perf",
+ "//third_party/blink/public:test_support",
+ ]
+
+ configs += [ "//third_party/blink/renderer/platform:blink_platform_config" ]
+}
+
+source_set("scheduler_fuzzer_tests") {
+ testonly = true
+
+ sources = []
+ deps = [
+ "//base",
+ "//base/test:test_support",
+ "//testing/gmock",
+ "//testing/gtest",
+ "//third_party/blink/renderer/platform/scheduler:test_support",
]
+ if (is_linux) {
+ sources += [
+ "base/sequence_manager_fuzzer_processor.cc",
+ "base/sequence_manager_fuzzer_processor.h",
+ "base/sequence_manager_fuzzer_processor_unittest.cc",
+ ]
+
+ deps += [
+ ":sequence_manager_test_description_proto",
+ "//third_party/libprotobuf-mutator",
+ ]
+ }
+
configs += [ "//third_party/blink/renderer/platform:blink_platform_config" ]
}
+
+fuzzer_test("sequence_manager_fuzzer") {
+ sources = [
+ "base/sequence_manager_fuzzer.cc",
+ "base/sequence_manager_fuzzer_processor.cc",
+ "base/sequence_manager_fuzzer_processor.h",
+ ]
+
+ deps = [
+ ":sequence_manager_test_description_proto",
+ "//third_party/blink/renderer/platform:blink_fuzzer_test_support",
+ "//third_party/blink/renderer/platform:test_support",
+ "//third_party/libprotobuf-mutator",
+ ]
+}
+
+proto_library("sequence_manager_test_description_proto") {
+ sources = [
+ "base/proto/sequence_manager_test_description.proto",
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/DEPS b/chromium/third_party/blink/renderer/platform/scheduler/DEPS
index 872751e234f..c8e9a1cdcca 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/DEPS
+++ b/chromium/third_party/blink/renderer/platform/scheduler/DEPS
@@ -35,7 +35,10 @@ include_rules = [
"+base/synchronization/atomic_flag.h",
"+base/synchronization/cancellation_flag.h",
"+base/synchronization/lock.h",
- "+base/task/sequence_manager",
+ "+base/task/sequence_manager/lazy_now.h",
+ "+base/task/sequence_manager/sequence_manager.h",
+ "+base/task/sequence_manager/task_queue.h",
+ "+base/task/sequence_manager/time_domain.h",
"+base/threading/platform_thread.h",
"+base/threading/sequenced_task_runner_handle.h",
"+base/threading/thread.h",
@@ -56,6 +59,10 @@ include_rules = [
specific_include_rules = {
".*test\.cc": [
"+base/metrics/field_trial_param_associator.h",
+ "+base/task/sequence_manager/test",
"+testing",
],
+ "sequence_manager_fuzzer.cc": [
+ '+testing/libfuzzer/proto/lpm_interface.h'
+ ],
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/README.md b/chromium/third_party/blink/renderer/platform/scheduler/README.md
index 610e26ff86b..461593517e0 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/README.md
+++ b/chromium/third_party/blink/renderer/platform/scheduler/README.md
@@ -4,7 +4,7 @@ This directory contains the Blink Scheduler, which coordinates task execution
in renderer processes. The main subdirectories are:
- `base/` -- basic scheduling primitives such as `TaskQueue` and
- `TaskQueueManager`.
+ `SequenceManager`.
- `child/` -- contains the `ChildScheduler` which is the base class for all
thread schedulers, as well as a `WorkerScheduler` for worker threads.
- `utility/` -- a small scheduler for utility processes.
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/DEPS b/chromium/third_party/blink/renderer/platform/scheduler/base/DEPS
index 2b191979763..5fcbda71de3 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/DEPS
+++ b/chromium/third_party/blink/renderer/platform/scheduler/base/DEPS
@@ -6,3 +6,10 @@ include_rules = [
"+third_party/blink/renderer/platform/platform_export.h",
"+base",
]
+
+specific_include_rules = {
+ "sequence_manager_fuzzer_processor_unittest.cc": [
+ "+third_party/protobuf/src/google/protobuf/text_format.h",
+ "+third_party/protobuf/src/google/protobuf/util/message_differencer.h",
+ ],
+}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/enqueue_order.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/enqueue_order.cc
deleted file mode 100644
index 0baabcbaf15..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/enqueue_order.cc
+++ /dev/null
@@ -1,25 +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/platform/scheduler/base/enqueue_order.h"
-
-namespace base {
-namespace sequence_manager {
-namespace internal {
-
-// Note we set the first |enqueue_order_| to a specific non-zero value, because
-// first N values of EnqueueOrder have special meaning (see EnqueueOrderValues).
-EnqueueOrderGenerator::EnqueueOrderGenerator()
- : enqueue_order_(static_cast<EnqueueOrder>(EnqueueOrderValues::kFirst)) {}
-
-EnqueueOrderGenerator::~EnqueueOrderGenerator() = default;
-
-EnqueueOrder EnqueueOrderGenerator::GenerateNext() {
- AutoLock lock(lock_);
- return enqueue_order_++;
-}
-
-} // namespace internal
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/enqueue_order.h b/chromium/third_party/blink/renderer/platform/scheduler/base/enqueue_order.h
deleted file mode 100644
index ae5f480feae..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/enqueue_order.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_ENQUEUE_ORDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_ENQUEUE_ORDER_H_
-
-#include <stdint.h>
-
-#include "base/synchronization/lock.h"
-
-namespace base {
-namespace sequence_manager {
-namespace internal {
-
-using EnqueueOrder = uint64_t;
-
-// TODO(scheduler-dev): Remove explicit casts when c++17 comes.
-enum class EnqueueOrderValues : EnqueueOrder {
- // Invalid EnqueueOrder.
- kNone = 0,
-
- // Earliest possible EnqueueOrder, to be used for fence blocking.
- kBlockingFence = 1,
- kFirst = 2,
-};
-
-// A 64bit integer used to provide ordering of tasks. NOTE The scheduler assumes
-// these values will not overflow.
-class EnqueueOrderGenerator {
- public:
- EnqueueOrderGenerator();
- ~EnqueueOrderGenerator();
-
- // Returns a monotonically increasing integer, starting from one. Can be
- // called from any thread.
- EnqueueOrder GenerateNext();
-
- static bool IsValidEnqueueOrder(EnqueueOrder enqueue_order) {
- return enqueue_order != 0ull;
- }
-
- private:
- Lock lock_;
- EnqueueOrder enqueue_order_;
-};
-
-} // namespace internal
-} // namespace sequence_manager
-} // namespace base
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_ENQUEUE_ORDER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/graceful_queue_shutdown_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/graceful_queue_shutdown_helper.cc
deleted file mode 100644
index 6ea076b1c71..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/graceful_queue_shutdown_helper.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-
-namespace base {
-namespace sequence_manager {
-namespace internal {
-
-GracefulQueueShutdownHelper::GracefulQueueShutdownHelper()
- : task_queue_manager_deleted_(false) {}
-
-GracefulQueueShutdownHelper::~GracefulQueueShutdownHelper() = default;
-
-void GracefulQueueShutdownHelper::GracefullyShutdownTaskQueue(
- std::unique_ptr<internal::TaskQueueImpl> task_queue) {
- AutoLock lock(lock_);
- if (task_queue_manager_deleted_)
- return;
- queues_.push_back(std::move(task_queue));
-}
-
-void GracefulQueueShutdownHelper::OnTaskQueueManagerDeleted() {
- AutoLock lock(lock_);
- task_queue_manager_deleted_ = true;
- queues_.clear();
-}
-
-std::vector<std::unique_ptr<internal::TaskQueueImpl>>
-GracefulQueueShutdownHelper::TakeQueues() {
- AutoLock lock(lock_);
- std::vector<std::unique_ptr<internal::TaskQueueImpl>> result;
- result.swap(queues_);
- return result;
-}
-
-} // namespace internal
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/graceful_queue_shutdown_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/base/graceful_queue_shutdown_helper.h
deleted file mode 100644
index 79d0b1b6890..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/graceful_queue_shutdown_helper.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_GRACEFUL_QUEUE_SHUTDOWN_HELPER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_GRACEFUL_QUEUE_SHUTDOWN_HELPER_H_
-
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/lock.h"
-
-namespace base {
-namespace sequence_manager {
-namespace internal {
-
-class TaskQueueImpl;
-
-// Thread-safe helper to shutdown queues from any thread.
-class GracefulQueueShutdownHelper
- : public RefCountedThreadSafe<GracefulQueueShutdownHelper> {
- public:
- GracefulQueueShutdownHelper();
- ~GracefulQueueShutdownHelper();
-
- void GracefullyShutdownTaskQueue(
- std::unique_ptr<internal::TaskQueueImpl> queue);
-
- void OnTaskQueueManagerDeleted();
-
- std::vector<std::unique_ptr<internal::TaskQueueImpl>> TakeQueues();
-
- private:
- Lock lock_;
- bool task_queue_manager_deleted_;
- std::vector<std::unique_ptr<internal::TaskQueueImpl>> queues_;
-
- DISALLOW_COPY_AND_ASSIGN(GracefulQueueShutdownHelper);
-};
-
-} // namespace internal
-} // namespace sequence_manager
-} // namespace base
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_GRACEFUL_QUEUE_SHUTDOWN_HELPER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/intrusive_heap.h b/chromium/third_party/blink/renderer/platform/scheduler/base/intrusive_heap.h
deleted file mode 100644
index 0b2aa9ff95a..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/intrusive_heap.h
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_INTRUSIVE_HEAP_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_INTRUSIVE_HEAP_H_
-
-#include <algorithm>
-#include <vector>
-
-#include "base/logging.h"
-
-namespace base {
-namespace sequence_manager {
-
-template <typename T>
-class IntrusiveHeap;
-
-// Intended as an opaque wrapper around |index_|.
-class HeapHandle {
- public:
- HeapHandle() : index_(0u) {}
-
- bool IsValid() const { return index_ != 0u; }
-
- private:
- template <typename T>
- friend class IntrusiveHeap;
-
- HeapHandle(size_t index) : index_(index) {}
-
- size_t index_;
-};
-
-// A standard min-heap with the following assumptions:
-// 1. T has operator <=
-// 2. T has method void SetHeapHandle(HeapHandle handle)
-// 3. T has method void ClearHeapHandle()
-// 4. T is moveable
-// 5. T is default constructible
-// 6. The heap size never gets terribly big so reclaiming memory on pop/erase
-// isn't a priority.
-//
-// The reason IntrusiveHeap exists is to provide similar performance to
-// std::priority_queue while allowing removal of arbitrary elements.
-template <typename T>
-class IntrusiveHeap {
- public:
- IntrusiveHeap() : nodes_(kMinimumHeapSize), size_(0) {}
-
- ~IntrusiveHeap() {
- for (size_t i = 1; i <= size_; i++) {
- MakeHole(i);
- }
- }
-
- bool empty() const { return size_ == 0; }
-
- size_t size() const { return size_; }
-
- void Clear() {
- for (size_t i = 1; i <= size_; i++) {
- MakeHole(i);
- }
- nodes_.resize(kMinimumHeapSize);
- size_ = 0;
- }
-
- const T& Min() const {
- DCHECK_GE(size_, 1u);
- return nodes_[1];
- }
-
- void Pop() {
- DCHECK_GE(size_, 1u);
- MakeHole(1u);
- size_t top_index = size_--;
- if (!empty())
- MoveHoleDownAndFillWithLeafElement(1u, std::move(nodes_[top_index]));
- }
-
- void insert(T&& element) {
- size_++;
- if (size_ >= nodes_.size())
- nodes_.resize(nodes_.size() * 2);
- // Notionally we have a hole in the tree at index |size_|, move this up
- // to find the right insertion point.
- MoveHoleUpAndFillWithElement(size_, std::move(element));
- }
-
- void erase(HeapHandle handle) {
- DCHECK_GT(handle.index_, 0u);
- DCHECK_LE(handle.index_, size_);
- MakeHole(handle.index_);
- size_t top_index = size_--;
- if (empty() || top_index == handle.index_)
- return;
- if (nodes_[handle.index_] <= nodes_[top_index]) {
- MoveHoleDownAndFillWithLeafElement(handle.index_,
- std::move(nodes_[top_index]));
- } else {
- MoveHoleUpAndFillWithElement(handle.index_, std::move(nodes_[top_index]));
- }
- }
-
- void ReplaceMin(T&& element) {
- // Note |element| might not be a leaf node so we can't use
- // MoveHoleDownAndFillWithLeafElement.
- MoveHoleDownAndFillWithElement(1u, std::move(element));
- }
-
- void ChangeKey(HeapHandle handle, T&& element) {
- if (nodes_[handle.index_] <= element) {
- MoveHoleDownAndFillWithLeafElement(handle.index_, std::move(element));
- } else {
- MoveHoleUpAndFillWithElement(handle.index_, std::move(element));
- }
- }
-
- // Caution mutating the heap invalidates the iterators.
- const T* begin() const { return &nodes_[1u]; }
- const T* end() const { return begin() + size_; }
-
- private:
- enum {
- // The majority of sets in the scheduler have 0-3 items in them (a few will
- // have perhaps up to 100), so this means we usually only have to allocate
- // memory once.
- kMinimumHeapSize = 4u
- };
-
- friend class IntrusiveHeapTest;
-
- size_t MoveHole(size_t new_hole_pos, size_t old_hole_pos) {
- DCHECK_GT(new_hole_pos, 0u);
- DCHECK_LE(new_hole_pos, size_);
- DCHECK_GT(new_hole_pos, 0u);
- DCHECK_LE(new_hole_pos, size_);
- DCHECK_NE(old_hole_pos, new_hole_pos);
- nodes_[old_hole_pos] = std::move(nodes_[new_hole_pos]);
- nodes_[old_hole_pos].SetHeapHandle(HeapHandle(old_hole_pos));
- return new_hole_pos;
- }
-
- // Notionally creates a hole in the tree at |index|.
- void MakeHole(size_t index) {
- DCHECK_GT(index, 0u);
- DCHECK_LE(index, size_);
- nodes_[index].ClearHeapHandle();
- }
-
- void FillHole(size_t hole, T&& element) {
- DCHECK_GT(hole, 0u);
- DCHECK_LE(hole, size_);
- nodes_[hole] = std::move(element);
- nodes_[hole].SetHeapHandle(HeapHandle(hole));
- DCHECK(std::is_heap(begin(), end(), CompareNodes));
- }
-
- // is_heap requires a strict comparator.
- static bool CompareNodes(const T& a, const T& b) { return !(a <= b); }
-
- // Moves the |hole| up the tree and when the right position has been found
- // |element| is moved in.
- void MoveHoleUpAndFillWithElement(size_t hole, T&& element) {
- DCHECK_GT(hole, 0u);
- DCHECK_LE(hole, size_);
- while (hole >= 2u) {
- size_t parent_pos = hole / 2;
- if (nodes_[parent_pos] <= element)
- break;
-
- hole = MoveHole(parent_pos, hole);
- }
- FillHole(hole, std::move(element));
- }
-
- // Moves the |hole| down the tree and when the right position has been found
- // |element| is moved in.
- void MoveHoleDownAndFillWithElement(size_t hole, T&& element) {
- DCHECK_GT(hole, 0u);
- DCHECK_LE(hole, size_);
- size_t child_pos = hole * 2;
- while (child_pos < size_) {
- if (nodes_[child_pos + 1] <= nodes_[child_pos])
- child_pos++;
-
- if (element <= nodes_[child_pos])
- break;
-
- hole = MoveHole(child_pos, hole);
- child_pos *= 2;
- }
- if (child_pos == size_ && !(element <= nodes_[child_pos]))
- hole = MoveHole(child_pos, hole);
- FillHole(hole, std::move(element));
- }
-
- // Moves the |hole| down the tree and when the right position has been found
- // |leaf_element| is moved in. Faster than MoveHoleDownAndFillWithElement
- // (it does one key comparison per level instead of two) but only valid for
- // leaf elements (i.e. one of the max values).
- void MoveHoleDownAndFillWithLeafElement(size_t hole, T&& leaf_element) {
- DCHECK_GT(hole, 0u);
- DCHECK_LE(hole, size_);
- size_t child_pos = hole * 2;
- while (child_pos < size_) {
- size_t second_child = child_pos + 1;
- if (nodes_[second_child] <= nodes_[child_pos])
- child_pos = second_child;
-
- hole = MoveHole(child_pos, hole);
- child_pos *= 2;
- }
- if (child_pos == size_)
- hole = MoveHole(child_pos, hole);
- MoveHoleUpAndFillWithElement(hole, std::move(leaf_element));
- }
-
- std::vector<T> nodes_; // NOTE we use 1-based indexing
- size_t size_;
-};
-
-} // namespace sequence_manager
-} // namespace base
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_INTRUSIVE_HEAP_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/intrusive_heap_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/intrusive_heap_unittest.cc
deleted file mode 100644
index c20412c8a78..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/intrusive_heap_unittest.cc
+++ /dev/null
@@ -1,374 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/base/intrusive_heap.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace sequence_manager {
-namespace {
-
-struct TestElement {
- int key;
- HeapHandle* handle;
-
- bool operator<=(const TestElement& other) const { return key <= other.key; }
-
- void SetHeapHandle(HeapHandle h) {
- if (handle)
- *handle = h;
- }
-
- void ClearHeapHandle() {
- if (handle)
- *handle = HeapHandle();
- }
-};
-
-} // namespace
-
-class IntrusiveHeapTest : public testing::Test {
- protected:
- static bool CompareNodes(const TestElement& a, const TestElement& b) {
- return IntrusiveHeap<TestElement>::CompareNodes(a, b);
- }
-};
-
-TEST_F(IntrusiveHeapTest, Basic) {
- IntrusiveHeap<TestElement> heap;
-
- EXPECT_TRUE(heap.empty());
- EXPECT_EQ(0u, heap.size());
-}
-
-TEST_F(IntrusiveHeapTest, Clear) {
- IntrusiveHeap<TestElement> heap;
- HeapHandle index1;
-
- heap.insert({11, &index1});
- EXPECT_EQ(1u, heap.size());
- EXPECT_TRUE(index1.IsValid());
-
- heap.Clear();
- EXPECT_EQ(0u, heap.size());
- EXPECT_FALSE(index1.IsValid());
-}
-
-TEST_F(IntrusiveHeapTest, Destructor) {
- HeapHandle index1;
-
- {
- IntrusiveHeap<TestElement> heap;
-
- heap.insert({11, &index1});
- EXPECT_EQ(1u, heap.size());
- EXPECT_TRUE(index1.IsValid());
- }
-
- EXPECT_FALSE(index1.IsValid());
-}
-
-TEST_F(IntrusiveHeapTest, Min) {
- IntrusiveHeap<TestElement> heap;
-
- heap.insert({9, nullptr});
- heap.insert({10, nullptr});
- heap.insert({8, nullptr});
- heap.insert({2, nullptr});
- heap.insert({7, nullptr});
- heap.insert({15, nullptr});
- heap.insert({22, nullptr});
- heap.insert({3, nullptr});
-
- EXPECT_FALSE(heap.empty());
- EXPECT_EQ(8u, heap.size());
- EXPECT_EQ(2, heap.Min().key);
-}
-
-TEST_F(IntrusiveHeapTest, InsertAscending) {
- IntrusiveHeap<TestElement> heap;
- HeapHandle index1;
-
- for (int i = 0; i < 50; i++)
- heap.insert({i, nullptr});
-
- EXPECT_EQ(0, heap.Min().key);
- EXPECT_EQ(50u, heap.size());
-}
-
-TEST_F(IntrusiveHeapTest, InsertDescending) {
- IntrusiveHeap<TestElement> heap;
-
- for (int i = 0; i < 50; i++)
- heap.insert({50 - i, nullptr});
-
- EXPECT_EQ(1, heap.Min().key);
- EXPECT_EQ(50u, heap.size());
-}
-
-TEST_F(IntrusiveHeapTest, HeapIndex) {
- HeapHandle index5;
- HeapHandle index4;
- HeapHandle index3;
- HeapHandle index2;
- HeapHandle index1;
- IntrusiveHeap<TestElement> heap;
-
- EXPECT_FALSE(index1.IsValid());
- EXPECT_FALSE(index2.IsValid());
- EXPECT_FALSE(index3.IsValid());
- EXPECT_FALSE(index4.IsValid());
- EXPECT_FALSE(index5.IsValid());
-
- heap.insert({15, &index5});
- heap.insert({14, &index4});
- heap.insert({13, &index3});
- heap.insert({12, &index2});
- heap.insert({11, &index1});
-
- EXPECT_TRUE(index1.IsValid());
- EXPECT_TRUE(index2.IsValid());
- EXPECT_TRUE(index3.IsValid());
- EXPECT_TRUE(index4.IsValid());
- EXPECT_TRUE(index5.IsValid());
-
- EXPECT_FALSE(heap.empty());
-}
-
-TEST_F(IntrusiveHeapTest, Pop) {
- IntrusiveHeap<TestElement> heap;
- HeapHandle index1;
- HeapHandle index2;
-
- heap.insert({11, &index1});
- heap.insert({12, &index2});
- EXPECT_EQ(2u, heap.size());
- EXPECT_TRUE(index1.IsValid());
- EXPECT_TRUE(index2.IsValid());
-
- heap.Pop();
- EXPECT_EQ(1u, heap.size());
- EXPECT_FALSE(index1.IsValid());
- EXPECT_TRUE(index2.IsValid());
-
- heap.Pop();
- EXPECT_EQ(0u, heap.size());
- EXPECT_FALSE(index1.IsValid());
- EXPECT_FALSE(index2.IsValid());
-}
-
-TEST_F(IntrusiveHeapTest, PopMany) {
- IntrusiveHeap<TestElement> heap;
-
- for (int i = 0; i < 500; i++)
- heap.insert({i, nullptr});
-
- EXPECT_FALSE(heap.empty());
- EXPECT_EQ(500u, heap.size());
- for (int i = 0; i < 500; i++) {
- EXPECT_EQ(i, heap.Min().key);
- heap.Pop();
- }
- EXPECT_TRUE(heap.empty());
-}
-
-TEST_F(IntrusiveHeapTest, Erase) {
- IntrusiveHeap<TestElement> heap;
-
- HeapHandle index12;
-
- heap.insert({15, nullptr});
- heap.insert({14, nullptr});
- heap.insert({13, nullptr});
- heap.insert({12, &index12});
- heap.insert({11, nullptr});
-
- EXPECT_EQ(5u, heap.size());
- EXPECT_TRUE(index12.IsValid());
- heap.erase(index12);
- EXPECT_EQ(4u, heap.size());
- EXPECT_FALSE(index12.IsValid());
-
- EXPECT_EQ(11, heap.Min().key);
- heap.Pop();
- EXPECT_EQ(13, heap.Min().key);
- heap.Pop();
- EXPECT_EQ(14, heap.Min().key);
- heap.Pop();
- EXPECT_EQ(15, heap.Min().key);
- heap.Pop();
- EXPECT_TRUE(heap.empty());
-}
-
-TEST_F(IntrusiveHeapTest, ReplaceMin) {
- IntrusiveHeap<TestElement> heap;
-
- for (int i = 0; i < 500; i++)
- heap.insert({500 - i, nullptr});
-
- EXPECT_EQ(1, heap.Min().key);
-
- for (int i = 0; i < 500; i++)
- heap.ReplaceMin({1000 + i, nullptr});
-
- EXPECT_EQ(1000, heap.Min().key);
-}
-
-TEST_F(IntrusiveHeapTest, ReplaceMinWithNonLeafNode) {
- IntrusiveHeap<TestElement> heap;
-
- for (int i = 0; i < 50; i++) {
- heap.insert({i, nullptr});
- heap.insert({200 + i, nullptr});
- }
-
- EXPECT_EQ(0, heap.Min().key);
-
- for (int i = 0; i < 50; i++)
- heap.ReplaceMin({100 + i, nullptr});
-
- for (int i = 0; i < 50; i++) {
- EXPECT_EQ((100 + i), heap.Min().key);
- heap.Pop();
- }
- for (int i = 0; i < 50; i++) {
- EXPECT_EQ((200 + i), heap.Min().key);
- heap.Pop();
- }
- EXPECT_TRUE(heap.empty());
-}
-
-TEST_F(IntrusiveHeapTest, ReplaceMinCheckAllFinalPositions) {
- HeapHandle index[100];
-
- for (int j = -1; j <= 201; j += 2) {
- IntrusiveHeap<TestElement> heap;
- for (size_t i = 0; i < 100; i++) {
- heap.insert({static_cast<int>(i) * 2, &index[i]});
- }
-
- heap.ReplaceMin({j, &index[40]});
-
- int prev = -2;
- while (!heap.empty()) {
- DCHECK_GT(heap.Min().key, prev);
- DCHECK(heap.Min().key == j || (heap.Min().key % 2) == 0);
- DCHECK_NE(heap.Min().key, 0);
- prev = heap.Min().key;
- heap.Pop();
- }
- }
-}
-
-TEST_F(IntrusiveHeapTest, ChangeKeyUp) {
- IntrusiveHeap<TestElement> heap;
- HeapHandle index[10];
-
- for (size_t i = 0; i < 10; i++) {
- heap.insert({static_cast<int>(i) * 2, &index[i]});
- }
-
- heap.ChangeKey(index[5], {17, &index[5]});
-
- std::vector<int> results;
- while (!heap.empty()) {
- results.push_back(heap.Min().key);
- heap.Pop();
- }
-
- EXPECT_THAT(results, testing::ElementsAre(0, 2, 4, 6, 8, 12, 14, 16, 17, 18));
-}
-
-TEST_F(IntrusiveHeapTest, ChangeKeyUpButDoesntMove) {
- IntrusiveHeap<TestElement> heap;
- HeapHandle index[10];
-
- for (size_t i = 0; i < 10; i++) {
- heap.insert({static_cast<int>(i) * 2, &index[i]});
- }
-
- heap.ChangeKey(index[5], {11, &index[5]});
-
- std::vector<int> results;
- while (!heap.empty()) {
- results.push_back(heap.Min().key);
- heap.Pop();
- }
-
- EXPECT_THAT(results, testing::ElementsAre(0, 2, 4, 6, 8, 11, 12, 14, 16, 18));
-}
-
-TEST_F(IntrusiveHeapTest, ChangeKeyDown) {
- IntrusiveHeap<TestElement> heap;
- HeapHandle index[10];
-
- for (size_t i = 0; i < 10; i++) {
- heap.insert({static_cast<int>(i) * 2, &index[i]});
- }
-
- heap.ChangeKey(index[5], {1, &index[5]});
-
- std::vector<int> results;
- while (!heap.empty()) {
- results.push_back(heap.Min().key);
- heap.Pop();
- }
-
- EXPECT_THAT(results, testing::ElementsAre(0, 1, 2, 4, 6, 8, 12, 14, 16, 18));
-}
-
-TEST_F(IntrusiveHeapTest, ChangeKeyDownButDoesntMove) {
- IntrusiveHeap<TestElement> heap;
- HeapHandle index[10];
-
- for (size_t i = 0; i < 10; i++) {
- heap.insert({static_cast<int>(i) * 2, &index[i]});
- }
-
- heap.ChangeKey(index[5], {9, &index[5]});
-
- std::vector<int> results;
- while (!heap.empty()) {
- results.push_back(heap.Min().key);
- heap.Pop();
- }
-
- EXPECT_THAT(results, testing::ElementsAre(0, 2, 4, 6, 8, 9, 12, 14, 16, 18));
-}
-
-TEST_F(IntrusiveHeapTest, ChangeKeyCheckAllFinalPositions) {
- HeapHandle index[100];
-
- for (int j = -1; j <= 201; j += 2) {
- IntrusiveHeap<TestElement> heap;
- for (size_t i = 0; i < 100; i++) {
- heap.insert({static_cast<int>(i) * 2, &index[i]});
- }
-
- heap.ChangeKey(index[40], {j, &index[40]});
-
- int prev = -2;
- while (!heap.empty()) {
- DCHECK_GT(heap.Min().key, prev);
- DCHECK(heap.Min().key == j || (heap.Min().key % 2) == 0);
- DCHECK_NE(heap.Min().key, 80);
- prev = heap.Min().key;
- heap.Pop();
- }
- }
-}
-
-TEST_F(IntrusiveHeapTest, CompareNodes) {
- TestElement five{5, nullptr}, six{6, nullptr};
-
- // This is the stdlibc++ assertion that fails in http://crbug.com/661080
- EXPECT_FALSE(IntrusiveHeapTest::CompareNodes(six, six));
-
- EXPECT_FALSE(IntrusiveHeapTest::CompareNodes(five, six));
- EXPECT_TRUE(IntrusiveHeapTest::CompareNodes(six, five));
-}
-
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/moveable_auto_lock.h b/chromium/third_party/blink/renderer/platform/scheduler/base/moveable_auto_lock.h
deleted file mode 100644
index 4065ebe46f8..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/moveable_auto_lock.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_MOVEABLE_AUTO_LOCK_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_MOVEABLE_AUTO_LOCK_H_
-
-#include "base/synchronization/lock.h"
-
-namespace base {
-namespace sequence_manager {
-
-class MoveableAutoLock {
- public:
- explicit MoveableAutoLock(Lock& lock) : lock_(lock), moved_(false) {
- lock_.Acquire();
- }
-
- MoveableAutoLock(MoveableAutoLock&& other)
- : lock_(other.lock_), moved_(other.moved_) {
- lock_.AssertAcquired();
- other.moved_ = true;
- }
-
- ~MoveableAutoLock() {
- if (moved_)
- return;
- lock_.AssertAcquired();
- lock_.Release();
- }
-
- private:
- Lock& lock_;
- bool moved_;
- DISALLOW_COPY_AND_ASSIGN(MoveableAutoLock);
-};
-
-} // namespace sequence_manager
-} // namespace base
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_MOVEABLE_AUTO_LOCK_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/proto/sequence_manager_test_description.proto b/chromium/third_party/blink/renderer/platform/scheduler/base/proto/sequence_manager_test_description.proto
new file mode 100644
index 00000000000..59f25384bc7
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/base/proto/sequence_manager_test_description.proto
@@ -0,0 +1,67 @@
+syntax = "proto2";
+
+package base.sequence_manager;
+
+// Describes the grammar of the fuzzer's test description. At a high level, it
+// describes a sequence of actions that can be executed.
+message SequenceManagerTestDescription {
+ // NEXT ID = 2
+
+ enum QueuePriority {
+ // NEXT ID = 6
+
+ UNDEFINED = 0;
+ BEST_EFFORT = 1;
+ LOW = 2;
+ NORMAL = 3;
+ HIGH = 4;
+ HIGHEST = 5;
+ }
+
+ // Describes interfaces that can be tested by the fuzzer.
+ // TODO(farahcharab) Add more interfaces here.
+ message Action {
+ // NEXT ID = 4
+
+ optional uint64 action_id = 1;
+
+ oneof action {
+ CreateTaskQueueAction create_task_queue = 2;
+ PostDelayedTaskAction post_delayed_task = 3;
+ }
+ }
+
+ message Task {
+ // NEXT ID = 4
+
+ optional uint64 task_id = 1;
+
+ optional uint64 duration_ms = 2;
+
+ // If not set, then this is a no-op task.
+ repeated Action action = 3;
+ }
+
+ // Describes the grammar of SequenceManager::CreateTaskQueue.
+ message CreateTaskQueueAction {
+ // NEXT ID = 2
+
+ optional QueuePriority initial_priority = 1;
+ }
+
+ // Describes the grammar of TaskQueue::PostDelayedTask.
+ message PostDelayedTaskAction {
+ // NEXT ID = 4
+
+ // Used to identify the queue to post to.
+ optional uint64 task_queue_id = 1;
+
+ optional Task task = 2;
+
+ // Delay parameter passed to TaskQueue::PostDelayedTask i.e. the delay is
+ // measured after executing the PostDelayedTaskAction.
+ optional uint64 delay_ms = 3;
+ }
+
+ repeated Action initial_actions = 1;
+}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/real_time_domain.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/real_time_domain.cc
deleted file mode 100644
index a30dc11e16b..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/real_time_domain.cc
+++ /dev/null
@@ -1,68 +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/platform/scheduler/base/real_time_domain.h"
-
-#include "base/bind.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl.h"
-
-namespace base {
-namespace sequence_manager {
-
-RealTimeDomain::RealTimeDomain() : task_queue_manager_(nullptr) {}
-
-RealTimeDomain::~RealTimeDomain() = default;
-
-void RealTimeDomain::OnRegisterWithTaskQueueManager(
- TaskQueueManagerImpl* task_queue_manager) {
- task_queue_manager_ = task_queue_manager;
- DCHECK(task_queue_manager_);
-}
-
-LazyNow RealTimeDomain::CreateLazyNow() const {
- return task_queue_manager_->CreateLazyNow();
-}
-
-TimeTicks RealTimeDomain::Now() const {
- return task_queue_manager_->NowTicks();
-}
-
-void RealTimeDomain::RequestWakeUpAt(TimeTicks now, TimeTicks run_time) {
- // NOTE this is only called if the scheduled runtime is sooner than any
- // previously scheduled runtime, or there is no (outstanding) previously
- // scheduled runtime.
- task_queue_manager_->MaybeScheduleDelayedWork(FROM_HERE, this, now, run_time);
-}
-
-void RealTimeDomain::CancelWakeUpAt(TimeTicks run_time) {
- task_queue_manager_->CancelDelayedWork(this, run_time);
-}
-
-Optional<TimeDelta> RealTimeDomain::DelayTillNextTask(LazyNow* lazy_now) {
- TimeTicks next_run_time;
- if (!NextScheduledRunTime(&next_run_time))
- return nullopt;
-
- TimeTicks now = lazy_now->Now();
- if (now >= next_run_time)
- return TimeDelta(); // Makes DoWork post an immediate continuation.
-
- TimeDelta delay = next_run_time - now;
- TRACE_EVENT1("sequence_manager", "RealTimeDomain::DelayTillNextTask",
- "delay_ms", delay.InMillisecondsF());
-
- // The next task is sometime in the future. DoWork will make sure it gets
- // run at the right time.
- return delay;
-}
-
-void RealTimeDomain::AsValueIntoInternal(
- trace_event::TracedValue* state) const {}
-
-const char* RealTimeDomain::GetName() const {
- return "RealTimeDomain";
-}
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/real_time_domain.h b/chromium/third_party/blink/renderer/platform/scheduler/base/real_time_domain.h
deleted file mode 100644
index f89191d4627..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/real_time_domain.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_REAL_TIME_DOMAIN_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_REAL_TIME_DOMAIN_H_
-
-#include <set>
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/time_domain.h"
-
-namespace base {
-namespace sequence_manager {
-
-class PLATFORM_EXPORT RealTimeDomain : public TimeDomain {
- public:
- RealTimeDomain();
- ~RealTimeDomain() override;
-
- // TimeDomain implementation:
- LazyNow CreateLazyNow() const override;
- TimeTicks Now() const override;
- Optional<TimeDelta> DelayTillNextTask(LazyNow* lazy_now) override;
- const char* GetName() const override;
-
- protected:
- void OnRegisterWithTaskQueueManager(
- TaskQueueManagerImpl* task_queue_manager) override;
- void RequestWakeUpAt(TimeTicks now, TimeTicks run_time) override;
- void CancelWakeUpAt(TimeTicks run_time) override;
- void AsValueIntoInternal(trace_event::TracedValue* state) const override;
-
- private:
- TaskQueueManagerImpl* task_queue_manager_; // NOT OWNED
-
- DISALLOW_COPY_AND_ASSIGN(RealTimeDomain);
-};
-
-} // namespace sequence_manager
-} // namespace base
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_REAL_TIME_DOMAIN_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer.cc
new file mode 100644
index 00000000000..4c50375e643
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer.cc
@@ -0,0 +1,24 @@
+#include <stdlib.h>
+#include <iostream>
+
+#include "testing/libfuzzer/proto/lpm_interface.h"
+#include "third_party/blink/renderer/platform/scheduler/base/proto/sequence_manager_test_description.pb.h"
+#include "third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer_processor.h"
+
+// Tests some APIs in base::sequence_manager::SequenceManager (ones defined in
+// SequenceManagerTesrDescription proto) for crashes, hangs, memory leaks,
+// etc ... by running randomly generated tests, and exposing problematic corner
+// cases. For more details, check out go/libfuzzer-chromium.
+DEFINE_BINARY_PROTO_FUZZER(
+ const base::sequence_manager::SequenceManagerTestDescription&
+ fuzzer_input) {
+ // Dump code for debugging.
+ // TODO(farahcharab): Add code so that output looks more like the native
+ // function call.
+ if (getenv("LPM_DUMP_NATIVE_INPUT")) {
+ std::cout << fuzzer_input.DebugString() << std::endl;
+ }
+
+ base::sequence_manager::SequenceManagerFuzzerProcessor::ParseAndRun(
+ fuzzer_input);
+}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer_processor.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer_processor.cc
new file mode 100644
index 00000000000..fc78acb2ba6
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer_processor.cc
@@ -0,0 +1,170 @@
+#include "third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer_processor.h"
+
+#include <algorithm>
+#include <string>
+
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/test/test_mock_time_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+
+namespace base {
+namespace sequence_manager {
+
+void SequenceManagerFuzzerProcessor::ParseAndRun(
+ const SequenceManagerTestDescription& description) {
+ SequenceManagerFuzzerProcessor processor;
+ processor.RunTest(description);
+}
+
+SequenceManagerFuzzerProcessor::SequenceManagerFuzzerProcessor()
+ : SequenceManagerFuzzerProcessor(false) {}
+
+SequenceManagerFuzzerProcessor::SequenceManagerFuzzerProcessor(
+ bool log_for_testing)
+ : log_for_testing_(log_for_testing) {
+ test_task_runner_ = WrapRefCounted(
+ new TestMockTimeTaskRunner(TestMockTimeTaskRunner::Type::kBoundToThread));
+
+ // A zero clock triggers some assertions.
+ test_task_runner_->AdvanceMockTickClock(TimeDelta::FromMilliseconds(1));
+
+ initial_time_ = test_task_runner_->GetMockTickClock()->NowTicks();
+
+ manager_ =
+ SequenceManagerForTest::Create(nullptr, ThreadTaskRunnerHandle::Get(),
+ test_task_runner_->GetMockTickClock());
+
+ TaskQueue::Spec spec = TaskQueue::Spec("default_task_queue");
+ task_queues_.push_back(manager_->CreateTaskQueue<TestTaskQueue>(spec));
+}
+
+void SequenceManagerFuzzerProcessor::RunTest(
+ const SequenceManagerTestDescription& description) {
+ for (const auto& initial_action : description.initial_actions()) {
+ RunAction(initial_action);
+ }
+
+ test_task_runner_->FastForwardUntilNoTasksRemain();
+}
+
+void SequenceManagerFuzzerProcessor::RunAction(
+ const SequenceManagerTestDescription::Action& action) {
+ if (action.has_create_task_queue()) {
+ return CreateTaskQueueFromAction(action.action_id(),
+ action.create_task_queue());
+ }
+
+ return PostDelayedTaskFromAction(action.action_id(),
+ action.post_delayed_task());
+}
+
+void SequenceManagerFuzzerProcessor::PostDelayedTaskFromAction(
+ uint64_t action_id,
+ const SequenceManagerTestDescription::PostDelayedTaskAction& action) {
+ DCHECK(!task_queues_.empty());
+
+ LogActionForTesting(action_id, ActionForTest::ActionType::kPostDelayedTask,
+ test_task_runner_->GetMockTickClock()->NowTicks());
+
+ size_t index = action.task_queue_id() % task_queues_.size();
+ TestTaskQueue* chosen_task_queue = task_queues_[index].get();
+
+ // TODO(farahcharab) After adding non-nestable/nestable tasks, fix this to
+ // PostNonnestableDelayedTask for the former and PostDelayedTask for the
+ // latter.
+ chosen_task_queue->PostDelayedTask(
+ FROM_HERE,
+ BindOnce(&SequenceManagerFuzzerProcessor::ExecuteTask, Unretained(this),
+ action.task()),
+ TimeDelta::FromMilliseconds(action.delay_ms()));
+}
+
+void SequenceManagerFuzzerProcessor::CreateTaskQueueFromAction(
+ uint64_t action_id,
+ const SequenceManagerTestDescription::CreateTaskQueueAction& action) {
+ LogActionForTesting(action_id, ActionForTest::ActionType::kCreateTaskQueue,
+ test_task_runner_->GetMockTickClock()->NowTicks());
+
+ TaskQueue::Spec spec = TaskQueue::Spec("test_task_queue");
+ task_queues_.push_back(manager_->CreateTaskQueue<TestTaskQueue>(spec));
+}
+
+void SequenceManagerFuzzerProcessor::ExecuteTask(
+ const SequenceManagerTestDescription::Task& task) {
+ TimeTicks start_time = test_task_runner_->GetMockTickClock()->NowTicks();
+
+ // We can limit the depth of the nested post delayed action when processing
+ // the proto.
+ for (const auto& task_action : task.action()) {
+ // TODO(farahcharab) Add run loop to deal with nested tasks later. So far,
+ // we are assuming tasks are non-nestable.
+ RunAction(task_action);
+ }
+
+ TimeTicks end_time = test_task_runner_->GetMockTickClock()->NowTicks();
+
+ test_task_runner_->AdvanceMockTickClock(
+ TimeDelta::FromMilliseconds(task.duration_ms()) -
+ (end_time - start_time));
+
+ LogTaskForTesting(task.task_id(), start_time,
+ test_task_runner_->GetMockTickClock()->NowTicks());
+}
+
+void SequenceManagerFuzzerProcessor::LogTaskForTesting(uint64_t task_id,
+ TimeTicks start_time,
+ TimeTicks end_time) {
+ if (!log_for_testing_)
+ return;
+
+ uint64_t start_time_ms = (start_time - initial_time_).InMilliseconds();
+ uint64_t end_time_ms = (end_time - initial_time_).InMilliseconds();
+
+ ordered_tasks_.emplace_back(task_id, start_time_ms, end_time_ms);
+}
+
+void SequenceManagerFuzzerProcessor::LogActionForTesting(
+ uint64_t action_id,
+ ActionForTest::ActionType type,
+ TimeTicks start_time) {
+ if (!log_for_testing_)
+ return;
+
+ ordered_actions_.emplace_back(action_id, type,
+ (start_time - initial_time_).InMilliseconds());
+}
+
+const std::vector<SequenceManagerFuzzerProcessor::TaskForTest>&
+SequenceManagerFuzzerProcessor::ordered_tasks() const {
+ return ordered_tasks_;
+}
+
+const std::vector<SequenceManagerFuzzerProcessor::ActionForTest>&
+SequenceManagerFuzzerProcessor::ordered_actions() const {
+ return ordered_actions_;
+}
+
+SequenceManagerFuzzerProcessor::TaskForTest::TaskForTest(uint64_t id,
+ uint64_t start,
+ uint64_t end)
+ : task_id(id), start_time_ms(start), end_time_ms(end) {}
+
+bool SequenceManagerFuzzerProcessor::TaskForTest::operator==(
+ const TaskForTest& rhs) const {
+ return task_id == rhs.task_id && start_time_ms == rhs.start_time_ms &&
+ end_time_ms == rhs.end_time_ms;
+}
+
+SequenceManagerFuzzerProcessor::ActionForTest::ActionForTest(uint64_t id,
+ ActionType type,
+ uint64_t start)
+ : action_id(id), action_type(type), start_time_ms(start) {}
+
+bool SequenceManagerFuzzerProcessor::ActionForTest::operator==(
+ const ActionForTest& rhs) const {
+ return action_id == rhs.action_id && action_type == rhs.action_type &&
+ start_time_ms == rhs.start_time_ms;
+}
+
+} // namespace sequence_manager
+} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer_processor.h b/chromium/third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer_processor.h
new file mode 100644
index 00000000000..07140f8d652
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer_processor.h
@@ -0,0 +1,102 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_SEQUENCE_MANAGER_FUZZER_PROCESSOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_SEQUENCE_MANAGER_FUZZER_PROCESSOR_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/task/sequence_manager/test/test_task_queue.h"
+#include "base/test/test_mock_time_task_runner.h"
+#include "base/time/time.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/scheduler/base/proto/sequence_manager_test_description.pb.h"
+
+namespace base {
+namespace sequence_manager {
+
+// Provides functionality to parse the fuzzer's test description and run the
+// relevant APIs.
+class PLATFORM_EXPORT SequenceManagerFuzzerProcessor {
+ public:
+ // Public interface used to parse the fuzzer's test description and
+ // run the relevant APIs.
+ static void ParseAndRun(const SequenceManagerTestDescription& description);
+
+ protected:
+ struct TaskForTest {
+ TaskForTest(uint64_t id, uint64_t start, uint64_t end);
+ bool operator==(const TaskForTest& rhs) const;
+
+ uint64_t task_id;
+ uint64_t start_time_ms;
+ uint64_t end_time_ms;
+ };
+
+ struct ActionForTest {
+ enum class ActionType { kCreateTaskQueue, kPostDelayedTask };
+
+ ActionForTest(uint64_t id, ActionType type, uint64_t start);
+ bool operator==(const ActionForTest& rhs) const;
+
+ uint64_t action_id;
+ ActionType action_type;
+ uint64_t start_time_ms;
+ };
+
+ SequenceManagerFuzzerProcessor();
+
+ explicit SequenceManagerFuzzerProcessor(bool log_for_testing);
+
+ void RunTest(const SequenceManagerTestDescription& description);
+
+ void RunAction(const SequenceManagerTestDescription::Action& action);
+
+ const std::vector<TaskForTest>& ordered_tasks() const;
+ const std::vector<ActionForTest>& ordered_actions() const;
+
+ private:
+ void CreateTaskQueueFromAction(
+ uint64_t action_id,
+ const SequenceManagerTestDescription::CreateTaskQueueAction& action);
+
+ void PostDelayedTaskFromAction(
+ uint64_t action_id,
+ const SequenceManagerTestDescription::PostDelayedTaskAction& action);
+
+ void ExecuteTask(const SequenceManagerTestDescription::Task& task);
+
+ void LogTaskForTesting(uint64_t task_id,
+ TimeTicks start_time,
+ TimeTicks end_time);
+
+ void LogActionForTesting(uint64_t action_id,
+ ActionForTest::ActionType type,
+ TimeTicks start_time);
+
+ std::unique_ptr<SequenceManagerForTest> manager_;
+
+ // Bound to current thread. Used to control the clock of the task queue
+ // manager.
+ scoped_refptr<TestMockTimeTaskRunner> test_task_runner_;
+
+ std::vector<scoped_refptr<TestTaskQueue>> task_queues_;
+
+ const bool log_for_testing_;
+
+ TimeTicks initial_time_;
+
+ // For Testing. Used to log tasks in their order of execution.
+ std::vector<TaskForTest> ordered_tasks_;
+
+ // For Testing. Used to log actions in their order of execution.
+ std::vector<ActionForTest> ordered_actions_;
+};
+
+} // namespace sequence_manager
+} // namespace base
+
+#endif
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer_processor_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer_processor_unittest.cc
new file mode 100644
index 00000000000..00aed913222
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer_processor_unittest.cc
@@ -0,0 +1,347 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/base/sequence_manager_fuzzer_processor.h"
+
+#include <memory>
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/scheduler/base/proto/sequence_manager_test_description.pb.h"
+#include "third_party/protobuf/src/google/protobuf/text_format.h"
+#include "third_party/protobuf/src/google/protobuf/util/message_differencer.h"
+
+namespace base {
+namespace sequence_manager {
+
+using testing::ContainerEq;
+
+class SequenceManagerFuzzerProcessorForTest
+ : public SequenceManagerFuzzerProcessor {
+ public:
+ SequenceManagerFuzzerProcessorForTest()
+ : SequenceManagerFuzzerProcessor(true) {}
+
+ static void ParseAndRun(std::string test_description,
+ std::vector<TaskForTest>* executed_tasks,
+ std::vector<ActionForTest>* executed_actions) {
+ SequenceManagerTestDescription proto_description;
+ google::protobuf::TextFormat::ParseFromString(test_description,
+ &proto_description);
+
+ SequenceManagerFuzzerProcessorForTest processor;
+ processor.RunTest(proto_description);
+
+ if (executed_tasks)
+ *executed_tasks = processor.ordered_tasks();
+ if (executed_actions)
+ *executed_actions = processor.ordered_actions();
+ }
+
+ using SequenceManagerFuzzerProcessor::ordered_actions;
+ using SequenceManagerFuzzerProcessor::ordered_tasks;
+
+ using SequenceManagerFuzzerProcessor::ActionForTest;
+ using SequenceManagerFuzzerProcessor::TaskForTest;
+};
+
+using ActionForTest = SequenceManagerFuzzerProcessorForTest::ActionForTest;
+using TaskForTest = SequenceManagerFuzzerProcessorForTest::TaskForTest;
+
+TEST(SequenceManagerFuzzerProcessorTest, CreateTaskQueue) {
+ std::vector<ActionForTest> executed_actions;
+ SequenceManagerFuzzerProcessorForTest::ParseAndRun(R"(
+ initial_actions {
+ action_id : 1
+ create_task_queue {
+ }
+ })",
+ nullptr,
+ &executed_actions);
+
+ std::vector<ActionForTest> expected_actions;
+ expected_actions.emplace_back(1, ActionForTest::ActionType::kCreateTaskQueue,
+ 0);
+
+ EXPECT_THAT(executed_actions, ContainerEq(expected_actions));
+}
+
+TEST(SequenceManagerFuzzerProcessorTest, PostDelayedTaskWithDuration) {
+ std::vector<TaskForTest> executed_tasks;
+ std::vector<ActionForTest> executed_actions;
+
+ // Posts an 10 ms delayed task of duration 20 ms.
+ SequenceManagerFuzzerProcessorForTest::ParseAndRun(R"(
+ initial_actions {
+ action_id : 1
+ post_delayed_task {
+ task_queue_id : 1
+ delay_ms : 10
+ task {
+ task_id : 1
+ duration_ms : 20
+ }
+ }
+ })",
+ &executed_tasks,
+ &executed_actions);
+
+ std::vector<TaskForTest> expected_tasks;
+ expected_tasks.emplace_back(1, 10, 30);
+ EXPECT_THAT(executed_tasks, ContainerEq(expected_tasks));
+
+ std::vector<ActionForTest> expected_actions;
+ expected_actions.emplace_back(1, ActionForTest::ActionType::kPostDelayedTask,
+ 0);
+ EXPECT_THAT(executed_actions, ContainerEq(expected_actions));
+}
+
+TEST(SequenceManagerFuzzerProcessorTest,
+ TaskDurationBlocksOtherPendingTasksPostedFromOutsideOfTask) {
+ std::vector<TaskForTest> executed_tasks;
+ std::vector<ActionForTest> executed_actions;
+
+ // Posts a task of duration 40 ms and a 10 ms delayed task of duration 20 ms.
+ SequenceManagerFuzzerProcessorForTest::ParseAndRun(R"(
+ initial_actions {
+ action_id : 1
+ post_delayed_task {
+ delay_ms : 10
+ task {
+ task_id : 1
+ duration_ms : 20
+ }
+ }
+ }
+ initial_actions {
+ action_id :2
+ post_delayed_task {
+ delay_ms : 0
+ task {
+ task_id : 2
+ duration_ms : 40
+ }
+ }
+ })",
+ &executed_tasks,
+ &executed_actions);
+
+ // Task with id 2 is expected to run first and block the other task until it
+ // done.
+ std::vector<TaskForTest> expected_tasks;
+ expected_tasks.emplace_back(2, 0, 40);
+ expected_tasks.emplace_back(1, 40, 60);
+ EXPECT_THAT(executed_tasks, ContainerEq(expected_tasks));
+
+ std::vector<ActionForTest> expected_actions;
+ expected_actions.emplace_back(1, ActionForTest::ActionType::kPostDelayedTask,
+ 0);
+ expected_actions.emplace_back(2, ActionForTest::ActionType::kPostDelayedTask,
+ 0);
+ EXPECT_THAT(executed_actions, ContainerEq(expected_actions));
+}
+
+TEST(SequenceManagerFuzzerProcessorTest,
+ TaskDurationBlocksOtherNonNestableTaskWhenPostedFromTheWithinTask) {
+ // Posts an instant task of duration 40 ms that posts another non-nested
+ // instant task.
+ std::vector<TaskForTest> executed_tasks;
+ SequenceManagerFuzzerProcessorForTest::ParseAndRun(R"(
+ initial_actions {
+ post_delayed_task {
+ task {
+ task_id : 1
+ duration_ms : 40
+ action {
+ post_delayed_task {
+ task {
+ task_id : 2
+ }
+ }
+ }
+ }
+ }
+ })",
+ &executed_tasks, nullptr);
+
+ // Task with task id 1 is expected to run for 40 ms, and block the other
+ // posted task from running until its done. Note that the task with id 2 is
+ // blocked since it is non-nested, so it is not supposed to run from within
+ // the posting task.
+ std::vector<TaskForTest> expected_tasks;
+ expected_tasks.emplace_back(1, 0, 40);
+ expected_tasks.emplace_back(2, 40, 40);
+
+ EXPECT_THAT(executed_tasks, ContainerEq(expected_tasks));
+}
+
+TEST(SequenceManagerFuzzerProcessorTest, PostNonEmptyTask) {
+ // Posts a 5 ms delayed task of duration 40 ms that creates a task queue,
+ // posts a 4 ms delayed task, posts an instant task, creates a task queue,
+ // and then posts a 40 ms delayed task.
+ std::vector<TaskForTest> executed_tasks;
+ std::vector<ActionForTest> executed_actions;
+
+ SequenceManagerFuzzerProcessorForTest::ParseAndRun(R"(
+ initial_actions {
+ action_id : 1
+ post_delayed_task {
+ delay_ms: 5
+ task {
+ task_id : 1
+ duration_ms : 40
+ action {
+ action_id : 2
+ create_task_queue {
+ }
+ }
+ action {
+ action_id : 3
+ post_delayed_task {
+ delay_ms : 4
+ task {
+ task_id : 2
+ }
+ }
+ }
+ action {
+ action_id: 4
+ post_delayed_task {
+ task {
+ task_id : 3
+ }
+ }
+ }
+ action {
+ action_id : 5
+ create_task_queue {
+ }
+ }
+ action {
+ action_id : 6
+ post_delayed_task {
+ delay_ms : 40
+ task {
+ task_id : 4
+ }
+ }
+ }
+ }
+ }
+ })",
+ &executed_tasks,
+ &executed_actions);
+
+ // Task with task id 1 is expected to run first, and block all other pending
+ // tasks until its done. The remaining tasks will be executed in
+ // non-decreasing order of the delay parameter with ties broken by
+ // the post order.
+ std::vector<TaskForTest> expected_tasks;
+ expected_tasks.emplace_back(1, 5, 45);
+ expected_tasks.emplace_back(3, 45, 45);
+ expected_tasks.emplace_back(2, 45, 45);
+ expected_tasks.emplace_back(4, 45, 45);
+ EXPECT_THAT(executed_tasks, ContainerEq(expected_tasks));
+
+ std::vector<ActionForTest> expected_actions;
+ expected_actions.emplace_back(1, ActionForTest::ActionType::kPostDelayedTask,
+ 0);
+ expected_actions.emplace_back(2, ActionForTest::ActionType::kCreateTaskQueue,
+ 5);
+ expected_actions.emplace_back(3, ActionForTest::ActionType::kPostDelayedTask,
+ 5);
+ expected_actions.emplace_back(4, ActionForTest::ActionType::kPostDelayedTask,
+ 5);
+ expected_actions.emplace_back(5, ActionForTest::ActionType::kCreateTaskQueue,
+ 5);
+ expected_actions.emplace_back(6, ActionForTest::ActionType::kPostDelayedTask,
+ 5);
+ EXPECT_THAT(executed_actions, ContainerEq(expected_actions));
+}
+
+TEST(SequenceManagerFuzzerProcessorTest, OrderOfSimpleUnnestedExecutedActions) {
+ // Creates a task queue, creates a task queue after 10 ms of delay, posts a
+ // task after 20 ms delay, posts a 10 ms duration task after 15 ms of delay,
+ // and posts a task after 100 ms of delay.
+ std::vector<TaskForTest> executed_tasks;
+ std::vector<ActionForTest> executed_actions;
+ SequenceManagerFuzzerProcessorForTest::ParseAndRun(R"(
+ initial_actions {
+ action_id : 1
+ create_task_queue {
+ }
+ }
+ initial_actions {
+ action_id : 2
+ post_delayed_task {
+ delay_ms : 10
+ task {
+ task_id : 1
+ action {
+ action_id : 3
+ create_task_queue {
+ }
+ }
+ }
+ }
+ }
+ initial_actions {
+ action_id : 4
+ post_delayed_task {
+ delay_ms : 20
+ task {
+ task_id : 2
+ }
+ }
+ }
+ initial_actions {
+ action_id : 5
+ post_delayed_task {
+ delay_ms : 15
+ task {
+ task_id : 3
+ duration_ms : 10
+ }
+ }
+ }
+ initial_actions {
+ action_id : 6
+ post_delayed_task {
+ delay_ms : 100
+ task {
+ task_id : 4
+ }
+ }
+ })",
+ &executed_tasks,
+ &executed_actions);
+
+ // Tasks are expected to run in order of non-decreasing delay with ties broken
+ // by order of posting. Note that the task with id 3 will block the task with
+ // id 2 from running at its scheduled time.
+ std::vector<TaskForTest> expected_tasks;
+ expected_tasks.emplace_back(1, 10, 10);
+ expected_tasks.emplace_back(3, 15, 25);
+ expected_tasks.emplace_back(2, 25, 25);
+ expected_tasks.emplace_back(4, 100, 100);
+ EXPECT_THAT(executed_tasks, ContainerEq(expected_tasks));
+
+ std::vector<ActionForTest> expected_actions;
+ expected_actions.emplace_back(1, ActionForTest::ActionType::kCreateTaskQueue,
+ 0);
+ expected_actions.emplace_back(2, ActionForTest::ActionType::kPostDelayedTask,
+ 0);
+ expected_actions.emplace_back(4, ActionForTest::ActionType::kPostDelayedTask,
+ 0);
+ expected_actions.emplace_back(5, ActionForTest::ActionType::kPostDelayedTask,
+ 0);
+ expected_actions.emplace_back(6, ActionForTest::ActionType::kPostDelayedTask,
+ 0);
+ expected_actions.emplace_back(3, ActionForTest::ActionType::kCreateTaskQueue,
+ 10);
+ EXPECT_THAT(executed_actions, ContainerEq(expected_actions));
+}
+
+} // namespace sequence_manager
+} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue.cc
deleted file mode 100644
index 2f450e4cd54..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue.cc
+++ /dev/null
@@ -1,273 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
-
-#include "base/bind_helpers.h"
-#include "base/optional.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl.h"
-
-namespace base {
-namespace sequence_manager {
-
-TaskQueue::TaskQueue(std::unique_ptr<internal::TaskQueueImpl> impl,
- const TaskQueue::Spec& spec)
- : impl_(std::move(impl)),
- thread_id_(PlatformThread::CurrentId()),
- task_queue_manager_(impl_ ? impl_->GetTaskQueueManagerWeakPtr()
- : nullptr),
- graceful_queue_shutdown_helper_(
- impl_ ? impl_->GetGracefulQueueShutdownHelper() : nullptr) {}
-
-TaskQueue::~TaskQueue() {
- // scoped_refptr guarantees us that this object isn't used.
- if (!impl_)
- return;
- if (impl_->IsUnregistered())
- return;
- graceful_queue_shutdown_helper_->GracefullyShutdownTaskQueue(
- TakeTaskQueueImpl());
-}
-
-TaskQueue::Task::Task(TaskQueue::PostedTask task, TimeTicks desired_run_time)
- : PendingTask(task.posted_from,
- std::move(task.callback),
- desired_run_time,
- task.nestable),
- task_type_(task.task_type) {}
-
-TaskQueue::PostedTask::PostedTask(OnceClosure callback,
- Location posted_from,
- TimeDelta delay,
- Nestable nestable,
- int task_type)
- : callback(std::move(callback)),
- posted_from(posted_from),
- delay(delay),
- nestable(nestable),
- task_type(task_type) {}
-
-TaskQueue::PostedTask::PostedTask(PostedTask&& move_from)
- : callback(std::move(move_from.callback)),
- posted_from(move_from.posted_from),
- delay(move_from.delay),
- nestable(move_from.nestable),
- task_type(move_from.task_type) {}
-
-TaskQueue::PostedTask::~PostedTask() = default;
-
-void TaskQueue::ShutdownTaskQueue() {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- AutoLock lock(impl_lock_);
- if (!impl_)
- return;
- if (!task_queue_manager_) {
- impl_.reset();
- return;
- }
- impl_->SetBlameContext(nullptr);
- impl_->SetOnTaskStartedHandler(
- internal::TaskQueueImpl::OnTaskStartedHandler());
- impl_->SetOnTaskCompletedHandler(
- internal::TaskQueueImpl::OnTaskCompletedHandler());
- task_queue_manager_->UnregisterTaskQueueImpl(TakeTaskQueueImpl());
-}
-
-bool TaskQueue::RunsTasksInCurrentSequence() const {
- return IsOnMainThread();
-}
-
-bool TaskQueue::PostDelayedTask(const Location& from_here,
- OnceClosure task,
- TimeDelta delay) {
- return PostTaskWithMetadata(
- PostedTask(std::move(task), from_here, delay, Nestable::kNestable));
-}
-
-bool TaskQueue::PostNonNestableDelayedTask(const Location& from_here,
- OnceClosure task,
- TimeDelta delay) {
- return PostTaskWithMetadata(
- PostedTask(std::move(task), from_here, delay, Nestable::kNonNestable));
-}
-
-bool TaskQueue::PostTaskWithMetadata(PostedTask task) {
- Optional<MoveableAutoLock> lock = AcquireImplReadLockIfNeeded();
- if (!impl_)
- return false;
- internal::TaskQueueImpl::PostTaskResult result(
- impl_->PostDelayedTask(std::move(task)));
- if (result.success)
- return true;
- // If posting task was unsuccessful then |result| will contain
- // the original task which should be destructed outside of the lock.
- lock = nullopt;
- // Task gets implicitly destructed here.
- return false;
-}
-
-std::unique_ptr<TaskQueue::QueueEnabledVoter>
-TaskQueue::CreateQueueEnabledVoter() {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- if (!impl_)
- return nullptr;
- return impl_->CreateQueueEnabledVoter(this);
-}
-
-bool TaskQueue::IsQueueEnabled() const {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- if (!impl_)
- return false;
- return impl_->IsQueueEnabled();
-}
-
-bool TaskQueue::IsEmpty() const {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- if (!impl_)
- return true;
- return impl_->IsEmpty();
-}
-
-size_t TaskQueue::GetNumberOfPendingTasks() const {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- if (!impl_)
- return 0;
- return impl_->GetNumberOfPendingTasks();
-}
-
-bool TaskQueue::HasTaskToRunImmediately() const {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- if (!impl_)
- return false;
- return impl_->HasTaskToRunImmediately();
-}
-
-Optional<TimeTicks> TaskQueue::GetNextScheduledWakeUp() {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- if (!impl_)
- return nullopt;
- return impl_->GetNextScheduledWakeUp();
-}
-
-void TaskQueue::SetQueuePriority(TaskQueue::QueuePriority priority) {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- if (!impl_)
- return;
- impl_->SetQueuePriority(priority);
-}
-
-TaskQueue::QueuePriority TaskQueue::GetQueuePriority() const {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- if (!impl_)
- return TaskQueue::QueuePriority::kLowPriority;
- return impl_->GetQueuePriority();
-}
-
-void TaskQueue::AddTaskObserver(MessageLoop::TaskObserver* task_observer) {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- if (!impl_)
- return;
- impl_->AddTaskObserver(task_observer);
-}
-
-void TaskQueue::RemoveTaskObserver(MessageLoop::TaskObserver* task_observer) {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- if (!impl_)
- return;
- impl_->RemoveTaskObserver(task_observer);
-}
-
-void TaskQueue::SetTimeDomain(TimeDomain* time_domain) {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- if (!impl_)
- return;
- impl_->SetTimeDomain(time_domain);
-}
-
-TimeDomain* TaskQueue::GetTimeDomain() const {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- if (!impl_)
- return nullptr;
- return impl_->GetTimeDomain();
-}
-
-void TaskQueue::SetBlameContext(trace_event::BlameContext* blame_context) {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- if (!impl_)
- return;
- impl_->SetBlameContext(blame_context);
-}
-
-void TaskQueue::InsertFence(InsertFencePosition position) {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- if (!impl_)
- return;
- impl_->InsertFence(position);
-}
-
-void TaskQueue::InsertFenceAt(TimeTicks time) {
- impl_->InsertFenceAt(time);
-}
-
-void TaskQueue::RemoveFence() {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- if (!impl_)
- return;
- impl_->RemoveFence();
-}
-
-bool TaskQueue::HasActiveFence() {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- if (!impl_)
- return false;
- return impl_->HasActiveFence();
-}
-
-bool TaskQueue::BlockedByFence() const {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- if (!impl_)
- return false;
- return impl_->BlockedByFence();
-}
-
-const char* TaskQueue::GetName() const {
- auto lock = AcquireImplReadLockIfNeeded();
- if (!impl_)
- return "";
- return impl_->GetName();
-}
-
-void TaskQueue::SetObserver(Observer* observer) {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- if (!impl_)
- return;
- if (observer) {
- // Observer is guaranteed to outlive TaskQueue and TaskQueueImpl lifecycle
- // is controlled by |this|.
- impl_->SetOnNextWakeUpChangedCallback(
- BindRepeating(&TaskQueue::Observer::OnQueueNextWakeUpChanged,
- Unretained(observer), Unretained(this)));
- } else {
- impl_->SetOnNextWakeUpChangedCallback(RepeatingCallback<void(TimeTicks)>());
- }
-}
-
-bool TaskQueue::IsOnMainThread() const {
- return thread_id_ == PlatformThread::CurrentId();
-}
-
-Optional<MoveableAutoLock> TaskQueue::AcquireImplReadLockIfNeeded() const {
- if (IsOnMainThread())
- return nullopt;
- return MoveableAutoLock(impl_lock_);
-}
-
-std::unique_ptr<internal::TaskQueueImpl> TaskQueue::TakeTaskQueueImpl() {
- DCHECK(impl_);
- return std::move(impl_);
-}
-
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue.h b/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue.h
deleted file mode 100644
index 187a9c15af3..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue.h
+++ /dev/null
@@ -1,307 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_H_
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/optional.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/graceful_queue_shutdown_helper.h"
-#include "third_party/blink/renderer/platform/scheduler/base/moveable_auto_lock.h"
-
-namespace base {
-namespace trace_event {
-class BlameContext;
-}
-} // namespace base
-
-namespace base {
-namespace sequence_manager {
-
-namespace internal {
-class TaskQueueImpl;
-}
-
-class TimeDomain;
-class TaskQueueManagerImpl;
-
-class PLATFORM_EXPORT TaskQueue : public SingleThreadTaskRunner {
- public:
- class PLATFORM_EXPORT Observer {
- public:
- virtual ~Observer() = default;
-
- // Notify observer that the time at which this queue wants to run
- // the next task has changed. |next_wakeup| can be in the past
- // (e.g. TimeTicks() can be used to notify about immediate work).
- // Can be called on any thread
- // All methods but SetObserver, SetTimeDomain and GetTimeDomain can be
- // called on |queue|.
- //
- // TODO(altimin): Make it Optional<TimeTicks> to tell
- // observer about cancellations.
- virtual void OnQueueNextWakeUpChanged(TaskQueue* queue,
- TimeTicks next_wake_up) = 0;
- };
-
- // A wrapper around OnceClosure with additional metadata to be passed
- // to PostTask and plumbed until PendingTask is created.
- struct PLATFORM_EXPORT PostedTask {
- PostedTask(OnceClosure callback,
- Location posted_from,
- TimeDelta delay = TimeDelta(),
- Nestable nestable = Nestable::kNestable,
- int task_type = 0);
- PostedTask(PostedTask&& move_from);
- PostedTask(const PostedTask& copy_from) = delete;
- ~PostedTask();
-
- OnceClosure callback;
- Location posted_from;
- TimeDelta delay;
- Nestable nestable;
- int task_type;
- };
-
- // Unregisters the task queue after which no tasks posted to it will run and
- // the TaskQueueManagerImpl's reference to it will be released soon.
- virtual void ShutdownTaskQueue();
-
- enum QueuePriority {
- // Queues with control priority will run before any other queue, and will
- // explicitly starve other queues. Typically this should only be used for
- // private queues which perform control operations.
- kControlPriority,
-
- // The selector will prioritize highest over high, normal and low; and
- // high over normal and low; and normal over low. However it will ensure
- // neither of the lower priority queues can be completely starved by higher
- // priority tasks. All three of these queues will always take priority over
- // and can starve the best effort queue.
- kHighestPriority,
-
- kHighPriority,
-
- // Queues with normal priority are the default.
- kNormalPriority,
- kLowPriority,
-
- // Queues with best effort priority will only be run if all other queues are
- // empty. They can be starved by the other queues.
- kBestEffortPriority,
- // Must be the last entry.
- kQueuePriorityCount,
- kFirstQueuePriority = kControlPriority,
- };
-
- // Can be called on any thread.
- static const char* PriorityToString(QueuePriority priority);
-
- // Options for constructing a TaskQueue.
- struct Spec {
- explicit Spec(const char* name)
- : name(name),
- should_monitor_quiescence(false),
- time_domain(nullptr),
- should_notify_observers(true) {}
-
- Spec SetShouldMonitorQuiescence(bool should_monitor) {
- should_monitor_quiescence = should_monitor;
- return *this;
- }
-
- Spec SetShouldNotifyObservers(bool run_observers) {
- should_notify_observers = run_observers;
- return *this;
- }
-
- Spec SetTimeDomain(TimeDomain* domain) {
- time_domain = domain;
- return *this;
- }
-
- const char* name;
- bool should_monitor_quiescence;
- TimeDomain* time_domain;
- bool should_notify_observers;
- };
-
- // Interface to pass per-task metadata to RendererScheduler.
- class PLATFORM_EXPORT Task : public PendingTask {
- public:
- Task(PostedTask posted_task, TimeTicks desired_run_time);
-
- int task_type() const { return task_type_; }
-
- private:
- int task_type_;
- };
-
- // An interface that lets the owner vote on whether or not the associated
- // TaskQueue should be enabled.
- class QueueEnabledVoter {
- public:
- QueueEnabledVoter() = default;
- virtual ~QueueEnabledVoter() = default;
-
- // Votes to enable or disable the associated TaskQueue. The TaskQueue will
- // only be enabled if all the voters agree it should be enabled, or if there
- // are no voters.
- // NOTE this must be called on the thread the associated TaskQueue was
- // created on.
- virtual void SetQueueEnabled(bool enabled) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(QueueEnabledVoter);
- };
-
- // Returns an interface that allows the caller to vote on whether or not this
- // TaskQueue is enabled. The TaskQueue will be enabled if there are no voters
- // or if all agree it should be enabled.
- // NOTE this must be called on the thread this TaskQueue was created by.
- std::unique_ptr<QueueEnabledVoter> CreateQueueEnabledVoter();
-
- // NOTE this must be called on the thread this TaskQueue was created by.
- bool IsQueueEnabled() const;
-
- // Returns true if the queue is completely empty.
- bool IsEmpty() const;
-
- // Returns the number of pending tasks in the queue.
- size_t GetNumberOfPendingTasks() const;
-
- // Returns true if the queue has work that's ready to execute now.
- // NOTE: this must be called on the thread this TaskQueue was created by.
- bool HasTaskToRunImmediately() const;
-
- // Returns requested run time of next scheduled wake-up for a delayed task
- // which is not ready to run. If there are no such tasks or the queue is
- // disabled (by a QueueEnabledVoter) it returns nullopt.
- // NOTE: this must be called on the thread this TaskQueue was created by.
- Optional<TimeTicks> GetNextScheduledWakeUp();
-
- // Can be called on any thread.
- virtual const char* GetName() const;
-
- // Set the priority of the queue to |priority|. NOTE this must be called on
- // the thread this TaskQueue was created by.
- void SetQueuePriority(QueuePriority priority);
-
- // Returns the current queue priority.
- QueuePriority GetQueuePriority() const;
-
- // These functions can only be called on the same thread that the task queue
- // manager executes its tasks on.
- void AddTaskObserver(MessageLoop::TaskObserver* task_observer);
- void RemoveTaskObserver(MessageLoop::TaskObserver* task_observer);
-
- // Set the blame context which is entered and left while executing tasks from
- // this task queue. |blame_context| must be null or outlive this task queue.
- // Must be called on the thread this TaskQueue was created by.
- void SetBlameContext(trace_event::BlameContext* blame_context);
-
- // Removes the task queue from the previous TimeDomain and adds it to
- // |domain|. This is a moderately expensive operation.
- void SetTimeDomain(TimeDomain* domain);
-
- // Returns the queue's current TimeDomain. Can be called from any thread.
- TimeDomain* GetTimeDomain() const;
-
- enum class InsertFencePosition {
- kNow, // Tasks posted on the queue up till this point further may run.
- // All further tasks are blocked.
- kBeginningOfTime, // No tasks posted on this queue may run.
- };
-
- // Inserts a barrier into the task queue which prevents tasks with an enqueue
- // order greater than the fence from running until either the fence has been
- // removed or a subsequent fence has unblocked some tasks within the queue.
- // Note: delayed tasks get their enqueue order set once their delay has
- // expired, and non-delayed tasks get their enqueue order set when posted.
- //
- // Fences come in three flavours:
- // - Regular (InsertFence(NOW)) - all tasks posted after this moment
- // are blocked.
- // - Fully blocking (InsertFence(kBeginningOfTime)) - all tasks including
- // already posted are blocked.
- // - Delayed (InsertFenceAt(timestamp)) - blocks all tasks posted after given
- // point in time (must be in the future).
- //
- // Only one fence can be scheduled at a time. Inserting a new fence
- // will automatically remove the previous one, regardless of fence type.
- void InsertFence(InsertFencePosition position);
- void InsertFenceAt(TimeTicks time);
-
- // Removes any previously added fence and unblocks execution of any tasks
- // blocked by it.
- void RemoveFence();
-
- bool HasActiveFence();
-
- // Returns true if the queue has a fence which is blocking execution of tasks.
- bool BlockedByFence() const;
-
- void SetObserver(Observer* observer);
-
- // SingleThreadTaskRunner implementation
- bool RunsTasksInCurrentSequence() const override;
- bool PostDelayedTask(const Location& from_here,
- OnceClosure task,
- TimeDelta delay) override;
- bool PostNonNestableDelayedTask(const Location& from_here,
- OnceClosure task,
- TimeDelta delay) override;
-
- bool PostTaskWithMetadata(PostedTask task);
-
- // TODO(kraynov): Make protected.
- internal::TaskQueueImpl* GetTaskQueueImpl() const { return impl_.get(); }
-
- protected:
- TaskQueue(std::unique_ptr<internal::TaskQueueImpl> impl,
- const TaskQueue::Spec& spec);
- ~TaskQueue() override;
-
- private:
- friend class internal::TaskQueueImpl;
- friend class TaskQueueManagerImpl;
-
- bool IsOnMainThread() const;
-
- Optional<MoveableAutoLock> AcquireImplReadLockIfNeeded() const;
-
- // Take |impl_| and untie it from the enclosing task queue.
- std::unique_ptr<internal::TaskQueueImpl> TakeTaskQueueImpl();
-
- // |impl_| can be written to on the main thread but can be read from
- // any thread.
- // |impl_lock_| must be acquired when writing to |impl_| or when accessing
- // it from non-main thread. Reading from the main thread does not require
- // a lock.
- mutable Lock impl_lock_;
- std::unique_ptr<internal::TaskQueueImpl> impl_;
-
- const PlatformThreadId thread_id_;
-
- const WeakPtr<TaskQueueManagerImpl> task_queue_manager_;
-
- const scoped_refptr<internal::GracefulQueueShutdownHelper>
- graceful_queue_shutdown_helper_;
-
- THREAD_CHECKER(main_thread_checker_);
-
- DISALLOW_COPY_AND_ASSIGN(TaskQueue);
-};
-
-} // namespace sequence_manager
-} // namespace base
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_impl.cc
deleted file mode 100644
index a3356141268..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_impl.cc
+++ /dev/null
@@ -1,1041 +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/platform/scheduler/base/task_queue_impl.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/strings/stringprintf.h"
-#include "base/time/time.h"
-#include "base/trace_event/blame_context.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/base/work_queue.h"
-
-namespace base {
-namespace sequence_manager {
-
-// static
-const char* TaskQueue::PriorityToString(TaskQueue::QueuePriority priority) {
- switch (priority) {
- case kControlPriority:
- return "control";
- case kHighestPriority:
- return "highest";
- case kHighPriority:
- return "high";
- case kNormalPriority:
- return "normal";
- case kLowPriority:
- return "low";
- case kBestEffortPriority:
- return "best_effort";
- default:
- NOTREACHED();
- return nullptr;
- }
-}
-
-namespace internal {
-
-TaskQueueImpl::TaskQueueImpl(TaskQueueManagerImpl* task_queue_manager,
- TimeDomain* time_domain,
- const TaskQueue::Spec& spec)
- : name_(spec.name),
- thread_id_(PlatformThread::CurrentId()),
- any_thread_(task_queue_manager, time_domain),
- main_thread_only_(task_queue_manager, this, time_domain),
- should_monitor_quiescence_(spec.should_monitor_quiescence),
- should_notify_observers_(spec.should_notify_observers) {
- DCHECK(time_domain);
- time_domain->RegisterQueue(this);
-}
-
-TaskQueueImpl::~TaskQueueImpl() {
-#if DCHECK_IS_ON()
- AutoLock lock(any_thread_lock_);
- // NOTE this check shouldn't fire because |TaskQueueManagerImpl::queues_|
- // contains a strong reference to this TaskQueueImpl and the
- // TaskQueueManagerImpl destructor calls UnregisterTaskQueue on all task
- // queues.
- DCHECK(!any_thread().task_queue_manager)
- << "UnregisterTaskQueue must be called first!";
-#endif
-}
-
-TaskQueueImpl::PostTaskResult::PostTaskResult()
- : success(false), task(OnceClosure(), Location()) {}
-
-TaskQueueImpl::PostTaskResult::PostTaskResult(bool success,
- TaskQueue::PostedTask task)
- : success(success), task(std::move(task)) {}
-
-TaskQueueImpl::PostTaskResult::PostTaskResult(PostTaskResult&& move_from)
- : success(move_from.success), task(std::move(move_from.task)) {}
-
-TaskQueueImpl::PostTaskResult::~PostTaskResult() = default;
-
-TaskQueueImpl::PostTaskResult TaskQueueImpl::PostTaskResult::Success() {
- return PostTaskResult(true, TaskQueue::PostedTask(OnceClosure(), Location()));
-}
-
-TaskQueueImpl::PostTaskResult TaskQueueImpl::PostTaskResult::Fail(
- TaskQueue::PostedTask task) {
- return PostTaskResult(false, std::move(task));
-}
-
-TaskQueueImpl::Task::Task(TaskQueue::PostedTask task,
- TimeTicks desired_run_time,
- EnqueueOrder sequence_number)
- : TaskQueue::Task(std::move(task), desired_run_time),
-#ifndef NDEBUG
- enqueue_order_set_(false),
-#endif
- enqueue_order_(0) {
- sequence_num = sequence_number;
-}
-
-TaskQueueImpl::Task::Task(TaskQueue::PostedTask task,
- TimeTicks desired_run_time,
- EnqueueOrder sequence_number,
- EnqueueOrder enqueue_order)
- : TaskQueue::Task(std::move(task), desired_run_time),
-#ifndef NDEBUG
- enqueue_order_set_(true),
-#endif
- enqueue_order_(enqueue_order) {
- sequence_num = sequence_number;
-}
-
-TaskQueueImpl::AnyThread::AnyThread(TaskQueueManagerImpl* task_queue_manager,
- TimeDomain* time_domain)
- : task_queue_manager(task_queue_manager), time_domain(time_domain) {}
-
-TaskQueueImpl::AnyThread::~AnyThread() = default;
-
-TaskQueueImpl::MainThreadOnly::MainThreadOnly(
- TaskQueueManagerImpl* task_queue_manager,
- TaskQueueImpl* task_queue,
- TimeDomain* time_domain)
- : task_queue_manager(task_queue_manager),
- time_domain(time_domain),
- delayed_work_queue(
- new WorkQueue(task_queue, "delayed", WorkQueue::QueueType::kDelayed)),
- immediate_work_queue(new WorkQueue(task_queue,
- "immediate",
- WorkQueue::QueueType::kImmediate)),
- set_index(0),
- is_enabled_refcount(0),
- voter_refcount(0),
- blame_context(nullptr),
- current_fence(0),
- is_enabled_for_test(true) {}
-
-TaskQueueImpl::MainThreadOnly::~MainThreadOnly() = default;
-
-void TaskQueueImpl::UnregisterTaskQueue() {
- TaskDeque immediate_incoming_queue;
-
- {
- AutoLock lock(any_thread_lock_);
- AutoLock immediate_incoming_queue_lock(immediate_incoming_queue_lock_);
-
- if (main_thread_only().time_domain)
- main_thread_only().time_domain->UnregisterQueue(this);
-
- if (!any_thread().task_queue_manager)
- return;
-
- main_thread_only().on_task_completed_handler = OnTaskCompletedHandler();
- any_thread().time_domain = nullptr;
- main_thread_only().time_domain = nullptr;
-
- any_thread().task_queue_manager = nullptr;
- main_thread_only().task_queue_manager = nullptr;
- any_thread().on_next_wake_up_changed_callback =
- OnNextWakeUpChangedCallback();
- main_thread_only().on_next_wake_up_changed_callback =
- OnNextWakeUpChangedCallback();
- immediate_incoming_queue.swap(immediate_incoming_queue_);
- }
-
- // It is possible for a task to hold a scoped_refptr to this, which
- // will lead to TaskQueueImpl destructor being called when deleting a task.
- // To avoid use-after-free, we need to clear all fields of a task queue
- // before starting to delete the tasks.
- // All work queues and priority queues containing tasks should be moved to
- // local variables on stack (std::move for unique_ptrs and swap for queues)
- // before clearing them and deleting tasks.
-
- // Flush the queues outside of the lock because TSAN complains about a lock
- // order inversion for tasks that are posted from within a lock, with a
- // destructor that acquires the same lock.
-
- std::priority_queue<Task> delayed_incoming_queue;
- delayed_incoming_queue.swap(main_thread_only().delayed_incoming_queue);
-
- std::unique_ptr<WorkQueue> immediate_work_queue =
- std::move(main_thread_only().immediate_work_queue);
- std::unique_ptr<WorkQueue> delayed_work_queue =
- std::move(main_thread_only().delayed_work_queue);
-}
-
-const char* TaskQueueImpl::GetName() const {
- return name_;
-}
-
-bool TaskQueueImpl::RunsTasksInCurrentSequence() const {
- return PlatformThread::CurrentId() == thread_id_;
-}
-
-TaskQueueImpl::PostTaskResult TaskQueueImpl::PostDelayedTask(
- TaskQueue::PostedTask task) {
- if (task.delay.is_zero())
- return PostImmediateTaskImpl(std::move(task));
-
- return PostDelayedTaskImpl(std::move(task));
-}
-
-TaskQueueImpl::PostTaskResult TaskQueueImpl::PostImmediateTaskImpl(
- TaskQueue::PostedTask task) {
- // Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167
- // for details.
- CHECK(task.callback);
- AutoLock lock(any_thread_lock_);
- if (!any_thread().task_queue_manager)
- return PostTaskResult::Fail(std::move(task));
-
- EnqueueOrder sequence_number =
- any_thread().task_queue_manager->GetNextSequenceNumber();
-
- PushOntoImmediateIncomingQueueLocked(Task(std::move(task),
- any_thread().time_domain->Now(),
- sequence_number, sequence_number));
- return PostTaskResult::Success();
-}
-
-TaskQueueImpl::PostTaskResult TaskQueueImpl::PostDelayedTaskImpl(
- TaskQueue::PostedTask task) {
- // Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167
- // for details.
- CHECK(task.callback);
- DCHECK_GT(task.delay, TimeDelta());
- if (PlatformThread::CurrentId() == thread_id_) {
- // Lock-free fast path for delayed tasks posted from the main thread.
- if (!main_thread_only().task_queue_manager)
- return PostTaskResult::Fail(std::move(task));
-
- EnqueueOrder sequence_number =
- main_thread_only().task_queue_manager->GetNextSequenceNumber();
-
- TimeTicks time_domain_now = main_thread_only().time_domain->Now();
- TimeTicks time_domain_delayed_run_time = time_domain_now + task.delay;
- PushOntoDelayedIncomingQueueFromMainThread(
- Task(std::move(task), time_domain_delayed_run_time, sequence_number),
- time_domain_now);
- } else {
- // NOTE posting a delayed task from a different thread is not expected to
- // be common. This pathway is less optimal than perhaps it could be
- // because it causes two main thread tasks to be run. Should this
- // assumption prove to be false in future, we may need to revisit this.
- AutoLock lock(any_thread_lock_);
- if (!any_thread().task_queue_manager)
- return PostTaskResult::Fail(std::move(task));
-
- EnqueueOrder sequence_number =
- any_thread().task_queue_manager->GetNextSequenceNumber();
-
- TimeTicks time_domain_now = any_thread().time_domain->Now();
- TimeTicks time_domain_delayed_run_time = time_domain_now + task.delay;
- PushOntoDelayedIncomingQueueLocked(
- Task(std::move(task), time_domain_delayed_run_time, sequence_number));
- }
- return PostTaskResult::Success();
-}
-
-void TaskQueueImpl::PushOntoDelayedIncomingQueueFromMainThread(
- Task pending_task,
- TimeTicks now) {
- main_thread_only().task_queue_manager->DidQueueTask(pending_task);
- main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
-
- LazyNow lazy_now = main_thread_only().time_domain->CreateLazyNow();
- UpdateDelayedWakeUp(&lazy_now);
-
- TraceQueueSize();
-}
-
-void TaskQueueImpl::PushOntoDelayedIncomingQueueLocked(Task pending_task) {
- any_thread().task_queue_manager->DidQueueTask(pending_task);
-
- int thread_hop_task_sequence_number =
- any_thread().task_queue_manager->GetNextSequenceNumber();
- // TODO(altimin): Add a copy method to Task to capture metadata here.
- PushOntoImmediateIncomingQueueLocked(Task(
- TaskQueue::PostedTask(BindOnce(&TaskQueueImpl::ScheduleDelayedWorkTask,
- Unretained(this), std::move(pending_task)),
- FROM_HERE, TimeDelta(), Nestable::kNonNestable,
- pending_task.task_type()),
- TimeTicks(), thread_hop_task_sequence_number,
- thread_hop_task_sequence_number));
-}
-
-void TaskQueueImpl::ScheduleDelayedWorkTask(Task pending_task) {
- DCHECK(main_thread_checker_.CalledOnValidThread());
- TimeTicks delayed_run_time = pending_task.delayed_run_time;
- TimeTicks time_domain_now = main_thread_only().time_domain->Now();
- if (delayed_run_time <= time_domain_now) {
- // If |delayed_run_time| is in the past then push it onto the work queue
- // immediately. To ensure the right task ordering we need to temporarily
- // push it onto the |delayed_incoming_queue|.
- delayed_run_time = time_domain_now;
- pending_task.delayed_run_time = time_domain_now;
- main_thread_only().delayed_incoming_queue.push(std::move(pending_task));
- LazyNow lazy_now(time_domain_now);
- WakeUpForDelayedWork(&lazy_now);
- } else {
- // If |delayed_run_time| is in the future we can queue it as normal.
- PushOntoDelayedIncomingQueueFromMainThread(std::move(pending_task),
- time_domain_now);
- }
- TraceQueueSize();
-}
-
-void TaskQueueImpl::PushOntoImmediateIncomingQueueLocked(Task task) {
- // If the |immediate_incoming_queue| is empty we need a DoWork posted to make
- // it run.
- bool was_immediate_incoming_queue_empty;
-
- EnqueueOrder sequence_number = task.sequence_num;
- TimeTicks desired_run_time = task.delayed_run_time;
-
- {
- AutoLock lock(immediate_incoming_queue_lock_);
- was_immediate_incoming_queue_empty = immediate_incoming_queue().empty();
- immediate_incoming_queue().push_back(std::move(task));
- any_thread().task_queue_manager->DidQueueTask(
- immediate_incoming_queue().back());
- }
-
- if (was_immediate_incoming_queue_empty) {
- // However there's no point posting a DoWork for a blocked queue. NB we can
- // only tell if it's disabled from the main thread.
- bool queue_is_blocked =
- RunsTasksInCurrentSequence() &&
- (!IsQueueEnabled() || main_thread_only().current_fence);
- any_thread().task_queue_manager->OnQueueHasIncomingImmediateWork(
- this, sequence_number, queue_is_blocked);
- if (!any_thread().on_next_wake_up_changed_callback.is_null())
- any_thread().on_next_wake_up_changed_callback.Run(desired_run_time);
- }
-
- TraceQueueSize();
-}
-
-void TaskQueueImpl::ReloadImmediateWorkQueueIfEmpty() {
- if (!main_thread_only().immediate_work_queue->Empty())
- return;
-
- main_thread_only().immediate_work_queue->ReloadEmptyImmediateQueue();
-}
-
-TaskQueueImpl::TaskDeque TaskQueueImpl::TakeImmediateIncomingQueue() {
- AutoLock immediate_incoming_queue_lock(immediate_incoming_queue_lock_);
- TaskQueueImpl::TaskDeque queue;
- queue.swap(immediate_incoming_queue());
-
- // Activate delayed fence if necessary. This is ideologically similar to
- // ActivateDelayedFenceIfNeeded, but due to immediate tasks being posted
- // from any thread we can't generate an enqueue order for the fence there,
- // so we have to check all immediate tasks and use their enqueue order for
- // a fence.
- if (main_thread_only().delayed_fence) {
- for (const Task& task : queue) {
- if (task.delayed_run_time >= main_thread_only().delayed_fence.value()) {
- main_thread_only().delayed_fence = nullopt;
- DCHECK_EQ(main_thread_only().current_fence,
- static_cast<EnqueueOrder>(EnqueueOrderValues::kNone));
- main_thread_only().current_fence = task.enqueue_order();
- // Do not trigger WorkQueueSets notification when taking incoming
- // immediate queue.
- main_thread_only().immediate_work_queue->InsertFenceSilently(
- main_thread_only().current_fence);
- main_thread_only().delayed_work_queue->InsertFenceSilently(
- main_thread_only().current_fence);
- break;
- }
- }
- }
-
- return queue;
-}
-
-bool TaskQueueImpl::IsEmpty() const {
- if (!main_thread_only().delayed_work_queue->Empty() ||
- !main_thread_only().delayed_incoming_queue.empty() ||
- !main_thread_only().immediate_work_queue->Empty()) {
- return false;
- }
-
- AutoLock lock(immediate_incoming_queue_lock_);
- return immediate_incoming_queue().empty();
-}
-
-size_t TaskQueueImpl::GetNumberOfPendingTasks() const {
- size_t task_count = 0;
- task_count += main_thread_only().delayed_work_queue->Size();
- task_count += main_thread_only().delayed_incoming_queue.size();
- task_count += main_thread_only().immediate_work_queue->Size();
-
- AutoLock lock(immediate_incoming_queue_lock_);
- task_count += immediate_incoming_queue().size();
- return task_count;
-}
-
-bool TaskQueueImpl::HasTaskToRunImmediately() const {
- // Any work queue tasks count as immediate work.
- if (!main_thread_only().delayed_work_queue->Empty() ||
- !main_thread_only().immediate_work_queue->Empty()) {
- return true;
- }
-
- // Tasks on |delayed_incoming_queue| that could run now, count as
- // immediate work.
- if (!main_thread_only().delayed_incoming_queue.empty() &&
- main_thread_only().delayed_incoming_queue.top().delayed_run_time <=
- main_thread_only().time_domain->CreateLazyNow().Now()) {
- return true;
- }
-
- // Finally tasks on |immediate_incoming_queue| count as immediate work.
- AutoLock lock(immediate_incoming_queue_lock_);
- return !immediate_incoming_queue().empty();
-}
-
-Optional<TaskQueueImpl::DelayedWakeUp>
-TaskQueueImpl::GetNextScheduledWakeUpImpl() {
- // Note we don't scheduled a wake-up for disabled queues.
- if (main_thread_only().delayed_incoming_queue.empty() || !IsQueueEnabled())
- return nullopt;
-
- return main_thread_only().delayed_incoming_queue.top().delayed_wake_up();
-}
-
-Optional<TimeTicks> TaskQueueImpl::GetNextScheduledWakeUp() {
- Optional<DelayedWakeUp> wake_up = GetNextScheduledWakeUpImpl();
- if (!wake_up)
- return nullopt;
- return wake_up->time;
-}
-
-void TaskQueueImpl::WakeUpForDelayedWork(LazyNow* lazy_now) {
- // Enqueue all delayed tasks that should be running now, skipping any that
- // have been canceled.
- while (!main_thread_only().delayed_incoming_queue.empty()) {
- Task& task =
- const_cast<Task&>(main_thread_only().delayed_incoming_queue.top());
- if (!task.task || task.task.IsCancelled()) {
- main_thread_only().delayed_incoming_queue.pop();
- continue;
- }
- if (task.delayed_run_time > lazy_now->Now())
- break;
- ActivateDelayedFenceIfNeeded(task.delayed_run_time);
- task.set_enqueue_order(
- main_thread_only().task_queue_manager->GetNextSequenceNumber());
- main_thread_only().delayed_work_queue->Push(std::move(task));
- main_thread_only().delayed_incoming_queue.pop();
-
- // Normally WakeUpForDelayedWork is called inside DoWork, but it also
- // can be called elsewhere (e.g. tests and fast-path for posting
- // delayed tasks). Ensure that there is a DoWork posting. No-op inside
- // existing DoWork due to DoWork deduplication.
- if (IsQueueEnabled() || !main_thread_only().current_fence) {
- main_thread_only().task_queue_manager->MaybeScheduleImmediateWork(
- FROM_HERE);
- }
- }
-
- UpdateDelayedWakeUp(lazy_now);
-}
-
-void TaskQueueImpl::TraceQueueSize() const {
- bool is_tracing;
- TRACE_EVENT_CATEGORY_GROUP_ENABLED(
- TRACE_DISABLED_BY_DEFAULT("sequence_manager"), &is_tracing);
- if (!is_tracing)
- return;
-
- // It's only safe to access the work queues from the main thread.
- // TODO(alexclarke): We should find another way of tracing this
- if (PlatformThread::CurrentId() != thread_id_)
- return;
-
- AutoLock lock(immediate_incoming_queue_lock_);
- TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("sequence_manager"), GetName(),
- immediate_incoming_queue().size() +
- main_thread_only().immediate_work_queue->Size() +
- main_thread_only().delayed_work_queue->Size() +
- main_thread_only().delayed_incoming_queue.size());
-}
-
-void TaskQueueImpl::SetQueuePriority(TaskQueue::QueuePriority priority) {
- if (!main_thread_only().task_queue_manager || priority == GetQueuePriority())
- return;
- main_thread_only()
- .task_queue_manager->main_thread_only()
- .selector.SetQueuePriority(this, priority);
-}
-
-TaskQueue::QueuePriority TaskQueueImpl::GetQueuePriority() const {
- size_t set_index = immediate_work_queue()->work_queue_set_index();
- DCHECK_EQ(set_index, delayed_work_queue()->work_queue_set_index());
- return static_cast<TaskQueue::QueuePriority>(set_index);
-}
-
-void TaskQueueImpl::AsValueInto(TimeTicks now,
- trace_event::TracedValue* state) const {
- AutoLock lock(any_thread_lock_);
- AutoLock immediate_incoming_queue_lock(immediate_incoming_queue_lock_);
- state->BeginDictionary();
- state->SetString("name", GetName());
- if (!main_thread_only().task_queue_manager) {
- state->SetBoolean("unregistered", true);
- state->EndDictionary();
- return;
- }
- DCHECK(main_thread_only().time_domain);
- DCHECK(main_thread_only().delayed_work_queue);
- DCHECK(main_thread_only().immediate_work_queue);
-
- state->SetString(
- "task_queue_id",
- StringPrintf("0x%" PRIx64,
- static_cast<uint64_t>(reinterpret_cast<uintptr_t>(this))));
- state->SetBoolean("enabled", IsQueueEnabled());
- state->SetString("time_domain_name",
- main_thread_only().time_domain->GetName());
- state->SetInteger("immediate_incoming_queue_size",
- immediate_incoming_queue().size());
- state->SetInteger("delayed_incoming_queue_size",
- main_thread_only().delayed_incoming_queue.size());
- state->SetInteger("immediate_work_queue_size",
- main_thread_only().immediate_work_queue->Size());
- state->SetInteger("delayed_work_queue_size",
- main_thread_only().delayed_work_queue->Size());
- if (!main_thread_only().delayed_incoming_queue.empty()) {
- TimeDelta delay_to_next_task =
- (main_thread_only().delayed_incoming_queue.top().delayed_run_time -
- main_thread_only().time_domain->CreateLazyNow().Now());
- state->SetDouble("delay_to_next_task_ms",
- delay_to_next_task.InMillisecondsF());
- }
- if (main_thread_only().current_fence)
- state->SetInteger("current_fence", main_thread_only().current_fence);
- if (main_thread_only().delayed_fence) {
- state->SetDouble(
- "delayed_fence_seconds_from_now",
- (main_thread_only().delayed_fence.value() - now).InSecondsF());
- }
-
- bool verbose = false;
- TRACE_EVENT_CATEGORY_GROUP_ENABLED(
- TRACE_DISABLED_BY_DEFAULT("sequence_manager.verbose_snapshots"),
- &verbose);
-
- if (verbose) {
- state->BeginArray("immediate_incoming_queue");
- QueueAsValueInto(immediate_incoming_queue(), now, state);
- state->EndArray();
- state->BeginArray("delayed_work_queue");
- main_thread_only().delayed_work_queue->AsValueInto(now, state);
- state->EndArray();
- state->BeginArray("immediate_work_queue");
- main_thread_only().immediate_work_queue->AsValueInto(now, state);
- state->EndArray();
- state->BeginArray("delayed_incoming_queue");
- QueueAsValueInto(main_thread_only().delayed_incoming_queue, now, state);
- state->EndArray();
- }
- state->SetString("priority", TaskQueue::PriorityToString(GetQueuePriority()));
- state->EndDictionary();
-}
-
-void TaskQueueImpl::AddTaskObserver(MessageLoop::TaskObserver* task_observer) {
- main_thread_only().task_observers.AddObserver(task_observer);
-}
-
-void TaskQueueImpl::RemoveTaskObserver(
- MessageLoop::TaskObserver* task_observer) {
- main_thread_only().task_observers.RemoveObserver(task_observer);
-}
-
-void TaskQueueImpl::NotifyWillProcessTask(const PendingTask& pending_task) {
- DCHECK(should_notify_observers_);
- if (main_thread_only().blame_context)
- main_thread_only().blame_context->Enter();
- for (auto& observer : main_thread_only().task_observers)
- observer.WillProcessTask(pending_task);
-}
-
-void TaskQueueImpl::NotifyDidProcessTask(const PendingTask& pending_task) {
- DCHECK(should_notify_observers_);
- for (auto& observer : main_thread_only().task_observers)
- observer.DidProcessTask(pending_task);
- if (main_thread_only().blame_context)
- main_thread_only().blame_context->Leave();
-}
-
-void TaskQueueImpl::SetTimeDomain(TimeDomain* time_domain) {
- {
- AutoLock lock(any_thread_lock_);
- DCHECK(time_domain);
- // NOTE this is similar to checking |any_thread().task_queue_manager| but
- // the TaskQueueSelectorTests constructs TaskQueueImpl directly with a null
- // task_queue_manager. Instead we check |any_thread().time_domain| which is
- // another way of asserting that UnregisterTaskQueue has not been called.
- DCHECK(any_thread().time_domain);
- if (!any_thread().time_domain)
- return;
- DCHECK(main_thread_checker_.CalledOnValidThread());
- if (time_domain == main_thread_only().time_domain)
- return;
-
- any_thread().time_domain = time_domain;
- }
-
- main_thread_only().time_domain->UnregisterQueue(this);
- main_thread_only().time_domain = time_domain;
- time_domain->RegisterQueue(this);
-
- LazyNow lazy_now = time_domain->CreateLazyNow();
- // Clear scheduled wake up to ensure that new notifications are issued
- // correctly.
- // TODO(altimin): Remove this when we won't have to support changing time
- // domains.
- main_thread_only().scheduled_wake_up = nullopt;
- UpdateDelayedWakeUp(&lazy_now);
-}
-
-TimeDomain* TaskQueueImpl::GetTimeDomain() const {
- if (PlatformThread::CurrentId() == thread_id_)
- return main_thread_only().time_domain;
-
- AutoLock lock(any_thread_lock_);
- return any_thread().time_domain;
-}
-
-void TaskQueueImpl::SetBlameContext(trace_event::BlameContext* blame_context) {
- main_thread_only().blame_context = blame_context;
-}
-
-void TaskQueueImpl::InsertFence(TaskQueue::InsertFencePosition position) {
- if (!main_thread_only().task_queue_manager)
- return;
-
- // Only one fence may be present at a time.
- main_thread_only().delayed_fence = nullopt;
-
- EnqueueOrder previous_fence = main_thread_only().current_fence;
- EnqueueOrder current_fence =
- position == TaskQueue::InsertFencePosition::kNow
- ? main_thread_only().task_queue_manager->GetNextSequenceNumber()
- : static_cast<EnqueueOrder>(EnqueueOrderValues::kBlockingFence);
-
- // Tasks posted after this point will have a strictly higher enqueue order
- // and will be blocked from running.
- main_thread_only().current_fence = current_fence;
- bool task_unblocked =
- main_thread_only().immediate_work_queue->InsertFence(current_fence);
- task_unblocked |=
- main_thread_only().delayed_work_queue->InsertFence(current_fence);
-
- if (!task_unblocked && previous_fence && previous_fence < current_fence) {
- AutoLock lock(immediate_incoming_queue_lock_);
- if (!immediate_incoming_queue().empty() &&
- immediate_incoming_queue().front().enqueue_order() > previous_fence &&
- immediate_incoming_queue().front().enqueue_order() < current_fence) {
- task_unblocked = true;
- }
- }
-
- if (IsQueueEnabled() && task_unblocked) {
- main_thread_only().task_queue_manager->MaybeScheduleImmediateWork(
- FROM_HERE);
- }
-}
-
-void TaskQueueImpl::InsertFenceAt(TimeTicks time) {
- // Task queue can have only one fence, delayed or not.
- RemoveFence();
- main_thread_only().delayed_fence = time;
-}
-
-void TaskQueueImpl::RemoveFence() {
- if (!main_thread_only().task_queue_manager)
- return;
-
- EnqueueOrder previous_fence = main_thread_only().current_fence;
- main_thread_only().current_fence = 0;
- main_thread_only().delayed_fence = nullopt;
-
- bool task_unblocked = main_thread_only().immediate_work_queue->RemoveFence();
- task_unblocked |= main_thread_only().delayed_work_queue->RemoveFence();
-
- if (!task_unblocked && previous_fence) {
- AutoLock lock(immediate_incoming_queue_lock_);
- if (!immediate_incoming_queue().empty() &&
- immediate_incoming_queue().front().enqueue_order() > previous_fence) {
- task_unblocked = true;
- }
- }
-
- if (IsQueueEnabled() && task_unblocked) {
- main_thread_only().task_queue_manager->MaybeScheduleImmediateWork(
- FROM_HERE);
- }
-}
-
-bool TaskQueueImpl::BlockedByFence() const {
- if (!main_thread_only().current_fence)
- return false;
-
- if (!main_thread_only().immediate_work_queue->BlockedByFence() ||
- !main_thread_only().delayed_work_queue->BlockedByFence()) {
- return false;
- }
-
- AutoLock lock(immediate_incoming_queue_lock_);
- if (immediate_incoming_queue().empty())
- return true;
-
- return immediate_incoming_queue().front().enqueue_order() >
- main_thread_only().current_fence;
-}
-
-bool TaskQueueImpl::HasActiveFence() {
- if (main_thread_only().delayed_fence &&
- main_thread_only().time_domain->Now() >
- main_thread_only().delayed_fence.value()) {
- return true;
- }
- return !!main_thread_only().current_fence;
-}
-
-bool TaskQueueImpl::CouldTaskRun(EnqueueOrder enqueue_order) const {
- if (!IsQueueEnabled())
- return false;
-
- if (!main_thread_only().current_fence)
- return true;
-
- return enqueue_order < main_thread_only().current_fence;
-}
-
-EnqueueOrder TaskQueueImpl::GetFenceForTest() const {
- return main_thread_only().current_fence;
-}
-
-// static
-void TaskQueueImpl::QueueAsValueInto(const TaskDeque& queue,
- TimeTicks now,
- trace_event::TracedValue* state) {
- for (const Task& task : queue) {
- TaskAsValueInto(task, now, state);
- }
-}
-
-// static
-void TaskQueueImpl::QueueAsValueInto(const std::priority_queue<Task>& queue,
- TimeTicks now,
- trace_event::TracedValue* state) {
- // Remove const to search |queue| in the destructive manner. Restore the
- // content from |visited| later.
- std::priority_queue<Task>* mutable_queue =
- const_cast<std::priority_queue<Task>*>(&queue);
- std::priority_queue<Task> visited;
- while (!mutable_queue->empty()) {
- TaskAsValueInto(mutable_queue->top(), now, state);
- visited.push(std::move(const_cast<Task&>(mutable_queue->top())));
- mutable_queue->pop();
- }
- *mutable_queue = std::move(visited);
-}
-
-// static
-void TaskQueueImpl::TaskAsValueInto(const Task& task,
- TimeTicks now,
- trace_event::TracedValue* state) {
- state->BeginDictionary();
- state->SetString("posted_from", task.posted_from.ToString());
-#ifndef NDEBUG
- if (task.enqueue_order_set())
- state->SetInteger("enqueue_order", task.enqueue_order());
-#else
- state->SetInteger("enqueue_order", task.enqueue_order());
-#endif
- state->SetInteger("sequence_num", task.sequence_num);
- state->SetBoolean("nestable", task.nestable == Nestable::kNestable);
- state->SetBoolean("is_high_res", task.is_high_res);
- state->SetBoolean("is_cancelled", task.task.IsCancelled());
- state->SetDouble("delayed_run_time",
- (task.delayed_run_time - TimeTicks()).InMillisecondsF());
- state->SetDouble("delayed_run_time_milliseconds_from_now",
- (task.delayed_run_time - now).InMillisecondsF());
- state->EndDictionary();
-}
-
-TaskQueueImpl::QueueEnabledVoterImpl::QueueEnabledVoterImpl(
- scoped_refptr<TaskQueue> task_queue)
- : task_queue_(task_queue), enabled_(true) {}
-
-TaskQueueImpl::QueueEnabledVoterImpl::~QueueEnabledVoterImpl() {
- if (task_queue_->GetTaskQueueImpl())
- task_queue_->GetTaskQueueImpl()->RemoveQueueEnabledVoter(this);
-}
-
-void TaskQueueImpl::QueueEnabledVoterImpl::SetQueueEnabled(bool enabled) {
- if (enabled_ == enabled)
- return;
-
- task_queue_->GetTaskQueueImpl()->OnQueueEnabledVoteChanged(enabled);
- enabled_ = enabled;
-}
-
-void TaskQueueImpl::RemoveQueueEnabledVoter(
- const QueueEnabledVoterImpl* voter) {
- // Bail out if we're being called from TaskQueueImpl::UnregisterTaskQueue.
- if (!main_thread_only().time_domain)
- return;
-
- bool was_enabled = IsQueueEnabled();
- if (voter->enabled_) {
- main_thread_only().is_enabled_refcount--;
- DCHECK_GE(main_thread_only().is_enabled_refcount, 0);
- }
-
- main_thread_only().voter_refcount--;
- DCHECK_GE(main_thread_only().voter_refcount, 0);
-
- bool is_enabled = IsQueueEnabled();
- if (was_enabled != is_enabled)
- EnableOrDisableWithSelector(is_enabled);
-}
-
-bool TaskQueueImpl::IsQueueEnabled() const {
- // By default is_enabled_refcount and voter_refcount both equal zero.
- return (main_thread_only().is_enabled_refcount ==
- main_thread_only().voter_refcount) &&
- main_thread_only().is_enabled_for_test;
-}
-
-void TaskQueueImpl::OnQueueEnabledVoteChanged(bool enabled) {
- bool was_enabled = IsQueueEnabled();
- if (enabled) {
- main_thread_only().is_enabled_refcount++;
- DCHECK_LE(main_thread_only().is_enabled_refcount,
- main_thread_only().voter_refcount);
- } else {
- main_thread_only().is_enabled_refcount--;
- DCHECK_GE(main_thread_only().is_enabled_refcount, 0);
- }
-
- bool is_enabled = IsQueueEnabled();
- if (was_enabled != is_enabled)
- EnableOrDisableWithSelector(is_enabled);
-}
-
-void TaskQueueImpl::EnableOrDisableWithSelector(bool enable) {
- if (!main_thread_only().task_queue_manager)
- return;
-
- LazyNow lazy_now = main_thread_only().time_domain->CreateLazyNow();
- UpdateDelayedWakeUp(&lazy_now);
-
- if (enable) {
- if (HasPendingImmediateWork() &&
- !main_thread_only().on_next_wake_up_changed_callback.is_null()) {
- // Delayed work notification will be issued via time domain.
- main_thread_only().on_next_wake_up_changed_callback.Run(TimeTicks());
- }
-
- // Note the selector calls TaskQueueManager::OnTaskQueueEnabled which posts
- // a DoWork if needed.
- main_thread_only()
- .task_queue_manager->main_thread_only()
- .selector.EnableQueue(this);
- } else {
- main_thread_only()
- .task_queue_manager->main_thread_only()
- .selector.DisableQueue(this);
- }
-}
-
-std::unique_ptr<TaskQueue::QueueEnabledVoter>
-TaskQueueImpl::CreateQueueEnabledVoter(scoped_refptr<TaskQueue> task_queue) {
- DCHECK_EQ(task_queue->GetTaskQueueImpl(), this);
- main_thread_only().voter_refcount++;
- main_thread_only().is_enabled_refcount++;
- return std::make_unique<QueueEnabledVoterImpl>(task_queue);
-}
-
-void TaskQueueImpl::SweepCanceledDelayedTasks(TimeTicks now) {
- if (main_thread_only().delayed_incoming_queue.empty())
- return;
-
- // Remove canceled tasks.
- std::priority_queue<Task> remaining_tasks;
- while (!main_thread_only().delayed_incoming_queue.empty()) {
- if (!main_thread_only().delayed_incoming_queue.top().task.IsCancelled()) {
- remaining_tasks.push(std::move(
- const_cast<Task&>(main_thread_only().delayed_incoming_queue.top())));
- }
- main_thread_only().delayed_incoming_queue.pop();
- }
-
- main_thread_only().delayed_incoming_queue = std::move(remaining_tasks);
-
- LazyNow lazy_now(now);
- UpdateDelayedWakeUp(&lazy_now);
-}
-
-void TaskQueueImpl::PushImmediateIncomingTaskForTest(
- TaskQueueImpl::Task&& task) {
- AutoLock lock(immediate_incoming_queue_lock_);
- immediate_incoming_queue().push_back(std::move(task));
-}
-
-void TaskQueueImpl::RequeueDeferredNonNestableTask(
- DeferredNonNestableTask task) {
- DCHECK(task.task.nestable == Nestable::kNonNestable);
- // The re-queued tasks have to be pushed onto the front because we'd otherwise
- // violate the strict monotonically increasing enqueue order within the
- // WorkQueue. We can't assign them a new enqueue order here because that will
- // not behave correctly with fences and things will break (e.g Idle TQ).
- if (task.work_queue_type == WorkQueueType::kDelayed) {
- main_thread_only().delayed_work_queue->PushNonNestableTaskToFront(
- std::move(task.task));
- } else {
- main_thread_only().immediate_work_queue->PushNonNestableTaskToFront(
- std::move(task.task));
- }
-}
-
-void TaskQueueImpl::SetOnNextWakeUpChangedCallback(
- TaskQueueImpl::OnNextWakeUpChangedCallback callback) {
-#if DCHECK_IS_ON()
- if (callback) {
- DCHECK(main_thread_only().on_next_wake_up_changed_callback.is_null())
- << "Can't assign two different observers to "
- "blink::scheduler::TaskQueue";
- }
-#endif
- AutoLock lock(any_thread_lock_);
- any_thread().on_next_wake_up_changed_callback = callback;
- main_thread_only().on_next_wake_up_changed_callback = callback;
-}
-
-void TaskQueueImpl::UpdateDelayedWakeUp(LazyNow* lazy_now) {
- return UpdateDelayedWakeUpImpl(lazy_now, GetNextScheduledWakeUpImpl());
-}
-
-void TaskQueueImpl::UpdateDelayedWakeUpImpl(
- LazyNow* lazy_now,
- Optional<TaskQueueImpl::DelayedWakeUp> wake_up) {
- if (main_thread_only().scheduled_wake_up == wake_up)
- return;
- main_thread_only().scheduled_wake_up = wake_up;
-
- if (wake_up &&
- !main_thread_only().on_next_wake_up_changed_callback.is_null() &&
- !HasPendingImmediateWork()) {
- main_thread_only().on_next_wake_up_changed_callback.Run(wake_up->time);
- }
-
- main_thread_only().time_domain->ScheduleWakeUpForQueue(this, wake_up,
- lazy_now);
-}
-
-void TaskQueueImpl::SetDelayedWakeUpForTesting(
- Optional<TaskQueueImpl::DelayedWakeUp> wake_up) {
- LazyNow lazy_now = main_thread_only().time_domain->CreateLazyNow();
- UpdateDelayedWakeUpImpl(&lazy_now, wake_up);
-}
-
-bool TaskQueueImpl::HasPendingImmediateWork() {
- // Any work queue tasks count as immediate work.
- if (!main_thread_only().delayed_work_queue->Empty() ||
- !main_thread_only().immediate_work_queue->Empty()) {
- return true;
- }
-
- // Finally tasks on |immediate_incoming_queue| count as immediate work.
- AutoLock lock(immediate_incoming_queue_lock_);
- return !immediate_incoming_queue().empty();
-}
-
-void TaskQueueImpl::SetOnTaskStartedHandler(
- TaskQueueImpl::OnTaskStartedHandler handler) {
- main_thread_only().on_task_started_handler = std::move(handler);
-}
-
-void TaskQueueImpl::OnTaskStarted(const TaskQueue::Task& task,
- TimeTicks start) {
- if (!main_thread_only().on_task_started_handler.is_null())
- main_thread_only().on_task_started_handler.Run(task, start);
-}
-
-void TaskQueueImpl::SetOnTaskCompletedHandler(
- TaskQueueImpl::OnTaskCompletedHandler handler) {
- main_thread_only().on_task_completed_handler = std::move(handler);
-}
-
-void TaskQueueImpl::OnTaskCompleted(const TaskQueue::Task& task,
- TimeTicks start,
- TimeTicks end,
- Optional<TimeDelta> thread_time) {
- if (!main_thread_only().on_task_completed_handler.is_null()) {
- main_thread_only().on_task_completed_handler.Run(task, start, end,
- thread_time);
- }
-}
-
-bool TaskQueueImpl::RequiresTaskTiming() const {
- return !main_thread_only().on_task_started_handler.is_null() ||
- !main_thread_only().on_task_completed_handler.is_null();
-}
-
-bool TaskQueueImpl::IsUnregistered() const {
- AutoLock lock(any_thread_lock_);
- return !any_thread().task_queue_manager;
-}
-
-WeakPtr<TaskQueueManagerImpl> TaskQueueImpl::GetTaskQueueManagerWeakPtr() {
- return main_thread_only().task_queue_manager->GetWeakPtr();
-}
-
-scoped_refptr<GracefulQueueShutdownHelper>
-TaskQueueImpl::GetGracefulQueueShutdownHelper() {
- return main_thread_only()
- .task_queue_manager->GetGracefulQueueShutdownHelper();
-}
-
-void TaskQueueImpl::SetQueueEnabledForTest(bool enabled) {
- main_thread_only().is_enabled_for_test = enabled;
- EnableOrDisableWithSelector(IsQueueEnabled());
-}
-
-void TaskQueueImpl::ActivateDelayedFenceIfNeeded(TimeTicks now) {
- if (!main_thread_only().delayed_fence)
- return;
- if (main_thread_only().delayed_fence.value() > now)
- return;
- InsertFence(TaskQueue::InsertFencePosition::kNow);
- main_thread_only().delayed_fence = nullopt;
-}
-
-} // namespace internal
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h
deleted file mode 100644
index 471e60bec22..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h
+++ /dev/null
@@ -1,460 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_IMPL_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_IMPL_H_
-
-#include <stddef.h>
-
-#include <memory>
-#include <set>
-
-#include "base/callback.h"
-#include "base/containers/circular_deque.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/pending_task.h"
-#include "base/task/sequence_manager/sequenced_task_source.h"
-#include "base/threading/thread_checker.h"
-#include "base/trace_event/trace_event.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "third_party/blink/renderer/platform/scheduler/base/enqueue_order.h"
-#include "third_party/blink/renderer/platform/scheduler/base/graceful_queue_shutdown_helper.h"
-#include "third_party/blink/renderer/platform/scheduler/base/intrusive_heap.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
-
-namespace base {
-namespace sequence_manager {
-class LazyNow;
-class TimeDomain;
-class TaskQueueManagerImpl;
-
-namespace internal {
-class WorkQueue;
-class WorkQueueSets;
-
-// TaskQueueImpl has four main queues:
-//
-// Immediate (non-delayed) tasks:
-// immediate_incoming_queue - PostTask enqueues tasks here
-// immediate_work_queue
-//
-// Delayed tasks
-// delayed_incoming_queue - PostDelayedTask enqueues tasks here
-// delayed_work_queue
-//
-// The immediate_incoming_queue can be accessed from any thread, the other
-// queues are main-thread only. To reduce the overhead of locking,
-// immediate_work_queue is swapped with immediate_incoming_queue when
-// immediate_work_queue becomes empty.
-//
-// Delayed tasks are initially posted to delayed_incoming_queue and a wake-up
-// is scheduled with the TimeDomain. When the delay has elapsed, the TimeDomain
-// calls UpdateDelayedWorkQueue and ready delayed tasks are moved into the
-// delayed_work_queue. Note the EnqueueOrder (used for ordering) for a delayed
-// task is not set until it's moved into the delayed_work_queue.
-//
-// TaskQueueImpl uses the WorkQueueSets and the TaskQueueSelector to implement
-// prioritization. Task selection is done by the TaskQueueSelector and when a
-// queue is selected, it round-robins between the immediate_work_queue and
-// delayed_work_queue. The reason for this is we want to make sure delayed
-// tasks (normally the most common type) don't starve out immediate work.
-class PLATFORM_EXPORT TaskQueueImpl {
- public:
- TaskQueueImpl(TaskQueueManagerImpl* task_queue_manager,
- TimeDomain* time_domain,
- const TaskQueue::Spec& spec);
-
- ~TaskQueueImpl();
-
- // Represents a time at which a task wants to run. Tasks scheduled for the
- // same point in time will be ordered by their sequence numbers.
- struct DelayedWakeUp {
- TimeTicks time;
- int sequence_num;
-
- bool operator!=(const DelayedWakeUp& other) const {
- return time != other.time || other.sequence_num != sequence_num;
- }
-
- bool operator==(const DelayedWakeUp& other) const {
- return !(*this != other);
- }
-
- bool operator<=(const DelayedWakeUp& other) const {
- if (time == other.time) {
- // Debug gcc builds can compare an element against itself.
- DCHECK(sequence_num != other.sequence_num || this == &other);
- return (sequence_num - other.sequence_num) < 0;
- }
- return time < other.time;
- }
- };
-
- class PLATFORM_EXPORT Task : public TaskQueue::Task {
- public:
- Task(TaskQueue::PostedTask task,
- TimeTicks desired_run_time,
- EnqueueOrder sequence_number);
-
- Task(TaskQueue::PostedTask task,
- TimeTicks desired_run_time,
- EnqueueOrder sequence_number,
- EnqueueOrder enqueue_order);
-
- DelayedWakeUp delayed_wake_up() const {
- return DelayedWakeUp{delayed_run_time, sequence_num};
- }
-
- EnqueueOrder enqueue_order() const {
-#ifndef NDEBUG
- DCHECK(enqueue_order_set_);
-#endif
- return enqueue_order_;
- }
-
- void set_enqueue_order(EnqueueOrder enqueue_order) {
-#ifndef NDEBUG
- DCHECK(!enqueue_order_set_);
- enqueue_order_set_ = true;
-#endif
- enqueue_order_ = enqueue_order;
- }
-
-#ifndef NDEBUG
- bool enqueue_order_set() const { return enqueue_order_set_; }
-#endif
-
- private:
-#ifndef NDEBUG
- bool enqueue_order_set_;
-#endif
- // Similar to sequence number, but ultimately the |enqueue_order_| is what
- // the scheduler uses for task ordering. For immediate tasks |enqueue_order|
- // is set when posted, but for delayed tasks it's not defined until they are
- // enqueued on the |delayed_work_queue_|. This is because otherwise delayed
- // tasks could run before an immediate task posted after the delayed task.
- EnqueueOrder enqueue_order_;
- };
-
- // A result retuned by PostDelayedTask. When scheduler failed to post a task
- // due to being shutdown a task is returned to be destroyed outside the lock.
- struct PostTaskResult {
- PostTaskResult();
- PostTaskResult(bool success, TaskQueue::PostedTask task);
- PostTaskResult(PostTaskResult&& move_from);
- PostTaskResult(const PostTaskResult& copy_from) = delete;
- ~PostTaskResult();
-
- static PostTaskResult Success();
- static PostTaskResult Fail(TaskQueue::PostedTask task);
-
- bool success;
- TaskQueue::PostedTask task;
- };
-
- // Types of queues TaskQueueImpl is maintaining internally.
- enum class WorkQueueType { kImmediate, kDelayed };
-
- // Non-nestable tasks may get deferred but such queue is being maintained on
- // TaskQueueManager side, so we need to keep information how to requeue it.
- struct DeferredNonNestableTask {
- internal::TaskQueueImpl::Task task;
- internal::TaskQueueImpl* task_queue;
- WorkQueueType work_queue_type;
- };
-
- using OnNextWakeUpChangedCallback = RepeatingCallback<void(TimeTicks)>;
- using OnTaskStartedHandler =
- RepeatingCallback<void(const TaskQueue::Task&, TimeTicks)>;
- using OnTaskCompletedHandler = RepeatingCallback<
- void(const TaskQueue::Task&, TimeTicks, TimeTicks, Optional<TimeDelta>)>;
-
- // TaskQueue implementation.
- const char* GetName() const;
- bool RunsTasksInCurrentSequence() const;
- PostTaskResult PostDelayedTask(TaskQueue::PostedTask task);
- // Require a reference to enclosing task queue for lifetime control.
- std::unique_ptr<TaskQueue::QueueEnabledVoter> CreateQueueEnabledVoter(
- scoped_refptr<TaskQueue> owning_task_queue);
- bool IsQueueEnabled() const;
- bool IsEmpty() const;
- size_t GetNumberOfPendingTasks() const;
- bool HasTaskToRunImmediately() const;
- Optional<TimeTicks> GetNextScheduledWakeUp();
- Optional<DelayedWakeUp> GetNextScheduledWakeUpImpl();
- void SetQueuePriority(TaskQueue::QueuePriority priority);
- TaskQueue::QueuePriority GetQueuePriority() const;
- void AddTaskObserver(MessageLoop::TaskObserver* task_observer);
- void RemoveTaskObserver(MessageLoop::TaskObserver* task_observer);
- void SetTimeDomain(TimeDomain* time_domain);
- TimeDomain* GetTimeDomain() const;
- void SetBlameContext(trace_event::BlameContext* blame_context);
- void InsertFence(TaskQueue::InsertFencePosition position);
- void InsertFenceAt(TimeTicks time);
- void RemoveFence();
- bool HasActiveFence();
- bool BlockedByFence() const;
- // Implementation of TaskQueue::SetObserver.
- void SetOnNextWakeUpChangedCallback(OnNextWakeUpChangedCallback callback);
-
- void UnregisterTaskQueue();
-
- // Returns true if a (potentially hypothetical) task with the specified
- // |enqueue_order| could run on the queue. Must be called from the main
- // thread.
- bool CouldTaskRun(EnqueueOrder enqueue_order) const;
-
- // Must only be called from the thread this task queue was created on.
- void ReloadImmediateWorkQueueIfEmpty();
-
- void AsValueInto(TimeTicks now, trace_event::TracedValue* state) const;
-
- bool GetQuiescenceMonitored() const { return should_monitor_quiescence_; }
- bool GetShouldNotifyObservers() const { return should_notify_observers_; }
-
- void NotifyWillProcessTask(const PendingTask& pending_task);
- void NotifyDidProcessTask(const PendingTask& pending_task);
-
- // Check for available tasks in immediate work queues.
- // Used to check if we need to generate notifications about delayed work.
- bool HasPendingImmediateWork();
-
- WorkQueue* delayed_work_queue() {
- return main_thread_only().delayed_work_queue.get();
- }
-
- const WorkQueue* delayed_work_queue() const {
- return main_thread_only().delayed_work_queue.get();
- }
-
- WorkQueue* immediate_work_queue() {
- return main_thread_only().immediate_work_queue.get();
- }
-
- const WorkQueue* immediate_work_queue() const {
- return main_thread_only().immediate_work_queue.get();
- }
-
- // Enqueues any delayed tasks which should be run now on the
- // |delayed_work_queue|.
- // Must be called from the main thread.
- void WakeUpForDelayedWork(LazyNow* lazy_now);
-
- HeapHandle heap_handle() const { return main_thread_only().heap_handle; }
-
- void set_heap_handle(HeapHandle heap_handle) {
- main_thread_only().heap_handle = heap_handle;
- }
-
- // Pushes |task| onto the front of the specified work queue. Caution must be
- // taken with this API because you could easily starve out other work.
- // TODO(kraynov): Simplify non-nestable task logic https://crbug.com/845437.
- void RequeueDeferredNonNestableTask(DeferredNonNestableTask task);
-
- void PushImmediateIncomingTaskForTest(TaskQueueImpl::Task&& task);
- EnqueueOrder GetFenceForTest() const;
-
- class QueueEnabledVoterImpl : public TaskQueue::QueueEnabledVoter {
- public:
- explicit QueueEnabledVoterImpl(scoped_refptr<TaskQueue> task_queue);
- ~QueueEnabledVoterImpl() override;
-
- // QueueEnabledVoter implementation.
- void SetQueueEnabled(bool enabled) override;
-
- TaskQueueImpl* GetTaskQueueForTest() const {
- return task_queue_->GetTaskQueueImpl();
- }
-
- private:
- friend class TaskQueueImpl;
-
- scoped_refptr<TaskQueue> task_queue_;
- bool enabled_;
- };
-
- // Iterates over |delayed_incoming_queue| removing canceled tasks.
- void SweepCanceledDelayedTasks(TimeTicks now);
-
- // Allows wrapping TaskQueue to set a handler to subscribe for notifications
- // about started and completed tasks.
- void SetOnTaskStartedHandler(OnTaskStartedHandler handler);
- void OnTaskStarted(const TaskQueue::Task& task, TimeTicks start);
- void SetOnTaskCompletedHandler(OnTaskCompletedHandler handler);
- void OnTaskCompleted(const TaskQueue::Task& task,
- TimeTicks start,
- TimeTicks end,
- Optional<TimeDelta> thread_time);
- bool RequiresTaskTiming() const;
-
- WeakPtr<TaskQueueManagerImpl> GetTaskQueueManagerWeakPtr();
-
- scoped_refptr<GracefulQueueShutdownHelper> GetGracefulQueueShutdownHelper();
-
- // Returns true if this queue is unregistered or task queue manager is deleted
- // and this queue can be safely deleted on any thread.
- bool IsUnregistered() const;
-
- // Disables queue for testing purposes, when a QueueEnabledVoter can't be
- // constructed due to not having TaskQueue.
- void SetQueueEnabledForTest(bool enabled);
-
- protected:
- void SetDelayedWakeUpForTesting(Optional<DelayedWakeUp> wake_up);
-
- private:
- friend class WorkQueue;
- friend class WorkQueueTest;
-
- struct AnyThread {
- AnyThread(TaskQueueManagerImpl* task_queue_manager,
- TimeDomain* time_domain);
- ~AnyThread();
-
- // TaskQueueManagerImpl, TimeDomain and Observer are maintained in two
- // copies: inside AnyThread and inside MainThreadOnly. They can be changed
- // only from main thread, so it should be locked before accessing from other
- // threads.
- TaskQueueManagerImpl* task_queue_manager;
- TimeDomain* time_domain;
- // Callback corresponding to TaskQueue::Observer::OnQueueNextChanged.
- OnNextWakeUpChangedCallback on_next_wake_up_changed_callback;
- };
-
- struct MainThreadOnly {
- MainThreadOnly(TaskQueueManagerImpl* task_queue_manager,
- TaskQueueImpl* task_queue,
- TimeDomain* time_domain);
- ~MainThreadOnly();
-
- // Another copy of TaskQueueManagerImpl, TimeDomain and Observer
- // for lock-free access from the main thread.
- // See description inside struct AnyThread for details.
- TaskQueueManagerImpl* task_queue_manager;
- TimeDomain* time_domain;
- // Callback corresponding to TaskQueue::Observer::OnQueueNextChanged.
- OnNextWakeUpChangedCallback on_next_wake_up_changed_callback;
-
- std::unique_ptr<WorkQueue> delayed_work_queue;
- std::unique_ptr<WorkQueue> immediate_work_queue;
- std::priority_queue<Task> delayed_incoming_queue;
- ObserverList<MessageLoop::TaskObserver> task_observers;
- size_t set_index;
- HeapHandle heap_handle;
- int is_enabled_refcount;
- int voter_refcount;
- trace_event::BlameContext* blame_context; // Not owned.
- EnqueueOrder current_fence;
- Optional<TimeTicks> delayed_fence;
- OnTaskStartedHandler on_task_started_handler;
- OnTaskCompletedHandler on_task_completed_handler;
- // Last reported wake up, used only in UpdateWakeUp to avoid
- // excessive calls.
- Optional<DelayedWakeUp> scheduled_wake_up;
- // If false, queue will be disabled. Used only for tests.
- bool is_enabled_for_test;
- };
-
- PostTaskResult PostImmediateTaskImpl(TaskQueue::PostedTask task);
- PostTaskResult PostDelayedTaskImpl(TaskQueue::PostedTask task);
-
- // Push the task onto the |delayed_incoming_queue|. Lock-free main thread
- // only fast path.
- void PushOntoDelayedIncomingQueueFromMainThread(Task pending_task,
- TimeTicks now);
-
- // Push the task onto the |delayed_incoming_queue|. Slow path from other
- // threads.
- void PushOntoDelayedIncomingQueueLocked(Task pending_task);
-
- void ScheduleDelayedWorkTask(Task pending_task);
-
- void MoveReadyImmediateTasksToImmediateWorkQueueLocked();
-
- // Push the task onto the |immediate_incoming_queue| and for auto pumped
- // queues it calls MaybePostDoWorkOnMainRunner if the Incoming queue was
- // empty.
- void PushOntoImmediateIncomingQueueLocked(Task task);
-
- // We reserve an inline capacity of 8 tasks to try and reduce the load on
- // PartitionAlloc.
- using TaskDeque = circular_deque<Task>;
-
- // Extracts all the tasks from the immediate incoming queue and clears it.
- // Can be called from any thread.
- TaskDeque TakeImmediateIncomingQueue();
-
- void TraceQueueSize() const;
- static void QueueAsValueInto(const TaskDeque& queue,
- TimeTicks now,
- trace_event::TracedValue* state);
- static void QueueAsValueInto(const std::priority_queue<Task>& queue,
- TimeTicks now,
- trace_event::TracedValue* state);
- static void TaskAsValueInto(const Task& task,
- TimeTicks now,
- trace_event::TracedValue* state);
-
- void RemoveQueueEnabledVoter(const QueueEnabledVoterImpl* voter);
- void OnQueueEnabledVoteChanged(bool enabled);
- void EnableOrDisableWithSelector(bool enable);
-
- // Schedules delayed work on time domain and calls the observer.
- void UpdateDelayedWakeUp(LazyNow* lazy_now);
- void UpdateDelayedWakeUpImpl(LazyNow* lazy_now,
- Optional<DelayedWakeUp> wake_up);
-
- // Activate a delayed fence if a time has come.
- void ActivateDelayedFenceIfNeeded(TimeTicks now);
-
- const char* name_;
-
- const PlatformThreadId thread_id_;
-
- mutable Lock any_thread_lock_;
- AnyThread any_thread_;
- struct AnyThread& any_thread() {
- any_thread_lock_.AssertAcquired();
- return any_thread_;
- }
- const struct AnyThread& any_thread() const {
- any_thread_lock_.AssertAcquired();
- return any_thread_;
- }
-
- ThreadChecker main_thread_checker_;
- MainThreadOnly main_thread_only_;
- MainThreadOnly& main_thread_only() {
- DCHECK(main_thread_checker_.CalledOnValidThread());
- return main_thread_only_;
- }
- const MainThreadOnly& main_thread_only() const {
- DCHECK(main_thread_checker_.CalledOnValidThread());
- return main_thread_only_;
- }
-
- mutable Lock immediate_incoming_queue_lock_;
- TaskDeque immediate_incoming_queue_;
- TaskDeque& immediate_incoming_queue() {
- immediate_incoming_queue_lock_.AssertAcquired();
- return immediate_incoming_queue_;
- }
- const TaskDeque& immediate_incoming_queue() const {
- immediate_incoming_queue_lock_.AssertAcquired();
- return immediate_incoming_queue_;
- }
-
- const bool should_monitor_quiescence_;
- const bool should_notify_observers_;
-
- DISALLOW_COPY_AND_ASSIGN(TaskQueueImpl);
-};
-
-} // namespace internal
-} // namespace sequence_manager
-} // namespace base
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h b/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h
deleted file mode 100644
index 988194589d0..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_MANAGER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_MANAGER_H_
-
-#include <memory>
-#include <utility>
-
-#include "base/message_loop/message_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/real_time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_time_observer.h"
-#include "third_party/blink/renderer/platform/scheduler/base/time_domain.h"
-
-namespace base {
-namespace sequence_manager {
-
-class PLATFORM_EXPORT TaskQueueManager {
- public:
- // Keep TaskQueueManagerImpl in sync with this interface.
- // The general rule is not to expose methods only used in scheduler/base.
- // Try to keep interface as lean as possible.
-
- // Observer class. Always called back on the main thread.
- class PLATFORM_EXPORT Observer {
- public:
- virtual ~Observer() {}
- virtual void OnBeginNestedRunLoop() = 0;
- virtual void OnExitNestedRunLoop() = 0;
- };
-
- virtual ~TaskQueueManager() = default;
-
- // Forwards to TaskQueueManagerImpl::TakeOverCurrentThread.
- // TODO(kraynov): Any way to make it truly agnostic of TaskQueueManagerImpl?
- static std::unique_ptr<TaskQueueManager> TakeOverCurrentThread();
-
- // Should be called once, on main thread only.
- // If |null| is passed, no callbacks will occur.
- // Note: |observer| is expected to outlive the SchedulerHelper.
- // TODO(kraynov): Review these lifetime assumptions.
- virtual void SetObserver(Observer* observer) = 0;
-
- // These functions can only be called on the same thread that the task queue
- // manager executes its tasks on.
- virtual void AddTaskObserver(MessageLoop::TaskObserver* task_observer) = 0;
- virtual void RemoveTaskObserver(MessageLoop::TaskObserver* task_observer) = 0;
- virtual void AddTaskTimeObserver(TaskTimeObserver* task_time_observer) = 0;
- virtual void RemoveTaskTimeObserver(TaskTimeObserver* task_time_observer) = 0;
-
- // Time domains must be registered for the task queues to get updated.
- virtual void RegisterTimeDomain(TimeDomain* time_domain) = 0;
- virtual void UnregisterTimeDomain(TimeDomain* time_domain) = 0;
- virtual RealTimeDomain* GetRealTimeDomain() const = 0;
-
- virtual const TickClock* GetClock() const = 0;
- virtual TimeTicks NowTicks() const = 0;
-
- // Sets the SingleThreadTaskRunner that will be returned by
- // ThreadTaskRunnerHandle::Get on the thread associated with this
- // TaskQueueManager.
- virtual void SetDefaultTaskRunner(
- scoped_refptr<SingleThreadTaskRunner> task_runner) = 0;
-
- // Removes all canceled delayed tasks.
- virtual void SweepCanceledDelayedTasks() = 0;
-
- // Returns true if any task from a monitored task queue was was run since the
- // last call to GetAndClearSystemIsQuiescentBit.
- virtual bool GetAndClearSystemIsQuiescentBit() = 0;
-
- // Set the number of tasks executed in a single invocation of the task queue
- // manager. Increasing the batch size can reduce the overhead of yielding
- // back to the main message loop -- at the cost of potentially delaying other
- // tasks posted to the main loop. The batch size is 1 by default.
- virtual void SetWorkBatchSize(int work_batch_size) = 0;
-
- virtual void EnableCrashKeys(const char* file_name_crash_key,
- const char* function_name_crash_key) = 0;
-
- // Returns the portion of tasks for which CPU time is recorded or 0 if not
- // sampled.
- virtual double GetSamplingRateForRecordingCPUTime() const = 0;
-
- // Creates a task queue with the given type, |spec| and args. Must be called
- // on the thread this class was created on.
- // TODO(altimin): TaskQueueManager should not create TaskQueues.
- template <typename TaskQueueType, typename... Args>
- scoped_refptr<TaskQueueType> CreateTaskQueue(const TaskQueue::Spec& spec,
- Args&&... args) {
- scoped_refptr<TaskQueueType> task_queue(new TaskQueueType(
- CreateTaskQueueImpl(spec), spec, std::forward<Args>(args)...));
- return task_queue;
- }
-
- protected:
- virtual std::unique_ptr<internal::TaskQueueImpl> CreateTaskQueueImpl(
- const TaskQueue::Spec& spec) = 0;
-};
-
-} // namespace sequence_manager
-} // namespace base
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_MANAGER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_delegate_for_test.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_delegate_for_test.cc
deleted file mode 100644
index 371180047c7..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_delegate_for_test.cc
+++ /dev/null
@@ -1,64 +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/platform/scheduler/base/task_queue_manager_delegate_for_test.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-
-namespace base {
-namespace sequence_manager {
-
-// static
-scoped_refptr<TaskQueueManagerDelegateForTest>
-TaskQueueManagerDelegateForTest::Create(
- scoped_refptr<SingleThreadTaskRunner> task_runner,
- const TickClock* time_source) {
- return WrapRefCounted(
- new TaskQueueManagerDelegateForTest(task_runner, time_source));
-}
-
-TaskQueueManagerDelegateForTest::TaskQueueManagerDelegateForTest(
- scoped_refptr<SingleThreadTaskRunner> task_runner,
- const TickClock* time_source)
- : task_runner_(task_runner), time_source_(time_source) {}
-
-TaskQueueManagerDelegateForTest::~TaskQueueManagerDelegateForTest() {}
-
-bool TaskQueueManagerDelegateForTest::PostDelayedTask(const Location& from_here,
- OnceClosure task,
- TimeDelta delay) {
- return task_runner_->PostDelayedTask(from_here, std::move(task), delay);
-}
-
-bool TaskQueueManagerDelegateForTest::PostNonNestableDelayedTask(
- const Location& from_here,
- OnceClosure task,
- TimeDelta delay) {
- return task_runner_->PostNonNestableDelayedTask(from_here, std::move(task),
- delay);
-}
-
-bool TaskQueueManagerDelegateForTest::RunsTasksInCurrentSequence() const {
- return task_runner_->RunsTasksInCurrentSequence();
-}
-
-bool TaskQueueManagerDelegateForTest::IsNested() const {
- return false;
-}
-
-void TaskQueueManagerDelegateForTest::AddNestingObserver(
- RunLoop::NestingObserver* observer) {}
-
-void TaskQueueManagerDelegateForTest::RemoveNestingObserver(
- RunLoop::NestingObserver* observer) {}
-
-TimeTicks TaskQueueManagerDelegateForTest::NowTicks() const {
- return time_source_->NowTicks();
-}
-
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_delegate_for_test.h b/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_delegate_for_test.h
deleted file mode 100644
index b0c5f574af7..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_delegate_for_test.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_MANAGER_DELEGATE_FOR_TEST_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_MANAGER_DELEGATE_FOR_TEST_H_
-
-#include <memory>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/time/tick_clock.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager_delegate.h"
-
-namespace base {
-namespace sequence_manager {
-
-class TaskQueueManagerDelegateForTest : public TaskQueueManagerDelegate {
- public:
- static scoped_refptr<TaskQueueManagerDelegateForTest> Create(
- scoped_refptr<SingleThreadTaskRunner> task_runner,
- const TickClock* time_source);
-
- // SingleThreadTaskRunner:
- bool PostDelayedTask(const Location& from_here,
- OnceClosure task,
- TimeDelta delay) override;
- bool PostNonNestableDelayedTask(const Location& from_here,
- OnceClosure task,
- TimeDelta delay) override;
- bool RunsTasksInCurrentSequence() const override;
-
- // TaskQueueManagerDelegate:
- bool IsNested() const override;
- void AddNestingObserver(RunLoop::NestingObserver* observer) override;
- void RemoveNestingObserver(RunLoop::NestingObserver* observer) override;
-
- // TickClock:
- TimeTicks NowTicks() const override;
-
- protected:
- ~TaskQueueManagerDelegateForTest() override;
- TaskQueueManagerDelegateForTest(
- scoped_refptr<SingleThreadTaskRunner> task_runner,
- const TickClock* time_source);
-
- private:
- scoped_refptr<SingleThreadTaskRunner> task_runner_;
- const TickClock* time_source_;
-
- DISALLOW_COPY_AND_ASSIGN(TaskQueueManagerDelegateForTest);
-};
-
-} // namespace sequence_manager
-} // namespace base
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_MANAGER_DELEGATE_FOR_TEST_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl.cc
deleted file mode 100644
index 78f006450dc..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl.cc
+++ /dev/null
@@ -1,683 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl.h"
-
-#include <queue>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/bit_cast.h"
-#include "base/compiler_specific.h"
-#include "base/debug/crash_logging.h"
-#include "base/rand_util.h"
-#include "base/time/default_tick_clock.h"
-#include "base/time/tick_clock.h"
-#include "base/trace_event/trace_event.h"
-#include "third_party/blink/renderer/platform/scheduler/base/real_time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_time_observer.h"
-#include "third_party/blink/renderer/platform/scheduler/base/thread_controller_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/work_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h"
-
-namespace base {
-namespace sequence_manager {
-
-namespace {
-
-const double kLongTaskTraceEventThreshold = 0.05;
-const double kSamplingRateForRecordingCPUTime = 0.01;
-
-double MonotonicTimeInSeconds(TimeTicks time_ticks) {
- return (time_ticks - TimeTicks()).InSecondsF();
-}
-
-// Magic value to protect against memory corruption and bail out
-// early when detected.
-constexpr int kMemoryCorruptionSentinelValue = 0xdeadbeef;
-
-void SweepCanceledDelayedTasksInQueue(
- internal::TaskQueueImpl* queue,
- std::map<TimeDomain*, TimeTicks>* time_domain_now) {
- TimeDomain* time_domain = queue->GetTimeDomain();
- if (time_domain_now->find(time_domain) == time_domain_now->end())
- time_domain_now->insert(std::make_pair(time_domain, time_domain->Now()));
- queue->SweepCanceledDelayedTasks(time_domain_now->at(time_domain));
-}
-
-} // namespace
-
-// static
-std::unique_ptr<TaskQueueManager> TaskQueueManager::TakeOverCurrentThread() {
- return TaskQueueManagerImpl::TakeOverCurrentThread();
-}
-
-TaskQueueManagerImpl::TaskQueueManagerImpl(
- std::unique_ptr<internal::ThreadController> controller)
- : graceful_shutdown_helper_(new internal::GracefulQueueShutdownHelper()),
- controller_(std::move(controller)),
- memory_corruption_sentinel_(kMemoryCorruptionSentinelValue),
- weak_factory_(this) {
- // TODO(altimin): Create a sequence checker here.
- DCHECK(controller_->RunsTasksInCurrentSequence());
-
- TRACE_EVENT_WARMUP_CATEGORY("sequence_manager");
- TRACE_EVENT_WARMUP_CATEGORY(TRACE_DISABLED_BY_DEFAULT("sequence_manager"));
- TRACE_EVENT_WARMUP_CATEGORY(
- TRACE_DISABLED_BY_DEFAULT("sequence_manager.debug"));
- TRACE_EVENT_WARMUP_CATEGORY(
- TRACE_DISABLED_BY_DEFAULT("sequence_manager.verbose_snapshots"));
-
- TRACE_EVENT_OBJECT_CREATED_WITH_ID(
- TRACE_DISABLED_BY_DEFAULT("sequence_manager"), "TaskQueueManager", this);
- main_thread_only().selector.SetTaskQueueSelectorObserver(this);
-
- RegisterTimeDomain(main_thread_only().real_time_domain.get());
-
- controller_->SetSequencedTaskSource(this);
- controller_->AddNestingObserver(this);
-}
-
-TaskQueueManagerImpl::~TaskQueueManagerImpl() {
- TRACE_EVENT_OBJECT_DELETED_WITH_ID(
- TRACE_DISABLED_BY_DEFAULT("sequence_manager"), "TaskQueueManager", this);
-
- // TODO(altimin): restore default task runner automatically when
- // ThreadController is destroyed.
- controller_->RestoreDefaultTaskRunner();
-
- for (internal::TaskQueueImpl* queue : main_thread_only().active_queues) {
- main_thread_only().selector.RemoveQueue(queue);
- queue->UnregisterTaskQueue();
- }
-
- main_thread_only().active_queues.clear();
- main_thread_only().queues_to_gracefully_shutdown.clear();
-
- graceful_shutdown_helper_->OnTaskQueueManagerDeleted();
-
- main_thread_only().selector.SetTaskQueueSelectorObserver(nullptr);
- controller_->RemoveNestingObserver(this);
-}
-
-TaskQueueManagerImpl::AnyThread::AnyThread() = default;
-
-TaskQueueManagerImpl::AnyThread::~AnyThread() = default;
-
-TaskQueueManagerImpl::MainThreadOnly::MainThreadOnly()
- : random_generator(RandUint64()),
- uniform_distribution(0.0, 1.0),
- real_time_domain(new RealTimeDomain()) {}
-
-TaskQueueManagerImpl::MainThreadOnly::~MainThreadOnly() = default;
-
-std::unique_ptr<TaskQueueManagerImpl>
-TaskQueueManagerImpl::TakeOverCurrentThread() {
- return std::unique_ptr<TaskQueueManagerImpl>(
- new TaskQueueManagerImpl(internal::ThreadControllerImpl::Create(
- MessageLoop::current(), DefaultTickClock::GetInstance())));
-}
-
-void TaskQueueManagerImpl::RegisterTimeDomain(TimeDomain* time_domain) {
- main_thread_only().time_domains.insert(time_domain);
- time_domain->OnRegisterWithTaskQueueManager(this);
-}
-
-void TaskQueueManagerImpl::UnregisterTimeDomain(TimeDomain* time_domain) {
- main_thread_only().time_domains.erase(time_domain);
-}
-
-RealTimeDomain* TaskQueueManagerImpl::GetRealTimeDomain() const {
- return main_thread_only().real_time_domain.get();
-}
-
-std::unique_ptr<internal::TaskQueueImpl>
-TaskQueueManagerImpl::CreateTaskQueueImpl(const TaskQueue::Spec& spec) {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- TimeDomain* time_domain = spec.time_domain
- ? spec.time_domain
- : main_thread_only().real_time_domain.get();
- DCHECK(main_thread_only().time_domains.find(time_domain) !=
- main_thread_only().time_domains.end());
- std::unique_ptr<internal::TaskQueueImpl> task_queue =
- std::make_unique<internal::TaskQueueImpl>(this, time_domain, spec);
- main_thread_only().active_queues.insert(task_queue.get());
- main_thread_only().selector.AddQueue(task_queue.get());
- return task_queue;
-}
-
-void TaskQueueManagerImpl::SetObserver(Observer* observer) {
- main_thread_only().observer = observer;
-}
-
-void TaskQueueManagerImpl::UnregisterTaskQueueImpl(
- std::unique_ptr<internal::TaskQueueImpl> task_queue) {
- TRACE_EVENT1("sequence_manager", "TaskQueueManagerImpl::UnregisterTaskQueue",
- "queue_name", task_queue->GetName());
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
-
- main_thread_only().selector.RemoveQueue(task_queue.get());
-
- {
- AutoLock lock(any_thread_lock_);
- any_thread().has_incoming_immediate_work.erase(task_queue.get());
- }
-
- task_queue->UnregisterTaskQueue();
-
- // Add |task_queue| to |main_thread_only().queues_to_delete| so we can prevent
- // it from being freed while any of our structures hold hold a raw pointer to
- // it.
- main_thread_only().active_queues.erase(task_queue.get());
- main_thread_only().queues_to_delete[task_queue.get()] = std::move(task_queue);
-}
-
-void TaskQueueManagerImpl::ReloadEmptyWorkQueues(
- const IncomingImmediateWorkMap& queues_to_reload) const {
- // There are two cases where a queue needs reloading. First, it might be
- // completely empty and we've just posted a task (this method handles that
- // case). Secondly if the work queue becomes empty in when calling
- // WorkQueue::TakeTaskFromWorkQueue (handled there).
- for (const auto& pair : queues_to_reload) {
- pair.first->ReloadImmediateWorkQueueIfEmpty();
- }
-}
-
-void TaskQueueManagerImpl::WakeUpReadyDelayedQueues(LazyNow* lazy_now) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
- "TaskQueueManagerImpl::WakeUpReadyDelayedQueues");
-
- for (TimeDomain* time_domain : main_thread_only().time_domains) {
- if (time_domain == main_thread_only().real_time_domain.get()) {
- time_domain->WakeUpReadyDelayedQueues(lazy_now);
- } else {
- LazyNow time_domain_lazy_now = time_domain->CreateLazyNow();
- time_domain->WakeUpReadyDelayedQueues(&time_domain_lazy_now);
- }
- }
-}
-
-void TaskQueueManagerImpl::OnBeginNestedRunLoop() {
- // We just entered a nested run loop, make sure there's a DoWork posted or
- // the system will grind to a halt.
- main_thread_only().nesting_depth++;
- if (main_thread_only().observer && main_thread_only().nesting_depth == 1)
- main_thread_only().observer->OnBeginNestedRunLoop();
-}
-
-void TaskQueueManagerImpl::OnExitNestedRunLoop() {
- main_thread_only().nesting_depth--;
- DCHECK_GE(main_thread_only().nesting_depth, 0);
- if (main_thread_only().nesting_depth == 0) {
- // While we were nested some non-nestable tasks may have become eligible to
- // run. We push them back onto the front of their original work queues.
- while (!main_thread_only().non_nestable_task_queue.empty()) {
- internal::TaskQueueImpl::DeferredNonNestableTask& non_nestable_task =
- *main_thread_only().non_nestable_task_queue.begin();
- non_nestable_task.task_queue->RequeueDeferredNonNestableTask(
- std::move(non_nestable_task));
- main_thread_only().non_nestable_task_queue.pop_front();
- }
- if (main_thread_only().observer)
- main_thread_only().observer->OnExitNestedRunLoop();
- }
-}
-
-void TaskQueueManagerImpl::OnQueueHasIncomingImmediateWork(
- internal::TaskQueueImpl* queue,
- internal::EnqueueOrder enqueue_order,
- bool queue_is_blocked) {
- {
- AutoLock lock(any_thread_lock_);
- any_thread().has_incoming_immediate_work.insert(
- std::make_pair(queue, enqueue_order));
- }
-
- if (!queue_is_blocked)
- controller_->ScheduleWork();
-}
-
-void TaskQueueManagerImpl::MaybeScheduleImmediateWork(
- const Location& from_here) {
- controller_->ScheduleWork();
-}
-
-void TaskQueueManagerImpl::MaybeScheduleDelayedWork(
- const Location& from_here,
- TimeDomain* requesting_time_domain,
- TimeTicks now,
- TimeTicks run_time) {
- // TODO(kraynov): Convert time domains to use LazyNow.
- LazyNow lazy_now(now);
- controller_->SetNextDelayedDoWork(&lazy_now, run_time);
-}
-
-// TODO(kraynov): Remove after simplifying TimeDomain.
-void TaskQueueManagerImpl::CancelDelayedWork(TimeDomain* requesting_time_domain,
- TimeTicks run_time) {
- controller_->SetNextDelayedDoWork(nullptr, TimeTicks::Max());
-}
-
-Optional<PendingTask> TaskQueueManagerImpl::TakeTask() {
- CHECK(Validate());
-
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- TRACE_EVENT0("sequence_manager", "TaskQueueManagerImpl::TakeTask");
-
- IncomingImmediateWorkMap queues_to_reload;
-
- {
- AutoLock lock(any_thread_lock_);
- std::swap(queues_to_reload, any_thread().has_incoming_immediate_work);
- }
-
- // It's important we call ReloadEmptyWorkQueues out side of the lock to
- // avoid a lock order inversion.
- ReloadEmptyWorkQueues(queues_to_reload);
- LazyNow lazy_now(main_thread_only().real_time_domain->CreateLazyNow());
- WakeUpReadyDelayedQueues(&lazy_now);
-
- while (true) {
- internal::WorkQueue* work_queue = nullptr;
- bool should_run =
- main_thread_only().selector.SelectWorkQueueToService(&work_queue);
- TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
- TRACE_DISABLED_BY_DEFAULT("sequence_manager.debug"), "TaskQueueManager",
- this, AsValueWithSelectorResult(should_run, work_queue));
-
- if (!should_run)
- return nullopt;
-
- // If the head task was canceled, remove it and run the selector again.
- if (work_queue->RemoveAllCanceledTasksFromFront())
- continue;
-
- if (work_queue->GetFrontTask()->nestable == Nestable::kNonNestable &&
- main_thread_only().nesting_depth > 0) {
- // Defer non-nestable work. NOTE these tasks can be arbitrarily delayed so
- // the additional delay should not be a problem.
- // Note because we don't delete queues while nested, it's perfectly OK to
- // store the raw pointer for |queue| here.
- internal::TaskQueueImpl::DeferredNonNestableTask deferred_task{
- work_queue->TakeTaskFromWorkQueue(), work_queue->task_queue(),
- work_queue->queue_type()};
- // We push these tasks onto the front to make sure that when requeued they
- // are pushed in the right order.
- main_thread_only().non_nestable_task_queue.push_front(
- std::move(deferred_task));
- continue;
- }
-
- // Due to nested message loops we need to maintain a stack of currently
- // executing tasks so in TaskQueueManagerImpl::DidRunTask we can run the
- // right observers.
- main_thread_only().task_execution_stack.emplace_back(
- work_queue->TakeTaskFromWorkQueue(), work_queue->task_queue());
- ExecutingTask& executing_task =
- *main_thread_only().task_execution_stack.rbegin();
- NotifyWillProcessTask(&executing_task, &lazy_now);
- return std::move(executing_task.pending_task);
- }
-}
-
-void TaskQueueManagerImpl::DidRunTask() {
- LazyNow lazy_now(main_thread_only().real_time_domain->CreateLazyNow());
- ExecutingTask& executing_task =
- *main_thread_only().task_execution_stack.rbegin();
- NotifyDidProcessTask(executing_task, &lazy_now);
- main_thread_only().task_execution_stack.pop_back();
-
- if (main_thread_only().nesting_depth == 0)
- CleanUpQueues();
-}
-
-TimeDelta TaskQueueManagerImpl::DelayTillNextTask(LazyNow* lazy_now) {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
-
- // If the selector has non-empty queues we trivially know there is immediate
- // work to be done.
- if (!main_thread_only().selector.AllEnabledWorkQueuesAreEmpty())
- return TimeDelta();
-
- // Its possible the selectors state is dirty because ReloadEmptyWorkQueues
- // hasn't been called yet. This check catches the case of fresh incoming work.
- {
- AutoLock lock(any_thread_lock_);
- for (const auto& pair : any_thread().has_incoming_immediate_work) {
- if (pair.first->CouldTaskRun(pair.second))
- return TimeDelta();
- }
- }
-
- // Otherwise we need to find the shortest delay, if any. NB we don't need to
- // call WakeUpReadyDelayedQueues because it's assumed DelayTillNextTask will
- // return TimeDelta>() if the delayed task is due to run now.
- TimeDelta delay_till_next_task = TimeDelta::Max();
- for (TimeDomain* time_domain : main_thread_only().time_domains) {
- Optional<TimeDelta> delay = time_domain->DelayTillNextTask(lazy_now);
- if (!delay)
- continue;
-
- if (*delay < delay_till_next_task)
- delay_till_next_task = *delay;
- }
- return delay_till_next_task;
-}
-
-void TaskQueueManagerImpl::DidQueueTask(
- const internal::TaskQueueImpl::Task& pending_task) {
- controller_->DidQueueTask(pending_task);
-}
-
-void TaskQueueManagerImpl::NotifyWillProcessTask(ExecutingTask* executing_task,
- LazyNow* time_before_task) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
- "TaskQueueManagerImpl::NotifyWillProcessTaskObservers");
- if (executing_task->task_queue->GetQuiescenceMonitored())
- main_thread_only().task_was_run_on_quiescence_monitored_queue = true;
-
- debug::SetCrashKeyString(
- main_thread_only().file_name_crash_key,
- executing_task->pending_task.posted_from.file_name());
- debug::SetCrashKeyString(
- main_thread_only().function_name_crash_key,
- executing_task->pending_task.posted_from.function_name());
-
- if (executing_task->task_queue->GetShouldNotifyObservers()) {
- {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
- "TaskQueueManager.WillProcessTaskObservers");
- for (auto& observer : main_thread_only().task_observers)
- observer.WillProcessTask(executing_task->pending_task);
- }
-
- {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
- "TaskQueueManager.QueueNotifyWillProcessTask");
- executing_task->task_queue->NotifyWillProcessTask(
- executing_task->pending_task);
- }
-
- bool notify_time_observers =
- main_thread_only().nesting_depth == 0 &&
- (main_thread_only().task_time_observers.might_have_observers() ||
- executing_task->task_queue->RequiresTaskTiming());
- if (notify_time_observers) {
- executing_task->task_start_time = time_before_task->Now();
- double task_start_time_sec =
- MonotonicTimeInSeconds(executing_task->task_start_time);
-
- {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
- "TaskQueueManager.WillProcessTaskTimeObservers");
- for (auto& observer : main_thread_only().task_time_observers)
- observer.WillProcessTask(task_start_time_sec);
- }
-
- {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
- "TaskQueueManager.QueueOnTaskStarted");
- executing_task->task_queue->OnTaskStarted(
- executing_task->pending_task, executing_task->task_start_time);
- }
- }
- }
-
- executing_task->should_record_thread_time = ShouldRecordCPUTimeForTask();
- if (executing_task->should_record_thread_time)
- executing_task->task_start_thread_time = ThreadTicks::Now();
-}
-
-void TaskQueueManagerImpl::NotifyDidProcessTask(
- const ExecutingTask& executing_task,
- LazyNow* time_after_task) {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
- "TaskQueueManagerImpl::NotifyDidProcessTaskObservers");
-
- Optional<TimeDelta> thread_time;
- if (executing_task.should_record_thread_time) {
- auto task_end_thread_time = ThreadTicks::Now();
- thread_time = task_end_thread_time - executing_task.task_start_thread_time;
- }
-
- if (!executing_task.task_queue->GetShouldNotifyObservers())
- return;
-
- double task_start_time_sec =
- MonotonicTimeInSeconds(executing_task.task_start_time);
- double task_end_time_sec = 0;
-
- if (task_start_time_sec) {
- task_end_time_sec = MonotonicTimeInSeconds(time_after_task->Now());
-
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
- "TaskQueueManager.DidProcessTaskTimeObservers");
- for (auto& observer : main_thread_only().task_time_observers)
- observer.DidProcessTask(task_start_time_sec, task_end_time_sec);
- }
-
- {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
- "TaskQueueManager.DidProcessTaskObservers");
- for (auto& observer : main_thread_only().task_observers)
- observer.DidProcessTask(executing_task.pending_task);
- }
-
- {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
- "TaskQueueManager.QueueNotifyDidProcessTask");
- executing_task.task_queue->NotifyDidProcessTask(
- executing_task.pending_task);
- }
-
- {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
- "TaskQueueManager.QueueOnTaskCompleted");
- if (task_start_time_sec && task_end_time_sec) {
- executing_task.task_queue->OnTaskCompleted(
- executing_task.pending_task, executing_task.task_start_time,
- time_after_task->Now(), thread_time);
- }
- }
-
- if (task_start_time_sec && task_end_time_sec &&
- task_end_time_sec - task_start_time_sec > kLongTaskTraceEventThreshold) {
- TRACE_EVENT_INSTANT1("blink", "LongTask", TRACE_EVENT_SCOPE_THREAD,
- "duration", task_end_time_sec - task_start_time_sec);
- }
-}
-
-void TaskQueueManagerImpl::SetWorkBatchSize(int work_batch_size) {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- DCHECK_GE(work_batch_size, 1);
- controller_->SetWorkBatchSize(work_batch_size);
-}
-
-void TaskQueueManagerImpl::AddTaskObserver(
- MessageLoop::TaskObserver* task_observer) {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- main_thread_only().task_observers.AddObserver(task_observer);
-}
-
-void TaskQueueManagerImpl::RemoveTaskObserver(
- MessageLoop::TaskObserver* task_observer) {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- main_thread_only().task_observers.RemoveObserver(task_observer);
-}
-
-void TaskQueueManagerImpl::AddTaskTimeObserver(
- TaskTimeObserver* task_time_observer) {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- main_thread_only().task_time_observers.AddObserver(task_time_observer);
-}
-
-void TaskQueueManagerImpl::RemoveTaskTimeObserver(
- TaskTimeObserver* task_time_observer) {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- main_thread_only().task_time_observers.RemoveObserver(task_time_observer);
-}
-
-bool TaskQueueManagerImpl::GetAndClearSystemIsQuiescentBit() {
- bool task_was_run =
- main_thread_only().task_was_run_on_quiescence_monitored_queue;
- main_thread_only().task_was_run_on_quiescence_monitored_queue = false;
- return !task_was_run;
-}
-
-internal::EnqueueOrder TaskQueueManagerImpl::GetNextSequenceNumber() {
- return enqueue_order_generator_.GenerateNext();
-}
-
-LazyNow TaskQueueManagerImpl::CreateLazyNow() const {
- return LazyNow(controller_->GetClock());
-}
-
-std::unique_ptr<trace_event::ConvertableToTraceFormat>
-TaskQueueManagerImpl::AsValueWithSelectorResult(
- bool should_run,
- internal::WorkQueue* selected_work_queue) const {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- std::unique_ptr<trace_event::TracedValue> state(
- new trace_event::TracedValue());
- TimeTicks now = main_thread_only().real_time_domain->CreateLazyNow().Now();
- state->BeginArray("active_queues");
- for (auto* const queue : main_thread_only().active_queues)
- queue->AsValueInto(now, state.get());
- state->EndArray();
- state->BeginArray("queues_to_gracefully_shutdown");
- for (const auto& pair : main_thread_only().queues_to_gracefully_shutdown)
- pair.first->AsValueInto(now, state.get());
- state->EndArray();
- state->BeginArray("queues_to_delete");
- for (const auto& pair : main_thread_only().queues_to_delete)
- pair.first->AsValueInto(now, state.get());
- state->EndArray();
- state->BeginDictionary("selector");
- main_thread_only().selector.AsValueInto(state.get());
- state->EndDictionary();
- if (should_run) {
- state->SetString("selected_queue",
- selected_work_queue->task_queue()->GetName());
- state->SetString("work_queue_name", selected_work_queue->name());
- }
-
- state->BeginArray("time_domains");
- for (auto* time_domain : main_thread_only().time_domains)
- time_domain->AsValueInto(state.get());
- state->EndArray();
- {
- AutoLock lock(any_thread_lock_);
- state->BeginArray("has_incoming_immediate_work");
- for (const auto& pair : any_thread().has_incoming_immediate_work) {
- state->AppendString(pair.first->GetName());
- }
- state->EndArray();
- }
- return std::move(state);
-}
-
-void TaskQueueManagerImpl::OnTaskQueueEnabled(internal::TaskQueueImpl* queue) {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- DCHECK(queue->IsQueueEnabled());
- // Only schedule DoWork if there's something to do.
- if (queue->HasTaskToRunImmediately() && !queue->BlockedByFence())
- MaybeScheduleImmediateWork(FROM_HERE);
-}
-
-void TaskQueueManagerImpl::SweepCanceledDelayedTasks() {
- std::map<TimeDomain*, TimeTicks> time_domain_now;
- for (auto* const queue : main_thread_only().active_queues)
- SweepCanceledDelayedTasksInQueue(queue, &time_domain_now);
- for (const auto& pair : main_thread_only().queues_to_gracefully_shutdown)
- SweepCanceledDelayedTasksInQueue(pair.first, &time_domain_now);
-}
-
-void TaskQueueManagerImpl::TakeQueuesToGracefullyShutdownFromHelper() {
- std::vector<std::unique_ptr<internal::TaskQueueImpl>> queues =
- graceful_shutdown_helper_->TakeQueues();
- for (std::unique_ptr<internal::TaskQueueImpl>& queue : queues) {
- main_thread_only().queues_to_gracefully_shutdown[queue.get()] =
- std::move(queue);
- }
-}
-
-void TaskQueueManagerImpl::CleanUpQueues() {
- TakeQueuesToGracefullyShutdownFromHelper();
-
- for (auto it = main_thread_only().queues_to_gracefully_shutdown.begin();
- it != main_thread_only().queues_to_gracefully_shutdown.end();) {
- if (it->first->IsEmpty()) {
- UnregisterTaskQueueImpl(std::move(it->second));
- main_thread_only().active_queues.erase(it->first);
- main_thread_only().queues_to_gracefully_shutdown.erase(it++);
- } else {
- ++it;
- }
- }
- main_thread_only().queues_to_delete.clear();
-}
-
-scoped_refptr<internal::GracefulQueueShutdownHelper>
-TaskQueueManagerImpl::GetGracefulQueueShutdownHelper() const {
- return graceful_shutdown_helper_;
-}
-
-WeakPtr<TaskQueueManagerImpl> TaskQueueManagerImpl::GetWeakPtr() {
- return weak_factory_.GetWeakPtr();
-}
-
-void TaskQueueManagerImpl::SetDefaultTaskRunner(
- scoped_refptr<SingleThreadTaskRunner> task_runner) {
- controller_->SetDefaultTaskRunner(task_runner);
-}
-
-const TickClock* TaskQueueManagerImpl::GetClock() const {
- return controller_->GetClock();
-}
-
-TimeTicks TaskQueueManagerImpl::NowTicks() const {
- return controller_->GetClock()->NowTicks();
-}
-
-bool TaskQueueManagerImpl::ShouldRecordCPUTimeForTask() {
- return ThreadTicks::IsSupported() &&
- main_thread_only().uniform_distribution(
- main_thread_only().random_generator) <
- kSamplingRateForRecordingCPUTime;
-}
-
-double TaskQueueManagerImpl::GetSamplingRateForRecordingCPUTime() const {
- if (!ThreadTicks::IsSupported())
- return 0;
- return kSamplingRateForRecordingCPUTime;
-}
-
-MSVC_DISABLE_OPTIMIZE()
-bool TaskQueueManagerImpl::Validate() {
- return memory_corruption_sentinel_ == kMemoryCorruptionSentinelValue;
-}
-MSVC_ENABLE_OPTIMIZE()
-
-void TaskQueueManagerImpl::EnableCrashKeys(
- const char* file_name_crash_key_name,
- const char* function_name_crash_key_name) {
- DCHECK(!main_thread_only().file_name_crash_key);
- DCHECK(!main_thread_only().function_name_crash_key);
- main_thread_only().file_name_crash_key = debug::AllocateCrashKeyString(
- file_name_crash_key_name, debug::CrashKeySize::Size64);
- main_thread_only().function_name_crash_key = debug::AllocateCrashKeyString(
- function_name_crash_key_name, debug::CrashKeySize::Size64);
-}
-
-internal::TaskQueueImpl* TaskQueueManagerImpl::currently_executing_task_queue()
- const {
- if (main_thread_only().task_execution_stack.empty())
- return nullptr;
- return main_thread_only().task_execution_stack.rbegin()->task_queue;
-}
-
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl.h
deleted file mode 100644
index ba348f20b03..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl.h
+++ /dev/null
@@ -1,337 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_MANAGER_IMPL_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_MANAGER_IMPL_H_
-
-#include <list>
-#include <map>
-#include <memory>
-#include <random>
-#include <set>
-#include <unordered_map>
-#include <utility>
-
-#include "base/atomic_sequence_num.h"
-#include "base/cancelable_callback.h"
-#include "base/containers/circular_deque.h"
-#include "base/debug/task_annotator.h"
-#include "base/macros.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/pending_task.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/lock.h"
-#include "base/task/sequence_manager/thread_controller.h"
-#include "base/threading/thread_checker.h"
-#include "third_party/blink/renderer/platform/scheduler/base/enqueue_order.h"
-#include "third_party/blink/renderer/platform/scheduler/base/graceful_queue_shutdown_helper.h"
-#include "third_party/blink/renderer/platform/scheduler/base/moveable_auto_lock.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h"
-
-namespace base {
-namespace debug {
-struct CrashKeyString;
-} // namespace debug
-
-namespace trace_event {
-class ConvertableToTraceFormat;
-} // namespace trace_event
-} // namespace base
-
-namespace base {
-namespace sequence_manager {
-
-namespace internal {
-class TaskQueueImpl;
-} // namespace internal
-
-class RealTimeDomain;
-class TaskQueue;
-class TaskTimeObserver;
-class TimeDomain;
-
-// The task queue manager provides N task queues and a selector interface for
-// choosing which task queue to service next. Each task queue consists of two
-// sub queues:
-//
-// 1. Incoming task queue. Tasks that are posted get immediately appended here.
-// When a task is appended into an empty incoming queue, the task manager
-// work function (DoWork()) is scheduled to run on the main task runner.
-//
-// 2. Work queue. If a work queue is empty when DoWork() is entered, tasks from
-// the incoming task queue (if any) are moved here. The work queues are
-// registered with the selector as input to the scheduling decision.
-//
-class PLATFORM_EXPORT TaskQueueManagerImpl
- : public TaskQueueManager,
- public internal::SequencedTaskSource,
- public internal::TaskQueueSelector::Observer,
- public RunLoop::NestingObserver {
- public:
- // Keep public methods in sync with TaskQueueManager interface.
- // The general rule is to keep methods only used in scheduler/base just here
- // and not to define them in the interface.
-
- using Observer = TaskQueueManager::Observer;
-
- ~TaskQueueManagerImpl() override;
-
- // Assume direct control over current thread and create a TaskQueueManager.
- // This function should be called only once per thread.
- // This function assumes that a MessageLoop is initialized for current
- // thread.
- static std::unique_ptr<TaskQueueManagerImpl> TakeOverCurrentThread();
-
- // TaskQueueManager implementation:
- void SetObserver(Observer* observer) override;
- void AddTaskObserver(MessageLoop::TaskObserver* task_observer) override;
- void RemoveTaskObserver(MessageLoop::TaskObserver* task_observer) override;
- void AddTaskTimeObserver(TaskTimeObserver* task_time_observer) override;
- void RemoveTaskTimeObserver(TaskTimeObserver* task_time_observer) override;
- void RegisterTimeDomain(TimeDomain* time_domain) override;
- void UnregisterTimeDomain(TimeDomain* time_domain) override;
- RealTimeDomain* GetRealTimeDomain() const override;
- const TickClock* GetClock() const override;
- TimeTicks NowTicks() const override;
- void SetDefaultTaskRunner(
- scoped_refptr<SingleThreadTaskRunner> task_runner) override;
- void SweepCanceledDelayedTasks() override;
- bool GetAndClearSystemIsQuiescentBit() override;
- void SetWorkBatchSize(int work_batch_size) override;
- void EnableCrashKeys(const char* file_name_crash_key,
- const char* function_name_crash_key) override;
- double GetSamplingRateForRecordingCPUTime() const override;
-
- // Implementation of SequencedTaskSource:
- Optional<PendingTask> TakeTask() override;
- void DidRunTask() override;
- TimeDelta DelayTillNextTask(LazyNow* lazy_now) override;
-
- // Requests that a task to process work is posted on the main task runner.
- // These tasks are de-duplicated in two buckets: main-thread and all other
- // threads. This distinction is done to reduce the overhead from locks, we
- // assume the main-thread path will be hot.
- void MaybeScheduleImmediateWork(const Location& from_here);
-
- // Requests that a delayed task to process work is posted on the main task
- // runner. These delayed tasks are de-duplicated. Must be called on the thread
- // this class was created on.
- void MaybeScheduleDelayedWork(const Location& from_here,
- TimeDomain* requesting_time_domain,
- TimeTicks now,
- TimeTicks run_time);
-
- // Cancels a delayed task to process work at |run_time|, previously requested
- // with MaybeScheduleDelayedWork.
- void CancelDelayedWork(TimeDomain* requesting_time_domain,
- TimeTicks run_time);
-
- LazyNow CreateLazyNow() const;
-
- // Returns the currently executing TaskQueue if any. Must be called on the
- // thread this class was created on.
- internal::TaskQueueImpl* currently_executing_task_queue() const;
-
- // Unregisters a TaskQueue previously created by |NewTaskQueue()|.
- // No tasks will run on this queue after this call.
- void UnregisterTaskQueueImpl(
- std::unique_ptr<internal::TaskQueueImpl> task_queue);
-
- scoped_refptr<internal::GracefulQueueShutdownHelper>
- GetGracefulQueueShutdownHelper() const;
-
- WeakPtr<TaskQueueManagerImpl> GetWeakPtr();
-
- protected:
- // Create a task queue manager where |controller| controls the thread
- // on which the tasks are eventually run.
- explicit TaskQueueManagerImpl(
- std::unique_ptr<internal::ThreadController> controller);
-
- friend class internal::TaskQueueImpl;
- friend class TaskQueueManagerForTest;
-
- private:
- enum class ProcessTaskResult {
- kDeferred,
- kExecuted,
- kTaskQueueManagerDeleted,
- };
-
- using IncomingImmediateWorkMap =
- std::unordered_map<internal::TaskQueueImpl*, internal::EnqueueOrder>;
-
- struct AnyThread {
- AnyThread();
- ~AnyThread();
-
- // Task queues with newly available work on the incoming queue.
- IncomingImmediateWorkMap has_incoming_immediate_work;
- };
-
- // TaskQueueManager maintains a queue of non-nestable tasks since they're
- // uncommon and allocating an extra deque per TaskQueue will waste the memory.
- using NonNestableTaskDeque =
- circular_deque<internal::TaskQueueImpl::DeferredNonNestableTask>;
-
- // We have to track rentrancy because we support nested runloops but the
- // selector interface is unaware of those. This struct keeps track off all
- // task related state needed to make pairs of TakeTask() / DidRunTask() work.
- struct ExecutingTask {
- ExecutingTask()
- : pending_task(TaskQueue::PostedTask(OnceClosure(), Location()),
- TimeTicks(),
- 0) {}
-
- ExecutingTask(internal::TaskQueueImpl::Task&& pending_task,
- internal::TaskQueueImpl* task_queue)
- : pending_task(std::move(pending_task)), task_queue(task_queue) {}
-
- internal::TaskQueueImpl::Task pending_task;
- internal::TaskQueueImpl* task_queue = nullptr;
- TimeTicks task_start_time;
- ThreadTicks task_start_thread_time;
- bool should_record_thread_time = false;
- };
-
- struct MainThreadOnly {
- MainThreadOnly();
- ~MainThreadOnly();
-
- int nesting_depth = 0;
- NonNestableTaskDeque non_nestable_task_queue;
- // TODO(altimin): Switch to instruction pointer crash key when it's
- // available.
- debug::CrashKeyString* file_name_crash_key = nullptr;
- debug::CrashKeyString* function_name_crash_key = nullptr;
-
- std::mt19937_64 random_generator;
- std::uniform_real_distribution<double> uniform_distribution;
-
- internal::TaskQueueSelector selector;
- ObserverList<MessageLoop::TaskObserver> task_observers;
- ObserverList<TaskTimeObserver> task_time_observers;
- std::set<TimeDomain*> time_domains;
- std::unique_ptr<RealTimeDomain> real_time_domain;
-
- // List of task queues managed by this TaskQueueManager.
- // - active_queues contains queues that are still running tasks.
- // Most often they are owned by relevant TaskQueues, but
- // queues_to_gracefully_shutdown_ are included here too.
- // - queues_to_gracefully_shutdown contains queues which should be deleted
- // when they become empty.
- // - queues_to_delete contains soon-to-be-deleted queues, because some
- // internal scheduling code does not expect queues to be pulled
- // from underneath.
-
- std::set<internal::TaskQueueImpl*> active_queues;
- std::map<internal::TaskQueueImpl*, std::unique_ptr<internal::TaskQueueImpl>>
- queues_to_gracefully_shutdown;
- std::map<internal::TaskQueueImpl*, std::unique_ptr<internal::TaskQueueImpl>>
- queues_to_delete;
-
- bool task_was_run_on_quiescence_monitored_queue = false;
-
- // Due to nested runloops more than one task can be executing concurrently.
- std::list<ExecutingTask> task_execution_stack;
-
- Observer* observer = nullptr; // NOT OWNED
- };
-
- // TaskQueueSelector::Observer:
- void OnTaskQueueEnabled(internal::TaskQueueImpl* queue) override;
-
- // RunLoop::NestingObserver:
- void OnBeginNestedRunLoop() override;
- void OnExitNestedRunLoop() override;
-
- // Called by the task queue to register a new pending task.
- void DidQueueTask(const internal::TaskQueueImpl::Task& pending_task);
-
- // Delayed Tasks with run_times <= Now() are enqueued onto the work queue and
- // reloads any empty work queues.
- void WakeUpReadyDelayedQueues(LazyNow* lazy_now);
-
- void NotifyWillProcessTask(ExecutingTask* task, LazyNow* time_before_task);
- void NotifyDidProcessTask(const ExecutingTask& task,
- LazyNow* time_after_task);
-
- internal::EnqueueOrder GetNextSequenceNumber();
-
- std::unique_ptr<trace_event::ConvertableToTraceFormat>
- AsValueWithSelectorResult(bool should_run,
- internal::WorkQueue* selected_work_queue) const;
-
- // Adds |queue| to |any_thread().has_incoming_immediate_work_| and if
- // |queue_is_blocked| is false it makes sure a DoWork is posted.
- // Can be called from any thread.
- void OnQueueHasIncomingImmediateWork(internal::TaskQueueImpl* queue,
- internal::EnqueueOrder enqueue_order,
- bool queue_is_blocked);
-
- // Calls |ReloadImmediateWorkQueueIfEmpty| on all queues in
- // |queues_to_reload|.
- void ReloadEmptyWorkQueues(
- const IncomingImmediateWorkMap& queues_to_reload) const;
-
- std::unique_ptr<internal::TaskQueueImpl> CreateTaskQueueImpl(
- const TaskQueue::Spec& spec) override;
-
- void TakeQueuesToGracefullyShutdownFromHelper();
-
- // Deletes queues marked for deletion and empty queues marked for shutdown.
- void CleanUpQueues();
-
- bool ShouldRecordCPUTimeForTask();
-
- const scoped_refptr<internal::GracefulQueueShutdownHelper>
- graceful_shutdown_helper_;
-
- internal::EnqueueOrderGenerator enqueue_order_generator_;
-
- std::unique_ptr<internal::ThreadController> controller_;
-
- mutable Lock any_thread_lock_;
- AnyThread any_thread_;
-
- struct AnyThread& any_thread() {
- any_thread_lock_.AssertAcquired();
- return any_thread_;
- }
- const struct AnyThread& any_thread() const {
- any_thread_lock_.AssertAcquired();
- return any_thread_;
- }
-
- // A check to bail out early during memory corruption.
- // crbug.com/757940
- bool Validate();
-
- int32_t memory_corruption_sentinel_;
-
- THREAD_CHECKER(main_thread_checker_);
- MainThreadOnly main_thread_only_;
- MainThreadOnly& main_thread_only() {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- return main_thread_only_;
- }
- const MainThreadOnly& main_thread_only() const {
- DCHECK_CALLED_ON_VALID_THREAD(main_thread_checker_);
- return main_thread_only_;
- }
-
- WeakPtrFactory<TaskQueueManagerImpl> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(TaskQueueManagerImpl);
-};
-
-} // namespace sequence_manager
-} // namespace base
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_MANAGER_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl_unittest.cc
deleted file mode 100644
index f4c8561873a..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl_unittest.cc
+++ /dev/null
@@ -1,3220 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl.h"
-
-#include <stddef.h>
-#include <memory>
-#include <utility>
-
-#include "base/location.h"
-#include "base/memory/ref_counted_memory.h"
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_current.h"
-#include "base/optional.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "base/test/test_mock_time_task_runner.h"
-#include "base/test/test_simple_task_runner.h"
-#include "base/test/trace_event_analyzer.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/trace_event/blame_context.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/blink/renderer/platform/scheduler/base/real_time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/test_count_uses_time_source.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/test_task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/test_task_time_observer.h"
-#include "third_party/blink/renderer/platform/scheduler/base/thread_controller_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/virtual_time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/base/work_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h"
-
-using testing::AnyNumber;
-using testing::Contains;
-using testing::ElementsAre;
-using testing::ElementsAreArray;
-using testing::Mock;
-using testing::Not;
-using testing::_;
-using base::sequence_manager::internal::EnqueueOrder;
-
-namespace base {
-namespace sequence_manager {
-
-class TaskQueueManagerTestBase : public testing::Test {
- protected:
- void TearDown() override {
- // TaskQueueManager should be deleted before an underlying task runner.
- manager_.reset();
- }
-
- scoped_refptr<TestTaskQueue> CreateTaskQueue(
- TaskQueue::Spec spec = TaskQueue::Spec("test")) {
- return manager_->CreateTaskQueue<TestTaskQueue>(spec);
- }
-
- void CreateTaskQueues(size_t num_queues) {
- for (size_t i = 0; i < num_queues; i++)
- runners_.push_back(CreateTaskQueue());
- }
-
- std::unique_ptr<TaskQueueManagerForTest> manager_;
- std::vector<scoped_refptr<TestTaskQueue>> runners_;
- TimeTicks start_time_;
- TestTaskTimeObserver test_task_time_observer_;
-};
-
-// TaskQueueManagerImpl uses TestMockTimeTaskRunner which controls
-// both task execution and mock clock.
-class TaskQueueManagerTest : public TaskQueueManagerTestBase {
- public:
- void DeleteTaskQueueManagerTask() { manager_.reset(); }
-
- protected:
- void SetUp() override {
- test_task_runner_ = WrapRefCounted(new TestMockTimeTaskRunner(
- TestMockTimeTaskRunner::Type::kBoundToThread));
- // A null clock triggers some assertions.
- test_task_runner_->AdvanceMockTickClock(TimeDelta::FromMilliseconds(1));
- start_time_ = GetTickClock()->NowTicks();
-
- manager_ =
- TaskQueueManagerForTest::Create(nullptr, ThreadTaskRunnerHandle::Get(),
- test_task_runner_->GetMockTickClock());
- }
-
- const TickClock* GetTickClock() {
- return test_task_runner_->GetMockTickClock();
- }
-
- void RunPendingTasks() {
- // We should only run tasks already posted by that moment.
- RunLoop run_loop;
- test_task_runner_->PostTask(FROM_HERE, run_loop.QuitClosure());
- // TestMockTimeTaskRunner will fast-forward mock clock if necessary.
- run_loop.Run();
- }
-
- // Runs all immediate tasks until there is no more work to do and advances
- // time if there is a pending delayed task. |per_run_time_callback| is called
- // when the clock advances.
- // The only difference to FastForwardUntilNoTasksRemain is that time
- // advancing isn't driven by the test task runner, but uses time domain's
- // next scheduled run time instead. It allows us to double-check consistency
- // and allows to count such bursts of doing work, which is a test subject.
- void RunUntilManagerIsIdle(RepeatingClosure per_run_time_callback) {
- for (;;) {
- // Advance time if we've run out of immediate work to do.
- if (!manager_->HasImmediateWork()) {
- TimeTicks run_time;
- if (manager_->GetRealTimeDomain()->NextScheduledRunTime(&run_time)) {
- test_task_runner_->AdvanceMockTickClock(run_time -
- GetTickClock()->NowTicks());
- per_run_time_callback.Run();
- } else {
- break;
- }
- }
- RunPendingTasks();
- }
- }
-
- scoped_refptr<TestMockTimeTaskRunner> test_task_runner_;
-};
-
-// TaskQueueManagerImpl is being initialized with real MessageLoop
-// at cost of less control over a task runner.
-class TaskQueueManagerTestWithMessageLoop : public TaskQueueManagerTestBase {
- protected:
- void SetUp() override {
- message_loop_.reset(new MessageLoop());
- // A null clock triggers some assertions.
- mock_clock_.Advance(TimeDelta::FromMilliseconds(1));
- start_time_ = mock_clock_.NowTicks();
-
- manager_ = TaskQueueManagerForTest::Create(
- message_loop_.get(), ThreadTaskRunnerHandle::Get(), &mock_clock_);
- }
-
- const TickClock* GetTickClock() { return &mock_clock_; }
-
- std::unique_ptr<MessageLoop> message_loop_;
- SimpleTestTickClock mock_clock_;
-};
-
-class TaskQueueManagerTestWithCustomInitialization
- : public TaskQueueManagerTestWithMessageLoop {
- protected:
- void SetUp() override {}
-};
-
-void PostFromNestedRunloop(SingleThreadTaskRunner* runner,
- std::vector<std::pair<OnceClosure, bool>>* tasks) {
- for (std::pair<OnceClosure, bool>& pair : *tasks) {
- if (pair.second) {
- runner->PostTask(FROM_HERE, std::move(pair.first));
- } else {
- runner->PostNonNestableTask(FROM_HERE, std::move(pair.first));
- }
- }
- RunLoop(RunLoop::Type::kNestableTasksAllowed).RunUntilIdle();
-}
-
-void NopTask() {}
-
-TEST_F(TaskQueueManagerTestWithCustomInitialization,
- NowCalledMinimumNumberOfTimesToComputeTaskDurations) {
- message_loop_.reset(new MessageLoop());
- // This memory is managed by the TaskQueueManager, but we need to hold a
- // pointer to this object to read out how many times Now was called.
- TestCountUsesTimeSource test_count_uses_time_source;
-
- manager_ = TaskQueueManagerForTest::Create(
- nullptr, ThreadTaskRunnerHandle::Get(), &test_count_uses_time_source);
- manager_->SetWorkBatchSize(6);
- manager_->AddTaskTimeObserver(&test_task_time_observer_);
-
- for (size_t i = 0; i < 3; i++)
- runners_.push_back(CreateTaskQueue());
-
- runners_[0]->PostTask(FROM_HERE, BindOnce(&NopTask));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&NopTask));
- runners_[1]->PostTask(FROM_HERE, BindOnce(&NopTask));
- runners_[1]->PostTask(FROM_HERE, BindOnce(&NopTask));
- runners_[2]->PostTask(FROM_HERE, BindOnce(&NopTask));
- runners_[2]->PostTask(FROM_HERE, BindOnce(&NopTask));
-
- RunLoop().RunUntilIdle();
- // Now is called each time a task is queued, when first task is started
- // running, and when a task is completed. 6 * 3 = 18 calls.
- EXPECT_EQ(18, test_count_uses_time_source.now_calls_count());
-}
-
-TEST_F(TaskQueueManagerTestWithCustomInitialization,
- NowNotCalledForNestedTasks) {
- message_loop_.reset(new MessageLoop());
- // This memory is managed by the TaskQueueManager, but we need to hold a
- // pointer to this object to read out how many times Now was called.
- TestCountUsesTimeSource test_count_uses_time_source;
-
- manager_ = TaskQueueManagerForTest::Create(message_loop_.get(),
- message_loop_->task_runner(),
- &test_count_uses_time_source);
- manager_->AddTaskTimeObserver(&test_task_time_observer_);
-
- runners_.push_back(CreateTaskQueue());
-
- std::vector<std::pair<OnceClosure, bool>> tasks_to_post_from_nested_loop;
- for (int i = 0; i < 7; ++i) {
- tasks_to_post_from_nested_loop.push_back(
- std::make_pair(BindOnce(&NopTask), true));
- }
-
- runners_[0]->PostTask(
- FROM_HERE, BindOnce(&PostFromNestedRunloop, RetainedRef(runners_[0]),
- Unretained(&tasks_to_post_from_nested_loop)));
-
- RunLoop().RunUntilIdle();
- // We need to call Now twice, to measure the start and end of the outermost
- // task. We shouldn't call it for any of the nested tasks.
- // Also Now is called when a task is scheduled (8 times).
- // That brings expected call count for Now() to 2 + 8 = 10
- EXPECT_EQ(10, test_count_uses_time_source.now_calls_count());
-}
-
-void NullTask() {}
-
-void TestTask(EnqueueOrder value, std::vector<EnqueueOrder>* out_result) {
- out_result->push_back(value);
-}
-
-void DisableQueueTestTask(EnqueueOrder value,
- std::vector<EnqueueOrder>* out_result,
- TaskQueue::QueueEnabledVoter* voter) {
- out_result->push_back(value);
- voter->SetQueueEnabled(false);
-}
-
-TEST_F(TaskQueueManagerTest, SingleQueuePosting) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order));
-
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(1, 2, 3));
-}
-
-TEST_F(TaskQueueManagerTest, MultiQueuePosting) {
- CreateTaskQueues(3u);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
- runners_[1]->PostTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order));
- runners_[1]->PostTask(FROM_HERE, BindOnce(&TestTask, 4, &run_order));
- runners_[2]->PostTask(FROM_HERE, BindOnce(&TestTask, 5, &run_order));
- runners_[2]->PostTask(FROM_HERE, BindOnce(&TestTask, 6, &run_order));
-
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(1, 2, 3, 4, 5, 6));
-}
-
-TEST_F(TaskQueueManagerTestWithMessageLoop, NonNestableTaskPosting) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostNonNestableTask(FROM_HERE,
- BindOnce(&TestTask, 1, &run_order));
-
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(1));
-}
-
-TEST_F(TaskQueueManagerTestWithMessageLoop,
- NonNestableTaskExecutesInExpectedOrder) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 4, &run_order));
- runners_[0]->PostNonNestableTask(FROM_HERE,
- BindOnce(&TestTask, 5, &run_order));
-
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(1, 2, 3, 4, 5));
-}
-
-TEST_F(TaskQueueManagerTestWithMessageLoop,
- NonNestableTasksDoesntExecuteInNestedLoop) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
-
- std::vector<std::pair<OnceClosure, bool>> tasks_to_post_from_nested_loop;
- tasks_to_post_from_nested_loop.push_back(
- std::make_pair(BindOnce(&TestTask, 3, &run_order), false));
- tasks_to_post_from_nested_loop.push_back(
- std::make_pair(BindOnce(&TestTask, 4, &run_order), false));
- tasks_to_post_from_nested_loop.push_back(
- std::make_pair(BindOnce(&TestTask, 5, &run_order), true));
- tasks_to_post_from_nested_loop.push_back(
- std::make_pair(BindOnce(&TestTask, 6, &run_order), true));
-
- runners_[0]->PostTask(
- FROM_HERE, BindOnce(&PostFromNestedRunloop, RetainedRef(runners_[0]),
- Unretained(&tasks_to_post_from_nested_loop)));
-
- RunLoop().RunUntilIdle();
- // Note we expect tasks 3 & 4 to run last because they're non-nestable.
- EXPECT_THAT(run_order, ElementsAre(1, 2, 5, 6, 3, 4));
-}
-
-namespace {
-
-void InsertFenceAndPostTestTask(EnqueueOrder id,
- std::vector<EnqueueOrder>* run_order,
- scoped_refptr<TestTaskQueue> task_queue) {
- run_order->push_back(id);
- task_queue->InsertFence(TaskQueue::InsertFencePosition::kNow);
- task_queue->PostTask(FROM_HERE, BindOnce(&TestTask, id + 1, run_order));
-
- // Force reload of immediate work queue. In real life the same effect can be
- // achieved with cross-thread posting.
- task_queue->GetTaskQueueImpl()->ReloadImmediateWorkQueueIfEmpty();
-}
-
-} // namespace
-
-TEST_F(TaskQueueManagerTestWithMessageLoop, TaskQueueDisabledFromNestedLoop) {
- CreateTaskQueues(1u);
- std::vector<EnqueueOrder> run_order;
-
- std::vector<std::pair<OnceClosure, bool>> tasks_to_post_from_nested_loop;
-
- tasks_to_post_from_nested_loop.push_back(
- std::make_pair(BindOnce(&TestTask, 1, &run_order), false));
- tasks_to_post_from_nested_loop.push_back(std::make_pair(
- BindOnce(&InsertFenceAndPostTestTask, 2, &run_order, runners_[0]), true));
-
- runners_[0]->PostTask(
- FROM_HERE, BindOnce(&PostFromNestedRunloop, RetainedRef(runners_[0]),
- Unretained(&tasks_to_post_from_nested_loop)));
- RunLoop().RunUntilIdle();
-
- // Task 1 shouldn't run first due to it being non-nestable and queue gets
- // blocked after task 2. Task 1 runs after existing nested message loop
- // due to being posted before inserting a fence.
- // This test checks that breaks when nestable task is pushed into a redo
- // queue.
- EXPECT_THAT(run_order, ElementsAre(2, 1));
-
- runners_[0]->RemoveFence();
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(2, 1, 3));
-}
-
-TEST_F(TaskQueueManagerTest, HasPendingImmediateWork_ImmediateTask) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- EXPECT_TRUE(runners_[0]->HasTaskToRunImmediately());
-
- // Move the task into the |immediate_work_queue|.
- EXPECT_TRUE(runners_[0]->GetTaskQueueImpl()->immediate_work_queue()->Empty());
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
- runners_[0]->CreateQueueEnabledVoter();
- voter->SetQueueEnabled(false);
- RunLoop().RunUntilIdle();
- EXPECT_FALSE(
- runners_[0]->GetTaskQueueImpl()->immediate_work_queue()->Empty());
- EXPECT_TRUE(runners_[0]->HasTaskToRunImmediately());
-
- // Run the task, making the queue empty.
- voter->SetQueueEnabled(true);
- RunLoop().RunUntilIdle();
- EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
-}
-
-TEST_F(TaskQueueManagerTest, HasPendingImmediateWork_DelayedTask) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- TimeDelta delay(TimeDelta::FromMilliseconds(10));
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order),
- delay);
- EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
- test_task_runner_->AdvanceMockTickClock(delay);
- EXPECT_TRUE(runners_[0]->HasTaskToRunImmediately());
-
- // Move the task into the |delayed_work_queue|.
- LazyNow lazy_now(GetTickClock());
- manager_->WakeUpReadyDelayedQueues(&lazy_now);
- EXPECT_FALSE(runners_[0]->GetTaskQueueImpl()->delayed_work_queue()->Empty());
- EXPECT_TRUE(runners_[0]->HasTaskToRunImmediately());
-
- // Run the task, making the queue empty.
- RunLoop().RunUntilIdle();
- EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
-}
-
-TEST_F(TaskQueueManagerTest, DelayedTaskPosting) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- TimeDelta delay(TimeDelta::FromMilliseconds(10));
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order),
- delay);
- EXPECT_EQ(TimeDelta::FromMilliseconds(10),
- test_task_runner_->NextPendingTaskDelay());
- EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
- EXPECT_TRUE(run_order.empty());
-
- // The task doesn't run before the delay has completed.
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(9));
- EXPECT_TRUE(run_order.empty());
-
- // After the delay has completed, the task runs normally.
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(1));
- EXPECT_THAT(run_order, ElementsAre(1));
- EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
-}
-
-TEST_F(TaskQueueManagerTest, DelayedTaskExecutedInOneMessageLoopTask) {
- CreateTaskQueues(1u);
-
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask),
- TimeDelta::FromMilliseconds(10));
- RunLoop().RunUntilIdle();
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
- test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_EQ(0u, test_task_runner_->GetPendingTaskCount());
-}
-
-TEST_F(TaskQueueManagerTest, DelayedTaskPosting_MultipleTasks_DecendingOrder) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order),
- TimeDelta::FromMilliseconds(10));
-
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order),
- TimeDelta::FromMilliseconds(8));
-
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order),
- TimeDelta::FromMilliseconds(5));
-
- EXPECT_EQ(TimeDelta::FromMilliseconds(5),
- test_task_runner_->NextPendingTaskDelay());
-
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(5));
- EXPECT_THAT(run_order, ElementsAre(3));
- EXPECT_EQ(TimeDelta::FromMilliseconds(3),
- test_task_runner_->NextPendingTaskDelay());
-
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(3));
- EXPECT_THAT(run_order, ElementsAre(3, 2));
- EXPECT_EQ(TimeDelta::FromMilliseconds(2),
- test_task_runner_->NextPendingTaskDelay());
-
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(2));
- EXPECT_THAT(run_order, ElementsAre(3, 2, 1));
-}
-
-TEST_F(TaskQueueManagerTest, DelayedTaskPosting_MultipleTasks_AscendingOrder) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order),
- TimeDelta::FromMilliseconds(1));
-
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order),
- TimeDelta::FromMilliseconds(5));
-
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order),
- TimeDelta::FromMilliseconds(10));
-
- EXPECT_EQ(TimeDelta::FromMilliseconds(1),
- test_task_runner_->NextPendingTaskDelay());
-
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(1));
- EXPECT_THAT(run_order, ElementsAre(1));
- EXPECT_EQ(TimeDelta::FromMilliseconds(4),
- test_task_runner_->NextPendingTaskDelay());
-
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(4));
- EXPECT_THAT(run_order, ElementsAre(1, 2));
- EXPECT_EQ(TimeDelta::FromMilliseconds(5),
- test_task_runner_->NextPendingTaskDelay());
-
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(5));
- EXPECT_THAT(run_order, ElementsAre(1, 2, 3));
-}
-
-TEST_F(TaskQueueManagerTest, PostDelayedTask_SharesUnderlyingDelayedTasks) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- TimeDelta delay(TimeDelta::FromMilliseconds(10));
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order),
- delay);
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order),
- delay);
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order),
- delay);
-
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
-}
-
-class TestObject {
- public:
- ~TestObject() { destructor_count__++; }
-
- void Run() { FAIL() << "TestObject::Run should not be called"; }
-
- static int destructor_count__;
-};
-
-int TestObject::destructor_count__ = 0;
-
-TEST_F(TaskQueueManagerTest, PendingDelayedTasksRemovedOnShutdown) {
- CreateTaskQueues(1u);
-
- TestObject::destructor_count__ = 0;
-
- TimeDelta delay(TimeDelta::FromMilliseconds(10));
- runners_[0]->PostDelayedTask(
- FROM_HERE, BindOnce(&TestObject::Run, Owned(new TestObject())), delay);
- runners_[0]->PostTask(FROM_HERE,
- BindOnce(&TestObject::Run, Owned(new TestObject())));
-
- manager_.reset();
-
- EXPECT_EQ(2, TestObject::destructor_count__);
-}
-
-TEST_F(TaskQueueManagerTest, InsertAndRemoveFence) {
- CreateTaskQueues(1u);
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
-
- std::vector<EnqueueOrder> run_order;
- // Posting a task when pumping is disabled doesn't result in work getting
- // posted.
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- EXPECT_FALSE(test_task_runner_->HasPendingTask());
-
- // However polling still works.
- EXPECT_TRUE(runners_[0]->HasTaskToRunImmediately());
-
- // After removing the fence the task runs normally.
- runners_[0]->RemoveFence();
- EXPECT_TRUE(test_task_runner_->HasPendingTask());
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(1));
-}
-
-TEST_F(TaskQueueManagerTest, RemovingFenceForDisabledQueueDoesNotPostDoWork) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
- runners_[0]->CreateQueueEnabledVoter();
- voter->SetQueueEnabled(false);
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
-
- runners_[0]->RemoveFence();
- EXPECT_FALSE(test_task_runner_->HasPendingTask());
-}
-
-TEST_F(TaskQueueManagerTest, EnablingFencedQueueDoesNotPostDoWork) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
- runners_[0]->CreateQueueEnabledVoter();
- voter->SetQueueEnabled(false);
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
-
- voter->SetQueueEnabled(true);
- EXPECT_FALSE(test_task_runner_->HasPendingTask());
-}
-
-TEST_F(TaskQueueManagerTest, DenyRunning_BeforePosting) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
- runners_[0]->CreateQueueEnabledVoter();
- voter->SetQueueEnabled(false);
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- EXPECT_FALSE(test_task_runner_->HasPendingTask());
-
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(run_order.empty());
-
- voter->SetQueueEnabled(true);
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(1));
-}
-
-TEST_F(TaskQueueManagerTest, DenyRunning_AfterPosting) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
- runners_[0]->CreateQueueEnabledVoter();
- EXPECT_TRUE(test_task_runner_->HasPendingTask());
- voter->SetQueueEnabled(false);
-
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(run_order.empty());
-
- voter->SetQueueEnabled(true);
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(1));
-}
-
-TEST_F(TaskQueueManagerTest, DenyRunning_AfterRemovingFence) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
- runners_[0]->CreateQueueEnabledVoter();
- voter->SetQueueEnabled(false);
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
-
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(run_order.empty());
-
- runners_[0]->RemoveFence();
- voter->SetQueueEnabled(true);
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(1));
-}
-
-TEST_F(TaskQueueManagerTest, RemovingFenceWithDelayedTask) {
- CreateTaskQueues(1u);
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
-
- std::vector<EnqueueOrder> run_order;
- // Posting a delayed task when fenced will apply the delay, but won't cause
- // work to executed afterwards.
- TimeDelta delay(TimeDelta::FromMilliseconds(10));
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order),
- delay);
-
- // The task does not run even though it's delay is up.
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(10));
- EXPECT_TRUE(run_order.empty());
-
- // Removing the fence causes the task to run.
- runners_[0]->RemoveFence();
- EXPECT_TRUE(test_task_runner_->HasPendingTask());
- RunPendingTasks();
- EXPECT_THAT(run_order, ElementsAre(1));
-}
-
-TEST_F(TaskQueueManagerTest, RemovingFenceWithMultipleDelayedTasks) {
- CreateTaskQueues(1u);
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
-
- std::vector<EnqueueOrder> run_order;
- // Posting a delayed task when fenced will apply the delay, but won't cause
- // work to executed afterwards.
- TimeDelta delay1(TimeDelta::FromMilliseconds(1));
- TimeDelta delay2(TimeDelta::FromMilliseconds(10));
- TimeDelta delay3(TimeDelta::FromMilliseconds(20));
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order),
- delay1);
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order),
- delay2);
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order),
- delay3);
-
- test_task_runner_->AdvanceMockTickClock(TimeDelta::FromMilliseconds(15));
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(run_order.empty());
-
- // Removing the fence causes the ready tasks to run.
- runners_[0]->RemoveFence();
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(1, 2));
-}
-
-TEST_F(TaskQueueManagerTest, InsertFencePreventsDelayedTasksFromRunning) {
- CreateTaskQueues(1u);
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
-
- std::vector<EnqueueOrder> run_order;
- TimeDelta delay(TimeDelta::FromMilliseconds(10));
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order),
- delay);
-
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(10));
- EXPECT_TRUE(run_order.empty());
-}
-
-TEST_F(TaskQueueManagerTest, MultipleFences) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
-
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order));
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(1, 2));
-
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
- // Subsequent tasks should be blocked.
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 4, &run_order));
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(1, 2, 3));
-}
-
-TEST_F(TaskQueueManagerTest, InsertFenceThenImmediatlyRemoveDoesNotBlock) {
- CreateTaskQueues(1u);
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
- runners_[0]->RemoveFence();
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
-
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(1, 2));
-}
-
-TEST_F(TaskQueueManagerTest, InsertFencePostThenRemoveDoesNotBlock) {
- CreateTaskQueues(1u);
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
- runners_[0]->RemoveFence();
-
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(1, 2));
-}
-
-TEST_F(TaskQueueManagerTest, MultipleFencesWithInitiallyEmptyQueue) {
- CreateTaskQueues(1u);
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
-
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(1));
-}
-
-TEST_F(TaskQueueManagerTest, BlockedByFence) {
- CreateTaskQueues(1u);
- EXPECT_FALSE(runners_[0]->BlockedByFence());
-
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
- EXPECT_TRUE(runners_[0]->BlockedByFence());
-
- runners_[0]->RemoveFence();
- EXPECT_FALSE(runners_[0]->BlockedByFence());
-
- runners_[0]->PostTask(FROM_HERE, BindOnce(&NopTask));
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
- EXPECT_FALSE(runners_[0]->BlockedByFence());
-
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(runners_[0]->BlockedByFence());
-
- runners_[0]->RemoveFence();
- EXPECT_FALSE(runners_[0]->BlockedByFence());
-}
-
-TEST_F(TaskQueueManagerTest, BlockedByFence_BothTypesOfFence) {
- CreateTaskQueues(1u);
-
- runners_[0]->PostTask(FROM_HERE, BindOnce(&NopTask));
-
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
- EXPECT_FALSE(runners_[0]->BlockedByFence());
-
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kBeginningOfTime);
- EXPECT_TRUE(runners_[0]->BlockedByFence());
-}
-
-namespace {
-
-void RecordTimeTask(std::vector<TimeTicks>* run_times, const TickClock* clock) {
- run_times->push_back(clock->NowTicks());
-}
-
-void RecordTimeAndQueueTask(
- std::vector<std::pair<scoped_refptr<TestTaskQueue>, TimeTicks>>* run_times,
- scoped_refptr<TestTaskQueue> task_queue,
- const TickClock* clock) {
- run_times->emplace_back(task_queue, clock->NowTicks());
-}
-
-} // namespace
-
-TEST_F(TaskQueueManagerTest, DelayedFence_DelayedTasks) {
- CreateTaskQueues(1u);
-
- std::vector<TimeTicks> run_times;
- runners_[0]->PostDelayedTask(
- FROM_HERE, BindOnce(&RecordTimeTask, &run_times, GetTickClock()),
- TimeDelta::FromMilliseconds(100));
- runners_[0]->PostDelayedTask(
- FROM_HERE, BindOnce(&RecordTimeTask, &run_times, GetTickClock()),
- TimeDelta::FromMilliseconds(200));
- runners_[0]->PostDelayedTask(
- FROM_HERE, BindOnce(&RecordTimeTask, &run_times, GetTickClock()),
- TimeDelta::FromMilliseconds(300));
-
- runners_[0]->InsertFenceAt(GetTickClock()->NowTicks() +
- TimeDelta::FromMilliseconds(250));
- EXPECT_FALSE(runners_[0]->HasActiveFence());
-
- test_task_runner_->FastForwardUntilNoTasksRemain();
-
- EXPECT_TRUE(runners_[0]->HasActiveFence());
- EXPECT_THAT(run_times,
- ElementsAre(start_time_ + TimeDelta::FromMilliseconds(100),
- start_time_ + TimeDelta::FromMilliseconds(200)));
- run_times.clear();
-
- runners_[0]->RemoveFence();
-
- test_task_runner_->FastForwardUntilNoTasksRemain();
-
- EXPECT_FALSE(runners_[0]->HasActiveFence());
- EXPECT_THAT(run_times,
- ElementsAre(start_time_ + TimeDelta::FromMilliseconds(300)));
-}
-
-TEST_F(TaskQueueManagerTest, DelayedFence_ImmediateTasks) {
- CreateTaskQueues(1u);
-
- std::vector<TimeTicks> run_times;
- runners_[0]->InsertFenceAt(GetTickClock()->NowTicks() +
- TimeDelta::FromMilliseconds(250));
-
- for (int i = 0; i < 5; ++i) {
- runners_[0]->PostTask(
- FROM_HERE, BindOnce(&RecordTimeTask, &run_times, GetTickClock()));
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(100));
- if (i < 2) {
- EXPECT_FALSE(runners_[0]->HasActiveFence());
- } else {
- EXPECT_TRUE(runners_[0]->HasActiveFence());
- }
- }
-
- EXPECT_THAT(
- run_times,
- ElementsAre(start_time_, start_time_ + TimeDelta::FromMilliseconds(100),
- start_time_ + TimeDelta::FromMilliseconds(200)));
- run_times.clear();
-
- runners_[0]->RemoveFence();
- test_task_runner_->FastForwardUntilNoTasksRemain();
-
- EXPECT_THAT(run_times,
- ElementsAre(start_time_ + TimeDelta::FromMilliseconds(500),
- start_time_ + TimeDelta::FromMilliseconds(500)));
-}
-
-TEST_F(TaskQueueManagerTest, DelayedFence_RemovedFenceDoesNotActivate) {
- CreateTaskQueues(1u);
-
- std::vector<TimeTicks> run_times;
- runners_[0]->InsertFenceAt(GetTickClock()->NowTicks() +
- TimeDelta::FromMilliseconds(250));
-
- for (int i = 0; i < 3; ++i) {
- runners_[0]->PostTask(
- FROM_HERE, BindOnce(&RecordTimeTask, &run_times, GetTickClock()));
- EXPECT_FALSE(runners_[0]->HasActiveFence());
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(100));
- }
-
- EXPECT_TRUE(runners_[0]->HasActiveFence());
- runners_[0]->RemoveFence();
-
- for (int i = 0; i < 2; ++i) {
- runners_[0]->PostTask(
- FROM_HERE, BindOnce(&RecordTimeTask, &run_times, GetTickClock()));
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(100));
- EXPECT_FALSE(runners_[0]->HasActiveFence());
- }
-
- EXPECT_THAT(
- run_times,
- ElementsAre(start_time_, start_time_ + TimeDelta::FromMilliseconds(100),
- start_time_ + TimeDelta::FromMilliseconds(200),
- start_time_ + TimeDelta::FromMilliseconds(300),
- start_time_ + TimeDelta::FromMilliseconds(400)));
-}
-
-TEST_F(TaskQueueManagerTest, DelayedFence_TakeIncomingImmediateQueue) {
- // This test checks that everything works correctly when a work queue
- // is swapped with an immediate incoming queue and a delayed fence
- // is activated, forcing a different queue to become active.
- CreateTaskQueues(2u);
-
- scoped_refptr<TestTaskQueue> queue1 = runners_[0];
- scoped_refptr<TestTaskQueue> queue2 = runners_[1];
-
- std::vector<std::pair<scoped_refptr<TestTaskQueue>, TimeTicks>> run_times;
-
- // Fence ensures that the task posted after advancing time is blocked.
- queue1->InsertFenceAt(GetTickClock()->NowTicks() +
- TimeDelta::FromMilliseconds(250));
-
- // This task should not be blocked and should run immediately after
- // advancing time at 301ms.
- queue1->PostTask(FROM_HERE, BindOnce(&RecordTimeAndQueueTask, &run_times,
- queue1, GetTickClock()));
- // Force reload of immediate work queue. In real life the same effect can be
- // achieved with cross-thread posting.
- queue1->GetTaskQueueImpl()->ReloadImmediateWorkQueueIfEmpty();
-
- test_task_runner_->AdvanceMockTickClock(TimeDelta::FromMilliseconds(300));
-
- // This task should be blocked.
- queue1->PostTask(FROM_HERE, BindOnce(&RecordTimeAndQueueTask, &run_times,
- queue1, GetTickClock()));
- // This task on a different runner should run as expected.
- queue2->PostTask(FROM_HERE, BindOnce(&RecordTimeAndQueueTask, &run_times,
- queue2, GetTickClock()));
-
- test_task_runner_->FastForwardUntilNoTasksRemain();
-
- EXPECT_THAT(
- run_times,
- ElementsAre(std::make_pair(
- queue1, start_time_ + TimeDelta::FromMilliseconds(300)),
- std::make_pair(
- queue2, start_time_ + TimeDelta::FromMilliseconds(300))));
-}
-
-namespace {
-
-void ReentrantTestTask(scoped_refptr<SingleThreadTaskRunner> runner,
- int countdown,
- std::vector<EnqueueOrder>* out_result) {
- out_result->push_back(countdown);
- if (--countdown) {
- runner->PostTask(
- FROM_HERE, BindOnce(&ReentrantTestTask, runner, countdown, out_result));
- }
-}
-
-} // namespace
-
-TEST_F(TaskQueueManagerTest, ReentrantPosting) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostTask(
- FROM_HERE, BindOnce(&ReentrantTestTask, runners_[0], 3, &run_order));
-
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(3, 2, 1));
-}
-
-TEST_F(TaskQueueManagerTest, NoTasksAfterShutdown) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- manager_.reset();
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
-
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(run_order.empty());
-}
-
-void PostTaskToRunner(scoped_refptr<SingleThreadTaskRunner> runner,
- std::vector<EnqueueOrder>* run_order) {
- runner->PostTask(FROM_HERE, BindOnce(&TestTask, 1, run_order));
-}
-
-TEST_F(TaskQueueManagerTestWithMessageLoop, PostFromThread) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- Thread thread("TestThread");
- thread.Start();
- thread.task_runner()->PostTask(
- FROM_HERE, BindOnce(&PostTaskToRunner, runners_[0], &run_order));
- thread.Stop();
-
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(1));
-}
-
-void RePostingTestTask(scoped_refptr<SingleThreadTaskRunner> runner,
- int* run_count) {
- (*run_count)++;
- runner->PostTask(FROM_HERE, BindOnce(&RePostingTestTask,
- Unretained(runner.get()), run_count));
-}
-
-TEST_F(TaskQueueManagerTest, DoWorkCantPostItselfMultipleTimes) {
- CreateTaskQueues(1u);
-
- int run_count = 0;
- runners_[0]->PostTask(FROM_HERE,
- BindOnce(&RePostingTestTask, runners_[0], &run_count));
-
- RunPendingTasks();
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
- EXPECT_EQ(1, run_count);
-}
-
-TEST_F(TaskQueueManagerTestWithMessageLoop, PostFromNestedRunloop) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- std::vector<std::pair<OnceClosure, bool>> tasks_to_post_from_nested_loop;
- tasks_to_post_from_nested_loop.push_back(
- std::make_pair(BindOnce(&TestTask, 1, &run_order), true));
-
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 0, &run_order));
- runners_[0]->PostTask(
- FROM_HERE, BindOnce(&PostFromNestedRunloop, RetainedRef(runners_[0]),
- Unretained(&tasks_to_post_from_nested_loop)));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
-
- RunLoop().RunUntilIdle();
-
- EXPECT_THAT(run_order, ElementsAre(0, 2, 1));
-}
-
-TEST_F(TaskQueueManagerTest, WorkBatching) {
- CreateTaskQueues(1u);
-
- manager_->SetWorkBatchSize(2);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 4, &run_order));
-
- // Running one task in the host message loop should cause two posted tasks to
- // get executed.
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
- RunPendingTasks();
- EXPECT_THAT(run_order, ElementsAre(1, 2));
-
- // The second task runs the remaining two posted tasks.
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
- RunPendingTasks();
- EXPECT_THAT(run_order, ElementsAre(1, 2, 3, 4));
-}
-
-class MockTaskObserver : public MessageLoop::TaskObserver {
- public:
- MOCK_METHOD1(DidProcessTask, void(const PendingTask& task));
- MOCK_METHOD1(WillProcessTask, void(const PendingTask& task));
-};
-
-TEST_F(TaskQueueManagerTestWithMessageLoop, TaskObserverAdding) {
- CreateTaskQueues(1u);
- MockTaskObserver observer;
-
- manager_->SetWorkBatchSize(2);
- manager_->AddTaskObserver(&observer);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
-
- EXPECT_CALL(observer, WillProcessTask(_)).Times(2);
- EXPECT_CALL(observer, DidProcessTask(_)).Times(2);
- RunLoop().RunUntilIdle();
-}
-
-TEST_F(TaskQueueManagerTestWithMessageLoop, TaskObserverRemoving) {
- CreateTaskQueues(1u);
- MockTaskObserver observer;
- manager_->SetWorkBatchSize(2);
- manager_->AddTaskObserver(&observer);
- manager_->RemoveTaskObserver(&observer);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
-
- EXPECT_CALL(observer, WillProcessTask(_)).Times(0);
- EXPECT_CALL(observer, DidProcessTask(_)).Times(0);
- RunLoop().RunUntilIdle();
-}
-
-void RemoveObserverTask(TaskQueueManagerImpl* manager,
- MessageLoop::TaskObserver* observer) {
- manager->RemoveTaskObserver(observer);
-}
-
-TEST_F(TaskQueueManagerTestWithMessageLoop, TaskObserverRemovingInsideTask) {
- CreateTaskQueues(1u);
- MockTaskObserver observer;
- manager_->SetWorkBatchSize(3);
- manager_->AddTaskObserver(&observer);
-
- runners_[0]->PostTask(
- FROM_HERE, BindOnce(&RemoveObserverTask, manager_.get(), &observer));
-
- EXPECT_CALL(observer, WillProcessTask(_)).Times(1);
- EXPECT_CALL(observer, DidProcessTask(_)).Times(0);
- RunLoop().RunUntilIdle();
-}
-
-TEST_F(TaskQueueManagerTestWithMessageLoop, QueueTaskObserverAdding) {
- CreateTaskQueues(2u);
- MockTaskObserver observer;
-
- manager_->SetWorkBatchSize(2);
- runners_[0]->AddTaskObserver(&observer);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- runners_[1]->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
-
- EXPECT_CALL(observer, WillProcessTask(_)).Times(1);
- EXPECT_CALL(observer, DidProcessTask(_)).Times(1);
- RunLoop().RunUntilIdle();
-}
-
-TEST_F(TaskQueueManagerTestWithMessageLoop, QueueTaskObserverRemoving) {
- CreateTaskQueues(1u);
- MockTaskObserver observer;
- manager_->SetWorkBatchSize(2);
- runners_[0]->AddTaskObserver(&observer);
- runners_[0]->RemoveTaskObserver(&observer);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
-
- EXPECT_CALL(observer, WillProcessTask(_)).Times(0);
- EXPECT_CALL(observer, DidProcessTask(_)).Times(0);
-
- RunLoop().RunUntilIdle();
-}
-
-void RemoveQueueObserverTask(scoped_refptr<TaskQueue> queue,
- MessageLoop::TaskObserver* observer) {
- queue->RemoveTaskObserver(observer);
-}
-
-TEST_F(TaskQueueManagerTestWithMessageLoop,
- QueueTaskObserverRemovingInsideTask) {
- CreateTaskQueues(1u);
- MockTaskObserver observer;
- runners_[0]->AddTaskObserver(&observer);
-
- runners_[0]->PostTask(
- FROM_HERE, BindOnce(&RemoveQueueObserverTask, runners_[0], &observer));
-
- EXPECT_CALL(observer, WillProcessTask(_)).Times(1);
- EXPECT_CALL(observer, DidProcessTask(_)).Times(0);
- RunLoop().RunUntilIdle();
-}
-
-TEST_F(TaskQueueManagerTest, ThreadCheckAfterTermination) {
- CreateTaskQueues(1u);
- EXPECT_TRUE(runners_[0]->RunsTasksInCurrentSequence());
- manager_.reset();
- EXPECT_TRUE(runners_[0]->RunsTasksInCurrentSequence());
-}
-
-TEST_F(TaskQueueManagerTest, TimeDomain_NextScheduledRunTime) {
- CreateTaskQueues(2u);
- test_task_runner_->AdvanceMockTickClock(TimeDelta::FromMicroseconds(10000));
-
- // With no delayed tasks.
- TimeTicks run_time;
- EXPECT_FALSE(manager_->GetRealTimeDomain()->NextScheduledRunTime(&run_time));
-
- // With a non-delayed task.
- runners_[0]->PostTask(FROM_HERE, BindOnce(&NopTask));
- EXPECT_FALSE(manager_->GetRealTimeDomain()->NextScheduledRunTime(&run_time));
-
- // With a delayed task.
- TimeDelta expected_delay = TimeDelta::FromMilliseconds(50);
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask), expected_delay);
- EXPECT_TRUE(manager_->GetRealTimeDomain()->NextScheduledRunTime(&run_time));
- EXPECT_EQ(GetTickClock()->NowTicks() + expected_delay, run_time);
-
- // With another delayed task in the same queue with a longer delay.
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask),
- TimeDelta::FromMilliseconds(100));
- EXPECT_TRUE(manager_->GetRealTimeDomain()->NextScheduledRunTime(&run_time));
- EXPECT_EQ(GetTickClock()->NowTicks() + expected_delay, run_time);
-
- // With another delayed task in the same queue with a shorter delay.
- expected_delay = TimeDelta::FromMilliseconds(20);
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask), expected_delay);
- EXPECT_TRUE(manager_->GetRealTimeDomain()->NextScheduledRunTime(&run_time));
- EXPECT_EQ(GetTickClock()->NowTicks() + expected_delay, run_time);
-
- // With another delayed task in a different queue with a shorter delay.
- expected_delay = TimeDelta::FromMilliseconds(10);
- runners_[1]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask), expected_delay);
- EXPECT_TRUE(manager_->GetRealTimeDomain()->NextScheduledRunTime(&run_time));
- EXPECT_EQ(GetTickClock()->NowTicks() + expected_delay, run_time);
-
- // Test it updates as time progresses
- test_task_runner_->AdvanceMockTickClock(expected_delay);
- EXPECT_TRUE(manager_->GetRealTimeDomain()->NextScheduledRunTime(&run_time));
- EXPECT_EQ(GetTickClock()->NowTicks(), run_time);
-}
-
-TEST_F(TaskQueueManagerTest, TimeDomain_NextScheduledRunTime_MultipleQueues) {
- CreateTaskQueues(3u);
-
- TimeDelta delay1 = TimeDelta::FromMilliseconds(50);
- TimeDelta delay2 = TimeDelta::FromMilliseconds(5);
- TimeDelta delay3 = TimeDelta::FromMilliseconds(10);
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask), delay1);
- runners_[1]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask), delay2);
- runners_[2]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask), delay3);
- runners_[0]->PostTask(FROM_HERE, BindOnce(&NopTask));
-
- TimeTicks run_time;
- EXPECT_TRUE(manager_->GetRealTimeDomain()->NextScheduledRunTime(&run_time));
- EXPECT_EQ(GetTickClock()->NowTicks() + delay2, run_time);
-}
-
-TEST_F(TaskQueueManagerTest, DeleteTaskQueueManagerInsideATask) {
- CreateTaskQueues(1u);
-
- runners_[0]->PostTask(
- FROM_HERE, BindOnce(&TaskQueueManagerTest::DeleteTaskQueueManagerTask,
- Unretained(this)));
-
- // This should not crash, assuming DoWork detects the TaskQueueManager has
- // been deleted.
- RunLoop().RunUntilIdle();
-}
-
-TEST_F(TaskQueueManagerTest, GetAndClearSystemIsQuiescentBit) {
- CreateTaskQueues(3u);
-
- scoped_refptr<TaskQueue> queue0 =
- CreateTaskQueue(TaskQueue::Spec("test").SetShouldMonitorQuiescence(true));
- scoped_refptr<TaskQueue> queue1 =
- CreateTaskQueue(TaskQueue::Spec("test").SetShouldMonitorQuiescence(true));
- scoped_refptr<TaskQueue> queue2 = CreateTaskQueue();
-
- EXPECT_TRUE(manager_->GetAndClearSystemIsQuiescentBit());
-
- queue0->PostTask(FROM_HERE, BindOnce(&NopTask));
- RunLoop().RunUntilIdle();
- EXPECT_FALSE(manager_->GetAndClearSystemIsQuiescentBit());
- EXPECT_TRUE(manager_->GetAndClearSystemIsQuiescentBit());
-
- queue1->PostTask(FROM_HERE, BindOnce(&NopTask));
- RunLoop().RunUntilIdle();
- EXPECT_FALSE(manager_->GetAndClearSystemIsQuiescentBit());
- EXPECT_TRUE(manager_->GetAndClearSystemIsQuiescentBit());
-
- queue2->PostTask(FROM_HERE, BindOnce(&NopTask));
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(manager_->GetAndClearSystemIsQuiescentBit());
-
- queue0->PostTask(FROM_HERE, BindOnce(&NopTask));
- queue1->PostTask(FROM_HERE, BindOnce(&NopTask));
- RunLoop().RunUntilIdle();
- EXPECT_FALSE(manager_->GetAndClearSystemIsQuiescentBit());
- EXPECT_TRUE(manager_->GetAndClearSystemIsQuiescentBit());
-}
-
-TEST_F(TaskQueueManagerTest, HasPendingImmediateWork) {
- CreateTaskQueues(1u);
-
- EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
- runners_[0]->PostTask(FROM_HERE, BindOnce(NullTask));
- EXPECT_TRUE(runners_[0]->HasTaskToRunImmediately());
-
- RunLoop().RunUntilIdle();
- EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
-}
-
-TEST_F(TaskQueueManagerTest, HasPendingImmediateWork_DelayedTasks) {
- CreateTaskQueues(1u);
-
- EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(NullTask),
- TimeDelta::FromMilliseconds(12));
- EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
-
- // Move time forwards until just before the delayed task should run.
- test_task_runner_->AdvanceMockTickClock(TimeDelta::FromMilliseconds(10));
- LazyNow lazy_now_1(GetTickClock());
- manager_->WakeUpReadyDelayedQueues(&lazy_now_1);
- EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
-
- // Force the delayed task onto the work queue.
- test_task_runner_->AdvanceMockTickClock(TimeDelta::FromMilliseconds(2));
- LazyNow lazy_now_2(GetTickClock());
- manager_->WakeUpReadyDelayedQueues(&lazy_now_2);
- EXPECT_TRUE(runners_[0]->HasTaskToRunImmediately());
-
- RunLoop().RunUntilIdle();
- EXPECT_FALSE(runners_[0]->HasTaskToRunImmediately());
-}
-
-void ExpensiveTestTask(int value,
- scoped_refptr<TestMockTimeTaskRunner> test_task_runner,
- std::vector<EnqueueOrder>* out_result) {
- out_result->push_back(value);
- test_task_runner->FastForwardBy(TimeDelta::FromMilliseconds(1));
-}
-
-TEST_F(TaskQueueManagerTest, ImmediateAndDelayedTaskInterleaving) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- TimeDelta delay = TimeDelta::FromMilliseconds(10);
- for (int i = 10; i < 19; i++) {
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&ExpensiveTestTask, i, test_task_runner_, &run_order), delay);
- }
-
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(10));
-
- for (int i = 0; i < 9; i++) {
- runners_[0]->PostTask(FROM_HERE, BindOnce(&ExpensiveTestTask, i,
- test_task_runner_, &run_order));
- }
-
- test_task_runner_->FastForwardUntilNoTasksRemain();
-
- // Delayed tasks are not allowed to starve out immediate work which is why
- // some of the immediate tasks run out of order.
- int expected_run_order[] = {10, 11, 12, 13, 0, 14, 15, 16, 1,
- 17, 18, 2, 3, 4, 5, 6, 7, 8};
- EXPECT_THAT(run_order, ElementsAreArray(expected_run_order));
-}
-
-TEST_F(TaskQueueManagerTest,
- DelayedTaskDoesNotSkipAHeadOfNonDelayedTask_SameQueue) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
- TimeDelta delay = TimeDelta::FromMilliseconds(10);
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order));
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order),
- delay);
-
- test_task_runner_->AdvanceMockTickClock(delay * 2);
- RunLoop().RunUntilIdle();
-
- EXPECT_THAT(run_order, ElementsAre(2, 3, 1));
-}
-
-TEST_F(TaskQueueManagerTest,
- DelayedTaskDoesNotSkipAHeadOfNonDelayedTask_DifferentQueues) {
- CreateTaskQueues(2u);
-
- std::vector<EnqueueOrder> run_order;
- TimeDelta delay = TimeDelta::FromMilliseconds(10);
- runners_[1]->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
- runners_[1]->PostTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order));
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order),
- delay);
-
- test_task_runner_->AdvanceMockTickClock(delay * 2);
- RunLoop().RunUntilIdle();
-
- EXPECT_THAT(run_order, ElementsAre(2, 3, 1));
-}
-
-TEST_F(TaskQueueManagerTest, DelayedTaskDoesNotSkipAHeadOfShorterDelayedTask) {
- CreateTaskQueues(2u);
-
- std::vector<EnqueueOrder> run_order;
- TimeDelta delay1 = TimeDelta::FromMilliseconds(10);
- TimeDelta delay2 = TimeDelta::FromMilliseconds(5);
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order),
- delay1);
- runners_[1]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order),
- delay2);
-
- test_task_runner_->AdvanceMockTickClock(delay1 * 2);
- RunLoop().RunUntilIdle();
-
- EXPECT_THAT(run_order, ElementsAre(2, 1));
-}
-
-void CheckIsNested(bool* is_nested) {
- *is_nested = RunLoop::IsNestedOnCurrentThread();
-}
-
-void PostAndQuitFromNestedRunloop(RunLoop* run_loop,
- SingleThreadTaskRunner* runner,
- bool* was_nested) {
- runner->PostTask(FROM_HERE, run_loop->QuitClosure());
- runner->PostTask(FROM_HERE, BindOnce(&CheckIsNested, was_nested));
- run_loop->Run();
-}
-
-TEST_F(TaskQueueManagerTestWithMessageLoop, QuitWhileNested) {
- // This test makes sure we don't continue running a work batch after a nested
- // run loop has been exited in the middle of the batch.
- CreateTaskQueues(1u);
- manager_->SetWorkBatchSize(2);
-
- bool was_nested = true;
- RunLoop run_loop(RunLoop::Type::kNestableTasksAllowed);
- runners_[0]->PostTask(
- FROM_HERE, BindOnce(&PostAndQuitFromNestedRunloop, Unretained(&run_loop),
- RetainedRef(runners_[0]), Unretained(&was_nested)));
-
- RunLoop().RunUntilIdle();
- EXPECT_FALSE(was_nested);
-}
-
-class SequenceNumberCapturingTaskObserver : public MessageLoop::TaskObserver {
- public:
- // MessageLoop::TaskObserver overrides.
- void WillProcessTask(const PendingTask& pending_task) override {}
- void DidProcessTask(const PendingTask& pending_task) override {
- sequence_numbers_.push_back(pending_task.sequence_num);
- }
-
- const std::vector<EnqueueOrder>& sequence_numbers() const {
- return sequence_numbers_;
- }
-
- private:
- std::vector<EnqueueOrder> sequence_numbers_;
-};
-
-TEST_F(TaskQueueManagerTest, SequenceNumSetWhenTaskIsPosted) {
- CreateTaskQueues(1u);
-
- SequenceNumberCapturingTaskObserver observer;
- manager_->AddTaskObserver(&observer);
-
- // Register four tasks that will run in reverse order.
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order),
- TimeDelta::FromMilliseconds(30));
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order),
- TimeDelta::FromMilliseconds(20));
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order),
- TimeDelta::FromMilliseconds(10));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 4, &run_order));
-
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(40));
- ASSERT_THAT(run_order, ElementsAre(4, 3, 2, 1));
-
- // The sequence numbers are a one-based monotonically incrememting counter
- // which should be set when the task is posted rather than when it's enqueued
- // onto the Incoming queue. This counter starts with 2.
- EXPECT_THAT(observer.sequence_numbers(), ElementsAre(5, 4, 3, 2));
-
- manager_->RemoveTaskObserver(&observer);
-}
-
-TEST_F(TaskQueueManagerTest, NewTaskQueues) {
- CreateTaskQueues(1u);
-
- scoped_refptr<TaskQueue> queue1 = CreateTaskQueue();
- scoped_refptr<TaskQueue> queue2 = CreateTaskQueue();
- scoped_refptr<TaskQueue> queue3 = CreateTaskQueue();
-
- ASSERT_NE(queue1, queue2);
- ASSERT_NE(queue1, queue3);
- ASSERT_NE(queue2, queue3);
-
- std::vector<EnqueueOrder> run_order;
- queue1->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- queue2->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
- queue3->PostTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order));
- RunLoop().RunUntilIdle();
-
- EXPECT_THAT(run_order, ElementsAre(1, 2, 3));
-}
-
-TEST_F(TaskQueueManagerTest, ShutdownTaskQueue) {
- CreateTaskQueues(1u);
-
- scoped_refptr<TaskQueue> queue1 = CreateTaskQueue();
- scoped_refptr<TaskQueue> queue2 = CreateTaskQueue();
- scoped_refptr<TaskQueue> queue3 = CreateTaskQueue();
-
- ASSERT_NE(queue1, queue2);
- ASSERT_NE(queue1, queue3);
- ASSERT_NE(queue2, queue3);
-
- std::vector<EnqueueOrder> run_order;
- queue1->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- queue2->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
- queue3->PostTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order));
-
- queue2->ShutdownTaskQueue();
- RunLoop().RunUntilIdle();
-
- EXPECT_THAT(run_order, ElementsAre(1, 3));
-}
-
-TEST_F(TaskQueueManagerTest, ShutdownTaskQueue_WithDelayedTasks) {
- CreateTaskQueues(2u);
-
- // Register three delayed tasks
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order),
- TimeDelta::FromMilliseconds(10));
- runners_[1]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order),
- TimeDelta::FromMilliseconds(20));
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order),
- TimeDelta::FromMilliseconds(30));
-
- runners_[1]->ShutdownTaskQueue();
- RunLoop().RunUntilIdle();
-
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(40));
- ASSERT_THAT(run_order, ElementsAre(1, 3));
-}
-
-namespace {
-void ShutdownQueue(scoped_refptr<TaskQueue> queue) {
- queue->ShutdownTaskQueue();
-}
-} // namespace
-
-TEST_F(TaskQueueManagerTest, ShutdownTaskQueue_InTasks) {
- CreateTaskQueues(3u);
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&ShutdownQueue, runners_[1]));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&ShutdownQueue, runners_[2]));
- runners_[1]->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
- runners_[2]->PostTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order));
-
- RunLoop().RunUntilIdle();
- ASSERT_THAT(run_order, ElementsAre(1));
-}
-
-namespace {
-
-class MockObserver : public TaskQueueManager::Observer {
- public:
- MOCK_METHOD0(OnTriedToExecuteBlockedTask, void());
- MOCK_METHOD0(OnBeginNestedRunLoop, void());
- MOCK_METHOD0(OnExitNestedRunLoop, void());
-};
-
-} // namespace
-
-TEST_F(TaskQueueManagerTestWithMessageLoop, ShutdownTaskQueueInNestedLoop) {
- CreateTaskQueues(1u);
-
- // We retain a reference to the task queue even when the manager has deleted
- // its reference.
- scoped_refptr<TaskQueue> task_queue = CreateTaskQueue();
-
- std::vector<bool> log;
- std::vector<std::pair<OnceClosure, bool>> tasks_to_post_from_nested_loop;
-
- // Inside a nested run loop, call task_queue->ShutdownTaskQueue, bookended
- // by calls to HasOneRefTask to make sure the manager doesn't release its
- // reference until the nested run loop exits.
- // NB: This first HasOneRefTask is a sanity check.
- tasks_to_post_from_nested_loop.push_back(
- std::make_pair(BindOnce(&NopTask), true));
- tasks_to_post_from_nested_loop.push_back(std::make_pair(
- BindOnce(&TaskQueue::ShutdownTaskQueue, Unretained(task_queue.get())),
- true));
- tasks_to_post_from_nested_loop.push_back(
- std::make_pair(BindOnce(&NopTask), true));
- runners_[0]->PostTask(
- FROM_HERE, BindOnce(&PostFromNestedRunloop, RetainedRef(runners_[0]),
- Unretained(&tasks_to_post_from_nested_loop)));
- RunLoop().RunUntilIdle();
-
- // Just make sure that we don't crash.
-}
-
-TEST_F(TaskQueueManagerTest, TimeDomainsAreIndependant) {
- CreateTaskQueues(2u);
-
- TimeTicks start_time_ticks = manager_->NowTicks();
- std::unique_ptr<VirtualTimeDomain> domain_a(
- new VirtualTimeDomain(start_time_ticks));
- std::unique_ptr<VirtualTimeDomain> domain_b(
- new VirtualTimeDomain(start_time_ticks));
- manager_->RegisterTimeDomain(domain_a.get());
- manager_->RegisterTimeDomain(domain_b.get());
- runners_[0]->SetTimeDomain(domain_a.get());
- runners_[1]->SetTimeDomain(domain_b.get());
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order),
- TimeDelta::FromMilliseconds(10));
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order),
- TimeDelta::FromMilliseconds(20));
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order),
- TimeDelta::FromMilliseconds(30));
-
- runners_[1]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 4, &run_order),
- TimeDelta::FromMilliseconds(10));
- runners_[1]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 5, &run_order),
- TimeDelta::FromMilliseconds(20));
- runners_[1]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 6, &run_order),
- TimeDelta::FromMilliseconds(30));
-
- domain_b->AdvanceNowTo(start_time_ticks + TimeDelta::FromMilliseconds(50));
- manager_->MaybeScheduleImmediateWork(FROM_HERE);
-
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(4, 5, 6));
-
- domain_a->AdvanceNowTo(start_time_ticks + TimeDelta::FromMilliseconds(50));
- manager_->MaybeScheduleImmediateWork(FROM_HERE);
-
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(4, 5, 6, 1, 2, 3));
-
- runners_[0]->ShutdownTaskQueue();
- runners_[1]->ShutdownTaskQueue();
-
- manager_->UnregisterTimeDomain(domain_a.get());
- manager_->UnregisterTimeDomain(domain_b.get());
-}
-
-TEST_F(TaskQueueManagerTest, TimeDomainMigration) {
- CreateTaskQueues(1u);
-
- TimeTicks start_time_ticks = manager_->NowTicks();
- std::unique_ptr<VirtualTimeDomain> domain_a(
- new VirtualTimeDomain(start_time_ticks));
- manager_->RegisterTimeDomain(domain_a.get());
- runners_[0]->SetTimeDomain(domain_a.get());
-
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order),
- TimeDelta::FromMilliseconds(10));
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order),
- TimeDelta::FromMilliseconds(20));
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order),
- TimeDelta::FromMilliseconds(30));
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 4, &run_order),
- TimeDelta::FromMilliseconds(40));
-
- domain_a->AdvanceNowTo(start_time_ticks + TimeDelta::FromMilliseconds(20));
- manager_->MaybeScheduleImmediateWork(FROM_HERE);
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(1, 2));
-
- std::unique_ptr<VirtualTimeDomain> domain_b(
- new VirtualTimeDomain(start_time_ticks));
- manager_->RegisterTimeDomain(domain_b.get());
- runners_[0]->SetTimeDomain(domain_b.get());
-
- domain_b->AdvanceNowTo(start_time_ticks + TimeDelta::FromMilliseconds(50));
- manager_->MaybeScheduleImmediateWork(FROM_HERE);
-
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(1, 2, 3, 4));
-
- runners_[0]->ShutdownTaskQueue();
-
- manager_->UnregisterTimeDomain(domain_a.get());
- manager_->UnregisterTimeDomain(domain_b.get());
-}
-
-TEST_F(TaskQueueManagerTest, TimeDomainMigrationWithIncomingImmediateTasks) {
- CreateTaskQueues(1u);
-
- TimeTicks start_time_ticks = manager_->NowTicks();
- std::unique_ptr<VirtualTimeDomain> domain_a(
- new VirtualTimeDomain(start_time_ticks));
- std::unique_ptr<VirtualTimeDomain> domain_b(
- new VirtualTimeDomain(start_time_ticks));
- manager_->RegisterTimeDomain(domain_a.get());
- manager_->RegisterTimeDomain(domain_b.get());
-
- runners_[0]->SetTimeDomain(domain_a.get());
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- runners_[0]->SetTimeDomain(domain_b.get());
-
- RunLoop().RunUntilIdle();
- EXPECT_THAT(run_order, ElementsAre(1));
-
- runners_[0]->ShutdownTaskQueue();
-
- manager_->UnregisterTimeDomain(domain_a.get());
- manager_->UnregisterTimeDomain(domain_b.get());
-}
-
-TEST_F(TaskQueueManagerTest,
- PostDelayedTasksReverseOrderAlternatingTimeDomains) {
- CreateTaskQueues(1u);
-
- std::vector<EnqueueOrder> run_order;
-
- std::unique_ptr<RealTimeDomain> domain_a(new RealTimeDomain());
- std::unique_ptr<RealTimeDomain> domain_b(new RealTimeDomain());
- manager_->RegisterTimeDomain(domain_a.get());
- manager_->RegisterTimeDomain(domain_b.get());
-
- runners_[0]->SetTimeDomain(domain_a.get());
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order),
- TimeDelta::FromMilliseconds(40));
-
- runners_[0]->SetTimeDomain(domain_b.get());
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order),
- TimeDelta::FromMilliseconds(30));
-
- runners_[0]->SetTimeDomain(domain_a.get());
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order),
- TimeDelta::FromMilliseconds(20));
-
- runners_[0]->SetTimeDomain(domain_b.get());
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&TestTask, 4, &run_order),
- TimeDelta::FromMilliseconds(10));
-
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(40));
- EXPECT_THAT(run_order, ElementsAre(4, 3, 2, 1));
-
- runners_[0]->ShutdownTaskQueue();
-
- manager_->UnregisterTimeDomain(domain_a.get());
- manager_->UnregisterTimeDomain(domain_b.get());
-}
-
-namespace {
-
-class MockTaskQueueObserver : public TaskQueue::Observer {
- public:
- ~MockTaskQueueObserver() override = default;
-
- MOCK_METHOD2(OnQueueNextWakeUpChanged, void(TaskQueue*, TimeTicks));
-};
-
-} // namespace
-
-TEST_F(TaskQueueManagerTest, TaskQueueObserver_ImmediateTask) {
- CreateTaskQueues(1u);
-
- MockTaskQueueObserver observer;
- runners_[0]->SetObserver(&observer);
-
- // We should get a notification when a task is posted on an empty queue.
- EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[0].get(), _));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&NopTask));
- Mock::VerifyAndClearExpectations(&observer);
-
- // But not subsequently.
- EXPECT_CALL(observer, OnQueueNextWakeUpChanged(_, _)).Times(0);
- runners_[0]->PostTask(FROM_HERE, BindOnce(&NopTask));
- Mock::VerifyAndClearExpectations(&observer);
-
- // Unless the immediate work queue is emptied.
- runners_[0]->GetTaskQueueImpl()->ReloadImmediateWorkQueueIfEmpty();
- EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[0].get(), _));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&NopTask));
-
- // Tidy up.
- runners_[0]->ShutdownTaskQueue();
-}
-
-TEST_F(TaskQueueManagerTest, TaskQueueObserver_DelayedTask) {
- CreateTaskQueues(1u);
-
- TimeTicks start_time = manager_->NowTicks();
- TimeDelta delay10s(TimeDelta::FromSeconds(10));
- TimeDelta delay100s(TimeDelta::FromSeconds(100));
- TimeDelta delay1s(TimeDelta::FromSeconds(1));
-
- MockTaskQueueObserver observer;
- runners_[0]->SetObserver(&observer);
-
- // We should get a notification when a delayed task is posted on an empty
- // queue.
- EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[0].get(),
- start_time + delay10s));
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask), delay10s);
- Mock::VerifyAndClearExpectations(&observer);
-
- // We should not get a notification for a longer delay.
- EXPECT_CALL(observer, OnQueueNextWakeUpChanged(_, _)).Times(0);
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask), delay100s);
- Mock::VerifyAndClearExpectations(&observer);
-
- // We should get a notification for a shorter delay.
- EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[0].get(),
- start_time + delay1s));
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask), delay1s);
- Mock::VerifyAndClearExpectations(&observer);
-
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
- runners_[0]->CreateQueueEnabledVoter();
- voter->SetQueueEnabled(false);
- Mock::VerifyAndClearExpectations(&observer);
-
- // When a queue has been enabled, we may get a notification if the
- // TimeDomain's next scheduled wake-up has changed.
- EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[0].get(),
- start_time + delay1s));
- voter->SetQueueEnabled(true);
- Mock::VerifyAndClearExpectations(&observer);
-
- // Tidy up.
- runners_[0]->ShutdownTaskQueue();
-}
-
-TEST_F(TaskQueueManagerTest, TaskQueueObserver_DelayedTaskMultipleQueues) {
- CreateTaskQueues(2u);
-
- MockTaskQueueObserver observer;
- runners_[0]->SetObserver(&observer);
- runners_[1]->SetObserver(&observer);
-
- TimeTicks start_time = manager_->NowTicks();
- TimeDelta delay1s(TimeDelta::FromSeconds(1));
- TimeDelta delay10s(TimeDelta::FromSeconds(10));
-
- EXPECT_CALL(observer,
- OnQueueNextWakeUpChanged(runners_[0].get(), start_time + delay1s))
- .Times(1);
- EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[1].get(),
- start_time + delay10s))
- .Times(1);
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask), delay1s);
- runners_[1]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask), delay10s);
- testing::Mock::VerifyAndClearExpectations(&observer);
-
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter0 =
- runners_[0]->CreateQueueEnabledVoter();
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter1 =
- runners_[1]->CreateQueueEnabledVoter();
-
- // Disabling a queue should not trigger a notification.
- EXPECT_CALL(observer, OnQueueNextWakeUpChanged(_, _)).Times(0);
- voter0->SetQueueEnabled(false);
- Mock::VerifyAndClearExpectations(&observer);
-
- // Re-enabling it should should also trigger a notification.
- EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[0].get(),
- start_time + delay1s));
- voter0->SetQueueEnabled(true);
- Mock::VerifyAndClearExpectations(&observer);
-
- // Disabling a queue should not trigger a notification.
- EXPECT_CALL(observer, OnQueueNextWakeUpChanged(_, _)).Times(0);
- voter1->SetQueueEnabled(false);
- Mock::VerifyAndClearExpectations(&observer);
-
- // Re-enabling it should should trigger a notification.
- EXPECT_CALL(observer, OnQueueNextWakeUpChanged(runners_[1].get(),
- start_time + delay10s));
- voter1->SetQueueEnabled(true);
- Mock::VerifyAndClearExpectations(&observer);
-
- // Tidy up.
- EXPECT_CALL(observer, OnQueueNextWakeUpChanged(_, _)).Times(AnyNumber());
- runners_[0]->ShutdownTaskQueue();
- runners_[1]->ShutdownTaskQueue();
-}
-
-TEST_F(TaskQueueManagerTest, TaskQueueObserver_DelayedWorkWhichCanRunNow) {
- // This test checks that when delayed work becomes available
- // the notification still fires. This usually happens when time advances
- // and task becomes available in the middle of the scheduling code.
- // For this test we rely on the fact that notification dispatching code
- // is the same in all conditions and just change a time domain to
- // trigger notification.
-
- CreateTaskQueues(1u);
-
- TimeDelta delay1s(TimeDelta::FromSeconds(1));
- TimeDelta delay10s(TimeDelta::FromSeconds(10));
-
- MockTaskQueueObserver observer;
- runners_[0]->SetObserver(&observer);
-
- // We should get a notification when a delayed task is posted on an empty
- // queue.
- EXPECT_CALL(observer, OnQueueNextWakeUpChanged(_, _));
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask), delay1s);
- Mock::VerifyAndClearExpectations(&observer);
-
- std::unique_ptr<TimeDomain> mock_time_domain =
- std::make_unique<RealTimeDomain>();
- manager_->RegisterTimeDomain(mock_time_domain.get());
-
- test_task_runner_->AdvanceMockTickClock(delay10s);
-
- EXPECT_CALL(observer, OnQueueNextWakeUpChanged(_, _));
- runners_[0]->SetTimeDomain(mock_time_domain.get());
- Mock::VerifyAndClearExpectations(&observer);
-
- // Tidy up.
- runners_[0]->ShutdownTaskQueue();
-}
-
-class CancelableTask {
- public:
- explicit CancelableTask(const TickClock* clock)
- : clock_(clock), weak_factory_(this) {}
-
- void RecordTimeTask(std::vector<TimeTicks>* run_times) {
- run_times->push_back(clock_->NowTicks());
- }
-
- const TickClock* clock_;
- WeakPtrFactory<CancelableTask> weak_factory_;
-};
-
-TEST_F(TaskQueueManagerTest, TaskQueueObserver_SweepCanceledDelayedTasks) {
- CreateTaskQueues(1u);
-
- MockTaskQueueObserver observer;
- runners_[0]->SetObserver(&observer);
-
- TimeTicks start_time = manager_->NowTicks();
- TimeDelta delay1(TimeDelta::FromSeconds(5));
- TimeDelta delay2(TimeDelta::FromSeconds(10));
-
- EXPECT_CALL(observer,
- OnQueueNextWakeUpChanged(runners_[0].get(), start_time + delay1))
- .Times(1);
-
- CancelableTask task1(GetTickClock());
- CancelableTask task2(GetTickClock());
- std::vector<TimeTicks> run_times;
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task1.weak_factory_.GetWeakPtr(), &run_times),
- delay1);
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task2.weak_factory_.GetWeakPtr(), &run_times),
- delay2);
-
- task1.weak_factory_.InvalidateWeakPtrs();
-
- // Sweeping away canceled delayed tasks should trigger a notification.
- EXPECT_CALL(observer,
- OnQueueNextWakeUpChanged(runners_[0].get(), start_time + delay2))
- .Times(1);
- manager_->SweepCanceledDelayedTasks();
-}
-
-namespace {
-void ChromiumRunloopInspectionTask(
- scoped_refptr<TestMockTimeTaskRunner> test_task_runner) {
- // We don't expect more than 1 pending task at any time.
- EXPECT_GE(1u, test_task_runner->GetPendingTaskCount());
-}
-} // namespace
-
-TEST_F(TaskQueueManagerTest, NumberOfPendingTasksOnChromiumRunLoop) {
- CreateTaskQueues(1u);
-
- // NOTE because tasks posted to the chromiumrun loop are not cancellable, we
- // will end up with a lot more tasks posted if the delayed tasks were posted
- // in the reverse order.
- // TODO(alexclarke): Consider talking to the message pump directly.
- for (int i = 1; i < 100; i++) {
- runners_[0]->PostDelayedTask(
- FROM_HERE, BindOnce(&ChromiumRunloopInspectionTask, test_task_runner_),
- TimeDelta::FromMilliseconds(i));
- }
- test_task_runner_->FastForwardUntilNoTasksRemain();
-}
-
-namespace {
-
-class QuadraticTask {
- public:
- QuadraticTask(scoped_refptr<TaskQueue> task_queue,
- TimeDelta delay,
- scoped_refptr<TestMockTimeTaskRunner> test_task_runner)
- : count_(0),
- task_queue_(task_queue),
- delay_(delay),
- test_task_runner_(test_task_runner) {}
-
- void SetShouldExit(RepeatingCallback<bool()> should_exit) {
- should_exit_ = should_exit;
- }
-
- void Run() {
- if (should_exit_.Run())
- return;
- count_++;
- task_queue_->PostDelayedTask(
- FROM_HERE, BindOnce(&QuadraticTask::Run, Unretained(this)), delay_);
- task_queue_->PostDelayedTask(
- FROM_HERE, BindOnce(&QuadraticTask::Run, Unretained(this)), delay_);
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(5));
- }
-
- int Count() const { return count_; }
-
- private:
- int count_;
- scoped_refptr<TaskQueue> task_queue_;
- TimeDelta delay_;
- RepeatingCallback<bool()> should_exit_;
- scoped_refptr<TestMockTimeTaskRunner> test_task_runner_;
-};
-
-class LinearTask {
- public:
- LinearTask(scoped_refptr<TaskQueue> task_queue,
- TimeDelta delay,
- scoped_refptr<TestMockTimeTaskRunner> test_task_runner)
- : count_(0),
- task_queue_(task_queue),
- delay_(delay),
- test_task_runner_(test_task_runner) {}
-
- void SetShouldExit(RepeatingCallback<bool()> should_exit) {
- should_exit_ = should_exit;
- }
-
- void Run() {
- if (should_exit_.Run())
- return;
- count_++;
- task_queue_->PostDelayedTask(
- FROM_HERE, BindOnce(&LinearTask::Run, Unretained(this)), delay_);
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(5));
- }
-
- int Count() const { return count_; }
-
- private:
- int count_;
- scoped_refptr<TaskQueue> task_queue_;
- TimeDelta delay_;
- RepeatingCallback<bool()> should_exit_;
- scoped_refptr<TestMockTimeTaskRunner> test_task_runner_;
-};
-
-bool ShouldExit(QuadraticTask* quadratic_task, LinearTask* linear_task) {
- return quadratic_task->Count() == 1000 || linear_task->Count() == 1000;
-}
-
-} // namespace
-
-TEST_F(TaskQueueManagerTest,
- DelayedTasksDontBadlyStarveNonDelayedWork_SameQueue) {
- CreateTaskQueues(1u);
-
- QuadraticTask quadratic_delayed_task(
- runners_[0], TimeDelta::FromMilliseconds(10), test_task_runner_);
- LinearTask linear_immediate_task(runners_[0], TimeDelta(), test_task_runner_);
- RepeatingCallback<bool()> should_exit = BindRepeating(
- ShouldExit, &quadratic_delayed_task, &linear_immediate_task);
- quadratic_delayed_task.SetShouldExit(should_exit);
- linear_immediate_task.SetShouldExit(should_exit);
-
- quadratic_delayed_task.Run();
- linear_immediate_task.Run();
-
- test_task_runner_->FastForwardUntilNoTasksRemain();
-
- double ratio = static_cast<double>(linear_immediate_task.Count()) /
- static_cast<double>(quadratic_delayed_task.Count());
-
- EXPECT_GT(ratio, 0.333);
- EXPECT_LT(ratio, 1.1);
-}
-
-TEST_F(TaskQueueManagerTest, ImmediateWorkCanStarveDelayedTasks_SameQueue) {
- CreateTaskQueues(1u);
-
- QuadraticTask quadratic_immediate_task(runners_[0], TimeDelta(),
- test_task_runner_);
- LinearTask linear_delayed_task(runners_[0], TimeDelta::FromMilliseconds(10),
- test_task_runner_);
- RepeatingCallback<bool()> should_exit = BindRepeating(
- &ShouldExit, &quadratic_immediate_task, &linear_delayed_task);
-
- quadratic_immediate_task.SetShouldExit(should_exit);
- linear_delayed_task.SetShouldExit(should_exit);
-
- quadratic_immediate_task.Run();
- linear_delayed_task.Run();
-
- test_task_runner_->FastForwardUntilNoTasksRemain();
-
- double ratio = static_cast<double>(linear_delayed_task.Count()) /
- static_cast<double>(quadratic_immediate_task.Count());
-
- // This is by design, we want to enforce a strict ordering in task execution
- // where by delayed tasks can not skip ahead of non-delayed work.
- EXPECT_GT(ratio, 0.0);
- EXPECT_LT(ratio, 0.1);
-}
-
-TEST_F(TaskQueueManagerTest,
- DelayedTasksDontBadlyStarveNonDelayedWork_DifferentQueue) {
- CreateTaskQueues(2u);
-
- QuadraticTask quadratic_delayed_task(
- runners_[0], TimeDelta::FromMilliseconds(10), test_task_runner_);
- LinearTask linear_immediate_task(runners_[1], TimeDelta(), test_task_runner_);
- RepeatingCallback<bool()> should_exit = BindRepeating(
- ShouldExit, &quadratic_delayed_task, &linear_immediate_task);
- quadratic_delayed_task.SetShouldExit(should_exit);
- linear_immediate_task.SetShouldExit(should_exit);
-
- quadratic_delayed_task.Run();
- linear_immediate_task.Run();
-
- test_task_runner_->FastForwardUntilNoTasksRemain();
-
- double ratio = static_cast<double>(linear_immediate_task.Count()) /
- static_cast<double>(quadratic_delayed_task.Count());
-
- EXPECT_GT(ratio, 0.333);
- EXPECT_LT(ratio, 1.1);
-}
-
-TEST_F(TaskQueueManagerTest,
- ImmediateWorkCanStarveDelayedTasks_DifferentQueue) {
- CreateTaskQueues(2u);
-
- QuadraticTask quadratic_immediate_task(runners_[0], TimeDelta(),
- test_task_runner_);
- LinearTask linear_delayed_task(runners_[1], TimeDelta::FromMilliseconds(10),
- test_task_runner_);
- RepeatingCallback<bool()> should_exit = BindRepeating(
- &ShouldExit, &quadratic_immediate_task, &linear_delayed_task);
-
- quadratic_immediate_task.SetShouldExit(should_exit);
- linear_delayed_task.SetShouldExit(should_exit);
-
- quadratic_immediate_task.Run();
- linear_delayed_task.Run();
-
- test_task_runner_->FastForwardUntilNoTasksRemain();
-
- double ratio = static_cast<double>(linear_delayed_task.Count()) /
- static_cast<double>(quadratic_immediate_task.Count());
-
- // This is by design, we want to enforce a strict ordering in task execution
- // where by delayed tasks can not skip ahead of non-delayed work.
- EXPECT_GT(ratio, 0.0);
- EXPECT_LT(ratio, 0.1);
-}
-
-TEST_F(TaskQueueManagerTest, CurrentlyExecutingTaskQueue_NoTaskRunning) {
- CreateTaskQueues(1u);
-
- EXPECT_EQ(nullptr, manager_->currently_executing_task_queue());
-}
-
-namespace {
-void CurrentlyExecutingTaskQueueTestTask(
- TaskQueueManagerImpl* task_queue_manager,
- std::vector<internal::TaskQueueImpl*>* task_sources) {
- task_sources->push_back(task_queue_manager->currently_executing_task_queue());
-}
-} // namespace
-
-TEST_F(TaskQueueManagerTest, CurrentlyExecutingTaskQueue_TaskRunning) {
- CreateTaskQueues(2u);
-
- TestTaskQueue* queue0 = runners_[0].get();
- TestTaskQueue* queue1 = runners_[1].get();
-
- std::vector<internal::TaskQueueImpl*> task_sources;
- queue0->PostTask(FROM_HERE, BindOnce(&CurrentlyExecutingTaskQueueTestTask,
- manager_.get(), &task_sources));
- queue1->PostTask(FROM_HERE, BindOnce(&CurrentlyExecutingTaskQueueTestTask,
- manager_.get(), &task_sources));
- RunLoop().RunUntilIdle();
-
- EXPECT_THAT(task_sources, ElementsAre(queue0->GetTaskQueueImpl(),
- queue1->GetTaskQueueImpl()));
- EXPECT_EQ(nullptr, manager_->currently_executing_task_queue());
-}
-
-namespace {
-void RunloopCurrentlyExecutingTaskQueueTestTask(
- TaskQueueManagerImpl* task_queue_manager,
- std::vector<internal::TaskQueueImpl*>* task_sources,
- std::vector<std::pair<OnceClosure, TestTaskQueue*>>* tasks) {
- task_sources->push_back(task_queue_manager->currently_executing_task_queue());
-
- for (std::pair<OnceClosure, TestTaskQueue*>& pair : *tasks) {
- pair.second->PostTask(FROM_HERE, std::move(pair.first));
- }
-
- RunLoop(RunLoop::Type::kNestableTasksAllowed).RunUntilIdle();
- task_sources->push_back(task_queue_manager->currently_executing_task_queue());
-}
-} // namespace
-
-TEST_F(TaskQueueManagerTestWithMessageLoop,
- CurrentlyExecutingTaskQueue_NestedLoop) {
- CreateTaskQueues(3u);
-
- TestTaskQueue* queue0 = runners_[0].get();
- TestTaskQueue* queue1 = runners_[1].get();
- TestTaskQueue* queue2 = runners_[2].get();
-
- std::vector<internal::TaskQueueImpl*> task_sources;
- std::vector<std::pair<OnceClosure, TestTaskQueue*>>
- tasks_to_post_from_nested_loop;
- tasks_to_post_from_nested_loop.push_back(
- std::make_pair(BindOnce(&CurrentlyExecutingTaskQueueTestTask,
- manager_.get(), &task_sources),
- queue1));
- tasks_to_post_from_nested_loop.push_back(
- std::make_pair(BindOnce(&CurrentlyExecutingTaskQueueTestTask,
- manager_.get(), &task_sources),
- queue2));
-
- queue0->PostTask(
- FROM_HERE,
- BindOnce(&RunloopCurrentlyExecutingTaskQueueTestTask, manager_.get(),
- &task_sources, &tasks_to_post_from_nested_loop));
-
- RunLoop().RunUntilIdle();
- EXPECT_THAT(
- task_sources,
- ElementsAre(queue0->GetTaskQueueImpl(), queue1->GetTaskQueueImpl(),
- queue2->GetTaskQueueImpl(), queue0->GetTaskQueueImpl()));
- EXPECT_EQ(nullptr, manager_->currently_executing_task_queue());
-}
-
-TEST_F(TaskQueueManagerTestWithMessageLoop, BlameContextAttribution) {
- using trace_analyzer::Query;
-
- CreateTaskQueues(1u);
- TestTaskQueue* queue = runners_[0].get();
-
- trace_analyzer::Start("*");
- {
- trace_event::BlameContext blame_context("cat", "name", "type", "scope", 0,
- nullptr);
- blame_context.Initialize();
- queue->SetBlameContext(&blame_context);
- queue->PostTask(FROM_HERE, BindOnce(&NopTask));
- RunLoop().RunUntilIdle();
- }
- auto analyzer = trace_analyzer::Stop();
-
- trace_analyzer::TraceEventVector events;
- Query q = Query::EventPhaseIs(TRACE_EVENT_PHASE_ENTER_CONTEXT) ||
- Query::EventPhaseIs(TRACE_EVENT_PHASE_LEAVE_CONTEXT);
- analyzer->FindEvents(q, &events);
-
- EXPECT_EQ(2u, events.size());
-}
-
-TEST_F(TaskQueueManagerTest, NoWakeUpsForCanceledDelayedTasks) {
- CreateTaskQueues(1u);
-
- TimeTicks start_time = manager_->NowTicks();
-
- CancelableTask task1(GetTickClock());
- CancelableTask task2(GetTickClock());
- CancelableTask task3(GetTickClock());
- CancelableTask task4(GetTickClock());
- TimeDelta delay1(TimeDelta::FromSeconds(5));
- TimeDelta delay2(TimeDelta::FromSeconds(10));
- TimeDelta delay3(TimeDelta::FromSeconds(15));
- TimeDelta delay4(TimeDelta::FromSeconds(30));
- std::vector<TimeTicks> run_times;
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task1.weak_factory_.GetWeakPtr(), &run_times),
- delay1);
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task2.weak_factory_.GetWeakPtr(), &run_times),
- delay2);
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task3.weak_factory_.GetWeakPtr(), &run_times),
- delay3);
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task4.weak_factory_.GetWeakPtr(), &run_times),
- delay4);
-
- task2.weak_factory_.InvalidateWeakPtrs();
- task3.weak_factory_.InvalidateWeakPtrs();
-
- std::set<TimeTicks> wake_up_times;
-
- RunUntilManagerIsIdle(BindRepeating(
- [](std::set<TimeTicks>* wake_up_times, const TickClock* clock) {
- wake_up_times->insert(clock->NowTicks());
- },
- &wake_up_times, GetTickClock()));
-
- EXPECT_THAT(wake_up_times,
- ElementsAre(start_time + delay1, start_time + delay4));
- EXPECT_THAT(run_times, ElementsAre(start_time + delay1, start_time + delay4));
-}
-
-TEST_F(TaskQueueManagerTest, NoWakeUpsForCanceledDelayedTasksReversePostOrder) {
- CreateTaskQueues(1u);
-
- TimeTicks start_time = manager_->NowTicks();
-
- CancelableTask task1(GetTickClock());
- CancelableTask task2(GetTickClock());
- CancelableTask task3(GetTickClock());
- CancelableTask task4(GetTickClock());
- TimeDelta delay1(TimeDelta::FromSeconds(5));
- TimeDelta delay2(TimeDelta::FromSeconds(10));
- TimeDelta delay3(TimeDelta::FromSeconds(15));
- TimeDelta delay4(TimeDelta::FromSeconds(30));
- std::vector<TimeTicks> run_times;
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task4.weak_factory_.GetWeakPtr(), &run_times),
- delay4);
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task3.weak_factory_.GetWeakPtr(), &run_times),
- delay3);
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task2.weak_factory_.GetWeakPtr(), &run_times),
- delay2);
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task1.weak_factory_.GetWeakPtr(), &run_times),
- delay1);
-
- task2.weak_factory_.InvalidateWeakPtrs();
- task3.weak_factory_.InvalidateWeakPtrs();
-
- std::set<TimeTicks> wake_up_times;
-
- RunUntilManagerIsIdle(BindRepeating(
- [](std::set<TimeTicks>* wake_up_times, const TickClock* clock) {
- wake_up_times->insert(clock->NowTicks());
- },
- &wake_up_times, GetTickClock()));
-
- EXPECT_THAT(wake_up_times,
- ElementsAre(start_time + delay1, start_time + delay4));
- EXPECT_THAT(run_times, ElementsAre(start_time + delay1, start_time + delay4));
-}
-
-TEST_F(TaskQueueManagerTest, TimeDomainWakeUpOnlyCancelledIfAllUsesCancelled) {
- CreateTaskQueues(1u);
-
- TimeTicks start_time = manager_->NowTicks();
-
- CancelableTask task1(GetTickClock());
- CancelableTask task2(GetTickClock());
- CancelableTask task3(GetTickClock());
- CancelableTask task4(GetTickClock());
- TimeDelta delay1(TimeDelta::FromSeconds(5));
- TimeDelta delay2(TimeDelta::FromSeconds(10));
- TimeDelta delay3(TimeDelta::FromSeconds(15));
- TimeDelta delay4(TimeDelta::FromSeconds(30));
- std::vector<TimeTicks> run_times;
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task1.weak_factory_.GetWeakPtr(), &run_times),
- delay1);
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task2.weak_factory_.GetWeakPtr(), &run_times),
- delay2);
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task3.weak_factory_.GetWeakPtr(), &run_times),
- delay3);
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task4.weak_factory_.GetWeakPtr(), &run_times),
- delay4);
-
- // Post a non-canceled task with |delay3|. So we should still get a wake-up at
- // |delay3| even though we cancel |task3|.
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask, Unretained(&task3), &run_times),
- delay3);
-
- task2.weak_factory_.InvalidateWeakPtrs();
- task3.weak_factory_.InvalidateWeakPtrs();
- task1.weak_factory_.InvalidateWeakPtrs();
-
- std::set<TimeTicks> wake_up_times;
-
- RunUntilManagerIsIdle(BindRepeating(
- [](std::set<TimeTicks>* wake_up_times, const TickClock* clock) {
- wake_up_times->insert(clock->NowTicks());
- },
- &wake_up_times, GetTickClock()));
-
- EXPECT_THAT(wake_up_times,
- ElementsAre(start_time + delay1, start_time + delay3,
- start_time + delay4));
-
- EXPECT_THAT(run_times, ElementsAre(start_time + delay3, start_time + delay4));
-}
-
-TEST_F(TaskQueueManagerTest, TaskQueueVoters) {
- CreateTaskQueues(1u);
-
- // The task queue should be initially enabled.
- EXPECT_TRUE(runners_[0]->IsQueueEnabled());
-
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter1 =
- runners_[0]->CreateQueueEnabledVoter();
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter2 =
- runners_[0]->CreateQueueEnabledVoter();
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter3 =
- runners_[0]->CreateQueueEnabledVoter();
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter4 =
- runners_[0]->CreateQueueEnabledVoter();
-
- // Voters should initially vote for the queue to be enabled.
- EXPECT_TRUE(runners_[0]->IsQueueEnabled());
-
- // If any voter wants to disable, the queue is disabled.
- voter1->SetQueueEnabled(false);
- EXPECT_FALSE(runners_[0]->IsQueueEnabled());
-
- // If the voter is deleted then the queue should be re-enabled.
- voter1.reset();
- EXPECT_TRUE(runners_[0]->IsQueueEnabled());
-
- // If any of the remaining voters wants to disable, the queue should be
- // disabled.
- voter2->SetQueueEnabled(false);
- EXPECT_FALSE(runners_[0]->IsQueueEnabled());
-
- // If another queue votes to disable, nothing happens because it's already
- // disabled.
- voter3->SetQueueEnabled(false);
- EXPECT_FALSE(runners_[0]->IsQueueEnabled());
-
- // There are two votes to disable, so one of them voting to enable does
- // nothing.
- voter2->SetQueueEnabled(true);
- EXPECT_FALSE(runners_[0]->IsQueueEnabled());
-
- // IF all queues vote to enable then the queue is enabled.
- voter3->SetQueueEnabled(true);
- EXPECT_TRUE(runners_[0]->IsQueueEnabled());
-}
-
-TEST_F(TaskQueueManagerTest, ShutdownQueueBeforeEnabledVoterDeleted) {
- CreateTaskQueues(1u);
-
- scoped_refptr<TaskQueue> queue = CreateTaskQueue();
-
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
- queue->CreateQueueEnabledVoter();
-
- voter->SetQueueEnabled(true); // NOP
- queue->ShutdownTaskQueue();
-
- // This should complete without DCHECKing.
- voter.reset();
-}
-
-TEST_F(TaskQueueManagerTest, ShutdownQueueBeforeDisabledVoterDeleted) {
- CreateTaskQueues(1u);
-
- scoped_refptr<TaskQueue> queue = CreateTaskQueue();
-
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
- queue->CreateQueueEnabledVoter();
-
- voter->SetQueueEnabled(false);
- queue->ShutdownTaskQueue();
-
- // This should complete without DCHECKing.
- voter.reset();
-}
-
-TEST_F(TaskQueueManagerTest, SweepCanceledDelayedTasks) {
- CreateTaskQueues(1u);
-
- CancelableTask task1(GetTickClock());
- CancelableTask task2(GetTickClock());
- CancelableTask task3(GetTickClock());
- CancelableTask task4(GetTickClock());
- TimeDelta delay1(TimeDelta::FromSeconds(5));
- TimeDelta delay2(TimeDelta::FromSeconds(10));
- TimeDelta delay3(TimeDelta::FromSeconds(15));
- TimeDelta delay4(TimeDelta::FromSeconds(30));
- std::vector<TimeTicks> run_times;
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task1.weak_factory_.GetWeakPtr(), &run_times),
- delay1);
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task2.weak_factory_.GetWeakPtr(), &run_times),
- delay2);
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task3.weak_factory_.GetWeakPtr(), &run_times),
- delay3);
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task4.weak_factory_.GetWeakPtr(), &run_times),
- delay4);
-
- EXPECT_EQ(4u, runners_[0]->GetNumberOfPendingTasks());
- task2.weak_factory_.InvalidateWeakPtrs();
- task3.weak_factory_.InvalidateWeakPtrs();
- EXPECT_EQ(4u, runners_[0]->GetNumberOfPendingTasks());
-
- manager_->SweepCanceledDelayedTasks();
- EXPECT_EQ(2u, runners_[0]->GetNumberOfPendingTasks());
-
- task1.weak_factory_.InvalidateWeakPtrs();
- task4.weak_factory_.InvalidateWeakPtrs();
-
- manager_->SweepCanceledDelayedTasks();
- EXPECT_EQ(0u, runners_[0]->GetNumberOfPendingTasks());
-}
-
-TEST_F(TaskQueueManagerTest, DelayTillNextTask) {
- CreateTaskQueues(2u);
-
- LazyNow lazy_now(GetTickClock());
- EXPECT_EQ(TimeDelta::Max(), manager_->DelayTillNextTask(&lazy_now));
-
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask),
- TimeDelta::FromSeconds(10));
-
- EXPECT_EQ(TimeDelta::FromSeconds(10), manager_->DelayTillNextTask(&lazy_now));
-
- runners_[1]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask),
- TimeDelta::FromSeconds(15));
-
- EXPECT_EQ(TimeDelta::FromSeconds(10), manager_->DelayTillNextTask(&lazy_now));
-
- runners_[1]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask),
- TimeDelta::FromSeconds(5));
-
- EXPECT_EQ(TimeDelta::FromSeconds(5), manager_->DelayTillNextTask(&lazy_now));
-
- runners_[0]->PostTask(FROM_HERE, BindOnce(&NopTask));
-
- EXPECT_EQ(TimeDelta(), manager_->DelayTillNextTask(&lazy_now));
-}
-
-TEST_F(TaskQueueManagerTest, DelayTillNextTask_Disabled) {
- CreateTaskQueues(1u);
-
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
- runners_[0]->CreateQueueEnabledVoter();
- voter->SetQueueEnabled(false);
- runners_[0]->PostTask(FROM_HERE, BindOnce(&NopTask));
-
- LazyNow lazy_now(GetTickClock());
- EXPECT_EQ(TimeDelta::Max(), manager_->DelayTillNextTask(&lazy_now));
-}
-
-TEST_F(TaskQueueManagerTest, DelayTillNextTask_Fence) {
- CreateTaskQueues(1u);
-
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
- runners_[0]->PostTask(FROM_HERE, BindOnce(&NopTask));
-
- LazyNow lazy_now(GetTickClock());
- EXPECT_EQ(TimeDelta::Max(), manager_->DelayTillNextTask(&lazy_now));
-}
-
-TEST_F(TaskQueueManagerTest, DelayTillNextTask_FenceUnblocking) {
- CreateTaskQueues(1u);
-
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
- runners_[0]->PostTask(FROM_HERE, BindOnce(&NopTask));
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
-
- LazyNow lazy_now(GetTickClock());
- EXPECT_EQ(TimeDelta(), manager_->DelayTillNextTask(&lazy_now));
-}
-
-TEST_F(TaskQueueManagerTest, DelayTillNextTask_DelayedTaskReady) {
- CreateTaskQueues(1u);
-
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask),
- TimeDelta::FromSeconds(1));
-
- test_task_runner_->AdvanceMockTickClock(TimeDelta::FromSeconds(10));
-
- LazyNow lazy_now(GetTickClock());
- EXPECT_EQ(TimeDelta(), manager_->DelayTillNextTask(&lazy_now));
-}
-
-namespace {
-void MessageLoopTaskWithDelayedQuit(SimpleTestTickClock* now_src,
- scoped_refptr<TaskQueue> task_queue) {
- RunLoop run_loop(RunLoop::Type::kNestableTasksAllowed);
- task_queue->PostDelayedTask(FROM_HERE, run_loop.QuitClosure(),
- TimeDelta::FromMilliseconds(100));
- now_src->Advance(TimeDelta::FromMilliseconds(200));
- run_loop.Run();
-}
-} // namespace
-
-TEST_F(TaskQueueManagerTestWithMessageLoop,
- DelayedTaskRunsInNestedMessageLoop) {
- CreateTaskQueues(1u);
- RunLoop run_loop;
- runners_[0]->PostTask(FROM_HERE,
- BindOnce(&MessageLoopTaskWithDelayedQuit, &mock_clock_,
- RetainedRef(runners_[0])));
- run_loop.RunUntilIdle();
-}
-
-namespace {
-void MessageLoopTaskWithImmediateQuit(OnceClosure non_nested_quit_closure,
- scoped_refptr<TaskQueue> task_queue) {
- RunLoop run_loop(RunLoop::Type::kNestableTasksAllowed);
- // Needed because entering the nested run loop causes a DoWork to get
- // posted.
- task_queue->PostTask(FROM_HERE, BindOnce(&NopTask));
- task_queue->PostTask(FROM_HERE, run_loop.QuitClosure());
- run_loop.Run();
- std::move(non_nested_quit_closure).Run();
-}
-} // namespace
-
-TEST_F(TaskQueueManagerTestWithMessageLoop,
- DelayedNestedMessageLoopDoesntPreventTasksRunning) {
- CreateTaskQueues(1u);
- RunLoop run_loop;
- runners_[0]->PostDelayedTask(
- FROM_HERE,
- BindOnce(&MessageLoopTaskWithImmediateQuit, run_loop.QuitClosure(),
- RetainedRef(runners_[0])),
- TimeDelta::FromMilliseconds(100));
-
- mock_clock_.Advance(TimeDelta::FromMilliseconds(200));
- run_loop.Run();
-}
-
-TEST_F(TaskQueueManagerTest, CouldTaskRun_DisableAndReenable) {
- CreateTaskQueues(1u);
-
- EnqueueOrder enqueue_order = manager_->GetNextSequenceNumber();
- EXPECT_TRUE(runners_[0]->GetTaskQueueImpl()->CouldTaskRun(enqueue_order));
-
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
- runners_[0]->CreateQueueEnabledVoter();
- voter->SetQueueEnabled(false);
- EXPECT_FALSE(runners_[0]->GetTaskQueueImpl()->CouldTaskRun(enqueue_order));
-
- voter->SetQueueEnabled(true);
- EXPECT_TRUE(runners_[0]->GetTaskQueueImpl()->CouldTaskRun(enqueue_order));
-}
-
-TEST_F(TaskQueueManagerTest, CouldTaskRun_Fence) {
- CreateTaskQueues(1u);
-
- EnqueueOrder enqueue_order = manager_->GetNextSequenceNumber();
- EXPECT_TRUE(runners_[0]->GetTaskQueueImpl()->CouldTaskRun(enqueue_order));
-
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
- EXPECT_TRUE(runners_[0]->GetTaskQueueImpl()->CouldTaskRun(enqueue_order));
-
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kBeginningOfTime);
- EXPECT_FALSE(runners_[0]->GetTaskQueueImpl()->CouldTaskRun(enqueue_order));
-
- runners_[0]->RemoveFence();
- EXPECT_TRUE(runners_[0]->GetTaskQueueImpl()->CouldTaskRun(enqueue_order));
-}
-
-TEST_F(TaskQueueManagerTest, CouldTaskRun_FenceBeforeThenAfter) {
- CreateTaskQueues(1u);
-
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
-
- EnqueueOrder enqueue_order = manager_->GetNextSequenceNumber();
- EXPECT_FALSE(runners_[0]->GetTaskQueueImpl()->CouldTaskRun(enqueue_order));
-
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kNow);
- EXPECT_TRUE(runners_[0]->GetTaskQueueImpl()->CouldTaskRun(enqueue_order));
-}
-
-TEST_F(TaskQueueManagerTest, DelayedDoWorkNotPostedForDisabledQueue) {
- CreateTaskQueues(1u);
-
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask),
- TimeDelta::FromMilliseconds(1));
- ASSERT_TRUE(test_task_runner_->HasPendingTask());
- EXPECT_EQ(TimeDelta::FromMilliseconds(1),
- test_task_runner_->NextPendingTaskDelay());
-
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
- runners_[0]->CreateQueueEnabledVoter();
- voter->SetQueueEnabled(false);
- EXPECT_FALSE(test_task_runner_->HasPendingTask());
-
- voter->SetQueueEnabled(true);
- ASSERT_TRUE(test_task_runner_->HasPendingTask());
- EXPECT_EQ(TimeDelta::FromMilliseconds(1),
- test_task_runner_->NextPendingTaskDelay());
-}
-
-TEST_F(TaskQueueManagerTest, DisablingQueuesChangesDelayTillNextDoWork) {
- CreateTaskQueues(3u);
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask),
- TimeDelta::FromMilliseconds(1));
- runners_[1]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask),
- TimeDelta::FromMilliseconds(10));
- runners_[2]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask),
- TimeDelta::FromMilliseconds(100));
-
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter0 =
- runners_[0]->CreateQueueEnabledVoter();
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter1 =
- runners_[1]->CreateQueueEnabledVoter();
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter2 =
- runners_[2]->CreateQueueEnabledVoter();
-
- ASSERT_TRUE(test_task_runner_->HasPendingTask());
- EXPECT_EQ(TimeDelta::FromMilliseconds(1),
- test_task_runner_->NextPendingTaskDelay());
-
- voter0->SetQueueEnabled(false);
- ASSERT_TRUE(test_task_runner_->HasPendingTask());
- EXPECT_EQ(TimeDelta::FromMilliseconds(10),
- test_task_runner_->NextPendingTaskDelay());
-
- voter1->SetQueueEnabled(false);
- ASSERT_TRUE(test_task_runner_->HasPendingTask());
- EXPECT_EQ(TimeDelta::FromMilliseconds(100),
- test_task_runner_->NextPendingTaskDelay());
-
- voter2->SetQueueEnabled(false);
- EXPECT_FALSE(test_task_runner_->HasPendingTask());
-}
-
-TEST_F(TaskQueueManagerTest, GetNextScheduledWakeUp) {
- CreateTaskQueues(1u);
-
- EXPECT_EQ(nullopt, runners_[0]->GetNextScheduledWakeUp());
-
- TimeTicks start_time = manager_->NowTicks();
- TimeDelta delay1 = TimeDelta::FromMilliseconds(10);
- TimeDelta delay2 = TimeDelta::FromMilliseconds(2);
-
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask), delay1);
- EXPECT_EQ(start_time + delay1, runners_[0]->GetNextScheduledWakeUp());
-
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask), delay2);
- EXPECT_EQ(start_time + delay2, runners_[0]->GetNextScheduledWakeUp());
-
- // We don't have wake-ups scheduled for disabled queues.
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
- runners_[0]->CreateQueueEnabledVoter();
- voter->SetQueueEnabled(false);
- EXPECT_EQ(nullopt, runners_[0]->GetNextScheduledWakeUp());
-
- voter->SetQueueEnabled(true);
- EXPECT_EQ(start_time + delay2, runners_[0]->GetNextScheduledWakeUp());
-
- // Immediate tasks shouldn't make any difference.
- runners_[0]->PostTask(FROM_HERE, BindOnce(&NopTask));
- EXPECT_EQ(start_time + delay2, runners_[0]->GetNextScheduledWakeUp());
-
- // Neither should fences.
- runners_[0]->InsertFence(TaskQueue::InsertFencePosition::kBeginningOfTime);
- EXPECT_EQ(start_time + delay2, runners_[0]->GetNextScheduledWakeUp());
-}
-
-TEST_F(TaskQueueManagerTest, SetTimeDomainForDisabledQueue) {
- CreateTaskQueues(1u);
-
- MockTaskQueueObserver observer;
- runners_[0]->SetObserver(&observer);
-
- runners_[0]->PostDelayedTask(FROM_HERE, BindOnce(&NopTask),
- TimeDelta::FromMilliseconds(1));
-
- std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
- runners_[0]->CreateQueueEnabledVoter();
- voter->SetQueueEnabled(false);
-
- // We should not get a notification for a disabled queue.
- EXPECT_CALL(observer, OnQueueNextWakeUpChanged(_, _)).Times(0);
-
- std::unique_ptr<VirtualTimeDomain> domain(
- new VirtualTimeDomain(manager_->NowTicks()));
- manager_->RegisterTimeDomain(domain.get());
- runners_[0]->SetTimeDomain(domain.get());
-
- // Tidy up.
- runners_[0]->ShutdownTaskQueue();
- manager_->UnregisterTimeDomain(domain.get());
-}
-
-namespace {
-void SetOnTaskHandlers(scoped_refptr<TestTaskQueue> task_queue,
- int* start_counter,
- int* complete_counter) {
- task_queue->GetTaskQueueImpl()->SetOnTaskStartedHandler(
- BindRepeating([](int* counter, const TaskQueue::Task& task,
- TimeTicks start) { ++(*counter); },
- start_counter));
- task_queue->GetTaskQueueImpl()->SetOnTaskCompletedHandler(BindRepeating(
- [](int* counter, const TaskQueue::Task& task, TimeTicks start,
- TimeTicks end, Optional<TimeDelta> thread_time) { ++(*counter); },
- complete_counter));
-}
-
-void UnsetOnTaskHandlers(scoped_refptr<TestTaskQueue> task_queue) {
- task_queue->GetTaskQueueImpl()->SetOnTaskStartedHandler(
- RepeatingCallback<void(const TaskQueue::Task& task, TimeTicks start)>());
- task_queue->GetTaskQueueImpl()->SetOnTaskCompletedHandler(
- RepeatingCallback<void(const TaskQueue::Task& task, TimeTicks start,
- TimeTicks end,
- Optional<TimeDelta> thread_time)>());
-}
-} // namespace
-
-TEST_F(TaskQueueManagerTest, ProcessTasksWithoutTaskTimeObservers) {
- CreateTaskQueues(1u);
- int start_counter = 0;
- int complete_counter = 0;
- std::vector<EnqueueOrder> run_order;
- SetOnTaskHandlers(runners_[0], &start_counter, &complete_counter);
- EXPECT_TRUE(runners_[0]->GetTaskQueueImpl()->RequiresTaskTiming());
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order));
-
- RunLoop().RunUntilIdle();
- EXPECT_EQ(start_counter, 3);
- EXPECT_EQ(complete_counter, 3);
- EXPECT_THAT(run_order, ElementsAre(1, 2, 3));
-
- UnsetOnTaskHandlers(runners_[0]);
- EXPECT_FALSE(runners_[0]->GetTaskQueueImpl()->RequiresTaskTiming());
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 4, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 5, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 6, &run_order));
-
- RunLoop().RunUntilIdle();
- EXPECT_EQ(start_counter, 3);
- EXPECT_EQ(complete_counter, 3);
- EXPECT_THAT(run_order, ElementsAre(1, 2, 3, 4, 5, 6));
-}
-
-TEST_F(TaskQueueManagerTest, ProcessTasksWithTaskTimeObservers) {
- CreateTaskQueues(1u);
- int start_counter = 0;
- int complete_counter = 0;
-
- manager_->AddTaskTimeObserver(&test_task_time_observer_);
- SetOnTaskHandlers(runners_[0], &start_counter, &complete_counter);
- EXPECT_TRUE(runners_[0]->GetTaskQueueImpl()->RequiresTaskTiming());
- std::vector<EnqueueOrder> run_order;
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
-
- RunLoop().RunUntilIdle();
- EXPECT_EQ(start_counter, 2);
- EXPECT_EQ(complete_counter, 2);
- EXPECT_THAT(run_order, ElementsAre(1, 2));
-
- UnsetOnTaskHandlers(runners_[0]);
- EXPECT_FALSE(runners_[0]->GetTaskQueueImpl()->RequiresTaskTiming());
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 3, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 4, &run_order));
-
- RunLoop().RunUntilIdle();
- EXPECT_EQ(start_counter, 2);
- EXPECT_EQ(complete_counter, 2);
- EXPECT_THAT(run_order, ElementsAre(1, 2, 3, 4));
-
- manager_->RemoveTaskTimeObserver(&test_task_time_observer_);
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 5, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 6, &run_order));
-
- RunLoop().RunUntilIdle();
- EXPECT_EQ(start_counter, 2);
- EXPECT_EQ(complete_counter, 2);
- EXPECT_FALSE(runners_[0]->GetTaskQueueImpl()->RequiresTaskTiming());
- EXPECT_THAT(run_order, ElementsAre(1, 2, 3, 4, 5, 6));
-
- SetOnTaskHandlers(runners_[0], &start_counter, &complete_counter);
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 7, &run_order));
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 8, &run_order));
-
- RunLoop().RunUntilIdle();
- EXPECT_EQ(start_counter, 4);
- EXPECT_EQ(complete_counter, 4);
- EXPECT_TRUE(runners_[0]->GetTaskQueueImpl()->RequiresTaskTiming());
- EXPECT_THAT(run_order, ElementsAre(1, 2, 3, 4, 5, 6, 7, 8));
- UnsetOnTaskHandlers(runners_[0]);
-}
-
-TEST_F(TaskQueueManagerTest, GracefulShutdown) {
- std::vector<TimeTicks> run_times;
- scoped_refptr<TestTaskQueue> main_tq = CreateTaskQueue();
- WeakPtr<TestTaskQueue> main_tq_weak_ptr = main_tq->GetWeakPtr();
-
- EXPECT_EQ(1u, manager_->ActiveQueuesCount());
- EXPECT_EQ(0u, manager_->QueuesToShutdownCount());
- EXPECT_EQ(0u, manager_->QueuesToDeleteCount());
-
- for (int i = 1; i <= 5; ++i) {
- main_tq->PostDelayedTask(
- FROM_HERE, BindOnce(&RecordTimeTask, &run_times, GetTickClock()),
- TimeDelta::FromMilliseconds(i * 100));
- }
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(250));
-
- main_tq = nullptr;
- // Ensure that task queue went away.
- EXPECT_FALSE(main_tq_weak_ptr.get());
-
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(1));
-
- EXPECT_EQ(1u, manager_->ActiveQueuesCount());
- EXPECT_EQ(1u, manager_->QueuesToShutdownCount());
- EXPECT_EQ(0u, manager_->QueuesToDeleteCount());
-
- test_task_runner_->FastForwardUntilNoTasksRemain();
-
- // Even with TaskQueue gone, tasks are executed.
- EXPECT_THAT(run_times,
- ElementsAre(start_time_ + TimeDelta::FromMilliseconds(100),
- start_time_ + TimeDelta::FromMilliseconds(200),
- start_time_ + TimeDelta::FromMilliseconds(300),
- start_time_ + TimeDelta::FromMilliseconds(400),
- start_time_ + TimeDelta::FromMilliseconds(500)));
-
- EXPECT_EQ(0u, manager_->ActiveQueuesCount());
- EXPECT_EQ(0u, manager_->QueuesToShutdownCount());
- EXPECT_EQ(0u, manager_->QueuesToDeleteCount());
-}
-
-TEST_F(TaskQueueManagerTest, GracefulShutdown_ManagerDeletedInFlight) {
- std::vector<TimeTicks> run_times;
- scoped_refptr<TestTaskQueue> control_tq = CreateTaskQueue();
- std::vector<scoped_refptr<TestTaskQueue>> main_tqs;
- std::vector<WeakPtr<TestTaskQueue>> main_tq_weak_ptrs;
-
- // There might be a race condition - async task queues should be unregistered
- // first. Increase the number of task queues to surely detect that.
- // The problem is that pointers are compared in a set and generally for
- // a small number of allocations value of the pointers increases
- // monotonically. 100 is large enough to force allocations from different
- // pages.
- const int N = 100;
- for (int i = 0; i < N; ++i) {
- scoped_refptr<TestTaskQueue> tq = CreateTaskQueue();
- main_tq_weak_ptrs.push_back(tq->GetWeakPtr());
- main_tqs.push_back(std::move(tq));
- }
-
- for (int i = 1; i <= 5; ++i) {
- main_tqs[0]->PostDelayedTask(
- FROM_HERE, BindOnce(&RecordTimeTask, &run_times, GetTickClock()),
- TimeDelta::FromMilliseconds(i * 100));
- }
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(250));
-
- main_tqs.clear();
- // Ensure that task queues went away.
- for (int i = 0; i < N; ++i) {
- EXPECT_FALSE(main_tq_weak_ptrs[i].get());
- }
-
- // No leaks should occur when TQM was destroyed before processing
- // shutdown task and TaskQueueImpl should be safely deleted on a correct
- // thread.
- manager_.reset();
-
- test_task_runner_->FastForwardUntilNoTasksRemain();
-
- EXPECT_THAT(run_times,
- ElementsAre(start_time_ + TimeDelta::FromMilliseconds(100),
- start_time_ + TimeDelta::FromMilliseconds(200)));
-}
-
-TEST_F(TaskQueueManagerTest,
- GracefulShutdown_ManagerDeletedWithQueuesToShutdown) {
- std::vector<TimeTicks> run_times;
- scoped_refptr<TestTaskQueue> main_tq = CreateTaskQueue();
- WeakPtr<TestTaskQueue> main_tq_weak_ptr = main_tq->GetWeakPtr();
-
- EXPECT_EQ(1u, manager_->ActiveQueuesCount());
- EXPECT_EQ(0u, manager_->QueuesToShutdownCount());
- EXPECT_EQ(0u, manager_->QueuesToDeleteCount());
-
- for (int i = 1; i <= 5; ++i) {
- main_tq->PostDelayedTask(
- FROM_HERE, BindOnce(&RecordTimeTask, &run_times, GetTickClock()),
- TimeDelta::FromMilliseconds(i * 100));
- }
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(250));
-
- main_tq = nullptr;
- // Ensure that task queue went away.
- EXPECT_FALSE(main_tq_weak_ptr.get());
-
- test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(1));
-
- EXPECT_EQ(1u, manager_->ActiveQueuesCount());
- EXPECT_EQ(1u, manager_->QueuesToShutdownCount());
- EXPECT_EQ(0u, manager_->QueuesToDeleteCount());
-
- // Ensure that all queues-to-gracefully-shutdown are properly unregistered.
- manager_.reset();
-
- test_task_runner_->FastForwardUntilNoTasksRemain();
-
- EXPECT_THAT(run_times,
- ElementsAre(start_time_ + TimeDelta::FromMilliseconds(100),
- start_time_ + TimeDelta::FromMilliseconds(200)));
-}
-
-TEST_F(TaskQueueManagerTestWithCustomInitialization, DefaultTaskRunnerSupport) {
- MessageLoop message_loop;
- scoped_refptr<SingleThreadTaskRunner> original_task_runner =
- message_loop.task_runner();
- scoped_refptr<SingleThreadTaskRunner> custom_task_runner =
- MakeRefCounted<TestSimpleTaskRunner>();
- {
- std::unique_ptr<TaskQueueManagerForTest> manager =
- TaskQueueManagerForTest::Create(&message_loop,
- message_loop.task_runner(), nullptr);
- manager->SetDefaultTaskRunner(custom_task_runner);
- DCHECK_EQ(custom_task_runner, message_loop.task_runner());
- }
- DCHECK_EQ(original_task_runner, message_loop.task_runner());
-}
-
-TEST_F(TaskQueueManagerTest, CanceledTasksInQueueCantMakeOtherTasksSkipAhead) {
- CreateTaskQueues(2u);
-
- CancelableTask task1(GetTickClock());
- CancelableTask task2(GetTickClock());
- std::vector<TimeTicks> run_times;
-
- runners_[0]->PostTask(FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task1.weak_factory_.GetWeakPtr(), &run_times));
- runners_[0]->PostTask(FROM_HERE,
- BindOnce(&CancelableTask::RecordTimeTask,
- task2.weak_factory_.GetWeakPtr(), &run_times));
-
- std::vector<EnqueueOrder> run_order;
- runners_[1]->PostTask(FROM_HERE, BindOnce(&TestTask, 1, &run_order));
-
- runners_[0]->PostTask(FROM_HERE, BindOnce(&TestTask, 2, &run_order));
-
- task1.weak_factory_.InvalidateWeakPtrs();
- task2.weak_factory_.InvalidateWeakPtrs();
- RunLoop().RunUntilIdle();
-
- EXPECT_THAT(run_order, ElementsAre(1, 2));
-}
-
-TEST_F(TaskQueueManagerTest, TaskQueueDeletedOnAnotherThread) {
- std::vector<TimeTicks> run_times;
- scoped_refptr<TestTaskQueue> main_tq = CreateTaskQueue();
-
- int start_counter = 0;
- int complete_counter = 0;
- SetOnTaskHandlers(main_tq, &start_counter, &complete_counter);
-
- EXPECT_EQ(1u, manager_->ActiveQueuesCount());
- EXPECT_EQ(0u, manager_->QueuesToShutdownCount());
- EXPECT_EQ(0u, manager_->QueuesToDeleteCount());
-
- for (int i = 1; i <= 5; ++i) {
- main_tq->PostDelayedTask(
- FROM_HERE, BindOnce(&RecordTimeTask, &run_times, GetTickClock()),
- TimeDelta::FromMilliseconds(i * 100));
- }
-
- // TODO(altimin): do not do this after switching to weak pointer-based
- // task handlers.
- UnsetOnTaskHandlers(main_tq);
-
- WaitableEvent task_queue_deleted(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- std::unique_ptr<Thread> thread = std::make_unique<Thread>("test thread");
- thread->StartAndWaitForTesting();
-
- thread->task_runner()->PostTask(
- FROM_HERE, BindOnce(
- [](scoped_refptr<SingleThreadTaskRunner> task_queue,
- WaitableEvent* task_queue_deleted) {
- task_queue = nullptr;
- task_queue_deleted->Signal();
- },
- std::move(main_tq), &task_queue_deleted));
- task_queue_deleted.Wait();
-
- EXPECT_EQ(1u, manager_->ActiveQueuesCount());
- EXPECT_EQ(1u, manager_->QueuesToShutdownCount());
- EXPECT_EQ(0u, manager_->QueuesToDeleteCount());
-
- test_task_runner_->FastForwardUntilNoTasksRemain();
-
- // Even with TaskQueue gone, tasks are executed.
- EXPECT_THAT(run_times,
- ElementsAre(start_time_ + TimeDelta::FromMilliseconds(100),
- start_time_ + TimeDelta::FromMilliseconds(200),
- start_time_ + TimeDelta::FromMilliseconds(300),
- start_time_ + TimeDelta::FromMilliseconds(400),
- start_time_ + TimeDelta::FromMilliseconds(500)));
-
- EXPECT_EQ(0u, manager_->ActiveQueuesCount());
- EXPECT_EQ(0u, manager_->QueuesToShutdownCount());
- EXPECT_EQ(0u, manager_->QueuesToDeleteCount());
-
- thread->Stop();
-}
-
-namespace {
-
-void DoNothing() {}
-
-class PostTaskInDestructor {
- public:
- explicit PostTaskInDestructor(scoped_refptr<TaskQueue> task_queue)
- : task_queue_(task_queue) {}
-
- ~PostTaskInDestructor() {
- task_queue_->PostTask(FROM_HERE, BindOnce(&DoNothing));
- }
-
- void Do() {}
-
- private:
- scoped_refptr<TaskQueue> task_queue_;
-};
-
-} // namespace
-
-TEST_F(TaskQueueManagerTest, TaskQueueUsedInTaskDestructorAfterShutdown) {
- // This test checks that when a task is posted to a shutdown queue and
- // destroyed, it can try to post a task to the same queue without deadlocks.
- scoped_refptr<TestTaskQueue> main_tq = CreateTaskQueue();
-
- WaitableEvent test_executed(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- std::unique_ptr<Thread> thread = std::make_unique<Thread>("test thread");
- thread->StartAndWaitForTesting();
-
- manager_.reset();
-
- thread->task_runner()->PostTask(
- FROM_HERE, BindOnce(
- [](scoped_refptr<SingleThreadTaskRunner> task_queue,
- std::unique_ptr<PostTaskInDestructor> test_object,
- WaitableEvent* test_executed) {
- task_queue->PostTask(FROM_HERE,
- BindOnce(&PostTaskInDestructor::Do,
- std::move(test_object)));
- test_executed->Signal();
- },
- main_tq, std::make_unique<PostTaskInDestructor>(main_tq),
- &test_executed));
- test_executed.Wait();
-}
-
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_perftest.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_perftest.cc
deleted file mode 100644
index a80845f7e00..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_perftest.cc
+++ /dev/null
@@ -1,318 +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/platform/scheduler/base/task_queue_manager.h"
-
-#include <stddef.h>
-#include <memory>
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/stringprintf.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/default_tick_clock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/perf/perf_test.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/test_task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/test_task_time_observer.h"
-#include "third_party/blink/renderer/platform/scheduler/base/virtual_time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h"
-
-namespace base {
-namespace sequence_manager {
-
-// To reduce noise related to the OS timer, we use a virtual time domain to
-// fast forward the timers.
-class PerfTestTimeDomain : public VirtualTimeDomain {
- public:
- PerfTestTimeDomain() : VirtualTimeDomain(TimeTicks::Now()) {}
- ~PerfTestTimeDomain() override = default;
-
- Optional<TimeDelta> DelayTillNextTask(LazyNow* lazy_now) override {
- TimeTicks run_time;
- if (!NextScheduledRunTime(&run_time))
- return Optional<TimeDelta>();
-
- AdvanceNowTo(run_time);
- return TimeDelta(); // Makes DoWork post an immediate continuation.
- }
-
- void RequestWakeUpAt(TimeTicks now, TimeTicks run_time) override {
- // De-dupe DoWorks.
- if (NumberOfScheduledWakeUps() == 1u)
- RequestDoWork();
- }
-
- void CancelWakeUpAt(TimeTicks run_time) override {
- // We didn't post a delayed task in RequestWakeUpAt so there's no need to do
- // anything here.
- }
-
- const char* GetName() const override { return "PerfTestTimeDomain"; }
-
- DISALLOW_COPY_AND_ASSIGN(PerfTestTimeDomain);
-};
-
-class TaskQueueManagerPerfTest : public testing::Test {
- public:
- TaskQueueManagerPerfTest()
- : num_queues_(0),
- max_tasks_in_flight_(0),
- num_tasks_in_flight_(0),
- num_tasks_to_post_(0),
- num_tasks_to_run_(0) {}
-
- void SetUp() override {
- if (ThreadTicks::IsSupported())
- ThreadTicks::WaitUntilInitialized();
- }
-
- void TearDown() override {
- queues_.clear();
- manager_->UnregisterTimeDomain(virtual_time_domain_.get());
- manager_.reset();
- }
-
- void Initialize(size_t num_queues) {
- num_queues_ = num_queues;
- message_loop_.reset(new MessageLoop());
- manager_ = TaskQueueManagerForTest::Create(message_loop_.get(),
- message_loop_->task_runner(),
- DefaultTickClock::GetInstance());
- manager_->AddTaskTimeObserver(&test_task_time_observer_);
-
- virtual_time_domain_.reset(new PerfTestTimeDomain());
- manager_->RegisterTimeDomain(virtual_time_domain_.get());
-
- for (size_t i = 0; i < num_queues; i++) {
- queues_.push_back(manager_->CreateTaskQueue<TestTaskQueue>(
- TaskQueue::Spec("test").SetTimeDomain(virtual_time_domain_.get())));
- }
-
- delayed_task_closure_ = BindRepeating(
- &TaskQueueManagerPerfTest::TestDelayedTask, Unretained(this));
-
- immediate_task_closure_ = BindRepeating(
- &TaskQueueManagerPerfTest::TestImmediateTask, Unretained(this));
- }
-
- void TestDelayedTask() {
- if (--num_tasks_to_run_ == 0) {
- run_loop_->QuitWhenIdle();
- return;
- }
-
- num_tasks_in_flight_--;
- // NOTE there are only up to max_tasks_in_flight_ pending delayed tasks at
- // any one time. Thanks to the lower_num_tasks_to_post going to zero if
- // there are a lot of tasks in flight, the total number of task in flight at
- // any one time is very variable.
- unsigned int lower_num_tasks_to_post =
- num_tasks_in_flight_ < (max_tasks_in_flight_ / 2) ? 1 : 0;
- unsigned int max_tasks_to_post =
- num_tasks_to_post_ % 2 ? lower_num_tasks_to_post : 10;
- for (unsigned int i = 0;
- i < max_tasks_to_post && num_tasks_in_flight_ < max_tasks_in_flight_ &&
- num_tasks_to_post_ > 0;
- i++) {
- // Choose a queue weighted towards queue 0.
- unsigned int queue = num_tasks_to_post_ % (num_queues_ + 1);
- if (queue == num_queues_) {
- queue = 0;
- }
- // Simulate a mix of short and longer delays.
- unsigned int delay =
- num_tasks_to_post_ % 2 ? 1 : (10 + num_tasks_to_post_ % 10);
- queues_[queue]->PostDelayedTask(FROM_HERE, delayed_task_closure_,
- TimeDelta::FromMilliseconds(delay));
- num_tasks_in_flight_++;
- num_tasks_to_post_--;
- }
- }
-
- void TestImmediateTask() {
- if (--num_tasks_to_run_ == 0) {
- run_loop_->QuitWhenIdle();
- return;
- }
-
- num_tasks_in_flight_--;
- // NOTE there are only up to max_tasks_in_flight_ pending delayed tasks at
- // any one time. Thanks to the lower_num_tasks_to_post going to zero if
- // there are a lot of tasks in flight, the total number of task in flight at
- // any one time is very variable.
- unsigned int lower_num_tasks_to_post =
- num_tasks_in_flight_ < (max_tasks_in_flight_ / 2) ? 1 : 0;
- unsigned int max_tasks_to_post =
- num_tasks_to_post_ % 2 ? lower_num_tasks_to_post : 10;
- for (unsigned int i = 0;
- i < max_tasks_to_post && num_tasks_in_flight_ < max_tasks_in_flight_ &&
- num_tasks_to_post_ > 0;
- i++) {
- // Choose a queue weighted towards queue 0.
- unsigned int queue = num_tasks_to_post_ % (num_queues_ + 1);
- if (queue == num_queues_) {
- queue = 0;
- }
- queues_[queue]->PostTask(FROM_HERE, immediate_task_closure_);
- num_tasks_in_flight_++;
- num_tasks_to_post_--;
- }
- }
-
- void ResetAndCallTestDelayedTask(unsigned int num_tasks_to_run) {
- num_tasks_in_flight_ = 1;
- num_tasks_to_post_ = num_tasks_to_run;
- num_tasks_to_run_ = num_tasks_to_run;
- TestDelayedTask();
- }
-
- void ResetAndCallTestImmediateTask(unsigned int num_tasks_to_run) {
- num_tasks_in_flight_ = 1;
- num_tasks_to_post_ = num_tasks_to_run;
- num_tasks_to_run_ = num_tasks_to_run;
- TestImmediateTask();
- }
-
- void Benchmark(const std::string& trace, const RepeatingClosure& test_task) {
- ThreadTicks start = ThreadTicks::Now();
- ThreadTicks now;
- unsigned long long num_iterations = 0;
- do {
- test_task.Run();
- run_loop_.reset(new RunLoop());
- run_loop_->Run();
- now = ThreadTicks::Now();
- num_iterations++;
- } while (now - start < TimeDelta::FromSeconds(5));
- perf_test::PrintResult(
- "task", "", trace,
- (now - start).InMicroseconds() / static_cast<double>(num_iterations),
- "us/run", true);
- }
-
- size_t num_queues_;
- unsigned int max_tasks_in_flight_;
- unsigned int num_tasks_in_flight_;
- unsigned int num_tasks_to_post_;
- unsigned int num_tasks_to_run_;
- std::unique_ptr<MessageLoop> message_loop_;
- std::unique_ptr<TaskQueueManager> manager_;
- std::unique_ptr<RunLoop> run_loop_;
- std::unique_ptr<VirtualTimeDomain> virtual_time_domain_;
- std::vector<scoped_refptr<SingleThreadTaskRunner>> queues_;
- RepeatingClosure delayed_task_closure_;
- RepeatingClosure immediate_task_closure_;
- // TODO(alexclarke): parameterize so we can measure with and without a
- // TaskTimeObserver.
- TestTaskTimeObserver test_task_time_observer_;
-};
-
-TEST_F(TaskQueueManagerPerfTest, RunTenThousandDelayedTasks_OneQueue) {
- if (!ThreadTicks::IsSupported())
- return;
- Initialize(1u);
-
- max_tasks_in_flight_ = 200;
- Benchmark(
- "run 10000 delayed tasks with one queue",
- BindRepeating(&TaskQueueManagerPerfTest::ResetAndCallTestDelayedTask,
- Unretained(this), 10000));
-}
-
-TEST_F(TaskQueueManagerPerfTest, RunTenThousandDelayedTasks_FourQueues) {
- if (!ThreadTicks::IsSupported())
- return;
- Initialize(4u);
-
- max_tasks_in_flight_ = 200;
- Benchmark(
- "run 10000 delayed tasks with four queues",
- BindRepeating(&TaskQueueManagerPerfTest::ResetAndCallTestDelayedTask,
- Unretained(this), 10000));
-}
-
-TEST_F(TaskQueueManagerPerfTest, RunTenThousandDelayedTasks_EightQueues) {
- if (!ThreadTicks::IsSupported())
- return;
- Initialize(8u);
-
- max_tasks_in_flight_ = 200;
- Benchmark(
- "run 10000 delayed tasks with eight queues",
- BindRepeating(&TaskQueueManagerPerfTest::ResetAndCallTestDelayedTask,
- Unretained(this), 10000));
-}
-
-TEST_F(TaskQueueManagerPerfTest, RunTenThousandDelayedTasks_ThirtyTwoQueues) {
- if (!ThreadTicks::IsSupported())
- return;
- Initialize(32u);
-
- max_tasks_in_flight_ = 200;
- Benchmark(
- "run 10000 delayed tasks with eight queues",
- BindRepeating(&TaskQueueManagerPerfTest::ResetAndCallTestDelayedTask,
- Unretained(this), 10000));
-}
-
-TEST_F(TaskQueueManagerPerfTest, RunTenThousandImmediateTasks_OneQueue) {
- if (!ThreadTicks::IsSupported())
- return;
- Initialize(1u);
-
- max_tasks_in_flight_ = 200;
- Benchmark(
- "run 10000 immediate tasks with one queue",
- BindRepeating(&TaskQueueManagerPerfTest::ResetAndCallTestImmediateTask,
- Unretained(this), 10000));
-}
-
-TEST_F(TaskQueueManagerPerfTest, RunTenThousandImmediateTasks_FourQueues) {
- if (!ThreadTicks::IsSupported())
- return;
- Initialize(4u);
-
- max_tasks_in_flight_ = 200;
- Benchmark(
- "run 10000 immediate tasks with four queues",
- BindRepeating(&TaskQueueManagerPerfTest::ResetAndCallTestImmediateTask,
- Unretained(this), 10000));
-}
-
-TEST_F(TaskQueueManagerPerfTest, RunTenThousandImmediateTasks_EightQueues) {
- if (!ThreadTicks::IsSupported())
- return;
- Initialize(8u);
-
- max_tasks_in_flight_ = 200;
- Benchmark(
- "run 10000 immediate tasks with eight queues",
- BindRepeating(&TaskQueueManagerPerfTest::ResetAndCallTestImmediateTask,
- Unretained(this), 10000));
-}
-
-TEST_F(TaskQueueManagerPerfTest, RunTenThousandImmediateTasks_ThirtyTwoQueues) {
- if (!ThreadTicks::IsSupported())
- return;
- Initialize(32u);
-
- max_tasks_in_flight_ = 200;
- Benchmark(
- "run 10000 immediate tasks with eight queues",
- BindRepeating(&TaskQueueManagerPerfTest::ResetAndCallTestImmediateTask,
- Unretained(this), 10000));
-}
-
-// TODO(alexclarke): Add additional tests with different mixes of non-delayed vs
-// delayed tasks.
-
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector.cc
deleted file mode 100644
index 40c610654c1..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector.cc
+++ /dev/null
@@ -1,407 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h"
-
-#include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/work_queue.h"
-
-namespace base {
-namespace sequence_manager {
-namespace internal {
-
-namespace {
-
-TaskQueueSelectorLogic QueuePriorityToSelectorLogic(
- TaskQueue::QueuePriority priority) {
- switch (priority) {
- case TaskQueue::kControlPriority:
- return TaskQueueSelectorLogic::kControlPriorityLogic;
- case TaskQueue::kHighestPriority:
- return TaskQueueSelectorLogic::kHighestPriorityLogic;
- case TaskQueue::kHighPriority:
- return TaskQueueSelectorLogic::kHighPriorityLogic;
- case TaskQueue::kNormalPriority:
- return TaskQueueSelectorLogic::kNormalPriorityLogic;
- case TaskQueue::kLowPriority:
- return TaskQueueSelectorLogic::kLowPriorityLogic;
- case TaskQueue::kBestEffortPriority:
- return TaskQueueSelectorLogic::kBestEffortPriorityLogic;
- default:
- NOTREACHED();
- return TaskQueueSelectorLogic::kCount;
- }
-}
-
-// Helper function used to report the number of times a selector logic is
-// trigerred. This will create a histogram for the enumerated data.
-void ReportTaskSelectionLogic(TaskQueueSelectorLogic selector_logic) {
- UMA_HISTOGRAM_ENUMERATION("TaskQueueSelector.TaskServicedPerSelectorLogic",
- selector_logic, TaskQueueSelectorLogic::kCount);
-}
-
-} // namespace
-
-TaskQueueSelector::TaskQueueSelector()
- : prioritizing_selector_(this, "enabled"),
- immediate_starvation_count_(0),
- high_priority_starvation_score_(0),
- normal_priority_starvation_score_(0),
- low_priority_starvation_score_(0),
- task_queue_selector_observer_(nullptr) {}
-
-TaskQueueSelector::~TaskQueueSelector() = default;
-
-void TaskQueueSelector::AddQueue(internal::TaskQueueImpl* queue) {
- DCHECK(main_thread_checker_.CalledOnValidThread());
- DCHECK(queue->IsQueueEnabled());
- prioritizing_selector_.AddQueue(queue, TaskQueue::kNormalPriority);
-}
-
-void TaskQueueSelector::RemoveQueue(internal::TaskQueueImpl* queue) {
- DCHECK(main_thread_checker_.CalledOnValidThread());
- if (queue->IsQueueEnabled()) {
- prioritizing_selector_.RemoveQueue(queue);
- }
-}
-
-void TaskQueueSelector::EnableQueue(internal::TaskQueueImpl* queue) {
- DCHECK(main_thread_checker_.CalledOnValidThread());
- DCHECK(queue->IsQueueEnabled());
- prioritizing_selector_.AddQueue(queue, queue->GetQueuePriority());
- if (task_queue_selector_observer_)
- task_queue_selector_observer_->OnTaskQueueEnabled(queue);
-}
-
-void TaskQueueSelector::DisableQueue(internal::TaskQueueImpl* queue) {
- DCHECK(main_thread_checker_.CalledOnValidThread());
- DCHECK(!queue->IsQueueEnabled());
- prioritizing_selector_.RemoveQueue(queue);
-}
-
-void TaskQueueSelector::SetQueuePriority(internal::TaskQueueImpl* queue,
- TaskQueue::QueuePriority priority) {
- DCHECK_LT(priority, TaskQueue::kQueuePriorityCount);
- DCHECK(main_thread_checker_.CalledOnValidThread());
- if (queue->IsQueueEnabled()) {
- prioritizing_selector_.ChangeSetIndex(queue, priority);
- } else {
- // Disabled queue is not in any set so we can't use ChangeSetIndex here
- // and have to assign priority for the queue itself.
- queue->delayed_work_queue()->AssignSetIndex(priority);
- queue->immediate_work_queue()->AssignSetIndex(priority);
- }
- DCHECK_EQ(priority, queue->GetQueuePriority());
-}
-
-TaskQueue::QueuePriority TaskQueueSelector::NextPriority(
- TaskQueue::QueuePriority priority) {
- DCHECK(priority < TaskQueue::kQueuePriorityCount);
- return static_cast<TaskQueue::QueuePriority>(static_cast<int>(priority) + 1);
-}
-
-TaskQueueSelector::PrioritizingSelector::PrioritizingSelector(
- TaskQueueSelector* task_queue_selector,
- const char* name)
- : task_queue_selector_(task_queue_selector),
- delayed_work_queue_sets_(TaskQueue::kQueuePriorityCount, name),
- immediate_work_queue_sets_(TaskQueue::kQueuePriorityCount, name) {}
-
-void TaskQueueSelector::PrioritizingSelector::AddQueue(
- internal::TaskQueueImpl* queue,
- TaskQueue::QueuePriority priority) {
-#if DCHECK_IS_ON()
- DCHECK(!CheckContainsQueueForTest(queue));
-#endif
- delayed_work_queue_sets_.AddQueue(queue->delayed_work_queue(), priority);
- immediate_work_queue_sets_.AddQueue(queue->immediate_work_queue(), priority);
-#if DCHECK_IS_ON()
- DCHECK(CheckContainsQueueForTest(queue));
-#endif
-}
-
-void TaskQueueSelector::PrioritizingSelector::ChangeSetIndex(
- internal::TaskQueueImpl* queue,
- TaskQueue::QueuePriority priority) {
-#if DCHECK_IS_ON()
- DCHECK(CheckContainsQueueForTest(queue));
-#endif
- delayed_work_queue_sets_.ChangeSetIndex(queue->delayed_work_queue(),
- priority);
- immediate_work_queue_sets_.ChangeSetIndex(queue->immediate_work_queue(),
- priority);
-#if DCHECK_IS_ON()
- DCHECK(CheckContainsQueueForTest(queue));
-#endif
-}
-
-void TaskQueueSelector::PrioritizingSelector::RemoveQueue(
- internal::TaskQueueImpl* queue) {
-#if DCHECK_IS_ON()
- DCHECK(CheckContainsQueueForTest(queue));
-#endif
- delayed_work_queue_sets_.RemoveQueue(queue->delayed_work_queue());
- immediate_work_queue_sets_.RemoveQueue(queue->immediate_work_queue());
-
-#if DCHECK_IS_ON()
- DCHECK(!CheckContainsQueueForTest(queue));
-#endif
-}
-
-bool TaskQueueSelector::PrioritizingSelector::
- ChooseOldestImmediateTaskWithPriority(TaskQueue::QueuePriority priority,
- WorkQueue** out_work_queue) const {
- return immediate_work_queue_sets_.GetOldestQueueInSet(priority,
- out_work_queue);
-}
-
-bool TaskQueueSelector::PrioritizingSelector::
- ChooseOldestDelayedTaskWithPriority(TaskQueue::QueuePriority priority,
- WorkQueue** out_work_queue) const {
- return delayed_work_queue_sets_.GetOldestQueueInSet(priority, out_work_queue);
-}
-
-bool TaskQueueSelector::PrioritizingSelector::
- ChooseOldestImmediateOrDelayedTaskWithPriority(
- TaskQueue::QueuePriority priority,
- bool* out_chose_delayed_over_immediate,
- WorkQueue** out_work_queue) const {
- WorkQueue* immediate_queue;
- DCHECK_EQ(*out_chose_delayed_over_immediate, false);
- EnqueueOrder immediate_enqueue_order;
- if (immediate_work_queue_sets_.GetOldestQueueAndEnqueueOrderInSet(
- priority, &immediate_queue, &immediate_enqueue_order)) {
- WorkQueue* delayed_queue;
- EnqueueOrder delayed_enqueue_order;
- if (delayed_work_queue_sets_.GetOldestQueueAndEnqueueOrderInSet(
- priority, &delayed_queue, &delayed_enqueue_order)) {
- if (immediate_enqueue_order < delayed_enqueue_order) {
- *out_work_queue = immediate_queue;
- } else {
- *out_chose_delayed_over_immediate = true;
- *out_work_queue = delayed_queue;
- }
- } else {
- *out_work_queue = immediate_queue;
- }
- return true;
- }
- return delayed_work_queue_sets_.GetOldestQueueInSet(priority, out_work_queue);
-}
-
-bool TaskQueueSelector::PrioritizingSelector::ChooseOldestWithPriority(
- TaskQueue::QueuePriority priority,
- bool* out_chose_delayed_over_immediate,
- WorkQueue** out_work_queue) const {
- // Select an immediate work queue if we are starving immediate tasks.
- if (task_queue_selector_->immediate_starvation_count_ >=
- kMaxDelayedStarvationTasks) {
- if (ChooseOldestImmediateTaskWithPriority(priority, out_work_queue))
- return true;
- return ChooseOldestDelayedTaskWithPriority(priority, out_work_queue);
- }
- return ChooseOldestImmediateOrDelayedTaskWithPriority(
- priority, out_chose_delayed_over_immediate, out_work_queue);
-}
-
-bool TaskQueueSelector::PrioritizingSelector::SelectWorkQueueToService(
- TaskQueue::QueuePriority max_priority,
- WorkQueue** out_work_queue,
- bool* out_chose_delayed_over_immediate) {
- DCHECK(task_queue_selector_->main_thread_checker_.CalledOnValidThread());
- DCHECK_EQ(*out_chose_delayed_over_immediate, false);
-
- // Always service the control queue if it has any work.
- if (max_priority > TaskQueue::kControlPriority &&
- ChooseOldestWithPriority(TaskQueue::kControlPriority,
- out_chose_delayed_over_immediate,
- out_work_queue)) {
- ReportTaskSelectionLogic(TaskQueueSelectorLogic::kControlPriorityLogic);
- return true;
- }
-
- // Select from the low priority queue if we are starving it.
- if (max_priority > TaskQueue::kLowPriority &&
- task_queue_selector_->low_priority_starvation_score_ >=
- kMaxLowPriorityStarvationScore &&
- ChooseOldestWithPriority(TaskQueue::kLowPriority,
- out_chose_delayed_over_immediate,
- out_work_queue)) {
- ReportTaskSelectionLogic(
- TaskQueueSelectorLogic::kLowPriorityStarvationLogic);
- return true;
- }
-
- // Select from the normal priority queue if we are starving it.
- if (max_priority > TaskQueue::kNormalPriority &&
- task_queue_selector_->normal_priority_starvation_score_ >=
- kMaxNormalPriorityStarvationScore &&
- ChooseOldestWithPriority(TaskQueue::kNormalPriority,
- out_chose_delayed_over_immediate,
- out_work_queue)) {
- ReportTaskSelectionLogic(
- TaskQueueSelectorLogic::kNormalPriorityStarvationLogic);
- return true;
- }
-
- // Select from the high priority queue if we are starving it.
- if (max_priority > TaskQueue::kHighPriority &&
- task_queue_selector_->high_priority_starvation_score_ >=
- kMaxHighPriorityStarvationScore &&
- ChooseOldestWithPriority(TaskQueue::kHighPriority,
- out_chose_delayed_over_immediate,
- out_work_queue)) {
- ReportTaskSelectionLogic(
- TaskQueueSelectorLogic::kHighPriorityStarvationLogic);
- return true;
- }
-
- // Otherwise choose in priority order.
- for (TaskQueue::QueuePriority priority = TaskQueue::kHighestPriority;
- priority < max_priority; priority = NextPriority(priority)) {
- if (ChooseOldestWithPriority(priority, out_chose_delayed_over_immediate,
- out_work_queue)) {
- ReportTaskSelectionLogic(QueuePriorityToSelectorLogic(priority));
- return true;
- }
- }
- return false;
-}
-
-#if DCHECK_IS_ON() || !defined(NDEBUG)
-bool TaskQueueSelector::PrioritizingSelector::CheckContainsQueueForTest(
- const internal::TaskQueueImpl* queue) const {
- bool contains_delayed_work_queue =
- delayed_work_queue_sets_.ContainsWorkQueueForTest(
- queue->delayed_work_queue());
-
- bool contains_immediate_work_queue =
- immediate_work_queue_sets_.ContainsWorkQueueForTest(
- queue->immediate_work_queue());
-
- DCHECK_EQ(contains_delayed_work_queue, contains_immediate_work_queue);
- return contains_delayed_work_queue;
-}
-#endif
-
-bool TaskQueueSelector::SelectWorkQueueToService(WorkQueue** out_work_queue) {
- DCHECK(main_thread_checker_.CalledOnValidThread());
- bool chose_delayed_over_immediate = false;
- bool found_queue = prioritizing_selector_.SelectWorkQueueToService(
- TaskQueue::kQueuePriorityCount, out_work_queue,
- &chose_delayed_over_immediate);
- if (!found_queue)
- return false;
-
- // We could use |(*out_work_queue)->task_queue()->GetQueuePriority()| here but
- // for re-queued non-nestable tasks |task_queue()| returns null.
- DidSelectQueueWithPriority(static_cast<TaskQueue::QueuePriority>(
- (*out_work_queue)->work_queue_set_index()),
- chose_delayed_over_immediate);
- return true;
-}
-
-void TaskQueueSelector::DidSelectQueueWithPriority(
- TaskQueue::QueuePriority priority,
- bool chose_delayed_over_immediate) {
- switch (priority) {
- case TaskQueue::kControlPriority:
- break;
- case TaskQueue::kHighestPriority:
- low_priority_starvation_score_ +=
- HasTasksWithPriority(TaskQueue::kLowPriority)
- ? kSmallScoreIncrementForLowPriorityStarvation
- : 0;
- normal_priority_starvation_score_ +=
- HasTasksWithPriority(TaskQueue::kNormalPriority)
- ? kSmallScoreIncrementForNormalPriorityStarvation
- : 0;
- high_priority_starvation_score_ +=
- HasTasksWithPriority(TaskQueue::kHighPriority)
- ? kSmallScoreIncrementForHighPriorityStarvation
- : 0;
- break;
- case TaskQueue::kHighPriority:
- low_priority_starvation_score_ +=
- HasTasksWithPriority(TaskQueue::kLowPriority)
- ? kLargeScoreIncrementForLowPriorityStarvation
- : 0;
- normal_priority_starvation_score_ +=
- HasTasksWithPriority(TaskQueue::kNormalPriority)
- ? kLargeScoreIncrementForNormalPriorityStarvation
- : 0;
- high_priority_starvation_score_ = 0;
- break;
- case TaskQueue::kNormalPriority:
- low_priority_starvation_score_ +=
- HasTasksWithPriority(TaskQueue::kLowPriority)
- ? kLargeScoreIncrementForLowPriorityStarvation
- : 0;
- normal_priority_starvation_score_ = 0;
- break;
- case TaskQueue::kLowPriority:
- case TaskQueue::kBestEffortPriority:
- low_priority_starvation_score_ = 0;
- high_priority_starvation_score_ = 0;
- normal_priority_starvation_score_ = 0;
- break;
- default:
- NOTREACHED();
- }
- if (chose_delayed_over_immediate) {
- immediate_starvation_count_++;
- } else {
- immediate_starvation_count_ = 0;
- }
-}
-
-void TaskQueueSelector::AsValueInto(trace_event::TracedValue* state) const {
- DCHECK(main_thread_checker_.CalledOnValidThread());
- state->SetInteger("high_priority_starvation_score",
- high_priority_starvation_score_);
- state->SetInteger("normal_priority_starvation_score",
- normal_priority_starvation_score_);
- state->SetInteger("low_priority_starvation_score",
- low_priority_starvation_score_);
- state->SetInteger("immediate_starvation_count", immediate_starvation_count_);
-}
-
-void TaskQueueSelector::SetTaskQueueSelectorObserver(Observer* observer) {
- task_queue_selector_observer_ = observer;
-}
-
-bool TaskQueueSelector::AllEnabledWorkQueuesAreEmpty() const {
- DCHECK(main_thread_checker_.CalledOnValidThread());
- for (TaskQueue::QueuePriority priority = TaskQueue::kControlPriority;
- priority < TaskQueue::kQueuePriorityCount;
- priority = NextPriority(priority)) {
- if (!prioritizing_selector_.delayed_work_queue_sets()->IsSetEmpty(
- priority) ||
- !prioritizing_selector_.immediate_work_queue_sets()->IsSetEmpty(
- priority)) {
- return false;
- }
- }
- return true;
-}
-
-void TaskQueueSelector::SetImmediateStarvationCountForTest(
- size_t immediate_starvation_count) {
- immediate_starvation_count_ = immediate_starvation_count;
-}
-
-bool TaskQueueSelector::HasTasksWithPriority(
- TaskQueue::QueuePriority priority) {
- return !prioritizing_selector_.delayed_work_queue_sets()->IsSetEmpty(
- priority) ||
- !prioritizing_selector_.immediate_work_queue_sets()->IsSetEmpty(
- priority);
-}
-
-} // namespace internal
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h b/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h
deleted file mode 100644
index 9cb7c114be9..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_SELECTOR_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_SELECTOR_H_
-
-#include <stddef.h>
-
-#include <set>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/pending_task.h"
-#include "base/threading/thread_checker.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector_logic.h"
-#include "third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h"
-
-namespace base {
-namespace sequence_manager {
-namespace internal {
-
-// TaskQueueSelector is used by the SchedulerHelper to enable prioritization
-// of particular task queues.
-class PLATFORM_EXPORT TaskQueueSelector {
- public:
- TaskQueueSelector();
- ~TaskQueueSelector();
-
- // Called to register a queue that can be selected. This function is called
- // on the main thread.
- void AddQueue(internal::TaskQueueImpl* queue);
-
- // The specified work will no longer be considered for selection. This
- // function is called on the main thread.
- void RemoveQueue(internal::TaskQueueImpl* queue);
-
- // Make |queue| eligible for selection. This function is called on the main
- // thread. Must only be called if |queue| is disabled.
- void EnableQueue(internal::TaskQueueImpl* queue);
-
- // Disable selection from |queue|. Must only be called if |queue| is enabled.
- void DisableQueue(internal::TaskQueueImpl* queue);
-
- // Called get or set the priority of |queue|.
- void SetQueuePriority(internal::TaskQueueImpl* queue,
- TaskQueue::QueuePriority priority);
-
- // Called to choose the work queue from which the next task should be taken
- // and run. Return true if |out_work_queue| indicates the queue to service or
- // false to avoid running any task.
- //
- // This function is called on the main thread.
- bool SelectWorkQueueToService(WorkQueue** out_work_queue);
-
- // Serialize the selector state for tracing.
- void AsValueInto(trace_event::TracedValue* state) const;
-
- class PLATFORM_EXPORT Observer {
- public:
- virtual ~Observer() = default;
-
- // Called when |queue| transitions from disabled to enabled.
- virtual void OnTaskQueueEnabled(internal::TaskQueueImpl* queue) = 0;
- };
-
- // Called once to set the Observer. This function is called
- // on the main thread. If |observer| is null, then no callbacks will occur.
- void SetTaskQueueSelectorObserver(Observer* observer);
-
- // Returns true if all the enabled work queues are empty. Returns false
- // otherwise.
- bool AllEnabledWorkQueuesAreEmpty() const;
-
- protected:
- class PLATFORM_EXPORT PrioritizingSelector {
- public:
- PrioritizingSelector(TaskQueueSelector* task_queue_selector,
- const char* name);
-
- void ChangeSetIndex(internal::TaskQueueImpl* queue,
- TaskQueue::QueuePriority priority);
- void AddQueue(internal::TaskQueueImpl* queue,
- TaskQueue::QueuePriority priority);
- void RemoveQueue(internal::TaskQueueImpl* queue);
-
- bool SelectWorkQueueToService(TaskQueue::QueuePriority max_priority,
- WorkQueue** out_work_queue,
- bool* out_chose_delayed_over_immediate);
-
- WorkQueueSets* delayed_work_queue_sets() {
- return &delayed_work_queue_sets_;
- }
- WorkQueueSets* immediate_work_queue_sets() {
- return &immediate_work_queue_sets_;
- }
-
- const WorkQueueSets* delayed_work_queue_sets() const {
- return &delayed_work_queue_sets_;
- }
- const WorkQueueSets* immediate_work_queue_sets() const {
- return &immediate_work_queue_sets_;
- }
-
- bool ChooseOldestWithPriority(TaskQueue::QueuePriority priority,
- bool* out_chose_delayed_over_immediate,
- WorkQueue** out_work_queue) const;
-
-#if DCHECK_IS_ON() || !defined(NDEBUG)
- bool CheckContainsQueueForTest(const internal::TaskQueueImpl* queue) const;
-#endif
-
- private:
- bool ChooseOldestImmediateTaskWithPriority(
- TaskQueue::QueuePriority priority,
- WorkQueue** out_work_queue) const;
-
- bool ChooseOldestDelayedTaskWithPriority(TaskQueue::QueuePriority priority,
- WorkQueue** out_work_queue) const;
-
- // Return true if |out_queue| contains the queue with the oldest pending
- // task from the set of queues of |priority|, or false if all queues of that
- // priority are empty. In addition |out_chose_delayed_over_immediate| is set
- // to true iff we chose a delayed work queue in favour of an immediate work
- // queue.
- bool ChooseOldestImmediateOrDelayedTaskWithPriority(
- TaskQueue::QueuePriority priority,
- bool* out_chose_delayed_over_immediate,
- WorkQueue** out_work_queue) const;
-
- const TaskQueueSelector* task_queue_selector_;
- WorkQueueSets delayed_work_queue_sets_;
- WorkQueueSets immediate_work_queue_sets_;
-
- DISALLOW_COPY_AND_ASSIGN(PrioritizingSelector);
- };
-
- // Return true if |out_queue| contains the queue with the oldest pending task
- // from the set of queues of |priority|, or false if all queues of that
- // priority are empty. In addition |out_chose_delayed_over_immediate| is set
- // to true iff we chose a delayed work queue in favour of an immediate work
- // queue. This method will force select an immediate task if those are being
- // starved by delayed tasks.
- void SetImmediateStarvationCountForTest(size_t immediate_starvation_count);
-
- PrioritizingSelector* prioritizing_selector_for_test() {
- return &prioritizing_selector_;
- }
-
- // Maximum score to accumulate before high priority tasks are run even in
- // the presence of highest priority tasks.
- static const size_t kMaxHighPriorityStarvationScore = 3;
-
- // Increment to be applied to the high priority starvation score when a task
- // should have only a small effect on the score. E.g. A number of highest
- // priority tasks must run before the high priority queue is considered
- // starved.
- static const size_t kSmallScoreIncrementForHighPriorityStarvation = 1;
-
- // Maximum score to accumulate before normal priority tasks are run even in
- // the presence of higher priority tasks i.e. highest and high priority tasks.
- static const size_t kMaxNormalPriorityStarvationScore = 5;
-
- // Increment to be applied to the normal priority starvation score when a task
- // should have a large effect on the score. E.g Only a few high priority
- // priority tasks must run before the normal priority queue is considered
- // starved.
- static const size_t kLargeScoreIncrementForNormalPriorityStarvation = 2;
-
- // Increment to be applied to the normal priority starvation score when a task
- // should have only a small effect on the score. E.g. A number of highest
- // priority tasks must run before the normal priority queue is considered
- // starved.
- static const size_t kSmallScoreIncrementForNormalPriorityStarvation = 1;
-
- // Maximum score to accumulate before low priority tasks are run even in the
- // presence of highest, high, or normal priority tasks.
- static const size_t kMaxLowPriorityStarvationScore = 25;
-
- // Increment to be applied to the low priority starvation score when a task
- // should have a large effect on the score. E.g. Only a few normal/high
- // priority tasks must run before the low priority queue is considered
- // starved.
- static const size_t kLargeScoreIncrementForLowPriorityStarvation = 5;
-
- // Increment to be applied to the low priority starvation score when a task
- // should have only a small effect on the score. E.g. A lot of highest
- // priority tasks must run before the low priority queue is considered
- // starved.
- static const size_t kSmallScoreIncrementForLowPriorityStarvation = 1;
-
- // Maximum number of delayed tasks tasks which can be run while there's a
- // waiting non-delayed task.
- static const size_t kMaxDelayedStarvationTasks = 3;
-
- private:
- // Returns the priority which is next after |priority|.
- static TaskQueue::QueuePriority NextPriority(
- TaskQueue::QueuePriority priority);
-
- bool SelectWorkQueueToServiceInternal(WorkQueue** out_work_queue);
-
- // Called whenever the selector chooses a task queue for execution with the
- // priority |priority|.
- void DidSelectQueueWithPriority(TaskQueue::QueuePriority priority,
- bool chose_delayed_over_immediate);
-
- // Returns true if there are pending tasks with priority |priority|.
- bool HasTasksWithPriority(TaskQueue::QueuePriority priority);
-
- ThreadChecker main_thread_checker_;
-
- PrioritizingSelector prioritizing_selector_;
- size_t immediate_starvation_count_;
- size_t high_priority_starvation_score_;
- size_t normal_priority_starvation_score_;
- size_t low_priority_starvation_score_;
-
- Observer* task_queue_selector_observer_; // NOT OWNED
- DISALLOW_COPY_AND_ASSIGN(TaskQueueSelector);
-};
-
-} // namespace internal
-} // namespace sequence_manager
-} // namespace base
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_SELECTOR_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector_logic.h b/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector_logic.h
deleted file mode 100644
index 0e85d67bfe2..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector_logic.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_SELECTOR_LOGIC_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_SELECTOR_LOGIC_H_
-
-namespace base {
-namespace sequence_manager {
-
-// Used to describe the logic trigerred when a task queue is selected to
-// service.
-// This enum is used for histograms and should not be renumbered.
-enum class TaskQueueSelectorLogic {
-
- // Selected due to priority rules.
- kControlPriorityLogic = 0,
- kHighestPriorityLogic = 1,
- kHighPriorityLogic = 2,
- kNormalPriorityLogic = 3,
- kLowPriorityLogic = 4,
- kBestEffortPriorityLogic = 5,
-
- // Selected due to starvation logic.
- kHighPriorityStarvationLogic = 6,
- kNormalPriorityStarvationLogic = 7,
- kLowPriorityStarvationLogic = 8,
-
- kCount = 9,
-};
-
-} // namespace sequence_manager
-} // namespace base
-
-#endif
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector_unittest.cc
deleted file mode 100644
index 2638d8b342e..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector_unittest.cc
+++ /dev/null
@@ -1,878 +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/platform/scheduler/base/task_queue_selector.h"
-
-#include <stddef.h>
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/pending_task.h"
-#include "base/test/histogram_tester.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/virtual_time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/base/work_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h"
-
-using testing::_;
-
-namespace base {
-namespace sequence_manager {
-namespace internal {
-// To avoid symbol collisions in jumbo builds.
-namespace task_queue_selector_unittest {
-
-class MockObserver : public TaskQueueSelector::Observer {
- public:
- MockObserver() = default;
- ~MockObserver() override = default;
-
- MOCK_METHOD1(OnTaskQueueEnabled, void(internal::TaskQueueImpl*));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockObserver);
-};
-
-class TaskQueueSelectorForTest : public TaskQueueSelector {
- public:
- using TaskQueueSelector::prioritizing_selector_for_test;
- using TaskQueueSelector::PrioritizingSelector;
- using TaskQueueSelector::SetImmediateStarvationCountForTest;
-
- // Returns the number of highest priority tasks needed to starve high priority
- // task.
- static constexpr size_t NumberOfHighestPriorityToStarveHighPriority() {
- return (kMaxHighPriorityStarvationScore +
- kSmallScoreIncrementForHighPriorityStarvation - 1) /
- kSmallScoreIncrementForHighPriorityStarvation;
- }
-
- // Returns the number of highest priority tasks needed to starve normal
- // priority tasks.
- static constexpr size_t NumberOfHighestPriorityToStarveNormalPriority() {
- return (kMaxNormalPriorityStarvationScore +
- kSmallScoreIncrementForNormalPriorityStarvation - 1) /
- kSmallScoreIncrementForNormalPriorityStarvation;
- }
-
- // Returns the number of high priority tasks needed to starve normal priority
- // tasks.
- static constexpr size_t NumberOfHighPriorityToStarveNormalPriority() {
- return (kMaxNormalPriorityStarvationScore +
- kLargeScoreIncrementForNormalPriorityStarvation - 1) /
- kLargeScoreIncrementForNormalPriorityStarvation;
- }
-
- // Returns the number of highest priority tasks needed to starve low priority
- // ones.
- static constexpr size_t NumberOfHighestPriorityToStarveLowPriority() {
- return (kMaxLowPriorityStarvationScore +
- kSmallScoreIncrementForLowPriorityStarvation - 1) /
- kSmallScoreIncrementForLowPriorityStarvation;
- }
-
- // Returns the number of high/normal priority tasks needed to starve low
- // priority ones.
- static constexpr size_t NumberOfHighAndNormalPriorityToStarveLowPriority() {
- return (kMaxLowPriorityStarvationScore +
- kLargeScoreIncrementForLowPriorityStarvation - 1) /
- kLargeScoreIncrementForLowPriorityStarvation;
- }
-};
-
-class TaskQueueSelectorTest : public testing::Test {
- public:
- TaskQueueSelectorTest()
- : test_closure_(BindRepeating(&TaskQueueSelectorTest::TestFunction)) {}
- ~TaskQueueSelectorTest() override = default;
-
- TaskQueueSelectorForTest::PrioritizingSelector* prioritizing_selector() {
- return selector_.prioritizing_selector_for_test();
- }
-
- WorkQueueSets* delayed_work_queue_sets() {
- return prioritizing_selector()->delayed_work_queue_sets();
- }
- WorkQueueSets* immediate_work_queue_sets() {
- return prioritizing_selector()->immediate_work_queue_sets();
- }
-
- void PushTasks(const size_t queue_indices[], size_t num_tasks) {
- std::set<size_t> changed_queue_set;
- for (size_t i = 0; i < num_tasks; i++) {
- changed_queue_set.insert(queue_indices[i]);
- task_queues_[queue_indices[i]]->immediate_work_queue()->Push(
- TaskQueueImpl::Task(TaskQueue::PostedTask(test_closure_, FROM_HERE),
- TimeTicks(), 0, i));
- }
- }
-
- void PushTasksWithEnqueueOrder(const size_t queue_indices[],
- const size_t enqueue_orders[],
- size_t num_tasks) {
- std::set<size_t> changed_queue_set;
- for (size_t i = 0; i < num_tasks; i++) {
- changed_queue_set.insert(queue_indices[i]);
- task_queues_[queue_indices[i]]->immediate_work_queue()->Push(
- TaskQueueImpl::Task(TaskQueue::PostedTask(test_closure_, FROM_HERE),
- TimeTicks(), 0, enqueue_orders[i]));
- }
- }
-
- std::vector<size_t> PopTasks() {
- std::vector<size_t> order;
- WorkQueue* chosen_work_queue;
- while (selector_.SelectWorkQueueToService(&chosen_work_queue)) {
- size_t chosen_queue_index =
- queue_to_index_map_.find(chosen_work_queue->task_queue())->second;
- order.push_back(chosen_queue_index);
- chosen_work_queue->PopTaskForTesting();
- immediate_work_queue_sets()->OnPopQueue(chosen_work_queue);
- }
- return order;
- }
-
- static void TestFunction() {}
-
- protected:
- void SetUp() final {
- virtual_time_domain_ = std::make_unique<VirtualTimeDomain>(
- TimeTicks() + TimeDelta::FromSeconds(1));
- for (size_t i = 0; i < kTaskQueueCount; i++) {
- std::unique_ptr<TaskQueueImpl> task_queue =
- std::make_unique<TaskQueueImpl>(nullptr, virtual_time_domain_.get(),
- TaskQueue::Spec("test"));
- selector_.AddQueue(task_queue.get());
- task_queues_.push_back(std::move(task_queue));
- }
- for (size_t i = 0; i < kTaskQueueCount; i++) {
- EXPECT_EQ(TaskQueue::kNormalPriority, task_queues_[i]->GetQueuePriority())
- << i;
- queue_to_index_map_.insert(std::make_pair(task_queues_[i].get(), i));
- }
- histogram_tester_.reset(new HistogramTester());
- }
-
- void TearDown() final {
- for (std::unique_ptr<TaskQueueImpl>& task_queue : task_queues_) {
- // Note since this test doesn't have a TaskQueueManager we need to
- // manually remove |task_queue| from the |selector_|. Normally
- // UnregisterTaskQueue would do that.
- selector_.RemoveQueue(task_queue.get());
- task_queue->UnregisterTaskQueue();
- }
- }
-
- std::unique_ptr<TaskQueueImpl> NewTaskQueueWithBlockReporting() {
- return std::make_unique<TaskQueueImpl>(nullptr, virtual_time_domain_.get(),
- TaskQueue::Spec("test"));
- }
-
- const size_t kTaskQueueCount = 5;
- RepeatingClosure test_closure_;
- TaskQueueSelectorForTest selector_;
- std::unique_ptr<VirtualTimeDomain> virtual_time_domain_;
- std::vector<std::unique_ptr<TaskQueueImpl>> task_queues_;
- std::map<TaskQueueImpl*, size_t> queue_to_index_map_;
- std::unique_ptr<HistogramTester> histogram_tester_;
-};
-
-TEST_F(TaskQueueSelectorTest, TestDefaultPriority) {
- size_t queue_order[] = {4, 3, 2, 1, 0};
- PushTasks(queue_order, 5);
- EXPECT_THAT(PopTasks(), testing::ElementsAre(4, 3, 2, 1, 0));
- EXPECT_EQ(histogram_tester_->GetBucketCount(
- "TaskQueueSelector.TaskServicedPerSelectorLogic",
- static_cast<int>(TaskQueueSelectorLogic::kNormalPriorityLogic)),
- 5);
-}
-
-TEST_F(TaskQueueSelectorTest, TestHighestPriority) {
- size_t queue_order[] = {0, 1, 2, 3, 4};
- PushTasks(queue_order, 5);
- selector_.SetQueuePriority(task_queues_[2].get(),
- TaskQueue::kHighestPriority);
- EXPECT_THAT(PopTasks(), ::testing::ElementsAre(2, 0, 1, 3, 4));
- EXPECT_EQ(
- histogram_tester_->GetBucketCount(
- "TaskQueueSelector.TaskServicedPerSelectorLogic",
- static_cast<int>(TaskQueueSelectorLogic::kHighestPriorityLogic)),
- 1);
-}
-
-TEST_F(TaskQueueSelectorTest, TestHighPriority) {
- size_t queue_order[] = {0, 1, 2, 3, 4};
- PushTasks(queue_order, 5);
- selector_.SetQueuePriority(task_queues_[2].get(),
- TaskQueue::kHighestPriority);
- selector_.SetQueuePriority(task_queues_[1].get(), TaskQueue::kHighPriority);
- selector_.SetQueuePriority(task_queues_[0].get(), TaskQueue::kLowPriority);
- EXPECT_THAT(PopTasks(), ::testing::ElementsAre(2, 1, 3, 4, 0));
- EXPECT_EQ(histogram_tester_->GetBucketCount(
- "TaskQueueSelector.TaskServicedPerSelectorLogic",
- static_cast<int>(TaskQueueSelectorLogic::kHighPriorityLogic)),
- 1);
-}
-
-TEST_F(TaskQueueSelectorTest, TestLowPriority) {
- size_t queue_order[] = {0, 1, 2, 3, 4};
- PushTasks(queue_order, 5);
- selector_.SetQueuePriority(task_queues_[2].get(), TaskQueue::kLowPriority);
- EXPECT_THAT(PopTasks(), testing::ElementsAre(0, 1, 3, 4, 2));
- EXPECT_EQ(histogram_tester_->GetBucketCount(
- "TaskQueueSelector.TaskServicedPerSelectorLogic",
- static_cast<int>(TaskQueueSelectorLogic::kLowPriorityLogic)),
- 1);
-}
-
-TEST_F(TaskQueueSelectorTest, TestBestEffortPriority) {
- size_t queue_order[] = {0, 1, 2, 3, 4};
- PushTasks(queue_order, 5);
- selector_.SetQueuePriority(task_queues_[0].get(),
- TaskQueue::kBestEffortPriority);
- selector_.SetQueuePriority(task_queues_[2].get(), TaskQueue::kLowPriority);
- selector_.SetQueuePriority(task_queues_[3].get(),
- TaskQueue::kHighestPriority);
- EXPECT_THAT(PopTasks(), ::testing::ElementsAre(3, 1, 4, 2, 0));
- EXPECT_EQ(
- histogram_tester_->GetBucketCount(
- "TaskQueueSelector.TaskServicedPerSelectorLogic",
- static_cast<int>(TaskQueueSelectorLogic::kBestEffortPriorityLogic)),
- 1);
-}
-
-TEST_F(TaskQueueSelectorTest, TestControlPriority) {
- size_t queue_order[] = {0, 1, 2, 3, 4};
- PushTasks(queue_order, 5);
- selector_.SetQueuePriority(task_queues_[4].get(),
- TaskQueue::kControlPriority);
- EXPECT_EQ(TaskQueue::kControlPriority, task_queues_[4]->GetQueuePriority());
- selector_.SetQueuePriority(task_queues_[2].get(),
- TaskQueue::kHighestPriority);
- EXPECT_EQ(TaskQueue::kHighestPriority, task_queues_[2]->GetQueuePriority());
- EXPECT_THAT(PopTasks(), ::testing::ElementsAre(4, 2, 0, 1, 3));
- EXPECT_EQ(
- histogram_tester_->GetBucketCount(
- "TaskQueueSelector.TaskServicedPerSelectorLogic",
- static_cast<int>(TaskQueueSelectorLogic::kControlPriorityLogic)),
- 1);
-}
-
-TEST_F(TaskQueueSelectorTest, TestObserverWithEnabledQueue) {
- task_queues_[1]->SetQueueEnabledForTest(false);
- selector_.DisableQueue(task_queues_[1].get());
- MockObserver mock_observer;
- selector_.SetTaskQueueSelectorObserver(&mock_observer);
- EXPECT_CALL(mock_observer, OnTaskQueueEnabled(_)).Times(1);
- task_queues_[1]->SetQueueEnabledForTest(true);
- selector_.EnableQueue(task_queues_[1].get());
-}
-
-TEST_F(TaskQueueSelectorTest,
- TestObserverWithSetQueuePriorityAndQueueAlreadyEnabled) {
- selector_.SetQueuePriority(task_queues_[1].get(),
- TaskQueue::kHighestPriority);
- MockObserver mock_observer;
- selector_.SetTaskQueueSelectorObserver(&mock_observer);
- EXPECT_CALL(mock_observer, OnTaskQueueEnabled(_)).Times(0);
- selector_.SetQueuePriority(task_queues_[1].get(), TaskQueue::kNormalPriority);
-}
-
-TEST_F(TaskQueueSelectorTest, TestDisableEnable) {
- MockObserver mock_observer;
- selector_.SetTaskQueueSelectorObserver(&mock_observer);
-
- size_t queue_order[] = {0, 1, 2, 3, 4};
- PushTasks(queue_order, 5);
- task_queues_[2]->SetQueueEnabledForTest(false);
- selector_.DisableQueue(task_queues_[2].get());
- task_queues_[4]->SetQueueEnabledForTest(false);
- selector_.DisableQueue(task_queues_[4].get());
- // Disabling a queue should not affect its priority.
- EXPECT_EQ(TaskQueue::kNormalPriority, task_queues_[2]->GetQueuePriority());
- EXPECT_EQ(TaskQueue::kNormalPriority, task_queues_[4]->GetQueuePriority());
- EXPECT_THAT(PopTasks(), testing::ElementsAre(0, 1, 3));
-
- EXPECT_CALL(mock_observer, OnTaskQueueEnabled(_)).Times(2);
- task_queues_[2]->SetQueueEnabledForTest(true);
- selector_.EnableQueue(task_queues_[2].get());
- selector_.SetQueuePriority(task_queues_[2].get(),
- TaskQueue::kBestEffortPriority);
- EXPECT_THAT(PopTasks(), testing::ElementsAre(2));
- task_queues_[4]->SetQueueEnabledForTest(true);
- selector_.EnableQueue(task_queues_[4].get());
- EXPECT_THAT(PopTasks(), testing::ElementsAre(4));
-}
-
-TEST_F(TaskQueueSelectorTest, TestDisableChangePriorityThenEnable) {
- EXPECT_TRUE(task_queues_[2]->delayed_work_queue()->Empty());
- EXPECT_TRUE(task_queues_[2]->immediate_work_queue()->Empty());
-
- task_queues_[2]->SetQueueEnabledForTest(false);
- selector_.SetQueuePriority(task_queues_[2].get(),
- TaskQueue::kHighestPriority);
-
- size_t queue_order[] = {0, 1, 2, 3, 4};
- PushTasks(queue_order, 5);
-
- EXPECT_TRUE(task_queues_[2]->delayed_work_queue()->Empty());
- EXPECT_FALSE(task_queues_[2]->immediate_work_queue()->Empty());
- task_queues_[2]->SetQueueEnabledForTest(true);
-
- EXPECT_EQ(TaskQueue::kHighestPriority, task_queues_[2]->GetQueuePriority());
- EXPECT_THAT(PopTasks(), ::testing::ElementsAre(2, 0, 1, 3, 4));
-}
-
-TEST_F(TaskQueueSelectorTest, TestEmptyQueues) {
- WorkQueue* chosen_work_queue = nullptr;
- EXPECT_FALSE(selector_.SelectWorkQueueToService(&chosen_work_queue));
-
- // Test only disabled queues.
- size_t queue_order[] = {0};
- PushTasks(queue_order, 1);
- task_queues_[0]->SetQueueEnabledForTest(false);
- selector_.DisableQueue(task_queues_[0].get());
- EXPECT_FALSE(selector_.SelectWorkQueueToService(&chosen_work_queue));
-
- // These tests are unusual since there's no TQM. To avoid a later DCHECK when
- // deleting the task queue, we re-enable the queue here so the selector
- // doesn't get out of sync.
- task_queues_[0]->SetQueueEnabledForTest(true);
- selector_.EnableQueue(task_queues_[0].get());
-}
-
-TEST_F(TaskQueueSelectorTest, TestAge) {
- size_t enqueue_order[] = {10, 1, 2, 9, 4};
- size_t queue_order[] = {0, 1, 2, 3, 4};
- PushTasksWithEnqueueOrder(queue_order, enqueue_order, 5);
- EXPECT_THAT(PopTasks(), testing::ElementsAre(1, 2, 4, 3, 0));
-}
-
-TEST_F(TaskQueueSelectorTest, TestControlStarvesOthers) {
- size_t queue_order[] = {0, 1, 2, 3};
- PushTasks(queue_order, 4);
- selector_.SetQueuePriority(task_queues_[3].get(),
- TaskQueue::kControlPriority);
- selector_.SetQueuePriority(task_queues_[2].get(),
- TaskQueue::kHighestPriority);
- selector_.SetQueuePriority(task_queues_[1].get(),
- TaskQueue::kBestEffortPriority);
- for (int i = 0; i < 100; i++) {
- WorkQueue* chosen_work_queue = nullptr;
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
- EXPECT_EQ(task_queues_[3].get(), chosen_work_queue->task_queue());
- // Don't remove task from queue to simulate all queues still being full.
- }
-}
-
-TEST_F(TaskQueueSelectorTest, TestHighestPriorityDoesNotStarveHigh) {
- size_t queue_order[] = {0, 1};
- PushTasks(queue_order, 2);
- selector_.SetQueuePriority(task_queues_[0].get(),
- TaskQueue::kHighestPriority);
- selector_.SetQueuePriority(task_queues_[1].get(), TaskQueue::kHighPriority);
-
- size_t counts[] = {0, 0};
- for (int i = 0; i < 100; i++) {
- WorkQueue* chosen_work_queue = nullptr;
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
- size_t chosen_queue_index =
- queue_to_index_map_.find(chosen_work_queue->task_queue())->second;
- counts[chosen_queue_index]++;
- // Don't remove task from queue to simulate all queues still being full.
- }
- EXPECT_GT(counts[1], 0ul); // Check highest doesn't starve high.
- EXPECT_GT(counts[0], counts[1]); // Check highest gets more chance to run.
-}
-
-TEST_F(TaskQueueSelectorTest, TestHighestPriorityDoesNotStarveHighOrNormal) {
- size_t queue_order[] = {0, 1, 2};
- PushTasks(queue_order, 3);
- selector_.SetQueuePriority(task_queues_[0].get(),
- TaskQueue::kHighestPriority);
- selector_.SetQueuePriority(task_queues_[1].get(), TaskQueue::kHighPriority);
-
- size_t counts[] = {0, 0, 0};
- for (int i = 0; i < 100; i++) {
- WorkQueue* chosen_work_queue = nullptr;
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
- size_t chosen_queue_index =
- queue_to_index_map_.find(chosen_work_queue->task_queue())->second;
- counts[chosen_queue_index]++;
- // Don't remove task from queue to simulate all queues still being full.
- }
-
- // Check highest runs more frequently then high.
- EXPECT_GT(counts[0], counts[1]);
-
- // Check high runs at least as frequently as normal.
- EXPECT_GE(counts[1], counts[2]);
-
- // Check normal isn't starved.
- EXPECT_GT(counts[2], 0ul);
-}
-
-TEST_F(TaskQueueSelectorTest,
- TestHighestPriorityDoesNotStarveHighOrNormalOrLow) {
- size_t queue_order[] = {0, 1, 2, 3};
- PushTasks(queue_order, 4);
- selector_.SetQueuePriority(task_queues_[0].get(),
- TaskQueue::kHighestPriority);
- selector_.SetQueuePriority(task_queues_[1].get(), TaskQueue::kHighPriority);
- selector_.SetQueuePriority(task_queues_[3].get(), TaskQueue::kLowPriority);
-
- size_t counts[] = {0, 0, 0, 0};
- for (int i = 0; i < 100; i++) {
- WorkQueue* chosen_work_queue = nullptr;
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
- size_t chosen_queue_index =
- queue_to_index_map_.find(chosen_work_queue->task_queue())->second;
- counts[chosen_queue_index]++;
- // Don't remove task from queue to simulate all queues still being full.
- }
-
- // Check highest runs more frequently then high.
- EXPECT_GT(counts[0], counts[1]);
-
- // Check high runs at least as frequently as normal.
- EXPECT_GE(counts[1], counts[2]);
-
- // Check normal runs more frequently than low.
- EXPECT_GT(counts[2], counts[3]);
-
- // Check low isn't starved.
- EXPECT_GT(counts[3], 0ul);
-}
-
-TEST_F(TaskQueueSelectorTest, TestHighPriorityDoesNotStarveNormal) {
- size_t queue_order[] = {0, 1};
- PushTasks(queue_order, 2);
-
- selector_.SetQueuePriority(task_queues_[0].get(), TaskQueue::kHighPriority);
-
- size_t counts[] = {0, 0, 0, 0};
- for (int i = 0; i < 100; i++) {
- WorkQueue* chosen_work_queue = nullptr;
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
- size_t chosen_queue_index =
- queue_to_index_map_.find(chosen_work_queue->task_queue())->second;
- counts[chosen_queue_index]++;
- // Don't remove task from queue to simulate all queues still being full.
- }
-
- // Check high runs more frequently then normal.
- EXPECT_GT(counts[0], counts[1]);
-
- // Check low isn't starved.
- EXPECT_GT(counts[1], 0ul);
-}
-
-TEST_F(TaskQueueSelectorTest, TestHighPriorityDoesNotStarveNormalOrLow) {
- size_t queue_order[] = {0, 1, 2};
- PushTasks(queue_order, 3);
- selector_.SetQueuePriority(task_queues_[0].get(), TaskQueue::kHighPriority);
- selector_.SetQueuePriority(task_queues_[2].get(), TaskQueue::kLowPriority);
-
- size_t counts[] = {0, 0, 0};
- for (int i = 0; i < 100; i++) {
- WorkQueue* chosen_work_queue = nullptr;
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
- size_t chosen_queue_index =
- queue_to_index_map_.find(chosen_work_queue->task_queue())->second;
- counts[chosen_queue_index]++;
- // Don't remove task from queue to simulate all queues still being full.
- }
-
- // Check high runs more frequently than normal.
- EXPECT_GT(counts[0], counts[1]);
-
- // Check normal runs more frequently than low.
- EXPECT_GT(counts[1], counts[2]);
-
- // Check low isn't starved.
- EXPECT_GT(counts[2], 0ul);
-}
-
-TEST_F(TaskQueueSelectorTest, TestNormalPriorityDoesNotStarveLow) {
- size_t queue_order[] = {0, 1, 2};
- PushTasks(queue_order, 3);
- selector_.SetQueuePriority(task_queues_[0].get(), TaskQueue::kLowPriority);
- selector_.SetQueuePriority(task_queues_[1].get(),
- TaskQueue::kBestEffortPriority);
- size_t counts[] = {0, 0, 0};
- for (int i = 0; i < 100; i++) {
- WorkQueue* chosen_work_queue = nullptr;
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
- size_t chosen_queue_index =
- queue_to_index_map_.find(chosen_work_queue->task_queue())->second;
- counts[chosen_queue_index]++;
- // Don't remove task from queue to simulate all queues still being full.
- }
- EXPECT_GT(counts[0], 0ul); // Check normal doesn't starve low.
- EXPECT_GT(counts[2], counts[0]); // Check normal gets more chance to run.
- EXPECT_EQ(0ul, counts[1]); // Check best effort is starved.
-}
-
-TEST_F(TaskQueueSelectorTest, TestBestEffortGetsStarved) {
- size_t queue_order[] = {0, 1};
- PushTasks(queue_order, 2);
- selector_.SetQueuePriority(task_queues_[0].get(),
- TaskQueue::kBestEffortPriority);
- EXPECT_EQ(TaskQueue::kNormalPriority, task_queues_[1]->GetQueuePriority());
-
- // Check that normal priority tasks starve best effort.
- WorkQueue* chosen_work_queue = nullptr;
- for (int i = 0; i < 100; i++) {
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
- EXPECT_EQ(task_queues_[1].get(), chosen_work_queue->task_queue());
- // Don't remove task from queue to simulate all queues still being full.
- }
-
- // Check that highest priority tasks starve best effort.
- selector_.SetQueuePriority(task_queues_[1].get(),
- TaskQueue::kHighestPriority);
- for (int i = 0; i < 100; i++) {
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
- EXPECT_EQ(task_queues_[1].get(), chosen_work_queue->task_queue());
- // Don't remove task from queue to simulate all queues still being full.
- }
-
- // Check that high priority tasks starve best effort.
- selector_.SetQueuePriority(task_queues_[1].get(), TaskQueue::kHighPriority);
- for (int i = 0; i < 100; i++) {
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
- EXPECT_EQ(task_queues_[1].get(), chosen_work_queue->task_queue());
- // Don't remove task from queue to simulate all queues still being full.
- }
-
- // Check that low priority tasks starve best effort.
- selector_.SetQueuePriority(task_queues_[1].get(), TaskQueue::kLowPriority);
- for (int i = 0; i < 100; i++) {
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
- EXPECT_EQ(task_queues_[1].get(), chosen_work_queue->task_queue());
- // Don't remove task from queue to simulate all queues still being full.
- }
-
- // Check that control priority tasks starve best effort.
- selector_.SetQueuePriority(task_queues_[1].get(),
- TaskQueue::kControlPriority);
- for (int i = 0; i < 100; i++) {
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
- EXPECT_EQ(task_queues_[1].get(), chosen_work_queue->task_queue());
- // Don't remove task from queue to simulate all queues still being full.
- }
-}
-
-TEST_F(TaskQueueSelectorTest,
- TestHighPriorityStarvationScoreIncreasedOnlyWhenTasksArePresent) {
- size_t queue_order[] = {0, 1};
- PushTasks(queue_order, 2);
- selector_.SetQueuePriority(task_queues_[0].get(),
- TaskQueue::kHighestPriority);
- selector_.SetQueuePriority(task_queues_[1].get(),
- TaskQueue::kHighestPriority);
-
- // Run a number of highest priority tasks needed to starve high priority
- // tasks (when present).
- for (size_t num_tasks = 0;
- num_tasks <=
- TaskQueueSelectorForTest::NumberOfHighestPriorityToStarveHighPriority();
- num_tasks++) {
- WorkQueue* chosen_work_queue = nullptr;
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
- // Don't remove task from queue to simulate the queue is still full.
- }
-
- // Post a high priority task.
- selector_.SetQueuePriority(task_queues_[1].get(), TaskQueue::kHighPriority);
- WorkQueue* chosen_work_queue = nullptr;
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
-
- // Check that the high priority task is not considered starved, and thus isn't
- // processed.
- EXPECT_NE(
- static_cast<int>(
- queue_to_index_map_.find(chosen_work_queue->task_queue())->second),
- 1);
-}
-
-TEST_F(TaskQueueSelectorTest,
- TestNormalPriorityStarvationScoreIncreasedOnllWhenTasksArePresent) {
- size_t queue_order[] = {0, 1};
- PushTasks(queue_order, 2);
- selector_.SetQueuePriority(task_queues_[0].get(),
- TaskQueue::kHighestPriority);
- selector_.SetQueuePriority(task_queues_[1].get(),
- TaskQueue::kHighestPriority);
-
- // Run a number of highest priority tasks needed to starve normal priority
- // tasks (when present).
- for (size_t num_tasks = 0;
- num_tasks <= TaskQueueSelectorForTest::
- NumberOfHighestPriorityToStarveNormalPriority();
- num_tasks++) {
- WorkQueue* chosen_work_queue = nullptr;
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
- // Don't remove task from queue to simulate the queue is still full.
- }
-
- selector_.SetQueuePriority(task_queues_[0].get(), TaskQueue::kHighPriority);
- selector_.SetQueuePriority(task_queues_[1].get(), TaskQueue::kHighPriority);
-
- // Run a number of high priority tasks needed to starve normal priority
- // tasks (when present).
- for (size_t num_tasks = 0;
- num_tasks <=
- TaskQueueSelectorForTest::NumberOfHighPriorityToStarveNormalPriority();
- num_tasks++) {
- WorkQueue* chosen_work_queue = nullptr;
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
- // Don't remove task from queue to simulate the queue is still full.
- }
-
- // Post a normal priority task.
- selector_.SetQueuePriority(task_queues_[1].get(), TaskQueue::kNormalPriority);
- WorkQueue* chosen_work_queue = nullptr;
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
-
- // Check that the normal priority task is not considered starved, and thus
- // isn't processed.
- EXPECT_NE(
- static_cast<int>(
- queue_to_index_map_.find(chosen_work_queue->task_queue())->second),
- 1);
-}
-
-TEST_F(TaskQueueSelectorTest,
- TestLowPriorityTaskStarvationOnlyIncreasedWhenTasksArePresent) {
- size_t queue_order[] = {0, 1};
- PushTasks(queue_order, 2);
- selector_.SetQueuePriority(task_queues_[0].get(),
- TaskQueue::kHighestPriority);
- selector_.SetQueuePriority(task_queues_[1].get(),
- TaskQueue::kHighestPriority);
-
- // Run a number of highest priority tasks needed to starve low priority
- // tasks (when present).
- for (size_t num_tasks = 0;
- num_tasks <=
- TaskQueueSelectorForTest::NumberOfHighestPriorityToStarveLowPriority();
- num_tasks++) {
- WorkQueue* chosen_work_queue = nullptr;
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
- // Don't remove task from queue to simulate the queue is still full.
- }
-
- selector_.SetQueuePriority(task_queues_[0].get(), TaskQueue::kHighPriority);
- selector_.SetQueuePriority(task_queues_[1].get(), TaskQueue::kNormalPriority);
-
- // Run a number of high/normal priority tasks needed to starve low priority
- // tasks (when present).
- for (size_t num_tasks = 0;
- num_tasks <= TaskQueueSelectorForTest::
- NumberOfHighAndNormalPriorityToStarveLowPriority();
- num_tasks++) {
- WorkQueue* chosen_work_queue = nullptr;
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
- // Don't remove task from queue to simulate the queue is still full.
- }
-
- // Post a low priority task.
- selector_.SetQueuePriority(task_queues_[1].get(), TaskQueue::kLowPriority);
- WorkQueue* chosen_work_queue = nullptr;
- ASSERT_TRUE(selector_.SelectWorkQueueToService(&chosen_work_queue));
-
- // Check that the low priority task is not considered starved, and thus
- // isn't processed.
- EXPECT_NE(
- static_cast<int>(
- queue_to_index_map_.find(chosen_work_queue->task_queue())->second),
- 1);
-}
-
-TEST_F(TaskQueueSelectorTest, AllEnabledWorkQueuesAreEmpty) {
- EXPECT_TRUE(selector_.AllEnabledWorkQueuesAreEmpty());
- size_t queue_order[] = {0, 1};
- PushTasks(queue_order, 2);
-
- EXPECT_FALSE(selector_.AllEnabledWorkQueuesAreEmpty());
- PopTasks();
- EXPECT_TRUE(selector_.AllEnabledWorkQueuesAreEmpty());
-}
-
-TEST_F(TaskQueueSelectorTest, AllEnabledWorkQueuesAreEmpty_ControlPriority) {
- size_t queue_order[] = {0};
- PushTasks(queue_order, 1);
-
- selector_.SetQueuePriority(task_queues_[0].get(),
- TaskQueue::kControlPriority);
-
- EXPECT_FALSE(selector_.AllEnabledWorkQueuesAreEmpty());
-}
-
-TEST_F(TaskQueueSelectorTest, ChooseOldestWithPriority_Empty) {
- WorkQueue* chosen_work_queue = nullptr;
- bool chose_delayed_over_immediate = false;
- EXPECT_FALSE(prioritizing_selector()->ChooseOldestWithPriority(
- TaskQueue::kNormalPriority, &chose_delayed_over_immediate,
- &chosen_work_queue));
- EXPECT_FALSE(chose_delayed_over_immediate);
-}
-
-TEST_F(TaskQueueSelectorTest, ChooseOldestWithPriority_OnlyDelayed) {
- task_queues_[0]->delayed_work_queue()->Push(TaskQueueImpl::Task(
- TaskQueue::PostedTask(test_closure_, FROM_HERE), TimeTicks(), 0, 0));
-
- WorkQueue* chosen_work_queue = nullptr;
- bool chose_delayed_over_immediate = false;
- EXPECT_TRUE(prioritizing_selector()->ChooseOldestWithPriority(
- TaskQueue::kNormalPriority, &chose_delayed_over_immediate,
- &chosen_work_queue));
- EXPECT_EQ(chosen_work_queue, task_queues_[0]->delayed_work_queue());
- EXPECT_FALSE(chose_delayed_over_immediate);
-}
-
-TEST_F(TaskQueueSelectorTest, ChooseOldestWithPriority_OnlyImmediate) {
- task_queues_[0]->immediate_work_queue()->Push(TaskQueueImpl::Task(
- TaskQueue::PostedTask(test_closure_, FROM_HERE), TimeTicks(), 0, 0));
-
- WorkQueue* chosen_work_queue = nullptr;
- bool chose_delayed_over_immediate = false;
- EXPECT_TRUE(prioritizing_selector()->ChooseOldestWithPriority(
- TaskQueue::kNormalPriority, &chose_delayed_over_immediate,
- &chosen_work_queue));
- EXPECT_EQ(chosen_work_queue, task_queues_[0]->immediate_work_queue());
- EXPECT_FALSE(chose_delayed_over_immediate);
-}
-
-TEST_F(TaskQueueSelectorTest, TestObserverWithOneBlockedQueue) {
- TaskQueueSelectorForTest selector;
- MockObserver mock_observer;
- selector.SetTaskQueueSelectorObserver(&mock_observer);
-
- EXPECT_CALL(mock_observer, OnTaskQueueEnabled(_)).Times(1);
-
- std::unique_ptr<TaskQueueImpl> task_queue(NewTaskQueueWithBlockReporting());
- selector.AddQueue(task_queue.get());
-
- task_queue->SetQueueEnabledForTest(false);
- selector.DisableQueue(task_queue.get());
-
- TaskQueueImpl::Task task(TaskQueue::PostedTask(test_closure_, FROM_HERE),
- TimeTicks(), 0);
- task.set_enqueue_order(0);
- task_queue->immediate_work_queue()->Push(std::move(task));
-
- WorkQueue* chosen_work_queue;
- EXPECT_FALSE(selector.SelectWorkQueueToService(&chosen_work_queue));
-
- task_queue->SetQueueEnabledForTest(true);
- selector.EnableQueue(task_queue.get());
- selector.RemoveQueue(task_queue.get());
- task_queue->UnregisterTaskQueue();
-}
-
-TEST_F(TaskQueueSelectorTest, TestObserverWithTwoBlockedQueues) {
- TaskQueueSelectorForTest selector;
- MockObserver mock_observer;
- selector.SetTaskQueueSelectorObserver(&mock_observer);
-
- std::unique_ptr<TaskQueueImpl> task_queue(NewTaskQueueWithBlockReporting());
- std::unique_ptr<TaskQueueImpl> task_queue2(NewTaskQueueWithBlockReporting());
- selector.AddQueue(task_queue.get());
- selector.AddQueue(task_queue2.get());
-
- task_queue->SetQueueEnabledForTest(false);
- task_queue2->SetQueueEnabledForTest(false);
- selector.DisableQueue(task_queue.get());
- selector.DisableQueue(task_queue2.get());
-
- selector.SetQueuePriority(task_queue2.get(), TaskQueue::kControlPriority);
-
- TaskQueueImpl::Task task1(TaskQueue::PostedTask(test_closure_, FROM_HERE),
- TimeTicks(), 0);
- TaskQueueImpl::Task task2(TaskQueue::PostedTask(test_closure_, FROM_HERE),
- TimeTicks(), 1);
- task1.set_enqueue_order(0);
- task2.set_enqueue_order(1);
- task_queue->immediate_work_queue()->Push(std::move(task1));
- task_queue2->immediate_work_queue()->Push(std::move(task2));
-
- WorkQueue* chosen_work_queue;
- EXPECT_FALSE(selector.SelectWorkQueueToService(&chosen_work_queue));
- testing::Mock::VerifyAndClearExpectations(&mock_observer);
-
- EXPECT_CALL(mock_observer, OnTaskQueueEnabled(_)).Times(2);
-
- task_queue->SetQueueEnabledForTest(true);
- selector.EnableQueue(task_queue.get());
-
- selector.RemoveQueue(task_queue.get());
- task_queue->UnregisterTaskQueue();
- EXPECT_FALSE(selector.SelectWorkQueueToService(&chosen_work_queue));
-
- task_queue2->SetQueueEnabledForTest(true);
- selector.EnableQueue(task_queue2.get());
- selector.RemoveQueue(task_queue2.get());
- task_queue2->UnregisterTaskQueue();
-}
-
-struct ChooseOldestWithPriorityTestParam {
- int delayed_task_enqueue_order;
- int immediate_task_enqueue_order;
- int immediate_starvation_count;
- const char* expected_work_queue_name;
- bool expected_did_starve_immediate_queue;
-};
-
-static const ChooseOldestWithPriorityTestParam
- kChooseOldestWithPriorityTestCases[] = {
- {1, 2, 0, "delayed", true}, {1, 2, 1, "delayed", true},
- {1, 2, 2, "delayed", true}, {1, 2, 3, "immediate", false},
- {1, 2, 4, "immediate", false}, {2, 1, 4, "immediate", false},
- {2, 1, 4, "immediate", false},
-};
-
-class ChooseOldestWithPriorityTest
- : public TaskQueueSelectorTest,
- public testing::WithParamInterface<ChooseOldestWithPriorityTestParam> {};
-
-TEST_P(ChooseOldestWithPriorityTest, RoundRobinTest) {
- task_queues_[0]->immediate_work_queue()->Push(
- TaskQueueImpl::Task(TaskQueue::PostedTask(test_closure_, FROM_HERE),
- TimeTicks(), GetParam().immediate_task_enqueue_order,
- GetParam().immediate_task_enqueue_order));
-
- task_queues_[0]->delayed_work_queue()->Push(
- TaskQueueImpl::Task(TaskQueue::PostedTask(test_closure_, FROM_HERE),
- TimeTicks(), GetParam().delayed_task_enqueue_order,
- GetParam().delayed_task_enqueue_order));
-
- selector_.SetImmediateStarvationCountForTest(
- GetParam().immediate_starvation_count);
-
- WorkQueue* chosen_work_queue = nullptr;
- bool chose_delayed_over_immediate = false;
- EXPECT_TRUE(prioritizing_selector()->ChooseOldestWithPriority(
- TaskQueue::kNormalPriority, &chose_delayed_over_immediate,
- &chosen_work_queue));
- EXPECT_EQ(chosen_work_queue->task_queue(), task_queues_[0].get());
- EXPECT_STREQ(chosen_work_queue->name(), GetParam().expected_work_queue_name);
- EXPECT_EQ(chose_delayed_over_immediate,
- GetParam().expected_did_starve_immediate_queue);
-}
-
-INSTANTIATE_TEST_CASE_P(ChooseOldestWithPriorityTest,
- ChooseOldestWithPriorityTest,
- testing::ValuesIn(kChooseOldestWithPriorityTestCases));
-
-} // namespace task_queue_selector_unittest
-} // namespace internal
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/task_time_observer.h b/chromium/third_party/blink/renderer/platform/scheduler/base/task_time_observer.h
deleted file mode 100644
index 9704c222488..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/task_time_observer.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_TIME_OBSERVER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_TIME_OBSERVER_H_
-
-#include "base/time/time.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-
-namespace base {
-namespace sequence_manager {
-
-// TaskTimeObserver provides an API for observing completion of renderer tasks.
-class PLATFORM_EXPORT TaskTimeObserver {
- public:
- TaskTimeObserver() = default;
- virtual ~TaskTimeObserver() = default;
-
- // Callback to be called when task is about to start.
- // |start_time| - time in seconds when task started to run,
- virtual void WillProcessTask(double start_time) = 0;
-
- // Callback to be called when task is completed.
- // |start_time| - time in seconds when task started to run,
- // |end_time| - time in seconds when task was completed.
- virtual void DidProcessTask(double start_time, double end_time) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TaskTimeObserver);
-};
-
-} // namespace sequence_manager
-} // namespace base
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_TIME_OBSERVER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/thread_controller_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/thread_controller_impl.cc
deleted file mode 100644
index e108f455f21..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/thread_controller_impl.cc
+++ /dev/null
@@ -1,258 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/base/thread_controller_impl.h"
-
-#include "base/bind.h"
-#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/task/sequence_manager/lazy_now.h"
-#include "base/task/sequence_manager/sequenced_task_source.h"
-#include "base/trace_event/trace_event.h"
-
-namespace base {
-namespace sequence_manager {
-namespace internal {
-
-ThreadControllerImpl::ThreadControllerImpl(
- MessageLoop* message_loop,
- scoped_refptr<SingleThreadTaskRunner> task_runner,
- const TickClock* time_source)
- : message_loop_(message_loop),
- task_runner_(task_runner),
- message_loop_task_runner_(message_loop ? message_loop->task_runner()
- : nullptr),
- time_source_(time_source),
- weak_factory_(this) {
- immediate_do_work_closure_ =
- BindRepeating(&ThreadControllerImpl::DoWork, weak_factory_.GetWeakPtr(),
- WorkType::kImmediate);
- delayed_do_work_closure_ =
- BindRepeating(&ThreadControllerImpl::DoWork, weak_factory_.GetWeakPtr(),
- WorkType::kDelayed);
-}
-
-ThreadControllerImpl::~ThreadControllerImpl() = default;
-
-ThreadControllerImpl::AnySequence::AnySequence() = default;
-
-ThreadControllerImpl::AnySequence::~AnySequence() = default;
-
-ThreadControllerImpl::MainSequenceOnly::MainSequenceOnly() = default;
-
-ThreadControllerImpl::MainSequenceOnly::~MainSequenceOnly() = default;
-
-std::unique_ptr<ThreadControllerImpl> ThreadControllerImpl::Create(
- MessageLoop* message_loop,
- const TickClock* time_source) {
- return WrapUnique(new ThreadControllerImpl(
- message_loop, message_loop->task_runner(), time_source));
-}
-
-void ThreadControllerImpl::SetSequencedTaskSource(
- SequencedTaskSource* sequence) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(sequence);
- DCHECK(!sequence_);
- sequence_ = sequence;
-}
-
-void ThreadControllerImpl::ScheduleWork() {
- DCHECK(sequence_);
- AutoLock lock(any_sequence_lock_);
- // Don't post a DoWork if there's an immediate DoWork in flight or if we're
- // inside a top level DoWork. We can rely on a continuation being posted as
- // needed.
- if (any_sequence().immediate_do_work_posted ||
- (any_sequence().do_work_running_count > any_sequence().nesting_depth)) {
- return;
- }
- any_sequence().immediate_do_work_posted = true;
-
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
- "ThreadControllerImpl::ScheduleWork::PostTask");
- task_runner_->PostTask(FROM_HERE, immediate_do_work_closure_);
-}
-
-void ThreadControllerImpl::SetNextDelayedDoWork(LazyNow* lazy_now,
- TimeTicks run_time) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(sequence_);
-
- if (main_sequence_only().next_delayed_do_work == run_time)
- return;
-
- // Cancel DoWork if it was scheduled and we set an "infinite" delay now.
- if (run_time == TimeTicks::Max()) {
- cancelable_delayed_do_work_closure_.Cancel();
- main_sequence_only().next_delayed_do_work = TimeTicks::Max();
- return;
- }
-
- // If DoWork is running then we don't need to do anything because it will post
- // a continuation as needed. Bailing out here is by far the most common case.
- if (main_sequence_only().do_work_running_count >
- main_sequence_only().nesting_depth) {
- return;
- }
-
- // If DoWork is about to run then we also don't need to do anything.
- {
- AutoLock lock(any_sequence_lock_);
- if (any_sequence().immediate_do_work_posted)
- return;
- }
-
- base::TimeDelta delay = std::max(TimeDelta(), run_time - lazy_now->Now());
- TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
- "ThreadControllerImpl::SetNextDelayedDoWork::PostDelayedTask",
- "delay_ms", delay.InMillisecondsF());
-
- main_sequence_only().next_delayed_do_work = run_time;
- // Reset also causes cancellation of the previous DoWork task.
- cancelable_delayed_do_work_closure_.Reset(delayed_do_work_closure_);
- task_runner_->PostDelayedTask(
- FROM_HERE, cancelable_delayed_do_work_closure_.callback(), delay);
-}
-
-bool ThreadControllerImpl::RunsTasksInCurrentSequence() {
- return task_runner_->RunsTasksInCurrentSequence();
-}
-
-const TickClock* ThreadControllerImpl::GetClock() {
- return time_source_;
-}
-
-void ThreadControllerImpl::SetDefaultTaskRunner(
- scoped_refptr<SingleThreadTaskRunner> task_runner) {
- if (!message_loop_)
- return;
- message_loop_->SetTaskRunner(task_runner);
-}
-
-void ThreadControllerImpl::RestoreDefaultTaskRunner() {
- if (!message_loop_)
- return;
- message_loop_->SetTaskRunner(message_loop_task_runner_);
-}
-
-void ThreadControllerImpl::DidQueueTask(const PendingTask& pending_task) {
- task_annotator_.DidQueueTask("TaskQueueManager::PostTask", pending_task);
-}
-
-void ThreadControllerImpl::DoWork(WorkType work_type) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(sequence_);
-
- {
- AutoLock lock(any_sequence_lock_);
- if (work_type == WorkType::kImmediate)
- any_sequence().immediate_do_work_posted = false;
- any_sequence().do_work_running_count++;
- }
-
- main_sequence_only().do_work_running_count++;
-
- WeakPtr<ThreadControllerImpl> weak_ptr = weak_factory_.GetWeakPtr();
- // TODO(scheduler-dev): Consider moving to a time based work batch instead.
- for (int i = 0; i < main_sequence_only().work_batch_size_; i++) {
- Optional<PendingTask> task = sequence_->TakeTask();
- if (!task)
- break;
-
- TRACE_TASK_EXECUTION("ThreadControllerImpl::DoWork", *task);
- task_annotator_.RunTask("ThreadControllerImpl::DoWork", &*task);
-
- if (!weak_ptr)
- return;
-
- sequence_->DidRunTask();
-
- // TODO(alexclarke): Find out why this is needed.
- if (main_sequence_only().nesting_depth > 0)
- break;
- }
-
- main_sequence_only().do_work_running_count--;
-
- {
- AutoLock lock(any_sequence_lock_);
- any_sequence().do_work_running_count--;
- DCHECK_GE(any_sequence().do_work_running_count, 0);
- LazyNow lazy_now(time_source_);
- TimeDelta delay_till_next_task = sequence_->DelayTillNextTask(&lazy_now);
- if (delay_till_next_task <= TimeDelta()) {
- // The next task needs to run immediately, post a continuation if needed.
- if (!any_sequence().immediate_do_work_posted) {
- any_sequence().immediate_do_work_posted = true;
- task_runner_->PostTask(FROM_HERE, immediate_do_work_closure_);
- }
- } else if (delay_till_next_task < TimeDelta::Max()) {
- // The next task needs to run after a delay, post a continuation if
- // needed.
- TimeTicks next_task_at = lazy_now.Now() + delay_till_next_task;
- if (next_task_at != main_sequence_only().next_delayed_do_work) {
- main_sequence_only().next_delayed_do_work = next_task_at;
- cancelable_delayed_do_work_closure_.Reset(delayed_do_work_closure_);
- task_runner_->PostDelayedTask(
- FROM_HERE, cancelable_delayed_do_work_closure_.callback(),
- delay_till_next_task);
- }
- } else {
- // There is no next task scheduled.
- main_sequence_only().next_delayed_do_work = TimeTicks::Max();
- }
- }
-}
-
-void ThreadControllerImpl::AddNestingObserver(
- RunLoop::NestingObserver* observer) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- nesting_observer_ = observer;
- RunLoop::AddNestingObserverOnCurrentThread(this);
-}
-
-void ThreadControllerImpl::RemoveNestingObserver(
- RunLoop::NestingObserver* observer) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK_EQ(observer, nesting_observer_);
- nesting_observer_ = nullptr;
- RunLoop::RemoveNestingObserverOnCurrentThread(this);
-}
-
-void ThreadControllerImpl::OnBeginNestedRunLoop() {
- main_sequence_only().nesting_depth++;
- {
- AutoLock lock(any_sequence_lock_);
- any_sequence().nesting_depth++;
- if (!any_sequence().immediate_do_work_posted) {
- any_sequence().immediate_do_work_posted = true;
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
- "ThreadControllerImpl::OnBeginNestedRunLoop::PostTask");
- task_runner_->PostTask(FROM_HERE, immediate_do_work_closure_);
- }
- }
- if (nesting_observer_)
- nesting_observer_->OnBeginNestedRunLoop();
-}
-
-void ThreadControllerImpl::OnExitNestedRunLoop() {
- main_sequence_only().nesting_depth--;
- {
- AutoLock lock(any_sequence_lock_);
- any_sequence().nesting_depth--;
- DCHECK_GE(any_sequence().nesting_depth, 0);
- }
- if (nesting_observer_)
- nesting_observer_->OnExitNestedRunLoop();
-}
-
-void ThreadControllerImpl::SetWorkBatchSize(int work_batch_size) {
- main_sequence_only().work_batch_size_ = work_batch_size;
-}
-
-} // namespace internal
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/thread_controller_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/base/thread_controller_impl.h
deleted file mode 100644
index e6473caf68b..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/thread_controller_impl.h
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_THREAD_CONTROLLER_IMPL_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_THREAD_CONTROLLER_IMPL_H_
-
-#include "base/cancelable_callback.h"
-#include "base/debug/task_annotator.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/run_loop.h"
-#include "base/sequence_checker.h"
-#include "base/single_thread_task_runner.h"
-#include "base/task/sequence_manager/thread_controller.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-
-namespace base {
-
-class MessageLoop;
-
-namespace sequence_manager {
-namespace internal {
-
-class PLATFORM_EXPORT ThreadControllerImpl : public ThreadController,
- public RunLoop::NestingObserver {
- public:
- ~ThreadControllerImpl() override;
-
- static std::unique_ptr<ThreadControllerImpl> Create(
- MessageLoop* message_loop,
- const TickClock* time_source);
-
- // ThreadController:
- void SetWorkBatchSize(int work_batch_size) override;
- void DidQueueTask(const PendingTask& pending_task) override;
- void ScheduleWork() override;
- void SetNextDelayedDoWork(LazyNow* lazy_now, TimeTicks run_time) override;
- void SetSequencedTaskSource(SequencedTaskSource* sequence) override;
- bool RunsTasksInCurrentSequence() override;
- const TickClock* GetClock() override;
- void SetDefaultTaskRunner(scoped_refptr<SingleThreadTaskRunner>) override;
- void RestoreDefaultTaskRunner() override;
- void AddNestingObserver(RunLoop::NestingObserver* observer) override;
- void RemoveNestingObserver(RunLoop::NestingObserver* observer) override;
-
- // RunLoop::NestingObserver:
- void OnBeginNestedRunLoop() override;
- void OnExitNestedRunLoop() override;
-
- protected:
- ThreadControllerImpl(MessageLoop* message_loop,
- scoped_refptr<SingleThreadTaskRunner> task_runner,
- const TickClock* time_source);
-
- // TODO(altimin): Make these const. Blocked on removing
- // lazy initialisation support.
- MessageLoop* message_loop_;
- scoped_refptr<SingleThreadTaskRunner> task_runner_;
-
- RunLoop::NestingObserver* nesting_observer_ = nullptr;
-
- private:
- enum class WorkType { kImmediate, kDelayed };
-
- void DoWork(WorkType work_type);
-
- struct AnySequence {
- AnySequence();
- ~AnySequence();
-
- int do_work_running_count = 0;
- int nesting_depth = 0;
- bool immediate_do_work_posted = false;
- };
-
- mutable Lock any_sequence_lock_;
- AnySequence any_sequence_;
-
- struct AnySequence& any_sequence() {
- any_sequence_lock_.AssertAcquired();
- return any_sequence_;
- }
- const struct AnySequence& any_sequence() const {
- any_sequence_lock_.AssertAcquired();
- return any_sequence_;
- }
-
- struct MainSequenceOnly {
- MainSequenceOnly();
- ~MainSequenceOnly();
-
- int do_work_running_count = 0;
- int nesting_depth = 0;
- int work_batch_size_ = 1;
-
- TimeTicks next_delayed_do_work = TimeTicks::Max();
- };
-
- SEQUENCE_CHECKER(sequence_checker_);
- MainSequenceOnly main_sequence_only_;
- MainSequenceOnly& main_sequence_only() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return main_sequence_only_;
- }
- const MainSequenceOnly& main_sequence_only() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- return main_sequence_only_;
- }
-
- scoped_refptr<SingleThreadTaskRunner> message_loop_task_runner_;
- const TickClock* time_source_;
- RepeatingClosure immediate_do_work_closure_;
- RepeatingClosure delayed_do_work_closure_;
- CancelableClosure cancelable_delayed_do_work_closure_;
- SequencedTaskSource* sequence_ = nullptr; // NOT OWNED
- debug::TaskAnnotator task_annotator_;
-
- WeakPtrFactory<ThreadControllerImpl> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadControllerImpl);
-};
-
-} // namespace internal
-} // namespace sequence_manager
-} // namespace base
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_THREAD_CONTROLLER_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/time_domain.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/time_domain.cc
deleted file mode 100644
index 4fa86036ffb..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/time_domain.cc
+++ /dev/null
@@ -1,119 +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/platform/scheduler/base/time_domain.h"
-
-#include <set>
-
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/work_queue.h"
-
-namespace base {
-namespace sequence_manager {
-
-TimeDomain::TimeDomain() = default;
-
-TimeDomain::~TimeDomain() {
- DCHECK(main_thread_checker_.CalledOnValidThread());
-}
-
-void TimeDomain::RegisterQueue(internal::TaskQueueImpl* queue) {
- DCHECK(main_thread_checker_.CalledOnValidThread());
- DCHECK_EQ(queue->GetTimeDomain(), this);
-}
-
-void TimeDomain::UnregisterQueue(internal::TaskQueueImpl* queue) {
- DCHECK(main_thread_checker_.CalledOnValidThread());
- DCHECK_EQ(queue->GetTimeDomain(), this);
-
- LazyNow lazy_now = CreateLazyNow();
- ScheduleWakeUpForQueue(queue, nullopt, &lazy_now);
-}
-
-void TimeDomain::ScheduleWakeUpForQueue(
- internal::TaskQueueImpl* queue,
- Optional<internal::TaskQueueImpl::DelayedWakeUp> wake_up,
- LazyNow* lazy_now) {
- DCHECK(main_thread_checker_.CalledOnValidThread());
- DCHECK_EQ(queue->GetTimeDomain(), this);
- DCHECK(queue->IsQueueEnabled() || !wake_up);
-
- Optional<TimeTicks> previous_wake_up;
- if (!delayed_wake_up_queue_.empty())
- previous_wake_up = delayed_wake_up_queue_.Min().wake_up.time;
-
- if (wake_up) {
- // Insert a new wake-up into the heap.
- if (queue->heap_handle().IsValid()) {
- // O(log n)
- delayed_wake_up_queue_.ChangeKey(queue->heap_handle(),
- {wake_up.value(), queue});
- } else {
- // O(log n)
- delayed_wake_up_queue_.insert({wake_up.value(), queue});
- }
- } else {
- // Remove a wake-up from heap if present.
- if (queue->heap_handle().IsValid())
- delayed_wake_up_queue_.erase(queue->heap_handle());
- }
-
- Optional<TimeTicks> new_wake_up;
- if (!delayed_wake_up_queue_.empty())
- new_wake_up = delayed_wake_up_queue_.Min().wake_up.time;
-
- if (previous_wake_up == new_wake_up)
- return;
-
- if (previous_wake_up)
- CancelWakeUpAt(previous_wake_up.value());
- if (new_wake_up)
- RequestWakeUpAt(lazy_now->Now(), new_wake_up.value());
-}
-
-void TimeDomain::WakeUpReadyDelayedQueues(LazyNow* lazy_now) {
- DCHECK(main_thread_checker_.CalledOnValidThread());
- // Wake up any queues with pending delayed work. Note std::multimap stores
- // the elements sorted by key, so the begin() iterator points to the earliest
- // queue to wake-up.
- while (!delayed_wake_up_queue_.empty() &&
- delayed_wake_up_queue_.Min().wake_up.time <= lazy_now->Now()) {
- internal::TaskQueueImpl* queue = delayed_wake_up_queue_.Min().queue;
- queue->WakeUpForDelayedWork(lazy_now);
- }
-}
-
-bool TimeDomain::NextScheduledRunTime(TimeTicks* out_time) const {
- DCHECK(main_thread_checker_.CalledOnValidThread());
- if (delayed_wake_up_queue_.empty())
- return false;
-
- *out_time = delayed_wake_up_queue_.Min().wake_up.time;
- return true;
-}
-
-bool TimeDomain::NextScheduledTaskQueue(
- internal::TaskQueueImpl** out_task_queue) const {
- DCHECK(main_thread_checker_.CalledOnValidThread());
- if (delayed_wake_up_queue_.empty())
- return false;
-
- *out_task_queue = delayed_wake_up_queue_.Min().queue;
- return true;
-}
-
-void TimeDomain::AsValueInto(trace_event::TracedValue* state) const {
- state->BeginDictionary();
- state->SetString("name", GetName());
- state->SetInteger("registered_delay_count", delayed_wake_up_queue_.size());
- if (!delayed_wake_up_queue_.empty()) {
- TimeDelta delay = delayed_wake_up_queue_.Min().wake_up.time - Now();
- state->SetDouble("next_delay_ms", delay.InMillisecondsF());
- }
- AsValueIntoInternal(state);
- state->EndDictionary();
-}
-
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/time_domain.h b/chromium/third_party/blink/renderer/platform/scheduler/base/time_domain.h
deleted file mode 100644
index 4770dc307dc..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/time_domain.h
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TIME_DOMAIN_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TIME_DOMAIN_H_
-
-#include <map>
-
-#include "base/callback.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/task/sequence_manager/lazy_now.h"
-#include "base/time/time.h"
-#include "third_party/blink/renderer/platform/scheduler/base/intrusive_heap.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-
-namespace base {
-namespace sequence_manager {
-namespace internal {
-class TaskQueueImpl;
-} // internal
-class TaskQueueManager;
-
-// The TimeDomain's job is to wake task queues up when their next delayed tasks
-// are due to fire. TaskQueues request a wake up via ScheduleDelayedWork, when
-// the wake up is due the TimeDomain calls TaskQueue::WakeUpForDelayedWork.
-// The TimeDomain communicates with the TaskQueueManager to actually schedule
-// the wake-ups on the underlying MessageLoop. Various levels of de-duping
-// are employed to prevent unnecessary posting of TaskQueueManager::DoWork.
-//
-// Note the TimeDomain only knows about the first wake-up per queue, it's the
-// responsibility of TaskQueueImpl to keep the time domain up to date if this
-// changes.
-class PLATFORM_EXPORT TimeDomain {
- public:
- TimeDomain();
- virtual ~TimeDomain();
-
- // Returns a LazyNow that evaluate this TimeDomain's Now. Can be called from
- // any thread.
- // TODO(alexclarke): Make this main thread only.
- virtual LazyNow CreateLazyNow() const = 0;
-
- // Evaluate this TimeDomain's Now. Can be called from any thread.
- virtual TimeTicks Now() const = 0;
-
- // Computes the delay until the next task the TimeDomain is aware of, if any.
- // Note virtual time domains may return TimeDelta() if they have any
- // delayed tasks they deem eligible to run. Virtual time domains are allowed
- // to advance their internal clock when this method is called.
- virtual Optional<TimeDelta> DelayTillNextTask(LazyNow* lazy_now) = 0;
-
- // Returns the name of this time domain for tracing.
- virtual const char* GetName() const = 0;
-
- // If there is a scheduled delayed task, |out_time| is set to the scheduled
- // runtime for the next one and it returns true. Returns false otherwise.
- bool NextScheduledRunTime(TimeTicks* out_time) const;
-
- protected:
- friend class internal::TaskQueueImpl;
- friend class TaskQueueManagerImpl;
-
- void AsValueInto(trace_event::TracedValue* state) const;
-
- // If there is a scheduled delayed task, |out_task_queue| is set to the queue
- // the next task was posted to and it returns true. Returns false otherwise.
- bool NextScheduledTaskQueue(internal::TaskQueueImpl** out_task_queue) const;
-
- void ScheduleWakeUpForQueue(
- internal::TaskQueueImpl* queue,
- Optional<internal::TaskQueueImpl::DelayedWakeUp> wake_up,
- LazyNow* lazy_now);
-
- // Registers the |queue|.
- void RegisterQueue(internal::TaskQueueImpl* queue);
-
- // Removes |queue| from all internal data structures.
- void UnregisterQueue(internal::TaskQueueImpl* queue);
-
- // Called by the TaskQueueManager when the TimeDomain is registered.
- virtual void OnRegisterWithTaskQueueManager(
- TaskQueueManagerImpl* task_queue_manager) = 0;
-
- // The implementation will schedule task processing to run at time |run_time|
- // within the TimeDomain's time line. Only called from the main thread.
- // NOTE this is only called by ScheduleDelayedWork if the scheduled runtime
- // is sooner than any previously sheduled work or if there is no other
- // scheduled work.
- virtual void RequestWakeUpAt(TimeTicks now, TimeTicks run_time) = 0;
-
- // The implementation will cancel a wake up previously requested by
- // RequestWakeUpAt. It's expected this will be a NOP for most virtual time
- // domains.
- virtual void CancelWakeUpAt(TimeTicks run_time) = 0;
-
- // For implementation specific tracing.
- virtual void AsValueIntoInternal(trace_event::TracedValue* state) const = 0;
-
- // Call TaskQueueImpl::UpdateDelayedWorkQueue for each queue where the delay
- // has elapsed.
- void WakeUpReadyDelayedQueues(LazyNow* lazy_now);
-
- size_t NumberOfScheduledWakeUps() const {
- return delayed_wake_up_queue_.size();
- }
-
- private:
- struct ScheduledDelayedWakeUp {
- internal::TaskQueueImpl::DelayedWakeUp wake_up;
- internal::TaskQueueImpl* queue;
-
- bool operator<=(const ScheduledDelayedWakeUp& other) const {
- return wake_up <= other.wake_up;
- }
-
- void SetHeapHandle(HeapHandle handle) {
- DCHECK(handle.IsValid());
- queue->set_heap_handle(handle);
- }
-
- void ClearHeapHandle() {
- DCHECK(queue->heap_handle().IsValid());
- queue->set_heap_handle(HeapHandle());
- }
- };
-
- IntrusiveHeap<ScheduledDelayedWakeUp> delayed_wake_up_queue_;
-
- ThreadChecker main_thread_checker_;
-
- DISALLOW_COPY_AND_ASSIGN(TimeDomain);
-};
-
-} // namespace sequence_manager
-} // namespace base
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TIME_DOMAIN_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/time_domain_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/time_domain_unittest.cc
deleted file mode 100644
index b86a866d297..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/time_domain_unittest.cc
+++ /dev/null
@@ -1,343 +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/platform/scheduler/base/time_domain.h"
-
-#include <memory>
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h"
-#include "third_party/blink/renderer/platform/scheduler/base/work_queue.h"
-
-using testing::_;
-using testing::AnyNumber;
-using testing::Mock;
-
-namespace base {
-namespace sequence_manager {
-
-class TaskQueueImplForTest : public internal::TaskQueueImpl {
- public:
- TaskQueueImplForTest(TaskQueueManagerImpl* task_queue_manager,
- TimeDomain* time_domain,
- const TaskQueue::Spec& spec)
- : TaskQueueImpl(task_queue_manager, time_domain, spec) {}
- ~TaskQueueImplForTest() {}
-
- using TaskQueueImpl::SetDelayedWakeUpForTesting;
-};
-
-class MockTimeDomain : public TimeDomain {
- public:
- MockTimeDomain() : now_(TimeTicks() + TimeDelta::FromSeconds(1)) {}
-
- ~MockTimeDomain() override = default;
-
- using TimeDomain::NextScheduledRunTime;
- using TimeDomain::NextScheduledTaskQueue;
- using TimeDomain::UnregisterQueue;
- using TimeDomain::WakeUpReadyDelayedQueues;
-
- // TimeSource implementation:
- LazyNow CreateLazyNow() const override { return LazyNow(now_); }
- TimeTicks Now() const override { return now_; }
-
- void AsValueIntoInternal(trace_event::TracedValue* state) const override {}
-
- Optional<TimeDelta> DelayTillNextTask(LazyNow* lazy_now) override {
- return Optional<TimeDelta>();
- }
- const char* GetName() const override { return "Test"; }
- void OnRegisterWithTaskQueueManager(
- TaskQueueManagerImpl* task_queue_manager) override {}
-
- MOCK_METHOD2(RequestWakeUpAt, void(TimeTicks now, TimeTicks run_time));
-
- MOCK_METHOD1(CancelWakeUpAt, void(TimeTicks run_time));
-
- void SetNow(TimeTicks now) { now_ = now; }
-
- private:
- TimeTicks now_;
-
- DISALLOW_COPY_AND_ASSIGN(MockTimeDomain);
-};
-
-class TimeDomainTest : public testing::Test {
- public:
- void SetUp() final {
- time_domain_ = WrapUnique(CreateMockTimeDomain());
- task_queue_ = std::make_unique<TaskQueueImplForTest>(
- nullptr, time_domain_.get(), TaskQueue::Spec("test"));
- }
-
- void TearDown() final {
- if (task_queue_)
- task_queue_->UnregisterTaskQueue();
- }
-
- virtual MockTimeDomain* CreateMockTimeDomain() {
- return new MockTimeDomain();
- }
-
- std::unique_ptr<MockTimeDomain> time_domain_;
- std::unique_ptr<TaskQueueImplForTest> task_queue_;
-};
-
-TEST_F(TimeDomainTest, ScheduleWakeUpForQueue) {
- TimeDelta delay = TimeDelta::FromMilliseconds(10);
- TimeTicks delayed_runtime = time_domain_->Now() + delay;
- EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, delayed_runtime));
- TimeTicks now = time_domain_->Now();
- LazyNow lazy_now(now);
- task_queue_->SetDelayedWakeUpForTesting(
- internal::TaskQueueImpl::DelayedWakeUp{now + delay, 0});
-
- TimeTicks next_scheduled_runtime;
- EXPECT_TRUE(time_domain_->NextScheduledRunTime(&next_scheduled_runtime));
- EXPECT_EQ(delayed_runtime, next_scheduled_runtime);
-
- internal::TaskQueueImpl* next_task_queue;
- EXPECT_TRUE(time_domain_->NextScheduledTaskQueue(&next_task_queue));
- EXPECT_EQ(task_queue_.get(), next_task_queue);
- Mock::VerifyAndClearExpectations(time_domain_.get());
-
- EXPECT_CALL(*time_domain_.get(), CancelWakeUpAt(_)).Times(AnyNumber());
-}
-
-TEST_F(TimeDomainTest, ScheduleWakeUpForQueueSupersedesPreviousWakeUp) {
- TimeDelta delay1 = TimeDelta::FromMilliseconds(10);
- TimeDelta delay2 = TimeDelta::FromMilliseconds(100);
- TimeTicks delayed_runtime1 = time_domain_->Now() + delay1;
- TimeTicks delayed_runtime2 = time_domain_->Now() + delay2;
- EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, delayed_runtime1));
- TimeTicks now = time_domain_->Now();
- LazyNow lazy_now(now);
- task_queue_->SetDelayedWakeUpForTesting(
- internal::TaskQueueImpl::DelayedWakeUp{delayed_runtime1, 0});
-
- TimeTicks next_scheduled_runtime;
- EXPECT_TRUE(time_domain_->NextScheduledRunTime(&next_scheduled_runtime));
- EXPECT_EQ(delayed_runtime1, next_scheduled_runtime);
-
- Mock::VerifyAndClearExpectations(time_domain_.get());
-
- // Now schedule a later wake_up, which should replace the previously
- // requested one.
- EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, delayed_runtime2));
- task_queue_->SetDelayedWakeUpForTesting(
- internal::TaskQueueImpl::DelayedWakeUp{delayed_runtime2, 0});
-
- EXPECT_TRUE(time_domain_->NextScheduledRunTime(&next_scheduled_runtime));
- EXPECT_EQ(delayed_runtime2, next_scheduled_runtime);
- Mock::VerifyAndClearExpectations(time_domain_.get());
-
- EXPECT_CALL(*time_domain_.get(), CancelWakeUpAt(_)).Times(AnyNumber());
-}
-
-TEST_F(TimeDomainTest, RequestWakeUpAt_OnlyCalledForEarlierTasks) {
- std::unique_ptr<TaskQueueImplForTest> task_queue2 =
- std::make_unique<TaskQueueImplForTest>(nullptr, time_domain_.get(),
- TaskQueue::Spec("test"));
-
- std::unique_ptr<TaskQueueImplForTest> task_queue3 =
- std::make_unique<TaskQueueImplForTest>(nullptr, time_domain_.get(),
- TaskQueue::Spec("test"));
-
- std::unique_ptr<TaskQueueImplForTest> task_queue4 =
- std::make_unique<TaskQueueImplForTest>(nullptr, time_domain_.get(),
- TaskQueue::Spec("test"));
-
- TimeDelta delay1 = TimeDelta::FromMilliseconds(10);
- TimeDelta delay2 = TimeDelta::FromMilliseconds(20);
- TimeDelta delay3 = TimeDelta::FromMilliseconds(30);
- TimeDelta delay4 = TimeDelta::FromMilliseconds(1);
-
- // RequestWakeUpAt should always be called if there are no other wake-ups.
- TimeTicks now = time_domain_->Now();
- LazyNow lazy_now(now);
- EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, now + delay1));
- task_queue_->SetDelayedWakeUpForTesting(
- internal::TaskQueueImpl::DelayedWakeUp{now + delay1, 0});
-
- Mock::VerifyAndClearExpectations(time_domain_.get());
-
- // RequestWakeUpAt should not be called when scheduling later tasks.
- EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, _)).Times(0);
- task_queue2->SetDelayedWakeUpForTesting(
- internal::TaskQueueImpl::DelayedWakeUp{now + delay2, 0});
- task_queue3->SetDelayedWakeUpForTesting(
- internal::TaskQueueImpl::DelayedWakeUp{now + delay3, 0});
-
- // RequestWakeUpAt should be called when scheduling earlier tasks.
- Mock::VerifyAndClearExpectations(time_domain_.get());
- EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, now + delay4));
- task_queue4->SetDelayedWakeUpForTesting(
- internal::TaskQueueImpl::DelayedWakeUp{now + delay4, 0});
-
- Mock::VerifyAndClearExpectations(time_domain_.get());
-
- EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, _));
- EXPECT_CALL(*time_domain_.get(), CancelWakeUpAt(_)).Times(2);
- task_queue2->UnregisterTaskQueue();
- task_queue3->UnregisterTaskQueue();
- task_queue4->UnregisterTaskQueue();
-}
-
-TEST_F(TimeDomainTest, UnregisterQueue) {
- std::unique_ptr<TaskQueueImplForTest> task_queue2_ =
- std::make_unique<TaskQueueImplForTest>(nullptr, time_domain_.get(),
- TaskQueue::Spec("test"));
-
- TimeTicks now = time_domain_->Now();
- LazyNow lazy_now(now);
- TimeTicks wake_up1 = now + TimeDelta::FromMilliseconds(10);
- EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, wake_up1)).Times(1);
- task_queue_->SetDelayedWakeUpForTesting(
- internal::TaskQueueImpl::DelayedWakeUp{wake_up1, 0});
- TimeTicks wake_up2 = now + TimeDelta::FromMilliseconds(100);
- task_queue2_->SetDelayedWakeUpForTesting(
- internal::TaskQueueImpl::DelayedWakeUp{wake_up2, 0});
-
- internal::TaskQueueImpl* next_task_queue;
- EXPECT_TRUE(time_domain_->NextScheduledTaskQueue(&next_task_queue));
- EXPECT_EQ(task_queue_.get(), next_task_queue);
-
- testing::Mock::VerifyAndClearExpectations(time_domain_.get());
-
- EXPECT_CALL(*time_domain_.get(), CancelWakeUpAt(wake_up1)).Times(1);
- EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, wake_up2)).Times(1);
-
- time_domain_->UnregisterQueue(task_queue_.get());
- task_queue_ = std::unique_ptr<TaskQueueImplForTest>();
- EXPECT_TRUE(time_domain_->NextScheduledTaskQueue(&next_task_queue));
- EXPECT_EQ(task_queue2_.get(), next_task_queue);
-
- testing::Mock::VerifyAndClearExpectations(time_domain_.get());
-
- EXPECT_CALL(*time_domain_.get(), CancelWakeUpAt(wake_up2)).Times(1);
-
- time_domain_->UnregisterQueue(task_queue2_.get());
- EXPECT_FALSE(time_domain_->NextScheduledTaskQueue(&next_task_queue));
-}
-
-TEST_F(TimeDomainTest, WakeUpReadyDelayedQueues) {
- TimeDelta delay = TimeDelta::FromMilliseconds(50);
- TimeTicks now = time_domain_->Now();
- LazyNow lazy_now_1(now);
- TimeTicks delayed_runtime = now + delay;
- EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, delayed_runtime));
- task_queue_->SetDelayedWakeUpForTesting(
- internal::TaskQueueImpl::DelayedWakeUp{delayed_runtime, 0});
-
- TimeTicks next_run_time;
- ASSERT_TRUE(time_domain_->NextScheduledRunTime(&next_run_time));
- EXPECT_EQ(delayed_runtime, next_run_time);
-
- time_domain_->WakeUpReadyDelayedQueues(&lazy_now_1);
- ASSERT_TRUE(time_domain_->NextScheduledRunTime(&next_run_time));
- EXPECT_EQ(delayed_runtime, next_run_time);
-
- time_domain_->SetNow(delayed_runtime);
- LazyNow lazy_now_2(time_domain_->CreateLazyNow());
- time_domain_->WakeUpReadyDelayedQueues(&lazy_now_2);
- ASSERT_FALSE(time_domain_->NextScheduledRunTime(&next_run_time));
-}
-
-TEST_F(TimeDomainTest, WakeUpReadyDelayedQueuesWithIdenticalRuntimes) {
- int sequence_num = 0;
- TimeDelta delay = TimeDelta::FromMilliseconds(50);
- TimeTicks now = time_domain_->Now();
- LazyNow lazy_now(now);
- TimeTicks delayed_runtime = now + delay;
- EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, delayed_runtime));
- EXPECT_CALL(*time_domain_.get(), CancelWakeUpAt(delayed_runtime));
-
- std::unique_ptr<TaskQueueImplForTest> task_queue2 =
- std::make_unique<TaskQueueImplForTest>(nullptr, time_domain_.get(),
- TaskQueue::Spec("test"));
-
- task_queue2->SetDelayedWakeUpForTesting(
- internal::TaskQueueImpl::DelayedWakeUp{delayed_runtime, ++sequence_num});
- task_queue_->SetDelayedWakeUpForTesting(
- internal::TaskQueueImpl::DelayedWakeUp{delayed_runtime, ++sequence_num});
-
- time_domain_->WakeUpReadyDelayedQueues(&lazy_now);
-
- // The second task queue should wake up first since it has a lower sequence
- // number.
- internal::TaskQueueImpl* next_task_queue;
- EXPECT_TRUE(time_domain_->NextScheduledTaskQueue(&next_task_queue));
- EXPECT_EQ(task_queue2.get(), next_task_queue);
-
- task_queue2->UnregisterTaskQueue();
-}
-
-TEST_F(TimeDomainTest, CancelDelayedWork) {
- TimeTicks now = time_domain_->Now();
- LazyNow lazy_now(now);
- TimeTicks run_time = now + TimeDelta::FromMilliseconds(20);
-
- EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, run_time));
- task_queue_->SetDelayedWakeUpForTesting(
- internal::TaskQueueImpl::DelayedWakeUp{run_time, 0});
-
- internal::TaskQueueImpl* next_task_queue;
- EXPECT_TRUE(time_domain_->NextScheduledTaskQueue(&next_task_queue));
- EXPECT_EQ(task_queue_.get(), next_task_queue);
-
- EXPECT_CALL(*time_domain_.get(), CancelWakeUpAt(run_time));
- task_queue_->SetDelayedWakeUpForTesting(nullopt);
- EXPECT_FALSE(time_domain_->NextScheduledTaskQueue(&next_task_queue));
-}
-
-TEST_F(TimeDomainTest, CancelDelayedWork_TwoQueues) {
- std::unique_ptr<TaskQueueImplForTest> task_queue2 =
- std::make_unique<TaskQueueImplForTest>(nullptr, time_domain_.get(),
- TaskQueue::Spec("test"));
-
- TimeTicks now = time_domain_->Now();
- LazyNow lazy_now(now);
- TimeTicks run_time1 = now + TimeDelta::FromMilliseconds(20);
- TimeTicks run_time2 = now + TimeDelta::FromMilliseconds(40);
- EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, run_time1));
- task_queue_->SetDelayedWakeUpForTesting(
- internal::TaskQueueImpl::DelayedWakeUp{run_time1, 0});
- Mock::VerifyAndClearExpectations(time_domain_.get());
-
- EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, _)).Times(0);
- task_queue2->SetDelayedWakeUpForTesting(
- internal::TaskQueueImpl::DelayedWakeUp{run_time2, 0});
- Mock::VerifyAndClearExpectations(time_domain_.get());
-
- internal::TaskQueueImpl* next_task_queue;
- EXPECT_TRUE(time_domain_->NextScheduledTaskQueue(&next_task_queue));
- EXPECT_EQ(task_queue_.get(), next_task_queue);
-
- TimeTicks next_run_time;
- ASSERT_TRUE(time_domain_->NextScheduledRunTime(&next_run_time));
- EXPECT_EQ(run_time1, next_run_time);
-
- EXPECT_CALL(*time_domain_.get(), CancelWakeUpAt(run_time1));
- EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, run_time2));
- task_queue_->SetDelayedWakeUpForTesting(nullopt);
- EXPECT_TRUE(time_domain_->NextScheduledTaskQueue(&next_task_queue));
- EXPECT_EQ(task_queue2.get(), next_task_queue);
-
- ASSERT_TRUE(time_domain_->NextScheduledRunTime(&next_run_time));
- EXPECT_EQ(run_time2, next_run_time);
-
- Mock::VerifyAndClearExpectations(time_domain_.get());
- EXPECT_CALL(*time_domain_.get(), RequestWakeUpAt(_, _)).Times(AnyNumber());
- EXPECT_CALL(*time_domain_.get(), CancelWakeUpAt(_)).Times(AnyNumber());
-
- // Tidy up.
- task_queue2->UnregisterTaskQueue();
-}
-
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/virtual_time_domain.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/virtual_time_domain.cc
deleted file mode 100644
index ba3252ab83a..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/virtual_time_domain.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/base/virtual_time_domain.h"
-
-#include "base/bind.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl.h"
-
-namespace base {
-namespace sequence_manager {
-
-VirtualTimeDomain::VirtualTimeDomain(TimeTicks initial_time_ticks)
- : now_ticks_(initial_time_ticks), task_queue_manager_(nullptr) {}
-
-VirtualTimeDomain::~VirtualTimeDomain() = default;
-
-void VirtualTimeDomain::OnRegisterWithTaskQueueManager(
- TaskQueueManagerImpl* task_queue_manager) {
- task_queue_manager_ = task_queue_manager;
- DCHECK(task_queue_manager_);
-}
-
-LazyNow VirtualTimeDomain::CreateLazyNow() const {
- AutoLock lock(lock_);
- return LazyNow(now_ticks_);
-}
-
-TimeTicks VirtualTimeDomain::Now() const {
- AutoLock lock(lock_);
- return now_ticks_;
-}
-
-void VirtualTimeDomain::RequestWakeUpAt(TimeTicks now, TimeTicks run_time) {
- // We don't need to do anything here because the caller of AdvanceTo is
- // responsible for calling TaskQueueManagerImpl::MaybeScheduleImmediateWork if
- // needed.
-}
-
-void VirtualTimeDomain::CancelWakeUpAt(TimeTicks run_time) {
- // We ignore this because RequestWakeUpAt is a NOP.
-}
-
-Optional<TimeDelta> VirtualTimeDomain::DelayTillNextTask(LazyNow* lazy_now) {
- return nullopt;
-}
-
-void VirtualTimeDomain::AsValueIntoInternal(
- trace_event::TracedValue* state) const {}
-
-void VirtualTimeDomain::AdvanceNowTo(TimeTicks now) {
- AutoLock lock(lock_);
- DCHECK_GE(now, now_ticks_);
- now_ticks_ = now;
-}
-
-void VirtualTimeDomain::RequestDoWork() {
- task_queue_manager_->MaybeScheduleImmediateWork(FROM_HERE);
-}
-
-const char* VirtualTimeDomain::GetName() const {
- return "VirtualTimeDomain";
-}
-
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/virtual_time_domain.h b/chromium/third_party/blink/renderer/platform/scheduler/base/virtual_time_domain.h
deleted file mode 100644
index 6a4ca9de6a3..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/virtual_time_domain.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_PLATFORM_SCHEDULER_BASE_VIRTUAL_TIME_DOMAIN_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_VIRTUAL_TIME_DOMAIN_H_
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/threading/thread_checker.h"
-#include "third_party/blink/renderer/platform/scheduler/base/time_domain.h"
-
-namespace base {
-namespace sequence_manager {
-
-class PLATFORM_EXPORT VirtualTimeDomain : public TimeDomain {
- public:
- explicit VirtualTimeDomain(TimeTicks initial_time_ticks);
- ~VirtualTimeDomain() override;
-
- // TimeDomain implementation:
- LazyNow CreateLazyNow() const override;
- TimeTicks Now() const override;
- Optional<TimeDelta> DelayTillNextTask(LazyNow* lazy_now) override;
- const char* GetName() const override;
-
- // Advances this time domain to |now|. NOTE |now| is supposed to be
- // monotonically increasing. NOTE it's the responsibility of the caller to
- // call TaskQueueManager::MaybeScheduleImmediateWork if needed.
- void AdvanceNowTo(TimeTicks now);
-
- protected:
- void OnRegisterWithTaskQueueManager(
- TaskQueueManagerImpl* task_queue_manager) override;
- void RequestWakeUpAt(TimeTicks now, TimeTicks run_time) override;
- void CancelWakeUpAt(TimeTicks run_time) override;
- void AsValueIntoInternal(trace_event::TracedValue* state) const override;
-
- void RequestDoWork();
-
- private:
- mutable Lock lock_; // Protects |now_ticks_|
- TimeTicks now_ticks_;
-
- TaskQueueManagerImpl* task_queue_manager_; // NOT OWNED
- Closure do_work_closure_;
-
- DISALLOW_COPY_AND_ASSIGN(VirtualTimeDomain);
-};
-
-} // namespace sequence_manager
-} // namespace base
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_VIRTUAL_TIME_DOMAIN_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/work_queue.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/work_queue.cc
deleted file mode 100644
index f2319bc5b1d..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/work_queue.cc
+++ /dev/null
@@ -1,235 +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/platform/scheduler/base/work_queue.h"
-
-#include "third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h"
-
-namespace base {
-namespace sequence_manager {
-namespace internal {
-
-WorkQueue::WorkQueue(TaskQueueImpl* task_queue,
- const char* name,
- QueueType queue_type)
- : task_queue_(task_queue), name_(name), queue_type_(queue_type) {}
-
-void WorkQueue::AsValueInto(TimeTicks now,
- trace_event::TracedValue* state) const {
- for (const TaskQueueImpl::Task& task : tasks_) {
- TaskQueueImpl::TaskAsValueInto(task, now, state);
- }
-}
-
-WorkQueue::~WorkQueue() {
- DCHECK(!work_queue_sets_) << task_queue_->GetName() << " : "
- << work_queue_sets_->GetName() << " : " << name_;
-}
-
-const TaskQueueImpl::Task* WorkQueue::GetFrontTask() const {
- if (tasks_.empty())
- return nullptr;
- return &tasks_.front();
-}
-
-const TaskQueueImpl::Task* WorkQueue::GetBackTask() const {
- if (tasks_.empty())
- return nullptr;
- return &tasks_.back();
-}
-
-bool WorkQueue::BlockedByFence() const {
- if (!fence_)
- return false;
-
- // If the queue is empty then any future tasks will have a higher enqueue
- // order and will be blocked. The queue is also blocked if the head is past
- // the fence.
- return tasks_.empty() || tasks_.front().enqueue_order() >= fence_;
-}
-
-bool WorkQueue::GetFrontTaskEnqueueOrder(EnqueueOrder* enqueue_order) const {
- if (tasks_.empty() || BlockedByFence())
- return false;
- // Quick sanity check.
- DCHECK_LE(tasks_.front().enqueue_order(), tasks_.back().enqueue_order())
- << task_queue_->GetName() << " : " << work_queue_sets_->GetName() << " : "
- << name_;
- *enqueue_order = tasks_.front().enqueue_order();
- return true;
-}
-
-void WorkQueue::Push(TaskQueueImpl::Task task) {
- bool was_empty = tasks_.empty();
-#ifndef NDEBUG
- DCHECK(task.enqueue_order_set());
-#endif
-
- // Make sure the |enqueue_order()| is monotonically increasing.
- DCHECK(was_empty || tasks_.rbegin()->enqueue_order() < task.enqueue_order());
-
- // Amoritized O(1).
- tasks_.push_back(std::move(task));
-
- if (!was_empty)
- return;
-
- // If we hit the fence, pretend to WorkQueueSets that we're empty.
- if (work_queue_sets_ && !BlockedByFence())
- work_queue_sets_->OnTaskPushedToEmptyQueue(this);
-}
-
-void WorkQueue::PushNonNestableTaskToFront(TaskQueueImpl::Task task) {
- DCHECK(task.nestable == Nestable::kNonNestable);
-
- bool was_empty = tasks_.empty();
- bool was_blocked = BlockedByFence();
-#ifndef NDEBUG
- DCHECK(task.enqueue_order_set());
-#endif
-
- if (!was_empty) {
- // Make sure the |enqueue_order()| is monotonically increasing.
- DCHECK_LE(task.enqueue_order(), tasks_.front().enqueue_order())
- << task_queue_->GetName() << " : " << work_queue_sets_->GetName()
- << " : " << name_;
- }
-
- // Amoritized O(1).
- tasks_.push_front(std::move(task));
-
- if (!work_queue_sets_)
- return;
-
- // Pretend to WorkQueueSets that nothing has changed if we're blocked.
- if (BlockedByFence())
- return;
-
- // Pushing task to front may unblock the fence.
- if (was_empty || was_blocked) {
- work_queue_sets_->OnTaskPushedToEmptyQueue(this);
- } else {
- work_queue_sets_->OnFrontTaskChanged(this);
- }
-}
-
-void WorkQueue::ReloadEmptyImmediateQueue() {
- DCHECK(tasks_.empty());
-
- tasks_ = task_queue_->TakeImmediateIncomingQueue();
- if (tasks_.empty())
- return;
-
- // If we hit the fence, pretend to WorkQueueSets that we're empty.
- if (work_queue_sets_ && !BlockedByFence())
- work_queue_sets_->OnTaskPushedToEmptyQueue(this);
-}
-
-TaskQueueImpl::Task WorkQueue::TakeTaskFromWorkQueue() {
- DCHECK(work_queue_sets_);
- DCHECK(!tasks_.empty());
-
- TaskQueueImpl::Task pending_task = std::move(tasks_.front());
- tasks_.pop_front();
- // NB immediate tasks have a different pipeline to delayed ones.
- if (queue_type_ == QueueType::kImmediate && tasks_.empty()) {
- // Short-circuit the queue reload so that OnPopQueue does the right thing.
- tasks_ = task_queue_->TakeImmediateIncomingQueue();
- }
- // OnPopQueue calls GetFrontTaskEnqueueOrder which checks BlockedByFence() so
- // we don't need to here.
- work_queue_sets_->OnPopQueue(this);
- task_queue_->TraceQueueSize();
- return pending_task;
-}
-
-bool WorkQueue::RemoveAllCanceledTasksFromFront() {
- DCHECK(work_queue_sets_);
- bool task_removed = false;
- while (!tasks_.empty() &&
- (!tasks_.front().task || tasks_.front().task.IsCancelled())) {
- tasks_.pop_front();
- task_removed = true;
- }
- if (task_removed) {
- // NB immediate tasks have a different pipeline to delayed ones.
- if (queue_type_ == QueueType::kImmediate && tasks_.empty()) {
- // Short-circuit the queue reload so that OnPopQueue does the right thing.
- tasks_ = task_queue_->TakeImmediateIncomingQueue();
- }
- work_queue_sets_->OnPopQueue(this);
- task_queue_->TraceQueueSize();
- }
- return task_removed;
-}
-
-void WorkQueue::AssignToWorkQueueSets(WorkQueueSets* work_queue_sets) {
- work_queue_sets_ = work_queue_sets;
-}
-
-void WorkQueue::AssignSetIndex(size_t work_queue_set_index) {
- work_queue_set_index_ = work_queue_set_index;
-}
-
-bool WorkQueue::InsertFenceImpl(EnqueueOrder fence) {
- DCHECK_NE(fence, 0u);
- DCHECK(fence >= fence_ || fence == 1u);
- bool was_blocked_by_fence = BlockedByFence();
- fence_ = fence;
- return was_blocked_by_fence;
-}
-
-void WorkQueue::InsertFenceSilently(EnqueueOrder fence) {
- // Ensure that there is no fence present or a new one blocks queue completely.
- DCHECK(fence_ == 0u || fence == 1u);
- InsertFenceImpl(fence);
-}
-
-bool WorkQueue::InsertFence(EnqueueOrder fence) {
- bool was_blocked_by_fence = InsertFenceImpl(fence);
-
- // Moving the fence forward may unblock some tasks.
- if (work_queue_sets_ && !tasks_.empty() && was_blocked_by_fence &&
- !BlockedByFence()) {
- work_queue_sets_->OnTaskPushedToEmptyQueue(this);
- return true;
- }
- // Fence insertion may have blocked all tasks in this work queue.
- if (BlockedByFence())
- work_queue_sets_->OnQueueBlocked(this);
- return false;
-}
-
-bool WorkQueue::RemoveFence() {
- bool was_blocked_by_fence = BlockedByFence();
- fence_ = 0;
- if (work_queue_sets_ && !tasks_.empty() && was_blocked_by_fence) {
- work_queue_sets_->OnTaskPushedToEmptyQueue(this);
- return true;
- }
- return false;
-}
-
-bool WorkQueue::ShouldRunBefore(const WorkQueue* other_queue) const {
- DCHECK(!tasks_.empty());
- DCHECK(!other_queue->tasks_.empty());
- EnqueueOrder enqueue_order = 0;
- EnqueueOrder other_enqueue_order = 0;
- bool have_task = GetFrontTaskEnqueueOrder(&enqueue_order);
- bool have_other_task =
- other_queue->GetFrontTaskEnqueueOrder(&other_enqueue_order);
- DCHECK(have_task);
- DCHECK(have_other_task);
- return enqueue_order < other_enqueue_order;
-}
-
-void WorkQueue::PopTaskForTesting() {
- if (tasks_.empty())
- return;
- tasks_.pop_front();
-}
-
-} // namespace internal
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/work_queue.h b/chromium/third_party/blink/renderer/platform/scheduler/base/work_queue.h
deleted file mode 100644
index b94b660474c..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/work_queue.h
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_WORK_QUEUE_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_WORK_QUEUE_H_
-
-#include <stddef.h>
-
-#include <set>
-
-#include "base/task/sequence_manager/sequenced_task_source.h"
-#include "base/trace_event/trace_event.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "third_party/blink/renderer/platform/scheduler/base/enqueue_order.h"
-#include "third_party/blink/renderer/platform/scheduler/base/intrusive_heap.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-
-namespace base {
-namespace sequence_manager {
-namespace internal {
-
-class WorkQueueSets;
-
-// This class keeps track of immediate and delayed tasks which are due to run
-// now. It interfaces deeply with WorkQueueSets which keeps track of which queue
-// (with a given priority) contains the oldest task.
-//
-// If a fence is inserted, WorkQueue behaves normally up until
-// TakeTaskFromWorkQueue reaches or exceeds the fence. At that point it the
-// API subset used by WorkQueueSets pretends the WorkQueue is empty until the
-// fence is removed. This functionality is a primitive intended for use by
-// throttling mechanisms.
-class PLATFORM_EXPORT WorkQueue {
- public:
- using QueueType = internal::TaskQueueImpl::WorkQueueType;
-
- // Note |task_queue| can be null if queue_type is kNonNestable.
- WorkQueue(TaskQueueImpl* task_queue, const char* name, QueueType queue_type);
- ~WorkQueue();
-
- // Associates this work queue with the given work queue sets. This must be
- // called before any tasks can be inserted into this work queue.
- void AssignToWorkQueueSets(WorkQueueSets* work_queue_sets);
-
- // Assigns the current set index.
- void AssignSetIndex(size_t work_queue_set_index);
-
- void AsValueInto(TimeTicks now, trace_event::TracedValue* state) const;
-
- // Returns true if the |tasks_| is empty. This method ignores any fences.
- bool Empty() const { return tasks_.empty(); }
-
- // If the |tasks_| isn't empty and a fence hasn't been reached,
- // |enqueue_order| gets set to the enqueue order of the front task and the
- // function returns true. Otherwise the function returns false.
- bool GetFrontTaskEnqueueOrder(EnqueueOrder* enqueue_order) const;
-
- // Returns the first task in this queue or null if the queue is empty. This
- // method ignores any fences.
- const TaskQueueImpl::Task* GetFrontTask() const;
-
- // Returns the last task in this queue or null if the queue is empty. This
- // method ignores any fences.
- const TaskQueueImpl::Task* GetBackTask() const;
-
- // Pushes the task onto the |tasks_| and if a fence hasn't been reached
- // it informs the WorkQueueSets if the head changed.
- void Push(TaskQueueImpl::Task task);
-
- // Pushes the task onto the front of the |tasks_| and if it's before any
- // fence it informs the WorkQueueSets the head changed. Use with caution this
- // API can easily lead to task starvation if misused.
- void PushNonNestableTaskToFront(TaskQueueImpl::Task task);
-
- // Reloads the empty |tasks_| with
- // |task_queue_->TakeImmediateIncomingQueue| and if a fence hasn't been
- // reached it informs the WorkQueueSets if the head changed.
- void ReloadEmptyImmediateQueue();
-
- size_t Size() const { return tasks_.size(); }
-
- // Pulls a task off the |tasks_| and informs the WorkQueueSets. If the
- // task removed had an enqueue order >= the current fence then WorkQueue
- // pretends to be empty as far as the WorkQueueSets is concerned.
- TaskQueueImpl::Task TakeTaskFromWorkQueue();
-
- // Removes all canceled tasks from the head of the list. Returns true if any
- // tasks were removed.
- bool RemoveAllCanceledTasksFromFront();
-
- const char* name() const { return name_; }
-
- TaskQueueImpl* task_queue() const { return task_queue_; }
-
- WorkQueueSets* work_queue_sets() const { return work_queue_sets_; }
-
- size_t work_queue_set_index() const { return work_queue_set_index_; }
-
- HeapHandle heap_handle() const { return heap_handle_; }
-
- void set_heap_handle(HeapHandle handle) { heap_handle_ = handle; }
-
- QueueType queue_type() const { return queue_type_; }
-
- // Returns true if the front task in this queue has an older enqueue order
- // than the front task of |other_queue|. Both queue are assumed to be
- // non-empty. This method ignores any fences.
- bool ShouldRunBefore(const WorkQueue* other_queue) const;
-
- // Submit a fence. When TakeTaskFromWorkQueue encounters a task whose
- // enqueue_order is >= |fence| then the WorkQueue will start pretending to be.
- // empty.
- // Inserting a fence may supersede a previous one and unblock some tasks.
- // Returns true if any tasks where unblocked, returns false otherwise.
- bool InsertFence(EnqueueOrder fence);
-
- // Submit a fence without triggering a WorkQueueSets notification.
- // Caller must ensure that WorkQueueSets are properly updated.
- // This method should not be called when a fence is already present.
- void InsertFenceSilently(EnqueueOrder fence);
-
- // Removes any fences that where added and if WorkQueue was pretending to be
- // empty, then the real value is reported to WorkQueueSets. Returns true if
- // any tasks where unblocked.
- bool RemoveFence();
-
- // Returns true if any tasks are blocked by the fence. Returns true if the
- // queue is empty and fence has been set (i.e. future tasks would be blocked).
- // Otherwise returns false.
- bool BlockedByFence() const;
-
- // Test support function. This should not be used in production code.
- void PopTaskForTesting();
-
- private:
- bool InsertFenceImpl(EnqueueOrder fence);
-
- TaskQueueImpl::TaskDeque tasks_;
- WorkQueueSets* work_queue_sets_ = nullptr; // NOT OWNED.
- TaskQueueImpl* const task_queue_; // NOT OWNED.
- size_t work_queue_set_index_ = 0;
- HeapHandle heap_handle_;
- const char* const name_;
- EnqueueOrder fence_ = 0;
- const QueueType queue_type_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkQueue);
-};
-
-} // namespace internal
-} // namespace sequence_manager
-} // namespace base
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_WORK_QUEUE_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/work_queue_sets.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/work_queue_sets.cc
deleted file mode 100644
index 0d34d146ba1..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/work_queue_sets.cc
+++ /dev/null
@@ -1,172 +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/platform/scheduler/base/work_queue_sets.h"
-
-#include "base/logging.h"
-
-namespace base {
-namespace sequence_manager {
-namespace internal {
-
-WorkQueueSets::WorkQueueSets(size_t num_sets, const char* name)
- : work_queue_heaps_(num_sets), name_(name) {}
-
-WorkQueueSets::~WorkQueueSets() = default;
-
-void WorkQueueSets::AddQueue(WorkQueue* work_queue, size_t set_index) {
- DCHECK(!work_queue->work_queue_sets());
- DCHECK_LT(set_index, work_queue_heaps_.size());
- EnqueueOrder enqueue_order;
- bool has_enqueue_order = work_queue->GetFrontTaskEnqueueOrder(&enqueue_order);
- work_queue->AssignToWorkQueueSets(this);
- work_queue->AssignSetIndex(set_index);
- if (!has_enqueue_order)
- return;
- work_queue_heaps_[set_index].insert({enqueue_order, work_queue});
-}
-
-void WorkQueueSets::RemoveQueue(WorkQueue* work_queue) {
- DCHECK_EQ(this, work_queue->work_queue_sets());
- work_queue->AssignToWorkQueueSets(nullptr);
- HeapHandle heap_handle = work_queue->heap_handle();
- if (!heap_handle.IsValid())
- return;
- size_t set_index = work_queue->work_queue_set_index();
- DCHECK_LT(set_index, work_queue_heaps_.size());
- work_queue_heaps_[set_index].erase(heap_handle);
-}
-
-void WorkQueueSets::ChangeSetIndex(WorkQueue* work_queue, size_t set_index) {
- DCHECK_EQ(this, work_queue->work_queue_sets());
- DCHECK_LT(set_index, work_queue_heaps_.size());
- EnqueueOrder enqueue_order;
- bool has_enqueue_order = work_queue->GetFrontTaskEnqueueOrder(&enqueue_order);
- size_t old_set = work_queue->work_queue_set_index();
- DCHECK_LT(old_set, work_queue_heaps_.size());
- DCHECK_NE(old_set, set_index);
- work_queue->AssignSetIndex(set_index);
- if (!has_enqueue_order)
- return;
- work_queue_heaps_[old_set].erase(work_queue->heap_handle());
- work_queue_heaps_[set_index].insert({enqueue_order, work_queue});
-}
-
-void WorkQueueSets::OnFrontTaskChanged(WorkQueue* work_queue) {
- EnqueueOrder enqueue_order;
- bool has_enqueue_order = work_queue->GetFrontTaskEnqueueOrder(&enqueue_order);
- DCHECK(has_enqueue_order);
- size_t set = work_queue->work_queue_set_index();
- work_queue_heaps_[set].ChangeKey(work_queue->heap_handle(),
- {enqueue_order, work_queue});
-}
-
-void WorkQueueSets::OnTaskPushedToEmptyQueue(WorkQueue* work_queue) {
- // NOTE if this function changes, we need to keep |WorkQueueSets::AddQueue| in
- // sync.
- DCHECK_EQ(this, work_queue->work_queue_sets());
- EnqueueOrder enqueue_order;
- bool has_enqueue_order = work_queue->GetFrontTaskEnqueueOrder(&enqueue_order);
- DCHECK(has_enqueue_order);
- size_t set_index = work_queue->work_queue_set_index();
- DCHECK_LT(set_index, work_queue_heaps_.size()) << " set_index = "
- << set_index;
- // |work_queue| should not be in work_queue_heaps_[set_index].
- DCHECK(!work_queue->heap_handle().IsValid());
- work_queue_heaps_[set_index].insert({enqueue_order, work_queue});
-}
-
-void WorkQueueSets::OnPopQueue(WorkQueue* work_queue) {
- // Assume that |work_queue| contains the lowest enqueue_order.
- size_t set_index = work_queue->work_queue_set_index();
- DCHECK_EQ(this, work_queue->work_queue_sets());
- DCHECK_LT(set_index, work_queue_heaps_.size());
- DCHECK(!work_queue_heaps_[set_index].empty()) << " set_index = " << set_index;
- DCHECK_EQ(work_queue_heaps_[set_index].Min().value, work_queue)
- << " set_index = " << set_index;
- DCHECK(work_queue->heap_handle().IsValid());
- EnqueueOrder enqueue_order;
- if (work_queue->GetFrontTaskEnqueueOrder(&enqueue_order)) {
- // O(log n)
- work_queue_heaps_[set_index].ReplaceMin({enqueue_order, work_queue});
- } else {
- // O(log n)
- work_queue_heaps_[set_index].Pop();
- DCHECK(work_queue_heaps_[set_index].empty() ||
- work_queue_heaps_[set_index].Min().value != work_queue);
- }
-}
-
-void WorkQueueSets::OnQueueBlocked(WorkQueue* work_queue) {
- DCHECK_EQ(this, work_queue->work_queue_sets());
- HeapHandle heap_handle = work_queue->heap_handle();
- if (!heap_handle.IsValid())
- return;
- size_t set_index = work_queue->work_queue_set_index();
- DCHECK_LT(set_index, work_queue_heaps_.size());
- work_queue_heaps_[set_index].erase(heap_handle);
-}
-
-bool WorkQueueSets::GetOldestQueueInSet(size_t set_index,
- WorkQueue** out_work_queue) const {
- DCHECK_LT(set_index, work_queue_heaps_.size());
- if (work_queue_heaps_[set_index].empty())
- return false;
- *out_work_queue = work_queue_heaps_[set_index].Min().value;
- DCHECK_EQ(set_index, (*out_work_queue)->work_queue_set_index());
- DCHECK((*out_work_queue)->heap_handle().IsValid());
- return true;
-}
-
-bool WorkQueueSets::GetOldestQueueAndEnqueueOrderInSet(
- size_t set_index,
- WorkQueue** out_work_queue,
- EnqueueOrder* out_enqueue_order) const {
- DCHECK_LT(set_index, work_queue_heaps_.size());
- if (work_queue_heaps_[set_index].empty())
- return false;
- const OldestTaskEnqueueOrder& oldest = work_queue_heaps_[set_index].Min();
- *out_work_queue = oldest.value;
- *out_enqueue_order = oldest.key;
- EnqueueOrder enqueue_order;
- DCHECK(oldest.value->GetFrontTaskEnqueueOrder(&enqueue_order) &&
- oldest.key == enqueue_order);
- return true;
-}
-
-bool WorkQueueSets::IsSetEmpty(size_t set_index) const {
- DCHECK_LT(set_index, work_queue_heaps_.size()) << " set_index = "
- << set_index;
- return work_queue_heaps_[set_index].empty();
-}
-
-#if DCHECK_IS_ON() || !defined(NDEBUG)
-bool WorkQueueSets::ContainsWorkQueueForTest(
- const WorkQueue* work_queue) const {
- EnqueueOrder enqueue_order;
- bool has_enqueue_order = work_queue->GetFrontTaskEnqueueOrder(&enqueue_order);
-
- for (const IntrusiveHeap<OldestTaskEnqueueOrder>& heap : work_queue_heaps_) {
- for (const OldestTaskEnqueueOrder& heap_value_pair : heap) {
- if (heap_value_pair.value == work_queue) {
- DCHECK(has_enqueue_order);
- DCHECK_EQ(heap_value_pair.key, enqueue_order);
- DCHECK_EQ(this, work_queue->work_queue_sets());
- return true;
- }
- }
- }
-
- if (work_queue->work_queue_sets() == this) {
- DCHECK(!has_enqueue_order);
- return true;
- }
-
- return false;
-}
-#endif
-
-} // namespace internal
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h b/chromium/third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h
deleted file mode 100644
index 9244a691b10..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_WORK_QUEUE_SETS_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_WORK_QUEUE_SETS_H_
-
-#include <stddef.h>
-
-#include <map>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/intrusive_heap.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/work_queue.h"
-
-namespace base {
-namespace sequence_manager {
-namespace internal {
-
-// There is a WorkQueueSet for each scheduler priority and each WorkQueueSet
-// uses a EnqueueOrderToWorkQueueMap to keep track of which queue in the set has
-// the oldest task (i.e. the one that should be run next if the
-// TaskQueueSelector chooses to run a task a given priority). The reason this
-// works is because std::map is a tree based associative container and all the
-// values are kept in sorted order.
-class PLATFORM_EXPORT WorkQueueSets {
- public:
- WorkQueueSets(size_t num_sets, const char* name);
- ~WorkQueueSets();
-
- // O(log num queues)
- void AddQueue(WorkQueue* queue, size_t set_index);
-
- // O(log num queues)
- void RemoveQueue(WorkQueue* work_queue);
-
- // O(log num queues)
- void ChangeSetIndex(WorkQueue* queue, size_t set_index);
-
- // O(log num queues)
- void OnFrontTaskChanged(WorkQueue* queue);
-
- // O(log num queues)
- void OnTaskPushedToEmptyQueue(WorkQueue* work_queue);
-
- // If empty it's O(1) amortized, otherwise it's O(log num queues)
- // Assumes |work_queue| contains the lowest enqueue order in the set.
- void OnPopQueue(WorkQueue* work_queue);
-
- // O(log num queues)
- void OnQueueBlocked(WorkQueue* work_queue);
-
- // O(1)
- bool GetOldestQueueInSet(size_t set_index, WorkQueue** out_work_queue) const;
-
- // O(1)
- bool GetOldestQueueAndEnqueueOrderInSet(
- size_t set_index,
- WorkQueue** out_work_queue,
- EnqueueOrder* out_enqueue_order) const;
-
- // O(1)
- bool IsSetEmpty(size_t set_index) const;
-
-#if DCHECK_IS_ON() || !defined(NDEBUG)
- // Note this iterates over everything in |work_queue_heaps_|.
- // It's intended for use with DCHECKS and for testing
- bool ContainsWorkQueueForTest(const WorkQueue* queue) const;
-#endif
-
- const char* GetName() const { return name_; }
-
- private:
- struct OldestTaskEnqueueOrder {
- EnqueueOrder key;
- WorkQueue* value;
-
- bool operator<=(const OldestTaskEnqueueOrder& other) const {
- return key <= other.key;
- }
-
- void SetHeapHandle(HeapHandle handle) { value->set_heap_handle(handle); }
-
- void ClearHeapHandle() { value->set_heap_handle(HeapHandle()); }
- };
-
- // For each set |work_queue_heaps_| has a queue of WorkQueue ordered by the
- // oldest task in each WorkQueue.
- std::vector<IntrusiveHeap<OldestTaskEnqueueOrder>> work_queue_heaps_;
- const char* const name_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkQueueSets);
-};
-
-} // namespace internal
-} // namespace sequence_manager
-} // namespace base
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_WORK_QUEUE_SETS_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/work_queue_sets_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/work_queue_sets_unittest.cc
deleted file mode 100644
index 237f719d33b..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/work_queue_sets_unittest.cc
+++ /dev/null
@@ -1,327 +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/platform/scheduler/base/work_queue_sets.h"
-
-#include <stddef.h>
-
-#include "base/memory/ptr_util.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/blink/renderer/platform/scheduler/base/work_queue.h"
-
-namespace base {
-namespace sequence_manager {
-class TimeDomain;
-
-namespace internal {
-
-class WorkQueueSetsTest : public testing::Test {
- public:
- void SetUp() override {
- work_queue_sets_.reset(new WorkQueueSets(kNumSets, "test"));
- }
-
- void TearDown() override {
- for (std::unique_ptr<WorkQueue>& work_queue : work_queues_) {
- if (work_queue->work_queue_sets())
- work_queue_sets_->RemoveQueue(work_queue.get());
- }
- }
-
- protected:
- enum {
- kNumSets = 5 // An arbitary choice.
- };
-
- WorkQueue* NewTaskQueue(const char* queue_name) {
- WorkQueue* queue =
- new WorkQueue(nullptr, "test", WorkQueue::QueueType::kImmediate);
- work_queues_.push_back(WrapUnique(queue));
- work_queue_sets_->AddQueue(queue, TaskQueue::kControlPriority);
- return queue;
- }
-
- TaskQueueImpl::Task FakeTaskWithEnqueueOrder(int enqueue_order) {
- TaskQueueImpl::Task fake_task(
- TaskQueue::PostedTask(BindOnce([] {}), FROM_HERE), TimeTicks(), 0);
- fake_task.set_enqueue_order(enqueue_order);
- return fake_task;
- }
-
- TaskQueueImpl::Task FakeNonNestableTaskWithEnqueueOrder(int enqueue_order) {
- TaskQueueImpl::Task fake_task(
- TaskQueue::PostedTask(BindOnce([] {}), FROM_HERE), TimeTicks(), 0);
- fake_task.set_enqueue_order(enqueue_order);
- fake_task.nestable = Nestable::kNonNestable;
- return fake_task;
- }
-
- std::vector<std::unique_ptr<WorkQueue>> work_queues_;
- std::unique_ptr<WorkQueueSets> work_queue_sets_;
-};
-
-TEST_F(WorkQueueSetsTest, ChangeSetIndex) {
- WorkQueue* work_queue = NewTaskQueue("queue");
- size_t set = TaskQueue::kNormalPriority;
- work_queue_sets_->ChangeSetIndex(work_queue, set);
-
- EXPECT_EQ(set, work_queue->work_queue_set_index());
-}
-
-TEST_F(WorkQueueSetsTest, GetOldestQueueInSet_QueueEmpty) {
- WorkQueue* work_queue = NewTaskQueue("queue");
- size_t set = TaskQueue::kNormalPriority;
- work_queue_sets_->ChangeSetIndex(work_queue, set);
-
- WorkQueue* selected_work_queue;
- EXPECT_FALSE(
- work_queue_sets_->GetOldestQueueInSet(set, &selected_work_queue));
-}
-
-TEST_F(WorkQueueSetsTest, OnTaskPushedToEmptyQueue) {
- WorkQueue* work_queue = NewTaskQueue("queue");
- size_t set = TaskQueue::kNormalPriority;
- work_queue_sets_->ChangeSetIndex(work_queue, set);
-
- WorkQueue* selected_work_queue;
- EXPECT_FALSE(
- work_queue_sets_->GetOldestQueueInSet(set, &selected_work_queue));
-
- // Calls OnTaskPushedToEmptyQueue.
- work_queue->Push(FakeTaskWithEnqueueOrder(10));
-
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(set, &selected_work_queue));
- EXPECT_EQ(work_queue, selected_work_queue);
-}
-
-TEST_F(WorkQueueSetsTest, GetOldestQueueInSet_SingleTaskInSet) {
- WorkQueue* work_queue = NewTaskQueue("queue");
- work_queue->Push(FakeTaskWithEnqueueOrder(10));
- size_t set = 1;
- work_queue_sets_->ChangeSetIndex(work_queue, set);
-
- WorkQueue* selected_work_queue;
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(set, &selected_work_queue));
- EXPECT_EQ(work_queue, selected_work_queue);
-}
-
-TEST_F(WorkQueueSetsTest, GetOldestQueueAndEnqueueOrderInSet) {
- WorkQueue* work_queue = NewTaskQueue("queue");
- work_queue->Push(FakeTaskWithEnqueueOrder(10));
- size_t set = 1;
- work_queue_sets_->ChangeSetIndex(work_queue, set);
-
- WorkQueue* selected_work_queue;
- EnqueueOrder enqueue_order;
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueAndEnqueueOrderInSet(
- set, &selected_work_queue, &enqueue_order));
- EXPECT_EQ(work_queue, selected_work_queue);
- EXPECT_EQ(10u, enqueue_order);
-}
-
-TEST_F(WorkQueueSetsTest, GetOldestQueueInSet_MultipleAgesInSet) {
- WorkQueue* queue1 = NewTaskQueue("queue1");
- WorkQueue* queue2 = NewTaskQueue("queue2");
- WorkQueue* queue3 = NewTaskQueue("queue2");
- queue1->Push(FakeTaskWithEnqueueOrder(6));
- queue2->Push(FakeTaskWithEnqueueOrder(5));
- queue3->Push(FakeTaskWithEnqueueOrder(4));
- size_t set = 2;
- work_queue_sets_->ChangeSetIndex(queue1, set);
- work_queue_sets_->ChangeSetIndex(queue2, set);
- work_queue_sets_->ChangeSetIndex(queue3, set);
-
- WorkQueue* selected_work_queue;
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(set, &selected_work_queue));
- EXPECT_EQ(queue3, selected_work_queue);
-}
-
-TEST_F(WorkQueueSetsTest, OnPopQueue) {
- WorkQueue* queue1 = NewTaskQueue("queue1");
- WorkQueue* queue2 = NewTaskQueue("queue2");
- WorkQueue* queue3 = NewTaskQueue("queue3");
- queue1->Push(FakeTaskWithEnqueueOrder(6));
- queue2->Push(FakeTaskWithEnqueueOrder(1));
- queue2->Push(FakeTaskWithEnqueueOrder(3));
- queue3->Push(FakeTaskWithEnqueueOrder(4));
- size_t set = 3;
- work_queue_sets_->ChangeSetIndex(queue1, set);
- work_queue_sets_->ChangeSetIndex(queue2, set);
- work_queue_sets_->ChangeSetIndex(queue3, set);
-
- WorkQueue* selected_work_queue;
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(set, &selected_work_queue));
- EXPECT_EQ(queue2, selected_work_queue);
-
- queue2->PopTaskForTesting();
- work_queue_sets_->OnPopQueue(queue2);
-
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(set, &selected_work_queue));
- EXPECT_EQ(queue2, selected_work_queue);
-}
-
-TEST_F(WorkQueueSetsTest, OnPopQueue_QueueBecomesEmpty) {
- WorkQueue* queue1 = NewTaskQueue("queue1");
- WorkQueue* queue2 = NewTaskQueue("queue2");
- WorkQueue* queue3 = NewTaskQueue("queue3");
- queue1->Push(FakeTaskWithEnqueueOrder(6));
- queue2->Push(FakeTaskWithEnqueueOrder(5));
- queue3->Push(FakeTaskWithEnqueueOrder(4));
- size_t set = 4;
- work_queue_sets_->ChangeSetIndex(queue1, set);
- work_queue_sets_->ChangeSetIndex(queue2, set);
- work_queue_sets_->ChangeSetIndex(queue3, set);
-
- WorkQueue* selected_work_queue;
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(set, &selected_work_queue));
- EXPECT_EQ(queue3, selected_work_queue);
-
- queue3->PopTaskForTesting();
- work_queue_sets_->OnPopQueue(queue3);
-
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(set, &selected_work_queue));
- EXPECT_EQ(queue2, selected_work_queue);
-}
-
-TEST_F(WorkQueueSetsTest,
- GetOldestQueueInSet_MultipleAgesInSetIntegerRollover) {
- WorkQueue* queue1 = NewTaskQueue("queue1");
- WorkQueue* queue2 = NewTaskQueue("queue2");
- WorkQueue* queue3 = NewTaskQueue("queue3");
- queue1->Push(FakeTaskWithEnqueueOrder(0x7ffffff1));
- queue2->Push(FakeTaskWithEnqueueOrder(0x7ffffff0));
- queue3->Push(FakeTaskWithEnqueueOrder(-0x7ffffff1));
- size_t set = 1;
- work_queue_sets_->ChangeSetIndex(queue1, set);
- work_queue_sets_->ChangeSetIndex(queue2, set);
- work_queue_sets_->ChangeSetIndex(queue3, set);
-
- WorkQueue* selected_work_queue;
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(set, &selected_work_queue));
- EXPECT_EQ(queue2, selected_work_queue);
-}
-
-TEST_F(WorkQueueSetsTest, GetOldestQueueInSet_MultipleAgesInSet_RemoveQueue) {
- WorkQueue* queue1 = NewTaskQueue("queue1");
- WorkQueue* queue2 = NewTaskQueue("queue2");
- WorkQueue* queue3 = NewTaskQueue("queue3");
- queue1->Push(FakeTaskWithEnqueueOrder(6));
- queue2->Push(FakeTaskWithEnqueueOrder(5));
- queue3->Push(FakeTaskWithEnqueueOrder(4));
- size_t set = 1;
- work_queue_sets_->ChangeSetIndex(queue1, set);
- work_queue_sets_->ChangeSetIndex(queue2, set);
- work_queue_sets_->ChangeSetIndex(queue3, set);
- work_queue_sets_->RemoveQueue(queue3);
-
- WorkQueue* selected_work_queue;
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(set, &selected_work_queue));
- EXPECT_EQ(queue2, selected_work_queue);
-}
-
-TEST_F(WorkQueueSetsTest, ChangeSetIndex_Complex) {
- WorkQueue* queue1 = NewTaskQueue("queue1");
- WorkQueue* queue2 = NewTaskQueue("queue2");
- WorkQueue* queue3 = NewTaskQueue("queue3");
- WorkQueue* queue4 = NewTaskQueue("queue4");
- queue1->Push(FakeTaskWithEnqueueOrder(6));
- queue2->Push(FakeTaskWithEnqueueOrder(5));
- queue3->Push(FakeTaskWithEnqueueOrder(4));
- queue4->Push(FakeTaskWithEnqueueOrder(3));
- size_t set1 = 1;
- size_t set2 = 2;
- work_queue_sets_->ChangeSetIndex(queue1, set1);
- work_queue_sets_->ChangeSetIndex(queue2, set1);
- work_queue_sets_->ChangeSetIndex(queue3, set2);
- work_queue_sets_->ChangeSetIndex(queue4, set2);
-
- WorkQueue* selected_work_queue;
- EXPECT_TRUE(
- work_queue_sets_->GetOldestQueueInSet(set1, &selected_work_queue));
- EXPECT_EQ(queue2, selected_work_queue);
-
- EXPECT_TRUE(
- work_queue_sets_->GetOldestQueueInSet(set2, &selected_work_queue));
- EXPECT_EQ(queue4, selected_work_queue);
-
- work_queue_sets_->ChangeSetIndex(queue4, set1);
-
- EXPECT_TRUE(
- work_queue_sets_->GetOldestQueueInSet(set1, &selected_work_queue));
- EXPECT_EQ(queue4, selected_work_queue);
-
- EXPECT_TRUE(
- work_queue_sets_->GetOldestQueueInSet(set2, &selected_work_queue));
- EXPECT_EQ(queue3, selected_work_queue);
-}
-
-TEST_F(WorkQueueSetsTest, IsSetEmpty_NoWork) {
- size_t set = 2;
- EXPECT_TRUE(work_queue_sets_->IsSetEmpty(set));
-
- WorkQueue* work_queue = NewTaskQueue("queue");
- work_queue_sets_->ChangeSetIndex(work_queue, set);
- EXPECT_TRUE(work_queue_sets_->IsSetEmpty(set));
-}
-
-TEST_F(WorkQueueSetsTest, IsSetEmpty_Work) {
- size_t set = 2;
- EXPECT_TRUE(work_queue_sets_->IsSetEmpty(set));
-
- WorkQueue* work_queue = NewTaskQueue("queue");
- work_queue->Push(FakeTaskWithEnqueueOrder(1));
- work_queue_sets_->ChangeSetIndex(work_queue, set);
- EXPECT_FALSE(work_queue_sets_->IsSetEmpty(set));
-
- work_queue->PopTaskForTesting();
- work_queue_sets_->OnPopQueue(work_queue);
- EXPECT_TRUE(work_queue_sets_->IsSetEmpty(set));
-}
-
-TEST_F(WorkQueueSetsTest, BlockQueuesByFence) {
- WorkQueue* queue1 = NewTaskQueue("queue1");
- WorkQueue* queue2 = NewTaskQueue("queue2");
-
- queue1->Push(FakeTaskWithEnqueueOrder(6));
- queue2->Push(FakeTaskWithEnqueueOrder(7));
- queue1->Push(FakeTaskWithEnqueueOrder(8));
- queue2->Push(FakeTaskWithEnqueueOrder(9));
-
- size_t set = TaskQueue::kControlPriority;
-
- WorkQueue* selected_work_queue;
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(set, &selected_work_queue));
- EXPECT_EQ(selected_work_queue, queue1);
-
- queue1->InsertFence(1);
-
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(set, &selected_work_queue));
- EXPECT_EQ(selected_work_queue, queue2);
-}
-
-TEST_F(WorkQueueSetsTest, PushNonNestableTaskToFront) {
- WorkQueue* queue1 = NewTaskQueue("queue1");
- WorkQueue* queue2 = NewTaskQueue("queue2");
- WorkQueue* queue3 = NewTaskQueue("queue3");
- queue1->Push(FakeTaskWithEnqueueOrder(6));
- queue2->Push(FakeTaskWithEnqueueOrder(5));
- queue3->Push(FakeTaskWithEnqueueOrder(4));
- size_t set = 4;
- work_queue_sets_->ChangeSetIndex(queue1, set);
- work_queue_sets_->ChangeSetIndex(queue2, set);
- work_queue_sets_->ChangeSetIndex(queue3, set);
-
- WorkQueue* selected_work_queue;
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(set, &selected_work_queue));
- EXPECT_EQ(queue3, selected_work_queue);
-
- queue1->PushNonNestableTaskToFront(FakeNonNestableTaskWithEnqueueOrder(2));
-
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(set, &selected_work_queue));
- EXPECT_EQ(queue1, selected_work_queue);
-}
-
-} // namespace internal
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/work_queue_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/base/work_queue_unittest.cc
deleted file mode 100644
index 552662fd7f3..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/base/work_queue_unittest.cc
+++ /dev/null
@@ -1,472 +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/platform/scheduler/base/work_queue.h"
-
-#include <stddef.h>
-#include <memory>
-
-#include "base/bind.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/blink/renderer/platform/scheduler/base/real_time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h"
-
-namespace base {
-namespace sequence_manager {
-namespace internal {
-namespace {
-void NopTask() {}
-
-struct Cancelable {
- Cancelable() : weak_ptr_factory(this) {}
-
- void NopTask() {}
-
- WeakPtrFactory<Cancelable> weak_ptr_factory;
-};
-} // namespace
-
-class WorkQueueTest : public testing::Test {
- public:
- void SetUp() override {
- time_domain_.reset(new RealTimeDomain());
- task_queue_ = std::make_unique<TaskQueueImpl>(nullptr, time_domain_.get(),
- TaskQueue::Spec("test"));
-
- work_queue_.reset(new WorkQueue(task_queue_.get(), "test",
- WorkQueue::QueueType::kImmediate));
- work_queue_sets_.reset(new WorkQueueSets(1, "test"));
- work_queue_sets_->AddQueue(work_queue_.get(), 0);
- }
-
- void TearDown() override { work_queue_sets_->RemoveQueue(work_queue_.get()); }
-
- protected:
- TaskQueueImpl::Task FakeCancelableTaskWithEnqueueOrder(
- int enqueue_order,
- WeakPtr<Cancelable> weak_ptr) {
- TaskQueueImpl::Task fake_task(
- TaskQueue::PostedTask(BindOnce(&Cancelable::NopTask, weak_ptr),
- FROM_HERE),
- TimeTicks(), 0);
- fake_task.set_enqueue_order(enqueue_order);
- return fake_task;
- }
-
- TaskQueueImpl::Task FakeTaskWithEnqueueOrder(int enqueue_order) {
- TaskQueueImpl::Task fake_task(
- TaskQueue::PostedTask(BindOnce(&NopTask), FROM_HERE), TimeTicks(), 0);
- fake_task.set_enqueue_order(enqueue_order);
- return fake_task;
- }
-
- TaskQueueImpl::Task FakeNonNestableTaskWithEnqueueOrder(int enqueue_order) {
- TaskQueueImpl::Task fake_task(
- TaskQueue::PostedTask(BindOnce(&NopTask), FROM_HERE), TimeTicks(), 0);
- fake_task.set_enqueue_order(enqueue_order);
- fake_task.nestable = Nestable::kNonNestable;
- return fake_task;
- }
-
- std::unique_ptr<RealTimeDomain> time_domain_;
- std::unique_ptr<TaskQueueImpl> task_queue_;
- std::unique_ptr<WorkQueue> work_queue_;
- std::unique_ptr<WorkQueueSets> work_queue_sets_;
- std::unique_ptr<TaskQueueImpl::TaskDeque> incoming_queue_;
-};
-
-TEST_F(WorkQueueTest, Empty) {
- EXPECT_TRUE(work_queue_->Empty());
- work_queue_->Push(FakeTaskWithEnqueueOrder(1));
- EXPECT_FALSE(work_queue_->Empty());
-}
-
-TEST_F(WorkQueueTest, Empty_IgnoresFences) {
- work_queue_->Push(FakeTaskWithEnqueueOrder(1));
- work_queue_->InsertFence(1);
- EXPECT_FALSE(work_queue_->Empty());
-}
-
-TEST_F(WorkQueueTest, GetFrontTaskEnqueueOrderQueueEmpty) {
- EnqueueOrder enqueue_order;
- EXPECT_FALSE(work_queue_->GetFrontTaskEnqueueOrder(&enqueue_order));
-}
-
-TEST_F(WorkQueueTest, GetFrontTaskEnqueueOrder) {
- work_queue_->Push(FakeTaskWithEnqueueOrder(2));
- work_queue_->Push(FakeTaskWithEnqueueOrder(3));
- work_queue_->Push(FakeTaskWithEnqueueOrder(4));
-
- EnqueueOrder enqueue_order;
- EXPECT_TRUE(work_queue_->GetFrontTaskEnqueueOrder(&enqueue_order));
- EXPECT_EQ(2ull, enqueue_order);
-}
-
-TEST_F(WorkQueueTest, GetFrontTaskQueueEmpty) {
- EXPECT_EQ(nullptr, work_queue_->GetFrontTask());
-}
-
-TEST_F(WorkQueueTest, GetFrontTask) {
- work_queue_->Push(FakeTaskWithEnqueueOrder(2));
- work_queue_->Push(FakeTaskWithEnqueueOrder(3));
- work_queue_->Push(FakeTaskWithEnqueueOrder(4));
-
- ASSERT_NE(nullptr, work_queue_->GetFrontTask());
- EXPECT_EQ(2ull, work_queue_->GetFrontTask()->enqueue_order());
-}
-
-TEST_F(WorkQueueTest, GetBackTask_Empty) {
- EXPECT_EQ(nullptr, work_queue_->GetBackTask());
-}
-
-TEST_F(WorkQueueTest, GetBackTask) {
- work_queue_->Push(FakeTaskWithEnqueueOrder(2));
- work_queue_->Push(FakeTaskWithEnqueueOrder(3));
- work_queue_->Push(FakeTaskWithEnqueueOrder(4));
-
- ASSERT_NE(nullptr, work_queue_->GetBackTask());
- EXPECT_EQ(4ull, work_queue_->GetBackTask()->enqueue_order());
-}
-
-TEST_F(WorkQueueTest, Push) {
- WorkQueue* work_queue;
- EXPECT_FALSE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
-
- work_queue_->Push(FakeTaskWithEnqueueOrder(2));
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
- EXPECT_EQ(work_queue_.get(), work_queue);
-}
-
-TEST_F(WorkQueueTest, PushAfterFenceHit) {
- work_queue_->InsertFence(1);
- WorkQueue* work_queue;
- EXPECT_FALSE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
-
- work_queue_->Push(FakeTaskWithEnqueueOrder(2));
- EXPECT_FALSE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
-}
-
-TEST_F(WorkQueueTest, PushNonNestableTaskToFront) {
- WorkQueue* work_queue;
- EXPECT_FALSE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
-
- work_queue_->PushNonNestableTaskToFront(
- FakeNonNestableTaskWithEnqueueOrder(3));
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
- EXPECT_EQ(work_queue_.get(), work_queue);
-
- work_queue_->PushNonNestableTaskToFront(
- FakeNonNestableTaskWithEnqueueOrder(2));
-
- EXPECT_EQ(2ull, work_queue_->GetFrontTask()->enqueue_order());
- EXPECT_EQ(3ull, work_queue_->GetBackTask()->enqueue_order());
-}
-
-TEST_F(WorkQueueTest, PushNonNestableTaskToFrontAfterFenceHit) {
- work_queue_->InsertFence(1);
- WorkQueue* work_queue;
- EXPECT_FALSE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
-
- work_queue_->PushNonNestableTaskToFront(
- FakeNonNestableTaskWithEnqueueOrder(2));
- EXPECT_FALSE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
-}
-
-TEST_F(WorkQueueTest, PushNonNestableTaskToFrontBeforeFenceHit) {
- work_queue_->InsertFence(3);
- WorkQueue* work_queue;
- EXPECT_FALSE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
-
- work_queue_->PushNonNestableTaskToFront(
- FakeNonNestableTaskWithEnqueueOrder(2));
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
-}
-
-TEST_F(WorkQueueTest, ReloadEmptyImmediateQueue) {
- task_queue_->PushImmediateIncomingTaskForTest(FakeTaskWithEnqueueOrder(2));
- task_queue_->PushImmediateIncomingTaskForTest(FakeTaskWithEnqueueOrder(3));
- task_queue_->PushImmediateIncomingTaskForTest(FakeTaskWithEnqueueOrder(4));
-
- WorkQueue* work_queue;
- EXPECT_FALSE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
- EXPECT_TRUE(work_queue_->Empty());
- work_queue_->ReloadEmptyImmediateQueue();
-
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
- EXPECT_FALSE(work_queue_->Empty());
-
- ASSERT_NE(nullptr, work_queue_->GetFrontTask());
- EXPECT_EQ(2ull, work_queue_->GetFrontTask()->enqueue_order());
-
- ASSERT_NE(nullptr, work_queue_->GetBackTask());
- EXPECT_EQ(4ull, work_queue_->GetBackTask()->enqueue_order());
-}
-
-TEST_F(WorkQueueTest, ReloadEmptyImmediateQueueAfterFenceHit) {
- work_queue_->InsertFence(1);
- task_queue_->PushImmediateIncomingTaskForTest(FakeTaskWithEnqueueOrder(2));
- task_queue_->PushImmediateIncomingTaskForTest(FakeTaskWithEnqueueOrder(3));
- task_queue_->PushImmediateIncomingTaskForTest(FakeTaskWithEnqueueOrder(4));
-
- WorkQueue* work_queue;
- EXPECT_FALSE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
- EXPECT_TRUE(work_queue_->Empty());
- work_queue_->ReloadEmptyImmediateQueue();
-
- EXPECT_FALSE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
- EXPECT_FALSE(work_queue_->Empty());
-
- ASSERT_NE(nullptr, work_queue_->GetFrontTask());
- EXPECT_EQ(2ull, work_queue_->GetFrontTask()->enqueue_order());
-
- ASSERT_NE(nullptr, work_queue_->GetBackTask());
- EXPECT_EQ(4ull, work_queue_->GetBackTask()->enqueue_order());
-}
-
-TEST_F(WorkQueueTest, TakeTaskFromWorkQueue) {
- work_queue_->Push(FakeTaskWithEnqueueOrder(2));
- work_queue_->Push(FakeTaskWithEnqueueOrder(3));
- work_queue_->Push(FakeTaskWithEnqueueOrder(4));
-
- WorkQueue* work_queue;
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
- EXPECT_FALSE(work_queue_->Empty());
-
- EXPECT_EQ(2ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order());
- EXPECT_EQ(3ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order());
- EXPECT_EQ(4ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order());
-
- EXPECT_FALSE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
- EXPECT_TRUE(work_queue_->Empty());
-}
-
-TEST_F(WorkQueueTest, TakeTaskFromWorkQueue_HitFence) {
- work_queue_->InsertFence(3);
- work_queue_->Push(FakeTaskWithEnqueueOrder(2));
- work_queue_->Push(FakeTaskWithEnqueueOrder(4));
- EXPECT_FALSE(work_queue_->BlockedByFence());
-
- WorkQueue* work_queue;
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
- EXPECT_FALSE(work_queue_->Empty());
- EXPECT_FALSE(work_queue_->BlockedByFence());
-
- EXPECT_EQ(2ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order());
- EXPECT_FALSE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
- EXPECT_FALSE(work_queue_->Empty());
- EXPECT_TRUE(work_queue_->BlockedByFence());
-}
-
-TEST_F(WorkQueueTest, InsertFenceBeforeEnqueueing) {
- EXPECT_FALSE(work_queue_->InsertFence(1));
- EXPECT_TRUE(work_queue_->BlockedByFence());
-
- work_queue_->Push(FakeTaskWithEnqueueOrder(2));
- work_queue_->Push(FakeTaskWithEnqueueOrder(3));
- work_queue_->Push(FakeTaskWithEnqueueOrder(4));
-
- EnqueueOrder enqueue_order;
- EXPECT_FALSE(work_queue_->GetFrontTaskEnqueueOrder(&enqueue_order));
-}
-
-TEST_F(WorkQueueTest, InsertFenceAfterEnqueueingNonBlocking) {
- work_queue_->Push(FakeTaskWithEnqueueOrder(2));
- work_queue_->Push(FakeTaskWithEnqueueOrder(3));
- work_queue_->Push(FakeTaskWithEnqueueOrder(4));
-
- EXPECT_FALSE(work_queue_->InsertFence(5));
- EXPECT_FALSE(work_queue_->BlockedByFence());
-
- EnqueueOrder enqueue_order;
- EXPECT_TRUE(work_queue_->GetFrontTaskEnqueueOrder(&enqueue_order));
- EXPECT_EQ(2ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order());
-}
-
-TEST_F(WorkQueueTest, InsertFenceAfterEnqueueing) {
- work_queue_->Push(FakeTaskWithEnqueueOrder(2));
- work_queue_->Push(FakeTaskWithEnqueueOrder(3));
- work_queue_->Push(FakeTaskWithEnqueueOrder(4));
-
- // NB in reality a fence will always be greater than any currently enqueued
- // tasks.
- EXPECT_FALSE(work_queue_->InsertFence(1));
- EXPECT_TRUE(work_queue_->BlockedByFence());
-
- EnqueueOrder enqueue_order;
- EXPECT_FALSE(work_queue_->GetFrontTaskEnqueueOrder(&enqueue_order));
-}
-
-TEST_F(WorkQueueTest, InsertNewFence) {
- work_queue_->Push(FakeTaskWithEnqueueOrder(2));
- work_queue_->Push(FakeTaskWithEnqueueOrder(4));
- work_queue_->Push(FakeTaskWithEnqueueOrder(5));
-
- EXPECT_FALSE(work_queue_->InsertFence(3));
- EXPECT_FALSE(work_queue_->BlockedByFence());
-
- // Note until TakeTaskFromWorkQueue() is called we don't hit the fence.
- EnqueueOrder enqueue_order;
- EXPECT_TRUE(work_queue_->GetFrontTaskEnqueueOrder(&enqueue_order));
- EXPECT_EQ(2ull, enqueue_order);
-
- EXPECT_EQ(2ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order());
- EXPECT_FALSE(work_queue_->GetFrontTaskEnqueueOrder(&enqueue_order));
- EXPECT_TRUE(work_queue_->BlockedByFence());
-
- // Inserting the new fence should temporarily unblock the queue until the new
- // one is hit.
- EXPECT_TRUE(work_queue_->InsertFence(6));
- EXPECT_FALSE(work_queue_->BlockedByFence());
-
- EXPECT_TRUE(work_queue_->GetFrontTaskEnqueueOrder(&enqueue_order));
- EXPECT_EQ(4ull, enqueue_order);
- EXPECT_EQ(4ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order());
- EXPECT_TRUE(work_queue_->GetFrontTaskEnqueueOrder(&enqueue_order));
- EXPECT_FALSE(work_queue_->BlockedByFence());
-}
-
-TEST_F(WorkQueueTest, PushWithNonEmptyQueueDoesNotHitFence) {
- work_queue_->Push(FakeTaskWithEnqueueOrder(1));
- EXPECT_FALSE(work_queue_->InsertFence(2));
- work_queue_->Push(FakeTaskWithEnqueueOrder(3));
- EXPECT_FALSE(work_queue_->BlockedByFence());
-}
-
-TEST_F(WorkQueueTest, RemoveFence) {
- work_queue_->Push(FakeTaskWithEnqueueOrder(2));
- work_queue_->Push(FakeTaskWithEnqueueOrder(4));
- work_queue_->Push(FakeTaskWithEnqueueOrder(5));
- work_queue_->InsertFence(3);
-
- WorkQueue* work_queue;
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
- EXPECT_FALSE(work_queue_->Empty());
-
- EXPECT_EQ(2ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order());
- EXPECT_FALSE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
- EXPECT_FALSE(work_queue_->Empty());
- EXPECT_TRUE(work_queue_->BlockedByFence());
-
- EXPECT_TRUE(work_queue_->RemoveFence());
- EXPECT_EQ(4ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order());
- EXPECT_TRUE(work_queue_sets_->GetOldestQueueInSet(0, &work_queue));
- EXPECT_FALSE(work_queue_->BlockedByFence());
-}
-
-TEST_F(WorkQueueTest, RemoveFenceButNoFence) {
- EXPECT_FALSE(work_queue_->RemoveFence());
-}
-
-TEST_F(WorkQueueTest, RemoveFenceNothingUnblocked) {
- EXPECT_FALSE(work_queue_->InsertFence(1));
- EXPECT_TRUE(work_queue_->BlockedByFence());
-
- EXPECT_FALSE(work_queue_->RemoveFence());
- EXPECT_FALSE(work_queue_->BlockedByFence());
-}
-
-TEST_F(WorkQueueTest, BlockedByFence) {
- EXPECT_FALSE(work_queue_->BlockedByFence());
- EXPECT_FALSE(work_queue_->InsertFence(1));
- EXPECT_TRUE(work_queue_->BlockedByFence());
-}
-
-TEST_F(WorkQueueTest, BlockedByFencePopBecomesEmpty) {
- work_queue_->Push(FakeTaskWithEnqueueOrder(1));
- EXPECT_FALSE(work_queue_->InsertFence(2));
- EXPECT_FALSE(work_queue_->BlockedByFence());
-
- EXPECT_EQ(1ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order());
- EXPECT_TRUE(work_queue_->BlockedByFence());
-}
-
-TEST_F(WorkQueueTest, BlockedByFencePop) {
- work_queue_->Push(FakeTaskWithEnqueueOrder(1));
- EXPECT_FALSE(work_queue_->InsertFence(2));
- EXPECT_FALSE(work_queue_->BlockedByFence());
-
- work_queue_->Push(FakeTaskWithEnqueueOrder(3));
- EXPECT_FALSE(work_queue_->BlockedByFence());
-
- EXPECT_EQ(1ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order());
- EXPECT_TRUE(work_queue_->BlockedByFence());
-}
-
-TEST_F(WorkQueueTest, InitiallyEmptyBlockedByFenceNewFenceUnblocks) {
- EXPECT_FALSE(work_queue_->InsertFence(1));
- EXPECT_TRUE(work_queue_->BlockedByFence());
-
- work_queue_->Push(FakeTaskWithEnqueueOrder(2));
- EXPECT_TRUE(work_queue_->InsertFence(3));
- EXPECT_FALSE(work_queue_->BlockedByFence());
-}
-
-TEST_F(WorkQueueTest, BlockedByFenceNewFenceUnblocks) {
- work_queue_->Push(FakeTaskWithEnqueueOrder(1));
- EXPECT_FALSE(work_queue_->InsertFence(2));
- EXPECT_FALSE(work_queue_->BlockedByFence());
-
- work_queue_->Push(FakeTaskWithEnqueueOrder(3));
- EXPECT_FALSE(work_queue_->BlockedByFence());
-
- EXPECT_EQ(1ull, work_queue_->TakeTaskFromWorkQueue().enqueue_order());
- EXPECT_TRUE(work_queue_->BlockedByFence());
-
- EXPECT_TRUE(work_queue_->InsertFence(4));
- EXPECT_FALSE(work_queue_->BlockedByFence());
-}
-
-TEST_F(WorkQueueTest, InsertFenceAfterEnqueuing) {
- work_queue_->Push(FakeTaskWithEnqueueOrder(2));
- work_queue_->Push(FakeTaskWithEnqueueOrder(3));
- work_queue_->Push(FakeTaskWithEnqueueOrder(4));
- EXPECT_FALSE(work_queue_->BlockedByFence());
-
- EXPECT_FALSE(work_queue_->InsertFence(1));
- EXPECT_TRUE(work_queue_->BlockedByFence());
-
- EnqueueOrder enqueue_order;
- EXPECT_FALSE(work_queue_->GetFrontTaskEnqueueOrder(&enqueue_order));
-}
-
-TEST_F(WorkQueueTest, RemoveAllCanceledTasksFromFront) {
- {
- Cancelable cancelable;
- work_queue_->Push(FakeCancelableTaskWithEnqueueOrder(
- 2, cancelable.weak_ptr_factory.GetWeakPtr()));
- work_queue_->Push(FakeCancelableTaskWithEnqueueOrder(
- 3, cancelable.weak_ptr_factory.GetWeakPtr()));
- work_queue_->Push(FakeCancelableTaskWithEnqueueOrder(
- 4, cancelable.weak_ptr_factory.GetWeakPtr()));
- work_queue_->Push(FakeTaskWithEnqueueOrder(5));
- }
- EXPECT_TRUE(work_queue_->RemoveAllCanceledTasksFromFront());
-
- EnqueueOrder enqueue_order;
- EXPECT_TRUE(work_queue_->GetFrontTaskEnqueueOrder(&enqueue_order));
- EXPECT_EQ(5ull, enqueue_order);
-}
-
-TEST_F(WorkQueueTest, RemoveAllCanceledTasksFromFrontTasksNotCanceled) {
- {
- Cancelable cancelable;
- work_queue_->Push(FakeCancelableTaskWithEnqueueOrder(
- 2, cancelable.weak_ptr_factory.GetWeakPtr()));
- work_queue_->Push(FakeCancelableTaskWithEnqueueOrder(
- 3, cancelable.weak_ptr_factory.GetWeakPtr()));
- work_queue_->Push(FakeCancelableTaskWithEnqueueOrder(
- 4, cancelable.weak_ptr_factory.GetWeakPtr()));
- work_queue_->Push(FakeTaskWithEnqueueOrder(5));
- EXPECT_FALSE(work_queue_->RemoveAllCanceledTasksFromFront());
-
- EnqueueOrder enqueue_order;
- EXPECT_TRUE(work_queue_->GetFrontTaskEnqueueOrder(&enqueue_order));
- EXPECT_EQ(2ull, enqueue_order);
- }
-}
-
-} // namespace internal
-} // namespace sequence_manager
-} // namespace base
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/DEPS b/chromium/third_party/blink/renderer/platform/scheduler/child/DEPS
index aadaadfbcab..f3b7e66a005 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/DEPS
+++ b/chromium/third_party/blink/renderer/platform/scheduler/child/DEPS
@@ -2,9 +2,3 @@ include_rules = [
"+third_party/blink/public/platform/scheduler/base",
"+third_party/blink/renderer/platform/scheduler/base",
]
-
-specific_include_rules = {
- ".*test\.cc": [
- "+components/viz/test",
- ],
-}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/cancelable_closure_holder.cc b/chromium/third_party/blink/renderer/platform/scheduler/child/cancelable_closure_holder.cc
deleted file mode 100644
index 9264b364afe..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/cancelable_closure_holder.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/child/cancelable_closure_holder.h"
-
-namespace blink {
-namespace scheduler {
-
-CancelableClosureHolder::CancelableClosureHolder() = default;
-
-CancelableClosureHolder::~CancelableClosureHolder() = default;
-
-void CancelableClosureHolder::Reset(const base::Closure& callback) {
- callback_ = callback;
- cancelable_callback_.Reset(callback_);
-}
-
-void CancelableClosureHolder::Cancel() {
- DCHECK(!callback_.is_null());
- cancelable_callback_.Reset(callback_);
-}
-
-base::Closure CancelableClosureHolder::GetCallback() const {
- DCHECK(!callback_.is_null());
- return cancelable_callback_.callback();
-}
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/cancelable_closure_holder.h b/chromium/third_party/blink/renderer/platform/scheduler/child/cancelable_closure_holder.h
deleted file mode 100644
index a8b484c3ebe..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/cancelable_closure_holder.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_CANCELABLE_CLOSURE_HOLDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_CANCELABLE_CLOSURE_HOLDER_H_
-
-#include "base/cancelable_callback.h"
-#include "base/macros.h"
-
-namespace blink {
-namespace scheduler {
-
-// A CancelableClosureHolder is a CancelableCallback which resets its wrapped
-// callback with a cached closure whenever it is canceled.
-class CancelableClosureHolder {
- public:
- CancelableClosureHolder();
- ~CancelableClosureHolder();
-
- // Resets the closure to be wrapped by the cancelable callback. Cancels any
- // outstanding callbacks.
- void Reset(const base::Closure& callback);
-
- // Cancels any outstanding closures returned by callback().
- void Cancel();
-
- // Returns a callback that will be disabled by calling Cancel(). Callback
- // must have been set using Reset() before calling this function.
- base::Closure GetCallback() const;
-
- private:
- base::Closure callback_;
- base::CancelableClosure cancelable_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(CancelableClosureHolder);
-};
-
-} // namespace scheduler
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_CANCELABLE_CLOSURE_HOLDER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/compositor_metrics_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/child/compositor_metrics_helper.cc
deleted file mode 100644
index 1f221201b89..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/compositor_metrics_helper.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/platform/scheduler/child/compositor_metrics_helper.h"
-
-namespace blink {
-namespace scheduler {
-
-CompositorMetricsHelper::CompositorMetricsHelper()
- : MetricsHelper(WebThreadType::kCompositorThread) {}
-
-CompositorMetricsHelper::~CompositorMetricsHelper() {}
-
-void CompositorMetricsHelper::RecordTaskMetrics(
- WorkerTaskQueue* queue,
- const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start_time,
- base::TimeTicks end_time,
- base::Optional<base::TimeDelta> thread_time) {
- if (ShouldDiscardTask(queue, task, start_time, end_time, thread_time))
- return;
-
- MetricsHelper::RecordCommonTaskMetrics(queue, task, start_time, end_time,
- thread_time);
-}
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/compositor_metrics_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/child/compositor_metrics_helper.h
deleted file mode 100644
index f1e07b28d20..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/compositor_metrics_helper.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_COMPOSITOR_METRICS_HELPER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_COMPOSITOR_METRICS_HELPER_H_
-
-#include "third_party/blink/renderer/platform/scheduler/child/metrics_helper.h"
-#include "third_party/blink/renderer/platform/scheduler/child/worker_task_queue.h"
-
-namespace blink {
-namespace scheduler {
-
-class PLATFORM_EXPORT CompositorMetricsHelper : public MetricsHelper {
- public:
- CompositorMetricsHelper();
- ~CompositorMetricsHelper();
-
- void RecordTaskMetrics(WorkerTaskQueue* queue,
- const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start_time,
- base::TimeTicks end_time,
- base::Optional<base::TimeDelta> thread_time);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CompositorMetricsHelper);
-};
-
-} // namespace scheduler
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_COMPOSITOR_METRICS_HELPER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/default_params.h b/chromium/third_party/blink/renderer/platform/scheduler/child/default_params.h
deleted file mode 100644
index 0db12d608d6..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/default_params.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_DEFAULT_PARAMS_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_DEFAULT_PARAMS_H_
-
-#include "third_party/blink/renderer/platform/scheduler/child/page_visibility_state.h"
-
-namespace blink {
-namespace scheduler {
-
-constexpr PageVisibilityState kDefaultPageVisibility =
- PageVisibilityState::kVisible;
-
-} // namespace scheduler
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_DEFAULT_PARAMS_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/features.h b/chromium/third_party/blink/renderer/platform/scheduler/child/features.h
index 05ddbce5a92..4b7c8b74743 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/features.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/child/features.h
@@ -10,11 +10,128 @@
namespace blink {
namespace scheduler {
-const base::Feature kHighPriorityInput{"BlinkSchedulerHighPriorityInput",
- base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kHighPriorityInputOnMainThread{
+ "BlinkSchedulerHighPriorityInput", base::FEATURE_ENABLED_BY_DEFAULT};
+
+const base::Feature kHighPriorityInputOnCompositorThread{
+ "BlinkSchedulerHighPriorityInputOnCompositorThread",
+ base::FEATURE_DISABLED_BY_DEFAULT};
const base::Feature kDedicatedWorkerThrottling{
- "kBlinkSchedulerWorkerThrottling", base::FEATURE_DISABLED_BY_DEFAULT};
+ "BlinkSchedulerWorkerThrottling", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// COMPOSITING PRIORITY EXPERIMENT CONTROLS
+
+// Enables experiment to increase priority of the compositing tasks during
+// input handling. Other features in this section do not have any effect
+// when this feature is disabled.
+const base::Feature kPrioritizeCompositingAfterInput{
+ "BlinkSchedulerPrioritizeCompositingAfterInput",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Use kHighestPriority for compositing tasks during the experiment.
+// kHighPriority is used otherwise.
+const base::Feature kHighestPriorityForCompositingAfterInput{
+ "BlinkSchedulerHighestPriorityForCompostingAfterInput",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// If enabled, MainFrameSchedulerImpl::OnRequestMainFrameForInput is used as
+// triggering signal for the experiment. If disabled, the presence of an input
+// task is used as trigger.
+const base::Feature kUseExplicitSignalForTriggeringCompositingPrioritization{
+ "BlinkSchedulerUseExplicitSignalForTriggeringCompositingPrioritization",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// If enabled, the increased priority continues until we get the appropriate
+// number of WillBeginMainFrame signals. If disabled, the priority is increased
+// for the fixed number of compositing tasks.
+const base::Feature kUseWillBeginMainFrameForCompositingPrioritization{
+ "BlinkSchedulerUseWillBeginMainFrameForCompositingPrioritization",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// LOAD PRIORITY EXPERIMENT CONTROLS
+
+// Enables setting the priority of background (with no audio) pages'
+// task queues to low priority.
+const base::Feature kLowPriorityForBackgroundPages{
+ "BlinkSchedulerLowPriorityForBackgroundPages",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enables setting the priority of background (with no audio) pages'
+// task queues to best effort.
+const base::Feature kBestEffortPriorityForBackgroundPages{
+ "BlinkSchedulerBestEffortPriorityForBackgroundPages",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enables setting the priority of sub-frame task queues to low
+// priority.
+const base::Feature kLowPriorityForSubFrame{
+ "BlinkSchedulerLowPriorityForSubFrame", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enables setting the priority of throttleable task queues to
+// low priority.
+const base::Feature kLowPriorityForThrottleableTask{
+ "BlinkSchedulerLowPriorityForThrottleableTask",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enables setting the priority of sub-frame throttleable
+// task queues to low priority.
+const base::Feature kLowPriorityForSubFrameThrottleableTask{
+ "BlinkSchedulerLowPriorityForSubFrameThrottleableTask",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enables setting the priority of hidden frame task queues to
+// low priority.
+const base::Feature kLowPriorityForHiddenFrame{
+ "BlinkSchedulerLowPriorityForHiddenFrame",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Used along with |kLowPriorityForHiddenFrame|,
+// |kLowPriorityForSubFrameThrottleableTask|, |kLowPriorityForThrottleableTask|,
+// |kLowPriorityForSubFrame| to enable one of these experiments only during the
+// load use case.
+const base::Feature kFrameExperimentOnlyWhenLoading{
+ "BlinkSchedulerFrameExperimentOnlyWhenLoading",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enables setting the priority of an ad frame to low priority.
+const base::Feature kLowPriorityForAdFrame{
+ "BlinkSchedulerLowPriorityForAdFrame", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enables setting the priority of an ad frame to best effort priority.
+const base::Feature kBestEffortPriorityForAdFrame{
+ "BlinkSchedulerBestEffortPriorityForAdFrame",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Used along with |kLowPriorityForAdFrame| or |kBestEffortPriorityForAdFrame|
+// to enable one of these experiments only during the load use case.
+const base::Feature kAdFrameExperimentOnlyWhenLoading{
+ "BlinkSchedulerAdFrameExperimentOnlyWhenLoading",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enables using a resource's fetch priority to determine the priority of the
+// resource's loading tasks posted to blink's scheduler.
+const base::Feature kUseResourceFetchPriority{
+ "BlinkSchedulerResourceFetchPriority", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enables using a resource's fetch priority to determine the priority of the
+// resource's loading tasks posted to blink's scheduler only for resources
+// requested during the loading phase.
+const base::Feature kUseResourceFetchPriorityOnlyWhenLoading{
+ "BlinkSchedulerResourceFetchPriorityOnlyWhenLoading",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enables setting the priority of cross-origin task queues to
+// low priority.
+const base::Feature kLowPriorityForCrossOrigin{
+ "BlinkSchedulerLowPriorityForCrossOrigin",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enables setting the priority of cross-origin task queues to
+// low priority during loading only.
+const base::Feature kLowPriorityForCrossOriginOnlyWhenLoading{
+ "BlinkSchedulerLowPriorityForCrossOriginOnlyWhenLoading",
+ base::FEATURE_DISABLED_BY_DEFAULT};
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper.cc b/chromium/third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper.cc
deleted file mode 100644
index 2d6a8164915..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper.h"
-
-#include "base/bind.h"
-
-namespace blink {
-namespace scheduler {
-
-namespace {
-const int kDelayedTaskSweepIntervalSeconds = 30;
-}
-
-IdleCanceledDelayedTaskSweeper::IdleCanceledDelayedTaskSweeper(
- SchedulerHelper* scheduler_helper,
- scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner)
- : scheduler_helper_(scheduler_helper),
- idle_task_runner_(idle_task_runner),
- weak_factory_(this) {
- PostIdleTask();
-}
-
-void IdleCanceledDelayedTaskSweeper::PostIdleTask() {
- idle_task_runner_->PostDelayedIdleTask(
- FROM_HERE, base::TimeDelta::FromSeconds(kDelayedTaskSweepIntervalSeconds),
- base::BindOnce(&IdleCanceledDelayedTaskSweeper::SweepIdleTask,
- weak_factory_.GetWeakPtr()));
-}
-
-void IdleCanceledDelayedTaskSweeper::SweepIdleTask(base::TimeTicks deadline) {
- TRACE_EVENT0("renderer.scheduler",
- "IdleCanceledDelayedTaskSweeper::SweepIdleTask");
- scheduler_helper_->SweepCanceledDelayedTasks();
- PostIdleTask();
-}
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper.h b/chromium/third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper.h
deleted file mode 100644
index 2e7da89d924..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_IDLE_CANCELED_DELAYED_TASK_SWEEPER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_IDLE_CANCELED_DELAYED_TASK_SWEEPER_H_
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "third_party/blink/public/platform/scheduler/single_thread_idle_task_runner.h"
-#include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
-
-namespace blink {
-namespace scheduler {
-
-// This class periodically sweeps away canceled delayed tasks, which helps
-// reduce memory consumption.
-class PLATFORM_EXPORT IdleCanceledDelayedTaskSweeper {
- public:
- IdleCanceledDelayedTaskSweeper(
- SchedulerHelper* scheduler_helper,
- scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner);
-
- private:
- void PostIdleTask();
- void SweepIdleTask(base::TimeTicks deadline);
-
- SchedulerHelper* scheduler_helper_; // NOT OWNED
- scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
- base::WeakPtrFactory<IdleCanceledDelayedTaskSweeper> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(IdleCanceledDelayedTaskSweeper);
-};
-
-} // namespace scheduler
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_IDLE_CANCELED_DELAYED_TASK_SWEEPER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc
deleted file mode 100644
index 00779dfa5c9..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper_unittest.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper.h"
-
-#include "base/task/sequence_manager/lazy_now.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "components/viz/test/ordered_simple_task_runner.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
-#include "third_party/blink/renderer/platform/scheduler/child/idle_helper.h"
-#include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.h"
-
-namespace blink {
-namespace scheduler {
-
-class TestClass {
- public:
- TestClass() : weak_factory_(this) {}
-
- void NopTask() {}
-
- base::WeakPtrFactory<TestClass> weak_factory_;
-};
-
-class IdleCanceledDelayedTaskSweeperTest : public testing::Test,
- public IdleHelper::Delegate {
- public:
- IdleCanceledDelayedTaskSweeperTest()
- : mock_task_runner_(new cc::OrderedSimpleTaskRunner(&clock_, true)),
- scheduler_helper_(new MainThreadSchedulerHelper(
- base::sequence_manager::TaskQueueManagerForTest::Create(
- nullptr,
- mock_task_runner_,
- &clock_),
- nullptr)),
- idle_helper_(
- new IdleHelper(scheduler_helper_.get(),
- this,
- "test",
- base::TimeDelta::FromSeconds(30),
- scheduler_helper_->NewTaskQueue(
- MainThreadTaskQueue::QueueCreationParams(
- MainThreadTaskQueue::QueueType::kTest)))),
- idle_canceled_delayed_taks_sweeper_(
- new IdleCanceledDelayedTaskSweeper(scheduler_helper_.get(),
- idle_helper_->IdleTaskRunner())),
- default_task_queue_(scheduler_helper_->DefaultMainThreadTaskQueue()) {
- clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
- }
-
- ~IdleCanceledDelayedTaskSweeperTest() override = default;
-
- void TearDown() override {
- // Check that all tests stop posting tasks.
- mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
- while (mock_task_runner_->RunUntilIdle()) {
- }
- }
-
- // IdleHelper::Delegate implementation:
- bool CanEnterLongIdlePeriod(
- base::TimeTicks now,
- base::TimeDelta* next_long_idle_period_delay_out) override {
- return true;
- }
- void IsNotQuiescent() override {}
- void OnIdlePeriodStarted() override {}
- void OnIdlePeriodEnded() override {}
- void OnPendingTasksChanged(bool has_tasks) override {}
-
- protected:
- base::SimpleTestTickClock clock_;
- scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
-
- std::unique_ptr<MainThreadSchedulerHelper> scheduler_helper_;
- std::unique_ptr<IdleHelper> idle_helper_;
- std::unique_ptr<IdleCanceledDelayedTaskSweeper>
- idle_canceled_delayed_taks_sweeper_;
- scoped_refptr<base::sequence_manager::TaskQueue> default_task_queue_;
-
- DISALLOW_COPY_AND_ASSIGN(IdleCanceledDelayedTaskSweeperTest);
-};
-
-TEST_F(IdleCanceledDelayedTaskSweeperTest, TestSweep) {
- TestClass class1;
- TestClass class2;
-
- // Post one task we won't cancel.
- default_task_queue_->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(&TestClass::NopTask, class1.weak_factory_.GetWeakPtr()),
- base::TimeDelta::FromSeconds(100));
-
- // And a bunch we will.
- default_task_queue_->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(&TestClass::NopTask, class2.weak_factory_.GetWeakPtr()),
- base::TimeDelta::FromSeconds(101));
-
- default_task_queue_->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(&TestClass::NopTask, class2.weak_factory_.GetWeakPtr()),
- base::TimeDelta::FromSeconds(102));
-
- default_task_queue_->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(&TestClass::NopTask, class2.weak_factory_.GetWeakPtr()),
- base::TimeDelta::FromSeconds(103));
-
- default_task_queue_->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(&TestClass::NopTask, class2.weak_factory_.GetWeakPtr()),
- base::TimeDelta::FromSeconds(104));
-
- // Cancel the last four tasks.
- class2.weak_factory_.InvalidateWeakPtrs();
-
- // Give the IdleCanceledDelayedTaskSweeper a chance to run but don't let
- // the first non canceled delayed task run. This is important because the
- // canceled tasks would get removed by TaskQueueImpl::WakeUpForDelayedWork.
- clock_.Advance(base::TimeDelta::FromSeconds(40));
- idle_helper_->EnableLongIdlePeriod();
- mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(40));
-
- EXPECT_EQ(1u, default_task_queue_->GetNumberOfPendingTasks());
-}
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/idle_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/child/idle_helper.cc
deleted file mode 100644
index 11947de63d4..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/idle_helper.cc
+++ /dev/null
@@ -1,502 +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/platform/scheduler/child/idle_helper.h"
-
-#include "base/time/time.h"
-#include "base/trace_event/trace_event.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "third_party/blink/renderer/platform/scheduler/base/real_time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h"
-#include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
-#include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
-
-namespace blink {
-namespace scheduler {
-
-using base::sequence_manager::TaskQueue;
-
-IdleHelper::IdleHelper(
- SchedulerHelper* helper,
- Delegate* delegate,
- const char* idle_period_tracing_name,
- base::TimeDelta required_quiescence_duration_before_long_idle_period,
- scoped_refptr<TaskQueue> idle_queue)
- : helper_(helper),
- delegate_(delegate),
- idle_queue_(std::move(idle_queue)),
- state_(helper, delegate, idle_period_tracing_name),
- required_quiescence_duration_before_long_idle_period_(
- required_quiescence_duration_before_long_idle_period),
- is_shutdown_(false),
- weak_factory_(this) {
- weak_idle_helper_ptr_ = weak_factory_.GetWeakPtr();
- enable_next_long_idle_period_closure_.Reset(base::BindRepeating(
- &IdleHelper::EnableLongIdlePeriod, weak_idle_helper_ptr_));
- on_idle_task_posted_closure_.Reset(base::BindRepeating(
- &IdleHelper::OnIdleTaskPostedOnMainThread, weak_idle_helper_ptr_));
-
- idle_task_runner_ = base::MakeRefCounted<SingleThreadIdleTaskRunner>(
- TaskQueueWithTaskType::Create(idle_queue_,
- TaskType::kMainThreadTaskQueueIdle),
- this);
-
- // This fence will block any idle tasks from running.
- idle_queue_->InsertFence(TaskQueue::InsertFencePosition::kBeginningOfTime);
- idle_queue_->SetQueuePriority(TaskQueue::kBestEffortPriority);
-}
-
-IdleHelper::~IdleHelper() {
- Shutdown();
-}
-
-void IdleHelper::Shutdown() {
- if (is_shutdown_)
- return;
-
- EndIdlePeriod();
- is_shutdown_ = true;
- weak_factory_.InvalidateWeakPtrs();
- // Belt & braces, might not be needed.
- idle_queue_->ShutdownTaskQueue();
-}
-
-IdleHelper::Delegate::Delegate() = default;
-
-IdleHelper::Delegate::~Delegate() = default;
-
-scoped_refptr<SingleThreadIdleTaskRunner> IdleHelper::IdleTaskRunner() {
- helper_->CheckOnValidThread();
- return idle_task_runner_;
-}
-
-IdleHelper::IdlePeriodState IdleHelper::ComputeNewLongIdlePeriodState(
- const base::TimeTicks now,
- base::TimeDelta* next_long_idle_period_delay_out) {
- helper_->CheckOnValidThread();
-
- if (!delegate_->CanEnterLongIdlePeriod(now,
- next_long_idle_period_delay_out)) {
- return IdlePeriodState::kNotInIdlePeriod;
- }
-
- base::TimeTicks next_pending_delayed_task;
- base::TimeDelta max_long_idle_period_duration =
- base::TimeDelta::FromMilliseconds(kMaximumIdlePeriodMillis);
- base::TimeDelta long_idle_period_duration;
- if (helper_->real_time_domain()->NextScheduledRunTime(
- &next_pending_delayed_task)) {
- // Limit the idle period duration to be before the next pending task.
- long_idle_period_duration = std::min(next_pending_delayed_task - now,
- max_long_idle_period_duration);
- } else {
- long_idle_period_duration = max_long_idle_period_duration;
- }
-
- if (long_idle_period_duration >=
- base::TimeDelta::FromMilliseconds(kMinimumIdlePeriodDurationMillis)) {
- *next_long_idle_period_delay_out = long_idle_period_duration;
- if (!idle_queue_->HasTaskToRunImmediately())
- return IdlePeriodState::kInLongIdlePeriodPaused;
- if (long_idle_period_duration == max_long_idle_period_duration)
- return IdlePeriodState::kInLongIdlePeriodWithMaxDeadline;
- return IdlePeriodState::kInLongIdlePeriod;
- } else {
- // If we can't start the idle period yet then try again after wake-up.
- *next_long_idle_period_delay_out = base::TimeDelta::FromMilliseconds(
- kRetryEnableLongIdlePeriodDelayMillis);
- return IdlePeriodState::kNotInIdlePeriod;
- }
-}
-
-bool IdleHelper::ShouldWaitForQuiescence() {
- helper_->CheckOnValidThread();
-
- if (required_quiescence_duration_before_long_idle_period_ ==
- base::TimeDelta()) {
- return false;
- }
-
- bool system_is_quiescent = helper_->GetAndClearSystemIsQuiescentBit();
- TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
- "ShouldWaitForQuiescence", "system_is_quiescent",
- system_is_quiescent);
- return !system_is_quiescent;
-}
-
-void IdleHelper::EnableLongIdlePeriod() {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
- "EnableLongIdlePeriod");
- helper_->CheckOnValidThread();
- if (is_shutdown_)
- return;
-
- // End any previous idle period.
- EndIdlePeriod();
-
- if (ShouldWaitForQuiescence()) {
- helper_->ControlTaskQueue()->PostDelayedTask(
- FROM_HERE, enable_next_long_idle_period_closure_.GetCallback(),
- required_quiescence_duration_before_long_idle_period_);
- delegate_->IsNotQuiescent();
- return;
- }
-
- base::TimeTicks now(helper_->NowTicks());
- base::TimeDelta next_long_idle_period_delay;
- IdlePeriodState new_idle_period_state =
- ComputeNewLongIdlePeriodState(now, &next_long_idle_period_delay);
- if (IsInIdlePeriod(new_idle_period_state)) {
- StartIdlePeriod(new_idle_period_state, now,
- now + next_long_idle_period_delay);
- } else {
- // Otherwise wait for the next long idle period delay before trying again.
- helper_->ControlTaskQueue()->PostDelayedTask(
- FROM_HERE, enable_next_long_idle_period_closure_.GetCallback(),
- next_long_idle_period_delay);
- }
-}
-
-void IdleHelper::StartIdlePeriod(IdlePeriodState new_state,
- base::TimeTicks now,
- base::TimeTicks idle_period_deadline) {
- DCHECK(!is_shutdown_);
- DCHECK_GT(idle_period_deadline, now);
- helper_->CheckOnValidThread();
- DCHECK(IsInIdlePeriod(new_state));
-
- // Allow any ready delayed idle tasks to run.
- idle_task_runner_->EnqueueReadyDelayedIdleTasks();
-
- base::TimeDelta idle_period_duration(idle_period_deadline - now);
- if (idle_period_duration <
- base::TimeDelta::FromMilliseconds(kMinimumIdlePeriodDurationMillis)) {
- TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
- "NotStartingIdlePeriodBecauseDeadlineIsTooClose",
- "idle_period_duration_ms",
- idle_period_duration.InMillisecondsF());
- return;
- }
-
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
- "StartIdlePeriod");
- if (!IsInIdlePeriod(state_.idle_period_state()))
- helper_->AddTaskObserver(this);
-
- // Use a fence to make sure any idle tasks posted after this point do not run
- // until the next idle period and unblock existing tasks.
- idle_queue_->InsertFence(TaskQueue::InsertFencePosition::kNow);
-
- state_.UpdateState(new_state, idle_period_deadline, now);
-}
-
-void IdleHelper::EndIdlePeriod() {
- if (is_shutdown_)
- return;
-
- helper_->CheckOnValidThread();
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
- "EndIdlePeriod");
-
- enable_next_long_idle_period_closure_.Cancel();
- on_idle_task_posted_closure_.Cancel();
-
- // If we weren't already within an idle period then early-out.
- if (!IsInIdlePeriod(state_.idle_period_state()))
- return;
-
- helper_->RemoveTaskObserver(this);
-
- // This fence will block any idle tasks from running.
- idle_queue_->InsertFence(TaskQueue::InsertFencePosition::kBeginningOfTime);
- state_.UpdateState(IdlePeriodState::kNotInIdlePeriod, base::TimeTicks(),
- base::TimeTicks());
-}
-
-void IdleHelper::WillProcessTask(const base::PendingTask& pending_task) {
- DCHECK(!is_shutdown_);
-}
-
-void IdleHelper::DidProcessTask(const base::PendingTask& pending_task) {
- helper_->CheckOnValidThread();
- DCHECK(!is_shutdown_);
- DCHECK(IsInIdlePeriod(state_.idle_period_state()));
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
- "DidProcessTask");
- if (state_.idle_period_state() != IdlePeriodState::kInLongIdlePeriodPaused &&
- helper_->NowTicks() >= state_.idle_period_deadline()) {
- // If the idle period deadline has now been reached, either end the idle
- // period or trigger a new long-idle period.
- if (IsInLongIdlePeriod(state_.idle_period_state())) {
- EnableLongIdlePeriod();
- } else {
- DCHECK(IdlePeriodState::kInShortIdlePeriod == state_.idle_period_state());
- EndIdlePeriod();
- }
- }
-}
-
-void IdleHelper::UpdateLongIdlePeriodStateAfterIdleTask() {
- helper_->CheckOnValidThread();
- DCHECK(!is_shutdown_);
- DCHECK(IsInLongIdlePeriod(state_.idle_period_state()));
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
- "UpdateLongIdlePeriodStateAfterIdleTask");
-
- if (!idle_queue_->HasTaskToRunImmediately()) {
- // If there are no more idle tasks then pause long idle period ticks until a
- // new idle task is posted.
- state_.UpdateState(IdlePeriodState::kInLongIdlePeriodPaused,
- state_.idle_period_deadline(), base::TimeTicks());
- } else if (idle_queue_->BlockedByFence()) {
- // If there is still idle work to do then just start the next idle period.
- base::TimeDelta next_long_idle_period_delay;
- // Ensure that we kick the scheduler at the right time to
- // initiate the next idle period.
- next_long_idle_period_delay = std::max(
- base::TimeDelta(), state_.idle_period_deadline() - helper_->NowTicks());
- if (next_long_idle_period_delay.is_zero()) {
- EnableLongIdlePeriod();
- } else {
- helper_->ControlTaskQueue()->PostDelayedTask(
- FROM_HERE, enable_next_long_idle_period_closure_.GetCallback(),
- next_long_idle_period_delay);
- }
- }
-}
-
-base::TimeTicks IdleHelper::CurrentIdleTaskDeadline() const {
- helper_->CheckOnValidThread();
- return state_.idle_period_deadline();
-}
-
-void IdleHelper::OnIdleTaskPosted() {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
- "OnIdleTaskPosted");
- if (is_shutdown_)
- return;
- if (idle_task_runner_->RunsTasksInCurrentSequence()) {
- OnIdleTaskPostedOnMainThread();
- } else {
- helper_->ControlTaskQueue()->PostTask(
- FROM_HERE, on_idle_task_posted_closure_.GetCallback());
- }
-}
-
-void IdleHelper::OnIdleTaskPostedOnMainThread() {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
- "OnIdleTaskPostedOnMainThread");
- if (is_shutdown_)
- return;
- delegate_->OnPendingTasksChanged(true);
- if (state_.idle_period_state() == IdlePeriodState::kInLongIdlePeriodPaused) {
- // Restart long idle period ticks.
- helper_->ControlTaskQueue()->PostTask(
- FROM_HERE, enable_next_long_idle_period_closure_.GetCallback());
- }
-}
-
-base::TimeTicks IdleHelper::WillProcessIdleTask() {
- helper_->CheckOnValidThread();
- DCHECK(!is_shutdown_);
- state_.TraceIdleIdleTaskStart();
- return CurrentIdleTaskDeadline();
-}
-
-void IdleHelper::DidProcessIdleTask() {
- helper_->CheckOnValidThread();
- if (is_shutdown_)
- return;
- state_.TraceIdleIdleTaskEnd();
- if (IsInLongIdlePeriod(state_.idle_period_state())) {
- UpdateLongIdlePeriodStateAfterIdleTask();
- }
- delegate_->OnPendingTasksChanged(idle_queue_->GetNumberOfPendingTasks() > 0);
-}
-
-base::TimeTicks IdleHelper::NowTicks() {
- return helper_->NowTicks();
-}
-
-// static
-bool IdleHelper::IsInIdlePeriod(IdlePeriodState state) {
- return state != IdlePeriodState::kNotInIdlePeriod;
-}
-
-// static
-bool IdleHelper::IsInLongIdlePeriod(IdlePeriodState state) {
- return state == IdlePeriodState::kInLongIdlePeriod ||
- state == IdlePeriodState::kInLongIdlePeriodWithMaxDeadline ||
- state == IdlePeriodState::kInLongIdlePeriodPaused;
-}
-
-bool IdleHelper::CanExceedIdleDeadlineIfRequired() const {
- TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
- "CanExceedIdleDeadlineIfRequired");
- helper_->CheckOnValidThread();
- return state_.idle_period_state() ==
- IdlePeriodState::kInLongIdlePeriodWithMaxDeadline;
-}
-
-IdleHelper::IdlePeriodState IdleHelper::SchedulerIdlePeriodState() const {
- return state_.idle_period_state();
-}
-
-IdleHelper::State::State(SchedulerHelper* helper,
- Delegate* delegate,
- const char* idle_period_tracing_name)
- : helper_(helper),
- delegate_(delegate),
- idle_period_state_(IdlePeriodState::kNotInIdlePeriod),
- idle_period_trace_event_started_(false),
- running_idle_task_for_tracing_(false),
- idle_period_tracing_name_(idle_period_tracing_name) {}
-
-IdleHelper::State::~State() = default;
-
-IdleHelper::IdlePeriodState IdleHelper::State::idle_period_state() const {
- helper_->CheckOnValidThread();
- return idle_period_state_;
-}
-
-base::TimeTicks IdleHelper::State::idle_period_deadline() const {
- helper_->CheckOnValidThread();
- return idle_period_deadline_;
-}
-
-void IdleHelper::State::UpdateState(IdlePeriodState new_state,
- base::TimeTicks new_deadline,
- base::TimeTicks optional_now) {
- IdlePeriodState old_idle_period_state = idle_period_state_;
-
- helper_->CheckOnValidThread();
- if (new_state == idle_period_state_) {
- DCHECK_EQ(new_deadline, idle_period_deadline_);
- return;
- }
-
- bool is_tracing;
- TRACE_EVENT_CATEGORY_GROUP_ENABLED("renderer.scheduler", &is_tracing);
- if (is_tracing) {
- base::TimeTicks now(optional_now.is_null() ? helper_->NowTicks()
- : optional_now);
- TraceEventIdlePeriodStateChange(new_state, running_idle_task_for_tracing_,
- new_deadline, now);
- }
-
- idle_period_state_ = new_state;
- idle_period_deadline_ = new_deadline;
-
- // Inform the delegate if we are starting or ending an idle period.
- if (IsInIdlePeriod(new_state) && !IsInIdlePeriod(old_idle_period_state)) {
- delegate_->OnIdlePeriodStarted();
- } else if (!IsInIdlePeriod(new_state) &&
- IsInIdlePeriod(old_idle_period_state)) {
- delegate_->OnIdlePeriodEnded();
- }
-}
-
-void IdleHelper::State::TraceIdleIdleTaskStart() {
- helper_->CheckOnValidThread();
-
- bool is_tracing;
- TRACE_EVENT_CATEGORY_GROUP_ENABLED("renderer.scheduler", &is_tracing);
- if (is_tracing) {
- TraceEventIdlePeriodStateChange(idle_period_state_, true,
- idle_period_deadline_,
- base::TimeTicks::Now());
- }
-}
-
-void IdleHelper::State::TraceIdleIdleTaskEnd() {
- helper_->CheckOnValidThread();
-
- bool is_tracing;
- TRACE_EVENT_CATEGORY_GROUP_ENABLED("renderer.scheduler", &is_tracing);
- if (is_tracing) {
- TraceEventIdlePeriodStateChange(idle_period_state_, false,
- idle_period_deadline_,
- base::TimeTicks::Now());
- }
-}
-
-void IdleHelper::State::TraceEventIdlePeriodStateChange(
- IdlePeriodState new_state,
- bool new_running_idle_task,
- base::TimeTicks new_deadline,
- base::TimeTicks now) {
- TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
- "SetIdlePeriodState", "old_state",
- IdleHelper::IdlePeriodStateToString(idle_period_state_),
- "new_state", IdleHelper::IdlePeriodStateToString(new_state));
-
- if (idle_period_trace_event_started_ && running_idle_task_for_tracing_ &&
- !new_running_idle_task) {
- running_idle_task_for_tracing_ = false;
- if (!idle_period_deadline_.is_null() && now > idle_period_deadline_) {
- TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0(
- "renderer.scheduler", idle_period_tracing_name_, this,
- "DeadlineOverrun",
- std::max(idle_period_deadline_, last_idle_task_trace_time_));
- }
- }
-
- if (IsInIdlePeriod(new_state)) {
- if (!idle_period_trace_event_started_) {
- idle_period_trace_event_started_ = true;
- TRACE_EVENT_ASYNC_BEGIN1("renderer.scheduler", idle_period_tracing_name_,
- this, "idle_period_length_ms",
- (new_deadline - now).InMillisecondsF());
- }
-
- if (new_running_idle_task) {
- last_idle_task_trace_time_ = now;
- running_idle_task_for_tracing_ = true;
- TRACE_EVENT_ASYNC_STEP_INTO0("renderer.scheduler",
- idle_period_tracing_name_, this,
- "RunningIdleTask");
- } else if (new_state == IdlePeriodState::kInShortIdlePeriod) {
- TRACE_EVENT_ASYNC_STEP_INTO0("renderer.scheduler",
- idle_period_tracing_name_, this,
- "ShortIdlePeriod");
- } else if (IsInLongIdlePeriod(new_state) &&
- new_state != IdlePeriodState::kInLongIdlePeriodPaused) {
- TRACE_EVENT_ASYNC_STEP_INTO0("renderer.scheduler",
- idle_period_tracing_name_, this,
- "LongIdlePeriod");
- } else if (new_state == IdlePeriodState::kInLongIdlePeriodPaused) {
- TRACE_EVENT_ASYNC_STEP_INTO0("renderer.scheduler",
- idle_period_tracing_name_, this,
- "LongIdlePeriodPaused");
- }
- } else if (idle_period_trace_event_started_) {
- idle_period_trace_event_started_ = false;
- TRACE_EVENT_ASYNC_END0("renderer.scheduler", idle_period_tracing_name_,
- this);
- }
-}
-
-// static
-const char* IdleHelper::IdlePeriodStateToString(
- IdlePeriodState idle_period_state) {
- switch (idle_period_state) {
- case IdlePeriodState::kNotInIdlePeriod:
- return "not_in_idle_period";
- case IdlePeriodState::kInShortIdlePeriod:
- return "in_short_idle_period";
- case IdlePeriodState::kInLongIdlePeriod:
- return "in_long_idle_period";
- case IdlePeriodState::kInLongIdlePeriodWithMaxDeadline:
- return "in_long_idle_period_with_max_deadline";
- case IdlePeriodState::kInLongIdlePeriodPaused:
- return "in_long_idle_period_paused";
- default:
- NOTREACHED();
- return nullptr;
- }
-}
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/idle_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/child/idle_helper.h
deleted file mode 100644
index ea5ac0a58d5..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/idle_helper.h
+++ /dev/null
@@ -1,251 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_IDLE_HELPER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_IDLE_HELPER_H_
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "third_party/blink/public/platform/scheduler/single_thread_idle_task_runner.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h"
-#include "third_party/blink/renderer/platform/scheduler/child/cancelable_closure_holder.h"
-#include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
-
-namespace blink {
-namespace scheduler {
-namespace idle_helper_unittest {
-class BaseIdleHelperTest;
-class IdleHelperTest;
-} // namespace idle_helper_unittest
-
-class SchedulerHelper;
-
-// The job of the IdleHelper is to run idle tasks when the system is otherwise
-// idle. Idle tasks should be optional work, with no guarantee they will be run
-// at all. Idle tasks are subject to three levels of throttling:
-//
-// 1. Both idle queues are run a BEST_EFFORT priority (i.e. only selected if
-// there is nothing else to do.
-// 2. The idle queues are only enabled during an idle period.
-// 3. Idle tasks posted from within an idle task run in the next idle period.
-// This is achieved by inserting a fence into the queue.
-//
-// There are two types of idle periods:
-// 1. Short idle period - typically less than 10ms run after begin main frame
-// has finished, with the idle period ending at the compositor provided
-// deadline.
-// 2. Long idle periods - typically up to 50ms when no frames are being
-// produced.
-//
-// Idle tasks are supplied a deadline, and should endeavor to finished before it
-// ends to avoid jank.
-class PLATFORM_EXPORT IdleHelper : public base::MessageLoop::TaskObserver,
- public SingleThreadIdleTaskRunner::Delegate {
- public:
- // Used to by scheduler implementations to customize idle behaviour.
- class PLATFORM_EXPORT Delegate {
- public:
- Delegate();
- virtual ~Delegate();
-
- // If it's ok to enter a long idle period, return true. Otherwise return
- // false and set next_long_idle_period_delay_out so we know when to try
- // again.
- virtual bool CanEnterLongIdlePeriod(
- base::TimeTicks now,
- base::TimeDelta* next_long_idle_period_delay_out) = 0;
-
- // Signals that the Long Idle Period hasn't started yet because the system
- // isn't quiescent.
- virtual void IsNotQuiescent() = 0;
-
- // Signals that we have started an Idle Period.
- virtual void OnIdlePeriodStarted() = 0;
-
- // Signals that we have finished an Idle Period.
- virtual void OnIdlePeriodEnded() = 0;
-
- // Signals that the task list has changed.
- virtual void OnPendingTasksChanged(bool has_tasks) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Delegate);
- };
-
- // Keep IdleHelper::IdlePeriodStateToString in sync with this enum.
- enum class IdlePeriodState {
- kNotInIdlePeriod,
- kInShortIdlePeriod,
- kInLongIdlePeriod,
- kInLongIdlePeriodWithMaxDeadline,
- kInLongIdlePeriodPaused,
- // Must be the last entry.
- kIdlePeriodStateCount,
- kFirstIdlePeriodState = kNotInIdlePeriod,
- };
-
- // The maximum length of an idle period.
- static const int kMaximumIdlePeriodMillis = 50;
-
- // |helper| and |delegate| are not owned by IdleHelper object and must
- // outlive it.
- IdleHelper(
- SchedulerHelper* helper,
- Delegate* delegate,
- const char* idle_period_tracing_name,
- base::TimeDelta required_quiescence_duration_before_long_idle_period,
- scoped_refptr<base::sequence_manager::TaskQueue> idle_queue);
- ~IdleHelper() override;
-
- // Prevents any further idle tasks from running.
- void Shutdown();
-
- // Returns the idle task runner. Tasks posted to this runner may be reordered
- // relative to other task types and may be starved for an arbitrarily long
- // time if no idle time is available.
- scoped_refptr<SingleThreadIdleTaskRunner> IdleTaskRunner();
-
- // If |required_quiescence_duration_before_long_idle_period_| is zero then
- // immediately initiate a long idle period, otherwise check if any tasks have
- // run recently and if so, check again after a delay of
- // |required_quiescence_duration_before_long_idle_period_|.
- // Calling this function will end any previous idle period immediately, and
- // potentially again later if
- // |required_quiescence_duration_before_long_idle_period_| is non-zero.
- // NOTE EndIdlePeriod will disable the long idle periods.
- void EnableLongIdlePeriod();
-
- // Start an idle period with a given idle period deadline.
- void StartIdlePeriod(IdlePeriodState new_idle_period_state,
- base::TimeTicks now,
- base::TimeTicks idle_period_deadline);
-
- // This will end an idle period either started with StartIdlePeriod or
- // EnableLongIdlePeriod.
- void EndIdlePeriod();
-
- // Returns true if a currently running idle task could exceed its deadline
- // without impacting user experience too much. This should only be used if
- // there is a task which cannot be pre-empted and is likely to take longer
- // than the largest expected idle task deadline. It should NOT be polled to
- // check whether more work can be performed on the current idle task after
- // its deadline has expired - post a new idle task for the continuation of the
- // work in this case.
- // Must be called from the thread this class was created on.
- bool CanExceedIdleDeadlineIfRequired() const;
-
- // Returns the deadline for the current idle task.
- base::TimeTicks CurrentIdleTaskDeadline() const;
-
- // SingleThreadIdleTaskRunner::Delegate implementation:
- void OnIdleTaskPosted() override;
- base::TimeTicks WillProcessIdleTask() override;
- void DidProcessIdleTask() override;
- base::TimeTicks NowTicks() override;
-
- // base::MessageLoop::TaskObserver implementation:
- void WillProcessTask(const base::PendingTask& pending_task) override;
- void DidProcessTask(const base::PendingTask& pending_task) override;
-
- IdlePeriodState SchedulerIdlePeriodState() const;
- static const char* IdlePeriodStateToString(IdlePeriodState state);
-
- private:
- friend class idle_helper_unittest::BaseIdleHelperTest;
- friend class idle_helper_unittest::IdleHelperTest;
-
- const scoped_refptr<base::sequence_manager::TaskQueue>& idle_queue() const {
- return idle_queue_;
- }
-
- class State {
- public:
- State(SchedulerHelper* helper,
- Delegate* delegate,
- const char* idle_period_tracing_name);
- virtual ~State();
-
- void UpdateState(IdlePeriodState new_state,
- base::TimeTicks new_deadline,
- base::TimeTicks optional_now);
- bool IsIdlePeriodPaused() const;
-
- IdlePeriodState idle_period_state() const;
- base::TimeTicks idle_period_deadline() const;
-
- void TraceIdleIdleTaskStart();
- void TraceIdleIdleTaskEnd();
-
- private:
- void TraceEventIdlePeriodStateChange(IdlePeriodState new_state,
- bool new_running_idle_task,
- base::TimeTicks new_deadline,
- base::TimeTicks optional_now);
-
- SchedulerHelper* helper_; // NOT OWNED
- Delegate* delegate_; // NOT OWNED
-
- IdlePeriodState idle_period_state_;
- base::TimeTicks idle_period_deadline_;
-
- base::TimeTicks last_idle_task_trace_time_;
- bool idle_period_trace_event_started_;
- bool running_idle_task_for_tracing_;
- const char* idle_period_tracing_name_;
-
- DISALLOW_COPY_AND_ASSIGN(State);
- };
-
- // The minimum duration of an idle period.
- static const int kMinimumIdlePeriodDurationMillis = 1;
-
- // The minimum delay to wait between retrying to initiate a long idle time.
- static const int kRetryEnableLongIdlePeriodDelayMillis = 1;
-
- // Returns the new idle period state for the next long idle period. Fills in
- // |next_long_idle_period_delay_out| with the next time we should try to
- // initiate the next idle period.
- IdlePeriodState ComputeNewLongIdlePeriodState(
- const base::TimeTicks now,
- base::TimeDelta* next_long_idle_period_delay_out);
-
- bool ShouldWaitForQuiescence();
- void OnIdleTaskPostedOnMainThread();
- void UpdateLongIdlePeriodStateAfterIdleTask();
-
- void SetIdlePeriodState(IdlePeriodState new_state,
- base::TimeTicks new_deadline,
- base::TimeTicks optional_now);
-
- // Returns true if |state| represents being within an idle period state.
- static bool IsInIdlePeriod(IdlePeriodState state);
- // Returns true if |state| represents being within a long idle period state.
- static bool IsInLongIdlePeriod(IdlePeriodState state);
-
- SchedulerHelper* helper_; // NOT OWNED
- Delegate* delegate_; // NOT OWNED
- scoped_refptr<base::sequence_manager::TaskQueue> idle_queue_;
- scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
-
- CancelableClosureHolder enable_next_long_idle_period_closure_;
- CancelableClosureHolder on_idle_task_posted_closure_;
-
- State state_;
-
- base::TimeDelta required_quiescence_duration_before_long_idle_period_;
-
- bool is_shutdown_;
-
- base::WeakPtr<IdleHelper> weak_idle_helper_ptr_;
- base::WeakPtrFactory<IdleHelper> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(IdleHelper);
-};
-
-} // namespace scheduler
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_IDLE_HELPER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/idle_helper_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/child/idle_helper_unittest.cc
deleted file mode 100644
index 2e7b506202d..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/idle_helper_unittest.cc
+++ /dev/null
@@ -1,1193 +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/platform/scheduler/child/idle_helper.h"
-
-#include <utility>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "components/viz/test/ordered_simple_task_runner.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/scheduler/base/real_time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
-#include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
-#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h"
-
-using testing::_;
-using testing::AnyNumber;
-using testing::AtLeast;
-using testing::Exactly;
-using testing::Invoke;
-using testing::Return;
-
-namespace blink {
-namespace scheduler {
-
-using base::sequence_manager::TaskQueue;
-using base::sequence_manager::TaskQueueManager;
-
-// To avoid symbol collisions in jumbo builds.
-namespace idle_helper_unittest {
-
-void AppendToVectorTestTask(std::vector<std::string>* vector,
- std::string value) {
- vector->push_back(value);
-}
-
-void AppendToVectorIdleTestTask(std::vector<std::string>* vector,
- std::string value,
- base::TimeTicks deadline) {
- AppendToVectorTestTask(vector, value);
-}
-
-void NullTask() {}
-
-void NullIdleTask(base::TimeTicks deadline) {}
-
-void AppendToVectorReentrantTask(base::SingleThreadTaskRunner* task_runner,
- std::vector<int>* vector,
- int* reentrant_count,
- int max_reentrant_count) {
- vector->push_back((*reentrant_count)++);
- if (*reentrant_count < max_reentrant_count) {
- task_runner->PostTask(FROM_HERE,
- base::BindOnce(AppendToVectorReentrantTask,
- base::Unretained(task_runner), vector,
- reentrant_count, max_reentrant_count));
- }
-}
-
-void IdleTestTask(int* run_count,
- base::TimeTicks* deadline_out,
- base::TimeTicks deadline) {
- (*run_count)++;
- *deadline_out = deadline;
-}
-
-int g_max_idle_task_reposts = 2;
-
-void RepostingIdleTestTask(SingleThreadIdleTaskRunner* idle_task_runner,
- int* run_count,
- base::TimeTicks* deadline_out,
- base::TimeTicks deadline) {
- if ((*run_count + 1) < g_max_idle_task_reposts) {
- idle_task_runner->PostIdleTask(
- FROM_HERE, base::BindOnce(&RepostingIdleTestTask,
- base::Unretained(idle_task_runner), run_count,
- deadline_out));
- }
- *deadline_out = deadline;
- (*run_count)++;
-}
-
-void RepostingUpdateClockIdleTestTask(
- SingleThreadIdleTaskRunner* idle_task_runner,
- int* run_count,
- base::SimpleTestTickClock* clock,
- base::TimeDelta advance_time,
- std::vector<base::TimeTicks>* deadlines,
- base::TimeTicks deadline) {
- if ((*run_count + 1) < g_max_idle_task_reposts) {
- idle_task_runner->PostIdleTask(
- FROM_HERE, base::BindOnce(&RepostingUpdateClockIdleTestTask,
- base::Unretained(idle_task_runner), run_count,
- clock, advance_time, deadlines));
- }
- deadlines->push_back(deadline);
- (*run_count)++;
- clock->Advance(advance_time);
-}
-
-void RepeatingTask(base::SingleThreadTaskRunner* task_runner,
- int num_repeats,
- base::TimeDelta delay) {
- if (num_repeats > 1) {
- task_runner->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(&RepeatingTask, base::Unretained(task_runner),
- num_repeats - 1, delay),
- delay);
- }
-}
-
-void UpdateClockIdleTestTask(base::SimpleTestTickClock* clock,
- int* run_count,
- base::TimeTicks set_time,
- base::TimeTicks deadline) {
- clock->Advance(set_time - clock->NowTicks());
- (*run_count)++;
-}
-
-void UpdateClockToDeadlineIdleTestTask(base::SimpleTestTickClock* clock,
- int* run_count,
- base::TimeTicks deadline) {
- UpdateClockIdleTestTask(clock, run_count, deadline, deadline);
-}
-
-void EndIdlePeriodIdleTask(IdleHelper* idle_helper, base::TimeTicks deadline) {
- idle_helper->EndIdlePeriod();
-}
-
-void ShutdownIdleTask(IdleHelper* helper,
- bool* shutdown_task_run,
- base::TimeTicks deadline) {
- *shutdown_task_run = true;
- helper->Shutdown();
-}
-
-// RAII helper class to enable auto advancing of time inside mock task runner.
-// Automatically disables auto-advancement when destroyed.
-class ScopedAutoAdvanceNowEnabler {
- public:
- ScopedAutoAdvanceNowEnabler(
- scoped_refptr<cc::OrderedSimpleTaskRunner> task_runner)
- : task_runner_(task_runner) {
- if (task_runner_)
- task_runner_->SetAutoAdvanceNowToPendingTasks(true);
- }
-
- ~ScopedAutoAdvanceNowEnabler() {
- if (task_runner_)
- task_runner_->SetAutoAdvanceNowToPendingTasks(false);
- }
-
- private:
- scoped_refptr<cc::OrderedSimpleTaskRunner> task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedAutoAdvanceNowEnabler);
-};
-
-class IdleHelperForTest : public IdleHelper, public IdleHelper::Delegate {
- public:
- explicit IdleHelperForTest(
- SchedulerHelper* scheduler_helper,
- base::TimeDelta required_quiescence_duration_before_long_idle_period,
- scoped_refptr<TaskQueue> idle_task_runner)
- : IdleHelper(scheduler_helper,
- this,
- "TestSchedulerIdlePeriod",
- required_quiescence_duration_before_long_idle_period,
- idle_task_runner) {}
-
- ~IdleHelperForTest() override = default;
-
- // IdleHelper::Delegate implementation:
- MOCK_METHOD2(CanEnterLongIdlePeriod,
- bool(base::TimeTicks now,
- base::TimeDelta* next_long_idle_period_delay_out));
-
- MOCK_METHOD0(IsNotQuiescent, void());
- MOCK_METHOD0(OnIdlePeriodStarted, void());
- MOCK_METHOD0(OnIdlePeriodEnded, void());
- MOCK_METHOD1(OnPendingTasksChanged, void(bool has_tasks));
-};
-
-class BaseIdleHelperTest : public testing::Test {
- public:
- BaseIdleHelperTest(
- base::MessageLoop* message_loop,
- base::TimeDelta required_quiescence_duration_before_long_idle_period)
- : mock_task_runner_(
- message_loop ? nullptr
- : new cc::OrderedSimpleTaskRunner(&clock_, false)),
- message_loop_(message_loop) {
- std::unique_ptr<TaskQueueManager> task_queue_manager =
- base::sequence_manager::TaskQueueManagerForTest::Create(
- message_loop,
- message_loop ? message_loop->task_runner() : mock_task_runner_,
- &clock_);
- task_queue_manager_ = task_queue_manager.get();
- scheduler_helper_ = std::make_unique<NonMainThreadSchedulerHelper>(
- std::move(task_queue_manager), nullptr, TaskType::kInternalTest);
- idle_helper_ = std::make_unique<IdleHelperForTest>(
- scheduler_helper_.get(),
- required_quiescence_duration_before_long_idle_period,
- scheduler_helper_->NewTaskQueue(TaskQueue::Spec("idle_test")));
- default_task_runner_ = scheduler_helper_->DefaultWorkerTaskQueue();
- idle_task_runner_ = idle_helper_->IdleTaskRunner();
- clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
- }
-
- ~BaseIdleHelperTest() override = default;
-
- void SetUp() override {
- EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(AnyNumber());
- EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(AnyNumber());
- EXPECT_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _))
- .Times(AnyNumber())
- .WillRepeatedly(Return(true));
- EXPECT_CALL(*idle_helper_, OnPendingTasksChanged(_)).Times(AnyNumber());
- }
-
- void TearDown() override {
- EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(AnyNumber());
- idle_helper_->Shutdown();
- DCHECK(!mock_task_runner_.get() || !message_loop_.get());
- if (mock_task_runner_.get()) {
- // Check that all tests stop posting tasks.
- mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
- while (mock_task_runner_->RunUntilIdle()) {
- }
- } else {
- base::RunLoop().RunUntilIdle();
- }
- }
-
- TaskQueueManager* task_queue_manager() const { return task_queue_manager_; }
-
- void RunUntilIdle() {
- // Only one of mock_task_runner_ or message_loop_ should be set.
- DCHECK(!mock_task_runner_.get() || !message_loop_.get());
- if (mock_task_runner_.get()) {
- mock_task_runner_->RunUntilIdle();
- } else {
- base::RunLoop().RunUntilIdle();
- }
- }
-
- template <typename E>
- static void CallForEachEnumValue(E first,
- E last,
- const char* (*function)(E)) {
- for (E val = first; val < last;
- val = static_cast<E>(static_cast<int>(val) + 1)) {
- (*function)(val);
- }
- }
-
- static void CheckAllTaskQueueIdToString() {
- CallForEachEnumValue<IdleHelper::IdlePeriodState>(
- IdleHelper::IdlePeriodState::kFirstIdlePeriodState,
- IdleHelper::IdlePeriodState::kIdlePeriodStateCount,
- &IdleHelper::IdlePeriodStateToString);
- }
-
- bool IsInIdlePeriod() const {
- return idle_helper_->IsInIdlePeriod(
- idle_helper_->SchedulerIdlePeriodState());
- }
-
- protected:
- static base::TimeDelta maximum_idle_period_duration() {
- return base::TimeDelta::FromMilliseconds(
- IdleHelper::kMaximumIdlePeriodMillis);
- }
-
- static base::TimeDelta retry_enable_long_idle_period_delay() {
- return base::TimeDelta::FromMilliseconds(
- IdleHelper::kRetryEnableLongIdlePeriodDelayMillis);
- }
-
- static base::TimeDelta minimum_idle_period_duration() {
- return base::TimeDelta::FromMilliseconds(
- IdleHelper::kMinimumIdlePeriodDurationMillis);
- }
-
- base::TimeTicks CurrentIdleTaskDeadline() {
- return idle_helper_->CurrentIdleTaskDeadline();
- }
-
- void CheckIdlePeriodStateIs(const char* expected) {
- EXPECT_STREQ(expected, IdleHelper::IdlePeriodStateToString(
- idle_helper_->SchedulerIdlePeriodState()));
- }
-
- const scoped_refptr<TaskQueue>& idle_queue() const {
- return idle_helper_->idle_queue_;
- }
-
- base::SimpleTestTickClock clock_;
- // Only one of mock_task_runner_ or message_loop_ will be set.
- scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
- std::unique_ptr<base::MessageLoop> message_loop_;
-
- std::unique_ptr<NonMainThreadSchedulerHelper> scheduler_helper_;
- TaskQueueManager* task_queue_manager_; // Owned by scheduler_helper_.
- std::unique_ptr<IdleHelperForTest> idle_helper_;
- scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
- scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(BaseIdleHelperTest);
-};
-
-class IdleHelperTest : public BaseIdleHelperTest {
- public:
- IdleHelperTest() : BaseIdleHelperTest(nullptr, base::TimeDelta()) {}
-
- ~IdleHelperTest() override = default;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(IdleHelperTest);
-};
-
-TEST_F(IdleHelperTest, TestPostIdleTask) {
- int run_count = 0;
- base::TimeTicks expected_deadline =
- clock_.NowTicks() + base::TimeDelta::FromMilliseconds(2300);
- base::TimeTicks deadline_in_task;
-
- clock_.Advance(base::TimeDelta::FromMilliseconds(100));
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
-
- RunUntilIdle();
- EXPECT_EQ(0, run_count);
-
- idle_helper_->StartIdlePeriod(IdleHelper::IdlePeriodState::kInShortIdlePeriod,
- clock_.NowTicks(), expected_deadline);
- RunUntilIdle();
- EXPECT_EQ(1, run_count);
- EXPECT_EQ(expected_deadline, deadline_in_task);
-}
-
-TEST_F(IdleHelperTest, TestPostIdleTask_EndIdlePeriod) {
- int run_count = 0;
- base::TimeTicks deadline_in_task;
-
- clock_.Advance(base::TimeDelta::FromMilliseconds(100));
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
-
- RunUntilIdle();
- EXPECT_EQ(0, run_count);
-
- idle_helper_->StartIdlePeriod(
- IdleHelper::IdlePeriodState::kInShortIdlePeriod, clock_.NowTicks(),
- clock_.NowTicks() + base::TimeDelta::FromMilliseconds(10));
- idle_helper_->EndIdlePeriod();
- RunUntilIdle();
- EXPECT_EQ(0, run_count);
-}
-
-TEST_F(IdleHelperTest, TestRepostingIdleTask) {
- base::TimeTicks actual_deadline;
- int run_count = 0;
-
- g_max_idle_task_reposts = 2;
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&RepostingIdleTestTask,
- base::RetainedRef(idle_task_runner_),
- &run_count, &actual_deadline));
- idle_helper_->StartIdlePeriod(
- IdleHelper::IdlePeriodState::kInShortIdlePeriod, clock_.NowTicks(),
- clock_.NowTicks() + base::TimeDelta::FromMilliseconds(10));
- RunUntilIdle();
- EXPECT_EQ(1, run_count);
-
- // Reposted tasks shouldn't run until next idle period.
- RunUntilIdle();
- EXPECT_EQ(1, run_count);
-
- idle_helper_->StartIdlePeriod(
- IdleHelper::IdlePeriodState::kInShortIdlePeriod, clock_.NowTicks(),
- clock_.NowTicks() + base::TimeDelta::FromMilliseconds(10));
- RunUntilIdle();
- EXPECT_EQ(2, run_count);
-}
-
-TEST_F(IdleHelperTest, TestIdleTaskExceedsDeadline) {
- int run_count = 0;
-
- // Post two UpdateClockToDeadlineIdleTestTask tasks.
- idle_task_runner_->PostIdleTask(
- FROM_HERE,
- base::BindOnce(&UpdateClockToDeadlineIdleTestTask, &clock_, &run_count));
- idle_task_runner_->PostIdleTask(
- FROM_HERE,
- base::BindOnce(&UpdateClockToDeadlineIdleTestTask, &clock_, &run_count));
-
- idle_helper_->StartIdlePeriod(
- IdleHelper::IdlePeriodState::kInShortIdlePeriod, clock_.NowTicks(),
- clock_.NowTicks() + base::TimeDelta::FromMilliseconds(10));
- RunUntilIdle();
- // Only the first idle task should execute since it's used up the deadline.
- EXPECT_EQ(1, run_count);
-
- idle_helper_->EndIdlePeriod();
- idle_helper_->StartIdlePeriod(
- IdleHelper::IdlePeriodState::kInShortIdlePeriod, clock_.NowTicks(),
- clock_.NowTicks() + base::TimeDelta::FromMilliseconds(10));
- RunUntilIdle();
- // Second task should be run on the next idle period.
- EXPECT_EQ(2, run_count);
-}
-
-class IdleHelperTestWithIdlePeriodObserver : public BaseIdleHelperTest {
- public:
- IdleHelperTestWithIdlePeriodObserver()
- : BaseIdleHelperTest(nullptr, base::TimeDelta()) {}
-
- ~IdleHelperTestWithIdlePeriodObserver() override = default;
-
- void SetUp() override {
- // Don't set expectations on IdleHelper::Delegate.
- }
-
- void ExpectIdlePeriodStartsButNeverEnds() {
- EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(1);
- EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(0);
- }
-
- void ExpectIdlePeriodStartsAndEnds(const testing::Cardinality& cardinality) {
- EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(cardinality);
- EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(cardinality);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(IdleHelperTestWithIdlePeriodObserver);
-};
-
-TEST_F(IdleHelperTestWithIdlePeriodObserver, TestEnterButNotExitIdlePeriod) {
- ExpectIdlePeriodStartsButNeverEnds();
-
- idle_helper_->StartIdlePeriod(
- IdleHelper::IdlePeriodState::kInShortIdlePeriod, clock_.NowTicks(),
- clock_.NowTicks() + base::TimeDelta::FromMilliseconds(10));
-}
-
-TEST_F(IdleHelperTestWithIdlePeriodObserver, TestEnterAndExitIdlePeriod) {
- BaseIdleHelperTest* fixture = this;
- ON_CALL(*idle_helper_, OnIdlePeriodStarted())
- .WillByDefault(
- Invoke([fixture]() { EXPECT_TRUE(fixture->IsInIdlePeriod()); }));
- ON_CALL(*idle_helper_, OnIdlePeriodEnded())
- .WillByDefault(
- Invoke([fixture]() { EXPECT_FALSE(fixture->IsInIdlePeriod()); }));
-
- ExpectIdlePeriodStartsAndEnds(Exactly(1));
-
- idle_helper_->StartIdlePeriod(
- IdleHelper::IdlePeriodState::kInShortIdlePeriod, clock_.NowTicks(),
- clock_.NowTicks() + base::TimeDelta::FromMilliseconds(10));
- idle_helper_->EndIdlePeriod();
-}
-
-class IdleHelperWithMessageLoopTest : public BaseIdleHelperTest {
- public:
- IdleHelperWithMessageLoopTest()
- : BaseIdleHelperTest(new base::MessageLoop(), base::TimeDelta()) {}
- ~IdleHelperWithMessageLoopTest() override = default;
-
- void PostFromNestedRunloop(
- std::vector<std::pair<SingleThreadIdleTaskRunner::IdleTask, bool>>*
- tasks) {
- for (std::pair<SingleThreadIdleTaskRunner::IdleTask, bool>& pair : *tasks) {
- if (pair.second) {
- idle_task_runner_->PostIdleTask(FROM_HERE, std::move(pair.first));
- } else {
- idle_task_runner_->PostNonNestableIdleTask(FROM_HERE,
- std::move(pair.first));
- }
- }
- idle_helper_->StartIdlePeriod(
- IdleHelper::IdlePeriodState::kInShortIdlePeriod, clock_.NowTicks(),
- clock_.NowTicks() + base::TimeDelta::FromMilliseconds(10));
- base::RunLoop(base::RunLoop::Type::kNestableTasksAllowed).RunUntilIdle();
- }
-
- void SetUp() override {
- EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(AnyNumber());
- EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(AnyNumber());
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(IdleHelperWithMessageLoopTest);
-};
-
-TEST_F(IdleHelperWithMessageLoopTest,
- NonNestableIdleTaskDoesntExecuteInNestedLoop) {
- std::vector<std::string> order;
- idle_task_runner_->PostIdleTask(
- FROM_HERE,
- base::BindOnce(&AppendToVectorIdleTestTask, &order, std::string("1")));
- idle_task_runner_->PostIdleTask(
- FROM_HERE,
- base::BindOnce(&AppendToVectorIdleTestTask, &order, std::string("2")));
-
- std::vector<std::pair<SingleThreadIdleTaskRunner::IdleTask, bool>>
- tasks_to_post_from_nested_loop;
- tasks_to_post_from_nested_loop.push_back(std::make_pair(
- base::BindOnce(&AppendToVectorIdleTestTask, &order, std::string("3")),
- false));
- tasks_to_post_from_nested_loop.push_back(std::make_pair(
- base::BindOnce(&AppendToVectorIdleTestTask, &order, std::string("4")),
- true));
- tasks_to_post_from_nested_loop.push_back(std::make_pair(
- base::BindOnce(&AppendToVectorIdleTestTask, &order, std::string("5")),
- true));
-
- default_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&IdleHelperWithMessageLoopTest::PostFromNestedRunloop,
- base::Unretained(this),
- base::Unretained(&tasks_to_post_from_nested_loop)));
-
- idle_helper_->StartIdlePeriod(
- IdleHelper::IdlePeriodState::kInShortIdlePeriod, clock_.NowTicks(),
- clock_.NowTicks() + base::TimeDelta::FromMilliseconds(10));
- RunUntilIdle();
- // Note we expect task 3 to run last because it's non-nestable.
- EXPECT_THAT(order, testing::ElementsAre(std::string("1"), std::string("2"),
- std::string("4"), std::string("5"),
- std::string("3")));
-}
-
-TEST_F(IdleHelperTestWithIdlePeriodObserver, TestLongIdlePeriod) {
- base::TimeTicks expected_deadline =
- clock_.NowTicks() + maximum_idle_period_duration();
- base::TimeTicks deadline_in_task;
- int run_count = 0;
-
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
-
- EXPECT_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _))
- .Times(1)
- .WillRepeatedly(Return(true));
- ExpectIdlePeriodStartsButNeverEnds();
-
- RunUntilIdle();
- EXPECT_EQ(0, run_count); // Shouldn't run yet as no idle period.
-
- idle_helper_->EnableLongIdlePeriod();
- RunUntilIdle();
- EXPECT_EQ(1, run_count); // Should have run in a long idle time.
- EXPECT_EQ(expected_deadline, deadline_in_task);
-}
-
-TEST_F(IdleHelperTest, TestLongIdlePeriodWithPendingDelayedTask) {
- base::TimeDelta pending_task_delay = base::TimeDelta::FromMilliseconds(30);
- base::TimeTicks expected_deadline = clock_.NowTicks() + pending_task_delay;
- base::TimeTicks deadline_in_task;
- int run_count = 0;
-
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
- default_task_runner_->PostDelayedTask(FROM_HERE, base::BindOnce(&NullTask),
- pending_task_delay);
-
- idle_helper_->EnableLongIdlePeriod();
- RunUntilIdle();
- EXPECT_EQ(1, run_count); // Should have run in a long idle time.
- EXPECT_EQ(expected_deadline, deadline_in_task);
-}
-
-TEST_F(IdleHelperTest, TestLongIdlePeriodWithLatePendingDelayedTask) {
- base::TimeDelta pending_task_delay = base::TimeDelta::FromMilliseconds(10);
- base::TimeTicks deadline_in_task;
- int run_count = 0;
-
- default_task_runner_->PostDelayedTask(FROM_HERE, base::BindOnce(&NullTask),
- pending_task_delay);
-
- // Advance clock until after delayed task was meant to be run.
- clock_.Advance(base::TimeDelta::FromMilliseconds(20));
-
- // Post an idle task and then EnableLongIdlePeriod. Since there is a late
- // pending delayed task this shouldn't actually start an idle period.
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
- idle_helper_->EnableLongIdlePeriod();
- RunUntilIdle();
- EXPECT_EQ(0, run_count);
-
- // After the delayed task has been run we should trigger an idle period.
- clock_.Advance(maximum_idle_period_duration());
- RunUntilIdle();
- EXPECT_EQ(1, run_count);
-}
-
-TEST_F(IdleHelperTestWithIdlePeriodObserver, TestLongIdlePeriodRepeating) {
- mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
- std::vector<base::TimeTicks> actual_deadlines;
- int run_count = 0;
-
- EXPECT_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _))
- .Times(4)
- .WillRepeatedly(Return(true));
- ExpectIdlePeriodStartsAndEnds(AtLeast(2));
-
- g_max_idle_task_reposts = 3;
- base::TimeTicks clock_before(clock_.NowTicks());
- base::TimeDelta idle_task_runtime(base::TimeDelta::FromMilliseconds(10));
- idle_task_runner_->PostIdleTask(
- FROM_HERE,
- base::BindOnce(&RepostingUpdateClockIdleTestTask,
- base::RetainedRef(idle_task_runner_), &run_count, &clock_,
- idle_task_runtime, &actual_deadlines));
-
- // Check each idle task runs in their own idle period.
- idle_helper_->EnableLongIdlePeriod();
- RunUntilIdle();
- EXPECT_EQ(3, run_count);
- EXPECT_THAT(
- actual_deadlines,
- testing::ElementsAre(clock_before + maximum_idle_period_duration(),
- clock_before + 2 * maximum_idle_period_duration(),
- clock_before + 3 * maximum_idle_period_duration()));
-
- g_max_idle_task_reposts = 5;
- idle_task_runner_->PostIdleTask(
- FROM_HERE,
- base::BindOnce(&RepostingUpdateClockIdleTestTask,
- base::RetainedRef(idle_task_runner_), &run_count, &clock_,
- idle_task_runtime, &actual_deadlines));
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&EndIdlePeriodIdleTask,
- base::Unretained(idle_helper_.get())));
-
- // Ensure that reposting tasks stop after EndIdlePeriod is called.
- RunUntilIdle();
- EXPECT_EQ(4, run_count);
-}
-
-TEST_F(IdleHelperTestWithIdlePeriodObserver,
- TestLongIdlePeriodWhenNotCanEnterLongIdlePeriod) {
- base::TimeDelta delay = base::TimeDelta::FromMilliseconds(1000);
- base::TimeDelta half_delay = base::TimeDelta::FromMilliseconds(500);
- base::TimeTicks delay_over = clock_.NowTicks() + delay;
- base::TimeTicks deadline_in_task;
- int run_count = 0;
-
- ON_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _))
- .WillByDefault(
- Invoke([delay, delay_over](
- base::TimeTicks now,
- base::TimeDelta* next_long_idle_period_delay_out) {
- if (now >= delay_over)
- return true;
- *next_long_idle_period_delay_out = delay;
- return false;
- }));
-
- EXPECT_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _)).Times(2);
- EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(AnyNumber());
-
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
-
- // Make sure Idle tasks don't run until the delay has occurred.
- idle_helper_->EnableLongIdlePeriod();
- RunUntilIdle();
- EXPECT_EQ(0, run_count);
-
- clock_.Advance(half_delay);
- RunUntilIdle();
- EXPECT_EQ(0, run_count);
-
- // Delay is finished, idle task should run.
- clock_.Advance(half_delay);
- RunUntilIdle();
- EXPECT_EQ(1, run_count);
-}
-
-TEST_F(IdleHelperTest,
- TestLongIdlePeriodDoesNotImmediatelyRestartIfMaxDeadline) {
- ScopedAutoAdvanceNowEnabler advance_now(mock_task_runner_);
-
- std::vector<base::TimeTicks> actual_deadlines;
- int run_count = 0;
-
- base::TimeTicks clock_before(clock_.NowTicks());
- base::TimeDelta idle_task_runtime(base::TimeDelta::FromMilliseconds(10));
-
- // The second idle period should happen immediately after the first the
- // they have max deadlines.
- g_max_idle_task_reposts = 2;
- idle_task_runner_->PostIdleTask(
- FROM_HERE,
- base::BindOnce(&RepostingUpdateClockIdleTestTask,
- base::RetainedRef(idle_task_runner_), &run_count, &clock_,
- idle_task_runtime, &actual_deadlines));
-
- idle_helper_->EnableLongIdlePeriod();
- RunUntilIdle();
- EXPECT_EQ(2, run_count);
- EXPECT_THAT(
- actual_deadlines,
- testing::ElementsAre(clock_before + maximum_idle_period_duration(),
- clock_before + 2 * maximum_idle_period_duration()));
-}
-
-TEST_F(IdleHelperTest, TestLongIdlePeriodRestartWaitsIfNotMaxDeadline) {
- base::TimeTicks actual_deadline;
- int run_count = 0;
-
- base::TimeDelta pending_task_delay(base::TimeDelta::FromMilliseconds(20));
- base::TimeDelta idle_task_duration(base::TimeDelta::FromMilliseconds(10));
- base::TimeTicks expected_deadline(clock_.NowTicks() + pending_task_delay +
- maximum_idle_period_duration() +
- retry_enable_long_idle_period_delay());
-
- // Post delayed task to ensure idle period doesn't have a max deadline.
- default_task_runner_->PostDelayedTask(FROM_HERE, base::BindOnce(&NullTask),
- pending_task_delay);
-
- g_max_idle_task_reposts = 2;
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&RepostingIdleTestTask,
- base::RetainedRef(idle_task_runner_),
- &run_count, &actual_deadline));
- idle_helper_->EnableLongIdlePeriod();
- RunUntilIdle();
- EXPECT_EQ(1, run_count);
- clock_.Advance(idle_task_duration);
-
- // Next idle period shouldn't happen until the pending task has been run.
- RunUntilIdle();
- EXPECT_EQ(1, run_count);
-
- // Once the pending task is run the new idle period should start.
- clock_.Advance(pending_task_delay - idle_task_duration);
-
- // Since the idle period tried to start before the pending task ran we have to
- // wait for the idle helper to retry starting the long idle period.
- clock_.Advance(retry_enable_long_idle_period_delay());
- RunUntilIdle();
-
- EXPECT_EQ(2, run_count);
- EXPECT_EQ(expected_deadline, actual_deadline);
-}
-
-TEST_F(IdleHelperTest, TestLongIdlePeriodPaused) {
- mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
- std::vector<base::TimeTicks> actual_deadlines;
- int run_count = 0;
-
- // If there are no idle tasks posted we should start in the paused state.
- idle_helper_->EnableLongIdlePeriod();
- CheckIdlePeriodStateIs("in_long_idle_period_paused");
- // There shouldn't be any delayed tasks posted by the idle helper when paused.
- base::TimeTicks next_pending_delayed_task;
- EXPECT_FALSE(scheduler_helper_->real_time_domain()->NextScheduledRunTime(
- &next_pending_delayed_task));
-
- // Posting a task should transition us to the an active state.
- g_max_idle_task_reposts = 2;
- base::TimeTicks clock_before(clock_.NowTicks());
- base::TimeDelta idle_task_runtime(base::TimeDelta::FromMilliseconds(10));
- idle_task_runner_->PostIdleTask(
- FROM_HERE,
- base::BindOnce(&RepostingUpdateClockIdleTestTask,
- base::RetainedRef(idle_task_runner_), &run_count, &clock_,
- idle_task_runtime, &actual_deadlines));
- RunUntilIdle();
- EXPECT_EQ(2, run_count);
- EXPECT_THAT(
- actual_deadlines,
- testing::ElementsAre(clock_before + maximum_idle_period_duration(),
- clock_before + 2 * maximum_idle_period_duration()));
-
- // Once all task have been run we should go back to the paused state.
- CheckIdlePeriodStateIs("in_long_idle_period_paused");
- EXPECT_FALSE(scheduler_helper_->real_time_domain()->NextScheduledRunTime(
- &next_pending_delayed_task));
-
- idle_helper_->EndIdlePeriod();
- CheckIdlePeriodStateIs("not_in_idle_period");
-}
-
-TEST_F(IdleHelperTest, TestLongIdlePeriodWhenShutdown) {
- base::TimeTicks deadline_in_task;
- int run_count = 0;
-
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
- idle_helper_->Shutdown();
-
- // We shouldn't be able to enter a long idle period when shutdown
- idle_helper_->EnableLongIdlePeriod();
- RunUntilIdle();
- CheckIdlePeriodStateIs("not_in_idle_period");
- EXPECT_EQ(0, run_count);
-}
-
-void TestCanExceedIdleDeadlineIfRequiredTask(IdleHelperForTest* idle_helper,
- bool* can_exceed_idle_deadline_out,
- int* run_count,
- base::TimeTicks deadline) {
- *can_exceed_idle_deadline_out =
- idle_helper->CanExceedIdleDeadlineIfRequired();
- (*run_count)++;
-}
-
-TEST_F(IdleHelperTest, CanExceedIdleDeadlineIfRequired) {
- int run_count = 0;
- bool can_exceed_idle_deadline = false;
-
- // Should return false if not in an idle period.
- EXPECT_FALSE(idle_helper_->CanExceedIdleDeadlineIfRequired());
-
- // Should return false for short idle periods.
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&TestCanExceedIdleDeadlineIfRequiredTask,
- idle_helper_.get(), &can_exceed_idle_deadline,
- &run_count));
- idle_helper_->StartIdlePeriod(
- IdleHelper::IdlePeriodState::kInShortIdlePeriod, clock_.NowTicks(),
- clock_.NowTicks() + base::TimeDelta::FromMilliseconds(10));
- RunUntilIdle();
- EXPECT_EQ(1, run_count);
- EXPECT_FALSE(can_exceed_idle_deadline);
-
- // Should return false for a long idle period which is shortened due to a
- // pending delayed task.
- default_task_runner_->PostDelayedTask(FROM_HERE, base::BindOnce(&NullTask),
- base::TimeDelta::FromMilliseconds(10));
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&TestCanExceedIdleDeadlineIfRequiredTask,
- idle_helper_.get(), &can_exceed_idle_deadline,
- &run_count));
- idle_helper_->EnableLongIdlePeriod();
- RunUntilIdle();
- EXPECT_EQ(2, run_count);
- EXPECT_FALSE(can_exceed_idle_deadline);
-
- // Next long idle period will be for the maximum time, so
- // CanExceedIdleDeadlineIfRequired should return true.
- clock_.Advance(maximum_idle_period_duration());
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&TestCanExceedIdleDeadlineIfRequiredTask,
- idle_helper_.get(), &can_exceed_idle_deadline,
- &run_count));
- RunUntilIdle();
- EXPECT_EQ(3, run_count);
- EXPECT_TRUE(can_exceed_idle_deadline);
-}
-
-class IdleHelperWithQuiescencePeriodTest : public BaseIdleHelperTest {
- public:
- enum {
- kQuiescenceDelayMs = 100,
- kLongIdlePeriodMs = 50,
- };
-
- IdleHelperWithQuiescencePeriodTest()
- : BaseIdleHelperTest(
- nullptr,
- base::TimeDelta::FromMilliseconds(kQuiescenceDelayMs)) {}
-
- ~IdleHelperWithQuiescencePeriodTest() override = default;
-
- void SetUp() override {
- EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(AnyNumber());
- EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(AnyNumber());
- EXPECT_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _))
- .Times(AnyNumber())
- .WillRepeatedly(Return(true));
- EXPECT_CALL(*idle_helper_, IsNotQuiescent()).Times(AnyNumber());
- }
-
- void MakeNonQuiescent() {
- // Run an arbitrary task so we're deemed to be not quiescent.
- default_task_runner_->PostTask(FROM_HERE, base::BindOnce(NullTask));
- RunUntilIdle();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(IdleHelperWithQuiescencePeriodTest);
-};
-
-class IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver
- : public IdleHelperWithQuiescencePeriodTest {
- public:
- IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver()
- : IdleHelperWithQuiescencePeriodTest() {}
-
- ~IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver() override =
- default;
-
- void SetUp() override {
- // Don't set expectations on IdleHelper::Delegate.
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(
- IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver);
-};
-
-TEST_F(IdleHelperWithQuiescencePeriodTest,
- LongIdlePeriodStartsImmediatelyIfQuiescent) {
- base::TimeTicks actual_deadline;
- int run_count = 0;
- g_max_idle_task_reposts = 1;
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&RepostingIdleTestTask,
- base::RetainedRef(idle_task_runner_),
- &run_count, &actual_deadline));
-
- idle_helper_->EnableLongIdlePeriod();
- RunUntilIdle();
-
- EXPECT_EQ(1, run_count);
-}
-
-TEST_F(IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver,
- LongIdlePeriodDoesNotStartsImmediatelyIfBusy) {
- MakeNonQuiescent();
- EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(0);
- EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(0);
- EXPECT_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _)).Times(0);
- EXPECT_CALL(*idle_helper_, IsNotQuiescent()).Times(AtLeast(1));
-
- base::TimeTicks actual_deadline;
- int run_count = 0;
- g_max_idle_task_reposts = 1;
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&RepostingIdleTestTask,
- base::RetainedRef(idle_task_runner_),
- &run_count, &actual_deadline));
-
- idle_helper_->EnableLongIdlePeriod();
- RunUntilIdle();
-
- EXPECT_EQ(0, run_count);
-
- scheduler_helper_->Shutdown();
-}
-
-TEST_F(IdleHelperWithQuiescencePeriodTest,
- LongIdlePeriodStartsAfterQuiescence) {
- MakeNonQuiescent();
- mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
-
- // Run a repeating task so we're deemed to be busy for the next 400ms.
- default_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&RepeatingTask,
- base::Unretained(default_task_runner_.get()),
- 10, base::TimeDelta::FromMilliseconds(40)));
-
- int run_count = 0;
- // In this scenario EnableLongIdlePeriod deems us not to be quiescent 5x in
- // a row.
- base::TimeTicks expected_deadline =
- clock_.NowTicks() + base::TimeDelta::FromMilliseconds(
- 5 * kQuiescenceDelayMs + kLongIdlePeriodMs);
- base::TimeTicks deadline_in_task;
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
-
- idle_helper_->EnableLongIdlePeriod();
- RunUntilIdle();
- EXPECT_EQ(1, run_count);
- EXPECT_EQ(expected_deadline, deadline_in_task);
-}
-
-TEST_F(IdleHelperWithQuiescencePeriodTest,
- QuescienceCheckedForAfterLongIdlePeriodEnds) {
- mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
-
- idle_task_runner_->PostIdleTask(FROM_HERE, base::BindOnce(&NullIdleTask));
- idle_helper_->EnableLongIdlePeriod();
- RunUntilIdle();
-
- // Post a normal task to make the scheduler non-quiescent.
- default_task_runner_->PostTask(FROM_HERE, base::BindOnce(&NullTask));
- RunUntilIdle();
-
- // Post an idle task. The idle task won't run initially because the system is
- // not judged to be quiescent, but should be run after the quiescence delay.
- int run_count = 0;
- base::TimeTicks deadline_in_task;
- base::TimeTicks expected_deadline =
- clock_.NowTicks() +
- base::TimeDelta::FromMilliseconds(kQuiescenceDelayMs + kLongIdlePeriodMs);
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
- idle_helper_->EnableLongIdlePeriod();
- RunUntilIdle();
-
- EXPECT_EQ(1, run_count);
- EXPECT_EQ(expected_deadline, deadline_in_task);
-}
-
-TEST_F(IdleHelperTest, NoShortIdlePeriodWhenDeadlineTooClose) {
- int run_count = 0;
- base::TimeTicks deadline_in_task;
-
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
-
- base::TimeDelta half_a_ms(base::TimeDelta::FromMicroseconds(50));
- base::TimeTicks less_than_min_deadline(
- clock_.NowTicks() + minimum_idle_period_duration() - half_a_ms);
- base::TimeTicks more_than_min_deadline(
- clock_.NowTicks() + minimum_idle_period_duration() + half_a_ms);
-
- idle_helper_->StartIdlePeriod(IdleHelper::IdlePeriodState::kInShortIdlePeriod,
- clock_.NowTicks(), less_than_min_deadline);
- RunUntilIdle();
- EXPECT_EQ(0, run_count);
-
- idle_helper_->StartIdlePeriod(IdleHelper::IdlePeriodState::kInShortIdlePeriod,
- clock_.NowTicks(), more_than_min_deadline);
- RunUntilIdle();
- EXPECT_EQ(1, run_count);
-}
-
-TEST_F(IdleHelperTest, NoLongIdlePeriodWhenDeadlineTooClose) {
- int run_count = 0;
- base::TimeTicks deadline_in_task;
-
- base::TimeDelta half_a_ms(base::TimeDelta::FromMicroseconds(50));
- base::TimeDelta less_than_min_deadline_duration(
- minimum_idle_period_duration() - half_a_ms);
- base::TimeDelta more_than_min_deadline_duration(
- minimum_idle_period_duration() + half_a_ms);
-
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
- default_task_runner_->PostDelayedTask(FROM_HERE, base::BindOnce(&NullTask),
- less_than_min_deadline_duration);
-
- idle_helper_->EnableLongIdlePeriod();
- RunUntilIdle();
- EXPECT_EQ(0, run_count);
-
- idle_helper_->EndIdlePeriod();
- clock_.Advance(maximum_idle_period_duration());
- RunUntilIdle();
- EXPECT_EQ(0, run_count);
-
- default_task_runner_->PostDelayedTask(FROM_HERE, base::BindOnce(&NullTask),
- more_than_min_deadline_duration);
- idle_helper_->EnableLongIdlePeriod();
- RunUntilIdle();
- EXPECT_EQ(1, run_count);
-}
-
-TEST_F(IdleHelperWithQuiescencePeriodTest,
- PendingEnableLongIdlePeriodNotRunAfterShutdown) {
- MakeNonQuiescent();
-
- bool shutdown_task_run = false;
- int run_count = 0;
- base::TimeTicks deadline_in_task;
- idle_task_runner_->PostIdleTask(
- FROM_HERE,
- base::BindOnce(&ShutdownIdleTask, base::Unretained(idle_helper_.get()),
- &shutdown_task_run));
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
-
- // Delayed call to IdleHelper::EnableLongIdlePeriod enables idle tasks.
- idle_helper_->EnableLongIdlePeriod();
- clock_.Advance(maximum_idle_period_duration() * 2.0);
- mock_task_runner_->RunPendingTasks();
- EXPECT_TRUE(shutdown_task_run);
- EXPECT_EQ(0, run_count);
-
- // Shutdown immediately after idle period started should prevent the idle
- // task from running.
- idle_helper_->Shutdown();
- mock_task_runner_->RunUntilIdle();
- EXPECT_EQ(0, run_count);
-}
-
-TEST_F(IdleHelperTest, TestPostDelayedIdleTask) {
- int run_count = 0;
- base::TimeTicks expected_deadline =
- clock_.NowTicks() + base::TimeDelta::FromMilliseconds(2300);
- base::TimeTicks deadline_in_task;
-
- // Posting a delayed idle task should not post anything on the underlying
- // task queue until the delay is up.
- idle_task_runner_->PostDelayedIdleTask(
- FROM_HERE, base::TimeDelta::FromMilliseconds(200),
- base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
- EXPECT_EQ(0u, idle_queue()->GetNumberOfPendingTasks());
-
- clock_.Advance(base::TimeDelta::FromMilliseconds(100));
-
- // It shouldn't run until the delay is over even though we went idle.
- idle_helper_->StartIdlePeriod(IdleHelper::IdlePeriodState::kInShortIdlePeriod,
- clock_.NowTicks(), expected_deadline);
- EXPECT_EQ(0u, idle_queue()->GetNumberOfPendingTasks());
- RunUntilIdle();
- EXPECT_EQ(0, run_count);
-
- clock_.Advance(base::TimeDelta::FromMilliseconds(100));
- idle_helper_->StartIdlePeriod(IdleHelper::IdlePeriodState::kInShortIdlePeriod,
- clock_.NowTicks(), expected_deadline);
- EXPECT_EQ(1u, idle_queue()->GetNumberOfPendingTasks());
- RunUntilIdle();
-
- EXPECT_EQ(1, run_count);
- EXPECT_EQ(expected_deadline, deadline_in_task);
-}
-
-// Tests that the OnPendingTasksChanged callback is called once when the idle
-// queue becomes non-empty and again when it becomes empty.
-TEST_F(IdleHelperTest, OnPendingTasksChanged) {
- int run_count = 0;
- base::TimeTicks expected_deadline =
- clock_.NowTicks() + base::TimeDelta::FromMilliseconds(2300);
- base::TimeTicks deadline_in_task;
-
- {
- testing::InSequence dummy;
- // This will be called once. I.e when the one and only task is posted.
- EXPECT_CALL(*idle_helper_, OnPendingTasksChanged(true)).Times(1);
- // This will be called once. I.e when the one and only task completes.
- EXPECT_CALL(*idle_helper_, OnPendingTasksChanged(false)).Times(1);
- }
-
- clock_.Advance(base::TimeDelta::FromMilliseconds(100));
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
-
- RunUntilIdle();
- EXPECT_EQ(0, run_count);
-
- idle_helper_->StartIdlePeriod(IdleHelper::IdlePeriodState::kInShortIdlePeriod,
- clock_.NowTicks(), expected_deadline);
- RunUntilIdle();
- EXPECT_EQ(1, run_count);
- EXPECT_EQ(expected_deadline, deadline_in_task);
-}
-
-// Tests that the OnPendingTasksChanged callback is still only called once
-// with false despite there being two idle tasks posted.
-TEST_F(IdleHelperTest, OnPendingTasksChanged_TwoTasksAtTheSameTime) {
- int run_count = 0;
- base::TimeTicks expected_deadline =
- clock_.NowTicks() + base::TimeDelta::FromMilliseconds(2300);
- base::TimeTicks deadline_in_task;
-
- {
- testing::InSequence dummy;
- // This will be called 3 times. I.e when T1 and T2 are posted and when T1
- // completes.
- EXPECT_CALL(*idle_helper_, OnPendingTasksChanged(true)).Times(3);
- // This will be called once. I.e when T2 completes.
- EXPECT_CALL(*idle_helper_, OnPendingTasksChanged(false)).Times(1);
- }
-
- clock_.Advance(base::TimeDelta::FromMilliseconds(100));
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
- idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
-
- RunUntilIdle();
- EXPECT_EQ(0, run_count);
-
- idle_helper_->StartIdlePeriod(IdleHelper::IdlePeriodState::kInShortIdlePeriod,
- clock_.NowTicks(), expected_deadline);
- RunUntilIdle();
- EXPECT_EQ(2, run_count);
- EXPECT_EQ(expected_deadline, deadline_in_task);
-}
-
-} // namespace idle_helper_unittest
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/metrics_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/child/metrics_helper.cc
deleted file mode 100644
index 2cccc61835d..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/metrics_helper.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/child/metrics_helper.h"
-
-#include "third_party/blink/renderer/platform/scheduler/child/process_state.h"
-
-namespace blink {
-namespace scheduler {
-
-namespace {
-
-// Threshold for discarding ultra-long tasks. It is assumed that ultra-long
-// tasks are reporting glitches (e.g. system falling asleep on the middle of the
-// task).
-constexpr base::TimeDelta kLongTaskDiscardingThreshold =
- base::TimeDelta::FromSeconds(30);
-
-} // namespace
-
-MetricsHelper::MetricsHelper(WebThreadType thread_type)
- : thread_type_(thread_type),
- thread_task_duration_reporter_(
- "RendererScheduler.TaskDurationPerThreadType"),
- thread_task_cpu_duration_reporter_(
- "RendererScheduler.TaskCPUDurationPerThreadType"),
- foreground_thread_task_duration_reporter_(
- "RendererScheduler.TaskDurationPerThreadType.Foreground"),
- foreground_thread_task_cpu_duration_reporter_(
- "RendererScheduler.TaskCPUDurationPerThreadType.Foreground"),
- background_thread_task_duration_reporter_(
- "RendererScheduler.TaskDurationPerThreadType.Background"),
- background_thread_task_cpu_duration_reporter_(
- "RendererScheduler.TaskCPUDurationPerThreadType.Background") {}
-
-MetricsHelper::~MetricsHelper() {}
-
-bool MetricsHelper::ShouldDiscardTask(
- base::sequence_manager::TaskQueue* queue,
- const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start_time,
- base::TimeTicks end_time,
- base::Optional<base::TimeDelta> thread_time) {
- // TODO(altimin): Investigate the relationship between thread time and
- // wall time for discarded tasks.
- return end_time - start_time > kLongTaskDiscardingThreshold;
-}
-
-void MetricsHelper::RecordCommonTaskMetrics(
- base::sequence_manager::TaskQueue* queue,
- const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start_time,
- base::TimeTicks end_time,
- base::Optional<base::TimeDelta> thread_time) {
- base::TimeDelta wall_time = end_time - start_time;
-
- thread_task_duration_reporter_.RecordTask(thread_type_, wall_time);
-
- bool backgrounded = internal::ProcessState::Get()->is_process_backgrounded;
-
- if (backgrounded) {
- background_thread_task_duration_reporter_.RecordTask(thread_type_,
- wall_time);
- } else {
- foreground_thread_task_duration_reporter_.RecordTask(thread_type_,
- wall_time);
- }
-
- if (!thread_time)
- return;
- thread_task_cpu_duration_reporter_.RecordTask(thread_type_,
- thread_time.value());
- if (backgrounded) {
- background_thread_task_cpu_duration_reporter_.RecordTask(
- thread_type_, thread_time.value());
- } else {
- foreground_thread_task_cpu_duration_reporter_.RecordTask(
- thread_type_, thread_time.value());
- }
-}
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/metrics_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/child/metrics_helper.h
deleted file mode 100644
index e22f12a07bd..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/metrics_helper.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_METRICS_HELPER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_METRICS_HELPER_H_
-
-#include "base/optional.h"
-#include "base/time/time.h"
-#include "third_party/blink/public/platform/web_thread_type.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter.h"
-
-namespace base {
-namespace sequence_manager {
-class TaskQueue;
-}
-} // namespace base
-
-namespace blink {
-namespace scheduler {
-
-// Helper class to take care of task metrics shared between main thread
-// and worker threads of the renderer process, including per-thread
-// task metrics.
-//
-// Each thread-specific scheduler should have its own subclass of MetricsHelper
-// (MainThreadMetricsHelper, WorkerMetricsHelper, etc) and should call
-// RecordCommonTaskMetrics manually.
-// Note that this is code reuse, not data reuse -- each thread should have its
-// own instantiation of this class.
-class PLATFORM_EXPORT MetricsHelper {
- public:
- explicit MetricsHelper(WebThreadType thread_type);
- ~MetricsHelper();
-
- protected:
- bool ShouldDiscardTask(base::sequence_manager::TaskQueue* queue,
- const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start_time,
- base::TimeTicks end_time,
- base::Optional<base::TimeDelta> thread_time);
-
- // Record task metrics which are shared between threads.
- void RecordCommonTaskMetrics(
- base::sequence_manager::TaskQueue* queue,
- const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start_time,
- base::TimeTicks end_time,
- base::Optional<base::TimeDelta> thread_time);
-
- protected:
- WebThreadType thread_type_;
-
- private:
- TaskDurationMetricReporter<WebThreadType> thread_task_duration_reporter_;
- TaskDurationMetricReporter<WebThreadType> thread_task_cpu_duration_reporter_;
- TaskDurationMetricReporter<WebThreadType>
- foreground_thread_task_duration_reporter_;
- TaskDurationMetricReporter<WebThreadType>
- foreground_thread_task_cpu_duration_reporter_;
- TaskDurationMetricReporter<WebThreadType>
- background_thread_task_duration_reporter_;
- TaskDurationMetricReporter<WebThreadType>
- background_thread_task_cpu_duration_reporter_;
-
- DISALLOW_COPY_AND_ASSIGN(MetricsHelper);
-};
-
-} // namespace scheduler
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_METRICS_HELPER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/metrics_helper_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/child/metrics_helper_unittest.cc
deleted file mode 100644
index a1d54dc539c..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/metrics_helper_unittest.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/child/metrics_helper.h"
-#include "base/test/histogram_tester.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::sequence_manager::TaskQueue;
-
-namespace blink {
-namespace scheduler {
-
-namespace {
-
-class MetricsHelperForTest : public MetricsHelper {
- public:
- MetricsHelperForTest(WebThreadType thread_type)
- : MetricsHelper(thread_type) {}
- ~MetricsHelperForTest() = default;
-
- using MetricsHelper::RecordCommonTaskMetrics;
-};
-
-} // namespace
-
-TEST(MetricsHelperTest, TaskDurationPerThreadType) {
- base::HistogramTester histogram_tester;
-
- MetricsHelperForTest main_thread_metrics(WebThreadType::kMainThread);
- MetricsHelperForTest compositor_metrics(WebThreadType::kCompositorThread);
- MetricsHelperForTest worker_metrics(WebThreadType::kUnspecifiedWorkerThread);
-
- TaskQueue::Task fake_task(
- (TaskQueue::PostedTask(base::OnceClosure(), base::Location())),
- base::TimeTicks());
-
- main_thread_metrics.RecordCommonTaskMetrics(
- nullptr, fake_task,
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(10),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(50),
- base::TimeDelta::FromMilliseconds(15));
- compositor_metrics.RecordCommonTaskMetrics(
- nullptr, fake_task,
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(10),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(80),
- base::TimeDelta::FromMilliseconds(5));
- compositor_metrics.RecordCommonTaskMetrics(
- nullptr, fake_task,
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(100),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(200),
- base::nullopt);
- worker_metrics.RecordCommonTaskMetrics(
- nullptr, fake_task,
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(10),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(125),
- base::TimeDelta::FromMilliseconds(25));
-
- EXPECT_THAT(
- histogram_tester.GetAllSamples(
- "RendererScheduler.TaskDurationPerThreadType"),
- testing::UnorderedElementsAre(
- base::Bucket(static_cast<int>(WebThreadType::kMainThread), 40),
- base::Bucket(static_cast<int>(WebThreadType::kCompositorThread), 170),
- base::Bucket(
- static_cast<int>(WebThreadType::kUnspecifiedWorkerThread), 115)));
-
- EXPECT_THAT(
- histogram_tester.GetAllSamples(
- "RendererScheduler.TaskCPUDurationPerThreadType"),
- testing::UnorderedElementsAre(
- base::Bucket(static_cast<int>(WebThreadType::kMainThread), 15),
- base::Bucket(static_cast<int>(WebThreadType::kCompositorThread), 5),
- base::Bucket(
- static_cast<int>(WebThreadType::kUnspecifiedWorkerThread), 25)));
-}
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/page_visibility_state.cc b/chromium/third_party/blink/renderer/platform/scheduler/child/page_visibility_state.cc
deleted file mode 100644
index af00b25482d..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/page_visibility_state.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/child/page_visibility_state.h"
-
-namespace blink {
-namespace scheduler {
-
-const char* PageVisibilityStateToString(PageVisibilityState visibility) {
- switch (visibility) {
- case PageVisibilityState::kVisible:
- return "visible";
- case PageVisibilityState::kHidden:
- return "hidden";
- }
- // Keep MSVC happy.
- return nullptr;
-}
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/page_visibility_state.h b/chromium/third_party/blink/renderer/platform/scheduler/child/page_visibility_state.h
deleted file mode 100644
index 11b6fe8bc6e..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/page_visibility_state.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_PAGE_VISIBILITY_STATE_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_PAGE_VISIBILITY_STATE_H_
-
-namespace blink {
-namespace scheduler {
-
-// TODO(altimin): Move to core/.
-enum class PageVisibilityState { kVisible, kHidden };
-
-const char* PageVisibilityStateToString(PageVisibilityState visibility);
-
-} // namespace scheduler
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_PAGE_VISIBILITY_STATE_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.cc b/chromium/third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.cc
index 409682767e7..8e672dcb97d 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.cc
@@ -8,7 +8,7 @@
#include "base/bind.h"
#include "base/location.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "base/task/sequence_manager/task_queue.h"
namespace blink {
namespace scheduler {
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/webthread_base.cc b/chromium/third_party/blink/renderer/platform/scheduler/child/webthread_base.cc
index 8b0a45fa229..2a9efbd4d75 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/webthread_base.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/child/webthread_base.cc
@@ -15,7 +15,6 @@
#include "base/message_loop/message_loop_current.h"
#include "base/pending_task.h"
#include "base/threading/platform_thread.h"
-#include "third_party/blink/public/platform/scheduler/single_thread_idle_task_runner.h"
#include "third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/utility/webthread_impl_for_utility_thread.h"
#include "third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h"
@@ -88,19 +87,6 @@ void WebThreadBase::RemoveTaskObserverInternal(
base::MessageLoopCurrent::Get()->RemoveTaskObserver(observer);
}
-// static
-void WebThreadBase::RunWebThreadIdleTask(blink::WebThread::IdleTask idle_task,
- base::TimeTicks deadline) {
- std::move(idle_task).Run((deadline - base::TimeTicks()).InSecondsF());
-}
-
-void WebThreadBase::PostIdleTask(const base::Location& location,
- IdleTask idle_task) {
- GetIdleTaskRunner()->PostIdleTask(
- location, base::BindOnce(&WebThreadBase::RunWebThreadIdleTask,
- std::move(idle_task)));
-}
-
bool WebThreadBase::IsCurrentThread() const {
return GetTaskRunner()->BelongsToCurrentThread();
}
@@ -117,11 +103,10 @@ class WebThreadForCompositor : public WebThreadImplForWorkerScheduler {
private:
// WebThreadImplForWorkerScheduler:
- std::unique_ptr<blink::scheduler::NonMainThreadScheduler>
+ std::unique_ptr<blink::scheduler::NonMainThreadSchedulerImpl>
CreateNonMainThreadScheduler() override {
return std::make_unique<CompositorThreadScheduler>(
- GetThread(),
- base::sequence_manager::TaskQueueManager::TakeOverCurrentThread());
+ base::sequence_manager::CreateSequenceManagerOnCurrentThread());
}
DISALLOW_COPY_AND_ASSIGN(WebThreadForCompositor);
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc
index 55583882fcd..7c9a23d8794 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc
@@ -9,11 +9,11 @@
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/sequence_manager/task_queue.h"
#include "base/time/default_tick_clock.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
#include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
-#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h"
#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
namespace blink {
@@ -23,10 +23,10 @@ WebThreadImplForWorkerScheduler::WebThreadImplForWorkerScheduler(
const WebThreadCreationParams& params)
: thread_(new base::Thread(params.name ? params.name : std::string())),
thread_type_(params.thread_type),
- worker_scheduler_proxy_(
- params.frame_scheduler
- ? std::make_unique<WorkerSchedulerProxy>(params.frame_scheduler)
- : nullptr) {
+ worker_scheduler_proxy_(params.frame_or_worker_scheduler
+ ? std::make_unique<WorkerSchedulerProxy>(
+ params.frame_or_worker_scheduler)
+ : nullptr) {
bool started = thread_->StartWithOptions(params.thread_options);
CHECK(started);
thread_task_runner_ = thread_->task_runner();
@@ -67,7 +67,6 @@ void WebThreadImplForWorkerScheduler::InitOnThread(
task_queue_ = non_main_thread_scheduler_->DefaultTaskQueue();
task_runner_ = TaskQueueWithTaskType::Create(
task_queue_, TaskType::kWorkerThreadTaskQueueDefault);
- idle_task_runner_ = non_main_thread_scheduler_->IdleTaskRunner();
base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
completion->Signal();
}
@@ -78,17 +77,16 @@ void WebThreadImplForWorkerScheduler::ShutdownOnThread(
task_queue_ = nullptr;
task_runner_ = nullptr;
- idle_task_runner_ = nullptr;
non_main_thread_scheduler_ = nullptr;
if (completion)
completion->Signal();
}
-std::unique_ptr<NonMainThreadScheduler>
+std::unique_ptr<NonMainThreadSchedulerImpl>
WebThreadImplForWorkerScheduler::CreateNonMainThreadScheduler() {
- return NonMainThreadScheduler::Create(thread_type_,
- worker_scheduler_proxy_.get());
+ return NonMainThreadSchedulerImpl::Create(thread_type_,
+ worker_scheduler_proxy_.get());
}
void WebThreadImplForWorkerScheduler::WillDestroyCurrentMessageLoop() {
@@ -103,11 +101,6 @@ blink::ThreadScheduler* WebThreadImplForWorkerScheduler::Scheduler() const {
return non_main_thread_scheduler_.get();
}
-SingleThreadIdleTaskRunner* WebThreadImplForWorkerScheduler::GetIdleTaskRunner()
- const {
- return idle_task_runner_.get();
-}
-
scoped_refptr<base::SingleThreadTaskRunner>
WebThreadImplForWorkerScheduler::GetTaskRunner() const {
return task_runner_;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.h
index e68d0a8e68b..59a9fcdb7eb 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.h
@@ -27,8 +27,7 @@ class ThreadScheduler;
namespace blink {
namespace scheduler {
-class SingleThreadIdleTaskRunner;
-class NonMainThreadScheduler;
+class NonMainThreadSchedulerImpl;
class WorkerSchedulerProxy;
class PLATFORM_EXPORT WebThreadImplForWorkerScheduler
@@ -45,25 +44,27 @@ class PLATFORM_EXPORT WebThreadImplForWorkerScheduler
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() const override;
// WebThreadBase implementation.
- scheduler::SingleThreadIdleTaskRunner* GetIdleTaskRunner() const override;
void Init() override;
// base::MessageLoopCurrent::DestructionObserver implementation.
void WillDestroyCurrentMessageLoop() override;
- scheduler::NonMainThreadScheduler* GetNonMainThreadScheduler() {
+ scheduler::NonMainThreadSchedulerImpl* GetNonMainThreadScheduler() {
return non_main_thread_scheduler_.get();
}
+ scheduler::WorkerSchedulerProxy* worker_scheduler_proxy() const {
+ return worker_scheduler_proxy_.get();
+ }
+
protected:
- virtual std::unique_ptr<NonMainThreadScheduler>
+ virtual std::unique_ptr<NonMainThreadSchedulerImpl>
CreateNonMainThreadScheduler();
base::Thread* GetThread() const { return thread_.get(); }
- scheduler::WorkerSchedulerProxy* worker_scheduler_proxy() const {
- return worker_scheduler_proxy_.get();
- }
+ // protected instead of private for unit tests.
+ scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner_;
private:
void AddTaskObserverInternal(
@@ -77,11 +78,10 @@ class PLATFORM_EXPORT WebThreadImplForWorkerScheduler
std::unique_ptr<base::Thread> thread_;
const WebThreadType thread_type_;
std::unique_ptr<scheduler::WorkerSchedulerProxy> worker_scheduler_proxy_;
- std::unique_ptr<scheduler::NonMainThreadScheduler> non_main_thread_scheduler_;
- scoped_refptr<base::SingleThreadTaskRunner> thread_task_runner_;
+ std::unique_ptr<scheduler::NonMainThreadSchedulerImpl>
+ non_main_thread_scheduler_;
scoped_refptr<base::sequence_manager::TaskQueue> task_queue_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- scoped_refptr<scheduler::SingleThreadIdleTaskRunner> idle_task_runner_;
base::AtomicFlag was_shutdown_on_thread_;
};
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc
index cc1dad6ce5b..17fb0e1123b 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler_unittest.cc
@@ -136,27 +136,6 @@ TEST_F(WebThreadImplForWorkerSchedulerTest,
thread_.reset();
}
-TEST_F(WebThreadImplForWorkerSchedulerTest, TestIdleTask) {
- MockIdleTask task;
- base::WaitableEvent completion(
- base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
-
- EXPECT_CALL(task, Run(_));
- ON_CALL(task, Run(_)).WillByDefault(Invoke([&completion](double) {
- completion.Signal();
- }));
-
- thread_->PostIdleTask(
- FROM_HERE, base::BindOnce(&MockIdleTask::Run, WTF::Unretained(&task)));
- // We need to post a wake-up task or idle work will never happen.
- PostDelayedCrossThreadTask(*thread_->GetTaskRunner(), FROM_HERE,
- CrossThreadBind([] {}),
- TimeDelta::FromMilliseconds(50));
-
- completion.Wait();
-}
-
TEST_F(WebThreadImplForWorkerSchedulerTest, TestTaskObserver) {
std::string calls;
TestObserver observer(&calls);
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_metrics_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/child/worker_metrics_helper.cc
deleted file mode 100644
index 577c6287ef8..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_metrics_helper.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/child/worker_metrics_helper.h"
-
-#include "third_party/blink/renderer/platform/scheduler/child/process_state.h"
-
-namespace blink {
-namespace scheduler {
-
-WorkerMetricsHelper::WorkerMetricsHelper(WebThreadType thread_type)
- : MetricsHelper(thread_type),
- dedicated_worker_per_task_type_duration_reporter_(
- "RendererScheduler.TaskDurationPerTaskType.DedicatedWorker"),
- dedicated_worker_per_task_type_cpu_duration_reporter_(
- "RendererScheduler.TaskCPUDurationPerTaskType.DedicatedWorker"),
- dedicated_worker_per_parent_frame_status_duration_reporter_(
- "RendererScheduler.TaskDurationPerFrameOriginType.DedicatedWorker"),
- background_dedicated_worker_per_parent_frame_status_duration_reporter_(
- "RendererScheduler.TaskDurationPerFrameOriginType.DedicatedWorker."
- "Background") {}
-
-WorkerMetricsHelper::~WorkerMetricsHelper() {}
-
-void WorkerMetricsHelper::SetParentFrameType(FrameOriginType frame_type) {
- parent_frame_type_ = frame_type;
-}
-
-void WorkerMetricsHelper::RecordTaskMetrics(
- WorkerTaskQueue* queue,
- const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start_time,
- base::TimeTicks end_time,
- base::Optional<base::TimeDelta> thread_time) {
- if (ShouldDiscardTask(queue, task, start_time, end_time, thread_time))
- return;
-
- MetricsHelper::RecordCommonTaskMetrics(queue, task, start_time, end_time,
- thread_time);
-
- bool backgrounded = internal::ProcessState::Get()->is_process_backgrounded;
-
- if (thread_type_ == WebThreadType::kDedicatedWorkerThread) {
- TaskType task_type = static_cast<TaskType>(task.task_type());
- dedicated_worker_per_task_type_duration_reporter_.RecordTask(
- task_type, end_time - start_time);
- if (thread_time) {
- dedicated_worker_per_task_type_cpu_duration_reporter_.RecordTask(
- task_type, thread_time.value());
- }
-
- if (parent_frame_type_) {
- dedicated_worker_per_parent_frame_status_duration_reporter_.RecordTask(
- parent_frame_type_.value(), end_time - start_time);
-
- if (backgrounded) {
- background_dedicated_worker_per_parent_frame_status_duration_reporter_
- .RecordTask(parent_frame_type_.value(), end_time - start_time);
- }
- }
- }
-}
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_metrics_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/child/worker_metrics_helper.h
deleted file mode 100644
index 5b1cd7319d5..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_metrics_helper.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_WORKER_METRICS_HELPER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_WORKER_METRICS_HELPER_H_
-
-#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/platform/scheduler/child/metrics_helper.h"
-#include "third_party/blink/renderer/platform/scheduler/child/worker_task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h"
-#include "third_party/blink/renderer/platform/scheduler/util/thread_load_tracker.h"
-
-namespace blink {
-namespace scheduler {
-
-class PLATFORM_EXPORT WorkerMetricsHelper : public MetricsHelper {
- public:
- explicit WorkerMetricsHelper(WebThreadType thread_type);
- ~WorkerMetricsHelper();
-
- void RecordTaskMetrics(WorkerTaskQueue* queue,
- const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start_time,
- base::TimeTicks end_time,
- base::Optional<base::TimeDelta> thread_time);
-
- void SetParentFrameType(FrameOriginType frame_type);
-
- private:
- TaskDurationMetricReporter<TaskType>
- dedicated_worker_per_task_type_duration_reporter_;
- TaskDurationMetricReporter<TaskType>
- dedicated_worker_per_task_type_cpu_duration_reporter_;
- TaskDurationMetricReporter<FrameOriginType>
- dedicated_worker_per_parent_frame_status_duration_reporter_;
- TaskDurationMetricReporter<FrameOriginType>
- background_dedicated_worker_per_parent_frame_status_duration_reporter_;
-
- base::Optional<FrameOriginType> parent_frame_type_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerMetricsHelper);
-};
-
-} // namespace scheduler
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_WORKER_METRICS_HELPER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler.cc
deleted file mode 100644
index 158609a9da6..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler.cc
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler.h"
-
-#include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
-#include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
-#include "third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h"
-#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread_scheduler.h"
-
-namespace blink {
-namespace scheduler {
-
-WorkerScheduler::WorkerScheduler(
- NonMainThreadScheduler* non_main_thread_scheduler)
- : default_task_queue_(non_main_thread_scheduler->CreateTaskRunner()),
- throttleable_task_queue_(non_main_thread_scheduler->CreateTaskRunner()),
- thread_scheduler_(non_main_thread_scheduler) {
- thread_scheduler_->RegisterWorkerScheduler(this);
- if (WakeUpBudgetPool* wake_up_budget_pool =
- thread_scheduler_->wake_up_budget_pool()) {
- wake_up_budget_pool->AddQueue(thread_scheduler_->GetTickClock()->NowTicks(),
- throttleable_task_queue_.get());
- }
-}
-
-WorkerScheduler::~WorkerScheduler() {
-#if DCHECK_IS_ON()
- DCHECK(is_disposed_);
-#endif
-}
-
-std::unique_ptr<FrameOrWorkerScheduler::ActiveConnectionHandle>
-WorkerScheduler::OnActiveConnectionCreated() {
- return nullptr;
-}
-
-void WorkerScheduler::Dispose() {
- if (TaskQueueThrottler* throttler =
- thread_scheduler_->task_queue_throttler()) {
- throttler->ShutdownTaskQueue(throttleable_task_queue_.get());
- }
-
- thread_scheduler_->UnregisterWorkerScheduler(this);
-
- default_task_queue_->ShutdownTaskQueue();
- throttleable_task_queue_->ShutdownTaskQueue();
-
-#if DCHECK_IS_ON()
- is_disposed_ = true;
-#endif
-}
-
-scoped_refptr<base::SingleThreadTaskRunner> WorkerScheduler::GetTaskRunner(
- TaskType type) const {
- switch (type) {
- case TaskType::kJavascriptTimer:
- case TaskType::kPostedMessage:
- return TaskQueueWithTaskType::Create(throttleable_task_queue_, type);
- case TaskType::kDeprecatedNone:
- case TaskType::kDOMManipulation:
- case TaskType::kUserInteraction:
- case TaskType::kNetworking:
- case TaskType::kNetworkingControl:
- case TaskType::kHistoryTraversal:
- case TaskType::kEmbed:
- case TaskType::kMediaElementEvent:
- case TaskType::kCanvasBlobSerialization:
- case TaskType::kMicrotask:
- case TaskType::kRemoteEvent:
- case TaskType::kWebSocket:
- case TaskType::kUnshippedPortMessage:
- case TaskType::kFileReading:
- case TaskType::kDatabaseAccess:
- case TaskType::kPresentation:
- case TaskType::kSensor:
- case TaskType::kPerformanceTimeline:
- case TaskType::kWebGL:
- case TaskType::kIdleTask:
- case TaskType::kMiscPlatformAPI:
- case TaskType::kInternalDefault:
- case TaskType::kInternalLoading:
- case TaskType::kUnthrottled:
- case TaskType::kInternalTest:
- case TaskType::kInternalWebCrypto:
- case TaskType::kInternalIndexedDB:
- case TaskType::kInternalMedia:
- case TaskType::kInternalMediaRealTime:
- case TaskType::kInternalIPC:
- case TaskType::kInternalUserInteraction:
- case TaskType::kInternalInspector:
- case TaskType::kInternalWorker:
- case TaskType::kInternalIntersectionObserver:
- // UnthrottledTaskRunner is generally discouraged in future.
- // TODO(nhiroki): Identify which tasks can be throttled / suspendable and
- // move them into other task runners. See also comments in
- // Get(LocalFrame). (https://crbug.com/670534)
- return TaskQueueWithTaskType::Create(default_task_queue_, type);
- case TaskType::kMainThreadTaskQueueV8:
- case TaskType::kMainThreadTaskQueueCompositor:
- case TaskType::kMainThreadTaskQueueDefault:
- case TaskType::kMainThreadTaskQueueInput:
- case TaskType::kMainThreadTaskQueueIdle:
- case TaskType::kMainThreadTaskQueueIPC:
- case TaskType::kMainThreadTaskQueueControl:
- case TaskType::kCompositorThreadTaskQueueDefault:
- case TaskType::kWorkerThreadTaskQueueDefault:
- case TaskType::kCount:
- NOTREACHED();
- break;
- }
- NOTREACHED();
- return nullptr;
-}
-
-void WorkerScheduler::OnThrottlingStateChanged(
- FrameScheduler::ThrottlingState throttling_state) {
- if (throttling_state_ == throttling_state)
- return;
- throttling_state_ = throttling_state;
-
- if (TaskQueueThrottler* throttler =
- thread_scheduler_->task_queue_throttler()) {
- if (throttling_state_ == FrameScheduler::ThrottlingState::kThrottled) {
- throttler->IncreaseThrottleRefCount(throttleable_task_queue_.get());
- } else {
- throttler->DecreaseThrottleRefCount(throttleable_task_queue_.get());
- }
- }
-}
-
-scoped_refptr<base::sequence_manager::TaskQueue>
-WorkerScheduler::DefaultTaskQueue() {
- return default_task_queue_.get();
-}
-
-scoped_refptr<base::sequence_manager::TaskQueue>
-WorkerScheduler::ThrottleableTaskQueue() {
- return throttleable_task_queue_.get();
-}
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler.h
deleted file mode 100644
index 93e9ae6db2d..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_WORKER_SCHEDULER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_WORKER_SCHEDULER_H_
-
-#include "base/single_thread_task_runner.h"
-#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h"
-#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
-
-namespace blink {
-
-namespace scheduler {
-
-class NonMainThreadScheduler;
-
-// A scheduler provides per-global-scope task queues. This is constructed when a
-// global scope is created and destructed when it's closed.
-//
-// Unless stated otherwise, all methods must be called on the worker thread.
-class PLATFORM_EXPORT WorkerScheduler : public FrameOrWorkerScheduler {
- public:
- explicit WorkerScheduler(NonMainThreadScheduler* non_main_thread_scheduler);
- ~WorkerScheduler() override;
-
- std::unique_ptr<ActiveConnectionHandle> OnActiveConnectionCreated() override;
-
- // Unregisters the task queues and cancels tasks in them.
- void Dispose();
-
- // Returns a task runner that is suitable with the given task type. This can
- // be called from any thread.
- //
- // This must be called only from WorkerThread::GetTaskRunner().
- scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) const;
-
- void OnThrottlingStateChanged(
- FrameScheduler::ThrottlingState throtting_state);
-
- protected:
- scoped_refptr<base::sequence_manager::TaskQueue> DefaultTaskQueue();
- scoped_refptr<base::sequence_manager::TaskQueue> ThrottleableTaskQueue();
-
- private:
- scoped_refptr<base::sequence_manager::TaskQueue> default_task_queue_;
- scoped_refptr<base::sequence_manager::TaskQueue> throttleable_task_queue_;
-
- FrameScheduler::ThrottlingState throttling_state_ =
- FrameScheduler::ThrottlingState::kNotThrottled;
-
- NonMainThreadScheduler* thread_scheduler_; // NOT OWNED
-
-#if DCHECK_IS_ON()
- bool is_disposed_ = false;
-#endif
-};
-
-} // namespace scheduler
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_WORKER_SCHEDULER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy.cc b/chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy.cc
deleted file mode 100644
index 0bdfdf5a4fb..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy.h"
-
-#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
-
-namespace blink {
-namespace scheduler {
-
-WorkerSchedulerProxy::WorkerSchedulerProxy(FrameScheduler* frame_scheduler) {
- throttling_observer_handle_ = frame_scheduler->AddThrottlingObserver(
- FrameScheduler::ObserverType::kWorkerScheduler, this);
- parent_frame_type_ = GetFrameOriginType(frame_scheduler);
-}
-
-WorkerSchedulerProxy::~WorkerSchedulerProxy() {
- DCHECK(IsMainThread());
-}
-
-void WorkerSchedulerProxy::OnWorkerSchedulerCreated(
- base::WeakPtr<WorkerThreadScheduler> worker_scheduler) {
- DCHECK(!IsMainThread())
- << "OnWorkerSchedulerCreated should be called from the worker thread";
- DCHECK(!worker_scheduler_) << "OnWorkerSchedulerCreated is called twice";
- DCHECK(worker_scheduler) << "WorkerScheduler is expected to exist";
- worker_scheduler_ = std::move(worker_scheduler);
- worker_thread_task_runner_ = worker_scheduler_->ControlTaskQueue();
- initialized_ = true;
-}
-
-void WorkerSchedulerProxy::OnThrottlingStateChanged(
- FrameScheduler::ThrottlingState throttling_state) {
- DCHECK(IsMainThread());
- if (throttling_state_ == throttling_state)
- return;
- throttling_state_ = throttling_state;
-
- if (!initialized_)
- return;
-
- worker_thread_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&WorkerThreadScheduler::OnThrottlingStateChanged,
- worker_scheduler_, throttling_state));
-}
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy.h b/chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy.h
deleted file mode 100644
index 4188c5b474f..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_WORKER_SCHEDULER_PROXY_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_WORKER_SCHEDULER_PROXY_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/single_thread_task_runner.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/child/page_visibility_state.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h"
-#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
-#include "third_party/blink/renderer/platform/wtf/wtf.h"
-
-namespace blink {
-namespace scheduler {
-class WorkerThreadScheduler;
-
-// Helper class for communication between frame scheduler (main thread) and
-// worker scheduler (worker thread).
-//
-// It's owned by DedicatedWorkerThread and is created and destroyed
-// on the main thread. It's passed to WorkerScheduler during its construction.
-// Given that DedicatedWorkerThread object outlives worker thread, this class
-// outlives worker thread too.
-class PLATFORM_EXPORT WorkerSchedulerProxy : public FrameScheduler::Observer {
- public:
- explicit WorkerSchedulerProxy(FrameScheduler* scheduler);
- ~WorkerSchedulerProxy() override;
-
- void OnWorkerSchedulerCreated(
- base::WeakPtr<WorkerThreadScheduler> worker_scheduler);
-
- void OnThrottlingStateChanged(
- FrameScheduler::ThrottlingState throttling_state) override;
-
- // Should be accessed only from the main thread or during init.
- FrameScheduler::ThrottlingState throttling_state() const {
- DCHECK(IsMainThread() || !initialized_);
- return throttling_state_;
- }
-
- FrameOriginType parent_frame_type() const {
- DCHECK(IsMainThread() || !initialized_);
- return parent_frame_type_;
- }
-
- private:
- // Can be accessed only from the worker thread.
- base::WeakPtr<WorkerThreadScheduler> worker_scheduler_;
-
- // Const after init on the worker thread.
- scoped_refptr<base::SingleThreadTaskRunner> worker_thread_task_runner_;
-
- FrameScheduler::ThrottlingState throttling_state_ =
- FrameScheduler::ThrottlingState::kNotThrottled;
-
- std::unique_ptr<FrameScheduler::ThrottlingObserverHandle>
- throttling_observer_handle_;
-
- bool initialized_ = false;
-
- FrameOriginType parent_frame_type_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerSchedulerProxy);
-};
-
-} // namespace scheduler
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_WORKER_SCHEDULER_PROXY_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy_unittest.cc
deleted file mode 100644
index f556eab34e7..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy_unittest.cc
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy.h"
-#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
-#include "third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
-#include "third_party/blink/renderer/platform/waitable_event.h"
-
-namespace blink {
-namespace scheduler {
-
-namespace {
-
-class WorkerThreadSchedulerForTest : public WorkerThreadScheduler {
- public:
- WorkerThreadSchedulerForTest(
- std::unique_ptr<base::sequence_manager::TaskQueueManager> manager,
- WorkerSchedulerProxy* proxy,
- WaitableEvent* throtting_state_changed)
- : WorkerThreadScheduler(WebThreadType::kTestThread,
- std::move(manager),
- proxy),
- throtting_state_changed_(throtting_state_changed) {}
-
- void OnThrottlingStateChanged(
- FrameScheduler::ThrottlingState throttling_state) override {
- WorkerThreadScheduler::OnThrottlingStateChanged(throttling_state);
-
- throtting_state_changed_->Signal();
- }
-
- using WorkerThreadScheduler::throttling_state;
-
- private:
- WaitableEvent* throtting_state_changed_;
-};
-
-class WebThreadImplForWorkerSchedulerForTest
- : public WebThreadImplForWorkerScheduler {
- public:
- WebThreadImplForWorkerSchedulerForTest(FrameScheduler* frame_scheduler,
- WaitableEvent* throtting_state_changed)
- : WebThreadImplForWorkerScheduler(
- WebThreadCreationParams(WebThreadType::kTestThread)
- .SetFrameScheduler(frame_scheduler)),
- throtting_state_changed_(throtting_state_changed) {}
-
- std::unique_ptr<NonMainThreadScheduler> CreateNonMainThreadScheduler()
- override {
- auto scheduler = std::make_unique<WorkerThreadSchedulerForTest>(
- base::sequence_manager::TaskQueueManager::TakeOverCurrentThread(),
- worker_scheduler_proxy(), throtting_state_changed_);
- scheduler_ = scheduler.get();
- return scheduler;
- }
-
- WorkerThreadSchedulerForTest* GetWorkerScheduler() { return scheduler_; }
-
- private:
- WaitableEvent* throtting_state_changed_; // NOT OWNED
- WorkerThreadSchedulerForTest* scheduler_ = nullptr; // NOT OWNED
-};
-
-std::unique_ptr<WebThreadImplForWorkerSchedulerForTest> CreateWorkerThread(
- FrameScheduler* frame_scheduler,
- WaitableEvent* throtting_state_changed) {
- std::unique_ptr<WebThreadImplForWorkerSchedulerForTest> thread =
- std::make_unique<WebThreadImplForWorkerSchedulerForTest>(
- frame_scheduler, throtting_state_changed);
- thread->Init();
- return thread;
-}
-
-} // namespace
-
-class WorkerSchedulerProxyTest : public testing::Test {
- public:
- WorkerSchedulerProxyTest()
- : task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
- base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED),
- main_thread_scheduler_(std::make_unique<MainThreadSchedulerImpl>(
- base::sequence_manager::TaskQueueManagerForTest::Create(
- nullptr,
- base::ThreadTaskRunnerHandle::Get(),
- task_environment_.GetMockTickClock()),
- base::nullopt)),
- page_scheduler_(
- std::make_unique<PageSchedulerImpl>(nullptr,
- main_thread_scheduler_.get(),
- false)),
- frame_scheduler_(page_scheduler_->CreateFrameSchedulerImpl(
- nullptr,
- FrameScheduler::FrameType::kMainFrame)) {
- // Null clock triggers some assertions.
- task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(5));
- }
-
- ~WorkerSchedulerProxyTest() override {
- frame_scheduler_.reset();
- page_scheduler_.reset();
- main_thread_scheduler_->Shutdown();
- }
-
- protected:
- base::test::ScopedTaskEnvironment task_environment_;
- std::unique_ptr<MainThreadSchedulerImpl> main_thread_scheduler_;
- std::unique_ptr<PageSchedulerImpl> page_scheduler_;
- std::unique_ptr<FrameSchedulerImpl> frame_scheduler_;
-};
-
-TEST_F(WorkerSchedulerProxyTest, VisibilitySignalReceived) {
- WaitableEvent throtting_state_changed;
-
- auto worker_thread =
- CreateWorkerThread(frame_scheduler_.get(), &throtting_state_changed);
-
- DCHECK(worker_thread->GetWorkerScheduler()->throttling_state() ==
- FrameScheduler::ThrottlingState::kNotThrottled);
-
- page_scheduler_->SetPageVisible(false);
- throtting_state_changed.Wait();
- DCHECK(worker_thread->GetWorkerScheduler()->throttling_state() ==
- FrameScheduler::ThrottlingState::kHidden);
-
- // Trigger full throttling.
- task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(30));
- throtting_state_changed.Wait();
- DCHECK(worker_thread->GetWorkerScheduler()->throttling_state() ==
- FrameScheduler::ThrottlingState::kThrottled);
-
- page_scheduler_->SetPageVisible(true);
- throtting_state_changed.Wait();
- DCHECK(worker_thread->GetWorkerScheduler()->throttling_state() ==
- FrameScheduler::ThrottlingState::kNotThrottled);
-
- base::RunLoop().RunUntilIdle();
-}
-
-// Tests below check that no crashes occur during different shutdown sequences.
-
-TEST_F(WorkerSchedulerProxyTest, FrameSchedulerDestroyed) {
- WaitableEvent throtting_state_changed;
-
- auto worker_thread =
- CreateWorkerThread(frame_scheduler_.get(), &throtting_state_changed);
-
- DCHECK(worker_thread->GetWorkerScheduler()->throttling_state() ==
- FrameScheduler::ThrottlingState::kNotThrottled);
-
- page_scheduler_->SetPageVisible(false);
- throtting_state_changed.Wait();
- DCHECK(worker_thread->GetWorkerScheduler()->throttling_state() ==
- FrameScheduler::ThrottlingState::kHidden);
-
- frame_scheduler_.reset();
- base::RunLoop().RunUntilIdle();
-
- worker_thread.reset();
- base::RunLoop().RunUntilIdle();
-}
-
-TEST_F(WorkerSchedulerProxyTest, ThreadDestroyed) {
- WaitableEvent throtting_state_changed;
-
- auto worker_thread =
- CreateWorkerThread(frame_scheduler_.get(), &throtting_state_changed);
-
- DCHECK(worker_thread->GetWorkerScheduler()->throttling_state() ==
- FrameScheduler::ThrottlingState::kNotThrottled);
-
- page_scheduler_->SetPageVisible(false);
- throtting_state_changed.Wait();
- DCHECK(worker_thread->GetWorkerScheduler()->throttling_state() ==
- FrameScheduler::ThrottlingState::kHidden);
-
- worker_thread.reset();
- base::RunLoop().RunUntilIdle();
-
- page_scheduler_->SetPageVisible(true);
- base::RunLoop().RunUntilIdle();
-
- frame_scheduler_.reset();
- base::RunLoop().RunUntilIdle();
-}
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler_unittest.cc
deleted file mode 100644
index f439a1fe492..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_scheduler_unittest.cc
+++ /dev/null
@@ -1,241 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler.h"
-
-#include <memory>
-#include "base/macros.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "base/test/test_mock_time_task_runner.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
-#include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
-#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
-#include "third_party/blink/renderer/platform/wtf/functional.h"
-
-using testing::ElementsAreArray;
-using testing::ElementsAre;
-
-namespace blink {
-namespace scheduler {
-// To avoid symbol collisions in jumbo builds.
-namespace worker_scheduler_unittest {
-
-void AppendToVectorTestTask(std::vector<std::string>* vector,
- std::string value) {
- vector->push_back(value);
-}
-
-void RunChainedTask(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- int count,
- const base::TickClock* clock,
- std::vector<base::TimeTicks>* tasks) {
- tasks->push_back(clock->NowTicks());
-
- if (count == 1)
- return;
-
- // Add a delay of 50ms to ensure that wake-up based throttling does not affect
- // us.
- task_runner->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(&RunChainedTask, task_runner, count - 1,
- base::Unretained(clock), base::Unretained(tasks)),
- base::TimeDelta::FromMilliseconds(50));
-}
-
-class WorkerThreadSchedulerForTest : public WorkerThreadScheduler {
- public:
- WorkerThreadSchedulerForTest(
- WebThreadType thread_type,
- std::unique_ptr<base::sequence_manager::TaskQueueManager> manager,
- WorkerSchedulerProxy* proxy)
- : WorkerThreadScheduler(thread_type, std::move(manager), proxy) {}
-
- const std::unordered_set<WorkerScheduler*>& worker_schedulers() {
- return worker_schedulers_;
- }
-
- using WorkerThreadScheduler::CreateTaskQueueThrottler;
-};
-
-class WorkerSchedulerForTest : public WorkerScheduler {
- public:
- explicit WorkerSchedulerForTest(
- WorkerThreadSchedulerForTest* thread_scheduler)
- : WorkerScheduler(thread_scheduler) {}
-
- using WorkerScheduler::DefaultTaskQueue;
- using WorkerScheduler::ThrottleableTaskQueue;
-};
-
-class WorkerSchedulerTest : public testing::Test {
- public:
- WorkerSchedulerTest()
- : mock_task_runner_(new base::TestMockTimeTaskRunner()),
- scheduler_(new WorkerThreadSchedulerForTest(
- WebThreadType::kTestThread,
- base::sequence_manager::TaskQueueManagerForTest::Create(
- nullptr,
- mock_task_runner_,
- mock_task_runner_->GetMockTickClock()),
- nullptr /* proxy */)) {
- mock_task_runner_->AdvanceMockTickClock(
- base::TimeDelta::FromMicroseconds(5000));
- }
-
- ~WorkerSchedulerTest() override = default;
-
- void SetUp() override {
- scheduler_->Init();
- worker_scheduler_ =
- std::make_unique<WorkerSchedulerForTest>(scheduler_.get());
- }
-
- void TearDown() override {
- if (worker_scheduler_) {
- worker_scheduler_->Dispose();
- worker_scheduler_.reset();
- }
- }
-
- const base::TickClock* GetClock() {
- return mock_task_runner_->GetMockTickClock();
- }
-
- void RunUntilIdle() { mock_task_runner_->FastForwardUntilNoTasksRemain(); }
-
- // Helper for posting a task.
- void PostTestTask(std::vector<std::string>* run_order,
- const std::string& task_descriptor) {
- worker_scheduler_->GetTaskRunner(TaskType::kInternalTest)
- ->PostTask(FROM_HERE,
- WTF::Bind(&AppendToVectorTestTask,
- WTF::Unretained(run_order), task_descriptor));
- }
-
- protected:
- scoped_refptr<base::TestMockTimeTaskRunner> mock_task_runner_;
-
- std::unique_ptr<WorkerThreadSchedulerForTest> scheduler_;
- std::unique_ptr<WorkerSchedulerForTest> worker_scheduler_;
-
- DISALLOW_COPY_AND_ASSIGN(WorkerSchedulerTest);
-};
-
-TEST_F(WorkerSchedulerTest, TestPostTasks) {
- std::vector<std::string> run_order;
- PostTestTask(&run_order, "T1");
- PostTestTask(&run_order, "T2");
- RunUntilIdle();
- PostTestTask(&run_order, "T3");
- RunUntilIdle();
- EXPECT_THAT(run_order, testing::ElementsAre("T1", "T2", "T3"));
-
- // Tasks should not run after the scheduler is disposed of.
- worker_scheduler_->Dispose();
- run_order.clear();
- PostTestTask(&run_order, "T4");
- PostTestTask(&run_order, "T5");
- RunUntilIdle();
- EXPECT_TRUE(run_order.empty());
-
- worker_scheduler_.reset();
-}
-
-TEST_F(WorkerSchedulerTest, RegisterWorkerSchedulers) {
- EXPECT_THAT(scheduler_->worker_schedulers(),
- testing::ElementsAre(worker_scheduler_.get()));
-
- std::unique_ptr<WorkerSchedulerForTest> worker_scheduler2 =
- std::make_unique<WorkerSchedulerForTest>(scheduler_.get());
-
- EXPECT_THAT(scheduler_->worker_schedulers(),
- testing::UnorderedElementsAre(worker_scheduler_.get(),
- worker_scheduler2.get()));
-
- worker_scheduler_->Dispose();
- worker_scheduler_.reset();
-
- EXPECT_THAT(scheduler_->worker_schedulers(),
- testing::ElementsAre(worker_scheduler2.get()));
-
- worker_scheduler2->Dispose();
-
- EXPECT_THAT(scheduler_->worker_schedulers(), testing::ElementsAre());
-}
-
-TEST_F(WorkerSchedulerTest, ThrottleWorkerScheduler) {
- scheduler_->CreateTaskQueueThrottler();
-
- EXPECT_FALSE(scheduler_->task_queue_throttler()->IsThrottled(
- worker_scheduler_->ThrottleableTaskQueue().get()));
-
- scheduler_->OnThrottlingStateChanged(
- FrameScheduler::ThrottlingState::kThrottled);
- EXPECT_TRUE(scheduler_->task_queue_throttler()->IsThrottled(
- worker_scheduler_->ThrottleableTaskQueue().get()));
-
- scheduler_->OnThrottlingStateChanged(
- FrameScheduler::ThrottlingState::kThrottled);
- EXPECT_TRUE(scheduler_->task_queue_throttler()->IsThrottled(
- worker_scheduler_->ThrottleableTaskQueue().get()));
-
- // Ensure that two calls with kThrottled do not mess with throttling
- // refcount.
- scheduler_->OnThrottlingStateChanged(
- FrameScheduler::ThrottlingState::kNotThrottled);
- EXPECT_FALSE(scheduler_->task_queue_throttler()->IsThrottled(
- worker_scheduler_->ThrottleableTaskQueue().get()));
-}
-
-TEST_F(WorkerSchedulerTest, ThrottleWorkerScheduler_CreateThrottled) {
- scheduler_->CreateTaskQueueThrottler();
-
- scheduler_->OnThrottlingStateChanged(
- FrameScheduler::ThrottlingState::kThrottled);
-
- std::unique_ptr<WorkerSchedulerForTest> worker_scheduler2 =
- std::make_unique<WorkerSchedulerForTest>(scheduler_.get());
-
- // Ensure that newly created scheduler is throttled.
- EXPECT_TRUE(scheduler_->task_queue_throttler()->IsThrottled(
- worker_scheduler2->ThrottleableTaskQueue().get()));
-
- worker_scheduler2->Dispose();
-}
-
-TEST_F(WorkerSchedulerTest, ThrottleWorkerScheduler_RunThrottledTasks) {
- scheduler_->CreateTaskQueueThrottler();
-
- // Create a new |worker_scheduler| to ensure that it's properly initialised.
- worker_scheduler_->Dispose();
- worker_scheduler_ =
- std::make_unique<WorkerSchedulerForTest>(scheduler_.get());
-
- scheduler_->OnThrottlingStateChanged(
- FrameScheduler::ThrottlingState::kThrottled);
-
- std::vector<base::TimeTicks> tasks;
-
- worker_scheduler_->ThrottleableTaskQueue()->PostTask(
- FROM_HERE,
- base::BindOnce(&RunChainedTask,
- worker_scheduler_->ThrottleableTaskQueue(), 5,
- base::Unretained(GetClock()), base::Unretained(&tasks)));
-
- RunUntilIdle();
-
- EXPECT_THAT(tasks,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1),
- base::TimeTicks() + base::TimeDelta::FromSeconds(2),
- base::TimeTicks() + base::TimeDelta::FromSeconds(3),
- base::TimeTicks() + base::TimeDelta::FromSeconds(4),
- base::TimeTicks() + base::TimeDelta::FromSeconds(5)));
-}
-
-} // namespace worker_scheduler_unittest
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_task_queue.cc b/chromium/third_party/blink/renderer/platform/scheduler/child/worker_task_queue.cc
deleted file mode 100644
index 67098630669..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_task_queue.cc
+++ /dev/null
@@ -1,43 +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/platform/scheduler/child/worker_task_queue.h"
-
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread_scheduler.h"
-
-namespace blink {
-namespace scheduler {
-
-using base::sequence_manager::TaskQueue;
-
-WorkerTaskQueue::WorkerTaskQueue(
- std::unique_ptr<base::sequence_manager::internal::TaskQueueImpl> impl,
- const TaskQueue::Spec& spec,
- NonMainThreadScheduler* non_main_thread_scheduler)
- : TaskQueue(std::move(impl), spec),
- non_main_thread_scheduler_(non_main_thread_scheduler) {
- if (GetTaskQueueImpl()) {
- // TaskQueueImpl may be null for tests.
- GetTaskQueueImpl()->SetOnTaskCompletedHandler(base::BindRepeating(
- &WorkerTaskQueue::OnTaskCompleted, base::Unretained(this)));
- }
-}
-
-WorkerTaskQueue::~WorkerTaskQueue() = default;
-
-void WorkerTaskQueue::OnTaskCompleted(
- const TaskQueue::Task& task,
- base::TimeTicks start,
- base::TimeTicks end,
- base::Optional<base::TimeDelta> thread_time) {
- // |non_main_thread_scheduler_| can be nullptr in tests.
- if (non_main_thread_scheduler_) {
- non_main_thread_scheduler_->OnTaskCompleted(this, task, start, end,
- thread_time);
- }
-}
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_task_queue.h b/chromium/third_party/blink/renderer/platform/scheduler/child/worker_task_queue.h
deleted file mode 100644
index 194cf956b06..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/child/worker_task_queue.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_WORKER_TASK_QUEUE_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_WORKER_TASK_QUEUE_H_
-
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
-
-namespace blink {
-namespace scheduler {
-
-class NonMainThreadScheduler;
-
-class PLATFORM_EXPORT WorkerTaskQueue
- : public base::sequence_manager::TaskQueue {
- public:
- WorkerTaskQueue(
- std::unique_ptr<base::sequence_manager::internal::TaskQueueImpl> impl,
- const Spec& spec,
- NonMainThreadScheduler* non_main_thread_scheduler);
- ~WorkerTaskQueue() override;
-
- void OnTaskCompleted(const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start,
- base::TimeTicks end,
- base::Optional<base::TimeDelta> thread_time);
-
- private:
- // Not owned.
- NonMainThreadScheduler* non_main_thread_scheduler_;
-};
-
-} // namespace scheduler
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_CHILD_WORKER_TASK_QUEUE_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/DEPS b/chromium/third_party/blink/renderer/platform/scheduler/common/DEPS
deleted file mode 100644
index a3018fec64f..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/DEPS
+++ /dev/null
@@ -1,6 +0,0 @@
-specific_include_rules = {
- ".*test\.cc": [
- "+cc/test",
- "+components/viz/test",
- ],
-}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/background_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/background_scheduler.cc
new file mode 100644
index 00000000000..18d898e39f3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/background_scheduler.cc
@@ -0,0 +1,19 @@
+// 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/platform/scheduler/public/background_scheduler.h"
+
+#include "base/location.h"
+#include "base/task_scheduler/post_task.h"
+
+namespace blink {
+
+void BackgroundScheduler::PostOnBackgroundThread(const base::Location& location,
+ CrossThreadClosure closure) {
+ base::PostTaskWithTraits(location,
+ {base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+ ConvertToBaseCallback(std::move(closure)));
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/background_scheduler_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/background_scheduler_unittest.cc
new file mode 100644
index 00000000000..66710ec5290
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/background_scheduler_unittest.cc
@@ -0,0 +1,34 @@
+// 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/platform/scheduler/public/background_scheduler.h"
+
+#include <memory>
+#include "base/location.h"
+#include "base/test/scoped_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/waitable_event.h"
+
+namespace blink {
+
+namespace {
+
+void PingPongTask(WaitableEvent* done_event) {
+ done_event->Signal();
+}
+
+} // namespace
+
+TEST(BackgroundSchedulerTest, RunOnBackgroundThread) {
+ base::test::ScopedTaskEnvironment scoped_task_environment;
+ std::unique_ptr<WaitableEvent> done_event = std::make_unique<WaitableEvent>();
+ BackgroundScheduler::PostOnBackgroundThread(
+ FROM_HERE,
+ CrossThreadBind(&PingPongTask, CrossThreadUnretained(done_event.get())));
+ // Test passes by not hanging on the following wait().
+ done_event->Wait();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.cc
new file mode 100644
index 00000000000..5abf5604a38
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.cc
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h"
+
+namespace blink {
+namespace scheduler {
+
+CancelableClosureHolder::CancelableClosureHolder() = default;
+
+CancelableClosureHolder::~CancelableClosureHolder() = default;
+
+void CancelableClosureHolder::Reset(const base::Closure& callback) {
+ callback_ = callback;
+ cancelable_callback_.Reset(callback_);
+}
+
+void CancelableClosureHolder::Cancel() {
+ DCHECK(!callback_.is_null());
+ cancelable_callback_.Reset(callback_);
+}
+
+base::Closure CancelableClosureHolder::GetCallback() const {
+ DCHECK(!callback_.is_null());
+ return cancelable_callback_.callback();
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h b/chromium/third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h
new file mode 100644
index 00000000000..a070892e78b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h
@@ -0,0 +1,42 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_CANCELABLE_CLOSURE_HOLDER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_CANCELABLE_CLOSURE_HOLDER_H_
+
+#include "base/cancelable_callback.h"
+#include "base/macros.h"
+
+namespace blink {
+namespace scheduler {
+
+// A CancelableClosureHolder is a CancelableCallback which resets its wrapped
+// callback with a cached closure whenever it is canceled.
+class CancelableClosureHolder {
+ public:
+ CancelableClosureHolder();
+ ~CancelableClosureHolder();
+
+ // Resets the closure to be wrapped by the cancelable callback. Cancels any
+ // outstanding callbacks.
+ void Reset(const base::Closure& callback);
+
+ // Cancels any outstanding closures returned by callback().
+ void Cancel();
+
+ // Returns a callback that will be disabled by calling Cancel(). Callback
+ // must have been set using Reset() before calling this function.
+ base::Closure GetCallback() const;
+
+ private:
+ base::Closure callback_;
+ base::CancelableClosure cancelable_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(CancelableClosureHolder);
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_CANCELABLE_CLOSURE_HOLDER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/frame_or_worker_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/frame_or_worker_scheduler.cc
new file mode 100644
index 00000000000..d5b0eb5966e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/frame_or_worker_scheduler.cc
@@ -0,0 +1,52 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h"
+
+namespace blink {
+
+FrameOrWorkerScheduler::LifecycleObserverHandle::LifecycleObserverHandle(
+ FrameOrWorkerScheduler* scheduler,
+ Observer* observer)
+ : scheduler_(scheduler->GetWeakPtr()), observer_(observer) {}
+
+FrameOrWorkerScheduler::LifecycleObserverHandle::~LifecycleObserverHandle() {
+ if (scheduler_)
+ scheduler_->RemoveLifecycleObserver(observer_);
+}
+
+FrameOrWorkerScheduler::FrameOrWorkerScheduler() : weak_factory_(this) {}
+
+FrameOrWorkerScheduler::~FrameOrWorkerScheduler() {
+ weak_factory_.InvalidateWeakPtrs();
+}
+
+std::unique_ptr<FrameOrWorkerScheduler::LifecycleObserverHandle>
+FrameOrWorkerScheduler::AddLifecycleObserver(ObserverType type,
+ Observer* observer) {
+ DCHECK(observer);
+ observer->OnLifecycleStateChanged(CalculateLifecycleState(type));
+ lifecycle_observers_[observer] = type;
+ return std::make_unique<LifecycleObserverHandle>(this, observer);
+}
+
+void FrameOrWorkerScheduler::RemoveLifecycleObserver(Observer* observer) {
+ DCHECK(observer);
+ const auto found = lifecycle_observers_.find(observer);
+ DCHECK(lifecycle_observers_.end() != found);
+ lifecycle_observers_.erase(found);
+}
+
+void FrameOrWorkerScheduler::NotifyLifecycleObservers() {
+ for (const auto& observer : lifecycle_observers_) {
+ observer.first->OnLifecycleStateChanged(
+ CalculateLifecycleState(observer.second));
+ }
+}
+
+base::WeakPtr<FrameOrWorkerScheduler> FrameOrWorkerScheduler::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper.cc
new file mode 100644
index 00000000000..41ab99b37aa
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper.cc
@@ -0,0 +1,40 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper.h"
+
+#include "base/bind.h"
+
+namespace blink {
+namespace scheduler {
+
+namespace {
+const int kDelayedTaskSweepIntervalSeconds = 30;
+}
+
+IdleCanceledDelayedTaskSweeper::IdleCanceledDelayedTaskSweeper(
+ SchedulerHelper* scheduler_helper,
+ scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner)
+ : scheduler_helper_(scheduler_helper),
+ idle_task_runner_(idle_task_runner),
+ weak_factory_(this) {
+ PostIdleTask();
+}
+
+void IdleCanceledDelayedTaskSweeper::PostIdleTask() {
+ idle_task_runner_->PostDelayedIdleTask(
+ FROM_HERE, base::TimeDelta::FromSeconds(kDelayedTaskSweepIntervalSeconds),
+ base::BindOnce(&IdleCanceledDelayedTaskSweeper::SweepIdleTask,
+ weak_factory_.GetWeakPtr()));
+}
+
+void IdleCanceledDelayedTaskSweeper::SweepIdleTask(base::TimeTicks deadline) {
+ TRACE_EVENT0("renderer.scheduler",
+ "IdleCanceledDelayedTaskSweeper::SweepIdleTask");
+ scheduler_helper_->SweepCanceledDelayedTasks();
+ PostIdleTask();
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper.h b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper.h
new file mode 100644
index 00000000000..def2193665e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper.h
@@ -0,0 +1,38 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_IDLE_CANCELED_DELAYED_TASK_SWEEPER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_IDLE_CANCELED_DELAYED_TASK_SWEEPER_H_
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "third_party/blink/public/platform/scheduler/single_thread_idle_task_runner.h"
+#include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
+
+namespace blink {
+namespace scheduler {
+
+// This class periodically sweeps away canceled delayed tasks, which helps
+// reduce memory consumption.
+class PLATFORM_EXPORT IdleCanceledDelayedTaskSweeper {
+ public:
+ IdleCanceledDelayedTaskSweeper(
+ SchedulerHelper* scheduler_helper,
+ scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner);
+
+ private:
+ void PostIdleTask();
+ void SweepIdleTask(base::TimeTicks deadline);
+
+ SchedulerHelper* scheduler_helper_; // NOT OWNED
+ scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
+ base::WeakPtrFactory<IdleCanceledDelayedTaskSweeper> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(IdleCanceledDelayedTaskSweeper);
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_IDLE_CANCELED_DELAYED_TASK_SWEEPER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper_unittest.cc
new file mode 100644
index 00000000000..5d522b7dfc2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper_unittest.cc
@@ -0,0 +1,132 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper.h"
+
+#include "base/task/sequence_manager/lazy_now.h"
+#include "base/task/sequence_manager/task_queue.h"
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/test/scoped_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/scheduler/common/idle_helper.h"
+#include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.h"
+
+namespace blink {
+namespace scheduler {
+
+class TestClass {
+ public:
+ TestClass() : weak_factory_(this) {}
+
+ void NopTask() {}
+
+ base::WeakPtrFactory<TestClass> weak_factory_;
+};
+
+class IdleCanceledDelayedTaskSweeperTest : public testing::Test,
+ public IdleHelper::Delegate {
+ public:
+ IdleCanceledDelayedTaskSweeperTest()
+ : task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+ base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED),
+ scheduler_helper_(new MainThreadSchedulerHelper(
+ base::sequence_manager::SequenceManagerForTest::Create(
+ nullptr,
+ task_environment_.GetMainThreadTaskRunner(),
+ task_environment_.GetMockTickClock()),
+ nullptr)),
+ idle_helper_(
+ new IdleHelper(scheduler_helper_.get(),
+ this,
+ "test",
+ base::TimeDelta::FromSeconds(30),
+ scheduler_helper_->NewTaskQueue(
+ MainThreadTaskQueue::QueueCreationParams(
+ MainThreadTaskQueue::QueueType::kTest)))),
+ idle_canceled_delayed_taks_sweeper_(
+ new IdleCanceledDelayedTaskSweeper(scheduler_helper_.get(),
+ idle_helper_->IdleTaskRunner())),
+ default_task_queue_(scheduler_helper_->DefaultMainThreadTaskQueue()) {
+ // Null clock might trigger some assertions.
+ task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(5));
+ }
+
+ ~IdleCanceledDelayedTaskSweeperTest() override = default;
+
+ void TearDown() override {
+ // Check that all tests stop posting tasks.
+ task_environment_.FastForwardUntilNoTasksRemain();
+ }
+
+ // IdleHelper::Delegate implementation:
+ bool CanEnterLongIdlePeriod(
+ base::TimeTicks now,
+ base::TimeDelta* next_long_idle_period_delay_out) override {
+ return true;
+ }
+ void IsNotQuiescent() override {}
+ void OnIdlePeriodStarted() override {}
+ void OnIdlePeriodEnded() override {}
+ void OnPendingTasksChanged(bool has_tasks) override {}
+
+ protected:
+ base::test::ScopedTaskEnvironment task_environment_;
+
+ std::unique_ptr<MainThreadSchedulerHelper> scheduler_helper_;
+ std::unique_ptr<IdleHelper> idle_helper_;
+ std::unique_ptr<IdleCanceledDelayedTaskSweeper>
+ idle_canceled_delayed_taks_sweeper_;
+ scoped_refptr<base::sequence_manager::TaskQueue> default_task_queue_;
+
+ DISALLOW_COPY_AND_ASSIGN(IdleCanceledDelayedTaskSweeperTest);
+};
+
+TEST_F(IdleCanceledDelayedTaskSweeperTest, TestSweep) {
+ TestClass class1;
+ TestClass class2;
+
+ // Post one task we won't cancel.
+ default_task_queue_->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&TestClass::NopTask, class1.weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromSeconds(100));
+
+ // And a bunch we will.
+ default_task_queue_->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&TestClass::NopTask, class2.weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromSeconds(101));
+
+ default_task_queue_->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&TestClass::NopTask, class2.weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromSeconds(102));
+
+ default_task_queue_->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&TestClass::NopTask, class2.weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromSeconds(103));
+
+ default_task_queue_->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&TestClass::NopTask, class2.weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromSeconds(104));
+
+ // Cancel the last four tasks.
+ class2.weak_factory_.InvalidateWeakPtrs();
+
+ // Give the IdleCanceledDelayedTaskSweeper a chance to run but don't let
+ // the first non canceled delayed task run. This is important because the
+ // canceled tasks would get removed by TaskQueueImpl::WakeUpForDelayedWork.
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(40));
+ idle_helper_->EnableLongIdlePeriod();
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(40));
+
+ EXPECT_EQ(1u, default_task_queue_->GetNumberOfPendingTasks());
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc
new file mode 100644
index 00000000000..6929547040f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc
@@ -0,0 +1,505 @@
+// 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/platform/scheduler/common/idle_helper.h"
+
+#include "base/task/sequence_manager/sequence_manager.h"
+#include "base/task/sequence_manager/task_queue.h"
+#include "base/task/sequence_manager/time_domain.h"
+#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
+#include "base/trace_event/trace_event_argument.h"
+#include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
+#include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
+
+namespace blink {
+namespace scheduler {
+
+using base::sequence_manager::TaskQueue;
+
+IdleHelper::IdleHelper(
+ SchedulerHelper* helper,
+ Delegate* delegate,
+ const char* idle_period_tracing_name,
+ base::TimeDelta required_quiescence_duration_before_long_idle_period,
+ scoped_refptr<TaskQueue> idle_queue)
+ : helper_(helper),
+ delegate_(delegate),
+ idle_queue_(std::move(idle_queue)),
+ state_(helper, delegate, idle_period_tracing_name),
+ required_quiescence_duration_before_long_idle_period_(
+ required_quiescence_duration_before_long_idle_period),
+ is_shutdown_(false),
+ weak_factory_(this) {
+ weak_idle_helper_ptr_ = weak_factory_.GetWeakPtr();
+ enable_next_long_idle_period_closure_.Reset(base::BindRepeating(
+ &IdleHelper::EnableLongIdlePeriod, weak_idle_helper_ptr_));
+ on_idle_task_posted_closure_.Reset(base::BindRepeating(
+ &IdleHelper::OnIdleTaskPostedOnMainThread, weak_idle_helper_ptr_));
+
+ idle_task_runner_ = base::MakeRefCounted<SingleThreadIdleTaskRunner>(
+ TaskQueueWithTaskType::Create(idle_queue_,
+ TaskType::kMainThreadTaskQueueIdle),
+ this);
+
+ // This fence will block any idle tasks from running.
+ idle_queue_->InsertFence(TaskQueue::InsertFencePosition::kBeginningOfTime);
+ idle_queue_->SetQueuePriority(TaskQueue::kBestEffortPriority);
+}
+
+IdleHelper::~IdleHelper() {
+ Shutdown();
+}
+
+void IdleHelper::Shutdown() {
+ if (is_shutdown_)
+ return;
+
+ EndIdlePeriod();
+ is_shutdown_ = true;
+ weak_factory_.InvalidateWeakPtrs();
+ // Belt & braces, might not be needed.
+ idle_queue_->ShutdownTaskQueue();
+}
+
+IdleHelper::Delegate::Delegate() = default;
+
+IdleHelper::Delegate::~Delegate() = default;
+
+scoped_refptr<SingleThreadIdleTaskRunner> IdleHelper::IdleTaskRunner() {
+ helper_->CheckOnValidThread();
+ return idle_task_runner_;
+}
+
+IdleHelper::IdlePeriodState IdleHelper::ComputeNewLongIdlePeriodState(
+ const base::TimeTicks now,
+ base::TimeDelta* next_long_idle_period_delay_out) {
+ helper_->CheckOnValidThread();
+
+ if (!delegate_->CanEnterLongIdlePeriod(now,
+ next_long_idle_period_delay_out)) {
+ return IdlePeriodState::kNotInIdlePeriod;
+ }
+
+ base::sequence_manager::LazyNow lazy_now(now);
+ base::Optional<base::TimeDelta> delay_till_next_task =
+ helper_->real_time_domain()->DelayTillNextTask(&lazy_now);
+
+ base::TimeDelta max_long_idle_period_duration =
+ base::TimeDelta::FromMilliseconds(kMaximumIdlePeriodMillis);
+ base::TimeDelta long_idle_period_duration;
+
+ if (delay_till_next_task) {
+ // Limit the idle period duration to be before the next pending task.
+ long_idle_period_duration =
+ std::min(*delay_till_next_task, max_long_idle_period_duration);
+ } else {
+ long_idle_period_duration = max_long_idle_period_duration;
+ }
+
+ if (long_idle_period_duration >=
+ base::TimeDelta::FromMilliseconds(kMinimumIdlePeriodDurationMillis)) {
+ *next_long_idle_period_delay_out = long_idle_period_duration;
+ if (!idle_queue_->HasTaskToRunImmediately())
+ return IdlePeriodState::kInLongIdlePeriodPaused;
+ if (long_idle_period_duration == max_long_idle_period_duration)
+ return IdlePeriodState::kInLongIdlePeriodWithMaxDeadline;
+ return IdlePeriodState::kInLongIdlePeriod;
+ } else {
+ // If we can't start the idle period yet then try again after wake-up.
+ *next_long_idle_period_delay_out = base::TimeDelta::FromMilliseconds(
+ kRetryEnableLongIdlePeriodDelayMillis);
+ return IdlePeriodState::kNotInIdlePeriod;
+ }
+}
+
+bool IdleHelper::ShouldWaitForQuiescence() {
+ helper_->CheckOnValidThread();
+
+ if (required_quiescence_duration_before_long_idle_period_ ==
+ base::TimeDelta()) {
+ return false;
+ }
+
+ bool system_is_quiescent = helper_->GetAndClearSystemIsQuiescentBit();
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
+ "ShouldWaitForQuiescence", "system_is_quiescent",
+ system_is_quiescent);
+ return !system_is_quiescent;
+}
+
+void IdleHelper::EnableLongIdlePeriod() {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
+ "EnableLongIdlePeriod");
+ helper_->CheckOnValidThread();
+ if (is_shutdown_)
+ return;
+
+ // End any previous idle period.
+ EndIdlePeriod();
+
+ if (ShouldWaitForQuiescence()) {
+ helper_->ControlTaskQueue()->PostDelayedTask(
+ FROM_HERE, enable_next_long_idle_period_closure_.GetCallback(),
+ required_quiescence_duration_before_long_idle_period_);
+ delegate_->IsNotQuiescent();
+ return;
+ }
+
+ base::TimeTicks now(helper_->NowTicks());
+ base::TimeDelta next_long_idle_period_delay;
+ IdlePeriodState new_idle_period_state =
+ ComputeNewLongIdlePeriodState(now, &next_long_idle_period_delay);
+ if (IsInIdlePeriod(new_idle_period_state)) {
+ StartIdlePeriod(new_idle_period_state, now,
+ now + next_long_idle_period_delay);
+ } else {
+ // Otherwise wait for the next long idle period delay before trying again.
+ helper_->ControlTaskQueue()->PostDelayedTask(
+ FROM_HERE, enable_next_long_idle_period_closure_.GetCallback(),
+ next_long_idle_period_delay);
+ }
+}
+
+void IdleHelper::StartIdlePeriod(IdlePeriodState new_state,
+ base::TimeTicks now,
+ base::TimeTicks idle_period_deadline) {
+ DCHECK(!is_shutdown_);
+ DCHECK_GT(idle_period_deadline, now);
+ helper_->CheckOnValidThread();
+ DCHECK(IsInIdlePeriod(new_state));
+
+ // Allow any ready delayed idle tasks to run.
+ idle_task_runner_->EnqueueReadyDelayedIdleTasks();
+
+ base::TimeDelta idle_period_duration(idle_period_deadline - now);
+ if (idle_period_duration <
+ base::TimeDelta::FromMilliseconds(kMinimumIdlePeriodDurationMillis)) {
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
+ "NotStartingIdlePeriodBecauseDeadlineIsTooClose",
+ "idle_period_duration_ms",
+ idle_period_duration.InMillisecondsF());
+ return;
+ }
+
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
+ "StartIdlePeriod");
+ if (!IsInIdlePeriod(state_.idle_period_state()))
+ helper_->AddTaskObserver(this);
+
+ // Use a fence to make sure any idle tasks posted after this point do not run
+ // until the next idle period and unblock existing tasks.
+ idle_queue_->InsertFence(TaskQueue::InsertFencePosition::kNow);
+
+ state_.UpdateState(new_state, idle_period_deadline, now);
+}
+
+void IdleHelper::EndIdlePeriod() {
+ if (is_shutdown_)
+ return;
+
+ helper_->CheckOnValidThread();
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
+ "EndIdlePeriod");
+
+ enable_next_long_idle_period_closure_.Cancel();
+ on_idle_task_posted_closure_.Cancel();
+
+ // If we weren't already within an idle period then early-out.
+ if (!IsInIdlePeriod(state_.idle_period_state()))
+ return;
+
+ helper_->RemoveTaskObserver(this);
+
+ // This fence will block any idle tasks from running.
+ idle_queue_->InsertFence(TaskQueue::InsertFencePosition::kBeginningOfTime);
+ state_.UpdateState(IdlePeriodState::kNotInIdlePeriod, base::TimeTicks(),
+ base::TimeTicks());
+}
+
+void IdleHelper::WillProcessTask(const base::PendingTask& pending_task) {
+ DCHECK(!is_shutdown_);
+}
+
+void IdleHelper::DidProcessTask(const base::PendingTask& pending_task) {
+ helper_->CheckOnValidThread();
+ DCHECK(!is_shutdown_);
+ DCHECK(IsInIdlePeriod(state_.idle_period_state()));
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
+ "DidProcessTask");
+ if (state_.idle_period_state() != IdlePeriodState::kInLongIdlePeriodPaused &&
+ helper_->NowTicks() >= state_.idle_period_deadline()) {
+ // If the idle period deadline has now been reached, either end the idle
+ // period or trigger a new long-idle period.
+ if (IsInLongIdlePeriod(state_.idle_period_state())) {
+ EnableLongIdlePeriod();
+ } else {
+ DCHECK(IdlePeriodState::kInShortIdlePeriod == state_.idle_period_state());
+ EndIdlePeriod();
+ }
+ }
+}
+
+void IdleHelper::UpdateLongIdlePeriodStateAfterIdleTask() {
+ helper_->CheckOnValidThread();
+ DCHECK(!is_shutdown_);
+ DCHECK(IsInLongIdlePeriod(state_.idle_period_state()));
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
+ "UpdateLongIdlePeriodStateAfterIdleTask");
+
+ if (!idle_queue_->HasTaskToRunImmediately()) {
+ // If there are no more idle tasks then pause long idle period ticks until a
+ // new idle task is posted.
+ state_.UpdateState(IdlePeriodState::kInLongIdlePeriodPaused,
+ state_.idle_period_deadline(), base::TimeTicks());
+ } else if (idle_queue_->BlockedByFence()) {
+ // If there is still idle work to do then just start the next idle period.
+ base::TimeDelta next_long_idle_period_delay;
+ // Ensure that we kick the scheduler at the right time to
+ // initiate the next idle period.
+ next_long_idle_period_delay = std::max(
+ base::TimeDelta(), state_.idle_period_deadline() - helper_->NowTicks());
+ if (next_long_idle_period_delay.is_zero()) {
+ EnableLongIdlePeriod();
+ } else {
+ helper_->ControlTaskQueue()->PostDelayedTask(
+ FROM_HERE, enable_next_long_idle_period_closure_.GetCallback(),
+ next_long_idle_period_delay);
+ }
+ }
+}
+
+base::TimeTicks IdleHelper::CurrentIdleTaskDeadline() const {
+ helper_->CheckOnValidThread();
+ return state_.idle_period_deadline();
+}
+
+void IdleHelper::OnIdleTaskPosted() {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
+ "OnIdleTaskPosted");
+ if (is_shutdown_)
+ return;
+ if (idle_task_runner_->RunsTasksInCurrentSequence()) {
+ OnIdleTaskPostedOnMainThread();
+ } else {
+ helper_->ControlTaskQueue()->PostTask(
+ FROM_HERE, on_idle_task_posted_closure_.GetCallback());
+ }
+}
+
+void IdleHelper::OnIdleTaskPostedOnMainThread() {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
+ "OnIdleTaskPostedOnMainThread");
+ if (is_shutdown_)
+ return;
+ delegate_->OnPendingTasksChanged(true);
+ if (state_.idle_period_state() == IdlePeriodState::kInLongIdlePeriodPaused) {
+ // Restart long idle period ticks.
+ helper_->ControlTaskQueue()->PostTask(
+ FROM_HERE, enable_next_long_idle_period_closure_.GetCallback());
+ }
+}
+
+base::TimeTicks IdleHelper::WillProcessIdleTask() {
+ helper_->CheckOnValidThread();
+ DCHECK(!is_shutdown_);
+ state_.TraceIdleIdleTaskStart();
+ return CurrentIdleTaskDeadline();
+}
+
+void IdleHelper::DidProcessIdleTask() {
+ helper_->CheckOnValidThread();
+ if (is_shutdown_)
+ return;
+ state_.TraceIdleIdleTaskEnd();
+ if (IsInLongIdlePeriod(state_.idle_period_state())) {
+ UpdateLongIdlePeriodStateAfterIdleTask();
+ }
+ delegate_->OnPendingTasksChanged(idle_queue_->GetNumberOfPendingTasks() > 0);
+}
+
+base::TimeTicks IdleHelper::NowTicks() {
+ return helper_->NowTicks();
+}
+
+// static
+bool IdleHelper::IsInIdlePeriod(IdlePeriodState state) {
+ return state != IdlePeriodState::kNotInIdlePeriod;
+}
+
+// static
+bool IdleHelper::IsInLongIdlePeriod(IdlePeriodState state) {
+ return state == IdlePeriodState::kInLongIdlePeriod ||
+ state == IdlePeriodState::kInLongIdlePeriodWithMaxDeadline ||
+ state == IdlePeriodState::kInLongIdlePeriodPaused;
+}
+
+bool IdleHelper::CanExceedIdleDeadlineIfRequired() const {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
+ "CanExceedIdleDeadlineIfRequired");
+ helper_->CheckOnValidThread();
+ return state_.idle_period_state() ==
+ IdlePeriodState::kInLongIdlePeriodWithMaxDeadline;
+}
+
+IdleHelper::IdlePeriodState IdleHelper::SchedulerIdlePeriodState() const {
+ return state_.idle_period_state();
+}
+
+IdleHelper::State::State(SchedulerHelper* helper,
+ Delegate* delegate,
+ const char* idle_period_tracing_name)
+ : helper_(helper),
+ delegate_(delegate),
+ idle_period_state_(IdlePeriodState::kNotInIdlePeriod),
+ idle_period_trace_event_started_(false),
+ running_idle_task_for_tracing_(false),
+ idle_period_tracing_name_(idle_period_tracing_name) {}
+
+IdleHelper::State::~State() = default;
+
+IdleHelper::IdlePeriodState IdleHelper::State::idle_period_state() const {
+ helper_->CheckOnValidThread();
+ return idle_period_state_;
+}
+
+base::TimeTicks IdleHelper::State::idle_period_deadline() const {
+ helper_->CheckOnValidThread();
+ return idle_period_deadline_;
+}
+
+void IdleHelper::State::UpdateState(IdlePeriodState new_state,
+ base::TimeTicks new_deadline,
+ base::TimeTicks optional_now) {
+ IdlePeriodState old_idle_period_state = idle_period_state_;
+
+ helper_->CheckOnValidThread();
+ if (new_state == idle_period_state_) {
+ DCHECK_EQ(new_deadline, idle_period_deadline_);
+ return;
+ }
+
+ bool is_tracing;
+ TRACE_EVENT_CATEGORY_GROUP_ENABLED("renderer.scheduler", &is_tracing);
+ if (is_tracing) {
+ base::TimeTicks now(optional_now.is_null() ? helper_->NowTicks()
+ : optional_now);
+ TraceEventIdlePeriodStateChange(new_state, running_idle_task_for_tracing_,
+ new_deadline, now);
+ }
+
+ idle_period_state_ = new_state;
+ idle_period_deadline_ = new_deadline;
+
+ // Inform the delegate if we are starting or ending an idle period.
+ if (IsInIdlePeriod(new_state) && !IsInIdlePeriod(old_idle_period_state)) {
+ delegate_->OnIdlePeriodStarted();
+ } else if (!IsInIdlePeriod(new_state) &&
+ IsInIdlePeriod(old_idle_period_state)) {
+ delegate_->OnIdlePeriodEnded();
+ }
+}
+
+void IdleHelper::State::TraceIdleIdleTaskStart() {
+ helper_->CheckOnValidThread();
+
+ bool is_tracing;
+ TRACE_EVENT_CATEGORY_GROUP_ENABLED("renderer.scheduler", &is_tracing);
+ if (is_tracing) {
+ TraceEventIdlePeriodStateChange(idle_period_state_, true,
+ idle_period_deadline_,
+ base::TimeTicks::Now());
+ }
+}
+
+void IdleHelper::State::TraceIdleIdleTaskEnd() {
+ helper_->CheckOnValidThread();
+
+ bool is_tracing;
+ TRACE_EVENT_CATEGORY_GROUP_ENABLED("renderer.scheduler", &is_tracing);
+ if (is_tracing) {
+ TraceEventIdlePeriodStateChange(idle_period_state_, false,
+ idle_period_deadline_,
+ base::TimeTicks::Now());
+ }
+}
+
+void IdleHelper::State::TraceEventIdlePeriodStateChange(
+ IdlePeriodState new_state,
+ bool new_running_idle_task,
+ base::TimeTicks new_deadline,
+ base::TimeTicks now) {
+ TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
+ "SetIdlePeriodState", "old_state",
+ IdleHelper::IdlePeriodStateToString(idle_period_state_),
+ "new_state", IdleHelper::IdlePeriodStateToString(new_state));
+
+ if (idle_period_trace_event_started_ && running_idle_task_for_tracing_ &&
+ !new_running_idle_task) {
+ running_idle_task_for_tracing_ = false;
+ if (!idle_period_deadline_.is_null() && now > idle_period_deadline_) {
+ TRACE_EVENT_ASYNC_STEP_INTO_WITH_TIMESTAMP0(
+ "renderer.scheduler", idle_period_tracing_name_, this,
+ "DeadlineOverrun",
+ std::max(idle_period_deadline_, last_idle_task_trace_time_));
+ }
+ }
+
+ if (IsInIdlePeriod(new_state)) {
+ if (!idle_period_trace_event_started_) {
+ idle_period_trace_event_started_ = true;
+ TRACE_EVENT_ASYNC_BEGIN1("renderer.scheduler", idle_period_tracing_name_,
+ this, "idle_period_length_ms",
+ (new_deadline - now).InMillisecondsF());
+ }
+
+ if (new_running_idle_task) {
+ last_idle_task_trace_time_ = now;
+ running_idle_task_for_tracing_ = true;
+ TRACE_EVENT_ASYNC_STEP_INTO0("renderer.scheduler",
+ idle_period_tracing_name_, this,
+ "RunningIdleTask");
+ } else if (new_state == IdlePeriodState::kInShortIdlePeriod) {
+ TRACE_EVENT_ASYNC_STEP_INTO0("renderer.scheduler",
+ idle_period_tracing_name_, this,
+ "ShortIdlePeriod");
+ } else if (IsInLongIdlePeriod(new_state) &&
+ new_state != IdlePeriodState::kInLongIdlePeriodPaused) {
+ TRACE_EVENT_ASYNC_STEP_INTO0("renderer.scheduler",
+ idle_period_tracing_name_, this,
+ "LongIdlePeriod");
+ } else if (new_state == IdlePeriodState::kInLongIdlePeriodPaused) {
+ TRACE_EVENT_ASYNC_STEP_INTO0("renderer.scheduler",
+ idle_period_tracing_name_, this,
+ "LongIdlePeriodPaused");
+ }
+ } else if (idle_period_trace_event_started_) {
+ idle_period_trace_event_started_ = false;
+ TRACE_EVENT_ASYNC_END0("renderer.scheduler", idle_period_tracing_name_,
+ this);
+ }
+}
+
+// static
+const char* IdleHelper::IdlePeriodStateToString(
+ IdlePeriodState idle_period_state) {
+ switch (idle_period_state) {
+ case IdlePeriodState::kNotInIdlePeriod:
+ return "not_in_idle_period";
+ case IdlePeriodState::kInShortIdlePeriod:
+ return "in_short_idle_period";
+ case IdlePeriodState::kInLongIdlePeriod:
+ return "in_long_idle_period";
+ case IdlePeriodState::kInLongIdlePeriodWithMaxDeadline:
+ return "in_long_idle_period_with_max_deadline";
+ case IdlePeriodState::kInLongIdlePeriodPaused:
+ return "in_long_idle_period_paused";
+ default:
+ NOTREACHED();
+ return nullptr;
+ }
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.h
new file mode 100644
index 00000000000..a7f5f49a6ba
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper.h
@@ -0,0 +1,250 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_IDLE_HELPER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_IDLE_HELPER_H_
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "third_party/blink/public/platform/scheduler/single_thread_idle_task_runner.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h"
+#include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
+
+namespace blink {
+namespace scheduler {
+namespace idle_helper_unittest {
+class BaseIdleHelperTest;
+class IdleHelperTest;
+} // namespace idle_helper_unittest
+
+class SchedulerHelper;
+
+// The job of the IdleHelper is to run idle tasks when the system is otherwise
+// idle. Idle tasks should be optional work, with no guarantee they will be run
+// at all. Idle tasks are subject to three levels of throttling:
+//
+// 1. Both idle queues are run a BEST_EFFORT priority (i.e. only selected if
+// there is nothing else to do.
+// 2. The idle queues are only enabled during an idle period.
+// 3. Idle tasks posted from within an idle task run in the next idle period.
+// This is achieved by inserting a fence into the queue.
+//
+// There are two types of idle periods:
+// 1. Short idle period - typically less than 10ms run after begin main frame
+// has finished, with the idle period ending at the compositor provided
+// deadline.
+// 2. Long idle periods - typically up to 50ms when no frames are being
+// produced.
+//
+// Idle tasks are supplied a deadline, and should endeavor to finished before it
+// ends to avoid jank.
+class PLATFORM_EXPORT IdleHelper : public base::MessageLoop::TaskObserver,
+ public SingleThreadIdleTaskRunner::Delegate {
+ public:
+ // Used to by scheduler implementations to customize idle behaviour.
+ class PLATFORM_EXPORT Delegate {
+ public:
+ Delegate();
+ virtual ~Delegate();
+
+ // If it's ok to enter a long idle period, return true. Otherwise return
+ // false and set next_long_idle_period_delay_out so we know when to try
+ // again.
+ virtual bool CanEnterLongIdlePeriod(
+ base::TimeTicks now,
+ base::TimeDelta* next_long_idle_period_delay_out) = 0;
+
+ // Signals that the Long Idle Period hasn't started yet because the system
+ // isn't quiescent.
+ virtual void IsNotQuiescent() = 0;
+
+ // Signals that we have started an Idle Period.
+ virtual void OnIdlePeriodStarted() = 0;
+
+ // Signals that we have finished an Idle Period.
+ virtual void OnIdlePeriodEnded() = 0;
+
+ // Signals that the task list has changed.
+ virtual void OnPendingTasksChanged(bool has_tasks) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Delegate);
+ };
+
+ // Keep IdleHelper::IdlePeriodStateToString in sync with this enum.
+ enum class IdlePeriodState {
+ kNotInIdlePeriod,
+ kInShortIdlePeriod,
+ kInLongIdlePeriod,
+ kInLongIdlePeriodWithMaxDeadline,
+ kInLongIdlePeriodPaused,
+ // Must be the last entry.
+ kIdlePeriodStateCount,
+ kFirstIdlePeriodState = kNotInIdlePeriod,
+ };
+
+ // The maximum length of an idle period.
+ static const int kMaximumIdlePeriodMillis = 50;
+
+ // |helper| and |delegate| are not owned by IdleHelper object and must
+ // outlive it.
+ IdleHelper(
+ SchedulerHelper* helper,
+ Delegate* delegate,
+ const char* idle_period_tracing_name,
+ base::TimeDelta required_quiescence_duration_before_long_idle_period,
+ scoped_refptr<base::sequence_manager::TaskQueue> idle_queue);
+ ~IdleHelper() override;
+
+ // Prevents any further idle tasks from running.
+ void Shutdown();
+
+ // Returns the idle task runner. Tasks posted to this runner may be reordered
+ // relative to other task types and may be starved for an arbitrarily long
+ // time if no idle time is available.
+ scoped_refptr<SingleThreadIdleTaskRunner> IdleTaskRunner();
+
+ // If |required_quiescence_duration_before_long_idle_period_| is zero then
+ // immediately initiate a long idle period, otherwise check if any tasks have
+ // run recently and if so, check again after a delay of
+ // |required_quiescence_duration_before_long_idle_period_|.
+ // Calling this function will end any previous idle period immediately, and
+ // potentially again later if
+ // |required_quiescence_duration_before_long_idle_period_| is non-zero.
+ // NOTE EndIdlePeriod will disable the long idle periods.
+ void EnableLongIdlePeriod();
+
+ // Start an idle period with a given idle period deadline.
+ void StartIdlePeriod(IdlePeriodState new_idle_period_state,
+ base::TimeTicks now,
+ base::TimeTicks idle_period_deadline);
+
+ // This will end an idle period either started with StartIdlePeriod or
+ // EnableLongIdlePeriod.
+ void EndIdlePeriod();
+
+ // Returns true if a currently running idle task could exceed its deadline
+ // without impacting user experience too much. This should only be used if
+ // there is a task which cannot be pre-empted and is likely to take longer
+ // than the largest expected idle task deadline. It should NOT be polled to
+ // check whether more work can be performed on the current idle task after
+ // its deadline has expired - post a new idle task for the continuation of the
+ // work in this case.
+ // Must be called from the thread this class was created on.
+ bool CanExceedIdleDeadlineIfRequired() const;
+
+ // Returns the deadline for the current idle task.
+ base::TimeTicks CurrentIdleTaskDeadline() const;
+
+ // SingleThreadIdleTaskRunner::Delegate implementation:
+ void OnIdleTaskPosted() override;
+ base::TimeTicks WillProcessIdleTask() override;
+ void DidProcessIdleTask() override;
+ base::TimeTicks NowTicks() override;
+
+ // base::MessageLoop::TaskObserver implementation:
+ void WillProcessTask(const base::PendingTask& pending_task) override;
+ void DidProcessTask(const base::PendingTask& pending_task) override;
+
+ IdlePeriodState SchedulerIdlePeriodState() const;
+ static const char* IdlePeriodStateToString(IdlePeriodState state);
+
+ private:
+ friend class idle_helper_unittest::BaseIdleHelperTest;
+ friend class idle_helper_unittest::IdleHelperTest;
+
+ const scoped_refptr<base::sequence_manager::TaskQueue>& idle_queue() const {
+ return idle_queue_;
+ }
+
+ class State {
+ public:
+ State(SchedulerHelper* helper,
+ Delegate* delegate,
+ const char* idle_period_tracing_name);
+ virtual ~State();
+
+ void UpdateState(IdlePeriodState new_state,
+ base::TimeTicks new_deadline,
+ base::TimeTicks optional_now);
+ bool IsIdlePeriodPaused() const;
+
+ IdlePeriodState idle_period_state() const;
+ base::TimeTicks idle_period_deadline() const;
+
+ void TraceIdleIdleTaskStart();
+ void TraceIdleIdleTaskEnd();
+
+ private:
+ void TraceEventIdlePeriodStateChange(IdlePeriodState new_state,
+ bool new_running_idle_task,
+ base::TimeTicks new_deadline,
+ base::TimeTicks optional_now);
+
+ SchedulerHelper* helper_; // NOT OWNED
+ Delegate* delegate_; // NOT OWNED
+
+ IdlePeriodState idle_period_state_;
+ base::TimeTicks idle_period_deadline_;
+
+ base::TimeTicks last_idle_task_trace_time_;
+ bool idle_period_trace_event_started_;
+ bool running_idle_task_for_tracing_;
+ const char* idle_period_tracing_name_;
+
+ DISALLOW_COPY_AND_ASSIGN(State);
+ };
+
+ // The minimum duration of an idle period.
+ static const int kMinimumIdlePeriodDurationMillis = 1;
+
+ // The minimum delay to wait between retrying to initiate a long idle time.
+ static const int kRetryEnableLongIdlePeriodDelayMillis = 1;
+
+ // Returns the new idle period state for the next long idle period. Fills in
+ // |next_long_idle_period_delay_out| with the next time we should try to
+ // initiate the next idle period.
+ IdlePeriodState ComputeNewLongIdlePeriodState(
+ const base::TimeTicks now,
+ base::TimeDelta* next_long_idle_period_delay_out);
+
+ bool ShouldWaitForQuiescence();
+ void OnIdleTaskPostedOnMainThread();
+ void UpdateLongIdlePeriodStateAfterIdleTask();
+
+ void SetIdlePeriodState(IdlePeriodState new_state,
+ base::TimeTicks new_deadline,
+ base::TimeTicks optional_now);
+
+ // Returns true if |state| represents being within an idle period state.
+ static bool IsInIdlePeriod(IdlePeriodState state);
+ // Returns true if |state| represents being within a long idle period state.
+ static bool IsInLongIdlePeriod(IdlePeriodState state);
+
+ SchedulerHelper* helper_; // NOT OWNED
+ Delegate* delegate_; // NOT OWNED
+ scoped_refptr<base::sequence_manager::TaskQueue> idle_queue_;
+ scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
+
+ CancelableClosureHolder enable_next_long_idle_period_closure_;
+ CancelableClosureHolder on_idle_task_posted_closure_;
+
+ State state_;
+
+ base::TimeDelta required_quiescence_duration_before_long_idle_period_;
+
+ bool is_shutdown_;
+
+ base::WeakPtr<IdleHelper> weak_idle_helper_ptr_;
+ base::WeakPtrFactory<IdleHelper> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(IdleHelper);
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_IDLE_HELPER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc
new file mode 100644
index 00000000000..52f09b80ab1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc
@@ -0,0 +1,1185 @@
+// 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/platform/scheduler/common/idle_helper.h"
+
+#include <utility>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/task/sequence_manager/sequence_manager.h"
+#include "base/task/sequence_manager/task_queue.h"
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/task/sequence_manager/time_domain.h"
+#include "base/test/test_mock_time_task_runner.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h"
+
+using testing::_;
+using testing::AnyNumber;
+using testing::AtLeast;
+using testing::Exactly;
+using testing::Invoke;
+using testing::Return;
+
+namespace blink {
+namespace scheduler {
+// To avoid symbol collisions in jumbo builds.
+namespace idle_helper_unittest {
+
+using base::sequence_manager::TaskQueue;
+using base::sequence_manager::SequenceManager;
+
+void AppendToVectorTestTask(std::vector<std::string>* vector,
+ std::string value) {
+ vector->push_back(value);
+}
+
+void AppendToVectorIdleTestTask(std::vector<std::string>* vector,
+ std::string value,
+ base::TimeTicks deadline) {
+ AppendToVectorTestTask(vector, value);
+}
+
+void NullTask() {}
+
+void NullIdleTask(base::TimeTicks deadline) {}
+
+void AppendToVectorReentrantTask(base::SingleThreadTaskRunner* task_runner,
+ std::vector<int>* vector,
+ int* reentrant_count,
+ int max_reentrant_count) {
+ vector->push_back((*reentrant_count)++);
+ if (*reentrant_count < max_reentrant_count) {
+ task_runner->PostTask(FROM_HERE,
+ base::BindOnce(AppendToVectorReentrantTask,
+ base::Unretained(task_runner), vector,
+ reentrant_count, max_reentrant_count));
+ }
+}
+
+void IdleTestTask(int* run_count,
+ base::TimeTicks* deadline_out,
+ base::TimeTicks deadline) {
+ (*run_count)++;
+ *deadline_out = deadline;
+}
+
+int g_max_idle_task_reposts = 2;
+
+void RepostingIdleTestTask(SingleThreadIdleTaskRunner* idle_task_runner,
+ int* run_count,
+ base::TimeTicks* deadline_out,
+ base::TimeTicks deadline) {
+ if ((*run_count + 1) < g_max_idle_task_reposts) {
+ idle_task_runner->PostIdleTask(
+ FROM_HERE, base::BindOnce(&RepostingIdleTestTask,
+ base::Unretained(idle_task_runner), run_count,
+ deadline_out));
+ }
+ *deadline_out = deadline;
+ (*run_count)++;
+}
+
+void RepostingUpdateClockIdleTestTask(
+ SingleThreadIdleTaskRunner* idle_task_runner,
+ int* run_count,
+ scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner,
+ base::TimeDelta advance_time,
+ std::vector<base::TimeTicks>* deadlines,
+ base::TimeTicks deadline) {
+ if ((*run_count + 1) < g_max_idle_task_reposts) {
+ idle_task_runner->PostIdleTask(
+ FROM_HERE, base::BindOnce(&RepostingUpdateClockIdleTestTask,
+ base::Unretained(idle_task_runner), run_count,
+ test_task_runner, advance_time, deadlines));
+ }
+ deadlines->push_back(deadline);
+ (*run_count)++;
+ test_task_runner->AdvanceMockTickClock(advance_time);
+}
+
+void RepeatingTask(base::SingleThreadTaskRunner* task_runner,
+ int num_repeats,
+ base::TimeDelta delay) {
+ if (num_repeats > 1) {
+ task_runner->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&RepeatingTask, base::Unretained(task_runner),
+ num_repeats - 1, delay),
+ delay);
+ }
+}
+
+void UpdateClockIdleTestTask(
+ scoped_refptr<base::TestMockTimeTaskRunner> task_runner,
+ int* run_count,
+ base::TimeTicks set_time,
+ base::TimeTicks deadline) {
+ task_runner->AdvanceMockTickClock(set_time - task_runner->NowTicks());
+ (*run_count)++;
+}
+
+void UpdateClockToDeadlineIdleTestTask(
+ scoped_refptr<base::TestMockTimeTaskRunner> task_runner,
+ int* run_count,
+ base::TimeTicks deadline) {
+ UpdateClockIdleTestTask(task_runner, run_count, deadline, deadline);
+}
+
+void EndIdlePeriodIdleTask(IdleHelper* idle_helper, base::TimeTicks deadline) {
+ idle_helper->EndIdlePeriod();
+}
+
+void ShutdownIdleTask(IdleHelper* helper,
+ bool* shutdown_task_run,
+ base::TimeTicks deadline) {
+ *shutdown_task_run = true;
+ helper->Shutdown();
+}
+
+class IdleHelperForTest : public IdleHelper, public IdleHelper::Delegate {
+ public:
+ explicit IdleHelperForTest(
+ SchedulerHelper* scheduler_helper,
+ base::TimeDelta required_quiescence_duration_before_long_idle_period,
+ scoped_refptr<TaskQueue> idle_task_runner)
+ : IdleHelper(scheduler_helper,
+ this,
+ "TestSchedulerIdlePeriod",
+ required_quiescence_duration_before_long_idle_period,
+ idle_task_runner) {}
+
+ ~IdleHelperForTest() override = default;
+
+ // IdleHelper::Delegate implementation:
+ MOCK_METHOD2(CanEnterLongIdlePeriod,
+ bool(base::TimeTicks now,
+ base::TimeDelta* next_long_idle_period_delay_out));
+
+ MOCK_METHOD0(IsNotQuiescent, void());
+ MOCK_METHOD0(OnIdlePeriodStarted, void());
+ MOCK_METHOD0(OnIdlePeriodEnded, void());
+ MOCK_METHOD1(OnPendingTasksChanged, void(bool has_tasks));
+};
+
+class BaseIdleHelperTest : public testing::Test {
+ public:
+ BaseIdleHelperTest(
+ std::unique_ptr<base::MessageLoop> message_loop,
+ base::TimeDelta required_quiescence_duration_before_long_idle_period)
+ : message_loop_(std::move(message_loop)),
+ test_task_runner_(base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::TestMockTimeTaskRunner::Type::kStandalone)) {
+ std::unique_ptr<SequenceManager> sequence_manager;
+ if (!message_loop_) {
+ sequence_manager = base::sequence_manager::SequenceManagerForTest::Create(
+ nullptr, test_task_runner_, test_task_runner_->GetMockTickClock());
+ } else {
+ // It's okay to use |test_task_runner_| just as a mock clock because
+ // it isn't bound to thread and all tasks will go through a MessageLoop.
+ sequence_manager = base::sequence_manager::SequenceManagerForTest::Create(
+ message_loop_.get(), message_loop_->task_runner(),
+ test_task_runner_->GetMockTickClock());
+ }
+ sequence_manager_ = sequence_manager.get();
+ scheduler_helper_ = std::make_unique<NonMainThreadSchedulerHelper>(
+ std::move(sequence_manager), nullptr, TaskType::kInternalTest);
+ idle_helper_ = std::make_unique<IdleHelperForTest>(
+ scheduler_helper_.get(),
+ required_quiescence_duration_before_long_idle_period,
+ scheduler_helper_->NewTaskQueue(TaskQueue::Spec("idle_test")));
+ default_task_runner_ = scheduler_helper_->DefaultNonMainThreadTaskQueue();
+ idle_task_runner_ = idle_helper_->IdleTaskRunner();
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMicroseconds(5000));
+ }
+
+ ~BaseIdleHelperTest() override = default;
+
+ void SetUp() override {
+ EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(AnyNumber());
+ EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(AnyNumber());
+ EXPECT_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _))
+ .Times(AnyNumber())
+ .WillRepeatedly(Return(true));
+ EXPECT_CALL(*idle_helper_, OnPendingTasksChanged(_)).Times(AnyNumber());
+ }
+
+ void TearDown() override {
+ EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(AnyNumber());
+ idle_helper_->Shutdown();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
+ }
+
+ SequenceManager* sequence_manager() const { return sequence_manager_; }
+
+ template <typename E>
+ static void CallForEachEnumValue(E first,
+ E last,
+ const char* (*function)(E)) {
+ for (E val = first; val < last;
+ val = static_cast<E>(static_cast<int>(val) + 1)) {
+ (*function)(val);
+ }
+ }
+
+ static void CheckAllTaskQueueIdToString() {
+ CallForEachEnumValue<IdleHelper::IdlePeriodState>(
+ IdleHelper::IdlePeriodState::kFirstIdlePeriodState,
+ IdleHelper::IdlePeriodState::kIdlePeriodStateCount,
+ &IdleHelper::IdlePeriodStateToString);
+ }
+
+ bool IsInIdlePeriod() const {
+ return idle_helper_->IsInIdlePeriod(
+ idle_helper_->SchedulerIdlePeriodState());
+ }
+
+ protected:
+ static base::TimeDelta maximum_idle_period_duration() {
+ return base::TimeDelta::FromMilliseconds(
+ IdleHelper::kMaximumIdlePeriodMillis);
+ }
+
+ static base::TimeDelta retry_enable_long_idle_period_delay() {
+ return base::TimeDelta::FromMilliseconds(
+ IdleHelper::kRetryEnableLongIdlePeriodDelayMillis);
+ }
+
+ static base::TimeDelta minimum_idle_period_duration() {
+ return base::TimeDelta::FromMilliseconds(
+ IdleHelper::kMinimumIdlePeriodDurationMillis);
+ }
+
+ base::TimeTicks CurrentIdleTaskDeadline() {
+ return idle_helper_->CurrentIdleTaskDeadline();
+ }
+
+ void CheckIdlePeriodStateIs(const char* expected) {
+ EXPECT_STREQ(expected, IdleHelper::IdlePeriodStateToString(
+ idle_helper_->SchedulerIdlePeriodState()));
+ }
+
+ const scoped_refptr<TaskQueue>& idle_queue() const {
+ return idle_helper_->idle_queue_;
+ }
+
+ std::unique_ptr<base::MessageLoop> message_loop_;
+ scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_;
+ std::unique_ptr<NonMainThreadSchedulerHelper> scheduler_helper_;
+ SequenceManager* sequence_manager_; // Owned by scheduler_helper_.
+ std::unique_ptr<IdleHelperForTest> idle_helper_;
+ scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
+ scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(BaseIdleHelperTest);
+};
+
+class IdleHelperTest : public BaseIdleHelperTest {
+ public:
+ IdleHelperTest() : BaseIdleHelperTest(nullptr, base::TimeDelta()) {}
+
+ ~IdleHelperTest() override = default;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(IdleHelperTest);
+};
+
+TEST_F(IdleHelperTest, TestPostIdleTask) {
+ int run_count = 0;
+ base::TimeTicks expected_deadline =
+ test_task_runner_->NowTicks() + base::TimeDelta::FromMilliseconds(2300);
+ base::TimeTicks deadline_in_task;
+
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMilliseconds(100));
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
+
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(0, run_count);
+
+ idle_helper_->StartIdlePeriod(IdleHelper::IdlePeriodState::kInShortIdlePeriod,
+ test_task_runner_->NowTicks(),
+ expected_deadline);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_count);
+ EXPECT_EQ(expected_deadline, deadline_in_task);
+}
+
+TEST_F(IdleHelperTest, TestPostIdleTask_EndIdlePeriod) {
+ int run_count = 0;
+ base::TimeTicks deadline_in_task;
+
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMilliseconds(100));
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
+
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(0, run_count);
+
+ idle_helper_->StartIdlePeriod(
+ IdleHelper::IdlePeriodState::kInShortIdlePeriod,
+ test_task_runner_->NowTicks(),
+ test_task_runner_->NowTicks() + base::TimeDelta::FromMilliseconds(10));
+ idle_helper_->EndIdlePeriod();
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(0, run_count);
+}
+
+TEST_F(IdleHelperTest, TestRepostingIdleTask) {
+ base::TimeTicks actual_deadline;
+ int run_count = 0;
+
+ g_max_idle_task_reposts = 2;
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&RepostingIdleTestTask,
+ base::RetainedRef(idle_task_runner_),
+ &run_count, &actual_deadline));
+ idle_helper_->StartIdlePeriod(
+ IdleHelper::IdlePeriodState::kInShortIdlePeriod,
+ test_task_runner_->NowTicks(),
+ test_task_runner_->NowTicks() + base::TimeDelta::FromMilliseconds(10));
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_count);
+
+ // Reposted tasks shouldn't run until next idle period.
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_count);
+
+ idle_helper_->StartIdlePeriod(
+ IdleHelper::IdlePeriodState::kInShortIdlePeriod,
+ test_task_runner_->NowTicks(),
+ test_task_runner_->NowTicks() + base::TimeDelta::FromMilliseconds(10));
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(2, run_count);
+}
+
+TEST_F(IdleHelperTest, TestIdleTaskExceedsDeadline) {
+ int run_count = 0;
+
+ // Post two UpdateClockToDeadlineIdleTestTask tasks.
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&UpdateClockToDeadlineIdleTestTask,
+ test_task_runner_, &run_count));
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&UpdateClockToDeadlineIdleTestTask,
+ test_task_runner_, &run_count));
+
+ idle_helper_->StartIdlePeriod(
+ IdleHelper::IdlePeriodState::kInShortIdlePeriod,
+ test_task_runner_->NowTicks(),
+ test_task_runner_->NowTicks() + base::TimeDelta::FromMilliseconds(10));
+ test_task_runner_->RunUntilIdle();
+ // Only the first idle task should execute since it's used up the deadline.
+ EXPECT_EQ(1, run_count);
+
+ idle_helper_->EndIdlePeriod();
+ idle_helper_->StartIdlePeriod(
+ IdleHelper::IdlePeriodState::kInShortIdlePeriod,
+ test_task_runner_->NowTicks(),
+ test_task_runner_->NowTicks() + base::TimeDelta::FromMilliseconds(10));
+ test_task_runner_->RunUntilIdle();
+ // Second task should be run on the next idle period.
+ EXPECT_EQ(2, run_count);
+}
+
+class IdleHelperTestWithIdlePeriodObserver : public BaseIdleHelperTest {
+ public:
+ IdleHelperTestWithIdlePeriodObserver()
+ : BaseIdleHelperTest(nullptr, base::TimeDelta()) {}
+
+ ~IdleHelperTestWithIdlePeriodObserver() override = default;
+
+ void SetUp() override {
+ EXPECT_CALL(*idle_helper_, OnPendingTasksChanged(_)).Times(AnyNumber());
+ }
+
+ void ExpectIdlePeriodStartsButNeverEnds() {
+ EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(1);
+ EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(0);
+ }
+
+ void ExpectIdlePeriodStartsAndEnds(const testing::Cardinality& cardinality) {
+ EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(cardinality);
+ EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(cardinality);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(IdleHelperTestWithIdlePeriodObserver);
+};
+
+TEST_F(IdleHelperTestWithIdlePeriodObserver, TestEnterButNotExitIdlePeriod) {
+ ExpectIdlePeriodStartsButNeverEnds();
+
+ idle_helper_->StartIdlePeriod(
+ IdleHelper::IdlePeriodState::kInShortIdlePeriod,
+ test_task_runner_->NowTicks(),
+ test_task_runner_->NowTicks() + base::TimeDelta::FromMilliseconds(10));
+}
+
+TEST_F(IdleHelperTestWithIdlePeriodObserver, TestEnterAndExitIdlePeriod) {
+ BaseIdleHelperTest* fixture = this;
+ ON_CALL(*idle_helper_, OnIdlePeriodStarted())
+ .WillByDefault(
+ Invoke([fixture]() { EXPECT_TRUE(fixture->IsInIdlePeriod()); }));
+ ON_CALL(*idle_helper_, OnIdlePeriodEnded()).WillByDefault(Invoke([fixture]() {
+ EXPECT_FALSE(fixture->IsInIdlePeriod());
+ }));
+
+ ExpectIdlePeriodStartsAndEnds(Exactly(1));
+
+ idle_helper_->StartIdlePeriod(
+ IdleHelper::IdlePeriodState::kInShortIdlePeriod,
+ test_task_runner_->NowTicks(),
+ test_task_runner_->NowTicks() + base::TimeDelta::FromMilliseconds(10));
+ idle_helper_->EndIdlePeriod();
+}
+
+class IdleHelperWithMessageLoopTest : public BaseIdleHelperTest {
+ public:
+ IdleHelperWithMessageLoopTest()
+ : BaseIdleHelperTest(std::make_unique<base::MessageLoop>(),
+ base::TimeDelta()) {}
+ ~IdleHelperWithMessageLoopTest() override = default;
+
+ void PostFromNestedRunloop(
+ std::vector<std::pair<SingleThreadIdleTaskRunner::IdleTask, bool>>*
+ tasks) {
+ for (std::pair<SingleThreadIdleTaskRunner::IdleTask, bool>& pair : *tasks) {
+ if (pair.second) {
+ idle_task_runner_->PostIdleTask(FROM_HERE, std::move(pair.first));
+ } else {
+ idle_task_runner_->PostNonNestableIdleTask(FROM_HERE,
+ std::move(pair.first));
+ }
+ }
+ idle_helper_->StartIdlePeriod(
+ IdleHelper::IdlePeriodState::kInShortIdlePeriod,
+ test_task_runner_->NowTicks(),
+ test_task_runner_->NowTicks() + base::TimeDelta::FromMilliseconds(10));
+ base::RunLoop(base::RunLoop::Type::kNestableTasksAllowed).RunUntilIdle();
+ }
+
+ void SetUp() override {
+ EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(AnyNumber());
+ EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(AnyNumber());
+ EXPECT_CALL(*idle_helper_, OnPendingTasksChanged(_)).Times(AnyNumber());
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(IdleHelperWithMessageLoopTest);
+};
+
+TEST_F(IdleHelperWithMessageLoopTest,
+ NonNestableIdleTaskDoesntExecuteInNestedLoop) {
+ std::vector<std::string> order;
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE,
+ base::BindOnce(&AppendToVectorIdleTestTask, &order, std::string("1")));
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE,
+ base::BindOnce(&AppendToVectorIdleTestTask, &order, std::string("2")));
+
+ std::vector<std::pair<SingleThreadIdleTaskRunner::IdleTask, bool>>
+ tasks_to_post_from_nested_loop;
+ tasks_to_post_from_nested_loop.push_back(std::make_pair(
+ base::BindOnce(&AppendToVectorIdleTestTask, &order, std::string("3")),
+ false));
+ tasks_to_post_from_nested_loop.push_back(std::make_pair(
+ base::BindOnce(&AppendToVectorIdleTestTask, &order, std::string("4")),
+ true));
+ tasks_to_post_from_nested_loop.push_back(std::make_pair(
+ base::BindOnce(&AppendToVectorIdleTestTask, &order, std::string("5")),
+ true));
+
+ default_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(&IdleHelperWithMessageLoopTest::PostFromNestedRunloop,
+ base::Unretained(this),
+ base::Unretained(&tasks_to_post_from_nested_loop)));
+
+ idle_helper_->StartIdlePeriod(
+ IdleHelper::IdlePeriodState::kInShortIdlePeriod,
+ test_task_runner_->NowTicks(),
+ test_task_runner_->NowTicks() + base::TimeDelta::FromMilliseconds(10));
+ base::RunLoop().RunUntilIdle();
+ // Note we expect task 3 to run last because it's non-nestable.
+ EXPECT_THAT(order, testing::ElementsAre(std::string("1"), std::string("2"),
+ std::string("4"), std::string("5"),
+ std::string("3")));
+}
+
+TEST_F(IdleHelperTestWithIdlePeriodObserver, TestLongIdlePeriod) {
+ base::TimeTicks expected_deadline =
+ test_task_runner_->NowTicks() + maximum_idle_period_duration();
+ base::TimeTicks deadline_in_task;
+ int run_count = 0;
+
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
+
+ EXPECT_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _))
+ .Times(1)
+ .WillRepeatedly(Return(true));
+ ExpectIdlePeriodStartsButNeverEnds();
+
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(0, run_count); // Shouldn't run yet as no idle period.
+
+ idle_helper_->EnableLongIdlePeriod();
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_count); // Should have run in a long idle time.
+ EXPECT_EQ(expected_deadline, deadline_in_task);
+}
+
+TEST_F(IdleHelperTest, TestLongIdlePeriodWithPendingDelayedTask) {
+ base::TimeDelta pending_task_delay = base::TimeDelta::FromMilliseconds(30);
+ base::TimeTicks expected_deadline =
+ test_task_runner_->NowTicks() + pending_task_delay;
+ base::TimeTicks deadline_in_task;
+ int run_count = 0;
+
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
+ default_task_runner_->PostDelayedTask(FROM_HERE, base::BindOnce(&NullTask),
+ pending_task_delay);
+
+ idle_helper_->EnableLongIdlePeriod();
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_count); // Should have run in a long idle time.
+ EXPECT_EQ(expected_deadline, deadline_in_task);
+}
+
+TEST_F(IdleHelperTest, TestLongIdlePeriodWithLatePendingDelayedTask) {
+ base::TimeDelta pending_task_delay = base::TimeDelta::FromMilliseconds(10);
+ base::TimeTicks deadline_in_task;
+ int run_count = 0;
+
+ default_task_runner_->PostDelayedTask(FROM_HERE, base::BindOnce(&NullTask),
+ pending_task_delay);
+
+ // Advance clock until after delayed task was meant to be run.
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMilliseconds(20));
+
+ // Post an idle task and then EnableLongIdlePeriod. Since there is a late
+ // pending delayed task this shouldn't actually start an idle period.
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
+ idle_helper_->EnableLongIdlePeriod();
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(0, run_count);
+
+ // After the delayed task has been run we should trigger an idle period.
+ test_task_runner_->AdvanceMockTickClock(maximum_idle_period_duration());
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_count);
+}
+
+TEST_F(IdleHelperTestWithIdlePeriodObserver, TestLongIdlePeriodRepeating) {
+ std::vector<base::TimeTicks> actual_deadlines;
+ int run_count = 0;
+
+ EXPECT_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _))
+ .Times(4)
+ .WillRepeatedly(Return(true));
+ ExpectIdlePeriodStartsAndEnds(AtLeast(2));
+
+ g_max_idle_task_reposts = 3;
+ base::TimeTicks clock_before(test_task_runner_->NowTicks());
+ base::TimeDelta idle_task_runtime(base::TimeDelta::FromMilliseconds(10));
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE,
+ base::BindOnce(&RepostingUpdateClockIdleTestTask,
+ base::RetainedRef(idle_task_runner_), &run_count,
+ test_task_runner_, idle_task_runtime, &actual_deadlines));
+
+ // Check each idle task runs in their own idle period.
+ idle_helper_->EnableLongIdlePeriod();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_EQ(3, run_count);
+ EXPECT_THAT(
+ actual_deadlines,
+ testing::ElementsAre(clock_before + maximum_idle_period_duration(),
+ clock_before + 2 * maximum_idle_period_duration(),
+ clock_before + 3 * maximum_idle_period_duration()));
+
+ g_max_idle_task_reposts = 5;
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE,
+ base::BindOnce(&RepostingUpdateClockIdleTestTask,
+ base::RetainedRef(idle_task_runner_), &run_count,
+ test_task_runner_, idle_task_runtime, &actual_deadlines));
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&EndIdlePeriodIdleTask,
+ base::Unretained(idle_helper_.get())));
+
+ // Ensure that reposting tasks stop after EndIdlePeriod is called.
+ test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_EQ(4, run_count);
+}
+
+TEST_F(IdleHelperTestWithIdlePeriodObserver,
+ TestLongIdlePeriodWhenNotCanEnterLongIdlePeriod) {
+ base::TimeDelta delay = base::TimeDelta::FromMilliseconds(1000);
+ base::TimeDelta half_delay = base::TimeDelta::FromMilliseconds(500);
+ base::TimeTicks delay_over = test_task_runner_->NowTicks() + delay;
+ base::TimeTicks deadline_in_task;
+ int run_count = 0;
+
+ ON_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _))
+ .WillByDefault(
+ Invoke([delay, delay_over](
+ base::TimeTicks now,
+ base::TimeDelta* next_long_idle_period_delay_out) {
+ if (now >= delay_over)
+ return true;
+ *next_long_idle_period_delay_out = delay;
+ return false;
+ }));
+
+ EXPECT_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _)).Times(2);
+ EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(AnyNumber());
+
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
+
+ // Make sure Idle tasks don't run until the delay has occurred.
+ idle_helper_->EnableLongIdlePeriod();
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(0, run_count);
+
+ test_task_runner_->AdvanceMockTickClock(half_delay);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(0, run_count);
+
+ // Delay is finished, idle task should run.
+ test_task_runner_->AdvanceMockTickClock(half_delay);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_count);
+}
+
+TEST_F(IdleHelperTest,
+ TestLongIdlePeriodDoesNotImmediatelyRestartIfMaxDeadline) {
+ std::vector<base::TimeTicks> actual_deadlines;
+ int run_count = 0;
+
+ base::TimeTicks clock_before(test_task_runner_->NowTicks());
+ base::TimeDelta idle_task_runtime(base::TimeDelta::FromMilliseconds(10));
+
+ // The second idle period should happen immediately after the first the
+ // they have max deadlines.
+ g_max_idle_task_reposts = 2;
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE,
+ base::BindOnce(&RepostingUpdateClockIdleTestTask,
+ base::RetainedRef(idle_task_runner_), &run_count,
+ test_task_runner_, idle_task_runtime, &actual_deadlines));
+
+ idle_helper_->EnableLongIdlePeriod();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_EQ(2, run_count);
+ EXPECT_THAT(
+ actual_deadlines,
+ testing::ElementsAre(clock_before + maximum_idle_period_duration(),
+ clock_before + 2 * maximum_idle_period_duration()));
+}
+
+TEST_F(IdleHelperTest, TestLongIdlePeriodRestartWaitsIfNotMaxDeadline) {
+ base::TimeTicks actual_deadline;
+ int run_count = 0;
+
+ base::TimeDelta pending_task_delay(base::TimeDelta::FromMilliseconds(20));
+ base::TimeDelta idle_task_duration(base::TimeDelta::FromMilliseconds(10));
+ base::TimeTicks expected_deadline(
+ test_task_runner_->NowTicks() + pending_task_delay +
+ maximum_idle_period_duration() + retry_enable_long_idle_period_delay());
+
+ // Post delayed task to ensure idle period doesn't have a max deadline.
+ default_task_runner_->PostDelayedTask(FROM_HERE, base::BindOnce(&NullTask),
+ pending_task_delay);
+
+ g_max_idle_task_reposts = 2;
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&RepostingIdleTestTask,
+ base::RetainedRef(idle_task_runner_),
+ &run_count, &actual_deadline));
+ idle_helper_->EnableLongIdlePeriod();
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_count);
+ test_task_runner_->AdvanceMockTickClock(idle_task_duration);
+
+ // Next idle period shouldn't happen until the pending task has been run.
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_count);
+
+ // Once the pending task is run the new idle period should start.
+ test_task_runner_->AdvanceMockTickClock(pending_task_delay -
+ idle_task_duration);
+
+ // Since the idle period tried to start before the pending task ran we have to
+ // wait for the idle helper to retry starting the long idle period.
+ test_task_runner_->AdvanceMockTickClock(
+ retry_enable_long_idle_period_delay());
+ test_task_runner_->RunUntilIdle();
+
+ EXPECT_EQ(2, run_count);
+ EXPECT_EQ(expected_deadline, actual_deadline);
+}
+
+TEST_F(IdleHelperTest, TestLongIdlePeriodPaused) {
+ std::vector<base::TimeTicks> actual_deadlines;
+ int run_count = 0;
+
+ // If there are no idle tasks posted we should start in the paused state.
+ idle_helper_->EnableLongIdlePeriod();
+ CheckIdlePeriodStateIs("in_long_idle_period_paused");
+ // There shouldn't be any delayed tasks posted by the idle helper when paused.
+ base::sequence_manager::LazyNow lazy_now_1(
+ test_task_runner_->GetMockTickClock());
+ EXPECT_FALSE(
+ scheduler_helper_->real_time_domain()->DelayTillNextTask(&lazy_now_1));
+
+ // Posting a task should transition us to the an active state.
+ g_max_idle_task_reposts = 2;
+ base::TimeTicks clock_before(test_task_runner_->NowTicks());
+ base::TimeDelta idle_task_runtime(base::TimeDelta::FromMilliseconds(10));
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE,
+ base::BindOnce(&RepostingUpdateClockIdleTestTask,
+ base::RetainedRef(idle_task_runner_), &run_count,
+ test_task_runner_, idle_task_runtime, &actual_deadlines));
+ test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_EQ(2, run_count);
+ EXPECT_THAT(
+ actual_deadlines,
+ testing::ElementsAre(clock_before + maximum_idle_period_duration(),
+ clock_before + 2 * maximum_idle_period_duration()));
+
+ // Once all task have been run we should go back to the paused state.
+ CheckIdlePeriodStateIs("in_long_idle_period_paused");
+ base::sequence_manager::LazyNow lazy_now_2(
+ test_task_runner_->GetMockTickClock());
+ EXPECT_FALSE(
+ scheduler_helper_->real_time_domain()->DelayTillNextTask(&lazy_now_2));
+
+ idle_helper_->EndIdlePeriod();
+ CheckIdlePeriodStateIs("not_in_idle_period");
+}
+
+TEST_F(IdleHelperTest, TestLongIdlePeriodWhenShutdown) {
+ base::TimeTicks deadline_in_task;
+ int run_count = 0;
+
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
+ idle_helper_->Shutdown();
+
+ // We shouldn't be able to enter a long idle period when shutdown
+ idle_helper_->EnableLongIdlePeriod();
+ test_task_runner_->RunUntilIdle();
+ CheckIdlePeriodStateIs("not_in_idle_period");
+ EXPECT_EQ(0, run_count);
+}
+
+void TestCanExceedIdleDeadlineIfRequiredTask(IdleHelperForTest* idle_helper,
+ bool* can_exceed_idle_deadline_out,
+ int* run_count,
+ base::TimeTicks deadline) {
+ *can_exceed_idle_deadline_out =
+ idle_helper->CanExceedIdleDeadlineIfRequired();
+ (*run_count)++;
+}
+
+TEST_F(IdleHelperTest, CanExceedIdleDeadlineIfRequired) {
+ int run_count = 0;
+ bool can_exceed_idle_deadline = false;
+
+ // Should return false if not in an idle period.
+ EXPECT_FALSE(idle_helper_->CanExceedIdleDeadlineIfRequired());
+
+ // Should return false for short idle periods.
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&TestCanExceedIdleDeadlineIfRequiredTask,
+ idle_helper_.get(), &can_exceed_idle_deadline,
+ &run_count));
+ idle_helper_->StartIdlePeriod(
+ IdleHelper::IdlePeriodState::kInShortIdlePeriod,
+ test_task_runner_->NowTicks(),
+ test_task_runner_->NowTicks() + base::TimeDelta::FromMilliseconds(10));
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_count);
+ EXPECT_FALSE(can_exceed_idle_deadline);
+
+ // Should return false for a long idle period which is shortened due to a
+ // pending delayed task.
+ default_task_runner_->PostDelayedTask(FROM_HERE, base::BindOnce(&NullTask),
+ base::TimeDelta::FromMilliseconds(10));
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&TestCanExceedIdleDeadlineIfRequiredTask,
+ idle_helper_.get(), &can_exceed_idle_deadline,
+ &run_count));
+ idle_helper_->EnableLongIdlePeriod();
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(2, run_count);
+ EXPECT_FALSE(can_exceed_idle_deadline);
+
+ // Next long idle period will be for the maximum time, so
+ // CanExceedIdleDeadlineIfRequired should return true.
+ test_task_runner_->AdvanceMockTickClock(maximum_idle_period_duration());
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&TestCanExceedIdleDeadlineIfRequiredTask,
+ idle_helper_.get(), &can_exceed_idle_deadline,
+ &run_count));
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(3, run_count);
+ EXPECT_TRUE(can_exceed_idle_deadline);
+}
+
+class IdleHelperWithQuiescencePeriodTest : public BaseIdleHelperTest {
+ public:
+ enum {
+ kQuiescenceDelayMs = 100,
+ kLongIdlePeriodMs = 50,
+ };
+
+ IdleHelperWithQuiescencePeriodTest()
+ : BaseIdleHelperTest(
+ nullptr,
+ base::TimeDelta::FromMilliseconds(kQuiescenceDelayMs)) {}
+
+ ~IdleHelperWithQuiescencePeriodTest() override = default;
+
+ void SetUp() override {
+ EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(AnyNumber());
+ EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(AnyNumber());
+ EXPECT_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _))
+ .Times(AnyNumber())
+ .WillRepeatedly(Return(true));
+ EXPECT_CALL(*idle_helper_, IsNotQuiescent()).Times(AnyNumber());
+ EXPECT_CALL(*idle_helper_, OnPendingTasksChanged(_)).Times(AnyNumber());
+ }
+
+ void MakeNonQuiescent() {
+ // Run an arbitrary task so we're deemed to be not quiescent.
+ default_task_runner_->PostTask(FROM_HERE, base::BindOnce(NullTask));
+ test_task_runner_->RunUntilIdle();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(IdleHelperWithQuiescencePeriodTest);
+};
+
+class IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver
+ : public IdleHelperWithQuiescencePeriodTest {
+ public:
+ IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver()
+ : IdleHelperWithQuiescencePeriodTest() {}
+
+ ~IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver() override =
+ default;
+
+ void SetUp() override {
+ EXPECT_CALL(*idle_helper_, OnPendingTasksChanged(_)).Times(AnyNumber());
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(
+ IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver);
+};
+
+TEST_F(IdleHelperWithQuiescencePeriodTest,
+ LongIdlePeriodStartsImmediatelyIfQuiescent) {
+ base::TimeTicks actual_deadline;
+ int run_count = 0;
+ g_max_idle_task_reposts = 1;
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&RepostingIdleTestTask,
+ base::RetainedRef(idle_task_runner_),
+ &run_count, &actual_deadline));
+
+ idle_helper_->EnableLongIdlePeriod();
+ test_task_runner_->RunUntilIdle();
+
+ EXPECT_EQ(1, run_count);
+}
+
+TEST_F(IdleHelperWithQuiescencePeriodTestWithIdlePeriodObserver,
+ LongIdlePeriodDoesNotStartsImmediatelyIfBusy) {
+ MakeNonQuiescent();
+ EXPECT_CALL(*idle_helper_, OnIdlePeriodStarted()).Times(0);
+ EXPECT_CALL(*idle_helper_, OnIdlePeriodEnded()).Times(0);
+ EXPECT_CALL(*idle_helper_, CanEnterLongIdlePeriod(_, _)).Times(0);
+ EXPECT_CALL(*idle_helper_, IsNotQuiescent()).Times(AtLeast(1));
+
+ base::TimeTicks actual_deadline;
+ int run_count = 0;
+ g_max_idle_task_reposts = 1;
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&RepostingIdleTestTask,
+ base::RetainedRef(idle_task_runner_),
+ &run_count, &actual_deadline));
+
+ idle_helper_->EnableLongIdlePeriod();
+ test_task_runner_->RunUntilIdle();
+
+ EXPECT_EQ(0, run_count);
+
+ scheduler_helper_->Shutdown();
+}
+
+TEST_F(IdleHelperWithQuiescencePeriodTest,
+ LongIdlePeriodStartsAfterQuiescence) {
+ MakeNonQuiescent();
+
+ // Run a repeating task so we're deemed to be busy for the next 400ms.
+ default_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&RepeatingTask,
+ base::Unretained(default_task_runner_.get()),
+ 10, base::TimeDelta::FromMilliseconds(40)));
+
+ int run_count = 0;
+ // In this scenario EnableLongIdlePeriod deems us not to be quiescent 5x in
+ // a row.
+ base::TimeTicks expected_deadline =
+ test_task_runner_->NowTicks() +
+ base::TimeDelta::FromMilliseconds(5 * kQuiescenceDelayMs +
+ kLongIdlePeriodMs);
+ base::TimeTicks deadline_in_task;
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
+
+ idle_helper_->EnableLongIdlePeriod();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_EQ(1, run_count);
+ EXPECT_EQ(expected_deadline, deadline_in_task);
+}
+
+TEST_F(IdleHelperWithQuiescencePeriodTest,
+ QuescienceCheckedForAfterLongIdlePeriodEnds) {
+ idle_task_runner_->PostIdleTask(FROM_HERE, base::BindOnce(&NullIdleTask));
+ idle_helper_->EnableLongIdlePeriod();
+ test_task_runner_->RunUntilIdle();
+
+ // Post a normal task to make the scheduler non-quiescent.
+ default_task_runner_->PostTask(FROM_HERE, base::BindOnce(&NullTask));
+ test_task_runner_->RunUntilIdle();
+
+ // Post an idle task. The idle task won't run initially because the system is
+ // not judged to be quiescent, but should be run after the quiescence delay.
+ int run_count = 0;
+ base::TimeTicks deadline_in_task;
+ base::TimeTicks expected_deadline =
+ test_task_runner_->NowTicks() +
+ base::TimeDelta::FromMilliseconds(kQuiescenceDelayMs + kLongIdlePeriodMs);
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
+ idle_helper_->EnableLongIdlePeriod();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
+
+ EXPECT_EQ(1, run_count);
+ EXPECT_EQ(expected_deadline, deadline_in_task);
+}
+
+TEST_F(IdleHelperTest, NoShortIdlePeriodWhenDeadlineTooClose) {
+ int run_count = 0;
+ base::TimeTicks deadline_in_task;
+
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
+
+ base::TimeDelta half_a_ms(base::TimeDelta::FromMicroseconds(50));
+ base::TimeTicks less_than_min_deadline(test_task_runner_->NowTicks() +
+ minimum_idle_period_duration() -
+ half_a_ms);
+ base::TimeTicks more_than_min_deadline(test_task_runner_->NowTicks() +
+ minimum_idle_period_duration() +
+ half_a_ms);
+
+ idle_helper_->StartIdlePeriod(IdleHelper::IdlePeriodState::kInShortIdlePeriod,
+ test_task_runner_->NowTicks(),
+ less_than_min_deadline);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(0, run_count);
+
+ idle_helper_->StartIdlePeriod(IdleHelper::IdlePeriodState::kInShortIdlePeriod,
+ test_task_runner_->NowTicks(),
+ more_than_min_deadline);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_count);
+}
+
+TEST_F(IdleHelperTest, NoLongIdlePeriodWhenDeadlineTooClose) {
+ int run_count = 0;
+ base::TimeTicks deadline_in_task;
+
+ base::TimeDelta half_a_ms(base::TimeDelta::FromMicroseconds(50));
+ base::TimeDelta less_than_min_deadline_duration(
+ minimum_idle_period_duration() - half_a_ms);
+ base::TimeDelta more_than_min_deadline_duration(
+ minimum_idle_period_duration() + half_a_ms);
+
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
+ default_task_runner_->PostDelayedTask(FROM_HERE, base::BindOnce(&NullTask),
+ less_than_min_deadline_duration);
+
+ idle_helper_->EnableLongIdlePeriod();
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(0, run_count);
+
+ idle_helper_->EndIdlePeriod();
+ test_task_runner_->AdvanceMockTickClock(maximum_idle_period_duration());
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(0, run_count);
+
+ default_task_runner_->PostDelayedTask(FROM_HERE, base::BindOnce(&NullTask),
+ more_than_min_deadline_duration);
+ idle_helper_->EnableLongIdlePeriod();
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_count);
+}
+
+TEST_F(IdleHelperWithQuiescencePeriodTest,
+ PendingEnableLongIdlePeriodNotRunAfterShutdown) {
+ MakeNonQuiescent();
+
+ bool shutdown_task_run = false;
+ int run_count = 0;
+ base::TimeTicks deadline_in_task;
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE,
+ base::BindOnce(&ShutdownIdleTask, base::Unretained(idle_helper_.get()),
+ &shutdown_task_run));
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
+
+ // Delayed call to IdleHelper::EnableLongIdlePeriod enables idle tasks.
+ idle_helper_->EnableLongIdlePeriod();
+ test_task_runner_->AdvanceMockTickClock(maximum_idle_period_duration() * 2.0);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_TRUE(shutdown_task_run);
+ EXPECT_EQ(0, run_count);
+
+ // Shutdown immediately after idle period started should prevent the idle
+ // task from running.
+ idle_helper_->Shutdown();
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(0, run_count);
+}
+
+TEST_F(IdleHelperTest, TestPostDelayedIdleTask) {
+ int run_count = 0;
+ base::TimeTicks expected_deadline =
+ test_task_runner_->NowTicks() + base::TimeDelta::FromMilliseconds(2300);
+ base::TimeTicks deadline_in_task;
+
+ // Posting a delayed idle task should not post anything on the underlying
+ // task queue until the delay is up.
+ idle_task_runner_->PostDelayedIdleTask(
+ FROM_HERE, base::TimeDelta::FromMilliseconds(200),
+ base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
+ EXPECT_EQ(0u, idle_queue()->GetNumberOfPendingTasks());
+
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMilliseconds(100));
+
+ // It shouldn't run until the delay is over even though we went idle.
+ idle_helper_->StartIdlePeriod(IdleHelper::IdlePeriodState::kInShortIdlePeriod,
+ test_task_runner_->NowTicks(),
+ expected_deadline);
+ EXPECT_EQ(0u, idle_queue()->GetNumberOfPendingTasks());
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(0, run_count);
+
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMilliseconds(100));
+ idle_helper_->StartIdlePeriod(IdleHelper::IdlePeriodState::kInShortIdlePeriod,
+ test_task_runner_->NowTicks(),
+ expected_deadline);
+ EXPECT_EQ(1u, idle_queue()->GetNumberOfPendingTasks());
+ test_task_runner_->RunUntilIdle();
+
+ EXPECT_EQ(1, run_count);
+ EXPECT_EQ(expected_deadline, deadline_in_task);
+}
+
+// Tests that the OnPendingTasksChanged callback is called once when the idle
+// queue becomes non-empty and again when it becomes empty.
+TEST_F(IdleHelperTest, OnPendingTasksChanged) {
+ int run_count = 0;
+ base::TimeTicks expected_deadline =
+ test_task_runner_->NowTicks() + base::TimeDelta::FromMilliseconds(2300);
+ base::TimeTicks deadline_in_task;
+
+ {
+ testing::InSequence dummy;
+ // This will be called once. I.e when the one and only task is posted.
+ EXPECT_CALL(*idle_helper_, OnPendingTasksChanged(true)).Times(1);
+ // This will be called once. I.e when the one and only task completes.
+ EXPECT_CALL(*idle_helper_, OnPendingTasksChanged(false)).Times(1);
+ }
+
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMilliseconds(100));
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
+
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(0, run_count);
+
+ idle_helper_->StartIdlePeriod(IdleHelper::IdlePeriodState::kInShortIdlePeriod,
+ test_task_runner_->NowTicks(),
+ expected_deadline);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(1, run_count);
+ EXPECT_EQ(expected_deadline, deadline_in_task);
+}
+
+// Tests that the OnPendingTasksChanged callback is still only called once
+// with false despite there being two idle tasks posted.
+TEST_F(IdleHelperTest, OnPendingTasksChanged_TwoTasksAtTheSameTime) {
+ int run_count = 0;
+ base::TimeTicks expected_deadline =
+ test_task_runner_->NowTicks() + base::TimeDelta::FromMilliseconds(2300);
+ base::TimeTicks deadline_in_task;
+
+ {
+ testing::InSequence dummy;
+ // This will be called 3 times. I.e when T1 and T2 are posted and when T1
+ // completes.
+ EXPECT_CALL(*idle_helper_, OnPendingTasksChanged(true)).Times(3);
+ // This will be called once. I.e when T2 completes.
+ EXPECT_CALL(*idle_helper_, OnPendingTasksChanged(false)).Times(1);
+ }
+
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMilliseconds(100));
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
+ idle_task_runner_->PostIdleTask(
+ FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
+
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(0, run_count);
+
+ idle_helper_->StartIdlePeriod(IdleHelper::IdlePeriodState::kInShortIdlePeriod,
+ test_task_runner_->NowTicks(),
+ expected_deadline);
+ test_task_runner_->RunUntilIdle();
+ EXPECT_EQ(2, run_count);
+ EXPECT_EQ(expected_deadline, deadline_in_task);
+}
+
+} // namespace idle_helper_unittest
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.cc
new file mode 100644
index 00000000000..7a802b74f53
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.cc
@@ -0,0 +1,97 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/common/metrics_helper.h"
+
+#include "third_party/blink/renderer/platform/scheduler/child/process_state.h"
+
+namespace blink {
+namespace scheduler {
+
+namespace {
+
+// Threshold for discarding ultra-long tasks. It is assumed that ultra-long
+// tasks are reporting glitches (e.g. system falling asleep on the middle of the
+// task).
+constexpr base::TimeDelta kLongTaskDiscardingThreshold =
+ base::TimeDelta::FromSeconds(30);
+
+} // namespace
+
+MetricsHelper::MetricsHelper(WebThreadType thread_type,
+ bool has_cpu_timing_for_each_task)
+ : thread_type_(thread_type),
+ has_cpu_timing_for_each_task_(has_cpu_timing_for_each_task),
+ last_known_time_(has_cpu_timing_for_each_task_ ? base::ThreadTicks::Now()
+ : base::ThreadTicks()),
+ thread_task_duration_reporter_(
+ "RendererScheduler.TaskDurationPerThreadType2"),
+ thread_task_cpu_duration_reporter_(
+ "RendererScheduler.TaskCPUDurationPerThreadType2"),
+ foreground_thread_task_duration_reporter_(
+ "RendererScheduler.TaskDurationPerThreadType2.Foreground"),
+ foreground_thread_task_cpu_duration_reporter_(
+ "RendererScheduler.TaskCPUDurationPerThreadType2.Foreground"),
+ background_thread_task_duration_reporter_(
+ "RendererScheduler.TaskDurationPerThreadType2.Background"),
+ background_thread_task_cpu_duration_reporter_(
+ "RendererScheduler.TaskCPUDurationPerThreadType2.Background"),
+ tracked_cpu_duration_reporter_(
+ "Scheduler.Experimental.Renderer.CPUTimePerThread.Tracked"),
+ non_tracked_cpu_duration_reporter_(
+ "Scheduler.Experimental.Renderer.CPUTimePerThread.Untracked") {}
+
+MetricsHelper::~MetricsHelper() {}
+
+bool MetricsHelper::ShouldDiscardTask(
+ base::sequence_manager::TaskQueue* queue,
+ const base::sequence_manager::TaskQueue::Task& task,
+ const base::sequence_manager::TaskQueue::TaskTiming& task_timing) {
+ // TODO(altimin): Investigate the relationship between thread time and
+ // wall time for discarded tasks.
+ return task_timing.wall_duration() > kLongTaskDiscardingThreshold;
+}
+
+void MetricsHelper::RecordCommonTaskMetrics(
+ base::sequence_manager::TaskQueue* queue,
+ const base::sequence_manager::TaskQueue::Task& task,
+ const base::sequence_manager::TaskQueue::TaskTiming& task_timing) {
+ DCHECK(!has_cpu_timing_for_each_task_ || task_timing.has_thread_time());
+ thread_task_duration_reporter_.RecordTask(thread_type_,
+ task_timing.wall_duration());
+
+ bool backgrounded = internal::ProcessState::Get()->is_process_backgrounded;
+
+ if (backgrounded) {
+ background_thread_task_duration_reporter_.RecordTask(
+ thread_type_, task_timing.wall_duration());
+ } else {
+ foreground_thread_task_duration_reporter_.RecordTask(
+ thread_type_, task_timing.wall_duration());
+ }
+
+ if (!task_timing.has_thread_time())
+ return;
+ thread_task_cpu_duration_reporter_.RecordTask(thread_type_,
+ task_timing.thread_duration());
+ if (backgrounded) {
+ background_thread_task_cpu_duration_reporter_.RecordTask(
+ thread_type_, task_timing.thread_duration());
+ } else {
+ foreground_thread_task_cpu_duration_reporter_.RecordTask(
+ thread_type_, task_timing.thread_duration());
+ }
+
+ if (has_cpu_timing_for_each_task_) {
+ non_tracked_cpu_duration_reporter_.RecordTask(
+ thread_type_, task_timing.start_thread_time() - last_known_time_);
+ tracked_cpu_duration_reporter_.RecordTask(thread_type_,
+ task_timing.thread_duration());
+
+ last_known_time_ = task_timing.end_thread_time();
+ }
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.h
new file mode 100644
index 00000000000..643523250ef
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper.h
@@ -0,0 +1,77 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_METRICS_HELPER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_METRICS_HELPER_H_
+
+#include "base/optional.h"
+#include "base/task/sequence_manager/task_queue.h"
+#include "base/time/time.h"
+#include "third_party/blink/public/platform/web_thread_type.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/scheduler/common/total_duration_metric_reporter.h"
+#include "third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter.h"
+
+namespace base {
+namespace sequence_manager {
+class TaskQueue;
+}
+} // namespace base
+
+namespace blink {
+namespace scheduler {
+
+// Helper class to take care of task metrics shared between main thread
+// and worker threads of the renderer process, including per-thread
+// task metrics.
+//
+// Each thread-specific scheduler should have its own subclass of MetricsHelper
+// (MainThreadMetricsHelper, WorkerMetricsHelper, etc) and should call
+// RecordCommonTaskMetrics manually.
+// Note that this is code reuse, not data reuse -- each thread should have its
+// own instantiation of this class.
+class PLATFORM_EXPORT MetricsHelper {
+ public:
+ MetricsHelper(WebThreadType thread_type, bool has_cpu_timing_for_each_task);
+ ~MetricsHelper();
+
+ protected:
+ bool ShouldDiscardTask(
+ base::sequence_manager::TaskQueue* queue,
+ const base::sequence_manager::TaskQueue::Task& task,
+ const base::sequence_manager::TaskQueue::TaskTiming& task_timing);
+
+ // Record task metrics which are shared between threads.
+ void RecordCommonTaskMetrics(
+ base::sequence_manager::TaskQueue* queue,
+ const base::sequence_manager::TaskQueue::Task& task,
+ const base::sequence_manager::TaskQueue::TaskTiming& task_timing);
+
+ protected:
+ const WebThreadType thread_type_;
+ const bool has_cpu_timing_for_each_task_;
+
+ private:
+ base::ThreadTicks last_known_time_;
+
+ TaskDurationMetricReporter<WebThreadType> thread_task_duration_reporter_;
+ TaskDurationMetricReporter<WebThreadType> thread_task_cpu_duration_reporter_;
+ TaskDurationMetricReporter<WebThreadType>
+ foreground_thread_task_duration_reporter_;
+ TaskDurationMetricReporter<WebThreadType>
+ foreground_thread_task_cpu_duration_reporter_;
+ TaskDurationMetricReporter<WebThreadType>
+ background_thread_task_duration_reporter_;
+ TaskDurationMetricReporter<WebThreadType>
+ background_thread_task_cpu_duration_reporter_;
+ TaskDurationMetricReporter<WebThreadType> tracked_cpu_duration_reporter_;
+ TaskDurationMetricReporter<WebThreadType> non_tracked_cpu_duration_reporter_;
+
+ DISALLOW_COPY_AND_ASSIGN(MetricsHelper);
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_METRICS_HELPER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper_unittest.cc
new file mode 100644
index 00000000000..8fec7193d4e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/metrics_helper_unittest.cc
@@ -0,0 +1,118 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/common/metrics_helper.h"
+
+#include "base/task/sequence_manager/test/fake_task.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/time/time_override.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::sequence_manager::TaskQueue;
+
+namespace blink {
+namespace scheduler {
+
+namespace {
+
+using base::sequence_manager::FakeTask;
+using base::sequence_manager::FakeTaskTiming;
+
+class MetricsHelperForTest : public MetricsHelper {
+ public:
+ MetricsHelperForTest(WebThreadType thread_type,
+ bool has_cpu_timing_for_each_task)
+ : MetricsHelper(thread_type, has_cpu_timing_for_each_task) {}
+ ~MetricsHelperForTest() = default;
+
+ using MetricsHelper::RecordCommonTaskMetrics;
+};
+
+base::TimeTicks Seconds(int seconds) {
+ return base::TimeTicks() + base::TimeDelta::FromSeconds(seconds);
+}
+
+base::ThreadTicks ThreadSeconds(int seconds) {
+ return base::ThreadTicks() + base::TimeDelta::FromSeconds(seconds);
+}
+
+} // namespace
+
+TEST(MetricsHelperTest, TaskDurationPerThreadType) {
+ base::HistogramTester histogram_tester;
+
+ MetricsHelperForTest main_thread_metrics(
+ WebThreadType::kMainThread, false /* has_cpu_timing_for_each_task */);
+ MetricsHelperForTest compositor_metrics(
+ WebThreadType::kCompositorThread,
+ false /* has_cpu_timing_for_each_task */);
+ MetricsHelperForTest worker_metrics(WebThreadType::kUnspecifiedWorkerThread,
+ false /* has_cpu_timing_for_each_task */);
+
+ main_thread_metrics.RecordCommonTaskMetrics(
+ nullptr, FakeTask(),
+ FakeTaskTiming(Seconds(10), Seconds(50), ThreadSeconds(0),
+ ThreadSeconds(15)));
+ compositor_metrics.RecordCommonTaskMetrics(
+ nullptr, FakeTask(),
+ FakeTaskTiming(Seconds(10), Seconds(80), ThreadSeconds(0),
+ ThreadSeconds(5)));
+ compositor_metrics.RecordCommonTaskMetrics(
+ nullptr, FakeTask(), FakeTaskTiming(Seconds(100), Seconds(200)));
+ worker_metrics.RecordCommonTaskMetrics(
+ nullptr, FakeTask(),
+ FakeTaskTiming(Seconds(10), Seconds(125), ThreadSeconds(0),
+ ThreadSeconds(25)));
+
+ EXPECT_THAT(
+ histogram_tester.GetAllSamples(
+ "RendererScheduler.TaskDurationPerThreadType2"),
+ testing::UnorderedElementsAre(
+ base::Bucket(static_cast<int>(WebThreadType::kMainThread), 40),
+ base::Bucket(static_cast<int>(WebThreadType::kCompositorThread), 170),
+ base::Bucket(
+ static_cast<int>(WebThreadType::kUnspecifiedWorkerThread), 115)));
+
+ EXPECT_THAT(
+ histogram_tester.GetAllSamples(
+ "RendererScheduler.TaskCPUDurationPerThreadType2"),
+ testing::UnorderedElementsAre(
+ base::Bucket(static_cast<int>(WebThreadType::kMainThread), 15),
+ base::Bucket(static_cast<int>(WebThreadType::kCompositorThread), 5),
+ base::Bucket(
+ static_cast<int>(WebThreadType::kUnspecifiedWorkerThread), 25)));
+}
+
+TEST(MetricsHelperTest, TrackedCPUTimeMetrics) {
+ base::HistogramTester histogram_tester;
+ base::subtle::ScopedTimeClockOverrides time_override(
+ []() { return base::Time(); }, []() { return Seconds(1); },
+ []() { return ThreadSeconds(1); });
+
+ MetricsHelperForTest main_thread_metrics(
+ WebThreadType::kMainThread, true /* has_cpu_timing_for_each_task */);
+
+ main_thread_metrics.RecordCommonTaskMetrics(
+ nullptr, FakeTask(),
+ FakeTaskTiming(Seconds(10), Seconds(50), ThreadSeconds(5),
+ ThreadSeconds(15)));
+ main_thread_metrics.RecordCommonTaskMetrics(
+ nullptr, FakeTask(),
+ FakeTaskTiming(Seconds(10), Seconds(50), ThreadSeconds(20),
+ ThreadSeconds(25)));
+
+ EXPECT_THAT(histogram_tester.GetAllSamples(
+ "Scheduler.Experimental.Renderer.CPUTimePerThread.Tracked"),
+ testing::UnorderedElementsAre(base::Bucket(
+ static_cast<int>(WebThreadType::kMainThread), 15)));
+ // 9 = 4 seconds before task 1 and 5 seconds between tasks 1 and 2.
+ EXPECT_THAT(histogram_tester.GetAllSamples(
+ "Scheduler.Experimental.Renderer.CPUTimePerThread.Untracked"),
+ testing::UnorderedElementsAre(base::Bucket(
+ static_cast<int>(WebThreadType::kMainThread), 9)));
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc
index 15206469d37..dc58a367443 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.cc
@@ -6,25 +6,24 @@
#include <utility>
+#include "base/task/sequence_manager/task_queue.h"
#include "base/time/default_tick_clock.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_argument.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
#include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
namespace blink {
namespace scheduler {
-using base::sequence_manager::RealTimeDomain;
using base::sequence_manager::TaskQueue;
-using base::sequence_manager::TaskQueueManager;
+using base::sequence_manager::SequenceManager;
using base::sequence_manager::TaskTimeObserver;
using base::sequence_manager::TimeDomain;
SchedulerHelper::SchedulerHelper(
- std::unique_ptr<TaskQueueManager> task_queue_manager)
- : task_queue_manager_(std::move(task_queue_manager)), observer_(nullptr) {
- task_queue_manager_->SetWorkBatchSize(4);
+ std::unique_ptr<SequenceManager> sequence_manager)
+ : sequence_manager_(std::move(sequence_manager)), observer_(nullptr) {
+ sequence_manager_->SetWorkBatchSize(4);
}
void SchedulerHelper::InitDefaultQueues(
@@ -33,9 +32,11 @@ void SchedulerHelper::InitDefaultQueues(
TaskType default_task_type) {
control_task_queue->SetQueuePriority(TaskQueue::kControlPriority);
- DCHECK(task_queue_manager_);
- task_queue_manager_->SetDefaultTaskRunner(
- TaskQueueWithTaskType::Create(default_task_queue, default_task_type));
+ default_task_runner_ =
+ TaskQueueWithTaskType::Create(default_task_queue, default_task_type);
+
+ DCHECK(sequence_manager_);
+ sequence_manager_->SetDefaultTaskRunner(default_task_runner_);
}
SchedulerHelper::~SchedulerHelper() {
@@ -44,79 +45,84 @@ SchedulerHelper::~SchedulerHelper() {
void SchedulerHelper::Shutdown() {
CheckOnValidThread();
- if (!task_queue_manager_)
+ if (!sequence_manager_)
return;
- task_queue_manager_->SetObserver(nullptr);
- task_queue_manager_.reset();
+ sequence_manager_->SetObserver(nullptr);
+ sequence_manager_.reset();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+SchedulerHelper::DefaultTaskRunner() {
+ return default_task_runner_;
}
void SchedulerHelper::SetWorkBatchSizeForTesting(size_t work_batch_size) {
CheckOnValidThread();
- DCHECK(task_queue_manager_.get());
- task_queue_manager_->SetWorkBatchSize(work_batch_size);
+ DCHECK(sequence_manager_.get());
+ sequence_manager_->SetWorkBatchSize(work_batch_size);
}
bool SchedulerHelper::GetAndClearSystemIsQuiescentBit() {
CheckOnValidThread();
- DCHECK(task_queue_manager_.get());
- return task_queue_manager_->GetAndClearSystemIsQuiescentBit();
+ DCHECK(sequence_manager_.get());
+ return sequence_manager_->GetAndClearSystemIsQuiescentBit();
}
void SchedulerHelper::AddTaskObserver(
base::MessageLoop::TaskObserver* task_observer) {
CheckOnValidThread();
- if (task_queue_manager_)
- task_queue_manager_->AddTaskObserver(task_observer);
+ if (sequence_manager_)
+ sequence_manager_->AddTaskObserver(task_observer);
}
void SchedulerHelper::RemoveTaskObserver(
base::MessageLoop::TaskObserver* task_observer) {
CheckOnValidThread();
- if (task_queue_manager_)
- task_queue_manager_->RemoveTaskObserver(task_observer);
+ if (sequence_manager_)
+ sequence_manager_->RemoveTaskObserver(task_observer);
}
void SchedulerHelper::AddTaskTimeObserver(
TaskTimeObserver* task_time_observer) {
- if (task_queue_manager_)
- task_queue_manager_->AddTaskTimeObserver(task_time_observer);
+ if (sequence_manager_)
+ sequence_manager_->AddTaskTimeObserver(task_time_observer);
}
void SchedulerHelper::RemoveTaskTimeObserver(
TaskTimeObserver* task_time_observer) {
- if (task_queue_manager_)
- task_queue_manager_->RemoveTaskTimeObserver(task_time_observer);
+ if (sequence_manager_)
+ sequence_manager_->RemoveTaskTimeObserver(task_time_observer);
}
void SchedulerHelper::SetObserver(Observer* observer) {
CheckOnValidThread();
observer_ = observer;
- DCHECK(task_queue_manager_);
- task_queue_manager_->SetObserver(this);
+ DCHECK(sequence_manager_);
+ sequence_manager_->SetObserver(this);
}
void SchedulerHelper::SweepCanceledDelayedTasks() {
CheckOnValidThread();
- DCHECK(task_queue_manager_);
- task_queue_manager_->SweepCanceledDelayedTasks();
+ DCHECK(sequence_manager_);
+ sequence_manager_->SweepCanceledDelayedTasks();
}
-RealTimeDomain* SchedulerHelper::real_time_domain() const {
+TimeDomain* SchedulerHelper::real_time_domain() const {
CheckOnValidThread();
- DCHECK(task_queue_manager_);
- return task_queue_manager_->GetRealTimeDomain();
+ DCHECK(sequence_manager_);
+ return sequence_manager_->GetRealTimeDomain();
}
void SchedulerHelper::RegisterTimeDomain(TimeDomain* time_domain) {
CheckOnValidThread();
- DCHECK(task_queue_manager_);
- task_queue_manager_->RegisterTimeDomain(time_domain);
+ DCHECK(sequence_manager_);
+ sequence_manager_->RegisterTimeDomain(time_domain);
}
void SchedulerHelper::UnregisterTimeDomain(TimeDomain* time_domain) {
CheckOnValidThread();
- if (task_queue_manager_)
- task_queue_manager_->UnregisterTimeDomain(time_domain);
+ if (sequence_manager_)
+ sequence_manager_->UnregisterTimeDomain(time_domain);
}
void SchedulerHelper::OnBeginNestedRunLoop() {
@@ -130,21 +136,31 @@ void SchedulerHelper::OnExitNestedRunLoop() {
}
const base::TickClock* SchedulerHelper::GetClock() const {
- return task_queue_manager_->GetClock();
+ return sequence_manager_->GetTickClock();
}
base::TimeTicks SchedulerHelper::NowTicks() const {
- if (task_queue_manager_)
- return task_queue_manager_->NowTicks();
+ if (sequence_manager_)
+ return sequence_manager_->NowTicks();
// We may need current time for tracing when shutting down worker thread.
return base::TimeTicks::Now();
}
double SchedulerHelper::GetSamplingRateForRecordingCPUTime() const {
- if (task_queue_manager_)
- return task_queue_manager_->GetSamplingRateForRecordingCPUTime();
+ if (sequence_manager_) {
+ return sequence_manager_->GetMetricRecordingSettings()
+ .task_sampling_rate_for_recording_cpu_time;
+ }
return 0;
}
+bool SchedulerHelper::HasCPUTimingForEachTask() const {
+ if (sequence_manager_) {
+ return sequence_manager_->GetMetricRecordingSettings()
+ .records_cpu_time_for_each_task;
+ }
+ return false;
+}
+
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h
index f1fbdb5dc9c..2cb6a3e9f27 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h
@@ -10,24 +10,24 @@
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
+#include "base/task/sequence_manager/sequence_manager.h"
#include "base/time/tick_clock.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
namespace blink {
namespace scheduler {
// Common scheduler functionality for default tasks.
class PLATFORM_EXPORT SchedulerHelper
- : public base::sequence_manager::TaskQueueManager::Observer {
+ : public base::sequence_manager::SequenceManager::Observer {
public:
explicit SchedulerHelper(
- std::unique_ptr<base::sequence_manager::TaskQueueManager>
- task_queue_manager);
+ std::unique_ptr<base::sequence_manager::SequenceManager>
+ sequence_manager);
~SchedulerHelper() override;
- // TaskQueueManager::Observer implementation:
+ // SequenceManager::Observer implementation:
void OnBeginNestedRunLoop() override;
void OnExitNestedRunLoop() override;
@@ -44,6 +44,9 @@ class PLATFORM_EXPORT SchedulerHelper
virtual scoped_refptr<base::sequence_manager::TaskQueue>
ControlTaskQueue() = 0;
+ // Returns task runner for the default queue.
+ scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner();
+
// Adds or removes a task observer from the scheduler. The observer will be
// notified before and after every executed task. These functions can only be
// called on the thread this class was created on.
@@ -61,7 +64,7 @@ class PLATFORM_EXPORT SchedulerHelper
void Shutdown();
// Returns true if Shutdown() has been called. Otherwise returns false.
- bool IsShutdown() const { return !task_queue_manager_.get(); }
+ bool IsShutdown() const { return !sequence_manager_.get(); }
inline void CheckOnValidThread() const {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -87,11 +90,12 @@ class PLATFORM_EXPORT SchedulerHelper
void SweepCanceledDelayedTasks();
// Accessor methods.
- base::sequence_manager::RealTimeDomain* real_time_domain() const;
+ base::sequence_manager::TimeDomain* real_time_domain() const;
void RegisterTimeDomain(base::sequence_manager::TimeDomain* time_domain);
void UnregisterTimeDomain(base::sequence_manager::TimeDomain* time_domain);
bool GetAndClearSystemIsQuiescentBit();
double GetSamplingRateForRecordingCPUTime() const;
+ bool HasCPUTimingForEachTask() const;
// Test helpers.
void SetWorkBatchSizeForTesting(size_t work_batch_size);
@@ -103,11 +107,13 @@ class PLATFORM_EXPORT SchedulerHelper
TaskType default_task_type);
base::ThreadChecker thread_checker_;
- std::unique_ptr<base::sequence_manager::TaskQueueManager> task_queue_manager_;
+ std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager_;
private:
friend class SchedulerHelperTest;
+ scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
+
Observer* observer_; // NOT OWNED
DISALLOW_COPY_AND_ASSIGN(SchedulerHelper);
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc
index 011f4a96c39..438189ed1cf 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc
@@ -9,12 +9,11 @@
#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/task/sequence_manager/lazy_now.h"
+#include "base/task/sequence_manager/task_queue.h"
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
#include "base/test/scoped_task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h"
using testing::_;
@@ -55,15 +54,15 @@ class SchedulerHelperTest : public testing::Test {
base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED) {
// Null clock triggers some assertions.
task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(5));
- std::unique_ptr<base::sequence_manager::TaskQueueManagerForTest>
- task_queue_manager =
- base::sequence_manager::TaskQueueManagerForTest::Create(
- nullptr, base::ThreadTaskRunnerHandle::Get(),
+ std::unique_ptr<base::sequence_manager::SequenceManagerForTest>
+ sequence_manager =
+ base::sequence_manager::SequenceManagerForTest::Create(
+ nullptr, task_environment_.GetMainThreadTaskRunner(),
task_environment_.GetMockTickClock());
- task_queue_manager_ = task_queue_manager.get();
+ sequence_manager_ = sequence_manager.get();
scheduler_helper_ = std::make_unique<NonMainThreadSchedulerHelper>(
- std::move(task_queue_manager), nullptr, TaskType::kInternalTest);
- default_task_runner_ = scheduler_helper_->DefaultWorkerTaskQueue();
+ std::move(sequence_manager), nullptr, TaskType::kInternalTest);
+ default_task_runner_ = scheduler_helper_->DefaultNonMainThreadTaskQueue();
}
~SchedulerHelperTest() override = default;
@@ -87,8 +86,8 @@ class SchedulerHelperTest : public testing::Test {
protected:
base::test::ScopedTaskEnvironment task_environment_;
std::unique_ptr<NonMainThreadSchedulerHelper> scheduler_helper_;
- base::sequence_manager::TaskQueueManagerForTest*
- task_queue_manager_; // Owned by scheduler_helper.
+ base::sequence_manager::SequenceManagerForTest*
+ sequence_manager_; // Owned by scheduler_helper.
scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
DISALLOW_COPY_AND_ASSIGN(SchedulerHelperTest);
@@ -132,15 +131,15 @@ TEST_F(SchedulerHelperTest, IsShutdown) {
TEST_F(SchedulerHelperTest, GetNumberOfPendingTasks) {
std::vector<std::string> run_order;
- scheduler_helper_->DefaultWorkerTaskQueue()->PostTask(
+ scheduler_helper_->DefaultNonMainThreadTaskQueue()->PostTask(
FROM_HERE, base::BindOnce(&AppendToVectorTestTask, &run_order, "D1"));
- scheduler_helper_->DefaultWorkerTaskQueue()->PostTask(
+ scheduler_helper_->DefaultNonMainThreadTaskQueue()->PostTask(
FROM_HERE, base::BindOnce(&AppendToVectorTestTask, &run_order, "D2"));
- scheduler_helper_->ControlWorkerTaskQueue()->PostTask(
+ scheduler_helper_->ControlNonMainThreadTaskQueue()->PostTask(
FROM_HERE, base::BindOnce(&AppendToVectorTestTask, &run_order, "C1"));
- EXPECT_EQ(3U, task_queue_manager_->PendingTasksCount());
+ EXPECT_EQ(3U, sequence_manager_->PendingTasksCount());
task_environment_.RunUntilIdle();
- EXPECT_EQ(0U, task_queue_manager_->PendingTasksCount());
+ EXPECT_EQ(0U, sequence_manager_->PendingTasksCount());
}
namespace {
@@ -157,7 +156,7 @@ TEST_F(SchedulerHelperTest, ObserversNotifiedFor_DefaultTaskRunner) {
MockTaskObserver observer;
scheduler_helper_->AddTaskObserver(&observer);
- scheduler_helper_->DefaultWorkerTaskQueue()->PostTask(
+ scheduler_helper_->DefaultNonMainThreadTaskQueue()->PostTask(
FROM_HERE, base::BindOnce(&NopTask));
EXPECT_CALL(observer, WillProcessTask(_)).Times(1);
@@ -169,7 +168,7 @@ TEST_F(SchedulerHelperTest, ObserversNotNotifiedFor_ControlTaskQueue) {
MockTaskObserver observer;
scheduler_helper_->AddTaskObserver(&observer);
- scheduler_helper_->ControlWorkerTaskQueue()->PostTask(
+ scheduler_helper_->ControlNonMainThreadTaskQueue()->PostTask(
FROM_HERE, base::BindOnce(&NopTask));
EXPECT_CALL(observer, WillProcessTask(_)).Times(0);
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_lifecycle_state.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_lifecycle_state.cc
new file mode 100644
index 00000000000..b7dd1b87f3d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/scheduling_lifecycle_state.cc
@@ -0,0 +1,29 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/public/scheduling_lifecycle_state.h"
+#include "base/logging.h"
+
+namespace blink {
+namespace scheduler {
+
+// static
+const char* SchedulingLifecycleStateToString(SchedulingLifecycleState state) {
+ switch (state) {
+ case SchedulingLifecycleState::kNotThrottled:
+ return "not throttled";
+ case SchedulingLifecycleState::kHidden:
+ return "hidden";
+ case SchedulingLifecycleState::kThrottled:
+ return "throttled";
+ case SchedulingLifecycleState::kStopped:
+ return "frozen";
+ default:
+ NOTREACHED();
+ return nullptr;
+ }
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h
index 2af85c76457..20ac914b910 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h
@@ -25,9 +25,14 @@ namespace scheduler {
// Scheduler-internal interface for the common methods between
// MainThreadSchedulerImpl and NonMainThreadSchedulerImpl which should
// not be exposed outside the scheduler.
-class PLATFORM_EXPORT ThreadSchedulerImpl : virtual public ThreadScheduler,
- virtual public WebThreadScheduler {
+class PLATFORM_EXPORT ThreadSchedulerImpl : public ThreadScheduler,
+ public WebThreadScheduler {
public:
+ // This type is defined in both ThreadScheduler and WebThreadScheduler,
+ // so the use of this type causes ambiguous lookup. Redefine this again
+ // to hide the base classes' ones.
+ using RendererPauseHandle = WebThreadScheduler::RendererPauseHandle;
+
virtual scoped_refptr<base::SingleThreadTaskRunner> ControlTaskRunner() = 0;
virtual void RegisterTimeDomain(
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.cc
index 160e35b7a29..cbe2886227b 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.cc
@@ -32,7 +32,7 @@ void BudgetPool::AddQueue(base::TimeTicks now, TaskQueue* queue) {
if (!is_enabled_)
return;
- budget_pool_controller_->UpdateQueueThrottlingState(now, queue);
+ budget_pool_controller_->UpdateQueueSchedulingLifecycleState(now, queue);
}
void BudgetPool::UnregisterQueue(TaskQueue* queue) {
@@ -45,7 +45,7 @@ void BudgetPool::RemoveQueue(base::TimeTicks now, TaskQueue* queue) {
if (!is_enabled_)
return;
- budget_pool_controller_->UpdateQueueThrottlingState(now, queue);
+ budget_pool_controller_->UpdateQueueSchedulingLifecycleState(now, queue);
}
void BudgetPool::DissociateQueue(TaskQueue* queue) {
@@ -71,7 +71,8 @@ void BudgetPool::DisableThrottling(base::sequence_manager::LazyNow* lazy_now) {
TRACE_EVENT0("renderer.scheduler", "BudgetPool_DisableThrottling");
for (TaskQueue* queue : associated_task_queues_) {
- budget_pool_controller_->UpdateQueueThrottlingState(lazy_now->Now(), queue);
+ budget_pool_controller_->UpdateQueueSchedulingLifecycleState(
+ lazy_now->Now(), queue);
}
// TODO(altimin): We need to disable TimeBudgetQueues here or they will
@@ -90,7 +91,7 @@ void BudgetPool::Close() {
void BudgetPool::BlockThrottledQueues(base::TimeTicks now) {
for (TaskQueue* queue : associated_task_queues_)
- budget_pool_controller_->UpdateQueueThrottlingState(now, queue);
+ budget_pool_controller_->UpdateQueueSchedulingLifecycleState(now, queue);
}
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_unittest.cc
index 9d65c9ce0a7..1adb70195e2 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool_unittest.cc
@@ -10,12 +10,11 @@
#include "base/callback.h"
#include "base/macros.h"
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/test/null_task_runner.h"
#include "base/test/simple_test_tick_clock.h"
-#include "components/viz/test/ordered_simple_task_runner.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h"
@@ -31,11 +30,10 @@ class BudgetPoolTest : public testing::Test {
void SetUp() override {
clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
- mock_task_runner_ =
- base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, true);
+ null_task_runner_ = base::MakeRefCounted<base::NullTaskRunner>();
scheduler_.reset(new MainThreadSchedulerImpl(
- base::sequence_manager::TaskQueueManagerForTest::Create(
- nullptr, mock_task_runner_, &clock_),
+ base::sequence_manager::SequenceManagerForTest::Create(
+ nullptr, null_task_runner_, &clock_),
base::nullopt));
task_queue_throttler_ = scheduler_->task_queue_throttler();
start_time_ = clock_.NowTicks();
@@ -56,7 +54,7 @@ class BudgetPoolTest : public testing::Test {
protected:
base::SimpleTestTickClock clock_;
- scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
+ scoped_refptr<base::NullTaskRunner> null_task_runner_;
std::unique_ptr<MainThreadSchedulerImpl> scheduler_;
TaskQueueThrottler* task_queue_throttler_; // NOT OWNED
base::TimeTicks start_time_;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc
index feb24ff95f5..2a9e8d65843 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.cc
@@ -123,7 +123,7 @@ void CPUTimeBudgetPool::OnQueueNextWakeUpChanged(
TaskQueue* queue,
base::TimeTicks now,
base::TimeTicks desired_run_time) {
- budget_pool_controller_->UpdateQueueThrottlingState(now, queue);
+ budget_pool_controller_->UpdateQueueSchedulingLifecycleState(now, queue);
}
void CPUTimeBudgetPool::OnWakeUp(base::TimeTicks now) {}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc
index 611510da31a..6ac788abf76 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.cc
@@ -10,7 +10,6 @@
#include "base/memory/ptr_util.h"
#include "base/optional.h"
#include "base/time/tick_clock.h"
-#include "third_party/blink/renderer/platform/scheduler/base/real_time_domain.h"
#include "third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.h"
@@ -239,7 +238,8 @@ void TaskQueueThrottler::PumpThrottledTasks() {
for (const TaskQueueMap::value_type& map_entry : queue_details_) {
TaskQueue* task_queue = map_entry.first;
- UpdateQueueThrottlingStateInternal(lazy_now.Now(), task_queue, true);
+ UpdateQueueSchedulingLifecycleStateInternal(lazy_now.Now(), task_queue,
+ true);
}
}
@@ -314,14 +314,16 @@ void TaskQueueThrottler::OnTaskRunTimeReported(TaskQueue* task_queue,
}
}
-void TaskQueueThrottler::UpdateQueueThrottlingState(base::TimeTicks now,
- TaskQueue* queue) {
- UpdateQueueThrottlingStateInternal(now, queue, false);
+void TaskQueueThrottler::UpdateQueueSchedulingLifecycleState(
+ base::TimeTicks now,
+ TaskQueue* queue) {
+ UpdateQueueSchedulingLifecycleStateInternal(now, queue, false);
}
-void TaskQueueThrottler::UpdateQueueThrottlingStateInternal(base::TimeTicks now,
- TaskQueue* queue,
- bool is_wake_up) {
+void TaskQueueThrottler::UpdateQueueSchedulingLifecycleStateInternal(
+ base::TimeTicks now,
+ TaskQueue* queue,
+ bool is_wake_up) {
if (!queue->IsQueueEnabled() || !IsThrottled(queue)) {
return;
}
@@ -572,7 +574,7 @@ void TaskQueueThrottler::EnableThrottling() {
// to enforce task alignment.
queue->InsertFence(TaskQueue::InsertFencePosition::kBeginningOfTime);
queue->SetTimeDomain(time_domain_.get());
- UpdateQueueThrottlingState(lazy_now.Now(), queue);
+ UpdateQueueSchedulingLifecycleState(lazy_now.Now(), queue);
}
TRACE_EVENT0("renderer.scheduler", "TaskQueueThrottler_EnableThrottling");
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h
index bfeadc4aad0..42269fa5dd7 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h
@@ -12,11 +12,11 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
+#include "base/task/sequence_manager/task_queue.h"
+#include "base/task/sequence_manager/time_domain.h"
#include "base/threading/thread_checker.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/base/time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/child/cancelable_closure_holder.h"
+#include "third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/cpu_time_budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h"
@@ -63,7 +63,7 @@ class PLATFORM_EXPORT BudgetPoolController {
// Ensure that an appropriate type of the fence is installed and schedule
// a pump for this queue when needed.
- virtual void UpdateQueueThrottlingState(
+ virtual void UpdateQueueSchedulingLifecycleState(
base::TimeTicks now,
base::sequence_manager::TaskQueue* queue) = 0;
@@ -115,7 +115,7 @@ class PLATFORM_EXPORT TaskQueueThrottler
void RemoveQueueFromBudgetPool(base::sequence_manager::TaskQueue* queue,
BudgetPool* budget_pool) override;
void UnregisterBudgetPool(BudgetPool* budget_pool) override;
- void UpdateQueueThrottlingState(
+ void UpdateQueueSchedulingLifecycleState(
base::TimeTicks now,
base::sequence_manager::TaskQueue* queue) override;
bool IsThrottled(base::sequence_manager::TaskQueue* queue) const override;
@@ -195,7 +195,7 @@ class PLATFORM_EXPORT TaskQueueThrottler
void MaybeDeleteQueueMetadata(TaskQueueMap::iterator it);
- void UpdateQueueThrottlingStateInternal(
+ void UpdateQueueSchedulingLifecycleStateInternal(
base::TimeTicks now,
base::sequence_manager::TaskQueue* queue,
bool is_wake_up);
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc
index 3bd39ee366e..14cd8872185 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler_unittest.cc
@@ -11,43 +11,38 @@
#include "base/callback.h"
#include "base/macros.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "components/viz/test/ordered_simple_task_runner.h"
+#include "base/task/sequence_manager/sequence_manager.h"
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/test/test_mock_time_task_runner.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/scheduler/base/real_time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
-using base::sequence_manager::LazyNow;
-using base::sequence_manager::TaskQueue;
-using testing::ElementsAre;
-
namespace blink {
namespace scheduler {
// To avoid symbol collisions in jumbo builds.
namespace task_queue_throttler_unittest {
+using base::TimeDelta;
+using base::TimeTicks;
+using base::TestMockTimeTaskRunner;
+using base::sequence_manager::LazyNow;
+using base::sequence_manager::TaskQueue;
+using testing::ElementsAre;
+
class MainThreadSchedulerImplForTest : public MainThreadSchedulerImpl {
public:
using MainThreadSchedulerImpl::ControlTaskQueue;
MainThreadSchedulerImplForTest(
- std::unique_ptr<base::sequence_manager::TaskQueueManager> manager,
+ std::unique_ptr<base::sequence_manager::SequenceManager> manager,
base::Optional<base::Time> initial_virtual_time)
: MainThreadSchedulerImpl(std::move(manager), initial_virtual_time) {}
};
-bool MessageLoopTaskCounter(size_t* count) {
- *count = *count + 1;
- return true;
-}
-
void NopTask() {}
void AddOneTask(size_t* count) {
@@ -61,43 +56,21 @@ void RunTenTimesTask(size_t* count, scoped_refptr<TaskQueue> timer_queue) {
}
}
-// Test clock which simulates passage of time by automatically
-// advancing time with each call to Now().
-class AutoAdvancingTestClock : public base::SimpleTestTickClock {
- public:
- AutoAdvancingTestClock(base::TimeDelta interval)
- : advancing_interval_(interval) {}
- ~AutoAdvancingTestClock() override = default;
-
- base::TimeTicks NowTicks() const override {
- const_cast<AutoAdvancingTestClock*>(this)->Advance(advancing_interval_);
- return SimpleTestTickClock::NowTicks();
- }
-
- base::TimeTicks GetNowTicksWithoutAdvancing() {
- return SimpleTestTickClock::NowTicks();
- }
-
- private:
- base::TimeDelta advancing_interval_;
-};
-
class TaskQueueThrottlerTest : public testing::Test {
public:
- TaskQueueThrottlerTest() = default;
+ TaskQueueThrottlerTest()
+ : test_task_runner_(base::MakeRefCounted<TestMockTimeTaskRunner>()) {}
~TaskQueueThrottlerTest() override = default;
void SetUp() override {
- clock_ = CreateClock();
- clock_->Advance(base::TimeDelta::FromMicroseconds(5000));
- mock_task_runner_ =
- base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(clock_.get(), true);
+ // A null clock triggers some assertions.
+ test_task_runner_->AdvanceMockTickClock(TimeDelta::FromMilliseconds(5));
+
scheduler_.reset(new MainThreadSchedulerImplForTest(
- base::sequence_manager::TaskQueueManagerForTest::Create(
- nullptr, mock_task_runner_, clock_.get()),
+ base::sequence_manager::SequenceManagerForTest::Create(
+ nullptr, test_task_runner_, GetTickClock()),
base::nullopt));
- scheduler_->GetWakeUpBudgetPoolForTesting()->SetWakeUpDuration(
- base::TimeDelta());
+ scheduler_->GetWakeUpBudgetPoolForTesting()->SetWakeUpDuration(TimeDelta());
task_queue_throttler_ = scheduler_->task_queue_throttler();
timer_queue_ = scheduler_->NewTimerTaskQueue(
MainThreadTaskQueue::QueueType::kFrameThrottleable, nullptr);
@@ -113,11 +86,11 @@ class TaskQueueThrottlerTest : public testing::Test {
timer_queue->PostTask(
FROM_HERE, base::BindOnce(&RunTenTimesTask, &count, timer_queue));
- mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
+ test_task_runner_->FastForwardBy(TimeDelta::FromSeconds(1));
EXPECT_LE(count, 1u);
// Make sure the rest of the tasks run or we risk a UAF on |count|.
- mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(10));
+ test_task_runner_->FastForwardBy(TimeDelta::FromSeconds(10));
EXPECT_EQ(10u, count);
}
@@ -126,218 +99,237 @@ class TaskQueueThrottlerTest : public testing::Test {
timer_queue->PostTask(
FROM_HERE, base::BindOnce(&RunTenTimesTask, &count, timer_queue));
- mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
+ test_task_runner_->FastForwardBy(TimeDelta::FromSeconds(1));
EXPECT_EQ(10u, count);
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
}
bool IsQueueBlocked(TaskQueue* task_queue) {
- base::sequence_manager::internal::TaskQueueImpl* task_queue_impl =
- task_queue->GetTaskQueueImpl();
- if (!task_queue_impl->IsQueueEnabled())
+ if (!task_queue->IsQueueEnabled())
return true;
- return task_queue_impl->GetFenceForTest() ==
- static_cast<base::sequence_manager::internal::EnqueueOrder>(
- base::sequence_manager::internal::EnqueueOrderValues::
- kBlockingFence);
+ return task_queue->BlockedByFence();
}
protected:
- virtual std::unique_ptr<AutoAdvancingTestClock> CreateClock() {
- return std::make_unique<AutoAdvancingTestClock>(base::TimeDelta());
+ virtual const base::TickClock* GetTickClock() const {
+ return test_task_runner_->GetMockTickClock();
}
- std::unique_ptr<AutoAdvancingTestClock> clock_;
- scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
+ scoped_refptr<TestMockTimeTaskRunner> test_task_runner_;
std::unique_ptr<MainThreadSchedulerImplForTest> scheduler_;
scoped_refptr<TaskQueue> timer_queue_;
TaskQueueThrottler* task_queue_throttler_; // NOT OWNED
+ private:
DISALLOW_COPY_AND_ASSIGN(TaskQueueThrottlerTest);
};
+// Advances mock clock every time we call NowTicks() from the scheduler.
+class AutoAdvancingProxyClock : public base::TickClock {
+ public:
+ AutoAdvancingProxyClock(scoped_refptr<TestMockTimeTaskRunner> task_runner)
+ : task_runner_(task_runner) {}
+ ~AutoAdvancingProxyClock() override = default;
+
+ void SetAutoAdvanceInterval(TimeDelta interval) {
+ advance_interval_ = interval;
+ }
+
+ TimeTicks NowTicks() const override {
+ if (!advance_interval_.is_zero())
+ task_runner_->AdvanceMockTickClock(advance_interval_);
+ return task_runner_->NowTicks();
+ }
+
+ private:
+ scoped_refptr<TestMockTimeTaskRunner> task_runner_;
+ TimeDelta advance_interval_;
+};
+
class TaskQueueThrottlerWithAutoAdvancingTimeTest
: public TaskQueueThrottlerTest,
public testing::WithParamInterface<bool> {
public:
TaskQueueThrottlerWithAutoAdvancingTimeTest()
- : auto_advance_time_interval_(GetParam()
- ? base::TimeDelta::FromMicroseconds(1)
- : base::TimeDelta()) {}
+ : proxy_clock_(test_task_runner_) {}
~TaskQueueThrottlerWithAutoAdvancingTimeTest() override = default;
- protected:
- std::unique_ptr<AutoAdvancingTestClock> CreateClock() override {
- return std::make_unique<AutoAdvancingTestClock>(
- auto_advance_time_interval_);
+ void SetUp() override {
+ TaskQueueThrottlerTest::SetUp();
+ if (GetParam()) {
+ // Will advance the time by this value after running each task.
+ proxy_clock_.SetAutoAdvanceInterval(TimeDelta::FromMicroseconds(10));
+ }
}
- base::TimeDelta auto_advance_time_interval_;
+ protected:
+ const base::TickClock* GetTickClock() const override { return &proxy_clock_; }
+
+ private:
+ AutoAdvancingProxyClock proxy_clock_;
DISALLOW_COPY_AND_ASSIGN(TaskQueueThrottlerWithAutoAdvancingTimeTest);
};
-INSTANTIATE_TEST_CASE_P(All,
+INSTANTIATE_TEST_CASE_P(,
TaskQueueThrottlerWithAutoAdvancingTimeTest,
testing::Bool());
TEST_F(TaskQueueThrottlerTest, ThrottledTasksReportRealTime) {
EXPECT_EQ(timer_queue_->GetTimeDomain()->Now(),
- clock_->GetNowTicksWithoutAdvancing());
+ test_task_runner_->NowTicks());
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
EXPECT_EQ(timer_queue_->GetTimeDomain()->Now(),
- clock_->GetNowTicksWithoutAdvancing());
+ test_task_runner_->NowTicks());
- clock_->Advance(base::TimeDelta::FromMilliseconds(250));
+ test_task_runner_->AdvanceMockTickClock(TimeDelta::FromMilliseconds(250));
// Make sure the throttled time domain's Now() reports the same as the
// underlying clock.
EXPECT_EQ(timer_queue_->GetTimeDomain()->Now(),
- clock_->GetNowTicksWithoutAdvancing());
+ test_task_runner_->NowTicks());
}
TEST_F(TaskQueueThrottlerTest, AlignedThrottledRunTime) {
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0),
+ EXPECT_EQ(TimeTicks() + TimeDelta::FromSecondsD(1.0),
TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(0.0)));
+ TimeTicks() + TimeDelta::FromSecondsD(0.0)));
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0),
+ EXPECT_EQ(TimeTicks() + TimeDelta::FromSecondsD(1.0),
TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(0.1)));
+ TimeTicks() + TimeDelta::FromSecondsD(0.1)));
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0),
+ EXPECT_EQ(TimeTicks() + TimeDelta::FromSecondsD(1.0),
TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(0.2)));
+ TimeTicks() + TimeDelta::FromSecondsD(0.2)));
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0),
+ EXPECT_EQ(TimeTicks() + TimeDelta::FromSecondsD(1.0),
TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(0.5)));
+ TimeTicks() + TimeDelta::FromSecondsD(0.5)));
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0),
+ EXPECT_EQ(TimeTicks() + TimeDelta::FromSecondsD(1.0),
TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(0.8)));
+ TimeTicks() + TimeDelta::FromSecondsD(0.8)));
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0),
+ EXPECT_EQ(TimeTicks() + TimeDelta::FromSecondsD(1.0),
TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(0.9)));
+ TimeTicks() + TimeDelta::FromSecondsD(0.9)));
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(2.0),
+ EXPECT_EQ(TimeTicks() + TimeDelta::FromSecondsD(2.0),
TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(1.0)));
+ TimeTicks() + TimeDelta::FromSecondsD(1.0)));
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(2.0),
+ EXPECT_EQ(TimeTicks() + TimeDelta::FromSecondsD(2.0),
TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(1.1)));
+ TimeTicks() + TimeDelta::FromSecondsD(1.1)));
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(9.0),
+ EXPECT_EQ(TimeTicks() + TimeDelta::FromSecondsD(9.0),
TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(8.0)));
+ TimeTicks() + TimeDelta::FromSecondsD(8.0)));
- EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromSecondsD(9.0),
+ EXPECT_EQ(TimeTicks() + TimeDelta::FromSecondsD(9.0),
TaskQueueThrottler::AlignedThrottledRunTime(
- base::TimeTicks() + base::TimeDelta::FromSecondsD(8.1)));
+ TimeTicks() + TimeDelta::FromSecondsD(8.1)));
}
namespace {
// Round up time to milliseconds to deal with autoadvancing time.
// TODO(altimin): round time only when autoadvancing time is enabled.
-base::TimeDelta RoundTimeToMilliseconds(base::TimeDelta time) {
- return time - time % base::TimeDelta::FromMilliseconds(1);
+TimeDelta RoundTimeToMilliseconds(TimeDelta time) {
+ return time - time % TimeDelta::FromMilliseconds(1);
}
-base::TimeTicks RoundTimeToMilliseconds(base::TimeTicks time) {
- return base::TimeTicks() + RoundTimeToMilliseconds(time - base::TimeTicks());
+TimeTicks RoundTimeToMilliseconds(TimeTicks time) {
+ return TimeTicks() + RoundTimeToMilliseconds(time - TimeTicks());
}
-void TestTask(std::vector<base::TimeTicks>* run_times,
- AutoAdvancingTestClock* clock) {
- run_times->push_back(
- RoundTimeToMilliseconds(clock->GetNowTicksWithoutAdvancing()));
+void TestTask(std::vector<TimeTicks>* run_times,
+ scoped_refptr<TestMockTimeTaskRunner> task_runner) {
+ run_times->push_back(RoundTimeToMilliseconds(task_runner->NowTicks()));
+ // FIXME No auto-advancing
}
-void ExpensiveTestTask(std::vector<base::TimeTicks>* run_times,
- AutoAdvancingTestClock* clock) {
- run_times->push_back(
- RoundTimeToMilliseconds(clock->GetNowTicksWithoutAdvancing()));
- clock->Advance(base::TimeDelta::FromMilliseconds(250));
+void ExpensiveTestTask(std::vector<TimeTicks>* run_times,
+ scoped_refptr<TestMockTimeTaskRunner> task_runner) {
+ run_times->push_back(RoundTimeToMilliseconds(task_runner->NowTicks()));
+ task_runner->AdvanceMockTickClock(TimeDelta::FromMilliseconds(250));
+ // FIXME No auto-advancing
}
-void RecordThrottling(std::vector<base::TimeDelta>* reported_throttling_times,
- base::TimeDelta throttling_duration) {
+void RecordThrottling(std::vector<TimeDelta>* reported_throttling_times,
+ TimeDelta throttling_duration) {
reported_throttling_times->push_back(
RoundTimeToMilliseconds(throttling_duration));
}
} // namespace
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TimerAlignment) {
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200.0));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200.0));
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(800.0));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(800.0));
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(1200.0));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(1200.0));
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(8300.0));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(8300.0));
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
// Times are aligned to a multiple of 1000 milliseconds.
- EXPECT_THAT(
- run_times,
- ElementsAre(
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000.0),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000.0),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(2000.0),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(9000.0)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(1000.0),
+ TimeTicks() + TimeDelta::FromMilliseconds(1000.0),
+ TimeTicks() + TimeDelta::FromMilliseconds(2000.0),
+ TimeTicks() + TimeDelta::FromMilliseconds(9000.0)));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
TimerAlignment_Unthrottled) {
- std::vector<base::TimeTicks> run_times;
- base::TimeTicks start_time = clock_->GetNowTicksWithoutAdvancing();
+ std::vector<TimeTicks> run_times;
+ TimeTicks start_time = test_task_runner_->NowTicks();
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200.0));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200.0));
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(800.0));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(800.0));
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(1200.0));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(1200.0));
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(8300.0));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(8300.0));
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
task_queue_throttler_->DecreaseThrottleRefCount(timer_queue_.get());
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
// Times are not aligned.
EXPECT_THAT(
run_times,
- ElementsAre(RoundTimeToMilliseconds(
- start_time + base::TimeDelta::FromMilliseconds(200.0)),
- RoundTimeToMilliseconds(
- start_time + base::TimeDelta::FromMilliseconds(800.0)),
+ ElementsAre(RoundTimeToMilliseconds(start_time +
+ TimeDelta::FromMilliseconds(200.0)),
+ RoundTimeToMilliseconds(start_time +
+ TimeDelta::FromMilliseconds(800.0)),
+ RoundTimeToMilliseconds(start_time +
+ TimeDelta::FromMilliseconds(1200.0)),
RoundTimeToMilliseconds(
- start_time + base::TimeDelta::FromMilliseconds(1200.0)),
- RoundTimeToMilliseconds(
- start_time + base::TimeDelta::FromMilliseconds(8300.0))));
+ start_time + TimeDelta::FromMilliseconds(8300.0))));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, Refcount) {
@@ -373,7 +365,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
OnTimeDomainHasImmediateWork_EnabledQueue) {
task_queue_throttler_->OnQueueNextWakeUpChanged(timer_queue_.get(),
- base::TimeTicks());
+ TimeTicks());
// Check PostPumpThrottledTasksLocked was called.
EXPECT_FALSE(scheduler_->ControlTaskQueue()->IsEmpty());
}
@@ -385,7 +377,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
voter->SetQueueEnabled(false);
task_queue_throttler_->OnQueueNextWakeUpChanged(timer_queue_.get(),
- base::TimeTicks());
+ TimeTicks());
// Check PostPumpThrottledTasksLocked was not called.
EXPECT_TRUE(scheduler_->ControlTaskQueue()->IsEmpty());
}
@@ -409,7 +401,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
ThrottlingADisabledQueueDoesNotPostPumpThrottledTasks_DelayedTask) {
timer_queue_->PostDelayedTask(FROM_HERE, base::BindOnce(&NopTask),
- base::TimeDelta::FromMilliseconds(1));
+ TimeDelta::FromMilliseconds(1));
std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
timer_queue_->CreateQueueEnabledVoter();
@@ -424,123 +416,106 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, WakeUpForNonDelayedTask) {
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
// Nothing is posted on timer_queue_ so PumpThrottledTasks will not tick.
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
// Posting a task should trigger the pump.
- timer_queue_->PostTask(FROM_HERE,
- base::BindOnce(&TestTask, &run_times, clock_.get()));
+ timer_queue_->PostTask(
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_THAT(run_times,
- ElementsAre(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(1000.0)));
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(1000.0)));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, WakeUpForDelayedTask) {
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
// Nothing is posted on timer_queue_ so PumpThrottledTasks will not tick.
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
// Posting a task should trigger the pump.
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(1200.0));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(1200.0));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_THAT(run_times,
- ElementsAre(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(2000.0)));
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(2000.0)));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
SingleThrottledTaskPumpedAndRunWithNoExtraneousMessageLoopTasks) {
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
- base::TimeDelta delay(base::TimeDelta::FromMilliseconds(10));
+ TimeDelta delay(TimeDelta::FromMilliseconds(10));
timer_queue_->PostDelayedTask(FROM_HERE, base::BindOnce(&NopTask), delay);
-
- size_t task_count = 0;
- mock_task_runner_->RunTasksWhile(
- base::BindRepeating(&MessageLoopTaskCounter, &task_count));
-
- // Run the task.
- EXPECT_EQ(1u, task_count);
+ EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
SingleFutureThrottledTaskPumpedAndRunWithNoExtraneousMessageLoopTasks) {
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
- base::TimeDelta delay(base::TimeDelta::FromSecondsD(15.5));
+ TimeDelta delay(TimeDelta::FromSecondsD(15.5));
timer_queue_->PostDelayedTask(FROM_HERE, base::BindOnce(&NopTask), delay);
-
- size_t task_count = 0;
- mock_task_runner_->RunTasksWhile(
- base::BindRepeating(&MessageLoopTaskCounter, &task_count));
-
- // Run the delayed task.
- EXPECT_EQ(1u, task_count);
+ EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
TwoFutureThrottledTaskPumpedAndRunWithNoExtraneousMessageLoopTasks) {
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
- base::TimeDelta delay(base::TimeDelta::FromSecondsD(15.5));
+ TimeDelta delay(TimeDelta::FromSecondsD(15.5));
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()), delay);
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ delay);
- base::TimeDelta delay2(base::TimeDelta::FromSecondsD(5.5));
+ TimeDelta delay2(TimeDelta::FromSecondsD(5.5));
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()), delay2);
-
- size_t task_count = 0;
- mock_task_runner_->RunTasksWhile(
- base::BindRepeating(&MessageLoopTaskCounter, &task_count));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ delay2);
- // Run both delayed tasks.
- EXPECT_EQ(2u, task_count);
+ EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ test_task_runner_->FastForwardBy(test_task_runner_->NextPendingTaskDelay());
+ EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ test_task_runner_->FastForwardBy(test_task_runner_->NextPendingTaskDelay());
+ EXPECT_EQ(0u, test_task_runner_->GetPendingTaskCount());
- EXPECT_THAT(
- run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(6),
- base::TimeTicks() + base::TimeDelta::FromSeconds(16)));
+ EXPECT_THAT(run_times, ElementsAre(TimeTicks() + TimeDelta::FromSeconds(6),
+ TimeTicks() + TimeDelta::FromSeconds(16)));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
TaskDelayIsBasedOnRealTime) {
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
// Post an initial task that should run at the first aligned time period.
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(900.0));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(900.0));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
// Advance realtime.
- clock_->Advance(base::TimeDelta::FromMilliseconds(250));
+ test_task_runner_->AdvanceMockTickClock(TimeDelta::FromMilliseconds(250));
// Post a task that due to real time + delay must run in the third aligned
// time period.
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(900.0));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(900.0));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(
- run_times,
- ElementsAre(
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000.0),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000.0)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(1000.0),
+ TimeTicks() + TimeDelta::FromMilliseconds(3000.0)));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TaskQueueDisabledTillPump) {
@@ -551,9 +526,8 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TaskQueueDisabledTillPump) {
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
EXPECT_TRUE(IsQueueBlocked(timer_queue_.get()));
- mock_task_runner_->RunUntilIdle(); // Wait until the pump.
- EXPECT_EQ(1u, count); // The task got run
- EXPECT_FALSE(IsQueueBlocked(timer_queue_.get()));
+ test_task_runner_->FastForwardUntilNoTasksRemain(); // Wait until the pump.
+ EXPECT_EQ(1u, count); // The task got run.
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
@@ -598,49 +572,51 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TimeBasedThrottling) {
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
CPUTimeBudgetPool* pool =
task_queue_throttler_->CreateCPUTimeBudgetPool("test");
- pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
- pool->AddQueue(base::TimeTicks(), timer_queue_.get());
+ pool->SetTimeBudgetRecoveryRate(TimeTicks(), 0.1);
+ pool->AddQueue(TimeTicks(), timer_queue_.get());
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
// Submit two tasks. They should be aligned, and second one should be
// throttled.
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200));
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1),
- base::TimeTicks() + base::TimeDelta::FromSeconds(3)));
+ EXPECT_THAT(run_times, ElementsAre(TimeTicks() + TimeDelta::FromSeconds(1),
+ TimeTicks() + TimeDelta::FromSeconds(3)));
- pool->RemoveQueue(clock_->GetNowTicksWithoutAdvancing(), timer_queue_.get());
+ pool->RemoveQueue(test_task_runner_->NowTicks(), timer_queue_.get());
run_times.clear();
// Queue was removed from CPUTimeBudgetPool, only timer alignment should be
// active now.
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200));
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(
- run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(4000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(4250)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(4000),
+ TimeTicks() + TimeDelta::FromMilliseconds(4250)));
task_queue_throttler_->DecreaseThrottleRefCount(timer_queue_.get());
pool->Close();
@@ -648,106 +624,111 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TimeBasedThrottling) {
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
EnableAndDisableCPUTimeBudgetPool) {
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
CPUTimeBudgetPool* pool =
task_queue_throttler_->CreateCPUTimeBudgetPool("test");
EXPECT_TRUE(pool->IsThrottlingEnabled());
- pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
- pool->AddQueue(base::TimeTicks(), timer_queue_.get());
+ pool->SetTimeBudgetRecoveryRate(TimeTicks(), 0.1);
+ pool->AddQueue(TimeTicks(), timer_queue_.get());
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
// Post an expensive task. Pool is now throttled.
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(run_times, ElementsAre(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(1000)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(1000)));
run_times.clear();
- LazyNow lazy_now_1(clock_.get());
+ LazyNow lazy_now_1(test_task_runner_->GetMockTickClock());
pool->DisableThrottling(&lazy_now_1);
EXPECT_FALSE(pool->IsThrottlingEnabled());
// Pool should not be throttled now.
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(run_times, ElementsAre(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(2000)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(2000)));
run_times.clear();
- LazyNow lazy_now_2(clock_.get());
+ LazyNow lazy_now_2(test_task_runner_->GetMockTickClock());
pool->EnableThrottling(&lazy_now_2);
EXPECT_TRUE(pool->IsThrottlingEnabled());
// Because time pool was disabled, time budget level did not replenish
// and queue is throttled.
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(run_times, ElementsAre(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(4000)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(4000)));
run_times.clear();
task_queue_throttler_->DecreaseThrottleRefCount(timer_queue_.get());
- pool->RemoveQueue(clock_->GetNowTicksWithoutAdvancing(), timer_queue_.get());
+ pool->RemoveQueue(test_task_runner_->NowTicks(), timer_queue_.get());
pool->Close();
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
ImmediateTasksTimeBudgetThrottling) {
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
CPUTimeBudgetPool* pool =
task_queue_throttler_->CreateCPUTimeBudgetPool("test");
- pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
- pool->AddQueue(base::TimeTicks(), timer_queue_.get());
+ pool->SetTimeBudgetRecoveryRate(TimeTicks(), 0.1);
+ pool->AddQueue(TimeTicks(), timer_queue_.get());
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
// Submit two tasks. They should be aligned, and second one should be
// throttled.
timer_queue_->PostTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_));
timer_queue_->PostTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1),
- base::TimeTicks() + base::TimeDelta::FromSeconds(3)));
+ EXPECT_THAT(run_times, ElementsAre(TimeTicks() + TimeDelta::FromSeconds(1),
+ TimeTicks() + TimeDelta::FromSeconds(3)));
- pool->RemoveQueue(clock_->GetNowTicksWithoutAdvancing(), timer_queue_.get());
+ pool->RemoveQueue(test_task_runner_->NowTicks(), timer_queue_.get());
run_times.clear();
// Queue was removed from CPUTimeBudgetPool, only timer alignment should be
// active now.
timer_queue_->PostTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_));
timer_queue_->PostTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(
- run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(4000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(4250)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(4000),
+ TimeTicks() + TimeDelta::FromMilliseconds(4250)));
task_queue_throttler_->DecreaseThrottleRefCount(timer_queue_.get());
pool->Close();
@@ -755,7 +736,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
TwoQueuesTimeBudgetThrottling) {
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
scoped_refptr<TaskQueue> second_queue = scheduler_->NewTimerTaskQueue(
MainThreadTaskQueue::QueueType::kFrameThrottleable, nullptr);
@@ -763,37 +744,38 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
CPUTimeBudgetPool* pool =
task_queue_throttler_->CreateCPUTimeBudgetPool("test");
- pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
- pool->AddQueue(base::TimeTicks(), timer_queue_.get());
- pool->AddQueue(base::TimeTicks(), second_queue.get());
+ pool->SetTimeBudgetRecoveryRate(TimeTicks(), 0.1);
+ pool->AddQueue(TimeTicks(), timer_queue_.get());
+ pool->AddQueue(TimeTicks(), second_queue.get());
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
task_queue_throttler_->IncreaseThrottleRefCount(second_queue.get());
timer_queue_->PostTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_));
second_queue->PostTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1),
- base::TimeTicks() + base::TimeDelta::FromSeconds(3)));
+ EXPECT_THAT(run_times, ElementsAre(TimeTicks() + TimeDelta::FromSeconds(1),
+ TimeTicks() + TimeDelta::FromSeconds(3)));
task_queue_throttler_->DecreaseThrottleRefCount(timer_queue_.get());
task_queue_throttler_->DecreaseThrottleRefCount(second_queue.get());
- pool->RemoveQueue(clock_->GetNowTicksWithoutAdvancing(), timer_queue_.get());
- pool->RemoveQueue(clock_->GetNowTicksWithoutAdvancing(), second_queue.get());
+ pool->RemoveQueue(test_task_runner_->NowTicks(), timer_queue_.get());
+ pool->RemoveQueue(test_task_runner_->NowTicks(), second_queue.get());
pool->Close();
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
DisabledTimeBudgetDoesNotAffectThrottledQueues) {
- std::vector<base::TimeTicks> run_times;
- LazyNow lazy_now(clock_.get());
+ std::vector<TimeTicks> run_times;
+ LazyNow lazy_now(test_task_runner_->GetMockTickClock());
CPUTimeBudgetPool* pool =
task_queue_throttler_->CreateCPUTimeBudgetPool("test");
@@ -805,151 +787,147 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(100));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(100));
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(100));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(100));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(
- run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1250)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(1000),
+ TimeTicks() + TimeDelta::FromMilliseconds(1250)));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
TimeBudgetThrottlingDoesNotAffectUnthrottledQueues) {
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
CPUTimeBudgetPool* pool =
task_queue_throttler_->CreateCPUTimeBudgetPool("test");
- pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
+ pool->SetTimeBudgetRecoveryRate(TimeTicks(), 0.1);
- LazyNow lazy_now(clock_.get());
+ LazyNow lazy_now(test_task_runner_->GetMockTickClock());
pool->DisableThrottling(&lazy_now);
- pool->AddQueue(clock_->GetNowTicksWithoutAdvancing(), timer_queue_.get());
+ pool->AddQueue(test_task_runner_->NowTicks(), timer_queue_.get());
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(100));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(100));
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(100));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(100));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(
- run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(105),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(355)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(105),
+ TimeTicks() + TimeDelta::FromMilliseconds(355)));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, MaxThrottlingDelay) {
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
CPUTimeBudgetPool* pool =
task_queue_throttler_->CreateCPUTimeBudgetPool("test");
- pool->SetMaxThrottlingDelay(base::TimeTicks(),
- base::TimeDelta::FromMinutes(1));
+ pool->SetMaxThrottlingDelay(TimeTicks(), TimeDelta::FromMinutes(1));
- pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.001);
- pool->AddQueue(base::TimeTicks(), timer_queue_.get());
+ pool->SetTimeBudgetRecoveryRate(TimeTicks(), 0.001);
+ pool->AddQueue(TimeTicks(), timer_queue_.get());
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
for (int i = 0; i < 5; ++i) {
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200));
}
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(
- run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1),
- base::TimeTicks() + base::TimeDelta::FromSeconds(62),
- base::TimeTicks() + base::TimeDelta::FromSeconds(123),
- base::TimeTicks() + base::TimeDelta::FromSeconds(184),
- base::TimeTicks() + base::TimeDelta::FromSeconds(245)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromSeconds(1),
+ TimeTicks() + TimeDelta::FromSeconds(62),
+ TimeTicks() + TimeDelta::FromSeconds(123),
+ TimeTicks() + TimeDelta::FromSeconds(184),
+ TimeTicks() + TimeDelta::FromSeconds(245)));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
EnableAndDisableThrottling) {
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200));
- mock_task_runner_->RunUntilTime(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(300));
+ test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(295));
// Disable throttling - task should run immediately.
task_queue_throttler_->DisableThrottling();
- mock_task_runner_->RunUntilTime(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(500));
+ test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(200));
- EXPECT_THAT(run_times, ElementsAre(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(300)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(300)));
run_times.clear();
// Schedule a task at 900ms. It should proceed as normal.
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(400));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(400));
// Schedule a task at 1200ms. It should proceed as normal.
// PumpThrottledTasks was scheduled at 1000ms, so it needs to be checked
// that it was cancelled and it does not interfere with tasks posted before
// 1s mark and scheduled to run after 1s mark.
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(700));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(700));
- mock_task_runner_->RunUntilTime(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(1300));
+ test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(800));
- EXPECT_THAT(
- run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(900),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1200)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(900),
+ TimeTicks() + TimeDelta::FromMilliseconds(1200)));
run_times.clear();
// Schedule a task at 1500ms. It should be throttled because of enabled
// throttling.
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200));
- mock_task_runner_->RunUntilTime(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(1400));
+ test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(100));
// Throttling is enabled and new task should be aligned.
task_queue_throttler_->EnableThrottling();
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(run_times, ElementsAre(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(2000)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(2000)));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, ReportThrottling) {
- std::vector<base::TimeTicks> run_times;
- std::vector<base::TimeDelta> reported_throttling_times;
+ std::vector<TimeTicks> run_times;
+ std::vector<TimeDelta> reported_throttling_times;
CPUTimeBudgetPool* pool =
task_queue_throttler_->CreateCPUTimeBudgetPool("test");
- pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
- pool->AddQueue(base::TimeTicks(), timer_queue_.get());
+ pool->SetTimeBudgetRecoveryRate(TimeTicks(), 0.1);
+ pool->AddQueue(TimeTicks(), timer_queue_.get());
pool->SetReportingCallback(
base::BindRepeating(&RecordThrottling, &reported_throttling_times));
@@ -957,41 +935,41 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, ReportThrottling) {
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200));
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200));
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1),
- base::TimeTicks() + base::TimeDelta::FromSeconds(1),
- base::TimeTicks() + base::TimeDelta::FromSeconds(3)));
+ EXPECT_THAT(run_times, ElementsAre(TimeTicks() + TimeDelta::FromSeconds(1),
+ TimeTicks() + TimeDelta::FromSeconds(1),
+ TimeTicks() + TimeDelta::FromSeconds(3)));
EXPECT_THAT(reported_throttling_times,
- ElementsAre(base::TimeDelta::FromMilliseconds(1255),
- base::TimeDelta::FromMilliseconds(1755)));
+ ElementsAre(TimeDelta::FromMilliseconds(1255),
+ TimeDelta::FromMilliseconds(1755)));
- pool->RemoveQueue(clock_->GetNowTicksWithoutAdvancing(), timer_queue_.get());
+ pool->RemoveQueue(test_task_runner_->NowTicks(), timer_queue_.get());
task_queue_throttler_->DecreaseThrottleRefCount(timer_queue_.get());
pool->Close();
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, GrantAdditionalBudget) {
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
CPUTimeBudgetPool* pool =
task_queue_throttler_->CreateCPUTimeBudgetPool("test");
- pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
- pool->AddQueue(base::TimeTicks(), timer_queue_.get());
- pool->GrantAdditionalBudget(base::TimeTicks(),
- base::TimeDelta::FromMilliseconds(500));
+ pool->SetTimeBudgetRecoveryRate(TimeTicks(), 0.1);
+ pool->AddQueue(TimeTicks(), timer_queue_.get());
+ pool->GrantAdditionalBudget(TimeTicks(), TimeDelta::FromMilliseconds(500));
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
@@ -999,21 +977,21 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, GrantAdditionalBudget) {
// budget to run.
for (int i = 0; i < 5; ++i) {
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200));
}
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(
- run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1250),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1500),
- base::TimeTicks() + base::TimeDelta::FromSeconds(3),
- base::TimeTicks() + base::TimeDelta::FromSeconds(6)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(1000),
+ TimeTicks() + TimeDelta::FromMilliseconds(1250),
+ TimeTicks() + TimeDelta::FromMilliseconds(1500),
+ TimeTicks() + TimeDelta::FromSeconds(3),
+ TimeTicks() + TimeDelta::FromSeconds(6)));
- pool->RemoveQueue(clock_->GetNowTicksWithoutAdvancing(), timer_queue_.get());
+ pool->RemoveQueue(test_task_runner_->NowTicks(), timer_queue_.get());
task_queue_throttler_->DecreaseThrottleRefCount(timer_queue_.get());
pool->Close();
}
@@ -1022,7 +1000,7 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
EnableAndDisableThrottlingAndTimeBudgets) {
// This test checks that if time budget pool is enabled when throttling
// is disabled, it does not throttle the queue.
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
task_queue_throttler_->DisableThrottling();
@@ -1030,32 +1008,31 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
task_queue_throttler_->CreateCPUTimeBudgetPool("test");
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
- LazyNow lazy_now_1(clock_.get());
+ LazyNow lazy_now_1(test_task_runner_->GetMockTickClock());
pool->DisableThrottling(&lazy_now_1);
- pool->AddQueue(base::TimeTicks(), timer_queue_.get());
+ pool->AddQueue(TimeTicks(), timer_queue_.get());
- mock_task_runner_->RunUntilTime(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(100));
+ test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(95));
- LazyNow lazy_now_2(clock_.get());
+ LazyNow lazy_now_2(test_task_runner_->GetMockTickClock());
pool->EnableThrottling(&lazy_now_2);
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(run_times, ElementsAre(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(300)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(300)));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
AddQueueToBudgetPoolWhenThrottlingDisabled) {
// This test checks that a task queue is added to time budget pool
// when throttling is disabled, is does not throttle queue.
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
task_queue_throttler_->DisableThrottling();
@@ -1063,24 +1040,23 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
task_queue_throttler_->CreateCPUTimeBudgetPool("test");
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
- mock_task_runner_->RunUntilTime(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(100));
+ test_task_runner_->FastForwardBy(TimeDelta::FromMilliseconds(95));
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200));
- pool->AddQueue(base::TimeTicks(), timer_queue_.get());
+ pool->AddQueue(TimeTicks(), timer_queue_.get());
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(run_times, ElementsAre(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(300)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(300)));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
DisabledQueueThenEnabledQueue) {
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
scoped_refptr<MainThreadTaskQueue> second_queue =
scheduler_->NewTimerTaskQueue(
@@ -1090,91 +1066,93 @@ TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
task_queue_throttler_->IncreaseThrottleRefCount(second_queue.get());
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(100));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(100));
second_queue->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200));
std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
timer_queue_->CreateQueueEnabledVoter();
voter->SetQueueEnabled(false);
- clock_->Advance(base::TimeDelta::FromMilliseconds(250));
+ test_task_runner_->AdvanceMockTickClock(TimeDelta::FromMilliseconds(250));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(run_times, ElementsAre(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(1000)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(1000)));
voter->SetQueueEnabled(true);
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(
- run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(2000)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(1000),
+ TimeTicks() + TimeDelta::FromMilliseconds(2000)));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest, TwoBudgetPools) {
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
scoped_refptr<TaskQueue> second_queue = scheduler_->NewTimerTaskQueue(
MainThreadTaskQueue::QueueType::kFrameThrottleable, nullptr);
CPUTimeBudgetPool* pool1 =
task_queue_throttler_->CreateCPUTimeBudgetPool("test");
- pool1->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
- pool1->AddQueue(base::TimeTicks(), timer_queue_.get());
- pool1->AddQueue(base::TimeTicks(), second_queue.get());
+ pool1->SetTimeBudgetRecoveryRate(TimeTicks(), 0.1);
+ pool1->AddQueue(TimeTicks(), timer_queue_.get());
+ pool1->AddQueue(TimeTicks(), second_queue.get());
CPUTimeBudgetPool* pool2 =
task_queue_throttler_->CreateCPUTimeBudgetPool("test");
- pool2->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.01);
- pool2->AddQueue(base::TimeTicks(), timer_queue_.get());
+ pool2->SetTimeBudgetRecoveryRate(TimeTicks(), 0.01);
+ pool2->AddQueue(TimeTicks(), timer_queue_.get());
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
task_queue_throttler_->IncreaseThrottleRefCount(second_queue.get());
timer_queue_->PostTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_));
second_queue->PostTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_));
timer_queue_->PostTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_));
second_queue->PostTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(
- run_times,
- ElementsAre(
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(6000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(26000)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(1000),
+ TimeTicks() + TimeDelta::FromMilliseconds(3000),
+ TimeTicks() + TimeDelta::FromMilliseconds(6000),
+ TimeTicks() + TimeDelta::FromMilliseconds(26000)));
}
namespace {
-void RunChainedTask(std::deque<base::TimeDelta> task_durations,
+void RunChainedTask(std::deque<TimeDelta> task_durations,
scoped_refptr<TaskQueue> queue,
- AutoAdvancingTestClock* clock,
- std::vector<base::TimeTicks>* run_times,
- base::TimeDelta delay) {
+ scoped_refptr<TestMockTimeTaskRunner> task_runner,
+ std::vector<TimeTicks>* run_times,
+ TimeDelta delay) {
if (task_durations.empty())
return;
- run_times->push_back(
- RoundTimeToMilliseconds(clock->GetNowTicksWithoutAdvancing()));
- clock->Advance(task_durations.front());
+ // FIXME No auto-advancing.
+
+ run_times->push_back(RoundTimeToMilliseconds(task_runner->NowTicks()));
+ task_runner->AdvanceMockTickClock(task_durations.front());
task_durations.pop_front();
queue->PostDelayedTask(
FROM_HERE,
- base::BindOnce(&RunChainedTask, std::move(task_durations), queue, clock,
- run_times, delay),
+ base::BindOnce(&RunChainedTask, std::move(task_durations), queue,
+ task_runner, run_times, delay),
delay);
}
} // namespace
@@ -1182,109 +1160,103 @@ void RunChainedTask(std::deque<base::TimeDelta> task_durations,
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
WakeUpBasedThrottling_ChainedTasks_Instantaneous) {
scheduler_->GetWakeUpBudgetPoolForTesting()->SetWakeUpDuration(
- base::TimeDelta::FromMilliseconds(10));
- std::vector<base::TimeTicks> run_times;
+ TimeDelta::FromMilliseconds(10));
+ std::vector<TimeTicks> run_times;
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
timer_queue_->PostDelayedTask(
FROM_HERE,
- base::BindOnce(&RunChainedTask,
- std::deque<base::TimeDelta>(10, base::TimeDelta()),
- timer_queue_, clock_.get(), &run_times, base::TimeDelta()),
- base::TimeDelta::FromMilliseconds(100));
-
- mock_task_runner_->RunUntilIdle();
-
- EXPECT_THAT(run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1),
- base::TimeTicks() + base::TimeDelta::FromSeconds(1),
- base::TimeTicks() + base::TimeDelta::FromSeconds(1),
- base::TimeTicks() + base::TimeDelta::FromSeconds(1),
- base::TimeTicks() + base::TimeDelta::FromSeconds(1),
- base::TimeTicks() + base::TimeDelta::FromSeconds(1),
- base::TimeTicks() + base::TimeDelta::FromSeconds(1),
- base::TimeTicks() + base::TimeDelta::FromSeconds(1),
- base::TimeTicks() + base::TimeDelta::FromSeconds(1),
- base::TimeTicks() + base::TimeDelta::FromSeconds(1)));
+ base::BindOnce(&RunChainedTask, std::deque<TimeDelta>(10, TimeDelta()),
+ timer_queue_, test_task_runner_, &run_times, TimeDelta()),
+ TimeDelta::FromMilliseconds(100));
+
+ test_task_runner_->FastForwardUntilNoTasksRemain();
+
+ EXPECT_THAT(run_times, ElementsAre(TimeTicks() + TimeDelta::FromSeconds(1),
+ TimeTicks() + TimeDelta::FromSeconds(1),
+ TimeTicks() + TimeDelta::FromSeconds(1),
+ TimeTicks() + TimeDelta::FromSeconds(1),
+ TimeTicks() + TimeDelta::FromSeconds(1),
+ TimeTicks() + TimeDelta::FromSeconds(1),
+ TimeTicks() + TimeDelta::FromSeconds(1),
+ TimeTicks() + TimeDelta::FromSeconds(1),
+ TimeTicks() + TimeDelta::FromSeconds(1),
+ TimeTicks() + TimeDelta::FromSeconds(1)));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
WakeUpBasedThrottling_ImmediateTasks_Fast) {
scheduler_->GetWakeUpBudgetPoolForTesting()->SetWakeUpDuration(
- base::TimeDelta::FromMilliseconds(10));
- std::vector<base::TimeTicks> run_times;
+ TimeDelta::FromMilliseconds(10));
+ std::vector<TimeTicks> run_times;
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
timer_queue_->PostDelayedTask(
FROM_HERE,
- base::BindOnce(
- &RunChainedTask,
- std::deque<base::TimeDelta>(10, base::TimeDelta::FromMilliseconds(3)),
- timer_queue_, clock_.get(), &run_times, base::TimeDelta()),
- base::TimeDelta::FromMilliseconds(100));
+ base::BindOnce(&RunChainedTask,
+ std::deque<TimeDelta>(10, TimeDelta::FromMilliseconds(3)),
+ timer_queue_, test_task_runner_, &run_times, TimeDelta()),
+ TimeDelta::FromMilliseconds(100));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
// TODO(altimin): Add fence mechanism to block immediate tasks.
- EXPECT_THAT(
- run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1003),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1006),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1009),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(2000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(2003),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(2006),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(2009),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(3003)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(1000),
+ TimeTicks() + TimeDelta::FromMilliseconds(1003),
+ TimeTicks() + TimeDelta::FromMilliseconds(1006),
+ TimeTicks() + TimeDelta::FromMilliseconds(1009),
+ TimeTicks() + TimeDelta::FromMilliseconds(2000),
+ TimeTicks() + TimeDelta::FromMilliseconds(2003),
+ TimeTicks() + TimeDelta::FromMilliseconds(2006),
+ TimeTicks() + TimeDelta::FromMilliseconds(2009),
+ TimeTicks() + TimeDelta::FromMilliseconds(3000),
+ TimeTicks() + TimeDelta::FromMilliseconds(3003)));
}
TEST_P(TaskQueueThrottlerWithAutoAdvancingTimeTest,
WakeUpBasedThrottling_DelayedTasks) {
scheduler_->GetWakeUpBudgetPoolForTesting()->SetWakeUpDuration(
- base::TimeDelta::FromMilliseconds(10));
- std::vector<base::TimeTicks> run_times;
+ TimeDelta::FromMilliseconds(10));
+ std::vector<TimeTicks> run_times;
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
timer_queue_->PostDelayedTask(
FROM_HERE,
- base::BindOnce(&RunChainedTask,
- std::deque<base::TimeDelta>(10, base::TimeDelta()),
- timer_queue_, clock_.get(), &run_times,
- base::TimeDelta::FromMilliseconds(3)),
- base::TimeDelta::FromMilliseconds(100));
+ base::BindOnce(&RunChainedTask, std::deque<TimeDelta>(10, TimeDelta()),
+ timer_queue_, test_task_runner_, &run_times,
+ TimeDelta::FromMilliseconds(3)),
+ TimeDelta::FromMilliseconds(100));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(
- run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1003),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1006),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1009),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(2000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(2003),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(2006),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(2009),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(3003)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(1000),
+ TimeTicks() + TimeDelta::FromMilliseconds(1003),
+ TimeTicks() + TimeDelta::FromMilliseconds(1006),
+ TimeTicks() + TimeDelta::FromMilliseconds(1009),
+ TimeTicks() + TimeDelta::FromMilliseconds(2000),
+ TimeTicks() + TimeDelta::FromMilliseconds(2003),
+ TimeTicks() + TimeDelta::FromMilliseconds(2006),
+ TimeTicks() + TimeDelta::FromMilliseconds(2009),
+ TimeTicks() + TimeDelta::FromMilliseconds(3000),
+ TimeTicks() + TimeDelta::FromMilliseconds(3003)));
}
TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottlingWithCPUBudgetThrottling) {
scheduler_->GetWakeUpBudgetPoolForTesting()->SetWakeUpDuration(
- base::TimeDelta::FromMilliseconds(10));
+ TimeDelta::FromMilliseconds(10));
CPUTimeBudgetPool* pool =
task_queue_throttler_->CreateCPUTimeBudgetPool("test");
- pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
- pool->AddQueue(base::TimeTicks(), timer_queue_.get());
+ pool->SetTimeBudgetRecoveryRate(TimeTicks(), 0.1);
+ pool->AddQueue(TimeTicks(), timer_queue_.get());
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
@@ -1292,52 +1264,50 @@ TEST_F(TaskQueueThrottlerTest, WakeUpBasedThrottlingWithCPUBudgetThrottling) {
FROM_HERE,
base::BindOnce(
&RunChainedTask,
- std::deque<base::TimeDelta>{base::TimeDelta::FromMilliseconds(250),
- base::TimeDelta(), base::TimeDelta(),
- base::TimeDelta::FromMilliseconds(250),
- base::TimeDelta(), base::TimeDelta(),
- base::TimeDelta::FromMilliseconds(250),
- base::TimeDelta(), base::TimeDelta()},
- timer_queue_, clock_.get(), &run_times, base::TimeDelta()),
- base::TimeDelta::FromMilliseconds(100));
+ std::deque<TimeDelta>{
+ TimeDelta::FromMilliseconds(250), TimeDelta(), TimeDelta(),
+ TimeDelta::FromMilliseconds(250), TimeDelta(), TimeDelta(),
+ TimeDelta::FromMilliseconds(250), TimeDelta(), TimeDelta()},
+ timer_queue_, test_task_runner_, &run_times, TimeDelta()),
+ TimeDelta::FromMilliseconds(100));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
- EXPECT_THAT(
- run_times,
- ElementsAre(base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(6000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(6000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(6000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(8000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(8000)));
+ EXPECT_THAT(run_times,
+ ElementsAre(TimeTicks() + TimeDelta::FromMilliseconds(1000),
+ TimeTicks() + TimeDelta::FromMilliseconds(3000),
+ TimeTicks() + TimeDelta::FromMilliseconds(3000),
+ TimeTicks() + TimeDelta::FromMilliseconds(3000),
+ TimeTicks() + TimeDelta::FromMilliseconds(6000),
+ TimeTicks() + TimeDelta::FromMilliseconds(6000),
+ TimeTicks() + TimeDelta::FromMilliseconds(6000),
+ TimeTicks() + TimeDelta::FromMilliseconds(8000),
+ TimeTicks() + TimeDelta::FromMilliseconds(8000)));
}
TEST_F(TaskQueueThrottlerTest,
WakeUpBasedThrottlingWithCPUBudgetThrottling_OnAndOff) {
scheduler_->GetWakeUpBudgetPoolForTesting()->SetWakeUpDuration(
- base::TimeDelta::FromMilliseconds(10));
+ TimeDelta::FromMilliseconds(10));
CPUTimeBudgetPool* pool =
task_queue_throttler_->CreateCPUTimeBudgetPool("test");
- pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.1);
- pool->AddQueue(base::TimeTicks(), timer_queue_.get());
+ pool->SetTimeBudgetRecoveryRate(TimeTicks(), 0.1);
+ pool->AddQueue(TimeTicks(), timer_queue_.get());
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
bool is_throttled = false;
for (int i = 0; i < 5; ++i) {
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(200));
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(200));
timer_queue_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&TestTask, &run_times, clock_.get()),
- base::TimeDelta::FromMilliseconds(300));
+ FROM_HERE, base::BindOnce(&TestTask, &run_times, test_task_runner_),
+ TimeDelta::FromMilliseconds(300));
if (is_throttled) {
task_queue_throttler_->DecreaseThrottleRefCount(timer_queue_.get());
@@ -1347,26 +1317,26 @@ TEST_F(TaskQueueThrottlerTest,
is_throttled = true;
}
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
}
EXPECT_THAT(run_times,
ElementsAre(
// Throttled due to cpu budget.
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000),
+ TimeTicks() + TimeDelta::FromMilliseconds(1000),
+ TimeTicks() + TimeDelta::FromMilliseconds(3000),
// Unthrottled.
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(3200),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(3450),
+ TimeTicks() + TimeDelta::FromMilliseconds(3200),
+ TimeTicks() + TimeDelta::FromMilliseconds(3450),
// Throttled due to wake-up budget. Old tasks still run.
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(5000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(5250),
+ TimeTicks() + TimeDelta::FromMilliseconds(5000),
+ TimeTicks() + TimeDelta::FromMilliseconds(5250),
// Unthrottled.
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(6200),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(6450),
+ TimeTicks() + TimeDelta::FromMilliseconds(6200),
+ TimeTicks() + TimeDelta::FromMilliseconds(6450),
// Throttled due to wake-up budget. Old tasks still run.
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(8000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(8250)));
+ TimeTicks() + TimeDelta::FromMilliseconds(8000),
+ TimeTicks() + TimeDelta::FromMilliseconds(8250)));
}
TEST_F(TaskQueueThrottlerTest,
@@ -1375,46 +1345,45 @@ TEST_F(TaskQueueThrottlerTest,
// when time budget allows that and should be blocked when time budget is
// exhausted.
scheduler_->GetWakeUpBudgetPoolForTesting()->SetWakeUpDuration(
- base::TimeDelta::FromMilliseconds(10));
+ TimeDelta::FromMilliseconds(10));
CPUTimeBudgetPool* pool =
task_queue_throttler_->CreateCPUTimeBudgetPool("test");
- pool->SetTimeBudgetRecoveryRate(base::TimeTicks(), 0.01);
- pool->AddQueue(base::TimeTicks(), timer_queue_.get());
+ pool->SetTimeBudgetRecoveryRate(TimeTicks(), 0.01);
+ pool->AddQueue(TimeTicks(), timer_queue_.get());
- std::vector<base::TimeTicks> run_times;
+ std::vector<TimeTicks> run_times;
task_queue_throttler_->IncreaseThrottleRefCount(timer_queue_.get());
timer_queue_->PostDelayedTask(
FROM_HERE,
- base::BindOnce(
- &RunChainedTask,
- std::deque<base::TimeDelta>(10, base::TimeDelta::FromMilliseconds(7)),
- timer_queue_, clock_.get(), &run_times, base::TimeDelta()),
- base::TimeDelta::FromMilliseconds(100));
+ base::BindOnce(&RunChainedTask,
+ std::deque<TimeDelta>(10, TimeDelta::FromMilliseconds(7)),
+ timer_queue_, test_task_runner_, &run_times, TimeDelta()),
+ TimeDelta::FromMilliseconds(100));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_THAT(run_times,
ElementsAre(
// Time budget is ~10ms and we can run two 7ms tasks.
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(1007),
+ TimeTicks() + TimeDelta::FromMilliseconds(1000),
+ TimeTicks() + TimeDelta::FromMilliseconds(1007),
// Time budget is ~6ms and we can run one 7ms task.
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(2000),
+ TimeTicks() + TimeDelta::FromMilliseconds(2000),
// Time budget is ~8ms and we can run two 7ms tasks.
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(3000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(3007),
+ TimeTicks() + TimeDelta::FromMilliseconds(3000),
+ TimeTicks() + TimeDelta::FromMilliseconds(3007),
// Time budget is ~5ms and we can run one 7ms task.
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(4000),
+ TimeTicks() + TimeDelta::FromMilliseconds(4000),
// Time budget is ~8ms and we can run two 7ms tasks.
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(5000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(5007),
+ TimeTicks() + TimeDelta::FromMilliseconds(5000),
+ TimeTicks() + TimeDelta::FromMilliseconds(5007),
// Time budget is ~4ms and we can run one 7ms task.
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(6000),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(7000)));
+ TimeTicks() + TimeDelta::FromMilliseconds(6000),
+ TimeTicks() + TimeDelta::FromMilliseconds(7000)));
}
} // namespace task_queue_throttler_unittest
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.cc
index dff3566df59..ca69a886b36 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.cc
@@ -4,41 +4,48 @@
#include "third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.h"
+#include "base/task/sequence_manager/sequence_manager.h"
+
namespace blink {
namespace scheduler {
-ThrottledTimeDomain::ThrottledTimeDomain() : RealTimeDomain() {}
+ThrottledTimeDomain::ThrottledTimeDomain() {}
ThrottledTimeDomain::~ThrottledTimeDomain() = default;
+base::sequence_manager::LazyNow ThrottledTimeDomain::CreateLazyNow() const {
+ return base::sequence_manager::LazyNow(sequence_manager()->GetTickClock());
+}
+
+base::TimeTicks ThrottledTimeDomain::Now() const {
+ return sequence_manager()->NowTicks();
+}
+
const char* ThrottledTimeDomain::GetName() const {
return "ThrottledTimeDomain";
}
-void ThrottledTimeDomain::RequestWakeUpAt(base::TimeTicks now,
- base::TimeTicks run_time) {
+void ThrottledTimeDomain::SetNextDelayedDoWork(
+ base::sequence_manager::LazyNow* lazy_now,
+ base::TimeTicks run_time) {
// We assume the owner (i.e. TaskQueueThrottler) will manage wake-ups on our
// behalf.
}
-void ThrottledTimeDomain::CancelWakeUpAt(base::TimeTicks run_time) {
- // We ignore this because RequestWakeUpAt is a NOP.
-}
-
void ThrottledTimeDomain::SetNextTaskRunTime(base::TimeTicks run_time) {
next_task_run_time_ = run_time;
}
base::Optional<base::TimeDelta> ThrottledTimeDomain::DelayTillNextTask(
base::sequence_manager::LazyNow* lazy_now) {
- if (next_task_run_time_ && next_task_run_time_ > lazy_now->Now())
- return next_task_run_time_.value() - lazy_now->Now();
+ base::TimeTicks now = lazy_now->Now();
+ if (next_task_run_time_ && next_task_run_time_ > now)
+ return next_task_run_time_.value() - now;
- base::TimeTicks next_run_time;
- if (!NextScheduledRunTime(&next_run_time))
+ base::Optional<base::TimeTicks> next_run_time = NextScheduledRunTime();
+ if (!next_run_time)
return base::nullopt;
- base::TimeTicks now = lazy_now->Now();
if (now >= next_run_time)
return base::TimeDelta(); // Makes DoWork post an immediate continuation.
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.h b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.h
index 29b941b720e..889a4918833 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/throttled_time_domain.h
@@ -6,15 +6,16 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_THROTTLING_THROTTLED_TIME_DOMAIN_H_
#include "base/macros.h"
-#include "third_party/blink/renderer/platform/scheduler/base/real_time_domain.h"
+#include "base/task/sequence_manager/time_domain.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
namespace blink {
namespace scheduler {
-// A time domain for throttled tasks. behaves like an RealTimeDomain except it
+// A time domain for throttled tasks. Behaves like an RealTimeDomain except it
// relies on the owner (TaskQueueThrottler) to schedule wake-ups.
class PLATFORM_EXPORT ThrottledTimeDomain
- : public base::sequence_manager::RealTimeDomain {
+ : public base::sequence_manager::TimeDomain {
public:
ThrottledTimeDomain();
~ThrottledTimeDomain() override;
@@ -22,13 +23,15 @@ class PLATFORM_EXPORT ThrottledTimeDomain
void SetNextTaskRunTime(base::TimeTicks run_time);
// TimeDomain implementation:
- const char* GetName() const override;
- void RequestWakeUpAt(base::TimeTicks now, base::TimeTicks run_time) override;
- void CancelWakeUpAt(base::TimeTicks run_time) override;
+ base::sequence_manager::LazyNow CreateLazyNow() const override;
+ base::TimeTicks Now() const override;
base::Optional<base::TimeDelta> DelayTillNextTask(
base::sequence_manager::LazyNow* lazy_now) override;
- using TimeDomain::WakeUpReadyDelayedQueues;
+ protected:
+ const char* GetName() const override;
+ void SetNextDelayedDoWork(base::sequence_manager::LazyNow* lazy_now,
+ base::TimeTicks run_time) override;
private:
// Next task run time provided by task queue throttler. Note that it does not
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.cc
index 6c1e5f2d155..48bee55d124 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.cc
@@ -37,7 +37,7 @@ void WakeUpBudgetPool::SetWakeUpDuration(base::TimeDelta duration) {
void WakeUpBudgetPool::RecordTaskRunTime(TaskQueue* queue,
base::TimeTicks start_time,
base::TimeTicks end_time) {
- budget_pool_controller_->UpdateQueueThrottlingState(end_time, queue);
+ budget_pool_controller_->UpdateQueueSchedulingLifecycleState(end_time, queue);
}
bool WakeUpBudgetPool::CanRunTasksAt(base::TimeTicks moment,
@@ -92,7 +92,7 @@ void WakeUpBudgetPool::OnQueueNextWakeUpChanged(
TaskQueue* queue,
base::TimeTicks now,
base::TimeTicks desired_run_time) {
- budget_pool_controller_->UpdateQueueThrottlingState(now, queue);
+ budget_pool_controller_->UpdateQueueSchedulingLifecycleState(now, queue);
}
void WakeUpBudgetPool::OnWakeUp(base::TimeTicks now) {
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/total_duration_metric_reporter.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/total_duration_metric_reporter.cc
new file mode 100644
index 00000000000..54ed2afdb4a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/total_duration_metric_reporter.cc
@@ -0,0 +1,47 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/common/total_duration_metric_reporter.h"
+
+namespace blink {
+namespace scheduler {
+
+namespace {
+
+constexpr base::TimeDelta kMinimalValue = base::TimeDelta::FromSeconds(1);
+constexpr base::TimeDelta kMaximalValue = base::TimeDelta::FromHours(1);
+constexpr int kBucketCount = 50;
+
+} // namespace
+
+TotalDurationMetricReporter::TotalDurationMetricReporter(
+ const char* positive_histogram_name,
+ const char* negative_histogram_name)
+ : positive_histogram_(base::Histogram::FactoryGet(
+ positive_histogram_name,
+ kMinimalValue.InSeconds(),
+ kMaximalValue.InSeconds(),
+ kBucketCount,
+ base::Histogram::kUmaTargetedHistogramFlag)),
+ negative_histogram_(base::Histogram::FactoryGet(
+ negative_histogram_name,
+ kMinimalValue.InSeconds(),
+ kMaximalValue.InSeconds(),
+ kBucketCount,
+ base::Histogram::kUmaTargetedHistogramFlag)) {}
+
+void TotalDurationMetricReporter::RecordAdditionalDuration(
+ base::TimeDelta duration) {
+ if (reported_value_)
+ negative_histogram_->Add(reported_value_->InSeconds());
+ reported_value_ = reported_value_.value_or(base::TimeDelta()) + duration;
+ positive_histogram_->Add(reported_value_->InSeconds());
+}
+
+void TotalDurationMetricReporter::Reset() {
+ reported_value_ = base::nullopt;
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/total_duration_metric_reporter.h b/chromium/third_party/blink/renderer/platform/scheduler/common/total_duration_metric_reporter.h
new file mode 100644
index 00000000000..f15e5011399
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/total_duration_metric_reporter.h
@@ -0,0 +1,43 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_TOTAL_DURATION_METRIC_REPORTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_TOTAL_DURATION_METRIC_REPORTER_H_
+
+#include "base/metrics/histogram.h"
+#include "base/optional.h"
+#include "base/time/time.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+namespace scheduler {
+
+// Helper class to measure the total duration of the event accounting for
+// possibility of the renderer process going away at any point.
+//
+// This is implemented by "undoing" old total value and "applying" new one
+// each time RecordAdditionalDuration() is called.
+// "Undoing" is implemented by having a second "negative" histogram, so to
+// obtain the result, |positive_histogram - negative_histogram| difference
+// should be analysed.
+class PLATFORM_EXPORT TotalDurationMetricReporter {
+ public:
+ TotalDurationMetricReporter(const char* positive_histogram_name,
+ const char* negative_histogram_name);
+
+ void RecordAdditionalDuration(base::TimeDelta duration);
+
+ void Reset();
+
+ private:
+ base::Optional<base::TimeDelta> reported_value_;
+
+ base::HistogramBase* positive_histogram_;
+ base::HistogramBase* negative_histogram_;
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_TOTAL_DURATION_METRIC_REPORTER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/total_duration_metric_reporter_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/total_duration_metric_reporter_unittest.cc
new file mode 100644
index 00000000000..c30cfaae128
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/total_duration_metric_reporter_unittest.cc
@@ -0,0 +1,45 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/common/total_duration_metric_reporter.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+namespace scheduler {
+
+TEST(TotalDurationMetricReporterTest, Test) {
+ base::HistogramTester histogram_tester;
+
+ TotalDurationMetricReporter metric_reporter("TestHistogram.Positive",
+ "TestHistogram.Negative");
+
+ metric_reporter.RecordAdditionalDuration(base::TimeDelta::FromSeconds(1));
+ metric_reporter.RecordAdditionalDuration(base::TimeDelta::FromSeconds(2));
+ metric_reporter.RecordAdditionalDuration(base::TimeDelta::FromSeconds(5));
+
+ metric_reporter.Reset();
+
+ metric_reporter.RecordAdditionalDuration(base::TimeDelta::FromSeconds(10));
+
+ std::map<base::Histogram::Sample, base::HistogramBase::Count> result;
+
+ for (const base::Bucket& bucket :
+ histogram_tester.GetAllSamples("TestHistogram.Positive")) {
+ result[bucket.min] += bucket.count;
+ }
+ for (const base::Bucket& bucket :
+ histogram_tester.GetAllSamples("TestHistogram.Negative")) {
+ result[bucket.min] -= bucket.count;
+ }
+
+ // 1 and 3 correspond to "reverted" values.
+ EXPECT_THAT(result, testing::UnorderedElementsAre(
+ std::make_pair(1, 0), std::make_pair(3, 0),
+ std::make_pair(8, 1), std::make_pair(10, 1)));
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/unprioritized_resource_loading_task_runner_handle.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/unprioritized_resource_loading_task_runner_handle.cc
new file mode 100644
index 00000000000..ba2f87a98fe
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/unprioritized_resource_loading_task_runner_handle.cc
@@ -0,0 +1,30 @@
+#include "third_party/blink/renderer/platform/scheduler/common/unprioritized_resource_loading_task_runner_handle.h"
+
+#include "base/memory/ptr_util.h"
+
+namespace blink {
+namespace scheduler {
+
+std::unique_ptr<UnprioritizedResourceLoadingTaskRunnerHandle>
+UnprioritizedResourceLoadingTaskRunnerHandle::WrapTaskRunner(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ DCHECK(task_runner);
+ return base::WrapUnique(
+ new UnprioritizedResourceLoadingTaskRunnerHandle(std::move(task_runner)));
+}
+
+UnprioritizedResourceLoadingTaskRunnerHandle::
+ UnprioritizedResourceLoadingTaskRunnerHandle(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ : task_runner_(std::move(task_runner)){};
+
+scoped_refptr<base::SingleThreadTaskRunner>
+UnprioritizedResourceLoadingTaskRunnerHandle::GetTaskRunner() const {
+ return task_runner_;
+}
+
+void UnprioritizedResourceLoadingTaskRunnerHandle::DidChangeRequestPriority(
+ net::RequestPriority priority) {}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/unprioritized_resource_loading_task_runner_handle.h b/chromium/third_party/blink/renderer/platform/scheduler/common/unprioritized_resource_loading_task_runner_handle.h
new file mode 100644
index 00000000000..db9e86d2e48
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/unprioritized_resource_loading_task_runner_handle.h
@@ -0,0 +1,45 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_UNPRIORITIZED_RESOURCE_LOADING_TASK_RUNNER_HANDLE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_UNPRIORITIZED_RESOURCE_LOADING_TASK_RUNNER_HANDLE_H_
+
+#include <memory>
+
+#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/public/platform/scheduler/web_resource_loading_task_runner_handle.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+namespace scheduler {
+
+// Provides a wrapper around task runners that do not support priorities.
+// Intended to be used by WebURLLoader for posting tasks that are not bound to a
+// frame.
+class PLATFORM_EXPORT UnprioritizedResourceLoadingTaskRunnerHandle
+ : public WebResourceLoadingTaskRunnerHandle {
+ public:
+ static std::unique_ptr<UnprioritizedResourceLoadingTaskRunnerHandle>
+ WrapTaskRunner(scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() const override;
+
+ void DidChangeRequestPriority(net::RequestPriority priority) override;
+
+ ~UnprioritizedResourceLoadingTaskRunnerHandle() override = default;
+
+ protected:
+ explicit UnprioritizedResourceLoadingTaskRunnerHandle(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+
+ private:
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(UnprioritizedResourceLoadingTaskRunnerHandle);
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/web_resource_loading_task_runner_handle.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/web_resource_loading_task_runner_handle.cc
new file mode 100644
index 00000000000..ced928131a4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/web_resource_loading_task_runner_handle.cc
@@ -0,0 +1,17 @@
+#include "third_party/blink/public/platform/scheduler/web_resource_loading_task_runner_handle.h"
+
+#include "third_party/blink/renderer/platform/scheduler/common/unprioritized_resource_loading_task_runner_handle.h"
+
+namespace blink {
+namespace scheduler {
+
+std::unique_ptr<WebResourceLoadingTaskRunnerHandle>
+WebResourceLoadingTaskRunnerHandle::CreateUnprioritized(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
+ DCHECK(task_runner);
+ return UnprioritizedResourceLoadingTaskRunnerHandle::WrapTaskRunner(
+ std::move(task_runner));
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/common/web_thread_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/common/web_thread_scheduler.cc
index 719d8e30b5c..2d93ae8a391 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/common/web_thread_scheduler.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/common/web_thread_scheduler.cc
@@ -4,10 +4,173 @@
#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
+#include <utility>
+#include "base/trace_event/trace_event.h"
+#include "build/build_config.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/util/tracing_helper.h"
+
namespace blink {
namespace scheduler {
-WebThreadScheduler::~WebThreadScheduler() {}
+WebThreadScheduler::~WebThreadScheduler() = default;
+
+WebThreadScheduler::RAILModeObserver::~RAILModeObserver() = default;
+
+// static
+std::unique_ptr<WebThreadScheduler>
+WebThreadScheduler::CreateMainThreadScheduler(
+ base::Optional<base::Time> initial_virtual_time) {
+ // Ensure categories appear as an option in chrome://tracing.
+ WarmupTracingCategories();
+ // Workers might be short-lived, so placing warmup here.
+ TRACE_EVENT_WARMUP_CATEGORY(TRACE_DISABLED_BY_DEFAULT("worker.scheduler"));
+
+ std::unique_ptr<MainThreadSchedulerImpl> scheduler(
+ new MainThreadSchedulerImpl(
+ base::sequence_manager::CreateSequenceManagerOnCurrentThread(),
+ initial_virtual_time));
+ return std::move(scheduler);
+}
+
+// static
+const char* WebThreadScheduler::InputEventStateToString(
+ InputEventState input_event_state) {
+ switch (input_event_state) {
+ case InputEventState::EVENT_CONSUMED_BY_COMPOSITOR:
+ return "event_consumed_by_compositor";
+ case InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD:
+ return "event_forwarded_to_main_thread";
+ default:
+ NOTREACHED();
+ return nullptr;
+ }
+}
+
+// Stubs for main thread only virtual functions.
+scoped_refptr<base::SingleThreadTaskRunner>
+WebThreadScheduler::DefaultTaskRunner() {
+ NOTREACHED();
+ return nullptr;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+WebThreadScheduler::CompositorTaskRunner() {
+ NOTREACHED();
+ return nullptr;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+WebThreadScheduler::InputTaskRunner() {
+ NOTREACHED();
+ return nullptr;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+WebThreadScheduler::IPCTaskRunner() {
+ NOTREACHED();
+ return nullptr;
+}
+
+std::unique_ptr<WebThread> WebThreadScheduler::CreateMainThread() {
+ NOTREACHED();
+ return nullptr;
+}
+
+std::unique_ptr<WebRenderWidgetSchedulingState>
+WebThreadScheduler::NewRenderWidgetSchedulingState() {
+ NOTREACHED();
+ return nullptr;
+}
+
+void WebThreadScheduler::BeginFrameNotExpectedSoon() {
+ NOTREACHED();
+}
+
+void WebThreadScheduler::BeginMainFrameNotExpectedUntil(base::TimeTicks time) {
+ NOTREACHED();
+}
+
+void WebThreadScheduler::WillBeginFrame(const viz::BeginFrameArgs& args) {
+ NOTREACHED();
+}
+
+void WebThreadScheduler::DidCommitFrameToCompositor() {
+ NOTREACHED();
+}
+
+void WebThreadScheduler::DidHandleInputEventOnCompositorThread(
+ const WebInputEvent& web_input_event,
+ InputEventState event_state) {
+ NOTREACHED();
+}
+
+void WebThreadScheduler::DidHandleInputEventOnMainThread(
+ const WebInputEvent& web_input_event,
+ WebInputEventResult result) {
+ NOTREACHED();
+}
+
+void WebThreadScheduler::DidAnimateForInputOnCompositorThread() {
+ NOTREACHED();
+}
+
+void WebThreadScheduler::SetRendererHidden(bool hidden) {
+ NOTREACHED();
+}
+
+void WebThreadScheduler::SetRendererBackgrounded(bool backgrounded) {
+ NOTREACHED();
+}
+
+void WebThreadScheduler::SetSchedulerKeepActive(bool keep_active) {
+ NOTREACHED();
+}
+
+#if defined(OS_ANDROID)
+void WebThreadScheduler::PauseTimersForAndroidWebView() {
+ NOTREACHED();
+}
+
+void WebThreadScheduler::ResumeTimersForAndroidWebView() {
+ NOTREACHED();
+}
+#endif // defined(OS_ANDROID)
+
+std::unique_ptr<WebThreadScheduler::RendererPauseHandle>
+WebThreadScheduler::PauseRenderer() {
+ NOTREACHED();
+ return nullptr;
+}
+
+bool WebThreadScheduler::IsHighPriorityWorkAnticipated() {
+ NOTREACHED();
+ return false;
+}
+
+void WebThreadScheduler::SetTopLevelBlameContext(
+ base::trace_event::BlameContext* blame_context) {
+ NOTREACHED();
+}
+
+void WebThreadScheduler::AddRAILModeObserver(RAILModeObserver* observer) {
+ NOTREACHED();
+}
+
+void WebThreadScheduler::SetRendererProcessType(RendererProcessType type) {
+ NOTREACHED();
+}
+
+WebScopedVirtualTimePauser WebThreadScheduler::CreateWebScopedVirtualTimePauser(
+ const char* name,
+ WebScopedVirtualTimePauser::VirtualTaskDuration duration) {
+ NOTREACHED();
+ return WebScopedVirtualTimePauser();
+}
+
+void WebThreadScheduler::OnMainFrameRequestedForInput() {
+ NOTREACHED();
+}
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/DEPS b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/DEPS
index 92b89d6e63d..7e5548fc57e 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/DEPS
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/DEPS
@@ -6,7 +6,10 @@ include_rules = [
]
specific_include_rules = {
- ".*test\.cc": [
- "+components/viz/test",
+ "main_thread_task_queue.h": [
+ "+base/task/sequence_manager/task_queue_impl.h",
],
+ "frame_scheduler_impl.h": [
+ "+net/base/request_priority.h"
+ ]
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.cc
index c941ca527f6..58c7a6d5592 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.cc
@@ -4,9 +4,17 @@
#include "third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h"
+#include "base/atomicops.h"
#include "base/time/time_override.h"
+#include "build/build_config.h"
#include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
+// windows.h #defines MemoryBarrier on x64. So we copy this bit
+// from base/atomicops.h to be independent of the include order in this file.
+#if defined(OS_WIN) && defined(ARCH_CPU_64_BITS)
+#undef MemoryBarrier
+#endif
+
namespace blink {
namespace scheduler {
@@ -15,38 +23,59 @@ AutoAdvancingVirtualTimeDomain::AutoAdvancingVirtualTimeDomain(
base::TimeTicks initial_time_ticks,
SchedulerHelper* helper,
BaseTimeOverridePolicy policy)
- : VirtualTimeDomain(initial_time_ticks),
- task_starvation_count_(0),
+ : task_starvation_count_(0),
max_task_starvation_count_(0),
can_advance_virtual_time_(true),
observer_(nullptr),
helper_(helper),
+ now_ticks_(initial_time_ticks),
initial_time_ticks_(initial_time_ticks),
initial_time_(initial_time),
- previous_time_(initial_time),
- time_overrides_(
- policy == BaseTimeOverridePolicy::OVERRIDE
- ? std::make_unique<base::subtle::ScopedTimeClockOverrides>(
- &AutoAdvancingVirtualTimeDomain::GetVirtualTime,
- &AutoAdvancingVirtualTimeDomain::GetVirtualTimeTicks,
- nullptr)
- : nullptr) {
- helper_->AddTaskObserver(this);
+ previous_time_(initial_time) {
DCHECK_EQ(AutoAdvancingVirtualTimeDomain::g_time_domain_, nullptr);
AutoAdvancingVirtualTimeDomain::g_time_domain_ = this;
+
+ // GetVirtualTime / GetVirtualTimeTicks access g_time_domain_.
+ base::subtle::MemoryBarrier();
+
+ if (policy == BaseTimeOverridePolicy::OVERRIDE) {
+ time_overrides_ = std::make_unique<base::subtle::ScopedTimeClockOverrides>(
+ &AutoAdvancingVirtualTimeDomain::GetVirtualTime,
+ &AutoAdvancingVirtualTimeDomain::GetVirtualTimeTicks, nullptr);
+ }
+
+ helper_->AddTaskObserver(this);
}
AutoAdvancingVirtualTimeDomain::~AutoAdvancingVirtualTimeDomain() {
helper_->RemoveTaskObserver(this);
+
+ time_overrides_.reset();
+
+ // GetVirtualTime / GetVirtualTimeTicks (the functions we may have
+ // temporariliy installed in the constructor) access g_time_domain_.
+ base::subtle::MemoryBarrier();
+
DCHECK_EQ(AutoAdvancingVirtualTimeDomain::g_time_domain_, this);
AutoAdvancingVirtualTimeDomain::g_time_domain_ = nullptr;
}
+base::sequence_manager::LazyNow AutoAdvancingVirtualTimeDomain::CreateLazyNow()
+ const {
+ base::AutoLock lock(now_ticks_lock_);
+ return base::sequence_manager::LazyNow(now_ticks_);
+}
+
+base::TimeTicks AutoAdvancingVirtualTimeDomain::Now() const {
+ base::AutoLock lock(now_ticks_lock_);
+ return now_ticks_;
+}
+
base::Optional<base::TimeDelta>
AutoAdvancingVirtualTimeDomain::DelayTillNextTask(
base::sequence_manager::LazyNow* lazy_now) {
- base::TimeTicks run_time;
- if (!NextScheduledRunTime(&run_time))
+ base::Optional<base::TimeTicks> run_time = NextScheduledRunTime();
+ if (!run_time)
return base::nullopt;
// We may have advanced virtual time past the next task when a
@@ -57,7 +86,7 @@ AutoAdvancingVirtualTimeDomain::DelayTillNextTask(
if (!can_advance_virtual_time_)
return base::nullopt;
- if (MaybeAdvanceVirtualTime(run_time)) {
+ if (MaybeAdvanceVirtualTime(*run_time)) {
task_starvation_count_ = 0;
return base::TimeDelta(); // Makes DoWork post an immediate continuation.
}
@@ -65,18 +94,19 @@ AutoAdvancingVirtualTimeDomain::DelayTillNextTask(
return base::nullopt;
}
-void AutoAdvancingVirtualTimeDomain::RequestWakeUpAt(base::TimeTicks now,
- base::TimeTicks run_time) {
- // Avoid posting pointless DoWorks. I.e. if the time domain has more then one
+void AutoAdvancingVirtualTimeDomain::SetNextDelayedDoWork(
+ base::sequence_manager::LazyNow* lazy_now,
+ base::TimeTicks run_time) {
+ // Ignore cancelation since no delayed work is actually being posted.
+ if (run_time == base::TimeTicks::Max())
+ return;
+
+ // Avoid posting pointless DoWorks, i.e. if the time domain has more then one
// scheduled wake up then we don't need to do anything.
if (can_advance_virtual_time_ && NumberOfScheduledWakeUps() == 1u)
RequestDoWork();
}
-void AutoAdvancingVirtualTimeDomain::CancelWakeUpAt(base::TimeTicks run_time) {
- // We ignore this because RequestWakeUpAt doesn't post a delayed task.
-}
-
void AutoAdvancingVirtualTimeDomain::SetObserver(Observer* observer) {
observer_ = observer;
}
@@ -116,7 +146,10 @@ bool AutoAdvancingVirtualTimeDomain::MaybeAdvanceVirtualTime(
if (new_virtual_time <= Now())
return false;
- AdvanceNowTo(new_virtual_time);
+ {
+ base::AutoLock lock(now_ticks_lock_);
+ now_ticks_ = new_virtual_time;
+ }
if (observer_)
observer_->OnVirtualTimeAdvanced();
@@ -140,8 +173,8 @@ void AutoAdvancingVirtualTimeDomain::DidProcessTask(
// Delayed tasks are being excessively starved, so allow virtual time to
// advance.
- base::TimeTicks run_time;
- if (NextScheduledRunTime(&run_time) && MaybeAdvanceVirtualTime(run_time))
+ base::Optional<base::TimeTicks> run_time = NextScheduledRunTime();
+ if (run_time && MaybeAdvanceVirtualTime(*run_time))
task_starvation_count_ = 0;
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h
index 6bae605a65b..3a3dbecddc5 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h
@@ -7,8 +7,9 @@
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
+#include "base/task/sequence_manager/time_domain.h"
#include "base/time/time_override.h"
-#include "third_party/blink/renderer/platform/scheduler/base/virtual_time_domain.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
namespace blink {
namespace scheduler {
@@ -24,7 +25,7 @@ class SchedulerHelper;
// |ABCDE (Execution with AutoAdvancingVirtualTimeDomain)
// |-----------------------------> time
class PLATFORM_EXPORT AutoAdvancingVirtualTimeDomain
- : public base::sequence_manager::VirtualTimeDomain,
+ : public base::sequence_manager::TimeDomain,
public base::MessageLoop::TaskObserver {
public:
enum class BaseTimeOverridePolicy { OVERRIDE, DO_NOT_OVERRIDE };
@@ -35,13 +36,6 @@ class PLATFORM_EXPORT AutoAdvancingVirtualTimeDomain
BaseTimeOverridePolicy policy);
~AutoAdvancingVirtualTimeDomain() override;
- // TimeDomain implementation:
- base::Optional<base::TimeDelta> DelayTillNextTask(
- base::sequence_manager::LazyNow* lazy_now) override;
- void RequestWakeUpAt(base::TimeTicks now, base::TimeTicks run_time) override;
- void CancelWakeUpAt(base::TimeTicks run_time) override;
- const char* GetName() const override;
-
class PLATFORM_EXPORT Observer {
public:
Observer();
@@ -56,7 +50,7 @@ class PLATFORM_EXPORT AutoAdvancingVirtualTimeDomain
void SetObserver(Observer* observer);
// Controls whether or not virtual time is allowed to advance, when the
- // TaskQueueManager runs out of immediate work to do.
+ // SequenceManager runs out of immediate work to do.
void SetCanAdvanceVirtualTime(bool can_advance_virtual_time);
// If non-null, virtual time may not advance past |virtual_time_fence|.
@@ -78,10 +72,22 @@ class PLATFORM_EXPORT AutoAdvancingVirtualTimeDomain
int task_starvation_count() const { return task_starvation_count_; }
+ // TimeDomain implementation:
+ base::sequence_manager::LazyNow CreateLazyNow() const override;
+ base::TimeTicks Now() const override;
+ base::Optional<base::TimeDelta> DelayTillNextTask(
+ base::sequence_manager::LazyNow* lazy_now) override;
+
+ protected:
+ const char* GetName() const override;
+ void SetNextDelayedDoWork(base::sequence_manager::LazyNow* lazy_now,
+ base::TimeTicks run_time) override;
+
private:
// Can be called on any thread.
base::Time Date() const;
+ // For base time overriding.
static base::TimeTicks GetVirtualTimeTicks();
static base::Time GetVirtualTime();
static AutoAdvancingVirtualTimeDomain* g_time_domain_;
@@ -106,6 +112,9 @@ class PLATFORM_EXPORT AutoAdvancingVirtualTimeDomain
// Upper limit on how far virtual time is allowed to advance.
base::TimeTicks virtual_time_fence_;
+ mutable base::Lock now_ticks_lock_;
+ base::TimeTicks now_ticks_;
+
const base::TimeTicks initial_time_ticks_;
const base::Time initial_time_;
base::Time previous_time_;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain_unittest.cc
index 3e96a0bd539..66e9d60b70f 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain_unittest.cc
@@ -6,14 +6,13 @@
#include <memory>
#include "base/run_loop.h"
+#include "base/task/sequence_manager/sequence_manager.h"
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/task/sequence_manager/test/test_task_queue.h"
+#include "base/task/sequence_manager/test/test_task_time_observer.h"
#include "base/test/test_mock_time_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/test_task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/test_task_time_observer.h"
#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h"
namespace blink {
@@ -33,13 +32,12 @@ class AutoAdvancingVirtualTimeDomainTest : public testing::Test {
test_task_runner_->AdvanceMockTickClock(
base::TimeDelta::FromMilliseconds(5));
scheduler_helper_.reset(new NonMainThreadSchedulerHelper(
- base::sequence_manager::TaskQueueManagerForTest::Create(
- nullptr, base::ThreadTaskRunnerHandle::Get(),
- test_task_runner_->GetMockTickClock()),
+ base::sequence_manager::SequenceManagerForTest::Create(
+ nullptr, test_task_runner_, test_task_runner_->GetMockTickClock()),
nullptr, TaskType::kInternalTest));
scheduler_helper_->AddTaskTimeObserver(&test_task_time_observer_);
- task_queue_ = scheduler_helper_->DefaultWorkerTaskQueue();
+ task_queue_ = scheduler_helper_->DefaultNonMainThreadTaskQueue();
initial_time_ = base::Time::FromJsTime(100000.0);
initial_time_ticks_ = test_task_runner_->NowTicks();
auto_advancing_time_domain_.reset(new AutoAdvancingVirtualTimeDomain(
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner.h
index 2cf9c70a920..a59ef9aa8cb 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner.h
@@ -10,7 +10,7 @@
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/child/cancelable_closure_holder.h"
+#include "third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h"
namespace blink {
namespace scheduler {
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner_unittest.cc
index f56d0e87e92..555d782d771 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner_unittest.cc
@@ -6,8 +6,8 @@
#include <memory>
-#include "base/test/simple_test_tick_clock.h"
-#include "components/viz/test/ordered_simple_task_runner.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/time/tick_clock.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -16,86 +16,88 @@ namespace scheduler {
class DeadlineTaskRunnerTest : public testing::Test {
public:
- DeadlineTaskRunnerTest() = default;
+ DeadlineTaskRunnerTest()
+ : task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+ base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED) {
+ // Null clock might trigger some assertions.
+ task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(5));
+ }
~DeadlineTaskRunnerTest() override = default;
void SetUp() override {
- clock_.reset(new base::SimpleTestTickClock());
- clock_->Advance(base::TimeDelta::FromMicroseconds(5000));
- mock_task_runner_ = new cc::OrderedSimpleTaskRunner(clock_.get(), true);
deadline_task_runner_.reset(new DeadlineTaskRunner(
base::BindRepeating(&DeadlineTaskRunnerTest::TestTask,
base::Unretained(this)),
- mock_task_runner_));
+ task_environment_.GetMainThreadTaskRunner()));
run_times_.clear();
}
- bool RunUntilIdle() { return mock_task_runner_->RunUntilIdle(); }
+ base::TimeTicks Now() {
+ return task_environment_.GetMockTickClock()->NowTicks();
+ }
- void TestTask() { run_times_.push_back(clock_->NowTicks()); }
+ void TestTask() { run_times_.push_back(Now()); }
- std::unique_ptr<base::SimpleTestTickClock> clock_;
- scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
+ base::test::ScopedTaskEnvironment task_environment_;
std::unique_ptr<DeadlineTaskRunner> deadline_task_runner_;
std::vector<base::TimeTicks> run_times_;
};
TEST_F(DeadlineTaskRunnerTest, RunOnce) {
- base::TimeTicks start_time = clock_->NowTicks();
+ base::TimeTicks start_time = Now();
base::TimeDelta delay = base::TimeDelta::FromMilliseconds(10);
- deadline_task_runner_->SetDeadline(FROM_HERE, delay, clock_->NowTicks());
- RunUntilIdle();
+ deadline_task_runner_->SetDeadline(FROM_HERE, delay, Now());
+ task_environment_.FastForwardUntilNoTasksRemain();
EXPECT_THAT(run_times_, testing::ElementsAre(start_time + delay));
};
TEST_F(DeadlineTaskRunnerTest, RunTwice) {
base::TimeDelta delay1 = base::TimeDelta::FromMilliseconds(10);
- base::TimeTicks deadline1 = clock_->NowTicks() + delay1;
- deadline_task_runner_->SetDeadline(FROM_HERE, delay1, clock_->NowTicks());
- RunUntilIdle();
+ base::TimeTicks deadline1 = Now() + delay1;
+ deadline_task_runner_->SetDeadline(FROM_HERE, delay1, Now());
+ task_environment_.FastForwardUntilNoTasksRemain();
base::TimeDelta delay2 = base::TimeDelta::FromMilliseconds(100);
- base::TimeTicks deadline2 = clock_->NowTicks() + delay2;
- deadline_task_runner_->SetDeadline(FROM_HERE, delay2, clock_->NowTicks());
- RunUntilIdle();
+ base::TimeTicks deadline2 = Now() + delay2;
+ deadline_task_runner_->SetDeadline(FROM_HERE, delay2, Now());
+ task_environment_.FastForwardUntilNoTasksRemain();
EXPECT_THAT(run_times_, testing::ElementsAre(deadline1, deadline2));
};
TEST_F(DeadlineTaskRunnerTest, EarlierDeadlinesTakePrecidence) {
- base::TimeTicks start_time = clock_->NowTicks();
+ base::TimeTicks start_time = Now();
base::TimeDelta delay1 = base::TimeDelta::FromMilliseconds(1);
base::TimeDelta delay10 = base::TimeDelta::FromMilliseconds(10);
base::TimeDelta delay100 = base::TimeDelta::FromMilliseconds(100);
- deadline_task_runner_->SetDeadline(FROM_HERE, delay100, clock_->NowTicks());
- deadline_task_runner_->SetDeadline(FROM_HERE, delay10, clock_->NowTicks());
- deadline_task_runner_->SetDeadline(FROM_HERE, delay1, clock_->NowTicks());
-
- RunUntilIdle();
+ deadline_task_runner_->SetDeadline(FROM_HERE, delay100, Now());
+ deadline_task_runner_->SetDeadline(FROM_HERE, delay10, Now());
+ deadline_task_runner_->SetDeadline(FROM_HERE, delay1, Now());
+ task_environment_.FastForwardUntilNoTasksRemain();
EXPECT_THAT(run_times_, testing::ElementsAre(start_time + delay1));
};
TEST_F(DeadlineTaskRunnerTest, LaterDeadlinesIgnored) {
- base::TimeTicks start_time = clock_->NowTicks();
+ base::TimeTicks start_time = Now();
base::TimeDelta delay100 = base::TimeDelta::FromMilliseconds(100);
base::TimeDelta delay10000 = base::TimeDelta::FromMilliseconds(10000);
- deadline_task_runner_->SetDeadline(FROM_HERE, delay100, clock_->NowTicks());
- deadline_task_runner_->SetDeadline(FROM_HERE, delay10000, clock_->NowTicks());
-
- RunUntilIdle();
+ deadline_task_runner_->SetDeadline(FROM_HERE, delay100, Now());
+ deadline_task_runner_->SetDeadline(FROM_HERE, delay10000, Now());
+ task_environment_.FastForwardUntilNoTasksRemain();
EXPECT_THAT(run_times_, testing::ElementsAre(start_time + delay100));
};
TEST_F(DeadlineTaskRunnerTest, DeleteDeadlineTaskRunnerAfterPosting) {
deadline_task_runner_->SetDeadline(
- FROM_HERE, base::TimeDelta::FromMilliseconds(10), clock_->NowTicks());
+ FROM_HERE, base::TimeDelta::FromMilliseconds(10), Now());
// Deleting the pending task should cancel it.
deadline_task_runner_.reset(nullptr);
- RunUntilIdle();
+ task_environment_.FastForwardUntilNoTasksRemain();
EXPECT_TRUE(run_times_.empty());
};
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
index b061db7db52..f94bcb88e6d 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -5,42 +5,25 @@
#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
#include <memory>
+
#include "base/metrics/histogram_macros.h"
#include "base/trace_event/blame_context.h"
#include "third_party/blink/public/platform/blame_context.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/scheduler/base/real_time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/base/virtual_time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/child/default_params.h"
-#include "third_party/blink/renderer/platform/scheduler/child/page_visibility_state.h"
+#include "third_party/blink/renderer/platform/scheduler/child/features.h"
#include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
-#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/resource_loading_task_runner_handle_impl.h"
#include "third_party/blink/renderer/platform/scheduler/util/tracing_helper.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h"
namespace blink {
-// static
-const char* FrameScheduler::ThrottlingStateToString(ThrottlingState state) {
- switch (state) {
- case ThrottlingState::kNotThrottled:
- return "not throttled";
- case ThrottlingState::kHidden:
- return "hidden";
- case ThrottlingState::kThrottled:
- return "throttled";
- case ThrottlingState::kStopped:
- return "frozen";
- default:
- NOTREACHED();
- return nullptr;
- }
-}
-
namespace scheduler {
using base::sequence_manager::TaskQueue;
@@ -79,6 +62,17 @@ const char* KeepActiveStateToString(bool keep_active) {
}
}
+// Used to update the priority of task_queue. Note that this function is
+// used for queues associated with a frame.
+void UpdatePriority(MainThreadTaskQueue* task_queue) {
+ if (!task_queue)
+ return;
+
+ FrameSchedulerImpl* frame_scheduler = task_queue->GetFrameScheduler();
+ DCHECK(frame_scheduler);
+ task_queue->SetQueuePriority(frame_scheduler->ComputePriority(task_queue));
+}
+
} // namespace
FrameSchedulerImpl::ActiveConnectionHandleImpl::ActiveConnectionHandleImpl(
@@ -88,19 +82,35 @@ FrameSchedulerImpl::ActiveConnectionHandleImpl::ActiveConnectionHandleImpl(
}
FrameSchedulerImpl::ActiveConnectionHandleImpl::~ActiveConnectionHandleImpl() {
- if (frame_scheduler_)
- frame_scheduler_->DidCloseActiveConnection();
+ if (frame_scheduler_) {
+ static_cast<FrameSchedulerImpl*>(frame_scheduler_.get())
+ ->DidCloseActiveConnection();
+ }
}
-FrameSchedulerImpl::ThrottlingObserverHandleImpl::ThrottlingObserverHandleImpl(
- FrameSchedulerImpl* frame_scheduler,
- Observer* observer)
- : frame_scheduler_(frame_scheduler->GetWeakPtr()), observer_(observer) {}
+FrameSchedulerImpl::PauseSubresourceLoadingHandleImpl::
+ PauseSubresourceLoadingHandleImpl(
+ base::WeakPtr<FrameSchedulerImpl> frame_scheduler)
+ : frame_scheduler_(std::move(frame_scheduler)) {
+ DCHECK(frame_scheduler_);
+ frame_scheduler_->AddPauseSubresourceLoadingHandle();
+}
-FrameSchedulerImpl::ThrottlingObserverHandleImpl::
- ~ThrottlingObserverHandleImpl() {
+FrameSchedulerImpl::PauseSubresourceLoadingHandleImpl::
+ ~PauseSubresourceLoadingHandleImpl() {
if (frame_scheduler_)
- frame_scheduler_->RemoveThrottlingObserver(observer_);
+ frame_scheduler_->RemovePauseSubresourceLoadingHandle();
+}
+
+std::unique_ptr<FrameSchedulerImpl> FrameSchedulerImpl::Create(
+ PageSchedulerImpl* parent_page_scheduler,
+ base::trace_event::BlameContext* blame_context,
+ FrameScheduler::FrameType frame_type) {
+ std::unique_ptr<FrameSchedulerImpl> frame_scheduler(
+ new FrameSchedulerImpl(parent_page_scheduler->GetMainThreadScheduler(),
+ parent_page_scheduler, blame_context, frame_type));
+ parent_page_scheduler->RegisterFrameSchedulerImpl(frame_scheduler.get());
+ return frame_scheduler;
}
FrameSchedulerImpl::FrameSchedulerImpl(
@@ -109,10 +119,11 @@ FrameSchedulerImpl::FrameSchedulerImpl(
base::trace_event::BlameContext* blame_context,
FrameScheduler::FrameType frame_type)
: frame_type_(frame_type),
+ is_ad_frame_(false),
main_thread_scheduler_(main_thread_scheduler),
parent_page_scheduler_(parent_page_scheduler),
blame_context_(blame_context),
- throttling_state_(FrameScheduler::ThrottlingState::kNotThrottled),
+ throttling_state_(SchedulingLifecycleState::kNotThrottled),
frame_visible_(true,
"FrameScheduler.FrameVisible",
this,
@@ -130,6 +141,11 @@ FrameSchedulerImpl::FrameSchedulerImpl(
this,
&tracing_controller_,
FrameOriginTypeToString),
+ subresource_loading_paused_(false,
+ "FrameScheduler.SubResourceLoadingPaused",
+ this,
+ &tracing_controller_,
+ PausedStateToString),
url_tracer_("FrameScheduler.URL", this),
task_queue_throttled_(false,
"FrameScheduler.TaskQueueThrottled",
@@ -137,30 +153,37 @@ FrameSchedulerImpl::FrameSchedulerImpl(
&tracing_controller_,
YesNoStateToString),
active_connection_count_(0),
+ subresource_loading_pause_count_(0u),
has_active_connection_(false,
"FrameScheduler.HasActiveConnection",
this,
&tracing_controller_,
YesNoStateToString),
- page_frozen_for_tracing_(parent_page_scheduler_->IsFrozen(),
- "FrameScheduler.PageFrozen",
- this,
- &tracing_controller_,
- FrozenStateToString),
- page_visibility_for_tracing_(parent_page_scheduler_->IsPageVisible()
- ? PageVisibilityState::kVisible
- : PageVisibilityState::kHidden,
- "FrameScheduler.PageVisibility",
- this,
- &tracing_controller_,
- PageVisibilityStateToString),
- page_keep_active_for_tracing_(parent_page_scheduler_->KeepActive(),
- "FrameScheduler.KeepActive",
- this,
- &tracing_controller_,
- KeepActiveStateToString),
+ page_frozen_for_tracing_(
+ parent_page_scheduler_ ? parent_page_scheduler_->IsFrozen() : true,
+ "FrameScheduler.PageFrozen",
+ this,
+ &tracing_controller_,
+ FrozenStateToString),
+ page_visibility_for_tracing_(
+ parent_page_scheduler_ && parent_page_scheduler_->IsPageVisible()
+ ? PageVisibilityState::kVisible
+ : PageVisibilityState::kHidden,
+ "FrameScheduler.PageVisibility",
+ this,
+ &tracing_controller_,
+ PageVisibilityStateToString),
+ page_keep_active_for_tracing_(
+ parent_page_scheduler_ ? parent_page_scheduler_->KeepActive() : false,
+ "FrameScheduler.KeepActive",
+ this,
+ &tracing_controller_,
+ KeepActiveStateToString),
weak_factory_(this) {}
+FrameSchedulerImpl::FrameSchedulerImpl()
+ : FrameSchedulerImpl(nullptr, nullptr, nullptr, FrameType::kSubframe) {}
+
namespace {
void CleanUpQueue(MainThreadTaskQueue* queue) {
@@ -186,6 +209,10 @@ FrameSchedulerImpl::~FrameSchedulerImpl() {
CleanUpQueue(pausable_task_queue_.get());
CleanUpQueue(unpausable_task_queue_.get());
+ for (const auto& pair : resource_loading_task_queues_) {
+ CleanUpQueue(pair.key.get());
+ }
+
if (parent_page_scheduler_) {
parent_page_scheduler_->Unregister(this);
@@ -219,22 +246,6 @@ void FrameSchedulerImpl::
throttleable_task_queue_.get());
}
-std::unique_ptr<FrameScheduler::ThrottlingObserverHandle>
-FrameSchedulerImpl::AddThrottlingObserver(ObserverType type,
- Observer* observer) {
- DCHECK(observer);
- observer->OnThrottlingStateChanged(CalculateThrottlingState(type));
- throttling_observers_[observer] = type;
- return std::make_unique<ThrottlingObserverHandleImpl>(this, observer);
-}
-
-void FrameSchedulerImpl::RemoveThrottlingObserver(Observer* observer) {
- DCHECK(observer);
- const auto found = throttling_observers_.find(observer);
- DCHECK(throttling_observers_.end() != found);
- throttling_observers_.erase(found);
-}
-
void FrameSchedulerImpl::SetFrameVisible(bool frame_visible) {
DCHECK(parent_page_scheduler_);
if (frame_visible_ == frame_visible)
@@ -262,6 +273,15 @@ void FrameSchedulerImpl::SetCrossOrigin(bool cross_origin) {
UpdatePolicy();
}
+void FrameSchedulerImpl::SetIsAdFrame() {
+ is_ad_frame_ = true;
+ UpdatePolicy();
+}
+
+bool FrameSchedulerImpl::IsAdFrame() const {
+ return is_ad_frame_;
+}
+
bool FrameSchedulerImpl::IsCrossOrigin() const {
return frame_origin_type_ == FrameOriginType::kCrossOriginFrame;
}
@@ -282,6 +302,7 @@ scoped_refptr<base::SingleThreadTaskRunner> FrameSchedulerImpl::GetTaskRunner(
return TaskQueueWithTaskType::Create(ThrottleableTaskQueue(), type);
case TaskType::kInternalLoading:
case TaskType::kNetworking:
+ case TaskType::kNetworkingWithURLLoaderAnnotation:
return TaskQueueWithTaskType::Create(LoadingTaskQueue(), type);
case TaskType::kNetworkingControl:
return TaskQueueWithTaskType::Create(LoadingControlTaskQueue(), type);
@@ -312,19 +333,20 @@ scoped_refptr<base::SingleThreadTaskRunner> FrameSchedulerImpl::GetTaskRunner(
// PostedMessage can be used for navigation, so we shouldn't defer it
// when expecting a user gesture.
case TaskType::kPostedMessage:
+ case TaskType::kWorkerAnimation:
// UserInteraction tasks should be run even when expecting a user gesture.
case TaskType::kUserInteraction:
// Media events should not be deferred to ensure that media playback is
// smooth.
case TaskType::kMediaElementEvent:
+ case TaskType::kInternalTest:
+ case TaskType::kInternalWebCrypto:
case TaskType::kInternalIndexedDB:
case TaskType::kInternalMedia:
case TaskType::kInternalMediaRealTime:
case TaskType::kInternalUserInteraction:
+ case TaskType::kInternalIntersectionObserver:
return TaskQueueWithTaskType::Create(PausableTaskQueue(), type);
- case TaskType::kUnthrottled:
- case TaskType::kInternalTest:
- case TaskType::kInternalWebCrypto:
case TaskType::kInternalIPC:
// The TaskType of Inspector tasks needs to be unpausable because they need
// to run even on a paused page.
@@ -333,7 +355,6 @@ scoped_refptr<base::SingleThreadTaskRunner> FrameSchedulerImpl::GetTaskRunner(
// unthrottled and undeferred) not to prevent service workers that may
// control browser navigation on multiple tabs.
case TaskType::kInternalWorker:
- case TaskType::kInternalIntersectionObserver:
return TaskQueueWithTaskType::Create(UnpausableTaskQueue(), type);
case TaskType::kDeprecatedNone:
case TaskType::kMainThreadTaskQueueV8:
@@ -344,7 +365,10 @@ scoped_refptr<base::SingleThreadTaskRunner> FrameSchedulerImpl::GetTaskRunner(
case TaskType::kMainThreadTaskQueueIPC:
case TaskType::kMainThreadTaskQueueControl:
case TaskType::kCompositorThreadTaskQueueDefault:
+ case TaskType::kCompositorThreadTaskQueueInput:
case TaskType::kWorkerThreadTaskQueueDefault:
+ case TaskType::kWorkerThreadTaskQueueV8:
+ case TaskType::kWorkerThreadTaskQueueCompositor:
case TaskType::kCount:
NOTREACHED();
break;
@@ -353,20 +377,87 @@ scoped_refptr<base::SingleThreadTaskRunner> FrameSchedulerImpl::GetTaskRunner(
return nullptr;
}
+std::pair<scoped_refptr<MainThreadTaskQueue>,
+ std::unique_ptr<TaskQueue::QueueEnabledVoter>>
+FrameSchedulerImpl::CreateNewLoadingTaskQueue() {
+ // TODO(panicker): Avoid adding this queue in RS task_runners_.
+ scoped_refptr<MainThreadTaskQueue> loading_task_queue =
+ main_thread_scheduler_->NewLoadingTaskQueue(
+ MainThreadTaskQueue::QueueType::kFrameLoading, this);
+ loading_task_queue->SetBlameContext(blame_context_);
+ std::unique_ptr<TaskQueue::QueueEnabledVoter> voter =
+ loading_task_queue->CreateQueueEnabledVoter();
+ voter->SetQueueEnabled(!frame_paused_);
+ return std::make_pair(loading_task_queue, std::move(voter));
+}
+
scoped_refptr<TaskQueue> FrameSchedulerImpl::LoadingTaskQueue() {
DCHECK(parent_page_scheduler_);
if (!loading_task_queue_) {
- // TODO(panicker): Avoid adding this queue in RS task_runners_.
- loading_task_queue_ = main_thread_scheduler_->NewLoadingTaskQueue(
- MainThreadTaskQueue::QueueType::kFrameLoading, this);
- loading_task_queue_->SetBlameContext(blame_context_);
- loading_queue_enabled_voter_ =
- loading_task_queue_->CreateQueueEnabledVoter();
- loading_queue_enabled_voter_->SetQueueEnabled(!frame_paused_);
+ auto queue_voter_pair = CreateNewLoadingTaskQueue();
+ loading_task_queue_ = queue_voter_pair.first;
+ loading_queue_enabled_voter_ = std::move(queue_voter_pair.second);
}
return loading_task_queue_;
}
+std::unique_ptr<WebResourceLoadingTaskRunnerHandle>
+FrameSchedulerImpl::CreateResourceLoadingTaskRunnerHandle() {
+ return CreateResourceLoadingTaskRunnerHandleImpl();
+}
+
+std::unique_ptr<ResourceLoadingTaskRunnerHandleImpl>
+FrameSchedulerImpl::CreateResourceLoadingTaskRunnerHandleImpl() {
+ if (main_thread_scheduler_->scheduling_settings()
+ .use_resource_fetch_priority ||
+ (parent_page_scheduler_->IsLoading() &&
+ main_thread_scheduler_->scheduling_settings()
+ .use_resource_priorities_only_during_loading)) {
+ auto queue_voter_pair = CreateNewLoadingTaskQueue();
+
+ resource_loading_task_queues_.insert(
+ queue_voter_pair.first, ResourceLoadingTaskQueueMetadata(
+ queue_voter_pair.first->GetQueuePriority(),
+ std::move(queue_voter_pair.second)));
+
+ return ResourceLoadingTaskRunnerHandleImpl::WrapTaskRunner(
+ queue_voter_pair.first);
+ }
+
+ // Make sure the loading task queue exists.
+ LoadingTaskQueue();
+ return ResourceLoadingTaskRunnerHandleImpl::WrapTaskRunner(
+ loading_task_queue_);
+}
+
+void FrameSchedulerImpl::DidChangeResourceLoadingPriority(
+ scoped_refptr<MainThreadTaskQueue> task_queue,
+ net::RequestPriority priority) {
+ // This check is done since in some cases (when kUseResourceFetchPriority
+ // feature isn't enabled) we use |loading_task_queue_| for resource loading
+ // and the priority of this queue shouldn't be affected by resource
+ // priorities.
+ auto queue_metadata_pair = resource_loading_task_queues_.find(task_queue);
+ if (queue_metadata_pair != resource_loading_task_queues_.end()) {
+ queue_metadata_pair->value.priority =
+ main_thread_scheduler_->scheduling_settings()
+ .net_to_blink_priority[priority];
+ UpdateQueuePolicy(task_queue.get(), queue_metadata_pair->value.voter.get());
+ }
+}
+
+void FrameSchedulerImpl::OnShutdownResourceLoadingTaskQueue(
+ scoped_refptr<MainThreadTaskQueue> task_queue) {
+ // This check is done since in some cases (when kUseResourceFetchPriority
+ // feature isn't enabled) we use |loading_task_queue_| for resource loading,
+ // and the lifetime of this queue isn't bound to one resource.
+ auto iter = resource_loading_task_queues_.find(task_queue);
+ if (iter != resource_loading_task_queues_.end()) {
+ resource_loading_task_queues_.erase(iter);
+ CleanUpQueue(task_queue.get());
+ }
+}
+
scoped_refptr<TaskQueue> FrameSchedulerImpl::LoadingControlTaskQueue() {
DCHECK(parent_page_scheduler_);
if (!loading_control_task_queue_) {
@@ -511,6 +602,9 @@ void FrameSchedulerImpl::AsValueInto(
frame_type_ == FrameScheduler::FrameType::kMainFrame
? "MainFrame"
: "Subframe");
+ state->SetBoolean(
+ "disable_background_timer_throttling",
+ !RuntimeEnabledFeatures::TimerThrottlingForBackgroundTabsEnabled());
if (loading_task_queue_) {
state->SetString("loading_task_queue",
PointerToString(loading_task_queue_.get()));
@@ -535,6 +629,13 @@ void FrameSchedulerImpl::AsValueInto(
state->SetString("unpausable_task_queue",
PointerToString(unpausable_task_queue_.get()));
}
+
+ state->BeginArray("resource_loading_task_queues");
+ for (const auto& queue : resource_loading_task_queues_) {
+ state->AppendString(PointerToString(queue.key.get()));
+ }
+ state->EndArray();
+
if (blame_context_) {
state->BeginDictionary("blame_context");
state->SetString(
@@ -555,6 +656,11 @@ bool FrameSchedulerImpl::IsPageVisible() const {
: true;
}
+bool FrameSchedulerImpl::IsAudioPlaying() const {
+ return parent_page_scheduler_ ? parent_page_scheduler_->IsAudioPlaying()
+ : false;
+}
+
void FrameSchedulerImpl::SetPaused(bool frame_paused) {
DCHECK(parent_page_scheduler_);
if (frame_paused_ == frame_paused)
@@ -583,16 +689,24 @@ void FrameSchedulerImpl::UpdatePolicy() {
UpdateQueuePolicy(deferrable_task_queue_,
deferrable_queue_enabled_voter_.get());
UpdateQueuePolicy(pausable_task_queue_, pausable_queue_enabled_voter_.get());
+ UpdateQueuePolicy(unpausable_task_queue_, nullptr);
+
+ for (const auto& pair : resource_loading_task_queues_) {
+ UpdateQueuePolicy(pair.key, pair.value.voter.get());
+ }
UpdateThrottling();
- NotifyThrottlingObservers();
+ NotifyLifecycleObservers();
}
void FrameSchedulerImpl::UpdateQueuePolicy(
const scoped_refptr<MainThreadTaskQueue>& queue,
TaskQueue::QueueEnabledVoter* voter) {
- if (!queue || !voter)
+ if (!queue)
+ return;
+ UpdatePriority(queue.get());
+ if (!voter)
return;
DCHECK(parent_page_scheduler_);
bool queue_paused = frame_paused_ && queue->CanBePaused();
@@ -604,34 +718,28 @@ void FrameSchedulerImpl::UpdateQueuePolicy(
voter->SetQueueEnabled(!queue_paused && !queue_frozen);
}
-void FrameSchedulerImpl::NotifyThrottlingObservers() {
- for (const auto& observer : throttling_observers_) {
- observer.first->OnThrottlingStateChanged(
- CalculateThrottlingState(observer.second));
- }
-}
-
-FrameScheduler::ThrottlingState FrameSchedulerImpl::CalculateThrottlingState(
+SchedulingLifecycleState FrameSchedulerImpl::CalculateLifecycleState(
ObserverType type) const {
// Detached frames are not throttled.
if (!parent_page_scheduler_)
- return FrameScheduler::ThrottlingState::kNotThrottled;
+ return SchedulingLifecycleState::kNotThrottled;
- if (RuntimeEnabledFeatures::StopLoadingInBackgroundEnabled() &&
- parent_page_scheduler_->IsFrozen() &&
+ if (parent_page_scheduler_->IsFrozen() &&
!parent_page_scheduler_->KeepActive()) {
DCHECK(!parent_page_scheduler_->IsPageVisible());
- return FrameScheduler::ThrottlingState::kStopped;
+ return SchedulingLifecycleState::kStopped;
}
+ if (subresource_loading_paused_ && type == ObserverType::kLoader)
+ return SchedulingLifecycleState::kStopped;
if (type == ObserverType::kLoader &&
parent_page_scheduler_->HasActiveConnection()) {
- return FrameScheduler::ThrottlingState::kNotThrottled;
+ return SchedulingLifecycleState::kNotThrottled;
}
if (parent_page_scheduler_->IsThrottled())
- return FrameScheduler::ThrottlingState::kThrottled;
+ return SchedulingLifecycleState::kThrottled;
if (!parent_page_scheduler_->IsPageVisible())
- return FrameScheduler::ThrottlingState::kHidden;
- return FrameScheduler::ThrottlingState::kNotThrottled;
+ return SchedulingLifecycleState::kHidden;
+ return SchedulingLifecycleState::kNotThrottled;
}
void FrameSchedulerImpl::OnFirstMeaningfulPaint() {
@@ -644,6 +752,8 @@ FrameSchedulerImpl::OnActiveConnectionCreated() {
}
bool FrameSchedulerImpl::ShouldThrottleTimers() const {
+ if (!RuntimeEnabledFeatures::TimerThrottlingForBackgroundTabsEnabled())
+ return false;
if (parent_page_scheduler_ && parent_page_scheduler_->IsAudioPlaying())
return false;
if (!parent_page_scheduler_->IsPageVisible())
@@ -673,13 +783,133 @@ void FrameSchedulerImpl::UpdateThrottling() {
}
}
-base::WeakPtr<FrameSchedulerImpl> FrameSchedulerImpl::GetWeakPtr() {
- return weak_factory_.GetWeakPtr();
-}
-
bool FrameSchedulerImpl::IsExemptFromBudgetBasedThrottling() const {
return has_active_connection();
}
+TaskQueue::QueuePriority FrameSchedulerImpl::ComputePriority(
+ MainThreadTaskQueue* task_queue) const {
+ DCHECK(task_queue);
+
+ FrameScheduler* frame_scheduler = task_queue->GetFrameScheduler();
+
+ // Checks the task queue is associated with this frame scheduler.
+ DCHECK_EQ(frame_scheduler, this);
+
+ auto queue_metadata_pair =
+ resource_loading_task_queues_.find(base::WrapRefCounted(task_queue));
+ if (queue_metadata_pair != resource_loading_task_queues_.end()) {
+ return queue_metadata_pair->value.priority;
+ }
+
+ base::Optional<TaskQueue::QueuePriority> fixed_priority =
+ task_queue->FixedPriority();
+
+ if (fixed_priority)
+ return fixed_priority.value();
+
+ // A hidden page with no audio.
+ if (parent_page_scheduler_->IsBackgrounded()) {
+ if (main_thread_scheduler_->scheduling_settings()
+ .low_priority_background_page)
+ return TaskQueue::QueuePriority::kLowPriority;
+
+ if (main_thread_scheduler_->scheduling_settings()
+ .best_effort_background_page)
+ return TaskQueue::QueuePriority::kBestEffortPriority;
+ }
+
+ // If the page is loading or if the priority experiments should take place at
+ // all times.
+ if (parent_page_scheduler_->IsLoading() ||
+ !main_thread_scheduler_->scheduling_settings()
+ .use_frame_priorities_only_during_loading) {
+ // Low priority feature enabled for hidden frame.
+ if (main_thread_scheduler_->scheduling_settings()
+ .low_priority_hidden_frame &&
+ !IsFrameVisible())
+ return TaskQueue::QueuePriority::kLowPriority;
+
+ bool is_subframe = GetFrameType() == FrameScheduler::FrameType::kSubframe;
+ bool is_throttleable_task_queue =
+ task_queue->queue_type() ==
+ MainThreadTaskQueue::QueueType::kFrameThrottleable;
+
+ // Low priority feature enabled for sub-frame.
+ if (main_thread_scheduler_->scheduling_settings().low_priority_subframe &&
+ is_subframe)
+ return TaskQueue::QueuePriority::kLowPriority;
+
+ // Low priority feature enabled for sub-frame throttleable task queues.
+ if (main_thread_scheduler_->scheduling_settings()
+ .low_priority_subframe_throttleable &&
+ is_subframe && is_throttleable_task_queue)
+ return TaskQueue::QueuePriority::kLowPriority;
+
+ // Low priority feature enabled for throttleable task queues.
+ if (main_thread_scheduler_->scheduling_settings()
+ .low_priority_throttleable &&
+ is_throttleable_task_queue)
+ return TaskQueue::QueuePriority::kLowPriority;
+ }
+
+ // Ad frame experiment.
+ if (IsAdFrame() && (parent_page_scheduler_->IsLoading() ||
+ !main_thread_scheduler_->scheduling_settings()
+ .use_adframe_priorities_only_during_loading)) {
+ if (main_thread_scheduler_->scheduling_settings().low_priority_ad_frame) {
+ return TaskQueue::QueuePriority::kLowPriority;
+ }
+
+ if (main_thread_scheduler_->scheduling_settings().best_effort_ad_frame) {
+ return TaskQueue::QueuePriority::kBestEffortPriority;
+ }
+ }
+
+ // Frame origin type experiment.
+ if (IsCrossOrigin()) {
+ if (main_thread_scheduler_->scheduling_settings()
+ .low_priority_cross_origin ||
+ (main_thread_scheduler_->scheduling_settings()
+ .low_priority_cross_origin_only_during_loading &&
+ parent_page_scheduler_->IsLoading())) {
+ return TaskQueue::QueuePriority::kLowPriority;
+ }
+ }
+
+ return task_queue->queue_type() ==
+ MainThreadTaskQueue::QueueType::kFrameLoadingControl
+ ? TaskQueue::QueuePriority::kHighPriority
+ : TaskQueue::QueuePriority::kNormalPriority;
+}
+
+std::unique_ptr<blink::mojom::blink::PauseSubresourceLoadingHandle>
+FrameSchedulerImpl::GetPauseSubresourceLoadingHandle() {
+ return std::make_unique<PauseSubresourceLoadingHandleImpl>(
+ weak_factory_.GetWeakPtr());
+}
+
+void FrameSchedulerImpl::AddPauseSubresourceLoadingHandle() {
+ ++subresource_loading_pause_count_;
+ if (subresource_loading_pause_count_ != 1) {
+ DCHECK(subresource_loading_paused_);
+ return;
+ }
+
+ DCHECK(!subresource_loading_paused_);
+ subresource_loading_paused_ = true;
+ UpdatePolicy();
+}
+
+void FrameSchedulerImpl::RemovePauseSubresourceLoadingHandle() {
+ DCHECK_LT(0u, subresource_loading_pause_count_);
+ --subresource_loading_pause_count_;
+ DCHECK(subresource_loading_paused_);
+ if (subresource_loading_pause_count_ == 0) {
+ subresource_loading_paused_ = false;
+ UpdatePolicy();
+ }
+}
+
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
index 43f223c2c6f..1f5cb1c0d65 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
@@ -6,19 +6,22 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_FRAME_SCHEDULER_IMPL_H_
#include <memory>
+#include <utility>
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
+#include "base/task/sequence_manager/task_queue.h"
#include "base/trace_event/trace_event.h"
+#include "net/base/request_priority.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/child/page_visibility_state.h"
-#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/util/tracing_helper.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
namespace base {
namespace sequence_manager {
@@ -36,6 +39,7 @@ namespace scheduler {
class MainThreadSchedulerImpl;
class MainThreadTaskQueue;
class PageSchedulerImpl;
+class ResourceLoadingTaskRunnerHandleImpl;
namespace main_thread_scheduler_impl_unittest {
class MainThreadSchedulerImplTest;
@@ -51,27 +55,38 @@ class PageSchedulerImplTest;
class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler {
public:
- FrameSchedulerImpl(MainThreadSchedulerImpl* main_thread_scheduler,
- PageSchedulerImpl* parent_page_scheduler,
- base::trace_event::BlameContext* blame_context,
- FrameScheduler::FrameType frame_type);
-
+ static std::unique_ptr<FrameSchedulerImpl> Create(
+ PageSchedulerImpl* page_scheduler,
+ base::trace_event::BlameContext* blame_context,
+ FrameScheduler::FrameType frame_type);
~FrameSchedulerImpl() override;
// FrameScheduler implementation:
- std::unique_ptr<ThrottlingObserverHandle> AddThrottlingObserver(
- ObserverType,
- Observer*) override;
void SetFrameVisible(bool frame_visible) override;
bool IsFrameVisible() const override;
+
bool IsPageVisible() const override;
+ bool IsAudioPlaying() const;
+
void SetPaused(bool frame_paused) override;
void SetCrossOrigin(bool cross_origin) override;
bool IsCrossOrigin() const override;
+
+ void SetIsAdFrame() override;
+ bool IsAdFrame() const override;
+
void TraceUrlChange(const String& url) override;
FrameScheduler::FrameType GetFrameType() const override;
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) override;
+
+ // Returns a wrapper around an instance of MainThreadTaskQueue which is
+ // maintained in |resource_loading_task_queues_| map. The main thread task
+ // queue is removed from the map and detached from both the main thread and
+ // the frame schedulers when the wrapper instance goes out of scope.
+ std::unique_ptr<WebResourceLoadingTaskRunnerHandle>
+ CreateResourceLoadingTaskRunnerHandle() override;
+
PageScheduler* GetPageScheduler() const override;
void DidStartProvisionalLoad(bool is_main_frame) override;
void DidCommitProvisionalLoad(bool is_web_history_inert_commit,
@@ -84,6 +99,8 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler {
std::unique_ptr<ActiveConnectionHandle> OnActiveConnectionCreated() override;
void AsValueInto(base::trace_event::TracedValue* state) const;
bool IsExemptFromBudgetBasedThrottling() const override;
+ std::unique_ptr<blink::mojom::blink::PauseSubresourceLoadingHandle>
+ GetPauseSubresourceLoadingHandle() override;
scoped_refptr<base::SingleThreadTaskRunner> ControlTaskRunner();
@@ -97,11 +114,35 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler {
void SetPageKeepActiveForTracing(bool keep_active);
void SetPageFrozenForTracing(bool frozen);
+ // Computes the priority of |task_queue| if it is associated to this frame
+ // scheduler. Note that the main's thread policy should be upto date to
+ // compute the correct priority.
+ base::sequence_manager::TaskQueue::QueuePriority ComputePriority(
+ MainThreadTaskQueue* task_queue) const;
+
+ protected:
+ FrameSchedulerImpl(MainThreadSchedulerImpl* main_thread_scheduler,
+ PageSchedulerImpl* parent_page_scheduler,
+ base::trace_event::BlameContext* blame_context,
+ FrameScheduler::FrameType frame_type);
+
+ // This will construct a subframe that is not linked to any main thread or
+ // page scheduler. Should be used only for testing purposes.
+ FrameSchedulerImpl();
+
+ void OnShutdownResourceLoadingTaskQueue(
+ scoped_refptr<MainThreadTaskQueue> task_queue);
+
+ void DidChangeResourceLoadingPriority(
+ scoped_refptr<MainThreadTaskQueue> task_queue,
+ net::RequestPriority priority);
+
private:
friend class PageSchedulerImpl;
friend class main_thread_scheduler_impl_unittest::MainThreadSchedulerImplTest;
friend class frame_scheduler_impl_unittest::FrameSchedulerImplTest;
friend class page_scheduler_impl_unittest::PageSchedulerImplTest;
+ friend class ResourceLoadingTaskRunnerHandleImpl;
class ActiveConnectionHandleImpl : public ActiveConnectionHandle {
public:
@@ -109,40 +150,66 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler {
~ActiveConnectionHandleImpl() override;
private:
- base::WeakPtr<FrameSchedulerImpl> frame_scheduler_;
+ base::WeakPtr<FrameOrWorkerScheduler> frame_scheduler_;
DISALLOW_COPY_AND_ASSIGN(ActiveConnectionHandleImpl);
};
- class ThrottlingObserverHandleImpl : public ThrottlingObserverHandle {
+ // A class that adds and removes itself from the passed in weak pointer. While
+ // one exists, resource loading is paused.
+ class PauseSubresourceLoadingHandleImpl
+ : public blink::mojom::blink::PauseSubresourceLoadingHandle {
public:
- ThrottlingObserverHandleImpl(FrameSchedulerImpl* frame_scheduler,
- Observer* observer);
- ~ThrottlingObserverHandleImpl() override;
+ // This object takes a reference in |frame_scheduler| preventing resource
+ // loading in the frame until the reference is released during destruction.
+ explicit PauseSubresourceLoadingHandleImpl(
+ base::WeakPtr<FrameSchedulerImpl> frame_scheduler);
+ ~PauseSubresourceLoadingHandleImpl() override;
private:
base::WeakPtr<FrameSchedulerImpl> frame_scheduler_;
- Observer* observer_;
- DISALLOW_COPY_AND_ASSIGN(ThrottlingObserverHandleImpl);
+ DISALLOW_COPY_AND_ASSIGN(PauseSubresourceLoadingHandleImpl);
+ };
+
+ struct ResourceLoadingTaskQueueMetadata {
+ ResourceLoadingTaskQueueMetadata(){};
+
+ ResourceLoadingTaskQueueMetadata(
+ base::sequence_manager::TaskQueue::QueuePriority queue_priority,
+ std::unique_ptr<base::sequence_manager::TaskQueue::QueueEnabledVoter>
+ queue_voter)
+ : priority(queue_priority), voter(std::move(queue_voter)) {}
+
+ base::sequence_manager::TaskQueue::QueuePriority priority;
+ std::unique_ptr<base::sequence_manager::TaskQueue::QueueEnabledVoter> voter;
};
void DetachFromPageScheduler();
void RemoveThrottleableQueueFromBackgroundCPUTimeBudgetPool();
void ApplyPolicyToThrottleableQueue();
bool ShouldThrottleTimers() const;
- FrameScheduler::ThrottlingState CalculateThrottlingState(
- ObserverType type) const;
- void RemoveThrottlingObserver(Observer* observer);
+ SchedulingLifecycleState CalculateLifecycleState(
+ ObserverType type) const override;
void UpdateQueuePolicy(
const scoped_refptr<MainThreadTaskQueue>& queue,
base::sequence_manager::TaskQueue::QueueEnabledVoter* voter);
void UpdateThrottling();
- void NotifyThrottlingObservers();
void DidOpenActiveConnection();
void DidCloseActiveConnection();
+ void AddPauseSubresourceLoadingHandle();
+ void RemovePauseSubresourceLoadingHandle();
+
+ std::unique_ptr<ResourceLoadingTaskRunnerHandleImpl>
+ CreateResourceLoadingTaskRunnerHandleImpl();
+
+ std::pair<
+ scoped_refptr<MainThreadTaskQueue>,
+ std::unique_ptr<base::sequence_manager::TaskQueue::QueueEnabledVoter>>
+ CreateNewLoadingTaskQueue();
+
scoped_refptr<base::sequence_manager::TaskQueue> LoadingTaskQueue();
scoped_refptr<base::sequence_manager::TaskQueue> LoadingControlTaskQueue();
scoped_refptr<base::sequence_manager::TaskQueue> ThrottleableTaskQueue();
@@ -150,10 +217,10 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler {
scoped_refptr<base::sequence_manager::TaskQueue> PausableTaskQueue();
scoped_refptr<base::sequence_manager::TaskQueue> UnpausableTaskQueue();
- base::WeakPtr<FrameSchedulerImpl> GetWeakPtr();
-
const FrameScheduler::FrameType frame_type_;
+ bool is_ad_frame_;
+
TraceableVariableController tracing_controller_;
scoped_refptr<MainThreadTaskQueue> loading_task_queue_;
scoped_refptr<MainThreadTaskQueue> loading_control_task_queue_;
@@ -171,21 +238,29 @@ class PLATFORM_EXPORT FrameSchedulerImpl : public FrameScheduler {
deferrable_queue_enabled_voter_;
std::unique_ptr<base::sequence_manager::TaskQueue::QueueEnabledVoter>
pausable_queue_enabled_voter_;
+
+ using ResourceLoadingTaskQueueMetadataMap =
+ WTF::HashMap<scoped_refptr<MainThreadTaskQueue>,
+ ResourceLoadingTaskQueueMetadata>;
+
+ // Holds queues created by CreateResourceLoadingTaskRunnerHandle.
+ ResourceLoadingTaskQueueMetadataMap resource_loading_task_queues_;
+
MainThreadSchedulerImpl* main_thread_scheduler_; // NOT OWNED
PageSchedulerImpl* parent_page_scheduler_; // NOT OWNED
base::trace_event::BlameContext* blame_context_; // NOT OWNED
- // Observers are not owned by the scheduler.
- std::unordered_map<Observer*, ObserverType> throttling_observers_;
- FrameScheduler::ThrottlingState throttling_state_;
+ SchedulingLifecycleState throttling_state_;
TraceableState<bool, kTracingCategoryNameInfo> frame_visible_;
TraceableState<bool, kTracingCategoryNameInfo> frame_paused_;
TraceableState<FrameOriginType, kTracingCategoryNameInfo> frame_origin_type_;
+ TraceableState<bool, kTracingCategoryNameInfo> subresource_loading_paused_;
StateTracer<kTracingCategoryNameInfo> url_tracer_;
// |task_queue_throttled_| is false if |throttleable_task_queue_| is absent.
TraceableState<bool, kTracingCategoryNameInfo> task_queue_throttled_;
// TODO(kraynov): https://crbug.com/827113
// Trace active connection count.
int active_connection_count_;
+ size_t subresource_loading_pause_count_;
TraceableState<bool, kTracingCategoryNameInfo> has_active_connection_;
// These are the states of the Page.
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
index e7c9e3858e4..97dd4266058 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
@@ -8,14 +8,18 @@
#include "base/callback.h"
#include "base/location.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "components/viz/test/ordered_simple_task_runner.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/run_loop.h"
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/scoped_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
+#include "third_party/blink/renderer/platform/scheduler/child/features.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/resource_loading_task_runner_handle_impl.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "third_party/blink/renderer/platform/web_task_runner.h"
@@ -29,21 +33,31 @@ namespace frame_scheduler_impl_unittest {
class FrameSchedulerImplTest : public testing::Test {
public:
- FrameSchedulerImplTest() = default;
+ FrameSchedulerImplTest()
+ : task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+ base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED) {
+ // Null clock might trigger some assertions.
+ task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(5));
+ }
+
+ FrameSchedulerImplTest(std::vector<base::Feature> features_to_enable,
+ std::vector<base::Feature> features_to_disable)
+ : FrameSchedulerImplTest() {
+ feature_list_.InitWithFeatures(features_to_enable, features_to_disable);
+ }
+
~FrameSchedulerImplTest() override = default;
void SetUp() override {
- clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
- mock_task_runner_ =
- base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, true);
scheduler_.reset(new MainThreadSchedulerImpl(
- base::sequence_manager::TaskQueueManagerForTest::Create(
- nullptr, mock_task_runner_, &clock_),
+ base::sequence_manager::SequenceManagerForTest::Create(
+ nullptr, task_environment_.GetMainThreadTaskRunner(),
+ task_environment_.GetMockTickClock()),
base::nullopt));
- page_scheduler_.reset(
- new PageSchedulerImpl(nullptr, scheduler_.get(), false));
- frame_scheduler_ = page_scheduler_->CreateFrameSchedulerImpl(
- nullptr, FrameScheduler::FrameType::kSubframe);
+ page_scheduler_.reset(new PageSchedulerImpl(nullptr, scheduler_.get()));
+ frame_scheduler_ = FrameSchedulerImpl::Create(
+ page_scheduler_.get(), nullptr, FrameScheduler::FrameType::kSubframe);
}
void TearDown() override {
@@ -72,6 +86,10 @@ class FrameSchedulerImplTest : public testing::Test {
return frame_scheduler_->LoadingTaskQueue();
}
+ scoped_refptr<TaskQueue> LoadingControlTaskQueue() {
+ return frame_scheduler_->LoadingControlTaskQueue();
+ }
+
scoped_refptr<TaskQueue> DeferrableTaskQueue() {
return frame_scheduler_->DeferrableTaskQueue();
}
@@ -84,19 +102,31 @@ class FrameSchedulerImplTest : public testing::Test {
return frame_scheduler_->UnpausableTaskQueue();
}
+ std::unique_ptr<ResourceLoadingTaskRunnerHandleImpl>
+ GetResourceLoadingTaskRunnerHandleImpl() {
+ return frame_scheduler_->CreateResourceLoadingTaskRunnerHandleImpl();
+ }
+
bool IsThrottled() {
EXPECT_TRUE(throttleable_task_queue());
return scheduler_->task_queue_throttler()->IsThrottled(
throttleable_task_queue().get());
}
- FrameScheduler::ThrottlingState CalculateThrottlingState(
+ SchedulingLifecycleState CalculateLifecycleState(
FrameScheduler::ObserverType type) {
- return frame_scheduler_->CalculateThrottlingState(type);
+ return frame_scheduler_->CalculateLifecycleState(type);
+ }
+
+ void DidChangeResourceLoadingPriority(
+ scoped_refptr<MainThreadTaskQueue> task_queue,
+ net::RequestPriority priority) {
+ frame_scheduler_->DidChangeResourceLoadingPriority(task_queue, priority);
}
- base::SimpleTestTickClock clock_;
- scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
+ std::unique_ptr<base::FieldTrialList> field_trial_list_;
+ base::test::ScopedFeatureList feature_list_;
+ base::test::ScopedTaskEnvironment task_environment_;
std::unique_ptr<MainThreadSchedulerImpl> scheduler_;
std::unique_ptr<PageSchedulerImpl> page_scheduler_;
std::unique_ptr<FrameSchedulerImpl> frame_scheduler_;
@@ -104,9 +134,9 @@ class FrameSchedulerImplTest : public testing::Test {
namespace {
-class MockThrottlingObserver final : public FrameScheduler::Observer {
+class MockLifecycleObserver final : public FrameScheduler::Observer {
public:
- MockThrottlingObserver()
+ MockLifecycleObserver()
: not_throttled_count_(0u),
hidden_count_(0u),
throttled_count_(0u),
@@ -124,19 +154,18 @@ class MockThrottlingObserver final : public FrameScheduler::Observer {
EXPECT_EQ(stopped_count_expectation, stopped_count_) << from.ToString();
}
- void OnThrottlingStateChanged(
- FrameScheduler::ThrottlingState state) override {
+ void OnLifecycleStateChanged(SchedulingLifecycleState state) override {
switch (state) {
- case FrameScheduler::ThrottlingState::kNotThrottled:
+ case SchedulingLifecycleState::kNotThrottled:
not_throttled_count_++;
break;
- case FrameScheduler::ThrottlingState::kHidden:
+ case SchedulingLifecycleState::kHidden:
hidden_count_++;
break;
- case FrameScheduler::ThrottlingState::kThrottled:
+ case SchedulingLifecycleState::kThrottled:
throttled_count_++;
break;
- case FrameScheduler::ThrottlingState::kStopped:
+ case SchedulingLifecycleState::kStopped:
stopped_count_++;
break;
// We should not have another state, and compiler checks it.
@@ -294,18 +323,17 @@ TEST_F(FrameSchedulerImplTest, PauseAndResume) {
frame_scheduler_->SetPaused(true);
EXPECT_EQ(0, counter);
- mock_task_runner_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, counter);
frame_scheduler_->SetPaused(false);
EXPECT_EQ(1, counter);
- mock_task_runner_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(5, counter);
}
TEST_F(FrameSchedulerImplTest, PageFreezeAndUnfreezeFlagEnabled) {
- ScopedStopLoadingInBackgroundForTest stop_loading_enabler(true);
ScopedStopNonTimersInBackgroundForTest stop_non_timers_enabler(true);
int counter = 0;
LoadingTaskQueue()->PostTask(
@@ -323,19 +351,19 @@ TEST_F(FrameSchedulerImplTest, PageFreezeAndUnfreezeFlagEnabled) {
page_scheduler_->SetPageFrozen(true);
EXPECT_EQ(0, counter);
- mock_task_runner_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// unpausable tasks continue to run.
EXPECT_EQ(1, counter);
page_scheduler_->SetPageFrozen(false);
EXPECT_EQ(1, counter);
- mock_task_runner_->RunUntilIdle();
+ // Same as RunUntilIdle but also advances the cock if necessary.
+ task_environment_.FastForwardUntilNoTasksRemain();
EXPECT_EQ(5, counter);
}
TEST_F(FrameSchedulerImplTest, PageFreezeAndUnfreezeFlagDisabled) {
- ScopedStopLoadingInBackgroundForTest stop_loading_enabler(false);
ScopedStopNonTimersInBackgroundForTest stop_non_timers_enabler(false);
int counter = 0;
LoadingTaskQueue()->PostTask(
@@ -353,19 +381,19 @@ TEST_F(FrameSchedulerImplTest, PageFreezeAndUnfreezeFlagDisabled) {
page_scheduler_->SetPageFrozen(true);
EXPECT_EQ(0, counter);
- mock_task_runner_->RunUntilIdle();
- // throttleable tasks are frozen, other tasks continue to run.
- EXPECT_EQ(4, counter);
+ base::RunLoop().RunUntilIdle();
+ // throttleable tasks and loading tasks are frozen, others continue to run.
+ EXPECT_EQ(3, counter);
page_scheduler_->SetPageFrozen(false);
- EXPECT_EQ(4, counter);
- mock_task_runner_->RunUntilIdle();
+ EXPECT_EQ(3, counter);
+ // Same as RunUntilIdle but also advances the clock if necessary.
+ task_environment_.FastForwardUntilNoTasksRemain();
EXPECT_EQ(5, counter);
}
TEST_F(FrameSchedulerImplTest, PageFreezeWithKeepActive) {
- ScopedStopLoadingInBackgroundForTest stop_loading_enabler(true);
ScopedStopNonTimersInBackgroundForTest stop_non_timers_enabler(false);
std::vector<std::string> tasks;
LoadingTaskQueue()->PostTask(
@@ -387,7 +415,7 @@ TEST_F(FrameSchedulerImplTest, PageFreezeWithKeepActive) {
page_scheduler_->SetPageFrozen(true);
EXPECT_THAT(tasks, UnorderedElementsAre());
- mock_task_runner_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Everything runs except throttleable tasks (timers)
EXPECT_THAT(tasks, UnorderedElementsAre(
std::string(LoadingTaskQueue()->GetName()),
@@ -400,7 +428,7 @@ TEST_F(FrameSchedulerImplTest, PageFreezeWithKeepActive) {
FROM_HERE, base::BindOnce(&RecordQueueName, LoadingTaskQueue(), &tasks));
EXPECT_THAT(tasks, UnorderedElementsAre());
- mock_task_runner_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// loading task runs
EXPECT_THAT(tasks,
UnorderedElementsAre(std::string(LoadingTaskQueue()->GetName())));
@@ -411,20 +439,19 @@ TEST_F(FrameSchedulerImplTest, PageFreezeWithKeepActive) {
// KeepActive is false when Service Worker stops.
page_scheduler_->SetKeepActive(false);
EXPECT_THAT(tasks, UnorderedElementsAre());
- mock_task_runner_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(tasks, UnorderedElementsAre()); // loading task does not run
tasks.clear();
page_scheduler_->SetKeepActive(true);
EXPECT_THAT(tasks, UnorderedElementsAre());
- mock_task_runner_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// loading task runs
EXPECT_THAT(tasks,
UnorderedElementsAre(std::string(LoadingTaskQueue()->GetName())));
}
TEST_F(FrameSchedulerImplTest, PageFreezeAndPageVisible) {
- ScopedStopLoadingInBackgroundForTest stop_loading_enabler(true);
ScopedStopNonTimersInBackgroundForTest stop_non_timers_enabler(true);
int counter = 0;
LoadingTaskQueue()->PostTask(
@@ -442,21 +469,21 @@ TEST_F(FrameSchedulerImplTest, PageFreezeAndPageVisible) {
page_scheduler_->SetPageFrozen(true);
EXPECT_EQ(0, counter);
- mock_task_runner_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, counter);
// Making the page visible should cause frozen queues to resume.
page_scheduler_->SetPageVisible(true);
EXPECT_EQ(1, counter);
- mock_task_runner_->RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(5, counter);
}
// Tests if throttling observer interfaces work.
-TEST_F(FrameSchedulerImplTest, ThrottlingObserver) {
- std::unique_ptr<MockThrottlingObserver> observer =
- std::make_unique<MockThrottlingObserver>();
+TEST_F(FrameSchedulerImplTest, LifecycleObserver) {
+ std::unique_ptr<MockLifecycleObserver> observer =
+ std::make_unique<MockLifecycleObserver>();
size_t not_throttled_count = 0u;
size_t hidden_count = 0u;
@@ -466,7 +493,7 @@ TEST_F(FrameSchedulerImplTest, ThrottlingObserver) {
observer->CheckObserverState(FROM_HERE, not_throttled_count, hidden_count,
throttled_count, stopped_count);
- auto observer_handle = frame_scheduler_->AddThrottlingObserver(
+ auto observer_handle = frame_scheduler_->AddLifecycleObserver(
FrameScheduler::ObserverType::kLoader, observer.get());
// Initial state should be synchronously notified here.
@@ -487,7 +514,7 @@ TEST_F(FrameSchedulerImplTest, ThrottlingObserver) {
observer->CheckObserverState(FROM_HERE, not_throttled_count, hidden_count,
throttled_count, stopped_count);
- mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(30));
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(30));
// The frame gets throttled after some time in background.
observer->CheckObserverState(FROM_HERE, not_throttled_count, hidden_count,
@@ -521,19 +548,987 @@ TEST_F(FrameSchedulerImplTest, ThrottlingObserver) {
page_scheduler_->SetPageVisible(false);
// Wait 100 secs virtually and run pending tasks just in case.
- clock_.Advance(base::TimeDelta::FromSeconds(100));
- mock_task_runner_->RunUntilIdle();
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(100));
+ base::RunLoop().RunUntilIdle();
observer->CheckObserverState(FROM_HERE, not_throttled_count, hidden_count,
throttled_count, stopped_count);
}
-TEST_F(FrameSchedulerImplTest, DefaultThrottlingState) {
- EXPECT_EQ(CalculateThrottlingState(FrameScheduler::ObserverType::kLoader),
- FrameScheduler::ThrottlingState::kNotThrottled);
+TEST_F(FrameSchedulerImplTest, DefaultSchedulingLifecycleState) {
+ EXPECT_EQ(CalculateLifecycleState(FrameScheduler::ObserverType::kLoader),
+ SchedulingLifecycleState::kNotThrottled);
EXPECT_EQ(
- CalculateThrottlingState(FrameScheduler::ObserverType::kWorkerScheduler),
- FrameScheduler::ThrottlingState::kNotThrottled);
+ CalculateLifecycleState(FrameScheduler::ObserverType::kWorkerScheduler),
+ SchedulingLifecycleState::kNotThrottled);
+}
+
+TEST_F(FrameSchedulerImplTest, SubesourceLoadingPaused) {
+ // A loader observer and related counts.
+ std::unique_ptr<MockLifecycleObserver> loader_observer =
+ std::make_unique<MockLifecycleObserver>();
+
+ size_t loader_throttled_count = 0u;
+ size_t loader_not_throttled_count = 0u;
+ size_t loader_hidden_count = 0u;
+ size_t loader_stopped_count = 0u;
+
+ // A worker observer and related counts.
+ std::unique_ptr<MockLifecycleObserver> worker_observer =
+ std::make_unique<MockLifecycleObserver>();
+
+ size_t worker_throttled_count = 0u;
+ size_t worker_not_throttled_count = 0u;
+ size_t worker_hidden_count = 0u;
+ size_t worker_stopped_count = 0u;
+
+ // Both observers should start with no responses.
+ loader_observer->CheckObserverState(
+ FROM_HERE, loader_not_throttled_count, loader_hidden_count,
+ loader_throttled_count, loader_stopped_count);
+
+ worker_observer->CheckObserverState(
+ FROM_HERE, worker_not_throttled_count, worker_hidden_count,
+ worker_throttled_count, worker_stopped_count);
+
+ // Adding the observers should recieve a non-throttled response
+ auto loader_observer_handle = frame_scheduler_->AddLifecycleObserver(
+ FrameScheduler::ObserverType::kLoader, loader_observer.get());
+
+ auto worker_observer_handle = frame_scheduler_->AddLifecycleObserver(
+ FrameScheduler::ObserverType::kWorkerScheduler, worker_observer.get());
+
+ loader_observer->CheckObserverState(
+ FROM_HERE, ++loader_not_throttled_count, loader_hidden_count,
+ loader_throttled_count, loader_stopped_count);
+
+ worker_observer->CheckObserverState(
+ FROM_HERE, ++worker_not_throttled_count, worker_hidden_count,
+ worker_throttled_count, worker_stopped_count);
+
+ {
+ auto pause_handle_a = frame_scheduler_->GetPauseSubresourceLoadingHandle();
+
+ loader_observer->CheckObserverState(
+ FROM_HERE, loader_not_throttled_count, loader_hidden_count,
+ loader_throttled_count, ++loader_stopped_count);
+
+ worker_observer->CheckObserverState(
+ FROM_HERE, ++worker_not_throttled_count, worker_hidden_count,
+ worker_throttled_count, worker_stopped_count);
+
+ std::unique_ptr<MockLifecycleObserver> loader_observer_added_after_stopped =
+ std::make_unique<MockLifecycleObserver>();
+
+ auto loader_observer_handle = frame_scheduler_->AddLifecycleObserver(
+ FrameScheduler::ObserverType::kLoader,
+ loader_observer_added_after_stopped.get());
+ // This observer should see stopped when added.
+ loader_observer_added_after_stopped->CheckObserverState(FROM_HERE, 0, 0, 0,
+ 1u);
+
+ // Adding another handle should not create a new state.
+ auto pause_handle_b = frame_scheduler_->GetPauseSubresourceLoadingHandle();
+
+ loader_observer->CheckObserverState(
+ FROM_HERE, loader_not_throttled_count, loader_hidden_count,
+ loader_throttled_count, loader_stopped_count);
+
+ worker_observer->CheckObserverState(
+ FROM_HERE, worker_not_throttled_count, worker_hidden_count,
+ worker_throttled_count, worker_stopped_count);
+ }
+
+ // Removing the handles should return the state to non throttled.
+ loader_observer->CheckObserverState(
+ FROM_HERE, ++loader_not_throttled_count, loader_hidden_count,
+ loader_throttled_count, loader_stopped_count);
+
+ worker_observer->CheckObserverState(
+ FROM_HERE, ++worker_not_throttled_count, worker_hidden_count,
+ worker_throttled_count, worker_stopped_count);
+}
+
+// TODO(farahcharab) Move priority testing to MainThreadTaskQueueTest after
+// landing the change that moves priority computation to MainThreadTaskQueue.
+
+class LowPriorityBackgroundPageExperimentTest : public FrameSchedulerImplTest {
+ public:
+ LowPriorityBackgroundPageExperimentTest()
+ : FrameSchedulerImplTest({kLowPriorityForBackgroundPages}, {}) {}
+};
+
+TEST_F(LowPriorityBackgroundPageExperimentTest, FrameQueuesPriorities) {
+ page_scheduler_->SetPageVisible(false);
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+
+ page_scheduler_->AudioStateChanged(true);
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+
+ page_scheduler_->AudioStateChanged(false);
+ page_scheduler_->SetPageVisible(true);
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+}
+
+class BestEffortPriorityBackgroundPageExperimentTest
+ : public FrameSchedulerImplTest {
+ public:
+ BestEffortPriorityBackgroundPageExperimentTest()
+ : FrameSchedulerImplTest({kBestEffortPriorityForBackgroundPages}, {}) {}
+};
+
+TEST_F(BestEffortPriorityBackgroundPageExperimentTest, FrameQueuesPriorities) {
+ page_scheduler_->SetPageVisible(false);
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kBestEffortPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kBestEffortPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kBestEffortPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kBestEffortPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kBestEffortPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kBestEffortPriority);
+
+ page_scheduler_->AudioStateChanged(true);
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+
+ page_scheduler_->AudioStateChanged(false);
+ page_scheduler_->SetPageVisible(true);
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+}
+
+class LowPriorityHiddenFrameExperimentTest : public FrameSchedulerImplTest {
+ public:
+ LowPriorityHiddenFrameExperimentTest()
+ : FrameSchedulerImplTest({kLowPriorityForHiddenFrame},
+ {kFrameExperimentOnlyWhenLoading}) {}
+};
+
+TEST_F(LowPriorityHiddenFrameExperimentTest, FrameQueuesPriorities) {
+ // Hidden Frame Task Queues.
+ frame_scheduler_->SetFrameVisible(false);
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+
+ // Visible Frame Task Queues.
+ frame_scheduler_->SetFrameVisible(true);
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+}
+
+class LowPriorityHiddenFrameDuringLoadingExperimentTest
+ : public FrameSchedulerImplTest {
+ public:
+ LowPriorityHiddenFrameDuringLoadingExperimentTest()
+ : FrameSchedulerImplTest(
+ {kLowPriorityForHiddenFrame, kFrameExperimentOnlyWhenLoading},
+ {}) {}
+};
+
+TEST_F(LowPriorityHiddenFrameDuringLoadingExperimentTest,
+ FrameQueuesPriorities) {
+ // Main thread scheduler is in the loading use case.
+ scheduler_->DidStartProvisionalLoad(true);
+ EXPECT_TRUE(page_scheduler_->IsLoading());
+
+ // Hidden Frame Task Queues.
+ frame_scheduler_->SetFrameVisible(false);
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+
+ // Main thread scheduler is no longer in loading use case.
+ scheduler_->OnFirstMeaningfulPaint();
+ EXPECT_FALSE(page_scheduler_->IsLoading());
+
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+}
+
+class LowPrioritySubFrameExperimentTest : public FrameSchedulerImplTest {
+ public:
+ LowPrioritySubFrameExperimentTest()
+ : FrameSchedulerImplTest({kLowPriorityForSubFrame},
+ {kFrameExperimentOnlyWhenLoading}) {}
+};
+
+TEST_F(LowPrioritySubFrameExperimentTest, FrameQueuesPriorities) {
+ // Sub-Frame Task Queues.
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+
+ frame_scheduler_ = FrameSchedulerImpl::Create(
+ page_scheduler_.get(), nullptr, FrameScheduler::FrameType::kMainFrame);
+
+ // Main Frame Task Queues.
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+}
+
+class LowPrioritySubFrameDuringLoadingExperimentTest
+ : public FrameSchedulerImplTest {
+ public:
+ LowPrioritySubFrameDuringLoadingExperimentTest()
+ : FrameSchedulerImplTest(
+ {kLowPriorityForSubFrame, kFrameExperimentOnlyWhenLoading},
+ {}) {}
+};
+
+TEST_F(LowPrioritySubFrameDuringLoadingExperimentTest, FrameQueuesPriorities) {
+ // Main thread scheduler is in the loading use case.
+ scheduler_->DidStartProvisionalLoad(true);
+ EXPECT_TRUE(page_scheduler_->IsLoading());
+
+ // Sub-Frame Task Queues.
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+
+ // Main thread scheduler is no longer in loading use case.
+ scheduler_->OnFirstMeaningfulPaint();
+ EXPECT_FALSE(page_scheduler_->IsLoading());
+
+ // Sub-Frame Task Queues.
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+}
+
+class LowPrioritySubFrameThrottleableTaskExperimentTest
+ : public FrameSchedulerImplTest {
+ public:
+ LowPrioritySubFrameThrottleableTaskExperimentTest()
+ : FrameSchedulerImplTest({kLowPriorityForSubFrameThrottleableTask},
+ {kFrameExperimentOnlyWhenLoading}) {}
+};
+
+TEST_F(LowPrioritySubFrameThrottleableTaskExperimentTest,
+ FrameQueuesPriorities) {
+ // Sub-Frame Task Queues.
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+
+ frame_scheduler_ = FrameSchedulerImpl::Create(
+ page_scheduler_.get(), nullptr, FrameScheduler::FrameType::kMainFrame);
+
+ // Main Frame Task Queues.
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+}
+
+class LowPrioritySubFrameThrottleableTaskDuringLoadingExperimentTest
+ : public FrameSchedulerImplTest {
+ public:
+ LowPrioritySubFrameThrottleableTaskDuringLoadingExperimentTest()
+ : FrameSchedulerImplTest({kLowPriorityForSubFrameThrottleableTask,
+ kFrameExperimentOnlyWhenLoading},
+ {}) {}
+};
+
+TEST_F(LowPrioritySubFrameThrottleableTaskDuringLoadingExperimentTest,
+ FrameQueuesPriorities) {
+ // Main thread scheduler is in the loading use case.
+ scheduler_->DidStartProvisionalLoad(true);
+ EXPECT_TRUE(page_scheduler_->IsLoading());
+
+ // Sub-Frame Task Queues.
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+
+ // Main thread scheduler is no longer in loading use case.
+ scheduler_->OnFirstMeaningfulPaint();
+ EXPECT_FALSE(page_scheduler_->IsLoading());
+
+ // Sub-Frame Task Queues.
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+}
+
+class LowPriorityThrottleableTaskExperimentTest
+ : public FrameSchedulerImplTest {
+ public:
+ LowPriorityThrottleableTaskExperimentTest()
+ : FrameSchedulerImplTest({kLowPriorityForThrottleableTask},
+ {kFrameExperimentOnlyWhenLoading}) {}
+};
+
+TEST_F(LowPriorityThrottleableTaskExperimentTest, FrameQueuesPriorities) {
+ // Sub-Frame Task Queues.
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+
+ frame_scheduler_ = FrameSchedulerImpl::Create(
+ page_scheduler_.get(), nullptr, FrameScheduler::FrameType::kMainFrame);
+
+ // Main Frame Task Queues.
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+}
+
+class LowPriorityThrottleableTaskDuringLoadingExperimentTest
+ : public FrameSchedulerImplTest {
+ public:
+ LowPriorityThrottleableTaskDuringLoadingExperimentTest()
+ : FrameSchedulerImplTest(
+ {kLowPriorityForThrottleableTask, kFrameExperimentOnlyWhenLoading},
+ {}) {}
+};
+
+TEST_F(LowPriorityThrottleableTaskDuringLoadingExperimentTest,
+ SubFrameQueuesPriorities) {
+ // Main thread is in the loading use case.
+ scheduler_->DidStartProvisionalLoad(true);
+ EXPECT_TRUE(page_scheduler_->IsLoading());
+
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+
+ // Main thread is no longer in loading use case.
+ scheduler_->OnFirstMeaningfulPaint();
+ EXPECT_FALSE(page_scheduler_->IsLoading());
+
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+}
+
+TEST_F(LowPriorityThrottleableTaskDuringLoadingExperimentTest,
+ MainFrameQueuesPriorities) {
+ frame_scheduler_ = FrameSchedulerImpl::Create(
+ page_scheduler_.get(), nullptr, FrameScheduler::FrameType::kMainFrame);
+
+ // Main thread is in the loading use case.
+ scheduler_->DidStartProvisionalLoad(true);
+ EXPECT_TRUE(page_scheduler_->IsLoading());
+
+ // Main Frame Task Queues.
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+
+ // Main thread is no longer in loading use case.
+ scheduler_->OnFirstMeaningfulPaint();
+ EXPECT_FALSE(page_scheduler_->IsLoading());
+
+ // Main Frame Task Queues.
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+}
+
+class LowPriorityAdFrameExperimentTest : public FrameSchedulerImplTest {
+ public:
+ LowPriorityAdFrameExperimentTest()
+ : FrameSchedulerImplTest({kLowPriorityForAdFrame},
+ {kAdFrameExperimentOnlyWhenLoading}) {}
+};
+
+TEST_F(LowPriorityAdFrameExperimentTest, FrameQueuesPriorities) {
+ EXPECT_FALSE(frame_scheduler_->IsAdFrame());
+
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+
+ frame_scheduler_->SetIsAdFrame();
+
+ EXPECT_TRUE(frame_scheduler_->IsAdFrame());
+
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+}
+
+class LowPriorityAdFrameDuringLoadingExperimentTest
+ : public FrameSchedulerImplTest {
+ public:
+ LowPriorityAdFrameDuringLoadingExperimentTest()
+ : FrameSchedulerImplTest(
+ {kLowPriorityForAdFrame, kAdFrameExperimentOnlyWhenLoading},
+ {}) {}
+};
+
+TEST_F(LowPriorityAdFrameDuringLoadingExperimentTest, FrameQueuesPriorities) {
+ frame_scheduler_->SetIsAdFrame();
+
+ EXPECT_TRUE(frame_scheduler_->IsAdFrame());
+
+ // Main thread scheduler is in the loading use case.
+ scheduler_->DidStartProvisionalLoad(true);
+ EXPECT_TRUE(page_scheduler_->IsLoading());
+
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+
+ // Main thread scheduler is no longer in loading use case.
+ scheduler_->OnFirstMeaningfulPaint();
+
+ EXPECT_FALSE(page_scheduler_->IsLoading());
+
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+}
+
+class BestEffortPriorityAdFrameExperimentTest : public FrameSchedulerImplTest {
+ public:
+ BestEffortPriorityAdFrameExperimentTest()
+ : FrameSchedulerImplTest({kBestEffortPriorityForAdFrame},
+ {kAdFrameExperimentOnlyWhenLoading}) {}
+};
+
+TEST_F(BestEffortPriorityAdFrameExperimentTest, FrameQueuesPriorities) {
+ EXPECT_FALSE(frame_scheduler_->IsAdFrame());
+
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+
+ frame_scheduler_->SetIsAdFrame();
+
+ EXPECT_TRUE(frame_scheduler_->IsAdFrame());
+
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kBestEffortPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kBestEffortPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kBestEffortPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kBestEffortPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kBestEffortPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kBestEffortPriority);
+}
+
+class BestEffortPriorityAdFrameDuringLoadingExperimentTest
+ : public FrameSchedulerImplTest {
+ public:
+ BestEffortPriorityAdFrameDuringLoadingExperimentTest()
+ : FrameSchedulerImplTest(
+ {kBestEffortPriorityForAdFrame, kAdFrameExperimentOnlyWhenLoading},
+ {}) {}
+};
+
+TEST_F(BestEffortPriorityAdFrameDuringLoadingExperimentTest,
+ FrameQueuesPriorities) {
+ frame_scheduler_->SetIsAdFrame();
+
+ EXPECT_TRUE(frame_scheduler_->IsAdFrame());
+
+ // Main thread scheduler is in the loading use case.
+ scheduler_->DidStartProvisionalLoad(true);
+ EXPECT_TRUE(page_scheduler_->IsLoading());
+
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kBestEffortPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kBestEffortPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kBestEffortPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kBestEffortPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kBestEffortPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kBestEffortPriority);
+
+ // Main thread scheduler is no longer in loading use case.
+ scheduler_->OnFirstMeaningfulPaint();
+
+ EXPECT_FALSE(page_scheduler_->IsLoading());
+
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+}
+
+class ResourceFetchPriorityExperimentTest : public FrameSchedulerImplTest {
+ public:
+ ResourceFetchPriorityExperimentTest()
+ : FrameSchedulerImplTest({kUseResourceFetchPriority}, {}) {
+ std::map<std::string, std::string> params{
+ {"HIGHEST", "HIGH"}, {"MEDIUM", "NORMAL"}, {"LOW", "NORMAL"},
+ {"LOWEST", "LOW"}, {"IDLE", "LOW"}, {"THROTTLED", "LOW"}};
+
+ const char kStudyName[] = "ResourceFetchPriorityExperiment";
+ const char kGroupName[] = "GroupName1";
+
+ field_trial_list_ = std::make_unique<base::FieldTrialList>(nullptr);
+ base::AssociateFieldTrialParams(kStudyName, kGroupName, params);
+ base::FieldTrialList::CreateFieldTrial(kStudyName, kGroupName);
+ }
+};
+
+TEST_F(ResourceFetchPriorityExperimentTest, DidChangePriority) {
+ std::unique_ptr<ResourceLoadingTaskRunnerHandleImpl> handle =
+ GetResourceLoadingTaskRunnerHandleImpl();
+ scoped_refptr<MainThreadTaskQueue> task_queue = handle->task_queue();
+
+ TaskQueue::QueuePriority priority = task_queue->GetQueuePriority();
+ EXPECT_EQ(priority, TaskQueue::QueuePriority::kNormalPriority);
+
+ DidChangeResourceLoadingPriority(task_queue, net::RequestPriority::LOWEST);
+ EXPECT_EQ(task_queue->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+
+ DidChangeResourceLoadingPriority(task_queue, net::RequestPriority::HIGHEST);
+ EXPECT_EQ(task_queue->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+}
+
+class ResourceFetchPriorityExperimentOnlyWhenLoadingTest
+ : public FrameSchedulerImplTest {
+ public:
+ ResourceFetchPriorityExperimentOnlyWhenLoadingTest()
+ : FrameSchedulerImplTest({kUseResourceFetchPriorityOnlyWhenLoading}, {}) {
+ std::map<std::string, std::string> params{
+ {"HIGHEST", "HIGH"}, {"MEDIUM", "NORMAL"}, {"LOW", "NORMAL"},
+ {"LOWEST", "LOW"}, {"IDLE", "LOW"}, {"THROTTLED", "LOW"}};
+
+ const char kStudyName[] = "ResourceFetchPriorityExperiment";
+ const char kGroupName[] = "GroupName2";
+
+ field_trial_list_ = std::make_unique<base::FieldTrialList>(nullptr);
+ base::AssociateFieldTrialParams(kStudyName, kGroupName, params);
+ base::FieldTrialList::CreateFieldTrial(kStudyName, kGroupName);
+ }
+};
+
+TEST_F(ResourceFetchPriorityExperimentOnlyWhenLoadingTest, DidChangePriority) {
+ std::unique_ptr<ResourceLoadingTaskRunnerHandleImpl> handle =
+ GetResourceLoadingTaskRunnerHandleImpl();
+ scoped_refptr<MainThreadTaskQueue> task_queue = handle->task_queue();
+
+ TaskQueue::QueuePriority priority = task_queue->GetQueuePriority();
+ EXPECT_EQ(priority, TaskQueue::QueuePriority::kNormalPriority);
+
+ // Experiment is only enabled during the loading phase.
+ DidChangeResourceLoadingPriority(task_queue, net::RequestPriority::LOWEST);
+ EXPECT_EQ(task_queue->GetQueuePriority(), priority);
+
+ // Main thread scheduler is in the loading use case.
+ scheduler_->DidStartProvisionalLoad(true);
+ EXPECT_TRUE(page_scheduler_->IsLoading());
+
+ handle = GetResourceLoadingTaskRunnerHandleImpl();
+ task_queue = handle->task_queue();
+
+ DidChangeResourceLoadingPriority(task_queue, net::RequestPriority::LOWEST);
+ EXPECT_EQ(task_queue->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+
+ DidChangeResourceLoadingPriority(task_queue, net::RequestPriority::HIGHEST);
+ EXPECT_EQ(task_queue->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+}
+
+TEST_F(
+ FrameSchedulerImplTest,
+ DidChangeResourceLoadingPriority_ResourceFecthPriorityExperimentDisabled) {
+ // If the experiment is disabled, we use |loading_task_queue_| for resource
+ // loading tasks and we don't want the priority of this queue to be affected
+ // by individual resources.
+ std::unique_ptr<ResourceLoadingTaskRunnerHandleImpl> handle =
+ GetResourceLoadingTaskRunnerHandleImpl();
+ scoped_refptr<MainThreadTaskQueue> task_queue = handle->task_queue();
+
+ TaskQueue::QueuePriority priority = task_queue->GetQueuePriority();
+
+ DidChangeResourceLoadingPriority(task_queue, net::RequestPriority::LOW);
+ EXPECT_EQ(task_queue->GetQueuePriority(), priority);
+
+ DidChangeResourceLoadingPriority(task_queue, net::RequestPriority::HIGHEST);
+ EXPECT_EQ(task_queue->GetQueuePriority(), priority);
+}
+
+class LowPriorityCrossOriginTaskExperimentTest : public FrameSchedulerImplTest {
+ public:
+ LowPriorityCrossOriginTaskExperimentTest()
+ : FrameSchedulerImplTest({kLowPriorityForCrossOrigin}, {}) {}
+};
+
+TEST_F(LowPriorityCrossOriginTaskExperimentTest, FrameQueuesPriorities) {
+ EXPECT_FALSE(frame_scheduler_->IsCrossOrigin());
+
+ // Same Origin Task Queues.
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+
+ frame_scheduler_->SetCrossOrigin(true);
+ EXPECT_TRUE(frame_scheduler_->IsCrossOrigin());
+
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+}
+
+class LowPriorityCrossOriginTaskDuringLoadingExperimentTest
+ : public FrameSchedulerImplTest {
+ public:
+ LowPriorityCrossOriginTaskDuringLoadingExperimentTest()
+ : FrameSchedulerImplTest({kLowPriorityForCrossOriginOnlyWhenLoading},
+ {}) {}
+};
+
+TEST_F(LowPriorityCrossOriginTaskDuringLoadingExperimentTest,
+ FrameQueuesPriorities) {
+ // Main thread is in the loading use case.
+ scheduler_->DidStartProvisionalLoad(true);
+ EXPECT_TRUE(page_scheduler_->IsLoading());
+
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+
+ frame_scheduler_->SetCrossOrigin(true);
+ EXPECT_TRUE(frame_scheduler_->IsCrossOrigin());
+
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kLowPriority);
+
+ // Main thread is no longer in loading use case.
+ scheduler_->OnFirstMeaningfulPaint();
+ EXPECT_FALSE(page_scheduler_->IsLoading());
+
+ EXPECT_EQ(LoadingTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(LoadingControlTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kHighPriority);
+ EXPECT_EQ(DeferrableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(ThrottleableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(PausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
+ EXPECT_EQ(UnpausableTaskQueue()->GetQueuePriority(),
+ TaskQueue::QueuePriority::kNormalPriority);
}
} // namespace frame_scheduler_impl_unittest
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
new file mode 100644
index 00000000000..5c1a7612b08
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
@@ -0,0 +1,169 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h"
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/logging.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
+
+namespace blink {
+namespace scheduler {
+
+using base::sequence_manager::TaskQueue;
+using QueueTraits = MainThreadTaskQueue::QueueTraits;
+using QueueEnabledVoter = base::sequence_manager::TaskQueue::QueueEnabledVoter;
+
+FrameTaskQueueController::FrameTaskQueueController(
+ MainThreadSchedulerImpl* main_thread_scheduler_impl,
+ FrameSchedulerImpl* frame_scheduler_impl,
+ Delegate* delegate)
+ : main_thread_scheduler_impl_(main_thread_scheduler_impl),
+ frame_scheduler_impl_(frame_scheduler_impl),
+ delegate_(delegate) {
+ DCHECK(main_thread_scheduler_impl_);
+ DCHECK(frame_scheduler_impl_);
+ DCHECK(delegate_);
+}
+
+FrameTaskQueueController::~FrameTaskQueueController() = default;
+
+scoped_refptr<MainThreadTaskQueue>
+FrameTaskQueueController::GetNonLoadingTaskQueue(
+ QueueTraits queue_traits) const {
+ auto it = non_loading_task_queues_.find(queue_traits.Key());
+ if (it != non_loading_task_queues_.end())
+ return it->value;
+ return nullptr;
+}
+
+const std::vector<FrameTaskQueueController::TaskQueueAndEnabledVoterPair>&
+FrameTaskQueueController::GetAllTaskQueuesAndVoters() const {
+ return all_task_queues_and_voters_;
+}
+
+scoped_refptr<MainThreadTaskQueue>
+FrameTaskQueueController::NewLoadingTaskQueue() {
+ DCHECK(!loading_task_queue_);
+
+ loading_task_queue_ = main_thread_scheduler_impl_->NewLoadingTaskQueue(
+ MainThreadTaskQueue::QueueType::kFrameLoading, frame_scheduler_impl_);
+ TaskQueueCreated(loading_task_queue_);
+ return loading_task_queue_;
+}
+
+scoped_refptr<MainThreadTaskQueue>
+FrameTaskQueueController::NewLoadingControlTaskQueue() {
+ DCHECK(!loading_control_task_queue_);
+
+ loading_control_task_queue_ =
+ main_thread_scheduler_impl_->NewLoadingTaskQueue(
+ MainThreadTaskQueue::QueueType::kFrameLoadingControl,
+ frame_scheduler_impl_);
+ TaskQueueCreated(loading_control_task_queue_);
+ return loading_control_task_queue_;
+}
+
+scoped_refptr<MainThreadTaskQueue>
+FrameTaskQueueController::NewResourceLoadingTaskQueue() {
+ scoped_refptr<MainThreadTaskQueue> task_queue =
+ main_thread_scheduler_impl_->NewLoadingTaskQueue(
+ MainThreadTaskQueue::QueueType::kFrameLoading, frame_scheduler_impl_);
+ TaskQueueCreated(task_queue);
+ resource_loading_task_queues_.insert(task_queue);
+ return task_queue;
+}
+
+scoped_refptr<MainThreadTaskQueue>
+FrameTaskQueueController::NewNonLoadingTaskQueue(QueueTraits queue_traits) {
+ DCHECK(!GetNonLoadingTaskQueue(queue_traits));
+
+ scoped_refptr<MainThreadTaskQueue> task_queue =
+ main_thread_scheduler_impl_->NewTaskQueue(
+ MainThreadTaskQueue::QueueCreationParams(
+ QueueTypeFromQueueTraits(queue_traits))
+ .SetQueueTraits(queue_traits)
+ // Freeze when keep active is currently only set for the
+ // throttleable queue.
+ // TODO(shaseley): Figure out how to set this for new queues.
+ .SetFreezeWhenKeepActive(queue_traits.can_be_throttled)
+ .SetFrameScheduler(frame_scheduler_impl_));
+ TaskQueueCreated(task_queue);
+ non_loading_task_queues_.insert(queue_traits.Key(), task_queue);
+ return task_queue;
+}
+
+void FrameTaskQueueController::TaskQueueCreated(
+ const scoped_refptr<MainThreadTaskQueue>& task_queue) {
+ DCHECK(task_queue);
+
+ std::unique_ptr<QueueEnabledVoter> voter;
+ // Only create a voter for queues that can be disabled.
+ if (task_queue->CanBePaused() || task_queue->CanBeFrozen())
+ voter = task_queue->CreateQueueEnabledVoter();
+
+ delegate_->OnTaskQueueCreated(task_queue.get(), voter.get());
+
+ all_task_queues_and_voters_.push_back(
+ TaskQueueAndEnabledVoterPair(task_queue.get(), voter.get()));
+
+ if (voter) {
+ DCHECK(task_queue_enabled_voters_.find(task_queue) ==
+ task_queue_enabled_voters_.end());
+ task_queue_enabled_voters_.insert(task_queue, std::move(voter));
+ }
+}
+
+base::sequence_manager::TaskQueue::QueueEnabledVoter*
+FrameTaskQueueController::GetQueueEnabledVoter(
+ const scoped_refptr<MainThreadTaskQueue>& task_queue) {
+ auto it = task_queue_enabled_voters_.find(task_queue);
+ if (it == task_queue_enabled_voters_.end())
+ return nullptr;
+ return it->value.get();
+}
+
+bool FrameTaskQueueController::RemoveResourceLoadingTaskQueue(
+ const scoped_refptr<MainThreadTaskQueue>& task_queue) {
+ DCHECK(task_queue);
+
+ if (!resource_loading_task_queues_.Contains(task_queue))
+ return false;
+ resource_loading_task_queues_.erase(task_queue);
+ DCHECK(task_queue_enabled_voters_.Contains(task_queue));
+ task_queue_enabled_voters_.erase(task_queue);
+
+ bool found_task_queue = false;
+ for (auto it = all_task_queues_and_voters_.begin();
+ it != all_task_queues_and_voters_.end(); ++it) {
+ if (it->first == task_queue.get()) {
+ found_task_queue = true;
+ all_task_queues_and_voters_.erase(it);
+ break;
+ }
+ }
+ DCHECK(found_task_queue);
+ return true;
+}
+
+// static
+MainThreadTaskQueue::QueueType
+FrameTaskQueueController::QueueTypeFromQueueTraits(QueueTraits queue_traits) {
+ if (queue_traits.can_be_throttled)
+ return MainThreadTaskQueue::QueueType::kFrameThrottleable;
+ if (queue_traits.can_be_deferred)
+ return MainThreadTaskQueue::QueueType::kFrameDeferrable;
+ if (queue_traits.can_be_paused)
+ return MainThreadTaskQueue::QueueType::kFramePausable;
+ return MainThreadTaskQueue::QueueType::kFrameUnpausable;
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h
new file mode 100644
index 00000000000..356d27a8181
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h
@@ -0,0 +1,144 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_FRAME_TASK_QUEUE_CONTROLLER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_FRAME_TASK_QUEUE_CONTROLLER_H_
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/hash_set.h"
+
+namespace base {
+namespace sequence_manager {
+class TaskQueue;
+} // namespace sequence_manager
+} // namespace base
+
+namespace blink {
+namespace scheduler {
+
+class FrameSchedulerImpl;
+class FrameTaskQueueControllerTest;
+class MainThreadSchedulerImpl;
+
+// FrameTaskQueueController creates and manages and FrameSchedulerImpl's task
+// queues. It is in charge of maintaining mappings between TaskType and
+// QueueTraits and from QueueTraits to MainThreadTaskQueue, for accessing task
+// queues and their related voters, and for creating new task queues.
+class PLATFORM_EXPORT FrameTaskQueueController {
+ public:
+ using TaskQueueAndEnabledVoterPair =
+ std::pair<MainThreadTaskQueue*,
+ base::sequence_manager::TaskQueue::QueueEnabledVoter*>;
+
+ // Delegate receives callbacks when task queues are created to perform any
+ // additional task queue setup or tasks.
+ class Delegate {
+ public:
+ Delegate() = default;
+ virtual ~Delegate() = default;
+
+ virtual void OnTaskQueueCreated(
+ MainThreadTaskQueue*,
+ base::sequence_manager::TaskQueue::QueueEnabledVoter*) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Delegate);
+ };
+
+ FrameTaskQueueController(MainThreadSchedulerImpl*,
+ FrameSchedulerImpl*,
+ Delegate*);
+ ~FrameTaskQueueController();
+
+ // Get the list of all task queue and voter pairs.
+ const std::vector<TaskQueueAndEnabledVoterPair>& GetAllTaskQueuesAndVoters()
+ const;
+
+ // Gets the associated QueueEnabledVoter for the given task queue, or nullptr
+ // if one doesn't exist.
+ base::sequence_manager::TaskQueue::QueueEnabledVoter* GetQueueEnabledVoter(
+ const scoped_refptr<MainThreadTaskQueue>&);
+
+ scoped_refptr<MainThreadTaskQueue> NewResourceLoadingTaskQueue();
+
+ // Remove a resource loading task queue that FrameTaskQueueController created,
+ // along with its QueueEnabledVoter, if one exists. Returns true if the task
+ // queue was found and erased and false otherwise.
+ //
+ // Removes are linear in the total number of task queues since
+ // |all_task_queues_and_voters_| needs to be updated.
+ bool RemoveResourceLoadingTaskQueue(
+ const scoped_refptr<MainThreadTaskQueue>&);
+
+ private:
+ friend class FrameTaskQueueControllerTest;
+
+ scoped_refptr<MainThreadTaskQueue> NewLoadingTaskQueue();
+ scoped_refptr<MainThreadTaskQueue> NewLoadingControlTaskQueue();
+ scoped_refptr<MainThreadTaskQueue> NewNonLoadingTaskQueue(
+ MainThreadTaskQueue::QueueTraits);
+
+ void TaskQueueCreated(const scoped_refptr<MainThreadTaskQueue>&);
+
+ // Returns the unique non-loading task queue for the given QueueTraits, or
+ // nullptr if one has not yet been created.
+ scoped_refptr<MainThreadTaskQueue> GetNonLoadingTaskQueue(
+ MainThreadTaskQueue::QueueTraits) const;
+
+ // Map a set of QueueTraits to a QueueType.
+ // TODO(shaseley): Consider creating a new queue type kFrameNonLoading and use
+ // it instead of this for new queue types.
+ static MainThreadTaskQueue::QueueType QueueTypeFromQueueTraits(
+ MainThreadTaskQueue::QueueTraits);
+
+ MainThreadSchedulerImpl* const main_thread_scheduler_impl_;
+ FrameSchedulerImpl* const frame_scheduler_impl_;
+ Delegate* const delegate_;
+
+ // Keep track of loading queues separately. We keep these separate because
+ // loading and loading control task queues share the same queue traits, and
+ // those queue traits can be the same as non-loading queues. This prevents us
+ // from being able to the find right task queue by queue traits alone.
+ scoped_refptr<MainThreadTaskQueue> loading_task_queue_;
+ scoped_refptr<MainThreadTaskQueue> loading_control_task_queue_;
+
+ using NonLoadingTaskQueueMap =
+ WTF::HashMap<MainThreadTaskQueue::QueueTraitsKeyType,
+ scoped_refptr<MainThreadTaskQueue>>;
+
+ // Map of all non-loading TaskQueues, indexed by QueueTraits.
+ NonLoadingTaskQueueMap non_loading_task_queues_;
+
+ // Set of all resource loading task queues.
+ WTF::HashSet<scoped_refptr<MainThreadTaskQueue>>
+ resource_loading_task_queues_;
+
+ using TaskQueueEnabledVoterMap = WTF::HashMap<
+ scoped_refptr<MainThreadTaskQueue>,
+ std::unique_ptr<base::sequence_manager::TaskQueue::QueueEnabledVoter>>;
+
+ // QueueEnabledVoters for the task queues we've created. Note: Some task
+ // queues do not have an associated voter.
+ TaskQueueEnabledVoterMap task_queue_enabled_voters_;
+
+ // The list of all task queue and voter pairs for all QueueTypeInternal queue
+ // types.
+ std::vector<TaskQueueAndEnabledVoterPair> all_task_queues_and_voters_;
+
+ DISALLOW_COPY_AND_ASSIGN(FrameTaskQueueController);
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_FRAME_TASK_QUEUE_CONTROLLER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
new file mode 100644
index 00000000000..2f862a9886f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
@@ -0,0 +1,235 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h"
+
+#include <memory>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
+#include "base/task/sequence_manager/task_queue.h"
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/test/scoped_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+
+using base::sequence_manager::TaskQueue;
+using QueueType = blink::scheduler::MainThreadTaskQueue::QueueType;
+using QueueTraits = blink::scheduler::MainThreadTaskQueue::QueueTraits;
+
+namespace blink {
+namespace scheduler {
+
+class FrameTaskQueueControllerTest : public testing::Test,
+ FrameTaskQueueController::Delegate {
+ public:
+ FrameTaskQueueControllerTest()
+ : task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+ base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED),
+ task_queue_created_count_(0) {}
+
+ ~FrameTaskQueueControllerTest() override = default;
+
+ void SetUp() override {
+ scheduler_.reset(new MainThreadSchedulerImpl(
+ base::sequence_manager::SequenceManagerForTest::Create(
+ nullptr, task_environment_.GetMainThreadTaskRunner(),
+ task_environment_.GetMockTickClock()),
+ base::nullopt));
+ page_scheduler_.reset(new PageSchedulerImpl(nullptr, scheduler_.get()));
+ frame_scheduler_ = FrameSchedulerImpl::Create(
+ page_scheduler_.get(), nullptr, FrameScheduler::FrameType::kSubframe);
+ frame_task_queue_controller_.reset(new FrameTaskQueueController(
+ scheduler_.get(), frame_scheduler_.get(), this));
+ }
+
+ void TearDown() override {
+ frame_task_queue_controller_.reset();
+ frame_scheduler_.reset();
+ page_scheduler_.reset();
+ scheduler_->Shutdown();
+ scheduler_.reset();
+ }
+
+ // FrameTaskQueueController::Delegate implementation.
+ void OnTaskQueueCreated(MainThreadTaskQueue* task_queue,
+ TaskQueue::QueueEnabledVoter* voter) override {
+ ++task_queue_created_count_;
+ }
+
+ protected:
+ scoped_refptr<MainThreadTaskQueue> NewLoadingTaskQueue() const {
+ return frame_task_queue_controller_->NewLoadingTaskQueue();
+ }
+
+ scoped_refptr<MainThreadTaskQueue> NewLoadingControlTaskQueue() const {
+ return frame_task_queue_controller_->NewLoadingControlTaskQueue();
+ }
+
+ scoped_refptr<MainThreadTaskQueue> NewNonLoadingTaskQueue(
+ QueueTraits queue_traits) const {
+ return frame_task_queue_controller_->NewNonLoadingTaskQueue(queue_traits);
+ }
+
+ scoped_refptr<MainThreadTaskQueue> NewResourceLoadingTaskQueue() const {
+ return frame_task_queue_controller_->NewResourceLoadingTaskQueue();
+ }
+
+ size_t task_queue_created_count() const { return task_queue_created_count_; }
+
+ protected:
+ base::test::ScopedTaskEnvironment task_environment_;
+ std::unique_ptr<MainThreadSchedulerImpl> scheduler_;
+ std::unique_ptr<PageSchedulerImpl> page_scheduler_;
+ std::unique_ptr<FrameSchedulerImpl> frame_scheduler_;
+ std::unique_ptr<FrameTaskQueueController> frame_task_queue_controller_;
+
+ private:
+ size_t task_queue_created_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(FrameTaskQueueControllerTest);
+};
+
+TEST_F(FrameTaskQueueControllerTest, CreateAllTaskQueues) {
+ enum class QueueCheckResult { kDidNotSeeQueue, kDidSeeQueue };
+
+ WTF::HashMap<scoped_refptr<MainThreadTaskQueue>, QueueCheckResult>
+ all_task_queues;
+
+ scoped_refptr<MainThreadTaskQueue> task_queue = NewLoadingTaskQueue();
+ EXPECT_FALSE(all_task_queues.Contains(task_queue));
+ all_task_queues.insert(task_queue.get(), QueueCheckResult::kDidNotSeeQueue);
+ EXPECT_EQ(all_task_queues.size(), task_queue_created_count());
+
+ task_queue = NewLoadingControlTaskQueue();
+ EXPECT_FALSE(all_task_queues.Contains(task_queue));
+ all_task_queues.insert(task_queue.get(), QueueCheckResult::kDidNotSeeQueue);
+ EXPECT_EQ(all_task_queues.size(), task_queue_created_count());
+
+ // Create the 4 default non-loading task queues used by FrameSchedulerImpl.
+ task_queue = NewNonLoadingTaskQueue(QueueTraits()
+ .SetCanBeThrottled(true)
+ .SetCanBeDeferred(true)
+ .SetCanBeFrozen(true)
+ .SetCanBePaused(true));
+ EXPECT_FALSE(all_task_queues.Contains(task_queue));
+ all_task_queues.insert(task_queue.get(), QueueCheckResult::kDidNotSeeQueue);
+ EXPECT_EQ(all_task_queues.size(), task_queue_created_count());
+
+ task_queue = NewNonLoadingTaskQueue(
+ QueueTraits().SetCanBeDeferred(true).SetCanBePaused(true));
+ EXPECT_FALSE(all_task_queues.Contains(task_queue));
+ all_task_queues.insert(task_queue.get(), QueueCheckResult::kDidNotSeeQueue);
+ EXPECT_EQ(all_task_queues.size(), task_queue_created_count());
+
+ task_queue = NewNonLoadingTaskQueue(QueueTraits().SetCanBePaused(true));
+ EXPECT_FALSE(all_task_queues.Contains(task_queue));
+ all_task_queues.insert(task_queue.get(), QueueCheckResult::kDidNotSeeQueue);
+ EXPECT_EQ(all_task_queues.size(), task_queue_created_count());
+
+ task_queue = NewNonLoadingTaskQueue(QueueTraits());
+ EXPECT_FALSE(all_task_queues.Contains(task_queue));
+ all_task_queues.insert(task_queue.get(), QueueCheckResult::kDidNotSeeQueue);
+ EXPECT_EQ(all_task_queues.size(), task_queue_created_count());
+
+ // Add a couple resource loading task queues.
+ task_queue = NewResourceLoadingTaskQueue();
+ EXPECT_FALSE(all_task_queues.Contains(task_queue));
+ all_task_queues.insert(task_queue.get(), QueueCheckResult::kDidNotSeeQueue);
+ EXPECT_EQ(all_task_queues.size(), task_queue_created_count());
+
+ task_queue = NewResourceLoadingTaskQueue();
+ EXPECT_FALSE(all_task_queues.Contains(task_queue));
+ all_task_queues.insert(task_queue.get(), QueueCheckResult::kDidNotSeeQueue);
+ EXPECT_EQ(all_task_queues.size(), task_queue_created_count());
+
+ // Verify that we get all of the queues that we added, and only those queues.
+ EXPECT_EQ(all_task_queues.size(),
+ frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
+ for (const auto& task_queue_and_voter :
+ frame_task_queue_controller_->GetAllTaskQueuesAndVoters()) {
+ MainThreadTaskQueue* task_queue;
+ TaskQueue::QueueEnabledVoter* voter;
+ std::tie(task_queue, voter) = task_queue_and_voter;
+
+ EXPECT_NE(task_queue, nullptr);
+ EXPECT_TRUE(all_task_queues.find(task_queue) != all_task_queues.end());
+ // Make sure we don't get the same queue twice.
+ auto it = all_task_queues.find(task_queue);
+ EXPECT_FALSE(it == all_task_queues.end());
+ EXPECT_EQ(it->value, QueueCheckResult::kDidNotSeeQueue);
+ all_task_queues.Set(task_queue, QueueCheckResult::kDidSeeQueue);
+ if (task_queue->queue_type() ==
+ MainThreadTaskQueue::QueueType::kFrameLoading ||
+ task_queue->queue_type() ==
+ MainThreadTaskQueue::QueueType::kFrameLoadingControl) {
+ EXPECT_NE(voter, nullptr);
+ } else if (task_queue->GetQueueTraits().can_be_paused) {
+ EXPECT_NE(voter, nullptr);
+ } else {
+ EXPECT_EQ(voter, nullptr);
+ }
+ }
+}
+
+TEST_F(FrameTaskQueueControllerTest, RemoveResourceLoadingTaskQueues) {
+ scoped_refptr<MainThreadTaskQueue> resource_loading_queue1 =
+ NewResourceLoadingTaskQueue();
+ EXPECT_EQ(1u,
+ frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
+ scoped_refptr<MainThreadTaskQueue> resource_loading_queue2 =
+ NewResourceLoadingTaskQueue();
+ EXPECT_EQ(2u,
+ frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
+
+ // Check that we can remove the resource loading queues.
+ bool was_removed =
+ frame_task_queue_controller_->RemoveResourceLoadingTaskQueue(
+ resource_loading_queue1);
+ EXPECT_TRUE(was_removed);
+ EXPECT_EQ(1u,
+ frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
+ // Can't delete twice.
+ was_removed = frame_task_queue_controller_->RemoveResourceLoadingTaskQueue(
+ resource_loading_queue1);
+ EXPECT_FALSE(was_removed);
+ EXPECT_EQ(1u,
+ frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
+
+ was_removed = frame_task_queue_controller_->RemoveResourceLoadingTaskQueue(
+ resource_loading_queue2);
+ EXPECT_TRUE(was_removed);
+ EXPECT_EQ(0u,
+ frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
+ // Can't delete twice.
+ was_removed = frame_task_queue_controller_->RemoveResourceLoadingTaskQueue(
+ resource_loading_queue2);
+ EXPECT_FALSE(was_removed);
+ EXPECT_EQ(0u,
+ frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
+}
+
+TEST_F(FrameTaskQueueControllerTest, CannotRemoveNonResourceLoadingTaskQueues) {
+ scoped_refptr<MainThreadTaskQueue> task_queue = NewLoadingTaskQueue();
+ EXPECT_EQ(1u,
+ frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
+ bool was_removed =
+ frame_task_queue_controller_->RemoveResourceLoadingTaskQueue(task_queue);
+ EXPECT_FALSE(was_removed);
+ EXPECT_EQ(1u,
+ frame_task_queue_controller_->GetAllTaskQueuesAndVoters().size());
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h
index 48141651c0e..1f72d600fbe 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h
@@ -7,10 +7,10 @@
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
+#include "base/task/sequence_manager/task_queue.h"
#include "base/time/tick_clock.h"
#include "cc/base/rolling_time_delta_history.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
namespace blink {
namespace scheduler {
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator_unittest.cc
index 57b5b940027..c12e7b3ae43 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator_unittest.cc
@@ -5,16 +5,16 @@
#include "third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h"
#include <memory>
+
#include "base/memory/scoped_refptr.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "components/viz/test/ordered_simple_task_runner.h"
+#include "base/task/sequence_manager/sequence_manager.h"
+#include "base/task/sequence_manager/task_queue.h"
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/task/sequence_manager/test/test_task_queue.h"
+#include "base/task/sequence_manager/test/test_task_time_observer.h"
+#include "base/test/scoped_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/test_task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/test_task_time_observer.h"
namespace blink {
namespace scheduler {
@@ -36,21 +36,25 @@ class IdleTimeEstimatorForTest : public IdleTimeEstimator {
class IdleTimeEstimatorTest : public testing::Test {
public:
IdleTimeEstimatorTest()
- : frame_length_(base::TimeDelta::FromMilliseconds(16)) {}
+ : task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+ base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED),
+ frame_length_(base::TimeDelta::FromMilliseconds(16)) {
+ // Null clock might trigger some assertions.
+ task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(5));
+ }
~IdleTimeEstimatorTest() override = default;
void SetUp() override {
- clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
- mock_task_runner_ =
- base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, false);
- manager_ = base::sequence_manager::TaskQueueManagerForTest::Create(
- nullptr, mock_task_runner_, &clock_);
+ manager_ = base::sequence_manager::SequenceManagerForTest::Create(
+ nullptr, task_environment_.GetMainThreadTaskRunner(),
+ task_environment_.GetMockTickClock());
compositor_task_queue_ =
manager_->CreateTaskQueue<base::sequence_manager::TestTaskQueue>(
base::sequence_manager::TaskQueue::Spec("test_tq"));
- estimator_.reset(
- new IdleTimeEstimatorForTest(compositor_task_queue_, &clock_, 10, 50));
+ estimator_.reset(new IdleTimeEstimatorForTest(
+ compositor_task_queue_, task_environment_.GetMockTickClock(), 10, 50));
}
void SimulateFrameWithOneCompositorTask(int compositor_time) {
@@ -58,11 +62,11 @@ class IdleTimeEstimatorTest : public testing::Test {
base::TimeDelta::FromMilliseconds(compositor_time);
base::PendingTask task(FROM_HERE, base::Closure());
estimator_->WillProcessTask(task);
- clock_.Advance(non_idle_time);
+ task_environment_.FastForwardBy(non_idle_time);
estimator_->DidCommitFrameToCompositor();
estimator_->DidProcessTask(task);
if (non_idle_time < frame_length_)
- clock_.Advance(frame_length_ - non_idle_time);
+ task_environment_.FastForwardBy(frame_length_ - non_idle_time);
}
void SimulateFrameWithTwoCompositorTasks(int compositor_time1,
@@ -73,21 +77,20 @@ class IdleTimeEstimatorTest : public testing::Test {
base::TimeDelta::FromMilliseconds(compositor_time2);
base::PendingTask task(FROM_HERE, base::Closure());
estimator_->WillProcessTask(task);
- clock_.Advance(non_idle_time1);
+ task_environment_.FastForwardBy(non_idle_time1);
estimator_->DidProcessTask(task);
estimator_->WillProcessTask(task);
- clock_.Advance(non_idle_time2);
+ task_environment_.FastForwardBy(non_idle_time2);
estimator_->DidCommitFrameToCompositor();
estimator_->DidProcessTask(task);
base::TimeDelta idle_time = frame_length_ - non_idle_time1 - non_idle_time2;
- clock_.Advance(idle_time);
+ task_environment_.FastForwardBy(idle_time);
}
- base::SimpleTestTickClock clock_;
- scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
- std::unique_ptr<base::sequence_manager::TaskQueueManager> manager_;
+ base::test::ScopedTaskEnvironment task_environment_;
+ std::unique_ptr<base::sequence_manager::SequenceManager> manager_;
scoped_refptr<base::sequence_manager::TaskQueue> compositor_task_queue_;
std::unique_ptr<IdleTimeEstimatorForTest> estimator_;
const base::TimeDelta frame_length_;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.cc
index 783c18a88b7..69bc681f6b3 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.cc
@@ -6,9 +6,11 @@
#include "base/bind.h"
#include "base/metrics/histogram_macros.h"
+#include "base/numerics/safe_conversions.h"
#include "services/resource_coordinator/public/cpp/resource_coordinator_features.h"
#include "third_party/blink/public/platform/scheduler/renderer_process_type.h"
#include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
@@ -16,19 +18,19 @@ namespace blink {
namespace scheduler {
#define DURATION_PER_QUEUE_TYPE_METRIC_NAME \
- "RendererScheduler.TaskDurationPerQueueType2"
+ "RendererScheduler.TaskDurationPerQueueType3"
#define COUNT_PER_QUEUE_TYPE_METRIC_NAME \
"RendererScheduler.TaskCountPerQueueType"
#define MAIN_THREAD_LOAD_METRIC_NAME "RendererScheduler.RendererMainThreadLoad5"
#define EXTENSIONS_MAIN_THREAD_LOAD_METRIC_NAME \
MAIN_THREAD_LOAD_METRIC_NAME ".Extension"
#define DURATION_PER_FRAME_TYPE_METRIC_NAME \
- "RendererScheduler.TaskDurationPerFrameType2"
+ "RendererScheduler.TaskDurationPerFrameType3"
#define DURATION_PER_TASK_TYPE_METRIC_NAME \
- "RendererScheduler.TaskDurationPerTaskType"
+ "RendererScheduler.TaskDurationPerTaskType2"
#define COUNT_PER_FRAME_METRIC_NAME "RendererScheduler.TaskCountPerFrameType"
#define DURATION_PER_TASK_USE_CASE_NAME \
- "RendererScheduler.TaskDurationPerUseCase"
+ "RendererScheduler.TaskDurationPerUseCase2"
enum class MainThreadTaskLoadState { kLow, kHigh, kUnknown };
@@ -66,19 +68,28 @@ MainThreadMetricsHelper::PerQueueTypeDurationReporters::
".Background.FifthMinute"),
background_after_fifth_minute(DURATION_PER_QUEUE_TYPE_METRIC_NAME
".Background.AfterFifthMinute"),
+ background_after_tenth_minute(DURATION_PER_QUEUE_TYPE_METRIC_NAME
+ ".Background.AfterTenthMinute"),
background_keep_active_after_fifth_minute(
DURATION_PER_QUEUE_TYPE_METRIC_NAME
".Background.KeepAlive.AfterFifthMinute"),
+ background_keep_active_after_tenth_minute(
+ DURATION_PER_QUEUE_TYPE_METRIC_NAME
+ ".Background.KeepAlive.AfterTenthMinute"),
hidden(DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Hidden"),
visible(DURATION_PER_QUEUE_TYPE_METRIC_NAME ".Visible"),
hidden_music(DURATION_PER_QUEUE_TYPE_METRIC_NAME ".HiddenMusic") {}
MainThreadMetricsHelper::MainThreadMetricsHelper(
MainThreadSchedulerImpl* main_thread_scheduler,
+ bool has_cpu_timing_for_each_task,
base::TimeTicks now,
bool renderer_backgrounded)
- : MetricsHelper(WebThreadType::kMainThread),
+ : MetricsHelper(WebThreadType::kMainThread, has_cpu_timing_for_each_task),
main_thread_scheduler_(main_thread_scheduler),
+ renderer_shutting_down_(false),
+ is_page_almost_idle_signal_enabled_(
+ ::resource_coordinator::IsPageAlmostIdleSignalEnabled()),
main_thread_load_tracker_(
now,
base::BindRepeating(
@@ -109,7 +120,14 @@ MainThreadMetricsHelper::MainThreadMetricsHelper(
DURATION_PER_TASK_TYPE_METRIC_NAME ".Foreground"),
background_per_task_type_duration_reporter_(
DURATION_PER_TASK_TYPE_METRIC_NAME ".Background"),
+ background_after_fifth_minute_per_task_type_duration_reporter_(
+ DURATION_PER_TASK_TYPE_METRIC_NAME ".Background.AfterFifthMinute"),
+ background_after_tenth_minute_per_task_type_duration_reporter_(
+ DURATION_PER_TASK_TYPE_METRIC_NAME ".Background.AfterTenthMinute"),
per_task_use_case_duration_reporter_(DURATION_PER_TASK_USE_CASE_NAME),
+ total_task_time_reporter_(
+ "Scheduler.Experimental.Renderer.TotalTime.Wall.MainThread.Positive",
+ "Scheduler.Experimental.Renderer.TotalTime.Wall.MainThread.Negative"),
main_thread_task_load_state_(MainThreadTaskLoadState::kUnknown) {
main_thread_load_tracker_.Resume(now);
if (renderer_backgrounded) {
@@ -132,6 +150,7 @@ void MainThreadMetricsHelper::OnRendererBackgrounded(base::TimeTicks now) {
}
void MainThreadMetricsHelper::OnRendererShutdown(base::TimeTicks now) {
+ renderer_shutting_down_ = true;
foreground_main_thread_load_tracker_.RecordIdle(now);
background_main_thread_load_tracker_.RecordIdle(now);
main_thread_load_tracker_.RecordIdle(now);
@@ -177,38 +196,44 @@ base::TimeDelta DurationOfIntervalOverlap(base::TimeTicks start1,
void MainThreadMetricsHelper::RecordTaskMetrics(
MainThreadTaskQueue* queue,
const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start_time,
- base::TimeTicks end_time,
- base::Optional<base::TimeDelta> thread_time) {
- if (ShouldDiscardTask(queue, task, start_time, end_time, thread_time))
+ const base::sequence_manager::TaskQueue::TaskTiming& task_timing) {
+ if (ShouldDiscardTask(queue, task, task_timing))
return;
- MetricsHelper::RecordCommonTaskMetrics(queue, task, start_time, end_time,
- thread_time);
+ MetricsHelper::RecordCommonTaskMetrics(queue, task, task_timing);
+
+ total_task_time_reporter_.RecordAdditionalDuration(
+ task_timing.wall_duration());
MainThreadTaskQueue::QueueType queue_type =
queue ? queue->queue_type() : MainThreadTaskQueue::QueueType::kDetached;
- base::TimeDelta duration = end_time - start_time;
+ base::TimeDelta duration = task_timing.wall_duration();
// Discard anomalously long idle periods.
- if (last_reported_task_ && start_time - last_reported_task_.value() >
- kLongIdlePeriodDiscardingThreshold) {
- main_thread_load_tracker_.Reset(end_time);
- foreground_main_thread_load_tracker_.Reset(end_time);
- background_main_thread_load_tracker_.Reset(end_time);
+ if (last_reported_task_ &&
+ task_timing.start_time() - last_reported_task_.value() >
+ kLongIdlePeriodDiscardingThreshold) {
+ main_thread_load_tracker_.Reset(task_timing.end_time());
+ foreground_main_thread_load_tracker_.Reset(task_timing.end_time());
+ background_main_thread_load_tracker_.Reset(task_timing.end_time());
return;
}
- last_reported_task_ = end_time;
+ last_reported_task_ = task_timing.end_time();
UMA_HISTOGRAM_CUSTOM_COUNTS("RendererScheduler.TaskTime2",
- duration.InMicroseconds(), 1, 1000 * 1000, 50);
+ base::saturated_cast<base::HistogramBase::Sample>(
+ duration.InMicroseconds()),
+ 1, 1000 * 1000, 50);
// We want to measure thread time here, but for efficiency reasons
// we stick with wall time.
- main_thread_load_tracker_.RecordTaskTime(start_time, end_time);
- foreground_main_thread_load_tracker_.RecordTaskTime(start_time, end_time);
- background_main_thread_load_tracker_.RecordTaskTime(start_time, end_time);
+ main_thread_load_tracker_.RecordTaskTime(task_timing.start_time(),
+ task_timing.end_time());
+ foreground_main_thread_load_tracker_.RecordTaskTime(task_timing.start_time(),
+ task_timing.end_time());
+ background_main_thread_load_tracker_.RecordTaskTime(task_timing.start_time(),
+ task_timing.end_time());
UMA_HISTOGRAM_ENUMERATION(COUNT_PER_QUEUE_TYPE_METRIC_NAME, queue_type,
MainThreadTaskQueue::QueueType::kCount);
@@ -257,41 +282,50 @@ void MainThreadMetricsHelper::RecordTaskMetrics(
main_thread_scheduler_->main_thread_only().background_status_changed_at;
per_queue_type_reporters_.background_first_minute.RecordTask(
- queue_type, DurationOfIntervalOverlap(
- start_time, end_time, backgrounded_at,
- backgrounded_at + base::TimeDelta::FromMinutes(1)));
+ queue_type,
+ DurationOfIntervalOverlap(
+ task_timing.start_time(), task_timing.end_time(), backgrounded_at,
+ backgrounded_at + base::TimeDelta::FromMinutes(1)));
per_queue_type_reporters_.background_second_minute.RecordTask(
queue_type, DurationOfIntervalOverlap(
- start_time, end_time,
+ task_timing.start_time(), task_timing.end_time(),
backgrounded_at + base::TimeDelta::FromMinutes(1),
backgrounded_at + base::TimeDelta::FromMinutes(2)));
per_queue_type_reporters_.background_third_minute.RecordTask(
queue_type, DurationOfIntervalOverlap(
- start_time, end_time,
+ task_timing.start_time(), task_timing.end_time(),
backgrounded_at + base::TimeDelta::FromMinutes(2),
backgrounded_at + base::TimeDelta::FromMinutes(3)));
per_queue_type_reporters_.background_fourth_minute.RecordTask(
queue_type, DurationOfIntervalOverlap(
- start_time, end_time,
+ task_timing.start_time(), task_timing.end_time(),
backgrounded_at + base::TimeDelta::FromMinutes(3),
backgrounded_at + base::TimeDelta::FromMinutes(4)));
per_queue_type_reporters_.background_fifth_minute.RecordTask(
queue_type, DurationOfIntervalOverlap(
- start_time, end_time,
+ task_timing.start_time(), task_timing.end_time(),
backgrounded_at + base::TimeDelta::FromMinutes(4),
backgrounded_at + base::TimeDelta::FromMinutes(5)));
per_queue_type_reporters_.background_after_fifth_minute.RecordTask(
queue_type,
DurationOfIntervalOverlap(
- start_time, end_time,
+ task_timing.start_time(), task_timing.end_time(),
backgrounded_at + base::TimeDelta::FromMinutes(5),
std::max(backgrounded_at + base::TimeDelta::FromMinutes(5),
- end_time)));
+ task_timing.end_time())));
+
+ per_queue_type_reporters_.background_after_tenth_minute.RecordTask(
+ queue_type,
+ DurationOfIntervalOverlap(
+ task_timing.start_time(), task_timing.end_time(),
+ backgrounded_at + base::TimeDelta::FromMinutes(10),
+ std::max(backgrounded_at + base::TimeDelta::FromMinutes(10),
+ task_timing.end_time())));
if (main_thread_scheduler_->main_thread_only()
.keep_active_fetch_or_worker) {
@@ -299,13 +333,36 @@ void MainThreadMetricsHelper::RecordTaskMetrics(
.RecordTask(
queue_type,
DurationOfIntervalOverlap(
- start_time, end_time,
+ task_timing.start_time(), task_timing.end_time(),
backgrounded_at + base::TimeDelta::FromMinutes(5),
std::max(backgrounded_at + base::TimeDelta::FromMinutes(5),
- end_time)));
+ task_timing.end_time())));
+ per_queue_type_reporters_.background_keep_active_after_tenth_minute
+ .RecordTask(
+ queue_type,
+ DurationOfIntervalOverlap(
+ task_timing.start_time(), task_timing.end_time(),
+ backgrounded_at + base::TimeDelta::FromMinutes(10),
+ std::max(backgrounded_at + base::TimeDelta::FromMinutes(10),
+ task_timing.end_time())));
}
background_per_task_type_duration_reporter_.RecordTask(task_type, duration);
+
+ background_after_fifth_minute_per_task_type_duration_reporter_.RecordTask(
+ task_type,
+ DurationOfIntervalOverlap(
+ task_timing.start_time(), task_timing.end_time(),
+ backgrounded_at + base::TimeDelta::FromMinutes(5),
+ std::max(backgrounded_at + base::TimeDelta::FromMinutes(5),
+ task_timing.end_time())));
+ background_after_tenth_minute_per_task_type_duration_reporter_.RecordTask(
+ task_type,
+ DurationOfIntervalOverlap(
+ task_timing.start_time(), task_timing.end_time(),
+ backgrounded_at + base::TimeDelta::FromMinutes(10),
+ std::max(backgrounded_at + base::TimeDelta::FromMinutes(10),
+ task_timing.end_time())));
} else {
per_queue_type_reporters_.foreground.RecordTask(queue_type, duration);
@@ -315,29 +372,30 @@ void MainThreadMetricsHelper::RecordTaskMetrics(
main_thread_scheduler_->main_thread_only().background_status_changed_at;
per_queue_type_reporters_.foreground_first_minute.RecordTask(
- queue_type, DurationOfIntervalOverlap(
- start_time, end_time, foregrounded_at,
- foregrounded_at + base::TimeDelta::FromMinutes(1)));
+ queue_type,
+ DurationOfIntervalOverlap(
+ task_timing.start_time(), task_timing.end_time(), foregrounded_at,
+ foregrounded_at + base::TimeDelta::FromMinutes(1)));
per_queue_type_reporters_.foreground_second_minute.RecordTask(
queue_type, DurationOfIntervalOverlap(
- start_time, end_time,
+ task_timing.start_time(), task_timing.end_time(),
foregrounded_at + base::TimeDelta::FromMinutes(1),
foregrounded_at + base::TimeDelta::FromMinutes(2)));
per_queue_type_reporters_.foreground_third_minute.RecordTask(
queue_type, DurationOfIntervalOverlap(
- start_time, end_time,
+ task_timing.start_time(), task_timing.end_time(),
foregrounded_at + base::TimeDelta::FromMinutes(2),
foregrounded_at + base::TimeDelta::FromMinutes(3)));
per_queue_type_reporters_.foreground_after_third_minute.RecordTask(
queue_type,
DurationOfIntervalOverlap(
- start_time, end_time,
+ task_timing.start_time(), task_timing.end_time(),
foregrounded_at + base::TimeDelta::FromMinutes(3),
std::max(foregrounded_at + base::TimeDelta::FromMinutes(3),
- end_time)));
+ task_timing.end_time())));
foreground_per_task_type_duration_reporter_.RecordTask(task_type, duration);
}
@@ -401,21 +459,7 @@ void MainThreadMetricsHelper::RecordMainThreadTaskLoad(base::TimeTicks time,
int load_percentage = static_cast<int>(load * 100);
DCHECK_LE(load_percentage, 100);
- if (::resource_coordinator::IsPageAlmostIdleSignalEnabled()) {
- static const int main_thread_task_load_low_threshold =
- ::resource_coordinator::GetMainThreadTaskLoadLowThreshold();
-
- // Avoid sending duplicate IPCs when the state doesn't change.
- if (load_percentage <= main_thread_task_load_low_threshold &&
- main_thread_task_load_state_ != MainThreadTaskLoadState::kLow) {
- RendererResourceCoordinator::Get().SetMainThreadTaskLoadIsLow(true);
- main_thread_task_load_state_ = MainThreadTaskLoadState::kLow;
- } else if (load_percentage > main_thread_task_load_low_threshold &&
- main_thread_task_load_state_ != MainThreadTaskLoadState::kHigh) {
- RendererResourceCoordinator::Get().SetMainThreadTaskLoadIsLow(false);
- main_thread_task_load_state_ = MainThreadTaskLoadState::kHigh;
- }
- }
+ ReportLowThreadLoadForPageAlmostIdleSignal(load_percentage);
UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME, load_percentage);
@@ -445,9 +489,10 @@ void MainThreadMetricsHelper::RecordForegroundMainThreadTaskLoad(
UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME ".Foreground",
load_percentage);
- if (time - main_thread_scheduler_->main_thread_only()
- .background_status_changed_at >
- base::TimeDelta::FromMinutes(1)) {
+ base::TimeDelta time_since_foregrounded =
+ time - main_thread_scheduler_->main_thread_only()
+ .background_status_changed_at;
+ if (time_since_foregrounded > base::TimeDelta::FromMinutes(1)) {
UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME
".Foreground.AfterFirstMinute",
load_percentage);
@@ -476,13 +521,24 @@ void MainThreadMetricsHelper::RecordBackgroundMainThreadTaskLoad(
UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME ".Background",
load_percentage);
- if (time - main_thread_scheduler_->main_thread_only()
- .background_status_changed_at >
- base::TimeDelta::FromMinutes(1)) {
+ base::TimeDelta time_since_backgrounded =
+ time - main_thread_scheduler_->main_thread_only()
+ .background_status_changed_at;
+ if (time_since_backgrounded > base::TimeDelta::FromMinutes(1)) {
UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME
".Background.AfterFirstMinute",
load_percentage);
}
+ if (time_since_backgrounded > base::TimeDelta::FromMinutes(5)) {
+ UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME
+ ".Background.AfterFifthMinute",
+ load_percentage);
+ }
+ if (time_since_backgrounded > base::TimeDelta::FromMinutes(10)) {
+ UMA_HISTOGRAM_PERCENTAGE(MAIN_THREAD_LOAD_METRIC_NAME
+ ".Background.AfterTenthMinute",
+ load_percentage);
+ }
break;
}
@@ -491,11 +547,32 @@ void MainThreadMetricsHelper::RecordBackgroundMainThreadTaskLoad(
load_percentage);
}
-// static
-void MainThreadMetricsHelper::RecordBackgroundedTransition(
- BackgroundedRendererTransition transition) {
- UMA_HISTOGRAM_ENUMERATION("RendererScheduler.BackgroundedRendererTransition",
- transition, BackgroundedRendererTransition::kCount);
+void MainThreadMetricsHelper::ReportLowThreadLoadForPageAlmostIdleSignal(
+ int load_percentage) {
+ if (!is_page_almost_idle_signal_enabled_)
+ return;
+
+ // Avoid sending IPCs when the renderer is shutting down as this wreaks havoc
+ // in test harnesses. These messages aren't needed in production code either
+ // as the endpoint receiving them dies shortly after and does nothing with
+ // them.
+ if (renderer_shutting_down_)
+ return;
+
+ static const int main_thread_task_load_low_threshold =
+ ::resource_coordinator::GetMainThreadTaskLoadLowThreshold();
+
+ // Avoid sending duplicate IPCs when the state doesn't change.
+ if (load_percentage <= main_thread_task_load_low_threshold &&
+ main_thread_task_load_state_ != MainThreadTaskLoadState::kLow) {
+ RendererResourceCoordinator::Get().SetMainThreadTaskLoadIsLow(true);
+ main_thread_task_load_state_ = MainThreadTaskLoadState::kLow;
+ } else if (load_percentage > main_thread_task_load_low_threshold &&
+ main_thread_task_load_state_ != MainThreadTaskLoadState::kHigh) {
+ RendererResourceCoordinator::Get().SetMainThreadTaskLoadIsLow(false);
+ main_thread_task_load_state_ = MainThreadTaskLoadState::kHigh;
+ }
}
+
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.h
index 0e851539360..88d0e58e237 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper.h
@@ -11,7 +11,8 @@
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_thread_type.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/child/metrics_helper.h"
+#include "third_party/blink/renderer/platform/scheduler/common/metrics_helper.h"
+#include "third_party/blink/renderer/platform/scheduler/common/total_duration_metric_reporter.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/use_case.h"
#include "third_party/blink/renderer/platform/scheduler/renderer/frame_status.h"
@@ -25,41 +26,20 @@ enum class MainThreadTaskLoadState;
class MainThreadTaskQueue;
class MainThreadSchedulerImpl;
-// This enum is used for histogram and should not be renumbered.
-// It tracks the following possible transitions:
-// -> kBackgrounded (-> [FROZEN_* -> kResumed])? -> kForegrounded
-enum class BackgroundedRendererTransition {
- // Renderer is backgrounded
- kBackgrounded = 0,
- // Renderer is frozen after being backgrounded for a while
- kFrozenAfterDelay = 1,
- // Renderer is frozen due to critical resources, reserved for future use.
- kFrozenDueToCriticalResources = 2,
- // Renderer is resumed after being frozen
- kResumed = 3,
- // Renderer is foregrounded
- kForegrounded = 4,
-
- kCount = 5
-};
-
// Helper class to take care of metrics on behalf of MainThreadScheduler.
// This class should be used only on the main thread.
class PLATFORM_EXPORT MainThreadMetricsHelper : public MetricsHelper {
public:
- static void RecordBackgroundedTransition(
- BackgroundedRendererTransition transition);
-
MainThreadMetricsHelper(MainThreadSchedulerImpl* main_thread_scheduler,
+ bool has_cpu_timing_for_each_task,
base::TimeTicks now,
bool renderer_backgrounded);
~MainThreadMetricsHelper();
- void RecordTaskMetrics(MainThreadTaskQueue* queue,
- const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start_time,
- base::TimeTicks end_time,
- base::Optional<base::TimeDelta> thread_time);
+ void RecordTaskMetrics(
+ MainThreadTaskQueue* queue,
+ const base::sequence_manager::TaskQueue::Task& task,
+ const base::sequence_manager::TaskQueue::TaskTiming& task_timing);
void OnRendererForegrounded(base::TimeTicks now);
void OnRendererBackgrounded(base::TimeTicks now);
@@ -72,8 +52,17 @@ class PLATFORM_EXPORT MainThreadMetricsHelper : public MetricsHelper {
void ResetForTest(base::TimeTicks now);
private:
+ void ReportLowThreadLoadForPageAlmostIdleSignal(int load_percentage);
+
MainThreadSchedulerImpl* main_thread_scheduler_; // NOT OWNED
+ // Set to true when OnRendererShutdown is called. Used to ensure that metrics
+ // that need to cross IPC boundaries aren't sent, as they cause additional
+ // useless tasks to be posted.
+ bool renderer_shutting_down_;
+
+ const bool is_page_almost_idle_signal_enabled_;
+
base::Optional<base::TimeTicks> last_reported_task_;
ThreadLoadTracker main_thread_load_tracker_;
@@ -99,8 +88,11 @@ class PLATFORM_EXPORT MainThreadMetricsHelper : public MetricsHelper {
TaskDurationPerQueueTypeMetricReporter background_fourth_minute;
TaskDurationPerQueueTypeMetricReporter background_fifth_minute;
TaskDurationPerQueueTypeMetricReporter background_after_fifth_minute;
+ TaskDurationPerQueueTypeMetricReporter background_after_tenth_minute;
TaskDurationPerQueueTypeMetricReporter
background_keep_active_after_fifth_minute;
+ TaskDurationPerQueueTypeMetricReporter
+ background_keep_active_after_tenth_minute;
TaskDurationPerQueueTypeMetricReporter hidden;
TaskDurationPerQueueTypeMetricReporter visible;
TaskDurationPerQueueTypeMetricReporter hidden_music;
@@ -130,9 +122,15 @@ class PLATFORM_EXPORT MainThreadMetricsHelper : public MetricsHelper {
foreground_per_task_type_duration_reporter_;
TaskDurationPerTaskTypeMetricReporter
background_per_task_type_duration_reporter_;
+ TaskDurationPerTaskTypeMetricReporter
+ background_after_fifth_minute_per_task_type_duration_reporter_;
+ TaskDurationPerTaskTypeMetricReporter
+ background_after_tenth_minute_per_task_type_duration_reporter_;
TaskDurationMetricReporter<UseCase> per_task_use_case_duration_reporter_;
+ TotalDurationMetricReporter total_task_time_reporter_;
+
MainThreadTaskLoadState main_thread_task_load_state_;
DISALLOW_COPY_AND_ASSIGN(MainThreadMetricsHelper);
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper_unittest.cc
index c31f8cd57b9..435fd1a687d 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper_unittest.cc
@@ -6,19 +6,22 @@
#include <memory>
#include "base/macros.h"
-#include "base/test/histogram_tester.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "components/viz/test/ordered_simple_task_runner.h"
+#include "base/task/sequence_manager/test/fake_task.h"
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/page/launching_process_state.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/test/fake_frame_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/test/fake_page_scheduler.h"
+#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
using base::sequence_manager::TaskQueue;
+using base::sequence_manager::FakeTask;
+using base::sequence_manager::FakeTaskTiming;
namespace blink {
namespace scheduler {
@@ -27,10 +30,9 @@ namespace {
class MainThreadSchedulerImplForTest : public MainThreadSchedulerImpl {
public:
MainThreadSchedulerImplForTest(
- std::unique_ptr<base::sequence_manager::TaskQueueManager>
- task_queue_manager,
+ std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager,
base::Optional<base::Time> initial_virtual_time)
- : MainThreadSchedulerImpl(std::move(task_queue_manager),
+ : MainThreadSchedulerImpl(std::move(sequence_manager),
initial_virtual_time){};
using MainThreadSchedulerImpl::SetCurrentUseCaseForTest;
@@ -44,17 +46,22 @@ using testing::UnorderedElementsAre;
class MainThreadMetricsHelperTest : public testing::Test {
public:
- MainThreadMetricsHelperTest() = default;
+ MainThreadMetricsHelperTest()
+ : task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+ base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED) {
+ // Null clock might trigger some assertions.
+ task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(1));
+ }
+
~MainThreadMetricsHelperTest() override = default;
void SetUp() override {
histogram_tester_.reset(new base::HistogramTester());
- clock_.Advance(base::TimeDelta::FromMilliseconds(1));
- mock_task_runner_ =
- base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, true);
scheduler_ = std::make_unique<MainThreadSchedulerImplForTest>(
- base::sequence_manager::TaskQueueManagerForTest::Create(
- nullptr, mock_task_runner_, &clock_),
+ base::sequence_manager::SequenceManagerForTest::Create(
+ nullptr, task_environment_.GetMainThreadTaskRunner(),
+ task_environment_.GetMockTickClock()),
base::nullopt);
metrics_helper_ = &scheduler_->main_thread_only().metrics_helper;
}
@@ -64,58 +71,62 @@ class MainThreadMetricsHelperTest : public testing::Test {
scheduler_.reset();
}
+ base::TimeTicks Now() {
+ return task_environment_.GetMockTickClock()->NowTicks();
+ }
+
+ void FastForwardTo(base::TimeTicks time) {
+ CHECK_LE(Now(), time);
+ task_environment_.FastForwardBy(time - Now());
+ }
+
void RunTask(MainThreadTaskQueue::QueueType queue_type,
base::TimeTicks start,
base::TimeDelta duration) {
- DCHECK_LE(clock_.NowTicks(), start);
- clock_.SetNowTicks(start + duration);
+ DCHECK_LE(Now(), start);
+ FastForwardTo(start + duration);
scoped_refptr<MainThreadTaskQueueForTest> queue;
if (queue_type != MainThreadTaskQueue::QueueType::kDetached) {
queue = scoped_refptr<MainThreadTaskQueueForTest>(
new MainThreadTaskQueueForTest(queue_type));
}
- // Pass an empty task for recording.
- TaskQueue::PostedTask posted_task(base::OnceClosure(), FROM_HERE);
- TaskQueue::Task task(std::move(posted_task), base::TimeTicks());
- metrics_helper_->RecordTaskMetrics(queue.get(), task, start,
- start + duration, base::nullopt);
+ metrics_helper_->RecordTaskMetrics(queue.get(), FakeTask(),
+ FakeTaskTiming(start, start + duration));
}
- void RunTask(FrameScheduler* scheduler,
+ void RunTask(FrameSchedulerImpl* scheduler,
base::TimeTicks start,
base::TimeDelta duration) {
- DCHECK_LE(clock_.NowTicks(), start);
- clock_.SetNowTicks(start + duration);
+ DCHECK_LE(Now(), start);
+ FastForwardTo(start + duration);
scoped_refptr<MainThreadTaskQueueForTest> queue(
new MainThreadTaskQueueForTest(QueueType::kDefault));
queue->SetFrameSchedulerForTest(scheduler);
- // Pass an empty task for recording.
- TaskQueue::PostedTask posted_task(base::OnceClosure(), FROM_HERE);
- TaskQueue::Task task(std::move(posted_task), base::TimeTicks());
- metrics_helper_->RecordTaskMetrics(queue.get(), task, start,
- start + duration, base::nullopt);
+ metrics_helper_->RecordTaskMetrics(queue.get(), FakeTask(),
+ FakeTaskTiming(start, start + duration));
}
void RunTask(UseCase use_case,
base::TimeTicks start,
base::TimeDelta duration) {
- DCHECK_LE(clock_.NowTicks(), start);
- clock_.SetNowTicks(start + duration);
+ DCHECK_LE(Now(), start);
+ FastForwardTo(start + duration);
scoped_refptr<MainThreadTaskQueueForTest> queue(
new MainThreadTaskQueueForTest(QueueType::kDefault));
scheduler_->SetCurrentUseCaseForTest(use_case);
- // Pass an empty task for recording.
- TaskQueue::PostedTask posted_task(base::OnceClosure(), FROM_HERE);
- TaskQueue::Task task(std::move(posted_task), base::TimeTicks());
- metrics_helper_->RecordTaskMetrics(queue.get(), task, start,
- start + duration, base::nullopt);
+ metrics_helper_->RecordTaskMetrics(queue.get(), FakeTask(),
+ FakeTaskTiming(start, start + duration));
}
base::TimeTicks Milliseconds(int milliseconds) {
return base::TimeTicks() + base::TimeDelta::FromMilliseconds(milliseconds);
}
+ base::TimeTicks Seconds(int seconds) {
+ return base::TimeTicks() + base::TimeDelta::FromSeconds(seconds);
+ }
+
void ForceUpdatePolicy() { scheduler_->ForceUpdatePolicy(); }
std::unique_ptr<FakeFrameScheduler> CreateFakeFrameSchedulerWithType(
@@ -226,8 +237,7 @@ class MainThreadMetricsHelperTest : public testing::Test {
return builder.Build();
}
- base::SimpleTestTickClock clock_;
- scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
+ base::test::ScopedTaskEnvironment task_environment_;
std::unique_ptr<MainThreadSchedulerImplForTest> scheduler_;
MainThreadMetricsHelper* metrics_helper_; // NOT OWNED
std::unique_ptr<base::HistogramTester> histogram_tester_;
@@ -248,133 +258,128 @@ TEST_F(MainThreadMetricsHelperTest, Metrics_PerQueueType) {
if (kLaunchingProcessIsBackgrounded)
scheduler_->SetRendererBackgrounded(false);
- RunTask(QueueType::kDefault, Milliseconds(1),
- base::TimeDelta::FromMicroseconds(700));
- RunTask(QueueType::kDefault, Milliseconds(2),
- base::TimeDelta::FromMicroseconds(700));
- RunTask(QueueType::kDefault, Milliseconds(3),
- base::TimeDelta::FromMicroseconds(700));
-
- RunTask(QueueType::kControl, Milliseconds(400),
- base::TimeDelta::FromMilliseconds(30));
- RunTask(QueueType::kFrameLoading, Milliseconds(800),
- base::TimeDelta::FromMilliseconds(70));
- RunTask(QueueType::kFramePausable, Milliseconds(1000),
- base::TimeDelta::FromMilliseconds(20));
- RunTask(QueueType::kCompositor, Milliseconds(1200),
- base::TimeDelta::FromMilliseconds(25));
- RunTask(QueueType::kTest, Milliseconds(1600),
- base::TimeDelta::FromMilliseconds(85));
+ RunTask(QueueType::kDefault, Seconds(1),
+ base::TimeDelta::FromMilliseconds(700));
+ RunTask(QueueType::kDefault, Seconds(2),
+ base::TimeDelta::FromMilliseconds(700));
+ RunTask(QueueType::kDefault, Seconds(3),
+ base::TimeDelta::FromMilliseconds(700));
+
+ RunTask(QueueType::kControl, Seconds(4), base::TimeDelta::FromSeconds(3));
+ RunTask(QueueType::kFrameLoading, Seconds(8),
+ base::TimeDelta::FromSeconds(6));
+ RunTask(QueueType::kFramePausable, Seconds(16),
+ base::TimeDelta::FromSeconds(2));
+ RunTask(QueueType::kCompositor, Seconds(19), base::TimeDelta::FromSeconds(2));
+ RunTask(QueueType::kTest, Seconds(22), base::TimeDelta::FromSeconds(4));
scheduler_->SetRendererBackgrounded(true);
-
- RunTask(QueueType::kControl, Milliseconds(2000),
- base::TimeDelta::FromMilliseconds(25));
- RunTask(QueueType::kFrameThrottleable, Milliseconds(2600),
- base::TimeDelta::FromMilliseconds(175));
- RunTask(QueueType::kUnthrottled, Milliseconds(2800),
- base::TimeDelta::FromMilliseconds(25));
- RunTask(QueueType::kFrameLoading, Milliseconds(3000),
- base::TimeDelta::FromMilliseconds(35));
- RunTask(QueueType::kFrameThrottleable, Milliseconds(3200),
- base::TimeDelta::FromMilliseconds(5));
- RunTask(QueueType::kCompositor, Milliseconds(3400),
- base::TimeDelta::FromMilliseconds(20));
- RunTask(QueueType::kIdle, Milliseconds(3600),
- base::TimeDelta::FromMilliseconds(50));
- RunTask(QueueType::kFrameLoadingControl, Milliseconds(4000),
- base::TimeDelta::FromMilliseconds(5));
- RunTask(QueueType::kControl, Milliseconds(4200),
- base::TimeDelta::FromMilliseconds(20));
- RunTask(QueueType::kFrameThrottleable, Milliseconds(4400),
- base::TimeDelta::FromMilliseconds(115));
- RunTask(QueueType::kFramePausable, Milliseconds(4600),
- base::TimeDelta::FromMilliseconds(175));
- RunTask(QueueType::kIdle, Milliseconds(5000),
- base::TimeDelta::FromMilliseconds(1600));
-
- RunTask(QueueType::kDetached, Milliseconds(8000),
- base::TimeDelta::FromMilliseconds(150));
+ // Wait for internally triggered tasks to run.
+ constexpr int kCoolingOfTimeSeconds = 10;
+
+ RunTask(QueueType::kControl, Seconds(26 + kCoolingOfTimeSeconds),
+ base::TimeDelta::FromSeconds(2));
+ RunTask(QueueType::kFrameThrottleable, Seconds(28 + kCoolingOfTimeSeconds),
+ base::TimeDelta::FromSeconds(8));
+ RunTask(QueueType::kUnthrottled, Seconds(38 + kCoolingOfTimeSeconds),
+ base::TimeDelta::FromSeconds(5));
+ RunTask(QueueType::kFrameLoading, Seconds(45 + kCoolingOfTimeSeconds),
+ base::TimeDelta::FromSeconds(10));
+ RunTask(QueueType::kFrameThrottleable, Seconds(60 + kCoolingOfTimeSeconds),
+ base::TimeDelta::FromSeconds(5));
+ RunTask(QueueType::kCompositor, Seconds(70 + kCoolingOfTimeSeconds),
+ base::TimeDelta::FromSeconds(20));
+ RunTask(QueueType::kIdle, Seconds(90 + kCoolingOfTimeSeconds),
+ base::TimeDelta::FromSeconds(5));
+ RunTask(QueueType::kFrameLoadingControl, Seconds(100 + kCoolingOfTimeSeconds),
+ base::TimeDelta::FromSeconds(5));
+ RunTask(QueueType::kControl, Seconds(106 + kCoolingOfTimeSeconds),
+ base::TimeDelta::FromSeconds(6));
+ RunTask(QueueType::kFrameThrottleable, Seconds(114 + kCoolingOfTimeSeconds),
+ base::TimeDelta::FromSeconds(6));
+ RunTask(QueueType::kFramePausable, Seconds(120 + kCoolingOfTimeSeconds),
+ base::TimeDelta::FromSeconds(17));
+ RunTask(QueueType::kIdle, Seconds(140 + kCoolingOfTimeSeconds),
+ base::TimeDelta::FromSeconds(15));
+
+ RunTask(QueueType::kDetached, Seconds(156 + kCoolingOfTimeSeconds),
+ base::TimeDelta::FromSeconds(2));
std::vector<base::Bucket> expected_samples = {
- {static_cast<int>(QueueType::kControl), 75},
+ {static_cast<int>(QueueType::kControl), 11},
{static_cast<int>(QueueType::kDefault), 2},
- {static_cast<int>(QueueType::kUnthrottled), 25},
- {static_cast<int>(QueueType::kFrameLoading), 105},
- {static_cast<int>(QueueType::kCompositor), 45},
- {static_cast<int>(QueueType::kIdle), 1650},
- {static_cast<int>(QueueType::kTest), 85},
+ {static_cast<int>(QueueType::kUnthrottled), 5},
+ {static_cast<int>(QueueType::kFrameLoading), 16},
+ {static_cast<int>(QueueType::kCompositor), 22},
+ {static_cast<int>(QueueType::kIdle), 20},
+ {static_cast<int>(QueueType::kTest), 4},
{static_cast<int>(QueueType::kFrameLoadingControl), 5},
- {static_cast<int>(QueueType::kFrameThrottleable), 295},
- {static_cast<int>(QueueType::kFramePausable), 195},
- {static_cast<int>(QueueType::kDetached), 150},
+ {static_cast<int>(QueueType::kFrameThrottleable), 19},
+ {static_cast<int>(QueueType::kFramePausable), 19},
+ {static_cast<int>(QueueType::kDetached), 2},
};
EXPECT_THAT(histogram_tester_->GetAllSamples(
- "RendererScheduler.TaskDurationPerQueueType2"),
+ "RendererScheduler.TaskDurationPerQueueType3"),
testing::ContainerEq(expected_samples));
EXPECT_THAT(histogram_tester_->GetAllSamples(
- "RendererScheduler.TaskDurationPerQueueType2.Foreground"),
+ "RendererScheduler.TaskDurationPerQueueType3.Foreground"),
UnorderedElementsAre(
- Bucket(static_cast<int>(QueueType::kControl), 30),
+ Bucket(static_cast<int>(QueueType::kControl), 3),
Bucket(static_cast<int>(QueueType::kDefault), 2),
- Bucket(static_cast<int>(QueueType::kFrameLoading), 70),
- Bucket(static_cast<int>(QueueType::kCompositor), 25),
- Bucket(static_cast<int>(QueueType::kTest), 85),
- Bucket(static_cast<int>(QueueType::kFramePausable), 20)));
+ Bucket(static_cast<int>(QueueType::kFrameLoading), 6),
+ Bucket(static_cast<int>(QueueType::kCompositor), 2),
+ Bucket(static_cast<int>(QueueType::kTest), 4),
+ Bucket(static_cast<int>(QueueType::kFramePausable), 2)));
EXPECT_THAT(histogram_tester_->GetAllSamples(
- "RendererScheduler.TaskDurationPerQueueType2.Background"),
+ "RendererScheduler.TaskDurationPerQueueType3.Background"),
UnorderedElementsAre(
- Bucket(static_cast<int>(QueueType::kControl), 45),
- Bucket(static_cast<int>(QueueType::kUnthrottled), 25),
- Bucket(static_cast<int>(QueueType::kFrameLoading), 35),
- Bucket(static_cast<int>(QueueType::kFrameThrottleable), 295),
- Bucket(static_cast<int>(QueueType::kFramePausable), 175),
+ Bucket(static_cast<int>(QueueType::kControl), 8),
+ Bucket(static_cast<int>(QueueType::kUnthrottled), 5),
+ Bucket(static_cast<int>(QueueType::kFrameLoading), 10),
+ Bucket(static_cast<int>(QueueType::kFrameThrottleable), 19),
+ Bucket(static_cast<int>(QueueType::kFramePausable), 17),
Bucket(static_cast<int>(QueueType::kCompositor), 20),
- Bucket(static_cast<int>(QueueType::kIdle), 1650),
+ Bucket(static_cast<int>(QueueType::kIdle), 20),
Bucket(static_cast<int>(QueueType::kFrameLoadingControl), 5),
- Bucket(static_cast<int>(QueueType::kDetached), 150)));
+ Bucket(static_cast<int>(QueueType::kDetached), 2)));
}
TEST_F(MainThreadMetricsHelperTest, Metrics_PerUseCase) {
RunTask(UseCase::kNone, Milliseconds(500),
- base::TimeDelta::FromMilliseconds(4000));
-
- RunTask(UseCase::kTouchstart, Milliseconds(7000),
- base::TimeDelta::FromMilliseconds(25));
- RunTask(UseCase::kTouchstart, Milliseconds(7050),
- base::TimeDelta::FromMilliseconds(25));
- RunTask(UseCase::kTouchstart, Milliseconds(7100),
- base::TimeDelta::FromMilliseconds(25));
-
- RunTask(UseCase::kCompositorGesture, Milliseconds(7150),
- base::TimeDelta::FromMilliseconds(5));
- RunTask(UseCase::kCompositorGesture, Milliseconds(7200),
- base::TimeDelta::FromMilliseconds(30));
-
- RunTask(UseCase::kMainThreadCustomInputHandling, Milliseconds(7300),
- base::TimeDelta::FromMilliseconds(2));
- RunTask(UseCase::kSynchronizedGesture, Milliseconds(7400),
- base::TimeDelta::FromMilliseconds(250));
- RunTask(UseCase::kMainThreadCustomInputHandling, Milliseconds(7700),
- base::TimeDelta::FromMilliseconds(150));
- RunTask(UseCase::kLoading, Milliseconds(7900),
- base::TimeDelta::FromMilliseconds(50));
- RunTask(UseCase::kMainThreadGesture, Milliseconds(8000),
- base::TimeDelta::FromMilliseconds(60));
+ base::TimeDelta::FromMilliseconds(400));
+
+ RunTask(UseCase::kTouchstart, Seconds(1), base::TimeDelta::FromSeconds(2));
+ RunTask(UseCase::kTouchstart, Seconds(3),
+ base::TimeDelta::FromMilliseconds(300));
+ RunTask(UseCase::kTouchstart, Seconds(4),
+ base::TimeDelta::FromMilliseconds(300));
+
+ RunTask(UseCase::kCompositorGesture, Seconds(5),
+ base::TimeDelta::FromSeconds(5));
+ RunTask(UseCase::kCompositorGesture, Seconds(10),
+ base::TimeDelta::FromSeconds(3));
+
+ RunTask(UseCase::kMainThreadCustomInputHandling, Seconds(14),
+ base::TimeDelta::FromSeconds(2));
+ RunTask(UseCase::kSynchronizedGesture, Seconds(17),
+ base::TimeDelta::FromSeconds(2));
+ RunTask(UseCase::kMainThreadCustomInputHandling, Seconds(19),
+ base::TimeDelta::FromSeconds(5));
+ RunTask(UseCase::kLoading, Seconds(25), base::TimeDelta::FromSeconds(6));
+ RunTask(UseCase::kMainThreadGesture, Seconds(31),
+ base::TimeDelta::FromSeconds(6));
EXPECT_THAT(
histogram_tester_->GetAllSamples(
- "RendererScheduler.TaskDurationPerUseCase"),
+ "RendererScheduler.TaskDurationPerUseCase2"),
UnorderedElementsAre(
- Bucket(static_cast<int>(UseCase::kNone), 4000),
- Bucket(static_cast<int>(UseCase::kCompositorGesture), 35),
- Bucket(static_cast<int>(UseCase::kMainThreadCustomInputHandling),
- 152),
- Bucket(static_cast<int>(UseCase::kSynchronizedGesture), 250),
- Bucket(static_cast<int>(UseCase::kTouchstart), 75),
- Bucket(static_cast<int>(UseCase::kLoading), 50),
- Bucket(static_cast<int>(UseCase::kMainThreadGesture), 60)));
+ Bucket(static_cast<int>(UseCase::kTouchstart), 3),
+ Bucket(static_cast<int>(UseCase::kCompositorGesture), 8),
+ Bucket(static_cast<int>(UseCase::kMainThreadCustomInputHandling), 7),
+ Bucket(static_cast<int>(UseCase::kSynchronizedGesture), 2),
+ Bucket(static_cast<int>(UseCase::kLoading), 6),
+ Bucket(static_cast<int>(UseCase::kMainThreadGesture), 6)));
}
TEST_F(MainThreadMetricsHelperTest, GetFrameStatusTest) {
@@ -396,81 +401,6 @@ TEST_F(MainThreadMetricsHelperTest, GetFrameStatusTest) {
}
}
-TEST_F(MainThreadMetricsHelperTest, BackgroundedRendererTransition) {
- scheduler_->SetFreezingWhenBackgroundedEnabled(true);
- typedef BackgroundedRendererTransition Transition;
-
- int backgrounding_transitions = 0;
- int foregrounding_transitions = 0;
- if (!kLaunchingProcessIsBackgrounded) {
- scheduler_->SetRendererBackgrounded(true);
- backgrounding_transitions++;
- EXPECT_THAT(
- histogram_tester_->GetAllSamples(
- "RendererScheduler.BackgroundedRendererTransition"),
- UnorderedElementsAre(Bucket(static_cast<int>(Transition::kBackgrounded),
- backgrounding_transitions)));
- scheduler_->SetRendererBackgrounded(false);
- foregrounding_transitions++;
- EXPECT_THAT(
- histogram_tester_->GetAllSamples(
- "RendererScheduler.BackgroundedRendererTransition"),
- UnorderedElementsAre(Bucket(static_cast<int>(Transition::kBackgrounded),
- backgrounding_transitions),
- Bucket(static_cast<int>(Transition::kForegrounded),
- foregrounding_transitions)));
- } else {
- scheduler_->SetRendererBackgrounded(false);
- foregrounding_transitions++;
- EXPECT_THAT(
- histogram_tester_->GetAllSamples(
- "RendererScheduler.BackgroundedRendererTransition"),
- UnorderedElementsAre(Bucket(static_cast<int>(Transition::kForegrounded),
- foregrounding_transitions)));
- }
-
- scheduler_->SetRendererBackgrounded(true);
- backgrounding_transitions++;
- EXPECT_THAT(
- histogram_tester_->GetAllSamples(
- "RendererScheduler.BackgroundedRendererTransition"),
- UnorderedElementsAre(Bucket(static_cast<int>(Transition::kBackgrounded),
- backgrounding_transitions),
- Bucket(static_cast<int>(Transition::kForegrounded),
- foregrounding_transitions)));
-
- // Waste 5+ minutes so that the delayed stop is triggered
- RunTask(QueueType::kDefault, Milliseconds(1),
- base::TimeDelta::FromSeconds(5 * 61));
- // Firing ForceUpdatePolicy multiple times to make sure that the
- // metric is only recorded upon an actual change.
- ForceUpdatePolicy();
- ForceUpdatePolicy();
- ForceUpdatePolicy();
- EXPECT_THAT(histogram_tester_->GetAllSamples(
- "RendererScheduler.BackgroundedRendererTransition"),
- UnorderedElementsAre(
- Bucket(static_cast<int>(Transition::kBackgrounded),
- backgrounding_transitions),
- Bucket(static_cast<int>(Transition::kForegrounded),
- foregrounding_transitions),
- Bucket(static_cast<int>(Transition::kFrozenAfterDelay), 1)));
-
- scheduler_->SetRendererBackgrounded(false);
- foregrounding_transitions++;
- ForceUpdatePolicy();
- ForceUpdatePolicy();
- EXPECT_THAT(histogram_tester_->GetAllSamples(
- "RendererScheduler.BackgroundedRendererTransition"),
- UnorderedElementsAre(
- Bucket(static_cast<int>(Transition::kBackgrounded),
- backgrounding_transitions),
- Bucket(static_cast<int>(Transition::kForegrounded),
- foregrounding_transitions),
- Bucket(static_cast<int>(Transition::kFrozenAfterDelay), 1),
- Bucket(static_cast<int>(Transition::kResumed), 1)));
-}
-
TEST_F(MainThreadMetricsHelperTest, TaskCountPerFrameStatus) {
int task_count = 0;
struct CountPerFrameStatus {
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.cc
index ea6584920a5..bd4d984a589 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.cc
@@ -13,10 +13,9 @@ namespace scheduler {
using base::sequence_manager::TaskQueue;
MainThreadSchedulerHelper::MainThreadSchedulerHelper(
- std::unique_ptr<base::sequence_manager::TaskQueueManager>
- task_queue_manager,
+ std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager,
MainThreadSchedulerImpl* main_thread_scheduler)
- : SchedulerHelper(std::move(task_queue_manager)),
+ : SchedulerHelper(std::move(sequence_manager)),
main_thread_scheduler_(main_thread_scheduler),
default_task_queue_(
NewTaskQueue(MainThreadTaskQueue::QueueCreationParams(
@@ -28,8 +27,8 @@ MainThreadSchedulerHelper::MainThreadSchedulerHelper(
.SetShouldNotifyObservers(false))) {
InitDefaultQueues(default_task_queue_, control_task_queue_,
TaskType::kMainThreadTaskQueueDefault);
- task_queue_manager_->EnableCrashKeys("blink_scheduler_task_file_name",
- "blink_scheduler_task_function_name");
+ sequence_manager_->EnableCrashKeys("blink_scheduler_task_file_name",
+ "blink_scheduler_task_function_name");
}
MainThreadSchedulerHelper::~MainThreadSchedulerHelper() {
@@ -58,12 +57,10 @@ scoped_refptr<TaskQueue> MainThreadSchedulerHelper::ControlTaskQueue() {
scoped_refptr<MainThreadTaskQueue> MainThreadSchedulerHelper::NewTaskQueue(
const MainThreadTaskQueue::QueueCreationParams& params) {
scoped_refptr<MainThreadTaskQueue> task_queue =
- task_queue_manager_->CreateTaskQueue<MainThreadTaskQueue>(
+ sequence_manager_->CreateTaskQueue<MainThreadTaskQueue>(
params.spec, params, main_thread_scheduler_);
if (params.fixed_priority)
task_queue->SetQueuePriority(params.fixed_priority.value());
- if (params.used_for_important_tasks)
- task_queue->SetQueuePriority(TaskQueue::QueuePriority::kHighestPriority);
return task_queue;
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.h
index 0b71b797ba9..afcaa79c166 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.h
@@ -17,8 +17,7 @@ class MainThreadSchedulerImpl;
class PLATFORM_EXPORT MainThreadSchedulerHelper : public SchedulerHelper {
public:
MainThreadSchedulerHelper(
- std::unique_ptr<base::sequence_manager::TaskQueueManager>
- task_queue_manager,
+ std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager,
MainThreadSchedulerImpl* main_thread_scheduler);
~MainThreadSchedulerHelper() override;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
index 292a82df666..970f7113daf 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -15,6 +15,7 @@
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
+#include "base/numerics/safe_conversions.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
@@ -23,21 +24,20 @@
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "third_party/blink/public/common/page/launching_process_state.h"
-#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/scheduler/renderer_process_type.h"
+#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
+#include "third_party/blink/public/platform/web_touch_event.h"
#include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/blink_resource_coordinator_base.h"
#include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/scheduler/base/real_time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h"
-#include "third_party/blink/renderer/platform/scheduler/base/virtual_time_domain.h"
#include "third_party/blink/renderer/platform/scheduler/child/features.h"
#include "third_party/blink/renderer/platform/scheduler/child/process_state.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.h"
+#include "third_party/blink/renderer/platform/wtf/text/movable_string.h"
namespace blink {
namespace scheduler {
@@ -63,14 +63,20 @@ const double kFastCompositingIdleTimeThreshold = .2;
constexpr base::TimeDelta kQueueingTimeWindowDuration =
base::TimeDelta::FromSeconds(1);
const double kSamplingRateForTaskUkm = 0.0001;
+const int64_t kSecondsPerMinute = 60;
-// Field trial name.
+// Wake-up throttling trial.
const char kWakeUpThrottlingTrial[] = "RendererSchedulerWakeUpThrottling";
const char kWakeUpDurationParam[] = "wake_up_duration_ms";
constexpr base::TimeDelta kDefaultWakeUpDuration =
base::TimeDelta::FromMilliseconds(3);
+// Name of the finch study that enables using resource fetch priorities to
+// schedule tasks on Blink.
+constexpr const char kResourceFetchPriorityExperiment[] =
+ "ResourceFetchPriorityExperiment";
+
base::TimeDelta GetWakeUpDuration() {
int duration_ms;
if (!base::StringToInt(base::GetFieldTrialParamValue(kWakeUpThrottlingTrial,
@@ -125,6 +131,8 @@ const char* TaskTypeToString(TaskType task_type) {
return "UserInteraction";
case TaskType::kNetworking:
return "Networking";
+ case TaskType::kNetworkingWithURLLoaderAnnotation:
+ return "NetworkingWithURLLoaderAnnotation";
case TaskType::kNetworkingControl:
return "NetworkingControl";
case TaskType::kHistoryTraversal:
@@ -167,8 +175,6 @@ const char* TaskTypeToString(TaskType task_type) {
return "InternalDefault";
case TaskType::kInternalLoading:
return "InternalLoading";
- case TaskType::kUnthrottled:
- return "Unthrottled";
case TaskType::kInternalTest:
return "InternalTest";
case TaskType::kInternalWebCrypto:
@@ -205,8 +211,16 @@ const char* TaskTypeToString(TaskType task_type) {
return "InternalIntersectionObserver";
case TaskType::kCompositorThreadTaskQueueDefault:
return "CompositorThreadTaskQueueDefault";
+ case TaskType::kCompositorThreadTaskQueueInput:
+ return "CompositorThreadTaskQueueInput";
case TaskType::kWorkerThreadTaskQueueDefault:
return "WorkerThreadTaskQueueDefault";
+ case TaskType::kWorkerThreadTaskQueueV8:
+ return "WorkerThreadTaskQueueV8";
+ case TaskType::kWorkerThreadTaskQueueCompositor:
+ return "WorkerThreadTaskQueueCompositor";
+ case TaskType::kWorkerAnimation:
+ return "WorkerAnimation";
case TaskType::kCount:
return "Count";
}
@@ -232,17 +246,48 @@ const char* OptionalTaskPriorityToString(
return TaskQueue::PriorityToString(priority.value());
}
-bool IsUnconditionalHighPriorityInputEnabled() {
- return base::FeatureList::IsEnabled(kHighPriorityInput);
+TaskQueue::QueuePriority StringToTaskQueuePriority(
+ const std::string& priority) {
+ if (priority == "CONTROL") {
+ return TaskQueue::QueuePriority::kControlPriority;
+ } else if (priority == "HIGHEST") {
+ return TaskQueue::QueuePriority::kHighestPriority;
+ } else if (priority == "HIGH") {
+ return TaskQueue::QueuePriority::kHighPriority;
+ } else if (priority == "NORMAL") {
+ return TaskQueue::QueuePriority::kNormalPriority;
+ } else if (priority == "LOW") {
+ return TaskQueue::QueuePriority::kLowPriority;
+ } else if (priority == "BEST_EFFORT") {
+ return TaskQueue::QueuePriority::kBestEffortPriority;
+ } else {
+ NOTREACHED();
+ return TaskQueue::QueuePriority::kQueuePriorityCount;
+ }
+}
+
+bool IsBlockingEvent(const blink::WebInputEvent& web_input_event) {
+ blink::WebInputEvent::Type type = web_input_event.GetType();
+ DCHECK(type == blink::WebInputEvent::kTouchStart ||
+ type == blink::WebInputEvent::kMouseWheel);
+
+ if (type == blink::WebInputEvent::kTouchStart) {
+ const WebTouchEvent& touch_event =
+ static_cast<const WebTouchEvent&>(web_input_event);
+ return touch_event.dispatch_type == blink::WebInputEvent::kBlocking;
+ }
+
+ const WebMouseWheelEvent& mouse_event =
+ static_cast<const WebMouseWheelEvent&>(web_input_event);
+ return mouse_event.dispatch_type == blink::WebInputEvent::kBlocking;
}
} // namespace
MainThreadSchedulerImpl::MainThreadSchedulerImpl(
- std::unique_ptr<base::sequence_manager::TaskQueueManager>
- task_queue_manager,
+ std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager,
base::Optional<base::Time> initial_virtual_time)
- : helper_(std::move(task_queue_manager), this),
+ : helper_(std::move(sequence_manager), this),
idle_helper_(&helper_,
this,
"MainThreadSchedulerIdlePeriod",
@@ -265,7 +310,7 @@ MainThreadSchedulerImpl::MainThreadSchedulerImpl(
MainThreadTaskQueue::QueueType::kInput)
.SetShouldMonitorQuiescence(true)
.SetFixedPriority(
- IsUnconditionalHighPriorityInputEnabled()
+ scheduling_settings_.high_priority_input
? base::make_optional(
TaskQueue::QueuePriority::kHighestPriority)
: base::nullopt))),
@@ -286,15 +331,8 @@ MainThreadSchedulerImpl::MainThreadSchedulerImpl(
any_thread_(this),
policy_may_need_update_(&any_thread_lock_),
weak_factory_(this) {
- task_queue_throttler_.reset(
- new TaskQueueThrottler(this, &tracing_controller_));
- update_policy_closure_ = base::BindRepeating(
- &MainThreadSchedulerImpl::UpdatePolicy, weak_factory_.GetWeakPtr());
- end_renderer_hidden_idle_period_closure_.Reset(base::BindRepeating(
- &MainThreadSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr()));
-
// Compositor task queue and default task queue should be managed by
- // WebMainThreadScheduler. Control task queue should not.
+ // WebThreadScheduler. Control task queue should not.
task_runners_.insert(
std::make_pair(helper_.DefaultMainThreadTaskQueue(), nullptr));
task_runners_.insert(
@@ -312,6 +350,22 @@ MainThreadSchedulerImpl::MainThreadSchedulerImpl(
v8_task_queue_, TaskType::kMainThreadTaskQueueV8);
compositor_task_runner_ = TaskQueueWithTaskType::Create(
compositor_task_queue_, TaskType::kMainThreadTaskQueueCompositor);
+ control_task_runner_ =
+ TaskQueueWithTaskType::Create(helper_.ControlMainThreadTaskQueue(),
+ TaskType::kMainThreadTaskQueueControl);
+ input_task_runner_ = TaskQueueWithTaskType::Create(
+ input_task_queue_, TaskType::kMainThreadTaskQueueInput);
+ ipc_task_runner_ = TaskQueueWithTaskType::Create(
+ ipc_task_queue_, TaskType::kMainThreadTaskQueueIPC);
+
+ // TaskQueueThrottler requires some task runners, then initialize
+ // TaskQueueThrottler after task queues/runners are initialized.
+ task_queue_throttler_.reset(
+ new TaskQueueThrottler(this, &tracing_controller_));
+ update_policy_closure_ = base::BindRepeating(
+ &MainThreadSchedulerImpl::UpdatePolicy, weak_factory_.GetWeakPtr());
+ end_renderer_hidden_idle_period_closure_.Reset(base::BindRepeating(
+ &MainThreadSchedulerImpl::EndIdlePeriod, weak_factory_.GetWeakPtr()));
TRACE_EVENT_OBJECT_CREATED_WITH_ID(
TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"), "MainThreadScheduler",
@@ -326,17 +380,6 @@ MainThreadSchedulerImpl::MainThreadSchedulerImpl(
weak_factory_.GetWeakPtr());
}
- int32_t delay_for_background_tab_freezing_millis;
- if (!base::StringToInt(
- base::GetFieldTrialParamValue("BackgroundTabFreezing",
- "DelayForBackgroundTabFreezingMills"),
- &delay_for_background_tab_freezing_millis)) {
- delay_for_background_tab_freezing_millis =
- kDelayForBackgroundTabFreezingMillis;
- }
- delay_for_background_tab_freezing_ = base::TimeDelta::FromMilliseconds(
- delay_for_background_tab_freezing_millis);
-
internal::ProcessState::Get()->is_process_backgrounded =
main_thread_only().renderer_backgrounded;
@@ -446,17 +489,6 @@ MainThreadSchedulerImpl::MainThreadOnly::MainThreadOnly(
main_thread_scheduler_impl,
&main_thread_scheduler_impl->tracing_controller_,
YesNoStateToString),
- freezing_when_backgrounded_enabled(
- false,
- "MainThreadScheduler.FreezingWhenBackgroundedEnabled",
- main_thread_scheduler_impl,
- &main_thread_scheduler_impl->tracing_controller_,
- YesNoStateToString),
- frozen_when_backgrounded(false,
- "MainThreadScheduler.FrozenWhenBackgrounded",
- main_thread_scheduler_impl,
- &main_thread_scheduler_impl->tracing_controller_,
- YesNoStateToString),
loading_task_estimated_cost(
base::TimeDelta(),
"Scheduler.LoadingTaskEstimatedCostMs",
@@ -481,11 +513,12 @@ MainThreadSchedulerImpl::MainThreadOnly::MainThreadOnly(
main_thread_scheduler_impl,
&main_thread_scheduler_impl->tracing_controller_,
YesNoStateToString),
- touchstart_expected_soon(false,
- "Scheduler.TouchstartExpectedSoon",
- main_thread_scheduler_impl,
- &main_thread_scheduler_impl->tracing_controller_,
- YesNoStateToString),
+ blocking_input_expected_soon(
+ false,
+ "Scheduler.BlockingInputExpectedSoon",
+ main_thread_scheduler_impl,
+ &main_thread_scheduler_impl->tracing_controller_,
+ YesNoStateToString),
have_seen_a_begin_main_frame(
false,
"Scheduler.HasSeenBeginMainFrame",
@@ -549,9 +582,12 @@ MainThreadSchedulerImpl::MainThreadOnly::MainThreadOnly(
&main_thread_scheduler_impl->tracing_controller_,
YesNoStateToString),
background_status_changed_at(now),
- rail_mode_observer(nullptr),
wake_up_budget_pool(nullptr),
- metrics_helper(main_thread_scheduler_impl, now, renderer_backgrounded),
+ metrics_helper(
+ main_thread_scheduler_impl,
+ main_thread_scheduler_impl->helper_.HasCPUTimingForEachTask(),
+ now,
+ renderer_backgrounded),
process_type(RendererProcessType::kRenderer,
"RendererProcessType",
main_thread_scheduler_impl,
@@ -574,7 +610,9 @@ MainThreadSchedulerImpl::MainThreadOnly::MainThreadOnly(
max_virtual_time_task_starvation_count(0),
virtual_time_stopped(false),
nested_runloop(false),
- uniform_distribution(0.0f, 1.0f) {}
+ uniform_distribution(0.0f, 1.0f),
+ compositing_experiment(main_thread_scheduler_impl),
+ should_prioritize_compositing(false) {}
MainThreadSchedulerImpl::MainThreadOnly::~MainThreadOnly() = default;
@@ -609,9 +647,9 @@ MainThreadSchedulerImpl::AnyThread::AnyThread(
main_thread_scheduler_impl,
&main_thread_scheduler_impl->tracing_controller_,
YesNoStateToString),
- have_seen_a_potentially_blocking_gesture(
+ have_seen_a_blocking_gesture(
false,
- "Scheduler.HaveSeenPotentiallyBlockingGesture",
+ "Scheduler.HaveSeenBlockingGesture",
main_thread_scheduler_impl,
&main_thread_scheduler_impl->tracing_controller_,
YesNoStateToString),
@@ -628,6 +666,60 @@ MainThreadSchedulerImpl::AnyThread::AnyThread(
&main_thread_scheduler_impl->tracing_controller_,
YesNoStateToString) {}
+MainThreadSchedulerImpl::SchedulingSettings::SchedulingSettings() {
+ high_priority_input =
+ base::FeatureList::IsEnabled(kHighPriorityInputOnMainThread);
+
+ low_priority_background_page =
+ base::FeatureList::IsEnabled(kLowPriorityForBackgroundPages);
+ best_effort_background_page =
+ base::FeatureList::IsEnabled(kBestEffortPriorityForBackgroundPages);
+
+ low_priority_hidden_frame =
+ base::FeatureList::IsEnabled(kLowPriorityForHiddenFrame);
+ low_priority_subframe = base::FeatureList::IsEnabled(kLowPriorityForSubFrame);
+ low_priority_throttleable =
+ base::FeatureList::IsEnabled(kLowPriorityForThrottleableTask);
+ low_priority_subframe_throttleable =
+ base::FeatureList::IsEnabled(kLowPriorityForSubFrameThrottleableTask);
+ use_frame_priorities_only_during_loading =
+ base::FeatureList::IsEnabled(kFrameExperimentOnlyWhenLoading);
+
+ low_priority_ad_frame = base::FeatureList::IsEnabled(kLowPriorityForAdFrame);
+ best_effort_ad_frame =
+ base::FeatureList::IsEnabled(kBestEffortPriorityForAdFrame);
+ use_adframe_priorities_only_during_loading =
+ base::FeatureList::IsEnabled(kAdFrameExperimentOnlyWhenLoading);
+
+ low_priority_cross_origin =
+ base::FeatureList::IsEnabled(kLowPriorityForCrossOrigin);
+ low_priority_cross_origin_only_during_loading =
+ base::FeatureList::IsEnabled(kLowPriorityForCrossOriginOnlyWhenLoading);
+
+ use_resource_fetch_priority =
+ base::FeatureList::IsEnabled(kUseResourceFetchPriority);
+ use_resource_priorities_only_during_loading =
+ base::FeatureList::IsEnabled(kUseResourceFetchPriorityOnlyWhenLoading);
+
+ if (use_resource_fetch_priority ||
+ use_resource_priorities_only_during_loading) {
+ std::map<std::string, std::string> params;
+ base::GetFieldTrialParams(kResourceFetchPriorityExperiment, &params);
+ for (size_t net_priority = 0;
+ net_priority < net::RequestPrioritySize::NUM_PRIORITIES;
+ net_priority++) {
+ net_to_blink_priority[net_priority] =
+ TaskQueue::QueuePriority::kNormalPriority;
+ auto iter = params.find(net::RequestPriorityToString(
+ static_cast<net::RequestPriority>(net_priority)));
+ if (iter != params.end()) {
+ net_to_blink_priority[net_priority] =
+ StringToTaskQueuePriority(iter->second);
+ }
+ }
+ }
+}
+
MainThreadSchedulerImpl::AnyThread::~AnyThread() = default;
MainThreadSchedulerImpl::CompositorThreadOnly::CompositorThreadOnly()
@@ -656,7 +748,7 @@ void MainThreadSchedulerImpl::Shutdown() {
task_queue_throttler_.reset();
idle_helper_.Shutdown();
helper_.Shutdown();
- main_thread_only().rail_mode_observer = nullptr;
+ main_thread_only().rail_mode_observers.Clear();
was_shutdown_ = true;
}
@@ -666,21 +758,18 @@ std::unique_ptr<blink::WebThread> MainThreadSchedulerImpl::CreateMainThread() {
scoped_refptr<base::SingleThreadTaskRunner>
MainThreadSchedulerImpl::ControlTaskRunner() {
- return TaskQueueWithTaskType::Create(ControlTaskQueue(),
- TaskType::kMainThreadTaskQueueControl);
+ return control_task_runner_;
}
scoped_refptr<base::SingleThreadTaskRunner>
MainThreadSchedulerImpl::DefaultTaskRunner() {
- return TaskQueueWithTaskType::Create(helper_.DefaultMainThreadTaskQueue(),
- TaskType::kMainThreadTaskQueueDefault);
+ return helper_.DefaultTaskRunner();
}
scoped_refptr<base::SingleThreadTaskRunner>
MainThreadSchedulerImpl::InputTaskRunner() {
helper_.CheckOnValidThread();
- return TaskQueueWithTaskType::Create(input_task_queue_,
- TaskType::kMainThreadTaskQueueInput);
+ return input_task_runner_;
}
scoped_refptr<SingleThreadIdleTaskRunner>
@@ -690,8 +779,7 @@ MainThreadSchedulerImpl::IdleTaskRunner() {
scoped_refptr<base::SingleThreadTaskRunner>
MainThreadSchedulerImpl::IPCTaskRunner() {
- return TaskQueueWithTaskType::Create(ipc_task_queue_,
- TaskType::kMainThreadTaskQueueIPC);
+ return ipc_task_runner_;
}
scoped_refptr<base::SingleThreadTaskRunner>
@@ -735,8 +823,10 @@ scoped_refptr<MainThreadTaskQueue> MainThreadSchedulerImpl::NewTaskQueue(
scoped_refptr<MainThreadTaskQueue> task_queue(helper_.NewTaskQueue(params));
std::unique_ptr<TaskQueue::QueueEnabledVoter> voter;
- if (params.can_be_deferred || params.can_be_paused || params.can_be_frozen)
+ if (params.queue_traits.can_be_deferred ||
+ params.queue_traits.can_be_paused || params.queue_traits.can_be_frozen) {
voter = task_queue->CreateQueueEnabledVoter();
+ }
auto insert_result =
task_runners_.insert(std::make_pair(task_queue, std::move(voter)));
@@ -752,6 +842,8 @@ scoped_refptr<MainThreadTaskQueue> MainThreadSchedulerImpl::NewTaskQueue(
task_queue.get(), insert_result.first->second.get(), TaskQueuePolicy(),
main_thread_only().current_policy.GetQueuePolicy(queue_class));
+ task_queue->SetQueuePriority(ComputePriority(task_queue.get()));
+
if (task_queue->CanBeThrottled())
AddQueueToWakeUpBudgetPool(task_queue.get());
@@ -772,16 +864,11 @@ scoped_refptr<MainThreadTaskQueue> MainThreadSchedulerImpl::NewLoadingTaskQueue(
FrameSchedulerImpl* frame_scheduler) {
DCHECK_EQ(MainThreadTaskQueue::QueueClassForQueueType(queue_type),
MainThreadTaskQueue::QueueClass::kLoading);
- return NewTaskQueue(
- MainThreadTaskQueue::QueueCreationParams(queue_type)
- .SetCanBePaused(true)
- .SetCanBeFrozen(
- RuntimeEnabledFeatures::StopLoadingInBackgroundEnabled())
- .SetCanBeDeferred(true)
- .SetUsedForImportantTasks(
- queue_type ==
- MainThreadTaskQueue::QueueType::kFrameLoadingControl)
- .SetFrameScheduler(frame_scheduler));
+ return NewTaskQueue(MainThreadTaskQueue::QueueCreationParams(queue_type)
+ .SetCanBePaused(true)
+ .SetCanBeFrozen(true)
+ .SetCanBeDeferred(true)
+ .SetFrameScheduler(frame_scheduler));
}
scoped_refptr<MainThreadTaskQueue> MainThreadSchedulerImpl::NewTimerTaskQueue(
@@ -858,6 +945,7 @@ void MainThreadSchedulerImpl::WillBeginFrame(const viz::BeginFrameArgs& args) {
base::AutoLock lock(any_thread_lock_);
any_thread().begin_main_frame_on_critical_path = args.on_critical_path;
}
+ main_thread_only().compositing_experiment.OnWillBeginMainFrame();
}
void MainThreadSchedulerImpl::DidCommitFrameToCompositor() {
@@ -982,13 +1070,9 @@ void MainThreadSchedulerImpl::SetRendererBackgrounded(bool backgrounded) {
if (backgrounded) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
"MainThreadSchedulerImpl::OnRendererBackgrounded");
- MainThreadMetricsHelper::RecordBackgroundedTransition(
- BackgroundedRendererTransition::kBackgrounded);
} else {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
"MainThreadSchedulerImpl::OnRendererForegrounded");
- MainThreadMetricsHelper::RecordBackgroundedTransition(
- BackgroundedRendererTransition::kForegrounded);
}
main_thread_only().renderer_backgrounded = backgrounded;
@@ -1006,6 +1090,15 @@ void MainThreadSchedulerImpl::SetRendererBackgrounded(bool backgrounded) {
} else {
main_thread_only().metrics_helper.OnRendererForegrounded(now);
}
+
+ auto& movable_string_table = MovableStringTable::Instance();
+ movable_string_table.SetRendererBackgrounded(backgrounded);
+ if (backgrounded) {
+ DefaultTaskRunner()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce([]() { MovableStringTable::Instance().MaybeParkAll(); }),
+ base::TimeDelta::FromSeconds(10));
+ }
}
void MainThreadSchedulerImpl::SetSchedulerKeepActive(bool keep_active) {
@@ -1015,6 +1108,10 @@ void MainThreadSchedulerImpl::SetSchedulerKeepActive(bool keep_active) {
}
}
+void MainThreadSchedulerImpl::OnMainFrameRequestedForInput() {
+ main_thread_only().compositing_experiment.OnMainFrameRequestedForInput();
+}
+
bool MainThreadSchedulerImpl::SchedulerKeepActive() {
return main_thread_only().keep_active_fetch_or_worker;
}
@@ -1087,6 +1184,12 @@ bool MainThreadSchedulerImpl::PolicyNeedsUpdateForTesting() {
return policy_may_need_update_.IsSet();
}
+void MainThreadSchedulerImpl::SetHaveSeenABlockingGestureForTesting(
+ bool status) {
+ base::AutoLock lock(any_thread_lock_);
+ any_thread().have_seen_a_blocking_gesture = status;
+}
+
// static
bool MainThreadSchedulerImpl::ShouldPrioritizeInputEvent(
const blink::WebInputEvent& web_input_event) {
@@ -1119,7 +1222,7 @@ void MainThreadSchedulerImpl::DidHandleInputEventOnCompositorThread(
if (!ShouldPrioritizeInputEvent(web_input_event))
return;
- UpdateForInputEventOnCompositorThread(web_input_event.GetType(), event_state);
+ UpdateForInputEventOnCompositorThread(web_input_event, event_state);
}
void MainThreadSchedulerImpl::DidAnimateForInputOnCompositorThread() {
@@ -1132,11 +1235,13 @@ void MainThreadSchedulerImpl::DidAnimateForInputOnCompositorThread() {
}
void MainThreadSchedulerImpl::UpdateForInputEventOnCompositorThread(
- blink::WebInputEvent::Type type,
+ const blink::WebInputEvent& web_input_event,
InputEventState input_event_state) {
base::AutoLock lock(any_thread_lock_);
base::TimeTicks now = helper_.NowTicks();
+ blink::WebInputEvent::Type type = web_input_event.GetType();
+
// TODO(alexclarke): Move WebInputEventTraits where we can access it from here
// and record the name rather than the integer representation.
TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
@@ -1163,12 +1268,13 @@ void MainThreadSchedulerImpl::UpdateForInputEventOnCompositorThread(
// |last_gesture_was_compositor_driven| to the default. We don't know
// yet where the gesture will run.
any_thread().last_gesture_was_compositor_driven = false;
- any_thread().have_seen_a_potentially_blocking_gesture = true;
// Assume the default gesture is prevented until we see evidence
// otherwise.
any_thread().default_gesture_prevented = true;
- break;
+ if (IsBlockingEvent(web_input_event))
+ any_thread().have_seen_a_blocking_gesture = true;
+ break;
case blink::WebInputEvent::kTouchMove:
// Observation of consecutive touchmoves is a strong signal that the
// page is consuming the touch sequence, in which case touchstart
@@ -1221,13 +1327,13 @@ void MainThreadSchedulerImpl::UpdateForInputEventOnCompositorThread(
any_thread().last_gesture_was_compositor_driven =
input_event_state == InputEventState::EVENT_CONSUMED_BY_COMPOSITOR;
any_thread().awaiting_touch_start_response = false;
- any_thread().have_seen_a_potentially_blocking_gesture = true;
// If the event was sent to the main thread, assume the default gesture is
// prevented until we see evidence otherwise.
any_thread().default_gesture_prevented =
!any_thread().last_gesture_was_compositor_driven;
+ if (IsBlockingEvent(web_input_event))
+ any_thread().have_seen_a_blocking_gesture = true;
break;
-
case blink::WebInputEvent::kUndefined:
break;
@@ -1279,7 +1385,7 @@ bool MainThreadSchedulerImpl::IsHighPriorityWorkAnticipated() {
// The touchstart, synchronized gesture and main-thread gesture use cases
// indicate a strong likelihood of high-priority work in the near future.
UseCase use_case = main_thread_only().current_use_case;
- return main_thread_only().touchstart_expected_soon ||
+ return main_thread_only().blocking_input_expected_soon ||
use_case == UseCase::kTouchstart ||
use_case == UseCase::kMainThreadGesture ||
use_case == UseCase::kMainThreadCustomInputHandling ||
@@ -1300,13 +1406,13 @@ bool MainThreadSchedulerImpl::ShouldYieldForHighPriorityWork() {
switch (main_thread_only().current_use_case) {
case UseCase::kCompositorGesture:
case UseCase::kNone:
- return main_thread_only().touchstart_expected_soon;
+ return main_thread_only().blocking_input_expected_soon;
case UseCase::kMainThreadGesture:
case UseCase::kMainThreadCustomInputHandling:
case UseCase::kSynchronizedGesture:
return compositor_task_queue_->HasTaskToRunImmediately() ||
- main_thread_only().touchstart_expected_soon;
+ main_thread_only().blocking_input_expected_soon;
case UseCase::kTouchstart:
return true;
@@ -1363,24 +1469,6 @@ void MainThreadSchedulerImpl::ForceUpdatePolicy() {
UpdatePolicyLocked(UpdateType::kForceUpdate);
}
-namespace {
-
-void UpdatePolicyDuration(base::TimeTicks now,
- base::TimeTicks policy_expiration,
- base::TimeDelta* policy_duration) {
- if (policy_expiration <= now)
- return;
-
- if (policy_duration->is_zero()) {
- *policy_duration = policy_expiration - now;
- return;
- }
-
- *policy_duration = std::min(*policy_duration, policy_expiration - now);
-}
-
-} // namespace
-
void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
helper_.CheckOnValidThread();
any_thread_lock_.AssertAcquired();
@@ -1391,18 +1479,17 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
policy_may_need_update_.SetWhileLocked(false);
base::TimeDelta expected_use_case_duration;
- UseCase use_case = ComputeCurrentUseCase(now, &expected_use_case_duration);
- main_thread_only().current_use_case = use_case;
+ main_thread_only().current_use_case =
+ ComputeCurrentUseCase(now, &expected_use_case_duration);
+
+ base::TimeDelta gesture_expected_flag_valid_for_duration;
- base::TimeDelta touchstart_expected_flag_valid_for_duration;
- // TODO(skyostil): Consider handlers for all types of blocking gestures (e.g.,
- // mouse wheel) instead of just touchstart.
- bool touchstart_expected_soon = false;
- if (main_thread_only().has_visible_render_widget_with_touch_handler) {
- touchstart_expected_soon = any_thread().user_model.IsGestureExpectedSoon(
- now, &touchstart_expected_flag_valid_for_duration);
+ main_thread_only().blocking_input_expected_soon = false;
+ if (any_thread().have_seen_a_blocking_gesture) {
+ main_thread_only().blocking_input_expected_soon =
+ any_thread().user_model.IsGestureExpectedSoon(
+ now, &gesture_expected_flag_valid_for_duration);
}
- main_thread_only().touchstart_expected_soon = touchstart_expected_soon;
base::TimeDelta longest_jank_free_task_duration =
EstimateLongestJankFreeTaskDuration();
@@ -1426,31 +1513,13 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
loading_tasks_seem_expensive;
// The |new_policy_duration| is the minimum of |expected_use_case_duration|
- // and |touchstart_expected_flag_valid_for_duration| unless one is zero in
+ // and |gesture_expected_flag_valid_for_duration| unless one is zero in
// which case we choose the other.
base::TimeDelta new_policy_duration = expected_use_case_duration;
if (new_policy_duration.is_zero() ||
- (touchstart_expected_flag_valid_for_duration > base::TimeDelta() &&
- new_policy_duration > touchstart_expected_flag_valid_for_duration)) {
- new_policy_duration = touchstart_expected_flag_valid_for_duration;
- }
-
- bool previously_frozen_when_backgrounded =
- main_thread_only().frozen_when_backgrounded;
- bool newly_frozen = false;
- if (main_thread_only().renderer_backgrounded &&
- main_thread_only().freezing_when_backgrounded_enabled) {
- base::TimeTicks stop_at = main_thread_only().background_status_changed_at +
- delay_for_background_tab_freezing_;
-
- newly_frozen = !main_thread_only().frozen_when_backgrounded;
- main_thread_only().frozen_when_backgrounded = now >= stop_at;
- newly_frozen &= main_thread_only().frozen_when_backgrounded;
-
- if (!main_thread_only().frozen_when_backgrounded)
- UpdatePolicyDuration(now, stop_at, &new_policy_duration);
- } else {
- main_thread_only().frozen_when_backgrounded = false;
+ (gesture_expected_flag_valid_for_duration > base::TimeDelta() &&
+ new_policy_duration > gesture_expected_flag_valid_for_duration)) {
+ new_policy_duration = gesture_expected_flag_valid_for_duration;
}
if (new_policy_duration > base::TimeDelta()) {
@@ -1473,28 +1542,30 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
Policy new_policy;
ExpensiveTaskPolicy expensive_task_policy = ExpensiveTaskPolicy::kRun;
new_policy.rail_mode() = v8::PERFORMANCE_ANIMATION;
+ new_policy.use_case() = main_thread_only().current_use_case;
- switch (use_case) {
+ switch (new_policy.use_case()) {
case UseCase::kCompositorGesture:
- if (touchstart_expected_soon) {
+ if (main_thread_only().blocking_input_expected_soon) {
new_policy.rail_mode() = v8::PERFORMANCE_RESPONSE;
expensive_task_policy = ExpensiveTaskPolicy::kBlock;
- new_policy.compositor_queue_policy().priority =
- TaskQueue::kHighestPriority;
+ new_policy.compositor_priority() =
+ TaskQueue::QueuePriority::kHighestPriority;
} else {
// What we really want to do is priorize loading tasks, but that doesn't
// seem to be safe. Instead we do that by proxy by deprioritizing
// compositor tasks. This should be safe since we've already gone to the
// pain of fixing ordering issues with them.
- new_policy.compositor_queue_policy().priority = TaskQueue::kLowPriority;
+ new_policy.compositor_priority() =
+ TaskQueue::QueuePriority::kLowPriority;
}
break;
case UseCase::kSynchronizedGesture:
- new_policy.compositor_queue_policy().priority =
- main_thread_compositing_is_fast ? TaskQueue::kHighestPriority
- : TaskQueue::kNormalPriority;
- if (touchstart_expected_soon) {
+ new_policy.compositor_priority() = main_thread_compositing_is_fast
+ ? TaskQueue::kHighestPriority
+ : TaskQueue::kNormalPriority;
+ if (main_thread_only().blocking_input_expected_soon) {
new_policy.rail_mode() = v8::PERFORMANCE_RESPONSE;
expensive_task_policy = ExpensiveTaskPolicy::kBlock;
} else {
@@ -1507,9 +1578,10 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
// about which things we should be prioritizing, so we don't attempt to
// block expensive tasks because we don't know whether they were integral
// to the page's functionality or not.
- new_policy.compositor_queue_policy().priority =
- main_thread_compositing_is_fast ? TaskQueue::kHighestPriority
- : TaskQueue::kNormalPriority;
+ new_policy.compositor_priority() =
+ main_thread_compositing_is_fast
+ ? TaskQueue::QueuePriority::kHighestPriority
+ : TaskQueue::QueuePriority::kNormalPriority;
break;
case UseCase::kMainThreadGesture:
@@ -1517,9 +1589,9 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
// by the main thread. Since we know the established gesture type, we can
// be a little more aggressive about prioritizing compositing and input
// handling over other tasks.
- new_policy.compositor_queue_policy().priority =
- TaskQueue::kHighestPriority;
- if (touchstart_expected_soon) {
+ new_policy.compositor_priority() =
+ TaskQueue::QueuePriority::kHighestPriority;
+ if (main_thread_only().blocking_input_expected_soon) {
new_policy.rail_mode() = v8::PERFORMANCE_RESPONSE;
expensive_task_policy = ExpensiveTaskPolicy::kBlock;
} else {
@@ -1528,11 +1600,11 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
break;
case UseCase::kTouchstart:
+ new_policy.compositor_priority() =
+ TaskQueue::QueuePriority::kHighestPriority;
new_policy.rail_mode() = v8::PERFORMANCE_RESPONSE;
- new_policy.compositor_queue_policy().priority =
- TaskQueue::kHighestPriority;
- new_policy.loading_queue_policy().is_blocked = true;
- new_policy.timer_queue_policy().is_blocked = true;
+ new_policy.loading_queue_policy().is_deferred = true;
+ new_policy.timer_queue_policy().is_deferred = true;
// NOTE this is a nop due to the above.
expensive_task_policy = ExpensiveTaskPolicy::kBlock;
break;
@@ -1540,7 +1612,7 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
case UseCase::kNone:
// It's only safe to block tasks that if we are expecting a compositor
// driven gesture.
- if (touchstart_expected_soon &&
+ if (main_thread_only().blocking_input_expected_soon &&
any_thread().last_gesture_was_compositor_driven) {
new_policy.rail_mode() = v8::PERFORMANCE_RESPONSE;
expensive_task_policy = ExpensiveTaskPolicy::kBlock;
@@ -1572,9 +1644,9 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
case ExpensiveTaskPolicy::kBlock:
if (loading_tasks_seem_expensive)
- new_policy.loading_queue_policy().is_blocked = true;
+ new_policy.loading_queue_policy().is_deferred = true;
if (timer_tasks_seem_expensive)
- new_policy.timer_queue_policy().is_blocked = true;
+ new_policy.timer_queue_policy().is_deferred = true;
break;
case ExpensiveTaskPolicy::kThrottle:
@@ -1588,12 +1660,6 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
}
main_thread_only().expensive_task_policy = expensive_task_policy;
- if (main_thread_only().frozen_when_backgrounded) {
- // TODO(panicker): Remove this, as it is controlled at
- // FrameScheduler. This is currently needed to avoid early out.
- new_policy.timer_queue_policy().is_frozen = true;
- }
-
if (main_thread_only().renderer_pause_count != 0) {
new_policy.loading_queue_policy().is_paused = true;
new_policy.timer_queue_policy().is_paused = true;
@@ -1616,6 +1682,12 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
new_policy.should_disable_throttling() = main_thread_only().use_virtual_time;
+ if (main_thread_only().should_prioritize_compositing) {
+ new_policy.compositor_priority() =
+ main_thread_only()
+ .compositing_experiment.GetIncreasedCompositingPriority();
+ }
+
// Tracing is done before the early out check, because it's quite possible we
// will otherwise miss this information in traces.
CreateTraceEventObjectSnapshotLocked();
@@ -1636,22 +1708,9 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
}
main_thread_only().rail_mode_for_tracing = new_policy.rail_mode();
- if (main_thread_only().rail_mode_observer &&
- new_policy.rail_mode() != main_thread_only().current_policy.rail_mode()) {
- main_thread_only().rail_mode_observer->OnRAILModeChanged(
- new_policy.rail_mode());
- }
-
- // TODO(skyostil): send these notifications after releasing the scheduler
- // lock.
- if (main_thread_only().freezing_when_backgrounded_enabled) {
- if (main_thread_only().frozen_when_backgrounded !=
- previously_frozen_when_backgrounded) {
- SetFrozenInBackground(main_thread_only().frozen_when_backgrounded);
- MainThreadMetricsHelper::RecordBackgroundedTransition(
- main_thread_only().frozen_when_backgrounded
- ? BackgroundedRendererTransition::kFrozenAfterDelay
- : BackgroundedRendererTransition::kResumed);
+ if (new_policy.rail_mode() != main_thread_only().current_policy.rail_mode()) {
+ for (auto& observer : main_thread_only().rail_mode_observers) {
+ observer.OnRAILModeChanged(new_policy.rail_mode());
}
}
@@ -1665,10 +1724,16 @@ void MainThreadSchedulerImpl::UpdatePolicyLocked(UpdateType update_type) {
}
DCHECK(compositor_task_queue_->IsQueueEnabled());
+
+ Policy old_policy = main_thread_only().current_policy;
main_thread_only().current_policy = new_policy;
- if (newly_frozen)
- Platform::Current()->RequestPurgeMemory();
+ if (ShouldUpdateTaskQueuePriorities(old_policy)) {
+ for (const auto& pair : task_runners_) {
+ MainThreadTaskQueue* task_queue = pair.first.get();
+ task_queue->SetQueuePriority(ComputePriority(task_queue));
+ }
+ }
}
void MainThreadSchedulerImpl::ApplyTaskQueuePolicy(
@@ -1687,8 +1752,6 @@ void MainThreadSchedulerImpl::ApplyTaskQueuePolicy(
DCHECK(task_queue_enabled_voter ||
old_task_queue_policy.IsQueueEnabled(task_queue));
- task_queue->SetQueuePriority(new_task_queue_policy.GetPriority(task_queue));
-
TimeDomainType old_time_domain_type =
old_task_queue_policy.GetTimeDomainType(task_queue);
TimeDomainType new_time_domain_type =
@@ -1803,13 +1866,6 @@ bool MainThreadSchedulerImpl::CanEnterLongIdlePeriod(
return true;
}
-void MainThreadSchedulerImpl::SetFrozenInBackground(bool frozen) const {
- for (PageSchedulerImpl* page_scheduler : main_thread_only().page_schedulers) {
- // This moves the page to FROZEN lifecycle state.
- page_scheduler->SetPageFrozen(frozen);
- }
-}
-
MainThreadSchedulerHelper*
MainThreadSchedulerImpl::GetSchedulerHelperForTesting() {
return &helper_;
@@ -2048,11 +2104,6 @@ void MainThreadSchedulerImpl::SetMaxVirtualTimeTaskStarvationCount(
ApplyVirtualTimePolicy();
}
-void MainThreadSchedulerImpl::SetFreezingWhenBackgroundedEnabled(bool enabled) {
- // Note that this will only take effect for the next backgrounded signal.
- main_thread_only().freezing_when_backgrounded_enabled = enabled;
-}
-
std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
MainThreadSchedulerImpl::AsValue(base::TimeTicks optional_now) const {
base::AutoLock lock(any_thread_lock_);
@@ -2110,8 +2161,8 @@ MainThreadSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const {
state->SetBoolean(
"compositor_will_send_main_frame_not_expected",
main_thread_only().compositor_will_send_main_frame_not_expected);
- state->SetBoolean("touchstart_expected_soon",
- main_thread_only().touchstart_expected_soon);
+ state->SetBoolean("blocking_input_expected_soon",
+ main_thread_only().blocking_input_expected_soon);
state->SetString("idle_period_state",
IdleHelper::IdlePeriodStateToString(
idle_helper_.SchedulerIdlePeriodState()));
@@ -2132,8 +2183,6 @@ MainThreadSchedulerImpl::AsValueLocked(base::TimeTicks optional_now) const {
main_thread_only().renderer_backgrounded);
state->SetBoolean("keep_active_fetch_or_worker",
main_thread_only().keep_active_fetch_or_worker);
- state->SetBoolean("frozen_when_backgrounded",
- main_thread_only().frozen_when_backgrounded);
state->SetDouble("now", (optional_now - base::TimeTicks()).InMillisecondsF());
state->SetDouble(
"fling_compositor_escalation_deadline",
@@ -2213,25 +2262,11 @@ bool MainThreadSchedulerImpl::TaskQueuePolicy::IsQueueEnabled(
return false;
if (is_paused && task_queue->CanBePaused())
return false;
- if (is_blocked && task_queue->CanBeDeferred())
- return false;
- // TODO(panicker): Remove this, as it is redundant as we stop per-frame
- // task_queues in WebFrameScheduler
- if (is_frozen && task_queue->CanBeFrozen())
+ if (is_deferred && task_queue->CanBeDeferred())
return false;
return true;
}
-TaskQueue::QueuePriority MainThreadSchedulerImpl::TaskQueuePolicy::GetPriority(
- MainThreadTaskQueue* task_queue) const {
- base::Optional<TaskQueue::QueuePriority> fixed_priority =
- task_queue->FixedPriority();
- if (fixed_priority)
- return fixed_priority.value();
- return task_queue->UsedForImportantTasks() ? TaskQueue::kHighestPriority
- : priority;
-}
-
MainThreadSchedulerImpl::TimeDomainType
MainThreadSchedulerImpl::TaskQueuePolicy::GetTimeDomainType(
MainThreadTaskQueue* task_queue) const {
@@ -2247,10 +2282,8 @@ void MainThreadSchedulerImpl::TaskQueuePolicy::AsValueInto(
state->SetBoolean("is_enabled", is_enabled);
state->SetBoolean("is_paused", is_paused);
state->SetBoolean("is_throttled", is_throttled);
- state->SetBoolean("is_blocked", is_blocked);
- state->SetBoolean("is_frozen", is_frozen);
+ state->SetBoolean("is_deferred", is_deferred);
state->SetBoolean("use_virtual_time", use_virtual_time);
- state->SetString("priority", TaskQueue::PriorityToString(priority));
}
void MainThreadSchedulerImpl::Policy::AsValueInto(
@@ -2272,6 +2305,10 @@ void MainThreadSchedulerImpl::Policy::AsValueInto(
state->EndDictionary();
state->SetString("rail_mode", RAILModeToString(rail_mode()));
+ state->SetString("compositor_priority",
+ TaskQueue::PriorityToString(compositor_priority()));
+ state->SetString("use_case", UseCaseToString(use_case()));
+
state->SetBoolean("should_disable_throttling", should_disable_throttling());
}
@@ -2310,15 +2347,17 @@ void MainThreadSchedulerImpl::DispatchRequestBeginMainFrameNotExpected(
if (has_tasks ==
main_thread_only().compositor_will_send_main_frame_not_expected.get())
return;
- main_thread_only().compositor_will_send_main_frame_not_expected = has_tasks;
TRACE_EVENT1(
TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
"MainThreadSchedulerImpl::DispatchRequestBeginMainFrameNotExpected",
"has_tasks", has_tasks);
+ bool success = false;
for (PageSchedulerImpl* page_scheduler : main_thread_only().page_schedulers) {
- page_scheduler->RequestBeginMainFrameNotExpected(has_tasks);
+ success |= page_scheduler->RequestBeginMainFrameNotExpected(has_tasks);
}
+ main_thread_only().compositor_will_send_main_frame_not_expected =
+ success && has_tasks;
}
std::unique_ptr<base::SingleSampleMetric>
@@ -2374,7 +2413,7 @@ void MainThreadSchedulerImpl::ResetForNavigationLocked() {
helper_.CheckOnValidThread();
any_thread_lock_.AssertAcquired();
any_thread().user_model.Reset(helper_.NowTicks());
- any_thread().have_seen_a_potentially_blocking_gesture = false;
+ any_thread().have_seen_a_blocking_gesture = false;
any_thread().waiting_for_meaningful_paint = true;
any_thread().have_seen_input_since_navigation = false;
main_thread_only().loading_task_cost_estimator.Clear();
@@ -2418,8 +2457,9 @@ void MainThreadSchedulerImpl::SetTopLevelBlameContext(
ipc_task_queue_->SetBlameContext(blame_context);
}
-void MainThreadSchedulerImpl::SetRAILModeObserver(RAILModeObserver* observer) {
- main_thread_only().rail_mode_observer = observer;
+void MainThreadSchedulerImpl::AddRAILModeObserver(RAILModeObserver* observer) {
+ main_thread_only().rail_mode_observers.AddObserver(observer);
+ observer->OnRAILModeChanged(main_thread_only().current_policy.rail_mode());
}
void MainThreadSchedulerImpl::SetRendererProcessType(RendererProcessType type) {
@@ -2436,7 +2476,7 @@ MainThreadSchedulerImpl::CreateWebScopedVirtualTimePauser(
void MainThreadSchedulerImpl::RunIdleTask(WebThread::IdleTask task,
base::TimeTicks deadline) {
- std::move(task).Run((deadline - base::TimeTicks()).InSecondsF());
+ std::move(task).Run(deadline);
}
void MainThreadSchedulerImpl::PostIdleTask(const base::Location& location,
@@ -2466,9 +2506,7 @@ MainThreadSchedulerImpl::CompositorTaskRunner() {
std::unique_ptr<PageScheduler> MainThreadSchedulerImpl::CreatePageScheduler(
PageScheduler::Delegate* delegate) {
- return std::make_unique<PageSchedulerImpl>(
- delegate, this,
- !RuntimeEnabledFeatures::TimerThrottlingForBackgroundTabsEnabled());
+ return std::make_unique<PageSchedulerImpl>(delegate, this);
}
std::unique_ptr<ThreadScheduler::RendererPauseHandle>
@@ -2480,7 +2518,7 @@ base::TimeTicks MainThreadSchedulerImpl::MonotonicallyIncreasingVirtualTime() {
return GetActiveTimeDomain()->Now();
}
-WebMainThreadScheduler*
+WebThreadScheduler*
MainThreadSchedulerImpl::GetWebMainThreadSchedulerForTest() {
return this;
}
@@ -2520,11 +2558,16 @@ void MainThreadSchedulerImpl::BroadcastIntervention(
page_scheduler->ReportIntervention(message);
}
-void MainThreadSchedulerImpl::OnTaskStarted(MainThreadTaskQueue* queue,
- const TaskQueue::Task& task,
- base::TimeTicks start) {
- main_thread_only().current_task_start_time = start;
- queueing_time_estimator_.OnTopLevelTaskStarted(start, queue);
+void MainThreadSchedulerImpl::OnTaskStarted(
+ MainThreadTaskQueue* queue,
+ const TaskQueue::Task& task,
+ const TaskQueue::TaskTiming& task_timing) {
+ main_thread_only().running_queues.push(queue);
+ queueing_time_estimator_.OnExecutionStarted(task_timing.start_time(), queue);
+ if (main_thread_only().nested_runloop)
+ return;
+
+ main_thread_only().current_task_start_time = task_timing.start_time();
main_thread_only().task_description_for_tracing = TaskDescriptionForTracing{
static_cast<TaskType>(task.task_type()),
queue
@@ -2540,37 +2583,41 @@ void MainThreadSchedulerImpl::OnTaskStarted(MainThreadTaskQueue* queue,
void MainThreadSchedulerImpl::OnTaskCompleted(
MainThreadTaskQueue* queue,
const TaskQueue::Task& task,
- base::TimeTicks start,
- base::TimeTicks end,
- base::Optional<base::TimeDelta> thread_time) {
- DCHECK_LE(start, end);
- queueing_time_estimator_.OnTopLevelTaskCompleted(end);
+ const TaskQueue::TaskTiming& task_timing) {
+ DCHECK_LE(task_timing.start_time(), task_timing.end_time());
+ DCHECK(!main_thread_only().running_queues.empty());
+ DCHECK(!queue || main_thread_only().running_queues.top().get() == queue);
+ main_thread_only().running_queues.pop();
+ queueing_time_estimator_.OnExecutionStopped(task_timing.end_time());
+ if (main_thread_only().nested_runloop)
+ return;
+
+ if (queue) {
+ task_queue_throttler()->OnTaskRunTimeReported(
+ queue, task_timing.start_time(), task_timing.end_time());
+ }
- if (queue)
- task_queue_throttler()->OnTaskRunTimeReported(queue, start, end);
+ main_thread_only().compositing_experiment.OnTaskCompleted(queue);
// TODO(altimin): Per-page metrics should also be considered.
- main_thread_only().metrics_helper.RecordTaskMetrics(queue, task, start, end,
- thread_time);
+ main_thread_only().metrics_helper.RecordTaskMetrics(queue, task, task_timing);
main_thread_only().task_description_for_tracing = base::nullopt;
// Unset the state of |task_priority_for_tracing|.
main_thread_only().task_priority_for_tracing = base::nullopt;
- RecordTaskUkm(queue, task, start, end, thread_time);
+ RecordTaskUkm(queue, task, task_timing);
}
void MainThreadSchedulerImpl::RecordTaskUkm(
MainThreadTaskQueue* queue,
const TaskQueue::Task& task,
- base::TimeTicks start,
- base::TimeTicks end,
- base::Optional<base::TimeDelta> thread_time) {
- if (!ShouldRecordTaskUkm(thread_time.has_value()))
+ const TaskQueue::TaskTiming& task_timing) {
+ if (!ShouldRecordTaskUkm(task_timing.has_thread_time()))
return;
if (queue && queue->GetFrameScheduler()) {
- RecordTaskUkmImpl(queue, task, start, end, thread_time,
+ RecordTaskUkmImpl(queue, task, task_timing,
static_cast<PageSchedulerImpl*>(
queue->GetFrameScheduler()->GetPageScheduler()),
1);
@@ -2578,7 +2625,7 @@ void MainThreadSchedulerImpl::RecordTaskUkm(
}
for (PageSchedulerImpl* page_scheduler : main_thread_only().page_schedulers) {
- RecordTaskUkmImpl(queue, task, start, end, thread_time, page_scheduler,
+ RecordTaskUkmImpl(queue, task, task_timing, page_scheduler,
main_thread_only().page_schedulers.size());
}
}
@@ -2586,9 +2633,7 @@ void MainThreadSchedulerImpl::RecordTaskUkm(
void MainThreadSchedulerImpl::RecordTaskUkmImpl(
MainThreadTaskQueue* queue,
const TaskQueue::Task& task,
- base::TimeTicks start,
- base::TimeTicks end,
- base::Optional<base::TimeDelta> thread_time,
+ const TaskQueue::TaskTiming& task_timing,
PageSchedulerImpl* page_scheduler,
size_t page_schedulers_to_attribute) {
// Skip tasks which have deleted the page scheduler.
@@ -2614,23 +2659,70 @@ void MainThreadSchedulerImpl::RecordTaskUkmImpl(
queue ? queue->queue_type() : MainThreadTaskQueue::QueueType::kDetached));
builder.SetFrameStatus(static_cast<int>(
GetFrameStatus(queue ? queue->GetFrameScheduler() : nullptr)));
- builder.SetTaskDuration((end - start).InMicroseconds());
+ builder.SetTaskDuration(task_timing.wall_duration().InMicroseconds());
+
+ if (main_thread_only().renderer_backgrounded) {
+ base::TimeDelta time_since_backgrounded =
+ (task_timing.end_time() -
+ main_thread_only().background_status_changed_at);
+
+ // Trade off for privacy: Round to seconds for times below 10 minutes and
+ // minutes afterwards.
+ int seconds_since_backgrounded = 0;
+ if (time_since_backgrounded < base::TimeDelta::FromMinutes(10)) {
+ seconds_since_backgrounded = time_since_backgrounded.InSeconds();
+ } else {
+ seconds_since_backgrounded =
+ time_since_backgrounded.InMinutes() * kSecondsPerMinute;
+ }
- if (thread_time) {
- builder.SetTaskCPUDuration(thread_time->InMicroseconds());
+ builder.SetSecondsSinceBackgrounded(seconds_since_backgrounded);
+ }
+
+ if (task_timing.has_thread_time()) {
+ builder.SetTaskCPUDuration(task_timing.thread_duration().InMicroseconds());
}
builder.Record(ukm_recorder);
}
-void MainThreadSchedulerImpl::OnBeginNestedRunLoop() {
- queueing_time_estimator_.OnBeginNestedRunLoop();
+TaskQueue::QueuePriority MainThreadSchedulerImpl::ComputePriority(
+ MainThreadTaskQueue* task_queue) const {
+ DCHECK(task_queue);
+
+ // If |task_queue| is associated to a frame, the the frame scheduler computes
+ // the priority.
+ FrameSchedulerImpl* frame_scheduler = task_queue->GetFrameScheduler();
+
+ if (frame_scheduler) {
+ return frame_scheduler->ComputePriority(task_queue);
+ }
+
+ base::Optional<TaskQueue::QueuePriority> fixed_priority =
+ task_queue->FixedPriority();
+ if (fixed_priority) {
+ return fixed_priority.value();
+ }
+
+ if (task_queue->queue_class() ==
+ MainThreadTaskQueue::QueueClass::kCompositor) {
+ return main_thread_only().current_policy.compositor_priority();
+ }
+
+ // Default priority.
+ return TaskQueue::QueuePriority::kNormalPriority;
+}
+void MainThreadSchedulerImpl::OnBeginNestedRunLoop() {
+ queueing_time_estimator_.OnExecutionStopped(real_time_domain()->Now());
main_thread_only().nested_runloop = true;
ApplyVirtualTimePolicy();
}
void MainThreadSchedulerImpl::OnExitNestedRunLoop() {
+ DCHECK(!main_thread_only().running_queues.empty());
+ queueing_time_estimator_.OnExecutionStarted(
+ real_time_domain()->Now(), main_thread_only().running_queues.top().get());
main_thread_only().nested_runloop = false;
ApplyVirtualTimePolicy();
}
@@ -2663,20 +2755,33 @@ void MainThreadSchedulerImpl::OnQueueingTimeForWindowEstimated(
CreateMaxQueueingTimeMetric();
}
main_thread_only().max_queueing_time_metric->SetSample(
- queueing_time.InMilliseconds());
+ base::saturated_cast<base::HistogramBase::Sample>(
+ queueing_time.InMilliseconds()));
main_thread_only().max_queueing_time = queueing_time;
}
}
- if (!is_disjoint_window || !ContainsLocalMainFrame())
+ if (!is_disjoint_window)
return;
+ if (!ContainsLocalMainFrame()) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "RendererScheduler.ExpectedTaskQueueingDurationWithoutMainFrame",
+ base::saturated_cast<base::HistogramBase::Sample>(
+ queueing_time.InMicroseconds()),
+ kMinExpectedQueueingTimeBucket, kMaxExpectedQueueingTimeBucket,
+ kNumberExpectedQueueingTimeBuckets);
+ return;
+ }
+
UMA_HISTOGRAM_TIMES("RendererScheduler.ExpectedTaskQueueingDuration",
queueing_time);
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "RendererScheduler.ExpectedTaskQueueingDuration3",
- queueing_time.InMicroseconds(), kMinExpectedQueueingTimeBucket,
- kMaxExpectedQueueingTimeBucket, kNumberExpectedQueueingTimeBuckets);
+ UMA_HISTOGRAM_CUSTOM_COUNTS("RendererScheduler.ExpectedTaskQueueingDuration3",
+ base::saturated_cast<base::HistogramBase::Sample>(
+ queueing_time.InMicroseconds()),
+ kMinExpectedQueueingTimeBucket,
+ kMaxExpectedQueueingTimeBucket,
+ kNumberExpectedQueueingTimeBuckets);
TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("renderer.scheduler"),
"estimated_queueing_time_for_window",
queueing_time.InMillisecondsF());
@@ -2694,7 +2799,9 @@ void MainThreadSchedulerImpl::OnReportFineGrainedExpectedQueueingTime(
return;
base::UmaHistogramCustomCounts(
- split_description, queueing_time.InMicroseconds(),
+ split_description,
+ base::saturated_cast<base::HistogramBase::Sample>(
+ queueing_time.InMicroseconds()),
kMinExpectedQueueingTimeBucket, kMaxExpectedQueueingTimeBucket,
kNumberExpectedQueueingTimeBuckets);
}
@@ -2773,6 +2880,34 @@ bool MainThreadSchedulerImpl::ShouldRecordTaskUkm(bool has_thread_time) {
main_thread_only().random_generator) < sampling_rate;
}
+bool MainThreadSchedulerImpl::ShouldUpdateTaskQueuePriorities(
+ Policy old_policy) const {
+ return old_policy.use_case() !=
+ main_thread_only().current_policy.use_case() ||
+ old_policy.compositor_priority() !=
+ main_thread_only().current_policy.compositor_priority();
+}
+
+UseCase MainThreadSchedulerImpl::current_use_case() const {
+ return main_thread_only().current_use_case;
+}
+
+const MainThreadSchedulerImpl::SchedulingSettings&
+MainThreadSchedulerImpl::scheduling_settings() const {
+ return scheduling_settings_;
+}
+
+void MainThreadSchedulerImpl::SetShouldPrioritizeCompositing(
+ bool should_prioritize_compositing) {
+ if (main_thread_only().should_prioritize_compositing ==
+ should_prioritize_compositing) {
+ return;
+ }
+ main_thread_only().should_prioritize_compositing =
+ should_prioritize_compositing;
+ UpdatePolicy();
+}
+
// static
const char* MainThreadSchedulerImpl::UseCaseToString(UseCase use_case) {
switch (use_case) {
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
index 7b2b64a33c4..20fb1a37a14 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
@@ -19,16 +19,16 @@
#include "base/metrics/single_sample_metrics.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
+#include "base/task/sequence_manager/task_queue.h"
+#include "base/task/sequence_manager/task_time_observer.h"
#include "base/trace_event/trace_log.h"
#include "build/build_config.h"
-#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_time_observer.h"
-#include "third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper.h"
-#include "third_party/blink/renderer/platform/scheduler/child/idle_helper.h"
#include "third_party/blink/renderer/platform/scheduler/child/pollable_thread_safe_flag.h"
#include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
+#include "third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper.h"
+#include "third_party/blink/renderer/platform/scheduler/common/idle_helper.h"
#include "third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner.h"
@@ -37,6 +37,7 @@
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_helper.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/render_widget_signals.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/task_cost_estimator.h"
@@ -64,8 +65,7 @@ class TaskQueueThrottler;
class WebRenderWidgetSchedulingState;
class PLATFORM_EXPORT MainThreadSchedulerImpl
- : public WebMainThreadScheduler,
- public ThreadSchedulerImpl,
+ : public ThreadSchedulerImpl,
public IdleHelper::Delegate,
public MainThreadSchedulerHelper::Observer,
public RenderWidgetSignals::Observer,
@@ -84,6 +84,51 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
}
};
+ struct SchedulingSettings {
+ SchedulingSettings();
+
+ // High priority input experiment.
+ bool high_priority_input;
+
+ // Background page priority experiment (crbug.com/848835).
+ bool low_priority_background_page;
+ bool best_effort_background_page;
+
+ // Task and subframe priority experiment (crbug.com/852380).
+ bool low_priority_subframe;
+ bool low_priority_throttleable;
+ bool low_priority_subframe_throttleable;
+ bool low_priority_hidden_frame;
+
+ // Used along with |low_priority_subframe|, |low_priority_throttleable|,
+ // |low_priority_subframe_throttleable|, |low_priority_hidden_frame|
+ // to enable one of these experiments during the loading phase only.
+ bool use_frame_priorities_only_during_loading;
+
+ // Ads priority experiment (crbug.com/856150).
+ bool low_priority_ad_frame;
+ bool best_effort_ad_frame;
+ bool use_adframe_priorities_only_during_loading;
+
+ // Origin type priority experiment (crbug.com/856158).
+ bool low_priority_cross_origin;
+ bool low_priority_cross_origin_only_during_loading;
+
+ // Use resource fetch priority for resource loading tasks
+ // (crbug.com/860545).
+ bool use_resource_fetch_priority;
+ bool use_resource_priorities_only_during_loading;
+
+ // Contains a mapping from net::RequestPriority to TaskQueue::QueuePriority
+ // when use_resource_fetch_priority is enabled.
+ std::array<base::sequence_manager::TaskQueue::QueuePriority,
+ net::RequestPrioritySize::NUM_PRIORITIES>
+ net_to_blink_priority;
+
+ // Turn on relevant experiments during the loading phase.
+ bool experiment_only_when_loading;
+ };
+
static const char* UseCaseToString(UseCase use_case);
static const char* RAILModeToString(v8::RAILMode rail_mode);
static const char* VirtualTimePolicyToString(
@@ -100,13 +145,12 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
// with virtual time enabled and paused with base::Time will be overridden to
// start at |initial_virtual_time|.
MainThreadSchedulerImpl(
- std::unique_ptr<base::sequence_manager::TaskQueueManager>
- task_queue_manager,
+ std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager,
base::Optional<base::Time> initial_virtual_time);
~MainThreadSchedulerImpl() override;
- // WebMainThreadScheduler implementation:
+ // WebThreadScheduler implementation:
std::unique_ptr<WebThread> CreateMainThread() override;
scoped_refptr<SingleThreadIdleTaskRunner> IdleTaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> IPCTaskRunner() override;
@@ -126,6 +170,7 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
void SetRendererBackgrounded(bool backgrounded) override;
void SetSchedulerKeepActive(bool keep_active) override;
bool SchedulerKeepActive();
+ void OnMainFrameRequestedForInput() override;
#if defined(OS_ANDROID)
void PauseTimersForAndroidWebView() override;
void ResumeTimersForAndroidWebView() override;
@@ -139,10 +184,9 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
void RemoveTaskObserver(
base::MessageLoop::TaskObserver* task_observer) override;
void Shutdown() override;
- void SetFreezingWhenBackgroundedEnabled(bool enabled) override;
void SetTopLevelBlameContext(
base::trace_event::BlameContext* blame_context) override;
- void SetRAILModeObserver(RAILModeObserver* observer) override;
+ void AddRAILModeObserver(RAILModeObserver* observer) override;
void SetRendererProcessType(RendererProcessType type) override;
WebScopedVirtualTimePauser CreateWebScopedVirtualTimePauser(
const char* name,
@@ -159,12 +203,12 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
std::unique_ptr<ThreadScheduler::RendererPauseHandle> PauseScheduler()
override;
base::TimeTicks MonotonicallyIncreasingVirtualTime() override;
- WebMainThreadScheduler* GetWebMainThreadSchedulerForTest() override;
- NonMainThreadScheduler* AsNonMainThreadScheduler() override {
+ WebThreadScheduler* GetWebMainThreadSchedulerForTest() override;
+ NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() override {
return nullptr;
}
- // WebMainThreadScheduler implementation:
+ // WebThreadScheduler implementation:
scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> InputTaskRunner() override;
@@ -275,6 +319,11 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
bool is_reload,
bool is_main_frame);
+ // Note that the main's thread policy should be upto date to compute
+ // the correct priority.
+ base::sequence_manager::TaskQueue::QueuePriority ComputePriority(
+ MainThreadTaskQueue* task_queue) const;
+
// Test helpers.
MainThreadSchedulerHelper* GetSchedulerHelperForTesting();
TaskCostEstimator* GetLoadingTaskCostEstimatorForTesting();
@@ -289,7 +338,7 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
const base::TickClock* tick_clock() const;
- base::sequence_manager::RealTimeDomain* real_time_domain() const {
+ base::sequence_manager::TimeDomain* real_time_domain() const {
return helper_.real_time_domain();
}
@@ -303,15 +352,15 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
void OnShutdownTaskQueue(const scoped_refptr<MainThreadTaskQueue>& queue);
- void OnTaskStarted(MainThreadTaskQueue* queue,
- const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start);
+ void OnTaskStarted(
+ MainThreadTaskQueue* queue,
+ const base::sequence_manager::TaskQueue::Task& task,
+ const base::sequence_manager::TaskQueue::TaskTiming& task_timing);
- void OnTaskCompleted(MainThreadTaskQueue* queue,
- const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start,
- base::TimeTicks end,
- base::Optional<base::TimeDelta> thread_time);
+ void OnTaskCompleted(
+ MainThreadTaskQueue* queue,
+ const base::sequence_manager::TaskQueue::Task& task,
+ const base::sequence_manager::TaskQueue::TaskTiming& task_timing);
bool IsAudioPlaying() const;
@@ -319,6 +368,12 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
void OnTraceLogEnabled() override;
void OnTraceLogDisabled() override;
+ UseCase current_use_case() const;
+
+ const SchedulingSettings& scheduling_settings() const;
+
+ void SetShouldPrioritizeCompositing(bool should_prioritize_compositing);
+
base::WeakPtr<MainThreadSchedulerImpl> GetWeakPtr();
protected:
@@ -337,6 +392,8 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
main_thread_only().current_use_case = use_case;
}
+ void SetHaveSeenABlockingGestureForTesting(bool status);
+
private:
friend class WebRenderWidgetSchedulingState;
friend class MainThreadMetricsHelper;
@@ -345,6 +402,7 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
friend class main_thread_scheduler_impl_unittest::
MainThreadSchedulerImplForTest;
friend class main_thread_scheduler_impl_unittest::MainThreadSchedulerImplTest;
+
FRIEND_TEST_ALL_PREFIXES(
main_thread_scheduler_impl_unittest::MainThreadSchedulerImplTest,
ShouldIgnoreTaskForUkm);
@@ -362,8 +420,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
static const char* TimeDomainTypeToString(TimeDomainType domain_type);
- void SetFrozenInBackground(bool) const;
-
bool ContainsLocalMainFrame();
struct TaskQueuePolicy {
@@ -373,32 +429,24 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
: is_enabled(true),
is_paused(false),
is_throttled(false),
- is_blocked(false),
- is_frozen(false),
- use_virtual_time(false),
- priority(base::sequence_manager::TaskQueue::kNormalPriority) {}
+ is_deferred(false),
+ use_virtual_time(false) {}
bool is_enabled;
bool is_paused;
bool is_throttled;
- bool is_blocked;
- bool is_frozen;
+ bool is_deferred;
bool use_virtual_time;
- base::sequence_manager::TaskQueue::QueuePriority priority;
bool IsQueueEnabled(MainThreadTaskQueue* task_queue) const;
- base::sequence_manager::TaskQueue::QueuePriority GetPriority(
- MainThreadTaskQueue* task_queue) const;
-
TimeDomainType GetTimeDomainType(MainThreadTaskQueue* task_queue) const;
bool operator==(const TaskQueuePolicy& other) const {
return is_enabled == other.is_enabled && is_paused == other.is_paused &&
is_throttled == other.is_throttled &&
- is_blocked == other.is_blocked && is_frozen == other.is_frozen &&
- use_virtual_time == other.use_virtual_time &&
- priority == other.priority;
+ is_deferred == other.is_deferred &&
+ use_virtual_time == other.use_virtual_time;
}
void AsValueInto(base::trace_event::TracedValue* state) const;
@@ -408,7 +456,12 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
public:
Policy()
: rail_mode_(v8::PERFORMANCE_ANIMATION),
- should_disable_throttling_(false) {}
+ should_disable_throttling_(false),
+ frozen_when_backgrounded_(false),
+ compositor_priority_(base::sequence_manager::TaskQueue::
+ QueuePriority::kNormalPriority),
+ use_case_(UseCase::kNone) {}
+
~Policy() = default;
TaskQueuePolicy& compositor_queue_policy() {
@@ -460,9 +513,26 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
return should_disable_throttling_;
}
+ bool& frozen_when_backgrounded() { return frozen_when_backgrounded_; }
+ bool frozen_when_backgrounded() const { return frozen_when_backgrounded_; }
+
+ base::sequence_manager::TaskQueue::QueuePriority& compositor_priority() {
+ return compositor_priority_;
+ }
+ base::sequence_manager::TaskQueue::QueuePriority compositor_priority()
+ const {
+ return compositor_priority_;
+ }
+
+ UseCase& use_case() { return use_case_; }
+ UseCase use_case() const { return use_case_; }
+
bool operator==(const Policy& other) const {
return policies_ == other.policies_ && rail_mode_ == other.rail_mode_ &&
- should_disable_throttling_ == other.should_disable_throttling_;
+ should_disable_throttling_ == other.should_disable_throttling_ &&
+ frozen_when_backgrounded_ == other.frozen_when_backgrounded_ &&
+ compositor_priority_ == other.compositor_priority_ &&
+ use_case_ == other.use_case_;
}
void AsValueInto(base::trace_event::TracedValue* state) const;
@@ -470,6 +540,13 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
private:
v8::RAILMode rail_mode_;
bool should_disable_throttling_;
+ bool frozen_when_backgrounded_;
+
+ // Priority of task queues belonging to the compositor class (Check
+ // MainThread::QueueClass).
+ base::sequence_manager::TaskQueue::QueuePriority compositor_priority_;
+
+ UseCase use_case_;
std::array<TaskQueuePolicy,
static_cast<size_t>(MainThreadTaskQueue::QueueClass::kCount)>
@@ -518,6 +595,11 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
void EndIdlePeriod();
+ // Update a policy which increases priority for the next beginMainFrame after
+ // an input event.
+ void UpdatePrioritizeCompositingAfterInputAfterTaskCompleted(
+ MainThreadTaskQueue* queue);
+
// Returns the serialized scheduler state for tracing.
std::unique_ptr<base::trace_event::ConvertableToTraceFormat> AsValue(
base::TimeTicks optional_now) const;
@@ -535,11 +617,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
// defined by RAILS.
static const int kRailsResponseTimeMillis = 50;
- // The amount of time to wait before suspending shared timers, and loading
- // etc. after the renderer has been backgrounded. This is used only if
- // background suspension is enabled.
- static const int kDelayForBackgroundTabFreezingMillis = 5 * 60 * 1000;
-
// The time we should stay in a priority-escalated mode after a call to
// DidAnimateForInputOnCompositorThread().
static const int kFlingEscalationLimitMillis = 100;
@@ -582,7 +659,7 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
std::unique_ptr<base::SingleSampleMetric> CreateMaxQueueingTimeMetric();
// An input event of some sort happened, the policy may need updating.
- void UpdateForInputEventOnCompositorThread(WebInputEvent::Type type,
+ void UpdateForInputEventOnCompositorThread(const WebInputEvent& event,
InputEventState input_event_state);
// The task cost estimators and the UserModel need to be reset upon page
@@ -634,27 +711,31 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
// Returns true with probability of kSamplingRateForTaskUkm.
bool ShouldRecordTaskUkm(bool has_thread_time);
+ // Returns true if there is a change in the main thread's policy that should
+ // trigger a priority update.
+ bool ShouldUpdateTaskQueuePriorities(Policy new_policy) const;
+
static void RunIdleTask(WebThread::IdleTask, base::TimeTicks deadline);
// Probabilistically record all task metadata for the current task.
// If task belongs to a per-frame queue, this task is attributed to
// a particular Page, otherwise it's attributed to all Pages in the process.
- void RecordTaskUkm(MainThreadTaskQueue* queue,
- const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start,
- base::TimeTicks end,
- base::Optional<base::TimeDelta> thread_time);
-
- void RecordTaskUkmImpl(MainThreadTaskQueue* queue,
- const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start,
- base::TimeTicks end,
- base::Optional<base::TimeDelta> thread_time,
- PageSchedulerImpl* page_scheduler,
- size_t page_schedulers_to_attribute);
+ void RecordTaskUkm(
+ MainThreadTaskQueue* queue,
+ const base::sequence_manager::TaskQueue::Task& task,
+ const base::sequence_manager::TaskQueue::TaskTiming& task_timing);
+
+ void RecordTaskUkmImpl(
+ MainThreadTaskQueue* queue,
+ const base::sequence_manager::TaskQueue::Task& task,
+ const base::sequence_manager::TaskQueue::TaskTiming& task_timing,
+ PageSchedulerImpl* page_scheduler,
+ size_t page_schedulers_to_attribute);
void InitWakeUpBudgetPoolIfNeeded();
+ void SetNumberOfCompositingTasksToPrioritize(int number_of_tasks);
+
// Indicates that scheduler has been shutdown.
// It should be accessed only on the main thread, but couldn't be a member
// of MainThreadOnly struct because last might be destructed before we
@@ -665,6 +746,14 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
// because they require one to initialize themselves.
TraceableVariableController tracing_controller_;
+ // Used for experiments on finch. On main thread instantiation, we cache
+ // the values of base::Feature flags using this struct, since calling
+ // base::Feature::IsEnabled is a relatively expensive operation.
+ //
+ // Note that it is important to keep this as the first member to ensure it is
+ // initialized first and can be used everywhere.
+ const SchedulingSettings scheduling_settings_;
+
MainThreadSchedulerHelper helper_;
IdleHelper idle_helper_;
IdleCanceledDelayedTaskSweeper idle_canceled_delayed_task_sweeper_;
@@ -691,6 +780,9 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
scoped_refptr<TaskQueueWithTaskType> v8_task_runner_;
scoped_refptr<TaskQueueWithTaskType> compositor_task_runner_;
+ scoped_refptr<TaskQueueWithTaskType> control_task_runner_;
+ scoped_refptr<TaskQueueWithTaskType> input_task_runner_;
+ scoped_refptr<TaskQueueWithTaskType> ipc_task_runner_;
// Note |virtual_time_domain_| is lazily created.
std::unique_ptr<AutoAdvancingVirtualTimeDomain> virtual_time_domain_;
@@ -701,8 +793,6 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
QueueingTimeEstimator queueing_time_estimator_;
- base::TimeDelta delay_for_background_tab_freezing_;
-
// We have decided to improve thread safety at the cost of some boilerplate
// (the accessors) for the following data members.
@@ -735,16 +825,14 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
TraceableState<bool, kTracingCategoryNameTopLevel> renderer_backgrounded;
TraceableState<bool, kTracingCategoryNameDefault>
keep_active_fetch_or_worker;
- TraceableState<bool, kTracingCategoryNameInfo>
- freezing_when_backgrounded_enabled;
- TraceableState<bool, kTracingCategoryNameInfo> frozen_when_backgrounded;
TraceableCounter<base::TimeDelta, kTracingCategoryNameInfo>
loading_task_estimated_cost;
TraceableCounter<base::TimeDelta, kTracingCategoryNameInfo>
timer_task_estimated_cost;
TraceableState<bool, kTracingCategoryNameInfo> loading_tasks_seem_expensive;
TraceableState<bool, kTracingCategoryNameInfo> timer_tasks_seem_expensive;
- TraceableState<bool, kTracingCategoryNameDefault> touchstart_expected_soon;
+ TraceableState<bool, kTracingCategoryNameDefault>
+ blocking_input_expected_soon;
TraceableState<bool, kTracingCategoryNameDebug>
have_seen_a_begin_main_frame;
TraceableState<bool, kTracingCategoryNameDebug>
@@ -766,7 +854,7 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
base::TimeDelta max_queueing_time;
base::TimeTicks background_status_changed_at;
std::set<PageSchedulerImpl*> page_schedulers; // Not owned.
- RAILModeObserver* rail_mode_observer; // Not owned.
+ base::ObserverList<RAILModeObserver> rail_mode_observers; // Not owned.
WakeUpBudgetPool* wake_up_budget_pool; // Not owned.
MainThreadMetricsHelper metrics_helper;
TraceableState<RendererProcessType, kTracingCategoryNameTopLevel>
@@ -797,10 +885,23 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
// allowed). NB a value of 0 allows infinite starvation.
int max_virtual_time_task_starvation_count;
bool virtual_time_stopped;
+
+ // Holds task queues that are currently running.
+ // The queue for the inmost task is at the top of stack when there are
+ // nested RunLoops.
+ std::stack<scoped_refptr<MainThreadTaskQueue>,
+ std::vector<scoped_refptr<MainThreadTaskQueue>>>
+ running_queues;
+
+ // True if a nested RunLoop is running.
bool nested_runloop;
std::mt19937_64 random_generator;
std::uniform_real_distribution<double> uniform_distribution;
+
+ // High-priority for compositing events after input experiment.
+ PrioritizeCompositingAfterInputExperiment compositing_experiment;
+ bool should_prioritize_compositing;
};
struct AnyThread {
@@ -818,8 +919,7 @@ class PLATFORM_EXPORT MainThreadSchedulerImpl
TraceableState<bool, kTracingCategoryNameInfo>
last_gesture_was_compositor_driven;
TraceableState<bool, kTracingCategoryNameInfo> default_gesture_prevented;
- TraceableState<bool, kTracingCategoryNameInfo>
- have_seen_a_potentially_blocking_gesture;
+ TraceableState<bool, kTracingCategoryNameInfo> have_seen_a_blocking_gesture;
TraceableState<bool, kTracingCategoryNameInfo> waiting_for_meaningful_paint;
TraceableState<bool, kTracingCategoryNameInfo>
have_seen_input_since_navigation;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
index 056a1ec5a75..8e37aaea02c 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl_unittest.cc
@@ -12,17 +12,20 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/test/histogram_tester.h"
+#include "base/task/sequence_manager/test/fake_task.h"
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_tick_clock.h"
+#include "base/test/test_mock_time_task_runner.h"
#include "build/build_config.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
-#include "components/viz/test/ordered_simple_task_runner.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/page/launching_process_state.h"
-#include "third_party/blink/renderer/platform/scheduler/base/real_time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
+#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
+#include "third_party/blink/public/platform/web_touch_event.h"
#include "third_party/blink/renderer/platform/scheduler/child/features.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h"
@@ -37,7 +40,9 @@ namespace scheduler {
namespace main_thread_scheduler_impl_unittest {
using testing::Mock;
-using InputEventState = WebMainThreadScheduler::InputEventState;
+using InputEventState = WebThreadScheduler::InputEventState;
+using base::sequence_manager::FakeTask;
+using base::sequence_manager::FakeTaskTiming;
class FakeInputEvent : public blink::WebInputEvent {
public:
@@ -49,6 +54,30 @@ class FakeInputEvent : public blink::WebInputEvent {
WebInputEvent::GetStaticTimeStampForTests()) {}
};
+class FakeTouchEvent : public blink::WebTouchEvent {
+ public:
+ explicit FakeTouchEvent(
+ blink::WebInputEvent::Type event_type,
+ DispatchType dispatch_type = blink::WebInputEvent::kBlocking)
+ : WebTouchEvent(event_type,
+ WebInputEvent::kNoModifiers,
+ WebInputEvent::GetStaticTimeStampForTests()) {
+ this->dispatch_type = dispatch_type;
+ }
+};
+
+class FakeMouseWheelEvent : public blink::WebMouseWheelEvent {
+ public:
+ explicit FakeMouseWheelEvent(
+ blink::WebInputEvent::Type event_type,
+ DispatchType dispatch_type = blink::WebInputEvent::kBlocking)
+ : WebMouseWheelEvent(event_type,
+ WebInputEvent::kNoModifiers,
+ WebInputEvent::GetStaticTimeStampForTests()) {
+ this->dispatch_type = dispatch_type;
+ }
+};
+
void AppendToVectorTestTask(std::vector<std::string>* vector,
std::string value) {
vector->push_back(value);
@@ -99,7 +128,7 @@ void RepostingIdleTestTask(SingleThreadIdleTaskRunner* idle_task_runner,
void RepostingUpdateClockIdleTestTask(
SingleThreadIdleTaskRunner* idle_task_runner,
int* run_count,
- base::SimpleTestTickClock* clock,
+ scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner,
base::TimeDelta advance_time,
std::vector<base::TimeTicks>* deadlines,
base::TimeTicks deadline) {
@@ -107,16 +136,16 @@ void RepostingUpdateClockIdleTestTask(
idle_task_runner->PostIdleTask(
FROM_HERE, base::BindOnce(&RepostingUpdateClockIdleTestTask,
base::Unretained(idle_task_runner), run_count,
- clock, advance_time, deadlines));
+ test_task_runner, advance_time, deadlines));
}
deadlines->push_back(deadline);
(*run_count)++;
- clock->Advance(advance_time);
+ test_task_runner->AdvanceMockTickClock(advance_time);
}
-void WillBeginFrameIdleTask(WebMainThreadScheduler* scheduler,
+void WillBeginFrameIdleTask(WebThreadScheduler* scheduler,
uint64_t sequence_number,
- base::SimpleTestTickClock* clock,
+ const base::TickClock* clock,
base::TimeTicks deadline) {
scheduler->WillBeginFrame(viz::BeginFrameArgs::Create(
BEGINFRAME_FROM_HERE, 0, sequence_number, clock->NowTicks(),
@@ -124,10 +153,12 @@ void WillBeginFrameIdleTask(WebMainThreadScheduler* scheduler,
viz::BeginFrameArgs::NORMAL));
}
-void UpdateClockToDeadlineIdleTestTask(base::SimpleTestTickClock* clock,
- int* run_count,
- base::TimeTicks deadline) {
- clock->Advance(deadline - clock->NowTicks());
+void UpdateClockToDeadlineIdleTestTask(
+ scoped_refptr<base::TestMockTimeTaskRunner> task_runner,
+ int* run_count,
+ base::TimeTicks deadline) {
+ task_runner->AdvanceMockTickClock(
+ deadline - task_runner->GetMockTickClock()->NowTicks());
(*run_count)++;
}
@@ -165,7 +196,7 @@ void AnticipationTestTask(MainThreadSchedulerImpl* scheduler,
case SimulateInputType::kTouchStart:
scheduler->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
break;
@@ -190,41 +221,22 @@ void AnticipationTestTask(MainThreadSchedulerImpl* scheduler,
*is_anticipated_after = scheduler->IsHighPriorityWorkAnticipated();
}
-// RAII helper class to enable auto advancing of time inside mock task runner.
-// Automatically disables auto-advancement when destroyed.
-class ScopedAutoAdvanceNowEnabler {
- public:
- ScopedAutoAdvanceNowEnabler(
- scoped_refptr<cc::OrderedSimpleTaskRunner> task_runner)
- : task_runner_(task_runner) {
- task_runner_->SetAutoAdvanceNowToPendingTasks(true);
- }
-
- ~ScopedAutoAdvanceNowEnabler() {
- task_runner_->SetAutoAdvanceNowToPendingTasks(false);
- }
-
- private:
- scoped_refptr<cc::OrderedSimpleTaskRunner> task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedAutoAdvanceNowEnabler);
-};
-
class MainThreadSchedulerImplForTest : public MainThreadSchedulerImpl {
public:
- using MainThreadSchedulerImpl::EstimateLongestJankFreeTaskDuration;
- using MainThreadSchedulerImpl::OnIdlePeriodEnded;
- using MainThreadSchedulerImpl::OnIdlePeriodStarted;
- using MainThreadSchedulerImpl::OnPendingTasksChanged;
using MainThreadSchedulerImpl::CompositorTaskQueue;
using MainThreadSchedulerImpl::ControlTaskQueue;
using MainThreadSchedulerImpl::DefaultTaskQueue;
+ using MainThreadSchedulerImpl::EstimateLongestJankFreeTaskDuration;
using MainThreadSchedulerImpl::InputTaskQueue;
+ using MainThreadSchedulerImpl::OnIdlePeriodEnded;
+ using MainThreadSchedulerImpl::OnIdlePeriodStarted;
+ using MainThreadSchedulerImpl::OnPendingTasksChanged;
using MainThreadSchedulerImpl::V8TaskQueue;
using MainThreadSchedulerImpl::VirtualTimeControlTaskQueue;
+ using MainThreadSchedulerImpl::SetHaveSeenABlockingGestureForTesting;
MainThreadSchedulerImplForTest(
- std::unique_ptr<base::sequence_manager::TaskQueueManager> manager,
+ std::unique_ptr<base::sequence_manager::SequenceManager> manager,
base::Optional<base::Time> initial_virtual_time)
: MainThreadSchedulerImpl(std::move(manager), initial_virtual_time),
update_policy_count_(0) {}
@@ -235,13 +247,20 @@ class MainThreadSchedulerImplForTest : public MainThreadSchedulerImpl {
std::string use_case = MainThreadSchedulerImpl::UseCaseToString(
main_thread_only().current_use_case);
- if (main_thread_only().touchstart_expected_soon) {
- use_cases_.push_back(use_case + " touchstart expected");
+ if (main_thread_only().blocking_input_expected_soon) {
+ use_cases_.push_back(use_case + " blocking input expected");
} else {
use_cases_.push_back(use_case);
}
}
+ void OnQueueingTimeForWindowEstimated(base::TimeDelta queueing_time,
+ bool is_disjoint_window) override {
+ MainThreadSchedulerImpl::OnQueueingTimeForWindowEstimated(
+ queueing_time, is_disjoint_window);
+ expected_queueing_times_.push_back(queueing_time);
+ }
+
void EnsureUrgentPolicyUpdatePostedOnMainThread() {
base::AutoLock lock(any_thread_lock_);
MainThreadSchedulerImpl::EnsureUrgentPolicyUpdatePostedOnMainThread(
@@ -257,6 +276,10 @@ class MainThreadSchedulerImplForTest : public MainThreadSchedulerImpl {
return any_thread().begin_main_frame_on_critical_path;
}
+ void RemoveRAILModeObserver(RAILModeObserver const* observer) {
+ main_thread_only().rail_mode_observers.RemoveObserver(observer);
+ }
+
bool waiting_for_meaningful_paint() const {
base::AutoLock lock(any_thread_lock_);
return any_thread().waiting_for_meaningful_paint;
@@ -266,8 +289,13 @@ class MainThreadSchedulerImplForTest : public MainThreadSchedulerImpl {
return main_thread_only().virtual_time_policy;
}
+ const std::vector<base::TimeDelta>& expected_queueing_times() const {
+ return expected_queueing_times_;
+ }
+
int update_policy_count_;
std::vector<std::string> use_cases_;
+ std::vector<base::TimeDelta> expected_queueing_times_;
};
// Lets gtest print human readable Policy values.
@@ -277,85 +305,88 @@ class MainThreadSchedulerImplForTest : public MainThreadSchedulerImpl {
class MainThreadSchedulerImplTest : public testing::Test {
public:
- MainThreadSchedulerImplTest()
- : fake_task_(TaskQueue::PostedTask(base::BindOnce([] {}), FROM_HERE),
- base::TimeTicks()) {
- feature_list_.InitAndEnableFeature(kHighPriorityInput);
- clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
+ MainThreadSchedulerImplTest(std::vector<base::Feature> features_to_enable,
+ std::vector<base::Feature> features_to_disable) {
+ feature_list_.InitWithFeatures(features_to_enable, features_to_disable);
}
- MainThreadSchedulerImplTest(base::MessageLoop* message_loop)
- : fake_task_(TaskQueue::PostedTask(base::BindOnce([] {}), FROM_HERE),
- base::TimeTicks()),
- message_loop_(message_loop) {
- clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
- }
+ MainThreadSchedulerImplTest()
+ : MainThreadSchedulerImplTest({kHighPriorityInputOnMainThread},
+ {kPrioritizeCompositingAfterInput}) {}
~MainThreadSchedulerImplTest() override = default;
void SetUp() override {
- if (!message_loop_) {
- mock_task_runner_ =
- base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, false);
- }
+ CreateTestTaskRunner();
Initialize(std::make_unique<MainThreadSchedulerImplForTest>(
- base::sequence_manager::TaskQueueManagerForTest::Create(
- message_loop_.get(),
- message_loop_ ? message_loop_->task_runner() : mock_task_runner_,
- &clock_),
+ base::sequence_manager::SequenceManagerForTest::Create(
+ nullptr, test_task_runner_, test_task_runner_->GetMockTickClock()),
base::nullopt));
}
+ void CreateTestTaskRunner() {
+ test_task_runner_ = base::WrapRefCounted(new base::TestMockTimeTaskRunner(
+ base::TestMockTimeTaskRunner::Type::kBoundToThread));
+ // A null clock triggers some assertions.
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMilliseconds(5));
+ }
+
void Initialize(std::unique_ptr<MainThreadSchedulerImplForTest> scheduler) {
scheduler_ = std::move(scheduler);
+
if (kLaunchingProcessIsBackgrounded) {
scheduler_->SetRendererBackgrounded(false);
// Reset the policy count as foregrounding would force an initial update.
scheduler_->update_policy_count_ = 0;
scheduler_->use_cases_.clear();
}
+
default_task_runner_ = scheduler_->DefaultTaskQueue();
compositor_task_runner_ = scheduler_->CompositorTaskQueue();
input_task_runner_ = scheduler_->InputTaskQueue();
- loading_task_runner_ = scheduler_->NewLoadingTaskQueue(
- MainThreadTaskQueue::QueueType::kFrameLoading, nullptr);
- loading_control_task_runner_ = scheduler_->NewLoadingTaskQueue(
- MainThreadTaskQueue::QueueType::kFrameLoadingControl, nullptr);
idle_task_runner_ = scheduler_->IdleTaskRunner();
- timer_task_runner_ = scheduler_->NewTimerTaskQueue(
- MainThreadTaskQueue::QueueType::kFrameThrottleable, nullptr);
v8_task_runner_ = scheduler_->V8TaskQueue();
- fake_queue_ = scheduler_->NewLoadingTaskQueue(
- MainThreadTaskQueue::QueueType::kFrameLoading, nullptr);
+
+ page_scheduler_ =
+ std::make_unique<PageSchedulerImpl>(nullptr, scheduler_.get());
+ main_frame_scheduler_ = FrameSchedulerImpl::Create(
+ page_scheduler_.get(), nullptr, FrameScheduler::FrameType::kMainFrame);
+
+ loading_task_runner_ = main_frame_scheduler_->LoadingTaskQueue();
+ loading_control_task_runner_ =
+ main_frame_scheduler_->LoadingControlTaskQueue();
+ timer_task_runner_ = main_frame_scheduler_->ThrottleableTaskQueue();
}
void TearDown() override {
- DCHECK(!mock_task_runner_.get() || !message_loop_.get());
+ main_frame_scheduler_.reset();
+ page_scheduler_.reset();
scheduler_->Shutdown();
- if (mock_task_runner_.get()) {
- // Check that all tests stop posting tasks.
- mock_task_runner_->SetAutoAdvanceNowToPendingTasks(true);
- while (mock_task_runner_->RunUntilIdle()) {
- }
- } else {
- base::RunLoop().RunUntilIdle();
- }
+ base::RunLoop().RunUntilIdle();
scheduler_.reset();
}
- void RunUntilIdle() {
- // Only one of mock_task_runner_ or message_loop_ should be set.
- DCHECK(!mock_task_runner_.get() || !message_loop_.get());
- if (mock_task_runner_.get()) {
- mock_task_runner_->RunUntilIdle();
- } else {
- base::RunLoop().RunUntilIdle();
- }
+ virtual base::TimeTicks Now() {
+ CHECK(test_task_runner_);
+ return test_task_runner_->GetMockTickClock()->NowTicks();
+ }
+
+ void AdvanceMockTickClockTo(base::TimeTicks time) {
+ CHECK(test_task_runner_);
+ CHECK_LE(Now(), time);
+ test_task_runner_->AdvanceMockTickClock(time - Now());
+ }
+
+ void AdvanceMockTickClockBy(base::TimeDelta delta) {
+ CHECK(test_task_runner_);
+ CHECK_LE(base::TimeDelta(), delta);
+ test_task_runner_->AdvanceMockTickClock(delta);
}
void DoMainFrame() {
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
viz::BeginFrameArgs::NORMAL);
begin_frame_args.on_critical_path = false;
@@ -365,39 +396,36 @@ class MainThreadSchedulerImplTest : public testing::Test {
void DoMainFrameOnCriticalPath() {
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
viz::BeginFrameArgs::NORMAL);
begin_frame_args.on_critical_path = true;
scheduler_->WillBeginFrame(begin_frame_args);
}
- void ForceTouchStartToBeExpectedSoon() {
+ void ForceBlockingInputToBeExpectedSoon() {
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kGestureScrollUpdate),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kGestureScrollEnd),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- clock_.Advance(priority_escalation_after_input_duration() * 2);
+ test_task_runner_->AdvanceMockTickClock(
+ priority_escalation_after_input_duration() * 2);
scheduler_->ForceUpdatePolicy();
}
void SimulateExpensiveTasks(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
- // RunUntilIdle won't actually run all of the SimpleTestTickClock::Advance
- // tasks unless we set AutoAdvanceNow to true :/
- ScopedAutoAdvanceNowEnabler enable_auto_advance_now(mock_task_runner_);
-
- // Simulate a bunch of expensive tasks
+ // Simulate a bunch of expensive tasks.
for (int i = 0; i < 10; i++) {
task_runner->PostTask(
- FROM_HERE, base::BindOnce(&base::SimpleTestTickClock::Advance,
- base::Unretained(&clock_),
- base::TimeDelta::FromMilliseconds(500)));
+ FROM_HERE,
+ base::BindOnce(&base::TestMockTimeTaskRunner::AdvanceMockTickClock,
+ test_task_runner_,
+ base::TimeDelta::FromMilliseconds(500)));
}
-
- RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
}
enum class TouchEventPolicy {
@@ -408,7 +436,7 @@ class MainThreadSchedulerImplTest : public testing::Test {
void SimulateCompositorGestureStart(TouchEventPolicy touch_event_policy) {
if (touch_event_policy == TouchEventPolicy::kSendTouchStart) {
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kTouchMove),
@@ -431,7 +459,7 @@ class MainThreadSchedulerImplTest : public testing::Test {
// driven gesture.
void SimulateMainThreadGestureWithoutScrollUpdates() {
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kTouchMove),
@@ -450,7 +478,7 @@ class MainThreadSchedulerImplTest : public testing::Test {
// scheduled.
void SimulateMainThreadGestureWithoutPreventDefault() {
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
// Touchstart policy update.
@@ -495,10 +523,10 @@ class MainThreadSchedulerImplTest : public testing::Test {
blink::WebInputEvent::Type gesture_type) {
if (touch_event_policy == TouchEventPolicy::kSendTouchStart) {
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
scheduler_->DidHandleInputEventOnMainThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
WebInputEventResult::kHandledSystem);
scheduler_->DidHandleInputEventOnCompositorThread(
@@ -529,7 +557,7 @@ class MainThreadSchedulerImplTest : public testing::Test {
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kTouchMove),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
- clock_.Advance(begin_main_frame_duration);
+ test_task_runner_->AdvanceMockTickClock(begin_main_frame_duration);
scheduler_->DidHandleInputEventOnMainThread(
FakeInputEvent(blink::WebInputEvent::kTouchMove),
WebInputEventResult::kHandledApplication);
@@ -538,17 +566,18 @@ class MainThreadSchedulerImplTest : public testing::Test {
void SimulateMainThreadCompositorTask(
base::TimeDelta begin_main_frame_duration) {
- clock_.Advance(begin_main_frame_duration);
+ test_task_runner_->AdvanceMockTickClock(begin_main_frame_duration);
scheduler_->DidCommitFrameToCompositor();
- simulate_compositor_task_ran_ = true;
}
- bool SimulatedCompositorTaskPending() const {
- return !simulate_compositor_task_ran_;
+ void SimulateMainThreadCompositorAndQuitRunLoopTask(
+ base::TimeDelta begin_main_frame_duration) {
+ SimulateMainThreadCompositorTask(begin_main_frame_duration);
+ base::RunLoop().Quit();
}
void SimulateTimerTask(base::TimeDelta duration) {
- clock_.Advance(duration);
+ test_task_runner_->AdvanceMockTickClock(duration);
simulate_timer_task_ran_ = true;
}
@@ -571,8 +600,8 @@ class MainThreadSchedulerImplTest : public testing::Test {
return scheduler_->main_thread_only().begin_frame_not_expected_soon;
}
- bool TouchStartExpectedSoon() {
- return scheduler_->main_thread_only().touchstart_expected_soon;
+ bool BlockingInputExpectedSoon() {
+ return scheduler_->main_thread_only().blocking_input_expected_soon;
}
bool HaveSeenABeginMainframe() {
@@ -591,13 +620,33 @@ class MainThreadSchedulerImplTest : public testing::Test {
return scheduler_->main_thread_only().estimated_next_frame_begin;
}
- void AdvanceTimeWithTask(double duration) {
- base::TimeTicks start = clock_.NowTicks();
- scheduler_->OnTaskStarted(fake_queue_.get(), fake_task_, start);
- clock_.Advance(base::TimeDelta::FromSecondsD(duration));
- base::TimeTicks end = clock_.NowTicks();
- scheduler_->OnTaskCompleted(fake_queue_.get(), fake_task_, start, end,
- base::nullopt);
+ bool HaveSeenABlockingGesture() {
+ base::AutoLock lock(scheduler_->any_thread_lock_);
+ return scheduler_->any_thread().have_seen_a_blocking_gesture;
+ }
+
+ void AdvanceTimeWithTask(double duration_seconds) {
+ base::TimeDelta duration = base::TimeDelta::FromSecondsD(duration_seconds);
+ RunTask(base::BindOnce(
+ [](scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner,
+ base::TimeDelta duration) {
+ test_task_runner->AdvanceMockTickClock(duration);
+ },
+ test_task_runner_, duration));
+ }
+
+ void RunTask(base::OnceClosure task) {
+ scoped_refptr<MainThreadTaskQueue> fake_queue =
+ scheduler_->NewLoadingTaskQueue(
+ MainThreadTaskQueue::QueueType::kFrameLoading, nullptr);
+
+ base::TimeTicks start = Now();
+ scheduler_->OnTaskStarted(fake_queue.get(), FakeTask(),
+ FakeTaskTiming(start, base::TimeTicks()));
+ std::move(task).Run();
+ base::TimeTicks end = Now();
+ scheduler_->OnTaskCompleted(fake_queue.get(), FakeTask(),
+ FakeTaskTiming(start, end));
}
void RunSlowCompositorTask() {
@@ -608,7 +657,7 @@ class MainThreadSchedulerImplTest : public testing::Test {
base::BindOnce(
&MainThreadSchedulerImplTest::SimulateMainThreadCompositorTask,
base::Unretained(this), base::TimeDelta::FromMilliseconds(1000)));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
// Helper for posting several tasks of specific types. |task_descriptor| is a
@@ -696,11 +745,6 @@ class MainThreadSchedulerImplTest : public testing::Test {
MainThreadSchedulerImpl::kEndIdleWhenHiddenDelayMillis);
}
- static base::TimeDelta delay_for_background_tab_freezing() {
- return base::TimeDelta::FromMilliseconds(
- MainThreadSchedulerImpl::kDelayForBackgroundTabFreezingMillis);
- }
-
static base::TimeDelta rails_response_time() {
return base::TimeDelta::FromMilliseconds(
MainThreadSchedulerImpl::kRailsResponseTimeMillis);
@@ -721,20 +765,23 @@ class MainThreadSchedulerImplTest : public testing::Test {
&MainThreadSchedulerImpl::UseCaseToString);
}
- static scoped_refptr<TaskQueue> ThrottableTaskQueue(
+ static scoped_refptr<TaskQueue> ThrottleableTaskQueue(
FrameSchedulerImpl* scheduler) {
return scheduler->ThrottleableTaskQueue();
}
+ QueueingTimeEstimator* queueing_time_estimator() {
+ return &scheduler_->queueing_time_estimator_;
+ }
+
base::test::ScopedFeatureList feature_list_;
- base::SimpleTestTickClock clock_;
- TaskQueue::Task fake_task_;
- scoped_refptr<MainThreadTaskQueue> fake_queue_;
- // Only one of mock_task_runner_ or message_loop_ will be set.
- scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
- std::unique_ptr<base::MessageLoop> message_loop_;
+
+ scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_;
std::unique_ptr<MainThreadSchedulerImplForTest> scheduler_;
+ std::unique_ptr<PageSchedulerImpl> page_scheduler_;
+ std::unique_ptr<FrameSchedulerImpl> main_frame_scheduler_;
+
scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> input_task_runner_;
@@ -744,7 +791,6 @@ class MainThreadSchedulerImplTest : public testing::Test {
scoped_refptr<TaskQueue> timer_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> v8_task_runner_;
bool simulate_timer_task_ran_;
- bool simulate_compositor_task_ran_;
uint64_t next_begin_frame_number_ = viz::BeginFrameArgs::kStartingFrameNumber;
DISALLOW_COPY_AND_ASSIGN(MainThreadSchedulerImplTest);
@@ -754,7 +800,7 @@ TEST_F(MainThreadSchedulerImplTest, TestPostDefaultTask) {
std::vector<std::string> run_order;
PostTestTasks(&run_order, "D1 D2 D3 D4");
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("D1"), std::string("D2"),
std::string("D3"), std::string("D4")));
@@ -763,7 +809,7 @@ TEST_F(MainThreadSchedulerImplTest, TestPostDefaultTask) {
TEST_F(MainThreadSchedulerImplTest, TestPostDefaultAndCompositor) {
std::vector<std::string> run_order;
PostTestTasks(&run_order, "D1 C1 P1");
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order, testing::Contains("D1"));
EXPECT_THAT(run_order, testing::Contains("C1"));
EXPECT_THAT(run_order, testing::Contains("P1"));
@@ -776,7 +822,7 @@ TEST_F(MainThreadSchedulerImplTest, TestRentrantTask) {
FROM_HERE, base::BindOnce(AppendToVectorReentrantTask,
base::RetainedRef(default_task_runner_),
&run_order, &count, 5));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order, testing::ElementsAre(0, 1, 2, 3, 4));
}
@@ -784,35 +830,38 @@ TEST_F(MainThreadSchedulerImplTest, TestRentrantTask) {
TEST_F(MainThreadSchedulerImplTest, TestPostIdleTask) {
int run_count = 0;
base::TimeTicks expected_deadline =
- clock_.NowTicks() + base::TimeDelta::FromMilliseconds(2300);
+ Now() + base::TimeDelta::FromMilliseconds(2300);
base::TimeTicks deadline_in_task;
- clock_.Advance(base::TimeDelta::FromMilliseconds(100));
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMilliseconds(100));
idle_task_runner_->PostIdleTask(
FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, run_count); // Shouldn't run yet as no WillBeginFrame.
scheduler_->WillBeginFrame(viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(1000),
viz::BeginFrameArgs::NORMAL));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, run_count); // Shouldn't run as no DidCommitFrameToCompositor.
- clock_.Advance(base::TimeDelta::FromMilliseconds(1200));
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMilliseconds(1200));
scheduler_->DidCommitFrameToCompositor();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, run_count); // We missed the deadline.
scheduler_->WillBeginFrame(viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(1000),
viz::BeginFrameArgs::NORMAL));
- clock_.Advance(base::TimeDelta::FromMilliseconds(800));
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMilliseconds(800));
scheduler_->DidCommitFrameToCompositor();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, run_count);
EXPECT_EQ(expected_deadline, deadline_in_task);
}
@@ -826,37 +875,36 @@ TEST_F(MainThreadSchedulerImplTest, TestRepostingIdleTask) {
base::BindOnce(&RepostingIdleTestTask,
base::RetainedRef(idle_task_runner_), &run_count));
EnableIdleTasks();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, run_count);
// Reposted tasks shouldn't run until next idle period.
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, run_count);
EnableIdleTasks();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(2, run_count);
}
TEST_F(MainThreadSchedulerImplTest, TestIdleTaskExceedsDeadline) {
- ScopedAutoAdvanceNowEnabler enable_auto_advance_now(mock_task_runner_);
int run_count = 0;
// Post two UpdateClockToDeadlineIdleTestTask tasks.
idle_task_runner_->PostIdleTask(
- FROM_HERE,
- base::BindOnce(&UpdateClockToDeadlineIdleTestTask, &clock_, &run_count));
+ FROM_HERE, base::BindOnce(&UpdateClockToDeadlineIdleTestTask,
+ test_task_runner_, &run_count));
idle_task_runner_->PostIdleTask(
- FROM_HERE,
- base::BindOnce(&UpdateClockToDeadlineIdleTestTask, &clock_, &run_count));
+ FROM_HERE, base::BindOnce(&UpdateClockToDeadlineIdleTestTask,
+ test_task_runner_, &run_count));
EnableIdleTasks();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Only the first idle task should execute since it's used up the deadline.
EXPECT_EQ(1, run_count);
EnableIdleTasks();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Second task should be run on the next idle period.
EXPECT_EQ(2, run_count);
}
@@ -870,33 +918,33 @@ TEST_F(MainThreadSchedulerImplTest, TestDelayedEndIdlePeriodCanceled) {
// Trigger the beginning of an idle period for 1000ms.
scheduler_->WillBeginFrame(viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(1000),
viz::BeginFrameArgs::NORMAL));
DoMainFrame();
// End the idle period early (after 500ms), and send a WillBeginFrame which
// specifies that the next idle period should end 1000ms from now.
- clock_.Advance(base::TimeDelta::FromMilliseconds(500));
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMilliseconds(500));
scheduler_->WillBeginFrame(viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(1000),
viz::BeginFrameArgs::NORMAL));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, run_count); // Not currently in an idle period.
// Trigger the start of the idle period before the task to end the previous
// idle period has been triggered.
- clock_.Advance(base::TimeDelta::FromMilliseconds(400));
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMilliseconds(400));
scheduler_->DidCommitFrameToCompositor();
// Post a task which simulates running until after the previous end idle
// period delayed task was scheduled for
scheduler_->DefaultTaskQueue()->PostTask(FROM_HERE, base::BindOnce(NullTask));
- clock_.Advance(base::TimeDelta::FromMilliseconds(300));
-
- RunUntilIdle();
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(300));
EXPECT_EQ(1, run_count); // We should still be in the new idle period.
}
@@ -905,8 +953,10 @@ TEST_F(MainThreadSchedulerImplTest, TestDefaultPolicy) {
PostTestTasks(&run_order, "L1 I1 D1 P1 C1 D2 P2 C2");
EnableIdleTasks();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// High-priority input is enabled and input tasks are processed first.
+ // One compositing event is prioritized after an input event but still
+ // has lower priority than input event.
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("P1"), std::string("P2"),
std::string("L1"), std::string("D1"),
@@ -922,7 +972,7 @@ TEST_F(MainThreadSchedulerImplTest, TestDefaultPolicyWithSlowCompositor) {
PostTestTasks(&run_order, "L1 I1 D1 C1 P1 D2 C2");
EnableIdleTasks();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Even with slow compositor input tasks are handled first.
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("P1"), std::string("L1"),
@@ -940,7 +990,7 @@ TEST_F(MainThreadSchedulerImplTest,
scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
EnableIdleTasks();
SimulateCompositorGestureStart(TouchEventPolicy::kSendTouchStart);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("L1"), std::string("D1"),
std::string("D2"), std::string("C1"),
@@ -956,7 +1006,7 @@ TEST_F(MainThreadSchedulerImplTest,
scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
EnableIdleTasks();
SimulateMainThreadGestureWithoutScrollUpdates();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("C1"), std::string("C2"),
std::string("L1"), std::string("D1"),
@@ -972,7 +1022,7 @@ TEST_F(MainThreadSchedulerImplTest,
scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
EnableIdleTasks();
SimulateMainThreadGestureWithoutPreventDefault();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("L1"), std::string("D1"),
std::string("D2"), std::string("C1"),
@@ -982,30 +1032,30 @@ TEST_F(MainThreadSchedulerImplTest,
TEST_F(MainThreadSchedulerImplTest,
TestCompositorPolicy_CompositorHandlesInput_LongGestureDuration) {
- scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
EnableIdleTasks();
SimulateCompositorGestureStart(TouchEventPolicy::kSendTouchStart);
base::TimeTicks loop_end_time =
- clock_.NowTicks() + base::TimeDelta::FromMilliseconds(
- UserModel::kMedianGestureDurationMillis * 2);
+ Now() + base::TimeDelta::FromMilliseconds(
+ UserModel::kMedianGestureDurationMillis * 2);
// The UseCase::kCompositorGesture usecase initially deprioritizes
// compositor tasks (see
// TestCompositorPolicy_CompositorHandlesInput_WithTouchHandler) but if the
// gesture is long enough, compositor tasks get prioritized again.
- while (clock_.NowTicks() < loop_end_time) {
+ while (Now() < loop_end_time) {
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kTouchMove),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- clock_.Advance(base::TimeDelta::FromMilliseconds(16));
- RunUntilIdle();
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMilliseconds(16));
+ base::RunLoop().RunUntilIdle();
}
std::vector<std::string> run_order;
PostTestTasks(&run_order, "L1 I1 D1 C1 D2 C2");
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("C1"), std::string("C2"),
std::string("L1"), std::string("D1"),
@@ -1020,7 +1070,7 @@ TEST_F(MainThreadSchedulerImplTest,
EnableIdleTasks();
SimulateCompositorGestureStart(TouchEventPolicy::kDontSendTouchStart);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("L1"), std::string("D1"),
std::string("D2"), std::string("C1"),
@@ -1037,7 +1087,7 @@ TEST_F(MainThreadSchedulerImplTest,
EnableIdleTasks();
SimulateMainThreadGestureStart(TouchEventPolicy::kSendTouchStart,
blink::WebInputEvent::kGestureScrollBegin);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("C1"), std::string("C2"),
std::string("L1"), std::string("D1"),
@@ -1056,7 +1106,7 @@ TEST_F(MainThreadSchedulerImplTest,
EnableIdleTasks();
SimulateMainThreadGestureStart(TouchEventPolicy::kDontSendTouchStart,
blink::WebInputEvent::kGestureScrollBegin);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("C1"), std::string("C2"),
std::string("L1"), std::string("D1"),
@@ -1075,12 +1125,12 @@ TEST_F(MainThreadSchedulerImplTest,
scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
EnableIdleTasks();
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
scheduler_->DidHandleInputEventOnMainThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
WebInputEventResult::kHandledApplication);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Because the main thread is performing custom input handling, we let all
// tasks run. However compositing tasks are still given priority.
EXPECT_THAT(run_order,
@@ -1099,12 +1149,12 @@ TEST_F(
scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
EnableIdleTasks();
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
scheduler_->DidHandleInputEventOnMainThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
WebInputEventResult::kHandledSystem);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Because we are still waiting for the touchstart to be processed,
// non-essential tasks like loading tasks are blocked.
EXPECT_THAT(run_order,
@@ -1125,7 +1175,7 @@ TEST_F(MainThreadSchedulerImplTest, TestCompositorPolicy_DidAnimateForInput) {
EXPECT_EQ(UseCase::kCompositorGesture,
ForceUpdatePolicyAndGetCurrentUseCase());
EnableIdleTasks();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("D1"), std::string("D2"),
std::string("C1"), std::string("C2"),
@@ -1147,7 +1197,7 @@ TEST_F(MainThreadSchedulerImplTest, Navigation_ResetsTaskCostEstimations) {
PostTestTasks(&run_order, "C1 T1");
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("C1"), std::string("T1")));
@@ -1165,8 +1215,8 @@ TEST_F(MainThreadSchedulerImplTest,
PostTestTasks(&run_order, "C1 T1");
- RunUntilIdle();
- EXPECT_FALSE(TouchStartExpectedSoon());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(BlockingInputExpectedSoon());
EXPECT_EQ(UseCase::kMainThreadGesture, CurrentUseCase());
EXPECT_THAT(run_order, testing::ElementsAre(std::string("C1")));
@@ -1184,8 +1234,8 @@ TEST_F(MainThreadSchedulerImplTest,
PostTestTasks(&run_order, "C1 T1");
- RunUntilIdle();
- EXPECT_FALSE(TouchStartExpectedSoon());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(BlockingInputExpectedSoon());
EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
EXPECT_THAT(run_order,
@@ -1204,8 +1254,8 @@ TEST_F(MainThreadSchedulerImplTest,
PostTestTasks(&run_order, "C1 T1");
- RunUntilIdle();
- EXPECT_FALSE(TouchStartExpectedSoon());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(BlockingInputExpectedSoon());
EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
EXPECT_THAT(run_order,
@@ -1219,10 +1269,10 @@ TEST_F(MainThreadSchedulerImplTest, TestTouchstartPolicy_Compositor) {
// Observation of touchstart should defer execution of timer, idle and loading
// tasks.
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
EnableIdleTasks();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("C1"), std::string("C2"),
std::string("D1"), std::string("D2")));
@@ -1237,7 +1287,7 @@ TEST_F(MainThreadSchedulerImplTest, TestTouchstartPolicy_Compositor) {
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kGestureTapDown),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order, testing::ElementsAre());
// Action events like ScrollBegin will kick us back into compositor priority,
@@ -1246,7 +1296,7 @@ TEST_F(MainThreadSchedulerImplTest, TestTouchstartPolicy_Compositor) {
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kGestureScrollBegin),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("L1"), std::string("T1"),
@@ -1260,13 +1310,13 @@ TEST_F(MainThreadSchedulerImplTest, TestTouchstartPolicy_MainThread) {
// Observation of touchstart should defer execution of timer, idle and loading
// tasks.
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
scheduler_->DidHandleInputEventOnMainThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
WebInputEventResult::kHandledSystem);
EnableIdleTasks();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("C1"), std::string("C2"),
std::string("D1"), std::string("D2")));
@@ -1285,7 +1335,7 @@ TEST_F(MainThreadSchedulerImplTest, TestTouchstartPolicy_MainThread) {
scheduler_->DidHandleInputEventOnMainThread(
FakeInputEvent(blink::WebInputEvent::kGestureTapDown),
WebInputEventResult::kHandledSystem);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order, testing::ElementsAre());
// Action events like ScrollBegin will kick us back into compositor priority,
@@ -1297,7 +1347,7 @@ TEST_F(MainThreadSchedulerImplTest, TestTouchstartPolicy_MainThread) {
scheduler_->DidHandleInputEventOnMainThread(
FakeInputEvent(blink::WebInputEvent::kGestureScrollBegin),
WebInputEventResult::kHandledSystem);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("L1"), std::string("T1"),
@@ -1312,7 +1362,7 @@ TEST_F(MainThreadSchedulerImplTest, DISABLED_LoadingUseCase) {
scheduler_->DidStartProvisionalLoad(true);
EnableIdleTasks();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// In loading policy, loading tasks are prioritized other others.
std::string loading_policy_expected[] = {
@@ -1325,11 +1375,12 @@ TEST_F(MainThreadSchedulerImplTest, DISABLED_LoadingUseCase) {
// Advance 15s and try again, the loading policy should have ended and the
// task order should return to the NONE use case where loading tasks are no
// longer prioritized.
- clock_.Advance(base::TimeDelta::FromMilliseconds(150000));
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMilliseconds(150000));
run_order.clear();
PostTestTasks(&run_order, "I1 D1 C1 T1 L1 D2 C2 T2 L2");
EnableIdleTasks();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
std::string default_order_expected[] = {
std::string("D1"), std::string("C1"), std::string("T1"),
@@ -1350,7 +1401,7 @@ TEST_F(MainThreadSchedulerImplTest,
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kMouseMove),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Note compositor tasks are not prioritized.
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
EXPECT_THAT(run_order,
@@ -1370,7 +1421,7 @@ TEST_F(MainThreadSchedulerImplTest,
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kMouseMove),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Note compositor tasks are not prioritized.
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
EXPECT_THAT(run_order,
@@ -1391,7 +1442,7 @@ TEST_F(MainThreadSchedulerImplTest,
FakeInputEvent(blink::WebInputEvent::kMouseMove,
blink::WebInputEvent::kLeftButtonDown),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Note compositor tasks deprioritized.
EXPECT_EQ(UseCase::kCompositorGesture, CurrentUseCase());
EXPECT_THAT(run_order,
@@ -1410,7 +1461,7 @@ TEST_F(MainThreadSchedulerImplTest,
FakeInputEvent(blink::WebInputEvent::kMouseMove,
blink::WebInputEvent::kLeftButtonDown),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Note compositor tasks are prioritized.
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("C1"), std::string("C2"),
@@ -1427,8 +1478,8 @@ TEST_F(MainThreadSchedulerImplTest,
// Simulate a main thread driven mouse wheel scroll gesture.
SimulateMainThreadGestureStart(TouchEventPolicy::kSendTouchStart,
blink::WebInputEvent::kGestureScrollUpdate);
- RunUntilIdle();
- EXPECT_FALSE(TouchStartExpectedSoon());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(BlockingInputExpectedSoon());
EXPECT_EQ(UseCase::kMainThreadGesture, CurrentUseCase());
// Now start a main thread mouse touch gesture. It should be detected as main
@@ -1445,7 +1496,7 @@ TEST_F(MainThreadSchedulerImplTest,
FakeInputEvent(blink::WebInputEvent::kMouseMove,
blink::WebInputEvent::kLeftButtonDown),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
@@ -1472,7 +1523,7 @@ TEST_F(MainThreadSchedulerImplTest, EventForwardedToMainThread_MouseClick) {
FakeInputEvent(blink::WebInputEvent::kMouseUp,
blink::WebInputEvent::kLeftButtonDown),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
@@ -1490,9 +1541,9 @@ TEST_F(MainThreadSchedulerImplTest,
EnableIdleTasks();
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kMouseWheel),
+ FakeMouseWheelEvent(blink::WebInputEvent::kMouseWheel),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Note compositor tasks are not prioritized.
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("D1"), std::string("D2"),
@@ -1508,9 +1559,9 @@ TEST_F(MainThreadSchedulerImplTest,
EnableIdleTasks();
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kMouseWheel),
+ FakeMouseWheelEvent(blink::WebInputEvent::kMouseWheel),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Note compositor tasks are prioritized (since they are fast).
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("C1"), std::string("C2"),
@@ -1526,7 +1577,7 @@ TEST_F(MainThreadSchedulerImplTest,
EnableIdleTasks();
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kMouseWheel),
+ FakeMouseWheelEvent(blink::WebInputEvent::kMouseWheel),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kGestureScrollBegin),
@@ -1537,7 +1588,7 @@ TEST_F(MainThreadSchedulerImplTest,
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kGestureScrollUpdate),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Note compositor tasks are prioritized.
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("C1"), std::string("C2"),
@@ -1554,7 +1605,7 @@ TEST_F(
EnableIdleTasks();
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kMouseWheel),
+ FakeMouseWheelEvent(blink::WebInputEvent::kMouseWheel),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kGestureScrollBegin),
@@ -1565,7 +1616,7 @@ TEST_F(
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kGestureScrollUpdate),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Note compositor tasks are not prioritized.
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("D1"), std::string("D2"),
@@ -1585,7 +1636,7 @@ TEST_F(MainThreadSchedulerImplTest,
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kKeyDown),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Note compositor tasks are not prioritized.
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("D1"), std::string("C1"),
@@ -1605,7 +1656,7 @@ TEST_F(MainThreadSchedulerImplTest,
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kKeyDown),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Note compositor tasks are not prioritized.
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("D1"), std::string("C1"),
@@ -1635,7 +1686,7 @@ TEST_F(MainThreadSchedulerImplTest,
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kGestureFlingStart),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Ensure that the default D1 task gets to run at some point before the final
// C2 compositor task.
EXPECT_THAT(run_order,
@@ -1649,7 +1700,7 @@ TEST_F(MainThreadSchedulerImplTest,
EXPECT_EQ(UseCase::kCompositorGesture,
ForceUpdatePolicyAndGetCurrentUseCase());
- clock_.Advance(base::TimeDelta::FromMilliseconds(1000));
+ test_task_runner_->AdvanceMockTickClock(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(UseCase::kNone, ForceUpdatePolicyAndGetCurrentUseCase());
}
@@ -1660,7 +1711,7 @@ TEST_F(MainThreadSchedulerImplTest,
EXPECT_EQ(UseCase::kMainThreadCustomInputHandling,
ForceUpdatePolicyAndGetCurrentUseCase());
- clock_.Advance(base::TimeDelta::FromMilliseconds(1000));
+ test_task_runner_->AdvanceMockTickClock(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(UseCase::kNone, ForceUpdatePolicyAndGetCurrentUseCase());
}
@@ -1669,22 +1720,22 @@ TEST_F(MainThreadSchedulerImplTest, TestTouchstartPolicyEndsAfterTimeout) {
PostTestTasks(&run_order, "L1 D1 C1 D2 C2");
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("C1"), std::string("C2"),
std::string("D1"), std::string("D2")));
run_order.clear();
- clock_.Advance(base::TimeDelta::FromMilliseconds(1000));
+ test_task_runner_->AdvanceMockTickClock(base::TimeDelta::FromSeconds(1));
// Don't post any compositor tasks to simulate a very long running event
// handler.
PostTestTasks(&run_order, "D1 D2");
// Touchstart policy mode should have ended now that the clock has advanced.
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("L1"), std::string("D1"),
std::string("D2")));
@@ -1697,9 +1748,9 @@ TEST_F(MainThreadSchedulerImplTest,
// Observation of touchstart should defer execution of idle and loading tasks.
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("C1"), std::string("C2"),
std::string("D1"), std::string("D2")));
@@ -1709,7 +1760,7 @@ TEST_F(MainThreadSchedulerImplTest,
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kTouchMove),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order, testing::ElementsAre());
// Receiving the second touchmove will kick us back into compositor priority.
@@ -1717,7 +1768,7 @@ TEST_F(MainThreadSchedulerImplTest,
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kTouchMove),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order, testing::ElementsAre(std::string("L1")));
}
@@ -1725,12 +1776,12 @@ TEST_F(MainThreadSchedulerImplTest, TestIsHighPriorityWorkAnticipated) {
bool is_anticipated_before = false;
bool is_anticipated_after = false;
- scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
+ scheduler_->SetHaveSeenABlockingGestureForTesting(true);
default_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&AnticipationTestTask, scheduler_.get(),
SimulateInputType::kNone,
&is_anticipated_before, &is_anticipated_after));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// In its default state, without input receipt, the scheduler should indicate
// that no high-priority is anticipated.
EXPECT_FALSE(is_anticipated_before);
@@ -1753,36 +1804,38 @@ TEST_F(MainThreadSchedulerImplTest, TestIsHighPriorityWorkAnticipated) {
base::BindOnce(&AnticipationTestTask, scheduler_.get(),
SimulateInputType::kGestureScrollEnd, &dummy, &dummy));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// When input is received, the scheduler should indicate that high-priority
// work is anticipated.
EXPECT_FALSE(is_anticipated_before);
EXPECT_TRUE(is_anticipated_after);
- clock_.Advance(priority_escalation_after_input_duration() * 2);
+ test_task_runner_->AdvanceMockTickClock(
+ priority_escalation_after_input_duration() * 2);
default_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&AnticipationTestTask, scheduler_.get(),
SimulateInputType::kNone,
&is_anticipated_before, &is_anticipated_after));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Without additional input, the scheduler should go into NONE
// use case but with scrolling expected where high-priority work is still
// anticipated.
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
- EXPECT_TRUE(TouchStartExpectedSoon());
+ EXPECT_TRUE(BlockingInputExpectedSoon());
EXPECT_TRUE(is_anticipated_before);
EXPECT_TRUE(is_anticipated_after);
- clock_.Advance(subsequent_input_expected_after_input_duration() * 2);
+ test_task_runner_->AdvanceMockTickClock(
+ subsequent_input_expected_after_input_duration() * 2);
default_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&AnticipationTestTask, scheduler_.get(),
SimulateInputType::kNone,
&is_anticipated_before, &is_anticipated_after));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Eventually the scheduler should go into the default use case where
// high-priority work is no longer anticipated.
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
- EXPECT_FALSE(TouchStartExpectedSoon());
+ EXPECT_FALSE(BlockingInputExpectedSoon());
EXPECT_FALSE(is_anticipated_before);
EXPECT_FALSE(is_anticipated_after);
}
@@ -1795,7 +1848,7 @@ TEST_F(MainThreadSchedulerImplTest, TestShouldYield) {
FROM_HERE, base::BindOnce(&PostingYieldingTestTask, scheduler_.get(),
base::RetainedRef(default_task_runner_), false,
&should_yield_before, &should_yield_after));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Posting to default runner shouldn't cause yielding.
EXPECT_FALSE(should_yield_before);
EXPECT_FALSE(should_yield_after);
@@ -1805,7 +1858,7 @@ TEST_F(MainThreadSchedulerImplTest, TestShouldYield) {
base::BindOnce(&PostingYieldingTestTask, scheduler_.get(),
base::RetainedRef(compositor_task_runner_), false,
&should_yield_before, &should_yield_after));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Posting while not mainthread scrolling shouldn't cause yielding.
EXPECT_FALSE(should_yield_before);
EXPECT_FALSE(should_yield_after);
@@ -1815,7 +1868,7 @@ TEST_F(MainThreadSchedulerImplTest, TestShouldYield) {
base::BindOnce(&PostingYieldingTestTask, scheduler_.get(),
base::RetainedRef(compositor_task_runner_), true,
&should_yield_before, &should_yield_after));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// We should be able to switch to compositor priority mid-task.
EXPECT_FALSE(should_yield_before);
EXPECT_TRUE(should_yield_after);
@@ -1826,10 +1879,10 @@ TEST_F(MainThreadSchedulerImplTest, TestShouldYield_TouchStart) {
// there's no immediately pending work in the compositor queue.
EXPECT_FALSE(scheduler_->ShouldYieldForHighPriorityWork());
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
EXPECT_TRUE(scheduler_->ShouldYieldForHighPriorityWork());
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
TEST_F(MainThreadSchedulerImplTest, SlowMainThreadInputEvent) {
@@ -1839,217 +1892,178 @@ TEST_F(MainThreadSchedulerImplTest, SlowMainThreadInputEvent) {
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kGestureFlingStart),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
// Simulate the input event being queued for a very long time. The compositor
// task we post here represents the enqueued input task.
- clock_.Advance(priority_escalation_after_input_duration() * 2);
+ test_task_runner_->AdvanceMockTickClock(
+ priority_escalation_after_input_duration() * 2);
scheduler_->DidHandleInputEventOnMainThread(
FakeInputEvent(blink::WebInputEvent::kGestureFlingStart),
WebInputEventResult::kHandledSystem);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Even though we exceeded the input priority escalation period, we should
// still be in main thread gesture since the input remains queued.
EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
// After the escalation period ends we should go back into normal mode.
- clock_.Advance(priority_escalation_after_input_duration() * 2);
- RunUntilIdle();
+ test_task_runner_->FastForwardBy(priority_escalation_after_input_duration() *
+ 2);
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
}
-class MainThreadSchedulerImplWithMockSchedulerTest
- : public MainThreadSchedulerImplTest {
- public:
- void SetUp() override {
- mock_task_runner_ =
- base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, false);
- mock_scheduler_ = new MainThreadSchedulerImplForTest(
- base::sequence_manager::TaskQueueManagerForTest::Create(
- nullptr, mock_task_runner_, &clock_),
- base::nullopt);
- Initialize(base::WrapUnique(mock_scheduler_));
+TEST_F(MainThreadSchedulerImplTest, OnlyOnePendingUrgentPolicyUpdate) {
+ for (int i = 0; i < 4; i++) {
+ scheduler_->EnsureUrgentPolicyUpdatePostedOnMainThread();
}
-
- protected:
- MainThreadSchedulerImplForTest* mock_scheduler_;
-};
-
-TEST_F(MainThreadSchedulerImplWithMockSchedulerTest,
- OnlyOnePendingUrgentPolicyUpdatey) {
- mock_scheduler_->EnsureUrgentPolicyUpdatePostedOnMainThread();
- mock_scheduler_->EnsureUrgentPolicyUpdatePostedOnMainThread();
- mock_scheduler_->EnsureUrgentPolicyUpdatePostedOnMainThread();
- mock_scheduler_->EnsureUrgentPolicyUpdatePostedOnMainThread();
-
- RunUntilIdle();
-
- EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, scheduler_->update_policy_count_);
}
-TEST_F(MainThreadSchedulerImplWithMockSchedulerTest,
- OnePendingDelayedAndOneUrgentUpdatePolicy) {
- ScopedAutoAdvanceNowEnabler enable_auto_advance_now(mock_task_runner_);
-
- mock_scheduler_->ScheduleDelayedPolicyUpdate(
- clock_.NowTicks(), base::TimeDelta::FromMilliseconds(1));
- mock_scheduler_->EnsureUrgentPolicyUpdatePostedOnMainThread();
-
- RunUntilIdle();
+TEST_F(MainThreadSchedulerImplTest, OnePendingDelayedAndOneUrgentUpdatePolicy) {
+ scheduler_->ScheduleDelayedPolicyUpdate(Now(),
+ base::TimeDelta::FromMilliseconds(1));
+ scheduler_->EnsureUrgentPolicyUpdatePostedOnMainThread();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
// We expect both the urgent and the delayed updates to run.
- EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
+ EXPECT_EQ(2, scheduler_->update_policy_count_);
}
-TEST_F(MainThreadSchedulerImplWithMockSchedulerTest,
- OneUrgentAndOnePendingDelayedUpdatePolicy) {
- ScopedAutoAdvanceNowEnabler enable_auto_advance_now(mock_task_runner_);
-
- mock_scheduler_->EnsureUrgentPolicyUpdatePostedOnMainThread();
- mock_scheduler_->ScheduleDelayedPolicyUpdate(
- clock_.NowTicks(), base::TimeDelta::FromMilliseconds(1));
-
- RunUntilIdle();
+TEST_F(MainThreadSchedulerImplTest, OneUrgentAndOnePendingDelayedUpdatePolicy) {
+ scheduler_->EnsureUrgentPolicyUpdatePostedOnMainThread();
+ scheduler_->ScheduleDelayedPolicyUpdate(Now(),
+ base::TimeDelta::FromMilliseconds(1));
+ test_task_runner_->FastForwardUntilNoTasksRemain();
// We expect both the urgent and the delayed updates to run.
- EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
+ EXPECT_EQ(2, scheduler_->update_policy_count_);
}
-TEST_F(MainThreadSchedulerImplWithMockSchedulerTest,
- UpdatePolicyCountTriggeredByOneInputEvent) {
+TEST_F(MainThreadSchedulerImplTest, UpdatePolicyCountTriggeredByOneInputEvent) {
// We expect DidHandleInputEventOnCompositorThread to post an urgent policy
// update.
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
- EXPECT_EQ(0, mock_scheduler_->update_policy_count_);
- mock_task_runner_->RunPendingTasks();
- EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
+ EXPECT_EQ(0, scheduler_->update_policy_count_);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, scheduler_->update_policy_count_);
scheduler_->DidHandleInputEventOnMainThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
WebInputEventResult::kHandledSystem);
- EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
-
- clock_.Advance(base::TimeDelta::FromMilliseconds(1000));
- RunUntilIdle();
+ EXPECT_EQ(1, scheduler_->update_policy_count_);
+ test_task_runner_->AdvanceMockTickClock(base::TimeDelta::FromSeconds(1));
+ base::RunLoop().RunUntilIdle();
// We finally expect a delayed policy update 100ms later.
- EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
+ EXPECT_EQ(2, scheduler_->update_policy_count_);
}
-TEST_F(MainThreadSchedulerImplWithMockSchedulerTest,
+TEST_F(MainThreadSchedulerImplTest,
UpdatePolicyCountTriggeredByThreeInputEvents) {
- // We expect DidHandleInputEventOnCompositorThread to post an urgent policy
- // update.
+ // We expect DidHandleInputEventOnCompositorThread to post
+ // an urgent policy update.
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart,
+ blink::WebInputEvent::kEventNonBlocking),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
- EXPECT_EQ(0, mock_scheduler_->update_policy_count_);
- mock_task_runner_->RunPendingTasks();
- EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
+ EXPECT_EQ(0, scheduler_->update_policy_count_);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, scheduler_->update_policy_count_);
scheduler_->DidHandleInputEventOnMainThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
WebInputEventResult::kHandledSystem);
- EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
+ EXPECT_EQ(1, scheduler_->update_policy_count_);
- // The second call to DidHandleInputEventOnCompositorThread should not post a
- // policy update because we are already in compositor priority.
+ // The second call to DidHandleInputEventOnCompositorThread should not post
+ // a policy update because we are already in compositor priority.
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kTouchMove),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
- mock_task_runner_->RunPendingTasks();
- EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, scheduler_->update_policy_count_);
// We expect DidHandleInputEvent to trigger a policy update.
scheduler_->DidHandleInputEventOnMainThread(
FakeInputEvent(blink::WebInputEvent::kTouchMove),
WebInputEventResult::kHandledSystem);
- EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
+ EXPECT_EQ(1, scheduler_->update_policy_count_);
// The third call to DidHandleInputEventOnCompositorThread should post a
// policy update because the awaiting_touch_start_response_ flag changed.
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kTouchMove),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
- EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
- mock_task_runner_->RunPendingTasks();
- EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
+ EXPECT_EQ(1, scheduler_->update_policy_count_);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(2, scheduler_->update_policy_count_);
// We expect DidHandleInputEvent to trigger a policy update.
scheduler_->DidHandleInputEventOnMainThread(
FakeInputEvent(blink::WebInputEvent::kTouchMove),
WebInputEventResult::kHandledSystem);
- EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
-
- clock_.Advance(base::TimeDelta::FromMilliseconds(1000));
- RunUntilIdle();
-
+ EXPECT_EQ(2, scheduler_->update_policy_count_);
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
// We finally expect a delayed policy update.
- EXPECT_EQ(3, mock_scheduler_->update_policy_count_);
+ EXPECT_EQ(3, scheduler_->update_policy_count_);
}
-TEST_F(MainThreadSchedulerImplWithMockSchedulerTest,
+TEST_F(MainThreadSchedulerImplTest,
UpdatePolicyCountTriggeredByTwoInputEventsWithALongSeparatingDelay) {
// We expect DidHandleInputEventOnCompositorThread to post an urgent policy
// update.
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart,
+ blink::WebInputEvent::kEventNonBlocking),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
- EXPECT_EQ(0, mock_scheduler_->update_policy_count_);
- mock_task_runner_->RunPendingTasks();
- EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
+ EXPECT_EQ(0, scheduler_->update_policy_count_);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1, scheduler_->update_policy_count_);
scheduler_->DidHandleInputEventOnMainThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
WebInputEventResult::kHandledSystem);
- EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
-
- clock_.Advance(base::TimeDelta::FromMilliseconds(1000));
- RunUntilIdle();
+ EXPECT_EQ(1, scheduler_->update_policy_count_);
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
// We expect a delayed policy update.
- EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
+ EXPECT_EQ(2, scheduler_->update_policy_count_);
// We expect the second call to DidHandleInputEventOnCompositorThread to post
// an urgent policy update because we are no longer in compositor priority.
scheduler_->DidHandleInputEventOnCompositorThread(
FakeInputEvent(blink::WebInputEvent::kTouchMove),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
- EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
- mock_task_runner_->RunPendingTasks();
- EXPECT_EQ(3, mock_scheduler_->update_policy_count_);
+ EXPECT_EQ(2, scheduler_->update_policy_count_);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(3, scheduler_->update_policy_count_);
scheduler_->DidHandleInputEventOnMainThread(
FakeInputEvent(blink::WebInputEvent::kTouchMove),
WebInputEventResult::kHandledSystem);
- EXPECT_EQ(3, mock_scheduler_->update_policy_count_);
-
- clock_.Advance(base::TimeDelta::FromMilliseconds(1000));
- RunUntilIdle();
-
+ EXPECT_EQ(3, scheduler_->update_policy_count_);
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
// We finally expect a delayed policy update.
- EXPECT_EQ(4, mock_scheduler_->update_policy_count_);
+ EXPECT_EQ(4, scheduler_->update_policy_count_);
}
-TEST_F(MainThreadSchedulerImplWithMockSchedulerTest,
- EnsureUpdatePolicyNotTriggeredTooOften) {
- ScopedAutoAdvanceNowEnabler enable_auto_advance_now(mock_task_runner_);
-
- EXPECT_EQ(0, mock_scheduler_->update_policy_count_);
+TEST_F(MainThreadSchedulerImplTest, EnsureUpdatePolicyNotTriggeredTooOften) {
+ EXPECT_EQ(0, scheduler_->update_policy_count_);
scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
- EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
+ EXPECT_EQ(1, scheduler_->update_policy_count_);
SimulateCompositorGestureStart(TouchEventPolicy::kSendTouchStart);
// We expect the first call to IsHighPriorityWorkAnticipated to be called
// after receiving an input event (but before the UpdateTask was processed) to
// call UpdatePolicy.
- EXPECT_EQ(1, mock_scheduler_->update_policy_count_);
+ EXPECT_EQ(1, scheduler_->update_policy_count_);
scheduler_->IsHighPriorityWorkAnticipated();
- EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
+ EXPECT_EQ(2, scheduler_->update_policy_count_);
// Subsequent calls should not call UpdatePolicy.
scheduler_->IsHighPriorityWorkAnticipated();
scheduler_->IsHighPriorityWorkAnticipated();
@@ -2067,7 +2081,7 @@ TEST_F(MainThreadSchedulerImplWithMockSchedulerTest,
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
scheduler_->DidHandleInputEventOnMainThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
WebInputEventResult::kHandledSystem);
scheduler_->DidHandleInputEventOnMainThread(
FakeInputEvent(blink::WebInputEvent::kTouchMove),
@@ -2079,27 +2093,54 @@ TEST_F(MainThreadSchedulerImplWithMockSchedulerTest,
FakeInputEvent(blink::WebInputEvent::kTouchEnd),
WebInputEventResult::kHandledSystem);
- EXPECT_EQ(2, mock_scheduler_->update_policy_count_);
+ EXPECT_EQ(2, scheduler_->update_policy_count_);
// We expect both the urgent and the delayed updates to run in addition to the
// earlier updated cause by IsHighPriorityWorkAnticipated, a final update
// transitions from 'not_scrolling touchstart expected' to 'not_scrolling'.
- RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_THAT(
- mock_scheduler_->use_cases_,
+ scheduler_->use_cases_,
testing::ElementsAre(
std::string("none"), std::string("compositor_gesture"),
- std::string("compositor_gesture touchstart expected"),
- std::string("none touchstart expected"), std::string("none")));
+ std::string("compositor_gesture blocking input expected"),
+ std::string("none blocking input expected"), std::string("none")));
+}
+
+TEST_F(MainThreadSchedulerImplTest,
+ BlockingInputExpectedSoonWhenBlockInputEventSeen) {
+ SimulateCompositorGestureStart(TouchEventPolicy::kSendTouchStart);
+ EXPECT_TRUE(HaveSeenABlockingGesture());
+ ForceBlockingInputToBeExpectedSoon();
+ EXPECT_TRUE(BlockingInputExpectedSoon());
+}
+
+TEST_F(MainThreadSchedulerImplTest,
+ BlockingInputNotExpectedSoonWhenNoBlockInputEventSeen) {
+ SimulateCompositorGestureStart(TouchEventPolicy::kDontSendTouchStart);
+ EXPECT_FALSE(HaveSeenABlockingGesture());
+ ForceBlockingInputToBeExpectedSoon();
+ EXPECT_FALSE(BlockingInputExpectedSoon());
}
class MainThreadSchedulerImplWithMessageLoopTest
: public MainThreadSchedulerImplTest {
public:
MainThreadSchedulerImplWithMessageLoopTest()
- : MainThreadSchedulerImplTest(new base::MessageLoop()) {}
+ : message_loop_(new base::MessageLoop()) {}
~MainThreadSchedulerImplWithMessageLoopTest() override = default;
+ void SetUp() override {
+ clock_.Advance(base::TimeDelta::FromMilliseconds(5));
+ Initialize(std::make_unique<MainThreadSchedulerImplForTest>(
+ base::sequence_manager::SequenceManagerForTest::Create(
+ message_loop_.get(), message_loop_->task_runner(), &clock_),
+ base::nullopt));
+ }
+
+ // Needed for EnableIdleTasks().
+ base::TimeTicks Now() override { return clock_.NowTicks(); }
+
void PostFromNestedRunloop(
std::vector<std::pair<SingleThreadIdleTaskRunner::IdleTask, bool>>*
tasks) {
@@ -2116,6 +2157,9 @@ class MainThreadSchedulerImplWithMessageLoopTest
}
private:
+ std::unique_ptr<base::MessageLoop> message_loop_;
+ base::SimpleTestTickClock clock_;
+
DISALLOW_COPY_AND_ASSIGN(MainThreadSchedulerImplWithMessageLoopTest);
};
@@ -2149,7 +2193,7 @@ TEST_F(MainThreadSchedulerImplWithMessageLoopTest,
base::Unretained(&tasks_to_post_from_nested_loop)));
EnableIdleTasks();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Note we expect task 3 to run last because it's non-nestable.
EXPECT_THAT(order, testing::ElementsAre(std::string("1"), std::string("2"),
std::string("4"), std::string("5"),
@@ -2158,47 +2202,46 @@ TEST_F(MainThreadSchedulerImplWithMessageLoopTest,
TEST_F(MainThreadSchedulerImplTest, TestBeginMainFrameNotExpectedUntil) {
base::TimeDelta ten_millis(base::TimeDelta::FromMilliseconds(10));
- base::TimeTicks expected_deadline = clock_.NowTicks() + ten_millis;
+ base::TimeTicks expected_deadline = Now() + ten_millis;
base::TimeTicks deadline_in_task;
int run_count = 0;
idle_task_runner_->PostIdleTask(
FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, run_count); // Shouldn't run yet as no idle period.
- base::TimeTicks now = clock_.NowTicks();
+ base::TimeTicks now = Now();
base::TimeTicks frame_time = now + ten_millis;
// No main frame is expected until frame_time, so short idle work can be
// scheduled in the mean time.
scheduler_->BeginMainFrameNotExpectedUntil(frame_time);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, run_count); // Should have run in a long idle time.
EXPECT_EQ(expected_deadline, deadline_in_task);
}
TEST_F(MainThreadSchedulerImplTest, TestLongIdlePeriod) {
- base::TimeTicks expected_deadline =
- clock_.NowTicks() + maximum_idle_period_duration();
+ base::TimeTicks expected_deadline = Now() + maximum_idle_period_duration();
base::TimeTicks deadline_in_task;
int run_count = 0;
idle_task_runner_->PostIdleTask(
FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, run_count); // Shouldn't run yet as no idle period.
scheduler_->BeginFrameNotExpectedSoon();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, run_count); // Should have run in a long idle time.
EXPECT_EQ(expected_deadline, deadline_in_task);
}
TEST_F(MainThreadSchedulerImplTest, TestLongIdlePeriodWithPendingDelayedTask) {
base::TimeDelta pending_task_delay = base::TimeDelta::FromMilliseconds(30);
- base::TimeTicks expected_deadline = clock_.NowTicks() + pending_task_delay;
+ base::TimeTicks expected_deadline = Now() + pending_task_delay;
base::TimeTicks deadline_in_task;
int run_count = 0;
@@ -2208,7 +2251,7 @@ TEST_F(MainThreadSchedulerImplTest, TestLongIdlePeriodWithPendingDelayedTask) {
pending_task_delay);
scheduler_->BeginFrameNotExpectedSoon();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, run_count); // Should have run in a long idle time.
EXPECT_EQ(expected_deadline, deadline_in_task);
}
@@ -2223,7 +2266,8 @@ TEST_F(MainThreadSchedulerImplTest,
pending_task_delay);
// Advance clock until after delayed task was meant to be run.
- clock_.Advance(base::TimeDelta::FromMilliseconds(20));
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMilliseconds(20));
// Post an idle task and BeginFrameNotExpectedSoon to initiate a long idle
// period. Since there is a late pending delayed task this shouldn't actually
@@ -2231,30 +2275,28 @@ TEST_F(MainThreadSchedulerImplTest,
idle_task_runner_->PostIdleTask(
FROM_HERE, base::BindOnce(&IdleTestTask, &run_count, &deadline_in_task));
scheduler_->BeginFrameNotExpectedSoon();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, run_count);
// After the delayed task has been run we should trigger an idle period.
- clock_.Advance(maximum_idle_period_duration());
- RunUntilIdle();
+ test_task_runner_->FastForwardBy(maximum_idle_period_duration());
EXPECT_EQ(1, run_count);
}
TEST_F(MainThreadSchedulerImplTest, TestLongIdlePeriodRepeating) {
- ScopedAutoAdvanceNowEnabler enable_auto_advance_now(mock_task_runner_);
std::vector<base::TimeTicks> actual_deadlines;
int run_count = 0;
g_max_idle_task_reposts = 3;
- base::TimeTicks clock_before(clock_.NowTicks());
+ base::TimeTicks clock_before = Now();
base::TimeDelta idle_task_runtime(base::TimeDelta::FromMilliseconds(10));
idle_task_runner_->PostIdleTask(
FROM_HERE,
base::BindOnce(&RepostingUpdateClockIdleTestTask,
- base::RetainedRef(idle_task_runner_), &run_count, &clock_,
- idle_task_runtime, &actual_deadlines));
+ base::RetainedRef(idle_task_runner_), &run_count,
+ test_task_runner_, idle_task_runtime, &actual_deadlines));
scheduler_->BeginFrameNotExpectedSoon();
- RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_EQ(3, run_count);
EXPECT_THAT(
actual_deadlines,
@@ -2268,13 +2310,15 @@ TEST_F(MainThreadSchedulerImplTest, TestLongIdlePeriodRepeating) {
idle_task_runner_->PostIdleTask(
FROM_HERE,
base::BindOnce(&RepostingUpdateClockIdleTestTask,
- base::RetainedRef(idle_task_runner_), &run_count, &clock_,
- idle_task_runtime, &actual_deadlines));
+ base::RetainedRef(idle_task_runner_), &run_count,
+ test_task_runner_, idle_task_runtime, &actual_deadlines));
idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&WillBeginFrameIdleTask,
- base::Unretained(scheduler_.get()),
- next_begin_frame_number_++, &clock_));
- RunUntilIdle();
+ FROM_HERE,
+ base::BindOnce(&WillBeginFrameIdleTask,
+ base::Unretained(scheduler_.get()),
+ next_begin_frame_number_++,
+ base::Unretained(test_task_runner_->GetMockTickClock())));
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_EQ(4, run_count);
}
@@ -2287,15 +2331,14 @@ TEST_F(MainThreadSchedulerImplTest, TestLongIdlePeriodInTouchStartPolicy) {
// Observation of touchstart should defer the start of the long idle period.
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
scheduler_->BeginFrameNotExpectedSoon();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, run_count);
// The long idle period should start after the touchstart policy has finished.
- clock_.Advance(priority_escalation_after_input_duration());
- RunUntilIdle();
+ test_task_runner_->FastForwardBy(priority_escalation_after_input_duration());
EXPECT_EQ(1, run_count);
}
@@ -2320,7 +2363,7 @@ TEST_F(MainThreadSchedulerImplTest, CanExceedIdleDeadlineIfRequired) {
base::BindOnce(&TestCanExceedIdleDeadlineIfRequiredTask, scheduler_.get(),
&can_exceed_idle_deadline, &run_count));
EnableIdleTasks();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, run_count);
EXPECT_FALSE(can_exceed_idle_deadline);
@@ -2333,33 +2376,31 @@ TEST_F(MainThreadSchedulerImplTest, CanExceedIdleDeadlineIfRequired) {
base::BindOnce(&TestCanExceedIdleDeadlineIfRequiredTask, scheduler_.get(),
&can_exceed_idle_deadline, &run_count));
scheduler_->BeginFrameNotExpectedSoon();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(2, run_count);
EXPECT_FALSE(can_exceed_idle_deadline);
// Next long idle period will be for the maximum time, so
// CanExceedIdleDeadlineIfRequired should return true.
- clock_.Advance(maximum_idle_period_duration());
+ test_task_runner_->AdvanceMockTickClock(maximum_idle_period_duration());
idle_task_runner_->PostIdleTask(
FROM_HERE,
base::BindOnce(&TestCanExceedIdleDeadlineIfRequiredTask, scheduler_.get(),
&can_exceed_idle_deadline, &run_count));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(3, run_count);
EXPECT_TRUE(can_exceed_idle_deadline);
// Next long idle period will be for the maximum time, so
// CanExceedIdleDeadlineIfRequired should return true.
scheduler_->WillBeginFrame(viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(1000),
viz::BeginFrameArgs::NORMAL));
EXPECT_FALSE(scheduler_->CanExceedIdleDeadlineIfRequired());
}
TEST_F(MainThreadSchedulerImplTest, TestRendererHiddenIdlePeriod) {
- ScopedAutoAdvanceNowEnabler enable_auto_advance_now(mock_task_runner_);
-
int run_count = 0;
g_max_idle_task_reposts = 2;
@@ -2369,14 +2410,14 @@ TEST_F(MainThreadSchedulerImplTest, TestRendererHiddenIdlePeriod) {
base::RetainedRef(idle_task_runner_), &run_count));
// Renderer should start in visible state.
- RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_EQ(0, run_count);
// When we hide the renderer it should start a max deadline idle period, which
// will run an idle task and then immediately start a new idle period, which
// runs the second idle task.
scheduler_->SetAllRenderWidgetsHidden(true);
- RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_EQ(2, run_count);
// Advance time by amount of time by the maximum amount of time we execute
@@ -2386,16 +2427,15 @@ TEST_F(MainThreadSchedulerImplTest, TestRendererHiddenIdlePeriod) {
FROM_HERE,
base::BindOnce(&RepostingIdleTestTask,
base::RetainedRef(idle_task_runner_), &run_count));
- clock_.Advance(end_idle_when_hidden_delay() +
- base::TimeDelta::FromMilliseconds(10));
- RunUntilIdle();
+ test_task_runner_->FastForwardBy(end_idle_when_hidden_delay() +
+ base::TimeDelta::FromMilliseconds(10));
EXPECT_EQ(2, run_count);
}
TEST_F(MainThreadSchedulerImplTest, TimerQueueEnabledByDefault) {
std::vector<std::string> run_order;
PostTestTasks(&run_order, "T1 T2");
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("T1"), std::string("T2")));
}
@@ -2405,11 +2445,11 @@ TEST_F(MainThreadSchedulerImplTest, StopAndResumeRenderer) {
PostTestTasks(&run_order, "T1 T2");
auto pause_handle = scheduler_->PauseRenderer();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order, testing::ElementsAre());
pause_handle.reset();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("T1"), std::string("T2")));
}
@@ -2419,10 +2459,10 @@ TEST_F(MainThreadSchedulerImplTest, StopAndThrottleTimerQueue) {
PostTestTasks(&run_order, "T1 T2");
auto pause_handle = scheduler_->PauseRenderer();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
scheduler_->task_queue_throttler()->IncreaseThrottleRefCount(
static_cast<TaskQueue*>(timer_task_runner_.get()));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order, testing::ElementsAre());
}
@@ -2432,9 +2472,9 @@ TEST_F(MainThreadSchedulerImplTest, ThrottleAndPauseRenderer) {
scheduler_->task_queue_throttler()->IncreaseThrottleRefCount(
static_cast<TaskQueue*>(timer_task_runner_.get()));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
auto pause_handle = scheduler_->PauseRenderer();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order, testing::ElementsAre());
}
@@ -2445,19 +2485,19 @@ TEST_F(MainThreadSchedulerImplTest, MultipleStopsNeedMultipleResumes) {
auto pause_handle1 = scheduler_->PauseRenderer();
auto pause_handle2 = scheduler_->PauseRenderer();
auto pause_handle3 = scheduler_->PauseRenderer();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order, testing::ElementsAre());
pause_handle1.reset();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order, testing::ElementsAre());
pause_handle2.reset();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order, testing::ElementsAre());
pause_handle3.reset();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("T1"), std::string("T2")));
}
@@ -2468,7 +2508,7 @@ TEST_F(MainThreadSchedulerImplTest, PauseRenderer) {
PostTestTasks(&run_order, "D1 C1 L1 I1 T1");
auto pause_handle = scheduler_->PauseRenderer();
EnableIdleTasks();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("D1"), std::string("C1"),
std::string("I1")));
@@ -2476,7 +2516,7 @@ TEST_F(MainThreadSchedulerImplTest, PauseRenderer) {
// Tasks are executed when renderer is resumed.
run_order.clear();
pause_handle.reset();
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("L1"), std::string("T1")));
}
@@ -2499,7 +2539,7 @@ TEST_F(MainThreadSchedulerImplTest, BeginMainFrameOnCriticalPath) {
ASSERT_FALSE(scheduler_->BeginMainFrameOnCriticalPath());
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(1000),
viz::BeginFrameArgs::NORMAL);
scheduler_->WillBeginFrame(begin_frame_args);
@@ -2511,80 +2551,30 @@ TEST_F(MainThreadSchedulerImplTest, BeginMainFrameOnCriticalPath) {
}
TEST_F(MainThreadSchedulerImplTest, ShutdownPreventsPostingOfNewTasks) {
+ main_frame_scheduler_.reset();
+ page_scheduler_.reset();
scheduler_->Shutdown();
std::vector<std::string> run_order;
PostTestTasks(&run_order, "D1 C1");
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order, testing::ElementsAre());
}
-TEST_F(MainThreadSchedulerImplTest, TestRendererBackgroundedTimerSuspension) {
- scheduler_->SetFreezingWhenBackgroundedEnabled(true);
-
- std::vector<std::string> run_order;
- PostTestTasks(&run_order, "T1 T2");
-
- base::TimeTicks now;
-
- // The background signal will not immediately suspend the timer queue.
- scheduler_->SetRendererBackgrounded(true);
- now += base::TimeDelta::FromMilliseconds(1100);
- clock_.SetNowTicks(now);
- RunUntilIdle();
- EXPECT_THAT(run_order,
- testing::ElementsAre(std::string("T1"), std::string("T2")));
-
- run_order.clear();
- PostTestTasks(&run_order, "T3");
-
- now += base::TimeDelta::FromSeconds(1);
- clock_.SetNowTicks(now);
- RunUntilIdle();
- EXPECT_THAT(run_order, testing::ElementsAre(std::string("T3")));
-
- // Advance the time until after the scheduled timer queue suspension.
- now = base::TimeTicks() + delay_for_background_tab_freezing() +
- base::TimeDelta::FromMilliseconds(10);
- run_order.clear();
- clock_.SetNowTicks(now);
- RunUntilIdle();
- ASSERT_TRUE(run_order.empty());
-
- // Timer tasks should be paused until the foregrounded signal.
- PostTestTasks(&run_order, "T4 T5 V1");
- now += base::TimeDelta::FromSeconds(10);
- clock_.SetNowTicks(now);
- RunUntilIdle();
- EXPECT_THAT(run_order, testing::ElementsAre(std::string("V1")));
-
- run_order.clear();
- scheduler_->SetRendererBackgrounded(false);
- RunUntilIdle();
- EXPECT_THAT(run_order,
- testing::ElementsAre(std::string("T4"), std::string("T5")));
-
- // Subsequent timer tasks should fire as usual.
- run_order.clear();
- PostTestTasks(&run_order, "T6");
- RunUntilIdle();
- EXPECT_THAT(run_order, testing::ElementsAre(std::string("T6")));
-}
-
TEST_F(MainThreadSchedulerImplTest,
ExpensiveLoadingTasksNotBlockedTillFirstBeginMainFrame) {
std::vector<std::string> run_order;
- scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
+ scheduler_->SetHaveSeenABlockingGestureForTesting(true);
SimulateExpensiveTasks(loading_task_runner_);
- ForceTouchStartToBeExpectedSoon();
+ ForceBlockingInputToBeExpectedSoon();
PostTestTasks(&run_order, "L1 D1");
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kNone, ForceUpdatePolicyAndGetCurrentUseCase());
EXPECT_FALSE(HaveSeenABeginMainframe());
EXPECT_TRUE(LoadingTasksSeemExpensive());
EXPECT_FALSE(TimerTasksSeemExpensive());
- EXPECT_TRUE(TouchStartExpectedSoon());
+ EXPECT_TRUE(BlockingInputExpectedSoon());
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("L1"), std::string("D1")));
@@ -2593,13 +2583,13 @@ TEST_F(MainThreadSchedulerImplTest,
run_order.clear();
PostTestTasks(&run_order, "L1 D1");
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kNone, CurrentUseCase());
EXPECT_TRUE(HaveSeenABeginMainframe());
EXPECT_TRUE(LoadingTasksSeemExpensive());
EXPECT_FALSE(TimerTasksSeemExpensive());
- EXPECT_TRUE(TouchStartExpectedSoon());
+ EXPECT_TRUE(BlockingInputExpectedSoon());
EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1")));
EXPECT_EQ(v8::PERFORMANCE_RESPONSE, GetRAILMode());
}
@@ -2611,15 +2601,15 @@ TEST_F(MainThreadSchedulerImplTest,
scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(false);
DoMainFrame();
SimulateExpensiveTasks(loading_task_runner_);
- ForceTouchStartToBeExpectedSoon();
+ ForceBlockingInputToBeExpectedSoon();
PostTestTasks(&run_order, "L1 D1");
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kNone, ForceUpdatePolicyAndGetCurrentUseCase());
EXPECT_TRUE(HaveSeenABeginMainframe());
EXPECT_TRUE(LoadingTasksSeemExpensive());
EXPECT_FALSE(TimerTasksSeemExpensive());
- EXPECT_FALSE(TouchStartExpectedSoon());
+ EXPECT_FALSE(BlockingInputExpectedSoon());
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("L1"), std::string("D1")));
EXPECT_EQ(v8::PERFORMANCE_ANIMATION, GetRAILMode());
@@ -2629,19 +2619,19 @@ TEST_F(MainThreadSchedulerImplTest,
ExpensiveTimerTaskBlocked_UseCase_NONE_PreviousCompositorGesture) {
std::vector<std::string> run_order;
- scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
+ scheduler_->SetHaveSeenABlockingGestureForTesting(true);
DoMainFrame();
SimulateExpensiveTasks(timer_task_runner_);
- ForceTouchStartToBeExpectedSoon();
+ ForceBlockingInputToBeExpectedSoon();
PostTestTasks(&run_order, "T1 D1");
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kNone, ForceUpdatePolicyAndGetCurrentUseCase());
EXPECT_TRUE(HaveSeenABeginMainframe());
EXPECT_FALSE(LoadingTasksSeemExpensive());
EXPECT_TRUE(TimerTasksSeemExpensive());
- EXPECT_TRUE(TouchStartExpectedSoon());
+ EXPECT_TRUE(BlockingInputExpectedSoon());
EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1")));
EXPECT_EQ(v8::PERFORMANCE_RESPONSE, GetRAILMode());
}
@@ -2666,17 +2656,18 @@ TEST_F(MainThreadSchedulerImplTest,
FakeInputEvent(blink::WebInputEvent::kTouchEnd),
WebInputEventResult::kHandledSystem);
- clock_.Advance(priority_escalation_after_input_duration() * 2);
+ test_task_runner_->AdvanceMockTickClock(
+ priority_escalation_after_input_duration() * 2);
EXPECT_EQ(UseCase::kNone, ForceUpdatePolicyAndGetCurrentUseCase());
PostTestTasks(&run_order, "T1 D1");
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kNone, ForceUpdatePolicyAndGetCurrentUseCase());
EXPECT_TRUE(HaveSeenABeginMainframe());
EXPECT_FALSE(LoadingTasksSeemExpensive());
EXPECT_TRUE(TimerTasksSeemExpensive());
- EXPECT_TRUE(TouchStartExpectedSoon());
+ EXPECT_TRUE(BlockingInputExpectedSoon());
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("T1"), std::string("D1")));
EXPECT_EQ(v8::PERFORMANCE_ANIMATION, GetRAILMode());
@@ -2686,21 +2677,21 @@ TEST_F(MainThreadSchedulerImplTest,
ExpensiveTimerTaskBlocked_UseCase_kCompositorGesture) {
std::vector<std::string> run_order;
- scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
+ scheduler_->SetHaveSeenABlockingGestureForTesting(true);
DoMainFrame();
SimulateExpensiveTasks(timer_task_runner_);
- ForceTouchStartToBeExpectedSoon();
+ ForceBlockingInputToBeExpectedSoon();
scheduler_->DidAnimateForInputOnCompositorThread();
PostTestTasks(&run_order, "T1 D1");
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kCompositorGesture,
ForceUpdatePolicyAndGetCurrentUseCase());
EXPECT_TRUE(HaveSeenABeginMainframe());
EXPECT_FALSE(LoadingTasksSeemExpensive());
EXPECT_TRUE(TimerTasksSeemExpensive());
- EXPECT_TRUE(TouchStartExpectedSoon());
+ EXPECT_TRUE(BlockingInputExpectedSoon());
EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1")));
EXPECT_EQ(v8::PERFORMANCE_RESPONSE, GetRAILMode());
}
@@ -2709,20 +2700,20 @@ TEST_F(MainThreadSchedulerImplTest,
ExpensiveTimerTaskBlocked_EvenIfBeginMainFrameNotExpectedSoon) {
std::vector<std::string> run_order;
- scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
+ scheduler_->SetHaveSeenABlockingGestureForTesting(true);
DoMainFrame();
SimulateExpensiveTasks(timer_task_runner_);
- ForceTouchStartToBeExpectedSoon();
+ ForceBlockingInputToBeExpectedSoon();
scheduler_->BeginFrameNotExpectedSoon();
PostTestTasks(&run_order, "T1 D1");
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kNone, ForceUpdatePolicyAndGetCurrentUseCase());
EXPECT_TRUE(HaveSeenABeginMainframe());
EXPECT_FALSE(LoadingTasksSeemExpensive());
EXPECT_TRUE(TimerTasksSeemExpensive());
- EXPECT_TRUE(TouchStartExpectedSoon());
+ EXPECT_TRUE(BlockingInputExpectedSoon());
EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1")));
EXPECT_EQ(v8::PERFORMANCE_RESPONSE, GetRAILMode());
}
@@ -2732,12 +2723,12 @@ TEST_F(MainThreadSchedulerImplTest,
std::vector<std::string> run_order;
DoMainFrame();
- scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
+ scheduler_->SetHaveSeenABlockingGestureForTesting(true);
SimulateExpensiveTasks(loading_task_runner_);
- ForceTouchStartToBeExpectedSoon();
+ ForceBlockingInputToBeExpectedSoon();
PostTestTasks(&run_order, "L1 D1");
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// The expensive loading task gets blocked.
EXPECT_THAT(run_order, testing::ElementsAre(std::string("D1")));
@@ -2756,7 +2747,7 @@ TEST_F(MainThreadSchedulerImplTest,
// Trigger main_thread_gesture UseCase
SimulateMainThreadGestureStart(TouchEventPolicy::kSendTouchStart,
blink::WebInputEvent::kGestureScrollBegin);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
EXPECT_TRUE(LoadingTasksSeemExpensive());
@@ -2770,12 +2761,12 @@ TEST_F(MainThreadSchedulerImplTest, ModeratelyExpensiveTimer_NotBlocked) {
scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
SimulateMainThreadGestureStart(TouchEventPolicy::kSendTouchStart,
blink::WebInputEvent::kTouchMove);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
for (int i = 0; i < 20; i++) {
simulate_timer_task_ran_ = false;
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
viz::BeginFrameArgs::NORMAL);
begin_frame_args.on_critical_path = false;
@@ -2793,29 +2784,28 @@ TEST_F(MainThreadSchedulerImplTest, ModeratelyExpensiveTimer_NotBlocked) {
base::Unretained(this),
base::TimeDelta::FromMilliseconds(4)));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(simulate_timer_task_ran_) << " i = " << i;
EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase())
<< " i = " << i;
EXPECT_FALSE(LoadingTasksSeemExpensive()) << " i = " << i;
EXPECT_FALSE(TimerTasksSeemExpensive()) << " i = " << i;
- base::TimeDelta time_till_next_frame =
- EstimatedNextFrameBegin() - clock_.NowTicks();
+ base::TimeDelta time_till_next_frame = EstimatedNextFrameBegin() - Now();
if (time_till_next_frame > base::TimeDelta())
- clock_.Advance(time_till_next_frame);
+ test_task_runner_->AdvanceMockTickClock(time_till_next_frame);
}
}
TEST_F(MainThreadSchedulerImplTest,
FourtyMsTimer_NotBlocked_CompositorScrolling) {
scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
for (int i = 0; i < 20; i++) {
simulate_timer_task_ran_ = false;
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
viz::BeginFrameArgs::NORMAL);
begin_frame_args.on_critical_path = false;
@@ -2833,16 +2823,15 @@ TEST_F(MainThreadSchedulerImplTest,
base::Unretained(this),
base::TimeDelta::FromMilliseconds(40)));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(simulate_timer_task_ran_) << " i = " << i;
EXPECT_EQ(UseCase::kCompositorGesture, CurrentUseCase()) << " i = " << i;
EXPECT_FALSE(LoadingTasksSeemExpensive()) << " i = " << i;
EXPECT_FALSE(TimerTasksSeemExpensive()) << " i = " << i;
- base::TimeDelta time_till_next_frame =
- EstimatedNextFrameBegin() - clock_.NowTicks();
+ base::TimeDelta time_till_next_frame = EstimatedNextFrameBegin() - Now();
if (time_till_next_frame > base::TimeDelta())
- clock_.Advance(time_till_next_frame);
+ test_task_runner_->AdvanceMockTickClock(time_till_next_frame);
}
}
@@ -2851,12 +2840,12 @@ TEST_F(MainThreadSchedulerImplTest,
scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
SimulateMainThreadGestureStart(TouchEventPolicy::kSendTouchStart,
blink::WebInputEvent::kTouchMove);
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
for (int i = 0; i < 20; i++) {
simulate_timer_task_ran_ = false;
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
viz::BeginFrameArgs::NORMAL);
begin_frame_args.on_critical_path = false;
@@ -2874,7 +2863,7 @@ TEST_F(MainThreadSchedulerImplTest,
base::Unretained(this),
base::TimeDelta::FromMilliseconds(10)));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase())
<< " i = " << i;
EXPECT_FALSE(LoadingTasksSeemExpensive()) << " i = " << i;
@@ -2885,10 +2874,9 @@ TEST_F(MainThreadSchedulerImplTest,
}
EXPECT_TRUE(simulate_timer_task_ran_) << " i = " << i;
- base::TimeDelta time_till_next_frame =
- EstimatedNextFrameBegin() - clock_.NowTicks();
+ base::TimeDelta time_till_next_frame = EstimatedNextFrameBegin() - Now();
if (time_till_next_frame > base::TimeDelta())
- clock_.Advance(time_till_next_frame);
+ test_task_runner_->AdvanceMockTickClock(time_till_next_frame);
}
}
@@ -2923,7 +2911,7 @@ TEST_F(MainThreadSchedulerImplTest,
SimulateMainThreadGestureStart(TouchEventPolicy::kSendTouchStart,
blink::WebInputEvent::kGestureScrollUpdate);
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
viz::BeginFrameArgs::NORMAL);
begin_frame_args.on_critical_path = false;
@@ -2936,7 +2924,7 @@ TEST_F(MainThreadSchedulerImplTest,
base::Unretained(this),
base::TimeDelta::FromMilliseconds(5)));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kMainThreadGesture, CurrentUseCase());
// 16ms frame - 5ms compositor work = 11ms for other stuff.
@@ -2948,7 +2936,7 @@ TEST_F(
MainThreadSchedulerImplTest,
EstimateLongestJankFreeTaskDuration_UseCase_MAIN_THREAD_CUSTOM_INPUT_HANDLING) {
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
viz::BeginFrameArgs::NORMAL);
begin_frame_args.on_critical_path = false;
@@ -2961,7 +2949,7 @@ TEST_F(
base::Unretained(this),
base::TimeDelta::FromMilliseconds(5)));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase());
// 16ms frame - 5ms compositor work = 11ms for other stuff.
@@ -2974,7 +2962,7 @@ TEST_F(MainThreadSchedulerImplTest,
SimulateCompositorGestureStart(TouchEventPolicy::kDontSendTouchStart);
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
viz::BeginFrameArgs::NORMAL);
begin_frame_args.on_critical_path = true;
@@ -2986,7 +2974,7 @@ TEST_F(MainThreadSchedulerImplTest,
&MainThreadSchedulerImplTest::SimulateMainThreadCompositorTask,
base::Unretained(this), base::TimeDelta::FromMilliseconds(5)));
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kSynchronizedGesture, CurrentUseCase());
// 16ms frame - 5ms compositor work = 11ms for other stuff.
@@ -2997,7 +2985,7 @@ TEST_F(MainThreadSchedulerImplTest,
class PageSchedulerImplForTest : public PageSchedulerImpl {
public:
explicit PageSchedulerImplForTest(MainThreadSchedulerImpl* scheduler)
- : PageSchedulerImpl(nullptr, scheduler, false) {}
+ : PageSchedulerImpl(nullptr, scheduler) {}
~PageSchedulerImplForTest() override = default;
void ReportIntervention(const std::string& message) override {
@@ -3008,7 +2996,7 @@ class PageSchedulerImplForTest : public PageSchedulerImpl {
return interventions_;
}
- MOCK_METHOD1(RequestBeginMainFrameNotExpected, void(bool));
+ MOCK_METHOD1(RequestBeginMainFrameNotExpected, bool(bool));
private:
std::vector<std::string> interventions_;
@@ -3018,35 +3006,36 @@ class PageSchedulerImplForTest : public PageSchedulerImpl {
namespace {
void SlowCountingTask(size_t* count,
- base::SimpleTestTickClock* clock,
+ scoped_refptr<base::TestMockTimeTaskRunner> task_runner,
int task_duration,
scoped_refptr<base::SingleThreadTaskRunner> timer_queue) {
- clock->Advance(base::TimeDelta::FromMilliseconds(task_duration));
+ task_runner->AdvanceMockTickClock(
+ base::TimeDelta::FromMilliseconds(task_duration));
if (++(*count) < 500) {
- timer_queue->PostTask(
- FROM_HERE, base::BindOnce(SlowCountingTask, count, clock, task_duration,
- timer_queue));
+ timer_queue->PostTask(FROM_HERE,
+ base::BindOnce(SlowCountingTask, count, task_runner,
+ task_duration, timer_queue));
}
}
} // namespace
TEST_F(MainThreadSchedulerImplTest,
SYNCHRONIZED_GESTURE_TimerTaskThrottling_task_expensive) {
- SimulateCompositorGestureStart(TouchEventPolicy::kSendTouchStart);
+ SimulateCompositorGestureStart(TouchEventPolicy::kDontSendTouchStart);
base::TimeTicks first_throttled_run_time =
- TaskQueueThrottler::AlignedThrottledRunTime(clock_.NowTicks());
+ TaskQueueThrottler::AlignedThrottledRunTime(Now());
size_t count = 0;
// With the compositor task taking 10ms, there is not enough time to run this
// 7ms timer task in the 16ms frame.
timer_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(SlowCountingTask, &count, &clock_, 7, timer_task_runner_));
+ FROM_HERE, base::BindOnce(SlowCountingTask, &count, test_task_runner_, 7,
+ timer_task_runner_));
for (int i = 0; i < 1000; i++) {
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
viz::BeginFrameArgs::NORMAL);
begin_frame_args.on_critical_path = true;
@@ -3055,16 +3044,14 @@ TEST_F(MainThreadSchedulerImplTest,
FakeInputEvent(blink::WebInputEvent::kGestureScrollUpdate),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- simulate_compositor_task_ran_ = false;
compositor_task_runner_->PostTask(
FROM_HERE,
- base::BindOnce(
- &MainThreadSchedulerImplTest::SimulateMainThreadCompositorTask,
- base::Unretained(this), base::TimeDelta::FromMilliseconds(10)));
+ base::BindOnce(&MainThreadSchedulerImplTest::
+ SimulateMainThreadCompositorAndQuitRunLoopTask,
+ base::Unretained(this),
+ base::TimeDelta::FromMilliseconds(10)));
- mock_task_runner_->RunTasksWhile(base::BindRepeating(
- &MainThreadSchedulerImplTest::SimulatedCompositorTaskPending,
- base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kSynchronizedGesture, CurrentUseCase()) << "i = " << i;
// We expect the queue to get throttled on the second iteration which is
@@ -3084,7 +3071,7 @@ TEST_F(MainThreadSchedulerImplTest,
// The task runs twice before the system realizes it's too expensive.
bool throttled_task_has_run = count > 2;
bool throttled_task_expected_to_have_run =
- (clock_.NowTicks() > first_throttled_run_time);
+ (Now() > first_throttled_run_time);
EXPECT_EQ(throttled_task_expected_to_have_run, throttled_task_has_run)
<< "i = " << i << " count = " << count;
}
@@ -3098,19 +3085,19 @@ TEST_F(MainThreadSchedulerImplTest,
SimulateCompositorGestureStart(TouchEventPolicy::kSendTouchStart);
base::TimeTicks first_throttled_run_time =
- TaskQueueThrottler::AlignedThrottledRunTime(clock_.NowTicks());
+ TaskQueueThrottler::AlignedThrottledRunTime(Now());
size_t count = 0;
// With the compositor task taking 10ms, there is not enough time to run this
// 7ms timer task in the 16ms frame.
timer_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(SlowCountingTask, &count, &clock_, 7, timer_task_runner_));
+ FROM_HERE, base::BindOnce(SlowCountingTask, &count, test_task_runner_, 7,
+ timer_task_runner_));
- std::unique_ptr<WebMainThreadScheduler::RendererPauseHandle> paused;
+ std::unique_ptr<WebThreadScheduler::RendererPauseHandle> paused;
for (int i = 0; i < 1000; i++) {
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
viz::BeginFrameArgs::NORMAL);
begin_frame_args.on_critical_path = true;
@@ -3119,22 +3106,19 @@ TEST_F(MainThreadSchedulerImplTest,
FakeInputEvent(blink::WebInputEvent::kGestureScrollUpdate),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- simulate_compositor_task_ran_ = false;
compositor_task_runner_->PostTask(
FROM_HERE,
- base::BindOnce(
- &MainThreadSchedulerImplTest::SimulateMainThreadCompositorTask,
- base::Unretained(this), base::TimeDelta::FromMilliseconds(10)));
+ base::BindOnce(&MainThreadSchedulerImplTest::
+ SimulateMainThreadCompositorAndQuitRunLoopTask,
+ base::Unretained(this),
+ base::TimeDelta::FromMilliseconds(10)));
- mock_task_runner_->RunTasksWhile(base::BindRepeating(
- &MainThreadSchedulerImplTest::SimulatedCompositorTaskPending,
- base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kSynchronizedGesture, CurrentUseCase()) << "i = " << i;
// Before the policy is updated the queue will be enabled. Subsequently it
// will be disabled until the throttled queue is pumped.
- bool expect_queue_enabled =
- (i == 0) || (clock_.NowTicks() > first_throttled_run_time);
+ bool expect_queue_enabled = (i == 0) || (Now() > first_throttled_run_time);
if (paused)
expect_queue_enabled = false;
EXPECT_EQ(expect_queue_enabled, timer_task_runner_->IsQueueEnabled())
@@ -3161,12 +3145,12 @@ TEST_F(MainThreadSchedulerImplTest,
// With the compositor task taking 10ms, there is enough time to run this 6ms
// timer task in the 16ms frame.
timer_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(SlowCountingTask, &count, &clock_, 6, timer_task_runner_));
+ FROM_HERE, base::BindOnce(SlowCountingTask, &count, test_task_runner_, 6,
+ timer_task_runner_));
for (int i = 0; i < 1000; i++) {
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
viz::BeginFrameArgs::NORMAL);
begin_frame_args.on_critical_path = true;
@@ -3175,16 +3159,14 @@ TEST_F(MainThreadSchedulerImplTest,
FakeInputEvent(blink::WebInputEvent::kGestureScrollUpdate),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- simulate_compositor_task_ran_ = false;
compositor_task_runner_->PostTask(
FROM_HERE,
- base::BindOnce(
- &MainThreadSchedulerImplTest::SimulateMainThreadCompositorTask,
- base::Unretained(this), base::TimeDelta::FromMilliseconds(10)));
+ base::BindOnce(&MainThreadSchedulerImplTest::
+ SimulateMainThreadCompositorAndQuitRunLoopTask,
+ base::Unretained(this),
+ base::TimeDelta::FromMilliseconds(10)));
- mock_task_runner_->RunTasksWhile(base::BindRepeating(
- &MainThreadSchedulerImplTest::SimulatedCompositorTaskPending,
- base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kSynchronizedGesture, CurrentUseCase()) << "i = " << i;
EXPECT_TRUE(timer_task_runner_->IsQueueEnabled()) << "i = " << i;
}
@@ -3194,11 +3176,12 @@ TEST_F(MainThreadSchedulerImplTest,
}
TEST_F(MainThreadSchedulerImplTest,
- ExpensiveTimerTaskBlocked_SYNCHRONIZED_GESTURE_TouchStartExpected) {
+ ExpensiveTimerTaskBlocked_SYNCHRONIZED_GESTURE_GestureExpected) {
SimulateExpensiveTasks(timer_task_runner_);
- SimulateCompositorGestureStart(TouchEventPolicy::kSendTouchStart);
- scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
- ForceTouchStartToBeExpectedSoon();
+ scheduler_->DidHandleInputEventOnCompositorThread(
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
+ InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
+ ForceBlockingInputToBeExpectedSoon();
// Bump us into SYNCHRONIZED_GESTURE.
scheduler_->DidHandleInputEventOnCompositorThread(
@@ -3206,7 +3189,7 @@ TEST_F(MainThreadSchedulerImplTest,
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
viz::BeginFrameArgs::NORMAL);
begin_frame_args.on_critical_path = true;
@@ -3216,13 +3199,13 @@ TEST_F(MainThreadSchedulerImplTest,
ForceUpdatePolicyAndGetCurrentUseCase());
EXPECT_TRUE(TimerTasksSeemExpensive());
- EXPECT_TRUE(TouchStartExpectedSoon());
+ EXPECT_TRUE(BlockingInputExpectedSoon());
EXPECT_FALSE(timer_task_runner_->IsQueueEnabled());
}
TEST_F(MainThreadSchedulerImplTest, DenyLongIdleDuringTouchStart) {
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
EXPECT_EQ(UseCase::kTouchstart, ForceUpdatePolicyAndGetCurrentUseCase());
@@ -3251,7 +3234,7 @@ TEST_F(MainThreadSchedulerImplTest,
// Make sure TouchStart causes a policy change.
scheduler_->DidHandleInputEventOnCompositorThread(
- FakeInputEvent(blink::WebInputEvent::kTouchStart),
+ FakeTouchEvent(blink::WebInputEvent::kTouchStart),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
EXPECT_EQ(UseCase::kTouchstart, ForceUpdatePolicyAndGetCurrentUseCase());
}
@@ -3268,7 +3251,7 @@ TEST_F(MainThreadSchedulerImplTest, SYNCHRONIZED_GESTURE_CompositingExpensive) {
for (int i = 0; i < 100; i++) {
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
viz::BeginFrameArgs::NORMAL);
begin_frame_args.on_critical_path = true;
@@ -3277,16 +3260,14 @@ TEST_F(MainThreadSchedulerImplTest, SYNCHRONIZED_GESTURE_CompositingExpensive) {
FakeInputEvent(blink::WebInputEvent::kGestureScrollUpdate),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- simulate_compositor_task_ran_ = false;
compositor_task_runner_->PostTask(
FROM_HERE,
- base::BindOnce(
- &MainThreadSchedulerImplTest::SimulateMainThreadCompositorTask,
- base::Unretained(this), base::TimeDelta::FromMilliseconds(20)));
+ base::BindOnce(&MainThreadSchedulerImplTest::
+ SimulateMainThreadCompositorAndQuitRunLoopTask,
+ base::Unretained(this),
+ base::TimeDelta::FromMilliseconds(20)));
- mock_task_runner_->RunTasksWhile(base::BindRepeating(
- &MainThreadSchedulerImplTest::SimulatedCompositorTaskPending,
- base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kSynchronizedGesture, CurrentUseCase()) << "i = " << i;
}
@@ -3310,7 +3291,7 @@ TEST_F(MainThreadSchedulerImplTest, MAIN_THREAD_CUSTOM_INPUT_HANDLING) {
for (int i = 0; i < 100; i++) {
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
viz::BeginFrameArgs::NORMAL);
begin_frame_args.on_critical_path = true;
@@ -3319,16 +3300,14 @@ TEST_F(MainThreadSchedulerImplTest, MAIN_THREAD_CUSTOM_INPUT_HANDLING) {
FakeInputEvent(blink::WebInputEvent::kTouchMove),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
- simulate_compositor_task_ran_ = false;
compositor_task_runner_->PostTask(
FROM_HERE,
- base::BindOnce(
- &MainThreadSchedulerImplTest::SimulateMainThreadCompositorTask,
- base::Unretained(this), base::TimeDelta::FromMilliseconds(20)));
+ base::BindOnce(&MainThreadSchedulerImplTest::
+ SimulateMainThreadCompositorAndQuitRunLoopTask,
+ base::Unretained(this),
+ base::TimeDelta::FromMilliseconds(20)));
- mock_task_runner_->RunTasksWhile(base::BindRepeating(
- &MainThreadSchedulerImplTest::SimulatedCompositorTaskPending,
- base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kMainThreadCustomInputHandling, CurrentUseCase())
<< "i = " << i;
}
@@ -3354,7 +3333,7 @@ TEST_F(MainThreadSchedulerImplTest, MAIN_THREAD_GESTURE) {
for (int i = 0; i < 100; i++) {
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
viz::BeginFrameArgs::NORMAL);
begin_frame_args.on_critical_path = true;
@@ -3363,16 +3342,14 @@ TEST_F(MainThreadSchedulerImplTest, MAIN_THREAD_GESTURE) {
FakeInputEvent(blink::WebInputEvent::kGestureScrollUpdate),
InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD);
- simulate_compositor_task_ran_ = false;
compositor_task_runner_->PostTask(
FROM_HERE,
- base::BindOnce(
- &MainThreadSchedulerImplTest::SimulateMainThreadCompositorTask,
- base::Unretained(this), base::TimeDelta::FromMilliseconds(20)));
+ base::BindOnce(&MainThreadSchedulerImplTest::
+ SimulateMainThreadCompositorAndQuitRunLoopTask,
+ base::Unretained(this),
+ base::TimeDelta::FromMilliseconds(20)));
- mock_task_runner_->RunTasksWhile(base::BindRepeating(
- &MainThreadSchedulerImplTest::SimulatedCompositorTaskPending,
- base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kMainThreadGesture, CurrentUseCase()) << "i = " << i;
}
@@ -3381,37 +3358,37 @@ TEST_F(MainThreadSchedulerImplTest, MAIN_THREAD_GESTURE) {
EXPECT_EQ(279u, run_order.size());
}
-class MockRAILModeObserver : public WebMainThreadScheduler::RAILModeObserver {
+class MockRAILModeObserver : public WebThreadScheduler::RAILModeObserver {
public:
MOCK_METHOD1(OnRAILModeChanged, void(v8::RAILMode rail_mode));
};
TEST_F(MainThreadSchedulerImplTest, TestResponseRAILMode) {
MockRAILModeObserver observer;
- scheduler_->SetRAILModeObserver(&observer);
+ scheduler_->AddRAILModeObserver(&observer);
EXPECT_CALL(observer, OnRAILModeChanged(v8::PERFORMANCE_RESPONSE));
- scheduler_->SetHasVisibleRenderWidgetWithTouchHandler(true);
- ForceTouchStartToBeExpectedSoon();
+ scheduler_->SetHaveSeenABlockingGestureForTesting(true);
+ ForceBlockingInputToBeExpectedSoon();
EXPECT_EQ(UseCase::kNone, ForceUpdatePolicyAndGetCurrentUseCase());
EXPECT_EQ(v8::PERFORMANCE_RESPONSE, GetRAILMode());
- scheduler_->SetRAILModeObserver(nullptr);
+ scheduler_->RemoveRAILModeObserver(&observer);
}
TEST_F(MainThreadSchedulerImplTest, TestAnimateRAILMode) {
MockRAILModeObserver observer;
- scheduler_->SetRAILModeObserver(&observer);
+ scheduler_->AddRAILModeObserver(&observer);
EXPECT_CALL(observer, OnRAILModeChanged(v8::PERFORMANCE_ANIMATION)).Times(0);
EXPECT_FALSE(BeginFrameNotExpectedSoon());
EXPECT_EQ(UseCase::kNone, ForceUpdatePolicyAndGetCurrentUseCase());
EXPECT_EQ(v8::PERFORMANCE_ANIMATION, GetRAILMode());
- scheduler_->SetRAILModeObserver(nullptr);
+ scheduler_->RemoveRAILModeObserver(&observer);
}
TEST_F(MainThreadSchedulerImplTest, TestIdleRAILMode) {
MockRAILModeObserver observer;
- scheduler_->SetRAILModeObserver(&observer);
+ scheduler_->AddRAILModeObserver(&observer);
EXPECT_CALL(observer, OnRAILModeChanged(v8::PERFORMANCE_ANIMATION));
EXPECT_CALL(observer, OnRAILModeChanged(v8::PERFORMANCE_IDLE));
@@ -3421,12 +3398,12 @@ TEST_F(MainThreadSchedulerImplTest, TestIdleRAILMode) {
scheduler_->SetAllRenderWidgetsHidden(false);
EXPECT_EQ(UseCase::kNone, ForceUpdatePolicyAndGetCurrentUseCase());
EXPECT_EQ(v8::PERFORMANCE_ANIMATION, GetRAILMode());
- scheduler_->SetRAILModeObserver(nullptr);
+ scheduler_->RemoveRAILModeObserver(&observer);
}
TEST_F(MainThreadSchedulerImplTest, TestLoadRAILMode) {
MockRAILModeObserver observer;
- scheduler_->SetRAILModeObserver(&observer);
+ scheduler_->AddRAILModeObserver(&observer);
EXPECT_CALL(observer, OnRAILModeChanged(v8::PERFORMANCE_ANIMATION));
EXPECT_CALL(observer, OnRAILModeChanged(v8::PERFORMANCE_LOAD));
@@ -3436,12 +3413,12 @@ TEST_F(MainThreadSchedulerImplTest, TestLoadRAILMode) {
scheduler_->OnFirstMeaningfulPaint();
EXPECT_EQ(UseCase::kNone, ForceUpdatePolicyAndGetCurrentUseCase());
EXPECT_EQ(v8::PERFORMANCE_ANIMATION, GetRAILMode());
- scheduler_->SetRAILModeObserver(nullptr);
+ scheduler_->RemoveRAILModeObserver(&observer);
}
TEST_F(MainThreadSchedulerImplTest, InputTerminatesLoadRAILMode) {
MockRAILModeObserver observer;
- scheduler_->SetRAILModeObserver(&observer);
+ scheduler_->AddRAILModeObserver(&observer);
EXPECT_CALL(observer, OnRAILModeChanged(v8::PERFORMANCE_ANIMATION));
EXPECT_CALL(observer, OnRAILModeChanged(v8::PERFORMANCE_LOAD));
@@ -3457,7 +3434,7 @@ TEST_F(MainThreadSchedulerImplTest, InputTerminatesLoadRAILMode) {
EXPECT_EQ(UseCase::kCompositorGesture,
ForceUpdatePolicyAndGetCurrentUseCase());
EXPECT_EQ(v8::PERFORMANCE_ANIMATION, GetRAILMode());
- scheduler_->SetRAILModeObserver(nullptr);
+ scheduler_->RemoveRAILModeObserver(&observer);
}
TEST_F(MainThreadSchedulerImplTest, UnthrottledTaskRunner) {
@@ -3471,16 +3448,16 @@ TEST_F(MainThreadSchedulerImplTest, UnthrottledTaskRunner) {
size_t timer_count = 0;
size_t unthrottled_count = 0;
timer_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(SlowCountingTask, &timer_count, &clock_, 7,
- timer_task_runner_));
+ FROM_HERE, base::BindOnce(SlowCountingTask, &timer_count,
+ test_task_runner_, 7, timer_task_runner_));
unthrottled_task_runner->PostTask(
- FROM_HERE, base::BindOnce(SlowCountingTask, &unthrottled_count, &clock_,
- 7, unthrottled_task_runner));
+ FROM_HERE, base::BindOnce(SlowCountingTask, &unthrottled_count,
+ test_task_runner_, 7, unthrottled_task_runner));
auto handle = scheduler_->PauseRenderer();
for (int i = 0; i < 1000; i++) {
viz::BeginFrameArgs begin_frame_args = viz::BeginFrameArgs::Create(
- BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, clock_.NowTicks(),
+ BEGINFRAME_FROM_HERE, 0, next_begin_frame_number_++, Now(),
base::TimeTicks(), base::TimeDelta::FromMilliseconds(16),
viz::BeginFrameArgs::NORMAL);
begin_frame_args.on_critical_path = true;
@@ -3489,16 +3466,14 @@ TEST_F(MainThreadSchedulerImplTest, UnthrottledTaskRunner) {
FakeInputEvent(blink::WebInputEvent::kGestureScrollUpdate),
InputEventState::EVENT_CONSUMED_BY_COMPOSITOR);
- simulate_compositor_task_ran_ = false;
compositor_task_runner_->PostTask(
FROM_HERE,
- base::BindOnce(
- &MainThreadSchedulerImplTest::SimulateMainThreadCompositorTask,
- base::Unretained(this), base::TimeDelta::FromMilliseconds(10)));
+ base::BindOnce(&MainThreadSchedulerImplTest::
+ SimulateMainThreadCompositorAndQuitRunLoopTask,
+ base::Unretained(this),
+ base::TimeDelta::FromMilliseconds(10)));
- mock_task_runner_->RunTasksWhile(base::BindRepeating(
- &MainThreadSchedulerImplTest::SimulatedCompositorTaskPending,
- base::Unretained(this)));
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(UseCase::kSynchronizedGesture, CurrentUseCase()) << "i = " << i;
}
@@ -3578,16 +3553,15 @@ TEST_F(MainThreadSchedulerImplTest, EnableVirtualTime) {
}
TEST_F(MainThreadSchedulerImplTest, EnableVirtualTimeAfterThrottling) {
- std::unique_ptr<PageSchedulerImpl> page_scheduler = base::WrapUnique(
- new PageSchedulerImpl(nullptr, scheduler_.get(),
- false /* disable_background_timer_throttling */));
+ std::unique_ptr<PageSchedulerImpl> page_scheduler =
+ base::WrapUnique(new PageSchedulerImpl(nullptr, scheduler_.get()));
scheduler_->AddPageScheduler(page_scheduler.get());
std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
- page_scheduler->CreateFrameSchedulerImpl(
- nullptr, FrameScheduler::FrameType::kSubframe);
+ FrameSchedulerImpl::Create(page_scheduler.get(), nullptr,
+ FrameScheduler::FrameType::kSubframe);
- TaskQueue* timer_tq = ThrottableTaskQueue(frame_scheduler.get()).get();
+ TaskQueue* timer_tq = ThrottleableTaskQueue(frame_scheduler.get()).get();
frame_scheduler->SetCrossOrigin(true);
frame_scheduler->SetFrameVisible(false);
@@ -3669,15 +3643,15 @@ TEST_F(MainThreadSchedulerImplTest, Tracing) {
// traced value. This test checks that no internal checks fire during this.
std::unique_ptr<PageSchedulerImpl> page_scheduler1 =
- base::WrapUnique(new PageSchedulerImpl(nullptr, scheduler_.get(), false));
+ base::WrapUnique(new PageSchedulerImpl(nullptr, scheduler_.get()));
scheduler_->AddPageScheduler(page_scheduler1.get());
std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
- page_scheduler1->CreateFrameSchedulerImpl(
- nullptr, FrameScheduler::FrameType::kSubframe);
+ FrameSchedulerImpl::Create(page_scheduler1.get(), nullptr,
+ FrameScheduler::FrameType::kSubframe);
std::unique_ptr<PageSchedulerImpl> page_scheduler2 =
- base::WrapUnique(new PageSchedulerImpl(nullptr, scheduler_.get(), false));
+ base::WrapUnique(new PageSchedulerImpl(nullptr, scheduler_.get()));
scheduler_->AddPageScheduler(page_scheduler2.get());
CPUTimeBudgetPool* time_budget_pool =
@@ -3695,43 +3669,39 @@ TEST_F(MainThreadSchedulerImplTest, Tracing) {
EXPECT_TRUE(value);
}
-void RecordingTimeTestTask(std::vector<base::TimeTicks>* run_times,
- base::SimpleTestTickClock* clock) {
- run_times->push_back(clock->NowTicks());
+void RecordingTimeTestTask(
+ std::vector<base::TimeTicks>* run_times,
+ scoped_refptr<base::TestMockTimeTaskRunner> task_runner) {
+ run_times->push_back(task_runner->GetMockTickClock()->NowTicks());
}
-// TODO(altimin@): Re-enable after splitting the timer policy into separate
-// policies.
TEST_F(MainThreadSchedulerImplTest,
- DISABLED_DefaultTimerTasksAreThrottledWhenBackgrounded) {
- ScopedAutoAdvanceNowEnabler enable_auto_advance_now(mock_task_runner_);
-
- scheduler_->SetRendererBackgrounded(true);
-
+ DefaultTimerTasksAreThrottledWhenBackgrounded) {
std::vector<base::TimeTicks> run_times;
+ scheduler_->SetRendererBackgrounded(true);
timer_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&RecordingTimeTestTask, &run_times, &clock_));
-
- mock_task_runner_->RunUntilTime(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(1100));
+ FROM_HERE,
+ base::BindOnce(&RecordingTimeTestTask, &run_times, test_task_runner_));
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(1100));
+ // It's expected to run every "absolute" second.
EXPECT_THAT(run_times, testing::ElementsAre(base::TimeTicks() +
base::TimeDelta::FromSeconds(1)));
run_times.clear();
+ base::TimeTicks posting_time = Now();
timer_task_runner_->PostDelayedTask(
- FROM_HERE, base::BindOnce(&RecordingTimeTestTask, &run_times, &clock_),
+ FROM_HERE,
+ base::BindOnce(&RecordingTimeTestTask, &run_times, test_task_runner_),
base::TimeDelta::FromMilliseconds(200));
scheduler_->SetRendererBackgrounded(false);
- mock_task_runner_->RunUntilTime(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(1500));
-
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(400));
EXPECT_THAT(run_times,
- testing::ElementsAre(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(1300)));
+ testing::ElementsAre(posting_time +
+ base::TimeDelta::FromMilliseconds(200)));
}
// Nav Start Nav Start assert
@@ -3839,7 +3809,7 @@ TEST_F(MainThreadSchedulerImplTest, LoadingControlTasks) {
// tasks (L).
std::vector<std::string> run_order;
PostTestTasks(&run_order, "L1 L2 M1 L3 L4 M2 L5 L6");
- RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("M1"), std::string("M2"),
std::string("L1"), std::string("L2"),
@@ -3853,15 +3823,18 @@ TEST_F(MainThreadSchedulerImplTest, RequestBeginMainFrameNotExpected) {
scheduler_->AddPageScheduler(page_scheduler.get());
scheduler_->OnPendingTasksChanged(true);
- EXPECT_CALL(*page_scheduler, RequestBeginMainFrameNotExpected(true)).Times(1);
- RunUntilIdle();
+ EXPECT_CALL(*page_scheduler, RequestBeginMainFrameNotExpected(true))
+ .Times(1)
+ .WillRepeatedly(testing::Return(true));
+ base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(page_scheduler.get());
scheduler_->OnPendingTasksChanged(false);
EXPECT_CALL(*page_scheduler, RequestBeginMainFrameNotExpected(false))
- .Times(1);
- RunUntilIdle();
+ .Times(1)
+ .WillRepeatedly(testing::Return(true));
+ base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(page_scheduler.get());
}
@@ -3875,28 +3848,29 @@ TEST_F(MainThreadSchedulerImplTest,
scheduler_->OnPendingTasksChanged(true);
scheduler_->OnPendingTasksChanged(true);
// Multiple calls should result in only one call.
- EXPECT_CALL(*page_scheduler, RequestBeginMainFrameNotExpected(true)).Times(1);
- RunUntilIdle();
+ EXPECT_CALL(*page_scheduler, RequestBeginMainFrameNotExpected(true))
+ .Times(1)
+ .WillRepeatedly(testing::Return(true));
+ base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(page_scheduler.get());
}
#if defined(OS_ANDROID)
TEST_F(MainThreadSchedulerImplTest, PauseTimersForAndroidWebView) {
- ScopedAutoAdvanceNowEnabler enable_auto_advance_now(mock_task_runner_);
// Tasks in some queues don't fire when the timers are paused.
std::vector<std::string> run_order;
PostTestTasks(&run_order, "D1 C1 L1 I1 T1");
scheduler_->PauseTimersForAndroidWebView();
EnableIdleTasks();
- RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_THAT(run_order,
testing::ElementsAre(std::string("D1"), std::string("C1"),
std::string("L1"), std::string("I1")));
// The rest queued tasks fire when the timers are resumed.
run_order.clear();
scheduler_->ResumeTimersForAndroidWebView();
- RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_THAT(run_order, testing::ElementsAre(std::string("T1")));
}
#endif // defined(OS_ANDROID)
@@ -3905,15 +3879,10 @@ class MainThreadSchedulerImplWithInitalVirtualTimeTest
: public MainThreadSchedulerImplTest {
public:
void SetUp() override {
- if (!message_loop_) {
- mock_task_runner_ =
- base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, false);
- }
+ CreateTestTaskRunner();
Initialize(std::make_unique<MainThreadSchedulerImplForTest>(
- base::sequence_manager::TaskQueueManagerForTest::Create(
- message_loop_.get(),
- message_loop_ ? message_loop_->task_runner() : mock_task_runner_,
- &clock_),
+ base::sequence_manager::SequenceManagerForTest::Create(
+ nullptr, test_task_runner_, test_task_runner_->GetMockTickClock()),
base::Time::FromJsTime(1000000.0)));
}
};
@@ -3946,6 +3915,109 @@ TEST_F(MainThreadSchedulerImplTest, ShouldIgnoreTaskForUkm) {
}
}
+class CompositingExperimentWithExplicitSignalsTest
+ : public MainThreadSchedulerImplTest {
+ public:
+ CompositingExperimentWithExplicitSignalsTest()
+ : MainThreadSchedulerImplTest(
+ {kHighPriorityInputOnMainThread, kPrioritizeCompositingAfterInput,
+ kUseExplicitSignalForTriggeringCompositingPrioritization,
+ kUseWillBeginMainFrameForCompositingPrioritization},
+ {}) {}
+};
+
+TEST_F(CompositingExperimentWithExplicitSignalsTest, CompositingAfterInput) {
+ std::vector<std::string> run_order;
+ PostTestTasks(&run_order, "P1 T1 C1");
+ base::RunLoop().RunUntilIdle();
+ // Without an explicit signal nothing should be reordered.
+ EXPECT_THAT(run_order,
+ testing::ElementsAre(std::string("P1"), std::string("T1"),
+ std::string("C1")));
+ run_order.clear();
+
+ scheduler_->OnMainFrameRequestedForInput();
+
+ PostTestTasks(&run_order, "T2 C2 C3");
+ base::RunLoop().RunUntilIdle();
+ // When a signal is present, compositing tasks should be prioritized until
+ // WillBeginMainFrame is received.
+ EXPECT_THAT(run_order,
+ testing::ElementsAre(std::string("C2"), std::string("C3"),
+ std::string("T2")));
+ run_order.clear();
+
+ scheduler_->WillBeginFrame(viz::BeginFrameArgs());
+
+ PostTestTasks(&run_order, "T3 C4 C5");
+ base::RunLoop().RunUntilIdle();
+ EXPECT_THAT(run_order,
+ testing::ElementsAre(std::string("T3"), std::string("C4"),
+ std::string("C5")));
+ run_order.clear();
+}
+
+class CompositingExperimentWithImplicitSignalsTest
+ : public MainThreadSchedulerImplTest {
+ public:
+ CompositingExperimentWithImplicitSignalsTest()
+ : MainThreadSchedulerImplTest(
+ {kHighPriorityInputOnMainThread, kPrioritizeCompositingAfterInput},
+ {kHighestPriorityForCompositingAfterInput,
+ kUseExplicitSignalForTriggeringCompositingPrioritization,
+ kUseWillBeginMainFrameForCompositingPrioritization}) {}
+};
+
+TEST_F(CompositingExperimentWithImplicitSignalsTest, CompositingAfterInput) {
+ std::vector<std::string> run_order;
+ PostTestTasks(&run_order, "T1 C1 C2 P1 P2");
+ base::RunLoop().RunUntilIdle();
+ // One compositing task should be prioritized after input.
+ EXPECT_THAT(run_order,
+ testing::ElementsAre(std::string("P1"), std::string("P2"),
+ std::string("C1"), std::string("T1"),
+ std::string("C2")));
+}
+
+TEST_F(MainThreadSchedulerImplTest, EQTWithNestedLoop) {
+ AdvanceMockTickClockBy(base::TimeDelta::FromMilliseconds(100));
+
+ RunTask(base::BindLambdaForTesting([&] {
+ // After running a task for 10ms, start running a nested loop.
+ // This contributes to the first step EQT by 1ms ((10ms)^2 / 2 / 50ms), and
+ // the window EQT by 50us (1ms / 20).
+ AdvanceMockTickClockBy(base::TimeDelta::FromMilliseconds(10));
+ scheduler_->OnBeginNestedRunLoop();
+
+ // Leave the loop idle for 20ms.
+ AdvanceMockTickClockBy(base::TimeDelta::FromMilliseconds(20));
+
+ RunTask(base::BindLambdaForTesting([&] {
+ // Run a 30ms task in the nested loop.
+ // This contributes to the first step EQT by 8ms ((30ms + 10ms) * 20ms / 2
+ // / 50ms), and the window EQT by 400us (8ms / 20). Also, contributes to
+ // the second step EQT by 1ms ((10ms)^2 / 2 / 50ms), and the window EQT by
+ // 50us (1ms / 20).
+ AdvanceMockTickClockBy(base::TimeDelta::FromMilliseconds(30));
+ }));
+
+ // After 40ms idle duration, exit the nested loop.
+ AdvanceMockTickClockBy(base::TimeDelta::FromMilliseconds(40));
+ scheduler_->OnExitNestedRunLoop();
+
+ // The outer task ends after extra 50ms work.
+ // This contributes to the third step EQT by 25ms ((50ms)^2 / 2 / 50ms), and
+ // the window EQT by 1250us (25ms / 20).
+ AdvanceMockTickClockBy(base::TimeDelta::FromMilliseconds(50));
+ }));
+
+ EXPECT_THAT(scheduler_->expected_queueing_times(),
+ testing::ElementsAre(
+ base::TimeDelta::FromMicroseconds(400 + 50),
+ base::TimeDelta::FromMicroseconds(400 + 50 + 50),
+ base::TimeDelta::FromMicroseconds(400 + 50 + 50 + 1250)));
+}
+
} // namespace main_thread_scheduler_impl_unittest
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc
index 8f2584c5ec6..c7f9dffa9cc 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
namespace blink {
@@ -103,12 +102,8 @@ MainThreadTaskQueue::MainThreadTaskQueue(
queue_type_(params.queue_type),
queue_class_(QueueClassForQueueType(params.queue_type)),
fixed_priority_(params.fixed_priority),
- can_be_deferred_(params.can_be_deferred),
- can_be_throttled_(params.can_be_throttled),
- can_be_paused_(params.can_be_paused),
- can_be_frozen_(params.can_be_frozen),
+ queue_traits_(params.queue_traits),
freeze_when_keep_active_(params.freeze_when_keep_active),
- used_for_important_tasks_(params.used_for_important_tasks),
main_thread_scheduler_(main_thread_scheduler),
frame_scheduler_(params.frame_scheduler) {
if (GetTaskQueueImpl()) {
@@ -126,20 +121,18 @@ MainThreadTaskQueue::MainThreadTaskQueue(
MainThreadTaskQueue::~MainThreadTaskQueue() = default;
-void MainThreadTaskQueue::OnTaskStarted(const TaskQueue::Task& task,
- base::TimeTicks start) {
+void MainThreadTaskQueue::OnTaskStarted(
+ const TaskQueue::Task& task,
+ const TaskQueue::TaskTiming& task_timing) {
if (main_thread_scheduler_)
- main_thread_scheduler_->OnTaskStarted(this, task, start);
+ main_thread_scheduler_->OnTaskStarted(this, task, task_timing);
}
void MainThreadTaskQueue::OnTaskCompleted(
const TaskQueue::Task& task,
- base::TimeTicks start,
- base::TimeTicks end,
- base::Optional<base::TimeDelta> thread_time) {
+ const TaskQueue::TaskTiming& task_timing) {
if (main_thread_scheduler_) {
- main_thread_scheduler_->OnTaskCompleted(this, task, start, end,
- thread_time);
+ main_thread_scheduler_->OnTaskCompleted(this, task, task_timing);
}
}
@@ -172,7 +165,7 @@ void MainThreadTaskQueue::ClearReferencesToSchedulers() {
frame_scheduler_ = nullptr;
}
-FrameScheduler* MainThreadTaskQueue::GetFrameScheduler() const {
+FrameSchedulerImpl* MainThreadTaskQueue::GetFrameScheduler() const {
return frame_scheduler_;
}
@@ -181,7 +174,7 @@ void MainThreadTaskQueue::DetachFromFrameScheduler() {
}
void MainThreadTaskQueue::SetFrameSchedulerForTest(
- FrameScheduler* frame_scheduler) {
+ FrameSchedulerImpl* frame_scheduler) {
frame_scheduler_ = frame_scheduler;
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h
index 99c0747b15b..f3e08007def 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h
@@ -5,23 +5,20 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MAIN_THREAD_TASK_QUEUE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MAIN_THREAD_TASK_QUEUE_H_
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
+#include "base/task/sequence_manager/task_queue.h"
+#include "base/task/sequence_manager/task_queue_impl.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
namespace base {
namespace sequence_manager {
-class TaskQueueManager;
+class SequenceManager;
}
} // namespace base
namespace blink {
-
-class FrameScheduler;
-
namespace scheduler {
+class FrameSchedulerImpl;
class MainThreadSchedulerImpl;
class PLATFORM_EXPORT MainThreadTaskQueue
@@ -82,17 +79,72 @@ class PLATFORM_EXPORT MainThreadTaskQueue
static QueueClass QueueClassForQueueType(QueueType type);
+ using QueueTraitsKeyType = int;
+
+ // QueueTraits represent the deferrable, throttleable, pausable, and freezable
+ // properties of a MainThreadTaskQueue. For non-loading task queues, there
+ // will be at most one task queue with a specific set of QueueTraits, and the
+ // the QueueTraits determine which queues should be used to run which task
+ // types.
+ struct QueueTraits {
+ QueueTraits()
+ : can_be_deferred(false),
+ can_be_throttled(false),
+ can_be_paused(false),
+ can_be_frozen(false) {}
+
+ QueueTraits(const QueueTraits&) = default;
+
+ QueueTraits SetCanBeDeferred(bool value) {
+ can_be_deferred = value;
+ return *this;
+ }
+
+ QueueTraits SetCanBeThrottled(bool value) {
+ can_be_throttled = value;
+ return *this;
+ }
+
+ QueueTraits SetCanBePaused(bool value) {
+ can_be_paused = value;
+ return *this;
+ }
+
+ QueueTraits SetCanBeFrozen(bool value) {
+ can_be_frozen = value;
+ return *this;
+ }
+
+ bool operator==(const QueueTraits& other) const {
+ return can_be_deferred == other.can_be_deferred &&
+ can_be_throttled == other.can_be_throttled &&
+ can_be_paused == other.can_be_paused &&
+ can_be_frozen == other.can_be_frozen;
+ }
+
+ // Return a key suitable for WTF::HashMap.
+ QueueTraitsKeyType Key() const {
+ // Start at 1; 0 and -1 are used for empty/deleted values.
+ int key = 1 << 0;
+ key |= can_be_deferred << 1;
+ key |= can_be_throttled << 2;
+ key |= can_be_paused << 3;
+ key |= can_be_frozen << 4;
+ return key;
+ }
+
+ bool can_be_deferred : 1;
+ bool can_be_throttled : 1;
+ bool can_be_paused : 1;
+ bool can_be_frozen : 1;
+ };
+
struct QueueCreationParams {
explicit QueueCreationParams(QueueType queue_type)
: queue_type(queue_type),
spec(NameForQueueType(queue_type)),
frame_scheduler(nullptr),
- can_be_deferred(false),
- can_be_throttled(false),
- can_be_paused(false),
- can_be_frozen(false),
- freeze_when_keep_active(false),
- used_for_important_tasks(false) {}
+ freeze_when_keep_active(false) {}
QueueCreationParams SetFixedPriority(
base::Optional<base::sequence_manager::TaskQueue::QueuePriority>
@@ -101,33 +153,35 @@ class PLATFORM_EXPORT MainThreadTaskQueue
return *this;
}
+ QueueCreationParams SetFreezeWhenKeepActive(bool value) {
+ freeze_when_keep_active = value;
+ return *this;
+ }
+
+ // Forwarded calls to |queue_traits|
+
QueueCreationParams SetCanBeDeferred(bool value) {
- can_be_deferred = value;
+ queue_traits = queue_traits.SetCanBeDeferred(value);
return *this;
}
QueueCreationParams SetCanBeThrottled(bool value) {
- can_be_throttled = value;
+ queue_traits = queue_traits.SetCanBeThrottled(value);
return *this;
}
QueueCreationParams SetCanBePaused(bool value) {
- can_be_paused = value;
+ queue_traits = queue_traits.SetCanBePaused(value);
return *this;
}
QueueCreationParams SetCanBeFrozen(bool value) {
- can_be_frozen = value;
- return *this;
- }
-
- QueueCreationParams SetFreezeWhenKeepActive(bool value) {
- freeze_when_keep_active = value;
+ queue_traits = queue_traits.SetCanBeFrozen(value);
return *this;
}
- QueueCreationParams SetUsedForImportantTasks(bool value) {
- used_for_important_tasks = value;
+ QueueCreationParams SetQueueTraits(QueueTraits value) {
+ queue_traits = value;
return *this;
}
@@ -157,13 +211,9 @@ class PLATFORM_EXPORT MainThreadTaskQueue
base::sequence_manager::TaskQueue::Spec spec;
base::Optional<base::sequence_manager::TaskQueue::QueuePriority>
fixed_priority;
- FrameScheduler* frame_scheduler;
- bool can_be_deferred;
- bool can_be_throttled;
- bool can_be_paused;
- bool can_be_frozen;
+ FrameSchedulerImpl* frame_scheduler;
+ QueueTraits queue_traits;
bool freeze_when_keep_active;
- bool used_for_important_tasks;
};
~MainThreadTaskQueue() override;
@@ -177,37 +227,38 @@ class PLATFORM_EXPORT MainThreadTaskQueue
return fixed_priority_;
}
- bool CanBeDeferred() const { return can_be_deferred_; }
+ bool CanBeDeferred() const { return queue_traits_.can_be_deferred; }
- bool CanBeThrottled() const { return can_be_throttled_; }
+ bool CanBeThrottled() const { return queue_traits_.can_be_throttled; }
- bool CanBePaused() const { return can_be_paused_; }
+ bool CanBePaused() const { return queue_traits_.can_be_paused; }
- bool CanBeFrozen() const { return can_be_frozen_; }
+ bool CanBeFrozen() const { return queue_traits_.can_be_frozen; }
bool FreezeWhenKeepActive() const { return freeze_when_keep_active_; }
- bool UsedForImportantTasks() const { return used_for_important_tasks_; }
+ QueueTraits GetQueueTraits() const { return queue_traits_; }
- void OnTaskStarted(const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start);
+ void OnTaskStarted(
+ const base::sequence_manager::TaskQueue::Task& task,
+ const base::sequence_manager::TaskQueue::TaskTiming& task_timing);
- void OnTaskCompleted(const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start,
- base::TimeTicks end,
- base::Optional<base::TimeDelta> thread_time);
+ void OnTaskCompleted(
+ const base::sequence_manager::TaskQueue::Task& task,
+ const base::sequence_manager::TaskQueue::TaskTiming& task_timing);
void DetachFromMainThreadScheduler();
// Override base method to notify MainThreadScheduler about shutdown queue.
void ShutdownTaskQueue() override;
- FrameScheduler* GetFrameScheduler() const;
+ FrameSchedulerImpl* GetFrameScheduler() const;
void DetachFromFrameScheduler();
protected:
- void SetFrameSchedulerForTest(FrameScheduler* frame);
+ void SetFrameSchedulerForTest(FrameSchedulerImpl* frame_scheduler);
+ // TODO(kraynov): Consider options to remove TaskQueueImpl reference here.
MainThreadTaskQueue(
std::unique_ptr<base::sequence_manager::internal::TaskQueueImpl> impl,
const Spec& spec,
@@ -215,7 +266,7 @@ class PLATFORM_EXPORT MainThreadTaskQueue
MainThreadSchedulerImpl* main_thread_scheduler);
private:
- friend class base::sequence_manager::TaskQueueManager;
+ friend class base::sequence_manager::SequenceManager;
// Clear references to main thread scheduler and frame scheduler and dispatch
// appropriate notifications. This is the common part of ShutdownTaskQueue and
@@ -226,17 +277,13 @@ class PLATFORM_EXPORT MainThreadTaskQueue
const QueueClass queue_class_;
const base::Optional<base::sequence_manager::TaskQueue::QueuePriority>
fixed_priority_;
- const bool can_be_deferred_;
- const bool can_be_throttled_;
- const bool can_be_paused_;
- const bool can_be_frozen_;
+ const QueueTraits queue_traits_;
const bool freeze_when_keep_active_;
- const bool used_for_important_tasks_;
// Needed to notify renderer scheduler about completed tasks.
MainThreadSchedulerImpl* main_thread_scheduler_; // NOT OWNED
- FrameScheduler* frame_scheduler_; // NOT OWNED
+ FrameSchedulerImpl* frame_scheduler_; // NOT OWNED
DISALLOW_COPY_AND_ASSIGN(MainThreadTaskQueue);
};
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc
index a12e5f32f40..0b74a9da022 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc
@@ -6,16 +6,20 @@
#include "base/logging.h"
#include "base/metrics/field_trial_params.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/optional.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
+#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/scheduler/base/virtual_time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/child/default_params.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/auto_advancing_virtual_time_domain.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/use_case.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/page_lifecycle_state.h"
namespace blink {
namespace scheduler {
@@ -32,13 +36,16 @@ constexpr double kDefaultMaxBackgroundThrottlingDelayInSeconds = 0;
constexpr base::TimeDelta kMinimalBackgroundThrottlingDurationToReport =
base::TimeDelta::FromSeconds(3);
-// We do not throttle anything while audio is played and shortly after that.
-constexpr base::TimeDelta kRecentAudioDelay = base::TimeDelta::FromSeconds(5);
-
// Delay for fully throttling the page after backgrounding.
constexpr base::TimeDelta kThrottlingDelayAfterBackgrounding =
base::TimeDelta::FromSeconds(10);
+// The amount of time to wait before suspending shared timers, and loading
+// etc. after the renderer has been backgrounded. This is used only if
+// background suspension is enabled.
+constexpr base::TimeDelta kDelayForBackgroundTabFreezing =
+ base::TimeDelta::FromMinutes(5);
+
// Values coming from the field trial config are interpreted as follows:
// -1 is "not set". Scheduler should use a reasonable default.
// 0 corresponds to base::nullopt.
@@ -102,11 +109,9 @@ BackgroundThrottlingSettings GetBackgroundThrottlingSettings() {
PageSchedulerImpl::PageSchedulerImpl(
PageScheduler::Delegate* delegate,
- MainThreadSchedulerImpl* main_thread_scheduler,
- bool disable_background_timer_throttling)
+ MainThreadSchedulerImpl* main_thread_scheduler)
: main_thread_scheduler_(main_thread_scheduler),
page_visibility_(kDefaultPageVisibility),
- disable_background_timer_throttling_(disable_background_timer_throttling),
audio_state_(AudioState::kSilent),
is_frozen_(false),
reported_background_throttling_since_navigation_(false),
@@ -123,6 +128,23 @@ PageSchedulerImpl::PageSchedulerImpl(
&PageSchedulerImpl::DoThrottlePage, base::Unretained(this)));
on_audio_silent_closure_.Reset(base::BindRepeating(
&PageSchedulerImpl::OnAudioSilent, base::Unretained(this)));
+ do_freeze_page_callback_.Reset(base::BindRepeating(
+ &PageSchedulerImpl::DoFreezePage, base::Unretained(this)));
+
+ int32_t delay_for_background_tab_freezing_millis;
+ if (base::StringToInt(
+ base::GetFieldTrialParamValue("BackgroundTabFreezing",
+ "DelayForBackgroundTabFreezingMills"),
+ &delay_for_background_tab_freezing_millis)) {
+ delay_for_background_tab_freezing_ = base::TimeDelta::FromMilliseconds(
+ delay_for_background_tab_freezing_millis);
+ } else {
+ delay_for_background_tab_freezing_ = kDelayForBackgroundTabFreezing;
+ }
+ page_lifecycle_state_tracker_.reset(new PageLifecycleStateTracker(
+ this, kDefaultPageVisibility == PageVisibilityState::kVisible
+ ? PageLifecycleState::kActive
+ : PageLifecycleState::kHiddenBackgrounded));
}
PageSchedulerImpl::~PageSchedulerImpl() {
@@ -137,45 +159,98 @@ PageSchedulerImpl::~PageSchedulerImpl() {
background_time_budget_pool_->Close();
}
+// static
+// kRecentAudioDelay is defined in the header for use in unit tests and requires
+// storage for linking to succeed with some compiler toolchains.
+constexpr base::TimeDelta PageSchedulerImpl::kRecentAudioDelay;
+
void PageSchedulerImpl::SetPageVisible(bool page_visible) {
PageVisibilityState page_visibility = page_visible
? PageVisibilityState::kVisible
: PageVisibilityState::kHidden;
- if (disable_background_timer_throttling_ ||
- page_visibility_ == page_visibility)
+ if (page_visibility_ == page_visibility)
return;
page_visibility_ = page_visibility;
- // Visible pages should not be frozen.
- if (page_visibility_ == PageVisibilityState::kVisible)
- SetPageFrozenImpl(false, NotificationPolicy::kDoNotNotifyFrames);
+ switch (page_visibility_) {
+ case PageVisibilityState::kVisible:
+ // Visible pages should not be frozen.
+ SetPageFrozenImpl(false, NotificationPolicy::kDoNotNotifyFrames);
+ page_lifecycle_state_tracker_->SetPageLifecycleState(
+ PageLifecycleState::kActive);
+ break;
+ case PageVisibilityState::kHidden:
+ page_lifecycle_state_tracker_->SetPageLifecycleState(
+ IsBackgrounded() ? PageLifecycleState::kHiddenBackgrounded
+ : PageLifecycleState::kHiddenForegrounded);
+ break;
+ }
+
+ if (ShouldFreezePage()) {
+ main_thread_scheduler_->ControlTaskRunner()->PostDelayedTask(
+ FROM_HERE, do_freeze_page_callback_.GetCallback(),
+ delay_for_background_tab_freezing_);
+ }
for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_)
frame_scheduler->SetPageVisibilityForTracing(page_visibility_);
- UpdateBackgroundThrottlingState(NotificationPolicy::kDoNotNotifyFrames);
+ UpdateBackgroundSchedulingLifecycleState(
+ NotificationPolicy::kDoNotNotifyFrames);
NotifyFrames();
}
void PageSchedulerImpl::SetPageFrozen(bool frozen) {
+ // Only transitions from HIDDEN to FROZEN are allowed for pages (see
+ // https://github.com/WICG/page-lifecycle).
+ // This is the page freezing path we expose via WebView, which is how
+ // embedders freeze pages. Visibility is also controlled by the embedder,
+ // through [WebView|WebViewFrameWidget]::SetVisibilityState(). The following
+ // happens if the embedder attempts to freeze a page that it set to visible.
+ // We check for this illegal state transition later on this code path in page
+ // scheduler and frame scheduler when computing the new lifecycle state, but
+ // it is desirable to reject the page freeze to prevent the scheduler from
+ // being put in a bad state. See https://crbug.com/873214 for context of how
+ // this can happen on the browser side.
+ if (frozen && IsPageVisible()) {
+ DCHECK(false);
+ return;
+ }
SetPageFrozenImpl(frozen, NotificationPolicy::kNotifyFrames);
}
void PageSchedulerImpl::SetPageFrozenImpl(
bool frozen,
PageSchedulerImpl::NotificationPolicy notification_policy) {
+ do_freeze_page_callback_.Cancel();
if (is_frozen_ == frozen)
return;
is_frozen_ = frozen;
for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_)
frame_scheduler->SetPageFrozenForTracing(frozen);
- if (delegate_)
- delegate_->SetPageFrozen(frozen);
if (notification_policy ==
PageSchedulerImpl::NotificationPolicy::kNotifyFrames)
NotifyFrames();
+ if (frozen) {
+ page_lifecycle_state_tracker_->SetPageLifecycleState(
+ PageLifecycleState::kFrozen);
+ Platform::Current()->RequestPurgeMemory();
+ } else {
+ // The new state may have already been set if unfreezing through the
+ // renderer, but that's okay - duplicate state changes won't be recorded.
+ if (page_visibility_ == PageVisibilityState::kVisible) {
+ page_lifecycle_state_tracker_->SetPageLifecycleState(
+ PageLifecycleState::kActive);
+ } else if (IsBackgrounded()) {
+ page_lifecycle_state_tracker_->SetPageLifecycleState(
+ PageLifecycleState::kHiddenBackgrounded);
+ } else {
+ page_lifecycle_state_tracker_->SetPageLifecycleState(
+ PageLifecycleState::kHiddenForegrounded);
+ }
+ }
}
void PageSchedulerImpl::SetKeepActive(bool keep_active) {
@@ -197,25 +272,25 @@ bool PageSchedulerImpl::IsMainFrameLocal() const {
return is_main_frame_local_;
}
+bool PageSchedulerImpl::IsLoading() const {
+ return main_thread_scheduler_->current_use_case() == UseCase::kLoading;
+}
+
void PageSchedulerImpl::SetIsMainFrameLocal(bool is_local) {
is_main_frame_local_ = is_local;
}
-std::unique_ptr<FrameSchedulerImpl> PageSchedulerImpl::CreateFrameSchedulerImpl(
- base::trace_event::BlameContext* blame_context,
- FrameScheduler::FrameType frame_type) {
+void PageSchedulerImpl::RegisterFrameSchedulerImpl(
+ FrameSchedulerImpl* frame_scheduler) {
MaybeInitializeBackgroundCPUTimeBudgetPool();
- std::unique_ptr<FrameSchedulerImpl> frame_scheduler(new FrameSchedulerImpl(
- main_thread_scheduler_, this, blame_context, frame_type));
+ frame_schedulers_.insert(frame_scheduler);
frame_scheduler->UpdatePolicy();
- frame_schedulers_.insert(frame_scheduler.get());
- return frame_scheduler;
}
std::unique_ptr<blink::FrameScheduler> PageSchedulerImpl::CreateFrameScheduler(
blink::BlameContext* blame_context,
FrameScheduler::FrameType frame_type) {
- return CreateFrameSchedulerImpl(blame_context, frame_type);
+ return FrameSchedulerImpl::Create(this, blame_context, frame_type);
}
void PageSchedulerImpl::Unregister(FrameSchedulerImpl* frame_scheduler) {
@@ -279,6 +354,12 @@ void PageSchedulerImpl::AudioStateChanged(bool is_audio_playing) {
if (is_audio_playing) {
audio_state_ = AudioState::kAudible;
on_audio_silent_closure_.Cancel();
+ if (page_visibility_ == PageVisibilityState::kHidden) {
+ page_lifecycle_state_tracker_->SetPageLifecycleState(
+ PageLifecycleState::kHiddenForegrounded);
+ }
+ // Pages with audio playing should not be frozen.
+ SetPageFrozenImpl(false, NotificationPolicy::kDoNotNotifyFrames);
NotifyFrames();
main_thread_scheduler_->OnAudioStateChanged();
} else {
@@ -300,6 +381,15 @@ void PageSchedulerImpl::OnAudioSilent() {
audio_state_ = AudioState::kSilent;
NotifyFrames();
main_thread_scheduler_->OnAudioStateChanged();
+ if (IsBackgrounded()) {
+ page_lifecycle_state_tracker_->SetPageLifecycleState(
+ PageLifecycleState::kHiddenBackgrounded);
+ }
+ if (ShouldFreezePage()) {
+ main_thread_scheduler_->ControlTaskRunner()->PostDelayedTask(
+ FROM_HERE, do_freeze_page_callback_.GetCallback(),
+ delay_for_background_tab_freezing_);
+ }
}
bool PageSchedulerImpl::IsExemptFromBudgetBasedThrottling() const {
@@ -314,8 +404,10 @@ bool PageSchedulerImpl::HasActiveConnection() const {
return has_active_connection_;
}
-void PageSchedulerImpl::RequestBeginMainFrameNotExpected(bool new_state) {
- delegate_->RequestBeginMainFrameNotExpected(new_state);
+bool PageSchedulerImpl::RequestBeginMainFrameNotExpected(bool new_state) {
+ if (!delegate_)
+ return false;
+ return delegate_->RequestBeginMainFrameNotExpected(new_state);
}
bool PageSchedulerImpl::IsAudioPlaying() const {
@@ -343,7 +435,7 @@ void PageSchedulerImpl::OnConnectionUpdated() {
if (has_active_connection_ != has_active_connection) {
has_active_connection_ = has_active_connection;
- UpdateBackgroundBudgetPoolThrottlingState();
+ UpdateBackgroundBudgetPoolSchedulingLifecycleState();
}
}
@@ -358,12 +450,11 @@ void PageSchedulerImpl::AsValueInto(
base::trace_event::TracedValue* state) const {
state->SetBoolean("page_visible",
page_visibility_ == PageVisibilityState::kVisible);
- state->SetBoolean("disable_background_timer_throttling",
- disable_background_timer_throttling_);
state->SetBoolean("is_audio_playing", IsAudioPlaying());
state->SetBoolean("is_frozen", is_frozen_);
state->SetBoolean("reported_background_throttling_since_navigation",
reported_background_throttling_since_navigation_);
+ state->SetBoolean("is_page_freezable", IsBackgrounded());
state->BeginDictionary("frame_schedulers");
for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_) {
@@ -407,7 +498,7 @@ void PageSchedulerImpl::MaybeInitializeBackgroundCPUTimeBudgetPool() {
lazy_now.Now(), settings.initial_budget.value());
}
- UpdateBackgroundBudgetPoolThrottlingState();
+ UpdateBackgroundBudgetPoolSchedulingLifecycleState();
}
void PageSchedulerImpl::OnThrottlingReported(
@@ -430,12 +521,12 @@ void PageSchedulerImpl::OnThrottlingReported(
delegate_->ReportIntervention(String::FromUTF8(message.c_str()));
}
-void PageSchedulerImpl::UpdateBackgroundThrottlingState(
+void PageSchedulerImpl::UpdateBackgroundSchedulingLifecycleState(
NotificationPolicy notification_policy) {
if (page_visibility_ == PageVisibilityState::kVisible) {
is_throttled_ = false;
do_throttle_page_callback_.Cancel();
- UpdateBackgroundBudgetPoolThrottlingState();
+ UpdateBackgroundBudgetPoolSchedulingLifecycleState();
} else {
main_thread_scheduler_->ControlTaskRunner()->PostDelayedTask(
FROM_HERE, do_throttle_page_callback_.GetCallback(),
@@ -449,11 +540,11 @@ void PageSchedulerImpl::DoThrottlePage() {
do_throttle_page_callback_.Cancel();
is_throttled_ = true;
- UpdateBackgroundBudgetPoolThrottlingState();
+ UpdateBackgroundBudgetPoolSchedulingLifecycleState();
NotifyFrames();
}
-void PageSchedulerImpl::UpdateBackgroundBudgetPoolThrottlingState() {
+void PageSchedulerImpl::UpdateBackgroundBudgetPoolSchedulingLifecycleState() {
if (!background_time_budget_pool_)
return;
@@ -467,8 +558,9 @@ void PageSchedulerImpl::UpdateBackgroundBudgetPoolThrottlingState() {
}
void PageSchedulerImpl::NotifyFrames() {
- for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_)
+ for (FrameSchedulerImpl* frame_scheduler : frame_schedulers_) {
frame_scheduler->UpdatePolicy();
+ }
}
size_t PageSchedulerImpl::FrameCount() const {
@@ -481,6 +573,10 @@ void PageSchedulerImpl::SetMaxVirtualTimeTaskStarvationCount(
max_task_starvation_count);
}
+MainThreadSchedulerImpl* PageSchedulerImpl::GetMainThreadScheduler() const {
+ return main_thread_scheduler_;
+}
+
ukm::UkmRecorder* PageSchedulerImpl::GetUkmRecorder() {
if (!delegate_)
return nullptr;
@@ -493,5 +589,108 @@ int64_t PageSchedulerImpl::GetUkmSourceId() {
return delegate_->GetUkmSourceId();
}
+bool PageSchedulerImpl::IsBackgrounded() const {
+ return page_visibility_ == PageVisibilityState::kHidden && !IsAudioPlaying();
+}
+
+bool PageSchedulerImpl::ShouldFreezePage() const {
+ if (!RuntimeEnabledFeatures::StopInBackgroundEnabled())
+ return false;
+ return IsBackgrounded();
+}
+
+void PageSchedulerImpl::DoFreezePage() {
+ DCHECK(ShouldFreezePage());
+ SetPageFrozenImpl(true, NotificationPolicy::kNotifyFrames);
+}
+
+PageSchedulerImpl::PageLifecycleStateTracker::PageLifecycleStateTracker(
+ PageSchedulerImpl* page_scheduler_impl,
+ PageLifecycleState state)
+ : page_scheduler_impl_(page_scheduler_impl),
+ current_state_(kDefaultPageLifecycleState) {
+ SetPageLifecycleState(state);
+}
+
+void PageSchedulerImpl::PageLifecycleStateTracker::SetPageLifecycleState(
+ PageLifecycleState new_state) {
+ if (new_state == current_state_)
+ return;
+ base::Optional<PageLifecycleStateTransition> transition =
+ ComputePageLifecycleStateTransition(current_state_, new_state);
+ if (transition) {
+ UMA_HISTOGRAM_ENUMERATION(
+ kHistogramPageLifecycleStateTransition,
+ static_cast<PageLifecycleStateTransition>(transition.value()));
+ }
+ if (page_scheduler_impl_->delegate_)
+ page_scheduler_impl_->delegate_->SetLifecycleState(new_state);
+ current_state_ = new_state;
+}
+
+// static
+base::Optional<PageSchedulerImpl::PageLifecycleStateTransition>
+PageSchedulerImpl::PageLifecycleStateTracker::
+ ComputePageLifecycleStateTransition(PageLifecycleState old_state,
+ PageLifecycleState new_state) {
+ switch (old_state) {
+ case PageLifecycleState::kUnknown:
+ // We don't track the initial transition.
+ return base::nullopt;
+ case PageLifecycleState::kActive:
+ switch (new_state) {
+ case PageLifecycleState::kHiddenForegrounded:
+ return PageLifecycleStateTransition::kActiveToHiddenForegrounded;
+ case PageLifecycleState::kHiddenBackgrounded:
+ return PageLifecycleStateTransition::kActiveToHiddenBackgrounded;
+ default:
+ NOTREACHED();
+ return base::nullopt;
+ }
+ case PageLifecycleState::kHiddenForegrounded:
+ switch (new_state) {
+ case PageLifecycleState::kActive:
+ return PageLifecycleStateTransition::kHiddenForegroundedToActive;
+ case PageLifecycleState::kHiddenBackgrounded:
+ return PageLifecycleStateTransition::
+ kHiddenForegroundedToHiddenBackgrounded;
+ case PageLifecycleState::kFrozen:
+ return PageLifecycleStateTransition::kHiddenForegroundedToFrozen;
+ default:
+ NOTREACHED();
+ return base::nullopt;
+ }
+ case PageLifecycleState::kHiddenBackgrounded:
+ switch (new_state) {
+ case PageLifecycleState::kActive:
+ return PageLifecycleStateTransition::kHiddenBackgroundedToActive;
+ case PageLifecycleState::kHiddenForegrounded:
+ return PageLifecycleStateTransition::
+ kHiddenBackgroundedToHiddenForegrounded;
+ case PageLifecycleState::kFrozen:
+ return PageLifecycleStateTransition::kHiddenBackgroundedToFrozen;
+ default:
+ NOTREACHED();
+ return base::nullopt;
+ }
+ case PageLifecycleState::kFrozen:
+ switch (new_state) {
+ case PageLifecycleState::kActive:
+ return PageLifecycleStateTransition::kFrozenToActive;
+ case PageLifecycleState::kHiddenForegrounded:
+ return PageLifecycleStateTransition::kFrozenToHiddenForegrounded;
+ case PageLifecycleState::kHiddenBackgrounded:
+ return PageLifecycleStateTransition::kFrozenToHiddenBackgrounded;
+ default:
+ NOTREACHED();
+ return base::nullopt;
+ }
+ }
+}
+
+// static
+const char PageSchedulerImpl::kHistogramPageLifecycleStateTransition[] =
+ "PageScheduler.PageLifecycleStateTransition";
+
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h
index b7cd3a32fee..1d4d6db82f3 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h
@@ -12,10 +12,13 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
+#include "base/optional.h"
+#include "base/task/sequence_manager/task_queue.h"
+#include "base/time/time.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/child/page_visibility_state.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.h"
+#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/scheduler/util/tracing_helper.h"
@@ -29,6 +32,12 @@ class TracedValue;
namespace blink {
namespace scheduler {
+namespace page_scheduler_impl_unittest {
+class PageSchedulerImplTest;
+class PageSchedulerImplPageTransitionTest;
+class
+ PageSchedulerImplPageTransitionTest_PageLifecycleStateTransitionMetric_Test;
+} // namespace page_scheduler_impl_unittest
class CPUTimeBudgetPool;
class FrameSchedulerImpl;
@@ -36,9 +45,7 @@ class MainThreadSchedulerImpl;
class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
public:
- PageSchedulerImpl(PageScheduler::Delegate*,
- MainThreadSchedulerImpl*,
- bool disable_background_timer_throttling);
+ PageSchedulerImpl(PageScheduler::Delegate*, MainThreadSchedulerImpl*);
~PageSchedulerImpl() override;
@@ -67,7 +74,7 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
bool IsAudioPlaying() const override;
bool IsExemptFromBudgetBasedThrottling() const override;
bool HasActiveConnectionForTest() const override;
- void RequestBeginMainFrameNotExpected(bool new_state) override;
+ bool RequestBeginMainFrameNotExpected(bool new_state) override;
void AddVirtualTimeObserver(VirtualTimeObserver*) override;
void RemoveVirtualTimeObserver(VirtualTimeObserver*) override;
@@ -84,9 +91,11 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
bool IsThrottled() const;
bool KeepActive() const;
- std::unique_ptr<FrameSchedulerImpl> CreateFrameSchedulerImpl(
- base::trace_event::BlameContext*,
- FrameScheduler::FrameType);
+ bool IsLoading() const;
+
+ void RegisterFrameSchedulerImpl(FrameSchedulerImpl* frame_scheduler);
+
+ MainThreadSchedulerImpl* GetMainThreadScheduler() const;
void Unregister(FrameSchedulerImpl*);
void OnNavigation();
@@ -109,6 +118,11 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
private:
friend class FrameSchedulerImpl;
+ friend class page_scheduler_impl_unittest::PageSchedulerImplTest;
+ friend class page_scheduler_impl_unittest::
+ PageSchedulerImplPageTransitionTest;
+ friend class page_scheduler_impl_unittest::
+ PageSchedulerImplPageTransitionTest_PageLifecycleStateTransitionMetric_Test;
enum class AudioState {
kSilent,
@@ -118,6 +132,51 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
enum class NotificationPolicy { kNotifyFrames, kDoNotNotifyFrames };
+ // This enum is used for a histogram and should not be renumbered.
+ // It tracks permissible page state transitions between PageLifecycleStates.
+ // We allow all transitions except for visible to frozen and self transitions.
+ enum class PageLifecycleStateTransition {
+ kActiveToHiddenForegrounded = 0,
+ kActiveToHiddenBackgrounded = 1,
+ kHiddenForegroundedToActive = 2,
+ kHiddenForegroundedToHiddenBackgrounded = 3,
+ kHiddenForegroundedToFrozen = 4,
+ kHiddenBackgroundedToActive = 5,
+ kHiddenBackgroundedToHiddenForegrounded = 6,
+ kHiddenBackgroundedToFrozen = 7,
+ kFrozenToActive = 8,
+ kFrozenToHiddenForegrounded = 9,
+ kFrozenToHiddenBackgrounded = 10,
+ kMaxValue = kFrozenToHiddenBackgrounded,
+ };
+
+ class PageLifecycleStateTracker {
+ public:
+ explicit PageLifecycleStateTracker(PageSchedulerImpl*, PageLifecycleState);
+ ~PageLifecycleStateTracker() = default;
+
+ void SetPageLifecycleState(PageLifecycleState);
+
+ private:
+ static base::Optional<PageLifecycleStateTransition>
+ ComputePageLifecycleStateTransition(PageLifecycleState old_state,
+ PageLifecycleState new_state);
+
+ static void RecordPageLifecycleStateTransition(
+ PageLifecycleStateTransition);
+
+ PageSchedulerImpl* page_scheduler_impl_;
+ PageLifecycleState current_state_;
+
+ DISALLOW_COPY_AND_ASSIGN(PageLifecycleStateTracker);
+ };
+
+ // We do not throttle anything while audio is played and shortly after that.
+ static constexpr base::TimeDelta kRecentAudioDelay =
+ base::TimeDelta::FromSeconds(5);
+
+ static const char kHistogramPageLifecycleStateTransition[];
+
// Support not issuing a notification to frames when we disable freezing as
// a part of foregrounding the page.
void SetPageFrozenImpl(bool frozen, NotificationPolicy notification_policy);
@@ -129,12 +188,13 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
// Depending on page visibility, either turns throttling off, or schedules a
// call to enable it after a grace period.
- void UpdateBackgroundThrottlingState(NotificationPolicy notification_policy);
+ void UpdateBackgroundSchedulingLifecycleState(
+ NotificationPolicy notification_policy);
- // As a part of UpdateBackgroundThrottlingState set correct
+ // As a part of UpdateBackgroundSchedulingLifecycleState set correct
// background_time_budget_pool_ state depending on page visibility and
// number of active connections.
- void UpdateBackgroundBudgetPoolThrottlingState();
+ void UpdateBackgroundBudgetPoolSchedulingLifecycleState();
// Callback for marking page is silent after a delay since last audible
// signal.
@@ -150,12 +210,23 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
void EnableThrottling();
+ // Returns true if the page is backgrounded, false otherwise. A page is
+ // considered backgrounded if it is both not visible and not playing audio.
+ bool IsBackgrounded() const;
+
+ // Returns true if the page should be frozen after delay, which happens if
+ // IsBackgrounded() and freezing is enabled.
+ bool ShouldFreezePage() const;
+
+ // Callback for freezing the page. Freezing must be enabled and the page must
+ // be freezable.
+ void DoFreezePage();
+
TraceableVariableController tracing_controller_;
std::set<FrameSchedulerImpl*> frame_schedulers_;
MainThreadSchedulerImpl* main_thread_scheduler_;
PageVisibilityState page_visibility_;
- bool disable_background_timer_throttling_;
AudioState audio_state_;
bool is_frozen_;
bool reported_background_throttling_since_navigation_;
@@ -168,6 +239,9 @@ class PLATFORM_EXPORT PageSchedulerImpl : public PageScheduler {
PageScheduler::Delegate* delegate_; // Not owned.
CancelableClosureHolder do_throttle_page_callback_;
CancelableClosureHolder on_audio_silent_closure_;
+ CancelableClosureHolder do_freeze_page_callback_;
+ base::TimeDelta delay_for_background_tab_freezing_;
+ std::unique_ptr<PageLifecycleStateTracker> page_lifecycle_state_tracker_;
base::WeakPtrFactory<PageSchedulerImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PageSchedulerImpl);
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc
index 67771e96e57..e17810b31c4 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc
@@ -5,6 +5,7 @@
#include "third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h"
#include <memory>
+#include <vector>
#include "base/callback.h"
#include "base/location.h"
@@ -13,17 +14,21 @@
#include "base/metrics/field_trial_params.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "components/viz/test/ordered_simple_task_runner.h"
+#include "base/task/sequence_manager/test/fake_task.h"
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/test_mock_time_task_runner.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
#include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
using base::sequence_manager::TaskQueue;
+using base::sequence_manager::FakeTask;
+using base::sequence_manager::FakeTaskTiming;
using testing::ElementsAre;
using VirtualTimePolicy = blink::PageScheduler::VirtualTimePolicy;
@@ -32,23 +37,34 @@ namespace scheduler {
// To avoid symbol collisions in jumbo builds.
namespace page_scheduler_impl_unittest {
+namespace {
+void IncrementCounter(int* counter) {
+ ++*counter;
+}
+} // namespace
+
+using base::Bucket;
+using testing::UnorderedElementsAreArray;
+
class PageSchedulerImplTest : public testing::Test {
public:
PageSchedulerImplTest() = default;
~PageSchedulerImplTest() override = default;
+ protected:
void SetUp() override {
- clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
- mock_task_runner_ =
- base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, true);
+ test_task_runner_ = base::WrapRefCounted(new base::TestMockTimeTaskRunner(
+ base::TestMockTimeTaskRunner::Type::kBoundToThread));
+ // A null clock triggers some assertions.
+ test_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMilliseconds(5));
scheduler_.reset(new MainThreadSchedulerImpl(
- base::sequence_manager::TaskQueueManagerForTest::Create(
- nullptr, mock_task_runner_, &clock_),
+ base::sequence_manager::SequenceManagerForTest::Create(
+ nullptr, test_task_runner_, test_task_runner_->GetMockTickClock()),
base::nullopt));
- page_scheduler_.reset(new PageSchedulerImpl(
- nullptr, scheduler_.get(), DisableBackgroundTimerThrottling()));
- frame_scheduler_ = page_scheduler_->CreateFrameSchedulerImpl(
- nullptr, FrameScheduler::FrameType::kSubframe);
+ page_scheduler_.reset(new PageSchedulerImpl(nullptr, scheduler_.get()));
+ frame_scheduler_ = FrameSchedulerImpl::Create(
+ page_scheduler_.get(), nullptr, FrameScheduler::FrameType::kSubframe);
}
void TearDown() override {
@@ -58,14 +74,25 @@ class PageSchedulerImplTest : public testing::Test {
scheduler_.reset();
}
- virtual bool DisableBackgroundTimerThrottling() const { return false; }
+ void FastForwardTo(base::TimeTicks time) {
+ base::TimeTicks now = test_task_runner_->GetMockTickClock()->NowTicks();
+ CHECK_LE(now, time);
+ test_task_runner_->FastForwardBy(time - now);
+ }
- protected:
static scoped_refptr<TaskQueue> ThrottleableTaskQueueForScheduler(
FrameSchedulerImpl* scheduler) {
return scheduler->ThrottleableTaskQueue();
}
+ base::TimeDelta delay_for_background_tab_freezing() const {
+ return page_scheduler_->delay_for_background_tab_freezing_;
+ }
+
+ static base::TimeDelta recent_audio_delay() {
+ return PageSchedulerImpl::kRecentAudioDelay;
+ }
+
scoped_refptr<base::SingleThreadTaskRunner> ThrottleableTaskRunner() {
return TaskQueueWithTaskType::Create(ThrottleableTaskQueue(),
TaskType::kInternalTest);
@@ -96,8 +123,75 @@ class PageSchedulerImplTest : public testing::Test {
return frame_scheduler_->UnpausableTaskQueue();
}
- base::SimpleTestTickClock clock_;
- scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
+ bool ShouldFreezePage() { return page_scheduler_->ShouldFreezePage(); }
+
+ // Verifies that freezing the PageScheduler prevents tasks from running. Then
+ // set the page as visible or unfreezes it while still hidden (depending on
+ // the argument), and verifies that tasks can run.
+ void TestFreeze(bool make_page_visible) {
+ ScopedStopNonTimersInBackgroundForTest stop_non_timers_enabler(true);
+
+ int counter = 0;
+ LoadingTaskQueue()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+ ThrottleableTaskQueue()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+ DeferrableTaskQueue()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+ PausableTaskQueue()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+ UnpausableTaskQueue()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+
+ page_scheduler_->SetPageVisible(false);
+ EXPECT_EQ(false, page_scheduler_->IsFrozen());
+
+ // In a backgrounded active page, all queues should run.
+ test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_EQ(5, counter);
+
+ LoadingTaskQueue()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+ ThrottleableTaskQueue()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+ DeferrableTaskQueue()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+ PausableTaskQueue()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+ UnpausableTaskQueue()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+ counter = 0;
+
+ page_scheduler_->SetPageFrozen(true);
+ EXPECT_EQ(true, page_scheduler_->IsFrozen());
+
+ // In a backgrounded frozen page, only Unpausable queue should run.
+ test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_EQ(1, counter);
+
+ // Make the page visible or unfreeze it while hidden.
+ if (make_page_visible)
+ page_scheduler_->SetPageVisible(true);
+ else
+ page_scheduler_->SetPageFrozen(false);
+ EXPECT_EQ(false, page_scheduler_->IsFrozen());
+
+ // Once the page is unfrozen, the rest of the queues should run.
+ test_task_runner_->FastForwardUntilNoTasksRemain();
+ EXPECT_EQ(5, counter);
+ }
+
+ scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_;
std::unique_ptr<MainThreadSchedulerImpl> scheduler_;
std::unique_ptr<PageSchedulerImpl> page_scheduler_;
std::unique_ptr<FrameSchedulerImpl> frame_scheduler_;
@@ -138,7 +232,10 @@ base::OnceClosure MakeRepeatingTask(scoped_refptr<TaskQueue> task_queue,
void RunRepeatingTask(scoped_refptr<TaskQueue> task_queue,
int* run_count,
base::TimeDelta delay) {
- ++*run_count;
+ // Limit the number of repetitions.
+ // Test cases can make expectations against this number.
+ if (++*run_count == 2000)
+ return;
TaskQueue* task_queue_ptr = task_queue.get();
task_queue_ptr->PostDelayedTask(
FROM_HERE, MakeRepeatingTask(std::move(task_queue_ptr), run_count, delay),
@@ -157,7 +254,7 @@ TEST_F(PageSchedulerImplTest, RepeatingTimer_PageInForeground) {
base::TimeDelta::FromMilliseconds(1)),
base::TimeDelta::FromMilliseconds(1));
- mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(1000, run_count);
}
@@ -171,7 +268,7 @@ TEST_F(PageSchedulerImplTest, RepeatingTimer_PageInBackgroundThenForeground) {
base::TimeDelta::FromMilliseconds(20)),
base::TimeDelta::FromMilliseconds(20));
- mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(1, run_count);
// Make sure there's no delay in throttling being removed for pages that have
@@ -179,7 +276,7 @@ TEST_F(PageSchedulerImplTest, RepeatingTimer_PageInBackgroundThenForeground) {
page_scheduler_->SetPageVisible(true);
run_count = 0;
- mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(50, run_count);
}
@@ -193,16 +290,16 @@ TEST_F(PageSchedulerImplTest, RepeatingLoadingTask_PageInBackground) {
base::TimeDelta::FromMilliseconds(1)),
base::TimeDelta::FromMilliseconds(1));
- mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(1000, run_count); // Loading tasks should not be throttled
}
TEST_F(PageSchedulerImplTest, RepeatingTimers_OneBackgroundOneForeground) {
std::unique_ptr<PageSchedulerImpl> page_scheduler2(
- new PageSchedulerImpl(nullptr, scheduler_.get(), false));
+ new PageSchedulerImpl(nullptr, scheduler_.get()));
std::unique_ptr<FrameSchedulerImpl> frame_scheduler2 =
- page_scheduler2->CreateFrameSchedulerImpl(
- nullptr, FrameScheduler::FrameType::kSubframe);
+ FrameSchedulerImpl::Create(page_scheduler2.get(), nullptr,
+ FrameScheduler::FrameType::kSubframe);
page_scheduler_->SetPageVisible(true);
page_scheduler2->SetPageVisible(false);
@@ -222,7 +319,7 @@ TEST_F(PageSchedulerImplTest, RepeatingTimers_OneBackgroundOneForeground) {
&run_count2, base::TimeDelta::FromMilliseconds(20)),
base::TimeDelta::FromMilliseconds(20));
- mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(50, run_count1);
EXPECT_EQ(1, run_count2);
}
@@ -230,7 +327,7 @@ TEST_F(PageSchedulerImplTest, RepeatingTimers_OneBackgroundOneForeground) {
namespace {
void RunVirtualTimeRecorderTask(
- base::SimpleTestTickClock* clock,
+ const base::TickClock* clock,
MainThreadSchedulerImpl* scheduler,
std::vector<base::TimeTicks>* out_real_times,
std::vector<base::TimeTicks>* out_virtual_times) {
@@ -239,13 +336,14 @@ void RunVirtualTimeRecorderTask(
}
base::OnceClosure MakeVirtualTimeRecorderTask(
- base::SimpleTestTickClock* clock,
+ const base::TickClock* clock,
MainThreadSchedulerImpl* scheduler,
std::vector<base::TimeTicks>* out_real_times,
std::vector<base::TimeTicks>* out_virtual_times) {
- return WTF::Bind(&RunVirtualTimeRecorderTask, WTF::Unretained(clock),
- WTF::Unretained(scheduler), WTF::Unretained(out_real_times),
- WTF::Unretained(out_virtual_times));
+ return base::BindOnce(&RunVirtualTimeRecorderTask, base::Unretained(clock),
+ base::Unretained(scheduler),
+ base::Unretained(out_real_times),
+ base::Unretained(out_virtual_times));
}
} // namespace
@@ -261,23 +359,26 @@ TEST_F(PageSchedulerImplTest, VirtualTime_TimerFastForwarding) {
ThrottleableTaskRunner()->PostDelayedTask(
FROM_HERE,
- MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+ MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+ scheduler_.get(), &real_times,
&virtual_times),
base::TimeDelta::FromMilliseconds(2));
ThrottleableTaskRunner()->PostDelayedTask(
FROM_HERE,
- MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+ MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+ scheduler_.get(), &real_times,
&virtual_times),
base::TimeDelta::FromMilliseconds(20));
ThrottleableTaskRunner()->PostDelayedTask(
FROM_HERE,
- MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+ MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+ scheduler_.get(), &real_times,
&virtual_times),
base::TimeDelta::FromMilliseconds(200));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_THAT(real_times, ElementsAre(initial_real_time, initial_real_time,
initial_real_time));
@@ -301,23 +402,26 @@ TEST_F(PageSchedulerImplTest, VirtualTime_LoadingTaskFastForwarding) {
LoadingTaskRunner()->PostDelayedTask(
FROM_HERE,
- MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+ MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+ scheduler_.get(), &real_times,
&virtual_times),
base::TimeDelta::FromMilliseconds(2));
LoadingTaskRunner()->PostDelayedTask(
FROM_HERE,
- MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+ MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+ scheduler_.get(), &real_times,
&virtual_times),
base::TimeDelta::FromMilliseconds(20));
LoadingTaskRunner()->PostDelayedTask(
FROM_HERE,
- MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+ MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+ scheduler_.get(), &real_times,
&virtual_times),
base::TimeDelta::FromMilliseconds(200));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_THAT(real_times, ElementsAre(initial_real_time, initial_real_time,
initial_real_time));
@@ -343,9 +447,10 @@ TEST_F(PageSchedulerImplTest,
base::TimeDelta::FromMilliseconds(1)),
base::TimeDelta::FromMilliseconds(1));
- mock_task_runner_->RunTasksWhile(mock_task_runner_->TaskRunCountBelow(2000));
+ test_task_runner_->RunUntilIdle();
// Virtual time means page visibility is ignored.
- EXPECT_EQ(1999, run_count);
+ // 2000 is the |run_count| limit, we expect to reach it.
+ EXPECT_EQ(2000, run_count);
// The global tick clock has not moved, yet we ran a large number of "delayed"
// tasks despite calling setPageVisible(false).
@@ -390,7 +495,7 @@ TEST_F(PageSchedulerImplTest, VirtualTime_NotAllowedToAdvance) {
base::Unretained(&run_order)),
base::TimeDelta::FromMilliseconds(4));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
// No timer tasks are allowed to run.
EXPECT_THAT(run_order, ElementsAre());
@@ -418,23 +523,13 @@ TEST_F(PageSchedulerImplTest, VirtualTime_AllowedToAdvance) {
base::Unretained(&run_order)),
base::TimeDelta::FromMilliseconds(4));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_THAT(run_order, ElementsAre(0, 1, 2, 3, 4));
}
-class PageSchedulerImplTestWithDisabledBackgroundTimerThrottling
- : public PageSchedulerImplTest {
- public:
- PageSchedulerImplTestWithDisabledBackgroundTimerThrottling() = default;
- ~PageSchedulerImplTestWithDisabledBackgroundTimerThrottling() override =
- default;
-
- bool DisableBackgroundTimerThrottling() const override { return true; }
-};
-
-TEST_F(PageSchedulerImplTestWithDisabledBackgroundTimerThrottling,
- RepeatingTimer_PageInBackground) {
+TEST_F(PageSchedulerImplTest, RepeatingTimer_PageInBackground) {
+ ScopedTimerThrottlingForBackgroundTabsForTest timer_throttling_enabler(false);
page_scheduler_->SetPageVisible(false);
int run_count = 0;
@@ -444,7 +539,7 @@ TEST_F(PageSchedulerImplTestWithDisabledBackgroundTimerThrottling,
base::TimeDelta::FromMilliseconds(1)),
base::TimeDelta::FromMilliseconds(1));
- mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
EXPECT_EQ(1000, run_count);
}
@@ -455,8 +550,8 @@ TEST_F(PageSchedulerImplTest, VirtualTimeSettings_NewFrameScheduler) {
page_scheduler_->EnableVirtualTime();
std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
- page_scheduler_->CreateFrameSchedulerImpl(
- nullptr, FrameScheduler::FrameType::kSubframe);
+ FrameSchedulerImpl::Create(page_scheduler_.get(), nullptr,
+ FrameScheduler::FrameType::kSubframe);
ThrottleableTaskQueueForScheduler(frame_scheduler.get())
->PostDelayedTask(
@@ -464,11 +559,11 @@ TEST_F(PageSchedulerImplTest, VirtualTimeSettings_NewFrameScheduler) {
base::BindOnce(&RunOrderTask, 1, base::Unretained(&run_order)),
base::TimeDelta::FromMilliseconds(1));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_TRUE(run_order.empty());
page_scheduler_->SetVirtualTimePolicy(VirtualTimePolicy::kAdvance);
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_THAT(run_order, ElementsAre(1));
}
@@ -485,30 +580,28 @@ base::OnceClosure MakeDeletionTask(T* obj) {
TEST_F(PageSchedulerImplTest, DeleteFrameSchedulers_InTask) {
for (int i = 0; i < 10; i++) {
FrameSchedulerImpl* frame_scheduler =
- page_scheduler_
- ->CreateFrameSchedulerImpl(nullptr,
- FrameScheduler::FrameType::kSubframe)
+ FrameSchedulerImpl::Create(page_scheduler_.get(), nullptr,
+ FrameScheduler::FrameType::kSubframe)
.release();
ThrottleableTaskQueueForScheduler(frame_scheduler)
->PostDelayedTask(FROM_HERE, MakeDeletionTask(frame_scheduler),
base::TimeDelta::FromMilliseconds(1));
}
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
}
TEST_F(PageSchedulerImplTest, DeletePageScheduler_InTask) {
ThrottleableTaskQueue()->PostTask(
FROM_HERE, MakeDeletionTask(page_scheduler_.release()));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
}
TEST_F(PageSchedulerImplTest, DeleteThrottledQueue_InTask) {
page_scheduler_->SetPageVisible(false);
FrameSchedulerImpl* frame_scheduler =
- page_scheduler_
- ->CreateFrameSchedulerImpl(nullptr,
- FrameScheduler::FrameType::kSubframe)
+ FrameSchedulerImpl::Create(page_scheduler_.get(), nullptr,
+ FrameScheduler::FrameType::kSubframe)
.release();
scoped_refptr<TaskQueue> timer_task_queue =
ThrottleableTaskQueueForScheduler(frame_scheduler);
@@ -526,7 +619,7 @@ TEST_F(PageSchedulerImplTest, DeleteThrottledQueue_InTask) {
MakeDeletionTask(frame_scheduler),
base::TimeDelta::FromMilliseconds(9990));
- mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(20));
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(20));
EXPECT_EQ(110, run_count);
}
@@ -560,8 +653,8 @@ TEST_F(PageSchedulerImplTest,
VirtualTimePolicy::kDeterministicLoading);
std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
- page_scheduler_->CreateFrameSchedulerImpl(
- nullptr, FrameScheduler::FrameType::kSubframe);
+ FrameSchedulerImpl::Create(page_scheduler_.get(), nullptr,
+ FrameScheduler::FrameType::kSubframe);
{
WebScopedVirtualTimePauser virtual_time_pauser =
@@ -627,26 +720,27 @@ TEST_F(PageSchedulerImplTest,
base::TimeTicks time_second_task;
std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
- page_scheduler_->CreateFrameSchedulerImpl(
- nullptr, FrameScheduler::FrameType::kSubframe);
+ FrameSchedulerImpl::Create(page_scheduler_.get(), nullptr,
+ FrameScheduler::FrameType::kSubframe);
// Pauses and unpauses virtual time, thereby advancing virtual time by an
// additional 10ms due to WebScopedVirtualTimePauser's delay.
ThrottleableTaskRunner()->PostDelayedTask(
FROM_HERE,
- WTF::Bind(&PauseAndUnpauseVirtualTime, WTF::Unretained(scheduler_.get()),
- WTF::Unretained(frame_scheduler.get()),
- WTF::Unretained(&time_paused), WTF::Unretained(&time_unpaused)),
+ base::BindOnce(
+ &PauseAndUnpauseVirtualTime, base::Unretained(scheduler_.get()),
+ base::Unretained(frame_scheduler.get()),
+ base::Unretained(&time_paused), base::Unretained(&time_unpaused)),
base::TimeDelta::FromMilliseconds(3));
// Will run after the first task has advanced virtual time past 5ms.
ThrottleableTaskRunner()->PostDelayedTask(
FROM_HERE,
- WTF::Bind(&RecordVirtualTime, WTF::Unretained(scheduler_.get()),
- WTF::Unretained(&time_second_task)),
+ base::BindOnce(&RecordVirtualTime, base::Unretained(scheduler_.get()),
+ base::Unretained(&time_second_task)),
base::TimeDelta::FromMilliseconds(5));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_EQ(time_paused,
initial_virtual_time + base::TimeDelta::FromMilliseconds(3));
@@ -662,8 +756,8 @@ TEST_F(PageSchedulerImplTest,
VirtualTimePolicy::kDeterministicLoading);
std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
- page_scheduler_->CreateFrameSchedulerImpl(
- nullptr, FrameScheduler::FrameType::kSubframe);
+ FrameSchedulerImpl::Create(page_scheduler_.get(), nullptr,
+ FrameScheduler::FrameType::kSubframe);
WebScopedVirtualTimePauser virtual_time_pauser1 =
frame_scheduler->CreateWebScopedVirtualTimePauser(
@@ -690,19 +784,25 @@ TEST_F(PageSchedulerImplTest, NestedMessageLoop_DETERMINISTIC_LOADING) {
VirtualTimePolicy::kDeterministicLoading);
EXPECT_TRUE(scheduler_->VirtualTimeAllowedToAdvance());
+ scheduler_->OnTaskStarted(
+ nullptr, FakeTask(),
+ FakeTaskTiming(base::TimeTicks(), base::TimeTicks()));
scheduler_->OnBeginNestedRunLoop();
EXPECT_FALSE(scheduler_->VirtualTimeAllowedToAdvance());
scheduler_->OnExitNestedRunLoop();
EXPECT_TRUE(scheduler_->VirtualTimeAllowedToAdvance());
+ scheduler_->OnTaskCompleted(
+ nullptr, FakeTask(),
+ FakeTaskTiming(base::TimeTicks(), scheduler_->real_time_domain()->Now()));
}
TEST_F(PageSchedulerImplTest, PauseTimersWhileVirtualTimeIsPaused) {
std::vector<int> run_order;
std::unique_ptr<FrameSchedulerImpl> frame_scheduler =
- page_scheduler_->CreateFrameSchedulerImpl(
- nullptr, FrameScheduler::FrameType::kSubframe);
+ FrameSchedulerImpl::Create(page_scheduler_.get(), nullptr,
+ FrameScheduler::FrameType::kSubframe);
page_scheduler_->SetVirtualTimePolicy(VirtualTimePolicy::kPause);
page_scheduler_->EnableVirtualTime();
@@ -710,11 +810,11 @@ TEST_F(PageSchedulerImplTest, PauseTimersWhileVirtualTimeIsPaused) {
->PostTask(FROM_HERE, base::BindOnce(&RunOrderTask, 1,
base::Unretained(&run_order)));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_TRUE(run_order.empty());
page_scheduler_->SetVirtualTimePolicy(VirtualTimePolicy::kAdvance);
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_THAT(run_order, ElementsAre(1));
}
@@ -731,37 +831,41 @@ TEST_F(PageSchedulerImplTest, VirtualTimeBudgetExhaustedCallback) {
ThrottleableTaskRunner()->PostDelayedTask(
FROM_HERE,
- MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+ MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+ scheduler_.get(), &real_times,
&virtual_times),
base::TimeDelta::FromMilliseconds(1));
ThrottleableTaskRunner()->PostDelayedTask(
FROM_HERE,
- MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+ MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+ scheduler_.get(), &real_times,
&virtual_times),
base::TimeDelta::FromMilliseconds(2));
ThrottleableTaskRunner()->PostDelayedTask(
FROM_HERE,
- MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+ MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+ scheduler_.get(), &real_times,
&virtual_times),
base::TimeDelta::FromMilliseconds(5));
ThrottleableTaskRunner()->PostDelayedTask(
FROM_HERE,
- MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+ MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+ scheduler_.get(), &real_times,
&virtual_times),
base::TimeDelta::FromMilliseconds(7));
page_scheduler_->GrantVirtualTimeBudget(
base::TimeDelta::FromMilliseconds(5),
- WTF::Bind(
+ base::BindOnce(
[](PageScheduler* scheduler) {
scheduler->SetVirtualTimePolicy(VirtualTimePolicy::kPause);
},
- WTF::Unretained(page_scheduler_.get())));
+ base::Unretained(page_scheduler_.get())));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
// The timer that is scheduled for the exact point in time when virtual time
// expires will not run.
@@ -821,13 +925,13 @@ TEST_F(PageSchedulerImplTest, VirtualTimeObserver) {
page_scheduler_->GrantVirtualTimeBudget(
base::TimeDelta::FromMilliseconds(1000),
- WTF::Bind(
+ base::BindOnce(
[](PageScheduler* scheduler) {
scheduler->SetVirtualTimePolicy(VirtualTimePolicy::kPause);
},
- WTF::Unretained(page_scheduler_.get())));
+ base::Unretained(page_scheduler_.get())));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_THAT(
mock_observer.virtual_time_log(),
@@ -870,13 +974,13 @@ TEST_F(PageSchedulerImplTest, MaxVirtualTimeTaskStarvationCountOneHundred) {
page_scheduler_->GrantVirtualTimeBudget(
base::TimeDelta::FromMilliseconds(1000),
- WTF::Bind(
+ base::BindOnce(
[](PageScheduler* scheduler) {
scheduler->SetVirtualTimePolicy(VirtualTimePolicy::kPause);
},
- WTF::Unretained(page_scheduler_.get())));
+ base::Unretained(page_scheduler_.get())));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
// Two delayed tasks with a run of 100 tasks, plus initial call.
EXPECT_EQ(201, count);
@@ -888,6 +992,10 @@ TEST_F(PageSchedulerImplTest,
page_scheduler_->EnableVirtualTime();
page_scheduler_->SetMaxVirtualTimeTaskStarvationCount(100);
page_scheduler_->SetVirtualTimePolicy(VirtualTimePolicy::kAdvance);
+
+ scheduler_->OnTaskStarted(
+ nullptr, FakeTask(),
+ FakeTaskTiming(base::TimeTicks(), base::TimeTicks()));
scheduler_->OnBeginNestedRunLoop();
int count = 0;
@@ -895,19 +1003,19 @@ TEST_F(PageSchedulerImplTest,
RepostingTask(ThrottleableTaskQueue(), 1000, &count);
ThrottleableTaskQueue()->PostDelayedTask(
FROM_HERE,
- base::BindOnce(DelayedTask, WTF::Unretained(&count),
- WTF::Unretained(&delayed_task_run_at_count)),
+ base::BindOnce(DelayedTask, base::Unretained(&count),
+ base::Unretained(&delayed_task_run_at_count)),
base::TimeDelta::FromMilliseconds(10));
page_scheduler_->GrantVirtualTimeBudget(
base::TimeDelta::FromMilliseconds(1000),
- WTF::Bind(
+ base::BindOnce(
[](PageScheduler* scheduler) {
scheduler->SetVirtualTimePolicy(VirtualTimePolicy::kPause);
},
- WTF::Unretained(page_scheduler_.get())));
+ base::Unretained(page_scheduler_.get())));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_EQ(1000, count);
EXPECT_EQ(1000, delayed_task_run_at_count);
@@ -923,19 +1031,19 @@ TEST_F(PageSchedulerImplTest, MaxVirtualTimeTaskStarvationCountZero) {
RepostingTask(ThrottleableTaskQueue(), 1000, &count);
ThrottleableTaskQueue()->PostDelayedTask(
FROM_HERE,
- base::BindOnce(DelayedTask, WTF::Unretained(&count),
- WTF::Unretained(&delayed_task_run_at_count)),
+ base::BindOnce(DelayedTask, base::Unretained(&count),
+ base::Unretained(&delayed_task_run_at_count)),
base::TimeDelta::FromMilliseconds(10));
page_scheduler_->GrantVirtualTimeBudget(
base::TimeDelta::FromMilliseconds(1000),
- WTF::Bind(
+ base::BindOnce(
[](PageScheduler* scheduler) {
scheduler->SetVirtualTimePolicy(VirtualTimePolicy::kPause);
},
- WTF::Unretained(page_scheduler_.get())));
+ base::Unretained(page_scheduler_.get())));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_EQ(1000, count);
// If the initial count had been higher, the delayed task could have been
@@ -945,10 +1053,10 @@ TEST_F(PageSchedulerImplTest, MaxVirtualTimeTaskStarvationCountZero) {
namespace {
-void ExpensiveTestTask(base::SimpleTestTickClock* clock,
+void ExpensiveTestTask(scoped_refptr<base::TestMockTimeTaskRunner> task_runner,
std::vector<base::TimeTicks>* run_times) {
- run_times->push_back(clock->NowTicks());
- clock->Advance(base::TimeDelta::FromMilliseconds(250));
+ run_times->push_back(task_runner->GetMockTickClock()->NowTicks());
+ task_runner->AdvanceMockTickClock(base::TimeDelta::FromMilliseconds(250));
}
void InitializeTrialParams() {
@@ -975,28 +1083,27 @@ TEST_F(PageSchedulerImplTest, BackgroundTimerThrottling) {
std::unique_ptr<base::FieldTrialList> field_trial_list =
std::make_unique<base::FieldTrialList>(nullptr);
InitializeTrialParams();
- page_scheduler_.reset(
- new PageSchedulerImpl(nullptr, scheduler_.get(), false));
+ page_scheduler_.reset(new PageSchedulerImpl(nullptr, scheduler_.get()));
EXPECT_FALSE(page_scheduler_->IsThrottled());
std::vector<base::TimeTicks> run_times;
- frame_scheduler_ = page_scheduler_->CreateFrameSchedulerImpl(
- nullptr, FrameScheduler::FrameType::kSubframe);
+ frame_scheduler_ = FrameSchedulerImpl::Create(
+ page_scheduler_.get(), nullptr, FrameScheduler::FrameType::kSubframe);
page_scheduler_->SetPageVisible(true);
EXPECT_FALSE(page_scheduler_->IsThrottled());
- mock_task_runner_->RunUntilTime(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(2500));
+ FastForwardTo(base::TimeTicks() + base::TimeDelta::FromMilliseconds(2500));
ThrottleableTaskQueue()->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, test_task_runner_, &run_times),
base::TimeDelta::FromMilliseconds(1));
ThrottleableTaskQueue()->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, test_task_runner_, &run_times),
base::TimeDelta::FromMilliseconds(1));
- mock_task_runner_->RunUntilTime(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(3500));
+ FastForwardTo(base::TimeTicks() + base::TimeDelta::FromMilliseconds(3500));
// Check that these tasks are aligned, but are not subject to budget-based
// throttling.
@@ -1010,18 +1117,19 @@ TEST_F(PageSchedulerImplTest, BackgroundTimerThrottling) {
EXPECT_FALSE(page_scheduler_->IsThrottled());
// Ensure that the page is fully throttled.
- mock_task_runner_->RunUntilTime(base::TimeTicks() +
- base::TimeDelta::FromSeconds(15));
+ FastForwardTo(base::TimeTicks() + base::TimeDelta::FromSeconds(15));
EXPECT_TRUE(page_scheduler_->IsThrottled());
ThrottleableTaskQueue()->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, test_task_runner_, &run_times),
base::TimeDelta::FromMicroseconds(1));
ThrottleableTaskQueue()->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, test_task_runner_, &run_times),
base::TimeDelta::FromMicroseconds(1));
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
// Check that tasks are aligned and throttled.
EXPECT_THAT(
@@ -1040,32 +1148,31 @@ TEST_F(PageSchedulerImplTest, OpenWebSocketExemptsFromBudgetThrottling) {
std::make_unique<base::FieldTrialList>(nullptr);
InitializeTrialParams();
std::unique_ptr<PageSchedulerImpl> page_scheduler(
- new PageSchedulerImpl(nullptr, scheduler_.get(), false));
+ new PageSchedulerImpl(nullptr, scheduler_.get()));
std::vector<base::TimeTicks> run_times;
std::unique_ptr<FrameSchedulerImpl> frame_scheduler1 =
- page_scheduler->CreateFrameSchedulerImpl(
- nullptr, FrameScheduler::FrameType::kSubframe);
+ FrameSchedulerImpl::Create(page_scheduler.get(), nullptr,
+ FrameScheduler::FrameType::kSubframe);
std::unique_ptr<FrameSchedulerImpl> frame_scheduler2 =
- page_scheduler->CreateFrameSchedulerImpl(
- nullptr, FrameScheduler::FrameType::kSubframe);
+ FrameSchedulerImpl::Create(page_scheduler.get(), nullptr,
+ FrameScheduler::FrameType::kSubframe);
page_scheduler->SetPageVisible(false);
// Wait for 20s to avoid initial throttling delay.
- mock_task_runner_->RunUntilTime(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(20500));
+ FastForwardTo(base::TimeTicks() + base::TimeDelta::FromMilliseconds(20500));
for (size_t i = 0; i < 3; ++i) {
ThrottleableTaskQueueForScheduler(frame_scheduler1.get())
->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, test_task_runner_, &run_times),
base::TimeDelta::FromMilliseconds(1));
}
- mock_task_runner_->RunUntilTime(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(55500));
+ FastForwardTo(base::TimeTicks() + base::TimeDelta::FromMilliseconds(55500));
// Check that tasks are throttled.
EXPECT_THAT(
@@ -1081,12 +1188,12 @@ TEST_F(PageSchedulerImplTest, OpenWebSocketExemptsFromBudgetThrottling) {
for (size_t i = 0; i < 3; ++i) {
ThrottleableTaskQueueForScheduler(frame_scheduler1.get())
->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, test_task_runner_, &run_times),
base::TimeDelta::FromMilliseconds(1));
}
- mock_task_runner_->RunUntilTime(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(58500));
+ FastForwardTo(base::TimeTicks() + base::TimeDelta::FromMilliseconds(58500));
// Check that the timer task queue from the first frame is aligned,
// but not throttled.
@@ -1101,12 +1208,12 @@ TEST_F(PageSchedulerImplTest, OpenWebSocketExemptsFromBudgetThrottling) {
for (size_t i = 0; i < 3; ++i) {
ThrottleableTaskQueueForScheduler(frame_scheduler2.get())
->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, test_task_runner_, &run_times),
base::TimeDelta::FromMilliseconds(1));
}
- mock_task_runner_->RunUntilTime(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(59500));
+ FastForwardTo(base::TimeTicks() + base::TimeDelta::FromMilliseconds(59500));
// Check that the second frame scheduler becomes unthrottled.
EXPECT_THAT(
@@ -1120,17 +1227,17 @@ TEST_F(PageSchedulerImplTest, OpenWebSocketExemptsFromBudgetThrottling) {
websocket_connection.reset();
// Wait for 10s to enable throttling back.
- mock_task_runner_->RunUntilTime(base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(70500));
+ FastForwardTo(base::TimeTicks() + base::TimeDelta::FromMilliseconds(70500));
for (size_t i = 0; i < 3; ++i) {
ThrottleableTaskQueueForScheduler(frame_scheduler1.get())
->PostDelayedTask(
- FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
+ FROM_HERE,
+ base::BindOnce(&ExpensiveTestTask, test_task_runner_, &run_times),
base::TimeDelta::FromMilliseconds(1));
}
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
// WebSocket is closed, budget-based throttling now applies.
EXPECT_THAT(
@@ -1142,61 +1249,17 @@ TEST_F(PageSchedulerImplTest, OpenWebSocketExemptsFromBudgetThrottling) {
base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
}
-namespace {
-void IncrementCounter(int* counter) {
- ++*counter;
+// Verify that freezing a page prevents tasks in its task queues from running.
+// Then, verify that making the page visible unfreezes it and allows tasks in
+// its task queues to run.
+TEST_F(PageSchedulerImplTest, PageFreezeAndSetVisible) {
+ TestFreeze(true);
}
-} // namespace
-
-TEST_F(PageSchedulerImplTest, PageFreeze) {
- ScopedStopLoadingInBackgroundForTest stop_loading_enabler(true);
- ScopedStopNonTimersInBackgroundForTest stop_non_timers_enabler(true);
-
- int counter = 0;
- LoadingTaskQueue()->PostTask(
- FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
- ThrottleableTaskQueue()->PostTask(
- FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
- DeferrableTaskQueue()->PostTask(
- FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
- PausableTaskQueue()->PostTask(
- FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
- UnpausableTaskQueue()->PostTask(
- FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
-
- page_scheduler_->SetPageVisible(false);
- EXPECT_EQ(false, page_scheduler_->IsFrozen());
-
- // In a backgrounded active page, all queues should run.
- mock_task_runner_->RunUntilIdle();
- EXPECT_EQ(5, counter);
-
- LoadingTaskQueue()->PostTask(
- FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
- ThrottleableTaskQueue()->PostTask(
- FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
- DeferrableTaskQueue()->PostTask(
- FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
- PausableTaskQueue()->PostTask(
- FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
- UnpausableTaskQueue()->PostTask(
- FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
- counter = 0;
-
- page_scheduler_->SetPageFrozen(true);
- EXPECT_EQ(true, page_scheduler_->IsFrozen());
-
- // In a backgrounded frozen page, only Unpausable queue should run.
- mock_task_runner_->RunUntilIdle();
- EXPECT_EQ(1, counter);
-
- // A visible page should not be frozen.
- page_scheduler_->SetPageVisible(true);
- EXPECT_EQ(false, page_scheduler_->IsFrozen());
- // Once the page is unfrozen, the rest of the queues should run.
- mock_task_runner_->RunUntilIdle();
- EXPECT_EQ(5, counter);
+// Same as before, but unfreeze the page explicitly instead of making it
+// visible.
+TEST_F(PageSchedulerImplTest, PageFreezeAndUnfreeze) {
+ TestFreeze(false);
}
TEST_F(PageSchedulerImplTest, AudioState) {
@@ -1207,14 +1270,14 @@ TEST_F(PageSchedulerImplTest, AudioState) {
// We are audible for a certain period after raw signal disappearing.
EXPECT_TRUE(page_scheduler_->IsAudioPlaying());
- mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(3));
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(3));
page_scheduler_->AudioStateChanged(false);
// We are still audible. A new call to AudioStateChanged shouldn't change
// anything.
EXPECT_TRUE(page_scheduler_->IsAudioPlaying());
- mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(3));
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(3));
// Audio is finally silent.
EXPECT_FALSE(page_scheduler_->IsAudioPlaying());
@@ -1227,7 +1290,7 @@ TEST_F(PageSchedulerImplTest, PageSchedulerDestroyedWhileAudioChangePending) {
page_scheduler_.reset();
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
}
TEST_F(PageSchedulerImplTest, AudiblePagesAreNotThrottled) {
@@ -1246,7 +1309,7 @@ TEST_F(PageSchedulerImplTest, AudiblePagesAreNotThrottled) {
ThrottleableTaskQueue().get()));
// Eventually throttling is reenabled again.
- mock_task_runner_->RunUntilIdle();
+ test_task_runner_->FastForwardUntilNoTasksRemain();
EXPECT_TRUE(scheduler_->task_queue_throttler()->IsThrottled(
ThrottleableTaskQueue().get()));
}
@@ -1259,13 +1322,293 @@ TEST_F(PageSchedulerImplTest, KeepActiveSetForNewPages) {
scheduler_->SetSchedulerKeepActive(true);
std::unique_ptr<PageSchedulerImpl> page_scheduler2 =
- std::make_unique<PageSchedulerImpl>(nullptr, scheduler_.get(),
- DisableBackgroundTimerThrottling());
+ std::make_unique<PageSchedulerImpl>(nullptr, scheduler_.get());
EXPECT_TRUE(page_scheduler_->KeepActive());
EXPECT_TRUE(page_scheduler2->KeepActive());
}
+TEST_F(PageSchedulerImplTest, TestPageBackgroundedTimerSuspension) {
+ int counter = 0;
+ ThrottleableTaskQueue()->PostTask(
+ FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+ ThrottleableTaskQueue()->PostTask(
+ FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+
+ // The background signal will not immediately suspend the timer queue.
+ page_scheduler_->SetPageVisible(false);
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromMilliseconds(1100));
+ EXPECT_FALSE(page_scheduler_->IsFrozen());
+ EXPECT_EQ(2, counter);
+
+ counter = 0;
+ ThrottleableTaskQueue()->PostTask(
+ FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
+ EXPECT_FALSE(page_scheduler_->IsFrozen());
+ EXPECT_EQ(1, counter);
+
+ // Advance the time until after the scheduled timer queue suspension.
+ counter = 0;
+ test_task_runner_->FastForwardBy(delay_for_background_tab_freezing() +
+ base::TimeDelta::FromMilliseconds(10));
+ EXPECT_TRUE(page_scheduler_->IsFrozen());
+ EXPECT_EQ(0, counter);
+
+ // Timer tasks should be paused until the page becomes visible.
+ ThrottleableTaskQueue()->PostTask(
+ FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+ ThrottleableTaskQueue()->PostTask(
+ FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+ UnpausableTaskQueue()->PostTask(
+ FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(10));
+ EXPECT_EQ(1, counter);
+
+ counter = 0;
+ page_scheduler_->SetPageVisible(true);
+ EXPECT_FALSE(page_scheduler_->IsFrozen());
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
+ EXPECT_EQ(2, counter);
+
+ // Subsequent timer tasks should fire as usual.
+ counter = 0;
+ ThrottleableTaskQueue()->PostTask(
+ FROM_HERE, base::BindOnce(&IncrementCounter, base::Unretained(&counter)));
+ test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
+ EXPECT_EQ(1, counter);
+}
+
+TEST_F(PageSchedulerImplTest, PageFrozenOnlyWhileAudioSilent) {
+ page_scheduler_->AudioStateChanged(true);
+ page_scheduler_->SetPageVisible(false);
+ EXPECT_TRUE(page_scheduler_->IsAudioPlaying());
+ EXPECT_FALSE(ShouldFreezePage());
+ EXPECT_FALSE(page_scheduler_->IsFrozen());
+
+ page_scheduler_->AudioStateChanged(false);
+ // We are audible for a certain period after raw signal disappearing. The page
+ // should not be eligible to freeze until after this delay.
+ EXPECT_TRUE(page_scheduler_->IsAudioPlaying());
+ EXPECT_FALSE(ShouldFreezePage());
+
+ test_task_runner_->FastForwardBy(recent_audio_delay() +
+ base::TimeDelta::FromMilliseconds(100));
+ // Audio is finally silent. The page should be eligible for freezing.
+ EXPECT_FALSE(page_scheduler_->IsAudioPlaying());
+ EXPECT_TRUE(ShouldFreezePage());
+ EXPECT_FALSE(page_scheduler_->IsFrozen());
+
+ test_task_runner_->FastForwardBy(delay_for_background_tab_freezing() +
+ base::TimeDelta::FromMilliseconds(100));
+ EXPECT_TRUE(page_scheduler_->IsFrozen());
+
+ // Page should unfreeze if audio starts playing.
+ page_scheduler_->AudioStateChanged(true);
+ EXPECT_FALSE(page_scheduler_->IsFrozen());
+}
+
+TEST_F(PageSchedulerImplTest, PageFrozenOnlyWhileNotVisible) {
+ page_scheduler_->SetPageVisible(true);
+ EXPECT_FALSE(ShouldFreezePage());
+ EXPECT_FALSE(page_scheduler_->IsFrozen());
+
+ // Page should freeze after delay.
+ page_scheduler_->SetPageVisible(false);
+ EXPECT_TRUE(ShouldFreezePage());
+ test_task_runner_->FastForwardBy(delay_for_background_tab_freezing() +
+ base::TimeDelta::FromMilliseconds(100));
+ EXPECT_TRUE(page_scheduler_->IsFrozen());
+
+ // Page should unfreeze when it becomes visible.
+ page_scheduler_->SetPageVisible(true);
+ EXPECT_FALSE(page_scheduler_->IsFrozen());
+
+ // If the page becomes visible before the freezing delay expires, it should
+ // not freeze after the delay elapses.
+ page_scheduler_->SetPageVisible(false);
+ EXPECT_TRUE(ShouldFreezePage());
+ test_task_runner_->FastForwardBy(delay_for_background_tab_freezing() -
+ base::TimeDelta::FromMilliseconds(100));
+ EXPECT_FALSE(page_scheduler_->IsFrozen());
+ page_scheduler_->SetPageVisible(true);
+ test_task_runner_->FastForwardBy(delay_for_background_tab_freezing() +
+ base::TimeDelta::FromMilliseconds(100));
+ EXPECT_FALSE(page_scheduler_->IsFrozen());
+}
+
+class PageSchedulerImplPageTransitionTest : public PageSchedulerImplTest {
+ public:
+ typedef PageSchedulerImpl::PageLifecycleStateTransition Transition;
+
+ PageSchedulerImplPageTransitionTest() {
+ for (int i = 0; i <= static_cast<int>(Transition::kMaxValue); i++)
+ transition_counts_.push_back(0);
+ }
+
+ ~PageSchedulerImplPageTransitionTest() override = default;
+
+ void IncrementPageTransition(Transition transition) {
+ transition_counts_[static_cast<int>(transition)] += 1;
+ }
+
+ std::vector<Bucket> GetExpectedBuckets() {
+ std::vector<Bucket> buckets;
+ for (int i = 0; i <= static_cast<int>(Transition::kMaxValue); i++) {
+ if (transition_counts_[i] > 0)
+ buckets.push_back(Bucket(i, transition_counts_[i]));
+ }
+ return buckets;
+ }
+
+ void WaitForFreezingDelay() {
+ test_task_runner_->FastForwardBy(delay_for_background_tab_freezing() +
+ base::TimeDelta::FromMilliseconds(100));
+ }
+
+ void DisableAudioAndWaitForSilent() {
+ page_scheduler_->AudioStateChanged(false);
+ test_task_runner_->FastForwardBy(recent_audio_delay() +
+ base::TimeDelta::FromMilliseconds(100));
+ }
+
+ protected:
+ std::vector<int> transition_counts_;
+};
+
+TEST_F(PageSchedulerImplPageTransitionTest,
+ PageLifecycleStateTransitionMetric) {
+ typedef PageSchedulerImpl::PageLifecycleStateTransition Transition;
+
+ base::HistogramTester histogram_tester_;
+
+ if (kDefaultPageVisibility == PageVisibilityState::kHidden) {
+ page_scheduler_->SetPageVisible(true);
+ IncrementPageTransition(Transition::kHiddenBackgroundedToActive);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+ }
+
+ // Visible w/o audio -> hidden/backgrounded -> frozen.
+ page_scheduler_->SetPageVisible(false);
+ IncrementPageTransition(Transition::kActiveToHiddenBackgrounded);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+ WaitForFreezingDelay();
+ IncrementPageTransition(Transition::kHiddenBackgroundedToFrozen);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+
+ // Visible w/ audio -> hidden/not backgrouneded -> hidden/backgrounded ->
+ // frozen.
+ page_scheduler_->SetPageVisible(true);
+ IncrementPageTransition(Transition::kFrozenToActive);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+ page_scheduler_->AudioStateChanged(true);
+ // No transition when audio state changes in the foreground.
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+ page_scheduler_->SetPageVisible(false);
+ IncrementPageTransition(Transition::kActiveToHiddenForegrounded);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+ DisableAudioAndWaitForSilent();
+ IncrementPageTransition(Transition::kHiddenForegroundedToHiddenBackgrounded);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+ WaitForFreezingDelay();
+ IncrementPageTransition(Transition::kHiddenBackgroundedToFrozen);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+
+ // When freezing from outside the renderer, it's possible to have transitions
+ // to frozen from hidden/foregrounded and hidden/backgrounded.
+ //
+ // Visible w/o audio -> hidden/backgrounded -> frozen from outside the
+ // renderer.
+ page_scheduler_->SetPageVisible(true);
+ IncrementPageTransition(Transition::kFrozenToActive);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+ page_scheduler_->SetPageVisible(false);
+ IncrementPageTransition(Transition::kActiveToHiddenBackgrounded);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+ page_scheduler_->SetPageFrozen(true);
+ IncrementPageTransition(Transition::kHiddenBackgroundedToFrozen);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+ // Unfreezing from outside the renderer should return to hidden/backgrounded.
+ page_scheduler_->SetPageFrozen(false);
+ IncrementPageTransition(Transition::kFrozenToHiddenBackgrounded);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+
+ // Hidden/backgrounded -> hidden/not backgrouneded -> frozen from outside the
+ // renderer.
+ page_scheduler_->AudioStateChanged(true);
+ IncrementPageTransition(Transition::kHiddenBackgroundedToHiddenForegrounded);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+ page_scheduler_->SetPageFrozen(true);
+ IncrementPageTransition(Transition::kHiddenForegroundedToFrozen);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+ // Unfreezing from outside the renderer should return to hidden/foregrounded.
+ page_scheduler_->SetPageFrozen(false);
+ IncrementPageTransition(Transition::kFrozenToHiddenForegrounded);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+
+ // Visible -> hidden* -> hidden* -> visible.
+ page_scheduler_->SetPageVisible(true);
+ IncrementPageTransition(Transition::kHiddenForegroundedToActive);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+ page_scheduler_->SetPageVisible(false);
+ IncrementPageTransition(Transition::kActiveToHiddenForegrounded);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+ DisableAudioAndWaitForSilent();
+ IncrementPageTransition(Transition::kHiddenForegroundedToHiddenBackgrounded);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+ page_scheduler_->AudioStateChanged(true);
+ IncrementPageTransition(Transition::kHiddenBackgroundedToHiddenForegrounded);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+ DisableAudioAndWaitForSilent();
+ IncrementPageTransition(Transition::kHiddenForegroundedToHiddenBackgrounded);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+ page_scheduler_->SetPageVisible(true);
+ IncrementPageTransition(Transition::kHiddenBackgroundedToActive);
+ EXPECT_THAT(histogram_tester_.GetAllSamples(
+ PageSchedulerImpl::kHistogramPageLifecycleStateTransition),
+ UnorderedElementsAreArray(GetExpectedBuckets()));
+}
+
} // namespace page_scheduler_impl_unittest
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.cc
new file mode 100644
index 00000000000..f57d1b73edc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.cc
@@ -0,0 +1,22 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.h"
+
+namespace blink {
+namespace scheduler {
+
+const char* PageVisibilityStateToString(PageVisibilityState visibility) {
+ switch (visibility) {
+ case PageVisibilityState::kVisible:
+ return "visible";
+ case PageVisibilityState::kHidden:
+ return "hidden";
+ }
+ // Keep MSVC happy.
+ return nullptr;
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.h
new file mode 100644
index 00000000000..5bb56b1754c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.h
@@ -0,0 +1,22 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_PAGE_VISIBILITY_STATE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_PAGE_VISIBILITY_STATE_H_
+
+namespace blink {
+namespace scheduler {
+
+// TODO(altimin): Move to core/.
+enum class PageVisibilityState { kVisible, kHidden };
+
+const char* PageVisibilityStateToString(PageVisibilityState visibility);
+
+constexpr PageVisibilityState kDefaultPageVisibility =
+ PageVisibilityState::kVisible;
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_PAGE_VISIBILITY_STATE_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.cc
new file mode 100644
index 00000000000..efacf002661
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.cc
@@ -0,0 +1,112 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.h"
+
+#include "base/metrics/field_trial_params.h"
+#include "base/strings/string_number_conversions.h"
+#include "third_party/blink/renderer/platform/scheduler/child/features.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
+
+namespace blink {
+namespace scheduler {
+
+namespace {
+
+// Prioritize compositing after input trial.
+constexpr const char kPrioritizeCompositingAfterInputTrial[] =
+ "BlinkSchedulerPrioritizeCompositingAfterInput";
+constexpr const char kNumberOfCompositingTasksToPrioritizeAfterInputParam[] =
+ "number_of_tasks";
+
+constexpr size_t kDefaultNumberOfTasksToPrioritizeAfterInput = 1;
+
+size_t GetNumberOfCompositingTasksToPrioritizeAfterInput() {
+ if (!base::FeatureList::IsEnabled(kPrioritizeCompositingAfterInput))
+ return 0;
+ int number_of_tasks;
+ if (!base::StringToInt(
+ base::GetFieldTrialParamValue(
+ kPrioritizeCompositingAfterInputTrial,
+ kNumberOfCompositingTasksToPrioritizeAfterInputParam),
+ &number_of_tasks)) {
+ return kDefaultNumberOfTasksToPrioritizeAfterInput;
+ }
+ return number_of_tasks;
+}
+
+} // namespace
+
+PrioritizeCompositingAfterInputExperiment::
+ PrioritizeCompositingAfterInputExperiment(
+ MainThreadSchedulerImpl* scheduler)
+ : scheduler_(scheduler),
+ increased_compositing_priority_(
+ base::FeatureList::IsEnabled(kHighestPriorityForCompositingAfterInput)
+ ? base::sequence_manager::TaskQueue::QueuePriority::
+ kHighestPriority
+ : base::sequence_manager::TaskQueue::QueuePriority::
+ kHighPriority),
+ number_of_tasks_to_prioritize_after_input_(
+ GetNumberOfCompositingTasksToPrioritizeAfterInput()),
+ trigger_type_(
+ base::FeatureList::IsEnabled(
+ kUseExplicitSignalForTriggeringCompositingPrioritization)
+ ? TriggerType::kExplicitSignal
+ : TriggerType::kInferredFromInput),
+ stop_signal_type_(base::FeatureList::IsEnabled(
+ kUseWillBeginMainFrameForCompositingPrioritization)
+ ? StopSignalType::kWillBeginMainFrameSignal
+ : StopSignalType::kAllCompositingTasks),
+ number_of_tasks_to_prioritize_(0) {}
+
+PrioritizeCompositingAfterInputExperiment::
+ ~PrioritizeCompositingAfterInputExperiment() {}
+
+void PrioritizeCompositingAfterInputExperiment::
+ SetNumberOfCompositingTasksToPrioritize(int number_of_tasks) {
+ number_of_tasks = std::max(number_of_tasks, 0);
+ bool did_prioritize_compositing = number_of_tasks_to_prioritize_ > 0;
+ number_of_tasks_to_prioritize_ = number_of_tasks;
+ bool should_prioritize_compositing = number_of_tasks_to_prioritize_ > 0;
+ if (did_prioritize_compositing != should_prioritize_compositing)
+ scheduler_->SetShouldPrioritizeCompositing(should_prioritize_compositing);
+}
+
+base::sequence_manager::TaskQueue::QueuePriority
+PrioritizeCompositingAfterInputExperiment::GetIncreasedCompositingPriority() {
+ return increased_compositing_priority_;
+}
+
+void PrioritizeCompositingAfterInputExperiment::OnTaskCompleted(
+ MainThreadTaskQueue* queue) {
+ if (!queue)
+ return;
+ if (queue->queue_type() == MainThreadTaskQueue::QueueType::kInput &&
+ trigger_type_ == TriggerType::kInferredFromInput) {
+ SetNumberOfCompositingTasksToPrioritize(
+ number_of_tasks_to_prioritize_after_input_);
+ } else if (queue->queue_type() ==
+ MainThreadTaskQueue::QueueType::kCompositor &&
+ stop_signal_type_ == StopSignalType::kAllCompositingTasks) {
+ SetNumberOfCompositingTasksToPrioritize(number_of_tasks_to_prioritize_ - 1);
+ }
+}
+
+void PrioritizeCompositingAfterInputExperiment::OnWillBeginMainFrame() {
+ if (stop_signal_type_ != StopSignalType::kWillBeginMainFrameSignal)
+ return;
+ SetNumberOfCompositingTasksToPrioritize(number_of_tasks_to_prioritize_ - 1);
+}
+
+void PrioritizeCompositingAfterInputExperiment::OnMainFrameRequestedForInput() {
+ if (trigger_type_ != TriggerType::kExplicitSignal)
+ return;
+ SetNumberOfCompositingTasksToPrioritize(
+ number_of_tasks_to_prioritize_after_input_);
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.h
new file mode 100644
index 00000000000..6caf61e5946
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/prioritize_compositing_after_input_experiment.h
@@ -0,0 +1,53 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_PRIORITIZE_COMPOSITING_AFTER_INPUT_EXPERIMENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_PRIORITIZE_COMPOSITING_AFTER_INPUT_EXPERIMENT_H_
+
+#include "base/task/sequence_manager/task_queue.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+namespace scheduler {
+
+class MainThreadSchedulerImpl;
+class MainThreadTaskQueue;
+
+class PLATFORM_EXPORT PrioritizeCompositingAfterInputExperiment {
+ public:
+ explicit PrioritizeCompositingAfterInputExperiment(
+ MainThreadSchedulerImpl* scheduler);
+ ~PrioritizeCompositingAfterInputExperiment();
+
+ base::sequence_manager::TaskQueue::QueuePriority
+ GetIncreasedCompositingPriority();
+
+ void OnTaskCompleted(MainThreadTaskQueue* queue);
+
+ void OnWillBeginMainFrame();
+
+ void OnMainFrameRequestedForInput();
+
+ private:
+ enum class TriggerType { kExplicitSignal, kInferredFromInput };
+
+ enum class StopSignalType { kAllCompositingTasks, kWillBeginMainFrameSignal };
+
+ void SetNumberOfCompositingTasksToPrioritize(int number_of_tasks);
+
+ MainThreadSchedulerImpl* scheduler_; // Not owned.
+
+ const base::sequence_manager::TaskQueue::QueuePriority
+ increased_compositing_priority_;
+ const int number_of_tasks_to_prioritize_after_input_;
+ const TriggerType trigger_type_;
+ const StopSignalType stop_signal_type_;
+
+ int number_of_tasks_to_prioritize_;
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_PRIORITIZE_COMPOSITING_AFTER_INPUT_EXPERIMENT_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.cc
index b31f3988d39..5bc2d976028 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.cc
@@ -4,6 +4,7 @@
#include "third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
#include <algorithm>
@@ -14,6 +15,8 @@ namespace scheduler {
namespace {
+using QueueType = MainThreadTaskQueue::QueueType;
+
#define FRAME_STATUS_PREFIX \
"RendererScheduler.ExpectedQueueingTimeByFrameStatus2."
#define TASK_QUEUE_PREFIX "RendererScheduler.ExpectedQueueingTimeByTaskQueue2."
@@ -49,62 +52,50 @@ base::TimeDelta ExpectedQueueingTimeFromTask(base::TimeTicks task_start,
DCHECK_LE(task_in_step_end_time, task_in_step_end_time);
double probability_of_this_task =
- static_cast<double>(
- (task_in_step_end_time - task_in_step_start_time).InMicroseconds()) /
- (step_end - step_start).InMicroseconds();
+ (task_in_step_end_time - task_in_step_start_time).InMicrosecondsF() /
+ (step_end - step_start).InMicrosecondsF();
base::TimeDelta expected_queueing_duration_within_task =
((task_end - task_in_step_start_time) +
(task_end - task_in_step_end_time)) /
2;
- return base::TimeDelta::FromMillisecondsD(
- probability_of_this_task *
- expected_queueing_duration_within_task.InMillisecondsF());
+ return probability_of_this_task * expected_queueing_duration_within_task;
}
} // namespace
-QueueingTimeEstimator::QueueingTimeEstimator(
- QueueingTimeEstimator::Client* client,
- base::TimeDelta window_duration,
- int steps_per_window)
+QueueingTimeEstimator::QueueingTimeEstimator(Client* client,
+ base::TimeDelta window_duration,
+ int steps_per_window)
: client_(client),
window_step_width_(window_duration / steps_per_window),
renderer_backgrounded_(kLaunchingProcessIsBackgrounded),
- processing_task_(false),
- in_nested_message_loop_(false),
calculator_(steps_per_window) {
DCHECK_GE(steps_per_window, 1);
}
-void QueueingTimeEstimator::OnTopLevelTaskStarted(
- base::TimeTicks task_start_time,
- MainThreadTaskQueue* queue) {
- AdvanceTime(task_start_time);
- current_task_start_time_ = task_start_time;
- processing_task_ = true;
+void QueueingTimeEstimator::OnExecutionStarted(base::TimeTicks now,
+ MainThreadTaskQueue* queue) {
+ DCHECK(!busy_);
+ AdvanceTime(now);
+ busy_ = true;
+ busy_period_start_time_ = now;
calculator_.UpdateStatusFromTaskQueue(queue);
}
-void QueueingTimeEstimator::OnTopLevelTaskCompleted(
- base::TimeTicks task_end_time) {
- DCHECK(processing_task_);
- AdvanceTime(task_end_time);
- processing_task_ = false;
- current_task_start_time_ = base::TimeTicks();
- in_nested_message_loop_ = false;
-}
-
-void QueueingTimeEstimator::OnBeginNestedRunLoop() {
- in_nested_message_loop_ = true;
+void QueueingTimeEstimator::OnExecutionStopped(base::TimeTicks now) {
+ DCHECK(busy_);
+ AdvanceTime(now);
+ busy_ = false;
+ busy_period_start_time_ = base::TimeTicks();
}
void QueueingTimeEstimator::OnRendererStateChanged(
bool backgrounded,
base::TimeTicks transition_time) {
DCHECK_NE(backgrounded, renderer_backgrounded_);
- if (!processing_task_)
+ if (!busy_)
AdvanceTime(transition_time);
renderer_backgrounded_ = backgrounded;
}
@@ -112,18 +103,18 @@ void QueueingTimeEstimator::OnRendererStateChanged(
void QueueingTimeEstimator::AdvanceTime(base::TimeTicks current_time) {
if (step_start_time_.is_null()) {
// Ignore any time before the first task.
- if (!processing_task_)
+ if (!busy_)
return;
- step_start_time_ = current_task_start_time_;
+ step_start_time_ = busy_period_start_time_;
}
base::TimeTicks reference_time =
- processing_task_ ? current_task_start_time_ : step_start_time_;
- if (in_nested_message_loop_ || renderer_backgrounded_ ||
+ busy_ ? busy_period_start_time_ : step_start_time_;
+ if (renderer_backgrounded_ ||
current_time - reference_time > kInvalidPeriodThreshold) {
- // Skip steps when the renderer was backgrounded, when we are at a nested
- // message loop, when a task took too long, or when we remained idle for
- // too long. May cause |step_start_time_| to go slightly into the future.
+ // Skip steps when the renderer was backgrounded, when a task took too long,
+ // or when we remained idle for too long. May cause |step_start_time_| to go
+ // slightly into the future.
// TODO(npm): crbug.com/776013. Base skipping long tasks/idling on a signal
// that we've been suspended.
step_start_time_ =
@@ -132,18 +123,18 @@ void QueueingTimeEstimator::AdvanceTime(base::TimeTicks current_time) {
return;
}
while (TimePastStepEnd(current_time)) {
- if (processing_task_) {
+ if (busy_) {
// Include the current task in this window.
calculator_.AddQueueingTime(ExpectedQueueingTimeFromTask(
- current_task_start_time_, current_time, step_start_time_,
+ busy_period_start_time_, current_time, step_start_time_,
step_start_time_ + window_step_width_));
}
calculator_.EndStep(client_);
step_start_time_ += window_step_width_;
}
- if (processing_task_) {
+ if (busy_) {
calculator_.AddQueueingTime(ExpectedQueueingTimeFromTask(
- current_task_start_time_, current_time, step_start_time_,
+ busy_period_start_time_, current_time, step_start_time_,
step_start_time_ + window_step_width_));
}
}
@@ -156,84 +147,6 @@ QueueingTimeEstimator::Calculator::Calculator(int steps_per_window)
: steps_per_window_(steps_per_window),
step_queueing_times_(steps_per_window) {}
-// static
-const char* QueueingTimeEstimator::Calculator::GetReportingMessageFromQueueType(
- MainThreadTaskQueue::QueueType queue_type) {
- switch (queue_type) {
- case MainThreadTaskQueue::QueueType::kDefault:
- return TASK_QUEUE_PREFIX "Default";
- case MainThreadTaskQueue::QueueType::kUnthrottled:
- return TASK_QUEUE_PREFIX "Unthrottled";
- case MainThreadTaskQueue::QueueType::kFrameLoading:
- return TASK_QUEUE_PREFIX "FrameLoading";
- case MainThreadTaskQueue::QueueType::kCompositor:
- return TASK_QUEUE_PREFIX "Compositor";
- case MainThreadTaskQueue::QueueType::kFrameThrottleable:
- return TASK_QUEUE_PREFIX "FrameThrottleable";
- case MainThreadTaskQueue::QueueType::kFramePausable:
- return TASK_QUEUE_PREFIX "FramePausable";
- case MainThreadTaskQueue::QueueType::kControl:
- case MainThreadTaskQueue::QueueType::kIdle:
- case MainThreadTaskQueue::QueueType::kTest:
- case MainThreadTaskQueue::QueueType::kFrameLoadingControl:
- case MainThreadTaskQueue::QueueType::kFrameDeferrable:
- case MainThreadTaskQueue::QueueType::kFrameUnpausable:
- case MainThreadTaskQueue::QueueType::kV8:
- case MainThreadTaskQueue::QueueType::kOther:
- case MainThreadTaskQueue::QueueType::kCount:
- // Using default here as well because there are some values less than COUNT
- // that have been removed and do not correspond to any QueueType.
- default:
- return TASK_QUEUE_PREFIX "Other";
- }
-}
-
-// static
-const char*
-QueueingTimeEstimator::Calculator::GetReportingMessageFromFrameStatus(
- FrameStatus frame_status) {
- switch (frame_status) {
- case FrameStatus::kMainFrameVisible:
- case FrameStatus::kMainFrameVisibleService:
- return FRAME_STATUS_PREFIX "MainFrameVisible";
- case FrameStatus::kMainFrameHidden:
- case FrameStatus::kMainFrameHiddenService:
- return FRAME_STATUS_PREFIX "MainFrameHidden";
- case FrameStatus::kMainFrameBackground:
- case FrameStatus::kMainFrameBackgroundExemptSelf:
- case FrameStatus::kMainFrameBackgroundExemptOther:
- return FRAME_STATUS_PREFIX "MainFrameBackground";
- case FrameStatus::kSameOriginVisible:
- case FrameStatus::kSameOriginVisibleService:
- return FRAME_STATUS_PREFIX "SameOriginVisible";
- case FrameStatus::kSameOriginHidden:
- case FrameStatus::kSameOriginHiddenService:
- return FRAME_STATUS_PREFIX "SameOriginHidden";
- case FrameStatus::kSameOriginBackground:
- case FrameStatus::kSameOriginBackgroundExemptSelf:
- case FrameStatus::kSameOriginBackgroundExemptOther:
- return FRAME_STATUS_PREFIX "SameOriginBackground";
- case FrameStatus::kCrossOriginVisible:
- case FrameStatus::kCrossOriginVisibleService:
- return FRAME_STATUS_PREFIX "CrossOriginVisible";
- case FrameStatus::kCrossOriginHidden:
- case FrameStatus::kCrossOriginHiddenService:
- return FRAME_STATUS_PREFIX "CrossOriginHidden";
- case FrameStatus::kCrossOriginBackground:
- case FrameStatus::kCrossOriginBackgroundExemptSelf:
- case FrameStatus::kCrossOriginBackgroundExemptOther:
- return FRAME_STATUS_PREFIX "CrossOriginBackground";
- case FrameStatus::kNone:
- case FrameStatus::kDetached:
- return FRAME_STATUS_PREFIX "Other";
- case FrameStatus::kCount:
- NOTREACHED();
- return "";
- }
- NOTREACHED();
- return "";
-}
-
void QueueingTimeEstimator::Calculator::UpdateStatusFromTaskQueue(
MainThreadTaskQueue* queue) {
current_queue_type_ =
@@ -251,11 +164,11 @@ void QueueingTimeEstimator::Calculator::AddQueueingTime(
queueing_time;
}
-void QueueingTimeEstimator::Calculator::EndStep(
- QueueingTimeEstimator::Client* client) {
+void QueueingTimeEstimator::Calculator::EndStep(Client* client) {
step_queueing_times_.Add(step_expected_queueing_time_);
- // RendererScheduler reports the queueing time once per disjoint window.
+ DCHECK(client);
+ // MainThreadSchedulerImpl reports the queueing time once per disjoint window.
// |stepEQT|stepEQT|stepEQT|stepEQT|stepEQT|stepEQT|
// Report: |-------window EQT------|
// Discard: |-------window EQT------|
@@ -267,21 +180,64 @@ void QueueingTimeEstimator::Calculator::EndStep(
if (!step_queueing_times_.IndexIsZero())
return;
- std::map<const char*, base::TimeDelta> delta_by_message;
- for (int i = 0; i < static_cast<int>(MainThreadTaskQueue::QueueType::kCount);
- ++i) {
- delta_by_message[GetReportingMessageFromQueueType(
- static_cast<MainThreadTaskQueue::QueueType>(i))] +=
- eqt_by_queue_type_[i];
- }
- for (int i = 0; i < static_cast<int>(FrameStatus::kCount); ++i) {
- delta_by_message[GetReportingMessageFromFrameStatus(
- static_cast<FrameStatus>(i))] += eqt_by_frame_status_[i];
- }
- for (auto it : delta_by_message) {
- client->OnReportFineGrainedExpectedQueueingTime(
- it.first, it.second / steps_per_window_);
- }
+// Report splits by task queue type.
+#define REPORT_BY_TASK_QUEUE(queue) \
+ client->OnReportFineGrainedExpectedQueueingTime( \
+ TASK_QUEUE_PREFIX #queue, \
+ eqt_by_queue_type_[static_cast<int>(QueueType::k##queue)] / \
+ steps_per_window_);
+ REPORT_BY_TASK_QUEUE(Default)
+ REPORT_BY_TASK_QUEUE(Unthrottled)
+ REPORT_BY_TASK_QUEUE(FrameLoading)
+ REPORT_BY_TASK_QUEUE(Compositor)
+ REPORT_BY_TASK_QUEUE(FrameThrottleable)
+ REPORT_BY_TASK_QUEUE(FramePausable)
+#undef REPORT_BY_TASK_QUEUE
+ client->OnReportFineGrainedExpectedQueueingTime(
+ TASK_QUEUE_PREFIX "Other",
+ (eqt_by_queue_type_[static_cast<int>(QueueType::kControl)] +
+ eqt_by_queue_type_[static_cast<int>(QueueType::kIdle)] +
+ eqt_by_queue_type_[static_cast<int>(QueueType::kTest)] +
+ eqt_by_queue_type_[static_cast<int>(QueueType::kFrameLoadingControl)] +
+ eqt_by_queue_type_[static_cast<int>(QueueType::kFrameDeferrable)] +
+ eqt_by_queue_type_[static_cast<int>(QueueType::kFrameUnpausable)] +
+ eqt_by_queue_type_[static_cast<int>(QueueType::kV8)] +
+ eqt_by_queue_type_[static_cast<int>(QueueType::kOther)]) /
+ steps_per_window_);
+
+// Report splits by frame status.
+#define REPORT_BY_FRAME_TYPE(frame) \
+ client->OnReportFineGrainedExpectedQueueingTime( \
+ FRAME_STATUS_PREFIX #frame "Visible", \
+ (eqt_by_frame_status_[static_cast<int>( \
+ FrameStatus::k##frame##Visible)] + \
+ eqt_by_frame_status_[static_cast<int>( \
+ FrameStatus::k##frame##VisibleService)]) / \
+ steps_per_window_); \
+ client->OnReportFineGrainedExpectedQueueingTime( \
+ FRAME_STATUS_PREFIX #frame "Hidden", \
+ (eqt_by_frame_status_[static_cast<int>(FrameStatus::k##frame##Hidden)] + \
+ eqt_by_frame_status_[static_cast<int>( \
+ FrameStatus::k##frame##HiddenService)]) / \
+ steps_per_window_); \
+ client->OnReportFineGrainedExpectedQueueingTime( \
+ FRAME_STATUS_PREFIX #frame "Background", \
+ (eqt_by_frame_status_[static_cast<int>( \
+ FrameStatus::k##frame##Background)] + \
+ eqt_by_frame_status_[static_cast<int>( \
+ FrameStatus::k##frame##BackgroundExemptSelf)] + \
+ eqt_by_frame_status_[static_cast<int>( \
+ FrameStatus::k##frame##BackgroundExemptOther)]) / \
+ steps_per_window_);
+ REPORT_BY_FRAME_TYPE(MainFrame)
+ REPORT_BY_FRAME_TYPE(SameOrigin)
+ REPORT_BY_FRAME_TYPE(CrossOrigin)
+#undef REPORT_BY_FRAME_TYPE
+ client->OnReportFineGrainedExpectedQueueingTime(
+ FRAME_STATUS_PREFIX "Other",
+ (eqt_by_frame_status_[static_cast<int>(FrameStatus::kNone)] +
+ eqt_by_frame_status_[static_cast<int>(FrameStatus::kDetached)]) /
+ steps_per_window_);
std::fill(eqt_by_queue_type_.begin(), eqt_by_queue_type_.end(),
base::TimeDelta());
std::fill(eqt_by_frame_status_.begin(), eqt_by_frame_status_.end(),
@@ -316,28 +272,5 @@ bool QueueingTimeEstimator::RunningAverage::IndexIsZero() const {
return index_ == 0;
}
-// Keeps track of the queueing time.
-class RecordQueueingTimeClient : public QueueingTimeEstimator::Client {
- public:
- // QueueingTimeEstimator::Client implementation:
- void OnQueueingTimeForWindowEstimated(base::TimeDelta queueing_time,
- bool is_disjoint_window) override {
- queueing_time_ = queueing_time;
- }
-
- void OnReportFineGrainedExpectedQueueingTime(
- const char* split_description,
- base::TimeDelta queueing_time) override {}
-
- base::TimeDelta queueing_time() { return queueing_time_; }
-
- RecordQueueingTimeClient() = default;
- ~RecordQueueingTimeClient() override = default;
-
- private:
- base::TimeDelta queueing_time_;
- DISALLOW_COPY_AND_ASSIGN(RecordQueueingTimeClient);
-};
-
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h
index 7fb95dc6a99..f56ab52afa3 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h
@@ -53,10 +53,6 @@ class PLATFORM_EXPORT QueueingTimeEstimator {
class PLATFORM_EXPORT Calculator {
public:
explicit Calculator(int steps_per_window);
- static const char* GetReportingMessageFromQueueType(
- MainThreadTaskQueue::QueueType queue_type);
- static const char* GetReportingMessageFromFrameStatus(
- FrameStatus frame_status);
void UpdateStatusFromTaskQueue(MainThreadTaskQueue* queue);
void AddQueueingTime(base::TimeDelta queuing_time);
@@ -114,10 +110,8 @@ class PLATFORM_EXPORT QueueingTimeEstimator {
base::TimeDelta window_duration,
int steps_per_window);
- void OnTopLevelTaskStarted(base::TimeTicks task_start_time,
- MainThreadTaskQueue* queue);
- void OnTopLevelTaskCompleted(base::TimeTicks task_end_time);
- void OnBeginNestedRunLoop();
+ void OnExecutionStarted(base::TimeTicks now, MainThreadTaskQueue* queue);
+ void OnExecutionStopped(base::TimeTicks now);
void OnRendererStateChanged(bool backgrounded,
base::TimeTicks transition_time);
@@ -128,11 +122,13 @@ class PLATFORM_EXPORT QueueingTimeEstimator {
Client* client_; // NOT OWNED.
const base::TimeDelta window_step_width_;
base::TimeTicks step_start_time_;
- base::TimeTicks current_task_start_time_;
+
+ // Tasks that arrive in the busy period need to wait in a task queue.
+ bool busy_ = false;
+ base::TimeTicks busy_period_start_time_;
+
// |renderer_backgrounded_| is the renderer's current status.
bool renderer_backgrounded_;
- bool processing_task_;
- bool in_nested_message_loop_;
Calculator calculator_;
DISALLOW_ASSIGN(QueueingTimeEstimator);
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator_unittest.cc
index d842b33411f..780a929790d 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/scheduler/main_thread/queueing_time_estimator.h"
+
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -10,6 +11,7 @@
#include "third_party/blink/public/common/page/launching_process_state.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/test/fake_frame_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/test/test_queueing_time_estimator_client.h"
#include "third_party/blink/renderer/platform/testing/histogram_tester.h"
#include <map>
@@ -19,82 +21,13 @@
namespace blink {
namespace scheduler {
-using QueueType = MainThreadTaskQueue::QueueType;
-
namespace {
-class TestQueueingTimeEstimatorClient : public QueueingTimeEstimator::Client {
- public:
- void OnQueueingTimeForWindowEstimated(base::TimeDelta queueing_time,
- bool is_disjoint_window) override {
- expected_queueing_times_.push_back(queueing_time);
- // Mimic RendererSchedulerImpl::OnQueueingTimeForWindowEstimated.
- if (is_disjoint_window) {
- UMA_HISTOGRAM_TIMES("RendererScheduler.ExpectedTaskQueueingDuration",
- queueing_time);
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "RendererScheduler.ExpectedTaskQueueingDuration3",
- queueing_time.InMicroseconds(),
- MainThreadSchedulerImpl::kMinExpectedQueueingTimeBucket,
- MainThreadSchedulerImpl::kMaxExpectedQueueingTimeBucket,
- MainThreadSchedulerImpl::kNumberExpectedQueueingTimeBuckets);
- }
- }
- void OnReportFineGrainedExpectedQueueingTime(
- const char* split_description,
- base::TimeDelta queueing_time) override {
- if (split_eqts_.find(split_description) == split_eqts_.end())
- split_eqts_[split_description] = std::vector<base::TimeDelta>();
- split_eqts_[split_description].push_back(queueing_time);
- // Mimic MainThreadSchedulerImpl::OnReportFineGrainedExpectedQueueingTime.
- base::UmaHistogramCustomCounts(
- split_description, queueing_time.InMicroseconds(),
- MainThreadSchedulerImpl::kMinExpectedQueueingTimeBucket,
- MainThreadSchedulerImpl::kMaxExpectedQueueingTimeBucket,
- MainThreadSchedulerImpl::kNumberExpectedQueueingTimeBuckets);
- }
- const std::vector<base::TimeDelta>& expected_queueing_times() {
- return expected_queueing_times_;
- }
- const std::map<const char*, std::vector<base::TimeDelta>>& split_eqts() {
- return split_eqts_;
- }
- const std::vector<base::TimeDelta>& QueueTypeValues(QueueType queue_type) {
- return split_eqts_[QueueingTimeEstimator::Calculator::
- GetReportingMessageFromQueueType(queue_type)];
- }
- const std::vector<base::TimeDelta>& FrameStatusValues(
- FrameStatus frame_status) {
- return split_eqts_[QueueingTimeEstimator::Calculator::
- GetReportingMessageFromFrameStatus(frame_status)];
- }
-
- private:
- std::vector<base::TimeDelta> expected_queueing_times_;
- std::map<const char*, std::vector<base::TimeDelta>> split_eqts_;
-};
-
-class QueueingTimeEstimatorForTest : public QueueingTimeEstimator {
- public:
- QueueingTimeEstimatorForTest(TestQueueingTimeEstimatorClient* client,
- base::TimeDelta window_duration,
- int steps_per_window,
- base::TimeTicks time)
- : QueueingTimeEstimator(client, window_duration, steps_per_window) {
- // If initial state is not foregrounded, foreground.
- if (kLaunchingProcessIsBackgrounded) {
- this->OnRendererStateChanged(false, time);
- }
- }
-};
-
struct BucketExpectation {
int sample;
int count;
};
-} // namespace
-
class QueueingTimeEstimatorTest : public testing::Test {
protected:
static std::vector<BucketExpectation> GetFineGrained(
@@ -139,6 +72,8 @@ class QueueingTimeEstimatorTest : public testing::Test {
TestQueueingTimeEstimatorClient client;
};
+} // namespace
+
// Three tasks of one second each, all within a 5 second window. Expected
// queueing time is the probability of falling into one of these tasks (3/5),
// multiplied by the expected queueing time within a task (0.5 seconds). Thus we
@@ -147,16 +82,16 @@ TEST_F(QueueingTimeEstimatorTest, AllTasksWithinWindow) {
QueueingTimeEstimatorForTest estimator(
&client, base::TimeDelta::FromSeconds(5), 1, time);
for (int i = 0; i < 3; ++i) {
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(1000);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
}
// Flush the data by adding a task in the next window.
time += base::TimeDelta::FromMilliseconds(5000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(500);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
EXPECT_THAT(client.expected_queueing_times(),
testing::ElementsAre(base::TimeDelta::FromMilliseconds(300)));
@@ -178,20 +113,20 @@ TEST_F(QueueingTimeEstimatorTest, MultiWindowTask) {
QueueingTimeEstimatorForTest estimator(
&client, base::TimeDelta::FromSeconds(5), 1, time);
time += base::TimeDelta::FromMilliseconds(5000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStarted(time, nullptr);
+ estimator.OnExecutionStopped(time);
time += base::TimeDelta::FromMilliseconds(3000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(20000);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
// Flush the data by adding a task in the next window.
time += base::TimeDelta::FromMilliseconds(5000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(500);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
EXPECT_THAT(client.expected_queueing_times(),
testing::ElementsAre(base::TimeDelta::FromMilliseconds(7600),
@@ -209,44 +144,6 @@ TEST_F(QueueingTimeEstimatorTest, MultiWindowTask) {
fine_grained);
}
-// Tasks containing nested run loops may be extremely long without
-// negatively impacting user experience. Ignore such tasks.
-TEST_F(QueueingTimeEstimatorTest, IgnoresTasksWithNestedMessageLoops) {
- QueueingTimeEstimatorForTest estimator(
- &client, base::TimeDelta::FromSeconds(5), 1, time);
- time += base::TimeDelta::FromMilliseconds(5000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
- estimator.OnTopLevelTaskCompleted(time);
-
- time += base::TimeDelta::FromMilliseconds(5000);
-
- estimator.OnTopLevelTaskStarted(time, nullptr);
- time += base::TimeDelta::FromMilliseconds(20000);
- estimator.OnBeginNestedRunLoop();
- estimator.OnTopLevelTaskCompleted(time);
-
- // Perform an additional task after the nested run loop. A 1 second task
- // in a 5 second window results in a 100ms expected queueing time.
- estimator.OnTopLevelTaskStarted(time, nullptr);
- time += base::TimeDelta::FromMilliseconds(1000);
- estimator.OnTopLevelTaskCompleted(time);
-
- // Flush the data by adding a task in the next window.
- time += base::TimeDelta::FromMilliseconds(5000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
- time += base::TimeDelta::FromMilliseconds(500);
- estimator.OnTopLevelTaskCompleted(time);
-
- EXPECT_THAT(client.expected_queueing_times(),
- testing::ElementsAre(base::TimeDelta::FromMilliseconds(0),
- base::TimeDelta::FromMilliseconds(100)));
- std::vector<BucketExpectation> expected = {{0, 1}, {100, 1}};
- TestHistogram("RendererScheduler.ExpectedTaskQueueingDuration", 2, expected);
- std::vector<BucketExpectation> fine_grained = GetFineGrained(expected);
- TestHistogram("RendererScheduler.ExpectedTaskQueueingDuration3", 2,
- fine_grained);
-}
-
// If a task is too long, we assume it's invalid. Perhaps the user's machine
// went to sleep during a task, resulting in an extremely long task. Ignore
// these long tasks completely.
@@ -255,38 +152,38 @@ TEST_F(QueueingTimeEstimatorTest, IgnoreExtremelyLongTasks) {
&client, base::TimeDelta::FromSeconds(5), 1, time);
time += base::TimeDelta::FromMilliseconds(5000);
// Start with a 1 second task.
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(1000);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
time += base::TimeDelta::FromMilliseconds(4000);
// Now perform an invalid task. This will cause the windows involving this
// task to be ignored.
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(35000);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
// Perform another 1 second task.
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(1000);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
// Add a task in the next window.
time += base::TimeDelta::FromMilliseconds(5000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(500);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
// Now perform another invalid task. This will cause the windows involving
// this task to be ignored. Therefore, the previous task is ignored.
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(35000);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
// Flush by adding a task.
time += base::TimeDelta::FromMilliseconds(5000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStarted(time, nullptr);
+ estimator.OnExecutionStopped(time);
EXPECT_THAT(client.expected_queueing_times(),
testing::ElementsAre(base::TimeDelta::FromMilliseconds(100),
@@ -305,28 +202,28 @@ TEST_F(QueueingTimeEstimatorTest, IgnoreExtremelyLongIdlePeriods) {
&client, base::TimeDelta::FromSeconds(5), 1, time);
time += base::TimeDelta::FromMilliseconds(5000);
// Start with a 1 second task.
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(1000);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
time += base::TimeDelta::FromMilliseconds(4000);
// Dummy task to ensure this window is reported.
- estimator.OnTopLevelTaskStarted(time, nullptr);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStarted(time, nullptr);
+ estimator.OnExecutionStopped(time);
// Now go idle for long. This will cause the windows involving this
// time to be ignored.
time += base::TimeDelta::FromMilliseconds(35000);
// Perform another 1 second task.
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(1000);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
// Add a task in the next window.
time += base::TimeDelta::FromMilliseconds(5000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(500);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
// Now go idle again. This will cause the windows involving this idle period
// to be ignored. Therefore, the previous task is ignored.
@@ -334,8 +231,8 @@ TEST_F(QueueingTimeEstimatorTest, IgnoreExtremelyLongIdlePeriods) {
// Flush by adding a task.
time += base::TimeDelta::FromMilliseconds(5000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStarted(time, nullptr);
+ estimator.OnExecutionStopped(time);
EXPECT_THAT(client.expected_queueing_times(),
testing::ElementsAre(base::TimeDelta::FromMilliseconds(100),
@@ -365,14 +262,14 @@ TEST_F(QueueingTimeEstimatorTest, SlidingWindowOverOneTask) {
&client, base::TimeDelta::FromSeconds(5), 5, time);
time += base::TimeDelta::FromMilliseconds(1000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(5000);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
time += base::TimeDelta::FromMilliseconds(6000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStarted(time, nullptr);
+ estimator.OnExecutionStopped(time);
std::vector<base::TimeDelta> expected_durations = {
base::TimeDelta::FromMilliseconds(900),
@@ -411,20 +308,20 @@ TEST_F(QueueingTimeEstimatorTest, SlidingWindowOverTwoTasksWithinFirstWindow) {
&client, base::TimeDelta::FromSeconds(5), 5, time);
time += base::TimeDelta::FromMilliseconds(1000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(2500);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
time += base::TimeDelta::FromMilliseconds(500);
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(1000);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
time += base::TimeDelta::FromMilliseconds(6000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStarted(time, nullptr);
+ estimator.OnExecutionStopped(time);
std::vector<base::TimeDelta> expected_durations = {
base::TimeDelta::FromMilliseconds(400),
@@ -464,23 +361,23 @@ TEST_F(QueueingTimeEstimatorTest,
QueueingTimeEstimatorForTest estimator(
&client, base::TimeDelta::FromSeconds(5), 5, time);
time += base::TimeDelta::FromMilliseconds(1000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStarted(time, nullptr);
+ estimator.OnExecutionStopped(time);
time += base::TimeDelta::FromMilliseconds(4000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(2500);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(1000);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
time += base::TimeDelta::FromMilliseconds(6000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStarted(time, nullptr);
+ estimator.OnExecutionStopped(time);
std::vector<base::TimeDelta> expected_durations = {
base::TimeDelta::FromMilliseconds(0),
@@ -514,42 +411,42 @@ TEST_F(QueueingTimeEstimatorTest, BackgroundedEQTsWithSingleStepPerWindow) {
QueueingTimeEstimatorForTest estimator(
&client, base::TimeDelta::FromSeconds(1), 1, time);
time += base::TimeDelta::FromMilliseconds(1000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStarted(time, nullptr);
+ estimator.OnExecutionStopped(time);
time += base::TimeDelta::FromMilliseconds(1001);
// Second window should not be reported.
estimator.OnRendererStateChanged(true, time);
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(456);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
time += base::TimeDelta::FromMilliseconds(200);
estimator.OnRendererStateChanged(false, time);
time += base::TimeDelta::FromMilliseconds(343);
// Third, fourth windows should be reported
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(1500);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
time += base::TimeDelta::FromMilliseconds(501);
// Fifth, sixth task should not be reported
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(800);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
estimator.OnRendererStateChanged(true, time);
time += base::TimeDelta::FromMilliseconds(200);
estimator.OnRendererStateChanged(false, time);
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(999);
// Seventh task should be reported.
time += base::TimeDelta::FromMilliseconds(200);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
time += base::TimeDelta::FromMilliseconds(1000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStarted(time, nullptr);
+ estimator.OnExecutionStopped(time);
EXPECT_THAT(client.expected_queueing_times(),
testing::ElementsAre(base::TimeDelta::FromMilliseconds(0),
@@ -587,53 +484,53 @@ TEST_F(QueueingTimeEstimatorTest, BackgroundedEQTsWithMutipleStepsPerWindow) {
QueueingTimeEstimatorForTest estimator(
&client, base::TimeDelta::FromSeconds(5), 5, time);
time += base::TimeDelta::FromMilliseconds(5000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStarted(time, nullptr);
+ estimator.OnExecutionStopped(time);
time += base::TimeDelta::FromMilliseconds(500);
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(500);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
estimator.OnRendererStateChanged(true, time);
// This task should be ignored.
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(800);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
estimator.OnRendererStateChanged(false, time);
time += base::TimeDelta::FromMilliseconds(400);
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(1000);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
time += base::TimeDelta::FromMilliseconds(300);
estimator.OnRendererStateChanged(true, time);
time += base::TimeDelta::FromMilliseconds(2000);
// These tasks should be ignored.
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(2000);
- estimator.OnTopLevelTaskCompleted(time);
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStopped(time);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(3400);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
estimator.OnRendererStateChanged(false, time);
time += base::TimeDelta::FromMilliseconds(2000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(1500);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
time += base::TimeDelta::FromMilliseconds(800);
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(2500);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
// Window with last step should not be reported.
estimator.OnRendererStateChanged(true, time);
time += base::TimeDelta::FromMilliseconds(1000);
- estimator.OnTopLevelTaskStarted(time, nullptr);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStarted(time, nullptr);
+ estimator.OnExecutionStopped(time);
EXPECT_THAT(client.expected_queueing_times(),
testing::ElementsAre(base::TimeDelta::FromMilliseconds(25),
@@ -661,25 +558,25 @@ TEST_F(QueueingTimeEstimatorTest, SplitEQTByTaskQueueType) {
&client, base::TimeDelta::FromSeconds(5), 5, time);
time += base::TimeDelta::FromMilliseconds(5000);
// Dummy task to initialize the estimator.
- estimator.OnTopLevelTaskStarted(time, nullptr);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStarted(time, nullptr);
+ estimator.OnExecutionStopped(time);
// Beginning of window 1.
time += base::TimeDelta::FromMilliseconds(500);
scoped_refptr<MainThreadTaskQueueForTest> default_queue(
new MainThreadTaskQueueForTest(QueueType::kDefault));
- estimator.OnTopLevelTaskStarted(time, default_queue.get());
+ estimator.OnExecutionStarted(time, default_queue.get());
time += base::TimeDelta::FromMilliseconds(3000);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
time += base::TimeDelta::FromMilliseconds(1500);
// Beginning of window 2.
time += base::TimeDelta::FromMilliseconds(3000);
- estimator.OnTopLevelTaskStarted(time, default_queue.get());
+ estimator.OnExecutionStarted(time, default_queue.get());
time += base::TimeDelta::FromMilliseconds(3000);
// 1000 ms after beginning of window 3.
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
time += base::TimeDelta::FromMilliseconds(1000);
scoped_refptr<MainThreadTaskQueueForTest> frame_loading_queue(
@@ -692,9 +589,9 @@ TEST_F(QueueingTimeEstimatorTest, SplitEQTByTaskQueueType) {
frame_throttleable_queue.get(),
unthrottled_queue.get()};
for (auto* queue : queues_for_thousand) {
- estimator.OnTopLevelTaskStarted(time, queue);
+ estimator.OnExecutionStarted(time, queue);
time += base::TimeDelta::FromMilliseconds(1000);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
}
// Beginning of window 4.
@@ -710,9 +607,9 @@ TEST_F(QueueingTimeEstimatorTest, SplitEQTByTaskQueueType) {
unthrottled_queue.get(),
compositor_queue.get()};
for (auto* queue : queues_for_six_hundred) {
- estimator.OnTopLevelTaskStarted(time, queue);
+ estimator.OnExecutionStarted(time, queue);
time += base::TimeDelta::FromMilliseconds(600);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
}
time += base::TimeDelta::FromMilliseconds(600);
@@ -720,22 +617,22 @@ TEST_F(QueueingTimeEstimatorTest, SplitEQTByTaskQueueType) {
// supported queue type.
scoped_refptr<MainThreadTaskQueueForTest> control_queue(
new MainThreadTaskQueueForTest(QueueType::kControl));
- estimator.OnTopLevelTaskStarted(time, control_queue.get());
+ estimator.OnExecutionStarted(time, control_queue.get());
time += base::TimeDelta::FromMilliseconds(300);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
// The following task contributes to "Other" because kTest is not a supported
// queue type.
scoped_refptr<MainThreadTaskQueueForTest> test_queue(
new MainThreadTaskQueueForTest(QueueType::kTest));
- estimator.OnTopLevelTaskStarted(time, test_queue.get());
+ estimator.OnExecutionStarted(time, test_queue.get());
time += base::TimeDelta::FromMilliseconds(300);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
// The following task contributes to "Other" because there is no task queue.
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(200);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
// End of window 4. Now check the vectors per task queue type.
EXPECT_THAT(client.QueueTypeValues(QueueType::kDefault),
@@ -845,8 +742,8 @@ TEST_F(QueueingTimeEstimatorTest, SplitEQTByFrameStatus) {
&client, base::TimeDelta::FromSeconds(5), 5, time);
time += base::TimeDelta::FromMilliseconds(5000);
// Dummy task to initialize the estimator.
- estimator.OnTopLevelTaskStarted(time, nullptr);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStarted(time, nullptr);
+ estimator.OnExecutionStopped(time);
scoped_refptr<MainThreadTaskQueueForTest> queue1(
new MainThreadTaskQueueForTest(QueueType::kTest));
@@ -858,9 +755,9 @@ TEST_F(QueueingTimeEstimatorTest, SplitEQTByFrameStatus) {
.SetFrameType(FrameScheduler::FrameType::kMainFrame)
.Build();
queue1->SetFrameSchedulerForTest(frame1.get());
- estimator.OnTopLevelTaskStarted(time, queue1.get());
+ estimator.OnExecutionStarted(time, queue1.get());
time += base::TimeDelta::FromMilliseconds(3000);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
time += base::TimeDelta::FromMilliseconds(1500);
// Beginning of window 2.
@@ -872,17 +769,17 @@ TEST_F(QueueingTimeEstimatorTest, SplitEQTByFrameStatus) {
.SetIsFrameVisible(true)
.Build();
queue1->SetFrameSchedulerForTest(frame2.get());
- estimator.OnTopLevelTaskStarted(time, queue1.get());
+ estimator.OnExecutionStarted(time, queue1.get());
time += base::TimeDelta::FromMilliseconds(2000);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
scoped_refptr<MainThreadTaskQueueForTest> queue2(
new MainThreadTaskQueueForTest(QueueType::kTest));
queue2->SetFrameSchedulerForTest(frame2.get());
time += base::TimeDelta::FromMilliseconds(1000);
- estimator.OnTopLevelTaskStarted(time, queue2.get());
+ estimator.OnExecutionStarted(time, queue2.get());
time += base::TimeDelta::FromMilliseconds(2000);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
// Beginning of window 3.
// Scheduler with frame type: MAIN_FRAME_VISIBLE.
@@ -894,9 +791,9 @@ TEST_F(QueueingTimeEstimatorTest, SplitEQTByFrameStatus) {
.SetIsExemptFromThrottling(true)
.Build();
queue1->SetFrameSchedulerForTest(frame3.get());
- estimator.OnTopLevelTaskStarted(time, queue1.get());
+ estimator.OnExecutionStarted(time, queue1.get());
time += base::TimeDelta::FromMilliseconds(3000);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
// Scheduler with frame type: MAIN_FRAME_BACKGROUND.
std::unique_ptr<FakeFrameScheduler> frame4 =
@@ -906,10 +803,10 @@ TEST_F(QueueingTimeEstimatorTest, SplitEQTByFrameStatus) {
.SetIsExemptFromThrottling(true)
.Build();
queue1->SetFrameSchedulerForTest(frame4.get());
- estimator.OnTopLevelTaskStarted(time, queue1.get());
+ estimator.OnExecutionStarted(time, queue1.get());
time += base::TimeDelta::FromMilliseconds(3000);
// 1000 ms after beginning of window 4.
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
time += base::TimeDelta::FromMilliseconds(1000);
// Scheduler with frame type: SAME_ORIGIN_VISIBLE.
@@ -937,9 +834,9 @@ TEST_F(QueueingTimeEstimatorTest, SplitEQTByFrameStatus) {
frame7.get()};
for (auto* scheduler : schedulers_for_thousand) {
queue1->SetFrameSchedulerForTest(scheduler);
- estimator.OnTopLevelTaskStarted(time, queue1.get());
+ estimator.OnExecutionStarted(time, queue1.get());
time += base::TimeDelta::FromMilliseconds(1000);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
}
// Beginning of window 5.
@@ -973,24 +870,24 @@ TEST_F(QueueingTimeEstimatorTest, SplitEQTByFrameStatus) {
frame9.get(), frame7.get(), frame10.get(), frame11.get()};
for (auto* scheduler : schedulers_for_four_hundred) {
queue1->SetFrameSchedulerForTest(scheduler);
- estimator.OnTopLevelTaskStarted(time, queue1.get());
+ estimator.OnExecutionStarted(time, queue1.get());
time += base::TimeDelta::FromMilliseconds(400);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
}
// The following tasks contribute to "Other" because there is no frame.
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(300);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
queue1->DetachFromFrameScheduler();
- estimator.OnTopLevelTaskStarted(time, queue1.get());
+ estimator.OnExecutionStarted(time, queue1.get());
time += base::TimeDelta::FromMilliseconds(300);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
- estimator.OnTopLevelTaskStarted(time, nullptr);
+ estimator.OnExecutionStarted(time, nullptr);
time += base::TimeDelta::FromMilliseconds(800);
- estimator.OnTopLevelTaskCompleted(time);
+ estimator.OnExecutionStopped(time);
// End of window 5. Now check the vectors per frame type.
EXPECT_THAT(client.FrameStatusValues(FrameStatus::kMainFrameBackground),
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/resource_loading_task_runner_handle_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/resource_loading_task_runner_handle_impl.cc
new file mode 100644
index 00000000000..685fd6a8acd
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/resource_loading_task_runner_handle_impl.cc
@@ -0,0 +1,57 @@
+#include "third_party/blink/renderer/platform/scheduler/main_thread/resource_loading_task_runner_handle_impl.h"
+
+#include <iostream>
+
+#include "base/memory/ptr_util.h"
+#include "base/task/sequence_manager/task_queue.h"
+#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
+
+namespace blink {
+namespace scheduler {
+
+using base::sequence_manager::TaskQueue;
+
+std::unique_ptr<ResourceLoadingTaskRunnerHandleImpl>
+ResourceLoadingTaskRunnerHandleImpl::WrapTaskRunner(
+ scoped_refptr<MainThreadTaskQueue> task_queue) {
+ DCHECK(task_queue);
+ return base::WrapUnique(
+ new ResourceLoadingTaskRunnerHandleImpl(std::move(task_queue)));
+}
+
+ResourceLoadingTaskRunnerHandleImpl::ResourceLoadingTaskRunnerHandleImpl(
+ scoped_refptr<MainThreadTaskQueue> task_queue)
+ : task_queue_(std::move(task_queue)),
+ task_runner_(TaskQueueWithTaskType::Create(
+ task_queue_,
+ TaskType::kNetworkingWithURLLoaderAnnotation)){};
+
+ResourceLoadingTaskRunnerHandleImpl::~ResourceLoadingTaskRunnerHandleImpl() {
+ if (task_queue_->GetFrameScheduler()) {
+ task_queue_->GetFrameScheduler()->OnShutdownResourceLoadingTaskQueue(
+ task_queue_);
+ }
+}
+
+void ResourceLoadingTaskRunnerHandleImpl::DidChangeRequestPriority(
+ net::RequestPriority priority) {
+ FrameSchedulerImpl* frame_scheduler = task_queue_->GetFrameScheduler();
+ if (frame_scheduler) {
+ frame_scheduler->DidChangeResourceLoadingPriority(task_queue_, priority);
+ }
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+ResourceLoadingTaskRunnerHandleImpl::GetTaskRunner() const {
+ return task_runner_;
+}
+
+const scoped_refptr<MainThreadTaskQueue>&
+ResourceLoadingTaskRunnerHandleImpl::task_queue() {
+ return task_queue_;
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/resource_loading_task_runner_handle_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/resource_loading_task_runner_handle_impl.h
new file mode 100644
index 00000000000..4b13aeec409
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/resource_loading_task_runner_handle_impl.h
@@ -0,0 +1,48 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_RESOURCE_LOADING_TASK_RUNNER_HANDLE_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_RESOURCE_LOADING_TASK_RUNNER_HANDLE_IMPL_H_
+
+#include <memory>
+
+#include "third_party/blink/public/platform/scheduler/web_resource_loading_task_runner_handle.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
+
+namespace blink {
+namespace scheduler {
+
+// Provides an interface to the loading stack (i.e. WebURLLoader) to post
+// resource loading tasks and to notify blink's scheduler when a resource's
+// fetch priority changes.
+class PLATFORM_EXPORT ResourceLoadingTaskRunnerHandleImpl
+ : public WebResourceLoadingTaskRunnerHandle {
+ public:
+ static std::unique_ptr<ResourceLoadingTaskRunnerHandleImpl> WrapTaskRunner(
+ scoped_refptr<MainThreadTaskQueue> task_runner);
+
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() const override;
+
+ void DidChangeRequestPriority(net::RequestPriority priority) override;
+
+ const scoped_refptr<MainThreadTaskQueue>& task_queue();
+
+ ~ResourceLoadingTaskRunnerHandleImpl() override;
+
+ protected:
+ explicit ResourceLoadingTaskRunnerHandleImpl(
+ scoped_refptr<MainThreadTaskQueue> task_queue);
+
+ private:
+ scoped_refptr<MainThreadTaskQueue> task_queue_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResourceLoadingTaskRunnerHandleImpl);
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.h b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.h
index afbab65cd6e..559a853e62d 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/user_model.h
@@ -8,7 +8,7 @@
#include "base/macros.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_argument.h"
-#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/renderer/platform/platform_export.h"
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_main_thread_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_main_thread_scheduler.cc
deleted file mode 100644
index 7009683434e..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/main_thread/web_main_thread_scheduler.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h"
-
-#include <memory>
-#include "base/command_line.h"
-#include "base/memory/ptr_util.h"
-#include "base/metrics/field_trial.h"
-#include "base/time/default_tick_clock.h"
-#include "base/trace_event/trace_event.h"
-#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/util/tracing_helper.h"
-
-namespace blink {
-namespace scheduler {
-
-WebMainThreadScheduler::WebMainThreadScheduler() = default;
-
-WebMainThreadScheduler::~WebMainThreadScheduler() = default;
-
-WebMainThreadScheduler::RAILModeObserver::~RAILModeObserver() = default;
-
-// static
-std::unique_ptr<WebMainThreadScheduler> WebMainThreadScheduler::Create(
- base::Optional<base::Time> initial_virtual_time) {
- // Ensure categories appear as an option in chrome://tracing.
- WarmupTracingCategories();
- // Workers might be short-lived, so placing warmup here.
- TRACE_EVENT_WARMUP_CATEGORY(TRACE_DISABLED_BY_DEFAULT("worker.scheduler"));
-
- std::unique_ptr<MainThreadSchedulerImpl> scheduler(
- new MainThreadSchedulerImpl(
- base::sequence_manager::TaskQueueManager::TakeOverCurrentThread(),
- initial_virtual_time));
- return base::WrapUnique<WebMainThreadScheduler>(scheduler.release());
-}
-
-// static
-const char* WebMainThreadScheduler::InputEventStateToString(
- InputEventState input_event_state) {
- switch (input_event_state) {
- case InputEventState::EVENT_CONSUMED_BY_COMPOSITOR:
- return "event_consumed_by_compositor";
- case InputEventState::EVENT_FORWARDED_TO_MAIN_THREAD:
- return "event_forwarded_to_main_thread";
- default:
- NOTREACHED();
- return nullptr;
- }
-}
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/background_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/public/background_scheduler.h
new file mode 100644
index 00000000000..ef80a0a828e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/background_scheduler.h
@@ -0,0 +1,28 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_BACKGROUND_SCHEDULER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_BACKGROUND_SCHEDULER_H_
+
+#include "base/location.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+
+namespace blink {
+
+namespace BackgroundScheduler {
+
+// This is a thin wrapper around base::TaskScheduler to accomodate
+// Blink's CrossThreadClosure, which only allows background tasks.
+//
+// Non-background tasks should be posted using another scheduler, e.g.
+// FrameShceduler.
+PLATFORM_EXPORT void PostOnBackgroundThread(const base::Location&,
+ CrossThreadClosure);
+
+} // namespace BackgroundScheduler
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_BACKGROUND_SCHEDULER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h
index 5121a7f7b6a..94c1c1caf59 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h
@@ -5,16 +5,49 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_FRAME_OR_WORKER_SCHEDULER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_FRAME_OR_WORKER_SCHEDULER_H_
+#include <unordered_map>
+
+#include "base/memory/weak_ptr.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/scheduler/public/scheduling_lifecycle_state.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
namespace blink {
+class FrameScheduler;
// This is the base class of FrameScheduler and WorkerScheduler.
-class FrameOrWorkerScheduler {
+class PLATFORM_EXPORT FrameOrWorkerScheduler {
USING_FAST_MALLOC(FrameOrWorkerScheduler);
public:
- virtual ~FrameOrWorkerScheduler() = default;
+ // Observer type that regulates conditions to invoke callbacks.
+ enum class ObserverType { kLoader, kWorkerScheduler };
+
+ // Observer interface to receive scheduling policy change events.
+ class Observer {
+ public:
+ virtual ~Observer() = default;
+
+ // Notified when throttling state is changed. May be called consecutively
+ // with the same value.
+ virtual void OnLifecycleStateChanged(
+ scheduler::SchedulingLifecycleState) = 0;
+ };
+
+ class PLATFORM_EXPORT LifecycleObserverHandle {
+ public:
+ LifecycleObserverHandle(FrameOrWorkerScheduler* scheduler,
+ Observer* observer);
+ ~LifecycleObserverHandle();
+
+ private:
+ base::WeakPtr<FrameOrWorkerScheduler> scheduler_;
+ Observer* observer_;
+
+ DISALLOW_COPY_AND_ASSIGN(LifecycleObserverHandle);
+ };
+
+ virtual ~FrameOrWorkerScheduler();
class ActiveConnectionHandle {
public:
@@ -30,6 +63,35 @@ class FrameOrWorkerScheduler {
// this handle must be destroyed.
virtual std::unique_ptr<ActiveConnectionHandle>
OnActiveConnectionCreated() = 0;
+
+ // Adds an Observer instance to be notified on scheduling policy changed.
+ // When an Observer is added, the initial state will be notified synchronously
+ // through the Observer interface.
+ // A RAII handle is returned and observer is unregistered when the handle is
+ // destroyed.
+ std::unique_ptr<LifecycleObserverHandle> AddLifecycleObserver(ObserverType,
+ Observer*);
+
+ virtual FrameScheduler* ToFrameScheduler() { return nullptr; }
+
+ protected:
+ FrameOrWorkerScheduler();
+
+ void NotifyLifecycleObservers();
+
+ virtual scheduler::SchedulingLifecycleState CalculateLifecycleState(
+ ObserverType) const {
+ return scheduler::SchedulingLifecycleState::kNotThrottled;
+ }
+
+ base::WeakPtr<FrameOrWorkerScheduler> GetWeakPtr();
+
+ private:
+ void RemoveLifecycleObserver(Observer* observer);
+
+ // Observers are not owned by the scheduler.
+ std::unordered_map<Observer*, ObserverType> lifecycle_observers_;
+ base::WeakPtrFactory<FrameOrWorkerScheduler> weak_factory_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h
index c10e521fcb0..d82659b7ddf 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h
@@ -9,6 +9,8 @@
#include "base/memory/scoped_refptr.h"
#include "base/single_thread_task_runner.h"
+#include "third_party/blink/public/mojom/loader/pause_subresource_loading_handle.mojom-blink.h"
+#include "third_party/blink/public/platform/scheduler/web_resource_loading_task_runner_handle.h"
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/public/platform/web_scoped_virtual_time_pauser.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -23,59 +25,12 @@ class FrameScheduler : public FrameOrWorkerScheduler {
public:
~FrameScheduler() override = default;
- // Observer type that regulates conditions to invoke callbacks.
- enum class ObserverType { kLoader, kWorkerScheduler };
-
- // Represents throttling state.
- // TODO(altimin): Move it into standalone LifecycleState.
- enum class ThrottlingState {
- // Frame is active and should not be throttled.
- kNotThrottled,
- // Frame has just been backgrounded and can be throttled non-aggressively.
- kHidden,
- // Frame spent some time in background and can be fully throttled.
- kThrottled,
- // Frame is stopped, no tasks associated with it can run.
- kStopped,
- };
-
- PLATFORM_EXPORT static const char* ThrottlingStateToString(
- ThrottlingState state);
-
// Represents the type of frame: main (top-level) vs not.
enum class FrameType {
kMainFrame,
kSubframe,
};
- // Observer interface to receive scheduling policy change events.
- class Observer {
- public:
- virtual ~Observer() = default;
-
- // Notified when throttling state is changed. May be called consecutively
- // with the same value.
- virtual void OnThrottlingStateChanged(ThrottlingState) = 0;
- };
-
- class ThrottlingObserverHandle {
- public:
- ThrottlingObserverHandle() = default;
- virtual ~ThrottlingObserverHandle() = default;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ThrottlingObserverHandle);
- };
-
- // Adds an Observer instance to be notified on scheduling policy changed.
- // When an Observer is added, the initial state will be notified synchronously
- // through the Observer interface.
- // A RAII handle is returned and observer is unregistered when the handle is
- // destroyed.
- virtual std::unique_ptr<ThrottlingObserverHandle> AddThrottlingObserver(
- ObserverType,
- Observer*) = 0;
-
// The scheduler may throttle tasks associated with offscreen frames.
virtual void SetFrameVisible(bool) = 0;
virtual bool IsFrameVisible() const = 0;
@@ -95,6 +50,10 @@ class FrameScheduler : public FrameOrWorkerScheduler {
// frames.
virtual void SetCrossOrigin(bool) = 0;
virtual bool IsCrossOrigin() const = 0;
+
+ virtual void SetIsAdFrame() = 0;
+ virtual bool IsAdFrame() const = 0;
+
virtual void TraceUrlChange(const String&) = 0;
// Returns the frame type, which currently determines whether this frame is
@@ -133,6 +92,13 @@ class FrameScheduler : public FrameOrWorkerScheduler {
virtual scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(
TaskType) = 0;
+ // Returns a WebResourceLoadingTaskRunnerHandle which is intended to be used
+ // by the loading stack to post resource loading tasks to the renderer's main
+ // thread and to notify the main thread of any change in the resource's fetch
+ // (net) priority.
+ virtual std::unique_ptr<scheduler::WebResourceLoadingTaskRunnerHandle>
+ CreateResourceLoadingTaskRunnerHandle() = 0;
+
// Returns the parent PageScheduler.
virtual PageScheduler* GetPageScheduler() const = 0;
@@ -168,6 +134,13 @@ class FrameScheduler : public FrameOrWorkerScheduler {
// use GetPageScheduler()->IsExemptFromBudgetBasedThrottling for the status
// of the page.
virtual bool IsExemptFromBudgetBasedThrottling() const = 0;
+
+ FrameScheduler* ToFrameScheduler() override { return this; }
+
+ // Returns a handle that prevents resource loading as long as the handle
+ // exists.
+ virtual std::unique_ptr<blink::mojom::blink::PauseSubresourceLoadingHandle>
+ GetPauseSubresourceLoadingHandle() = 0;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/non_main_thread_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/public/non_main_thread_scheduler.h
deleted file mode 100644
index fed347c79a1..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/non_main_thread_scheduler.h
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_NON_MAIN_THREAD_SCHEDULER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_NON_MAIN_THREAD_SCHEDULER_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "third_party/blink/public/platform/scheduler/single_thread_idle_task_runner.h"
-#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
-#include "third_party/blink/public/platform/web_thread_type.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/child/worker_task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h"
-#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
-#include "third_party/blink/renderer/platform/scheduler/util/tracing_helper.h"
-#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h"
-
-namespace blink {
-namespace scheduler {
-class TaskQueueWithTaskType;
-class WorkerSchedulerProxy;
-class WorkerScheduler;
-class TaskQueueThrottler;
-class WakeUpBudgetPool;
-
-// TODO(yutak): Rename this class to NonMainThreadSchedulerImpl and consider
-// changing all non-impl scheduler classes to have only static methods.
-class PLATFORM_EXPORT NonMainThreadScheduler : public ThreadSchedulerImpl {
- public:
- ~NonMainThreadScheduler() override;
-
- static std::unique_ptr<NonMainThreadScheduler> Create(
- WebThreadType thread_type,
- WorkerSchedulerProxy* proxy);
-
- // Same as ThreadScheduler::Current(), but this asserts the caller is on
- // a non-main thread.
- static NonMainThreadScheduler* Current();
-
- // Blink should use NonMainThreadScheduler::DefaultTaskQueue instead of
- // WebThreadScheduler::DefaultTaskRunner.
- virtual scoped_refptr<WorkerTaskQueue> DefaultTaskQueue() = 0;
-
- // Must be called before the scheduler can be used. Does any post construction
- // initialization needed such as initializing idle period detection.
- void Init();
-
- virtual void OnTaskCompleted(
- WorkerTaskQueue* worker_task_queue,
- const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start,
- base::TimeTicks end,
- base::Optional<base::TimeDelta> thread_time) = 0;
-
- // ThreadSchedulerImpl:
- scoped_refptr<base::SingleThreadTaskRunner> ControlTaskRunner() override;
- void RegisterTimeDomain(
- base::sequence_manager::TimeDomain* time_domain) override;
- void UnregisterTimeDomain(
- base::sequence_manager::TimeDomain* time_domain) override;
- base::sequence_manager::TimeDomain* GetActiveTimeDomain() override;
- const base::TickClock* GetTickClock() override;
-
- // ThreadScheduler implementation.
- // TODO(yutak): Some functions are only meaningful in main thread. Move them
- // to MainThreadScheduler.
- void PostIdleTask(const base::Location& location,
- WebThread::IdleTask task) override;
- void PostNonNestableIdleTask(const base::Location& location,
- WebThread::IdleTask task) override;
- scoped_refptr<base::SingleThreadTaskRunner> V8TaskRunner() override;
- scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner() override;
- std::unique_ptr<PageScheduler> CreatePageScheduler(
- PageScheduler::Delegate*) override;
- std::unique_ptr<RendererPauseHandle> PauseScheduler() override
- WARN_UNUSED_RESULT;
-
- // Returns TimeTicks::Now() by default.
- base::TimeTicks MonotonicallyIncreasingVirtualTime() override;
-
- NonMainThreadScheduler* AsNonMainThreadScheduler() override { return this; }
-
- // The following virtual methods are defined in *both* WebThreadScheduler
- // and ThreadScheduler, with identical interfaces and semantics. They are
- // overriden in a subclass, effectively implementing the virtual methods
- // in both classes at the same time. This is allowed in C++, as long as
- // there is only one final overrider (i.e. definitions in base classes are
- // not used in instantiated objects, since otherwise they may have multiple
- // definitions of the virtual function in question).
- //
- // virtual void Shutdown();
-
- scoped_refptr<WorkerTaskQueue> CreateTaskRunner();
-
- // TaskQueueThrottler might be null if throttling is not enabled or
- // not supported.
- TaskQueueThrottler* task_queue_throttler() const {
- return task_queue_throttler_.get();
- }
- WakeUpBudgetPool* wake_up_budget_pool() const { return wake_up_budget_pool_; }
-
- protected:
- explicit NonMainThreadScheduler(
- std::unique_ptr<NonMainThreadSchedulerHelper> helper);
-
- friend class WorkerScheduler;
-
- // Each WorkerScheduler should notify NonMainThreadScheduler when it is
- // created or destroyed.
- virtual void RegisterWorkerScheduler(WorkerScheduler* worker_scheduler);
- virtual void UnregisterWorkerScheduler(WorkerScheduler* worker_scheduler);
-
- // Called during Init() for delayed initialization for subclasses.
- virtual void InitImpl() = 0;
-
- // This controller should be initialized before any TraceableVariables
- // because they require one to initialize themselves.
- TraceableVariableController traceable_variable_controller_;
-
- std::unique_ptr<NonMainThreadSchedulerHelper> helper_;
-
- // Worker schedulers associated with this thread.
- std::unordered_set<WorkerScheduler*> worker_schedulers_;
-
- std::unique_ptr<TaskQueueThrottler> task_queue_throttler_;
- // Owned by |task_queue_throttler_|.
- WakeUpBudgetPool* wake_up_budget_pool_ = nullptr;
-
- private:
- static void RunIdleTask(WebThread::IdleTask task, base::TimeTicks deadline);
- scoped_refptr<TaskQueueWithTaskType> v8_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(NonMainThreadScheduler);
-};
-
-} // namespace scheduler
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_NON_MAIN_THREAD_SCHEDULER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/page_lifecycle_state.h b/chromium/third_party/blink/renderer/platform/scheduler/public/page_lifecycle_state.h
new file mode 100644
index 00000000000..33b6ee306da
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/page_lifecycle_state.h
@@ -0,0 +1,33 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_PAGE_LIFECYCLE_STATE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_PAGE_LIFECYCLE_STATE_H_
+
+namespace blink {
+
+// Page lifecycle states, as defined in
+// https://github.com/WICG/page-lifecycle/blob/master/README.md. We maintain two
+// HIDDEN states, distinguishing between hidden pages that should not be frozen
+// because they are still providing a service (e.g. audio), and hidden pages
+// that are not providing a service and are eligible to be frozen.
+enum class PageLifecycleState {
+ // The page state is unknown.
+ kUnknown,
+ // The page is visible and active.
+ kActive,
+ // The page is not visible, but is still active, performing a useful service
+ // for the user, such as playing audio.
+ kHiddenForegrounded,
+ // The page is not visible and not active.
+ kHiddenBackgrounded,
+ // The page is frozen.
+ kFrozen,
+};
+
+constexpr PageLifecycleState kDefaultPageLifecycleState =
+ PageLifecycleState::kUnknown;
+
+} // namespace blink
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_PAGE_LIFECYCLE_STATE_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/page_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/public/page_scheduler.h
index c0cf79d9dff..603595002d2 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/page_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/page_scheduler.h
@@ -9,6 +9,7 @@
#include "third_party/blink/public/platform/blame_context.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/page_lifecycle_state.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -25,8 +26,10 @@ class PLATFORM_EXPORT PageScheduler {
virtual ~Delegate() = default;
virtual void ReportIntervention(const WTF::String& message) = 0;
- virtual void RequestBeginMainFrameNotExpected(bool new_state) = 0;
- virtual void SetPageFrozen(bool frozen) = 0;
+ // Returns true if the request has been succcessfully relayed to the
+ // compositor.
+ virtual bool RequestBeginMainFrameNotExpected(bool new_state) = 0;
+ virtual void SetLifecycleState(PageLifecycleState) = 0;
virtual ukm::UkmRecorder* GetUkmRecorder() = 0;
virtual int64_t GetUkmSourceId() = 0;
};
@@ -35,7 +38,7 @@ class PLATFORM_EXPORT PageScheduler {
// The scheduler may throttle tasks associated with background pages.
virtual void SetPageVisible(bool) = 0;
- // The scheduler transitions app to and from STOPPED state in background.
+ // The scheduler transitions app to and from FROZEN state in background.
virtual void SetPageFrozen(bool) = 0;
// Tells the scheduler about "keep-alive" state which can be due to:
// service workers, shared workers, or fetch keep-alive.
@@ -149,7 +152,9 @@ class PLATFORM_EXPORT PageScheduler {
virtual bool HasActiveConnectionForTest() const = 0;
- virtual void RequestBeginMainFrameNotExpected(bool new_state) = 0;
+ // Returns true if the request has been succcessfully relayed to the
+ // compositor.
+ virtual bool RequestBeginMainFrameNotExpected(bool new_state) = 0;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/scheduling_lifecycle_state.h b/chromium/third_party/blink/renderer/platform/scheduler/public/scheduling_lifecycle_state.h
new file mode 100644
index 00000000000..d4791532c26
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/scheduling_lifecycle_state.h
@@ -0,0 +1,32 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_SCHEDULING_LIFECYCLE_STATE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_SCHEDULING_LIFECYCLE_STATE_H_
+
+namespace blink {
+namespace scheduler {
+
+// The scheduling state of the frame which is communicated to observers.
+// It's closely related to Web Lifecycle[1] states and should be distingushed
+// from DocumentLifecycle.
+//
+// [1] https://wicg.github.io/page-lifecycle/spec.html.
+enum class SchedulingLifecycleState {
+ // Frame is active and should not be throttled.
+ kNotThrottled,
+ // Frame has just been backgrounded and can be throttled non-aggressively.
+ kHidden,
+ // Frame spent some time in background and can be fully throttled.
+ kThrottled,
+ // Frame is stopped, no tasks associated with it can run.
+ kStopped,
+};
+
+const char* SchedulingLifecycleStateToString(SchedulingLifecycleState state);
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_SCHEDULING_LIFECYCLE_STATE_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h
index 5166bd66dcf..8381a3615cc 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h
@@ -10,13 +10,13 @@
#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
-#include "third_party/blink/public/platform/scheduler/web_main_thread_scheduler.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/platform/scheduler/public/page_scheduler.h"
namespace blink {
namespace scheduler {
-class NonMainThreadScheduler;
+class NonMainThreadSchedulerImpl;
}
// This class is used to submit tasks and pass other information from Blink to
@@ -25,7 +25,7 @@ class NonMainThreadScheduler;
class PLATFORM_EXPORT ThreadScheduler {
public:
using RendererPauseHandle =
- scheduler::WebMainThreadScheduler::RendererPauseHandle;
+ scheduler::WebThreadScheduler::RendererPauseHandle;
// Return the current thread's ThreadScheduler.
//
@@ -68,6 +68,9 @@ class PLATFORM_EXPORT ThreadScheduler {
virtual void PostNonNestableIdleTask(const base::Location&,
WebThread::IdleTask) = 0;
+ virtual void AddRAILModeObserver(
+ scheduler::WebThreadScheduler::RAILModeObserver* observer) = 0;
+
// Returns a task runner for kV8 tasks. Can be called from any thread.
virtual scoped_refptr<base::SingleThreadTaskRunner> V8TaskRunner() = 0;
@@ -82,7 +85,7 @@ class PLATFORM_EXPORT ThreadScheduler {
virtual std::unique_ptr<PageScheduler> CreatePageScheduler(
PageScheduler::Delegate*) = 0;
- // Pauses the scheduler. See WebMainThreadScheduler::PauseRenderer for
+ // Pauses the scheduler. See WebThreadScheduler::PauseRenderer for
// details. May only be called from the main thread.
virtual std::unique_ptr<RendererPauseHandle> PauseScheduler()
WARN_UNUSED_RESULT = 0;
@@ -101,15 +104,14 @@ class PLATFORM_EXPORT ThreadScheduler {
// Test helpers.
- // Return a reference to an underlying WebMainThreadScheduler object.
- // Can be null if there is no underlying WebMainThreadScheduler
+ // Return a reference to an underlying main thread WebThreadScheduler object.
+ // Can be null if there is no underlying main thread WebThreadScheduler
// (e.g. worker threads).
- virtual scheduler::WebMainThreadScheduler*
- GetWebMainThreadSchedulerForTest() {
+ virtual scheduler::WebThreadScheduler* GetWebMainThreadSchedulerForTest() {
return nullptr;
}
- virtual scheduler::NonMainThreadScheduler* AsNonMainThreadScheduler() = 0;
+ virtual scheduler::NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() = 0;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h
new file mode 100644
index 00000000000..63873ee6db3
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h
@@ -0,0 +1,78 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_WORKER_SCHEDULER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_WORKER_SCHEDULER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "base/task/sequence_manager/task_queue.h"
+#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
+
+namespace blink {
+
+namespace scheduler {
+
+class WorkerSchedulerProxy;
+class WorkerThreadScheduler;
+
+// A scheduler provides per-global-scope task queues. This is constructed when a
+// global scope is created and destructed when it's closed.
+//
+// Unless stated otherwise, all methods must be called on the worker thread.
+class PLATFORM_EXPORT WorkerScheduler : public FrameOrWorkerScheduler {
+ public:
+ WorkerScheduler(WorkerThreadScheduler* worker_thread_scheduler,
+ WorkerSchedulerProxy* proxy);
+ ~WorkerScheduler() override;
+
+ std::unique_ptr<ActiveConnectionHandle> OnActiveConnectionCreated() override;
+
+ // Unregisters the task queues and cancels tasks in them.
+ void Dispose();
+
+ // Returns a task runner that is suitable with the given task type. This can
+ // be called from any thread.
+ //
+ // This must be called only from WorkerThread::GetTaskRunner().
+ scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType) const;
+
+ WorkerThreadScheduler* GetWorkerThreadScheduler() const {
+ return thread_scheduler_;
+ }
+
+ void OnLifecycleStateChanged(SchedulingLifecycleState lifecycle_state);
+
+ SchedulingLifecycleState CalculateLifecycleState(ObserverType) const override;
+
+ protected:
+ scoped_refptr<base::sequence_manager::TaskQueue> ThrottleableTaskQueue();
+ scoped_refptr<base::sequence_manager::TaskQueue> UnthrottleableTaskQueue();
+
+ private:
+ void SetUpThrottling();
+
+ base::WeakPtr<WorkerScheduler> GetWeakPtr();
+
+ scoped_refptr<base::sequence_manager::TaskQueue> throttleable_task_queue_;
+ scoped_refptr<base::sequence_manager::TaskQueue> unthrottleable_task_queue_;
+
+ SchedulingLifecycleState lifecycle_state_ =
+ SchedulingLifecycleState::kNotThrottled;
+
+ WorkerThreadScheduler* thread_scheduler_; // NOT OWNED
+
+#if DCHECK_IS_ON()
+ bool is_disposed_ = false;
+#endif
+
+ base::WeakPtrFactory<WorkerScheduler> weak_factory_;
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_PUBLIC_WORKER_SCHEDULER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/renderer/DEPS b/chromium/third_party/blink/renderer/platform/scheduler/renderer/DEPS
index 37007ef0655..e6bf2b837da 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/renderer/DEPS
+++ b/chromium/third_party/blink/renderer/platform/scheduler/renderer/DEPS
@@ -6,10 +6,3 @@ include_rules = [
"+third_party/blink/renderer/platform/scheduler/base",
"+third_party/blink/renderer/platform/scheduler/child",
]
-
-specific_include_rules = {
- ".*test\.cc": [
- "+cc/test",
- "+components/viz/test",
- ],
-}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/renderer/frame_status.h b/chromium/third_party/blink/renderer/platform/scheduler/renderer/frame_status.h
index 29c98f89891..d1dfdc80741 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/renderer/frame_status.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/renderer/frame_status.h
@@ -13,7 +13,7 @@ class FrameScheduler;
namespace scheduler {
// This enum is used for histogram and should not be renumbered.
-// This enum should be kept in sync with FrameThrottlingState and
+// This enum should be kept in sync with FrameSchedulingLifecycleState and
// FrameOriginState.
//
// There are three main states:
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.cc
index 3b31822773e..09dfa7892e2 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.cc
@@ -5,7 +5,7 @@
#include "third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.h"
#include "base/location.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "base/task/sequence_manager/task_queue.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
namespace blink {
@@ -14,7 +14,6 @@ namespace scheduler {
WebThreadImplForRendererScheduler::WebThreadImplForRendererScheduler(
MainThreadSchedulerImpl* scheduler)
: task_runner_(scheduler->DefaultTaskRunner()),
- idle_task_runner_(scheduler->IdleTaskRunner()),
scheduler_(scheduler),
thread_id_(base::PlatformThread::CurrentId()) {}
@@ -29,11 +28,6 @@ blink::ThreadScheduler* WebThreadImplForRendererScheduler::Scheduler() const {
return scheduler_;
}
-SingleThreadIdleTaskRunner*
-WebThreadImplForRendererScheduler::GetIdleTaskRunner() const {
- return idle_task_runner_.get();
-}
-
scoped_refptr<base::SingleThreadTaskRunner>
WebThreadImplForRendererScheduler::GetTaskRunner() const {
return task_runner_;
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.h
index 478b78f0d18..d1d8f4662c6 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.h
@@ -31,7 +31,6 @@ class PLATFORM_EXPORT WebThreadImplForRendererScheduler : public WebThreadBase {
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() const override;
// WebThreadBase implementation.
- SingleThreadIdleTaskRunner* GetIdleTaskRunner() const override;
void Init() override;
private:
@@ -46,7 +45,6 @@ class PLATFORM_EXPORT WebThreadImplForRendererScheduler : public WebThreadBase {
base::sequence_manager::TaskTimeObserver*) override;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
MainThreadSchedulerImpl* scheduler_; // Not owned.
PlatformThreadId thread_id_;
};
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc
index c8d0f6e04b9..3e4cc6ddb78 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler_unittest.cc
@@ -12,10 +12,10 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
#include "base/test/simple_test_tick_clock.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
namespace blink {
@@ -43,7 +43,7 @@ class WebThreadImplForRendererSchedulerTest : public testing::Test {
void SetUp() override {
clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
scheduler_.reset(new MainThreadSchedulerImpl(
- base::sequence_manager::TaskQueueManagerForTest::Create(
+ base::sequence_manager::SequenceManagerForTest::Create(
&message_loop_, message_loop_.task_runner(), &clock_),
base::nullopt));
default_task_runner_ = scheduler_->DefaultTaskRunner();
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter.cc b/chromium/third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter.cc
deleted file mode 100644
index 37acbae342a..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter.cc
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter.h"
-
-namespace blink {
-namespace scheduler {
-namespace internal {
-
-int TakeFullMilliseconds(base::TimeDelta& duration) {
- int milliseconds = static_cast<int>(duration.InMilliseconds());
- duration = duration % base::TimeDelta::FromMilliseconds(1);
- return milliseconds;
-}
-
-} // namespace internal
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter.h b/chromium/third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter.h
index f01fe8b4888..de4dc8a3738 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter.h
@@ -1,18 +1,13 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors.All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_UTIL_TASK_DURATION_METRIC_REPORTER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_UTIL_TASK_DURATION_METRIC_REPORTER_H_
-#include <array>
-
-#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/metrics/histogram.h"
#include "base/time/time.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/util/aggregated_metric_reporter.h"
namespace base {
class HistogramBase;
@@ -20,33 +15,42 @@ class HistogramBase;
namespace blink {
namespace scheduler {
-namespace internal {
-PLATFORM_EXPORT int TakeFullMilliseconds(base::TimeDelta& duration);
-} // namespace internal
-// A helper class to report task duration split by a specific type.
-// Aggregates small tasks internally and reports only whole milliseconds.
+// A helper class to report total task runtime split by the different types of
+// |TypeClass|. Only full seconds are reported. Note that partial seconds are
+// rounded up/down, so that on average the correct value is reported when many
+// reports are added.
//
-// |TaskClass| is an enum which should have COUNT field.
-// All values reported to RecordTask should have lower values.
+//|TaskClass| is an enum which should have COUNT field.
template <class TaskClass>
-class TaskDurationMetricReporter
- : public AggregatedMetricReporter<TaskClass, base::TimeDelta> {
+class TaskDurationMetricReporter {
public:
+ // Note that 1000*1000 is used to get microseconds precision.
explicit TaskDurationMetricReporter(const char* metric_name)
- : AggregatedMetricReporter<TaskClass, base::TimeDelta>(
+ : value_per_type_histogram_(new base::ScaledLinearHistogram(
metric_name,
- &internal::TakeFullMilliseconds) {}
-
- ~TaskDurationMetricReporter() = default;
+ 1,
+ static_cast<int>(TaskClass::kCount),
+ static_cast<int>(TaskClass::kCount) + 1,
+ 1000 * 1000,
+ base::HistogramBase::kUmaTargetedHistogramFlag)){};
+
+ void RecordTask(TaskClass task_class, base::TimeDelta duration) {
+ DCHECK_LT(static_cast<int>(task_class),
+ static_cast<int>(TaskClass::kCount));
+
+ // To get mircoseconds precision, duration is converted to microseconds
+ // since |value_per_type_histogram_| is constructed with a scale of
+ // 1000*1000.
+ if (!duration.is_zero()) {
+ value_per_type_histogram_->AddScaledCount(
+ static_cast<int>(task_class),
+ base::saturated_cast<int>(duration.InMicroseconds()));
+ }
+ }
private:
- FRIEND_TEST_ALL_PREFIXES(TaskDurationMetricReporterTest, Test);
-
- TaskDurationMetricReporter(base::HistogramBase* histogram)
- : AggregatedMetricReporter<TaskClass, base::TimeDelta>(
- histogram,
- &internal::TakeFullMilliseconds) {}
+ std::unique_ptr<base::ScaledLinearHistogram> value_per_type_histogram_;
DISALLOW_COPY_AND_ASSIGN(TaskDurationMetricReporter);
};
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter_unittest.cc
deleted file mode 100644
index 9b1e8763044..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter_unittest.cc
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter.h"
-
-#include "base/metrics/histogram_base.h"
-#include "base/metrics/histogram_samples.h"
-#include "base/values.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace blink {
-namespace scheduler {
-
-namespace {
-
-using testing::_;
-using testing::Mock;
-
-class FakeHistogram : public base::HistogramBase {
- public:
- FakeHistogram() : base::HistogramBase("fake") {}
- ~FakeHistogram() override = default;
-
- MOCK_METHOD2(AddCount, void(base::HistogramBase::Sample, int));
- MOCK_CONST_METHOD0(name_hash, uint64_t());
- MOCK_CONST_METHOD0(GetHistogramType, base::HistogramType());
- MOCK_CONST_METHOD3(HasConstructionArguments,
- bool(base::HistogramBase::Sample,
- base::HistogramBase::Sample,
- uint32_t));
- MOCK_METHOD1(Add, void(base::HistogramBase::Sample));
- MOCK_METHOD1(AddSamples, void(const base::HistogramSamples&));
- MOCK_CONST_METHOD0(SnapshotSamples,
- std::unique_ptr<base::HistogramSamples>());
- MOCK_METHOD0(SnapshotDelta, std::unique_ptr<base::HistogramSamples>());
- MOCK_CONST_METHOD0(SnapshotFinalDelta,
- std::unique_ptr<base::HistogramSamples>());
- MOCK_METHOD1(AddSamplesFromPickle, bool(base::PickleIterator*));
- MOCK_CONST_METHOD1(WriteHTMLGraph, void(std::string*));
- MOCK_CONST_METHOD1(WriteAscii, void(std::string*));
- MOCK_CONST_METHOD1(SerializeInfoImpl, void(base::Pickle*));
- MOCK_CONST_METHOD1(GetParameters, void(base::DictionaryValue*));
- MOCK_CONST_METHOD3(GetCountAndBucketData,
- void(base::HistogramBase::Count*,
- int64_t*,
- base::ListValue*));
-};
-
-enum class FakeTaskQueueType {
- kFakeType0 = 0,
- kFakeType1 = 1,
- kFakeType2 = 2,
- kCount = 3
-};
-
-} // namespace
-
-TEST(TaskDurationMetricReporterTest, Test) {
- FakeHistogram histogram;
-
- TaskDurationMetricReporter<FakeTaskQueueType> metric_reporter(&histogram);
-
- EXPECT_CALL(histogram, AddCount(2, 3));
- metric_reporter.RecordTask(static_cast<FakeTaskQueueType>(2),
- base::TimeDelta::FromMicroseconds(3400));
- Mock::VerifyAndClearExpectations(&histogram);
-
- EXPECT_CALL(histogram, AddCount(_, _)).Times(0);
- metric_reporter.RecordTask(static_cast<FakeTaskQueueType>(2),
- base::TimeDelta::FromMicroseconds(300));
- Mock::VerifyAndClearExpectations(&histogram);
-
- EXPECT_CALL(histogram, AddCount(2, 1));
- metric_reporter.RecordTask(static_cast<FakeTaskQueueType>(2),
- base::TimeDelta::FromMicroseconds(800));
- Mock::VerifyAndClearExpectations(&histogram);
-
- EXPECT_CALL(histogram, AddCount(2, 16));
- metric_reporter.RecordTask(static_cast<FakeTaskQueueType>(2),
- base::TimeDelta::FromMicroseconds(15600));
- Mock::VerifyAndClearExpectations(&histogram);
-}
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/util/thread_cpu_throttler.cc b/chromium/third_party/blink/renderer/platform/scheduler/util/thread_cpu_throttler.cc
index 2023865282a..a38dd349293 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/util/thread_cpu_throttler.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/util/thread_cpu_throttler.cc
@@ -11,7 +11,7 @@
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
#include <signal.h>
#define USE_SIGNALS 1
#elif defined(OS_WIN)
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/utility/webthread_impl_for_utility_thread.cc b/chromium/third_party/blink/renderer/platform/scheduler/utility/webthread_impl_for_utility_thread.cc
index 9da0528370f..c37f106f886 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/utility/webthread_impl_for_utility_thread.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/utility/webthread_impl_for_utility_thread.cc
@@ -29,12 +29,6 @@ WebThreadImplForUtilityThread::GetTaskRunner() const {
return task_runner_;
}
-scheduler::SingleThreadIdleTaskRunner*
-WebThreadImplForUtilityThread::GetIdleTaskRunner() const {
- NOTIMPLEMENTED();
- return nullptr;
-}
-
void WebThreadImplForUtilityThread::Init() {}
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/utility/webthread_impl_for_utility_thread.h b/chromium/third_party/blink/renderer/platform/scheduler/utility/webthread_impl_for_utility_thread.h
index 2228317522d..e3137f013ba 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/utility/webthread_impl_for_utility_thread.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/utility/webthread_impl_for_utility_thread.h
@@ -26,7 +26,6 @@ class PLATFORM_EXPORT WebThreadImplForUtilityThread
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() const override;
// WebThreadBase implementation.
- scheduler::SingleThreadIdleTaskRunner* GetIdleTaskRunner() const override;
void Init() override;
private:
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/DEPS b/chromium/third_party/blink/renderer/platform/scheduler/worker/DEPS
index 53701134c2e..0674e3c032b 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/DEPS
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/DEPS
@@ -1,5 +1,5 @@
specific_include_rules = {
- ".*test\.cc": [
- "+components/viz/test",
+ "non_main_thread_task_queue.h": [
+ "+base/task/sequence_manager/task_queue_impl.h",
],
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_metrics_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_metrics_helper.cc
new file mode 100644
index 00000000000..3cd0891fe3b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_metrics_helper.cc
@@ -0,0 +1,28 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/worker/compositor_metrics_helper.h"
+
+namespace blink {
+namespace scheduler {
+
+CompositorMetricsHelper::CompositorMetricsHelper(
+ bool has_cpu_timing_for_each_task)
+ : MetricsHelper(WebThreadType::kCompositorThread,
+ has_cpu_timing_for_each_task) {}
+
+CompositorMetricsHelper::~CompositorMetricsHelper() {}
+
+void CompositorMetricsHelper::RecordTaskMetrics(
+ NonMainThreadTaskQueue* queue,
+ const base::sequence_manager::TaskQueue::Task& task,
+ const base::sequence_manager::TaskQueue::TaskTiming& task_timing) {
+ if (ShouldDiscardTask(queue, task, task_timing))
+ return;
+
+ MetricsHelper::RecordCommonTaskMetrics(queue, task, task_timing);
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_metrics_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_metrics_helper.h
new file mode 100644
index 00000000000..1bc4163accc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_metrics_helper.h
@@ -0,0 +1,31 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_COMPOSITOR_METRICS_HELPER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_COMPOSITOR_METRICS_HELPER_H_
+
+#include "third_party/blink/renderer/platform/scheduler/common/metrics_helper.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h"
+
+namespace blink {
+namespace scheduler {
+
+class PLATFORM_EXPORT CompositorMetricsHelper : public MetricsHelper {
+ public:
+ explicit CompositorMetricsHelper(bool has_cpu_timing_for_each_task);
+ ~CompositorMetricsHelper();
+
+ void RecordTaskMetrics(
+ NonMainThreadTaskQueue* queue,
+ const base::sequence_manager::TaskQueue::Task& task,
+ const base::sequence_manager::TaskQueue::TaskTiming& task_timing);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CompositorMetricsHelper);
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_COMPOSITOR_METRICS_HELPER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc
index 2ff477006a3..9063c89ed00 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc
@@ -9,50 +9,72 @@
#include "base/callback.h"
#include "base/message_loop/message_loop.h"
+#include "base/task/sequence_manager/task_queue.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/child/features.h"
#include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
#include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
namespace blink {
namespace scheduler {
+namespace {
+
+CompositorThreadScheduler* g_compositor_thread_scheduler = nullptr;
+
+} // namespace
+
+// static
+WebThreadScheduler* WebThreadScheduler::CompositorThreadScheduler() {
+ return g_compositor_thread_scheduler;
+}
+
CompositorThreadScheduler::CompositorThreadScheduler(
- base::Thread* thread,
- std::unique_ptr<base::sequence_manager::TaskQueueManager>
- task_queue_manager)
- : NonMainThreadScheduler(std::make_unique<NonMainThreadSchedulerHelper>(
- std::move(task_queue_manager),
+ std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager)
+ : NonMainThreadSchedulerImpl(std::make_unique<NonMainThreadSchedulerHelper>(
+ std::move(sequence_manager),
this,
TaskType::kCompositorThreadTaskQueueDefault)),
- thread_(thread),
- default_task_runner_(TaskQueueWithTaskType::Create(
- DefaultTaskQueue(),
- TaskType::kCompositorThreadTaskQueueDefault)) {}
+ input_task_queue_(
+ base::FeatureList::IsEnabled(kHighPriorityInputOnCompositorThread)
+ ? helper()->NewTaskQueue(
+ base::sequence_manager::TaskQueue::Spec("input_tq")
+ .SetShouldMonitorQuiescence(true))
+ : nullptr),
+ input_task_runner_(input_task_queue_
+ ? TaskQueueWithTaskType::Create(
+ input_task_queue_,
+ TaskType::kCompositorThreadTaskQueueInput)
+ : nullptr),
+ compositor_metrics_helper_(helper()->HasCPUTimingForEachTask()) {
+ if (input_task_queue_) {
+ input_task_queue_->SetQueuePriority(
+ base::sequence_manager::TaskQueue::QueuePriority::kHighestPriority);
+ }
+ DCHECK(!g_compositor_thread_scheduler);
+ g_compositor_thread_scheduler = this;
+}
-CompositorThreadScheduler::~CompositorThreadScheduler() = default;
+CompositorThreadScheduler::~CompositorThreadScheduler() {
+ DCHECK_EQ(g_compositor_thread_scheduler, this);
+ g_compositor_thread_scheduler = nullptr;
+}
-scoped_refptr<WorkerTaskQueue> CompositorThreadScheduler::DefaultTaskQueue() {
- return helper_->DefaultWorkerTaskQueue();
+scoped_refptr<NonMainThreadTaskQueue>
+CompositorThreadScheduler::DefaultTaskQueue() {
+ return helper()->DefaultNonMainThreadTaskQueue();
}
void CompositorThreadScheduler::InitImpl() {}
void CompositorThreadScheduler::OnTaskCompleted(
- WorkerTaskQueue* worker_task_queue,
+ NonMainThreadTaskQueue* worker_task_queue,
const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start,
- base::TimeTicks end,
- base::Optional<base::TimeDelta> thread_time) {
- compositor_metrics_helper_.RecordTaskMetrics(worker_task_queue, task, start,
- end, thread_time);
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-CompositorThreadScheduler::DefaultTaskRunner() {
- return default_task_runner_;
+ const base::sequence_manager::TaskQueue::TaskTiming& task_timing) {
+ compositor_metrics_helper_.RecordTaskMetrics(worker_task_queue, task,
+ task_timing);
}
scoped_refptr<scheduler::SingleThreadIdleTaskRunner>
@@ -62,12 +84,26 @@ CompositorThreadScheduler::IdleTaskRunner() {
// which runs them after the current frame has been drawn before the next
// vsync. https://crbug.com/609532
return base::MakeRefCounted<SingleThreadIdleTaskRunner>(
- thread_->task_runner(), this);
+ helper()->DefaultTaskRunner(), this);
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+CompositorThreadScheduler::InputTaskRunner() {
+ if (input_task_runner_)
+ return input_task_runner_;
+ return helper()->DefaultTaskRunner();
}
scoped_refptr<base::SingleThreadTaskRunner>
-CompositorThreadScheduler::IPCTaskRunner() {
- return base::ThreadTaskRunnerHandle::Get();
+CompositorThreadScheduler::V8TaskRunner() {
+ NOTREACHED();
+ return nullptr;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+CompositorThreadScheduler::CompositorTaskRunner() {
+ NOTREACHED();
+ return nullptr;
}
bool CompositorThreadScheduler::CanExceedIdleDeadlineIfRequired() const {
@@ -80,15 +116,17 @@ bool CompositorThreadScheduler::ShouldYieldForHighPriorityWork() {
void CompositorThreadScheduler::AddTaskObserver(
base::MessageLoop::TaskObserver* task_observer) {
- helper_->AddTaskObserver(task_observer);
+ helper()->AddTaskObserver(task_observer);
}
void CompositorThreadScheduler::RemoveTaskObserver(
base::MessageLoop::TaskObserver* task_observer) {
- helper_->RemoveTaskObserver(task_observer);
+ helper()->RemoveTaskObserver(task_observer);
}
-void CompositorThreadScheduler::Shutdown() {}
+void CompositorThreadScheduler::Shutdown() {
+ input_task_queue_->ShutdownTaskQueue();
+}
void CompositorThreadScheduler::OnIdleTaskPosted() {}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h
index 40b0819c71a..08f0dcec537 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h
@@ -11,46 +11,42 @@
#include "third_party/blink/public/platform/scheduler/single_thread_idle_task_runner.h"
#include "third_party/blink/public/platform/web_thread_type.h"
#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/child/compositor_metrics_helper.h"
-#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter.h"
-
-namespace base {
-class Thread;
-}
+#include "third_party/blink/renderer/platform/scheduler/worker/compositor_metrics_helper.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h"
namespace blink {
namespace scheduler {
class PLATFORM_EXPORT CompositorThreadScheduler
- : public NonMainThreadScheduler,
+ : public NonMainThreadSchedulerImpl,
public SingleThreadIdleTaskRunner::Delegate {
public:
- CompositorThreadScheduler(
- base::Thread* thread,
- std::unique_ptr<base::sequence_manager::TaskQueueManager>
- task_queue_manager);
+ explicit CompositorThreadScheduler(
+ std::unique_ptr<base::sequence_manager::SequenceManager>
+ sequence_manager);
~CompositorThreadScheduler() override;
- // NonMainThreadScheduler:
- scoped_refptr<WorkerTaskQueue> DefaultTaskQueue() override;
- void OnTaskCompleted(WorkerTaskQueue* worker_task_queue,
+ // NonMainThreadSchedulerImpl:
+ scoped_refptr<NonMainThreadTaskQueue> DefaultTaskQueue() override;
+ void OnTaskCompleted(NonMainThreadTaskQueue* worker_task_queue,
const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start,
- base::TimeTicks end,
- base::Optional<base::TimeDelta> thread_time) override;
+ const base::sequence_manager::TaskQueue::TaskTiming&
+ task_timing) override;
// WebThreadScheduler:
- scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner() override;
scoped_refptr<scheduler::SingleThreadIdleTaskRunner> IdleTaskRunner()
override;
- scoped_refptr<base::SingleThreadTaskRunner> IPCTaskRunner() override;
+ scoped_refptr<base::SingleThreadTaskRunner> V8TaskRunner() override;
+ scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner() override;
+ scoped_refptr<base::SingleThreadTaskRunner> InputTaskRunner() override;
bool ShouldYieldForHighPriorityWork() override;
bool CanExceedIdleDeadlineIfRequired() const override;
void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer) override;
void RemoveTaskObserver(
base::MessageLoop::TaskObserver* task_observer) override;
+ void AddRAILModeObserver(RAILModeObserver*) override {}
void Shutdown() override;
// SingleThreadIdleTaskRunner::Delegate:
@@ -64,10 +60,10 @@ class PLATFORM_EXPORT CompositorThreadScheduler
void InitImpl() override;
private:
- base::Thread* thread_;
+ scoped_refptr<NonMainThreadTaskQueue> input_task_queue_;
+ scoped_refptr<base::SingleThreadTaskRunner> input_task_runner_;
CompositorMetricsHelper compositor_metrics_helper_;
- scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
DISALLOW_COPY_AND_ASSIGN(CompositorThreadScheduler);
};
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler_unittest.cc
new file mode 100644
index 00000000000..33289e633fb
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler_unittest.cc
@@ -0,0 +1,119 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.h"
+#include <memory>
+#include "base/macros.h"
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "base/test/test_mock_time_task_runner.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/scheduler/child/features.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+
+using testing::ElementsAreArray;
+using testing::ElementsAre;
+
+namespace blink {
+namespace scheduler {
+// To avoid symbol collisions in jumbo builds.
+namespace compositor_thread_scheduler_unittest {
+
+class CompositorThreadSchedulerTest : public testing::Test {
+ public:
+ CompositorThreadSchedulerTest(
+ std::vector<base::Feature> features_to_enable,
+ std::vector<base::Feature> features_to_disable) {
+ feature_list_.InitWithFeatures(features_to_enable, features_to_disable);
+ }
+
+ CompositorThreadSchedulerTest() : CompositorThreadSchedulerTest({}, {}) {}
+
+ ~CompositorThreadSchedulerTest() override = default;
+
+ void SetUp() override {
+ mock_task_runner_ = base::MakeRefCounted<base::TestMockTimeTaskRunner>();
+ mock_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMicroseconds(5000));
+
+ scheduler_ = std::make_unique<CompositorThreadScheduler>(
+ base::sequence_manager::SequenceManagerForTest::Create(
+ nullptr, mock_task_runner_, mock_task_runner_->GetMockTickClock()));
+ scheduler_->Init();
+ }
+
+ void TearDown() override {}
+
+ protected:
+ base::test::ScopedFeatureList feature_list_;
+
+ scoped_refptr<base::TestMockTimeTaskRunner> mock_task_runner_;
+ std::unique_ptr<CompositorThreadScheduler> scheduler_;
+
+ DISALLOW_COPY_AND_ASSIGN(CompositorThreadSchedulerTest);
+};
+
+class CompositorThreadInputPriorityTest : public CompositorThreadSchedulerTest {
+ public:
+ CompositorThreadInputPriorityTest()
+ : CompositorThreadSchedulerTest(
+ {kHighPriorityInputOnCompositorThread} /* features_to_enable */,
+ {} /* features_to_disable */) {}
+ ~CompositorThreadInputPriorityTest() override = default;
+};
+
+namespace {
+
+void RunTestTask(std::string name, std::vector<std::string>* log) {
+ log->push_back(name);
+}
+
+} // namespace
+
+TEST_F(CompositorThreadInputPriorityTest, HighestPriorityInput) {
+ std::vector<std::string> run_order;
+
+ scheduler_->DefaultTaskQueue()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&RunTestTask, "default", base::Unretained(&run_order)));
+ scheduler_->InputTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&RunTestTask, "input", base::Unretained(&run_order)));
+
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, testing::ElementsAre(std::string("input"),
+ std::string("default")));
+}
+
+class CompositorThreadNoInputPriorityTest
+ : public CompositorThreadSchedulerTest {
+ public:
+ CompositorThreadNoInputPriorityTest()
+ : CompositorThreadSchedulerTest(
+ {} /* features_to_enable */,
+ {kHighPriorityInputOnCompositorThread} /* features_to_disable */) {}
+ ~CompositorThreadNoInputPriorityTest() override = default;
+};
+
+TEST_F(CompositorThreadNoInputPriorityTest, InputNotPrioritized) {
+ std::vector<std::string> run_order;
+
+ scheduler_->DefaultTaskQueue()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&RunTestTask, "default", base::Unretained(&run_order)));
+ scheduler_->InputTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&RunTestTask, "input", base::Unretained(&run_order)));
+
+ mock_task_runner_->RunUntilIdle();
+
+ EXPECT_THAT(run_order, testing::ElementsAre(std::string("default"),
+ std::string("input")));
+}
+} // namespace compositor_thread_scheduler_unittest
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler.cc
deleted file mode 100644
index 627184f05e9..00000000000
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler.cc
+++ /dev/null
@@ -1,141 +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/platform/scheduler/public/non_main_thread_scheduler.h"
-
-#include <utility>
-
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
-#include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
-#include "third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h"
-#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
-
-namespace blink {
-namespace scheduler {
-
-NonMainThreadScheduler::NonMainThreadScheduler(
- std::unique_ptr<NonMainThreadSchedulerHelper> helper)
- : helper_(std::move(helper)) {}
-
-NonMainThreadScheduler::~NonMainThreadScheduler() {
- DCHECK(worker_schedulers_.empty());
-}
-
-// static
-std::unique_ptr<NonMainThreadScheduler> NonMainThreadScheduler::Create(
- WebThreadType thread_type,
- WorkerSchedulerProxy* proxy) {
- return std::make_unique<WorkerThreadScheduler>(
- thread_type,
- base::sequence_manager::TaskQueueManager::TakeOverCurrentThread(), proxy);
-}
-
-// static
-NonMainThreadScheduler* NonMainThreadScheduler::Current() {
- DCHECK_NE(Platform::Current()->CurrentThread(),
- Platform::Current()->MainThread());
- return ThreadScheduler::Current()->AsNonMainThreadScheduler();
-}
-
-void NonMainThreadScheduler::Init() {
- InitImpl();
-
- // DefaultTaskQueue() is a virtual function, so it can't be called in the
- // constructor. Also, DefaultTaskQueue() checks if InitImpl() is called.
- // Therefore, v8_task_runner_ needs to be initialized here.
- v8_task_runner_ = TaskQueueWithTaskType::Create(
- DefaultTaskQueue(), TaskType::kMainThreadTaskQueueV8);
-}
-
-scoped_refptr<WorkerTaskQueue> NonMainThreadScheduler::CreateTaskRunner() {
- helper_->CheckOnValidThread();
- return helper_->NewTaskQueue(
- base::sequence_manager::TaskQueue::Spec("worker_tq")
- .SetShouldMonitorQuiescence(true)
- .SetTimeDomain(nullptr));
-}
-
-void NonMainThreadScheduler::RunIdleTask(blink::WebThread::IdleTask task,
- base::TimeTicks deadline) {
- std::move(task).Run((deadline - base::TimeTicks()).InSecondsF());
-}
-
-void NonMainThreadScheduler::PostIdleTask(const base::Location& location,
- blink::WebThread::IdleTask task) {
- IdleTaskRunner()->PostIdleTask(
- location,
- base::BindOnce(&NonMainThreadScheduler::RunIdleTask, std::move(task)));
-}
-
-void NonMainThreadScheduler::PostNonNestableIdleTask(
- const base::Location& location,
- blink::WebThread::IdleTask task) {
- IdleTaskRunner()->PostNonNestableIdleTask(
- location,
- base::BindOnce(&NonMainThreadScheduler::RunIdleTask, std::move(task)));
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-NonMainThreadScheduler::V8TaskRunner() {
- return v8_task_runner_;
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-NonMainThreadScheduler::CompositorTaskRunner() {
- return nullptr;
-}
-
-std::unique_ptr<blink::PageScheduler>
-NonMainThreadScheduler::CreatePageScheduler(PageScheduler::Delegate* delegate) {
- NOTREACHED();
- return nullptr;
-}
-
-std::unique_ptr<NonMainThreadScheduler::RendererPauseHandle>
-NonMainThreadScheduler::PauseScheduler() {
- return nullptr;
-}
-
-base::TimeTicks NonMainThreadScheduler::MonotonicallyIncreasingVirtualTime() {
- return base::TimeTicks::Now();
-}
-
-void NonMainThreadScheduler::RegisterWorkerScheduler(
- WorkerScheduler* worker_scheduler) {
- worker_schedulers_.insert(worker_scheduler);
-}
-
-void NonMainThreadScheduler::UnregisterWorkerScheduler(
- WorkerScheduler* worker_scheduler) {
- DCHECK(worker_schedulers_.find(worker_scheduler) != worker_schedulers_.end());
- worker_schedulers_.erase(worker_scheduler);
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-NonMainThreadScheduler::ControlTaskRunner() {
- return helper_->ControlWorkerTaskQueue();
-}
-
-void NonMainThreadScheduler::RegisterTimeDomain(
- base::sequence_manager::TimeDomain* time_domain) {
- return helper_->RegisterTimeDomain(time_domain);
-}
-
-void NonMainThreadScheduler::UnregisterTimeDomain(
- base::sequence_manager::TimeDomain* time_domain) {
- return helper_->UnregisterTimeDomain(time_domain);
-}
-
-base::sequence_manager::TimeDomain*
-NonMainThreadScheduler::GetActiveTimeDomain() {
- return helper_->real_time_domain();
-}
-
-const base::TickClock* NonMainThreadScheduler::GetTickClock() {
- return helper_->GetClock();
-}
-
-} // namespace scheduler
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.cc
index dd674be044b..a63fae8f06e 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.cc
@@ -6,7 +6,7 @@
#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
-#include "third_party/blink/renderer/platform/scheduler/child/worker_task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h"
namespace blink {
namespace scheduler {
@@ -14,15 +14,14 @@ namespace scheduler {
using base::sequence_manager::TaskQueue;
NonMainThreadSchedulerHelper::NonMainThreadSchedulerHelper(
- std::unique_ptr<base::sequence_manager::TaskQueueManager>
- task_queue_manager,
- NonMainThreadScheduler* non_main_thread_scheduler,
+ std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager,
+ NonMainThreadSchedulerImpl* non_main_thread_scheduler,
TaskType default_task_type)
- : SchedulerHelper(std::move(task_queue_manager)),
+ : SchedulerHelper(std::move(sequence_manager)),
non_main_thread_scheduler_(non_main_thread_scheduler),
- default_task_queue_(NewTaskQueue(TaskQueue::Spec("worker_default_tq")
+ default_task_queue_(NewTaskQueue(TaskQueue::Spec("subthread_default_tq")
.SetShouldMonitorQuiescence(true))),
- control_task_queue_(NewTaskQueue(TaskQueue::Spec("worker_control_tq")
+ control_task_queue_(NewTaskQueue(TaskQueue::Spec("subthread_control_tq")
.SetShouldNotifyObservers(false))) {
InitDefaultQueues(default_task_queue_, control_task_queue_,
default_task_type);
@@ -33,8 +32,8 @@ NonMainThreadSchedulerHelper::~NonMainThreadSchedulerHelper() {
default_task_queue_->ShutdownTaskQueue();
}
-scoped_refptr<WorkerTaskQueue>
-NonMainThreadSchedulerHelper::DefaultWorkerTaskQueue() {
+scoped_refptr<NonMainThreadTaskQueue>
+NonMainThreadSchedulerHelper::DefaultNonMainThreadTaskQueue() {
return default_task_queue_;
}
@@ -42,8 +41,8 @@ scoped_refptr<TaskQueue> NonMainThreadSchedulerHelper::DefaultTaskQueue() {
return default_task_queue_;
}
-scoped_refptr<WorkerTaskQueue>
-NonMainThreadSchedulerHelper::ControlWorkerTaskQueue() {
+scoped_refptr<NonMainThreadTaskQueue>
+NonMainThreadSchedulerHelper::ControlNonMainThreadTaskQueue() {
return control_task_queue_;
}
@@ -51,9 +50,9 @@ scoped_refptr<TaskQueue> NonMainThreadSchedulerHelper::ControlTaskQueue() {
return control_task_queue_;
}
-scoped_refptr<WorkerTaskQueue> NonMainThreadSchedulerHelper::NewTaskQueue(
- const TaskQueue::Spec& spec) {
- return task_queue_manager_->CreateTaskQueue<WorkerTaskQueue>(
+scoped_refptr<NonMainThreadTaskQueue>
+NonMainThreadSchedulerHelper::NewTaskQueue(const TaskQueue::Spec& spec) {
+ return sequence_manager_->CreateTaskQueue<NonMainThreadTaskQueue>(
spec, non_main_thread_scheduler_);
}
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h
index 8613de252ae..621a3bf5dbc 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h
@@ -8,35 +8,35 @@
#include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
#include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/platform/scheduler/child/worker_task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h"
namespace blink {
namespace scheduler {
-class NonMainThreadScheduler;
+class NonMainThreadSchedulerImpl;
class PLATFORM_EXPORT NonMainThreadSchedulerHelper : public SchedulerHelper {
public:
NonMainThreadSchedulerHelper(
- std::unique_ptr<base::sequence_manager::TaskQueueManager> manager,
- NonMainThreadScheduler* non_main_thread_scheduler,
+ std::unique_ptr<base::sequence_manager::SequenceManager> manager,
+ NonMainThreadSchedulerImpl* non_main_thread_scheduler,
TaskType default_task_type);
~NonMainThreadSchedulerHelper() override;
- scoped_refptr<WorkerTaskQueue> NewTaskQueue(
+ scoped_refptr<NonMainThreadTaskQueue> NewTaskQueue(
const base::sequence_manager::TaskQueue::Spec& spec);
- scoped_refptr<WorkerTaskQueue> DefaultWorkerTaskQueue();
- scoped_refptr<WorkerTaskQueue> ControlWorkerTaskQueue();
+ scoped_refptr<NonMainThreadTaskQueue> DefaultNonMainThreadTaskQueue();
+ scoped_refptr<NonMainThreadTaskQueue> ControlNonMainThreadTaskQueue();
protected:
scoped_refptr<base::sequence_manager::TaskQueue> DefaultTaskQueue() override;
scoped_refptr<base::sequence_manager::TaskQueue> ControlTaskQueue() override;
private:
- NonMainThreadScheduler* non_main_thread_scheduler_; // NOT OWNED
- const scoped_refptr<WorkerTaskQueue> default_task_queue_;
- const scoped_refptr<WorkerTaskQueue> control_task_queue_;
+ NonMainThreadSchedulerImpl* non_main_thread_scheduler_; // NOT OWNED
+ const scoped_refptr<NonMainThreadTaskQueue> default_task_queue_;
+ const scoped_refptr<NonMainThreadTaskQueue> control_task_queue_;
DISALLOW_COPY_AND_ASSIGN(NonMainThreadSchedulerHelper);
};
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.cc
new file mode 100644
index 00000000000..ccfd7cbc73d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.cc
@@ -0,0 +1,105 @@
+// 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/platform/scheduler/worker/non_main_thread_scheduler_impl.h"
+
+#include <utility>
+
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
+
+namespace blink {
+namespace scheduler {
+
+NonMainThreadSchedulerImpl::NonMainThreadSchedulerImpl(
+ std::unique_ptr<NonMainThreadSchedulerHelper> helper)
+ : helper_(std::move(helper)) {}
+
+NonMainThreadSchedulerImpl::~NonMainThreadSchedulerImpl() = default;
+
+// static
+std::unique_ptr<NonMainThreadSchedulerImpl> NonMainThreadSchedulerImpl::Create(
+ WebThreadType thread_type,
+ WorkerSchedulerProxy* proxy) {
+ return std::make_unique<WorkerThreadScheduler>(
+ thread_type,
+ base::sequence_manager::CreateSequenceManagerOnCurrentThread(), proxy);
+}
+
+void NonMainThreadSchedulerImpl::Init() {
+ InitImpl();
+}
+
+scoped_refptr<NonMainThreadTaskQueue>
+NonMainThreadSchedulerImpl::CreateTaskRunner(const char* name) {
+ helper_->CheckOnValidThread();
+ return helper_->NewTaskQueue(base::sequence_manager::TaskQueue::Spec(name)
+ .SetShouldMonitorQuiescence(true)
+ .SetTimeDomain(nullptr));
+}
+
+void NonMainThreadSchedulerImpl::RunIdleTask(blink::WebThread::IdleTask task,
+ base::TimeTicks deadline) {
+ std::move(task).Run(deadline);
+}
+
+void NonMainThreadSchedulerImpl::PostIdleTask(const base::Location& location,
+ blink::WebThread::IdleTask task) {
+ IdleTaskRunner()->PostIdleTask(
+ location, base::BindOnce(&NonMainThreadSchedulerImpl::RunIdleTask,
+ std::move(task)));
+}
+
+void NonMainThreadSchedulerImpl::PostNonNestableIdleTask(
+ const base::Location& location,
+ blink::WebThread::IdleTask task) {
+ IdleTaskRunner()->PostNonNestableIdleTask(
+ location, base::BindOnce(&NonMainThreadSchedulerImpl::RunIdleTask,
+ std::move(task)));
+}
+
+std::unique_ptr<blink::PageScheduler>
+NonMainThreadSchedulerImpl::CreatePageScheduler(
+ PageScheduler::Delegate* delegate) {
+ NOTREACHED();
+ return nullptr;
+}
+
+std::unique_ptr<NonMainThreadSchedulerImpl::RendererPauseHandle>
+NonMainThreadSchedulerImpl::PauseScheduler() {
+ return nullptr;
+}
+
+base::TimeTicks
+NonMainThreadSchedulerImpl::MonotonicallyIncreasingVirtualTime() {
+ return base::TimeTicks::Now();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+NonMainThreadSchedulerImpl::ControlTaskRunner() {
+ return helper_->ControlNonMainThreadTaskQueue();
+}
+
+void NonMainThreadSchedulerImpl::RegisterTimeDomain(
+ base::sequence_manager::TimeDomain* time_domain) {
+ return helper_->RegisterTimeDomain(time_domain);
+}
+
+void NonMainThreadSchedulerImpl::UnregisterTimeDomain(
+ base::sequence_manager::TimeDomain* time_domain) {
+ return helper_->UnregisterTimeDomain(time_domain);
+}
+
+base::sequence_manager::TimeDomain*
+NonMainThreadSchedulerImpl::GetActiveTimeDomain() {
+ return helper_->real_time_domain();
+}
+
+const base::TickClock* NonMainThreadSchedulerImpl::GetTickClock() {
+ return helper_->GetClock();
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h
new file mode 100644
index 00000000000..f6b0dc6e1cc
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h
@@ -0,0 +1,110 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_SCHEDULER_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_SCHEDULER_IMPL_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/task/sequence_manager/task_queue.h"
+#include "third_party/blink/public/platform/scheduler/single_thread_idle_task_runner.h"
+#include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
+#include "third_party/blink/public/platform/web_thread_type.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/util/tracing_helper.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h"
+
+namespace blink {
+namespace scheduler {
+
+class WorkerSchedulerProxy;
+
+class PLATFORM_EXPORT NonMainThreadSchedulerImpl : public ThreadSchedulerImpl {
+ public:
+ ~NonMainThreadSchedulerImpl() override;
+
+ static std::unique_ptr<NonMainThreadSchedulerImpl> Create(
+ WebThreadType thread_type,
+ WorkerSchedulerProxy* proxy);
+
+ // Blink should use NonMainThreadSchedulerImpl::DefaultTaskQueue instead of
+ // WebThreadScheduler::DefaultTaskRunner.
+ virtual scoped_refptr<NonMainThreadTaskQueue> DefaultTaskQueue() = 0;
+
+ // Must be called before the scheduler can be used. Does any post construction
+ // initialization needed such as initializing idle period detection.
+ void Init();
+
+ virtual void OnTaskCompleted(
+ NonMainThreadTaskQueue* worker_task_queue,
+ const base::sequence_manager::TaskQueue::Task& task,
+ const base::sequence_manager::TaskQueue::TaskTiming& task_timing) = 0;
+
+ // ThreadSchedulerImpl:
+ scoped_refptr<base::SingleThreadTaskRunner> ControlTaskRunner() override;
+ void RegisterTimeDomain(
+ base::sequence_manager::TimeDomain* time_domain) override;
+ void UnregisterTimeDomain(
+ base::sequence_manager::TimeDomain* time_domain) override;
+ base::sequence_manager::TimeDomain* GetActiveTimeDomain() override;
+ const base::TickClock* GetTickClock() override;
+
+ // ThreadScheduler implementation.
+ // TODO(yutak): Some functions are only meaningful in main thread. Move them
+ // to MainThreadScheduler.
+ void PostIdleTask(const base::Location& location,
+ WebThread::IdleTask task) override;
+ void PostNonNestableIdleTask(const base::Location& location,
+ WebThread::IdleTask task) override;
+ std::unique_ptr<PageScheduler> CreatePageScheduler(
+ PageScheduler::Delegate*) override;
+ std::unique_ptr<RendererPauseHandle> PauseScheduler() override
+ WARN_UNUSED_RESULT;
+
+ // Returns TimeTicks::Now() by default.
+ base::TimeTicks MonotonicallyIncreasingVirtualTime() override;
+
+ NonMainThreadSchedulerImpl* AsNonMainThreadScheduler() override {
+ return this;
+ }
+
+ // The following virtual methods are defined in *both* WebThreadScheduler
+ // and ThreadScheduler, with identical interfaces and semantics. They are
+ // overriden in a subclass, effectively implementing the virtual methods
+ // in both classes at the same time. This is allowed in C++, as long as
+ // there is only one final overrider (i.e. definitions in base classes are
+ // not used in instantiated objects, since otherwise they may have multiple
+ // definitions of the virtual function in question).
+ //
+ // virtual void Shutdown();
+
+ scoped_refptr<NonMainThreadTaskQueue> CreateTaskRunner(const char* name);
+
+ protected:
+ static void RunIdleTask(WebThread::IdleTask task, base::TimeTicks deadline);
+
+ explicit NonMainThreadSchedulerImpl(
+ std::unique_ptr<NonMainThreadSchedulerHelper> helper);
+
+ friend class WorkerScheduler;
+
+ // Called during Init() for delayed initialization for subclasses.
+ virtual void InitImpl() = 0;
+
+ NonMainThreadSchedulerHelper* helper() { return helper_.get(); }
+
+ private:
+ std::unique_ptr<NonMainThreadSchedulerHelper> helper_;
+
+ DISALLOW_COPY_AND_ASSIGN(NonMainThreadSchedulerImpl);
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_SCHEDULER_IMPL_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.cc
new file mode 100644
index 00000000000..b3fce8d4bee
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.cc
@@ -0,0 +1,39 @@
+// 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/platform/scheduler/worker/non_main_thread_task_queue.h"
+
+#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h"
+
+namespace blink {
+namespace scheduler {
+
+using base::sequence_manager::TaskQueue;
+
+NonMainThreadTaskQueue::NonMainThreadTaskQueue(
+ std::unique_ptr<base::sequence_manager::internal::TaskQueueImpl> impl,
+ const TaskQueue::Spec& spec,
+ NonMainThreadSchedulerImpl* non_main_thread_scheduler)
+ : TaskQueue(std::move(impl), spec),
+ non_main_thread_scheduler_(non_main_thread_scheduler) {
+ if (GetTaskQueueImpl()) {
+ // TaskQueueImpl may be null for tests.
+ GetTaskQueueImpl()->SetOnTaskCompletedHandler(base::BindRepeating(
+ &NonMainThreadTaskQueue::OnTaskCompleted, base::Unretained(this)));
+ }
+}
+
+NonMainThreadTaskQueue::~NonMainThreadTaskQueue() = default;
+
+void NonMainThreadTaskQueue::OnTaskCompleted(
+ const TaskQueue::Task& task,
+ const TaskQueue::TaskTiming& task_timing) {
+ // |non_main_thread_scheduler_| can be nullptr in tests.
+ if (non_main_thread_scheduler_) {
+ non_main_thread_scheduler_->OnTaskCompleted(this, task, task_timing);
+ }
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h
new file mode 100644
index 00000000000..ac48631136f
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h
@@ -0,0 +1,38 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_TASK_QUEUE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_TASK_QUEUE_H_
+
+#include "base/task/sequence_manager/task_queue_impl.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+namespace blink {
+namespace scheduler {
+
+class NonMainThreadSchedulerImpl;
+
+class PLATFORM_EXPORT NonMainThreadTaskQueue
+ : public base::sequence_manager::TaskQueue {
+ public:
+ // TODO(kraynov): Consider options to remove TaskQueueImpl reference here.
+ NonMainThreadTaskQueue(
+ std::unique_ptr<base::sequence_manager::internal::TaskQueueImpl> impl,
+ const Spec& spec,
+ NonMainThreadSchedulerImpl* non_main_thread_scheduler);
+ ~NonMainThreadTaskQueue() override;
+
+ void OnTaskCompleted(
+ const base::sequence_manager::TaskQueue::Task& task,
+ const base::sequence_manager::TaskQueue::TaskTiming& task_timing);
+
+ private:
+ // Not owned.
+ NonMainThreadSchedulerImpl* non_main_thread_scheduler_;
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_TASK_QUEUE_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_metrics_helper.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_metrics_helper.cc
new file mode 100644
index 00000000000..daa7522cf49
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_metrics_helper.cc
@@ -0,0 +1,65 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/worker/worker_metrics_helper.h"
+
+#include "third_party/blink/renderer/platform/scheduler/child/process_state.h"
+
+namespace blink {
+namespace scheduler {
+
+WorkerMetricsHelper::WorkerMetricsHelper(WebThreadType thread_type,
+ bool has_cpu_timing_for_each_task)
+ : MetricsHelper(thread_type, has_cpu_timing_for_each_task),
+ dedicated_worker_per_task_type_duration_reporter_(
+ "RendererScheduler.TaskDurationPerTaskType2.DedicatedWorker"),
+ dedicated_worker_per_task_type_cpu_duration_reporter_(
+ "RendererScheduler.TaskCPUDurationPerTaskType2.DedicatedWorker"),
+ dedicated_worker_per_parent_frame_status_duration_reporter_(
+ "RendererScheduler.TaskDurationPerFrameOriginType2.DedicatedWorker"),
+ background_dedicated_worker_per_parent_frame_status_duration_reporter_(
+ "RendererScheduler.TaskDurationPerFrameOriginType2.DedicatedWorker."
+ "Background") {}
+
+WorkerMetricsHelper::~WorkerMetricsHelper() {}
+
+void WorkerMetricsHelper::SetParentFrameType(FrameOriginType frame_type) {
+ parent_frame_type_ = frame_type;
+}
+
+void WorkerMetricsHelper::RecordTaskMetrics(
+ NonMainThreadTaskQueue* queue,
+ const base::sequence_manager::TaskQueue::Task& task,
+ const base::sequence_manager::TaskQueue::TaskTiming& task_timing) {
+ if (ShouldDiscardTask(queue, task, task_timing))
+ return;
+
+ MetricsHelper::RecordCommonTaskMetrics(queue, task, task_timing);
+
+ bool backgrounded = internal::ProcessState::Get()->is_process_backgrounded;
+
+ if (thread_type_ == WebThreadType::kDedicatedWorkerThread) {
+ TaskType task_type = static_cast<TaskType>(task.task_type());
+ dedicated_worker_per_task_type_duration_reporter_.RecordTask(
+ task_type, task_timing.wall_duration());
+ if (task_timing.has_thread_time()) {
+ dedicated_worker_per_task_type_cpu_duration_reporter_.RecordTask(
+ task_type, task_timing.thread_duration());
+ }
+
+ if (parent_frame_type_) {
+ dedicated_worker_per_parent_frame_status_duration_reporter_.RecordTask(
+ parent_frame_type_.value(), task_timing.wall_duration());
+
+ if (backgrounded) {
+ background_dedicated_worker_per_parent_frame_status_duration_reporter_
+ .RecordTask(parent_frame_type_.value(),
+ task_timing.wall_duration());
+ }
+ }
+ }
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_metrics_helper.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_metrics_helper.h
new file mode 100644
index 00000000000..b4dd2cadaa1
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_metrics_helper.h
@@ -0,0 +1,48 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_METRICS_HELPER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_METRICS_HELPER_H_
+
+#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/platform/scheduler/common/metrics_helper.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h"
+#include "third_party/blink/renderer/platform/scheduler/util/thread_load_tracker.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h"
+
+namespace blink {
+namespace scheduler {
+
+class PLATFORM_EXPORT WorkerMetricsHelper : public MetricsHelper {
+ public:
+ explicit WorkerMetricsHelper(WebThreadType thread_type,
+ bool has_cpu_timing_for_each_task);
+ ~WorkerMetricsHelper();
+
+ void RecordTaskMetrics(
+ NonMainThreadTaskQueue* queue,
+ const base::sequence_manager::TaskQueue::Task& task,
+ const base::sequence_manager::TaskQueue::TaskTiming& task_timing);
+
+ void SetParentFrameType(FrameOriginType frame_type);
+
+ private:
+ TaskDurationMetricReporter<TaskType>
+ dedicated_worker_per_task_type_duration_reporter_;
+ TaskDurationMetricReporter<TaskType>
+ dedicated_worker_per_task_type_cpu_duration_reporter_;
+ TaskDurationMetricReporter<FrameOriginType>
+ dedicated_worker_per_parent_frame_status_duration_reporter_;
+ TaskDurationMetricReporter<FrameOriginType>
+ background_dedicated_worker_per_parent_frame_status_duration_reporter_;
+
+ base::Optional<FrameOriginType> parent_frame_type_;
+
+ DISALLOW_COPY_AND_ASSIGN(WorkerMetricsHelper);
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_METRICS_HELPER_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc
new file mode 100644
index 00000000000..61bb507f5d2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc
@@ -0,0 +1,185 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h"
+
+#include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
+#include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
+#include "third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
+
+namespace blink {
+namespace scheduler {
+
+WorkerScheduler::WorkerScheduler(WorkerThreadScheduler* worker_thread_scheduler,
+ WorkerSchedulerProxy* proxy)
+ : throttleable_task_queue_(
+ worker_thread_scheduler->CreateTaskRunner("worker_throttleable_tq")),
+ unthrottleable_task_queue_(worker_thread_scheduler->CreateTaskRunner(
+ "worker_unthrottleable_tq")),
+ thread_scheduler_(worker_thread_scheduler),
+ weak_factory_(this) {
+ thread_scheduler_->RegisterWorkerScheduler(this);
+
+ SetUpThrottling();
+
+ // |proxy| can be nullptr in unit tests.
+ if (proxy)
+ proxy->OnWorkerSchedulerCreated(GetWeakPtr());
+}
+
+base::WeakPtr<WorkerScheduler> WorkerScheduler::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
+WorkerScheduler::~WorkerScheduler() {
+#if DCHECK_IS_ON()
+ DCHECK(is_disposed_);
+#endif
+}
+
+void WorkerScheduler::SetUpThrottling() {
+ if (!thread_scheduler_->task_queue_throttler())
+ return;
+ base::TimeTicks now = thread_scheduler_->GetTickClock()->NowTicks();
+
+ WakeUpBudgetPool* wake_up_budget_pool =
+ thread_scheduler_->wake_up_budget_pool();
+ CPUTimeBudgetPool* cpu_time_budget_pool =
+ thread_scheduler_->cpu_time_budget_pool();
+
+ DCHECK(wake_up_budget_pool || cpu_time_budget_pool)
+ << "At least one budget pool should be present";
+
+ if (wake_up_budget_pool) {
+ wake_up_budget_pool->AddQueue(now, throttleable_task_queue_.get());
+ }
+ if (cpu_time_budget_pool) {
+ cpu_time_budget_pool->AddQueue(now, throttleable_task_queue_.get());
+ }
+}
+
+std::unique_ptr<FrameOrWorkerScheduler::ActiveConnectionHandle>
+WorkerScheduler::OnActiveConnectionCreated() {
+ return nullptr;
+}
+
+SchedulingLifecycleState WorkerScheduler::CalculateLifecycleState(
+ ObserverType) const {
+ return thread_scheduler_->lifecycle_state();
+}
+
+void WorkerScheduler::Dispose() {
+ if (TaskQueueThrottler* throttler =
+ thread_scheduler_->task_queue_throttler()) {
+ throttler->ShutdownTaskQueue(throttleable_task_queue_.get());
+ }
+
+ thread_scheduler_->UnregisterWorkerScheduler(this);
+
+ unthrottleable_task_queue_->ShutdownTaskQueue();
+ throttleable_task_queue_->ShutdownTaskQueue();
+
+#if DCHECK_IS_ON()
+ is_disposed_ = true;
+#endif
+}
+
+scoped_refptr<base::SingleThreadTaskRunner> WorkerScheduler::GetTaskRunner(
+ TaskType type) const {
+ switch (type) {
+ case TaskType::kJavascriptTimer:
+ case TaskType::kPostedMessage:
+ case TaskType::kWorkerAnimation:
+ return TaskQueueWithTaskType::Create(throttleable_task_queue_, type);
+ case TaskType::kDeprecatedNone:
+ case TaskType::kDOMManipulation:
+ case TaskType::kUserInteraction:
+ case TaskType::kNetworking:
+ case TaskType::kNetworkingWithURLLoaderAnnotation:
+ case TaskType::kNetworkingControl:
+ case TaskType::kHistoryTraversal:
+ case TaskType::kEmbed:
+ case TaskType::kMediaElementEvent:
+ case TaskType::kCanvasBlobSerialization:
+ case TaskType::kMicrotask:
+ case TaskType::kRemoteEvent:
+ case TaskType::kWebSocket:
+ case TaskType::kUnshippedPortMessage:
+ case TaskType::kFileReading:
+ case TaskType::kDatabaseAccess:
+ case TaskType::kPresentation:
+ case TaskType::kSensor:
+ case TaskType::kPerformanceTimeline:
+ case TaskType::kWebGL:
+ case TaskType::kIdleTask:
+ case TaskType::kMiscPlatformAPI:
+ case TaskType::kInternalDefault:
+ case TaskType::kInternalLoading:
+ case TaskType::kInternalTest:
+ case TaskType::kInternalWebCrypto:
+ case TaskType::kInternalIndexedDB:
+ case TaskType::kInternalMedia:
+ case TaskType::kInternalMediaRealTime:
+ case TaskType::kInternalIPC:
+ case TaskType::kInternalUserInteraction:
+ case TaskType::kInternalInspector:
+ case TaskType::kInternalWorker:
+ case TaskType::kInternalIntersectionObserver:
+ // UnthrottledTaskRunner is generally discouraged in future.
+ // TODO(nhiroki): Identify which tasks can be throttled / suspendable and
+ // move them into other task runners. See also comments in
+ // Get(LocalFrame). (https://crbug.com/670534)
+ return TaskQueueWithTaskType::Create(unthrottleable_task_queue_, type);
+ case TaskType::kMainThreadTaskQueueV8:
+ case TaskType::kMainThreadTaskQueueCompositor:
+ case TaskType::kMainThreadTaskQueueDefault:
+ case TaskType::kMainThreadTaskQueueInput:
+ case TaskType::kMainThreadTaskQueueIdle:
+ case TaskType::kMainThreadTaskQueueIPC:
+ case TaskType::kMainThreadTaskQueueControl:
+ case TaskType::kCompositorThreadTaskQueueDefault:
+ case TaskType::kCompositorThreadTaskQueueInput:
+ case TaskType::kWorkerThreadTaskQueueDefault:
+ case TaskType::kWorkerThreadTaskQueueV8:
+ case TaskType::kWorkerThreadTaskQueueCompositor:
+ case TaskType::kCount:
+ NOTREACHED();
+ break;
+ }
+ NOTREACHED();
+ return nullptr;
+}
+
+void WorkerScheduler::OnLifecycleStateChanged(
+ SchedulingLifecycleState lifecycle_state) {
+ if (lifecycle_state_ == lifecycle_state)
+ return;
+ lifecycle_state_ = lifecycle_state;
+ thread_scheduler_->OnLifecycleStateChanged(lifecycle_state);
+
+ if (TaskQueueThrottler* throttler =
+ thread_scheduler_->task_queue_throttler()) {
+ if (lifecycle_state_ == SchedulingLifecycleState::kThrottled) {
+ throttler->IncreaseThrottleRefCount(throttleable_task_queue_.get());
+ } else {
+ throttler->DecreaseThrottleRefCount(throttleable_task_queue_.get());
+ }
+ }
+ NotifyLifecycleObservers();
+}
+
+scoped_refptr<base::sequence_manager::TaskQueue>
+WorkerScheduler::UnthrottleableTaskQueue() {
+ return unthrottleable_task_queue_.get();
+}
+
+scoped_refptr<base::sequence_manager::TaskQueue>
+WorkerScheduler::ThrottleableTaskQueue() {
+ return throttleable_task_queue_.get();
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.cc
new file mode 100644
index 00000000000..67d6279836d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.cc
@@ -0,0 +1,55 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h"
+
+#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
+
+namespace blink {
+namespace scheduler {
+
+WorkerSchedulerProxy::WorkerSchedulerProxy(FrameOrWorkerScheduler* scheduler) {
+ DCHECK(scheduler);
+ throttling_observer_handle_ = scheduler->AddLifecycleObserver(
+ FrameOrWorkerScheduler::ObserverType::kWorkerScheduler, this);
+ if (FrameScheduler* frame_scheduler = scheduler->ToFrameScheduler()) {
+ parent_frame_type_ = GetFrameOriginType(frame_scheduler);
+ }
+}
+
+WorkerSchedulerProxy::~WorkerSchedulerProxy() {
+ DETACH_FROM_THREAD(parent_thread_checker_);
+}
+
+void WorkerSchedulerProxy::OnWorkerSchedulerCreated(
+ base::WeakPtr<WorkerScheduler> worker_scheduler) {
+ DCHECK(!IsMainThread())
+ << "OnWorkerSchedulerCreated should be called from the worker thread";
+ DCHECK(!worker_scheduler_) << "OnWorkerSchedulerCreated is called twice";
+ DCHECK(worker_scheduler) << "WorkerScheduler is expected to exist";
+ worker_scheduler_ = std::move(worker_scheduler);
+ worker_thread_task_runner_ =
+ worker_scheduler_->GetWorkerThreadScheduler()->ControlTaskQueue();
+ initialized_ = true;
+}
+
+void WorkerSchedulerProxy::OnLifecycleStateChanged(
+ SchedulingLifecycleState lifecycle_state) {
+ DCHECK_CALLED_ON_VALID_THREAD(parent_thread_checker_);
+ if (lifecycle_state_ == lifecycle_state)
+ return;
+ lifecycle_state_ = lifecycle_state;
+
+ if (!initialized_)
+ return;
+
+ worker_thread_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&WorkerScheduler::OnLifecycleStateChanged,
+ worker_scheduler_, lifecycle_state));
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h
new file mode 100644
index 00000000000..e01b24f5a15
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h
@@ -0,0 +1,80 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_SCHEDULER_PROXY_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_SCHEDULER_PROXY_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_checker.h"
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h"
+#include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
+
+namespace blink {
+namespace scheduler {
+class WorkerScheduler;
+
+// Helper class for communication between parent scheduler (may be a frame
+// scheduler on the main thread or another woker scheduler on a worker thread)
+// and worker scheduler (worker thread).
+//
+// It's owned by DedicatedWorkerThread and is created and destroyed
+// on the parent thread. It's passed to WorkerScheduler during its
+// construction. Given that DedicatedWorkerThread object outlives worker thread,
+// this class outlives worker thread too.
+class PLATFORM_EXPORT WorkerSchedulerProxy
+ : public FrameOrWorkerScheduler::Observer {
+ public:
+ explicit WorkerSchedulerProxy(FrameOrWorkerScheduler* scheduler);
+ ~WorkerSchedulerProxy() override;
+
+ void OnWorkerSchedulerCreated(
+ base::WeakPtr<WorkerScheduler> worker_scheduler);
+
+ void OnLifecycleStateChanged(
+ SchedulingLifecycleState lifecycle_state) override;
+
+ // Accessed only during init.
+ SchedulingLifecycleState lifecycle_state() const {
+ DCHECK(!initialized_);
+ return lifecycle_state_;
+ }
+
+ // Accessed only during init.
+ base::Optional<FrameOriginType> parent_frame_type() const {
+ DCHECK(!initialized_);
+ return parent_frame_type_;
+ }
+
+ private:
+ // Can be accessed only from the worker thread.
+ base::WeakPtr<WorkerScheduler> worker_scheduler_;
+
+ // Const after init on the worker thread.
+ scoped_refptr<base::SingleThreadTaskRunner> worker_thread_task_runner_;
+
+ SchedulingLifecycleState lifecycle_state_ =
+ SchedulingLifecycleState::kNotThrottled;
+
+ std::unique_ptr<FrameOrWorkerScheduler::LifecycleObserverHandle>
+ throttling_observer_handle_;
+
+ bool initialized_ = false;
+
+ base::Optional<FrameOriginType> parent_frame_type_;
+
+ THREAD_CHECKER(parent_thread_checker_);
+
+ DISALLOW_COPY_AND_ASSIGN(WorkerSchedulerProxy);
+};
+
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_SCHEDULER_PROXY_H_
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy_unittest.cc
new file mode 100644
index 00000000000..6d8438a9776
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy_unittest.cc
@@ -0,0 +1,221 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h"
+#include "base/run_loop.h"
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/test/scoped_task_environment.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
+#include "third_party/blink/renderer/platform/waitable_event.h"
+
+namespace blink {
+namespace scheduler {
+
+namespace {
+
+class WorkerThreadSchedulerForTest : public WorkerThreadScheduler {
+ public:
+ WorkerThreadSchedulerForTest(
+ std::unique_ptr<base::sequence_manager::SequenceManager> manager,
+ WorkerSchedulerProxy* proxy,
+ WaitableEvent* throtting_state_changed)
+ : WorkerThreadScheduler(WebThreadType::kTestThread,
+ std::move(manager),
+ proxy),
+ throtting_state_changed_(throtting_state_changed) {}
+
+ void OnLifecycleStateChanged(
+ SchedulingLifecycleState lifecycle_state) override {
+ WorkerThreadScheduler::OnLifecycleStateChanged(lifecycle_state);
+
+ throtting_state_changed_->Signal();
+ }
+
+ using WorkerThreadScheduler::lifecycle_state;
+
+ private:
+ WaitableEvent* throtting_state_changed_;
+};
+
+class WebThreadImplForWorkerSchedulerForTest
+ : public WebThreadImplForWorkerScheduler {
+ public:
+ WebThreadImplForWorkerSchedulerForTest(FrameScheduler* frame_scheduler,
+ WaitableEvent* throtting_state_changed)
+ : WebThreadImplForWorkerScheduler(
+ WebThreadCreationParams(WebThreadType::kTestThread)
+ .SetFrameOrWorkerScheduler(frame_scheduler)),
+ throtting_state_changed_(throtting_state_changed) {}
+
+ ~WebThreadImplForWorkerSchedulerForTest() override {
+ base::WaitableEvent completion(
+ base::WaitableEvent::ResetPolicy::AUTOMATIC,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ thread_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(&WebThreadImplForWorkerSchedulerForTest::
+ DisposeWorkerSchedulerOnThread,
+ base::Unretained(this), &completion));
+ completion.Wait();
+ }
+
+ void DisposeWorkerSchedulerOnThread(base::WaitableEvent* completion) {
+ DCHECK(thread_task_runner_->BelongsToCurrentThread());
+ if (worker_scheduler_) {
+ worker_scheduler_->Dispose();
+ worker_scheduler_ = nullptr;
+ }
+ completion->Signal();
+ }
+
+ std::unique_ptr<NonMainThreadSchedulerImpl> CreateNonMainThreadScheduler()
+ override {
+ auto scheduler = std::make_unique<WorkerThreadSchedulerForTest>(
+ base::sequence_manager::CreateSequenceManagerOnCurrentThread(),
+ worker_scheduler_proxy(), throtting_state_changed_);
+ scheduler_ = scheduler.get();
+ worker_scheduler_ = std::make_unique<scheduler::WorkerScheduler>(
+ scheduler_, worker_scheduler_proxy());
+ return scheduler;
+ }
+
+ WorkerThreadSchedulerForTest* GetWorkerScheduler() { return scheduler_; }
+
+ private:
+ WaitableEvent* throtting_state_changed_; // NOT OWNED
+ WorkerThreadSchedulerForTest* scheduler_ = nullptr; // NOT OWNED
+ std::unique_ptr<WorkerScheduler> worker_scheduler_ = nullptr;
+};
+
+std::unique_ptr<WebThreadImplForWorkerSchedulerForTest> CreateWorkerThread(
+ FrameScheduler* frame_scheduler,
+ WaitableEvent* throtting_state_changed) {
+ std::unique_ptr<WebThreadImplForWorkerSchedulerForTest> thread =
+ std::make_unique<WebThreadImplForWorkerSchedulerForTest>(
+ frame_scheduler, throtting_state_changed);
+ thread->Init();
+ return thread;
+}
+
+} // namespace
+
+class WorkerSchedulerProxyTest : public testing::Test {
+ public:
+ WorkerSchedulerProxyTest()
+ : task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+ base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED),
+ main_thread_scheduler_(std::make_unique<MainThreadSchedulerImpl>(
+ base::sequence_manager::SequenceManagerForTest::Create(
+ nullptr,
+ task_environment_.GetMainThreadTaskRunner(),
+ task_environment_.GetMockTickClock()),
+ base::nullopt)),
+ page_scheduler_(
+ std::make_unique<PageSchedulerImpl>(nullptr,
+ main_thread_scheduler_.get())),
+ frame_scheduler_(
+ FrameSchedulerImpl::Create(page_scheduler_.get(),
+ nullptr,
+ FrameScheduler::FrameType::kMainFrame)) {
+ // Null clock triggers some assertions.
+ task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(5));
+ }
+
+ ~WorkerSchedulerProxyTest() override {
+ frame_scheduler_.reset();
+ page_scheduler_.reset();
+ main_thread_scheduler_->Shutdown();
+ }
+
+ protected:
+ base::test::ScopedTaskEnvironment task_environment_;
+ std::unique_ptr<MainThreadSchedulerImpl> main_thread_scheduler_;
+ std::unique_ptr<PageSchedulerImpl> page_scheduler_;
+ std::unique_ptr<FrameSchedulerImpl> frame_scheduler_;
+};
+
+TEST_F(WorkerSchedulerProxyTest, VisibilitySignalReceived) {
+ WaitableEvent throtting_state_changed;
+
+ auto worker_thread =
+ CreateWorkerThread(frame_scheduler_.get(), &throtting_state_changed);
+
+ DCHECK(worker_thread->GetWorkerScheduler()->lifecycle_state() ==
+ SchedulingLifecycleState::kNotThrottled);
+
+ page_scheduler_->SetPageVisible(false);
+ throtting_state_changed.Wait();
+ DCHECK(worker_thread->GetWorkerScheduler()->lifecycle_state() ==
+ SchedulingLifecycleState::kHidden);
+
+ // Trigger full throttling.
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(30));
+ throtting_state_changed.Wait();
+ DCHECK(worker_thread->GetWorkerScheduler()->lifecycle_state() ==
+ SchedulingLifecycleState::kThrottled);
+
+ page_scheduler_->SetPageVisible(true);
+ throtting_state_changed.Wait();
+ DCHECK(worker_thread->GetWorkerScheduler()->lifecycle_state() ==
+ SchedulingLifecycleState::kNotThrottled);
+
+ base::RunLoop().RunUntilIdle();
+}
+
+// Tests below check that no crashes occur during different shutdown sequences.
+
+TEST_F(WorkerSchedulerProxyTest, FrameSchedulerDestroyed) {
+ WaitableEvent throtting_state_changed;
+
+ auto worker_thread =
+ CreateWorkerThread(frame_scheduler_.get(), &throtting_state_changed);
+
+ DCHECK(worker_thread->GetWorkerScheduler()->lifecycle_state() ==
+ SchedulingLifecycleState::kNotThrottled);
+
+ page_scheduler_->SetPageVisible(false);
+ throtting_state_changed.Wait();
+ DCHECK(worker_thread->GetWorkerScheduler()->lifecycle_state() ==
+ SchedulingLifecycleState::kHidden);
+
+ frame_scheduler_.reset();
+ base::RunLoop().RunUntilIdle();
+
+ worker_thread.reset();
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(WorkerSchedulerProxyTest, ThreadDestroyed) {
+ WaitableEvent throtting_state_changed;
+
+ auto worker_thread =
+ CreateWorkerThread(frame_scheduler_.get(), &throtting_state_changed);
+
+ DCHECK(worker_thread->GetWorkerScheduler()->lifecycle_state() ==
+ SchedulingLifecycleState::kNotThrottled);
+
+ page_scheduler_->SetPageVisible(false);
+ throtting_state_changed.Wait();
+ DCHECK(worker_thread->GetWorkerScheduler()->lifecycle_state() ==
+ SchedulingLifecycleState::kHidden);
+
+ worker_thread.reset();
+ base::RunLoop().RunUntilIdle();
+
+ page_scheduler_->SetPageVisible(true);
+ base::RunLoop().RunUntilIdle();
+
+ frame_scheduler_.reset();
+ base::RunLoop().RunUntilIdle();
+}
+
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc
new file mode 100644
index 00000000000..bab1624d5ff
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc
@@ -0,0 +1,273 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h"
+
+#include <memory>
+#include "base/macros.h"
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "base/test/test_mock_time_task_runner.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+
+using testing::ElementsAreArray;
+using testing::ElementsAre;
+
+namespace blink {
+namespace scheduler {
+// To avoid symbol collisions in jumbo builds.
+namespace worker_scheduler_unittest {
+
+void AppendToVectorTestTask(std::vector<std::string>* vector,
+ std::string value) {
+ vector->push_back(value);
+}
+
+void RunChainedTask(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ int count,
+ base::TimeDelta duration,
+ scoped_refptr<base::TestMockTimeTaskRunner> environment,
+ std::vector<base::TimeTicks>* tasks) {
+ tasks->push_back(environment->GetMockTickClock()->NowTicks());
+
+ environment->AdvanceMockTickClock(duration);
+
+ if (count == 1)
+ return;
+
+ // Add a delay of 50ms to ensure that wake-up based throttling does not affect
+ // us.
+ task_runner->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&RunChainedTask, task_runner, count - 1, duration,
+ environment, base::Unretained(tasks)),
+ base::TimeDelta::FromMilliseconds(50));
+}
+
+class WorkerThreadSchedulerForTest : public WorkerThreadScheduler {
+ public:
+ WorkerThreadSchedulerForTest(
+ WebThreadType thread_type,
+ std::unique_ptr<base::sequence_manager::SequenceManager> manager,
+ WorkerSchedulerProxy* proxy)
+ : WorkerThreadScheduler(thread_type, std::move(manager), proxy) {}
+
+ const std::unordered_set<WorkerScheduler*>& worker_schedulers() {
+ return GetWorkerSchedulersForTesting();
+ }
+
+ using WorkerThreadScheduler::CreateTaskQueueThrottler;
+ using WorkerThreadScheduler::SetCPUTimeBudgetPoolForTesting;
+};
+
+class WorkerSchedulerForTest : public WorkerScheduler {
+ public:
+ explicit WorkerSchedulerForTest(
+ WorkerThreadSchedulerForTest* thread_scheduler)
+ : WorkerScheduler(thread_scheduler, nullptr) {}
+
+ using WorkerScheduler::UnthrottleableTaskQueue;
+ using WorkerScheduler::ThrottleableTaskQueue;
+};
+
+class WorkerSchedulerTest : public testing::Test {
+ public:
+ WorkerSchedulerTest()
+ : mock_task_runner_(new base::TestMockTimeTaskRunner()),
+ scheduler_(new WorkerThreadSchedulerForTest(
+ WebThreadType::kTestThread,
+ base::sequence_manager::SequenceManagerForTest::Create(
+ nullptr,
+ mock_task_runner_,
+ mock_task_runner_->GetMockTickClock()),
+ nullptr /* proxy */)) {
+ mock_task_runner_->AdvanceMockTickClock(
+ base::TimeDelta::FromMicroseconds(5000));
+ }
+
+ ~WorkerSchedulerTest() override = default;
+
+ void SetUp() override {
+ scheduler_->Init();
+ worker_scheduler_ =
+ std::make_unique<WorkerSchedulerForTest>(scheduler_.get());
+ }
+
+ void TearDown() override {
+ if (worker_scheduler_) {
+ worker_scheduler_->Dispose();
+ worker_scheduler_.reset();
+ }
+ }
+
+ const base::TickClock* GetClock() {
+ return mock_task_runner_->GetMockTickClock();
+ }
+
+ void RunUntilIdle() { mock_task_runner_->FastForwardUntilNoTasksRemain(); }
+
+ // Helper for posting a task.
+ void PostTestTask(std::vector<std::string>* run_order,
+ const std::string& task_descriptor) {
+ worker_scheduler_->GetTaskRunner(TaskType::kInternalTest)
+ ->PostTask(FROM_HERE,
+ WTF::Bind(&AppendToVectorTestTask,
+ WTF::Unretained(run_order), task_descriptor));
+ }
+
+ protected:
+ scoped_refptr<base::TestMockTimeTaskRunner> mock_task_runner_;
+
+ std::unique_ptr<WorkerThreadSchedulerForTest> scheduler_;
+ std::unique_ptr<WorkerSchedulerForTest> worker_scheduler_;
+
+ DISALLOW_COPY_AND_ASSIGN(WorkerSchedulerTest);
+};
+
+TEST_F(WorkerSchedulerTest, TestPostTasks) {
+ std::vector<std::string> run_order;
+ PostTestTask(&run_order, "T1");
+ PostTestTask(&run_order, "T2");
+ RunUntilIdle();
+ PostTestTask(&run_order, "T3");
+ RunUntilIdle();
+ EXPECT_THAT(run_order, testing::ElementsAre("T1", "T2", "T3"));
+
+ // Tasks should not run after the scheduler is disposed of.
+ worker_scheduler_->Dispose();
+ run_order.clear();
+ PostTestTask(&run_order, "T4");
+ PostTestTask(&run_order, "T5");
+ RunUntilIdle();
+ EXPECT_TRUE(run_order.empty());
+
+ worker_scheduler_.reset();
+}
+
+TEST_F(WorkerSchedulerTest, RegisterWorkerSchedulers) {
+ EXPECT_THAT(scheduler_->worker_schedulers(),
+ testing::ElementsAre(worker_scheduler_.get()));
+
+ std::unique_ptr<WorkerSchedulerForTest> worker_scheduler2 =
+ std::make_unique<WorkerSchedulerForTest>(scheduler_.get());
+
+ EXPECT_THAT(scheduler_->worker_schedulers(),
+ testing::UnorderedElementsAre(worker_scheduler_.get(),
+ worker_scheduler2.get()));
+
+ worker_scheduler_->Dispose();
+ worker_scheduler_.reset();
+
+ EXPECT_THAT(scheduler_->worker_schedulers(),
+ testing::ElementsAre(worker_scheduler2.get()));
+
+ worker_scheduler2->Dispose();
+
+ EXPECT_THAT(scheduler_->worker_schedulers(), testing::ElementsAre());
+}
+
+TEST_F(WorkerSchedulerTest, ThrottleWorkerScheduler) {
+ scheduler_->CreateTaskQueueThrottler();
+
+ EXPECT_FALSE(scheduler_->task_queue_throttler()->IsThrottled(
+ worker_scheduler_->ThrottleableTaskQueue().get()));
+
+ scheduler_->OnLifecycleStateChanged(SchedulingLifecycleState::kThrottled);
+ EXPECT_TRUE(scheduler_->task_queue_throttler()->IsThrottled(
+ worker_scheduler_->ThrottleableTaskQueue().get()));
+
+ scheduler_->OnLifecycleStateChanged(SchedulingLifecycleState::kThrottled);
+ EXPECT_TRUE(scheduler_->task_queue_throttler()->IsThrottled(
+ worker_scheduler_->ThrottleableTaskQueue().get()));
+
+ // Ensure that two calls with kThrottled do not mess with throttling
+ // refcount.
+ scheduler_->OnLifecycleStateChanged(SchedulingLifecycleState::kNotThrottled);
+ EXPECT_FALSE(scheduler_->task_queue_throttler()->IsThrottled(
+ worker_scheduler_->ThrottleableTaskQueue().get()));
+}
+
+TEST_F(WorkerSchedulerTest, ThrottleWorkerScheduler_CreateThrottled) {
+ scheduler_->CreateTaskQueueThrottler();
+
+ scheduler_->OnLifecycleStateChanged(SchedulingLifecycleState::kThrottled);
+
+ std::unique_ptr<WorkerSchedulerForTest> worker_scheduler2 =
+ std::make_unique<WorkerSchedulerForTest>(scheduler_.get());
+
+ // Ensure that newly created scheduler is throttled.
+ EXPECT_TRUE(scheduler_->task_queue_throttler()->IsThrottled(
+ worker_scheduler2->ThrottleableTaskQueue().get()));
+
+ worker_scheduler2->Dispose();
+}
+
+TEST_F(WorkerSchedulerTest, ThrottleWorkerScheduler_RunThrottledTasks) {
+ scheduler_->CreateTaskQueueThrottler();
+ scheduler_->SetCPUTimeBudgetPoolForTesting(nullptr);
+
+ // Create a new |worker_scheduler| to ensure that it's properly initialised.
+ worker_scheduler_->Dispose();
+ worker_scheduler_ =
+ std::make_unique<WorkerSchedulerForTest>(scheduler_.get());
+
+ scheduler_->OnLifecycleStateChanged(SchedulingLifecycleState::kThrottled);
+
+ std::vector<base::TimeTicks> tasks;
+
+ worker_scheduler_->ThrottleableTaskQueue()->PostTask(
+ FROM_HERE, base::BindOnce(&RunChainedTask,
+ worker_scheduler_->ThrottleableTaskQueue(), 5,
+ base::TimeDelta(), mock_task_runner_,
+ base::Unretained(&tasks)));
+
+ RunUntilIdle();
+
+ EXPECT_THAT(tasks,
+ ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1),
+ base::TimeTicks() + base::TimeDelta::FromSeconds(2),
+ base::TimeTicks() + base::TimeDelta::FromSeconds(3),
+ base::TimeTicks() + base::TimeDelta::FromSeconds(4),
+ base::TimeTicks() + base::TimeDelta::FromSeconds(5)));
+}
+
+TEST_F(WorkerSchedulerTest,
+ ThrottleWorkerScheduler_RunThrottledTasks_CPUBudget) {
+ scheduler_->CreateTaskQueueThrottler();
+
+ scheduler_->cpu_time_budget_pool()->SetTimeBudgetRecoveryRate(
+ GetClock()->NowTicks(), 0.01);
+
+ // Create a new |worker_scheduler| to ensure that it's properly initialised.
+ worker_scheduler_->Dispose();
+ worker_scheduler_ =
+ std::make_unique<WorkerSchedulerForTest>(scheduler_.get());
+
+ scheduler_->OnLifecycleStateChanged(SchedulingLifecycleState::kThrottled);
+
+ std::vector<base::TimeTicks> tasks;
+
+ worker_scheduler_->ThrottleableTaskQueue()->PostTask(
+ FROM_HERE, base::BindOnce(&RunChainedTask,
+ worker_scheduler_->ThrottleableTaskQueue(), 5,
+ base::TimeDelta::FromMilliseconds(100),
+ mock_task_runner_, base::Unretained(&tasks)));
+
+ RunUntilIdle();
+
+ EXPECT_THAT(
+ tasks, ElementsAre(base::TimeTicks() + base::TimeDelta::FromSeconds(1),
+ base::TimeTicks() + base::TimeDelta::FromSeconds(11),
+ base::TimeTicks() + base::TimeDelta::FromSeconds(21),
+ base::TimeTicks() + base::TimeDelta::FromSeconds(31),
+ base::TimeTicks() + base::TimeDelta::FromSeconds(41)));
+}
+
+} // namespace worker_scheduler_unittest
+} // namespace scheduler
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc
index 65d1854cd35..cfbe0417331 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc
@@ -7,20 +7,22 @@
#include <memory>
#include "base/bind.h"
+#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/task/sequence_manager/sequence_manager.h"
+#include "base/task/sequence_manager/task_queue.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_argument.h"
#include "third_party/blink/renderer/platform/histogram.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h"
-#include "third_party/blink/renderer/platform/scheduler/child/default_params.h"
#include "third_party/blink/renderer/platform/scheduler/child/features.h"
#include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
-#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler.h"
-#include "third_party/blink/renderer/platform/scheduler/child/worker_scheduler_proxy.h"
#include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
+#include "third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
namespace blink {
namespace scheduler {
@@ -33,6 +35,17 @@ namespace {
constexpr base::TimeDelta kUnspecifiedWorkerThreadLoadTrackerReportingInterval =
base::TimeDelta::FromSeconds(1);
+// Worker throttling trial
+const char kWorkerThrottlingTrial[] = "BlinkSchedulerDedicatedWorkerThrottling";
+const char kWorkerThrottlingMaxBudgetParam[] = "max_budget_ms";
+const char kWorkerThrottlingRecoveryRateParam[] = "recovery_rate";
+const char kWorkerThrottlingMaxDelayParam[] = "max_delay_ms";
+
+constexpr base::TimeDelta kDefaultMaxBudget = base::TimeDelta::FromSeconds(1);
+constexpr double kDefaultRecoveryRate = 0.01;
+constexpr base::TimeDelta kDefaultMaxThrottlingDelay =
+ base::TimeDelta::FromSeconds(60);
+
void ReportWorkerTaskLoad(base::TimeTicks time, double load) {
int load_percentage = static_cast<int>(load * 100);
DCHECK_LE(load_percentage, 100);
@@ -41,50 +54,72 @@ void ReportWorkerTaskLoad(base::TimeTicks time, double load) {
UMA_HISTOGRAM_PERCENTAGE("WorkerScheduler.WorkerThreadLoad", load_percentage);
}
-// TODO(scheduler-dev): Remove conversions when Blink starts using
-// base::TimeTicks instead of doubles for time.
-base::TimeTicks MonotonicTimeInSecondsToTimeTicks(
- double monotonic_time_in_seconds) {
- return base::TimeTicks() +
- base::TimeDelta::FromSecondsD(monotonic_time_in_seconds);
+base::Optional<base::TimeDelta> GetMaxBudgetLevel() {
+ int max_budget_level_ms;
+ if (!base::StringToInt(
+ base::GetFieldTrialParamValue(kWorkerThrottlingTrial,
+ kWorkerThrottlingMaxBudgetParam),
+ &max_budget_level_ms)) {
+ return kDefaultMaxBudget;
+ }
+ if (max_budget_level_ms < 0)
+ return base::nullopt;
+ return base::TimeDelta::FromMilliseconds(max_budget_level_ms);
+}
+
+double GetBudgetRecoveryRate() {
+ double recovery_rate;
+ if (!base::StringToDouble(
+ base::GetFieldTrialParamValue(kWorkerThrottlingTrial,
+ kWorkerThrottlingRecoveryRateParam),
+ &recovery_rate)) {
+ return kDefaultRecoveryRate;
+ }
+ return recovery_rate;
+}
+
+base::Optional<base::TimeDelta> GetMaxThrottlingDelay() {
+ int max_throttling_delay_ms;
+ if (!base::StringToInt(
+ base::GetFieldTrialParamValue(kWorkerThrottlingTrial,
+ kWorkerThrottlingMaxDelayParam),
+ &max_throttling_delay_ms)) {
+ return kDefaultMaxThrottlingDelay;
+ }
+ if (max_throttling_delay_ms < 0)
+ return base::nullopt;
+ return base::TimeDelta::FromMilliseconds(max_throttling_delay_ms);
}
} // namespace
WorkerThreadScheduler::WorkerThreadScheduler(
WebThreadType thread_type,
- std::unique_ptr<base::sequence_manager::TaskQueueManager>
- task_queue_manager,
+ std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager,
WorkerSchedulerProxy* proxy)
- : NonMainThreadScheduler(std::make_unique<NonMainThreadSchedulerHelper>(
- std::move(task_queue_manager),
+ : NonMainThreadSchedulerImpl(std::make_unique<NonMainThreadSchedulerHelper>(
+ std::move(sequence_manager),
this,
TaskType::kWorkerThreadTaskQueueDefault)),
- idle_helper_(helper_.get(),
+ idle_helper_(helper(),
this,
"WorkerSchedulerIdlePeriod",
base::TimeDelta::FromMilliseconds(300),
- helper_->NewTaskQueue(TaskQueue::Spec("worker_idle_tq"))),
- idle_canceled_delayed_task_sweeper_(helper_.get(),
+ helper()->NewTaskQueue(TaskQueue::Spec("worker_idle_tq"))),
+ idle_canceled_delayed_task_sweeper_(helper(),
idle_helper_.IdleTaskRunner()),
- load_tracker_(helper_->NowTicks(),
+ load_tracker_(helper()->NowTicks(),
base::BindRepeating(&ReportWorkerTaskLoad),
kUnspecifiedWorkerThreadLoadTrackerReportingInterval),
- throttling_state_(proxy ? proxy->throttling_state()
- : FrameScheduler::ThrottlingState::kNotThrottled),
- worker_metrics_helper_(thread_type),
- default_task_runner_(TaskQueueWithTaskType::Create(
- helper_->DefaultWorkerTaskQueue(),
- TaskType::kWorkerThreadTaskQueueDefault)),
- weak_factory_(this) {
- thread_start_time_ = helper_->NowTicks();
+ lifecycle_state_(proxy ? proxy->lifecycle_state()
+ : SchedulingLifecycleState::kNotThrottled),
+ worker_metrics_helper_(thread_type, helper()->HasCPUTimingForEachTask()) {
+ thread_start_time_ = helper()->NowTicks();
load_tracker_.Resume(thread_start_time_);
- helper_->AddTaskTimeObserver(this);
+ helper()->AddTaskTimeObserver(this);
- if (proxy) {
- worker_metrics_helper_.SetParentFrameType(proxy->parent_frame_type());
- proxy->OnWorkerSchedulerCreated(GetWeakPtr());
- }
+ if (proxy && proxy->parent_frame_type())
+ worker_metrics_helper_.SetParentFrameType(*proxy->parent_frame_type());
if (thread_type == WebThreadType::kDedicatedWorkerThread &&
base::FeatureList::IsEnabled(kDedicatedWorkerThrottling)) {
@@ -99,12 +134,9 @@ WorkerThreadScheduler::~WorkerThreadScheduler() {
TRACE_EVENT_OBJECT_DELETED_WITH_ID(
TRACE_DISABLED_BY_DEFAULT("worker.scheduler"), "WorkerScheduler", this);
- helper_->RemoveTaskTimeObserver(this);
-}
+ helper()->RemoveTaskTimeObserver(this);
-scoped_refptr<base::SingleThreadTaskRunner>
-WorkerThreadScheduler::DefaultTaskRunner() {
- return default_task_runner_;
+ DCHECK(worker_schedulers_.empty());
}
scoped_refptr<SingleThreadIdleTaskRunner>
@@ -114,8 +146,15 @@ WorkerThreadScheduler::IdleTaskRunner() {
}
scoped_refptr<base::SingleThreadTaskRunner>
-WorkerThreadScheduler::IPCTaskRunner() {
- return base::ThreadTaskRunnerHandle::Get();
+WorkerThreadScheduler::V8TaskRunner() {
+ DCHECK(initialized_);
+ return v8_task_runner_;
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+WorkerThreadScheduler::CompositorTaskRunner() {
+ DCHECK(initialized_);
+ return compositor_task_runner_;
}
bool WorkerThreadScheduler::CanExceedIdleDeadlineIfRequired() const {
@@ -131,19 +170,19 @@ bool WorkerThreadScheduler::ShouldYieldForHighPriorityWork() {
void WorkerThreadScheduler::AddTaskObserver(
base::MessageLoop::TaskObserver* task_observer) {
DCHECK(initialized_);
- helper_->AddTaskObserver(task_observer);
+ helper()->AddTaskObserver(task_observer);
}
void WorkerThreadScheduler::RemoveTaskObserver(
base::MessageLoop::TaskObserver* task_observer) {
DCHECK(initialized_);
- helper_->RemoveTaskObserver(task_observer);
+ helper()->RemoveTaskObserver(task_observer);
}
void WorkerThreadScheduler::Shutdown() {
DCHECK(initialized_);
- load_tracker_.RecordIdle(helper_->NowTicks());
- base::TimeTicks end_time = helper_->NowTicks();
+ load_tracker_.RecordIdle(helper()->NowTicks());
+ base::TimeTicks end_time = helper()->NowTicks();
base::TimeDelta delta = end_time - thread_start_time_;
// The lifetime could be radically different for different workers,
@@ -153,31 +192,40 @@ void WorkerThreadScheduler::Shutdown() {
"WorkerThread.Runtime", delta, base::TimeDelta::FromSeconds(1),
base::TimeDelta::FromDays(1), 50 /* bucket count */);
task_queue_throttler_.reset();
- helper_->Shutdown();
+ helper()->Shutdown();
}
-scoped_refptr<WorkerTaskQueue> WorkerThreadScheduler::DefaultTaskQueue() {
+scoped_refptr<NonMainThreadTaskQueue>
+WorkerThreadScheduler::DefaultTaskQueue() {
DCHECK(initialized_);
- return helper_->DefaultWorkerTaskQueue();
+ return helper()->DefaultNonMainThreadTaskQueue();
}
void WorkerThreadScheduler::InitImpl() {
initialized_ = true;
idle_helper_.EnableLongIdlePeriod();
+
+ v8_task_runner_ = TaskQueueWithTaskType::Create(
+ DefaultTaskQueue(), TaskType::kWorkerThreadTaskQueueV8);
+ compositor_task_runner_ = TaskQueueWithTaskType::Create(
+ DefaultTaskQueue(), TaskType::kWorkerThreadTaskQueueCompositor);
}
void WorkerThreadScheduler::OnTaskCompleted(
- WorkerTaskQueue* worker_task_queue,
+ NonMainThreadTaskQueue* worker_task_queue,
const TaskQueue::Task& task,
- base::TimeTicks start,
- base::TimeTicks end,
- base::Optional<base::TimeDelta> thread_time) {
- worker_metrics_helper_.RecordTaskMetrics(worker_task_queue, task, start, end,
- thread_time);
+ const TaskQueue::TaskTiming& task_timing) {
+ worker_metrics_helper_.RecordTaskMetrics(worker_task_queue, task,
+ task_timing);
+
+ if (task_queue_throttler_) {
+ task_queue_throttler_->OnTaskRunTimeReported(
+ worker_task_queue, task_timing.start_time(), task_timing.end_time());
+ }
}
SchedulerHelper* WorkerThreadScheduler::GetSchedulerHelperForTesting() {
- return helper_.get();
+ return helper();
}
bool WorkerThreadScheduler::CanEnterLongIdlePeriod(base::TimeTicks,
@@ -190,38 +238,38 @@ base::TimeTicks WorkerThreadScheduler::CurrentIdleTaskDeadlineForTesting()
return idle_helper_.CurrentIdleTaskDeadline();
}
-void WorkerThreadScheduler::WillProcessTask(double start_time) {}
-
-void WorkerThreadScheduler::DidProcessTask(double start_time, double end_time) {
- base::TimeTicks start_time_ticks =
- MonotonicTimeInSecondsToTimeTicks(start_time);
- base::TimeTicks end_time_ticks = MonotonicTimeInSecondsToTimeTicks(end_time);
+void WorkerThreadScheduler::WillProcessTask(base::TimeTicks start_time) {}
- load_tracker_.RecordTaskTime(start_time_ticks, end_time_ticks);
+void WorkerThreadScheduler::DidProcessTask(base::TimeTicks start_time,
+ base::TimeTicks end_time) {
+ load_tracker_.RecordTaskTime(start_time, end_time);
}
-void WorkerThreadScheduler::OnThrottlingStateChanged(
- FrameScheduler::ThrottlingState throttling_state) {
- if (throttling_state_ == throttling_state)
+void WorkerThreadScheduler::OnLifecycleStateChanged(
+ SchedulingLifecycleState lifecycle_state) {
+ if (lifecycle_state_ == lifecycle_state)
return;
- throttling_state_ = throttling_state;
+ lifecycle_state_ = lifecycle_state;
for (WorkerScheduler* worker_scheduler : worker_schedulers_)
- worker_scheduler->OnThrottlingStateChanged(throttling_state);
+ worker_scheduler->OnLifecycleStateChanged(lifecycle_state);
}
void WorkerThreadScheduler::RegisterWorkerScheduler(
WorkerScheduler* worker_scheduler) {
- NonMainThreadScheduler::RegisterWorkerScheduler(worker_scheduler);
- worker_scheduler->OnThrottlingStateChanged(throttling_state_);
+ worker_schedulers_.insert(worker_scheduler);
+ worker_scheduler->OnLifecycleStateChanged(lifecycle_state_);
}
-scoped_refptr<WorkerTaskQueue> WorkerThreadScheduler::ControlTaskQueue() {
- return helper_->ControlWorkerTaskQueue();
+void WorkerThreadScheduler::UnregisterWorkerScheduler(
+ WorkerScheduler* worker_scheduler) {
+ DCHECK(worker_schedulers_.find(worker_scheduler) != worker_schedulers_.end());
+ worker_schedulers_.erase(worker_scheduler);
}
-base::WeakPtr<WorkerThreadScheduler> WorkerThreadScheduler::GetWeakPtr() {
- return weak_factory_.GetWeakPtr();
+scoped_refptr<NonMainThreadTaskQueue>
+WorkerThreadScheduler::ControlTaskQueue() {
+ return helper()->ControlNonMainThreadTaskQueue();
}
void WorkerThreadScheduler::CreateTaskQueueThrottler() {
@@ -231,6 +279,24 @@ void WorkerThreadScheduler::CreateTaskQueueThrottler() {
this, &traceable_variable_controller_);
wake_up_budget_pool_ =
task_queue_throttler_->CreateWakeUpBudgetPool("worker_wake_up_pool");
+ cpu_time_budget_pool_ =
+ task_queue_throttler_->CreateCPUTimeBudgetPool("worker_cpu_time_pool");
+
+ base::TimeTicks now = GetTickClock()->NowTicks();
+ cpu_time_budget_pool_->SetMaxBudgetLevel(now, GetMaxBudgetLevel());
+ cpu_time_budget_pool_->SetTimeBudgetRecoveryRate(now,
+ GetBudgetRecoveryRate());
+ cpu_time_budget_pool_->SetMaxThrottlingDelay(now, GetMaxThrottlingDelay());
+}
+
+void WorkerThreadScheduler::SetCPUTimeBudgetPoolForTesting(
+ CPUTimeBudgetPool* cpu_time_budget_pool) {
+ cpu_time_budget_pool_ = cpu_time_budget_pool;
+}
+
+std::unordered_set<WorkerScheduler*>&
+WorkerThreadScheduler::GetWorkerSchedulersForTesting() {
+ return worker_schedulers_;
}
} // namespace scheduler
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h
index 4bc59994057..19e9ac40675 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h
@@ -6,76 +6,96 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_WORKER_THREAD_SCHEDULER_H_
#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
+#include "base/task/sequence_manager/task_time_observer.h"
#include "third_party/blink/public/platform/web_thread_type.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_time_observer.h"
-#include "third_party/blink/renderer/platform/scheduler/child/idle_canceled_delayed_task_sweeper.h"
-#include "third_party/blink/renderer/platform/scheduler/child/idle_helper.h"
-#include "third_party/blink/renderer/platform/scheduler/child/worker_metrics_helper.h"
+#include "third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper.h"
+#include "third_party/blink/renderer/platform/scheduler/common/idle_helper.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
-#include "third_party/blink/renderer/platform/scheduler/public/non_main_thread_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter.h"
#include "third_party/blink/renderer/platform/scheduler/util/thread_load_tracker.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/worker_metrics_helper.h"
namespace base {
namespace sequence_manager {
-class TaskQueueManager;
+class SequenceManager;
}
} // namespace base
namespace blink {
namespace scheduler {
+class WorkerScheduler;
class WorkerSchedulerProxy;
+class TaskQueueThrottler;
+class WakeUpBudgetPool;
+class CPUTimeBudgetPool;
class PLATFORM_EXPORT WorkerThreadScheduler
- : public NonMainThreadScheduler,
+ : public NonMainThreadSchedulerImpl,
public IdleHelper::Delegate,
public base::sequence_manager::TaskTimeObserver {
public:
WorkerThreadScheduler(
WebThreadType thread_type,
- std::unique_ptr<base::sequence_manager::TaskQueueManager>
- task_queue_manager,
+ std::unique_ptr<base::sequence_manager::SequenceManager> sequence_manager,
WorkerSchedulerProxy* proxy);
~WorkerThreadScheduler() override;
// WebThreadScheduler implementation:
- scoped_refptr<base::SingleThreadTaskRunner> DefaultTaskRunner() override;
scoped_refptr<SingleThreadIdleTaskRunner> IdleTaskRunner() override;
- scoped_refptr<base::SingleThreadTaskRunner> IPCTaskRunner() override;
+ scoped_refptr<base::SingleThreadTaskRunner> V8TaskRunner() override;
+ scoped_refptr<base::SingleThreadTaskRunner> CompositorTaskRunner() override;
bool ShouldYieldForHighPriorityWork() override;
bool CanExceedIdleDeadlineIfRequired() const override;
void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer) override;
void RemoveTaskObserver(
base::MessageLoop::TaskObserver* task_observer) override;
+ void AddRAILModeObserver(RAILModeObserver*) override {}
void Shutdown() override;
- // NonMainThreadScheduler implementation:
- scoped_refptr<WorkerTaskQueue> DefaultTaskQueue() override;
- void OnTaskCompleted(WorkerTaskQueue* worker_task_queue,
+ // NonMainThreadSchedulerImpl implementation:
+ scoped_refptr<NonMainThreadTaskQueue> DefaultTaskQueue() override;
+ void OnTaskCompleted(NonMainThreadTaskQueue* worker_task_queue,
const base::sequence_manager::TaskQueue::Task& task,
- base::TimeTicks start,
- base::TimeTicks end,
- base::Optional<base::TimeDelta> thread_time) override;
+ const base::sequence_manager::TaskQueue::TaskTiming&
+ task_timing) override;
// TaskTimeObserver implementation:
- void WillProcessTask(double start_time) override;
- void DidProcessTask(double start_time, double end_time) override;
+ void WillProcessTask(base::TimeTicks start_time) override;
+ void DidProcessTask(base::TimeTicks start_time,
+ base::TimeTicks end_time) override;
SchedulerHelper* GetSchedulerHelperForTesting();
base::TimeTicks CurrentIdleTaskDeadlineForTesting() const;
// Virtual for test.
- virtual void OnThrottlingStateChanged(
- FrameScheduler::ThrottlingState throttling_state);
+ virtual void OnLifecycleStateChanged(
+ SchedulingLifecycleState lifecycle_state);
+
+ SchedulingLifecycleState lifecycle_state() const { return lifecycle_state_; }
+
+ // Each WorkerScheduler should notify NonMainThreadSchedulerImpl when it is
+ // created or destroyed.
+ void RegisterWorkerScheduler(WorkerScheduler* worker_scheduler);
+ void UnregisterWorkerScheduler(WorkerScheduler* worker_scheduler);
// Returns the control task queue. Tasks posted to this queue are executed
// with the highest priority. Care must be taken to avoid starvation of other
// task queues.
- scoped_refptr<WorkerTaskQueue> ControlTaskQueue();
+ scoped_refptr<NonMainThreadTaskQueue> ControlTaskQueue();
+
+ // TaskQueueThrottler might be null if throttling is not enabled or
+ // not supported.
+ TaskQueueThrottler* task_queue_throttler() const {
+ return task_queue_throttler_.get();
+ }
+ WakeUpBudgetPool* wake_up_budget_pool() const { return wake_up_budget_pool_; }
+ CPUTimeBudgetPool* cpu_time_budget_pool() const {
+ return cpu_time_budget_pool_;
+ }
protected:
// NonMainThreadScheduler implementation:
@@ -90,32 +110,38 @@ class PLATFORM_EXPORT WorkerThreadScheduler
void OnIdlePeriodEnded() override {}
void OnPendingTasksChanged(bool new_state) override {}
- FrameScheduler::ThrottlingState throttling_state() const {
- return throttling_state_;
- }
+ void CreateTaskQueueThrottler();
- void RegisterWorkerScheduler(WorkerScheduler* worker_scheduler) override;
+ void SetCPUTimeBudgetPoolForTesting(CPUTimeBudgetPool* cpu_time_budget_pool);
- void CreateTaskQueueThrottler();
+ std::unordered_set<WorkerScheduler*>& GetWorkerSchedulersForTesting();
private:
void MaybeStartLongIdlePeriod();
- base::WeakPtr<WorkerThreadScheduler> GetWeakPtr();
-
IdleHelper idle_helper_;
IdleCanceledDelayedTaskSweeper idle_canceled_delayed_task_sweeper_;
ThreadLoadTracker load_tracker_;
bool initialized_;
base::TimeTicks thread_start_time_;
- scoped_refptr<WorkerTaskQueue> control_task_queue_;
- FrameScheduler::ThrottlingState throttling_state_;
+ scoped_refptr<NonMainThreadTaskQueue> control_task_queue_;
+ scoped_refptr<base::SingleThreadTaskRunner> v8_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
+ SchedulingLifecycleState lifecycle_state_;
WorkerMetricsHelper worker_metrics_helper_;
- scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
+ // This controller should be initialized before any TraceableVariables
+ // because they require one to initialize themselves.
+ TraceableVariableController traceable_variable_controller_;
+
+ // Worker schedulers associated with this thread.
+ std::unordered_set<WorkerScheduler*> worker_schedulers_;
- base::WeakPtrFactory<WorkerThreadScheduler> weak_factory_;
+ std::unique_ptr<TaskQueueThrottler> task_queue_throttler_;
+ // Owned by |task_queue_throttler_|.
+ WakeUpBudgetPool* wake_up_budget_pool_ = nullptr;
+ CPUTimeBudgetPool* cpu_time_budget_pool_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(WorkerThreadScheduler);
};
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc
index f2f9a1d7f29..7144c3516f0 100644
--- a/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc
+++ b/chromium/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc
@@ -8,11 +8,10 @@
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "components/viz/test/ordered_simple_task_runner.h"
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/test/scoped_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
using testing::ElementsAreArray;
@@ -28,7 +27,7 @@ int TimeTicksToIntMs(const base::TimeTicks& time) {
}
void RecordTimelineTask(std::vector<std::string>* timeline,
- base::SimpleTestTickClock* clock) {
+ const base::TickClock* clock) {
timeline->push_back(base::StringPrintf("run RecordTimelineTask @ %d",
TimeTicksToIntMs(clock->NowTicks())));
}
@@ -53,17 +52,14 @@ void TimelineIdleTestTask(std::vector<std::string>* timeline,
class WorkerThreadSchedulerForTest : public WorkerThreadScheduler {
public:
WorkerThreadSchedulerForTest(
- std::unique_ptr<base::sequence_manager::TaskQueueManager> manager,
- base::SimpleTestTickClock* clock_)
+ std::unique_ptr<base::sequence_manager::SequenceManager> manager,
+ const base::TickClock* clock_,
+ std::vector<std::string>* timeline)
: WorkerThreadScheduler(WebThreadType::kTestThread,
std::move(manager),
nullptr),
clock_(clock_),
- timeline_(nullptr) {}
-
- void RecordTimelineEvents(std::vector<std::string>* timeline) {
- timeline_ = timeline;
- }
+ timeline_(timeline) {}
private:
bool CanEnterLongIdlePeriod(
@@ -85,54 +81,45 @@ class WorkerThreadSchedulerForTest : public WorkerThreadScheduler {
WorkerThreadScheduler::IsNotQuiescent();
}
- base::SimpleTestTickClock* clock_; // NOT OWNED
- std::vector<std::string>* timeline_; // NOT OWNED
+ const base::TickClock* clock_; // Not owned.
+ std::vector<std::string>* timeline_; // Not owned.
};
class WorkerThreadSchedulerTest : public testing::Test {
public:
WorkerThreadSchedulerTest()
- : mock_task_runner_(new cc::OrderedSimpleTaskRunner(&clock_, true)),
+ : task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+ base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED),
scheduler_(new WorkerThreadSchedulerForTest(
- base::sequence_manager::TaskQueueManagerForTest::Create(
+ base::sequence_manager::SequenceManagerForTest::Create(
nullptr,
- mock_task_runner_,
- &clock_),
- &clock_)),
- timeline_(nullptr) {
- clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
+ task_environment_.GetMainThreadTaskRunner(),
+ task_environment_.GetMockTickClock()),
+ task_environment_.GetMockTickClock(),
+ &timeline_)) {
+ // Null clock might trigger some assertions.
+ task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(5));
+ scheduler_->Init();
+ default_task_runner_ = scheduler_->CreateTaskRunner("test_tq");
+ idle_task_runner_ = scheduler_->IdleTaskRunner();
}
~WorkerThreadSchedulerTest() override = default;
void TearDown() override {
- // Check that all tests stop posting tasks.
- while (mock_task_runner_->RunUntilIdle()) {
- }
- }
-
- void Init() {
- scheduler_->Init();
- default_task_runner_ = scheduler_->DefaultTaskRunner();
- idle_task_runner_ = scheduler_->IdleTaskRunner();
- timeline_ = nullptr;
- }
-
- void RecordTimelineEvents(std::vector<std::string>* timeline) {
- timeline_ = timeline;
- scheduler_->RecordTimelineEvents(timeline);
+ task_environment_.FastForwardUntilNoTasksRemain();
}
void RunUntilIdle() {
- if (timeline_) {
- timeline_->push_back(base::StringPrintf(
- "RunUntilIdle begin @ %d", TimeTicksToIntMs(clock_.NowTicks())));
- }
- mock_task_runner_->RunUntilIdle();
- if (timeline_) {
- timeline_->push_back(base::StringPrintf(
- "RunUntilIdle end @ %d", TimeTicksToIntMs(clock_.NowTicks())));
- }
+ timeline_.push_back(base::StringPrintf(
+ "RunUntilIdle begin @ %d",
+ TimeTicksToIntMs(task_environment_.GetMockTickClock()->NowTicks())));
+ // RunUntilIdle with auto-advancing for the mock clock.
+ task_environment_.FastForwardUntilNoTasksRemain();
+ timeline_.push_back(base::StringPrintf(
+ "RunUntilIdle end @ %d",
+ TimeTicksToIntMs(task_environment_.GetMockTickClock()->NowTicks())));
}
// Helper for posting several tasks of specific types. |task_descriptor| is a
@@ -169,21 +156,16 @@ class WorkerThreadSchedulerTest : public testing::Test {
}
protected:
- base::SimpleTestTickClock clock_;
- // Only one of mock_task_runner_ or message_loop_ will be set.
- scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
-
+ base::test::ScopedTaskEnvironment task_environment_;
+ std::vector<std::string> timeline_;
std::unique_ptr<WorkerThreadSchedulerForTest> scheduler_;
scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
scoped_refptr<SingleThreadIdleTaskRunner> idle_task_runner_;
- std::vector<std::string>* timeline_; // NOT OWNED
DISALLOW_COPY_AND_ASSIGN(WorkerThreadSchedulerTest);
};
TEST_F(WorkerThreadSchedulerTest, TestPostDefaultTask) {
- Init();
-
std::vector<std::string> run_order;
PostTestTasks(&run_order, "D1 D2 D3 D4");
@@ -194,8 +176,6 @@ TEST_F(WorkerThreadSchedulerTest, TestPostDefaultTask) {
}
TEST_F(WorkerThreadSchedulerTest, TestPostIdleTask) {
- Init();
-
std::vector<std::string> run_order;
PostTestTasks(&run_order, "I1");
@@ -204,8 +184,6 @@ TEST_F(WorkerThreadSchedulerTest, TestPostIdleTask) {
}
TEST_F(WorkerThreadSchedulerTest, TestPostDefaultAndIdleTasks) {
- Init();
-
std::vector<std::string> run_order;
PostTestTasks(&run_order, "I1 D2 D3 D4");
@@ -216,8 +194,6 @@ TEST_F(WorkerThreadSchedulerTest, TestPostDefaultAndIdleTasks) {
}
TEST_F(WorkerThreadSchedulerTest, TestPostDefaultDelayedAndIdleTasks) {
- Init();
-
std::vector<std::string> run_order;
PostTestTasks(&run_order, "I1 D2 D3 D4");
@@ -233,91 +209,86 @@ TEST_F(WorkerThreadSchedulerTest, TestPostDefaultDelayedAndIdleTasks) {
}
TEST_F(WorkerThreadSchedulerTest, TestIdleTaskWhenIsNotQuiescent) {
- std::vector<std::string> timeline;
- RecordTimelineEvents(&timeline);
- Init();
-
- timeline.push_back("Post default task");
+ timeline_.push_back("Post default task");
// Post a delayed task timed to occur mid way during the long idle period.
default_task_runner_->PostTask(
FROM_HERE,
- base::BindOnce(&RecordTimelineTask, base::Unretained(&timeline),
- base::Unretained(&clock_)));
+ base::BindOnce(&RecordTimelineTask, base::Unretained(&timeline_),
+ base::Unretained(task_environment_.GetMockTickClock())));
RunUntilIdle();
- timeline.push_back("Post idle task");
+ timeline_.push_back("Post idle task");
idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&TimelineIdleTestTask, &timeline));
+ FROM_HERE,
+ base::BindOnce(&TimelineIdleTestTask, base::Unretained(&timeline_)));
RunUntilIdle();
- std::string expected_timeline[] = {"CanEnterLongIdlePeriod @ 5",
- "Post default task",
- "run RecordTimelineTask @ 5",
- "Post idle task",
- "IsNotQuiescent @ 5",
- "CanEnterLongIdlePeriod @ 305",
- "run TimelineIdleTestTask deadline 355"};
-
- EXPECT_THAT(timeline, ElementsAreArray(expected_timeline));
+ std::string expected_timeline[] = {
+ "CanEnterLongIdlePeriod @ 5", "Post default task",
+ "RunUntilIdle begin @ 5", "run RecordTimelineTask @ 5",
+ "RunUntilIdle end @ 5", "Post idle task",
+ "RunUntilIdle begin @ 5", "IsNotQuiescent @ 5",
+ "CanEnterLongIdlePeriod @ 305", "run TimelineIdleTestTask deadline 355",
+ "RunUntilIdle end @ 305"};
+
+ EXPECT_THAT(timeline_, ElementsAreArray(expected_timeline));
}
TEST_F(WorkerThreadSchedulerTest, TestIdleDeadlineWithPendingDelayedTask) {
- std::vector<std::string> timeline;
- RecordTimelineEvents(&timeline);
- Init();
-
- timeline.push_back("Post delayed and idle tasks");
+ timeline_.push_back("Post delayed and idle tasks");
// Post a delayed task timed to occur mid way during the long idle period.
default_task_runner_->PostDelayedTask(
FROM_HERE,
- base::BindOnce(&RecordTimelineTask, base::Unretained(&timeline),
- base::Unretained(&clock_)),
+ base::BindOnce(&RecordTimelineTask, base::Unretained(&timeline_),
+ base::Unretained(task_environment_.GetMockTickClock())),
base::TimeDelta::FromMilliseconds(20));
idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&TimelineIdleTestTask, &timeline));
+ FROM_HERE,
+ base::BindOnce(&TimelineIdleTestTask, base::Unretained(&timeline_)));
RunUntilIdle();
std::string expected_timeline[] = {
- "CanEnterLongIdlePeriod @ 5", "Post delayed and idle tasks",
+ "CanEnterLongIdlePeriod @ 5",
+ "Post delayed and idle tasks",
+ "RunUntilIdle begin @ 5",
"CanEnterLongIdlePeriod @ 5",
"run TimelineIdleTestTask deadline 25", // Note the short 20ms deadline.
- "run RecordTimelineTask @ 25"};
+ "run RecordTimelineTask @ 25",
+ "RunUntilIdle end @ 25"};
- EXPECT_THAT(timeline, ElementsAreArray(expected_timeline));
+ EXPECT_THAT(timeline_, ElementsAreArray(expected_timeline));
}
TEST_F(WorkerThreadSchedulerTest,
TestIdleDeadlineWithPendingDelayedTaskFarInTheFuture) {
- std::vector<std::string> timeline;
- RecordTimelineEvents(&timeline);
- Init();
-
- timeline.push_back("Post delayed and idle tasks");
+ timeline_.push_back("Post delayed and idle tasks");
// Post a delayed task timed to occur well after the long idle period.
default_task_runner_->PostDelayedTask(
FROM_HERE,
- base::BindOnce(&RecordTimelineTask, base::Unretained(&timeline),
- base::Unretained(&clock_)),
+ base::BindOnce(&RecordTimelineTask, base::Unretained(&timeline_),
+ base::Unretained(task_environment_.GetMockTickClock())),
base::TimeDelta::FromMilliseconds(500));
idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&TimelineIdleTestTask, &timeline));
+ FROM_HERE,
+ base::BindOnce(&TimelineIdleTestTask, base::Unretained(&timeline_)));
RunUntilIdle();
std::string expected_timeline[] = {
- "CanEnterLongIdlePeriod @ 5", "Post delayed and idle tasks",
+ "CanEnterLongIdlePeriod @ 5",
+ "Post delayed and idle tasks",
+ "RunUntilIdle begin @ 5",
"CanEnterLongIdlePeriod @ 5",
"run TimelineIdleTestTask deadline 55", // Note the full 50ms deadline.
- "run RecordTimelineTask @ 505"};
+ "run RecordTimelineTask @ 505",
+ "RunUntilIdle end @ 505"};
- EXPECT_THAT(timeline, ElementsAreArray(expected_timeline));
+ EXPECT_THAT(timeline_, ElementsAreArray(expected_timeline));
}
TEST_F(WorkerThreadSchedulerTest, TestPostIdleTaskAfterRunningUntilIdle) {
- Init();
-
default_task_runner_->PostDelayedTask(
FROM_HERE, base::BindOnce(&NopTask),
base::TimeDelta::FromMilliseconds(1000));
@@ -333,7 +304,7 @@ TEST_F(WorkerThreadSchedulerTest, TestPostIdleTaskAfterRunningUntilIdle) {
}
void PostIdleTask(std::vector<std::string>* timeline,
- base::SimpleTestTickClock* clock,
+ const base::TickClock* clock,
SingleThreadIdleTaskRunner* idle_task_runner) {
timeline->push_back(base::StringPrintf("run PostIdleTask @ %d",
TimeTicksToIntMs(clock->NowTicks())));
@@ -343,19 +314,14 @@ void PostIdleTask(std::vector<std::string>* timeline,
}
TEST_F(WorkerThreadSchedulerTest, TestLongIdlePeriodTimeline) {
- Init();
-
- std::vector<std::string> timeline;
- RecordTimelineEvents(&timeline);
-
// The scheduler should not run the initiate_next_long_idle_period task if
// there are no idle tasks and no other task woke up the scheduler, thus
// the idle period deadline shouldn't update at the end of the current long
// idle period.
base::TimeTicks idle_period_deadline =
scheduler_->CurrentIdleTaskDeadlineForTesting();
- clock_.Advance(maximum_idle_period_duration());
- RunUntilIdle();
+ // Not printed in the timeline.
+ task_environment_.FastForwardBy(maximum_idle_period_duration());
base::TimeTicks new_idle_period_deadline =
scheduler_->CurrentIdleTaskDeadlineForTesting();
@@ -366,27 +332,27 @@ TEST_F(WorkerThreadSchedulerTest, TestLongIdlePeriodTimeline) {
// the idle task run.
default_task_runner_->PostDelayedTask(
FROM_HERE,
- base::BindOnce(&PostIdleTask, base::Unretained(&timeline),
- base::Unretained(&clock_),
+ base::BindOnce(&PostIdleTask, base::Unretained(&timeline_),
+ base::Unretained(task_environment_.GetMockTickClock()),
base::Unretained(idle_task_runner_.get())),
base::TimeDelta::FromMilliseconds(30));
- timeline.push_back("PostFirstIdleTask");
+ timeline_.push_back("PostFirstIdleTask");
idle_task_runner_->PostIdleTask(
- FROM_HERE, base::BindOnce(&TimelineIdleTestTask, &timeline));
+ FROM_HERE,
+ base::BindOnce(&TimelineIdleTestTask, base::Unretained(&timeline_)));
RunUntilIdle();
new_idle_period_deadline = scheduler_->CurrentIdleTaskDeadlineForTesting();
// Running a normal task will mark the system as non-quiescent.
- timeline.push_back("Post RecordTimelineTask");
+ timeline_.push_back("Post RecordTimelineTask");
default_task_runner_->PostTask(
FROM_HERE,
- base::BindOnce(&RecordTimelineTask, base::Unretained(&timeline),
- base::Unretained(&clock_)));
+ base::BindOnce(&RecordTimelineTask, base::Unretained(&timeline_),
+ base::Unretained(task_environment_.GetMockTickClock())));
RunUntilIdle();
- std::string expected_timeline[] = {"RunUntilIdle begin @ 55",
- "RunUntilIdle end @ 55",
+ std::string expected_timeline[] = {"CanEnterLongIdlePeriod @ 5",
"PostFirstIdleTask",
"RunUntilIdle begin @ 55",
"CanEnterLongIdlePeriod @ 55",
@@ -401,9 +367,9 @@ TEST_F(WorkerThreadSchedulerTest, TestLongIdlePeriodTimeline) {
"run RecordTimelineTask @ 385",
"RunUntilIdle end @ 385"};
- EXPECT_THAT(timeline, ElementsAreArray(expected_timeline));
+ EXPECT_THAT(timeline_, ElementsAreArray(expected_timeline));
}
-} // namespace worker_scheduler_impl_unittest
+} // namespace worker_thread_scheduler_unittest
} // namespace scheduler
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scoped_orientation_change_indicator.cc b/chromium/third_party/blink/renderer/platform/scoped_orientation_change_indicator.cc
index 281c68dd94b..a96f0002edb 100644
--- a/chromium/third_party/blink/renderer/platform/scoped_orientation_change_indicator.cc
+++ b/chromium/third_party/blink/renderer/platform/scoped_orientation_change_indicator.cc
@@ -4,7 +4,8 @@
#include "third_party/blink/renderer/platform/scoped_orientation_change_indicator.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "base/logging.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scroll_animator.cc b/chromium/third_party/blink/renderer/platform/scroll/scroll_animator.cc
index f6b0f889b8a..565abbea0c0 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scroll_animator.cc
+++ b/chromium/third_party/blink/renderer/platform/scroll/scroll_animator.cc
@@ -34,7 +34,7 @@
#include "base/memory/scoped_refptr.h"
#include "cc/animation/scroll_offset_animation_curve.h"
-#include "cc/layers/layer.h"
+#include "cc/layers/picture_layer.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/animation/compositor_keyframe_model.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
@@ -47,7 +47,7 @@ namespace blink {
namespace {
-cc::Layer* ToCcLayer(GraphicsLayer* layer) {
+cc::PictureLayer* ToCcLayer(GraphicsLayer* layer) {
return layer ? layer->CcLayer() : nullptr;
}
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scroll_animator_compositor_coordinator.cc b/chromium/third_party/blink/renderer/platform/scroll/scroll_animator_compositor_coordinator.cc
index 2d1541d2676..85be672cf90 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scroll_animator_compositor_coordinator.cc
+++ b/chromium/third_party/blink/renderer/platform/scroll/scroll_animator_compositor_coordinator.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "cc/animation/scroll_offset_animation_curve.h"
+#include "cc/layers/picture_layer.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_host.h"
@@ -230,13 +231,13 @@ ScrollAnimatorCompositorCoordinator::GetCompositorAnimation() const {
FloatPoint ScrollAnimatorCompositorCoordinator::CompositorOffsetFromBlinkOffset(
ScrollOffset offset) {
- return GetScrollableArea()->ScrollOrigin() + offset;
+ return GetScrollableArea()->ScrollOffsetToPosition(offset);
}
ScrollOffset
ScrollAnimatorCompositorCoordinator::BlinkOffsetFromCompositorOffset(
- FloatPoint offset) {
- return offset - GetScrollableArea()->ScrollOrigin();
+ FloatPoint position) {
+ return GetScrollableArea()->ScrollPositionToOffset(position);
}
bool ScrollAnimatorCompositorCoordinator::HasImplOnlyAnimationUpdate() const {
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scroll_animator_test.cc b/chromium/third_party/blink/renderer/platform/scroll/scroll_animator_test.cc
index f228ae00944..8a8441ebcc7 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scroll_animator_test.cc
+++ b/chromium/third_party/blink/renderer/platform/scroll/scroll_animator_test.cc
@@ -70,6 +70,7 @@ class MockScrollableAreaForAnimatorTest
MOCK_CONST_METHOD0(VisualRectForScrollbarParts, LayoutRect());
MOCK_CONST_METHOD0(IsActive, bool());
+ MOCK_CONST_METHOD0(IsThrottled, bool());
MOCK_CONST_METHOD1(ScrollSize, int(ScrollbarOrientation));
MOCK_CONST_METHOD0(IsScrollCornerVisible, bool());
MOCK_CONST_METHOD0(ScrollCornerRect, IntRect());
@@ -622,7 +623,7 @@ TEST(ScrollAnimatorTest, ImplOnlyAnimationUpdatesCleared) {
animator->AdjustImplOnlyScrollOffsetAnimation(IntSize(10, -10));
EXPECT_TRUE(animator->HasAnimationThatRequiresService());
- EXPECT_EQ(FloatSize(110, 90),
+ EXPECT_EQ(IntSize(110, 90),
animator->ImplOnlyAnimationAdjustmentForTesting());
animator->UpdateCompositorAnimations();
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scroll_snap_data.h b/chromium/third_party/blink/renderer/platform/scroll/scroll_snap_data.h
index 6cc9550b3ab..0aa52947b3b 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scroll_snap_data.h
+++ b/chromium/third_party/blink/renderer/platform/scroll/scroll_snap_data.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCROLL_SCROLL_SNAP_DATA_H_
#include "cc/input/scroll_snap_data.h"
+#include "cc/input/snap_fling_controller.h"
// This file defines classes and structs used in SnapCoordinator.h
@@ -19,6 +20,8 @@ using ScrollSnapType = cc::ScrollSnapType;
using ScrollSnapAlign = cc::ScrollSnapAlign;
using SnapAreaData = cc::SnapAreaData;
using SnapContainerData = cc::SnapContainerData;
+using SnapFlingController = cc::SnapFlingController;
+using SnapFlingClient = cc::SnapFlingClient;
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scroll_types.h b/chromium/third_party/blink/renderer/platform/scroll/scroll_types.h
index 9215523cb35..4f4884b73ba 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scroll_types.h
+++ b/chromium/third_party/blink/renderer/platform/scroll/scroll_types.h
@@ -266,16 +266,6 @@ inline ScrollGranularity ToPlatformScrollGranularity(
}
}
-inline ScrollOffset ScrollPositionToOffset(FloatPoint position,
- FloatPoint origin) {
- return position - origin;
-}
-
-inline FloatPoint ScrollOffsetToPosition(ScrollOffset offset,
- FloatPoint origin) {
- return origin + offset;
-}
-
typedef unsigned ScrollbarControlPartMask;
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scrollable_area.cc b/chromium/third_party/blink/renderer/platform/scroll/scrollable_area.cc
index 1fe39e6590c..95c660bb23d 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scrollable_area.cc
+++ b/chromium/third_party/blink/renderer/platform/scroll/scrollable_area.cc
@@ -32,6 +32,7 @@
#include "third_party/blink/renderer/platform/scroll/scrollable_area.h"
#include "build/build_config.h"
+#include "cc/layers/picture_layer.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -39,6 +40,7 @@
#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
#include "third_party/blink/renderer/platform/scroll/main_thread_scrolling_reason.h"
#include "third_party/blink/renderer/platform/scroll/programmatic_scroll_animator.h"
+#include "third_party/blink/renderer/platform/scroll/scroll_animator_base.h"
#include "third_party/blink/renderer/platform/scroll/scrollbar_theme.h"
#include "third_party/blink/renderer/platform/scroll/smooth_scroll_sequencer.h"
@@ -77,10 +79,7 @@ ScrollBehavior ScrollableArea::DetermineScrollBehavior(
}
ScrollableArea::ScrollableArea()
- : autosize_vertical_scrollbar_mode_(kScrollbarAuto),
- autosize_horizontal_scrollbar_mode_(kScrollbarAuto),
- scrollbar_overlay_color_theme_(kScrollbarOverlayColorThemeDark),
- scroll_origin_changed_(false),
+ : scrollbar_overlay_color_theme_(kScrollbarOverlayColorThemeDark),
horizontal_scrollbar_needs_paint_invalidation_(false),
vertical_scrollbar_needs_paint_invalidation_(false),
scroll_corner_needs_paint_invalidation_(false),
@@ -120,13 +119,6 @@ ProgrammaticScrollAnimator& ScrollableArea::GetProgrammaticScrollAnimator()
return *programmatic_scroll_animator_;
}
-void ScrollableArea::SetScrollOrigin(const IntPoint& origin) {
- if (scroll_origin_ != origin) {
- scroll_origin_ = origin;
- scroll_origin_changed_ = true;
- }
-}
-
GraphicsLayer* ScrollableArea::LayerForContainer() const {
return LayerForScrolling() ? LayerForScrolling()->Parent() : nullptr;
}
@@ -398,11 +390,10 @@ void ScrollableArea::MouseCapturedScrollbar() {
fade_overlay_scrollbars_timer_->Stop();
}
-void ScrollableArea::MouseReleasedScrollbar(ScrollbarOrientation orientation) {
+void ScrollableArea::MouseReleasedScrollbar() {
scrollbar_captured_ = false;
// This will kick off the fade out timer.
ShowOverlayScrollbars();
- SnapAfterScrollbarDragging(orientation);
}
void ScrollableArea::ContentAreaDidShow() const {
@@ -621,9 +612,9 @@ void ScrollableArea::ShowOverlayScrollbars() {
SetScrollbarsHiddenIfOverlay(false);
needs_show_scrollbar_layers_ = true;
- const double time_until_disable =
- GetPageScrollbarTheme().OverlayScrollbarFadeOutDelaySeconds() +
- GetPageScrollbarTheme().OverlayScrollbarFadeOutDurationSeconds();
+ const TimeDelta time_until_disable =
+ GetPageScrollbarTheme().OverlayScrollbarFadeOutDelay() +
+ GetPageScrollbarTheme().OverlayScrollbarFadeOutDuration();
// If the overlay scrollbars don't fade out, don't do anything. This is the
// case for the mock overlays used in tests and on Mac, where the fade-out is
@@ -631,7 +622,7 @@ void ScrollableArea::ShowOverlayScrollbars() {
// We also don't fade out overlay scrollbar for popup since we don't create
// compositor for popup and thus they don't appear on hover so users without
// a wheel can't scroll if they fade out.
- if (!time_until_disable || GetChromeClient()->IsPopup())
+ if (time_until_disable.is_zero() || GetChromeClient()->IsPopup())
return;
if (!fade_overlay_scrollbars_timer_) {
@@ -661,9 +652,14 @@ int ScrollableArea::LineStep(ScrollbarOrientation) const {
}
int ScrollableArea::PageStep(ScrollbarOrientation orientation) const {
- IntRect visible_rect = VisibleContentRect(kIncludeScrollbars);
- int length = (orientation == kHorizontalScrollbar) ? visible_rect.Width()
- : visible_rect.Height();
+ // Paging scroll operations should take scroll-padding into account [1]. So we
+ // use the snapport rect to calculate the page step instead of the visible
+ // rect.
+ // [1] https://drafts.csswg.org/css-scroll-snap/#scroll-padding
+ IntSize snapport_size =
+ VisibleScrollSnapportRect(kIncludeScrollbars).PixelSnappedSize();
+ int length = (orientation == kHorizontalScrollbar) ? snapport_size.Width()
+ : snapport_size.Height();
int min_page_step =
static_cast<float>(length) * MinFractionToStepWhenPaging();
int page_step = std::max(min_page_step, length - MaxOverlapBetweenPages());
@@ -708,17 +704,21 @@ IntSize ScrollableArea::ExcludeScrollbars(const IntSize& size) const {
std::max(0, size.Height() - HorizontalScrollbarHeight()));
}
-void ScrollableArea::DidScroll(const gfx::ScrollOffset& offset) {
- ScrollOffset new_offset = ScrollOffset(offset.x() - ScrollOrigin().X(),
- offset.y() - ScrollOrigin().Y());
+void ScrollableArea::DidScroll(const FloatPoint& position) {
+ ScrollOffset new_offset(ScrollPositionToOffset(position));
SetScrollOffset(new_offset, kCompositorScroll);
}
-void ScrollableArea::SetAutosizeScrollbarModes(ScrollbarMode vertical,
- ScrollbarMode horizontal) {
- DCHECK_EQ(vertical == kScrollbarAuto, horizontal == kScrollbarAuto);
- autosize_vertical_scrollbar_mode_ = vertical;
- autosize_horizontal_scrollbar_mode_ = horizontal;
+CompositorElementId ScrollableArea::GetScrollbarElementId(
+ ScrollbarOrientation orientation) {
+ CompositorElementId scrollable_element_id = GetCompositorElementId();
+ DCHECK(scrollable_element_id);
+ CompositorElementIdNamespace element_id_namespace =
+ orientation == kHorizontalScrollbar
+ ? CompositorElementIdNamespace::kHorizontalScrollbar
+ : CompositorElementIdNamespace::kVerticalScrollbar;
+ return CompositorElementIdFromUniqueObjectId(
+ scrollable_element_id.GetInternalValue(), element_id_namespace);
}
void ScrollableArea::Trace(blink::Visitor* visitor) {
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scrollable_area.h b/chromium/third_party/blink/renderer/platform/scroll/scrollable_area.h
index 323bc8307c9..a517e8a183a 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scrollable_area.h
+++ b/chromium/third_party/blink/renderer/platform/scroll/scrollable_area.h
@@ -26,20 +26,23 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCROLL_SCROLLABLE_AREA_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCROLL_SCROLLABLE_AREA_H_
-#include "base/single_thread_task_runner.h"
#include "third_party/blink/renderer/platform/geometry/float_quad.h"
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
+#include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/scroll/scroll_animator_base.h"
#include "third_party/blink/renderer/platform/scroll/scroll_types.h"
#include "third_party/blink/renderer/platform/scroll/scrollbar.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
+namespace base {
+class SingleThreadTaskRunner;
+}
+
namespace blink {
class CompositorAnimationHost;
@@ -110,11 +113,11 @@ class PLATFORM_EXPORT ScrollableArea : public GarbageCollectedMixin {
void MouseEnteredScrollbar(Scrollbar&);
void MouseExitedScrollbar(Scrollbar&);
void MouseCapturedScrollbar();
- void MouseReleasedScrollbar(ScrollbarOrientation);
+ void MouseReleasedScrollbar();
void ContentAreaDidShow() const;
void ContentAreaDidHide() const;
- virtual void SnapAfterScrollbarDragging(ScrollbarOrientation) {}
+ virtual void SnapAfterScrollbarScrolling(ScrollbarOrientation) {}
void FinishCurrentScrollAnimations() const;
@@ -156,10 +159,6 @@ class PLATFORM_EXPORT ScrollableArea : public GarbageCollectedMixin {
return nullptr;
}
- // See Source/core/layout/README.md for an explanation of scroll origin.
- virtual IntPoint ScrollOrigin() const { return scroll_origin_; }
- bool ScrollOriginChanged() const { return scroll_origin_changed_; }
-
// This is used to determine whether the incoming fractional scroll offset
// should be truncated to integer. Current rule is that if
// preferCompositingToLCDTextEnabled() is disabled (which is true on low-dpi
@@ -173,6 +172,10 @@ class PLATFORM_EXPORT ScrollableArea : public GarbageCollectedMixin {
}
virtual bool IsActive() const = 0;
+ // Returns true if the frame this ScrollableArea is attached to is being
+ // throttled for lifecycle updates. In this case it should also not be
+ // painted.
+ virtual bool IsThrottled() const = 0;
virtual int ScrollSize(ScrollbarOrientation) const = 0;
void SetScrollbarNeedsPaintInvalidation(ScrollbarOrientation);
virtual bool IsScrollCornerVisible() const = 0;
@@ -214,14 +217,20 @@ class PLATFORM_EXPORT ScrollableArea : public GarbageCollectedMixin {
virtual PaintLayer* Layer() const { return nullptr; }
- // scrollPosition is the location of the top/left of the scroll viewport in
- // the coordinate system defined by the top/left of the overflow rect.
- // scrollOffset is the offset of the scroll viewport from its position when
- // scrolled all the way to the beginning of its content's flow.
- // For a more detailed explanation of scrollPosition, scrollOffset, and
- // scrollOrigin, see core/layout/README.md.
- FloatPoint ScrollPosition() const {
- return FloatPoint(ScrollOrigin()) + GetScrollOffset();
+ // "Scroll offset" is in content-flow-aware coordinates, "Scroll position" is
+ // in physical (i.e., not flow-aware) coordinates. Among ScrollableArea
+ // sub-classes, only PaintLayerScrollableArea has a real distinction between
+ // the two. For a more detailed explanation of scrollPosition, scrollOffset,
+ // and scrollOrigin, see core/layout/README.md.
+ virtual FloatPoint ScrollPosition() const {
+ return FloatPoint(GetScrollOffset());
+ }
+ virtual FloatPoint ScrollOffsetToPosition(const ScrollOffset& offset) const {
+ return FloatPoint(offset);
+ }
+ virtual ScrollOffset ScrollPositionToOffset(
+ const FloatPoint& position) const {
+ return ToScrollOffset(position);
}
virtual IntSize ScrollOffsetInt() const = 0;
virtual ScrollOffset GetScrollOffset() const {
@@ -246,8 +255,9 @@ class PLATFORM_EXPORT ScrollableArea : public GarbageCollectedMixin {
// container for the scroll snap areas when calculating snap positions. It's
// the box's scrollport contracted by its scroll-padding.
// https://drafts.csswg.org/css-scroll-snap-1/#scroll-padding
- virtual LayoutRect VisibleScrollSnapportRect() const {
- return LayoutRect(VisibleContentRect());
+ virtual LayoutRect VisibleScrollSnapportRect(
+ IncludeScrollbarsInRect scrollbar_inclusion = kExcludeScrollbars) const {
+ return LayoutRect(VisibleContentRect(scrollbar_inclusion));
}
virtual IntPoint LastKnownMousePosition() const { return IntPoint(); }
@@ -261,6 +271,10 @@ class PLATFORM_EXPORT ScrollableArea : public GarbageCollectedMixin {
virtual IntRect ScrollableAreaBoundingBox() const = 0;
virtual CompositorElementId GetCompositorElementId() const = 0;
+
+ virtual CompositorElementId GetScrollbarElementId(
+ ScrollbarOrientation orientation);
+
virtual bool ScrollAnimatorEnabled() const { return false; }
// NOTE: Only called from Internals for testing.
@@ -287,9 +301,6 @@ class PLATFORM_EXPORT ScrollableArea : public GarbageCollectedMixin {
virtual bool ScrollbarsHiddenIfOverlay() const;
virtual void SetScrollbarsHiddenIfOverlay(bool);
- // Returns true if the GraphicsLayer tree needs to be rebuilt.
- virtual bool UpdateAfterCompositingChange() { return false; }
-
virtual bool UserInputScrollable(ScrollbarOrientation) const = 0;
virtual bool ShouldPlaceVerticalScrollbarOnLeft() const = 0;
@@ -336,15 +347,6 @@ class PLATFORM_EXPORT ScrollableArea : public GarbageCollectedMixin {
return kScrollBehaviorInstant;
}
- virtual bool IsScrollable() const { return true; }
-
- // TODO(bokan): FrameView::setScrollOffset uses updateScrollbars to scroll
- // which bails out early if its already in updateScrollbars, the effect being
- // that programmatic scrolls (i.e. setScrollOffset) are disabled when in
- // updateScrollbars. Expose this here to allow RootFrameViewport to match the
- // semantics for now but it should be cleaned up at the source.
- virtual bool IsProgrammaticallyScrollable() { return true; }
-
// Subtracts space occupied by this ScrollableArea's scrollbars.
// Does nothing if overlay scrollbars are enabled.
IntSize ExcludeScrollbars(const IntSize&) const;
@@ -368,6 +370,8 @@ class PLATFORM_EXPORT ScrollableArea : public GarbageCollectedMixin {
virtual bool IsPaintLayerScrollableArea() const { return false; }
virtual bool IsRootFrameViewport() const { return false; }
+ virtual bool VisualViewportSuppliesScrollbars() const { return false; }
+
// Returns true if the scroller adjusts the scroll offset to compensate
// for layout movements (bit.ly/scroll-anchoring).
virtual bool ShouldPerformScrollAnchoring() const { return false; }
@@ -389,16 +393,12 @@ class PLATFORM_EXPORT ScrollableArea : public GarbageCollectedMixin {
const = 0;
// Callback for compositor-side scrolling.
- virtual void DidScroll(const gfx::ScrollOffset&);
+ virtual void DidScroll(const FloatPoint&);
virtual void ScrollbarFrameRectChanged() {}
virtual ScrollbarTheme& GetPageScrollbarTheme() const = 0;
- // If either direction has a non-auto mode, the other must as well.
- void SetAutosizeScrollbarModes(ScrollbarMode vertical,
- ScrollbarMode horizontal);
-
protected:
// Deduces the ScrollBehavior based on the element style and the parameter set
// by programmatic scroll into either instant or smooth scroll.
@@ -412,9 +412,6 @@ class PLATFORM_EXPORT ScrollableArea : public GarbageCollectedMixin {
ScrollDirectionPhysical) const;
float ScrollStep(ScrollGranularity, ScrollbarOrientation) const;
- void SetScrollOrigin(const IntPoint&);
- void ResetScrollOriginChanged() { scroll_origin_changed_ = false; }
-
// Needed to let the animators call scrollOffsetChanged.
friend class ScrollAnimatorCompositorCoordinator;
void ScrollOffsetChanged(const ScrollOffset&, ScrollType);
@@ -441,13 +438,6 @@ class PLATFORM_EXPORT ScrollableArea : public GarbageCollectedMixin {
// then reset to alpha, causing spurrious "visibilityChanged" calls.
virtual void ScrollbarVisibilityChanged() {}
- ScrollbarMode AutosizeVerticalScrollbarMode() const {
- return autosize_vertical_scrollbar_mode_;
- }
- ScrollbarMode AutosizeHorizontalScrollbarMode() const {
- return autosize_horizontal_scrollbar_mode_;
- }
-
virtual bool HasBeenDisposed() const { return false; }
private:
@@ -474,17 +464,8 @@ class PLATFORM_EXPORT ScrollableArea : public GarbageCollectedMixin {
std::unique_ptr<TaskRunnerTimer<ScrollableArea>>
fade_overlay_scrollbars_timer_;
- // FrameViewAutoSizeInfo controls scrollbar appearance manually rather than
- // relying on layout. These members are used to override the
- // ScrollableArea's ScrollbarModes as calculated from style. kScrollbarAuto
- // disables the override.
- ScrollbarMode autosize_vertical_scrollbar_mode_;
- ScrollbarMode autosize_horizontal_scrollbar_mode_;
-
unsigned scrollbar_overlay_color_theme_ : 2;
- unsigned scroll_origin_changed_ : 1;
-
unsigned horizontal_scrollbar_needs_paint_invalidation_ : 1;
unsigned vertical_scrollbar_needs_paint_invalidation_ : 1;
unsigned scroll_corner_needs_paint_invalidation_ : 1;
@@ -496,18 +477,6 @@ class PLATFORM_EXPORT ScrollableArea : public GarbageCollectedMixin {
// cc::Layer::ShowScrollbars() on our scroll layer. Ignored if not composited.
unsigned needs_show_scrollbar_layers_ : 1;
unsigned uses_composited_scrolling_ : 1;
-
- // There are 6 possible combinations of writing mode and direction. Scroll
- // origin will be non-zero in the x or y axis if there is any reversed
- // direction or writing-mode. The combinations are:
- // writing-mode / direction scrollOrigin.x() set scrollOrigin.y() set
- // horizontal-tb / ltr NO NO
- // horizontal-tb / rtl YES NO
- // vertical-lr / ltr NO NO
- // vertical-lr / rtl NO YES
- // vertical-rl / ltr YES NO
- // vertical-rl / rtl YES YES
- IntPoint scroll_origin_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scrollable_area_test.cc b/chromium/third_party/blink/renderer/platform/scroll/scrollable_area_test.cc
index b959f8a2afe..0f47eea58f0 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scrollable_area_test.cc
+++ b/chromium/third_party/blink/renderer/platform/scroll/scrollable_area_test.cc
@@ -10,6 +10,7 @@
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
+#include "third_party/blink/renderer/platform/scroll/scroll_animator_base.h"
#include "third_party/blink/renderer/platform/scroll/scrollbar_test_suite.h"
#include "third_party/blink/renderer/platform/scroll/scrollbar_theme.h"
#include "third_party/blink/renderer/platform/scroll/scrollbar_theme_mock.h"
@@ -266,12 +267,10 @@ TEST_F(ScrollableAreaTest, ScrollableAreaDidScroll) {
MockScrollableArea* scrollable_area =
MockScrollableArea::Create(ScrollOffset(100, 100));
- scrollable_area->SetScrollOrigin(IntPoint(20, 30));
- scrollable_area->DidScroll(gfx::ScrollOffset(40, 51));
+ scrollable_area->DidScroll(FloatPoint(40, 51));
- // After calling didScroll, the new offset should account for scroll origin.
- EXPECT_EQ(20, scrollable_area->ScrollOffsetInt().Width());
- EXPECT_EQ(21, scrollable_area->ScrollOffsetInt().Height());
+ EXPECT_EQ(40, scrollable_area->ScrollOffsetInt().Width());
+ EXPECT_EQ(51, scrollable_area->ScrollOffsetInt().Height());
}
// Scrollbars in popups shouldn't fade out since they aren't composited and thus
@@ -290,7 +289,7 @@ TEST_F(ScrollableAreaTest, PopupOverlayScrollbarShouldNotFadeOut) {
ScrollbarThemeOverlayMock& theme =
(ScrollbarThemeOverlayMock&)scrollable_area->GetPageScrollbarTheme();
- theme.SetOverlayScrollbarFadeOutDelay(1);
+ theme.SetOverlayScrollbarFadeOutDelay(TimeDelta::FromSeconds(1));
Scrollbar* scrollbar = Scrollbar::CreateForTesting(
scrollable_area, kHorizontalScrollbar, kRegularScrollbar, &theme);
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scrollbar.cc b/chromium/third_party/blink/renderer/platform/scroll/scrollbar.cc
index 4b885d81259..89b50db2f45 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scrollbar.cc
+++ b/chromium/third_party/blink/renderer/platform/scroll/scrollbar.cc
@@ -172,7 +172,10 @@ bool Scrollbar::ThumbWillBeUnderMouse() const {
return PressedPos() >= thumb_pos && PressedPos() < thumb_pos + thumb_length;
}
-void Scrollbar::AutoscrollPressedPart(double delay) {
+void Scrollbar::AutoscrollPressedPart(TimeDelta delay) {
+ if (!scrollable_area_)
+ return;
+
// Don't do anything for the thumb or if nothing was pressed.
if (pressed_part_ == kThumbPart || pressed_part_ == kNoPart)
return;
@@ -185,15 +188,30 @@ void Scrollbar::AutoscrollPressedPart(double delay) {
}
// Handle the arrows and track.
- if (scrollable_area_ &&
+ bool did_scroll =
scrollable_area_
->UserScroll(PressedPartScrollGranularity(),
ToScrollDelta(PressedPartScrollDirectionPhysical(), 1))
- .DidScroll())
+ .DidScroll();
+
+ // Always start timer when user press on button since scrollable area maybe
+ // infinite scrolling.
+ if (pressed_part_ == kBackButtonStartPart ||
+ pressed_part_ == kForwardButtonStartPart ||
+ pressed_part_ == kBackButtonEndPart ||
+ pressed_part_ == kForwardButtonEndPart) {
+ StartTimerIfNeeded(delay);
+ return;
+ }
+
+ if ((pressed_part_ == kBackTrackPart || pressed_part_ == kForwardTrackPart) &&
+ did_scroll) {
StartTimerIfNeeded(delay);
+ return;
+ }
}
-void Scrollbar::StartTimerIfNeeded(double delay) {
+void Scrollbar::StartTimerIfNeeded(TimeDelta delay) {
// Don't do anything for the thumb.
if (pressed_part_ == kThumbPart)
return;
@@ -206,16 +224,6 @@ void Scrollbar::StartTimerIfNeeded(double delay) {
return;
}
- // We can't scroll if we've hit the beginning or end.
- ScrollDirectionPhysical dir = PressedPartScrollDirectionPhysical();
- if (dir == kScrollUp || dir == kScrollLeft) {
- if (current_pos_ == 0)
- return;
- } else {
- if (current_pos_ == Maximum())
- return;
- }
-
scroll_timer_.StartOneShot(delay, FROM_HERE);
}
@@ -476,7 +484,8 @@ void Scrollbar::MouseUp(const WebMouseEvent& mouse_event) {
if (scrollable_area_) {
if (is_captured)
- scrollable_area_->MouseReleasedScrollbar(orientation_);
+ scrollable_area_->MouseReleasedScrollbar();
+ scrollable_area_->SnapAfterScrollbarScrolling(orientation_);
ScrollbarPart part = GetTheme().HitTest(
*this, FlooredIntPoint(mouse_event.PositionInRootFrame()));
@@ -636,6 +645,11 @@ void Scrollbar::SetNeedsPaintInvalidation(ScrollbarPart invalid_parts) {
scrollable_area_->SetScrollbarNeedsPaintInvalidation(Orientation());
}
+CompositorElementId Scrollbar::GetElementId() {
+ DCHECK(scrollable_area_);
+ return scrollable_area_->GetScrollbarElementId(orientation_);
+}
+
STATIC_ASSERT_ENUM(kWebScrollbarOverlayColorThemeDark,
kScrollbarOverlayColorThemeDark);
STATIC_ASSERT_ENUM(kWebScrollbarOverlayColorThemeLight,
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scrollbar.h b/chromium/third_party/blink/renderer/platform/scroll/scrollbar.h
index 20eac35e4ac..780489ec217 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scrollbar.h
+++ b/chromium/third_party/blink/renderer/platform/scroll/scrollbar.h
@@ -26,6 +26,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCROLL_SCROLLBAR_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCROLL_SCROLLBAR_H_
+#include "third_party/blink/renderer/platform/graphics/compositor_element_id.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/scroll/scroll_types.h"
@@ -186,6 +187,8 @@ class PLATFORM_EXPORT Scrollbar : public GarbageCollectedFinalized<Scrollbar>,
// part.
void SetNeedsPaintInvalidation(ScrollbarPart invalid_parts);
+ CompositorElementId GetElementId();
+
// Promptly unregister from the theme manager + run finalizers of derived
// Scrollbars.
EAGERLY_FINALIZE();
@@ -200,9 +203,9 @@ class PLATFORM_EXPORT Scrollbar : public GarbageCollectedFinalized<Scrollbar>,
ScrollbarTheme* = nullptr);
void AutoscrollTimerFired(TimerBase*);
- void StartTimerIfNeeded(double delay);
+ void StartTimerIfNeeded(TimeDelta delay);
void StopTimerIfNeeded();
- void AutoscrollPressedPart(double delay);
+ void AutoscrollPressedPart(TimeDelta delay);
ScrollDirectionPhysical PressedPartScrollDirectionPhysical();
ScrollGranularity PressedPartScrollGranularity();
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_layer_delegate.cc b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_layer_delegate.cc
index 322ef7247bd..ed9bf154117 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_layer_delegate.cc
+++ b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_layer_delegate.cc
@@ -6,8 +6,11 @@
#include "third_party/blink/public/platform/web_point.h"
#include "third_party/blink/public/platform/web_rect.h"
+#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
+#include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
#include "third_party/blink/renderer/platform/scroll/scroll_types.h"
+#include "third_party/blink/renderer/platform/scroll/scrollable_area.h"
#include "third_party/blink/renderer/platform/scroll/scrollbar.h"
#include "third_party/blink/renderer/platform/scroll/scrollbar_theme.h"
#include "ui/gfx/skia_util.h"
@@ -106,6 +109,18 @@ gfx::Rect ScrollbarLayerDelegate::NinePatchThumbAperture() const {
}
bool ScrollbarLayerDelegate::HasTickmarks() const {
+ // TODO(crbug.com/860499): Remove this condition, it should not occur.
+ // Layers may exist and be painted for a |scrollbar_| that has had its
+ // ScrollableArea detached. This seems weird because if the area is detached
+ // the layer should be destroyed but here we are. https://crbug.com/860499.
+ if (!scrollbar_->GetScrollableArea())
+ return false;
+ // When the frame is throttled, the scrollbar will not be painted because
+ // the frame has not had its lifecycle updated. Thus the actual value of
+ // HasTickmarks can't be known and may change once the frame is unthrottled.
+ if (scrollbar_->GetScrollableArea()->IsThrottled())
+ return false;
+
Vector<IntRect> tickmarks;
scrollbar_->GetTickmarks(tickmarks);
return !tickmarks.IsEmpty();
@@ -117,6 +132,17 @@ void ScrollbarLayerDelegate::PaintPart(cc::PaintCanvas* canvas,
PaintCanvasAutoRestore auto_restore(canvas, true);
blink::Scrollbar& scrollbar = *scrollbar_;
+ // TODO(crbug.com/860499): Remove this condition, it should not occur.
+ // Layers may exist and be painted for a |scrollbar_| that has had its
+ // ScrollableArea detached. This seems weird because if the area is detached
+ // the layer should be destroyed but here we are.
+ if (!scrollbar_->GetScrollableArea())
+ return;
+ // When the frame is throttled, the scrollbar will not be painted because
+ // the frame has not had its lifecycle updated.
+ if (scrollbar.GetScrollableArea()->IsThrottled())
+ return;
+
if (part == cc::THUMB) {
ScopedScrollbarPainter painter(*canvas, device_scale_factor_);
theme_.PaintThumb(painter.Context(), scrollbar, IntRect(content_rect));
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_layer_delegate.h b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_layer_delegate.h
index 819ce5bd3ef..f8d52474cea 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_layer_delegate.h
+++ b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_layer_delegate.h
@@ -13,6 +13,10 @@
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/platform_export.h"
+namespace cc {
+class PaintCanvas;
+}
+
namespace blink {
class Scrollbar;
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_test_suite.h b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_test_suite.h
index 3101387404b..60224eb7367 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_test_suite.h
+++ b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_test_suite.h
@@ -49,6 +49,7 @@ class MockScrollableArea : public GarbageCollectedFinalized<MockScrollableArea>,
MOCK_CONST_METHOD0(VisualRectForScrollbarParts, LayoutRect());
MOCK_CONST_METHOD0(IsActive, bool());
+ MOCK_CONST_METHOD0(IsThrottled, bool());
MOCK_CONST_METHOD1(ScrollSize, int(ScrollbarOrientation));
MOCK_CONST_METHOD0(IsScrollCornerVisible, bool());
MOCK_CONST_METHOD0(ScrollCornerRect, IntRect());
@@ -83,9 +84,6 @@ class MockScrollableArea : public GarbageCollectedFinalized<MockScrollableArea>,
bool ScrollAnimatorEnabled() const override { return false; }
int PageStep(ScrollbarOrientation) const override { return 0; }
void ScrollControlWasSetNeedsPaintInvalidation() override {}
- void SetScrollOrigin(const IntPoint& origin) {
- ScrollableArea::SetScrollOrigin(origin);
- }
scoped_refptr<base::SingleThreadTaskRunner> GetTimerTaskRunner() const final {
return blink::scheduler::GetSingleThreadTaskRunnerForTesting();
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme.cc b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme.cc
index 4ca6b6a7dc0..a3352ccbcc3 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme.cc
+++ b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme.cc
@@ -31,7 +31,6 @@
#include "third_party/blink/public/platform/web_mouse_event.h"
#include "third_party/blink/public/platform/web_point.h"
#include "third_party/blink/public/platform/web_rect.h"
-#include "third_party/blink/public/platform/web_scrollbar_behavior.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_context_state_saver.h"
@@ -209,13 +208,6 @@ void ScrollbarTheme::PaintScrollCorner(
#endif
}
-bool ScrollbarTheme::ShouldCenterOnThumb(const Scrollbar& scrollbar,
- const WebMouseEvent& evt) {
- return Platform::Current()->ScrollbarBehavior()->ShouldCenterOnThumb(
- evt.button, evt.GetModifiers() & WebInputEvent::kShiftKey,
- evt.GetModifiers() & WebInputEvent::kAltKey);
-}
-
void ScrollbarTheme::PaintTickmarks(GraphicsContext& context,
const Scrollbar& scrollbar,
const IntRect& rect) {
@@ -260,24 +252,14 @@ void ScrollbarTheme::PaintTickmarks(GraphicsContext& context,
#endif
}
-bool ScrollbarTheme::ShouldSnapBackToDragOrigin(const Scrollbar& scrollbar,
- const WebMouseEvent& evt) {
- IntPoint mouse_position = scrollbar.ConvertFromRootFrame(
- FlooredIntPoint(evt.PositionInRootFrame()));
- mouse_position.Move(scrollbar.X(), scrollbar.Y());
- return Platform::Current()->ScrollbarBehavior()->ShouldSnapBackToDragOrigin(
- mouse_position, TrackRect(scrollbar),
- scrollbar.Orientation() == kHorizontalScrollbar);
-}
-
-double ScrollbarTheme::OverlayScrollbarFadeOutDelaySeconds() const {
+TimeDelta ScrollbarTheme::OverlayScrollbarFadeOutDelay() const {
// On Mac, fading is controlled by the painting code in ScrollAnimatorMac.
- return 0.0;
+ return TimeDelta();
}
-double ScrollbarTheme::OverlayScrollbarFadeOutDurationSeconds() const {
+TimeDelta ScrollbarTheme::OverlayScrollbarFadeOutDuration() const {
// On Mac, fading is controlled by the painting code in ScrollAnimatorMac.
- return 0.0;
+ return TimeDelta();
}
int ScrollbarTheme::ThumbPosition(const Scrollbar& scrollbar,
@@ -380,6 +362,14 @@ void ScrollbarTheme::SplitTrack(const Scrollbar& scrollbar,
}
}
+TimeDelta ScrollbarTheme::InitialAutoscrollTimerDelay() {
+ return TimeDelta::FromMilliseconds(250);
+}
+
+TimeDelta ScrollbarTheme::AutoscrollTimerDelay() {
+ return TimeDelta::FromMilliseconds(50);
+}
+
ScrollbarTheme& ScrollbarTheme::DeprecatedStaticGetTheme() {
if (ScrollbarTheme::MockScrollbarsEnabled()) {
if (RuntimeEnabledFeatures::OverlayScrollbarsEnabled()) {
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme.h b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme.h
index 5712dab6a82..d1f4289e463 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme.h
+++ b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme.h
@@ -101,9 +101,13 @@ class PLATFORM_EXPORT ScrollbarTheme {
const Scrollbar&,
const IntRect&);
- virtual bool ShouldCenterOnThumb(const Scrollbar&, const WebMouseEvent&);
+ virtual bool ShouldCenterOnThumb(const Scrollbar&, const WebMouseEvent&) {
+ return false;
+ }
virtual bool ShouldSnapBackToDragOrigin(const Scrollbar&,
- const WebMouseEvent&);
+ const WebMouseEvent&) {
+ return false;
+ }
virtual bool ShouldDragDocumentInsteadOfThumb(const Scrollbar&,
const WebMouseEvent&) {
return false;
@@ -113,8 +117,8 @@ class PLATFORM_EXPORT ScrollbarTheme {
int ThumbPosition(const Scrollbar& scrollbar) {
return ThumbPosition(scrollbar, scrollbar.CurrentPos());
}
- virtual double OverlayScrollbarFadeOutDelaySeconds() const;
- virtual double OverlayScrollbarFadeOutDurationSeconds() const;
+ virtual TimeDelta OverlayScrollbarFadeOutDelay() const;
+ virtual TimeDelta OverlayScrollbarFadeOutDuration() const;
// The position the thumb would have, relative to the track, at the specified
// scroll position.
virtual int ThumbPosition(const Scrollbar&, float scroll_position);
@@ -177,8 +181,8 @@ class PLATFORM_EXPORT ScrollbarTheme {
return std::numeric_limits<int>::max();
}
- virtual double InitialAutoscrollTimerDelay() { return 0.25; }
- virtual double AutoscrollTimerDelay() { return 0.05; }
+ virtual TimeDelta InitialAutoscrollTimerDelay();
+ virtual TimeDelta AutoscrollTimerDelay();
virtual IntRect ConstrainTrackRectToTrackPieces(const Scrollbar&,
const IntRect& rect) {
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_aura.cc b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_aura.cc
index e2797eda5c9..5b4a5f8f79d 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_aura.cc
+++ b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_aura.cc
@@ -30,9 +30,12 @@
#include "third_party/blink/renderer/platform/scroll/scrollbar_theme_aura.h"
+#include "build/build_config.h"
#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_mouse_event.h"
#include "third_party/blink/public/platform/web_rect.h"
#include "third_party/blink/public/platform/web_theme_engine.h"
+#include "third_party/blink/renderer/platform/geometry/int_rect_outsets.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/layout_test_support.h"
@@ -290,7 +293,7 @@ void ScrollbarThemeAura::PaintThumb(GraphicsContext& gc,
DrawingRecorder recorder(gc, scrollbar, DisplayItem::kScrollbarThumb);
WebThemeEngine::State state;
- WebCanvas* canvas = gc.Canvas();
+ cc::PaintCanvas* canvas = gc.Canvas();
if (scrollbar.PressedPart() == kThumbPart)
state = WebThemeEngine::kStatePressed;
else if (scrollbar.HoveredPart() == kThumbPart)
@@ -327,6 +330,58 @@ ScrollbarPart ScrollbarThemeAura::InvalidateOnThumbPositionChange(
return invalid_parts;
}
+bool ScrollbarThemeAura::ShouldCenterOnThumb(const Scrollbar& scrollbar,
+ const WebMouseEvent& event) {
+#if (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+ if (event.button == WebPointerProperties::Button::kMiddle)
+ return true;
+#endif
+ bool shift_key_pressed = event.GetModifiers() & WebInputEvent::kShiftKey;
+ return (event.button == WebPointerProperties::Button::kLeft) &&
+ shift_key_pressed;
+}
+
+bool ScrollbarThemeAura::ShouldSnapBackToDragOrigin(
+ const Scrollbar& scrollbar,
+ const WebMouseEvent& event) {
+// Disable snapback on desktop Linux to better integrate with the desktop
+// behavior. Typically, Linux apps do not implement scrollbar snapback (this is
+// true for at least GTK and QT apps).
+#if (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+ return false;
+#endif
+
+ // Constants used to figure the drag rect outside which we should snap the
+ // scrollbar thumb back to its origin. These calculations are based on
+ // observing the behavior of the MSVC8 main window scrollbar + some
+ // guessing/extrapolation.
+ static const int kOffEndMultiplier = 3;
+ static const int kOffSideMultiplier = 8;
+ static const int kDefaultWinScrollbarThickness = 17;
+
+ // Find the rect within which we shouldn't snap, by expanding the track rect
+ // in both dimensions.
+ IntRect no_snap_rect(TrackRect(scrollbar));
+ bool is_horizontal = scrollbar.Orientation() == kHorizontalScrollbar;
+ int thickness = is_horizontal ? no_snap_rect.Height() : no_snap_rect.Width();
+ // Even if the platform's scrollbar is narrower than the default Windows one,
+ // we still want to provide at least as much slop area, since a slightly
+ // narrower scrollbar doesn't necessarily imply that users will drag
+ // straighter.
+ thickness = std::max(thickness, kDefaultWinScrollbarThickness);
+ int width_outset =
+ (is_horizontal ? kOffEndMultiplier : kOffSideMultiplier) * thickness;
+ int height_outset =
+ (is_horizontal ? kOffSideMultiplier : kOffEndMultiplier) * thickness;
+ no_snap_rect.Expand(
+ IntRectOutsets(height_outset, width_outset, height_outset, width_outset));
+
+ IntPoint mouse_position = scrollbar.ConvertFromRootFrame(
+ FlooredIntPoint(event.PositionInRootFrame()));
+ mouse_position.Move(scrollbar.X(), scrollbar.Y());
+ return !no_snap_rect.Contains(mouse_position);
+}
+
bool ScrollbarThemeAura::HasScrollbarButtons(
ScrollbarOrientation orientation) const {
WebThemeEngine* theme_engine = Platform::Current()->ThemeEngine();
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_aura.h b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_aura.h
index 6ad10afea4d..2742065caeb 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_aura.h
+++ b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_aura.h
@@ -72,6 +72,10 @@ class PLATFORM_EXPORT ScrollbarThemeAura : public ScrollbarTheme {
float old_position,
float new_position) const override;
+ bool ShouldCenterOnThumb(const Scrollbar&, const WebMouseEvent&) override;
+ bool ShouldSnapBackToDragOrigin(const Scrollbar&,
+ const WebMouseEvent&) override;
+
private:
FRIEND_TEST_ALL_PREFIXES(ScrollbarThemeAuraTest, ButtonSizeHorizontal);
FRIEND_TEST_ALL_PREFIXES(ScrollbarThemeAuraTest, ButtonSizeVertical);
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_mac.h b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_mac.h
index 3372fdeb0ad..4259a28587e 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_mac.h
+++ b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_mac.h
@@ -47,7 +47,8 @@ class PLATFORM_EXPORT ScrollbarThemeMac : public ScrollbarTheme {
float autoscroll_button_delay,
NSScrollerStyle preferred_scroller_style,
bool redraw,
- WebScrollbarButtonsPlacement);
+ WebScrollbarButtonsPlacement,
+ bool jump_on_track_click);
bool SupportsControlTints() const override { return true; }
@@ -57,13 +58,15 @@ class PLATFORM_EXPORT ScrollbarThemeMac : public ScrollbarTheme {
// Mac queues up scrollbar paint timers.
bool ShouldDisableInvisibleScrollbars() const override { return false; }
- double InitialAutoscrollTimerDelay() override;
- double AutoscrollTimerDelay() override;
+ TimeDelta InitialAutoscrollTimerDelay() override;
+ TimeDelta AutoscrollTimerDelay() override;
void PaintTickmarks(GraphicsContext&,
const Scrollbar&,
const IntRect&) override;
+ bool ShouldCenterOnThumb(const Scrollbar&, const WebMouseEvent&) override;
+
bool ShouldRepaintAllPartsOnInvalidation() const override { return false; }
ScrollbarPart InvalidateOnThumbPositionChange(
const Scrollbar&,
@@ -95,6 +98,7 @@ class PLATFORM_EXPORT ScrollbarThemeMac : public ScrollbarTheme {
float ThumbOpacity(const Scrollbar&) const override;
static NSScrollerStyle RecommendedScrollerStyle();
+ static void SetJumpOnTrackClick(bool);
protected:
int MaxOverlapBetweenPages() override { return 40; }
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_mac.mm b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_mac.mm
index 0e120742828..d15d6f2630f 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_mac.mm
+++ b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_mac.mm
@@ -106,6 +106,7 @@ static ScrollbarSet& GetScrollbarSet() {
static float g_initial_button_delay = 0.5f;
static float g_autoscroll_button_delay = 0.05f;
static NSScrollerStyle g_preferred_scroller_style = NSScrollerStyleLegacy;
+static bool g_jump_on_track_click = false;
typedef PersistentHeapHashMap<WeakMember<Scrollbar>,
RetainPtr<BlinkScrollbarObserver>>
@@ -139,6 +140,13 @@ void ScrollbarThemeMac::PaintTickmarks(GraphicsContext& context,
ScrollbarTheme::PaintTickmarks(context, scrollbar, tickmark_track_rect);
}
+bool ScrollbarThemeMac::ShouldCenterOnThumb(const Scrollbar& scrollbar,
+ const WebMouseEvent& event) {
+ bool alt_key_pressed = event.GetModifiers() & WebInputEvent::kAltKey;
+ return (event.button == WebPointerProperties::Button::kLeft) &&
+ (g_jump_on_track_click != alt_key_pressed);
+}
+
ScrollbarThemeMac::~ScrollbarThemeMac() {}
void ScrollbarThemeMac::PreferencesChanged(
@@ -146,11 +154,13 @@ void ScrollbarThemeMac::PreferencesChanged(
float autoscroll_button_delay,
NSScrollerStyle preferred_scroller_style,
bool redraw,
- WebScrollbarButtonsPlacement button_placement) {
+ WebScrollbarButtonsPlacement button_placement,
+ bool jump_on_track_click) {
UpdateButtonPlacement(button_placement);
g_initial_button_delay = initial_button_delay;
g_autoscroll_button_delay = autoscroll_button_delay;
g_preferred_scroller_style = preferred_scroller_style;
+ g_jump_on_track_click = jump_on_track_click;
if (redraw && !GetScrollbarSet().IsEmpty()) {
for (const auto& scrollbar : GetScrollbarSet()) {
scrollbar->StyleChanged();
@@ -159,12 +169,12 @@ void ScrollbarThemeMac::PreferencesChanged(
}
}
-double ScrollbarThemeMac::InitialAutoscrollTimerDelay() {
- return g_initial_button_delay;
+TimeDelta ScrollbarThemeMac::InitialAutoscrollTimerDelay() {
+ return TimeDelta::FromSecondsD(g_initial_button_delay);
}
-double ScrollbarThemeMac::AutoscrollTimerDelay() {
- return g_autoscroll_button_delay;
+TimeDelta ScrollbarThemeMac::AutoscrollTimerDelay() {
+ return TimeDelta::FromSecondsD(g_autoscroll_button_delay);
}
bool ScrollbarThemeMac::ShouldDragDocumentInsteadOfThumb(
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_overlay.cc b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_overlay.cc
index 5d5a07aa083..33121af31c5 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_overlay.cc
+++ b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_overlay.cc
@@ -82,25 +82,25 @@ bool ScrollbarThemeOverlay::UsesOverlayScrollbars() const {
return true;
}
-double ScrollbarThemeOverlay::OverlayScrollbarFadeOutDelaySeconds() const {
+TimeDelta ScrollbarThemeOverlay::OverlayScrollbarFadeOutDelay() const {
// TODO(bokan): Unit tests run without a theme engine. This is normally fine
// because they expect to use ScrollbarThemeMock which doesn't use a theme
// engine. If overlays are turned on though, this class is used even if mock
// scrollbars are on. We should either provide mock out a web theme engine for
// unit tests or provide a mock version of this class.
if (!Platform::Current()->ThemeEngine())
- return 0.0;
+ return TimeDelta();
WebThemeEngine::ScrollbarStyle style;
Platform::Current()->ThemeEngine()->GetOverlayScrollbarStyle(&style);
- return style.fade_out_delay_seconds;
+ return style.fade_out_delay;
}
-double ScrollbarThemeOverlay::OverlayScrollbarFadeOutDurationSeconds() const {
+TimeDelta ScrollbarThemeOverlay::OverlayScrollbarFadeOutDuration() const {
if (!Platform::Current()->ThemeEngine())
- return 0.0;
+ return TimeDelta();
WebThemeEngine::ScrollbarStyle style;
Platform::Current()->ThemeEngine()->GetOverlayScrollbarStyle(&style);
- return style.fade_out_duration_seconds;
+ return style.fade_out_duration;
}
int ScrollbarThemeOverlay::ThumbLength(const Scrollbar& scrollbar) {
@@ -178,7 +178,7 @@ void ScrollbarThemeOverlay::PaintThumb(GraphicsContext& context,
else if (scrollbar.HoveredPart() == kThumbPart)
state = WebThemeEngine::kStateHover;
- WebCanvas* canvas = context.Canvas();
+ cc::PaintCanvas* canvas = context.Canvas();
WebThemeEngine::Part part = WebThemeEngine::kPartScrollbarHorizontalThumb;
if (scrollbar.Orientation() == kVerticalScrollbar)
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_overlay.h b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_overlay.h
index 18c4748c0e5..b36d9ccc594 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_overlay.h
+++ b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_overlay.h
@@ -56,8 +56,8 @@ class PLATFORM_EXPORT ScrollbarThemeOverlay : public ScrollbarTheme {
int ScrollbarThickness(ScrollbarControlSize) override;
int ScrollbarMargin() const override;
bool UsesOverlayScrollbars() const override;
- double OverlayScrollbarFadeOutDelaySeconds() const override;
- double OverlayScrollbarFadeOutDurationSeconds() const override;
+ TimeDelta OverlayScrollbarFadeOutDelay() const override;
+ TimeDelta OverlayScrollbarFadeOutDuration() const override;
int ThumbLength(const Scrollbar&) override;
diff --git a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_overlay_mock.h b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_overlay_mock.h
index d27b0dc4cd2..0a38a31ca9c 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_overlay_mock.h
+++ b/chromium/third_party/blink/renderer/platform/scroll/scrollbar_theme_overlay_mock.h
@@ -38,17 +38,14 @@ namespace blink {
class PLATFORM_EXPORT ScrollbarThemeOverlayMock : public ScrollbarThemeOverlay {
public:
ScrollbarThemeOverlayMock()
- : ScrollbarThemeOverlay(3, 4, kDisallowHitTest, Color(128, 128, 128)),
- delay_in_seconds_(0.0) {}
+ : ScrollbarThemeOverlay(3, 4, kDisallowHitTest, Color(128, 128, 128)) {}
- double OverlayScrollbarFadeOutDelaySeconds() const override {
- return delay_in_seconds_;
+ TimeDelta OverlayScrollbarFadeOutDelay() const override { return delay_; }
+ TimeDelta OverlayScrollbarFadeOutDuration() const override {
+ return TimeDelta();
}
- double OverlayScrollbarFadeOutDurationSeconds() const override { return 0.0; }
- void SetOverlayScrollbarFadeOutDelay(double delay_in_seconds) {
- delay_in_seconds_ = delay_in_seconds;
- }
+ void SetOverlayScrollbarFadeOutDelay(TimeDelta delay) { delay_ = delay; }
void PaintThumb(GraphicsContext& gc,
const Scrollbar& scrollbar,
@@ -66,7 +63,7 @@ class PLATFORM_EXPORT ScrollbarThemeOverlayMock : public ScrollbarThemeOverlay {
int MinimumThumbLength(const Scrollbar&) override { return 7; }
private:
- double delay_in_seconds_;
+ TimeDelta delay_;
bool IsMockTheme() const final { return true; }
};
diff --git a/chromium/third_party/blink/renderer/platform/scroll/web_scrollbar_theme.mm b/chromium/third_party/blink/renderer/platform/scroll/web_scrollbar_theme.mm
index 4494a7d709d..d55393282ae 100644
--- a/chromium/third_party/blink/renderer/platform/scroll/web_scrollbar_theme.mm
+++ b/chromium/third_party/blink/renderer/platform/scroll/web_scrollbar_theme.mm
@@ -49,7 +49,8 @@ void WebScrollbarTheme::UpdateScrollbarsWithNSDefaults(
float autoscroll_button_delay,
ScrollerStyle preferred_scroller_style,
bool redraw,
- WebScrollbarButtonsPlacement button_placement) {
+ WebScrollbarButtonsPlacement button_placement,
+ bool jump_on_track_click) {
ScrollbarTheme& theme = ScrollbarTheme::DeprecatedStaticGetTheme();
if (theme.IsMockTheme())
return;
@@ -57,7 +58,7 @@ void WebScrollbarTheme::UpdateScrollbarsWithNSDefaults(
static_cast<ScrollbarThemeMac&>(theme).PreferencesChanged(
initial_button_delay, autoscroll_button_delay,
static_cast<NSScrollerStyle>(preferred_scroller_style), redraw,
- button_placement);
+ button_placement, jump_on_track_click);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/shared_buffer.cc b/chromium/third_party/blink/renderer/platform/shared_buffer.cc
index c9702bfbca7..7925b3f9f08 100644
--- a/chromium/third_party/blink/renderer/platform/shared_buffer.cc
+++ b/chromium/third_party/blink/renderer/platform/shared_buffer.cc
@@ -26,6 +26,8 @@
#include "third_party/blink/renderer/platform/shared_buffer.h"
+#include <memory>
+
#include "third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h"
#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
#include "third_party/blink/renderer/platform/wtf/text/utf8.h"
@@ -33,6 +35,8 @@
namespace blink {
+constexpr unsigned SharedBuffer::kSegmentSize;
+
static inline size_t SegmentIndex(size_t position) {
return position / SharedBuffer::kSegmentSize;
}
@@ -41,13 +45,68 @@ static inline size_t OffsetInSegment(size_t position) {
return position % SharedBuffer::kSegmentSize;
}
-static inline char* AllocateSegment() {
- return static_cast<char*>(WTF::Partitions::FastMalloc(
- SharedBuffer::kSegmentSize, "blink::SharedBuffer"));
+class SharedBuffer::Segment final {
+ public:
+ Segment() {
+ ptr_.reset(static_cast<char*>(WTF::Partitions::FastMalloc(
+ SharedBuffer::kSegmentSize, "blink::SharedBuffer")));
+ }
+ ~Segment() = default;
+ Segment(Segment&&) = default;
+
+ char* get() { return ptr_.get(); }
+ const char* get() const { return ptr_.get(); }
+
+ private:
+ struct Deleter {
+ void operator()(char* p) const { WTF::Partitions::FastFree(p); }
+ };
+ std::unique_ptr<char[], Deleter> ptr_;
+};
+
+SharedBuffer::Iterator& SharedBuffer::Iterator::operator++() {
+ DCHECK(!IsEnd());
+ ++index_;
+ Init(0);
+ return *this;
+}
+
+SharedBuffer::Iterator::Iterator(const SharedBuffer* buffer)
+ : index_(buffer->segments_.size() + 1), buffer_(buffer) {
+ DCHECK(IsEnd());
+}
+
+SharedBuffer::Iterator::Iterator(size_t offset, const SharedBuffer* buffer)
+ : index_(0), buffer_(buffer) {
+ Init(offset);
+}
+
+SharedBuffer::Iterator::Iterator(size_t segment_index,
+ size_t offset,
+ const SharedBuffer* buffer)
+ : index_(segment_index + 1), buffer_(buffer) {
+ Init(offset);
}
-static inline void FreeSegment(char* p) {
- WTF::Partitions::FastFree(p);
+void SharedBuffer::Iterator::Init(size_t offset) {
+ if (IsEnd()) {
+ value_ = base::span<const char>();
+ return;
+ }
+
+ if (index_ == 0) {
+ DCHECK_LT(offset, buffer_->buffer_.size());
+ value_ = base::make_span(buffer_->buffer_.data() + offset,
+ buffer_->buffer_.size() - offset);
+ return;
+ }
+ const auto segment_index = index_ - 1;
+ const auto& segment = buffer_->segments_[segment_index];
+ size_t segment_size = segment_index == buffer_->segments_.size() - 1
+ ? buffer_->GetLastSegmentSize()
+ : kSegmentSize;
+ DCHECK_LT(offset, segment_size);
+ value_ = base::make_span(segment.get() + offset, segment_size - offset);
}
SharedBuffer::SharedBuffer() : size_(0) {}
@@ -61,9 +120,7 @@ SharedBuffer::SharedBuffer(const char* data, size_t size) : size_(size) {
SharedBuffer::SharedBuffer(const unsigned char* data, size_t size)
: SharedBuffer(reinterpret_cast<const char*>(data), size) {}
-SharedBuffer::~SharedBuffer() {
- Clear();
-}
+SharedBuffer::~SharedBuffer() = default;
scoped_refptr<SharedBuffer> SharedBuffer::AdoptVector(Vector<char>& vector) {
scoped_refptr<SharedBuffer> buffer = Create();
@@ -72,22 +129,14 @@ scoped_refptr<SharedBuffer> SharedBuffer::AdoptVector(Vector<char>& vector) {
return buffer;
}
-size_t SharedBuffer::size() const {
- return size_;
-}
-
-const char* SharedBuffer::Data() const {
+const char* SharedBuffer::Data() {
MergeSegmentsIntoBuffer();
return buffer_.data();
}
void SharedBuffer::Append(const SharedBuffer& data) {
- const char* segment;
- size_t position = 0;
- while (size_t length = data.GetSomeDataInternal(segment, position)) {
- Append(segment, length);
- position += length;
- }
+ for (const auto& span : data)
+ Append(span.data(), span.size());
}
void SharedBuffer::AppendInternal(const char* data, size_t length) {
@@ -104,142 +153,80 @@ void SharedBuffer::AppendInternal(const char* data, size_t length) {
return;
}
- char* segment;
- if (!position_in_segment) {
- segment = AllocateSegment();
- segments_.push_back(segment);
- } else
- segment = segments_.back() + position_in_segment;
+ while (length > 0) {
+ if (!position_in_segment)
+ segments_.push_back(Segment());
- size_t segment_free_space = kSegmentSize - position_in_segment;
- size_t bytes_to_copy = std::min(length, segment_free_space);
+ size_t bytes_to_copy = std::min(length, kSegmentSize - position_in_segment);
+ memcpy(segments_.back().get() + position_in_segment, data, bytes_to_copy);
- for (;;) {
- memcpy(segment, data, bytes_to_copy);
- if (length == bytes_to_copy)
- break;
-
- length -= bytes_to_copy;
data += bytes_to_copy;
- segment = AllocateSegment();
- segments_.push_back(segment);
- bytes_to_copy = std::min(length, static_cast<size_t>(kSegmentSize));
+ length -= bytes_to_copy;
+ position_in_segment = 0;
}
}
-void SharedBuffer::Append(const Vector<char>& data) {
- Append(data.data(), data.size());
-}
-
void SharedBuffer::Clear() {
- for (size_t i = 0; i < segments_.size(); ++i)
- FreeSegment(segments_[i]);
-
segments_.clear();
size_ = 0;
buffer_.clear();
}
-Vector<char> SharedBuffer::Copy() const {
- Vector<char> buffer;
- buffer.ReserveInitialCapacity(size_);
-
- ForEachSegment([&buffer](const char* segment, size_t segment_size,
- size_t segment_offset) -> bool {
- buffer.Append(segment, segment_size);
- return true;
- });
+SharedBuffer::Iterator SharedBuffer::begin() const {
+ return GetIteratorAt(static_cast<size_t>(0));
+}
- DCHECK_EQ(buffer.size(), size_);
- return buffer;
+SharedBuffer::Iterator SharedBuffer::end() const {
+ return Iterator(this);
}
-void SharedBuffer::MergeSegmentsIntoBuffer() const {
- size_t buffer_size = buffer_.size();
- if (size_ > buffer_size) {
- size_t bytes_left = size_ - buffer_size;
- for (size_t i = 0; i < segments_.size(); ++i) {
- size_t bytes_to_copy =
- std::min(bytes_left, static_cast<size_t>(kSegmentSize));
- buffer_.Append(segments_[i], bytes_to_copy);
- bytes_left -= bytes_to_copy;
- FreeSegment(segments_[i]);
- }
- segments_.clear();
+void SharedBuffer::MergeSegmentsIntoBuffer() {
+ size_t bytes_left = size_ - buffer_.size();
+ for (const auto& segment : segments_) {
+ size_t bytes_to_copy = std::min<size_t>(bytes_left, kSegmentSize);
+ buffer_.Append(segment.get(), bytes_to_copy);
+ bytes_left -= bytes_to_copy;
}
+ segments_.clear();
}
-size_t SharedBuffer::GetSomeDataInternal(const char*& some_data,
- size_t position) const {
- size_t total_size = size();
- if (position >= total_size) {
- some_data = nullptr;
- return 0;
- }
+SharedBuffer::Iterator SharedBuffer::GetIteratorAtInternal(
+ size_t position) const {
+ if (position >= size())
+ return cend();
- SECURITY_DCHECK(position < size_);
- size_t consecutive_size = buffer_.size();
- if (position < consecutive_size) {
- some_data = buffer_.data() + position;
- return consecutive_size - position;
- }
+ if (position < buffer_.size())
+ return Iterator(position, this);
- position -= consecutive_size;
- size_t segments = segments_.size();
- size_t max_segmented_size = segments * kSegmentSize;
- size_t segment = SegmentIndex(position);
- if (segment < segments) {
- size_t bytes_left = total_size - consecutive_size;
- size_t segmented_size = std::min(max_segmented_size, bytes_left);
-
- size_t position_in_segment = OffsetInSegment(position);
- some_data = segments_[segment] + position_in_segment;
- return segment == segments - 1 ? segmented_size - position
- : kSegmentSize - position_in_segment;
- }
- NOTREACHED();
- return 0;
+ return Iterator(SegmentIndex(position - buffer_.size()),
+ OffsetInSegment(position - buffer_.size()), this);
}
-bool SharedBuffer::GetBytesInternal(void* dest, size_t byte_length) const {
+bool SharedBuffer::GetBytesInternal(void* dest, size_t dest_size) const {
if (!dest)
return false;
- const char* segment = nullptr;
- size_t load_position = 0;
- size_t write_position = 0;
- while (byte_length > 0) {
- size_t load_size = GetSomeDataInternal(segment, load_position);
- if (load_size == 0)
+ size_t offset = 0;
+ for (const auto& span : *this) {
+ if (offset >= dest_size)
break;
-
- if (byte_length < load_size)
- load_size = byte_length;
- memcpy(static_cast<char*>(dest) + write_position, segment, load_size);
- load_position += load_size;
- write_position += load_size;
- byte_length -= load_size;
+ size_t to_be_written = std::min(span.size(), dest_size - offset);
+ memcpy(static_cast<char*>(dest) + offset, span.data(), to_be_written);
+ offset += to_be_written;
}
-
- return byte_length == 0;
+ return offset == dest_size;
}
sk_sp<SkData> SharedBuffer::GetAsSkData() const {
- size_t buffer_length = size();
- sk_sp<SkData> data = SkData::MakeUninitialized(buffer_length);
+ sk_sp<SkData> data = SkData::MakeUninitialized(size());
char* buffer = static_cast<char*>(data->writable_data());
- const char* segment = nullptr;
- size_t position = 0;
- while (size_t segment_size = GetSomeDataInternal(segment, position)) {
- memcpy(buffer + position, segment, segment_size);
- position += segment_size;
+ size_t offset = 0;
+ for (const auto& span : *this) {
+ memcpy(buffer + offset, span.data(), span.size());
+ offset += span.size();
}
- if (position != buffer_length) {
- NOTREACHED();
- // Don't return the incomplete SkData.
- return nullptr;
- }
+ DCHECK_EQ(offset, size());
return data;
}
@@ -275,11 +262,8 @@ SharedBuffer::DeprecatedFlatData::DeprecatedFlatData(
// Merge all segments.
flat_buffer_.ReserveInitialCapacity(buffer_->size());
- buffer_->ForEachSegment([this](const char* segment, size_t segment_size,
- size_t segment_offset) -> bool {
- flat_buffer_.Append(segment, segment_size);
- return true;
- });
+ for (const auto& span : *buffer_)
+ flat_buffer_.Append(span.data(), span.size());
data_ = flat_buffer_.data();
}
diff --git a/chromium/third_party/blink/renderer/platform/shared_buffer.h b/chromium/third_party/blink/renderer/platform/shared_buffer.h
index c73c303c7c4..3bd98712d68 100644
--- a/chromium/third_party/blink/renderer/platform/shared_buffer.h
+++ b/chromium/third_party/blink/renderer/platform/shared_buffer.h
@@ -27,6 +27,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SHARED_BUFFER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SHARED_BUFFER_H_
+#include <utility>
+#include <vector>
+
+#include "base/containers/span.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
@@ -43,7 +47,52 @@ class WebProcessMemoryDump;
class PLATFORM_EXPORT SharedBuffer : public RefCounted<SharedBuffer> {
public:
- enum : unsigned { kSegmentSize = 0x1000 };
+ // Iterator for ShreadBuffer contents. An Iterator will get invalid once the
+ // associated SharedBuffer is modified (e.g., Append() is called). An Iterator
+ // doesn't retain the associated container.
+ class PLATFORM_EXPORT Iterator final {
+ public:
+ ~Iterator() = default;
+
+ Iterator& operator++();
+ Iterator operator++(int) {
+ auto temp = *this;
+ ++*this;
+ return temp;
+ }
+ bool operator==(const Iterator& that) const {
+ return value_ == that.value_ && buffer_ == that.buffer_;
+ }
+ bool operator!=(const Iterator& that) const { return !(*this == that); }
+ const base::span<const char>& operator*() const {
+ DCHECK(!IsEnd());
+ return value_;
+ }
+ const base::span<const char>* operator->() const {
+ DCHECK(!IsEnd());
+ return &value_;
+ }
+
+ private:
+ friend class SharedBuffer;
+ // for end()
+ Iterator(const SharedBuffer* buffer);
+ // for the consecutive part
+ Iterator(size_t offset, const SharedBuffer* buffer);
+ // for the rest
+ Iterator(size_t segment_index, size_t offset, const SharedBuffer* buffer);
+
+ void Init(size_t offset);
+ bool IsEnd() const { return index_ == buffer_->segments_.size() + 1; }
+
+ // It represents |buffer_->buffer| if |index_| is 0, and
+ // |buffer_->segments[index_ - 1]| otherwise.
+ size_t index_;
+ base::span<const char> value_;
+ const SharedBuffer* buffer_;
+ };
+
+ static constexpr unsigned kSegmentSize = 0x1000;
static scoped_refptr<SharedBuffer> Create() {
return base::AdoptRef(new SharedBuffer);
@@ -73,14 +122,13 @@ class PLATFORM_EXPORT SharedBuffer : public RefCounted<SharedBuffer> {
~SharedBuffer();
- // DEPRECATED: use a segment iterator, FlatData or Copy() instead.
+ // DEPRECATED: use a segment iterator, FlatData or explicit Copy() instead.
//
// Calling this function will force internal segmented buffers to be merged
- // into a flat buffer. Use getSomeData() whenever possible for better
- // performance.
- const char* Data() const;
+ // into a flat buffer. Use iterator whenever possible for better performance.
+ const char* Data();
- size_t size() const;
+ size_t size() const { return size_; }
bool IsEmpty() const { return !size(); }
@@ -91,32 +139,27 @@ class PLATFORM_EXPORT SharedBuffer : public RefCounted<SharedBuffer> {
ALLOW_NUMERIC_ARG_TYPES_PROMOTABLE_TO(size_t);
AppendInternal(data, size);
}
- void Append(const Vector<char>&);
+ void Append(const Vector<char>& data) { Append(data.data(), data.size()); }
void Clear();
+ Iterator begin() const;
+ Iterator cbegin() const { return begin(); }
+ Iterator end() const;
+ Iterator cend() const { return end(); }
+
// Copies the segmented data into a contiguous buffer. Use GetSomeData() or
- // ForEachSegment() whenever possible, as they are cheaper.
- Vector<char> Copy() const;
-
- // Return the number of consecutive bytes after "position". "data"
- // points to the first byte.
- // Return 0 when no more data left.
- // When extracting all data with getSomeData(), the caller should
- // repeat calling it until it returns 0.
- // Usage:
- // const char* segment;
- // size_t pos = 0;
- // while (size_t length = sharedBuffer->getSomeData(segment, pos)) {
- // // Use the data. for example: decoder->decode(segment, length);
- // pos += length;
- // }
+ // iterators if a copy is not required, as they are cheaper.
+ // Supported Ts: WTF::Vector<char>, std::vector<char>.
+ template <typename T>
+ T CopyAs() const;
+
+ // Returns an iterator for the given position of bytes. Returns |cend()| if
+ // |position| is greater than or equal to |size()|.
HAS_STRICTLY_TYPED_ARG
- size_t GetSomeData(
- const char*& data,
- STRICTLY_TYPED_ARG(position) = static_cast<size_t>(0)) const {
+ Iterator GetIteratorAt(STRICTLY_TYPED_ARG(position)) const {
STRICT_ARG_TYPE(size_t);
- return GetSomeDataInternal(data, position);
+ return GetIteratorAtInternal(position);
}
// Copies |byteLength| bytes from the beginning of the content data into
@@ -135,25 +178,6 @@ class PLATFORM_EXPORT SharedBuffer : public RefCounted<SharedBuffer> {
void OnMemoryDump(const String& dump_prefix, WebProcessMemoryDump*) const;
- // Helper for applying a lambda to all data segments, sequentially:
- //
- // bool func(const char* segment, size_t segment_size,
- // size_t segment_offset);
- //
- // The iterator stops early when the lambda returns |false|.
- //
- template <typename Func>
- void ForEachSegment(Func&& func) const {
- const char* segment;
- size_t pos = 0;
-
- while (size_t length = GetSomeData(segment, pos)) {
- if (!func(segment, length, pos))
- break;
- pos += length;
- }
- }
-
// Helper for providing a contiguous view of the data. If the SharedBuffer is
// segmented, this will copy/merge all segments into a temporary buffer.
// In general, clients should use the efficient/segmented accessors.
@@ -173,23 +197,54 @@ class PLATFORM_EXPORT SharedBuffer : public RefCounted<SharedBuffer> {
};
private:
+ class Segment;
+
SharedBuffer();
explicit SharedBuffer(size_t);
SharedBuffer(const char*, size_t);
SharedBuffer(const unsigned char*, size_t);
// See SharedBuffer::data().
- void MergeSegmentsIntoBuffer() const;
+ void MergeSegmentsIntoBuffer();
void AppendInternal(const char* data, size_t);
bool GetBytesInternal(void* dest, size_t) const;
- size_t GetSomeDataInternal(const char*& data, size_t position) const;
+ Iterator GetIteratorAtInternal(size_t position) const;
+ size_t GetLastSegmentSize() const {
+ DCHECK(!segments_.IsEmpty());
+ return (size_ - buffer_.size() + kSegmentSize - 1) % kSegmentSize + 1;
+ }
size_t size_;
- mutable Vector<char> buffer_;
- mutable Vector<char*> segments_;
+ Vector<char> buffer_;
+ Vector<Segment> segments_;
};
+// Current CopyAs specializations.
+template <>
+inline Vector<char> SharedBuffer::CopyAs() const {
+ Vector<char> buffer;
+ buffer.ReserveInitialCapacity(size_);
+
+ for (const auto& span : *this)
+ buffer.Append(span.data(), span.size());
+
+ DCHECK_EQ(buffer.size(), size_);
+ return buffer;
+}
+
+template <>
+inline std::vector<char> SharedBuffer::CopyAs() const {
+ std::vector<char> buffer;
+ buffer.reserve(size_);
+
+ for (const auto& span : *this)
+ buffer.insert(buffer.end(), span.data(), span.data() + span.size());
+
+ DCHECK_EQ(buffer.size(), size_);
+ return buffer;
+}
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SHARED_BUFFER_H_
diff --git a/chromium/third_party/blink/renderer/platform/shared_buffer_chunk_reader.cc b/chromium/third_party/blink/renderer/platform/shared_buffer_chunk_reader.cc
index f0664e46752..a31a7f4aed7 100644
--- a/chromium/third_party/blink/renderer/platform/shared_buffer_chunk_reader.cc
+++ b/chromium/third_party/blink/renderer/platform/shared_buffer_chunk_reader.cc
@@ -98,13 +98,17 @@ bool SharedBufferChunkReader::NextChunk(Vector<char>& chunk,
// Read the next segment.
segment_index_ = 0;
buffer_position_ += segment_length_;
- segment_length_ = buffer_->GetSomeData(segment_, buffer_position_);
- if (!segment_length_) {
+ auto it = buffer_->GetIteratorAt(buffer_position_);
+ if (it == buffer_->cend()) {
+ segment_ = nullptr;
+ segment_length_ = 0;
reached_end_of_file_ = true;
if (separator_index_ > 0)
chunk.Append(separator_.data(), separator_index_);
return !chunk.IsEmpty();
}
+ segment_ = it->data();
+ segment_length_ = it->size();
}
NOTREACHED();
return false;
@@ -132,18 +136,15 @@ size_t SharedBufferChunkReader::Peek(Vector<char>& data,
size_t read_bytes_count = segment_length_ - segment_index_;
data.Append(segment_ + segment_index_, read_bytes_count);
- size_t buffer_position = buffer_position_ + segment_length_;
- const char* segment = nullptr;
- while (size_t segment_length =
- buffer_->GetSomeData(segment, buffer_position)) {
- if (requested_size <= read_bytes_count + segment_length) {
- data.Append(segment, requested_size - read_bytes_count);
+ for (auto it = buffer_->GetIteratorAt(buffer_position_ + segment_length_);
+ it != buffer_->cend(); ++it) {
+ if (requested_size <= read_bytes_count + it->size()) {
+ data.Append(it->data(), requested_size - read_bytes_count);
read_bytes_count += (requested_size - read_bytes_count);
break;
}
- data.Append(segment, segment_length);
- read_bytes_count += segment_length;
- buffer_position += segment_length;
+ data.Append(it->data(), it->size());
+ read_bytes_count += it->size();
}
return read_bytes_count;
}
diff --git a/chromium/third_party/blink/renderer/platform/shared_buffer_test.cc b/chromium/third_party/blink/renderer/platform/shared_buffer_test.cc
index 9edcb6a99e2..560212007de 100644
--- a/chromium/third_party/blink/renderer/platform/shared_buffer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/shared_buffer_test.cc
@@ -132,9 +132,9 @@ TEST(SharedBufferTest, copy) {
// copy().
ASSERT_EQ(length * 4, shared_buffer->size());
- Vector<char> clone = shared_buffer->Copy();
+ Vector<char> clone = shared_buffer->CopyAs<Vector<char>>();
ASSERT_EQ(length * 4, clone.size());
- const Vector<char> contiguous = shared_buffer->Copy();
+ const Vector<char> contiguous = shared_buffer->CopyAs<Vector<char>>();
ASSERT_EQ(contiguous.size(), shared_buffer->size());
ASSERT_EQ(0, memcmp(clone.data(), contiguous.data(), clone.size()));
@@ -148,9 +148,10 @@ TEST(SharedBufferTest, constructorWithSizeOnly) {
ASSERT_EQ(length, shared_buffer->size());
// The internal flat buffer should have been resized to |length| therefore
- // getSomeData() should directly return the full size.
- const char* data;
- ASSERT_EQ(length, shared_buffer->GetSomeData(data, static_cast<size_t>(0u)));
+ // the buffer consists of one big buffer.
+ const auto it = shared_buffer->cbegin();
+ ASSERT_NE(it, shared_buffer->cend());
+ ASSERT_EQ(length, it->size());
}
TEST(SharedBufferTest, constructorWithFlatData) {
@@ -161,12 +162,10 @@ TEST(SharedBufferTest, constructorWithFlatData) {
auto shared_buffer = SharedBuffer::Create(data.begin(), data.size());
Vector<Vector<char>> segments;
- shared_buffer->ForEachSegment(
- [&segments](const char* segment, size_t segment_size, size_t) -> bool {
- segments.emplace_back();
- segments.back().Append(segment, segment_size);
- return true;
- });
+ for (const auto& span : *shared_buffer) {
+ segments.emplace_back();
+ segments.back().Append(span.data(), span.size());
+ }
// Shared buffers constructed from flat data should stay flat.
ASSERT_EQ(segments.size(), 1ul);
@@ -180,18 +179,16 @@ TEST(SharedBufferTest, FlatData) {
const SharedBuffer::DeprecatedFlatData flat_buffer(shared_buffer);
EXPECT_EQ(shared_buffer->size(), flat_buffer.size());
- shared_buffer->ForEachSegment([&flat_buffer](
- const char* segment, size_t segment_size,
- size_t segment_offset) -> bool {
- EXPECT_EQ(
- memcmp(segment, flat_buffer.Data() + segment_offset, segment_size),
- 0);
+ size_t offset = 0;
+ for (const auto& span : *shared_buffer) {
+ EXPECT_EQ(memcmp(span.data(), flat_buffer.Data() + offset, span.size()),
+ 0);
+ offset += span.size();
// If the SharedBuffer is not segmented, FlatData doesn't copy any data.
- EXPECT_EQ(segment_size == flat_buffer.size(),
- segment == flat_buffer.Data());
- return true;
- });
+ EXPECT_EQ(span.size() == flat_buffer.size(),
+ span.data() == flat_buffer.Data());
+ }
};
scoped_refptr<SharedBuffer> shared_buffer = SharedBuffer::Create();
@@ -203,4 +200,201 @@ TEST(SharedBufferTest, FlatData) {
}
}
+TEST(SharedBufferTest, GetIteratorAt) {
+ Vector<char> data(SharedBuffer::kSegmentSize + 256);
+ std::generate(data.begin(), data.end(), &std::rand);
+ auto buffer = SharedBuffer::Create();
+ buffer->Append(data.data(), static_cast<size_t>(127));
+ buffer->Append(data.data() + 127, data.size() - 127);
+
+ const auto it0 = buffer->GetIteratorAt(static_cast<size_t>(0));
+ EXPECT_EQ(it0, buffer->cbegin());
+ ASSERT_NE(it0, buffer->cend());
+ ASSERT_EQ(it0->size(), 127u);
+ EXPECT_EQ(0, memcmp(it0->data(), data.data(), it0->size()));
+
+ const auto it1 = buffer->GetIteratorAt(static_cast<size_t>(1));
+ EXPECT_NE(it1, buffer->cbegin());
+ ASSERT_NE(it1, buffer->cend());
+ ASSERT_EQ(it1->size(), 126u);
+ EXPECT_EQ(0, memcmp(it1->data(), data.data() + 1, it1->size()));
+
+ const auto it126 = buffer->GetIteratorAt(static_cast<size_t>(126));
+ EXPECT_NE(it126, buffer->cbegin());
+ ASSERT_NE(it126, buffer->cend());
+ ASSERT_EQ(it126->size(), 1u);
+ EXPECT_EQ(0, memcmp(it126->data(), data.data() + 126, it126->size()));
+
+ const auto it127 = buffer->GetIteratorAt(static_cast<size_t>(127));
+ EXPECT_NE(it127, buffer->cbegin());
+ ASSERT_NE(it127, buffer->cend());
+ ASSERT_EQ(it127->size(), SharedBuffer::kSegmentSize);
+ EXPECT_EQ(0, memcmp(it127->data(), data.data() + 127, it127->size()));
+
+ const auto it128 = buffer->GetIteratorAt(static_cast<size_t>(128));
+ EXPECT_NE(it128, buffer->cbegin());
+ ASSERT_NE(it128, buffer->cend());
+ ASSERT_EQ(it128->size(), SharedBuffer::kSegmentSize - 1);
+ EXPECT_EQ(0, memcmp(it128->data(), data.data() + 128, it128->size()));
+
+ const auto it4222 = buffer->GetIteratorAt(static_cast<size_t>(4222));
+ EXPECT_NE(it4222, buffer->cbegin());
+ ASSERT_NE(it4222, buffer->cend());
+ ASSERT_EQ(it4222->size(), 1u);
+ EXPECT_EQ(0, memcmp(it4222->data(), data.data() + 4222, it4222->size()));
+
+ const auto it4223 = buffer->GetIteratorAt(static_cast<size_t>(4223));
+ EXPECT_NE(it4223, buffer->cbegin());
+ ASSERT_NE(it4223, buffer->cend());
+ ASSERT_EQ(it4223->size(), 129u);
+ EXPECT_EQ(0, memcmp(it4223->data(), data.data() + 4223, it4223->size()));
+
+ const auto it4224 = buffer->GetIteratorAt(static_cast<size_t>(4224));
+ EXPECT_NE(it4224, buffer->cbegin());
+ ASSERT_NE(it4224, buffer->cend());
+ ASSERT_EQ(it4224->size(), 128u);
+ EXPECT_EQ(0, memcmp(it4224->data(), data.data() + 4224, it4224->size()));
+
+ const auto it4351 = buffer->GetIteratorAt(static_cast<size_t>(4351));
+ EXPECT_NE(it4351, buffer->cbegin());
+ ASSERT_NE(it4351, buffer->cend());
+ ASSERT_EQ(it4351->size(), 1u);
+ EXPECT_EQ(0, memcmp(it4351->data(), data.data() + 4351, it4351->size()));
+
+ // All of the iterators above are different each other.
+ const SharedBuffer::Iterator iters[] = {
+ it0, it1, it126, it127, it128, it4222, it4223, it4224, it4351,
+ };
+ for (size_t i = 0; i < base::size(iters); ++i) {
+ for (size_t j = 0; j < base::size(iters); ++j) {
+ EXPECT_EQ(i == j, iters[i] == iters[j]);
+ }
+ }
+
+ auto it = it0;
+ ++it;
+ EXPECT_EQ(it, it127);
+
+ it = it1;
+ ++it;
+ EXPECT_EQ(it, it127);
+
+ it = it126;
+ ++it;
+ EXPECT_EQ(it, it127);
+
+ it = it127;
+ ++it;
+ EXPECT_EQ(it, it4223);
+
+ it = it4222;
+ ++it;
+ EXPECT_EQ(it, it4223);
+
+ it = it4223;
+ ++it;
+ EXPECT_EQ(it, buffer->cend());
+
+ it = it4224;
+ ++it;
+ EXPECT_EQ(it, buffer->cend());
+
+ const auto it4352 = buffer->GetIteratorAt(static_cast<size_t>(4352));
+ EXPECT_EQ(it4352, buffer->cend());
+
+ const auto it4353 = buffer->GetIteratorAt(static_cast<size_t>(4353));
+ EXPECT_EQ(it4353, buffer->cend());
+}
+
+TEST(SharedBufferIteratorTest, Empty) {
+ auto buffer = SharedBuffer::Create();
+
+ EXPECT_EQ(buffer->begin(), buffer->end());
+ EXPECT_EQ(buffer->cbegin(), buffer->cend());
+}
+
+TEST(SharedBufferIteratorTest, ConsecutivePartOnly) {
+ auto buffer = SharedBuffer::Create("hello", static_cast<size_t>(5));
+
+ EXPECT_EQ(buffer->begin(), buffer->cbegin());
+ EXPECT_EQ(buffer->end(), buffer->cend());
+
+ auto it = buffer->cbegin();
+ ASSERT_NE(it, buffer->cend());
+
+ EXPECT_EQ(String(it->data(), it->size()), "hello");
+
+ ++it;
+
+ EXPECT_EQ(it, buffer->cend());
+}
+
+TEST(SharedBufferIteratorTest, SegmentedPartOnly) {
+ Vector<char> data(SharedBuffer::kSegmentSize * 2 + 256);
+ std::generate(data.begin(), data.end(), &std::rand);
+ auto buffer = SharedBuffer::Create();
+ buffer->Append(data);
+
+ EXPECT_EQ(buffer->begin(), buffer->cbegin());
+ EXPECT_EQ(buffer->end(), buffer->cend());
+
+ auto it = buffer->cbegin();
+ ASSERT_NE(it, buffer->cend());
+
+ ASSERT_EQ(it->size(), SharedBuffer::kSegmentSize);
+ EXPECT_EQ(0, memcmp(data.data(), it->data(), it->size()));
+
+ ++it;
+ ASSERT_NE(it, buffer->cend());
+ ASSERT_EQ(it->size(), SharedBuffer::kSegmentSize);
+ EXPECT_EQ(0, memcmp(data.data() + SharedBuffer::kSegmentSize, it->data(),
+ it->size()));
+
+ ++it;
+ ASSERT_NE(it, buffer->cend());
+ ASSERT_EQ(it->size(), 256u);
+ EXPECT_EQ(0, memcmp(data.data() + 2 * SharedBuffer::kSegmentSize, it->data(),
+ it->size()));
+
+ ++it;
+ EXPECT_EQ(it, buffer->cend());
+}
+
+TEST(SharedBufferIteratorTest, ConsecutivePartAndSegmentedPart) {
+ Vector<char> data(SharedBuffer::kSegmentSize * 2 + 256);
+ std::generate(data.begin(), data.end(), &std::rand);
+ auto buffer = SharedBuffer::Create();
+ buffer->Append(data.data(), static_cast<size_t>(128));
+ buffer->Append(data.data() + 128, data.size() - 128);
+
+ EXPECT_EQ(buffer->begin(), buffer->cbegin());
+ EXPECT_EQ(buffer->end(), buffer->cend());
+
+ auto it = buffer->cbegin();
+ ASSERT_NE(it, buffer->cend());
+
+ ASSERT_EQ(it->size(), 128u);
+ EXPECT_EQ(0, memcmp(data.data(), it->data(), it->size()));
+
+ ++it;
+ ASSERT_NE(it, buffer->cend());
+ ASSERT_EQ(it->size(), SharedBuffer::kSegmentSize);
+ EXPECT_EQ(0, memcmp(data.data() + 128, it->data(), it->size()));
+
+ ++it;
+ ASSERT_NE(it, buffer->cend());
+ ASSERT_EQ(it->size(), SharedBuffer::kSegmentSize);
+ EXPECT_EQ(0, memcmp(data.data() + 128 + SharedBuffer::kSegmentSize,
+ it->data(), it->size()));
+
+ ++it;
+ ASSERT_NE(it, buffer->cend());
+ ASSERT_EQ(it->size(), 128u);
+ EXPECT_EQ(0, memcmp(data.data() + 128 + 2 * SharedBuffer::kSegmentSize,
+ it->data(), it->size()));
+
+ ++it;
+ EXPECT_EQ(it, buffer->cend());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/supplementable.h b/chromium/third_party/blink/renderer/platform/supplementable.h
index 50381117540..356a674e4ec 100644
--- a/chromium/third_party/blink/renderer/platform/supplementable.h
+++ b/chromium/third_party/blink/renderer/platform/supplementable.h
@@ -105,19 +105,8 @@ namespace blink {
template <typename T>
class Supplementable;
-// Supplement<T>-specific version of TraceWrapperBase class. In order to support
-// wrapper-tracing from Supplementable<T> to Supplement<T> (especially when
-// crossing core/modules boundary), Supplement<T> needs to be wrapper-traceable.
-// This class provides a common API for all subclasses of Supplement<T> to
-// support wrapper-tracing.
-class PLATFORM_EXPORT TraceWrapperBaseForSupplement {
- public:
- virtual void TraceWrappers(ScriptWrappableVisitor* visitor) const {}
-};
-
template <typename T>
-class Supplement : public GarbageCollectedMixin,
- public TraceWrapperBaseForSupplement {
+class Supplement : public GarbageCollectedMixin {
public:
// TODO(haraken): Remove the default constructor.
// All Supplement objects should be instantiated with |supplementable_|.
@@ -205,10 +194,6 @@ class Supplementable : public GarbageCollectedMixin {
}
void Trace(blink::Visitor* visitor) override { visitor->Trace(supplements_); }
- virtual void TraceWrappers(ScriptWrappableVisitor* visitor) const {
- for (const auto& supplement : supplements_.Values())
- visitor->TraceWrappers(supplement);
- }
protected:
using SupplementMap = HeapHashMap<const char*,
diff --git a/chromium/third_party/blink/renderer/platform/testing/DEPS b/chromium/third_party/blink/renderer/platform/testing/DEPS
index c8468495efa..ea9cdc999dd 100644
--- a/chromium/third_party/blink/renderer/platform/testing/DEPS
+++ b/chromium/third_party/blink/renderer/platform/testing/DEPS
@@ -16,8 +16,7 @@ include_rules = [
"+base/metrics/statistics_recorder.h",
"+base/test/test_io_thread.h",
"+cc",
- "+components/viz/test",
- "+mojo/edk/embedder",
+ "+mojo/core/embedder",
'+testing',
"+third_party/blink/renderer/platform/font_family_names.h",
@@ -47,4 +46,7 @@ specific_include_rules = {
'blink_fuzzer_test_support\.cc': [
"+content/public/test/blink_test_environment.h",
],
+ 'testing_platform_support_with_mock_scheduler\.cc': [
+ "+base/task/sequence_manager/test/sequence_manager_for_test.h",
+ ],
}
diff --git a/chromium/third_party/blink/renderer/platform/testing/OWNERS b/chromium/third_party/blink/renderer/platform/testing/OWNERS
new file mode 100644
index 00000000000..7a40d39e254
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/testing/OWNERS
@@ -0,0 +1 @@
+per-file testing_platform_support_with_web_rtc.*=hbos@chromium.org
diff --git a/chromium/third_party/blink/renderer/platform/testing/blink_perf_test_suite.cc b/chromium/third_party/blink/renderer/platform/testing/blink_perf_test_suite.cc
index 270b7ef0eab..446c788b687 100644
--- a/chromium/third_party/blink/renderer/platform/testing/blink_perf_test_suite.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/blink_perf_test_suite.cc
@@ -19,12 +19,10 @@
namespace blink {
BlinkPerfTestSuite::BlinkPerfTestSuite(int argc, char** argv)
- : base::TestSuite(argc, argv) {}
+ : base::TestSuite(argc, argv), env(argc, argv) {}
void BlinkPerfTestSuite::Initialize() {
TestSuite::Initialize();
- WTF::Partitions::Initialize(nullptr);
- WTF::Initialize(nullptr);
// Initialize the perf timer log
base::FilePath log_path =
diff --git a/chromium/third_party/blink/renderer/platform/testing/blink_perf_test_suite.h b/chromium/third_party/blink/renderer/platform/testing/blink_perf_test_suite.h
index 76e5dccd960..d1d263e2cad 100644
--- a/chromium/third_party/blink/renderer/platform/testing/blink_perf_test_suite.h
+++ b/chromium/third_party/blink/renderer/platform/testing/blink_perf_test_suite.h
@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_BLINK_PERF_TEST_SUITE_H_
#include "base/test/test_suite.h"
+#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
namespace blink {
@@ -15,6 +16,9 @@ class BlinkPerfTestSuite : public base::TestSuite {
void Initialize() override;
void Shutdown() override;
+
+ private:
+ ScopedUnittestsEnvironmentSetup env;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/testing/compositor_test.h b/chromium/third_party/blink/renderer/platform/testing/compositor_test.h
index bf4c8427c34..543dac4151c 100644
--- a/chromium/third_party/blink/renderer/platform/testing/compositor_test.h
+++ b/chromium/third_party/blink/renderer/platform/testing/compositor_test.h
@@ -21,8 +21,8 @@ class CompositorTest : public testing::Test {
~CompositorTest() override;
protected:
- // Mock task runner is initialized here because tests create
- // WebLayerTreeViewImplForTesting which needs the current task runner handle.
+ // cc::LayerTreeHost requires a task runner, so we use a mock task runner
+ // and bind it as the current ThreadTaskRunnerHandle for this thread.
scoped_refptr<base::TestMockTimeTaskRunner> runner_;
base::ThreadTaskRunnerHandle runner_handle_;
};
diff --git a/chromium/third_party/blink/renderer/platform/testing/data/third_party/Roboto/LICENSE.txt b/chromium/third_party/blink/renderer/platform/testing/data/third_party/Roboto/LICENSE.txt
new file mode 100644
index 00000000000..d6456956733
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/testing/data/third_party/Roboto/LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/chromium/third_party/blink/renderer/platform/testing/data/third_party/Roboto/README.chromium b/chromium/third_party/blink/renderer/platform/testing/data/third_party/Roboto/README.chromium
new file mode 100644
index 00000000000..8660130f081
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/testing/data/third_party/Roboto/README.chromium
@@ -0,0 +1,12 @@
+Name: Roboto Font
+Short Name: roboto
+URL: https://github.com/google/roboto/
+Version: 5700de83856781fa0c097a349e46dbaae5792cb0
+Date: 2017-08-02
+License: Apache-2.0
+License File: LICENSE.txt
+Security Critical: no
+
+Description:
+We need a a latin font with ligatures for platform testing.
+Roboto contains ffi and ff.
diff --git a/chromium/third_party/blink/renderer/platform/testing/data/third_party/Roboto/roboto-regular.woff2 b/chromium/third_party/blink/renderer/platform/testing/data/third_party/Roboto/roboto-regular.woff2
new file mode 100644
index 00000000000..bf6ecadf0d2
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/testing/data/third_party/Roboto/roboto-regular.woff2
Binary files differ
diff --git a/chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.cc b/chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.cc
index ef1bde3af31..10ed823d1d5 100644
--- a/chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.cc
@@ -9,6 +9,11 @@
namespace blink {
+WebMediaPlayer::LoadTiming
+EmptyWebMediaPlayer::Load(LoadType, const WebMediaPlayerSource&, CORSMode) {
+ return LoadTiming::kImmediate;
+}
+
WebTimeRanges EmptyWebMediaPlayer::Buffered() const {
return WebTimeRanges();
}
diff --git a/chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.h b/chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.h
index 009d2720875..ef7511a198c 100644
--- a/chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.h
+++ b/chromium/third_party/blink/renderer/platform/testing/empty_web_media_player.h
@@ -2,11 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "third_party/blink/public/platform/web_media_player.h"
-
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_EMPTY_WEB_MEDIA_PLAYER_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_EMPTY_WEB_MEDIA_PLAYER_H_
+#include "base/callback.h"
+#include "third_party/blink/public/platform/web_media_player.h"
+
+namespace cc {
+class PaintCanvas;
+class PaintFlags;
+} // namespace cc
+
namespace blink {
// An empty WebMediaPlayer used only for tests. This class defines the methods
@@ -16,7 +22,7 @@ class EmptyWebMediaPlayer : public WebMediaPlayer {
public:
~EmptyWebMediaPlayer() override = default;
- void Load(LoadType, const WebMediaPlayerSource&, CORSMode) override {}
+ LoadTiming Load(LoadType, const WebMediaPlayerSource&, CORSMode) override;
void Play() override {}
void Pause() override {}
void Seek(double seconds) override {}
@@ -52,7 +58,7 @@ class EmptyWebMediaPlayer : public WebMediaPlayer {
unsigned DroppedFrameCount() const override { return 0; }
size_t AudioDecodedByteCount() const override { return 0; }
size_t VideoDecodedByteCount() const override { return 0; }
- void Paint(WebCanvas*,
+ void Paint(cc::PaintCanvas*,
const WebRect&,
cc::PaintFlags&,
int already_uploaded_id,
diff --git a/chromium/third_party/blink/renderer/platform/testing/fake_display_item_client.h b/chromium/third_party/blink/renderer/platform/testing/fake_display_item_client.h
index e097c22aa5a..a9c456211e1 100644
--- a/chromium/third_party/blink/renderer/platform/testing/fake_display_item_client.h
+++ b/chromium/third_party/blink/renderer/platform/testing/fake_display_item_client.h
@@ -20,28 +20,26 @@ class FakeDisplayItemClient : public DisplayItemClient {
String DebugName() const final { return name_; }
LayoutRect VisualRect() const override { return visual_rect_; }
- LayoutRect PartialInvalidationRect() const override {
- return partial_invalidation_rect_;
+ LayoutRect PartialInvalidationVisualRect() const override {
+ return partial_invalidation_visual_rect_;
}
- void ClearPartialInvalidationRect() const override {
- partial_invalidation_rect_ = LayoutRect();
+ void ClearPartialInvalidationVisualRect() const override {
+ partial_invalidation_visual_rect_ = LayoutRect();
}
void SetVisualRect(const LayoutRect& r) { visual_rect_ = r; }
- void SetPartialInvalidationRect(const LayoutRect& r) {
- SetDisplayItemsUncached(PaintInvalidationReason::kRectangle);
- partial_invalidation_rect_ = r;
+ void SetPartialInvalidationVisualRect(const LayoutRect& r) {
+ Invalidate(PaintInvalidationReason::kRectangle);
+ partial_invalidation_visual_rect_ = r;
}
// This simulates a paint without needing a PaintController.
- void UpdateCacheGeneration() {
- SetDisplayItemsCached(CacheGenerationOrInvalidationReason::Next());
- }
+ using DisplayItemClient::Validate;
private:
String name_;
LayoutRect visual_rect_;
- mutable LayoutRect partial_invalidation_rect_;
+ mutable LayoutRect partial_invalidation_visual_rect_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/testing/histogram_tester.cc b/chromium/third_party/blink/renderer/platform/testing/histogram_tester.cc
index 467ff74112a..970700e22a9 100644
--- a/chromium/third_party/blink/renderer/platform/testing/histogram_tester.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/histogram_tester.cc
@@ -6,7 +6,7 @@
#include <string>
-#include "base/test/histogram_tester.h"
+#include "base/test/metrics/histogram_tester.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/testing/image_decode_bench.cc b/chromium/third_party/blink/renderer/platform/testing/image_decode_bench.cc
index 223f23bc987..00c158d339f 100644
--- a/chromium/third_party/blink/renderer/platform/testing/image_decode_bench.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/image_decode_bench.cc
@@ -21,7 +21,7 @@
#include "base/command_line.h"
#include "base/memory/scoped_refptr.h"
#include "base/message_loop/message_loop.h"
-#include "mojo/edk/embedder/embedder.h"
+#include "mojo/core/embedder/embedder.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
@@ -72,8 +72,10 @@ void DecodeFailure(ImageMeta* image) {
}
void DecodeImageData(SharedBuffer* data, ImageMeta* image) {
+ const bool data_complete = true;
std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
- data, true, ImageDecoder::kAlphaPremultiplied, ColorBehavior::Ignore());
+ data, data_complete, ImageDecoder::kAlphaPremultiplied,
+ ImageDecoder::kDefaultBitDepth, ColorBehavior::Ignore());
auto start = CurrentTimeTicks();
@@ -155,6 +157,6 @@ int ImageDecodeBenchMain(int argc, char* argv[]) {
int main(int argc, char* argv[]) {
base::MessageLoop message_loop;
- mojo::edk::Init();
+ mojo::core::Init();
return blink::ImageDecodeBenchMain(argc, argv);
}
diff --git a/chromium/third_party/blink/renderer/platform/testing/layer_tree_host_embedder.cc b/chromium/third_party/blink/renderer/platform/testing/layer_tree_host_embedder.cc
new file mode 100644
index 00000000000..fdfcef59d7d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/testing/layer_tree_host_embedder.cc
@@ -0,0 +1,39 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/testing/layer_tree_host_embedder.h"
+
+#include "base/threading/thread_task_runner_handle.h"
+
+namespace blink {
+
+LayerTreeHostEmbedder::LayerTreeHostEmbedder()
+ : LayerTreeHostEmbedder(/*client=*/nullptr,
+ /*single_thread_client=*/nullptr,
+ /*use_layer_lists=*/false) {}
+
+LayerTreeHostEmbedder::LayerTreeHostEmbedder(
+ cc::LayerTreeHostClient* client,
+ cc::LayerTreeHostSingleThreadClient* single_thread_client,
+ bool use_layer_lists) {
+ cc::LayerTreeSettings settings;
+ settings.layer_transforms_should_scale_layer_contents = true;
+ settings.single_thread_proxy_scheduler = false;
+ settings.use_layer_lists = use_layer_lists;
+
+ animation_host_ = cc::AnimationHost::CreateMainInstance();
+ cc::LayerTreeHost::InitParams params;
+ params.client = client ? client : &layer_tree_host_client_;
+ params.settings = &settings;
+ params.main_task_runner = base::ThreadTaskRunnerHandle::Get();
+ params.task_graph_runner = &task_graph_runner_;
+ params.mutator_host = animation_host_.get();
+
+ layer_tree_host_ = cc::LayerTreeHost::CreateSingleThreaded(
+ single_thread_client ? single_thread_client
+ : &layer_tree_host_single_thread_client_,
+ &params);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/testing/layer_tree_host_embedder.h b/chromium/third_party/blink/renderer/platform/testing/layer_tree_host_embedder.h
new file mode 100644
index 00000000000..92be21c2d95
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/testing/layer_tree_host_embedder.h
@@ -0,0 +1,45 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_LAYER_TREE_HOST_EMBEDDER_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_LAYER_TREE_HOST_EMBEDDER_H_
+
+#include "cc/animation/animation_host.h"
+#include "cc/test/stub_layer_tree_host_client.h"
+#include "cc/test/stub_layer_tree_host_single_thread_client.h"
+#include "cc/test/test_task_graph_runner.h"
+#include "cc/trees/layer_tree_host.h"
+#include "cc/trees/layer_tree_settings.h"
+
+namespace blink {
+
+// A class that owns the lifetime of a cc::LayerTreeHost and its dependencies
+// for unit tests that need to instantiate only a cc::LayerTreeHost and not the
+// full blink APIs that normally own and embed it.
+class LayerTreeHostEmbedder {
+ public:
+ // Default constructor uses stub clients, and default LayerTreeSettings
+ // appropriate for blink unit tests.
+ LayerTreeHostEmbedder();
+ // Constructor to specify the clients, or null to use stubs. Also specify
+ // overrides of LayerTreeSettings.
+ LayerTreeHostEmbedder(
+ cc::LayerTreeHostClient* client,
+ cc::LayerTreeHostSingleThreadClient* single_thread_client,
+ bool use_layer_lists);
+
+ cc::LayerTreeHost* layer_tree_host() { return layer_tree_host_.get(); }
+ cc::AnimationHost* animation_host() { return animation_host_.get(); }
+
+ private:
+ cc::StubLayerTreeHostSingleThreadClient layer_tree_host_single_thread_client_;
+ cc::StubLayerTreeHostClient layer_tree_host_client_;
+ cc::TestTaskGraphRunner task_graph_runner_;
+ std::unique_ptr<cc::AnimationHost> animation_host_;
+ std::unique_ptr<cc::LayerTreeHost> layer_tree_host_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_LAYER_TREE_HOST_EMBEDDER_H_
diff --git a/chromium/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h b/chromium/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h
index 14b2b280095..5d852e90277 100644
--- a/chromium/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h
+++ b/chromium/third_party/blink/renderer/platform/testing/paint_property_test_helpers.h
@@ -12,10 +12,21 @@
namespace blink {
+// Convenient shorthands.
+inline const TransformPaintPropertyNode& t0() {
+ return TransformPaintPropertyNode::Root();
+}
+inline const ClipPaintPropertyNode& c0() {
+ return ClipPaintPropertyNode::Root();
+}
+inline const EffectPaintPropertyNode& e0() {
+ return EffectPaintPropertyNode::Root();
+}
+
inline scoped_refptr<EffectPaintPropertyNode> CreateOpacityEffect(
- scoped_refptr<const EffectPaintPropertyNode> parent,
- scoped_refptr<const TransformPaintPropertyNode> local_transform_space,
- scoped_refptr<const ClipPaintPropertyNode> output_clip,
+ const EffectPaintPropertyNode& parent,
+ const TransformPaintPropertyNode* local_transform_space,
+ const ClipPaintPropertyNode* output_clip,
float opacity,
CompositingReasons compositing_reasons = CompositingReason::kNone) {
EffectPaintPropertyNode::State state;
@@ -23,22 +34,21 @@ inline scoped_refptr<EffectPaintPropertyNode> CreateOpacityEffect(
state.output_clip = output_clip;
state.opacity = opacity;
state.direct_compositing_reasons = compositing_reasons;
- return EffectPaintPropertyNode::Create(std::move(parent), std::move(state));
+ return EffectPaintPropertyNode::Create(parent, std::move(state));
}
inline scoped_refptr<EffectPaintPropertyNode> CreateOpacityEffect(
- scoped_refptr<const EffectPaintPropertyNode> parent,
+ const EffectPaintPropertyNode& parent,
float opacity,
CompositingReasons compositing_reasons = CompositingReason::kNone) {
- return CreateOpacityEffect(parent, parent->LocalTransformSpace(),
- parent->OutputClip(), opacity,
- compositing_reasons);
+ return CreateOpacityEffect(parent, parent.LocalTransformSpace(),
+ parent.OutputClip(), opacity, compositing_reasons);
}
inline scoped_refptr<EffectPaintPropertyNode> CreateFilterEffect(
- scoped_refptr<const EffectPaintPropertyNode> parent,
- scoped_refptr<const TransformPaintPropertyNode> local_transform_space,
- scoped_refptr<const ClipPaintPropertyNode> output_clip,
+ const EffectPaintPropertyNode& parent,
+ const TransformPaintPropertyNode* local_transform_space,
+ const ClipPaintPropertyNode* output_clip,
CompositorFilterOperations filter,
const FloatPoint& paint_offset = FloatPoint(),
CompositingReasons compositing_reasons = CompositingReason::kNone) {
@@ -48,22 +58,22 @@ inline scoped_refptr<EffectPaintPropertyNode> CreateFilterEffect(
state.filter = std::move(filter);
state.paint_offset = paint_offset;
state.direct_compositing_reasons = compositing_reasons;
- return EffectPaintPropertyNode::Create(std::move(parent), std::move(state));
+ return EffectPaintPropertyNode::Create(parent, std::move(state));
}
inline scoped_refptr<EffectPaintPropertyNode> CreateFilterEffect(
- scoped_refptr<const EffectPaintPropertyNode> parent,
+ const EffectPaintPropertyNode& parent,
CompositorFilterOperations filter,
const FloatPoint& paint_offset = FloatPoint(),
CompositingReasons compositing_reasons = CompositingReason::kNone) {
- return CreateFilterEffect(parent, parent->LocalTransformSpace(),
- parent->OutputClip(), filter, paint_offset,
+ return CreateFilterEffect(parent, parent.LocalTransformSpace(),
+ parent.OutputClip(), filter, paint_offset,
compositing_reasons);
}
inline scoped_refptr<ClipPaintPropertyNode> CreateClip(
- scoped_refptr<const ClipPaintPropertyNode> parent,
- scoped_refptr<const TransformPaintPropertyNode> local_transform_space,
+ const ClipPaintPropertyNode& parent,
+ const TransformPaintPropertyNode* local_transform_space,
const FloatRoundedRect& clip_rect,
CompositingReasons compositing_reasons = CompositingReason::kNone) {
ClipPaintPropertyNode::State state;
@@ -74,8 +84,8 @@ inline scoped_refptr<ClipPaintPropertyNode> CreateClip(
}
inline scoped_refptr<ClipPaintPropertyNode> CreateClipPathClip(
- scoped_refptr<const ClipPaintPropertyNode> parent,
- scoped_refptr<const TransformPaintPropertyNode> local_transform_space,
+ const ClipPaintPropertyNode& parent,
+ const TransformPaintPropertyNode* local_transform_space,
const FloatRoundedRect& clip_rect) {
ClipPaintPropertyNode::State state;
state.local_transform_space = local_transform_space;
@@ -85,7 +95,7 @@ inline scoped_refptr<ClipPaintPropertyNode> CreateClipPathClip(
}
inline scoped_refptr<TransformPaintPropertyNode> CreateTransform(
- scoped_refptr<const TransformPaintPropertyNode> parent,
+ const TransformPaintPropertyNode& parent,
const TransformationMatrix& matrix,
const FloatPoint3D& origin = FloatPoint3D(),
CompositingReasons compositing_reasons = CompositingReason::kNone) {
@@ -97,15 +107,15 @@ inline scoped_refptr<TransformPaintPropertyNode> CreateTransform(
}
inline scoped_refptr<TransformPaintPropertyNode> CreateScrollTranslation(
- scoped_refptr<const TransformPaintPropertyNode> parent,
+ const TransformPaintPropertyNode& parent,
float offset_x,
float offset_y,
- scoped_refptr<const ScrollPaintPropertyNode> scroll,
+ const ScrollPaintPropertyNode& scroll,
CompositingReasons compositing_reasons = CompositingReason::kNone) {
TransformPaintPropertyNode::State state;
state.matrix.Translate(offset_x, offset_y);
state.direct_compositing_reasons = compositing_reasons;
- state.scroll = scroll;
+ state.scroll = &scroll;
return TransformPaintPropertyNode::Create(parent, std::move(state));
}
diff --git a/chromium/third_party/blink/renderer/platform/testing/paint_test_configurations.h b/chromium/third_party/blink/renderer/platform/testing/paint_test_configurations.h
index c32b0eb1360..fafe1ade6bb 100644
--- a/chromium/third_party/blink/renderer/platform/testing/paint_test_configurations.h
+++ b/chromium/third_party/blink/renderer/platform/testing/paint_test_configurations.h
@@ -12,22 +12,19 @@
namespace blink {
enum {
- kSlimmingPaintV175 = 1 << 0,
- kBlinkGenPropertyTrees = 1 << 1,
- kSlimmingPaintV2 = 1 << 2,
- kUnderInvalidationChecking = 1 << 3,
+ kBlinkGenPropertyTrees = 1 << 0,
+ kSlimmingPaintV2 = 1 << 1,
+ kUnderInvalidationChecking = 1 << 2,
};
class PaintTestConfigurations
: public testing::WithParamInterface<unsigned>,
- private ScopedSlimmingPaintV175ForTest,
private ScopedBlinkGenPropertyTreesForTest,
private ScopedSlimmingPaintV2ForTest,
private ScopedPaintUnderInvalidationCheckingForTest {
public:
PaintTestConfigurations()
- : ScopedSlimmingPaintV175ForTest(GetParam() & kSlimmingPaintV175),
- ScopedBlinkGenPropertyTreesForTest(GetParam() & kBlinkGenPropertyTrees),
+ : ScopedBlinkGenPropertyTreesForTest(GetParam() & kBlinkGenPropertyTrees),
ScopedSlimmingPaintV2ForTest(GetParam() & kSlimmingPaintV2),
ScopedPaintUnderInvalidationCheckingForTest(
GetParam() & kUnderInvalidationChecking) {}
@@ -37,11 +34,10 @@ class PaintTestConfigurations
}
};
-#define INSTANTIATE_PAINT_TEST_CASE_P(test_class) \
- INSTANTIATE_TEST_CASE_P( \
- All, test_class, \
- ::testing::Values(0, kSlimmingPaintV175, kBlinkGenPropertyTrees, \
- kSlimmingPaintV2))
+#define INSTANTIATE_PAINT_TEST_CASE_P(test_class) \
+ INSTANTIATE_TEST_CASE_P( \
+ All, test_class, \
+ ::testing::Values(0, kBlinkGenPropertyTrees, kSlimmingPaintV2))
#define INSTANTIATE_SPV2_TEST_CASE_P(test_class) \
INSTANTIATE_TEST_CASE_P(All, test_class, ::testing::Values(kSlimmingPaintV2))
diff --git a/chromium/third_party/blink/renderer/platform/testing/run_all_tests.cc b/chromium/third_party/blink/renderer/platform/testing/run_all_tests.cc
index ce8e4d87dd0..8b7ea4b585b 100644
--- a/chromium/third_party/blink/renderer/platform/testing/run_all_tests.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/run_all_tests.cc
@@ -33,8 +33,8 @@
#include "base/test/launcher/unit_test_launcher.h"
#include "base/test/test_io_thread.h"
#include "base/test/test_suite.h"
-#include "mojo/edk/embedder/embedder.h"
-#include "mojo/edk/embedder/scoped_ipc_support.h"
+#include "mojo/core/embedder/embedder.h"
+#include "mojo/core/embedder/scoped_ipc_support.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
@@ -54,11 +54,11 @@ int main(int argc, char** argv) {
{
base::TestSuite testSuite(argc, argv);
- mojo::edk::Init();
+ mojo::core::Init();
base::TestIOThread testIoThread(base::TestIOThread::kAutoStart);
- mojo::edk::ScopedIPCSupport ipcSupport(
+ mojo::core::ScopedIPCSupport ipcSupport(
testIoThread.task_runner(),
- mojo::edk::ScopedIPCSupport::ShutdownPolicy::CLEAN);
+ mojo::core::ScopedIPCSupport::ShutdownPolicy::CLEAN);
result = base::LaunchUnitTests(
argc, argv, base::BindOnce(runTestSuite, base::Unretained(&testSuite)));
}
diff --git a/chromium/third_party/blink/renderer/platform/testing/scoped_fake_plugin_registry.cc b/chromium/third_party/blink/renderer/platform/testing/scoped_fake_plugin_registry.cc
new file mode 100644
index 00000000000..df5f4e9e77d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/testing/scoped_fake_plugin_registry.cc
@@ -0,0 +1,75 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/testing/scoped_fake_plugin_registry.h"
+
+#include "base/files/file_path.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "third_party/blink/public/mojom/plugins/plugin_registry.mojom-blink.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
+#include "third_party/skia/include/core/SkColor.h"
+
+namespace blink {
+
+namespace {
+
+class FakePluginRegistryImpl : public mojom::blink::PluginRegistry {
+ public:
+ static void Bind(mojo::ScopedMessagePipeHandle handle) {
+ DEFINE_STATIC_LOCAL(FakePluginRegistryImpl, impl, ());
+ impl.bindings_.AddBinding(
+ &impl, mojom::blink::PluginRegistryRequest(std::move(handle)));
+ }
+
+ // PluginRegistry
+ void GetPlugins(bool refresh,
+ const scoped_refptr<const SecurityOrigin>& origin,
+ GetPluginsCallback callback) override {
+ auto mime = mojom::blink::PluginMimeType::New();
+ mime->mime_type = "application/pdf";
+ mime->description = "pdf";
+
+ auto plugin = mojom::blink::PluginInfo::New();
+ plugin->name = "pdf";
+ plugin->description = "pdf";
+ plugin->filename = base::FilePath(FILE_PATH_LITERAL("pdf-files"));
+ plugin->background_color = SkColorSetRGB(38, 38, 38);
+ plugin->mime_types.push_back(std::move(mime));
+
+ Vector<mojom::blink::PluginInfoPtr> plugins;
+ plugins.push_back(std::move(plugin));
+ std::move(callback).Run(std::move(plugins));
+ }
+
+ private:
+ mojo::BindingSet<PluginRegistry> bindings_;
+};
+
+} // namespace
+
+ScopedFakePluginRegistry::ScopedFakePluginRegistry() {
+ service_manager::Identity browser_id(
+ Platform::Current()->GetBrowserServiceName());
+ const char* interface_name = mojom::blink::PluginRegistry::Name_;
+ service_manager::Connector::TestApi test_api(
+ Platform::Current()->GetConnector());
+ DCHECK(!test_api.HasBinderOverride(browser_id, interface_name));
+ test_api.OverrideBinderForTesting(
+ browser_id, interface_name,
+ WTF::BindRepeating(&FakePluginRegistryImpl::Bind));
+}
+
+ScopedFakePluginRegistry::~ScopedFakePluginRegistry() {
+ service_manager::Identity browser_id(
+ Platform::Current()->GetBrowserServiceName());
+ const char* interface_name = mojom::blink::PluginRegistry::Name_;
+ service_manager::Connector::TestApi test_api(
+ Platform::Current()->GetConnector());
+ test_api.ClearBinderOverride(browser_id, interface_name);
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/testing/scoped_fake_plugin_registry.h b/chromium/third_party/blink/renderer/platform/testing/scoped_fake_plugin_registry.h
new file mode 100644
index 00000000000..5d92c65748e
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/testing/scoped_fake_plugin_registry.h
@@ -0,0 +1,20 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_SCOPED_FAKE_PLUGIN_REGISTRY_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_SCOPED_FAKE_PLUGIN_REGISTRY_H_
+
+namespace blink {
+
+// Simulates the browser process serving a list of plugins that includes just a
+// fake PDF plugin.
+class ScopedFakePluginRegistry {
+ public:
+ ScopedFakePluginRegistry();
+ ~ScopedFakePluginRegistry();
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_SCOPED_FAKE_PLUGIN_REGISTRY_H_
diff --git a/chromium/third_party/blink/renderer/platform/testing/shape_result_perf_test.cc b/chromium/third_party/blink/renderer/platform/testing/shape_result_perf_test.cc
new file mode 100644
index 00000000000..008e697d67a
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/testing/shape_result_perf_test.cc
@@ -0,0 +1,170 @@
+// Copyright (c) 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 "base/time/time.h"
+#include "cc/base/lap_timer.h"
+
+#include "build/build_config.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/perf/perf_test.h"
+#include "third_party/blink/renderer/platform/fonts/font.h"
+#include "third_party/blink/renderer/platform/fonts/font_description.h"
+#include "third_party/blink/renderer/platform/testing/font_test_helpers.h"
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
+
+using blink::test::CreateTestFont;
+
+namespace blink {
+
+static const int kTimeLimitMillis = 3000;
+static const int kWarmupRuns = 10000;
+static const int kTimeCheckInterval = 1000000;
+
+class ShapeResultPerfTest {
+ public:
+ enum FontName {
+ ahem,
+ amiri,
+ megalopolis,
+ roboto,
+ };
+
+ ShapeResultPerfTest()
+ : timer(kWarmupRuns,
+ base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
+ kTimeCheckInterval) {}
+
+ protected:
+ TextRun SetupFont(FontName font_name, const String& text, bool ltr) {
+ FontDescription::VariantLigatures ligatures(
+ FontDescription::kEnabledLigaturesState);
+ font = CreateTestFont("TestFont",
+ test::PlatformTestDataPath(font_path[font_name]), 100,
+ &ligatures);
+
+ return TextRun(
+ text, /* xpos */ 0, /* expansion */ 0,
+ TextRun::kAllowTrailingExpansion | TextRun::kForbidLeadingExpansion,
+ ltr ? TextDirection::kLtr : TextDirection::kRtl, false);
+ }
+
+ Font font;
+
+ std::map<FontName, String> font_path = {
+ {ahem, "Ahem.woff"},
+ {amiri, "third_party/Amiri/amiri_arabic.woff2"},
+ {megalopolis, "third_party/MEgalopolis/MEgalopolisExtra.woff"},
+ {roboto, "third_party/Roboto/roboto-regular.woff2"},
+ };
+
+ cc::LapTimer timer;
+};
+
+class OffsetForPositionPerfTest : public ShapeResultPerfTest,
+ public testing::TestWithParam<float> {
+ public:
+ void OffsetForPosition(TextRun& run,
+ IncludePartialGlyphsOption partial,
+ BreakGlyphsOption breakopt) {
+ timer.Reset();
+ float position = GetParam();
+ do {
+ font.OffsetForPosition(run, position, partial, breakopt);
+ timer.NextLap();
+ } while (!timer.HasTimeLimitExpired());
+ }
+};
+
+class CharacterRangePerfTest : public ShapeResultPerfTest,
+ public testing::TestWithParam<int> {
+ public:
+ void GetCharacter(TextRun& run) {
+ timer.Reset();
+ int endpos = GetParam();
+ do {
+ font.SelectionRectForText(run, FloatPoint(), 100, 0, endpos);
+ timer.NextLap();
+ } while (!timer.HasTimeLimitExpired());
+ }
+};
+
+TEST_P(OffsetForPositionPerfTest, LTROffsetForPositionFullBreak) {
+ TextRun run = SetupFont(ahem, "FURACOLO", true);
+ OffsetForPosition(run, OnlyFullGlyphs, BreakGlyphs);
+ perf_test::PrintResult("OffsetForPositionPerfTest", " LTR full break", "",
+ timer.LapsPerSecond(), "runs/s", true);
+}
+
+TEST_P(OffsetForPositionPerfTest, LTROffsetForPositionFullDontBreak) {
+ TextRun run = SetupFont(ahem, "FURACOLO", true);
+ OffsetForPosition(run, OnlyFullGlyphs, DontBreakGlyphs);
+ perf_test::PrintResult("OffsetForPositionPerfTest", " LTR full", "",
+ timer.LapsPerSecond(), "runs/s", true);
+}
+
+TEST_P(OffsetForPositionPerfTest, LTROffsetForPositionIncludePartialBreak) {
+ TextRun run = SetupFont(ahem, "FURACOLO", true);
+ OffsetForPosition(run, IncludePartialGlyphs, BreakGlyphs);
+ perf_test::PrintResult("OffsetForPositionPerfTest", " LTR partial break", "",
+ timer.LapsPerSecond(), "runs/s", true);
+}
+
+TEST_P(OffsetForPositionPerfTest, LTROffsetForPositionIncludePartialDontBreak) {
+ TextRun run = SetupFont(ahem, "FURACOLO", true);
+ OffsetForPosition(run, IncludePartialGlyphs, DontBreakGlyphs);
+ perf_test::PrintResult("OffsetForPositionPerfTest", " LTR partial", "",
+ timer.LapsPerSecond(), "runs/s", true);
+}
+
+TEST_P(OffsetForPositionPerfTest, RTLOffsetForPositionFullBreak) {
+ TextRun run = SetupFont(ahem, "OLOCARUF", false);
+ OffsetForPosition(run, OnlyFullGlyphs, BreakGlyphs);
+ perf_test::PrintResult("OffsetForPositionPerfTest", " RTL full break", "",
+ timer.LapsPerSecond(), "runs/s", true);
+}
+
+TEST_P(OffsetForPositionPerfTest, RTLOffsetForPositionFullDontBreak) {
+ TextRun run = SetupFont(ahem, "OLOCARUF", false);
+ OffsetForPosition(run, OnlyFullGlyphs, DontBreakGlyphs);
+ perf_test::PrintResult("OffsetForPositionPerfTest", " RTL full", "",
+ timer.LapsPerSecond(), "runs/s", true);
+}
+
+TEST_P(OffsetForPositionPerfTest, RTLOffsetForPositionIncludePartialBreak) {
+ TextRun run = SetupFont(ahem, "OLOCARUF", false);
+ OffsetForPosition(run, IncludePartialGlyphs, BreakGlyphs);
+ perf_test::PrintResult("OffsetForPositionPerfTest", " RTL partial break", "",
+ timer.LapsPerSecond(), "runs/s", true);
+}
+
+TEST_P(OffsetForPositionPerfTest, RTLOffsetForPositionIncludePartialDontBreak) {
+ TextRun run = SetupFont(ahem, "OLOCARUF", false);
+ OffsetForPosition(run, IncludePartialGlyphs, DontBreakGlyphs);
+ perf_test::PrintResult("OffsetForPositionPerfTest", " RTL partial", "",
+ timer.LapsPerSecond(), "runs/s", true);
+}
+
+INSTANTIATE_TEST_CASE_P(OffsetForPosition,
+ OffsetForPositionPerfTest,
+ testing::Values(0, 10, 60, 100, 200, 350));
+
+TEST_P(CharacterRangePerfTest, LTRCharacterForPosition) {
+ TextRun run = SetupFont(ahem, "FURACOLO", true);
+ GetCharacter(run);
+ perf_test::PrintResult("CharacterRangePerfTest", " LTR", "",
+ timer.LapsPerSecond(), "runs/s", true);
+}
+
+TEST_P(CharacterRangePerfTest, RTLCharacterForPosition) {
+ TextRun run = SetupFont(ahem, "OLOCARUF", false);
+ GetCharacter(run);
+ perf_test::PrintResult("CharacterRangePerfTest", " RTL", "",
+ timer.LapsPerSecond(), "runs/s", true);
+}
+
+INSTANTIATE_TEST_CASE_P(CharacterRange,
+ CharacterRangePerfTest,
+ testing::Values(0, 1, 2, 4, 8));
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/testing/shaping_line_breaker_perf_test.cc b/chromium/third_party/blink/renderer/platform/testing/shaping_line_breaker_perf_test.cc
index cb8149e50c9..542c058428e 100644
--- a/chromium/third_party/blink/renderer/platform/testing/shaping_line_breaker_perf_test.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/shaping_line_breaker_perf_test.cc
@@ -31,7 +31,7 @@ LayoutUnit ShapeText(ShapingLineBreaker* breaker,
unsigned break_offset = 0;
LayoutUnit total_width;
ShapingLineBreaker::Result result;
- scoped_refptr<ShapeResult> shape_result;
+ scoped_refptr<const ShapeResult> shape_result;
while (break_offset < string_length) {
shape_result = breaker->ShapeLine(break_offset, available_space, &result);
break_offset = result.break_offset;
@@ -71,7 +71,7 @@ TEST_F(ShapingLineBreakerPerfTest, ShapeLatinText) {
// By William Arthur Dunkerley (John Oxenham)
// In the public domain.
String string(
- u"\"Am I my brother's keeper?\""
+ "\"Am I my brother's keeper?\""
"Yes, of a truth!"
"Thine asking is thine answer."
"That self-condemning cry of Cain"
@@ -124,16 +124,22 @@ TEST_F(ShapingLineBreakerPerfTest, ShapeLatinText) {
LazyLineBreakIterator break_iterator(string, "en-US", LineBreakType::kNormal);
TextDirection direction = TextDirection::kLtr;
- HarfBuzzShaper shaper(string.Characters16(), len);
- scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
- ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
+ HarfBuzzShaper shaper(string);
+ scoped_refptr<const ShapeResult> reference_result =
+ shaper.Shape(&font, direction);
+ ShapingLineBreaker reference_breaker(&shaper, &font, reference_result.get(),
+ &break_iterator);
- scoped_refptr<ShapeResult> line;
+ scoped_refptr<const ShapeResult> line;
LayoutUnit available_width_px(500);
+ LayoutUnit expected_width =
+ ShapeText(&reference_breaker, available_width_px, len);
- LayoutUnit expected_width = ShapeText(&breaker, available_width_px, len);
timer_.Reset();
do {
+ scoped_refptr<const ShapeResult> result = shaper.Shape(&font, direction);
+ ShapingLineBreaker breaker(&shaper, &font, result.get(), &break_iterator);
+
LayoutUnit width = ShapeText(&breaker, available_width_px, len);
EXPECT_EQ(expected_width, width);
timer_.NextLap();
diff --git a/chromium/third_party/blink/renderer/platform/testing/stub_graphics_layer_client.h b/chromium/third_party/blink/renderer/platform/testing/stub_graphics_layer_client.h
new file mode 100644
index 00000000000..36ccdd9b42d
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/testing/stub_graphics_layer_client.h
@@ -0,0 +1,36 @@
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_STUB_GRAPHICS_LAYER_CLIENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_STUB_GRAPHICS_LAYER_CLIENT_H_
+
+#include "third_party/blink/renderer/platform/graphics/graphics_layer_client.h"
+
+namespace blink {
+
+class StubGraphicsLayerClient : public GraphicsLayerClient {
+ public:
+ StubGraphicsLayerClient() = default;
+ ~StubGraphicsLayerClient() override = default;
+
+ // GraphicsLayerClient implementation.
+ void InvalidateTargetElementForTesting() override {}
+ IntRect ComputeInterestRect(
+ const GraphicsLayer*,
+ const IntRect& previous_interest_rect) const override {
+ return IntRect();
+ }
+ LayoutSize SubpixelAccumulation() const override { return LayoutSize(); }
+ bool NeedsRepaint(const GraphicsLayer&) const override { return false; }
+ void PaintContents(const GraphicsLayer*,
+ GraphicsContext&,
+ GraphicsLayerPaintingPhase,
+ const IntRect& interest_rect) const override {}
+ bool ShouldThrottleRendering() const override { return false; }
+ bool IsTrackingRasterInvalidations() const override { return false; }
+ String DebugName(const GraphicsLayer*) const override { return "DebugName"; }
+#if DCHECK_IS_ON()
+ void VerifyNotPainting() override {}
+#endif
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_STUB_GRAPHICS_LAYER_CLIENT_H_
diff --git a/chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.cc b/chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.cc
index 0dfd6449b8d..ef0e947d251 100644
--- a/chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.cc
@@ -15,7 +15,6 @@
#include "third_party/blink/renderer/platform/graphics/paint/paint_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h"
#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
-#include "third_party/blink/renderer/platform/testing/fake_display_item_client.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
namespace blink {
@@ -28,7 +27,7 @@ class TestPaintArtifact::DummyRectClient : public FakeDisplayItemClient {
sk_sp<PaintRecord> MakeRecord(const FloatRect& rect, Color color) {
rect_ = rect;
PaintRecorder recorder;
- PaintCanvas* canvas = recorder.beginRecording(rect);
+ cc::PaintCanvas* canvas = recorder.beginRecording(rect);
PaintFlags flags;
flags.setColor(color.Rgb());
canvas->drawRect(rect, flags);
@@ -39,41 +38,38 @@ class TestPaintArtifact::DummyRectClient : public FakeDisplayItemClient {
FloatRect rect_;
};
-TestPaintArtifact::TestPaintArtifact() : display_item_list_(0), built_(false) {}
+TestPaintArtifact::TestPaintArtifact() : display_item_list_(0) {}
TestPaintArtifact::~TestPaintArtifact() = default;
-TestPaintArtifact& TestPaintArtifact::Chunk(
- scoped_refptr<const TransformPaintPropertyNode> transform,
- scoped_refptr<const ClipPaintPropertyNode> clip,
- scoped_refptr<const EffectPaintPropertyNode> effect) {
- return Chunk(NewClient(), transform, clip, effect);
+TestPaintArtifact& TestPaintArtifact::Chunk(int id) {
+ DEFINE_STATIC_LOCAL(DummyRectClient, client, ());
+ Chunk(client,
+ static_cast<DisplayItem::Type>(DisplayItem::kDrawingFirst + id));
+ // The default bounds with magic numbers make the chunks have different bounds
+ // from each other, for e.g. RasterInvalidatorTest to check the tracked raster
+ // invalidation rects of chunks. The actual values don't matter. If the chunk
+ // has display items, we will recalculate the bounds from the display items
+ // when constructing the PaintArtifact.
+ Bounds(FloatRect(id * 110, id * 220, id * 220 + 200, id * 110 + 200));
+ return *this;
}
-TestPaintArtifact& TestPaintArtifact::Chunk(
- DisplayItemClient& client,
- scoped_refptr<const TransformPaintPropertyNode> transform,
- scoped_refptr<const ClipPaintPropertyNode> clip,
- scoped_refptr<const EffectPaintPropertyNode> effect) {
- return Chunk(client,
- PropertyTreeState(transform.get(), clip.get(), effect.get()));
+TestPaintArtifact& TestPaintArtifact::Chunk(FakeDisplayItemClient& client,
+ DisplayItem::Type type) {
+ if (!paint_chunks_.IsEmpty())
+ paint_chunks_.back().end_index = display_item_list_.size();
+ paint_chunks_.push_back(PaintChunk(display_item_list_.size(), 0,
+ PaintChunk::Id(client, type),
+ PropertyTreeState::Root()));
+ // Assume PaintController has processed this chunk.
+ paint_chunks_.back().client_is_just_created = false;
+ return *this;
}
-TestPaintArtifact& TestPaintArtifact::Chunk(
+TestPaintArtifact& TestPaintArtifact::Properties(
const PropertyTreeState& properties) {
- return Chunk(NewClient(), properties);
-}
-
-TestPaintArtifact& TestPaintArtifact::Chunk(DisplayItemClient& client,
- const PropertyTreeState& state) {
- auto& chunks = paint_chunks_data_.chunks;
- if (!chunks.IsEmpty())
- chunks.back().end_index = display_item_list_.size();
- chunks.push_back(
- PaintChunk(display_item_list_.size(), 0,
- PaintChunk::Id(client, DisplayItem::kDrawingFirst), state));
- // Assume PaintController has processed this chunk.
- chunks.back().client_is_just_created = false;
+ paint_chunks_.back().properties = properties;
return *this;
}
@@ -82,7 +78,18 @@ TestPaintArtifact& TestPaintArtifact::RectDrawing(const FloatRect& bounds,
return RectDrawing(NewClient(), bounds, color);
}
-TestPaintArtifact& TestPaintArtifact::RectDrawing(DisplayItemClient& client,
+TestPaintArtifact& TestPaintArtifact::ForeignLayer(
+ const FloatPoint& location,
+ const IntSize& size,
+ scoped_refptr<cc::Layer> layer) {
+ return ForeignLayer(NewClient(), location, size, std::move(layer));
+}
+TestPaintArtifact& TestPaintArtifact::ScrollHitTest(
+ const TransformPaintPropertyNode& scroll_offset) {
+ return ScrollHitTest(NewClient(), scroll_offset);
+}
+
+TestPaintArtifact& TestPaintArtifact::RectDrawing(FakeDisplayItemClient& client,
const FloatRect& bounds,
Color color) {
display_item_list_.AllocateAndConstruct<DrawingDisplayItem>(
@@ -92,14 +99,7 @@ TestPaintArtifact& TestPaintArtifact::RectDrawing(DisplayItemClient& client,
}
TestPaintArtifact& TestPaintArtifact::ForeignLayer(
- const FloatPoint& location,
- const IntSize& size,
- scoped_refptr<cc::Layer> layer) {
- return ForeignLayer(NewClient(), location, size, layer);
-}
-
-TestPaintArtifact& TestPaintArtifact::ForeignLayer(
- DisplayItemClient& client,
+ FakeDisplayItemClient& client,
const FloatPoint& location,
const IntSize& size,
scoped_refptr<cc::Layer> layer) {
@@ -112,41 +112,41 @@ TestPaintArtifact& TestPaintArtifact::ForeignLayer(
}
TestPaintArtifact& TestPaintArtifact::ScrollHitTest(
- scoped_refptr<const TransformPaintPropertyNode> scroll_offset) {
- return ScrollHitTest(NewClient(), scroll_offset);
-}
-
-TestPaintArtifact& TestPaintArtifact::ScrollHitTest(
- DisplayItemClient& client,
- scoped_refptr<const TransformPaintPropertyNode> scroll_offset) {
+ FakeDisplayItemClient& client,
+ const TransformPaintPropertyNode& scroll_offset) {
display_item_list_.AllocateAndConstruct<ScrollHitTestDisplayItem>(
- client, DisplayItem::kScrollHitTest, std::move(scroll_offset));
+ client, scroll_offset);
return *this;
}
TestPaintArtifact& TestPaintArtifact::KnownToBeOpaque() {
- paint_chunks_data_.chunks.back().known_to_be_opaque = true;
+ paint_chunks_.back().known_to_be_opaque = true;
return *this;
}
-const PaintArtifact& TestPaintArtifact::Build() {
- if (built_)
- return paint_artifact_;
+TestPaintArtifact& TestPaintArtifact::Bounds(const FloatRect& bounds) {
+ paint_chunks_.back().bounds = bounds;
+ return *this;
+}
+
+TestPaintArtifact& TestPaintArtifact::Uncacheable() {
+ paint_chunks_.back().is_cacheable = false;
+ return *this;
+}
- if (!paint_chunks_data_.chunks.IsEmpty())
- paint_chunks_data_.chunks.back().end_index = display_item_list_.size();
- paint_artifact_ = PaintArtifact(std::move(display_item_list_),
- std::move(paint_chunks_data_));
- built_ = true;
- return paint_artifact_;
+scoped_refptr<PaintArtifact> TestPaintArtifact::Build() {
+ if (!paint_chunks_.IsEmpty())
+ paint_chunks_.back().end_index = display_item_list_.size();
+ return PaintArtifact::Create(std::move(display_item_list_),
+ std::move(paint_chunks_));
}
-DisplayItemClient& TestPaintArtifact::NewClient() {
+FakeDisplayItemClient& TestPaintArtifact::NewClient() {
dummy_clients_.push_back(std::make_unique<DummyRectClient>());
return *dummy_clients_.back();
}
-DisplayItemClient& TestPaintArtifact::Client(size_t i) const {
+FakeDisplayItemClient& TestPaintArtifact::Client(size_t i) const {
return *dummy_clients_[i];
}
diff --git a/chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.h b/chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.h
index 81aea7b349e..f69602b24af 100644
--- a/chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.h
+++ b/chromium/third_party/blink/renderer/platform/testing/test_paint_artifact.h
@@ -10,7 +10,7 @@
#include "third_party/blink/renderer/platform/graphics/color.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item_list.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
-#include "third_party/blink/renderer/platform/graphics/paint/transform_paint_property_node.h"
+#include "third_party/blink/renderer/platform/testing/fake_display_item_client.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -27,17 +27,25 @@ class PaintArtifact;
class TransformPaintPropertyNode;
// Useful for quickly making a paint artifact in unit tests.
-// Must remain in scope while the paint artifact is used, because it owns the
-// display item clients.
//
+// If any method that automatically creates display item client is called, the
+// object must remain in scope while the paint artifact is used, because it owns
+// the display item clients.
// Usage:
-// TestPaintArtifact artifact;
-// artifact.Chunk(paintProperties)
+// TestPaintArtifact test_artifact;
+// test_artifact.Chunk().Properties(paint_properties)
// .RectDrawing(bounds, color)
// .RectDrawing(bounds2, color2);
-// artifact.Chunk(otherPaintProperties)
+// test_artifact.Chunk().Properties(other_paint_properties)
// .RectDrawing(bounds3, color3);
+// auto artifact = test_artifact.Build();
// DoSomethingWithArtifact(artifact);
+//
+// Otherwise the TestPaintArtifact object can be temporary.
+// Usage:
+// auto artifact = TestPaintArtifact().Chunk(0).Chunk(1).Build();
+// DoSomethingWithArtifact(artifact);
+//
class TestPaintArtifact {
STACK_ALLOCATED();
@@ -45,57 +53,88 @@ class TestPaintArtifact {
TestPaintArtifact();
~TestPaintArtifact();
- // Add to the artifact.
- TestPaintArtifact& Chunk(scoped_refptr<const TransformPaintPropertyNode>,
- scoped_refptr<const ClipPaintPropertyNode>,
- scoped_refptr<const EffectPaintPropertyNode>);
- TestPaintArtifact& Chunk(const PropertyTreeState&);
- TestPaintArtifact& RectDrawing(const FloatRect& bounds, Color);
- TestPaintArtifact& ForeignLayer(const FloatPoint&,
- const IntSize&,
- scoped_refptr<cc::Layer>);
+ // Add a chunk to the artifact. Each chunk will have a different automatically
+ // created client.
+ TestPaintArtifact& Chunk() { return Chunk(NewClient()); }
+
+ // Add a chunk with the specified client.
+ TestPaintArtifact& Chunk(FakeDisplayItemClient&,
+ DisplayItem::Type = DisplayItem::kDrawingFirst);
+
+ // This is for RasterInvalidatorTest, to create a chunk with specific id and
+ // bounds calculated with a function from the id. The client is static so
+ // the caller doesn't need to retain this object when using the paint
+ // artifact.
+ TestPaintArtifact& Chunk(int id);
+
+ TestPaintArtifact& Properties(const PropertyTreeState&);
+ TestPaintArtifact& Properties(const TransformPaintPropertyNode& transform,
+ const ClipPaintPropertyNode& clip,
+ const EffectPaintPropertyNode& effect) {
+ return Properties(PropertyTreeState(&transform, &clip, &effect));
+ }
+ TestPaintArtifact& Properties(const RefCountedPropertyTreeState& properties) {
+ return Properties(properties.GetPropertyTreeState());
+ }
+
+ // Shorthands of Chunk().Properties(...).
+ TestPaintArtifact& Chunk(const TransformPaintPropertyNode& transform,
+ const ClipPaintPropertyNode& clip,
+ const EffectPaintPropertyNode& effect) {
+ return Chunk().Properties(transform, clip, effect);
+ }
+ TestPaintArtifact& Chunk(const PropertyTreeState& properties) {
+ return Chunk().Properties(properties);
+ }
+ TestPaintArtifact& Chunk(const RefCountedPropertyTreeState& properties) {
+ return Chunk().Properties(properties);
+ }
+
+ // Add display item in the chunk. Each display item will have a different
+ // automatically created client.
+ TestPaintArtifact& RectDrawing(const FloatRect& bounds, Color color);
+ TestPaintArtifact& ForeignLayer(const FloatPoint& location,
+ const IntSize& size,
+ scoped_refptr<cc::Layer> layer);
TestPaintArtifact& ScrollHitTest(
- scoped_refptr<const TransformPaintPropertyNode> scroll_offset);
- TestPaintArtifact& KnownToBeOpaque();
+ const TransformPaintPropertyNode& scroll_offset);
- // Add to the artifact, with specified display item client. These are used
- // to test incremental paint artifact updates.
- TestPaintArtifact& Chunk(DisplayItemClient&,
- scoped_refptr<const TransformPaintPropertyNode>,
- scoped_refptr<const ClipPaintPropertyNode>,
- scoped_refptr<const EffectPaintPropertyNode>);
- TestPaintArtifact& Chunk(DisplayItemClient&, const PropertyTreeState&);
- TestPaintArtifact& RectDrawing(DisplayItemClient&,
+ // Add display item with the specified client in the chunk.
+ TestPaintArtifact& RectDrawing(FakeDisplayItemClient&,
const FloatRect& bounds,
Color);
- TestPaintArtifact& ForeignLayer(DisplayItemClient&,
+ TestPaintArtifact& ForeignLayer(FakeDisplayItemClient&,
const FloatPoint&,
const IntSize&,
scoped_refptr<cc::Layer>);
TestPaintArtifact& ScrollHitTest(
- DisplayItemClient&,
- scoped_refptr<const TransformPaintPropertyNode> scroll_offset);
+ FakeDisplayItemClient&,
+ const TransformPaintPropertyNode& scroll_offset);
+
+ // Sets fake bounds for the last paint chunk. Note that the bounds will be
+ // overwritten when the PaintArtifact is constructed if the chunk has any
+ // display items.
+ TestPaintArtifact& Bounds(const FloatRect&);
+
+ TestPaintArtifact& KnownToBeOpaque();
+ TestPaintArtifact& Uncacheable();
- // Can't add more things once this is called.
- const PaintArtifact& Build();
+ // Build the paint artifact. After that, if this object has automatically
+ // created any display item client, the caller must retain this object when
+ // using the returned paint artifact.
+ scoped_refptr<PaintArtifact> Build();
// Create a new display item client which is owned by this TestPaintArtifact.
- DisplayItemClient& NewClient();
+ FakeDisplayItemClient& NewClient();
- DisplayItemClient& Client(size_t) const;
+ FakeDisplayItemClient& Client(size_t) const;
private:
class DummyRectClient;
Vector<std::unique_ptr<DummyRectClient>> dummy_clients_;
- // Exists if m_built is false.
DisplayItemList display_item_list_;
- PaintChunksAndRasterInvalidations paint_chunks_data_;
-
- // Exists if m_built is true.
- PaintArtifact paint_artifact_;
-
- bool built_;
+ Vector<PaintChunk> paint_chunks_;
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/testing/testing_platform_support.cc b/chromium/third_party/blink/renderer/platform/testing/testing_platform_support.cc
index 56fbb23341b..6b51f9a6e16 100644
--- a/chromium/third_party/blink/renderer/platform/testing/testing_platform_support.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/testing_platform_support.cc
@@ -49,8 +49,6 @@
#include "third_party/blink/renderer/platform/loader/fetch/fetch_initiator_type_names.h"
#include "third_party/blink/renderer/platform/network/http_names.h"
#include "third_party/blink/renderer/platform/network/mime/mock_mime_registry.h"
-#include "third_party/blink/renderer/platform/scheduler/base/real_time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
#include "third_party/blink/renderer/platform/wtf/wtf.h"
@@ -65,6 +63,11 @@ class TestingPlatformSupport::TestingInterfaceProvider
void GetInterface(const char* name,
mojo::ScopedMessagePipeHandle handle) override {
+ auto& override_callback = GetOverrideCallback();
+ if (!override_callback.is_null()) {
+ override_callback.Run(name, std::move(handle));
+ return;
+ }
if (std::string(name) == mojom::blink::MimeRegistry::Name_) {
mojo::MakeStrongBinding(
std::make_unique<MockMimeRegistry>(),
@@ -72,8 +75,23 @@ class TestingPlatformSupport::TestingInterfaceProvider
return;
}
}
+
+ static ScopedOverrideMojoInterface::GetInterfaceCallback&
+ GetOverrideCallback() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ ScopedOverrideMojoInterface::GetInterfaceCallback, callback, ());
+ return callback;
+ }
};
+TestingPlatformSupport::ScopedOverrideMojoInterface::
+ ScopedOverrideMojoInterface(GetInterfaceCallback callback)
+ : auto_reset_(&TestingInterfaceProvider::GetOverrideCallback(),
+ std::move(callback)) {}
+
+TestingPlatformSupport::ScopedOverrideMojoInterface::
+ ~ScopedOverrideMojoInterface() = default;
+
namespace {
class DummyThread final : public blink::WebThread {
diff --git a/chromium/third_party/blink/renderer/platform/testing/testing_platform_support.h b/chromium/third_party/blink/renderer/platform/testing/testing_platform_support.h
index b160d9a4261..cf5dec66d5c 100644
--- a/chromium/third_party/blink/renderer/platform/testing/testing_platform_support.h
+++ b/chromium/third_party/blink/renderer/platform/testing/testing_platform_support.h
@@ -34,6 +34,8 @@
#include <memory>
#include <utility>
+#include "base/auto_reset.h"
+#include "base/callback.h"
#include "base/macros.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/platform/platform_export.h"
@@ -69,6 +71,20 @@ class TestingPlatformSupport : public Platform {
virtual void RunUntilIdle();
+ // Overrides the handling of GetInterface on the platform's associated
+ // interface provider.
+ class ScopedOverrideMojoInterface {
+ public:
+ using GetInterfaceCallback =
+ base::RepeatingCallback<void(const char*,
+ mojo::ScopedMessagePipeHandle)>;
+ explicit ScopedOverrideMojoInterface(GetInterfaceCallback);
+ ~ScopedOverrideMojoInterface();
+
+ private:
+ base::AutoReset<GetInterfaceCallback> auto_reset_;
+ };
+
protected:
class TestingInterfaceProvider;
diff --git a/chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.cc b/chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.cc
index 810f5dc3ed7..790a4296495 100644
--- a/chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.cc
@@ -5,9 +5,9 @@
#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h"
#include "base/bind.h"
-#include "components/viz/test/ordered_simple_task_runner.h"
+#include "base/task/sequence_manager/test/sequence_manager_for_test.h"
+#include "base/test/test_mock_time_task_runner.h"
#include "third_party/blink/public/platform/scheduler/child/webthread_base.h"
-#include "third_party/blink/renderer/platform/scheduler/base/real_time_domain.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
#include "third_party/blink/renderer/platform/waitable_event.h"
#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
@@ -35,18 +35,19 @@ void PrepareCurrentThread(WaitableEvent* event, WebThread* thread) {
TestingPlatformSupportWithMockScheduler::
TestingPlatformSupportWithMockScheduler()
- : mock_task_runner_(
- base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, true)) {
+ : test_task_runner_(base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::TestMockTimeTaskRunner::Type::kStandalone)) {
DCHECK(IsMainThread());
- std::unique_ptr<base::sequence_manager::TaskQueueManagerForTest>
- task_queue_manager =
- base::sequence_manager::TaskQueueManagerForTest::Create(
- nullptr, mock_task_runner_, &clock_);
- task_queue_manager_ = task_queue_manager.get();
+ test_task_runner_->AdvanceMockTickClock(base::TimeDelta::FromSeconds(1));
+ std::unique_ptr<base::sequence_manager::SequenceManagerForTest>
+ sequence_manager = base::sequence_manager::SequenceManagerForTest::Create(
+ nullptr, test_task_runner_, test_task_runner_->GetMockTickClock());
+ sequence_manager_ = sequence_manager.get();
+
scheduler_ = std::make_unique<scheduler::MainThreadSchedulerImpl>(
- std::move(task_queue_manager), base::nullopt);
+ std::move(sequence_manager), base::nullopt);
thread_ = scheduler_->CreateMainThread();
- // Set the work batch size to one so RunPendingTasks behaves as expected.
+ // Set the work batch size to one so TakePendingTasks behaves as expected.
scheduler_->GetSchedulerHelperForTesting()->SetWorkBatchSizeForTesting(1);
WTF::SetTimeFunctionsForTesting(GetTestTime);
@@ -84,51 +85,51 @@ WebThread* TestingPlatformSupportWithMockScheduler::CurrentThread() {
}
void TestingPlatformSupportWithMockScheduler::RunSingleTask() {
- mock_task_runner_->SetRunTaskLimit(1);
- mock_task_runner_->RunPendingTasks();
- mock_task_runner_->ClearRunTaskLimit();
+ base::circular_deque<base::TestPendingTask> tasks =
+ test_task_runner_->TakePendingTasks();
+ if (tasks.empty())
+ return;
+ // Scheduler doesn't post more than one task.
+ DCHECK_EQ(tasks.size(), 1u);
+ base::TestPendingTask task = std::move(tasks.front());
+ tasks.clear();
+ // Set clock to the beginning of task and run it.
+ test_task_runner_->AdvanceMockTickClock(task.GetTimeToRun() -
+ test_task_runner_->NowTicks());
+ std::move(task.task).Run();
}
void TestingPlatformSupportWithMockScheduler::RunUntilIdle() {
- mock_task_runner_->RunUntilIdle();
+ if (auto_advance_) {
+ test_task_runner_->FastForwardUntilNoTasksRemain();
+ } else {
+ test_task_runner_->RunUntilIdle();
+ }
}
void TestingPlatformSupportWithMockScheduler::RunForPeriodSeconds(
double seconds) {
- const base::TimeTicks deadline =
- clock_.NowTicks() + base::TimeDelta::FromSecondsD(seconds);
-
- for (;;) {
- // If we've run out of immediate work then fast forward to the next delayed
- // task, but don't pass |deadline|.
- if (!task_queue_manager_->HasImmediateWork()) {
- base::TimeTicks next_delayed_task;
- if (!task_queue_manager_->GetRealTimeDomain()->NextScheduledRunTime(
- &next_delayed_task) ||
- next_delayed_task > deadline) {
- break;
- }
-
- clock_.SetNowTicks(next_delayed_task);
- }
-
- if (clock_.NowTicks() > deadline)
- break;
-
- mock_task_runner_->RunPendingTasks();
- }
+ RunForPeriod(base::TimeDelta::FromSecondsD(seconds));
+}
- clock_.SetNowTicks(deadline);
+void TestingPlatformSupportWithMockScheduler::RunForPeriod(
+ base::TimeDelta period) {
+ test_task_runner_->FastForwardBy(period);
}
void TestingPlatformSupportWithMockScheduler::AdvanceClockSeconds(
double seconds) {
- clock_.Advance(base::TimeDelta::FromSecondsD(seconds));
+ AdvanceClock(base::TimeDelta::FromSecondsD(seconds));
+}
+
+void TestingPlatformSupportWithMockScheduler::AdvanceClock(
+ base::TimeDelta duration) {
+ test_task_runner_->AdvanceMockTickClock(duration);
}
void TestingPlatformSupportWithMockScheduler::SetAutoAdvanceNowToPendingTasks(
bool auto_advance) {
- mock_task_runner_->SetAutoAdvanceNowToPendingTasks(auto_advance);
+ auto_advance_ = auto_advance;
}
scheduler::MainThreadSchedulerImpl*
@@ -141,7 +142,8 @@ double TestingPlatformSupportWithMockScheduler::GetTestTime() {
TestingPlatformSupportWithMockScheduler* platform =
static_cast<TestingPlatformSupportWithMockScheduler*>(
Platform::Current());
- return (platform->clock_.NowTicks() - base::TimeTicks()).InSecondsF();
+ return (platform->test_task_runner_->NowTicks() - base::TimeTicks())
+ .InSecondsF();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h b/chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h
index c22570c3e55..785f456df47 100644
--- a/chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h
+++ b/chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h
@@ -6,15 +6,19 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_TESTING_PLATFORM_SUPPORT_WITH_MOCK_SCHEDULER_H_
#include <memory>
-#include "base/test/simple_test_tick_clock.h"
#include "third_party/blink/public/platform/web_thread.h"
-#include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
-namespace cc {
-class OrderedSimpleTaskRunner;
-}
+namespace base {
+
+class TestMockTimeTaskRunner;
+
+namespace sequence_manager {
+class SequenceManager;
+} // namespace sequence_manager
+
+} // namespace base
namespace blink {
@@ -52,9 +56,11 @@ class TestingPlatformSupportWithMockScheduler : public TestingPlatformSupport {
// time elapsed will typically much less than |seconds| because delays between
// timers are fast forwarded.
void RunForPeriodSeconds(double seconds);
+ void RunForPeriod(base::TimeDelta period);
- // Advances |m_clock| by |seconds|.
+ // Advances |clock_| by |seconds|.
void AdvanceClockSeconds(double seconds);
+ void AdvanceClock(base::TimeDelta duration);
scheduler::MainThreadSchedulerImpl* GetMainThreadScheduler() const;
@@ -65,11 +71,12 @@ class TestingPlatformSupportWithMockScheduler : public TestingPlatformSupport {
protected:
static double GetTestTime();
- base::SimpleTestTickClock clock_;
- scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
+ scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_;
+ bool auto_advance_ = true;
+
std::unique_ptr<scheduler::MainThreadSchedulerImpl> scheduler_;
- base::sequence_manager::TaskQueueManagerForTest*
- task_queue_manager_; // Owned by scheduler_.
+ base::sequence_manager::SequenceManager*
+ sequence_manager_; // Owned by scheduler_.
std::unique_ptr<WebThread> thread_;
};
diff --git a/chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_web_rtc.cc b/chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_web_rtc.cc
index 53e4a2fdac9..db69771b88a 100644
--- a/chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_web_rtc.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_web_rtc.cc
@@ -5,10 +5,10 @@
#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_web_rtc.h"
#include <memory>
+#include "third_party/blink/public/platform/web_media_stream.h"
#include "third_party/blink/public/platform/web_media_stream_track.h"
#include "third_party/blink/public/platform/web_rtc_dtmf_sender_handler.h"
-#include "third_party/blink/public/platform/web_rtc_rtp_receiver.h"
-#include "third_party/blink/public/platform/web_rtc_rtp_sender.h"
+#include "third_party/blink/public/platform/web_rtc_rtp_transceiver.h"
#include "third_party/blink/public/platform/web_rtc_session_description.h"
#include "third_party/blink/public/platform/web_vector.h"
@@ -21,11 +21,18 @@ class DummyWebRTCRtpSender : public WebRTCRtpSender {
static uintptr_t last_id_;
public:
- DummyWebRTCRtpSender() : id_(++last_id_) {}
+ DummyWebRTCRtpSender(WebMediaStreamTrack track)
+ : id_(++last_id_), track_(std::move(track)) {}
~DummyWebRTCRtpSender() override {}
+ std::unique_ptr<WebRTCRtpSender> ShallowCopy() const override {
+ return nullptr;
+ }
uintptr_t Id() const override { return id_; }
- WebMediaStreamTrack Track() const override { return WebMediaStreamTrack(); }
+ WebMediaStreamTrack Track() const override { return track_; }
+ WebVector<WebString> StreamIds() const override {
+ return std::vector<WebString>({WebString::FromUTF8("DummyStringId")});
+ }
void ReplaceTrack(WebMediaStreamTrack, WebRTCVoidRequest) override {}
std::unique_ptr<WebRTCDTMFSenderHandler> GetDtmfSender() const override {
return nullptr;
@@ -38,12 +45,50 @@ class DummyWebRTCRtpSender : public WebRTCRtpSender {
WebRTCVoidRequest) override {}
void GetStats(std::unique_ptr<blink::WebRTCStatsReportCallback>) override {}
+ void set_track(WebMediaStreamTrack track) { track_ = std::move(track); }
+
private:
const uintptr_t id_;
+ WebMediaStreamTrack track_;
};
uintptr_t DummyWebRTCRtpSender::last_id_ = 0;
+class DummyRTCRtpTransceiver : public WebRTCRtpTransceiver {
+ public:
+ DummyRTCRtpTransceiver(WebMediaStreamTrack track)
+ : track_(std::move(track)) {}
+ ~DummyRTCRtpTransceiver() override {}
+
+ WebRTCRtpTransceiverImplementationType ImplementationType() const override {
+ return WebRTCRtpTransceiverImplementationType::kPlanBSenderOnly;
+ }
+ uintptr_t Id() const override { return 0u; }
+ WebString Mid() const override { return WebString(); }
+ std::unique_ptr<WebRTCRtpSender> Sender() const override {
+ return std::make_unique<DummyWebRTCRtpSender>(track_);
+ }
+ std::unique_ptr<WebRTCRtpReceiver> Receiver() const override {
+ return nullptr;
+ }
+ bool Stopped() const override { return true; }
+ webrtc::RtpTransceiverDirection Direction() const override {
+ return webrtc::RtpTransceiverDirection::kInactive;
+ }
+ void SetDirection(webrtc::RtpTransceiverDirection) override {}
+ base::Optional<webrtc::RtpTransceiverDirection> CurrentDirection()
+ const override {
+ return base::nullopt;
+ }
+ base::Optional<webrtc::RtpTransceiverDirection> FiredDirection()
+ const override {
+ return base::nullopt;
+ }
+
+ private:
+ WebMediaStreamTrack track_;
+};
+
} // namespace
MockWebRTCPeerConnectionHandler::MockWebRTCPeerConnectionHandler() = default;
@@ -51,7 +96,8 @@ MockWebRTCPeerConnectionHandler::MockWebRTCPeerConnectionHandler() = default;
MockWebRTCPeerConnectionHandler::~MockWebRTCPeerConnectionHandler() = default;
bool MockWebRTCPeerConnectionHandler::Initialize(const WebRTCConfiguration&,
- const WebMediaConstraints&) {
+ const WebMediaConstraints&,
+ WebRTCSdpSemantics) {
return true;
}
@@ -97,14 +143,36 @@ void MockWebRTCPeerConnectionHandler::GetStats(const WebRTCStatsRequest&) {}
void MockWebRTCPeerConnectionHandler::GetStats(
std::unique_ptr<WebRTCStatsReportCallback>) {}
-std::unique_ptr<WebRTCRtpSender> MockWebRTCPeerConnectionHandler::AddTrack(
- const WebMediaStreamTrack&,
- const WebVector<WebMediaStream>&) {
- return std::make_unique<DummyWebRTCRtpSender>();
+webrtc::RTCErrorOr<std::unique_ptr<WebRTCRtpTransceiver>>
+MockWebRTCPeerConnectionHandler::AddTransceiverWithTrack(
+ const WebMediaStreamTrack& track,
+ const webrtc::RtpTransceiverInit&) {
+ std::unique_ptr<WebRTCRtpTransceiver> transceiver =
+ std::make_unique<DummyRTCRtpTransceiver>(track);
+ return transceiver;
}
-bool MockWebRTCPeerConnectionHandler::RemoveTrack(WebRTCRtpSender*) {
- return true;
+webrtc::RTCErrorOr<std::unique_ptr<WebRTCRtpTransceiver>>
+MockWebRTCPeerConnectionHandler::AddTransceiverWithKind(
+ std::string kind,
+ const webrtc::RtpTransceiverInit&) {
+ std::unique_ptr<WebRTCRtpTransceiver> transceiver =
+ std::make_unique<DummyRTCRtpTransceiver>(WebMediaStreamTrack());
+ return transceiver;
+}
+
+webrtc::RTCErrorOr<std::unique_ptr<WebRTCRtpTransceiver>>
+MockWebRTCPeerConnectionHandler::AddTrack(const WebMediaStreamTrack& track,
+ const WebVector<WebMediaStream>&) {
+ std::unique_ptr<WebRTCRtpTransceiver> transceiver =
+ std::make_unique<DummyRTCRtpTransceiver>(track);
+ return transceiver;
+}
+
+webrtc::RTCErrorOr<std::unique_ptr<WebRTCRtpTransceiver>>
+MockWebRTCPeerConnectionHandler::RemoveTrack(WebRTCRtpSender* sender) {
+ static_cast<DummyWebRTCRtpSender*>(sender)->set_track(WebMediaStreamTrack());
+ return std::unique_ptr<WebRTCRtpTransceiver>(nullptr);
}
WebRTCDataChannelHandler* MockWebRTCPeerConnectionHandler::CreateDataChannel(
diff --git a/chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_web_rtc.h b/chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_web_rtc.h
index b3cd0e4c8df..091f79d6570 100644
--- a/chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_web_rtc.h
+++ b/chromium/third_party/blink/renderer/platform/testing/testing_platform_support_with_web_rtc.h
@@ -17,7 +17,8 @@ class MockWebRTCPeerConnectionHandler : public WebRTCPeerConnectionHandler {
~MockWebRTCPeerConnectionHandler() override;
bool Initialize(const WebRTCConfiguration&,
- const WebMediaConstraints&) override;
+ const WebMediaConstraints&,
+ WebRTCSdpSemantics original_sdp_semantics_value) override;
void CreateOffer(const WebRTCSessionDescriptionRequest&,
const WebMediaConstraints&) override;
@@ -36,10 +37,17 @@ class MockWebRTCPeerConnectionHandler : public WebRTCPeerConnectionHandler {
webrtc::RTCErrorType SetConfiguration(const WebRTCConfiguration&) override;
void GetStats(const WebRTCStatsRequest&) override;
void GetStats(std::unique_ptr<WebRTCStatsReportCallback>) override;
- std::unique_ptr<WebRTCRtpSender> AddTrack(
+ webrtc::RTCErrorOr<std::unique_ptr<WebRTCRtpTransceiver>>
+ AddTransceiverWithTrack(const WebMediaStreamTrack&,
+ const webrtc::RtpTransceiverInit&) override;
+ webrtc::RTCErrorOr<std::unique_ptr<WebRTCRtpTransceiver>>
+ AddTransceiverWithKind(std::string kind,
+ const webrtc::RtpTransceiverInit&) override;
+ webrtc::RTCErrorOr<std::unique_ptr<WebRTCRtpTransceiver>> AddTrack(
const WebMediaStreamTrack&,
const WebVector<WebMediaStream>&) override;
- bool RemoveTrack(WebRTCRtpSender*) override;
+ webrtc::RTCErrorOr<std::unique_ptr<WebRTCRtpTransceiver>> RemoveTrack(
+ WebRTCRtpSender*) override;
WebRTCDataChannelHandler* CreateDataChannel(
const WebString& label,
const WebRTCDataChannelInit&) override;
diff --git a/chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.cc b/chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.cc
index 60235e9d3df..05c5480d3fb 100644
--- a/chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/unit_test_helpers.cc
@@ -36,6 +36,7 @@
#include "third_party/blink/public/platform/web_thread.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/shared_buffer.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
namespace blink {
diff --git a/chromium/third_party/blink/renderer/platform/testing/use_mock_scrollbar_settings.h b/chromium/third_party/blink/renderer/platform/testing/use_mock_scrollbar_settings.h
deleted file mode 100644
index 64cb943a027..00000000000
--- a/chromium/third_party/blink/renderer/platform/testing/use_mock_scrollbar_settings.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_USE_MOCK_SCROLLBAR_SETTINGS_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_USE_MOCK_SCROLLBAR_SETTINGS_H_
-
-#include "third_party/blink/renderer/platform/scroll/scrollbar_theme.h"
-#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
-
-namespace blink {
-
-// Forces to use mocked overlay scrollbars instead of the default native theme
-// scrollbars to avoid crash in Chromium code when it tries to load UI
-// resources that are not available when running blink unit tests, and to
-// ensure consistent layout regardless of differences between scrollbar themes.
-// WebViewHelper includes this, so this is only needed if a test doesn't use
-// WebViewHelper or the test needs a bigger scope of mock scrollbar settings
-// than the scope of WebViewHelper.
-class UseMockScrollbarSettings : private ScopedOverlayScrollbarsForTest {
- public:
- UseMockScrollbarSettings()
- : ScopedOverlayScrollbarsForTest(true),
- original_mock_scrollbar_enabled_(
- ScrollbarTheme::MockScrollbarsEnabled()),
- original_overlay_scrollbars_enabled_(
- RuntimeEnabledFeatures::OverlayScrollbarsEnabled()) {
- ScrollbarTheme::SetMockScrollbarsEnabled(true);
- }
-
- UseMockScrollbarSettings(bool use_mock, bool use_overlay)
- : ScopedOverlayScrollbarsForTest(use_overlay),
- original_mock_scrollbar_enabled_(
- ScrollbarTheme::MockScrollbarsEnabled()),
- original_overlay_scrollbars_enabled_(
- RuntimeEnabledFeatures::OverlayScrollbarsEnabled()) {
- ScrollbarTheme::SetMockScrollbarsEnabled(use_mock);
- }
-
- ~UseMockScrollbarSettings() {
- ScrollbarTheme::SetMockScrollbarsEnabled(original_mock_scrollbar_enabled_);
- }
-
- private:
- bool original_mock_scrollbar_enabled_;
- bool original_overlay_scrollbars_enabled_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_USE_MOCK_SCROLLBAR_SETTINGS_H_
diff --git a/chromium/third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.cc b/chromium/third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.cc
deleted file mode 100644
index 4343a44b45b..00000000000
--- a/chromium/third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.cc
+++ /dev/null
@@ -1,195 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.h"
-
-#include "base/threading/thread_task_runner_handle.h"
-#include "cc/animation/animation_host.h"
-#include "cc/animation/animation_timeline.h"
-#include "cc/layers/layer.h"
-#include "cc/trees/layer_tree_host.h"
-#include "cc/trees/layer_tree_settings.h"
-#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/web_layer_tree_view.h"
-#include "third_party/blink/public/platform/web_size.h"
-
-namespace blink {
-
-WebLayerTreeViewImplForTesting::WebLayerTreeViewImplForTesting()
- : WebLayerTreeViewImplForTesting(DefaultLayerTreeSettings()) {}
-
-WebLayerTreeViewImplForTesting::WebLayerTreeViewImplForTesting(
- const cc::LayerTreeSettings& settings) {
- animation_host_ = cc::AnimationHost::CreateMainInstance();
- cc::LayerTreeHost::InitParams params;
- params.client = this;
- params.settings = &settings;
- params.main_task_runner = base::ThreadTaskRunnerHandle::Get();
- params.task_graph_runner = &task_graph_runner_;
- params.mutator_host = animation_host_.get();
- layer_tree_host_ = cc::LayerTreeHost::CreateSingleThreaded(this, &params);
- DCHECK(layer_tree_host_);
-}
-
-WebLayerTreeViewImplForTesting::~WebLayerTreeViewImplForTesting() = default;
-
-// static
-cc::LayerTreeSettings
-WebLayerTreeViewImplForTesting::DefaultLayerTreeSettings() {
- cc::LayerTreeSettings settings;
-
- // For web contents, layer transforms should scale up the contents of layers
- // to keep content always crisp when possible.
- settings.layer_transforms_should_scale_layer_contents = true;
-
- return settings;
-}
-
-bool WebLayerTreeViewImplForTesting::HasLayer(const cc::Layer& layer) {
- return layer.GetLayerTreeHostForTesting() == layer_tree_host_.get();
-}
-
-void WebLayerTreeViewImplForTesting::SetViewportSize(
- const WebSize& device_viewport_size) {
- gfx::Size gfx_size(std::max(0, device_viewport_size.width),
- std::max(0, device_viewport_size.height));
- // TODO(ccameron): This likely causes surface invariant violations.
- layer_tree_host_->SetViewportSizeAndScale(
- gfx_size, layer_tree_host_->device_scale_factor(),
- layer_tree_host_->local_surface_id_from_parent());
-}
-
-void WebLayerTreeViewImplForTesting::SetRootLayer(
- scoped_refptr<cc::Layer> root) {
- layer_tree_host_->SetRootLayer(root);
-}
-
-void WebLayerTreeViewImplForTesting::ClearRootLayer() {
- layer_tree_host_->SetRootLayer(scoped_refptr<cc::Layer>());
-}
-
-cc::AnimationHost* WebLayerTreeViewImplForTesting::CompositorAnimationHost() {
- return animation_host_.get();
-}
-
-WebSize WebLayerTreeViewImplForTesting::GetViewportSize() const {
- return WebSize(layer_tree_host_->device_viewport_size().width(),
- layer_tree_host_->device_viewport_size().height());
-}
-
-void WebLayerTreeViewImplForTesting::SetBackgroundColor(SkColor color) {
- layer_tree_host_->set_background_color(color);
-}
-
-void WebLayerTreeViewImplForTesting::SetVisible(bool visible) {
- layer_tree_host_->SetVisible(visible);
-}
-
-void WebLayerTreeViewImplForTesting::SetPageScaleFactorAndLimits(
- float page_scale_factor,
- float minimum,
- float maximum) {
- layer_tree_host_->SetPageScaleFactorAndLimits(page_scale_factor, minimum,
- maximum);
-}
-
-void WebLayerTreeViewImplForTesting::StartPageScaleAnimation(
- const blink::WebPoint& scroll,
- bool use_anchor,
- float new_page_scale,
- double duration_sec) {}
-
-void WebLayerTreeViewImplForTesting::SetNeedsBeginFrame() {
- layer_tree_host_->SetNeedsAnimate();
-}
-
-void WebLayerTreeViewImplForTesting::DidStopFlinging() {}
-
-void WebLayerTreeViewImplForTesting::SetDeferCommits(bool defer_commits) {
- layer_tree_host_->SetDeferCommits(defer_commits);
-}
-
-void WebLayerTreeViewImplForTesting::UpdateLayerTreeHost(
- VisualStateUpdate requested_update) {}
-
-void WebLayerTreeViewImplForTesting::ApplyViewportDeltas(
- const gfx::Vector2dF& inner_delta,
- const gfx::Vector2dF& outer_delta,
- const gfx::Vector2dF& elastic_overscroll_delta,
- float page_scale,
- float browser_controls_delta) {}
-
-void WebLayerTreeViewImplForTesting::RecordWheelAndTouchScrollingCount(
- bool has_scrolled_by_wheel,
- bool has_scrolled_by_touch) {}
-
-void WebLayerTreeViewImplForTesting::RequestNewLayerTreeFrameSink() {
- // Intentionally do not create and set a LayerTreeFrameSink.
-}
-
-void WebLayerTreeViewImplForTesting::DidFailToInitializeLayerTreeFrameSink() {
- NOTREACHED();
-}
-
-void WebLayerTreeViewImplForTesting::RegisterViewportLayers(
- const WebLayerTreeView::ViewportLayers& layers) {
- cc::LayerTreeHost::ViewportLayers viewport_layers;
- if (layers.overscroll_elasticity) {
- viewport_layers.overscroll_elasticity = layers.overscroll_elasticity;
- }
- viewport_layers.page_scale = layers.page_scale;
- if (layers.inner_viewport_container) {
- viewport_layers.inner_viewport_container = layers.inner_viewport_container;
- }
- if (layers.outer_viewport_container) {
- viewport_layers.outer_viewport_container = layers.outer_viewport_container;
- }
- viewport_layers.inner_viewport_scroll = layers.inner_viewport_scroll;
- if (layers.outer_viewport_scroll) {
- viewport_layers.outer_viewport_scroll = layers.outer_viewport_scroll;
- }
- layer_tree_host_->RegisterViewportLayers(viewport_layers);
-}
-
-void WebLayerTreeViewImplForTesting::ClearViewportLayers() {
- layer_tree_host_->RegisterViewportLayers(cc::LayerTreeHost::ViewportLayers());
-}
-
-void WebLayerTreeViewImplForTesting::RegisterSelection(
- const blink::WebSelection& selection) {}
-
-void WebLayerTreeViewImplForTesting::ClearSelection() {}
-
-void WebLayerTreeViewImplForTesting::SetEventListenerProperties(
- blink::WebEventListenerClass event_class,
- blink::WebEventListenerProperties properties) {
- // Equality of static_cast is checked in render_widget_compositor.cc.
- layer_tree_host_->SetEventListenerProperties(
- static_cast<cc::EventListenerClass>(event_class),
- static_cast<cc::EventListenerProperties>(properties));
-}
-
-blink::WebEventListenerProperties
-WebLayerTreeViewImplForTesting::EventListenerProperties(
- blink::WebEventListenerClass event_class) const {
- // Equality of static_cast is checked in render_widget_compositor.cc.
- return static_cast<blink::WebEventListenerProperties>(
- layer_tree_host_->event_listener_properties(
- static_cast<cc::EventListenerClass>(event_class)));
-}
-
-void WebLayerTreeViewImplForTesting::SetHaveScrollEventHandlers(
- bool have_eent_handlers) {
- layer_tree_host_->SetHaveScrollEventHandlers(have_eent_handlers);
-}
-
-bool WebLayerTreeViewImplForTesting::HaveScrollEventHandlers() const {
- return layer_tree_host_->have_scroll_event_handlers();
-}
-
-bool WebLayerTreeViewImplForTesting::IsForSubframe() {
- return false;
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.h b/chromium/third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.h
deleted file mode 100644
index bfe8d1a3c89..00000000000
--- a/chromium/third_party/blink/renderer/platform/testing/web_layer_tree_view_impl_for_testing.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_WEB_LAYER_TREE_VIEW_IMPL_FOR_TESTING_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_WEB_LAYER_TREE_VIEW_IMPL_FOR_TESTING_H_
-
-#include <memory>
-#include "cc/test/test_task_graph_runner.h"
-#include "cc/trees/layer_tree_host_client.h"
-#include "cc/trees/layer_tree_host_single_thread_client.h"
-#include "third_party/blink/public/platform/web_layer_tree_view.h"
-#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
-
-namespace cc {
-class AnimationHost;
-class Layer;
-class LayerTreeHost;
-class LayerTreeSettings;
-}
-
-namespace blink {
-
-// Dummy WeblayerTeeView that does not support any actual compositing.
-class WebLayerTreeViewImplForTesting
- : public blink::WebLayerTreeView,
- public cc::LayerTreeHostClient,
- public cc::LayerTreeHostSingleThreadClient {
- WTF_MAKE_NONCOPYABLE(WebLayerTreeViewImplForTesting);
-
- public:
- WebLayerTreeViewImplForTesting();
- explicit WebLayerTreeViewImplForTesting(const cc::LayerTreeSettings&);
- ~WebLayerTreeViewImplForTesting() override;
-
- static cc::LayerTreeSettings DefaultLayerTreeSettings();
- cc::LayerTreeHost* GetLayerTreeHost() { return layer_tree_host_.get(); }
- bool HasLayer(const cc::Layer&);
- void SetViewportSize(const blink::WebSize&);
-
- // blink::WebLayerTreeView implementation.
- void SetRootLayer(scoped_refptr<cc::Layer>) override;
- void ClearRootLayer() override;
- cc::AnimationHost* CompositorAnimationHost() override;
- WebSize GetViewportSize() const override;
- void SetBackgroundColor(SkColor) override;
- void SetVisible(bool) override;
- void SetPageScaleFactorAndLimits(float page_scale_factor,
- float minimum,
- float maximum) override;
- void StartPageScaleAnimation(const blink::WebPoint& destination,
- bool use_anchor,
- float new_page_scale,
- double duration_sec) override;
- void SetNeedsBeginFrame() override;
- void DidStopFlinging() override;
- void SetDeferCommits(bool) override;
- void RegisterViewportLayers(const WebLayerTreeView::ViewportLayers&) override;
- void ClearViewportLayers() override;
- void RegisterSelection(const blink::WebSelection&) override;
- void ClearSelection() override;
- void SetEventListenerProperties(blink::WebEventListenerClass event_class,
- blink::WebEventListenerProperties) override;
- blink::WebEventListenerProperties EventListenerProperties(
- blink::WebEventListenerClass event_class) const override;
- void SetHaveScrollEventHandlers(bool) override;
- bool HaveScrollEventHandlers() const override;
-
- // cc::LayerTreeHostClient implementation.
- void WillBeginMainFrame() override {}
- void DidBeginMainFrame() override {}
- void BeginMainFrame(const viz::BeginFrameArgs& args) override {}
- void BeginMainFrameNotExpectedSoon() override {}
- void BeginMainFrameNotExpectedUntil(base::TimeTicks) override {}
- void UpdateLayerTreeHost(VisualStateUpdate requested_update) override;
- void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta,
- const gfx::Vector2dF& outer_delta,
- const gfx::Vector2dF& elastic_overscroll_delta,
- float page_scale,
- float browser_controls_delta) override;
- void RecordWheelAndTouchScrollingCount(bool has_scrolled_by_wheel,
- bool has_scrolled_by_touch) override;
- void RequestNewLayerTreeFrameSink() override;
- void DidInitializeLayerTreeFrameSink() override {}
- void DidFailToInitializeLayerTreeFrameSink() override;
- void WillCommit() override {}
- void DidCommit() override {}
- void DidCommitAndDrawFrame() override {}
- void DidReceiveCompositorFrameAck() override {}
- void DidCompletePageScaleAnimation() override {}
-
- bool IsForSubframe() override;
-
- // cc::LayerTreeHostSingleThreadClient implementation.
- void DidSubmitCompositorFrame() override {}
- void DidLoseLayerTreeFrameSink() override {}
-
- private:
- cc::TestTaskGraphRunner task_graph_runner_;
- std::unique_ptr<cc::AnimationHost> animation_host_;
- std::unique_ptr<cc::LayerTreeHost> layer_tree_host_;
-};
-
-} // namespace blink
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TESTING_WEB_LAYER_TREE_VIEW_IMPL_FOR_TESTING_H_
diff --git a/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.cc b/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.cc
index 43cea089b19..f27c87c8b52 100644
--- a/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.cc
+++ b/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.cc
@@ -113,7 +113,6 @@ void WebURLLoaderMock::LoadSynchronously(
WebData& data,
int64_t& encoded_data_length,
int64_t& encoded_body_length,
- base::Optional<int64_t>& downloaded_file_length,
blink::WebBlobInfo& downloaded_blob) {
if (factory_->IsMockedURL(request.Url())) {
factory_->LoadSynchronously(request, &response, &error, &data,
@@ -124,7 +123,7 @@ void WebURLLoaderMock::LoadSynchronously(
using_default_loader_ = true;
default_loader_->LoadSynchronously(request, client, response, error, data,
encoded_data_length, encoded_body_length,
- downloaded_file_length, downloaded_blob);
+ downloaded_blob);
}
void WebURLLoaderMock::LoadAsynchronously(const WebURLRequest& request,
diff --git a/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.h b/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.h
index 90accfd8f6c..88e60495084 100644
--- a/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.h
+++ b/chromium/third_party/blink/renderer/platform/testing/weburl_loader_mock.h
@@ -52,7 +52,6 @@ class WebURLLoaderMock : public WebURLLoader {
WebData&,
int64_t& encoded_data_length,
int64_t& encoded_body_length,
- base::Optional<int64_t>& downloaded_file_length,
blink::WebBlobInfo& downloaded_blob) override;
void LoadAsynchronously(const WebURLRequest& request,
WebURLLoaderClient* client) override;
diff --git a/chromium/third_party/blink/renderer/platform/text/DEPS b/chromium/third_party/blink/renderer/platform/text/DEPS
index a3eeba08689..a7e3ce7576e 100644
--- a/chromium/third_party/blink/renderer/platform/text/DEPS
+++ b/chromium/third_party/blink/renderer/platform/text/DEPS
@@ -7,10 +7,8 @@ include_rules = [
# Dependencies.
"+third_party/blink/renderer/platform/date_components.h",
- "+third_party/blink/renderer/platform/fonts",
"+third_party/blink/renderer/platform/heap",
"+third_party/blink/renderer/platform/language.h",
- "+third_party/blink/renderer/platform/layout_locale.h",
"+third_party/blink/renderer/platform/layout_test_support.h",
"+third_party/blink/renderer/platform/platform_export.h",
"+third_party/blink/renderer/platform/runtime_enabled_features.h",
diff --git a/chromium/third_party/blink/renderer/platform/text/character.cc b/chromium/third_party/blink/renderer/platform/text/character.cc
index 76a37e6c180..6f64a2a2240 100644
--- a/chromium/third_party/blink/renderer/platform/text/character.cc
+++ b/chromium/third_party/blink/renderer/platform/text/character.cc
@@ -122,6 +122,10 @@ bool Character::IsBidiControl(UChar32 character) {
RETURN_HAS_PROPERTY(character, kIsBidiControl);
}
+bool Character::IsHangulSlow(UChar32 character) {
+ RETURN_HAS_PROPERTY(character, kIsHangul);
+}
+
unsigned Character::ExpansionOpportunityCount(const LChar* characters,
size_t length,
TextDirection direction,
@@ -291,9 +295,12 @@ bool Character::IsCommonOrInheritedScript(UChar32 character) {
(script == USCRIPT_COMMON || script == USCRIPT_INHERITED);
}
-bool Character::IsUnassignedOrPrivateUse(UChar32 character) {
- return WTF::Unicode::Category(character) &
- (WTF::Unicode::kOther_NotAssigned | WTF::Unicode::kOther_PrivateUse);
+bool Character::IsPrivateUse(UChar32 character) {
+ return WTF::Unicode::Category(character) & WTF::Unicode::kOther_PrivateUse;
+}
+
+bool Character::IsNonCharacter(UChar32 character) {
+ return U_IS_UNICODE_NONCHAR(character);
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/text/character.h b/chromium/third_party/blink/renderer/platform/text/character.h
index 22f0aaf93dd..c436616ec61 100644
--- a/chromium/third_party/blink/renderer/platform/text/character.h
+++ b/chromium/third_party/blink/renderer/platform/text/character.h
@@ -72,6 +72,11 @@ class PLATFORM_EXPORT Character {
!(U_GET_GC_MASK(c) & (U_GC_M_MASK | U_GC_LM_MASK | U_GC_SK_MASK));
}
+ static bool IsHangul(UChar32 c) {
+ // Below U+1100 is likely a common case.
+ return c < 0x1100 ? false : IsHangulSlow(c);
+ }
+
static unsigned ExpansionOpportunityCount(const LChar*,
size_t length,
TextDirection,
@@ -178,10 +183,12 @@ class PLATFORM_EXPORT Character {
static String NormalizeSpaces(const UChar*, unsigned length);
static bool IsCommonOrInheritedScript(UChar32);
- static bool IsUnassignedOrPrivateUse(UChar32);
+ static bool IsPrivateUse(UChar32);
+ static bool IsNonCharacter(UChar32);
private:
static bool IsCJKIdeographOrSymbolSlow(UChar32);
+ static bool IsHangulSlow(UChar32);
};
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/text/character_emoji.cc b/chromium/third_party/blink/renderer/platform/text/character_emoji.cc
index 4d281e2b94b..054cdcfad69 100644
--- a/chromium/third_party/blink/renderer/platform/text/character_emoji.cc
+++ b/chromium/third_party/blink/renderer/platform/text/character_emoji.cc
@@ -6,22 +6,31 @@
#include <unicode/uvernum.h>
#include "third_party/blink/renderer/platform/text/icu_error.h"
+#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
-#if defined(USING_SYSTEM_ICU) || (U_ICU_VERSION_MAJOR_NUM <= 57)
+#if defined(USING_SYSTEM_ICU) || (U_ICU_VERSION_MAJOR_NUM <= 61)
#include <unicode/uniset.h>
+
+namespace {
+Mutex& GetFreezePatternMutex() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, mutex, ());
+ return mutex;
+}
+} // namespace
+
#else
#include <unicode/uchar.h>
#endif
namespace blink {
-// ICU 57 or earlier does not have up to date Emoji properties, so we're
+// ICU 61 or earlier does not have up to date v11 Emoji properties, so we're
// temporarily uing our own functions again. Compare crbug.com/628333 Other than
// that: versions before 56 do not have an API for Emoji properties, but
// Chrome's copy of ICU 56 does.
-#if defined(USING_SYSTEM_ICU) || (U_ICU_VERSION_MAJOR_NUM <= 57)
+#if defined(USING_SYSTEM_ICU) || (U_ICU_VERSION_MAJOR_NUM <= 61)
// The following UnicodeSet patterns were compiled from
-// http://www.unicode.org/Public/emoji/3.0//emoji-data.txt
+// https://unicode.org/Public/emoji//11.0/emoji-data.txt
// The following patterns can be generated from the respective sections of the
// emoji_data.txt file by using the following Elisp function in Emacs.
@@ -78,20 +87,20 @@ static const char kEmojiTextPattern[] =
R"([\U00002614-\U00002615][\U00002618][\U0000261D][\U00002620])"
R"([\U00002622-\U00002623][\U00002626][\U0000262A])"
R"([\U0000262E-\U0000262F][\U00002638-\U0000263A][\U00002640])"
- R"([\U00002642][\U00002648-\U00002653][\U00002660][\U00002663])"
- R"([\U00002665-\U00002666][\U00002668][\U0000267B][\U0000267F])"
- R"([\U00002692-\U00002697][\U00002699][\U0000269B-\U0000269C])"
- R"([\U000026A0-\U000026A1][\U000026AA-\U000026AB][\U000026B0-\U000026B1])"
- R"([\U000026BD-\U000026BE][\U000026C4-\U000026C5][\U000026C8])"
- R"([\U000026CE][\U000026CF][\U000026D1][\U000026D3-\U000026D4])"
- R"([\U000026E9-\U000026EA][\U000026F0-\U000026F5][\U000026F7-\U000026FA])"
- R"([\U000026FD][\U00002702][\U00002705][\U00002708-\U00002709])"
- R"([\U0000270A-\U0000270B][\U0000270C-\U0000270D][\U0000270F])"
- R"([\U00002712][\U00002714][\U00002716][\U0000271D][\U00002721])"
- R"([\U00002728][\U00002733-\U00002734][\U00002744][\U00002747])"
- R"([\U0000274C][\U0000274E][\U00002753-\U00002755][\U00002757])"
- R"([\U00002763-\U00002764][\U00002795-\U00002797][\U000027A1])"
- R"([\U000027B0][\U000027BF][\U00002934-\U00002935])"
+ R"([\U00002642][\U00002648-\U00002653][\U0000265F-\U00002660])"
+ R"([\U00002663][\U00002665-\U00002666][\U00002668][\U0000267B])"
+ R"([\U0000267E-\U0000267F][\U00002692-\U00002697][\U00002699])"
+ R"([\U0000269B-\U0000269C][\U000026A0-\U000026A1][\U000026AA-\U000026AB])"
+ R"([\U000026B0-\U000026B1][\U000026BD-\U000026BE][\U000026C4-\U000026C5])"
+ R"([\U000026C8][\U000026CE][\U000026CF][\U000026D1])"
+ R"([\U000026D3-\U000026D4][\U000026E9-\U000026EA][\U000026F0-\U000026F5])"
+ R"([\U000026F7-\U000026FA][\U000026FD][\U00002702][\U00002705])"
+ R"([\U00002708-\U00002709][\U0000270A-\U0000270B][\U0000270C-\U0000270D])"
+ R"([\U0000270F][\U00002712][\U00002714][\U00002716][\U0000271D])"
+ R"([\U00002721][\U00002728][\U00002733-\U00002734][\U00002744])"
+ R"([\U00002747][\U0000274C][\U0000274E][\U00002753-\U00002755])"
+ R"([\U00002757][\U00002763-\U00002764][\U00002795-\U00002797])"
+ R"([\U000027A1][\U000027B0][\U000027BF][\U00002934-\U00002935])"
R"([\U00002B05-\U00002B07][\U00002B1B-\U00002B1C][\U00002B50])"
R"([\U00002B55][\U00003030][\U0000303D][\U00003297][\U00003299])"
R"([\U0001F004][\U0001F0CF][\U0001F170-\U0001F171][\U0001F17E])"
@@ -126,10 +135,16 @@ static const char kEmojiTextPattern[] =
R"([\U0001F6CB-\U0001F6CF][\U0001F6D0][\U0001F6D1-\U0001F6D2])"
R"([\U0001F6E0-\U0001F6E5][\U0001F6E9][\U0001F6EB-\U0001F6EC])"
R"([\U0001F6F0][\U0001F6F3][\U0001F6F4-\U0001F6F6])"
- R"([\U0001F910-\U0001F918][\U0001F919-\U0001F91E][\U0001F920-\U0001F927])"
- R"([\U0001F930][\U0001F933-\U0001F93A][\U0001F93C-\U0001F93E])"
- R"([\U0001F940-\U0001F945][\U0001F947-\U0001F94B][\U0001F950-\U0001F95E])"
- R"([\U0001F980-\U0001F984][\U0001F985-\U0001F991][\U0001F9C0]])";
+ R"([\U0001F6F7-\U0001F6F8][\U0001F6F9][\U0001F910-\U0001F918])"
+ R"([\U0001F919-\U0001F91E][\U0001F91F][\U0001F920-\U0001F927])"
+ R"([\U0001F928-\U0001F92F][\U0001F930][\U0001F931-\U0001F932])"
+ R"([\U0001F933-\U0001F93A][\U0001F93C-\U0001F93E][\U0001F940-\U0001F945])"
+ R"([\U0001F947-\U0001F94B][\U0001F94C][\U0001F94D-\U0001F94F])"
+ R"([\U0001F950-\U0001F95E][\U0001F95F-\U0001F96B][\U0001F96C-\U0001F970])"
+ R"([\U0001F973-\U0001F976][\U0001F97A][\U0001F97C-\U0001F97F])"
+ R"([\U0001F980-\U0001F984][\U0001F985-\U0001F991][\U0001F992-\U0001F997])"
+ R"([\U0001F998-\U0001F9A2][\U0001F9B0-\U0001F9B9][\U0001F9C0])"
+ R"([\U0001F9C1-\U0001F9C2][\U0001F9D0-\U0001F9E6][\U0001F9E7-\U0001F9FF]])";
static const char kEmojiEmojiPattern[] =
R"([[\U0000231A-\U0000231B][\U000023E9-\U000023EC][\U000023F0])"
@@ -162,26 +177,38 @@ static const char kEmojiEmojiPattern[] =
R"([\U0001F634][\U0001F635-\U0001F640][\U0001F641-\U0001F642])"
R"([\U0001F643-\U0001F644][\U0001F645-\U0001F64F][\U0001F680-\U0001F6C5])"
R"([\U0001F6CC][\U0001F6D0][\U0001F6D1-\U0001F6D2])"
- R"([\U0001F6EB-\U0001F6EC][\U0001F6F4-\U0001F6F6][\U0001F910-\U0001F918])"
- R"([\U0001F919-\U0001F91E][\U0001F920-\U0001F927][\U0001F930])"
- R"([\U0001F933-\U0001F93A][\U0001F93C-\U0001F93E][\U0001F940-\U0001F945])"
- R"([\U0001F947-\U0001F94B][\U0001F950-\U0001F95E][\U0001F980-\U0001F984])"
- R"([\U0001F985-\U0001F991][\U0001F9C0]])";
+ R"([\U0001F6EB-\U0001F6EC][\U0001F6F4-\U0001F6F6][\U0001F6F7-\U0001F6F8])"
+ R"([\U0001F6F9][\U0001F910-\U0001F918][\U0001F919-\U0001F91E])"
+ R"([\U0001F91F][\U0001F920-\U0001F927][\U0001F928-\U0001F92F])"
+ R"([\U0001F930][\U0001F931-\U0001F932][\U0001F933-\U0001F93A])"
+ R"([\U0001F93C-\U0001F93E][\U0001F940-\U0001F945][\U0001F947-\U0001F94B])"
+ R"([\U0001F94C][\U0001F94D-\U0001F94F][\U0001F950-\U0001F95E])"
+ R"([\U0001F95F-\U0001F96B][\U0001F96C-\U0001F970][\U0001F973-\U0001F976])"
+ R"([\U0001F97A][\U0001F97C-\U0001F97F][\U0001F980-\U0001F984])"
+ R"([\U0001F985-\U0001F991][\U0001F992-\U0001F997][\U0001F998-\U0001F9A2])"
+ R"([\U0001F9B0-\U0001F9B9][\U0001F9C0][\U0001F9C1-\U0001F9C2])"
+ R"([\U0001F9D0-\U0001F9E6][\U0001F9E7-\U0001F9FF]])";
static const char kEmojiModifierBasePattern[] =
R"([[\U0000261D][\U000026F9][\U0000270A-\U0000270B])"
R"([\U0000270C-\U0000270D][\U0001F385][\U0001F3C2-\U0001F3C4])"
R"([\U0001F3C7][\U0001F3CA][\U0001F3CB-\U0001F3CC])"
- R"([\U0001F442-\U0001F443][\U0001F446-\U0001F450][\U0001F466-\U0001F478])"
- R"([\U0001F47C][\U0001F481-\U0001F483][\U0001F485-\U0001F487])"
- R"([\U0001F4AA][\U0001F574-\U0001F575][\U0001F57A][\U0001F590])"
+ R"([\U0001F442-\U0001F443][\U0001F446-\U0001F450][\U0001F466-\U0001F469])"
+ R"([\U0001F46E][\U0001F470-\U0001F478][\U0001F47C])"
+ R"([\U0001F481-\U0001F483][\U0001F485-\U0001F487][\U0001F4AA])"
+ R"([\U0001F574-\U0001F575][\U0001F57A][\U0001F590])"
R"([\U0001F595-\U0001F596][\U0001F645-\U0001F647][\U0001F64B-\U0001F64F])"
R"([\U0001F6A3][\U0001F6B4-\U0001F6B6][\U0001F6C0][\U0001F6CC])"
- R"([\U0001F918][\U0001F919-\U0001F91E][\U0001F926][\U0001F930])"
- R"([\U0001F933-\U0001F939][\U0001F93C-\U0001F93E]])";
+ R"([\U0001F918][\U0001F919-\U0001F91C][\U0001F91E][\U0001F91F])"
+ R"([\U0001F926][\U0001F930][\U0001F931-\U0001F932])"
+ R"([\U0001F933-\U0001F939][\U0001F93D-\U0001F93E][\U0001F9B5-\U0001F9B6])"
+ R"([\U0001F9B8-\U0001F9B9][\U0001F9D1-\U0001F9DD]])";
-static void applyPatternAndFreeze(icu::UnicodeSet* unicodeSet,
- const char* pattern) {
+static void applyPatternAndFreezeIfEmpty(icu::UnicodeSet* unicodeSet,
+ const char* pattern) {
+ MutexLocker mutexLocker(GetFreezePatternMutex());
+ if (!unicodeSet->isEmpty())
+ return;
ICUError err;
// Use ICU's invariant-character initialization method.
unicodeSet->applyPattern(icu::UnicodeString(pattern, -1, US_INV), err);
@@ -195,23 +222,21 @@ bool Character::IsEmoji(UChar32 ch) {
}
bool Character::IsEmojiTextDefault(UChar32 ch) {
- DEFINE_STATIC_LOCAL(icu::UnicodeSet, emojiTextSet, ());
- if (emojiTextSet.isEmpty())
- applyPatternAndFreeze(&emojiTextSet, kEmojiTextPattern);
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(icu::UnicodeSet, emojiTextSet, ());
+ applyPatternAndFreezeIfEmpty(&emojiTextSet, kEmojiTextPattern);
return emojiTextSet.contains(ch) && !IsEmojiEmojiDefault(ch);
}
bool Character::IsEmojiEmojiDefault(UChar32 ch) {
- DEFINE_STATIC_LOCAL(icu::UnicodeSet, emojiEmojiSet, ());
- if (emojiEmojiSet.isEmpty())
- applyPatternAndFreeze(&emojiEmojiSet, kEmojiEmojiPattern);
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(icu::UnicodeSet, emojiEmojiSet, ());
+ applyPatternAndFreezeIfEmpty(&emojiEmojiSet, kEmojiEmojiPattern);
return emojiEmojiSet.contains(ch);
}
bool Character::IsEmojiModifierBase(UChar32 ch) {
- DEFINE_STATIC_LOCAL(icu::UnicodeSet, emojieModifierBaseSet, ());
- if (emojieModifierBaseSet.isEmpty())
- applyPatternAndFreeze(&emojieModifierBaseSet, kEmojiModifierBasePattern);
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(icu::UnicodeSet, emojieModifierBaseSet, ());
+ applyPatternAndFreezeIfEmpty(&emojieModifierBaseSet,
+ kEmojiModifierBasePattern);
return emojieModifierBaseSet.contains(ch);
}
#else
diff --git a/chromium/third_party/blink/renderer/platform/text/character_property.h b/chromium/third_party/blink/renderer/platform/text/character_property.h
index 4c6d88676d2..18a8c718ce1 100644
--- a/chromium/third_party/blink/renderer/platform/text/character_property.h
+++ b/chromium/third_party/blink/renderer/platform/text/character_property.h
@@ -16,6 +16,7 @@ enum class CharacterProperty : CharacterPropertyType {
kIsUprightInMixedVertical = 0x0002,
kIsPotentialCustomElementNameChar = 0x0004,
kIsBidiControl = 0x0008,
+ kIsHangul = 0x0010
};
inline CharacterProperty operator|(CharacterProperty a, CharacterProperty b) {
diff --git a/chromium/third_party/blink/renderer/platform/text/character_property_data_generator.cc b/chromium/third_party/blink/renderer/platform/text/character_property_data_generator.cc
index d3b4f6b1516..846ceea42a7 100644
--- a/chromium/third_party/blink/renderer/platform/text/character_property_data_generator.cc
+++ b/chromium/third_party/blink/renderer/platform/text/character_property_data_generator.cc
@@ -82,6 +82,7 @@ static void Generate(FILE* fp) {
SET(kIsUprightInMixedVertical);
SET(kIsPotentialCustomElementNameChar);
SET(kIsBidiControl);
+ SET(kIsHangul);
// Create a trie from the value array.
UErrorCode error = U_ZERO_ERROR;
diff --git a/chromium/third_party/blink/renderer/platform/text/character_property_data_generator.h b/chromium/third_party/blink/renderer/platform/text/character_property_data_generator.h
index ee33611c7d7..28fb6a930cf 100644
--- a/chromium/third_party/blink/renderer/platform/text/character_property_data_generator.h
+++ b/chromium/third_party/blink/renderer/platform/text/character_property_data_generator.h
@@ -230,6 +230,25 @@ static const UChar32 kIsBidiControlRanges[] = {
0x202A, 0x202E, 0x2066, 0x2069,
};
+// https://unicode.org/Public/UNIDATA/Blocks.txt
+static const UChar32 kIsHangulRanges[] = {
+ // Hangul Jamo
+ 0x1100, 0x11FF,
+ // Hangul Compatibility Jamo
+ 0x3130, 0x318F,
+ // Hangul Jamo Extended-A
+ 0xA960, 0xA97F,
+ // Hangul Syllables
+ 0xAC00, 0xD7AF,
+ // Hangul Jamo Extended-B
+ 0xD7B0, 0xD7FF,
+ // Halfwidth Hangul Jamo
+ // https://www.unicode.org/charts/nameslist/c_FF00.html
+ 0xFFA0, 0xFFDC,
+};
+
+static const UChar32 kIsHangulArray[] = {};
+
} // namespace blink
#endif
diff --git a/chromium/third_party/blink/renderer/platform/text/character_test.cc b/chromium/third_party/blink/renderer/platform/text/character_test.cc
index e82d4c91c0b..504e37a8a5c 100644
--- a/chromium/third_party/blink/renderer/platform/text/character_test.cc
+++ b/chromium/third_party/blink/renderer/platform/text/character_test.cc
@@ -279,6 +279,13 @@ TEST(CharacterTest, TestEmojiEmojiDefault) {
EXPECT_FALSE(Character::IsEmojiEmojiDefault(0x1F202));
}
+TEST(CharacterTest, EmojificationV11) {
+ // Infinity and Chess pawn were given the emoji class, but have default text
+ // presentation in Unicode 11.
+ EXPECT_TRUE(Character::IsEmojiTextDefault(0x265F));
+ EXPECT_TRUE(Character::IsEmojiTextDefault(0x267E));
+}
+
TEST(CharacterTest, TestEmojiModifierBase) {
EXPECT_TRUE(Character::IsEmojiModifierBase(0x261D));
EXPECT_TRUE(Character::IsEmojiModifierBase(0x1F470));
@@ -349,4 +356,30 @@ TEST(CharacterTest, IsBidiControl) {
EXPECT_FALSE(Character::IsBidiControl(0x05D0));
}
+TEST(CharacterTest, IsNonCharacter) {
+ // See http://www.unicode.org/faq/private_use.html#nonchar4
+ EXPECT_FALSE(Character::IsNonCharacter(0xFDD0 - 1));
+ for (UChar32 bmp_noncharacter = 0xFDD0; bmp_noncharacter < 0xFDEF;
+ ++bmp_noncharacter) {
+ EXPECT_TRUE(Character::IsNonCharacter(bmp_noncharacter));
+ }
+ EXPECT_FALSE(Character::IsNonCharacter(0xFDEF + 1));
+
+ EXPECT_FALSE(Character::IsNonCharacter(0xFFFE - 1));
+ EXPECT_TRUE(Character::IsNonCharacter(0xFFFE));
+ EXPECT_TRUE(Character::IsNonCharacter(0xFFFF));
+ EXPECT_FALSE(Character::IsNonCharacter(0xFFFF + 1));
+
+ for (uint32_t supplementary_plane_prefix = 0x10000;
+ supplementary_plane_prefix < 0x100000;
+ supplementary_plane_prefix += 0x10000) {
+ EXPECT_FALSE(
+ Character::IsNonCharacter(supplementary_plane_prefix + 0xFFFE - 1));
+ EXPECT_TRUE(Character::IsNonCharacter(supplementary_plane_prefix + 0xFFFE));
+ EXPECT_TRUE(Character::IsNonCharacter(supplementary_plane_prefix + 0xFFFF));
+ EXPECT_FALSE(
+ Character::IsNonCharacter(supplementary_plane_prefix + 0xFFFF + 1));
+ }
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/text/hyphenation.cc b/chromium/third_party/blink/renderer/platform/text/hyphenation.cc
index fcc5649c497..c205901fdb3 100644
--- a/chromium/third_party/blink/renderer/platform/text/hyphenation.cc
+++ b/chromium/third_party/blink/renderer/platform/text/hyphenation.cc
@@ -4,7 +4,6 @@
#include "third_party/blink/renderer/platform/text/hyphenation.h"
-#include "third_party/blink/renderer/platform/fonts/font.h"
#include "third_party/blink/renderer/platform/wtf/text/string_view.h"
namespace blink {
@@ -34,15 +33,4 @@ Vector<size_t, 8> Hyphenation::HyphenLocations(const StringView& text) const {
return hyphen_locations;
}
-int Hyphenation::MinimumPrefixWidth(const Font& font) {
- // If the maximum width available for the prefix before the hyphen is small,
- // then it is very unlikely that an hyphenation opportunity exists, so do not
- // bother to look for it. These are heuristic numbers for performance added
- // in http://wkb.ug/45606
- const int kMinimumPrefixWidthNumerator = 5;
- const int kMinimumPrefixWidthDenominator = 4;
- return font.GetFontDescription().ComputedPixelSize() *
- kMinimumPrefixWidthNumerator / kMinimumPrefixWidthDenominator;
-}
-
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/text/hyphenation.h b/chromium/third_party/blink/renderer/platform/text/hyphenation.h
index c903fbf942a..363473b091c 100644
--- a/chromium/third_party/blink/renderer/platform/text/hyphenation.h
+++ b/chromium/third_party/blink/renderer/platform/text/hyphenation.h
@@ -14,8 +14,6 @@
namespace blink {
-class Font;
-
class PLATFORM_EXPORT Hyphenation : public RefCounted<Hyphenation> {
public:
virtual ~Hyphenation() = default;
@@ -35,7 +33,6 @@ class PLATFORM_EXPORT Hyphenation : public RefCounted<Hyphenation> {
static const unsigned kMinimumPrefixLength = 2;
static const unsigned kMinimumSuffixLength = 2;
- static int MinimumPrefixWidth(const Font&);
private:
friend class LayoutLocale;
diff --git a/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.cc b/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.cc
index 68d8ee7de49..4c4b9f02666 100644
--- a/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.cc
+++ b/chromium/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.cc
@@ -16,9 +16,9 @@
#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/modules/hyphenation/hyphenation.mojom-blink.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/renderer/platform/layout_locale.h"
#include "third_party/blink/renderer/platform/text/character.h"
#include "third_party/blink/renderer/platform/text/hyphenation/hyphenator_aosp.h"
+#include "third_party/blink/renderer/platform/text/layout_locale.h"
namespace blink {
@@ -33,7 +33,7 @@ StringView SkipLeadingSpaces(const CharType* text,
while (text != end && Character::TreatAsSpace(*text))
text++;
*num_leading_spaces_out = text - begin;
- return StringView(text, end - text);
+ return StringView(text, static_cast<unsigned>(end - text));
}
StringView SkipLeadingSpaces(const StringView& text,
@@ -177,7 +177,7 @@ static LocaleMap CreateLocaleFallbackMap() {
};
LocaleMap map;
for (const auto& it : locale_fallback_data)
- map.insert(it[0], it[1]);
+ map.insert(AtomicString(it[0]), it[1]);
return map;
}
diff --git a/chromium/third_party/blink/renderer/platform/text/hyphenation_test.cc b/chromium/third_party/blink/renderer/platform/text/hyphenation_test.cc
index 7b827e84324..6f50192392e 100644
--- a/chromium/third_party/blink/renderer/platform/text/hyphenation_test.cc
+++ b/chromium/third_party/blink/renderer/platform/text/hyphenation_test.cc
@@ -7,8 +7,7 @@
#include "build/build_config.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/fonts/font_global_context.h"
-#include "third_party/blink/renderer/platform/layout_locale.h"
+#include "third_party/blink/renderer/platform/text/layout_locale.h"
using testing::ElementsAre;
using testing::ElementsAreArray;
@@ -33,7 +32,7 @@ class NoHyphenation : public Hyphenation {
class HyphenationTest : public testing::Test {
protected:
- void TearDown() override { FontGlobalContext::ClearForTesting(); }
+ void TearDown() override { LayoutLocale::ClearForTesting(); }
#if defined(USE_MINIKIN_HYPHENATION) || defined(OS_MACOSX)
// Get a |Hyphenation| instnace for the specified locale for testing.
@@ -72,7 +71,13 @@ TEST_F(HyphenationTest, Get) {
}
#if defined(USE_MINIKIN_HYPHENATION) || defined(OS_MACOSX)
-TEST_F(HyphenationTest, HyphenLocations) {
+// TODO(crbug.com/851413): Reenable this test.
+#if defined(OS_ANDROID)
+#define MAYBE_HyphenLocations DISABLED_HyphenLocations
+#else
+#define MAYBE_HyphenLocations HyphenLocations
+#endif
+TEST_F(HyphenationTest, MAYBE_HyphenLocations) {
scoped_refptr<Hyphenation> hyphenation = GetHyphenation("en-us");
ASSERT_TRUE(hyphenation) << "Cannot find the hyphenation engine";
diff --git a/chromium/third_party/blink/renderer/platform/text/icu_error.cc b/chromium/third_party/blink/renderer/platform/text/icu_error.cc
index d2e9cce4687..1aad8529944 100644
--- a/chromium/third_party/blink/renderer/platform/text/icu_error.cc
+++ b/chromium/third_party/blink/renderer/platform/text/icu_error.cc
@@ -10,7 +10,7 @@ namespace blink {
// Distinguish memory allocation failures from other errors.
// https://groups.google.com/a/chromium.org/d/msg/platform-architecture-dev/MP0k9WGnCjA/zIBiJtilBwAJ
-static NEVER_INLINE void ICUOutOfMemory() {
+static NOINLINE void ICUOutOfMemory() {
OOM_CRASH();
}
diff --git a/chromium/third_party/blink/renderer/platform/text/layout_locale.cc b/chromium/third_party/blink/renderer/platform/text/layout_locale.cc
new file mode 100644
index 00000000000..34dd35f6e94
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/text/layout_locale.cc
@@ -0,0 +1,276 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/text/layout_locale.h"
+
+#include "base/compiler_specific.h"
+#include "third_party/blink/renderer/platform/language.h"
+#include "third_party/blink/renderer/platform/text/hyphenation.h"
+#include "third_party/blink/renderer/platform/text/icu_error.h"
+#include "third_party/blink/renderer/platform/text/locale_to_script_mapping.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
+#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
+
+#include <hb.h>
+#include <unicode/locid.h>
+
+namespace blink {
+
+namespace {
+
+struct PerThreadData {
+ HashMap<AtomicString, scoped_refptr<LayoutLocale>, CaseFoldingHash>
+ locale_map;
+ const LayoutLocale* default_locale = nullptr;
+ const LayoutLocale* system_locale = nullptr;
+ const LayoutLocale* default_locale_for_han = nullptr;
+ bool default_locale_for_han_computed = false;
+ String current_accept_languages;
+};
+
+PerThreadData& GetPerThreadData() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<PerThreadData>, data, ());
+ return *data;
+}
+
+} // namespace
+
+static hb_language_t ToHarfbuzLanguage(const AtomicString& locale) {
+ CString locale_as_latin1 = locale.Latin1();
+ return hb_language_from_string(locale_as_latin1.data(),
+ locale_as_latin1.length());
+}
+
+// SkFontMgr requires script-based locale names, like "zh-Hant" and "zh-Hans",
+// instead of "zh-CN" and "zh-TW".
+static const char* ToSkFontMgrLocale(UScriptCode script) {
+ switch (script) {
+ case USCRIPT_KATAKANA_OR_HIRAGANA:
+ return "ja-JP";
+ case USCRIPT_HANGUL:
+ return "ko-KR";
+ case USCRIPT_SIMPLIFIED_HAN:
+ return "zh-Hans";
+ case USCRIPT_TRADITIONAL_HAN:
+ return "zh-Hant";
+ default:
+ return nullptr;
+ }
+}
+
+const char* LayoutLocale::LocaleForSkFontMgr() const {
+ if (string_for_sk_font_mgr_.IsNull()) {
+ string_for_sk_font_mgr_ = ToSkFontMgrLocale(script_);
+ if (string_for_sk_font_mgr_.IsNull())
+ string_for_sk_font_mgr_ = string_.Ascii();
+ }
+ return string_for_sk_font_mgr_.data();
+}
+
+void LayoutLocale::ComputeScriptForHan() const {
+ if (IsUnambiguousHanScript(script_)) {
+ script_for_han_ = script_;
+ has_script_for_han_ = true;
+ return;
+ }
+
+ script_for_han_ = ScriptCodeForHanFromSubtags(string_);
+ if (script_for_han_ == USCRIPT_COMMON)
+ script_for_han_ = USCRIPT_SIMPLIFIED_HAN;
+ else
+ has_script_for_han_ = true;
+ DCHECK(IsUnambiguousHanScript(script_for_han_));
+}
+
+UScriptCode LayoutLocale::GetScriptForHan() const {
+ if (script_for_han_ == USCRIPT_COMMON)
+ ComputeScriptForHan();
+ return script_for_han_;
+}
+
+bool LayoutLocale::HasScriptForHan() const {
+ if (script_for_han_ == USCRIPT_COMMON)
+ ComputeScriptForHan();
+ return has_script_for_han_;
+}
+
+// static
+const LayoutLocale* LayoutLocale::LocaleForHan(
+ const LayoutLocale* content_locale) {
+ if (content_locale && content_locale->HasScriptForHan())
+ return content_locale;
+
+ PerThreadData& data = GetPerThreadData();
+ if (UNLIKELY(!data.default_locale_for_han_computed)) {
+ // Use the first acceptLanguages that can disambiguate.
+ Vector<String> languages;
+ data.current_accept_languages.Split(',', languages);
+ for (String token : languages) {
+ token = token.StripWhiteSpace();
+ const LayoutLocale* locale = LayoutLocale::Get(AtomicString(token));
+ if (locale->HasScriptForHan()) {
+ data.default_locale_for_han = locale;
+ break;
+ }
+ }
+ if (!data.default_locale_for_han) {
+ const LayoutLocale& default_locale = GetDefault();
+ if (default_locale.HasScriptForHan())
+ data.default_locale_for_han = &default_locale;
+ }
+ if (!data.default_locale_for_han) {
+ const LayoutLocale& system_locale = GetSystem();
+ if (system_locale.HasScriptForHan())
+ data.default_locale_for_han = &system_locale;
+ }
+ data.default_locale_for_han_computed = true;
+ }
+ return data.default_locale_for_han;
+}
+
+const char* LayoutLocale::LocaleForHanForSkFontMgr() const {
+ const char* locale = ToSkFontMgrLocale(GetScriptForHan());
+ DCHECK(locale);
+ return locale;
+}
+
+LayoutLocale::LayoutLocale(const AtomicString& locale)
+ : string_(locale),
+ harfbuzz_language_(ToHarfbuzLanguage(locale)),
+ script_(LocaleToScriptCodeForFontSelection(locale)),
+ script_for_han_(USCRIPT_COMMON),
+ has_script_for_han_(false),
+ hyphenation_computed_(false) {}
+
+// static
+const LayoutLocale* LayoutLocale::Get(const AtomicString& locale) {
+ if (locale.IsNull())
+ return nullptr;
+
+ auto result = GetPerThreadData().locale_map.insert(locale, nullptr);
+ if (result.is_new_entry)
+ result.stored_value->value = base::AdoptRef(new LayoutLocale(locale));
+ return result.stored_value->value.get();
+}
+
+// static
+const LayoutLocale& LayoutLocale::GetDefault() {
+ PerThreadData& data = GetPerThreadData();
+ if (UNLIKELY(!data.default_locale)) {
+ AtomicString language = DefaultLanguage();
+ data.default_locale =
+ LayoutLocale::Get(!language.IsEmpty() ? language : "en");
+ }
+ return *data.default_locale;
+}
+
+// static
+const LayoutLocale& LayoutLocale::GetSystem() {
+ PerThreadData& data = GetPerThreadData();
+ if (UNLIKELY(!data.system_locale)) {
+ // Platforms such as Windows can give more information than the default
+ // locale, such as "en-JP" for English speakers in Japan.
+ String name = icu::Locale::getDefault().getName();
+ data.system_locale =
+ LayoutLocale::Get(AtomicString(name.Replace('_', '-')));
+ }
+ return *data.system_locale;
+}
+
+scoped_refptr<LayoutLocale> LayoutLocale::CreateForTesting(
+ const AtomicString& locale) {
+ return base::AdoptRef(new LayoutLocale(locale));
+}
+
+Hyphenation* LayoutLocale::GetHyphenation() const {
+ if (hyphenation_computed_)
+ return hyphenation_.get();
+
+ hyphenation_computed_ = true;
+ hyphenation_ = Hyphenation::PlatformGetHyphenation(LocaleString());
+ return hyphenation_.get();
+}
+
+void LayoutLocale::SetHyphenationForTesting(
+ const AtomicString& locale_string,
+ scoped_refptr<Hyphenation> hyphenation) {
+ const LayoutLocale& locale = ValueOrDefault(Get(locale_string));
+ locale.hyphenation_computed_ = true;
+ locale.hyphenation_ = std::move(hyphenation);
+}
+
+AtomicString LayoutLocale::LocaleWithBreakKeyword(
+ LineBreakIteratorMode mode) const {
+ if (string_.IsEmpty())
+ return string_;
+
+ // uloc_setKeywordValue_58 has a problem to handle "@" in the original
+ // string. crbug.com/697859
+ if (string_.Contains('@'))
+ return string_;
+
+ CString utf8_locale = string_.Utf8();
+ Vector<char> buffer(utf8_locale.length() + 11, 0);
+ memcpy(buffer.data(), utf8_locale.data(), utf8_locale.length());
+
+ const char* keyword_value = nullptr;
+ switch (mode) {
+ default:
+ NOTREACHED();
+ FALLTHROUGH;
+ case LineBreakIteratorMode::kDefault:
+ // nullptr will cause any existing values to be removed.
+ break;
+ case LineBreakIteratorMode::kNormal:
+ keyword_value = "normal";
+ break;
+ case LineBreakIteratorMode::kStrict:
+ keyword_value = "strict";
+ break;
+ case LineBreakIteratorMode::kLoose:
+ keyword_value = "loose";
+ break;
+ }
+
+ ICUError status;
+ int32_t length_needed = uloc_setKeywordValue(
+ "lb", keyword_value, buffer.data(), buffer.size(), &status);
+ if (U_SUCCESS(status))
+ return AtomicString::FromUTF8(buffer.data(), length_needed);
+
+ if (status == U_BUFFER_OVERFLOW_ERROR) {
+ buffer.Grow(length_needed + 1);
+ memset(buffer.data() + utf8_locale.length(), 0,
+ buffer.size() - utf8_locale.length());
+ status = U_ZERO_ERROR;
+ int32_t length_needed2 = uloc_setKeywordValue(
+ "lb", keyword_value, buffer.data(), buffer.size(), &status);
+ DCHECK_EQ(length_needed, length_needed2);
+ if (U_SUCCESS(status) && length_needed == length_needed2)
+ return AtomicString::FromUTF8(buffer.data(), length_needed);
+ }
+
+ NOTREACHED();
+ return string_;
+}
+
+// static
+void LayoutLocale::AcceptLanguagesChanged(const String& accept_languages) {
+ PerThreadData& data = GetPerThreadData();
+ if (data.current_accept_languages == accept_languages)
+ return;
+
+ data.current_accept_languages = accept_languages;
+ data.default_locale_for_han = nullptr;
+ data.default_locale_for_han_computed = false;
+}
+
+// static
+void LayoutLocale::ClearForTesting() {
+ GetPerThreadData() = PerThreadData();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/text/layout_locale.h b/chromium/third_party/blink/renderer/platform/text/layout_locale.h
new file mode 100644
index 00000000000..2ec39dd66af
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/text/layout_locale.h
@@ -0,0 +1,93 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_LAYOUT_LOCALE_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_LAYOUT_LOCALE_H_
+
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/text/hyphenation.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
+#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
+
+#include <unicode/uscript.h>
+
+struct hb_language_impl_t;
+
+namespace blink {
+
+enum class LineBreakIteratorMode { kDefault, kNormal, kStrict, kLoose };
+
+class PLATFORM_EXPORT LayoutLocale : public RefCounted<LayoutLocale> {
+ public:
+ static const LayoutLocale* Get(const AtomicString& locale);
+ static const LayoutLocale& GetDefault();
+ static const LayoutLocale& GetSystem();
+ static const LayoutLocale& ValueOrDefault(const LayoutLocale* locale) {
+ return locale ? *locale : GetDefault();
+ }
+
+ bool operator==(const LayoutLocale& other) const {
+ return string_ == other.string_;
+ }
+ bool operator!=(const LayoutLocale& other) const {
+ return string_ != other.string_;
+ }
+
+ const AtomicString& LocaleString() const { return string_; }
+ static const AtomicString& LocaleString(const LayoutLocale* locale) {
+ return locale ? locale->string_ : g_null_atom;
+ }
+ operator const AtomicString&() const { return string_; }
+ CString Ascii() const { return string_.Ascii(); }
+
+ const hb_language_impl_t* HarfbuzzLanguage() const {
+ return harfbuzz_language_;
+ }
+ const char* LocaleForSkFontMgr() const;
+ UScriptCode GetScript() const { return script_; }
+
+ // Disambiguation of the Unified Han Ideographs.
+ UScriptCode GetScriptForHan() const;
+ bool HasScriptForHan() const;
+ static const LayoutLocale* LocaleForHan(const LayoutLocale*);
+ const char* LocaleForHanForSkFontMgr() const;
+
+ Hyphenation* GetHyphenation() const;
+
+ AtomicString LocaleWithBreakKeyword(LineBreakIteratorMode) const;
+
+ static scoped_refptr<LayoutLocale> CreateForTesting(const AtomicString&);
+ static void SetHyphenationForTesting(const AtomicString&,
+ scoped_refptr<Hyphenation>);
+
+ static void AcceptLanguagesChanged(const String&);
+
+ static void ClearForTesting();
+
+ private:
+ explicit LayoutLocale(const AtomicString&);
+
+ void ComputeScriptForHan() const;
+
+ AtomicString string_;
+ mutable CString string_for_sk_font_mgr_;
+ mutable scoped_refptr<Hyphenation> hyphenation_;
+
+ // hb_language_t is defined in hb.h, which not all files can include.
+ const hb_language_impl_t* harfbuzz_language_;
+
+ UScriptCode script_;
+ mutable UScriptCode script_for_han_;
+
+ mutable unsigned has_script_for_han_ : 1;
+ mutable unsigned hyphenation_computed_ : 1;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_LAYOUT_LOCALE_H_
diff --git a/chromium/third_party/blink/renderer/platform/text/layout_locale_test.cc b/chromium/third_party/blink/renderer/platform/text/layout_locale_test.cc
new file mode 100644
index 00000000000..5421e9f940c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/text/layout_locale_test.cc
@@ -0,0 +1,206 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/text/layout_locale.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace blink {
+
+TEST(LayoutLocaleTest, Get) {
+ LayoutLocale::ClearForTesting();
+
+ EXPECT_EQ(nullptr, LayoutLocale::Get(g_null_atom));
+
+ EXPECT_EQ(g_empty_atom, LayoutLocale::Get(g_empty_atom)->LocaleString());
+
+ EXPECT_STRCASEEQ("en-us",
+ LayoutLocale::Get("en-us")->LocaleString().Ascii().data());
+ EXPECT_STRCASEEQ("ja-jp",
+ LayoutLocale::Get("ja-jp")->LocaleString().Ascii().data());
+
+ LayoutLocale::ClearForTesting();
+}
+
+TEST(LayoutLocaleTest, GetCaseInsensitive) {
+ const LayoutLocale* en_us = LayoutLocale::Get("en-us");
+ EXPECT_EQ(en_us, LayoutLocale::Get("en-US"));
+}
+
+TEST(LayoutLocaleTest, ScriptTest) {
+ // Test combinations of BCP 47 locales.
+ // https://tools.ietf.org/html/bcp47
+ struct {
+ const char* locale;
+ UScriptCode script;
+ bool has_script_for_han;
+ UScriptCode script_for_han;
+ } tests[] = {
+ {"en-US", USCRIPT_LATIN},
+
+ // Common lang-script.
+ {"en-Latn", USCRIPT_LATIN},
+ {"ar-Arab", USCRIPT_ARABIC},
+
+ // Common lang-region in East Asia.
+ {"ja-JP", USCRIPT_KATAKANA_OR_HIRAGANA, true},
+ {"ko-KR", USCRIPT_HANGUL, true},
+ {"zh", USCRIPT_SIMPLIFIED_HAN, true},
+ {"zh-CN", USCRIPT_SIMPLIFIED_HAN, true},
+ {"zh-HK", USCRIPT_TRADITIONAL_HAN, true},
+ {"zh-MO", USCRIPT_TRADITIONAL_HAN, true},
+ {"zh-SG", USCRIPT_SIMPLIFIED_HAN, true},
+ {"zh-TW", USCRIPT_TRADITIONAL_HAN, true},
+
+ // Encompassed languages within the Chinese macrolanguage.
+ // Both "lang" and "lang-extlang" should work.
+ {"nan", USCRIPT_TRADITIONAL_HAN, true},
+ {"wuu", USCRIPT_SIMPLIFIED_HAN, true},
+ {"yue", USCRIPT_TRADITIONAL_HAN, true},
+ {"zh-nan", USCRIPT_TRADITIONAL_HAN, true},
+ {"zh-wuu", USCRIPT_SIMPLIFIED_HAN, true},
+ {"zh-yue", USCRIPT_TRADITIONAL_HAN, true},
+
+ // Script has priority over other subtags.
+ {"zh-Hant", USCRIPT_TRADITIONAL_HAN, true},
+ {"en-Hans", USCRIPT_SIMPLIFIED_HAN, true},
+ {"en-Hant", USCRIPT_TRADITIONAL_HAN, true},
+ {"en-Hans-TW", USCRIPT_SIMPLIFIED_HAN, true},
+ {"en-Hant-CN", USCRIPT_TRADITIONAL_HAN, true},
+ {"wuu-Hant", USCRIPT_TRADITIONAL_HAN, true},
+ {"yue-Hans", USCRIPT_SIMPLIFIED_HAN, true},
+ {"zh-wuu-Hant", USCRIPT_TRADITIONAL_HAN, true},
+ {"zh-yue-Hans", USCRIPT_SIMPLIFIED_HAN, true},
+
+ // Lang has priority over region.
+ // icu::Locale::getDefault() returns other combinations if, for instnace,
+ // English Windows with the display language set to Japanese.
+ {"ja", USCRIPT_KATAKANA_OR_HIRAGANA, true},
+ {"ja-US", USCRIPT_KATAKANA_OR_HIRAGANA, true},
+ {"ko", USCRIPT_HANGUL, true},
+ {"ko-US", USCRIPT_HANGUL, true},
+ {"wuu-TW", USCRIPT_SIMPLIFIED_HAN, true},
+ {"yue-CN", USCRIPT_TRADITIONAL_HAN, true},
+ {"zh-wuu-TW", USCRIPT_SIMPLIFIED_HAN, true},
+ {"zh-yue-CN", USCRIPT_TRADITIONAL_HAN, true},
+
+ // Region should not affect script, but it can influence scriptForHan.
+ {"en-CN", USCRIPT_LATIN, false},
+ {"en-HK", USCRIPT_LATIN, true, USCRIPT_TRADITIONAL_HAN},
+ {"en-MO", USCRIPT_LATIN, true, USCRIPT_TRADITIONAL_HAN},
+ {"en-SG", USCRIPT_LATIN, false},
+ {"en-TW", USCRIPT_LATIN, true, USCRIPT_TRADITIONAL_HAN},
+ {"en-JP", USCRIPT_LATIN, true, USCRIPT_KATAKANA_OR_HIRAGANA},
+ {"en-KR", USCRIPT_LATIN, true, USCRIPT_HANGUL},
+
+ // Multiple regions are invalid, but it can still give hints for the font
+ // selection.
+ {"en-US-JP", USCRIPT_LATIN, true, USCRIPT_KATAKANA_OR_HIRAGANA},
+ };
+
+ for (const auto& test : tests) {
+ scoped_refptr<LayoutLocale> locale =
+ LayoutLocale::CreateForTesting(test.locale);
+ EXPECT_EQ(test.script, locale->GetScript()) << test.locale;
+ EXPECT_EQ(test.has_script_for_han, locale->HasScriptForHan())
+ << test.locale;
+ if (!test.has_script_for_han) {
+ EXPECT_EQ(USCRIPT_SIMPLIFIED_HAN, locale->GetScriptForHan())
+ << test.locale;
+ } else if (test.script_for_han) {
+ EXPECT_EQ(test.script_for_han, locale->GetScriptForHan()) << test.locale;
+ } else {
+ EXPECT_EQ(test.script, locale->GetScriptForHan()) << test.locale;
+ }
+ }
+}
+
+TEST(LayoutLocaleTest, BreakKeyword) {
+ struct {
+ const char* expected;
+ const char* locale;
+ LineBreakIteratorMode mode;
+ } tests[] = {
+ {nullptr, nullptr, LineBreakIteratorMode::kDefault},
+ {"", "", LineBreakIteratorMode::kDefault},
+ {nullptr, nullptr, LineBreakIteratorMode::kStrict},
+ {"", "", LineBreakIteratorMode::kStrict},
+ {"ja", "ja", LineBreakIteratorMode::kDefault},
+ {"ja@lb=normal", "ja", LineBreakIteratorMode::kNormal},
+ {"ja@lb=strict", "ja", LineBreakIteratorMode::kStrict},
+ {"ja@lb=loose", "ja", LineBreakIteratorMode::kLoose},
+ };
+ for (const auto& test : tests) {
+ scoped_refptr<LayoutLocale> locale =
+ LayoutLocale::CreateForTesting(test.locale);
+ EXPECT_EQ(test.expected, locale->LocaleWithBreakKeyword(test.mode))
+ << String::Format("'%s' with line-break %d should be '%s'", test.locale,
+ static_cast<int>(test.mode), test.expected);
+ }
+}
+
+TEST(LayoutLocaleTest, ExistingKeywordName) {
+ const char* tests[] = {
+ "en@x=", "en@lb=xyz", "en@ =",
+ };
+ for (auto* const test : tests) {
+ scoped_refptr<LayoutLocale> locale = LayoutLocale::CreateForTesting(test);
+ EXPECT_EQ(test,
+ locale->LocaleWithBreakKeyword(LineBreakIteratorMode::kNormal));
+ }
+}
+
+TEST(LayoutLocaleTest, AcceptLanguagesChanged) {
+ struct {
+ const char* accept_languages;
+ UScriptCode script;
+ const char* locale;
+ } tests[] = {
+ // Non-Han script cases.
+ {nullptr, USCRIPT_COMMON, nullptr},
+ {"", USCRIPT_COMMON, nullptr},
+ {"en-US", USCRIPT_COMMON, nullptr},
+ {",en-US", USCRIPT_COMMON, nullptr},
+
+ // Single value cases.
+ {"ja-JP", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp"},
+ {"ko-KR", USCRIPT_HANGUL, "ko-kr"},
+ {"zh-CN", USCRIPT_SIMPLIFIED_HAN, "zh-Hans"},
+ {"zh-HK", USCRIPT_TRADITIONAL_HAN, "zh-Hant"},
+ {"zh-TW", USCRIPT_TRADITIONAL_HAN, "zh-Hant"},
+
+ // Language only.
+ {"ja", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp"},
+ {"ko", USCRIPT_HANGUL, "ko-kr"},
+ {"zh", USCRIPT_SIMPLIFIED_HAN, "zh-Hans"},
+
+ // Unusual combinations.
+ {"en-JP", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp"},
+
+ // Han scripts not in the first item.
+ {"en-US,ja-JP", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp"},
+ {"en-US,en-JP", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp"},
+
+ // Multiple Han scripts. The first one wins.
+ {"ja-JP,zh-CN", USCRIPT_KATAKANA_OR_HIRAGANA, "ja-jp"},
+ {"zh-TW,ja-JP", USCRIPT_TRADITIONAL_HAN, "zh-Hant"},
+ };
+
+ for (const auto& test : tests) {
+ LayoutLocale::AcceptLanguagesChanged(test.accept_languages);
+ const LayoutLocale* locale = LayoutLocale::LocaleForHan(nullptr);
+
+ if (test.script == USCRIPT_COMMON) {
+ EXPECT_EQ(nullptr, locale) << test.accept_languages;
+ continue;
+ }
+
+ ASSERT_NE(nullptr, locale) << test.accept_languages;
+ EXPECT_EQ(test.script, locale->GetScriptForHan()) << test.accept_languages;
+ EXPECT_STRCASEEQ(test.locale, locale->LocaleForHanForSkFontMgr())
+ << test.accept_languages;
+ }
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/text/line_ending.cc b/chromium/third_party/blink/renderer/platform/text/line_ending.cc
index 9182cbd34a6..442f62d6fd8 100644
--- a/chromium/third_party/blink/renderer/platform/text/line_ending.cc
+++ b/chromium/third_party/blink/renderer/platform/text/line_ending.cc
@@ -41,55 +41,6 @@
namespace blink {
namespace {
-class OutputBuffer {
- STACK_ALLOCATED();
- DISALLOW_COPY_AND_ASSIGN(OutputBuffer);
-
- public:
- OutputBuffer() = default;
- virtual char* Allocate(size_t) = 0;
- virtual void Copy(const CString&) = 0;
- virtual ~OutputBuffer() = default;
-};
-
-class CStringBuffer final : public OutputBuffer {
- public:
- CStringBuffer(CString& buffer) : buffer_(buffer) {}
- ~CStringBuffer() override = default;
-
- char* Allocate(size_t size) override {
- char* ptr;
- buffer_ = CString::CreateUninitialized(size, ptr);
- return ptr;
- }
-
- void Copy(const CString& source) override { buffer_ = source; }
-
- const CString& Buffer() const { return buffer_; }
-
- private:
- CString buffer_;
-};
-
-class VectorCharAppendBuffer final : public OutputBuffer {
- public:
- VectorCharAppendBuffer(Vector<char>& buffer) : buffer_(buffer) {}
- ~VectorCharAppendBuffer() override = default;
-
- char* Allocate(size_t size) override {
- size_t old_size = buffer_.size();
- buffer_.Grow(old_size + size);
- return buffer_.data() + old_size;
- }
-
- void Copy(const CString& source) override {
- buffer_.Append(source.data(), source.length());
- }
-
- private:
- Vector<char>& buffer_;
-};
-
template <typename CharType>
size_t RequiredSizeForCRLF(const CharType* data, size_t length) {
size_t new_len = 0;
@@ -137,19 +88,24 @@ void NormalizeToCRLF(const CharType* src, size_t src_length, CharType* q) {
}
}
+#if defined(OS_WIN)
void InternalNormalizeLineEndingsToCRLF(const CString& from,
- OutputBuffer& buffer) {
+ Vector<char>& buffer) {
size_t new_len = RequiredSizeForCRLF(from.data(), from.length());
if (new_len < from.length())
return;
if (new_len == from.length()) {
- buffer.Copy(from);
+ buffer.Append(from.data(), from.length());
return;
}
- NormalizeToCRLF(from.data(), from.length(), buffer.Allocate(new_len));
+ size_t old_buffer_size = buffer.size();
+ buffer.Grow(old_buffer_size + new_len);
+ char* write_position = buffer.data() + old_buffer_size;
+ NormalizeToCRLF(from.data(), from.length(), write_position);
}
+#endif // defined(OS_WIN)
} // namespace
@@ -202,15 +158,6 @@ void NormalizeLineEndingsToLF(const CString& from, Vector<char>& result) {
}
}
-CString NormalizeLineEndingsToCRLF(const CString& from) {
- if (!from.length())
- return from;
- CString result;
- CStringBuffer buffer(result);
- InternalNormalizeLineEndingsToCRLF(from, buffer);
- return buffer.Buffer();
-}
-
String NormalizeLineEndingsToCRLF(const String& src) {
size_t length = src.length();
if (length == 0)
@@ -233,8 +180,7 @@ String NormalizeLineEndingsToCRLF(const String& src) {
void NormalizeLineEndingsToNative(const CString& from, Vector<char>& result) {
#if defined(OS_WIN)
- VectorCharAppendBuffer buffer(result);
- InternalNormalizeLineEndingsToCRLF(from, buffer);
+ InternalNormalizeLineEndingsToCRLF(from, result);
#else
NormalizeLineEndingsToLF(from, result);
#endif
diff --git a/chromium/third_party/blink/renderer/platform/text/line_ending.h b/chromium/third_party/blink/renderer/platform/text/line_ending.h
index 2c15f0f820a..fca3cd8a56d 100644
--- a/chromium/third_party/blink/renderer/platform/text/line_ending.h
+++ b/chromium/third_party/blink/renderer/platform/text/line_ending.h
@@ -39,7 +39,6 @@
namespace blink {
// Normalize all line-endings in the given string to CRLF.
-PLATFORM_EXPORT CString NormalizeLineEndingsToCRLF(const CString& from);
PLATFORM_EXPORT String NormalizeLineEndingsToCRLF(const String& from);
// Normalize all line-endings in the given string to LF and append the result to
diff --git a/chromium/third_party/blink/renderer/platform/text/platform_locale_test.cc b/chromium/third_party/blink/renderer/platform/text/platform_locale_test.cc
index 3882b5c6f93..1e8e041779a 100644
--- a/chromium/third_party/blink/renderer/platform/text/platform_locale_test.cc
+++ b/chromium/third_party/blink/renderer/platform/text/platform_locale_test.cc
@@ -9,10 +9,13 @@
namespace blink {
TEST(PlatformLocaleTest, StripInvalidNumberCharacters) {
- std::unique_ptr<Locale> locale = Locale::Create("ar");
+ // Arabic does not use Arabic-Indic digit any more per
+ // Google's customized CLDR 33.1, but ar-EG does. Persian
+ // uses Extened Arabic-Indic digits.
+ std::unique_ptr<Locale> locale = Locale::Create("fa");
String result = locale->StripInvalidNumberCharacters(
- String::FromUTF8("abc\xD9\xA0ghi"), "0123456789");
- // ARABIC-INDIC DIGIT ZERO U+0660 = \xD9\xA0 in UTF-8
- EXPECT_EQ(String::FromUTF8("\xD9\xA0"), result);
+ String::FromUTF8(u8"abc\u06F0ghi"), "0123456789");
+ // EXTENDED ARABIC-INDIC DIGIT ZERO U+06F0
+ EXPECT_EQ(String::FromUTF8(u8"\u06F0"), result);
}
}
diff --git a/chromium/third_party/blink/renderer/platform/text/text_boundaries_test.cc b/chromium/third_party/blink/renderer/platform/text/text_boundaries_test.cc
index ca60c49d010..3241d14a2e7 100644
--- a/chromium/third_party/blink/renderer/platform/text/text_boundaries_test.cc
+++ b/chromium/third_party/blink/renderer/platform/text/text_boundaries_test.cc
@@ -151,19 +151,21 @@ TEST_F(TextBoundariesTest, ForwardPunctuations) {
EXPECT_EQ("abc^,|,", TryFindWordForward("abc|,,"));
}
+// A sequence of whitespaces is treated as a single word.
+// See http://unicode.org/reports/tr29/#WB3d .
TEST_F(TextBoundariesTest, ForwardWhitespaces) {
- EXPECT_EQ("^ | abc def ", TryFindWordForward("| abc def "));
- EXPECT_EQ(" ^ |abc def ", TryFindWordForward(" | abc def "));
+ EXPECT_EQ("^ |abc def ", TryFindWordForward("| abc def "));
+ EXPECT_EQ("^ |abc def ", TryFindWordForward(" | abc def "));
EXPECT_EQ(" ^abc| def ", TryFindWordForward(" |abc def "));
EXPECT_EQ(" ^abc| def ", TryFindWordForward(" a|bc def "));
EXPECT_EQ(" ^abc| def ", TryFindWordForward(" ab|c def "));
- EXPECT_EQ(" abc^ | def ", TryFindWordForward(" abc| def "));
- EXPECT_EQ(" abc ^ |def ", TryFindWordForward(" abc | def "));
+ EXPECT_EQ(" abc^ |def ", TryFindWordForward(" abc| def "));
+ EXPECT_EQ(" abc^ |def ", TryFindWordForward(" abc | def "));
EXPECT_EQ(" abc ^def| ", TryFindWordForward(" abc |def "));
EXPECT_EQ(" abc ^def| ", TryFindWordForward(" abc d|ef "));
EXPECT_EQ(" abc ^def| ", TryFindWordForward(" abc de|f "));
- EXPECT_EQ(" abc def^ | ", TryFindWordForward(" abc def| "));
- EXPECT_EQ(" abc def ^ |", TryFindWordForward(" abc def | "));
+ EXPECT_EQ(" abc def^ |", TryFindWordForward(" abc def| "));
+ EXPECT_EQ(" abc def^ |", TryFindWordForward(" abc def | "));
EXPECT_EQ(" abc def ^|", TryFindWordForward(" abc def |"))
<< "No word after |";
}
diff --git a/chromium/third_party/blink/renderer/platform/text/text_break_iterator.cc b/chromium/third_party/blink/renderer/platform/text/text_break_iterator.cc
index 6ff0d5437b7..bc6d101d91d 100644
--- a/chromium/third_party/blink/renderer/platform/text/text_break_iterator.cc
+++ b/chromium/third_party/blink/renderer/platform/text/text_break_iterator.cc
@@ -53,6 +53,29 @@ unsigned NumGraphemeClusters(const String& string) {
return num;
}
+void GraphemesClusterList(String text,
+ unsigned start,
+ unsigned length,
+ Vector<unsigned>* graphemes) {
+ graphemes->resize(length);
+ if (!length)
+ return;
+
+ String substring = text.Substring(start, length);
+ NonSharedCharacterBreakIterator it(substring);
+
+ int cursor_pos = it.Next();
+ unsigned count = 0;
+ unsigned pos = 0;
+ while (cursor_pos >= 0) {
+ for (; pos < static_cast<unsigned>(cursor_pos) && pos < length; ++pos) {
+ (*graphemes)[pos] = count;
+ }
+ cursor_pos = it.Next();
+ count++;
+ }
+}
+
unsigned LengthOfGraphemeCluster(const String& string, unsigned offset) {
unsigned string_length = string.length();
@@ -279,10 +302,9 @@ template <typename CharacterType,
BreakSpaceType break_space>
inline int LazyLineBreakIterator::NextBreakablePosition(
int pos,
- const CharacterType* str) const {
- int len = static_cast<int>(string_.length());
+ const CharacterType* str,
+ int len) const {
int next_break = -1;
-
UChar last_last_ch = pos > 1 ? str[pos - 2] : SecondToLastCharacter();
UChar last_ch = pos > 0 ? str[pos - 1] : LastCharacter();
bool is_last_space = IsBreakableSpace(last_ch);
@@ -357,30 +379,35 @@ inline int LazyLineBreakIterator::NextBreakablePosition(
template <typename CharacterType, LineBreakType lineBreakType>
inline int LazyLineBreakIterator::NextBreakablePosition(
int pos,
- const CharacterType* str) const {
+ const CharacterType* str,
+ int len) const {
switch (break_space_) {
case BreakSpaceType::kBeforeEverySpace:
return NextBreakablePosition<CharacterType, lineBreakType,
- BreakSpaceType::kBeforeEverySpace>(pos, str);
+ BreakSpaceType::kBeforeEverySpace>(pos, str,
+ len);
case BreakSpaceType::kBeforeSpaceRun:
return NextBreakablePosition<CharacterType, lineBreakType,
- BreakSpaceType::kBeforeSpaceRun>(pos, str);
+ BreakSpaceType::kBeforeSpaceRun>(pos, str,
+ len);
}
NOTREACHED();
return NextBreakablePosition<CharacterType, lineBreakType,
- BreakSpaceType::kBeforeEverySpace>(pos, str);
+ BreakSpaceType::kBeforeEverySpace>(pos, str,
+ len);
}
template <LineBreakType lineBreakType>
-inline int LazyLineBreakIterator::NextBreakablePosition(int pos) const {
+inline int LazyLineBreakIterator::NextBreakablePosition(int pos,
+ int len) const {
if (UNLIKELY(string_.IsNull()))
return 0;
if (string_.Is8Bit()) {
- return NextBreakablePosition<LChar, lineBreakType>(pos,
- string_.Characters8());
+ return NextBreakablePosition<LChar, lineBreakType>(
+ pos, string_.Characters8(), len);
}
- return NextBreakablePosition<UChar, lineBreakType>(pos,
- string_.Characters16());
+ return NextBreakablePosition<UChar, lineBreakType>(
+ pos, string_.Characters16(), len);
}
int LazyLineBreakIterator::NextBreakablePositionBreakCharacter(int pos) const {
@@ -389,16 +416,16 @@ int LazyLineBreakIterator::NextBreakablePositionBreakCharacter(int pos) const {
return next != kTextBreakDone ? next : string_.length();
}
-int LazyLineBreakIterator::NextBreakablePosition(
- int pos,
- LineBreakType line_break_type) const {
+int LazyLineBreakIterator::NextBreakablePosition(int pos,
+ LineBreakType line_break_type,
+ int len) const {
switch (line_break_type) {
case LineBreakType::kNormal:
- return NextBreakablePosition<LineBreakType::kNormal>(pos);
+ return NextBreakablePosition<LineBreakType::kNormal>(pos, len);
case LineBreakType::kBreakAll:
- return NextBreakablePosition<LineBreakType::kBreakAll>(pos);
+ return NextBreakablePosition<LineBreakType::kBreakAll>(pos, len);
case LineBreakType::kKeepAll:
- return NextBreakablePosition<LineBreakType::kKeepAll>(pos);
+ return NextBreakablePosition<LineBreakType::kKeepAll>(pos, len);
case LineBreakType::kBreakCharacter:
return NextBreakablePositionBreakCharacter(pos);
}
@@ -406,9 +433,15 @@ int LazyLineBreakIterator::NextBreakablePosition(
return NextBreakablePosition(pos, LineBreakType::kNormal);
}
+int LazyLineBreakIterator::NextBreakablePosition(
+ int pos,
+ LineBreakType line_break_type) const {
+ return NextBreakablePosition(pos, line_break_type,
+ static_cast<int>(string_.length()));
+}
+
unsigned LazyLineBreakIterator::NextBreakOpportunity(unsigned offset) const {
- int next_break = -1;
- IsBreakable(offset, next_break);
+ int next_break = NextBreakablePosition(offset, break_type_);
DCHECK_GE(next_break, 0);
return next_break;
}
@@ -416,9 +449,20 @@ unsigned LazyLineBreakIterator::NextBreakOpportunity(unsigned offset) const {
unsigned LazyLineBreakIterator::PreviousBreakOpportunity(unsigned offset,
unsigned min) const {
unsigned pos = std::min(offset, string_.length());
- for (; pos > min; pos--) {
- if (IsBreakable(pos))
- return pos;
+ // +2 to ensure at least one code point is included.
+ unsigned end = std::min(pos + 2, string_.length());
+ while (pos > min) {
+ int next_break = NextBreakablePosition(pos, break_type_, end);
+ DCHECK_GE(next_break, 0);
+ if (static_cast<unsigned>(next_break) == pos)
+ return next_break;
+
+ // There's no break opportunities at |pos| or after.
+ end = pos;
+ if (string_.Is8Bit())
+ --pos;
+ else
+ U16_BACK_1(string_.Characters16(), 0, pos);
}
return min;
}
diff --git a/chromium/third_party/blink/renderer/platform/text/text_break_iterator.h b/chromium/third_party/blink/renderer/platform/text/text_break_iterator.h
index 02f32172082..958e3f844d6 100644
--- a/chromium/third_party/blink/renderer/platform/text/text_break_iterator.h
+++ b/chromium/third_party/blink/renderer/platform/text/text_break_iterator.h
@@ -279,12 +279,13 @@ class PLATFORM_EXPORT LazyLineBreakIterator final {
}
template <typename CharacterType, LineBreakType, BreakSpaceType>
- int NextBreakablePosition(int pos, const CharacterType* str) const;
+ int NextBreakablePosition(int pos, const CharacterType* str, int len) const;
template <typename CharacterType, LineBreakType>
- int NextBreakablePosition(int pos, const CharacterType* str) const;
+ int NextBreakablePosition(int pos, const CharacterType* str, int len) const;
template <LineBreakType>
- int NextBreakablePosition(int pos) const;
+ int NextBreakablePosition(int pos, int len) const;
int NextBreakablePositionBreakCharacter(int pos) const;
+ int NextBreakablePosition(int pos, LineBreakType, int len) const;
int NextBreakablePosition(int pos, LineBreakType) const;
static const unsigned kPriorContextCapacity = 2;
@@ -362,6 +363,13 @@ PLATFORM_EXPORT unsigned NumGraphemeClusters(const String&);
// Returns the number of code units that the next grapheme cluster is made of.
PLATFORM_EXPORT unsigned LengthOfGraphemeCluster(const String&, unsigned = 0);
+// Returns a list of graphemes cluster at each character using character break
+// rules.
+PLATFORM_EXPORT void GraphemesClusterList(String text,
+ unsigned start,
+ unsigned length,
+ Vector<unsigned>* graphemes);
+
} // namespace blink
#endif
diff --git a/chromium/third_party/blink/renderer/platform/text/text_break_iterator_icu.cc b/chromium/third_party/blink/renderer/platform/text/text_break_iterator_icu.cc
index 824a51f0d46..327c6f9a9e1 100644
--- a/chromium/third_party/blink/renderer/platform/text/text_break_iterator_icu.cc
+++ b/chromium/third_party/blink/renderer/platform/text/text_break_iterator_icu.cc
@@ -34,6 +34,7 @@
#include "third_party/blink/renderer/platform/text/text_break_iterator_internal_icu.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
@@ -730,17 +731,23 @@ void ReleaseLineBreakIterator(TextBreakIterator* iterator) {
LineBreakIteratorPool::SharedPool().Put(iterator);
}
-static TextBreakIterator* g_non_shared_character_break_iterator;
+static TextBreakIterator* GetNonSharedCharacterBreakIterator() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ ThreadSpecific<std::unique_ptr<TextBreakIterator>>, thread_specific, ());
-static inline bool CompareAndSwapNonSharedCharacterBreakIterator(
- TextBreakIterator* expected,
- TextBreakIterator* new_value) {
- DEFINE_STATIC_LOCAL(Mutex, non_shared_character_break_iterator_mutex, ());
- MutexLocker locker(non_shared_character_break_iterator_mutex);
- if (g_non_shared_character_break_iterator != expected)
- return false;
- g_non_shared_character_break_iterator = new_value;
- return true;
+ std::unique_ptr<TextBreakIterator>& iterator = *thread_specific;
+
+ if (!iterator) {
+ ICUError error_code;
+ iterator = base::WrapUnique(icu::BreakIterator::createCharacterInstance(
+ icu::Locale(CurrentTextBreakLocaleID()), error_code));
+ CHECK(U_SUCCESS(error_code) && iterator)
+ << "ICU could not open a break iterator: " << u_errorName(error_code)
+ << " (" << error_code << ")";
+ }
+
+ DCHECK(iterator);
+ return iterator.get();
}
NonSharedCharacterBreakIterator::NonSharedCharacterBreakIterator(
@@ -779,29 +786,13 @@ NonSharedCharacterBreakIterator::NonSharedCharacterBreakIterator(
void NonSharedCharacterBreakIterator::CreateIteratorForBuffer(
const UChar* buffer,
unsigned length) {
- iterator_ = g_non_shared_character_break_iterator;
- bool created_iterator =
- iterator_ &&
- CompareAndSwapNonSharedCharacterBreakIterator(iterator_, nullptr);
- if (!created_iterator) {
- ICUError error_code;
- iterator_ = icu::BreakIterator::createCharacterInstance(
- icu::Locale(CurrentTextBreakLocaleID()), error_code);
- CHECK(U_SUCCESS(error_code) && iterator_)
- << "ICU could not open a break iterator: " << u_errorName(error_code)
- << " (" << error_code << ")";
- } else {
- CHECK(iterator_);
- }
-
+ iterator_ = GetNonSharedCharacterBreakIterator();
SetText16(iterator_, buffer, length);
}
NonSharedCharacterBreakIterator::~NonSharedCharacterBreakIterator() {
if (is8_bit_)
return;
- if (!CompareAndSwapNonSharedCharacterBreakIterator(nullptr, iterator_))
- delete iterator_;
}
int NonSharedCharacterBreakIterator::Next() {
@@ -869,30 +860,6 @@ bool IsWordTextBreak(TextBreakIterator* iterator) {
return rule_status != UBRK_WORD_NONE;
}
-static TextBreakIterator* SetUpIteratorWithRules(const char* break_rules,
- const UChar* string,
- int length) {
- if (!string)
- return nullptr;
-
- static TextBreakIterator* iterator = nullptr;
- if (!iterator) {
- UParseError parse_status;
- UErrorCode open_status = U_ZERO_ERROR;
- // break_rules is ASCII. Pick the most efficient UnicodeString ctor.
- iterator = new icu::RuleBasedBreakIterator(
- icu::UnicodeString(break_rules, -1, US_INV), parse_status, open_status);
- DCHECK(U_SUCCESS(open_status))
- << "ICU could not open a break iterator: " << u_errorName(open_status)
- << " (" << open_status << ")";
- if (!iterator)
- return nullptr;
- }
-
- SetText16(iterator, string, length);
- return iterator;
-}
-
TextBreakIterator* CursorMovementIterator(const UChar* string, int length) {
// This rule set is based on character-break iterator rules of ICU 4.0
// <http://source.icu-project.org/repos/icu/icu/tags/release-4-0/source/data/brkitr/char.txt>.
@@ -983,7 +950,28 @@ TextBreakIterator* CursorMovementIterator(const UChar* string, int length) {
"!!safe_reverse;"
"!!safe_forward;";
- return SetUpIteratorWithRules(kRules, string, length);
+ if (!string)
+ return nullptr;
+
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(
+ ThreadSpecific<std::unique_ptr<icu::RuleBasedBreakIterator>>,
+ thread_specific, ());
+
+ std::unique_ptr<icu::RuleBasedBreakIterator>& iterator = *thread_specific;
+
+ if (!iterator) {
+ UParseError parse_status;
+ UErrorCode open_status = U_ZERO_ERROR;
+ // break_rules is ASCII. Pick the most efficient UnicodeString ctor.
+ iterator = std::make_unique<icu::RuleBasedBreakIterator>(
+ icu::UnicodeString(kRules, -1, US_INV), parse_status, open_status);
+ DCHECK(U_SUCCESS(open_status))
+ << "ICU could not open a break iterator: " << u_errorName(open_status)
+ << " (" << open_status << ")";
+ }
+
+ SetText16(iterator.get(), string, length);
+ return iterator.get();
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/text/text_break_iterator_internal_icu.cc b/chromium/third_party/blink/renderer/platform/text/text_break_iterator_internal_icu.cc
index 75151ef1b4b..dd26ae05027 100644
--- a/chromium/third_party/blink/renderer/platform/text/text_break_iterator_internal_icu.cc
+++ b/chromium/third_party/blink/renderer/platform/text/text_break_iterator_internal_icu.cc
@@ -31,7 +31,8 @@ namespace blink {
static const char* UILanguage() {
// Chrome's UI language can be different from the OS UI language on Windows.
// We want to return Chrome's UI language here.
- DEFINE_STATIC_LOCAL(const CString, locale, (DefaultLanguage().Latin1()));
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(const CString, locale,
+ (DefaultLanguage().Latin1()));
return locale.data();
}
diff --git a/chromium/third_party/blink/renderer/platform/text/text_break_iterator_test.cc b/chromium/third_party/blink/renderer/platform/text/text_break_iterator_test.cc
index 74f59591782..fd23955285d 100644
--- a/chromium/third_party/blink/renderer/platform/text/text_break_iterator_test.cc
+++ b/chromium/third_party/blink/renderer/platform/text/text_break_iterator_test.cc
@@ -71,6 +71,14 @@ class TextBreakIteratorTest : public testing::Test {
return LengthOfGraphemeCluster(test_string_);
}
+ Vector<unsigned> GraphemesClusterList(String input,
+ unsigned start,
+ unsigned length) {
+ Vector<unsigned> result;
+ ::blink::GraphemesClusterList(input, start, length, &result);
+ return result;
+ }
+
private:
String test_string_;
};
@@ -268,4 +276,21 @@ TEST_F(TextBreakIteratorTest, LengthOfGraphemeCluster) {
EXPECT_EQ(2u, TestLengthOfGraphemeCluster());
}
+TEST_F(TextBreakIteratorTest, GraphemesClusterListTest) {
+ EXPECT_EQ(GraphemesClusterList(u"hello", 0, 5),
+ Vector<unsigned>({0, 1, 2, 3, 4}));
+ EXPECT_EQ(GraphemesClusterList(u"hello", 2, 2), Vector<unsigned>({0, 1}));
+ EXPECT_EQ(GraphemesClusterList(u"voila\u0300!", 0, 7),
+ Vector<unsigned>({0, 1, 2, 3, 4, 4, 5}));
+ EXPECT_EQ(GraphemesClusterList(u"di\u0303\u031c\u0337!", 0, 6),
+ Vector<unsigned>({0, 1, 1, 1, 1, 2}));
+ EXPECT_EQ(GraphemesClusterList(u"🇨🇦", 0, 4), Vector<unsigned>({0, 0, 0, 0}));
+
+ EXPECT_EQ(GraphemesClusterList(u"🏳️‍🌈", 0, 6),
+ Vector<unsigned>({0, 0, 0, 0, 0, 0}));
+ // NO ZWJ on this sequence.
+ EXPECT_EQ(GraphemesClusterList(u"🏳🌈", 0, 4),
+ Vector<unsigned>({0, 0, 1, 1}));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/text/text_encoding_detector.cc b/chromium/third_party/blink/renderer/platform/text/text_encoding_detector.cc
index 16efbc2ee4e..e11100f057d 100644
--- a/chromium/third_party/blink/renderer/platform/text/text_encoding_detector.cc
+++ b/chromium/third_party/blink/renderer/platform/text/text_encoding_detector.cc
@@ -69,6 +69,11 @@ bool DetectTextEncoding(const char* data,
false, // Include 7-bit encodings to detect ISO-2022-JP
&consumed_bytes, &is_reliable);
+ if (encoding == UNKNOWN_ENCODING)
+ *detected_encoding = WTF::UnknownEncoding();
+ else
+ *detected_encoding = WTF::TextEncoding(MimeEncodingName(encoding));
+
// Should return false if the detected encoding is UTF8. This helps prevent
// modern web sites from neglecting proper encoding labelling and simply
// relying on browser-side encoding detection. Encoding detection is supposed
@@ -76,12 +81,8 @@ bool DetectTextEncoding(const char* data,
// be applied to local file resources).
// Detection failure leads |TextResourceDecoder| to use its default encoding
// determined from system locale or TLD.
- if (encoding == UNKNOWN_ENCODING ||
- (hint_url.Protocol() != "file" && encoding == UTF8))
- return false;
-
- *detected_encoding = WTF::TextEncoding(MimeEncodingName(encoding));
- return true;
+ return !(encoding == UNKNOWN_ENCODING ||
+ (hint_url.Protocol() != "file" && encoding == UTF8));
}
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/text/text_run.cc b/chromium/third_party/blink/renderer/platform/text/text_run.cc
index 3aa7a156c69..74782e83b62 100644
--- a/chromium/third_party/blink/renderer/platform/text/text_run.cc
+++ b/chromium/third_party/blink/renderer/platform/text/text_run.cc
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/text/character.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
namespace blink {
@@ -56,8 +57,7 @@ void TextRun::SetText(const String& string) {
data_.characters16 = string.Characters16();
}
-std::unique_ptr<UChar[]> TextRun::NormalizedUTF16(
- unsigned* result_length) const {
+String TextRun::NormalizedUTF16() const {
const UChar* source;
String string_for8_bit_run;
if (Is8Bit()) {
@@ -68,8 +68,8 @@ std::unique_ptr<UChar[]> TextRun::NormalizedUTF16(
source = Characters16();
}
- auto buffer = std::make_unique<UChar[]>(len_ + 1);
- *result_length = 0;
+ StringBuffer<UChar> buffer(len_);
+ unsigned result_length = 0;
bool error = false;
unsigned position = 0;
@@ -92,12 +92,12 @@ std::unique_ptr<UChar[]> TextRun::NormalizedUTF16(
character = kZeroWidthSpaceCharacter;
}
- U16_APPEND(buffer, *result_length, len_, character, error);
+ U16_APPEND(buffer.Characters(), result_length, len_, character, error);
DCHECK(!error);
}
- DCHECK(*result_length <= len_);
- return buffer;
+ DCHECK(result_length <= len_);
+ return String::Adopt(buffer);
}
unsigned TextRun::IndexOfSubRun(const TextRun& sub_run) const {
diff --git a/chromium/third_party/blink/renderer/platform/text/text_run.h b/chromium/third_party/blink/renderer/platform/text/text_run.h
index b70d5c5ac46..e2522c3f33b 100644
--- a/chromium/third_party/blink/renderer/platform/text/text_run.h
+++ b/chromium/third_party/blink/renderer/platform/text/text_run.h
@@ -25,7 +25,6 @@
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_TEXT_TEXT_RUN_H_
#include "base/optional.h"
-#include "third_party/blink/renderer/platform/fonts/glyph.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/text/tab_size.h"
@@ -263,7 +262,7 @@ class PLATFORM_EXPORT TextRun final {
// Up-converts to UTF-16 as needed and normalizes spaces and Unicode control
// characters as per the CSS Text Module Level 3 specification.
// https://drafts.csswg.org/css-text-3/#white-space-processing
- std::unique_ptr<UChar[]> NormalizedUTF16(unsigned* result_length) const;
+ String NormalizedUTF16() const;
private:
union {
diff --git a/chromium/third_party/blink/renderer/platform/text/writing_mode.h b/chromium/third_party/blink/renderer/platform/text/writing_mode.h
index e954659304d..bbe414bc241 100644
--- a/chromium/third_party/blink/renderer/platform/text/writing_mode.h
+++ b/chromium/third_party/blink/renderer/platform/text/writing_mode.h
@@ -56,6 +56,16 @@ inline bool IsFlippedLinesWritingMode(WritingMode writing_mode) {
return writing_mode == WritingMode::kVerticalLr;
}
+// In flipped-lines writing mode, 'line-over' and 'block-start' don't match.
+// When dealing with the logical coordinate system in the [line-relative
+// directions], 'vertical-lr' has 'line-over' on right, which is equivalent to
+// the 'vertical-rl' in the flow-relative directions.
+// https://drafts.csswg.org/css-writing-modes-3/#line-directions
+inline WritingMode ToLineWritingMode(WritingMode writing_mode) {
+ return !IsFlippedLinesWritingMode(writing_mode) ? writing_mode
+ : WritingMode::kVerticalRl;
+}
+
// Block progression increases in the opposite direction to normal; modes
// vertical-rl.
inline bool IsFlippedBlocksWritingMode(WritingMode writing_mode) {
diff --git a/chromium/third_party/blink/renderer/platform/text_codec_fuzzer.cc b/chromium/third_party/blink/renderer/platform/text_codec_fuzzer.cc
index e5c06f75000..e69046bce0d 100644
--- a/chromium/third_party/blink/renderer/platform/text_codec_fuzzer.cc
+++ b/chromium/third_party/blink/renderer/platform/text_codec_fuzzer.cc
@@ -16,8 +16,9 @@ using namespace blink;
// so it must live in the latter directory. Once wtf/ moves into platform/wtf
// this should move there as well.
-WTF::FlushBehavior kFlushBehavior[] = {WTF::kDoNotFlush, WTF::kFetchEOF,
- WTF::kDataEOF};
+WTF::FlushBehavior kFlushBehavior[] = {WTF::FlushBehavior::kDoNotFlush,
+ WTF::FlushBehavior::kFetchEOF,
+ WTF::FlushBehavior::kDataEOF};
WTF::UnencodableHandling kUnencodableHandlingOptions[] = {
WTF::kEntitiesForUnencodables, WTF::kURLEncodedEntitiesForUnencodables,
diff --git a/chromium/third_party/blink/renderer/platform/threading/DEPS b/chromium/third_party/blink/renderer/platform/threading/DEPS
deleted file mode 100644
index 7dd39b3f68b..00000000000
--- a/chromium/third_party/blink/renderer/platform/threading/DEPS
+++ /dev/null
@@ -1,16 +0,0 @@
-include_rules = [
- # Don't depend on platform/.
- "-third_party/blink/renderer/platform",
-
- # Module.
- "+third_party/blink/renderer/platform/threading",
-
- # Dependencies.
- "+base/task_scheduler",
- "+base/test",
- "+third_party/blink/renderer/platform/cross_thread_functional.h",
- "+third_party/blink/renderer/platform/platform_export.h",
- "+third_party/blink/renderer/platform/threading/background_task_runner.h",
- "+third_party/blink/renderer/platform/waitable_event.h",
- "+third_party/blink/renderer/platform/wtf",
-]
diff --git a/chromium/third_party/blink/renderer/platform/threading/background_task_runner.cc b/chromium/third_party/blink/renderer/platform/threading/background_task_runner.cc
deleted file mode 100644
index b5d0e0c80bd..00000000000
--- a/chromium/third_party/blink/renderer/platform/threading/background_task_runner.cc
+++ /dev/null
@@ -1,20 +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/platform/threading/background_task_runner.h"
-
-#include "base/location.h"
-#include "base/task_scheduler/post_task.h"
-
-namespace blink {
-
-void BackgroundTaskRunner::PostOnBackgroundThread(
- const base::Location& location,
- CrossThreadClosure closure) {
- base::PostTaskWithTraits(location,
- {base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
- ConvertToBaseCallback(std::move(closure)));
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/threading/background_task_runner.h b/chromium/third_party/blink/renderer/platform/threading/background_task_runner.h
deleted file mode 100644
index 52df8375607..00000000000
--- a/chromium/third_party/blink/renderer/platform/threading/background_task_runner.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_THREADING_BACKGROUND_TASK_RUNNER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_THREADING_BACKGROUND_TASK_RUNNER_H_
-
-#include "base/location.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/functional.h"
-
-namespace blink {
-
-namespace BackgroundTaskRunner {
-
-PLATFORM_EXPORT void PostOnBackgroundThread(const base::Location&,
- CrossThreadClosure);
-
-} // BackgroundTaskRunner
-
-} // namespace blink
-
-#endif
diff --git a/chromium/third_party/blink/renderer/platform/threading/background_task_runner_test.cc b/chromium/third_party/blink/renderer/platform/threading/background_task_runner_test.cc
deleted file mode 100644
index 5c9cc81b154..00000000000
--- a/chromium/third_party/blink/renderer/platform/threading/background_task_runner_test.cc
+++ /dev/null
@@ -1,34 +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/platform/threading/background_task_runner.h"
-
-#include <memory>
-#include "base/location.h"
-#include "base/test/scoped_task_environment.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/cross_thread_functional.h"
-#include "third_party/blink/renderer/platform/waitable_event.h"
-
-namespace blink {
-
-namespace {
-
-void PingPongTask(WaitableEvent* done_event) {
- done_event->Signal();
-}
-
-} // namespace
-
-TEST(BackgroundTaskRunnerTest, RunOnBackgroundThread) {
- base::test::ScopedTaskEnvironment scoped_task_environment;
- std::unique_ptr<WaitableEvent> done_event = std::make_unique<WaitableEvent>();
- BackgroundTaskRunner::PostOnBackgroundThread(
- FROM_HERE,
- CrossThreadBind(&PingPongTask, CrossThreadUnretained(done_event.get())));
- // Test passes by not hanging on the following wait().
- done_event->Wait();
-}
-
-} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/timer.cc b/chromium/third_party/blink/renderer/platform/timer.cc
index dacd888c445..b7fed475935 100644
--- a/chromium/third_party/blink/renderer/platform/timer.cc
+++ b/chromium/third_party/blink/renderer/platform/timer.cc
@@ -26,16 +26,11 @@
#include "third_party/blink/renderer/platform/timer.h"
-#include <limits.h>
-#include <math.h>
#include <algorithm>
-#include <limits>
#include "third_party/blink/public/platform/platform.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/address_sanitizer.h"
-#include "third_party/blink/renderer/platform/wtf/atomics.h"
-#include "third_party/blink/renderer/platform/wtf/hash_set.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
namespace blink {
@@ -75,7 +70,7 @@ void TimerBase::Stop() {
weak_ptr_factory_.InvalidateWeakPtrs();
}
-TimeDelta TimerBase::NextFireIntervalDelta() const {
+TimeDelta TimerBase::NextFireInterval() const {
DCHECK(IsActive());
TimeTicks current = TimerCurrentTimeTicks();
if (next_fire_time_ < current)
diff --git a/chromium/third_party/blink/renderer/platform/timer.h b/chromium/third_party/blink/renderer/platform/timer.h
index ede8fc7b73d..92bfbbb1a7f 100644
--- a/chromium/third_party/blink/renderer/platform/timer.h
+++ b/chromium/third_party/blink/renderer/platform/timer.h
@@ -52,12 +52,6 @@ class PLATFORM_EXPORT TimerBase {
void Start(TimeDelta next_fire_interval,
TimeDelta repeat_interval,
const base::Location&);
- void Start(double next_fire_interval,
- double repeat_interval,
- const base::Location& from_here) {
- Start(TimeDelta::FromSecondsD(next_fire_interval),
- TimeDelta::FromSecondsD(repeat_interval), from_here);
- }
void StartRepeating(TimeDelta repeat_interval, const base::Location& caller) {
Start(repeat_interval, repeat_interval, caller);
@@ -66,9 +60,6 @@ class PLATFORM_EXPORT TimerBase {
void StartOneShot(TimeDelta interval, const base::Location& caller) {
Start(interval, TimeDelta(), caller);
}
- void StartOneShot(double interval, const base::Location& caller) {
- StartOneShot(TimeDelta::FromSecondsD(interval), caller);
- }
// Timer cancellation is fast enough that you shouldn't have to worry
// about it unless you're canceling tens of thousands of tasks.
@@ -76,22 +67,14 @@ class PLATFORM_EXPORT TimerBase {
bool IsActive() const;
const base::Location& GetLocation() const { return location_; }
- TimeDelta NextFireIntervalDelta() const;
- double NextFireInterval() const {
- return NextFireIntervalDelta().InSecondsF();
- }
-
- TimeDelta RepeatIntervalDelta() const { return repeat_interval_; }
- double RepeatInterval() const { return RepeatIntervalDelta().InSecondsF(); }
+ TimeDelta NextFireInterval() const;
+ TimeDelta RepeatInterval() const { return repeat_interval_; }
void AugmentRepeatInterval(TimeDelta delta) {
TimeTicks now = TimerCurrentTimeTicks();
SetNextFireTime(now, std::max(next_fire_time_ - now + delta, TimeDelta()));
repeat_interval_ += delta;
}
- void AugmentRepeatInterval(double delta) {
- AugmentRepeatInterval(TimeDelta::FromSecondsD(delta));
- }
void MoveToNewTaskRunner(scoped_refptr<base::SingleThreadTaskRunner>);
diff --git a/chromium/third_party/blink/renderer/platform/timer_test.cc b/chromium/third_party/blink/renderer/platform/timer_test.cc
index 7b69e301a43..3ba86fac13c 100644
--- a/chromium/third_party/blink/renderer/platform/timer_test.cc
+++ b/chromium/third_party/blink/renderer/platform/timer_test.cc
@@ -12,7 +12,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/web_thread.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
#include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
#include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h"
@@ -31,44 +30,43 @@ class TimerTest : public testing::Test {
public:
void SetUp() override {
run_times_.clear();
- platform_->AdvanceClockSeconds(10.0);
- start_time_ = CurrentTimeTicksInSeconds();
+ platform_->AdvanceClock(TimeDelta::FromSeconds(10));
+ start_time_ = CurrentTimeTicks();
}
- void CountingTask(TimerBase*) {
- run_times_.push_back(CurrentTimeTicksInSeconds());
- }
+ void CountingTask(TimerBase*) { run_times_.push_back(CurrentTimeTicks()); }
void RecordNextFireTimeTask(TimerBase* timer) {
- next_fire_times_.push_back(CurrentTimeTicksInSeconds() +
- timer->NextFireInterval());
+ next_fire_times_.push_back(CurrentTimeTicks() + timer->NextFireInterval());
}
- void RunUntilDeadline(double deadline) {
- double period = deadline - CurrentTimeTicksInSeconds();
- EXPECT_GE(period, 0.0);
- platform_->RunForPeriodSeconds(period);
+ void RunUntilDeadline(TimeTicks deadline) {
+ TimeDelta period = deadline - CurrentTimeTicks();
+ EXPECT_GE(period, TimeDelta());
+ platform_->RunForPeriod(period);
}
// Returns false if there are no pending delayed tasks, otherwise sets |time|
// to the delay in seconds till the next pending delayed task is scheduled to
// fire.
- bool TimeTillNextDelayedTask(double* time) const {
- base::TimeTicks next_run_time;
- if (!platform_->GetMainThreadScheduler()
- ->GetActiveTimeDomain()
- ->NextScheduledRunTime(&next_run_time))
+ bool TimeTillNextDelayedTask(TimeDelta* time) const {
+ base::sequence_manager::LazyNow lazy_now =
+ platform_->GetMainThreadScheduler()
+ ->real_time_domain()
+ ->CreateLazyNow();
+ base::Optional<base::TimeDelta> delay = platform_->GetMainThreadScheduler()
+ ->GetActiveTimeDomain()
+ ->DelayTillNextTask(&lazy_now);
+ if (!delay)
return false;
- *time = (next_run_time -
- platform_->GetMainThreadScheduler()->GetActiveTimeDomain()->Now())
- .InSecondsF();
+ *time = *delay;
return true;
}
protected:
- double start_time_;
- WTF::Vector<double> run_times_;
- WTF::Vector<double> next_fire_times_;
+ TimeTicks start_time_;
+ WTF::Vector<TimeTicks> run_times_;
+ WTF::Vector<TimeTicks> next_fire_times_;
ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler>
platform_;
@@ -133,7 +131,7 @@ TEST_F(TimerTest, StartOneShot_Zero) {
&TimerTest::CountingTask);
timer.StartOneShot(TimeDelta(), FROM_HERE);
- double run_time;
+ TimeDelta run_time;
EXPECT_FALSE(TimeTillNextDelayedTask(&run_time));
platform_->RunUntilIdle();
@@ -146,7 +144,7 @@ TEST_F(TimerTest, StartOneShot_ZeroAndCancel) {
&TimerTest::CountingTask);
timer.StartOneShot(TimeDelta(), FROM_HERE);
- double run_time;
+ TimeDelta run_time;
EXPECT_FALSE(TimeTillNextDelayedTask(&run_time));
timer.Stop();
@@ -161,7 +159,7 @@ TEST_F(TimerTest, StartOneShot_ZeroAndCancelThenRepost) {
&TimerTest::CountingTask);
timer.StartOneShot(TimeDelta(), FROM_HERE);
- double run_time;
+ TimeDelta run_time;
EXPECT_FALSE(TimeTillNextDelayedTask(&run_time));
timer.Stop();
@@ -183,7 +181,7 @@ TEST_F(TimerTest, StartOneShot_Zero_RepostingAfterRunning) {
&TimerTest::CountingTask);
timer.StartOneShot(TimeDelta(), FROM_HERE);
- double run_time;
+ TimeDelta run_time;
EXPECT_FALSE(TimeTillNextDelayedTask(&run_time));
platform_->RunUntilIdle();
@@ -203,12 +201,13 @@ TEST_F(TimerTest, StartOneShot_NonZero) {
&TimerTest::CountingTask);
timer.StartOneShot(TimeDelta::FromSeconds(10), FROM_HERE);
- double run_time;
+ TimeDelta run_time;
EXPECT_TRUE(TimeTillNextDelayedTask(&run_time));
- EXPECT_FLOAT_EQ(10.0, run_time);
+ EXPECT_EQ(TimeDelta::FromSeconds(10), run_time);
platform_->RunUntilIdle();
- EXPECT_THAT(run_times_, ElementsAre(start_time_ + 10.0));
+ EXPECT_THAT(run_times_,
+ ElementsAre(start_time_ + TimeDelta::FromSeconds(10)));
}
TEST_F(TimerTest, StartOneShot_NonZeroAndCancel) {
@@ -217,9 +216,9 @@ TEST_F(TimerTest, StartOneShot_NonZeroAndCancel) {
&TimerTest::CountingTask);
timer.StartOneShot(TimeDelta::FromSeconds(10), FROM_HERE);
- double run_time;
+ TimeDelta run_time;
EXPECT_TRUE(TimeTillNextDelayedTask(&run_time));
- EXPECT_FLOAT_EQ(10.0, run_time);
+ EXPECT_EQ(TimeDelta::FromSeconds(10), run_time);
timer.Stop();
EXPECT_TRUE(TimeTillNextDelayedTask(&run_time));
@@ -234,9 +233,9 @@ TEST_F(TimerTest, StartOneShot_NonZeroAndCancelThenRepost) {
&TimerTest::CountingTask);
timer.StartOneShot(TimeDelta::FromSeconds(10), FROM_HERE);
- double run_time;
+ TimeDelta run_time;
EXPECT_TRUE(TimeTillNextDelayedTask(&run_time));
- EXPECT_FLOAT_EQ(10.0, run_time);
+ EXPECT_EQ(TimeDelta::FromSeconds(10), run_time);
timer.Stop();
EXPECT_TRUE(TimeTillNextDelayedTask(&run_time));
@@ -244,14 +243,15 @@ TEST_F(TimerTest, StartOneShot_NonZeroAndCancelThenRepost) {
platform_->RunUntilIdle();
EXPECT_FALSE(run_times_.size());
- double second_post_time = CurrentTimeTicksInSeconds();
+ TimeTicks second_post_time = CurrentTimeTicks();
timer.StartOneShot(TimeDelta::FromSeconds(10), FROM_HERE);
EXPECT_TRUE(TimeTillNextDelayedTask(&run_time));
- EXPECT_FLOAT_EQ(10.0, run_time);
+ EXPECT_EQ(TimeDelta::FromSeconds(10), run_time);
platform_->RunUntilIdle();
- EXPECT_THAT(run_times_, ElementsAre(second_post_time + 10.0));
+ EXPECT_THAT(run_times_,
+ ElementsAre(second_post_time + TimeDelta::FromSeconds(10)));
}
TEST_F(TimerTest, StartOneShot_NonZero_RepostingAfterRunning) {
@@ -260,20 +260,23 @@ TEST_F(TimerTest, StartOneShot_NonZero_RepostingAfterRunning) {
&TimerTest::CountingTask);
timer.StartOneShot(TimeDelta::FromSeconds(10), FROM_HERE);
- double run_time;
+ TimeDelta run_time;
EXPECT_TRUE(TimeTillNextDelayedTask(&run_time));
- EXPECT_FLOAT_EQ(10.0, run_time);
+ EXPECT_EQ(TimeDelta::FromSeconds(10), run_time);
platform_->RunUntilIdle();
- EXPECT_THAT(run_times_, ElementsAre(start_time_ + 10.0));
+ EXPECT_THAT(run_times_,
+ ElementsAre(start_time_ + TimeDelta::FromSeconds(10)));
timer.StartOneShot(TimeDelta::FromSeconds(20), FROM_HERE);
EXPECT_TRUE(TimeTillNextDelayedTask(&run_time));
- EXPECT_FLOAT_EQ(20.0, run_time);
+ EXPECT_EQ(TimeDelta::FromSeconds(20), run_time);
platform_->RunUntilIdle();
- EXPECT_THAT(run_times_, ElementsAre(start_time_ + 10.0, start_time_ + 30.0));
+ EXPECT_THAT(run_times_,
+ ElementsAre(start_time_ + TimeDelta::FromSeconds(10),
+ start_time_ + TimeDelta::FromSeconds(30)));
}
TEST_F(TimerTest, PostingTimerTwiceWithSameRunTimeDoesNothing) {
@@ -283,12 +286,13 @@ TEST_F(TimerTest, PostingTimerTwiceWithSameRunTimeDoesNothing) {
timer.StartOneShot(TimeDelta::FromSeconds(10), FROM_HERE);
timer.StartOneShot(TimeDelta::FromSeconds(10), FROM_HERE);
- double run_time;
+ TimeDelta run_time;
EXPECT_TRUE(TimeTillNextDelayedTask(&run_time));
- EXPECT_FLOAT_EQ(10.0, run_time);
+ EXPECT_EQ(TimeDelta::FromSeconds(10), run_time);
platform_->RunUntilIdle();
- EXPECT_THAT(run_times_, ElementsAre(start_time_ + 10.0));
+ EXPECT_THAT(run_times_,
+ ElementsAre(start_time_ + TimeDelta::FromSeconds(10)));
}
TEST_F(TimerTest, PostingTimerTwiceWithNewerRunTimeCancelsOriginalTask) {
@@ -299,7 +303,7 @@ TEST_F(TimerTest, PostingTimerTwiceWithNewerRunTimeCancelsOriginalTask) {
timer.StartOneShot(TimeDelta(), FROM_HERE);
platform_->RunUntilIdle();
- EXPECT_THAT(run_times_, ElementsAre(start_time_ + 0.0));
+ EXPECT_THAT(run_times_, ElementsAre(start_time_ + TimeDelta::FromSeconds(0)));
}
TEST_F(TimerTest, PostingTimerTwiceWithLaterRunTimeCancelsOriginalTask) {
@@ -310,7 +314,8 @@ TEST_F(TimerTest, PostingTimerTwiceWithLaterRunTimeCancelsOriginalTask) {
timer.StartOneShot(TimeDelta::FromSeconds(10), FROM_HERE);
platform_->RunUntilIdle();
- EXPECT_THAT(run_times_, ElementsAre(start_time_ + 10.0));
+ EXPECT_THAT(run_times_,
+ ElementsAre(start_time_ + TimeDelta::FromSeconds(10)));
}
TEST_F(TimerTest, StartRepeatingTask) {
@@ -319,14 +324,16 @@ TEST_F(TimerTest, StartRepeatingTask) {
&TimerTest::CountingTask);
timer.StartRepeating(TimeDelta::FromSeconds(1), FROM_HERE);
- double run_time;
+ TimeDelta run_time;
EXPECT_TRUE(TimeTillNextDelayedTask(&run_time));
- EXPECT_FLOAT_EQ(1.0, run_time);
+ EXPECT_EQ(TimeDelta::FromSeconds(1), run_time);
- RunUntilDeadline(start_time_ + 5.5);
- EXPECT_THAT(run_times_, ElementsAre(start_time_ + 1.0, start_time_ + 2.0,
- start_time_ + 3.0, start_time_ + 4.0,
- start_time_ + 5.0));
+ RunUntilDeadline(start_time_ + TimeDelta::FromMilliseconds(5500));
+ EXPECT_THAT(run_times_, ElementsAre(start_time_ + TimeDelta::FromSeconds(1),
+ start_time_ + TimeDelta::FromSeconds(2),
+ start_time_ + TimeDelta::FromSeconds(3),
+ start_time_ + TimeDelta::FromSeconds(4),
+ start_time_ + TimeDelta::FromSeconds(5)));
}
TEST_F(TimerTest, StartRepeatingTask_ThenCancel) {
@@ -335,17 +342,19 @@ TEST_F(TimerTest, StartRepeatingTask_ThenCancel) {
&TimerTest::CountingTask);
timer.StartRepeating(TimeDelta::FromSeconds(1), FROM_HERE);
- double run_time;
+ TimeDelta run_time;
EXPECT_TRUE(TimeTillNextDelayedTask(&run_time));
- EXPECT_FLOAT_EQ(1.0, run_time);
+ EXPECT_EQ(TimeDelta::FromSeconds(1), run_time);
- RunUntilDeadline(start_time_ + 2.5);
- EXPECT_THAT(run_times_, ElementsAre(start_time_ + 1.0, start_time_ + 2.0));
+ RunUntilDeadline(start_time_ + TimeDelta::FromMilliseconds(2500));
+ EXPECT_THAT(run_times_, ElementsAre(start_time_ + TimeDelta::FromSeconds(1),
+ start_time_ + TimeDelta::FromSeconds(2)));
timer.Stop();
platform_->RunUntilIdle();
- EXPECT_THAT(run_times_, ElementsAre(start_time_ + 1.0, start_time_ + 2.0));
+ EXPECT_THAT(run_times_, ElementsAre(start_time_ + TimeDelta::FromSeconds(1),
+ start_time_ + TimeDelta::FromSeconds(2)));
}
TEST_F(TimerTest, StartRepeatingTask_ThenPostOneShot) {
@@ -354,18 +363,21 @@ TEST_F(TimerTest, StartRepeatingTask_ThenPostOneShot) {
&TimerTest::CountingTask);
timer.StartRepeating(TimeDelta::FromSeconds(1), FROM_HERE);
- double run_time;
+ TimeDelta run_time;
EXPECT_TRUE(TimeTillNextDelayedTask(&run_time));
- EXPECT_FLOAT_EQ(1.0, run_time);
+ EXPECT_EQ(TimeDelta::FromSeconds(1), run_time);
- RunUntilDeadline(start_time_ + 2.5);
- EXPECT_THAT(run_times_, ElementsAre(start_time_ + 1.0, start_time_ + 2.0));
+ RunUntilDeadline(start_time_ + TimeDelta::FromMilliseconds(2500));
+ EXPECT_THAT(run_times_, ElementsAre(start_time_ + TimeDelta::FromSeconds(1),
+ start_time_ + TimeDelta::FromSeconds(2)));
timer.StartOneShot(TimeDelta(), FROM_HERE);
platform_->RunUntilIdle();
- EXPECT_THAT(run_times_, ElementsAre(start_time_ + 1.0, start_time_ + 2.0,
- start_time_ + 2.5));
+ EXPECT_THAT(run_times_,
+ ElementsAre(start_time_ + TimeDelta::FromSeconds(1),
+ start_time_ + TimeDelta::FromSeconds(2),
+ start_time_ + TimeDelta::FromMilliseconds(2500)));
}
TEST_F(TimerTest, IsActive_NeverPosted) {
@@ -429,7 +441,7 @@ TEST_F(TimerTest, IsActive_AfterRunning_Repeating) {
&TimerTest::CountingTask);
timer.StartRepeating(TimeDelta::FromSeconds(1), FROM_HERE);
- RunUntilDeadline(start_time_ + 10);
+ RunUntilDeadline(start_time_ + TimeDelta::FromSeconds(10));
EXPECT_TRUE(timer.IsActive()); // It should run until cancelled.
}
@@ -439,7 +451,7 @@ TEST_F(TimerTest, NextFireInterval_OneShotZero) {
&TimerTest::CountingTask);
timer.StartOneShot(TimeDelta(), FROM_HERE);
- EXPECT_FLOAT_EQ(0.0, timer.NextFireInterval());
+ EXPECT_TRUE(timer.NextFireInterval().is_zero());
}
TEST_F(TimerTest, NextFireInterval_OneShotNonZero) {
@@ -448,7 +460,7 @@ TEST_F(TimerTest, NextFireInterval_OneShotNonZero) {
&TimerTest::CountingTask);
timer.StartOneShot(TimeDelta::FromSeconds(10), FROM_HERE);
- EXPECT_FLOAT_EQ(10.0, timer.NextFireInterval());
+ EXPECT_EQ(TimeDelta::FromSeconds(10), timer.NextFireInterval());
}
TEST_F(TimerTest, NextFireInterval_OneShotNonZero_AfterAFewSeconds) {
@@ -459,8 +471,8 @@ TEST_F(TimerTest, NextFireInterval_OneShotNonZero_AfterAFewSeconds) {
&TimerTest::CountingTask);
timer.StartOneShot(TimeDelta::FromSeconds(10), FROM_HERE);
- platform_->AdvanceClockSeconds(2.0);
- EXPECT_FLOAT_EQ(8.0, timer.NextFireInterval());
+ platform_->AdvanceClock(TimeDelta::FromSeconds(2));
+ EXPECT_EQ(TimeDelta::FromSeconds(8), timer.NextFireInterval());
}
TEST_F(TimerTest, NextFireInterval_Repeating) {
@@ -469,7 +481,7 @@ TEST_F(TimerTest, NextFireInterval_Repeating) {
&TimerTest::CountingTask);
timer.StartRepeating(TimeDelta::FromSeconds(20), FROM_HERE);
- EXPECT_FLOAT_EQ(20.0, timer.NextFireInterval());
+ EXPECT_EQ(TimeDelta::FromSeconds(20), timer.NextFireInterval());
}
TEST_F(TimerTest, RepeatInterval_NeverStarted) {
@@ -477,7 +489,7 @@ TEST_F(TimerTest, RepeatInterval_NeverStarted) {
platform_->GetMainThreadScheduler()->DefaultTaskRunner(), this,
&TimerTest::CountingTask);
- EXPECT_FLOAT_EQ(0.0, timer.RepeatInterval());
+ EXPECT_TRUE(timer.RepeatInterval().is_zero());
}
TEST_F(TimerTest, RepeatInterval_OneShotZero) {
@@ -486,7 +498,7 @@ TEST_F(TimerTest, RepeatInterval_OneShotZero) {
&TimerTest::CountingTask);
timer.StartOneShot(TimeDelta(), FROM_HERE);
- EXPECT_FLOAT_EQ(0.0, timer.RepeatInterval());
+ EXPECT_TRUE(timer.RepeatInterval().is_zero());
}
TEST_F(TimerTest, RepeatInterval_OneShotNonZero) {
@@ -495,7 +507,7 @@ TEST_F(TimerTest, RepeatInterval_OneShotNonZero) {
&TimerTest::CountingTask);
timer.StartOneShot(TimeDelta::FromSeconds(10), FROM_HERE);
- EXPECT_FLOAT_EQ(0.0, timer.RepeatInterval());
+ EXPECT_TRUE(timer.RepeatInterval().is_zero());
}
TEST_F(TimerTest, RepeatInterval_Repeating) {
@@ -504,7 +516,7 @@ TEST_F(TimerTest, RepeatInterval_Repeating) {
&TimerTest::CountingTask);
timer.StartRepeating(TimeDelta::FromSeconds(20), FROM_HERE);
- EXPECT_FLOAT_EQ(20.0, timer.RepeatInterval());
+ EXPECT_EQ(TimeDelta::FromSeconds(20), timer.RepeatInterval());
}
TEST_F(TimerTest, AugmentRepeatInterval) {
@@ -512,21 +524,19 @@ TEST_F(TimerTest, AugmentRepeatInterval) {
platform_->GetMainThreadScheduler()->DefaultTaskRunner(), this,
&TimerTest::CountingTask);
timer.StartRepeating(TimeDelta::FromSeconds(10), FROM_HERE);
- EXPECT_FLOAT_EQ(10.0, timer.RepeatInterval());
- EXPECT_FLOAT_EQ(10.0, timer.NextFireInterval());
+ EXPECT_EQ(TimeDelta::FromSeconds(10), timer.RepeatInterval());
+ EXPECT_EQ(TimeDelta::FromSeconds(10), timer.NextFireInterval());
- platform_->AdvanceClockSeconds(2.0);
- timer.AugmentRepeatInterval(10);
+ platform_->AdvanceClock(TimeDelta::FromSeconds(2));
+ timer.AugmentRepeatInterval(TimeDelta::FromSeconds(10));
- EXPECT_FLOAT_EQ(20.0, timer.RepeatInterval());
- EXPECT_FLOAT_EQ(18.0, timer.NextFireInterval());
+ EXPECT_EQ(TimeDelta::FromSeconds(20), timer.RepeatInterval());
+ EXPECT_EQ(TimeDelta::FromSeconds(18), timer.NextFireInterval());
- // NOTE setAutoAdvanceNowToPendingTasks(true) (which uses
- // cc::OrderedSimpleTaskRunner) results in somewhat strange behavior of the
- // test clock which breaks this test. Specifically the test clock advancing
- // logic ignores newly posted delayed tasks and advances too far.
- RunUntilDeadline(start_time_ + 50.0);
- EXPECT_THAT(run_times_, ElementsAre(start_time_ + 20.0, start_time_ + 40.0));
+ RunUntilDeadline(start_time_ + TimeDelta::FromSeconds(50));
+ EXPECT_THAT(run_times_,
+ ElementsAre(start_time_ + TimeDelta::FromSeconds(20),
+ start_time_ + TimeDelta::FromSeconds(40)));
}
TEST_F(TimerTest, AugmentRepeatInterval_TimerFireDelayed) {
@@ -536,15 +546,16 @@ TEST_F(TimerTest, AugmentRepeatInterval_TimerFireDelayed) {
platform_->GetMainThreadScheduler()->DefaultTaskRunner(), this,
&TimerTest::CountingTask);
timer.StartRepeating(TimeDelta::FromSeconds(10), FROM_HERE);
- EXPECT_FLOAT_EQ(10.0, timer.RepeatInterval());
- EXPECT_FLOAT_EQ(10.0, timer.NextFireInterval());
+ EXPECT_EQ(TimeDelta::FromSeconds(10), timer.RepeatInterval());
+ EXPECT_EQ(TimeDelta::FromSeconds(10), timer.NextFireInterval());
- platform_->AdvanceClockSeconds(123.0); // Make the timer long overdue.
- timer.AugmentRepeatInterval(10);
+ platform_->AdvanceClock(
+ TimeDelta::FromSeconds(123)); // Make the timer long overdue.
+ timer.AugmentRepeatInterval(TimeDelta::FromSeconds(10));
- EXPECT_FLOAT_EQ(20.0, timer.RepeatInterval());
+ EXPECT_EQ(TimeDelta::FromSeconds(20), timer.RepeatInterval());
// The timer is overdue so it should be scheduled to fire immediatly.
- EXPECT_FLOAT_EQ(0.0, timer.NextFireInterval());
+ EXPECT_TRUE(timer.NextFireInterval().is_zero());
}
TEST_F(TimerTest, RepeatingTimerDoesNotDrift) {
@@ -556,34 +567,38 @@ TEST_F(TimerTest, RepeatingTimerDoesNotDrift) {
timer.StartRepeating(TimeDelta::FromSeconds(2), FROM_HERE);
RecordNextFireTimeTask(
- &timer); // Next scheduled task to run at m_startTime + 2.0
+ &timer); // Next scheduled task to run at |start_time_| + 2s
// Simulate timer firing early. Next scheduled task to run at
- // m_startTime + 4.0
- platform_->AdvanceClockSeconds(1.9);
- RunUntilDeadline(CurrentTimeTicksInSeconds() + 0.2);
-
- // Next scheduled task to run at m_startTime + 6.0
- platform_->RunForPeriodSeconds(2.0);
- // Next scheduled task to run at m_startTime + 8.0
- platform_->RunForPeriodSeconds(2.1);
- // Next scheduled task to run at m_startTime + 10.0
- platform_->RunForPeriodSeconds(2.9);
- // Next scheduled task to run at m_startTime + 14.0 (skips a beat)
- platform_->AdvanceClockSeconds(3.1);
+ // |start_time_| + 4s
+ platform_->AdvanceClock(TimeDelta::FromMilliseconds(1900));
+ RunUntilDeadline(CurrentTimeTicks() + TimeDelta::FromMilliseconds(200));
+
+ // Next scheduled task to run at |start_time_| + 6s
+ platform_->RunForPeriod(TimeDelta::FromSeconds(2));
+ // Next scheduled task to run at |start_time_| + 8s
+ platform_->RunForPeriod(TimeDelta::FromMilliseconds(2100));
+ // Next scheduled task to run at |start_time_| + 10s
+ platform_->RunForPeriod(TimeDelta::FromMilliseconds(2900));
+ // Next scheduled task to run at |start_time_| + 14s (skips a beat)
+ platform_->AdvanceClock(TimeDelta::FromMilliseconds(3100));
platform_->RunUntilIdle();
- // Next scheduled task to run at m_startTime + 18.0 (skips a beat)
- platform_->AdvanceClockSeconds(4.0);
+ // Next scheduled task to run at |start_time_| + 18s (skips a beat)
+ platform_->AdvanceClock(TimeDelta::FromSeconds(4));
platform_->RunUntilIdle();
- // Next scheduled task to run at m_startTime + 28.0 (skips 5 beats)
- platform_->AdvanceClockSeconds(10.0);
+ // Next scheduled task to run at |start_time_| + 28s (skips 5 beats)
+ platform_->AdvanceClock(TimeDelta::FromSeconds(10));
platform_->RunUntilIdle();
- EXPECT_THAT(
- next_fire_times_,
- ElementsAre(start_time_ + 2.0, start_time_ + 4.0, start_time_ + 6.0,
- start_time_ + 8.0, start_time_ + 10.0, start_time_ + 14.0,
- start_time_ + 18.0, start_time_ + 28.0));
+ EXPECT_THAT(next_fire_times_,
+ ElementsAre(start_time_ + TimeDelta::FromSeconds(2),
+ start_time_ + TimeDelta::FromSeconds(4),
+ start_time_ + TimeDelta::FromSeconds(6),
+ start_time_ + TimeDelta::FromSeconds(8),
+ start_time_ + TimeDelta::FromSeconds(10),
+ start_time_ + TimeDelta::FromSeconds(14),
+ start_time_ + TimeDelta::FromSeconds(18),
+ start_time_ + TimeDelta::FromSeconds(28)));
}
template <typename TimerFiredClass>
@@ -643,7 +658,7 @@ TEST_F(TimerTest, DestructOnHeapTimer) {
owner = nullptr;
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kEagerSweeping, BlinkGC::kForcedGC);
+ BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
EXPECT_TRUE(record->OwnerIsDestructed());
EXPECT_FALSE(record->TimerHasFired());
@@ -663,7 +678,7 @@ TEST_F(TimerTest, MarkOnHeapTimerAsUnreachable) {
owner = nullptr;
ThreadState::Current()->CollectGarbage(
BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
- BlinkGC::kLazySweeping, BlinkGC::kForcedGC);
+ BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGC);
EXPECT_FALSE(record->OwnerIsDestructed());
{
@@ -723,17 +738,17 @@ TEST_F(TimerTest, MoveToNewTaskRunnerOneShot) {
TimerForTest<TimerTest> timer(task_queue_with_task_type1, this,
&TimerTest::CountingTask);
- double start_time = CurrentTimeTicksInSeconds();
+ TimeTicks start_time = CurrentTimeTicks();
timer.StartOneShot(TimeDelta::FromSeconds(1), FROM_HERE);
- platform_->RunForPeriodSeconds(0.5);
+ platform_->RunForPeriod(TimeDelta::FromMilliseconds(500));
timer.MoveToNewTaskRunner(task_queue_with_task_type2);
platform_->RunUntilIdle();
- EXPECT_THAT(run_times_, ElementsAre(start_time + 1.0));
+ EXPECT_THAT(run_times_, ElementsAre(start_time + TimeDelta::FromSeconds(1)));
EXPECT_THAT(run_order, ElementsAre(task_queue_with_task_type2));
@@ -767,18 +782,20 @@ TEST_F(TimerTest, MoveToNewTaskRunnerRepeating) {
TimerForTest<TimerTest> timer(task_queue_with_task_type1, this,
&TimerTest::CountingTask);
- double start_time = CurrentTimeTicksInSeconds();
+ TimeTicks start_time = CurrentTimeTicks();
timer.StartRepeating(TimeDelta::FromSeconds(1), FROM_HERE);
- platform_->RunForPeriodSeconds(2.5);
+ platform_->RunForPeriod(TimeDelta::FromMilliseconds(2500));
timer.MoveToNewTaskRunner(task_queue_with_task_type2);
- platform_->RunForPeriodSeconds(2);
+ platform_->RunForPeriod(TimeDelta::FromSeconds(2));
- EXPECT_THAT(run_times_, ElementsAre(start_time + 1.0, start_time + 2.0,
- start_time + 3.0, start_time + 4.0));
+ EXPECT_THAT(run_times_, ElementsAre(start_time + TimeDelta::FromSeconds(1),
+ start_time + TimeDelta::FromSeconds(2),
+ start_time + TimeDelta::FromSeconds(3),
+ start_time + TimeDelta::FromSeconds(4)));
EXPECT_THAT(
run_order,
diff --git a/chromium/third_party/blink/renderer/platform/transforms/transformation_matrix.cc b/chromium/third_party/blink/renderer/platform/transforms/transformation_matrix.cc
index 69ff1646412..23ded0ee68d 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/transformation_matrix.cc
+++ b/chromium/third_party/blink/renderer/platform/transforms/transformation_matrix.cc
@@ -78,8 +78,6 @@ namespace blink {
typedef double Vector4[4];
typedef double Vector3[3];
-const double kSmallNumber = 1.e-8;
-
// inverse(original_matrix, inverse_matrix)
//
// calculate the inverse of a 4x4 matrix
@@ -225,7 +223,7 @@ static bool Inverse(const TransformationMatrix::Matrix4& matrix,
// then the inverse matrix is not unique.
double det = Determinant4x4(matrix);
- if (fabs(det) < kSmallNumber)
+ if (det == 0)
return false;
#if defined(ARCH_CPU_ARM64)
@@ -1651,15 +1649,7 @@ void TransformationMatrix::MultVecMatrix(double x,
}
bool TransformationMatrix::IsInvertible() const {
- if (IsIdentityOrTranslation())
- return true;
-
- double det = blink::Determinant4x4(matrix_);
-
- if (fabs(det) < kSmallNumber)
- return false;
-
- return true;
+ return IsIdentityOrTranslation() || blink::Determinant4x4(matrix_) != 0;
}
TransformationMatrix TransformationMatrix::Inverse() const {
diff --git a/chromium/third_party/blink/renderer/platform/transforms/transformation_matrix.h b/chromium/third_party/blink/renderer/platform/transforms/transformation_matrix.h
index 763d2b17bdb..9e61366a9b4 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/transformation_matrix.h
+++ b/chromium/third_party/blink/renderer/platform/transforms/transformation_matrix.h
@@ -461,6 +461,15 @@ class PLATFORM_EXPORT TransformationMatrix {
return IsIdentityOrTranslation() && matrix_[3][2] == 0;
}
+ bool Is2DProportionalUpscaleAndOr2DTranslation() const {
+ if (matrix_[0][0] < 1 || matrix_[0][0] != matrix_[1][1])
+ return false;
+ return matrix_[0][1] == 0 && matrix_[0][2] == 0 && matrix_[0][3] == 0 &&
+ matrix_[1][0] == 0 && matrix_[1][2] == 0 && matrix_[1][3] == 0 &&
+ matrix_[2][0] == 0 && matrix_[2][1] == 0 && matrix_[2][2] == 1 &&
+ matrix_[2][3] == 0 && matrix_[3][2] == 0 && matrix_[3][3] == 1;
+ }
+
bool IsIntegerTranslation() const;
// If this transformation is identity or 2D translation, returns the
diff --git a/chromium/third_party/blink/renderer/platform/transforms/transformation_matrix_test.cc b/chromium/third_party/blink/renderer/platform/transforms/transformation_matrix_test.cc
index 698aeb9ce50..359c6966382 100644
--- a/chromium/third_party/blink/renderer/platform/transforms/transformation_matrix_test.cc
+++ b/chromium/third_party/blink/renderer/platform/transforms/transformation_matrix_test.cc
@@ -49,6 +49,40 @@ TEST(TransformationMatrixTest, IsIdentityOr2DTranslation) {
EXPECT_FALSE(matrix.IsIdentityOr2DTranslation());
}
+TEST(TransformationMatrixTest, Is2DProportionalUpscaleAndOr2DTranslation) {
+ TransformationMatrix matrix;
+ EXPECT_TRUE(matrix.Is2DProportionalUpscaleAndOr2DTranslation());
+
+ matrix.MakeIdentity();
+ matrix.Translate(10, 0);
+ EXPECT_TRUE(matrix.Is2DProportionalUpscaleAndOr2DTranslation());
+
+ matrix.MakeIdentity();
+ matrix.Scale(1.3);
+ EXPECT_TRUE(matrix.Is2DProportionalUpscaleAndOr2DTranslation());
+
+ matrix.MakeIdentity();
+ matrix.Translate(0, -20);
+ matrix.Scale(1.7);
+ EXPECT_TRUE(matrix.Is2DProportionalUpscaleAndOr2DTranslation());
+
+ matrix.MakeIdentity();
+ matrix.Scale(0.99);
+ EXPECT_FALSE(matrix.Is2DProportionalUpscaleAndOr2DTranslation());
+
+ matrix.MakeIdentity();
+ matrix.Translate3d(0, 0, 1);
+ EXPECT_FALSE(matrix.Is2DProportionalUpscaleAndOr2DTranslation());
+
+ matrix.MakeIdentity();
+ matrix.Rotate(40 /* degrees */);
+ EXPECT_FALSE(matrix.Is2DProportionalUpscaleAndOr2DTranslation());
+
+ matrix.MakeIdentity();
+ matrix.SkewX(30 /* degrees */);
+ EXPECT_FALSE(matrix.Is2DProportionalUpscaleAndOr2DTranslation());
+}
+
TEST(TransformationMatrixTest, To2DTranslation) {
TransformationMatrix matrix;
EXPECT_EQ(FloatSize(), matrix.To2DTranslation());
@@ -285,4 +319,15 @@ TEST(TransformationMatrixTest, ToString) {
column_major_constructor.ToString(true));
}
+TEST(TransformationMatrix, IsInvertible) {
+ EXPECT_FALSE(
+ TransformationMatrix(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
+ .IsInvertible());
+ EXPECT_TRUE(TransformationMatrix().IsInvertible());
+ EXPECT_TRUE(TransformationMatrix().Translate3d(10, 20, 30).IsInvertible());
+ EXPECT_TRUE(TransformationMatrix().Scale(1e-8).IsInvertible());
+ EXPECT_TRUE(TransformationMatrix().Scale3d(1e-8, -1e-8, 1).IsInvertible());
+ EXPECT_FALSE(TransformationMatrix().Scale(0).IsInvertible());
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/ukm_time_aggregator.cc b/chromium/third_party/blink/renderer/platform/ukm_time_aggregator.cc
index c537a94d38c..9a4dd175c6a 100644
--- a/chromium/third_party/blink/renderer/platform/ukm_time_aggregator.cc
+++ b/chromium/third_party/blink/renderer/platform/ukm_time_aggregator.cc
@@ -76,7 +76,7 @@ void UkmTimeAggregator::RecordSample(size_t metric_index,
// Record the UMA if we have a counter.
TimeDelta duration = end - start;
if (histogram_counter)
- histogram_counter->Count(duration.InMicroseconds());
+ histogram_counter->CountMicroseconds(duration);
// Append the duration to the appropriate metrics record.
DCHECK_LT(metric_index, metric_records_.size());
diff --git a/chromium/third_party/blink/renderer/platform/ukm_time_aggregator_test.cc b/chromium/third_party/blink/renderer/platform/ukm_time_aggregator_test.cc
index d2c8e2a5d8c..c6f7f450095 100644
--- a/chromium/third_party/blink/renderer/platform/ukm_time_aggregator_test.cc
+++ b/chromium/third_party/blink/renderer/platform/ukm_time_aggregator_test.cc
@@ -6,6 +6,7 @@
#include "components/ukm/test_ukm_recorder.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/testing/wtf/scoped_mock_clock.h"
namespace blink {
namespace {
@@ -19,34 +20,22 @@ const char* kMetric2 = "Paint";
const char* kMetric2Average = "Paint.Average";
const char* kMetric2WorstCase = "Paint.WorstCase";
-struct Timer {
- static double GetTime() { return fake_time; }
- static double fake_time;
-};
-
-double Timer::fake_time = 0;
-
TEST(UkmTimeAggregatorTest, EmptyEventsNotRecorded) {
- Timer::fake_time = 0;
- auto original_time_function = SetTimeFunctionsForTesting(&Timer::GetTime);
-
+ WTF::ScopedMockClock clock;
ukm::TestUkmRecorder recorder;
int64_t source_id = ukm::UkmRecorder::GetNewSourceID();
std::unique_ptr<UkmTimeAggregator> aggregator(
new UkmTimeAggregator(kEvent, source_id, &recorder, {kMetric1, kMetric2},
TimeDelta::FromSeconds(1)));
- Timer::fake_time += 10.;
+ clock.Advance(TimeDelta::FromSeconds(10));
aggregator.reset();
EXPECT_EQ(recorder.sources_count(), 0u);
EXPECT_EQ(recorder.entries_count(), 0u);
- SetTimeFunctionsForTesting(original_time_function);
}
TEST(UkmTimeAggregatorTest, EventsRecordedPerSecond) {
- Timer::fake_time = 0;
- auto original_time_function = SetTimeFunctionsForTesting(&Timer::GetTime);
-
+ WTF::ScopedMockClock clock;
ukm::TestUkmRecorder recorder;
int64_t source_id = ukm::UkmRecorder::GetNewSourceID();
std::unique_ptr<UkmTimeAggregator> aggregator(
@@ -57,7 +46,7 @@ TEST(UkmTimeAggregatorTest, EventsRecordedPerSecond) {
// ..., 8-9 seconds.
for (int i = 0; i < 100; ++i) {
auto timer = aggregator->GetScopedTimer(i % 2);
- Timer::fake_time += 0.099;
+ clock.Advance(TimeDelta::FromMilliseconds(99));
}
EXPECT_EQ(recorder.entries_count(), 9u);
@@ -91,14 +80,10 @@ TEST(UkmTimeAggregatorTest, EventsRecordedPerSecond) {
ukm::TestUkmRecorder::GetEntryMetric(entry, kMetric2WorstCase);
EXPECT_NEAR(*metric2_worst / 1e6, 0.099, 0.0001);
}
-
- SetTimeFunctionsForTesting(original_time_function);
}
TEST(UkmTimeAggregatorTest, EventsAveragedCorrectly) {
- Timer::fake_time = 0;
- auto original_time_function = SetTimeFunctionsForTesting(&Timer::GetTime);
-
+ WTF::ScopedMockClock clock;
ukm::TestUkmRecorder recorder;
int64_t source_id = ukm::UkmRecorder::GetNewSourceID();
std::unique_ptr<UkmTimeAggregator> aggregator(
@@ -107,17 +92,17 @@ TEST(UkmTimeAggregatorTest, EventsAveragedCorrectly) {
// 1, 2, and 3 seconds.
for (int i = 1; i <= 3; ++i) {
auto timer = aggregator->GetScopedTimer(0);
- Timer::fake_time += i;
+ clock.Advance(TimeDelta::FromSeconds(i));
}
// 3, 3, 3, and then 1 outside of the loop.
for (int i = 0; i < 3; ++i) {
auto timer = aggregator->GetScopedTimer(1);
- Timer::fake_time += 3.;
+ clock.Advance(TimeDelta::FromSeconds(3));
}
{
auto timer = aggregator->GetScopedTimer(1);
- Timer::fake_time += 1.;
+ clock.Advance(TimeDelta::FromSeconds(1));
}
aggregator.reset();
@@ -148,8 +133,6 @@ TEST(UkmTimeAggregatorTest, EventsAveragedCorrectly) {
ukm::TestUkmRecorder::GetEntryMetric(entry, kMetric2WorstCase);
// metric1 (3, 3, 3, 1) worst case is 3
EXPECT_NEAR(*metric2_worst / 1e6, 3.0, 0.0001);
-
- SetTimeFunctionsForTesting(original_time_function);
}
} // namespace
diff --git a/chromium/third_party/blink/renderer/platform/web_gesture_event.cc b/chromium/third_party/blink/renderer/platform/web_gesture_event.cc
index e8900f6e405..305bc488f07 100644
--- a/chromium/third_party/blink/renderer/platform/web_gesture_event.cc
+++ b/chromium/third_party/blink/renderer/platform/web_gesture_event.cc
@@ -29,11 +29,6 @@ WebGestureEvent::ScrollUnits WebGestureEvent::DeltaUnits() const {
return data.scroll_end.delta_units;
}
-float WebGestureEvent::PinchScale() const {
- DCHECK(type_ == WebInputEvent::kGesturePinchUpdate);
- return data.pinch_update.scale;
-}
-
WebGestureEvent::InertialPhaseState WebGestureEvent::InertialPhase() const {
if (type_ == WebInputEvent::kGestureScrollBegin)
return data.scroll_begin.inertial_phase;
diff --git a/chromium/third_party/blink/renderer/platform/web_task_runner.cc b/chromium/third_party/blink/renderer/platform/web_task_runner.cc
index 3ae21f300a3..818c8870194 100644
--- a/chromium/third_party/blink/renderer/platform/web_task_runner.cc
+++ b/chromium/third_party/blink/renderer/platform/web_task_runner.cc
@@ -7,26 +7,6 @@
#include "base/bind_helpers.h"
#include "base/single_thread_task_runner.h"
-namespace base {
-
-using RunnerMethodType =
- void (blink::TaskHandle::Runner::*)(const blink::TaskHandle&);
-
-template <>
-struct CallbackCancellationTraits<
- RunnerMethodType,
- std::tuple<base::WeakPtr<blink::TaskHandle::Runner>, blink::TaskHandle>> {
- static constexpr bool is_cancellable = true;
-
- static bool IsCancelled(RunnerMethodType,
- const base::WeakPtr<blink::TaskHandle::Runner>&,
- const blink::TaskHandle& handle) {
- return !handle.IsActive();
- }
-};
-
-} // namespace base
-
namespace blink {
namespace {
@@ -82,6 +62,30 @@ class TaskHandle::Runner : public WTF::ThreadSafeRefCounted<Runner> {
DISALLOW_COPY_AND_ASSIGN(Runner);
};
+} // namespace blink
+
+namespace base {
+
+using RunnerMethodType =
+ void (blink::TaskHandle::Runner::*)(const blink::TaskHandle&);
+
+template <>
+struct CallbackCancellationTraits<
+ RunnerMethodType,
+ std::tuple<base::WeakPtr<blink::TaskHandle::Runner>, blink::TaskHandle>> {
+ static constexpr bool is_cancellable = true;
+
+ static bool IsCancelled(RunnerMethodType,
+ const base::WeakPtr<blink::TaskHandle::Runner>&,
+ const blink::TaskHandle& handle) {
+ return !handle.IsActive();
+ }
+};
+
+} // namespace base
+
+namespace blink {
+
bool TaskHandle::IsActive() const {
return runner_ && runner_->IsActive();
}
diff --git a/chromium/third_party/blink/renderer/platform/web_thread.cc b/chromium/third_party/blink/renderer/platform/web_thread.cc
index 5d100e61e50..7f244c70ed1 100644
--- a/chromium/third_party/blink/renderer/platform/web_thread.cc
+++ b/chromium/third_party/blink/renderer/platform/web_thread.cc
@@ -19,7 +19,7 @@ namespace blink {
WebThreadCreationParams::WebThreadCreationParams(WebThreadType thread_type)
: thread_type(thread_type),
name(GetNameForThreadType(thread_type)),
- frame_scheduler(nullptr) {}
+ frame_or_worker_scheduler(nullptr) {}
WebThreadCreationParams& WebThreadCreationParams::SetThreadNameForTest(
const char* thread_name) {
@@ -27,9 +27,9 @@ WebThreadCreationParams& WebThreadCreationParams::SetThreadNameForTest(
return *this;
}
-WebThreadCreationParams& WebThreadCreationParams::SetFrameScheduler(
- FrameScheduler* scheduler) {
- frame_scheduler = scheduler;
+WebThreadCreationParams& WebThreadCreationParams::SetFrameOrWorkerScheduler(
+ FrameOrWorkerScheduler* scheduler) {
+ frame_or_worker_scheduler = scheduler;
return *this;
}
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/kurl.cc b/chromium/third_party/blink/renderer/platform/weborigin/kurl.cc
index 09d31ec610b..4afb31a31b6 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/kurl.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/kurl.cc
@@ -45,9 +45,6 @@
namespace blink {
-static const int kMaximumValidPortNumber = 0xFFFE;
-static const int kInvalidPortNumber = 0xFFFF;
-
#if DCHECK_IS_ON()
static void AssertProtocolIsGood(const StringView protocol) {
DCHECK(protocol != "");
@@ -215,12 +212,18 @@ KURL::KURL(const String& url) {
else {
// WebCore expects us to preserve the nullness of strings when this
// constructor is used. In all other cases, it expects a non-null
- // empty string, which is what init() will create.
+ // empty string, which is what Init() will create.
is_valid_ = false;
protocol_is_in_http_family_ = false;
}
}
+// Initializes with a GURL. This is used to covert from a GURL to a KURL.
+KURL::KURL(const GURL& gurl) {
+ Init(NullURL() /* base */, String(gurl.spec().c_str()) /* relative */,
+ nullptr /* query_encoding */);
+}
+
KURL KURL::CreateIsolated(const String& url) {
// FIXME: We should be able to skip this extra copy and created an
// isolated KURL more efficiently.
@@ -353,12 +356,6 @@ String KURL::Host() const {
return ComponentString(parsed_.host);
}
-// Returns 0 when there is no port.
-//
-// We treat URL's with out-of-range port numbers as invalid URLs, and they will
-// be rejected by the canonicalizer. KURL.cpp will allow them in parsing, but
-// return invalidPortNumber from this port() function, so we mirror that
-// behavior here.
unsigned short KURL::Port() const {
if (!is_valid_ || parsed_.port.len <= 0)
return 0;
@@ -366,11 +363,8 @@ unsigned short KURL::Port() const {
int port = string_.Is8Bit()
? url::ParsePort(AsURLChar8Subtle(string_), parsed_.port)
: url::ParsePort(string_.Characters16(), parsed_.port);
- DCHECK_NE(port, url::PORT_UNSPECIFIED); // Checked port.len <= 0 before.
-
- if (port == url::PORT_INVALID ||
- port > kMaximumValidPortNumber) // Mimic KURL::port()
- port = kInvalidPortNumber;
+ DCHECK_NE(port, url::PORT_UNSPECIFIED); // Checked port.len <= 0 already.
+ DCHECK_NE(port, url::PORT_INVALID); // Checked is_valid_ already.
return static_cast<unsigned short>(port);
}
@@ -647,7 +641,7 @@ String EncodeWithURLEscapeSequences(const String& not_encoded_string) {
buffer.Resize(input_length * 3);
url::EncodeURIComponent(utf8.data(), input_length, &buffer);
- String escaped(buffer.data(), buffer.length());
+ String escaped(buffer.data(), static_cast<unsigned>(buffer.length()));
// Unescape '/'; it's safe and much prettier.
escaped.Replace("%2F", "/");
return escaped;
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/kurl.h b/chromium/third_party/blink/renderer/platform/weborigin/kurl.h
index 67a5e9df177..e3251f376a6 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/kurl.h
+++ b/chromium/third_party/blink/renderer/platform/weborigin/kurl.h
@@ -78,6 +78,11 @@ class PLATFORM_EXPORT KURL {
KURL();
KURL(const KURL&);
+
+ // This should only be used to convert a GURL returned from a layer which
+ // operates in the base terms (e.g. from common/* code).
+ explicit KURL(const GURL&);
+
KURL& operator=(const KURL&);
// The argument is an absolute URL string. The string is assumed to be
@@ -142,6 +147,12 @@ class PLATFORM_EXPORT KURL {
String Protocol() const;
String Host() const;
+
+ // Returns 0 when there is no port or the default port was specified, or the
+ // URL is invalid.
+ //
+ // We treat URLs with out-of-range port numbers as invalid URLs, and they
+ // will be rejected by the canonicalizer.
unsigned short Port() const;
bool HasPort() const;
String User() const;
@@ -218,6 +229,7 @@ class PLATFORM_EXPORT KURL {
// Returns a GURL with the same properties. This can be used in platform/ and
// web/. However, in core/ and modules/, this should only be used to pass
// a GURL to a layer that is expecting one instead of a KURL or a WebURL.
+ // TODO(crbug.com/862940): Make this conversion explicit.
operator GURL() const;
private:
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/kurl_test.cc b/chromium/third_party/blink/renderer/platform/weborigin/kurl_test.cc
index 76ef9117e81..bafdb256be9 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/kurl_test.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/kurl_test.cc
@@ -33,6 +33,8 @@
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include <stdint.h>
+
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/cstring.h"
@@ -279,7 +281,7 @@ TEST(KURLTest, EncodeWithURLEscapeSequences) {
}
// Our encode escapes NULLs for safety, so we need to check that too.
- String input("\x00\x01", 2);
+ String input("\x00\x01", 2u);
String reference("%00%01");
String output = EncodeWithURLEscapeSequences(input);
@@ -837,4 +839,120 @@ TEST(KURLTest, strippedForUseAsReferrer) {
}
}
+enum class PortIsValid {
+ // The constructor does strict checking. Ports which are considered valid by
+ // the constructor are kAlways valid.
+ kAlways,
+
+ // SetHostAndPort() truncates to the initial numerical prefix, and then does
+ // strict checking. kInSetHostAndPort is used for ports which are considered
+ // valid by SetHostAndPort() but not by the constructor. In this case, the
+ // expected value is the same as for SetPort().
+ kInSetHostAndPort,
+
+ // SetPort() considers all input valid.
+ kInSetPort
+};
+
+struct PortTestCase {
+ const char* input;
+ const uint16_t constructor_output;
+ const uint16_t set_port_output;
+ const PortIsValid is_valid;
+};
+
+// The tested behaviour matches the implementation. It doesn't necessarily match
+// the URL Standard.
+const PortTestCase port_test_cases[] = {
+ {"80", 0, 0, PortIsValid::kAlways}, // 0 because scheme is http.
+ {"443", 443, 443, PortIsValid::kAlways},
+ {"8000", 8000, 8000, PortIsValid::kAlways},
+ {"0", 0, 0, PortIsValid::kAlways},
+ {"1", 1, 1, PortIsValid::kAlways},
+ {"00000000000000000000000000000000000443", 443, 443, PortIsValid::kAlways},
+ {"+80", 0, 0, PortIsValid::kInSetHostAndPort},
+ {"-80", 0, 0, PortIsValid::kInSetHostAndPort},
+ {"443e0", 0, 443, PortIsValid::kInSetHostAndPort},
+ {"0x80", 0, 0, PortIsValid::kInSetHostAndPort},
+ {"8%30", 0, 8, PortIsValid::kInSetHostAndPort},
+ {" 443", 0, 0, PortIsValid::kInSetHostAndPort},
+ {"443 ", 0, 443, PortIsValid::kInSetHostAndPort},
+ {":443", 0, 0, PortIsValid::kInSetHostAndPort},
+ {"65535", 65535, 65535, PortIsValid::kAlways},
+ {"65534", 65534, 65534, PortIsValid::kAlways},
+ {"65536", 0, 0, PortIsValid::kInSetPort},
+ {"65537", 0, 1, PortIsValid::kInSetPort},
+ {"2147483647", 0, 65535, PortIsValid::kInSetPort},
+ {"2147483648", 0, 0, PortIsValid::kInSetPort},
+ {"2147483649", 0, 1, PortIsValid::kInSetPort},
+ {"4294967295", 0, 65535, PortIsValid::kInSetPort},
+ {"4294967296", 0, 0, PortIsValid::kInSetPort},
+ {"4294967297", 0, 0, PortIsValid::kInSetPort},
+ {"18446744073709551615", 0, 0, PortIsValid::kInSetPort},
+ {"18446744073709551616", 0, 0, PortIsValid::kInSetPort},
+ {"18446744073709551617", 0, 0, PortIsValid::kInSetPort},
+ {"9999999999999999999999999999990999999999", 0, 0, PortIsValid::kInSetPort},
+};
+
+void PrintTo(const PortTestCase& port_test_case, ::std::ostream* os) {
+ *os << '"' << port_test_case.input << '"';
+}
+
+class KURLPortTest : public ::testing::TestWithParam<PortTestCase> {};
+
+TEST_P(KURLPortTest, Construct) {
+ const auto& param = GetParam();
+ const KURL url(String("http://a:") + param.input + "/");
+ EXPECT_EQ(url.Port(), param.constructor_output);
+ if (param.is_valid == PortIsValid::kAlways) {
+ EXPECT_EQ(url.IsValid(), true);
+ } else {
+ EXPECT_EQ(url.IsValid(), false);
+ }
+}
+
+TEST_P(KURLPortTest, ConstructRelative) {
+ const auto& param = GetParam();
+ const KURL base("http://a/");
+ const KURL url(base, String("//a:") + param.input + "/");
+ EXPECT_EQ(url.Port(), param.constructor_output);
+ if (param.is_valid == PortIsValid::kAlways) {
+ EXPECT_EQ(url.IsValid(), true);
+ } else {
+ EXPECT_EQ(url.IsValid(), false);
+ }
+}
+
+TEST_P(KURLPortTest, SetPort) {
+ const auto& param = GetParam();
+ KURL url("http://a:8888/");
+ url.SetPort(param.input);
+ EXPECT_EQ(url.Port(), param.set_port_output);
+ EXPECT_EQ(url.IsValid(), true);
+}
+
+TEST_P(KURLPortTest, SetHostAndPort) {
+ const auto& param = GetParam();
+ KURL url("http://a:8888/");
+ url.SetHostAndPort(String("a:") + param.input);
+ switch (param.is_valid) {
+ case PortIsValid::kAlways:
+ EXPECT_EQ(url.Port(), param.constructor_output);
+ EXPECT_EQ(url.IsValid(), true);
+ break;
+
+ case PortIsValid::kInSetHostAndPort:
+ EXPECT_EQ(url.Port(), param.set_port_output);
+ EXPECT_EQ(url.IsValid(), true);
+ break;
+
+ case PortIsValid::kInSetPort:
+ EXPECT_EQ(url.Port(), param.constructor_output);
+ EXPECT_EQ(url.IsValid(), false);
+ break;
+ }
+}
+
+INSTANTIATE_TEST_CASE_P(, KURLPortTest, ::testing::ValuesIn(port_test_cases));
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry.cc b/chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry.cc
index d6c49e216d1..37220fd5888 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry.cc
@@ -30,10 +30,11 @@
#include "third_party/blink/renderer/platform/weborigin/origin_access_entry.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/web_public_suffix_list.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
#include "url/third_party/mozilla/url_parse.h"
#include "url/url_canon.h"
@@ -90,11 +91,16 @@ OriginAccessEntry::OriginAccessEntry(const String& protocol,
// Look for top-level domains, either with or without an additional dot.
if (!host_is_ip_address_) {
- WebPublicSuffixList* suffix_list = Platform::Current()->PublicSuffixList();
- if (!suffix_list)
- return;
+ // Blink passes some things that aren't technically hosts like "*.foo", so
+ // use the permissive variant.
+ size_t public_suffix_length =
+ net::registry_controlled_domains::PermissiveGetHostRegistryLength(
+ StringUTF8Adaptor(host_).AsStringPiece(),
+ net::registry_controlled_domains::INCLUDE_UNKNOWN_REGISTRIES,
+ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+ if (public_suffix_length == 0)
+ public_suffix_length = host_.length();
- size_t public_suffix_length = suffix_list->GetPublicSuffixLength(host_);
if (host_.length() <= public_suffix_length + 1) {
host_is_public_suffix_ = true;
} else if (subdomain_setting == kAllowRegisterableDomains &&
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry_test.cc b/chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry_test.cc
index e8ee05e2006..9bfe18073ed 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry_test.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/origin_access_entry_test.cc
@@ -32,45 +32,13 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/platform.h"
-#include "third_party/blink/public/platform/web_public_suffix_list.h"
#include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
namespace blink {
-class OriginAccessEntryTestSuffixList : public blink::WebPublicSuffixList {
- public:
- size_t GetPublicSuffixLength(const blink::WebString&) override {
- return length_;
- }
-
- void SetPublicSuffix(const blink::WebString& suffix) {
- length_ = suffix.length();
- }
-
- private:
- size_t length_;
-};
-
-class OriginAccessEntryTestPlatform : public TestingPlatformSupport {
- public:
- blink::WebPublicSuffixList* PublicSuffixList() override {
- return &suffix_list_;
- }
-
- void SetPublicSuffix(const blink::WebString& suffix) {
- suffix_list_.SetPublicSuffix(suffix);
- }
-
- private:
- OriginAccessEntryTestSuffixList suffix_list_;
-};
-
TEST(OriginAccessEntryTest, PublicSuffixListTest) {
- ScopedTestingPlatformSupport<OriginAccessEntryTestPlatform> platform;
- platform->SetPublicSuffix("com");
-
scoped_refptr<const SecurityOrigin> origin =
SecurityOrigin::CreateFromString("http://www.google.com");
OriginAccessEntry entry1("http", "google.com",
@@ -139,9 +107,6 @@ TEST(OriginAccessEntryTest, AllowSubdomainsTest) {
OriginAccessEntry::kMatchesOrigin},
};
- ScopedTestingPlatformSupport<OriginAccessEntryTestPlatform> platform;
- platform->SetPublicSuffix("com");
-
for (const auto& test : inputs) {
SCOPED_TRACE(testing::Message()
<< "Host: " << test.host << ", Origin: " << test.origin);
@@ -193,9 +158,6 @@ TEST(OriginAccessEntryTest, AllowRegisterableDomainsTest) {
OriginAccessEntry::kDoesNotMatchOrigin},
};
- ScopedTestingPlatformSupport<OriginAccessEntryTestPlatform> platform;
- platform->SetPublicSuffix("com");
-
for (const auto& test : inputs) {
scoped_refptr<const SecurityOrigin> origin_to_test =
SecurityOrigin::CreateFromString(test.origin);
@@ -249,9 +211,6 @@ TEST(OriginAccessEntryTest, AllowRegisterableDomainsTestWithDottedSuffix) {
OriginAccessEntry::kDoesNotMatchOrigin},
};
- ScopedTestingPlatformSupport<OriginAccessEntryTestPlatform> platform;
- platform->SetPublicSuffix("appspot.com");
-
for (const auto& test : inputs) {
scoped_refptr<const SecurityOrigin> origin_to_test =
SecurityOrigin::CreateFromString(test.origin);
@@ -300,9 +259,6 @@ TEST(OriginAccessEntryTest, DisallowSubdomainsTest) {
OriginAccessEntry::kDoesNotMatchOrigin},
};
- ScopedTestingPlatformSupport<OriginAccessEntryTestPlatform> platform;
- platform->SetPublicSuffix("com");
-
for (const auto& test : inputs) {
SCOPED_TRACE(testing::Message()
<< "Host: " << test.host << ", Origin: " << test.origin);
@@ -331,9 +287,6 @@ TEST(OriginAccessEntryTest, IPAddressTest) {
{"http", "", false},
};
- ScopedTestingPlatformSupport<OriginAccessEntryTestPlatform> platform;
- platform->SetPublicSuffix("com");
-
for (const auto& test : inputs) {
SCOPED_TRACE(testing::Message() << "Host: " << test.host);
OriginAccessEntry entry(test.protocol, test.host,
@@ -359,9 +312,6 @@ TEST(OriginAccessEntryTest, IPAddressMatchingTest) {
OriginAccessEntry::kDoesNotMatchOrigin},
};
- ScopedTestingPlatformSupport<OriginAccessEntryTestPlatform> platform;
- platform->SetPublicSuffix("com");
-
for (const auto& test : inputs) {
SCOPED_TRACE(testing::Message()
<< "Host: " << test.host << ", Origin: " << test.origin);
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/referrer_policy.h b/chromium/third_party/blink/renderer/platform/weborigin/referrer_policy.h
index e8f6662721d..e9ddd2f8366 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/referrer_policy.h
+++ b/chromium/third_party/blink/renderer/platform/weborigin/referrer_policy.h
@@ -32,6 +32,8 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBORIGIN_REFERRER_POLICY_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WEBORIGIN_REFERRER_POLICY_H_
+#include <stdint.h>
+
namespace blink {
enum ReferrerPolicy : uint8_t {
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/security_origin.cc b/chromium/third_party/blink/renderer/platform/weborigin/security_origin.cc
index 8213041d59f..2a11de1e2c6 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/security_origin.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/security_origin.cc
@@ -44,6 +44,7 @@
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
#include "url/url_canon.h"
#include "url/url_canon_ip.h"
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/security_origin.h b/chromium/third_party/blink/renderer/platform/weborigin/security_origin.h
index e54f3f67f50..4101ef4e39c 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/security_origin.h
+++ b/chromium/third_party/blink/renderer/platform/weborigin/security_origin.h
@@ -59,10 +59,6 @@ class PLATFORM_EXPORT SecurityOrigin : public RefCounted<SecurityOrigin> {
// Creates a new opaque SecurityOrigin that is guaranteed to be cross-origin
// to all currently existing SecurityOrigins.
static scoped_refptr<SecurityOrigin> CreateUniqueOpaque();
- // Deprecated alias for CreateOpaque().
- static scoped_refptr<SecurityOrigin> CreateUnique() {
- return CreateUniqueOpaque();
- }
static scoped_refptr<SecurityOrigin> CreateFromString(const String&);
static scoped_refptr<SecurityOrigin> Create(const String& protocol,
@@ -196,8 +192,6 @@ class PLATFORM_EXPORT SecurityOrigin : public RefCounted<SecurityOrigin> {
// details), such as for documents generated from data: URLs or documents
// with the sandboxed origin browsing context flag set.
bool IsOpaque() const { return is_opaque_; }
- // Deprecated alias for IsOpaque().
- bool IsUnique() const { return IsOpaque(); }
// By default 'file:' URLs may access other 'file:' URLs. This method
// denies access. If either SecurityOrigin sets this flag, the access
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/security_policy.cc b/chromium/third_party/blink/renderer/platform/weborigin/security_policy.cc
index fa1c15badfc..1147ed188da 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/security_policy.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/security_policy.cc
@@ -44,6 +44,7 @@
#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
#include "third_party/blink/renderer/platform/wtf/threading.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace blink {
@@ -72,8 +73,8 @@ static void AddOriginAccessEntry(const SecurityOrigin& source_origin,
bool allow_destination_subdomains,
OriginAccessMap& access_map) {
DCHECK(IsMainThread());
- DCHECK(!source_origin.IsUnique());
- if (source_origin.IsUnique())
+ DCHECK(!source_origin.IsOpaque());
+ if (source_origin.IsOpaque())
return;
String source_string = source_origin.ToString();
@@ -94,8 +95,8 @@ static void RemoveOriginAccessEntry(const SecurityOrigin& source_origin,
bool allow_destination_subdomains,
OriginAccessMap& access_map) {
DCHECK(IsMainThread());
- DCHECK(!source_origin.IsUnique());
- if (source_origin.IsUnique())
+ DCHECK(!source_origin.IsOpaque());
+ if (source_origin.IsOpaque())
return;
String source_string = source_origin.ToString();
@@ -118,6 +119,14 @@ static void RemoveOriginAccessEntry(const SecurityOrigin& source_origin,
access_map.erase(it);
}
+static void RemoveAllOriginAccessEntriesForOrigin(
+ const SecurityOrigin& source_origin,
+ OriginAccessMap& access_map) {
+ DCHECK(IsMainThread());
+ DCHECK(!source_origin.IsOpaque());
+ access_map.erase(source_origin.ToString());
+}
+
static bool IsOriginPairInAccessMap(const SecurityOrigin* active_origin,
const SecurityOrigin* target_origin,
const OriginAccessMap& access_map) {
@@ -257,7 +266,7 @@ bool SecurityPolicy::IsOriginWhiteListedTrustworthy(
const SecurityOrigin& origin) {
// Early return if there are no whitelisted origins to avoid unnecessary
// allocations, copies, and frees.
- if (origin.IsUnique() || TrustworthyOriginSet().IsEmpty())
+ if (origin.IsOpaque() || TrustworthyOriginSet().IsEmpty())
return false;
if (TrustworthyOriginSet().Contains(origin.ToRawString()))
return true;
@@ -323,6 +332,12 @@ void SecurityPolicy::RemoveOriginAccessWhitelistEntry(
GetOriginAccessWhitelistMap());
}
+void SecurityPolicy::RemoveAllOriginAccessWhitelistEntriesForOrigin(
+ const SecurityOrigin& source_origin) {
+ RemoveAllOriginAccessEntriesForOrigin(source_origin,
+ GetOriginAccessWhitelistMap());
+}
+
void SecurityPolicy::ResetOriginAccessWhitelists() {
DCHECK(IsMainThread());
GetOriginAccessWhitelistMap().clear();
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/security_policy.h b/chromium/third_party/blink/renderer/platform/weborigin/security_policy.h
index 38d16bcd971..30f338e4c00 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/security_policy.h
+++ b/chromium/third_party/blink/renderer/platform/weborigin/security_policy.h
@@ -74,6 +74,8 @@ class PLATFORM_EXPORT SecurityPolicy {
const String& destination_protocol,
const String& destination_domain,
bool allow_destination_subdomains);
+ static void RemoveAllOriginAccessWhitelistEntriesForOrigin(
+ const SecurityOrigin& source_origin);
static void ResetOriginAccessWhitelists();
static void AddOriginAccessBlacklistEntry(const SecurityOrigin& source_origin,
diff --git a/chromium/third_party/blink/renderer/platform/weborigin/security_policy_test.cc b/chromium/third_party/blink/renderer/platform/weborigin/security_policy_test.cc
index 9790ee421c5..a31ecf3e4ce 100644
--- a/chromium/third_party/blink/renderer/platform/weborigin/security_policy_test.cc
+++ b/chromium/third_party/blink/renderer/platform/weborigin/security_policy_test.cc
@@ -425,4 +425,24 @@ TEST_F(SecurityPolicyAccessTest,
https_google_origin()));
}
+TEST_F(SecurityPolicyAccessTest,
+ RemoveAllOriginAccessWhitelistEntriesForOrigin) {
+ SecurityPolicy::AddOriginAccessWhitelistEntry(*https_chromium_origin(),
+ "https", "example.com", true);
+ SecurityPolicy::AddOriginAccessWhitelistEntry(*https_chromium_origin(),
+ "https", "google.com", true);
+ SecurityPolicy::AddOriginAccessWhitelistEntry(*https_example_origin(),
+ "https", "google.com", true);
+
+ SecurityPolicy::RemoveAllOriginAccessWhitelistEntriesForOrigin(
+ *https_chromium_origin());
+
+ EXPECT_FALSE(SecurityPolicy::IsAccessWhiteListed(https_chromium_origin(),
+ https_example_origin()));
+ EXPECT_FALSE(SecurityPolicy::IsAccessWhiteListed(https_chromium_origin(),
+ https_google_origin()));
+ EXPECT_TRUE(SecurityPolicy::IsAccessWhiteListed(https_example_origin(),
+ https_google_origin()));
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/wtf/BUILD.gn b/chromium/third_party/blink/renderer/platform/wtf/BUILD.gn
index c2abc5d4b67..dba0b46aff5 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/BUILD.gn
+++ b/chromium/third_party/blink/renderer/platform/wtf/BUILD.gn
@@ -59,15 +59,14 @@ jumbo_component("wtf") {
"bit_vector.cc",
"bit_vector.h",
"bloom_filter.h",
- "byte_order.h",
- "byte_swap.h",
- "checked_numeric.h",
"compiler.h",
"conditional_destructor.h",
"container_annotations.h",
"cpu.h",
"date_math.cc",
"date_math.h",
+ "decimal.cc",
+ "decimal.h",
"deque.h",
"doubly_linked_list.h",
"dtoa.cc",
@@ -113,7 +112,6 @@ jumbo_component("wtf") {
"math_extras.h",
"noncopyable.h",
"not_found.h",
- "process_metrics.h",
"ref_counted.h",
"ref_vector.h",
"retain_ptr.h",
@@ -141,12 +139,13 @@ jumbo_component("wtf") {
"text/base64.cc",
"text/base64.h",
"text/character_names.h",
+ "text/collator.cc",
"text/collator.h",
"text/cstring.cc",
"text/cstring.h",
- "text/icu/collator_icu.cc",
- "text/icu/unicode_icu.h",
"text/integer_to_string_conversion.h",
+ "text/movable_string.cc",
+ "text/movable_string.h",
"text/number_parsing_options.h",
"text/parsing_utilities.h",
"text/string_buffer.h",
@@ -311,6 +310,7 @@ jumbo_source_set("wtf_unittests_sources") {
sources = [
"ascii_ctype_test.cc",
"assertions_test.cc",
+ "decimal_test.cc",
"deque_test.cc",
"dtoa_test.cc",
"experimental/container_type_operations_test.cc",
@@ -319,7 +319,6 @@ jumbo_source_set("wtf_unittests_sources") {
"hash_set_test.cc",
"list_hash_set_test.cc",
"math_extras_test.cc",
- "ref_ptr_test.cc",
"saturated_arithmetic_test.cc",
"scoped_logger_test.cc",
"string_hasher_test.cc",
@@ -327,6 +326,7 @@ jumbo_source_set("wtf_unittests_sources") {
"text/atomic_string_test.cc",
"text/cstring_test.cc",
"text/integer_to_string_conversion_test.cc",
+ "text/movable_string_test.cc",
"text/string_buffer_test.cc",
"text/string_builder_test.cc",
"text/string_impl_test.cc",
diff --git a/chromium/third_party/blink/renderer/platform/wtf/DEPS b/chromium/third_party/blink/renderer/platform/wtf/DEPS
index 886c40c8564..2576c5d932a 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/DEPS
+++ b/chromium/third_party/blink/renderer/platform/wtf/DEPS
@@ -11,6 +11,7 @@ include_rules = [
"+base/memory/ptr_util.h",
"+base/memory/ref_counted.h",
"+base/memory/weak_ptr.h",
+ "+base/metrics/histogram_macros.h",
"+base/numerics",
"+base/optional.h",
"+base/process/process_metrics.h",
@@ -18,6 +19,7 @@ include_rules = [
"+base/stl_util.h",
"+base/strings",
"+base/template_util.h",
+ "+base/test/metrics/histogram_tester.h",
"+base/threading/thread_checker.h",
"+base/threading/thread_local_storage.h",
"+base/time/time.h",
diff --git a/chromium/third_party/blink/renderer/platform/wtf/OWNERS b/chromium/third_party/blink/renderer/platform/wtf/OWNERS
index 0be7ad9c02c..52eda6933ad 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/OWNERS
+++ b/chromium/third_party/blink/renderer/platform/wtf/OWNERS
@@ -1,7 +1,6 @@
erik.corry@gmail.com
haraken@chromium.org
jochen@chromium.org
-mikhail.pozdnyakov@intel.com
thakis@chromium.org
tkent@chromium.org
yutak@chromium.org
diff --git a/chromium/third_party/blink/renderer/platform/wtf/README.md b/chromium/third_party/blink/renderer/platform/wtf/README.md
index c34ba5d3b12..80e00dadf91 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/README.md
+++ b/chromium/third_party/blink/renderer/platform/wtf/README.md
@@ -25,7 +25,7 @@ functionality.
Also, we are trying to eliminate duplicated functionalities between WTF and
[base]. Historically, WTF was developed as a stand-alone library, so there
-are still many overlaps. We want to eventually delegate sharable implementation
+are still many overlaps. We want to eventually delegate shareable implementation
to [base] as much as possible.
If you find a missing functionality in WTF, regardless of whether it is
diff --git a/chromium/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h b/chromium/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h
index 590dd0b5d8e..cbd0f90b4b3 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h
@@ -105,6 +105,7 @@ class WTF_EXPORT PartitionAllocator {
static bool IsAllocationAllowed() { return true; }
static bool IsObjectResurrectionForbidden() { return false; }
+ static bool IsSweepForbidden() { return false; }
static void EnterGCForbiddenScope() {}
static void LeaveGCForbiddenScope() {}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.cc b/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.cc
index 1d7bbd3a4c8..065fea96db7 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.cc
@@ -35,6 +35,7 @@
#include "base/debug/alias.h"
#include "base/lazy_instance.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace WTF {
@@ -136,19 +137,19 @@ void Partitions::DumpMemoryStats(
namespace {
-class LightPartitionStatsDumperImpl : public WTF::PartitionStatsDumper {
+class LightPartitionStatsDumperImpl : public base::PartitionStatsDumper {
public:
LightPartitionStatsDumperImpl() : total_active_bytes_(0) {}
void PartitionDumpTotals(
const char* partition_name,
- const WTF::PartitionMemoryStats* memory_stats) override {
+ const base::PartitionMemoryStats* memory_stats) override {
total_active_bytes_ += memory_stats->total_active_bytes;
}
void PartitionsDumpBucketStats(
const char* partition_name,
- const WTF::PartitionBucketMemoryStats*) override {}
+ const base::PartitionBucketMemoryStats*) override {}
size_t TotalActiveBytes() const { return total_active_bytes_; }
@@ -164,64 +165,64 @@ size_t Partitions::TotalActiveBytes() {
return dumper.TotalActiveBytes();
}
-static NEVER_INLINE void PartitionsOutOfMemoryUsing2G() {
+static NOINLINE void PartitionsOutOfMemoryUsing2G() {
size_t signature = 2UL * 1024 * 1024 * 1024;
base::debug::Alias(&signature);
OOM_CRASH();
}
-static NEVER_INLINE void PartitionsOutOfMemoryUsing1G() {
+static NOINLINE void PartitionsOutOfMemoryUsing1G() {
size_t signature = 1UL * 1024 * 1024 * 1024;
base::debug::Alias(&signature);
OOM_CRASH();
}
-static NEVER_INLINE void PartitionsOutOfMemoryUsing512M() {
+static NOINLINE void PartitionsOutOfMemoryUsing512M() {
size_t signature = 512 * 1024 * 1024;
base::debug::Alias(&signature);
OOM_CRASH();
}
-static NEVER_INLINE void PartitionsOutOfMemoryUsing256M() {
+static NOINLINE void PartitionsOutOfMemoryUsing256M() {
size_t signature = 256 * 1024 * 1024;
base::debug::Alias(&signature);
OOM_CRASH();
}
-static NEVER_INLINE void PartitionsOutOfMemoryUsing128M() {
+static NOINLINE void PartitionsOutOfMemoryUsing128M() {
size_t signature = 128 * 1024 * 1024;
base::debug::Alias(&signature);
OOM_CRASH();
}
-static NEVER_INLINE void PartitionsOutOfMemoryUsing64M() {
+static NOINLINE void PartitionsOutOfMemoryUsing64M() {
size_t signature = 64 * 1024 * 1024;
base::debug::Alias(&signature);
OOM_CRASH();
}
-static NEVER_INLINE void PartitionsOutOfMemoryUsing32M() {
+static NOINLINE void PartitionsOutOfMemoryUsing32M() {
size_t signature = 32 * 1024 * 1024;
base::debug::Alias(&signature);
OOM_CRASH();
}
-static NEVER_INLINE void PartitionsOutOfMemoryUsing16M() {
+static NOINLINE void PartitionsOutOfMemoryUsing16M() {
size_t signature = 16 * 1024 * 1024;
base::debug::Alias(&signature);
OOM_CRASH();
}
-static NEVER_INLINE void PartitionsOutOfMemoryUsingLessThan16M() {
+static NOINLINE void PartitionsOutOfMemoryUsingLessThan16M() {
size_t signature = 16 * 1024 * 1024 - 1;
base::debug::Alias(&signature);
DLOG(FATAL) << "ParitionAlloc: out of memory with < 16M usage (error:"
- << GetAllocPageErrorCode() << ")";
+ << base::GetAllocPageErrorCode() << ")";
}
void Partitions::HandleOutOfMemory() {
volatile size_t total_usage = TotalSizeOfCommittedPages();
- uint32_t alloc_page_error_code = GetAllocPageErrorCode();
+ uint32_t alloc_page_error_code = base::GetAllocPageErrorCode();
base::debug::Alias(&alloc_page_error_code);
if (total_usage >= 2UL * 1024 * 1024 * 1024)
diff --git a/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.h b/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.h
index 5201b027d65..079afd0c248 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/allocator/partitions.h
@@ -33,10 +33,8 @@
#include <string.h>
#include "base/allocator/partition_allocator/partition_alloc.h"
-#include "base/allocator/partition_allocator/spin_lock.h"
+#include "base/logging.h"
#include "base/numerics/checked_math.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/wtf.h"
#include "third_party/blink/renderer/platform/wtf/wtf_export.h"
namespace WTF {
@@ -65,11 +63,6 @@ class WTF_EXPORT Partitions {
return fast_malloc_allocator_->root();
}
- ALWAYS_INLINE static base::PartitionRoot* NodePartition() {
- NOTREACHED();
- return nullptr;
- }
-
ALWAYS_INLINE static base::PartitionRoot* LayoutPartition() {
DCHECK(initialized_);
return layout_allocator_->root();
@@ -81,11 +74,6 @@ class WTF_EXPORT Partitions {
return total.ValueOrDie();
}
- static size_t CurrentDOMMemoryUsage() {
- NOTREACHED();
- return 0;
- }
-
static size_t TotalSizeOfCommittedPages() {
DCHECK(initialized_);
size_t total_size = 0;
@@ -143,32 +131,6 @@ class WTF_EXPORT Partitions {
static ReportPartitionAllocSizeFunction report_size_function_;
};
-using base::kGenericMaxDirectMapped;
-using base::kPageAllocationGranularity;
-using base::kPageAllocationGranularityBaseMask;
-using base::kPageAllocationGranularityOffsetMask;
-using base::kSystemPageSize;
-
-using base::AllocPages;
-using base::DecommitSystemPages;
-using base::DiscardSystemPages;
-using base::PartitionFree;
-using base::FreePages;
-using base::GetAllocPageErrorCode;
-using base::RecommitSystemPages;
-using base::RoundDownToSystemPage;
-using base::RoundUpToSystemPage;
-using base::SetSystemPagesAccess;
-
-using base::PageInaccessible;
-using base::PageReadWrite;
-using base::PartitionStatsDumper;
-using base::PartitionMemoryStats;
-using base::PartitionBucketMemoryStats;
-using base::PartitionAllocHooks;
-
-using CheckedSizeT = base::CheckedNumeric<size_t>;
-
} // namespace WTF
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_ALLOCATOR_PARTITIONS_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/ascii_ctype.h b/chromium/third_party/blink/renderer/platform/wtf/ascii_ctype.h
index 0d748576522..f210954827b 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/ascii_ctype.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/ascii_ctype.h
@@ -155,7 +155,7 @@ inline char UpperNibbleToASCIIHexDigit(char c) {
template <typename CharType>
inline bool IsASCIIAlphaCaselessEqual(CharType css_character, char character) {
- // This function compares a (preferrably) constant ASCII
+ // This function compares a (preferably) constant ASCII
// lowercase letter to any input character.
DCHECK_GE(character, 'a');
DCHECK_LE(character, 'z');
diff --git a/chromium/third_party/blink/renderer/platform/wtf/bit_vector.h b/chromium/third_party/blink/renderer/platform/wtf/bit_vector.h
index d434424deb0..a0db94fe55f 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/bit_vector.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/bit_vector.h
@@ -33,7 +33,7 @@
namespace WTF {
-// This is a space-efficient, resizeable bitvector class. In the common case it
+// This is a space-efficient, resizable bitvector class. In the common case it
// occupies one word, but if necessary, it will inflate this one word to point
// to a single chunk of out-of-line allocated storage to store an arbitrary
// number of bits.
diff --git a/chromium/third_party/blink/renderer/platform/wtf/byte_order.h b/chromium/third_party/blink/renderer/platform/wtf/byte_order.h
deleted file mode 100644
index 0d5fe42d842..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/byte_order.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-* Copyright (C) 2012 Google Inc. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-*
-* * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following disclaimer
-* in the documentation and/or other materials provided with the
-* distribution.
-* * Neither the name of Google Inc. nor the names of its
-* contributors may be used to endorse or promote products derived from
-* this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_BYTE_ORDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_BYTE_ORDER_H_
-
-#include "build/build_config.h"
-
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
-#include <arpa/inet.h>
-#endif
-
-#if defined(OS_WIN)
-#include <winsock2.h>
-#endif // defined(OS_WIN)
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_BYTE_ORDER_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/byte_swap.h b/chromium/third_party/blink/renderer/platform/wtf/byte_swap.h
deleted file mode 100644
index ebd6896f00e..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/byte_swap.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2013 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_BYTE_SWAP_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_BYTE_SWAP_H_
-
-#include <stdint.h>
-#include "build/build_config.h"
-#include "third_party/blink/renderer/platform/wtf/compiler.h"
-#include "third_party/blink/renderer/platform/wtf/cpu.h"
-
-#if defined(COMPILER_MSVC)
-#include <stdlib.h>
-#endif
-
-namespace WTF {
-
-inline uint32_t Wswap32(uint32_t x) {
- return ((x & 0xffff0000) >> 16) | ((x & 0x0000ffff) << 16);
-}
-
-#if defined(COMPILER_MSVC)
-
-ALWAYS_INLINE uint64_t Bswap64(uint64_t x) {
- return _byteswap_uint64(x);
-}
-ALWAYS_INLINE uint32_t Bswap32(uint32_t x) {
- return _byteswap_ulong(x);
-}
-ALWAYS_INLINE uint16_t Bswap16(uint16_t x) {
- return _byteswap_ushort(x);
-}
-
-#else
-
-ALWAYS_INLINE uint64_t Bswap64(uint64_t x) {
- return __builtin_bswap64(x);
-}
-ALWAYS_INLINE uint32_t Bswap32(uint32_t x) {
- return __builtin_bswap32(x);
-}
-ALWAYS_INLINE uint16_t Bswap16(uint16_t x) {
- return __builtin_bswap16(x);
-}
-
-#endif
-
-} // namespace WTF
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_BYTE_SWAP_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/checked_numeric.h b/chromium/third_party/blink/renderer/platform/wtf/checked_numeric.h
deleted file mode 100644
index 5a705f9cb9c..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/checked_numeric.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_CHECKED_NUMERIC_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_CHECKED_NUMERIC_H_
-
-/* See base/numerics/safe_math.h for usage.
- */
-#include "base/numerics/safe_math.h"
-
-namespace WTF {
-using base::CheckedNumeric;
-using base::IsValidForType;
-using base::ValueOrDieForType;
-using base::ValueOrDefaultForType;
-using base::MakeCheckedNum;
-using base::CheckMax;
-using base::CheckMin;
-using base::CheckAdd;
-using base::CheckSub;
-using base::CheckMul;
-using base::CheckDiv;
-using base::CheckMod;
-using base::CheckLsh;
-using base::CheckRsh;
-using base::CheckAnd;
-using base::CheckOr;
-using base::CheckXor;
-} // namespace WTF
-
-using WTF::CheckedNumeric;
-
-#endif
diff --git a/chromium/third_party/blink/renderer/platform/wtf/compiler.h b/chromium/third_party/blink/renderer/platform/wtf/compiler.h
index 4f0d73c30df..51595afdc95 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/compiler.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/compiler.h
@@ -29,25 +29,8 @@
#include "base/compiler_specific.h"
#include "build/build_config.h"
-#if defined(__GNUC__)
-#define GCC_VERSION \
- (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
-#define GCC_VERSION_AT_LEAST(major, minor, patch) \
- (GCC_VERSION >= (major * 10000 + minor * 100 + patch))
-#else
-/* Define this for !GCC compilers, just so we can write things like
- * GCC_VERSION_AT_LEAST(4, 1, 0). */
-#define GCC_VERSION_AT_LEAST(major, minor, patch) 0
-#endif
-
/* ==== Compiler features ==== */
-/* NEVER_INLINE */
-
-// TODO(palmer): Remove this and update callers to use NOINLINE from Chromium
-// base. https://bugs.chromium.org/p/chromium/issues/detail?id=632441
-#define NEVER_INLINE NOINLINE
-
/* OBJC_CLASS */
#ifndef OBJC_CLASS
diff --git a/chromium/third_party/blink/renderer/platform/wtf/conditional_destructor.h b/chromium/third_party/blink/renderer/platform/wtf/conditional_destructor.h
index 1b7e0020cd0..34fbfdedca0 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/conditional_destructor.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/conditional_destructor.h
@@ -12,7 +12,7 @@ namespace WTF {
// for an object that does not need to be destructed. By doing so,
// the clang compiler will have correct information about whether or not
// the object has a trivial destructor.
-// Note: the derived object MUST release all its recources at the finalize()
+// Note: the derived object MUST release all its resources at the finalize()
// method.
template <typename Derived, bool noDestructor>
class ConditionalDestructor {
diff --git a/chromium/third_party/blink/renderer/platform/wtf/date_math.cc b/chromium/third_party/blink/renderer/platform/wtf/date_math.cc
index 10f895e3a92..a7f3e3e8c80 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/date_math.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/date_math.cc
@@ -77,6 +77,7 @@
#include <time.h>
#include <algorithm>
#include <limits>
+#include <memory>
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/ascii_ctype.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
@@ -86,6 +87,8 @@
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
+#include <unicode/timezone.h>
+
#if defined(OS_WIN)
#include <windows.h>
#else
@@ -493,7 +496,7 @@ static bool ParseLong(const char* string,
return true;
}
-// Odd case where 'exec' is allowed to be 0, to accomodate a caller in WebCore.
+// Odd case where 'exec' is allowed to be 0, to accommodate a caller in WebCore.
static double ParseDateFromNullTerminatedCharacters(const char* date_string,
bool& have_tz,
int& offset) {
@@ -646,7 +649,7 @@ static double ParseDateFromNullTerminatedCharacters(const char* date_string,
ParseLong(date_string, &new_pos_str, 10, &hour);
// Do not check for errno here since we want to continue
- // even if errno was set becasue we are still looking
+ // even if errno was set because we are still looking
// for the timezone!
// Read a number? If not, this might be a timezone name.
@@ -835,9 +838,11 @@ String MakeRFC2822DateString(const Time date, int utc_offset) {
}
double ConvertToLocalTime(double ms) {
- double utc_offset = CalculateUTCOffset();
- double dst_offset = CalculateDSTOffset(ms, utc_offset);
- return (ms + utc_offset + dst_offset);
+ std::unique_ptr<icu::TimeZone> timezone(icu::TimeZone::createDefault());
+ int32_t raw_offset, dst_offset;
+ UErrorCode status = U_ZERO_ERROR;
+ timezone->getOffset(ms, false, raw_offset, dst_offset, status);
+ return (ms + static_cast<double>(raw_offset + dst_offset));
}
} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/decimal.cc b/chromium/third_party/blink/renderer/platform/wtf/decimal.cc
new file mode 100644
index 00000000000..5dcc3b8d7a4
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/wtf/decimal.cc
@@ -0,0 +1,1007 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "third_party/blink/renderer/platform/wtf/decimal.h"
+
+#include <algorithm>
+#include <cfloat>
+
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/blink/renderer/platform/wtf/noncopyable.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
+
+namespace blink {
+
+namespace DecimalPrivate {
+
+static int const kExponentMax = 1023;
+static int const kExponentMin = -1023;
+static int const kPrecision = 18;
+
+static const uint64_t kMaxCoefficient =
+ UINT64_C(0xDE0B6B3A763FFFF); // 999999999999999999 == 18 9's
+
+// This class handles Decimal special values.
+class SpecialValueHandler {
+ STACK_ALLOCATED();
+ WTF_MAKE_NONCOPYABLE(SpecialValueHandler);
+
+ public:
+ enum HandleResult {
+ kBothFinite,
+ kBothInfinity,
+ kEitherNaN,
+ kLHSIsInfinity,
+ kRHSIsInfinity,
+ };
+
+ SpecialValueHandler(const Decimal& lhs, const Decimal& rhs);
+ HandleResult Handle();
+ Decimal Value() const;
+
+ private:
+ enum Result {
+ kResultIsLHS,
+ kResultIsRHS,
+ kResultIsUnknown,
+ };
+
+ const Decimal& lhs_;
+ const Decimal& rhs_;
+ Result result_;
+};
+
+SpecialValueHandler::SpecialValueHandler(const Decimal& lhs, const Decimal& rhs)
+ : lhs_(lhs), rhs_(rhs), result_(kResultIsUnknown) {}
+
+SpecialValueHandler::HandleResult SpecialValueHandler::Handle() {
+ if (lhs_.IsFinite() && rhs_.IsFinite())
+ return kBothFinite;
+
+ const Decimal::EncodedData::FormatClass lhs_class =
+ lhs_.Value().GetFormatClass();
+ const Decimal::EncodedData::FormatClass rhs_class =
+ rhs_.Value().GetFormatClass();
+ if (lhs_class == Decimal::EncodedData::kClassNaN) {
+ result_ = kResultIsLHS;
+ return kEitherNaN;
+ }
+
+ if (rhs_class == Decimal::EncodedData::kClassNaN) {
+ result_ = kResultIsRHS;
+ return kEitherNaN;
+ }
+
+ if (lhs_class == Decimal::EncodedData::kClassInfinity)
+ return rhs_class == Decimal::EncodedData::kClassInfinity ? kBothInfinity
+ : kLHSIsInfinity;
+
+ if (rhs_class == Decimal::EncodedData::kClassInfinity)
+ return kRHSIsInfinity;
+
+ NOTREACHED();
+ return kBothFinite;
+}
+
+Decimal SpecialValueHandler::Value() const {
+ switch (result_) {
+ case kResultIsLHS:
+ return lhs_;
+ case kResultIsRHS:
+ return rhs_;
+ case kResultIsUnknown:
+ default:
+ NOTREACHED();
+ return lhs_;
+ }
+}
+
+// This class is used for 128 bit unsigned integer arithmetic.
+class UInt128 {
+ public:
+ UInt128(uint64_t low, uint64_t high) : high_(high), low_(low) {}
+
+ UInt128& operator/=(uint32_t);
+
+ uint64_t High() const { return high_; }
+ uint64_t Low() const { return low_; }
+
+ static UInt128 Multiply(uint64_t u, uint64_t v) {
+ return UInt128(u * v, MultiplyHigh(u, v));
+ }
+
+ private:
+ static uint32_t HighUInt32(uint64_t x) {
+ return static_cast<uint32_t>(x >> 32);
+ }
+ static uint32_t LowUInt32(uint64_t x) {
+ return static_cast<uint32_t>(x & ((static_cast<uint64_t>(1) << 32) - 1));
+ }
+ static uint64_t MakeUInt64(uint32_t low, uint32_t high) {
+ return low | (static_cast<uint64_t>(high) << 32);
+ }
+
+ static uint64_t MultiplyHigh(uint64_t, uint64_t);
+
+ uint64_t high_;
+ uint64_t low_;
+};
+
+UInt128& UInt128::operator/=(const uint32_t divisor) {
+ DCHECK(divisor);
+
+ if (!high_) {
+ low_ /= divisor;
+ return *this;
+ }
+
+ uint32_t dividend[4];
+ dividend[0] = LowUInt32(low_);
+ dividend[1] = HighUInt32(low_);
+ dividend[2] = LowUInt32(high_);
+ dividend[3] = HighUInt32(high_);
+
+ uint32_t quotient[4];
+ uint32_t remainder = 0;
+ for (int i = 3; i >= 0; --i) {
+ const uint64_t work = MakeUInt64(dividend[i], remainder);
+ remainder = static_cast<uint32_t>(work % divisor);
+ quotient[i] = static_cast<uint32_t>(work / divisor);
+ }
+ low_ = MakeUInt64(quotient[0], quotient[1]);
+ high_ = MakeUInt64(quotient[2], quotient[3]);
+ return *this;
+}
+
+// Returns high 64bit of 128bit product.
+uint64_t UInt128::MultiplyHigh(uint64_t u, uint64_t v) {
+ const uint64_t u_low = LowUInt32(u);
+ const uint64_t u_high = HighUInt32(u);
+ const uint64_t v_low = LowUInt32(v);
+ const uint64_t v_high = HighUInt32(v);
+ const uint64_t partial_product = u_high * v_low + HighUInt32(u_low * v_low);
+ return u_high * v_high + HighUInt32(partial_product) +
+ HighUInt32(u_low * v_high + LowUInt32(partial_product));
+}
+
+static int CountDigits(uint64_t x) {
+ int number_of_digits = 0;
+ for (uint64_t power_of_ten = 1; x >= power_of_ten; power_of_ten *= 10) {
+ ++number_of_digits;
+ if (power_of_ten >= std::numeric_limits<uint64_t>::max() / 10)
+ break;
+ }
+ return number_of_digits;
+}
+
+static uint64_t ScaleDown(uint64_t x, int n) {
+ DCHECK_GE(n, 0);
+ while (n > 0 && x) {
+ x /= 10;
+ --n;
+ }
+ return x;
+}
+
+static uint64_t ScaleUp(uint64_t x, int n) {
+ DCHECK_GE(n, 0);
+ DCHECK_LE(n, kPrecision);
+
+ uint64_t y = 1;
+ uint64_t z = 10;
+ for (;;) {
+ if (n & 1)
+ y = y * z;
+
+ n >>= 1;
+ if (!n)
+ return x * y;
+
+ z = z * z;
+ }
+}
+
+} // namespace DecimalPrivate
+
+using namespace DecimalPrivate;
+
+Decimal::EncodedData::EncodedData(Sign sign, FormatClass format_class)
+ : coefficient_(0), exponent_(0), format_class_(format_class), sign_(sign) {}
+
+Decimal::EncodedData::EncodedData(Sign sign, int exponent, uint64_t coefficient)
+ : format_class_(coefficient ? kClassNormal : kClassZero), sign_(sign) {
+ if (exponent >= kExponentMin && exponent <= kExponentMax) {
+ while (coefficient > kMaxCoefficient) {
+ coefficient /= 10;
+ ++exponent;
+ }
+ }
+
+ if (exponent > kExponentMax) {
+ coefficient_ = 0;
+ exponent_ = 0;
+ format_class_ = kClassInfinity;
+ return;
+ }
+
+ if (exponent < kExponentMin) {
+ coefficient_ = 0;
+ exponent_ = 0;
+ format_class_ = kClassZero;
+ return;
+ }
+
+ coefficient_ = coefficient;
+ exponent_ = static_cast<int16_t>(exponent);
+}
+
+bool Decimal::EncodedData::operator==(const EncodedData& another) const {
+ return sign_ == another.sign_ && format_class_ == another.format_class_ &&
+ exponent_ == another.exponent_ && coefficient_ == another.coefficient_;
+}
+
+Decimal::Decimal(int32_t i32)
+ : data_(i32 < 0 ? kNegative : kPositive,
+ 0,
+ i32 < 0 ? static_cast<uint64_t>(-static_cast<int64_t>(i32))
+ : static_cast<uint64_t>(i32)) {}
+
+Decimal::Decimal(Sign sign, int exponent, uint64_t coefficient)
+ : data_(sign, exponent, coefficient) {}
+
+Decimal::Decimal(const EncodedData& data) : data_(data) {}
+
+Decimal::Decimal(const Decimal& other) = default;
+
+Decimal& Decimal::operator=(const Decimal& other) = default;
+
+Decimal& Decimal::operator+=(const Decimal& other) {
+ data_ = (*this + other).data_;
+ return *this;
+}
+
+Decimal& Decimal::operator-=(const Decimal& other) {
+ data_ = (*this - other).data_;
+ return *this;
+}
+
+Decimal& Decimal::operator*=(const Decimal& other) {
+ data_ = (*this * other).data_;
+ return *this;
+}
+
+Decimal& Decimal::operator/=(const Decimal& other) {
+ data_ = (*this / other).data_;
+ return *this;
+}
+
+Decimal Decimal::operator-() const {
+ if (IsNaN())
+ return *this;
+
+ Decimal result(*this);
+ result.data_.SetSign(InvertSign(data_.GetSign()));
+ return result;
+}
+
+Decimal Decimal::operator+(const Decimal& rhs) const {
+ const Decimal& lhs = *this;
+ const Sign lhs_sign = lhs.GetSign();
+ const Sign rhs_sign = rhs.GetSign();
+
+ SpecialValueHandler handler(lhs, rhs);
+ switch (handler.Handle()) {
+ case SpecialValueHandler::kBothFinite:
+ break;
+
+ case SpecialValueHandler::kBothInfinity:
+ return lhs_sign == rhs_sign ? lhs : Nan();
+
+ case SpecialValueHandler::kEitherNaN:
+ return handler.Value();
+
+ case SpecialValueHandler::kLHSIsInfinity:
+ return lhs;
+
+ case SpecialValueHandler::kRHSIsInfinity:
+ return rhs;
+ }
+
+ const AlignedOperands aligned_operands = AlignOperands(lhs, rhs);
+
+ const uint64_t result =
+ lhs_sign == rhs_sign
+ ? aligned_operands.lhs_coefficient + aligned_operands.rhs_coefficient
+ : aligned_operands.lhs_coefficient - aligned_operands.rhs_coefficient;
+
+ if (lhs_sign == kNegative && rhs_sign == kPositive && !result)
+ return Decimal(kPositive, aligned_operands.exponent, 0);
+
+ return static_cast<int64_t>(result) >= 0
+ ? Decimal(lhs_sign, aligned_operands.exponent, result)
+ : Decimal(InvertSign(lhs_sign), aligned_operands.exponent,
+ -static_cast<int64_t>(result));
+}
+
+Decimal Decimal::operator-(const Decimal& rhs) const {
+ const Decimal& lhs = *this;
+ const Sign lhs_sign = lhs.GetSign();
+ const Sign rhs_sign = rhs.GetSign();
+
+ SpecialValueHandler handler(lhs, rhs);
+ switch (handler.Handle()) {
+ case SpecialValueHandler::kBothFinite:
+ break;
+
+ case SpecialValueHandler::kBothInfinity:
+ return lhs_sign == rhs_sign ? Nan() : lhs;
+
+ case SpecialValueHandler::kEitherNaN:
+ return handler.Value();
+
+ case SpecialValueHandler::kLHSIsInfinity:
+ return lhs;
+
+ case SpecialValueHandler::kRHSIsInfinity:
+ return Infinity(InvertSign(rhs_sign));
+ }
+
+ const AlignedOperands aligned_operands = AlignOperands(lhs, rhs);
+
+ const uint64_t result =
+ lhs_sign == rhs_sign
+ ? aligned_operands.lhs_coefficient - aligned_operands.rhs_coefficient
+ : aligned_operands.lhs_coefficient + aligned_operands.rhs_coefficient;
+
+ if (lhs_sign == kNegative && rhs_sign == kNegative && !result)
+ return Decimal(kPositive, aligned_operands.exponent, 0);
+
+ return static_cast<int64_t>(result) >= 0
+ ? Decimal(lhs_sign, aligned_operands.exponent, result)
+ : Decimal(InvertSign(lhs_sign), aligned_operands.exponent,
+ -static_cast<int64_t>(result));
+}
+
+Decimal Decimal::operator*(const Decimal& rhs) const {
+ const Decimal& lhs = *this;
+ const Sign lhs_sign = lhs.GetSign();
+ const Sign rhs_sign = rhs.GetSign();
+ const Sign result_sign = lhs_sign == rhs_sign ? kPositive : kNegative;
+
+ SpecialValueHandler handler(lhs, rhs);
+ switch (handler.Handle()) {
+ case SpecialValueHandler::kBothFinite: {
+ const uint64_t lhs_coefficient = lhs.data_.Coefficient();
+ const uint64_t rhs_coefficient = rhs.data_.Coefficient();
+ int result_exponent = lhs.Exponent() + rhs.Exponent();
+ UInt128 work(UInt128::Multiply(lhs_coefficient, rhs_coefficient));
+ while (work.High()) {
+ work /= 10;
+ ++result_exponent;
+ }
+ return Decimal(result_sign, result_exponent, work.Low());
+ }
+
+ case SpecialValueHandler::kBothInfinity:
+ return Infinity(result_sign);
+
+ case SpecialValueHandler::kEitherNaN:
+ return handler.Value();
+
+ case SpecialValueHandler::kLHSIsInfinity:
+ return rhs.IsZero() ? Nan() : Infinity(result_sign);
+
+ case SpecialValueHandler::kRHSIsInfinity:
+ return lhs.IsZero() ? Nan() : Infinity(result_sign);
+ }
+
+ NOTREACHED();
+ return Nan();
+}
+
+Decimal Decimal::operator/(const Decimal& rhs) const {
+ const Decimal& lhs = *this;
+ const Sign lhs_sign = lhs.GetSign();
+ const Sign rhs_sign = rhs.GetSign();
+ const Sign result_sign = lhs_sign == rhs_sign ? kPositive : kNegative;
+
+ SpecialValueHandler handler(lhs, rhs);
+ switch (handler.Handle()) {
+ case SpecialValueHandler::kBothFinite:
+ break;
+
+ case SpecialValueHandler::kBothInfinity:
+ return Nan();
+
+ case SpecialValueHandler::kEitherNaN:
+ return handler.Value();
+
+ case SpecialValueHandler::kLHSIsInfinity:
+ return Infinity(result_sign);
+
+ case SpecialValueHandler::kRHSIsInfinity:
+ return Zero(result_sign);
+ }
+
+ DCHECK(lhs.IsFinite());
+ DCHECK(rhs.IsFinite());
+
+ if (rhs.IsZero())
+ return lhs.IsZero() ? Nan() : Infinity(result_sign);
+
+ int result_exponent = lhs.Exponent() - rhs.Exponent();
+
+ if (lhs.IsZero())
+ return Decimal(result_sign, result_exponent, 0);
+
+ uint64_t remainder = lhs.data_.Coefficient();
+ const uint64_t divisor = rhs.data_.Coefficient();
+ uint64_t result = 0;
+ for (;;) {
+ while (remainder < divisor && result < kMaxCoefficient / 10) {
+ remainder *= 10;
+ result *= 10;
+ --result_exponent;
+ }
+ if (remainder < divisor)
+ break;
+ uint64_t quotient = remainder / divisor;
+ if (result > kMaxCoefficient - quotient)
+ break;
+ result += quotient;
+ remainder %= divisor;
+ if (!remainder)
+ break;
+ }
+
+ if (remainder > divisor / 2)
+ ++result;
+
+ return Decimal(result_sign, result_exponent, result);
+}
+
+bool Decimal::operator==(const Decimal& rhs) const {
+ return data_ == rhs.data_ || CompareTo(rhs).IsZero();
+}
+
+bool Decimal::operator!=(const Decimal& rhs) const {
+ if (data_ == rhs.data_)
+ return false;
+ const Decimal result = CompareTo(rhs);
+ if (result.IsNaN())
+ return false;
+ return !result.IsZero();
+}
+
+bool Decimal::operator<(const Decimal& rhs) const {
+ const Decimal result = CompareTo(rhs);
+ if (result.IsNaN())
+ return false;
+ return !result.IsZero() && result.IsNegative();
+}
+
+bool Decimal::operator<=(const Decimal& rhs) const {
+ if (data_ == rhs.data_)
+ return true;
+ const Decimal result = CompareTo(rhs);
+ if (result.IsNaN())
+ return false;
+ return result.IsZero() || result.IsNegative();
+}
+
+bool Decimal::operator>(const Decimal& rhs) const {
+ const Decimal result = CompareTo(rhs);
+ if (result.IsNaN())
+ return false;
+ return !result.IsZero() && result.IsPositive();
+}
+
+bool Decimal::operator>=(const Decimal& rhs) const {
+ if (data_ == rhs.data_)
+ return true;
+ const Decimal result = CompareTo(rhs);
+ if (result.IsNaN())
+ return false;
+ return result.IsZero() || !result.IsNegative();
+}
+
+Decimal Decimal::Abs() const {
+ Decimal result(*this);
+ result.data_.SetSign(kPositive);
+ return result;
+}
+
+Decimal::AlignedOperands Decimal::AlignOperands(const Decimal& lhs,
+ const Decimal& rhs) {
+ DCHECK(lhs.IsFinite());
+ DCHECK(rhs.IsFinite());
+
+ const int lhs_exponent = lhs.Exponent();
+ const int rhs_exponent = rhs.Exponent();
+ int exponent = std::min(lhs_exponent, rhs_exponent);
+ uint64_t lhs_coefficient = lhs.data_.Coefficient();
+ uint64_t rhs_coefficient = rhs.data_.Coefficient();
+
+ if (lhs_exponent > rhs_exponent) {
+ const int number_of_lhs_digits = CountDigits(lhs_coefficient);
+ if (number_of_lhs_digits) {
+ const int lhs_shift_amount = lhs_exponent - rhs_exponent;
+ const int overflow = number_of_lhs_digits + lhs_shift_amount - kPrecision;
+ if (overflow <= 0) {
+ lhs_coefficient = ScaleUp(lhs_coefficient, lhs_shift_amount);
+ } else {
+ lhs_coefficient = ScaleUp(lhs_coefficient, lhs_shift_amount - overflow);
+ rhs_coefficient = ScaleDown(rhs_coefficient, overflow);
+ exponent += overflow;
+ }
+ }
+
+ } else if (lhs_exponent < rhs_exponent) {
+ const int number_of_rhs_digits = CountDigits(rhs_coefficient);
+ if (number_of_rhs_digits) {
+ const int rhs_shift_amount = rhs_exponent - lhs_exponent;
+ const int overflow = number_of_rhs_digits + rhs_shift_amount - kPrecision;
+ if (overflow <= 0) {
+ rhs_coefficient = ScaleUp(rhs_coefficient, rhs_shift_amount);
+ } else {
+ rhs_coefficient = ScaleUp(rhs_coefficient, rhs_shift_amount - overflow);
+ lhs_coefficient = ScaleDown(lhs_coefficient, overflow);
+ exponent += overflow;
+ }
+ }
+ }
+
+ AlignedOperands aligned_operands;
+ aligned_operands.exponent = exponent;
+ aligned_operands.lhs_coefficient = lhs_coefficient;
+ aligned_operands.rhs_coefficient = rhs_coefficient;
+ return aligned_operands;
+}
+
+static bool IsMultiplePowersOfTen(uint64_t coefficient, int n) {
+ return !coefficient || !(coefficient % ScaleUp(1, n));
+}
+
+// Round toward positive infinity.
+Decimal Decimal::Ceil() const {
+ if (IsSpecial())
+ return *this;
+
+ if (Exponent() >= 0)
+ return *this;
+
+ uint64_t result = data_.Coefficient();
+ const int number_of_digits = CountDigits(result);
+ const int number_of_drop_digits = -Exponent();
+ if (number_of_digits <= number_of_drop_digits)
+ return IsPositive() ? Decimal(1) : Zero(kPositive);
+
+ result = ScaleDown(result, number_of_drop_digits);
+ if (IsPositive() &&
+ !IsMultiplePowersOfTen(data_.Coefficient(), number_of_drop_digits))
+ ++result;
+ return Decimal(GetSign(), 0, result);
+}
+
+Decimal Decimal::CompareTo(const Decimal& rhs) const {
+ const Decimal result(*this - rhs);
+ switch (result.data_.GetFormatClass()) {
+ case EncodedData::kClassInfinity:
+ return result.IsNegative() ? Decimal(-1) : Decimal(1);
+
+ case EncodedData::kClassNaN:
+ case EncodedData::kClassNormal:
+ return result;
+
+ case EncodedData::kClassZero:
+ return Zero(kPositive);
+
+ default:
+ NOTREACHED();
+ return Nan();
+ }
+}
+
+// Round toward negative infinity.
+Decimal Decimal::Floor() const {
+ if (IsSpecial())
+ return *this;
+
+ if (Exponent() >= 0)
+ return *this;
+
+ uint64_t result = data_.Coefficient();
+ const int number_of_digits = CountDigits(result);
+ const int number_of_drop_digits = -Exponent();
+ if (number_of_digits < number_of_drop_digits)
+ return IsPositive() ? Zero(kPositive) : Decimal(-1);
+
+ result = ScaleDown(result, number_of_drop_digits);
+ if (IsNegative() &&
+ !IsMultiplePowersOfTen(data_.Coefficient(), number_of_drop_digits))
+ ++result;
+ return Decimal(GetSign(), 0, result);
+}
+
+Decimal Decimal::FromDouble(double double_value) {
+ if (std::isfinite(double_value))
+ return FromString(String::NumberToStringECMAScript(double_value));
+
+ if (std::isinf(double_value))
+ return Infinity(double_value < 0 ? kNegative : kPositive);
+
+ return Nan();
+}
+
+Decimal Decimal::FromString(const String& str) {
+ int exponent = 0;
+ Sign exponent_sign = kPositive;
+ int number_of_digits = 0;
+ int number_of_digits_after_dot = 0;
+ int number_of_extra_digits = 0;
+ Sign sign = kPositive;
+
+ enum {
+ kStateDigit,
+ kStateDot,
+ kStateDotDigit,
+ kStateE,
+ kStateEDigit,
+ kStateESign,
+ kStateSign,
+ kStateStart,
+ kStateZero,
+ } state = kStateStart;
+
+#define HandleCharAndBreak(expected, nextState) \
+ if (ch == expected) { \
+ state = nextState; \
+ break; \
+ }
+
+#define HandleTwoCharsAndBreak(expected1, expected2, nextState) \
+ if (ch == expected1 || ch == expected2) { \
+ state = nextState; \
+ break; \
+ }
+
+ uint64_t accumulator = 0;
+ for (unsigned index = 0; index < str.length(); ++index) {
+ const int ch = str[index];
+ switch (state) {
+ case kStateDigit:
+ if (ch >= '0' && ch <= '9') {
+ if (number_of_digits < kPrecision) {
+ ++number_of_digits;
+ accumulator *= 10;
+ accumulator += ch - '0';
+ } else {
+ ++number_of_extra_digits;
+ }
+ break;
+ }
+
+ HandleCharAndBreak('.', kStateDot);
+ HandleTwoCharsAndBreak('E', 'e', kStateE);
+ return Nan();
+
+ case kStateDot:
+ case kStateDotDigit:
+ if (ch >= '0' && ch <= '9') {
+ if (number_of_digits < kPrecision) {
+ ++number_of_digits;
+ ++number_of_digits_after_dot;
+ accumulator *= 10;
+ accumulator += ch - '0';
+ }
+ state = kStateDotDigit;
+ break;
+ }
+
+ HandleTwoCharsAndBreak('E', 'e', kStateE);
+ return Nan();
+
+ case kStateE:
+ if (ch == '+') {
+ exponent_sign = kPositive;
+ state = kStateESign;
+ break;
+ }
+
+ if (ch == '-') {
+ exponent_sign = kNegative;
+ state = kStateESign;
+ break;
+ }
+
+ if (ch >= '0' && ch <= '9') {
+ exponent = ch - '0';
+ state = kStateEDigit;
+ break;
+ }
+
+ return Nan();
+
+ case kStateEDigit:
+ if (ch >= '0' && ch <= '9') {
+ exponent *= 10;
+ exponent += ch - '0';
+ if (exponent > kExponentMax + kPrecision) {
+ if (accumulator)
+ return exponent_sign == kNegative ? Zero(kPositive)
+ : Infinity(sign);
+ return Zero(sign);
+ }
+ state = kStateEDigit;
+ break;
+ }
+
+ return Nan();
+
+ case kStateESign:
+ if (ch >= '0' && ch <= '9') {
+ exponent = ch - '0';
+ state = kStateEDigit;
+ break;
+ }
+
+ return Nan();
+
+ case kStateSign:
+ if (ch >= '1' && ch <= '9') {
+ accumulator = ch - '0';
+ number_of_digits = 1;
+ state = kStateDigit;
+ break;
+ }
+
+ HandleCharAndBreak('0', kStateZero);
+ return Nan();
+
+ case kStateStart:
+ if (ch >= '1' && ch <= '9') {
+ accumulator = ch - '0';
+ number_of_digits = 1;
+ state = kStateDigit;
+ break;
+ }
+
+ if (ch == '-') {
+ sign = kNegative;
+ state = kStateSign;
+ break;
+ }
+
+ if (ch == '+') {
+ sign = kPositive;
+ state = kStateSign;
+ break;
+ }
+
+ HandleCharAndBreak('0', kStateZero);
+ HandleCharAndBreak('.', kStateDot);
+ return Nan();
+
+ case kStateZero:
+ if (ch == '0')
+ break;
+
+ if (ch >= '1' && ch <= '9') {
+ accumulator = ch - '0';
+ number_of_digits = 1;
+ state = kStateDigit;
+ break;
+ }
+
+ HandleCharAndBreak('.', kStateDot);
+ HandleTwoCharsAndBreak('E', 'e', kStateE);
+ return Nan();
+
+ default:
+ NOTREACHED();
+ return Nan();
+ }
+ }
+
+ if (state == kStateZero)
+ return Zero(sign);
+
+ if (state == kStateDigit || state == kStateEDigit ||
+ state == kStateDotDigit) {
+ int result_exponent = exponent * (exponent_sign == kNegative ? -1 : 1) -
+ number_of_digits_after_dot + number_of_extra_digits;
+ if (result_exponent < kExponentMin)
+ return Zero(kPositive);
+
+ const int overflow = result_exponent - kExponentMax + 1;
+ if (overflow > 0) {
+ if (overflow + number_of_digits - number_of_digits_after_dot > kPrecision)
+ return Infinity(sign);
+ accumulator = ScaleUp(accumulator, overflow);
+ result_exponent -= overflow;
+ }
+
+ return Decimal(sign, result_exponent, accumulator);
+ }
+
+ return Nan();
+}
+
+Decimal Decimal::Infinity(const Sign sign) {
+ return Decimal(EncodedData(sign, EncodedData::kClassInfinity));
+}
+
+Decimal Decimal::Nan() {
+ return Decimal(EncodedData(kPositive, EncodedData::kClassNaN));
+}
+
+Decimal Decimal::Remainder(const Decimal& rhs) const {
+ const Decimal quotient = *this / rhs;
+ return quotient.IsSpecial()
+ ? quotient
+ : *this - (quotient.IsNegative() ? quotient.Ceil()
+ : quotient.Floor()) *
+ rhs;
+}
+
+Decimal Decimal::Round() const {
+ if (IsSpecial())
+ return *this;
+
+ if (Exponent() >= 0)
+ return *this;
+
+ uint64_t result = data_.Coefficient();
+ const int number_of_digits = CountDigits(result);
+ const int number_of_drop_digits = -Exponent();
+ if (number_of_digits < number_of_drop_digits)
+ return Zero(kPositive);
+
+ result = ScaleDown(result, number_of_drop_digits - 1);
+ if (result % 10 >= 5)
+ result += 10;
+ result /= 10;
+ return Decimal(GetSign(), 0, result);
+}
+
+double Decimal::ToDouble() const {
+ if (IsFinite()) {
+ bool valid;
+ const double double_value = ToString().ToDouble(&valid);
+ return valid ? double_value : std::numeric_limits<double>::quiet_NaN();
+ }
+
+ if (IsInfinity())
+ return IsNegative() ? -std::numeric_limits<double>::infinity()
+ : std::numeric_limits<double>::infinity();
+
+ return std::numeric_limits<double>::quiet_NaN();
+}
+
+String Decimal::ToString() const {
+ switch (data_.GetFormatClass()) {
+ case EncodedData::kClassInfinity:
+ return GetSign() ? "-Infinity" : "Infinity";
+
+ case EncodedData::kClassNaN:
+ return "NaN";
+
+ case EncodedData::kClassNormal:
+ case EncodedData::kClassZero:
+ break;
+
+ default:
+ NOTREACHED();
+ return "";
+ }
+
+ StringBuilder builder;
+ if (GetSign())
+ builder.Append('-');
+
+ int original_exponent = Exponent();
+ uint64_t coefficient = data_.Coefficient();
+
+ if (original_exponent < 0) {
+ const int kMaxDigits = DBL_DIG;
+ uint64_t last_digit = 0;
+ while (CountDigits(coefficient) > kMaxDigits) {
+ last_digit = coefficient % 10;
+ coefficient /= 10;
+ ++original_exponent;
+ }
+
+ if (last_digit >= 5)
+ ++coefficient;
+
+ while (original_exponent < 0 && coefficient && !(coefficient % 10)) {
+ coefficient /= 10;
+ ++original_exponent;
+ }
+ }
+
+ const String digits = String::Number(coefficient);
+ int coefficient_length = static_cast<int>(digits.length());
+ const int adjusted_exponent = original_exponent + coefficient_length - 1;
+ if (original_exponent <= 0 && adjusted_exponent >= -6) {
+ if (!original_exponent) {
+ builder.Append(digits);
+ return builder.ToString();
+ }
+
+ if (adjusted_exponent >= 0) {
+ for (int i = 0; i < coefficient_length; ++i) {
+ builder.Append(digits[i]);
+ if (i == adjusted_exponent)
+ builder.Append('.');
+ }
+ return builder.ToString();
+ }
+
+ builder.Append("0.");
+ for (int i = adjusted_exponent + 1; i < 0; ++i)
+ builder.Append('0');
+
+ builder.Append(digits);
+
+ } else {
+ builder.Append(digits[0]);
+ while (coefficient_length >= 2 && digits[coefficient_length - 1] == '0')
+ --coefficient_length;
+ if (coefficient_length >= 2) {
+ builder.Append('.');
+ for (int i = 1; i < coefficient_length; ++i)
+ builder.Append(digits[i]);
+ }
+
+ if (adjusted_exponent) {
+ builder.Append(adjusted_exponent < 0 ? "e" : "e+");
+ builder.AppendNumber(adjusted_exponent);
+ }
+ }
+ return builder.ToString();
+}
+
+Decimal Decimal::Zero(Sign sign) {
+ return Decimal(EncodedData(sign, EncodedData::kClassZero));
+}
+
+std::ostream& operator<<(std::ostream& ostream, const Decimal& decimal) {
+ Decimal::EncodedData data = decimal.Value();
+ return ostream << "encode("
+ << String::Number(data.Coefficient()).Ascii().data() << ", "
+ << String::Number(data.Exponent()).Ascii().data() << ", "
+ << (data.GetSign() == Decimal::kNegative ? "Negative"
+ : "Positive")
+ << ")=" << decimal.ToString().Ascii().data();
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/wtf/decimal.h b/chromium/third_party/blink/renderer/platform/wtf/decimal.h
new file mode 100644
index 00000000000..48665c85c15
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/wtf/decimal.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DECIMAL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DECIMAL_H_
+
+#include <cstdint>
+
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/assertions.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+
+namespace blink {
+
+namespace DecimalPrivate {
+class SpecialValueHandler;
+}
+
+// This class represents decimal base floating point number.
+//
+// FIXME: Once all C++ compiler support decimal type, we should replace this
+// class to compiler supported one. See below URI for current status of decimal
+// type for C++:
+// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1977.html
+class WTF_EXPORT Decimal {
+ USING_FAST_MALLOC(Decimal);
+
+ public:
+ enum Sign {
+ kPositive,
+ kNegative,
+ };
+
+ // You should not use EncodedData other than unit testing.
+ class EncodedData {
+ DISALLOW_NEW();
+ // For accessing FormatClass.
+ friend class Decimal;
+ friend class DecimalPrivate::SpecialValueHandler;
+
+ public:
+ EncodedData(Sign, int exponent, uint64_t coefficient);
+
+ bool operator==(const EncodedData&) const;
+ bool operator!=(const EncodedData& another) const {
+ return !operator==(another);
+ }
+
+ uint64_t Coefficient() const { return coefficient_; }
+ int CountDigits() const;
+ int Exponent() const { return exponent_; }
+ bool IsFinite() const { return !IsSpecial(); }
+ bool IsInfinity() const { return format_class_ == kClassInfinity; }
+ bool IsNaN() const { return format_class_ == kClassNaN; }
+ bool IsSpecial() const {
+ return format_class_ == kClassInfinity || format_class_ == kClassNaN;
+ }
+ bool IsZero() const { return format_class_ == kClassZero; }
+ Sign GetSign() const { return sign_; }
+ void SetSign(Sign sign) { sign_ = sign; }
+
+ private:
+ enum FormatClass {
+ kClassInfinity,
+ kClassNormal,
+ kClassNaN,
+ kClassZero,
+ };
+
+ EncodedData(Sign, FormatClass);
+ FormatClass GetFormatClass() const { return format_class_; }
+
+ uint64_t coefficient_;
+ int16_t exponent_;
+ FormatClass format_class_;
+ Sign sign_;
+ };
+
+ Decimal(int32_t = 0);
+ Decimal(Sign, int exponent, uint64_t coefficient);
+ Decimal(const Decimal&);
+
+ Decimal& operator=(const Decimal&);
+ Decimal& operator+=(const Decimal&);
+ Decimal& operator-=(const Decimal&);
+ Decimal& operator*=(const Decimal&);
+ Decimal& operator/=(const Decimal&);
+
+ Decimal operator-() const;
+
+ bool operator==(const Decimal&) const;
+ bool operator!=(const Decimal&) const;
+ bool operator<(const Decimal&) const;
+ bool operator<=(const Decimal&) const;
+ bool operator>(const Decimal&) const;
+ bool operator>=(const Decimal&) const;
+
+ Decimal operator+(const Decimal&) const;
+ Decimal operator-(const Decimal&) const;
+ Decimal operator*(const Decimal&)const;
+ Decimal operator/(const Decimal&) const;
+
+ int Exponent() const {
+ DCHECK(IsFinite());
+ return data_.Exponent();
+ }
+
+ bool IsFinite() const { return data_.IsFinite(); }
+ bool IsInfinity() const { return data_.IsInfinity(); }
+ bool IsNaN() const { return data_.IsNaN(); }
+ bool IsNegative() const { return GetSign() == kNegative; }
+ bool IsPositive() const { return GetSign() == kPositive; }
+ bool IsSpecial() const { return data_.IsSpecial(); }
+ bool IsZero() const { return data_.IsZero(); }
+
+ Decimal Abs() const;
+ Decimal Ceil() const;
+ Decimal Floor() const;
+ Decimal Remainder(const Decimal&) const;
+ Decimal Round() const;
+
+ double ToDouble() const;
+ // Note: toString method supports infinity and nan but fromString not.
+ String ToString() const;
+
+ static Decimal FromDouble(double);
+ // fromString supports following syntax EBNF:
+ // number ::= sign? digit+ ('.' digit*) (exponent-marker sign? digit+)?
+ // | sign? '.' digit+ (exponent-marker sign? digit+)?
+ // sign ::= '+' | '-'
+ // exponent-marker ::= 'e' | 'E'
+ // digit ::= '0' | '1' | ... | '9'
+ // Note: fromString doesn't support "infinity" and "nan".
+ static Decimal FromString(const String&);
+ static Decimal Infinity(Sign);
+ static Decimal Nan();
+ static Decimal Zero(Sign);
+
+ // You should not use below methods. We expose them for unit testing.
+ explicit Decimal(const EncodedData&);
+ const EncodedData& Value() const { return data_; }
+
+ private:
+ struct AlignedOperands {
+ uint64_t lhs_coefficient;
+ uint64_t rhs_coefficient;
+ int exponent;
+ };
+
+ Decimal(double);
+ Decimal CompareTo(const Decimal&) const;
+
+ static AlignedOperands AlignOperands(const Decimal& lhs, const Decimal& rhs);
+ static inline Sign InvertSign(Sign sign) {
+ return sign == kNegative ? kPositive : kNegative;
+ }
+
+ Sign GetSign() const { return data_.GetSign(); }
+
+ EncodedData data_;
+};
+
+WTF_EXPORT std::ostream& operator<<(std::ostream&, const Decimal&);
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_DECIMAL_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/decimal_test.cc b/chromium/third_party/blink/renderer/platform/wtf/decimal_test.cc
new file mode 100644
index 00000000000..da5330e0707
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/wtf/decimal_test.cc
@@ -0,0 +1,1162 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "third_party/blink/renderer/platform/wtf/decimal.h"
+
+#include <cfloat>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/wtf/math_extras.h"
+#include "third_party/blink/renderer/platform/wtf/text/cstring.h"
+
+namespace blink {
+
+// Simulate core/html/forms/StepRange
+class DecimalStepRange {
+ public:
+ Decimal maximum;
+ Decimal minimum;
+ Decimal step;
+
+ DecimalStepRange(const Decimal& minimum,
+ const Decimal& maximum,
+ const Decimal& step)
+ : maximum(maximum), minimum(minimum), step(step) {}
+
+ Decimal ClampValue(Decimal value) const {
+ const Decimal result = minimum + ((value - minimum) / step).Round() * step;
+ DCHECK(result.IsFinite());
+ return result > maximum ? result - step : result;
+ }
+};
+
+class DecimalTest : public testing::Test {
+ protected:
+ using Sign = Decimal::Sign;
+ static const Sign kPositive = Decimal::kPositive;
+ static const Sign kNegative = Decimal::kNegative;
+
+ Decimal Encode(uint64_t coefficient, int exponent, Sign sign) {
+ return Decimal(sign, exponent, coefficient);
+ }
+
+ Decimal FromString(const String& string) {
+ return Decimal::FromString(string);
+ }
+
+ Decimal StepDown(const String& minimum,
+ const String& maximum,
+ const String& step,
+ const String& value_string,
+ int number_of_step_times) {
+ DecimalStepRange step_range(FromString(minimum), FromString(maximum),
+ FromString(step));
+ Decimal value = FromString(value_string);
+ for (int i = 0; i < number_of_step_times; ++i) {
+ value -= step_range.step;
+ value = step_range.ClampValue(value);
+ }
+ return value;
+ }
+
+ Decimal StepUp(const String& minimum,
+ const String& maximum,
+ const String& step,
+ const String& value_string,
+ int number_of_step_times) {
+ DecimalStepRange step_range(FromString(minimum), FromString(maximum),
+ FromString(step));
+ Decimal value = FromString(value_string);
+ for (int i = 0; i < number_of_step_times; ++i) {
+ value += step_range.step;
+ value = step_range.ClampValue(value);
+ }
+ return value;
+ }
+};
+
+// FIXME: We should use expectedSign without "Decimal::", however, g++ causes
+// undefined references for DecimalTest::Positive and Negative.
+#define EXPECT_DECIMAL_ENCODED_DATA_EQ(expectedCoefficient, expectedExponent, \
+ expectedSign, decimal) \
+ EXPECT_EQ((expectedCoefficient), (decimal).Value().Coefficient()); \
+ EXPECT_EQ((expectedExponent), (decimal).Value().Exponent()); \
+ EXPECT_EQ(Decimal::expectedSign, (decimal).Value().GetSign());
+
+#define EXPECT_DECIMAL_STREQ(expected, decimal) \
+ EXPECT_STREQ((expected), (decimal).ToString().Ascii().data())
+
+TEST_F(DecimalTest, Abs) {
+ EXPECT_EQ(Encode(0, 0, kPositive), Encode(0, 0, kPositive).Abs());
+ EXPECT_EQ(Encode(0, 0, kPositive), Encode(0, 0, kNegative).Abs());
+
+ EXPECT_EQ(Encode(0, 10, kPositive), Encode(0, 10, kPositive).Abs());
+ EXPECT_EQ(Encode(0, 10, kPositive), Encode(0, 10, kNegative).Abs());
+
+ EXPECT_EQ(Encode(0, -10, kPositive), Encode(0, -10, kPositive).Abs());
+ EXPECT_EQ(Encode(0, -10, kPositive), Encode(0, -10, kNegative).Abs());
+
+ EXPECT_EQ(Encode(1, 0, kPositive), Encode(1, 0, kPositive).Abs());
+ EXPECT_EQ(Encode(1, 0, kPositive), Encode(1, 0, kNegative).Abs());
+
+ EXPECT_EQ(Encode(1, 10, kPositive), Encode(1, 10, kPositive).Abs());
+ EXPECT_EQ(Encode(1, 10, kPositive), Encode(1, 10, kNegative).Abs());
+
+ EXPECT_EQ(Encode(1, -10, kPositive), Encode(1, -10, kPositive).Abs());
+ EXPECT_EQ(Encode(1, -10, kPositive), Encode(1, -10, kNegative).Abs());
+}
+
+TEST_F(DecimalTest, AbsBigExponent) {
+ EXPECT_EQ(Encode(1, 1000, kPositive), Encode(1, 1000, kPositive).Abs());
+ EXPECT_EQ(Encode(1, 1000, kPositive), Encode(1, 1000, kNegative).Abs());
+}
+
+TEST_F(DecimalTest, AbsSmallExponent) {
+ EXPECT_EQ(Encode(1, -1000, kPositive), Encode(1, -1000, kPositive).Abs());
+ EXPECT_EQ(Encode(1, -1000, kPositive), Encode(1, -1000, kNegative).Abs());
+}
+
+TEST_F(DecimalTest, AbsSpecialValues) {
+ EXPECT_EQ(Decimal::Infinity(kPositive), Decimal::Infinity(kPositive).Abs());
+ EXPECT_EQ(Decimal::Infinity(kPositive), Decimal::Infinity(kNegative).Abs());
+ EXPECT_EQ(Decimal::Nan(), Decimal::Nan().Abs());
+}
+
+TEST_F(DecimalTest, Add) {
+ EXPECT_EQ(Encode(0, 0, kPositive), Decimal(0) + Decimal(0));
+ EXPECT_EQ(Decimal(1), Decimal(2) + Decimal(-1));
+ EXPECT_EQ(Decimal(1), Decimal(-1) + Decimal(2));
+ EXPECT_EQ(Encode(100, 0, kPositive), Decimal(99) + Decimal(1));
+ EXPECT_EQ(Encode(100, 0, kNegative), Decimal(-50) + Decimal(-50));
+ EXPECT_EQ(Encode(UINT64_C(1000000000000000), 35, kPositive),
+ Encode(1, 50, kPositive) + Decimal(1));
+ EXPECT_EQ(Encode(UINT64_C(1000000000000000), 35, kPositive),
+ Decimal(1) + Encode(1, 50, kPositive));
+ EXPECT_EQ(Encode(UINT64_C(10000000001), 0, kPositive),
+ Encode(1, 10, kPositive) + Decimal(1));
+ EXPECT_EQ(Encode(UINT64_C(10000000001), 0, kPositive),
+ Decimal(1) + Encode(1, 10, kPositive));
+ EXPECT_EQ(Encode(1, 0, kPositive),
+ Encode(1, -1022, kPositive) + Encode(1, 0, kPositive));
+ EXPECT_EQ(Encode(2, -1022, kPositive),
+ Encode(1, -1022, kPositive) + Encode(1, -1022, kPositive));
+}
+
+TEST_F(DecimalTest, AddBigExponent) {
+ EXPECT_EQ(Encode(1, 1022, kPositive),
+ Encode(1, 1022, kPositive) + Encode(1, 0, kPositive));
+ EXPECT_EQ(Encode(2, 1022, kPositive),
+ Encode(1, 1022, kPositive) + Encode(1, 1022, kPositive));
+ EXPECT_EQ(Decimal::Infinity(kPositive),
+ Encode(std::numeric_limits<uint64_t>::max(), 1022, kPositive) +
+ Encode(1, 0, kPositive));
+ EXPECT_EQ(Encode(1, 1022, kPositive),
+ Encode(1, 1022, kPositive) + Encode(1, -1000, kPositive));
+}
+
+TEST_F(DecimalTest, AddSmallExponent) {
+ EXPECT_EQ(Encode(1, 0, kPositive),
+ Encode(1, -1022, kPositive) + Encode(1, 0, kPositive));
+ EXPECT_EQ(Encode(2, -1022, kPositive),
+ Encode(1, -1022, kPositive) + Encode(1, -1022, kPositive));
+}
+
+TEST_F(DecimalTest, AddSpecialValues) {
+ const Decimal infinity(Decimal::Infinity(kPositive));
+ const Decimal minus_infinity(Decimal::Infinity(kNegative));
+ const Decimal na_n(Decimal::Nan());
+ const Decimal ten(10);
+
+ EXPECT_EQ(infinity, infinity + infinity);
+ EXPECT_EQ(na_n, infinity + minus_infinity);
+ EXPECT_EQ(na_n, minus_infinity + infinity);
+ EXPECT_EQ(minus_infinity, minus_infinity + minus_infinity);
+
+ EXPECT_EQ(infinity, infinity + ten);
+ EXPECT_EQ(infinity, ten + infinity);
+ EXPECT_EQ(minus_infinity, minus_infinity + ten);
+ EXPECT_EQ(minus_infinity, ten + minus_infinity);
+
+ EXPECT_EQ(na_n, na_n + na_n);
+ EXPECT_EQ(na_n, na_n + ten);
+ EXPECT_EQ(na_n, ten + na_n);
+
+ EXPECT_EQ(na_n, na_n - infinity);
+ EXPECT_EQ(na_n, na_n - minus_infinity);
+ EXPECT_EQ(na_n, infinity - na_n);
+ EXPECT_EQ(na_n, minus_infinity - na_n);
+}
+
+TEST_F(DecimalTest, Ceil) {
+ EXPECT_EQ(Decimal(1), Decimal(1).Ceil());
+ EXPECT_EQ(Decimal(1), Encode(1, -10, kPositive).Ceil());
+ EXPECT_EQ(Decimal(2), Encode(11, -1, kPositive).Ceil());
+ EXPECT_EQ(Decimal(2), Encode(13, -1, kPositive).Ceil());
+ EXPECT_EQ(Decimal(2), Encode(15, -1, kPositive).Ceil());
+ EXPECT_EQ(Decimal(2), Encode(19, -1, kPositive).Ceil());
+ EXPECT_EQ(Decimal(2), Encode(151, -2, kPositive).Ceil());
+ EXPECT_EQ(Decimal(2), Encode(101, -2, kPositive).Ceil());
+ EXPECT_EQ(Decimal(1), Encode(199, -3, kPositive).Ceil());
+ EXPECT_EQ(Decimal(2), Encode(199, -2, kPositive).Ceil());
+ EXPECT_EQ(Decimal(3), Encode(209, -2, kPositive).Ceil());
+
+ EXPECT_EQ(Decimal(-1), Decimal(-1).Ceil());
+ EXPECT_EQ(Decimal(0), Encode(1, -10, kNegative).Ceil());
+ EXPECT_EQ(Decimal(-1), Encode(11, -1, kNegative).Ceil());
+ EXPECT_EQ(Decimal(-1), Encode(13, -1, kNegative).Ceil());
+ EXPECT_EQ(Decimal(-1), Encode(15, -1, kNegative).Ceil());
+ EXPECT_EQ(Decimal(-1), Encode(19, -1, kNegative).Ceil());
+ EXPECT_EQ(Decimal(-1), Encode(151, -2, kNegative).Ceil());
+ EXPECT_EQ(Decimal(-1), Encode(101, -2, kNegative).Ceil());
+ EXPECT_EQ(Decimal(0), Encode(199, -3, kNegative).Ceil());
+ EXPECT_EQ(Decimal(-1), Encode(199, -2, kNegative).Ceil());
+ EXPECT_EQ(Decimal(-2), Encode(209, -2, kNegative).Ceil());
+ EXPECT_EQ(Decimal(1),
+ Encode(UINT64_C(123456789012345678), -18, kPositive).Ceil());
+}
+
+TEST_F(DecimalTest, CeilingBigExponent) {
+ EXPECT_EQ(Encode(1, 1000, kPositive), Encode(1, 1000, kPositive).Ceil());
+ EXPECT_EQ(Encode(1, 1000, kNegative), Encode(1, 1000, kNegative).Ceil());
+}
+
+TEST_F(DecimalTest, CeilingSmallExponent) {
+ EXPECT_EQ(Encode(1, 0, kPositive), Encode(1, -1000, kPositive).Ceil());
+ EXPECT_EQ(Encode(0, 0, kNegative), Encode(1, -1000, kNegative).Ceil());
+}
+
+TEST_F(DecimalTest, CeilingSpecialValues) {
+ EXPECT_EQ(Decimal::Infinity(kPositive), Decimal::Infinity(kPositive).Ceil());
+ EXPECT_EQ(Decimal::Infinity(kNegative), Decimal::Infinity(kNegative).Ceil());
+ EXPECT_EQ(Decimal::Nan(), Decimal::Nan().Ceil());
+}
+
+TEST_F(DecimalTest, Compare) {
+ EXPECT_TRUE(Decimal(0) == Decimal(0));
+ EXPECT_TRUE(Decimal(0) != Decimal(1));
+ EXPECT_TRUE(Decimal(0) < Decimal(1));
+ EXPECT_TRUE(Decimal(0) <= Decimal(0));
+ EXPECT_TRUE(Decimal(0) > Decimal(-1));
+ EXPECT_TRUE(Decimal(0) >= Decimal(0));
+
+ EXPECT_FALSE(Decimal(1) == Decimal(2));
+ EXPECT_FALSE(Decimal(1) != Decimal(1));
+ EXPECT_FALSE(Decimal(1) < Decimal(0));
+ EXPECT_FALSE(Decimal(1) <= Decimal(0));
+ EXPECT_FALSE(Decimal(1) > Decimal(2));
+ EXPECT_FALSE(Decimal(1) >= Decimal(2));
+}
+
+TEST_F(DecimalTest, CompareBigExponent) {
+ EXPECT_TRUE(Encode(1, 1000, kPositive) == Encode(1, 1000, kPositive));
+ EXPECT_FALSE(Encode(1, 1000, kPositive) != Encode(1, 1000, kPositive));
+ EXPECT_FALSE(Encode(1, 1000, kPositive) < Encode(1, 1000, kPositive));
+ EXPECT_TRUE(Encode(1, 1000, kPositive) <= Encode(1, 1000, kPositive));
+ EXPECT_FALSE(Encode(1, 1000, kPositive) > Encode(1, 1000, kPositive));
+ EXPECT_TRUE(Encode(1, 1000, kPositive) >= Encode(1, 1000, kPositive));
+
+ EXPECT_TRUE(Encode(1, 1000, kNegative) == Encode(1, 1000, kNegative));
+ EXPECT_FALSE(Encode(1, 1000, kNegative) != Encode(1, 1000, kNegative));
+ EXPECT_FALSE(Encode(1, 1000, kNegative) < Encode(1, 1000, kNegative));
+ EXPECT_TRUE(Encode(1, 1000, kNegative) <= Encode(1, 1000, kNegative));
+ EXPECT_FALSE(Encode(1, 1000, kNegative) > Encode(1, 1000, kNegative));
+ EXPECT_TRUE(Encode(1, 1000, kNegative) >= Encode(1, 1000, kNegative));
+
+ EXPECT_FALSE(Encode(2, 1000, kPositive) == Encode(1, 1000, kPositive));
+ EXPECT_TRUE(Encode(2, 1000, kPositive) != Encode(1, 1000, kPositive));
+ EXPECT_FALSE(Encode(2, 1000, kPositive) < Encode(1, 1000, kPositive));
+ EXPECT_FALSE(Encode(2, 1000, kPositive) <= Encode(1, 1000, kPositive));
+ EXPECT_TRUE(Encode(2, 1000, kPositive) > Encode(1, 1000, kPositive));
+ EXPECT_TRUE(Encode(2, 1000, kPositive) >= Encode(1, 1000, kPositive));
+
+ EXPECT_FALSE(Encode(2, 1000, kNegative) == Encode(1, 1000, kNegative));
+ EXPECT_TRUE(Encode(2, 1000, kNegative) != Encode(1, 1000, kNegative));
+ EXPECT_TRUE(Encode(2, 1000, kNegative) < Encode(1, 1000, kNegative));
+ EXPECT_TRUE(Encode(2, 1000, kNegative) <= Encode(1, 1000, kNegative));
+ EXPECT_FALSE(Encode(2, 1000, kNegative) > Encode(1, 1000, kNegative));
+ EXPECT_FALSE(Encode(2, 1000, kNegative) >= Encode(1, 1000, kNegative));
+}
+
+TEST_F(DecimalTest, CompareSmallExponent) {
+ EXPECT_TRUE(Encode(1, -1000, kPositive) == Encode(1, -1000, kPositive));
+ EXPECT_FALSE(Encode(1, -1000, kPositive) != Encode(1, -1000, kPositive));
+ EXPECT_FALSE(Encode(1, -1000, kPositive) < Encode(1, -1000, kPositive));
+ EXPECT_TRUE(Encode(1, -1000, kPositive) <= Encode(1, -1000, kPositive));
+ EXPECT_FALSE(Encode(1, -1000, kPositive) > Encode(1, -1000, kPositive));
+ EXPECT_TRUE(Encode(1, -1000, kPositive) >= Encode(1, -1000, kPositive));
+
+ EXPECT_TRUE(Encode(1, -1000, kNegative) == Encode(1, -1000, kNegative));
+ EXPECT_FALSE(Encode(1, -1000, kNegative) != Encode(1, -1000, kNegative));
+ EXPECT_FALSE(Encode(1, -1000, kNegative) < Encode(1, -1000, kNegative));
+ EXPECT_TRUE(Encode(1, -1000, kNegative) <= Encode(1, -1000, kNegative));
+ EXPECT_FALSE(Encode(1, -1000, kNegative) > Encode(1, -1000, kNegative));
+ EXPECT_TRUE(Encode(1, -1000, kNegative) >= Encode(1, -1000, kNegative));
+
+ EXPECT_FALSE(Encode(2, -1000, kPositive) == Encode(1, -1000, kPositive));
+ EXPECT_TRUE(Encode(2, -1000, kPositive) != Encode(1, -1000, kPositive));
+ EXPECT_FALSE(Encode(2, -1000, kPositive) < Encode(1, -1000, kPositive));
+ EXPECT_FALSE(Encode(2, -1000, kPositive) <= Encode(1, -1000, kPositive));
+ EXPECT_TRUE(Encode(2, -1000, kPositive) > Encode(1, -1000, kPositive));
+ EXPECT_TRUE(Encode(2, -1000, kPositive) >= Encode(1, -1000, kPositive));
+
+ EXPECT_FALSE(Encode(2, -1000, kNegative) == Encode(1, -1000, kNegative));
+ EXPECT_TRUE(Encode(2, -1000, kNegative) != Encode(1, -1000, kNegative));
+ EXPECT_TRUE(Encode(2, -1000, kNegative) < Encode(1, -1000, kNegative));
+ EXPECT_TRUE(Encode(2, -1000, kNegative) <= Encode(1, -1000, kNegative));
+ EXPECT_FALSE(Encode(2, -1000, kNegative) > Encode(1, -1000, kNegative));
+ EXPECT_FALSE(Encode(2, -1000, kNegative) >= Encode(1, -1000, kNegative));
+}
+
+TEST_F(DecimalTest, CompareSpecialValues) {
+ const Decimal infinity(Decimal::Infinity(kPositive));
+ const Decimal minus_infinity(Decimal::Infinity(kNegative));
+ const Decimal na_n(Decimal::Nan());
+ const Decimal zero(Decimal::Zero(kPositive));
+ const Decimal minus_zero(Decimal::Zero(kNegative));
+ const Decimal ten(10);
+
+ EXPECT_TRUE(zero == zero);
+ EXPECT_FALSE(zero != zero);
+ EXPECT_FALSE(zero < zero);
+ EXPECT_TRUE(zero <= zero);
+ EXPECT_FALSE(zero > zero);
+ EXPECT_TRUE(zero >= zero);
+
+ EXPECT_TRUE(zero == minus_zero);
+ EXPECT_FALSE(zero != minus_zero);
+ EXPECT_FALSE(zero < minus_zero);
+ EXPECT_TRUE(zero <= minus_zero);
+ EXPECT_FALSE(zero > minus_zero);
+ EXPECT_TRUE(zero >= minus_zero);
+
+ EXPECT_TRUE(minus_zero == zero);
+ EXPECT_FALSE(minus_zero != zero);
+ EXPECT_FALSE(minus_zero < zero);
+ EXPECT_TRUE(minus_zero <= zero);
+ EXPECT_FALSE(minus_zero > zero);
+ EXPECT_TRUE(minus_zero >= zero);
+
+ EXPECT_TRUE(minus_zero == minus_zero);
+ EXPECT_FALSE(minus_zero != minus_zero);
+ EXPECT_FALSE(minus_zero < minus_zero);
+ EXPECT_TRUE(minus_zero <= minus_zero);
+ EXPECT_FALSE(minus_zero > minus_zero);
+ EXPECT_TRUE(minus_zero >= minus_zero);
+
+ EXPECT_TRUE(infinity == infinity);
+ EXPECT_FALSE(infinity != infinity);
+ EXPECT_FALSE(infinity < infinity);
+ EXPECT_TRUE(infinity <= infinity);
+ EXPECT_FALSE(infinity > infinity);
+ EXPECT_TRUE(infinity >= infinity);
+
+ EXPECT_FALSE(infinity == ten);
+ EXPECT_TRUE(infinity != ten);
+ EXPECT_FALSE(infinity < ten);
+ EXPECT_FALSE(infinity <= ten);
+ EXPECT_TRUE(infinity > ten);
+ EXPECT_TRUE(infinity >= ten);
+
+ EXPECT_FALSE(infinity == minus_infinity);
+ EXPECT_TRUE(infinity != minus_infinity);
+ EXPECT_FALSE(infinity < minus_infinity);
+ EXPECT_FALSE(infinity <= minus_infinity);
+ EXPECT_TRUE(infinity > minus_infinity);
+ EXPECT_TRUE(infinity >= minus_infinity);
+
+ EXPECT_FALSE(infinity == na_n);
+ EXPECT_FALSE(infinity != na_n);
+ EXPECT_FALSE(infinity < na_n);
+ EXPECT_FALSE(infinity <= na_n);
+ EXPECT_FALSE(infinity > na_n);
+ EXPECT_FALSE(infinity >= na_n);
+
+ EXPECT_FALSE(minus_infinity == infinity);
+ EXPECT_TRUE(minus_infinity != infinity);
+ EXPECT_TRUE(minus_infinity < infinity);
+ EXPECT_TRUE(minus_infinity <= infinity);
+ EXPECT_FALSE(minus_infinity > infinity);
+ EXPECT_FALSE(minus_infinity >= infinity);
+
+ EXPECT_FALSE(minus_infinity == ten);
+ EXPECT_TRUE(minus_infinity != ten);
+ EXPECT_TRUE(minus_infinity < ten);
+ EXPECT_TRUE(minus_infinity <= ten);
+ EXPECT_FALSE(minus_infinity > ten);
+ EXPECT_FALSE(minus_infinity >= ten);
+
+ EXPECT_TRUE(minus_infinity == minus_infinity);
+ EXPECT_FALSE(minus_infinity != minus_infinity);
+ EXPECT_FALSE(minus_infinity < minus_infinity);
+ EXPECT_TRUE(minus_infinity <= minus_infinity);
+ EXPECT_FALSE(minus_infinity > minus_infinity);
+ EXPECT_TRUE(minus_infinity >= minus_infinity);
+
+ EXPECT_FALSE(minus_infinity == na_n);
+ EXPECT_FALSE(minus_infinity != na_n);
+ EXPECT_FALSE(minus_infinity < na_n);
+ EXPECT_FALSE(minus_infinity <= na_n);
+ EXPECT_FALSE(minus_infinity > na_n);
+ EXPECT_FALSE(minus_infinity >= na_n);
+
+ EXPECT_FALSE(na_n == infinity);
+ EXPECT_FALSE(na_n != infinity);
+ EXPECT_FALSE(na_n < infinity);
+ EXPECT_FALSE(na_n <= infinity);
+ EXPECT_FALSE(na_n > infinity);
+ EXPECT_FALSE(na_n >= infinity);
+
+ EXPECT_FALSE(na_n == ten);
+ EXPECT_FALSE(na_n != ten);
+ EXPECT_FALSE(na_n < ten);
+ EXPECT_FALSE(na_n <= ten);
+ EXPECT_FALSE(na_n > ten);
+ EXPECT_FALSE(na_n >= ten);
+
+ EXPECT_FALSE(na_n == minus_infinity);
+ EXPECT_FALSE(na_n != minus_infinity);
+ EXPECT_FALSE(na_n < minus_infinity);
+ EXPECT_FALSE(na_n <= minus_infinity);
+ EXPECT_FALSE(na_n > minus_infinity);
+ EXPECT_FALSE(na_n >= minus_infinity);
+
+ EXPECT_TRUE(na_n == na_n);
+ EXPECT_FALSE(na_n != na_n);
+ EXPECT_FALSE(na_n < na_n);
+ EXPECT_TRUE(na_n <= na_n);
+ EXPECT_FALSE(na_n > na_n);
+ EXPECT_TRUE(na_n >= na_n);
+}
+
+TEST_F(DecimalTest, Constructor) {
+ EXPECT_DECIMAL_ENCODED_DATA_EQ(0u, 0, kPositive, Encode(0, 0, kPositive));
+ EXPECT_DECIMAL_ENCODED_DATA_EQ(0u, 0, kNegative, Encode(0, 0, kNegative));
+ EXPECT_DECIMAL_ENCODED_DATA_EQ(1u, 0, kPositive, Encode(1, 0, kPositive));
+ EXPECT_DECIMAL_ENCODED_DATA_EQ(1u, 0, kNegative, Encode(1, 0, kNegative));
+ EXPECT_DECIMAL_ENCODED_DATA_EQ(1u, 1022, kPositive,
+ Encode(1, 1022, kPositive));
+ EXPECT_DECIMAL_ENCODED_DATA_EQ(1u, 1022, kNegative,
+ Encode(1, 1022, kNegative));
+ EXPECT_DECIMAL_ENCODED_DATA_EQ(1u, 1023, kPositive,
+ Encode(1, 1023, kPositive));
+ EXPECT_DECIMAL_ENCODED_DATA_EQ(1u, 1023, kNegative,
+ Encode(1, 1023, kNegative));
+ EXPECT_TRUE(Encode(1, 2000, kPositive).IsInfinity());
+ EXPECT_TRUE(Encode(1, 2000, kNegative).IsInfinity());
+ EXPECT_DECIMAL_ENCODED_DATA_EQ(0u, 0, kPositive, Encode(1, -2000, kPositive));
+ EXPECT_DECIMAL_ENCODED_DATA_EQ(0u, 0, kNegative, Encode(1, -2000, kNegative));
+ EXPECT_DECIMAL_ENCODED_DATA_EQ(
+ UINT64_C(99999999999999998), 0, kPositive,
+ Encode(UINT64_C(99999999999999998), 0, kPositive));
+ EXPECT_DECIMAL_ENCODED_DATA_EQ(
+ UINT64_C(99999999999999998), 0, kNegative,
+ Encode(UINT64_C(99999999999999998), 0, kNegative));
+ EXPECT_DECIMAL_ENCODED_DATA_EQ(
+ UINT64_C(99999999999999999), 0, kPositive,
+ Encode(UINT64_C(99999999999999999), 0, kPositive));
+ EXPECT_DECIMAL_ENCODED_DATA_EQ(
+ UINT64_C(99999999999999999), 0, kNegative,
+ Encode(UINT64_C(99999999999999999), 0, kNegative));
+ EXPECT_DECIMAL_ENCODED_DATA_EQ(
+ UINT64_C(100000000000000000), 0, kPositive,
+ Encode(UINT64_C(100000000000000000), 0, kPositive));
+ EXPECT_DECIMAL_ENCODED_DATA_EQ(
+ UINT64_C(100000000000000000), 0, kNegative,
+ Encode(UINT64_C(100000000000000000), 0, kNegative));
+}
+
+TEST_F(DecimalTest, Division) {
+ EXPECT_EQ(Encode(0, 0, kPositive), Decimal(0) / Decimal(1));
+ EXPECT_EQ(Encode(2, 0, kNegative), Decimal(2) / Decimal(-1));
+ EXPECT_EQ(Encode(5, -1, kNegative), Decimal(-1) / Decimal(2));
+ EXPECT_EQ(Encode(99, 0, kPositive), Decimal(99) / Decimal(1));
+ EXPECT_EQ(Decimal(1), Decimal(-50) / Decimal(-50));
+ EXPECT_EQ(Encode(UINT64_C(333333333333333333), -18, kPositive),
+ Decimal(1) / Decimal(3));
+ EXPECT_EQ(Encode(UINT64_C(12345678901234), -1, kPositive),
+ Encode(UINT64_C(12345678901234), 0, kPositive) / Decimal(10));
+ EXPECT_EQ(Encode(UINT64_C(500005000050000500), -18, kPositive),
+ Decimal(50000) / Decimal(99999));
+}
+
+TEST_F(DecimalTest, DivisionBigExponent) {
+ EXPECT_EQ(Encode(1, 1022, kPositive),
+ Encode(1, 1022, kPositive) / Encode(1, 0, kPositive));
+ EXPECT_EQ(Encode(1, 0, kPositive),
+ Encode(1, 1022, kPositive) / Encode(1, 1022, kPositive));
+ EXPECT_EQ(Decimal::Infinity(kPositive),
+ Encode(1, 1022, kPositive) / Encode(1, -1000, kPositive));
+}
+
+TEST_F(DecimalTest, DivisionSmallExponent) {
+ EXPECT_EQ(Encode(1, -1022, kPositive),
+ Encode(1, -1022, kPositive) / Encode(1, 0, kPositive));
+ EXPECT_EQ(Encode(1, 0, kPositive),
+ Encode(1, -1022, kPositive) / Encode(1, -1022, kPositive));
+}
+
+TEST_F(DecimalTest, DivisionSpecialValues) {
+ const Decimal infinity(Decimal::Infinity(kPositive));
+ const Decimal minus_infinity(Decimal::Infinity(kNegative));
+ const Decimal na_n(Decimal::Nan());
+ const Decimal zero(Decimal::Zero(kPositive));
+ const Decimal minus_zero(Decimal::Zero(kNegative));
+ const Decimal ten(10);
+ const Decimal minus_ten(-10);
+
+ EXPECT_EQ(na_n, zero / zero);
+ EXPECT_EQ(na_n, zero / minus_zero);
+ EXPECT_EQ(na_n, minus_zero / zero);
+ EXPECT_EQ(na_n, minus_zero / minus_zero);
+
+ EXPECT_EQ(infinity, ten / zero);
+ EXPECT_EQ(minus_infinity, ten / minus_zero);
+ EXPECT_EQ(minus_infinity, minus_ten / zero);
+ EXPECT_EQ(infinity, minus_ten / minus_zero);
+
+ EXPECT_EQ(infinity, infinity / zero);
+ EXPECT_EQ(minus_infinity, infinity / minus_zero);
+ EXPECT_EQ(minus_infinity, minus_infinity / zero);
+ EXPECT_EQ(infinity, minus_infinity / minus_zero);
+
+ EXPECT_EQ(na_n, infinity / infinity);
+ EXPECT_EQ(na_n, infinity / minus_infinity);
+ EXPECT_EQ(na_n, minus_infinity / infinity);
+ EXPECT_EQ(na_n, minus_infinity / minus_infinity);
+
+ EXPECT_EQ(zero, ten / infinity);
+ EXPECT_EQ(minus_zero, ten / minus_infinity);
+ EXPECT_EQ(minus_zero, minus_ten / infinity);
+ EXPECT_EQ(zero, minus_ten / minus_infinity);
+
+ EXPECT_EQ(na_n, na_n / na_n);
+ EXPECT_EQ(na_n, na_n / ten);
+ EXPECT_EQ(na_n, ten / na_n);
+
+ EXPECT_EQ(na_n, na_n / infinity);
+ EXPECT_EQ(na_n, na_n / minus_infinity);
+ EXPECT_EQ(na_n, infinity / na_n);
+ EXPECT_EQ(na_n, minus_infinity / na_n);
+}
+
+TEST_F(DecimalTest, EncodedData) {
+ EXPECT_EQ(Encode(0, 0, kPositive), Encode(0, 0, kPositive));
+ EXPECT_EQ(Encode(0, 0, kNegative), Encode(0, 0, kNegative));
+ EXPECT_EQ(Decimal(1), Decimal(1));
+ EXPECT_EQ(Encode(1, 0, kNegative), Encode(1, 0, kNegative));
+ EXPECT_EQ(Decimal::Infinity(kPositive), Encode(1, 2000, kPositive));
+ EXPECT_EQ(Decimal::Zero(kPositive), Encode(1, -2000, kPositive));
+}
+
+TEST_F(DecimalTest, Floor) {
+ EXPECT_EQ(Decimal(1), Decimal(1).Floor());
+ EXPECT_EQ(Decimal(0), Encode(1, -10, kPositive).Floor());
+ EXPECT_EQ(Decimal(1), Encode(11, -1, kPositive).Floor());
+ EXPECT_EQ(Decimal(1), Encode(13, -1, kPositive).Floor());
+ EXPECT_EQ(Decimal(1), Encode(15, -1, kPositive).Floor());
+ EXPECT_EQ(Decimal(1), Encode(19, -1, kPositive).Floor());
+ EXPECT_EQ(Decimal(1), Encode(193332, -5, kPositive).Floor());
+ EXPECT_EQ(Decimal(12), Encode(12002, -3, kPositive).Floor());
+
+ EXPECT_EQ(Decimal(-1), Decimal(-1).Floor());
+ EXPECT_EQ(Decimal(-1), Encode(1, -10, kNegative).Floor());
+ EXPECT_EQ(Decimal(-2), Encode(11, -1, kNegative).Floor());
+ EXPECT_EQ(Decimal(-2), Encode(13, -1, kNegative).Floor());
+ EXPECT_EQ(Decimal(-2), Encode(15, -1, kNegative).Floor());
+ EXPECT_EQ(Decimal(-2), Encode(19, -1, kNegative).Floor());
+ EXPECT_EQ(Decimal(-2), Encode(193332, -5, kNegative).Floor());
+ EXPECT_EQ(Decimal(-13), Encode(12002, -3, kNegative).Floor());
+
+ // crbug.com/572769
+ EXPECT_EQ(Decimal(-1), Encode(992971299197409433, -18, kNegative).Floor());
+}
+
+TEST_F(DecimalTest, FloorBigExponent) {
+ EXPECT_EQ(Encode(1, 1000, kPositive), Encode(1, 1000, kPositive).Floor());
+ EXPECT_EQ(Encode(1, 1000, kNegative), Encode(1, 1000, kNegative).Floor());
+}
+
+TEST_F(DecimalTest, FloorSmallExponent) {
+ EXPECT_EQ(Encode(0, 0, kPositive), Encode(1, -1000, kPositive).Floor());
+ EXPECT_EQ(Encode(1, 0, kNegative), Encode(1, -1000, kNegative).Floor());
+}
+
+TEST_F(DecimalTest, FloorSpecialValues) {
+ EXPECT_EQ(Decimal::Infinity(kPositive), Decimal::Infinity(kPositive).Floor());
+ EXPECT_EQ(Decimal::Infinity(kNegative), Decimal::Infinity(kNegative).Floor());
+ EXPECT_EQ(Decimal::Nan(), Decimal::Nan().Floor());
+}
+
+TEST_F(DecimalTest, FromDouble) {
+ EXPECT_EQ(Encode(0, 0, kPositive), Decimal::FromDouble(0.0));
+ EXPECT_EQ(Encode(0, 0, kNegative), Decimal::FromDouble(-0.0));
+ EXPECT_EQ(Encode(1, 0, kPositive), Decimal::FromDouble(1));
+ EXPECT_EQ(Encode(1, 0, kNegative), Decimal::FromDouble(-1));
+ EXPECT_EQ(Encode(123, 0, kPositive), Decimal::FromDouble(123));
+ EXPECT_EQ(Encode(123, 0, kNegative), Decimal::FromDouble(-123));
+ EXPECT_EQ(Encode(1, -1, kPositive), Decimal::FromDouble(0.1));
+ EXPECT_EQ(Encode(1, -1, kNegative), Decimal::FromDouble(-0.1));
+}
+
+TEST_F(DecimalTest, FromDoubleLimits) {
+ EXPECT_EQ(Encode(UINT64_C(2220446049250313), -31, kPositive),
+ Decimal::FromDouble(std::numeric_limits<double>::epsilon()));
+ EXPECT_EQ(Encode(UINT64_C(2220446049250313), -31, kNegative),
+ Decimal::FromDouble(-std::numeric_limits<double>::epsilon()));
+ EXPECT_EQ(Encode(UINT64_C(17976931348623157), 292, kPositive),
+ Decimal::FromDouble(std::numeric_limits<double>::max()));
+ EXPECT_EQ(Encode(UINT64_C(17976931348623157), 292, kNegative),
+ Decimal::FromDouble(-std::numeric_limits<double>::max()));
+ EXPECT_EQ(Encode(UINT64_C(22250738585072014), -324, kPositive),
+ Decimal::FromDouble(std::numeric_limits<double>::min()));
+ EXPECT_EQ(Encode(UINT64_C(22250738585072014), -324, kNegative),
+ Decimal::FromDouble(-std::numeric_limits<double>::min()));
+ EXPECT_TRUE(Decimal::FromDouble(std::numeric_limits<double>::infinity())
+ .IsInfinity());
+ EXPECT_TRUE(Decimal::FromDouble(-std::numeric_limits<double>::infinity())
+ .IsInfinity());
+ EXPECT_TRUE(
+ Decimal::FromDouble(std::numeric_limits<double>::quiet_NaN()).IsNaN());
+ EXPECT_TRUE(
+ Decimal::FromDouble(-std::numeric_limits<double>::quiet_NaN()).IsNaN());
+}
+
+TEST_F(DecimalTest, FromInt32) {
+ EXPECT_EQ(Encode(0, 0, kPositive), Decimal(0));
+ EXPECT_EQ(Encode(1, 0, kPositive), Decimal(1));
+ EXPECT_EQ(Encode(1, 0, kNegative), Decimal(-1));
+ EXPECT_EQ(Encode(100, 0, kPositive), Decimal(100));
+ EXPECT_EQ(Encode(100, 0, kNegative), Decimal(-100));
+ EXPECT_EQ(Encode(0x7FFFFFFF, 0, kPositive),
+ Decimal(std::numeric_limits<int32_t>::max()));
+ EXPECT_EQ(Encode(0x80000000u, 0, kNegative),
+ Decimal(std::numeric_limits<int32_t>::min()));
+}
+
+TEST_F(DecimalTest, FromString) {
+ EXPECT_EQ(Encode(0, 0, kPositive), FromString("0"));
+ EXPECT_EQ(Encode(0, 0, kNegative), FromString("-0"));
+ EXPECT_EQ(Decimal(1), FromString("1"));
+ EXPECT_EQ(Encode(1, 0, kNegative), FromString("-1"));
+ EXPECT_EQ(Decimal(1), FromString("01"));
+ EXPECT_EQ(Encode(3, 0, kPositive), FromString("+3"));
+ EXPECT_EQ(Encode(0, 3, kPositive), FromString("0E3"));
+ EXPECT_EQ(Encode(5, -1, kPositive), FromString(".5"));
+ EXPECT_EQ(Encode(100, 0, kPositive), FromString("100"));
+ EXPECT_EQ(Encode(100, 0, kNegative), FromString("-100"));
+ EXPECT_EQ(Encode(123, -2, kPositive), FromString("1.23"));
+ EXPECT_EQ(Encode(123, -2, kNegative), FromString("-1.23"));
+ EXPECT_EQ(Encode(123, 8, kPositive), FromString("1.23E10"));
+ EXPECT_EQ(Encode(123, 8, kNegative), FromString("-1.23E10"));
+ EXPECT_EQ(Encode(123, 8, kPositive), FromString("1.23E+10"));
+ EXPECT_EQ(Encode(123, 8, kNegative), FromString("-1.23E+10"));
+ EXPECT_EQ(Encode(123, -12, kPositive), FromString("1.23E-10"));
+ EXPECT_EQ(Encode(123, -12, kNegative), FromString("-1.23E-10"));
+ EXPECT_EQ(Encode(5, -7, kPositive), FromString("0.0000005"));
+ EXPECT_EQ(Encode(0, 0, kPositive), FromString("0e9999"));
+ EXPECT_EQ(Encode(123, -3, kPositive), FromString("0.123"));
+ EXPECT_EQ(Encode(0, -2, kPositive), FromString("00.00"));
+ EXPECT_EQ(Encode(1, 2, kPositive), FromString("1E2"));
+ EXPECT_EQ(Decimal::Infinity(kPositive), FromString("1E20000"));
+ EXPECT_EQ(Decimal::Zero(kPositive), FromString("1E-20000"));
+ EXPECT_EQ(Encode(1000, 1023, kPositive), FromString("1E1026"));
+ EXPECT_EQ(Decimal::Zero(kPositive), FromString("1E-1026"));
+ EXPECT_EQ(Decimal::Infinity(kPositive), FromString("1234567890E1036"));
+
+ // 2^1024
+ const uint64_t kLeadingDigitsOf2PowerOf1024 = UINT64_C(17976931348623159);
+ EXPECT_EQ(Encode(kLeadingDigitsOf2PowerOf1024, 292, kPositive),
+ FromString("1797693134862315907729305190789024733617976978942306572"
+ "7343008115773267580550096313270847732240753602112011387"
+ "9871393357658789768814416622492847430639474124377767893"
+ "4248654852763022196012460941194530829520850057688381506"
+ "8234246288147391311054082723716335051068458629823994724"
+ "5938479716304835356329624224137216"));
+}
+
+// These strings are look like proper number, but we don't accept them.
+TEST_F(DecimalTest, FromStringLikeNumber) {
+ EXPECT_EQ(Decimal::Nan(), FromString(" 123 "));
+ EXPECT_EQ(Decimal::Nan(), FromString("1,234"));
+}
+
+// fromString doesn't support infinity and NaN.
+TEST_F(DecimalTest, FromStringSpecialValues) {
+ EXPECT_EQ(Decimal::Nan(), FromString("INF"));
+ EXPECT_EQ(Decimal::Nan(), FromString("Infinity"));
+ EXPECT_EQ(Decimal::Nan(), FromString("infinity"));
+ EXPECT_EQ(Decimal::Nan(), FromString("+Infinity"));
+ EXPECT_EQ(Decimal::Nan(), FromString("+infinity"));
+ EXPECT_EQ(Decimal::Nan(), FromString("-Infinity"));
+ EXPECT_EQ(Decimal::Nan(), FromString("-infinity"));
+ EXPECT_EQ(Decimal::Nan(), FromString("NaN"));
+ EXPECT_EQ(Decimal::Nan(), FromString("nan"));
+ EXPECT_EQ(Decimal::Nan(), FromString("+NaN"));
+ EXPECT_EQ(Decimal::Nan(), FromString("+nan"));
+ EXPECT_EQ(Decimal::Nan(), FromString("-NaN"));
+ EXPECT_EQ(Decimal::Nan(), FromString("-nan"));
+}
+
+TEST_F(DecimalTest, fromStringTruncated) {
+ EXPECT_EQ(Decimal::Nan(), FromString("x"));
+ EXPECT_EQ(Decimal::Nan(), FromString("0."));
+ EXPECT_EQ(Decimal::Nan(), FromString("1x"));
+
+ EXPECT_EQ(Decimal::Nan(), FromString("1Ex"));
+ EXPECT_EQ(Decimal::Nan(), FromString("1E2x"));
+ EXPECT_EQ(Decimal::Nan(), FromString("1E+x"));
+}
+
+TEST_F(DecimalTest, Multiplication) {
+ EXPECT_EQ(Encode(0, 0, kPositive), Decimal(0) * Decimal(0));
+ EXPECT_EQ(Encode(2, 0, kNegative), Decimal(2) * Decimal(-1));
+ EXPECT_EQ(Encode(2, 0, kNegative), Decimal(-1) * Decimal(2));
+ EXPECT_EQ(Encode(99, 0, kPositive), Decimal(99) * Decimal(1));
+ EXPECT_EQ(Encode(2500, 0, kPositive), Decimal(-50) * Decimal(-50));
+ EXPECT_EQ(Encode(1, 21, kPositive),
+ Encode(UINT64_C(10000000000), 0, kPositive) *
+ Encode(UINT64_C(100000000000), 0, kPositive));
+}
+
+TEST_F(DecimalTest, MultiplicationBigExponent) {
+ EXPECT_EQ(Encode(1, 1022, kPositive),
+ Encode(1, 1022, kPositive) * Encode(1, 0, kPositive));
+ EXPECT_EQ(Decimal::Infinity(kPositive),
+ Encode(1, 1022, kPositive) * Encode(1, 1022, kPositive));
+ EXPECT_EQ(Encode(1, 22, kPositive),
+ Encode(1, 1022, kPositive) * Encode(1, -1000, kPositive));
+}
+
+TEST_F(DecimalTest, MultiplicationSmallExponent) {
+ EXPECT_EQ(Encode(1, -1022, kPositive),
+ Encode(1, -1022, kPositive) * Encode(1, 0, kPositive));
+ EXPECT_EQ(Encode(0, 0, kPositive),
+ Encode(1, -1022, kPositive) * Encode(1, -1022, kPositive));
+}
+
+TEST_F(DecimalTest, MultiplicationSpecialValues) {
+ const Decimal infinity(Decimal::Infinity(kPositive));
+ const Decimal minus_infinity(Decimal::Infinity(kNegative));
+ const Decimal na_n(Decimal::Nan());
+ const Decimal ten(10);
+ const Decimal minus_ten(-10);
+ const Decimal zero(Decimal::Zero(kPositive));
+ const Decimal minus_zero(Decimal::Zero(kNegative));
+
+ EXPECT_EQ(infinity, infinity * infinity);
+ EXPECT_EQ(minus_infinity, infinity * minus_infinity);
+ EXPECT_EQ(minus_infinity, minus_infinity * infinity);
+ EXPECT_EQ(infinity, minus_infinity * minus_infinity);
+
+ EXPECT_EQ(na_n, infinity * zero);
+ EXPECT_EQ(na_n, zero * minus_infinity);
+ EXPECT_EQ(na_n, minus_infinity * zero);
+ EXPECT_EQ(na_n, minus_infinity * zero);
+
+ EXPECT_EQ(na_n, infinity * minus_zero);
+ EXPECT_EQ(na_n, minus_zero * minus_infinity);
+ EXPECT_EQ(na_n, minus_infinity * minus_zero);
+ EXPECT_EQ(na_n, minus_infinity * minus_zero);
+
+ EXPECT_EQ(infinity, infinity * ten);
+ EXPECT_EQ(infinity, ten * infinity);
+ EXPECT_EQ(minus_infinity, minus_infinity * ten);
+ EXPECT_EQ(minus_infinity, ten * minus_infinity);
+
+ EXPECT_EQ(minus_infinity, infinity * minus_ten);
+ EXPECT_EQ(minus_infinity, minus_ten * infinity);
+ EXPECT_EQ(infinity, minus_infinity * minus_ten);
+ EXPECT_EQ(infinity, minus_ten * minus_infinity);
+
+ EXPECT_EQ(na_n, na_n * na_n);
+ EXPECT_EQ(na_n, na_n * ten);
+ EXPECT_EQ(na_n, ten * na_n);
+
+ EXPECT_EQ(na_n, na_n * infinity);
+ EXPECT_EQ(na_n, na_n * minus_infinity);
+ EXPECT_EQ(na_n, infinity * na_n);
+ EXPECT_EQ(na_n, minus_infinity * na_n);
+}
+
+TEST_F(DecimalTest, Negate) {
+ EXPECT_EQ(Encode(0, 0, kNegative), -Encode(0, 0, kPositive));
+ EXPECT_EQ(Encode(0, 0, kPositive), -Encode(0, 0, kNegative));
+
+ EXPECT_EQ(Encode(0, 10, kNegative), -Encode(0, 10, kPositive));
+ EXPECT_EQ(Encode(0, 10, kPositive), -Encode(0, 10, kNegative));
+
+ EXPECT_EQ(Encode(0, -10, kNegative), -Encode(0, -10, kPositive));
+ EXPECT_EQ(Encode(0, -10, kPositive), -Encode(0, -10, kNegative));
+
+ EXPECT_EQ(Encode(1, 0, kNegative), -Encode(1, 0, kPositive));
+ EXPECT_EQ(Encode(1, 0, kPositive), -Encode(1, 0, kNegative));
+
+ EXPECT_EQ(Encode(1, 10, kNegative), -Encode(1, 10, kPositive));
+ EXPECT_EQ(Encode(1, 10, kPositive), -Encode(1, 10, kNegative));
+
+ EXPECT_EQ(Encode(1, -10, kNegative), -Encode(1, -10, kPositive));
+ EXPECT_EQ(Encode(1, -10, kPositive), -Encode(1, -10, kNegative));
+}
+
+TEST_F(DecimalTest, NegateBigExponent) {
+ EXPECT_EQ(Encode(1, 1000, kNegative), -Encode(1, 1000, kPositive));
+ EXPECT_EQ(Encode(1, 1000, kPositive), -Encode(1, 1000, kNegative));
+}
+
+TEST_F(DecimalTest, NegateSmallExponent) {
+ EXPECT_EQ(Encode(1, -1000, kNegative), -Encode(1, -1000, kPositive));
+ EXPECT_EQ(Encode(1, -1000, kPositive), -Encode(1, -1000, kNegative));
+}
+
+TEST_F(DecimalTest, NegateSpecialValues) {
+ EXPECT_EQ(Decimal::Infinity(kNegative), -Decimal::Infinity(kPositive));
+ EXPECT_EQ(Decimal::Infinity(kPositive), -Decimal::Infinity(kNegative));
+ EXPECT_EQ(Decimal::Nan(), -Decimal::Nan());
+}
+
+TEST_F(DecimalTest, Predicates) {
+ EXPECT_TRUE(Decimal::Zero(kPositive).IsFinite());
+ EXPECT_FALSE(Decimal::Zero(kPositive).IsInfinity());
+ EXPECT_FALSE(Decimal::Zero(kPositive).IsNaN());
+ EXPECT_TRUE(Decimal::Zero(kPositive).IsPositive());
+ EXPECT_FALSE(Decimal::Zero(kPositive).IsNegative());
+ EXPECT_FALSE(Decimal::Zero(kPositive).IsSpecial());
+ EXPECT_TRUE(Decimal::Zero(kPositive).IsZero());
+
+ EXPECT_TRUE(Decimal::Zero(kNegative).IsFinite());
+ EXPECT_FALSE(Decimal::Zero(kNegative).IsInfinity());
+ EXPECT_FALSE(Decimal::Zero(kNegative).IsNaN());
+ EXPECT_FALSE(Decimal::Zero(kNegative).IsPositive());
+ EXPECT_TRUE(Decimal::Zero(kNegative).IsNegative());
+ EXPECT_FALSE(Decimal::Zero(kNegative).IsSpecial());
+ EXPECT_TRUE(Decimal::Zero(kNegative).IsZero());
+
+ EXPECT_TRUE(Decimal(123).IsFinite());
+ EXPECT_FALSE(Decimal(123).IsInfinity());
+ EXPECT_FALSE(Decimal(123).IsNaN());
+ EXPECT_TRUE(Decimal(123).IsPositive());
+ EXPECT_FALSE(Decimal(123).IsNegative());
+ EXPECT_FALSE(Decimal(123).IsSpecial());
+ EXPECT_FALSE(Decimal(123).IsZero());
+
+ EXPECT_TRUE(Decimal(-123).IsFinite());
+ EXPECT_FALSE(Decimal(-123).IsInfinity());
+ EXPECT_FALSE(Decimal(-123).IsNaN());
+ EXPECT_FALSE(Decimal(-123).IsPositive());
+ EXPECT_TRUE(Decimal(-123).IsNegative());
+ EXPECT_FALSE(Decimal(-123).IsSpecial());
+ EXPECT_FALSE(Decimal(-123).IsZero());
+}
+
+TEST_F(DecimalTest, PredicatesSpecialValues) {
+ EXPECT_FALSE(Decimal::Infinity(kPositive).IsFinite());
+ EXPECT_TRUE(Decimal::Infinity(kPositive).IsInfinity());
+ EXPECT_FALSE(Decimal::Infinity(kPositive).IsNaN());
+ EXPECT_TRUE(Decimal::Infinity(kPositive).IsPositive());
+ EXPECT_FALSE(Decimal::Infinity(kPositive).IsNegative());
+ EXPECT_TRUE(Decimal::Infinity(kPositive).IsSpecial());
+ EXPECT_FALSE(Decimal::Infinity(kPositive).IsZero());
+
+ EXPECT_FALSE(Decimal::Infinity(kNegative).IsFinite());
+ EXPECT_TRUE(Decimal::Infinity(kNegative).IsInfinity());
+ EXPECT_FALSE(Decimal::Infinity(kNegative).IsNaN());
+ EXPECT_FALSE(Decimal::Infinity(kNegative).IsPositive());
+ EXPECT_TRUE(Decimal::Infinity(kNegative).IsNegative());
+ EXPECT_TRUE(Decimal::Infinity(kNegative).IsSpecial());
+ EXPECT_FALSE(Decimal::Infinity(kNegative).IsZero());
+
+ EXPECT_FALSE(Decimal::Nan().IsFinite());
+ EXPECT_FALSE(Decimal::Nan().IsInfinity());
+ EXPECT_TRUE(Decimal::Nan().IsNaN());
+ EXPECT_TRUE(Decimal::Nan().IsSpecial());
+ EXPECT_FALSE(Decimal::Nan().IsZero());
+}
+
+// LayoutTests/fast/forms/number/number-stepup-stepdown-from-renderer
+TEST_F(DecimalTest, RealWorldExampleNumberStepUpStepDownFromRenderer) {
+ EXPECT_DECIMAL_STREQ("10", StepDown("0", "100", "10", "19", 1));
+ EXPECT_DECIMAL_STREQ("90", StepUp("0", "99", "10", "89", 1));
+ EXPECT_DECIMAL_STREQ(
+ "1", StepUp("0", "1", "0.33333333333333333", "0", 3)); // step=1/3
+ EXPECT_DECIMAL_STREQ("0.01", StepUp("0", "0.01", "0.0033333333333333333", "0",
+ 3)); // step=1/300
+ EXPECT_DECIMAL_STREQ(
+ "1", StepUp("0", "1", "0.003921568627450980", "0", 255)); // step=1/255
+ EXPECT_DECIMAL_STREQ("1", StepUp("0", "1", "0.1", "0", 10));
+}
+
+TEST_F(DecimalTest, RealWorldExampleNumberStepUpStepDownFromRendererRounding) {
+ EXPECT_DECIMAL_STREQ("5.015", StepUp("0", "100", "0.005", "5.005", 2));
+ EXPECT_DECIMAL_STREQ("5.06", StepUp("0", "100", "0.005", "5.005", 11));
+ EXPECT_DECIMAL_STREQ("5.065", StepUp("0", "100", "0.005", "5.005", 12));
+
+ EXPECT_DECIMAL_STREQ("5.015", StepUp("4", "9", "0.005", "5.005", 2));
+ EXPECT_DECIMAL_STREQ("5.06", StepUp("4", "9", "0.005", "5.005", 11));
+ EXPECT_DECIMAL_STREQ("5.065", StepUp("4", "9", "0.005", "5.005", 12));
+}
+
+TEST_F(DecimalTest, RealWorldExampleRangeStepUpStepDown) {
+ EXPECT_DECIMAL_STREQ("1e+38", StepUp("0", "1E38", "1", "1E38", 9));
+ EXPECT_DECIMAL_STREQ("1e+38", StepDown("0", "1E38", "1", "1E38", 9));
+}
+
+TEST_F(DecimalTest, Remainder) {
+ EXPECT_EQ(Encode(21, -1, kPositive), Encode(21, -1, kPositive).Remainder(3));
+ EXPECT_EQ(Decimal(1), Decimal(10).Remainder(3));
+ EXPECT_EQ(Decimal(1), Decimal(10).Remainder(-3));
+ EXPECT_EQ(Encode(1, 0, kNegative), Decimal(-10).Remainder(3));
+ EXPECT_EQ(Decimal(-1), Decimal(-10).Remainder(-3));
+ EXPECT_EQ(Encode(2, -1, kPositive), Encode(102, -1, kPositive).Remainder(1));
+ EXPECT_EQ(Encode(1, -1, kPositive),
+ Decimal(10).Remainder(Encode(3, -1, kPositive)));
+ EXPECT_EQ(Decimal(1),
+ Encode(36, -1, kPositive).Remainder(Encode(13, -1, kPositive)));
+ EXPECT_EQ(Encode(1, 86, kPositive),
+ (Encode(1234, 100, kPositive).Remainder(Decimal(3))));
+ EXPECT_EQ(Decimal(500), (Decimal(500).Remainder(1000)));
+ EXPECT_EQ(Decimal(-500), (Decimal(-500).Remainder(1000)));
+}
+
+TEST_F(DecimalTest, RemainderBigExponent) {
+ EXPECT_EQ(Encode(0, 1022, kPositive),
+ Encode(1, 1022, kPositive).Remainder(Encode(1, 0, kPositive)));
+ EXPECT_EQ(Encode(0, 1022, kPositive),
+ Encode(1, 1022, kPositive).Remainder(Encode(1, 1022, kPositive)));
+ EXPECT_EQ(Decimal::Infinity(kPositive),
+ Encode(1, 1022, kPositive).Remainder(Encode(1, -1000, kPositive)));
+}
+
+TEST_F(DecimalTest, RemainderSmallExponent) {
+ EXPECT_EQ(Encode(1, -1022, kPositive),
+ Encode(1, -1022, kPositive).Remainder(Encode(1, 0, kPositive)));
+ EXPECT_EQ(Encode(0, -1022, kPositive),
+ Encode(1, -1022, kPositive).Remainder(Encode(1, -1022, kPositive)));
+}
+
+TEST_F(DecimalTest, RemainderSpecialValues) {
+ EXPECT_EQ(Decimal::Infinity(kPositive),
+ Decimal::Infinity(kPositive).Remainder(1));
+ EXPECT_EQ(Decimal::Infinity(kNegative),
+ Decimal::Infinity(kNegative).Remainder(1));
+ EXPECT_EQ(Decimal::Nan(), Decimal::Nan().Remainder(1));
+
+ EXPECT_EQ(Decimal::Infinity(kNegative),
+ Decimal::Infinity(kPositive).Remainder(-1));
+ EXPECT_EQ(Decimal::Infinity(kPositive),
+ Decimal::Infinity(kNegative).Remainder(-1));
+ EXPECT_EQ(Decimal::Nan(), Decimal::Nan().Remainder(-1));
+
+ EXPECT_EQ(Decimal::Infinity(kPositive),
+ Decimal::Infinity(kPositive).Remainder(3));
+ EXPECT_EQ(Decimal::Infinity(kNegative),
+ Decimal::Infinity(kNegative).Remainder(3));
+ EXPECT_EQ(Decimal::Nan(), Decimal::Nan().Remainder(3));
+
+ EXPECT_EQ(Decimal::Infinity(kNegative),
+ Decimal::Infinity(kPositive).Remainder(-1));
+ EXPECT_EQ(Decimal::Infinity(kPositive),
+ Decimal::Infinity(kNegative).Remainder(-1));
+ EXPECT_EQ(Decimal::Nan(), Decimal::Nan().Remainder(-1));
+
+ EXPECT_EQ(Decimal::Nan(), Decimal(1).Remainder(Decimal::Infinity(kPositive)));
+ EXPECT_EQ(Decimal::Nan(), Decimal(1).Remainder(Decimal::Infinity(kNegative)));
+ EXPECT_EQ(Decimal::Nan(), Decimal(1).Remainder(Decimal::Nan()));
+}
+
+TEST_F(DecimalTest, Round) {
+ EXPECT_EQ(Decimal(1), (Decimal(9) / Decimal(10)).Round());
+ EXPECT_EQ(Decimal(25), (Decimal(5) / FromString("0.200")).Round());
+ EXPECT_EQ(Decimal(3), (Decimal(5) / Decimal(2)).Round());
+ EXPECT_EQ(Decimal(1), (Decimal(2) / Decimal(3)).Round());
+ EXPECT_EQ(Decimal(3), (Decimal(10) / Decimal(3)).Round());
+ EXPECT_EQ(Decimal(3), (Decimal(1) / FromString("0.3")).Round());
+ EXPECT_EQ(Decimal(10), (Decimal(1) / FromString("0.1")).Round());
+ EXPECT_EQ(Decimal(5), (Decimal(1) / FromString("0.2")).Round());
+ EXPECT_EQ(Decimal(10), (FromString("10.2") / 1).Round());
+ EXPECT_EQ(Encode(1234, 100, kPositive), Encode(1234, 100, kPositive).Round());
+
+ EXPECT_EQ(Decimal(2), Encode(190002, -5, kPositive).Round());
+ EXPECT_EQ(Decimal(2), Encode(150002, -5, kPositive).Round());
+ EXPECT_EQ(Decimal(2), Encode(150000, -5, kPositive).Round());
+ EXPECT_EQ(Decimal(12), Encode(12492, -3, kPositive).Round());
+ EXPECT_EQ(Decimal(13), Encode(12502, -3, kPositive).Round());
+
+ EXPECT_EQ(Decimal(-2), Encode(190002, -5, kNegative).Round());
+ EXPECT_EQ(Decimal(-2), Encode(150002, -5, kNegative).Round());
+ EXPECT_EQ(Decimal(-2), Encode(150000, -5, kNegative).Round());
+ EXPECT_EQ(Decimal(-12), Encode(12492, -3, kNegative).Round());
+ EXPECT_EQ(Decimal(-13), Encode(12502, -3, kNegative).Round());
+}
+
+TEST_F(DecimalTest, RoundSpecialValues) {
+ EXPECT_EQ(Decimal::Infinity(kPositive), Decimal::Infinity(kPositive).Round());
+ EXPECT_EQ(Decimal::Infinity(kNegative), Decimal::Infinity(kNegative).Round());
+ EXPECT_EQ(Decimal::Nan(), Decimal::Nan().Round());
+}
+
+TEST_F(DecimalTest, Subtract) {
+ EXPECT_EQ(Encode(0, 0, kPositive), Decimal(0) - Decimal(0));
+ EXPECT_EQ(Encode(3, 0, kPositive), Decimal(2) - Decimal(-1));
+ EXPECT_EQ(Encode(3, 0, kNegative), Decimal(-1) - Decimal(2));
+ EXPECT_EQ(Encode(98, 0, kPositive), Decimal(99) - Decimal(1));
+ EXPECT_EQ(Encode(0, 0, kPositive), Decimal(-50) - Decimal(-50));
+ EXPECT_EQ(Encode(UINT64_C(1000000000000000), 35, kPositive),
+ Encode(1, 50, kPositive) - Decimal(1));
+ EXPECT_EQ(Encode(UINT64_C(1000000000000000), 35, kNegative),
+ Decimal(1) - Encode(1, 50, kPositive));
+}
+
+TEST_F(DecimalTest, SubtractBigExponent) {
+ EXPECT_EQ(Encode(1, 1022, kPositive),
+ Encode(1, 1022, kPositive) - Encode(1, 0, kPositive));
+ EXPECT_EQ(Encode(0, 0, kPositive),
+ Encode(1, 1022, kPositive) - Encode(1, 1022, kPositive));
+ EXPECT_EQ(Encode(1, 1022, kPositive),
+ Encode(1, 1022, kPositive) + Encode(1, -1000, kPositive));
+}
+
+TEST_F(DecimalTest, SubtractSmallExponent) {
+ EXPECT_EQ(Encode(UINT64_C(10000000000000000), -16, kNegative),
+ Encode(1, -1022, kPositive) - Encode(1, 0, kPositive));
+ EXPECT_EQ(Encode(0, 0, kPositive),
+ Encode(1, -1022, kPositive) - Encode(1, -1022, kPositive));
+}
+
+TEST_F(DecimalTest, SubtractSpecialValues) {
+ const Decimal infinity(Decimal::Infinity(kPositive));
+ const Decimal minus_infinity(Decimal::Infinity(kNegative));
+ const Decimal na_n(Decimal::Nan());
+ const Decimal ten(10);
+
+ EXPECT_EQ(na_n, infinity - infinity);
+ EXPECT_EQ(infinity, infinity - minus_infinity);
+ EXPECT_EQ(minus_infinity, minus_infinity - infinity);
+ EXPECT_EQ(na_n, minus_infinity - minus_infinity);
+
+ EXPECT_EQ(infinity, infinity - ten);
+ EXPECT_EQ(minus_infinity, ten - infinity);
+ EXPECT_EQ(minus_infinity, minus_infinity - ten);
+ EXPECT_EQ(infinity, ten - minus_infinity);
+
+ EXPECT_EQ(na_n, na_n - na_n);
+ EXPECT_EQ(na_n, na_n - ten);
+ EXPECT_EQ(na_n, ten - na_n);
+
+ EXPECT_EQ(na_n, na_n - infinity);
+ EXPECT_EQ(na_n, na_n - minus_infinity);
+ EXPECT_EQ(na_n, infinity - na_n);
+ EXPECT_EQ(na_n, minus_infinity - na_n);
+}
+
+TEST_F(DecimalTest, ToDouble) {
+ EXPECT_EQ(0.0, Encode(0, 0, kPositive).ToDouble());
+ EXPECT_EQ(-0.0, Encode(0, 0, kNegative).ToDouble());
+
+ EXPECT_EQ(1.0, Encode(1, 0, kPositive).ToDouble());
+ EXPECT_EQ(-1.0, Encode(1, 0, kNegative).ToDouble());
+
+ EXPECT_EQ(0.1, Encode(1, -1, kPositive).ToDouble());
+ EXPECT_EQ(-0.1, Encode(1, -1, kNegative).ToDouble());
+ EXPECT_EQ(0.3, Encode(3, -1, kPositive).ToDouble());
+ EXPECT_EQ(-0.3, Encode(3, -1, kNegative).ToDouble());
+ EXPECT_EQ(0.6, Encode(6, -1, kPositive).ToDouble());
+ EXPECT_EQ(-0.6, Encode(6, -1, kNegative).ToDouble());
+ EXPECT_EQ(0.7, Encode(7, -1, kPositive).ToDouble());
+ EXPECT_EQ(-0.7, Encode(7, -1, kNegative).ToDouble());
+
+ EXPECT_EQ(0.01, Encode(1, -2, kPositive).ToDouble());
+ EXPECT_EQ(0.001, Encode(1, -3, kPositive).ToDouble());
+ EXPECT_EQ(0.0001, Encode(1, -4, kPositive).ToDouble());
+ EXPECT_EQ(0.00001, Encode(1, -5, kPositive).ToDouble());
+
+ EXPECT_EQ(1e+308, Encode(1, 308, kPositive).ToDouble());
+ EXPECT_EQ(1e-307, Encode(1, -307, kPositive).ToDouble());
+
+ EXPECT_TRUE(std::isinf(Encode(1, 1000, kPositive).ToDouble()));
+ EXPECT_EQ(0.0, Encode(1, -1000, kPositive).ToDouble());
+}
+
+TEST_F(DecimalTest, ToDoubleSpecialValues) {
+ EXPECT_TRUE(std::isinf(Decimal::Infinity(Decimal::kPositive).ToDouble()));
+ EXPECT_TRUE(std::isinf(Decimal::Infinity(Decimal::kNegative).ToDouble()));
+ EXPECT_TRUE(std::isnan(Decimal::Nan().ToDouble()));
+}
+
+TEST_F(DecimalTest, ToString) {
+ EXPECT_DECIMAL_STREQ("0", Decimal::Zero(kPositive));
+ EXPECT_DECIMAL_STREQ("-0", Decimal::Zero(kNegative));
+ EXPECT_DECIMAL_STREQ("1", Decimal(1));
+ EXPECT_DECIMAL_STREQ("-1", Decimal(-1));
+ EXPECT_DECIMAL_STREQ("1234567", Decimal(1234567));
+ EXPECT_DECIMAL_STREQ("-1234567", Decimal(-1234567));
+ EXPECT_DECIMAL_STREQ("0.5", Encode(5, -1, kPositive));
+ EXPECT_DECIMAL_STREQ("-0.5", Encode(5, -1, kNegative));
+ EXPECT_DECIMAL_STREQ("12.345", Encode(12345, -3, kPositive));
+ EXPECT_DECIMAL_STREQ("-12.345", Encode(12345, -3, kNegative));
+ EXPECT_DECIMAL_STREQ("0.12345", Encode(12345, -5, kPositive));
+ EXPECT_DECIMAL_STREQ("-0.12345", Encode(12345, -5, kNegative));
+ EXPECT_DECIMAL_STREQ("50", Encode(50, 0, kPositive));
+ EXPECT_DECIMAL_STREQ("-50", Encode(50, 0, kNegative));
+ EXPECT_DECIMAL_STREQ("5e+1", Encode(5, 1, kPositive));
+ EXPECT_DECIMAL_STREQ("-5e+1", Encode(5, 1, kNegative));
+ EXPECT_DECIMAL_STREQ("5.678e+103", Encode(5678, 100, kPositive));
+ EXPECT_DECIMAL_STREQ("-5.678e+103", Encode(5678, 100, kNegative));
+ EXPECT_DECIMAL_STREQ("5.678e-97", Encode(5678, -100, kPositive));
+ EXPECT_DECIMAL_STREQ("-5.678e-97", Encode(5678, -100, kNegative));
+ EXPECT_DECIMAL_STREQ("8639999913600001",
+ Encode(UINT64_C(8639999913600001), 0, kPositive));
+ EXPECT_DECIMAL_STREQ(
+ "9007199254740991",
+ Encode((static_cast<uint64_t>(1) << DBL_MANT_DIG) - 1, 0, kPositive));
+ EXPECT_DECIMAL_STREQ("99999999999999999",
+ Encode(UINT64_C(99999999999999999), 0, kPositive));
+ EXPECT_DECIMAL_STREQ("9.9999999999999999e+17",
+ Encode(UINT64_C(99999999999999999), 1, kPositive));
+ EXPECT_DECIMAL_STREQ("9.9999999999999999e+18",
+ Encode(UINT64_C(99999999999999999), 2, kPositive));
+ EXPECT_DECIMAL_STREQ("1e+16",
+ Encode(UINT64_C(99999999999999999), -1, kPositive));
+ EXPECT_DECIMAL_STREQ("1000000000000000",
+ Encode(UINT64_C(99999999999999999), -2, kPositive));
+ EXPECT_DECIMAL_STREQ("1",
+ Encode(UINT64_C(99999999999999999), -17, kPositive));
+ EXPECT_DECIMAL_STREQ("0.001",
+ Encode(UINT64_C(99999999999999999), -20, kPositive));
+ EXPECT_DECIMAL_STREQ("1e-83",
+ Encode(UINT64_C(99999999999999999), -100, kPositive));
+}
+
+TEST_F(DecimalTest, ToStringSpecialValues) {
+ EXPECT_DECIMAL_STREQ("Infinity", Decimal::Infinity(kPositive));
+ EXPECT_DECIMAL_STREQ("-Infinity", Decimal::Infinity(kNegative));
+ EXPECT_DECIMAL_STREQ("NaN", Decimal::Nan());
+}
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/wtf/deque.h b/chromium/third_party/blink/renderer/platform/wtf/deque.h
index b46b088e415..bdc041e0787 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/deque.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/deque.h
@@ -52,9 +52,7 @@ class DequeConstIterator;
template <typename T,
size_t inlineCapacity = 0,
typename Allocator = PartitionAllocator>
-class Deque : public ConditionalDestructor<Deque<T, INLINE_CAPACITY, Allocator>,
- (INLINE_CAPACITY == 0) &&
- Allocator::kIsGarbageCollected> {
+class Deque {
USE_ALLOCATOR(Deque, Allocator);
public:
@@ -68,9 +66,9 @@ class Deque : public ConditionalDestructor<Deque<T, INLINE_CAPACITY, Allocator>,
Deque& operator=(const Deque&);
Deque(Deque&&);
Deque& operator=(Deque&&);
+ ~Deque();
- void Finalize();
- void FinalizeGarbageCollectedObject() { Finalize(); }
+ void FinalizeGarbageCollectedObject() { NOTREACHED(); }
void Swap(Deque&);
@@ -371,18 +369,19 @@ inline void Deque<T, inlineCapacity, Allocator>::DestroyAll() {
}
}
-// Off-GC-heap deques: Destructor should be called.
-// On-GC-heap deques: Destructor should be called for inline buffers (if any)
-// but destructor shouldn't be called for vector backing since it is managed by
-// the traced GC heap.
+// For design of the destructor, please refer to
+// [here](https://docs.google.com/document/d/1AoGTvb3tNLx2tD1hNqAfLRLmyM59GM0O-7rCHTT_7_U/)
template <typename T, size_t inlineCapacity, typename Allocator>
-inline void Deque<T, inlineCapacity, Allocator>::Finalize() {
- if (!INLINE_CAPACITY && !buffer_.Buffer())
+inline Deque<T, inlineCapacity, Allocator>::~Deque() {
+ if ((!INLINE_CAPACITY && !buffer_.Buffer()))
return;
if (!IsEmpty() &&
!(Allocator::kIsGarbageCollected && buffer_.HasOutOfLineBuffer()))
DestroyAll();
+ // If this is called during sweeping, it must not touch the OutOfLineBuffer.
+ if (Allocator::IsSweepForbidden())
+ return;
buffer_.Destruct();
}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa.cc b/chromium/third_party/blink/renderer/platform/wtf/dtoa.cc
index ba12295637a..f2307278ff2 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/dtoa.cc
@@ -64,7 +64,6 @@ static inline const char* FormatStringTruncatingTrailingZerosIfNeeded(
break;
}
- // No decimal seperator found, early exit.
if (decimal_point_position == length)
return builder.Finalize();
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum-dtoa.cc b/chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum-dtoa.cc
index f86315822b6..00f8870d2b8 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum-dtoa.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/dtoa/bignum-dtoa.cc
@@ -595,7 +595,7 @@ static void InitialScaledStartValuesNegativeExponentNegativePower(
//
// Let ep == estimated_power, then the returned values will satisfy:
// v / 10^ep = numerator / denominator.
-// v's boundarys m- and m+:
+// v's boundaries m- and m+:
// m- / 10^ep == v / 10^ep - delta_minus / denominator
// m+ / 10^ep == v / 10^ep + delta_plus / denominator
// Or in other words:
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/double-conversion.h b/chromium/third_party/blink/renderer/platform/wtf/dtoa/double-conversion.h
index 173d49999e7..de48a646374 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/double-conversion.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/dtoa/double-conversion.h
@@ -98,7 +98,7 @@ class DoubleToStringConverter {
// Example with max_leading_padding_zeroes_in_precision_mode = 6.
// ToPrecision(0.0000012345, 2) -> "0.0000012"
// ToPrecision(0.00000012345, 2) -> "1.2e-7"
- // Similarily the converter may add up to
+ // Similarly the converter may add up to
// max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid
// returning an exponential representation. A zero added by the
// EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.
@@ -140,7 +140,7 @@ class DoubleToStringConverter {
// Example with decimal_in_shortest_low = -6,
// decimal_in_shortest_high = 21,
// EMIT_POSITIVE_EXPONENT_SIGN activated, and
- // EMIT_TRAILING_DECIMAL_POINT deactived:
+ // EMIT_TRAILING_DECIMAL_POINT deactivated:
// ToShortest(0.000001) -> "0.000001"
// ToShortest(0.0000001) -> "1e-7"
// ToShortest(111111111111111111111.0) -> "111111111111111110000"
@@ -236,7 +236,7 @@ class DoubleToStringConverter {
// Example with max_leading_padding_zeroes_in_precision_mode = 6.
// ToPrecision(0.0000012345, 2) -> "0.0000012"
// ToPrecision(0.00000012345, 2) -> "1.2e-7"
- // Similarily the converter may add up to
+ // Similarly the converter may add up to
// max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid
// returning an exponential representation. A zero added by the
// EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.
diff --git a/chromium/third_party/blink/renderer/platform/wtf/dtoa/fixed-dtoa.cc b/chromium/third_party/blink/renderer/platform/wtf/dtoa/fixed-dtoa.cc
index 693d84ea4e5..c99e19ce72a 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/dtoa/fixed-dtoa.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/dtoa/fixed-dtoa.cc
@@ -398,7 +398,7 @@ bool FastFixedDtoa(double v,
TrimZeros(buffer, length, decimal_point);
buffer[*length] = '\0';
if ((*length) == 0) {
- // The string is empty and the decimal_point thus has no importance. Mimick
+ // The string is empty and the decimal_point thus has no importance. Mimic
// Gay's dtoa and and set it to -fractional_count.
*decimal_point = -fractional_count;
}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/experimental/README.md b/chromium/third_party/blink/renderer/platform/wtf/experimental/README.md
index 0600fc88194..d2438d62097 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/experimental/README.md
+++ b/chromium/third_party/blink/renderer/platform/wtf/experimental/README.md
@@ -7,7 +7,7 @@ Don't use files in this directory without prior consent of the author.
## Experimental files policy
-The use of experimental files must be closely controled and monitored by
+The use of experimental files must be closely controlled and monitored by
the author. If any anomalies caused by files in this directory are observed,
please contact the author (essentially yutak@chromium.org) immediately.
diff --git a/chromium/third_party/blink/renderer/platform/wtf/experimental/container_type_operations_test.cc b/chromium/third_party/blink/renderer/platform/wtf/experimental/container_type_operations_test.cc
index dfd75956b99..4bf0ee80ce4 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/experimental/container_type_operations_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/experimental/container_type_operations_test.cc
@@ -33,7 +33,7 @@ TYPED_TEST_CASE_P(ContainerTypeOperationsTest);
TYPED_TEST_P(ContainerTypeOperationsTest, Completeness) {
using Ops = CompletedContainerTypeOperations<TypeParam>;
- // Call all funcions in Ops and make sure they are callable.
+ // Call all functions in Ops and make sure they are callable.
constexpr size_t SIZE = 4;
// We need to initialize the content of |data| to let the compiler think
diff --git a/chromium/third_party/blink/renderer/platform/wtf/hash_iterators.h b/chromium/third_party/blink/renderer/platform/wtf/hash_iterators.h
index fa6a563c6fc..2d1b0129070 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/hash_iterators.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/hash_iterators.h
@@ -68,6 +68,12 @@ struct HashTableConstIteratorAdapter<HashTableType,
}
// postfix ++ intentionally omitted
+ HashTableConstIteratorAdapter& operator--() {
+ --impl_;
+ return *this;
+ }
+ // postfix -- intentionally omitted
+
KeysIterator Keys() { return KeysIterator(*this); }
ValuesIterator Values() { return ValuesIterator(*this); }
@@ -102,6 +108,12 @@ struct HashTableIteratorAdapter<HashTableType,
}
// postfix ++ intentionally omitted
+ HashTableIteratorAdapter& operator--() {
+ --impl_;
+ return *this;
+ }
+ // postfix -- intentionally omitted
+
operator HashTableConstIteratorAdapter<HashTableType, ValueType>() {
typename HashTableType::const_iterator i = impl_;
return i;
@@ -135,6 +147,12 @@ struct HashTableConstKeysIterator {
}
// postfix ++ intentionally omitted
+ HashTableConstKeysIterator& operator--() {
+ --impl_;
+ return *this;
+ }
+ // postfix -- intentionally omitted
+
ConstIterator impl_;
};
@@ -160,6 +178,12 @@ struct HashTableConstValuesIterator {
}
// postfix ++ intentionally omitted
+ HashTableConstValuesIterator& operator--() {
+ --impl_;
+ return *this;
+ }
+ // postfix -- intentionally omitted
+
ConstIterator impl_;
};
@@ -188,6 +212,12 @@ struct HashTableKeysIterator {
}
// postfix ++ intentionally omitted
+ HashTableKeysIterator& operator--() {
+ --impl_;
+ return *this;
+ }
+ // postfix -- intentionally omitted
+
operator HashTableConstKeysIterator<HashTableType, KeyType, MappedType>() {
ConstIterator i = impl_;
return i;
@@ -221,6 +251,12 @@ struct HashTableValuesIterator {
}
// postfix ++ intentionally omitted
+ HashTableValuesIterator& operator--() {
+ --impl_;
+ return *this;
+ }
+ // postfix -- intentionally omitted
+
operator HashTableConstValuesIterator<HashTableType, KeyType, MappedType>() {
ConstIterator i = impl_;
return i;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/hash_map_test.cc b/chromium/third_party/blink/renderer/platform/wtf/hash_map_test.cc
index f9f187c6938..d1864f1c9fa 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/hash_map_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/hash_map_test.cc
@@ -59,6 +59,29 @@ TEST(HashMapTest, IteratorComparison) {
EXPECT_FALSE(map.end() == begin);
}
+TEST(HashMapTest, Iteration) {
+ IntHashMap map;
+ for (int i = 0; i < 10; ++i)
+ map.insert(1 << i, i);
+
+ int encountered_keys = 0, count = 0;
+ for (auto it = map.begin(); it != map.end(); ++it) {
+ encountered_keys |= it->key;
+ count++;
+ }
+ EXPECT_EQ(10, count);
+ EXPECT_EQ((1 << 10) - 1, encountered_keys);
+
+ encountered_keys = count = 0;
+ for (auto it = map.end(); it != map.begin();) {
+ --it;
+ encountered_keys |= it->key;
+ count++;
+ }
+ EXPECT_EQ(10, count);
+ EXPECT_EQ((1 << 10) - 1, encountered_keys);
+}
+
struct TestDoubleHashTraits : HashTraits<double> {
static const unsigned kMinimumTableSize = 8;
};
diff --git a/chromium/third_party/blink/renderer/platform/wtf/hash_set_test.cc b/chromium/third_party/blink/renderer/platform/wtf/hash_set_test.cc
index 98468aa16c1..968c7e5819c 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/hash_set_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/hash_set_test.cc
@@ -39,6 +39,46 @@ int* const CountCopy::kDeletedValue =
namespace {
+TEST(HashSetTest, IteratorComparison) {
+ HashSet<int> set;
+ set.insert(1);
+ EXPECT_TRUE(set.begin() != set.end());
+ EXPECT_FALSE(set.begin() == set.end());
+
+ HashSet<int>::const_iterator begin = set.begin();
+ EXPECT_TRUE(begin == set.begin());
+ EXPECT_TRUE(set.begin() == begin);
+ EXPECT_TRUE(begin != set.end());
+ EXPECT_TRUE(set.end() != begin);
+ EXPECT_FALSE(begin != set.begin());
+ EXPECT_FALSE(set.begin() != begin);
+ EXPECT_FALSE(begin == set.end());
+ EXPECT_FALSE(set.end() == begin);
+}
+
+TEST(HashSetTest, Iteration) {
+ HashSet<int> set;
+ for (int i = 0; i < 10; ++i)
+ set.insert(1 << i);
+
+ int encountered_keys = 0, count = 0;
+ for (auto it = set.begin(); it != set.end(); ++it) {
+ encountered_keys |= *it;
+ count++;
+ }
+ EXPECT_EQ(10, count);
+ EXPECT_EQ((1 << 10) - 1, encountered_keys);
+
+ encountered_keys = count = 0;
+ for (auto it = set.end(); it != set.begin();) {
+ --it;
+ encountered_keys |= *it;
+ count++;
+ }
+ EXPECT_EQ(10, count);
+ EXPECT_EQ((1 << 10) - 1, encountered_keys);
+}
+
template <unsigned size>
void TestReserveCapacity();
template <>
diff --git a/chromium/third_party/blink/renderer/platform/wtf/hash_table.h b/chromium/third_party/blink/renderer/platform/wtf/hash_table.h
index 7011104db03..f47d1d6a7f0 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/hash_table.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/hash_table.h
@@ -29,7 +29,6 @@
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/conditional_destructor.h"
#include "third_party/blink/renderer/platform/wtf/construct_traits.h"
#include "third_party/blink/renderer/platform/wtf/hash_traits.h"
@@ -295,13 +294,26 @@ class HashTableConstIterator final {
++position_;
}
+ void ReverseSkipEmptyBuckets() {
+ // Don't need to check for out-of-bounds positions, as begin position is
+ // always going to be a non-empty bucket.
+ while (HashTableType::IsEmptyOrDeletedBucket(*position_)) {
+#if DCHECK_IS_ON()
+ DCHECK_NE(position_, begin_position_);
+#endif
+ --position_;
+ }
+ }
+
HashTableConstIterator(PointerType position,
+ PointerType begin_position,
PointerType end_position,
const HashTableType* container)
: position_(position),
end_position_(end_position)
#if DCHECK_IS_ON()
,
+ begin_position_(begin_position),
container_(container),
container_modifications_(container->Modifications())
#endif
@@ -310,6 +322,7 @@ class HashTableConstIterator final {
}
HashTableConstIterator(PointerType position,
+ PointerType begin_position,
PointerType end_position,
const HashTableType* container,
HashItemKnownGoodTag)
@@ -317,6 +330,7 @@ class HashTableConstIterator final {
end_position_(end_position)
#if DCHECK_IS_ON()
,
+ begin_position_(begin_position),
container_(container),
container_modifications_(container->Modifications())
#endif
@@ -359,6 +373,18 @@ class HashTableConstIterator final {
// postfix ++ intentionally omitted
+ const_iterator& operator--() {
+#if DCHECK_IS_ON()
+ DCHECK_NE(position_, begin_position_);
+#endif
+ CheckModifications();
+ --position_;
+ ReverseSkipEmptyBuckets();
+ return *this;
+ }
+
+ // postfix -- intentionally omitted
+
// Comparison.
bool operator==(const const_iterator& other) const {
return position_ == other.position_;
@@ -385,6 +411,7 @@ class HashTableConstIterator final {
PointerType position_;
PointerType end_position_;
#if DCHECK_IS_ON()
+ PointerType begin_position_;
const HashTableType* container_;
int64_t container_modifications_;
#endif
@@ -456,14 +483,16 @@ class HashTableIterator final {
Allocator>;
HashTableIterator(PointerType pos,
+ PointerType begin,
PointerType end,
const HashTableType* container)
- : iterator_(pos, end, container) {}
+ : iterator_(pos, begin, end, container) {}
HashTableIterator(PointerType pos,
+ PointerType begin,
PointerType end,
const HashTableType* container,
HashItemKnownGoodTag tag)
- : iterator_(pos, end, container, tag) {}
+ : iterator_(pos, begin, end, container, tag) {}
public:
HashTableIterator() = default;
@@ -483,6 +512,13 @@ class HashTableIterator final {
// postfix ++ intentionally omitted
+ iterator& operator--() {
+ --iterator_;
+ return *this;
+ }
+
+ // postfix -- intentionally omitted
+
// Comparison.
bool operator==(const iterator& other) const {
return iterator_ == other.iterator_;
@@ -654,15 +690,7 @@ template <typename Key,
typename Traits,
typename KeyTraits,
typename Allocator>
-class HashTable final
- : public ConditionalDestructor<HashTable<Key,
- Value,
- Extractor,
- HashFunctions,
- Traits,
- KeyTraits,
- Allocator>,
- Allocator::kIsGarbageCollected> {
+class HashTable final {
DISALLOW_NEW();
public:
@@ -693,10 +721,16 @@ class HashTable final
typedef HashTableAddResult<HashTable, ValueType> AddResult;
HashTable();
- void Finalize() {
- DCHECK(!Allocator::kIsGarbageCollected);
+
+ // For design of the destructor, please refer to
+ // [here](https://docs.google.com/document/d/1AoGTvb3tNLx2tD1hNqAfLRLmyM59GM0O-7rCHTT_7_U/)
+ ~HashTable() {
if (LIKELY(!table_))
return;
+ // If this is called during sweeping, it must not touch other heap objects
+ // such as the backing.
+ if (Allocator::IsSweepForbidden())
+ return;
EnterAccessForbiddenScope();
DeleteAllBucketsAndDeallocate(table_, table_size_);
LeaveAccessForbiddenScope();
@@ -875,23 +909,25 @@ class HashTable final
}
iterator MakeIterator(ValueType* pos) {
- return iterator(pos, table_ + table_size_, this);
+ return iterator(pos, table_, table_ + table_size_, this);
}
const_iterator MakeConstIterator(const ValueType* pos) const {
- return const_iterator(pos, table_ + table_size_, this);
+ return const_iterator(pos, table_, table_ + table_size_, this);
}
iterator MakeKnownGoodIterator(ValueType* pos) {
- return iterator(pos, table_ + table_size_, this, kHashItemKnownGood);
+ return iterator(pos, table_, table_ + table_size_, this,
+ kHashItemKnownGood);
}
const_iterator MakeKnownGoodConstIterator(const ValueType* pos) const {
- return const_iterator(pos, table_ + table_size_, this, kHashItemKnownGood);
+ return const_iterator(pos, table_, table_ + table_size_, this,
+ kHashItemKnownGood);
}
static const unsigned kMaxLoad = 2;
static const unsigned kMinLoad = 6;
unsigned TableSizeMask() const {
- size_t mask = table_size_ - 1;
+ unsigned mask = table_size_ - 1;
DCHECK_EQ((mask & table_size_), 0u);
return mask;
}
@@ -2151,7 +2187,11 @@ struct HashTableConstIteratorAdapter {
return *this;
}
// postfix ++ intentionally omitted
-
+ HashTableConstIteratorAdapter& operator--() {
+ --impl_;
+ return *this;
+ }
+ // postfix -- intentionally omitted
typename HashTableType::const_iterator impl_;
};
@@ -2186,6 +2226,12 @@ struct HashTableIteratorAdapter {
}
// postfix ++ intentionally omitted
+ HashTableIteratorAdapter& operator--() {
+ --impl_;
+ return *this;
+ }
+ // postfix -- intentionally omitted
+
operator HashTableConstIteratorAdapter<HashTableType, Traits>() {
typename HashTableType::const_iterator i = impl_;
return i;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/list_hash_set.h b/chromium/third_party/blink/renderer/platform/wtf/list_hash_set.h
index 610bdff1b01..ddc89aa3809 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/list_hash_set.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/list_hash_set.h
@@ -76,10 +76,7 @@ template <typename ValueArg,
typename HashArg = typename DefaultHash<ValueArg>::Hash,
typename AllocatorArg =
ListHashSetAllocator<ValueArg, inlineCapacity>>
-class ListHashSet
- : public ConditionalDestructor<
- ListHashSet<ValueArg, inlineCapacity, HashArg, AllocatorArg>,
- AllocatorArg::kIsGarbageCollected> {
+class ListHashSet {
typedef AllocatorArg Allocator;
USE_ALLOCATOR(ListHashSet, Allocator);
@@ -149,7 +146,7 @@ class ListHashSet
ListHashSet(ListHashSet&&);
ListHashSet& operator=(const ListHashSet&);
ListHashSet& operator=(ListHashSet&&);
- void Finalize();
+ ~ListHashSet();
void Swap(ListHashSet&);
@@ -246,7 +243,6 @@ class ListHashSet
void CreateAllocatorIfNeeded() {
allocator_provider_.CreateAllocatorIfNeeded();
}
- void Deallocate(Node* node) const { allocator_provider_.deallocate(node); }
iterator MakeIterator(Node* position) { return iterator(this, position); }
const_iterator MakeConstIterator(Node* position) const {
@@ -311,11 +307,6 @@ struct ListHashSetAllocator : public PartitionAllocator {
std::swap(allocator_, other.allocator_);
}
- void Deallocate(Node* node) const {
- DCHECK(allocator_);
- allocator_->Deallocate(node);
- }
-
ListHashSetAllocator* Get() const {
DCHECK(allocator_);
return allocator_;
@@ -804,10 +795,14 @@ inline void ListHashSet<T, inlineCapacity, U, V>::Swap(ListHashSet& other) {
allocator_provider_.Swap(other.allocator_provider_);
}
+// For design of the destructor, please refer to
+// [here](https://docs.google.com/document/d/1AoGTvb3tNLx2tD1hNqAfLRLmyM59GM0O-7rCHTT_7_U/)
template <typename T, size_t inlineCapacity, typename U, typename V>
-inline void ListHashSet<T, inlineCapacity, U, V>::Finalize() {
- static_assert(!Allocator::kIsGarbageCollected,
- "heap allocated ListHashSet should never call finalize()");
+inline ListHashSet<T, inlineCapacity, U, V>::~ListHashSet() {
+ // If this is called during GC sweeping, it must not touch other heap objects
+ // such as the ListHashSetNodes that is touching in DeleteAllNodes().
+ if (Allocator::IsSweepForbidden())
+ return;
DeleteAllNodes();
allocator_provider_.ReleaseAllocator();
}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/math_extras.h b/chromium/third_party/blink/renderer/platform/wtf/math_extras.h
index 2e3d0749e3a..c090e11627f 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/math_extras.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/math_extras.h
@@ -48,69 +48,23 @@
#include <sys/types.h>
#endif
-const double piDouble = M_PI;
-const float piFloat = static_cast<float>(M_PI);
+const double kPiDouble = M_PI;
+const float kPiFloat = static_cast<float>(M_PI);
-const double piOverTwoDouble = M_PI_2;
-const float piOverTwoFloat = static_cast<float>(M_PI_2);
+const double kPiOverTwoDouble = M_PI_2;
+const float kPiOverTwoFloat = static_cast<float>(M_PI_2);
-const double piOverFourDouble = M_PI_4;
-const float piOverFourFloat = static_cast<float>(M_PI_4);
+const double kPiOverFourDouble = M_PI_4;
+const float kPiOverFourFloat = static_cast<float>(M_PI_4);
-const double twoPiDouble = piDouble * 2.0;
-const float twoPiFloat = piFloat * 2.0f;
-
-#if defined(COMPILER_MSVC)
-
-// VS2013 has most of the math functions now, but we still need to work
-// around various differences in behavior of Inf.
-
-// Work around a bug in Win, where atan2(+-infinity, +-infinity) yields NaN
-// instead of specific values.
-inline double wtf_atan2(double x, double y) {
- double posInf = std::numeric_limits<double>::infinity();
- double negInf = -std::numeric_limits<double>::infinity();
- double nan = std::numeric_limits<double>::quiet_NaN();
-
- double result = nan;
-
- if (x == posInf && y == posInf)
- result = piOverFourDouble;
- else if (x == posInf && y == negInf)
- result = 3 * piOverFourDouble;
- else if (x == negInf && y == posInf)
- result = -piOverFourDouble;
- else if (x == negInf && y == negInf)
- result = -3 * piOverFourDouble;
- else
- result = ::atan2(x, y);
-
- return result;
-}
-
-// Work around a bug in the Microsoft CRT, where fmod(x, +-infinity) yields NaN
-// instead of x.
-inline double wtf_fmod(double x, double y) {
- return (!std::isinf(x) && std::isinf(y)) ? x : fmod(x, y);
-}
-
-// Work around a bug in the Microsoft CRT, where pow(NaN, 0) yields NaN instead
-// of 1.
-inline double wtf_pow(double x, double y) {
- return y == 0 ? 1 : pow(x, y);
-}
-
-#define atan2(x, y) wtf_atan2(x, y)
-#define fmod(x, y) wtf_fmod(x, y)
-#define pow(x, y) wtf_pow(x, y)
-
-#endif // defined(COMPILER_MSVC)
+const double kTwoPiDouble = kPiDouble * 2.0;
+const float kTwoPiFloat = kPiFloat * 2.0f;
inline double deg2rad(double d) {
- return d * piDouble / 180.0;
+ return d * kPiDouble / 180.0;
}
inline double rad2deg(double r) {
- return r * 180.0 / piDouble;
+ return r * 180.0 / kPiDouble;
}
inline double deg2grad(double d) {
return d * 400.0 / 360.0;
@@ -125,10 +79,10 @@ inline double deg2turn(double d) {
return d / 360.0;
}
inline double rad2grad(double r) {
- return r * 200.0 / piDouble;
+ return r * 200.0 / kPiDouble;
}
inline double grad2rad(double g) {
- return g * piDouble / 200.0;
+ return g * kPiDouble / 200.0;
}
inline double turn2grad(double t) {
return t * 400;
@@ -137,17 +91,17 @@ inline double grad2turn(double g) {
return g / 400;
}
inline double rad2turn(double r) {
- return r / twoPiDouble;
+ return r / kTwoPiDouble;
}
inline double turn2rad(double t) {
- return t * twoPiDouble;
+ return t * kTwoPiDouble;
}
inline float deg2rad(float d) {
- return d * piFloat / 180.0f;
+ return d * kPiFloat / 180.0f;
}
inline float rad2deg(float r) {
- return r * 180.0f / piFloat;
+ return r * 180.0f / kPiFloat;
}
inline float deg2grad(float d) {
return d * 400.0f / 360.0f;
@@ -162,10 +116,10 @@ inline float deg2turn(float d) {
return d / 360.0f;
}
inline float rad2grad(float r) {
- return r * 200.0f / piFloat;
+ return r * 200.0f / kPiFloat;
}
inline float grad2rad(float g) {
- return g * piFloat / 200.0f;
+ return g * kPiFloat / 200.0f;
}
inline float turn2grad(float t) {
return t * 400;
@@ -383,60 +337,4 @@ inline size_t lowestCommonMultiple(size_t a, size_t b) {
return a && b ? a / greatestCommonDivisor(a, b) * b : 0;
}
-#ifndef UINT64_C
-#if defined(COMPILER_MSVC)
-#define UINT64_C(c) c##ui64
-#else
-#define UINT64_C(c) c##ull
-#endif
-#endif
-
-// Calculate d % 2^{64}.
-inline void doubleToInteger(double d, unsigned long long& value) {
- if (std::isnan(d) || std::isinf(d)) {
- value = 0;
- } else {
- // -2^{64} < fmodValue < 2^{64}.
- double fmodValue =
- fmod(trunc(d), std::numeric_limits<unsigned long long>::max() + 1.0);
- if (fmodValue >= 0) {
- // 0 <= fmodValue < 2^{64}.
- // 0 <= value < 2^{64}. This cast causes no loss.
- value = static_cast<unsigned long long>(fmodValue);
- } else {
- // -2^{64} < fmodValue < 0.
- // 0 < fmodValueInUnsignedLongLong < 2^{64}. This cast causes no loss.
- unsigned long long fmodValueInUnsignedLongLong =
- static_cast<unsigned long long>(-fmodValue);
- // -1 < (std::numeric_limits<unsigned long long>::max() -
- // fmodValueInUnsignedLongLong)
- // < 2^{64} - 1.
- // 0 < value < 2^{64}.
- value = std::numeric_limits<unsigned long long>::max() -
- fmodValueInUnsignedLongLong + 1;
- }
- }
-}
-
-namespace WTF {
-
-inline unsigned FastLog2(unsigned i) {
- unsigned log2 = 0;
- if (i & (i - 1))
- log2 += 1;
- if (i >> 16)
- log2 += 16, i >>= 16;
- if (i >> 8)
- log2 += 8, i >>= 8;
- if (i >> 4)
- log2 += 4, i >>= 4;
- if (i >> 2)
- log2 += 2, i >>= 2;
- if (i >> 1)
- log2 += 1;
- return log2;
-}
-
-} // namespace WTF
-
#endif // #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_MATH_EXTRAS_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/math_extras_test.cc b/chromium/third_party/blink/renderer/platform/wtf/math_extras_test.cc
index aedfb303757..e90ac4314da 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/math_extras_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/math_extras_test.cc
@@ -235,8 +235,8 @@ TEST(MathExtrasTest, clampToUnsignedLongLongUnsignedLongLong) {
clampTo<unsigned long long>(0xFFFFFFFFFFFFFFF5ULL));
}
-// Make sure that various +-inf cases are handled properly (they aren't
-// by default on VS).
+// Make sure that various +-inf cases are handled properly (they weren't
+// by default on older VS).
TEST(MathExtrasTest, infinityMath) {
double pos_inf = std::numeric_limits<double>::infinity();
double neg_inf = -std::numeric_limits<double>::infinity();
diff --git a/chromium/third_party/blink/renderer/platform/wtf/process_metrics.h b/chromium/third_party/blink/renderer/platform/wtf/process_metrics.h
deleted file mode 100644
index 3c5e18ae9a6..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/process_metrics.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_PROCESS_METRICS_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_PROCESS_METRICS_H_
-
-#include "base/process/process_metrics.h"
-
-namespace WTF {
-
-size_t GetMallocUsage() {
- std::unique_ptr<base::ProcessMetrics> metric(
- base::ProcessMetrics::CreateCurrentProcessMetrics());
- return metric->GetMallocUsage();
-}
-
-} // namespace WTF
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_PROCESS_METRICS_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/ref_ptr_test.cc b/chromium/third_party/blink/renderer/platform/wtf/ref_ptr_test.cc
deleted file mode 100644
index 4b8a2c93c39..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/ref_ptr_test.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/memory/scoped_refptr.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/wtf/ref_counted.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
-#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
-
-namespace WTF {
-namespace {
-
-TEST(RefPtrTest, Basic) {
- scoped_refptr<StringImpl> string;
- EXPECT_TRUE(!string);
- string = StringImpl::Create("test");
- EXPECT_TRUE(!!string);
- string = nullptr;
- EXPECT_TRUE(!string);
-}
-
-TEST(RefPtrTest, MoveAssignmentOperator) {
- scoped_refptr<StringImpl> a = StringImpl::Create("a");
- scoped_refptr<StringImpl> b = StringImpl::Create("b");
- b = std::move(a);
- EXPECT_TRUE(!!b);
- EXPECT_TRUE(!a);
-}
-
-class RefCountedClass : public RefCounted<RefCountedClass> {};
-
-TEST(RefPtrTest, ConstObject) {
- // This test is only to ensure we force the compilation of a const RefCounted
- // object to ensure the generated code compiles.
- scoped_refptr<const RefCountedClass> ptr_to_const =
- base::AdoptRef(new RefCountedClass());
-}
-
-class CustomDeleter;
-
-struct Deleter {
- static void Destruct(const CustomDeleter*);
-};
-
-class CustomDeleter : public RefCounted<CustomDeleter, Deleter> {
- public:
- explicit CustomDeleter(bool* deleted) : deleted_(deleted) {}
-
- private:
- friend struct Deleter;
- ~CustomDeleter() = default;
-
- bool* deleted_;
-};
-
-void Deleter::Destruct(const CustomDeleter* obj) {
- EXPECT_FALSE(*obj->deleted_);
- *obj->deleted_ = true;
- delete obj;
-}
-
-TEST(RefPtrTest, CustomDeleter) {
- bool deleted = false;
- scoped_refptr<CustomDeleter> obj =
- base::AdoptRef(new CustomDeleter(&deleted));
- EXPECT_FALSE(deleted);
- obj = nullptr;
- EXPECT_TRUE(deleted);
-}
-
-class CustomDeleterThreadSafe;
-
-struct DeleterThreadSafe {
- static void Destruct(const CustomDeleterThreadSafe*);
-};
-
-class CustomDeleterThreadSafe
- : public ThreadSafeRefCounted<CustomDeleterThreadSafe, DeleterThreadSafe> {
- public:
- explicit CustomDeleterThreadSafe(bool* deleted) : deleted_(deleted) {}
-
- private:
- friend struct DeleterThreadSafe;
- ~CustomDeleterThreadSafe() = default;
-
- bool* deleted_;
-};
-
-void DeleterThreadSafe::Destruct(const CustomDeleterThreadSafe* obj) {
- EXPECT_FALSE(*obj->deleted_);
- *obj->deleted_ = true;
- delete obj;
-}
-
-TEST(RefPtrTest, CustomDeleterThreadSafe) {
- bool deleted = false;
- scoped_refptr<CustomDeleterThreadSafe> obj =
- base::AdoptRef(new CustomDeleterThreadSafe(&deleted));
- EXPECT_FALSE(deleted);
- obj = nullptr;
- EXPECT_TRUE(deleted);
-}
-
-} // namespace
-} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/ref_vector.h b/chromium/third_party/blink/renderer/platform/wtf/ref_vector.h
index d43dfbea088..53e3e0a799d 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/ref_vector.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/ref_vector.h
@@ -39,6 +39,7 @@ class RefVector : public RefCounted<RefVector<T>> {
bool IsEmpty() const { return !size(); }
void push_back(const T& decoration) { vector_.push_back(decoration); }
const Vector<T>& GetVector() const { return vector_; }
+ Vector<T>* GetMutableVector() { return &vector_; }
private:
Vector<T> vector_;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/atomic_string.cc b/chromium/third_party/blink/renderer/platform/wtf/text/atomic_string.cc
index 75ceaf12c2c..b55d1168f0e 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/atomic_string.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/atomic_string.cc
@@ -33,6 +33,11 @@ namespace WTF {
static_assert(sizeof(AtomicString) == sizeof(String),
"AtomicString and String must be same size");
+#if defined(ARCH_CPU_64_BITS)
+AtomicString::AtomicString(const LChar* chars, size_t length)
+ : AtomicString(chars, SafeCast<unsigned>(length)) {}
+#endif // defined(ARCH_CPU_64_BITS)
+
AtomicString::AtomicString(const LChar* chars, unsigned length)
: string_(AtomicStringTable::Instance().Add(chars, length)) {}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/atomic_string.h b/chromium/third_party/blink/renderer/platform/wtf/text/atomic_string.h
index 837d1a82a20..3ace8cc9de1 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/atomic_string.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/atomic_string.h
@@ -61,6 +61,13 @@ class WTF_EXPORT AtomicString {
: AtomicString(chars,
chars ? strlen(reinterpret_cast<const char*>(chars)) : 0) {
}
+
+#if defined(ARCH_CPU_64_BITS)
+ // Only define a size_t constructor if size_t is 64 bit otherwise
+ // we'd have a duplicate define.
+ AtomicString(const LChar* chars, size_t length);
+#endif // defined(ARCH_CPU_64_BITS)
+
AtomicString(const char* chars)
: AtomicString(reinterpret_cast<const LChar*>(chars)) {}
AtomicString(const LChar* chars, unsigned length);
@@ -292,7 +299,7 @@ struct DefaultHash<AtomicString> {
};
// Pretty printer for gtest and base/logging.*. It prepends and appends
-// double-quotes, and escapes chracters other than ASCII printables.
+// double-quotes, and escapes characters other than ASCII printables.
WTF_EXPORT std::ostream& operator<<(std::ostream&, const AtomicString&);
inline StringView::StringView(const AtomicString& string,
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/icu/collator_icu.cc b/chromium/third_party/blink/renderer/platform/wtf/text/collator.cc
index 743f827f1e5..743f827f1e5 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/icu/collator_icu.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/collator.cc
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/cstring.cc b/chromium/third_party/blink/renderer/platform/wtf/text/cstring.cc
index 63c4c4382cc..33ac70a692a 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/cstring.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/cstring.cc
@@ -27,24 +27,24 @@
#include "third_party/blink/renderer/platform/wtf/text/cstring.h"
#include <string.h>
+#include "base/numerics/checked_math.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
#include "third_party/blink/renderer/platform/wtf/ascii_ctype.h"
+#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
namespace WTF {
scoped_refptr<CStringImpl> CStringImpl::CreateUninitialized(size_t length,
char*& data) {
- // TODO(esprehn): This doesn't account for the NUL.
- CHECK_LT(length,
- (std::numeric_limits<unsigned>::max() - sizeof(CStringImpl)));
-
+ unsigned length_in_unsigned = SafeCast<unsigned>(length);
+ base::CheckedNumeric<size_t> size = length;
// The +1 is for the terminating NUL character.
- size_t size = sizeof(CStringImpl) + length + 1;
- CStringImpl* buffer = static_cast<CStringImpl*>(
- Partitions::BufferMalloc(size, WTF_HEAP_PROFILER_TYPE_NAME(CStringImpl)));
+ size += sizeof(CStringImpl) + 1;
+ CStringImpl* buffer = static_cast<CStringImpl*>(Partitions::BufferMalloc(
+ size.ValueOrDie(), WTF_HEAP_PROFILER_TYPE_NAME(CStringImpl)));
data = reinterpret_cast<char*>(buffer + 1);
data[length] = '\0';
- return base::AdoptRef(new (buffer) CStringImpl(length));
+ return base::AdoptRef(new (buffer) CStringImpl(length_in_unsigned));
}
void CStringImpl::operator delete(void* ptr) {
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/cstring.h b/chromium/third_party/blink/renderer/platform/wtf/text/cstring.h
index 797714e7c97..5a912e240d4 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/cstring.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/cstring.h
@@ -55,7 +55,7 @@ class WTF_EXPORT CStringImpl : public RefCounted<CStringImpl> {
size_t length() const { return length_; }
private:
- explicit CStringImpl(size_t length) : length_(length) {}
+ explicit CStringImpl(unsigned length) : length_(length) {}
const unsigned length_;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/icu/unicode_icu.h b/chromium/third_party/blink/renderer/platform/wtf/text/icu/unicode_icu.h
deleted file mode 100644
index ffa022cf090..00000000000
--- a/chromium/third_party/blink/renderer/platform/wtf/text/icu/unicode_icu.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) 2006 George Staikos <staikos@kde.org>
- * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com>
- * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
- *
- * 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_PLATFORM_WTF_TEXT_ICU_UNICODE_ICU_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_ICU_UNICODE_ICU_H_
-
-#include <unicode/uchar.h>
-#include <unicode/ustring.h>
-
-namespace WTF {
-
-namespace Unicode {
-
-enum CharDirection {
- kLeftToRight = U_LEFT_TO_RIGHT,
- kRightToLeft = U_RIGHT_TO_LEFT,
- kEuropeanNumber = U_EUROPEAN_NUMBER,
- kEuropeanNumberSeparator = U_EUROPEAN_NUMBER_SEPARATOR,
- kEuropeanNumberTerminator = U_EUROPEAN_NUMBER_TERMINATOR,
- kArabicNumber = U_ARABIC_NUMBER,
- kCommonNumberSeparator = U_COMMON_NUMBER_SEPARATOR,
- kBlockSeparator = U_BLOCK_SEPARATOR,
- kSegmentSeparator = U_SEGMENT_SEPARATOR,
- kWhiteSpaceNeutral = U_WHITE_SPACE_NEUTRAL,
- kOtherNeutral = U_OTHER_NEUTRAL,
- kLeftToRightEmbedding = U_LEFT_TO_RIGHT_EMBEDDING,
- kLeftToRightOverride = U_LEFT_TO_RIGHT_OVERRIDE,
- kRightToLeftArabic = U_RIGHT_TO_LEFT_ARABIC,
- kRightToLeftEmbedding = U_RIGHT_TO_LEFT_EMBEDDING,
- kRightToLeftOverride = U_RIGHT_TO_LEFT_OVERRIDE,
- kPopDirectionalFormat = U_POP_DIRECTIONAL_FORMAT,
- kNonSpacingMark = U_DIR_NON_SPACING_MARK,
- kBoundaryNeutral = U_BOUNDARY_NEUTRAL
-};
-
-enum CharDecompositionType {
- kDecompositionNone = U_DT_NONE,
- kDecompositionCanonical = U_DT_CANONICAL,
- kDecompositionCompat = U_DT_COMPAT,
- kDecompositionCircle = U_DT_CIRCLE,
- kDecompositionFinal = U_DT_FINAL,
- kDecompositionFont = U_DT_FONT,
- kDecompositionFraction = U_DT_FRACTION,
- kDecompositionInitial = U_DT_INITIAL,
- kDecompositionIsolated = U_DT_ISOLATED,
- kDecompositionMedial = U_DT_MEDIAL,
- kDecompositionNarrow = U_DT_NARROW,
- kDecompositionNoBreak = U_DT_NOBREAK,
- kDecompositionSmall = U_DT_SMALL,
- kDecompositionSquare = U_DT_SQUARE,
- kDecompositionSub = U_DT_SUB,
- kDecompositionSuper = U_DT_SUPER,
- kDecompositionVertical = U_DT_VERTICAL,
- kDecompositionWide = U_DT_WIDE,
-};
-
-enum CharCategory {
- kNoCategory = 0,
- kOther_NotAssigned = U_MASK(U_GENERAL_OTHER_TYPES),
- kLetter_Uppercase = U_MASK(U_UPPERCASE_LETTER),
- kLetter_Lowercase = U_MASK(U_LOWERCASE_LETTER),
- kLetter_Titlecase = U_MASK(U_TITLECASE_LETTER),
- kLetter_Modifier = U_MASK(U_MODIFIER_LETTER),
- kLetter_Other = U_MASK(U_OTHER_LETTER),
-
- kMark_NonSpacing = U_MASK(U_NON_SPACING_MARK),
- kMark_Enclosing = U_MASK(U_ENCLOSING_MARK),
- kMark_SpacingCombining = U_MASK(U_COMBINING_SPACING_MARK),
-
- kNumber_DecimalDigit = U_MASK(U_DECIMAL_DIGIT_NUMBER),
- kNumber_Letter = U_MASK(U_LETTER_NUMBER),
- kNumber_Other = U_MASK(U_OTHER_NUMBER),
-
- kSeparator_Space = U_MASK(U_SPACE_SEPARATOR),
- kSeparator_Line = U_MASK(U_LINE_SEPARATOR),
- kSeparator_Paragraph = U_MASK(U_PARAGRAPH_SEPARATOR),
-
- kOther_Control = U_MASK(U_CONTROL_CHAR),
- kOther_Format = U_MASK(U_FORMAT_CHAR),
- kOther_PrivateUse = U_MASK(U_PRIVATE_USE_CHAR),
- kOther_Surrogate = U_MASK(U_SURROGATE),
-
- kPunctuation_Dash = U_MASK(U_DASH_PUNCTUATION),
- kPunctuation_Open = U_MASK(U_START_PUNCTUATION),
- kPunctuation_Close = U_MASK(U_END_PUNCTUATION),
- kPunctuation_Connector = U_MASK(U_CONNECTOR_PUNCTUATION),
- kPunctuation_Other = U_MASK(U_OTHER_PUNCTUATION),
-
- kSymbol_Math = U_MASK(U_MATH_SYMBOL),
- kSymbol_Currency = U_MASK(U_CURRENCY_SYMBOL),
- kSymbol_Modifier = U_MASK(U_MODIFIER_SYMBOL),
- kSymbol_Other = U_MASK(U_OTHER_SYMBOL),
-
- kPunctuation_InitialQuote = U_MASK(U_INITIAL_PUNCTUATION),
- kPunctuation_FinalQuote = U_MASK(U_FINAL_PUNCTUATION)
-};
-
-inline UChar32 FoldCase(UChar32 c) {
- return u_foldCase(c, U_FOLD_CASE_DEFAULT);
-}
-
-inline int FoldCase(UChar* result,
- int result_length,
- const UChar* src,
- int src_length,
- bool* error) {
- UErrorCode status = U_ZERO_ERROR;
- int real_length = u_strFoldCase(result, result_length, src, src_length,
- U_FOLD_CASE_DEFAULT, &status);
- *error = !U_SUCCESS(status);
- return real_length;
-}
-
-inline int ToLower(UChar* result,
- int result_length,
- const UChar* src,
- int src_length,
- bool* error) {
- UErrorCode status = U_ZERO_ERROR;
- int real_length =
- u_strToLower(result, result_length, src, src_length, "", &status);
- *error = !!U_FAILURE(status);
- return real_length;
-}
-
-inline UChar32 ToLower(UChar32 c) {
- return u_tolower(c);
-}
-
-inline UChar32 ToUpper(UChar32 c) {
- return u_toupper(c);
-}
-
-inline int ToUpper(UChar* result,
- int result_length,
- const UChar* src,
- int src_length,
- bool* error) {
- UErrorCode status = U_ZERO_ERROR;
- int real_length =
- u_strToUpper(result, result_length, src, src_length, "", &status);
- *error = !!U_FAILURE(status);
- return real_length;
-}
-
-inline UChar32 ToTitleCase(UChar32 c) {
- return u_totitle(c);
-}
-
-inline bool IsArabicChar(UChar32 c) {
- return ublock_getCode(c) == UBLOCK_ARABIC;
-}
-
-inline bool IsAlphanumeric(UChar32 c) {
- return !!u_isalnum(c);
-}
-
-inline bool IsSeparatorSpace(UChar32 c) {
- return u_charType(c) == U_SPACE_SEPARATOR;
-}
-
-inline bool IsPrintableChar(UChar32 c) {
- return !!u_isprint(c);
-}
-
-inline bool IsPunct(UChar32 c) {
- return !!u_ispunct(c);
-}
-
-inline bool HasLineBreakingPropertyComplexContext(UChar32 c) {
- return u_getIntPropertyValue(c, UCHAR_LINE_BREAK) == U_LB_COMPLEX_CONTEXT;
-}
-
-inline UChar32 MirroredChar(UChar32 c) {
- return u_charMirror(c);
-}
-
-inline CharCategory Category(UChar32 c) {
- return static_cast<CharCategory>(U_GET_GC_MASK(c));
-}
-
-inline CharDirection Direction(UChar32 c) {
- return static_cast<CharDirection>(u_charDirection(c));
-}
-
-inline bool IsLower(UChar32 c) {
- return !!u_islower(c);
-}
-
-inline uint8_t CombiningClass(UChar32 c) {
- return u_getCombiningClass(c);
-}
-
-inline CharDecompositionType DecompositionType(UChar32 c) {
- return static_cast<CharDecompositionType>(
- u_getIntPropertyValue(c, UCHAR_DECOMPOSITION_TYPE));
-}
-
-inline int Umemcasecmp(const UChar* a, const UChar* b, int len) {
- return u_memcasecmp(a, b, len, U_FOLD_CASE_DEFAULT);
-}
-
-} // namespace Unicode
-
-} // namespace WTF
-
-#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_ICU_UNICODE_ICU_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/integer_to_string_conversion.h b/chromium/third_party/blink/renderer/platform/wtf/text/integer_to_string_conversion.h
index 48ece3d1c35..4933c9b856b 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/integer_to_string_conversion.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/integer_to_string_conversion.h
@@ -32,7 +32,7 @@ namespace WTF {
// TODO(esprehn): See if we can generalize IntToStringT in
// base/strings/string_number_conversions.cc, and use unsigned type expansion
-// optimization here instead of CheckedNumeric::UnsignedAbs().
+// optimization here instead of base::CheckedNumeric::UnsignedAbs().
template <typename IntegerType>
class IntegerToStringConverter {
public:
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/movable_string.cc b/chromium/third_party/blink/renderer/platform/wtf/text/movable_string.cc
new file mode 100644
index 00000000000..fdfa440ea96
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/movable_string.cc
@@ -0,0 +1,147 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/wtf/text/movable_string.h"
+
+#include "base/metrics/histogram_macros.h"
+
+namespace WTF {
+
+namespace {
+
+bool IsLargeEnough(const StringImpl* impl) {
+ // Don't attempt to park strings smaller than this size.
+ static constexpr unsigned int kSizeThreshold = 10000;
+ return impl && impl->length() > kSizeThreshold;
+}
+
+void RecordParkingAction(MovableStringImpl::ParkingAction action) {
+ UMA_HISTOGRAM_ENUMERATION("Memory.MovableStringParkingAction", action);
+}
+
+} // namespace
+
+MovableStringImpl::MovableStringImpl() = default;
+
+MovableStringImpl::MovableStringImpl(scoped_refptr<StringImpl>&& impl)
+ : string_(std::move(impl)), is_parked_(false) {}
+
+MovableStringImpl::~MovableStringImpl() {
+ MovableStringTable::Instance().Remove(string_.Impl());
+}
+
+bool MovableStringImpl::Is8Bit() const {
+ return string_.Is8Bit();
+}
+
+bool MovableStringImpl::IsNull() const {
+ return string_.IsNull();
+}
+
+const String& MovableStringImpl::ToString() {
+ Unpark();
+ return string_;
+}
+
+unsigned MovableStringImpl::CharactersSizeInBytes() const {
+ return string_.CharactersSizeInBytes();
+}
+
+bool MovableStringImpl::Park() {
+ // Cannot park strings with several references.
+ if (string_.Impl()->HasOneRef()) {
+ RecordParkingAction(ParkingAction::kParkedInBackground);
+ is_parked_ = true;
+ }
+ return is_parked_;
+}
+
+void MovableStringImpl::Unpark() {
+ if (!is_parked_)
+ return;
+
+ bool backgrounded = MovableStringTable::Instance().IsRendererBackgrounded();
+ RecordParkingAction(backgrounded ? ParkingAction::kUnparkedInBackground
+ : ParkingAction::kUnparkedInForeground);
+ is_parked_ = false;
+}
+
+MovableString::MovableString(scoped_refptr<StringImpl>&& impl) {
+ // Don't move small strings.
+ if (IsLargeEnough(impl.get())) {
+ impl_ = MovableStringTable::Instance().Add(std::move(impl));
+ } else {
+ impl_ = base::MakeRefCounted<MovableStringImpl>(std::move(impl));
+ }
+}
+
+MovableString::~MovableString() = default;
+
+bool MovableString::Is8Bit() const {
+ return impl_->Is8Bit();
+}
+
+bool MovableString::IsNull() const {
+ return impl_->IsNull();
+}
+const String& MovableString::ToString() const {
+ return impl_->ToString();
+}
+
+unsigned MovableString::CharactersSizeInBytes() const {
+ return impl_->CharactersSizeInBytes();
+}
+
+MovableStringTable::MovableStringTable() = default;
+MovableStringTable::~MovableStringTable() = default;
+
+scoped_refptr<MovableStringImpl> MovableStringTable::Add(
+ scoped_refptr<StringImpl>&& string) {
+ StringImpl* raw_ptr = string.get();
+ auto it = table_.find(raw_ptr);
+ if (it != table_.end()) {
+ return it->second;
+ }
+ auto new_movable_string =
+ base::MakeRefCounted<MovableStringImpl>(std::move(string));
+ table_.emplace(raw_ptr, new_movable_string.get());
+ return new_movable_string;
+}
+
+void MovableStringTable::Remove(StringImpl* string) {
+ if (!IsLargeEnough(string))
+ return;
+
+ auto it = table_.find(string);
+ DCHECK(it != table_.end());
+ table_.erase(it);
+}
+
+void MovableStringTable::SetRendererBackgrounded(bool backgrounded) {
+ backgrounded_ = backgrounded;
+}
+
+bool MovableStringTable::IsRendererBackgrounded() const {
+ return backgrounded_;
+}
+
+void MovableStringTable::MaybeParkAll() {
+ if (!IsRendererBackgrounded())
+ return;
+
+ size_t total_size = 0, count = 0;
+ for (auto& kv : table_) {
+ MovableStringImpl* str = kv.second;
+ str->Park();
+ total_size += str->CharactersSizeInBytes();
+ count += 1;
+ }
+
+ size_t total_size_kb = total_size / 1000;
+ UMA_HISTOGRAM_COUNTS_100000("Memory.MovableStringsTotalSizeKb",
+ total_size_kb);
+ UMA_HISTOGRAM_COUNTS_1000("Memory.MovableStringsCount", table_.size());
+}
+
+} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/movable_string.h b/chromium/third_party/blink/renderer/platform/wtf/text/movable_string.h
new file mode 100644
index 00000000000..7b943e9b578
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/movable_string.h
@@ -0,0 +1,139 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_MOVABLE_STRING_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_MOVABLE_STRING_H_
+
+#include <map>
+#include <set>
+#include <utility>
+
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/renderer/platform/wtf/wtf_thread_data.h"
+
+// MovableString represents a string that may be moved in memory, that it its
+// underlying memory address may change. Its content can be retrieved with the
+// |ToString()| method.
+// As a consequence, the inner pointer should never be cached, and only touched
+// through a string returned by the |ToString()| method.
+//
+// As with WTF::AtomicString, this class is *not* thread-safe, and strings
+// created on a thread must always be used on the same thread.
+//
+// Implementation note: the string content is not moved yet, it is merely
+// used to gather statistics.
+
+namespace WTF {
+
+class WTF_EXPORT MovableStringImpl final
+ : public RefCounted<MovableStringImpl> {
+ public:
+ // Histogram buckets, exported for testing.
+ enum class ParkingAction {
+ kParkedInBackground = 0,
+ kUnparkedInBackground = 1,
+ kUnparkedInForeground = 2,
+ kMaxValue = kUnparkedInForeground
+ };
+
+ MovableStringImpl();
+ explicit MovableStringImpl(scoped_refptr<StringImpl>&& impl);
+ ~MovableStringImpl();
+
+ // The returned string may be used as a normal one, as long as the
+ // returned value (or a copy of it) is alive.
+ const String& ToString();
+
+ // See the matching String methods.
+ bool Is8Bit() const;
+ bool IsNull() const;
+ unsigned length() const { return string_.length(); }
+ unsigned CharactersSizeInBytes() const;
+
+ // A parked string cannot be accessed until it has been |Unpark()|-ed.
+ // Returns true iff the string has been parked.
+ bool Park();
+ // Returns true if the string is parked.
+ bool is_parked() const { return is_parked_; }
+
+ private:
+ void Unpark();
+
+ String string_;
+ bool is_parked_;
+
+ DISALLOW_COPY_AND_ASSIGN(MovableStringImpl);
+};
+
+class WTF_EXPORT MovableString final {
+ public:
+ MovableString() : impl_(base::MakeRefCounted<MovableStringImpl>(nullptr)) {}
+ explicit MovableString(scoped_refptr<StringImpl>&& impl);
+ MovableString(const MovableString& rhs) : impl_(rhs.impl_) {}
+ ~MovableString();
+
+ // See the matching String methods.
+ bool Is8Bit() const;
+ bool IsNull() const;
+ unsigned length() const { return impl_->length(); }
+ MovableStringImpl* Impl() const { return impl_.get(); }
+ // Returns an unparked version of the string.
+ // The string is guaranteed to be valid for
+ // max(lifetime of a copy of the returned reference, current thread task).
+ const String& ToString() const;
+ unsigned CharactersSizeInBytes() const;
+
+ // Causes the string to be unparked. Note that the pointer must not be
+ // cached.
+ const LChar* Characters8() const { return ToString().Characters8(); }
+ const UChar* Characters16() const { return ToString().Characters16(); }
+
+ private:
+ scoped_refptr<MovableStringImpl> impl_;
+};
+
+// Per-thread registry of all MovableString instances. NOT thread-safe.
+class WTF_EXPORT MovableStringTable final {
+ public:
+ MovableStringTable();
+ ~MovableStringTable();
+
+ static MovableStringTable& Instance() {
+ return WtfThreadData().GetMovableStringTable();
+ }
+
+ scoped_refptr<MovableStringImpl> Add(scoped_refptr<StringImpl>&&);
+
+ // This is for ~MovableStringImpl to unregister a string before
+ // destruction since the table is holding raw pointers. It should not be used
+ // directly.
+ void Remove(StringImpl*);
+
+ void SetRendererBackgrounded(bool backgrounded);
+ bool IsRendererBackgrounded() const;
+
+ // Parks all the strings in the table if currently in background.
+ void MaybeParkAll();
+
+ private:
+ bool backgrounded_;
+ // Could bet a set where the hashing function is
+ // MovableStringImpl::string_.Impl(), but clearer this way.
+ std::map<StringImpl*, MovableStringImpl*> table_;
+
+ FRIEND_TEST_ALL_PREFIXES(MovableStringTest, TableSimple);
+ FRIEND_TEST_ALL_PREFIXES(MovableStringTest, TableMultiple);
+
+ DISALLOW_COPY_AND_ASSIGN(MovableStringTable);
+};
+
+} // namespace WTF
+
+using WTF::MovableStringTable;
+using WTF::MovableString;
+using WTF::MovableStringImpl;
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_MOVABLE_STRING_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/movable_string_test.cc b/chromium/third_party/blink/renderer/platform/wtf/text/movable_string_test.cc
new file mode 100644
index 00000000000..6eebafcd3f8
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/movable_string_test.cc
@@ -0,0 +1,185 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/wtf/text/movable_string.h"
+
+#include <vector>
+
+#include "base/test/metrics/histogram_tester.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace WTF {
+
+class MovableStringTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ MovableStringTable::Instance().SetRendererBackgrounded(false);
+ }
+};
+
+TEST_F(MovableStringTest, Simple) {
+ MovableString movable_abc(String("abc").ReleaseImpl());
+
+ EXPECT_TRUE(MovableString().IsNull());
+ EXPECT_FALSE(movable_abc.IsNull());
+ EXPECT_TRUE(movable_abc.Is8Bit());
+ EXPECT_EQ(3u, movable_abc.length());
+ EXPECT_EQ(3u, movable_abc.CharactersSizeInBytes());
+
+ EXPECT_EQ(String("abc"), movable_abc.ToString());
+ MovableString copy = movable_abc;
+ EXPECT_EQ(copy.Impl(), movable_abc.Impl());
+}
+
+TEST_F(MovableStringTest, Park) {
+ base::HistogramTester histogram_tester;
+
+ MovableString movable(String("abc").Impl());
+ EXPECT_FALSE(movable.Impl()->is_parked());
+ EXPECT_TRUE(movable.Impl()->Park());
+ EXPECT_TRUE(movable.Impl()->is_parked());
+
+ // Not the only one to have a reference to the string.
+ String abc("abc");
+ MovableString movable2(abc.Impl());
+ EXPECT_FALSE(movable2.Impl()->Park());
+ abc = String();
+ EXPECT_TRUE(movable2.Impl()->Park());
+
+ histogram_tester.ExpectBucketCount(
+ "Memory.MovableStringParkingAction",
+ MovableStringImpl::ParkingAction::kParkedInBackground, 2);
+ histogram_tester.ExpectTotalCount("Memory.MovableStringParkingAction", 2);
+}
+
+TEST_F(MovableStringTest, Unpark) {
+ base::HistogramTester histogram_tester;
+
+ MovableString movable(String("abc").Impl());
+ EXPECT_FALSE(movable.Impl()->is_parked());
+ EXPECT_TRUE(movable.Impl()->Park());
+ EXPECT_TRUE(movable.Impl()->is_parked());
+
+ String unparked = movable.ToString();
+ EXPECT_EQ(String("abc"), unparked);
+ EXPECT_FALSE(movable.Impl()->is_parked());
+
+ histogram_tester.ExpectTotalCount("Memory.MovableStringParkingAction", 2);
+ histogram_tester.ExpectBucketCount(
+ "Memory.MovableStringParkingAction",
+ MovableStringImpl::ParkingAction::kParkedInBackground, 1);
+ histogram_tester.ExpectBucketCount(
+ "Memory.MovableStringParkingAction",
+ MovableStringImpl::ParkingAction::kUnparkedInForeground, 1);
+}
+
+TEST_F(MovableStringTest, TableSimple) {
+ base::HistogramTester histogram_tester;
+
+ std::vector<char> data(20000, 'a');
+ MovableString movable(String(data.data(), data.size()).ReleaseImpl());
+ ASSERT_FALSE(movable.Impl()->is_parked());
+
+ auto& table = MovableStringTable::Instance();
+ EXPECT_EQ(1u, table.table_.size());
+
+ // Small strings are not in the table.
+ MovableString small(String("abc").ReleaseImpl());
+ EXPECT_EQ(1u, table.table_.size());
+
+ // No parking as the current state is not "backgrounded".
+ table.SetRendererBackgrounded(false);
+ ASSERT_FALSE(table.IsRendererBackgrounded());
+ table.MaybeParkAll();
+ EXPECT_FALSE(movable.Impl()->is_parked());
+ histogram_tester.ExpectTotalCount("Memory.MovableStringsCount", 0);
+
+ table.SetRendererBackgrounded(true);
+ ASSERT_TRUE(table.IsRendererBackgrounded());
+ table.MaybeParkAll();
+ EXPECT_TRUE(movable.Impl()->is_parked());
+ histogram_tester.ExpectUniqueSample("Memory.MovableStringsCount", 1, 1);
+
+ // Park and unpark.
+ movable.ToString();
+ EXPECT_FALSE(movable.Impl()->is_parked());
+ table.MaybeParkAll();
+ EXPECT_TRUE(movable.Impl()->is_parked());
+ histogram_tester.ExpectUniqueSample("Memory.MovableStringsCount", 1, 2);
+
+ // More than one reference, no parking.
+ table.SetRendererBackgrounded(false);
+ String alive_unparked = movable.ToString(); // Unparked in foreground.
+ table.SetRendererBackgrounded(true);
+ table.MaybeParkAll();
+ EXPECT_FALSE(movable.Impl()->is_parked());
+
+ // Other reference is dropped, OK to park.
+ alive_unparked = String();
+ table.MaybeParkAll();
+ EXPECT_TRUE(movable.Impl()->is_parked());
+
+ histogram_tester.ExpectTotalCount("Memory.MovableStringParkingAction", 5);
+ histogram_tester.ExpectBucketCount(
+ "Memory.MovableStringParkingAction",
+ MovableStringImpl::ParkingAction::kParkedInBackground, 3);
+ histogram_tester.ExpectBucketCount(
+ "Memory.MovableStringParkingAction",
+ MovableStringImpl::ParkingAction::kUnparkedInBackground, 1);
+ histogram_tester.ExpectBucketCount(
+ "Memory.MovableStringParkingAction",
+ MovableStringImpl::ParkingAction::kUnparkedInForeground, 1);
+}
+
+TEST_F(MovableStringTest, TableMultiple) {
+ base::HistogramTester histogram_tester;
+
+ size_t size_kb = 20;
+ std::vector<char> data(size_kb * 1000, 'a');
+ MovableString movable(String(data.data(), data.size()).ReleaseImpl());
+ MovableString movable2(String(data.data(), data.size()).ReleaseImpl());
+
+ auto& table = MovableStringTable::Instance();
+ EXPECT_EQ(2u, table.table_.size());
+
+ movable2 = MovableString();
+ EXPECT_EQ(1u, table.table_.size());
+
+ MovableString copy = movable;
+ movable = MovableString();
+ EXPECT_EQ(1u, table.table_.size());
+ copy = MovableString();
+ EXPECT_EQ(0u, table.table_.size());
+
+ String str(data.data(), data.size());
+ MovableString movable3(str.Impl());
+ EXPECT_EQ(1u, table.table_.size());
+ // De-duplicated.
+ MovableString other_movable3(str.Impl());
+ EXPECT_EQ(1u, table.table_.size());
+ EXPECT_EQ(movable3.Impl(), other_movable3.Impl());
+
+ // If all the references to a string are in the table, park it.
+ str = String();
+ table.SetRendererBackgrounded(true);
+ ASSERT_TRUE(table.IsRendererBackgrounded());
+ table.MaybeParkAll();
+ EXPECT_TRUE(movable3.Impl()->is_parked());
+
+ // Only drop it from the table when the last one is gone.
+ movable3 = MovableString();
+ EXPECT_EQ(1u, table.table_.size());
+ other_movable3 = MovableString();
+ EXPECT_EQ(0u, table.table_.size());
+
+ histogram_tester.ExpectUniqueSample("Memory.MovableStringsCount", 1, 1);
+ histogram_tester.ExpectUniqueSample("Memory.MovableStringsTotalSizeKb",
+ size_kb, 1);
+ histogram_tester.ExpectTotalCount("Memory.MovableStringParkingAction", 1);
+ histogram_tester.ExpectBucketCount(
+ "Memory.MovableStringParkingAction",
+ MovableStringImpl::ParkingAction::kParkedInBackground, 1);
+}
+
+} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_builder.cc b/chromium/third_party/blink/renderer/platform/wtf/text/string_builder.cc
index 46e7df001ce..5f6594a71c5 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_builder.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_builder.cc
@@ -27,6 +27,7 @@
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include <algorithm>
+#include "base/optional.h"
#include "third_party/blink/renderer/platform/wtf/dtoa.h"
#include "third_party/blink/renderer/platform/wtf/text/integer_to_string_conversion.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -71,18 +72,47 @@ String StringBuilder::Substring(unsigned start, unsigned length) const {
}
void StringBuilder::Swap(StringBuilder& builder) {
+ base::Optional<Buffer8> buffer8;
+ base::Optional<Buffer16> buffer16;
+ if (has_buffer_) {
+ if (is8_bit_) {
+ buffer8 = std::move(buffer8_);
+ buffer8_.~Buffer8();
+ } else {
+ buffer16 = std::move(buffer16_);
+ buffer16_.~Buffer16();
+ }
+ }
+
+ if (builder.has_buffer_) {
+ if (builder.is8_bit_) {
+ new (&buffer8_) Buffer8(std::move(builder.buffer8_));
+ builder.buffer8_.~Buffer8();
+ } else {
+ new (&buffer16_) Buffer16(std::move(builder.buffer16_));
+ builder.buffer16_.~Buffer16();
+ }
+ }
+
+ if (buffer8)
+ new (&builder.buffer8_) Buffer8(std::move(*buffer8));
+ else if (buffer16)
+ new (&builder.buffer16_) Buffer16(std::move(*buffer16));
+
std::swap(string_, builder.string_);
- std::swap(buffer_, builder.buffer_);
std::swap(length_, builder.length_);
std::swap(is8_bit_, builder.is8_bit_);
+ std::swap(has_buffer_, builder.has_buffer_);
}
void StringBuilder::ClearBuffer() {
+ if (!has_buffer_)
+ return;
if (is8_bit_)
- delete buffer8_;
+ buffer8_.~Buffer8();
else
- delete buffer16_;
- buffer_ = nullptr;
+ buffer16_.~Buffer16();
+ has_buffer_ = false;
}
void StringBuilder::Clear() {
@@ -96,8 +126,8 @@ unsigned StringBuilder::Capacity() const {
if (!HasBuffer())
return 0;
if (is8_bit_)
- return buffer8_->capacity();
- return buffer16_->capacity();
+ return buffer8_.capacity();
+ return buffer16_.capacity();
}
void StringBuilder::ReserveCapacity(unsigned new_capacity) {
@@ -113,16 +143,17 @@ void StringBuilder::Resize(unsigned new_size) {
length_ = new_size;
if (HasBuffer()) {
if (is8_bit_)
- buffer8_->resize(new_size);
+ buffer8_.resize(new_size);
else
- buffer16_->resize(new_size);
+ buffer16_.resize(new_size);
}
}
void StringBuilder::CreateBuffer8(unsigned added_size) {
DCHECK(!HasBuffer());
DCHECK(is8_bit_);
- buffer8_ = new Buffer8;
+ new (&buffer8_) Buffer8;
+ has_buffer_ = true;
// createBuffer is called right before appending addedSize more bytes. We
// want to ensure we have enough space to fit m_string plus the added
// size.
@@ -132,8 +163,8 @@ void StringBuilder::CreateBuffer8(unsigned added_size) {
// strings or single characters. This is a no-op if m_length == 0 since
// initialBufferSize() is the same as the inline capacity of the vector.
// This allows doing append(string); append('\0') without extra mallocs.
- buffer8_->ReserveInitialCapacity(length_ +
- std::max(added_size, InitialBufferSize()));
+ buffer8_.ReserveInitialCapacity(length_ +
+ std::max(added_size, InitialBufferSize()));
length_ = 0;
Append(string_);
string_ = String();
@@ -143,14 +174,16 @@ void StringBuilder::CreateBuffer16(unsigned added_size) {
DCHECK(is8_bit_ || !HasBuffer());
Buffer8 buffer8;
unsigned length = length_;
- if (buffer8_) {
- buffer8_->swap(buffer8);
- delete buffer8_;
+ if (has_buffer_) {
+ buffer8 = std::move(buffer8_);
+ buffer8_.~Buffer8();
}
- buffer16_ = new Buffer16;
+ new (&buffer16_) Buffer16;
+ has_buffer_ = true;
// See createBuffer8's call to reserveInitialCapacity for why we do this.
- buffer16_->ReserveInitialCapacity(length_ +
- std::max(added_size, InitialBufferSize()));
+ buffer16_.ReserveInitialCapacity(
+ length_ +
+ std::max<unsigned>(added_size, InitialBufferSize() / sizeof(UChar)));
is8_bit_ = false;
length_ = 0;
if (!buffer8.IsEmpty()) {
@@ -174,7 +207,7 @@ void StringBuilder::Append(const UChar* characters, unsigned length) {
}
EnsureBuffer16(length);
- buffer16_->Append(characters, length);
+ buffer16_.Append(characters, length);
length_ += length;
}
@@ -185,13 +218,13 @@ void StringBuilder::Append(const LChar* characters, unsigned length) {
if (is8_bit_) {
EnsureBuffer8(length);
- buffer8_->Append(characters, length);
+ buffer8_.Append(characters, length);
length_ += length;
return;
}
EnsureBuffer16(length);
- buffer16_->Append(characters, length);
+ buffer16_.Append(characters, length);
length_ += length;
}
@@ -236,10 +269,10 @@ void StringBuilder::erase(unsigned index) {
if (is8_bit_) {
EnsureBuffer8(0);
- buffer8_->EraseAt(index);
+ buffer8_.EraseAt(index);
} else {
EnsureBuffer16(0);
- buffer16_->EraseAt(index);
+ buffer16_.EraseAt(index);
}
--length_;
}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_builder.h b/chromium/third_party/blink/renderer/platform/wtf/text/string_builder.h
index ae74e0fc253..2eed705ccbe 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_builder.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_builder.h
@@ -37,8 +37,7 @@ namespace WTF {
class WTF_EXPORT StringBuilder {
public:
- StringBuilder() : buffer_(nullptr), length_(0), is8_bit_(true) {}
-
+ StringBuilder() : no_buffer_() {}
~StringBuilder() { Clear(); }
void Append(const UChar*, unsigned length);
@@ -111,7 +110,7 @@ class WTF_EXPORT StringBuilder {
return;
}
EnsureBuffer16(1);
- buffer16_->push_back(c);
+ buffer16_.push_back(c);
++length_;
}
@@ -121,7 +120,7 @@ class WTF_EXPORT StringBuilder {
return;
}
EnsureBuffer8(1);
- buffer8_->push_back(c);
+ buffer8_.push_back(c);
++length_;
}
@@ -172,8 +171,8 @@ class WTF_EXPORT StringBuilder {
return nullptr;
if (!string_.IsNull())
return string_.Characters8();
- DCHECK(buffer8_);
- return buffer8_->data();
+ DCHECK(has_buffer_);
+ return buffer8_.data();
}
const UChar* Characters16() const {
@@ -182,8 +181,8 @@ class WTF_EXPORT StringBuilder {
return nullptr;
if (!string_.IsNull())
return string_.Characters16();
- DCHECK(buffer16_);
- return buffer16_->data();
+ DCHECK(has_buffer_);
+ return buffer16_.data();
}
bool Is8Bit() const { return is8_bit_; }
@@ -195,8 +194,8 @@ class WTF_EXPORT StringBuilder {
static const unsigned kInlineBufferSize = 16;
static unsigned InitialBufferSize() { return kInlineBufferSize; }
- typedef Vector<LChar, kInlineBufferSize> Buffer8;
- typedef Vector<UChar, kInlineBufferSize> Buffer16;
+ typedef Vector<LChar, kInlineBufferSize / sizeof(LChar)> Buffer8;
+ typedef Vector<UChar, kInlineBufferSize / sizeof(UChar)> Buffer16;
void EnsureBuffer8(unsigned added_size) {
DCHECK(is8_bit_);
@@ -212,16 +211,17 @@ class WTF_EXPORT StringBuilder {
void CreateBuffer8(unsigned added_size);
void CreateBuffer16(unsigned added_size);
void ClearBuffer();
- bool HasBuffer() const { return buffer_; }
+ bool HasBuffer() const { return has_buffer_; }
String string_;
union {
- Buffer8* buffer8_;
- Buffer16* buffer16_;
- void* buffer_;
+ char no_buffer_;
+ Buffer8 buffer8_;
+ Buffer16 buffer16_;
};
- unsigned length_;
- bool is8_bit_;
+ unsigned length_ = 0;
+ bool is8_bit_ = true;
+ bool has_buffer_ = false;
DISALLOW_COPY_AND_ASSIGN(StringBuilder);
};
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_concatenate.cc b/chromium/third_party/blink/renderer/platform/wtf/text/string_concatenate.cc
index fee8323d744..ae3c881b5bc 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_concatenate.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_concatenate.cc
@@ -8,6 +8,9 @@
#include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
+WTF::StringTypeAdapter<char*>::StringTypeAdapter(char* buffer, size_t length)
+ : buffer_(buffer), length_(SafeCast<unsigned>(length)) {}
+
void WTF::StringTypeAdapter<char*>::WriteTo(LChar* destination) const {
for (unsigned i = 0; i < length_; ++i)
destination[i] = static_cast<LChar>(buffer_[i]);
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_concatenate.h b/chromium/third_party/blink/renderer/platform/wtf/text/string_concatenate.h
index 94ec2410355..db24c119744 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_concatenate.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_concatenate.h
@@ -101,7 +101,7 @@ class WTF_EXPORT StringTypeAdapter<char*> {
public:
explicit StringTypeAdapter<char*>(char* buffer)
- : buffer_(buffer), length_(strlen(buffer)) {}
+ : StringTypeAdapter(buffer, strlen(buffer)) {}
unsigned length() const { return length_; }
bool Is8Bit() const { return true; }
@@ -110,6 +110,8 @@ class WTF_EXPORT StringTypeAdapter<char*> {
void WriteTo(UChar* destination) const;
private:
+ StringTypeAdapter<char*>(char* buffer, size_t length);
+
const char* buffer_;
unsigned length_;
};
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_hash.h b/chromium/third_party/blink/renderer/platform/wtf/text/string_hash.h
index 170451c724b..615a3c99c43 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_hash.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_hash.h
@@ -100,11 +100,6 @@ class CaseFoldingHash {
length);
}
- static inline unsigned GetHash(const char* data) {
- return CaseFoldingHash::GetHash(reinterpret_cast<const LChar*>(data),
- strlen(data));
- }
-
static inline bool Equal(const StringImpl* a, const StringImpl* b) {
DCHECK(a);
DCHECK(b);
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_impl.h b/chromium/third_party/blink/renderer/platform/wtf/text/string_impl.h
index 158d81ca9ba..0e7c40b732e 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_impl.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_impl.h
@@ -456,7 +456,7 @@ class WTF_EXPORT StringImpl {
template <typename CharType, class UCharPredicate>
scoped_refptr<StringImpl> SimplifyMatchedCharactersToSpace(UCharPredicate,
StripBehavior);
- NEVER_INLINE unsigned HashSlowCase() const;
+ NOINLINE unsigned HashSlowCase() const;
void DestroyIfNotStatic() const;
void UpdateContainsOnlyASCII() const;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_impl_cf.cc b/chromium/third_party/blink/renderer/platform/wtf/text/string_impl_cf.cc
index 5ba1b63868e..cb1a4a46e49 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_impl_cf.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_impl_cf.cc
@@ -28,6 +28,7 @@
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
#include "third_party/blink/renderer/platform/wtf/retain_ptr.h"
#include "third_party/blink/renderer/platform/wtf/threading.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace WTF {
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_statics.cc b/chromium/third_party/blink/renderer/platform/wtf/text/string_statics.cc
index d0013cde895..8652c13d597 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_statics.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_statics.cc
@@ -29,6 +29,7 @@
#include "third_party/blink/renderer/platform/wtf/static_constructors.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
#include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace WTF {
@@ -49,7 +50,7 @@ WTF_EXPORT DEFINE_GLOBAL(String, g_xmlns_with_colon);
WTF_EXPORT DEFINE_GLOBAL(String, g_empty_string);
WTF_EXPORT DEFINE_GLOBAL(String, g_empty_string16_bit);
-NEVER_INLINE unsigned StringImpl::HashSlowCase() const {
+NOINLINE unsigned StringImpl::HashSlowCase() const {
if (Is8Bit())
SetHash(StringHasher::ComputeHashAndMaskTop8Bits(Characters8(), length_));
else
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_view.h b/chromium/third_party/blink/renderer/platform/wtf/text/string_view.h
index ea7e299075d..47f0d57f1d5 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_view.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_view.h
@@ -11,6 +11,7 @@
#include "base/memory/scoped_refptr.h"
#endif
#include <cstring>
+#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
#include "third_party/blink/renderer/platform/wtf/text/unicode.h"
@@ -73,7 +74,9 @@ class WTF_EXPORT StringView {
: StringView(reinterpret_cast<const LChar*>(chars), length) {}
StringView(const LChar* chars)
: StringView(chars,
- chars ? strlen(reinterpret_cast<const char*>(chars)) : 0) {}
+ chars ? SafeCast<unsigned>(
+ strlen(reinterpret_cast<const char*>(chars)))
+ : 0) {}
StringView(const char* chars)
: StringView(reinterpret_cast<const LChar*>(chars)) {}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/string_view_test.cc b/chromium/third_party/blink/renderer/platform/wtf/text/string_view_test.cc
index c36168d83a4..e949f60c68d 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/string_view_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/string_view_test.cc
@@ -252,7 +252,7 @@ TEST(StringViewTest, ConstructionAtomicString16) {
}
TEST(StringViewTest, ConstructionStringView8) {
- StringView view8_bit = StringView(kChars8, 5);
+ StringView view8_bit = StringView(kChars8, 5u);
// StringView(StringView&);
ASSERT_TRUE(StringView(view8_bit).Is8Bit());
@@ -325,18 +325,18 @@ TEST(StringViewTest, ConstructionLiteral8) {
EXPECT_STREQ(kChars, StringView(kChars).ToString().Utf8().data());
// StringView(const LChar* chars, unsigned length);
- ASSERT_TRUE(StringView(kChars8, 2).Is8Bit());
- EXPECT_FALSE(StringView(kChars8, 2).IsNull());
- EXPECT_EQ(2u, StringView(kChars8, 2).length());
- EXPECT_EQ(StringView("12"), StringView(kChars8, 2));
- EXPECT_STREQ("12", StringView(kChars8, 2).ToString().Utf8().data());
+ ASSERT_TRUE(StringView(kChars8, 2u).Is8Bit());
+ EXPECT_FALSE(StringView(kChars8, 2u).IsNull());
+ EXPECT_EQ(2u, StringView(kChars8, 2u).length());
+ EXPECT_EQ(StringView("12"), StringView(kChars8, 2u));
+ EXPECT_STREQ("12", StringView(kChars8, 2u).ToString().Utf8().data());
// StringView(const char* chars, unsigned length);
- ASSERT_TRUE(StringView(kChars, 2).Is8Bit());
- EXPECT_FALSE(StringView(kChars, 2).IsNull());
- EXPECT_EQ(2u, StringView(kChars, 2).length());
- EXPECT_EQ(StringView("12"), StringView(kChars, 2));
- EXPECT_STREQ("12", StringView(kChars, 2).ToString().Utf8().data());
+ ASSERT_TRUE(StringView(kChars, 2u).Is8Bit());
+ EXPECT_FALSE(StringView(kChars, 2u).IsNull());
+ EXPECT_EQ(2u, StringView(kChars, 2u).length());
+ EXPECT_EQ(StringView("12"), StringView(kChars, 2u));
+ EXPECT_STREQ("12", StringView(kChars, 2u).ToString().Utf8().data());
}
TEST(StringViewTest, ConstructionLiteral16) {
@@ -348,14 +348,14 @@ TEST(StringViewTest, ConstructionLiteral16) {
EXPECT_EQ(String(kChars16), StringView(kChars16).ToString().Utf8().data());
// StringView(const UChar* chars, unsigned length);
- ASSERT_FALSE(StringView(kChars16, 2).Is8Bit());
- EXPECT_FALSE(StringView(kChars16, 2).IsNull());
- EXPECT_EQ(kChars16, StringView(kChars16, 2).Characters16());
- EXPECT_EQ(StringView("12"), StringView(kChars16, 2));
+ ASSERT_FALSE(StringView(kChars16, 2u).Is8Bit());
+ EXPECT_FALSE(StringView(kChars16, 2u).IsNull());
+ EXPECT_EQ(kChars16, StringView(kChars16, 2u).Characters16());
+ EXPECT_EQ(StringView("12"), StringView(kChars16, 2u));
EXPECT_EQ(StringView(reinterpret_cast<const UChar*>(u"12")),
- StringView(kChars16, 2));
- EXPECT_EQ(2u, StringView(kChars16, 2).length());
- EXPECT_EQ(String("12"), StringView(kChars16, 2).ToString());
+ StringView(kChars16, 2u));
+ EXPECT_EQ(2u, StringView(kChars16, 2u).length());
+ EXPECT_EQ(String("12"), StringView(kChars16, 2u).ToString());
}
TEST(StringViewTest, IsEmpty) {
@@ -379,7 +379,7 @@ TEST(StringViewTest, ToString) {
TEST(StringViewTest, ToAtomicString) {
EXPECT_EQ(g_null_atom.Impl(), StringView().ToAtomicString());
EXPECT_EQ(g_empty_atom.Impl(), StringView("").ToAtomicString());
- EXPECT_EQ(AtomicString("12"), StringView(kChars8, 2).ToAtomicString());
+ EXPECT_EQ(AtomicString("12"), StringView(kChars8, 2u).ToAtomicString());
// AtomicString will convert to 8bit if possible when creating the string.
EXPECT_EQ(AtomicString("12").Impl(),
StringView(kChars16, 2).ToAtomicString().Impl());
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec.cc b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec.cc
index e1526e29798..39ee19f004e 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec.cc
@@ -30,7 +30,7 @@ namespace WTF {
TextCodec::~TextCodec() = default;
-int TextCodec::GetUnencodableReplacement(
+uint32_t TextCodec::GetUnencodableReplacement(
unsigned code_point,
UnencodableHandling handling,
UnencodableReplacementArray replacement) {
@@ -38,16 +38,16 @@ int TextCodec::GetUnencodableReplacement(
case kEntitiesForUnencodables:
snprintf(replacement, sizeof(UnencodableReplacementArray), "&#%u;",
code_point);
- return static_cast<int>(strlen(replacement));
+ return static_cast<uint32_t>(strlen(replacement));
case kURLEncodedEntitiesForUnencodables:
snprintf(replacement, sizeof(UnencodableReplacementArray),
"%%26%%23%u%%3B", code_point);
- return static_cast<int>(strlen(replacement));
+ return static_cast<uint32_t>(strlen(replacement));
case kCSSEncodedEntitiesForUnencodables:
snprintf(replacement, sizeof(UnencodableReplacementArray), "\\%x ",
code_point);
- return static_cast<int>(strlen(replacement));
+ return static_cast<uint32_t>(strlen(replacement));
}
NOTREACHED();
replacement[0] = 0;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec.h b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec.h
index 5bc0c2793b4..e13cad7df69 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec.h
@@ -56,7 +56,7 @@ enum UnencodableHandling {
typedef char UnencodableReplacementArray[32];
-enum FlushBehavior {
+enum class FlushBehavior {
// More bytes are coming, don't flush the codec.
kDoNotFlush = 0,
@@ -68,10 +68,6 @@ enum FlushBehavior {
kDataEOF
};
-static_assert(!kDoNotFlush, "DoNotFlush should be falsy");
-static_assert(kFetchEOF, "FetchEOF should be truthy");
-static_assert(kDataEOF, "DataEOF should be truthy");
-
class WTF_EXPORT TextCodec {
USING_FAST_MALLOC(TextCodec);
@@ -81,7 +77,7 @@ class WTF_EXPORT TextCodec {
String Decode(const char* str,
size_t length,
- FlushBehavior flush = kDoNotFlush) {
+ FlushBehavior flush = FlushBehavior::kDoNotFlush) {
bool ignored;
return Decode(str, length, flush, false, ignored);
}
@@ -97,9 +93,9 @@ class WTF_EXPORT TextCodec {
// Fills a null-terminated string representation of the given
// unencodable character into the given replacement buffer.
// The length of the string (not including the null) will be returned.
- static int GetUnencodableReplacement(unsigned code_point,
- UnencodableHandling,
- UnencodableReplacementArray);
+ static uint32_t GetUnencodableReplacement(unsigned code_point,
+ UnencodableHandling,
+ UnencodableReplacementArray);
DISALLOW_COPY_AND_ASSIGN(TextCodec);
};
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_icu.cc b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_icu.cc
index 69ff38631c8..5b933744c03 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_icu.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_icu.cc
@@ -408,7 +408,7 @@ String TextCodecICU::Decode(const char* bytes,
do {
int uchars_decoded =
DecodeToBuffer(buffer, buffer_limit, source, source_limit, offsets,
- flush != kDoNotFlush, err);
+ flush != FlushBehavior::kDoNotFlush, err);
result.Append(buffer, uchars_decoded);
} while (err == U_BUFFER_OVERFLOW_ERROR);
@@ -458,7 +458,7 @@ static UChar FallbackForGBK(UChar32 character) {
}
#endif
-// Generic helper for writing escaped entities using the specfied
+// Generic helper for writing escaped entities using the specified
// UnencodableHandling.
static void FormatEscapedEntityCallback(const void* context,
UConverterFromUnicodeArgs* from_u_args,
@@ -472,7 +472,7 @@ static void FormatEscapedEntityCallback(const void* context,
*err = U_ZERO_ERROR;
UnencodableReplacementArray entity;
- int entity_len =
+ uint32_t entity_len =
TextCodec::GetUnencodableReplacement(code_point, handling, entity);
String entity_u(entity, entity_len);
entity_u.Ensure16Bit();
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_replacement_test.cc b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_replacement_test.cc
index fe5e5df0f30..fac402a01d6 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_replacement_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_replacement_test.cc
@@ -36,7 +36,8 @@ TEST(TextCodecReplacement, DecodesToFFFD) {
size_t test_case_size = sizeof(kTestCase) - 1;
const String result =
- codec->Decode(kTestCase, test_case_size, kDataEOF, false, saw_error);
+ codec->Decode(kTestCase, test_case_size, FlushBehavior::kDataEOF,
+ false, saw_error);
EXPECT_TRUE(saw_error);
ASSERT_EQ(1u, result.length());
EXPECT_EQ(0xFFFDU, result[0]);
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf16.cc b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf16.cc
index 1a30e0d699d..b814960e625 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf16.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf16.cc
@@ -70,7 +70,8 @@ String TextCodecUTF16::Decode(const char* bytes,
bool,
bool& saw_error) {
// For compatibility reasons, ignore flush from fetch EOF.
- const bool really_flush = flush != kDoNotFlush && flush != kFetchEOF;
+ const bool really_flush = flush != FlushBehavior::kDoNotFlush &&
+ flush != FlushBehavior::kFetchEOF;
if (!length) {
if (really_flush && (have_lead_byte_ || have_lead_surrogate_)) {
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.cc b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.cc
index 3a5a0d71b5d..ab2a9dbde40 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8.cc
@@ -290,6 +290,7 @@ String TextCodecUTF8::Decode(const char* bytes,
FlushBehavior flush,
bool stop_on_error,
bool& saw_error) {
+ const bool do_flush = flush != FlushBehavior::kDoNotFlush;
// Each input byte might turn into a character.
// That includes all bytes in the partial-sequence buffer because
// each byte in an invalid sequence will turn into a replacement character.
@@ -308,8 +309,8 @@ String TextCodecUTF8::Decode(const char* bytes,
LChar* destination_for_handle_partial_sequence = destination;
const uint8_t* source_for_handle_partial_sequence = source;
if (HandlePartialSequence(destination_for_handle_partial_sequence,
- source_for_handle_partial_sequence, end, flush,
- stop_on_error, saw_error)) {
+ source_for_handle_partial_sequence, end,
+ do_flush, stop_on_error, saw_error)) {
source = source_for_handle_partial_sequence;
goto upConvertTo16Bit;
}
@@ -369,7 +370,7 @@ String TextCodecUTF8::Decode(const char* bytes,
source += count;
*destination++ = static_cast<LChar>(character);
}
- } while (flush && partial_sequence_size_);
+ } while (do_flush && partial_sequence_size_);
buffer.Shrink(destination - buffer.Characters());
@@ -392,7 +393,7 @@ upConvertTo16Bit:
UChar* destination_for_handle_partial_sequence = destination16;
const uint8_t* source_for_handle_partial_sequence = source;
HandlePartialSequence(destination_for_handle_partial_sequence,
- source_for_handle_partial_sequence, end, flush,
+ source_for_handle_partial_sequence, end, do_flush,
stop_on_error, saw_error);
destination16 = destination_for_handle_partial_sequence;
source = source_for_handle_partial_sequence;
@@ -454,7 +455,7 @@ upConvertTo16Bit:
source += count;
destination16 = AppendCharacter(destination16, character);
}
- } while (flush && partial_sequence_size_);
+ } while (do_flush && partial_sequence_size_);
buffer16.Shrink(destination16 - buffer16.Characters());
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8_test.cc b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8_test.cc
index bbc96c5ec56..da150c35088 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/text_codec_utf8_test.cc
@@ -50,7 +50,8 @@ TEST(TextCodecUTF8, DecodeAscii) {
bool saw_error = false;
const String& result =
- codec->Decode(kTestCase, test_case_size, kDataEOF, false, saw_error);
+ codec->Decode(kTestCase, test_case_size, FlushBehavior::kDataEOF,
+ false, saw_error);
EXPECT_FALSE(saw_error);
ASSERT_EQ(test_case_size, result.length());
for (size_t i = 0; i < test_case_size; ++i) {
@@ -68,7 +69,8 @@ TEST(TextCodecUTF8, DecodeChineseCharacters) {
bool saw_error = false;
const String& result =
- codec->Decode(kTestCase, test_case_size, kDataEOF, false, saw_error);
+ codec->Decode(kTestCase, test_case_size, FlushBehavior::kDataEOF,
+ false, saw_error);
EXPECT_FALSE(saw_error);
ASSERT_EQ(2u, result.length());
EXPECT_EQ(0x6f22U, result[0]);
@@ -80,7 +82,8 @@ TEST(TextCodecUTF8, Decode0xFF) {
std::unique_ptr<TextCodec> codec(NewTextCodec(encoding));
bool saw_error = false;
- const String& result = codec->Decode("\xff", 1, kDataEOF, false, saw_error);
+ const String& result =
+ codec->Decode("\xff", 1, FlushBehavior::kDataEOF, false, saw_error);
EXPECT_TRUE(saw_error);
ASSERT_EQ(1u, result.length());
EXPECT_EQ(0xFFFDU, result[0]);
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_encoding.cc b/chromium/third_party/blink/renderer/platform/wtf/text/text_encoding.cc
index 92d840d79cf..809eca13715 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/text_encoding.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/text_encoding.cc
@@ -51,8 +51,8 @@ String TextEncoding::Decode(const char* data,
if (!name_)
return String();
- return NewTextCodec(*this)->Decode(data, length, kDataEOF, stop_on_error,
- saw_error);
+ return NewTextCodec(*this)->Decode(data, length, FlushBehavior::kDataEOF,
+ stop_on_error, saw_error);
}
CString TextEncoding::Encode(const String& string,
@@ -144,4 +144,10 @@ const TextEncoding& WindowsLatin1Encoding() {
return global_windows_latin1_encoding;
}
+const TextEncoding& UnknownEncoding() {
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(const TextEncoding, global_unknown_encoding,
+ ("Unknown"));
+ return global_unknown_encoding;
+}
+
} // namespace WTF
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_encoding.h b/chromium/third_party/blink/renderer/platform/wtf/text/text_encoding.h
index 07dc5941ce0..f89855c3b65 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/text_encoding.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/text_encoding.h
@@ -74,15 +74,16 @@ inline bool operator!=(const TextEncoding& a, const TextEncoding& b) {
WTF_EXPORT const TextEncoding& ASCIIEncoding();
WTF_EXPORT const TextEncoding& Latin1Encoding();
+WTF_EXPORT const TextEncoding& UnknownEncoding();
WTF_EXPORT const TextEncoding& UTF16BigEndianEncoding();
WTF_EXPORT const TextEncoding& UTF16LittleEndianEncoding();
WTF_EXPORT const TextEncoding& UTF8Encoding();
WTF_EXPORT const TextEncoding& WindowsLatin1Encoding();
-
} // namespace WTF
using WTF::ASCIIEncoding;
using WTF::Latin1Encoding;
+using WTF::UnknownEncoding;
using WTF::UTF16BigEndianEncoding;
using WTF::UTF16LittleEndianEncoding;
using WTF::UTF8Encoding;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/text_encoding_registry.cc b/chromium/third_party/blink/renderer/platform/wtf/text/text_encoding_registry.cc
index 9b69e7fa23b..b4649af0731 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/text_encoding_registry.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/text_encoding_registry.cc
@@ -43,6 +43,7 @@
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
#include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
namespace WTF {
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/unicode.h b/chromium/third_party/blink/renderer/platform/wtf/text/unicode.h
index 04a28a529a4..9202dc11d58 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/unicode.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/unicode.h
@@ -23,13 +23,207 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_UNICODE_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_UNICODE_H_
+#include <unicode/uchar.h>
+#include <unicode/ustring.h>
#include "third_party/blink/renderer/platform/wtf/assertions.h"
// Define platform neutral 8 bit character type (L is for Latin-1).
typedef unsigned char LChar;
+static_assert(sizeof(UChar) == 2, "UChar should be two bytes");
-#include "third_party/blink/renderer/platform/wtf/text/icu/unicode_icu.h"
+namespace WTF {
+namespace Unicode {
-static_assert(sizeof(UChar) == 2, "UChar should be two bytes");
+enum CharDirection {
+ kLeftToRight = U_LEFT_TO_RIGHT,
+ kRightToLeft = U_RIGHT_TO_LEFT,
+ kEuropeanNumber = U_EUROPEAN_NUMBER,
+ kEuropeanNumberSeparator = U_EUROPEAN_NUMBER_SEPARATOR,
+ kEuropeanNumberTerminator = U_EUROPEAN_NUMBER_TERMINATOR,
+ kArabicNumber = U_ARABIC_NUMBER,
+ kCommonNumberSeparator = U_COMMON_NUMBER_SEPARATOR,
+ kBlockSeparator = U_BLOCK_SEPARATOR,
+ kSegmentSeparator = U_SEGMENT_SEPARATOR,
+ kWhiteSpaceNeutral = U_WHITE_SPACE_NEUTRAL,
+ kOtherNeutral = U_OTHER_NEUTRAL,
+ kLeftToRightEmbedding = U_LEFT_TO_RIGHT_EMBEDDING,
+ kLeftToRightOverride = U_LEFT_TO_RIGHT_OVERRIDE,
+ kRightToLeftArabic = U_RIGHT_TO_LEFT_ARABIC,
+ kRightToLeftEmbedding = U_RIGHT_TO_LEFT_EMBEDDING,
+ kRightToLeftOverride = U_RIGHT_TO_LEFT_OVERRIDE,
+ kPopDirectionalFormat = U_POP_DIRECTIONAL_FORMAT,
+ kNonSpacingMark = U_DIR_NON_SPACING_MARK,
+ kBoundaryNeutral = U_BOUNDARY_NEUTRAL
+};
+
+enum CharDecompositionType {
+ kDecompositionNone = U_DT_NONE,
+ kDecompositionCanonical = U_DT_CANONICAL,
+ kDecompositionCompat = U_DT_COMPAT,
+ kDecompositionCircle = U_DT_CIRCLE,
+ kDecompositionFinal = U_DT_FINAL,
+ kDecompositionFont = U_DT_FONT,
+ kDecompositionFraction = U_DT_FRACTION,
+ kDecompositionInitial = U_DT_INITIAL,
+ kDecompositionIsolated = U_DT_ISOLATED,
+ kDecompositionMedial = U_DT_MEDIAL,
+ kDecompositionNarrow = U_DT_NARROW,
+ kDecompositionNoBreak = U_DT_NOBREAK,
+ kDecompositionSmall = U_DT_SMALL,
+ kDecompositionSquare = U_DT_SQUARE,
+ kDecompositionSub = U_DT_SUB,
+ kDecompositionSuper = U_DT_SUPER,
+ kDecompositionVertical = U_DT_VERTICAL,
+ kDecompositionWide = U_DT_WIDE,
+};
+
+enum CharCategory {
+ kNoCategory = 0,
+ kOther_NotAssigned = U_MASK(U_GENERAL_OTHER_TYPES),
+ kLetter_Uppercase = U_MASK(U_UPPERCASE_LETTER),
+ kLetter_Lowercase = U_MASK(U_LOWERCASE_LETTER),
+ kLetter_Titlecase = U_MASK(U_TITLECASE_LETTER),
+ kLetter_Modifier = U_MASK(U_MODIFIER_LETTER),
+ kLetter_Other = U_MASK(U_OTHER_LETTER),
+
+ kMark_NonSpacing = U_MASK(U_NON_SPACING_MARK),
+ kMark_Enclosing = U_MASK(U_ENCLOSING_MARK),
+ kMark_SpacingCombining = U_MASK(U_COMBINING_SPACING_MARK),
+
+ kNumber_DecimalDigit = U_MASK(U_DECIMAL_DIGIT_NUMBER),
+ kNumber_Letter = U_MASK(U_LETTER_NUMBER),
+ kNumber_Other = U_MASK(U_OTHER_NUMBER),
+
+ kSeparator_Space = U_MASK(U_SPACE_SEPARATOR),
+ kSeparator_Line = U_MASK(U_LINE_SEPARATOR),
+ kSeparator_Paragraph = U_MASK(U_PARAGRAPH_SEPARATOR),
+
+ kOther_Control = U_MASK(U_CONTROL_CHAR),
+ kOther_Format = U_MASK(U_FORMAT_CHAR),
+ kOther_PrivateUse = U_MASK(U_PRIVATE_USE_CHAR),
+ kOther_Surrogate = U_MASK(U_SURROGATE),
+
+ kPunctuation_Dash = U_MASK(U_DASH_PUNCTUATION),
+ kPunctuation_Open = U_MASK(U_START_PUNCTUATION),
+ kPunctuation_Close = U_MASK(U_END_PUNCTUATION),
+ kPunctuation_Connector = U_MASK(U_CONNECTOR_PUNCTUATION),
+ kPunctuation_Other = U_MASK(U_OTHER_PUNCTUATION),
+
+ kSymbol_Math = U_MASK(U_MATH_SYMBOL),
+ kSymbol_Currency = U_MASK(U_CURRENCY_SYMBOL),
+ kSymbol_Modifier = U_MASK(U_MODIFIER_SYMBOL),
+ kSymbol_Other = U_MASK(U_OTHER_SYMBOL),
+
+ kPunctuation_InitialQuote = U_MASK(U_INITIAL_PUNCTUATION),
+ kPunctuation_FinalQuote = U_MASK(U_FINAL_PUNCTUATION)
+};
+
+inline UChar32 FoldCase(UChar32 c) {
+ return u_foldCase(c, U_FOLD_CASE_DEFAULT);
+}
+
+inline int FoldCase(UChar* result,
+ int result_length,
+ const UChar* src,
+ int src_length,
+ bool* error) {
+ UErrorCode status = U_ZERO_ERROR;
+ int real_length = u_strFoldCase(result, result_length, src, src_length,
+ U_FOLD_CASE_DEFAULT, &status);
+ *error = !U_SUCCESS(status);
+ return real_length;
+}
+
+inline int ToLower(UChar* result,
+ int result_length,
+ const UChar* src,
+ int src_length,
+ bool* error) {
+ UErrorCode status = U_ZERO_ERROR;
+ int real_length =
+ u_strToLower(result, result_length, src, src_length, "", &status);
+ *error = !!U_FAILURE(status);
+ return real_length;
+}
+
+inline UChar32 ToLower(UChar32 c) {
+ return u_tolower(c);
+}
+
+inline UChar32 ToUpper(UChar32 c) {
+ return u_toupper(c);
+}
+
+inline int ToUpper(UChar* result,
+ int result_length,
+ const UChar* src,
+ int src_length,
+ bool* error) {
+ UErrorCode status = U_ZERO_ERROR;
+ int real_length =
+ u_strToUpper(result, result_length, src, src_length, "", &status);
+ *error = !!U_FAILURE(status);
+ return real_length;
+}
+
+inline UChar32 ToTitleCase(UChar32 c) {
+ return u_totitle(c);
+}
+
+inline bool IsArabicChar(UChar32 c) {
+ return ublock_getCode(c) == UBLOCK_ARABIC;
+}
+
+inline bool IsAlphanumeric(UChar32 c) {
+ return !!u_isalnum(c);
+}
+
+inline bool IsSeparatorSpace(UChar32 c) {
+ return u_charType(c) == U_SPACE_SEPARATOR;
+}
+
+inline bool IsPrintableChar(UChar32 c) {
+ return !!u_isprint(c);
+}
+
+inline bool IsPunct(UChar32 c) {
+ return !!u_ispunct(c);
+}
+
+inline bool HasLineBreakingPropertyComplexContext(UChar32 c) {
+ return u_getIntPropertyValue(c, UCHAR_LINE_BREAK) == U_LB_COMPLEX_CONTEXT;
+}
+
+inline UChar32 MirroredChar(UChar32 c) {
+ return u_charMirror(c);
+}
+
+inline CharCategory Category(UChar32 c) {
+ return static_cast<CharCategory>(U_GET_GC_MASK(c));
+}
+
+inline CharDirection Direction(UChar32 c) {
+ return static_cast<CharDirection>(u_charDirection(c));
+}
+
+inline bool IsLower(UChar32 c) {
+ return !!u_islower(c);
+}
+
+inline uint8_t CombiningClass(UChar32 c) {
+ return u_getCombiningClass(c);
+}
+
+inline CharDecompositionType DecompositionType(UChar32 c) {
+ return static_cast<CharDecompositionType>(
+ u_getIntPropertyValue(c, UCHAR_DECOMPOSITION_TYPE));
+}
+
+inline int Umemcasecmp(const UChar* a, const UChar* b, int len) {
+ return u_memcasecmp(a, b, len, U_FOLD_CASE_DEFAULT);
+}
+
+} // namespace Unicode
+} // namespace WTF
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_UNICODE_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.cc b/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.cc
index fe4c2dba491..4f7effa67af 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.cc
@@ -58,6 +58,11 @@ String::String(const char* characters, unsigned length)
length)
: nullptr) {}
+#if defined(ARCH_CPU_64_BITS)
+String::String(const char* characters, size_t length)
+ : String(characters, SafeCast<unsigned>(length)) {}
+#endif // defined(ARCH_CPU_64_BITS)
+
void String::append(const StringView& string) {
if (string.IsEmpty())
return;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.h b/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.h
index 361322374f6..a177893f98b 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string.h
@@ -27,6 +27,7 @@
// on systems without case-sensitive file systems.
#include <iosfwd>
+#include "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/compiler.h"
#include "third_party/blink/renderer/platform/wtf/hash_table_deleted_value_type.h"
@@ -88,6 +89,12 @@ class WTF_EXPORT String {
String(const LChar* characters, unsigned length);
String(const char* characters, unsigned length);
+#if defined(ARCH_CPU_64_BITS)
+ // Only define a size_t constructor if size_t is 64 bit otherwise
+ // we'd have a duplicate define.
+ String(const char* characters, size_t length);
+#endif // defined(ARCH_CPU_64_BITS)
+
// Construct a string with latin1 data, from a null-terminated source.
String(const LChar* characters)
: String(reinterpret_cast<const char*>(characters)) {}
@@ -342,7 +349,7 @@ class WTF_EXPORT String {
PRINTF_FORMAT(1, 2) static String Format(const char* format, ...);
// Returns a version suitable for gtest and base/logging.*. It prepends and
- // appends double-quotes, and escapes chracters other than ASCII printables.
+ // appends double-quotes, and escapes characters other than ASCII printables.
String EncodeForDebugging() const;
// Returns an uninitialized string. The characters needs to be written
@@ -644,7 +651,7 @@ WTF_EXPORT extern const String& g_empty_string16_bit;
WTF_EXPORT extern const String& g_xmlns_with_colon;
// Pretty printer for gtest and base/logging.*. It prepends and appends
-// double-quotes, and escapes chracters other than ASCII printables.
+// double-quotes, and escapes characters other than ASCII printables.
WTF_EXPORT std::ostream& operator<<(std::ostream&, const String&);
inline StringView::StringView(const String& string,
diff --git a/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string_test.cc b/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string_test.cc
index 9a54ed0efb9..01adf9e46d7 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string_test.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/text/wtf_string_test.cc
@@ -87,12 +87,12 @@ TEST(StringTest, NumberToStringECMAScriptBoundaries) {
TEST(StringTest, NumberToStringECMAScriptRegularNumbers) {
// Pi.
- TestNumberToStringECMAScript(piDouble, "3.141592653589793");
- TestNumberToStringECMAScript(piFloat, "3.1415927410125732");
- TestNumberToStringECMAScript(piOverTwoDouble, "1.5707963267948966");
- TestNumberToStringECMAScript(piOverTwoFloat, "1.5707963705062866");
- TestNumberToStringECMAScript(piOverFourDouble, "0.7853981633974483");
- TestNumberToStringECMAScript(piOverFourFloat, "0.7853981852531433");
+ TestNumberToStringECMAScript(kPiDouble, "3.141592653589793");
+ TestNumberToStringECMAScript(kPiFloat, "3.1415927410125732");
+ TestNumberToStringECMAScript(kPiOverTwoDouble, "1.5707963267948966");
+ TestNumberToStringECMAScript(kPiOverTwoFloat, "1.5707963705062866");
+ TestNumberToStringECMAScript(kPiOverFourDouble, "0.7853981633974483");
+ TestNumberToStringECMAScript(kPiOverFourFloat, "0.7853981852531433");
// e.
const double kE = 2.71828182845904523536028747135266249775724709369995;
@@ -475,16 +475,16 @@ TEST(StringTest, StringPrinter) {
EXPECT_EQ(CString("\"\\\\\""), ToCStringThroughPrinter("\\"));
EXPECT_EQ(
CString("\"\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\""),
- ToCStringThroughPrinter(String("\x00\x01\x02\x03\x04\x05\x06\x07", 8)));
+ ToCStringThroughPrinter(String("\x00\x01\x02\x03\x04\x05\x06\x07", 8u)));
EXPECT_EQ(
CString("\"\\u0008\\t\\n\\u000B\\u000C\\r\\u000E\\u000F\""),
- ToCStringThroughPrinter(String("\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 8)));
+ ToCStringThroughPrinter(String("\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 8u)));
EXPECT_EQ(
CString("\"\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\""),
- ToCStringThroughPrinter(String("\x10\x11\x12\x13\x14\x15\x16\x17", 8)));
+ ToCStringThroughPrinter(String("\x10\x11\x12\x13\x14\x15\x16\x17", 8u)));
EXPECT_EQ(
CString("\"\\u0018\\u0019\\u001A\\u001B\\u001C\\u001D\\u001E\\u001F\""),
- ToCStringThroughPrinter(String("\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", 8)));
+ ToCStringThroughPrinter(String("\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", 8u)));
EXPECT_EQ(CString("\"\\u007F\\u0080\\u0081\""),
ToCStringThroughPrinter("\x7F\x80\x81"));
EXPECT_EQ(CString("\"\""), ToCStringThroughPrinter(g_empty_string));
diff --git a/chromium/third_party/blink/renderer/platform/wtf/threading.h b/chromium/third_party/blink/renderer/platform/wtf/threading.h
index 91af79bcd49..61ca3d304df 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/threading.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/threading.h
@@ -32,8 +32,8 @@
#include <stdint.h>
+#include "base/logging.h"
#include "build/build_config.h"
-#include "third_party/blink/renderer/platform/wtf/atomics.h"
#include "third_party/blink/renderer/platform/wtf/type_traits.h"
#include "third_party/blink/renderer/platform/wtf/wtf_export.h"
diff --git a/chromium/third_party/blink/renderer/platform/wtf/threading_primitives.h b/chromium/third_party/blink/renderer/platform/wtf/threading_primitives.h
index 12c24ab9529..f112896f6ac 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/threading_primitives.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/threading_primitives.h
@@ -161,14 +161,6 @@ class WTF_EXPORT ThreadCondition final {
DISALLOW_COPY_AND_ASSIGN(ThreadCondition);
};
-#if defined(OS_WIN)
-// The absoluteTime is in seconds, starting on January 1, 1970. The time is
-// assumed to use the same time zone as WTF::currentTime().
-// Returns an interval in milliseconds suitable for passing to one of the Win32
-// wait functions (e.g., ::WaitForSingleObject).
-DWORD AbsoluteTimeToWaitTimeoutInterval(double absolute_time);
-#endif
-
} // namespace WTF
using WTF::MutexBase;
@@ -179,8 +171,4 @@ using WTF::MutexTryLocker;
using WTF::RecursiveMutexLocker;
using WTF::ThreadCondition;
-#if defined(OS_WIN)
-using WTF::AbsoluteTimeToWaitTimeoutInterval;
-#endif
-
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_THREADING_PRIMITIVES_H_
diff --git a/chromium/third_party/blink/renderer/platform/wtf/threading_win.cc b/chromium/third_party/blink/renderer/platform/wtf/threading_win.cc
index 76bef7f83ef..09cc847bd63 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/threading_win.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/threading_win.cc
@@ -255,14 +255,22 @@ void ThreadCondition::Wait(Mutex& mutex) {
}
bool ThreadCondition::TimedWait(Mutex& mutex, double absolute_time) {
- DWORD interval = AbsoluteTimeToWaitTimeoutInterval(absolute_time);
+ double current_time = WTF::CurrentTime();
- if (!interval) {
+ // Time is in the past - return immediately.
+ if (absolute_time <= current_time) {
// Consider the wait to have timed out, even if our condition has already
// been signaled, to match the pthreads implementation.
return false;
}
+ // If time is too far in the future (and would overflow unsigned long), wait
+ // forever.
+ DWORD interval =
+ (absolute_time - current_time > static_cast<double>(INT_MAX) / 1000.0)
+ ? INFINITE
+ : ((absolute_time - current_time) * 1000.0);
+
PlatformMutex& platform_mutex = mutex.Impl();
BOOL result = SleepConditionVariableCS(
&condition_, &platform_mutex.internal_mutex_, interval);
@@ -279,21 +287,6 @@ void ThreadCondition::Broadcast() {
WakeAllConditionVariable(&condition_);
}
-DWORD AbsoluteTimeToWaitTimeoutInterval(double absolute_time) {
- double current_time = WTF::CurrentTime();
-
- // Time is in the past - return immediately.
- if (absolute_time < current_time)
- return 0;
-
- // Time is too far in the future (and would overflow unsigned long) - wait
- // forever.
- if (absolute_time - current_time > static_cast<double>(INT_MAX) / 1000.0)
- return INFINITE;
-
- return static_cast<DWORD>((absolute_time - current_time) * 1000.0);
-}
-
#if DCHECK_IS_ON()
static bool g_thread_created = false;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer.h b/chromium/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer.h
index 7f3bb0b902a..55d59c9f656 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer.h
@@ -72,7 +72,7 @@ class WTF_EXPORT ArrayBuffer : public RefCounted<ArrayBuffer> {
inline unsigned ByteLength() const;
// Creates a new ArrayBuffer object with copy of bytes in this object
- // ranging from |begin| upto but not including |end|.
+ // ranging from |begin| up to but not including |end|.
inline scoped_refptr<ArrayBuffer> Slice(int begin, int end) const;
inline scoped_refptr<ArrayBuffer> Slice(int begin) const;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/vector.h b/chromium/third_party/blink/renderer/platform/wtf/vector.h
index 6a341478a70..51bf9f034f0 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/vector.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/vector.h
@@ -32,7 +32,6 @@
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/alignment.h"
#include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
-#include "third_party/blink/renderer/platform/wtf/conditional_destructor.h"
#include "third_party/blink/renderer/platform/wtf/construct_traits.h"
#include "third_party/blink/renderer/platform/wtf/container_annotations.h"
#include "third_party/blink/renderer/platform/wtf/forward.h" // For default Vector template parameters.
@@ -598,7 +597,7 @@ class VectorBuffer : protected VectorBufferBase<T, true, Allocator> {
buffer_ = nullptr;
}
- NEVER_INLINE void ReallyDeallocateBuffer(T* buffer_to_deallocate) {
+ NOINLINE void ReallyDeallocateBuffer(T* buffer_to_deallocate) {
Allocator::FreeInlineVectorBacking(buffer_to_deallocate);
}
@@ -979,12 +978,7 @@ class VectorBuffer : protected VectorBufferBase<T, true, Allocator> {
// store iterators in another heap object.
template <typename T, size_t inlineCapacity, typename Allocator>
-class Vector
- : private VectorBuffer<T, INLINE_CAPACITY, Allocator>,
- // Heap-allocated vectors with no inlineCapacity never need a destructor.
- public ConditionalDestructor<Vector<T, INLINE_CAPACITY, Allocator>,
- (INLINE_CAPACITY == 0) &&
- Allocator::kIsGarbageCollected> {
+class Vector : private VectorBuffer<T, INLINE_CAPACITY, Allocator> {
USE_ALLOCATOR(Vector, Allocator);
using Base = VectorBuffer<T, INLINE_CAPACITY, Allocator>;
using TypeOperations = VectorTypeOperations<T, Allocator>;
@@ -1259,11 +1253,9 @@ class Vector
return Allocator::template MaxElementCountInBackingStore<T>();
}
- // Off-GC-heap vectors: Destructor should be called.
- // On-GC-heap vectors: Destructor should be called for inline buffers (if
- // any) but destructor shouldn't be called for vector backing since it is
- // managed by the traced GC heap.
- void Finalize() {
+ // For design of the destructor, please refer to
+ // [here](https://docs.google.com/document/d/1AoGTvb3tNLx2tD1hNqAfLRLmyM59GM0O-7rCHTT_7_U/)
+ ~Vector() {
if (!INLINE_CAPACITY) {
if (LIKELY(!Base::Buffer()))
return;
@@ -1275,10 +1267,16 @@ class Vector
size_ = 0; // Partial protection against use-after-free.
}
+ // If this is called during sweeping, it must not touch the OutOfLineBuffer.
+ if (Allocator::IsSweepForbidden())
+ return;
Base::Destruct();
}
- void FinalizeGarbageCollectedObject() { Finalize(); }
+ // This method will be referenced when creating an on-heap HeapVector with
+ // inline capacity and elements requiring destruction. However usage of such a
+ // type is banned with a static assert.
+ void FinalizeGarbageCollectedObject() { NOTREACHED(); }
template <typename VisitorDispatcher, typename A = Allocator>
std::enable_if_t<A::kIsGarbageCollected> Trace(VisitorDispatcher);
@@ -1766,8 +1764,7 @@ void Vector<T, inlineCapacity, Allocator>::Append(const U* data,
template <typename T, size_t inlineCapacity, typename Allocator>
template <typename U>
-NEVER_INLINE void Vector<T, inlineCapacity, Allocator>::AppendSlowCase(
- U&& val) {
+NOINLINE void Vector<T, inlineCapacity, Allocator>::AppendSlowCase(U&& val) {
DCHECK_EQ(size(), capacity());
typename std::remove_reference<U>::type* ptr = &val;
diff --git a/chromium/third_party/blink/renderer/platform/wtf/wtf_thread_data.cc b/chromium/third_party/blink/renderer/platform/wtf/wtf_thread_data.cc
index 91bdf2e9caf..1bd1b10327e 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/wtf_thread_data.cc
+++ b/chromium/third_party/blink/renderer/platform/wtf/wtf_thread_data.cc
@@ -28,6 +28,7 @@
#include "third_party/blink/renderer/platform/wtf/stack_util.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string_table.h"
+#include "third_party/blink/renderer/platform/wtf/text/movable_string.h"
#include "third_party/blink/renderer/platform/wtf/text/text_codec_icu.h"
namespace WTF {
@@ -36,6 +37,7 @@ ThreadSpecific<WTFThreadData>* WTFThreadData::static_data_;
WTFThreadData::WTFThreadData()
: atomic_string_table_(new AtomicStringTable),
+ movable_string_table_(new MovableStringTable),
cached_converter_icu_(new ICUConverterWrapper),
thread_id_(internal::CurrentThreadSyscall()) {}
diff --git a/chromium/third_party/blink/renderer/platform/wtf/wtf_thread_data.h b/chromium/third_party/blink/renderer/platform/wtf/wtf_thread_data.h
index c45674e3df8..84707d248c4 100644
--- a/chromium/third_party/blink/renderer/platform/wtf/wtf_thread_data.h
+++ b/chromium/third_party/blink/renderer/platform/wtf/wtf_thread_data.h
@@ -41,6 +41,7 @@
namespace WTF {
class AtomicStringTable;
+class MovableStringTable;
struct ICUConverterWrapper;
class WTF_EXPORT WTFThreadData {
@@ -52,6 +53,8 @@ class WTF_EXPORT WTFThreadData {
AtomicStringTable& GetAtomicStringTable() { return *atomic_string_table_; }
+ MovableStringTable& GetMovableStringTable() { return *movable_string_table_; }
+
ICUConverterWrapper& CachedConverterICU() { return *cached_converter_icu_; }
ThreadIdentifier ThreadId() const { return thread_id_; }
@@ -65,6 +68,7 @@ class WTF_EXPORT WTFThreadData {
private:
std::unique_ptr<AtomicStringTable> atomic_string_table_;
+ std::unique_ptr<MovableStringTable> movable_string_table_;
std::unique_ptr<ICUConverterWrapper> cached_converter_icu_;
ThreadIdentifier thread_id_;